From bfcf613779ddc7afbc021fd26976e72d97ec3611 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Sat, 15 Feb 2020 14:44:45 +0000 Subject: [PATCH] Import systemd_244.3.orig.tar.gz [dgit import orig systemd_244.3.orig.tar.gz] --- .ctags | 1 + .dir-locals.el | 28 + .editorconfig | 28 + .gitattributes | 1 + .github/FUNDING.yml | 1 + .github/ISSUE_TEMPLATE/Bug_report.md | 22 + .github/ISSUE_TEMPLATE/Feature_request.md | 14 + .gitignore | 37 + .lgtm.yml | 13 + .../PotentiallyDangerousFunction.ql | 54 + .mailmap | 206 + .mkosi/mkosi.arch | 58 + .mkosi/mkosi.debian | 66 + .mkosi/mkosi.fedora | 67 + .mkosi/mkosi.ubuntu | 68 + .travis.yml | 158 + .vimrc | 21 + .ycm_extra_conf.py | 250 + LICENSE.GPL2 | 339 + LICENSE.LGPL2.1 | 502 + Makefile | 5 + NEWS | 10215 + README | 334 + README.md | 33 + TODO | 1157 + azure-pipelines.yml | 15 + catalog/meson.build | 34 + catalog/systemd.be.catalog.in | 297 + catalog/systemd.be@latin.catalog.in | 302 + catalog/systemd.bg.catalog.in | 310 + catalog/systemd.catalog.in | 414 + catalog/systemd.da.catalog.in | 246 + catalog/systemd.de.catalog.in | 13 + catalog/systemd.fr.catalog.in | 350 + catalog/systemd.hr.catalog.in | 299 + catalog/systemd.hu.catalog.in | 248 + catalog/systemd.it.catalog.in | 427 + catalog/systemd.ko.catalog.in | 306 + catalog/systemd.pl.catalog.in | 413 + catalog/systemd.pt_BR.catalog.in | 250 + catalog/systemd.ru.catalog.in | 403 + catalog/systemd.sr.catalog.in | 247 + catalog/systemd.zh_CN.catalog.in | 239 + catalog/systemd.zh_TW.catalog.in | 249 + coccinelle/bool-cast.cocci | 12 + coccinelle/close-above-stdio.cocci | 36 + coccinelle/cmp.cocci | 28 + coccinelle/const-strlen.disabled | 14 + coccinelle/debug-logging.cocci | 16 + coccinelle/div-round-up.cocci | 20 + coccinelle/dup-fcntl.cocci | 7 + coccinelle/empty-or-dash.cocci | 5 + coccinelle/empty-or-root.cocci | 10 + coccinelle/empty-to-null.cocci | 8 + coccinelle/empty-to-root.cocci | 11 + coccinelle/enotsup.cocci | 4 + coccinelle/equals-null.cocci | 14 + coccinelle/errno.cocci | 32 + coccinelle/exit-0.cocci | 16 + coccinelle/flags-set.cocci | 16 + coccinelle/fopen-unlocked.cocci | 71 + coccinelle/free_and_replace.cocci | 15 + coccinelle/hashmap_free.cocci | 54 + coccinelle/htonl.cocci | 20 + coccinelle/in_set.cocci | 37 + coccinelle/iovec-make.cocci | 29 + coccinelle/isempty.cocci | 42 + coccinelle/log-json.cocci | 8 + coccinelle/malloc_multiply.cocci | 20 + coccinelle/memzero.cocci | 38 + coccinelle/mfree.cocci | 6 + coccinelle/mfree_return.cocci | 8 + coccinelle/no-if-assignments.cocci | 20 + coccinelle/not_in_set.cocci | 34 + coccinelle/o-ndelay.cocci | 4 + coccinelle/reallocarray.cocci | 20 + coccinelle/redundant-if.cocci | 54 + coccinelle/run-coccinelle.sh | 43 + coccinelle/safe_close-no-if.cocci | 7 + coccinelle/safe_close.cocci | 18 + coccinelle/safe_closedir.cocci | 27 + coccinelle/safe_fclose.cocci | 27 + .../sd_event_source_disable_unref.cocci | 36 + coccinelle/strempty.cocci | 60 + coccinelle/strjoin.cocci | 16 + coccinelle/strjoina.cocci | 6 + coccinelle/strv_free.cocci | 27 + coccinelle/swap-two.cocci | 7 + coccinelle/synthetic-errno.cocci | 48 + coccinelle/systemd-definitions.iso | 20 + coccinelle/take-fd.cocci | 21 + coccinelle/take-ptr.cocci | 14 + coccinelle/while-true.cocci | 12 + coccinelle/xsprintf.cocci | 6 + configure | 21 + docs/AUTOMATIC_BOOT_ASSESSMENT.md | 207 + docs/BLOCK_DEVICE_LOCKING.md | 67 + docs/BOOT_LOADER_INTERFACE.md | 142 + docs/BOOT_LOADER_SPECIFICATION.md | 222 + docs/CGROUP_DELEGATION.md | 477 + docs/CNAME | 1 + docs/CODE_OF_CONDUCT.md | 18 + docs/CODE_QUALITY.md | 73 + docs/CODING_STYLE.md | 550 + docs/CONTRIBUTING.md | 41 + docs/DISTRO_PORTING.md | 92 + docs/ENVIRONMENT.md | 243 + docs/HACKING.md | 131 + docs/PORTABLE_SERVICES.md | 285 + docs/PREDICTABLE_INTERFACE_NAMES.md | 68 + docs/RANDOM_SEEDS.md | 418 + docs/RELEASE.md | 19 + docs/SECURITY.md | 7 + docs/TEMPORARY_DIRECTORIES.md | 220 + docs/TESTING_WITH_SANITIZERS.md | 88 + docs/TRANSIENT-SETTINGS.md | 479 + docs/TRANSLATORS.md | 78 + docs/UIDS-GIDS.md | 290 + docs/_config.yml | 1 + docs/index.md | 11 + docs/sysvinit/README.in | 27 + docs/sysvinit/meson.build | 11 + docs/var-log/README | 25 + docs/var-log/meson.build | 6 + factory/etc/issue | 3 + factory/etc/nsswitch.conf | 15 + factory/etc/pam.d/other | 6 + factory/etc/pam.d/system-auth | 19 + fuzzbuzz.yaml | 32 + hwdb.d/.gitattributes | 2 + hwdb.d/.gitignore | 1 + hwdb.d/20-OUI.hwdb | 101934 +++++++++ hwdb.d/20-acpi-vendor.hwdb | 7705 + hwdb.d/20-acpi-vendor.hwdb.patch | 502 + hwdb.d/20-bluetooth-vendor-product.hwdb | 3121 + hwdb.d/20-net-ifname.hwdb | 5 + hwdb.d/20-pci-classes.hwdb | 600 + hwdb.d/20-pci-vendor-model.hwdb | 95073 +++++++++ hwdb.d/20-sdio-classes.hwdb | 33 + hwdb.d/20-sdio-vendor-model.hwdb | 210 + hwdb.d/20-usb-classes.hwdb | 342 + hwdb.d/20-usb-vendor-model.hwdb | 60309 ++++++ hwdb.d/20-vmbus-class.hwdb | 57 + hwdb.d/60-evdev.hwdb | 615 + hwdb.d/60-input-id.hwdb | 72 + hwdb.d/60-keyboard.hwdb | 1740 + hwdb.d/60-sensor.hwdb | 628 + hwdb.d/70-joystick.hwdb | 50 + hwdb.d/70-mouse.hwdb | 756 + hwdb.d/70-pointingstick.hwdb | 161 + hwdb.d/70-touchpad.hwdb | 69 + hwdb.d/acpi-update.py | 79 + hwdb.d/acpi_id_registry.html | 102 + hwdb.d/ids_parser.py | 369 + hwdb.d/ma-large.txt | 164760 +++++++++++++++ hwdb.d/ma-medium.txt | 17784 ++ hwdb.d/ma-small.txt | 21870 ++ hwdb.d/meson.build | 53 + hwdb.d/parse_hwdb.py | 247 + hwdb.d/pci.ids | 32441 +++ hwdb.d/pnp_id_registry.html | 2464 + hwdb.d/sdio.ids | 95 + hwdb.d/usb.ids | 21826 ++ man/.dir-locals.el | 14 + man/50-xdg-data-dirs.sh | 12 + man/90-rearrange-path.py | 40 + man/binfmt.d.xml | 74 + man/bootctl.xml | 222 + man/bootup.xml | 356 + man/busctl.xml | 517 + man/coredump.conf.xml | 138 + man/coredumpctl.xml | 340 + man/crypttab.xml | 470 + man/custom-entities.ent.in | 11 + man/custom-html.xsl | 297 + man/custom-man.xsl | 49 + man/daemon.xml | 741 + man/dnssec-trust-anchors.d.xml | 171 + man/environment.d.xml | 101 + man/file-hierarchy.xml | 792 + man/glib-event-glue.c | 48 + man/halt.xml | 158 + man/hostname.xml | 71 + man/hostnamectl.xml | 224 + man/html.in | 12 + man/hwdb.xml | 132 + man/id128-app-specific.c | 11 + man/inotify-watch-tmp.c | 56 + man/journal-iterate-poll.c | 25 + man/journal-iterate-unique.c | 25 + man/journal-iterate-wait.c | 39 + man/journal-remote.conf.xml | 100 + man/journal-upload.conf.xml | 90 + man/journalctl.xml | 1029 + man/journald.conf.xml | 429 + man/kernel-command-line.xml | 460 + man/kernel-install.xml | 240 + man/less-variables.xml | 97 + man/libsystemd-pkgconfig.xml | 13 + man/libudev.xml | 96 + man/loader.conf.xml | 203 + man/locale.conf.xml | 127 + man/localectl.xml | 209 + man/localtime.xml | 69 + man/loginctl.xml | 429 + man/logind.conf.xml | 346 + man/machine-id.xml | 169 + man/machine-info.xml | 159 + man/machinectl.xml | 1007 + man/man.in | 16 + man/meson.build | 217 + man/modules-load.d.xml | 76 + man/networkctl.xml | 337 + man/networkd.conf.xml | 169 + man/nss-myhostname.xml | 122 + man/nss-mymachines.xml | 160 + man/nss-resolve.xml | 92 + man/nss-systemd.xml | 85 + man/os-release.xml | 371 + man/pam_systemd.xml | 316 + man/portablectl.xml | 400 + man/print-unit-path.c | 64 + man/pstore.conf.xml | 89 + man/resolvectl.xml | 447 + man/resolved.conf.xml | 274 + man/rules/meson.build | 948 + man/runlevel.xml | 163 + man/sd-bus-errors.xml | 275 + man/sd-bus.xml | 111 + man/sd-daemon.xml | 117 + man/sd-event.xml | 162 + man/sd-id128.xml | 168 + man/sd-journal.xml | 118 + man/sd-login.xml | 248 + man/sd_booted.xml | 68 + man/sd_bus_add_match.xml | 173 + man/sd_bus_add_object_vtable.xml | 473 + man/sd_bus_attach_event.xml | 119 + man/sd_bus_close.xml | 98 + man/sd_bus_creds_get_pid.xml | 527 + man/sd_bus_creds_new_from_pid.xml | 315 + man/sd_bus_default.xml | 322 + man/sd_bus_error.xml | 367 + man/sd_bus_error_add_map.xml | 139 + man/sd_bus_get_fd.xml | 160 + man/sd_bus_get_n_queued_read.xml | 100 + man/sd_bus_is_open.xml | 103 + man/sd_bus_message_append.xml | 249 + man/sd_bus_message_append_array.xml | 178 + man/sd_bus_message_append_basic.xml | 261 + man/sd_bus_message_append_string_memfd.xml | 119 + man/sd_bus_message_append_strv.xml | 81 + man/sd_bus_message_copy.xml | 111 + man/sd_bus_message_get_cookie.xml | 107 + man/sd_bus_message_get_monotonic_usec.xml | 141 + man/sd_bus_message_get_signature.xml | 111 + man/sd_bus_message_get_type.xml | 129 + man/sd_bus_message_new.xml | 189 + man/sd_bus_message_new_method_call.xml | 166 + man/sd_bus_message_new_method_error.xml | 187 + man/sd_bus_message_new_signal.xml | 120 + man/sd_bus_message_read.xml | 227 + man/sd_bus_message_read_array.xml | 108 + man/sd_bus_message_read_basic.xml | 235 + man/sd_bus_message_rewind.xml | 88 + man/sd_bus_message_set_destination.xml | 153 + man/sd_bus_message_set_expect_reply.xml | 127 + man/sd_bus_message_skip.xml | 108 + man/sd_bus_message_verify_type.xml | 99 + man/sd_bus_negotiate_fds.xml | 144 + man/sd_bus_new.xml | 201 + man/sd_bus_path_encode.xml | 153 + man/sd_bus_process.xml | 133 + man/sd_bus_reply_method_error.xml | 158 + man/sd_bus_request_name.xml | 208 + man/sd_bus_set_close_on_exit.xml | 102 + man/sd_bus_set_connected_signal.xml | 109 + man/sd_bus_set_description.xml | 177 + man/sd_bus_set_sender.xml | 103 + man/sd_bus_set_watch_bind.xml | 118 + man/sd_bus_slot_ref.xml | 107 + man/sd_bus_slot_set_description.xml | 105 + man/sd_bus_slot_set_destroy_callback.xml | 130 + man/sd_bus_slot_set_floating.xml | 117 + man/sd_bus_slot_set_userdata.xml | 88 + man/sd_bus_track_add_name.xml | 228 + man/sd_bus_track_new.xml | 231 + man/sd_bus_wait.xml | 113 + man/sd_event_add_child.xml | 221 + man/sd_event_add_defer.xml | 191 + man/sd_event_add_inotify.xml | 191 + man/sd_event_add_io.xml | 305 + man/sd_event_add_signal.xml | 196 + man/sd_event_add_time.xml | 288 + man/sd_event_exit.xml | 135 + man/sd_event_get_fd.xml | 111 + man/sd_event_new.xml | 216 + man/sd_event_now.xml | 114 + man/sd_event_run.xml | 164 + man/sd_event_set_watchdog.xml | 145 + man/sd_event_source_get_event.xml | 74 + man/sd_event_source_get_pending.xml | 137 + man/sd_event_source_set_description.xml | 140 + man/sd_event_source_set_destroy_callback.xml | 112 + man/sd_event_source_set_enabled.xml | 154 + man/sd_event_source_set_floating.xml | 118 + man/sd_event_source_set_prepare.xml | 142 + man/sd_event_source_set_priority.xml | 166 + man/sd_event_source_set_userdata.xml | 93 + man/sd_event_source_unref.xml | 136 + man/sd_event_wait.xml | 324 + man/sd_get_seats.xml | 118 + man/sd_id128_get_machine.xml | 208 + man/sd_id128_randomize.xml | 79 + man/sd_id128_to_string.xml | 94 + man/sd_is_fifo.xml | 201 + man/sd_journal_add_match.xml | 177 + man/sd_journal_enumerate_fields.xml | 133 + man/sd_journal_get_catalog.xml | 113 + man/sd_journal_get_cursor.xml | 114 + man/sd_journal_get_cutoff_realtime_usec.xml | 114 + man/sd_journal_get_data.xml | 201 + man/sd_journal_get_fd.xml | 259 + man/sd_journal_get_realtime_usec.xml | 112 + man/sd_journal_get_usage.xml | 71 + man/sd_journal_has_runtime_files.xml | 79 + man/sd_journal_next.xml | 175 + man/sd_journal_open.xml | 202 + man/sd_journal_print.xml | 210 + man/sd_journal_query_unique.xml | 156 + man/sd_journal_seek_head.xml | 131 + man/sd_journal_stream_fd.xml | 146 + man/sd_listen_fds.xml | 230 + man/sd_login_monitor_new.xml | 247 + man/sd_machine_get_class.xml | 115 + man/sd_notify.xml | 410 + man/sd_pid_get_owner_uid.xml | 314 + man/sd_seat_get_active.xml | 170 + man/sd_session_is_active.xml | 315 + man/sd_uid_get_state.xml | 190 + man/sd_watchdog_enabled.xml | 142 + man/send-unit-files-changed.c | 16 + man/shutdown.xml | 148 + man/standard-conf.xml | 77 + man/standard-options.xml | 55 + man/sysctl.d.xml | 165 + man/system-only.xml | 16 + man/systemctl.xml | 2185 + man/systemd-analyze.xml | 765 + man/systemd-ask-password-console.service.xml | 68 + man/systemd-ask-password.xml | 213 + man/systemd-backlight@.service.xml | 69 + man/systemd-binfmt.service.xml | 60 + man/systemd-bless-boot-generator.xml | 48 + man/systemd-bless-boot.service.xml | 112 + ...systemd-boot-check-no-failures.service.xml | 51 + man/systemd-boot-system-token.service.xml | 76 + man/systemd-boot.xml | 490 + man/systemd-cat.xml | 174 + man/systemd-cgls.xml | 133 + man/systemd-cgtop.xml | 356 + man/systemd-coredump.xml | 149 + man/systemd-cryptsetup-generator.xml | 182 + man/systemd-cryptsetup@.service.xml | 59 + man/systemd-debug-generator.xml | 85 + man/systemd-delta.xml | 178 + man/systemd-detect-virt.xml | 267 + man/systemd-environment-d-generator.xml | 53 + man/systemd-escape.xml | 182 + man/systemd-firstboot.xml | 268 + man/systemd-fsck@.service.xml | 114 + man/systemd-fstab-generator.xml | 212 + man/systemd-getty-generator.xml | 73 + man/systemd-gpt-auto-generator.xml | 275 + man/systemd-halt.service.xml | 93 + man/systemd-hibernate-resume-generator.xml | 83 + man/systemd-hibernate-resume@.service.xml | 56 + man/systemd-hostnamed.service.xml | 58 + man/systemd-hwdb.xml | 84 + man/systemd-id128.xml | 132 + man/systemd-importd.service.xml | 55 + man/systemd-inhibit.xml | 154 + man/systemd-initctl.service.xml | 49 + man/systemd-journal-gatewayd.service.xml | 294 + man/systemd-journal-remote.service.xml | 350 + man/systemd-journal-upload.service.xml | 286 + man/systemd-journald.service.xml | 305 + man/systemd-localed.service.xml | 60 + man/systemd-logind.service.xml | 103 + man/systemd-machine-id-commit.service.xml | 74 + man/systemd-machine-id-setup.xml | 151 + man/systemd-machined.service.xml | 63 + man/systemd-makefs@.service.xml | 94 + man/systemd-modules-load.service.xml | 71 + man/systemd-mount.xml | 326 + man/systemd-networkd-wait-online.service.xml | 129 + man/systemd-networkd.service.xml | 93 + man/systemd-notify.xml | 181 + man/systemd-nspawn.xml | 1484 + man/systemd-path.xml | 81 + man/systemd-portabled.service.xml | 50 + man/systemd-pstore.xml | 99 + man/systemd-quotacheck.service.xml | 69 + man/systemd-random-seed.service.xml | 92 + man/systemd-rc-local-generator.xml | 55 + man/systemd-remount-fs.service.xml | 70 + man/systemd-resolved.service.xml | 285 + man/systemd-rfkill.service.xml | 65 + man/systemd-run-generator.xml | 81 + man/systemd-run.xml | 540 + man/systemd-sleep.conf.xml | 202 + man/systemd-socket-activate.xml | 181 + man/systemd-socket-proxyd.xml | 174 + man/systemd-suspend.service.xml | 127 + man/systemd-sysctl.service.xml | 129 + man/systemd-system-update-generator.xml | 50 + man/systemd-system.conf.xml | 436 + man/systemd-sysusers.xml | 135 + man/systemd-sysv-generator.xml | 72 + man/systemd-time-wait-sync.service.xml | 68 + man/systemd-timedated.service.xml | 90 + man/systemd-timesyncd.service.xml | 104 + man/systemd-tmpfiles.xml | 235 + man/systemd-tty-ask-password-agent.xml | 126 + man/systemd-udev-settle.service.xml | 51 + man/systemd-udevd.service.xml | 199 + man/systemd-update-done.service.xml | 72 + man/systemd-update-utmp.service.xml | 51 + man/systemd-user-sessions.service.xml | 50 + man/systemd-vconsole-setup.service.xml | 63 + man/systemd-veritysetup-generator.xml | 97 + man/systemd-veritysetup@.service.xml | 50 + man/systemd-volatile-root.service.xml | 54 + man/systemd.automount.xml | 161 + man/systemd.device.xml | 165 + man/systemd.dnssd.xml | 231 + man/systemd.environment-generator.xml | 134 + man/systemd.exec.xml | 3186 + man/systemd.generator.xml | 318 + man/systemd.journal-fields.xml | 553 + man/systemd.kill.xml | 191 + man/systemd.link.xml | 782 + man/systemd.mount.xml | 548 + man/systemd.net-naming-scheme.xml | 442 + man/systemd.netdev.xml | 2131 + man/systemd.network.xml | 2664 + man/systemd.nspawn.xml | 553 + man/systemd.offline-updates.xml | 163 + man/systemd.path.xml | 192 + man/systemd.preset.xml | 173 + man/systemd.resource-control.xml | 1032 + man/systemd.scope.xml | 117 + man/systemd.service.xml | 1524 + man/systemd.slice.xml | 114 + man/systemd.socket.xml | 872 + man/systemd.special.xml | 1143 + man/systemd.swap.xml | 258 + man/systemd.syntax.xml | 130 + man/systemd.target.xml | 135 + man/systemd.time.xml | 301 + man/systemd.timer.xml | 350 + man/systemd.unit.xml | 1993 + man/systemd.xml | 1241 + man/sysusers.d.xml | 296 + man/telinit.xml | 152 + man/threads-aware.xml | 15 + man/timedatectl.xml | 325 + man/timesyncd.conf.xml | 106 + man/tmpfiles.d.xml | 817 + man/udev.conf.xml | 117 + man/udev.xml | 789 + man/udev_device_get_syspath.xml | 180 + man/udev_device_has_tag.xml | 143 + man/udev_device_new_from_syspath.xml | 187 + man/udev_enumerate_add_match_subsystem.xml | 136 + man/udev_enumerate_new.xml | 84 + man/udev_enumerate_scan_devices.xml | 106 + man/udev_list_entry.xml | 96 + man/udev_monitor_filter_update.xml | 95 + man/udev_monitor_new_from_netlink.xml | 86 + man/udev_monitor_receive_device.xml | 110 + man/udev_new.xml | 83 + man/udevadm.xml | 579 + man/user-system-options.xml | 52 + man/user@.service.xml | 191 + man/vconsole.conf.xml | 144 + man/vtable-example.c | 70 + man/vtable-example.xml | 54 + meson.build | 3293 + meson_options.txt | 346 + mkosi.build | 101 + mkosi.default | 1 + modprobe.d/systemd.conf | 20 + network/80-container-host0.network | 25 + network/80-container-ve.network | 25 + network/80-container-vz.network | 24 + network/80-wifi-adhoc.network | 6 + network/80-wifi-ap.network.example | 8 + network/80-wifi-station.network.example | 6 + network/99-default.link | 15 + network/meson.build | 17 + po/.gitignore | 1 + po/LINGUAS | 29 + po/POTFILES.in | 11 + po/POTFILES.skip | 20 + po/be.po | 592 + po/be@latin.po | 605 + po/bg.po | 618 + po/ca.po | 667 + po/cs.po | 812 + po/da.po | 609 + po/de.po | 633 + po/el.po | 614 + po/es.po | 612 + po/fr.po | 748 + po/gl.po | 584 + po/hr.po | 571 + po/hu.po | 597 + po/id.po | 624 + po/it.po | 728 + po/its/polkit.its | 8 + po/its/polkit.loc | 6 + po/ja.po | 779 + po/ko.po | 545 + po/lt.po | 724 + po/meson.build | 6 + po/pl.po | 887 + po/pt_BR.po | 854 + po/ro.po | 618 + po/ru.po | 744 + po/sk.po | 556 + po/sr.po | 676 + po/sv.po | 626 + po/tr.po | 704 + po/uk.po | 813 + po/zh_CN.po | 524 + po/zh_TW.po | 760 + presets/90-systemd.preset | 52 + presets/meson.build | 7 + presets/user/90-systemd.preset | 21 + rules.d/50-udev-default.rules.in | 91 + rules.d/60-block.rules | 13 + rules.d/60-cdrom_id.rules | 29 + rules.d/60-drm.rules | 8 + rules.d/60-evdev.rules | 23 + rules.d/60-fido-id.rules | 7 + rules.d/60-input-id.rules | 8 + rules.d/60-persistent-alsa.rules | 14 + rules.d/60-persistent-input.rules | 42 + rules.d/60-persistent-storage-tape.rules | 36 + rules.d/60-persistent-storage.rules | 123 + rules.d/60-persistent-v4l.rules | 20 + rules.d/60-sensor.rules | 18 + rules.d/60-serial.rules | 26 + rules.d/61-autosuspend-manual.rules | 19 + rules.d/64-btrfs.rules.in | 17 + rules.d/70-joystick.rules | 12 + rules.d/70-mouse.rules | 18 + rules.d/70-touchpad.rules | 13 + rules.d/75-net-description.rules | 14 + rules.d/75-probe_mtd.rules | 7 + rules.d/78-sound-card.rules | 96 + rules.d/80-drivers.rules | 13 + rules.d/80-net-setup-link.rules | 13 + rules.d/99-systemd.rules.in | 78 + rules.d/meson.build | 55 + semaphoreci/semaphore-runner.sh | 104 + shell-completion/bash/bootctl | 95 + shell-completion/bash/busctl | 207 + shell-completion/bash/coredumpctl | 94 + shell-completion/bash/hostnamectl | 65 + shell-completion/bash/journalctl | 149 + shell-completion/bash/kernel-install | 48 + shell-completion/bash/localectl | 96 + shell-completion/bash/loginctl | 125 + shell-completion/bash/machinectl | 116 + shell-completion/bash/meson.build | 52 + shell-completion/bash/networkctl | 71 + shell-completion/bash/portablectl | 111 + shell-completion/bash/resolvectl | 181 + shell-completion/bash/systemctl.in | 335 + shell-completion/bash/systemd-analyze | 186 + shell-completion/bash/systemd-cat | 57 + shell-completion/bash/systemd-cgls | 69 + shell-completion/bash/systemd-cgtop | 61 + shell-completion/bash/systemd-delta | 60 + shell-completion/bash/systemd-detect-virt | 40 + shell-completion/bash/systemd-id128 | 74 + shell-completion/bash/systemd-nspawn | 194 + shell-completion/bash/systemd-path | 61 + shell-completion/bash/systemd-resolve | 80 + shell-completion/bash/systemd-run | 130 + shell-completion/bash/timedatectl | 95 + shell-completion/bash/udevadm | 244 + shell-completion/zsh/_bootctl | 62 + shell-completion/zsh/_busctl | 286 + shell-completion/zsh/_coredumpctl | 46 + shell-completion/zsh/_hostnamectl | 87 + shell-completion/zsh/_journalctl | 136 + shell-completion/zsh/_kernel-install | 27 + shell-completion/zsh/_localectl | 98 + shell-completion/zsh/_loginctl | 176 + shell-completion/zsh/_machinectl | 105 + shell-completion/zsh/_networkctl | 38 + shell-completion/zsh/_resolvectl | 87 + .../zsh/_sd_hosts_or_user_at_host | 6 + shell-completion/zsh/_sd_machines | 16 + shell-completion/zsh/_sd_outputmodes | 6 + shell-completion/zsh/_sd_unit_files | 10 + shell-completion/zsh/_systemctl.in | 424 + shell-completion/zsh/_systemd | 81 + shell-completion/zsh/_systemd-analyze | 82 + shell-completion/zsh/_systemd-delta | 17 + shell-completion/zsh/_systemd-inhibit | 36 + shell-completion/zsh/_systemd-nspawn | 52 + shell-completion/zsh/_systemd-run | 65 + shell-completion/zsh/_systemd-tmpfiles | 14 + shell-completion/zsh/_timedatectl | 67 + shell-completion/zsh/_udevadm | 149 + shell-completion/zsh/meson.build | 47 + src/ac-power/ac-power.c | 90 + src/activate/activate.c | 524 + src/analyze/analyze-condition.c | 155 + src/analyze/analyze-condition.h | 6 + src/analyze/analyze-security.c | 2147 + src/analyze/analyze-security.h | 12 + src/analyze/analyze-verify.c | 290 + src/analyze/analyze-verify.h | 8 + src/analyze/analyze.c | 2518 + src/analyze/meson.build | 11 + src/ask-password/ask-password.c | 189 + src/backlight/backlight.c | 435 + src/basic/MurmurHash2.c | 90 + src/basic/MurmurHash2.h | 30 + src/basic/af-list.c | 40 + src/basic/af-list.h | 25 + src/basic/af-to-name.awk | 9 + src/basic/alloc-util.c | 112 + src/basic/alloc-util.h | 174 + src/basic/architecture.c | 178 + src/basic/architecture.h | 237 + src/basic/arphrd-list.c | 25 + src/basic/arphrd-list.h | 5 + src/basic/arphrd-to-name.awk | 12 + src/basic/async.c | 108 + src/basic/async.h | 7 + src/basic/audit-util.c | 89 + src/basic/audit-util.h | 17 + src/basic/blockdev-util.c | 183 + src/basic/blockdev-util.h | 20 + src/basic/btrfs-util.c | 1986 + src/basic/btrfs-util.h | 121 + src/basic/build.h | 156 + src/basic/bus-label.c | 81 + src/basic/bus-label.h | 14 + src/basic/cap-list.c | 118 + src/basic/cap-list.h | 9 + src/basic/cap-to-name.awk | 9 + src/basic/capability-util.c | 574 + src/basic/capability-util.h | 77 + src/basic/cgroup-util.c | 2130 + src/basic/cgroup-util.h | 251 + src/basic/chattr-util.c | 96 + src/basic/chattr-util.h | 39 + src/basic/conf-files.c | 318 + src/basic/conf-files.h | 23 + src/basic/copy.c | 942 + src/basic/copy.h | 63 + src/basic/def.h | 65 + src/basic/device-nodes.c | 63 + src/basic/device-nodes.h | 16 + src/basic/dirent-util.c | 71 + src/basic/dirent-util.h | 36 + src/basic/efivars.c | 284 + src/basic/efivars.h | 75 + src/basic/env-file.c | 563 + src/basic/env-file.h | 17 + src/basic/env-util.c | 751 + src/basic/env-util.h | 54 + src/basic/errno-list.c | 37 + src/basic/errno-list.h | 15 + src/basic/errno-to-name.awk | 9 + src/basic/errno-util.h | 103 + src/basic/escape.c | 551 + src/basic/escape.h | 57 + src/basic/ether-addr-util.c | 111 + src/basic/ether-addr-util.h | 28 + src/basic/extract-word.c | 284 + src/basic/extract-word.h | 17 + src/basic/fd-util.c | 978 + src/basic/fd-util.h | 98 + src/basic/fileio.c | 1044 + src/basic/fileio.h | 100 + src/basic/format-util.c | 81 + src/basic/format-util.h | 91 + src/basic/fs-util.c | 1394 + src/basic/fs-util.h | 123 + src/basic/gcrypt-util.c | 49 + src/basic/gcrypt-util.h | 34 + src/basic/generate-af-list.sh | 6 + src/basic/generate-arphrd-list.sh | 6 + src/basic/generate-cap-list.sh | 6 + src/basic/generate-errno-list.sh | 5 + src/basic/glob-util.c | 73 + src/basic/glob-util.h | 21 + src/basic/gunicode.c | 110 + src/basic/gunicode.h | 30 + src/basic/hash-funcs.c | 90 + src/basic/hash-funcs.h | 106 + src/basic/hashmap.c | 1938 + src/basic/hashmap.h | 433 + src/basic/hexdecoct.c | 862 + src/basic/hexdecoct.h | 44 + src/basic/hostname-util.c | 307 + src/basic/hostname-util.h | 28 + src/basic/in-addr-util.c | 760 + src/basic/in-addr-util.h | 76 + src/basic/io-util.c | 345 + src/basic/io-util.h | 92 + src/basic/ioprio.h | 56 + src/basic/kbd-util.c | 109 + src/basic/kbd-util.h | 20 + src/basic/khash.c | 322 + src/basic/khash.h | 37 + src/basic/label.c | 64 + src/basic/label.h | 18 + src/basic/limits-util.c | 156 + src/basic/limits-util.h | 10 + src/basic/linux/README | 6 + src/basic/linux/btrfs.h | 947 + src/basic/linux/btrfs_tree.h | 976 + src/basic/linux/can/vxcan.h | 13 + src/basic/linux/fib_rules.h | 90 + src/basic/linux/fou.h | 48 + src/basic/linux/if.h | 294 + src/basic/linux/if_addr.h | 72 + src/basic/linux/if_arp.h | 164 + src/basic/linux/if_bonding.h | 155 + src/basic/linux/if_bridge.h | 316 + src/basic/linux/if_ether.h | 170 + src/basic/linux/if_link.h | 1025 + src/basic/linux/if_macsec.h | 177 + src/basic/linux/if_tun.h | 114 + src/basic/linux/if_tunnel.h | 183 + src/basic/linux/in.h | 306 + src/basic/linux/in6.h | 300 + src/basic/linux/l2tp.h | 201 + src/basic/linux/libc-compat.h | 267 + src/basic/linux/netdevice.h | 66 + src/basic/linux/netlink.h | 252 + src/basic/linux/nexthop.h | 56 + src/basic/linux/pkt_sched.h | 1184 + src/basic/linux/rtnetlink.h | 761 + src/basic/linux/update.sh | 13 + src/basic/linux/wireguard.h | 190 + src/basic/list.h | 171 + src/basic/locale-util.c | 417 + src/basic/locale-util.h | 81 + src/basic/log.c | 1368 + src/basic/log.h | 340 + src/basic/login-util.c | 12 + src/basic/login-util.h | 11 + src/basic/macro.h | 563 + src/basic/memfd-util.c | 154 + src/basic/memfd-util.h | 18 + src/basic/memory-util.c | 57 + src/basic/memory-util.h | 96 + src/basic/mempool.c | 100 + src/basic/mempool.h | 31 + src/basic/meson.build | 337 + src/basic/missing_audit.h | 24 + src/basic/missing_capability.h | 12 + src/basic/missing_drm.h | 10 + src/basic/missing_fcntl.h | 60 + src/basic/missing_fs.h | 67 + src/basic/missing_input.h | 45 + src/basic/missing_keyctl.h | 78 + src/basic/missing_magic.h | 34 + src/basic/missing_mman.h | 12 + src/basic/missing_network.h | 31 + src/basic/missing_prctl.h | 14 + src/basic/missing_random.h | 16 + src/basic/missing_resource.h | 11 + src/basic/missing_sched.h | 21 + src/basic/missing_securebits.h | 17 + src/basic/missing_socket.h | 64 + src/basic/missing_stat.h | 51 + src/basic/missing_stdlib.h | 13 + src/basic/missing_syscall.h | 526 + src/basic/missing_timerfd.h | 8 + src/basic/missing_type.h | 12 + src/basic/mkdir-label.c | 58 + src/basic/mkdir.c | 166 + src/basic/mkdir.h | 26 + src/basic/mountpoint-util.c | 443 + src/basic/mountpoint-util.h | 24 + src/basic/namespace-util.c | 171 + src/basic/namespace-util.h | 9 + src/basic/nss-util.h | 183 + src/basic/nulstr-util.c | 17 + src/basic/nulstr-util.h | 13 + src/basic/ordered-set.c | 82 + src/basic/ordered-set.h | 74 + src/basic/parse-util.c | 758 + src/basic/parse-util.h | 116 + src/basic/path-util.c | 1117 + src/basic/path-util.h | 183 + src/basic/prioq.c | 300 + src/basic/prioq.h | 32 + src/basic/proc-cmdline.c | 353 + src/basic/proc-cmdline.h | 38 + src/basic/process-util.c | 1519 + src/basic/process-util.h | 199 + src/basic/procfs-util.c | 268 + src/basic/procfs-util.h | 17 + src/basic/random-util.c | 411 + src/basic/random-util.h | 39 + src/basic/ratelimit.c | 38 + src/basic/ratelimit.h | 20 + src/basic/raw-clone.h | 79 + src/basic/raw-reboot.h | 14 + src/basic/replace-var.c | 93 + src/basic/replace-var.h | 4 + src/basic/rlimit-util.c | 409 + src/basic/rlimit-util.h | 25 + src/basic/rm-rf.c | 227 + src/basic/rm-rf.h | 33 + src/basic/selinux-util.c | 520 + src/basic/selinux-util.h | 34 + src/basic/set.h | 130 + src/basic/sigbus.c | 139 + src/basic/sigbus.h | 7 + src/basic/signal-util.c | 289 + src/basic/signal-util.h | 43 + src/basic/siphash24.c | 206 + src/basic/siphash24.h | 29 + src/basic/smack-util.c | 288 + src/basic/smack-util.h | 42 + src/basic/socket-label.c | 164 + src/basic/socket-util.c | 1414 + src/basic/socket-util.h | 204 + src/basic/sort-util.c | 27 + src/basic/sort-util.h | 70 + src/basic/sparse-endian.h | 90 + src/basic/special.h | 107 + src/basic/stat-util.c | 379 + src/basic/stat-util.h | 89 + src/basic/static-destruct.h | 56 + src/basic/stdio-util.h | 64 + src/basic/strbuf.c | 183 + src/basic/strbuf.h | 39 + src/basic/string-table.c | 17 + src/basic/string-table.h | 111 + src/basic/string-util.c | 1066 + src/basic/string-util.h | 280 + src/basic/strv.c | 950 + src/basic/strv.h | 207 + src/basic/strxcpyx.c | 116 + src/basic/strxcpyx.h | 14 + src/basic/syslog-util.c | 98 + src/basic/syslog-util.h | 14 + src/basic/terminal-util.c | 1372 + src/basic/terminal-util.h | 168 + src/basic/time-util.c | 1528 + src/basic/time-util.h | 185 + src/basic/tmpfile-util.c | 332 + src/basic/tmpfile-util.h | 19 + src/basic/umask-util.h | 26 + src/basic/unaligned.h | 99 + src/basic/unit-def.c | 279 + src/basic/unit-def.h | 293 + src/basic/unit-name.c | 773 + src/basic/unit-name.h | 63 + src/basic/user-util.c | 942 + src/basic/user-util.h | 129 + src/basic/utf8.c | 581 + src/basic/utf8.h | 54 + src/basic/util.c | 273 + src/basic/util.h | 68 + src/basic/virt.c | 670 + src/basic/virt.h | 60 + src/basic/xattr-util.c | 270 + src/basic/xattr-util.h | 27 + src/binfmt/binfmt.c | 227 + src/boot/bless-boot-generator.c | 71 + src/boot/bless-boot.c | 525 + src/boot/boot-check-no-failures.c | 114 + src/boot/bootctl.c | 1800 + src/boot/efi/boot.c | 2512 + src/boot/efi/console.c | 227 + src/boot/efi/console.h | 24 + src/boot/efi/crc32.c | 142 + src/boot/efi/crc32.h | 8 + src/boot/efi/disk.c | 35 + src/boot/efi/disk.h | 4 + src/boot/efi/graphics.c | 77 + src/boot/efi/graphics.h | 8 + src/boot/efi/linux.c | 74 + src/boot/efi/linux.h | 87 + src/boot/efi/loader-features.h | 14 + src/boot/efi/measure.c | 317 + src/boot/efi/measure.h | 4 + src/boot/efi/meson.build | 252 + src/boot/efi/missing_efi.h | 55 + src/boot/efi/no-undefined-symbols.sh | 7 + src/boot/efi/pe.c | 170 + src/boot/efi/pe.h | 7 + src/boot/efi/random-seed.c | 326 + src/boot/efi/random-seed.h | 14 + src/boot/efi/sha256.c | 275 + src/boot/efi/sha256.h | 28 + src/boot/efi/shim.c | 210 + src/boot/efi/shim.h | 16 + src/boot/efi/splash.c | 305 + src/boot/efi/splash.h | 4 + src/boot/efi/stub.c | 134 + src/boot/efi/util.c | 358 + src/boot/efi/util.h | 70 + src/busctl/busctl-introspect.c | 730 + src/busctl/busctl-introspect.h | 14 + src/busctl/busctl.c | 2567 + src/cgls/cgls.c | 302 + src/cgroups-agent/cgroups-agent.c | 47 + src/cgtop/cgtop.c | 1103 + src/core/all-units.h | 15 + src/core/audit-fd.c | 63 + src/core/audit-fd.h | 5 + src/core/automount.c | 1150 + src/core/automount.h | 43 + src/core/bpf-devices.c | 489 + src/core/bpf-devices.h | 21 + src/core/bpf-firewall.c | 918 + src/core/bpf-firewall.h | 23 + src/core/cgroup.c | 3635 + src/core/cgroup.h | 276 + src/core/chown-recursive.c | 141 + src/core/chown-recursive.h | 6 + src/core/dbus-automount.c | 64 + src/core/dbus-automount.h | 11 + src/core/dbus-cgroup.c | 1675 + src/core/dbus-cgroup.h | 14 + src/core/dbus-device.c | 11 + src/core/dbus-device.h | 6 + src/core/dbus-execute.c | 2559 + src/core/dbus-execute.h | 33 + src/core/dbus-job.c | 313 + src/core/dbus-job.h | 19 + src/core/dbus-kill.c | 83 + src/core/dbus-kill.h | 12 + src/core/dbus-manager.c | 2656 + src/core/dbus-manager.h | 16 + src/core/dbus-mount.c | 152 + src/core/dbus-mount.h | 12 + src/core/dbus-path.c | 159 + src/core/dbus-path.h | 11 + src/core/dbus-scope.c | 261 + src/core/dbus-scope.h | 19 + src/core/dbus-service.c | 454 + src/core/dbus-service.h | 12 + src/core/dbus-slice.c | 35 + src/core/dbus-slice.h | 12 + src/core/dbus-socket.c | 471 + src/core/dbus-socket.h | 12 + src/core/dbus-swap.c | 70 + src/core/dbus-swap.h | 16 + src/core/dbus-target.c | 9 + src/core/dbus-target.h | 6 + src/core/dbus-timer.c | 378 + src/core/dbus-timer.h | 11 + src/core/dbus-unit.c | 2280 + src/core/dbus-unit.h | 39 + src/core/dbus-util.c | 121 + src/core/dbus-util.h | 248 + src/core/dbus.c | 1317 + src/core/dbus.h | 37 + src/core/device.c | 1102 + src/core/device.h | 43 + src/core/dynamic-user.c | 826 + src/core/dynamic-user.h | 40 + src/core/efi-random.c | 110 + src/core/efi-random.h | 4 + src/core/emergency-action.c | 158 + src/core/emergency-action.h | 34 + src/core/execute.c | 5636 + src/core/execute.h | 424 + src/core/hostname-setup.c | 51 + src/core/hostname-setup.h | 4 + src/core/ima-setup.c | 92 + src/core/ima-setup.h | 9 + src/core/ip-address-access.c | 208 + src/core/ip-address-access.h | 25 + src/core/job.c | 1686 + src/core/job.h | 243 + src/core/kill.c | 57 + src/core/kill.h | 56 + src/core/killall.c | 285 + src/core/killall.h | 6 + src/core/kmod-setup.c | 127 + src/core/kmod-setup.h | 4 + src/core/load-dropin.c | 142 + src/core/load-dropin.h | 20 + src/core/load-fragment-gperf-nulstr.awk | 14 + src/core/load-fragment-gperf.gperf.m4 | 480 + src/core/load-fragment.c | 5006 + src/core/load-fragment.h | 127 + src/core/locale-setup.c | 96 + src/core/locale-setup.h | 4 + src/core/loopback-setup.c | 213 + src/core/loopback-setup.h | 4 + src/core/machine-id-setup.c | 249 + src/core/machine-id-setup.h | 5 + src/core/macros.systemd.in | 158 + src/core/main.c | 2757 + src/core/manager.c | 4732 + src/core/manager.h | 557 + src/core/meson.build | 217 + src/core/mount-setup.c | 542 + src/core/mount-setup.h | 12 + src/core/mount.c | 2127 + src/core/mount.h | 100 + src/core/namespace.c | 1910 + src/core/namespace.h | 117 + src/core/org.freedesktop.systemd1.conf | 400 + src/core/org.freedesktop.systemd1.policy.in | 73 + src/core/org.freedesktop.systemd1.service | 13 + src/core/path.c | 833 + src/core/path.h | 77 + src/core/scope.c | 656 + src/core/scope.h | 45 + src/core/selinux-access.c | 276 + src/core/selinux-access.h | 24 + src/core/selinux-setup.c | 107 + src/core/selinux-setup.h | 6 + src/core/service.c | 4473 + src/core/service.h | 227 + src/core/show-status.c | 127 + src/core/show-status.h | 39 + src/core/slice.c | 394 + src/core/slice.h | 18 + src/core/smack-setup.c | 396 + src/core/smack-setup.h | 10 + src/core/socket.c | 3482 + src/core/socket.h | 183 + src/core/swap.c | 1656 + src/core/swap.h | 99 + src/core/system.conf.in | 70 + src/core/systemd.pc.in | 44 + src/core/target.c | 220 + src/core/target.h | 16 + src/core/timer.c | 928 + src/core/timer.h | 78 + src/core/transaction.c | 1190 + src/core/transaction.h | 35 + src/core/triggers.systemd.in | 143 + src/core/unit-printf.c | 288 + src/core/unit-printf.h | 7 + src/core/unit.c | 5942 + src/core/unit.h | 899 + src/core/user.conf.in | 46 + src/coredump/coredump-vacuum.c | 248 + src/coredump/coredump-vacuum.h | 7 + src/coredump/coredump.c | 1354 + src/coredump/coredump.conf | 21 + src/coredump/coredumpctl.c | 1102 + src/coredump/meson.build | 28 + src/coredump/stacktrace.c | 198 + src/coredump/stacktrace.h | 4 + src/coredump/test-coredump-vacuum.c | 13 + src/cryptsetup/cryptsetup-generator.c | 709 + src/cryptsetup/cryptsetup.c | 766 + src/debug-generator/debug-generator.c | 190 + src/delta/delta.c | 690 + src/detect-virt/detect-virt.c | 178 + src/dissect/dissect.c | 282 + .../environment-d-generator.c | 99 + src/escape/escape.c | 259 + src/firstboot/firstboot.c | 988 + src/fsck/fsck.c | 430 + src/fstab-generator/fstab-generator.c | 905 + src/fuzz/fuzz-bus-label.c | 18 + src/fuzz/fuzz-bus-message.c | 45 + src/fuzz/fuzz-calendarspec.c | 24 + src/fuzz/fuzz-catalog.c | 26 + src/fuzz/fuzz-compress.c | 80 + src/fuzz/fuzz-dhcp-server.c | 56 + src/fuzz/fuzz-dhcp-server.options | 2 + src/fuzz/fuzz-dhcp6-client.c | 62 + src/fuzz/fuzz-dhcp6-client.options | 2 + src/fuzz/fuzz-dns-packet.c | 25 + src/fuzz/fuzz-dns-packet.options | 2 + src/fuzz/fuzz-env-file.c | 32 + src/fuzz/fuzz-env-file.options | 2 + src/fuzz/fuzz-fido-id-desc.dict | 6 + src/fuzz/fuzz-hostname-util.c | 27 + src/fuzz/fuzz-journal-remote.c | 78 + src/fuzz/fuzz-journal-remote.options | 2 + src/fuzz/fuzz-journald-audit.c | 15 + src/fuzz/fuzz-journald-kmsg.c | 18 + src/fuzz/fuzz-journald-native-fd.c | 47 + src/fuzz/fuzz-journald-native.c | 10 + src/fuzz/fuzz-journald-stream.c | 37 + src/fuzz/fuzz-journald-stream.options | 2 + src/fuzz/fuzz-journald-syslog.c | 10 + src/fuzz/fuzz-journald.c | 46 + src/fuzz/fuzz-journald.h | 12 + src/fuzz/fuzz-json.c | 31 + src/fuzz/fuzz-lldp.c | 43 + src/fuzz/fuzz-lldp.options | 2 + src/fuzz/fuzz-main.c | 45 + src/fuzz/fuzz-ndisc-rs.c | 61 + src/fuzz/fuzz-ndisc-rs.options | 2 + src/fuzz/fuzz-nspawn-oci.c | 27 + src/fuzz/fuzz-nspawn-settings.c | 27 + src/fuzz/fuzz-time-util.c | 28 + src/fuzz/fuzz-udev-database.c | 26 + src/fuzz/fuzz-udev-rules.c | 106 + src/fuzz/fuzz-unit-file.c | 85 + src/fuzz/fuzz-varlink.c | 131 + src/fuzz/fuzz.h | 11 + src/fuzz/fuzzer-entry-point.c | 5 + src/fuzz/meson.build | 149 + src/getty-generator/getty-generator.c | 208 + src/gpt-auto-generator/gpt-auto-generator.c | 832 + .../hibernate-resume-generator.c | 142 + src/hibernate-resume/hibernate-resume.c | 63 + src/hostname/hostnamectl.c | 454 + src/hostname/hostnamed.c | 767 + src/hostname/meson.build | 10 + src/hostname/org.freedesktop.hostname1.conf | 29 + src/hostname/org.freedesktop.hostname1.policy | 60 + .../org.freedesktop.hostname1.service | 12 + src/hwdb/hwdb.c | 133 + src/id128/id128.c | 179 + src/import/curl-util.c | 372 + src/import/curl-util.h | 39 + src/import/export-raw.c | 331 + src/import/export-raw.h | 18 + src/import/export-tar.c | 330 + src/import/export-tar.h | 18 + src/import/export.c | 297 + src/import/import-common.c | 268 + src/import/import-common.h | 12 + src/import/import-compress.c | 466 + src/import/import-compress.h | 47 + src/import/import-fs.c | 326 + src/import/import-pubring.gpg | Bin 0 -> 9551 bytes src/import/import-raw.c | 437 + src/import/import-raw.h | 18 + src/import/import-tar.c | 368 + src/import/import-tar.h | 18 + src/import/import.c | 319 + src/import/importd.c | 1272 + src/import/meson.build | 79 + src/import/org.freedesktop.import1.conf | 84 + src/import/org.freedesktop.import1.policy | 51 + src/import/org.freedesktop.import1.service | 14 + src/import/pull-common.c | 528 + src/import/pull-common.h | 18 + src/import/pull-job.c | 639 + src/import/pull-job.h | 93 + src/import/pull-raw.c | 750 + src/import/pull-raw.h | 18 + src/import/pull-tar.c | 559 + src/import/pull-tar.h | 18 + src/import/pull.c | 332 + src/import/qcow2-util.c | 334 + src/import/qcow2-util.h | 5 + src/import/test-qcow2.c | 39 + src/initctl/initctl.c | 407 + src/journal-remote/browse.html | 547 + src/journal-remote/journal-gatewayd.c | 1048 + src/journal-remote/journal-remote-main.c | 1172 + src/journal-remote/journal-remote-parse.c | 88 + src/journal-remote/journal-remote-parse.h | 20 + src/journal-remote/journal-remote-write.c | 106 + src/journal-remote/journal-remote-write.h | 40 + src/journal-remote/journal-remote.c | 536 + src/journal-remote/journal-remote.conf.in | 19 + src/journal-remote/journal-remote.h | 65 + src/journal-remote/journal-upload-journal.c | 414 + src/journal-remote/journal-upload.c | 854 + src/journal-remote/journal-upload.conf.in | 18 + src/journal-remote/journal-upload.h | 71 + src/journal-remote/log-generator.py | 78 + src/journal-remote/meson.build | 73 + src/journal-remote/microhttpd-util.c | 311 + src/journal-remote/microhttpd-util.h | 78 + src/journal/audit-type.c | 6 + src/journal/audit-type.h | 22 + src/journal/audit_type-to-name.awk | 9 + src/journal/cat.c | 171 + src/journal/catalog.c | 743 + src/journal/catalog.h | 19 + src/journal/compress.c | 679 + src/journal/compress.h | 67 + src/journal/fsprg.c | 378 + src/journal/fsprg.h | 62 + src/journal/generate-audit_type-list.sh | 15 + src/journal/journal-authenticate.c | 536 + src/journal/journal-authenticate.h | 23 + src/journal/journal-def.h | 229 + src/journal/journal-file.c | 3923 + src/journal/journal-file.h | 263 + src/journal/journal-internal.h | 128 + src/journal/journal-qrcode.c | 119 + src/journal/journal-qrcode.h | 9 + src/journal/journal-send.c | 542 + src/journal/journal-vacuum.c | 321 + src/journal/journal-vacuum.h | 9 + src/journal/journal-verify.c | 1320 + src/journal/journal-verify.h | 6 + src/journal/journalctl.c | 2696 + src/journal/journald-audit.c | 548 + src/journal/journald-audit.h | 11 + src/journal/journald-console.c | 103 + src/journal/journald-console.h | 6 + src/journal/journald-context.c | 779 + src/journal/journald-context.h | 101 + src/journal/journald-gperf.gperf | 51 + src/journal/journald-kmsg.c | 450 + src/journal/journald-kmsg.h | 13 + src/journal/journald-native.c | 503 + src/journal/journald-native.h | 23 + src/journal/journald-rate-limit.c | 254 + src/journal/journald-rate-limit.h | 10 + src/journal/journald-server.c | 2386 + src/journal/journald-server.h | 216 + src/journal/journald-stream.c | 922 + src/journal/journald-stream.h | 15 + src/journal/journald-syslog.c | 516 + src/journal/journald-syslog.h | 15 + src/journal/journald-wall.c | 54 + src/journal/journald-wall.h | 8 + src/journal/journald.c | 112 + src/journal/journald.conf | 43 + src/journal/lookup3.c | 1005 + src/journal/lookup3.h | 22 + src/journal/meson.build | 132 + src/journal/mmap-cache.c | 669 + src/journal/mmap-cache.h | 34 + src/journal/sd-journal.c | 3134 + src/journal/test-audit-type.c | 25 + src/journal/test-catalog.c | 240 + src/journal/test-compress-benchmark.c | 176 + src/journal/test-compress.c | 343 + src/journal/test-journal-config.c | 53 + src/journal/test-journal-enum.c | 37 + src/journal/test-journal-flush.c | 66 + src/journal/test-journal-init.c | 50 + src/journal/test-journal-interleaving.c | 296 + src/journal/test-journal-match.c | 62 + src/journal/test-journal-send.c | 85 + src/journal/test-journal-stream.c | 182 + src/journal/test-journal-syslog.c | 59 + src/journal/test-journal-verify.c | 136 + src/journal/test-journal.c | 259 + src/journal/test-mmap-cache.c | 66 + src/kernel-install/00-entry-directory.install | 32 + src/kernel-install/50-depmod.install | 27 + src/kernel-install/90-loaderentry.install | 122 + src/kernel-install/kernel-install | 184 + src/kernel-install/meson.build | 14 + src/libsystemd-network/arp-util.c | 138 + src/libsystemd-network/arp-util.h | 18 + src/libsystemd-network/dhcp-client-internal.h | 4 + src/libsystemd-network/dhcp-identifier.c | 217 + src/libsystemd-network/dhcp-identifier.h | 60 + src/libsystemd-network/dhcp-internal.h | 65 + src/libsystemd-network/dhcp-lease-internal.h | 96 + src/libsystemd-network/dhcp-network.c | 234 + src/libsystemd-network/dhcp-option.c | 357 + src/libsystemd-network/dhcp-packet.c | 171 + src/libsystemd-network/dhcp-protocol.h | 99 + src/libsystemd-network/dhcp-server-internal.h | 94 + src/libsystemd-network/dhcp6-internal.h | 107 + src/libsystemd-network/dhcp6-lease-internal.h | 61 + src/libsystemd-network/dhcp6-network.c | 74 + src/libsystemd-network/dhcp6-option.c | 599 + src/libsystemd-network/dhcp6-protocol.h | 99 + src/libsystemd-network/icmp6-util.c | 212 + src/libsystemd-network/icmp6-util.h | 24 + src/libsystemd-network/lldp-internal.h | 39 + src/libsystemd-network/lldp-neighbor.c | 769 + src/libsystemd-network/lldp-neighbor.h | 91 + src/libsystemd-network/lldp-network.c | 78 + src/libsystemd-network/lldp-network.h | 6 + src/libsystemd-network/meson.build | 51 + src/libsystemd-network/ndisc-internal.h | 44 + src/libsystemd-network/ndisc-router.c | 750 + src/libsystemd-network/ndisc-router.h | 48 + src/libsystemd-network/network-internal.c | 837 + src/libsystemd-network/network-internal.h | 65 + src/libsystemd-network/radv-internal.h | 129 + src/libsystemd-network/sd-dhcp-client.c | 2072 + src/libsystemd-network/sd-dhcp-lease.c | 1358 + src/libsystemd-network/sd-dhcp-server.c | 1202 + src/libsystemd-network/sd-dhcp6-client.c | 1563 + src/libsystemd-network/sd-dhcp6-lease.c | 400 + src/libsystemd-network/sd-ipv4acd.c | 485 + src/libsystemd-network/sd-ipv4ll.c | 321 + src/libsystemd-network/sd-lldp.c | 498 + src/libsystemd-network/sd-ndisc.c | 388 + src/libsystemd-network/sd-radv.c | 916 + src/libsystemd-network/test-acd.c | 96 + src/libsystemd-network/test-dhcp-client.c | 582 + src/libsystemd-network/test-dhcp-option.c | 367 + src/libsystemd-network/test-dhcp-server.c | 244 + src/libsystemd-network/test-dhcp6-client.c | 950 + src/libsystemd-network/test-ipv4ll-manual.c | 110 + src/libsystemd-network/test-ipv4ll.c | 205 + src/libsystemd-network/test-lldp.c | 378 + src/libsystemd-network/test-ndisc-ra.c | 370 + src/libsystemd-network/test-ndisc-rs.c | 418 + src/libsystemd-network/test-sd-dhcp-lease.c | 90 + src/libsystemd/disable-mempool.c | 5 + src/libsystemd/libsystemd.pc.in | 20 + src/libsystemd/libsystemd.sym | 684 + src/libsystemd/meson.build | 115 + src/libsystemd/sd-bus/GVARIANT-SERIALIZATION | 105 + src/libsystemd/sd-bus/bus-common-errors.c | 108 + src/libsystemd/sd-bus/bus-common-errors.h | 86 + src/libsystemd/sd-bus/bus-container.c | 94 + src/libsystemd/sd-bus/bus-container.h | 6 + src/libsystemd/sd-bus/bus-control.c | 942 + src/libsystemd/sd-bus/bus-control.h | 9 + src/libsystemd/sd-bus/bus-convenience.c | 672 + src/libsystemd/sd-bus/bus-creds.c | 1340 + src/libsystemd/sd-bus/bus-creds.h | 72 + src/libsystemd/sd-bus/bus-dump.c | 593 + src/libsystemd/sd-bus/bus-dump.h | 19 + src/libsystemd/sd-bus/bus-error.c | 610 + src/libsystemd/sd-bus/bus-error.h | 48 + src/libsystemd/sd-bus/bus-gvariant.c | 299 + src/libsystemd/sd-bus/bus-gvariant.h | 12 + src/libsystemd/sd-bus/bus-internal.c | 342 + src/libsystemd/sd-bus/bus-internal.h | 415 + src/libsystemd/sd-bus/bus-introspect.c | 199 + src/libsystemd/sd-bus/bus-introspect.h | 22 + src/libsystemd/sd-bus/bus-kernel.c | 50 + src/libsystemd/sd-bus/bus-kernel.h | 24 + src/libsystemd/sd-bus/bus-match.c | 1102 + src/libsystemd/sd-bus/bus-match.h | 80 + src/libsystemd/sd-bus/bus-message.c | 5921 + src/libsystemd/sd-bus/bus-message.h | 228 + src/libsystemd/sd-bus/bus-objects.c | 3006 + src/libsystemd/sd-bus/bus-objects.h | 20 + src/libsystemd/sd-bus/bus-protocol.h | 162 + src/libsystemd/sd-bus/bus-signature.c | 148 + src/libsystemd/sd-bus/bus-signature.h | 10 + src/libsystemd/sd-bus/bus-slot.c | 311 + src/libsystemd/sd-bus/bus-slot.h | 10 + src/libsystemd/sd-bus/bus-socket.c | 1329 + src/libsystemd/sd-bus/bus-socket.h | 20 + src/libsystemd/sd-bus/bus-track.c | 492 + src/libsystemd/sd-bus/bus-track.h | 5 + src/libsystemd/sd-bus/bus-type.c | 137 + src/libsystemd/sd-bus/bus-type.h | 16 + src/libsystemd/sd-bus/sd-bus.c | 4233 + src/libsystemd/sd-bus/test-bus-address.c | 68 + src/libsystemd/sd-bus/test-bus-benchmark.c | 324 + src/libsystemd/sd-bus/test-bus-chat.c | 548 + src/libsystemd/sd-bus/test-bus-cleanup.c | 79 + src/libsystemd/sd-bus/test-bus-creds.c | 35 + src/libsystemd/sd-bus/test-bus-error.c | 216 + src/libsystemd/sd-bus/test-bus-gvariant.c | 221 + src/libsystemd/sd-bus/test-bus-introspect.c | 35 + src/libsystemd/sd-bus/test-bus-marshal.c | 422 + src/libsystemd/sd-bus/test-bus-match.c | 148 + src/libsystemd/sd-bus/test-bus-objects.c | 536 + .../sd-bus/test-bus-queue-ref-cycle.c | 56 + src/libsystemd/sd-bus/test-bus-server.c | 198 + src/libsystemd/sd-bus/test-bus-signature.c | 147 + src/libsystemd/sd-bus/test-bus-track.c | 108 + src/libsystemd/sd-bus/test-bus-vtable-cc.cc | 1 + src/libsystemd/sd-bus/test-bus-vtable.c | 76 + src/libsystemd/sd-bus/test-bus-watch-bind.c | 222 + src/libsystemd/sd-bus/test-vtable-data.h | 132 + src/libsystemd/sd-daemon/sd-daemon.c | 658 + .../sd-device/device-enumerator-private.h | 18 + src/libsystemd/sd-device/device-enumerator.c | 1035 + src/libsystemd/sd-device/device-internal.h | 102 + .../sd-device/device-monitor-private.h | 20 + src/libsystemd/sd-device/device-monitor.c | 755 + src/libsystemd/sd-device/device-private.c | 1004 + src/libsystemd/sd-device/device-private.h | 78 + src/libsystemd/sd-device/device-util.h | 57 + src/libsystemd/sd-device/sd-device.c | 1877 + .../sd-device/test-sd-device-monitor.c | 218 + .../sd-device/test-sd-device-thread.c | 39 + src/libsystemd/sd-device/test-sd-device.c | 156 + .../sd-device/test-udev-device-thread.c | 36 + src/libsystemd/sd-event/event-source.h | 206 + src/libsystemd/sd-event/event-util.c | 99 + src/libsystemd/sd-event/event-util.h | 13 + src/libsystemd/sd-event/sd-event.c | 3551 + src/libsystemd/sd-event/test-event.c | 496 + src/libsystemd/sd-hwdb/hwdb-internal.h | 65 + src/libsystemd/sd-hwdb/hwdb-util.c | 688 + src/libsystemd/sd-hwdb/hwdb-util.h | 10 + src/libsystemd/sd-hwdb/sd-hwdb.c | 466 + src/libsystemd/sd-id128/id128-util.c | 193 + src/libsystemd/sd-id128/id128-util.h | 30 + src/libsystemd/sd-id128/sd-id128.c | 337 + src/libsystemd/sd-login/sd-login.c | 1058 + src/libsystemd/sd-login/test-login.c | 287 + src/libsystemd/sd-netlink/generic-netlink.c | 176 + src/libsystemd/sd-netlink/generic-netlink.h | 6 + src/libsystemd/sd-netlink/netlink-internal.h | 150 + src/libsystemd/sd-netlink/netlink-message.c | 1085 + src/libsystemd/sd-netlink/netlink-slot.c | 202 + src/libsystemd/sd-netlink/netlink-slot.h | 14 + src/libsystemd/sd-netlink/netlink-socket.c | 453 + src/libsystemd/sd-netlink/netlink-types.c | 1221 + src/libsystemd/sd-netlink/netlink-types.h | 91 + src/libsystemd/sd-netlink/netlink-util.c | 111 + src/libsystemd/sd-netlink/netlink-util.h | 75 + src/libsystemd/sd-netlink/rtnl-message.c | 1077 + src/libsystemd/sd-netlink/sd-netlink.c | 922 + src/libsystemd/sd-netlink/test-netlink.c | 611 + src/libsystemd/sd-network/network-util.c | 58 + src/libsystemd/sd-network/network-util.h | 49 + src/libsystemd/sd-network/sd-network.c | 457 + src/libsystemd/sd-path/sd-path.c | 614 + src/libsystemd/sd-resolve/resolve-private.h | 39 + src/libsystemd/sd-resolve/sd-resolve.c | 1301 + src/libsystemd/sd-resolve/test-resolve.c | 107 + src/libsystemd/sd-utf8/sd-utf8.c | 18 + src/libudev/libudev-device-internal.h | 10 + src/libudev/libudev-device.c | 873 + src/libudev/libudev-enumerate.c | 458 + src/libudev/libudev-hwdb.c | 123 + src/libudev/libudev-list-internal.h | 16 + src/libudev/libudev-list.c | 242 + src/libudev/libudev-monitor.c | 309 + src/libudev/libudev-queue.c | 236 + src/libudev/libudev-util.c | 214 + src/libudev/libudev-util.h | 24 + src/libudev/libudev.c | 154 + src/libudev/libudev.h | 189 + src/libudev/libudev.pc.in | 19 + src/libudev/libudev.sym | 120 + src/libudev/meson.build | 29 + src/locale/kbd-model-map | 68 + src/locale/keymap-util.c | 783 + src/locale/keymap-util.h | 44 + src/locale/language-fallback-map | 13 + src/locale/localectl.c | 530 + src/locale/localed.c | 759 + src/locale/meson.build | 38 + src/locale/org.freedesktop.locale1.conf | 29 + src/locale/org.freedesktop.locale1.policy | 42 + src/locale/org.freedesktop.locale1.service | 14 + src/locale/test-keymap-util.c | 203 + src/login/70-power-switch.rules | 15 + src/login/70-uaccess.rules.m4 | 88 + src/login/71-seat.rules.in | 77 + src/login/73-seat-late.rules.m4 | 20 + src/login/inhibit.c | 333 + src/login/loginctl.c | 1546 + src/login/logind-acl.c | 253 + src/login/logind-acl.h | 34 + src/login/logind-action.c | 184 + src/login/logind-action.h | 36 + src/login/logind-brightness.c | 256 + src/login/logind-brightness.h | 9 + src/login/logind-button.c | 368 + src/login/logind-button.h | 26 + src/login/logind-core.c | 817 + src/login/logind-dbus.c | 3898 + src/login/logind-dbus.h | 31 + src/login/logind-device.c | 106 + src/login/logind-device.h | 25 + src/login/logind-gperf.gperf | 44 + src/login/logind-inhibit.c | 518 + src/login/logind-inhibit.h | 72 + src/login/logind-seat-dbus.c | 412 + src/login/logind-seat-dbus.h | 17 + src/login/logind-seat.c | 671 + src/login/logind-seat.h | 76 + src/login/logind-session-dbus.c | 842 + src/login/logind-session-dbus.h | 23 + src/login/logind-session-device.c | 523 + src/login/logind-session-device.h | 39 + src/login/logind-session.c | 1432 + src/login/logind-session.h | 176 + src/login/logind-user-dbus.c | 368 + src/login/logind-user-dbus.h | 17 + src/login/logind-user.c | 861 + src/login/logind-user.h | 75 + src/login/logind-utmp.c | 169 + src/login/logind.c | 1244 + src/login/logind.conf.in | 37 + src/login/logind.h | 170 + src/login/meson.build | 122 + src/login/org.freedesktop.login1.conf | 320 + src/login/org.freedesktop.login1.policy | 394 + src/login/org.freedesktop.login1.service | 14 + src/login/pam_systemd.c | 818 + src/login/pam_systemd.sym | 8 + src/login/sysfs-show.c | 165 + src/login/sysfs-show.h | 8 + src/login/systemd-user.m4 | 12 + src/login/test-inhibit.c | 96 + src/login/test-login-shared.c | 22 + src/login/test-login-tables.c | 17 + src/login/user-runtime-dir.c | 199 + src/machine-id-setup/machine-id-setup-main.c | 142 + src/machine/image-dbus.c | 499 + src/machine/image-dbus.h | 21 + src/machine/machine-dbus.c | 1485 + src/machine/machine-dbus.h | 28 + src/machine/machine.c | 772 + src/machine/machine.h | 96 + src/machine/machinectl.c | 3130 + src/machine/machined-core.c | 36 + src/machine/machined-dbus.c | 1497 + src/machine/machined.c | 392 + src/machine/machined.h | 58 + src/machine/meson.build | 42 + src/machine/operation.c | 138 + src/machine/operation.h | 31 + src/machine/org.freedesktop.machine1.conf | 242 + src/machine/org.freedesktop.machine1.policy | 104 + src/machine/org.freedesktop.machine1.service | 14 + src/machine/test-machine-tables.c | 12 + src/modules-load/modules-load.c | 227 + src/mount/mount-tool.c | 1615 + src/network/fuzz-netdev-parser.c | 25 + src/network/fuzz-network-parser.c | 28 + src/network/fuzz-network-parser.options | 2 + src/network/generator/main.c | 207 + src/network/generator/network-generator.c | 1232 + src/network/generator/network-generator.h | 108 + .../generator/test-network-generator.c | 438 + src/network/meson.build | 243 + src/network/netdev/bond.c | 594 + src/network/netdev/bond.h | 160 + src/network/netdev/bridge.c | 361 + src/network/netdev/bridge.h | 46 + src/network/netdev/dummy.c | 10 + src/network/netdev/dummy.h | 11 + src/network/netdev/fou-tunnel.c | 269 + src/network/netdev/fou-tunnel.h | 42 + src/network/netdev/geneve.c | 356 + src/network/netdev/geneve.h | 52 + src/network/netdev/ipvlan.c | 105 + src/network/netdev/ipvlan.h | 46 + src/network/netdev/l2tp-tunnel.c | 731 + src/network/netdev/l2tp-tunnel.h | 78 + src/network/netdev/macsec.c | 1245 + src/network/netdev/macsec.h | 86 + src/network/netdev/macvlan.c | 74 + src/network/netdev/macvlan.h | 31 + src/network/netdev/netdev-gperf.gperf | 225 + src/network/netdev/netdev.c | 852 + src/network/netdev/netdev.h | 212 + src/network/netdev/netdevsim.c | 10 + src/network/netdev/netdevsim.h | 13 + src/network/netdev/nlmon.c | 22 + src/network/netdev/nlmon.h | 14 + src/network/netdev/tunnel.c | 903 + src/network/netdev/tunnel.h | 92 + src/network/netdev/tuntap.c | 164 + src/network/netdev/tuntap.h | 21 + src/network/netdev/vcan.c | 10 + src/network/netdev/vcan.h | 17 + src/network/netdev/veth.c | 94 + src/network/netdev/veth.h | 16 + src/network/netdev/vlan.c | 92 + src/network/netdev/vlan.h | 20 + src/network/netdev/vrf.c | 32 + src/network/netdev/vrf.h | 15 + src/network/netdev/vxcan.c | 74 + src/network/netdev/vxcan.h | 16 + src/network/netdev/vxlan.c | 379 + src/network/netdev/vxlan.h | 73 + src/network/netdev/wireguard.c | 977 + src/network/netdev/wireguard.h | 70 + src/network/netdev/xfrm.c | 33 + src/network/netdev/xfrm.h | 14 + src/network/networkctl.c | 2017 + src/network/networkd-address-label.c | 231 + src/network/networkd-address-label.h | 39 + src/network/networkd-address-pool.c | 157 + src/network/networkd-address-pool.h | 25 + src/network/networkd-address.c | 987 + src/network/networkd-address.h | 70 + src/network/networkd-brvlan.c | 281 + src/network/networkd-brvlan.h | 21 + src/network/networkd-can.c | 231 + src/network/networkd-can.h | 6 + src/network/networkd-conf.c | 211 + src/network/networkd-conf.h | 18 + src/network/networkd-dhcp-common.c | 448 + src/network/networkd-dhcp-common.h | 51 + src/network/networkd-dhcp-server.c | 480 + src/network/networkd-dhcp-server.h | 14 + src/network/networkd-dhcp4.c | 1576 + src/network/networkd-dhcp4.h | 29 + src/network/networkd-dhcp6.c | 838 + src/network/networkd-dhcp6.h | 15 + src/network/networkd-fdb.c | 392 + src/network/networkd-fdb.h | 57 + src/network/networkd-gperf.gperf | 24 + src/network/networkd-ipv4ll.c | 225 + src/network/networkd-ipv4ll.h | 12 + src/network/networkd-ipv6-proxy-ndp.c | 203 + src/network/networkd-ipv6-proxy-ndp.h | 25 + src/network/networkd-link-bus.c | 759 + src/network/networkd-link-bus.h | 34 + src/network/networkd-link.c | 4100 + src/network/networkd-link.h | 221 + src/network/networkd-lldp-rx.c | 198 + src/network/networkd-lldp-rx.h | 26 + src/network/networkd-lldp-tx.c | 416 + src/network/networkd-lldp-tx.h | 22 + src/network/networkd-manager-bus.c | 269 + src/network/networkd-manager-bus.h | 10 + src/network/networkd-manager.c | 2308 + src/network/networkd-manager.h | 104 + src/network/networkd-ndisc.c | 808 + src/network/networkd-ndisc.h | 26 + src/network/networkd-neighbor.c | 506 + src/network/networkd-neighbor.h | 52 + src/network/networkd-network-bus.c | 139 + src/network/networkd-network-bus.h | 11 + src/network/networkd-network-gperf.gperf | 281 + src/network/networkd-network.c | 1330 + src/network/networkd-network.h | 326 + src/network/networkd-nexthop.c | 473 + src/network/networkd-nexthop.h | 50 + src/network/networkd-radv.c | 806 + src/network/networkd-radv.h | 65 + src/network/networkd-route.c | 1517 + src/network/networkd-route.h | 98 + src/network/networkd-routing-policy-rule.c | 1378 + src/network/networkd-routing-policy-rule.h | 81 + src/network/networkd-speed-meter.c | 114 + src/network/networkd-speed-meter.h | 12 + src/network/networkd-util.c | 135 + src/network/networkd-util.h | 64 + src/network/networkd-wifi.c | 61 + src/network/networkd-wifi.h | 8 + src/network/networkd.c | 129 + src/network/networkd.conf | 20 + src/network/org.freedesktop.network1.conf | 27 + src/network/org.freedesktop.network1.policy | 175 + src/network/org.freedesktop.network1.service | 14 + src/network/systemd-networkd.pkla | 4 + src/network/systemd-networkd.rules | 10 + src/network/tc/netem.c | 222 + src/network/tc/netem.h | 27 + src/network/tc/qdisc.c | 210 + src/network/tc/qdisc.h | 32 + src/network/tc/tc-util.c | 63 + src/network/tc/tc-util.h | 8 + src/network/test-network-tables.c | 47 + src/network/test-network.c | 249 + src/network/test-networkd-conf.c | 258 + src/network/test-routing-policy-rule.c | 92 + src/network/wait-online/link.c | 152 + src/network/wait-online/link.h | 30 + src/network/wait-online/manager.c | 359 + src/network/wait-online/manager.h | 42 + src/network/wait-online/wait-online.c | 224 + src/notify/notify.c | 219 + src/nspawn/meson.build | 58 + src/nspawn/nspawn-cgroup.c | 609 + src/nspawn/nspawn-cgroup.h | 14 + src/nspawn/nspawn-def.h | 8 + src/nspawn/nspawn-expose-ports.c | 227 + src/nspawn/nspawn-expose-ports.h | 26 + src/nspawn/nspawn-gperf.gperf | 77 + src/nspawn/nspawn-mount.c | 1298 + src/nspawn/nspawn-mount.h | 62 + src/nspawn/nspawn-network.c | 671 + src/nspawn/nspawn-network.h | 21 + src/nspawn/nspawn-oci.c | 2266 + src/nspawn/nspawn-oci.h | 6 + src/nspawn/nspawn-patch-uid.c | 485 + src/nspawn/nspawn-patch-uid.h | 7 + src/nspawn/nspawn-register.c | 403 + src/nspawn/nspawn-register.h | 14 + src/nspawn/nspawn-seccomp.c | 238 + src/nspawn/nspawn-seccomp.h | 6 + src/nspawn/nspawn-settings.c | 899 + src/nspawn/nspawn-settings.h | 258 + src/nspawn/nspawn-setuid.c | 243 + src/nspawn/nspawn-setuid.h | 5 + src/nspawn/nspawn-stub-pid1.c | 197 + src/nspawn/nspawn-stub-pid1.h | 6 + src/nspawn/nspawn.c | 5171 + src/nspawn/test-nspawn-tables.c | 11 + src/nspawn/test-patch-uid.c | 43 + src/nss-myhostname/nss-myhostname.c | 500 + src/nss-myhostname/nss-myhostname.sym | 19 + src/nss-mymachines/nss-mymachines.c | 778 + src/nss-mymachines/nss-mymachines.sym | 21 + src/nss-resolve/nss-resolve.c | 652 + src/nss-resolve/nss-resolve.sym | 19 + src/nss-systemd/nss-systemd.c | 835 + src/nss-systemd/nss-systemd.sym | 23 + src/partition/growfs.c | 330 + src/partition/makefs.c | 82 + src/path/path.c | 196 + src/portable/meson.build | 29 + src/portable/org.freedesktop.portable1.conf | 117 + src/portable/org.freedesktop.portable1.policy | 43 + .../org.freedesktop.portable1.service | 7 + src/portable/portable.c | 1442 + src/portable/portable.h | 74 + src/portable/portablectl.c | 973 + src/portable/portabled-bus.c | 403 + src/portable/portabled-bus.h | 10 + src/portable/portabled-image-bus.c | 742 + src/portable/portabled-image-bus.h | 41 + src/portable/portabled-image.c | 104 + src/portable/portabled-image.h | 12 + src/portable/portabled-operation.c | 128 + src/portable/portabled-operation.h | 29 + src/portable/portabled.c | 164 + src/portable/portabled.h | 25 + src/portable/profile/default/service.conf | 32 + src/portable/profile/nonetwork/service.conf | 32 + src/portable/profile/strict/service.conf | 31 + src/portable/profile/trusted/service.conf | 7 + src/pstore/meson.build | 10 + src/pstore/pstore.c | 406 + src/pstore/pstore.conf | 16 + src/quotacheck/quotacheck.c | 102 + src/random-seed/random-seed.c | 314 + src/rc-local-generator/rc-local-generator.c | 71 + src/remount-fs/remount-fs.c | 152 + src/reply-password/reply-password.c | 81 + src/resolve/RFCs | 60 + src/resolve/dns-type.c | 316 + src/resolve/dns-type.h | 144 + src/resolve/dns_type-to-name.awk | 11 + src/resolve/generate-dns_type-gperf.py | 24 + src/resolve/generate-dns_type-list.sed | 1 + src/resolve/meson.build | 231 + src/resolve/org.freedesktop.resolve1.conf | 27 + src/resolve/org.freedesktop.resolve1.policy | 142 + src/resolve/org.freedesktop.resolve1.service | 14 + src/resolve/resolv.conf | 18 + src/resolve/resolvconf-compat.c | 275 + src/resolve/resolvconf-compat.h | 4 + src/resolve/resolvectl.c | 3261 + src/resolve/resolvectl.h | 29 + src/resolve/resolved-bus.c | 1969 + src/resolve/resolved-bus.h | 12 + src/resolve/resolved-conf.c | 403 + src/resolve/resolved-conf.h | 36 + src/resolve/resolved-def.h | 24 + src/resolve/resolved-dns-answer.c | 752 + src/resolve/resolved-dns-answer.h | 129 + src/resolve/resolved-dns-cache.c | 1116 + src/resolve/resolved-dns-cache.h | 35 + src/resolve/resolved-dns-dnssec.c | 2310 + src/resolve/resolved-dns-dnssec.h | 83 + src/resolve/resolved-dns-packet.c | 2400 + src/resolve/resolved-dns-packet.h | 302 + src/resolve/resolved-dns-query.c | 1107 + src/resolve/resolved-dns-query.h | 125 + src/resolve/resolved-dns-question.c | 446 + src/resolve/resolved-dns-question.h | 56 + src/resolve/resolved-dns-rr.c | 1820 + src/resolve/resolved-dns-rr.h | 341 + src/resolve/resolved-dns-scope.c | 1461 + src/resolve/resolved-dns-scope.h | 112 + src/resolve/resolved-dns-search-domain.c | 192 + src/resolve/resolved-dns-search-domain.h | 56 + src/resolve/resolved-dns-server.c | 901 + src/resolve/resolved-dns-server.h | 151 + src/resolve/resolved-dns-stream.c | 600 + src/resolve/resolved-dns-stream.h | 100 + src/resolve/resolved-dns-stub.c | 585 + src/resolve/resolved-dns-stub.h | 7 + src/resolve/resolved-dns-synthesize.c | 434 + src/resolve/resolved-dns-synthesize.h | 12 + src/resolve/resolved-dns-transaction.c | 3279 + src/resolve/resolved-dns-transaction.h | 178 + src/resolve/resolved-dns-trust-anchor.c | 782 + src/resolve/resolved-dns-trust-anchor.h | 25 + src/resolve/resolved-dns-zone.c | 704 + src/resolve/resolved-dns-zone.h | 69 + src/resolve/resolved-dnssd-bus.c | 129 + src/resolve/resolved-dnssd-bus.h | 10 + src/resolve/resolved-dnssd-gperf.gperf | 24 + src/resolve/resolved-dnssd.c | 360 + src/resolve/resolved-dnssd.h | 59 + src/resolve/resolved-dnstls-gnutls.c | 230 + src/resolve/resolved-dnstls-gnutls.h | 24 + src/resolve/resolved-dnstls-openssl.c | 383 + src/resolve/resolved-dnstls-openssl.h | 25 + src/resolve/resolved-dnstls.h | 36 + src/resolve/resolved-etc-hosts.c | 381 + src/resolve/resolved-etc-hosts.h | 25 + src/resolve/resolved-gperf.gperf | 29 + src/resolve/resolved-link-bus.c | 787 + src/resolve/resolved-link-bus.h | 22 + src/resolve/resolved-link.c | 1395 + src/resolve/resolved-link.h | 110 + src/resolve/resolved-llmnr.c | 450 + src/resolve/resolved-llmnr.h | 14 + src/resolve/resolved-manager.c | 1552 + src/resolve/resolved-manager.h | 189 + src/resolve/resolved-mdns.c | 482 + src/resolve/resolved-mdns.h | 13 + src/resolve/resolved-resolv-conf.c | 399 + src/resolve/resolved-resolv-conf.h | 8 + src/resolve/resolved.c | 91 + src/resolve/resolved.conf.in | 24 + src/resolve/test-dns-packet.c | 120 + src/resolve/test-dnssec-complex.c | 223 + src/resolve/test-dnssec.c | 514 + src/resolve/test-resolve-tables.c | 54 + src/resolve/test-resolved-etc-hosts.c | 150 + src/resolve/test-resolved-packet.c | 32 + src/rfkill/rfkill.c | 377 + src/run-generator/run-generator.c | 138 + src/run/run.c | 1734 + src/shared/acl-util.c | 408 + src/shared/acl-util.h | 30 + src/shared/acpi-fpdt.c | 147 + src/shared/acpi-fpdt.h | 6 + src/shared/apparmor-util.c | 22 + src/shared/apparmor-util.h | 6 + src/shared/ask-password-api.c | 1011 + src/shared/ask-password-api.h | 21 + src/shared/barrier.c | 394 + src/shared/barrier.h | 74 + src/shared/base-filesystem.c | 124 + src/shared/base-filesystem.h | 6 + src/shared/bitmap.c | 212 + src/shared/bitmap.h | 35 + src/shared/blkid-util.h | 10 + src/shared/boot-timestamps.c | 46 + src/shared/boot-timestamps.h | 6 + src/shared/bootspec.c | 1431 + src/shared/bootspec.h | 88 + src/shared/bpf-program.c | 256 + src/shared/bpf-program.h | 43 + src/shared/bus-polkit.c | 416 + src/shared/bus-polkit.h | 11 + src/shared/bus-unit-procs.c | 410 + src/shared/bus-unit-procs.h | 8 + src/shared/bus-unit-util.c | 2045 + src/shared/bus-unit-util.h | 30 + src/shared/bus-util.c | 1412 + src/shared/bus-util.h | 181 + src/shared/bus-wait-for-jobs.c | 337 + src/shared/bus-wait-for-jobs.h | 15 + src/shared/bus-wait-for-units.c | 433 + src/shared/bus-wait-for-units.h | 35 + src/shared/calendarspec.c | 1380 + src/shared/calendarspec.h | 46 + src/shared/cgroup-setup.c | 859 + src/shared/cgroup-setup.h | 34 + src/shared/cgroup-show.c | 400 + src/shared/cgroup-show.h | 24 + src/shared/clean-ipc.c | 451 + src/shared/clean-ipc.h | 17 + src/shared/clock-util.c | 157 + src/shared/clock-util.h | 11 + src/shared/condition.c | 905 + src/shared/condition.h | 103 + src/shared/conf-parser.c | 1117 + src/shared/conf-parser.h | 291 + src/shared/cpu-set-util.c | 382 + src/shared/cpu-set-util.h | 78 + src/shared/crypt-util.c | 28 + src/shared/crypt-util.h | 12 + src/shared/daemon-util.h | 22 + src/shared/dev-setup.c | 115 + src/shared/dev-setup.h | 8 + src/shared/dissect-image.c | 1523 + src/shared/dissect-image.h | 97 + src/shared/dm-util.c | 41 + src/shared/dm-util.h | 4 + src/shared/dns-domain.c | 1374 + src/shared/dns-domain.h | 112 + src/shared/dropin.c | 275 + src/shared/dropin.h | 25 + src/shared/efi-loader.c | 699 + src/shared/efi-loader.h | 84 + src/shared/enable-mempool.c | 5 + src/shared/env-file-label.c | 21 + src/shared/env-file-label.h | 8 + src/shared/ethtool-util.c | 948 + src/shared/ethtool-util.h | 120 + src/shared/exec-util.c | 446 + src/shared/exec-util.h | 47 + src/shared/exit-status.c | 176 + src/shared/exit-status.h | 110 + src/shared/fdset.c | 254 + src/shared/fdset.h | 42 + src/shared/fileio-label.c | 37 + src/shared/fileio-label.h | 15 + src/shared/firewall-util.c | 350 + src/shared/firewall-util.h | 65 + src/shared/format-table.c | 2090 + src/shared/format-table.h | 119 + src/shared/fsck-util.h | 14 + src/shared/fstab-util.c | 262 + src/shared/fstab-util.h | 37 + src/shared/generate-ip-protocol-list.sh | 6 + src/shared/generator.c | 525 + src/shared/generator.h | 69 + src/shared/gpt.h | 65 + src/shared/id128-print.c | 72 + src/shared/id128-print.h | 18 + src/shared/ima-util.c | 15 + src/shared/ima-util.h | 6 + src/shared/import-util.c | 165 + src/shared/import-util.h | 25 + src/shared/initreq.h | 73 + src/shared/install-printf.c | 147 + src/shared/install-printf.h | 6 + src/shared/install.c | 3367 + src/shared/install.h | 200 + src/shared/ip-protocol-list.c | 67 + src/shared/ip-protocol-list.h | 6 + src/shared/ip-protocol-to-name.awk | 9 + src/shared/journal-importer.c | 473 + src/shared/journal-importer.h | 59 + src/shared/journal-util.c | 174 + src/shared/journal-util.h | 11 + src/shared/json-internal.h | 63 + src/shared/json.c | 3463 + src/shared/json.h | 288 + src/shared/libmount-util.h | 47 + src/shared/libshared.sym | 3 + src/shared/linux/README | 8 + src/shared/linux/auto_dev-ioctl.h | 220 + src/shared/linux/bpf.h | 3057 + src/shared/linux/bpf_common.h | 57 + src/shared/linux/bpf_insn.h | 225 + src/shared/linux/dm-ioctl.h | 363 + src/shared/linux/ethtool.h | 1871 + src/shared/linux/nl80211.h | 6552 + src/shared/local-addresses.c | 260 + src/shared/local-addresses.h | 17 + src/shared/lockfile-util.c | 137 + src/shared/lockfile-util.h | 14 + src/shared/log-link.h | 37 + src/shared/logs-show.c | 1501 + src/shared/logs-show.h | 63 + src/shared/loop-util.c | 158 + src/shared/loop-util.h | 23 + src/shared/machine-image.c | 1273 + src/shared/machine-image.h | 112 + src/shared/machine-pool.c | 45 + src/shared/machine-pool.h | 8 + src/shared/main-func.h | 36 + src/shared/meson.build | 308 + src/shared/module-util.c | 72 + src/shared/module-util.h | 12 + src/shared/mount-util.c | 559 + src/shared/mount-util.h | 34 + src/shared/nscd-flush.c | 151 + src/shared/nscd-flush.h | 4 + src/shared/nsflags.c | 77 + src/shared/nsflags.h | 29 + src/shared/os-util.c | 119 + src/shared/os-util.h | 12 + src/shared/output-mode.c | 42 + src/shared/output-mode.h | 50 + src/shared/pager.c | 293 + src/shared/pager.h | 17 + src/shared/path-lookup.c | 839 + src/shared/path-lookup.h | 74 + src/shared/pe-header.h | 59 + src/shared/pretty-print.c | 319 + src/shared/pretty-print.h | 17 + src/shared/ptyfwd.c | 631 + src/shared/ptyfwd.h | 42 + src/shared/reboot-util.c | 110 + src/shared/reboot-util.h | 15 + src/shared/resolve-util.c | 52 + src/shared/resolve-util.h | 83 + src/shared/seccomp-util.c | 2062 + src/shared/seccomp-util.h | 110 + src/shared/securebits-util.c | 66 + src/shared/securebits-util.h | 18 + src/shared/serialize.c | 215 + src/shared/serialize.h | 27 + src/shared/sleep-config.c | 638 + src/shared/sleep-config.h | 59 + src/shared/spawn-ask-password-agent.c | 61 + src/shared/spawn-ask-password-agent.h | 11 + src/shared/spawn-polkit-agent.c | 98 + src/shared/spawn-polkit-agent.h | 11 + src/shared/specifier.c | 299 + src/shared/specifier.h | 37 + src/shared/switch-root.c | 127 + src/shared/switch-root.h | 6 + src/shared/sysctl-util.c | 129 + src/shared/sysctl-util.h | 30 + src/shared/test-tables.h | 44 + src/shared/tests.c | 202 + src/shared/tests.h | 41 + src/shared/tmpfile-util-label.c | 26 + src/shared/tmpfile-util-label.h | 10 + src/shared/tomoyo-util.c | 15 + src/shared/tomoyo-util.h | 6 + src/shared/udev-util.c | 218 + src/shared/udev-util.h | 32 + src/shared/uid-range.c | 186 + src/shared/uid-range.h | 15 + src/shared/unit-file.c | 559 + src/shared/unit-file.h | 58 + src/shared/utmp-wtmp.c | 424 + src/shared/utmp-wtmp.h | 56 + src/shared/varlink.c | 2459 + src/shared/varlink.h | 166 + src/shared/verbs.c | 121 + src/shared/verbs.h | 22 + src/shared/vlan-util.c | 98 + src/shared/vlan-util.h | 21 + src/shared/volatile-util.c | 46 + src/shared/volatile-util.h | 16 + src/shared/watchdog.c | 163 + src/shared/watchdog.h | 16 + src/shared/web-util.c | 53 + src/shared/web-util.h | 12 + src/shared/wifi-util.c | 101 + src/shared/wifi-util.h | 10 + src/shared/xml.c | 237 + src/shared/xml.h | 14 + src/shutdown/meson.build | 5 + src/shutdown/shutdown.c | 590 + src/shutdown/umount.c | 691 + src/shutdown/umount.h | 30 + src/sleep/sleep.c | 352 + src/sleep/sleep.conf | 25 + src/socket-proxy/socket-proxyd.c | 664 + src/stdio-bridge/stdio-bridge.c | 257 + src/sulogin-shell/sulogin-shell.c | 122 + src/sysctl/sysctl.c | 368 + .../system-update-generator.c | 72 + src/systemctl/systemctl.c | 9510 + src/systemctl/systemd-sysv-install.SKELETON | 49 + src/systemctl/sysv-compat.c | 102 + src/systemctl/sysv-compat.h | 33 + src/systemd/_sd-common.h | 90 + src/systemd/meson.build | 79 + src/systemd/sd-bus-protocol.h | 99 + src/systemd/sd-bus-vtable.h | 191 + src/systemd/sd-bus.h | 512 + src/systemd/sd-daemon.h | 320 + src/systemd/sd-device.h | 124 + src/systemd/sd-dhcp-client.h | 207 + src/systemd/sd-dhcp-lease.h | 67 + src/systemd/sd-dhcp-option.h | 38 + src/systemd/sd-dhcp-server.h | 66 + src/systemd/sd-dhcp6-client.h | 158 + src/systemd/sd-dhcp6-lease.h | 55 + src/systemd/sd-event.h | 157 + src/systemd/sd-hwdb.h | 45 + src/systemd/sd-id128.h | 124 + src/systemd/sd-ipv4acd.h | 58 + src/systemd/sd-ipv4ll.h | 60 + src/systemd/sd-journal.h | 172 + src/systemd/sd-lldp.h | 190 + src/systemd/sd-login.h | 242 + src/systemd/sd-messages.h | 163 + src/systemd/sd-ndisc.h | 131 + src/systemd/sd-netlink.h | 234 + src/systemd/sd-network.h | 203 + src/systemd/sd-path.h | 89 + src/systemd/sd-radv.h | 98 + src/systemd/sd-resolve.h | 124 + src/systemd/sd-utf8.h | 29 + src/sysusers/sysusers.c | 1943 + src/sysv-generator/sysv-generator.c | 956 + src/test/generate-sym-test.py | 27 + src/test/meson.build | 1131 + src/test/test-acl-util.c | 68 + src/test/test-af-list.c | 33 + src/test/test-alloc-util.c | 161 + src/test/test-architecture.c | 52 + src/test/test-arphrd-list.c | 29 + src/test/test-ask-password-api.c | 24 + src/test/test-async.c | 39 + src/test/test-barrier.c | 464 + src/test/test-bitmap.c | 117 + src/test/test-boot-timestamps.c | 92 + src/test/test-bpf-devices.c | 306 + src/test/test-bpf-firewall.c | 199 + src/test/test-btrfs.c | 181 + src/test/test-bus-util.c | 55 + src/test/test-calendarspec.c | 252 + src/test/test-cap-list.c | 124 + src/test/test-capability.c | 265 + src/test/test-cgroup-cpu.c | 38 + src/test/test-cgroup-mask.c | 156 + src/test/test-cgroup-setup.c | 67 + src/test/test-cgroup-unit-default.c | 144 + src/test/test-cgroup-util.c | 434 + src/test/test-cgroup.c | 87 + src/test/test-chase-symlinks.c | 117 + src/test/test-chown-rec.c | 161 + src/test/test-clock.c | 78 + src/test/test-condition.c | 842 + src/test/test-conf-files.c | 157 + src/test/test-conf-parser.c | 395 + src/test/test-copy.c | 297 + src/test/test-cpu-set-util.c | 290 + src/test/test-daemon.c | 57 + src/test/test-date.c | 110 + src/test/test-dev-setup.c | 62 + src/test/test-device-nodes.c | 40 + src/test/test-dissect-image.c | 50 + src/test/test-dlopen.c | 15 + src/test/test-dns-domain.c | 815 + src/test/test-ellipsize.c | 127 + src/test/test-emergency-action.c | 51 + src/test/test-engine.c | 155 + src/test/test-env-file.c | 143 + src/test/test-env-util.c | 323 + src/test/test-escape.c | 169 + src/test/test-exec-util.c | 461 + src/test/test-execute.c | 926 + src/test/test-exit-status.c | 52 + src/test/test-extract-word.c | 562 + src/test/test-fd-util.c | 335 + src/test/test-fdset.c | 204 + src/test/test-fileio.c | 870 + src/test/test-firewall-util.c | 42 + src/test/test-format-table.c | 177 + src/test/test-format-util.c | 39 + src/test/test-fs-util.c | 814 + src/test/test-fstab-util.c | 162 + src/test/test-gcrypt-util.c | 32 + src/test/test-glob-util.c | 102 + src/test/test-hash.c | 76 + src/test/test-hashmap-ordered.awk | 11 + src/test/test-hashmap-plain.c | 1099 + src/test/test-hashmap.c | 132 + src/test/test-hexdecoct.c | 355 + src/test/test-hostname-util.c | 152 + src/test/test-hostname.c | 14 + src/test/test-id128.c | 161 + src/test/test-in-addr-util.c | 186 + src/test/test-install-root.c | 1084 + src/test/test-install.c | 273 + src/test/test-io-util.c | 52 + src/test/test-ip-protocol-list.c | 64 + src/test/test-ipcrm.c | 25 + src/test/test-job-type.c | 81 + src/test/test-journal-importer.c | 78 + src/test/test-json.c | 471 + src/test/test-libmount.c | 115 + src/test/test-libudev.c | 584 + src/test/test-list.c | 207 + src/test/test-load-fragment.c | 798 + src/test/test-local-addresses.c | 44 + src/test/test-locale-util.c | 106 + src/test/test-log.c | 94 + src/test/test-loopback.c | 20 + src/test/test-mount-util.c | 70 + src/test/test-mountpoint-util.c | 274 + src/test/test-namespace.c | 200 + src/test/test-netlink-manual.c | 127 + src/test/test-ns.c | 94 + src/test/test-nscd-flush.c | 20 + src/test/test-nss.c | 521 + src/test/test-ordered-set.c | 121 + src/test/test-os-util.c | 21 + src/test/test-parse-util.c | 853 + src/test/test-path-lookup.c | 94 + src/test/test-path-util.c | 691 + src/test/test-path.c | 272 + src/test/test-pretty-print.c | 43 + src/test/test-prioq.c | 128 + src/test/test-proc-cmdline.c | 265 + src/test/test-process-util.c | 632 + src/test/test-procfs-util.c | 47 + src/test/test-random-util.c | 67 + src/test/test-ratelimit.c | 29 + src/test/test-replace-var.c | 27 + src/test/test-rlimit-util.c | 134 + src/test/test-sched-prio.c | 78 + src/test/test-sd-hwdb.c | 74 + src/test/test-seccomp.c | 1040 + src/test/test-selinux.c | 105 + src/test/test-serialize.c | 208 + src/test/test-set-disable-mempool.c | 53 + src/test/test-set.c | 96 + src/test/test-sigbus.c | 61 + src/test/test-signal-util.c | 150 + src/test/test-siphash24.c | 107 + src/test/test-sizeof.c | 79 + src/test/test-sleep.c | 129 + src/test/test-socket-util.c | 909 + src/test/test-specifier.c | 49 + src/test/test-stat-util.c | 167 + src/test/test-static-destruct.c | 34 + src/test/test-strbuf.c | 75 + src/test/test-string-util.c | 576 + src/test/test-strip-tab-ansi.c | 72 + src/test/test-strv.c | 1004 + src/test/test-strxcpyx.c | 109 + src/test/test-sysctl-util.c | 44 + src/test/test-systemd-tmpfiles.py | 143 + src/test/test-tables.c | 126 + src/test/test-terminal-util.c | 119 + src/test/test-time-util.c | 524 + src/test/test-tmpfiles.c | 66 + src/test/test-udev.c | 131 + src/test/test-uid-range.c | 74 + src/test/test-umask-util.c | 41 + src/test/test-umount.c | 65 + src/test/test-unaligned.c | 172 + src/test/test-unit-file.c | 104 + src/test/test-unit-name.c | 901 + src/test/test-user-util.c | 335 + src/test/test-utf8.c | 233 + src/test/test-util.c | 421 + src/test/test-varlink.c | 239 + src/test/test-verbs.c | 63 + src/test/test-watch-pid.c | 87 + src/test/test-watchdog.c | 40 + src/test/test-web-util.c | 24 + src/test/test-xattr-util.c | 88 + src/test/test-xml.c | 66 + src/time-wait-sync/time-wait-sync.c | 250 + src/timedate/meson.build | 10 + src/timedate/org.freedesktop.timedate1.conf | 29 + src/timedate/org.freedesktop.timedate1.policy | 62 + .../org.freedesktop.timedate1.service | 14 + src/timedate/timedatectl.c | 989 + src/timedate/timedated.c | 1132 + src/timesync/80-systemd-timesync.list | 1 + src/timesync/meson.build | 53 + src/timesync/org.freedesktop.timesync1.conf | 42 + .../org.freedesktop.timesync1.service | 14 + src/timesync/test-timesync.c | 34 + src/timesync/timesyncd-bus.c | 201 + src/timesync/timesyncd-bus.h | 6 + src/timesync/timesyncd-conf.c | 124 + src/timesync/timesyncd-conf.h | 14 + src/timesync/timesyncd-gperf.gperf | 25 + src/timesync/timesyncd-manager.c | 1122 + src/timesync/timesyncd-manager.h | 109 + src/timesync/timesyncd-ntp-message.h | 45 + src/timesync/timesyncd-server.c | 130 + src/timesync/timesyncd-server.h | 47 + src/timesync/timesyncd.c | 178 + src/timesync/timesyncd.conf.in | 19 + src/tmpfiles/tmpfiles.c | 3278 + .../tty-ask-password-agent.c | 711 + src/udev/.vimrc | 4 + src/udev/ata_id/ata_id.c | 653 + src/udev/cdrom_id/cdrom_id.c | 1018 + src/udev/fido_id/fido_id.c | 96 + src/udev/fido_id/fido_id_desc.c | 92 + src/udev/fido_id/fido_id_desc.h | 8 + src/udev/fido_id/fuzz-fido-id-desc.c | 23 + src/udev/fido_id/test-fido-id-desc.c | 85 + src/udev/generate-keyboard-keys-gperf.sh | 18 + src/udev/generate-keyboard-keys-list.sh | 7 + src/udev/meson.build | 224 + src/udev/mtd_probe/mtd_probe.c | 59 + src/udev/mtd_probe/mtd_probe.h | 52 + src/udev/mtd_probe/probe_smartmedia.c | 97 + src/udev/net/fuzz-link-parser.c | 28 + src/udev/net/fuzz-link-parser.options | 2 + src/udev/net/link-config-gperf.gperf | 57 + src/udev/net/link-config.c | 506 + src/udev/net/link-config.h | 88 + src/udev/net/naming-scheme.c | 66 + src/udev/net/naming-scheme.h | 53 + src/udev/scsi_id/README | 4 + src/udev/scsi_id/scsi.h | 100 + src/udev/scsi_id/scsi_id.c | 596 + src/udev/scsi_id/scsi_id.h | 63 + src/udev/scsi_id/scsi_serial.c | 893 + src/udev/udev-builtin-blkid.c | 317 + src/udev/udev-builtin-btrfs.c | 40 + src/udev/udev-builtin-hwdb.c | 218 + src/udev/udev-builtin-input_id.c | 362 + src/udev/udev-builtin-keyboard.c | 256 + src/udev/udev-builtin-kmod.c | 76 + src/udev/udev-builtin-net_id.c | 932 + src/udev/udev-builtin-net_setup_link.c | 85 + src/udev/udev-builtin-path_id.c | 682 + src/udev/udev-builtin-uaccess.c | 80 + src/udev/udev-builtin-usb_id.c | 462 + src/udev/udev-builtin.c | 144 + src/udev/udev-builtin.h | 71 + src/udev/udev-ctrl.c | 407 + src/udev/udev-ctrl.h | 79 + src/udev/udev-event.c | 1023 + src/udev/udev-event.h | 67 + src/udev/udev-node.c | 468 + src/udev/udev-node.h | 15 + src/udev/udev-rules.c | 2393 + src/udev/udev-rules.h | 27 + src/udev/udev-watch.c | 177 + src/udev/udev-watch.h | 10 + src/udev/udev.conf | 10 + src/udev/udev.pc.in | 5 + src/udev/udevadm-control.c | 185 + src/udev/udevadm-hwdb.c | 101 + src/udev/udevadm-info.c | 490 + src/udev/udevadm-monitor.c | 266 + src/udev/udevadm-settle.c | 211 + src/udev/udevadm-test-builtin.c | 97 + src/udev/udevadm-test.c | 162 + src/udev/udevadm-trigger.c | 391 + src/udev/udevadm-util.c | 49 + src/udev/udevadm-util.h | 6 + src/udev/udevadm.c | 127 + src/udev/udevadm.h | 22 + src/udev/udevd.c | 1819 + src/udev/v4l_id/v4l_id.c | 93 + src/update-done/update-done.c | 61 + src/update-utmp/update-utmp.c | 259 + src/user-sessions/user-sessions.c | 43 + src/vconsole/90-vconsole.rules.in | 12 + src/vconsole/meson.build | 10 + src/vconsole/vconsole-setup.c | 479 + src/veritysetup/veritysetup-generator.c | 230 + src/veritysetup/veritysetup.c | 116 + src/version/version.h.in | 1 + src/volatile-root/volatile-root.c | 197 + sysctl.d/50-coredump.conf.in | 12 + sysctl.d/50-default.conf | 50 + sysctl.d/50-pid-max.conf | 16 + sysctl.d/meson.build | 30 + sysusers.d/basic.conf.in | 38 + sysusers.d/meson.build | 33 + sysusers.d/systemd-remote.conf.m4 | 10 + sysusers.d/systemd.conf.m4 | 20 + test/.gitignore | 5 + test/README.testsuite | 122 + test/TEST-01-BASIC/Makefile | 9 + test/TEST-01-BASIC/test.sh | 34 + test/TEST-02-CRYPTSETUP/Makefile | 1 + test/TEST-02-CRYPTSETUP/test.sh | 89 + test/TEST-03-JOBS/Makefile | 1 + test/TEST-03-JOBS/test-jobs.sh | 97 + test/TEST-03-JOBS/test.sh | 40 + test/TEST-04-JOURNAL/Makefile | 1 + test/TEST-04-JOURNAL/test-journal.sh | 109 + test/TEST-04-JOURNAL/test.sh | 44 + test/TEST-05-RLIMITS/Makefile | 1 + test/TEST-05-RLIMITS/test-rlimits.sh | 15 + test/TEST-05-RLIMITS/test.sh | 40 + test/TEST-06-SELINUX/Makefile | 1 + test/TEST-06-SELINUX/systemd_test.if | 8 + test/TEST-06-SELINUX/systemd_test.te | 50 + test/TEST-06-SELINUX/test-selinux-checks.sh | 11 + test/TEST-06-SELINUX/test.sh | 97 + test/TEST-07-ISSUE-1981/Makefile | 1 + test/TEST-07-ISSUE-1981/test-segfault.sh | 35 + test/TEST-07-ISSUE-1981/test.sh | 38 + test/TEST-08-ISSUE-2730/Makefile | 1 + test/TEST-08-ISSUE-2730/test.sh | 70 + test/TEST-09-ISSUE-2691/Makefile | 1 + test/TEST-09-ISSUE-2691/test.sh | 37 + test/TEST-10-ISSUE-2467/Makefile | 1 + test/TEST-10-ISSUE-2467/test.sh | 48 + test/TEST-11-ISSUE-3166/Makefile | 1 + test/TEST-11-ISSUE-3166/test.sh | 61 + test/TEST-12-ISSUE-3171/Makefile | 1 + test/TEST-12-ISSUE-3171/test.sh | 89 + test/TEST-13-NSPAWN-SMOKE/Makefile | 10 + .../create-busybox-container | 53 + test/TEST-13-NSPAWN-SMOKE/test.sh | 192 + test/TEST-14-MACHINE-ID/Makefile | 1 + test/TEST-14-MACHINE-ID/test.sh | 78 + test/TEST-15-DROPIN/Makefile | 1 + test/TEST-15-DROPIN/test-dropin.sh | 441 + test/TEST-15-DROPIN/test.sh | 22 + test/TEST-15-DROPIN/testsuite.service | 6 + test/TEST-16-EXTEND-TIMEOUT/Makefile | 1 + test/TEST-16-EXTEND-TIMEOUT/assess.sh | 55 + .../extend_timeout_test_service.sh | 70 + test/TEST-16-EXTEND-TIMEOUT/test.sh | 35 + .../testsuite-fail-runtime.service | 13 + .../testsuite-fail-start.service | 13 + .../testsuite-fail-stop.service | 16 + .../testsuite-success-all.service | 14 + .../testsuite-success-runtime.service | 13 + .../testsuite-success-start.service | 13 + .../testsuite-success-stop.service | 13 + test/TEST-16-EXTEND-TIMEOUT/testsuite.service | 18 + test/TEST-17-UDEV-WANTS/Makefile | 1 + test/TEST-17-UDEV-WANTS/test.sh | 34 + test/TEST-17-UDEV-WANTS/testsuite.sh | 74 + test/TEST-18-FAILUREACTION/Makefile | 1 + test/TEST-18-FAILUREACTION/test.sh | 35 + test/TEST-18-FAILUREACTION/testsuite.sh | 16 + test/TEST-19-DELEGATE/Makefile | 1 + test/TEST-19-DELEGATE/test.sh | 35 + test/TEST-19-DELEGATE/testsuite.sh | 39 + test/TEST-20-MAINPIDGAMES/Makefile | 1 + test/TEST-20-MAINPIDGAMES/test.sh | 37 + test/TEST-20-MAINPIDGAMES/testsuite.sh | 139 + test/TEST-21-SYSUSERS/Makefile | 1 + test/TEST-21-SYSUSERS/inline.expected-group | 2 + test/TEST-21-SYSUSERS/inline.expected-passwd | 1 + test/TEST-21-SYSUSERS/test-1.expected-group | 2 + test/TEST-21-SYSUSERS/test-1.expected-passwd | 1 + test/TEST-21-SYSUSERS/test-1.input | 5 + test/TEST-21-SYSUSERS/test-10.expected-group | 2 + test/TEST-21-SYSUSERS/test-10.expected-passwd | 2 + test/TEST-21-SYSUSERS/test-10.input | 5 + test/TEST-21-SYSUSERS/test-11.expected-group | 6 + test/TEST-21-SYSUSERS/test-11.expected-passwd | 6 + test/TEST-21-SYSUSERS/test-11.initial-group | 4 + test/TEST-21-SYSUSERS/test-11.initial-passwd | 5 + test/TEST-21-SYSUSERS/test-11.input | 3 + test/TEST-21-SYSUSERS/test-12.expected-group | 2 + test/TEST-21-SYSUSERS/test-12.expected-passwd | 2 + test/TEST-21-SYSUSERS/test-12.initial-group | 1 + test/TEST-21-SYSUSERS/test-12.initial-passwd | 1 + test/TEST-21-SYSUSERS/test-12.input | 1 + test/TEST-21-SYSUSERS/test-2.expected-group | 4 + test/TEST-21-SYSUSERS/test-2.expected-passwd | 4 + test/TEST-21-SYSUSERS/test-2.input | 8 + test/TEST-21-SYSUSERS/test-3.expected-group | 4 + test/TEST-21-SYSUSERS/test-3.expected-passwd | 4 + test/TEST-21-SYSUSERS/test-3.input | 10 + test/TEST-21-SYSUSERS/test-4.expected-group | 1 + test/TEST-21-SYSUSERS/test-4.expected-passwd | 2 + test/TEST-21-SYSUSERS/test-4.input | 6 + test/TEST-21-SYSUSERS/test-5.expected-group | 39 + test/TEST-21-SYSUSERS/test-5.expected-passwd | 18 + test/TEST-21-SYSUSERS/test-5.input | 47 + test/TEST-21-SYSUSERS/test-6.expected-group | 2 + test/TEST-21-SYSUSERS/test-6.expected-passwd | 1 + test/TEST-21-SYSUSERS/test-6.input | 7 + test/TEST-21-SYSUSERS/test-7.expected-group | 16 + test/TEST-21-SYSUSERS/test-7.expected-passwd | 5 + test/TEST-21-SYSUSERS/test-7.input | 26 + test/TEST-21-SYSUSERS/test-8.expected-group | 1 + test/TEST-21-SYSUSERS/test-8.expected-passwd | 1 + test/TEST-21-SYSUSERS/test-8.input | 2 + test/TEST-21-SYSUSERS/test-9.expected-group | 1 + test/TEST-21-SYSUSERS/test-9.expected-passwd | 2 + test/TEST-21-SYSUSERS/test-9.input | 2 + test/TEST-21-SYSUSERS/test.sh | 127 + test/TEST-21-SYSUSERS/unhappy-1.expected-err | 1 + test/TEST-21-SYSUSERS/unhappy-1.input | 4 + test/TEST-21-SYSUSERS/unhappy-2.expected-err | 1 + test/TEST-21-SYSUSERS/unhappy-2.input | 4 + test/TEST-22-TMPFILES/Makefile | 1 + test/TEST-22-TMPFILES/run-tmpfiles-tests.sh | 13 + test/TEST-22-TMPFILES/test-01.sh | 13 + test/TEST-22-TMPFILES/test-02.sh | 122 + test/TEST-22-TMPFILES/test-03.sh | 236 + test/TEST-22-TMPFILES/test-04.sh | 44 + test/TEST-22-TMPFILES/test-05.sh | 45 + test/TEST-22-TMPFILES/test-06.sh | 38 + test/TEST-22-TMPFILES/test-07.sh | 31 + test/TEST-22-TMPFILES/test-08.sh | 32 + test/TEST-22-TMPFILES/test-09.sh | 59 + test/TEST-22-TMPFILES/test.sh | 31 + test/TEST-22-TMPFILES/testsuite.service | 12 + test/TEST-23-TYPE-EXEC/Makefile | 1 + test/TEST-23-TYPE-EXEC/test.sh | 33 + test/TEST-23-TYPE-EXEC/testsuite.sh | 34 + test/TEST-24-UNIT-TESTS/Makefile | 1 + .../blacklist-ubuntu-ci-ppc64el | 0 test/TEST-24-UNIT-TESTS/test.sh | 101 + test/TEST-24-UNIT-TESTS/testsuite.sh | 85 + test/TEST-25-IMPORT/Makefile | 1 + test/TEST-25-IMPORT/blacklist-ubuntu-ci | 0 test/TEST-25-IMPORT/test.sh | 33 + test/TEST-25-IMPORT/testsuite.sh | 138 + test/TEST-26-SETENV/Makefile | 1 + test/TEST-26-SETENV/test.sh | 32 + test/TEST-26-SETENV/testsuite.sh | 31 + test/TEST-27-STDOUTFILE/Makefile | 1 + test/TEST-27-STDOUTFILE/test.sh | 34 + test/TEST-27-STDOUTFILE/testsuite.sh | 50 + test/TEST-28-PERCENTJ-WANTEDBY/Makefile | 1 + test/TEST-28-PERCENTJ-WANTEDBY/test.sh | 56 + test/TEST-29-UDEV-ID_RENAMING/Makefile | 1 + test/TEST-29-UDEV-ID_RENAMING/test.sh | 34 + test/TEST-29-UDEV-ID_RENAMING/testsuite.sh | 43 + test/TEST-30-ONCLOCKCHANGE/Makefile | 1 + .../blacklist-ubuntu-ci-i386 | 0 test/TEST-30-ONCLOCKCHANGE/test.sh | 43 + test/TEST-30-ONCLOCKCHANGE/testsuite.sh | 31 + test/TEST-31-DEVICE-ENUMERATION/Makefile | 1 + test/TEST-31-DEVICE-ENUMERATION/test.sh | 34 + test/TEST-31-DEVICE-ENUMERATION/testsuite.sh | 10 + test/TEST-32-OOMPOLICY/Makefile | 1 + test/TEST-32-OOMPOLICY/test.sh | 36 + test/TEST-32-OOMPOLICY/testsuite.sh | 37 + test/TEST-33-CLEAN-UNIT/Makefile | 1 + test/TEST-33-CLEAN-UNIT/test.sh | 35 + test/TEST-33-CLEAN-UNIT/testsuite.sh | 319 + test/TEST-34-DYNAMICUSERMIGRATE/Makefile | 1 + test/TEST-34-DYNAMICUSERMIGRATE/test.sh | 33 + test/TEST-34-DYNAMICUSERMIGRATE/testsuite.sh | 46 + test/TEST-35-NETWORK-GENERATOR/Makefile | 1 + .../test-01-dhcp.expected/91-default.network | 11 + .../test-01-dhcp.input | 1 + .../90-bridge99.netdev | 5 + .../90-bridge99.network | 13 + .../test-02-bridge.expected/90-eth0.network | 21 + .../test-02-bridge.expected/90-eth1.network | 21 + .../test-02-bridge.input | 4 + test/TEST-35-NETWORK-GENERATOR/test.sh | 36 + test/TEST-36-NUMAPOLICY/Makefile | 1 + .../blacklist-ubuntu-ci-s390x | 0 test/TEST-36-NUMAPOLICY/test.sh | 37 + test/TEST-36-NUMAPOLICY/testsuite.sh | 323 + .../TEST-37-RUNTIMEDIRECTORYPRESERVE/Makefile | 1 + test/TEST-37-RUNTIMEDIRECTORYPRESERVE/test.sh | 35 + .../testsuite.sh | 19 + test/TEST-39-EXECRELOAD/Makefile | 1 + test/TEST-39-EXECRELOAD/test.sh | 35 + test/TEST-39-EXECRELOAD/testsuite.sh | 64 + test/TEST-40-EXEC-COMMAND-EX/Makefile | 9 + .../blacklist-ubuntu-ci-arm64 | 0 test/TEST-40-EXEC-COMMAND-EX/test.sh | 33 + test/TEST-40-EXEC-COMMAND-EX/testsuite.sh | 46 + test/TEST-41-ONESHOT-RESTART/Makefile | 9 + test/TEST-41-ONESHOT-RESTART/test.sh | 32 + test/TEST-41-ONESHOT-RESTART/testsuite.sh | 49 + test/TEST-42-EXECSTOPPOST/Makefile | 9 + test/TEST-42-EXECSTOPPOST/test.sh | 49 + test/TEST-42-EXECSTOPPOST/testsuite.sh | 89 + test/a-conj.service | 8 + test/a.service | 7 + test/b.service | 6 + test/basic.target | 1 + test/c.service | 6 + test/create-sys-script.py | 179 + test/d.service | 8 + test/daughter.service | 8 + test/dml-discard-empty.service | 7 + test/dml-discard-set-ml.service | 8 + test/dml-discard.slice | 5 + test/dml-override-empty.service | 7 + test/dml-override.slice | 5 + test/dml-passthrough-empty.service | 7 + test/dml-passthrough-set-dml.service | 8 + test/dml-passthrough-set-ml.service | 8 + test/dml-passthrough.slice | 5 + test/dml.slice | 5 + test/e.service | 8 + test/end.service | 10 + test/f.service | 5 + test/fuzz/.gitattributes | 1 + ...h-26bba7182dedc8848939931d9fcefcb7922f2e56 | Bin 0 -> 157 bytes ...h-29ed3c202e0ffade3cad42c8bbeb6cc68a21eb8e | Bin 0 -> 51 bytes ...h-32bf69483cbd4f2e6d46c25a2f92a472109aee45 | Bin 0 -> 89 bytes ...h-37449529b1ad867f0c2671fa80aca5d7812a2b70 | Bin 0 -> 534 bytes ...h-4162a61a79e4c5a832ca5232212f75fa560a1f75 | Bin 0 -> 534 bytes ...h-4f0211eb269e28db941961061494bfdbf3345e54 | Bin 0 -> 143 bytes ...h-603dfd98252375ac7dbced53c2ec312671939a36 | Bin 0 -> 40 bytes ...h-b88ad9ecf4aacf4a0caca5b5543953265367f084 | Bin 0 -> 32 bytes ...h-c1b37b4729b42c0c05b23cba4eed5d8102498a1e | Bin 0 -> 93 bytes ...h-d8f3941c74219b4c03532c9b244d5ea539c61af5 | Bin 0 -> 41 bytes ...h-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 | Bin 0 -> 28 bytes ...k-c09c0e2256d43bc5e2d02748c8d8760e7bc25d20 | Bin 0 -> 534 bytes test/fuzz/fuzz-bus-message/message1 | Bin 0 -> 534 bytes test/fuzz/fuzz-bus-message/oss-fuzz-14016 | Bin 0 -> 49343 bytes ...t-08ee8f6446a4064db064e8e0b3d220147f7d0b5b | Bin 0 -> 534 bytes test/fuzz/fuzz-calendarspec/oss-fuzz-14108 | 1 + ...se-minimized-fuzz-catalog-5674475278827520 | 2 + test/fuzz/fuzz-catalog/systemd.pl.catalog | 390 + test/fuzz/fuzz-dhcp-server/discover-existing | Bin 0 -> 248 bytes test/fuzz/fuzz-dhcp-server/discover-new | Bin 0 -> 247 bytes test/fuzz/fuzz-dhcp-server/release | Bin 0 -> 248 bytes test/fuzz/fuzz-dhcp-server/request-existing | Bin 0 -> 260 bytes test/fuzz/fuzz-dhcp-server/request-new | Bin 0 -> 259 bytes test/fuzz/fuzz-dhcp-server/request-reboot | Bin 0 -> 254 bytes test/fuzz/fuzz-dhcp-server/request-renew | Bin 0 -> 248 bytes test/fuzz/fuzz-dhcp6-client/crash-13578 | Bin 0 -> 62 bytes test/fuzz/fuzz-dhcp6-client/crash-13591 | Bin 0 -> 12069 bytes ...h-4003c06fce43a11fbd22f02584df2807ac333eae | Bin 0 -> 14 bytes ...h-6e88fcb6b85c9436bcbe05219aa8e550194645ef | Bin 0 -> 9 bytes test/fuzz/fuzz-dhcp6-client/oss-fuzz-10746 | Bin 0 -> 99 bytes test/fuzz/fuzz-dhcp6-client/oss-fuzz-11019 | Bin 0 -> 61198 bytes ...h-497be373856c321a8a7b06589df9b2ff2e0d866a | Bin 0 -> 34 bytes test/fuzz/fuzz-dns-packet/issue-7888 | Bin 0 -> 25 bytes test/fuzz/fuzz-dns-packet/oss-fuzz-13422 | Bin 0 -> 36510 bytes test/fuzz/fuzz-dns-packet/oss-fuzz-5465 | Bin 0 -> 24 bytes test/fuzz/fuzz-env-file/simple-env-file | 5 + test/fuzz/fuzz-fido-id-desc/crash0 | 1 + test/fuzz/fuzz-fido-id-desc/crash1 | 1 + test/fuzz/fuzz-fido-id-desc/report0 | Bin 0 -> 71 bytes test/fuzz/fuzz-fido-id-desc/report1 | Bin 0 -> 34 bytes ...h-5a8f03d4c3a46fcded39527084f437e8e4b54b76 | Bin 0 -> 7675 bytes ...h-96dee870ea66d03e89ac321eee28ea63a9b9aa45 | Bin 0 -> 2490 bytes test/fuzz/fuzz-journal-remote/invalid-ts.txt | Bin 0 -> 4657 bytes test/fuzz/fuzz-journal-remote/oss-fuzz-8658 | Bin 0 -> 10 bytes test/fuzz/fuzz-journal-remote/oss-fuzz-8659 | 8 + test/fuzz/fuzz-journal-remote/oss-fuzz-8686 | 6 + test/fuzz/fuzz-journal-remote/oss-fuzz-9341 | Bin 0 -> 1153 bytes test/fuzz/fuzz-journal-remote/sample.txt | 180 + test/fuzz/fuzz-journald-audit/basic | 1 + test/fuzz/fuzz-journald-audit/crash | 1 + test/fuzz/fuzz-journald-kmsg/basic | 1 + ...h-c6c04d83e73f3d1417bc0afce8fa81b99f955963 | Bin 0 -> 112 bytes test/fuzz/fuzz-journald-kmsg/dev-null | 2 + ...k-ab161e601e82f1ec31d11e2cbae2747834ce9e43 | Bin 0 -> 1847 bytes test/fuzz/fuzz-journald-kmsg/loopback | 2 + .../fuzz-journald-kmsg/subsystem-loopback | 2 + test/fuzz/fuzz-journald-native-fd/basic | Bin 0 -> 34 bytes test/fuzz/fuzz-journald-stream/basic | 8 + test/fuzz/fuzz-journald-syslog/github-9795 | 1 + test/fuzz/fuzz-journald-syslog/github-9820 | 1 + test/fuzz/fuzz-journald-syslog/github-9827 | 1 + test/fuzz/fuzz-journald-syslog/github-9829 | 1 + test/fuzz/fuzz-json/crash-5639441482252288 | 9 + test/fuzz/fuzz-json/oss-fuzz-10908 | 9 + test/fuzz/fuzz-link-parser/99-default.link | 12 + .../fuzz/fuzz-link-parser/advertise-segv.link | 2 + .../fuzz-link-parser/condition-memleak.link | 7 + test/fuzz/fuzz-link-parser/directives.link | 38 + test/fuzz/fuzz-link-parser/oss-fuzz-13878 | 4 + test/fuzz/fuzz-link-parser/oss-fuzz-13882 | Bin 0 -> 2015 bytes test/fuzz/fuzz-lldp/basic | Bin 0 -> 52 bytes test/fuzz/fuzz-lldp/incomplete | Bin 0 -> 31 bytes test/fuzz/fuzz-lldp/oui | Bin 0 -> 86 bytes test/fuzz/fuzz-ndisc-rs/oss-fuzz-10734 | Bin 0 -> 212961 bytes ...t-2815b773c712fa33bea62f541dfa3017c64ea2f1 | Bin 0 -> 53 bytes ...t-61fff7fd1e5dcc07e1b656baab29065ce634ad5b | Bin 0 -> 71 bytes test/fuzz/fuzz-netdev-parser/11-dummy.netdev | 3 + test/fuzz/fuzz-netdev-parser/12-dummy.netdev | 3 + .../fuzz/fuzz-netdev-parser/21-macvlan.netdev | 3 + .../fuzz/fuzz-netdev-parser/21-macvtap.netdev | 3 + test/fuzz/fuzz-netdev-parser/21-vlan.netdev | 10 + .../fuzz-netdev-parser/25-6rd-tunnel.netdev | 8 + .../25-bond-active-backup-slave.netdev | 6 + test/fuzz/fuzz-netdev-parser/25-bond.netdev | 18 + test/fuzz/fuzz-netdev-parser/25-bridge.netdev | 13 + .../25-erspan-tunnel.netdev | 11 + test/fuzz/fuzz-netdev-parser/25-geneve.netdev | 12 + .../fuzz-netdev-parser/25-gre-tunnel.netdev | 7 + .../25-gretap-tunnel.netdev | 7 + .../25-ip6gre-tunnel.netdev | 7 + .../25-ip6tnl-tunnel.netdev | 8 + .../25-ipip-tunnel-independent.netdev | 9 + .../fuzz-netdev-parser/25-ipip-tunnel.netdev | 8 + test/fuzz/fuzz-netdev-parser/25-ipvlan.netdev | 6 + .../fuzz-netdev-parser/25-sit-tunnel.netdev | 7 + test/fuzz/fuzz-netdev-parser/25-tap.netdev | 7 + test/fuzz/fuzz-netdev-parser/25-tun.netdev | 7 + test/fuzz/fuzz-netdev-parser/25-vcan.netdev | 3 + test/fuzz/fuzz-netdev-parser/25-veth.netdev | 8 + test/fuzz/fuzz-netdev-parser/25-vrf.netdev | 6 + .../fuzz-netdev-parser/25-vti-tunnel.netdev | 7 + .../fuzz-netdev-parser/25-vti6-tunnel.netdev | 7 + test/fuzz/fuzz-netdev-parser/25-vxlan.netdev | 16 + .../fuzz-netdev-parser/25-wireguard.netdev | 12 + test/fuzz/fuzz-netdev-parser/26-bridge.netdev | 3 + test/fuzz/fuzz-netdev-parser/27-xfrm.netdev | 7 + .../fuzz/fuzz-netdev-parser/directives.netdev | 214 + test/fuzz/fuzz-netdev-parser/github-10615 | 5 + test/fuzz/fuzz-netdev-parser/github-10629 | 10 + test/fuzz/fuzz-netdev-parser/oss-fuzz-11279 | Bin 0 -> 60 bytes test/fuzz/fuzz-netdev-parser/oss-fuzz-11280 | Bin 0 -> 76 bytes test/fuzz/fuzz-netdev-parser/oss-fuzz-11286 | Bin 0 -> 65 bytes test/fuzz/fuzz-netdev-parser/oss-fuzz-11287 | Bin 0 -> 60 bytes test/fuzz/fuzz-netdev-parser/oss-fuzz-11296 | Bin 0 -> 318 bytes test/fuzz/fuzz-netdev-parser/oss-fuzz-11297 | Bin 0 -> 77 bytes test/fuzz/fuzz-netdev-parser/oss-fuzz-11299 | Bin 0 -> 54 bytes test/fuzz/fuzz-netdev-parser/oss-fuzz-11324 | Bin 0 -> 79 bytes test/fuzz/fuzz-netdev-parser/oss-fuzz-11344 | 6 + test/fuzz/fuzz-netdev-parser/oss-fuzz-13719 | 6 + test/fuzz/fuzz-netdev-parser/oss-fuzz-13884 | Bin 0 -> 449 bytes test/fuzz/fuzz-netdev-parser/oss-fuzz-13886 | Bin 0 -> 47998 bytes test/fuzz/fuzz-netdev-parser/oss-fuzz-14157 | 5 + test/fuzz/fuzz-netdev-parser/oss-fuzz-14158 | 5 + test/fuzz/fuzz-network-parser/21-vlan.network | 5 + .../23-active-slave.network | 6 + .../fuzz-network-parser/23-bond199.network | 2 + .../fuzz-network-parser/23-emit-lldp.network | 5 + .../23-primary-slave.network | 6 + .../23-test1-bond199.network | 6 + test/fuzz/fuzz-network-parser/24-lldp.network | 5 + .../24-search-domain.network | 7 + .../25-address-link-section.network | 5 + .../25-address-section-miscellaneous.network | 10 + .../25-address-section.network | 11 + .../25-fibrule-port-range.network | 11 + .../25-ipv6-address-label-section.network | 6 + .../25-link-section-unmanaged.network | 6 + .../25-neighbor-section.network | 6 + .../25-route-section.network | 8 + .../25-route-tcp-window-settings.network | 10 + .../fuzz-network-parser/25-route-type.network | 14 + .../fuzz-network-parser/25-sysctl.network | 10 + .../26-bridge-slave-interface-1.network | 12 + .../26-bridge-slave-interface-2.network | 5 + test/fuzz/fuzz-network-parser/27-xfrm.network | 5 + .../fuzz/fuzz-network-parser/bridge99.network | 6 + .../configure-without-carrier.network | 7 + .../dhcp-client-anonymize.network | 16 + .../dhcp-client-critical-connection.network | 9 + .../dhcp-client-ipv4-dhcp-settings.network | 15 + ...hcp-client-ipv4-only-ipv6-disabled.network | 6 + .../dhcp-client-ipv4-only.network | 5 + .../dhcp-client-ipv6-only.network | 5 + .../dhcp-client-ipv6-rapid-commit.network | 8 + .../dhcp-client-listen-port.network | 8 + .../dhcp-client-route-metric.network | 10 + .../dhcp-client-route-table.network | 10 + .../dhcp-client-timezone-router.network | 8 + .../fuzz-network-parser/dhcp-client.network | 5 + .../dhcp-server-timezone-router.network | 13 + .../dhcp-server-veth-peer.network | 6 + .../fuzz-network-parser/dhcp-server.network | 12 + .../dhcp-v4-server-veth-peer.network | 6 + .../fuzz-network-parser/directives.network | 273 + test/fuzz/fuzz-network-parser/github-10639 | 8 + test/fuzz/fuzz-network-parser/github-13938 | Bin 0 -> 65 bytes test/fuzz/fuzz-network-parser/gretap.network | 5 + test/fuzz/fuzz-network-parser/gretun.network | 5 + .../fuzz-network-parser/ip6gretap.network | 5 + test/fuzz/fuzz-network-parser/ip6tnl.network | 5 + test/fuzz/fuzz-network-parser/ipip.network | 5 + .../ipv6-prefix-veth.network | 5 + .../fuzz-network-parser/ipv6-prefix.network | 10 + test/fuzz/fuzz-network-parser/ipvlan.network | 5 + test/fuzz/fuzz-network-parser/macvlan.network | 5 + test/fuzz/fuzz-network-parser/macvtap.network | 5 + test/fuzz/fuzz-network-parser/oss-fuzz-11285 | 2 + test/fuzz/fuzz-network-parser/oss-fuzz-11302 | 2 + test/fuzz/fuzz-network-parser/oss-fuzz-11314 | 5 + test/fuzz/fuzz-network-parser/oss-fuzz-11345 | 2 + test/fuzz/fuzz-network-parser/oss-fuzz-13059 | Bin 0 -> 6558 bytes test/fuzz/fuzz-network-parser/oss-fuzz-13354 | Bin 0 -> 918848 bytes test/fuzz/fuzz-network-parser/oss-fuzz-13433 | Bin 0 -> 29 bytes test/fuzz/fuzz-network-parser/oss-fuzz-13888 | Bin 0 -> 56 bytes test/fuzz/fuzz-network-parser/oss-fuzz-15678 | 2 + .../routing-policy-rule.network | 10 + test/fuzz/fuzz-network-parser/sit.network | 5 + .../fuzz-network-parser/test-static.network | 6 + test/fuzz/fuzz-network-parser/vti.network | 5 + test/fuzz/fuzz-network-parser/vti6.network | 5 + test/fuzz/fuzz-network-parser/vxlan.network | 5 + test/fuzz/fuzz-nspawn-oci/basic.json | 141 + ...h-bffbd2085d4e95c47e9749b3f4a2dbc0580c20d3 | 5 + ...h-db0595479ee2e625fa5419a821009b5eb4d809b7 | 92 + test/fuzz/fuzz-nspawn-settings/basic-config | 36 + ...k-4ff0e2498f596a77ea68d185c61e9e9ff9bb657f | Bin 0 -> 133 bytes test/fuzz/fuzz-nspawn-settings/oss-fuzz-13691 | 2 + test/fuzz/fuzz-udev-database/sample.txt | 500 + .../fuzz-udev-rules/50-udev-default.rules | 86 + test/fuzz/fuzz-udev-rules/60-block.rules | 11 + test/fuzz/fuzz-udev-rules/60-cdrom_id.rules | 29 + test/fuzz/fuzz-udev-rules/60-drm.rules | 8 + test/fuzz/fuzz-udev-rules/60-evdev.rules | 23 + test/fuzz/fuzz-udev-rules/60-input-id.rules | 8 + .../fuzz-udev-rules/60-persistent-alsa.rules | 14 + .../fuzz-udev-rules/60-persistent-input.rules | 42 + .../60-persistent-storage-tape.rules | 36 + .../60-persistent-storage.rules | 109 + .../fuzz-udev-rules/60-persistent-v4l.rules | 20 + test/fuzz/fuzz-udev-rules/60-sensor.rules | 18 + test/fuzz/fuzz-udev-rules/60-serial.rules | 26 + test/fuzz/fuzz-udev-rules/64-btrfs.rules | 17 + test/fuzz/fuzz-udev-rules/70-joystick.rules | 12 + test/fuzz/fuzz-udev-rules/70-mouse.rules | 18 + test/fuzz/fuzz-udev-rules/70-touchpad.rules | 13 + .../fuzz-udev-rules/75-net-description.rules | 14 + test/fuzz/fuzz-udev-rules/75-probe_mtd.rules | 7 + test/fuzz/fuzz-udev-rules/78-sound-card.rules | 96 + test/fuzz/fuzz-udev-rules/80-drivers.rules | 13 + .../fuzz-udev-rules/80-net-setup-link.rules | 13 + test/fuzz/fuzz-udev-rules/99-systemd.rules | 76 + test/fuzz/fuzz-udev-rules/oss-fuzz-12980 | 1 + .../dev-mapper-fedora_krowka\\x2dswap.swap" | 10 + test/fuzz/fuzz-unit-file/directives.scope | 2 + test/fuzz/fuzz-unit-file/directives.service | 924 + test/fuzz/fuzz-unit-file/empty.scope | 2 + test/fuzz/fuzz-unit-file/machine.slice | 14 + test/fuzz/fuzz-unit-file/oss-fuzz-10007 | 6 + test/fuzz/fuzz-unit-file/oss-fuzz-11569 | Bin 0 -> 277466 bytes test/fuzz/fuzz-unit-file/oss-fuzz-13125 | 10 + test/fuzz/fuzz-unit-file/oss-fuzz-6884 | 3 + test/fuzz/fuzz-unit-file/oss-fuzz-6885 | 3 + test/fuzz/fuzz-unit-file/oss-fuzz-6886 | 3 + test/fuzz/fuzz-unit-file/oss-fuzz-6892 | 3 + test/fuzz/fuzz-unit-file/oss-fuzz-6897 | 4 + test/fuzz/fuzz-unit-file/oss-fuzz-6897-evverx | 4 + test/fuzz/fuzz-unit-file/oss-fuzz-6908 | 3 + test/fuzz/fuzz-unit-file/oss-fuzz-6917 | 4 + test/fuzz/fuzz-unit-file/oss-fuzz-6977 | 3 + .../fuzz-unit-file/oss-fuzz-6977-unminimized | 3 + test/fuzz/fuzz-unit-file/oss-fuzz-7004 | 3 + test/fuzz/fuzz-unit-file/oss-fuzz-8064 | 3 + test/fuzz/fuzz-unit-file/oss-fuzz-8827 | 5 + .../proc-sys-fs-binfmt_misc.automount | 21 + test/fuzz/fuzz-unit-file/syslog.socket | 117 + .../systemd-ask-password-console.path | 22 + .../fuzz-unit-file/systemd-machined.service | 52 + .../fuzz-unit-file/systemd-resolved.service | 50 + .../systemd-tmpfiles-clean.timer | 40 + test/fuzz/fuzz-unit-file/timers.target | 16 + .../fuzz-unit-file/var-lib-machines.mount | 19 + test/fuzz/fuzz-varlink/array | Bin 0 -> 5 bytes test/fuzz/fuzz-varlink/do-something | Bin 0 -> 81 bytes test/fuzz/fuzz-varlink/huge-method | 1 + test/fuzz/fuzz-varlink/method-call | Bin 0 -> 301 bytes test/fuzz/fuzz-varlink/method-error | Bin 0 -> 110 bytes test/fuzz/fuzz-varlink/method-reply | Bin 0 -> 142 bytes test/fuzz/fuzz-varlink/oss-fuzz-14688 | 1 + test/fuzz/fuzz-varlink/oss-fuzz-14708 | 1 + ...t-d8a88bf4adea54537d21e3afb396e1a55c5b58bf | Bin 0 -> 10014 bytes test/fuzz/meson.build | 35 + test/g.service | 6 + test/grandchild.service | 7 + test/h.service | 6 + test/hello-after-sleep.target | 5 + test/hello.service | 5 + test/hwdb-test.sh | 62 + test/hwdb.d/10-bad.hwdb | 26 + test/i.service | 8 + test/journal-data/journal-1.txt | Bin 0 -> 586 bytes test/journal-data/journal-2.txt | Bin 0 -> 513 bytes test/loopy.service | 2 + test/loopy.service.d/compat.conf | 5 + test/loopy2.service | 1 + test/loopy3.service | 5 + test/loopy4.service | 1 + test/meson.build | 290 + test/mkosi.build.networkd-test | 24 + test/mkosi.default.networkd-test | 80 + test/mkosi.nspawn.networkd-test | 2 + test/mocks/fsck | 27 + test/networkd-test.py | 1123 + test/nomem.slice | 5 + test/nomemleaf.service | 9 + test/parent-deep.slice | 5 + test/parent.slice | 5 + test/rule-syntax-check.py | 65 + test/run-integration-tests.sh | 50 + test/run-unit-tests.py | 61 + test/sched_idle_bad.service | 6 + test/sched_idle_ok.service | 6 + test/sched_rr_bad.service | 8 + test/sched_rr_change.service | 9 + test/sched_rr_ok.service | 6 + test/shutdown.target | 1 + test/sleep.service | 6 + test/sockets.target | 1 + test/son.service | 8 + test/splash.bmp | Bin 0 -> 289238 bytes test/sys-script.py | 16850 ++ test/sysinit.target | 1 + test/sysv-generator-test.py | 411 + test/test-efi-create-disk.sh | 50 + test/test-exec-deserialization.py | 210 + ...mbientcapabilities-merge-nfsnobody.service | 9 + ...c-ambientcapabilities-merge-nobody.service | 9 + .../exec-ambientcapabilities-merge.service | 9 + ...exec-ambientcapabilities-nfsnobody.service | 8 + .../exec-ambientcapabilities-nobody.service | 8 + .../exec-ambientcapabilities.service | 8 + test/test-execute/exec-basic.service | 17 + test/test-execute/exec-bindpaths.service | 17 + .../exec-capabilityboundingset-invert.service | 8 + .../exec-capabilityboundingset-merge.service | 8 + .../exec-capabilityboundingset-reset.service | 8 + .../exec-capabilityboundingset-simple.service | 7 + .../exec-condition-failed.service | 11 + test/test-execute/exec-condition-skip.service | 15 + test/test-execute/exec-cpuaffinity1.service | 6 + test/test-execute/exec-cpuaffinity2.service | 8 + test/test-execute/exec-cpuaffinity3.service | 7 + .../exec-dynamicuser-fixeduser-adm.service | 11 + .../exec-dynamicuser-fixeduser-games.service | 11 + ...r-fixeduser-one-supplementarygroup.service | 10 + .../exec-dynamicuser-fixeduser.service | 9 + ...dynamicuser-statedir-migrate-step1.service | 17 + ...dynamicuser-statedir-migrate-step2.service | 25 + .../exec-dynamicuser-statedir.service | 20 + ...ec-dynamicuser-supplementarygroups.service | 10 + .../exec-environment-empty.service | 8 + .../exec-environment-multiple.service | 8 + .../exec-environment-no-substitute.service | 8 + test/test-execute/exec-environment.service | 7 + .../test-execute/exec-environmentfile.service | 7 + .../test-execute/exec-group-nfsnobody.service | 7 + test/test-execute/exec-group-nobody.service | 7 + test/test-execute/exec-group-nogroup.service | 7 + test/test-execute/exec-group.service | 7 + .../exec-ignoresigpipe-no.service | 7 + .../exec-ignoresigpipe-yes.service | 7 + ...naccessiblepaths-mount-propagation.service | 7 + .../exec-inaccessiblepaths-sys.service | 7 + ...exec-ioschedulingclass-best-effort.service | 7 + .../exec-ioschedulingclass-idle.service | 7 + .../exec-ioschedulingclass-none.service | 7 + .../exec-ioschedulingclass-realtime.service | 7 + .../exec-oomscoreadjust-negative.service | 7 + .../exec-oomscoreadjust-positive.service | 7 + .../exec-passenvironment-absent.service | 7 + .../exec-passenvironment-empty.service | 8 + .../exec-passenvironment-repeated.service | 10 + .../test-execute/exec-passenvironment.service | 7 + .../exec-personality-aarch64.service | 7 + .../exec-personality-ppc64.service | 7 + .../exec-personality-ppc64le.service | 7 + .../exec-personality-s390.service | 7 + .../exec-personality-x86-64.service | 7 + .../test-execute/exec-personality-x86.service | 7 + ...-privatedevices-disabled-by-prefix.service | 8 + ...privatedevices-no-capability-mknod.service | 8 + ...atedevices-no-capability-sys-rawio.service | 8 + .../exec-privatedevices-no.service | 7 + ...rivatedevices-yes-capability-mknod.service | 8 + ...tedevices-yes-capability-sys-rawio.service | 8 + .../exec-privatedevices-yes.service | 7 + .../exec-privatenetwork-yes.service | 7 + test/test-execute/exec-privatetmp-no.service | 7 + test/test-execute/exec-privatetmp-yes.service | 7 + ...home-tmpfs-vs-protectsystem-strict.service | 9 + ...-protectkernellogs-no-capabilities.service | 8 + ...protectkernellogs-yes-capabilities.service | 8 + ...otectkernelmodules-no-capabilities.service | 8 + ...tectkernelmodules-yes-capabilities.service | 8 + ...ernelmodules-yes-mount-propagation.service | 7 + ...ec-readonlypaths-mount-propagation.service | 7 + .../exec-readonlypaths-simple.service | 11 + .../exec-readonlypaths-with-bindpaths.service | 8 + test/test-execute/exec-readonlypaths.service | 9 + ...c-readwritepaths-mount-propagation.service | 7 + .../exec-restrictnamespaces-merge-all.service | 8 + .../exec-restrictnamespaces-merge-and.service | 9 + .../exec-restrictnamespaces-merge-or.service | 9 + ...c-restrictnamespaces-mnt-blacklist.service | 7 + .../exec-restrictnamespaces-mnt.service | 7 + .../exec-restrictnamespaces-no.service | 7 + .../exec-restrictnamespaces-yes.service | 7 + .../exec-runtimedirectory-mode.service | 9 + ...c-runtimedirectory-owner-nfsnobody.service | 9 + ...exec-runtimedirectory-owner-nobody.service | 9 + ...xec-runtimedirectory-owner-nogroup.service | 9 + .../exec-runtimedirectory-owner.service | 9 + .../exec-runtimedirectory.service | 10 + .../exec-specifier-interpolation.service | 6 + test/test-execute/exec-specifier.service | 31 + test/test-execute/exec-specifier@.service | 29 + .../exec-standardinput-data.service | 19 + .../exec-standardinput-file-cat.service | 9 + .../exec-standardinput-file.service | 7 + .../exec-standardoutput-append.service | 13 + .../exec-standardoutput-file.service | 13 + ...multiple-groups-default-group-user.service | 11 + ...tarygroups-multiple-groups-withgid.service | 11 + ...tarygroups-multiple-groups-withuid.service | 10 + ...plementarygroups-single-group-user.service | 10 + ...c-supplementarygroups-single-group.service | 9 + .../exec-supplementarygroups.service | 8 + .../exec-systemcallerrornumber-name.service | 8 + .../exec-systemcallerrornumber-number.service | 8 + .../exec-systemcallfilter-failing.service | 10 + .../exec-systemcallfilter-failing2.service | 8 + .../exec-systemcallfilter-not-failing.service | 10 + ...exec-systemcallfilter-not-failing2.service | 7 + ...emcallfilter-system-user-nfsnobody.service | 11 + ...ystemcallfilter-system-user-nobody.service | 11 + .../exec-systemcallfilter-system-user.service | 11 + ...-systemcallfilter-with-errno-multi.service | 9 + ...c-systemcallfilter-with-errno-name.service | 8 + ...systemcallfilter-with-errno-number.service | 8 + .../exec-temporaryfilesystem-options.service | 16 + .../exec-temporaryfilesystem-ro.service | 36 + .../exec-temporaryfilesystem-rw.service | 36 + .../exec-temporaryfilesystem-usr.service | 15 + test/test-execute/exec-umask-0177.service | 8 + test/test-execute/exec-umask-default.service | 7 + .../exec-unsetenvironment.service | 8 + test/test-execute/exec-user-nfsnobody.service | 7 + test/test-execute/exec-user-nobody.service | 7 + test/test-execute/exec-user.service | 7 + ...exec-workingdirectory-trailing-dot.service | 7 + .../exec-workingdirectory.service | 7 + test/test-functions | 1825 + test/test-network/conf/10-dropin-test.netdev | 4 + .../conf/10-dropin-test.netdev.d/mac.conf | 2 + .../conf/10-dropin-test.netdev.d/name.conf | 2 + test/test-network/conf/11-dummy-mtu.netdev | 4 + test/test-network/conf/11-dummy.netdev | 3 + test/test-network/conf/11-dummy.network | 5 + test/test-network/conf/12-dummy.netdev | 3 + .../conf/13-not-match-udev-property.network | 6 + .../conf/14-match-udev-property.network | 7 + .../conf/15-name-conflict-test.netdev | 4 + test/test-network/conf/21-macvlan.netdev | 4 + test/test-network/conf/21-macvtap.netdev | 3 + test/test-network/conf/21-vlan-test1.network | 2 + .../21-vlan-test1.network.d/override.conf | 5 + test/test-network/conf/21-vlan.netdev | 3 + .../conf/21-vlan.netdev.d/override.conf | 9 + test/test-network/conf/21-vlan.network | 7 + .../test-network/conf/23-active-slave.network | 6 + test/test-network/conf/23-bond199.network | 2 + test/test-network/conf/23-emit-lldp.network | 5 + .../conf/23-primary-slave.network | 6 + .../conf/24-keep-configuration-static.network | 5 + test/test-network/conf/24-lldp.network | 5 + .../conf/24-search-domain.network | 7 + test/test-network/conf/25-6rd-tunnel.netdev | 7 + .../conf/25-address-link-section.network | 5 + ...25-address-preferred-lifetime-zero.network | 33 + .../conf/25-address-static.network | 53 + .../test-network/conf/25-bind-carrier.network | 8 + .../conf/25-bond-active-backup-slave.netdev | 6 + .../conf/25-bond-balanced-tlb.netdev | 7 + test/test-network/conf/25-bond.netdev | 18 + ...5-bridge-configure-without-carrier.network | 7 + test/test-network/conf/25-bridge.netdev | 14 + test/test-network/conf/25-bridge.network | 5 + .../conf/25-erspan-tunnel-local-any.netdev | 10 + .../test-network/conf/25-erspan-tunnel.netdev | 10 + .../conf/25-fibrule-invert.network | 10 + .../conf/25-fibrule-port-range.network | 11 + test/test-network/conf/25-fou-gre.netdev | 14 + test/test-network/conf/25-fou-gretap.netdev | 13 + test/test-network/conf/25-fou-ipip.netdev | 12 + .../conf/25-fou-ipproto-gre.netdev | 8 + .../conf/25-fou-ipproto-ipip.netdev | 8 + test/test-network/conf/25-fou-sit.netdev | 11 + .../conf/25-gateway-next-static.network | 6 + .../conf/25-gateway-static.network | 6 + test/test-network/conf/25-geneve.netdev | 12 + .../conf/25-gre-tunnel-any-any.netdev | 9 + .../conf/25-gre-tunnel-local-any.netdev | 9 + .../conf/25-gre-tunnel-remote-any.netdev | 9 + test/test-network/conf/25-gre-tunnel.netdev | 10 + .../conf/25-gretap-tunnel-local-any.netdev | 9 + .../test-network/conf/25-gretap-tunnel.netdev | 9 + .../conf/25-ip6gre-tunnel-any-any.netdev | 7 + .../conf/25-ip6gre-tunnel-local-any.netdev | 7 + .../conf/25-ip6gre-tunnel-remote-any.netdev | 7 + .../test-network/conf/25-ip6gre-tunnel.netdev | 7 + .../conf/25-ip6gretap-tunnel-local-any.netdev | 7 + .../conf/25-ip6gretap-tunnel.netdev | 7 + .../conf/25-ip6tnl-tunnel-local-any.netdev | 8 + .../conf/25-ip6tnl-tunnel-remote-any.netdev | 8 + .../test-network/conf/25-ip6tnl-tunnel.netdev | 8 + .../conf/25-ipip-tunnel-any-any.netdev | 8 + ...25-ipip-tunnel-independent-loopback.netdev | 10 + .../conf/25-ipip-tunnel-independent.netdev | 9 + .../conf/25-ipip-tunnel-local-any.netdev | 8 + .../conf/25-ipip-tunnel-remote-any.netdev | 8 + test/test-network/conf/25-ipip-tunnel.netdev | 8 + .../25-ipv6-address-label-section.network | 6 + test/test-network/conf/25-ipvlan.netdev | 3 + test/test-network/conf/25-ipvtap.netdev | 3 + .../test-network/conf/25-isatap-tunnel.netdev | 8 + test/test-network/conf/25-l2tp-dummy.network | 7 + test/test-network/conf/25-l2tp-ip.netdev | 20 + test/test-network/conf/25-l2tp-udp.netdev | 25 + test/test-network/conf/25-l2tp.network | 6 + .../conf/25-link-local-addressing-no.network | 5 + .../conf/25-link-local-addressing-yes.network | 6 + .../conf/25-link-section-unmanaged.network | 6 + test/test-network/conf/25-macsec.key | 1 + test/test-network/conf/25-macsec.netdev | 68 + test/test-network/conf/25-macsec.network | 7 + .../conf/25-neighbor-ip-dummy.network | 7 + test/test-network/conf/25-neighbor-ip.network | 10 + .../conf/25-neighbor-ipv6.network | 11 + .../conf/25-neighbor-next.network | 9 + .../conf/25-neighbor-section.network | 13 + test/test-network/conf/25-netdevsim.netdev | 3 + test/test-network/conf/25-nexthop.network | 11 + test/test-network/conf/25-nlmon.netdev | 3 + test/test-network/conf/25-qdisc.network | 20 + .../conf/25-route-ipv6-src.network | 16 + .../test-network/conf/25-route-static.network | 64 + .../conf/25-sit-tunnel-any-any.netdev | 7 + .../conf/25-sit-tunnel-local-any.netdev | 7 + .../conf/25-sit-tunnel-remote-any.netdev | 7 + test/test-network/conf/25-sit-tunnel.netdev | 7 + .../conf/25-sysctl-disable-ipv6.network | 18 + test/test-network/conf/25-sysctl.network | 11 + test/test-network/conf/25-tap.netdev | 8 + test/test-network/conf/25-tun.netdev | 8 + .../conf/25-tunnel-any-any.network | 8 + .../conf/25-tunnel-local-any.network | 8 + .../conf/25-tunnel-remote-any.network | 8 + test/test-network/conf/25-tunnel.network | 8 + test/test-network/conf/25-vcan.netdev | 3 + test/test-network/conf/25-veth-peer.network | 7 + test/test-network/conf/25-veth.netdev | 8 + test/test-network/conf/25-vrf.netdev | 6 + test/test-network/conf/25-vrf.network | 2 + .../conf/25-vti-tunnel-any-any.netdev | 7 + .../conf/25-vti-tunnel-local-any.netdev | 7 + .../conf/25-vti-tunnel-remote-any.netdev | 7 + test/test-network/conf/25-vti-tunnel.netdev | 7 + .../conf/25-vti6-tunnel-local-any.netdev | 7 + .../conf/25-vti6-tunnel-remote-any.netdev | 7 + test/test-network/conf/25-vti6-tunnel.netdev | 7 + test/test-network/conf/25-vxcan.netdev | 6 + test/test-network/conf/25-vxlan.netdev | 16 + .../conf/25-wireguard-23-peers.netdev | 150 + .../conf/25-wireguard-23-peers.network | 97 + .../conf/25-wireguard-preshared-key.txt | 3 + .../conf/25-wireguard-private-key.txt | 6 + test/test-network/conf/25-wireguard.netdev | 16 + .../conf/25-wireguard.netdev.d/peer.conf | 5 + test/test-network/conf/25-wireguard.network | 2 + .../conf/25-xfrm-independent.netdev | 6 + test/test-network/conf/25-xfrm.netdev | 3 + .../conf/26-bridge-slave-interface-1.network | 18 + .../conf/26-bridge-slave-interface-2.network | 8 + .../conf/26-bridge-vlan-master.network | 8 + .../conf/26-bridge-vlan-slave.network | 9 + test/test-network/conf/26-bridge.netdev | 3 + .../26-link-local-addressing-ipv6.network | 6 + test/test-network/conf/6rd.network | 5 + test/test-network/conf/bond-slave.network | 12 + test/test-network/conf/bond99.network | 6 + .../conf/bridge99-ignore-carrier-loss.network | 13 + test/test-network/conf/bridge99.network | 7 + .../conf/configure-without-carrier.network | 7 + .../conf/dhcp-client-anonymize.network | 16 + ...hcp-client-gateway-onlink-implicit.network | 14 + .../dhcp-client-ipv4-dhcp-settings.network | 16 + ...hcp-client-ipv4-only-ipv6-disabled.network | 10 + .../conf/dhcp-client-ipv4-only.network | 5 + .../conf/dhcp-client-ipv6-only.network | 6 + .../dhcp-client-ipv6-rapid-commit.network | 8 + ...nt-keep-configuration-dhcp-on-stop.network | 7 + ...hcp-client-keep-configuration-dhcp.network | 7 + .../conf/dhcp-client-listen-port.network | 9 + ...client-reassign-static-routes-ipv4.network | 18 + ...client-reassign-static-routes-ipv6.network | 8 + .../conf/dhcp-client-route-metric.network | 10 + .../conf/dhcp-client-route-table.network | 10 + .../conf/dhcp-client-timezone-router.network | 10 + .../dhcp-client-use-dns-ipv4-and-ra.network | 11 + .../conf/dhcp-client-use-dns-ipv4.network | 14 + .../conf/dhcp-client-use-dns-no.network | 14 + .../conf/dhcp-client-use-dns-yes.network | 14 + .../conf/dhcp-client-use-domains.network | 9 + .../test-network/conf/dhcp-client-vrf.network | 8 + ...h-ipv4ll-fallback-with-dhcp-server.network | 7 + ...pv4ll-fallback-without-dhcp-server.network | 10 + .../dhcp-client-with-static-address.network | 7 + test/test-network/conf/dhcp-client.network | 5 + .../conf/dhcp-server-timezone-router.network | 13 + .../conf/dhcp-server-veth-peer.network | 7 + test/test-network/conf/dhcp-server.network | 13 + .../conf/dhcp-v4-server-veth-peer.network | 7 + test/test-network/conf/erspan.network | 6 + test/test-network/conf/gretap.network | 6 + test/test-network/conf/gretun.network | 8 + test/test-network/conf/ip6gretap.network | 6 + test/test-network/conf/ip6gretun.network | 8 + test/test-network/conf/ip6tnl.network | 7 + test/test-network/conf/ipip.network | 8 + .../conf/ipv6-prefix-veth.network | 5 + test/test-network/conf/ipv6-prefix.network | 10 + .../conf/ipv6ra-prefix-client.network | 6 + test/test-network/conf/ipv6ra-prefix.network | 14 + test/test-network/conf/ipvlan.network | 5 + test/test-network/conf/ipvtap.network | 5 + test/test-network/conf/isatap.network | 5 + test/test-network/conf/macsec.network | 10 + test/test-network/conf/macvlan.network | 5 + test/test-network/conf/macvtap.network | 5 + .../netdev-link-local-addressing-yes.network | 19 + .../conf/routing-policy-rule-dummy98.network | 10 + .../conf/routing-policy-rule-test1.network | 22 + test/test-network/conf/sit.network | 8 + .../conf/state-file-tests.network | 15 + test/test-network/conf/vlan6.netdev | 7 + test/test-network/conf/vlan6.network | 6 + test/test-network/conf/vti.network | 8 + test/test-network/conf/vti6.network | 7 + test/test-network/conf/vxlan-test1.network | 7 + test/test-network/conf/vxlan.network | 18 + test/test-network/conf/xfrm.network | 6 + test/test-network/systemd-networkd-tests.py | 3327 + test/test-path/basic.target | 1 + test/test-path/path-changed.path | 8 + test/test-path/path-changed.service | 1 + test/test-path/path-directorynotempty.path | 8 + test/test-path/path-directorynotempty.service | 1 + test/test-path/path-exists.path | 8 + test/test-path/path-exists.service | 1 + test/test-path/path-existsglob.path | 8 + test/test-path/path-existsglob.service | 1 + test/test-path/path-makedirectory.path | 10 + test/test-path/path-makedirectory.service | 1 + test/test-path/path-modified.path | 8 + test/test-path/path-modified.service | 1 + test/test-path/path-mycustomunit.service | 6 + test/test-path/path-service.service | 6 + test/test-path/path-unit.path | 9 + test/test-path/paths.target | 1 + test/test-path/sysinit.target | 1 + .../_443._tcp.fedoraproject.org.pkts | Bin 0 -> 169 bytes .../_openpgpkey.fedoraproject.org.pkts | Bin 0 -> 986 bytes test/test-resolve/fake-caa.pkts | Bin 0 -> 196 bytes test/test-resolve/fedoraproject.org.pkts | Bin 0 -> 1483 bytes test/test-resolve/gandi.net.pkts | Bin 0 -> 1010 bytes test/test-resolve/google.com.pkts | Bin 0 -> 747 bytes test/test-resolve/kyhwana.org.pkts | Bin 0 -> 1803 bytes test/test-resolve/root.pkts | Bin 0 -> 1061 bytes ...aa-sw1a2aa-sw1a2ab-sw1a2ac.find.me.uk.pkts | Bin 0 -> 330 bytes test/test-resolve/teamits.com.pkts | Bin 0 -> 1021 bytes .../zbyszek@fedoraproject.org.pkts | Bin 0 -> 2533 bytes test/test-umount/empty.mountinfo | 0 test/test-umount/example.swaps | 4 + test/test-umount/garbled.mountinfo | 5 + test/test-umount/rhbug-1554943.mountinfo | 47 + test/testsuite.target | 6 + test/timers.target | 1 + test/udev-test.pl | 1858 + test/unit-.service.d/10-override.conf | 2 + test/unit-with-.service.d/20-override.conf | 2 + .../20-override.conf | 2 + .../30-override.conf | 2 + test/unit-with-multiple-dashes.service | 6 + .../10-override.conf | 2 + test/unstoppable.service | 5 + tmpfiles.d/etc.conf.m4 | 22 + tmpfiles.d/home.conf | 11 + tmpfiles.d/journal-nocow.conf | 27 + tmpfiles.d/legacy.conf | 27 + tmpfiles.d/meson.build | 61 + tmpfiles.d/portables.conf | 4 + tmpfiles.d/static-nodes-permissions.conf.in | 17 + tmpfiles.d/systemd-nologin.conf | 11 + tmpfiles.d/systemd-nspawn.conf | 23 + tmpfiles.d/systemd-tmp.conf | 23 + tmpfiles.d/systemd.conf.m4 | 79 + tmpfiles.d/tmp.conf | 12 + tmpfiles.d/var.conf.m4 | 25 + tmpfiles.d/x11.conf | 19 + tools/add-git-hook.sh | 12 + tools/catalog-report.py | 84 + tools/check-directives.sh | 36 + tools/check-includes.pl | 23 + tools/choose-default-locale.sh | 11 + tools/chromiumos/LICENSE | 27 + tools/chromiumos/gen_autosuspend_rules.py | 317 + tools/coverity.sh | 233 + tools/find-build-dir.sh | 32 + tools/find-double-newline.sh | 41 + tools/find-tabs.sh | 41 + tools/gdb-sd_dump_hashmaps.py | 79 + tools/generate-gperfs.py | 24 + tools/make-autosuspend-rules.py | 14 + tools/make-directive-index.py | 310 + tools/make-man-index.py | 110 + tools/make-man-rules.py | 86 + tools/meson-apply-m4.sh | 24 + tools/meson-autosuspend-update.sh | 7 + tools/meson-build.sh | 20 + tools/meson-check-api-docs.sh | 33 + tools/meson-check-compilation.sh | 4 + tools/meson-check-help.sh | 29 + tools/meson-git-contrib.sh | 9 + tools/meson-hwdb-update.sh | 32 + tools/meson-make-symlink.sh | 12 + tools/meson-vcs-tag.sh | 22 + tools/oss-fuzz.sh | 55 + tools/xml_helper.py | 20 + travis-ci/.dockerignore | 30 + travis-ci/Dockerfile | 37 + travis-ci/managers/debian.sh | 79 + travis-ci/managers/fedora.sh | 92 + travis-ci/managers/fuzzbuzz.sh | 39 + travis-ci/managers/fuzzit.sh | 55 + travis-ci/managers/travis_wait.bash | 61 + travis-ci/requirements.txt | 5 + travis-ci/scripts/build-docker-image.sh | 13 + travis-ci/tools/get-coverity.sh | 35 + units/basic.target | 22 + units/bluetooth.target | 13 + units/boot-complete.target | 14 + units/console-getty.service.m4 | 38 + units/container-getty@.service.m4 | 41 + units/cryptsetup-pre.target | 14 + units/cryptsetup.target | 12 + units/debug-shell.service.in | 36 + units/dev-hugepages.mount | 23 + units/dev-mqueue.mount | 23 + units/emergency.service.in | 30 + units/emergency.target | 15 + units/exit.target | 19 + units/final.target | 15 + units/getty-pre.target | 13 + units/getty.target | 13 + units/getty@.service.m4 | 60 + units/graphical.target | 17 + units/halt.target | 19 + units/hibernate.target | 16 + units/hybrid-sleep.target | 16 + units/initrd-cleanup.service.in | 20 + units/initrd-fs.target | 18 + units/initrd-parse-etc.service.in | 24 + units/initrd-root-device.target | 17 + units/initrd-root-fs.target | 17 + units/initrd-switch-root.service.in | 20 + units/initrd-switch-root.target | 18 + units/initrd-udevadm-cleanup-db.service.in | 20 + units/initrd.target | 19 + units/kexec.target | 19 + units/kmod-static-nodes.service.in | 20 + units/ldconfig.service | 23 + units/local-fs-pre.target | 13 + units/local-fs.target | 17 + units/machine.slice | 13 + units/machines.target | 16 + units/meson-add-wants.sh | 28 + units/meson.build | 324 + units/multi-user.target | 16 + units/network-online.target | 14 + units/network-pre.target | 14 + units/network.target | 15 + units/nss-lookup.target | 16 + units/nss-user-lookup.target | 16 + units/paths.target | 12 + units/poweroff.target | 21 + units/printer.target | 13 + units/proc-sys-fs-binfmt_misc.automount | 20 + units/proc-sys-fs-binfmt_misc.mount | 23 + units/quotaon.service.in | 21 + units/rc-local.service.in | 23 + units/reboot.target | 21 + units/remote-cryptsetup.target | 18 + units/remote-fs-pre.target | 13 + units/remote-fs.target | 18 + units/rescue.service.in | 29 + units/rescue.target | 15 + units/rpcbind.target | 16 + units/serial-getty@.service.m4 | 48 + units/shutdown.target | 14 + units/sigpwr.target | 12 + units/sleep.target | 15 + units/slices.target | 14 + units/smartcard.target | 13 + units/sockets.target | 12 + units/sound.target | 13 + units/suspend-then-hibernate.target | 16 + units/suspend.target | 16 + units/swap.target | 12 + units/sys-fs-fuse-connections.mount | 25 + units/sys-kernel-config.mount | 24 + units/sys-kernel-debug.mount | 23 + units/sysinit.target | 15 + units/syslog.socket | 47 + units/system-update-cleanup.service | 35 + units/system-update-pre.target | 15 + units/system-update.target | 17 + units/systemd-ask-password-console.path | 21 + units/systemd-ask-password-console.service.in | 21 + units/systemd-ask-password-wall.path | 19 + units/systemd-ask-password-wall.service.in | 18 + units/systemd-backlight@.service.in | 24 + units/systemd-binfmt.service.in | 31 + units/systemd-bless-boot.service.in | 22 + .../systemd-boot-check-no-failures.service.in | 24 + units/systemd-boot-system-token.service.in | 34 + units/systemd-coredump.socket | 19 + units/systemd-coredump@.service.in | 45 + units/systemd-exit.service | 16 + units/systemd-firstboot.service.in | 26 + units/systemd-fsck-root.service.in | 22 + units/systemd-fsck@.service.in | 23 + units/systemd-halt.service.in | 19 + units/systemd-hibernate-resume@.service.in | 22 + units/systemd-hibernate.service.in | 19 + units/systemd-hostnamed.service.in | 40 + units/systemd-hwdb-update.service.in | 26 + units/systemd-hybrid-sleep.service.in | 19 + units/systemd-importd.service.in | 30 + units/systemd-initctl.service.in | 19 + units/systemd-initctl.socket | 19 + .../systemd-journal-catalog-update.service.in | 23 + units/systemd-journal-flush.service.in | 24 + units/systemd-journal-gatewayd.service.in | 40 + units/systemd-journal-gatewayd.socket | 18 + units/systemd-journal-remote.service.in | 44 + units/systemd-journal-remote.socket | 17 + units/systemd-journal-upload.service.in | 42 + units/systemd-journald-audit.socket | 22 + units/systemd-journald-dev-log.socket | 34 + units/systemd-journald.service.in | 44 + units/systemd-journald.socket | 28 + units/systemd-kexec.service.in | 19 + units/systemd-localed.service.in | 41 + units/systemd-logind.service.in | 63 + units/systemd-machine-id-commit.service.in | 24 + units/systemd-machined.service.in | 37 + units/systemd-modules-load.service.in | 29 + units/systemd-network-generator.service.in | 20 + units/systemd-networkd-wait-online.service.in | 25 + units/systemd-networkd.service.in | 59 + units/systemd-networkd.socket | 23 + units/systemd-nspawn@.service.in | 50 + units/systemd-portabled.service.in | 29 + units/systemd-poweroff.service | 16 + units/systemd-pstore.service.in | 25 + units/systemd-quotacheck.service.in | 22 + units/systemd-random-seed.service.in | 30 + units/systemd-reboot.service | 16 + units/systemd-remount-fs.service.in | 23 + units/systemd-resolved.service.in | 54 + units/systemd-rfkill.service.in | 24 + units/systemd-rfkill.socket | 22 + .../systemd-suspend-then-hibernate.service.in | 19 + units/systemd-suspend.service.in | 19 + units/systemd-sysctl.service.in | 23 + units/systemd-sysusers.service.in | 23 + units/systemd-time-wait-sync.service.in | 36 + units/systemd-timedated.service.in | 40 + units/systemd-timesyncd.service.in | 54 + units/systemd-tmpfiles-clean.service.in | 22 + units/systemd-tmpfiles-clean.timer | 16 + units/systemd-tmpfiles-setup-dev.service.in | 22 + units/systemd-tmpfiles-setup.service.in | 23 + units/systemd-udev-settle.service.in | 27 + units/systemd-udev-trigger.service.in | 23 + units/systemd-udevd-control.socket | 22 + units/systemd-udevd-kernel.socket | 21 + units/systemd-udevd.service.in | 40 + units/systemd-update-done.service.in | 23 + units/systemd-update-utmp-runlevel.service.in | 23 + units/systemd-update-utmp.service.in | 23 + units/systemd-user-sessions.service.in | 19 + units/systemd-vconsole-setup.service.in | 19 + units/systemd-volatile-root.service.in | 22 + units/time-set.target | 13 + units/time-sync.target | 15 + units/timers.target | 15 + units/tmp.mount | 25 + units/umount.target | 14 + units/usb-gadget.target | 12 + units/user-.slice.d/10-defaults.conf | 17 + units/user-runtime-dir@.service.in | 22 + units/user.slice | 13 + units/user/basic.target | 14 + units/user/bluetooth.target | 13 + units/user/default.target | 15 + units/user/exit.target | 16 + units/user/graphical-session-pre.target | 16 + units/user/graphical-session.target | 15 + units/user/meson.build | 38 + units/user/paths.target | 12 + units/user/printer.target | 13 + units/user/shutdown.target | 14 + units/user/smartcard.target | 13 + units/user/sockets.target | 12 + units/user/sound.target | 13 + units/user/systemd-exit.service | 16 + units/user/systemd-tmpfiles-clean.service.in | 21 + units/user/systemd-tmpfiles-clean.timer | 19 + units/user/systemd-tmpfiles-setup.service.in | 25 + units/user/timers.target | 15 + units/user@.service.in | 27 + units/var-lib-machines.mount | 23 + xorg/50-systemd-user.sh | 7 + zanata.xml | 9 + 3466 files changed, 1270985 insertions(+) create mode 100644 .ctags create mode 100644 .dir-locals.el create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/Bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/Feature_request.md create mode 100644 .gitignore create mode 100644 .lgtm.yml create mode 100644 .lgtm/cpp-queries/PotentiallyDangerousFunction.ql create mode 100644 .mailmap create mode 100644 .mkosi/mkosi.arch create mode 100644 .mkosi/mkosi.debian create mode 100644 .mkosi/mkosi.fedora create mode 100644 .mkosi/mkosi.ubuntu create mode 100644 .travis.yml create mode 100644 .vimrc create mode 100644 .ycm_extra_conf.py create mode 100644 LICENSE.GPL2 create mode 100644 LICENSE.LGPL2.1 create mode 100644 Makefile create mode 100644 NEWS create mode 100644 README create mode 100644 README.md create mode 100644 TODO create mode 100644 azure-pipelines.yml create mode 100644 catalog/meson.build create mode 100644 catalog/systemd.be.catalog.in create mode 100644 catalog/systemd.be@latin.catalog.in create mode 100644 catalog/systemd.bg.catalog.in create mode 100644 catalog/systemd.catalog.in create mode 100644 catalog/systemd.da.catalog.in create mode 100644 catalog/systemd.de.catalog.in create mode 100644 catalog/systemd.fr.catalog.in create mode 100644 catalog/systemd.hr.catalog.in create mode 100644 catalog/systemd.hu.catalog.in create mode 100644 catalog/systemd.it.catalog.in create mode 100644 catalog/systemd.ko.catalog.in create mode 100644 catalog/systemd.pl.catalog.in create mode 100644 catalog/systemd.pt_BR.catalog.in create mode 100644 catalog/systemd.ru.catalog.in create mode 100644 catalog/systemd.sr.catalog.in create mode 100644 catalog/systemd.zh_CN.catalog.in create mode 100644 catalog/systemd.zh_TW.catalog.in create mode 100644 coccinelle/bool-cast.cocci create mode 100644 coccinelle/close-above-stdio.cocci create mode 100644 coccinelle/cmp.cocci create mode 100644 coccinelle/const-strlen.disabled create mode 100644 coccinelle/debug-logging.cocci create mode 100644 coccinelle/div-round-up.cocci create mode 100644 coccinelle/dup-fcntl.cocci create mode 100644 coccinelle/empty-or-dash.cocci create mode 100644 coccinelle/empty-or-root.cocci create mode 100644 coccinelle/empty-to-null.cocci create mode 100644 coccinelle/empty-to-root.cocci create mode 100644 coccinelle/enotsup.cocci create mode 100644 coccinelle/equals-null.cocci create mode 100644 coccinelle/errno.cocci create mode 100644 coccinelle/exit-0.cocci create mode 100644 coccinelle/flags-set.cocci create mode 100644 coccinelle/fopen-unlocked.cocci create mode 100644 coccinelle/free_and_replace.cocci create mode 100644 coccinelle/hashmap_free.cocci create mode 100644 coccinelle/htonl.cocci create mode 100644 coccinelle/in_set.cocci create mode 100644 coccinelle/iovec-make.cocci create mode 100644 coccinelle/isempty.cocci create mode 100644 coccinelle/log-json.cocci create mode 100644 coccinelle/malloc_multiply.cocci create mode 100644 coccinelle/memzero.cocci create mode 100644 coccinelle/mfree.cocci create mode 100644 coccinelle/mfree_return.cocci create mode 100644 coccinelle/no-if-assignments.cocci create mode 100644 coccinelle/not_in_set.cocci create mode 100644 coccinelle/o-ndelay.cocci create mode 100644 coccinelle/reallocarray.cocci create mode 100644 coccinelle/redundant-if.cocci create mode 100755 coccinelle/run-coccinelle.sh create mode 100644 coccinelle/safe_close-no-if.cocci create mode 100644 coccinelle/safe_close.cocci create mode 100644 coccinelle/safe_closedir.cocci create mode 100644 coccinelle/safe_fclose.cocci create mode 100644 coccinelle/sd_event_source_disable_unref.cocci create mode 100644 coccinelle/strempty.cocci create mode 100644 coccinelle/strjoin.cocci create mode 100644 coccinelle/strjoina.cocci create mode 100644 coccinelle/strv_free.cocci create mode 100644 coccinelle/swap-two.cocci create mode 100644 coccinelle/synthetic-errno.cocci create mode 100644 coccinelle/systemd-definitions.iso create mode 100644 coccinelle/take-fd.cocci create mode 100644 coccinelle/take-ptr.cocci create mode 100644 coccinelle/while-true.cocci create mode 100644 coccinelle/xsprintf.cocci create mode 100755 configure create mode 100644 docs/AUTOMATIC_BOOT_ASSESSMENT.md create mode 100644 docs/BLOCK_DEVICE_LOCKING.md create mode 100644 docs/BOOT_LOADER_INTERFACE.md create mode 100644 docs/BOOT_LOADER_SPECIFICATION.md create mode 100644 docs/CGROUP_DELEGATION.md create mode 100644 docs/CNAME create mode 100644 docs/CODE_OF_CONDUCT.md create mode 100644 docs/CODE_QUALITY.md create mode 100644 docs/CODING_STYLE.md create mode 100644 docs/CONTRIBUTING.md create mode 100644 docs/DISTRO_PORTING.md create mode 100644 docs/ENVIRONMENT.md create mode 100644 docs/HACKING.md create mode 100644 docs/PORTABLE_SERVICES.md create mode 100644 docs/PREDICTABLE_INTERFACE_NAMES.md create mode 100644 docs/RANDOM_SEEDS.md create mode 100644 docs/RELEASE.md create mode 100644 docs/SECURITY.md create mode 100644 docs/TEMPORARY_DIRECTORIES.md create mode 100644 docs/TESTING_WITH_SANITIZERS.md create mode 100644 docs/TRANSIENT-SETTINGS.md create mode 100644 docs/TRANSLATORS.md create mode 100644 docs/UIDS-GIDS.md create mode 100644 docs/_config.yml create mode 100644 docs/index.md create mode 100644 docs/sysvinit/README.in create mode 100644 docs/sysvinit/meson.build create mode 100644 docs/var-log/README create mode 100644 docs/var-log/meson.build create mode 100644 factory/etc/issue create mode 100644 factory/etc/nsswitch.conf create mode 100644 factory/etc/pam.d/other create mode 100644 factory/etc/pam.d/system-auth create mode 100644 fuzzbuzz.yaml create mode 100644 hwdb.d/.gitattributes create mode 100644 hwdb.d/.gitignore create mode 100644 hwdb.d/20-OUI.hwdb create mode 100644 hwdb.d/20-acpi-vendor.hwdb create mode 100644 hwdb.d/20-acpi-vendor.hwdb.patch create mode 100644 hwdb.d/20-bluetooth-vendor-product.hwdb create mode 100644 hwdb.d/20-net-ifname.hwdb create mode 100644 hwdb.d/20-pci-classes.hwdb create mode 100644 hwdb.d/20-pci-vendor-model.hwdb create mode 100644 hwdb.d/20-sdio-classes.hwdb create mode 100644 hwdb.d/20-sdio-vendor-model.hwdb create mode 100644 hwdb.d/20-usb-classes.hwdb create mode 100644 hwdb.d/20-usb-vendor-model.hwdb create mode 100644 hwdb.d/20-vmbus-class.hwdb create mode 100644 hwdb.d/60-evdev.hwdb create mode 100644 hwdb.d/60-input-id.hwdb create mode 100644 hwdb.d/60-keyboard.hwdb create mode 100644 hwdb.d/60-sensor.hwdb create mode 100644 hwdb.d/70-joystick.hwdb create mode 100644 hwdb.d/70-mouse.hwdb create mode 100644 hwdb.d/70-pointingstick.hwdb create mode 100644 hwdb.d/70-touchpad.hwdb create mode 100755 hwdb.d/acpi-update.py create mode 100644 hwdb.d/acpi_id_registry.html create mode 100755 hwdb.d/ids_parser.py create mode 100644 hwdb.d/ma-large.txt create mode 100644 hwdb.d/ma-medium.txt create mode 100644 hwdb.d/ma-small.txt create mode 100644 hwdb.d/meson.build create mode 100755 hwdb.d/parse_hwdb.py create mode 100644 hwdb.d/pci.ids create mode 100644 hwdb.d/pnp_id_registry.html create mode 100644 hwdb.d/sdio.ids create mode 100644 hwdb.d/usb.ids create mode 100644 man/.dir-locals.el create mode 100755 man/50-xdg-data-dirs.sh create mode 100755 man/90-rearrange-path.py create mode 100644 man/binfmt.d.xml create mode 100644 man/bootctl.xml create mode 100644 man/bootup.xml create mode 100644 man/busctl.xml create mode 100644 man/coredump.conf.xml create mode 100644 man/coredumpctl.xml create mode 100644 man/crypttab.xml create mode 100644 man/custom-entities.ent.in create mode 100644 man/custom-html.xsl create mode 100644 man/custom-man.xsl create mode 100644 man/daemon.xml create mode 100644 man/dnssec-trust-anchors.d.xml create mode 100644 man/environment.d.xml create mode 100644 man/file-hierarchy.xml create mode 100644 man/glib-event-glue.c create mode 100644 man/halt.xml create mode 100644 man/hostname.xml create mode 100644 man/hostnamectl.xml create mode 100755 man/html.in create mode 100644 man/hwdb.xml create mode 100644 man/id128-app-specific.c create mode 100644 man/inotify-watch-tmp.c create mode 100644 man/journal-iterate-poll.c create mode 100644 man/journal-iterate-unique.c create mode 100644 man/journal-iterate-wait.c create mode 100644 man/journal-remote.conf.xml create mode 100644 man/journal-upload.conf.xml create mode 100644 man/journalctl.xml create mode 100644 man/journald.conf.xml create mode 100644 man/kernel-command-line.xml create mode 100644 man/kernel-install.xml create mode 100644 man/less-variables.xml create mode 100644 man/libsystemd-pkgconfig.xml create mode 100644 man/libudev.xml create mode 100644 man/loader.conf.xml create mode 100644 man/locale.conf.xml create mode 100644 man/localectl.xml create mode 100644 man/localtime.xml create mode 100644 man/loginctl.xml create mode 100644 man/logind.conf.xml create mode 100644 man/machine-id.xml create mode 100644 man/machine-info.xml create mode 100644 man/machinectl.xml create mode 100755 man/man.in create mode 100644 man/meson.build create mode 100644 man/modules-load.d.xml create mode 100644 man/networkctl.xml create mode 100644 man/networkd.conf.xml create mode 100644 man/nss-myhostname.xml create mode 100644 man/nss-mymachines.xml create mode 100644 man/nss-resolve.xml create mode 100644 man/nss-systemd.xml create mode 100644 man/os-release.xml create mode 100644 man/pam_systemd.xml create mode 100644 man/portablectl.xml create mode 100644 man/print-unit-path.c create mode 100644 man/pstore.conf.xml create mode 100644 man/resolvectl.xml create mode 100644 man/resolved.conf.xml create mode 100644 man/rules/meson.build create mode 100644 man/runlevel.xml create mode 100644 man/sd-bus-errors.xml create mode 100644 man/sd-bus.xml create mode 100644 man/sd-daemon.xml create mode 100644 man/sd-event.xml create mode 100644 man/sd-id128.xml create mode 100644 man/sd-journal.xml create mode 100644 man/sd-login.xml create mode 100644 man/sd_booted.xml create mode 100644 man/sd_bus_add_match.xml create mode 100644 man/sd_bus_add_object_vtable.xml create mode 100644 man/sd_bus_attach_event.xml create mode 100644 man/sd_bus_close.xml create mode 100644 man/sd_bus_creds_get_pid.xml create mode 100644 man/sd_bus_creds_new_from_pid.xml create mode 100644 man/sd_bus_default.xml create mode 100644 man/sd_bus_error.xml create mode 100644 man/sd_bus_error_add_map.xml create mode 100644 man/sd_bus_get_fd.xml create mode 100644 man/sd_bus_get_n_queued_read.xml create mode 100644 man/sd_bus_is_open.xml create mode 100644 man/sd_bus_message_append.xml create mode 100644 man/sd_bus_message_append_array.xml create mode 100644 man/sd_bus_message_append_basic.xml create mode 100644 man/sd_bus_message_append_string_memfd.xml create mode 100644 man/sd_bus_message_append_strv.xml create mode 100644 man/sd_bus_message_copy.xml create mode 100644 man/sd_bus_message_get_cookie.xml create mode 100644 man/sd_bus_message_get_monotonic_usec.xml create mode 100644 man/sd_bus_message_get_signature.xml create mode 100644 man/sd_bus_message_get_type.xml create mode 100644 man/sd_bus_message_new.xml create mode 100644 man/sd_bus_message_new_method_call.xml create mode 100644 man/sd_bus_message_new_method_error.xml create mode 100644 man/sd_bus_message_new_signal.xml create mode 100644 man/sd_bus_message_read.xml create mode 100644 man/sd_bus_message_read_array.xml create mode 100644 man/sd_bus_message_read_basic.xml create mode 100644 man/sd_bus_message_rewind.xml create mode 100644 man/sd_bus_message_set_destination.xml create mode 100644 man/sd_bus_message_set_expect_reply.xml create mode 100644 man/sd_bus_message_skip.xml create mode 100644 man/sd_bus_message_verify_type.xml create mode 100644 man/sd_bus_negotiate_fds.xml create mode 100644 man/sd_bus_new.xml create mode 100644 man/sd_bus_path_encode.xml create mode 100644 man/sd_bus_process.xml create mode 100644 man/sd_bus_reply_method_error.xml create mode 100644 man/sd_bus_request_name.xml create mode 100644 man/sd_bus_set_close_on_exit.xml create mode 100644 man/sd_bus_set_connected_signal.xml create mode 100644 man/sd_bus_set_description.xml create mode 100644 man/sd_bus_set_sender.xml create mode 100644 man/sd_bus_set_watch_bind.xml create mode 100644 man/sd_bus_slot_ref.xml create mode 100644 man/sd_bus_slot_set_description.xml create mode 100644 man/sd_bus_slot_set_destroy_callback.xml create mode 100644 man/sd_bus_slot_set_floating.xml create mode 100644 man/sd_bus_slot_set_userdata.xml create mode 100644 man/sd_bus_track_add_name.xml create mode 100644 man/sd_bus_track_new.xml create mode 100644 man/sd_bus_wait.xml create mode 100644 man/sd_event_add_child.xml create mode 100644 man/sd_event_add_defer.xml create mode 100644 man/sd_event_add_inotify.xml create mode 100644 man/sd_event_add_io.xml create mode 100644 man/sd_event_add_signal.xml create mode 100644 man/sd_event_add_time.xml create mode 100644 man/sd_event_exit.xml create mode 100644 man/sd_event_get_fd.xml create mode 100644 man/sd_event_new.xml create mode 100644 man/sd_event_now.xml create mode 100644 man/sd_event_run.xml create mode 100644 man/sd_event_set_watchdog.xml create mode 100644 man/sd_event_source_get_event.xml create mode 100644 man/sd_event_source_get_pending.xml create mode 100644 man/sd_event_source_set_description.xml create mode 100644 man/sd_event_source_set_destroy_callback.xml create mode 100644 man/sd_event_source_set_enabled.xml create mode 100644 man/sd_event_source_set_floating.xml create mode 100644 man/sd_event_source_set_prepare.xml create mode 100644 man/sd_event_source_set_priority.xml create mode 100644 man/sd_event_source_set_userdata.xml create mode 100644 man/sd_event_source_unref.xml create mode 100644 man/sd_event_wait.xml create mode 100644 man/sd_get_seats.xml create mode 100644 man/sd_id128_get_machine.xml create mode 100644 man/sd_id128_randomize.xml create mode 100644 man/sd_id128_to_string.xml create mode 100644 man/sd_is_fifo.xml create mode 100644 man/sd_journal_add_match.xml create mode 100644 man/sd_journal_enumerate_fields.xml create mode 100644 man/sd_journal_get_catalog.xml create mode 100644 man/sd_journal_get_cursor.xml create mode 100644 man/sd_journal_get_cutoff_realtime_usec.xml create mode 100644 man/sd_journal_get_data.xml create mode 100644 man/sd_journal_get_fd.xml create mode 100644 man/sd_journal_get_realtime_usec.xml create mode 100644 man/sd_journal_get_usage.xml create mode 100644 man/sd_journal_has_runtime_files.xml create mode 100644 man/sd_journal_next.xml create mode 100644 man/sd_journal_open.xml create mode 100644 man/sd_journal_print.xml create mode 100644 man/sd_journal_query_unique.xml create mode 100644 man/sd_journal_seek_head.xml create mode 100644 man/sd_journal_stream_fd.xml create mode 100644 man/sd_listen_fds.xml create mode 100644 man/sd_login_monitor_new.xml create mode 100644 man/sd_machine_get_class.xml create mode 100644 man/sd_notify.xml create mode 100644 man/sd_pid_get_owner_uid.xml create mode 100644 man/sd_seat_get_active.xml create mode 100644 man/sd_session_is_active.xml create mode 100644 man/sd_uid_get_state.xml create mode 100644 man/sd_watchdog_enabled.xml create mode 100644 man/send-unit-files-changed.c create mode 100644 man/shutdown.xml create mode 100644 man/standard-conf.xml create mode 100644 man/standard-options.xml create mode 100644 man/sysctl.d.xml create mode 100644 man/system-only.xml create mode 100644 man/systemctl.xml create mode 100644 man/systemd-analyze.xml create mode 100644 man/systemd-ask-password-console.service.xml create mode 100644 man/systemd-ask-password.xml create mode 100644 man/systemd-backlight@.service.xml create mode 100644 man/systemd-binfmt.service.xml create mode 100644 man/systemd-bless-boot-generator.xml create mode 100644 man/systemd-bless-boot.service.xml create mode 100644 man/systemd-boot-check-no-failures.service.xml create mode 100644 man/systemd-boot-system-token.service.xml create mode 100644 man/systemd-boot.xml create mode 100644 man/systemd-cat.xml create mode 100644 man/systemd-cgls.xml create mode 100644 man/systemd-cgtop.xml create mode 100644 man/systemd-coredump.xml create mode 100644 man/systemd-cryptsetup-generator.xml create mode 100644 man/systemd-cryptsetup@.service.xml create mode 100644 man/systemd-debug-generator.xml create mode 100644 man/systemd-delta.xml create mode 100644 man/systemd-detect-virt.xml create mode 100644 man/systemd-environment-d-generator.xml create mode 100644 man/systemd-escape.xml create mode 100644 man/systemd-firstboot.xml create mode 100644 man/systemd-fsck@.service.xml create mode 100644 man/systemd-fstab-generator.xml create mode 100644 man/systemd-getty-generator.xml create mode 100644 man/systemd-gpt-auto-generator.xml create mode 100644 man/systemd-halt.service.xml create mode 100644 man/systemd-hibernate-resume-generator.xml create mode 100644 man/systemd-hibernate-resume@.service.xml create mode 100644 man/systemd-hostnamed.service.xml create mode 100644 man/systemd-hwdb.xml create mode 100644 man/systemd-id128.xml create mode 100644 man/systemd-importd.service.xml create mode 100644 man/systemd-inhibit.xml create mode 100644 man/systemd-initctl.service.xml create mode 100644 man/systemd-journal-gatewayd.service.xml create mode 100644 man/systemd-journal-remote.service.xml create mode 100644 man/systemd-journal-upload.service.xml create mode 100644 man/systemd-journald.service.xml create mode 100644 man/systemd-localed.service.xml create mode 100644 man/systemd-logind.service.xml create mode 100644 man/systemd-machine-id-commit.service.xml create mode 100644 man/systemd-machine-id-setup.xml create mode 100644 man/systemd-machined.service.xml create mode 100644 man/systemd-makefs@.service.xml create mode 100644 man/systemd-modules-load.service.xml create mode 100644 man/systemd-mount.xml create mode 100644 man/systemd-networkd-wait-online.service.xml create mode 100644 man/systemd-networkd.service.xml create mode 100644 man/systemd-notify.xml create mode 100644 man/systemd-nspawn.xml create mode 100644 man/systemd-path.xml create mode 100644 man/systemd-portabled.service.xml create mode 100644 man/systemd-pstore.xml create mode 100644 man/systemd-quotacheck.service.xml create mode 100644 man/systemd-random-seed.service.xml create mode 100644 man/systemd-rc-local-generator.xml create mode 100644 man/systemd-remount-fs.service.xml create mode 100644 man/systemd-resolved.service.xml create mode 100644 man/systemd-rfkill.service.xml create mode 100644 man/systemd-run-generator.xml create mode 100644 man/systemd-run.xml create mode 100644 man/systemd-sleep.conf.xml create mode 100644 man/systemd-socket-activate.xml create mode 100644 man/systemd-socket-proxyd.xml create mode 100644 man/systemd-suspend.service.xml create mode 100644 man/systemd-sysctl.service.xml create mode 100644 man/systemd-system-update-generator.xml create mode 100644 man/systemd-system.conf.xml create mode 100644 man/systemd-sysusers.xml create mode 100644 man/systemd-sysv-generator.xml create mode 100644 man/systemd-time-wait-sync.service.xml create mode 100644 man/systemd-timedated.service.xml create mode 100644 man/systemd-timesyncd.service.xml create mode 100644 man/systemd-tmpfiles.xml create mode 100644 man/systemd-tty-ask-password-agent.xml create mode 100644 man/systemd-udev-settle.service.xml create mode 100644 man/systemd-udevd.service.xml create mode 100644 man/systemd-update-done.service.xml create mode 100644 man/systemd-update-utmp.service.xml create mode 100644 man/systemd-user-sessions.service.xml create mode 100644 man/systemd-vconsole-setup.service.xml create mode 100644 man/systemd-veritysetup-generator.xml create mode 100644 man/systemd-veritysetup@.service.xml create mode 100644 man/systemd-volatile-root.service.xml create mode 100644 man/systemd.automount.xml create mode 100644 man/systemd.device.xml create mode 100644 man/systemd.dnssd.xml create mode 100644 man/systemd.environment-generator.xml create mode 100644 man/systemd.exec.xml create mode 100644 man/systemd.generator.xml create mode 100644 man/systemd.journal-fields.xml create mode 100644 man/systemd.kill.xml create mode 100644 man/systemd.link.xml create mode 100644 man/systemd.mount.xml create mode 100644 man/systemd.net-naming-scheme.xml create mode 100644 man/systemd.netdev.xml create mode 100644 man/systemd.network.xml create mode 100644 man/systemd.nspawn.xml create mode 100644 man/systemd.offline-updates.xml create mode 100644 man/systemd.path.xml create mode 100644 man/systemd.preset.xml create mode 100644 man/systemd.resource-control.xml create mode 100644 man/systemd.scope.xml create mode 100644 man/systemd.service.xml create mode 100644 man/systemd.slice.xml create mode 100644 man/systemd.socket.xml create mode 100644 man/systemd.special.xml create mode 100644 man/systemd.swap.xml create mode 100644 man/systemd.syntax.xml create mode 100644 man/systemd.target.xml create mode 100644 man/systemd.time.xml create mode 100644 man/systemd.timer.xml create mode 100644 man/systemd.unit.xml create mode 100644 man/systemd.xml create mode 100644 man/sysusers.d.xml create mode 100644 man/telinit.xml create mode 100644 man/threads-aware.xml create mode 100644 man/timedatectl.xml create mode 100644 man/timesyncd.conf.xml create mode 100644 man/tmpfiles.d.xml create mode 100644 man/udev.conf.xml create mode 100644 man/udev.xml create mode 100644 man/udev_device_get_syspath.xml create mode 100644 man/udev_device_has_tag.xml create mode 100644 man/udev_device_new_from_syspath.xml create mode 100644 man/udev_enumerate_add_match_subsystem.xml create mode 100644 man/udev_enumerate_new.xml create mode 100644 man/udev_enumerate_scan_devices.xml create mode 100644 man/udev_list_entry.xml create mode 100644 man/udev_monitor_filter_update.xml create mode 100644 man/udev_monitor_new_from_netlink.xml create mode 100644 man/udev_monitor_receive_device.xml create mode 100644 man/udev_new.xml create mode 100644 man/udevadm.xml create mode 100644 man/user-system-options.xml create mode 100644 man/user@.service.xml create mode 100644 man/vconsole.conf.xml create mode 100644 man/vtable-example.c create mode 100644 man/vtable-example.xml create mode 100644 meson.build create mode 100644 meson_options.txt create mode 100755 mkosi.build create mode 120000 mkosi.default create mode 100644 modprobe.d/systemd.conf create mode 100644 network/80-container-host0.network create mode 100644 network/80-container-ve.network create mode 100644 network/80-container-vz.network create mode 100644 network/80-wifi-adhoc.network create mode 100644 network/80-wifi-ap.network.example create mode 100644 network/80-wifi-station.network.example create mode 100644 network/99-default.link create mode 100644 network/meson.build create mode 100644 po/.gitignore create mode 100644 po/LINGUAS create mode 100644 po/POTFILES.in create mode 100644 po/POTFILES.skip create mode 100644 po/be.po create mode 100644 po/be@latin.po create mode 100644 po/bg.po create mode 100644 po/ca.po create mode 100644 po/cs.po create mode 100644 po/da.po create mode 100644 po/de.po create mode 100644 po/el.po create mode 100644 po/es.po create mode 100644 po/fr.po create mode 100644 po/gl.po create mode 100644 po/hr.po create mode 100644 po/hu.po create mode 100644 po/id.po create mode 100644 po/it.po create mode 100644 po/its/polkit.its create mode 100644 po/its/polkit.loc create mode 100644 po/ja.po create mode 100644 po/ko.po create mode 100644 po/lt.po create mode 100644 po/meson.build create mode 100644 po/pl.po create mode 100644 po/pt_BR.po create mode 100644 po/ro.po create mode 100644 po/ru.po create mode 100644 po/sk.po create mode 100644 po/sr.po create mode 100644 po/sv.po create mode 100644 po/tr.po create mode 100644 po/uk.po create mode 100644 po/zh_CN.po create mode 100644 po/zh_TW.po create mode 100644 presets/90-systemd.preset create mode 100644 presets/meson.build create mode 100644 presets/user/90-systemd.preset create mode 100644 rules.d/50-udev-default.rules.in create mode 100644 rules.d/60-block.rules create mode 100644 rules.d/60-cdrom_id.rules create mode 100644 rules.d/60-drm.rules create mode 100644 rules.d/60-evdev.rules create mode 100644 rules.d/60-fido-id.rules create mode 100644 rules.d/60-input-id.rules create mode 100644 rules.d/60-persistent-alsa.rules create mode 100644 rules.d/60-persistent-input.rules create mode 100644 rules.d/60-persistent-storage-tape.rules create mode 100644 rules.d/60-persistent-storage.rules create mode 100644 rules.d/60-persistent-v4l.rules create mode 100644 rules.d/60-sensor.rules create mode 100644 rules.d/60-serial.rules create mode 100644 rules.d/61-autosuspend-manual.rules create mode 100644 rules.d/64-btrfs.rules.in create mode 100644 rules.d/70-joystick.rules create mode 100644 rules.d/70-mouse.rules create mode 100644 rules.d/70-touchpad.rules create mode 100644 rules.d/75-net-description.rules create mode 100644 rules.d/75-probe_mtd.rules create mode 100644 rules.d/78-sound-card.rules create mode 100644 rules.d/80-drivers.rules create mode 100644 rules.d/80-net-setup-link.rules create mode 100644 rules.d/99-systemd.rules.in create mode 100644 rules.d/meson.build create mode 100755 semaphoreci/semaphore-runner.sh create mode 100644 shell-completion/bash/bootctl create mode 100644 shell-completion/bash/busctl create mode 100644 shell-completion/bash/coredumpctl create mode 100644 shell-completion/bash/hostnamectl create mode 100644 shell-completion/bash/journalctl create mode 100644 shell-completion/bash/kernel-install create mode 100644 shell-completion/bash/localectl create mode 100644 shell-completion/bash/loginctl create mode 100644 shell-completion/bash/machinectl create mode 100644 shell-completion/bash/meson.build create mode 100644 shell-completion/bash/networkctl create mode 100644 shell-completion/bash/portablectl create mode 100644 shell-completion/bash/resolvectl create mode 100644 shell-completion/bash/systemctl.in create mode 100644 shell-completion/bash/systemd-analyze create mode 100644 shell-completion/bash/systemd-cat create mode 100644 shell-completion/bash/systemd-cgls create mode 100644 shell-completion/bash/systemd-cgtop create mode 100644 shell-completion/bash/systemd-delta create mode 100644 shell-completion/bash/systemd-detect-virt create mode 100644 shell-completion/bash/systemd-id128 create mode 100644 shell-completion/bash/systemd-nspawn create mode 100644 shell-completion/bash/systemd-path create mode 100644 shell-completion/bash/systemd-resolve create mode 100644 shell-completion/bash/systemd-run create mode 100644 shell-completion/bash/timedatectl create mode 100644 shell-completion/bash/udevadm create mode 100644 shell-completion/zsh/_bootctl create mode 100644 shell-completion/zsh/_busctl create mode 100644 shell-completion/zsh/_coredumpctl create mode 100644 shell-completion/zsh/_hostnamectl create mode 100644 shell-completion/zsh/_journalctl create mode 100644 shell-completion/zsh/_kernel-install create mode 100644 shell-completion/zsh/_localectl create mode 100644 shell-completion/zsh/_loginctl create mode 100644 shell-completion/zsh/_machinectl create mode 100644 shell-completion/zsh/_networkctl create mode 100644 shell-completion/zsh/_resolvectl create mode 100644 shell-completion/zsh/_sd_hosts_or_user_at_host create mode 100644 shell-completion/zsh/_sd_machines create mode 100644 shell-completion/zsh/_sd_outputmodes create mode 100644 shell-completion/zsh/_sd_unit_files create mode 100644 shell-completion/zsh/_systemctl.in create mode 100644 shell-completion/zsh/_systemd create mode 100644 shell-completion/zsh/_systemd-analyze create mode 100644 shell-completion/zsh/_systemd-delta create mode 100644 shell-completion/zsh/_systemd-inhibit create mode 100644 shell-completion/zsh/_systemd-nspawn create mode 100644 shell-completion/zsh/_systemd-run create mode 100644 shell-completion/zsh/_systemd-tmpfiles create mode 100644 shell-completion/zsh/_timedatectl create mode 100644 shell-completion/zsh/_udevadm create mode 100644 shell-completion/zsh/meson.build create mode 100644 src/ac-power/ac-power.c create mode 100644 src/activate/activate.c create mode 100644 src/analyze/analyze-condition.c create mode 100644 src/analyze/analyze-condition.h create mode 100644 src/analyze/analyze-security.c create mode 100644 src/analyze/analyze-security.h create mode 100644 src/analyze/analyze-verify.c create mode 100644 src/analyze/analyze-verify.h create mode 100644 src/analyze/analyze.c create mode 100644 src/analyze/meson.build create mode 100644 src/ask-password/ask-password.c create mode 100644 src/backlight/backlight.c create mode 100644 src/basic/MurmurHash2.c create mode 100644 src/basic/MurmurHash2.h create mode 100644 src/basic/af-list.c create mode 100644 src/basic/af-list.h create mode 100644 src/basic/af-to-name.awk create mode 100644 src/basic/alloc-util.c create mode 100644 src/basic/alloc-util.h create mode 100644 src/basic/architecture.c create mode 100644 src/basic/architecture.h create mode 100644 src/basic/arphrd-list.c create mode 100644 src/basic/arphrd-list.h create mode 100644 src/basic/arphrd-to-name.awk create mode 100644 src/basic/async.c create mode 100644 src/basic/async.h create mode 100644 src/basic/audit-util.c create mode 100644 src/basic/audit-util.h create mode 100644 src/basic/blockdev-util.c create mode 100644 src/basic/blockdev-util.h create mode 100644 src/basic/btrfs-util.c create mode 100644 src/basic/btrfs-util.h create mode 100644 src/basic/build.h create mode 100644 src/basic/bus-label.c create mode 100644 src/basic/bus-label.h create mode 100644 src/basic/cap-list.c create mode 100644 src/basic/cap-list.h create mode 100644 src/basic/cap-to-name.awk create mode 100644 src/basic/capability-util.c create mode 100644 src/basic/capability-util.h create mode 100644 src/basic/cgroup-util.c create mode 100644 src/basic/cgroup-util.h create mode 100644 src/basic/chattr-util.c create mode 100644 src/basic/chattr-util.h create mode 100644 src/basic/conf-files.c create mode 100644 src/basic/conf-files.h create mode 100644 src/basic/copy.c create mode 100644 src/basic/copy.h create mode 100644 src/basic/def.h create mode 100644 src/basic/device-nodes.c create mode 100644 src/basic/device-nodes.h create mode 100644 src/basic/dirent-util.c create mode 100644 src/basic/dirent-util.h create mode 100644 src/basic/efivars.c create mode 100644 src/basic/efivars.h create mode 100644 src/basic/env-file.c create mode 100644 src/basic/env-file.h create mode 100644 src/basic/env-util.c create mode 100644 src/basic/env-util.h create mode 100644 src/basic/errno-list.c create mode 100644 src/basic/errno-list.h create mode 100644 src/basic/errno-to-name.awk create mode 100644 src/basic/errno-util.h create mode 100644 src/basic/escape.c create mode 100644 src/basic/escape.h create mode 100644 src/basic/ether-addr-util.c create mode 100644 src/basic/ether-addr-util.h create mode 100644 src/basic/extract-word.c create mode 100644 src/basic/extract-word.h create mode 100644 src/basic/fd-util.c create mode 100644 src/basic/fd-util.h create mode 100644 src/basic/fileio.c create mode 100644 src/basic/fileio.h create mode 100644 src/basic/format-util.c create mode 100644 src/basic/format-util.h create mode 100644 src/basic/fs-util.c create mode 100644 src/basic/fs-util.h create mode 100644 src/basic/gcrypt-util.c create mode 100644 src/basic/gcrypt-util.h create mode 100755 src/basic/generate-af-list.sh create mode 100755 src/basic/generate-arphrd-list.sh create mode 100755 src/basic/generate-cap-list.sh create mode 100755 src/basic/generate-errno-list.sh create mode 100644 src/basic/glob-util.c create mode 100644 src/basic/glob-util.h create mode 100644 src/basic/gunicode.c create mode 100644 src/basic/gunicode.h create mode 100644 src/basic/hash-funcs.c create mode 100644 src/basic/hash-funcs.h create mode 100644 src/basic/hashmap.c create mode 100644 src/basic/hashmap.h create mode 100644 src/basic/hexdecoct.c create mode 100644 src/basic/hexdecoct.h create mode 100644 src/basic/hostname-util.c create mode 100644 src/basic/hostname-util.h create mode 100644 src/basic/in-addr-util.c create mode 100644 src/basic/in-addr-util.h create mode 100644 src/basic/io-util.c create mode 100644 src/basic/io-util.h create mode 100644 src/basic/ioprio.h create mode 100644 src/basic/kbd-util.c create mode 100644 src/basic/kbd-util.h create mode 100644 src/basic/khash.c create mode 100644 src/basic/khash.h create mode 100644 src/basic/label.c create mode 100644 src/basic/label.h create mode 100644 src/basic/limits-util.c create mode 100644 src/basic/limits-util.h create mode 100644 src/basic/linux/README create mode 100644 src/basic/linux/btrfs.h create mode 100644 src/basic/linux/btrfs_tree.h create mode 100644 src/basic/linux/can/vxcan.h create mode 100644 src/basic/linux/fib_rules.h create mode 100644 src/basic/linux/fou.h create mode 100644 src/basic/linux/if.h create mode 100644 src/basic/linux/if_addr.h create mode 100644 src/basic/linux/if_arp.h create mode 100644 src/basic/linux/if_bonding.h create mode 100644 src/basic/linux/if_bridge.h create mode 100644 src/basic/linux/if_ether.h create mode 100644 src/basic/linux/if_link.h create mode 100644 src/basic/linux/if_macsec.h create mode 100644 src/basic/linux/if_tun.h create mode 100644 src/basic/linux/if_tunnel.h create mode 100644 src/basic/linux/in.h create mode 100644 src/basic/linux/in6.h create mode 100644 src/basic/linux/l2tp.h create mode 100644 src/basic/linux/libc-compat.h create mode 100644 src/basic/linux/netdevice.h create mode 100644 src/basic/linux/netlink.h create mode 100644 src/basic/linux/nexthop.h create mode 100644 src/basic/linux/pkt_sched.h create mode 100644 src/basic/linux/rtnetlink.h create mode 100755 src/basic/linux/update.sh create mode 100644 src/basic/linux/wireguard.h create mode 100644 src/basic/list.h create mode 100644 src/basic/locale-util.c create mode 100644 src/basic/locale-util.h create mode 100644 src/basic/log.c create mode 100644 src/basic/log.h create mode 100644 src/basic/login-util.c create mode 100644 src/basic/login-util.h create mode 100644 src/basic/macro.h create mode 100644 src/basic/memfd-util.c create mode 100644 src/basic/memfd-util.h create mode 100644 src/basic/memory-util.c create mode 100644 src/basic/memory-util.h create mode 100644 src/basic/mempool.c create mode 100644 src/basic/mempool.h create mode 100644 src/basic/meson.build create mode 100644 src/basic/missing_audit.h create mode 100644 src/basic/missing_capability.h create mode 100644 src/basic/missing_drm.h create mode 100644 src/basic/missing_fcntl.h create mode 100644 src/basic/missing_fs.h create mode 100644 src/basic/missing_input.h create mode 100644 src/basic/missing_keyctl.h create mode 100644 src/basic/missing_magic.h create mode 100644 src/basic/missing_mman.h create mode 100644 src/basic/missing_network.h create mode 100644 src/basic/missing_prctl.h create mode 100644 src/basic/missing_random.h create mode 100644 src/basic/missing_resource.h create mode 100644 src/basic/missing_sched.h create mode 100644 src/basic/missing_securebits.h create mode 100644 src/basic/missing_socket.h create mode 100644 src/basic/missing_stat.h create mode 100644 src/basic/missing_stdlib.h create mode 100644 src/basic/missing_syscall.h create mode 100644 src/basic/missing_timerfd.h create mode 100644 src/basic/missing_type.h create mode 100644 src/basic/mkdir-label.c create mode 100644 src/basic/mkdir.c create mode 100644 src/basic/mkdir.h create mode 100644 src/basic/mountpoint-util.c create mode 100644 src/basic/mountpoint-util.h create mode 100644 src/basic/namespace-util.c create mode 100644 src/basic/namespace-util.h create mode 100644 src/basic/nss-util.h create mode 100644 src/basic/nulstr-util.c create mode 100644 src/basic/nulstr-util.h create mode 100644 src/basic/ordered-set.c create mode 100644 src/basic/ordered-set.h create mode 100644 src/basic/parse-util.c create mode 100644 src/basic/parse-util.h create mode 100644 src/basic/path-util.c create mode 100644 src/basic/path-util.h create mode 100644 src/basic/prioq.c create mode 100644 src/basic/prioq.h create mode 100644 src/basic/proc-cmdline.c create mode 100644 src/basic/proc-cmdline.h create mode 100644 src/basic/process-util.c create mode 100644 src/basic/process-util.h create mode 100644 src/basic/procfs-util.c create mode 100644 src/basic/procfs-util.h create mode 100644 src/basic/random-util.c create mode 100644 src/basic/random-util.h create mode 100644 src/basic/ratelimit.c create mode 100644 src/basic/ratelimit.h create mode 100644 src/basic/raw-clone.h create mode 100644 src/basic/raw-reboot.h create mode 100644 src/basic/replace-var.c create mode 100644 src/basic/replace-var.h create mode 100644 src/basic/rlimit-util.c create mode 100644 src/basic/rlimit-util.h create mode 100644 src/basic/rm-rf.c create mode 100644 src/basic/rm-rf.h create mode 100644 src/basic/selinux-util.c create mode 100644 src/basic/selinux-util.h create mode 100644 src/basic/set.h create mode 100644 src/basic/sigbus.c create mode 100644 src/basic/sigbus.h create mode 100644 src/basic/signal-util.c create mode 100644 src/basic/signal-util.h create mode 100644 src/basic/siphash24.c create mode 100644 src/basic/siphash24.h create mode 100644 src/basic/smack-util.c create mode 100644 src/basic/smack-util.h create mode 100644 src/basic/socket-label.c create mode 100644 src/basic/socket-util.c create mode 100644 src/basic/socket-util.h create mode 100644 src/basic/sort-util.c create mode 100644 src/basic/sort-util.h create mode 100644 src/basic/sparse-endian.h create mode 100644 src/basic/special.h create mode 100644 src/basic/stat-util.c create mode 100644 src/basic/stat-util.h create mode 100644 src/basic/static-destruct.h create mode 100644 src/basic/stdio-util.h create mode 100644 src/basic/strbuf.c create mode 100644 src/basic/strbuf.h create mode 100644 src/basic/string-table.c create mode 100644 src/basic/string-table.h create mode 100644 src/basic/string-util.c create mode 100644 src/basic/string-util.h create mode 100644 src/basic/strv.c create mode 100644 src/basic/strv.h create mode 100644 src/basic/strxcpyx.c create mode 100644 src/basic/strxcpyx.h create mode 100644 src/basic/syslog-util.c create mode 100644 src/basic/syslog-util.h create mode 100644 src/basic/terminal-util.c create mode 100644 src/basic/terminal-util.h create mode 100644 src/basic/time-util.c create mode 100644 src/basic/time-util.h create mode 100644 src/basic/tmpfile-util.c create mode 100644 src/basic/tmpfile-util.h create mode 100644 src/basic/umask-util.h create mode 100644 src/basic/unaligned.h create mode 100644 src/basic/unit-def.c create mode 100644 src/basic/unit-def.h create mode 100644 src/basic/unit-name.c create mode 100644 src/basic/unit-name.h create mode 100644 src/basic/user-util.c create mode 100644 src/basic/user-util.h create mode 100644 src/basic/utf8.c create mode 100644 src/basic/utf8.h create mode 100644 src/basic/util.c create mode 100644 src/basic/util.h create mode 100644 src/basic/virt.c create mode 100644 src/basic/virt.h create mode 100644 src/basic/xattr-util.c create mode 100644 src/basic/xattr-util.h create mode 100644 src/binfmt/binfmt.c create mode 100644 src/boot/bless-boot-generator.c create mode 100644 src/boot/bless-boot.c create mode 100644 src/boot/boot-check-no-failures.c create mode 100644 src/boot/bootctl.c create mode 100644 src/boot/efi/boot.c create mode 100644 src/boot/efi/console.c create mode 100644 src/boot/efi/console.h create mode 100644 src/boot/efi/crc32.c create mode 100644 src/boot/efi/crc32.h create mode 100644 src/boot/efi/disk.c create mode 100644 src/boot/efi/disk.h create mode 100644 src/boot/efi/graphics.c create mode 100644 src/boot/efi/graphics.h create mode 100644 src/boot/efi/linux.c create mode 100644 src/boot/efi/linux.h create mode 100644 src/boot/efi/loader-features.h create mode 100644 src/boot/efi/measure.c create mode 100644 src/boot/efi/measure.h create mode 100644 src/boot/efi/meson.build create mode 100644 src/boot/efi/missing_efi.h create mode 100755 src/boot/efi/no-undefined-symbols.sh create mode 100644 src/boot/efi/pe.c create mode 100644 src/boot/efi/pe.h create mode 100644 src/boot/efi/random-seed.c create mode 100644 src/boot/efi/random-seed.h create mode 100644 src/boot/efi/sha256.c create mode 100644 src/boot/efi/sha256.h create mode 100644 src/boot/efi/shim.c create mode 100644 src/boot/efi/shim.h create mode 100644 src/boot/efi/splash.c create mode 100644 src/boot/efi/splash.h create mode 100644 src/boot/efi/stub.c create mode 100644 src/boot/efi/util.c create mode 100644 src/boot/efi/util.h create mode 100644 src/busctl/busctl-introspect.c create mode 100644 src/busctl/busctl-introspect.h create mode 100644 src/busctl/busctl.c create mode 100644 src/cgls/cgls.c create mode 100644 src/cgroups-agent/cgroups-agent.c create mode 100644 src/cgtop/cgtop.c create mode 100644 src/core/all-units.h create mode 100644 src/core/audit-fd.c create mode 100644 src/core/audit-fd.h create mode 100644 src/core/automount.c create mode 100644 src/core/automount.h create mode 100644 src/core/bpf-devices.c create mode 100644 src/core/bpf-devices.h create mode 100644 src/core/bpf-firewall.c create mode 100644 src/core/bpf-firewall.h create mode 100644 src/core/cgroup.c create mode 100644 src/core/cgroup.h create mode 100644 src/core/chown-recursive.c create mode 100644 src/core/chown-recursive.h create mode 100644 src/core/dbus-automount.c create mode 100644 src/core/dbus-automount.h create mode 100644 src/core/dbus-cgroup.c create mode 100644 src/core/dbus-cgroup.h create mode 100644 src/core/dbus-device.c create mode 100644 src/core/dbus-device.h create mode 100644 src/core/dbus-execute.c create mode 100644 src/core/dbus-execute.h create mode 100644 src/core/dbus-job.c create mode 100644 src/core/dbus-job.h create mode 100644 src/core/dbus-kill.c create mode 100644 src/core/dbus-kill.h create mode 100644 src/core/dbus-manager.c create mode 100644 src/core/dbus-manager.h create mode 100644 src/core/dbus-mount.c create mode 100644 src/core/dbus-mount.h create mode 100644 src/core/dbus-path.c create mode 100644 src/core/dbus-path.h create mode 100644 src/core/dbus-scope.c create mode 100644 src/core/dbus-scope.h create mode 100644 src/core/dbus-service.c create mode 100644 src/core/dbus-service.h create mode 100644 src/core/dbus-slice.c create mode 100644 src/core/dbus-slice.h create mode 100644 src/core/dbus-socket.c create mode 100644 src/core/dbus-socket.h create mode 100644 src/core/dbus-swap.c create mode 100644 src/core/dbus-swap.h create mode 100644 src/core/dbus-target.c create mode 100644 src/core/dbus-target.h create mode 100644 src/core/dbus-timer.c create mode 100644 src/core/dbus-timer.h create mode 100644 src/core/dbus-unit.c create mode 100644 src/core/dbus-unit.h create mode 100644 src/core/dbus-util.c create mode 100644 src/core/dbus-util.h create mode 100644 src/core/dbus.c create mode 100644 src/core/dbus.h create mode 100644 src/core/device.c create mode 100644 src/core/device.h create mode 100644 src/core/dynamic-user.c create mode 100644 src/core/dynamic-user.h create mode 100644 src/core/efi-random.c create mode 100644 src/core/efi-random.h create mode 100644 src/core/emergency-action.c create mode 100644 src/core/emergency-action.h create mode 100644 src/core/execute.c create mode 100644 src/core/execute.h create mode 100644 src/core/hostname-setup.c create mode 100644 src/core/hostname-setup.h create mode 100644 src/core/ima-setup.c create mode 100644 src/core/ima-setup.h create mode 100644 src/core/ip-address-access.c create mode 100644 src/core/ip-address-access.h create mode 100644 src/core/job.c create mode 100644 src/core/job.h create mode 100644 src/core/kill.c create mode 100644 src/core/kill.h create mode 100644 src/core/killall.c create mode 100644 src/core/killall.h create mode 100644 src/core/kmod-setup.c create mode 100644 src/core/kmod-setup.h create mode 100644 src/core/load-dropin.c create mode 100644 src/core/load-dropin.h create mode 100644 src/core/load-fragment-gperf-nulstr.awk create mode 100644 src/core/load-fragment-gperf.gperf.m4 create mode 100644 src/core/load-fragment.c create mode 100644 src/core/load-fragment.h create mode 100644 src/core/locale-setup.c create mode 100644 src/core/locale-setup.h create mode 100644 src/core/loopback-setup.c create mode 100644 src/core/loopback-setup.h create mode 100644 src/core/machine-id-setup.c create mode 100644 src/core/machine-id-setup.h create mode 100644 src/core/macros.systemd.in create mode 100644 src/core/main.c create mode 100644 src/core/manager.c create mode 100644 src/core/manager.h create mode 100644 src/core/meson.build create mode 100644 src/core/mount-setup.c create mode 100644 src/core/mount-setup.h create mode 100644 src/core/mount.c create mode 100644 src/core/mount.h create mode 100644 src/core/namespace.c create mode 100644 src/core/namespace.h create mode 100644 src/core/org.freedesktop.systemd1.conf create mode 100644 src/core/org.freedesktop.systemd1.policy.in create mode 100644 src/core/org.freedesktop.systemd1.service create mode 100644 src/core/path.c create mode 100644 src/core/path.h create mode 100644 src/core/scope.c create mode 100644 src/core/scope.h create mode 100644 src/core/selinux-access.c create mode 100644 src/core/selinux-access.h create mode 100644 src/core/selinux-setup.c create mode 100644 src/core/selinux-setup.h create mode 100644 src/core/service.c create mode 100644 src/core/service.h create mode 100644 src/core/show-status.c create mode 100644 src/core/show-status.h create mode 100644 src/core/slice.c create mode 100644 src/core/slice.h create mode 100644 src/core/smack-setup.c create mode 100644 src/core/smack-setup.h create mode 100644 src/core/socket.c create mode 100644 src/core/socket.h create mode 100644 src/core/swap.c create mode 100644 src/core/swap.h create mode 100644 src/core/system.conf.in create mode 100644 src/core/systemd.pc.in create mode 100644 src/core/target.c create mode 100644 src/core/target.h create mode 100644 src/core/timer.c create mode 100644 src/core/timer.h create mode 100644 src/core/transaction.c create mode 100644 src/core/transaction.h create mode 100644 src/core/triggers.systemd.in create mode 100644 src/core/unit-printf.c create mode 100644 src/core/unit-printf.h create mode 100644 src/core/unit.c create mode 100644 src/core/unit.h create mode 100644 src/core/user.conf.in create mode 100644 src/coredump/coredump-vacuum.c create mode 100644 src/coredump/coredump-vacuum.h create mode 100644 src/coredump/coredump.c create mode 100644 src/coredump/coredump.conf create mode 100644 src/coredump/coredumpctl.c create mode 100644 src/coredump/meson.build create mode 100644 src/coredump/stacktrace.c create mode 100644 src/coredump/stacktrace.h create mode 100644 src/coredump/test-coredump-vacuum.c create mode 100644 src/cryptsetup/cryptsetup-generator.c create mode 100644 src/cryptsetup/cryptsetup.c create mode 100644 src/debug-generator/debug-generator.c create mode 100644 src/delta/delta.c create mode 100644 src/detect-virt/detect-virt.c create mode 100644 src/dissect/dissect.c create mode 100644 src/environment-d-generator/environment-d-generator.c create mode 100644 src/escape/escape.c create mode 100644 src/firstboot/firstboot.c create mode 100644 src/fsck/fsck.c create mode 100644 src/fstab-generator/fstab-generator.c create mode 100644 src/fuzz/fuzz-bus-label.c create mode 100644 src/fuzz/fuzz-bus-message.c create mode 100644 src/fuzz/fuzz-calendarspec.c create mode 100644 src/fuzz/fuzz-catalog.c create mode 100644 src/fuzz/fuzz-compress.c create mode 100644 src/fuzz/fuzz-dhcp-server.c create mode 100644 src/fuzz/fuzz-dhcp-server.options create mode 100644 src/fuzz/fuzz-dhcp6-client.c create mode 100644 src/fuzz/fuzz-dhcp6-client.options create mode 100644 src/fuzz/fuzz-dns-packet.c create mode 100644 src/fuzz/fuzz-dns-packet.options create mode 100644 src/fuzz/fuzz-env-file.c create mode 100644 src/fuzz/fuzz-env-file.options create mode 100644 src/fuzz/fuzz-fido-id-desc.dict create mode 100644 src/fuzz/fuzz-hostname-util.c create mode 100644 src/fuzz/fuzz-journal-remote.c create mode 100644 src/fuzz/fuzz-journal-remote.options create mode 100644 src/fuzz/fuzz-journald-audit.c create mode 100644 src/fuzz/fuzz-journald-kmsg.c create mode 100644 src/fuzz/fuzz-journald-native-fd.c create mode 100644 src/fuzz/fuzz-journald-native.c create mode 100644 src/fuzz/fuzz-journald-stream.c create mode 100644 src/fuzz/fuzz-journald-stream.options create mode 100644 src/fuzz/fuzz-journald-syslog.c create mode 100644 src/fuzz/fuzz-journald.c create mode 100644 src/fuzz/fuzz-journald.h create mode 100644 src/fuzz/fuzz-json.c create mode 100644 src/fuzz/fuzz-lldp.c create mode 100644 src/fuzz/fuzz-lldp.options create mode 100644 src/fuzz/fuzz-main.c create mode 100644 src/fuzz/fuzz-ndisc-rs.c create mode 100644 src/fuzz/fuzz-ndisc-rs.options create mode 100644 src/fuzz/fuzz-nspawn-oci.c create mode 100644 src/fuzz/fuzz-nspawn-settings.c create mode 100644 src/fuzz/fuzz-time-util.c create mode 100644 src/fuzz/fuzz-udev-database.c create mode 100644 src/fuzz/fuzz-udev-rules.c create mode 100644 src/fuzz/fuzz-unit-file.c create mode 100644 src/fuzz/fuzz-varlink.c create mode 100644 src/fuzz/fuzz.h create mode 100644 src/fuzz/fuzzer-entry-point.c create mode 100644 src/fuzz/meson.build create mode 100644 src/getty-generator/getty-generator.c create mode 100644 src/gpt-auto-generator/gpt-auto-generator.c create mode 100644 src/hibernate-resume/hibernate-resume-generator.c create mode 100644 src/hibernate-resume/hibernate-resume.c create mode 100644 src/hostname/hostnamectl.c create mode 100644 src/hostname/hostnamed.c create mode 100644 src/hostname/meson.build create mode 100644 src/hostname/org.freedesktop.hostname1.conf create mode 100644 src/hostname/org.freedesktop.hostname1.policy create mode 100644 src/hostname/org.freedesktop.hostname1.service create mode 100644 src/hwdb/hwdb.c create mode 100644 src/id128/id128.c create mode 100644 src/import/curl-util.c create mode 100644 src/import/curl-util.h create mode 100644 src/import/export-raw.c create mode 100644 src/import/export-raw.h create mode 100644 src/import/export-tar.c create mode 100644 src/import/export-tar.h create mode 100644 src/import/export.c create mode 100644 src/import/import-common.c create mode 100644 src/import/import-common.h create mode 100644 src/import/import-compress.c create mode 100644 src/import/import-compress.h create mode 100644 src/import/import-fs.c create mode 100644 src/import/import-pubring.gpg create mode 100644 src/import/import-raw.c create mode 100644 src/import/import-raw.h create mode 100644 src/import/import-tar.c create mode 100644 src/import/import-tar.h create mode 100644 src/import/import.c create mode 100644 src/import/importd.c create mode 100644 src/import/meson.build create mode 100644 src/import/org.freedesktop.import1.conf create mode 100644 src/import/org.freedesktop.import1.policy create mode 100644 src/import/org.freedesktop.import1.service create mode 100644 src/import/pull-common.c create mode 100644 src/import/pull-common.h create mode 100644 src/import/pull-job.c create mode 100644 src/import/pull-job.h create mode 100644 src/import/pull-raw.c create mode 100644 src/import/pull-raw.h create mode 100644 src/import/pull-tar.c create mode 100644 src/import/pull-tar.h create mode 100644 src/import/pull.c create mode 100644 src/import/qcow2-util.c create mode 100644 src/import/qcow2-util.h create mode 100644 src/import/test-qcow2.c create mode 100644 src/initctl/initctl.c create mode 100644 src/journal-remote/browse.html create mode 100644 src/journal-remote/journal-gatewayd.c create mode 100644 src/journal-remote/journal-remote-main.c create mode 100644 src/journal-remote/journal-remote-parse.c create mode 100644 src/journal-remote/journal-remote-parse.h create mode 100644 src/journal-remote/journal-remote-write.c create mode 100644 src/journal-remote/journal-remote-write.h create mode 100644 src/journal-remote/journal-remote.c create mode 100644 src/journal-remote/journal-remote.conf.in create mode 100644 src/journal-remote/journal-remote.h create mode 100644 src/journal-remote/journal-upload-journal.c create mode 100644 src/journal-remote/journal-upload.c create mode 100644 src/journal-remote/journal-upload.conf.in create mode 100644 src/journal-remote/journal-upload.h create mode 100755 src/journal-remote/log-generator.py create mode 100644 src/journal-remote/meson.build create mode 100644 src/journal-remote/microhttpd-util.c create mode 100644 src/journal-remote/microhttpd-util.h create mode 100644 src/journal/audit-type.c create mode 100644 src/journal/audit-type.h create mode 100644 src/journal/audit_type-to-name.awk create mode 100644 src/journal/cat.c create mode 100644 src/journal/catalog.c create mode 100644 src/journal/catalog.h create mode 100644 src/journal/compress.c create mode 100644 src/journal/compress.h create mode 100644 src/journal/fsprg.c create mode 100644 src/journal/fsprg.h create mode 100755 src/journal/generate-audit_type-list.sh create mode 100644 src/journal/journal-authenticate.c create mode 100644 src/journal/journal-authenticate.h create mode 100644 src/journal/journal-def.h create mode 100644 src/journal/journal-file.c create mode 100644 src/journal/journal-file.h create mode 100644 src/journal/journal-internal.h create mode 100644 src/journal/journal-qrcode.c create mode 100644 src/journal/journal-qrcode.h create mode 100644 src/journal/journal-send.c create mode 100644 src/journal/journal-vacuum.c create mode 100644 src/journal/journal-vacuum.h create mode 100644 src/journal/journal-verify.c create mode 100644 src/journal/journal-verify.h create mode 100644 src/journal/journalctl.c create mode 100644 src/journal/journald-audit.c create mode 100644 src/journal/journald-audit.h create mode 100644 src/journal/journald-console.c create mode 100644 src/journal/journald-console.h create mode 100644 src/journal/journald-context.c create mode 100644 src/journal/journald-context.h create mode 100644 src/journal/journald-gperf.gperf create mode 100644 src/journal/journald-kmsg.c create mode 100644 src/journal/journald-kmsg.h create mode 100644 src/journal/journald-native.c create mode 100644 src/journal/journald-native.h create mode 100644 src/journal/journald-rate-limit.c create mode 100644 src/journal/journald-rate-limit.h create mode 100644 src/journal/journald-server.c create mode 100644 src/journal/journald-server.h create mode 100644 src/journal/journald-stream.c create mode 100644 src/journal/journald-stream.h create mode 100644 src/journal/journald-syslog.c create mode 100644 src/journal/journald-syslog.h create mode 100644 src/journal/journald-wall.c create mode 100644 src/journal/journald-wall.h create mode 100644 src/journal/journald.c create mode 100644 src/journal/journald.conf create mode 100644 src/journal/lookup3.c create mode 100644 src/journal/lookup3.h create mode 100644 src/journal/meson.build create mode 100644 src/journal/mmap-cache.c create mode 100644 src/journal/mmap-cache.h create mode 100644 src/journal/sd-journal.c create mode 100644 src/journal/test-audit-type.c create mode 100644 src/journal/test-catalog.c create mode 100644 src/journal/test-compress-benchmark.c create mode 100644 src/journal/test-compress.c create mode 100644 src/journal/test-journal-config.c create mode 100644 src/journal/test-journal-enum.c create mode 100644 src/journal/test-journal-flush.c create mode 100644 src/journal/test-journal-init.c create mode 100644 src/journal/test-journal-interleaving.c create mode 100644 src/journal/test-journal-match.c create mode 100644 src/journal/test-journal-send.c create mode 100644 src/journal/test-journal-stream.c create mode 100644 src/journal/test-journal-syslog.c create mode 100644 src/journal/test-journal-verify.c create mode 100644 src/journal/test-journal.c create mode 100644 src/journal/test-mmap-cache.c create mode 100644 src/kernel-install/00-entry-directory.install create mode 100644 src/kernel-install/50-depmod.install create mode 100644 src/kernel-install/90-loaderentry.install create mode 100644 src/kernel-install/kernel-install create mode 100644 src/kernel-install/meson.build create mode 100644 src/libsystemd-network/arp-util.c create mode 100644 src/libsystemd-network/arp-util.h create mode 100644 src/libsystemd-network/dhcp-client-internal.h create mode 100644 src/libsystemd-network/dhcp-identifier.c create mode 100644 src/libsystemd-network/dhcp-identifier.h create mode 100644 src/libsystemd-network/dhcp-internal.h create mode 100644 src/libsystemd-network/dhcp-lease-internal.h create mode 100644 src/libsystemd-network/dhcp-network.c create mode 100644 src/libsystemd-network/dhcp-option.c create mode 100644 src/libsystemd-network/dhcp-packet.c create mode 100644 src/libsystemd-network/dhcp-protocol.h create mode 100644 src/libsystemd-network/dhcp-server-internal.h create mode 100644 src/libsystemd-network/dhcp6-internal.h create mode 100644 src/libsystemd-network/dhcp6-lease-internal.h create mode 100644 src/libsystemd-network/dhcp6-network.c create mode 100644 src/libsystemd-network/dhcp6-option.c create mode 100644 src/libsystemd-network/dhcp6-protocol.h create mode 100644 src/libsystemd-network/icmp6-util.c create mode 100644 src/libsystemd-network/icmp6-util.h create mode 100644 src/libsystemd-network/lldp-internal.h create mode 100644 src/libsystemd-network/lldp-neighbor.c create mode 100644 src/libsystemd-network/lldp-neighbor.h create mode 100644 src/libsystemd-network/lldp-network.c create mode 100644 src/libsystemd-network/lldp-network.h create mode 100644 src/libsystemd-network/meson.build create mode 100644 src/libsystemd-network/ndisc-internal.h create mode 100644 src/libsystemd-network/ndisc-router.c create mode 100644 src/libsystemd-network/ndisc-router.h create mode 100644 src/libsystemd-network/network-internal.c create mode 100644 src/libsystemd-network/network-internal.h create mode 100644 src/libsystemd-network/radv-internal.h create mode 100644 src/libsystemd-network/sd-dhcp-client.c create mode 100644 src/libsystemd-network/sd-dhcp-lease.c create mode 100644 src/libsystemd-network/sd-dhcp-server.c create mode 100644 src/libsystemd-network/sd-dhcp6-client.c create mode 100644 src/libsystemd-network/sd-dhcp6-lease.c create mode 100644 src/libsystemd-network/sd-ipv4acd.c create mode 100644 src/libsystemd-network/sd-ipv4ll.c create mode 100644 src/libsystemd-network/sd-lldp.c create mode 100644 src/libsystemd-network/sd-ndisc.c create mode 100644 src/libsystemd-network/sd-radv.c create mode 100644 src/libsystemd-network/test-acd.c create mode 100644 src/libsystemd-network/test-dhcp-client.c create mode 100644 src/libsystemd-network/test-dhcp-option.c create mode 100644 src/libsystemd-network/test-dhcp-server.c create mode 100644 src/libsystemd-network/test-dhcp6-client.c create mode 100644 src/libsystemd-network/test-ipv4ll-manual.c create mode 100644 src/libsystemd-network/test-ipv4ll.c create mode 100644 src/libsystemd-network/test-lldp.c create mode 100644 src/libsystemd-network/test-ndisc-ra.c create mode 100644 src/libsystemd-network/test-ndisc-rs.c create mode 100644 src/libsystemd-network/test-sd-dhcp-lease.c create mode 100644 src/libsystemd/disable-mempool.c create mode 100644 src/libsystemd/libsystemd.pc.in create mode 100644 src/libsystemd/libsystemd.sym create mode 100644 src/libsystemd/meson.build create mode 100644 src/libsystemd/sd-bus/GVARIANT-SERIALIZATION create mode 100644 src/libsystemd/sd-bus/bus-common-errors.c create mode 100644 src/libsystemd/sd-bus/bus-common-errors.h create mode 100644 src/libsystemd/sd-bus/bus-container.c create mode 100644 src/libsystemd/sd-bus/bus-container.h create mode 100644 src/libsystemd/sd-bus/bus-control.c create mode 100644 src/libsystemd/sd-bus/bus-control.h create mode 100644 src/libsystemd/sd-bus/bus-convenience.c create mode 100644 src/libsystemd/sd-bus/bus-creds.c create mode 100644 src/libsystemd/sd-bus/bus-creds.h create mode 100644 src/libsystemd/sd-bus/bus-dump.c create mode 100644 src/libsystemd/sd-bus/bus-dump.h create mode 100644 src/libsystemd/sd-bus/bus-error.c create mode 100644 src/libsystemd/sd-bus/bus-error.h create mode 100644 src/libsystemd/sd-bus/bus-gvariant.c create mode 100644 src/libsystemd/sd-bus/bus-gvariant.h create mode 100644 src/libsystemd/sd-bus/bus-internal.c create mode 100644 src/libsystemd/sd-bus/bus-internal.h create mode 100644 src/libsystemd/sd-bus/bus-introspect.c create mode 100644 src/libsystemd/sd-bus/bus-introspect.h create mode 100644 src/libsystemd/sd-bus/bus-kernel.c create mode 100644 src/libsystemd/sd-bus/bus-kernel.h create mode 100644 src/libsystemd/sd-bus/bus-match.c create mode 100644 src/libsystemd/sd-bus/bus-match.h create mode 100644 src/libsystemd/sd-bus/bus-message.c create mode 100644 src/libsystemd/sd-bus/bus-message.h create mode 100644 src/libsystemd/sd-bus/bus-objects.c create mode 100644 src/libsystemd/sd-bus/bus-objects.h create mode 100644 src/libsystemd/sd-bus/bus-protocol.h create mode 100644 src/libsystemd/sd-bus/bus-signature.c create mode 100644 src/libsystemd/sd-bus/bus-signature.h create mode 100644 src/libsystemd/sd-bus/bus-slot.c create mode 100644 src/libsystemd/sd-bus/bus-slot.h create mode 100644 src/libsystemd/sd-bus/bus-socket.c create mode 100644 src/libsystemd/sd-bus/bus-socket.h create mode 100644 src/libsystemd/sd-bus/bus-track.c create mode 100644 src/libsystemd/sd-bus/bus-track.h create mode 100644 src/libsystemd/sd-bus/bus-type.c create mode 100644 src/libsystemd/sd-bus/bus-type.h create mode 100644 src/libsystemd/sd-bus/sd-bus.c create mode 100644 src/libsystemd/sd-bus/test-bus-address.c create mode 100644 src/libsystemd/sd-bus/test-bus-benchmark.c create mode 100644 src/libsystemd/sd-bus/test-bus-chat.c create mode 100644 src/libsystemd/sd-bus/test-bus-cleanup.c create mode 100644 src/libsystemd/sd-bus/test-bus-creds.c create mode 100644 src/libsystemd/sd-bus/test-bus-error.c create mode 100644 src/libsystemd/sd-bus/test-bus-gvariant.c create mode 100644 src/libsystemd/sd-bus/test-bus-introspect.c create mode 100644 src/libsystemd/sd-bus/test-bus-marshal.c create mode 100644 src/libsystemd/sd-bus/test-bus-match.c create mode 100644 src/libsystemd/sd-bus/test-bus-objects.c create mode 100644 src/libsystemd/sd-bus/test-bus-queue-ref-cycle.c create mode 100644 src/libsystemd/sd-bus/test-bus-server.c create mode 100644 src/libsystemd/sd-bus/test-bus-signature.c create mode 100644 src/libsystemd/sd-bus/test-bus-track.c create mode 120000 src/libsystemd/sd-bus/test-bus-vtable-cc.cc create mode 100644 src/libsystemd/sd-bus/test-bus-vtable.c create mode 100644 src/libsystemd/sd-bus/test-bus-watch-bind.c create mode 100644 src/libsystemd/sd-bus/test-vtable-data.h create mode 100644 src/libsystemd/sd-daemon/sd-daemon.c create mode 100644 src/libsystemd/sd-device/device-enumerator-private.h create mode 100644 src/libsystemd/sd-device/device-enumerator.c create mode 100644 src/libsystemd/sd-device/device-internal.h create mode 100644 src/libsystemd/sd-device/device-monitor-private.h create mode 100644 src/libsystemd/sd-device/device-monitor.c create mode 100644 src/libsystemd/sd-device/device-private.c create mode 100644 src/libsystemd/sd-device/device-private.h create mode 100644 src/libsystemd/sd-device/device-util.h create mode 100644 src/libsystemd/sd-device/sd-device.c create mode 100644 src/libsystemd/sd-device/test-sd-device-monitor.c create mode 100644 src/libsystemd/sd-device/test-sd-device-thread.c create mode 100644 src/libsystemd/sd-device/test-sd-device.c create mode 100644 src/libsystemd/sd-device/test-udev-device-thread.c create mode 100644 src/libsystemd/sd-event/event-source.h create mode 100644 src/libsystemd/sd-event/event-util.c create mode 100644 src/libsystemd/sd-event/event-util.h create mode 100644 src/libsystemd/sd-event/sd-event.c create mode 100644 src/libsystemd/sd-event/test-event.c create mode 100644 src/libsystemd/sd-hwdb/hwdb-internal.h create mode 100644 src/libsystemd/sd-hwdb/hwdb-util.c create mode 100644 src/libsystemd/sd-hwdb/hwdb-util.h create mode 100644 src/libsystemd/sd-hwdb/sd-hwdb.c create mode 100644 src/libsystemd/sd-id128/id128-util.c create mode 100644 src/libsystemd/sd-id128/id128-util.h create mode 100644 src/libsystemd/sd-id128/sd-id128.c create mode 100644 src/libsystemd/sd-login/sd-login.c create mode 100644 src/libsystemd/sd-login/test-login.c create mode 100644 src/libsystemd/sd-netlink/generic-netlink.c create mode 100644 src/libsystemd/sd-netlink/generic-netlink.h create mode 100644 src/libsystemd/sd-netlink/netlink-internal.h create mode 100644 src/libsystemd/sd-netlink/netlink-message.c create mode 100644 src/libsystemd/sd-netlink/netlink-slot.c create mode 100644 src/libsystemd/sd-netlink/netlink-slot.h create mode 100644 src/libsystemd/sd-netlink/netlink-socket.c create mode 100644 src/libsystemd/sd-netlink/netlink-types.c create mode 100644 src/libsystemd/sd-netlink/netlink-types.h create mode 100644 src/libsystemd/sd-netlink/netlink-util.c create mode 100644 src/libsystemd/sd-netlink/netlink-util.h create mode 100644 src/libsystemd/sd-netlink/rtnl-message.c create mode 100644 src/libsystemd/sd-netlink/sd-netlink.c create mode 100644 src/libsystemd/sd-netlink/test-netlink.c create mode 100644 src/libsystemd/sd-network/network-util.c create mode 100644 src/libsystemd/sd-network/network-util.h create mode 100644 src/libsystemd/sd-network/sd-network.c create mode 100644 src/libsystemd/sd-path/sd-path.c create mode 100644 src/libsystemd/sd-resolve/resolve-private.h create mode 100644 src/libsystemd/sd-resolve/sd-resolve.c create mode 100644 src/libsystemd/sd-resolve/test-resolve.c create mode 100644 src/libsystemd/sd-utf8/sd-utf8.c create mode 100644 src/libudev/libudev-device-internal.h create mode 100644 src/libudev/libudev-device.c create mode 100644 src/libudev/libudev-enumerate.c create mode 100644 src/libudev/libudev-hwdb.c create mode 100644 src/libudev/libudev-list-internal.h create mode 100644 src/libudev/libudev-list.c create mode 100644 src/libudev/libudev-monitor.c create mode 100644 src/libudev/libudev-queue.c create mode 100644 src/libudev/libudev-util.c create mode 100644 src/libudev/libudev-util.h create mode 100644 src/libudev/libudev.c create mode 100644 src/libudev/libudev.h create mode 100644 src/libudev/libudev.pc.in create mode 100644 src/libudev/libudev.sym create mode 100644 src/libudev/meson.build create mode 100644 src/locale/kbd-model-map create mode 100644 src/locale/keymap-util.c create mode 100644 src/locale/keymap-util.h create mode 100644 src/locale/language-fallback-map create mode 100644 src/locale/localectl.c create mode 100644 src/locale/localed.c create mode 100644 src/locale/meson.build create mode 100644 src/locale/org.freedesktop.locale1.conf create mode 100644 src/locale/org.freedesktop.locale1.policy create mode 100644 src/locale/org.freedesktop.locale1.service create mode 100644 src/locale/test-keymap-util.c create mode 100644 src/login/70-power-switch.rules create mode 100644 src/login/70-uaccess.rules.m4 create mode 100644 src/login/71-seat.rules.in create mode 100644 src/login/73-seat-late.rules.m4 create mode 100644 src/login/inhibit.c create mode 100644 src/login/loginctl.c create mode 100644 src/login/logind-acl.c create mode 100644 src/login/logind-acl.h create mode 100644 src/login/logind-action.c create mode 100644 src/login/logind-action.h create mode 100644 src/login/logind-brightness.c create mode 100644 src/login/logind-brightness.h create mode 100644 src/login/logind-button.c create mode 100644 src/login/logind-button.h create mode 100644 src/login/logind-core.c create mode 100644 src/login/logind-dbus.c create mode 100644 src/login/logind-dbus.h create mode 100644 src/login/logind-device.c create mode 100644 src/login/logind-device.h create mode 100644 src/login/logind-gperf.gperf create mode 100644 src/login/logind-inhibit.c create mode 100644 src/login/logind-inhibit.h create mode 100644 src/login/logind-seat-dbus.c create mode 100644 src/login/logind-seat-dbus.h create mode 100644 src/login/logind-seat.c create mode 100644 src/login/logind-seat.h create mode 100644 src/login/logind-session-dbus.c create mode 100644 src/login/logind-session-dbus.h create mode 100644 src/login/logind-session-device.c create mode 100644 src/login/logind-session-device.h create mode 100644 src/login/logind-session.c create mode 100644 src/login/logind-session.h create mode 100644 src/login/logind-user-dbus.c create mode 100644 src/login/logind-user-dbus.h create mode 100644 src/login/logind-user.c create mode 100644 src/login/logind-user.h create mode 100644 src/login/logind-utmp.c create mode 100644 src/login/logind.c create mode 100644 src/login/logind.conf.in create mode 100644 src/login/logind.h create mode 100644 src/login/meson.build create mode 100644 src/login/org.freedesktop.login1.conf create mode 100644 src/login/org.freedesktop.login1.policy create mode 100644 src/login/org.freedesktop.login1.service create mode 100644 src/login/pam_systemd.c create mode 100644 src/login/pam_systemd.sym create mode 100644 src/login/sysfs-show.c create mode 100644 src/login/sysfs-show.h create mode 100644 src/login/systemd-user.m4 create mode 100644 src/login/test-inhibit.c create mode 100644 src/login/test-login-shared.c create mode 100644 src/login/test-login-tables.c create mode 100644 src/login/user-runtime-dir.c create mode 100644 src/machine-id-setup/machine-id-setup-main.c create mode 100644 src/machine/image-dbus.c create mode 100644 src/machine/image-dbus.h create mode 100644 src/machine/machine-dbus.c create mode 100644 src/machine/machine-dbus.h create mode 100644 src/machine/machine.c create mode 100644 src/machine/machine.h create mode 100644 src/machine/machinectl.c create mode 100644 src/machine/machined-core.c create mode 100644 src/machine/machined-dbus.c create mode 100644 src/machine/machined.c create mode 100644 src/machine/machined.h create mode 100644 src/machine/meson.build create mode 100644 src/machine/operation.c create mode 100644 src/machine/operation.h create mode 100644 src/machine/org.freedesktop.machine1.conf create mode 100644 src/machine/org.freedesktop.machine1.policy create mode 100644 src/machine/org.freedesktop.machine1.service create mode 100644 src/machine/test-machine-tables.c create mode 100644 src/modules-load/modules-load.c create mode 100644 src/mount/mount-tool.c create mode 100644 src/network/fuzz-netdev-parser.c create mode 100644 src/network/fuzz-network-parser.c create mode 100644 src/network/fuzz-network-parser.options create mode 100644 src/network/generator/main.c create mode 100644 src/network/generator/network-generator.c create mode 100644 src/network/generator/network-generator.h create mode 100644 src/network/generator/test-network-generator.c create mode 100644 src/network/meson.build create mode 100644 src/network/netdev/bond.c create mode 100644 src/network/netdev/bond.h create mode 100644 src/network/netdev/bridge.c create mode 100644 src/network/netdev/bridge.h create mode 100644 src/network/netdev/dummy.c create mode 100644 src/network/netdev/dummy.h create mode 100644 src/network/netdev/fou-tunnel.c create mode 100644 src/network/netdev/fou-tunnel.h create mode 100644 src/network/netdev/geneve.c create mode 100644 src/network/netdev/geneve.h create mode 100644 src/network/netdev/ipvlan.c create mode 100644 src/network/netdev/ipvlan.h create mode 100644 src/network/netdev/l2tp-tunnel.c create mode 100644 src/network/netdev/l2tp-tunnel.h create mode 100644 src/network/netdev/macsec.c create mode 100644 src/network/netdev/macsec.h create mode 100644 src/network/netdev/macvlan.c create mode 100644 src/network/netdev/macvlan.h create mode 100644 src/network/netdev/netdev-gperf.gperf create mode 100644 src/network/netdev/netdev.c create mode 100644 src/network/netdev/netdev.h create mode 100644 src/network/netdev/netdevsim.c create mode 100644 src/network/netdev/netdevsim.h create mode 100644 src/network/netdev/nlmon.c create mode 100644 src/network/netdev/nlmon.h create mode 100644 src/network/netdev/tunnel.c create mode 100644 src/network/netdev/tunnel.h create mode 100644 src/network/netdev/tuntap.c create mode 100644 src/network/netdev/tuntap.h create mode 100644 src/network/netdev/vcan.c create mode 100644 src/network/netdev/vcan.h create mode 100644 src/network/netdev/veth.c create mode 100644 src/network/netdev/veth.h create mode 100644 src/network/netdev/vlan.c create mode 100644 src/network/netdev/vlan.h create mode 100644 src/network/netdev/vrf.c create mode 100644 src/network/netdev/vrf.h create mode 100644 src/network/netdev/vxcan.c create mode 100644 src/network/netdev/vxcan.h create mode 100644 src/network/netdev/vxlan.c create mode 100644 src/network/netdev/vxlan.h create mode 100644 src/network/netdev/wireguard.c create mode 100644 src/network/netdev/wireguard.h create mode 100644 src/network/netdev/xfrm.c create mode 100644 src/network/netdev/xfrm.h create mode 100644 src/network/networkctl.c create mode 100644 src/network/networkd-address-label.c create mode 100644 src/network/networkd-address-label.h create mode 100644 src/network/networkd-address-pool.c create mode 100644 src/network/networkd-address-pool.h create mode 100644 src/network/networkd-address.c create mode 100644 src/network/networkd-address.h create mode 100644 src/network/networkd-brvlan.c create mode 100644 src/network/networkd-brvlan.h create mode 100644 src/network/networkd-can.c create mode 100644 src/network/networkd-can.h create mode 100644 src/network/networkd-conf.c create mode 100644 src/network/networkd-conf.h create mode 100644 src/network/networkd-dhcp-common.c create mode 100644 src/network/networkd-dhcp-common.h create mode 100644 src/network/networkd-dhcp-server.c create mode 100644 src/network/networkd-dhcp-server.h create mode 100644 src/network/networkd-dhcp4.c create mode 100644 src/network/networkd-dhcp4.h create mode 100644 src/network/networkd-dhcp6.c create mode 100644 src/network/networkd-dhcp6.h create mode 100644 src/network/networkd-fdb.c create mode 100644 src/network/networkd-fdb.h create mode 100644 src/network/networkd-gperf.gperf create mode 100644 src/network/networkd-ipv4ll.c create mode 100644 src/network/networkd-ipv4ll.h create mode 100644 src/network/networkd-ipv6-proxy-ndp.c create mode 100644 src/network/networkd-ipv6-proxy-ndp.h create mode 100644 src/network/networkd-link-bus.c create mode 100644 src/network/networkd-link-bus.h create mode 100644 src/network/networkd-link.c create mode 100644 src/network/networkd-link.h create mode 100644 src/network/networkd-lldp-rx.c create mode 100644 src/network/networkd-lldp-rx.h create mode 100644 src/network/networkd-lldp-tx.c create mode 100644 src/network/networkd-lldp-tx.h create mode 100644 src/network/networkd-manager-bus.c create mode 100644 src/network/networkd-manager-bus.h create mode 100644 src/network/networkd-manager.c create mode 100644 src/network/networkd-manager.h create mode 100644 src/network/networkd-ndisc.c create mode 100644 src/network/networkd-ndisc.h create mode 100644 src/network/networkd-neighbor.c create mode 100644 src/network/networkd-neighbor.h create mode 100644 src/network/networkd-network-bus.c create mode 100644 src/network/networkd-network-bus.h create mode 100644 src/network/networkd-network-gperf.gperf create mode 100644 src/network/networkd-network.c create mode 100644 src/network/networkd-network.h create mode 100644 src/network/networkd-nexthop.c create mode 100644 src/network/networkd-nexthop.h create mode 100644 src/network/networkd-radv.c create mode 100644 src/network/networkd-radv.h create mode 100644 src/network/networkd-route.c create mode 100644 src/network/networkd-route.h create mode 100644 src/network/networkd-routing-policy-rule.c create mode 100644 src/network/networkd-routing-policy-rule.h create mode 100644 src/network/networkd-speed-meter.c create mode 100644 src/network/networkd-speed-meter.h create mode 100644 src/network/networkd-util.c create mode 100644 src/network/networkd-util.h create mode 100644 src/network/networkd-wifi.c create mode 100644 src/network/networkd-wifi.h create mode 100644 src/network/networkd.c create mode 100644 src/network/networkd.conf create mode 100644 src/network/org.freedesktop.network1.conf create mode 100644 src/network/org.freedesktop.network1.policy create mode 100644 src/network/org.freedesktop.network1.service create mode 100644 src/network/systemd-networkd.pkla create mode 100644 src/network/systemd-networkd.rules create mode 100644 src/network/tc/netem.c create mode 100644 src/network/tc/netem.h create mode 100644 src/network/tc/qdisc.c create mode 100644 src/network/tc/qdisc.h create mode 100644 src/network/tc/tc-util.c create mode 100644 src/network/tc/tc-util.h create mode 100644 src/network/test-network-tables.c create mode 100644 src/network/test-network.c create mode 100644 src/network/test-networkd-conf.c create mode 100644 src/network/test-routing-policy-rule.c create mode 100644 src/network/wait-online/link.c create mode 100644 src/network/wait-online/link.h create mode 100644 src/network/wait-online/manager.c create mode 100644 src/network/wait-online/manager.h create mode 100644 src/network/wait-online/wait-online.c create mode 100644 src/notify/notify.c create mode 100644 src/nspawn/meson.build create mode 100644 src/nspawn/nspawn-cgroup.c create mode 100644 src/nspawn/nspawn-cgroup.h create mode 100644 src/nspawn/nspawn-def.h create mode 100644 src/nspawn/nspawn-expose-ports.c create mode 100644 src/nspawn/nspawn-expose-ports.h create mode 100644 src/nspawn/nspawn-gperf.gperf create mode 100644 src/nspawn/nspawn-mount.c create mode 100644 src/nspawn/nspawn-mount.h create mode 100644 src/nspawn/nspawn-network.c create mode 100644 src/nspawn/nspawn-network.h create mode 100644 src/nspawn/nspawn-oci.c create mode 100644 src/nspawn/nspawn-oci.h create mode 100644 src/nspawn/nspawn-patch-uid.c create mode 100644 src/nspawn/nspawn-patch-uid.h create mode 100644 src/nspawn/nspawn-register.c create mode 100644 src/nspawn/nspawn-register.h create mode 100644 src/nspawn/nspawn-seccomp.c create mode 100644 src/nspawn/nspawn-seccomp.h create mode 100644 src/nspawn/nspawn-settings.c create mode 100644 src/nspawn/nspawn-settings.h create mode 100644 src/nspawn/nspawn-setuid.c create mode 100644 src/nspawn/nspawn-setuid.h create mode 100644 src/nspawn/nspawn-stub-pid1.c create mode 100644 src/nspawn/nspawn-stub-pid1.h create mode 100644 src/nspawn/nspawn.c create mode 100644 src/nspawn/test-nspawn-tables.c create mode 100644 src/nspawn/test-patch-uid.c create mode 100644 src/nss-myhostname/nss-myhostname.c create mode 100644 src/nss-myhostname/nss-myhostname.sym create mode 100644 src/nss-mymachines/nss-mymachines.c create mode 100644 src/nss-mymachines/nss-mymachines.sym create mode 100644 src/nss-resolve/nss-resolve.c create mode 100644 src/nss-resolve/nss-resolve.sym create mode 100644 src/nss-systemd/nss-systemd.c create mode 100644 src/nss-systemd/nss-systemd.sym create mode 100644 src/partition/growfs.c create mode 100644 src/partition/makefs.c create mode 100644 src/path/path.c create mode 100644 src/portable/meson.build create mode 100644 src/portable/org.freedesktop.portable1.conf create mode 100644 src/portable/org.freedesktop.portable1.policy create mode 100644 src/portable/org.freedesktop.portable1.service create mode 100644 src/portable/portable.c create mode 100644 src/portable/portable.h create mode 100644 src/portable/portablectl.c create mode 100644 src/portable/portabled-bus.c create mode 100644 src/portable/portabled-bus.h create mode 100644 src/portable/portabled-image-bus.c create mode 100644 src/portable/portabled-image-bus.h create mode 100644 src/portable/portabled-image.c create mode 100644 src/portable/portabled-image.h create mode 100644 src/portable/portabled-operation.c create mode 100644 src/portable/portabled-operation.h create mode 100644 src/portable/portabled.c create mode 100644 src/portable/portabled.h create mode 100644 src/portable/profile/default/service.conf create mode 100644 src/portable/profile/nonetwork/service.conf create mode 100644 src/portable/profile/strict/service.conf create mode 100644 src/portable/profile/trusted/service.conf create mode 100644 src/pstore/meson.build create mode 100644 src/pstore/pstore.c create mode 100644 src/pstore/pstore.conf create mode 100644 src/quotacheck/quotacheck.c create mode 100644 src/random-seed/random-seed.c create mode 100644 src/rc-local-generator/rc-local-generator.c create mode 100644 src/remount-fs/remount-fs.c create mode 100644 src/reply-password/reply-password.c create mode 100644 src/resolve/RFCs create mode 100644 src/resolve/dns-type.c create mode 100644 src/resolve/dns-type.h create mode 100644 src/resolve/dns_type-to-name.awk create mode 100755 src/resolve/generate-dns_type-gperf.py create mode 100644 src/resolve/generate-dns_type-list.sed create mode 100644 src/resolve/meson.build create mode 100644 src/resolve/org.freedesktop.resolve1.conf create mode 100644 src/resolve/org.freedesktop.resolve1.policy create mode 100644 src/resolve/org.freedesktop.resolve1.service create mode 100644 src/resolve/resolv.conf create mode 100644 src/resolve/resolvconf-compat.c create mode 100644 src/resolve/resolvconf-compat.h create mode 100644 src/resolve/resolvectl.c create mode 100644 src/resolve/resolvectl.h create mode 100644 src/resolve/resolved-bus.c create mode 100644 src/resolve/resolved-bus.h create mode 100644 src/resolve/resolved-conf.c create mode 100644 src/resolve/resolved-conf.h create mode 100644 src/resolve/resolved-def.h create mode 100644 src/resolve/resolved-dns-answer.c create mode 100644 src/resolve/resolved-dns-answer.h create mode 100644 src/resolve/resolved-dns-cache.c create mode 100644 src/resolve/resolved-dns-cache.h create mode 100644 src/resolve/resolved-dns-dnssec.c create mode 100644 src/resolve/resolved-dns-dnssec.h create mode 100644 src/resolve/resolved-dns-packet.c create mode 100644 src/resolve/resolved-dns-packet.h create mode 100644 src/resolve/resolved-dns-query.c create mode 100644 src/resolve/resolved-dns-query.h create mode 100644 src/resolve/resolved-dns-question.c create mode 100644 src/resolve/resolved-dns-question.h create mode 100644 src/resolve/resolved-dns-rr.c create mode 100644 src/resolve/resolved-dns-rr.h create mode 100644 src/resolve/resolved-dns-scope.c create mode 100644 src/resolve/resolved-dns-scope.h create mode 100644 src/resolve/resolved-dns-search-domain.c create mode 100644 src/resolve/resolved-dns-search-domain.h create mode 100644 src/resolve/resolved-dns-server.c create mode 100644 src/resolve/resolved-dns-server.h create mode 100644 src/resolve/resolved-dns-stream.c create mode 100644 src/resolve/resolved-dns-stream.h create mode 100644 src/resolve/resolved-dns-stub.c create mode 100644 src/resolve/resolved-dns-stub.h create mode 100644 src/resolve/resolved-dns-synthesize.c create mode 100644 src/resolve/resolved-dns-synthesize.h create mode 100644 src/resolve/resolved-dns-transaction.c create mode 100644 src/resolve/resolved-dns-transaction.h create mode 100644 src/resolve/resolved-dns-trust-anchor.c create mode 100644 src/resolve/resolved-dns-trust-anchor.h create mode 100644 src/resolve/resolved-dns-zone.c create mode 100644 src/resolve/resolved-dns-zone.h create mode 100644 src/resolve/resolved-dnssd-bus.c create mode 100644 src/resolve/resolved-dnssd-bus.h create mode 100644 src/resolve/resolved-dnssd-gperf.gperf create mode 100644 src/resolve/resolved-dnssd.c create mode 100644 src/resolve/resolved-dnssd.h create mode 100644 src/resolve/resolved-dnstls-gnutls.c create mode 100644 src/resolve/resolved-dnstls-gnutls.h create mode 100644 src/resolve/resolved-dnstls-openssl.c create mode 100644 src/resolve/resolved-dnstls-openssl.h create mode 100644 src/resolve/resolved-dnstls.h create mode 100644 src/resolve/resolved-etc-hosts.c create mode 100644 src/resolve/resolved-etc-hosts.h create mode 100644 src/resolve/resolved-gperf.gperf create mode 100644 src/resolve/resolved-link-bus.c create mode 100644 src/resolve/resolved-link-bus.h create mode 100644 src/resolve/resolved-link.c create mode 100644 src/resolve/resolved-link.h create mode 100644 src/resolve/resolved-llmnr.c create mode 100644 src/resolve/resolved-llmnr.h create mode 100644 src/resolve/resolved-manager.c create mode 100644 src/resolve/resolved-manager.h create mode 100644 src/resolve/resolved-mdns.c create mode 100644 src/resolve/resolved-mdns.h create mode 100644 src/resolve/resolved-resolv-conf.c create mode 100644 src/resolve/resolved-resolv-conf.h create mode 100644 src/resolve/resolved.c create mode 100644 src/resolve/resolved.conf.in create mode 100644 src/resolve/test-dns-packet.c create mode 100644 src/resolve/test-dnssec-complex.c create mode 100644 src/resolve/test-dnssec.c create mode 100644 src/resolve/test-resolve-tables.c create mode 100644 src/resolve/test-resolved-etc-hosts.c create mode 100644 src/resolve/test-resolved-packet.c create mode 100644 src/rfkill/rfkill.c create mode 100644 src/run-generator/run-generator.c create mode 100644 src/run/run.c create mode 100644 src/shared/acl-util.c create mode 100644 src/shared/acl-util.h create mode 100644 src/shared/acpi-fpdt.c create mode 100644 src/shared/acpi-fpdt.h create mode 100644 src/shared/apparmor-util.c create mode 100644 src/shared/apparmor-util.h create mode 100644 src/shared/ask-password-api.c create mode 100644 src/shared/ask-password-api.h create mode 100644 src/shared/barrier.c create mode 100644 src/shared/barrier.h create mode 100644 src/shared/base-filesystem.c create mode 100644 src/shared/base-filesystem.h create mode 100644 src/shared/bitmap.c create mode 100644 src/shared/bitmap.h create mode 100644 src/shared/blkid-util.h create mode 100644 src/shared/boot-timestamps.c create mode 100644 src/shared/boot-timestamps.h create mode 100644 src/shared/bootspec.c create mode 100644 src/shared/bootspec.h create mode 100644 src/shared/bpf-program.c create mode 100644 src/shared/bpf-program.h create mode 100644 src/shared/bus-polkit.c create mode 100644 src/shared/bus-polkit.h create mode 100644 src/shared/bus-unit-procs.c create mode 100644 src/shared/bus-unit-procs.h create mode 100644 src/shared/bus-unit-util.c create mode 100644 src/shared/bus-unit-util.h create mode 100644 src/shared/bus-util.c create mode 100644 src/shared/bus-util.h create mode 100644 src/shared/bus-wait-for-jobs.c create mode 100644 src/shared/bus-wait-for-jobs.h create mode 100644 src/shared/bus-wait-for-units.c create mode 100644 src/shared/bus-wait-for-units.h create mode 100644 src/shared/calendarspec.c create mode 100644 src/shared/calendarspec.h create mode 100644 src/shared/cgroup-setup.c create mode 100644 src/shared/cgroup-setup.h create mode 100644 src/shared/cgroup-show.c create mode 100644 src/shared/cgroup-show.h create mode 100644 src/shared/clean-ipc.c create mode 100644 src/shared/clean-ipc.h create mode 100644 src/shared/clock-util.c create mode 100644 src/shared/clock-util.h create mode 100644 src/shared/condition.c create mode 100644 src/shared/condition.h create mode 100644 src/shared/conf-parser.c create mode 100644 src/shared/conf-parser.h create mode 100644 src/shared/cpu-set-util.c create mode 100644 src/shared/cpu-set-util.h create mode 100644 src/shared/crypt-util.c create mode 100644 src/shared/crypt-util.h create mode 100644 src/shared/daemon-util.h create mode 100644 src/shared/dev-setup.c create mode 100644 src/shared/dev-setup.h create mode 100644 src/shared/dissect-image.c create mode 100644 src/shared/dissect-image.h create mode 100644 src/shared/dm-util.c create mode 100644 src/shared/dm-util.h create mode 100644 src/shared/dns-domain.c create mode 100644 src/shared/dns-domain.h create mode 100644 src/shared/dropin.c create mode 100644 src/shared/dropin.h create mode 100644 src/shared/efi-loader.c create mode 100644 src/shared/efi-loader.h create mode 100644 src/shared/enable-mempool.c create mode 100644 src/shared/env-file-label.c create mode 100644 src/shared/env-file-label.h create mode 100644 src/shared/ethtool-util.c create mode 100644 src/shared/ethtool-util.h create mode 100644 src/shared/exec-util.c create mode 100644 src/shared/exec-util.h create mode 100644 src/shared/exit-status.c create mode 100644 src/shared/exit-status.h create mode 100644 src/shared/fdset.c create mode 100644 src/shared/fdset.h create mode 100644 src/shared/fileio-label.c create mode 100644 src/shared/fileio-label.h create mode 100644 src/shared/firewall-util.c create mode 100644 src/shared/firewall-util.h create mode 100644 src/shared/format-table.c create mode 100644 src/shared/format-table.h create mode 100644 src/shared/fsck-util.h create mode 100644 src/shared/fstab-util.c create mode 100644 src/shared/fstab-util.h create mode 100755 src/shared/generate-ip-protocol-list.sh create mode 100644 src/shared/generator.c create mode 100644 src/shared/generator.h create mode 100644 src/shared/gpt.h create mode 100644 src/shared/id128-print.c create mode 100644 src/shared/id128-print.h create mode 100644 src/shared/ima-util.c create mode 100644 src/shared/ima-util.h create mode 100644 src/shared/import-util.c create mode 100644 src/shared/import-util.h create mode 100644 src/shared/initreq.h create mode 100644 src/shared/install-printf.c create mode 100644 src/shared/install-printf.h create mode 100644 src/shared/install.c create mode 100644 src/shared/install.h create mode 100644 src/shared/ip-protocol-list.c create mode 100644 src/shared/ip-protocol-list.h create mode 100644 src/shared/ip-protocol-to-name.awk create mode 100644 src/shared/journal-importer.c create mode 100644 src/shared/journal-importer.h create mode 100644 src/shared/journal-util.c create mode 100644 src/shared/journal-util.h create mode 100644 src/shared/json-internal.h create mode 100644 src/shared/json.c create mode 100644 src/shared/json.h create mode 100644 src/shared/libmount-util.h create mode 100644 src/shared/libshared.sym create mode 100644 src/shared/linux/README create mode 100644 src/shared/linux/auto_dev-ioctl.h create mode 100644 src/shared/linux/bpf.h create mode 100644 src/shared/linux/bpf_common.h create mode 100644 src/shared/linux/bpf_insn.h create mode 100644 src/shared/linux/dm-ioctl.h create mode 100644 src/shared/linux/ethtool.h create mode 100644 src/shared/linux/nl80211.h create mode 100644 src/shared/local-addresses.c create mode 100644 src/shared/local-addresses.h create mode 100644 src/shared/lockfile-util.c create mode 100644 src/shared/lockfile-util.h create mode 100644 src/shared/log-link.h create mode 100644 src/shared/logs-show.c create mode 100644 src/shared/logs-show.h create mode 100644 src/shared/loop-util.c create mode 100644 src/shared/loop-util.h create mode 100644 src/shared/machine-image.c create mode 100644 src/shared/machine-image.h create mode 100644 src/shared/machine-pool.c create mode 100644 src/shared/machine-pool.h create mode 100644 src/shared/main-func.h create mode 100644 src/shared/meson.build create mode 100644 src/shared/module-util.c create mode 100644 src/shared/module-util.h create mode 100644 src/shared/mount-util.c create mode 100644 src/shared/mount-util.h create mode 100644 src/shared/nscd-flush.c create mode 100644 src/shared/nscd-flush.h create mode 100644 src/shared/nsflags.c create mode 100644 src/shared/nsflags.h create mode 100644 src/shared/os-util.c create mode 100644 src/shared/os-util.h create mode 100644 src/shared/output-mode.c create mode 100644 src/shared/output-mode.h create mode 100644 src/shared/pager.c create mode 100644 src/shared/pager.h create mode 100644 src/shared/path-lookup.c create mode 100644 src/shared/path-lookup.h create mode 100644 src/shared/pe-header.h create mode 100644 src/shared/pretty-print.c create mode 100644 src/shared/pretty-print.h create mode 100644 src/shared/ptyfwd.c create mode 100644 src/shared/ptyfwd.h create mode 100644 src/shared/reboot-util.c create mode 100644 src/shared/reboot-util.h create mode 100644 src/shared/resolve-util.c create mode 100644 src/shared/resolve-util.h create mode 100644 src/shared/seccomp-util.c create mode 100644 src/shared/seccomp-util.h create mode 100644 src/shared/securebits-util.c create mode 100644 src/shared/securebits-util.h create mode 100644 src/shared/serialize.c create mode 100644 src/shared/serialize.h create mode 100644 src/shared/sleep-config.c create mode 100644 src/shared/sleep-config.h create mode 100644 src/shared/spawn-ask-password-agent.c create mode 100644 src/shared/spawn-ask-password-agent.h create mode 100644 src/shared/spawn-polkit-agent.c create mode 100644 src/shared/spawn-polkit-agent.h create mode 100644 src/shared/specifier.c create mode 100644 src/shared/specifier.h create mode 100644 src/shared/switch-root.c create mode 100644 src/shared/switch-root.h create mode 100644 src/shared/sysctl-util.c create mode 100644 src/shared/sysctl-util.h create mode 100644 src/shared/test-tables.h create mode 100644 src/shared/tests.c create mode 100644 src/shared/tests.h create mode 100644 src/shared/tmpfile-util-label.c create mode 100644 src/shared/tmpfile-util-label.h create mode 100644 src/shared/tomoyo-util.c create mode 100644 src/shared/tomoyo-util.h create mode 100644 src/shared/udev-util.c create mode 100644 src/shared/udev-util.h create mode 100644 src/shared/uid-range.c create mode 100644 src/shared/uid-range.h create mode 100644 src/shared/unit-file.c create mode 100644 src/shared/unit-file.h create mode 100644 src/shared/utmp-wtmp.c create mode 100644 src/shared/utmp-wtmp.h create mode 100644 src/shared/varlink.c create mode 100644 src/shared/varlink.h create mode 100644 src/shared/verbs.c create mode 100644 src/shared/verbs.h create mode 100644 src/shared/vlan-util.c create mode 100644 src/shared/vlan-util.h create mode 100644 src/shared/volatile-util.c create mode 100644 src/shared/volatile-util.h create mode 100644 src/shared/watchdog.c create mode 100644 src/shared/watchdog.h create mode 100644 src/shared/web-util.c create mode 100644 src/shared/web-util.h create mode 100644 src/shared/wifi-util.c create mode 100644 src/shared/wifi-util.h create mode 100644 src/shared/xml.c create mode 100644 src/shared/xml.h create mode 100644 src/shutdown/meson.build create mode 100644 src/shutdown/shutdown.c create mode 100644 src/shutdown/umount.c create mode 100644 src/shutdown/umount.h create mode 100644 src/sleep/sleep.c create mode 100644 src/sleep/sleep.conf create mode 100644 src/socket-proxy/socket-proxyd.c create mode 100644 src/stdio-bridge/stdio-bridge.c create mode 100644 src/sulogin-shell/sulogin-shell.c create mode 100644 src/sysctl/sysctl.c create mode 100644 src/system-update-generator/system-update-generator.c create mode 100644 src/systemctl/systemctl.c create mode 100755 src/systemctl/systemd-sysv-install.SKELETON create mode 100644 src/systemctl/sysv-compat.c create mode 100644 src/systemctl/sysv-compat.h create mode 100644 src/systemd/_sd-common.h create mode 100644 src/systemd/meson.build create mode 100644 src/systemd/sd-bus-protocol.h create mode 100644 src/systemd/sd-bus-vtable.h create mode 100644 src/systemd/sd-bus.h create mode 100644 src/systemd/sd-daemon.h create mode 100644 src/systemd/sd-device.h create mode 100644 src/systemd/sd-dhcp-client.h create mode 100644 src/systemd/sd-dhcp-lease.h create mode 100644 src/systemd/sd-dhcp-option.h create mode 100644 src/systemd/sd-dhcp-server.h create mode 100644 src/systemd/sd-dhcp6-client.h create mode 100644 src/systemd/sd-dhcp6-lease.h create mode 100644 src/systemd/sd-event.h create mode 100644 src/systemd/sd-hwdb.h create mode 100644 src/systemd/sd-id128.h create mode 100644 src/systemd/sd-ipv4acd.h create mode 100644 src/systemd/sd-ipv4ll.h create mode 100644 src/systemd/sd-journal.h create mode 100644 src/systemd/sd-lldp.h create mode 100644 src/systemd/sd-login.h create mode 100644 src/systemd/sd-messages.h create mode 100644 src/systemd/sd-ndisc.h create mode 100644 src/systemd/sd-netlink.h create mode 100644 src/systemd/sd-network.h create mode 100644 src/systemd/sd-path.h create mode 100644 src/systemd/sd-radv.h create mode 100644 src/systemd/sd-resolve.h create mode 100644 src/systemd/sd-utf8.h create mode 100644 src/sysusers/sysusers.c create mode 100644 src/sysv-generator/sysv-generator.c create mode 100755 src/test/generate-sym-test.py create mode 100644 src/test/meson.build create mode 100644 src/test/test-acl-util.c create mode 100644 src/test/test-af-list.c create mode 100644 src/test/test-alloc-util.c create mode 100644 src/test/test-architecture.c create mode 100644 src/test/test-arphrd-list.c create mode 100644 src/test/test-ask-password-api.c create mode 100644 src/test/test-async.c create mode 100644 src/test/test-barrier.c create mode 100644 src/test/test-bitmap.c create mode 100644 src/test/test-boot-timestamps.c create mode 100644 src/test/test-bpf-devices.c create mode 100644 src/test/test-bpf-firewall.c create mode 100644 src/test/test-btrfs.c create mode 100644 src/test/test-bus-util.c create mode 100644 src/test/test-calendarspec.c create mode 100644 src/test/test-cap-list.c create mode 100644 src/test/test-capability.c create mode 100644 src/test/test-cgroup-cpu.c create mode 100644 src/test/test-cgroup-mask.c create mode 100644 src/test/test-cgroup-setup.c create mode 100644 src/test/test-cgroup-unit-default.c create mode 100644 src/test/test-cgroup-util.c create mode 100644 src/test/test-cgroup.c create mode 100644 src/test/test-chase-symlinks.c create mode 100644 src/test/test-chown-rec.c create mode 100644 src/test/test-clock.c create mode 100644 src/test/test-condition.c create mode 100644 src/test/test-conf-files.c create mode 100644 src/test/test-conf-parser.c create mode 100644 src/test/test-copy.c create mode 100644 src/test/test-cpu-set-util.c create mode 100644 src/test/test-daemon.c create mode 100644 src/test/test-date.c create mode 100644 src/test/test-dev-setup.c create mode 100644 src/test/test-device-nodes.c create mode 100644 src/test/test-dissect-image.c create mode 100644 src/test/test-dlopen.c create mode 100644 src/test/test-dns-domain.c create mode 100644 src/test/test-ellipsize.c create mode 100644 src/test/test-emergency-action.c create mode 100644 src/test/test-engine.c create mode 100644 src/test/test-env-file.c create mode 100644 src/test/test-env-util.c create mode 100644 src/test/test-escape.c create mode 100644 src/test/test-exec-util.c create mode 100644 src/test/test-execute.c create mode 100644 src/test/test-exit-status.c create mode 100644 src/test/test-extract-word.c create mode 100644 src/test/test-fd-util.c create mode 100644 src/test/test-fdset.c create mode 100644 src/test/test-fileio.c create mode 100644 src/test/test-firewall-util.c create mode 100644 src/test/test-format-table.c create mode 100644 src/test/test-format-util.c create mode 100644 src/test/test-fs-util.c create mode 100644 src/test/test-fstab-util.c create mode 100644 src/test/test-gcrypt-util.c create mode 100644 src/test/test-glob-util.c create mode 100644 src/test/test-hash.c create mode 100644 src/test/test-hashmap-ordered.awk create mode 100644 src/test/test-hashmap-plain.c create mode 100644 src/test/test-hashmap.c create mode 100644 src/test/test-hexdecoct.c create mode 100644 src/test/test-hostname-util.c create mode 100644 src/test/test-hostname.c create mode 100644 src/test/test-id128.c create mode 100644 src/test/test-in-addr-util.c create mode 100644 src/test/test-install-root.c create mode 100644 src/test/test-install.c create mode 100644 src/test/test-io-util.c create mode 100644 src/test/test-ip-protocol-list.c create mode 100644 src/test/test-ipcrm.c create mode 100644 src/test/test-job-type.c create mode 100644 src/test/test-journal-importer.c create mode 100644 src/test/test-json.c create mode 100644 src/test/test-libmount.c create mode 100644 src/test/test-libudev.c create mode 100644 src/test/test-list.c create mode 100644 src/test/test-load-fragment.c create mode 100644 src/test/test-local-addresses.c create mode 100644 src/test/test-locale-util.c create mode 100644 src/test/test-log.c create mode 100644 src/test/test-loopback.c create mode 100644 src/test/test-mount-util.c create mode 100644 src/test/test-mountpoint-util.c create mode 100644 src/test/test-namespace.c create mode 100644 src/test/test-netlink-manual.c create mode 100644 src/test/test-ns.c create mode 100644 src/test/test-nscd-flush.c create mode 100644 src/test/test-nss.c create mode 100644 src/test/test-ordered-set.c create mode 100644 src/test/test-os-util.c create mode 100644 src/test/test-parse-util.c create mode 100644 src/test/test-path-lookup.c create mode 100644 src/test/test-path-util.c create mode 100644 src/test/test-path.c create mode 100644 src/test/test-pretty-print.c create mode 100644 src/test/test-prioq.c create mode 100644 src/test/test-proc-cmdline.c create mode 100644 src/test/test-process-util.c create mode 100644 src/test/test-procfs-util.c create mode 100644 src/test/test-random-util.c create mode 100644 src/test/test-ratelimit.c create mode 100644 src/test/test-replace-var.c create mode 100644 src/test/test-rlimit-util.c create mode 100644 src/test/test-sched-prio.c create mode 100644 src/test/test-sd-hwdb.c create mode 100644 src/test/test-seccomp.c create mode 100644 src/test/test-selinux.c create mode 100644 src/test/test-serialize.c create mode 100644 src/test/test-set-disable-mempool.c create mode 100644 src/test/test-set.c create mode 100644 src/test/test-sigbus.c create mode 100644 src/test/test-signal-util.c create mode 100644 src/test/test-siphash24.c create mode 100644 src/test/test-sizeof.c create mode 100644 src/test/test-sleep.c create mode 100644 src/test/test-socket-util.c create mode 100644 src/test/test-specifier.c create mode 100644 src/test/test-stat-util.c create mode 100644 src/test/test-static-destruct.c create mode 100644 src/test/test-strbuf.c create mode 100644 src/test/test-string-util.c create mode 100644 src/test/test-strip-tab-ansi.c create mode 100644 src/test/test-strv.c create mode 100644 src/test/test-strxcpyx.c create mode 100644 src/test/test-sysctl-util.c create mode 100755 src/test/test-systemd-tmpfiles.py create mode 100644 src/test/test-tables.c create mode 100644 src/test/test-terminal-util.c create mode 100644 src/test/test-time-util.c create mode 100644 src/test/test-tmpfiles.c create mode 100644 src/test/test-udev.c create mode 100644 src/test/test-uid-range.c create mode 100644 src/test/test-umask-util.c create mode 100644 src/test/test-umount.c create mode 100644 src/test/test-unaligned.c create mode 100644 src/test/test-unit-file.c create mode 100644 src/test/test-unit-name.c create mode 100644 src/test/test-user-util.c create mode 100644 src/test/test-utf8.c create mode 100644 src/test/test-util.c create mode 100644 src/test/test-varlink.c create mode 100644 src/test/test-verbs.c create mode 100644 src/test/test-watch-pid.c create mode 100644 src/test/test-watchdog.c create mode 100644 src/test/test-web-util.c create mode 100644 src/test/test-xattr-util.c create mode 100644 src/test/test-xml.c create mode 100644 src/time-wait-sync/time-wait-sync.c create mode 100644 src/timedate/meson.build create mode 100644 src/timedate/org.freedesktop.timedate1.conf create mode 100644 src/timedate/org.freedesktop.timedate1.policy create mode 100644 src/timedate/org.freedesktop.timedate1.service create mode 100644 src/timedate/timedatectl.c create mode 100644 src/timedate/timedated.c create mode 100644 src/timesync/80-systemd-timesync.list create mode 100644 src/timesync/meson.build create mode 100644 src/timesync/org.freedesktop.timesync1.conf create mode 100644 src/timesync/org.freedesktop.timesync1.service create mode 100644 src/timesync/test-timesync.c create mode 100644 src/timesync/timesyncd-bus.c create mode 100644 src/timesync/timesyncd-bus.h create mode 100644 src/timesync/timesyncd-conf.c create mode 100644 src/timesync/timesyncd-conf.h create mode 100644 src/timesync/timesyncd-gperf.gperf create mode 100644 src/timesync/timesyncd-manager.c create mode 100644 src/timesync/timesyncd-manager.h create mode 100644 src/timesync/timesyncd-ntp-message.h create mode 100644 src/timesync/timesyncd-server.c create mode 100644 src/timesync/timesyncd-server.h create mode 100644 src/timesync/timesyncd.c create mode 100644 src/timesync/timesyncd.conf.in create mode 100644 src/tmpfiles/tmpfiles.c create mode 100644 src/tty-ask-password-agent/tty-ask-password-agent.c create mode 100644 src/udev/.vimrc create mode 100644 src/udev/ata_id/ata_id.c create mode 100644 src/udev/cdrom_id/cdrom_id.c create mode 100644 src/udev/fido_id/fido_id.c create mode 100644 src/udev/fido_id/fido_id_desc.c create mode 100644 src/udev/fido_id/fido_id_desc.h create mode 100644 src/udev/fido_id/fuzz-fido-id-desc.c create mode 100644 src/udev/fido_id/test-fido-id-desc.c create mode 100755 src/udev/generate-keyboard-keys-gperf.sh create mode 100755 src/udev/generate-keyboard-keys-list.sh create mode 100644 src/udev/meson.build create mode 100644 src/udev/mtd_probe/mtd_probe.c create mode 100644 src/udev/mtd_probe/mtd_probe.h create mode 100644 src/udev/mtd_probe/probe_smartmedia.c create mode 100644 src/udev/net/fuzz-link-parser.c create mode 100644 src/udev/net/fuzz-link-parser.options create mode 100644 src/udev/net/link-config-gperf.gperf create mode 100644 src/udev/net/link-config.c create mode 100644 src/udev/net/link-config.h create mode 100644 src/udev/net/naming-scheme.c create mode 100644 src/udev/net/naming-scheme.h create mode 100644 src/udev/scsi_id/README create mode 100644 src/udev/scsi_id/scsi.h create mode 100644 src/udev/scsi_id/scsi_id.c create mode 100644 src/udev/scsi_id/scsi_id.h create mode 100644 src/udev/scsi_id/scsi_serial.c create mode 100644 src/udev/udev-builtin-blkid.c create mode 100644 src/udev/udev-builtin-btrfs.c create mode 100644 src/udev/udev-builtin-hwdb.c create mode 100644 src/udev/udev-builtin-input_id.c create mode 100644 src/udev/udev-builtin-keyboard.c create mode 100644 src/udev/udev-builtin-kmod.c create mode 100644 src/udev/udev-builtin-net_id.c create mode 100644 src/udev/udev-builtin-net_setup_link.c create mode 100644 src/udev/udev-builtin-path_id.c create mode 100644 src/udev/udev-builtin-uaccess.c create mode 100644 src/udev/udev-builtin-usb_id.c create mode 100644 src/udev/udev-builtin.c create mode 100644 src/udev/udev-builtin.h create mode 100644 src/udev/udev-ctrl.c create mode 100644 src/udev/udev-ctrl.h create mode 100644 src/udev/udev-event.c create mode 100644 src/udev/udev-event.h create mode 100644 src/udev/udev-node.c create mode 100644 src/udev/udev-node.h create mode 100644 src/udev/udev-rules.c create mode 100644 src/udev/udev-rules.h create mode 100644 src/udev/udev-watch.c create mode 100644 src/udev/udev-watch.h create mode 100644 src/udev/udev.conf create mode 100644 src/udev/udev.pc.in create mode 100644 src/udev/udevadm-control.c create mode 100644 src/udev/udevadm-hwdb.c create mode 100644 src/udev/udevadm-info.c create mode 100644 src/udev/udevadm-monitor.c create mode 100644 src/udev/udevadm-settle.c create mode 100644 src/udev/udevadm-test-builtin.c create mode 100644 src/udev/udevadm-test.c create mode 100644 src/udev/udevadm-trigger.c create mode 100644 src/udev/udevadm-util.c create mode 100644 src/udev/udevadm-util.h create mode 100644 src/udev/udevadm.c create mode 100644 src/udev/udevadm.h create mode 100644 src/udev/udevd.c create mode 100644 src/udev/v4l_id/v4l_id.c create mode 100644 src/update-done/update-done.c create mode 100644 src/update-utmp/update-utmp.c create mode 100644 src/user-sessions/user-sessions.c create mode 100644 src/vconsole/90-vconsole.rules.in create mode 100644 src/vconsole/meson.build create mode 100644 src/vconsole/vconsole-setup.c create mode 100644 src/veritysetup/veritysetup-generator.c create mode 100644 src/veritysetup/veritysetup.c create mode 100644 src/version/version.h.in create mode 100644 src/volatile-root/volatile-root.c create mode 100644 sysctl.d/50-coredump.conf.in create mode 100644 sysctl.d/50-default.conf create mode 100644 sysctl.d/50-pid-max.conf create mode 100644 sysctl.d/meson.build create mode 100644 sysusers.d/basic.conf.in create mode 100644 sysusers.d/meson.build create mode 100644 sysusers.d/systemd-remote.conf.m4 create mode 100644 sysusers.d/systemd.conf.m4 create mode 100644 test/.gitignore create mode 100644 test/README.testsuite create mode 100644 test/TEST-01-BASIC/Makefile create mode 100755 test/TEST-01-BASIC/test.sh create mode 120000 test/TEST-02-CRYPTSETUP/Makefile create mode 100755 test/TEST-02-CRYPTSETUP/test.sh create mode 120000 test/TEST-03-JOBS/Makefile create mode 100755 test/TEST-03-JOBS/test-jobs.sh create mode 100755 test/TEST-03-JOBS/test.sh create mode 120000 test/TEST-04-JOURNAL/Makefile create mode 100755 test/TEST-04-JOURNAL/test-journal.sh create mode 100755 test/TEST-04-JOURNAL/test.sh create mode 120000 test/TEST-05-RLIMITS/Makefile create mode 100755 test/TEST-05-RLIMITS/test-rlimits.sh create mode 100755 test/TEST-05-RLIMITS/test.sh create mode 120000 test/TEST-06-SELINUX/Makefile create mode 100644 test/TEST-06-SELINUX/systemd_test.if create mode 100644 test/TEST-06-SELINUX/systemd_test.te create mode 100755 test/TEST-06-SELINUX/test-selinux-checks.sh create mode 100755 test/TEST-06-SELINUX/test.sh create mode 120000 test/TEST-07-ISSUE-1981/Makefile create mode 100755 test/TEST-07-ISSUE-1981/test-segfault.sh create mode 100755 test/TEST-07-ISSUE-1981/test.sh create mode 120000 test/TEST-08-ISSUE-2730/Makefile create mode 100755 test/TEST-08-ISSUE-2730/test.sh create mode 120000 test/TEST-09-ISSUE-2691/Makefile create mode 100755 test/TEST-09-ISSUE-2691/test.sh create mode 120000 test/TEST-10-ISSUE-2467/Makefile create mode 100755 test/TEST-10-ISSUE-2467/test.sh create mode 120000 test/TEST-11-ISSUE-3166/Makefile create mode 100755 test/TEST-11-ISSUE-3166/test.sh create mode 120000 test/TEST-12-ISSUE-3171/Makefile create mode 100755 test/TEST-12-ISSUE-3171/test.sh create mode 100644 test/TEST-13-NSPAWN-SMOKE/Makefile create mode 100755 test/TEST-13-NSPAWN-SMOKE/create-busybox-container create mode 100755 test/TEST-13-NSPAWN-SMOKE/test.sh create mode 120000 test/TEST-14-MACHINE-ID/Makefile create mode 100755 test/TEST-14-MACHINE-ID/test.sh create mode 120000 test/TEST-15-DROPIN/Makefile create mode 100755 test/TEST-15-DROPIN/test-dropin.sh create mode 100755 test/TEST-15-DROPIN/test.sh create mode 100644 test/TEST-15-DROPIN/testsuite.service create mode 120000 test/TEST-16-EXTEND-TIMEOUT/Makefile create mode 100755 test/TEST-16-EXTEND-TIMEOUT/assess.sh create mode 100755 test/TEST-16-EXTEND-TIMEOUT/extend_timeout_test_service.sh create mode 100755 test/TEST-16-EXTEND-TIMEOUT/test.sh create mode 100644 test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-runtime.service create mode 100644 test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-start.service create mode 100644 test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-stop.service create mode 100644 test/TEST-16-EXTEND-TIMEOUT/testsuite-success-all.service create mode 100644 test/TEST-16-EXTEND-TIMEOUT/testsuite-success-runtime.service create mode 100644 test/TEST-16-EXTEND-TIMEOUT/testsuite-success-start.service create mode 100644 test/TEST-16-EXTEND-TIMEOUT/testsuite-success-stop.service create mode 100644 test/TEST-16-EXTEND-TIMEOUT/testsuite.service create mode 120000 test/TEST-17-UDEV-WANTS/Makefile create mode 100755 test/TEST-17-UDEV-WANTS/test.sh create mode 100755 test/TEST-17-UDEV-WANTS/testsuite.sh create mode 120000 test/TEST-18-FAILUREACTION/Makefile create mode 100755 test/TEST-18-FAILUREACTION/test.sh create mode 100755 test/TEST-18-FAILUREACTION/testsuite.sh create mode 120000 test/TEST-19-DELEGATE/Makefile create mode 100755 test/TEST-19-DELEGATE/test.sh create mode 100755 test/TEST-19-DELEGATE/testsuite.sh create mode 120000 test/TEST-20-MAINPIDGAMES/Makefile create mode 100755 test/TEST-20-MAINPIDGAMES/test.sh create mode 100755 test/TEST-20-MAINPIDGAMES/testsuite.sh create mode 120000 test/TEST-21-SYSUSERS/Makefile create mode 100644 test/TEST-21-SYSUSERS/inline.expected-group create mode 100644 test/TEST-21-SYSUSERS/inline.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-1.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-1.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-1.input create mode 100644 test/TEST-21-SYSUSERS/test-10.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-10.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-10.input create mode 100644 test/TEST-21-SYSUSERS/test-11.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-11.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-11.initial-group create mode 100644 test/TEST-21-SYSUSERS/test-11.initial-passwd create mode 100644 test/TEST-21-SYSUSERS/test-11.input create mode 100644 test/TEST-21-SYSUSERS/test-12.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-12.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-12.initial-group create mode 100644 test/TEST-21-SYSUSERS/test-12.initial-passwd create mode 100644 test/TEST-21-SYSUSERS/test-12.input create mode 100644 test/TEST-21-SYSUSERS/test-2.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-2.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-2.input create mode 100644 test/TEST-21-SYSUSERS/test-3.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-3.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-3.input create mode 100644 test/TEST-21-SYSUSERS/test-4.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-4.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-4.input create mode 100644 test/TEST-21-SYSUSERS/test-5.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-5.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-5.input create mode 100644 test/TEST-21-SYSUSERS/test-6.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-6.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-6.input create mode 100644 test/TEST-21-SYSUSERS/test-7.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-7.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-7.input create mode 100644 test/TEST-21-SYSUSERS/test-8.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-8.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-8.input create mode 100644 test/TEST-21-SYSUSERS/test-9.expected-group create mode 100644 test/TEST-21-SYSUSERS/test-9.expected-passwd create mode 100644 test/TEST-21-SYSUSERS/test-9.input create mode 100755 test/TEST-21-SYSUSERS/test.sh create mode 100644 test/TEST-21-SYSUSERS/unhappy-1.expected-err create mode 100644 test/TEST-21-SYSUSERS/unhappy-1.input create mode 100644 test/TEST-21-SYSUSERS/unhappy-2.expected-err create mode 100644 test/TEST-21-SYSUSERS/unhappy-2.input create mode 120000 test/TEST-22-TMPFILES/Makefile create mode 100755 test/TEST-22-TMPFILES/run-tmpfiles-tests.sh create mode 100755 test/TEST-22-TMPFILES/test-01.sh create mode 100755 test/TEST-22-TMPFILES/test-02.sh create mode 100755 test/TEST-22-TMPFILES/test-03.sh create mode 100755 test/TEST-22-TMPFILES/test-04.sh create mode 100755 test/TEST-22-TMPFILES/test-05.sh create mode 100755 test/TEST-22-TMPFILES/test-06.sh create mode 100755 test/TEST-22-TMPFILES/test-07.sh create mode 100755 test/TEST-22-TMPFILES/test-08.sh create mode 100755 test/TEST-22-TMPFILES/test-09.sh create mode 100755 test/TEST-22-TMPFILES/test.sh create mode 100644 test/TEST-22-TMPFILES/testsuite.service create mode 120000 test/TEST-23-TYPE-EXEC/Makefile create mode 100755 test/TEST-23-TYPE-EXEC/test.sh create mode 100755 test/TEST-23-TYPE-EXEC/testsuite.sh create mode 120000 test/TEST-24-UNIT-TESTS/Makefile create mode 100644 test/TEST-24-UNIT-TESTS/blacklist-ubuntu-ci-ppc64el create mode 100755 test/TEST-24-UNIT-TESTS/test.sh create mode 100755 test/TEST-24-UNIT-TESTS/testsuite.sh create mode 120000 test/TEST-25-IMPORT/Makefile create mode 100644 test/TEST-25-IMPORT/blacklist-ubuntu-ci create mode 100755 test/TEST-25-IMPORT/test.sh create mode 100755 test/TEST-25-IMPORT/testsuite.sh create mode 120000 test/TEST-26-SETENV/Makefile create mode 100755 test/TEST-26-SETENV/test.sh create mode 100755 test/TEST-26-SETENV/testsuite.sh create mode 120000 test/TEST-27-STDOUTFILE/Makefile create mode 100755 test/TEST-27-STDOUTFILE/test.sh create mode 100755 test/TEST-27-STDOUTFILE/testsuite.sh create mode 120000 test/TEST-28-PERCENTJ-WANTEDBY/Makefile create mode 100755 test/TEST-28-PERCENTJ-WANTEDBY/test.sh create mode 120000 test/TEST-29-UDEV-ID_RENAMING/Makefile create mode 100755 test/TEST-29-UDEV-ID_RENAMING/test.sh create mode 100755 test/TEST-29-UDEV-ID_RENAMING/testsuite.sh create mode 120000 test/TEST-30-ONCLOCKCHANGE/Makefile create mode 100644 test/TEST-30-ONCLOCKCHANGE/blacklist-ubuntu-ci-i386 create mode 100755 test/TEST-30-ONCLOCKCHANGE/test.sh create mode 100755 test/TEST-30-ONCLOCKCHANGE/testsuite.sh create mode 120000 test/TEST-31-DEVICE-ENUMERATION/Makefile create mode 100755 test/TEST-31-DEVICE-ENUMERATION/test.sh create mode 100755 test/TEST-31-DEVICE-ENUMERATION/testsuite.sh create mode 120000 test/TEST-32-OOMPOLICY/Makefile create mode 100755 test/TEST-32-OOMPOLICY/test.sh create mode 100755 test/TEST-32-OOMPOLICY/testsuite.sh create mode 120000 test/TEST-33-CLEAN-UNIT/Makefile create mode 100755 test/TEST-33-CLEAN-UNIT/test.sh create mode 100755 test/TEST-33-CLEAN-UNIT/testsuite.sh create mode 120000 test/TEST-34-DYNAMICUSERMIGRATE/Makefile create mode 100755 test/TEST-34-DYNAMICUSERMIGRATE/test.sh create mode 100755 test/TEST-34-DYNAMICUSERMIGRATE/testsuite.sh create mode 120000 test/TEST-35-NETWORK-GENERATOR/Makefile create mode 100644 test/TEST-35-NETWORK-GENERATOR/test-01-dhcp.expected/91-default.network create mode 100644 test/TEST-35-NETWORK-GENERATOR/test-01-dhcp.input create mode 100644 test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-bridge99.netdev create mode 100644 test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-bridge99.network create mode 100644 test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-eth0.network create mode 100644 test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-eth1.network create mode 100644 test/TEST-35-NETWORK-GENERATOR/test-02-bridge.input create mode 100755 test/TEST-35-NETWORK-GENERATOR/test.sh create mode 120000 test/TEST-36-NUMAPOLICY/Makefile create mode 100644 test/TEST-36-NUMAPOLICY/blacklist-ubuntu-ci-s390x create mode 100755 test/TEST-36-NUMAPOLICY/test.sh create mode 100755 test/TEST-36-NUMAPOLICY/testsuite.sh create mode 120000 test/TEST-37-RUNTIMEDIRECTORYPRESERVE/Makefile create mode 100755 test/TEST-37-RUNTIMEDIRECTORYPRESERVE/test.sh create mode 100755 test/TEST-37-RUNTIMEDIRECTORYPRESERVE/testsuite.sh create mode 120000 test/TEST-39-EXECRELOAD/Makefile create mode 100755 test/TEST-39-EXECRELOAD/test.sh create mode 100644 test/TEST-39-EXECRELOAD/testsuite.sh create mode 100644 test/TEST-40-EXEC-COMMAND-EX/Makefile create mode 100644 test/TEST-40-EXEC-COMMAND-EX/blacklist-ubuntu-ci-arm64 create mode 100755 test/TEST-40-EXEC-COMMAND-EX/test.sh create mode 100755 test/TEST-40-EXEC-COMMAND-EX/testsuite.sh create mode 100644 test/TEST-41-ONESHOT-RESTART/Makefile create mode 100755 test/TEST-41-ONESHOT-RESTART/test.sh create mode 100755 test/TEST-41-ONESHOT-RESTART/testsuite.sh create mode 100644 test/TEST-42-EXECSTOPPOST/Makefile create mode 100755 test/TEST-42-EXECSTOPPOST/test.sh create mode 100755 test/TEST-42-EXECSTOPPOST/testsuite.sh create mode 100644 test/a-conj.service create mode 100644 test/a.service create mode 100644 test/b.service create mode 120000 test/basic.target create mode 100644 test/c.service create mode 100755 test/create-sys-script.py create mode 100644 test/d.service create mode 100644 test/daughter.service create mode 100644 test/dml-discard-empty.service create mode 100644 test/dml-discard-set-ml.service create mode 100644 test/dml-discard.slice create mode 100644 test/dml-override-empty.service create mode 100644 test/dml-override.slice create mode 100644 test/dml-passthrough-empty.service create mode 100644 test/dml-passthrough-set-dml.service create mode 100644 test/dml-passthrough-set-ml.service create mode 100644 test/dml-passthrough.slice create mode 100644 test/dml.slice create mode 100644 test/e.service create mode 100644 test/end.service create mode 100644 test/f.service create mode 100644 test/fuzz/.gitattributes create mode 100644 test/fuzz/fuzz-bus-message/crash-26bba7182dedc8848939931d9fcefcb7922f2e56 create mode 100644 test/fuzz/fuzz-bus-message/crash-29ed3c202e0ffade3cad42c8bbeb6cc68a21eb8e create mode 100644 test/fuzz/fuzz-bus-message/crash-32bf69483cbd4f2e6d46c25a2f92a472109aee45 create mode 100644 test/fuzz/fuzz-bus-message/crash-37449529b1ad867f0c2671fa80aca5d7812a2b70 create mode 100644 test/fuzz/fuzz-bus-message/crash-4162a61a79e4c5a832ca5232212f75fa560a1f75 create mode 100644 test/fuzz/fuzz-bus-message/crash-4f0211eb269e28db941961061494bfdbf3345e54 create mode 100644 test/fuzz/fuzz-bus-message/crash-603dfd98252375ac7dbced53c2ec312671939a36 create mode 100644 test/fuzz/fuzz-bus-message/crash-b88ad9ecf4aacf4a0caca5b5543953265367f084 create mode 100644 test/fuzz/fuzz-bus-message/crash-c1b37b4729b42c0c05b23cba4eed5d8102498a1e create mode 100644 test/fuzz/fuzz-bus-message/crash-d8f3941c74219b4c03532c9b244d5ea539c61af5 create mode 100644 test/fuzz/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 create mode 100644 test/fuzz/fuzz-bus-message/leak-c09c0e2256d43bc5e2d02748c8d8760e7bc25d20 create mode 100644 test/fuzz/fuzz-bus-message/message1 create mode 100644 test/fuzz/fuzz-bus-message/oss-fuzz-14016 create mode 100644 test/fuzz/fuzz-bus-message/timeout-08ee8f6446a4064db064e8e0b3d220147f7d0b5b create mode 100644 test/fuzz/fuzz-calendarspec/oss-fuzz-14108 create mode 100644 test/fuzz/fuzz-catalog/clusterfuzz-testcase-minimized-fuzz-catalog-5674475278827520 create mode 100644 test/fuzz/fuzz-catalog/systemd.pl.catalog create mode 100644 test/fuzz/fuzz-dhcp-server/discover-existing create mode 100644 test/fuzz/fuzz-dhcp-server/discover-new create mode 100644 test/fuzz/fuzz-dhcp-server/release create mode 100644 test/fuzz/fuzz-dhcp-server/request-existing create mode 100644 test/fuzz/fuzz-dhcp-server/request-new create mode 100644 test/fuzz/fuzz-dhcp-server/request-reboot create mode 100644 test/fuzz/fuzz-dhcp-server/request-renew create mode 100644 test/fuzz/fuzz-dhcp6-client/crash-13578 create mode 100644 test/fuzz/fuzz-dhcp6-client/crash-13591 create mode 100644 test/fuzz/fuzz-dhcp6-client/crash-4003c06fce43a11fbd22f02584df2807ac333eae create mode 100644 test/fuzz/fuzz-dhcp6-client/crash-6e88fcb6b85c9436bcbe05219aa8e550194645ef create mode 100644 test/fuzz/fuzz-dhcp6-client/oss-fuzz-10746 create mode 100644 test/fuzz/fuzz-dhcp6-client/oss-fuzz-11019 create mode 100644 test/fuzz/fuzz-dns-packet/crash-497be373856c321a8a7b06589df9b2ff2e0d866a create mode 100644 test/fuzz/fuzz-dns-packet/issue-7888 create mode 100644 test/fuzz/fuzz-dns-packet/oss-fuzz-13422 create mode 100644 test/fuzz/fuzz-dns-packet/oss-fuzz-5465 create mode 100644 test/fuzz/fuzz-env-file/simple-env-file create mode 100644 test/fuzz/fuzz-fido-id-desc/crash0 create mode 100644 test/fuzz/fuzz-fido-id-desc/crash1 create mode 100644 test/fuzz/fuzz-fido-id-desc/report0 create mode 100644 test/fuzz/fuzz-fido-id-desc/report1 create mode 100644 test/fuzz/fuzz-journal-remote/crash-5a8f03d4c3a46fcded39527084f437e8e4b54b76 create mode 100644 test/fuzz/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45 create mode 100644 test/fuzz/fuzz-journal-remote/invalid-ts.txt create mode 100644 test/fuzz/fuzz-journal-remote/oss-fuzz-8658 create mode 100644 test/fuzz/fuzz-journal-remote/oss-fuzz-8659 create mode 100644 test/fuzz/fuzz-journal-remote/oss-fuzz-8686 create mode 100644 test/fuzz/fuzz-journal-remote/oss-fuzz-9341 create mode 100644 test/fuzz/fuzz-journal-remote/sample.txt create mode 100644 test/fuzz/fuzz-journald-audit/basic create mode 100644 test/fuzz/fuzz-journald-audit/crash create mode 100644 test/fuzz/fuzz-journald-kmsg/basic create mode 100644 test/fuzz/fuzz-journald-kmsg/crash-c6c04d83e73f3d1417bc0afce8fa81b99f955963 create mode 100644 test/fuzz/fuzz-journald-kmsg/dev-null create mode 100644 test/fuzz/fuzz-journald-kmsg/leak-ab161e601e82f1ec31d11e2cbae2747834ce9e43 create mode 100644 test/fuzz/fuzz-journald-kmsg/loopback create mode 100644 test/fuzz/fuzz-journald-kmsg/subsystem-loopback create mode 100644 test/fuzz/fuzz-journald-native-fd/basic create mode 100644 test/fuzz/fuzz-journald-stream/basic create mode 100644 test/fuzz/fuzz-journald-syslog/github-9795 create mode 100644 test/fuzz/fuzz-journald-syslog/github-9820 create mode 100644 test/fuzz/fuzz-journald-syslog/github-9827 create mode 100644 test/fuzz/fuzz-journald-syslog/github-9829 create mode 100644 test/fuzz/fuzz-json/crash-5639441482252288 create mode 100644 test/fuzz/fuzz-json/oss-fuzz-10908 create mode 100644 test/fuzz/fuzz-link-parser/99-default.link create mode 100644 test/fuzz/fuzz-link-parser/advertise-segv.link create mode 100644 test/fuzz/fuzz-link-parser/condition-memleak.link create mode 100644 test/fuzz/fuzz-link-parser/directives.link create mode 100644 test/fuzz/fuzz-link-parser/oss-fuzz-13878 create mode 100644 test/fuzz/fuzz-link-parser/oss-fuzz-13882 create mode 100644 test/fuzz/fuzz-lldp/basic create mode 100644 test/fuzz/fuzz-lldp/incomplete create mode 100644 test/fuzz/fuzz-lldp/oui create mode 100644 test/fuzz/fuzz-ndisc-rs/oss-fuzz-10734 create mode 100644 test/fuzz/fuzz-ndisc-rs/timeout-2815b773c712fa33bea62f541dfa3017c64ea2f1 create mode 100644 test/fuzz/fuzz-ndisc-rs/timeout-61fff7fd1e5dcc07e1b656baab29065ce634ad5b create mode 100644 test/fuzz/fuzz-netdev-parser/11-dummy.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/12-dummy.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/21-macvlan.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/21-macvtap.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/21-vlan.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-6rd-tunnel.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-bond-active-backup-slave.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-bond.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-bridge.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-erspan-tunnel.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-geneve.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-gre-tunnel.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-gretap-tunnel.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-ip6gre-tunnel.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-ip6tnl-tunnel.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-ipip-tunnel-independent.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-ipip-tunnel.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-ipvlan.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-sit-tunnel.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-tap.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-tun.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-vcan.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-veth.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-vrf.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-vti-tunnel.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-vti6-tunnel.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-vxlan.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/25-wireguard.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/26-bridge.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/27-xfrm.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/directives.netdev create mode 100644 test/fuzz/fuzz-netdev-parser/github-10615 create mode 100644 test/fuzz/fuzz-netdev-parser/github-10629 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-11279 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-11280 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-11286 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-11287 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-11296 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-11297 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-11299 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-11324 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-11344 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-13719 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-13884 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-13886 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-14157 create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-14158 create mode 100644 test/fuzz/fuzz-network-parser/21-vlan.network create mode 100644 test/fuzz/fuzz-network-parser/23-active-slave.network create mode 100644 test/fuzz/fuzz-network-parser/23-bond199.network create mode 100644 test/fuzz/fuzz-network-parser/23-emit-lldp.network create mode 100644 test/fuzz/fuzz-network-parser/23-primary-slave.network create mode 100644 test/fuzz/fuzz-network-parser/23-test1-bond199.network create mode 100644 test/fuzz/fuzz-network-parser/24-lldp.network create mode 100644 test/fuzz/fuzz-network-parser/24-search-domain.network create mode 100644 test/fuzz/fuzz-network-parser/25-address-link-section.network create mode 100644 test/fuzz/fuzz-network-parser/25-address-section-miscellaneous.network create mode 100644 test/fuzz/fuzz-network-parser/25-address-section.network create mode 100644 test/fuzz/fuzz-network-parser/25-fibrule-port-range.network create mode 100644 test/fuzz/fuzz-network-parser/25-ipv6-address-label-section.network create mode 100644 test/fuzz/fuzz-network-parser/25-link-section-unmanaged.network create mode 100644 test/fuzz/fuzz-network-parser/25-neighbor-section.network create mode 100644 test/fuzz/fuzz-network-parser/25-route-section.network create mode 100644 test/fuzz/fuzz-network-parser/25-route-tcp-window-settings.network create mode 100644 test/fuzz/fuzz-network-parser/25-route-type.network create mode 100644 test/fuzz/fuzz-network-parser/25-sysctl.network create mode 100644 test/fuzz/fuzz-network-parser/26-bridge-slave-interface-1.network create mode 100644 test/fuzz/fuzz-network-parser/26-bridge-slave-interface-2.network create mode 100644 test/fuzz/fuzz-network-parser/27-xfrm.network create mode 100644 test/fuzz/fuzz-network-parser/bridge99.network create mode 100644 test/fuzz/fuzz-network-parser/configure-without-carrier.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-anonymize.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-critical-connection.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-ipv4-dhcp-settings.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-ipv4-only-ipv6-disabled.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-ipv4-only.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-ipv6-only.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-ipv6-rapid-commit.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-listen-port.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-route-metric.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-route-table.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client-timezone-router.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-client.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-server-timezone-router.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-server-veth-peer.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-server.network create mode 100644 test/fuzz/fuzz-network-parser/dhcp-v4-server-veth-peer.network create mode 100644 test/fuzz/fuzz-network-parser/directives.network create mode 100644 test/fuzz/fuzz-network-parser/github-10639 create mode 100644 test/fuzz/fuzz-network-parser/github-13938 create mode 100644 test/fuzz/fuzz-network-parser/gretap.network create mode 100644 test/fuzz/fuzz-network-parser/gretun.network create mode 100644 test/fuzz/fuzz-network-parser/ip6gretap.network create mode 100644 test/fuzz/fuzz-network-parser/ip6tnl.network create mode 100644 test/fuzz/fuzz-network-parser/ipip.network create mode 100644 test/fuzz/fuzz-network-parser/ipv6-prefix-veth.network create mode 100644 test/fuzz/fuzz-network-parser/ipv6-prefix.network create mode 100644 test/fuzz/fuzz-network-parser/ipvlan.network create mode 100644 test/fuzz/fuzz-network-parser/macvlan.network create mode 100644 test/fuzz/fuzz-network-parser/macvtap.network create mode 100644 test/fuzz/fuzz-network-parser/oss-fuzz-11285 create mode 100644 test/fuzz/fuzz-network-parser/oss-fuzz-11302 create mode 100644 test/fuzz/fuzz-network-parser/oss-fuzz-11314 create mode 100644 test/fuzz/fuzz-network-parser/oss-fuzz-11345 create mode 100644 test/fuzz/fuzz-network-parser/oss-fuzz-13059 create mode 100644 test/fuzz/fuzz-network-parser/oss-fuzz-13354 create mode 100644 test/fuzz/fuzz-network-parser/oss-fuzz-13433 create mode 100644 test/fuzz/fuzz-network-parser/oss-fuzz-13888 create mode 100644 test/fuzz/fuzz-network-parser/oss-fuzz-15678 create mode 100644 test/fuzz/fuzz-network-parser/routing-policy-rule.network create mode 100644 test/fuzz/fuzz-network-parser/sit.network create mode 100644 test/fuzz/fuzz-network-parser/test-static.network create mode 100644 test/fuzz/fuzz-network-parser/vti.network create mode 100644 test/fuzz/fuzz-network-parser/vti6.network create mode 100644 test/fuzz/fuzz-network-parser/vxlan.network create mode 100644 test/fuzz/fuzz-nspawn-oci/basic.json create mode 100644 test/fuzz/fuzz-nspawn-oci/crash-bffbd2085d4e95c47e9749b3f4a2dbc0580c20d3 create mode 100644 test/fuzz/fuzz-nspawn-oci/crash-db0595479ee2e625fa5419a821009b5eb4d809b7 create mode 100644 test/fuzz/fuzz-nspawn-settings/basic-config create mode 100644 test/fuzz/fuzz-nspawn-settings/leak-4ff0e2498f596a77ea68d185c61e9e9ff9bb657f create mode 100644 test/fuzz/fuzz-nspawn-settings/oss-fuzz-13691 create mode 100644 test/fuzz/fuzz-udev-database/sample.txt create mode 100644 test/fuzz/fuzz-udev-rules/50-udev-default.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-block.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-cdrom_id.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-drm.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-evdev.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-input-id.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-persistent-alsa.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-persistent-input.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-persistent-storage-tape.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-persistent-storage.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-persistent-v4l.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-sensor.rules create mode 100644 test/fuzz/fuzz-udev-rules/60-serial.rules create mode 100644 test/fuzz/fuzz-udev-rules/64-btrfs.rules create mode 100644 test/fuzz/fuzz-udev-rules/70-joystick.rules create mode 100644 test/fuzz/fuzz-udev-rules/70-mouse.rules create mode 100644 test/fuzz/fuzz-udev-rules/70-touchpad.rules create mode 100644 test/fuzz/fuzz-udev-rules/75-net-description.rules create mode 100644 test/fuzz/fuzz-udev-rules/75-probe_mtd.rules create mode 100644 test/fuzz/fuzz-udev-rules/78-sound-card.rules create mode 100644 test/fuzz/fuzz-udev-rules/80-drivers.rules create mode 100644 test/fuzz/fuzz-udev-rules/80-net-setup-link.rules create mode 100644 test/fuzz/fuzz-udev-rules/99-systemd.rules create mode 100644 test/fuzz/fuzz-udev-rules/oss-fuzz-12980 create mode 100644 "test/fuzz/fuzz-unit-file/dev-mapper-fedora_krowka\\x2dswap.swap" create mode 100644 test/fuzz/fuzz-unit-file/directives.scope create mode 100644 test/fuzz/fuzz-unit-file/directives.service create mode 100644 test/fuzz/fuzz-unit-file/empty.scope create mode 100644 test/fuzz/fuzz-unit-file/machine.slice create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-10007 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-11569 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-13125 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-6884 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-6885 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-6886 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-6892 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-6897 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-6897-evverx create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-6908 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-6917 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-6977 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-6977-unminimized create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-7004 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-8064 create mode 100644 test/fuzz/fuzz-unit-file/oss-fuzz-8827 create mode 100644 test/fuzz/fuzz-unit-file/proc-sys-fs-binfmt_misc.automount create mode 100644 test/fuzz/fuzz-unit-file/syslog.socket create mode 100644 test/fuzz/fuzz-unit-file/systemd-ask-password-console.path create mode 100644 test/fuzz/fuzz-unit-file/systemd-machined.service create mode 100644 test/fuzz/fuzz-unit-file/systemd-resolved.service create mode 100644 test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer create mode 100644 test/fuzz/fuzz-unit-file/timers.target create mode 100644 test/fuzz/fuzz-unit-file/var-lib-machines.mount create mode 100644 test/fuzz/fuzz-varlink/array create mode 100644 test/fuzz/fuzz-varlink/do-something create mode 100644 test/fuzz/fuzz-varlink/huge-method create mode 100644 test/fuzz/fuzz-varlink/method-call create mode 100644 test/fuzz/fuzz-varlink/method-error create mode 100644 test/fuzz/fuzz-varlink/method-reply create mode 100644 test/fuzz/fuzz-varlink/oss-fuzz-14688 create mode 100644 test/fuzz/fuzz-varlink/oss-fuzz-14708 create mode 100644 test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf create mode 100644 test/fuzz/meson.build create mode 100644 test/g.service create mode 100644 test/grandchild.service create mode 100644 test/h.service create mode 100644 test/hello-after-sleep.target create mode 100644 test/hello.service create mode 100755 test/hwdb-test.sh create mode 100644 test/hwdb.d/10-bad.hwdb create mode 100644 test/i.service create mode 100644 test/journal-data/journal-1.txt create mode 100644 test/journal-data/journal-2.txt create mode 100644 test/loopy.service create mode 100644 test/loopy.service.d/compat.conf create mode 120000 test/loopy2.service create mode 100644 test/loopy3.service create mode 120000 test/loopy4.service create mode 100644 test/meson.build create mode 100755 test/mkosi.build.networkd-test create mode 100644 test/mkosi.default.networkd-test create mode 100644 test/mkosi.nspawn.networkd-test create mode 100755 test/mocks/fsck create mode 100755 test/networkd-test.py create mode 100644 test/nomem.slice create mode 100644 test/nomemleaf.service create mode 100644 test/parent-deep.slice create mode 100644 test/parent.slice create mode 100755 test/rule-syntax-check.py create mode 100755 test/run-integration-tests.sh create mode 100755 test/run-unit-tests.py create mode 100644 test/sched_idle_bad.service create mode 100644 test/sched_idle_ok.service create mode 100644 test/sched_rr_bad.service create mode 100644 test/sched_rr_change.service create mode 100644 test/sched_rr_ok.service create mode 120000 test/shutdown.target create mode 100644 test/sleep.service create mode 120000 test/sockets.target create mode 100644 test/son.service create mode 100644 test/splash.bmp create mode 100755 test/sys-script.py create mode 120000 test/sysinit.target create mode 100755 test/sysv-generator-test.py create mode 100755 test/test-efi-create-disk.sh create mode 100755 test/test-exec-deserialization.py create mode 100644 test/test-execute/exec-ambientcapabilities-merge-nfsnobody.service create mode 100644 test/test-execute/exec-ambientcapabilities-merge-nobody.service create mode 100644 test/test-execute/exec-ambientcapabilities-merge.service create mode 100644 test/test-execute/exec-ambientcapabilities-nfsnobody.service create mode 100644 test/test-execute/exec-ambientcapabilities-nobody.service create mode 100644 test/test-execute/exec-ambientcapabilities.service create mode 100644 test/test-execute/exec-basic.service create mode 100644 test/test-execute/exec-bindpaths.service create mode 100644 test/test-execute/exec-capabilityboundingset-invert.service create mode 100644 test/test-execute/exec-capabilityboundingset-merge.service create mode 100644 test/test-execute/exec-capabilityboundingset-reset.service create mode 100644 test/test-execute/exec-capabilityboundingset-simple.service create mode 100644 test/test-execute/exec-condition-failed.service create mode 100644 test/test-execute/exec-condition-skip.service create mode 100644 test/test-execute/exec-cpuaffinity1.service create mode 100644 test/test-execute/exec-cpuaffinity2.service create mode 100644 test/test-execute/exec-cpuaffinity3.service create mode 100644 test/test-execute/exec-dynamicuser-fixeduser-adm.service create mode 100644 test/test-execute/exec-dynamicuser-fixeduser-games.service create mode 100644 test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service create mode 100644 test/test-execute/exec-dynamicuser-fixeduser.service create mode 100644 test/test-execute/exec-dynamicuser-statedir-migrate-step1.service create mode 100644 test/test-execute/exec-dynamicuser-statedir-migrate-step2.service create mode 100644 test/test-execute/exec-dynamicuser-statedir.service create mode 100644 test/test-execute/exec-dynamicuser-supplementarygroups.service create mode 100644 test/test-execute/exec-environment-empty.service create mode 100644 test/test-execute/exec-environment-multiple.service create mode 100644 test/test-execute/exec-environment-no-substitute.service create mode 100644 test/test-execute/exec-environment.service create mode 100644 test/test-execute/exec-environmentfile.service create mode 100644 test/test-execute/exec-group-nfsnobody.service create mode 100644 test/test-execute/exec-group-nobody.service create mode 100644 test/test-execute/exec-group-nogroup.service create mode 100644 test/test-execute/exec-group.service create mode 100644 test/test-execute/exec-ignoresigpipe-no.service create mode 100644 test/test-execute/exec-ignoresigpipe-yes.service create mode 100644 test/test-execute/exec-inaccessiblepaths-mount-propagation.service create mode 100644 test/test-execute/exec-inaccessiblepaths-sys.service create mode 100644 test/test-execute/exec-ioschedulingclass-best-effort.service create mode 100644 test/test-execute/exec-ioschedulingclass-idle.service create mode 100644 test/test-execute/exec-ioschedulingclass-none.service create mode 100644 test/test-execute/exec-ioschedulingclass-realtime.service create mode 100644 test/test-execute/exec-oomscoreadjust-negative.service create mode 100644 test/test-execute/exec-oomscoreadjust-positive.service create mode 100644 test/test-execute/exec-passenvironment-absent.service create mode 100644 test/test-execute/exec-passenvironment-empty.service create mode 100644 test/test-execute/exec-passenvironment-repeated.service create mode 100644 test/test-execute/exec-passenvironment.service create mode 100644 test/test-execute/exec-personality-aarch64.service create mode 100644 test/test-execute/exec-personality-ppc64.service create mode 100644 test/test-execute/exec-personality-ppc64le.service create mode 100644 test/test-execute/exec-personality-s390.service create mode 100644 test/test-execute/exec-personality-x86-64.service create mode 100644 test/test-execute/exec-personality-x86.service create mode 100644 test/test-execute/exec-privatedevices-disabled-by-prefix.service create mode 100644 test/test-execute/exec-privatedevices-no-capability-mknod.service create mode 100644 test/test-execute/exec-privatedevices-no-capability-sys-rawio.service create mode 100644 test/test-execute/exec-privatedevices-no.service create mode 100644 test/test-execute/exec-privatedevices-yes-capability-mknod.service create mode 100644 test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service create mode 100644 test/test-execute/exec-privatedevices-yes.service create mode 100644 test/test-execute/exec-privatenetwork-yes.service create mode 100644 test/test-execute/exec-privatetmp-no.service create mode 100644 test/test-execute/exec-privatetmp-yes.service create mode 100644 test/test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service create mode 100644 test/test-execute/exec-protectkernellogs-no-capabilities.service create mode 100644 test/test-execute/exec-protectkernellogs-yes-capabilities.service create mode 100644 test/test-execute/exec-protectkernelmodules-no-capabilities.service create mode 100644 test/test-execute/exec-protectkernelmodules-yes-capabilities.service create mode 100644 test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service create mode 100644 test/test-execute/exec-readonlypaths-mount-propagation.service create mode 100644 test/test-execute/exec-readonlypaths-simple.service create mode 100644 test/test-execute/exec-readonlypaths-with-bindpaths.service create mode 100644 test/test-execute/exec-readonlypaths.service create mode 100644 test/test-execute/exec-readwritepaths-mount-propagation.service create mode 100644 test/test-execute/exec-restrictnamespaces-merge-all.service create mode 100644 test/test-execute/exec-restrictnamespaces-merge-and.service create mode 100644 test/test-execute/exec-restrictnamespaces-merge-or.service create mode 100644 test/test-execute/exec-restrictnamespaces-mnt-blacklist.service create mode 100644 test/test-execute/exec-restrictnamespaces-mnt.service create mode 100644 test/test-execute/exec-restrictnamespaces-no.service create mode 100644 test/test-execute/exec-restrictnamespaces-yes.service create mode 100644 test/test-execute/exec-runtimedirectory-mode.service create mode 100644 test/test-execute/exec-runtimedirectory-owner-nfsnobody.service create mode 100644 test/test-execute/exec-runtimedirectory-owner-nobody.service create mode 100644 test/test-execute/exec-runtimedirectory-owner-nogroup.service create mode 100644 test/test-execute/exec-runtimedirectory-owner.service create mode 100644 test/test-execute/exec-runtimedirectory.service create mode 100644 test/test-execute/exec-specifier-interpolation.service create mode 100644 test/test-execute/exec-specifier.service create mode 100644 test/test-execute/exec-specifier@.service create mode 100644 test/test-execute/exec-standardinput-data.service create mode 100644 test/test-execute/exec-standardinput-file-cat.service create mode 100644 test/test-execute/exec-standardinput-file.service create mode 100644 test/test-execute/exec-standardoutput-append.service create mode 100644 test/test-execute/exec-standardoutput-file.service create mode 100644 test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service create mode 100644 test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service create mode 100644 test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service create mode 100644 test/test-execute/exec-supplementarygroups-single-group-user.service create mode 100644 test/test-execute/exec-supplementarygroups-single-group.service create mode 100644 test/test-execute/exec-supplementarygroups.service create mode 100644 test/test-execute/exec-systemcallerrornumber-name.service create mode 100644 test/test-execute/exec-systemcallerrornumber-number.service create mode 100644 test/test-execute/exec-systemcallfilter-failing.service create mode 100644 test/test-execute/exec-systemcallfilter-failing2.service create mode 100644 test/test-execute/exec-systemcallfilter-not-failing.service create mode 100644 test/test-execute/exec-systemcallfilter-not-failing2.service create mode 100644 test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service create mode 100644 test/test-execute/exec-systemcallfilter-system-user-nobody.service create mode 100644 test/test-execute/exec-systemcallfilter-system-user.service create mode 100644 test/test-execute/exec-systemcallfilter-with-errno-multi.service create mode 100644 test/test-execute/exec-systemcallfilter-with-errno-name.service create mode 100644 test/test-execute/exec-systemcallfilter-with-errno-number.service create mode 100644 test/test-execute/exec-temporaryfilesystem-options.service create mode 100644 test/test-execute/exec-temporaryfilesystem-ro.service create mode 100644 test/test-execute/exec-temporaryfilesystem-rw.service create mode 100644 test/test-execute/exec-temporaryfilesystem-usr.service create mode 100644 test/test-execute/exec-umask-0177.service create mode 100644 test/test-execute/exec-umask-default.service create mode 100644 test/test-execute/exec-unsetenvironment.service create mode 100644 test/test-execute/exec-user-nfsnobody.service create mode 100644 test/test-execute/exec-user-nobody.service create mode 100644 test/test-execute/exec-user.service create mode 100644 test/test-execute/exec-workingdirectory-trailing-dot.service create mode 100644 test/test-execute/exec-workingdirectory.service create mode 100644 test/test-functions create mode 100644 test/test-network/conf/10-dropin-test.netdev create mode 100644 test/test-network/conf/10-dropin-test.netdev.d/mac.conf create mode 100644 test/test-network/conf/10-dropin-test.netdev.d/name.conf create mode 100644 test/test-network/conf/11-dummy-mtu.netdev create mode 100644 test/test-network/conf/11-dummy.netdev create mode 100644 test/test-network/conf/11-dummy.network create mode 100644 test/test-network/conf/12-dummy.netdev create mode 100644 test/test-network/conf/13-not-match-udev-property.network create mode 100644 test/test-network/conf/14-match-udev-property.network create mode 100644 test/test-network/conf/15-name-conflict-test.netdev create mode 100644 test/test-network/conf/21-macvlan.netdev create mode 100644 test/test-network/conf/21-macvtap.netdev create mode 100644 test/test-network/conf/21-vlan-test1.network create mode 100644 test/test-network/conf/21-vlan-test1.network.d/override.conf create mode 100644 test/test-network/conf/21-vlan.netdev create mode 100644 test/test-network/conf/21-vlan.netdev.d/override.conf create mode 100644 test/test-network/conf/21-vlan.network create mode 100644 test/test-network/conf/23-active-slave.network create mode 100644 test/test-network/conf/23-bond199.network create mode 100644 test/test-network/conf/23-emit-lldp.network create mode 100644 test/test-network/conf/23-primary-slave.network create mode 100644 test/test-network/conf/24-keep-configuration-static.network create mode 100644 test/test-network/conf/24-lldp.network create mode 100644 test/test-network/conf/24-search-domain.network create mode 100644 test/test-network/conf/25-6rd-tunnel.netdev create mode 100644 test/test-network/conf/25-address-link-section.network create mode 100644 test/test-network/conf/25-address-preferred-lifetime-zero.network create mode 100644 test/test-network/conf/25-address-static.network create mode 100644 test/test-network/conf/25-bind-carrier.network create mode 100644 test/test-network/conf/25-bond-active-backup-slave.netdev create mode 100644 test/test-network/conf/25-bond-balanced-tlb.netdev create mode 100644 test/test-network/conf/25-bond.netdev create mode 100644 test/test-network/conf/25-bridge-configure-without-carrier.network create mode 100644 test/test-network/conf/25-bridge.netdev create mode 100644 test/test-network/conf/25-bridge.network create mode 100644 test/test-network/conf/25-erspan-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-erspan-tunnel.netdev create mode 100644 test/test-network/conf/25-fibrule-invert.network create mode 100644 test/test-network/conf/25-fibrule-port-range.network create mode 100644 test/test-network/conf/25-fou-gre.netdev create mode 100644 test/test-network/conf/25-fou-gretap.netdev create mode 100644 test/test-network/conf/25-fou-ipip.netdev create mode 100644 test/test-network/conf/25-fou-ipproto-gre.netdev create mode 100644 test/test-network/conf/25-fou-ipproto-ipip.netdev create mode 100644 test/test-network/conf/25-fou-sit.netdev create mode 100644 test/test-network/conf/25-gateway-next-static.network create mode 100644 test/test-network/conf/25-gateway-static.network create mode 100644 test/test-network/conf/25-geneve.netdev create mode 100644 test/test-network/conf/25-gre-tunnel-any-any.netdev create mode 100644 test/test-network/conf/25-gre-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-gre-tunnel-remote-any.netdev create mode 100644 test/test-network/conf/25-gre-tunnel.netdev create mode 100644 test/test-network/conf/25-gretap-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-gretap-tunnel.netdev create mode 100644 test/test-network/conf/25-ip6gre-tunnel-any-any.netdev create mode 100644 test/test-network/conf/25-ip6gre-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-ip6gre-tunnel-remote-any.netdev create mode 100644 test/test-network/conf/25-ip6gre-tunnel.netdev create mode 100644 test/test-network/conf/25-ip6gretap-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-ip6gretap-tunnel.netdev create mode 100644 test/test-network/conf/25-ip6tnl-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-ip6tnl-tunnel-remote-any.netdev create mode 100644 test/test-network/conf/25-ip6tnl-tunnel.netdev create mode 100644 test/test-network/conf/25-ipip-tunnel-any-any.netdev create mode 100644 test/test-network/conf/25-ipip-tunnel-independent-loopback.netdev create mode 100644 test/test-network/conf/25-ipip-tunnel-independent.netdev create mode 100644 test/test-network/conf/25-ipip-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-ipip-tunnel-remote-any.netdev create mode 100644 test/test-network/conf/25-ipip-tunnel.netdev create mode 100644 test/test-network/conf/25-ipv6-address-label-section.network create mode 100644 test/test-network/conf/25-ipvlan.netdev create mode 100644 test/test-network/conf/25-ipvtap.netdev create mode 100644 test/test-network/conf/25-isatap-tunnel.netdev create mode 100644 test/test-network/conf/25-l2tp-dummy.network create mode 100644 test/test-network/conf/25-l2tp-ip.netdev create mode 100644 test/test-network/conf/25-l2tp-udp.netdev create mode 100644 test/test-network/conf/25-l2tp.network create mode 100644 test/test-network/conf/25-link-local-addressing-no.network create mode 100644 test/test-network/conf/25-link-local-addressing-yes.network create mode 100644 test/test-network/conf/25-link-section-unmanaged.network create mode 100644 test/test-network/conf/25-macsec.key create mode 100644 test/test-network/conf/25-macsec.netdev create mode 100644 test/test-network/conf/25-macsec.network create mode 100644 test/test-network/conf/25-neighbor-ip-dummy.network create mode 100644 test/test-network/conf/25-neighbor-ip.network create mode 100644 test/test-network/conf/25-neighbor-ipv6.network create mode 100644 test/test-network/conf/25-neighbor-next.network create mode 100644 test/test-network/conf/25-neighbor-section.network create mode 100644 test/test-network/conf/25-netdevsim.netdev create mode 100644 test/test-network/conf/25-nexthop.network create mode 100644 test/test-network/conf/25-nlmon.netdev create mode 100644 test/test-network/conf/25-qdisc.network create mode 100644 test/test-network/conf/25-route-ipv6-src.network create mode 100644 test/test-network/conf/25-route-static.network create mode 100644 test/test-network/conf/25-sit-tunnel-any-any.netdev create mode 100644 test/test-network/conf/25-sit-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-sit-tunnel-remote-any.netdev create mode 100644 test/test-network/conf/25-sit-tunnel.netdev create mode 100644 test/test-network/conf/25-sysctl-disable-ipv6.network create mode 100644 test/test-network/conf/25-sysctl.network create mode 100644 test/test-network/conf/25-tap.netdev create mode 100644 test/test-network/conf/25-tun.netdev create mode 100644 test/test-network/conf/25-tunnel-any-any.network create mode 100644 test/test-network/conf/25-tunnel-local-any.network create mode 100644 test/test-network/conf/25-tunnel-remote-any.network create mode 100644 test/test-network/conf/25-tunnel.network create mode 100644 test/test-network/conf/25-vcan.netdev create mode 100644 test/test-network/conf/25-veth-peer.network create mode 100644 test/test-network/conf/25-veth.netdev create mode 100644 test/test-network/conf/25-vrf.netdev create mode 100644 test/test-network/conf/25-vrf.network create mode 100644 test/test-network/conf/25-vti-tunnel-any-any.netdev create mode 100644 test/test-network/conf/25-vti-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-vti-tunnel-remote-any.netdev create mode 100644 test/test-network/conf/25-vti-tunnel.netdev create mode 100644 test/test-network/conf/25-vti6-tunnel-local-any.netdev create mode 100644 test/test-network/conf/25-vti6-tunnel-remote-any.netdev create mode 100644 test/test-network/conf/25-vti6-tunnel.netdev create mode 100644 test/test-network/conf/25-vxcan.netdev create mode 100644 test/test-network/conf/25-vxlan.netdev create mode 100644 test/test-network/conf/25-wireguard-23-peers.netdev create mode 100644 test/test-network/conf/25-wireguard-23-peers.network create mode 100644 test/test-network/conf/25-wireguard-preshared-key.txt create mode 100644 test/test-network/conf/25-wireguard-private-key.txt create mode 100644 test/test-network/conf/25-wireguard.netdev create mode 100644 test/test-network/conf/25-wireguard.netdev.d/peer.conf create mode 100644 test/test-network/conf/25-wireguard.network create mode 100644 test/test-network/conf/25-xfrm-independent.netdev create mode 100644 test/test-network/conf/25-xfrm.netdev create mode 100644 test/test-network/conf/26-bridge-slave-interface-1.network create mode 100644 test/test-network/conf/26-bridge-slave-interface-2.network create mode 100644 test/test-network/conf/26-bridge-vlan-master.network create mode 100644 test/test-network/conf/26-bridge-vlan-slave.network create mode 100644 test/test-network/conf/26-bridge.netdev create mode 100644 test/test-network/conf/26-link-local-addressing-ipv6.network create mode 100644 test/test-network/conf/6rd.network create mode 100644 test/test-network/conf/bond-slave.network create mode 100644 test/test-network/conf/bond99.network create mode 100644 test/test-network/conf/bridge99-ignore-carrier-loss.network create mode 100644 test/test-network/conf/bridge99.network create mode 100644 test/test-network/conf/configure-without-carrier.network create mode 100644 test/test-network/conf/dhcp-client-anonymize.network create mode 100644 test/test-network/conf/dhcp-client-gateway-onlink-implicit.network create mode 100644 test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network create mode 100644 test/test-network/conf/dhcp-client-ipv4-only-ipv6-disabled.network create mode 100644 test/test-network/conf/dhcp-client-ipv4-only.network create mode 100644 test/test-network/conf/dhcp-client-ipv6-only.network create mode 100644 test/test-network/conf/dhcp-client-ipv6-rapid-commit.network create mode 100644 test/test-network/conf/dhcp-client-keep-configuration-dhcp-on-stop.network create mode 100644 test/test-network/conf/dhcp-client-keep-configuration-dhcp.network create mode 100644 test/test-network/conf/dhcp-client-listen-port.network create mode 100644 test/test-network/conf/dhcp-client-reassign-static-routes-ipv4.network create mode 100644 test/test-network/conf/dhcp-client-reassign-static-routes-ipv6.network create mode 100644 test/test-network/conf/dhcp-client-route-metric.network create mode 100644 test/test-network/conf/dhcp-client-route-table.network create mode 100644 test/test-network/conf/dhcp-client-timezone-router.network create mode 100644 test/test-network/conf/dhcp-client-use-dns-ipv4-and-ra.network create mode 100644 test/test-network/conf/dhcp-client-use-dns-ipv4.network create mode 100644 test/test-network/conf/dhcp-client-use-dns-no.network create mode 100644 test/test-network/conf/dhcp-client-use-dns-yes.network create mode 100644 test/test-network/conf/dhcp-client-use-domains.network create mode 100644 test/test-network/conf/dhcp-client-vrf.network create mode 100644 test/test-network/conf/dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network create mode 100644 test/test-network/conf/dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network create mode 100644 test/test-network/conf/dhcp-client-with-static-address.network create mode 100644 test/test-network/conf/dhcp-client.network create mode 100644 test/test-network/conf/dhcp-server-timezone-router.network create mode 100644 test/test-network/conf/dhcp-server-veth-peer.network create mode 100644 test/test-network/conf/dhcp-server.network create mode 100644 test/test-network/conf/dhcp-v4-server-veth-peer.network create mode 100644 test/test-network/conf/erspan.network create mode 100644 test/test-network/conf/gretap.network create mode 100644 test/test-network/conf/gretun.network create mode 100644 test/test-network/conf/ip6gretap.network create mode 100644 test/test-network/conf/ip6gretun.network create mode 100644 test/test-network/conf/ip6tnl.network create mode 100644 test/test-network/conf/ipip.network create mode 100644 test/test-network/conf/ipv6-prefix-veth.network create mode 100644 test/test-network/conf/ipv6-prefix.network create mode 100644 test/test-network/conf/ipv6ra-prefix-client.network create mode 100644 test/test-network/conf/ipv6ra-prefix.network create mode 100644 test/test-network/conf/ipvlan.network create mode 100644 test/test-network/conf/ipvtap.network create mode 100644 test/test-network/conf/isatap.network create mode 100644 test/test-network/conf/macsec.network create mode 100644 test/test-network/conf/macvlan.network create mode 100644 test/test-network/conf/macvtap.network create mode 100644 test/test-network/conf/netdev-link-local-addressing-yes.network create mode 100644 test/test-network/conf/routing-policy-rule-dummy98.network create mode 100644 test/test-network/conf/routing-policy-rule-test1.network create mode 100644 test/test-network/conf/sit.network create mode 100644 test/test-network/conf/state-file-tests.network create mode 100644 test/test-network/conf/vlan6.netdev create mode 100644 test/test-network/conf/vlan6.network create mode 100644 test/test-network/conf/vti.network create mode 100644 test/test-network/conf/vti6.network create mode 100644 test/test-network/conf/vxlan-test1.network create mode 100644 test/test-network/conf/vxlan.network create mode 100644 test/test-network/conf/xfrm.network create mode 100755 test/test-network/systemd-networkd-tests.py create mode 120000 test/test-path/basic.target create mode 100644 test/test-path/path-changed.path create mode 120000 test/test-path/path-changed.service create mode 100644 test/test-path/path-directorynotempty.path create mode 120000 test/test-path/path-directorynotempty.service create mode 100644 test/test-path/path-exists.path create mode 120000 test/test-path/path-exists.service create mode 100644 test/test-path/path-existsglob.path create mode 120000 test/test-path/path-existsglob.service create mode 100644 test/test-path/path-makedirectory.path create mode 120000 test/test-path/path-makedirectory.service create mode 100644 test/test-path/path-modified.path create mode 120000 test/test-path/path-modified.service create mode 100644 test/test-path/path-mycustomunit.service create mode 100644 test/test-path/path-service.service create mode 100644 test/test-path/path-unit.path create mode 120000 test/test-path/paths.target create mode 120000 test/test-path/sysinit.target create mode 100644 test/test-resolve/_443._tcp.fedoraproject.org.pkts create mode 100644 test/test-resolve/_openpgpkey.fedoraproject.org.pkts create mode 100644 test/test-resolve/fake-caa.pkts create mode 100644 test/test-resolve/fedoraproject.org.pkts create mode 100644 test/test-resolve/gandi.net.pkts create mode 100644 test/test-resolve/google.com.pkts create mode 100644 test/test-resolve/kyhwana.org.pkts create mode 100644 test/test-resolve/root.pkts create mode 100644 test/test-resolve/sw1a1aa-sw1a2aa-sw1a2ab-sw1a2ac.find.me.uk.pkts create mode 100644 test/test-resolve/teamits.com.pkts create mode 100644 test/test-resolve/zbyszek@fedoraproject.org.pkts create mode 100644 test/test-umount/empty.mountinfo create mode 100644 test/test-umount/example.swaps create mode 100644 test/test-umount/garbled.mountinfo create mode 100644 test/test-umount/rhbug-1554943.mountinfo create mode 100644 test/testsuite.target create mode 120000 test/timers.target create mode 100755 test/udev-test.pl create mode 100644 test/unit-.service.d/10-override.conf create mode 100644 test/unit-with-.service.d/20-override.conf create mode 100644 test/unit-with-multiple-.service.d/20-override.conf create mode 100644 test/unit-with-multiple-.service.d/30-override.conf create mode 100644 test/unit-with-multiple-dashes.service create mode 100644 test/unit-with-multiple-dashes.service.d/10-override.conf create mode 100644 test/unstoppable.service create mode 100644 tmpfiles.d/etc.conf.m4 create mode 100644 tmpfiles.d/home.conf create mode 100644 tmpfiles.d/journal-nocow.conf create mode 100644 tmpfiles.d/legacy.conf create mode 100644 tmpfiles.d/meson.build create mode 100644 tmpfiles.d/portables.conf create mode 100644 tmpfiles.d/static-nodes-permissions.conf.in create mode 100644 tmpfiles.d/systemd-nologin.conf create mode 100644 tmpfiles.d/systemd-nspawn.conf create mode 100644 tmpfiles.d/systemd-tmp.conf create mode 100644 tmpfiles.d/systemd.conf.m4 create mode 100644 tmpfiles.d/tmp.conf create mode 100644 tmpfiles.d/var.conf.m4 create mode 100644 tmpfiles.d/x11.conf create mode 100755 tools/add-git-hook.sh create mode 100755 tools/catalog-report.py create mode 100755 tools/check-directives.sh create mode 100755 tools/check-includes.pl create mode 100755 tools/choose-default-locale.sh create mode 100644 tools/chromiumos/LICENSE create mode 100644 tools/chromiumos/gen_autosuspend_rules.py create mode 100755 tools/coverity.sh create mode 100755 tools/find-build-dir.sh create mode 100755 tools/find-double-newline.sh create mode 100755 tools/find-tabs.sh create mode 100644 tools/gdb-sd_dump_hashmaps.py create mode 100755 tools/generate-gperfs.py create mode 100755 tools/make-autosuspend-rules.py create mode 100755 tools/make-directive-index.py create mode 100755 tools/make-man-index.py create mode 100755 tools/make-man-rules.py create mode 100755 tools/meson-apply-m4.sh create mode 100755 tools/meson-autosuspend-update.sh create mode 100755 tools/meson-build.sh create mode 100755 tools/meson-check-api-docs.sh create mode 100755 tools/meson-check-compilation.sh create mode 100755 tools/meson-check-help.sh create mode 100755 tools/meson-git-contrib.sh create mode 100755 tools/meson-hwdb-update.sh create mode 100755 tools/meson-make-symlink.sh create mode 100755 tools/meson-vcs-tag.sh create mode 100755 tools/oss-fuzz.sh create mode 100755 tools/xml_helper.py create mode 100644 travis-ci/.dockerignore create mode 100644 travis-ci/Dockerfile create mode 100755 travis-ci/managers/debian.sh create mode 100755 travis-ci/managers/fedora.sh create mode 100755 travis-ci/managers/fuzzbuzz.sh create mode 100755 travis-ci/managers/fuzzit.sh create mode 100644 travis-ci/managers/travis_wait.bash create mode 100644 travis-ci/requirements.txt create mode 100755 travis-ci/scripts/build-docker-image.sh create mode 100755 travis-ci/tools/get-coverity.sh create mode 100644 units/basic.target create mode 100644 units/bluetooth.target create mode 100644 units/boot-complete.target create mode 100644 units/console-getty.service.m4 create mode 100644 units/container-getty@.service.m4 create mode 100644 units/cryptsetup-pre.target create mode 100644 units/cryptsetup.target create mode 100644 units/debug-shell.service.in create mode 100644 units/dev-hugepages.mount create mode 100644 units/dev-mqueue.mount create mode 100644 units/emergency.service.in create mode 100644 units/emergency.target create mode 100644 units/exit.target create mode 100644 units/final.target create mode 100644 units/getty-pre.target create mode 100644 units/getty.target create mode 100644 units/getty@.service.m4 create mode 100644 units/graphical.target create mode 100644 units/halt.target create mode 100644 units/hibernate.target create mode 100644 units/hybrid-sleep.target create mode 100644 units/initrd-cleanup.service.in create mode 100644 units/initrd-fs.target create mode 100644 units/initrd-parse-etc.service.in create mode 100644 units/initrd-root-device.target create mode 100644 units/initrd-root-fs.target create mode 100644 units/initrd-switch-root.service.in create mode 100644 units/initrd-switch-root.target create mode 100644 units/initrd-udevadm-cleanup-db.service.in create mode 100644 units/initrd.target create mode 100644 units/kexec.target create mode 100644 units/kmod-static-nodes.service.in create mode 100644 units/ldconfig.service create mode 100644 units/local-fs-pre.target create mode 100644 units/local-fs.target create mode 100644 units/machine.slice create mode 100644 units/machines.target create mode 100755 units/meson-add-wants.sh create mode 100644 units/meson.build create mode 100644 units/multi-user.target create mode 100644 units/network-online.target create mode 100644 units/network-pre.target create mode 100644 units/network.target create mode 100644 units/nss-lookup.target create mode 100644 units/nss-user-lookup.target create mode 100644 units/paths.target create mode 100644 units/poweroff.target create mode 100644 units/printer.target create mode 100644 units/proc-sys-fs-binfmt_misc.automount create mode 100644 units/proc-sys-fs-binfmt_misc.mount create mode 100644 units/quotaon.service.in create mode 100644 units/rc-local.service.in create mode 100644 units/reboot.target create mode 100644 units/remote-cryptsetup.target create mode 100644 units/remote-fs-pre.target create mode 100644 units/remote-fs.target create mode 100644 units/rescue.service.in create mode 100644 units/rescue.target create mode 100644 units/rpcbind.target create mode 100644 units/serial-getty@.service.m4 create mode 100644 units/shutdown.target create mode 100644 units/sigpwr.target create mode 100644 units/sleep.target create mode 100644 units/slices.target create mode 100644 units/smartcard.target create mode 100644 units/sockets.target create mode 100644 units/sound.target create mode 100644 units/suspend-then-hibernate.target create mode 100644 units/suspend.target create mode 100644 units/swap.target create mode 100644 units/sys-fs-fuse-connections.mount create mode 100644 units/sys-kernel-config.mount create mode 100644 units/sys-kernel-debug.mount create mode 100644 units/sysinit.target create mode 100644 units/syslog.socket create mode 100644 units/system-update-cleanup.service create mode 100644 units/system-update-pre.target create mode 100644 units/system-update.target create mode 100644 units/systemd-ask-password-console.path create mode 100644 units/systemd-ask-password-console.service.in create mode 100644 units/systemd-ask-password-wall.path create mode 100644 units/systemd-ask-password-wall.service.in create mode 100644 units/systemd-backlight@.service.in create mode 100644 units/systemd-binfmt.service.in create mode 100644 units/systemd-bless-boot.service.in create mode 100644 units/systemd-boot-check-no-failures.service.in create mode 100644 units/systemd-boot-system-token.service.in create mode 100644 units/systemd-coredump.socket create mode 100644 units/systemd-coredump@.service.in create mode 100644 units/systemd-exit.service create mode 100644 units/systemd-firstboot.service.in create mode 100644 units/systemd-fsck-root.service.in create mode 100644 units/systemd-fsck@.service.in create mode 100644 units/systemd-halt.service.in create mode 100644 units/systemd-hibernate-resume@.service.in create mode 100644 units/systemd-hibernate.service.in create mode 100644 units/systemd-hostnamed.service.in create mode 100644 units/systemd-hwdb-update.service.in create mode 100644 units/systemd-hybrid-sleep.service.in create mode 100644 units/systemd-importd.service.in create mode 100644 units/systemd-initctl.service.in create mode 100644 units/systemd-initctl.socket create mode 100644 units/systemd-journal-catalog-update.service.in create mode 100644 units/systemd-journal-flush.service.in create mode 100644 units/systemd-journal-gatewayd.service.in create mode 100644 units/systemd-journal-gatewayd.socket create mode 100644 units/systemd-journal-remote.service.in create mode 100644 units/systemd-journal-remote.socket create mode 100644 units/systemd-journal-upload.service.in create mode 100644 units/systemd-journald-audit.socket create mode 100644 units/systemd-journald-dev-log.socket create mode 100644 units/systemd-journald.service.in create mode 100644 units/systemd-journald.socket create mode 100644 units/systemd-kexec.service.in create mode 100644 units/systemd-localed.service.in create mode 100644 units/systemd-logind.service.in create mode 100644 units/systemd-machine-id-commit.service.in create mode 100644 units/systemd-machined.service.in create mode 100644 units/systemd-modules-load.service.in create mode 100644 units/systemd-network-generator.service.in create mode 100644 units/systemd-networkd-wait-online.service.in create mode 100644 units/systemd-networkd.service.in create mode 100644 units/systemd-networkd.socket create mode 100644 units/systemd-nspawn@.service.in create mode 100644 units/systemd-portabled.service.in create mode 100644 units/systemd-poweroff.service create mode 100644 units/systemd-pstore.service.in create mode 100644 units/systemd-quotacheck.service.in create mode 100644 units/systemd-random-seed.service.in create mode 100644 units/systemd-reboot.service create mode 100644 units/systemd-remount-fs.service.in create mode 100644 units/systemd-resolved.service.in create mode 100644 units/systemd-rfkill.service.in create mode 100644 units/systemd-rfkill.socket create mode 100644 units/systemd-suspend-then-hibernate.service.in create mode 100644 units/systemd-suspend.service.in create mode 100644 units/systemd-sysctl.service.in create mode 100644 units/systemd-sysusers.service.in create mode 100644 units/systemd-time-wait-sync.service.in create mode 100644 units/systemd-timedated.service.in create mode 100644 units/systemd-timesyncd.service.in create mode 100644 units/systemd-tmpfiles-clean.service.in create mode 100644 units/systemd-tmpfiles-clean.timer create mode 100644 units/systemd-tmpfiles-setup-dev.service.in create mode 100644 units/systemd-tmpfiles-setup.service.in create mode 100644 units/systemd-udev-settle.service.in create mode 100644 units/systemd-udev-trigger.service.in create mode 100644 units/systemd-udevd-control.socket create mode 100644 units/systemd-udevd-kernel.socket create mode 100644 units/systemd-udevd.service.in create mode 100644 units/systemd-update-done.service.in create mode 100644 units/systemd-update-utmp-runlevel.service.in create mode 100644 units/systemd-update-utmp.service.in create mode 100644 units/systemd-user-sessions.service.in create mode 100644 units/systemd-vconsole-setup.service.in create mode 100644 units/systemd-volatile-root.service.in create mode 100644 units/time-set.target create mode 100644 units/time-sync.target create mode 100644 units/timers.target create mode 100644 units/tmp.mount create mode 100644 units/umount.target create mode 100644 units/usb-gadget.target create mode 100644 units/user-.slice.d/10-defaults.conf create mode 100644 units/user-runtime-dir@.service.in create mode 100644 units/user.slice create mode 100644 units/user/basic.target create mode 100644 units/user/bluetooth.target create mode 100644 units/user/default.target create mode 100644 units/user/exit.target create mode 100644 units/user/graphical-session-pre.target create mode 100644 units/user/graphical-session.target create mode 100644 units/user/meson.build create mode 100644 units/user/paths.target create mode 100644 units/user/printer.target create mode 100644 units/user/shutdown.target create mode 100644 units/user/smartcard.target create mode 100644 units/user/sockets.target create mode 100644 units/user/sound.target create mode 100644 units/user/systemd-exit.service create mode 100644 units/user/systemd-tmpfiles-clean.service.in create mode 100644 units/user/systemd-tmpfiles-clean.timer create mode 100644 units/user/systemd-tmpfiles-setup.service.in create mode 100644 units/user/timers.target create mode 100644 units/user@.service.in create mode 100644 units/var-lib-machines.mount create mode 100755 xorg/50-systemd-user.sh create mode 100644 zanata.xml diff --git a/.ctags b/.ctags new file mode 100644 index 00000000..a75e12e8 --- /dev/null +++ b/.ctags @@ -0,0 +1 @@ +--links=no diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 00000000..fde58d65 --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,28 @@ +; Sets emacs variables based on mode. +; A list of (major-mode . ((var1 . value1) (var2 . value2))) +; Mode can be nil, which gives default values. + +; Note that we set a line width of 109 for .c and XML files, but for everything +; else (such as journal catalog files, unit files, README files) we stick to a +; more conservative 79 characters. + +; NOTE: If you update this file make sure to update .vimrc and .editorconfig, +; too. + +((c-mode . ((fill-column . 109) + (c-basic-offset . 8) + (eval . (c-set-offset 'substatement-open 0)) + (eval . (c-set-offset 'statement-case-open 0)) + (eval . (c-set-offset 'case-label 0)) + (eval . (c-set-offset 'arglist-intro '++)) + (eval . (c-set-offset 'arglist-close 0)) + (eval . (c-set-offset 'arglist-cont-nonempty '(c-lineup-gcc-asm-reg c-lineup-arglist))))) + (nxml-mode . ((nxml-child-indent . 2) + (fill-column . 109))) + (meson-mode . ((meson-indent-basic . 8))) + (sh-mode . ((sh-basic-offset . 4) + (sh-indentation . 4))) + (awk-mode . ((c-basic-offset . 8))) + (nil . ((indent-tabs-mode . nil) + (tab-width . 8) + (fill-column . 79))) ) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..63b1d749 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,28 @@ +# EditorConfig configuration for systemd +# http://EditorConfig.org + +# NOTE: If you update this file make sure to update .dir-locals.el and .vimrc, +# too. + +# Top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file, utf-8 charset +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +# Match config files, set indent to spaces with width of eight +[*.{c,h}] +indent_style = space +indent_size = 8 + +[*.sh] +indent_style = space +indent_size = 4 + +[meson.build] +indent_style = space +indent_size = 8 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..18415085 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.[ch] whitespace=tab-in-indent,trailing-space diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..ee3b8022 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +custom: ['https://spi-inc.org/projects/systemd/', 'https://www.paypal.com/donate/?token=fBGzXDOyIGobZH3oEhYQlYlA61OMRXVnF9XXQqNNehRs-nliAU5XxozIh9z-hlmE-xXC-m'] diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 00000000..6a0b5527 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,22 @@ +--- +name: Bug report +about: A report of an error in a recent systemd version + +--- + +**systemd version the issue has been seen with** +> ... + + + + +**Used distribution** + > … + +**Expected behaviour you didn't see** + > … + +**Unexpected behaviour you saw** + > … + +**Steps to reproduce the problem** diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 00000000..c56aae87 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,14 @@ +--- +name: Feature request +about: Suggest an improvement + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5d187055 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +*.a +*.cache +*.gch +*.log +*.o +*.plist +*.py[co] +*.stamp +*.swp +*.trs +*~ +.config.args +.gdb_history +.deps/ +/*.gcda +/*.gcno +/*.tar.bz2 +/*.tar.gz +/*.tar.xz +/GPATH +/GRTAGS +/GSYMS +/GTAGS +/TAGS +/ID +/build* +/coverage/ +/image.raw +/.#image.raw.lck +/image.raw.cache-pre-dev +/image.raw.cache-pre-inst +/install-tree +/.mkosi-* +/mkosi.builddir/ +/mkosi.output/ +/tags +__pycache__/ diff --git a/.lgtm.yml b/.lgtm.yml new file mode 100644 index 00000000..5948d8c2 --- /dev/null +++ b/.lgtm.yml @@ -0,0 +1,13 @@ +extraction: + cpp: + prepare: + packages: + - python3-pip + - python3-setuptools + - python3-wheel + after_prepare: + - pip3 install meson + - export PATH="$HOME/.local/bin/:$PATH" + python: + python_setup: + version: 3 diff --git a/.lgtm/cpp-queries/PotentiallyDangerousFunction.ql b/.lgtm/cpp-queries/PotentiallyDangerousFunction.ql new file mode 100644 index 00000000..86533043 --- /dev/null +++ b/.lgtm/cpp-queries/PotentiallyDangerousFunction.ql @@ -0,0 +1,54 @@ +/** + * @name Use of potentially dangerous function + * @description Certain standard library functions are dangerous to call. + * @kind problem + * @problem.severity error + * @precision high + * @id cpp/potentially-dangerous-function + * @tags reliability + * security + * + * Borrowed from + * https://github.com/Semmle/ql/blob/master/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql + */ +import cpp + +predicate potentiallyDangerousFunction(Function f, string message) { + ( + f.getQualifiedName() = "fgets" and + message = "Call to fgets() is potentially dangerous. Use read_line() instead." + ) or ( + f.getQualifiedName() = "strtok" and + message = "Call to strtok() is potentially dangerous. Use extract_first_word() instead." + ) or ( + f.getQualifiedName() = "strsep" and + message = "Call to strsep() is potentially dangerous. Use extract_first_word() instead." + ) or ( + f.getQualifiedName() = "dup" and + message = "Call to dup() is potentially dangerous. Use fcntl(fd, FD_DUPFD_CLOEXEC, 3) instead." + ) or ( + f.getQualifiedName() = "htonl" and + message = "Call to htonl() is confusing. Use htobe32() instead." + ) or ( + f.getQualifiedName() = "htons" and + message = "Call to htons() is confusing. Use htobe16() instead." + ) or ( + f.getQualifiedName() = "ntohl" and + message = "Call to ntohl() is confusing. Use be32toh() instead." + ) or ( + f.getQualifiedName() = "ntohs" and + message = "Call to ntohs() is confusing. Use be16toh() instead." + ) or ( + f.getQualifiedName() = "strerror" and + message = "Call to strerror() is not thread-safe. Use strerror_r() or printf()'s %m format string instead." + ) or ( + f.getQualifiedName() = "accept" and + message = "Call to accept() is not O_CLOEXEC-safe. Use accept4() instead." + ) +} + +from FunctionCall call, Function target, string message +where + call.getTarget() = target and + potentiallyDangerousFunction(target, message) +select call, message diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000..2bfc6469 --- /dev/null +++ b/.mailmap @@ -0,0 +1,206 @@ +Alan Jenkins +Alan Jenkins +Alan Robertson +Alexander Kochetkov +Alexander Kuleshov <0xAX@users.noreply.github.com> +Alexander Kurtz +Alexandros Frantzis +Ananth N Mavinakayanahalli +Ananth N Mavinakayanahalli +Andreas Henriksson +Anthony Parsons +Antoine Eiche +Arnd Bergmann +Atul Sabharwal +Bart Rulon +Bastien Nocera +Baybal Ni +Beniamino Galvani +Bill Yodlowsky +Brian Boylston +Charles (Chas) Williams +Chen Qi <40684930+ChenQi1989@users.noreply.github.com> +Christophe Varoqui +Colin Guthrie +Daniel Elstner +Daniel Gorbea +Daniel J Walsh +Daniel Kahn Gillmor +Daniel Machon +Daniel Rusek +Daniel Stekloff +Daniel Șerbănescu +Dave Reisner +David Zeuthen +David Zeuthen +David Zeuthen +Davide Cavalca +Dennis Wassenberg +Diego Elio Pettenò +Dmitriy Geels +Dmitry Khlebnikov +Douglas Christman +Emil Soleyman +Eric Cook +Evgeny Vereshchagin +Fabiano Fidêncio Fabiano Fidencio +Faizal Luthfi +Federico Di Pierro +Fionn Cleary +Frederic Crozat +Gautier Husson +George Gaydarov +Gianluca Boiano +Greg Kroah-Hartman +Greg Kroah-Hartman +Greg Kroah-Hartman +Greg Kroah-Hartman +Greg Kroah-Hartman +Greg Kroah-Hartman +Gwendal Grignou +Hannes Reinecke +Harald Hoyer +Harald Hoyer +Heikki Kemppainen +Hendrik Brueckner +Hendrik Westerberg +Ian Campbell +Insun Pyo +Insun Pyo +Jerone Young +Jiuyang Liu +John Paul Adrian Glaubitz +John Paul Adrian Glaubitz +Jon Ringle +Jonas Dorel +Josef Andersson +Josef Andersson +José Bollo +Jun Bo Bi +Justin Capella +Jérémy Rosen +Jürg Billeter +Karl Kraus +Kay Sievers +Kay Sievers +Kay Sievers +Kay Sievers +Kay Sievers +Kay Sievers +Kevin Becker +Krzysztof Jackiewicz +Larry Bernstone +Lennart Poettering +Lennart Poettering +Lennart Poettering +Leonard König +Luis Felipe Strano Moraes +Lukáš Nykrýn +Lukáš Říha +Mao Huang +Marco d'Itri +Marcus Cooper +Mario Limonciello +Martin Pitt +Martin Pitt +Martin Pitt +Martin Steuer +Marty Plummer +Matthew Leeds +Matthew McGinn +Matthias Clasen +Matthias-Christian Ott +Michael Biebl +Michael Buesch +Michael Hoy +Michael Olbrich +Michal Soltys +Michal Suchanek +Michal Suchanek +Michał Szczepański +Michel Kraus <27o@users.noreply.github.com> +Miklos Vajna +Milan Pässler +Neil Brown +Neil Brown +Niklas Tibbling <45659916+tibbling@users.noreply.github.com> +Nikolas Nyby +Nogisaka Sadata +Olaf Hering +Otto Wallenius +Pablo Lezaeta Reyes +Paolo Giangrandi +Patrick Mansfield +Patryk Kocielnik +Paul Mundt +Pavel Hrdina +Peter D'Hoye +Piotr Szydełko +Piter PUNK +Reid Price +Reinhold Mueller +Richard Hughes +Richard W.M. Jones +Robby Workman +Robert Gerus Robert "arachnist" Gerus +Robert Kolchmeyer +Robert Love +Roman Stingler +Rubén Suárez Alvarez +Salvo Tomaselli +Sandy Carter +Scott James Remnant +Scott James Remnant +Seraphime Kirkovski +Shawn Landden +Shawn Landden +Silvio Knizek +Simon Peeters +Sjoerd Simons +Stanislav Angelovič +Stasiek Michalski +Stefan Pietsch +Stefan Schweter +Stuart McLaren +Susant Sahani <145210+ssahani@users.noreply.github.com> +Susant Sahani +Sébastien Bacher +Tanu Kaskinen +Ted Ts'o +Ted Wood +Ted Wood +Thomas Blume +Thomas H. P. Andersen +Tiago Levit +Tibor Nagy +Tinu Weber +Tobias Jungel Tobias Jungel +Tobias Klauser +Tobias Klauser +Tobias Klauser +Tobias Klauser +Tobias Klauser +Tom Rini +Tom Yan +Tomasz Bachorski <34866781+nulsoh@users.noreply.github.com> +Tomasz Pala +Torsten Hilbrich +Umut Tezduyar Lindskog +Vasilis Liaskovitis +Vladislav Vishnyakov +William Jon McCann +Wim van Mourik +Yann E. Morin +Yin Kangkai +Zachary Winnerman <33329648+winnerman-pythian@users.noreply.github.com> +Zbigniew Jędrzejewski-Szmek +Zbigniew Jędrzejewski-Szmek +Łukasz Stelmach +Jonathon Kowalski +Diego Canuhe <46734128+dcanuhe@users.noreply.github.com> +David Santamaría Rogado +Mike Auty +Roger James +Stephan Edel +Andrey Yashkin <38919268+AndreyYashkin@users.noreply.github.com> +Ronald Tschalär diff --git a/.mkosi/mkosi.arch b/.mkosi/mkosi.arch new file mode 100644 index 00000000..350d7cd2 --- /dev/null +++ b/.mkosi/mkosi.arch @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Copyright © 2016 Zeal Jagannatha + +# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +# Simply invoke "mkosi" in the project directory to build an OS image. + +[Distribution] +Distribution=arch + +[Output] +Format=raw_btrfs +Bootable=yes + +[Partitions] +RootSize=3G + +[Packages] +Cache=/var/cache/pacman/pkg/ +BuildPackages= + acl + bzip2 + cryptsetup + curl + dbus + diffutils + docbook-xsl + elfutils + gcc + git + gnu-efi-libs + gnutls + gperf + inetutils + iptables + kmod + libcap + libgcrypt + libidn2 + libmicrohttpd + libseccomp + libtool + libutil-linux + libxkbcommon + libxslt + lz4 + m4 + meson + pam + pkgconfig + python + python-lxml + qrencode + xz + +Packages= + libidn2 + qrencode diff --git a/.mkosi/mkosi.debian b/.mkosi/mkosi.debian new file mode 100644 index 00000000..e85612be --- /dev/null +++ b/.mkosi/mkosi.debian @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +# Simply invoke "mkosi" in the project directory to build an OS image. + +[Distribution] +Distribution=debian +Release=unstable + +[Output] +Format=raw_btrfs +Bootable=yes + +[Partitions] +RootSize=2G + +[Packages] +BuildPackages= + acl + docbook-xml + docbook-xsl + gcc + gettext + git + gnu-efi + gperf + iptables-dev + libacl1-dev + libaudit-dev + libblkid-dev + libbz2-dev + libcap-dev + libcryptsetup-dev + libcurl4-gnutls-dev + libdbus-1-dev + libdw-dev + libfdisk-dev + libgcrypt20-dev + libgnutls28-dev + libidn2-0-dev + libkmod-dev + liblzma-dev + liblz4-dev + liblz4-tool + libmicrohttpd-dev + libmount-dev + libpam0g-dev + libqrencode-dev + libseccomp-dev + libsmartcols-dev + libtool + libxkbcommon-dev + m4 + meson + pkg-config + python3 + python3-lxml + tree + uuid-dev + xsltproc + xz-utils + +Packages= + libqrencode4 + locales + libidn2-0 diff --git a/.mkosi/mkosi.fedora b/.mkosi/mkosi.fedora new file mode 100644 index 00000000..911908cb --- /dev/null +++ b/.mkosi/mkosi.fedora @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +# Simply invoke "mkosi" in the project directory to build an OS image. + +[Distribution] +Distribution=fedora +Release=31 + +[Output] +Format=raw_btrfs +Bootable=yes +KernelCommandLine=printk.devkmsg=on + +[Partitions] +RootSize=3G + +[Packages] +BuildPackages= + audit-libs-devel + bzip2-devel + cryptsetup-devel + dbus-devel + diffutils + docbook-style-xsl + elfutils-devel + gcc + gettext + git + gnu-efi + gnu-efi-devel + gnutls-devel + gperf + hostname + iptables-devel + kmod-devel + libacl-devel + libblkid-devel + libcap-devel + libcurl-devel + libgcrypt-devel + libidn2-devel + libmicrohttpd-devel + libmount-devel + libseccomp-devel + libselinux-devel + libtool + libxkbcommon-devel + libxslt + lz4 + lz4-devel + m4 + meson + pam-devel + pcre2-devel + pkgconfig + python3-devel + python3-lxml + qrencode-devel + tree + xz-devel + +Packages= + libidn2 + +BuildDirectory=mkosi.builddir +Cache=mkosi.cache diff --git a/.mkosi/mkosi.ubuntu b/.mkosi/mkosi.ubuntu new file mode 100644 index 00000000..1e4005f0 --- /dev/null +++ b/.mkosi/mkosi.ubuntu @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +# Simply invoke "mkosi" in the project directory to build an OS image. + +[Distribution] +Distribution=ubuntu +Release=bionic +Repositories=main,universe + +[Output] +Format=raw_btrfs +Bootable=no + +[Partitions] +RootSize=2G + +[Packages] +BuildPackages= + acl + docbook-xml + docbook-xsl + gcc + gettext + git + gnu-efi + gperf + iptables-dev + libacl1-dev + libaudit-dev + libblkid-dev + libbz2-dev + libcap-dev + libcryptsetup-dev + libcurl4-gnutls-dev + libdbus-1-dev + libdw-dev + libfdisk-dev + libgcrypt20-dev + libgnutls28-dev + libidn2-0-dev + libkmod-dev + liblz4-dev + liblz4-tool + liblzma-dev + libmicrohttpd-dev + libmount-dev + libpam0g-dev + libqrencode-dev + libseccomp-dev + libsmartcols-dev + libtool + libxkbcommon-dev + m4 + meson + pkg-config + python3 + python3-lxml + tree + tzdata + uuid-dev + xsltproc + xz-utils + +Packages= + libqrencode3 + locales + libidn2-0 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..82f62a86 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,158 @@ +sudo: required +dist: xenial +services: + - docker + +env: + global: + - AUTHOR_EMAIL="$(git log -1 $TRAVIS_COMMIT --pretty=\"%aE\")" + - CI_MANAGERS="$TRAVIS_BUILD_DIR/travis-ci/managers" + - CI_TOOLS="$TRAVIS_BUILD_DIR/travis-ci/tools" + - REPO_ROOT="$TRAVIS_BUILD_DIR" + +stages: + - name: Build & test + if: type != cron + + - name: Fuzzit-Fuzzing + if: type = cron + + - name: Fuzzit-Regression + if: type != cron + + # Run Coverity periodically instead of for each commit/PR + - name: Coverity + if: type = cron + +jobs: + include: + - stage: Build & test + name: Debian Testing + language: bash + env: + - DEBIAN_RELEASE="testing" + - CONT_NAME="systemd-debian-$DEBIAN_RELEASE" + - DOCKER_EXEC="docker exec -ti $CONT_NAME" + before_install: + - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce + - docker --version + install: + - $CI_MANAGERS/debian.sh SETUP + script: + - set -e + # Build systemd + - $CI_MANAGERS/debian.sh RUN + - set +e + after_script: + - $CI_MANAGERS/debian.sh CLEANUP + + - name: Debian Testing (ASan+UBSan) + language: bash + env: + - DEBIAN_RELEASE="testing" + - CONT_NAME="systemd-debian-$DEBIAN_RELEASE" + - DOCKER_EXEC="docker exec -ti $CONT_NAME" + before_install: + - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce + - docker --version + install: + - $CI_MANAGERS/debian.sh SETUP + script: + - set -e + - $CI_MANAGERS/debian.sh RUN_ASAN + - set +e + after_script: + - $CI_MANAGERS/debian.sh CLEANUP + + - name: Debian Testing (clang) + language: bash + env: + - DEBIAN_RELEASE="testing" + - CONT_NAME="systemd-debian-$DEBIAN_RELEASE" + - DOCKER_EXEC="docker exec -ti $CONT_NAME" + before_install: + - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce + - docker --version + install: + - $CI_MANAGERS/debian.sh SETUP + script: + - set -e + - $CI_MANAGERS/debian.sh RUN_CLANG + - set +e + after_script: + - $CI_MANAGERS/debian.sh CLEANUP + + - name: Debian Testing (clang ASan+UBSan) + language: bash + env: + - DEBIAN_RELEASE="testing" + - CONT_NAME="systemd-debian-$DEBIAN_RELEASE" + - DOCKER_EXEC="docker exec -ti $CONT_NAME" + before_install: + - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce + - docker --version + install: + - $CI_MANAGERS/debian.sh SETUP + script: + - set -e + - $CI_MANAGERS/debian.sh RUN_CLANG_ASAN + - set +e + after_script: + - $CI_MANAGERS/debian.sh CLEANUP + + - stage: Fuzzit-Regression + name: Continuous Fuzzing via Fuzzit (regression) + language: bash + script: + - set -e + - $CI_MANAGERS/fuzzit.sh regression + - set +e + + - stage: Fuzzit-Fuzzing + name: Continuous Fuzzing via Fuzzit (fuzzing daily) + language: bash + script: + - set -e + - $CI_MANAGERS/fuzzit.sh fuzzing + - set +e + + - stage: Coverity + language: bash + env: + - FEDORA_RELEASE="latest" + - CONT_NAME="coverity-fedora-$FEDORA_RELEASE" + - DOCKER_EXEC="docker exec -ti $CONT_NAME" + - TOOL_BASE="/var/tmp/coverity-scan-analysis" + - DOCKER_RUN="docker run -v $TOOL_BASE:$TOOL_BASE:rw --env-file .cov-env" + # Coverity env variables + - PLATFORM="$(uname)" + - TOOL_ARCHIVE="/var/tmp/cov-analysis-$PLATFORM.tgz" + - SCAN_URL="https://scan.coverity.com" + - UPLOAD_URL="https://scan.coverity.com/builds" + - COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG" + - COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}" + - COVERITY_SCAN_BRANCH_PATTERN="$TRAVIS_BRANCH" + # Encrypted COVERITY_SCAN_TOKEN env variable + # Generated using `travis encrypt -r systemd/systemd COVERITY_SCAN_TOKEN=xxxx` + - secure: "jKSz+Y1Mv8xMpQHh7g5lzW7E6HQGndFz/vKDJQ1CVShwFoyjV3Zu+MFS3UYKlh1236zL0Z4dvsYFx/b3Hq8nxZWCrWeZs2NdXgy/wh8LZhxwzcGYigp3sIA/cYdP5rDjFJO0MasNkl25/rml8+eZWz+8/xQic98UQHjSco/EOWtssoRcg0J0c4eDM7bGLfIQWE73NNY1Q1UtWjKmx1kekVrM8dPmHXJ9aERka7bmcbJAcKd6vabs6DQ5AfWccUPIn/EsRYqIJTRxJrFYU6XizANZ1a7Vwk/DWHZUEn2msxcZw5BbAMDTMx0TbfrNkKSHMHuvQUCu6KCBAq414i+LgkMfmQ2SWwKiIUsud1kxXX3ZPl9bxDv1HkvVdcniC/EM7lNEEVwm4meOnjuhI2lhOyOjmP3FTSlMHGP7xlK8DS2k9fqL58vn0BaSjwWgd+2+HuL2+nJmxcK1eLGzKqaostFxrk2Xs2vPZkUdV2nWY/asUrcWHml6YlWDn2eP83pfwxHYsMiEHY/rTKvxeVY+iirO/AphoO+eaYu7LvjKZU1Yx5Z4u/SnGWAiCH0yhMis0bWmgi7SCbw+sDd2uya+aoiLIGiB2ChW7hXHXCue/dif6/gLU7b+L8R00pQwnWdvKUPoIJCmZJYCluTeib4jpW+EmARB2+nR8wms2K9FGKM=" + before_install: + - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce + - docker --version + install: + # Install Coverity on the host + - $CI_TOOLS/get-coverity.sh + # Export necessary env variables for Coverity + - env | grep -E "TRAVIS|COV|TOOL|URL" > .cov-env + # Pull a Docker image and start a new container + - $CI_MANAGERS/fedora.sh SETUP + script: + - set -e + # Preconfigure with meson to prevent Coverity from capturing meson metadata + - $DOCKER_EXEC meson cov-build -Dman=false + # Run Coverity + - $DOCKER_EXEC tools/coverity.sh build + - $DOCKER_EXEC tools/coverity.sh upload + + - set +e + after_script: + - $CI_MANAGERS/fedora.sh CLEANUP diff --git a/.vimrc b/.vimrc new file mode 100644 index 00000000..d40b57a6 --- /dev/null +++ b/.vimrc @@ -0,0 +1,21 @@ +" 'set exrc' in ~/.vimrc will read .vimrc from the current directory +" Warning: Enabling exrc is dangerous! You can do nearly everything from a +" vimrc configuration file, including write operations and shell execution. +" You should consider setting 'set secure' as well, which is highly +" recommended! + +" Note that we set a line width of 109 for .c and XML files, but for everything +" else (such as journal catalog files, unit files, README files) we stick to a +" more conservative 79 characters. + +" NOTE: If you update this file make sure to update .dir-locals.el and +" .editorconfig, too. + +set tabstop=8 +set shiftwidth=8 +set expandtab +set makeprg=GCC_COLORS=\ make +set tw=79 +au BufRead,BufNewFile *.xml set tw=109 shiftwidth=2 smarttab +au FileType sh set tw=80 shiftwidth=4 smarttab +au FileType c set tw=109 diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py new file mode 100644 index 00000000..f297deef --- /dev/null +++ b/.ycm_extra_conf.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python + +# SPDX-License-Identifier: Unlicense +# +# Based on the template file provided by the 'YCM-Generator' project authored by +# Reuben D'Netto. +# Jiahui Xie has re-reformatted and expanded the original script in accordance +# to the requirements of the PEP 8 style guide and 'systemd' project, +# respectively. +# +# The original license is preserved as it is. +# +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# For more information, please refer to + +""" +YouCompleteMe configuration file tailored to support the 'meson' build system +used by the 'systemd' project. +""" + +import glob +import os +import ycm_core + + +SOURCE_EXTENSIONS = (".C", ".cpp", ".cxx", ".cc", ".c", ".m", ".mm") +HEADER_EXTENSIONS = (".H", ".h", ".hxx", ".hpp", ".hh") + + +def DirectoryOfThisScript(): + """ + Return the absolute path of the parent directory containing this + script. + """ + return os.path.dirname(os.path.abspath(__file__)) + + +def GuessBuildDirectory(): + """ + Guess the build directory using the following heuristics: + + 1. Returns the current directory of this script plus 'build' + subdirectory in absolute path if this subdirectory exists. + + 2. Otherwise, probes whether there exists any directory + containing '.ninja_log' file two levels above the current directory; + returns this single directory only if there is one candidate. + """ + result = os.path.join(DirectoryOfThisScript(), "build") + + if os.path.exists(result): + return result + + result = glob.glob(os.path.join(DirectoryOfThisScript(), + "..", "..", "*", ".ninja_log")) + + if not result: + return "" + + if 1 != len(result): + return "" + + return os.path.split(result[0])[0] + + +def TraverseByDepth(root, include_extensions): + """ + Return a set of child directories of the 'root' containing file + extensions specified in 'include_extensions'. + + NOTE: + 1. The 'root' directory itself is excluded from the result set. + 2. No subdirectories would be excluded if 'include_extensions' is left + to 'None'. + 3. Each entry in 'include_extensions' must begin with string '.'. + """ + is_root = True + result = set() + # Perform a depth first top down traverse of the given directory tree. + for root_dir, subdirs, file_list in os.walk(root): + if not is_root: + # print("Relative Root: ", root_dir) + # print(subdirs) + if include_extensions: + get_ext = os.path.splitext + subdir_extensions = { + get_ext(f)[-1] for f in file_list if get_ext(f)[-1] + } + if subdir_extensions & include_extensions: + result.add(root_dir) + else: + result.add(root_dir) + else: + is_root = False + + return result + + +_project_src_dir = os.path.join(DirectoryOfThisScript(), "src") +_include_dirs_set = TraverseByDepth(_project_src_dir, frozenset({".h"})) +flags = [ + "-x", + "c" + # The following flags are partially redundant due to the existence of + # 'compile_commands.json'. + # '-Wall', + # '-Wextra', + # '-Wfloat-equal', + # '-Wpointer-arith', + # '-Wshadow', + # '-std=gnu99', +] + +for include_dir in _include_dirs_set: + flags.append("-I" + include_dir) + +# Set this to the absolute path to the folder (NOT the file!) containing the +# compile_commands.json file to use that instead of 'flags'. See here for +# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html +# +# You can get CMake to generate this file for you by adding: +# set( CMAKE_EXPORT_COMPILE_COMMANDS 1 ) +# to your CMakeLists.txt file. +# +# Most projects will NOT need to set this to anything; you can just change the +# 'flags' list of compilation flags. Notice that YCM itself uses that approach. +compilation_database_folder = GuessBuildDirectory() + +if os.path.exists(compilation_database_folder): + database = ycm_core.CompilationDatabase(compilation_database_folder) +else: + database = None + + +def MakeRelativePathsInFlagsAbsolute(flags, working_directory): + """ + Iterate through 'flags' and replace the relative paths prefixed by + '-isystem', '-I', '-iquote', '--sysroot=' with absolute paths + start with 'working_directory'. + """ + if not working_directory: + return list(flags) + new_flags = [] + make_next_absolute = False + path_flags = ["-isystem", "-I", "-iquote", "--sysroot="] + for flag in flags: + new_flag = flag + + if make_next_absolute: + make_next_absolute = False + if not flag.startswith("/"): + new_flag = os.path.join(working_directory, flag) + + for path_flag in path_flags: + if flag == path_flag: + make_next_absolute = True + break + + if flag.startswith(path_flag): + path = flag[len(path_flag):] + new_flag = path_flag + os.path.join(working_directory, path) + break + + if new_flag: + new_flags.append(new_flag) + return new_flags + + +def IsHeaderFile(filename): + """ + Check whether 'filename' is considered as a header file. + """ + extension = os.path.splitext(filename)[1] + return extension in HEADER_EXTENSIONS + + +def GetCompilationInfoForFile(filename): + """ + Helper function to look up compilation info of 'filename' in the 'database'. + """ + # The compilation_commands.json file generated by CMake does not have + # entries for header files. So we do our best by asking the db for flags for + # a corresponding source file, if any. If one exists, the flags for that + # file should be good enough. + if not database: + return None + + if IsHeaderFile(filename): + basename = os.path.splitext(filename)[0] + for extension in SOURCE_EXTENSIONS: + replacement_file = basename + extension + if os.path.exists(replacement_file): + compilation_info = \ + database.GetCompilationInfoForFile(replacement_file) + if compilation_info.compiler_flags_: + return compilation_info + return None + return database.GetCompilationInfoForFile(filename) + + +def FlagsForFile(filename, **kwargs): + """ + Callback function to be invoked by YouCompleteMe in order to get the + information necessary to compile 'filename'. + + It returns a dictionary with a single element 'flags'. This element is a + list of compiler flags to pass to libclang for the file 'filename'. + """ + if database: + # Bear in mind that compilation_info.compiler_flags_ does NOT return a + # python list, but a "list-like" StringVec object + compilation_info = GetCompilationInfoForFile(filename) + if not compilation_info: + return None + + final_flags = MakeRelativePathsInFlagsAbsolute( + compilation_info.compiler_flags_, + compilation_info.compiler_working_dir_) + + else: + relative_to = DirectoryOfThisScript() + final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to) + + return { + "flags": final_flags, + "do_cache": True + } diff --git a/LICENSE.GPL2 b/LICENSE.GPL2 new file mode 100644 index 00000000..d511905c --- /dev/null +++ b/LICENSE.GPL2 @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/LICENSE.LGPL2.1 b/LICENSE.LGPL2.1 new file mode 100644 index 00000000..4362b491 --- /dev/null +++ b/LICENSE.LGPL2.1 @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..b7e13fba --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +all: + ninja -C build + +install: + DESTDIR=$(DESTDIR) ninja -C build install diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..4fe5799c --- /dev/null +++ b/NEWS @@ -0,0 +1,10215 @@ +systemd System and Service Manager + +CHANGES WITH 244: + + * Support for the cpuset cgroups v2 controller has been added. + Processes may be restricted to specific CPUs using the new + AllowedCPUs= setting, and to specific memory NUMA nodes using the new + AllowedMemoryNodes= setting. + + * The signal used in restart jobs (as opposed to e.g. stop jobs) may + now be configured using a new RestartKillSignal= setting. This + allows units which signals to request termination to implement + different behaviour when stopping in preparation for a restart. + + * "systemctl clean" may now be used also for socket, mount, and swap + units. + + * systemd will also read configuration options from the EFI variable + SystemdOptions. This may be used to configure systemd behaviour when + modifying the kernel command line is inconvenient, but configuration + on disk is read too late, for example for the options related to + cgroup hierarchy setup. 'bootctl systemd-efi-options' may be used to + set the EFI variable. + + * systemd will now disable printk ratelimits in early boot. This should + allow us to capture more logs from the early boot phase where normal + storage is not available and the kernel ring buffer is used for + logging. Configuration on the kernel command line has higher priority + and overrides the systemd setting. + + systemd programs which log to /dev/kmsg directly use internal + ratelimits to prevent runaway logging. (Normally this is only used + during early boot, so in practice this change has very little + effect.) + + * Unit files now support top level dropin directories of the form + .d/ (e.g. service.d/) that may be used to add configuration + that affects all corresponding unit files. + + * systemctl gained support for 'stop --job-mode=triggering' which will + stop the specified unit and any units which could trigger it. + + * Unit status display now includes units triggering and triggered by + the unit being shown. + + * The RuntimeMaxSec= setting is now supported by scopes, not just + .service units. This is particularly useful for PAM sessions which + create a scope unit for the user login. systemd.runtime_max_sec= + setting may used with the pam_systemd module to limit the duration + of the PAM session, for example for time-limited logins. + + * A new @pkey system call group is now defined to make it easier to + whitelist memory protection syscalls for containers and services + which need to use them. + + * systemd-udevd: removed the 30s timeout for killing stale workers on + exit. systemd-udevd now waits for workers to finish. The hard-coded + exit timeout of 30s was too short for some large installations, where + driver initialization could be prematurely interrupted during initrd + processing if the root file system had been mounted and init was + preparing to switch root. If udevd is run without systemd and workers + are hanging while udevd receives an exit signal, udevd will now exit + when udev.event_timeout is reached for the last hanging worker. With + systemd, the exit timeout can additionally be configured using + TimeoutStopSec= in systemd-udevd.service. + + * udev now provides a program (fido_id) that identifies FIDO CTAP1 + ("U2F")/CTAP2 security tokens based on the usage declared in their + report and descriptor and outputs suitable environment variables. + This replaces the externally maintained whitelists of all known + security tokens that were used previously. + + * Automatically generated autosuspend udev rules for whitelisted + devices have been imported from the Chromium OS project. This should + improve power saving with many more devices. + + * udev gained a new "CONST{key}=value" setting that allows matching + against system-wide constants without forking a helper binary. + Currently "arch" and "virt" keys are supported. + + * udev now opens CDROMs in non-exclusive mode when querying their + capabilities. This should fix issues where other programs trying to + use the CDROM cannot gain access to it, but carries a risk of + interfering with programs writing to the disk, if they did not open + the device in exclusive mode as they should. + + * systemd-networkd does not create a default route for IPv4 link local + addressing anymore. The creation of the route was unexpected and was + breaking routing in various cases, but people who rely on it being + created implicitly will need to adjust. Such a route may be requested + with DefaultRouteOnDevice=yes. + + Similarly, systemd-networkd will not assign a link-local IPv6 address + when IPv6 link-local routing is not enabled. + + * Receive and transmit buffers may now be configured on links with + the new RxBufferSize= and TxBufferSize= settings. + + * systemd-networkd may now advertise additional IPv6 routes. A new + [IPv6RoutePrefix] section with Route= and LifetimeSec= options is + now supported. + + * systemd-networkd may now configure "next hop" routes using the + [NextHop] section and Gateway= and Id= settings. + + * systemd-networkd will now retain DHCP config on restarts by default + (but this may be overridden using the KeepConfiguration= setting). + The default for SendRelease= has been changed to true. + + * The DHCPv4 client now uses the OPTION_INFORMATION_REFRESH_TIME option + received from the server. + + The client will use the received SIP server list if UseSIP=yes is + set. + + The client may be configured to request specific options from the + server using a new RequestOptions= setting. + + The client may be configured to send arbitrary options to the server + using a new SendOption= setting. + + A new IPServiceType= setting has been added to configure the "IP + service type" value used by the client. + + * The DHCPv6 client learnt a new PrefixDelegationHint= option to + request prefix hints in the DHCPv6 solicitation. + + * The DHCPv4 server may be configured to send arbitrary options using + a new SendOption= setting. + + * The DHCPv4 server may now be configured to emit SIP server list using + the new EmitSIP= and SIP= settings. + + * systemd-networkd and networkctl may now renew DHCP leases on demand. + networkctl has a new 'networkctl renew' verb. + + * systemd-networkd may now reconfigure links on demand. networkctl + gained two new verbs: "reload" will reload the configuration, and + "reconfigure DEVICE…" will reconfigure one or more devices. + + * .network files may now match on SSID and BSSID of a wireless network, + i.e. the access point name and hardware address using the new SSID= + and BSSID= options. networkctl will display the current SSID and + BSSID for wireless links. + + .network files may also match on the wireless network type using the + new WLANInterfaceType= option. + + * systemd-networkd now includes default configuration that enables + link-local addressing when connected to an ad-hoc wireless network. + + * systemd-networkd may configure the Traffic Control queueing + disciplines in the kernel using the new + [TrafficControlQueueingDiscipline] section and Parent=, + NetworkEmulatorDelaySec=, NetworkEmulatorDelayJitterSec=, + NetworkEmulatorPacketLimit=, NetworkEmulatorLossRate=, + NetworkEmulatorDuplicateRate= settings. + + * systemd-tmpfiles gained a new w+ setting to append to files. + + * systemd-analyze dump will now report when the memory configuration in + the kernel does not match what systemd has configured (usually, + because some external program has modified the kernel configuration + on its own). + + * systemd-analyze gained a new --base-time= switch instructs the + 'calendar' verb to resolve times relative to that timestamp instead + of the present time. + + * journalctl --update-catalog now produces deterministic output (making + reproducible image builds easier). + + * A new devicetree-overlay setting is now documented in the Boot Loader + Specification. + + * The default value of the WatchdogSec= setting used in systemd + services (the ones bundled with the project itself) may be set at + configuration time using the -Dservice-watchdog= setting. If set to + empty, the watchdogs will be disabled. + + * systemd-resolved validates IP addresses in certificates now when GnuTLS + is being used. + + * libcryptsetup >= 2.0.1 is now required. + + * A configuration option -Duser-path= may be used to override the $PATH + used by the user service manager. The default is again to use the same + path as the system manager. + + * The systemd-id128 tool gained a new switch "-u" (or "--uuid") for + outputting the 128bit IDs in UUID format (i.e. in the "canonical + representation"). + + * Service units gained a new sandboxing option ProtectKernelLogs= which + makes sure the program cannot get direct access to the kernel log + buffer anymore, i.e. the syslog() system call (not to be confused + with the API of the same name in libc, which is not affected), the + /proc/kmsg and /dev/kmsg nodes and the CAP_SYSLOG capability are made + inaccessible to the service. It's recommended to enable this setting + for all services that should not be able to read from or write to the + kernel log buffer, which are probably almost all. + + Contributions from: Aaron Plattner, Alcaro, Anita Zhang, Balint Reczey, + Bastien Nocera, Baybal Ni, Benjamin Bouvier, Benjamin Gilbert, Carlo + Teubner, cbzxt, Chen Qi, Chris Down, Christian Rebischke, Claudio + Zumbo, ClydeByrdIII, crashfistfight, Cyprien Laplace, Daniel Edgecumbe, + Daniel Gorbea, Daniel Rusek, Daniel Stuart, Dan Streetman, David + Pedersen, David Tardon, Dimitri John Ledkov, Dominique Martinet, Donald + A. Cupp Jr, Evgeny Vereshchagin, Fabian Henneke, Filipe Brandenburger, + Franck Bui, Frantisek Sumsal, Georg Müller, Hans de Goede, Haochen + Tong, HATAYAMA Daisuke, Iwan Timmer, Jan Janssen, Jan Kundrát, Jan + Synacek, Jan Tojnar, Jay Strict, Jérémy Rosen, Jóhann B. Guðmundsson, + Jonas Jelten, Jonas Thelemann, Justin Trudell, J. Xing, Kai-Heng Feng, + Kenneth D'souza, Kevin Becker, Kevin Kuehler, Lennart Poettering, + Léonard Gérard, Lorenz Bauer, Luca Boccassi, Maciej Stanczew, Mario + Limonciello, Marko Myllynen, Mark Stosberg, Martin Wilck, matthiasroos, + Michael Biebl, Michael Olbrich, Michael Tretter, Michal Sekletar, + Michal Sekletár, Michal Suchanek, Mike Gilbert, Mike Kazantsev, Nicolas + Douma, nikolas, Norbert Lange, pan93412, Pascal de Bruijn, Paul Menzel, + Pavel Hrdina, Peter Wu, Philip Withnall, Piotr Drąg, Rafael Fontenelle, + Renaud Métrich, Riccardo Schirone, RoadrunnerWMC, Ronan Pigott, Ryan + Attard, Sebastian Wick, Serge, Siddharth Chandrasekara, Steve Ramage, + Steve Traylen, Susant Sahani, Thibault Nélis, Tim Teichmann, Tom + Fitzhenry, Tommy J, Torsten Hilbrich, Vito Caputo, ypf791, Yu Watanabe, + Zach Smith, Zbigniew Jędrzejewski-Szmek + + – Warsaw, 2019-11-29 + +CHANGES WITH 243: + + * This release enables unprivileged programs (i.e. requiring neither + setuid nor file capabilities) to send ICMP Echo (i.e. ping) requests + by turning on the "net.ipv4.ping_group_range" sysctl of the Linux + kernel for the whole UNIX group range, i.e. all processes. This + change should be reasonably safe, as the kernel support for it was + specifically implemented to allow safe access to ICMP Echo for + processes lacking any privileges. If this is not desirable, it can be + disabled again by setting the parameter to "1 0". + + * Previously, filters defined with SystemCallFilter= would have the + effect that any calling of an offending system call would terminate + the calling thread. This behaviour never made much sense, since + killing individual threads of unsuspecting processes is likely to + create more problems than it solves. With this release the default + action changed from killing the thread to killing the whole + process. For this to work correctly both a kernel version (>= 4.14) + and a libseccomp version (>= 2.4.0) supporting this new seccomp + action is required. If an older kernel or libseccomp is used the old + behaviour continues to be used. This change does not affect any + services that have no system call filters defined, or that use + SystemCallErrorNumber= (and thus see EPERM or another error instead + of being killed when calling an offending system call). Note that + systemd documentation always claimed that the whole process is + killed. With this change behaviour is thus adjusted to match the + documentation. + + * On 64 bit systems, the "kernel.pid_max" sysctl is now bumped to + 4194304 by default, i.e. the full 22bit range the kernel allows, up + from the old 16bit range. This should improve security and + robustness, as PID collisions are made less likely (though certainly + still possible). There are rumours this might create compatibility + problems, though at this moment no practical ones are known to + us. Downstream distributions are hence advised to undo this change in + their builds if they are concerned about maximum compatibility, but + for everybody else we recommend leaving the value bumped. Besides + improving security and robustness this should also simplify things as + the maximum number of allowed concurrent tasks was previously bounded + by both "kernel.pid_max" and "kernel.threads-max" and now effectively + only a single knob is left ("kernel.threads-max"). There have been + concerns that usability is affected by this change because larger PID + numbers are harder to type, but we believe the change from 5 digits + to 7 digits doesn't hamper usability. + + * MemoryLow= and MemoryMin= gained hierarchy-aware counterparts, + DefaultMemoryLow= and DefaultMemoryMin=, which can be used to + hierarchically set default memory protection values for a particular + subtree of the unit hierarchy. + + * Memory protection directives can now take a value of zero, allowing + explicit opting out of a default value propagated by an ancestor. + + * systemd now defaults to the "unified" cgroup hierarchy setup during + build-time, i.e. -Ddefault-hierarchy=unified is now the build-time + default. Previously, -Ddefault-hierarchy=hybrid was the default. This + change reflects the fact that cgroupsv2 support has matured + substantially in both systemd and in the kernel, and is clearly the + way forward. Downstream production distributions might want to + continue to use -Ddefault-hierarchy=hybrid (or even =legacy) for + their builds as unfortunately the popular container managers have not + caught up with the kernel API changes. + + * Man pages are not built by default anymore (html pages were already + disabled by default), to make development builds quicker. When + building systemd for a full installation with documentation, meson + should be called with -Dman=true and/or -Dhtml=true as appropriate. + The default was changed based on the assumption that quick one-off or + repeated development builds are much more common than full optimized + builds for installation, and people need to pass various other + options to when doing "proper" builds anyway, so the gain from making + development builds quicker is bigger than the one time disruption for + packagers. + + Two scripts are created in the *build* directory to generate and + preview man and html pages on demand, e.g.: + + build/man/man systemctl + build/man/html systemd.index + + * libidn2 is used by default if both libidn2 and libidn are installed. + Please use -Dlibidn=true if libidn is preferred. + + * The D-Bus "wire format" of the CPUAffinity= attribute is changed on + big-endian machines. Before, bytes were written and read in native + machine order as exposed by the native libc __cpu_mask interface. + Now, little-endian order is always used (CPUs 0–7 are described by + bits 0–7 in byte 0, CPUs 8–15 are described by byte 1, and so on). + This change fixes D-Bus calls that cross endianness boundary. + + The presentation format used for CPUAffinity= by "systemctl show" and + "systemd-analyze dump" is changed to present CPU indices instead of + the raw __cpu_mask bitmask. For example, CPUAffinity=0-1 would be + shown as CPUAffinity=03000000000000000000000000000… (on + little-endian) or CPUAffinity=00000000000000300000000000000… (on + 64-bit big-endian), and is now shown as CPUAffinity=0-1, matching the + input format. The maximum integer that will be printed in the new + format is 8191 (four digits), while the old format always used a very + long number (with the length varying by architecture), so they can be + unambiguously distinguished. + + * /usr/sbin/halt.local is no longer supported. Implementation in + distributions was inconsistent and it seems this functionality was + very rarely used. + + To replace this functionality, users should: + - either define a new unit and make it a dependency of final.target + (systemctl add-wants final.target my-halt-local.service) + - or move the shutdown script to /usr/lib/systemd/system-shutdown/ + and ensure that it accepts "halt", "poweroff", "reboot", and + "kexec" as an argument, see the description in systemd-shutdown(8). + + * When a [Match] section in .link or .network file is empty (contains + no match patterns), a warning will be emitted. Please add any "match + all" pattern instead, e.g. OriginalName=* or Name=* in case all + interfaces should really be matched. + + * A new setting NUMAPolicy= may be used to set process memory + allocation policy. This setting can be specified in + /etc/systemd/system.conf and hence will set the default policy for + PID1. The default policy can be overridden on a per-service + basis. The related setting NUMAMask= is used to specify NUMA node + mask that should be associated with the selected policy. + + * PID 1 will now listen to Out-Of-Memory (OOM) events the kernel + generates when processes it manages are reaching their memory limits, + and will place their units in a special state, and optionally kill or + stop the whole unit. + + * The service manager will now expose bus properties for the IO + resources used by units. This information is also shown in "systemctl + status" now (for services that have IOAccounting=yes set). Moreover, + the IO accounting data is included in the resource log message + generated whenever a unit stops. + + * Units may now configure an explicit time-out to wait for when killed + with SIGABRT, for example when a service watchdog is hit. Previously, + the regular TimeoutStopSec= time-out was applied in this case too — + now a separate time-out may be set using TimeoutAbortSec=. + + * Services may now send a special WATCHDOG=trigger message with + sd_notify() to trigger an immediate "watchdog missed" event, and thus + trigger service termination. This is useful both for testing watchdog + handling, but also for defining error paths in services, that shall + be handled the same way as watchdog events. + + * There are two new per-unit settings IPIngressFilterPath= and + IPEgressFilterPath= which allow configuration of a BPF program + (usually by specifying a path to a program uploaded to /sys/fs/bpf/) + to apply to the IP packet ingress/egress path of all processes of a + unit. This is useful to allow running systemd services with BPF + programs set up externally. + + * systemctl gained a new "clean" verb for removing the state, cache, + runtime or logs directories of a service while it is terminated. The + new verb may also be used to remove the state maintained on disk for + timer units that have Persistent= configured. + + * During the last phase of shutdown systemd will now automatically + increase the log level configured in the "kernel.printk" sysctl so + that any relevant loggable events happening during late shutdown are + made visible. Previously, loggable events happening so late during + shutdown were generally lost if the "kernel.printk" sysctl was set to + high thresholds, as regular logging daemons are terminated at that + time and thus nothing is written to disk. + + * If processes terminated during the last phase of shutdown do not exit + quickly systemd will now show their names after a short time, to make + debugging easier. After a longer time-out they are forcibly killed, + as before. + + * journalctl (and the other tools that display logs) will now highlight + warnings in yellow (previously, both LOG_NOTICE and LOG_WARNING where + shown in bright bold, now only LOG_NOTICE is). Moreover, audit logs + are now shown in blue color, to separate them visually from regular + logs. References to configuration files are now turned into clickable + links on terminals that support that. + + * systemd-journald will now stop logging to /var/log/journal during + shutdown when /var/ is on a separate mount, so that it can be + unmounted safely during shutdown. + + * systemd-resolved gained support for a new 'strict' DNS-over-TLS mode. + + * systemd-resolved "Cache=" configuration option in resolved.conf has + been extended to also accept the 'no-negative' value. Previously, + only a boolean option was allowed (yes/no), having yes as the + default. If this option is set to 'no-negative', negative answers are + not cached while the old cache heuristics are used positive answers. + The default remains unchanged. + + * The predictable naming scheme for network devices now supports + generating predictable names for "netdevsim" devices. + + Moreover, the "en" prefix was dropped from the ID_NET_NAME_ONBOARD + udev property. + + Those two changes form a new net.naming-policy-scheme= entry. + Distributions which want to preserve naming stability may want to set + the -Ddefault-net-naming-scheme= configuration option. + + * systemd-networkd now supports MACsec, nlmon, IPVTAP and Xfrm + interfaces natively. + + * systemd-networkd's bridge FDB support now allows configuration of a + destination address for each entry (Destination=), as well as the + VXLAN VNI (VNI=), as well as an option to declare what an entry is + associated with (AssociatedWith=). + + * systemd-networkd's DHCPv4 support now understands a new MaxAttempts= + option for configuring the maximum number of DHCP lease requests. It + also learnt a new BlackList= option for blacklisting DHCP servers (a + similar setting has also been added to the IPv6 RA client), as well + as a SendRelease= option for configuring whether to send a DHCP + RELEASE message when terminating. + + * systemd-networkd's DHCPv4 and DHCPv6 stacks can now be configured + separately in the [DHCPv4] and [DHCPv6] sections. + + * systemd-networkd's DHCP support will now optionally create an + implicit host route to the DNS server specified in the DHCP lease, in + addition to the routes listed explicitly in the lease. This should + ensure that in multi-homed systems DNS traffic leaves the systems on + the interface that acquired the DNS server information even if other + routes such as default routes exist. This behaviour may be turned on + with the new RoutesToDNS= option. + + * systemd-networkd's VXLAN support gained a new option + GenericProtocolExtension= for enabling VXLAN Generic Protocol + Extension support, as well as IPDoNotFragment= for setting the IP + "Don't fragment" bit on outgoing packets. A similar option has been + added to the GENEVE support. + + * In systemd-networkd's [Route] section you may now configure + FastOpenNoCookie= for configuring per-route TCP fast-open support, as + well as TTLPropagate= for configuring Label Switched Path (LSP) TTL + propagation. The Type= setting now supports local, broadcast, + anycast, multicast, any, xresolve routes, too. + + * systemd-networkd's [Network] section learnt a new option + DefaultRouteOnDevice= for automatically configuring a default route + onto the network device. + + * systemd-networkd's bridging support gained two new options ProxyARP= + and ProxyARPWifi= for configuring proxy ARP behaviour as well as + MulticastRouter= for configuring multicast routing behaviour. A new + option MulticastIGMPVersion= may be used to change bridge's multicast + Internet Group Management Protocol (IGMP) version. + + * systemd-networkd's FooOverUDP support gained the ability to configure + local and peer IP addresses via Local= and Peer=. A new option + PeerPort= may be used to configure the peer's IP port. + + * systemd-networkd's TUN support gained a new setting VnetHeader= for + tweaking Generic Segment Offload support. + + * networkctl gained a new "delete" command for removing virtual network + devices, as well as a new "--stats" switch for showing device + statistics. + + * networkd.conf gained a new setting SpeedMeter= and + SpeedMeterIntervalSec=, to measure bitrate of network interfaces. The + measured speed may be shown by 'networkctl status'. + + * "networkctl status" now displays MTU and queue lengths, and more + detailed information about VXLAN and bridge devices. + + * systemd-networkd's .network and .link files gained a new Property= + setting in the [Match] section, to match against devices with + specific udev properties. + + * systemd-networkd's tunnel support gained a new option + AssignToLoopback= for selecting whether to use the loopback device + "lo" as underlying device. + + * systemd-networkd's MACAddress= setting in the [Neighbor] section has + been renamed to LinkLayerAddress=, and it now allows configuration of + IP addresses, too. + + * systemd-networkd's handling of the kernel's disable_ipv6 sysctl is + simplified: systemd-networkd will disable the sysctl (enable IPv6) if + IPv6 configuration (static or DHCPv6) was found for a given + interface. It will not touch the sysctl otherwise. + + * The order of entries is $PATH used by the user manager instance was + changed to put bin/ entries before the corresponding sbin/ entries. + It is recommended to not rely on this order, and only ever have one + binary with a given name in the system paths under /usr. + + * A new tool systemd-network-generator has been added that may generate + .network, .netdev and .link files from IP configuration specified on + the kernel command line in the format used by Dracut. + + * The CriticalConnection= setting in .network files is now deprecated, + and replaced by a new KeepConfiguration= setting which allows more + detailed configuration of the IP configuration to keep in place. + + * systemd-analyze gained a few new verbs: + + - "systemd-analyze timestamp" parses and converts timestamps. This is + similar to the existing "systemd-analyze calendar" command which + does the same for recurring calendar events. + + - "systemd-analyze timespan" parses and converts timespans (i.e. + durations as opposed to points in time). + + - "systemd-analyze condition" will parse and test ConditionXYZ= + expressions. + + - "systemd-analyze exit-status" will parse and convert exit status + codes to their names and back. + + - "systemd-analyze unit-files" will print a list of all unit + file paths and unit aliases. + + * SuccessExitStatus=, RestartPreventExitStatus=, and + RestartForceExitStatus= now accept exit status names (e.g. "DATAERR" + is equivalent to "65"). Those exit status name mappings may be + displayed with the systemd-analyze exit-status verb describe above. + + * systemd-logind now exposes a per-session SetBrightness() bus call, + which may be used to securely change the brightness of a kernel + brightness device, if it belongs to the session's seat. By using this + call unprivileged clients can make changes to "backlight" and "leds" + devices securely with strict requirements on session membership. + Desktop environments may use this to generically make brightness + changes to such devices without shipping private SUID binaries or + udev rules for that purpose. + + * "udevadm info" gained a --wait-for-initialization switch to wait for + a device to be initialized. + + * systemd-hibernate-resume-generator will now look for resumeflags= on + the kernel command line, which is similar to rootflags= and may be + used to configure device timeout for the hibernation device. + + * sd-event learnt a new API call sd_event_source_disable_unref() for + disabling and unref'ing an event source in a single function. A + related call sd_event_source_disable_unrefp() has been added for use + with gcc's cleanup extension. + + * The sd-id128.h public API gained a new definition + SD_ID128_UUID_FORMAT_STR for formatting a 128bit ID in UUID format + with printf(). + + * "busctl introspect" gained a new switch --xml-interface for dumping + XML introspection data unmodified. + + * PID 1 may now show the unit name instead of the unit description + string in its status output during boot. This may be configured in + the StatusUnitFormat= setting in /etc/systemd/system.conf or the + kernel command line option systemd.status_unit_format=. + + * PID 1 now understands a new option KExecWatchdogSec= in + /etc/systemd/system.conf to set a watchdog timeout for kexec reboots. + Previously watchdog functionality was only available for regular + reboots. The new setting defaults to off, because we don't know in + the general case if the watchdog will be reset after kexec (some + drivers do reset it, but not all), and the new userspace might not be + configured to handle the watchdog. + + Moreover, the old ShutdownWatchdogSec= setting has been renamed to + RebootWatchdogSec= to more clearly communicate what it is about. The + old name is still accepted for compatibility. + + * The systemd.debug_shell kernel command line option now optionally + takes a tty name to spawn the debug shell on, which allows a + different tty to be selected than the built-in default. + + * Service units gained a new ExecCondition= setting which will run + before ExecStartPre= and either continue execution of the unit (for + clean exit codes), stop execution without marking the unit failed + (for exit codes 1 through 254), or stop execution and fail the unit + (for exit code 255 or abnormal termination). + + * A new service systemd-pstore.service has been added that pulls data + from /sys/fs/pstore/ and saves it to /var/lib/pstore for later + review. + + * timedatectl gained new verbs for configuring per-interface NTP + service configuration for systemd-timesyncd. + + * "localectl list-locales" won't list non-UTF-8 locales anymore. It's + 2019. (You can set non-UTF-8 locales though, if you know their name.) + + * If variable assignments in sysctl.d/ files are prefixed with "-" any + failures to apply them are now ignored. + + * systemd-random-seed.service now optionally credits entropy when + applying the seed to the system. Set $SYSTEMD_RANDOM_SEED_CREDIT to + true for the service to enable this behaviour, but please consult the + documentation first, since this comes with a couple of caveats. + + * systemd-random-seed.service is now a synchronization point for full + initialization of the kernel's entropy pool. Services that require + /dev/urandom to be correctly initialized should be ordered after this + service. + + * The systemd-boot boot loader has been updated to optionally maintain + a random seed file in the EFI System Partition (ESP). During the boot + phase, this random seed is read and updated with a new seed + cryptographically derived from it. Another derived seed is passed to + the OS. The latter seed is then credited to the kernel's entropy pool + very early during userspace initialization (from PID 1). This allows + systems to boot up with a fully initialized kernel entropy pool from + earliest boot on, and thus entirely removes all entropy pool + initialization delays from systems using systemd-boot. Special care + is taken to ensure different seeds are derived on system images + replicated to multiple systems. "bootctl status" will show whether + a seed was received from the boot loader. + + * bootctl gained two new verbs: + + - "bootctl random-seed" will generate the file in ESP and an EFI + variable to allow a random seed to be passed to the OS as described + above. + + - "bootctl is-installed" checks whether systemd-boot is currently + installed. + + * bootctl will warn if it detects that boot entries are misconfigured + (for example if the kernel image was removed without purging the + bootloader entry). + + * A new document has been added describing systemd's use and support + for the kernel's entropy pool subsystem: + + https://systemd.io/RANDOM_SEEDS + + * When the system is hibernated the swap device to write the + hibernation image to is now automatically picked from all available + swap devices, preferring the swap device with the highest configured + priority over all others, and picking the device with the most free + space if there are multiple devices with the highest priority. + + * /etc/crypttab support has learnt a new keyfile-timeout= per-device + option that permits selecting the timout how long to wait for a + device with an encryption key before asking for the password. + + * IOWeight= has learnt to properly set the IO weight when using the + BFQ scheduler officially found in kernels 5.0+. + + * A new mailing list has been created for reporting of security issues: + systemd-security@redhat.com. For mode details, see + https://systemd.io/CONTRIBUTING#security-vulnerability-reports. + + Contributions from: Aaron Barany, Adrian Bunk, Alan Jenkins, Albrecht + Lohofener, Andrej Valek, Anita Zhang, Arian van Putten, Balint Reczey, + Bastien Nocera, Ben Boeckel, Benjamin Robin, camoz, Chen Qi, Chris + Chiu, Chris Down, Christian Kellner, Clinton Roy, Connor Reeder, Daniel + Black, Daniele Medri, Dan Streetman, Dave Reisner, Dave Ross, David + Art, David Tardon, Debarshi Ray, Dimitri John Ledkov, Dominick Grift, + Donald Buczek, Douglas Christman, Eric DeVolder, EtherGraf, Evgeny + Vereshchagin, Feldwor, Felix Riemann, Florian Dollinger, Francesco + Pennica, Franck Bui, Frantisek Sumsal, Franz Pletz, frederik, Hans + de Goede, Iago López Galeiras, Insun Pyo, Ivan Shapovalov, Iwan Timmer, + Jack, Jakob Unterwurzacher, Jan Chren, Jan Klötzke, Jan Losinski, Jan + Pokorný, Jan Synacek, Jan-Michael Brummer, Jeka Pats, Jeremy Soller, + Jérémy Rosen, Jiri Pirko, Joe Lin, Joerg Behrmann, Joe Richey, Jóhann + B. Guðmundsson, Johannes Christ, Johannes Schmitz, Jonathan Rouleau, + Jorge Niedbalski, Kai Krakow, Kai Lüke, Karel Zak, Kashyap Chamarthy, + Krayushkin Konstantin, Lennart Poettering, Lubomir Rintel, Luca + Boccassi, Luís Ferreira, Marc-André Lureau, Markus Felten, Martin Pitt, + Matthew Leeds, Mattias Jernberg, Michael Biebl, Michael Olbrich, + Michael Prokop, Michael Stapelberg, Michael Zhivich, Michal Koutný, + Michal Sekletar, Mike Gilbert, Milan Broz, Miroslav Lichvar, mpe85, + Mr-Foo, Network Silence, Oliver Harley, pan93412, Paul Menzel, pEJipE, + Peter A. Bigot, Philip Withnall, Piotr Drąg, Rafael Fontenelle, Roberto + Santalla, Ronan Pigott, root, RussianNeuroMancer, Sebastian Jennen, + shinygold, Shreyas Behera, Simon Schricker, Susant Sahani, Thadeu Lima + de Souza Cascardo, Theo Ouzhinski, Thiebaud Weksteen, Thomas Haller, + Thomas Weißschuh, Tomas Mraz, Tommi Rantala, Topi Miettinen, VD-Lycos, + ven, Wieland Hoffmann, William A. Kennington III, William Wold, Xi + Ruoyao, Yuri Chornoivan, Yu Watanabe, Zach Smith, Zbigniew + Jędrzejewski-Szmek, Zhang Xianwei + + – Camerino, 2019-09-03 + +CHANGES WITH 242: + + * In .link files, MACAddressPolicy=persistent (the default) is changed + to cover more devices. For devices like bridges, tun, tap, bond, and + similar interfaces that do not have other identifying information, + the interface name is used as the basis for persistent seed for MAC + and IPv4LL addresses. The way that devices that were handled + previously is not changed, and this change is about covering more + devices then previously by the "persistent" policy. + + MACAddressPolicy=random may be used to force randomized MACs and + IPv4LL addresses for a device if desired. + + Hint: the log output from udev (at debug level) was enhanced to + clarify what policy is followed and which attributes are used. + `SYSTEMD_LOG_LEVEL=debug udevadm test-builtin net_setup_link /sys/class/net/` + may be used to view this. + + Hint: if a bridge interface is created without any slaves, and gains + a slave later, then now the bridge does not inherit slave's MAC. + To inherit slave's MAC, for example, create the following file: + ``` + # /etc/systemd/network/98-bridge-inherit-mac.link + [Match] + Type=bridge + + [Link] + MACAddressPolicy=none + ``` + + * The .device units generated by systemd-fstab-generator and other + generators do not automatically pull in the corresponding .mount unit + as a Wants= dependency. This means that simply plugging in the device + will not cause the mount unit to be started automatically. But please + note that the mount unit may be started for other reasons, in + particular if it is part of local-fs.target, and any unit which + (transitively) depends on local-fs.target is started. + + * networkctl list/status/lldp now accept globbing wildcards for network + interface names to match against all existing interfaces. + + * The $PIDFILE environment variable is set to point the absolute path + configured with PIDFile= for processes of that service. + + * The fallback DNS server list was augmented with Cloudflare public DNS + servers. Use `-Ddns-servers=` to set a different fallback. + + * A new special target usb-gadget.target will be started automatically + when a USB Device Controller is detected (which means that the system + is a USB peripheral). + + * A new unit setting CPUQuotaPeriodSec= assigns the time period + relatively to which the CPU time quota specified by CPUQuota= is + measured. + + * A new unit setting ProtectHostname= may be used to prevent services + from modifying hostname information (even if they otherwise would + have privileges to do so). + + * A new unit setting NetworkNamespacePath= may be used to specify a + namespace for service or socket units through a path referring to a + Linux network namespace pseudo-file. + + * The PrivateNetwork= setting and JoinsNamespaceOf= dependencies now + have an effect on .socket units: when used the listening socket is + created within the configured network namespace instead of the host + namespace. + + * ExecStart= command lines in unit files may now be prefixed with ':' + in which case environment variable substitution is + disabled. (Supported for the other ExecXYZ= settings, too.) + + * .timer units gained two new boolean settings OnClockChange= and + OnTimezoneChange= which may be used to also trigger a unit when the + system clock is changed or the local timezone is + modified. systemd-run has been updated to make these options easily + accessible from the command line for transient timers. + + * Two new conditions for units have been added: ConditionMemory= may be + used to conditionalize a unit based on installed system + RAM. ConditionCPUs= may be used to conditionalize a unit based on + installed CPU cores. + + * The @default system call filter group understood by SystemCallFilter= + has been updated to include the new rseq() system call introduced in + kernel 4.15. + + * A new time-set.target has been added that indicates that the system + time has been set from a local source (possibly imprecise). The + existing time-sync.target is stronger and indicates that the time has + been synchronized with a precise external source. Services where + approximate time is sufficient should use the new target. + + * "systemctl start" (and related commands) learnt a new + --show-transaction option. If specified brief information about all + jobs queued because of the requested operation is shown. + + * systemd-networkd recognizes a new operation state 'enslaved', used + (instead of 'degraded' or 'carrier') for interfaces which form a + bridge, bond, or similar, and an new 'degraded-carrier' operational + state used for the bond or bridge master interface when one of the + enslaved devices is not operational. + + * .network files learnt the new IgnoreCarrierLoss= option for leaving + networks configured even if the carrier is lost. + + * The RequiredForOnline= setting in .network files may now specify a + minimum operational state required for the interface to be considered + "online" by systemd-networkd-wait-online. Related to this + systemd-networkd-wait-online gained a new option --operational-state= + to configure the same, and its --interface= option was updated to + optionally also take an operational state specific for an interface. + + * systemd-networkd-wait-online gained a new setting --any for waiting + for only one of the requested interfaces instead of all of them. + + * systemd-networkd now implements L2TP tunnels. + + * Two new .network settings UseAutonomousPrefix= and UseOnLinkPrefix= + may be used to cause autonomous and onlink prefixes received in IPv6 + Router Advertisements to be ignored. + + * New MulticastFlood=, NeighborSuppression=, and Learning= .network + file settings may be used to tweak bridge behaviour. + + * The new TripleSampling= option in .network files may be used to + configure CAN triple sampling. + + * A new .netdev settings PrivateKeyFile= and PresharedKeyFile= may be + used to point to private or preshared key for a WireGuard interface. + + * /etc/crypttab now supports the same-cpu-crypt and + submit-from-crypt-cpus options to tweak encryption work scheduling + details. + + * systemd-tmpfiles will now take a BSD file lock before operating on a + contents of directory. This may be used to temporarily exclude + directories from aging by taking the same lock (useful for example + when extracting a tarball into /tmp or /var/tmp as a privileged user, + which might create files with really old timestamps, which + nevertheless should not be deleted). For further details, see: + + https://systemd.io/TEMPORARY_DIRECTORIES + + * systemd-tmpfiles' h line type gained support for the + FS_PROJINHERIT_FL ('P') file attribute (introduced in kernel 4.5), + controlling project quota inheritance. + + * sd-boot and bootctl now implement support for an Extended Boot Loader + (XBOOTLDR) partition, that is intended to be mounted to /boot, in + addition to the ESP partition mounted to /efi or /boot/efi. + Configuration file fragments, kernels, initrds and other EFI images + to boot will be loaded from both the ESP and XBOOTLDR partitions. + The XBOOTLDR partition was previously described by the Boot Loader + Specification, but implementation was missing in sd-boot. Support for + this concept allows using the sd-boot boot loader in more + conservative scenarios where the boot loader itself is placed in the + ESP but the kernels to boot (and their metadata) in a separate + partition. + + * A system may now be booted with systemd.volatile=overlay on the + kernel command line, which causes the root file system to be set up + an overlayfs mount combining the root-only root directory with a + writable tmpfs. In this setup, the underlying root device is not + modified, and any changes are lost at reboot. + + * Similar, systemd-nspawn can now boot containers with a volatile + overlayfs root with the new --volatile=overlay switch. + + * systemd-nspawn can now consume OCI runtime bundles using a new + --oci-bundle= option. This implementation is fully usable, with most + features in the specification implemented, but since this a lot of + new code and functionality, this feature should most likely not + be used in production yet. + + * systemd-nspawn now supports various options described by the OCI + runtime specification on the command-line and in .nspawn files: + --inaccessible=/Inaccessible= may be used to mask parts of the file + system tree, --console=/--pipe may be used to configure how standard + input, output, and error are set up. + + * busctl learned the `emit` verb to generate D-Bus signals. + + * systemd-analyze cat-config may be used to gather and display + configuration spread over multiple files, for example system and user + presets, tmpfiles.d, sysusers.d, udev rules, etc. + + * systemd-analyze calendar now takes an optional new parameter + --iterations= which may be used to show a maximum number of iterations + the specified expression will elapse next. + + * The sd-bus C API gained support for naming method parameters in the + introspection data. + + * systemd-logind gained D-Bus APIs to specify the "reboot parameter" + the reboot() system call expects. + + * journalctl learnt a new --cursor-file= option that points to a file + from which a cursor should be loaded in the beginning and to which + the updated cursor should be stored at the end. + + * ACRN hypervisor and Windows Subsystem for Linux (WSL) are now + detected by systemd-detect-virt (and may also be used in + ConditionVirtualization=). + + * The behaviour of systemd-logind may now be modified with environment + variables $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP, + $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU, and + $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY. They cause logind to either + skip the relevant operation completely (when set to false), or to + create a flag file in /run/systemd (when set to true), instead of + actually commencing the real operation when requested. The presence + of /run/systemd/reboot-to-firmware-setup, + /run/systemd/reboot-to-boot-loader-menu, and + /run/systemd/reboot-to-boot-loader-entry, may be used by alternative + boot loader implementations to replace some steps logind performs + during reboot with their own operations. + + * systemctl can be used to request a reboot into the boot loader menu + or a specific boot loader entry with the new --boot-load-menu= and + --boot-loader-entry= options to a reboot command. (This requires a + boot loader that supports this, for example sd-boot.) + + * kernel-install will no longer unconditionally create the output + directory (e.g. /efi//) for boot loader + snippets, but will do only if the machine-specific parent directory + (i.e. /efi//) already exists. bootctl has been modified + to create this parent directory during sd-boot installation. + + This makes it easier to use kernel-install with plugins which support + a different layout of the bootloader partitions (for example grub2). + + * During package installation (with `ninja install`), we would create + symlinks for getty@tty1.service, systemd-networkd.service, + systemd-networkd.socket, systemd-resolved.service, + remote-cryptsetup.target, remote-fs.target, + systemd-networkd-wait-online.service, and systemd-timesyncd.service + in /etc, as if `systemctl enable` was called for those units, to make + the system usable immediately after installation. Now this is not + done anymore, and instead calling `systemctl preset-all` is + recommended after the first installation of systemd. + + * A new boolean sandboxing option RestrictSUIDSGID= has been added that + is built on seccomp. When turned on creation of SUID/SGID files is + prohibited. + + * The NoNewPrivileges= and the new RestrictSUIDSGID= options are now + implied if DynamicUser= is turned on for a service. This hardens + these services, so that they neither can benefit from nor create + SUID/SGID executables. This is a minor compatibility breakage, given + that when DynamicUser= was first introduced SUID/SGID behaviour was + unaffected. However, the security benefit of these two options is + substantial, and the setting is still relatively new, hence we opted + to make it mandatory for services with dynamic users. + + Contributions from: Adam Jackson, Alexander Tsoy, Andrey Yashkin, + Andrzej Pietrasiewicz, Anita Zhang, Balint Reczey, Beniamino Galvani, + Ben Iofel, Benjamin Berg, Benjamin Dahlhoff, Chris, Chris Morin, + Christopher Wong, Claudius Ellsel, Clemens Gruber, dana, Daniel Black, + Davide Cavalca, David Michael, David Rheinsberg, emersion, Evgeny + Vereshchagin, Filipe Brandenburger, Franck Bui, Frantisek Sumsal, + Giacinto Cifelli, Hans de Goede, Hugo Kindel, Ignat Korchagin, Insun + Pyo, Jan Engelhardt, Jonas Dorel, Jonathan Lebon, Jonathon Kowalski, + Jörg Sommer, Jörg Thalheim, Jussi Pakkanen, Kai-Heng Feng, Lennart + Poettering, Lubomir Rintel, Luís Ferreira, Martin Pitt, Matthias + Klumpp, Michael Biebl, Michael Niewöhner, Michael Olbrich, Michal + Sekletar, Mike Lothian, Paul Menzel, Piotr Drąg, Riccardo Schirone, + Robin Elvedi, Roman Kulikov, Ronald Tschalär, Ross Burton, Ryan + Gonzalez, Sebastian Krzyszkowiak, Stephane Chazelas, StKob, Susant + Sahani, Sylvain Plantefève, Szabolcs Fruhwald, Taro Yamada, Theo + Ouzhinski, Thomas Haller, Tobias Jungel, Tom Yan, Tony Asleson, Topi + Miettinen, unixsysadmin, Van Laser, Vesa Jääskeläinen, Yu, Li-Yu, + Yu Watanabe, Zbigniew Jędrzejewski-Szmek + + — Warsaw, 2019-04-11 + +CHANGES WITH 241: + + * The default locale can now be configured at compile time. Otherwise, + a suitable default will be selected automatically (one of C.UTF-8, + en_US.UTF-8, and C). + + * The version string shown by systemd and other tools now includes the + git commit hash when built from git. An override may be specified + during compilation, which is intended to be used by distributions to + include the package release information. + + * systemd-cat can now filter standard input and standard error streams + for different syslog priorities using the new --stderr-priority= + option. + + * systemd-journald and systemd-journal-remote reject entries which + contain too many fields (CVE-2018-16865) and set limits on the + process' command line length (CVE-2018-16864). + + * $DBUS_SESSION_BUS_ADDRESS environment variable is set by pam_systemd + again. + + * A new network device NamePolicy "keep" is implemented for link files, + and used by default in 99-default.link (the fallback configuration + provided by systemd). With this policy, if the network device name + was already set by userspace, the device will not be renamed again. + This matches the naming scheme that was implemented before + systemd-240. If naming-scheme < 240 is specified, the "keep" policy + is also enabled by default, even if not specified. Effectively, this + means that if naming-scheme >= 240 is specified, network devices will + be renamed according to the configuration, even if they have been + renamed already, if "keep" is not specified as the naming policy in + the .link file. The 99-default.link file provided by systemd includes + "keep" for backwards compatibility, but it is recommended for user + installed .link files to *not* include it. + + The "kernel" policy, which keeps kernel names declared to be + "persistent", now works again as documented. + + * kernel-install script now optionally takes the paths to one or more + initrd files, and passes them to all plugins. + + * The mincore() system call has been dropped from the @system-service + system call filter group, as it is pretty exotic and may potentially + used for side-channel attacks. + + * -fPIE is dropped from compiler and linker options. Please specify + -Db_pie=true option to meson to build position-independent + executables. Note that the meson option is supported since meson-0.49. + + * The fs.protected_regular and fs.protected_fifos sysctls, which were + added in Linux 4.19 to make some data spoofing attacks harder, are + now enabled by default. While this will hopefully improve the + security of most installations, it is technically a backwards + incompatible change; to disable these sysctls again, place the + following lines in /etc/sysctl.d/60-protected.conf or a similar file: + + fs.protected_regular = 0 + fs.protected_fifos = 0 + + Note that the similar hardlink and symlink protection has been + enabled since v199, and may be disabled likewise. + + * The files read from the EnvironmentFile= setting in unit files now + parse backslashes inside quotes literally, matching the behaviour of + POSIX shells. + + * udevadm trigger, udevadm control, udevadm settle and udevadm monitor + now automatically become NOPs when run in a chroot() environment. + + * The tmpfiles.d/ "C" line type will now copy directory trees not only + when the destination is so far missing, but also if it already exists + as a directory and is empty. This is useful to cater for systems + where directory trees are put together from multiple separate mount + points but otherwise empty. + + * A new function sd_bus_close_unref() (and the associated + sd_bus_close_unrefp()) has been added to libsystemd, that combines + sd_bus_close() and sd_bus_unref() in one. + + * udevadm control learnt a new option for --ping for testing whether a + systemd-udevd instance is running and reacting. + + * udevadm trigger learnt a new option for --wait-daemon for waiting + systemd-udevd daemon to be initialized. + + Contributions from: Aaron Plattner, Alberts Muktupāvels, Alex Mayer, + Ayman Bagabas, Beniamino Galvani, Burt P, Chris Down, Chris Lamb, Chris + Morin, Christian Hesse, Claudius Ellsel, dana, Daniel Axtens, Daniele + Medri, Dave Reisner, David Santamaría Rogado, Diego Canuhe, Dimitri + John Ledkov, Evgeny Vereshchagin, Fabrice Fontaine, Filipe + Brandenburger, Franck Bui, Frantisek Sumsal, govwin, Hans de Goede, + James Hilliard, Jan Engelhardt, Jani Uusitalo, Jan Janssen, Jan + Synacek, Jonathan McDowell, Jonathan Roemer, Jonathon Kowalski, Joost + Heitbrink, Jörg Thalheim, Lance, Lennart Poettering, Louis Taylor, + Lucas Werkmeister, Mantas Mikulėnas, Marc-Antoine Perennou, + marvelousblack, Michael Biebl, Michael Sloan, Michal Sekletar, Mike + Auty, Mike Gilbert, Mikhail Kasimov, Neil Brown, Niklas Hambüchen, + Patrick Williams, Paul Seyfert, Peter Hutterer, Philip Withnall, Roger + James, Ronnie P. Thomas, Ryan Gonzalez, Sam Morris, Stephan Edel, + Stephan Gerhold, Susant Sahani, Taro Yamada, Thomas Haller, Topi + Miettinen, YiFei Zhu, YmrDtnJu, YunQiang Su, Yu Watanabe, Zbigniew + Jędrzejewski-Szmek, zsergeant77, Дамјан Георгиевски + + — Berlin, 2019-02-14 + +CHANGES WITH 240: + + * NoNewPrivileges=yes has been set for all long-running services + implemented by systemd. Previously, this was problematic due to + SELinux (as this would also prohibit the transition from PID1's label + to the service's label). This restriction has since been lifted, but + an SELinux policy update is required. + (See e.g. https://github.com/fedora-selinux/selinux-policy/pull/234.) + + * DynamicUser=yes is dropped from systemd-networkd.service, + systemd-resolved.service and systemd-timesyncd.service, which was + enabled in v239 for systemd-networkd.service and systemd-resolved.service, + and since v236 for systemd-timesyncd.service. The users and groups + systemd-network, systemd-resolve and systemd-timesync are created + by systemd-sysusers again. Distributors or system administrators + may need to create these users and groups if they not exist (or need + to re-enable DynamicUser= for those units) while upgrading systemd. + Also, the clock file for systemd-timesyncd may need to move from + /var/lib/private/systemd/timesync/clock to /var/lib/systemd/timesync/clock. + + * When unit files are loaded from disk, previously systemd would + sometimes (depending on the unit loading order) load units from the + target path of symlinks in .wants/ or .requires/ directories of other + units. This meant that unit could be loaded from different paths + depending on whether the unit was requested explicitly or as a + dependency of another unit, not honouring the priority of directories + in search path. It also meant that it was possible to successfully + load and start units which are not found in the unit search path, as + long as they were requested as a dependency and linked to from + .wants/ or .requires/. The target paths of those symlinks are not + used for loading units anymore and the unit file must be found in + the search path. + + * A new service type has been added: Type=exec. It's very similar to + Type=simple but ensures the service manager will wait for both fork() + and execve() of the main service binary to complete before proceeding + with follow-up units. This is primarily useful so that the manager + propagates any errors in the preparation phase of service execution + back to the job that requested the unit to be started. For example, + consider a service that has ExecStart= set to a file system binary + that doesn't exist. With Type=simple starting the unit would be + considered instantly successful, as only fork() has to complete + successfully and the manager does not wait for execve(), and hence + its failure is seen "too late". With the new Type=exec service type + starting the unit will fail, as the manager will wait for the + execve() and notice its failure, which is then propagated back to the + start job. + + NOTE: with the next release 241 of systemd we intend to change the + systemd-run tool to default to Type=exec for transient services + started by it. This should be mostly safe, but in specific corner + cases might result in problems, as the systemd-run tool will then + block on NSS calls (such as user name look-ups due to User=) done + between the fork() and execve(), which under specific circumstances + might cause problems. It is recommended to specify "-p Type=simple" + explicitly in the few cases where this applies. For regular, + non-transient services (i.e. those defined with unit files on disk) + we will continue to default to Type=simple. + + * The Linux kernel's current default RLIMIT_NOFILE resource limit for + userspace processes is set to 1024 (soft) and 4096 + (hard). Previously, systemd passed this on unmodified to all + processes it forked off. With this systemd release the hard limit + systemd passes on is increased to 512K, overriding the kernel's + defaults and substantially increasing the number of simultaneous file + descriptors unprivileged userspace processes can allocate. Note that + the soft limit remains at 1024 for compatibility reasons: the + traditional UNIX select() call cannot deal with file descriptors >= + 1024 and increasing the soft limit globally might thus result in + programs unexpectedly allocating a high file descriptor and thus + failing abnormally when attempting to use it with select() (of + course, programs shouldn't use select() anymore, and prefer + poll()/epoll, but the call unfortunately remains undeservedly popular + at this time). This change reflects the fact that file descriptor + handling in the Linux kernel has been optimized in more recent + kernels and allocating large numbers of them should be much cheaper + both in memory and in performance than it used to be. Programs that + want to take benefit of the increased limit have to "opt-in" into + high file descriptors explicitly by raising their soft limit. Of + course, when they do that they must acknowledge that they cannot use + select() anymore (and neither can any shared library they use — or + any shared library used by any shared library they use and so on). + Which default hard limit is most appropriate is of course hard to + decide. However, given reports that ~300K file descriptors are used + in real-life applications we believe 512K is sufficiently high as new + default for now. Note that there are also reports that using very + high hard limits (e.g. 1G) is problematic: some software allocates + large arrays with one element for each potential file descriptor + (Java, …) — a high hard limit thus triggers excessively large memory + allocations in these applications. Hopefully, the new default of 512K + is a good middle ground: higher than what real-life applications + currently need, and low enough for avoid triggering excessively large + allocations in problematic software. (And yes, somebody should fix + Java.) + + * The fs.nr_open and fs.file-max sysctls are now automatically bumped + to the highest possible values, as separate accounting of file + descriptors is no longer necessary, as memcg tracks them correctly as + part of the memory accounting anyway. Thus, from the four limits on + file descriptors currently enforced (fs.file-max, fs.nr_open, + RLIMIT_NOFILE hard, RLIMIT_NOFILE soft) we turn off the first two, + and keep only the latter two. A set of build-time options + (-Dbump-proc-sys-fs-file-max=false and -Dbump-proc-sys-fs-nr-open=false) + has been added to revert this change in behaviour, which might be + an option for systems that turn off memcg in the kernel. + + * When no /etc/locale.conf file exists (and hence no locale settings + are in place), systemd will now use the "C.UTF-8" locale by default, + and set LANG= to it. This locale is supported by various + distributions including Fedora, with clear indications that upstream + glibc is going to make it available too. This locale enables UTF-8 + mode by default, which appears appropriate for 2018. + + * The "net.ipv4.conf.all.rp_filter" sysctl will now be set to 2 by + default. This effectively switches the RFC3704 Reverse Path filtering + from Strict mode to Loose mode. This is more appropriate for hosts + that have multiple links with routes to the same networks (e.g. + a client with a Wi-Fi and Ethernet both connected to the internet). + + Consult the kernel documentation for details on this sysctl: + https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt + + * CPUAccounting=yes no longer enables the CPU controller when using + kernel 4.15+ and the unified cgroup hierarchy, as required accounting + statistics are now provided independently from the CPU controller. + + * Support for disabling a particular cgroup controller within a sub-tree + has been added through the DisableControllers= directive. + + * cgroup_no_v1=all on the kernel command line now also implies + using the unified cgroup hierarchy, unless one explicitly passes + systemd.unified_cgroup_hierarchy=0 on the kernel command line. + + * The new "MemoryMin=" unit file property may now be used to set the + memory usage protection limit of processes invoked by the unit. This + controls the cgroup v2 memory.min attribute. Similarly, the new + "IODeviceLatencyTargetSec=" property has been added, wrapping the new + cgroup v2 io.latency cgroup property for configuring per-service I/O + latency. + + * systemd now supports the cgroup v2 devices BPF logic, as counterpart + to the cgroup v1 "devices" cgroup controller. + + * systemd-escape now is able to combine --unescape with --template. It + also learnt a new option --instance for extracting and unescaping the + instance part of a unit name. + + * sd-bus now provides the sd_bus_message_readv() which is similar to + sd_bus_message_read() but takes a va_list object. The pair + sd_bus_set_method_call_timeout() and sd_bus_get_method_call_timeout() + has been added for configuring the default method call timeout to + use. sd_bus_error_move() may be used to efficiently move the contents + from one sd_bus_error structure to another, invalidating the + source. sd_bus_set_close_on_exit() and sd_bus_get_close_on_exit() may + be used to control whether a bus connection object is automatically + flushed when an sd-event loop is exited. + + * When processing classic BSD syslog log messages, journald will now + save the original time-stamp string supplied in the new + SYSLOG_TIMESTAMP= journal field. This permits consumers to + reconstruct the original BSD syslog message more correctly. + + * StandardOutput=/StandardError= in service files gained support for + new "append:…" parameters, for connecting STDOUT/STDERR of a service + to a file, and appending to it. + + * The signal to use as last step of killing of unit processes is now + configurable. Previously it was hard-coded to SIGKILL, which may now + be overridden with the new KillSignal= setting. Note that this is the + signal used when regular termination (i.e. SIGTERM) does not suffice. + Similarly, the signal used when aborting a program in case of a + watchdog timeout may now be configured too (WatchdogSignal=). + + * The XDG_SESSION_DESKTOP environment variable may now be configured in + the pam_systemd argument line, using the new desktop= switch. This is + useful to initialize it properly from a display manager without + having to touch C code. + + * Most configuration options that previously accepted percentage values + now also accept permille values with the '‰' suffix (instead of '%'). + + * systemd-resolved may now optionally use OpenSSL instead of GnuTLS for + DNS-over-TLS. + + * systemd-resolved's configuration file resolved.conf gained a new + option ReadEtcHosts= which may be used to turn off processing and + honoring /etc/hosts entries. + + * The "--wait" switch may now be passed to "systemctl + is-system-running", in which case the tool will synchronously wait + until the system finished start-up. + + * hostnamed gained a new bus call to determine the DMI product UUID. + + * On x86-64 systemd will now prefer using the RDRAND processor + instruction over /dev/urandom whenever it requires randomness that + neither has to be crypto-grade nor should be reproducible. This + should substantially reduce the amount of entropy systemd requests + from the kernel during initialization on such systems, though not + reduce it to zero. (Why not zero? systemd still needs to allocate + UUIDs and such uniquely, which require high-quality randomness.) + + * networkd gained support for Foo-Over-UDP, ERSPAN and ISATAP + tunnels. It also gained a new option ForceDHCPv6PDOtherInformation= + for forcing the "Other Information" bit in IPv6 RA messages. The + bonding logic gained four new options AdActorSystemPriority=, + AdUserPortKey=, AdActorSystem= for configuring various 802.3ad + aspects, and DynamicTransmitLoadBalancing= for enabling dynamic + shuffling of flows. The tunnel logic gained a new + IPv6RapidDeploymentPrefix= option for configuring IPv6 Rapid + Deployment. The policy rule logic gained four new options IPProtocol=, + SourcePort= and DestinationPort=, InvertRule=. The bridge logic gained + support for the MulticastToUnicast= option. networkd also gained + support for configuring static IPv4 ARP or IPv6 neighbor entries. + + * .preset files (as read by 'systemctl preset') may now be used to + instantiate services. + + * /etc/crypttab now understands the sector-size= option to configure + the sector size for an encrypted partition. + + * Key material for encrypted disks may now be placed on a formatted + medium, and referenced from /etc/crypttab by the UUID of the file + system, followed by "=" suffixed by the path to the key file. + + * The "collect" udev component has been removed without replacement, as + it is neither used nor maintained. + + * When the RuntimeDirectory=, StateDirectory=, CacheDirectory=, + LogsDirectory=, ConfigurationDirectory= settings are used in a + service the executed processes will now receive a set of environment + variables containing the full paths of these directories. + Specifically, RUNTIME_DIRECTORY=, STATE_DIRECTORY, CACHE_DIRECTORY, + LOGS_DIRECTORY, CONFIGURATION_DIRECTORY are now set if these options + are used. Note that these options may be used multiple times per + service in which case the resulting paths will be concatenated and + separated by colons. + + * Predictable interface naming has been extended to cover InfiniBand + NICs. They will be exposed with an "ib" prefix. + + * tmpfiles.d/ line types may now be suffixed with a '-' character, in + which case the respective line failing is ignored. + + * .link files may now be used to configure the equivalent to the + "ethtool advertise" commands. + + * The sd-device.h and sd-hwdb.h APIs are now exported, as an + alternative to libudev.h. Previously, the latter was just an internal + wrapper around the former, but now these two APIs are exposed + directly. + + * sd-id128.h gained a new function sd_id128_get_boot_app_specific() + which calculates an app-specific boot ID similar to how + sd_id128_get_machine_app_specific() generates an app-specific machine + ID. + + * A new tool systemd-id128 has been added that can be used to determine + and generate various 128bit IDs. + + * /etc/os-release gained two new standardized fields DOCUMENTATION_URL= + and LOGO=. + + * systemd-hibernate-resume-generator will now honor the "noresume" + kernel command line option, in which case it will bypass resuming + from any hibernated image. + + * The systemd-sleep.conf configuration file gained new options + AllowSuspend=, AllowHibernation=, AllowSuspendThenHibernate=, + AllowHybridSleep= for prohibiting specific sleep modes even if the + kernel exports them. + + * portablectl is now officially supported and has thus moved to + /usr/bin/. + + * bootctl learnt the two new commands "set-default" and "set-oneshot" + for setting the default boot loader item to boot to (either + persistently or only for the next boot). This is currently only + compatible with sd-boot, but may be implemented on other boot loaders + too, that follow the boot loader interface. The updated interface is + now documented here: + + https://systemd.io/BOOT_LOADER_INTERFACE + + * A new kernel command line option systemd.early_core_pattern= is now + understood which may be used to influence the core_pattern PID 1 + installs during early boot. + + * busctl learnt two new options -j and --json= for outputting method + call replies, properties and monitoring output in JSON. + + * journalctl's JSON output now supports simple ANSI coloring as well as + a new "json-seq" mode for generating RFC7464 output. + + * Unit files now support the %g/%G specifiers that resolve to the UNIX + group/GID of the service manager runs as, similar to the existing + %u/%U specifiers that resolve to the UNIX user/UID. + + * systemd-logind learnt a new global configuration option + UserStopDelaySec= that may be set in logind.conf. It specifies how + long the systemd --user instance shall remain started after a user + logs out. This is useful to speed up repetitive re-connections of the + same user, as it means the user's service manager doesn't have to be + stopped/restarted on each iteration, but can be reused between + subsequent options. This setting defaults to 10s. systemd-logind also + exports two new properties on its Manager D-Bus objects indicating + whether the system's lid is currently closed, and whether the system + is on AC power. + + * systemd gained support for a generic boot counting logic, which + generically permits automatic reverting to older boot loader entries + if newer updated ones don't work. The boot loader side is implemented + in sd-boot, but is kept open for other boot loaders too. For details + see: + + https://systemd.io/AUTOMATIC_BOOT_ASSESSMENT + + * The SuccessAction=/FailureAction= unit file settings now learnt two + new parameters: "exit" and "exit-force", which result in immediate + exiting of the service manager, and are only useful in systemd --user + and container environments. + + * Unit files gained support for a pair of options + FailureActionExitStatus=/SuccessActionExitStatus= for configuring the + exit status to use as service manager exit status when + SuccessAction=/FailureAction= is set to exit or exit-force. + + * A pair of LogRateLimitIntervalSec=/LogRateLimitBurst= per-service + options may now be used to configure the log rate limiting applied by + journald per-service. + + * systemd-analyze gained a new verb "timespan" for parsing and + normalizing time span values (i.e. strings like "5min 7s 8us"). + + * systemd-analyze also gained a new verb "security" for analyzing the + security and sand-boxing settings of services in order to determine an + "exposure level" for them, indicating whether a service would benefit + from more sand-boxing options turned on for them. + + * "systemd-analyze syscall-filter" will now also show system calls + supported by the local kernel but not included in any of the defined + groups. + + * .nspawn files now understand the Ephemeral= setting, matching the + --ephemeral command line switch. + + * sd-event gained the new APIs sd_event_source_get_floating() and + sd_event_source_set_floating() for controlling whether a specific + event source is "floating", i.e. destroyed along with the even loop + object itself. + + * Unit objects on D-Bus gained a new "Refs" property that lists all + clients that currently have a reference on the unit (to ensure it is + not unloaded). + + * The JoinControllers= option in system.conf is no longer supported, as + it didn't work correctly, is hard to support properly, is legacy (as + the concept only exists on cgroup v1) and apparently wasn't used. + + * Journal messages that are generated whenever a unit enters the failed + state are now tagged with a unique MESSAGE_ID. Similarly, messages + generated whenever a service process exits are now made recognizable, + too. A tagged message is also emitted whenever a unit enters the + "dead" state on success. + + * systemd-run gained a new switch --working-directory= for configuring + the working directory of the service to start. A shortcut -d is + equivalent, setting the working directory of the service to the + current working directory of the invoking program. The new --shell + (or just -S) option has been added for invoking the $SHELL of the + caller as a service, and implies --pty --same-dir --wait --collect + --service-type=exec. Or in other words, "systemd-run -S" is now the + quickest way to quickly get an interactive in a fully clean and + well-defined system service context. + + * machinectl gained a new verb "import-fs" for importing an OS tree + from a directory. Moreover, when a directory or tarball is imported + and single top-level directory found with the OS itself below the OS + tree is automatically mangled and moved one level up. + + * systemd-importd will no longer set up an implicit btrfs loop-back + file system on /var/lib/machines. If one is already set up, it will + continue to be used. + + * A new generator "systemd-run-generator" has been added. It will + synthesize a unit from one or more program command lines included in + the kernel command line. This is very useful in container managers + for example: + + # systemd-nspawn -i someimage.raw -b systemd.run='"some command line"' + + This will run "systemd-nspawn" on an image, invoke the specified + command line and immediately shut down the container again, returning + the command line's exit code. + + * The block device locking logic is now documented: + + https://systemd.io/BLOCK_DEVICE_LOCKING + + * loginctl and machinectl now optionally output the various tables in + JSON using the --output= switch. It is our intention to add similar + support to systemctl and all other commands. + + * udevadm's query and trigger verb now optionally take a .device unit + name as argument. + + * systemd-udevd's network naming logic now understands a new + net.naming-scheme= kernel command line switch, which may be used to + pick a specific version of the naming scheme. This helps stabilizing + interface names even as systemd/udev are updated and the naming logic + is improved. + + * sd-id128.h learnt two new auxiliary helpers: sd_id128_is_allf() and + SD_ID128_ALLF to test if a 128bit ID is set to all 0xFF bytes, and to + initialize one to all 0xFF. + + * After loading the SELinux policy systemd will now recursively relabel + all files and directories listed in + /run/systemd/relabel-extra.d/*.relabel (which should be simple + newline separated lists of paths) in addition to the ones it already + implicitly relabels in /run, /dev and /sys. After the relabelling is + completed the *.relabel files (and /run/systemd/relabel-extra.d/) are + removed. This is useful to permit initrds (i.e. code running before + the SELinux policy is in effect) to generate files in the host + filesystem safely and ensure that the correct label is applied during + the transition to the host OS. + + * KERNEL API BREAKAGE: Linux kernel 4.18 changed behaviour regarding + mknod() handling in user namespaces. Previously mknod() would always + fail with EPERM in user namespaces. Since 4.18 mknod() will succeed + but device nodes generated that way cannot be opened, and attempts to + open them result in EPERM. This breaks the "graceful fallback" logic + in systemd's PrivateDevices= sand-boxing option. This option is + implemented defensively, so that when systemd detects it runs in a + restricted environment (such as a user namespace, or an environment + where mknod() is blocked through seccomp or absence of CAP_SYS_MKNOD) + where device nodes cannot be created the effect of PrivateDevices= is + bypassed (following the logic that 2nd-level sand-boxing is not + essential if the system systemd runs in is itself already sand-boxed + as a whole). This logic breaks with 4.18 in container managers where + user namespacing is used: suddenly PrivateDevices= succeeds setting + up a private /dev/ file system containing devices nodes — but when + these are opened they don't work. + + At this point it is recommended that container managers utilizing + user namespaces that intend to run systemd in the payload explicitly + block mknod() with seccomp or similar, so that the graceful fallback + logic works again. + + We are very sorry for the breakage and the requirement to change + container configurations for newer kernels. It's purely caused by an + incompatible kernel change. The relevant kernel developers have been + notified about this userspace breakage quickly, but they chose to + ignore it. + + * PermissionsStartOnly= setting is deprecated (but is still supported + for backwards compatibility). The same functionality is provided by + the more flexible "+", "!", and "!!" prefixes to ExecStart= and other + commands. + + * $DBUS_SESSION_BUS_ADDRESS environment variable is not set by + pam_systemd anymore. + + * The naming scheme for network devices was changed to always rename + devices, even if they were already renamed by userspace. The "kernel" + policy was changed to only apply as a fallback, if no other naming + policy took effect. + + * The requirements to build systemd is bumped to meson-0.46 and + python-3.5. + + Contributions from: afg, Alan Jenkins, Aleksei Timofeyev, Alexander + Filippov, Alexander Kurtz, Alexey Bogdanenko, Andreas Henriksson, + Andrew Jorgensen, Anita Zhang, apnix-uk, Arkan49, Arseny Maslennikov, + asavah, Asbjørn Apeland, aszlig, Bastien Nocera, Ben Boeckel, Benedikt + Morbach, Benjamin Berg, Bruce Zhang, Carlo Caione, Cedric Viou, Chen + Qi, Chris Chiu, Chris Down, Chris Morin, Christian Rebischke, Claudius + Ellsel, Colin Guthrie, dana, Daniel, Daniele Medri, Daniel Kahn + Gillmor, Daniel Rusek, Daniel van Vugt, Dariusz Gadomski, Dave Reisner, + David Anderson, Davide Cavalca, David Leeds, David Malcolm, David + Strauss, David Tardon, Dimitri John Ledkov, Dmitry Torokhov, dj-kaktus, + Dongsu Park, Elias Probst, Emil Soleyman, Erik Kooistra, Ervin Peters, + Evgeni Golov, Evgeny Vereshchagin, Fabrice Fontaine, Faheel Ahmad, + Faizal Luthfi, Felix Yan, Filipe Brandenburger, Franck Bui, Frank + Schaefer, Frantisek Sumsal, Gautier Husson, Gianluca Boiano, Giuseppe + Scrivano, glitsj16, Hans de Goede, Harald Hoyer, Harry Mallon, Harshit + Jain, Helmut Grohne, Henry Tung, Hui Yiqun, imayoda, Insun Pyo, Iwan + Timmer, Jan Janssen, Jan Pokorný, Jan Synacek, Jason A. Donenfeld, + javitoom, Jérémy Nouhaud, Jeremy Su, Jiuyang Liu, João Paulo Rechi + Vita, Joe Hershberger, Joe Rayhawk, Joerg Behrmann, Joerg Steffens, + Jonas Dorel, Jon Ringle, Josh Soref, Julian Andres Klode, Jun Bo Bi, + Jürg Billeter, Keith Busch, Khem Raj, Kirill Marinushkin, Larry + Bernstone, Lennart Poettering, Lion Yang, Li Song, Lorenz + Hübschle-Schneider, Lubomir Rintel, Lucas Werkmeister, Ludwin Janvier, + Lukáš Nykrýn, Luke Shumaker, mal, Marc-Antoine Perennou, Marcin + Skarbek, Marco Trevisan (Treviño), Marian Cepok, Mario Hros, Marko + Myllynen, Markus Grimm, Martin Pitt, Martin Sobotka, Martin Wilck, + Mathieu Trudel-Lapierre, Matthew Leeds, Michael Biebl, Michael Olbrich, + Michael 'pbone' Pobega, Michael Scherer, Michal Koutný, Michal + Sekletar, Michal Soltys, Mike Gilbert, Mike Palmer, Muhammet Kara, Neal + Gompa, Neil Brown, Network Silence, Niklas Tibbling, Nikolas Nyby, + Nogisaka Sadata, Oliver Smith, Patrik Flykt, Pavel Hrdina, Paweł + Szewczyk, Peter Hutterer, Piotr Drąg, Ray Strode, Reinhold Mueller, + Renaud Métrich, Roman Gushchin, Ronny Chevalier, Rubén Suárez Alvarez, + Ruixin Bao, RussianNeuroMancer, Ryutaroh Matsumoto, Saleem Rashid, Sam + Morris, Samuel Morris, Sandy Carter, scootergrisen, Sébastien Bacher, + Sergey Ptashnick, Shawn Landden, Shengyao Xue, Shih-Yuan Lee + (FourDollars), Silvio Knizek, Sjoerd Simons, Stasiek Michalski, Stephen + Gallagher, Steven Allen, Steve Ramage, Susant Sahani, Sven Joachim, + Sylvain Plantefève, Tanu Kaskinen, Tejun Heo, Thiago Macieira, Thomas + Blume, Thomas Haller, Thomas H. P. Andersen, Tim Ruffing, TJ, Tobias + Jungel, Todd Walton, Tommi Rantala, Tomsod M, Tony Novak, Tore + Anderson, Trevonn, Victor Laskurain, Victor Tapia, Violet Halo, Vojtech + Trefny, welaq, William A. Kennington III, William Douglas, Wyatt Ward, + Xiang Fan, Xi Ruoyao, Xuanwo, Yann E. Morin, YmrDtnJu, Yu Watanabe, + Zbigniew Jędrzejewski-Szmek, Zhang Xianwei, Zsolt Dollenstein + + — Warsaw, 2018-12-21 + +CHANGES WITH 239: + + * NETWORK INTERFACE DEVICE NAMING CHANGES: systemd-udevd's "net_id" + builtin will name network interfaces differently than in previous + versions for virtual network interfaces created with SR-IOV and NPAR + and for devices where the PCI network controller device does not have + a slot number associated. + + SR-IOV virtual devices are now named based on the name of the parent + interface, with a suffix of "v", where is the virtual device + number. Previously those virtual devices were named as if completely + independent. + + The ninth and later NPAR virtual devices will be named following the + scheme used for the first eight NPAR partitions. Previously those + devices were not renamed and the kernel default (eth) was used. + + "net_id" will also generate names for PCI devices where the PCI + network controller device does not have an associated slot number + itself, but one of its parents does. Previously those devices were + not renamed and the kernel default (eth) was used. + + * AF_INET and AF_INET6 are dropped from RestrictAddressFamilies= in + systemd-logind.service. Since v235, IPAddressDeny=any has been set to + the unit. So, it is expected that the default behavior of + systemd-logind is not changed. However, if distribution packagers or + administrators disabled or modified IPAddressDeny= setting by a + drop-in config file, then it may be necessary to update the file to + re-enable AF_INET and AF_INET6 to support network user name services, + e.g. NIS. + + * When the RestrictNamespaces= unit property is specified multiple + times, then the specified types are merged now. Previously, only the + last assignment was used. So, if distribution packagers or + administrators modified the setting by a drop-in config file, then it + may be necessary to update the file. + + * When OnFailure= is used in combination with Restart= on a service + unit, then the specified units will no longer be triggered on + failures that result in restarting. Previously, the specified units + would be activated each time the unit failed, even when the unit was + going to be restarted automatically. This behaviour contradicted the + documentation. With this release the code is adjusted to match the + documentation. + + * systemd-tmpfiles will now print a notice whenever it encounters + tmpfiles.d/ lines referencing the /var/run/ directory. It will + recommend reworking them to use the /run/ directory instead (for + which /var/run/ is simply a symlinked compatibility alias). This way + systemd-tmpfiles can properly detect line conflicts and merge lines + referencing the same file by two paths, without having to access + them. + + * systemctl disable/unmask/preset/preset-all cannot be used with + --runtime. Previously this was allowed, but resulted in unintuitive + behaviour that wasn't useful. systemctl disable/unmask will now undo + both runtime and persistent enablement/masking, i.e. it will remove + any relevant symlinks both in /run and /etc. + + * Note that all long-running system services shipped with systemd will + now default to a system call whitelist (rather than a blacklist, as + before). In particular, systemd-udevd will now enforce one too. For + most cases this should be safe, however downstream distributions + which disabled sandboxing of systemd-udevd (specifically the + MountFlags= setting), might want to disable this security feature + too, as the default whitelisting will prohibit all mount, swap, + reboot and clock changing operations from udev rules. + + * sd-boot acquired new loader configuration settings to optionally turn + off Windows and MacOS boot partition discovery as well as + reboot-into-firmware menu items. It is also able to pick a better + screen resolution for HiDPI systems, and now provides loader + configuration settings to change the resolution explicitly. + + * systemd-resolved now supports DNS-over-TLS. It's still + turned off by default, use DNSOverTLS=opportunistic to turn it on in + resolved.conf. We intend to make this the default as soon as couple + of additional techniques for optimizing the initial latency caused by + establishing a TLS/TCP connection are implemented. + + * systemd-resolved.service and systemd-networkd.service now set + DynamicUser=yes. The users systemd-resolve and systemd-network are + not created by systemd-sysusers anymore. + + NOTE: This has a chance of breaking nss-ldap and similar NSS modules + that embed a network facing module into any process using getpwuid() + or related call: the dynamic allocation of the user ID for + systemd-resolved.service means the service manager has to check NSS + if the user name is already taken when forking off the service. Since + the user in the common case won't be defined in /etc/passwd the + lookup is likely to trigger nss-ldap which in turn might use NSS to + ask systemd-resolved for hostname lookups. This will hence result in + a deadlock: a user name lookup in order to start + systemd-resolved.service will result in a host name lookup for which + systemd-resolved.service needs to be started already. There are + multiple ways to work around this problem: pre-allocate the + "systemd-resolve" user on such systems, so that nss-ldap won't be + triggered; or use a different NSS package that doesn't do networking + in-process but provides a local asynchronous name cache; or configure + the NSS package to avoid lookups for UIDs in the range `pkg-config + systemd --variable=dynamicuidmin` … `pkg-config systemd + --variable=dynamicuidmax`, so that it does not consider itself + authoritative for the same UID range systemd allocates dynamic users + from. + + * The systemd-resolve tool has been renamed to resolvectl (it also + remains available under the old name, for compatibility), and its + interface is now verb-based, similar in style to the other ctl + tools, such as systemctl or loginctl. + + * The resolvectl/systemd-resolve tool also provides 'resolvconf' + compatibility. It may be symlinked under the 'resolvconf' name, in + which case it will take arguments and input compatible with the + Debian and FreeBSD resolvconf tool. + + * Support for suspend-then-hibernate has been added, i.e. a sleep mode + where the system initially suspends, and after a timeout resumes and + hibernates again. + + * networkd's ClientIdentifier= now accepts a new option "duid-only". If + set the client will only send a DUID as client identifier. + + * The nss-systemd glibc NSS module will now enumerate dynamic users and + groups in effect. Previously, it could resolve UIDs/GIDs to user + names/groups and vice versa, but did not support enumeration. + + * journald's Compress= configuration setting now optionally accepts a + byte threshold value. All journal objects larger than this threshold + will be compressed, smaller ones will not. Previously this threshold + was not configurable and set to 512. + + * A new system.conf setting NoNewPrivileges= is now available which may + be used to turn off acquisition of new privileges system-wide + (i.e. set Linux' PR_SET_NO_NEW_PRIVS for PID 1 itself, and thus also + for all its children). Note that turning this option on means setuid + binaries and file system capabilities lose their special powers. + While turning on this option is a big step towards a more secure + system, doing so is likely to break numerous pre-existing UNIX tools, + in particular su and sudo. + + * A new service systemd-time-sync-wait.service has been added. If + enabled it will delay the time-sync.target unit at boot until time + synchronization has been received from the network. This + functionality is useful on systems lacking a local RTC or where it is + acceptable that the boot process shall be delayed by external network + services. + + * When hibernating, systemd will now inform the kernel of the image + write offset, on kernels new enough to support this. This means swap + files should work for hibernation now. + + * When loading unit files, systemd will now look for drop-in unit files + extensions in additional places. Previously, for a unit file name + "foo-bar-baz.service" it would look for dropin files in + "foo-bar-baz.service.d/*.conf". Now, it will also look in + "foo-bar-.service.d/*.conf" and "foo-.service.d/", i.e. at the + service name truncated after all inner dashes. This scheme allows + writing drop-ins easily that apply to a whole set of unit files at + once. It's particularly useful for mount and slice units (as their + naming is prefix based), but is also useful for service and other + units, for packages that install multiple unit files at once, + following a strict naming regime of beginning the unit file name with + the package's name. Two new specifiers are now supported in unit + files to match this: %j and %J are replaced by the part of the unit + name following the last dash. + + * Unit files and other configuration files that support specifier + expansion now understand another three new specifiers: %T and %V will + resolve to /tmp and /var/tmp respectively, or whatever temporary + directory has been set for the calling user. %E will expand to either + /etc (for system units) or $XDG_CONFIG_HOME (for user units). + + * The ExecStart= lines of unit files are no longer required to + reference absolute paths. If non-absolute paths are specified the + specified binary name is searched within the service manager's + built-in $PATH, which may be queried with 'systemd-path + search-binaries-default'. It's generally recommended to continue to + use absolute paths for all binaries specified in unit files. + + * Units gained a new load state "bad-setting", which is used when a + unit file was loaded, but contained fatal errors which prevent it + from being started (for example, a service unit has been defined + lacking both ExecStart= and ExecStop= lines). + + * coredumpctl's "gdb" verb has been renamed to "debug", in order to + support alternative debuggers, for example lldb. The old name + continues to be available however, for compatibility reasons. Use the + new --debugger= switch or the $SYSTEMD_DEBUGGER environment variable + to pick an alternative debugger instead of the default gdb. + + * systemctl and the other tools will now output escape sequences that + generate proper clickable hyperlinks in various terminal emulators + where useful (for example, in the "systemctl status" output you can + now click on the unit file name to quickly open it in the + editor/viewer of your choice). Note that not all terminal emulators + support this functionality yet, but many do. Unfortunately, the + "less" pager doesn't support this yet, hence this functionality is + currently automatically turned off when a pager is started (which + happens quite often due to auto-paging). We hope to remove this + limitation as soon as "less" learns these escape sequences. This new + behaviour may also be turned off explicitly with the $SYSTEMD_URLIFY + environment variable. For details on these escape sequences see: + https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda + + * networkd's .network files now support a new IPv6MTUBytes= option for + setting the MTU used by IPv6 explicitly as well as a new MTUBytes= + option in the [Route] section to configure the MTU to use for + specific routes. It also gained support for configuration of the DHCP + "UserClass" option through the new UserClass= setting. It gained + three new options in the new [CAN] section for configuring CAN + networks. The MULTICAST and ALLMULTI interface flags may now be + controlled explicitly with the new Multicast= and AllMulticast= + settings. + + * networkd will now automatically make use of the kernel's route + expiration feature, if it is available. + + * udevd's .link files now support setting the number of receive and + transmit channels, using the RxChannels=, TxChannels=, + OtherChannels=, CombinedChannels= settings. + + * Support for UDPSegmentationOffload= has been removed, given its + limited support in hardware, and waning software support. + + * networkd's .netdev files now support creating "netdevsim" interfaces. + + * PID 1 learnt a new bus call GetUnitByControlGroup() which may be used + to query the unit belonging to a specific kernel control group. + + * systemd-analyze gained a new verb "cat-config", which may be used to + dump the contents of any configuration file, with all its matching + drop-in files added in, and honouring the usual search and masking + logic applied to systemd configuration files. For example use + "systemd-analyze cat-config systemd/system.conf" to get the complete + system configuration file of systemd how it would be loaded by PID 1 + itself. Similar to this, various tools such as systemd-tmpfiles or + systemd-sysusers, gained a new option "--cat-config", which does the + corresponding operation for their own configuration settings. For + example, "systemd-tmpfiles --cat-config" will now output the full + list of tmpfiles.d/ lines in place. + + * timedatectl gained three new verbs: "show" shows bus properties of + systemd-timedated, "timesync-status" shows the current NTP + synchronization state of systemd-timesyncd, and "show-timesync" + shows bus properties of systemd-timesyncd. + + * systemd-timesyncd gained a bus interface on which it exposes details + about its state. + + * A new environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES is now + understood by systemd-timedated. It takes a colon-separated list of + unit names of NTP client services. The list is used by + "timedatectl set-ntp". + + * systemd-nspawn gained a new --rlimit= switch for setting initial + resource limits for the container payload. There's a new switch + --hostname= to explicitly override the container's hostname. A new + --no-new-privileges= switch may be used to control the + PR_SET_NO_NEW_PRIVS flag for the container payload. A new + --oom-score-adjust= switch controls the OOM scoring adjustment value + for the payload. The new --cpu-affinity= switch controls the CPU + affinity of the container payload. The new --resolv-conf= switch + allows more detailed control of /etc/resolv.conf handling of the + container. Similarly, the new --timezone= switch allows more detailed + control of /etc/localtime handling of the container. + + * systemd-detect-virt gained a new --list switch, which will print a + list of all currently known VM and container environments. + + * Support for "Portable Services" has been added, see + doc/PORTABLE_SERVICES.md for details. Currently, the support is still + experimental, but this is expected to change soon. Reflecting this + experimental state, the "portablectl" binary is not installed into + /usr/bin yet. The binary has to be called with the full path + /usr/lib/systemd/portablectl instead. + + * journalctl's and systemctl's -o switch now knows a new log output + mode "with-unit". The output it generates is very similar to the + regular "short" mode, but displays the unit name instead of the + syslog tag for each log line. Also, the date is shown with timezone + information. This mode is probably more useful than the classic + "short" output mode for most purposes, except where pixel-perfect + compatibility with classic /var/log/messages formatting is required. + + * A new --dump-bus-properties switch has been added to the systemd + binary, which may be used to dump all supported D-Bus properties. + (Options which are still supported, but are deprecated, are *not* + shown.) + + * sd-bus gained a set of new calls: + sd_bus_slot_set_floating()/sd_bus_slot_get_floating() may be used to + enable/disable the "floating" state of a bus slot object, + i.e. whether the slot object pins the bus it is allocated for into + memory or if the bus slot object gets disconnected when the bus goes + away. sd_bus_open_with_description(), + sd_bus_open_user_with_description(), + sd_bus_open_system_with_description() may be used to allocate bus + objects and set their description string already during allocation. + + * sd-event gained support for watching inotify events from the event + loop, in an efficient way, sharing inotify handles between multiple + users. For this a new function sd_event_add_inotify() has been added. + + * sd-event and sd-bus gained support for calling special user-supplied + destructor functions for userdata pointers associated with + sd_event_source, sd_bus_slot, and sd_bus_track objects. For this new + functions sd_bus_slot_set_destroy_callback, + sd_bus_slot_get_destroy_callback, sd_bus_track_set_destroy_callback, + sd_bus_track_get_destroy_callback, + sd_event_source_set_destroy_callback, + sd_event_source_get_destroy_callback have been added. + + * The "net.ipv4.tcp_ecn" sysctl will now be turned on by default. + + * PID 1 will now automatically reschedule .timer units whenever the + local timezone changes. (They previously got rescheduled + automatically when the system clock changed.) + + * New documentation has been added to document cgroups delegation, + portable services and the various code quality tools we have set up: + + https://github.com/systemd/systemd/blob/master/docs/CGROUP_DELEGATION.md + https://github.com/systemd/systemd/blob/master/docs/PORTABLE_SERVICES.md + https://github.com/systemd/systemd/blob/master/docs/CODE_QUALITY.md + + * The Boot Loader Specification has been added to the source tree. + + https://github.com/systemd/systemd/blob/master/docs/BOOT_LOADER_SPECIFICATION.md + + While moving it into our source tree we have updated it and further + changes are now accepted through the usual github PR workflow. + + * pam_systemd will now look for PAM userdata fields systemd.memory_max, + systemd.tasks_max, systemd.cpu_weight, systemd.io_weight set by + earlier PAM modules. The data in these fields is used to initialize + the session scope's resource properties. Thus external PAM modules + may now configure per-session limits, for example sourced from + external user databases. + + * socket units with Accept=yes will now maintain a "refused" counter in + addition to the existing "accepted" counter, counting connections + refused due to the enforced limits. + + * The "systemd-path search-binaries-default" command may now be use to + query the default, built-in $PATH PID 1 will pass to the services it + manages. + + * A new unit file setting PrivateMounts= has been added. It's a boolean + option. If enabled the unit's processes are invoked in their own file + system namespace. Note that this behaviour is also implied if any + other file system namespacing options (such as PrivateTmp=, + PrivateDevices=, ProtectSystem=, …) are used. This option is hence + primarily useful for services that do not use any of the other file + system namespacing options. One such service is systemd-udevd.service + where this is now used by default. + + * ConditionSecurity= gained a new value "uefi-secureboot" that is true + when the system is booted in UEFI "secure mode". + + * A new unit "system-update-pre.target" is added, which defines an + optional synchronization point for offline system updates, as + implemented by the pre-existing "system-update.target" unit. It + allows ordering services before the service that executes the actual + update process in a generic way. + + * Systemd now emits warnings whenever .include syntax is used. + + Contributions from: Adam Duskett, Alan Jenkins, Alessandro Casale, + Alexander Kurtz, Alex Gartrell, Anssi Hannula, Arnaud Rebillout, Brian + J. Murrell, Bruno Vernay, Chris Lamb, Chris Lesiak, Christian Brauner, + Christian Hesse, Christian Rebischke, Colin Guthrie, Daniel Dao, Daniel + Lin, Danylo Korostil, Davide Cavalca, David Tardon, Dimitri John + Ledkov, Dmitriy Geels, Douglas Christman, Elia Geretto, emelenas, Emil + Velikov, Evgeny Vereshchagin, Felipe Sateler, Feng Sun, Filipe + Brandenburger, Franck Bui, futpib, Giuseppe Scrivano, Guillem Jover, + guixxx, Hannes Reinecke, Hans de Goede, Harald Hoyer, Henrique Dante de + Almeida, Hiram van Paassen, Ian Miell, Igor Gnatenko, Ivan Shapovalov, + Iwan Timmer, James Cowgill, Jan Janssen, Jan Synacek, Jared Kazimir, + Jérémy Rosen, João Paulo Rechi Vita, Joost Heitbrink, Jui-Chi Ricky + Liang, Jürg Billeter, Kai-Heng Feng, Karol Augustin, Kay Sievers, + Krzysztof Nowicki, Lauri Tirkkonen, Lennart Poettering, Leonard König, + Long Li, Luca Boccassi, Lucas Werkmeister, Marcel Hoppe, Marc + Kleine-Budde, Mario Limonciello, Martin Jansa, Martin Wilck, Mathieu + Malaterre, Matteo F. Vescovi, Matthew McGinn, Matthias-Christian Ott, + Michael Biebl, Michael Olbrich, Michael Prokop, Michal Koutný, Michal + Sekletar, Mike Gilbert, Mikhail Kasimov, Milan Broz, Milan Pässler, + Mladen Pejaković, Muhammet Kara, Nicolas Boichat, Omer Katz, Paride + Legovini, Paul Menzel, Paul Milliken, Pavel Hrdina, Peter A. Bigot, + Peter D'Hoye, Peter Hutterer, Peter Jones, Philip Sequeira, Philip + Withnall, Piotr Drąg, Radostin Stoyanov, Ricardo Salveti de Araujo, + Ronny Chevalier, Rosen Penev, Rubén Suárez Alvarez, Ryan Gonzalez, + Salvo Tomaselli, Sebastian Reichel, Sergey Ptashnick, Sergio Lindo + Mansilla, Stefan Schweter, Stephen Hemminger, Stuart Hayes, Susant + Sahani, Sylvain Plantefève, Thomas H. P. Andersen, Tobias Jungel, + Tomasz Torcz, Vito Caputo, Will Dietz, Will Thompson, Wim van Mourik, + Yu Watanabe, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2018-06-22 + +CHANGES WITH 238: + + * The MemoryAccounting= unit property now defaults to on. After + discussions with the upstream control group maintainers we learnt + that the negative impact of cgroup memory accounting on current + kernels is finally relatively minimal, so that it should be safe to + enable this by default without affecting system performance. Besides + memory accounting only task accounting is turned on by default, all + other forms of resource accounting (CPU, IO, IP) remain off for now, + because it's not clear yet that their impact is small enough to move + from opt-in to opt-out. We recommend downstreams to leave memory + accounting on by default if kernel 4.14 or higher is primarily + used. On very resource constrained systems or when support for old + kernels is a necessity, -Dmemory-accounting-default=false can be used + to revert this change. + + * rpm scriptlets to update the udev hwdb and rules (%udev_hwdb_update, + %udev_rules_update) and the journal catalog (%journal_catalog_update) + from the upgrade scriptlets of individual packages now do nothing. + Transfiletriggers have been added which will perform those updates + once at the end of the transaction. + + Similar transfiletriggers have been added to execute any sysctl.d + and binfmt.d rules. Thus, it should be unnecessary to provide any + scriptlets to execute this configuration from package installation + scripts. + + * systemd-sysusers gained a mode where the configuration to execute is + specified on the command line, but this configuration is not executed + directly, but instead it is merged with the configuration on disk, + and the result is executed. This is useful for package installation + scripts which want to create the user before installing any files on + disk (in case some of those files are owned by that user), while + still allowing local admin overrides. + + This functionality is exposed to rpm scriptlets through a new + %sysusers_create_package macro. Old %sysusers_create and + %sysusers_create_inline macros are deprecated. + + A transfiletrigger for sysusers.d configuration is now installed, + which means that it should be unnecessary to call systemd-sysusers from + package installation scripts, unless the package installs any files + owned by those newly-created users, in which case + %sysusers_create_package should be used. + + * Analogous change has been done for systemd-tmpfiles: it gained a mode + where the command-line configuration is merged with the configuration + on disk. This is exposed as the new %tmpfiles_create_package macro, + and %tmpfiles_create is deprecated. A transfiletrigger is installed + for tmpfiles.d, hence it should be unnecessary to call systemd-tmpfiles + from package installation scripts. + + * sysusers.d configuration for a user may now also specify the group + number, in addition to the user number ("u username 123:456"), or + without the user number ("u username -:456"). + + * Configution items for systemd-sysusers can now be specified as + positional arguments when the new --inline switch is used. + + * The login shell of users created through sysusers.d may now be + specified (previously, it was always /bin/sh for root and + /sbin/nologin for other users). + + * systemd-analyze gained a new --global switch to look at global user + configuration. It also gained a unit-paths verb to list the unit load + paths that are compiled into systemd (which can be used with + --systemd, --user, or --global). + + * udevadm trigger gained a new --settle/-w option to wait for any + triggered events to finish (but just those, and not any other events + which are triggered meanwhile). + + * The action that systemd-logind takes when the lid is closed and the + machine is connected to external power can now be configured using + HandleLidSwitchExternalPower= in logind.conf. Previously, this action + was determined by HandleLidSwitch=, and, for backwards compatibility, + is still is, if HandleLidSwitchExternalPower= is not explicitly set. + + * journalctl will periodically call sd_journal_process() to make it + resilient against inotify queue overruns when journal files are + rotated very quickly. + + * Two new functions in libsystemd — sd_bus_get_n_queued_read and + sd_bus_get_n_queued_write — may be used to check the number of + pending bus messages. + + * systemd gained a new + org.freedesktop.systemd1.Manager.AttachProcessesToUnit dbus call + which can be used to migrate foreign processes to scope and service + units. The primary user for this new API is systemd itself: the + systemd --user instance uses this call of the systemd --system + instance to migrate processes if it itself gets the request to + migrate processes and the kernel refuses this due to access + restrictions. Thanks to this "systemd-run --scope --user …" works + again in pure cgroup v2 environments when invoked from the user + session scope. + + * A new TemporaryFileSystem= setting can be used to mask out part of + the real file system tree with tmpfs mounts. This may be combined + with BindPaths= and BindReadOnlyPaths= to hide files or directories + not relevant to the unit, while still allowing some paths lower in + the tree to be accessed. + + ProtectHome=tmpfs may now be used to hide user home and runtime + directories from units, in a way that is mostly equivalent to + "TemporaryFileSystem=/home /run/user /root". + + * Non-service units are now started with KeyringMode=shared by default. + This means that mount and swapon and other mount tools have access + to keys in the main keyring. + + * /sys/fs/bpf is now mounted automatically. + + * QNX virtualization is now detected by systemd-detect-virt and may + be used in ConditionVirtualization=. + + * IPAccounting= may now be enabled also for slice units. + + * A new -Dsplit-bin= build configuration switch may be used to specify + whether bin and sbin directories are merged, or if they should be + included separately in $PATH and various listings of executable + directories. The build configuration scripts will try to autodetect + the proper values of -Dsplit-usr= and -Dsplit-bin= based on build + system, but distributions are encouraged to configure this + explicitly. + + * A new -Dok-color= build configuration switch may be used to change + the colour of "OK" status messages. + + * UPGRADE ISSUE: serialization of units using JoinsNamespaceOf= with + PrivateNetwork=yes was buggy in previous versions of systemd. This + means that after the upgrade and daemon-reexec, any such units must + be restarted. + + * INCOMPATIBILITY: as announced in the NEWS for 237, systemd-tmpfiles + will not exclude read-only files owned by root from cleanup. + + Contributions from: Alan Jenkins, Alexander F Rødseth, Alexis Jeandet, + Andika Triwidada, Andrei Gherzan, Ansgar Burchardt, antizealot1337, + Batuhan Osman Taşkaya, Beniamino Galvani, Bill Yodlowsky, Caio Marcelo + de Oliveira Filho, CuBiC, Daniele Medri, Daniel Mouritzen, Daniel + Rusek, Davide Cavalca, Dimitri John Ledkov, Douglas Christman, Evgeny + Vereshchagin, Faalagorn, Filipe Brandenburger, Franck Bui, futpib, + Giacomo Longo, Gunnar Hjalmarsson, Hans de Goede, Hermann Gausterer, + Iago López Galeiras, Jakub Filak, Jan Synacek, Jason A. Donenfeld, + Javier Martinez Canillas, Jérémy Rosen, Lennart Poettering, Lucas + Werkmeister, Mao Huang, Marco Gulino, Michael Biebl, Michael Vogt, + MilhouseVH, Neal Gompa (ニール・ゴンパ), Oleander Reis, Olof Mogren, + Patrick Uiterwijk, Peter Hutterer, Peter Portante, Piotr Drąg, Robert + Antoni Buj Gelonch, Sergey Ptashnick, Shawn Landden, Shuang Liu, Simon + Fowler, SjonHortensius, snorreflorre, Susant Sahani, Sylvain + Plantefève, Thomas Blume, Thomas Haller, Vito Caputo, Yu Watanabe, + Zbigniew Jędrzejewski-Szmek, Марко М. Костић (Marko M. Kostić) + + — Warsaw, 2018-03-05 + +CHANGES WITH 237: + + * Some keyboards come with a zoom see-saw or rocker which until now got + mapped to the Linux "zoomin/out" keys in hwdb. However, these + keycodes are not recognized by any major desktop. They now produce + Up/Down key events so that they can be used for scrolling. + + * INCOMPATIBILITY: systemd-tmpfiles' "f" lines changed behaviour + slightly: previously, if an argument was specified for lines of this + type (i.e. the right-most column was set) this string was appended to + existing files each time systemd-tmpfiles was run. This behaviour was + different from what the documentation said, and not particularly + useful, as repeated systemd-tmpfiles invocations would not be + idempotent and grow such files without bounds. With this release + behaviour has been altered to match what the documentation says: + lines of this type only have an effect if the indicated files don't + exist yet, and only then the argument string is written to the file. + + * FUTURE INCOMPATIBILITY: In systemd v238 we intend to slightly change + systemd-tmpfiles behaviour: previously, read-only files owned by root + were always excluded from the file "aging" algorithm (i.e. the + automatic clean-up of directories like /tmp based on + atime/mtime/ctime). We intend to drop this restriction, and age files + by default even when owned by root and read-only. This behaviour was + inherited from older tools, but there have been requests to remove + it, and it's not obvious why this restriction was made in the first + place. Please speak up now, if you are aware of software that reqires + this behaviour, otherwise we'll remove the restriction in v238. + + * A new environment variable $SYSTEMD_OFFLINE is now understood by + systemctl. It takes a boolean argument. If on, systemctl assumes it + operates on an "offline" OS tree, and will not attempt to talk to the + service manager. Previously, this mode was implicitly enabled if a + chroot() environment was detected, and this new environment variable + now provides explicit control. + + * .path and .socket units may now be created transiently, too. + Previously only service, mount, automount and timer units were + supported as transient units. The systemd-run tool has been updated + to expose this new functionality, you may hence use it now to bind + arbitrary commands to path or socket activation on-the-fly from the + command line. Moreover, almost all properties are now exposed for the + unit types that already supported transient operation. + + * The systemd-mount command gained support for a new --owner= parameter + which takes a user name, which is then resolved and included in uid= + and gid= mount options string of the file system to mount. + + * A new unit condition ConditionControlGroupController= has been added + that checks whether a specific cgroup controller is available. + + * Unit files, udev's .link files, and systemd-networkd's .netdev and + .network files all gained support for a new condition + ConditionKernelVersion= for checking against specific kernel + versions. + + * In systemd-networkd, the [IPVLAN] section in .netdev files gained + support for configuring device flags in the Flags= setting. In the + same files, the [Tunnel] section gained support for configuring + AllowLocalRemote=. The [Route] section in .network files gained + support for configuring InitialCongestionWindow=, + InitialAdvertisedReceiveWindow= and QuickAck=. The [DHCP] section now + understands RapidCommit=. + + * systemd-networkd's DHCPv6 support gained support for Prefix + Delegation. + + * sd-bus gained support for a new "watch-bind" feature. When this + feature is enabled, an sd_bus connection may be set up to connect to + an AF_UNIX socket in the file system as soon as it is created. This + functionality is useful for writing early-boot services that + automatically connect to the system bus as soon as it is started, + without ugly time-based polling. systemd-networkd and + systemd-resolved have been updated to make use of this + functionality. busctl exposes this functionality in a new + --watch-bind= command line switch. + + * sd-bus will now optionally synthesize a local "Connected" signal as + soon as a D-Bus connection is set up fully. This message mirrors the + already existing "Disconnected" signal which is synthesized when the + connection is terminated. This signal is generally useful but + particularly handy in combination with the "watch-bind" feature + described above. Synthesizing of this message has to be requested + explicitly through the new API call sd_bus_set_connected_signal(). In + addition a new call sd_bus_is_ready() has been added that checks + whether a connection is fully set up (i.e. between the "Connected" and + "Disconnected" signals). + + * sd-bus gained two new calls sd_bus_request_name_async() and + sd_bus_release_name_async() for asynchronously registering bus + names. Similar, there is now sd_bus_add_match_async() for installing + a signal match asynchronously. All of systemd's own services have + been updated to make use of these calls. Doing these operations + asynchronously has two benefits: it reduces the risk of deadlocks in + case of cyclic dependencies between bus services, and it speeds up + service initialization since synchronization points for bus + round-trips are removed. + + * sd-bus gained two new calls sd_bus_match_signal() and + sd_bus_match_signal_async(), which are similar to sd_bus_add_match() + and sd_bus_add_match_async() but instead of taking a D-Bus match + string take match fields as normal function parameters. + + * sd-bus gained two new calls sd_bus_set_sender() and + sd_bus_message_set_sender() for setting the sender name of outgoing + messages (either for all outgoing messages or for just one specific + one). These calls are only useful in direct connections as on + brokered connections the broker fills in the sender anyway, + overwriting whatever the client filled in. + + * sd-event gained a new pseudo-handle that may be specified on all API + calls where an "sd_event*" object is expected: SD_EVENT_DEFAULT. When + used this refers to the default event loop object of the calling + thread. Note however that this does not implicitly allocate one — + which has to be done prior by using sd_event_default(). Similarly + sd-bus gained three new pseudo-handles SD_BUS_DEFAULT, + SD_BUS_DEFAULT_USER, SD_BUS_DEFAULT_SYSTEM that may be used to refer + to the default bus of the specified type of the calling thread. Here + too this does not implicitly allocate bus connection objects, this + has to be done prior with sd_bus_default() and friends. + + * sd-event gained a new call pair + sd_event_source_{get|set}_io_fd_own(). This may be used to request + automatic closure of the file descriptor an IO event source watches + when the event source is destroyed. + + * systemd-networkd gained support for natively configuring WireGuard + connections. + + * In previous versions systemd synthesized user records both for the + "nobody" (UID 65534) and "root" (UID 0) users in nss-systemd and + internally. In order to simplify distribution-wide renames of the + "nobody" user (like it is planned in Fedora: nfsnobody → nobody), a + new transitional flag file has been added: if + /etc/systemd/dont-synthesize-nobody exists synthesizing of the 65534 + user and group record within the systemd codebase is disabled. + + * systemd-notify gained a new --uid= option for selecting the source + user/UID to use for notification messages sent to the service + manager. + + * journalctl gained a new --grep= option to list only entries in which + the message matches a certain pattern. By default matching is case + insensitive if the pattern is lowercase, and case sensitive + otherwise. Option --case-sensitive=yes|no can be used to override + this an specify case sensitivity or case insensitivity. + + * There's now a "systemd-analyze service-watchdogs" command for printing + the current state of the service runtime watchdog, and optionally + enabling or disabling the per-service watchdogs system-wide if given a + boolean argument (i.e. the concept you configure in WatchdogSec=), for + debugging purposes. There's also a kernel command line option + systemd.service_watchdogs= for controlling the same. + + * Two new "log-level" and "log-target" options for systemd-analyze were + added that merge the now deprecated get-log-level, set-log-level and + get-log-target, set-log-target pairs. The deprecated options are still + understood for backwards compatibility. The two new options print the + current value when no arguments are given, and set them when a + level/target is given as an argument. + + * sysusers.d's "u" lines now optionally accept both a UID and a GID + specification, separated by a ":" character, in order to create users + where UID and GID do not match. + + Contributions from: Adam Duskett, Alan Jenkins, Alexander Kuleshov, + Alexis Deruelle, Andrew Jeddeloh, Armin Widegreen, Batuhan Osman + Taşkaya, Björn Esser, bleep_blop, Bruce A. Johnson, Chris Down, Clinton + Roy, Colin Walters, Daniel Rusek, Dimitri John Ledkov, Dmitry Rozhkov, + Evgeny Vereshchagin, Ewout van Mansom, Felipe Sateler, Franck Bui, + Frantisek Sumsal, George Gaydarov, Gianluca Boiano, Hans-Christian + Noren Egtvedt, Hans de Goede, Henrik Grindal Bakken, Jan Alexander + Steffens, Jan Klötzke, Jason A. Donenfeld, jdkbx, Jérémy Rosen, + Jerónimo Borque, John Lin, John Paul Herold, Jonathan Rudenberg, Jörg + Thalheim, Ken (Bitsko) MacLeod, Larry Bernstone, Lennart Poettering, + Lucas Werkmeister, Maciej S. Szmigiero, Marek Čermák, Martin Pitt, + Mathieu Malaterre, Matthew Thode, Matthias-Christian Ott, Max Harmathy, + Michael Biebl, Michael Vogt, Michal Koutný, Michal Sekletar, Michał + Szczepański, Mike Gilbert, Nathaniel McCallum, Nicolas Chauvet, Olaf + Hering, Olivier Schwander, Patrik Flykt, Paul Cercueil, Peter Hutterer, + Piotr Drąg, Raphael Vogelgsang, Reverend Homer, Robert Kolchmeyer, + Samuel Dionne-Riel, Sergey Ptashnick, Shawn Landden, Susant Sahani, + Sylvain Plantefève, Thomas H. P. Andersen, Thomas Huth, Tomasz + Bachorski, Vladislav Vishnyakov, Wieland Hoffmann, Yu Watanabe, Zachary + Winnerman, Zbigniew Jędrzejewski-Szmek, Дамјан Георгиевски, Дилян + Палаузов + + — Brno, 2018-01-28 + +CHANGES WITH 236: + + * The modprobe.d/ drop-in for the bonding.ko kernel module introduced + in v235 has been extended to also set the dummy.ko module option + numdummies=0, preventing the kernel from automatically creating + dummy0. All dummy interfaces must now be explicitly created. + + * Unknown '%' specifiers in configuration files are now rejected. This + applies to units and tmpfiles.d configuration. Any percent characters + that are followed by a letter or digit that are not supposed to be + interpreted as the beginning of a specifier should be escaped by + doubling ("%%"). (So "size=5%" is still accepted, as well as + "size=5%,foo=bar", but not "LABEL=x%y%z" since %y and %z are not + valid specifiers today.) + + * systemd-resolved now maintains a new dynamic + /run/systemd/resolve/stub-resolv.conf compatibility file. It is + recommended to make /etc/resolv.conf a symlink to it. This file + points at the systemd-resolved stub DNS 127.0.0.53 resolver and + includes dynamically acquired search domains, achieving more correct + DNS resolution by software that bypasses local DNS APIs such as NSS. + + * The "uaccess" udev tag has been dropped from /dev/kvm and + /dev/dri/renderD*. These devices now have the 0666 permissions by + default (but this may be changed at build-time). /dev/dri/renderD* + will now be owned by the "render" group along with /dev/kfd. + + * "DynamicUser=yes" has been enabled for systemd-timesyncd.service, + systemd-journal-gatewayd.service and + systemd-journal-upload.service. This means "nss-systemd" must be + enabled in /etc/nsswitch.conf to ensure the UIDs assigned to these + services are resolved properly. + + * In /etc/fstab two new mount options are now understood: + x-systemd.makefs and x-systemd.growfs. The former has the effect that + the configured file system is formatted before it is mounted, the + latter that the file system is resized to the full block device size + after it is mounted (i.e. if the file system is smaller than the + partition it resides on, it's grown). This is similar to the fsck + logic in /etc/fstab, and pulls in systemd-makefs@.service and + systemd-growfs@.service as necessary, similar to + systemd-fsck@.service. Resizing is currently only supported on ext4 + and btrfs. + + * In systemd-networkd, the IPv6 RA logic now optionally may announce + DNS server and domain information. + + * Support for the LUKS2 on-disk format for encrypted partitions has + been added. This requires libcryptsetup2 during compilation and + runtime. + + * The systemd --user instance will now signal "readiness" when its + basic.target unit has been reached, instead of when the run queue ran + empty for the first time. + + * Tmpfiles.d with user configuration are now also supported. + systemd-tmpfiles gained a new --user switch, and snippets placed in + ~/.config/user-tmpfiles.d/ and corresponding directories will be + executed by systemd-tmpfiles --user running in the new + systemd-tmpfiles-setup.service and systemd-tmpfiles-clean.service + running in the user session. + + * Unit files and tmpfiles.d snippets learnt three new % specifiers: + %S resolves to the top-level state directory (/var/lib for the system + instance, $XDG_CONFIG_HOME for the user instance), %C resolves to the + top-level cache directory (/var/cache for the system instance, + $XDG_CACHE_HOME for the user instance), %L resolves to the top-level + logs directory (/var/log for the system instance, + $XDG_CONFIG_HOME/log/ for the user instance). This matches the + existing %t specifier, that resolves to the top-level runtime + directory (/run for the system instance, and $XDG_RUNTIME_DIR for the + user instance). + + * journalctl learnt a new parameter --output-fields= for limiting the + set of journal fields to output in verbose and JSON output modes. + + * systemd-timesyncd's configuration file gained a new option + RootDistanceMaxSec= for setting the maximum root distance of servers + it'll use, as well as the new options PollIntervalMinSec= and + PollIntervalMaxSec= to tweak the minimum and maximum poll interval. + + * bootctl gained a new command "list" for listing all available boot + menu items on systems that follow the boot loader specification. + + * systemctl gained a new --dry-run switch that shows what would be done + instead of doing it, and is currently supported by the shutdown and + sleep verbs. + + * ConditionSecurity= can now detect the TOMOYO security module. + + * Unit file [Install] sections are now also respected in unit drop-in + files. This is intended to be used by drop-ins under /usr/lib/. + + * systemd-firstboot may now also set the initial keyboard mapping. + + * Udev "changed" events for devices which are exposed as systemd + .device units are now propagated to units specified in + ReloadPropagatedFrom= as reload requests. + + * If a udev device has a SYSTEMD_WANTS= property containing a systemd + unit template name (i.e. a name in the form of 'foobar@.service', + without the instance component between the '@' and - the '.'), then + the escaped sysfs path of the device is automatically used as the + instance. + + * SystemCallFilter= in unit files has been extended so that an "errno" + can be specified individually for each system call. Example: + SystemCallFilter=~uname:EILSEQ. + + * The cgroup delegation logic has been substantially updated. Delegate= + now optionally takes a list of controllers (instead of a boolean, as + before), which lists the controllers to delegate at least. + + * The networkd DHCPv6 client now implements the FQDN option (RFC 4704). + + * A new LogLevelMax= setting configures the maximum log level any + process of the service may log at (i.e. anything with a lesser + priority than what is specified is automatically dropped). A new + LogExtraFields= setting allows configuration of additional journal + fields to attach to all log records generated by any of the unit's + processes. + + * New StandardInputData= and StandardInputText= settings along with the + new option StandardInput=data may be used to configure textual or + binary data that shall be passed to the executed service process via + standard input, encoded in-line in the unit file. + + * StandardInput=, StandardOutput= and StandardError= may now be used to + connect stdin/stdout/stderr of executed processes directly with a + file or AF_UNIX socket in the file system, using the new "file:" option. + + * A new unit file option CollectMode= has been added, that allows + tweaking the garbage collection logic for units. It may be used to + tell systemd to garbage collect units that have failed automatically + (normally it only GCs units that exited successfully). systemd-run + and systemd-mount expose this new functionality with a new -G option. + + * "machinectl bind" may now be used to bind mount non-directories + (i.e. regularfiles, devices, fifos, sockets). + + * systemd-analyze gained a new verb "calendar" for validating and + testing calendar time specifications to use for OnCalendar= in timer + units. Besides validating the expression it will calculate the next + time the specified expression would elapse. + + * In addition to the pre-existing FailureAction= unit file setting + there's now SuccessAction=, for configuring a shutdown action to + execute when a unit completes successfully. This is useful in + particular inside containers that shall terminate after some workload + has been completed. Also, both options are now supported for all unit + types, not just services. + + * networkds's IP rule support gained two new options + IncomingInterface= and OutgoingInterface= for configuring the incoming + and outgoing interfaces of configured rules. systemd-networkd also + gained support for "vxcan" network devices. + + * networkd gained a new setting RequiredForOnline=, taking a + boolean. If set, systemd-wait-online will take it into consideration + when determining that the system is up, otherwise it will ignore the + interface for this purpose. + + * The sd_notify() protocol gained support for a new operation: with + FDSTOREREMOVE=1 file descriptors may be removed from the per-service + store again, ahead of POLLHUP or POLLERR when they are removed + anyway. + + * A new document doc/UIDS-GIDS.md has been added to the source tree, + that documents the UID/GID range and assignment assumptions and + requirements of systemd. + + * The watchdog device PID 1 will ping may now be configured through the + WatchdogDevice= configuration file setting, or by setting the + systemd.watchdog_service= kernel commandline option. + + * systemd-resolved's gained support for registering DNS-SD services on + the local network using MulticastDNS. Services may either be + registered by dropping in a .dnssd file in /etc/systemd/dnssd/ (or + the same dir below /run, /usr/lib), or through its D-Bus API. + + * The sd_notify() protocol can now with EXTEND_TIMEOUT_USEC=microsecond + extend the effective start, runtime, and stop time. The service must + continue to send EXTEND_TIMEOUT_USEC within the period specified to + prevent the service manager from making the service as timedout. + + * systemd-resolved's DNSSEC support gained support for RFC 8080 + (Ed25519 keys and signatures). + + * The systemd-resolve command line tool gained a new set of options + --set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnssec=, + --set-nta= and --revert to configure per-interface DNS configuration + dynamically during runtime. It's useful for pushing DNS information + into systemd-resolved from DNS hook scripts that various interface + managing software supports (such as pppd). + + * systemd-nspawn gained a new --network-namespace-path= command line + option, which may be used to make a container join an existing + network namespace, by specifying a path to a "netns" file. + + Contributions from: Alan Jenkins, Alan Robertson, Alessandro Ghedini, + Andrew Jeddeloh, Antonio Rojas, Ari, asavah, bleep_blop, Carsten + Strotmann, Christian Brauner, Christian Hesse, Clinton Roy, Collin + Eggert, Cong Wang, Daniel Black, Daniel Lockyer, Daniel Rusek, Dimitri + John Ledkov, Dmitry Rozhkov, Dongsu Park, Edward A. James, Evgeny + Vereshchagin, Florian Klink, Franck Bui, Gwendal Grignou, Hans de + Goede, Harald Hoyer, Hristo Venev, Iago López Galeiras, Ikey Doherty, + Jakub Wilk, Jérémy Rosen, Jiahui Xie, John Lin, José Bollo, Josef + Andersson, juga0, Krzysztof Nowicki, Kyle Walker, Lars Karlitski, Lars + Kellogg-Stedman, Lauri Tirkkonen, Lennart Poettering, Lubomir Rintel, + Luca Bruno, Lucas Werkmeister, Lukáš Nykrýn, Lukáš Říha, Lukasz + Rubaszewski, Maciej S. Szmigiero, Mantas Mikulėnas, Marcus Folkesson, + Martin Steuer, Mathieu Trudel-Lapierre, Matija Skala, + Matthias-Christian Ott, Max Resch, Michael Biebl, Michael Vogt, Michal + Koutný, Michal Sekletar, Mike Gilbert, Muhammet Kara, Neil Brown, Olaf + Hering, Ondrej Kozina, Patrik Flykt, Patryk Kocielnik, Peter Hutterer, + Piotr Drąg, Razvan Cojocaru, Robin McCorkell, Roland Hieber, Saran + Tunyasuvunakool, Sergey Ptashnick, Shawn Landden, Shuang Liu, Simon + Arlott, Simon Peeters, Stanislav Angelovič, Stefan Agner, Susant + Sahani, Sylvain Plantefève, Thomas Blume, Thomas Haller, Tiago Salem + Herrmann, Tinu Weber, Tom Stellard, Topi Miettinen, Torsten Hilbrich, + Vito Caputo, Vladislav Vishnyakov, WaLyong Cho, Yu Watanabe, Zbigniew + Jędrzejewski-Szmek, Zeal Jagannatha + + — Berlin, 2017-12-14 + +CHANGES WITH 235: + + * INCOMPATIBILITY: systemd-logind.service and other long-running + services now run inside an IPv4/IPv6 sandbox, prohibiting them any IP + communication with the outside. This generally improves security of + the system, and is in almost all cases a safe and good choice, as + these services do not and should not provide any network-facing + functionality. However, systemd-logind uses the glibc NSS API to + query the user database. This creates problems on systems where NSS + is set up to directly consult network services for user database + lookups. In particular, this creates incompatibilities with the + "nss-nis" module, which attempts to directly contact the NIS/YP + network servers it is configured for, and will now consistently + fail. In such cases, it is possible to turn off IP sandboxing for + systemd-logind.service (set IPAddressDeny= in its [Service] section + to the empty string, via a .d/ unit file drop-in). Downstream + distributions might want to update their nss-nis packaging to include + such a drop-in snippet, accordingly, to hide this incompatibility + from the user. Another option is to make use of glibc's nscd service + to proxy such network requests through a privilege-separated, minimal + local caching daemon, or to switch to more modern technologies such + sssd, whose NSS hook-ups generally do not involve direct network + access. In general, we think it's definitely time to question the + implementation choices of nss-nis, i.e. whether it's a good idea + today to embed a network-facing loadable module into all local + processes that need to query the user database, including the most + trivial and benign ones, such as "ls". For more details about + IPAddressDeny= see below. + + * A new modprobe.d drop-in is now shipped by default that sets the + bonding module option max_bonds=0. This overrides the kernel default, + to avoid conflicts and ambiguity as to whether or not bond0 should be + managed by systemd-networkd or not. This resolves multiple issues + with bond0 properties not being applied, when bond0 is configured + with systemd-networkd. Distributors may choose to not package this, + however in that case users will be prevented from correctly managing + bond0 interface using systemd-networkd. + + * systemd-analyze gained new verbs "get-log-level" and "get-log-target" + which print the logging level and target of the system manager. They + complement the existing "set-log-level" and "set-log-target" verbs + used to change those values. + + * journald.conf gained a new boolean setting ReadKMsg= which defaults + to on. If turned off kernel log messages will not be read by + systemd-journald or included in the logs. It also gained a new + setting LineMax= for configuring the maximum line length in + STDOUT/STDERR log streams. The new default for this value is 48K, up + from the previous hardcoded 2048. + + * A new unit setting RuntimeDirectoryPreserve= has been added, which + allows more detailed control of what to do with a runtime directory + configured with RuntimeDirectory= (i.e. a directory below /run or + $XDG_RUNTIME_DIR) after a unit is stopped. + + * The RuntimeDirectory= setting for units gained support for creating + deeper subdirectories below /run or $XDG_RUNTIME_DIR, instead of just + one top-level directory. + + * Units gained new options StateDirectory=, CacheDirectory=, + LogsDirectory= and ConfigurationDirectory= which are closely related + to RuntimeDirectory= but manage per-service directories below + /var/lib, /var/cache, /var/log and /etc. By making use of them it is + possible to write unit files which when activated automatically gain + properly owned service specific directories in these locations, thus + making unit files self-contained and increasing compatibility with + stateless systems and factory reset where /etc or /var are + unpopulated at boot. Matching these new settings there's also + StateDirectoryMode=, CacheDirectoryMode=, LogsDirectoryMode=, + ConfigurationDirectoryMode= for configuring the access mode of these + directories. These settings are particularly useful in combination + with DynamicUser=yes as they provide secure, properly-owned, + writable, and stateful locations for storage, excluded from the + sandbox that such services live in otherwise. + + * Automake support has been removed from this release. systemd is now + Meson-only. + + * systemd-journald will now aggressively cache client metadata during + runtime, speeding up log write performance under pressure. This comes + at a small price though: as much of the metadata is read + asynchronously from /proc/ (and isn't implicitly attached to log + datagrams by the kernel, like UID/GID/PID/SELinux are) this means the + metadata stored alongside a log entry might be slightly + out-of-date. Previously it could only be slightly newer than the log + message. The time window is small however, and given that the kernel + is unlikely to be improved anytime soon in this regard, this appears + acceptable to us. + + * nss-myhostname/systemd-resolved will now by default synthesize an + A/AAAA resource record for the "_gateway" hostname, pointing to the + current default IP gateway. Previously it did that for the "gateway" + name, hampering adoption, as some distributions wanted to leave that + host name open for local use. The old behaviour may still be + requested at build time. + + * systemd-networkd's [Address] section in .network files gained a new + Scope= setting for configuring the IP address scope. The [Network] + section gained a new boolean setting ConfigureWithoutCarrier= that + tells systemd-networkd to ignore link sensing when configuring the + device. The [DHCP] section gained a new Anonymize= boolean option for + turning on a number of options suggested in RFC 7844. A new + [RoutingPolicyRule] section has been added for configuring the IP + routing policy. The [Route] section has gained support for a new + Type= setting which permits configuring + blackhole/unreachable/prohibit routes. + + * The [VRF] section in .netdev files gained a new Table= setting for + configuring the routing table to use. The [Tunnel] section gained a + new Independent= boolean field for configuring tunnels independent of + an underlying network interface. The [Bridge] section gained a new + GroupForwardMask= option for configuration of propagation of link + local frames between bridge ports. + + * The WakeOnLan= setting in .link files gained support for a number of + new modes. A new TCP6SegmentationOffload= setting has been added for + configuring TCP/IPv6 hardware segmentation offload. + + * The IPv6 RA sender implementation may now optionally send out RDNSS + and RDNSSL records to supply DNS configuration to peers. + + * systemd-nspawn gained support for a new --system-call-filter= command + line option for adding and removing entries in the default system + call filter it applies. Moreover systemd-nspawn has been changed to + implement a system call whitelist instead of a blacklist. + + * systemd-run gained support for a new --pipe command line option. If + used the STDIN/STDOUT/STDERR file descriptors passed to systemd-run + are directly passed on to the activated transient service + executable. This allows invoking arbitrary processes as systemd + services (for example to take benefit of dependency management, + accounting management, resource management or log management that is + done automatically for services) — while still allowing them to be + integrated in a classic UNIX shell pipeline. + + * When a service sends RELOAD=1 via sd_notify() and reload propagation + using ReloadPropagationTo= is configured, a reload is now propagated + to configured units. (Previously this was only done on explicitly + requested reloads, using "systemctl reload" or an equivalent + command.) + + * For each service unit a restart counter is now kept: it is increased + each time the service is restarted due to Restart=, and may be + queried using "systemctl show -p NRestarts …". + + * New system call filter groups @aio, @sync, @chown, @setuid, @memlock, + @signal and @timer have been added, for usage with SystemCallFilter= + in unit files and the new --system-call-filter= command line option + of systemd-nspawn (see above). + + * ExecStart= lines in unit files gained two new modifiers: when a + command line is prefixed with "!" the command will be executed as + configured, except for the credentials applied by + setuid()/setgid()/setgroups(). It is very similar to the pre-existing + "+", but does still apply namespacing options unlike "+". There's + also "!!" now, which is mostly identical, but becomes a NOP on + systems that support ambient capabilities. This is useful to write + unit files that work with ambient capabilities where possible but + automatically fall back to traditional privilege dropping mechanisms + on systems where this is not supported. + + * ListenNetlink= settings in socket units now support RDMA netlink + sockets. + + * A new unit file setting LockPersonality= has been added which permits + locking down the chosen execution domain ("personality") of a service + during runtime. + + * A new special target "getty-pre.target" has been added, which is + ordered before all text logins, and may be used to order services + before textual logins acquire access to the console. + + * systemd will now attempt to load the virtio-rng.ko kernel module very + early on if a VM environment supporting this is detected. This should + improve entropy during early boot in virtualized environments. + + * A _netdev option is now supported in /etc/crypttab that operates in a + similar way as the same option in /etc/fstab: it permits configuring + encrypted devices that need to be ordered after the network is up. + Following this logic, two new special targets + remote-cryptsetup-pre.target and remote-cryptsetup.target have been + added that are to cryptsetup.target what remote-fs.target and + remote-fs-pre.target are to local-fs.target. + + * Service units gained a new UnsetEnvironment= setting which permits + unsetting specific environment variables for services that are + normally passed to it (for example in order to mask out locale + settings for specific services that can't deal with it). + + * Units acquired a new boolean option IPAccounting=. When turned on, IP + traffic accounting (packet count as well as byte count) is done for + the service, and shown as part of "systemctl status" or "systemd-run + --wait". + + * Service units acquired two new options IPAddressAllow= and + IPAddressDeny=, taking a list of IPv4 or IPv6 addresses and masks, + for configuring a simple IP access control list for all sockets of + the unit. These options are available also on .slice and .socket + units, permitting flexible access list configuration for individual + services as well as groups of services (as defined by a slice unit), + including system-wide. Note that IP ACLs configured this way are + enforced on every single IPv4 and IPv6 socket created by any process + of the service unit, and apply to ingress as well as egress traffic. + + * If CPUAccounting= or IPAccounting= is turned on for a unit a new + structured log message is generated each time the unit is stopped, + containing information about the consumed resources of this + invocation. + + * A new setting KeyringMode= has been added to unit files, which may be + used to control how the kernel keyring is set up for executed + processes. + + * "systemctl poweroff", "systemctl reboot", "systemctl halt", + "systemctl kexec" and "systemctl exit" are now always asynchronous in + behaviour (that is: these commands return immediately after the + operation was enqueued instead of waiting for the operation to + complete). Previously, "systemctl poweroff" and "systemctl reboot" + were asynchronous on systems using systemd-logind (i.e. almost + always, and like they were on sysvinit), and the other three commands + were unconditionally synchronous. With this release this is cleaned + up, and callers will see the same asynchronous behaviour on all + systems for all five operations. + + * systemd-logind gained new Halt() and CanHalt() bus calls for halting + the system. + + * .timer units now accept calendar specifications in other timezones + than UTC or the local timezone. + + * The tmpfiles snippet var.conf has been changed to create + /var/log/btmp with access mode 0660 instead of 0600. It was owned by + the "utmp" group already, and it appears to be generally understood + that members of "utmp" can modify/flush the utmp/wtmp/lastlog/btmp + databases. Previously this was implemented correctly for all these + databases excepts btmp, which has been opened up like this now + too. Note that while the other databases are world-readable + (i.e. 0644), btmp is not and remains more restrictive. + + * The systemd-resolve tool gained a new --reset-server-features + switch. When invoked like this systemd-resolved will forget + everything it learnt about the features supported by the configured + upstream DNS servers, and restarts the feature probing logic on the + next resolver look-up for them at the highest feature level + again. + + * The status dump systemd-resolved sends to the logs upon receiving + SIGUSR1 now also includes information about all DNS servers it is + configured to use, and the features levels it probed for them. + + Contributions from: Abdó Roig-Maranges, Alan Jenkins, Alexander + Kuleshov, Andreas Rammhold, Andrew Jeddeloh, Andrew Soutar, Ansgar + Burchardt, Beniamino Galvani, Benjamin Berg, Benjamin Robin, Charles + Huber, Christian Hesse, Daniel Berrange, Daniel Kahn Gillmor, Daniel + Mack, Daniel Rusek, Daniel Șerbănescu, Davide Cavalca, Dimitri John + Ledkov, Diogo Pereira, Djalal Harouni, Dmitriy Geels, Dmitry Torokhov, + ettavolt, Evgeny Vereshchagin, Fabio Kung, Felipe Sateler, Franck Bui, + Hans de Goede, Harald Hoyer, Insun Pyo, Ivan Kurnosov, Ivan Shapovalov, + Jakub Wilk, Jan Synacek, Jason Gunthorpe, Jeremy Bicha, Jérémy Rosen, + John Lin, jonasBoss, Jonathan Lebon, Jonathan Teh, Jon Ringle, Jörg + Thalheim, Jouke Witteveen, juga0, Justin Capella, Justin Michaud, + Kai-Heng Feng, Lennart Poettering, Lion Yang, Luca Bruno, Lucas + Werkmeister, Lukáš Nykrýn, Marcel Hollerbach, Marcus Lundblad, Martin + Pitt, Michael Biebl, Michael Grzeschik, Michal Sekletar, Mike Gilbert, + Neil Brown, Nicolas Iooss, Patrik Flykt, pEJipE, Piotr Drąg, Russell + Stuart, S. Fan, Shengyao Xue, Stefan Pietsch, Susant Sahani, Tejun Heo, + Thomas Miller, Thomas Sailer, Tobias Hunger, Tomasz Pala, Tom + Gundersen, Tommi Rantala, Topi Miettinen, Torstein Husebø, userwithuid, + Vasilis Liaskovitis, Vito Caputo, WaLyong Cho, William Douglas, Xiang + Fan, Yu Watanabe, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2017-10-06 + +CHANGES WITH 234: + + * Meson is now supported as build system in addition to Automake. It is + our plan to remove Automake in one of our next releases, so that + Meson becomes our exclusive build system. Hence, please start using + the Meson build system in your downstream packaging. There's plenty + of documentation around how to use Meson, the extremely brief + summary: + + ./autogen.sh && ./configure && make && sudo make install + + becomes: + + meson build && ninja -C build && sudo ninja -C build install + + * Unit files gained support for a new JobRunningTimeoutUSec= setting, + which permits configuring a timeout on the time a job is + running. This is particularly useful for setting timeouts on jobs for + .device units. + + * Unit files gained two new options ConditionUser= and ConditionGroup= + for conditionalizing units based on the identity of the user/group + running a systemd user instance. + + * systemd-networkd now understands a new FlowLabel= setting in the + [VXLAN] section of .network files, as well as a Priority= in + [Bridge], GVRP= + MVRP= + LooseBinding= + ReorderHeader= in [VLAN] + and GatewayOnlink= + IPv6Preference= + Protocol= in [Route]. It also + gained support for configuration of GENEVE links, and IPv6 address + labels. The [Network] section gained the new IPv6ProxyNDP= setting. + + * .link files now understand a new Port= setting. + + * systemd-networkd's DHCP support gained support for DHCP option 119 + (domain search list). + + * systemd-networkd gained support for serving IPv6 address ranges using + the Router Advertisement protocol. The new .network configuration + section [IPv6Prefix] may be used to configure the ranges to + serve. This is implemented based on a new, minimal, native server + implementation of RA. + + * journalctl's --output= switch gained support for a new parameter + "short-iso-precise" for a mode where timestamps are shown as precise + ISO date values. + + * systemd-udevd's "net_id" builtin may now generate stable network + interface names from IBM PowerVM VIO devices as well as ACPI platform + devices. + + * MulticastDNS support in systemd-resolved may now be explicitly + enabled/disabled using the new MulticastDNS= configuration file + option. + + * systemd-resolved may now optionally use libidn2 instead of the libidn + for processing internationalized domain names. Support for libidn2 + should be considered experimental and should not be enabled by + default yet. + + * "machinectl pull-tar" and related call may now do verification of + downloaded images using SUSE-style .sha256 checksum files in addition + to the already existing support for validating using Ubuntu-style + SHA256SUMS files. + + * sd-bus gained support for a new sd_bus_message_appendv() call which + is va_list equivalent of sd_bus_message_append(). + + * sd-boot gained support for validating images using SHIM/MOK. + + * The SMACK code learnt support for "onlycap". + + * systemd-mount --umount is now much smarter in figuring out how to + properly unmount a device given its mount or device path. + + * The code to call libnss_dns as a fallback from libnss_resolve when + the communication with systemd-resolved fails was removed. This + fallback was redundant and interfered with the [!UNAVAIL=return] + suffix. See nss-resolve(8) for the recommended configuration. + + * systemd-logind may now be restarted without losing state. It stores + the file descriptors for devices it manages in the system manager + using the FDSTORE= mechanism. Please note that further changes in + other components may be required to make use of this (for example + Xorg has code to listen for stops of systemd-logind and terminate + itself when logind is stopped or restarted, in order to avoid using + stale file descriptors for graphical devices, which is now + counterproductive and must be reverted in order for restarts of + systemd-logind to be safe. See + https://cgit.freedesktop.org/xorg/xserver/commit/?id=dc48bd653c7e101.) + + * All kernel-install plugins are called with the environment variable + KERNEL_INSTALL_MACHINE_ID which is set to the machine ID given by + /etc/machine-id. If the machine ID could not be determined, + $KERNEL_INSTALL_MACHINE_ID will be empty. Plugins should not put + anything in the entry directory (passed as the second argument) if + $KERNEL_INSTALL_MACHINE_ID is empty. For backwards compatibility, a + temporary directory is passed as the entry directory and removed + after all the plugins exit. + + Contributions from: Adrian Heine né Lang, Aggelos Avgerinos, Alexander + Kurtz, Alexandros Frantzis, Alexey Brodkin, Alex Lu, Amir Pakdel, Amir + Yalon, Anchor Cat, Anthony Parsons, Bastien Nocera, Benjamin Gilbert, + Benjamin Robin, Boucman, Charles Plessy, Chris Chiu, Chris Lamb, + Christian Brauner, Christian Hesse, Colin Walters, Daniel Drake, + Danielle Church, Daniel Molkentin, Daniel Rusek, Daniel Wang, Davide + Cavalca, David Herrmann, David Michael, Dax Kelson, Dimitri John + Ledkov, Djalal Harouni, Dušan Kazik, Elias Probst, Evgeny Vereshchagin, + Federico Di Pierro, Felipe Sateler, Felix Zhang, Franck Bui, Gary + Tierney, George McCollister, Giedrius Statkevičius, Hans de Goede, + hecke, Hendrik Westerberg, Hristo Venev, Ian Wienand, Insun Pyo, Ivan + Shapovalov, James Cowgill, James Hemsing, Janne Heß, Jan Synacek, Jason + Reeder, João Paulo Rechi Vita, John Paul Adrian Glaubitz, Jörg + Thalheim, Josef Andersson, Josef Gajdusek, Julian Mehne, Kai Krakow, + Krzysztof Jackiewicz, Lars Karlitski, Lennart Poettering, Lluís Gili, + Lucas Werkmeister, Lukáš Nykrýn, Łukasz Stelmach, Mantas Mikulėnas, + Marcin Bachry, Marcus Cooper, Mark Stosberg, Martin Pitt, Matija Skala, + Matt Clarkson, Matthew Garrett, Matthias Greiner, Matthijs van Duin, + Max Resch, Michael Biebl, Michal Koutný, Michal Sekletar, Michal + Soltys, Michal Suchanek, Mike Gilbert, Nate Clark, Nathaniel R. Lewis, + Neil Brown, Nikolai Kondrashov, Pascal S. de Kloe, Pat Riehecky, Patrik + Flykt, Paul Kocialkowski, Peter Hutterer, Philip Withnall, Piotr + Szydełko, Rafael Fontenelle, Ray Strode, Richard Maw, Roelf Wichertjes, + Ronny Chevalier, Sarang S. Dalal, Sjoerd Simons, slodki, Stefan + Schweter, Susant Sahani, Ted Wood, Thomas Blume, Thomas Haller, Thomas + H. P. Andersen, Timothée Ravier, Tobias Jungel, Tobias Stoeckmann, Tom + Gundersen, Tom Yan, Torstein Husebø, Umut Tezduyar Lindskog, + userwithuid, Vito Caputo, Waldemar Brodkorb, WaLyong Cho, Yu, Li-Yu, + Yusuke Nojima, Yu Watanabe, Zbigniew Jędrzejewski-Szmek, Дамјан + Георгиевски + + — Berlin, 2017-07-12 + +CHANGES WITH 233: + + * The "hybrid" control group mode has been modified to improve + compatibility with "legacy" cgroups-v1 setups. Specifically, the + "hybrid" setup of /sys/fs/cgroup is now pretty much identical to + "legacy" (including /sys/fs/cgroup/systemd as "name=systemd" named + cgroups-v1 hierarchy), the only externally visible change being that + the cgroups-v2 hierarchy is also mounted, to + /sys/fs/cgroup/unified. This should provide a large degree of + compatibility with "legacy" cgroups-v1, while taking benefit of the + better management capabilities of cgroups-v2. + + * The default control group setup mode may be selected both a boot-time + via a set of kernel command line parameters (specifically: + systemd.unified_cgroup_hierarchy= and + systemd.legacy_systemd_cgroup_controller=), as well as a compile-time + default selected on the configure command line + (--with-default-hierarchy=). The upstream default is "hybrid" + (i.e. the cgroups-v1 + cgroups-v2 mixture discussed above) now, but + this will change in a future systemd version to be "unified" (pure + cgroups-v2 mode). The third option for the compile time option is + "legacy", to enter pure cgroups-v1 mode. We recommend downstream + distributions to default to "hybrid" mode for release distributions, + starting with v233. We recommend "unified" for development + distributions (specifically: distributions such as Fedora's rawhide) + as that's where things are headed in the long run. Use "legacy" for + greatest stability and compatibility only. + + * Note one current limitation of "unified" and "hybrid" control group + setup modes: the kernel currently does not permit the systemd --user + instance (i.e. unprivileged code) to migrate processes between two + disconnected cgroup subtrees, even if both are managed and owned by + the user. This effectively means "systemd-run --user --scope" doesn't + work when invoked from outside of any "systemd --user" service or + scope. Specifically, it is not supported from session scopes. We are + working on fixing this in a future systemd version. (See #3388 for + further details about this.) + + * DBus policy files are now installed into /usr rather than /etc. Make + sure your system has dbus >= 1.9.18 running before upgrading to this + version, or override the install path with --with-dbuspolicydir= . + + * All python scripts shipped with systemd (specifically: the various + tests written in Python) now require Python 3. + + * systemd unit tests can now run standalone (without the source or + build directories), and can be installed into /usr/lib/systemd/tests/ + with 'make install-tests'. + + * Note that from this version on, CONFIG_CRYPTO_USER_API_HASH, + CONFIG_CRYPTO_HMAC and CONFIG_CRYPTO_SHA256 need to be enabled in the + kernel. + + * Support for the %c, %r, %R specifiers in unit files has been + removed. Specifiers are not supposed to be dependent on configuration + in the unit file itself (so that they resolve the same regardless + where used in the unit files), but these specifiers were influenced + by the Slice= option. + + * The shell invoked by debug-shell.service now defaults to /bin/sh in + all cases. If distributions want to use a different shell for this + purpose (for example Fedora's /sbin/sushell) they need to specify + this explicitly at configure time using --with-debug-shell=. + + * The confirmation spawn prompt has been reworked to offer the + following choices: + + (c)ontinue, proceed without asking anymore + (D)ump, show the state of the unit + (f)ail, don't execute the command and pretend it failed + (h)elp + (i)nfo, show a short summary of the unit + (j)obs, show jobs that are in progress + (s)kip, don't execute the command and pretend it succeeded + (y)es, execute the command + + The 'n' choice for the confirmation spawn prompt has been removed, + because its meaning was confusing. + + The prompt may now also be redirected to an alternative console by + specifying the console as parameter to systemd.confirm_spawn=. + + * Services of Type=notify require a READY=1 notification to be sent + during startup. If no such message is sent, the service now fails, + even if the main process exited with a successful exit code. + + * Services that fail to start up correctly now always have their + ExecStopPost= commands executed. Previously, they'd enter "failed" + state directly, without executing these commands. + + * The option MulticastDNS= of network configuration files has acquired + an actual implementation. With MulticastDNS=yes a host can resolve + names of remote hosts and reply to mDNS A and AAAA requests. + + * When units are about to be started an additional check is now done to + ensure that all dependencies of type BindsTo= (when used in + combination with After=) have been started. + + * systemd-analyze gained a new verb "syscall-filter" which shows which + system call groups are defined for the SystemCallFilter= unit file + setting, and which system calls they contain. + + * A new system call filter group "@filesystem" has been added, + consisting of various file system related system calls. Group + "@reboot" has been added, covering reboot, kexec and shutdown related + calls. Finally, group "@swap" has been added covering swap + configuration related calls. + + * A new unit file option RestrictNamespaces= has been added that may be + used to restrict access to the various process namespace types the + Linux kernel provides. Specifically, it may be used to take away the + right for a service unit to create additional file system, network, + user, and other namespaces. This sandboxing option is particularly + relevant due to the high amount of recently discovered namespacing + related vulnerabilities in the kernel. + + * systemd-udev's .link files gained support for a new AutoNegotiation= + setting for configuring Ethernet auto-negotiation. + + * systemd-networkd's .network files gained support for a new + ListenPort= setting in the [DHCP] section to explicitly configure the + UDP client port the DHCP client shall listen on. + + * .network files gained a new Unmanaged= boolean setting for explicitly + excluding one or more interfaces from management by systemd-networkd. + + * The systemd-networkd ProxyARP= option has been renamed to + IPV4ProxyARP=. Similarly, VXLAN-specific option ARPProxy= has been + renamed to ReduceARPProxy=. The old names continue to be available + for compatibility. + + * systemd-networkd gained support for configuring IPv6 Proxy NDP + addresses via the new IPv6ProxyNDPAddress= .network file setting. + + * systemd-networkd's bonding device support gained support for two new + configuration options ActiveSlave= and PrimarySlave=. + + * The various options in the [Match] section of .network files gained + support for negative matching. + + * New systemd-specific mount options are now understood in /etc/fstab: + + x-systemd.mount-timeout= may be used to configure the maximum + permitted runtime of the mount command. + + x-systemd.device-bound may be set to bind a mount point to its + backing device unit, in order to automatically remove a mount point + if its backing device is unplugged. This option may also be + configured through the new SYSTEMD_MOUNT_DEVICE_BOUND udev property + on the block device, which is now automatically set for all CDROM + drives, so that mounted CDs are automatically unmounted when they are + removed from the drive. + + x-systemd.after= and x-systemd.before= may be used to explicitly + order a mount after or before another unit or mount point. + + * Enqueued start jobs for device units are now automatically garbage + collected if there are no jobs waiting for them anymore. + + * systemctl list-jobs gained two new switches: with --after, for every + queued job the jobs it's waiting for are shown; with --before the + jobs which it's blocking are shown. + + * systemd-nspawn gained support for ephemeral boots from disk images + (or in other words: --ephemeral and --image= may now be + combined). Moreover, ephemeral boots are now supported for normal + directories, even if the backing file system is not btrfs. Of course, + if the file system does not support file system snapshots or + reflinks, the initial copy operation will be relatively expensive, but + this should still be suitable for many use cases. + + * Calendar time specifications in .timer units now support + specifications relative to the end of a month by using "~" instead of + "-" as separator between month and day. For example, "*-02~03" means + "the third last day in February". In addition a new syntax for + repeated events has been added using the "/" character. For example, + "9..17/2:00" means "every two hours from 9am to 5pm". + + * systemd-socket-proxyd gained a new parameter --connections-max= for + configuring the maximum number of concurrent connections. + + * sd-id128 gained a new API for generating unique IDs for the host in a + way that does not leak the machine ID. Specifically, + sd_id128_get_machine_app_specific() derives an ID based on the + machine ID a in well-defined, non-reversible, stable way. This is + useful whenever an identifier for the host is needed but where the + identifier shall not be useful to identify the system beyond the + scope of the application itself. (Internally this uses HMAC-SHA256 as + keyed hash function using the machine ID as input.) + + * NotifyAccess= gained a new supported value "exec". When set + notifications are accepted from all processes systemd itself invoked, + including all control processes. + + * .nspawn files gained support for defining overlay mounts using the + Overlay= and OverlayReadOnly= options. Previously this functionality + was only available on the systemd-nspawn command line. + + * systemd-nspawn's --bind= and --overlay= options gained support for + bind/overlay mounts whose source lies within the container tree by + prefixing the source path with "+". + + * systemd-nspawn's --bind= and --overlay= options gained support for + automatically allocating a temporary source directory in /var/tmp + that is removed when the container dies. Specifically, if the source + directory is specified as empty string this mechanism is selected. An + example usage is --overlay=+/var::/var, which creates an overlay + mount based on the original /var contained in the image, overlayed + with a temporary directory in the host's /var/tmp. This way changes + to /var are automatically flushed when the container shuts down. + + * systemd-nspawn --image= option does now permit raw file system block + devices (in addition to images containing partition tables, as + before). + + * The disk image dissection logic in systemd-nspawn gained support for + automatically setting up LUKS encrypted as well as Verity protected + partitions. When a container is booted from an encrypted image the + passphrase is queried at start-up time. When a container with Verity + data is started, the root hash is search in a ".roothash" file + accompanying the disk image (alternatively, pass the root hash via + the new --root-hash= command line option). + + * A new tool /usr/lib/systemd/systemd-dissect has been added that may + be used to dissect disk images the same way as systemd-nspawn does + it, following the Bootable Partition Specification. It may even be + used to mount disk images with complex partition setups (including + LUKS and Verity partitions) to a local host directory, in order to + inspect them. This tool is not considered public API (yet), and is + thus not installed into /usr/bin. Please do not rely on its + existence, since it might go away or be changed in later systemd + versions. + + * A new generator "systemd-verity-generator" has been added, similar in + style to "systemd-cryptsetup-generator", permitting automatic setup of + Verity root partitions when systemd boots up. In order to make use of + this your partition setup should follow the Discoverable Partitions + Specification, and the GPT partition ID of the root file system + partition should be identical to the upper 128bit of the Verity root + hash. The GPT partition ID of the Verity partition protecting it + should be the lower 128bit of the Verity root hash. If the partition + image follows this model it is sufficient to specify a single + "roothash=" kernel command line argument to both configure which root + image and verity partition to use as well as the root hash for + it. Note that systemd-nspawn's Verity support follows the same + semantics, meaning that disk images with proper Verity data in place + may be booted in containers with systemd-nspawn as well as on + physical systems via the verity generator. Also note that the "mkosi" + tool available at https://github.com/systemd/mkosi has been updated + to generate Verity protected disk images following this scheme. In + fact, it has been updated to generate disk images that optionally + implement a complete UEFI SecureBoot trust chain, involving a signed + kernel and initrd image that incorporates such a root hash as well as + a Verity-enabled root partition. + + * The hardware database (hwdb) udev supports has been updated to carry + accelerometer quirks. + + * All system services are now run with a fresh kernel keyring set up + for them. The invocation ID is stored by default in it, thus + providing a safe, non-overridable way to determine the invocation + ID of each service. + + * Service unit files gained new BindPaths= and BindReadOnlyPaths= + options for bind mounting arbitrary paths in a service-specific + way. When these options are used, arbitrary host or service files and + directories may be mounted to arbitrary locations in the service's + view. + + * Documentation has been added that lists all of systemd's low-level + environment variables: + + https://github.com/systemd/systemd/blob/master/docs/ENVIRONMENT.md + + * sd-daemon gained a new API sd_is_socket_sockaddr() for determining + whether a specific socket file descriptor matches a specified socket + address. + + * systemd-firstboot has been updated to check for the + systemd.firstboot= kernel command line option. It accepts a boolean + and when set to false the first boot questions are skipped. + + * systemd-fstab-generator has been updated to check for the + systemd.volatile= kernel command line option, which either takes an + optional boolean parameter or the special value "state". If used the + system may be booted in a "volatile" boot mode. Specifically, + "systemd.volatile" is used, the root directory will be mounted as + tmpfs, and only /usr is mounted from the actual root file system. If + "systemd.volatile=state" is used, the root directory will be mounted + as usual, but /var is mounted as tmpfs. This concept provides similar + functionality as systemd-nspawn's --volatile= option, but provides it + on physical boots. Use this option for implementing stateless + systems, or testing systems with all state and/or configuration reset + to the defaults. (Note though that many distributions are not + prepared to boot up without a populated /etc or /var, though.) + + * systemd-gpt-auto-generator gained support for LUKS encrypted root + partitions. Previously it only supported LUKS encrypted partitions + for all other uses, except for the root partition itself. + + * Socket units gained support for listening on AF_VSOCK sockets for + communication in virtualized QEMU environments. + + * The "configure" script gained a new option --with-fallback-hostname= + for specifying the fallback hostname to use if none is configured in + /etc/hostname. For example, by specifying + --with-fallback-hostname=fedora it is possible to default to a + hostname of "fedora" on pristine installations. + + * systemd-cgls gained support for a new --unit= switch for listing only + the control groups of a specific unit. Similar --user-unit= has been + added for listing only the control groups of a specific user unit. + + * systemd-mount gained a new --umount switch for unmounting a mount or + automount point (and all mount/automount points below it). + + * systemd will now refuse full configuration reloads (via systemctl + daemon-reload and related calls) unless at least 16MiB of free space + are available in /run. This is a safety precaution in order to ensure + that generators can safely operate after the reload completed. + + * A new unit file option RootImage= has been added, which has a similar + effect as RootDirectory= but mounts the service's root directory from + a disk image instead of plain directory. This logic reuses the same + image dissection and mount logic that systemd-nspawn already uses, + and hence supports any disk images systemd-nspawn supports, including + those following the Discoverable Partition Specification, as well as + Verity enabled images. This option enables systemd to run system + services directly off disk images acting as resource bundles, + possibly even including full integrity data. + + * A new MountAPIVFS= unit file option has been added, taking a boolean + argument. If enabled /proc, /sys and /dev (collectively called the + "API VFS") will be mounted for the service. This is only relevant if + RootDirectory= or RootImage= is used for the service, as these mounts + are of course in place in the host mount namespace anyway. + + * systemd-nspawn gained support for a new --pivot-root= switch. If + specified the root directory within the container image is pivoted to + the specified mount point, while the original root disk is moved to a + different place. This option enables booting of ostree images + directly with systemd-nspawn. + + * The systemd build scripts will no longer complain if the NTP server + addresses are not changed from the defaults. Google now supports + these NTP servers officially. We still recommend downstreams to + properly register an NTP pool with the NTP pool project though. + + * coredumpctl gained a new "--reverse" option for printing the list + of coredumps in reverse order. + + * coredumpctl will now show additional information about truncated and + inaccessible coredumps, as well as coredumps that are still being + processed. It also gained a new --quiet switch for suppressing + additional informational message in its output. + + * coredumpctl gained support for only showing coredumps newer and/or + older than specific timestamps, using the new --since= and --until= + options, reminiscent of journalctl's options by the same name. + + * The systemd-coredump logic has been improved so that it may be reused + to collect backtraces in non-compiled languages, for example in + scripting languages such as Python. + + * machinectl will now show the UID shift of local containers, if user + namespacing is enabled for them. + + * systemd will now optionally run "environment generator" binaries at + configuration load time. They may be used to add environment + variables to the environment block passed to services invoked. One + user environment generator is shipped by default that sets up + environment variables based on files dropped into /etc/environment.d + and ~/.config/environment.d/. + + * systemd-resolved now includes the new, recently published 2017 DNSSEC + root key (KSK). + + * hostnamed has been updated to report a new chassis type of + "convertible" to cover "foldable" laptops that can both act as a + tablet and as a laptop, such as various Lenovo Yoga devices. + + Contributions from: Adrián López, Alexander Galanin, Alexander + Kochetkov, Alexandros Frantzis, Andrey Ulanov, Antoine Eiche, Baruch + Siach, Bastien Nocera, Benjamin Robin, Björn, Brandon Philips, Cédric + Schieli, Charles (Chas) Williams, Christian Hesse, Daniele Medri, + Daniel Drake, Daniel Rusek, Daniel Wagner, Dan Streetman, Dave Reisner, + David Glasser, David Herrmann, David Michael, Djalal Harouni, Dmitry + Khlebnikov, Dmitry Rozhkov, Dongsu Park, Douglas Christman, Earnestly, + Emil Soleyman, Eric Cook, Evgeny Vereshchagin, Felipe Sateler, Fionn + Cleary, Florian Klink, Francesco Brozzu, Franck Bui, Gabriel Rauter, + Gianluca Boiano, Giedrius Statkevičius, Graeme Lawes, Hans de Goede, + Harald Hoyer, Ian Kelling, Ivan Shapovalov, Jakub Wilk, Janne Heß, Jan + Synacek, Jason Reeder, Jonathan Boulle, Jörg Thalheim, Jouke Witteveen, + Karl Kraus, Kees Cook, Keith Busch, Kieran Colford, kilian-k, Lennart + Poettering, Lubomir Rintel, Lucas Werkmeister, Lukas Rusak, Maarten de + Vries, Maks Naumov, Mantas Mikulėnas, Marc-Andre Lureau, Marcin Bachry, + Mark Stosberg, Martin Ejdestig, Martin Pitt, Mauricio Faria de + Oliveira, micah, Michael Biebl, Michael Shields, Michal Schmidt, Michal + Sekletar, Michel Kraus, Mike Gilbert, Mikko Ylinen, Mirza Krak, + Namhyung Kim, nikolaof, peoronoob, Peter Hutterer, Peter Körner, Philip + Withnall, Piotr Drąg, Ray Strode, Reverend Homer, Rike-Benjamin + Schuppner, Robert Kreuzer, Ronny Chevalier, Ruslan Bilovol, sammynx, + Sergey Ptashnick, Sergiusz Urbaniak, Stefan Berger, Stefan Hajnoczi, + Stefan Schweter, Stuart McLaren, Susant Sahani, Sylvain Plantefève, + Taylor Smock, Tejun Heo, Thomas Blume, Thomas H. P. Andersen, Tibor + Nagy, Tobias Stoeckmann, Tom Gundersen, Torstein Husebø, Viktar + Vaŭčkievič, Viktor Mihajlovski, Vitaly Sulimov, Waldemar Brodkorb, + Walter Garcia-Fontes, Wim de With, Yassine Imounachen, Yi EungJun, + YunQiang Su, Yu Watanabe, Zbigniew Jędrzejewski-Szmek, Александр + Тихонов + + — Berlin, 2017-03-01 + +CHANGES WITH 232: + + * udev now runs with MemoryDenyWriteExecute=, RestrictRealtime= and + RestrictAddressFamilies= enabled. These sandboxing options should + generally be compatible with the various external udev call-out + binaries we are aware of, however there may be exceptions, in + particular when exotic languages for these call-outs are used. In + this case, consider turning off these settings locally. + + * The new RemoveIPC= option can be used to remove IPC objects owned by + the user or group of a service when that service exits. + + * The new ProtectKernelModules= option can be used to disable explicit + load and unload operations of kernel modules by a service. In + addition access to /usr/lib/modules is removed if this option is set. + + * ProtectSystem= option gained a new value "strict", which causes the + whole file system tree with the exception of /dev, /proc, and /sys, + to be remounted read-only for a service. + + * The new ProtectKernelTunables= option can be used to disable + modification of configuration files in /sys and /proc by a service. + Various directories and files are remounted read-only, so access is + restricted even if the file permissions would allow it. + + * The new ProtectControlGroups= option can be used to disable write + access by a service to /sys/fs/cgroup. + + * Various systemd services have been hardened with + ProtectKernelTunables=yes, ProtectControlGroups=yes, + RestrictAddressFamilies=. + + * Support for dynamically creating users for the lifetime of a service + has been added. If DynamicUser=yes is specified, user and group IDs + will be allocated from the range 61184..65519 for the lifetime of the + service. They can be resolved using the new nss-systemd.so NSS + module. The module must be enabled in /etc/nsswitch.conf. Services + started in this way have PrivateTmp= and RemoveIPC= enabled, so that + any resources allocated by the service will be cleaned up when the + service exits. They also have ProtectHome=read-only and + ProtectSystem=strict enabled, so they are not able to make any + permanent modifications to the system. + + * The nss-systemd module also always resolves root and nobody, making + it possible to have no /etc/passwd or /etc/group files in minimal + container or chroot environments. + + * Services may be started with their own user namespace using the new + boolean PrivateUsers= option. Only root, nobody, and the uid/gid + under which the service is running are mapped. All other users are + mapped to nobody. + + * Support for the cgroup namespace has been added to systemd-nspawn. If + supported by kernel, the container system started by systemd-nspawn + will have its own view of the cgroup hierarchy. This new behaviour + can be disabled using $SYSTEMD_NSPAWN_USE_CGNS environment variable. + + * The new MemorySwapMax= option can be used to limit the maximum swap + usage under the unified cgroup hierarchy. + + * Support for the CPU controller in the unified cgroup hierarchy has + been added, via the CPUWeight=, CPUStartupWeight=, CPUAccounting= + options. This controller requires out-of-tree patches for the kernel + and the support is provisional. + + * Mount and automount units may now be created transiently + (i.e. dynamically at runtime via the bus API, instead of requiring + unit files in the file system). + + * systemd-mount is a new tool which may mount file systems – much like + mount(8), optionally pulling in additional dependencies through + transient .mount and .automount units. For example, this tool + automatically runs fsck on a backing block device before mounting, + and allows the automount logic to be used dynamically from the + command line for establishing mount points. This tool is particularly + useful when dealing with removable media, as it will ensure fsck is + run – if necessary – before the first access and that the file system + is quickly unmounted after each access by utilizing the automount + logic. This maximizes the chance that the file system on the + removable media stays in a clean state, and if it isn't in a clean + state is fixed automatically. + + * LazyUnmount=yes option for mount units has been added to expose the + umount --lazy option. Similarly, ForceUnmount=yes exposes the --force + option. + + * /efi will be used as the mount point of the EFI boot partition, if + the directory is present, and the mount point was not configured + through other means (e.g. fstab). If /efi directory does not exist, + /boot will be used as before. This makes it easier to automatically + mount the EFI partition on systems where /boot is used for something + else. + + * When operating on GPT disk images for containers, systemd-nspawn will + now mount the ESP to /boot or /efi according to the same rules as PID + 1 running on a host. This allows tools like "bootctl" to operate + correctly within such containers, in order to make container images + bootable on physical systems. + + * disk/by-id and disk/by-path symlinks are now created for NVMe drives. + + * Two new user session targets have been added to support running + graphical sessions under the systemd --user instance: + graphical-session.target and graphical-session-pre.target. See + systemd.special(7) for a description of how those targets should be + used. + + * The vconsole initialization code has been significantly reworked to + use KD_FONT_OP_GET/SET ioctls instead of KD_FONT_OP_COPY and better + support unicode keymaps. Font and keymap configuration will now be + copied to all allocated virtual consoles. + + * FreeBSD's bhyve virtualization is now detected. + + * Information recorded in the journal for core dumps now includes the + contents of /proc/mountinfo and the command line of the process at + the top of the process hierarchy (which is usually the init process + of the container). + + * systemd-journal-gatewayd learned the --directory= option to serve + files from the specified location. + + * journalctl --root=… can be used to peruse the journal in the + /var/log/ directories inside of a container tree. This is similar to + the existing --machine= option, but does not require the container to + be active. + + * The hardware database has been extended to support + ID_INPUT_TRACKBALL, used in addition to ID_INPUT_MOUSE to identify + trackball devices. + + MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL hwdb property has been added to + specify the click rate for mice which include a horizontal wheel with + a click rate that is different than the one for the vertical wheel. + + * systemd-run gained a new --wait option that makes service execution + synchronous. (Specifically, the command will not return until the + specified service binary exited.) + + * systemctl gained a new --wait option that causes the start command to + wait until the units being started have terminated again. + + * A new journal output mode "short-full" has been added which displays + timestamps with abbreviated English day names and adds a timezone + suffix. Those timestamps include more information than the default + "short" output mode, and can be passed directly to journalctl's + --since= and --until= options. + + * /etc/resolv.conf will be bind-mounted into containers started by + systemd-nspawn, if possible, so any changes to resolv.conf contents + are automatically propagated to the container. + + * The number of instances for socket-activated services originating + from a single IP address can be limited with + MaxConnectionsPerSource=, extending the existing setting of + MaxConnections=. + + * systemd-networkd gained support for vcan ("Virtual CAN") interface + configuration. + + * .netdev and .network configuration can now be extended through + drop-ins. + + * UDP Segmentation Offload, TCP Segmentation Offload, Generic + Segmentation Offload, Generic Receive Offload, Large Receive Offload + can be enabled and disabled using the new UDPSegmentationOffload=, + TCPSegmentationOffload=, GenericSegmentationOffload=, + GenericReceiveOffload=, LargeReceiveOffload= options in the + [Link] section of .link files. + + * The Spanning Tree Protocol, Priority, Aging Time, and the Default + Port VLAN ID can be configured for bridge devices using the new STP=, + Priority=, AgeingTimeSec=, and DefaultPVID= settings in the [Bridge] + section of .netdev files. + + * The route table to which routes received over DHCP or RA should be + added can be configured with the new RouteTable= option in the [DHCP] + and [IPv6AcceptRA] sections of .network files. + + * The Address Resolution Protocol can be disabled on links managed by + systemd-networkd using the ARP=no setting in the [Link] section of + .network files. + + * New environment variables $SERVICE_RESULT, $EXIT_CODE and + $EXIT_STATUS are set for ExecStop= and ExecStopPost= commands, and + encode information about the result and exit codes of the current + service runtime cycle. + + * systemd-sysctl will now configure kernel parameters in the order + they occur in the configuration files. This matches what sysctl + has been traditionally doing. + + * kernel-install "plugins" that are executed to perform various + tasks after a new kernel is added and before an old one is removed + can now return a special value to terminate the procedure and + prevent any later plugins from running. + + * Journald's SplitMode=login setting has been deprecated. It has been + removed from documentation, and its use is discouraged. In a future + release it will be completely removed, and made equivalent to current + default of SplitMode=uid. + + * Storage=both option setting in /etc/systemd/coredump.conf has been + removed. With fast LZ4 compression storing the core dump twice is not + useful. + + * The --share-system systemd-nspawn option has been replaced with an + (undocumented) variable $SYSTEMD_NSPAWN_SHARE_SYSTEM, but the use of + this functionality is discouraged. In addition the variables + $SYSTEMD_NSPAWN_SHARE_NS_IPC, $SYSTEMD_NSPAWN_SHARE_NS_PID, + $SYSTEMD_NSPAWN_SHARE_NS_UTS may be used to control the unsharing of + individual namespaces. + + * "machinectl list" now shows the IP address of running containers in + the output, as well as OS release information. + + * "loginctl list" now shows the TTY of each session in the output. + + * sd-bus gained new API calls sd_bus_track_set_recursive(), + sd_bus_track_get_recursive(), sd_bus_track_count_name(), + sd_bus_track_count_sender(). They permit usage of sd_bus_track peer + tracking objects in a "recursive" mode, where a single client can be + counted multiple times, if it takes multiple references. + + * sd-bus gained new API calls sd_bus_set_exit_on_disconnect() and + sd_bus_get_exit_on_disconnect(). They may be used to make a + process using sd-bus automatically exit if the bus connection is + severed. + + * Bus clients of the service manager may now "pin" loaded units into + memory, by taking an explicit reference on them. This is useful to + ensure the client can retrieve runtime data about the service even + after the service completed execution. Taking such a reference is + available only for privileged clients and should be helpful to watch + running services in a race-free manner, and in particular collect + information about exit statuses and results. + + * The nss-resolve module has been changed to strictly return UNAVAIL + when communication via D-Bus with resolved failed, and NOTFOUND when + a lookup completed but was negative. This means it is now possible to + neatly configure fallbacks using nsswitch.conf result checking + expressions. Taking benefit of this, the new recommended + configuration line for the "hosts" entry in /etc/nsswitch.conf is: + + hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname + + * A new setting CtrlAltDelBurstAction= has been added to + /etc/systemd/system.conf which may be used to configure the precise + behaviour if the user on the console presses Ctrl-Alt-Del more often + than 7 times in 2s. Previously this would unconditionally result in + an expedited, immediate reboot. With this new setting the precise + operation may be configured in more detail, and also turned off + entirely. + + * In .netdev files two new settings RemoteChecksumTx= and + RemoteChecksumRx= are now understood that permit configuring the + remote checksumming logic for VXLAN networks. + + * The service manager learnt a new "invocation ID" concept for invoked + services. Each runtime cycle of a service will get a new invocation + ID (a 128bit random UUID) assigned that identifies the current + run of the service uniquely and globally. A new invocation ID + is generated each time a service starts up. The journal will store + the invocation ID of a service along with any logged messages, thus + making the invocation ID useful for matching the online runtime of a + service with the offline log data it generated in a safe way without + relying on synchronized timestamps. In many ways this new service + invocation ID concept is similar to the kernel's boot ID concept that + uniquely and globally identifies the runtime of each boot. The + invocation ID of a service is passed to the service itself via an + environment variable ($INVOCATION_ID). A new bus call + GetUnitByInvocationID() has been added that is similar to GetUnit() + but instead of retrieving the bus path for a unit by its name + retrieves it by its invocation ID. The returned path is valid only as + long as the passed invocation ID is current. + + * systemd-resolved gained a new "DNSStubListener" setting in + resolved.conf. It either takes a boolean value or the special values + "udp" and "tcp", and configures whether to enable the stub DNS + listener on 127.0.0.53:53. + + * IP addresses configured via networkd may now carry additional + configuration settings supported by the kernel. New options include: + HomeAddress=, DuplicateAddressDetection=, ManageTemporaryAddress=, + PrefixRoute=, AutoJoin=. + + * The PAM configuration fragment file for "user@.service" shipped with + systemd (i.e. the --user instance of systemd) has been stripped to + the minimum necessary to make the system boot. Previously, it + contained Fedora-specific stanzas that did not apply to other + distributions. It is expected that downstream distributions add + additional configuration lines, matching their needs to this file, + using it only as rough template of what systemd itself needs. Note + that this reduced fragment does not even include an invocation of + pam_limits which most distributions probably want to add, even though + systemd itself does not need it. (There's also the new build time + option --with-pamconfdir=no to disable installation of the PAM + fragment entirely.) + + * If PrivateDevices=yes is set for a service the CAP_SYS_RAWIO + capability is now also dropped from its set (in addition to + CAP_SYS_MKNOD as before). + + * In service unit files it is now possible to connect a specific named + file descriptor with stdin/stdout/stdout of an executed service. The + name may be specified in matching .socket units using the + FileDescriptorName= setting. + + * A number of journal settings may now be configured on the kernel + command line. Specifically, the following options are now understood: + systemd.journald.max_level_console=, + systemd.journald.max_level_store=, + systemd.journald.max_level_syslog=, systemd.journald.max_level_kmsg=, + systemd.journald.max_level_wall=. + + * "systemctl is-enabled --full" will now show by which symlinks a unit + file is enabled in the unit dependency tree. + + * Support for VeraCrypt encrypted partitions has been added to the + "cryptsetup" logic and /etc/crypttab. + + * systemd-detect-virt gained support for a new --private-users switch + that checks whether the invoking processes are running inside a user + namespace. Similar, a new special value "private-users" for the + existing ConditionVirtualization= setting has been added, permitting + skipping of specific units in user namespace environments. + + Contributions from: Alban Crequy, Alexander Kuleshov, Alfie John, + Andreas Henriksson, Andrew Jeddeloh, Balázs Úr, Bart Rulon, Benjamin + Richter, Ben Gamari, Ben Harris, Brian J. Murrell, Christian Brauner, + Christian Rebischke, Clinton Roy, Colin Walters, Cristian Rodríguez, + Daniel Hahler, Daniel Mack, Daniel Maixner, Daniel Rusek, Dan Dedrick, + Davide Cavalca, David Herrmann, David Michael, Dennis Wassenberg, + Djalal Harouni, Dongsu Park, Douglas Christman, Elias Probst, Eric + Cook, Erik Karlsson, Evgeny Vereshchagin, Felipe Sateler, Felix Zhang, + Franck Bui, George Hilliard, Giuseppe Scrivano, HATAYAMA Daisuke, + Heikki Kemppainen, Hendrik Brueckner, hi117, Ismo Puustinen, Ivan + Shapovalov, Jakub Filak, Jakub Wilk, Jan Synacek, Jason Kölker, + Jean-Sébastien Bour, Jiří Pírko, Jonathan Boulle, Jorge Niedbalski, + Keith Busch, kristbaum, Kyle Russell, Lans Zhang, Lennart Poettering, + Leonardo Brondani Schenkel, Lucas Werkmeister, Luca Bruno, Lukáš + Nykrýn, Maciek Borzecki, Mantas Mikulėnas, Marc-Antoine Perennou, + Marcel Holtmann, Marcos Mello, Martin Ejdestig, Martin Pitt, Matej + Habrnal, Maxime de Roucy, Michael Biebl, Michael Chapman, Michael Hoy, + Michael Olbrich, Michael Pope, Michal Sekletar, Michal Soltys, Mike + Gilbert, Nick Owens, Patrik Flykt, Paweł Szewczyk, Peter Hutterer, + Piotr Drąg, Reid Price, Richard W.M. Jones, Roman Stingler, Ronny + Chevalier, Seraphime Kirkovski, Stefan Schweter, Steve Muir, Susant + Sahani, Tejun Heo, Thomas Blume, Thomas H. P. Andersen, Tiago Levit, + Tobias Jungel, Tomáš Janoušek, Topi Miettinen, Torstein Husebø, Umut + Tezduyar Lindskog, Vito Caputo, WaLyong Cho, Wilhelm Schuster, Yann + E. MORIN, Yi EungJun, Yuki Inoguchi, Yu Watanabe, Zbigniew + Jędrzejewski-Szmek, Zeal Jagannatha + + — Santa Fe, 2016-11-03 + +CHANGES WITH 231: + + * In service units the various ExecXYZ= settings have been extended + with an additional special character as first argument of the + assigned value: if the character '+' is used the specified command + line it will be run with full privileges, regardless of User=, + Group=, CapabilityBoundingSet= and similar options. The effect is + similar to the existing PermissionsStartOnly= option, but allows + configuration of this concept for each executed command line + independently. + + * Services may now alter the service watchdog timeout at runtime by + sending a WATCHDOG_USEC= message via sd_notify(). + + * MemoryLimit= and related unit settings now optionally take percentage + specifications. The percentage is taken relative to the amount of + physical memory in the system (or in case of containers, the assigned + amount of memory). This allows scaling service resources neatly with + the amount of RAM available on the system. Similarly, systemd-logind's + RuntimeDirectorySize= option now also optionally takes percentage + values. + + * In similar fashion TasksMax= takes percentage values now, too. The + value is taken relative to the configured maximum number of processes + on the system. The per-service task maximum has been changed to 15% + using this functionality. (Effectively this is an increase of 512 → + 4915 for service units, given the kernel's default pid_max setting.) + + * Calendar time specifications in .timer units now understand a ".." + syntax for time ranges. Example: "4..7:10" may now be used for + defining a timer that is triggered at 4:10am, 5:10am, 6:10am and + 7:10am every day. + + * The InaccessableDirectories=, ReadOnlyDirectories= and + ReadWriteDirectories= unit file settings have been renamed to + InaccessablePaths=, ReadOnlyPaths= and ReadWritePaths= and may now be + applied to all kinds of file nodes, and not just directories, with + the exception of symlinks. Specifically these settings may now be + used on block and character device nodes, UNIX sockets and FIFOS as + well as regular files. The old names of these settings remain + available for compatibility. + + * systemd will now log about all service processes it kills forcibly + (using SIGKILL) because they remained after the clean shutdown phase + of the service completed. This should help identifying services that + shut down uncleanly. Moreover if KillUserProcesses= is enabled in + systemd-logind's configuration a similar log message is generated for + processes killed at the end of each session due to this setting. + + * systemd will now set the $JOURNAL_STREAM environment variable for all + services whose stdout/stderr are connected to the Journal (which + effectively means by default: all services). The variable contains + the device and inode number of the file descriptor used for + stdout/stderr. This may be used by invoked programs to detect whether + their stdout/stderr is connected to the Journal, in which case they + can switch over to direct Journal communication, thus being able to + pass extended, structured metadata along with their log messages. As + one example, this is now used by glib's logging primitives. + + * When using systemd's default tmp.mount unit for /tmp, the mount point + will now be established with the "nosuid" and "nodev" options. This + avoids privilege escalation attacks that put traps and exploits into + /tmp. However, this might cause problems if you e. g. put container + images or overlays into /tmp; if you need this, override tmp.mount's + "Options=" with a drop-in, or mount /tmp from /etc/fstab with your + desired options. + + * systemd now supports the "memory" cgroup controller also on + cgroup v2. + + * The systemd-cgtop tool now optionally takes a control group path as + command line argument. If specified, the control group list shown is + limited to subgroups of that group. + + * The SystemCallFilter= unit file setting gained support for + pre-defined, named system call filter sets. For example + SystemCallFilter=@clock is now an effective way to make all clock + changing-related system calls unavailable to a service. A number of + similar pre-defined groups are defined. Writing system call filters + for system services is simplified substantially with this new + concept. Accordingly, all of systemd's own, long-running services now + enable system call filtering based on this, by default. + + * A new service setting MemoryDenyWriteExecute= has been added, taking + a boolean value. If turned on, a service may no longer create memory + mappings that are writable and executable at the same time. This + enhances security for services where this is enabled as it becomes + harder to dynamically write and then execute memory in exploited + service processes. This option has been enabled for all of systemd's + own long-running services. + + * A new RestrictRealtime= service setting has been added, taking a + boolean argument. If set the service's processes may no longer + acquire realtime scheduling. This improves security as realtime + scheduling may otherwise be used to easily freeze the system. + + * systemd-nspawn gained a new switch --notify-ready= taking a boolean + value. This may be used for requesting that the system manager inside + of the container reports start-up completion to nspawn which then + propagates this notification further to the service manager + supervising nspawn itself. A related option NotifyReady= in .nspawn + files has been added too. This functionality allows ordering of the + start-up of multiple containers using the usual systemd ordering + primitives. + + * machinectl gained a new command "stop" that is an alias for + "terminate". + + * systemd-resolved gained support for contacting DNS servers on + link-local IPv6 addresses. + + * If systemd-resolved receives the SIGUSR2 signal it will now flush all + its caches. A method call for requesting the same operation has been + added to the bus API too, and is made available via "systemd-resolve + --flush-caches". + + * systemd-resolve gained a new --status switch. If passed a brief + summary of the used DNS configuration with per-interface information + is shown. + + * resolved.conf gained a new Cache= boolean option, defaulting to + on. If turned off local DNS caching is disabled. This comes with a + performance penalty in particular when DNSSEC is enabled. Note that + resolved disables its internal caching implicitly anyway, when the + configured DNS server is on a host-local IP address such as ::1 or + 127.0.0.1, thus automatically avoiding double local caching. + + * systemd-resolved now listens on the local IP address 127.0.0.53:53 + for DNS requests. This improves compatibility with local programs + that do not use the libc NSS or systemd-resolved's bus APIs for name + resolution. This minimal DNS service is only available to local + programs and does not implement the full DNS protocol, but enough to + cover local DNS clients. A new, static resolv.conf file, listing just + this DNS server is now shipped in /usr/lib/systemd/resolv.conf. It is + now recommended to make /etc/resolv.conf a symlink to this file in + order to route all DNS lookups to systemd-resolved, regardless if + done via NSS, the bus API or raw DNS packets. Note that this local + DNS service is not as fully featured as the libc NSS or + systemd-resolved's bus APIs. For example, as unicast DNS cannot be + used to deliver link-local address information (as this implies + sending a local interface index along), LLMNR/mDNS support via this + interface is severely restricted. It is thus strongly recommended for + all applications to use the libc NSS API or native systemd-resolved + bus API instead. + + * systemd-networkd's bridge support learned a new setting + VLANFiltering= for controlling VLAN filtering. Moreover a new section + in .network files has been added for configuring VLAN bridging in + more detail: VLAN=, EgressUntagged=, PVID= in [BridgeVLAN]. + + * systemd-networkd's IPv6 Router Advertisement code now makes use of + the DNSSL and RDNSS options. This means IPv6 DNS configuration may + now be acquired without relying on DHCPv6. Two new options + UseDomains= and UseDNS= have been added to configure this behaviour. + + * systemd-networkd's IPv6AcceptRouterAdvertisements= option has been + renamed IPv6AcceptRA=, without altering its behaviour. The old + setting name remains available for compatibility reasons. + + * The systemd-networkd VTI/VTI6 tunneling support gained new options + Key=, InputKey= and OutputKey=. + + * systemd-networkd gained support for VRF ("Virtual Routing Function") + interface configuration. + + * "systemctl edit" may now be used to create new unit files by + specifying the --force switch. + + * sd-event gained a new function sd_event_get_iteration() for + requesting the current iteration counter of the event loop. It starts + at zero and is increased by one with each event loop iteration. + + * A new rpm macro %systemd_ordering is provided by the macros.systemd + file. It can be used in lieu of %systemd_requires in packages which + don't use any systemd functionality and are intended to be installed + in minimal containers without systemd present. This macro provides + ordering dependencies to ensure that if the package is installed in + the same rpm transaction as systemd, systemd will be installed before + the scriptlets for the package are executed, allowing unit presets + to be handled. + + New macros %_systemdgeneratordir and %_systemdusergeneratordir have + been added to simplify packaging of generators. + + * The os-release file gained VERSION_CODENAME field for the + distribution nickname (e.g. VERSION_CODENAME=woody). + + * New udev property UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG=1 + can be set to disable parsing of metadata and the creation + of persistent symlinks for that device. + + * The v230 change to tag framebuffer devices (/dev/fb*) with "uaccess" + to make them available to logged-in users has been reverted. + + * Much of the common code of the various systemd components is now + built into an internal shared library libsystemd-shared-231.so + (incorporating the systemd version number in the name, to be updated + with future releases) that the components link to. This should + decrease systemd footprint both in memory during runtime and on + disk. Note that the shared library is not for public use, and is + neither API nor ABI stable, but is likely to change with every new + released update. Packagers need to make sure that binaries + linking to libsystemd-shared.so are updated in step with the + library. + + * Configuration for "mkosi" is now part of the systemd + repository. mkosi is a tool to easily build legacy-free OS images, + and is available on github: https://github.com/systemd/mkosi. If + "mkosi" is invoked in the build tree a new raw OS image is generated + incorporating the systemd sources currently being worked on and a + clean, fresh distribution installation. The generated OS image may be + booted up with "systemd-nspawn -b -i", qemu-kvm or on any physical + UEFI PC. This functionality is particularly useful to easily test + local changes made to systemd in a pristine, defined environment. See + doc/HACKING for details. + + * configure learned the --with-support-url= option to specify the + distribution's bugtracker. + + Contributions from: Alban Crequy, Alessandro Puccetti, Alessio Igor + Bogani, Alexander Kuleshov, Alexander Kurtz, Alex Gaynor, Andika + Triwidada, Andreas Pokorny, Andreas Rammhold, Andrew Jeddeloh, Ansgar + Burchardt, Atrotors, Benjamin Drung, Brian Boylston, Christian Hesse, + Christian Rebischke, Daniele Medri, Daniel Mack, Dave Reisner, David + Herrmann, David Michael, Djalal Harouni, Douglas Christman, Elias + Probst, Evgeny Vereshchagin, Federico Mena Quintero, Felipe Sateler, + Franck Bui, Harald Hoyer, Ian Lee, Ivan Shapovalov, Jakub Wilk, Jan + Janssen, Jean-Sébastien Bour, John Paul Adrian Glaubitz, Jouke + Witteveen, Kai Ruhnau, kpengboy, Kyle Walker, Lénaïc Huard, Lennart + Poettering, Luca Bruno, Lukas Lösche, Lukáš Nykrýn, mahkoh, Marcel + Holtmann, Martin Pitt, Marty Plummer, Matthieu Codron, Max Prokhorov, + Michael Biebl, Michael Karcher, Michael Olbrich, Michał Bartoszkiewicz, + Michal Sekletar, Michal Soltys, Minkyung, Muhammet Kara, mulkieran, + Otto Wallenius, Pablo Lezaeta Reyes, Peter Hutterer, Ronny Chevalier, + Rusty Bird, Stef Walter, Susant Sahani, Tejun Heo, Thomas Blume, Thomas + Haller, Thomas H. P. Andersen, Tobias Jungel, Tom Gundersen, Tom Yan, + Topi Miettinen, Torstein Husebø, Valentin Vidić, Viktar Vaŭčkievič, + WaLyong Cho, Weng Xuetian, Werner Fink, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2016-07-25 + +CHANGES WITH 230: + + * DNSSEC is now turned on by default in systemd-resolved (in + "allow-downgrade" mode), but may be turned off during compile time by + passing "--with-default-dnssec=no" to "configure" (and of course, + during runtime with DNSSEC= in resolved.conf). We recommend + downstreams to leave this on at least during development cycles and + report any issues with the DNSSEC logic upstream. We are very + interested in collecting feedback about the DNSSEC validator and its + limitations in the wild. Note however, that DNSSEC support is + probably nothing downstreams should turn on in stable distros just + yet, as it might create incompatibilities with a few DNS servers and + networks. We tried hard to make sure we downgrade to non-DNSSEC mode + automatically whenever we detect such incompatible setups, but there + might be systems we do not cover yet. Hence: please help us testing + the DNSSEC code, leave this on where you can, report back, but then + again don't consider turning this on in your stable, LTS or + production release just yet. (Note that you have to enable + nss-resolve in /etc/nsswitch.conf, to actually use systemd-resolved + and its DNSSEC mode for host name resolution from local + applications.) + + * systemd-resolve conveniently resolves DANE records with the --tlsa + option and OPENPGPKEY records with the --openpgp option. It also + supports dumping raw DNS record data via the new --raw= switch. + + * systemd-logind will now by default terminate user processes that are + part of the user session scope unit (session-XX.scope) when the user + logs out. This behavior is controlled by the KillUserProcesses= + setting in logind.conf, and the previous default of "no" is now + changed to "yes". This means that user sessions will be properly + cleaned up after, but additional steps are necessary to allow + intentionally long-running processes to survive logout. + + While the user is logged in at least once, user@.service is running, + and any service that should survive the end of any individual login + session can be started at a user service or scope using systemd-run. + systemd-run(1) man page has been extended with an example which shows + how to run screen in a scope unit underneath user@.service. The same + command works for tmux. + + After the user logs out of all sessions, user@.service will be + terminated too, by default, unless the user has "lingering" enabled. + To effectively allow users to run long-term tasks even if they are + logged out, lingering must be enabled for them. See loginctl(1) for + details. The default polkit policy was modified to allow users to + set lingering for themselves without authentication. + + Previous defaults can be restored at compile time by the + --without-kill-user-processes option to "configure". + + * systemd-logind gained new configuration settings SessionsMax= and + InhibitorsMax=, both with a default of 8192. It will not register new + user sessions or inhibitors above this limit. + + * systemd-logind will now reload configuration on SIGHUP. + + * The unified cgroup hierarchy added in Linux 4.5 is now supported. + Use systemd.unified_cgroup_hierarchy=1 on the kernel command line to + enable. Also, support for the "io" cgroup controller in the unified + hierarchy has been added, so that the "memory", "pids" and "io" are + now the controllers that are supported on the unified hierarchy. + + WARNING: it is not possible to use previous systemd versions with + systemd.unified_cgroup_hierarchy=1 and the new kernel. Therefore it + is necessary to also update systemd in the initramfs if using the + unified hierarchy. An updated SELinux policy is also required. + + * LLDP support has been extended, and both passive (receive-only) and + active (sender) modes are supported. Passive mode ("routers-only") is + enabled by default in systemd-networkd. Active LLDP mode is enabled + by default for containers on the internal network. The "networkctl + lldp" command may be used to list information gathered. "networkctl + status" will also show basic LLDP information on connected peers now. + + * The IAID and DUID unique identifier sent in DHCP requests may now be + configured for the system and each .network file managed by + systemd-networkd using the DUIDType=, DUIDRawData=, IAID= options. + + * systemd-networkd gained support for configuring proxy ARP support for + each interface, via the ProxyArp= setting in .network files. It also + gained support for configuring the multicast querier feature of + bridge devices, via the new MulticastQuerier= setting in .netdev + files. Similarly, snooping on the IGMP traffic can be controlled + via the new setting MulticastSnooping=. + + A new setting PreferredLifetime= has been added for addresses + configured in .network file to configure the lifetime intended for an + address. + + The systemd-networkd DHCP server gained the option EmitRouter=, which + defaults to yes, to configure whether the DHCP Option 3 (Router) + should be emitted. + + * The testing tool /usr/lib/systemd/systemd-activate is renamed to + systemd-socket-activate and installed into /usr/bin. It is now fully + supported. + + * systemd-journald now uses separate threads to flush changes to disk + when closing journal files, thus reducing impact of slow disk I/O on + logging performance. + + * The sd-journal API gained two new calls + sd_journal_open_directory_fd() and sd_journal_open_files_fd() which + can be used to open journal files using file descriptors instead of + file or directory paths. sd_journal_open_container() has been + deprecated, sd_journal_open_directory_fd() should be used instead + with the flag SD_JOURNAL_OS_ROOT. + + * journalctl learned a new output mode "-o short-unix" that outputs log + lines prefixed by their UNIX time (i.e. seconds since Jan 1st, 1970 + UTC). It also gained support for a new --no-hostname setting to + suppress the hostname column in the family of "short" output modes. + + * systemd-ask-password now optionally skips printing of the password to + stdout with --no-output which can be useful in scripts. + + * Framebuffer devices (/dev/fb*) and 3D printers and scanners + (devices tagged with ID_MAKER_TOOL) are now tagged with + "uaccess" and are available to logged in users. + + * The DeviceAllow= unit setting now supports specifiers (with "%"). + + * "systemctl show" gained a new --value switch, which allows print a + only the contents of a specific unit property, without also printing + the property's name. Similar support was added to "show*" verbs + of loginctl and machinectl that output "key=value" lists. + + * A new unit type "generated" was added for files dynamically generated + by generator tools. Similarly, a new unit type "transient" is used + for unit files created using the runtime API. "systemctl enable" will + refuse to operate on such files. + + * A new command "systemctl revert" has been added that may be used to + revert to the vendor version of a unit file, in case local changes + have been made by adding drop-ins or overriding the unit file. + + * "machinectl clean" gained a new verb to automatically remove all or + just hidden container images. + + * systemd-tmpfiles gained support for a new line type "e" for emptying + directories, if they exist, without creating them if they don't. + + * systemd-nspawn gained support for automatically patching the UID/GIDs + of the owners and the ACLs of all files and directories in a + container tree to match the UID/GID user namespacing range selected + for the container invocation. This mode is enabled via the new + --private-users-chown switch. It also gained support for + automatically choosing a free, previously unused UID/GID range when + starting a container, via the new --private-users=pick setting (which + implies --private-users-chown). Together, these options for the first + time make user namespacing for nspawn containers fully automatic and + thus deployable. The systemd-nspawn@.service template unit file has + been changed to use this functionality by default. + + * systemd-nspawn gained a new --network-zone= switch, that allows + creating ad-hoc virtual Ethernet links between multiple containers, + that only exist as long as at least one container referencing them is + running. This allows easy connecting of multiple containers with a + common link that implements an Ethernet broadcast domain. Each of + these network "zones" may be named relatively freely by the user, and + may be referenced by any number of containers, but each container may + only reference one of these "zones". On the lower level, this is + implemented by an automatically managed bridge network interface for + each zone, that is created when the first container referencing its + zone is created and removed when the last one referencing its zone + terminates. + + * The default start timeout may now be configured on the kernel command + line via systemd.default_timeout_start_sec=. It was already + configurable via the DefaultTimeoutStartSec= option in + /etc/systemd/system.conf. + + * Socket units gained a new TriggerLimitIntervalSec= and + TriggerLimitBurst= setting to configure a limit on the activation + rate of the socket unit. + + * The LimitNICE= setting now optionally takes normal UNIX nice values + in addition to the raw integer limit value. If the specified + parameter is prefixed with "+" or "-" and is in the range -20..19 the + value is understood as UNIX nice value. If not prefixed like this it + is understood as raw RLIMIT_NICE limit. + + * Note that the effect of the PrivateDevices= unit file setting changed + slightly with this release: the per-device /dev file system will be + mounted read-only from this version on, and will have "noexec" + set. This (minor) change of behavior might cause some (exceptional) + legacy software to break, when PrivateDevices=yes is set for its + service. Please leave PrivateDevices= off if you run into problems + with this. + + * systemd-bootchart has been split out to a separate repository: + https://github.com/systemd/systemd-bootchart + + * systemd-bus-proxyd has been removed, as kdbus is unlikely to still be + merged into the kernel in its current form. + + * The compatibility libraries libsystemd-daemon.so, + libsystemd-journal.so, libsystemd-id128.so, and libsystemd-login.so + which have been deprecated since systemd-209 have been removed along + with the corresponding pkg-config files. All symbols provided by + those libraries are provided by libsystemd.so. + + * The Capabilities= unit file setting has been removed (it is ignored + for backwards compatibility). AmbientCapabilities= and + CapabilityBoundingSet= should be used instead. + + * A new special target has been added, initrd-root-device.target, + which creates a synchronization point for dependencies of the root + device in early userspace. Initramfs builders must ensure that this + target is now included in early userspace. + + Contributions from: Alban Crequy, Alexander Kuleshov, Alexander Shopov, + Alex Crawford, Andre Klärner, Andrew Eikum, Beniamino Galvani, Benjamin + Robin, Biao Lu, Bjørnar Ness, Calvin Owens, Christian Hesse, Clemens + Gruber, Colin Guthrie, Daniel Drake, Daniele Medri, Daniel J Walsh, + Daniel Mack, Dan Nicholson, daurnimator, David Herrmann, David + R. Hedges, Elias Probst, Emmanuel Gil Peyrot, EMOziko, Evgeny + Vereshchagin, Federico, Felipe Sateler, Filipe Brandenburger, Franck + Bui, frankheckenbach, gdamjan, Georgia Brikis, Harald Hoyer, Hendrik + Brueckner, Hristo Venev, Iago López Galeiras, Ian Kelling, Ismo + Puustinen, Jakub Wilk, Jaroslav Škarvada, Jeff Huang, Joel Holdsworth, + John Paul Adrian Glaubitz, Jonathan Boulle, kayrus, Klearchos + Chaloulos, Kyle Russell, Lars Uebernickel, Lennart Poettering, Lubomir + Rintel, Lukáš Nykrýn, Mantas Mikulėnas, Marcel Holtmann, Martin Pitt, + Michael Biebl, michaelolbrich, Michał Bartoszkiewicz, Michal Koutný, + Michal Sekletar, Mike Frysinger, Mike Gilbert, Mingcong Bai, Ming Lin, + mulkieran, muzena, Nalin Dahyabhai, Naohiro Aota, Nathan McSween, + Nicolas Braud-Santoni, Patrik Flykt, Peter Hutterer, Peter Mattern, + Petr Lautrbach, Petros Angelatos, Piotr Drąg, Rabin Vincent, Robert + Węcławski, Ronny Chevalier, Samuel Tardieu, Stefan Saraev, Stefan + Schallenberg aka nafets227, Steven Siloti, Susant Sahani, Sylvain + Plantefève, Taylor Smock, Tejun Heo, Thomas Blume, Thomas Haller, + Thomas H. P. Andersen, Tobias Klauser, Tom Gundersen, topimiettinen, + Torstein Husebø, Umut Tezduyar Lindskog, Uwe Kleine-König, Victor Toso, + Vinay Kulkarni, Vito Caputo, Vittorio G (VittGam), Vladimir Panteleev, + Wieland Hoffmann, Wouter Verhelst, Yu Watanabe, Zbigniew + Jędrzejewski-Szmek + + — Fairfax, 2016-05-21 + +CHANGES WITH 229: + + * The systemd-resolved DNS resolver service has gained a substantial + set of new features, most prominently it may now act as a DNSSEC + validating stub resolver. DNSSEC mode is currently turned off by + default, but is expected to be turned on by default in one of the + next releases. For now, we invite everybody to test the DNSSEC logic + by setting DNSSEC=allow-downgrade in /etc/systemd/resolved.conf. The + service also gained a full set of D-Bus interfaces, including calls + to configure DNS and DNSSEC settings per link (for use by external + network management software). systemd-resolved and systemd-networkd + now distinguish between "search" and "routing" domains. The former + are used to qualify single-label names, the latter are used purely + for routing lookups within certain domains to specific links. + resolved now also synthesizes RRs for all entries from /etc/hosts. + + * The systemd-resolve tool (which is a client utility for + systemd-resolved) has been improved considerably and is now fully + supported and documented. Hence it has moved from /usr/lib/systemd to + /usr/bin. + + * /dev/disk/by-path/ symlink support has been (re-)added for virtio + devices. + + * The coredump collection logic has been reworked: when a coredump is + collected it is now written to disk, compressed and processed + (including stacktrace extraction) from a new instantiated service + systemd-coredump@.service, instead of directly from the + /proc/sys/kernel/core_pattern hook we provide. This is beneficial as + processing large coredumps can take up a substantial amount of + resources and time, and this previously happened entirely outside of + systemd's service supervision. With the new logic the core_pattern + hook only does minimal metadata collection before passing off control + to the new instantiated service, which is configured with a time + limit, a nice level and other settings to minimize negative impact on + the rest of the system. Also note that the new logic will honour the + RLIMIT_CORE setting of the crashed process, which now allows users + and processes to turn off coredumping for their processes by setting + this limit. + + * The RLIMIT_CORE resource limit now defaults to "unlimited" for PID 1 + and all forked processes by default. Previously, PID 1 would leave + the setting at "0" for all processes, as set by the kernel. Note that + the resource limit traditionally has no effect on the generated + coredumps on the system if the /proc/sys/kernel/core_pattern hook + logic is used. Since the limit is now honoured (see above) its + default has been changed so that the coredumping logic is enabled by + default for all processes, while allowing specific opt-out. + + * When the stacktrace is extracted from processes of system users, this + is now done as "systemd-coredump" user, in order to sandbox this + potentially security sensitive parsing operation. (Note that when + processing coredumps of normal users this is done under the user ID + of process that crashed, as before.) Packagers should take notice + that it is now necessary to create the "systemd-coredump" system user + and group at package installation time. + + * The systemd-activate socket activation testing tool gained support + for SOCK_DGRAM and SOCK_SEQPACKET sockets using the new --datagram + and --seqpacket switches. It also has been extended to support both + new-style and inetd-style file descriptor passing. Use the new + --inetd switch to request inetd-style file descriptor passing. + + * Most systemd tools now honor a new $SYSTEMD_COLORS environment + variable, which takes a boolean value. If set to false, ANSI color + output is disabled in the tools even when run on a terminal that + supports it. + + * The VXLAN support in networkd now supports two new settings + DestinationPort= and PortRange=. + + * A new systemd.machine_id= kernel command line switch has been added, + that may be used to set the machine ID in /etc/machine-id if it is + not initialized yet. This command line option has no effect if the + file is already initialized. + + * systemd-nspawn gained a new --as-pid2 switch that invokes any + specified command line as PID 2 rather than PID 1 in the + container. In this mode PID 1 is a minimal stub init process that + implements the special POSIX and Linux semantics of PID 1 regarding + signal and child process management. Note that this stub init process + is implemented in nspawn itself and requires no support from the + container image. This new logic is useful to support running + arbitrary commands in the container, as normal processes are + generally not prepared to run as PID 1. + + * systemd-nspawn gained a new --chdir= switch for setting the current + working directory for the process started in the container. + + * "journalctl /dev/sda" will now output all kernel log messages for + specified device from the current boot, in addition to all devices + that are parents of it. This should make log output about devices + pretty useful, as long as kernel drivers attach enough metadata to + the log messages. (The usual SATA drivers do.) + + * The sd-journal API gained two new calls + sd_journal_has_runtime_files() and sd_journal_has_persistent_files() + that report whether log data from /run or /var has been found. + + * journalctl gained a new switch "--fields" that prints all journal + record field names currently in use in the journal. This is backed + by two new sd-journal API calls sd_journal_enumerate_fields() and + sd_journal_restart_fields(). + + * Most configurable timeouts in systemd now expect an argument of + "infinity" to turn them off, instead of "0" as before. The semantics + from now on is that a timeout of "0" means "now", and "infinity" + means "never". To maintain backwards compatibility, "0" continues to + turn off previously existing timeout settings. + + * "systemctl reload-or-try-restart" has been renamed to "systemctl + try-reload-or-restart" to clarify what it actually does: the "try" + logic applies to both reloading and restarting, not just restarting. + The old name continues to be accepted for compatibility. + + * On boot-up, when PID 1 detects that the system clock is behind the + release date of the systemd version in use, the clock is now set + to the latter. Previously, this was already done in timesyncd, in order + to avoid running with clocks set to the various clock epochs such as + 1902, 1938 or 1970. With this change the logic is now done in PID 1 + in addition to timesyncd during early boot-up, so that it is enforced + before the first process is spawned by systemd. Note that the logic + in timesyncd remains, as it is more comprehensive and ensures + clock monotonicity by maintaining a persistent timestamp file in + /var. Since /var is generally not available in earliest boot or the + initrd, this part of the logic remains in timesyncd, and is not done + by PID 1. + + * Support for tweaking details in net_cls.class_id through the + NetClass= configuration directive has been removed, as the kernel + people have decided to deprecate that controller in cgroup v2. + Userspace tools such as nftables are moving over to setting rules + that are specific to the full cgroup path of a task, which obsoletes + these controllers anyway. The NetClass= directive is kept around for + legacy compatibility reasons. For a more in-depth description of the + kernel change, please refer to the respective upstream commit: + + https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=bd1060a1d671 + + * A new service setting RuntimeMaxSec= has been added that may be used + to specify a maximum runtime for a service. If the timeout is hit, the + service is terminated and put into a failure state. + + * A new service setting AmbientCapabilities= has been added. It allows + configuration of additional Linux process capabilities that are + passed to the activated processes. This is only available on very + recent kernels. + + * The process resource limit settings in service units may now be used + to configure hard and soft limits individually. + + * The various libsystemd APIs such as sd-bus or sd-event now publicly + expose support for gcc's __attribute__((cleanup())) C extension. + Specifically, for many object destructor functions alternative + versions have been added that have names suffixed with "p" and take a + pointer to a pointer to the object to destroy, instead of just a + pointer to the object itself. This is useful because these destructor + functions may be used directly as parameters to the cleanup + construct. Internally, systemd has been a heavy user of this GCC + extension for a long time, and with this change similar support is + now available to consumers of the library outside of systemd. Note + that by using this extension in your sources compatibility with old + and strictly ANSI compatible C compilers is lost. However, all gcc or + LLVM versions of recent years support this extension. + + * Timer units gained support for a new setting RandomizedDelaySec= that + allows configuring some additional randomized delay to the configured + time. This is useful to spread out timer events to avoid load peaks in + clusters or larger setups. + + * Calendar time specifications now support sub-second accuracy. + + * Socket units now support listening on SCTP and UDP-lite protocol + sockets. + + * The sd-event API now comes with a full set of man pages. + + * Older versions of systemd contained experimental support for + compressing journal files and coredumps with the LZ4 compressor that + was not compatible with the lz4 binary (due to API limitations of the + lz4 library). This support has been removed; only support for files + compatible with the lz4 binary remains. This LZ4 logic is now + officially supported and no longer considered experimental. + + * The dkr image import logic has been removed again from importd. dkr's + micro-services focus doesn't fit into the machine image focus of + importd, and quickly got out of date with the upstream dkr API. + + * Creation of the /run/lock/lockdev/ directory was dropped from + tmpfiles.d/legacy.conf. Better locking mechanisms like flock() have + been available for many years. If you still need this, you need to + create your own tmpfiles.d config file with: + + d /run/lock/lockdev 0775 root lock - + + * The settings StartLimitBurst=, StartLimitInterval=, StartLimitAction= + and RebootArgument= have been moved from the [Service] section of + unit files to [Unit], and they are now supported on all unit types, + not just service units. Of course, systemd will continue to + understand these settings also at the old location, in order to + maintain compatibility. + + Contributions from: Abdo Roig-Maranges, Alban Crequy, Aleksander + Adamowski, Alexander Kuleshov, Andreas Pokorny, Andrei Borzenkov, + Andrew Wilcox, Arthur Clement, Beniamino Galvani, Casey Schaufler, + Chris Atkinson, Chris Mayo, Christian Hesse, Damjan Georgievski, Dan + Dedrick, Daniele Medri, Daniel J Walsh, Daniel Korostil, Daniel Mack, + David Herrmann, Dimitri John Ledkov, Dominik Hannen, Douglas Christman, + Evgeny Vereshchagin, Filipe Brandenburger, Franck Bui, Gabor Kelemen, + Harald Hoyer, Hayden Walles, Helmut Grohne, Henrik Kaare Poulsen, + Hristo Venev, Hui Wang, Indrajit Raychaudhuri, Ismo Puustinen, Jakub + Wilk, Jan Alexander Steffens (heftig), Jan Engelhardt, Jan Synacek, + Joost Bremmer, Jorgen Schaefer, Karel Zak, Klearchos Chaloulos, + lc85446, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, Marcel + Holtmann, Martin Pitt, Michael Biebl, Michael Olbrich, Michael Scherer, + Michał Górny, Michal Sekletar, Nicolas Cornu, Nicolas Iooss, Nils + Carlson, nmartensen, nnz1024, Patrick Ohly, Peter Hutterer, Phillip Sz, + Ronny Chevalier, Samu Kallio, Shawn Landden, Stef Walter, Susant + Sahani, Sylvain Plantefève, Tadej Janež, Thomas Hindoe Paaboel + Andersen, Tom Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Vito + Caputo, WaLyong Cho, Yu Watanabe, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2016-02-11 + +CHANGES WITH 228: + + * A number of properties previously only settable in unit + files are now also available as properties to set when + creating transient units programmatically via the bus, as it + is exposed with systemd-run's --property= + setting. Specifically, these are: SyslogIdentifier=, + SyslogLevelPrefix=, TimerSlackNSec=, OOMScoreAdjust=, + EnvironmentFile=, ReadWriteDirectories=, + ReadOnlyDirectories=, InaccessibleDirectories=, + ProtectSystem=, ProtectHome=, RuntimeDirectory=. + + * When creating transient services via the bus API it is now + possible to pass in a set of file descriptors to use as + STDIN/STDOUT/STDERR for the invoked process. + + * Slice units may now be created transiently via the bus APIs, + similar to the way service and scope units may already be + created transiently. + + * Wherever systemd expects a calendar timestamp specification + (like in journalctl's --since= and --until= switches) UTC + timestamps are now supported. Timestamps suffixed with "UTC" + are now considered to be in Universal Time Coordinated + instead of the local timezone. Also, timestamps may now + optionally be specified with sub-second accuracy. Both of + these additions also apply to recurring calendar event + specification, such as OnCalendar= in timer units. + + * journalctl gained a new "--sync" switch that asks the + journal daemon to write all so far unwritten log messages to + disk and sync the files, before returning. + + * systemd-tmpfiles learned two new line types "q" and "Q" that + operate like "v", but also set up a basic btrfs quota + hierarchy when used on a btrfs file system with quota + enabled. + + * tmpfiles' "v", "q" and "Q" will now create a plain directory + instead of a subvolume (even on a btrfs file system) if the + root directory is a plain directory, and not a + subvolume. This should simplify things with certain chroot() + environments which are not aware of the concept of btrfs + subvolumes. + + * systemd-detect-virt gained a new --chroot switch to detect + whether execution takes place in a chroot() environment. + + * CPUAffinity= now takes CPU index ranges in addition to + individual indexes. + + * The various memory-related resource limit settings (such as + LimitAS=) now understand the usual K, M, G, ... suffixes to + the base of 1024 (IEC). Similar, the time-related resource + limit settings understand the usual min, h, day, ... + suffixes now. + + * There's a new system.conf setting DefaultTasksMax= to + control the default TasksMax= setting for services and + scopes running on the system. (TasksMax= is the primary + setting that exposes the "pids" cgroup controller on systemd + and was introduced in the previous systemd release.) The + setting now defaults to 512, which means services that are + not explicitly configured otherwise will only be able to + create 512 processes or threads at maximum, from this + version on. Note that this means that thread- or + process-heavy services might need to be reconfigured to set + TasksMax= to a higher value. It is sufficient to set + TasksMax= in these specific unit files to a higher value, or + even "infinity". Similar, there's now a logind.conf setting + UserTasksMax= that defaults to 4096 and limits the total + number of processes or tasks each user may own + concurrently. nspawn containers also have the TasksMax= + value set by default now, to 8192. Note that all of this + only has an effect if the "pids" cgroup controller is + enabled in the kernel. The general benefit of these changes + should be a more robust and safer system, that provides a + certain amount of per-service fork() bomb protection. + + * systemd-nspawn gained the new --network-veth-extra= switch + to define additional and arbitrarily-named virtual Ethernet + links between the host and the container. + + * A new service execution setting PassEnvironment= has been + added that allows importing select environment variables + from PID1's environment block into the environment block of + the service. + + * Timer units gained support for a new RemainAfterElapse= + setting which takes a boolean argument. It defaults to on, + exposing behaviour unchanged to previous releases. If set to + off, timer units are unloaded after they elapsed if they + cannot elapse again. This is particularly useful for + transient timer units, which shall not stay around longer + than until they first elapse. + + * systemd will now bump the net.unix.max_dgram_qlen to 512 by + default now (the kernel default is 16). This is beneficial + for avoiding blocking on AF_UNIX/SOCK_DGRAM sockets since it + allows substantially larger numbers of queued + datagrams. This should increase the capability of systemd to + parallelize boot-up, as logging and sd_notify() are unlikely + to stall execution anymore. If you need to change the value + from the new defaults, use the usual sysctl.d/ snippets. + + * The compression framing format used by the journal or + coredump processing has changed to be in line with what the + official LZ4 tools generate. LZ4 compression support in + systemd was considered unsupported previously, as the format + was not compatible with the normal tools. With this release + this has changed now, and it is hence safe for downstream + distributions to turn it on. While not compressing as well + as the XZ, LZ4 is substantially faster, which makes + it a good default choice for the compression logic in the + journal and in coredump handling. + + * Any reference to /etc/mtab has been dropped from + systemd. The file has been obsolete since a while, but + systemd refused to work on systems where it was incorrectly + set up (it should be a symlink or non-existent). Please make + sure to update to util-linux 2.27.1 or newer in conjunction + with this systemd release, which also drops any reference to + /etc/mtab. If you maintain a distribution make sure that no + software you package still references it, as this is a + likely source of bugs. There's also a glibc bug pending, + asking for removal of any reference to this obsolete file: + + https://sourceware.org/bugzilla/show_bug.cgi?id=19108 + + Note that only util-linux versions built with + --enable-libmount-force-mountinfo are supported. + + * Support for the ".snapshot" unit type has been removed. This + feature turned out to be little useful and little used, and + has now been removed from the core and from systemctl. + + * The dependency types RequiresOverridable= and + RequisiteOverridable= have been removed from systemd. They + have been used only very sparingly to our knowledge and + other options that provide a similar effect (such as + systemctl --mode=ignore-dependencies) are much more useful + and commonly used. Moreover, they were only half-way + implemented as the option to control behaviour regarding + these dependencies was never added to systemctl. By removing + these dependency types the execution engine becomes a bit + simpler. Unit files that use these dependencies should be + changed to use the non-Overridable dependency types + instead. In fact, when parsing unit files with these + options, that's what systemd will automatically convert them + too, but it will also warn, asking users to fix the unit + files accordingly. Removal of these dependency types should + only affect a negligible number of unit files in the wild. + + * Behaviour of networkd's IPForward= option changed + (again). It will no longer maintain a per-interface setting, + but propagate one way from interfaces where this is enabled + to the global kernel setting. The global setting will be + enabled when requested by a network that is set up, but + never be disabled again. This change was made to make sure + IPv4 and IPv6 behaviour regarding packet forwarding is + similar (as the Linux IPv6 stack does not support + per-interface control of this setting) and to minimize + surprises. + + * In unit files the behaviour of %u, %U, %h, %s has + changed. These specifiers will now unconditionally resolve + to the various user database fields of the user that the + systemd instance is running as, instead of the user + configured in the specific unit via User=. Note that this + effectively doesn't change much, as resolving of these + specifiers was already turned off in the --system instance + of systemd, as we cannot do NSS lookups from PID 1. In the + --user instance of systemd these specifiers where correctly + resolved, but hardly made any sense, since the user instance + lacks privileges to do user switches anyway, and User= is + hence useless. Moreover, even in the --user instance of + systemd behaviour was awkward as it would only take settings + from User= assignment placed before the specifier into + account. In order to unify and simplify the logic around + this the specifiers will now always resolve to the + credentials of the user invoking the manager (which in case + of PID 1 is the root user). + + Contributions from: Andrew Jones, Beniamino Galvani, Boyuan + Yang, Daniel Machon, Daniel Mack, David Herrmann, David + Reynolds, David Strauss, Dongsu Park, Evgeny Vereshchagin, + Felipe Sateler, Filipe Brandenburger, Franck Bui, Hristo + Venev, Iago López Galeiras, Jan Engelhardt, Jan Janssen, Jan + Synacek, Jesus Ornelas Aguayo, Karel Zak, kayrus, Kay Sievers, + Lennart Poettering, Liu Yuan Yuan, Mantas Mikulėnas, Marcel + Holtmann, Marcin Bachry, Marcos Alano, Marcos Mello, Mark + Theunissen, Martin Pitt, Michael Marineau, Michael Olbrich, + Michal Schmidt, Michal Sekletar, Mirco Tischler, Nick Owens, + Nicolas Cornu, Patrik Flykt, Peter Hutterer, reverendhomer, + Ronny Chevalier, Sangjung Woo, Seong-ho Cho, Shawn Landden, + Susant Sahani, Thomas Haller, Thomas Hindoe Paaboel Andersen, + Tom Gundersen, Torstein Husebø, Vito Caputo, Zbigniew + Jędrzejewski-Szmek + + — Berlin, 2015-11-18 + +CHANGES WITH 227: + + * systemd now depends on util-linux v2.27. More specifically, + the newly added mount monitor feature in libmount now + replaces systemd's former own implementation. + + * libmount mandates /etc/mtab not to be regular file, and + systemd now enforces this condition at early boot. + /etc/mtab has been deprecated and warned about for a very + long time, so systems running systemd should already have + stopped having this file around as anything else than a + symlink to /proc/self/mounts. + + * Support for the "pids" cgroup controller has been added. It + allows accounting the number of tasks in a cgroup and + enforcing limits on it. This adds two new setting + TasksAccounting= and TasksMax= to each unit, as well as a + global option DefaultTasksAccounting=. + + * Support for the "net_cls" cgroup controller has been added. + It allows assigning a net class ID to each task in the + cgroup, which can then be used in firewall rules and traffic + shaping configurations. Note that the kernel netfilter net + class code does not currently work reliably for ingress + packets on unestablished sockets. + + This adds a new config directive called NetClass= to CGroup + enabled units. Allowed values are positive numbers for fixed + assignments and "auto" for picking a free value + automatically. + + * 'systemctl is-system-running' now returns 'offline' if the + system is not booted with systemd. This command can now be + used as a substitute for 'systemd-notify --booted'. + + * Watchdog timeouts have been increased to 3 minutes for all + in-tree service files. Apparently, disk IO issues are more + frequent than we hoped, and user reported >1 minute waiting + for disk IO. + + * 'machine-id-commit' functionality has been merged into + 'machine-id-setup --commit'. The separate binary has been + removed. + + * The WorkingDirectory= directive in unit files may now be set + to the special value '~'. In this case, the working + directory is set to the home directory of the user + configured in User=. + + * "machinectl shell" will now open the shell in the home + directory of the selected user by default. + + * The CrashChVT= configuration file setting is renamed to + CrashChangeVT=, following our usual logic of not + abbreviating unnecessarily. The old directive is still + supported for compat reasons. Also, this directive now takes + an integer value between 1 and 63, or a boolean value. The + formerly supported '-1' value for disabling stays around for + compat reasons. + + * The PrivateTmp=, PrivateDevices=, PrivateNetwork=, + NoNewPrivileges=, TTYPath=, WorkingDirectory= and + RootDirectory= properties can now be set for transient + units. + + * The systemd-analyze tool gained a new "set-log-target" verb + to change the logging target the system manager logs to + dynamically during runtime. This is similar to how + "systemd-analyze set-log-level" already changes the log + level. + + * In nspawn /sys is now mounted as tmpfs, with only a selected + set of subdirectories mounted in from the real sysfs. This + enhances security slightly, and is useful for ensuring user + namespaces work correctly. + + * Support for USB FunctionFS activation has been added. This + allows implementation of USB gadget services that are + activated as soon as they are requested, so that they don't + have to run continuously, similar to classic socket + activation. + + * The "systemctl exit" command now optionally takes an + additional parameter that sets the exit code to return from + the systemd manager when exiting. This is only relevant when + running the systemd user instance, or when running the + system instance in a container. + + * sd-bus gained the new API calls sd_bus_path_encode_many() + and sd_bus_path_decode_many() that allow easy encoding and + decoding of multiple identifier strings inside a D-Bus + object path. Another new call sd_bus_default_flush_close() + has been added to flush and close per-thread default + connections. + + * systemd-cgtop gained support for a -M/--machine= switch to + show the control groups within a certain container only. + + * "systemctl kill" gained support for an optional --fail + switch. If specified the requested operation will fail of no + processes have been killed, because the unit had no + processes attached, or similar. + + * A new systemd.crash_reboot=1 kernel command line option has + been added that triggers a reboot after crashing. This can + also be set through CrashReboot= in systemd.conf. + + * The RuntimeDirectory= setting now understands unit + specifiers like %i or %f. + + * A new (still internal) library API sd-ipv4acd has been added, + that implements address conflict detection for IPv4. It's + based on code from sd-ipv4ll, and will be useful for + detecting DHCP address conflicts. + + * File descriptors passed during socket activation may now be + named. A new API sd_listen_fds_with_names() is added to + access the names. The default names may be overridden, + either in the .socket file using the FileDescriptorName= + parameter, or by passing FDNAME= when storing the file + descriptors using sd_notify(). + + * systemd-networkd gained support for: + + - Setting the IPv6 Router Advertisement settings via + IPv6AcceptRouterAdvertisements= in .network files. + + - Configuring the HelloTimeSec=, MaxAgeSec= and + ForwardDelaySec= bridge parameters in .netdev files. + + - Configuring PreferredSource= for static routes in + .network files. + + * The "ask-password" framework used to query for LUKS harddisk + passwords or SSL passwords during boot gained support for + caching passwords in the kernel keyring, if it is + available. This makes sure that the user only has to type in + a passphrase once if there are multiple objects to unlock + with the same one. Previously, such password caching was + available only when Plymouth was used; this moves the + caching logic into the systemd codebase itself. The + "systemd-ask-password" utility gained a new --keyname= + switch to control which kernel keyring key to use for + caching a password in. This functionality is also useful for + enabling display managers such as gdm to automatically + unlock the user's GNOME keyring if its passphrase, the + user's password and the harddisk password are the same, if + gdm-autologin is used. + + * When downloading tar or raw images using "machinectl + pull-tar" or "machinectl pull-raw", a matching ".nspawn" + file is now also downloaded, if it is available and stored + next to the image file. + + * Units of type ".socket" gained a new boolean setting + Writable= which is only useful in conjunction with + ListenSpecial=. If true, enables opening the specified + special file in O_RDWR mode rather than O_RDONLY mode. + + * systemd-rfkill has been reworked to become a singleton + service that is activated through /dev/rfkill on each rfkill + state change and saves the settings to disk. This way, + systemd-rfkill is now compatible with devices that exist + only intermittendly, and even restores state if the previous + system shutdown was abrupt rather than clean. + + * The journal daemon gained support for vacuuming old journal + files controlled by the number of files that shall remain, + in addition to the already existing control by size and by + date. This is useful as journal interleaving performance + degrades with too many separate journal files, and allows + putting an effective limit on them. The new setting defaults + to 100, but this may be changed by setting SystemMaxFiles= + and RuntimeMaxFiles= in journald.conf. Also, the + "journalctl" tool gained the new --vacuum-files= switch to + manually vacuum journal files to leave only the specified + number of files in place. + + * udev will now create /dev/disk/by-path links for ATA devices + on kernels where that is supported. + + * Galician, Serbian, Turkish and Korean translations were added. + + Contributions from: Aaro Koskinen, Alban Crequy, Beniamino + Galvani, Benjamin Robin, Branislav Blaskovic, Chen-Han Hsiao + (Stanley), Daniel Buch, Daniel Machon, Daniel Mack, David + Herrmann, David Milburn, doubleodoug, Evgeny Vereshchagin, + Felipe Franciosi, Filipe Brandenburger, Fran Dieguez, Gabriel + de Perthuis, Georg Müller, Hans de Goede, Hendrik Brueckner, + Ivan Shapovalov, Jacob Keller, Jan Engelhardt, Jan Janssen, + Jan Synacek, Jens Kuske, Karel Zak, Kay Sievers, Krzesimir + Nowak, Krzysztof Kotlenga, Lars Uebernickel, Lennart + Poettering, Lukas Nykryn, Łukasz Stelmach, Maciej Wereski, + Marcel Holtmann, Marius Thesing, Martin Pitt, Michael Biebl, + Michael Gebetsroither, Michal Schmidt, Michal Sekletar, Mike + Gilbert, Muhammet Kara, nazgul77, Nicolas Cornu, NoXPhasma, + Olof Johansson, Patrik Flykt, Pawel Szewczyk, reverendhomer, + Ronny Chevalier, Sangjung Woo, Seong-ho Cho, Susant Sahani, + Sylvain Plantefève, Thomas Haller, Thomas Hindoe Paaboel + Andersen, Tom Gundersen, Tom Lyon, Viktar Vauchkevich, + Zbigniew Jędrzejewski-Szmek, Марко М. Костић + + — Berlin, 2015-10-07 + +CHANGES WITH 226: + + * The DHCP implementation of systemd-networkd gained a set of + new features: + + - The DHCP server now supports emitting DNS and NTP + information. It may be enabled and configured via + EmitDNS=, DNS=, EmitNTP=, and NTP=. If transmission of DNS + and NTP information is enabled, but no servers are + configured, the corresponding uplink information (if there + is any) is propagated. + + - Server and client now support transmission and reception + of timezone information. It can be configured via the + newly introduced network options UseTimezone=, + EmitTimezone=, and Timezone=. Transmission of timezone + information is enabled between host and containers by + default now: the container will change its local timezone + to what the host has set. + + - Lease timeouts can now be configured via + MaxLeaseTimeSec= and DefaultLeaseTimeSec=. + + - The DHCP server improved on the stability of + leases. Clients are more likely to get the same lease + information back, even if the server loses state. + + - The DHCP server supports two new configuration options to + control the lease address pool metrics, PoolOffset= and + PoolSize=. + + * The encapsulation limit of tunnels in systemd-networkd may + now be configured via 'EncapsulationLimit='. It allows + modifying the maximum additional levels of encapsulation + that are permitted to be prepended to a packet. + + * systemd now supports the concept of user buses replacing + session buses, if used with dbus-1.10 (and enabled via dbus + --enable-user-session). It previously only supported this on + kdbus-enabled systems, and this release expands this to + 'dbus-daemon' systems. + + * systemd-networkd now supports predictable interface names + for virtio devices. + + * systemd now optionally supports the new Linux kernel + "unified" control group hierarchy. If enabled via the kernel + command-line option 'systemd.unified_cgroup_hierarchy=1', + systemd will try to mount the unified cgroup hierarchy + directly on /sys/fs/cgroup. If not enabled, or not + available, systemd will fall back to the legacy cgroup + hierarchy setup, as before. Host system and containers can + mix and match legacy and unified hierarchies as they + wish. nspawn understands the $UNIFIED_CGROUP_HIERARCHY + environment variable to individually select the hierarchy to + use for executed containers. By default, nspawn will use the + unified hierarchy for the containers if the host uses the + unified hierarchy, and the legacy hierarchy otherwise. + Please note that at this point the unified hierarchy is an + experimental kernel feature and is likely to change in one + of the next kernel releases. Therefore, it should not be + enabled by default in downstream distributions yet. The + minimum required kernel version for the unified hierarchy to + work is 4.2. Note that when the unified hierarchy is used + for the first time delegated access to controllers is + safe. Because of this systemd-nspawn containers will get + access to controllers now, as will systemd user + sessions. This means containers and user sessions may now + manage their own resources, partitioning up what the system + grants them. + + * A new special scope unit "init.scope" has been introduced + that encapsulates PID 1 of the system. It may be used to + determine resource usage and enforce resource limits on PID + 1 itself. PID 1 hence moved out of the root of the control + group tree. + + * The cgtop tool gained support for filtering out kernel + threads when counting tasks in a control group. Also, the + count of processes is now recursively summed up by + default. Two options -k and --recursive= have been added to + revert to old behaviour. The tool has also been updated to + work correctly in containers now. + + * systemd-nspawn's --bind= and --bind-ro= options have been + extended to allow creation of non-recursive bind mounts. + + * libsystemd gained two new calls sd_pid_get_cgroup() and + sd_peer_get_cgroup() which return the control group path of + a process or peer of a connected AF_UNIX socket. This + function call is particularly useful when implementing + delegated subtrees support in the control group hierarchy. + + * The "sd-event" event loop API of libsystemd now supports + correct dequeuing of real-time signals, without losing + signal events. + + * When systemd requests a polkit decision when managing units it + will now add additional fields to the request, including unit + name and desired operation. This enables more powerful polkit + policies, that make decisions depending on these parameters. + + * nspawn learnt support for .nspawn settings files, that may + accompany the image files or directories of containers, and + may contain additional settings for the container. This is + an alternative to configuring container parameters via the + nspawn command line. + + Contributions from: Cristian Rodríguez, Daniel Mack, David + Herrmann, Eugene Yakubovich, Evgeny Vereshchagin, Filipe + Brandenburger, Hans de Goede, Jan Alexander Steffens, Jan + Synacek, Kay Sievers, Lennart Poettering, Mangix, Marcel + Holtmann, Martin Pitt, Michael Biebl, Michael Chapman, Michal + Sekletar, Peter Hutterer, Piotr Drąg, reverendhomer, Robin + Hack, Susant Sahani, Sylvain Pasche, Thomas Hindoe Paaboel + Andersen, Tom Gundersen, Torstein Husebø + + — Berlin, 2015-09-08 + +CHANGES WITH 225: + + * machinectl gained a new verb 'shell' which opens a fresh + shell on the target container or the host. It is similar to + the existing 'login' command of machinectl, but spawns the + shell directly without prompting for username or + password. The pseudo machine '.host' now refers to the local + host and is used by default. Hence, 'machinectl shell' can + be used as replacement for 'su -' which spawns a session as + a fresh systemd unit in a way that is fully isolated from + the originating session. + + * systemd-networkd learned to cope with private-zone DHCP + options and allows other programs to query the values. + + * SELinux access control when enabling/disabling units is no + longer enforced with this release. The previous implementation + was incorrect, and a new corrected implementation is not yet + available. As unit file operations are still protected via + polkit and D-Bus policy this is not a security problem. Yet, + distributions which care about optimal SELinux support should + probably not stabilize on this release. + + * sd-bus gained support for matches of type "arg0has=", that + test for membership of strings in string arrays sent in bus + messages. + + * systemd-resolved now dumps the contents of its DNS and LLMNR + caches to the logs on reception of the SIGUSR1 signal. This + is useful to debug DNS behaviour. + + * The coredumpctl tool gained a new --directory= option to + operate on journal files in a specific directory. + + * "systemctl reboot" and related commands gained a new + "--message=" option which may be used to set a free-text + wall message when shutting down or rebooting the + system. This message is also logged, which is useful for + figuring out the reason for a reboot or shutdown a + posteriori. + + * The "systemd-resolve-host" tool's -i switch now takes + network interface numbers as alternative to interface names. + + * A new unit file setting for services has been introduced: + UtmpMode= allows configuration of how precisely systemd + handles utmp and wtmp entries for the service if this is + enabled. This allows writing services that appear similar to + user sessions in the output of the "w", "who", "last" and + "lastlog" tools. + + * systemd-resolved will now locally synthesize DNS resource + records for the "localhost" and "gateway" domains as well as + the local hostname. This should ensure that clients querying + RRs via resolved will get similar results as those going via + NSS, if nss-myhostname is enabled. + + Contributions from: Alastair Hughes, Alex Crawford, Daniel + Mack, David Herrmann, Dimitri John Ledkov, Eric Kostrowski, + Evgeny Vereshchagin, Felipe Sateler, HATAYAMA Daisuke, Jan + Pokorný, Jan Synacek, Johnny Robeson, Karel Zak, Kay Sievers, + Kefeng Wang, Lennart Poettering, Major Hayden, Marcel + Holtmann, Markus Elfring, Martin Mikkelsen, Martin Pitt, Matt + Turner, Maxim Mikityanskiy, Michael Biebl, Namhyung Kim, + Nicolas Cornu, Owen W. Taylor, Patrik Flykt, Peter Hutterer, + reverendhomer, Richard Maw, Ronny Chevalier, Seth Jennings, + Stef Walter, Susant Sahani, Thomas Blume, Thomas Hindoe + Paaboel Andersen, Thomas Meyer, Tom Gundersen, Vincent Batts, + WaLyong Cho, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2015-08-27 + +CHANGES WITH 224: + + * The systemd-efi-boot-generator functionality was merged into + systemd-gpt-auto-generator. + + * systemd-networkd now supports Group Policy for vxlan + devices. It can be enabled via the new boolean configuration + option called 'GroupPolicyExtension='. + + Contributions from: Andreas Kempf, Christian Hesse, Daniel Mack, David + Herrmann, Herman Fries, Johannes Nixdorf, Kay Sievers, Lennart + Poettering, Peter Hutterer, Susant Sahani, Tom Gundersen + + — Berlin, 2015-07-31 + +CHANGES WITH 223: + + * The python-systemd code has been removed from the systemd repository. + A new repository has been created which accommodates the code from + now on, and we kindly ask distributions to create a separate package + for this: https://github.com/systemd/python-systemd + + * The systemd daemon will now reload its main configuration + (/etc/systemd/system.conf) on daemon-reload. + + * sd-dhcp now exposes vendor specific extensions via + sd_dhcp_lease_get_vendor_specific(). + + * systemd-networkd gained a number of new configuration options. + + - A new boolean configuration option for TAP devices called + 'VNetHeader='. If set, the IFF_VNET_HDR flag is set for the + device, thus allowing to send and receive GSO packets. + + - A new tunnel configuration option called 'CopyDSCP='. + If enabled, the DSCP field of ip6 tunnels is copied into the + decapsulated packet. + + - A set of boolean bridge configuration options were added. + 'UseBPDU=', 'HairPin=', 'FastLeave=', 'AllowPortToBeRoot=', + and 'UnicastFlood=' are now parsed by networkd and applied to the + respective bridge link device via the respective IFLA_BRPORT_* + netlink attribute. + + - A new string configuration option to override the hostname sent + to a DHCP server, called 'Hostname='. If set and 'SendHostname=' + is true, networkd will use the configured hostname instead of the + system hostname when sending DHCP requests. + + - A new tunnel configuration option called 'IPv6FlowLabel='. If set, + networkd will configure the IPv6 flow-label of the tunnel device + according to RFC2460. + + - The 'macvtap' virtual network devices are now supported, similar to + the already supported 'macvlan' devices. + + * systemd-resolved now implements RFC5452 to improve resilience against + cache poisoning. Additionally, source port randomization is enabled + by default to further protect against DNS spoofing attacks. + + * nss-mymachines now supports translating UIDs and GIDs of running + containers with user-namespaces enabled. If a container 'foo' + translates a host uid 'UID' to the container uid 'TUID', then + nss-mymachines will also map uid 'UID' to/from username 'vu-foo-TUID' + (with 'foo' and 'TUID' replaced accordingly). Similarly, groups are + mapped as 'vg-foo-TGID'. + + Contributions from: Beniamino Galvani, cee1, Christian Hesse, Daniel + Buch, Daniel Mack, daurnimator, David Herrmann, Dimitri John Ledkov, + HATAYAMA Daisuke, Ivan Shapovalov, Jan Alexander Steffens (heftig), + Johan Ouwerkerk, Jose Carlos Venegas Munoz, Karel Zak, Kay Sievers, + Lennart Poettering, Lidong Zhong, Martin Pitt, Michael Biebl, Michael + Olbrich, Michal Schmidt, Michal Sekletar, Mike Gilbert, Namhyung Kim, + Nick Owens, Peter Hutterer, Richard Maw, Steven Allen, Sungbae Yoo, + Susant Sahani, Thomas Blume, Thomas Hindoe Paaboel Andersen, Tom + Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Vito Caputo, + Vivenzio Pagliari, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2015-07-29 + +CHANGES WITH 222: + + * udev does not longer support the WAIT_FOR_SYSFS= key in udev rules. + There are no known issues with current sysfs, and udev does not need + or should be used to work around such bugs. + + * udev does no longer enable USB HID power management. Several reports + indicate, that some devices cannot handle that setting. + + * The udev accelerometer helper was removed. The functionality + is now fully included in iio-sensor-proxy. But this means, + older iio-sensor-proxy versions will no longer provide + accelerometer/orientation data with this systemd version. + Please upgrade iio-sensor-proxy to version 1.0. + + * networkd gained a new configuration option IPv6PrivacyExtensions= + which enables IPv6 privacy extensions (RFC 4941, "Privacy Extensions + for Stateless Address") on selected networks. + + * For the sake of fewer build-time dependencies and less code in the + main repository, the python bindings are about to be removed in the + next release. A new repository has been created which accommodates + the code from now on, and we kindly ask distributions to create a + separate package for this. The removal will take place in v223. + + https://github.com/systemd/python-systemd + + Contributions from: Abdo Roig-Maranges, Andrew Eikum, Bastien Nocera, + Cédric Delmas, Christian Hesse, Christos Trochalakis, Daniel Mack, + daurnimator, David Herrmann, Dimitri John Ledkov, Eric Biggers, Eric + Cook, Felipe Sateler, Geert Jansen, Gerd Hoffmann, Gianpaolo Macario, + Greg Kroah-Hartman, Iago López Galeiras, Jan Alexander Steffens + (heftig), Jan Engelhardt, Jay Strict, Kay Sievers, Lennart Poettering, + Markus Knetschke, Martin Pitt, Michael Biebl, Michael Marineau, Michal + Sekletar, Miguel Bernal Marin, Peter Hutterer, Richard Maw, rinrinne, + Susant Sahani, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein + Husebø, Vedran Miletić, WaLyong Cho, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2015-07-07 + +CHANGES WITH 221: + + * The sd-bus.h and sd-event.h APIs have now been declared + stable and have been added to the official interface of + libsystemd.so. sd-bus implements an alternative D-Bus client + library, that is relatively easy to use, very efficient and + supports both classic D-Bus as well as kdbus as transport + backend. sd-event is a generic event loop abstraction that + is built around Linux epoll, but adds features such as event + prioritization or efficient timer handling. Both APIs are good + choices for C programs looking for a bus and/or event loop + implementation that is minimal and does not have to be + portable to other kernels. + + * kdbus support is no longer compile-time optional. It is now + always built-in. However, it can still be disabled at + runtime using the kdbus=0 kernel command line setting, and + that setting may be changed to default to off, by specifying + --disable-kdbus at build-time. Note though that the kernel + command line setting has no effect if the kdbus.ko kernel + module is not installed, in which case kdbus is (obviously) + also disabled. We encourage all downstream distributions to + begin testing kdbus by adding it to the kernel images in the + development distributions, and leaving kdbus support in + systemd enabled. + + * The minimal required util-linux version has been bumped to + 2.26. + + * Support for chkconfig (--enable-chkconfig) was removed in + favor of calling an abstraction tool + /lib/systemd/systemd-sysv-install. This needs to be + implemented for your distribution. See "SYSV INIT.D SCRIPTS" + in README for details. + + * If there's a systemd unit and a SysV init script for the + same service name, and the user executes "systemctl enable" + for it (or a related call), then this will now enable both + (or execute the related operation on both), not just the + unit. + + * The libudev API documentation has been converted from gtkdoc + into man pages. + + * gudev has been removed from the systemd tree, it is now an + external project. + + * The systemd-cgtop tool learnt a new --raw switch to generate + "raw" (machine parsable) output. + + * networkd's IPForwarding= .network file setting learnt the + new setting "kernel", which ensures that networkd does not + change the IP forwarding sysctl from the default kernel + state. + + * The systemd-logind bus API now exposes a new boolean + property "Docked" that reports whether logind considers the + system "docked", i.e. connected to a docking station or not. + + Contributions from: Alex Crawford, Andreas Pokorny, Andrei + Borzenkov, Charles Duffy, Colin Guthrie, Cristian Rodríguez, + Daniele Medri, Daniel Hahler, Daniel Mack, David Herrmann, + David Mohr, Dimitri John Ledkov, Djalal Harouni, dslul, Ed + Swierk, Eric Cook, Filipe Brandenburger, Gianpaolo Macario, + Harald Hoyer, Iago López Galeiras, Igor Vuk, Jan Synacek, + Jason Pleau, Jason S. McMullan, Jean Delvare, Jeff Huang, + Jonathan Boulle, Karel Zak, Kay Sievers, kloun, Lennart + Poettering, Marc-Antoine Perennou, Marcel Holtmann, Mario + Limonciello, Martin Pitt, Michael Biebl, Michael Olbrich, + Michal Schmidt, Mike Gilbert, Nick Owens, Pablo Lezaeta Reyes, + Patrick Donnelly, Pavel Odvody, Peter Hutterer, Philip + Withnall, Ronny Chevalier, Simon McVittie, Susant Sahani, + Thomas Hindoe Paaboel Andersen, Tom Gundersen, Torstein + Husebø, Umut Tezduyar Lindskog, Viktar Vauchkevich, Werner + Fink, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2015-06-19 + +CHANGES WITH 220: + + * The gudev library has been extracted into a separate repository + available at: https://git.gnome.org/browse/libgudev/ + It is now managed as part of the Gnome project. Distributions + are recommended to pass --disable-gudev to systemd and use + gudev from the Gnome project instead. gudev is still included + in systemd, for now. It will be removed soon, though. Please + also see the announcement-thread on systemd-devel: + https://lists.freedesktop.org/archives/systemd-devel/2015-May/032070.html + + * systemd now exposes a CPUUsageNSec= property for each + service unit on the bus, that contains the overall consumed + CPU time of a service (the sum of what each process of the + service consumed). This value is only available if + CPUAccounting= is turned on for a service, and is then shown + in the "systemctl status" output. + + * Support for configuring alternative mappings of the old SysV + runlevels to systemd targets has been removed. They are now + hardcoded in a way that runlevels 2, 3, 4 all map to + multi-user.target and 5 to graphical.target (which + previously was already the default behaviour). + + * The auto-mounter logic gained support for mount point + expiry, using a new TimeoutIdleSec= setting in .automount + units. (Also available as x-systemd.idle-timeout= in /etc/fstab). + + * The EFI System Partition (ESP) as mounted to /boot by + systemd-efi-boot-generator will now be unmounted + automatically after 2 minutes of not being used. This should + minimize the risk of ESP corruptions. + + * New /etc/fstab options x-systemd.requires= and + x-systemd.requires-mounts-for= are now supported to express + additional dependencies for mounts. This is useful for + journalling file systems that support external journal + devices or overlay file systems that require underlying file + systems to be mounted. + + * systemd does not support direct live-upgrades (via systemctl + daemon-reexec) from versions older than v44 anymore. As no + distribution we are aware of shipped such old versions in a + stable release this should not be problematic. + + * When systemd forks off a new per-connection service instance + it will now set the $REMOTE_ADDR environment variable to the + remote IP address, and $REMOTE_PORT environment variable to + the remote IP port. This behaviour is similar to the + corresponding environment variables defined by CGI. + + * systemd-networkd gained support for uplink failure + detection. The BindCarrier= option allows binding interface + configuration dynamically to the link sense of other + interfaces. This is useful to achieve behaviour like in + network switches. + + * systemd-networkd gained support for configuring the DHCP + client identifier to use when requesting leases. + + * systemd-networkd now has a per-network UseNTP= option to + configure whether NTP server information acquired via DHCP + is passed on to services like systemd-timesyncd. + + * systemd-networkd gained support for vti6 tunnels. + + * Note that systemd-networkd manages the sysctl variable + /proc/sys/net/ipv[46]/conf/*/forwarding for each interface + it is configured for since v219. The variable controls IP + forwarding, and is a per-interface alternative to the global + /proc/sys/net/ipv[46]/ip_forward. This setting is + configurable in the IPForward= option, which defaults to + "no". This means if networkd is used for an interface it is + no longer sufficient to set the global sysctl option to turn + on IP forwarding! Instead, the .network file option + IPForward= needs to be turned on! Note that the + implementation of this behaviour was broken in v219 and has + been fixed in v220. + + * Many bonding and vxlan options are now configurable in + systemd-networkd. + + * systemd-nspawn gained a new --property= setting to set unit + properties for the container scope. This is useful for + setting resource parameters (e.g. "CPUShares=500") on + containers started from the command line. + + * systemd-nspawn gained a new --private-users= switch to make + use of user namespacing available on recent Linux kernels. + + * systemd-nspawn may now be called as part of a shell pipeline + in which case the pipes used for stdin and stdout are passed + directly to the process invoked in the container, without + indirection via a pseudo tty. + + * systemd-nspawn gained a new switch to control the UNIX + signal to use when killing the init process of the container + when shutting down. + + * systemd-nspawn gained a new --overlay= switch for mounting + overlay file systems into the container using the new kernel + overlayfs support. + + * When a container image is imported via systemd-importd and + the host file system is not btrfs, a loopback block device + file is created in /var/lib/machines.raw with a btrfs file + system inside. It is then mounted to /var/lib/machines to + enable btrfs features for container management. The loopback + file and btrfs file system is grown as needed when container + images are imported via systemd-importd. + + * systemd-machined/systemd-importd gained support for btrfs + quota, to enforce container disk space limits on disk. This + is exposed in "machinectl set-limit". + + * systemd-importd now can import containers from local .tar, + .raw and .qcow2 images, and export them to .tar and .raw. It + can also import dkr v2 images now from the network (on top + of v1 as before). + + * systemd-importd gained support for verifying downloaded + images with gpg2 (previously only gpg1 was supported). + + * systemd-machined, systemd-logind, systemd: most bus calls are + now accessible to unprivileged processes via polkit. Also, + systemd-logind will now allow users to kill their own sessions + without further privileges or authorization. + + * systemd-shutdownd has been removed. This service was + previously responsible for implementing scheduled shutdowns + as exposed in /usr/bin/shutdown's time parameter. This + functionality has now been moved into systemd-logind and is + accessible via a bus interface. + + * "systemctl reboot" gained a new switch --firmware-setup that + can be used to reboot into the EFI firmware setup, if that + is available. systemd-logind now exposes an API on the bus + to trigger such reboots, in case graphical desktop UIs want + to cover this functionality. + + * "systemctl enable", "systemctl disable" and "systemctl mask" + now support a new "--now" switch. If specified the units + that are enabled will also be started, and the ones + disabled/masked also stopped. + + * The Gummiboot EFI boot loader tool has been merged into + systemd, and renamed to "systemd-boot". The bootctl tool has been + updated to support systemd-boot. + + * An EFI kernel stub has been added that may be used to create + kernel EFI binaries that contain not only the actual kernel, + but also an initrd, boot splash, command line and OS release + information. This combined binary can then be signed as a + single image, so that the firmware can verify it all in one + step. systemd-boot has special support for EFI binaries created + like this and can extract OS release information from them + and show them in the boot menu. This functionality is useful + to implement cryptographically verified boot schemes. + + * Optional support has been added to systemd-fsck to pass + fsck's progress report to an AF_UNIX socket in the file + system. + + * udev will no longer create device symlinks for all block + devices by default. A blacklist for excluding special block + devices from this logic has been turned into a whitelist + that requires picking block devices explicitly that require + device symlinks. + + * A new (currently still internal) API sd-device.h has been + added to libsystemd. This modernized API is supposed to + replace libudev eventually. In fact, already much of libudev + is now just a wrapper around sd-device.h. + + * A new hwdb database for storing metadata about pointing + stick devices has been added. + + * systemd-tmpfiles gained support for setting file attributes + similar to the "chattr" tool with new 'h' and 'H' lines. + + * systemd-journald will no longer unconditionally set the + btrfs NOCOW flag on new journal files. This is instead done + with tmpfiles snippet using the new 'h' line type. This + allows easy disabling of this logic, by masking the + journal-nocow.conf tmpfiles file. + + * systemd-journald will now translate audit message types to + human readable identifiers when writing them to the + journal. This should improve readability of audit messages. + + * The LUKS logic gained support for the offset= and skip= + options in /etc/crypttab, as previously implemented by + Debian. + + * /usr/lib/os-release gained a new optional field VARIANT= for + distributions that support multiple variants (such as a + desktop edition, a server edition, ...) + + Contributions from: Aaro Koskinen, Adam Goode, Alban Crequy, + Alberto Fanjul Alonso, Alexander Sverdlin, Alex Puchades, Alin + Rauta, Alison Chaiken, Andrew Jones, Arend van Spriel, + Benedikt Morbach, Benjamin Franzke, Benjamin Tissoires, Blaž + Tomažič, Chris Morgan, Chris Morin, Colin Walters, Cristian + Rodríguez, Daniel Buch, Daniel Drake, Daniele Medri, Daniel + Mack, Daniel Mustieles, daurnimator, Davide Bettio, David + Herrmann, David Strauss, Didier Roche, Dimitri John Ledkov, + Eric Cook, Gavin Li, Goffredo Baroncelli, Hannes Reinecke, + Hans de Goede, Hans-Peter Deifel, Harald Hoyer, Iago López + Galeiras, Ivan Shapovalov, Jan Engelhardt, Jan Janssen, Jan + Pazdziora, Jan Synacek, Jasper St. Pierre, Jay Faulkner, John + Paul Adrian Glaubitz, Jonathon Gilbert, Karel Zak, Kay + Sievers, Koen Kooi, Lennart Poettering, Lubomir Rintel, Lucas + De Marchi, Lukas Nykryn, Lukas Rusak, Lukasz Skalski, Łukasz + Stelmach, Mantas Mikulėnas, Marc-Antoine Perennou, Marcel + Holtmann, Martin Pitt, Mathieu Chevrier, Matthew Garrett, + Michael Biebl, Michael Marineau, Michael Olbrich, Michal + Schmidt, Michal Sekletar, Mirco Tischler, Nir Soffer, Patrik + Flykt, Pavel Odvody, Peter Hutterer, Peter Lemenkov, Peter + Waller, Piotr Drąg, Raul Gutierrez S, Richard Maw, Ronny + Chevalier, Ross Burton, Sebastian Rasmussen, Sergey Ptashnick, + Seth Jennings, Shawn Landden, Simon Farnsworth, Stefan Junker, + Stephen Gallagher, Susant Sahani, Sylvain Plantefève, Thomas + Haller, Thomas Hindoe Paaboel Andersen, Tobias Hunger, Tom + Gundersen, Torstein Husebø, Umut Tezduyar Lindskog, Will + Woods, Zachary Cook, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2015-05-22 + +CHANGES WITH 219: + + * Introduce a new API "sd-hwdb.h" for querying the hardware + metadata database. With this minimal interface one can query + and enumerate the udev hwdb, decoupled from the old libudev + library. libudev's interface for this is now only a wrapper + around sd-hwdb. A new tool systemd-hwdb has been added to + interface with and update the database. + + * When any of systemd's tools copies files (for example due to + tmpfiles' C lines) a btrfs reflink will attempted first, + before bytewise copying is done. + + * systemd-nspawn gained a new --ephemeral switch. When + specified a btrfs snapshot is taken of the container's root + directory, and immediately removed when the container + terminates again. Thus, a container can be started whose + changes never alter the container's root directory, and are + lost on container termination. This switch can also be used + for starting a container off the root file system of the + host without affecting the host OS. This switch is only + available on btrfs file systems. + + * systemd-nspawn gained a new --template= switch. It takes the + path to a container tree to use as template for the tree + specified via --directory=, should that directory be + missing. This allows instantiating containers dynamically, + on first run. This switch is only available on btrfs file + systems. + + * When a .mount unit refers to a mount point on which multiple + mounts are stacked, and the .mount unit is stopped all of + the stacked mount points will now be unmounted until no + mount point remains. + + * systemd now has an explicit notion of supported and + unsupported unit types. Jobs enqueued for unsupported unit + types will now fail with an "unsupported" error code. More + specifically .swap, .automount and .device units are not + supported in containers, .busname units are not supported on + non-kdbus systems. .swap and .automount are also not + supported if their respective kernel compile time options + are disabled. + + * machinectl gained support for two new "copy-from" and + "copy-to" commands for copying files from a running + container to the host or vice versa. + + * machinectl gained support for a new "bind" command to bind + mount host directories into local containers. This is + currently only supported for nspawn containers. + + * networkd gained support for configuring bridge forwarding + database entries (fdb) from .network files. + + * A new tiny daemon "systemd-importd" has been added that can + download container images in tar, raw, qcow2 or dkr formats, + and make them available locally in /var/lib/machines, so + that they can run as nspawn containers. The daemon can GPG + verify the downloads (not supported for dkr, since it has no + provisions for verifying downloads). It will transparently + decompress bz2, xz, gzip compressed downloads if necessary, + and restore sparse files on disk. The daemon uses privilege + separation to ensure the actual download logic runs with + fewer privileges than the daemon itself. machinectl has + gained new commands "pull-tar", "pull-raw" and "pull-dkr" to + make the functionality of importd available to the + user. With this in place the Fedora and Ubuntu "Cloud" + images can be downloaded and booted as containers unmodified + (the Fedora images lack the appropriate GPG signature files + currently, so they cannot be verified, but this will change + soon, hopefully). Note that downloading images is currently + only fully supported on btrfs. + + * machinectl is now able to list container images found in + /var/lib/machines, along with some metadata about sizes of + disk and similar. If the directory is located on btrfs and + quota is enabled, this includes quota display. A new command + "image-status" has been added that shows additional + information about images. + + * machinectl is now able to clone container images + efficiently, if the underlying file system (btrfs) supports + it, with the new "machinectl clone" command. It also + gained commands for renaming and removing images, as well as + marking them read-only or read-write (supported also on + legacy file systems). + + * networkd gained support for collecting LLDP network + announcements, from hardware that supports this. This is + shown in networkctl output. + + * systemd-run gained support for a new -t (--pty) switch for + invoking a binary on a pty whose input and output is + connected to the invoking terminal. This allows executing + processes as system services while interactively + communicating with them via the terminal. Most interestingly + this is supported across container boundaries. Invoking + "systemd-run -t /bin/bash" is an alternative to running a + full login session, the difference being that the former + will not register a session, nor go through the PAM session + setup. + + * tmpfiles gained support for a new "v" line type for creating + btrfs subvolumes. If the underlying file system is a legacy + file system, this automatically degrades to creating a + normal directory. Among others /var/lib/machines is now + created like this at boot, should it be missing. + + * The directory /var/lib/containers/ has been deprecated and + been replaced by /var/lib/machines. The term "machines" has + been used in the systemd context as generic term for both + VMs and containers, and hence appears more appropriate for + this, as the directory can also contain raw images bootable + via qemu/kvm. + + * systemd-nspawn when invoked with -M but without --directory= + or --image= is now capable of searching for the container + root directory, subvolume or disk image automatically, in + /var/lib/machines. systemd-nspawn@.service has been updated + to make use of this, thus allowing it to be used for raw + disk images, too. + + * A new machines.target unit has been introduced that is + supposed to group all containers/VMs invoked as services on + the system. systemd-nspawn@.service has been updated to + integrate with that. + + * machinectl gained a new "start" command, for invoking a + container as a service. "machinectl start foo" is mostly + equivalent to "systemctl start systemd-nspawn@foo.service", + but handles escaping in a nicer way. + + * systemd-nspawn will now mount most of the cgroupfs tree + read-only into each container, with the exception of the + container's own subtree in the name=systemd hierarchy. + + * journald now sets the special FS_NOCOW file flag for its + journal files. This should improve performance on btrfs, by + avoiding heavy fragmentation when journald's write-pattern + is used on COW file systems. It degrades btrfs' data + integrity guarantees for the files to the same levels as for + ext3/ext4 however. This should be OK though as journald does + its own data integrity checks and all its objects are + checksummed on disk. Also, journald should handle btrfs disk + full events a lot more gracefully now, by processing SIGBUS + errors, and not relying on fallocate() anymore. + + * When journald detects that journal files it is writing to + have been deleted it will immediately start new journal + files. + + * systemd now provides a way to store file descriptors + per-service in PID 1. This is useful for daemons to ensure + that fds they require are not lost during a daemon + restart. The fds are passed to the daemon on the next + invocation in the same way socket activation fds are + passed. This is now used by journald to ensure that the + various sockets connected to all the system's stdout/stderr + are not lost when journald is restarted. File descriptors + may be stored in PID 1 via the sd_pid_notify_with_fds() API, + an extension to sd_notify(). Note that a limit is enforced + on the number of fds a service can store in PID 1, and it + defaults to 0, so that no fds may be stored, unless this is + explicitly turned on. + + * The default TERM variable to use for units connected to a + terminal, when no other value is explicitly is set is now + vt220 rather than vt102. This should be fairly safe still, + but allows PgUp/PgDn work. + + * The /etc/crypttab option header= as known from Debian is now + supported. + + * "loginctl user-status" and "loginctl session-status" will + now show the last 10 lines of log messages of the + user/session following the status output. Similar, + "machinectl status" will show the last 10 log lines + associated with a virtual machine or container + service. (Note that this is usually not the log messages + done in the VM/container itself, but simply what the + container manager logs. For nspawn this includes all console + output however.) + + * "loginctl session-status" without further argument will now + show the status of the session of the caller. Similar, + "lock-session", "unlock-session", "activate", + "enable-linger", "disable-linger" may now be called without + session/user parameter in which case they apply to the + caller's session/user. + + * An X11 session scriptlet is now shipped that uploads + $DISPLAY and $XAUTHORITY into the environment of the systemd + --user daemon if a session begins. This should improve + compatibility with X11 enabled applications run as systemd + user services. + + * Generators are now subject to masking via /etc and /run, the + same way as unit files. + + * networkd .network files gained support for configuring + per-link IPv4/IPv6 packet forwarding as well as IPv4 + masquerading. This is by default turned on for veth links to + containers, as registered by systemd-nspawn. This means that + nspawn containers run with --network-veth will now get + automatic routed access to the host's networks without any + further configuration or setup, as long as networkd runs on + the host. + + * systemd-nspawn gained the --port= (-p) switch to expose TCP + or UDP posts of a container on the host. With this in place + it is possible to run containers with private veth links + (--network-veth), and have their functionality exposed on + the host as if their services were running directly on the + host. + + * systemd-nspawn's --network-veth switch now gained a short + version "-n", since with the changes above it is now truly + useful out-of-the-box. The systemd-nspawn@.service has been + updated to make use of it too by default. + + * systemd-nspawn will now maintain a per-image R/W lock, to + ensure that the same image is not started more than once + writable. (It's OK to run an image multiple times + simultaneously in read-only mode.) + + * systemd-nspawn's --image= option is now capable of + dissecting and booting MBR and GPT disk images that contain + only a single active Linux partition. Previously it + supported only GPT disk images with proper GPT type + IDs. This allows running cloud images from major + distributions directly with systemd-nspawn, without + modification. + + * In addition to collecting mouse dpi data in the udev + hardware database, there's now support for collecting angle + information for mouse scroll wheels. The database is + supposed to guarantee similar scrolling behavior on mice + that it knows about. There's also support for collecting + information about Touchpad types. + + * udev's input_id built-in will now also collect touch screen + dimension data and attach it to probed devices. + + * /etc/os-release gained support for a Distribution Privacy + Policy link field. + + * networkd gained support for creating "ipvlan", "gretap", + "ip6gre", "ip6gretap" and "ip6tnl" network devices. + + * systemd-tmpfiles gained support for "a" lines for setting + ACLs on files. + + * systemd-nspawn will now mount /tmp in the container to + tmpfs, automatically. + + * systemd now exposes the memory.usage_in_bytes cgroup + attribute and shows it for each service in the "systemctl + status" output, if available. + + * When the user presses Ctrl-Alt-Del more than 7x within 2s an + immediate reboot is triggered. This useful if shutdown is + hung and is unable to complete, to expedite the + operation. Note that this kind of reboot will still unmount + all file systems, and hence should not result in fsck being + run on next reboot. + + * A .device unit for an optical block device will now be + considered active only when a medium is in the drive. Also, + mount units are now bound to their backing devices thus + triggering automatic unmounting when devices become + unavailable. With this in place systemd will now + automatically unmount left-over mounts when a CD-ROM is + ejected or an USB stick is yanked from the system. + + * networkd-wait-online now has support for waiting for + specific interfaces only (with globbing), and for giving up + after a configurable timeout. + + * networkd now exits when idle. It will be automatically + restarted as soon as interfaces show up, are removed or + change state. networkd will stay around as long as there is + at least one DHCP state machine or similar around, that keep + it non-idle. + + * networkd may now configure IPv6 link-local addressing in + addition to IPv4 link-local addressing. + + * The IPv6 "token" for use in SLAAC may now be configured for + each .network interface in networkd. + + * Routes configured with networkd may now be assigned a scope + in .network files. + + * networkd's [Match] sections now support globbing and lists + of multiple space-separated matches per item. + + Contributions from: Alban Crequy, Alin Rauta, Andrey Chaser, + Bastien Nocera, Bruno Bottazzini, Carlos Garnacho, Carlos + Morata Castillo, Chris Atkinson, Chris J. Arges, Christian + Kirbach, Christian Seiler, Christoph Brill, Colin Guthrie, + Colin Walters, Cristian Rodríguez, Daniele Medri, Daniel Mack, + Dave Reisner, David Herrmann, Djalal Harouni, Erik Auerswald, + Filipe Brandenburger, Frank Theile, Gabor Kelemen, Gabriel de + Perthuis, Harald Hoyer, Hui Wang, Ivan Shapovalov, Jan + Engelhardt, Jan Synacek, Jay Faulkner, Johannes Hölzl, Jonas + Ådahl, Jonathan Boulle, Josef Andersson, Kay Sievers, Ken + Werner, Lennart Poettering, Lucas De Marchi, Lukas Märdian, + Lukas Nykryn, Lukasz Skalski, Luke Shumaker, Mantas Mikulėnas, + Manuel Mendez, Marcel Holtmann, Marc Schmitzer, Marko + Myllynen, Martin Pitt, Maxim Mikityanskiy, Michael Biebl, + Michael Marineau, Michael Olbrich, Michal Schmidt, Mindaugas + Baranauskas, Moez Bouhlel, Naveen Kumar, Patrik Flykt, Paul + Martin, Peter Hutterer, Peter Mattern, Philippe De Swert, + Piotr Drąg, Rafael Ferreira, Rami Rosen, Robert Milasan, Ronny + Chevalier, Sangjung Woo, Sebastien Bacher, Sergey Ptashnick, + Shawn Landden, Stéphane Graber, Susant Sahani, Sylvain + Plantefève, Thomas Hindoe Paaboel Andersen, Tim JP, Tom + Gundersen, Topi Miettinen, Torstein Husebø, Umut Tezduyar + Lindskog, Veres Lajos, Vincent Batts, WaLyong Cho, Wieland + Hoffmann, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2015-02-16 + +CHANGES WITH 218: + + * When querying unit file enablement status (for example via + "systemctl is-enabled"), a new state "indirect" is now known + which indicates that a unit might not be enabled itself, but + another unit listed in its Also= setting might be. + + * Similar to the various existing ConditionXYZ= settings for + units, there are now matching AssertXYZ= settings. While + failing conditions cause a unit to be skipped, but its job + to succeed, failing assertions declared like this will cause + a unit start operation and its job to fail. + + * hostnamed now knows a new chassis type "embedded". + + * systemctl gained a new "edit" command. When used on a unit + file, this allows extending unit files with .d/ drop-in + configuration snippets or editing the full file (after + copying it from /usr/lib to /etc). This will invoke the + user's editor (as configured with $EDITOR), and reload the + modified configuration after editing. + + * "systemctl status" now shows the suggested enablement state + for a unit, as declared in the (usually vendor-supplied) + system preset files. + + * nss-myhostname will now resolve the single-label host name + "gateway" to the locally configured default IP routing + gateways, ordered by their metrics. This assigns a stable + name to the used gateways, regardless which ones are + currently configured. Note that the name will only be + resolved after all other name sources (if nss-myhostname is + configured properly) and should hence not negatively impact + systems that use the single-label host name "gateway" in + other contexts. + + * systemd-inhibit now allows filtering by mode when listing + inhibitors. + + * Scope and service units gained a new "Delegate" boolean + property, which, when set, allows processes running inside the + unit to further partition resources. This is primarily + useful for systemd user instances as well as container + managers. + + * journald will now pick up audit messages directly from + the kernel, and log them like any other log message. The + audit fields are split up and fully indexed. This means that + journalctl in many ways is now a (nicer!) alternative to + ausearch, the traditional audit client. Note that this + implements only a minimal audit client. If you want the + special audit modes like reboot-on-log-overflow, please use + the traditional auditd instead, which can be used in + parallel to journald. + + * The ConditionSecurity= unit file option now understands the + special string "audit" to check whether auditing is + available. + + * journalctl gained two new commands --vacuum-size= and + --vacuum-time= to delete old journal files until the + remaining ones take up no more than the specified size on disk, + or are not older than the specified time. + + * A new, native PPPoE library has been added to sd-network, + systemd's library of light-weight networking protocols. This + library will be used in a future version of networkd to + enable PPPoE communication without an external pppd daemon. + + * The busctl tool now understands a new "capture" verb that + works similar to "monitor", but writes a packet capture + trace to STDOUT that can be redirected to a file which is + compatible with libcap's capture file format. This can then + be loaded in Wireshark and similar tools to inspect bus + communication. + + * The busctl tool now understands a new "tree" verb that shows + the object trees of a specific service on the bus, or of all + services. + + * The busctl tool now understands a new "introspect" verb that + shows all interfaces and members of objects on the bus, + including their signature and values. This is particularly + useful to get more information about bus objects shown by + the new "busctl tree" command. + + * The busctl tool now understands new verbs "call", + "set-property" and "get-property" for invoking bus method + calls, setting and getting bus object properties in a + friendly way. + + * busctl gained a new --augment-creds= argument that controls + whether the tool shall augment credential information it + gets from the bus with data from /proc, in a possibly + race-ful way. + + * nspawn's --link-journal= switch gained two new values + "try-guest" and "try-host" that work like "guest" and + "host", but do not fail if the host has no persistent + journalling enabled. -j is now equivalent to + --link-journal=try-guest. + + * macvlan network devices created by nspawn will now have + stable MAC addresses. + + * A new SmackProcessLabel= unit setting has been added, which + controls the SMACK security label processes forked off by + the respective unit shall use. + + * If compiled with --enable-xkbcommon, systemd-localed will + verify x11 keymap settings by compiling the given keymap. It + will spew out warnings if the compilation fails. This + requires libxkbcommon to be installed. + + * When a coredump is collected, a larger number of metadata + fields is now collected and included in the journal records + created for it. More specifically, control group membership, + environment variables, memory maps, working directory, + chroot directory, /proc/$PID/status, and a list of open file + descriptors is now stored in the log entry. + + * The udev hwdb now contains DPI information for mice. For + details see: + + http://who-t.blogspot.de/2014/12/building-a-dpi-database-for-mice.html + + * All systemd programs that read standalone configuration + files in /etc now also support a corresponding series of + .conf.d configuration directories in /etc/, /run/, + /usr/local/lib/, /usr/lib/, and (if configured with + --enable-split-usr) /lib/. In particular, the following + configuration files now have corresponding configuration + directories: system.conf user.conf, logind.conf, + journald.conf, sleep.conf, bootchart.conf, coredump.conf, + resolved.conf, timesyncd.conf, journal-remote.conf, and + journal-upload.conf. Note that distributions should use the + configuration directories in /usr/lib/; the directories in + /etc/ are reserved for the system administrator. + + * systemd-rfkill will no longer take the rfkill device name + into account when storing rfkill state on disk, as the name + might be dynamically assigned and not stable. Instead, the + ID_PATH udev variable combined with the rfkill type (wlan, + bluetooth, ...) is used. + + * A new service systemd-machine-id-commit.service has been + added. When used on systems where /etc is read-only during + boot, and /etc/machine-id is not initialized (but an empty + file), this service will copy the temporary machine ID + created as replacement into /etc after the system is fully + booted up. This is useful for systems that are freshly + installed with a non-initialized machine ID, but should get + a fixed machine ID for subsequent boots. + + * networkd's .netdev files now provide a large set of + configuration parameters for VXLAN devices. Similarly, the + bridge port cost parameter is now configurable in .network + files. There's also new support for configuring IP source + routing. networkd .link files gained support for a new + OriginalName= match that is useful to match against the + original interface name the kernel assigned. .network files + may include MTU= and MACAddress= fields for altering the MTU + and MAC address while being connected to a specific network + interface. + + * The LUKS logic gained supported for configuring + UUID-specific key files. There's also new support for naming + LUKS device from the kernel command line, using the new + luks.name= argument. + + * Timer units may now be transiently created via the bus API + (this was previously already available for scope and service + units). In addition it is now possible to create multiple + transient units at the same time with a single bus call. The + "systemd-run" tool has been updated to make use of this for + running commands on a specified time, in at(1)-style. + + * tmpfiles gained support for "t" lines, for assigning + extended attributes to files. Among other uses this may be + used to assign SMACK labels to files. + + Contributions from: Alin Rauta, Alison Chaiken, Andrej + Manduch, Bastien Nocera, Chris Atkinson, Chris Leech, Chris + Mayo, Colin Guthrie, Colin Walters, Cristian Rodríguez, + Daniele Medri, Daniel Mack, Dan Williams, Dan Winship, Dave + Reisner, David Herrmann, Didier Roche, Felipe Sateler, Gavin + Li, Hans de Goede, Harald Hoyer, Iago López Galeiras, Ivan + Shapovalov, Jakub Filak, Jan Janssen, Jan Synacek, Joe + Lawrence, Josh Triplett, Kay Sievers, Lennart Poettering, + Lukas Nykryn, Łukasz Stelmach, Maciej Wereski, Mantas + Mikulėnas, Marcel Holtmann, Martin Pitt, Maurizio Lombardi, + Michael Biebl, Michael Chapman, Michael Marineau, Michal + Schmidt, Michal Sekletar, Olivier Brunel, Patrik Flykt, Peter + Hutterer, Przemyslaw Kedzierski, Rami Rosen, Ray Strode, + Richard Schütz, Richard W.M. Jones, Ronny Chevalier, Ross + Lagerwall, Sean Young, Stanisław Pitucha, Susant Sahani, + Thomas Haller, Thomas Hindoe Paaboel Andersen, Tom Gundersen, + Torstein Husebø, Umut Tezduyar Lindskog, Vicente Olivert + Riera, WaLyong Cho, Wesley Dawson, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2014-12-10 + +CHANGES WITH 217: + + * journalctl gained the new options -t/--identifier= to match + on the syslog identifier (aka "tag"), as well as --utc to + show log timestamps in the UTC timezone. journalctl now also + accepts -n/--lines=all to disable line capping in a pager. + + * journalctl gained a new switch, --flush, that synchronously + flushes logs from /run/log/journal to /var/log/journal if + persistent storage is enabled. systemd-journal-flush.service + now waits until the operation is complete. + + * Services can notify the manager before they start a reload + (by sending RELOADING=1) or shutdown (by sending + STOPPING=1). This allows the manager to track and show the + internal state of daemons and closes a race condition when + the process is still running but has closed its D-Bus + connection. + + * Services with Type=oneshot do not have to have any ExecStart + commands anymore. + + * User units are now loaded also from + $XDG_RUNTIME_DIR/systemd/user/. This is similar to the + /run/systemd/user directory that was already previously + supported, but is under the control of the user. + + * Job timeouts (i.e. timeouts on the time a job that is + queued stays in the run queue) can now optionally result in + immediate reboot or power-off actions (JobTimeoutAction= and + JobTimeoutRebootArgument=). This is useful on ".target" + units, to limit the maximum time a target remains + undispatched in the run queue, and to trigger an emergency + operation in such a case. This is now used by default to + turn off the system if boot-up (as defined by everything in + basic.target) hangs and does not complete for at least + 15min. Also, if power-off or reboot hang for at least 30min + an immediate power-off/reboot operation is triggered. This + functionality is particularly useful to increase reliability + on embedded devices, but also on laptops which might + accidentally get powered on when carried in a backpack and + whose boot stays stuck in a hard disk encryption passphrase + question. + + * systemd-logind can be configured to also handle lid switch + events even when the machine is docked or multiple displays + are attached (HandleLidSwitchDocked= option). + + * A helper binary and a service have been added which can be + used to resume from hibernation in the initramfs. A + generator will parse the resume= option on the kernel + command line to trigger resume. + + * A user console daemon systemd-consoled has been + added. Currently, it is a preview, and will so far open a + single terminal on each session of the user marked as + Desktop=systemd-console. + + * Route metrics can be specified for DHCP routes added by + systemd-networkd. + + * The SELinux context of socket-activated services can be set + from the information provided by the networking stack + (SELinuxContextFromNet= option). + + * Userspace firmware loading support has been removed and + the minimum supported kernel version is thus bumped to 3.7. + + * Timeout for udev workers has been increased from 1 to 3 + minutes, but a warning will be printed after 1 minute to + help diagnose kernel modules that take a long time to load. + + * Udev rules can now remove tags on devices with TAG-="foobar". + + * systemd's readahead implementation has been removed. In many + circumstances it didn't give expected benefits even for + rotational disk drives and was becoming less relevant in the + age of SSDs. As none of the developers has been using + rotating media anymore, and nobody stepped up to actively + maintain this component of systemd it has now been removed. + + * Swap units can use Options= to specify discard options. + Discard options specified for swaps in /etc/fstab are now + respected. + + * Docker containers are now detected as a separate type of + virtualization. + + * The Password Agent protocol gained support for queries where + the user input is shown, useful e.g. for user names. + systemd-ask-password gained a new --echo option to turn that + on. + + * The default sysctl.d/ snippets will now set: + + net.core.default_qdisc = fq_codel + + This selects Fair Queuing Controlled Delay as the default + queuing discipline for network interfaces. fq_codel helps + fight the network bufferbloat problem. It is believed to be + a good default with no tuning required for most workloads. + Downstream distributions may override this choice. On 10Gbit + servers that do not do forwarding, "fq" may perform better. + Systems without a good clocksource should use "pfifo_fast". + + * If kdbus is enabled during build a new option BusPolicy= is + available for service units, that allows locking all service + processes into a stricter bus policy, in order to limit + access to various bus services, or even hide most of them + from the service's view entirely. + + * networkctl will now show the .network and .link file + networkd has applied to a specific interface. + + * sd-login gained a new API call sd_session_get_desktop() to + query which desktop environment has been selected for a + session. + + * UNIX utmp support is now compile-time optional to support + legacy-free systems. + + * systemctl gained two new commands "add-wants" and + "add-requires" for pulling in units from specific targets + easily. + + * If the word "rescue" is specified on the kernel command line + the system will now boot into rescue mode (aka + rescue.target), which was previously available only by + specifying "1" or "systemd.unit=rescue.target" on the kernel + command line. This new kernel command line option nicely + mirrors the already existing "emergency" kernel command line + option. + + * New kernel command line options mount.usr=, mount.usrflags=, + mount.usrfstype= have been added that match root=, rootflags=, + rootfstype= but allow mounting a specific file system to + /usr. + + * The $NOTIFY_SOCKET is now also passed to control processes of + services, not only the main process. + + * This version reenables support for fsck's -l switch. This + means at least version v2.25 of util-linux is required for + operation, otherwise dead-locks on device nodes may + occur. Again: you need to update util-linux to at least + v2.25 when updating systemd to v217. + + * The "multi-seat-x" tool has been removed from systemd, as + its functionality has been integrated into X servers 1.16, + and the tool is hence redundant. It is recommended to update + display managers invoking this tool to simply invoke X + directly from now on, again. + + * Support for the new ALLOW_INTERACTIVE_AUTHORIZATION D-Bus + message flag has been added for all of systemd's polkit + authenticated method calls has been added. In particular this + now allows optional interactive authorization via polkit for + many of PID1's privileged operations such as unit file + enabling and disabling. + + * "udevadm hwdb --update" learnt a new switch "--usr" for + placing the rebuilt hardware database in /usr instead of + /etc. When used only hardware database entries stored in + /usr will be used, and any user database entries in /etc are + ignored. This functionality is useful for vendors to ship a + pre-built database on systems where local configuration is + unnecessary or unlikely. + + * Calendar time specifications in .timer units now also + understand the strings "semi-annually", "quarterly" and + "minutely" as shortcuts (in addition to the preexisting + "anually", "hourly", ...). + + * systemd-tmpfiles will now correctly create files in /dev + at boot which are marked for creation only at boot. It is + recommended to always create static device nodes with 'c!' + and 'b!', so that they are created only at boot and not + overwritten at runtime. + + * When the watchdog logic is used for a service (WatchdogSec=) + and the watchdog timeout is hit the service will now be + terminated with SIGABRT (instead of just SIGTERM), in order + to make sure a proper coredump and backtrace is + generated. This ensures that hanging services will result in + similar coredump/backtrace behaviour as services that hit a + segmentation fault. + + Contributions from: Andreas Henriksson, Andrei Borzenkov, + Angus Gibson, Ansgar Burchardt, Ben Wolsieffer, Brandon L. + Black, Christian Hesse, Cristian Rodríguez, Daniel Buch, + Daniele Medri, Daniel Mack, Dan Williams, Dave Reisner, David + Herrmann, David Sommerseth, David Strauss, Emil Renner + Berthing, Eric Cook, Evangelos Foutras, Filipe Brandenburger, + Gustavo Sverzut Barbieri, Hans de Goede, Harald Hoyer, Hristo + Venev, Hugo Grostabussiat, Ivan Shapovalov, Jan Janssen, Jan + Synacek, Jonathan Liu, Juho Son, Karel Zak, Kay Sievers, Klaus + Purer, Koen Kooi, Lennart Poettering, Lukas Nykryn, Lukasz + Skalski, Łukasz Stelmach, Mantas Mikulėnas, Marcel Holtmann, + Marius Tessmann, Marko Myllynen, Martin Pitt, Michael Biebl, + Michael Marineau, Michael Olbrich, Michael Scherer, Michal + Schmidt, Michal Sekletar, Miroslav Lichvar, Patrik Flykt, + Philippe De Swert, Piotr Drąg, Rahul Sundaram, Richard + Weinberger, Robert Milasan, Ronny Chevalier, Ruben Kerkhof, + Santiago Vila, Sergey Ptashnick, Simon McVittie, Sjoerd + Simons, Stefan Brüns, Steven Allen, Steven Noonan, Susant + Sahani, Sylvain Plantefève, Thomas Hindoe Paaboel Andersen, + Timofey Titovets, Tobias Hunger, Tom Gundersen, Torstein + Husebø, Umut Tezduyar Lindskog, WaLyong Cho, Zbigniew + Jędrzejewski-Szmek + + — Berlin, 2014-10-28 + +CHANGES WITH 216: + + * timedated no longer reads NTP implementation unit names from + /usr/lib/systemd/ntp-units.d/*.list. Alternative NTP + implementations should add a + + Conflicts=systemd-timesyncd.service + + to their unit files to take over and replace systemd's NTP + default functionality. + + * systemd-sysusers gained a new line type "r" for configuring + which UID/GID ranges to allocate system users/groups + from. Lines of type "u" may now add an additional column + that specifies the home directory for the system user to be + created. Also, systemd-sysusers may now optionally read user + information from STDIN instead of a file. This is useful for + invoking it from RPM preinst scriptlets that need to create + users before the first RPM file is installed since these + files might need to be owned by them. A new + %sysusers_create_inline RPM macro has been introduced to do + just that. systemd-sysusers now updates the shadow files as + well as the user/group databases, which should enhance + compatibility with certain tools like grpck. + + * A number of bus APIs of PID 1 now optionally consult polkit to + permit access for otherwise unprivileged clients under certain + conditions. Note that this currently doesn't support + interactive authentication yet, but this is expected to be + added eventually, too. + + * /etc/machine-info now has new fields for configuring the + deployment environment of the machine, as well as the + location of the machine. hostnamectl has been updated with + new command to update these fields. + + * systemd-timesyncd has been updated to automatically acquire + NTP server information from systemd-networkd, which might + have been discovered via DHCP. + + * systemd-resolved now includes a caching DNS stub resolver + and a complete LLMNR name resolution implementation. A new + NSS module "nss-resolve" has been added which can be used + instead of glibc's own "nss-dns" to resolve hostnames via + systemd-resolved. Hostnames, addresses and arbitrary RRs may + be resolved via systemd-resolved D-Bus APIs. In contrast to + the glibc internal resolver systemd-resolved is aware of + multi-homed system, and keeps DNS server and caches separate + and per-interface. Queries are sent simultaneously on all + interfaces that have DNS servers configured, in order to + properly handle VPNs and local LANs which might resolve + separate sets of domain names. systemd-resolved may acquire + DNS server information from systemd-networkd automatically, + which in turn might have discovered them via DHCP. A tool + "systemd-resolve-host" has been added that may be used to + query the DNS logic in resolved. systemd-resolved implements + IDNA and automatically uses IDNA or UTF-8 encoding depending + on whether classic DNS or LLMNR is used as transport. In the + next releases we intend to add a DNSSEC and mDNS/DNS-SD + implementation to systemd-resolved. + + * A new NSS module nss-mymachines has been added, that + automatically resolves the names of all local registered + containers to their respective IP addresses. + + * A new client tool "networkctl" for systemd-networkd has been + added. It currently is entirely passive and will query + networking configuration from udev, rtnetlink and networkd, + and present it to the user in a very friendly + way. Eventually, we hope to extend it to become a full + control utility for networkd. + + * .socket units gained a new DeferAcceptSec= setting that + controls the kernels' TCP_DEFER_ACCEPT sockopt for + TCP. Similarly, support for controlling TCP keep-alive + settings has been added (KeepAliveTimeSec=, + KeepAliveIntervalSec=, KeepAliveProbes=). Also, support for + turning off Nagle's algorithm on TCP has been added + (NoDelay=). + + * logind learned a new session type "web", for use in projects + like Cockpit which register web clients as PAM sessions. + + * timer units with at least one OnCalendar= setting will now + be started only after time-sync.target has been + reached. This way they will not elapse before the system + clock has been corrected by a local NTP client or + similar. This is particular useful on RTC-less embedded + machines, that come up with an invalid system clock. + + * systemd-nspawn's --network-veth= switch should now result in + stable MAC addresses for both the outer and the inner side + of the link. + + * systemd-nspawn gained a new --volatile= switch for running + container instances with /etc or /var unpopulated. + + * The kdbus client code has been updated to use the new Linux + 3.17 memfd subsystem instead of the old kdbus-specific one. + + * systemd-networkd's DHCP client and server now support + FORCERENEW. There are also new configuration options to + configure the vendor client identifier and broadcast mode + for DHCP. + + * systemd will no longer inform the kernel about the current + timezone, as this is necessarily incorrect and racy as the + kernel has no understanding of DST and similar + concepts. This hence means FAT timestamps will be always + considered UTC, similar to what Android is already + doing. Also, when the RTC is configured to the local time + (rather than UTC) systemd will never synchronize back to it, + as this might confuse Windows at a later boot. + + * systemd-analyze gained a new command "verify" for offline + validation of unit files. + + * systemd-networkd gained support for a couple of additional + settings for bonding networking setups. Also, the metric for + statically configured routes may now be configured. For + network interfaces where this is appropriate the peer IP + address may now be configured. + + * systemd-networkd's DHCP client will no longer request + broadcasting by default, as this tripped up some networks. + For hardware where broadcast is required the feature should + be switched back on using RequestBroadcast=yes. + + * systemd-networkd will now set up IPv4LL addresses (when + enabled) even if DHCP is configured successfully. + + * udev will now default to respect network device names given + by the kernel when the kernel indicates that these are + predictable. This behavior can be tweaked by changing + NamePolicy= in the relevant .link file. + + * A new library systemd-terminal has been added that + implements full TTY stream parsing and rendering. This + library is supposed to be used later on for implementing a + full userspace VT subsystem, replacing the current kernel + implementation. + + * A new tool systemd-journal-upload has been added to push + journal data to a remote system running + systemd-journal-remote. + + * journald will no longer forward all local data to another + running syslog daemon. This change has been made because + rsyslog (which appears to be the most commonly used syslog + implementation these days) no longer makes use of this, and + instead pulls the data out of the journal on its own. Since + forwarding the messages to a non-existent syslog server is + more expensive than we assumed we have now turned this + off. If you run a syslog server that is not a recent rsyslog + version, you have to turn this option on again + (ForwardToSyslog= in journald.conf). + + * journald now optionally supports the LZ4 compressor for + larger journal fields. This compressor should perform much + better than XZ which was the previous default. + + * machinectl now shows the IP addresses of local containers, + if it knows them, plus the interface name of the container. + + * A new tool "systemd-escape" has been added that makes it + easy to escape strings to build unit names and similar. + + * sd_notify() messages may now include a new ERRNO= field + which is parsed and collected by systemd and shown among the + "systemctl status" output for a service. + + * A new component "systemd-firstboot" has been added that + queries the most basic systemd information (timezone, + hostname, root password) interactively on first + boot. Alternatively it may also be used to provision these + things offline on OS images installed into directories. + + * The default sysctl.d/ snippets will now set + + net.ipv4.conf.default.promote_secondaries=1 + + This has the benefit of no flushing secondary IP addresses + when primary addresses are removed. + + Contributions from: Ansgar Burchardt, Bastien Nocera, Colin + Walters, Dan Dedrick, Daniel Buch, Daniel Korostil, Daniel + Mack, Dan Williams, Dave Reisner, David Herrmann, Denis + Kenzior, Eelco Dolstra, Eric Cook, Hannes Reinecke, Harald + Hoyer, Hong Shick Pak, Hui Wang, Jean-André Santoni, Jóhann + B. Guðmundsson, Jon Severinsson, Karel Zak, Kay Sievers, Kevin + Wells, Lennart Poettering, Lukas Nykryn, Mantas Mikulėnas, + Marc-Antoine Perennou, Martin Pitt, Michael Biebl, Michael + Marineau, Michael Olbrich, Michal Schmidt, Michal Sekletar, + Miguel Angel Ajo, Mike Gilbert, Olivier Brunel, Robert + Schiele, Ronny Chevalier, Simon McVittie, Sjoerd Simons, Stef + Walter, Steven Noonan, Susant Sahani, Tanu Kaskinen, Thomas + Blume, Thomas Hindoe Paaboel Andersen, Timofey Titovets, + Tobias Geerinckx-Rice, Tomasz Torcz, Tom Gundersen, Umut + Tezduyar Lindskog, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2014-08-19 + +CHANGES WITH 215: + + * A new tool systemd-sysusers has been added. This tool + creates system users and groups in /etc/passwd and + /etc/group, based on static declarative system user/group + definitions in /usr/lib/sysusers.d/. This is useful to + enable factory resets and volatile systems that boot up with + an empty /etc directory, and thus need system users and + groups created during early boot. systemd now also ships + with two default sysusers.d/ files for the most basic + users and groups systemd and the core operating system + require. + + * A new tmpfiles snippet has been added that rebuilds the + essential files in /etc on boot, should they be missing. + + * A directive for ensuring automatic clean-up of + /var/cache/man/ has been removed from the default + configuration. This line should now be shipped by the man + implementation. The necessary change has been made to the + man-db implementation. Note that you need to update your man + implementation to one that ships this line, otherwise no + automatic clean-up of /var/cache/man will take place. + + * A new condition ConditionNeedsUpdate= has been added that + may conditionalize services to only run when /etc or /var + are "older" than the vendor operating system resources in + /usr. This is useful for reconstructing or updating /etc + after an offline update of /usr or a factory reset, on the + next reboot. Services that want to run once after such an + update or reset should use this condition and order + themselves before the new systemd-update-done.service, which + will mark the two directories as fully updated. A number of + service files have been added making use of this, to rebuild + the udev hardware database, the journald message catalog and + dynamic loader cache (ldconfig). The systemd-sysusers tool + described above also makes use of this now. With this in + place it is now possible to start up a minimal operating + system with /etc empty cleanly. For more information on the + concepts involved see this recent blog story: + + http://0pointer.de/blog/projects/stateless.html + + * A new system group "input" has been introduced, and all + input device nodes get this group assigned. This is useful + for system-level software to get access to input devices. It + complements what is already done for "audio" and "video". + + * systemd-networkd learnt minimal DHCPv4 server support in + addition to the existing DHCPv4 client support. It also + learnt DHCPv6 client and IPv6 Router Solicitation client + support. The DHCPv4 client gained support for static routes + passed in from the server. Note that the [DHCPv4] section + known in older systemd-networkd versions has been renamed to + [DHCP] and is now also used by the DHCPv6 client. Existing + .network files using settings of this section should be + updated, though compatibility is maintained. Optionally, the + client hostname may now be sent to the DHCP server. + + * networkd gained support for vxlan virtual networks as well + as tun/tap and dummy devices. + + * networkd gained support for automatic allocation of address + ranges for interfaces from a system-wide pool of + addresses. This is useful for dynamically managing a large + number of interfaces with a single network configuration + file. In particular this is useful to easily assign + appropriate IP addresses to the veth links of a large number + of nspawn instances. + + * RPM macros for processing sysusers, sysctl and binfmt + drop-in snippets at package installation time have been + added. + + * The /etc/os-release file should now be placed in + /usr/lib/os-release. The old location is automatically + created as symlink. /usr/lib is the more appropriate + location of this file, since it shall actually describe the + vendor operating system shipped in /usr, and not the + configuration stored in /etc. + + * .mount units gained a new boolean SloppyOptions= setting + that maps to mount(8)'s -s option which enables permissive + parsing of unknown mount options. + + * tmpfiles learnt a new "L+" directive which creates a symlink + but (unlike "L") deletes a pre-existing file first, should + it already exist and not already be the correct + symlink. Similarly, "b+", "c+" and "p+" directives have been + added as well, which create block and character devices, as + well as fifos in the filesystem, possibly removing any + pre-existing files of different types. + + * For tmpfiles' "L", "L+", "C" and "C+" directives the final + 'argument' field (which so far specified the source to + symlink/copy the files from) is now optional. If omitted the + same file os copied from /usr/share/factory/ suffixed by the + full destination path. This is useful for populating /etc + with essential files, by copying them from vendor defaults + shipped in /usr/share/factory/etc. + + * A new command "systemctl preset-all" has been added that + applies the service preset settings to all installed unit + files. A new switch --preset-mode= has been added that + controls whether only enable or only disable operations + shall be executed. + + * A new command "systemctl is-system-running" has been added + that allows checking the overall state of the system, for + example whether it is fully up and running. + + * When the system boots up with an empty /etc, the equivalent + to "systemctl preset-all" is executed during early boot, to + make sure all default services are enabled after a factory + reset. + + * systemd now contains a minimal preset file that enables the + most basic services systemd ships by default. + + * Unit files' [Install] section gained a new DefaultInstance= + field for defining the default instance to create if a + template unit is enabled with no instance specified. + + * A new passive target cryptsetup-pre.target has been added + that may be used by services that need to make they run and + finish before the first LUKS cryptographic device is set up. + + * The /dev/loop-control and /dev/btrfs-control device nodes + are now owned by the "disk" group by default, opening up + access to this group. + + * systemd-coredump will now automatically generate a + stack trace of all core dumps taking place on the system, + based on elfutils' libdw library. This stack trace is logged + to the journal. + + * systemd-coredump may now optionally store coredumps directly + on disk (in /var/lib/systemd/coredump, possibly compressed), + instead of storing them unconditionally in the journal. This + mode is the new default. A new configuration file + /etc/systemd/coredump.conf has been added to configure this + and other parameters of systemd-coredump. + + * coredumpctl gained a new "info" verb to show details about a + specific coredump. A new switch "-1" has also been added + that makes sure to only show information about the most + recent entry instead of all entries. Also, as the tool is + generally useful now the "systemd-" prefix of the binary + name has been removed. Distributions that want to maintain + compatibility with the old name should add a symlink from + the old name to the new name. + + * journald's SplitMode= now defaults to "uid". This makes sure + that unprivileged users can access their own coredumps with + coredumpctl without restrictions. + + * New kernel command line options "systemd.wants=" (for + pulling an additional unit during boot), "systemd.mask=" + (for masking a specific unit for the boot), and + "systemd.debug-shell" (for enabling the debug shell on tty9) + have been added. This is implemented in the new generator + "systemd-debug-generator". + + * systemd-nspawn will now by default filter a couple of + syscalls for containers, among them those required for + kernel module loading, direct x86 IO port access, swap + management, and kexec. Most importantly though + open_by_handle_at() is now prohibited for containers, + closing a hole similar to a recently discussed vulnerability + in docker regarding access to files on file hierarchies the + container should normally not have access to. Note that, for + nspawn, we generally make no security claims anyway (and + this is explicitly documented in the man page), so this is + just a fix for one of the most obvious problems. + + * A new man page file-hierarchy(7) has been added that + contains a minimized, modernized version of the file system + layout systemd expects, similar in style to the FHS + specification or hier(5). A new tool systemd-path(1) has + been added to query many of these paths for the local + machine and user. + + * Automatic time-based clean-up of $XDG_RUNTIME_DIR is no + longer done. Since the directory now has a per-user size + limit, and is cleaned on logout this appears unnecessary, + in particular since this now brings the lifecycle of this + directory closer in line with how IPC objects are handled. + + * systemd.pc now exports a number of additional directories, + including $libdir (which is useful to identify the library + path for the primary architecture of the system), and a + couple of drop-in directories. + + * udev's predictable network interface names now use the dev_port + sysfs attribute, introduced in linux 3.15 instead of dev_id to + distinguish between ports of the same PCI function. dev_id should + only be used for ports using the same HW address, hence the need + for dev_port. + + * machined has been updated to export the OS version of a + container (read from /etc/os-release and + /usr/lib/os-release) on the bus. This is now shown in + "machinectl status" for a machine. + + * A new service setting RestartForceExitStatus= has been + added. If configured to a set of exit signals or process + return values, the service will be restarted when the main + daemon process exits with any of them, regardless of the + Restart= setting. + + * systemctl's -H switch for connecting to remote systemd + machines has been extended so that it may be used to + directly connect to a specific container on the + host. "systemctl -H root@foobar:waldi" will now connect as + user "root" to host "foobar", and then proceed directly to + the container named "waldi". Note that currently you have to + authenticate as user "root" for this to work, as entering + containers is a privileged operation. + + Contributions from: Andreas Henriksson, Benjamin Steinwender, + Carl Schaefer, Christian Hesse, Colin Ian King, Cristian + Rodríguez, Daniel Mack, Dave Reisner, David Herrmann, Eugene + Yakubovich, Filipe Brandenburger, Frederic Crozat, Hristo + Venev, Jan Engelhardt, Jonathan Boulle, Kay Sievers, Lennart + Poettering, Luke Shumaker, Mantas Mikulėnas, Marc-Antoine + Perennou, Marcel Holtmann, Michael Marineau, Michael Olbrich, + Michał Bartoszkiewicz, Michal Sekletar, Patrik Flykt, Ronan Le + Martret, Ronny Chevalier, Ruediger Oertel, Steven Noonan, + Susant Sahani, Thadeu Lima de Souza Cascardo, Thomas Hindoe + Paaboel Andersen, Tom Gundersen, Tom Hirst, Umut Tezduyar + Lindskog, Uoti Urpala, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2014-07-03 + +CHANGES WITH 214: + + * As an experimental feature, udev now tries to lock the + disk device node (flock(LOCK_SH|LOCK_NB)) while it + executes events for the disk or any of its partitions. + Applications like partitioning programs can lock the + disk device node (flock(LOCK_EX)) and claim temporary + device ownership that way; udev will entirely skip all event + handling for this disk and its partitions. If the disk + was opened for writing, the close will trigger a partition + table rescan in udev's "watch" facility, and if needed + synthesize "change" events for the disk and all its partitions. + This is now unconditionally enabled, and if it turns out to + cause major problems, we might turn it on only for specific + devices, or might need to disable it entirely. Device Mapper + devices are excluded from this logic. + + * We temporarily dropped the "-l" switch for fsck invocations, + since they collide with the flock() logic above. util-linux + upstream has been changed already to avoid this conflict, + and we will re-add "-l" as soon as util-linux with this + change has been released. + + * The dependency on libattr has been removed. Since a long + time, the extended attribute calls have moved to glibc, and + libattr is thus unnecessary. + + * Virtualization detection works without privileges now. This + means the systemd-detect-virt binary no longer requires + CAP_SYS_PTRACE file capabilities, and our daemons can run + with fewer privileges. + + * systemd-networkd now runs under its own "systemd-network" + user. It retains the CAP_NET_ADMIN, CAP_NET_BIND_SERVICE, + CAP_NET_BROADCAST, CAP_NET_RAW capabilities though, but + loses the ability to write to files owned by root this way. + + * Similarly, systemd-resolved now runs under its own + "systemd-resolve" user with no capabilities remaining. + + * Similarly, systemd-bus-proxyd now runs under its own + "systemd-bus-proxy" user with only CAP_IPC_OWNER remaining. + + * systemd-networkd gained support for setting up "veth" + virtual Ethernet devices for container connectivity, as well + as GRE and VTI tunnels. + + * systemd-networkd will no longer automatically attempt to + manually load kernel modules necessary for certain tunnel + transports. Instead, it is assumed the kernel loads them + automatically when required. This only works correctly on + very new kernels. On older kernels, please consider adding + the kernel modules to /etc/modules-load.d/ as a work-around. + + * The resolv.conf file systemd-resolved generates has been + moved to /run/systemd/resolve/. If you have a symlink from + /etc/resolv.conf, it might be necessary to correct it. + + * Two new service settings, ProtectHome= and ProtectSystem=, + have been added. When enabled, they will make the user data + (such as /home) inaccessible or read-only and the system + (such as /usr) read-only, for specific services. This allows + very light-weight per-service sandboxing to avoid + modifications of user data or system files from + services. These two new switches have been enabled for all + of systemd's long-running services, where appropriate. + + * Socket units gained new SocketUser= and SocketGroup= + settings to set the owner user and group of AF_UNIX sockets + and FIFOs in the file system. + + * Socket units gained a new RemoveOnStop= setting. If enabled, + all FIFOS and sockets in the file system will be removed + when the specific socket unit is stopped. + + * Socket units gained a new Symlinks= setting. It takes a list + of symlinks to create to file system sockets or FIFOs + created by the specific Unix sockets. This is useful to + manage symlinks to socket nodes with the same lifecycle as + the socket itself. + + * The /dev/log socket and /dev/initctl FIFO have been moved to + /run, and have been replaced by symlinks. This allows + connecting to these facilities even if PrivateDevices=yes is + used for a service (which makes /dev/log itself unavailable, + but /run is left). This also has the benefit of ensuring + that /dev only contains device nodes, directories and + symlinks, and nothing else. + + * sd-daemon gained two new calls sd_pid_notify() and + sd_pid_notifyf(). They are similar to sd_notify() and + sd_notifyf(), but allow overriding of the source PID of + notification messages if permissions permit this. This is + useful to send notify messages on behalf of a different + process (for example, the parent process). The + systemd-notify tool has been updated to make use of this + when sending messages (so that notification messages now + originate from the shell script invoking systemd-notify and + not the systemd-notify process itself. This should minimize + a race where systemd fails to associate notification + messages to services when the originating process already + vanished. + + * A new "on-abnormal" setting for Restart= has been added. If + set, it will result in automatic restarts on all "abnormal" + reasons for a process to exit, which includes unclean + signals, core dumps, timeouts and watchdog timeouts, but + does not include clean and unclean exit codes or clean + signals. Restart=on-abnormal is an alternative for + Restart=on-failure for services that shall be able to + terminate and avoid restarts on certain errors, by + indicating so with an unclean exit code. Restart=on-failure + or Restart=on-abnormal is now the recommended setting for + all long-running services. + + * If the InaccessibleDirectories= service setting points to a + mount point (or if there are any submounts contained within + it), it is now attempted to completely unmount it, to make + the file systems truly unavailable for the respective + service. + + * The ReadOnlyDirectories= service setting and + systemd-nspawn's --read-only parameter are now recursively + applied to all submounts, too. + + * Mount units may now be created transiently via the bus APIs. + + * The support for SysV and LSB init scripts has been removed + from the systemd daemon itself. Instead, it is now + implemented as a generator that creates native systemd units + from these scripts when needed. This enables us to remove a + substantial amount of legacy code from PID 1, following the + fact that many distributions only ship a very small number + of LSB/SysV init scripts nowadays. + + * Privileged Xen (dom0) domains are not considered + virtualization anymore by the virtualization detection + logic. After all, they generally have unrestricted access to + the hardware and usually are used to manage the unprivileged + (domU) domains. + + * systemd-tmpfiles gained a new "C" line type, for copying + files or entire directories. + + * systemd-tmpfiles "m" lines are now fully equivalent to "z" + lines. So far, they have been non-globbing versions of the + latter, and have thus been redundant. In future, it is + recommended to only use "z". "m" has hence been removed + from the documentation, even though it stays supported. + + * A tmpfiles snippet to recreate the most basic structure in + /var has been added. This is enough to create the /var/run → + /run symlink and create a couple of structural + directories. This allows systems to boot up with an empty or + volatile /var. Of course, while with this change, the core OS + now is capable with dealing with a volatile /var, not all + user services are ready for it. However, we hope that sooner + or later, many service daemons will be changed upstream so + that they are able to automatically create their necessary + directories in /var at boot, should they be missing. This is + the first step to allow state-less systems that only require + the vendor image for /usr to boot. + + * systemd-nspawn has gained a new --tmpfs= switch to mount an + empty tmpfs instance to a specific directory. This is + particularly useful for making use of the automatic + reconstruction of /var (see above), by passing --tmpfs=/var. + + * Access modes specified in tmpfiles snippets may now be + prefixed with "~", which indicates that they shall be masked + by whether the existing file or directory is currently + writable, readable or executable at all. Also, if specified, + the sgid/suid/sticky bits will be masked for all + non-directories. + + * A new passive target unit "network-pre.target" has been + added which is useful for services that shall run before any + network is configured, for example firewall scripts. + + * The "floppy" group that previously owned the /dev/fd* + devices is no longer used. The "disk" group is now used + instead. Distributions should probably deprecate usage of + this group. + + Contributions from: Camilo Aguilar, Christian Hesse, Colin Ian + King, Cristian Rodríguez, Daniel Buch, Dave Reisner, David + Strauss, Denis Tikhomirov, John, Jonathan Liu, Kay Sievers, + Lennart Poettering, Mantas Mikulėnas, Mark Eichin, Ronny + Chevalier, Susant Sahani, Thomas Blume, Thomas Hindoe Paaboel + Andersen, Tom Gundersen, Umut Tezduyar Lindskog, Zbigniew + Jędrzejewski-Szmek + + — Berlin, 2014-06-11 + +CHANGES WITH 213: + + * A new "systemd-timesyncd" daemon has been added for + synchronizing the system clock across the network. It + implements an SNTP client. In contrast to NTP + implementations such as chrony or the NTP reference server, + this only implements a client side, and does not bother with + the full NTP complexity, focusing only on querying time from + one remote server and synchronizing the local clock to + it. Unless you intend to serve NTP to networked clients or + want to connect to local hardware clocks, this simple NTP + client should be more than appropriate for most + installations. The daemon runs with minimal privileges, and + has been hooked up with networkd to only operate when + network connectivity is available. The daemon saves the + current clock to disk every time a new NTP sync has been + acquired, and uses this to possibly correct the system clock + early at bootup, in order to accommodate for systems that + lack an RTC such as the Raspberry Pi and embedded devices, + and to make sure that time monotonically progresses on these + systems, even if it is not always correct. To make use of + this daemon, a new system user and group "systemd-timesync" + needs to be created on installation of systemd. + + * The queue "seqnum" interface of libudev has been disabled, as + it was generally incompatible with device namespacing as + sequence numbers of devices go "missing" if the devices are + part of a different namespace. + + * "systemctl list-timers" and "systemctl list-sockets" gained + a --recursive switch for showing units of these types also + for all local containers, similar in style to the already + supported --recursive switch for "systemctl list-units". + + * A new RebootArgument= setting has been added for service + units, which may be used to specify a kernel reboot argument + to use when triggering reboots with StartLimitAction=. + + * A new FailureAction= setting has been added for service + units which may be used to specify an operation to trigger + when a service fails. This works similarly to + StartLimitAction=, but unlike it, controls what is done + immediately rather than only after several attempts to + restart the service in question. + + * hostnamed got updated to also expose the kernel name, + release, and version on the bus. This is useful for + executing commands like hostnamectl with the -H switch. + systemd-analyze makes use of this to properly display + details when running non-locally. + + * The bootchart tool can now show cgroup information in the + graphs it generates. + + * The CFS CPU quota cgroup attribute is now exposed for + services. The new CPUQuota= switch has been added for this + which takes a percentage value. Setting this will have the + result that a service may never get more CPU time than the + specified percentage, even if the machine is otherwise idle. + + * systemd-networkd learned IPIP and SIT tunnel support. + + * LSB init scripts exposing a dependency on $network will now + get a dependency on network-online.target rather than simply + network.target. This should bring LSB handling closer to + what it was on SysV systems. + + * A new fsck.repair= kernel option has been added to control + how fsck shall deal with unclean file systems at boot. + + * The (.ini) configuration file parser will now silently + ignore sections whose name begins with "X-". This may be + used to maintain application-specific extension sections in unit + files. + + * machined gained a new API to query the IP addresses of + registered containers. "machinectl status" has been updated + to show these addresses in its output. + + * A new call sd_uid_get_display() has been added to the + sd-login APIs for querying the "primary" session of a + user. The "primary" session of the user is elected from the + user's sessions and generally a graphical session is + preferred over a text one. + + * A minimal systemd-resolved daemon has been added. It + currently simply acts as a companion to systemd-networkd and + manages resolv.conf based on per-interface DNS + configuration, possibly supplied via DHCP. In the long run + we hope to extend this into a local DNSSEC enabled DNS and + mDNS cache. + + * The systemd-networkd-wait-online tool is now enabled by + default. It will delay network-online.target until a network + connection has been configured. The tool primarily integrates + with networkd, but will also make a best effort to make sense + of network configuration performed in some other way. + + * Two new service options StartupCPUShares= and + StartupBlockIOWeight= have been added that work similarly to + CPUShares= and BlockIOWeight= however only apply during + system startup. This is useful to prioritize certain services + differently during bootup than during normal runtime. + + * hostnamed has been changed to prefer the statically + configured hostname in /etc/hostname (unless set to + 'localhost' or empty) over any dynamic one supplied by + dhcp. With this change, the rules for picking the hostname + match more closely the rules of other configuration settings + where the local administrator's configuration in /etc always + overrides any other settings. + + Contributions from: Ali H. Caliskan, Alison Chaiken, Bas van + den Berg, Brandon Philips, Cristian Rodríguez, Daniel Buch, + Dan Kilman, Dave Reisner, David Härdeman, David Herrmann, + David Strauss, Dimitris Spingos, Djalal Harouni, Eelco + Dolstra, Evan Nemerson, Florian Albrechtskirchinger, Greg + Kroah-Hartman, Harald Hoyer, Holger Hans Peter Freyther, Jan + Engelhardt, Jani Nikula, Jason St. John, Jeffrey Clark, + Jonathan Boulle, Kay Sievers, Lennart Poettering, Lukas + Nykryn, Lukasz Skalski, Łukasz Stelmach, Mantas Mikulėnas, + Marcel Holtmann, Martin Pitt, Matthew Monaco, Michael + Marineau, Michael Olbrich, Michal Sekletar, Mike Gilbert, Nis + Martensen, Patrik Flykt, Philip Lorenz, poma, Ray Strode, + Reyad Attiyat, Robert Milasan, Scott Thrasher, Stef Walter, + Steven Siloti, Susant Sahani, Tanu Kaskinen, Thomas Bächler, + Thomas Hindoe Paaboel Andersen, Tom Gundersen, Umut Tezduyar + Lindskog, WaLyong Cho, Will Woods, Zbigniew + Jędrzejewski-Szmek + + — Beijing, 2014-05-28 + +CHANGES WITH 212: + + * When restoring the screen brightness at boot, stay away from + the darkest setting or from the lowest 5% of the available + range, depending on which is the larger value of both. This + should effectively protect the user from rebooting into a + black screen, should the brightness have been set to minimum + by accident. + + * sd-login gained a new sd_machine_get_class() call to + determine the class ("vm" or "container") of a machine + registered with machined. + + * sd-login gained new calls + sd_peer_get_{session,owner_uid,unit,user_unit,slice,machine_name}(), + to query the identity of the peer of a local AF_UNIX + connection. They operate similarly to their sd_pid_get_xyz() + counterparts. + + * PID 1 will now maintain a system-wide system state engine + with the states "starting", "running", "degraded", + "maintenance", "stopping". These states are bound to system + startup, normal runtime, runtime with at least one failed + service, rescue/emergency mode and system shutdown. This + state is shown in the "systemctl status" output when no unit + name is passed. It is useful to determine system state, in + particularly when doing so for many systems or containers at + once. + + * A new command "list-machines" has been added to "systemctl" + that lists all local OS containers and shows their system + state (see above), if systemd runs inside of them. + + * systemctl gained a new "-r" switch to recursively enumerate + units on all local containers, when used with the + "list-unit" command (which is the default one that is + executed when no parameters are specified). + + * The GPT automatic partition discovery logic will now honour + two GPT partition flags: one may be set on a partition to + cause it to be mounted read-only, and the other may be set + on a partition to ignore it during automatic discovery. + + * Two new GPT type UUIDs have been added for automatic root + partition discovery, for 32-bit and 64-bit ARM. This is not + particularly useful for discovering the root directory on + these architectures during bare-metal boots (since UEFI is + not common there), but still very useful to allow booting of + ARM disk images in nspawn with the -i option. + + * MAC addresses of interfaces created with nspawn's + --network-interface= switch will now be generated from the + machine name, and thus be stable between multiple invocations + of the container. + + * logind will now automatically remove all IPC objects owned + by a user if she or he fully logs out. This makes sure that + users who are logged out cannot continue to consume IPC + resources. This covers SysV memory, semaphores and message + queues as well as POSIX shared memory and message + queues. Traditionally, SysV and POSIX IPC had no lifecycle + limits. With this functionality, that is corrected. This may + be turned off by using the RemoveIPC= switch of logind.conf. + + * The systemd-machine-id-setup and tmpfiles tools gained a + --root= switch to operate on a specific root directory, + instead of /. + + * journald can now forward logged messages to the TTYs of all + logged in users ("wall"). This is the default for all + emergency messages now. + + * A new tool systemd-journal-remote has been added to stream + journal log messages across the network. + + * /sys/fs/cgroup/ is now mounted read-only after all cgroup + controller trees are mounted into it. Note that the + directories mounted beneath it are not read-only. This is a + security measure and is particularly useful because glibc + actually includes a search logic to pick any tmpfs it can + find to implement shm_open() if /dev/shm is not available + (which it might very well be in namespaced setups). + + * machinectl gained a new "poweroff" command to cleanly power + down a local OS container. + + * The PrivateDevices= unit file setting will now also drop the + CAP_MKNOD capability from the capability bound set, and + imply DevicePolicy=closed. + + * PrivateDevices=, PrivateNetwork= and PrivateTmp= is now used + comprehensively on all long-running systemd services where + this is appropriate. + + * systemd-udevd will now run in a disassociated mount + namespace. To mount directories from udev rules, make sure to + pull in mount units via SYSTEMD_WANTS properties. + + * The kdbus support gained support for uploading policy into + the kernel. sd-bus gained support for creating "monitoring" + connections that can eavesdrop into all bus communication + for debugging purposes. + + * Timestamps may now be specified in seconds since the UNIX + epoch Jan 1st, 1970 by specifying "@" followed by the value + in seconds. + + * Native tcpwrap support in systemd has been removed. tcpwrap + is old code, not really maintained anymore and has serious + shortcomings, and better options such as firewalls + exist. For setups that require tcpwrap usage, please + consider invoking your socket-activated service via tcpd, + like on traditional inetd. + + * A new system.conf configuration option + DefaultTimerAccuracySec= has been added that controls the + default AccuracySec= setting of .timer units. + + * Timer units gained a new WakeSystem= switch. If enabled, + timers configured this way will cause the system to resume + from system suspend (if the system supports that, which most + do these days). + + * Timer units gained a new Persistent= switch. If enabled, + timers configured this way will save to disk when they have + been last triggered. This information is then used on next + reboot to possible execute overdue timer events, that + could not take place because the system was powered off. + This enables simple anacron-like behaviour for timer units. + + * systemctl's "list-timers" will now also list the time a + timer unit was last triggered in addition to the next time + it will be triggered. + + * systemd-networkd will now assign predictable IPv4LL + addresses to its local interfaces. + + Contributions from: Brandon Philips, Daniel Buch, Daniel Mack, + Dave Reisner, David Herrmann, Gerd Hoffmann, Greg + Kroah-Hartman, Hendrik Brueckner, Jason St. John, Josh + Triplett, Kay Sievers, Lennart Poettering, Marc-Antoine + Perennou, Michael Marineau, Michael Olbrich, Miklos Vajna, + Patrik Flykt, poma, Sebastian Thorarensen, Thomas Bächler, + Thomas Hindoe Paaboel Andersen, Tomasz Torcz, Tom Gundersen, + Umut Tezduyar Lindskog, Wieland Hoffmann, Zbigniew + Jędrzejewski-Szmek + + — Berlin, 2014-03-25 + +CHANGES WITH 211: + + * A new unit file setting RestrictAddressFamilies= has been + added to restrict which socket address families unit + processes gain access to. This takes address family names + like "AF_INET" or "AF_UNIX", and is useful to minimize the + attack surface of services via exotic protocol stacks. This + is built on seccomp system call filters. + + * Two new unit file settings RuntimeDirectory= and + RuntimeDirectoryMode= have been added that may be used to + manage a per-daemon runtime directories below /run. This is + an alternative for setting up directory permissions with + tmpfiles snippets, and has the advantage that the runtime + directory's lifetime is bound to the daemon runtime and that + the daemon starts up with an empty directory each time. This + is particularly useful when writing services that drop + privileges using the User= or Group= setting. + + * The DeviceAllow= unit setting now supports globbing for + matching against device group names. + + * The systemd configuration file system.conf gained new + settings DefaultCPUAccounting=, DefaultBlockIOAccounting=, + DefaultMemoryAccounting= to globally turn on/off accounting + for specific resources (cgroups) for all units. These + settings may still be overridden individually in each unit + though. + + * systemd-gpt-auto-generator is now able to discover /srv and + root partitions in addition to /home and swap partitions. It + also supports LUKS-encrypted partitions now. With this in + place, automatic discovery of partitions to mount following + the Discoverable Partitions Specification + (https://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec) + is now a lot more complete. This allows booting without + /etc/fstab and without root= on the kernel command line on + systems prepared appropriately. + + * systemd-nspawn gained a new --image= switch which allows + booting up disk images and Linux installations on any block + device that follow the Discoverable Partitions Specification + (see above). This means that installations made with + appropriately updated installers may now be started and + deployed using container managers, completely + unmodified. (We hope that libvirt-lxc will add support for + this feature soon, too.) + + * systemd-nspawn gained a new --network-macvlan= setting to + set up a private macvlan interface for the + container. Similarly, systemd-networkd gained a new + Kind=macvlan setting in .netdev files. + + * systemd-networkd now supports configuring local addresses + using IPv4LL. + + * A new tool systemd-network-wait-online has been added to + synchronously wait for network connectivity using + systemd-networkd. + + * The sd-bus.h bus API gained a new sd_bus_track object for + tracking the lifecycle of bus peers. Note that sd-bus.h is + still not a public API though (unless you specify + --enable-kdbus on the configure command line, which however + voids your warranty and you get no API stability guarantee). + + * The $XDG_RUNTIME_DIR runtime directories for each user are + now individual tmpfs instances, which has the benefit of + introducing separate pools for each user, with individual + size limits, and thus making sure that unprivileged clients + can no longer negatively impact the system or other users by + filling up their $XDG_RUNTIME_DIR. A new logind.conf setting + RuntimeDirectorySize= has been introduced that allows + controlling the default size limit for all users. It + defaults to 10% of the available physical memory. This is no + replacement for quotas on tmpfs though (which the kernel + still does not support), as /dev/shm and /tmp are still + shared resources used by both the system and unprivileged + users. + + * logind will now automatically turn off automatic suspending + on laptop lid close when more than one display is + connected. This was previously expected to be implemented + individually in desktop environments (such as GNOME), + however has been added to logind now, in order to fix a + boot-time race where a desktop environment might not have + been started yet and thus not been able to take an inhibitor + lock at the time where logind already suspends the system + due to a closed lid. + + * logind will now wait at least 30s after each system + suspend/resume cycle, and 3min after system boot before + suspending the system due to a closed laptop lid. This + should give USB docking stations and similar enough time to + be probed and configured after system resume and boot in + order to then act as suspend blocker. + + * systemd-run gained a new --property= setting which allows + initialization of resource control properties (and others) + for the created scope or service unit. Example: "systemd-run + --property=BlockIOWeight=10 updatedb" may be used to run + updatedb at a low block IO scheduling weight. + + * systemd-run's --uid=, --gid=, --setenv=, --setenv= switches + now also work in --scope mode. + + * When systemd is compiled with kdbus support, basic support + for enforced policies is now in place. (Note that enabling + kdbus still voids your warranty and no API compatibility + promises are made.) + + Contributions from: Andrey Borzenkov, Ansgar Burchardt, Armin + K., Daniel Mack, Dave Reisner, David Herrmann, Djalal Harouni, + Harald Hoyer, Henrik Grindal Bakken, Jasper St. Pierre, Kay + Sievers, Kieran Clancy, Lennart Poettering, Lukas Nykryn, + Mantas Mikulėnas, Marcel Holtmann, Mark Oteiza, Martin Pitt, + Mike Gilbert, Peter Rajnoha, poma, Samuli Suominen, Stef + Walter, Susant Sahani, Tero Roponen, Thomas Andersen, Thomas + Bächler, Thomas Hindoe Paaboel Andersen, Tomasz Torcz, Tom + Gundersen, Umut Tezduyar Lindskog, Uoti Urpala, Zachary Cook, + Zbigniew Jędrzejewski-Szmek + + — Berlin, 2014-03-12 + +CHANGES WITH 210: + + * systemd will now relabel /dev after loading the SMACK policy + according to SMACK rules. + + * A new unit file option AppArmorProfile= has been added to + set the AppArmor profile for the processes of a unit. + + * A new condition check ConditionArchitecture= has been added + to conditionalize units based on the system architecture, as + reported by uname()'s "machine" field. + + * systemd-networkd now supports matching on the system + virtualization, architecture, kernel command line, host name + and machine ID. + + * logind is now a lot more aggressive when suspending the + machine due to a closed laptop lid. Instead of acting only + on the lid close action, it will continuously watch the lid + status and act on it. This is useful for laptops where the + power button is on the outside of the chassis so that it can + be reached without opening the lid (such as the Lenovo + Yoga). On those machines, logind will now immediately + re-suspend the machine if the power button has been + accidentally pressed while the laptop was suspended and in a + backpack or similar. + + * logind will now watch SW_DOCK switches and inhibit reaction + to the lid switch if it is pressed. This means that logind + will not suspend the machine anymore if the lid is closed + and the system is docked, if the laptop supports SW_DOCK + notifications via the input layer. Note that ACPI docking + stations do not generate this currently. Also note that this + logic is usually not fully sufficient and Desktop + Environments should take a lid switch inhibitor lock when an + external display is connected, as systemd will not watch + this on its own. + + * nspawn will now make use of the devices cgroup controller by + default, and only permit creation of and access to the usual + API device nodes like /dev/null or /dev/random, as well as + access to (but not creation of) the pty devices. + + * We will now ship a default .network file for + systemd-networkd that automatically configures DHCP for + network interfaces created by nspawn's --network-veth or + --network-bridge= switches. + + * systemd will now understand the usual M, K, G, T suffixes + according to SI conventions (i.e. to the base 1000) when + referring to throughput and hardware metrics. It will stay + with IEC conventions (i.e. to the base 1024) for software + metrics, according to what is customary according to + Wikipedia. We explicitly document which base applies for + each configuration option. + + * The DeviceAllow= setting in unit files now supports a syntax + to whitelist an entire group of devices node majors at once, + based on the /proc/devices listing. For example, with the + string "char-pts", it is now possible to whitelist all + current and future pseudo-TTYs at once. + + * sd-event learned a new "post" event source. Event sources of + this type are triggered by the dispatching of any event + source of a type that is not "post". This is useful for + implementing clean-up and check event sources that are + triggered by other work being done in the program. + + * systemd-networkd is no longer statically enabled, but uses + the usual [Install] sections so that it can be + enabled/disabled using systemctl. It still is enabled by + default however. + + * When creating a veth interface pair with systemd-nspawn, the + host side will now be prefixed with "vb-" if + --network-bridge= is used, and with "ve-" if --network-veth + is used. This way, it is easy to distinguish these cases on + the host, for example to apply different configuration to + them with systemd-networkd. + + * The compatibility libraries for libsystemd-journal.so, + libsystem-id128.so, libsystemd-login.so and + libsystemd-daemon.so do not make use of IFUNC + anymore. Instead, we now build libsystemd.so multiple times + under these alternative names. This means that the footprint + is drastically increased, but given that these are + transitional compatibility libraries, this should not matter + much. This change has been made necessary to support the ARM + platform for these compatibility libraries, as the ARM + toolchain is not really at the same level as the toolchain + for other architectures like x86 and does not support + IFUNC. Please make sure to use --enable-compat-libs only + during a transitional period! + + * The .include syntax has been deprecated and is not documented + anymore. Drop-in files in .d directories should be used instead. + + Contributions from: Andreas Fuchs, Armin K., Colin Walters, + Daniel Mack, Dave Reisner, David Herrmann, Djalal Harouni, + Holger Schurig, Jason A. Donenfeld, Jason St. John, Jasper + St. Pierre, Kay Sievers, Lennart Poettering, Łukasz Stelmach, + Marcel Holtmann, Michael Scherer, Michal Sekletar, Mike + Gilbert, Samuli Suominen, Thomas Bächler, Thomas Hindoe + Paaboel Andersen, Tom Gundersen, Umut Tezduyar Lindskog, + Zbigniew Jędrzejewski-Szmek + + — Berlin, 2014-02-24 + +CHANGES WITH 209: + + * A new component "systemd-networkd" has been added that can + be used to configure local network interfaces statically or + via DHCP. It is capable of bringing up bridges, VLANs, and + bonding. Currently, no hook-ups for interactive network + configuration are provided. Use this for your initrd, + container, embedded, or server setup if you need a simple, + yet powerful, network configuration solution. This + configuration subsystem is quite nifty, as it allows wildcard + hotplug matching in interfaces. For example, with a single + configuration snippet, you can configure that all Ethernet + interfaces showing up are automatically added to a bridge, + or similar. It supports link-sensing and more. + + * A new tool "systemd-socket-proxyd" has been added which can + act as a bidirectional proxy for TCP sockets. This is + useful for adding socket activation support to services that + do not actually support socket activation, including virtual + machines and the like. + + * Add a new tool to save/restore rfkill state on + shutdown/boot. + + * Save/restore state of keyboard backlights in addition to + display backlights on shutdown/boot. + + * udev learned a new SECLABEL{} construct to label device + nodes with a specific security label when they appear. For + now, only SECLABEL{selinux} is supported, but the syntax is + prepared for additional security frameworks. + + * udev gained a new scheme to configure link-level attributes + from files in /etc/systemd/network/*.link. These files can + match against MAC address, device path, driver name and type, + and will apply attributes like the naming policy, link speed, + MTU, duplex settings, Wake-on-LAN settings, MAC address, MAC + address assignment policy (randomized, ...). + + * The configuration of network interface naming rules for + "permanent interface names" has changed: a new NamePolicy= + setting in the [Link] section of .link files determines the + priority of possible naming schemes (onboard, slot, MAC, + path). The default value of this setting is determined by + /usr/lib/net/links/99-default.link. Old + 80-net-name-slot.rules udev configuration file has been + removed, so local configuration overriding this file should + be adapted to override 99-default.link instead. + + * When the User= switch is used in a unit file, also + initialize $SHELL= based on the user database entry. + + * systemd no longer depends on libdbus. All communication is + now done with sd-bus, systemd's low-level bus library + implementation. + + * kdbus support has been added to PID 1 itself. When kdbus is + enabled, this causes PID 1 to set up the system bus and + enable support for a new ".busname" unit type that + encapsulates bus name activation on kdbus. It works a little + bit like ".socket" units, except for bus names. A new + generator has been added that converts classic dbus1 service + activation files automatically into native systemd .busname + and .service units. + + * sd-bus: add a light-weight vtable implementation that allows + defining objects on the bus with a simple static const + vtable array of its methods, signals and properties. + + * systemd will not generate or install static dbus + introspection data anymore to /usr/share/dbus-1/interfaces, + as the precise format of these files is unclear, and + nothing makes use of it. + + * A proxy daemon is now provided to proxy clients connecting + via classic D-Bus AF_UNIX sockets to kdbus, to provide full + compatibility with classic D-Bus. + + * A bus driver implementation has been added that supports the + classic D-Bus bus driver calls on kdbus, also for + compatibility purposes. + + * A new API "sd-event.h" has been added that implements a + minimal event loop API built around epoll. It provides a + couple of features that direct epoll usage is lacking: + prioritization of events, scales to large numbers of timer + events, per-event timer slack (accuracy), system-wide + coalescing of timer events, exit handlers, watchdog + supervision support using systemd's sd_notify() API, child + process handling. + + * A new API "sd-rntl.h" has been added that provides an API + around the route netlink interface of the kernel, similar in + style to "sd-bus.h". + + * A new API "sd-dhcp-client.h" has been added that provides a + small DHCPv4 client-side implementation. This is used by + "systemd-networkd". + + * There is a new kernel command line option + "systemd.restore_state=0|1". When set to "0", none of the + systemd tools will restore saved runtime state to hardware + devices. More specifically, the rfkill and backlight states + are not restored. + + * The FsckPassNo= compatibility option in mount/service units + has been removed. The fstab generator will now add the + necessary dependencies automatically, and does not require + PID1's support for that anymore. + + * journalctl gained a new switch, --list-boots, that lists + recent boots with their times and boot IDs. + + * The various tools like systemctl, loginctl, timedatectl, + busctl, systemd-run, ... have gained a new switch "-M" to + connect to a specific, local OS container (as direct + connection, without requiring SSH). This works on any + container that is registered with machined, such as those + created by libvirt-lxc or nspawn. + + * systemd-run and systemd-analyze also gained support for "-H" + to connect to remote hosts via SSH. This is particularly + useful for systemd-run because it enables queuing of jobs + onto remote systems. + + * machinectl gained a new command "login" to open a getty + login in any local container. This works with any container + that is registered with machined (such as those created by + libvirt-lxc or nspawn), and which runs systemd inside. + + * machinectl gained a new "reboot" command that may be used to + trigger a reboot on a specific container that is registered + with machined. This works on any container that runs an init + system of some kind. + + * systemctl gained a new "list-timers" command to print a nice + listing of installed timer units with the times they elapse + next. + + * Alternative reboot() parameters may now be specified on the + "systemctl reboot" command line and are passed to the + reboot() system call. + + * systemctl gained a new --job-mode= switch to configure the + mode to queue a job with. This is a more generic version of + --fail, --irreversible, and --ignore-dependencies, which are + still available but not advertised anymore. + + * /etc/systemd/system.conf gained new settings to configure + various default timeouts of units, as well as the default + start limit interval and burst. These may still be overridden + within each Unit. + + * PID1 will now export on the bus profile data of the security + policy upload process (such as the SELinux policy upload to + the kernel). + + * journald: when forwarding logs to the console, include + timestamps (following the setting in + /sys/module/printk/parameters/time). + + * OnCalendar= in timer units now understands the special + strings "yearly" and "annually". (Both are equivalent) + + * The accuracy of timer units is now configurable with the new + AccuracySec= setting. It defaults to 1min. + + * A new dependency type JoinsNamespaceOf= has been added that + allows running two services within the same /tmp and network + namespace, if PrivateNetwork= or PrivateTmp= are used. + + * A new command "cat" has been added to systemctl. It outputs + the original unit file of a unit, and concatenates the + contents of additional "drop-in" unit file snippets, so that + the full configuration is shown. + + * systemctl now supports globbing on the various "list-xyz" + commands, like "list-units" or "list-sockets", as well as on + those commands which take multiple unit names. + + * journalctl's --unit= switch gained support for globbing. + + * All systemd daemons now make use of the watchdog logic so + that systemd automatically notices when they hang. + + * If the $container_ttys environment variable is set, + getty-generator will automatically spawn a getty for each + listed tty. This is useful for container managers to request + login gettys to be spawned on as many ttys as needed. + + * %h, %s, %U specifier support is not available anymore when + used in unit files for PID 1. This is because NSS calls are + not safe from PID 1. They stay available for --user + instances of systemd, and as special case for the root user. + + * loginctl gained a new "--no-legend" switch to turn off output + of the legend text. + + * The "sd-login.h" API gained three new calls: + sd_session_is_remote(), sd_session_get_remote_user(), + sd_session_get_remote_host() to query information about + remote sessions. + + * The udev hardware database now also carries vendor/product + information of SDIO devices. + + * The "sd-daemon.h" API gained a new sd_watchdog_enabled() to + determine whether watchdog notifications are requested by + the system manager. + + * Socket-activated per-connection services now include a + short description of the connection parameters in the + description. + + * tmpfiles gained a new "--boot" option. When this is not used, + only lines where the command character is not suffixed with + "!" are executed. When this option is specified, those + options are executed too. This partitions tmpfiles + directives into those that can be safely executed at any + time, and those which should be run only at boot (for + example, a line that creates /run/nologin). + + * A new API "sd-resolve.h" has been added which provides a simple + asynchronous wrapper around glibc NSS host name resolution + calls, such as getaddrinfo(). In contrast to glibc's + getaddrinfo_a(), it does not use signals. In contrast to most + other asynchronous name resolution libraries, this one does + not reimplement DNS, but reuses NSS, so that alternate + host name resolution systems continue to work, such as mDNS, + LDAP, etc. This API is based on libasyncns, but it has been + cleaned up for inclusion in systemd. + + * The APIs "sd-journal.h", "sd-login.h", "sd-id128.h", + "sd-daemon.h" are no longer found in individual libraries + libsystemd-journal.so, libsystemd-login.so, + libsystemd-id128.so, libsystemd-daemon.so. Instead, we have + merged them into a single library, libsystemd.so, which + provides all symbols. The reason for this is cyclic + dependencies, as these libraries tend to use each other's + symbols. So far, we have managed to workaround that by linking + a copy of a good part of our code into each of these + libraries again and again, which, however, makes certain + things hard to do, like sharing static variables. Also, it + substantially increases footprint. With this change, there + is only one library for the basic APIs systemd + provides. Also, "sd-bus.h", "sd-memfd.h", "sd-event.h", + "sd-rtnl.h", "sd-resolve.h", "sd-utf8.h" are found in this + library as well, however are subject to the --enable-kdbus + switch (see below). Note that "sd-dhcp-client.h" is not part + of this library (this is because it only consumes, never + provides, services of/to other APIs). To make the transition + easy from the separate libraries to the unified one, we + provide the --enable-compat-libs compile-time switch which + will generate stub libraries that are compatible with the + old ones but redirect all calls to the new one. + + * All of the kdbus logic and the new APIs "sd-bus.h", + "sd-memfd.h", "sd-event.h", "sd-rtnl.h", "sd-resolve.h", + and "sd-utf8.h" are compile-time optional via the + "--enable-kdbus" switch, and they are not compiled in by + default. To make use of kdbus, you have to explicitly enable + the switch. Note however, that neither the kernel nor the + userspace API for all of this is considered stable yet. We + want to maintain the freedom to still change the APIs for + now. By specifying this build-time switch, you acknowledge + that you are aware of the instability of the current + APIs. + + * Also, note that while kdbus is pretty much complete, + it lacks one thing: proper policy support. This means you + can build a fully working system with all features; however, + it will be highly insecure. Policy support will be added in + one of the next releases, at the same time that we will + declare the APIs stable. + + * When the kernel command line argument "kdbus" is specified, + systemd will automatically load the kdbus.ko kernel module. At + this stage of development, it is only useful for testing kdbus + and should not be used in production. Note: if "--enable-kdbus" + is specified, and the kdbus.ko kernel module is available, and + "kdbus" is added to the kernel command line, the entire system + runs with kdbus instead of dbus-daemon, with the above mentioned + problem of missing the system policy enforcement. Also a future + version of kdbus.ko or a newer systemd will not be compatible with + each other, and will unlikely be able to boot the machine if only + one of them is updated. + + * systemctl gained a new "import-environment" command which + uploads the caller's environment (or parts thereof) into the + service manager so that it is inherited by services started + by the manager. This is useful to upload variables like + $DISPLAY into the user service manager. + + * A new PrivateDevices= switch has been added to service units + which allows running a service with a namespaced /dev + directory that does not contain any device nodes for + physical devices. More specifically, it only includes devices + such as /dev/null, /dev/urandom, and /dev/zero which are API + entry points. + + * logind has been extended to support behaviour like VT + switching on seats that do not support a VT. This makes + multi-session available on seats that are not the first seat + (seat0), and on systems where kernel support for VTs has + been disabled at compile-time. + + * If a process holds a delay lock for system sleep or shutdown + and fails to release it in time, we will now log its + identity. This makes it easier to identify processes that + cause slow suspends or power-offs. + + * When parsing /etc/crypttab, support for a new key-slot= + option as supported by Debian is added. It allows indicating + which LUKS slot to use on disk, speeding up key loading. + + * The sd_journal_sendv() API call has been checked and + officially declared to be async-signal-safe so that it may + be invoked from signal handlers for logging purposes. + + * Boot-time status output is now enabled automatically after a + short timeout if boot does not progress, in order to give + the user an indication what she or he is waiting for. + + * The boot-time output has been improved to show how much time + remains until jobs expire. + + * The KillMode= switch in service units gained a new possible + value "mixed". If set, and the unit is shut down, then the + initial SIGTERM signal is sent only to the main daemon + process, while the following SIGKILL signal is sent to + all remaining processes of the service. + + * When a scope unit is registered, a new property "Controller" + may be set. If set to a valid bus name, systemd will send a + RequestStop() signal to this name when it would like to shut + down the scope. This may be used to hook manager logic into + the shutdown logic of scope units. Also, scope units may now + be put in a special "abandoned" state, in which case the + manager process which created them takes no further + responsibilities for it. + + * When reading unit files, systemd will now verify + the access mode of these files, and warn about certain + suspicious combinations. This has been added to make it + easier to track down packaging bugs where unit files are + marked executable or world-writable. + + * systemd-nspawn gained a new "--setenv=" switch to set + container-wide environment variables. The similar option in + systemd-activate was renamed from "--environment=" to + "--setenv=" for consistency. + + * systemd-nspawn has been updated to create a new kdbus domain + for each container that is invoked, thus allowing each + container to have its own set of system and user buses, + independent of the host. + + * systemd-nspawn gained a new --drop-capability= switch to run + the container with less capabilities than the default. Both + --drop-capability= and --capability= now take the special + string "all" for dropping or keeping all capabilities. + + * systemd-nspawn gained new switches for executing containers + with specific SELinux labels set. + + * systemd-nspawn gained a new --quiet switch to not generate + any additional output but the container's own console + output. + + * systemd-nspawn gained a new --share-system switch to run a + container without PID namespacing enabled. + + * systemd-nspawn gained a new --register= switch to control + whether the container is registered with systemd-machined or + not. This is useful for containers that do not run full + OS images, but only specific apps. + + * systemd-nspawn gained a new --keep-unit which may be used + when invoked as the only program from a service unit, and + results in registration of the unit service itself in + systemd-machined, instead of a newly opened scope unit. + + * systemd-nspawn gained a new --network-interface= switch for + moving arbitrary interfaces to the container. The new + --network-veth switch creates a virtual Ethernet connection + between host and container. The new --network-bridge= + switch then allows assigning the host side of this virtual + Ethernet connection to a bridge device. + + * systemd-nspawn gained a new --personality= switch for + setting the kernel personality for the container. This is + useful when running a 32-bit container on a 64-bit host. A + similar option Personality= is now also available for service + units to use. + + * logind will now also track a "Desktop" identifier for each + session which encodes the desktop environment of it. This is + useful for desktop environments that want to identify + multiple running sessions of itself easily. + + * A new SELinuxContext= setting for service units has been + added that allows setting a specific SELinux execution + context for a service. + + * Most systemd client tools will now honour $SYSTEMD_LESS for + settings of the "less" pager. By default, these tools will + override $LESS to allow certain operations to work, such as + jump-to-the-end. With $SYSTEMD_LESS, it is possible to + influence this logic. + + * systemd's "seccomp" hook-up has been changed to make use of + the libseccomp library instead of using its own + implementation. This has benefits for portability among + other things. + + * For usage together with SystemCallFilter=, a new + SystemCallErrorNumber= setting has been introduced that + allows configuration of a system error number to be returned + on filtered system calls, instead of immediately killing the + process. Also, SystemCallArchitectures= has been added to + limit access to system calls of a particular architecture + (in order to turn off support for unused secondary + architectures). There is also a global + SystemCallArchitectures= setting in system.conf now to turn + off support for non-native system calls system-wide. + + * systemd requires a kernel with a working name_to_handle_at(), + please see the kernel config requirements in the README file. + + Contributions from: Adam Williamson, Alex Jia, Anatol Pomozov, + Ansgar Burchardt, AppleBloom, Auke Kok, Bastien Nocera, + Chengwei Yang, Christian Seiler, Colin Guthrie, Colin Walters, + Cristian Rodríguez, Daniel Buch, Daniele Medri, Daniel J + Walsh, Daniel Mack, Dan McGee, Dave Reisner, David Coppa, + David Herrmann, David Strauss, Djalal Harouni, Dmitry Pisklov, + Elia Pinto, Florian Weimer, George McCollister, Goffredo + Baroncelli, Greg Kroah-Hartman, Hendrik Brueckner, Igor + Zhbanov, Jan Engelhardt, Jan Janssen, Jason A. Donenfeld, + Jason St. John, Jasper St. Pierre, Jóhann B. Guðmundsson, Jose + Ignacio Naranjo, Karel Zak, Kay Sievers, Kristian Høgsberg, + Lennart Poettering, Lubomir Rintel, Lukas Nykryn, Lukasz + Skalski, Łukasz Stelmach, Luke Shumaker, Mantas Mikulėnas, + Marc-Antoine Perennou, Marcel Holtmann, Marcos Felipe Rasia de + Mello, Marko Myllynen, Martin Pitt, Matthew Monaco, Michael + Marineau, Michael Scherer, Michał Górny, Michal Sekletar, + Michele Curti, Oleksii Shevchuk, Olivier Brunel, Patrik Flykt, + Pavel Holica, Raudi, Richard Marko, Ronny Chevalier, Sébastien + Luttringer, Sergey Ptashnick, Shawn Landden, Simon Peeters, + Stefan Beller, Susant Sahani, Sylvain Plantefeve, Sylvia Else, + Tero Roponen, Thomas Bächler, Thomas Hindoe Paaboel Andersen, + Tom Gundersen, Umut Tezduyar Lindskog, Unai Uribarri, Václav + Pavlín, Vincent Batts, WaLyong Cho, William Giokas, Yang + Zhiyong, Yin Kangkai, Yuxuan Shui, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2014-02-20 + +CHANGES WITH 208: + + * logind has gained support for facilitating privileged input + and drm device access for unprivileged clients. This work is + useful to allow Wayland display servers (and similar + programs, such as kmscon) to run under the user's ID and + access input and drm devices which are normally + protected. When this is used (and the kernel is new enough) + logind will "mute" IO on the file descriptors passed to + Wayland as long as it is in the background and "unmute" it + if it returns into the foreground. This allows secure + session switching without allowing background sessions to + eavesdrop on input and display data. This also introduces + session switching support if VT support is turned off in the + kernel, and on seats that are not seat0. + + * A new kernel command line option luks.options= is understood + now which allows specifying LUKS options for usage for LUKS + encrypted partitions specified with luks.uuid=. + + * tmpfiles.d(5) snippets may now use specifier expansion in + path names. More specifically %m, %b, %H, %v, are now + replaced by the local machine id, boot id, hostname, and + kernel version number. + + * A new tmpfiles.d(5) command "m" has been introduced which + may be used to change the owner/group/access mode of a file + or directory if it exists, but do nothing if it does not. + + * This release removes high-level support for the + MemorySoftLimit= cgroup setting. The underlying kernel + cgroup attribute memory.soft_limit= is currently badly + designed and likely to be removed from the kernel API in its + current form, hence we should not expose it for now. + + * The memory.use_hierarchy cgroup attribute is now enabled for + all cgroups systemd creates in the memory cgroup + hierarchy. This option is likely to be come the built-in + default in the kernel anyway, and the non-hierarchical mode + never made much sense in the intrinsically hierarchical + cgroup system. + + * A new field _SYSTEMD_SLICE= is logged along with all journal + messages containing the slice a message was generated + from. This is useful to allow easy per-customer filtering of + logs among other things. + + * systemd-journald will no longer adjust the group of journal + files it creates to the "systemd-journal" group. Instead we + rely on the journal directory to be owned by the + "systemd-journal" group, and its setgid bit set, so that the + kernel file system layer will automatically enforce that + journal files inherit this group assignment. The reason for + this change is that we cannot allow NSS look-ups from + journald which would be necessary to resolve + "systemd-journal" to a numeric GID, because this might + create deadlocks if NSS involves synchronous queries to + other daemons (such as nscd, or sssd) which in turn are + logging clients of journald and might block on it, which + would then dead lock. A tmpfiles.d(5) snippet included in + systemd will make sure the setgid bit and group are + properly set on the journal directory if it exists on every + boot. However, we recommend adjusting it manually after + upgrades too (or from RPM scriptlets), so that the change is + not delayed until next reboot. + + * Backlight and random seed files in /var/lib/ have moved into + the /var/lib/systemd/ directory, in order to centralize all + systemd generated files in one directory. + + * Boot time performance measurements (as displayed by + "systemd-analyze" for example) will now read ACPI 5.0 FPDT + performance information if that's available to determine how + much time BIOS and boot loader initialization required. With + a sufficiently new BIOS you hence no longer need to boot + with Gummiboot to get access to such information. + + Contributions from: Andrey Borzenkov, Chen Jie, Colin Walters, + Cristian Rodríguez, Dave Reisner, David Herrmann, David + Mackey, David Strauss, Eelco Dolstra, Evan Callicoat, Gao + feng, Harald Hoyer, Jimmie Tauriainen, Kay Sievers, Lennart + Poettering, Lukas Nykryn, Mantas Mikulėnas, Martin Pitt, + Michael Scherer, Michał Górny, Mike Gilbert, Patrick McCarty, + Sebastian Ott, Tom Gundersen, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2013-10-02 + +CHANGES WITH 207: + + * The Restart= option for services now understands a new + on-watchdog setting, which will restart the service + automatically if the service stops sending out watchdog keep + alive messages (as configured with WatchdogSec=). + + * The getty generator (which is responsible for bringing up a + getty on configured serial consoles) will no longer only + start a getty on the primary kernel console but on all + others, too. This makes the order in which console= is + specified on the kernel command line less important. + + * libsystemd-logind gained a new sd_session_get_vt() call to + retrieve the VT number of a session. + + * If the option "tries=0" is set for an entry of /etc/crypttab + its passphrase is queried indefinitely instead of any + maximum number of tries. + + * If a service with a configure PID file terminates its PID + file will now be removed automatically if it still exists + afterwards. This should put an end to stale PID files. + + * systemd-run will now also take relative binary path names + for execution and no longer insists on absolute paths. + + * InaccessibleDirectories= and ReadOnlyDirectories= now take + paths that are optionally prefixed with "-" to indicate that + it should not be considered a failure if they do not exist. + + * journalctl -o (and similar commands) now understands a new + output mode "short-precise", it is similar to "short" but + shows timestamps with usec accuracy. + + * The option "discard" (as known from Debian) is now + synonymous to "allow-discards" in /etc/crypttab. In fact, + "discard" is preferred now (since it is easier to remember + and type). + + * Some licensing clean-ups were made, so that more code is now + LGPL-2.1 licensed than before. + + * A minimal tool to save/restore the display backlight + brightness across reboots has been added. It will store the + backlight setting as late as possible at shutdown, and + restore it as early as possible during reboot. + + * A logic to automatically discover and enable home and swap + partitions on GPT disks has been added. With this in place + /etc/fstab becomes optional for many setups as systemd can + discover certain partitions located on the root disk + automatically. Home partitions are recognized under their + GPT type ID 933ac7e12eb44f13b8440e14e2aef915. Swap + partitions are recognized under their GPT type ID + 0657fd6da4ab43c484e50933c84b4f4f. + + * systemd will no longer pass any environment from the kernel + or initrd to system services. If you want to set an + environment for all services, do so via the kernel command + line systemd.setenv= assignment. + + * The systemd-sysctl tool no longer natively reads the file + /etc/sysctl.conf. If desired, the file should be symlinked + from /etc/sysctl.d/99-sysctl.conf. Apart from providing + legacy support by a symlink rather than built-in code, it + also makes the otherwise hidden order of application of the + different files visible. (Note that this partly reverts to a + pre-198 application order of sysctl knobs!) + + * The "systemctl set-log-level" and "systemctl dump" commands + have been moved to systemd-analyze. + + * systemd-run learned the new --remain-after-exit switch, + which causes the scope unit not to be cleaned up + automatically after the process terminated. + + * tmpfiles learned a new --exclude-prefix= switch to exclude + certain paths from operation. + + * journald will now automatically flush all messages to disk + as soon as a message at the log level CRIT, ALERT or EMERG + is received. + + Contributions from: Andrew Cook, Brandon Philips, Christian + Hesse, Christoph Junghans, Colin Walters, Daniel Schaal, + Daniel Wallace, Dave Reisner, David Herrmann, Gao feng, George + McCollister, Giovanni Campagna, Hannes Reinecke, Harald Hoyer, + Herczeg Zsolt, Holger Hans Peter Freyther, Jan Engelhardt, + Jesper Larsen, Kay Sievers, Khem Raj, Lennart Poettering, + Lukas Nykryn, Maciej Wereski, Mantas Mikulėnas, Marcel + Holtmann, Martin Pitt, Michael Biebl, Michael Marineau, + Michael Scherer, Michael Stapelberg, Michal Sekletar, Michał + Górny, Olivier Brunel, Ondrej Balaz, Ronny Chevalier, Shawn + Landden, Steven Hiscocks, Thomas Bächler, Thomas Hindoe + Paaboel Andersen, Tom Gundersen, Umut Tezduyar, WANG Chao, + William Giokas, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2013-09-13 + +CHANGES WITH 206: + + * The documentation has been updated to cover the various new + concepts introduced with 205. + + * Unit files now understand the new %v specifier which + resolves to the kernel version string as returned by "uname + -r". + + * systemctl now supports filtering the unit list output by + load state, active state and sub state, using the new + --state= parameter. + + * "systemctl status" will now show the results of the + condition checks (like ConditionPathExists= and similar) of + the last start attempts of the unit. They are also logged to + the journal. + + * "journalctl -b" may now be used to look for boot output of a + specific boot. Try "journalctl -b -1" for the previous boot, + but the syntax is substantially more powerful. + + * "journalctl --show-cursor" has been added which prints the + cursor string the last shown log line. This may then be used + with the new "journalctl --after-cursor=" switch to continue + browsing logs from that point on. + + * "journalctl --force" may now be used to force regeneration + of an FSS key. + + * Creation of "dead" device nodes has been moved from udev + into kmod and tmpfiles. Previously, udev would read the kmod + databases to pre-generate dead device nodes based on meta + information contained in kernel modules, so that these would + be auto-loaded on access rather then at boot. As this + does not really have much to do with the exposing actual + kernel devices to userspace this has always been slightly + alien in the udev codebase. Following the new scheme kmod + will now generate a runtime snippet for tmpfiles from the + module meta information and it now is tmpfiles' job to the + create the nodes. This also allows overriding access and + other parameters for the nodes using the usual tmpfiles + facilities. As side effect this allows us to remove the + CAP_SYS_MKNOD capability bit from udevd entirely. + + * logind's device ACLs may now be applied to these "dead" + devices nodes too, thus finally allowing managed access to + devices such as /dev/snd/sequencer without loading the + backing module right-away. + + * A new RPM macro has been added that may be used to apply + tmpfiles configuration during package installation. + + * systemd-detect-virt and ConditionVirtualization= now can + detect User-Mode-Linux machines (UML). + + * journald will now implicitly log the effective capabilities + set of processes in the message metadata. + + * systemd-cryptsetup has gained support for TrueCrypt volumes. + + * The initrd interface has been simplified (more specifically, + support for passing performance data via environment + variables and fsck results via files in /run has been + removed). These features were non-essential, and are + nowadays available in a much nicer way by having systemd in + the initrd serialize its state and have the hosts systemd + deserialize it again. + + * The udev "keymap" data files and tools to apply keyboard + specific mappings of scan to key codes, and force-release + scan code lists have been entirely replaced by a udev + "keyboard" builtin and a hwdb data file. + + * systemd will now honour the kernel's "quiet" command line + argument also during late shutdown, resulting in a + completely silent shutdown when used. + + * There's now an option to control the SO_REUSEPORT socket + option in .socket units. + + * Instance units will now automatically get a per-template + subslice of system.slice unless something else is explicitly + configured. For example, instances of sshd@.service will now + implicitly be placed in system-sshd.slice rather than + system.slice as before. + + * Test coverage support may now be enabled at build time. + + Contributions from: Dave Reisner, Frederic Crozat, Harald + Hoyer, Holger Hans Peter Freyther, Jan Engelhardt, Jan + Janssen, Jason St. John, Jesper Larsen, Kay Sievers, Lennart + Poettering, Lukas Nykryn, Maciej Wereski, Martin Pitt, Michael + Olbrich, Ramkumar Ramachandra, Ross Lagerwall, Shawn Landden, + Thomas H.P. Andersen, Tom Gundersen, Tomasz Torcz, William + Giokas, Zbigniew Jędrzejewski-Szmek + + — Berlin, 2013-07-23 + +CHANGES WITH 205: + + * Two new unit types have been introduced: + + Scope units are very similar to service units, however, are + created out of pre-existing processes — instead of PID 1 + forking off the processes. By using scope units it is + possible for system services and applications to group their + own child processes (worker processes) in a powerful way + which then maybe used to organize them, or kill them + together, or apply resource limits on them. + + Slice units may be used to partition system resources in an + hierarchical fashion and then assign other units to them. By + default there are now three slices: system.slice (for all + system services), user.slice (for all user sessions), + machine.slice (for VMs and containers). + + Slices and scopes have been introduced primarily in + context of the work to move cgroup handling to a + single-writer scheme, where only PID 1 + creates/removes/manages cgroups. + + * There's a new concept of "transient" units. In contrast to + normal units these units are created via an API at runtime, + not from configuration from disk. More specifically this + means it is now possible to run arbitrary programs as + independent services, with all execution parameters passed + in via bus APIs rather than read from disk. Transient units + make systemd substantially more dynamic then it ever was, + and useful as a general batch manager. + + * logind has been updated to make use of scope and slice units + for managing user sessions. As a user logs in he will get + his own private slice unit, to which all sessions are added + as scope units. We also added support for automatically + adding an instance of user@.service for the user into the + slice. Effectively logind will no longer create cgroup + hierarchies on its own now, it will defer entirely to PID 1 + for this by means of scope, service and slice units. Since + user sessions this way become entities managed by PID 1 + the output of "systemctl" is now a lot more comprehensive. + + * A new mini-daemon "systemd-machined" has been added which + may be used by virtualization managers to register local + VMs/containers. nspawn has been updated accordingly, and + libvirt will be updated shortly. machined will collect a bit + of meta information about the VMs/containers, and assign + them their own scope unit (see above). The collected + meta-data is then made available via the "machinectl" tool, + and exposed in "ps" and similar tools. machined/machinectl + is compile-time optional. + + * As discussed earlier, the low-level cgroup configuration + options ControlGroup=, ControlGroupModify=, + ControlGroupPersistent=, ControlGroupAttribute= have been + removed. Please use high-level attribute settings instead as + well as slice units. + + * A new bus call SetUnitProperties() has been added to alter + various runtime parameters of a unit. This is primarily + useful to alter cgroup parameters dynamically in a nice way, + but will be extended later on to make more properties + modifiable at runtime. systemctl gained a new set-properties + command that wraps this call. + + * A new tool "systemd-run" has been added which can be used to + run arbitrary command lines as transient services or scopes, + while configuring a number of settings via the command + line. This tool is currently very basic, however already + very useful. We plan to extend this tool to even allow + queuing of execution jobs with time triggers from the + command line, similar in fashion to "at". + + * nspawn will now inform the user explicitly that kernels with + audit enabled break containers, and suggest the user to turn + off audit. + + * Support for detecting the IMA and AppArmor security + frameworks with ConditionSecurity= has been added. + + * journalctl gained a new "-k" switch for showing only kernel + messages, mimicking dmesg output; in addition to "--user" + and "--system" switches for showing only user's own logs + and system logs. + + * systemd-delta can now show information about drop-in + snippets extending unit files. + + * libsystemd-bus has been substantially updated but is still + not available as public API. + + * systemd will now look for the "debug" argument on the kernel + command line and enable debug logging, similar to what + "systemd.log_level=debug" already did before. + + * "systemctl set-default", "systemctl get-default" has been + added to configure the default.target symlink, which + controls what to boot into by default. + + * "systemctl set-log-level" has been added as a convenient + way to raise and lower systemd logging threshold. + + * "systemd-analyze plot" will now show the time the various + generators needed for execution, as well as information + about the unit file loading. + + * libsystemd-journal gained a new sd_journal_open_files() call + for opening specific journal files. journactl also gained a + new switch to expose this new functionality. Previously we + only supported opening all files from a directory, or all + files from the system, as opening individual files only is + racy due to journal file rotation. + + * systemd gained the new DefaultEnvironment= setting in + /etc/systemd/system.conf to set environment variables for + all services. + + * If a privileged process logs a journal message with the + OBJECT_PID= field set, then journald will automatically + augment this with additional OBJECT_UID=, OBJECT_GID=, + OBJECT_COMM=, OBJECT_EXE=, ... fields. This is useful if + system services want to log events about specific client + processes. journactl/systemctl has been updated to make use + of this information if all log messages regarding a specific + unit is requested. + + Contributions from: Auke Kok, Chengwei Yang, Colin Walters, + Cristian Rodríguez, Daniel Albers, Daniel Wallace, Dave + Reisner, David Coppa, David King, David Strauss, Eelco + Dolstra, Gabriel de Perthuis, Harald Hoyer, Jan Alexander + Steffens, Jan Engelhardt, Jan Janssen, Jason St. John, Johan + Heikkilä, Karel Zak, Karol Lewandowski, Kay Sievers, Lennart + Poettering, Lukas Nykryn, Mantas Mikulėnas, Marius Vollmer, + Martin Pitt, Michael Biebl, Michael Olbrich, Michael Tremer, + Michal Schmidt, Michał Bartoszkiewicz, Nirbheek Chauhan, + Pierre Neidhardt, Ross Burton, Ross Lagerwall, Sean McGovern, + Thomas Hindoe Paaboel Andersen, Tom Gundersen, Umut Tezduyar, + Václav Pavlín, Zachary Cook, Zbigniew Jędrzejewski-Szmek, + Łukasz Stelmach, 장동준 + +CHANGES WITH 204: + + * The Python bindings gained some minimal support for the APIs + exposed by libsystemd-logind. + + * ConditionSecurity= gained support for detecting SMACK. Since + this condition already supports SELinux and AppArmor we only + miss IMA for this. Patches welcome! + + Contributions from: Karol Lewandowski, Lennart Poettering, + Zbigniew Jędrzejewski-Szmek + +CHANGES WITH 203: + + * systemd-nspawn will now create /etc/resolv.conf if + necessary, before bind-mounting the host's file onto it. + + * systemd-nspawn will now store meta information about a + container on the container's cgroup as extended attribute + fields, including the root directory. + + * The cgroup hierarchy has been reworked in many ways. All + objects any of the components systemd creates in the cgroup + tree are now suffixed. More specifically, user sessions are + now placed in cgroups suffixed with ".session", users in + cgroups suffixed with ".user", and nspawn containers in + cgroups suffixed with ".nspawn". Furthermore, all cgroup + names are now escaped in a simple scheme to avoid collision + of userspace object names with kernel filenames. This work + is preparation for making these objects relocatable in the + cgroup tree, in order to allow easy resource partitioning of + these objects without causing naming conflicts. + + * systemctl list-dependencies gained the new switches + --plain, --reverse, --after and --before. + + * systemd-inhibit now shows the process name of processes that + have taken an inhibitor lock. + + * nss-myhostname will now also resolve "localhost" + implicitly. This makes /etc/hosts an optional file and + nicely handles that on IPv6 ::1 maps to both "localhost" and + the local hostname. + + * libsystemd-logind.so gained a new call + sd_get_machine_names() to enumerate running containers and + VMs (currently only supported by very new libvirt and + nspawn). sd_login_monitor can now be used to watch + VMs/containers coming and going. + + * .include is not allowed recursively anymore, and only in + unit files. Usually it is better to use drop-in snippets in + .d/*.conf anyway, as introduced with systemd 198. + + * systemd-analyze gained a new "critical-chain" command that + determines the slowest chain of units run during system + boot-up. It is very useful for tracking down where + optimizing boot time is the most beneficial. + + * systemd will no longer allow manipulating service paths in + the name=systemd:/system cgroup tree using ControlGroup= in + units. (But is still fine with it in all other dirs.) + + * There's a new systemd-nspawn@.service service file that may + be used to easily run nspawn containers as system + services. With the container's root directory in + /var/lib/container/foobar it is now sufficient to run + "systemctl start systemd-nspawn@foobar.service" to boot it. + + * systemd-cgls gained a new parameter "--machine" to list only + the processes within a certain container. + + * ConditionSecurity= now can check for "apparmor". We still + are lacking checks for SMACK and IMA for this condition + check though. Patches welcome! + + * A new configuration file /etc/systemd/sleep.conf has been + added that may be used to configure which kernel operation + systemd is supposed to execute when "suspend", "hibernate" + or "hybrid-sleep" is requested. This makes the new kernel + "freeze" state accessible to the user. + + * ENV{SYSTEMD_WANTS} in udev rules will now implicitly escape + the passed argument if applicable. + + Contributions from: Auke Kok, Colin Guthrie, Colin Walters, + Cristian Rodríguez, Daniel Buch, Daniel Wallace, Dave Reisner, + Evangelos Foutras, Greg Kroah-Hartman, Harald Hoyer, Josh + Triplett, Kay Sievers, Lennart Poettering, Lukas Nykryn, + MUNEDA Takahiro, Mantas Mikulėnas, Mirco Tischler, Nathaniel + Chen, Nirbheek Chauhan, Ronny Chevalier, Ross Lagerwall, Tom + Gundersen, Umut Tezduyar, Ville Skyttä, Zbigniew + Jędrzejewski-Szmek + +CHANGES WITH 202: + + * The output of 'systemctl list-jobs' got some polishing. The + '--type=' argument may now be passed more than once. A new + command 'systemctl list-sockets' has been added which shows + a list of kernel sockets systemd is listening on with the + socket units they belong to, plus the units these socket + units activate. + + * The experimental libsystemd-bus library got substantial + updates to work in conjunction with the (also experimental) + kdbus kernel project. It works well enough to exchange + messages with some sophistication. Note that kdbus is not + ready yet, and the library is mostly an elaborate test case + for now, and not installable. + + * systemd gained a new unit 'systemd-static-nodes.service' + that generates static device nodes earlier during boot, and + can run in conjunction with udev. + + * libsystemd-login gained a new call sd_pid_get_user_unit() + to retrieve the user systemd unit a process is running + in. This is useful for systems where systemd is used as + session manager. + + * systemd-nspawn now places all containers in the new /machine + top-level cgroup directory in the name=systemd + hierarchy. libvirt will soon do the same, so that we get a + uniform separation of /system, /user and /machine for system + services, user processes and containers/virtual + machines. This new cgroup hierarchy is also useful to stick + stable names to specific container instances, which can be + recognized later this way (this name may be controlled + via systemd-nspawn's new -M switch). libsystemd-login also + gained a new call sd_pid_get_machine_name() to retrieve the + name of the container/VM a specific process belongs to. + + * bootchart can now store its data in the journal. + + * libsystemd-journal gained a new call + sd_journal_add_conjunction() for AND expressions to the + matching logic. This can be used to express more complex + logical expressions. + + * journactl can now take multiple --unit= and --user-unit= + switches. + + * The cryptsetup logic now understands the "luks.key=" kernel + command line switch for specifying a file to read the + decryption key from. Also, if a configured key file is not + found the tool will now automatically fall back to prompting + the user. + + * Python systemd.journal module was updated to wrap recently + added functions from libsystemd-journal. The interface was + changed to bring the low level interface in s.j._Reader + closer to the C API, and the high level interface in + s.j.Reader was updated to wrap and convert all data about + an entry. + + Contributions from: Anatol Pomozov, Auke Kok, Harald Hoyer, + Henrik Grindal Bakken, Josh Triplett, Kay Sievers, Lennart + Poettering, Lukas Nykryn, Mantas Mikulėnas Marius Vollmer, + Martin Jansa, Martin Pitt, Michael Biebl, Michal Schmidt, + Mirco Tischler, Pali Rohar, Simon Peeters, Steven Hiscocks, + Tom Gundersen, Zbigniew Jędrzejewski-Szmek + +CHANGES WITH 201: + + * journalctl --update-catalog now understands a new --root= + option to operate on catalogs found in a different root + directory. + + * During shutdown after systemd has terminated all running + services a final killing loop kills all remaining left-over + processes. We will now print the name of these processes + when we send SIGKILL to them, since this usually indicates a + problem. + + * If /etc/crypttab refers to password files stored on + configured mount points automatic dependencies will now be + generated to ensure the specific mount is established first + before the key file is attempted to be read. + + * 'systemctl status' will now show information about the + network sockets a socket unit is listening on. + + * 'systemctl status' will also shown information about any + drop-in configuration file for units. (Drop-In configuration + files in this context are files such as + /etc/systemd/systemd/foobar.service.d/*.conf) + + * systemd-cgtop now optionally shows summed up CPU times of + cgroups. Press '%' while running cgtop to switch between + percentage and absolute mode. This is useful to determine + which cgroups use up the most CPU time over the entire + runtime of the system. systemd-cgtop has also been updated + to be 'pipeable' for processing with further shell tools. + + * 'hostnamectl set-hostname' will now allow setting of FQDN + hostnames. + + * The formatting and parsing of time span values has been + changed. The parser now understands fractional expressions + such as "5.5h". The formatter will now output fractional + expressions for all time spans under 1min, i.e. "5.123456s" + rather than "5s 123ms 456us". For time spans under 1s + millisecond values are shown, for those under 1ms + microsecond values are shown. This should greatly improve + all time-related output of systemd. + + * libsystemd-login and libsystemd-journal gained new + functions for querying the poll() events mask and poll() + timeout value for integration into arbitrary event + loops. + + * localectl gained the ability to list available X11 keymaps + (models, layouts, variants, options). + + * 'systemd-analyze dot' gained the ability to filter for + specific units via shell-style globs, to create smaller, + more useful graphs. I.e. it is now possible to create simple + graphs of all the dependencies between only target units, or + of all units that Avahi has dependencies with. + + Contributions from: Cristian Rodríguez, Dr. Tilmann Bubeck, + Harald Hoyer, Holger Hans Peter Freyther, Kay Sievers, Kelly + Anderson, Koen Kooi, Lennart Poettering, Maksim Melnikau, + Marc-Antoine Perennou, Marius Vollmer, Martin Pitt, Michal + Schmidt, Oleksii Shevchuk, Ronny Chevalier, Simon McVittie, + Steven Hiscocks, Thomas Weißschuh, Umut Tezduyar, Václav + Pavlín, Zbigniew Jędrzejewski-Szmek, Łukasz Stelmach + +CHANGES WITH 200: + + * The boot-time readahead implementation for rotating media + will now read the read-ahead data in multiple passes which + consist of all read requests made in equidistant time + intervals. This means instead of strictly reading read-ahead + data in its physical order on disk we now try to find a + middle ground between physical and access time order. + + * /etc/os-release files gained a new BUILD_ID= field for usage + on operating systems that provide continuous builds of OS + images. + + Contributions from: Auke Kok, Eelco Dolstra, Kay Sievers, + Lennart Poettering, Lukas Nykryn, Martin Pitt, Václav Pavlín + William Douglas, Zbigniew Jędrzejewski-Szmek + +CHANGES WITH 199: + + * systemd-python gained an API exposing libsystemd-daemon. + + * The SMACK setup logic gained support for uploading CIPSO + security policy. + + * Behaviour of PrivateTmp=, ReadWriteDirectories=, + ReadOnlyDirectories= and InaccessibleDirectories= has + changed. The private /tmp and /var/tmp directories are now + shared by all processes of a service (which means + ExecStartPre= may now leave data in /tmp that ExecStart= of + the same service can still access). When a service is + stopped its temporary directories are immediately deleted + (normal clean-up with tmpfiles is still done in addition to + this though). + + * By default, systemd will now set a couple of sysctl + variables in the kernel: the safe sysrq options are turned + on, IP route verification is turned on, and source routing + disabled. The recently added hardlink and softlink + protection of the kernel is turned on. These settings should + be reasonably safe, and good defaults for all new systems. + + * The predictable network naming logic may now be turned off + with a new kernel command line switch: net.ifnames=0. + + * A new libsystemd-bus module has been added that implements a + pretty complete D-Bus client library. For details see: + + https://lists.freedesktop.org/archives/systemd-devel/2013-March/009797.html + + * journald will now explicitly flush the journal files to disk + at the latest 5min after each write. The file will then also + be marked offline until the next write. This should increase + reliability in case of a crash. The synchronization delay + can be configured via SyncIntervalSec= in journald.conf. + + * There's a new remote-fs-setup.target unit that can be used + to pull in specific services when at least one remote file + system is to be mounted. + + * There are new targets timers.target and paths.target as + canonical targets to pull user timer and path units in + from. This complements sockets.target with a similar + purpose for socket units. + + * libudev gained a new call udev_device_set_attribute_value() + to set sysfs attributes of a device. + + * The udev daemon now sets the default number of worker + processes executed in parallel based on the number of available + CPUs instead of the amount of available RAM. This is supposed + to provide a more reliable default and limit a too aggressive + parallelism for setups with 1000s of devices connected. + + Contributions from: Auke Kok, Colin Walters, Cristian + Rodríguez, Daniel Buch, Dave Reisner, Frederic Crozat, Hannes + Reinecke, Harald Hoyer, Jan Alexander Steffens, Jan + Engelhardt, Josh Triplett, Kay Sievers, Lennart Poettering, + Mantas Mikulėnas, Martin Pitt, Mathieu Bridon, Michael Biebl, + Michal Schmidt, Michal Sekletar, Miklos Vajna, Nathaniel Chen, + Oleksii Shevchuk, Ozan Çağlayan, Thomas Hindoe Paaboel + Andersen, Tollef Fog Heen, Tom Gundersen, Umut Tezduyar, + Zbigniew Jędrzejewski-Szmek + +CHANGES WITH 198: + + * Configuration of unit files may now be extended via drop-in + files without having to edit/override the unit files + themselves. More specifically, if the administrator wants to + change one value for a service file foobar.service he can + now do so by dropping in a configuration snippet into + /etc/systemd/system/foobar.service.d/*.conf. The unit logic + will load all these snippets and apply them on top of the + main unit configuration file, possibly extending or + overriding its settings. Using these drop-in snippets is + generally nicer than the two earlier options for changing + unit files locally: copying the files from + /usr/lib/systemd/system/ to /etc/systemd/system/ and editing + them there; or creating a new file in /etc/systemd/system/ + that incorporates the original one via ".include". Drop-in + snippets into these .d/ directories can be placed in any + directory systemd looks for units in, and the usual + overriding semantics between /usr/lib, /etc and /run apply + for them too. + + * Most unit file settings which take lists of items can now be + reset by assigning the empty string to them. For example, + normally, settings such as Environment=FOO=BAR append a new + environment variable assignment to the environment block, + each time they are used. By assigning Environment= the empty + string the environment block can be reset to empty. This is + particularly useful with the .d/*.conf drop-in snippets + mentioned above, since this adds the ability to reset list + settings from vendor unit files via these drop-ins. + + * systemctl gained a new "list-dependencies" command for + listing the dependencies of a unit recursively. + + * Inhibitors are now honored and listed by "systemctl + suspend", "systemctl poweroff" (and similar) too, not only + GNOME. These commands will also list active sessions by + other users. + + * Resource limits (as exposed by the various control group + controllers) can now be controlled dynamically at runtime + for all units. More specifically, you can now use a command + like "systemctl set-cgroup-attr foobar.service cpu.shares + 2000" to alter the CPU shares a specific service gets. These + settings are stored persistently on disk, and thus allow the + administrator to easily adjust the resource usage of + services with a few simple commands. This dynamic resource + management logic is also available to other programs via the + bus. Almost any kernel cgroup attribute and controller is + supported. + + * systemd-vconsole-setup will now copy all font settings to + all allocated VTs, where it previously applied them only to + the foreground VT. + + * libsystemd-login gained the new sd_session_get_tty() API + call. + + * This release drops support for a few legacy or + distribution-specific LSB facility names when parsing init + scripts: $x-display-manager, $mail-transfer-agent, + $mail-transport-agent, $mail-transfer-agent, $smtp, + $null. Also, the mail-transfer-agent.target unit backing + this has been removed. Distributions which want to retain + compatibility with this should carry the burden for + supporting this themselves and patch support for these back + in, if they really need to. Also, the facilities $syslog and + $local_fs are now ignored, since systemd does not support + early-boot LSB init scripts anymore, and these facilities + are implied anyway for normal services. syslog.target has + also been removed. + + * There are new bus calls on PID1's Manager object for + cancelling jobs, and removing snapshot units. Previously, + both calls were only available on the Job and Snapshot + objects themselves. + + * systemd-journal-gatewayd gained SSL support. + + * The various "environment" files, such as /etc/locale.conf + now support continuation lines with a backslash ("\") as + last character in the line, similarly in style (but different) + to how this is supported in shells. + + * For normal user processes the _SYSTEMD_USER_UNIT= field is + now implicitly appended to every log entry logged. systemctl + has been updated to filter by this field when operating on a + user systemd instance. + + * nspawn will now implicitly add the CAP_AUDIT_WRITE and + CAP_AUDIT_CONTROL capabilities to the capabilities set for + the container. This makes it easier to boot unmodified + Fedora systems in a container, which however still requires + audit=0 to be passed on the kernel command line. Auditing in + kernel and userspace is unfortunately still too broken in + context of containers, hence we recommend compiling it out + of the kernel or using audit=0. Hopefully this will be fixed + one day for good in the kernel. + + * nspawn gained the new --bind= and --bind-ro= parameters to + bind mount specific directories from the host into the + container. + + * nspawn will now mount its own devpts file system instance + into the container, in order not to leak pty devices from + the host into the container. + + * systemd will now read the firmware boot time performance + information from the EFI variables, if the used boot loader + supports this, and takes it into account for boot performance + analysis via "systemd-analyze". This is currently supported + only in conjunction with Gummiboot, but could be supported + by other boot loaders too. For details see: + + https://www.freedesktop.org/wiki/Software/systemd/BootLoaderInterface + + * A new generator has been added that automatically mounts the + EFI System Partition (ESP) to /boot, if that directory + exists, is empty, and no other file system has been + configured to be mounted there. + + * logind will now send out PrepareForSleep(false) out + unconditionally, after coming back from suspend. This may be + used by applications as asynchronous notification for + system resume events. + + * "systemctl unlock-sessions" has been added, that allows + unlocking the screens of all user sessions at once, similar + to how "systemctl lock-sessions" already locked all users + sessions. This is backed by a new D-Bus call UnlockSessions(). + + * "loginctl seat-status" will now show the master device of a + seat. (i.e. the device of a seat that needs to be around for + the seat to be considered available, usually the graphics + card). + + * tmpfiles gained a new "X" line type, that allows + configuration of files and directories (with wildcards) that + shall be excluded from automatic cleanup ("aging"). + + * udev default rules set the device node permissions now only + at "add" events, and do not change them any longer with a + later "change" event. + + * The log messages for lid events and power/sleep keypresses + now carry a message ID. + + * We now have a substantially larger unit test suite, but this + continues to be work in progress. + + * udevadm hwdb gained a new --root= parameter to change the + root directory to operate relative to. + + * logind will now issue a background sync() request to the kernel + early at shutdown, so that dirty buffers are flushed to disk early + instead of at the last moment, in order to optimize shutdown + times a little. + + * A new bootctl tool has been added that is an interface for + certain boot loader operations. This is currently a preview + and is likely to be extended into a small mechanism daemon + like timedated, localed, hostnamed, and can be used by + graphical UIs to enumerate available boot options, and + request boot into firmware operations. + + * systemd-bootchart has been relicensed to LGPLv2.1+ to match + the rest of the package. It also has been updated to work + correctly in initrds. + + * polkit previously has been runtime optional, and is now also + compile time optional via a configure switch. + + * systemd-analyze has been reimplemented in C. Also "systemctl + dot" has moved into systemd-analyze. + + * "systemctl status" with no further parameters will now print + the status of all active or failed units. + + * Operations such as "systemctl start" can now be executed + with a new mode "--irreversible" which may be used to queue + operations that cannot accidentally be reversed by a later + job queuing. This is by default used to make shutdown + requests more robust. + + * The Python API of systemd now gained a new module for + reading journal files. + + * A new tool kernel-install has been added that can install + kernel images according to the Boot Loader Specification: + + https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec + + * Boot time console output has been improved to provide + animated boot time output for hanging jobs. + + * A new tool systemd-activate has been added which can be used + to test socket activation with, directly from the command + line. This should make it much easier to test and debug + socket activation in daemons. + + * journalctl gained a new "--reverse" (or -r) option to show + journal output in reverse order (i.e. newest line first). + + * journalctl gained a new "--pager-end" (or -e) option to jump + to immediately jump to the end of the journal in the + pager. This is only supported in conjunction with "less". + + * journalctl gained a new "--user-unit=" option, that works + similarly to "--unit=" but filters for user units rather than + system units. + + * A number of unit files to ease adoption of systemd in + initrds has been added. This moves some minimal logic from + the various initrd implementations into systemd proper. + + * The journal files are now owned by a new group + "systemd-journal", which exists specifically to allow access + to the journal, and nothing else. Previously, we used the + "adm" group for that, which however possibly covers more + than just journal/log file access. This new group is now + already used by systemd-journal-gatewayd to ensure this + daemon gets access to the journal files and as little else + as possible. Note that "make install" will also set FS ACLs + up for /var/log/journal to give "adm" and "wheel" read + access to it, in addition to "systemd-journal" which owns + the journal files. We recommend that packaging scripts also + add read access to "adm" + "wheel" to /var/log/journal, and + all existing/future journal files. To normal users and + administrators little changes, however packagers need to + ensure to create the "systemd-journal" system group at + package installation time. + + * The systemd-journal-gatewayd now runs as unprivileged user + systemd-journal-gateway:systemd-journal-gateway. Packaging + scripts need to create these system user/group at + installation time. + + * timedated now exposes a new boolean property CanNTP that + indicates whether a local NTP service is available or not. + + * systemd-detect-virt will now also detect xen PVs + + * The pstore file system is now mounted by default, if it is + available. + + * In addition to the SELinux and IMA policies we will now also + load SMACK policies at early boot. + + Contributions from: Adel Gadllah, Aleksander Morgado, Auke + Kok, Ayan George, Bastien Nocera, Colin Walters, Daniel Buch, + Daniel Wallace, Dave Reisner, David Herrmann, David Strauss, + Eelco Dolstra, Enrico Scholz, Frederic Crozat, Harald Hoyer, + Jan Janssen, Jonathan Callen, Kay Sievers, Lennart Poettering, + Lukas Nykryn, Mantas Mikulėnas, Marc-Antoine Perennou, Martin + Pitt, Mauro Dreissig, Max F. Albrecht, Michael Biebl, Michael + Olbrich, Michal Schmidt, Michal Sekletar, Michal Vyskocil, + Michał Bartoszkiewicz, Mirco Tischler, Nathaniel Chen, Nestor + Ovroy, Oleksii Shevchuk, Paul W. Frields, Piotr Drąg, Rob + Clark, Ryan Lortie, Simon McVittie, Simon Peeters, Steven + Hiscocks, Thomas Hindoe Paaboel Andersen, Tollef Fog Heen, Tom + Gundersen, Umut Tezduyar, William Giokas, Zbigniew + Jędrzejewski-Szmek, Zeeshan Ali (Khattak) + +CHANGES WITH 197: + + * Timer units now support calendar time events in addition to + monotonic time events. That means you can now trigger a unit + based on a calendar time specification such as "Thu,Fri + 2013-*-1,5 11:12:13" which refers to 11:12:13 of the first + or fifth day of any month of the year 2013, given that it is + a thursday or friday. This brings timer event support + considerably closer to cron's capabilities. For details on + the supported calendar time specification language see + systemd.time(7). + + * udev now supports a number of different naming policies for + network interfaces for predictable names, and a combination + of these policies is now the default. Please see this wiki + document for details: + + https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames + + * Auke Kok's bootchart implementation has been added to the + systemd tree. It is an optional component that can graph the + boot in quite some detail. It is one of the best bootchart + implementations around and minimal in its code and + dependencies. + + * nss-myhostname has been integrated into the systemd source + tree. nss-myhostname guarantees that the local hostname + always stays resolvable via NSS. It has been a weak + requirement of systemd-hostnamed since a long time, and + since its code is actually trivial we decided to just + include it in systemd's source tree. It can be turned off + with a configure switch. + + * The read-ahead logic is now capable of properly detecting + whether a btrfs file system is on SSD or rotating media, in + order to optimize the read-ahead scheme. Previously, it was + only capable of detecting this on traditional file systems + such as ext4. + + * In udev, additional device properties are now read from the + IAB in addition to the OUI database. Also, Bluetooth company + identities are attached to the devices as well. + + * In service files %U may be used as specifier that is + replaced by the configured user name of the service. + + * nspawn may now be invoked without a controlling TTY. This + makes it suitable for invocation as its own service. This + may be used to set up a simple containerized server system + using only core OS tools. + + * systemd and nspawn can now accept socket file descriptors + when they are started for socket activation. This enables + implementation of socket activated nspawn + containers. i.e. think about autospawning an entire OS image + when the first SSH or HTTP connection is received. We expect + that similar functionality will also be added to libvirt-lxc + eventually. + + * journalctl will now suppress ANSI color codes when + presenting log data. + + * systemctl will no longer show control group information for + a unit if the control group is empty anyway. + + * logind can now automatically suspend/hibernate/shutdown the + system on idle. + + * /etc/machine-info and hostnamed now also expose the chassis + type of the system. This can be used to determine whether + the local system is a laptop, desktop, handset or + tablet. This information may either be configured by the + user/vendor or is automatically determined from ACPI and DMI + information if possible. + + * A number of polkit actions are now bound together with "imply" + rules. This should simplify creating UIs because many actions + will now authenticate similar ones as well. + + * Unit files learnt a new condition ConditionACPower= which + may be used to conditionalize a unit depending on whether an + AC power source is connected or not, of whether the system + is running on battery power. + + * systemctl gained a new "is-failed" verb that may be used in + shell scripts and suchlike to check whether a specific unit + is in the "failed" state. + + * The EnvironmentFile= setting in unit files now supports file + globbing, and can hence be used to easily read a number of + environment files at once. + + * systemd will no longer detect and recognize specific + distributions. All distribution-specific #ifdeffery has been + removed, systemd is now fully generic and + distribution-agnostic. Effectively, not too much is lost as + a lot of the code is still accessible via explicit configure + switches. However, support for some distribution specific + legacy configuration file formats has been dropped. We + recommend distributions to simply adopt the configuration + files everybody else uses now and convert the old + configuration from packaging scripts. Most distributions + already did that. If that's not possible or desirable, + distributions are welcome to forward port the specific + pieces of code locally from the git history. + + * When logging a message about a unit systemd will now always + log the unit name in the message meta data. + + * localectl will now also discover system locale data that is + not stored in locale archives, but directly unpacked. + + * logind will no longer unconditionally use framebuffer + devices as seat masters, i.e. as devices that are required + to be existing before a seat is considered preset. Instead, + it will now look for all devices that are tagged as + "seat-master" in udev. By default, framebuffer devices will + be marked as such, but depending on local systems, other + devices might be marked as well. This may be used to + integrate graphics cards using closed source drivers (such + as NVidia ones) more nicely into logind. Note however, that + we recommend using the open source NVidia drivers instead, + and no udev rules for the closed-source drivers will be + shipped from us upstream. + + Contributions from: Adam Williamson, Alessandro Crismani, Auke + Kok, Colin Walters, Daniel Wallace, Dave Reisner, David + Herrmann, David Strauss, Dimitrios Apostolou, Eelco Dolstra, + Eric Benoit, Giovanni Campagna, Hannes Reinecke, Henrik + Grindal Bakken, Hermann Gausterer, Kay Sievers, Lennart + Poettering, Lukas Nykryn, Mantas Mikulėnas, Marcel Holtmann, + Martin Pitt, Matthew Monaco, Michael Biebl, Michael Terry, + Michal Schmidt, Michal Sekletar, Michał Bartoszkiewicz, Oleg + Samarin, Pekka Lundstrom, Philip Nilsson, Ramkumar + Ramachandra, Richard Yao, Robert Millan, Sami Kerola, Shawn + Landden, Thomas Hindoe Paaboel Andersen, Thomas Jarosch, + Tollef Fog Heen, Tom Gundersen, Umut Tezduyar, Zbigniew + Jędrzejewski-Szmek + +CHANGES WITH 196: + + * udev gained support for loading additional device properties + from an indexed database that is keyed by vendor/product IDs + and similar device identifiers. For the beginning this + "hwdb" is populated with data from the well-known PCI and + USB database, but also includes PNP, ACPI and OID data. In + the longer run this indexed database shall grow into + becoming the one central database for non-essential + userspace device metadata. Previously, data from the PCI/USB + database was only attached to select devices, since the + lookup was a relatively expensive operation due to O(n) time + complexity (with n being the number of entries in the + database). Since this is now O(1), we decided to add in this + data for all devices where this is available, by + default. Note that the indexed database needs to be rebuilt + when new data files are installed. To achieve this you need + to update your packaging scripts to invoke "udevadm hwdb + --update" after installation of hwdb data files. For + RPM-based distributions we introduced the new + %udev_hwdb_update macro for this purpose. + + * The Journal gained support for the "Message Catalog", an + indexed database to link up additional information with + journal entries. For further details please check: + + https://www.freedesktop.org/wiki/Software/systemd/catalog + + The indexed message catalog database also needs to be + rebuilt after installation of message catalog files. Use + "journalctl --update-catalog" for this. For RPM-based + distributions we introduced the %journal_catalog_update + macro for this purpose. + + * The Python Journal bindings gained support for the standard + Python logging framework. + + * The Journal API gained new functions for checking whether + the underlying file system of a journal file is capable of + properly reporting file change notifications, or whether + applications that want to reflect journal changes "live" + need to recheck journal files continuously in appropriate + time intervals. + + * It is now possible to set the "age" field for tmpfiles + entries to 0, indicating that files matching this entry + shall always be removed when the directories are cleaned up. + + * coredumpctl gained a new "gdb" verb which invokes gdb + right-away on the selected coredump. + + * There's now support for "hybrid sleep" on kernels that + support this, in addition to "suspend" and "hibernate". Use + "systemctl hybrid-sleep" to make use of this. + + * logind's HandleSuspendKey= setting (and related settings) + now gained support for a new "lock" setting to simply + request the screen lock on all local sessions, instead of + actually executing a suspend or hibernation. + + * systemd will now mount the EFI variables file system by + default. + + * Socket units now gained support for configuration of the + SMACK security label. + + * timedatectl will now output the time of the last and next + daylight saving change. + + * We dropped support for various legacy and distro-specific + concepts, such as insserv, early-boot SysV services + (i.e. those for non-standard runlevels such as 'b' or 'S') + or ArchLinux /etc/rc.conf support. We recommend the + distributions who still need support this to either continue + to maintain the necessary patches downstream, or find a + different solution. (Talk to us if you have questions!) + + * Various systemd components will now bypass polkit checks for + root and otherwise handle properly if polkit is not found to + be around. This should fix most issues for polkit-less + systems. Quite frankly this should have been this way since + day one. It is absolutely our intention to make systemd work + fine on polkit-less systems, and we consider it a bug if + something does not work as it should if polkit is not around. + + * For embedded systems it is now possible to build udev and + systemd without blkid and/or kmod support. + + * "systemctl switch-root" is now capable of switching root + more than once. I.e. in addition to transitions from the + initrd to the host OS it is now possible to transition to + further OS images from the host. This is useful to implement + offline updating tools. + + * Various other additions have been made to the RPM macros + shipped with systemd. Use %udev_rules_update() after + installing new udev rules files. %_udevhwdbdir, + %_udevrulesdir, %_journalcatalogdir, %_tmpfilesdir, + %_sysctldir are now available which resolve to the right + directories for packages to place various data files in. + + * journalctl gained the new --full switch (in addition to + --all, to disable ellipsation for long messages. + + Contributions from: Anders Olofsson, Auke Kok, Ben Boeckel, + Colin Walters, Cosimo Cecchi, Daniel Wallace, Dave Reisner, + Eelco Dolstra, Holger Hans Peter Freyther, Kay Sievers, + Chun-Yi Lee, Lekensteyn, Lennart Poettering, Mantas Mikulėnas, + Marti Raudsepp, Martin Pitt, Mauro Dreissig, Michael Biebl, + Michal Schmidt, Michal Sekletar, Miklos Vajna, Nis Martensen, + Oleksii Shevchuk, Olivier Brunel, Ramkumar Ramachandra, Thomas + Bächler, Thomas Hindoe Paaboel Andersen, Tom Gundersen, Tony + Camuso, Umut Tezduyar, Zbigniew Jędrzejewski-Szmek + +CHANGES WITH 195: + + * journalctl gained new --since= and --until= switches to + filter by time. It also now supports nice filtering for + units via --unit=/-u. + + * Type=oneshot services may use ExecReload= and do the + right thing. + + * The journal daemon now supports time-based rotation and + vacuuming, in addition to the usual disk-space based + rotation. + + * The journal will now index the available field values for + each field name. This enables clients to show pretty drop + downs of available match values when filtering. The bash + completion of journalctl has been updated + accordingly. journalctl gained a new switch -F to list all + values a certain field takes in the journal database. + + * More service events are now written as structured messages + to the journal, and made recognizable via message IDs. + + * The timedated, localed and hostnamed mini-services which + previously only provided support for changing time, locale + and hostname settings from graphical DEs such as GNOME now + also have a minimal (but very useful) text-based client + utility each. This is probably the nicest way to changing + these settings from the command line now, especially since + it lists available options and is fully integrated with bash + completion. + + * There's now a new tool "systemd-coredumpctl" to list and + extract coredumps from the journal. + + * We now install a README each in /var/log/ and + /etc/rc.d/init.d explaining where the system logs and init + scripts went. This hopefully should help folks who go to + that dirs and look into the otherwise now empty void and + scratch their heads. + + * When user-services are invoked (by systemd --user) the + $MANAGERPID env var is set to the PID of systemd. + + * SIGRTMIN+24 when sent to a --user instance will now result + in immediate termination of systemd. + + * gatewayd received numerous feature additions such as a + "follow" mode, for live syncing and filtering. + + * browse.html now allows filtering and showing detailed + information on specific entries. Keyboard navigation and + mouse screen support has been added. + + * gatewayd/journalctl now supports HTML5/JSON + Server-Sent-Events as output. + + * The SysV init script compatibility logic will now + heuristically determine whether a script supports the + "reload" verb, and only then make this available as + "systemctl reload". + + * "systemctl status --follow" has been removed, use "journalctl + -u" instead. + + * journald.conf's RuntimeMinSize=, PersistentMinSize= settings + have been removed since they are hardly useful to be + configured. + + * And I'd like to take the opportunity to specifically mention + Zbigniew for his great contributions. Zbigniew, you rock! + + Contributions from: Andrew Eikum, Christian Hesse, Colin + Guthrie, Daniel J Walsh, Dave Reisner, Eelco Dolstra, Ferenc + Wágner, Kay Sievers, Lennart Poettering, Lukas Nykryn, Mantas + Mikulėnas, Martin Mikkelsen, Martin Pitt, Michael Olbrich, + Michael Stapelberg, Michal Schmidt, Sebastian Ott, Thomas + Bächler, Umut Tezduyar, Will Woods, Wulf C. Krueger, Zbigniew + Jędrzejewski-Szmek, Сковорода Никита Андреевич + +CHANGES WITH 194: + + * If /etc/vconsole.conf is non-existent or empty we will no + longer load any console font or key map at boot by + default. Instead the kernel defaults will be left + intact. This is definitely the right thing to do, as no + configuration should mean no configuration, and hard-coding + font names that are different on all archs is probably a bad + idea. Also, the kernel default key map and font should be + good enough for most cases anyway, and mostly identical to + the userspace fonts/key maps we previously overloaded them + with. If distributions want to continue to default to a + non-kernel font or key map they should ship a default + /etc/vconsole.conf with the appropriate contents. + + Contributions from: Colin Walters, Daniel J Walsh, Dave + Reisner, Kay Sievers, Lennart Poettering, Lukas Nykryn, Tollef + Fog Heen, Tom Gundersen, Zbigniew Jędrzejewski-Szmek + +CHANGES WITH 193: + + * journalctl gained a new --cursor= switch to show entries + starting from the specified location in the journal. + + * We now enforce a size limit on journal entry fields exported + with "-o json" in journalctl. Fields larger than 4K will be + assigned null. This can be turned off with --all. + + * An (optional) journal gateway daemon is now available as + "systemd-journal-gatewayd.service". This service provides + access to the journal via HTTP and JSON. This functionality + will be used to implement live log synchronization in both + pull and push modes, but has various other users too, such + as easy log access for debugging of embedded devices. Right + now it is already useful to retrieve the journal via HTTP: + + # systemctl start systemd-journal-gatewayd.service + # wget http://localhost:19531/entries + + This will download the journal contents in a + /var/log/messages compatible format. The same as JSON: + + # curl -H"Accept: application/json" http://localhost:19531/entries + + This service is also accessible via a web browser where a + single static HTML5 app is served that uses the JSON logic + to enable the user to do some basic browsing of the + journal. This will be extended later on. Here's an example + screenshot of this app in its current state: + + http://0pointer.de/public/journal-gatewayd + + Contributions from: Kay Sievers, Lennart Poettering, Robert + Milasan, Tom Gundersen + +CHANGES WITH 192: + + * The bash completion logic is now available for journalctl + too. + + * We do not mount the "cpuset" controller anymore together with + "cpu" and "cpuacct", as "cpuset" groups generally cannot be + started if no parameters are assigned to it. "cpuset" hence + broke code that assumed it could create "cpu" groups and + just start them. + + * journalctl -f will now subscribe to terminal size changes, + and line break accordingly. + + Contributions from: Dave Reisner, Kay Sievers, Lennart + Poettering, Lukas Nykrynm, Mirco Tischler, Václav Pavlín + +CHANGES WITH 191: + + * nspawn will now create a symlink /etc/localtime in the + container environment, copying the host's timezone + setting. Previously this has been done via a bind mount, but + since symlinks cannot be bind mounted this has now been + changed to create/update the appropriate symlink. + + * journalctl -n's line number argument is now optional, and + will default to 10 if omitted. + + * journald will now log the maximum size the journal files may + take up on disk. This is particularly useful if the default + built-in logic of determining this parameter from the file + system size is used. Use "systemctl status + systemd-journald.service" to see this information. + + * The multi-seat X wrapper tool has been stripped down. As X + is now capable of enumerating graphics devices via udev in a + seat-aware way the wrapper is not strictly necessary + anymore. A stripped down temporary stop-gap is still shipped + until the upstream display managers have been updated to + fully support the new X logic. Expect this wrapper to be + removed entirely in one of the next releases. + + * HandleSleepKey= in logind.conf has been split up into + HandleSuspendKey= and HandleHibernateKey=. The old setting + is not available anymore. X11 and the kernel are + distinguishing between these keys and we should too. This + also means the inhibition lock for these keys has been split + into two. + + Contributions from: Dave Airlie, Eelco Dolstra, Lennart + Poettering, Lukas Nykryn, Václav Pavlín + +CHANGES WITH 190: + + * Whenever a unit changes state we will now log this to the + journal and show along the unit's own log output in + "systemctl status". + + * ConditionPathIsMountPoint= can now properly detect bind + mount points too. (Previously, a bind mount of one file + system to another place in the same file system could not be + detected as mount, since they shared struct stat's st_dev + field.) + + * We will now mount the cgroup controllers cpu, cpuacct, + cpuset and the controllers net_cls, net_prio together by + default. + + * nspawn containers will now have a virtualized boot + ID. (i.e. /proc/sys/kernel/random/boot_id is now mounted + over with a randomized ID at container initialization). This + has the effect of making "journalctl -b" do the right thing + in a container. + + * The JSON output journal serialization has been updated not + to generate "endless" list objects anymore, but rather one + JSON object per line. This is more in line how most JSON + parsers expect JSON objects. The new output mode + "json-pretty" has been added to provide similar output, but + neatly aligned for readability by humans. + + * We dropped all explicit sync() invocations in the shutdown + code. The kernel does this implicitly anyway in the kernel + reboot() syscall. halt(8)'s -n option is now a compatibility + no-op. + + * We now support virtualized reboot() in containers, as + supported by newer kernels. We will fall back to exit() if + CAP_SYS_REBOOT is not available to the container. Also, + nspawn makes use of this now and will actually reboot the + container if the containerized OS asks for that. + + * journalctl will only show local log output by default + now. Use --merge (-m) to show remote log output, too. + + * libsystemd-journal gained the new sd_journal_get_usage() + call to determine the current disk usage of all journal + files. This is exposed in the new "journalctl --disk-usage" + command. + + * journald gained a new configuration setting SplitMode= in + journald.conf which may be used to control how user journals + are split off. See journald.conf(5) for details. + + * A new condition type ConditionFileNotEmpty= has been added. + + * tmpfiles' "w" lines now support file globbing, to write + multiple files at once. + + * We added Python bindings for the journal submission + APIs. More Python APIs for a number of selected APIs will + likely follow. Note that we intend to add native bindings + only for the Python language, as we consider it common + enough to deserve bindings shipped within systemd. There are + various projects outside of systemd that provide bindings + for languages such as PHP or Lua. + + * Many conditions will now resolve specifiers such as %i. In + addition, PathChanged= and related directives of .path units + now support specifiers as well. + + * There's now a new RPM macro definition for the system preset + dir: %_presetdir. + + * journald will now warn if it ca not forward a message to the + syslog daemon because its socket is full. + + * timedated will no longer write or process /etc/timezone, + except on Debian. As we do not support late mounted /usr + anymore /etc/localtime always being a symlink is now safe, + and hence the information in /etc/timezone is not necessary + anymore. + + * logind will now always reserve one VT for a text getty (VT6 + by default). Previously if more than 6 X sessions where + started they took up all the VTs with auto-spawned gettys, + so that no text gettys were available anymore. + + * udev will now automatically inform the btrfs kernel logic + about btrfs RAID components showing up. This should make + simple hotplug based btrfs RAID assembly work. + + * PID 1 will now increase its RLIMIT_NOFILE to 64K by default + (but not for its children which will stay at the kernel + default). This should allow setups with a lot more listening + sockets. + + * systemd will now always pass the configured timezone to the + kernel at boot. timedated will do the same when the timezone + is changed. + + * logind's inhibition logic has been updated. By default, + logind will now handle the lid switch, the power and sleep + keys all the time, even in graphical sessions. If DEs want + to handle these events on their own they should take the new + handle-power-key, handle-sleep-key and handle-lid-switch + inhibitors during their runtime. A simple way to achieve + that is to invoke the DE wrapped in an invocation of: + + systemd-inhibit --what=handle-power-key:handle-sleep-key:handle-lid-switch ... + + * Access to unit operations is now checked via SELinux taking + the unit file label and client process label into account. + + * systemd will now notify the administrator in the journal + when he over-mounts a non-empty directory. + + * There are new specifiers that are resolved in unit files, + for the host name (%H), the machine ID (%m) and the boot ID + (%b). + + Contributions from: Allin Cottrell, Auke Kok, Brandon Philips, + Colin Guthrie, Colin Walters, Daniel J Walsh, Dave Reisner, + Eelco Dolstra, Jan Engelhardt, Kay Sievers, Lennart + Poettering, Lucas De Marchi, Lukas Nykryn, Mantas Mikulėnas, + Martin Pitt, Matthias Clasen, Michael Olbrich, Pierre Schmitz, + Shawn Landden, Thomas Hindoe Paaboel Andersen, Tom Gundersen, + Václav Pavlín, Yin Kangkai, Zbigniew Jędrzejewski-Szmek + +CHANGES WITH 189: + + * Support for reading structured kernel messages from + /dev/kmsg has now been added and is enabled by default. + + * Support for reading kernel messages from /proc/kmsg has now + been removed. If you want kernel messages in the journal + make sure to run a recent kernel (>= 3.5) that supports + reading structured messages from /dev/kmsg (see + above). /proc/kmsg is now exclusive property of classic + syslog daemons again. + + * The libudev API gained the new + udev_device_new_from_device_id() call. + + * The logic for file system namespace (ReadOnlyDirectory=, + ReadWriteDirectoy=, PrivateTmp=) has been reworked not to + require pivot_root() anymore. This means fewer temporary + directories are created below /tmp for this feature. + + * nspawn containers will now see and receive all submounts + made on the host OS below the root file system of the + container. + + * Forward Secure Sealing is now supported for Journal files, + which provide cryptographical sealing of journal files so + that attackers cannot alter log history anymore without this + being detectable. Lennart will soon post a blog story about + this explaining it in more detail. + + * There are two new service settings RestartPreventExitStatus= + and SuccessExitStatus= which allow configuration of exit + status (exit code or signal) which will be excepted from the + restart logic, resp. consider successful. + + * journalctl gained the new --verify switch that can be used + to check the integrity of the structure of journal files and + (if Forward Secure Sealing is enabled) the contents of + journal files. + + * nspawn containers will now be run with /dev/stdin, /dev/fd/ + and similar symlinks pre-created. This makes running shells + as container init process a lot more fun. + + * The fstab support can now handle PARTUUID= and PARTLABEL= + entries. + + * A new ConditionHost= condition has been added to match + against the hostname (with globs) and machine ID. This is + useful for clusters where a single OS image is used to + provision a large number of hosts which shall run slightly + different sets of services. + + * Services which hit the restart limit will now be placed in a + failure state. + + Contributions from: Bertram Poettering, Dave Reisner, Huang + Hang, Kay Sievers, Lennart Poettering, Lukas Nykryn, Martin + Pitt, Simon Peeters, Zbigniew Jędrzejewski-Szmek + +CHANGES WITH 188: + + * When running in --user mode systemd will now become a + subreaper (PR_SET_CHILD_SUBREAPER). This should make the ps + tree a lot more organized. + + * A new PartOf= unit dependency type has been introduced that + may be used to group services in a natural way. + + * "systemctl enable" may now be used to enable instances of + services. + + * journalctl now prints error log levels in red, and + warning/notice log levels in bright white. It also supports + filtering by log level now. + + * cgtop gained a new -n switch (similar to top), to configure + the maximum number of iterations to run for. It also gained + -b, to run in batch mode (accepting no input). + + * The suffix ".service" may now be omitted on most systemctl + command lines involving service unit names. + + * There's a new bus call in logind to lock all sessions, as + well as a loginctl verb for it "lock-sessions". + + * libsystemd-logind.so gained a new call sd_journal_perror() + that works similar to libc perror() but logs to the journal + and encodes structured information about the error number. + + * /etc/crypttab entries now understand the new keyfile-size= + option. + + * shutdown(8) now can send a (configurable) wall message when + a shutdown is cancelled. + + * The mount propagation mode for the root file system will now + default to "shared", which is useful to make containers work + nicely out-of-the-box so that they receive new mounts from + the host. This can be undone locally by running "mount + --make-rprivate /" if needed. + + * The prefdm.service file has been removed. Distributions + should maintain this unit downstream if they intend to keep + it around. However, we recommend writing normal unit files + for display managers instead. + + * Since systemd is a crucial part of the OS we will now + default to a number of compiler switches that improve + security (hardening) such as read-only relocations, stack + protection, and suchlike. + + * The TimeoutSec= setting for services is now split into + TimeoutStartSec= and TimeoutStopSec= to allow configuration + of individual time outs for the start and the stop phase of + the service. + + Contributions from: Artur Zaprzala, Arvydas Sidorenko, Auke + Kok, Bryan Kadzban, Dave Reisner, David Strauss, Harald Hoyer, + Jim Meyering, Kay Sievers, Lennart Poettering, Mantas + Mikulėnas, Martin Pitt, Michal Schmidt, Michal Sekletar, Peter + Alfredsen, Shawn Landden, Simon Peeters, Terence Honles, Tom + Gundersen, Zbigniew Jędrzejewski-Szmek + +CHANGES WITH 187: + + * The journal and id128 C APIs are now fully documented as man + pages. + + * Extra safety checks have been added when transitioning from + the initial RAM disk to the main system to avoid accidental + data loss. + + * /etc/crypttab entries now understand the new keyfile-offset= + option. + + * systemctl -t can now be used to filter by unit load state. + + * The journal C API gained the new sd_journal_wait() call to + make writing synchronous journal clients easier. + + * journalctl gained the new -D switch to show journals from a + specific directory. + + * journalctl now displays a special marker between log + messages of two different boots. + + * The journal is now explicitly flushed to /var via a service + systemd-journal-flush.service, rather than implicitly simply + by seeing /var/log/journal to be writable. + + * journalctl (and the journal C APIs) can now match for much + more complex expressions, with alternatives and + disjunctions. + + * When transitioning from the initial RAM disk to the main + system we will now kill all processes in a killing spree to + ensure no processes stay around by accident. + + * Three new specifiers may be used in unit files: %u, %h, %s + resolve to the user name, user home directory resp. user + shell. This is useful for running systemd user instances. + + * We now automatically rotate journal files if their data + object hash table gets a fill level > 75%. We also size the + hash table based on the configured maximum file size. This + together should lower hash collisions drastically and thus + speed things up a bit. + + * journalctl gained the new "--header" switch to introspect + header data of journal files. + + * A new setting SystemCallFilters= has been added to services + which may be used to apply blacklists or whitelists to + system calls. This is based on SECCOMP Mode 2 of Linux 3.5. + + * nspawn gained a new --link-journal= switch (and quicker: -j) + to link the container journal with the host. This makes it + very easy to centralize log viewing on the host for all + guests while still keeping the journal files separated. + + * Many bugfixes and optimizations + + Contributions from: Auke Kok, Eelco Dolstra, Harald Hoyer, Kay + Sievers, Lennart Poettering, Malte Starostik, Paul Menzel, Rex + Tsai, Shawn Landden, Tom Gundersen, Ville Skyttä, Zbigniew + Jędrzejewski-Szmek + +CHANGES WITH 186: + + * Several tools now understand kernel command line arguments, + which are only read when run in an initial RAM disk. They + usually follow closely their normal counterparts, but are + prefixed with rd. + + * There's a new tool to analyze the readahead files that are + automatically generated at boot. Use: + + /usr/lib/systemd/systemd-readahead analyze /.readahead + + * We now provide an early debug shell on tty9 if this enabled. Use: + + systemctl enable debug-shell.service + + * All plymouth related units have been moved into the Plymouth + package. Please make sure to upgrade your Plymouth version + as well. + + * systemd-tmpfiles now supports getting passed the basename of + a configuration file only, in which case it will look for it + in all appropriate directories automatically. + + * udevadm info now takes a /dev or /sys path as argument, and + does the right thing. Example: + + udevadm info /dev/sda + udevadm info /sys/class/block/sda + + * systemctl now prints a warning if a unit is stopped but a + unit that might trigger it continues to run. Example: a + service is stopped but the socket that activates it is left + running. + + * "systemctl status" will now mention if the log output was + shortened due to rotation since a service has been started. + + * The journal API now exposes functions to determine the + "cutoff" times due to rotation. + + * journald now understands SIGUSR1 and SIGUSR2 for triggering + immediately flushing of runtime logs to /var if possible, + resp. for triggering immediate rotation of the journal + files. + + * It is now considered an error if a service is attempted to + be stopped that is not loaded. + + * XDG_RUNTIME_DIR now uses numeric UIDs instead of usernames. + + * systemd-analyze now supports Python 3 + + * tmpfiles now supports cleaning up directories via aging + where the first level dirs are always kept around but + directories beneath it automatically aged. This is enabled + by prefixing the age field with '~'. + + * Seat objects now expose CanGraphical, CanTTY properties + which is required to deal with very fast bootups where the + display manager might be running before the graphics drivers + completed initialization. + + * Seat objects now expose a State property. + + * We now include RPM macros for service enabling/disabling + based on the preset logic. We recommend RPM based + distributions to make use of these macros if possible. This + makes it simpler to reuse RPM spec files across + distributions. + + * We now make sure that the collected systemd unit name is + always valid when services log to the journal via + STDOUT/STDERR. + + * There's a new man page kernel-command-line(7) detailing all + command line options we understand. + + * The fstab generator may now be disabled at boot by passing + fstab=0 on the kernel command line. + + * A new kernel command line option modules-load= is now understood + to load a specific kernel module statically, early at boot. + + * Unit names specified on the systemctl command line are now + automatically escaped as needed. Also, if file system or + device paths are specified they are automatically turned + into the appropriate mount or device unit names. Example: + + systemctl status /home + systemctl status /dev/sda + + * The SysVConsole= configuration option has been removed from + system.conf parsing. + + * The SysV search path is no longer exported on the D-Bus + Manager object. + + * The Names= option has been removed from unit file parsing. + + * There's a new man page bootup(7) detailing the boot process. + + * Every unit and every generator we ship with systemd now + comes with full documentation. The self-explanatory boot is + complete. + + * A couple of services gained "systemd-" prefixes in their + name if they wrap systemd code, rather than only external + code. Among them fsck@.service which is now + systemd-fsck@.service. + + * The HaveWatchdog property has been removed from the D-Bus + Manager object. + + * systemd.confirm_spawn= on the kernel command line should now + work sensibly. + + * There's a new man page crypttab(5) which details all options + we actually understand. + + * systemd-nspawn gained a new --capability= switch to pass + additional capabilities to the container. + + * timedated will now read known NTP implementation unit names + from /usr/lib/systemd/ntp-units.d/*.list, + systemd-timedated-ntp.target has been removed. + + * journalctl gained a new switch "-b" that lists log data of + the current boot only. + + * The notify socket is in the abstract namespace again, in + order to support daemons which chroot() at start-up. + + * There is a new Storage= configuration option for journald + which allows configuration of where log data should go. This + also provides a way to disable journal logging entirely, so + that data collected is only forwarded to the console, the + kernel log buffer or another syslog implementation. + + * Many bugfixes and optimizations + + Contributions from: Auke Kok, Colin Guthrie, Dave Reisner, + David Strauss, Eelco Dolstra, Kay Sievers, Lennart Poettering, + Lukas Nykryn, Michal Schmidt, Michal Sekletar, Paul Menzel, + Shawn Landden, Tom Gundersen + +CHANGES WITH 185: + + * "systemctl help " now shows the man page if one is + available. + + * Several new man pages have been added. + + * MaxLevelStore=, MaxLevelSyslog=, MaxLevelKMsg=, + MaxLevelConsole= can now be specified in + journald.conf. These options allow reducing the amount of + data stored on disk or forwarded by the log level. + + * TimerSlackNSec= can now be specified in system.conf for + PID1. This allows system-wide power savings. + + Contributions from: Dave Reisner, Kay Sievers, Lauri Kasanen, + Lennart Poettering, Malte Starostik, Marc-Antoine Perennou, + Matthias Clasen + +CHANGES WITH 184: + + * logind is now capable of (optionally) handling power and + sleep keys as well as the lid switch. + + * journalctl now understands the syntax "journalctl + /usr/bin/avahi-daemon" to get all log output of a specific + daemon. + + * CapabilityBoundingSet= in system.conf now also influences + the capability bound set of usermode helpers of the kernel. + + Contributions from: Daniel Drake, Daniel J. Walsh, Gert + Michael Kulyk, Harald Hoyer, Jean Delvare, Kay Sievers, + Lennart Poettering, Matthew Garrett, Matthias Clasen, Paul + Menzel, Shawn Landden, Tero Roponen, Tom Gundersen + +CHANGES WITH 183: + + * Note that we skipped 139 releases here in order to set the + new version to something that is greater than both udev's + and systemd's most recent version number. + + * udev: all udev sources are merged into the systemd source tree now. + All future udev development will happen in the systemd tree. It + is still fully supported to use the udev daemon and tools without + systemd running, like in initramfs or other init systems. Building + udev though, will require the *build* of the systemd tree, but + udev can be properly *run* without systemd. + + * udev: /lib/udev/devices/ are not read anymore; systemd-tmpfiles + should be used to create dead device nodes as workarounds for broken + subsystems. + + * udev: RUN+="socket:..." and udev_monitor_new_from_socket() is + no longer supported. udev_monitor_new_from_netlink() needs to be + used to subscribe to events. + + * udev: when udevd is started by systemd, processes which are left + behind by forking them off of udev rules, are unconditionally cleaned + up and killed now after the event handling has finished. Services or + daemons must be started as systemd services. Services can be + pulled-in by udev to get started, but they can no longer be directly + forked by udev rules. + + * udev: the daemon binary is called systemd-udevd now and installed + in /usr/lib/systemd/. Standalone builds or non-systemd systems need + to adapt to that, create symlink, or rename the binary after building + it. + + * libudev no longer provides these symbols: + udev_monitor_from_socket() + udev_queue_get_failed_list_entry() + udev_get_{dev,sys,run}_path() + The versions number was bumped and symbol versioning introduced. + + * systemd-loginctl and systemd-journalctl have been renamed + to loginctl and journalctl to match systemctl. + + * The config files: /etc/systemd/systemd-logind.conf and + /etc/systemd/systemd-journald.conf have been renamed to + logind.conf and journald.conf. Package updates should rename + the files to the new names on upgrade. + + * For almost all files the license is now LGPL2.1+, changed + from the previous GPL2.0+. Exceptions are some minor stuff + of udev (which will be changed to LGPL2.1 eventually, too), + and the MIT licensed sd-daemon.[ch] library that is suitable + to be used as drop-in files. + + * systemd and logind now handle system sleep states, in + particular suspending and hibernating. + + * logind now implements a sleep/shutdown/idle inhibiting logic + suitable for a variety of uses. Soonishly Lennart will blog + about this in more detail. + + * var-run.mount and var-lock.mount are no longer provided + (which previously bind mounted these directories to their new + places). Distributions which have not converted these + directories to symlinks should consider stealing these files + from git history and add them downstream. + + * We introduced the Documentation= field for units and added + this to all our shipped units. This is useful to make it + easier to explore the boot and the purpose of the various + units. + + * All smaller setup units (such as + systemd-vconsole-setup.service) now detect properly if they + are run in a container and are skipped when + appropriate. This guarantees an entirely noise-free boot in + Linux container environments such as systemd-nspawn. + + * A framework for implementing offline system updates is now + integrated, for details see: + https://www.freedesktop.org/wiki/Software/systemd/SystemUpdates + + * A new service type Type=idle is available now which helps us + avoiding ugly interleaving of getty output and boot status + messages. + + * There's now a system-wide CapabilityBoundingSet= option to + globally reduce the set of capabilities for the + system. This is useful to drop CAP_SYS_MKNOD, CAP_SYS_RAWIO, + CAP_NET_RAW, CAP_SYS_MODULE, CAP_SYS_TIME, CAP_SYS_PTRACE or + even CAP_NET_ADMIN system-wide for secure systems. + + * There are now system-wide DefaultLimitXXX= options to + globally change the defaults of the various resource limits + for all units started by PID 1. + + * Harald Hoyer's systemd test suite has been integrated into + systemd which allows easy testing of systemd builds in qemu + and nspawn. (This is really awesome! Ask us for details!) + + * The fstab parser is now implemented as generator, not inside + of PID 1 anymore. + + * systemctl will now warn you if .mount units generated from + /etc/fstab are out of date due to changes in fstab that + have not been read by systemd yet. + + * systemd is now suitable for usage in initrds. Dracut has + already been updated to make use of this. With this in place + initrds get a slight bit faster but primarily are much + easier to introspect and debug since "systemctl status" in + the host system can be used to introspect initrd services, + and the journal from the initrd is kept around too. + + * systemd-delta has been added, a tool to explore differences + between user/admin configuration and vendor defaults. + + * PrivateTmp= now affects both /tmp and /var/tmp. + + * Boot time status messages are now much prettier and feature + proper english language. Booting up systemd has never been + so sexy. + + * Read-ahead pack files now include the inode number of all + files to pre-cache. When the inode changes the pre-caching + is not attempted. This should be nicer to deal with updated + packages which might result in changes of read-ahead + patterns. + + * We now temporaritly lower the kernel's read_ahead_kb variable + when collecting read-ahead data to ensure the kernel's + built-in read-ahead does not add noise to our measurements + of necessary blocks to pre-cache. + + * There's now RequiresMountsFor= to add automatic dependencies + for all mounts necessary for a specific file system path. + + * MountAuto= and SwapAuto= have been removed from + system.conf. Mounting file systems at boot has to take place + in systemd now. + + * nspawn now learned a new switch --uuid= to set the machine + ID on the command line. + + * nspawn now learned the -b switch to automatically search + for an init system. + + * vt102 is now the default TERM for serial TTYs, upgraded from + vt100. + + * systemd-logind now works on VT-less systems. + + * The build tree has been reorganized. The individual + components now have directories of their own. + + * A new condition type ConditionPathIsReadWrite= is now available. + + * nspawn learned the new -C switch to create cgroups for the + container in other hierarchies. + + * We now have support for hardware watchdogs, configurable in + system.conf. + + * The scheduled shutdown logic now has a public API. + + * We now mount /tmp as tmpfs by default, but this can be + masked and /etc/fstab can override it. + + * Since udisks does not make use of /media anymore we are not + mounting a tmpfs on it anymore. + + * journalctl gained a new --local switch to only interleave + locally generated journal files. + + * We can now load the IMA policy at boot automatically. + + * The GTK tools have been split off into a systemd-ui. + + Contributions from: Andreas Schwab, Auke Kok, Ayan George, + Colin Guthrie, Daniel Mack, Dave Reisner, David Ward, Elan + Ruusamäe, Frederic Crozat, Gergely Nagy, Guillermo Vidal, + Hannes Reinecke, Harald Hoyer, Javier Jardón, Kay Sievers, + Lennart Poettering, Lucas De Marchi, Léo Gillot-Lamure, + Marc-Antoine Perennou, Martin Pitt, Matthew Monaco, Maxim + A. Mikityanskiy, Michael Biebl, Michael Olbrich, Michal + Schmidt, Nis Martensen, Patrick McCarty, Roberto Sassu, Shawn + Landden, Sjoerd Simons, Sven Anders, Tollef Fog Heen, Tom + Gundersen + +CHANGES WITH 44: + + * This is mostly a bugfix release + + * Support optional initialization of the machine ID from the + KVM or container configured UUID. + + * Support immediate reboots with "systemctl reboot -ff" + + * Show /etc/os-release data in systemd-analyze output + + * Many bugfixes for the journal, including endianness fixes and + ensuring that disk space enforcement works + + * sd-login.h is C++ compatible again + + * Extend the /etc/os-release format on request of the Debian + folks + + * We now refuse non-UTF8 strings used in various configuration + and unit files. This is done to ensure we do not pass invalid + data over D-Bus or expose it elsewhere. + + * Register Mimo USB Screens as suitable for automatic seat + configuration + + * Read SELinux client context from journal clients in a race + free fashion + + * Reorder configuration file lookup order. /etc now always + overrides /run in order to allow the administrator to always + and unconditionally override vendor-supplied or + automatically generated data. + + * The various user visible bits of the journal now have man + pages. We still lack man pages for the journal API calls + however. + + * We now ship all man pages in HTML format again in the + tarball. + + Contributions from: Dave Reisner, Dirk Eibach, Frederic + Crozat, Harald Hoyer, Kay Sievers, Lennart Poettering, Marti + Raudsepp, Michal Schmidt, Shawn Landden, Tero Roponen, Thierry + Reding + +CHANGES WITH 43: + + * This is mostly a bugfix release + + * systems lacking /etc/os-release are no longer supported. + + * Various functionality updates to libsystemd-login.so + + * Track class of PAM logins to distinguish greeters from + normal user logins. + + Contributions from: Kay Sievers, Lennart Poettering, Michael + Biebl + +CHANGES WITH 42: + + * This is an important bugfix release for v41. + + * Building man pages is now optional which should be useful + for those building systemd from git but unwilling to install + xsltproc. + + * Watchdog support for supervising services is now usable. In + a future release support for hardware watchdogs + (i.e. /dev/watchdog) will be added building on this. + + * Service start rate limiting is now configurable and can be + turned off per service. When a start rate limit is hit a + reboot can automatically be triggered. + + * New CanReboot(), CanPowerOff() bus calls in systemd-logind. + + Contributions from: Benjamin Franzke, Bill Nottingham, + Frederic Crozat, Lennart Poettering, Michael Olbrich, Michal + Schmidt, Michał Górny, Piotr Drąg + +CHANGES WITH 41: + + * The systemd binary is installed /usr/lib/systemd/systemd now; + An existing /sbin/init symlink needs to be adapted with the + package update. + + * The code that loads kernel modules has been ported to invoke + libkmod directly, instead of modprobe. This means we do not + support systems with module-init-tools anymore. + + * Watchdog support is now already useful, but still not + complete. + + * A new kernel command line option systemd.setenv= is + understood to set system wide environment variables + dynamically at boot. + + * We now limit the set of capabilities of systemd-journald. + + * We now set SIGPIPE to ignore by default, since it only is + useful in shell pipelines, and has little use in general + code. This can be disabled with IgnoreSIPIPE=no in unit + files. + + Contributions from: Benjamin Franzke, Kay Sievers, Lennart + Poettering, Michael Olbrich, Michal Schmidt, Tom Gundersen, + William Douglas + +CHANGES WITH 40: + + * This is mostly a bugfix release + + * We now expose the reason why a service failed in the + "Result" D-Bus property. + + * Rudimentary service watchdog support (will be completed over + the next few releases.) + + * When systemd forks off in order execute some service we will + now immediately changes its argv[0] to reflect which process + it will execute. This is useful to minimize the time window + with a generic argv[0], which makes bootcharts more useful + + Contributions from: Alvaro Soliverez, Chris Paulson-Ellis, Kay + Sievers, Lennart Poettering, Michael Olbrich, Michal Schmidt, + Mike Kazantsev, Ray Strode + +CHANGES WITH 39: + + * This is mostly a test release, but incorporates many + bugfixes. + + * New systemd-cgtop tool to show control groups by their + resource usage. + + * Linking against libacl for ACLs is optional again. If + disabled, support tracking device access for active logins + goes becomes unavailable, and so does access to the user + journals by the respective users. + + * If a group "adm" exists, journal files are automatically + owned by them, thus allow members of this group full access + to the system journal as well as all user journals. + + * The journal now stores the SELinux context of the logging + client for all entries. + + * Add C++ inclusion guards to all public headers + + * New output mode "cat" in the journal to print only text + messages, without any meta data like date or time. + + * Include tiny X server wrapper as a temporary stop-gap to + teach XOrg udev display enumeration. This is used by display + managers such as gdm, and will go away as soon as XOrg + learned native udev hotplugging for display devices. + + * Add new systemd-cat tool for executing arbitrary programs + with STDERR/STDOUT connected to the journal. Can also act as + BSD logger replacement, and does so by default. + + * Optionally store all locally generated coredumps in the + journal along with meta data. + + * systemd-tmpfiles learnt four new commands: n, L, c, b, for + writing short strings to files (for usage for /sys), and for + creating symlinks, character and block device nodes. + + * New unit file option ControlGroupPersistent= to make cgroups + persistent, following the mechanisms outlined in + https://www.freedesktop.org/wiki/Software/systemd/PaxControlGroups + + * Support multiple local RTCs in a sane way + + * No longer monopolize IO when replaying readahead data on + rotating disks, since we might starve non-file-system IO to + death, since fanotify() will not see accesses done by blkid, + or fsck. + + * Do not show kernel threads in systemd-cgls anymore, unless + requested with new -k switch. + + Contributions from: Dan Horák, Kay Sievers, Lennart + Poettering, Michal Schmidt + +CHANGES WITH 38: + + * This is mostly a test release, but incorporates many + bugfixes. + + * The git repository moved to: + git://anongit.freedesktop.org/systemd/systemd + ssh://git.freedesktop.org/git/systemd/systemd + + * First release with the journal + http://0pointer.de/blog/projects/the-journal.html + + * The journal replaces both systemd-kmsg-syslogd and + systemd-stdout-bridge. + + * New sd_pid_get_unit() API call in libsystemd-logind + + * Many systemadm clean-ups + + * Introduce remote-fs-pre.target which is ordered before all + remote mounts and may be used to start services before all + remote mounts. + + * Added Mageia support + + * Add bash completion for systemd-loginctl + + * Actively monitor PID file creation for daemons which exit in + the parent process before having finished writing the PID + file in the daemon process. Daemons which do this need to be + fixed (i.e. PID file creation must have finished before the + parent exits), but we now react a bit more gracefully to them. + + * Add colourful boot output, mimicking the well-known output + of existing distributions. + + * New option PassCredentials= for socket units, for + compatibility with a recent kernel ABI breakage. + + * /etc/rc.local is now hooked in via a generator binary, and + thus will no longer act as synchronization point during + boot. + + * systemctl list-unit-files now supports --root=. + + * systemd-tmpfiles now understands two new commands: z, Z for + relabelling files according to the SELinux database. This is + useful to apply SELinux labels to specific files in /sys, + among other things. + + * Output of SysV services is now forwarded to both the console + and the journal by default, not only just the console. + + * New man pages for all APIs from libsystemd-login. + + * The build tree got reorganized and the build system is a + lot more modular allowing embedded setups to specifically + select the components of systemd they are interested in. + + * Support for Linux systems lacking the kernel VT subsystem is + restored. + + * configure's --with-rootdir= got renamed to + --with-rootprefix= to follow the naming used by udev and + kmod + + * Unless specified otherwise we will now install to /usr instead + of /usr/local by default. + + * Processes with '@' in argv[0][0] are now excluded from the + final shut-down killing spree, following the logic explained + in: + https://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons + + * All processes remaining in a service cgroup when we enter + the START or START_PRE states are now killed with + SIGKILL. That means it is no longer possible to spawn + background processes from ExecStart= lines (which was never + supported anyway, and bad style). + + * New PropagateReloadTo=/PropagateReloadFrom= options to bind + reloading of units together. + + Contributions from: Bill Nottingham, Daniel J. Walsh, Dave + Reisner, Dexter Morgan, Gregs Gregs, Jonathan Nieder, Kay + Sievers, Lennart Poettering, Michael Biebl, Michal Schmidt, + Michał Górny, Ran Benita, Thomas Jarosch, Tim Waugh, Tollef + Fog Heen, Tom Gundersen, Zbigniew Jędrzejewski-Szmek diff --git a/README b/README new file mode 100644 index 00000000..b2c8d284 --- /dev/null +++ b/README @@ -0,0 +1,334 @@ +systemd System and Service Manager + +DETAILS: + http://0pointer.de/blog/projects/systemd.html + +WEB SITE: + https://www.freedesktop.org/wiki/Software/systemd + +GIT: + git@github.com:systemd/systemd.git + https://github.com/systemd/systemd + +MAILING LIST: + https://lists.freedesktop.org/mailman/listinfo/systemd-devel + +IRC: + #systemd on irc.freenode.org + +BUG REPORTS: + https://github.com/systemd/systemd/issues + +AUTHOR: + Lennart Poettering + Kay Sievers + ...and many others + +LICENSE: + LGPLv2.1+ for all code + - except src/basic/MurmurHash2.c which is Public Domain + - except src/basic/siphash24.c which is CC0 Public Domain + - except src/journal/lookup3.c which is Public Domain + - except src/udev/* which is (currently still) GPLv2, GPLv2+ + - except tools/chromiumos/* which is BSD-style + +REQUIREMENTS: + Linux kernel >= 3.13 + Linux kernel >= 4.2 for unified cgroup hierarchy support + + Kernel Config Options: + CONFIG_DEVTMPFS + CONFIG_CGROUPS (it is OK to disable all controllers) + CONFIG_INOTIFY_USER + CONFIG_SIGNALFD + CONFIG_TIMERFD + CONFIG_EPOLL + CONFIG_NET + CONFIG_SYSFS + CONFIG_PROC_FS + CONFIG_FHANDLE (libudev, mount and bind mount handling) + + Kernel crypto/hash API + CONFIG_CRYPTO_USER_API_HASH + CONFIG_CRYPTO_HMAC + CONFIG_CRYPTO_SHA256 + + udev will fail to work with the legacy sysfs layout: + CONFIG_SYSFS_DEPRECATED=n + + Legacy hotplug slows down the system and confuses udev: + CONFIG_UEVENT_HELPER_PATH="" + + Userspace firmware loading is not supported and should + be disabled in the kernel: + CONFIG_FW_LOADER_USER_HELPER=n + + Some udev rules and virtualization detection relies on it: + CONFIG_DMIID + + Support for some SCSI devices serial number retrieval, to + create additional symlinks in /dev/disk/ and /dev/tape: + CONFIG_BLK_DEV_BSG + + Required for PrivateNetwork= in service units: + CONFIG_NET_NS + Note that systemd-localed.service and other systemd units use + PrivateNetwork so this is effectively required. + + Required for PrivateUsers= in service units: + CONFIG_USER_NS + + Optional but strongly recommended: + CONFIG_IPV6 + CONFIG_AUTOFS4_FS + CONFIG_TMPFS_XATTR + CONFIG_{TMPFS,EXT4_FS,XFS,BTRFS_FS,...}_POSIX_ACL + CONFIG_SECCOMP + CONFIG_SECCOMP_FILTER (required for seccomp support) + CONFIG_CHECKPOINT_RESTORE (for the kcmp() syscall) + + Required for CPUShares= in resource control unit settings + CONFIG_CGROUP_SCHED + CONFIG_FAIR_GROUP_SCHED + + Required for CPUQuota= in resource control unit settings + CONFIG_CFS_BANDWIDTH + + Required for IPAddressDeny= and IPAddressAllow= in resource control + unit settings + CONFIG_CGROUP_BPF + + For UEFI systems: + CONFIG_EFIVAR_FS + CONFIG_EFI_PARTITION + + We recommend to turn off Real-Time group scheduling in the + kernel when using systemd. RT group scheduling effectively + makes RT scheduling unavailable for most userspace, since it + requires explicit assignment of RT budgets to each unit whose + processes making use of RT. As there's no sensible way to + assign these budgets automatically this cannot really be + fixed, and it's best to disable group scheduling hence. + CONFIG_RT_GROUP_SCHED=n + + It's a good idea to disable the implicit creation of networking bonding + devices by the kernel networking bonding module, so that the + automatically created "bond0" interface doesn't conflict with any such + device created by systemd-networkd (or other tools). Ideally there + would be a kernel compile-time option for this, but there currently + isn't. The next best thing is to make this change through a modprobe.d + drop-in. This is shipped by default, see modprobe.d/systemd.conf. + + Required for systemd-nspawn: + CONFIG_DEVPTS_MULTIPLE_INSTANCES or Linux kernel >= 4.7 + + Note that kernel auditing is broken when used with systemd's + container code. When using systemd in conjunction with + containers, please make sure to either turn off auditing at + runtime using the kernel command line option "audit=0", or + turn it off at kernel compile time using: + CONFIG_AUDIT=n + If systemd is compiled with libseccomp support on + architectures which do not use socketcall() and where seccomp + is supported (this effectively means x86-64 and ARM, but + excludes 32-bit x86!), then nspawn will now install a + work-around seccomp filter that makes containers boot even + with audit being enabled. This works correctly only on kernels + 3.14 and newer though. TL;DR: turn audit off, still. + + glibc >= 2.16 + libcap + libmount >= 2.30 (from util-linux) + (util-linux *must* be built without --enable-libmount-support-mtab) + libseccomp >= 2.3.1 (optional) + libblkid >= 2.24 (from util-linux) (optional) + libkmod >= 15 (optional) + PAM >= 1.1.2 (optional) + libcryptsetup (optional) + libaudit (optional) + libacl (optional) + libselinux (optional) + liblzma (optional) + liblz4 >= 1.3.0 / 130 (optional) + libgcrypt (optional) + libqrencode (optional) + libmicrohttpd (optional) + libpython (optional) + libidn2 or libidn (optional) + gnutls >= 3.1.4 (optional, >= 3.6.0 is required to support DNS-over-TLS with gnutls) + openssl >= 1.1.0 (optional, required to support DNS-over-TLS with openssl) + elfutils >= 158 (optional) + polkit (optional) + tzdata >= 2014f (optional) + pkg-config + gperf + docbook-xsl (optional, required for documentation) + xsltproc (optional, required for documentation) + python-lxml (optional, required to build the indices) + python >= 3.5 + meson >= 0.46 (>= 0.49 is required to build position-independent executables) + ninja + gcc, awk, sed, grep, m4, and similar tools + + During runtime, you need the following additional + dependencies: + + util-linux >= v2.27.1 required + dbus >= 1.4.0 (strictly speaking optional, but recommended) + NOTE: If using dbus < 1.9.18, you should override the default + policy directory (--with-dbuspolicydir=/etc/dbus-1/system.d). + dracut (optional) + polkit (optional) + + To build in directory build/: + meson build/ && ninja -C build + + Any configuration options can be specified as -Darg=value... arguments + to meson. After the build directory is initially configured, meson will + refuse to run again, and options must be changed with: + mesonconf -Darg=value... + mesonconf without any arguments will print out available options and + their current values. + + Useful commands: + ninja -v some/target + ninja test + sudo ninja install + DESTDIR=... ninja install + + A tarball can be created with: + git archive --format=tar --prefix=systemd-222/ v222 | xz > systemd-222.tar.xz + + When systemd-hostnamed is used, it is strongly recommended to + install nss-myhostname to ensure that, in a world of + dynamically changing hostnames, the hostname stays resolvable + under all circumstances. In fact, systemd-hostnamed will warn + if nss-myhostname is not installed. + + nss-systemd must be enabled on systemd systems, as that's required for + DynamicUser= to work. Note that we ship services out-of-the-box that + make use of DynamicUser= now, hence enabling nss-systemd is not + optional. + + Note that the build prefix for systemd must be /usr. (Moreover, + packages systemd relies on — such as D-Bus — really should use the same + prefix, otherwise you are on your own.) -Dsplit-usr=false (which is the + default and does not need to be specified) is the recommended setting, + and -Dsplit-usr=true should be used on systems which have /usr on a + separate partition. + + Additional packages are necessary to run some tests: + - busybox (used by test/TEST-13-NSPAWN-SMOKE) + - nc (used by test/TEST-12-ISSUE-3171) + - python3-pyparsing + - python3-evdev (used by hwdb parsing tests) + - strace (used by test/test-functions) + - capsh (optional, used by test-execute) + +USERS AND GROUPS: + Default udev rules use the following standard system group + names, which need to be resolvable by getgrnam() at any time, + even in the very early boot stages, where no other databases + and network are available: + + audio, cdrom, dialout, disk, input, kmem, kvm, lp, render, tape, tty, video + + During runtime, the journal daemon requires the + "systemd-journal" system group to exist. New journal files will + be readable by this group (but not writable), which may be used + to grant specific users read access. In addition, system + groups "wheel" and "adm" will be given read-only access to + journal files using systemd-tmpfiles.service. + + The journal remote daemon requires the + "systemd-journal-remote" system user and group to + exist. During execution this network facing service will drop + privileges and assume this uid/gid for security reasons. + + Similarly, the network management daemon requires the + "systemd-network" system user and group to exist. + + Similarly, the name resolution daemon requires the + "systemd-resolve" system user and group to exist. + + Similarly, the coredump support requires the + "systemd-coredump" system user and group to exist. + +NSS: + systemd ships with four glibc NSS modules: + + nss-myhostname resolves the local hostname to locally + configured IP addresses, as well as "localhost" to + 127.0.0.1/::1. + + nss-resolve enables DNS resolution via the systemd-resolved + DNS/LLMNR caching stub resolver "systemd-resolved". + + nss-mymachines enables resolution of all local containers registered + with machined to their respective IP addresses. It also maps UID/GIDs + ranges used by containers to useful names. + + nss-systemd enables resolution of all dynamically allocated service + users. (See the DynamicUser= setting in unit files.) + + To make use of these NSS modules, please add them to the "hosts:", + "passwd:" and "group:" lines in /etc/nsswitch.conf. The "resolve" + module should replace the glibc "dns" module in this file (and don't + worry, it chain-loads the "dns" module if it can't talk to resolved). + + The four modules should be used in the following order: + + passwd: compat mymachines systemd + group: compat mymachines systemd + hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname + +SYSV INIT.D SCRIPTS: + When calling "systemctl enable/disable/is-enabled" on a unit which is a + SysV init.d script, it calls /usr/lib/systemd/systemd-sysv-install; + this needs to translate the action into the distribution specific + mechanism such as chkconfig or update-rc.d. Packagers need to provide + this script if you need this functionality (you don't if you disabled + SysV init support). + + Please see src/systemctl/systemd-sysv-install.SKELETON for how this + needs to look like, and provide an implementation at the marked places. + +WARNINGS: + systemd will warn during early boot if /usr is not already mounted at + this point (that means: either located on the same file system as / or + already mounted in the initrd). While in systemd itself very little + will break if /usr is on a separate, late-mounted partition, many of + its dependencies very likely will break sooner or later in one form or + another. For example, udev rules tend to refer to binaries in /usr, + binaries that link to libraries in /usr or binaries that refer to data + files in /usr. Since these breakages are not always directly visible, + systemd will warn about this, since this kind of file system setup is + not really supported anymore by the basic set of Linux OS components. + + systemd requires that the /run mount point exists. systemd also + requires that /var/run is a symlink to /run. + + For more information on this issue consult + https://www.freedesktop.org/wiki/Software/systemd/separate-usr-is-broken + + To run systemd under valgrind, compile with meson option + -Dvalgrind=true and have valgrind development headers installed + (i.e. valgrind-devel or equivalent). Otherwise, false positives will be + triggered by code which violates some rules but is actually safe. Note + that valgrind generates nice output only on exit(), hence on shutdown + we don't execve() systemd-shutdown. + +STABLE BRANCHES AND BACKPORTS: + Stable branches with backported patches are available in the + systemd-stable repo at https://github.com/systemd/systemd-stable. + + Stable branches are started for certain releases of systemd and named + after them, e.g. v238-stable. Stable branches are managed by + distribution maintainers on an as needed basis. See + https://www.freedesktop.org/wiki/Software/systemd/Backports/ for some + more information and examples. + +ENGINEERING AND CONSULTING SERVICES: + Kinvolk (https://kinvolk.io) offers professional engineering + and consulting services for systemd. Please contact Chris Kühl + for more information. diff --git a/README.md b/README.md new file mode 100644 index 00000000..0ba648a8 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +![systemd logo](http://brand.systemd.io/assets/page-logo.png) + +# systemd - System and Service Manager + +Count of open issues over time +Count of open pull requests over time +[![Semaphore CI Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)
+[![Coverity Scan Status](https://scan.coverity.com/projects/350/badge.svg)](https://scan.coverity.com/projects/350)
+[![Fuzzit Status](https://app.fuzzit.dev/badge?org_id=systemd&branch=master)](https://app.fuzzit.dev/orgs/systemd/dashboard)
+[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/systemd.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
+[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1369/badge)](https://bestpractices.coreinfrastructure.org/projects/1369)
+[![Travis CI Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)
+[![Language Grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/systemd/systemd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/systemd/systemd/context:cpp)
+[![CentOS CI Build Status](https://ci.centos.org/buildStatus/icon?job=systemd-pr-build)](https://ci.centos.org/job/systemd-pr-build/)
+[![Build Status](https://dev.azure.com/evvers/systemd-systemd/_apis/build/status/systemd.systemd?branchName=master)](https://dev.azure.com/evvers/systemd-systemd/_build/latest?definitionId=1&branchName=master) + +## Details + +General information about systemd can be found in the [systemd Wiki](https://www.freedesktop.org/wiki/Software/systemd). + +Information about build requirements is provided in the [README file](README). + +Consult our [NEWS file](NEWS) for information about what's new in the most recent systemd versions. + +Please see the [Hacking guide](docs/HACKING.md) for information on how to hack on systemd and test your modifications. + +Please see our [Contribution Guidelines](docs/CONTRIBUTING.md) for more information about filing GitHub Issues and posting GitHub Pull Requests. + +When preparing patches for systemd, please follow our [Coding Style Guidelines](docs/CODING_STYLE.md). + +If you are looking for support, please contact our [mailing list](https://lists.freedesktop.org/mailman/listinfo/systemd-devel) or join our [IRC channel](irc://irc.freenode.org/%23systemd). + +Stable branches with backported patches are available in the [stable repo](https://github.com/systemd/systemd-stable). diff --git a/TODO b/TODO new file mode 100644 index 00000000..c2ee593e --- /dev/null +++ b/TODO @@ -0,0 +1,1157 @@ +Bugfixes: + +* Many manager configuration settings that are only applicable to user + manager or system manager can be always set. It would be better to reject + them when parsing config. + +External: + +* Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros. + +* wiki: update journal format documentation for lz4 additions + +Janitorial Clean-ups: + +* Rearrange tests so that the various test-xyz.c match a specific src/basic/xyz.c again + +* rework mount.c and swap.c to follow proper state enumeration/deserialization + semantics, like we do for device.c now + +Before v244: + +* revisit SystemdOptions EFI variable. Find a better, systematic name and use + it for the env var, the bootctl verb and the EFI variable itself, clear up + semantics. + +Features: + +* socket units: allow creating a udev monitor socket with ListenDevices= or so, + with matches, then actviate app thorugh that passing socket oveer + +* move discoverable partitions spec into markdown and our tree + +* sd-event: add native support for P_ALL waitid() watching, then move PID 1 to + it fo reaping assigned but unknown children. This needs to some special care + to operate somewhat sensibly in light of priorities: P_ALL will return + arbitrary processes, regardless of the priority we want to watch them with, + hence on each event loop iteration check all processes which we shall watch + with higher prio explicitly, and then watch the entire rest with P_ALL. + +* tweak sd-event's child watching: keep a prioq of children to watch and use + waitid() only on the children with the highest priority until one is waitable + and ignore all lower-prio ones from that point on + +* sd-event: drop stack allocated epoll_event buffer in sd_event_wait() + +* maybe introduce xattrs that can be set on the root dir of the root fs + partition that declare the volatility mode to use the image in. Previously I + thought marking this via GPT partition flags but that's not ideal since + that's outside of the LUKS encryption/verity verification, and we probably + shouldn't operate in a volatile mode unless we got told so from a trusted + source. + +* look for /var/tmp automatically via gpt auto discovery + +* figure out automatic partition discovery when combining writable root dir + with immutable /usr + +* coredump: maybe when coredumping read a new xattr from /proc/$PID/exe that + may be used to mark a whole binary as non-coredumpable. Would fix: + https://bugs.freedesktop.org/show_bug.cgi?id=69447 + +* teach parse_timestamp() timezones like the calendar spec already knows it + +* beef up hibernation to optionally do swapon/swapoff immediately before/after + the hibernation + +* beef up s2h to implement a battery watch loop: instead of entering + hibernation unconditionally after coming back from resume make a decision + based on the battery load level: if battery level is above a specific + threshold, go to suspend again, only hibernate if below it. This means we'd + stick to suspend usually, but fall back to hibernation only when battery runs + empty (well, subject to our sampling interval). Related to this, check if we + can make ACPI _BTP (i.e. /sys/class/power_supply/*/alarm) work for us too, + i.e. see if it can wake up machines from suspend, so that we could resume + automatically when the system is low on power and move automatically to + hibernation mode. (see + https://uefi.org/sites/default/files/resources/ACPI%206_2_A_Sept29.pdf + section 10.2.2.8 and + https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/modern-standby-wake-sources + at the end). + +* add an explicit "vertical" mode to format-table, so that "systemctl + status"-like outputs (i.e. with a series of field names left and values + right) become genuine first class citizens, and we gain automatic, sane JSON + output for them. + +* dissector: invoke fsck on the file systems we encounter, after all ext4 is + still pretty popular (and we mount the ESP too with it after all, which is + fat) + +* systemd-firstboot: teach it dissector magic, so that you can point it to some + disk image and it will just set everything in it all behind the scenes. + +* systemd-firstboot: add --force mode that replaces existing configuration. + +* We should probably replace /var/log/README, /etc/rc.d/README with symlinks + that are linked to these places instead of copied. After all they are + constant vendor data. + +* maybe add kernel cmdline params: 1) to force first-boot mode + 2) to force + random seed crediting + +* nspawn: on cgroupsv1 issue cgroup empty handler process based on host events, + so that we make cgroup agent logic safe + +* nspawn/machined: add API to invoke binary in container, then use that as + fallback in "machinectl shell" + +* logind: rework pam_logind to also do a bus call in case of invocation from + user@.service, which returns the XDG_RUNTIME_DIR value, and make this + behaviour selectable via pam module option. + +* introduce a new per-process uuid, similar to the boot id, the machine id, the + invocation id, that is derived from process creds, specifically a hashed + combination of AT_RANDOM + getpid() + the starttime from + /proc/self/status. Then add these ids implicitly when logging. Deriving this + uuid from these three things has the benefit that it can be derived easily + from /proc/$PID/ in a stable, and unique way that changes on both fork() and + exec(). + +* let's not GC a unit while its ratelimits are still pending + +* when killing due to service watchdog timeout maybe detect whether target + process is under ptracing and then log loudly and continue instead. + +* introduce a new group to own TPM devices + +* make rfkill uaccess controllable by default, i.e. steal rule from + gnome-bluetooth and friends + +* tweak journald context caching. In addition to caching per-process attributes + keyed by PID, cache per-cgroup attributes (i.e. the various xattrs we read) + keyed by cgroup path, and guarded by ctime changes. This should provide us + with a nice speed-up on services that have many processes running in the same + cgroup. + +* make MAINPID= message reception checks even stricter: if service uses User=, + then check sending UID and ignore message if it doesn't match the user or + root. + +* maybe trigger a uevent "change" on a device if "systemctl reload xyz.device" + is issued. + +* when importing an fs tree with machined, optionally apply userns-rec-chown + +* when importing an fs tree with machined, complain if image is not an OS + +* Maybe introduce a helper safe_exec() or so, which is to execve() which + safe_fork() is to fork(). And then make revert the RLIMIT_NOFILE soft limit + to 1K implicitly, unless explicitly opted-out. + +* rework seccomp/nnp logic that even if User= is used in combination with + a seccomp option we don't have to set NNP. For that, change uid first whil + keeping CAP_SYS_ADMIN, then apply seccomp, the drop cap. + +* add a concept for automatically loading per-unit secrets off disk and + inserting them into the kernel keyring. Maybe SecretsDirectory= similar to + ConfigurationDirectory=. + +* when no locale is configured, default to UEFI's PlatformLang variable + +* bootctl,sd-boot: actually honour the "architecture" key + +* add a new syscall group "@esoteric" for more esoteric stuff such as bpf() and + usefaultd() and make systemd-analyze check for it. + +* paranoia: whenever we process passwords, call mlock() on the memory + first. i.e. look for all places we use free_and_erasep() and + augment them with mlock(). Also use MADV_DONTDUMP. + +* Move RestrictAddressFamily= to the new cgroup create socket + +* support the bind/connect/sendmsg cgroup stuff for sandboxing, and possibly + patching around + +* maybe implicitly attach monotonic+realtime timestamps to outgoing messages in + log.c and sd-journal-send + +* optionally: turn on cgroup delegation for per-session scope units + +* introduce per-unit (i.e. per-slice, per-service) journal log size limits. + +* optionally, if a per-partition GPT flag is set for the root/home/… partitions + format the partition on next boot and unset the flag, in order to implement + factory reset. also, add a second flag that simply indicates whether such a + scheme is supported. then, add a tool (or maybe beef up systemd-dissect) to + show state of these flags, and optionally trigger such a factory reset on + next boot by setting the flag. + +* sd-boot: automatically load EFI modules from some drop-in dir, so that people + can add in file system drivers and such + +* sd-boot: optionally, show boot menu when previous default boot item has + non-zero "tries done" count + +* introduce an option (or replacement) for "systemctl show" that outputs all + properties as JSON, similar to busctl's new JSON output. In contrast to that + it should skip the variant type string though. + +* augment CODE_FILE=, CODE_LINE= with something like CODE_BASE= or so which + contains some identifier for the project, which allows us to include + clickable links to source files generating these log messages. The identifier + could be some abberviated URL prefix or so (taking inspiration from Go + imports). For example, for systemd we could use + CODE_BASE=github.com/systemd/systemd/blob/98b0b1123cc or so which is + sufficient to build a link by prefixing "http://" and suffixing the + CODE_FILE. + +* Augment MESSAGE_ID with MESSAGE_BASE, in a similar fashion so that we can + make clickable links from log messages carrying a MESSAGE_ID, that lead to + some explanatory text online. + +* maybe extend .path units to expose fanotify() per-mount change events + +* Add a "systemctl list-units --by-slice" mode or so, which rearranges the + output of "systemctl list-units" slightly by showing the tree structure of + the slices, and the units attached to them. + +* the a-posteriori stopping of units bound to units that disappeared logic + should be reworked: there should be a queue of units, and we should only + enqueue stop jobs from a defer event that processes queue instead of + right-away when we find a unit that is bound to one that doesn't exist + anymore. (similar to how the stop-unneeded queue has been reworked the same + way) + +* nspawn: make nspawn suitable for shell pipelines: instead of triggering a + hangup when input is finished, send ^D, which synthesizes an EOF. Then wait + for hangup or ^D before passing on the EOF. + +* When reloading configuration PID 1 should reset all its properties to the + original defaults before calling parse_config() + +* nspawn: greater control over selinux label? + +* hibernate/s2h: make this robust and safe to enable in Fedora by default. + Specifically: + + 1. add resume_offset support to the resume code (i.e. support swap files + properly) + 2. check if swap is on weird storage and refuse if so + 3. add autodetection of hibernation images + +* cgroups: use inotify to get notified when somebody else modifies cgroups + owned by us, then log a friendly warning. + +* beef up log.c with support for stripping ANSI sequences from strings, so that + it is OK to include them in log strings. This would be particularly useful so + that our log messages could contain clickable links for example for unit + files and suchlike we operate on. + +* add support for "portablectl attach http://foobar.com/waaa.raw (i.e. importd integration) + +* add attach --enable and attach --now (for attach+enable+start) + +* sync dynamic uids/gids between host+portable srvice (i.e. if DynamicUser=1 is set for a service, make sure that the + selected user is resolvable in the service even if it ships its own /etc/passwd) + +* Fix DECIMAL_STR_MAX or DECIMAL_STR_WIDTH. One includes a trailing NUL, the + other doesn't. What a disaster. Probably to exclude it. Also + DECIMAL_STR_WIDTH should probably add an extra "-" into account for negative + numbers. + +* Check that users of inotify's IN_DELETE_SELF flag are using it properly, as + usually IN_ATTRIB is the right way to watch deleted files, as the former only + fires when a file is actually removed from disk, i.e. the link count drops to + zero and is not open anymore, while the latter happens when a file is + unlinked from any dir. + +* port systemctl, busctl, … over to format-table.[ch]'s table formatters + +* pid1: lock image configured with RootDirectory=/RootImage= using the usual nspawn semantics while the unit is up + +* add --vacuum-xyz options to coredumpctl, matching those journalctl already has. + +* introduce Ephemeral= unit file switch, that creates an ephemeral copy of all + files and directories that are left writable for a unit, and which are + removed after the unit goes down again. A bit like --ephemeral for + systemd-nspawn but for system services. If used together with RootImage= this + should reflink the image file itself. + + Related: add Ephemeral= … which would allow marking + specific paths only like this. + +* add CopyFile= or so as unit file setting that may be used to copy files or + directory trees from the host to the services RootImage= and RootDirectory= + environment. Which we can use for /etc/machine-id and in particular + /etc/resolv.conf. Should be smart and do something useful on read-only + images, for example fallback to read-only bind mounting the file instead. + +* show invocation ID in systemd-run output + +* bypass SIGTERM state in unit files if KillSignal is SIGKILL + +* add proper dbus APIs for the various sd_notify() commands, such as MAINPID=1 + and so on, which would mean we could report errors and such. + +* teach tmpfiles.d q/Q logic something sensible in the context of XFS/ext4 + project quota + +* introduce DefaultSlice= or so in system.conf that allows changing where we + place our units by default, i.e. change system.slice to something + else. Similar, ManagerSlice= should exist so that PID1's own scope unit could + be moved somewhere else too. Finally machined and logind should get similar + options so that it is possible to move user session scopes and machines to a + different slice too by default. Usecase: people who want to put resources on + the entire system, with the exception of one specific service. See: + https://lists.freedesktop.org/archives/systemd-devel/2018-February/040369.html + +* maybe rework get_user_creds() to query the user database if $SHELL is used + for root, but only then. + +* be stricter with fds we receive for the fdstore: close them asynchronously + +* calenderspec: add support for week numbers and day numbers within a + year. This would allow us to define "bi-weekly" triggers safely. + +* sd-bus: add vtable flag, that may be used to request client creds implicitly + and asynchronously before dispatching the operation + +* make use of ethtool veth peer info in machined, for automatically finding out + host-side interface pointing to the container. + +* add some special mode to LogsDirectory=/StateDirectory=… that allows + declaring these directories without necessarily pulling in deps for them, or + creating them when starting up. That way, we could declare that + systemd-journald writes to /var/log/journal, which could be useful when we + doing disk usage calculations and so on. + +* taint systemd if there are fewer than 65536 users assigned (userns) to the system. + +* deprecate RootDirectoryStartOnly= in favour of a new ExecStart= prefix char + +* add a new RuntimeDirectoryPreserve= mode that defines a similar lifecycle for + the runtime dir as we maintain for the fdstore: i.e. keep it around as long + as the unit is running or has a job queued. + +* support projid-based quota in machinectl for containers + +* maybe use SOURCE_DATE_EPOCH (i.e. the env var the reproducible builds folks + introduced) as the RTC epoch, instead of the mtime of NEWS. + +* add a way to lock down cgroup migration: a boolean, which when set for a unit + makes sure the processes in it can never migrate out of it + +* blog about fd store and restartable services + +* document Environment=SYSTEMD_LOG_LEVEL=debug drop-in in debugging document + +* rework ExecOutput and ExecInput enums so that EXEC_OUTPUT_NULL loses its + magic meaning and is no longer upgraded to something else if set explicitly. + +* in the long run: permit a system with /etc/machine-id linked to /dev/null, to + make it lose its identity, i.e. be anonymous. For this we'd have to patch + through the whole tree to make all code deal with the case where no machine + ID is available. + +* optionally, collect cgroup resource data, and store it in per-unit RRD files, + suitable for processing with rrdtool. Add bus API to access this data, and + possibly implement a CPULoad property based on it. + +* beef up pam_systemd to take unit file settings such as cgroups properties as + parameters + +* maybe hook of xfs/ext4 quotactl() with services? i.e. automatically manage + the quota of a the user indicated in User= via unit file settings, like the + other resource management concepts. Would mix nicely with DynamicUser=1. Or + alternatively, do this with projids, so that we can also cover services + running as root. Quota should probably cover all the special dirs such as + StateDirectory=, LogsDirectory=, CacheDirectory=, as well as RootDirectory= if it + is set, plus the whole disk space any image configured with RootImage=. + +* In DynamicUser= mode: before selecting a UID, use disk quota APIs on relevant + disks to see if the UID is already in use. + +* add "systemctl wait" or so, which does what "systemd-run --wait" does, but + for all units. It should be both a way to pin units into memory as well as a + wait to retrieve their exit data. + +* expose IO accounting data on the bus, show it in systemd-run --wait and log + about it in the resource log message + +* show whether a service has out-of-date configuration in "systemctl status" by + using mtime data of ConfigurationDirectory=. + +* replace all remaining uses of fgets() + LINE_MAX by read_line() + +* Add AddUser= setting to unit files, similar to DynamicUser=1 which however + creates a static, persistent user rather than a dynamic, transient user. We + can leverage code from sysusers.d for this. + +* add some optional flag to ReadWritePaths= and friends, that has the effect + that we create the dir in question when the service is started. Example: + + ReadWritePaths=:/var/lib/foobar + +* maybe add call sd_journal_set_block_timeout() or so to set SO_SNDTIMEO for + the sd-journal logging socket, and, if the timeout is set to 0, sets + O_NONBLOCK on it. That way people can control if and when to block for + logging. + +* hostnamed: populate form factor data from a new hwdb database, so that old + yogas can be recognized as "convertible" too, even if they predate the DMI + "convertible" form factor + +* Maybe add a small tool invoked early at boot, that adds in or resizes + partitions automatically, to be used when the media used is actually larger + than the image written onto it is. + +* Maybe add PrivatePIDs= as new unit setting, and do minimal PID namespacing + after all. Be strict however, only support the equivalent of nspawn's + --as-pid2 switch, and sanely proxy sd_notify() messages dropping stuff such + as MAINPID. + +* Add ExecMonitor= setting. May be used multiple times. Forks off a process in + the service cgroup, which is supposed to monitor the service, and when it + exits the service is considered failed by its monitor. + +* track the per-service PAM process properly (i.e. as an additional control + process), so that it may be queried on the bus and everything. + +* add a new "debug" job mode, that is propagated to unit_start() and for + services results in two things: we raise SIGSTOP right before invoking + execve() and turn off watchdog support. Then, use that to implement + "systemd-gdb" for attaching to the start-up of any system service in its + natural habitat. + +* maybe introduce gpt auto discovery for /var/tmp? + +* maybe add gpt-partition-based user management: each user gets his own + LUKS-encrypted GPT partition with a new GPT type. A small nss module + enumerates users via udev partition enumeration. UIDs are assigned in a fixed + way: the partition index is added as offset to some fixed base uid. User name + is stored in GPT partition name. A PAM module authenticates the user via the + LUKS partition password. Benefits: strong per-user security, compatibility + with stateless/read-only/verity-enabled root. (other idea: do this based on + loopback files in /home, without GPT involvement) + +* gpt-auto logic: introduce support for discovering /var matching an image. For + that, use a partition type UUID that is hashed from the OS name (as encoded + in /etc/os-release), the architecture, and 4 new bits from the gpt flags + field of the root partition. This way can easily support multiple OS + installations on the same GPT partition table, without problems with + unmatched /var partitions. + +* gpt-auto logic: related to the above, maybe support a "secondary" root + partition, that is mounted to / and is writable, and where the actual root's + /usr is mounted into. + +* gpt-auto logic: support encrypted swap, add kernel cmdline option to force it, and honour a gpt bit about it, plus maybe a configuration file + +* drop nss-myhostname in favour of nss-resolve? + +* add a percentage syntax for TimeoutStopSec=, e.g. TimeoutStopSec=150%, and + then use that for the setting used in user@.service. It should be understood + relative to the configured default value. + +* in networkd, when matching device types, fix up DEVTYPE rubbish the kernel passes to us + +* enable LockMLOCK to take a percentage value relative to physical memory + +* Permit masking specific netlink APIs with RestrictAddressFamily= + +* nspawn: support that /proc, /sys/, /dev are pre-mounted + +* define gpt header bits to select volatility mode + +* ProtectKernelLogs= (drops CAP_SYSLOG, add seccomp for syslog() syscall, and DeviceAllow to /dev/kmsg) in service files + +* ProtectClock= (drops CAP_SYS_TIMES, adds seecomp filters for settimeofday, adjtimex), sets DeviceAllow o /dev/rtc + +* ProtectTracing= (drops CAP_SYS_PTRACE, blocks ptrace syscall, makes /sys/kernel/tracing go away) + +* ProtectMount= (drop mount/umount/pivot_root from seccomp, disallow fuse via DeviceAllow, imply Mountflags=slave) + +* ProtectKeyRing= to take keyring calls away + +* RemoveKeyRing= to remove all keyring entries of the specified user + +* ProtectReboot= that masks reboot() and kexec_load() syscalls, prohibits kill + on PID 1 with the relevant signals, and makes relevant files in /sys and + /proc (such as the sysrq stuff) unavailable + +* make sure the ratelimit object can deal with USEC_INFINITY as way to turn off things + +* journalctl: make sure -f ends when the container indicated by -M terminates + +* mount: automatically search for "main" partition of an image has multiple + partitions + +* in nss-systemd, if we run inside of RootDirectory= with PrivateUsers= set, + find a way to map the User=/Group= of the service to the right name. This way + a user/group for a service only has to exist on the host for the right + mapping to work. + +* add bus API for creating unit files in /etc, reusing the code for transient units + +* add bus API to remove unit files from /etc + +* add bus API to retrieve current unit file contents (i.e. implement "systemctl cat" on the bus only) + +* rework fopen_temporary() to make use of open_tmpfile_linkable() (problem: the + kernel doesn't support linkat() that replaces existing files, currently) + +* transient units: don't bother with actually setting unit properties, we + reload the unit file anyway + +* journald: sigbus API via a signal-handler safe function that people may call + from the SIGBUS handler + +* optionally, also require WATCHDOG=1 notifications during service start-up and shutdown + +* delay activation of logind until somebody logs in, or when /dev/tty0 pulls it + in or lingering is on (so that containers don't bother with it until PAM is used). also exit-on-idle + +* cache sd_event_now() result from before the first iteration... + +* PID1: find a way how we can reload unit file configuration for + specific units only, without reloading the whole of systemd + +* add an explicit parser for LimitRTPRIO= that verifies + the specified range and generates sane error messages for incorrect + specifications. + +* when we detect that there are waiting jobs but no running jobs, do something + +* push CPUAffinity= also into the "cpuset" cgroup controller (only after the cpuset controller got ported to the unified hierarchy) + +* PID 1 should send out sd_notify("WATCHDOG=1") messages (for usage in the --user mode, and when run via nspawn) + +* there's probably something wrong with having user mounts below /sys, + as we have for debugfs. for example, src/core/mount.c handles mounts + prefixed with /sys generally special. + http://lists.freedesktop.org/archives/systemd-devel/2015-June/032962.html + +* fstab-generator: default to tmpfs-as-root if only usr= is specified on the kernel cmdline + +* docs: bring http://www.freedesktop.org/wiki/Software/systemd/MyServiceCantGetRealtime up to date + +* add a job mode that will fail if a transaction would mean stopping + running units. Use this in timedated to manage the NTP service + state. + http://lists.freedesktop.org/archives/systemd-devel/2015-April/030229.html + +* The udev blkid built-in should expose a property that reflects + whether media was sensed in USB CF/SD card readers. This should then + be used to control SYSTEMD_READY=1/0 so that USB card readers aren't + picked up by systemd unless they contain a medium. This would mirror + the behaviour we already have for CD drives. + +* networkd/udev: implement SR_IOV configuration in .link files: + http://lists.freedesktop.org/archives/systemd-devel/2015-January/027451.html + +* hostnamectl: show root image uuid + +* Find a solution for SMACK capabilities stuff: + http://lists.freedesktop.org/archives/systemd-devel/2014-December/026188.html + +* "systemctl preset-all" should probably order the unit files it + operates on lexicographically before starting to work, in order to + ensure deterministic behaviour if two unit files conflict (like DMs + do, for example) + +* synchronize console access with BSD locks: + http://lists.freedesktop.org/archives/systemd-devel/2014-October/024582.html + +* as soon as we have sender timestamps, revisit coalescing multiple parallel daemon reloads: + http://lists.freedesktop.org/archives/systemd-devel/2014-December/025862.html + +* in systemctl list-unit-files: show the install value the presets would suggest for a service in a third column + +* figure out when we can use the coarse timers + +* add "systemctl start -v foobar.service" that shows logs of a service + while the start command runs. This is non-trivial to do without + races though, since we should flush out all journal messages before + returning from the "systemctl stop". + +* firstboot: make it useful to be run immediately after yum --installroot to set up a machine. (most specifically, make --copy-root-password work even if /etc/passwd already exists + +* maybe add support for specifier expansion in user.conf, specifically DefaultEnvironment= + +* maybe allow timer units with an empty Units= setting, so that they + can be used for resuming the system but nothing else. + +* what to do about udev db binary stability for apps? (raw access is not an option) + +* man: maybe use the word "inspect" rather than "introspect"? + +* systemctl: if some operation fails, show log output? + +* systemctl edit: use equivalent of cat() to insert existing config as a comment, prepended with #. + Upon editor exit, lines with one # are removed, lines with two # are left with one #, etc. + +* exponential backoff in timesyncd when we cannot reach a server + +* timesyncd: add ugly bus calls to set NTP servers per-interface, for usage by NM + +* merge ~/.local/share and ~/.local/lib into one similar /usr/lib and /usr/share.... + +* systemd.show_status= should probably have a mode where only failed + units are shown. + +* add systemd.abort_on_kill or some other such flag to send SIGABRT instead of SIGKILL + (throughout the codebase, not only PID1) + +* resolved: + - mDNS/DNS-SD + - service registration + - service/domain/types browsing + - avahi compat + - DNS-SD service registration from socket units + - resolved should optionally register additional per-interface LLMNR + names, so that for the container case we can establish the same name + (maybe "host") for referencing the server, everywhere. + - allow clients to request DNSSEC for a single lookup even if DNSSEC is off (?) + - hook up resolved with machined-based address resolution + +* refcounting in sd-resolve is borked + +* Add a new verb "systemctl top" + +* add new gpt type for btrfs volumes + +* support empty /etc boots nicely: + - nspawn/gpt-generator: introduce new gpt partition type for /usr + +* generator that automatically discovers btrfs subvolumes, identifies their purpose based on some xattr on them. + +* a way for container managers to turn off getty starting via $container_headless= or so... + +* figure out a nice way how we can let the admin know what child/sibling unit causes cgroup membership for a specific unit + +* For timer units: add some mechanisms so that timer units that trigger immediately on boot do not have the services + they run added to the initial transaction and thus confuse Type=idle. + +* add bus api to query unit file's X fields. + +* gpt-auto-generator: + - Define new partition type for encrypted swap? Support probed LUKS for encrypted swap? + - Make /home automount rather than mount? + +* add generator that pulls in systemd-network from containers when + CAP_NET_ADMIN is set, more than the loopback device is defined, even + when it is otherwise off + +* MessageQueueMessageSize= (and suchlike) should use parse_iec_size(). + +* implement Distribute= in socket units to allow running multiple + service instances processing the listening socket, and open this up + for ReusePort= + +* introduce bus call FreezeUnit(s, b), as well as "systemctl freeze + $UNIT" and "systemctl thaw $UNIT" as wrappers around this. The calls + should SIGSTOP all unit processes in a loop until all processes of + it are fully stopped. This can later be used for app management by + desktop UIs such as gnome-shell to freeze apps that are not visible + on screen, not unlike how job control works on the shell + +* cgroups: + - implement per-slice CPUFairScheduling=1 switch + - introduce high-level settings for RT budget, swappiness + - how to reset dynamically changed unit cgroup attributes sanely? + - when reloading configuration, apply new cgroup configuration + - when recursively showing the cgroup hierarchy, optionally also show + the hierarchies of child processes + +* transient units: + - add field to transient units that indicate whether systemd or somebody else saves/restores its settings, for integration with libvirt + +* when we detect low battery and no AC on boot, show pretty splash and refuse boot + +* libsystemd-journal, libsystemd-login, libudev: add calls to easily attach these objects to sd-event event loops + +* be more careful what we export on the bus as (usec_t) 0 and (usec_t) -1 + +* rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it + +* After coming back from hibernation reset hibernation swap partition using the /dev/snapshot ioctl APIs + +* If we try to find a unit via a dangling symlink, generate a clean + error. Currently, we just ignore it and read the unit from the search + path anyway. + +* refuse boot if /usr/lib/os-release is missing or /etc/machine-id cannot be set up + +* man: the documentation of Restart= currently is very misleading and suggests the tools from ExecStartPre= might get restarted. + +* load .d/*.conf dropins for device units + +* sd-bus: + - EBADSLT handling + - GetAllProperties() on a non-existing object does not result in a failure currently + - port to sd-resolve for connecting to TCP dbus servers + - see if we can introduce a new sd_bus_get_owner_machine_id() call to retrieve the machine ID of the machine of the bus itself + - see if we can drop more message validation on the sending side + - add API to clone sd_bus_message objects + - longer term: priority inheritance + - dbus spec updates: + - NameLost/NameAcquired obsolete + - GVariant + - path escaping + - update systemd.special(7) to mention that dbus.socket is only about the compatibility socket now + +* sd-event + - allow multiple signal handlers per signal? + - document chaining of signal handler for SIGCHLD and child handlers + - define more intervals where we will shift wakeup intervals around in, 1h, 6h, 24h, ... + - generate a failure of a default event loop is executed out-of-thread + +* investigate endianness issues of UUID vs. GUID + +* dbus: when a unit failed to load (i.e. is in UNIT_ERROR state), we + should be able to safely try another attempt when the bus call LoadUnit() is invoked. + +* add a pam module that passes the hdd passphrase into the PAM stack and then expires it, for usage by gdm auto-login. + +* add a pam module that on password changes updates any LUKS slot where the password matches + +* test/: + - add unit tests for config_parse_device_allow() + +* seems that when we follow symlinks to units we prefer the symlink + destination path over /etc and /usr. We should not do that. Instead + /etc should always override /run+/usr and also any symlink + destination. + +* when isolating, try to figure out a way how we implicitly can order + all units we stop before the isolating unit... + +* teach ConditionKernelCommandLine= globs or regexes (in order to match foobar={no,0,off}) + +* BootLoaderSpec: Clarify that the kernel has to be in $BOOT. Clarify + that the boot loader should be installed to the ESP. Define a way + how an installer can figure out whether a BLS compliant boot loader + is installed. + +* think about requeuing jobs when daemon-reload is issued? usecase: + the initrd issues a reload after fstab from the host is accessible + and we might want to requeue the mounts local-fs acquired through + that automatically. + +* systemd-inhibit: make taking delay locks useful: support sending SIGINT or SIGTERM on PrepareForSleep() + +* remove any syslog support from log.c — we probably cannot do this before split-off udev is gone for good + +* shutdown logging: store to EFI var, and store to USB stick? + +* merge unit_kill_common() and unit_kill_context() + +* EFI: + - honor language efi variables for default language selection (if there are any?) + - honor timezone efi variables for default timezone selection (if there are any?) + - change bootctl to be backed by systemd-bootd to control temporary and persistent default boot goal plus efi variables +* bootctl + - recognize the case when not booted on EFI + +* maybe do not install getty@tty1.service symlink in /etc but in /usr? + +* print a nicer explanation if people use variable/specifier expansion in ExecStart= for the first word + +* mount: turn dependency information from /proc/self/mountinfo into dependency information between systemd units. + +* logind: + - logind: optionally, ignore idle-hint logic for autosuspend, block suspend as long as a session is around + - logind: wakelock/opportunistic suspend support + - Add pretty name for seats in logind + - logind: allow showing logout dialog from system? + - add Suspend() bus calls which take timestamps to fix double suspend issues when somebody hits suspend and closes laptop quickly. + - if pam_systemd is invoked by su from a process that is outside of a + any session we should probably just become a NOP, since that's + usually not a real user session but just some system code that just + needs setuid(). + - logind: make the Suspend()/Hibernate() bus calls wait for the for + the job to be completed. before returning, so that clients can wait + for "systemctl suspend" to finish to know when the suspending is + complete. + - logind: when the power button is pressed short, just popup a + logout dialog. If it is pressed for 1s, do the usual + shutdown. Inspiration are Macs here. + - expose "Locked" property on logind sesison objects + - maybe allow configuration of the StopTimeout for session scopes + - rename session scope so that it includes the UID. THat way + the session scope can be arranged freely in slices and we don't have + make assumptions about their slice anymore. + - follow PropertiesChanged state more closely, to deal with quick logouts and + relogins + +* journal: + - consider introducing implicit _TTY= + _PPID= + _EUID= + _EGID= + _FSUID= + _FSGID= fields + - journald: also get thread ID from client, plus thread name + - journal: when waiting for journal additions in the client always sleep at least 1s or so, in order to minimize wakeups + - add API to close/reopen/get fd for journal client fd in libsystemd-journal. + - fallback to /dev/log based logging in libsystemd-journal, if we cannot log natively? + - declare the local journal protocol stable in the wiki interface chart + - sd-journal: speed up sd_journal_get_data() with transparent hash table in bg + - journald: when dropping msgs due to ratelimit make sure to write + "dropped %u messages" not only when we are about to print the next + message that works, but already after a short timeout + - check if we can make journalctl by default use --follow mode inside of less if called without args? + - maybe add API to send pairs of iovecs via sd_journal_send + - journal: add a setgid "systemd-journal" utility to invoke from libsystemd-journal, which passes fds via STDOUT and does PK access + - journactl: support negative filtering, i.e. FOOBAR!="waldo", + and !FOOBAR for events without FOOBAR. + - journal: store timestamp of journal_file_set_offline() int he header, + so it is possible to display when the file was last synced. + - journal-send.c, log.c: when the log socket is clogged, and we drop, count this and write a message about this when it gets unclogged again. + - journal: find a way to allow dropping history early, based on priority, other rules + - journal: When used on NFS, check payload hashes + - journald: add kernel cmdline option to disable ratelimiting for debug purposes + - refuse taking lower-case variable names in sd_journal_send() and friends. + - journald: we currently rotate only after MaxUse+MaxFilesize has been reached. + - journal: deal nicely with byte-by-byte copied files, especially regards header + - journal: sanely deal with entries which are larger than the individual file size, but where the components would fit + - Replace utmp, wtmp, btmp, and lastlog completely with journal + - journalctl: instead --after-cursor= maybe have a --cursor=XYZ+1 syntax? + - when a kernel driver logs in a tight loop, we should ratelimit that too. + - journald: optionally, log debug messages to /run but everything else to /var + - journald: when we drop syslog messages because the syslog socket is + full, make sure to write how many messages are lost as first thing + to syslog when it works again. + - change systemd-journal-flush into a service that stays around during + boot, and causes the journal to be moved back to /run on shutdown, + so that we do not keep /var busy. This needs to happen synchronously, + hence doing this via signals is not going to work. + - optionally support running journald from the command line for testing purposes in external projects + - journald: allow per-priority and per-service retention times when rotating/vacuuming + - journald: make use of uid-range.h to managed uid ranges to split + journals in. + - journalctl: add the ability to look for the most recent process of a binary. journalctl /usr/bin/X11 --pid=-1 or so... + - improve journalctl performance by loading journal files + lazily. Encode just enough information in the file name, so that we + do not have to open it to know that it is not interesting for us, for + the most common operations. + - man: document that corrupted journal files is nothing to act on + - rework journald sigbus stuff to use mutex + - Set RLIMIT_NPROC for systemd-journal-xyz, and all other of our + services that run under their own user ids, and use User= (but only + in a world where userns is ubiquitous since otherwise we cannot + invoke those daemons on the host AND in a container anymore). Also, + if LimitNPROC= is used without User= we should warn and refuse + operation. + - journalctl --verify: don't show files that are currently being + written to as FAIL, but instead show that their are being written to. + - add journalctl -H that talks via ssh to a remote peer and passes through + binary logs data + - add a version of --merge which also merges /var/log/journal/remote + - journalctl: -m should access container journals directly by enumerating + them via machined, and also watch containers coming and going. + Benefit: nspawn --ephemeral would start working nicely with the journal. + - assign MESSAGE_ID to log messages about failed services + +* add a test if all entries in the catalog are properly formatted. + (Adding dashes in a catalog entry currently results in the catalog entry + being silently skipped. journalctl --update-catalog must warn about this, + and we should also have a unit test to check that all our message are OK.) + +* document: + - document that deps in [Unit] sections ignore Alias= fields in + [Install] units of other units, unless those units are disabled + - man: clarify that time-sync.target is not only sysv compat but also useful otherwise. Same for similar targets + - document that service reload may be implemented as service reexec + - add a man page containing packaging guidelines and recommending usage of things like Documentation=, PrivateTmp=, PrivateNetwork= and ReadOnlyDirectories=/etc /usr. + - document systemd-journal-flush.service properly + - documentation: recommend to connect the timer units of a service to the service via Also= in [Install] + - man: document the very specific env the shutdown drop-in tools live in + - man: add more examples to man pages + - man: maybe sort directives in man pages, and take sections from --help and apply them to man too + - document root=gpt-auto properly + +* systemctl: + - add systemctl switch to dump transaction without executing it + - Add a verbose mode to "systemctl start" and friends that explains what is being done or not done + - "systemctl disable" on a static unit prints no message and does + nothing. "systemctl enable" does nothing, and gives a bad message + about it. Should fix both to print nice actionable messages. + - print nice message from systemctl --failed if there are no entries shown, and hook that into ExecStartPre of rescue.service/emergency.service + - add new command to systemctl: "systemctl system-reexec" which reexecs as many daemons as virtually possible + - systemctl enable: fail if target to alias into does not exist? maybe show how many units are enabled afterwards? + - systemctl: "Journal has been rotated since unit was started." message is misleading + - systemctl status output should include list of triggering units and their status + +* unit install: + - "systemctl mask" should find all names by which a unit is accessible + (i.e. by scanning for symlinks to it) and link them all to /dev/null + +* timer units: + - timer units should get the ability to trigger when: + o DST changes + - Modulate timer frequency based on battery state + +* add libsystemd-password or so to query passwords during boot using the password agent logic + +* clean up date formatting and parsing so that all absolute/relative timestamps we format can also be parsed + +* on shutdown: move utmp, wall, audit logic all into PID 1 (or logind?), get rid of systemd-update-utmp-runlevel + +* make repeated alt-ctrl-del presses printing a dump + +* hostnamed: before returning information from /etc/machine-info.conf check the modification data and reread. Similar for localed, ... + +* currently x-systemd.timeout is lost in the initrd, since crypttab is copied into dracut, but fstab is not + +* nspawn: + - emulate /dev/kmsg using CUSE and turn off the syslog syscall + with seccomp. That should provide us with a useful log buffer that + systemd can log to during early boot, and disconnect container logs + from the kernel's logs. + - as soon as networkd has a bus interface, hook up --network-interface=, + --network-bridge= with networkd, to trigger netdev creation should an + interface be missing + - a nice way to boot up without machine id set, so that it is set at boot + automatically for supporting --ephemeral. Maybe hash the host machine id + together with the machine name to generate the machine id for the container + - fix logic always print a final newline on output. + https://github.com/systemd/systemd/pull/272#issuecomment-113153176 + - should optionally support receiving WATCHDOG=1 messages from its payload + PID 1... + - optionally automatically add FORWARD rules to iptables whenever nspawn is + running, remove them when shut down. + +* dissect + - refuse mounting over a mount point + - automatically discover .roothash files in dissect, similarly to nspawn + +* machined: + - add an API so that libvirt-lxc can inform us about network interfaces being + removed or added to an existing machine + - "machinectl migrate" or similar to copy a container from or to a + difference host, via ssh + - introduce systemd-nspawn-ephemeral@.service, and hook it into + "machinectl start" with a new --ephemeral switch + - "machinectl status" should also show internal logs of the container in + question + - "machinectl history" + - "machinectl diff" + - "machinectl commit" that takes a writable snapshot of a tree, invokes a + shell in it, and marks it read-only after use + +* cryptsetup: + - cryptsetup-generator: allow specification of passwords in crypttab itself + - support rd.luks.allow-discards= kernel cmdline params in cryptsetup generator + +* hw watchdog: optionally try to use the preset watchdog timeout instead of always overriding it + https://bugs.freedesktop.org/show_bug.cgi?id=54712 + +* add a dependency on standard-conf.xml and other included files to man pages + +* MountFlags=shared acts as MountFlags=slave right now. + +* properly handle loop back mounts via fstab, especially regards to fsck/passno + +* initialize the hostname from the fs label of /, if /etc/hostname does not exist? + +* udev: + - move to LGPL + - kill scsi_id + - add trigger --subsystem-match=usb/usb_device device + - reimport udev db after MOVE events for devices without dev_t + +* There's currently no way to cancel fsck (used to be possible via C-c or c on the console) + +* add option to sockets to avoid activation. Instead just drop packets/connections, see http://cyberelk.net/tim/2012/02/15/portreserve-systemd-solution/ + +* coredump: + - save coredump in Windows/Mozilla minidump format + - when truncating coredumps, also log the full size that the process had, and make a metadata field so we can report truncated coredumps + +* support crash reporting operation modes (https://live.gnome.org/GnomeOS/Design/Whiteboards/ProblemReporting) + +* be able to specify a forced restart of service A where service B depends on, in case B + needs to be auto-respawned? + +* tmpfiles: + - apply "x" on "D" too (see patch from William Douglas) + - instead of ignoring unknown fields, reject them. + - creating new directories/subvolumes/fifos/device nodes + should not follow symlinks. None of the other adjustment or creation + calls follow symlinks. + +* make sure systemd-ask-password-wall does not shutdown systemd-ask-password-console too early + +* verify that the AF_UNIX sockets of a service in the fs still exist + when we start a service in order to avoid confusion when a user + assumes starting a service is enough to make it accessible + +* Make it possible to set the keymap independently from the font on + the kernel cmdline. Right now setting one resets also the other. + +* and a dbus call to generate target from current state + +* write blog stories about: + - hwdb: what belongs into it, lsusb + - enabling dbus services + - how to make changes to sysctl and sysfs attributes + - remote access + - how to pass throw-away units to systemd, or dynamically change properties of existing units + - testing with Harald's awesome test kit + - auto-restart + - how to develop against journal browsing APIs + - the journal HTTP iface + - non-cgroup resource management + - dynamic resource management with cgroups + - refreshed, longer missions statement + - calendar time events + - init=/bin/sh vs. "emergency" mode, vs. "rescue" mode, vs. "multi-user" mode, vs. "graphical" mode, and the debug shell + - how to create your own target + - instantiated apache, dovecot and so on + - hooking a script into various stages of shutdown/rearly booot + +* investigate whether the gnome pty helper should be moved into systemd, to provide cgroup support. + +* dot output for --test showing the 'initial transaction' + +* pid1: + - When logging about multiple units (stopping BoundTo units, conflicts, etc.), + log both units as UNIT=, so that journalctl -u triggers on both. + - generate better errors when people try to set transient properties + that are not supported... + http://lists.freedesktop.org/archives/systemd-devel/2015-February/028076.html + - maybe introduce WantsMountsFor=? Usecase: + http://lists.freedesktop.org/archives/systemd-devel/2015-January/027729.html + - recreate systemd's D-Bus private socket file on SIGUSR2 + - move PAM code into its own binary + - when we automatically restart a service, ensure we restart its rdeps, too. + - hide PAM options in fragment parser when compile time disabled + - Support --test based on current system state + - If we show an error about a unit (such as not showing up) and it has no Description string, then show a description string generated form the reverse of unit_name_mangle(). + - after deserializing sockets in socket.c we should reapply sockopts and things + - drop PID 1 reloading, only do reexecing (difficult: Reload() + currently is properly synchronous, Reexec() is weird, because we + cannot delay the response properly until we are back, so instead of + being properly synchronous we just keep open the fd and close it + when done. That means clients do not get a successful method reply, + but much rather a disconnect on success. + - when breaking cycles drop sysv services first, then services from /run, then from /etc, then from /usr + - when a bus name of a service disappears from the bus make sure to queue further activation requests + +* unit files: + - allow port=0 in .socket units + - maybe introduce ExecRestartPre= + - add ReloadSignal= for configuring a reload signal to use + - implement Register= switch in .socket units to enable registration + in Avahi, RPC and other socket registration services. + - allow Type=simple with PIDFile= + https://bugzilla.redhat.com/show_bug.cgi?id=723942 + - allow writing multiple conditions in unit files on one line + - load-fragment: when loading a unit file via a chain of symlinks + verify that it is not masked via any of the names traversed. + - introduce Type=pid-file + - introduce mix of BindTo and Requisite + - add a concept of RemainAfterExit= to scope units + - Allow multiple ExecStart= for all Type= settings, so that we can cover rescue.service nicely + - add verification of [Install] section to systemd-analyze verify + +* udev-link-config: + - Make sure ID_PATH is always exported and complete for + network devices where possible, so we can safely rely + on Path= matching + +* sd-rtnl: + - add support for more attribute types + - inbuilt piping support (essentially degenerate async)? see loopback-setup.c and other places + +* networkd: + - add more keys to [Route] and [Address] sections + - add support for more DHCPv4 options (and, longer term, other kinds of dynamic config) + - add proper initrd support (in particular generate .network/.link files based on /proc/cmdline) + - add reduced [Link] support to .network files + - add Scope= parsing option for [Network] + - properly handle routerless dhcp leases + - work with non-Ethernet devices + - add support for more bond options + - dhcp: do we allow configuring dhcp routes on interfaces that are not the one we got the dhcp info from? + - the DHCP lease data (such as NTP/DNS) is still made available when + a carrier is lost on a link. It should be removed instantly. + - expose in the API the following bits: + - option 15, domain name and/or option 119, search list + - option 12, host name and/or option 81, fqdn + - option 123, 144, geolocation + - option 252, configure http proxy (PAC/wpad) + - provide a way to define a per-network interface default metric value + for all routes to it. possibly a second default for DHCP routes. + - allow Name= to be specified repeatedly in the [Match] section. Maybe also + support Name=foo*|bar*|baz ? + - duplicate address check for static IPs (like ARPCHECK in network-scripts) + - allow DUID/IAID to be customized, see issue #394. + - whenever uplink info changes, make DHCP server send out FORCERENEW + +* networkd-wait-online: + - make operstates to wait for configurable? + +* dhcp: + - figure out how much we can increase Maximum Message Size + +* dhcp6: + - add functions to set previously stored IPv6 addresses on startup and get + them at shutdown; store them in client->ia_na + - write more test cases + - implement reconfigure support, see 5.3., 15.11. and 22.20. + - implement support for temporary adressess (IA_TA) + - implement dhcpv6 authentication + - investigate the usefulness of Confirm messages; i.e. are there any + situations where the link changes without any loss in carrier detection + or interface down + - some servers don't do rapid commit without a filled in IA_NA, verify + this behavior + - RouteTable= ? + +External: + +* dbus: + - natively watch for dbus-*.service symlinks (PENDING) + - teach dbus to activate all services it finds in /etc/systemd/services/org-*.service + +* fix alsa mixer restore to not print error when no config is stored + +* make cryptsetup lower --iter-time + +* patch kernel for xattr support in /dev, /proc/, /sys? + +* kernel: add device_type = "fb", "fbcon" to class "graphics" + +* /usr/bin/service should actually show the new command line + +* fedora: suggest auto-restart on failure, but not on success and not on coredump. also, ask people to think about changing the start limit logic. Also point people to RestartPreventExitStatus=, SuccessExitStatus= + +* fedora: F20: go timer units all the way, leave cron.daily for cron + +* neither pkexec nor sudo initialize environ[] from the PAM environment? + +* fedora: update policy to declare access mode and ownership of unit files to root:root 0644, and add an rpmlint check for it + +* register catalog database signature as file magic + +* zsh shell completion: + - - should complete options, but currently does not + - systemctl add-wants,add-requires + +* systemctl status should know about 'systemd-analyze calendar ... --iterations=' +* If timer has just OnInactiveSec=..., it should fire after a specified time + after being started. + +Regularly: + +* look for close() vs. close_nointr() vs. close_nointr_nofail() + +* check for strerror(r) instead of strerror(-r) + +* pahole + +* set_put(), hashmap_put() return values check. i.e. == 0 does not free()! + +* use secure_getenv() instead of getenv() where appropriate + +* link up selected blog stories from man pages and unit files Documentation= fields +String is not UTF-8 clean, ignoring assignment + timedatex.service: Consumed 26ms CPU time. diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 00000000..b3219626 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,15 @@ +trigger: +- master + +jobs: +- job: FuzzBuzz + displayName: FuzzBuzz + + pool: + vmImage: 'ubuntu-latest' + + steps: + - script: | + set -e + ./travis-ci/managers/fuzzbuzz.sh + displayName: 'This is where it gets darker' diff --git a/catalog/meson.build b/catalog/meson.build new file mode 100644 index 00000000..3db8e390 --- /dev/null +++ b/catalog/meson.build @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +in_files = ''' + systemd.bg.catalog + systemd.be.catalog + systemd.be@latin.catalog + systemd.de.catalog + systemd.fr.catalog + systemd.it.catalog + systemd.pl.catalog + systemd.pt_BR.catalog + systemd.ru.catalog + systemd.zh_CN.catalog + systemd.zh_TW.catalog + systemd.catalog +'''.split() + +support_url = get_option('support-url') +support_sed = 's~%SUPPORT_URL%~@0@~'.format(support_url) + +foreach file : in_files + custom_target( + file, + input : file + '.in', + output: file, + command : [sed, support_sed, '@INPUT@'], + capture : true, + install : true, + install_dir : catalogdir) +endforeach + +meson.add_install_script('sh', '-c', + 'test -n "$DESTDIR" || @0@/journalctl --update-catalog' + .format(rootbindir)) diff --git a/catalog/systemd.be.catalog.in b/catalog/systemd.be.catalog.in new file mode 100644 index 00000000..c5786c40 --- /dev/null +++ b/catalog/systemd.be.catalog.in @@ -0,0 +1,297 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Message catalog for systemd's own messages +# Belarusian translation + +# Фармат каталога апісаны на старонцы +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# For an explanation why we do all this, see https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: Сэрвіс журналявання запусціўся +Defined-By: systemd +Support: %SUPPORT_URL% + +Працэс сістэмнага журналявання запусціўся, адкрыў файлы для +запісу і гатовы апрацоўваць запыты. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: Сэрвіс журналявання спыніўся +Defined-By: systemd +Support: %SUPPORT_URL% + +Працэс сістэмнага журналявання спыніўся і закрыў усе файлы. + +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: Дыскавае месца, занятае часопісам +Defined-By: systemd +Support: %SUPPORT_URL% + +@JOURNAL_NAME@ (@JOURNAL_PATH@) цяпер займае @CURRENT_USE_PRETTY@. +Максімальна дазволены памер складае @MAX_USE_PRETTY@. +Пакідаем вольнымі не меньш за @DISK_KEEP_FREE_PRETTY@ (даступна на дыску +@DISK_AVAILABLE_PRETTY@). +Такім чынам, ліміт складае @LIMIT_PRETTY@, з якіх @AVAILABLE_PRETTY@ +даступна. + +Ліміты на памер наладжваецца з дапамогай SystemMaxUse=, SystemKeepFree=, +SystemMaxFileSize=, RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= у +файле /etc/systemd/journald.conf. Глядзіце journald.conf(5) для дэталей. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Паведамленні з сэрвісу адкінуты +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Сэрвіс адправіў занадта штат паведамленняў за кароткі прамежак часу. +Частка паведамленняў была адкінута. + +Майце на ўвазе, што былі адкінуты паведамлення толькі гэтага сэрвісу. +Паведамленні іншых сэрвісаў засталіся. + +Мяжа, пасля якой паведамленні будуць адкінуты, наладжваецца з дапамогай +RateLimitIntervalSec= і RateLimitBurst= у файле /etc/systemd/journald.conf. +Глядзіце journald.conf(5) для дэталей. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Паведамленні страчаны +Defined-By: systemd +Support: %SUPPORT_URL% + +Паведамленні ядра былі страчаны, так як сістэма журналявання не паспела +іх апрацаваць. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Працэс @COREDUMP_PID@ (@COREDUMP_COMM@) скінуў дамп памяці +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Працэс @COREDUMP_PID@ (@COREDUMP_COMM@) разбіўся і скінуў дамп памяці. + +Звычайна гэта сведчыць аб памылцы ў праграмным кодзе. +Рэкамендуецца паведаміць аб гэтым распрацоўнікам. + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: Новая сесія № @SESSION_ID@ створана для карыстальніка @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Новая сесія з № @SESSION_ID@ створана для карыстальніка @USER_ID@. + +Лідар гэтай сесіі пад № @LEADER@. + +-- 3354939424b4456d9802ca8333ed424a +Subject: Сесія № @SESSION_ID@ спынена +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Сесія № @SESSION_ID@ спынена. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: Даступна новае працоўнае месца № @SEAT_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Новае працоўнае месца № @SEAT_ID@ наладжана і даступна для выкарыстання. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Працоўнае месца № @SEAT_ID@ выдалена +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Працоўнае месца № @SEAT_ID@ выдалена і больш не даступна. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Час зменены +Defined-By: systemd +Support: %SUPPORT_URL% + +Сістэмны гадзіннік зменены на @REALTIME@ мікрасекунд ад 1 студзеня 1970. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Часавы пояс зменены на @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Сістэмны часавы пояс зменены на @TIMEZONE@. + +-- b07a249cd024414a82dd00cd181378ff +Subject: Запуск сістэмы завяршыўся +Defined-By: systemd +Support: %SUPPORT_URL% + +Усе сістэмныя сэрвісы, неабходныя для загрузкі сістэмы, паспяхова +запусціліся. Майце на ўвазе, што гэта не значыць, што машына нічога не +робіць. Магчыма, некаторыя сэрвісы яшчэ ініцыялізіруюцца. + +На запуск ядра спатрэбілася @KERNEL_USEC@ мікрасекунд. + +На запуск пачатковага RAM-дыска спатрэбілася @INITRD_USEC@ мікрасекунд. + +На запуск сістэмных сэрвісаў спатрэбілася @USERSPACE_USEC@ мікрасекунд. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: Сістэма перайшла ў стан сну @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Цяпер сістэма перайшла у стан сну @SLEEP@. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: Сістэма выйшла са стана сну @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Цяпер сістэма выйшла са стана сну @SLEEP@. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Сістэма завяршае работу +Defined-By: systemd +Support: %SUPPORT_URL% + +Пачаўся працэс выключэння сістэмы. +Спыняюцца ўсе сістэмныя сэрвісы і дэмантуюцца файлавыя сістэмы. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: Юніт @UNIT@ запускаецца +Defined-By: systemd +Support: %SUPPORT_URL% + +Пачаўся працэс запуску юніта @UNIT@. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: Юніт @UNIT@ запусціўся +Defined-By: systemd +Support: %SUPPORT_URL% + +Працэс запуску юніта @UNIT@ завершаны. + +Вынік: @JOB_RESULT@. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: Юніт @UNIT@ спыняецца +Defined-By: systemd +Support: %SUPPORT_URL% + +Пачаўся працэс спынення юніта @UNIT@. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: Юніт @UNIT@ спынены +Defined-By: systemd +Support: %SUPPORT_URL% + +Працэс спынення юніта @UNIT@ завершаны. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: Збой юніта @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Збой юніта @UNIT@. + +Вынік: @JOB_RESULT@. + +-- d34d037fff1847e6ae669a370e694725 +Subject: Юніт @UNIT@ перачытвае сваю канфігурацыю +Defined-By: systemd +Support: %SUPPORT_URL% + +Юніт @UNIT@ пачаў перачытваць сваю канфігурацыю. + +-- 7b05ebc668384222baa8881179cfda54 +Subject: Юніт @UNIT@ перачытаў сваю канфігурацыю +Defined-By: systemd +Support: %SUPPORT_URL% + +Юніт @UNIT@ перачытаў сваю канфігурацыю. + +Вынік: @JOB_RESULT@. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Працэс @EXECUTABLE@ не можа быць выкананы +Defined-By: systemd +Support: %SUPPORT_URL% + +Працэс @EXECUTABLE@ не можа быць выкананы ў выніку збою. + +Ён вярнуў памылку нумар @ERRNO@. + +-- 0027229ca0644181a76c4e92458afa2e +Sibject: Адно ці больш паведамленняў не былі накіраваны ў syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +Адно ці больш паведамленняў не былі накіраваны ў syslog сэрвіс, які +выконваецца паралельна з journald. Звычайна гэта значыць, што +рэалізацыя syslog не паспявае апрацаваць паведамленні з неабходнай +хуткасцю. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Кропка мантавання не пустая +Defined-By: systemd +Support: %SUPPORT_URL% + +Каталог @WHERE@ указаны як кропка мантавання (другое поле ў /etc/fstab ці +Where= поле ў файле юніта systemd) і не пусты. Гэта не перашкаджае +мантаванню, але існуючыя ў ім файлы будуць недаступны. Для доступу да іх, +калі ласка, змантуйце гэтую файлавую сістэму ў іншае месца. + +-- 24d8d4452573402496068381a6312df2 +Subject: Віртуальная машына або кантэйнер запусціўся +Defined-By: systemd +Support: %SUPPORT_URL% + +Віртуальная машына @NAME@ з лідарам № @LEADER@ запусцілася і +гатова для выкарыстання. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: Віртуальная машына або кантэйнер спынены +Defined-By: systemd +Support: %SUPPORT_URL% + +Віртуальная машына @NAME@ з лідарам № @LEADER@ спынена. + +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: Механізм DNSSEC адключаны, бо сервер не падтымлівае яго +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +Сэрвіс вызначэння імён (systemd-resolved.service) вызначыў, што DNS-сервер +не падтрымлівае механізм DNSSEC. У выніку праверка DNSSEC была адключана. + +Гэтая падзея ўзнікае калі наладжаны DNSSEC=allow-downgrade +у файле resolved.conf і DNS-сервер не падтрымлівае механізм DNSSEC. +Звярніце ўвагу, што рэжым allow-downgrade дазваляе правесці атаку +«DNSSEC downgrade», у ходзе якой зламыснік можа адключыць праверку DNSSEC +шляхам падстаноўкі падробленых DNSSEC-адказаў у камунікацыйны канал. + +Гэта падзея можа быць прыкметай таго, што DNS-сервер сапраўды несумяшчальны +з DNSSEC або што зламысніку паспяхова атрымалася правесці атаку па +адключэнню DNSSEC. + +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: Збой пры праверцы DNSSEC +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +DNS-запыт або рэсурсны запіс не прайшоў праверку DNSSEC. +Як правіла, гэта паказвае на знешняе ўздзеянне на канал сувязі. + +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: Давераны ключ DNSSEC быў ануляваны +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Давераны ключ DNSSEC быў ануляваны. Неабходна наладзіць новы давераны ключ +або абнавіць аперацыйную сістэму, каб атрымаць абноўлены давераны ключ +DNSSEC. diff --git a/catalog/systemd.be@latin.catalog.in b/catalog/systemd.be@latin.catalog.in new file mode 100644 index 00000000..bec5c6f0 --- /dev/null +++ b/catalog/systemd.be@latin.catalog.in @@ -0,0 +1,302 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Message catalog for systemd's own messages +# Belarusian Latin translation + +# Farmat kataloha apisany na staroncy +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# For an explanation why we do all this, see https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: Servis žurnaliavannia zapusciŭsia +Defined-By: systemd +Support: %SUPPORT_URL% + +Praces sistemnaha žurnaliavannia zapusciŭsia, adkryŭ fajly dlia +zapisu i hatovy apracoŭvać zapyty. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: Servis žurnaliavannia spyniŭsia +Defined-By: systemd +Support: %SUPPORT_URL% + +Praces sistemnaha žurnaliavannia spyniŭsia i zakryŭ usie fajly. + +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: dyskavaje miesca, zaniataje časopisam +Defined-By: systemd +Support: %SUPPORT_URL% + +@JOURNAL_NAME@ (@JOURNAL_PATH@) ciapier zajmaje @CURRENT_USE_PRETTY@. +Maksimaĺna dazvolieny pamier skladaje @MAX_USE_PRETTY@. +Pakidajem voĺnymi nie mieńš za @DISK_KEEP_FREE_PRETTY@ (dastupna na dysku +@DISK_AVAILABLE_PRETTY@). +Takim čynam, limit skladaje @LIMIT_PRETTY@, z jakich @AVAILABLE_PRETTY@ +dastupna. + +Limity na pamier naladžvaiecca z dapamohaj SystemMaxUse=, SystemKeepFree=, +SystemMaxFileSize=, RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= u +fajlie /etc/systemd/journald.conf. Hliadzicie journald.conf(5) dlia +detaliej. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Paviedamlienni z servisu adkinuty +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Servis adpraviŭ zanadta štat paviedamlienniaŭ za karotki pramiežak času. +Častka paviedamlienniaŭ byla adkinuta. + +Majcie na ŭvazie, što byli adkinuty paviedamliennia toĺki hetaha servisu. +Paviedamlienni inšych servisaŭ zastalisia. + +Miaža, paslia jakoj paviedamlienni buduć adkinuty, naladžvajecca z dapamohaj +RateLimitIntervalSec= i RateLimitBurst= u fajlie /etc/systemd/journald.conf. +Hliadzicie journald.conf(5) dlia detaliej. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Paviedamlienni stračany +Defined-By: systemd +Support: %SUPPORT_URL% + +Paviedamlienni jadra byli stračany, tak jak sistema žurnaliavannia nie +paspiela ich apracavać. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Praces @COREDUMP_PID@ (@COREDUMP_COMM@) skinuŭ damp pamiaci +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Praces @COREDUMP_PID@ (@COREDUMP_COMM@) razbiŭsia i skinuŭ damp pamiaci. + +Zvyčajna heta sviedčyć ab pamylcy ŭ prahramnym kodzie. +Rekamiendujecca paviedamić ab hetym raspracoŭnikam. + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: Novaja siesija № @SESSION_ID@ stvorana dlia karystaĺnika @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Novaja siesija z № @SESSION_ID@ stvorana dlia karystaĺnika @USER_ID@. + +Lidar hetaj siesii pad № @LEADER@. + +-- 3354939424b4456d9802ca8333ed424a +Subject: Siesija № @SESSION_ID@ spyniena +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Siesija № @SESSION_ID@ spyniena. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: Dastupna novaje pracoŭnaje miesca № @SEAT_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Novaje pracoŭnaje miesca № @SEAT_ID@ naladžana i dastupna dlia +vykarystannia. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Pracoŭnaje miesca № @SEAT_ID@ vydaliena +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Pracoŭnaje miesca № @SEAT_ID@ vydaliena i boĺš nie dastupna. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Čas zmienieny +Defined-By: systemd +Support: %SUPPORT_URL% + +Sistemny hadzinnik zmienieny na @REALTIME@ mikrasiekund ad 1 studzienia +1970. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Časavy pojas zmienieny na @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Sistemny časavy pojas zmienieny na @TIMEZONE@. + +-- b07a249cd024414a82dd00cd181378ff +Subject: Zapusk sistemy zaviaršyŭsia +Defined-By: systemd +Support: %SUPPORT_URL% + +Usie sistemnyja servisy, nieabchodnyja dlia zahruzki sistemy, paspiachova +zapuscilisia. Majcie na ŭvazie, što heta nie značyć, što mašyna ničoha nie +robić. Mahčyma, niekatoryja servisy jašče inicyjalizirujucca. + +Na zapusk jadra spatrebilasia @KERNEL_USEC@ mikrasiekund. + +Na zapusk pačatkovaha RAM-dyska spatrebilasia @INITRD_USEC@ mikrasiekund. + +Na zapusk sistemnych servisaŭ spatrebilasia @USERSPACE_USEC@ mikrasiekund. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: Sistema pierajšla ŭ stan snu @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Ciapier sistema pierajšla u stan snu @SLEEP@. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: Sistema vyjšla sa stana snu @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Ciapier sistema vyjšla sa stana snu @SLEEP@. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Sistema zaviaršaje rabotu +Defined-By: systemd +Support: %SUPPORT_URL% + +Pačaŭsia praces vykliučennia sistemy. +Spyniajucca ŭsie sistemnyja servisy i demantujucca fajlavyja sistemy. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: Junit @UNIT@ zapuskajecca +Defined-By: systemd +Support: %SUPPORT_URL% + +Pačaŭsia praces zapusku junita @UNIT@. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: Junit @UNIT@ zapusciŭsia +Defined-By: systemd +Support: %SUPPORT_URL% + +Praces zapusku junita @UNIT@ zavieršany. + +Vynik: @JOB_RESULT@. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: Junit @UNIT@ spyniajecca +Defined-By: systemd +Support: %SUPPORT_URL% + +Pačaŭsia praces spyniennia junita @UNIT@. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: Junit @UNIT@ spynieny +Defined-By: systemd +Support: %SUPPORT_URL% + +Praces spyniennia junita @UNIT@ zavieršany. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: Zboj junita @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Zboj junita @UNIT@. + +Vynik: @JOB_RESULT@. + +-- d34d037fff1847e6ae669a370e694725 +Subject: Junit @UNIT@ pieračytvaje svaju kanfihuracyju +Defined-By: systemd +Support: %SUPPORT_URL% + +Junit @UNIT@ pačaŭ pieračytvać svaju kanfihuracyju. + +-- 7b05ebc668384222baa8881179cfda54 +Subject: Junit @UNIT@ pieračytaŭ svaju kanfihuracyju +Defined-By: systemd +Support: %SUPPORT_URL% + +Junit @UNIT@ pieračytaŭ svaju kanfihuracyju. + +Vynik: @JOB_RESULT@. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Praces @EXECUTABLE@ nie moža być vykanany +Defined-By: systemd +Support: %SUPPORT_URL% + +Praces @EXECUTABLE@ nie moža być vykanany ŭ vyniku zboju. + +Jon viarnuŭ pamylku numar @ERRNO@. + +-- 0027229ca0644181a76c4e92458afa2e +Sibject: Adno ci boĺš paviedamlienniaŭ nie byli nakiravany ŭ syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +Adno ci boĺš paviedamlienniaŭ nie byli nakiravany ŭ syslog servis, jaki +vykonvajecca paralieĺna z journald. Zvyčajna heta značyć, što +realizacyja syslog nie paspiavaje apracavać paviedamlienni z nieabchodnaj +chutkasciu. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Kropka mantavannia nie pustaja +Defined-By: systemd +Support: %SUPPORT_URL% + +Kataloh @WHERE@ ukazany jak kropka mantavannia (druhoje polie ŭ /etc/fstab +ci Where= polie ŭ fajlie junita systemd) i nie pusty. Heta nie pieraškadžaje +mantavanniu, alie isnujučyja ŭ im fajly buduć niedastupny. Dlia dostupu da +ich, kali laska, zmantujcie hetuju fajlavuju sistemu ŭ inšaje miesca. + +-- 24d8d4452573402496068381a6312df2 +Subject: Virtuaĺnaja mašyna abo kantejnier zapusciŭsia +Defined-By: systemd +Support: %SUPPORT_URL% + +Virtuaĺnaja mašyna @NAME@ z lidaram № @LEADER@ zapuscilasia i +hatova dlia vykarystannia. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: Virtuaĺnaja mašyna abo kantejnier spynieny +Defined-By: systemd +Support: %SUPPORT_URL% + +Virtuaĺnaja mašyna @NAME@ z lidaram № @LEADER@ spyniena. + +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: Miechanizm DNSSEC adkliučany, bo siervier nie padtrymlivaje jaho +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +Servis vyznačennia imion (systemd-resolved.service) vyznačyŭ, što +DNS-siervier nie padtrymlivaje miechanizm DNSSEC. U vyniku pravierka DNSSEC +byla adkliučana. + +Hetaja padzieja ŭznikaje kali naladžany DNSSEC=allow-downgrade +u fajlie resolved.conf i DNS-siervier nie padtrymlivaje miechanizm DNSSEC. +Zviarnicie ŭvahu, što režym allow-downgrade dazvaliaje praviesci ataku +«DNSSEC downgrade», u chodzie jakoj zlamysnik moža adkliučyć pravierku +DNSSEC šliacham padstanoŭki padroblienych DNSSEC-adkazaŭ u kamunikacyjny +kanal. + +Heta padzieja moža być prykmietaj taho, što DNS-siervier sapraŭdy +niesumiaščaĺny z DNSSEC abo što zlamysniku paspiachova atrymalasia praviesci +ataku pa adkliučenniu DNSSEC. + +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: Zboj pry praviercy DNSSEC +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +DNS-zapyt abo resursny zapis nie prajšoŭ pravierku DNSSEC. +Jak pravila, heta pakazvaje na zniešniaje ŭzdziejannie na kanal suviazi. + +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: Davierany kliuč DNSSEC byŭ anuliavany +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Davierany kliuč DNSSEC byŭ anuliavany. Nieabchodna naladzić novy davierany +kliuč abo abnavić apieracyjnuju sistemu, kab atrymać abnoŭlieny davierany +kliuč DNSSEC. diff --git a/catalog/systemd.bg.catalog.in b/catalog/systemd.bg.catalog.in new file mode 100644 index 00000000..41f7b21b --- /dev/null +++ b/catalog/systemd.bg.catalog.in @@ -0,0 +1,310 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Copyright © 2016 Alexander Shopov + +# Message catalog for systemd's own messages + +# The catalog format is documented on +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# For an explanation why we do all this, see https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: Журналният процес е пуснат +Defined-By: systemd +Support: %SUPPORT_URL% + +Журналният процес на системата е стартирал, отворил е журналните файлове +за запис и може да приема заявки. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: Журналният процес е спрян +Defined-By: systemd +Support: %SUPPORT_URL% + +Журналният процес на системата е спрян, затворени са всички отворени +журнални файлове. + +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: Пространството върху диска заето от журналните файлове +Defined-By: systemd +Support: %SUPPORT_URL% + +@JOURNAL_NAME@ (@JOURNAL_PATH@) в момента заема @CURRENT_USE_PRETTY@. +Максималният зададен размер е @MAX_USE_PRETTY@. +Свободни се оставят поне @DISK_KEEP_FREE_PRETTY@ (от текущо наличните @DISK_AVAILABLE_PRETTY@). +Максималният наложен размер е @LIMIT_PRETTY@, от който @AVAILABLE_PRETTY@ са свободни. + +Настройките за максималния размер на журнала върху диска се +управляват чрез директивите „SystemMaxUse=“, „SystemKeepFree=“, +„SystemMaxFileSize=“, „RuntimeMaxUse=“, „RuntimeKeepFree=“ и +„RuntimeMaxFileSize=“ във файла „/etc/systemd/journald.conf“. +За повече информация прегледайте „journald.conf(5)“ от ръководството. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Съобщенията от някоя услуга не са допуснати +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Някоя услуга генерира прекалено много съобщения за кратък период. +Част само от нейните съобщения са отхвърляни. + +Съобщенията от другите услуги не са засегнати. + +Настройките за максималния брой съобщения, които ще се обработят, се +управляват чрез директивите „RateLimitInterval=“ и „RateLimitBurst=“ във +файла „/etc/systemd/journald.conf“. За повече информация прегледайте +„journald.conf(5)“ от ръководството. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Пропуснати журнални съобщения +Defined-By: systemd +Support: %SUPPORT_URL% + +Някои от съобщенията на ядрото може и да са пропуснати, защото системата не +смогваше да ги обработи достатъчно бързо. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Процес № @COREDUMP_PID@ (@COREDUMP_COMM@) запази освободената памет +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Процес № @COREDUMP_PID@ (@COREDUMP_COMM@) заби, представянето му в паметта +бе запазено. + +Най-често това се дължи на грешка в забилата програма и следва да я +докладвате на създателите на програмата. + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: Създадена е нова сесия № @SESSION_ID@ за потребителя „@USER_ID@“ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +За потребителя „@USER_ID@“ е създадена нова сесия № @SESSION_ID@. + +Водещият процес на сесията е: @LEADER@ + +-- 3354939424b4456d9802ca8333ed424a +Subject: Сесия № @SESSION_ID@ приключи +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Сесия № @SESSION_ID@ приключи работа. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: Налично е ново работно място № @SEAT_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Новото работно място № @SEAT_ID@ е настроено и готово за работа. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Работното място № @SEAT_ID@ е премахнато +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Работното място № @SEAT_ID@ вече не е налично. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Смяна на системното време +Defined-By: systemd +Support: %SUPPORT_URL% + +Часовникът на системата е сверен да сочи @REALTIME@ микросекунди след +1 януари 1970. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Смяна на часовия пояс да е „@TIMEZONE@“ +Defined-By: systemd +Support: %SUPPORT_URL% + +Часовият пояс на системата е сменен на „@TIMEZONE@“. + +-- b07a249cd024414a82dd00cd181378ff +Subject: Стартирането на системата завърши +Defined-By: systemd +Support: %SUPPORT_URL% + +Успешно са стартирали всички услуги, които са посочени за задействане при +стартиране на системата. Това не означава, че системата бездейства, защото +някои от услугите може да извършват специфични действия при стартиране. + +Стартирането на ядрото отне @KERNEL_USEC@ микросекунди. + +Стартирането на RAM диска за първоначално зареждане отне @INITRD_USEC@ +микросекунди. + +Стартирането на потребителските програми отне @USERSPACE_USEC@ микросекунди. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: Системата е приспана на ниво „@SLEEP@“ +Defined-By: systemd +Support: %SUPPORT_URL% + +Системата премина в състояние на приспиване „@SLEEP@“. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: Системата се събуди след приспиване на ниво„@SLEEP@“ +Defined-By: systemd +Support: %SUPPORT_URL% + +Системата се събуди от състояние на приспиване „@SLEEP@“. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Започна процедура на спиране на системата +Defined-By: systemd +Support: %SUPPORT_URL% + +Започна процедурата на Systemd за спиране на системата. Всички процеси и +услуги се спират, всички файлови системи се демонтират. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: Модул „@UNIT@“ се стартира +Defined-By: systemd +Support: %SUPPORT_URL% + +Модулът „@UNIT@“ се стартира в момента + +-- 39f53479d3a045ac8e11786248231fbf +Subject: Модул „@UNIT@“ вече е стартиран +Defined-By: systemd +Support: %SUPPORT_URL% + +Стартирането на модул „@UNIT@“ завърши. + +Резултатът е: @JOB_RESULT@ + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: Модул „@UNIT@“ се спира +Defined-By: systemd +Support: %SUPPORT_URL% + +Модулът „@UNIT@“ се спира в момента. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: Модул „@UNIT@“ вече е спрян +Defined-By: systemd +Support: %SUPPORT_URL% + +Спирането на модул „@UNIT@“ завърши. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: Модулът „@UNIT@“ не успя да стартира +Defined-By: systemd +Support: %SUPPORT_URL% + +Модулът „@UNIT@“ не успя да стартира. + +Резултатът е: @JOB_RESULT@ + +-- d34d037fff1847e6ae669a370e694725 +Subject: Модулът „@UNIT@“ започна презареждане на настройките си +Defined-By: systemd +Support: %SUPPORT_URL% + +Модулът „@UNIT@“ започна презареждане на настройките си. + +-- 7b05ebc668384222baa8881179cfda54 +Subject: Модулът „@UNIT@“ завърши презареждането на настройките си +Defined-By: systemd +Support: %SUPPORT_URL% + +Модулът „@UNIT@“ завърши презареждането на настройките си. + +Резултатът e: @JOB_RESULT@ + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Програмата „@EXECUTABLE@“ не успя да се стартира +Defined-By: systemd +Support: %SUPPORT_URL% + +Програмата „@EXECUTABLE@“ не успя да се стартира. + +Върнатият номер на грешка е: @ERRNO@ + +-- 0027229ca0644181a76c4e92458afa2e +Subject: Поне едно съобщение не бе препратено към syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +Поне едно съобщение не бе препратено към журналната услуга syslog, която +работи успоредно с journald. + +Най-често това указва, че тази реализация на syslog не може да поеме текущия +обем съобщения. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Точката за монтиране не е празна +Defined-By: systemd +Support: %SUPPORT_URL% + +Директорията „@WHERE@“ не е празна. + +Тя е указана като точка за монтиране — или като второ поле във файла +„/etc/fstab“, или чрез директивата „Where=“ в някой от файловете за +модул на Systemd. + +Това не пречи на самото монтиране, но вече съществуващите там файлове и +директории няма да се виждат повече, освен ако ръчно не монтирате тази +непразна директория някъде другаде. + +-- 24d8d4452573402496068381a6312df2 +Subject: Стартирана е виртуална машина или контейнер +Defined-By: systemd +Support: %SUPPORT_URL% + +Виртуалната машина „@NAME@“ с идентификатор на водещия процес @LEADER@ +е стартирана и готова за работа. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: Спряна е виртуална машина или контейнер +Defined-By: systemd +Support: %SUPPORT_URL% + +Виртуалната машина „@NAME@“ с идентификатор на водещия процес @LEADER@ +е спряна. + +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: Режимът DNSSEC е изключен, защото сървърът не го поддържа +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +Локалната услуга за имена (systemd-resolved.service) установи, че +настроения сървър за DNS не поддържа DNSSEC, затова този режим е изключен. + +Това се случва, когато директивата „DNSSEC=allow-downgrade“ е включена във +файла „resolved.conf“ и зададеният сървър за DNS не е съвместим с DNSSEC. + +Внимавайте, защото това може да позволи атака, при която трета страна ви +връща отговори, които да предизвикат понижаването на сигурността от DNSSEC +до DNS. + +Такова събитие означава, че или сървърът за DNS не е съвместим с DNSSEC, +или някой успешно ви е атакувал за понижаване на сигурността на имената. + +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: Неуспешна проверка на DNSSEC +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Заявка или запис в DNS не издържа проверка с DNSSEC. + +Това обикновено показва вмешателство на трета страна в канала ви за връзка. + +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: Анулирана доверена котва в DNSSEC +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Анулирана е доверена котва за DNSSEC и трябва да настроите нова. + +Понякога новата идва с обновяване на системата. diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in new file mode 100644 index 00000000..db275d7c --- /dev/null +++ b/catalog/systemd.catalog.in @@ -0,0 +1,414 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +# Message catalog for systemd's own messages + +# The catalog format is documented on +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# For an explanation why we do all this, see https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: The journal has been started +Defined-By: systemd +Support: %SUPPORT_URL% + +The system journal process has started up, opened the journal +files for writing and is now ready to process requests. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: The journal has been stopped +Defined-By: systemd +Support: %SUPPORT_URL% + +The system journal process has shut down and closed all currently +active journal files. + +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: Disk space used by the journal +Defined-By: systemd +Support: %SUPPORT_URL% + +@JOURNAL_NAME@ (@JOURNAL_PATH@) is currently using @CURRENT_USE_PRETTY@. +Maximum allowed usage is set to @MAX_USE_PRETTY@. +Leaving at least @DISK_KEEP_FREE_PRETTY@ free (of currently available @DISK_AVAILABLE_PRETTY@ of disk space). +Enforced usage limit is thus @LIMIT_PRETTY@, of which @AVAILABLE_PRETTY@ are still available. + +The limits controlling how much disk space is used by the journal may +be configured with SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, +RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= settings in +/etc/systemd/journald.conf. See journald.conf(5) for details. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Messages from a service have been suppressed +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +A service has logged too many messages within a time period. Messages +from the service have been dropped. + +Note that only messages from the service in question have been +dropped, other services' messages are unaffected. + +The limits controlling when messages are dropped may be configured +with RateLimitIntervalSec= and RateLimitBurst= in +/etc/systemd/journald.conf or LogRateLimitIntervalSec= and LogRateLimitBurst= +in the unit file. See journald.conf(5) and systemd.exec(5) for details. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Journal messages have been missed +Defined-By: systemd +Support: %SUPPORT_URL% + +Kernel messages have been lost as the journal system has been unable +to process them quickly enough. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Process @COREDUMP_PID@ (@COREDUMP_COMM@) dumped core +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Process @COREDUMP_PID@ (@COREDUMP_COMM@) crashed and dumped core. + +This usually indicates a programming error in the crashing program and +should be reported to its vendor as a bug. + +-- 5aadd8e954dc4b1a8c954d63fd9e1137 +Subject: Core file was truncated to @SIZE_LIMIT@ bytes. +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:coredump.conf(5) + +The process had more memory mapped than the configured maximum for processing +and storage by systemd-coredump(8). Only the first @SIZE_LIMIT@ bytes were +saved. This core might still be usable, but various tools like gdb(1) will warn +about the file being truncated. + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: A new session @SESSION_ID@ has been created for user @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +A new session with the ID @SESSION_ID@ has been created for the user @USER_ID@. + +The leading process of the session is @LEADER@. + +-- 3354939424b4456d9802ca8333ed424a +Subject: Session @SESSION_ID@ has been terminated +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +A session with the ID @SESSION_ID@ has been terminated. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: A new seat @SEAT_ID@ is now available +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +A new seat @SEAT_ID@ has been configured and is now available. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Seat @SEAT_ID@ has now been removed +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +A seat @SEAT_ID@ has been removed and is no longer available. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Time change +Defined-By: systemd +Support: %SUPPORT_URL% + +The system clock has been changed to @REALTIME@ microseconds after January 1st, 1970. + +-- c7a787079b354eaaa9e77b371893cd27 de +Subject: Zeitänderung +Defined-By: systemd +Support: %SUPPORT_URL% + +Die System-Zeit wurde geändert auf @REALTIME@ Mikrosekunden nach dem 1. Januar 1970. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Time zone change to @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +The system timezone has been changed to @TIMEZONE@. + +-- b07a249cd024414a82dd00cd181378ff +Subject: System start-up is now complete +Defined-By: systemd +Support: %SUPPORT_URL% + +All system services necessary queued for starting at boot have been +started. Note that this does not mean that the machine is now idle as services +might still be busy with completing start-up. + +Kernel start-up required @KERNEL_USEC@ microseconds. + +Initial RAM disk start-up required @INITRD_USEC@ microseconds. + +Userspace start-up required @USERSPACE_USEC@ microseconds. + +-- eed00a68ffd84e31882105fd973abdd1 +Subject: User manager start-up is now complete +Defined-By: systemd +Support: %SUPPORT_URL% + +The user manager instance for user @_UID@ has been started. All services queued +for starting have been started. Note that other services might still be starting +up or be started at any later time. + +Startup of the manager took @USERSPACE_USEC@ microseconds. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: System sleep state @SLEEP@ entered +Defined-By: systemd +Support: %SUPPORT_URL% + +The system has now entered the @SLEEP@ sleep state. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: System sleep state @SLEEP@ left +Defined-By: systemd +Support: %SUPPORT_URL% + +The system has now left the @SLEEP@ sleep state. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: System shutdown initiated +Defined-By: systemd +Support: %SUPPORT_URL% + +System shutdown has been initiated. The shutdown has now begun and +all system services are terminated and all file systems unmounted. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: A start job for unit @UNIT@ has begun execution +Defined-By: systemd +Support: %SUPPORT_URL% + +A start job for unit @UNIT@ has begun execution. + +The job identifier is @JOB_ID@. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: A start job for unit @UNIT@ has finished successfully +Defined-By: systemd +Support: %SUPPORT_URL% + +A start job for unit @UNIT@ has finished successfully. + +The job identifier is @JOB_ID@. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: A start job for unit @UNIT@ has failed +Defined-By: systemd +Support: %SUPPORT_URL% + +A start job for unit @UNIT@ has finished with a failure. + +The job identifier is @JOB_ID@ and the job result is @JOB_RESULT@. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: A stop job for unit @UNIT@ has begun execution +Defined-By: systemd +Support: %SUPPORT_URL% + +A stop job for unit @UNIT@ has begun execution. + +The job identifier is @JOB_ID@. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: A stop job for unit @UNIT@ has finished +Defined-By: systemd +Support: %SUPPORT_URL% + +A stop job for unit @UNIT@ has finished. + +The job identifier is @JOB_ID@ and the job result is @JOB_RESULT@. + +-- d34d037fff1847e6ae669a370e694725 +Subject: A reload job for unit @UNIT@ has begun execution +Defined-By: systemd +Support: %SUPPORT_URL% + +A reload job for unit @UNIT@ has begun execution. + +The job identifier is @JOB_ID@. + +-- 7b05ebc668384222baa8881179cfda54 +Subject: A reload job for unit @UNIT@ has finished +Defined-By: systemd +Support: %SUPPORT_URL% + +A reload job for unit @UNIT@ has finished. + +The job identifier is @JOB_ID@ and the job result is @JOB_RESULT@. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Process @EXECUTABLE@ could not be executed +Defined-By: systemd +Support: %SUPPORT_URL% + +The process @EXECUTABLE@ could not be executed and failed. + +The error number returned by this process is @ERRNO@. + +-- 0027229ca0644181a76c4e92458afa2e +Subject: One or more messages could not be forwarded to syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +One or more messages could not be forwarded to the syslog service +running side-by-side with journald. This usually indicates that the +syslog implementation has not been able to keep up with the speed of +messages queued. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Mount point is not empty +Defined-By: systemd +Support: %SUPPORT_URL% + +The directory @WHERE@ is specified as the mount point (second field in +/etc/fstab or Where= field in systemd unit file) and is not empty. +This does not interfere with mounting, but the pre-exisiting files in +this directory become inaccessible. To see those over-mounted files, +please manually mount the underlying file system to a secondary +location. + +-- 24d8d4452573402496068381a6312df2 +Subject: A virtual machine or container has been started +Defined-By: systemd +Support: %SUPPORT_URL% + +The virtual machine @NAME@ with its leader PID @LEADER@ has been +started is now ready to use. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: A virtual machine or container has been terminated +Defined-By: systemd +Support: %SUPPORT_URL% + +The virtual machine @NAME@ with its leader PID @LEADER@ has been +shut down. + +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: DNSSEC mode has been turned off, as server doesn't support it +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +The resolver service (systemd-resolved.service) has detected that the +configured DNS server does not support DNSSEC, and DNSSEC validation has been +turned off as result. + +This event will take place if DNSSEC=allow-downgrade is configured in +resolved.conf and the configured DNS server is incompatible with DNSSEC. Note +that using this mode permits DNSSEC downgrade attacks, as an attacker might be +able turn off DNSSEC validation on the system by inserting DNS replies in the +communication channel that result in a downgrade like this. + +This event might be indication that the DNS server is indeed incompatible with +DNSSEC or that an attacker has successfully managed to stage such a downgrade +attack. + +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: DNSSEC validation failed +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +A DNS query or resource record set failed DNSSEC validation. This is usually +indication that the communication channel used was tampered with. + +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: A DNSSEC trust anchor has been revoked +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +A DNSSEC trust anchor has been revoked. A new trust anchor has to be +configured, or the operating system needs to be updated, to provide an updated +DNSSEC trust anchor. + +-- 5eb03494b6584870a536b337290809b3 +Subject: Automatic restarting of a unit has been scheduled +Defined-By: systemd +Support: %SUPPORT_URL% + +Automatic restarting of the unit @UNIT@ has been scheduled, as the result for +the configured Restart= setting for the unit. + +-- ae8f7b866b0347b9af31fe1c80b127c0 +Subject: Resources consumed by unit runtime +Defined-By: systemd +Support: %SUPPORT_URL% + +The unit @UNIT@ completed and consumed the indicated resources. + +-- 7ad2d189f7e94e70a38c781354912448 +Subject: Unit succeeded +Defined-By: systemd +Support: %SUPPORT_URL% + +The unit @UNIT@ has successfully entered the 'dead' state. + +-- 0e4284a0caca4bfc81c0bb6786972673 +Subject: Unit skipped +Defined-By: systemd +Support: %SUPPORT_URL% + +The unit @UNIT@ was skipped due to an ExecCondition= command failure, and has +entered the 'dead' state with result '@UNIT_RESULT@'. + +-- d9b373ed55a64feb8242e02dbe79a49c +Subject: Unit failed +Defined-By: systemd +Support: %SUPPORT_URL% + +The unit @UNIT@ has entered the 'failed' state with result '@UNIT_RESULT@'. + +-- 98e322203f7a4ed290d09fe03c09fe15 +Subject: Unit process exited +Defined-By: systemd +Support: %SUPPORT_URL% + +An @COMMAND@= process belonging to unit @UNIT@ has exited. + +The process' exit code is '@EXIT_CODE@' and its exit status is @EXIT_STATUS@. + +-- 50876a9db00f4c40bde1a2ad381c3a1b +Subject: The system is configured in a way that might cause problems +Defined-By: systemd +Support: %SUPPORT_URL% + +The following "tags" are possible: +- "split-usr" — /usr is a separate file system and was not mounted when systemd + was booted +- "cgroups-missing" — the kernel was compiled without cgroup support or access + to expected interface files is restricted +- "var-run-bad" — /var/run is not a symlink to /run +- "overflowuid-not-65534" — the kernel user ID used for "unknown" users (with + NFS or user namespaces) is not 65534 +- "overflowgid-not-65534" — the kernel group ID used for "unknown" users (with + NFS or user namespaces) is not 65534 +Current system is tagged as @TAINT@. + +-- fe6faa94e7774663a0da52717891d8ef +Subject: A process of @UNIT@ unit has been killed by the OOM killer. +Defined-By: systemd +Support: %SUPPORT_URL% + +A process of unit @UNIT has been killed by the Linux kernel out-of-memory (OOM) +killer logic. This usually indicates that the system is low on memory and that +memory needed to be freed. A process associated with @UNIT@ has been determined +as the best process to terminate and has been forcibly terminated by the +kernel. + +Note that the memory pressure might or might not have been caused by @UNIT@. diff --git a/catalog/systemd.da.catalog.in b/catalog/systemd.da.catalog.in new file mode 100644 index 00000000..aecfafa0 --- /dev/null +++ b/catalog/systemd.da.catalog.in @@ -0,0 +1,246 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +# Message catalog for systemd's own messages +# Danish translation + +# The catalog format is documented on +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# For an explanation why we do all this, see https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: Journalen er blevet startet +Defined-By: systemd +Support: %SUPPORT_URL% + +System-journal processen har startet op, åbnet journal filerne for +tilskrivning og er nu klar til at modtage anmodninger. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: Journalen er blevet stoppet +Defined-By: systemd +Support: %SUPPORT_URL% + +System-journal processen er stoppet og har lukket alle aktive journal +filer. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Beskeder fra en service er blevet undertrykt +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +En service har logget for mange beskeder inden for en given tidsperiode. +Beskeder fra omtalte service er blevet smidt væk. + +Kun beskeder fra omtalte service er smidt væk. Beskeder fra andre +services er ikke påvirket. + +Grænsen for hvornår beskeder bliver smidt væk kan konfigureres +med RateLimitIntervalSec= og RateLimitBurst= i +/etc/systemd/journald.conf. Se journald.conf(5) for detaljer herom. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Journal beskeder er gået tabt +Defined-By: systemd +Support: %SUPPORT_URL% + +Kernel beskeder er gået tabt da journal systemet ikke har været i stand +til at håndtere dem hurtigt nok. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Fejl-fil genereret for process @COREDUMP_PID@ (@COREDUMP_COMM@) +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Process @COREDUMP_PID@ (@COREDUMP_COMM@) har lukket ned og genereret en +fejl-fil. + +Dette indikerer som regel en programmeringsfejl i det nedlukkede program +og burde blive reporteret som en bug til folkene bag + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: En ny session @SESSION_ID@ er blevet lavet for bruger @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +En ny session med ID @SESSION_ID@ er blevet lavet for brugeren @USER_ID@. + +Den ledende process for sessionen er @LEADER@. + +-- 3354939424b4456d9802ca8333ed424a +Subject: Session @SESSION_ID@ er blevet lukket ned +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +En session med ID @SESSION_ID@ er blevet lukket ned. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: En ny arbejdsstation $SEAT_ID@ er nu tilgængelig +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +En ny arbejdsstation @SEAT_ID@ er blevet konfigureret og er nu tilgængelig. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Arbejdsstation @SEAT_ID@ er nu blevet fjernet +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +En arbejdsstation @SEAT_ID@ er blevet fjernet og er ikke længere tilgængelig. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Tidsændring +Defined-By: systemd +Support: %SUPPORT_URL% + +Systemtiden er blevet ændret til @REALTIME@ mikrosekunder efter d. 1. Januar 1970. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Tidszoneændring til @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Tidszonen for systemet er blevet ændret til @TIMEZONE@. + +-- b07a249cd024414a82dd00cd181378ff +Subject: Opstart af systemet er nu fuldført +Defined-By: systemd +Support: %SUPPORT_URL% + +Alle system services i kø til at køre ved opstart, er blevet startet +med success. Bemærk at dette ikke betyder at maskinen er i dvale, da +services stadig kan være i gang med at færdiggøre deres opstart. + +Opstart af kernel tog @KERNEL_USEC@ mikrosekunder. + +Opstart af initrd tog @INITRD_USEC@ mikrosekunder. + +Opstart af userspace tog @USERSPACE_USEC@ mikrosekunder. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: System slumretilstand @SLEEP@ trådt i kraft +Defined-By: systemd +Support: %SUPPORT_URL% + +System er nu gået i @SLEEP@ slumretilstand. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: System slumretilstand @SLEEP@ forladt +Defined-By: systemd +Support: %SUPPORT_URL% + +Systemet har nu forladt @SLEEP@ slumretilstand. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Systemnedlukning påbegyndt +Defined-By: systemd +Support: %SUPPORT_URL% + +Systemnedlukning er blevet påbegyndt. Nedlukningen er nu begyndt og +alle system services er blevet afbrudt og alle filsystemer afmonteret. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: Enhed @UNIT@ har påbegyndt opstart +Defined-By: systemd +Support: %SUPPORT_URL% + +Enhed @UNIT@ er begyndt at starte op. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: Enhed @UNIT har færdiggjort opstart +Defined-By: systemd +Support: %SUPPORT_URL% + +Enhed @UNIT@ er færdig med at starte op. + +Resultat for opstart er @JOB_RESULT@. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: Enhed @UNIT@ har påbegyndt nedlukning +Defined-By: systemd +Support: %SUPPORT_URL% + +Enhed @UNIT@ har påbegyndt nedlukning. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: Enhed @UNIT@ har færdiggjort nedlukning +Defined-By: systemd +Support: %SUPPORT_URL% + +Enhed @UNIT@ har færdiggjort nedlukning. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: Enhed @UNIT@ har fejlet +Defined-By: systemd +Support: %SUPPORT_URL% + +Enhed @UNIT@ har fejlet. + +Resultatet er @JOB_RESULT@ + +-- d34d037fff1847e6ae669a370e694725 +Subject: Enhed @UNIT@ har påbegyndt genindlæsning af sin konfiguration +Defined-By: systemd +Support: %SUPPORT_URL% + +Enhed @UNIT@ er begyndt at genindlæse sin konfiguration + +-- 7b05ebc668384222baa8881179cfda54 +Subject: Enhed @UNIT@ har færdiggjort genindlæsning af sin konfiguration +Defined-By: systemd +Support: %SUPPORT_URL% + +Enhed @UNIT@ er færdig med at genindlæse sin konfiguration + +Resultatet er: @JOB_RESULT@. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Process @EXECUTABLE@ kunne ikke eksekveres +Defined-By: systemd +Support: %SUPPORT_URL% + +Processen @EXECUTABLE@ kunne ikke eksekveres og fejlede. + +Processens returnerede fejlkode er @ERRNO@. + +-- 0027229ca0644181a76c4e92458afa2e +Subject: Èn eller flere beskeder kunne ikke videresendes til syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +Èn eller flere beskeder kunne ikke videresendes til syslog servicen +der kører side-om-side med journald. Dette indikerer typisk at syslog +implementationen ikke har kunnet følge med mængden af ventende beskeder. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Monteringspunkt er ikke tomt +Defined-By: systemd +Support: %SUPPORT_URL% + +Folderen @WHERE@ er specificeret som monteringspunkt (andet felt i +/etc/fstab eller Where= feltet i systemd enhedsfil) men er ikke tom. +Dette forstyrrer ikke monteringen, men de pre-eksisterende filer i folderen +bliver utilgængelige. For at se de over-monterede filer; montér det +underlæggende filsystem til en anden lokation. + +-- 24d8d4452573402496068381a6312df2 +Subject: En virtuel maskine eller container er blevet startet +Defined-By: systemd +Support: %SUPPORT_URL% + +Den virtuelle maskine @NAME@ med dens leder PID @LEADER@ er blevet +startet og er klar til brug. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: En virtuel maskine eller container er blevet afbrudt +Defined-By: systemd +Support: %SUPPORT_URL% + +Den virtuelle maskine @NAME@ med dens leder PID @LEADER@ er blevet +nedlukket. diff --git a/catalog/systemd.de.catalog.in b/catalog/systemd.de.catalog.in new file mode 100644 index 00000000..d10111b0 --- /dev/null +++ b/catalog/systemd.de.catalog.in @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Speicherabbild für Prozess @COREDUMP_PID@ (@COREDUMP_COMM) generiert +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Prozess @COREDUMP_PID@ (@COREDUMP_COMM@) ist abgebrochen worden und +ein Speicherabbild wurde generiert. + +Üblicherweise ist dies ein Hinweis auf einen Programmfehler und sollte +als Fehler dem jeweiligen Hersteller gemeldet werden. diff --git a/catalog/systemd.fr.catalog.in b/catalog/systemd.fr.catalog.in new file mode 100644 index 00000000..13edd083 --- /dev/null +++ b/catalog/systemd.fr.catalog.in @@ -0,0 +1,350 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Copyright © 2013-2016 Sylvain Plantefève + +# Message catalog for systemd's own messages +# French translation + +# Le format du catalogue de messages est décrit (en anglais) içi : +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +-- f77379a8490b408bbe5f6940505a777b +Subject: Le journal a été démarré +Defined-By: systemd +Support: %SUPPORT_URL% + +Le processus du journal système a démarré, ouvert ses fichiers en écriture +et est prêt à traiter les requêtes. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: Le journal a été arrêté +Defined-By: systemd +Support: %SUPPORT_URL% + +Le processus du journal système a été arrêté et tous ses fichiers actifs +ont été fermés. + +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: Espace disque utilisé par le journal +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +@JOURNAL_NAME@ (@JOURNAL_PATH@) utilise actuellement @CURRENT_USE_PRETTY@. +Le maximum autorisé est défini à @MAX_USE_PRETTY@. +Au moins @DISK_KEEP_FREE_PRETTY@ doivent être laissés libres +(sur @DISK_AVAILABLE_PRETTY@ d'espace disque actuellement libre). +La limite appliquée est donc @LIMIT_PRETTY@, dont @AVAILABLE_PRETTY@ +sont toujours disponibles. + +Les limites définissant la quantité d'espace disque que peut utiliser le +journal peuvent être configurées avec les paramètres SystemMaxUse=, +SystemKeepFree=, SystemMaxFileSize=, RuntimeMaxUse=, RuntimeKeepFree=, +RuntimeMaxFileSize= dans le fichier /etc/systemd/journald.conf. +Voir journald.conf(5) pour plus de détails. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Des messages d'un service ont été supprimés +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Un service a essayé d'enregistrer un trop grand nombre de messages sur un +intervalle de temps donné. Des messages de ce service ont été évincés. + +Notez que seuls des messages de ce service ont été évincés, les messages des +autres services ne sont pas affectés. + +Les limites définissant ce comportement peuvent être configurées avec les +paramètres RateLimitIntervalSec= et RateLimitBurst= dans le fichier +/etc/systemd/journald.conf. Voir journald.conf(5) pour plus de détails. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Des messages du journal ont été manqués +Defined-By: systemd +Support: %SUPPORT_URL% + +Des messages du noyau ont été manqués car le journal système n'a pas été +capable de les traiter suffisamment vite. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Le processus @COREDUMP_PID@ (@COREDUMP_COMM@) a généré un fichier « core » +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Le processus @COREDUMP_PID@ (@COREDUMP_COMM@) a planté et généré un fichier « core ». + +Cela indique généralement une erreur de programmation dans le programme +incriminé, et cela devrait être notifié à son concepteur comme un défaut (bug). + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: Une nouvelle session @SESSION_ID@ a été créée pour l'utilisateur @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Une nouvelle session a été créée pour l'utilisateur @USER_ID@ avec +l'identifiant (ID) @SESSION_ID@. + +Le processus maître de la session est @LEADER@. + +-- 3354939424b4456d9802ca8333ed424a +Subject: La session @SESSION_ID@ s'est terminée +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +La session d'identifiant (ID) @SESSION_ID@ s'est terminée. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: Un nouveau poste (seat) @SEAT_ID@ est disponible +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Un nouveau poste (seat) @SEAT_ID@ a été configuré et est maintenant +disponible. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Le poste (seat) @SEAT_ID@ a été retiré +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Le poste (seat) @SEAT_ID@ a été retiré et n'est plus disponible. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Changement d'heure +Defined-By: systemd +Support: %SUPPORT_URL% + +L'horloge système a été modifiée et positionnée à @REALTIME@ microsecondes +après le 1er janvier 1970. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Fuseau horaire modifié en @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Le fuseau horaire du système a été modifié et positionné à @TIMEZONE@. + +-- b07a249cd024414a82dd00cd181378ff +Subject: Le démarrage du système est terminé +Defined-By: systemd +Support: %SUPPORT_URL% + +Tous les services nécessaires au démarrage du système ont été lancés. +Notez que cela ne signifie pas que le système est maintenant au repos, +car des services peuvent encore être en train de terminer leur démarrage. + +Le chargement du noyau a nécessité @KERNEL_USEC@ microsecondes. + +Le chargement du « RAM disk » initial a nécessité @INITRD_USEC@ microsecondes. + +Le chargement de l'espace utilisateur a nécessité @USERSPACE_USEC@ microsecondes. + +-- eed00a68ffd84e31882105fd973abdd1 +Subject: Le démarrage du gestionnaire utilisateur est terminé +Defined-By: systemd +Support: %SUPPORT_URL% + +L'instance du gestionnaire d'utilisateurs pour l'utilisateur @_UID@ a été démarrée. +Tous les services en file d'attente pour démarrer ont été lancés. +Notez que des services peuvent être encore en train de démarrer, +ou d'autres être lancés à tout moment ultérieur. + +Le démarrage du gestionnaire a nécéssité @USERSPACE_USEC@ microsecondes. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: Le système entre dans l'état de repos (sleep state) @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Le système est maintenant à l'état de repos (sleep state) @SLEEP@. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: Le système sorti de l'état de repos (sleep state) @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Le système est maintenant sorti de l'état de repos (sleep state) @SLEEP@. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Arrêt du système amorcé +Defined-By: systemd +Support: %SUPPORT_URL% + +L'arrêt du système a été amorcé. L'arrêt a maintenant commencé, tous les +services du système sont terminés et tous les systèmes de fichiers sont +démontés. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: L'unité (unit) @UNIT@ a commencé à démarrer +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unité (unit) @UNIT@ a commencé à démarrer. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: L'unité (unit) @UNIT@ a terminé son démarrage +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unité (unit) @UNIT@ a terminé son démarrage, avec le résultat @JOB_RESULT@. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: L'unité (unit) @UNIT@ a commencé à s'arrêter +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unité (unit) @UNIT@ a commencé à s'arrêter. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: L'unité (unit) @UNIT@ a terminé son arrêt +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unité (unit) @UNIT@ a terminé son arrêt. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: L'unité (unit) @UNIT@ a échoué +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unité (unit) @UNIT@ a échoué, avec le résultat @JOB_RESULT@. + +-- d34d037fff1847e6ae669a370e694725 +Subject: L'unité (unit) @UNIT@ a commencé à recharger sa configuration +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unité (unit) @UNIT@ a commencé à recharger sa configuration. + +-- 7b05ebc668384222baa8881179cfda54 +Subject: L'unité (unit) @UNIT@ a terminé de recharger configuration +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unité (unit) @UNIT@ a terminé de recharger configuration, +avec le résultat @JOB_RESULT@. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Le processus @EXECUTABLE@ n'a pas pu être exécuté +Defined-By: systemd +Support: %SUPPORT_URL% + +Le processus @EXECUTABLE@ n'a pas pu être exécuté, et a donc échoué. + +Le code d'erreur renvoyé est @ERRNO@. + +-- 0027229ca0644181a76c4e92458afa2e +Subject: Un ou plusieurs messages n'ont pas pu être transmis à syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +Un ou plusieurs messages n'ont pas pu être transmis au service syslog +s'exécutant conjointement avec journald. Cela indique généralement que +l'implémentation de syslog utilisée n'a pas été capable de suivre +la cadence du flux de messages. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Le point de montage n'est pas vide +Defined-By: systemd +Support: %SUPPORT_URL% + +Le répertoire @WHERE@ est spécifié comme point de montage (second champ du +fichier /etc/fstab, ou champ Where= dans une unité (unit) systemd) et n'est +pas vide. +Cela ne perturbe pas le montage du système de fichiers, mais les fichiers +préalablement présents dans ce répertoire sont devenus inaccessibles. +Pour atteindre ces fichiers, veuillez monter manuellement le système de +fichiers sous-jacent à un autre emplacement. + +-- 24d8d4452573402496068381a6312df2 +Subject: Une machine virtuelle ou un conteneur (container) a été démarré +Defined-By: systemd +Support: %SUPPORT_URL% + +La machine virtuelle @NAME@ a été démarrée avec le PID maître @LEADER@, +et est maintenant prête à l'emploi. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: Une machine virtuelle ou un conteneur (container) a été arrêté +Defined-By: systemd +Support: %SUPPORT_URL% + +La machine virtuelle @NAME@ avec le PID maître @LEADER@ a été arrêtée. + +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: Le mode DNSSEC a été désactivé, car il n'est pas supporté par le serveur +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +Le service de résolution (systemd-resolved.service) a détecté que le serveur +DNS configuré ne supporte pas DNSSEC, et la validation DNSSEC a donc été +désactivée. + +Cet évènement se produit si DNSSEC=allow-downgrade est configuré dans +resolved.conf et que le serveur DNS configuré n'est pas compatible avec +DNSSEC. +Veuillez noter que ce mode permet des attaques de rétrogradation DNSSEC, +car un attaquant peut être capable de désactiver la validation DNSSEC sur +le système en injectant des réponses DNS dans le canal de communication. + +Cet évènement indique que le serveur DNS est effectivement incompatible avec +DNSSEC, ou qu'un attaquant a peut-être conduit une telle attaque avec succès. + +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: La validation DNSSEC a échoué +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Une requête ou une ressource DNS n'a pas passé la validation DNSSEC. +Ceci est généralement une indication que le canal de communication a été +altéré. + +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: Une ancre de confiance DNSSEC a été révoquée +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Une ancre de confiance DNSSEC a été révoquée. Une nouvelle ancre de +confiance doit être configurée, ou le système d'exploitation a besoin +d'être mis à jour, pour fournir une version à jour de l'ancre de confiance. + +-- 5eb03494b6584870a536b337290809b3 +Subject: Le redémarrage automatique d'une unité (unit) a été planifié +Defined-By: systemd +Support: %SUPPORT_URL% + +Le redémarrage automatique de l'unité (unit) @UNIT@ a été planifié, en +raison de sa configuration avec le paramètre Restart=. + +-- ae8f7b866b0347b9af31fe1c80b127c0 +Subject: Ressources consommées durant l'éxécution de l'unité (unit) +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unité (unit) @UNIT@ s'est arrêtée et a consommé les ressources indiquées. + +-- 50876a9db00f4c40bde1a2ad381c3a1b +Subject: Le système est configuré d'une manière qui pourrait causer des problèmes +Defined-By: systemd +Support: %SUPPORT_URL% + +Les étiquettes suivantes sont possibles : +- "split-usr" — /usr est un système de fichiers séparé et nétait pas + monté quand systemd a été démarré +- "cgroups-missing" — le noyau a été compilé sans le support des groupes + de contrôle (cgroups) ou l'accès aux fichiers d'interface est restreint +- "var-run-bad" — /var/run n'est pas un lien symbolique vers /run +- "overflowuid-not-65534" — l'ID utilisé par le noyau pour l'utilisateur + "unknown" (avec NFS ou l'espace de noms utilisateurs) n'est pas 65534 +- "overflowgid-not-65534" — l'ID utilisé par le noyau pour le groupe + "unknown" (avec NFS ou l'espace de noms utilisateurs) n'est pas 65534 + +Le présent système est étiqueté @TAINT@. diff --git a/catalog/systemd.hr.catalog.in b/catalog/systemd.hr.catalog.in new file mode 100644 index 00000000..4526ae2a --- /dev/null +++ b/catalog/systemd.hr.catalog.in @@ -0,0 +1,299 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +# Message catalog for systemd's own messages +# Croatian translation + +# Format kataloga je dokumentiran na +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# Za pojašnjenje zašto ovo radimo, posjetite https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: journal je pokrenut +Defined-By: systemd +Support: %SUPPORT_URL% + +Journal proces sustava se pokrenuo, otvorio je journal + datoteke za upis i spreman je za obradu zahtjeva. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: journal je zaustavljen +Defined-By: systemd +Support: %SUPPORT_URL% + +Journal proces sustava je isključio i zatvorio sve trenutno +aktivne journal datoteke. + +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: Diskovni prostor koji koristi journal +Defined-By: systemd +Support: %SUPPORT_URL% + +@JOURNAL_NAME@ (@JOURNAL_PATH@) trenutno koristi @CURRENT_USE_PRETTY@. +Najveća dopuštena upotreba je postavljena na @MAX_USE_PRETTY@. +Ostavljam najmanje @DISK_KEEP_FREE_PRETTY@ slobodno (trenutno dostupno @DISK_AVAILABLE_PRETTY@ diskovnog prostora). +Prisilno ograničenje upotrebe je @LIMIT_PRETTY@, od kojeg je @AVAILABLE_PRETTY@ još dostupno. + +Ograničenja kontroliraju koliko diskovnog prostora koristi journal mogu +se podesiti sa SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, +RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= settings u +/etc/systemd/journald.conf. Pogledajte journald.conf(5) za više pojedinosti. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Poruka iz usluge je potisnuta +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Usluga je prijavila previše poruka u određenom vremenskom razdoblju. Poruke +iz usluge su odbačene. + +Zapamtite da samo poruke iz usluge u upitu su +odbačene, ostale poruke usluga nisu zahvaćene. + +Ograničenja koja kontroliraju kada je poruka odbačena mogu se podesiti +sa RateLimitIntervalSec= i RateLimitBurst= u +/etc/systemd/journald.conf. Pogledajte journald.conf(5) za više pojedinosti. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Journal poruka je propuštena +Defined-By: systemd +Support: %SUPPORT_URL% + +Kernel poruka je izgubljena zato jer ih journal sustav nije mogao +dovoljno brzo obraditi. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Proces @COREDUMP_PID@ (@COREDUMP_COMM@) je izbacio jezgru +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Proces @COREDUMP_PID@ (@COREDUMP_COMM@) se srušio i izbacio jezgru. + +Rušenje programa je uobičajeno uzrokovano greškom u programiranju i +trebalo bi se prijaviti razvijatelju kao greška. + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: Nova sesija @SESSION_ID@ je stvorena za korisnika @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Nova sesija sa ID @SESSION_ID@ je stvorena za korisnika @USER_ID@. + +Glavni proces sesije je @LEADER@. + +-- 3354939424b4456d9802ca8333ed424a +Subject: Sesija @SESSION_ID@ je prekinuta +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Sesija sa ID @SESSION_ID@ je prekinuta. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: Novo sjedište @SEAT_ID@ je sada dostupno +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Novo sjedište @SEAT_ID@ je podešeno i sada je dostupno. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Sjedište @SEAT_ID@ je sada uklonjeno +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Sjedište @SEAT_ID@ je uklonjeno i više nije dostupno. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Vrijeme promjene +Defined-By: systemd +Support: %SUPPORT_URL% + +Sat sustava je promijenjen na @REALTIME@ microsekundi nakon 1. Siječnja, 1970 godine. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Vremenska zona je promijenjena u @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Vremenska zona je promijenjena u @TIMEZONE@. + +-- b07a249cd024414a82dd00cd181378ff +Subject: Pokretanje sustava je sada završeno +Defined-By: systemd +Support: %SUPPORT_URL% + +Sve usluge sustava koje su zadane za pokretanje pri pokretanju sustava +su uspješno pokrenute. Zapamtite da ovo ne znači da sada računalo +miruje zato jer se neke usluge još uvijek mogu pokretati. + +Pokretanje kernela zahtijeva @KERNEL_USEC@ mikrosekundi. + +Pokretanje početnog RAM diska zahtijeva @INITRD_USEC@ mikrosekundi. + +Pokretanje prostora korisnika zahtijeva @USERSPACE_USEC@ mikrosekundi. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: Pokrenuto je stanje spavanja @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Sustav je sada pokrenuo stanje spavanja @SLEEP@ + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: Završeno je stanje spavanja @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Sustav je sada završio stanje spavanja @SLEEP@ + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Pokrenuto je isključivanje sustava +Defined-By: systemd +Support: %SUPPORT_URL% + +Pokrenuto je isključivanje sustava. Isključivanje je sada pokrenuto, +sve usluge sustava su prekinute i svi datotečni sustavi su odmontirani. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: Jedinica @UNIT@ je započela pokretanje +Defined-By: systemd +Support: %SUPPORT_URL% + +Jedinica @UNIT@ je započela pokretanje. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: Jedinica @UNIT@ je završila pokretanje +Defined-By: systemd +Support: %SUPPORT_URL% + +Jedinica @UNIT@ je završila pokretanje. + +Rezultat pokretanja je @JOB_RESULT@. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: Jedinica @UNIT@ je započela isključivanje +Defined-By: systemd +Support: %SUPPORT_URL% + +Jedinica @UNIT@ je započela isključivanje. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: Jedinica @UNIT@ je završila isključivanje +Defined-By: systemd +Support: %SUPPORT_URL% + +Jedinica @UNIT@ je završila isključivanje. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: Jedinica @UNIT@ nije uspjela +Defined-By: systemd +Support: %SUPPORT_URL% + +Jedinica @UNIT@ nije uspjela. + +Rezultat je @JOB_RESULT@. + +-- d34d037fff1847e6ae669a370e694725 +Subject: Jedinica @UNIT@ je započela ponovno učitavati podešavanja +Defined-By: systemd +Support: %SUPPORT_URL% + +Jedinica @UNIT@ je započela ponovno učitavati podešavanja + +-- 7b05ebc668384222baa8881179cfda54 +Subject: Jedinica @UNIT@ je završila ponovno učitavati podešavanja +Defined-By: systemd +Support: %SUPPORT_URL% + +Jedinica @UNIT@ je završila ponovno učitavati podešavanja + +Rezultat je @JOB_RESULT@. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Proces @EXECUTABLE@ se ne može pokrenuti +Defined-By: systemd +Support: %SUPPORT_URL% + +Proces @EXECUTABLE@ se ne može pokrenuti i nije uspio. + +Broj greške vraćen ovim procesom je @ERRNO@. + +-- 0027229ca0644181a76c4e92458afa2e +Subject: Jedna ili više poruka se ne mogu proslijediti u dnevnik sustava +Defined-By: systemd +Support: %SUPPORT_URL% + +Jedna ili više poruka se ne mogu proslijediti u dnevnik sustava, usluge +su pokrenute istovremeno s journalom. Ovo uobičajeno označava da +implementacija dnevnika sustava ne može slijediti brzinu +zahtjeva poruka. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Točka montiranja nije prazna +Defined-By: systemd +Support: %SUPPORT_URL% + +Direktorij @WHERE@ je određen za točku montiranja (drugi redak u +/etc/fstab ili Where= redak u datoteci systemd jedinice) i nije prazan. +To ne utječe na montiranje, ali postojeće datoteke u ovom direktoriju +postaju nedostupne. Kako bi vidjeli datoteke preko kojih je montirano, +ručno montirajte osnovni datotečni sustav na drugu lokaciju. + +-- 24d8d4452573402496068381a6312df2 +Subject: Virtualni stroj ili spremnik su pokrenuti +Defined-By: systemd +Support: %SUPPORT_URL% + +Virtualni stroj @NAME@ sa vodećim @LEADER@ PID-om je +pokrenut i spreman je za korištenje. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: Virtualni stroj ili spremnik su isključeni +Defined-By: systemd +Support: %SUPPORT_URL% + +Virtualni stroj @NAME@ sa vodećim PID-om @LEADER@ je +isključen. + +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: DNSSEC način je isključen, jer ga poslužitelj ne podržava +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +Usluga razrješavanja (systemd-resolved.service) je otkrila da +podešeni DNS poslužitelj ne podržava DNSSEC, i DNSSEC, kao rezultat +provjera je isključena. + +Ovaj događaj će zauzeti mjesto ako je DNSSEC=allow-downgrade podešen u +resolved.conf i podešeni DNS poslužitelj je nekompatibilan s DNSSEC. Zapamtite +da korištenje ovog načina dopušta povećanje DNSSEC napada, napadač bi mogao +isključiti DNSSEC provjeru na sustavu umetanjem DNS odgovora u +komunikacijski kanal što rezultira povećanjem napada poput ovog. + +Ovaj događaj bi mogao označavati da je DNS poslužitelj uistinu nekompatibilan s +DNSSEC ili da je napadač uspješno izvršio takav napad. + +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: DNSSEC provjera neuspješna +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +DNS zahtjev ili snimak resursa nije prošao DNSSEC provjeru. To uobičajeno +označava da je komunikacijski kanal mijenjan. + +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: DNSSEC pouzdano sidro je opozvano +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +A DNSSEC trust anchor has been revoked. A new trust anchor has to be +configured, or the operating system needs to be updated, to provide an updated +DNSSEC trust anchor. diff --git a/catalog/systemd.hu.catalog.in b/catalog/systemd.hu.catalog.in new file mode 100644 index 00000000..5565b80b --- /dev/null +++ b/catalog/systemd.hu.catalog.in @@ -0,0 +1,248 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Copyright © 2016 Gabor Kelemen + +# Message catalog for systemd's own messages + +# The catalog format is documented on +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# For an explanation why we do all this, see https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: A napló elindult +Defined-By: systemd +Support: %SUPPORT_URL% + +A rendszernapló folyamat elindult, megnyitotta írásra a naplófájlokat, +és most készen áll kérések feldolgozására. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: A napló leállt +Defined-By: systemd +Support: %SUPPORT_URL% + +A rendszernapló folyamat leállt, és bezárt minden jelenleg aktív naplófájlt. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Egy szolgáltatás üzenetei elnémítva +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Egy szolgáltatás túl sok üzenetet naplózott adott idő alatt. A +szolgáltatástól származó üzenetek eldobásra kerültek. + +Ne feledje, hogy csak a kérdéses szolgáltatás üzenetei kerültek eldobásra, + más szolgáltatások üzeneteit ez nem befolyásolja. + +Az üzenetek eldobását vezérlő korlátok az /etc/systemd/journald.conf +RateLimitIntervalSec= és RateLimitBurst= beállításaival adhatók meg. +Részletekért lásd a journald.conf(5) man oldalt. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Naplóüzenetek vesztek el +Defined-By: systemd +Support: %SUPPORT_URL% + +Kernelüzenetek vesztek el, mert a naplózó rendszer nem tudta elég gyorsan +feldolgozni azokat. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Egy folyamat összeomlott: @COREDUMP_PID@ (@COREDUMP_COMM@) +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Ez a folyamat: @COREDUMP_PID@ (@COREDUMP_COMM@) összeomlott, és core fájlt + írt ki. + +Ez általában programozási hibát jelez az összeomló programban, és +a szállítója felé kell bejelenteni. + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: Új munkamenet (@SESSION_ID@) létrehozva, felhasználója: @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Létrejött egy új munkamenet @SESSION_ID@ azonosítóval ezen felhasználóhoz: +@USER_ID@. + +A munkamenet vezető folyamata: @LEADER@. + +-- 3354939424b4456d9802ca8333ed424a +Subject: Munkamenet (@SESSION_ID@) befejezve +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +A következő azonosítójú munkamenet befejeződött: @SESSION_ID@. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: Elérhető egy új munkaállomás: @SEAT_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Beállításra kerül és használható egy új munkaállomás: @SEAT_ID@. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: A munkaállomás eltávolítva: @SEAT_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +A munkaállomás el lett távolítva, és már nem érhető el: @SEAT_ID@ + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Időmódosítás +Defined-By: systemd +Support: %SUPPORT_URL% + +A rendszeróra beállítva @REALTIME@ ezredmásodpercre 1970. január 1. után. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Időzóna-módosítás erre: @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +A rendszer időzónája módosítva lett erre: @TIMEZONE@. + +-- b07a249cd024414a82dd00cd181378ff +Subject: A rendszer indítása kész +Defined-By: systemd +Support: %SUPPORT_URL% + +A rendszerindításkor szükséges indításhoz sorba állított összes +rendszerszolgáltatás elindult. Ne feledje, hogy ez nem jelenti, hogy a +gép üresjáratban van, mivel egyes szolgáltatások még az indítás +befejezésével lehetnek elfoglalva. + +A kernel indítása @KERNEL_USEC@ ezredmásodpercet igényelt. + +A kiinduló RAM lemez indítása @INITRD_USEC@ ezredmásodpercet igényelt. + +A felhasználói programok indítása @USERSPACE_USEC@ ezredmásodpercet igényelt. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: A rendszer „@SLEEP@” alvási állapotba lépett +Defined-By: systemd +Support: %SUPPORT_URL% + +A rendszer belépett ebbe az alvási állapotba: @SLEEP@. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: A rendszer „@SLEEP@” alvási állapotból kilépett +Defined-By: systemd +Support: %SUPPORT_URL% + +A rendszer kilépett ebből az alvási állapotból: @SLEEP@. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Rendszer leállítása kezdeményezve +Defined-By: systemd +Support: %SUPPORT_URL% + +A systemd leállítása kezdeményezve. A leállítás megkezdődött, minden +rendszerszolgáltatás befejeződik, minden fájlrendszer leválasztásra kerül. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: A(z) @UNIT@ egység indítása megkezdődött +Defined-By: systemd +Support: %SUPPORT_URL% + +A(z) @UNIT@ egység megkezdte az indulást. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: A(z) @UNIT@ egység befejezte az indulást +Defined-By: systemd +Support: %SUPPORT_URL% + +A(z) @UNIT@ egység befejezte az indulást + +Az indítás eredménye: @JOB_RESULT@. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: A(z) @UNIT@ egység megkezdte a leállást +Defined-By: systemd +Support: %SUPPORT_URL% + +A(z) @UNIT@ egység megkezdte a leállást. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: A(z) @UNIT@ egység befejezte a leállást +Defined-By: systemd +Support: %SUPPORT_URL% + +A(z) @UNIT@ egység befejezte a leállást. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: A(z) @UNIT@ egység hibát jelzett +Defined-By: systemd +Support: %SUPPORT_URL% + +A(z) @UNIT@ egység hibát jelzett. + +Az eredmény: @JOB_RESULT@. + +-- d34d037fff1847e6ae669a370e694725 +Subject: A(z) @UNIT@ egység megkezdte a beállításainak újratöltését +Defined-By: systemd +Support: %SUPPORT_URL% + +A(z) @UNIT@ egység megkezdte a beállításainak újratöltését. + +-- 7b05ebc668384222baa8881179cfda54 +Subject: A(z) @UNIT@ egység befejezte a beállításainak újratöltését +Defined-By: systemd +Support: %SUPPORT_URL% + +A(z) @UNIT@ egység befejezte a beállításainak újratöltését. + +Az eredmény: @JOB_RESULT@. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: A folyamat végrehajtása sikertelen: @EXECUTABLE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +A folyamat végrehajtása sikertelen volt, és hibát jelzett: @EXECUTABLE@. + +A folyamat által visszaadott hibaszám: @ERRNO@. + +-- 0027229ca0644181a76c4e92458afa2e +Subject: Legalább egy üzenet nem továbbítható a rendszernaplónak +Defined-By: systemd +Support: %SUPPORT_URL% + +Legalább egy üzenet nem volt továbbítható a journald-vel párhuzamosan futó +syslog szolgáltatásnak. Ez általában azt jelenti, hogy a syslog +megvalósítás nem volt képes lépést tartani a sorba állított +üzenetek sebességével. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: A csatolási pont nem üres +Defined-By: systemd +Support: %SUPPORT_URL% + +A csatolási pontként megadott @WHERE@ könyvtár (második mező az /etc/fstab +fájlban, vagy a Where= sor a systemd egységfájlban) nem üres. Ez nem +akadályozza meg a csatolást, de a könyvtárban már meglévő fájlok +elérhetetlenné válnak. A fájlok láthatóvá tételéhez csatolja +az azokat tartalmazó fájlrendszert egy másodlagos helyre. + +-- 24d8d4452573402496068381a6312df2 +Subject: Egy virtuális gép vagy konténer elindult +Defined-By: systemd +Support: %SUPPORT_URL% + +A(z) @NAME@ nevű virtuális gép (vezető PID: @LEADER@) elindult, és +használatra kész. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: Egy virtuális gép vagy konténer befejeződött +Defined-By: systemd +Support: %SUPPORT_URL% + +A(z) @NAME@ nevű virtuális gép (vezető PID: @LEADER@) leállt. diff --git a/catalog/systemd.it.catalog.in b/catalog/systemd.it.catalog.in new file mode 100644 index 00000000..c1375cca --- /dev/null +++ b/catalog/systemd.it.catalog.in @@ -0,0 +1,427 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Copyright © 2013-2019 Daniele Medri + +# Message catalog for systemd's own messages +# Italian translation + +# Il formato dei messaggi di catalogo è descritto (in inglese) qui: +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# Subject: The Journal has been started +-- f77379a8490b408bbe5f6940505a777b +Subject: Il registro è stato avviato +Defined-By: systemd +Support: %SUPPORT_URL% + +Il processo relativo al registro di sistema è stato avviato, ha aperto i +file in scrittura ed è ora pronto a gestire richieste. + +# Subject: The Journal has been stopped +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: Il registro è stato terminato +Defined-By: systemd +Support: %SUPPORT_URL% + +Il processo relativo al registro di sistema è stato terminato e ha chiuso +tutti i file attivi. + +# Subject: Disk space used by the journal +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: Spazio disco utilizzato dal journal +Defined-By: systemd +Support: %SUPPORT_URL% + +@JOURNAL_NAME@ (@JOURNAL_PATH@) sta attualmente utilizzando @CURRENT_USE_PRETTY@. +L'utilizzo massimo consentito è impostato a @MAX_USE_PRETTY@. +Si lasciano liberi almeno @DISK_KEEP_FREE_PRETTY@ (attuale spazio libero: @DISK_AVAILABLE_PRETTY@). +Il limite di utilizzo forzato è quindi @LIMIT_PRETTY@, con @AVAILABLE_PRETTY@ ancora disponibili. + +I limiti di controllo dello spazio disco utilizzati dal Journal possono +essere configurati con le impostazioni SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, +RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= nel file di configurazione +/etc/systemd/journald.conf. Guardare journald.conf(5) per i dettagli. + +# Subject: Messages from a service have been suppressed +-- a596d6fe7bfa4994828e72309e95d61e +Subject: I messaggi di un servizio sono stati soppressi +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Un servizio ha registrato troppi messaggi in un dato periodo di tempo. +I messaggi del servizio sono stati eliminati. + +Solo i messaggi del servizio indicato sono stati +eliminati, i messaggi degli altri servizi rimangono invariati. + +I limiti oltre i quali si eliminano i messaggi si configurano +con RateLimitIntervalSec= e RateLimitBurst= in +/etc/systemd/journald.conf. Vedi journald.conf(5) per maggiori informazioni. + +# Subject: Journal messages have been missed +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: I messaggi di un servizio sono stati perduti +Defined-By: systemd +Support: %SUPPORT_URL% + +I messaggi del kernel sono andati persi perché il registro di sistema +non è stato in grado di gestirli abbastanza velocemente. + +# Subject: Process @COREDUMP_PID@ (@COREDUMP_COMM@) dumped core +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Il processo @COREDUMP_PID@ (@COREDUMP_COMM@) ha generato un dump. +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Il processo @COREDUMP_PID@ (@COREDUMP_COMM@) si è bloccato generando un dump. + +Questo di solito capita per un errore di programmazione nell'applicazione e +dovrebbe essere segnalato come bug al vendor. + +# Subject: Core file was truncated to @SIZE_LIMIT@ bytes +-- 5aadd8e954dc4b1a8c954d63fd9e1137 +Subject: Il Core file è stato troncato a @SIZE_LIMIT@ bytes. +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:coredump.conf(5) + +Il processo ha più memoria mappata del limite massimo configurato da systemd-coredump(8) +per processare e memorizzare. Solo i primi @SIZE_LIMIT@ bytes sono stati salvati. +Il file potrebbe essere ancora utile, ma strumenti come gdb(1) dovrebbero +segnalare la troncatura. + +# Subject: A new session @SESSION_ID@ has been created for user @USER_ID@ +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: La nuova sessione @SESSION_ID@ è stata creata per l'utente @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Una nuova sessione con ID @SESSION_ID@ è stata creata per l'utente @USER_ID@. + +Il processo primario della sessione è @LEADER@. + +# Subject: A new seat @SEAT_ID@ has been terminated +-- 3354939424b4456d9802ca8333ed424a +Subject: La sessione @SESSION_ID@ è terminata +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +La sessione con ID @SESSION_ID@ è terminata. + +# Subject: A new seat @SEAT_ID@ is now available +-- fcbefc5da23d428093f97c82a9290f7b +Subject: La nuova postazione @SEAT_ID@ è ora disponibile +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +La nuova postazione @SEAT_ID@ è stata configurata ed è ora disponibile. + +# Subject: A seat @SEAT_ID@ has been removed +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: La postazione @SEAT_ID@ è stata rimossa +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +La postazione @SEAT_ID@ è stata rimossa e non è più disponibile. + +# Subject: Time Change +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Cambio d'orario +Defined-By: systemd +Support: %SUPPORT_URL% + +L'orologio di sistema è cambiato in @REALTIME@ microsecondi dal 1 gennaio, 1970. + +# Subject: Time zone change to @TIMEZONE@ +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Il fuso orario è cambiato in @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Il fuso orario di sistema è cambiato in @TIMEZONE@. + +# Subject: System start-up is now complete +-- b07a249cd024414a82dd00cd181378ff +Subject: Avvio del sistema completato. +Defined-By: systemd +Support: %SUPPORT_URL% + +Tutti i servizi di sistema richiesti per la fase di avvio sono stati eseguiti +con successo. La macchina potrebbe ancora attendere i servizi attivati sono +in fase di completamento. + +L'avvio del kernel ha richiesto @KERNEL_USEC@ microsecondi. + +L'avvio del disco RAM ha richiesto @INITRD_USEC@ microsecondi. + +L'avvio dello userspace ha richiesto @USERSPACE_USEC@ microsecondi. + +# Subject: User manager start-up is now complete +-- eed00a68ffd84e31882105fd973abdd1 +Subject: L'istanza di gestione per l'utente è completata +Defined-By: systemd +Support: %SUPPORT_URL% + +L'istanza di gestione per l'utente @_UID@ è stata avviata. Tutti i servizi +interrogati sono stati avviati. Altri servizi potrebbero essere ancora in +fase di avvio o in attesa di essere avviati. + +L'avvio dell'istanza ha impiegato @USERSPACE_USEC@ microsecondi. + +# Subject: System sleep state @SLEEP@ entered +-- 6bbd95ee977941e497c48be27c254128 +Subject: Il sistema è entrato in fase di pausa @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Il sistema è entrato nello stato di pausa @SLEEP@. + +# Subject: System sleep state @SLEEP@ left +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: Il sistema è uscito dalla fase di pausa @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Il sistema è uscito dallo stato di pausa @SLEEP@. + +# Subject: System shutdown initiated +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Il sistema è in fase di spegnimento +Defined-By: systemd +Support: %SUPPORT_URL% + +Systemd è in fase di spegnimento. Tutti i servizi di sistema +saranno terminati e tutti i file systems smontati. + +# Subject: Unit @UNIT@ has begun with start-up +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: L'unità @UNIT@ inizia la fase di avvio +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unità @UNIT@ ha iniziato la fase di avvio. + +# Subject: Unit @UNIT@ has finished start-up +-- 39f53479d3a045ac8e11786248231fbf +Subject: L'unità @UNIT@ ha terminato la fase di avvio +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unità @UNIT@ ha terminato la fase di avvio. + +La fase di avvio è @JOB_RESULT@. + +# Subject: Unit @UNIT@ has begun shutting down +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: L'unità @UNIT@ ha iniziato la fase di spegnimento +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unità @UNIT@ ha iniziato la fase di spegnimento. + +# Subject Unit @UNIT@ has finished shutting down +-- 9d1aaa27d60140bd96365438aad20286 +Subject: L'unità @UNIT@ ha terminato la fase di spegnimento +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unità @UNIT@ ha terminato la fase di spegnimento. + +# Subject: Unit @UNIT@ has failed +-- be02cf6855d2428ba40df7e9d022f03d +Subject: L'unità @UNIT@ è fallita +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unità @UNIT@ è fallita. + +Il risultato è @JOB_RESULT@. + +# Subject: Unit @UNIT@ has begun with reloading its configuration +-- d34d037fff1847e6ae669a370e694725 +Subject: L'unità @UNIT@ è iniziata con il ricaricamento della propria configurazione +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unità @UNIT@ è iniziata con il ricaricamento della propria configurazione + +# Subject: Unit @UNIT@ has finished reloading its configuration +-- 7b05ebc668384222baa8881179cfda54 +Subject: L'unità @UNIT@ è terminata con il ricaricamento della propria configurazione +Defined-By: systemd +Support: %SUPPORT_URL% + +L'unità @UNIT@ è terminata con il ricaricamento della propria configurazione + +Il risultato è @JOB_RESULT@. + +# Subject: Process @EXECUTABLE@ could not be executed +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Il processo @EXECUTABLE@ non può essere eseguito +Defined-By: systemd +Support: %SUPPORT_URL% + +Il processo @EXECUTABLE@ non può essere eseguito e termina. + +Il numero di errore restituito durante l'esecuzione del processo è @ERRNO@. + +# Subject: One or more messages could not be forwarded to syslog +-- 0027229ca0644181a76c4e92458afa2e +Subject: Uno o più messaggi non possono essere inoltrati a syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +Uno o più messaggi non possono essere inviati al servizio syslog +eseguito in parallelo a journald. Questo di solito capita perché, +l'implementazione di syslog non sta al passo con la +velocità dei messaggi accodati. + +# Subject: Mount point is not empty +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Il punto di montaggio non è vuoto +Defined-By: systemd +Support: %SUPPORT_URL% + +La directory @WHERE@ è specificata come punto di montaggio (secondo campo +in /etc/fstab o nel campo Where= del file unità di systemd) e non è vuoto. +Questo non interferisce con il montaggio, ma i file pre-esistenti in questa +directory diventano inaccessibili. Per visualizzare i file, si suggerisce +di montare manualmente il file system indicato in una posizione secondaria. + +# Subject: A virtual machine or container has been started +-- 24d8d4452573402496068381a6312df2 +Subject: Avviata macchina virtuale o container +Defined-By: systemd +Support: %SUPPORT_URL% + +La macchina virtuale @NAME@ con PID primario @LEADER@ è stata +avviata ed è pronta all'uso. + +# Subject: A virtual machine or container has been terminated +-- 58432bd3bace477cb514b56381b8a758 +Subject: Terminata macchina virtuale o container +Defined-By: systemd +Support: %SUPPORT_URL% + +La macchina virtuale @NAME@ con PID primario @LEADER@ è stata terminata. + +# Subject: DNSSEC mode has been turned off, as server doesn't support it +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: La modalità DNSSEC è stata spenta, il server non la supporta +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +Il servizio di risoluzione (systemd-resolved.service) ha rilevato che il +server DNS indicato non supporta DNSSEC e la validazione di quest'ultimo tipo +è stata conseguentemente disabilitata. + +Ciò avverrà se DNSSEC=allow-downgrade è configurato nel file +resolved.conf e il server DNS indicato è incompatibile con DNSSEC. +In questo modo ci si espone ad attacchi "DNSSEC downgrade", e un aggressore +potrebbe disabilitare la validazione DNSSEC sul sistema inserendo risposte +DNS nel canale di comunicazione. + +Questo evento potrebbe indicare un'incompatibilità del DNS Server con DNSSEC o +che un aggressore è riuscito nel suo intento malevolo. + +# Subject: DNSSEC validation failed +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: La validazione DNSSEC è fallita +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Una query DNS o un dato hanno fatto fallire la validazione DNSSEC. Questo è +usualmente un segnale che il canale di comunicazione utilizzato è stato +manomesso. + +# Subject: A DNSSEC trust anchor has been revoked +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: Un trust anchor DNSSEC è stato revocato +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Un trust anchor DNSSEC è stato revocato. Un nuovo punto di fiducia è stato +riconfigurato o il sistema operativo deve essere aggiornato per fornire un +nuovo ancoraggio. + +# Subject: Automatic restarting of a unit has been scheduled +-- 5eb03494b6584870a536b337290809b3 +Subject: Il riavvio automatico di un'unità è stato schedulato +Defined-By: systemd +Support: %SUPPORT_URL% + +Il riavvio automatico dell'unità @UNIT@ è stato schedulato, come risultato +delle impostazioni configurate in Restart=. + +# Subject: Resources consumed by unit runtime +-- ae8f7b866b0347b9af31fe1c80b127c0 +Subject: Risorse utilizzate dall'unità in esecuzione +Defined-By: systemd +Support: %SUPPORT_URL% + +Unità @UNIT@ terminata consumando le indicate risorse. + +# Subject: Unit succeeded +-- 7ad2d189f7e94e70a38c781354912448 +Subject: Unità terminata +Defined-By: systemd +Support: %SUPPORT_URL% + +Unità @UNIT@ entrata con successo nello stato 'dead' (morto). + +# Subject: Unit failed +-- d9b373ed55a64feb8242e02dbe79a49c +Subject: Unit fallita +Defined-By: systemd +Support: %SUPPORT_URL% + +Unità @UNIT@ entrata nello stato 'failed' (fallito) con risultato '@UNIT_RESULT@'. + +# Subject: Unit process exited +-- 98e322203f7a4ed290d09fe03c09fe15 +Subject: Uscito processo unità +Defined-By: systemd +Support: %SUPPORT_URL% + +Un processo @COMMAND@ appartenente all'unità @UNIT@ è uscito. + +Il codice di uscita del processo è '@EXIT_CODE@' ed è uscito con @EXIT_STATUS@. + +# Subject: The system is configured in a way that might cause problems +-- 50876a9db00f4c40bde1a2ad381c3a1b +Subject: Il sistema è configurato in un modo che potrebbe causare problemi +Defined-By: systemd +Support: %SUPPORT_URL% + +I seguenti "tags" sono possibili: +- "split-usr" — /usr è un file system separato e non è stato montato all'avvio di systemd +- "cgroups-missing" — il kernel era compilato senza supporto cgroup o l'accesso ai + file attesi è ristretto. +- "var-run-bad" — /var/run non è un link simbolico (symlink) a /run +- "overflowuid-not-65534" — l'ID usato dal kernel per gli utenti "unknown" (tipo + NFS o user namespace) non è 65534 +- "overflowgid-not-65534" — l'ID usato dal kernel per il gruppo "unknown" (tipo + NFS o user namespace) non è 65534 +L'attuale sistema è taggato come @TAINT@. + +# Subject: A process of @UNIT@ unit has been killed by the OOM killer. +-- fe6faa94e7774663a0da52717891d8ef +Subject: Un processo dell'unità @UNIT@ è stato terminato da un OOM killer. +Defined-By: systemd +Support: %SUPPORT_URL% + +Un processo dell'unità @UNIT@ è stato terminato dalla logica del kernel Linux per +gestire gli eventi out-of-memory (OOM). In altri termini, il sistema ha +poca memoria e dovrebbe essere liberata. Un processo associato con @UNIT@ è +stato identificato come il processo ideale da terminare e così è stato. + +La pressione sulla memoira potrebbe o meno essere causata da @UNIT@. diff --git a/catalog/systemd.ko.catalog.in b/catalog/systemd.ko.catalog.in new file mode 100644 index 00000000..59fbde8b --- /dev/null +++ b/catalog/systemd.ko.catalog.in @@ -0,0 +1,306 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +# Message catalog for systemd's own messages +# Korean translation + +# The catalog format is documented on +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# For an explanation why we do all this, see https://xkcd.com/1024/ +# +# Translator : +# Seong-ho Cho , 2015. +# Dongsu Park , 2016. + +-- f77379a8490b408bbe5f6940505a777b +Subject: 저널 시작 +Defined-By: systemd +Support: %SUPPORT_URL% + +시스템 저널 프로세스를 시작했고 기록목적으로 저널 파일을 열었으며, +프로세스 요청을 기다리고 있습니다. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: 저널 멈춤 +Defined-By: systemd +Support: %SUPPORT_URL% + +시스템 저널 프로세스를 껐고 현재 활성화 중인 저널 파일을 모두 +닫았습니다. + +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: 저널이 디스크 공간을 점유중 +Defined-By: systemd +Support: %SUPPORT_URL% + +저널 @JOURNAL_NAME@ (@JOURNAL_PATH@)이 현재 @CURRENT_USE_PRETTY@ +만큼의 용량을 사용하고 있습니다. 최대 허용 용량은 +@MAX_USE_PRETTY@입니다. 최소한 @DISK_KEEP_FREE_PRETTY@의 빈공간을 +남겨둡니다. (현재 디스크 전체 용량은 @DISK_AVAILABLE_PRETTY@) +따라서 실제 사용 최대 한도는 @LIMIT_PRETTY@으로 설정되며, +@AVAILABLE_PRETTY@ 만큼의 용량이 계속 비어있습니다. + +저널이 차지하는 디스크 공간을 제어하기 위해서는 +/etc/systemd/journald.conf 의 SystemMaxUse=, SystemKeepFree=, +SystemMaxFileSize=, RuntimeMaxUse=, RuntimeKeepFree=, +RuntimeMaxFileSize= 변수를 설정합니다. 자세한 내용은 +journald.conf(5)을 살펴보십시오. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: 서비스의 메시지를 거절함 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +일정 시간동안 서비스에서 너무 많은 메시지를 기록했습니다. +서비스에서 오는 메시지를 거절했습니다. + +의문점이 있는 서비스로부터 오는 메시지만 거절했음을 참고하십시오 +다른 서비스의 메시지에는 영향을 주지 않습니다. + +메시지 거절 제어 제한 값은 /etc/systemd/journald.conf 의 +RateLimitIntervalSec= 변수와 RateLimitBurst= 변수로 설정합니다. +자세한 내용은 journald.conf(5)를 살펴보십시오. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: 저널 메시지 놓침 +Defined-By: systemd +Support: %SUPPORT_URL% + +저널 시스템에서 커널 메시지를 충분히 빠르게 처리할 수 없어 커널 + 메시지를 잃었습니다. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: 프로세스 @COREDUMP_PID@번 코어 덤프(@COREDUMP_COMM@) 생성함 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +프로세스 @COREDUMP_PID@번 (@COREDUMP_COMM@)이 비정상적으로 끝나 +코어 덤프를 생성했습니다. + +보통 비정상 종료 관리 프로그램에서 프로그래밍 오류를 나타내며, +제작자에게 버그로 보고해야합니다. + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: @USER_ID@ 사용자의 새 @SESSION_ID@ 세션 만듦 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +@USER_ID@ 사용자의 새 @SESSION_ID@ 세션을 만들었습니다. + +이 세션의 관리 프로세스는 @LEADER@ 입니다. + +-- 3354939424b4456d9802ca8333ed424a +Subject: @SESSION_ID@ 세션 마침 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +@SESSION_ID@ 세션을 끝냈습니다. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: 새 @SEAT_ID@ 시트 사용할 수 있음 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +새 @SEAT_ID@ 시트를 설정했고 사용할 수 있습니다. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: @SEAT_ID@ 시트 제거함 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +@SEAT_ID@ 시트를 제거했으며 더이상 사용할 수 없습니다. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: 시간 바꿈 +Defined-By: systemd +Support: %SUPPORT_URL% + +시스템 시계를 1970년 1월 1일 이후로 @REALTIME@ 마이크로초 지난 값으로 +설정했습니다. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: @TIMEZONE@ 시간대로 시간대 바꿈 +Defined-By: systemd +Support: %SUPPORT_URL% + +시스템 시간대를 @TIMEZONE@ 시간대로 바꾸었습니다. + +-- b07a249cd024414a82dd00cd181378ff +Subject: 시스템 시동 마침 +Defined-By: systemd +Support: %SUPPORT_URL% + +부팅 과정에 시작하려고 준비한 모든 시스템 서비스를 성공적으로 + 시작했습니다. 머신이 서비스처럼 대기중이라는 의미는 아니며 +지동을 완전히 마칠 때까지 사용중일 수도 있는 점 참고하십시오. + +커널 시동에 @KERNEL_USEC@ 마이크로초가 걸립니다. + +초기 램 디스크 시동에 @INITRD_USEC@ 마이크로초가 걸립니다. + +사용자 영역 시동에 @USERSPACE_USEC@ 마이크로초가 걸립니다. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: @SLEEP@ 대기 상태 진입 +Defined-By: systemd +Support: %SUPPORT_URL% + +@SLEEP@ 대기 상태로 진입했습니다. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: @SLEEP@ 대기 상태 마침 +Defined-By: systemd +Support: %SUPPORT_URL% + +@SLEEP@ 대기 상태를 마쳤습니다. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: 컴퓨터 끄기 시작 +Defined-By: systemd +Support: %SUPPORT_URL% + +컴퓨터 끄기 동작을 시작했습니다. 모든 시스템 동작을 멈추고 +모든 파일 시스템의 마운트를 해제합니다. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: @UNIT@ 유닛 시작 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 유닛을 시작했습니다. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: @UNIT@ 유닛 시동 마침 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 유닛 시동을 마쳤습니다. + +시동 결과는 @JOB_RESULT@ 입니다. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: @UNIT@ 유닛 끝내기 동작 시작 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 유닛 끝내기 동작을 시작했습니다. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: @UNIT@ 유닛 끝내기 동작 마침 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 유닛 끝내기 동작을 마쳤습니다. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: @UNIT@ 유닛 동작 실패 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 유닛 동작에 실패했습니다. + +결과는 @JOB_RESULT@ 입니다. + +-- d34d037fff1847e6ae669a370e694725 +Subject: @UNIT@ 유닛 설정 다시 읽기 시작 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 유닛의 설정 다시 읽기를 시작했습니다 + +-- 7b05ebc668384222baa8881179cfda54 +Subject: @UNIT@ 유닛 설정 다시 읽기 완료 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 유닛의 설정 다시 읽기 동작을 끝냈습니다. + +결과는 @JOB_RESULT@ 입니다. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: @EXECUTABLE@ 프로세스 시작할 수 없음 +Defined-By: systemd +Support: %SUPPORT_URL% + +@EXECUTABLE@ 프로세스를 시작할 수 없어 실행에 실패했습니다. + +이 프로세스에서 반환한 오류 번호는 @ERRNO@번 입니다. + +-- 0027229ca0644181a76c4e92458afa2e +Subject: 하나 이상의 메시지를 syslog에 전달할 수 없음 +Defined-By: systemd +Support: %SUPPORT_URL% + +journald 서비스와 동시에 실행중인 syslog 서비스에 하나 이상의 메시지를 +전달할 수 없습니다. 보통 순차적으로 오는 메시지의 속도를 syslog 구현체가 +따라가지 못함을 의미합니다. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: 마운트 지점 비어있지 않음 +Defined-By: systemd +Support: %SUPPORT_URL% + +@WHERE@ 디렉터리를 마운트 지점으로 지정했으며 (/etc/fstab 파일의 + 두번째 필드 또는 systemd 유닛 파일의 Where= 필드) 비어있지 않습니다. +마운트 과정에 방해가 되진 않지만 이전에 이 디렉터리에 존재하는 파일에 + 접근할 수 없게 됩니다. 중복으로 마운트한 파일을 보려면, 근본 파일 +시스템을 별도 위치에 직접 마운트하십시오. + +-- 24d8d4452573402496068381a6312df2 +Subject: 가상 머신 또는 컨테이너 시작 +Defined-By: systemd +Support: %SUPPORT_URL% + +@LEADER@ 프로세스 ID로 동작하는 @NAME@ 가상 머신을 시작했으며, +이제부터 사용할 수 있습니다. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: 가상 머신 또는 컨테이너 마침 +Defined-By: systemd +Support: %SUPPORT_URL% + +@LEADER@ 프로세스 ID로 동작하는 @NAME@ 가상 머신을 껐습니다. + +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: 서버 미지원으로 인하여 DNSSEC 모드 종료 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +해당 DNS 서버가 DNSSEC을 지원하지 않는다는 것을 리졸버 서비스 +(systemd-resolved.service)가 인식했습니다. 따라서 DNSSEC 검증 기능도 +꺼집니다. + +이 이벤트는 resolved.conf 파일에 DNSSEC=allow-downgrade가 설정되었고, 해당 +DNS 서버가 DNSSEC과 비호환일 경우에만 발생합니다. 이 모드를 켤 경우에는 +DNSSEC 다운그레이드 공격을 허용할수 있다는 점에 주의하세요. 이는 공격자 +역시 다운그레이드가 발생한 통신 채널에 DNS 응답 메시지를 끼워넣는 방식으로 +DNSSEC 검증 기능을 꺼버릴수 있기 때문입니다. + +이 이벤트가 의미하는 것은, DNS 서버가 실제로 DNSSEC과 비호환이거나, 또는 +공격자가 위와 같은 다운그레이드 공격을 수행하는데 성공했다는 뜻입니다. + +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: DNSSEC 검증 실패 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +DNS 요청 또는 리소스 레코드가 DNSSEC 검증에 실패했습니다. 이것은 보통 +해당 통신 채널이 조작되었다는 뜻입니다. + +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: DNSSEC 신뢰성 시작점 취소 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +DNSSEC 신뢰성 시작점이 취소되었습니다. 새로운 신뢰성 시작점이 설정되거나, +또는 업데이트된 DNSSEC 신뢰성 시작점을 제공하기 위해서 운영체제를 업데이트 +해야 합니다. diff --git a/catalog/systemd.pl.catalog.in b/catalog/systemd.pl.catalog.in new file mode 100644 index 00000000..1a6c2546 --- /dev/null +++ b/catalog/systemd.pl.catalog.in @@ -0,0 +1,413 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +# Message catalog for systemd's own messages +# Polish translation + +# The catalog format is documented on +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# For an explanation why we do all this, see https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: Uruchomiono dziennik +Defined-By: systemd +Support: %SUPPORT_URL% + +Systemowy proces dziennika został uruchomiony, otworzył pliki dziennika +do zapisu i jest gotowy do przetwarzania żądań. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: Zatrzymano dziennik +Defined-By: systemd +Support: %SUPPORT_URL% + +Systemowy proces dziennika został wyłączony i zamknął wszystkie obecnie +aktywne pliki dziennika. + +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: Miejsce na dysku używane przez dziennik +Defined-By: systemd +Support: %SUPPORT_URL% + +@JOURNAL_NAME@ (@JOURNAL_PATH@) obecnie używa @CURRENT_USE_PRETTY@. +Maksymalnie może używać @MAX_USE_PRETTY@. +Zostawianie co najmniej @DISK_KEEP_FREE_PRETTY@ wolnego (z obecnie dostępnego @DISK_AVAILABLE_PRETTY@ miejsca na dysku). +Wymuszone ograniczenie użycia wynosi więc @LIMIT_PRETTY@, z czego @AVAILABLE_PRETTY@ jest nadal dostępne. + +Ograniczenia kontrolujące ilość miejsca na dysku używanego przez dziennik +można konfigurować za pomocą ustawień SystemMaxUse=, SystemKeepFree=, +SystemMaxFileSize=, RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= +w pliku /etc/systemd/journald.conf. Strona journald.conf(5) zawiera więcej +informacji. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Ograniczono komunikaty z usługi +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Usługa zapisała za dużo komunikatów w określonym czasie. +Komunikaty z usługi zostały pominięte. + +Proszę zauważyć, że tylko komunikaty z danej usługi zostały pominięte. +Nie ma to wpływu na komunikaty innych usług. + +Ograniczenia kontrolujące pomijanie komunikatów mogą być konfigurowane +za pomocą opcji RateLimitIntervalSec= i RateLimitBurst= w pliku +/etc/systemd/journald.conf lub LogRateLimitIntervalSec= i LogRateLimitBurst= +w pliku jednostki. Strony journald.conf(5) i systemd.exec(5) zawierają więcej +informacji. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Utracono komunikaty dziennika +Defined-By: systemd +Support: %SUPPORT_URL% + +Komunikaty jądra zostały utracone, ponieważ system dziennika nie mógł +przetworzyć ich odpowiednio szybko. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Proces @COREDUMP_PID@ (@COREDUMP_COMM@) zrzucił plik core +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Proces @COREDUMP_PID@ (@COREDUMP_COMM@) uległ awarii i zrzucił plik core. + +Zwykle wskazuje to na błąd programistyczny w danym programie i powinno zostać +zgłoszone jego producentowi jako błąd. + +-- 5aadd8e954dc4b1a8c954d63fd9e1137 +Subject: Plik core został skrócony do @SIZE_LIMIT@ B. +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:coredump.conf(5) + +Proces miał więcej zmapowanej pamięci niż maksimum dla przetwarzania i miejsca +skonfigurowane przez systemd-coredump(8). Tylko pierwsze @SIZE_LIMIT@ B +zostało zapisanych. Ten plik core może nadal być używalny, ale narzędzia typu +gdb(1) będą ostrzegały o skróceniu pliku. + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: Utworzono nową sesję @SESSION_ID@ dla użytkownika @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Nowa sesja o identyfikatorze @SESSION_ID@ została utworzona dla użytkownika +@USER_ID@. + +Proces prowadzący sesji: @LEADER@. + +-- 3354939424b4456d9802ca8333ed424a +Subject: Zakończono sesję @SESSION_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Sesja o identyfikatorze @SESSION_ID@ została zakończona. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: Dostępne jest nowe stanowisko @SEAT_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Nowe stanowisko @SEAT_ID@ zostało skonfigurowane i jest teraz dostępne. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Usunięto stanowisko @SEAT_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Stanowisko @SEAT_ID@ zostało usunięte i nie jest już dostępne. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Zmiana czasu +Defined-By: systemd +Support: %SUPPORT_URL% + +Zegar systemowy został zmieniony na @REALTIME@ μs po 1 stycznia 1970. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Zmiana strefy czasowej na @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Systemowa strefa czasowa została zmieniona na @TIMEZONE@. + +-- b07a249cd024414a82dd00cd181378ff +Subject: Ukończono uruchamianie systemu +Defined-By: systemd +Support: %SUPPORT_URL% + +Wszystkie usługi systemowe obowiązkowo zakolejkowane do włączenia podczas +uruchamiania systemu zostały uruchomione. Proszę zauważyć, że nie oznacza +to, że komputer jest bezczynny, jako że usługi mogą wciąż kończyć proces +uruchamiania. + +Uruchamianie jądra zajęło @KERNEL_USEC@ μs. + +Uruchamianie początkowego dysku RAM zajęło @INITRD_USEC@ μs. + +Uruchamianie przestrzeni użytkownika zajęło @USERSPACE_USEC@ μs. + +-- eed00a68ffd84e31882105fd973abdd1 +Subject: Ukończono uruchamianie menedżera użytkownika +Defined-By: systemd +Support: %SUPPORT_URL% + +Wystąpienie menedżera dla użytkownika @_UID@ zostało uruchomione. +Wszystkie usługi zakolejkowane do włączenia zostały uruchomione. +Proszę zauważyć, że inne usługi mogą być nadal uruchamiane +lub zostać uruchomione później. + +Uruchamianie menedżera zajęło @USERSPACE_USEC@ μs. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: Przejście do stanu uśpienia @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +System przeszedł do stanu uśpienia @SLEEP@. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: Wyjście ze stanu uśpienia @SLEEP@ +Defined-By: systemd +Support: %SUPPORT_URL% + +System wyszedł ze stanu uśpienia @SLEEP@. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Zainicjowano wyłączenie systemu +Defined-By: systemd +Support: %SUPPORT_URL% + +Zainicjowano wyłączenie systemu. Wyłączenie zostało rozpoczęte i wszystkie +usługi systemowe zostały zakończone, a wszystkie systemy plików odmontowane. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: Rozpoczęto wykonywanie zadania uruchamiania dla jednostki @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Rozpoczęto wykonywanie zadania uruchamiania dla jednostki @UNIT@. + +Identyfikator zadania: @JOB_ID@. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: Pomyślnie ukończono zadanie uruchamiania dla jednostki @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Pomyślnie ukończono zadanie uruchamiania dla jednostki @UNIT@. + +Identyfikator zadania: @JOB_ID@. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: Zadanie uruchamiania dla jednostki @UNIT@ się nie powiodło +Defined-By: systemd +Support: %SUPPORT_URL% + +Zadanie uruchamiania dla jednostki @UNIT@ zostało ukończone z niepowodzeniem. + +Identyfikator zadania: @JOB_ID@, wynik zadania: @JOB_RESULT@. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: Rozpoczęto wykonywanie zadania zatrzymania dla jednostki @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Rozpoczęto wykonywanie zadania zatrzymania dla jednostki @UNIT@. + +Identyfikator zadania: @JOB_ID@. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: Ukończono zadanie zatrzymania dla jednostki @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Ukończono zadanie zatrzymania dla jednostki @UNIT@. + +Identyfikator zadania: @JOB_ID@, wynik zadania: @JOB_RESULT@. + +-- d34d037fff1847e6ae669a370e694725 +Subject: Rozpoczęto wykonywanie zadania ponownego wczytania dla jednostki @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Rozpoczęto wykonywanie zadania ponownego wczytania dla jednostki @UNIT@. + +Identyfikator zadania: @JOB_ID@. + +-- 7b05ebc668384222baa8881179cfda54 +Subject: Ukończono zadanie ponownego wczytania dla jednostki @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Ukończono zadanie ponownego wczytania dla jednostki @UNIT@. + +Identyfikator zadania: @JOB_ID@, wynik zadania: @JOB_RESULT@. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Nie można wykonać procesu @EXECUTABLE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Proces @EXECUTABLE@ nie mógł zostać wykonany i się nie powiódł. + +Numer błędu zwrócony przez ten proces: @ERRNO@. + +-- 0027229ca0644181a76c4e92458afa2e +Subject: Nie można przekazać jednego lub więcej komunikatów do syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +Jeden lub więcej komunikatów nie może zostać przekazanych do usługi syslog +uruchomionej obok journald. Zwykle oznacza to, że implementacja syslog nie +jest w stanie nadążyć za prędkością kolejki komunikatów. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Punkt montowania nie jest pusty +Defined-By: systemd +Support: %SUPPORT_URL% + +Katalog @WHERE@ został podany jako punkt montowania (drugie pole w pliku +/etc/fstab lub pole Where= w pliku jednostki systemd) i nie jest pusty. Nie +wpływa to na montowanie, ale wcześniej istniejące pliki w tym katalogu stają +się niedostępne. Aby zobaczyć te pliki, proszę ręcznie zamontować system +plików w innym położeniu. + +-- 24d8d4452573402496068381a6312df2 +Subject: Uruchomiono maszynę wirtualną lub kontener +Defined-By: systemd +Support: %SUPPORT_URL% + +Maszyna wirtualna @NAME@ (PID prowadzący @LEADER@) została uruchomiona i jest +gotowa do użycia. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: Zakończono maszynę wirtualną lub kontener +Defined-By: systemd +Support: %SUPPORT_URL% + +Maszyna wirtualna @NAME@ (PID prowadzący @LEADER@) została wyłączona. + +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: Wyłączono tryb DNSSEC, ponieważ serwer go nie obsługuje +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +Usługa resolver (systemd-resolved.service) wykryła, że skonfigurowany serwer +DNS nie obsługuje DNSSEC, w wyniku czego walidacja DNSSEC została wyłączona. + +To zdarzenie będzie miało miejsce, jeśli skonfigurowano DNSSEC=allow-downgrade +w pliku resolved.conf, a skonfigurowany serwer DNS jest niezgodny z DNSSEC. +Proszę zauważyć, że używanie tego trybu umożliwia ataki wyłączające DNSSEC, +ponieważ atakujący będzie mógł wyłączyć walidację DNSSEC na komputerze przez +umieszczenie odpowiednich odpowiedzi DNS w kanale komunikacji. + +To zdarzenie może wskazywać, że serwer DNS jest faktycznie niezgodny z DNSSEC, +albo że atakującemu udało się upozorować atak tego typu. + +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: Walidacja DNSSEC się nie powiodła +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Zapytanie DNS lub ustawiony wpis zasobu nie przeszedł walidacji DNSSEC. +Zwykle wskazuje to, że ktoś manipulował używanym kanałem komunikacji. + +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: Unieważniono kotwicę zaufania DNSSEC +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Kotwica zaufania DNSSEC została unieważniona. Należy skonfigurować nową, albo +system operacyjny musi zostać zaktualizowany, aby dostarczyć zaktualizowaną +kotwicę zaufania DNSSEC. + +-- 5eb03494b6584870a536b337290809b3 +Subject: Zaplanowano automatyczne ponowne uruchamianie jednostki +Defined-By: systemd +Support: %SUPPORT_URL% + +W wyniki skonfigurowania ustawienia Restart= zaplanowano automatyczne ponowne +uruchamianie jednostki @UNIT@. + +-- ae8f7b866b0347b9af31fe1c80b127c0 +Subject: Zasoby zużyte przez uruchomienie jednostki +Defined-By: systemd +Support: %SUPPORT_URL% + +Jednostka @UNIT@ została ukończona, zużywając wskazane zasoby. + +-- 7ad2d189f7e94e70a38c781354912448 +Subject: Jednostka się powiodła +Defined-By: systemd +Support: %SUPPORT_URL% + +Jednostka @UNIT@ pomyślnie przeszła do stanu „dead” (martwego). + +-- 0e4284a0caca4bfc81c0bb6786972673 +Subject: Pominięto jednostkę +Defined-By: systemd +Support: %SUPPORT_URL% + +Jednostka @UNIT@ została pominięta z powodu niepowodzenia +polecenia ExecCondition=, i przeszła do stanu „dead” (martwego) +z wynikiem „@UNIT_RESULT@”. + +-- d9b373ed55a64feb8242e02dbe79a49c +Subject: Jednostka się nie powiodła +Defined-By: systemd +Support: %SUPPORT_URL% + +Jednostka @UNIT@ przeszła do stanu „failed” (niepowodzenia) +z wynikiem „@UNIT_RESULT@”. + +-- 98e322203f7a4ed290d09fe03c09fe15 +Subject: Proces jednostki zakończył działanie +Defined-By: systemd +Support: %SUPPORT_URL% + +Proces @COMMAND@= należący do jednostki @UNIT@ zakończył działanie. + +Kod wyjścia procesu: „@EXIT_CODE@”, jego stan wyjścia: @EXIT_STATUS@. + +-- 50876a9db00f4c40bde1a2ad381c3a1b +Subject: System jest skonfigurowany w sposób, który może powodować problemy +Defined-By: systemd +Support: %SUPPORT_URL% + +Możliwe są następujące „etykiety”: +• „split-usr” — /usr jest oddzielnym systemem plików, który nie był + zamontowany w czasie uruchomienia systemd, +• „cgroups-missing” — jądro zostało skompilowane bez obsługi cgroups + lub dostęp do oczekiwanych plików interfejsu jest ograniczony, +• „var-run-bad” — /var/run nie jest dowiązaniem symbolicznym do /run, +• „overflowuid-not-65534” — identyfikator użytkownika dla „nieznanych” + użytkowników (przy wykorzystaniu przestrzeni nazw użytkowników lub NFS) + nie wynosi 65534, +• „overflowgid-not-65534” — identyfikator grupy dla „nieznanych” + użytkowników (przy wykorzystaniu przestrzeni nazw użytkowników lub NFS) + nie wynosi 65534. +Obecny system ma etykietę „@TAINT@”. + +-- fe6faa94e7774663a0da52717891d8ef +Subject: Proces jednostki @UNIT@ został zakończony przez OOM Killer +Defined-By: systemd +Support: %SUPPORT_URL% + +Proces jednostki @UNIT został zakończony przez mechanizm kończenia +procesów przy braku pamięci (OOM) jądra Linux. Zwykle wskazuje to, +że system ma mało pamięci i należało ją zwolnić. Proces powiązany +z jednostką @UNIT@ został uznany za najlepszy do zakończenia +i jądro wymusiło zakończenie jego działania. + +Proszę zauważyć, że brak pamięci mógł nie zostać spowodowany +przez jednostkę @UNIT@. diff --git a/catalog/systemd.pt_BR.catalog.in b/catalog/systemd.pt_BR.catalog.in new file mode 100644 index 00000000..edaefb71 --- /dev/null +++ b/catalog/systemd.pt_BR.catalog.in @@ -0,0 +1,250 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Copyright © 2015 Rafael Ferreira (translation) + +# Catálogo de mensagens para as mensagens do próprio systemd + +# O formato do catálogo está documentado em +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# Para uma explicação do porquê de fazermos tudo isso, veja +# https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: O jornal foi inciado +Defined-By: systemd +Support: %SUPPORT_URL% + +O processo jornal do sistema foi iniciado, arquivos foram abertos e está +pronto para processar requisições. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: O jornal foi interrompido +Defined-By: systemd +Support: %SUPPORT_URL% + +O processo do jornal do sistema foi desligado e todos os arquivos de jornal +do sistema foram fechados. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Mensagens de um serviço foram suprimidas +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Um serviço registrou no log um número excessivo de mensagens dentro de um +período de tempo. Mensagens do serviço foram descartadas. + +Note que apenas mensagens de um serviço em questão foram descartadas; outras +mensagens dos serviços não foram afetadas. + +Os controles de limites de quando as mensagens são descartadas pode ser +configurado com RateLimitIntervalSec= e RateLimitBurst= no +/etc/systemd/journald.conf. Veja journald.conf(5) para detalhes. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Mensagens do jornal foram perdidas +Defined-By: systemd +Support: %SUPPORT_URL% + +Mensagens do kernel foram perdidas pois o sistema do jornal não pôde +processá-las em velocidade suficiente para a demanda. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Processo @COREDUMP_PID@ (@COREDUMP_COMM@) despejou núcleo +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Processo @COREDUMP_PID@ (@COREDUMP_COMM@) travou e despejou o núcleo. + +Isso normalmente indica um erro de programação no programa que travou e +deveria ser relatado para seu fabricante como um erro. + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: A nova sessão @SESSION_ID@ foi criada para usuário o @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Uma nova sessão com o ID @SESSION_ID@ foi criada para o usuário @USER_ID@. + +O processo originador da sessão é @LEADER@. + +-- 3354939424b4456d9802ca8333ed424a +Subject: Sessão @SESSION_ID@ foi terminada +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Um sessão com o ID @SESSION_ID@ foi terminada. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: Um novo seat @SEAT_ID@ está disponível +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Um novo seat @SEAT_ID@ foi configurado e está disponível. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Seat @SEAT_ID@ foi removido agora +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Um seat @SEAT_ID@ foi removido e não está mais disponível. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Time change +Defined-By: systemd +Support: %SUPPORT_URL% + +O relógio do sistema foi alterado para @REALTIME@ microssegundos após 1º de +janeiro de 1970. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Fuso horário alterado para @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +O fuso horário do sistema foi alterado para @TIMEZONE@. + +-- b07a249cd024414a82dd00cd181378ff +Subject: Inicialização do sistema foi concluída +Defined-By: systemd +Support: %SUPPORT_URL% + +Todos os serviços do sistema necessários que estão enfileirados para +executar na inicialização do sistema, foram iniciados com sucesso. Note +que isso não significa que a máquina está ociosa, pois os serviços podem +ainda estar ocupados com a inicialização completa. + +Inicialização do kernel precisou @KERNEL_USEC@ microssegundos. + +Disco de RAM inicial precisou de @INITRD_USEC@ microssegundos. + +Inicialização do espaço do usuário precisou de @USERSPACE_USEC@ microssegundos. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: Estado de suspensão do sistema @SLEEP@ iniciado +Defined-By: systemd +Support: %SUPPORT_URL% + +O sistema entrou agora no estado de suspensão @SLEEP@. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: Estado de suspensão do sistema @SLEEP@ finalizado +Defined-By: systemd +Support: %SUPPORT_URL% + +O sistema saiu agora do estado de suspensão @SLEEP@. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Desligamento do sistema iniciado +Defined-By: systemd +Support: %SUPPORT_URL% + +Desligamento do sistema foi inicializado. O desligamento se iniciou e todos +os serviços do sistema foram terminados e todos os sistemas desmontados. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: Unidade @UNIT@ sendo iniciado +Defined-By: systemd +Support: %SUPPORT_URL% + +A unidade @UNIT@ está sendo iniciada. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: Unidade @UNIT@ concluiu a inicialização +Defined-By: systemd +Support: %SUPPORT_URL% + +A unidade @UNIT@ concluiu a inicialização. + +The start-up result is @JOB_RESULT@. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: Unidade @UNIT@ sendo desligado +Defined-By: systemd +Support: %SUPPORT_URL% + +A unidade @UNIT@ está sendo desligada. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: A unidade @UNIT@ concluiu o desligamento +Defined-By: systemd +Support: %SUPPORT_URL% + +A unidade @UNIT@ concluiu o desligamento. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: A unidade @UNIT@ falhou +Defined-By: systemd +Support: %SUPPORT_URL% + +A unidade @UNIT@ falhou. + +O resultado é @JOB_RESULT@. + +-- d34d037fff1847e6ae669a370e694725 +Subject: Unidade @UNIT@ iniciou recarregamento de sua configuração +Defined-By: systemd +Support: %SUPPORT_URL% + +A unidade @UNIT@ iniciou o recarregamento de sua configuração. + +-- 7b05ebc668384222baa8881179cfda54 +Subject: Unidade @UNIT@ concluiu recarregamento de sua configuração +Defined-By: systemd +Support: %SUPPORT_URL% + +A unidade @UNIT@ concluiu o recarregamento de sua configuração. + +O resultado é @JOB_RESULT@. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Processo @EXECUTABLE@ não pôde ser executado +Defined-By: systemd +Support: %SUPPORT_URL% + +O processo @EXECUTABLE@ não pôde ser executado e falhou. + +O número de erro retornado por este processo é @ERRNO@. + +-- 0027229ca0644181a76c4e92458afa2e +Subject: Uma ou mais mensagens não puderam ser encaminhadas para o syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +Uma ou mais mensagens não puderam ser encaminhadas para o serviço do syslog +em execução paralela ao journald. Isso normalmente indica que a implementação +do syslog não foi capaz de se manter com a velocidade das mensagens +enfileiradas. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Ponto de montagem não está vazio +Defined-By: systemd +Support: %SUPPORT_URL% + +O diretório @WHERE@ está especificado como ponto de montagem (o segundo campo +no /etc/fstab ou campo Where= no arquivo de unidade do systemd) e não está +vazio. Isso não interfere com a montagem, mas os arquivos pré-existentes +neste diretório se tornaram inacessívels. Para ver aqueles arquivos, sobre os +quais foi realizada a montagem, por favor monte manualmente o sistema de +arquivos subjacente para uma localização secundária. + +-- 24d8d4452573402496068381a6312df2 +Subject: Uma máquina virtual ou contêiner foi iniciado +Defined-By: systemd +Support: %SUPPORT_URL% + +A máquina virtual @NAME@ com seu PID @LEADER@ incial foi iniciada e está +pronto para ser usad. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: Uma máquina virtual ou contêiner foi terminado +Defined-By: systemd +Support: %SUPPORT_URL% + +A máquina virtual @NAME@ com seu PID @LEADER@ incial foi desligada. diff --git a/catalog/systemd.ru.catalog.in b/catalog/systemd.ru.catalog.in new file mode 100644 index 00000000..ccdc6850 --- /dev/null +++ b/catalog/systemd.ru.catalog.in @@ -0,0 +1,403 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Copyright © 2013-2017 Sergey Ptashnick + +# Message catalog for systemd's own messages +# Russian translation + +# Формат каталога сообщений описан по ссылке +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# Перед каждым элементом в комментарии указан Subject исходного +# сообщения (на английском). + +# Subject: The Journal has been started +-- f77379a8490b408bbe5f6940505a777b +Subject: Запущена служба журналирования +Defined-By: systemd +Support: %SUPPORT_URL% + +Процесс, отвечающий за журналирование системных событий, успешно запустился, +открыл для записи файлы журнала, и готов обрабатывать запросы. + +# Subject: The Journal has been stopped +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: Служба журналирования остановлена +Defined-By: systemd +Support: %SUPPORT_URL% + +Процесс, отвечающий за журналирование системных событий, завершил работу и +закрыл все свои файлы. + +# Subject: Disk space used by the journal +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: Место на диске, занятое журналом +Defined-By: systemd +Support: %SUPPORT_URL% + +@JOURNAL_NAME@ (@JOURNAL_PATH@) сейчас занимает @CURRENT_USE_PRETTY@. +Максимальный разрешенный размер составляет @MAX_USE_PRETTY@. +Оставляем свободными как минимум @DISK_KEEP_FREE_PRETTY@ (сейчас на диске +свободно @DISK_AVAILABLE_PRETTY@). +Таким образом, предел использования составляет @LIMIT_PRETTY@, из которых +@AVAILABLE_PRETTY@ пока свободно. + +Ограничения на размер журнала настраиваются при помощи параметров +SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, RuntimeMaxUse=, +RuntimeKeepFree=, RuntimeMaxFileSize= в файле /etc/systemd/journald.conf. +Более подробные сведения вы можете получить на справочной странице +journald.conf(5). + +# Subject: Messages from a service have been suppressed +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Часть сообщений от службы пропущена +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Служба отправила слишком много сообщений за короткий промежуток времени. +Часть сообщений была пропущена. + +Обратите внимание, что были пропущены сообщения только от этой службы, +сообщения других служб не затронуты. + +Предел, после которого служба журнала начинает игнорировать сообщения, +настраивается параметрами RateLimitIntervalSec= и RateLimitBurst= в файле +/etc/systemd/journald.conf. Подробности смотрите на странице руководства +journald.conf(5). + +# Subject: Journal messages have been missed +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Часть сообщений ядра пропущена +Defined-By: systemd +Support: %SUPPORT_URL% + +Часть сообщений, поступивших от ядра, была потеряна, так как служба +журналирования не успела их обработать. + +# Subject: Process @COREDUMP_PID@ (@COREDUMP_COMM@) dumped core +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Процесс @COREDUMP_PID@ (@COREDUMP_COMM@) сбросил дамп памяти +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Процесс @COREDUMP_PID@ (@COREDUMP_COMM@) завершился из-за критической ошибки. +Записан дамп памяти. + +Вероятно, это произошло из-за ошибки, допущенной в коде программы. +Рекомендуется сообщить её разработчикам о возникшей проблеме. + +# Subject: Core file was truncated to @SIZE_LIMIT@ bytes +-- 5aadd8e954dc4b1a8c954d63fd9e1137 +Subject: Файл с дампом памяти был урезан до @SIZE_LIMIT@ байт +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:coredump.conf(5) + +Объем памяти процесса превысил ограничения на размер дампа, установленные +для systemd-coredump(8). Записаны только первые @SIZE_LIMIT@ байт. Не исключено, +что этот дамп еще пригоден для анализа, хотя инструменты для анализа +дампов (например, gdb(1)) могут выдать предупреждение, что файл был урезан. + +# Subject: A new session @SESSION_ID@ has been created for user @USER_ID@ +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: Для пользователя @USER_ID@ создан новый сеанс @SESSION_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Для пользователя @USER_ID@ создан новый сеанс с идентификатором @SESSION_ID@. + +Главный процесс нового сеанса имеет индентификатор @LEADER@. + +# Subject: A session @SESSION_ID@ has been terminated +-- 3354939424b4456d9802ca8333ed424a +Subject: Сеанс @SESSION_ID@ завершен +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Сеанс с идентификатором @SESSION_ID@ завершился. + +# Subject: A new seat @SEAT_ID@ is now available +-- fcbefc5da23d428093f97c82a9290f7b +Subject: Добавлено новое рабочее место @SEAT_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Новое рабочее место (seat) @SEAT_ID@ полностью настроено и готово к +использованию. + +# Subject: A seat @SEAT_ID@ has now been removed +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Рабочее место @SEAT_ID@ отключено +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Рабочее место (seat) @SEAT_ID@ было отключено. + +# Subject: Time change +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Переведены системные часы +Defined-By: systemd +Support: %SUPPORT_URL% + +Системные часы были переведены. Сейчас они показывают @REALTIME@ микросекунд +с момента 00:00:00 1 января 1970 года. + +# Subject: Time zone change to @TIMEZONE@ +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Часовой пояс изменен на @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Системный часовой пояс был изменен. Новое значение: @TIMEZONE@. + +# Subject: System start-up is now complete +-- b07a249cd024414a82dd00cd181378ff +Subject: Запуск системы завершен +Defined-By: systemd +Support: %SUPPORT_URL% + +Все системные службы, запуск которых предписан настройками, были запущены. +Впрочем, это ещё не означает, что система в данный момент ничем не занята, +так как некоторые службы могут продолжать инициализацию даже после того, как +отчитались о своем запуске. + +Запуск ядра занял @KERNEL_USEC@ микросекунд. + +Процессы начального RAM-диска (initrd) отработали за @INITRD_USEC@ микросекунд. + +Запуск системных служб занял @USERSPACE_USEC@ микросекунд. + +# Subject: User manager start-up is now complete +-- eed00a68ffd84e31882105fd973abdd1 +Subject: Завершен запуск менеджера пользовательского сеанса +Defined-By: systemd +Support: %SUPPORT_URL% + +Менеджер пользовательского сеанса для пользователя с идентификатором @_UID@ +был запущен. Все службы, стоявшие в очереди на запуск, также были запущены. Тем +не менее, прочие службы могут все еще находиться в процессе запуска, либо могут +быть запущены позднее. + +Запуск менеджера занял @USERSPACE_USEC@ микросекунд. + +# Subject: System sleep state @SLEEP@ entered +-- 6bbd95ee977941e497c48be27c254128 +Subject: Система перешла в состояние сна (@SLEEP@) +Defined-By: systemd +Support: %SUPPORT_URL% + +Система была переведена в состояние сна (@SLEEP@). + +# Subject: System sleep state @SLEEP@ left +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: Система вышла из состояния сна (@SLEEP@) +Defined-By: systemd +Support: %SUPPORT_URL% + +Система была выведена из состояния сна (@SLEEP@). + +# Subject: System shutdown initiated +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Подготовка системы к выключению +Defined-By: systemd +Support: %SUPPORT_URL% + +Начат процесс подготовки к выключению компьютера. Останавливаются все системные +службы, отмонтируются все файловые системы. + +# Subject: Unit @UNIT@ has begun with start-up +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: Начинается запуск юнита @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Начат процесс запуска юнита @UNIT@. + +# Subject: Unit @UNIT@ has finished start-up +-- 39f53479d3a045ac8e11786248231fbf +Subject: Запуск юнита @UNIT@ завершен +Defined-By: systemd +Support: %SUPPORT_URL% + +Процесс запуска юнита @UNIT@ был завершен. + +Результат: @JOB_RESULT@. + +# Subject: Unit @UNIT@ has begun shutting down +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: Начинается остановка юнита @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Начат процесс остановки юнита @UNIT@. + +# Subject: Unit @UNIT@ has finished shutting down +-- 9d1aaa27d60140bd96365438aad20286 +Subject: Завершена остановка юнита @UNIT@. +Defined-By: systemd +Support: %SUPPORT_URL% + +Процесс остановки юнита @UNIT@ был завершен. + +# Subject: Unit @UNIT@ has failed +-- be02cf6855d2428ba40df7e9d022f03d +Subject: Ошибка юнита @UNIT@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Произошел сбой юнита @UNIT@. + +Результат: @JOB_RESULT@. + +# Subject: Unit @UNIT@ has begun with reloading its configuration +-- d34d037fff1847e6ae669a370e694725 +Subject: Юнит @UNIT@ начал перечитывать свои настройки +Defined-By: systemd +Support: %SUPPORT_URL% + +Юнит @UNIT@ начал процесс перечитывания своей конфигурации. + +# Subject: Unit @UNIT@ has finished reloading its configuration +-- 7b05ebc668384222baa8881179cfda54 +Subject: Юнит @UNIT@ завершил перечитывание своих настроек +Defined-By: systemd +Support: %SUPPORT_URL% + +Юнит @UNIT@ завершил процесс перечитывания своей конфигурации. + +Результат: @JOB_RESULT@. + +# Subject: Process @EXECUTABLE@ could not be executed +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Не удалось запустить процесс @EXECUTABLE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Сбой: не удалось запустить процесс @EXECUTABLE@. + +Код ошибки: @ERRNO@. + +# Subject: One or more messages could not be forwarded to syslog +-- 0027229ca0644181a76c4e92458afa2e +Subject: Часть сообщений не удалось передать процессу syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +Не удалось передать некоторые сообщения демону системного лога (syslog), +дублирующему работу службы системного журнала. Скорее всего, причина в том, что +используемая реализация syslog не успевает обрабатывать сообщения с достаточной +скоростью. + +# Subject: Mount point is not empty +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Каталог, являющийся точкой монтирования, не пуст +Defined-By: systemd +Support: %SUPPORT_URL% + +Каталог @WHERE@, который был указан в качестве точки монтирования (во втором +столбце файла /etc/fstab, либо в параметре Where= файла конфигурации юнита), +не является пустым. Это никак не мешает монтированию, однако ранее находившиеся +в нем файлы будут недоступны. Чтобы получить к ним доступ, вы можете вручную +перемонтировать эту файловую систему в другую точку. + +# Subject: A virtual machine or container has been started +-- 24d8d4452573402496068381a6312df2 +Subject: Запущена виртуальная машина/контейнер +Defined-By: systemd +Support: %SUPPORT_URL% + +Виртуальная машина @NAME@ (идентификатор главного процесса: @LEADER@) запущена и +готова к работе. + +# Subject: A virtual machine or container has been terminated +-- 58432bd3bace477cb514b56381b8a758 +Subject: Остановлена виртуальная машина/контейнер +Defined-By: systemd +Support: %SUPPORT_URL% + +Виртуальная машина @NAME@ (идентификатор главного процесса: @LEADER@) выключена. + +# Subject: DNSSEC mode has been turned off, as server doesn't support it +-- 36db2dfa5a9045e1bd4af5f93e1cf057 +Subject: Механизм DNSSEC был отключен, так как DNS-сервер его не поддерживает +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) resolved.conf(5) + +Служба разрешения имен хостов (systemd-resolved.service) определила, что +указанный в настойках DNS-сервер не поддерживает технологию DNSSEC, и +автоматически отключила DNSSEC-проверки. + +Данное событие возникает, если в файле resolved.conf указан параметр +DNSSEC=allow-downgrade, и вышестоящий DNS-сервер не поддерживает DNSSEC. +Обратите внимание, что режим allow-downgrade допускает возможность атаки +"DNSSEC downgrade", в ходе которой атакующий хакер блокирует проверки DNSSEC +путем отправки ложных сообщений от имени DNS-сервера. + +Возникновение данного события может свидетельствовать как о том, что ваш +DNS-сервер не поддерживает DNSSEC, так и о том, что некий хакер успешно провел +против вас атаку, направленную на блокировку DNSSEC-проверок. + +# Subject: DNSSEC validation failed +-- 1675d7f172174098b1108bf8c7dc8f5d +Subject: Проверка DNSSEC провалена +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +DNS-запрос или отдельная ресурсная запись не прошла проверку DNSSEC. +Как правило, это свидетельствует о постороннем вмешательстве в канал связи. + +# Subject: A DNSSEC trust anchor has been revoked +-- 4d4408cfd0d144859184d1e65d7c8a65 +Subject: Открытый ключ DNSSEC был отозван +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:systemd-resolved.service(8) + +Открытый ключ (trust ahcnor) DNSSEC был отозван. Необходимо настроить новый +открытый ключ, либо обновить систему, чтобы получить обновленный открытый ключ. + +# Subject: Automatic restarting of a unit has been scheduled +-- 5eb03494b6584870a536b337290809b3 +Subject: Назначен автоматический перезапуск юнита +Defined-By: systemd +Support: %SUPPORT_URL% + +Назначен автоматический перезапуск юнита @UNIT@, так как для него был задан +параметр Restart=. + +# Subject: Resources consumed by unit runtime +-- ae8f7b866b0347b9af31fe1c80b127c0 +Subject: Потребленные юнитом ресурсы +Defined-By: systemd +Support: %SUPPORT_URL% + +Юнит @UNIT@ завершен. Приводится статистика по потребленным им ресурсам. + +# Subject: The system is configured in a way that might cause problems +-- 50876a9db00f4c40bde1a2ad381c3a1b +Subject: Выявлены потенциальные проблемы в конфигурации системы +Defined-By: systemd +Support: %SUPPORT_URL% + +Перечень всех возможных меток, указывающих на проблемы конфигурации: +- "split-usr" — каталог /usr расположен на отдельной файловой системе, + которая не была смонтирована на момент запуска systemd +- "cgroups-missing" — ядро собрано без поддержки контрольных групп, либо + отсутствуют права для доступа к интерфейсным файлам контрольных групп +- "var-run-bad" — /var/run не является символьной ссылкой на /run +- "overflowuid-not-65534" — используемый ядром UID для "неизвестных" + пользователей (применяется в NFS и пространствах имен пользователей) + не равен 65534 +- "overflowgid-not-65534" — используемый ядром GID для "неизвестных" + пользователей (применяется в NFS и пространствах имен пользователей) + не равен 65534 + +В вашей системе присутствуют следующие проблемы: @TAINT@. diff --git a/catalog/systemd.sr.catalog.in b/catalog/systemd.sr.catalog.in new file mode 100644 index 00000000..7cb6546d --- /dev/null +++ b/catalog/systemd.sr.catalog.in @@ -0,0 +1,247 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +# Message catalog for systemd's own messages +# Serbian translation + +# Формат каталога је документован на +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# Да бисте видели зашто ово радимо, погледајте https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: Журнал је покренут +Defined-By: systemd +Support: %SUPPORT_URL% + +Системски журналски процес се покренуо, отворио журналске +датотеке за упис и спреман је за обраду захтева. + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: Журнал је заустављен +Defined-By: systemd +Support: %SUPPORT_URL% + +Системски журналски процес се зауставио и затворио све тренутно +отворене журналске датотеке. + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: Поруке од услуге су утишане +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +Услуга је уписала сувише порука за једно време. Поруке +од услуге су одбачене. + +Знајте да су само поруке од ове услуге одбачене, друге +услуге нису захваћене овим. + +Ограничења која подешавају начин на који се поруке одбацују се могу подесити +помоћу „RateLimitIntervalSec=“ и „RateLimitBurst=“ параметара унутар датотеке +/etc/systemd/journald.conf. Погледајте journald.conf(5) за појединости. + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: Журналске поруке су изгубљене +Defined-By: systemd +Support: %SUPPORT_URL% + +Поруке кернела су изгубљене јер журналски систем није могао да их +обради довољно брзо. + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: Процес @COREDUMP_PID@ (@COREDUMP_COMM@) је избацио своје језгро +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +Процес @COREDUMP_PID@ (@COREDUMP_COMM@) је пао и избацио своје језгро. + +Ово обично значи да постоји грешка у програму који је пао и ова +грешка треба да се пријави продавцу. + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: Нова сесија @SESSION_ID@ је направљена за корисника @USER_ID@ +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Нова сесија са ИБ-ом @SESSION_ID@ је направљена за корисника @USER_ID@. + +Водећи процес сесије је @LEADER@. + +-- 3354939424b4456d9802ca8333ed424a +Subject: Сесија @SESSION_ID@ је окончана +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Сесија са ИБ-ом @SESSION_ID@ је окончана. + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: Ново седиште @SEAT_ID@ је сада доступно +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Ново седиште @SEAT_ID@ је исподешавано и сада је доступно. + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: Седиште @SEAT_ID@ је сада уклоњено +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +Седиште @SEAT_ID@ је сада уклоњено и више није доступно. + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: Време је промењено +Defined-By: systemd +Support: %SUPPORT_URL% + +Системски сат је сада подешен на @REALTIME@ микросекунде након 1. јануара 1970. године. + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: Временска зона је промењена на @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +Временска зона је промењена на @TIMEZONE@. + +-- b07a249cd024414a82dd00cd181378ff +Subject: Подизање система је сада готово +Defined-By: systemd +Support: %SUPPORT_URL% + +Све системске услуге које су заказане за подизање су успешно покренуте. +Знајте да ово не значи да је машина сада беспослена јер услуге могу +и даље бити заузете завршавањем покретања система. + +Подизање кернела је трајало @KERNEL_USEC@ микросекунде. + +Подизање почетног РАМ диска је трајало @INITRD_USEC@ микросекунде. + +Подизање корисничких програма је трајало @USERSPACE_USEC@ микросекунде. + +-- 6bbd95ee977941e497c48be27c254128 +Subject: Системско стање спавања @SLEEP@ започето +Defined-By: systemd +Support: %SUPPORT_URL% + +Систем је сада ушао у @SLEEP@ стање спавања. + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: Системско стање спавања @SLEEP@ напуштено +Defined-By: systemd +Support: %SUPPORT_URL% + +Систем је изашао из @SLEEP@ стања спавања. + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: Гашење система започето +Defined-By: systemd +Support: %SUPPORT_URL% + +Систем-де гашење је започето. Гашење је сада почело и све +системске услуге су окончане и сви системи датотека откачени. + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: Јединица @UNIT@ је почела са покретањем +Defined-By: systemd +Support: %SUPPORT_URL% + +Јединица @UNIT@ је почела са покретањем. + +-- 39f53479d3a045ac8e11786248231fbf +Subject: Јединица @UNIT@ је завршила са покретањем +Defined-By: systemd +Support: %SUPPORT_URL% + +Јединица @UNIT@ је завршила са покретањем. + +Исход покретања је @JOB_RESULT@. + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: Јединица @UNIT@ је почела са гашењем +Defined-By: systemd +Support: %SUPPORT_URL% + +Јединица @UNIT@ је почела са гашењем. + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: Јединица @UNIT@ је завршила са гашењем +Defined-By: systemd +Support: %SUPPORT_URL% + +Јединица @UNIT@ је завршила са гашењем. + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: Јединица @UNIT@ је пукла +Defined-By: systemd +Support: %SUPPORT_URL% + +Јединица @UNIT@ је пукла. + +Исход је @JOB_RESULT@. + +-- d34d037fff1847e6ae669a370e694725 +Subject: Јединица @UNIT@ је почела са поновним учитавањем свог подешавања +Defined-By: systemd +Support: %SUPPORT_URL% + +Јединица @UNIT@ је почела са поновним учитавањем свог подешавања + +-- 7b05ebc668384222baa8881179cfda54 +Subject: Јединица @UNIT@ је завршила са поновним учитавањем свог подешавања +Defined-By: systemd +Support: %SUPPORT_URL% + +Јединица @UNIT@ је завршила са поновним учитавањем свог подешавања + +Исход је @JOB_RESULT@. + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: Процес @EXECUTABLE@ није могао бити извршен +Defined-By: systemd +Support: %SUPPORT_URL% + +Процес @EXECUTABLE@ није могао бити извршен и пукао је. + +Овај процес је вратио број грешке @ERRNO@. + +-- 0027229ca0644181a76c4e92458afa2e +Subject: Једна или више порука није могло бити прослеђено системском записнику +Defined-By: systemd +Support: %SUPPORT_URL% + +Једна или више порука није могло бити прослеђено „syslog“ услузи +која ради упоредно са журнал-деом. Ово обично значи да спроведена +„syslog“ услуга није могла да издржи брзину свих надолазећих +порука у реду. + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: Тачка качења није празна +Defined-By: systemd +Support: %SUPPORT_URL% + +Директоријум @WHERE@ је наведен као тачка качења (друго поље у +/etc/fstab датотеци или у „Where=“ пољу систем-де јединичне датотеке) +и он није празан. Ово не утиче на качење али ће већ постојеће датотеке у +овом директоријуму постати недоступне. Да бисте видели ове недоступне +датотеке, ручно прикачите основни систем датотека у другу +путању. + +-- 24d8d4452573402496068381a6312df2 +Subject: Виртуелна машина или контејнер је покренут(а) +Defined-By: systemd +Support: %SUPPORT_URL% + +Виртуелна машина @NAME@ са водећим ПИБ-ом @LEADER@ је +покренута и сада је спремна за коришћење. + +-- 58432bd3bace477cb514b56381b8a758 +Subject: Виртуелна машина или контејнер је окончан(а) +Defined-By: systemd +Support: %SUPPORT_URL% + +Виртуелна машина @NAME@ са водећим ПИБ-ом @LEADER@ је +угашена. diff --git a/catalog/systemd.zh_CN.catalog.in b/catalog/systemd.zh_CN.catalog.in new file mode 100644 index 00000000..d6ac2592 --- /dev/null +++ b/catalog/systemd.zh_CN.catalog.in @@ -0,0 +1,239 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Copyright © 2015 Boyuan Yang + +# Message catalog for systemd's own messages +# Simplified Chinese translation + +# 本 catalog 文档格式被记载在 +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# 如需了解我们为什么做这些工作,请见 https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: 日志已开始 +Defined-By: systemd +Support: %SUPPORT_URL% + +系统日志进程已启动,已打开供写入的日志文件并准备好处理请求。 + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: 日志已停止 +Defined-By: systemd +Support: %SUPPORT_URL% + +系统日志进程已终止,并已关闭所有当前活动的日志文件。 + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: 由某个服务而来的消息已被抑制 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +某个服务在一个时间周期内记录了太多消息。 +从该服务而来的消息已被丢弃。 + +请注意只有由有问题的服务传来的消息被丢弃, +其它服务的消息不受影响。 + +可以在 /etc/systemd/journald.conf 中设定 RateLimitIntervalSec= +以及 RateLimitBurst = 的值以控制丢弃信息的限制。 +请参见 journald.conf(5) 以了解详情。 + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: 日志消息已遗失 +Defined-By: systemd +Support: %SUPPORT_URL% + +因日志系统对内核消息的处理速度不够快, +部分信息已经遗失。 + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: 进程 @COREDUMP_PID@ (@COREDUMP_COMM@) 核心已转储 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +进程 @COREDUMP_PID@ (@COREDUMP_COMM@) 已崩溃并进行核心转储。 + +这通常意味着崩溃程序中存在编程错误,并应当将此错误向其开发者报告。 + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: 一个新会话 @SESSION_ID@ 已为用户 @USER_ID@ 建立 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +一个 ID 为 @SESSION_ID@ 的新会话已为用户 @USER_ID@ 建立。 + +该会话的首进程为 @LEADER@。 + +-- 3354939424b4456d9802ca8333ed424a +Subject: 会话 @SESSION_ID@ 已终止 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +一个 ID 为 @SESSION_ID@ 的会话已终止。 + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: 一个新的座位 @SEAT_ID@ 可用 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +一个新的座位 @SEAT_ID@ 已被配置并已可用。 + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: 座位 @SEAT_ID@ 已被移除 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +座位 @SEAT_ID@ 已被移除并不再可用。 + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: 时间已变更 +Defined-By: systemd +Support: %SUPPORT_URL% + +系统时钟已变更为1970年1月1日后 @REALTIME@ 微秒。 + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: 时区变更为 @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +系统时区已变更为 @TIMEZONE@。 + +-- b07a249cd024414a82dd00cd181378ff +Subject: 系统启动已完成 +Defined-By: systemd +Support: %SUPPORT_URL% + +所有系统启动时需要的系统服务均已成功启动。 +请注意这并不代表现在机器已经空闲,因为某些服务可能仍处于完成启动的过程中。 + +内核启动使用了 @KERNEL_USEC@ 毫秒。 + +初始内存盘启动使用了 @INITRD_USEC@ 毫秒。 + +用户空间启动使用了 @USERSPACE_USEC@ 毫秒。 + +-- 6bbd95ee977941e497c48be27c254128 +Subject: 系统已进入 @SLEEP@ 睡眠状态 +Defined-By: systemd +Support: %SUPPORT_URL% + +系统现已进入 @SLEEP@ 睡眠状态。 + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: 系统已离开 @SLEEP@ 睡眠状态 +Defined-By: systemd +Support: %SUPPORT_URL% + +系统现已离开 @SLEEP@ 睡眠状态。 + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: 系统关机已开始 +Defined-By: systemd +Support: %SUPPORT_URL% + +系统关机操作已初始化。 +关机已开始,所有系统服务均已结束,所有文件系统已卸载。 + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: @UNIT@ 单元已开始启动 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 单元已开始启动。 + +-- 39f53479d3a045ac8e11786248231fbf +Subject: @UNIT@ 单元已结束启动 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 单元已结束启动。 + +启动结果为“@JOB_RESULT@”。 + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: @UNIT@ 单元已开始停止操作 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 单元已开始停止操作。 + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: @UNIT@ 单元已结束停止操作 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 单元已结束停止操作。 + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: @UNIT@ 单元已失败 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 单元已失败。 + +结果为“@JOB_RESULT@”。 + +-- d34d037fff1847e6ae669a370e694725 +Subject: @UNIT@ 单元已开始重新载入其配置 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 单元已开始重新载入其配置。 + +-- 7b05ebc668384222baa8881179cfda54 +Subject: @UNIT@ 单元已结束配置重载入 +Defined-By: systemd +Support: %SUPPORT_URL% + +@UNIT@ 单元已结束配置重载入操作。 + +结果为“@JOB_RESULT@”。 + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: 进程 @EXECUTABLE@ 无法执行 +Defined-By: systemd +Support: %SUPPORT_URL% + +进程 @EXECUTABLE@ 无法被执行并已失败。 + +该进程返回的错误代码为 @ERRNO@。 + +-- 0027229ca0644181a76c4e92458afa2e +Subject: 一个或更多消息无法被转发至 syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +有一条或更多的消息无法被转发至与 journald 同时运行的 syslog 服务。 +这通常意味着 syslog 实现无法跟上队列中消息进入的速度。 + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: 挂载点不为空 +Defined-By: systemd +Support: %SUPPORT_URL% + +目录 @WHERE@ 被指定为挂载点(即 /etc/fstab 文件的第二栏,或 systemd 单元 +文件的 Where= 字段),且该目录非空。 +这并不会影响挂载行为,但该目录中先前已存在的文件将无法被访问。 +如需查看这些文件,请手动将其下的文件系统挂载到另一个位置。 + +-- 24d8d4452573402496068381a6312df2 +Subject: 一个虚拟机或容器已启动 +Defined-By: systemd +Support: %SUPPORT_URL% + +虚拟机 @NAME@,以及其首进程 PID @LEADER@,已被启动并可被使用。 + +-- 58432bd3bace477cb514b56381b8a758 +Subject: 一个虚拟机或容器已被终止 +Defined-By: systemd +Support: %SUPPORT_URL% + +虚拟机 @NAME@,以及其首进程 PID @LEADER@,已被关闭并停止。 diff --git a/catalog/systemd.zh_TW.catalog.in b/catalog/systemd.zh_TW.catalog.in new file mode 100644 index 00000000..a468c2f6 --- /dev/null +++ b/catalog/systemd.zh_TW.catalog.in @@ -0,0 +1,249 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Copyright © 2015 Jeff Huang + +# Message catalog for systemd's own messages +# Traditional Chinese translation + +# Catalog 的格式記錄於 +# https://www.freedesktop.org/wiki/Software/systemd/catalog + +# For an explanation why we do all this, see https://xkcd.com/1024/ + +-- f77379a8490b408bbe5f6940505a777b +Subject: 日誌已開始 +Defined-By: systemd +Support: %SUPPORT_URL% + +系統日誌行程已啟動,已開啟日誌 +檔案供寫入並準備好對行程的要求做出回應。 + +-- d93fb3c9c24d451a97cea615ce59c00b +Subject: 日誌已停止 +Defined-By: systemd +Support: %SUPPORT_URL% + +系統日誌行程已關閉,且關閉所有目前 +活躍的日誌檔案。 + +-- a596d6fe7bfa4994828e72309e95d61e +Subject: 從服務而來的訊息已被抑制 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:journald.conf(5) + +有一個服務在一個時間週期內記錄了太多訊息。 +從該服務而來的訊息已被丟棄。 + +注意,只有有問題的服務之訊息被丟棄, +其他服務的訊息則不受影響。 + +可以在 /etc/systemd/journald.conf 中設定 +RateLimitIntervalSec= 以及 RateLimitBurst= +來控制當訊息要開始被丟棄時的限制。參見 journald.conf(5) 以獲得更多資訊。 + +-- e9bf28e6e834481bb6f48f548ad13606 +Subject: 日誌訊息已遺失 +Defined-By: systemd +Support: %SUPPORT_URL% + +因日誌系統對核心訊息的處理不夠快速, +部份訊息已遺失。 + +-- fc2e22bc6ee647b6b90729ab34a250b1 +Subject: 行程 @COREDUMP_PID@ (@COREDUMP_COMM@) 核心傾印 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: man:core(5) + +行程 @COREDUMP_PID@ (@COREDUMP_COMM@) 當掉並核心傾印。 + +這通常代表了在當掉的程式中的一個程式錯誤 +並需要回報錯誤給其開發者。 + +-- 8d45620c1a4348dbb17410da57c60c66 +Subject: 新的工作階段 @SESSION_ID@ 已為使用者 @USER_ID@ 建立 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +一個新的工作階段,ID @SESSION_ID@ 已為使用者 @USER_ID@ 建立。 + +這個工作階段的領導行程為 @LEADER@。 + +-- 3354939424b4456d9802ca8333ed424a +Subject: 工作階段 @SESSION_ID@ 已結束 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +一個工作階段,ID @SESSION_ID@ 已結束。 + +-- fcbefc5da23d428093f97c82a9290f7b +Subject: 新的座位 @SEAT_ID@ 可用 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +一個新的座位 @SEAT_ID@ 已被設定且現在可用。 + +-- e7852bfe46784ed0accde04bc864c2d5 +Subject: 座位 @SEAT_ID@ 已被移除 +Defined-By: systemd +Support: %SUPPORT_URL% +Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat + +座位 @SEAT_ID@ 已被移除且不再可用。 + +-- c7a787079b354eaaa9e77b371893cd27 +Subject: 時間變更 +Defined-By: systemd +Support: %SUPPORT_URL% + +系統時間已變更為1970年1月1日後 @REALTIME@ 微秒。 + +-- 45f82f4aef7a4bbf942ce861d1f20990 +Subject: 時區變更為 @TIMEZONE@ +Defined-By: systemd +Support: %SUPPORT_URL% + +系統時區已變更為 @TIMEZONE@。 + +-- b07a249cd024414a82dd00cd181378ff +Subject: 系統啟動已完成 +Defined-By: systemd +Support: %SUPPORT_URL% + +所有開機所必要的系統服務都已成功啟動。 +注意這並不代表這臺機器有空閒的時間 +可以服務,可能仍忙於完成啟動。 + +核心啟動需要 @KERNEL_USEC@ 微秒。 + +初始 RAM 磁碟啟動需要 @INITRD_USEC@ 微秒。 + +使用者空間啟動需要 @USERSPACE_USEC@ 微秒。 + +-- 6bbd95ee977941e497c48be27c254128 +Subject: 系統進入 @SLEEP@ 睡眠狀態 +Defined-By: systemd +Support: %SUPPORT_URL% + +系統現在已進入 @SLEEP@ 睡眠狀態。 + +-- 8811e6df2a8e40f58a94cea26f8ebf14 +Subject: 系統離開 @SLEEP@ 睡眠狀態 +Defined-By: systemd +Support: %SUPPORT_URL% + +系統現在已離開 @SLEEP@ 睡眠狀態。 + +-- 98268866d1d54a499c4e98921d93bc40 +Subject: 系統關機開始 +Defined-By: systemd +Support: %SUPPORT_URL% + +Systemd 關閉已經開始。關閉已開始且所有系統服務 +都已結束,所有的檔案系統也都已被卸載。 + +-- 7d4958e842da4a758f6c1cdc7b36dcc5 +Subject: 單位 @UNIT@ 已開始啟動 +Defined-By: systemd +Support: %SUPPORT_URL% + +單位 @UNIT@ 已開始啟動。 + +-- 39f53479d3a045ac8e11786248231fbf +Subject: 單位 @UNIT@ 啟動已結束 +Defined-By: systemd +Support: %SUPPORT_URL% + +單位 @UNIT@ 啟動已結束。 + +啟動結果為 @JOB_RESULT@。 + +-- de5b426a63be47a7b6ac3eaac82e2f6f +Subject: 單位 @UNIT@ 已開始關閉 +Defined-By: systemd +Support: %SUPPORT_URL% + +單位 @UNIT@ 已開始關閉。 + +-- 9d1aaa27d60140bd96365438aad20286 +Subject: 單位 @UNIT@ 已關閉結束 +Defined-By: systemd +Support: %SUPPORT_URL% + +單位 @UNIT@ 已關閉結束。 + +-- be02cf6855d2428ba40df7e9d022f03d +Subject: 單位 @UNIT@ 已失敗 +Defined-By: systemd +Support: %SUPPORT_URL% + +單位 @UNIT@ 已失敗。 + +結果為 @JOB_RESULT@。 + +-- d34d037fff1847e6ae669a370e694725 +Subject: 單位 @UNIT@ 已開始重新載入其設定 +Defined-By: systemd +Support: %SUPPORT_URL% + +單位 @UNIT@ 已開始重新載入其設定 + +-- 7b05ebc668384222baa8881179cfda54 +Subject: 單位 @UNIT@ 已結束重新載入其設定 +Defined-By: systemd +Support: %SUPPORT_URL% + +單位 @UNIT@ 已結束重新載入其設定 + +結果為 @JOB_RESULT@。 + +-- 641257651c1b4ec9a8624d7a40a9e1e7 +Subject: 行程 @EXECUTABLE@ 無法執行 +Defined-By: systemd +Support: %SUPPORT_URL% + +行程 @EXECUTABLE@ 無法執行且失敗。 + +由該行程所回傳的錯誤碼為 @ERRNO@。 + +-- 0027229ca0644181a76c4e92458afa2e +Subject: 一個或更多訊息無法被轉發到 syslog +Defined-By: systemd +Support: %SUPPORT_URL% + +一個或更多訊息無法被轉發到 syslog 服務 +以及並行執行的 journald。這通常代表著 +syslog 實作並無未跟上佇列中訊息 +的速度。 + +-- 1dee0369c7fc4736b7099b38ecb46ee7 +Subject: 掛載點不為空 +Defined-By: systemd +Support: %SUPPORT_URL% + +目錄 @WHERE@ 被指定為掛載點(在 /etc/fstab 中的 +第二欄或是在 systemd 單位檔案中的 Where= 欄位)且其不為空。 +這並不會干擾掛載,但在此目錄中已存在的檔案 +會變成無法存取的狀態。要檢視這些 over-mounted 的檔案, +請手動掛載下面的檔案系統到次要 +位置。 + +-- 24d8d4452573402496068381a6312df2 +Subject: 虛擬機器或容器已啟動 +Defined-By: systemd +Support: %SUPPORT_URL% + +虛擬機器 @NAME@ 包含它的領導 PID @LEADER@ 現在 +已經開始並已經可以使用。 + +-- 58432bd3bace477cb514b56381b8a758 +Subject: 虛擬機器或容器已結束 +Defined-By: systemd +Support: %SUPPORT_URL% + +虛擬機器 @NAME@ 包含它的領導 PID @LEADER@ 已經 +關閉。 diff --git a/coccinelle/bool-cast.cocci b/coccinelle/bool-cast.cocci new file mode 100644 index 00000000..051ccb94 --- /dev/null +++ b/coccinelle/bool-cast.cocci @@ -0,0 +1,12 @@ +@@ +bool b; +expression y; +@@ +- b = !!(y); ++ b = y; +@@ +bool b; +expression y; +@@ +- b = !!y; ++ b = y; diff --git a/coccinelle/close-above-stdio.cocci b/coccinelle/close-above-stdio.cocci new file mode 100644 index 00000000..44b3b1c9 --- /dev/null +++ b/coccinelle/close-above-stdio.cocci @@ -0,0 +1,36 @@ +@@ +expression fd; +@@ +- if (fd > 2) +- safe_close(fd); ++ safe_close_above_stdio(fd); +@@ +expression fd; +@@ +- if (fd > 2) +- fd = safe_close(fd); ++ fd = safe_close_above_stdio(fd); +@@ +expression fd; +@@ +- if (fd >= 3) +- safe_close(fd); ++ safe_close_above_stdio(fd); +@@ +expression fd; +@@ +- if (fd >= 3) +- fd = safe_close(fd); ++ fd = safe_close_above_stdio(fd); +@@ +expression fd; +@@ +- if (fd > STDERR_FILENO) +- safe_close(fd); ++ safe_close_above_stdio(fd); +@@ +expression fd; +@@ +- if (fd > STDERR_FILENO) +- fd = safe_close(fd); ++ fd = safe_close_above_stdio(fd); diff --git a/coccinelle/cmp.cocci b/coccinelle/cmp.cocci new file mode 100644 index 00000000..a34cbe5b --- /dev/null +++ b/coccinelle/cmp.cocci @@ -0,0 +1,28 @@ +@@ +expression x, y; +@@ +- if (x < y) +- return -1; +- if (x > y) +- return 1; +- return 0; ++ return CMP(x, y); +@@ +expression x, y; +@@ +- if (x < y) +- return -1; +- else if (x > y) +- return 1; +- return 0; ++ return CMP(x, y); +@@ +expression x, y; +@@ +- if (x < y) +- return -1; +- else if (x > y) +- return 1; +- else +- return 0; ++ return CMP(x, y); diff --git a/coccinelle/const-strlen.disabled b/coccinelle/const-strlen.disabled new file mode 100644 index 00000000..30a6e5a8 --- /dev/null +++ b/coccinelle/const-strlen.disabled @@ -0,0 +1,14 @@ +@@ +constant s; +@@ +( +#define STRLEN +& +- sizeof(s)-1 ++ STRLEN(s) +) +@@ +constant s; +@@ +- strlen(s) ++ STRLEN(s) diff --git a/coccinelle/debug-logging.cocci b/coccinelle/debug-logging.cocci new file mode 100644 index 00000000..a679dab0 --- /dev/null +++ b/coccinelle/debug-logging.cocci @@ -0,0 +1,16 @@ +@@ +@@ +( +#define DEBUG_LOGGING +& +- _unlikely_(log_get_max_level() >= LOG_DEBUG) ++ DEBUG_LOGGING +) +@@ +@@ +( +#define DEBUG_LOGGING +& +- log_get_max_level() >= LOG_DEBUG ++ DEBUG_LOGGING +) diff --git a/coccinelle/div-round-up.cocci b/coccinelle/div-round-up.cocci new file mode 100644 index 00000000..a0c6df98 --- /dev/null +++ b/coccinelle/div-round-up.cocci @@ -0,0 +1,20 @@ +@@ +expression x, y; +@@ +- ((x + y - 1) / y) ++ DIV_ROUND_UP(x, y) +@@ +expression x, y; +@@ +- ((x + (y - 1)) / y) ++ DIV_ROUND_UP(x, y) +@@ +expression x, y; +@@ +- (x + y - 1) / y ++ DIV_ROUND_UP(x, y) +@@ +expression x, y; +@@ +- (x + (y - 1)) / y ++ DIV_ROUND_UP(x, y) diff --git a/coccinelle/dup-fcntl.cocci b/coccinelle/dup-fcntl.cocci new file mode 100644 index 00000000..8b133b3a --- /dev/null +++ b/coccinelle/dup-fcntl.cocci @@ -0,0 +1,7 @@ +@@ +/* We want to stick with dup() in test-fd-util.c */ +position p : script:python() { p[0].file != "src/test/test-fd-util.c" }; +expression fd; +@@ +- dup@p(fd) ++ fcntl(fd, F_DUPFD, 3) diff --git a/coccinelle/empty-or-dash.cocci b/coccinelle/empty-or-dash.cocci new file mode 100644 index 00000000..bebaead2 --- /dev/null +++ b/coccinelle/empty-or-dash.cocci @@ -0,0 +1,5 @@ +@@ +expression s; +@@ +- (isempty(s) || streq(s, "-")) ++ empty_or_dash(s) diff --git a/coccinelle/empty-or-root.cocci b/coccinelle/empty-or-root.cocci new file mode 100644 index 00000000..bf2f614d --- /dev/null +++ b/coccinelle/empty-or-root.cocci @@ -0,0 +1,10 @@ +@@ +expression s; +@@ +- (isempty(s) || path_equal(s, "/")) ++ empty_or_root(s) +@@ +expression s; +@@ +- (!isempty(s) && !path_equal(s, "/")) ++ !empty_or_root(s) diff --git a/coccinelle/empty-to-null.cocci b/coccinelle/empty-to-null.cocci new file mode 100644 index 00000000..bc6c656e --- /dev/null +++ b/coccinelle/empty-to-null.cocci @@ -0,0 +1,8 @@ +@@ +/* Avoid running this transformation on the empty_to_null function itself */ +position p : script:python() { p[0].current_element != "empty_to_null" }; +expression s; +@@ + +- isempty@p(s) ? NULL : s ++ empty_to_null(s) diff --git a/coccinelle/empty-to-root.cocci b/coccinelle/empty-to-root.cocci new file mode 100644 index 00000000..45627c98 --- /dev/null +++ b/coccinelle/empty-to-root.cocci @@ -0,0 +1,11 @@ +@@ +expression s; +@@ +- if (empty_or_root(s)) +- s = "/"; ++ s = empty_to_root(s); +@@ +expression s; +@@ +- (empty_or_root(s) ? "/" : s) ++ empty_to_root(s) diff --git a/coccinelle/enotsup.cocci b/coccinelle/enotsup.cocci new file mode 100644 index 00000000..c65734d3 --- /dev/null +++ b/coccinelle/enotsup.cocci @@ -0,0 +1,4 @@ +@@ +@@ +- ENOTSUP ++ EOPNOTSUPP diff --git a/coccinelle/equals-null.cocci b/coccinelle/equals-null.cocci new file mode 100644 index 00000000..957d828a --- /dev/null +++ b/coccinelle/equals-null.cocci @@ -0,0 +1,14 @@ +@@ +expression e; +statement s; +@@ +- if (e == NULL) ++ if (!e) +s +@@ +expression e; +statement s; +@@ +- if (e != NULL) ++ if (e) +s diff --git a/coccinelle/errno.cocci b/coccinelle/errno.cocci new file mode 100644 index 00000000..ed74c0a9 --- /dev/null +++ b/coccinelle/errno.cocci @@ -0,0 +1,32 @@ +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +local idexpression r; +expression e; +@@ +- r = -e; ++ r = + log_LEVEL_errno(e, ...); +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +local idexpression r; +expression e; +@@ ++ r = + log_LEVEL_errno(e, ...); +- r = -e; +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +local idexpression r; +expression e; +@@ +- r = ++ return + log_LEVEL_errno(e, ...); +- return r; +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +expression e; +@@ ++ return + log_LEVEL_errno(e, ...); +- return -e; diff --git a/coccinelle/exit-0.cocci b/coccinelle/exit-0.cocci new file mode 100644 index 00000000..8b816005 --- /dev/null +++ b/coccinelle/exit-0.cocci @@ -0,0 +1,16 @@ +@@ +@@ +- exit(0); ++ exit(EXIT_SUCCESS); +@@ +@@ +- _exit(0); ++ _exit(EXIT_SUCCESS); +@@ +@@ +- exit(1); ++ exit(EXIT_FAILURE); +@@ +@@ +- _exit(1); ++ _exit(EXIT_FAILURE); diff --git a/coccinelle/flags-set.cocci b/coccinelle/flags-set.cocci new file mode 100644 index 00000000..73966b02 --- /dev/null +++ b/coccinelle/flags-set.cocci @@ -0,0 +1,16 @@ +@@ +/* Disable this transformation for the securebits-util.h, as it makes + * the expression there confusing. */ +position p : script:python() { p[0].file != "src/shared/securebits-util.h" }; +expression x, y; +@@ +( +- ((x@p) & (y)) == (y) ++ FLAGS_SET(x, y) +| +- (x@p & (y)) == (y) ++ FLAGS_SET(x, y) +| +- ((x@p) & y) == y ++ FLAGS_SET(x, y) +) diff --git a/coccinelle/fopen-unlocked.cocci b/coccinelle/fopen-unlocked.cocci new file mode 100644 index 00000000..7870f8cc --- /dev/null +++ b/coccinelle/fopen-unlocked.cocci @@ -0,0 +1,71 @@ +@@ +expression f, path, options; +@@ +- f = fopen(path, options); +- if (!f) +- return -errno; +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); ++ r = fopen_unlocked(path, options, &f); ++ if (r < 0) ++ return r; +@@ +expression f, path, options; +@@ +- f = fopen(path, options); +- if (!f) { +- if (errno == ENOENT) +- return -ESRCH; +- return -errno; +- } +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); ++ r = fopen_unlocked(path, options, &f); ++ if (r == -ENOENT) ++ return -ESRCH; ++ if (r < 0) ++ return r; +@@ +expression f, path, options; +@@ +- f = fopen(path, options); +- if (!f) +- return errno == ENOENT ? -ESRCH : -errno; +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); ++ r = fopen_unlocked(path, options, &f); ++ if (r == -ENOENT) ++ return -ESRCH; ++ if (r < 0) ++ return r; +@@ +expression f, path, p; +@@ + r = fopen_temporary(path, &f, &p); + if (r < 0) + return ...; +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); +@@ +expression f, g, path, p; +@@ + r = fopen_temporary_label(path, g, &f, &p); + if (r < 0) + return ...; +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); +@@ +expression f, fd, options; +@@ +- f = fdopen(fd, options); ++ r = fdopen_unlocked(fd, options, &f); ++ if (r < 0) { +- if (!f) { + ... +- return -errno; ++ return r; + } +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); +@@ +expression f, buf, sz; +@@ +- f = open_memstream(&buf, &sz); ++ f = open_memstream_unlocked(&buf, &sz); + if (!f) + return ...; +- (void) __fsetlocking(f, FSETLOCKING_BYCALLER); diff --git a/coccinelle/free_and_replace.cocci b/coccinelle/free_and_replace.cocci new file mode 100644 index 00000000..9dcdbf4d --- /dev/null +++ b/coccinelle/free_and_replace.cocci @@ -0,0 +1,15 @@ +@@ +expression p, q; +@@ +- free(p); +- p = q; +- q = NULL; +- return 0; ++ return free_and_replace(p, q); +@@ +expression p, q; +@@ +- free(p); +- p = q; +- q = NULL; ++ free_and_replace(p, q); diff --git a/coccinelle/hashmap_free.cocci b/coccinelle/hashmap_free.cocci new file mode 100644 index 00000000..86b95424 --- /dev/null +++ b/coccinelle/hashmap_free.cocci @@ -0,0 +1,54 @@ +@@ +expression p; +@@ +- set_free(p); +- p = NULL; ++ p = set_free(p); +@@ +expression p; +@@ +- if (p) +- set_free(p); +- p = NULL; ++ p = set_free(p); +@@ +expression p; +@@ +- if (p) { +- set_free(p); +- p = NULL; +- } ++ p = set_free(p); +@@ +expression p; +@@ +- if (p) +- set_free(p); ++ set_free(p); +@@ +expression p; +@@ +- hashmap_free(p); +- p = NULL; ++ p = hashmap_free(p); +@@ +expression p; +@@ +- if (p) +- hashmap_free(p); +- p = NULL; ++ p = hashmap_free(p); +@@ +expression p; +@@ +- if (p) { +- hashmap_free(p); +- p = NULL; +- } ++ p = hashmap_free(p); +@@ +expression p; +@@ +- if (p) +- hashmap_free(p); ++ hashmap_free(p); diff --git a/coccinelle/htonl.cocci b/coccinelle/htonl.cocci new file mode 100644 index 00000000..4e69bb70 --- /dev/null +++ b/coccinelle/htonl.cocci @@ -0,0 +1,20 @@ +@@ +expression s; +@@ +- htonl(s) ++ htobe32(s) +@@ +expression s; +@@ +- htons(s) ++ htobe16(s) +@@ +expression s; +@@ +- ntohl(s) ++ be32toh(s) +@@ +expression s; +@@ +- ntohs(s) ++ be16toh(s) diff --git a/coccinelle/in_set.cocci b/coccinelle/in_set.cocci new file mode 100644 index 00000000..2c9b94ce --- /dev/null +++ b/coccinelle/in_set.cocci @@ -0,0 +1,37 @@ +@@ +expression e; +/* Exclude JsonVariant * from the transformation, as it can't work with the + * current version of the IN_SET macro */ +typedef JsonVariant; +type T != JsonVariant*; +constant T n0, n1, n2, n3, n4, n5, n6, n7, n8, n9; +@@ + +( +- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7 || e == n8 || e == n9 ++ IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9) +| +- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7 || e == n8 ++ IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8) +| +- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 || e == n7 ++ IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7) +| +- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 || e == n6 ++ IN_SET(e, n0, n1, n2, n3, n4, n5, n6) +| +- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 || e == n5 ++ IN_SET(e, n0, n1, n2, n3, n4, n5) +| +- e == n0 || e == n1 || e == n2 || e == n3 || e == n4 ++ IN_SET(e, n0, n1, n2, n3, n4) +| +- e == n0 || e == n1 || e == n2 || e == n3 ++ IN_SET(e, n0, n1, n2, n3) +| +- e == n0 || e == n1 || e == n2 ++ IN_SET(e, n0, n1, n2) +| +- e == n0 || e == n1 ++ IN_SET(e, n0, n1) +) diff --git a/coccinelle/iovec-make.cocci b/coccinelle/iovec-make.cocci new file mode 100644 index 00000000..7a0d4ced --- /dev/null +++ b/coccinelle/iovec-make.cocci @@ -0,0 +1,29 @@ +@@ +expression x, y, p, l; +@@ +- x[y].iov_base = p; +- x[y].iov_len = l; +- y++; ++ x[y++] = IOVEC_MAKE(p, l); +@@ +expression x, p, l; +@@ +- x.iov_base = p; +- x.iov_len = l; ++ x = IOVEC_MAKE(p, l); +@@ +expression x, p, l; +@@ +- x->iov_base = p; +- x->iov_len = l; ++ *x = IOVEC_MAKE(p, l); +@@ +expression s; +@@ +- IOVEC_MAKE(s, strlen(s)); ++ IOVEC_MAKE_STRING(s); +@@ +expression x, y, z; +@@ +- x = (struct iovec) { .iov_base = y, .iov_len = z }; ++ x = IOVEC_MAKE(y, z); diff --git a/coccinelle/isempty.cocci b/coccinelle/isempty.cocci new file mode 100644 index 00000000..e0a9f07c --- /dev/null +++ b/coccinelle/isempty.cocci @@ -0,0 +1,42 @@ +@@ +/* Disable this transformation for the test-string-util.c */ +position p : script:python() { p[0].file != "src/test/test-string-util.c" }; +expression s; +@@ +( +- strv_length@p(s) == 0 ++ strv_isempty(s) +| +- strv_length@p(s) <= 0 ++ strv_isempty(s) +| +- strv_length@p(s) > 0 ++ !strv_isempty(s) +| +- strv_length@p(s) != 0 ++ !strv_isempty(s) +| +- strlen@p(s) == 0 ++ isempty(s) +| +- strlen@p(s) <= 0 ++ isempty(s) +| +- strlen@p(s) > 0 ++ !isempty(s) +| +- strlen@p(s) != 0 ++ !isempty(s) +| +- strlen_ptr@p(s) == 0 ++ isempty(s) +| +- strlen_ptr@p(s) <= 0 ++ isempty(s) +| +- strlen_ptr@p(s) > 0 ++ !isempty(s) +| +- strlen_ptr@p(s) != 0 ++ !isempty(s) +) diff --git a/coccinelle/log-json.cocci b/coccinelle/log-json.cocci new file mode 100644 index 00000000..3730fd6e --- /dev/null +++ b/coccinelle/log-json.cocci @@ -0,0 +1,8 @@ +@@ +expression e, v, flags; +expression list args; +@@ ++ return +- json_log(v, flags, 0, args); ++ json_log(v, flags, SYNTHETIC_ERRNO(e), args); +- return -e; diff --git a/coccinelle/malloc_multiply.cocci b/coccinelle/malloc_multiply.cocci new file mode 100644 index 00000000..3284edf7 --- /dev/null +++ b/coccinelle/malloc_multiply.cocci @@ -0,0 +1,20 @@ +@@ +expression q, n, m; +@@ +- q = malloc((n)*(m)) ++ q = malloc_multiply(n, m) +@@ +expression q, n, m; +@@ +- q = malloc(n*(m)) ++ q = malloc_multiply(n, m) +@@ +expression q, n, m; +@@ +- q = malloc((n)*m) ++ q = malloc_multiply(n, m) +@@ +expression q, n, m; +@@ +- q = malloc(n*m) ++ q = malloc_multiply(n, m) diff --git a/coccinelle/memzero.cocci b/coccinelle/memzero.cocci new file mode 100644 index 00000000..8198cc84 --- /dev/null +++ b/coccinelle/memzero.cocci @@ -0,0 +1,38 @@ +@@ +expression s; +@@ +- memset(&s, 0, sizeof(s)) ++ zero(s) +@@ +expression s; +@@ +- memset(s, 0, sizeof(*s)) ++ zero(*s) +@@ +expression s; +@@ +- bzero(&s, sizeof(s)) ++ zero(s) +@@ +expression s; +@@ +- bzero(s, sizeof(*s)) ++ zero(*s) +@@ +expression a, b; +@@ +( +#define memzero +& +- memset(a, 0, b) ++ memzero(a, b) +) +@@ +expression a, b; +@@ +( +#define memzero +& +- bzero(a, b) ++ memzero(a, b) +) diff --git a/coccinelle/mfree.cocci b/coccinelle/mfree.cocci new file mode 100644 index 00000000..1389cd35 --- /dev/null +++ b/coccinelle/mfree.cocci @@ -0,0 +1,6 @@ +@@ +expression p; +@@ +- free(p); +- p = NULL; ++ p = mfree(p); diff --git a/coccinelle/mfree_return.cocci b/coccinelle/mfree_return.cocci new file mode 100644 index 00000000..15e6c7d5 --- /dev/null +++ b/coccinelle/mfree_return.cocci @@ -0,0 +1,8 @@ +@@ +/* Avoid running this transformation on the mfree function itself */ +position p : script:python() { p[0].current_element != "mfree" }; +expression e; +@@ +- free@p(e); +- return NULL; ++ return mfree(e); diff --git a/coccinelle/no-if-assignments.cocci b/coccinelle/no-if-assignments.cocci new file mode 100644 index 00000000..9f63e903 --- /dev/null +++ b/coccinelle/no-if-assignments.cocci @@ -0,0 +1,20 @@ +@@ +expression p, q; +identifier r; +statement s; +@@ +- if ((r = q) < p) +- s ++ r = q; ++ if (r < p) ++ s +@@ +expression p, q; +identifier r; +statement s; +@@ +- if ((r = q) >= p) +- s ++ r = q; ++ if (r >= p) ++ s diff --git a/coccinelle/not_in_set.cocci b/coccinelle/not_in_set.cocci new file mode 100644 index 00000000..aed2c349 --- /dev/null +++ b/coccinelle/not_in_set.cocci @@ -0,0 +1,34 @@ +@@ +expression e; +typedef JsonVariant; +type T != JsonVariant*; +constant T n0, n1, n2, n3, n4, n5, n6, n7, n8, n9; +@@ +( +- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 && e != n9 ++ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9) +| +- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 && e != n8 ++ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7, n8) +| +- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 && e != n7 ++ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6, n7) +| +- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 && e != n6 ++ !IN_SET(e, n0, n1, n2, n3, n4, n5, n6) +| +- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 && e != n5 ++ !IN_SET(e, n0, n1, n2, n3, n4, n5) +| +- e != n0 && e != n1 && e != n2 && e != n3 && e != n4 ++ !IN_SET(e, n0, n1, n2, n3, n4) +| +- e != n0 && e != n1 && e != n2 && e != n3 ++ !IN_SET(e, n0, n1, n2, n3) +| +- e != n0 && e != n1 && e != n2 ++ !IN_SET(e, n0, n1, n2) +| +- e != n0 && e != n1 ++ !IN_SET(e, n0, n1) +) diff --git a/coccinelle/o-ndelay.cocci b/coccinelle/o-ndelay.cocci new file mode 100644 index 00000000..669424a0 --- /dev/null +++ b/coccinelle/o-ndelay.cocci @@ -0,0 +1,4 @@ +@@ +@@ +- O_NDELAY ++ O_NONBLOCK diff --git a/coccinelle/reallocarray.cocci b/coccinelle/reallocarray.cocci new file mode 100644 index 00000000..21fe9dfb --- /dev/null +++ b/coccinelle/reallocarray.cocci @@ -0,0 +1,20 @@ +@@ +expression q, p, n, m; +@@ +- q = realloc(p, (n)*(m)) ++ q = reallocarray(p, n, m) +@@ +expression q, p, n, m; +@@ +- q = realloc(p, n*(m)) ++ q = reallocarray(p, n, m) +@@ +expression q, p, n, m; +@@ +- q = realloc(p, (n)*m) ++ q = reallocarray(p, n, m) +@@ +expression q, p, n, m; +@@ +- q = realloc(p, n*m) ++ q = reallocarray(p, n, m) diff --git a/coccinelle/redundant-if.cocci b/coccinelle/redundant-if.cocci new file mode 100644 index 00000000..515e36e1 --- /dev/null +++ b/coccinelle/redundant-if.cocci @@ -0,0 +1,54 @@ +@@ +expression r; +@@ +- if (r < 0) +- return r; +- if (r == 0) +- return 0; ++ if (r <= 0) ++ return r; +@@ +expression r; +@@ +- if (r == 0) +- return 0; +- if (r < 0) +- return r; ++ if (r <= 0) ++ return r; +@@ +expression r; +@@ +- if (r < 0) +- return r; +- if (r == 0) +- return r; ++ if (r <= 0) ++ return r; +@@ +expression r; +@@ +- if (r == 0) +- return r; +- if (r < 0) +- return r; ++ if (r <= 0) ++ return r; +@@ +expression r; +@@ +- if (r < 0) +- return r; +- if (r > 0) +- return r; ++ if (r != 0) ++ return r; +@@ +expression r; +@@ +- if (r > 0) +- return r; +- if (r < 0) +- return r; ++ if (r != 0) ++ return r; diff --git a/coccinelle/run-coccinelle.sh b/coccinelle/run-coccinelle.sh new file mode 100755 index 00000000..be80a76a --- /dev/null +++ b/coccinelle/run-coccinelle.sh @@ -0,0 +1,43 @@ +#!/bin/bash -e + +# Exclude following paths from the Coccinelle transformations +EXCLUDED_PATHS=( + "src/boot/efi/*" + "src/shared/linux/*" + "src/basic/linux/*" + # Symlinked to test-bus-vtable-cc.cc, which causes issues with the IN_SET macro + "src/libsystemd/sd-bus/test-bus-vtable.c" +) + +top="$(git rev-parse --show-toplevel)" +iso_defs="$top/coccinelle/systemd-definitions.iso" +args= + +# Create an array from files tracked by git... +mapfile -t files < <(git ls-files ':/*.[ch]') +# ...and filter everything that matches patterns from EXCLUDED_PATHS +for excl in "${EXCLUDED_PATHS[@]}"; do + files=(${files[@]//$excl}) +done + +case "$1" in + -i) + args="$args --in-place" + shift + ;; +esac + +if ! parallel -h >/dev/null; then + echo 'Please install GNU parallel (package "parallel")' + exit 1 +fi + +for SCRIPT in ${@-$top/coccinelle/*.cocci} ; do + echo "--x-- Processing $SCRIPT --x--" + TMPFILE=`mktemp` + echo "+ spatch --sp-file $SCRIPT $args ..." + parallel --halt now,fail=1 --keep-order --noswap --max-args=20 \ + spatch --iso-file $iso_defs --sp-file $SCRIPT $args ::: "${files[@]}" \ + 2>"$TMPFILE" || cat "$TMPFILE" + echo -e "--x-- Processed $SCRIPT --x--\n" +done diff --git a/coccinelle/safe_close-no-if.cocci b/coccinelle/safe_close-no-if.cocci new file mode 100644 index 00000000..81c56785 --- /dev/null +++ b/coccinelle/safe_close-no-if.cocci @@ -0,0 +1,7 @@ +@@ +expression fd; +@@ +- if (fd >= 0) { +- fd = safe_close(fd); +- } ++ fd = safe_close(fd); diff --git a/coccinelle/safe_close.cocci b/coccinelle/safe_close.cocci new file mode 100644 index 00000000..6fedd804 --- /dev/null +++ b/coccinelle/safe_close.cocci @@ -0,0 +1,18 @@ +@@ +expression fd; +@@ +- close(fd); +- fd = -1; ++ fd = safe_close(fd); +@@ +expression fd; +@@ +- close_nointr(fd); +- fd = -1; ++ fd = safe_close(fd); +@@ +expression fd; +@@ +- safe_close(fd); +- fd = -1; ++ fd = safe_close(fd); diff --git a/coccinelle/safe_closedir.cocci b/coccinelle/safe_closedir.cocci new file mode 100644 index 00000000..743ffd97 --- /dev/null +++ b/coccinelle/safe_closedir.cocci @@ -0,0 +1,27 @@ +@@ +expression p; +@@ +- if (p) { +- closedir(p); +- p = NULL; +- } ++ p = safe_closedir(p); +@@ +expression p; +@@ +- if (p) +- closedir(p); +- p = NULL; ++ p = safe_closedir(p); +@@ +expression p; +@@ +- closedir(p); +- p = NULL; ++ p = safe_closedir(p); +@@ +expression p; +@@ +- if (p) +- closedir(p); ++ safe_closedir(p); diff --git a/coccinelle/safe_fclose.cocci b/coccinelle/safe_fclose.cocci new file mode 100644 index 00000000..6961cd01 --- /dev/null +++ b/coccinelle/safe_fclose.cocci @@ -0,0 +1,27 @@ +@@ +expression p; +@@ +- if (p) { +- fclose(p); +- p = NULL; +- } ++ p = safe_fclose(p); +@@ +expression p; +@@ +- if (p) +- fclose(p); +- p = NULL; ++ p = safe_fclose(p); +@@ +expression p; +@@ +- fclose(p); +- p = NULL; ++ p = safe_fclose(p); +@@ +expression p; +@@ +- if (p) +- fclose(p); ++ safe_fclose(p); diff --git a/coccinelle/sd_event_source_disable_unref.cocci b/coccinelle/sd_event_source_disable_unref.cocci new file mode 100644 index 00000000..2763fefa --- /dev/null +++ b/coccinelle/sd_event_source_disable_unref.cocci @@ -0,0 +1,36 @@ +@@ +expression p; +@@ +- if (p) { +- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF); +- p = sd_event_source_unref(p); +- } ++ p = sd_event_source_disable_unref(p); +@@ +expression p; +@@ +- if (p) { +- sd_event_source_set_enabled(p, SD_EVENT_OFF); +- sd_event_source_unref(p); +- } ++ sd_event_source_disable_unref(p); +@@ +expression p; +@@ +- if (p) { +- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF); +- sd_event_source_unref(p); +- } ++ sd_event_source_disable_unref(p); +@@ +expression p; +@@ +- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF); +- sd_event_source_unref(p); ++ sd_event_source_disable_unref(p); +@@ +expression p; +@@ +- sd_event_source_set_enabled(p, SD_EVENT_OFF); +- sd_event_source_unref(p); ++ sd_event_source_disable_unref(p); diff --git a/coccinelle/strempty.cocci b/coccinelle/strempty.cocci new file mode 100644 index 00000000..7901da36 --- /dev/null +++ b/coccinelle/strempty.cocci @@ -0,0 +1,60 @@ +@@ +/* Avoid running this transformation on the strempty function itself */ +position p : script:python() { p[0].current_element != "strempty" }; +expression s; +@@ +( +- s@p ?: "" ++ strempty(s) +| +- s@p ? s : "" ++ strempty(s) +) + +@@ +position p : script:python() { p[0].current_element != "strempty" }; +expression s; +@@ +- if (!s@p) +- s = ""; ++ s = strempty(s); + +@@ +position p : script:python() { p[0].current_element != "strnull" }; +expression s; +@@ +( +- s@p ?: "(null)" ++ strnull(s) +| +- s@p ? s : "(null)" ++ strnull(s) +) + +@@ +position p : script:python() { p[0].current_element != "strnull" }; +expression s; +@@ +- if (!s@p) +- s = "(null)"; ++ s = strnull(s); + +@@ +position p : script:python() { p[0].current_element != "strna" }; +expression s; +@@ +( +- s@p ?: "n/a" ++ strna(s) +| +- s@p ? s : "n/a" ++ strna(s) +) + +@@ +position p : script:python() { p[0].current_element != "strna" }; +expression s; +@@ +- if (!s@p) +- s = "n/a"; ++ s = strna(s); diff --git a/coccinelle/strjoin.cocci b/coccinelle/strjoin.cocci new file mode 100644 index 00000000..675760e3 --- /dev/null +++ b/coccinelle/strjoin.cocci @@ -0,0 +1,16 @@ +@@ +expression list args; +@@ +- strjoin(args, NULL); ++ strjoin(args); +@@ +expression t; +expression list args; +@@ +- t = strjoin(args, NULL); ++ t = strjoin(args); +@@ +expression list args; +@@ +- return strjoin(args, NULL); ++ return strjoin(args); diff --git a/coccinelle/strjoina.cocci b/coccinelle/strjoina.cocci new file mode 100644 index 00000000..a6236eb0 --- /dev/null +++ b/coccinelle/strjoina.cocci @@ -0,0 +1,6 @@ +@@ +expression n, m; +expression list s; +@@ +- n = strjoina(m, s, NULL); ++ n = strjoina(m, s); diff --git a/coccinelle/strv_free.cocci b/coccinelle/strv_free.cocci new file mode 100644 index 00000000..0ad56f77 --- /dev/null +++ b/coccinelle/strv_free.cocci @@ -0,0 +1,27 @@ +@@ +expression p; +@@ +- strv_free(p); +- p = NULL; ++ p = strv_free(p); +@@ +expression p; +@@ +- if (p) +- strv_free(p); +- p = NULL; ++ p = strv_free(p); +@@ +expression p; +@@ +- if (p) { +- strv_free(p); +- p = NULL; +- } ++ p = strv_free(p); +@@ +expression p; +@@ +- if (p) +- strv_free(p); ++ strv_free(p); diff --git a/coccinelle/swap-two.cocci b/coccinelle/swap-two.cocci new file mode 100644 index 00000000..edf7d324 --- /dev/null +++ b/coccinelle/swap-two.cocci @@ -0,0 +1,7 @@ +@@ +expression x, y, z; +@@ +- z = x; +- x = y; +- y = z; ++ SWAP_TWO(x, y); diff --git a/coccinelle/synthetic-errno.cocci b/coccinelle/synthetic-errno.cocci new file mode 100644 index 00000000..3ddb69cb --- /dev/null +++ b/coccinelle/synthetic-errno.cocci @@ -0,0 +1,48 @@ +@@ +expression e; +expression list args; +@@ +( +/* Ignore one specific case in src/shared/bootspec.c where we want to stick + * with the log_debug() + return pattern */ +log_debug("Found no default boot entry :("); +| +- log_debug(args); +- return -e; ++ return log_debug_errno(SYNTHETIC_ERRNO(e), args); +) +@@ +expression e; +expression list args; +@@ +- log_info(args); +- return -e; ++ return log_info_errno(SYNTHETIC_ERRNO(e), args); +@@ +expression e; +expression list args; +@@ +- log_notice(args); +- return -e; ++ return log_notice_errno(SYNTHETIC_ERRNO(e), args); +@@ +expression e; +expression list args; +@@ +- log_error(args); +- return -e; ++ return log_error_errno(SYNTHETIC_ERRNO(e), args); +@@ +expression e; +expression list args; +@@ +- log_emergency(args); +- return -e; ++ return log_emergency_errno(SYNTHETIC_ERRNO(e), args); +@@ +identifier log_LEVEL_errno =~ "^log_(debug|info|notice|warning|error|emergency)_errno$"; +identifier ERRNO =~ "^E[A-Z]+$"; +expression list args; +@@ +- return log_LEVEL_errno(ERRNO, args); ++ return log_LEVEL_errno(SYNTHETIC_ERRNO(ERRNO), args); diff --git a/coccinelle/systemd-definitions.iso b/coccinelle/systemd-definitions.iso new file mode 100644 index 00000000..92db763a --- /dev/null +++ b/coccinelle/systemd-definitions.iso @@ -0,0 +1,20 @@ +/* Statement isomorphisms - replace explicit checks against NULL with a + * shorter variant, which relies on C's downgrade-to-bool feature. + * The expression metavariables should be declared as pointers, however, + * that doesn't work well with complex expressions like: + * if (UNIT(p)->default_dependencies != NULL) + */ + +Statement +@@ +expression X; +statement S; +@@ +if (X == NULL) S => if (!X) S + +Statement +@@ +expression X; +statement S; +@@ +if (X != NULL) S => if (X) S diff --git a/coccinelle/take-fd.cocci b/coccinelle/take-fd.cocci new file mode 100644 index 00000000..f7124e78 --- /dev/null +++ b/coccinelle/take-fd.cocci @@ -0,0 +1,21 @@ +@@ +local idexpression p; +expression q; +@@ +- p = q; +- q = -1; +- return p; ++ return TAKE_FD(q); + +/* The ideal solution would use 'local idexpression' to avoid matching errno, + * which is a global variable. However, 'idexpression' nor 'identifier' + * would match, for example, "x->fd", which is considered 'expression' in + * the SmPL grammar + */ +@@ +expression p != errno; +expression q; +@@ +- p = q; +- q = -1; ++ p = TAKE_FD(q); diff --git a/coccinelle/take-ptr.cocci b/coccinelle/take-ptr.cocci new file mode 100644 index 00000000..0cebe815 --- /dev/null +++ b/coccinelle/take-ptr.cocci @@ -0,0 +1,14 @@ +@@ +local idexpression p; +expression q; +@@ +- p = q; +- q = NULL; +- return p; ++ return TAKE_PTR(q); +@@ +expression p, q; +@@ +- p = q; +- q = NULL; ++ p = TAKE_PTR(q); diff --git a/coccinelle/while-true.cocci b/coccinelle/while-true.cocci new file mode 100644 index 00000000..c23fb11f --- /dev/null +++ b/coccinelle/while-true.cocci @@ -0,0 +1,12 @@ +@@ +statement s; +@@ +- while (true) ++ for (;;) +s +@@ +statement s; +@@ +- while (1) ++ for (;;) +s diff --git a/coccinelle/xsprintf.cocci b/coccinelle/xsprintf.cocci new file mode 100644 index 00000000..401216ad --- /dev/null +++ b/coccinelle/xsprintf.cocci @@ -0,0 +1,6 @@ +@@ +expression e, fmt; +expression list vaargs; +@@ +- snprintf(e, sizeof(e), fmt, vaargs); ++ xsprintf(e, fmt, vaargs); diff --git a/configure b/configure new file mode 100755 index 00000000..a9db8a1c --- /dev/null +++ b/configure @@ -0,0 +1,21 @@ +#!/bin/bash -e + +cflags=CFLAGS="$CFLAGS" +cxxflags=CXXFLAGS="$CXXFLAGS" +declare -a args +j=0 +for i in "$@"; do + case "$i" in + CFLAGS=*) + cflags="$i";; + CXXFLAGS=*) + cxxflags="$i";; + *) + args[$j]="$i" + j=$((j+1)) + esac +done + +export "$cflags" "$cxxflags" +set -x +exec meson build "${args[@]}" diff --git a/docs/AUTOMATIC_BOOT_ASSESSMENT.md b/docs/AUTOMATIC_BOOT_ASSESSMENT.md new file mode 100644 index 00000000..1ef4bdcf --- /dev/null +++ b/docs/AUTOMATIC_BOOT_ASSESSMENT.md @@ -0,0 +1,207 @@ +--- +title: Automatic Boot Assessment +--- + +# Automatic Boot Assessment + +systemd provides support for automatically reverting back to the previous +version of the OS or kernel in case the system consistently fails to boot. This +support is built into various of its components. When used together these +components provide a complete solution on UEFI systems, built as add-on to the +[Boot Loader +Specification](https://systemd.io/BOOT_LOADER_SPECIFICATION). However, the +different components may also be used independently, and in combination with +other software, to implement similar schemes, for example with other boot +loaders or for non-UEFI systems. Here's a brief overview of the complete set of +components: + +* The + [`systemd-boot(7)`](https://www.freedesktop.org/software/systemd/man/systemd-boot.html) + boot loader optionally maintains a per-boot-loader-entry counter that is + decreased by one on each attempt to boot the entry, prioritizing entries that + have non-zero counters over those which already reached a counter of zero + when choosing the entry to boot. + +* The + [`systemd-bless-boot.service(8)`](https://www.freedesktop.org/software/systemd/man/systemd-bless-boot.service.html) + service automatically marks a boot loader entry, for which boot counting as + mentioned above is enabled, as "good" when a boot has been determined to be + successful, thus turning off boot counting for it. + +* The + [`systemd-bless-boot-generator(8)`](https://www.freedesktop.org/software/systemd/man/systemd-bless-boot-generator.html) + generator automatically pulls in `systemd-bless-boot.service` when use of + `systemd-boot` with boot counting enabled is detected. + +* The + [`systemd-boot-check-no-failures.service(8)`](https://www.freedesktop.org/software/systemd/man/systemd-boot-check-no-failures.service.html) + service is a simple health check tool that determines whether the boot + completed successfully. When enabled it becomes an indirect dependency of + `systemd-bless-boot.service` (by means of `boot-complete.target`, see + below), ensuring that the boot will not be considered successful if there are + any failed services. + +* The `boot-complete.target` target unit (see + [`systemd.special(7)`](https://www.freedesktop.org/software/systemd/man/systemd.special.html)) + serves as a generic extension point both for units that shall be considered + necessary to consider a boot successful on one side (example: + `systemd-boot-check-no-failures.service` as described above), and units that + want to act only if the boot is successful on the other (example: + `systemd-bless-boot.service` as described above). + +* The + [`kernel-install(8)`](https://www.freedesktop.org/software/systemd/man/kernel-install.html) + script can optionally create boot loader entries that carry an initial boot + counter (the initial counter is configurable in `/etc/kernel/tries`). + +# Details + +The boot counting data `systemd-boot` and `systemd-bless-boot.service` +manage is stored in the name of the boot loader entries. If a boot loader entry +file name contains `+` followed by one or two numbers (if two numbers, then +those need to be separated by `-`) right before the `.conf` suffix, then boot +counting is enabled for it. The first number is the "tries left" counter +encoding how many attempts to boot this entry shall still be made. The second +number is the "tries done" counter, encoding how many failed attempts to boot +it have already been made. Each time a boot loader entry marked this way is +booted the first counter is decreased by one, and the second one increased by +one. (If the second counter is missing, then it is assumed to be equivalent to +zero.) If the "tries left" counter is above zero the entry is still considered +for booting (the entry's state is considered to be "indeterminate"), as soon as +it reached zero the entry is not tried anymore (entry state "bad"). If the boot +attempt completed successfully the entry's counters are removed from the name +(entry state "good"), thus turning off boot counting for the future. + +## Walkthrough + +Here's an example walkthrough of how this all fits together. + +1. The user runs `echo 3 > /etc/kernel/tries` to enable boot counting. + +2. A new kernel is installed. `kernel-install` is used to generate a new boot + loader entry file for it. Let's say the version string for the new kernel is + `4.14.11-300.fc27.x86_64`, a new boot loader entry + `/boot/loader/entries/4.14.11-300.fc27.x86_64+3.conf` is hence created. + +3. The system is booted for the first time after the new kernel is + installed. The boot loader now sees the `+3` counter in the entry file + name. It hence renames the file to `4.14.11-300.fc27.x86_64+2-1.conf` + indicating that at this point one attempt has started and thus only one less + is left. After the rename completed the entry is booted as usual. + +4. Let's say this attempt to boot fails. On the following boot the boot loader + will hence see the `+2-1` tag in the name, and hence rename the entry file to + `4.14.11-300.fc27.x86_64+1-2.conf`, and boot it. + +5. Let's say the boot fails again. On the subsequent boot the loader hence will + see the `+1-2` tag, and rename the file to + `4.14.11-300.fc27.x86_64+0-3.conf` and boot it. + +6. If this boot also fails, on the next boot the boot loader will see the + tag `+0-3`, i.e. the counter reached zero. At this point the entry will be + considered "bad", and ordered to the end of the list of entries. The next + newest boot entry is now tried, i.e. the system automatically reverted back + to an earlier version. + +The above describes the walkthrough when the selected boot entry continuously +fails. Let's have a look at an alternative ending to this walkthrough. In this +scenario the first 4 steps are the same as above: + +1. *as above* + +2. *as above* + +3. *as above* + +4. *as above* + +5. Let's say the second boot succeeds. The kernel initializes properly, systemd + is started and invokes all generators. + +6. One of the generators started is `systemd-bless-boot-generator` which + detects that boot counting is used. It hence pulls + `systemd-bless-boot.service` into the initial transaction. + +7. `systemd-bless-boot.service` is ordered after and `Requires=` the generic + `boot-complete.target` unit. This unit is hence also pulled into the initial + transaction. + +8. The `boot-complete.target` unit is ordered after and pulls in various units + that are required to succeed for the boot process to be considered + successful. One such unit is `systemd-boot-check-no-failures.service`. + +9. `systemd-boot-check-no-failures.service` is run after all its own + dependencies completed, and assesses that the boot completed + successfully. It hence exits cleanly. + +10. This allows `boot-complete.target` to be reached. This signifies to the + system that this boot attempt shall be considered successful. + +11. Which in turn permits `systemd-bless-boot.service` to run. It now + determines which boot loader entry file was used to boot the system, and + renames it dropping the counter tag. Thus + `4.14.11-300.fc27.x86_64+1-2.conf` is renamed to + `4.14.11-300.fc27.x86_64.conf`. From this moment boot counting is turned + off. + +12. On the following boot (and all subsequent boots after that) the entry is + now seen with boot counting turned off, no further renaming takes place. + +# How to adapt this scheme to other setups + +Of the stack described above many components may be replaced or augmented. Here +are a couple of recommendations. + +1. To support alternative boot loaders in place of `systemd-boot` two scenarios + are recommended: + + a. Boot loaders already implementing the Boot Loader Specification can simply + implement an equivalent file rename based logic, and thus integrate fully + with the rest of the stack. + + b. Boot loaders that want to implement boot counting and store the counters + elsewhere can provide their own replacements for + `systemd-bless-boot.service` and `systemd-bless-boot-generator`, but should + continue to use `boot-complete.target` and thus support any services + ordered before that. + +2. To support additional components that shall succeed before the boot is + considered successful, simply place them in units (if they aren't already) + and order them before the generic `boot-complete.target` target unit, + combined with `Requires=` dependencies from the target, so that the target + cannot be reached when any of the units fail. You may add any number of + units like this, and only if they all succeed the boot entry is marked as + good. Note that the target unit shall pull in these boot checking units, not + the other way around. + +3. To support additional components that shall only run on boot success, simply + wrap them in a unit and order them after `boot-complete.target`, pulling it + in. + +# FAQ + +1. *Why do you use file renames to store the counter? Why not a regular file?* + — Mainly two reasons: it's relatively likely that renames can be implemented + atomically even in simpler file systems, while writing to file contents has + a much bigger chance to be result in incomplete or corrupt data, as renaming + generally avoids allocating or releasing data blocks. Moreover it has the + benefit that the boot count metadata is directly attached to the boot loader + entry file, and thus the lifecycle of the metadata and the entry itself are + bound together. This means no additional clean-up needs to take place to + drop the boot loader counting information for an entry when it is removed. + +2. *Why not use EFI variables for storing the boot counter?* — The memory chips + used to back the persistent EFI variables are generally not of the highest + quality, hence shouldn't be written to more than necessary. This means we + can't really use it for changes made regularly during boot, but can use it + only for seldom made configuration changes. + +3. *I have a service which — when it fails — should immediately cause a + reboot. How does that fit in with the above?* — Well, that's orthogonal to + the above, please use `FailureAction=` in the unit file for this. + +4. *Under some condition I want to mark the current boot loader entry as bad + right-away, so that it never is tried again, how do I do that?* — You may + invoke `/usr/lib/systemd/systemd-bless-boot bad` at any time to mark the + current boot loader entry as "bad" right-away so that it isn't tried again + on later boots. diff --git a/docs/BLOCK_DEVICE_LOCKING.md b/docs/BLOCK_DEVICE_LOCKING.md new file mode 100644 index 00000000..5509b419 --- /dev/null +++ b/docs/BLOCK_DEVICE_LOCKING.md @@ -0,0 +1,67 @@ +--- +title: Locking Block Device Access +--- + +# Locking Block Device Access + +*TL;DR: Use BSD file locks +[(`flock(2)`)](http://man7.org/linux/man-pages/man2/flock.2.html) on block +device nodes to synchronize access for partitioning and file system formatting +tools.* + +`systemd-udevd` probes all block devices showing up for file system superblock +and partition table information (utilizing `libblkid`). If another program +concurrently modifies a superblock or partition table this probing might be +affected, which is bad in itself, but also might in turn result in undesired +effects in programs subscribing to `udev` events. + +Applications manipulating a block device can temporarily stop `systemd-udevd` +from processing rules on it — and thus bar it from probing the device — by +taking a BSD file lock on the block device node. Specifically, whenever +`systemd-udevd` starts processing a block device it takes a `LOCK_SH|LOCK_NB` +lock using [`flock(2)`](http://man7.org/linux/man-pages/man2/flock.2.html) on +the main block device (i.e. never on any partition block device, but on the +device the partition belongs to). If this lock cannot be taken (i.e. `flock()` +returns `EBUSY`), it refrains from processing the device. If it manages to take +the lock it is kept for the entire time the device is processed. + +Note that `systemd-udevd` also watches all block device nodes it manages for +`inotify()` `IN_CLOSE` events: whenever such an event is seen, this is used as +trigger to re-run the rule-set for the device. + +These two concepts allow tools such as disk partitioners or file system +formatting tools to safely and easily take exclusive ownership of a block +device while operating: before starting work on the block device, they should +take an `LOCK_EX` lock on it. This has two effects: first of all, in case +`systemd-udevd` is still processing the device the tool will wait for it to +finish. Second, after the lock is taken, it can be sure that +`systemd-udevd` will refrain from processing the block device, and thus all +other client applications subscribed to it won't get device notifications from +potentially half-written data either. After the operation is complete the +partitioner/formatter can simply close the device node. This has two effects: +it implicitly releases the lock, so that `systemd-udevd` can process events on +the device node again. Secondly, it results an `IN_CLOSE` event, which causes +`systemd-udevd` to immediately re-process the device — seeing all changes the +tool made — and notify subscribed clients about it. + +Besides synchronizing block device access between `systemd-udevd` and such +tools this scheme may also be used to synchronize access between those tools +themselves. However, do note that `flock()` locks are advisory only. This means +if one tool honours this scheme and another tool does not, they will of course +not be synchronized properly, and might interfere with each other's work. + +Note that the file locks follow the usual access semantics of BSD locks: since +`systemd-udevd` never writes to such block devices it only takes a `LOCK_SH` +*shared* lock. A program intending to make changes to the block device should +take a `LOCK_EX` *exclusive* lock instead. For further details, see the +`flock(2)` man page. + +And please keep in mind: BSD file locks (`flock()`) and POSIX file locks +(`lockf()`, `F_SETLK`, …) are different concepts, and in their effect +orthogonal. The scheme discussed above uses the former and not the latter, +because these types of locks more closely match the required semantics. + +Summarizing: it is recommended to take `LOCK_EX` BSD file locks when +manipulating block devices in all tools that change file system block devices +(`mkfs`, `fsck`, …) or partition tables (`fdisk`, `parted`, …), right after +opening the node. diff --git a/docs/BOOT_LOADER_INTERFACE.md b/docs/BOOT_LOADER_INTERFACE.md new file mode 100644 index 00000000..c0ed0998 --- /dev/null +++ b/docs/BOOT_LOADER_INTERFACE.md @@ -0,0 +1,142 @@ +--- +title: The Boot Loader Interface +--- + +# The Boot Loader Interface + +systemd can interface with the boot loader to receive performance data and +other information, and pass control information. This is only supported on EFI +systems. Data is transferred between the boot loader and systemd in EFI +variables. All EFI variables use the vendor UUID +`4a67b082-0a4c-41cf-b6c7-440b29bb8c4f`. + +* The EFI Variable `LoaderTimeInitUSec` contains the timestamp in microseconds + when the loader was initialized. This value is the time spent in the firmware + for initialization, it is formatted as numeric, NUL-terminated, decimal + string, in UTF-16. + +* The EFI Variable `LoaderTimeExecUSec` contains the timestamp in microseconds + when the loader finished its work and is about to execute the kernel. The + time spent in the loader is the difference between `LoaderTimeExecUSec` and + `LoaderTimeInitUSec`. This value is formatted the same way as + `LoaderTimeInitUSec`. + +* The EFI variable `LoaderDevicePartUUID` contains the partition GUID of the + ESP the boot loader was run from formatted as NUL-terminated UTF16 string, in + normal GUID syntax. + +* The EFI variable `LoaderConfigTimeout` contains the boot menu timeout + currently in use. It may be modified both by the boot loader and by the + host. The value should be formatted as numeric, NUL-terminated, decimal + string, in UTF-16. The time is specified in µs. + +* Similarly, the EFI variable `LoaderConfigTimeoutOneShot` contains a boot menu + timeout for a single following boot. It is set by the OS in order to request + display of the boot menu on the following boot. When set overrides + `LoaderConfigTimeout`. It is removed automatically after being read by the + boot loader, to ensure it only takes effect a single time. This value is + formatted the same way as `LoaderConfigTimeout`. If set to `0` the boot menu + timeout is turned off, and the menu is shown indefinitely. + +* The EFI variable `LoaderEntries` may contain a series of boot loader entry + identifiers, one after the other, each individually NUL terminated. This may + be used to let the OS know which boot menu entries were discovered by the + boot loader. A boot loader entry identifier should be a short, non-empty + alphanumeric string (possibly containing `-`, too). The list should be in the + order the entries are shown on screen during boot. See below regarding a + recommended vocabulary for boot loader entry identifiers. + +* The EFI variable `LoaderEntryDefault` contains the default boot loader entry + to use. It contains a NUL-terminated boot loader entry identifier. + +* Similarly, the EFI variable `LoaderEntryOneShot` contains the default boot + loader entry to use for a single following boot. It is set by the OS in order + to request booting into a specific menu entry on the following boot. When set + overrides `LoaderEntryDefault`. It is removed automatically after being read + by the boot loader, to ensure it only takes effect a single time. This value + is formatted the same way as `LoaderEntryDefault`. + +* The EFI variable `LoaderEntrySelected` contains the boot loader entry + identifier that was booted. It is set by the boot loader and read by + the OS in order to identify which entry has been used for the current boot. + +* The EFI variable `LoaderFeatures` contains a 64bit unsigned integer with a + number of flags bits that are set by the boot loader and passed to the OS and + indicate the features the boot loader supports. Specifically, the following + bits are defined: + + * `1 << 0` → The boot loader honours `LoaderConfigTimeout` when set. + * `1 << 1` → The boot loader honours `LoaderConfigTimeoutOneShot` when set. + * `1 << 2` → The boot loader honours `LoaderEntryDefault` when set. + * `1 << 3` → The boot loader honours `LoaderEntryOneShot` when set. + * `1 << 4` → The boot loader supports boot counting as described in [Automatic Boot Assessment](https://systemd.io/AUTOMATIC_BOOT_ASSESSMENT). + * `1 << 5` → The boot loader supports looking for boot menu entries in the Extended Boot Loader Partition. + * `1 << 6` → The boot loader supports passing a random seed to the OS. + +* The EFI variable `LoaderRandomSeed` contains a binary random seed if set. It + is set by the boot loader to pass an entropy seed read from the ESP partition + to the OS. The system manager then credits this seed to the kernel's entropy + pool. It is the responsibility of the boot loader to ensure the quality and + integrity of the random seed. + +* The EFI variable `LoaderSystemToken` contains binary random data, + persistently set by the OS installer. Boot loaders that support passing + random seeds to the OS should use this data and combine it with the random + seed file read from the ESP. By combining this random data with the random + seed read off the disk before generating a seed to pass to the OS and a new + seed to store in the ESP the boot loader can protect itself from situations + where "golden" OS images that include a random seed are replicated and used + on multiple systems. Since the EFI variable storage is usually independent + (i.e. in physical NVRAM) of the ESP file system storage, and only the latter + is part of "golden" OS images, this ensures that different systems still come + up with different random seeds. Note that the `LoaderSystemToken` is + generally only written once, by the OS installer, and is usually not touched + after that. + +If `LoaderTimeInitUSec` and `LoaderTimeExecUSec` are set, `systemd-analyze` +will include them in its boot-time analysis. If `LoaderDevicePartUUID` is set, +systemd will mount the ESP that was used for the boot to `/boot`, but only if +that directory is empty, and only if no other file systems are mounted +there. The `systemctl reboot --boot-loader-entry=…` and `systemctl reboot +--boot-loader-menu=…` commands rely on the `LoaderFeatures` , +`LoaderConfigTimeoutOneShot`, `LoaderEntries`, `LoaderEntryOneShot` +variables. `LoaderRandomSeed` is read by PID during early boot and credited to +the kernel's random pool. + +## Boot Loader Entry Identifiers + +While boot loader entries may be named relatively freely, it's highly +recommended to follow the following rules when picking identifiers for the +entries, so that programs (and users) can derive basic context and meaning from +the identifiers as passed in `LoaderEntries`, `LoaderEntryDefault`, +`LoaderEntryOneShot`, `LoaderEntrySelected`, and possibly show nicely localized +names for them in UIs. + +1. When boot loader entries are defined through [Boot Loader + Specification](https://systemd.io/BOOT_LOADER_SPECIFICATION) drop-in files + the identifier should be derived directly from the drop-in snippet name, but + with the `.conf` (or `.efi` in case of Type #2 entries) suffix removed. + +2. Entries automatically discovered by the boot loader (as opposed to being + configured in configuration files) should generally have an identifier + prefixed with `auto-`. + +3. Boot menu entries referring to Microsoft Windows installations should either + use the identifier `windows` or use the `windows-` prefix for the + identifier. If a menu entry is automatically discovered, it should be + prefixed with `auto-`, see above (Example: this means an automatically + discovered Windows installation might have the identifier `auto-windows` or + `auto-windows-10` or so.). + +4. Similar, boot menu entries referring to Apple MacOS X installations should + use the identifier `osx` or one that is prefixed with `osx-`. If such an + entry is automatically discovered by the boot loader use `auto-osx` as + identifier, or `auto-osx-` as prefix for the identifier, see above. + +5. If a boot menu entry encapsulates the EFI shell program, it should use the + identifier `efi-shell` (or when automatically discovered: `auto-efi-shell`, + see above). + +6. If a boot menu entry encapsulates a reboot into EFI firmware setup feature, + it should use the identifier `reboot-to-firmware-setup` (or + `auto-reboot-to-firmware-setup` in case it is automatically discovered). diff --git a/docs/BOOT_LOADER_SPECIFICATION.md b/docs/BOOT_LOADER_SPECIFICATION.md new file mode 100644 index 00000000..3bd300c2 --- /dev/null +++ b/docs/BOOT_LOADER_SPECIFICATION.md @@ -0,0 +1,222 @@ +--- +title: The Boot Loader Specification +--- + +# The Boot Loader Specification + +_TL;DR: Currently there's no common boot scheme across architectures and +platforms for open-source operating systems. There's also little cooperation +between multiple distributions in dual-boot (or triple, … multi-boot) +setups. We'd like to improve this situation by getting everybody to commit to a +single boot configuration format that is based on drop-in files, and thus is +robust, simple, works without rewriting configuration files and is free of +namespace clashes._ + +The Boot Loader Specification defines a scheme how different operating systems +can cooperatively manage a boot loader configuration directory, that accepts +drop-in files for boot menu items that are defined in a format that is shared +between various boot loader implementations, operating systems, and userspace +programs. The same scheme can be used to prepare OS media for cases where the +firmware includes a boot loader. The target audience for this specification is: + +* Boot loader developers, to write a boot loader that directly reads its configuration at runtime from these drop-in snippets +* Firmware developers, to add generic boot loading support directly to the firmware itself +* Distribution and Core OS developers, in order to create these snippets at OS/kernel package installation time +* UI developers, for implementing a user interface that discovers the available boot options +* OS Installer developers, to prepare their installation media and for setting up the initial drop-in directory + +## Why is there a need for this specification? + +Of course, without this specification things already work mostly fine. But here's why we think this specification is needed: + +* To make the boot more robust, as no explicit rewriting of configuration files is required any more +* To allow an out of the box boot experience on any platform without the need of traditional firmware mechanisms (e.g. BIOS calls, UEFI Boot Services) +* To improve dual-boot scenarios. Currently, multiple Linux installations tend to fight over which boot loader becomes the primary one in possession of the MBR, and only that one installation can then update the boot loader configuration of it freely. Other Linux installs have to be manually configured to never touch the MBR and instead install a chain-loaded boot loader in their own partition headers. In this new scheme as all installations share a loader directory no manual configuration has to take place, and all participants implicitly cooperate due to removal of name collisions and can install/remove their own boot menu entries at free will, without interfering with the entries of other installed operating systems. +* Drop-in directories are otherwise now pretty ubiquitous on Linux as an easy way to extend configuration without having to edit, regenerate or manipulate configuration files. For the sake of uniformity, we should do the same for extending the boot menu. +* Userspace code can sanely parse boot loader configuration which is essential with modern BIOSes which do not necessarily initialize USB keyboards anymore during boot, which makes boot menus hard to reach for the user. If userspace code can parse the boot loader configuration, too, this allows for UIs that can select a boot menu item to boot into, before rebooting the machine, thus not requiring interactivity during early boot. +* To unify and thus simplify configuration of the various boot loaders around, which makes configuration of the boot loading process easier for users, administrators and developers alike. +* For boot loaders with configuration _scripts_ such as grub2, adopting this spec allows for mostly static scripts that are generated only once at first installation, but then do not need to be updated anymore as that is done via drop-in files exclusively. + +## Why not simply rely on the EFI boot menu logic? + +EFI is not ubiquitous, especially not in embedded systems. If you have an EFI +system, it provides a boot options logic that can offer similar +functionality. Here's why we think that it is not enough for our uses: + +* The various EFI implementations implement the boot order/boot item logic to different levels. Some firmware implementations do not offer a boot menu at all and instead unconditionally follow the EFI boot order, booting the first item that is working. +* If the firmware setup is used to reset all data usually all EFI boot entries are lost, making the system entirely unbootable, as the firmware setups generally do not offer a UI to define additional boot items. By placing the menu item information on disk, it is always available, regardless if the BIOS setup data is lost. +* Harddisk images should be moveable between machines and be bootable without requiring explicit EFI variables to be set. This also requires that the list of boot options is defined on disk, and not in EFI variables alone. +* EFI is not universal yet (especially on non-x86 platforms), this specification is useful both for EFI and non-EFI boot loaders. +* Many EFI systems disable USB support during early boot to optimize boot times, thus making keyboard input unavailable in the EFI menu. It is thus useful if the OS UI has a standardized way to discover available boot options which can be booted to. + +## Technical Details + +Everything described below is located on a placeholder file system `$BOOT`. The installer program should pick `$BOOT` according to the following rules: + +* On disks with MBR disk labels + * If the OS is installed on a disk with MBR disk label, and a partition with the MBR type id of 0xEA already exists it should be used as `$BOOT`. + * Otherwise, if the OS is installed on a disk with MBR disk label, a new partition with MBR type id of 0xEA shall be created, of a suitable size (let's say 500MB), and it should be used as `$BOOT`. +* On disks with GPT disk labels + * If the OS is installed on a disk with GPT disk label, and a partition with the GPT type GUID of `bc13c2ff-59e6-4262-a352-b275fd6f7172` already exists, it should be used as `$BOOT`. + * Otherwise, if the OS is installed on a disk with GPT disk label, and an ESP partition (i.e. with the GPT type UID of `c12a7328-f81f-11d2-ba4b-00a0c93ec93b`) already exists and is large enough (let's say 250MB`) and otherwise qualifies, it should be used as `$BOOT`. + * Otherwise, if the OS is installed on a disk with GPT disk label, and if the ESP partition already exists but is too small, a new suitably sized (let's say 500MB) partition with GPT type GUID of `bc13c2ff-59e6-4262-a352-b275fd6f7172` shall be created and it should be used as `$BOOT`. + * Otherwise, if the OS is installed on a disk with GPT disk label, and no ESP partition exists yet, a new suitably sized (let's say 500MB) ESP should be created and should be used as `$BOOT`. + +This placeholder file system shall be determined during _installation time_, and an fstab entry may be created. It should be mounted to either `/boot/` or `/efi/`. Additional locations like `/boot/efi/`, with `/boot/` being a separate file system, might be supported by implementations. This is not recommended because the mounting of `$BOOT` is then dependent on and requires the mounting of the intermediate file system. + +**Note:** _`$BOOT` should be considered **shared** among all OS installations of a system. Instead of maintaining one `$BOOT` per installed OS (as `/boot/` was traditionally handled), all installed OS share the same place to drop in their boot-time configuration._ + +For systems where the firmware is able to read file systems directly, `$BOOT` +must be a file system readable by the firmware. For other systems and generic +installation and live media, `$BOOT` must be a VFAT (16 or 32) file +system. Applications accessing `$BOOT` should hence not assume that fancier +file system features such as symlinks, hardlinks, access control or case +sensitivity are supported. + +This specification defines two types of boot loader entries. The first type is +text based, very simple and suitable for a variety of firmware, architecture +and image types ("Type #1"). The second type is specific to EFI, but allows +single-file images that embed all metadata in the kernel binary itself, which +is useful to cryptographically sign them as one file for the purpose of +SecureBoot ("Type #2"). + +Not all boot loader entries will apply to all systems. For example, Type #1 +entries that use the `efi` key and all Type #2 entries only apply to EFI +systems. Entries using the `architecture` key might specify an architecture that +doesn't match the local one. Boot loaders should ignore all entries that don't +match the local platform and what the boot loader can support, and hide them +from the user. Only entries matching the feature set of boot loader and system +shall be considered and displayed. This allows image builders to put together +images that transparently support multiple different architectures. + +### Type #1 Boot Loader Specification Entries + +We define two directories below `$BOOT`: + +* `$BOOT/loader/` is the directory containing all files needed for Type #1 entries +* `$BOOT/loader/entries/` is the directory containing the drop-in snippets. This directory contains one `.conf` file for each boot menu item. + +**Note:** _In all cases the `/loader/` directory should be located directly in the root of the file system. Specifically, if `$BOOT` is the ESP, then `/loader/` directory should be located directly in the root directory of the ESP, and not in the `/EFI/` subdirectory._ + +Inside the `$BOOT/loader/entries/` directory each OS vendor may drop one or more configuration snippets with the suffix ".conf", one for each boot menu item. The file name of the file is used for identification of the boot item but shall never be presented to the user in the UI. The file name may be chosen freely but should be unique enough to avoid clashes between OS installations. More specifically it is suggested to include the machine ID (`/etc/machine-id` or the D-Bus machine ID for OSes that lack `/etc/machine-id`), the kernel version (as returned by `uname -r`) and an OS identifier (The ID field of `/etc/os-release`). Example: `$BOOT/loader/entries/6a9857a393724b7a981ebb5b8495b9ea-3.8.0-2.fc19.x86_64.conf`. + +These configuration snippets shall be Unix-style text files (i.e. line separation with a single newline character), in the UTF-8 encoding. The configuration snippets are loosely inspired on Grub1's configuration syntax. Lines beginning with '#' shall be ignored and used for commenting. The first word of a line is used as key and shall be separated by one or more spaces from its value. The following keys are known: + +* `title` shall contain a human readable title string for this menu item. This will be displayed in the boot menu for the item. It is a good idea to initialize this from the `PRETTY_NAME` of `/etc/os-release`. This name should be descriptive and does not have to be unique. If a boot loader discovers two entries with the same title it is a good idea to show more than just the raw title in the UI, for example by appending the `version` field. This field is optional. Example: "Fedora 18 (Spherical Cow)". +* `version` shall contain a human readable version string for this menu item. This is usually the kernel version and is intended for use by OSes to install multiple kernel versions at the same time with the same `title` field. This field shall be in a syntax that is useful for Debian-style version sorts, so that the boot loader UI can determine the newest version easily and show it first or preselect it automatically. This field is optional. Example: `3.7.2-201.fc18.x86_64`. +* `machine-id` shall contain the machine ID of the OS `/etc/machine-id`. This is useful for boot loaders and applications to filter out boot entries, for example to show only a single newest kernel per OS, or to group items by OS, or to maybe filter out the currently booted OS in UIs that want to show only other installed operating systems. This ID shall be formatted as 32 lower case hexadecimal characters (i.e. without any UUID formatting). This key is optional. Example: `4098b3f648d74c13b1f04ccfba7798e8`. +* `linux` refers to the Linux kernel to spawn and shall be a path relative to the `$BOOT` directory. It is recommended that every distribution creates a machine id and version specific subdirectory below `$BOOT` and places its kernels and initial RAM disk images there. Example: `/6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/linux`. +* `initrd` refers to the initrd to use when executing the kernel. This also shall be a path relative to the `$BOOT` directory. This key is optional. This key may appear more than once in which case all specified images are used, in the order they are listed. Example: `6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/initrd`. +* `efi` refers to an arbitrary EFI program. This also takes a path relative to `$BOOT`. If this key is set, and the system is not an EFI system this entry should be hidden. +* `options` shall contain kernel parameters to pass to the Linux kernel to spawn. This key is optional and may appear more than once in which case all specified parameters are used in the order they are listed. +* `devicetree` refers to the binary device tree to use when executing the +kernel. This also shall be a path relative to the `$BOOT` directory. This +key is optional. Example: `6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.armv7hl/tegra20-paz00.dtb`. +* `devicetree-overlay` refers to a list of device tree overlays that should be +applied by the boot loader. Multiple overlays are separated by spaces and +applied in the same order as they are listed. This key is optional but depends +on the `devicetree` key. Example: +`/6a9857a393724b7a981ebb5b8495b9ea/overlays/overlay_A.dtbo +/6a9857a393724b7a981ebb5b8495b9ea/overlays/overlay_B.dtbo` +* `architecture` refers to the architecture this entry is defined for. The argument should be an architecture identifier, using the architecture vocabulary defined by the EFI specification (i.e. `IA32`, `x64`, `IA64`, `ARM`, `AA64`, …). If specified and this does not match (case insensitively) the local system architecture this entry should be hidden. + +Each configuration drop-in snippet must include at least a `linux` or an `efi` key and is otherwise not valid. Here's an example for a complete drop-in file: + + # /boot/loader/entries/6a9857a393724b7a981ebb5b8495b9ea-3.8.0-2.fc19.x86_64.conf + title Fedora 19 (Rawhide) + version 3.8.0-2.fc19.x86_64 + machine-id 6a9857a393724b7a981ebb5b8495b9ea + options root=UUID=6d3376e4-fc93-4509-95ec-a21d68011da2 + architecture x64 + linux /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/linux + initrd /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/initrd + +On EFI systems all Linux kernel images should be EFI images. In order to +increase compatibility with EFI systems it is highly recommended only to +install EFI kernel images, even on non-EFI systems, if that's applicable and +supported on the specific architecture. + +Conversely, in order to increase compatibility it is recommended to install +generic kernel images that make few assumptions about the firmware they run on, +i.e. it is a good idea that both images shipped as UEFI PE images and those +which are not don't make unnecessary assumption on the underlying firmware, +i.e. don't hard depend on legacy BIOS calls or UEFI boot services. + +Note that these configuration snippets may only reference kernels (and EFI programs) that reside on the same file system as the configuration snippets, i.e. everything referenced must be contained in the same file system. This is by design, as referencing other partitions or devices would require a non-trivial language for denoting device paths. If kernels/initrds are to be read from other partitions/disks the boot loader can do this in its own native configuration, using its own specific device path language, and this is out of focus for this specification. More specifically, on non-EFI systems configuration snippets following this specification cannot be used to spawn other operating systems (such as Windows). + +### Type #2 EFI Unified Kernel Images + +A unified kernel image is a single EFI PE executable combining an EFI stub +loader, a kernel image, an initramfs image, and the kernel command line. See +the description of the `--uefi` option in +[dracut(8)](http://man7.org/linux/man-pages/man8/dracut.8.html). Such unified +images will be searched for under `$BOOT/EFI/Linux/` and must have the +extension `.efi`. Support for images of this type is of course specific to +systems with EFI firmware. Ignore this section if you work on systems not +supporting EFI. + +Images of this type have the advantage that all metadata and payload that makes +up the boot entry is monopolized in a single PE file that can be signed +cryptographically as one for the purpose of EFI SecureBoot. + +A valid unified kernel image must contain two PE sections: + +* `.cmdline` section with the kernel command line +* `.osrel` section with an embedded copy of the [os-release](https://www.freedesktop.org/software/systemd/man/os-release.html) file describing the image + +The `PRETTY_NAME=` and `VERSION_ID=` fields in the embedded os-release file are used the same as `title` and `version` in the "boot loader specification" entries. The `.cmdline` section is used instead of the `options` field. `linux` and `initrd` fields are not necessary, and there is no counterpart for the `machine-id` field. + +On EFI, any such images shall be added to the list of valid boot entries. + +### Additional notes + +Note that these configurations snippets do not need to be the only configuration source for a boot loader. It may extend this list of entries with additional items from other configuration files (for example its own native configuration files) or automatically detected other entries without explicit configuration. + +To make this explicitly clear: this specification is designed with "free" operating systems in mind, starting Windows or MacOS is out of focus with these configuration snippets, use boot-loader specific solutions for that. In the text above, if we say "OS" we hence imply "free", i.e. primarily Linux (though this could be easily be extended to the BSDs and whatnot). + +Note that all paths used in the configuration snippets use a Unix-style "/" as path separator. This needs to be converted to an EFI-style "\" separator in EFI boot loaders. + + +## Logic + +A _boot loader_ needs a file system driver to discover and read `$BOOT`, then +simply reads all files `$BOOT/loader/entries/*.conf`, and populates its boot +menu with this. On EFI, it then extends this with any unified kernel images +found in `$BOOT/EFI/Linux/*.efi`. It may also add additional entries, for +example a "Reboot into firmware" option. Optionally it may sort the menu based +on the `machine-id` and `version` fields, and possibly others. It uses the file +name to identify specific items, for example in case it supports storing away +default entry information somewhere. A boot loader should generally not modify +these files. + +For "Boot Loader Specification Entries" (Type #1), the _kernel package +installer_ installs the kernel and initrd images to `$BOOT` (it is recommended +to place these files in a vendor and OS and installation specific directory) +and then generates a configuration snippet for it, placing this in +`$BOOT/loader/entries/xyz.conf`, with xyz as concatenation of machine id and +version information (see above). The files created by a kernel package are +private property of the kernel package and should be removed along with it. + +For "EFI Unified Kernel Images" (Type #2), the vendor or kernel package +installer creates the combined image and drops it into `$BOOT/EFI/Linux/`. This +file is also private property of the kernel package and should be removed along +with it. + +A _UI application_ intended to show available boot options shall operate similar to a boot loader, but might apply additional filters, for example by filtering out the booted OS via the machine ID, or by suppressing all but the newest kernel versions. + +An _OS installer_ picks the right place for `$BOOT` as defined above (possibly creating a partition and file system for it) and pre-creates the `/loader/entries/` directory in it. It then installs an appropriate boot loader that can read these snippets. Finally, it installs one or more kernel packages. + + +## Out of Focus + +There are a couple of items that are out of focus for this specification: + +* If userspace can figure out the available boot options, then this is only useful so much: we'd still need to come up with a way how userspace could communicate to the boot loader the default boot loader entry temporarily or persistently. Defining a common scheme for this is certainly a good idea, but out of focus for this specification. +* This specification is just about "Free" Operating systems. Hooking in other operating systems (like Windows and macOS) into the boot menu is a different story and should probably happen outside of this specification. For example, boot loaders might choose to detect other available OSes dynamically at runtime without explicit configuration (like `systemd-boot` does it), or via native configuration (for example via explicit Grub2 configuration generated once at installation). +* This specification leaves undefined what to do about systems which are upgraded from an OS that does not implement this specification. As the previous boot loader logic was largely handled by in distribution-specific ways we probably should leave the upgrade path (and whether there actually is one) to the distributions. The simplest solution might be to simply continue with the old scheme for old installations and use this new scheme only for new installations. + + +## Links + +[systemd-boot(7)](https://www.freedesktop.org/software/systemd/man/systemd-boot.html)
+[bootctl(1)](https://www.freedesktop.org/software/systemd/man/bootctl.html) diff --git a/docs/CGROUP_DELEGATION.md b/docs/CGROUP_DELEGATION.md new file mode 100644 index 00000000..607ba6f8 --- /dev/null +++ b/docs/CGROUP_DELEGATION.md @@ -0,0 +1,477 @@ +--- +title: Control Group APIs and Delegation +--- + +# Control Group APIs and Delegation + +*Intended audience: hackers working on userspace subsystems that require direct +cgroup access, such as container managers and similar.* + +So you are wondering about resource management with systemd, you know Linux +control groups (cgroups) a bit and are trying to integrate your software with +what systemd has to offer there. Here's a bit of documentation about the +concepts and interfaces involved with this. + +What's described here has been part of systemd and documented since v205 +times. However, it has been updated and improved substantially, even +though the concepts stayed mostly the same. This is an attempt to provide more +comprehensive up-to-date information about all this, particular in light of the +poor implementations of the components interfacing with systemd of current +container managers. + +Before you read on, please make sure you read the low-level [kernel +documentation about +cgroup v2](https://www.kernel.org/doc/Documentation/cgroup-v2.txt). This +documentation then adds in the higher-level view from systemd. + +This document augments the existing documentation we already have: + +* [The New Control Group Interfaces](https://www.freedesktop.org/wiki/Software/systemd/ControlGroupInterface/) +* [Writing VM and Container Managers](https://www.freedesktop.org/wiki/Software/systemd/writing-vm-managers/) + +These wiki documents are not as up to date as they should be, currently, but +the basic concepts still fully apply. You should read them too, if you do something +with cgroups and systemd, in particular as they shine more light on the various +D-Bus APIs provided. (That said, sooner or later we should probably fold that +wiki documentation into this very document, too.) + +## Two Key Design Rules + +Much of the philosophy behind these concepts is based on a couple of basic +design ideas of cgroup v2 (which we however try to adapt as far as we can to +cgroup v1 too). Specifically two cgroup v2 rules are the most relevant: + +1. The **no-processes-in-inner-nodes** rule: this means that it's not permitted +to have processes directly attached to a cgroup that also has child cgroups and +vice versa. A cgroup is either an inner node or a leaf node of the tree, and if +it's an inner node it may not contain processes directly, and if it's a leaf +node then it may not have child cgroups. (Note that there are some minor +exceptions to this rule, though. E.g. the root cgroup is special and allows +both processes and children — which is used in particular to maintain kernel +threads.) + +2. The **single-writer** rule: this means that each cgroup only has a single +writer, i.e. a single process managing it. It's OK if different cgroups have +different processes managing them. However, only a single process should own a +specific cgroup, and when it does that ownership is exclusive, and nothing else +should manipulate it at the same time. This rule ensures that various pieces of +software don't step on each other's toes constantly. + +These two rules have various effects. For example, one corollary of this is: if +your container manager creates and manages cgroups in the system's root cgroup +you violate rule #2, as the root cgroup is managed by systemd and hence off +limits to everybody else. + +Note that rule #1 is generally enforced by the kernel if cgroup v2 is used: as +soon as you add a process to a cgroup it is ensured the rule is not +violated. On cgroup v1 this rule didn't exist, and hence isn't enforced, even +though it's a good thing to follow it then too. Rule #2 is not enforced on +either cgroup v1 nor cgroup v2 (this is UNIX after all, in the general case +root can do anything, modulo SELinux and friends), but if you ignore it you'll +be in constant pain as various pieces of software will fight over cgroup +ownership. + +Note that cgroup v1 is currently the most deployed implementation, even though +it's semantically broken in many ways, and in many cases doesn't actually do +what people think it does. cgroup v2 is where things are going, and most new +kernel features in this area are only added to cgroup v2, and not cgroup v1 +anymore. For example cgroup v2 provides proper cgroup-empty notifications, has +support for all kinds of per-cgroup BPF magic, supports secure delegation of +cgroup trees to less privileged processes and so on, which all are not +available on cgroup v1. + +## Three Different Tree Setups 🌳 + +systemd supports three different modes how cgroups are set up. Specifically: + +1. **Unified** — this is the simplest mode, and exposes a pure cgroup v2 +logic. In this mode `/sys/fs/cgroup` is the only mounted cgroup API file system +and all available controllers are exclusively exposed through it. + +2. **Legacy** — this is the traditional cgroup v1 mode. In this mode the +various controllers each get their own cgroup file system mounted to +`/sys/fs/cgroup//`. On top of that systemd manages its own cgroup +hierarchy for managing purposes as `/sys/fs/cgroup/systemd/`. + +3. **Hybrid** — this is a hybrid between the unified and legacy mode. It's set +up mostly like legacy, except that there's also an additional hierarchy +`/sys/fs/cgroup/unified/` that contains the cgroup v2 hierarchy. (Note that in +this mode the unified hierarchy won't have controllers attached, the +controllers are all mounted as separate hierarchies as in legacy mode, +i.e. `/sys/fs/cgroup/unified/` is purely and exclusively about core cgroup v2 +functionality and not about resource management.) In this mode compatibility +with cgroup v1 is retained while some cgroup v2 features are available +too. This mode is a stopgap. Don't bother with this too much unless you have +too much free time. + +To say this clearly, legacy and hybrid modes have no future. If you develop +software today and don't focus on the unified mode, then you are writing +software for yesterday, not tomorrow. They are primarily supported for +compatibility reasons and will not receive new features. Sorry. + +Superficially, in legacy and hybrid modes it might appear that the parallel +cgroup hierarchies for each controller are orthogonal from each other. In +systemd they are not: the hierarchies of all controllers are always kept in +sync (at least mostly: sub-trees might be suppressed in certain hierarchies if +no controller usage is required for them). The fact that systemd keeps these +hierarchies in sync means that the legacy and hybrid hierarchies are +conceptually very close to the unified hierarchy. In particular this allows us +to talk of one specific cgroup and actually mean the same cgroup in all +available controller hierarchies. E.g. if we talk about the cgroup `/foo/bar/` +then we actually mean `/sys/fs/cgroup/cpu/foo/bar/` as well as +`/sys/fs/cgroup/memory/foo/bar/`, `/sys/fs/cgroup/pids/foo/bar/`, and so on. +Note that in cgroup v2 the controller hierarchies aren't orthogonal, hence +thinking about them as orthogonal won't help you in the long run anyway. + +If you wonder how to detect which of these three modes is currently used, use +`statfs()` on `/sys/fs/cgroup/`. If it reports `CGROUP2_SUPER_MAGIC` in its +`.f_type` field, then you are in unified mode. If it reports `TMPFS_MAGIC` then +you are either in legacy or hybrid mode. To distinguish these two cases, run +`statfs()` again on `/sys/fs/cgroup/unified/`. If that succeeds and reports +`CGROUP2_SUPER_MAGIC` you are in hybrid mode, otherwise not. + +## systemd's Unit Types + +The low-level kernel cgroups feature is exposed in systemd in three different +"unit" types. Specifically: + +1. 💼 The `.service` unit type. This unit type is for units encapsulating + processes systemd itself starts. Units of these types have cgroups that are + the leaves of the cgroup tree the systemd instance manages (though possibly + they might contain a sub-tree of their own managed by something else, made + possible by the concept of delegation, see below). Service units are usually + instantiated based on a unit file on disk that describes the command line to + invoke and other properties of the service. However, service units may also + be declared and started programmatically at runtime through a D-Bus API + (which is called *transient* services). + +2. 👓 The `.scope` unit type. This is very similar to `.service`. The main + difference: the processes the units of this type encapsulate are forked off + by some unrelated manager process, and that manager asked systemd to expose + them as a unit. Unlike services, scopes can only be declared and started + programmatically, i.e. are always transient. That's because they encapsulate + processes forked off by something else, i.e. existing runtime objects, and + hence cannot really be defined fully in 'offline' concepts such as unit + files. + +3. 🔪 The `.slice` unit type. Units of this type do not directly contain any + processes. Units of this type are the inner nodes of part of the cgroup tree + the systemd instance manages. Much like services, slices can be defined + either on disk with unit files or programmatically as transient units. + +Slices expose the trunk and branches of a tree, and scopes and services are +attached to those branches as leaves. The idea is that scopes and services can +be moved around though, i.e. assigned to a different slice if needed. + +The naming of slice units directly maps to the cgroup tree path. This is not +the case for service and scope units however. A slice named `foo-bar-baz.slice` +maps to a cgroup `/foo.slice/foo-bar.slice/foo-bar-baz.slice/`. A service +`quux.service` which is attached to the slice `foo-bar-baz.slice` maps to the +cgroup `/foo.slice/foo-bar.slice/foo-bar-baz.slice/quux.service/`. + +By default systemd sets up four slice units: + +1. `-.slice` is the root slice. i.e. the parent of everything else. On the host + system it maps directly to the top-level directory of cgroup v2. + +2. `system.slice` is where system services are by default placed, unless + configured otherwise. + +3. `user.slice` is where user sessions are placed. Each user gets a slice of + its own below that. + +4. `machines.slice` is where VMs and containers are supposed to be + placed. `systemd-nspawn` makes use of this by default, and you're very welcome + to place your containers and VMs there too if you hack on managers for those. + +Users may define any amount of additional slices they like though, the four +above are just the defaults. + +## Delegation + +Container managers and suchlike often want to control cgroups directly using +the raw kernel APIs. That's entirely fine and supported, as long as proper +*delegation* is followed. Delegation is a concept we inherited from cgroup v2, +but we expose it on cgroup v1 too. Delegation means that some parts of the +cgroup tree may be managed by different managers than others. As long as it is +clear which manager manages which part of the tree each one can do within its +sub-graph of the tree whatever it wants. + +Only sub-trees can be delegated (though whoever decides to request a sub-tree +can delegate sub-sub-trees further to somebody else if they like). Delegation +takes place at a specific cgroup: in systemd there's a `Delegate=` property you +can set for a service or scope unit. If you do, it's the cut-off point for +systemd's cgroup management: the unit itself is managed by systemd, i.e. all +its attributes are managed exclusively by systemd, however your program may +create/remove sub-cgroups inside it freely, and those then become exclusive +property of your program, systemd won't touch them — all attributes of *those* +sub-cgroups can be manipulated freely and exclusively by your program. + +By turning on the `Delegate=` property for a scope or service you get a few +guarantees: + +1. systemd won't fiddle with your sub-tree of the cgroup tree anymore. It won't + change attributes of any cgroups below it, nor will it create or remove any + cgroups thereunder, nor migrate processes across the boundaries of that + sub-tree as it deems useful anymore. + +2. If your service makes use of the `User=` functionality, then the sub-tree + will be `chown()`ed to the indicated user so that it can correctly create + cgroups below it. Note however that systemd will do that only in the unified + hierarchy (in unified and hybrid mode) as well as on systemd's own private + hierarchy (in legacy and hybrid mode). It won't pass ownership of the legacy + controller hierarchies. Delegation to less privileges processes is not safe + in cgroup v1 (as a limitation of the kernel), hence systemd won't facilitate + access to it. + +3. Any BPF IP filter programs systemd installs will be installed with + `BPF_F_ALLOW_MULTI` so that your program can install additional ones. + +In unit files the `Delegate=` property is superficially exposed as +boolean. However, since v236 it optionally takes a list of controller names +instead. If so, delegation is requested for listed controllers +specifically. Note that this only encodes a request. Depending on various +parameters it might happen that your service actually will get fewer +controllers delegated (for example, because the controller is not available on +the current kernel or was turned off) or more. If no list is specified +(i.e. the property simply set to `yes`) then all available controllers are +delegated. + +Let's stress one thing: delegation is available on scope and service units +only. It's expressly not available on slice units. Why? Because slice units are +our *inner* nodes of the cgroup trees and we freely attach service and scopes +to them. If we'd allow delegation on slice units then this would mean that +both systemd and your own manager would create/delete cgroups below the slice +unit and that conflicts with the single-writer rule. + +So, if you want to do your own raw cgroups kernel level access, then allocate a +scope unit, or a service unit (or just use the service unit you already have +for your service code), and turn on delegation for it. + +(OK, here's one caveat: if you turn on delegation for a service, and that +service has `ExecStartPost=`, `ExecReload=`, `ExecStop=` or `ExecStopPost=` +set, then these commands will be executed within the `.control/` sub-cgroup of +your service's cgroup. This is necessary because by turning on delegation we +have to assume that the cgroup delegated to your service is now an *inner* +cgroup, which means that it may not directly contain any processes. Hence, if +your service has any of these four settings set, you must be prepared that a +`.control/` subcgroup might appear, managed by the service manager. This also +means that your service code should have moved itself further down the cgroup +tree by the time it notifies the service manager about start-up readiness, so +that the service's main cgroup is definitely an inner node by the time the +service manager might start `ExecStartPost=`.) + +## Three Scenarios + +Let's say you write a container manager, and you wonder what to do regarding +cgroups for it, as you want your manager to be able to run on systemd systems. + +You basically have three options: + +1. 😊 The *integration-is-good* option. For this, you register each container + you have either as a systemd service (i.e. let systemd invoke the executor + binary for you) or a systemd scope (i.e. your manager executes the binary + directly, but then tells systemd about it. In this mode the administrator + can use the usual systemd resource management and reporting commands + individually on those containers. By turning on `Delegate=` for these scopes + or services you make it possible to run cgroup-enabled programs in your + containers, for example a nested systemd instance. This option has two + sub-options: + + a. You transiently register the service or scope by directly contacting + systemd via D-Bus. In this case systemd will just manage the unit for you + and nothing else. + + b. Instead you register the service or scope through `systemd-machined` + (also via D-Bus). This mini-daemon is basically just a proxy for the same + operations as in a. The main benefit of this: this way you let the system + know that what you are registering is a container, and this opens up + certain additional integration points. For example, `journalctl -M` can + then be used to directly look into any container's journal logs (should + the container run systemd inside), or `systemctl -M` can be used to + directly invoke systemd operations inside the containers. Moreover tools + like "ps" can then show you to which container a process belongs (`ps -eo + pid,comm,machine`), and even gnome-system-monitor supports it. + +2. 🙁 The *i-like-islands* option. If all you care about is your own cgroup tree, + and you want to have to do as little as possible with systemd and no + interest in integration with the rest of the system, then this is a valid + option. For this all you have to do is turn on `Delegate=` for your main + manager daemon. Then figure out the cgroup systemd placed your daemon in: + you can now freely create sub-cgroups beneath it. Don't forget the + *no-processes-in-inner-nodes* rule however: you have to move your main + daemon process out of that cgroup (and into a sub-cgroup) before you can + start further processes in any of your sub-cgroups. + +3. 🙁 The *i-like-continents* option. In this option you'd leave your manager + daemon where it is, and would not turn on delegation on its unit. However, + as first thing you register a new scope unit with systemd, and that scope + unit would have `Delegate=` turned on, and then you place all your + containers underneath it. From systemd's PoV there'd be two units: your + manager service and the big scope that contains all your containers in one. + +BTW: if for whatever reason you say "I hate D-Bus, I'll never call any D-Bus +API, kthxbye", then options #1 and #3 are not available, as they generally +involve talking to systemd from your program code, via D-Bus. You still have +option #2 in that case however, as you can simply set `Delegate=` in your +service's unit file and you are done and have your own sub-tree. In fact, #2 is +the one option that allows you to completely ignore systemd's existence: you +can entirely generically follow the single rule that you just use the cgroup +you are started in, and everything below it, whatever that might be. That said, +maybe if you dislike D-Bus and systemd that much, the better approach might be +to work on that, and widen your horizon a bit. You are welcome. + +## Controller Support + +systemd supports a number of controllers (but not all). Specifically, supported +are: + +* on cgroup v1: `cpu`, `cpuacct`, `blkio`, `memory`, `devices`, `pids` +* on cgroup v2: `cpu`, `io`, `memory`, `pids` + +It is our intention to natively support all cgroup v2 controllers as they are +added to the kernel. However, regarding cgroup v1: at this point we will not +add support for any other controllers anymore. This means systemd currently +does not and will never manage the following controllers on cgroup v1: +`freezer`, `cpuset`, `net_cls`, `perf_event`, `net_prio`, `hugetlb`. Why not? +Depending on the case, either their API semantics or implementations aren't +really usable, or it's very clear they have no future on cgroup v2, and we +won't add new code for stuff that clearly has no future. + +Effectively this means that all those mentioned cgroup v1 controllers are up +for grabs: systemd won't manage them, and hence won't delegate them to your +code (however, systemd will still mount their hierarchies, simply because it +mounts all controller hierarchies it finds available in the kernel). If you +decide to use them, then that's fine, but systemd won't help you with it (but +also not interfere with it). To be nice to other tenants it might be wise to +replicate the cgroup hierarchies of the other controllers in them too however, +but of course that's between you and those other tenants, and systemd won't +care. Replicating the cgroup hierarchies in those unsupported controllers would +mean replicating the full cgroup paths in them, and hence the prefixing +`.slice` components too, otherwise the hierarchies will start being orthogonal +after all, and that's not really desirable. On more thing: systemd will clean +up after you in the hierarchies it manages: if your daemon goes down, its +cgroups will be removed too. You basically get the guarantee that you start +with a pristine cgroup sub-tree for your service or scope whenever it is +started. This is not the case however in the hierarchies systemd doesn't +manage. This means that your programs should be ready to deal with left-over +cgroups in them — from previous runs, and be extra careful with them as they +might still carry settings that might not be valid anymore. + +Note a particular asymmetry here: if your systemd version doesn't support a +specific controller on cgroup v1 you can still make use of it for delegation, +by directly fiddling with its hierarchy and replicating the cgroup tree there +as necessary (as suggested above). However, on cgroup v2 this is different: +separately mounted hierarchies are not available, and delegation has always to +happen through systemd itself. This means: when you update your kernel and it +adds a new, so far unseen controller, and you want to use it for delegation, +then you also need to update systemd to a version that groks it. + +## systemd as Container Payload + +systemd can happily run as a container payload's PID 1. Note that systemd +unconditionally needs write access to the cgroup tree however, hence you need +to delegate a sub-tree to it. Note that there's nothing too special you have to +do beyond that: just invoke systemd as PID 1 inside the root of the delegated +cgroup sub-tree, and it will figure out the rest: it will determine the cgroup +it is running in and take possession of it. It won't interfere with any cgroup +outside of the sub-tree it was invoked in. Use of `CLONE_NEWCGROUP` is hence +optional (but of course wise). + +Note one particular asymmetry here though: systemd will try to take possession +of the root cgroup you pass to it *in* *full*, i.e. it will not only +create/remove child cgroups below it, it will also attempt to manage the +attributes of it. OTOH as mentioned above, when delegating a cgroup tree to +somebody else it only passes the rights to create/remove sub-cgroups, but will +insist on managing the delegated cgroup tree's top-level attributes. Or in +other words: systemd is *greedy* when accepting delegated cgroup trees and also +*greedy* when delegating them to others: it insists on managing attributes on +the specific cgroup in both cases. A container manager that is itself a payload +of a host systemd which wants to run a systemd as its own container payload +instead hence needs to insert an extra level in the hierarchy in between, so +that the systemd on the host and the one in the container won't fight for the +attributes. That said, you likely should do that anyway, due to the +no-processes-in-inner-cgroups rule, see below. + +When systemd runs as container payload it will make use of all hierarchies it +has write access to. For legacy mode you need to make at least +`/sys/fs/cgroup/systemd/` available, all other hierarchies are optional. For +hybrid mode you need to add `/sys/fs/cgroup/unified/`. Finally, for fully +unified you (of course, I guess) need to provide only `/sys/fs/cgroup/` itself. + +## Some Dos + +1. ⚡ If you go for implementation option 1a or 1b (as in the list above), then + each of your containers will have its own systemd-managed unit and hence + cgroup with possibly further sub-cgroups below. Typically the first process + running in that unit will be some kind of executor program, which will in + turn fork off the payload processes of the container. In this case don't + forget that there are two levels of delegation involved: first, systemd + delegates a group sub-tree to your executor. And then your executor should + delegate a sub-tree further down to the container payload. Oh, and because + of the no-process-in-inner-nodes rule, your executor needs to migrate itself + to a sub-cgroup of the cgroup it got delegated, too. Most likely you hence + want a two-pronged approach: below the cgroup you got started in, you want + one cgroup maybe called `supervisor/` where your manager runs in and then + for each container a sibling cgroup of that maybe called `payload-xyz/`. + +2. ⚡ Don't forget that the cgroups you create have to have names that are + suitable as UNIX file names, and that they live in the same namespace as the + various kernel attribute files. Hence, when you want to allow the user + arbitrary naming, you might need to escape some of the names (for example, + you really don't want to create a cgroup named `tasks`, just because the + user created a container by that name, because `tasks` after all is a magic + attribute in cgroup v1, and your `mkdir()` will hence fail with `EEXIST`. In + systemd we do escaping by prefixing names that might collide with a kernel + attribute name with an underscore. You might want to do the same, but this + is really up to you how you do it. Just do it, and be careful. + +## Some Don'ts + +1. 🚫 Never create your own cgroups below arbitrary cgroups systemd manages, i.e + cgroups you haven't set `Delegate=` in. Specifically: 🔥 don't create your + own cgroups below the root cgroup 🔥. That's owned by systemd, and you will + step on systemd's toes if you ignore that, and systemd will step on + yours. Get your own delegated sub-tree, you may create as many cgroups there + as you like. Seriously, if you create cgroups directly in the cgroup root, + then all you do is ask for trouble. + +2. 🚫 Don't attempt to set `Delegate=` in slice units, and in particular not in + `-.slice`. It's not supported, and will generate an error. + +3. 🚫 Never *write* to any of the attributes of a cgroup systemd created for + you. It's systemd's private property. You are welcome to manipulate the + attributes of cgroups you created in your own delegated sub-tree, but the + cgroup tree of systemd itself is out of limits for you. It's fine to *read* + from any attribute you like however. That's totally OK and welcome. + +4. 🚫 When not using `CLONE_NEWCGROUP` when delegating a sub-tree to a + container payload running systemd, then don't get the idea that you can bind + mount only a sub-tree of the host's cgroup tree into the container. Part of + the cgroup API is that `/proc/$PID/cgroup` reports the cgroup path of every + process, and hence any path below `/sys/fs/cgroup/` needs to match what + `/proc/$PID/cgroup` of the payload processes reports. What you can do safely + however, is mount the upper parts of the cgroup tree read-only (or even + replace the middle bits with an intermediary `tmpfs` — but be careful not to + break the `statfs()` detection logic discussed above), as long as the path + to the delegated sub-tree remains accessible as-is. + +5. ⚡ Currently, the algorithm for mapping between slice/scope/service unit + naming and their cgroup paths is not considered public API of systemd, and + may change in future versions. This means: it's best to avoid implementing a + local logic of translating cgroup paths to slice/scope/service names in your + program, or vice versa — it's likely going to break sooner or later. Use the + appropriate D-Bus API calls for that instead, so that systemd translates + this for you. (Specifically: each Unit object has a `ControlGroup` property + to get the cgroup for a unit. The method `GetUnitByControlGroup()` may be + used to get the unit for a cgroup.) + +6. ⚡ Think twice before delegating cgroup v1 controllers to less privileged + containers. It's not safe, you basically allow your containers to freeze the + system with that and worse. Delegation is a strongpoint of cgroup v2 though, + and there it's safe to treat delegation boundaries as privilege boundaries. + +And that's it for now. If you have further questions, refer to the systemd +mailing list. + +— Berlin, 2018-04-20 diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 00000000..cdcf4d9a --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +systemd.io \ No newline at end of file diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..da290ecd --- /dev/null +++ b/docs/CODE_OF_CONDUCT.md @@ -0,0 +1,18 @@ +--- +title: The systemd Community Conduct Guidelines +--- + +# The systemd Community Conduct Guidelines + +This document provides community guidelines for a safe, respectful, productive, and collaborative place for any person who is willing to contribute to systemd. It applies to all “collaborative spaces”, which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.). + +- Participants will be tolerant of opposing views. +- Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks. +- When interpreting the words and actions of others, participants should always assume good intentions. +- Behaviour which can be reasonably considered harassment will not be tolerated. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at systemd-conduct@googlegroups.com. This team currently consists of David Strauss <>, Ekaterina Gerasimova (Kat) <>, and Zbigniew Jędrzejewski-Szmek <>. In the unfortunate event that you wish to make a complaint against one of the members, you may instead contact any of the other members individually. + +All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. diff --git a/docs/CODE_QUALITY.md b/docs/CODE_QUALITY.md new file mode 100644 index 00000000..a3bdfaad --- /dev/null +++ b/docs/CODE_QUALITY.md @@ -0,0 +1,73 @@ +--- +title: Code Quality Tools +--- + +# Code Quality Tools + +The systemd project has a number of code quality tools set up in the source +tree and on the github infrastructure. Here's an incomprehensive list of the +available functionality: + +1. Use `ninja -C build test` to run the unit tests. Some tests are skipped if + no privileges are available, hence consider also running them with `sudo + ninja -C build test`. A couple of unit tests are considered "unsafe" (as + they change system state); to run those too, build with `meson + -Dtests=unsafe`. Finally, some unit tests are considered to be very slow, + build them too with `meson -Dslow-tests=true`. (Note that there are a couple + of manual tests in addition to these unit tests.) + +2. Use `./test/run-integration-tests.sh` to run the full integration test + suite. This will build OS images with a number of integration tests and run + them in nspawn and qemu. Requires root. + +3. Use `./coccinelle/run-coccinelle.sh` to run all + [Coccinelle](http://coccinelle.lip6.fr/) semantic patch scripts we ship. The + output will show false positives, hence take it with a pinch of salt. + +4. Use `./tools/find-double-newline.sh recdiff` to find double newlines. Use + `./tools/find-double-newline.sh recpatch` to fix them. Take this with a grain + of salt, in particular as we generally leave foreign header files we include in + our tree unmodified, if possible. + +5. Similar use `./tools/find-tabs.sh recdiff` to find TABs, and + `./tools/find-tabs.sh recpatch` to fix them. (Again, grain of salt, foreign + headers should usually be left unmodified.) + +6. Use `ninja -C build check-api-docs` to compare the list of exported + symbols of `libsystemd.so` and `libudev.so` with the list of man pages. Symbols + lacking documentation are highlighted. + +7. Use `ninja -C build hwdb-update` to automatically download and import the + PCI, USB and OUI databases into hwdb. + +8. Use `ninja -C build man/update-man-rules` to update the meson rules for + building man pages automatically from the docbook XML files included in + `man/`. + +9. There are multiple CI systems in use that run on every github PR submission. + +10. [Coverity](https://scan.coverity.com/) is analyzing systemd master in + regular intervals. The reports are available + [online](https://scan.coverity.com/projects/systemd). + +11. [oss-fuzz](https://oss-fuzz.com/) is continuously fuzzing the + codebase. Reports are available + [online](https://oss-fuzz.com/v2/testcases?project=systemd). + +12. Our tree includes `.editorconfig`, `.dir-locals.el` and `.vimrc` files, to + ensure that editors follow the right indentiation styles automatically. + +13. When building systemd from a git checkout the build scripts will + automatically enable a git commit hook that ensures whitespace cleanliness. + +14. [LGTM](https://lgtm.com/) analyzes every commit pushed to master. The list + of active alerts can be found + [here](https://lgtm.com/projects/g/systemd/systemd/alerts/?mode=list). + +15. Each PR is automatically tested with [Address Sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html) + and [Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html). + See [Testing systemd using sanitizers](https://systemd.io/TESTING_WITH_SANITIZERS) + for more information. + +Access to Coverity and oss-fuzz reports is limited. Please reach out to the +maintainers if you need access. diff --git a/docs/CODING_STYLE.md b/docs/CODING_STYLE.md new file mode 100644 index 00000000..3b9b5e6c --- /dev/null +++ b/docs/CODING_STYLE.md @@ -0,0 +1,550 @@ +--- +title: Coding Style +--- + +# Coding Style + +## Formatting + +- 8ch indent, no tabs, except for files in `man/` which are 2ch indent, and + still no tabs, and shell scripts, which are 4ch indent, and no tabs either. + +- We prefer `/* comments */` over `// comments` in code you commit, + please. This way `// comments` are left for developers to use for local, + temporary commenting of code for debug purposes (i.e. uncommittable stuff), + making such comments easily discernible from explanatory, documenting code + comments (i.e. committable stuff). + +- Don't break code lines too eagerly. We do **not** force line breaks at 80ch, + all of today's screens should be much larger than that. But then again, don't + overdo it, ~109ch should be enough really. The `.editorconfig`, `.vimrc` and + `.dir-locals.el` files contained in the repository will set this limit up for + you automatically, if you let them (as well as a few other things). Please + note that emacs loads `.dir-locals.el` automatically, but vim needs to be + configured to load `.vimrc`, see that file for instructions. + +- Try to write this: + + ```c + void foo() { + } + ``` + + instead of this: + + ```c + void foo() + { + } + ``` + +- Single-line `if` blocks should not be enclosed in `{}`. Write this: + + ```c + if (foobar) + waldo(); + ``` + + instead of this: + + ```c + if (foobar) { + waldo(); + } + ``` + +- Do not write `foo ()`, write `foo()`. + +## Code Organization and Semantics + +- Please name structures in `PascalCase` (with exceptions, such as public API + structs), variables and functions in `snake_case`. + +- Avoid static variables, except for caches and very few other cases. Think + about thread-safety! While most of our code is never used in threaded + environments, at least the library code should make sure it works correctly + in them. Instead of doing a lot of locking for that, we tend to prefer using + TLS to do per-thread caching (which only works for small, fixed-size cache + objects), or we disable caching for any thread that is not the main + thread. Use `is_main_thread()` to detect whether the calling thread is the + main thread. + +- Do not write functions that clobber call-by-reference variables on + failure. Use temporary variables for these cases and change the passed in + variables only on success. + +- The order in which header files are included doesn't matter too + much. systemd-internal headers must not rely on an include order, so it is + safe to include them in any order possible. However, to not clutter global + includes, and to make sure internal definitions will not affect global + headers, please always include the headers of external components first + (these are all headers enclosed in <>), followed by our own exported headers + (usually everything that's prefixed by `sd-`), and then followed by internal + headers. Furthermore, in all three groups, order all includes alphabetically + so duplicate includes can easily be detected. + +- Please avoid using global variables as much as you can. And if you do use + them make sure they are static at least, instead of exported. Especially in + library-like code it is important to avoid global variables. Why are global + variables bad? They usually hinder generic reusability of code (since they + break in threaded programs, and usually would require locking there), and as + the code using them has side-effects make programs non-transparent. That + said, there are many cases where they explicitly make a lot of sense, and are + OK to use. For example, the log level and target in `log.c` is stored in a + global variable, and that's OK and probably expected by most. Also in many + cases we cache data in global variables. If you add more caches like this, + please be careful however, and think about threading. Only use static + variables if you are sure that thread-safety doesn't matter in your + case. Alternatively, consider using TLS, which is pretty easy to use with + gcc's `thread_local` concept. It's also OK to store data that is inherently + global in global variables, for example data parsed from command lines, see + below. + +- You might wonder what kind of common code belongs in `src/shared/` and what + belongs in `src/basic/`. The split is like this: anything that is used to + implement the public shared object we provide (sd-bus, sd-login, sd-id128, + nss-systemd, nss-mymachines, nss-resolve, nss-myhostname, pam_systemd), must + be located in `src/basic` (those objects are not allowed to link to + libsystemd-shared.so). Conversely, anything which is shared between multiple + components and does not need to be in `src/basic/`, should be in + `src/shared/`. + + To summarize: + + `src/basic/` + - may be used by all code in the tree + - may not use any code outside of `src/basic/` + + `src/libsystemd/` + - may be used by all code in the tree, except for code in `src/basic/` + - may not use any code outside of `src/basic/`, `src/libsystemd/` + + `src/shared/` + - may be used by all code in the tree, except for code in `src/basic/`, + `src/libsystemd/`, `src/nss-*`, `src/login/pam_systemd.*`, and files under + `src/journal/` that end up in `libjournal-client.a` convenience library. + - may not use any code outside of `src/basic/`, `src/libsystemd/`, `src/shared/` + +- Our focus is on the GNU libc (glibc), not any other libcs. If other libcs are + incompatible with glibc it's on them. However, if there are equivalent POSIX + and Linux/GNU-specific APIs, we generally prefer the POSIX APIs. If there + aren't, we are happy to use GNU or Linux APIs, and expect non-GNU + implementations of libc to catch up with glibc. + +## Using C Constructs + +- Preferably allocate local variables on the top of the block: + + ```c + { + int a, b; + + a = 5; + b = a; + } + ``` + +- Do not mix function invocations with variable definitions in one line. Wrong: + + ```c + { + int a = foobar(); + uint64_t x = 7; + } + ``` + + Right: + + ```c + { + int a; + uint64_t x = 7; + + a = foobar(); + } + ``` + +- Use `goto` for cleaning up, and only use it for that. i.e. you may only jump + to the end of a function, and little else. Never jump backwards! + +- To minimize strict aliasing violations, we prefer unions over casting. + +- Instead of using `memzero()`/`memset()` to initialize structs allocated on + the stack, please try to use c99 structure initializers. It's short, prettier + and actually even faster at execution. Hence: + + ```c + struct foobar t = { + .foo = 7, + .bar = "bazz", + }; + ``` + + instead of: + + ```c + struct foobar t; + zero(t); + t.foo = 7; + t.bar = "bazz"; + ``` + +- To implement an endless loop, use `for (;;)` rather than `while (1)`. The + latter is a bit ugly anyway, since you probably really meant `while + (true)`. To avoid the discussion what the right always-true expression for an + infinite while loop is, our recommendation is to simply write it without any + such expression by using `for (;;)`. + +- To determine the length of a constant string `"foo"`, don't bother with + `sizeof("foo")-1`, please use `strlen()` instead (both gcc and clang optimize + the call away for fixed strings). The only exception is when declaring an + array. In that case use STRLEN, which evaluates to a static constant and + doesn't force the compiler to create a VLA. + +- Please use C's downgrade-to-bool feature only for expressions that are + actually booleans (or "boolean-like"), and not for variables that are really + numeric. Specifically, if you have an `int b` and it's only used in a boolean + sense, by all means check its state with `if (b) …` — but if `b` can actually + have more than two semantic values, and you want to compare for non-zero, + then please write that explicitly with `if (b != 0) …`. This helps readability + as the value range and semantical behaviour is directly clear from the + condition check. As a special addition: when dealing with pointers which you + want to check for non-NULL-ness, you may also use downgrade-to-bool feature. + +- Please do not use yoda comparisons, i.e. please prefer the more readable `if + (a == 7)` over the less readable `if (7 == a)`. + +## Destructors + +- The destructors always deregister the object from the next bigger object, not + the other way around. + +- For robustness reasons, destructors should be able to destruct + half-initialized objects, too. + +- When you define a destructor or `unref()` call for an object, please accept a + `NULL` object and simply treat this as NOP. This is similar to how libc + `free()` works, which accepts `NULL` pointers and becomes a NOP for them. By + following this scheme a lot of `if` checks can be removed before invoking + your destructor, which makes the code substantially more readable and robust. + +- Related to this: when you define a destructor or `unref()` call for an + object, please make it return the same type it takes and always return `NULL` + from it. This allows writing code like this: + + ```c + p = foobar_unref(p); + ``` + + which will always work regardless if `p` is initialized or not, and + guarantees that `p` is `NULL` afterwards, all in just one line. + +## Error Handling + +- Error codes are returned as negative `Exxx`. e.g. `return -EINVAL`. There are + some exceptions: for constructors, it is OK to return `NULL` on OOM. For + lookup functions, `NULL` is fine too for "not found". + + Be strict with this. When you write a function that can fail due to more than + one cause, it *really* should have an `int` as the return value for the error + code. + +- Do not bother with error checking whether writing to stdout/stderr worked. + +- Do not log errors from "library" code, only do so from "main program" + code. (With one exception: it is OK to log with DEBUG level from any code, + with the exception of maybe inner loops). + +- In public API calls, you **must** validate all your input arguments for + programming error with `assert_return()` and return a sensible return + code. In all other calls, it is recommended to check for programming errors + with a more brutal `assert()`. We are more forgiving to public users than for + ourselves! Note that `assert()` and `assert_return()` really only should be + used for detecting programming errors, not for runtime errors. `assert()` and + `assert_return()` by usage of `_likely_()` inform the compiler that he should + not expect these checks to fail, and they inform fellow programmers about the + expected validity and range of parameters. + +- When you invoke certain calls like `unlink()`, or `mkdir_p()` and you know it + is safe to ignore the error it might return (because a later call would + detect the failure anyway, or because the error is in an error path and you + thus couldn't do anything about it anyway), then make this clear by casting + the invocation explicitly to `(void)`. Code checks like Coverity understand + that, and will not complain about ignored error codes. Hence, please use + this: + + ```c + (void) unlink("/foo/bar/baz"); + ``` + + instead of just this: + + ```c + unlink("/foo/bar/baz"); + ``` + + Don't cast function calls to `(void)` that return no error + conditions. Specifically, the various `xyz_unref()` calls that return a + `NULL` object shouldn't be cast to `(void)`, since not using the return value + does not hide any errors. + +- When returning a return code from `main()`, please preferably use + `EXIT_FAILURE` and `EXIT_SUCCESS` as defined by libc. + +## Logging + +- For every function you add, think about whether it is a "logging" function or + a "non-logging" function. "Logging" functions do logging on their own, + "non-logging" function never log on their own and expect their callers to + log. All functions in "library" code, i.e. in `src/shared/` and suchlike must + be "non-logging". Every time a "logging" function calls a "non-logging" + function, it should log about the resulting errors. If a "logging" function + calls another "logging" function, then it should not generate log messages, + so that log messages are not generated twice for the same errors. + +- If possible, do a combined log & return operation: + + ```c + r = operation(...); + if (r < 0) + return log_(error|warning|notice|...)_errno(r, "Failed to ...: %m"); + ``` + + If the error value is "synthetic", i.e. it was not received from + the called function, use `SYNTHETIC_ERRNO` wrapper to tell the logging + system to not log the errno value, but still return it: + + ```c + n = read(..., s, sizeof s); + if (n != sizeof s) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to read ..."); + ``` + +## Memory Allocation + +- Always check OOM. There is no excuse. In program code, you can use + `log_oom()` for then printing a short message, but not in "library" code. + +- Avoid fixed-size string buffers, unless you really know the maximum size and + that maximum size is small. They are a source of errors, since they possibly + result in truncated strings. It is often nicer to use dynamic memory, + `alloca()` or VLAs. If you do allocate fixed-size strings on the stack, then + it is probably only OK if you either use a maximum size such as `LINE_MAX`, + or count in detail the maximum size a string can have. (`DECIMAL_STR_MAX` and + `DECIMAL_STR_WIDTH` macros are your friends for this!) + + Or in other words, if you use `char buf[256]` then you are likely doing + something wrong! + +- Make use of `_cleanup_free_` and friends. It makes your code much nicer to + read (and shorter)! + +- Use `alloca()`, but never forget that it is not OK to invoke `alloca()` + within a loop or within function call parameters. `alloca()` memory is + released at the end of a function, and not at the end of a `{}` block. Thus, + if you invoke it in a loop, you keep increasing the stack pointer without + ever releasing memory again. (VLAs have better behavior in this case, so + consider using them as an alternative.) Regarding not using `alloca()` + within function parameters, see the BUGS section of the `alloca(3)` man page. + +- If you want to concatenate two or more strings, consider using `strjoina()` + or `strjoin()` rather than `asprintf()`, as the latter is a lot slower. This + matters particularly in inner loops (but note that `strjoina()` cannot be + used there). + +## Runtime Behaviour + +- Avoid leaving long-running child processes around, i.e. `fork()`s that are + not followed quickly by an `execv()` in the child. Resource management is + unclear in this case, and memory CoW will result in unexpected penalties in + the parent much, much later on. + +- Don't block execution for arbitrary amounts of time using `usleep()` or a + similar call, unless you really know what you do. Just "giving something some + time", or so is a lazy excuse. Always wait for the proper event, instead of + doing time-based poll loops. + +- Whenever installing a signal handler, make sure to set `SA_RESTART` for it, + so that interrupted system calls are automatically restarted, and we minimize + hassles with handling `EINTR` (in particular as `EINTR` handling is pretty + broken on Linux). + +- When applying C-style unescaping as well as specifier expansion on the same + string, always apply the C-style unescaping fist, followed by the specifier + expansion. When doing the reverse, make sure to escape `%` in specifier-style + first (i.e. `%` → `%%`), and then do C-style escaping where necessary. + +- Be exceptionally careful when formatting and parsing floating point + numbers. Their syntax is locale dependent (i.e. `5.000` in en_US is generally + understood as 5, while in de_DE as 5000.). + +- Make sure to enforce limits on every user controllable resource. If the user + can allocate resources in your code, your code must enforce some form of + limits after which it will refuse operation. It's fine if it is hard-coded + (at least initially), but it needs to be there. This is particularly + important for objects that unprivileged users may allocate, but also matters + for everything else any user may allocated. + +## Types + +- Think about the types you use. If a value cannot sensibly be negative, do not + use `int`, but use `unsigned`. + +- Use `char` only for actual characters. Use `uint8_t` or `int8_t` when you + actually mean a byte-sized signed or unsigned integers. When referring to a + generic byte, we generally prefer the unsigned variant `uint8_t`. Do not use + types based on `short`. They *never* make sense. Use `int`, `long`, `long + long`, all in unsigned and signed fashion, and the fixed-size types + `uint8_t`, `uint16_t`, `uint32_t`, `uint64_t`, `int8_t`, `int16_t`, `int32_t` + and so on, as well as `size_t`, but nothing else. Do not use kernel types + like `u32` and so on, leave that to the kernel. + +- Stay uniform. For example, always use `usec_t` for time values. Do not mix + `usec` and `msec`, and `usec` and whatnot. + +- Never use the `off_t` type, and particularly avoid it in public APIs. It's + really weirdly defined, as it usually is 64-bit and we don't support it any + other way, but it could in theory also be 32-bit. Which one it is depends on + a compiler switch chosen by the compiled program, which hence corrupts APIs + using it unless they can also follow the program's choice. Moreover, in + systemd we should parse values the same way on all architectures and cannot + expose `off_t` values over D-Bus. To avoid any confusion regarding conversion + and ABIs, always use simply `uint64_t` directly. + +- Unless you allocate an array, `double` is always a better choice than + `float`. Processors speak `double` natively anyway, so there is no speed + benefit, and on calls like `printf()` `float`s get promoted to `double`s + anyway, so there is no point. + +- Use the bool type for booleans, not integers. One exception: in public + headers (i.e those in `src/systemd/sd-*.h`) use integers after all, as `bool` + is C99 and in our public APIs we try to stick to C89 (with a few extension). + +## Deadlocks + +- Do not issue NSS requests (that includes user name and host name lookups) + from PID 1 as this might trigger deadlocks when those lookups involve + synchronously talking to services that we would need to start up. + +- Do not synchronously talk to any other service from PID 1, due to risk of + deadlocks. + +## File Descriptors + +- When you allocate a file descriptor, it should be made `O_CLOEXEC` right from + the beginning, as none of our files should leak to forked binaries by + default. Hence, whenever you open a file, `O_CLOEXEC` must be specified, + right from the beginning. This also applies to sockets. Effectively, this + means that all invocations to: + + - `open()` must get `O_CLOEXEC` passed, + - `socket()` and `socketpair()` must get `SOCK_CLOEXEC` passed, + - `recvmsg()` must get `MSG_CMSG_CLOEXEC` set, + - `F_DUPFD_CLOEXEC` should be used instead of `F_DUPFD`, and so on, + - invocations of `fopen()` should take `e`. + +- It's a good idea to use `O_NONBLOCK` when opening 'foreign' regular files, + i.e. file system objects that are supposed to be regular files whose paths + where specified by the user and hence might actually refer to other types of + file system objects. This is a good idea so that we don't end up blocking on + 'strange' file nodes, for example if the user pointed us to a FIFO or device + node which may block when opening. Moreover even for actual regular files + `O_NONBLOCK` has a benefit: it bypasses any mandatory lock that might be in + effect on the regular file. If in doubt consider turning off `O_NONBLOCK` + again after opening. + +## Command Line + +- If you parse a command line, and want to store the parsed parameters in + global variables, please consider prefixing their names with `arg_`. We have + been following this naming rule in most of our tools, and we should continue + to do so, as it makes it easy to identify command line parameter variables, + and makes it clear why it is OK that they are global variables. + +- Command line option parsing: + - Do not print full `help()` on error, be specific about the error. + - Do not print messages to stdout on error. + - Do not POSIX_ME_HARDER unless necessary, i.e. avoid `+` in option string. + +## Exporting Symbols + +- Variables and functions **must** be static, unless they have a prototype, and + are supposed to be exported. + +- Public API calls (i.e. functions exported by our shared libraries) + must be marked `_public_` and need to be prefixed with `sd_`. No + other functions should be prefixed like that. + +- When exposing public C APIs, be careful what function parameters you make + `const`. For example, a parameter taking a context object should probably not + be `const`, even if you are writing an otherwise read-only accessor function + for it. The reason is that making it `const` fixates the contract that your + call won't alter the object ever, as part of the API. However, that's often + quite a promise, given that this even prohibits object-internal caching or + lazy initialization of object variables. Moreover, it's usually not too + useful for client applications. Hence, please be careful and avoid `const` on + object parameters, unless you are very sure `const` is appropriate. + +## Referencing Concepts + +- When referring to a configuration file option in the documentation and such, + please always suffix it with `=`, to indicate that it is a configuration file + setting. + +- When referring to a command line option in the documentation and such, please + always prefix with `--` or `-` (as appropriate), to indicate that it is a + command line option. + +- When referring to a file system path that is a directory, please always + suffix it with `/`, to indicate that it is a directory, not a regular file + (or other file system object). + +## Functions to Avoid + +- Use `memzero()` or even better `zero()` instead of `memset(..., 0, ...)` + +- Please use `streq()` and `strneq()` instead of `strcmp()`, `strncmp()` where + applicable (i.e. wherever you just care about equality/inequality, not about + the sorting order). + +- Never use `strtol()`, `atoi()` and similar calls. Use `safe_atoli()`, + `safe_atou32()` and suchlike instead. They are much nicer to use in most + cases and correctly check for parsing errors. + +- `htonl()`/`ntohl()` and `htons()`/`ntohs()` are weird. Please use `htobe32()` + and `htobe16()` instead, it's much more descriptive, and actually says what + really is happening, after all `htonl()` and `htons()` don't operate on + `long`s and `short`s as their name would suggest, but on `uint32_t` and + `uint16_t`. Also, "network byte order" is just a weird name for "big endian", + hence we might want to call it "big endian" right-away. + +- Please never use `dup()`. Use `fcntl(fd, F_DUPFD_CLOEXEC, 3)` instead. For + two reason: first, you want `O_CLOEXEC` set on the new `fd` (see + above). Second, `dup()` will happily duplicate your `fd` as 0, 1, 2, + i.e. stdin, stdout, stderr, should those `fd`s be closed. Given the special + semantics of those `fd`s, it's probably a good idea to avoid + them. `F_DUPFD_CLOEXEC` with `3` as parameter avoids them. + +- Don't use `fgets()`, it's too hard to properly handle errors such as overly + long lines. Use `read_line()` instead, which is our own function that handles + this much nicer. + +- Don't invoke `exit()`, ever. It is not replacement for proper error + handling. Please escalate errors up your call chain, and use normal `return` + to exit from the main function of a process. If you `fork()`ed off a child + process, please use `_exit()` instead of `exit()`, so that the exit handlers + are not run. + +- We never use the POSIX version of `basename()` (which glibc defines it in + `libgen.h`), only the GNU version (which glibc defines in `string.h`). The + only reason to include `libgen.h` is because `dirname()` is needed. Every + time you need that please immediately undefine `basename()`, and add a + comment about it, so that no code ever ends up using the POSIX version! + +# Committing to git + +- Commit message subject lines should be prefixed with an appropriate component + name of some kind. For example "journal: ", "nspawn: " and so on. + +- Do not use "Signed-Off-By:" in your commit messages. That's a kernel thing we + don't do in the systemd project. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 00000000..565acdd1 --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,41 @@ +--- +title: Contributing +--- + +# Contributing + +We welcome contributions from everyone. However, please follow the following guidelines when posting a GitHub Pull Request or filing a GitHub Issue on the systemd project: + +## Filing Issues + +* We use [GitHub Issues](https://github.com/systemd/systemd/issues) **exclusively** for tracking **bugs** and **feature** **requests** of systemd. If you are looking for help, please contact [systemd-devel mailing list](https://lists.freedesktop.org/mailman/listinfo/systemd-devel) instead. +* We only track bugs in the **two** **most** **recently** **released** **versions** of systemd in the GitHub Issue tracker. If you are using an older version of systemd, please contact your distribution's bug tracker instead. +* When filing an issue, specify the **systemd** **version** you are experiencing the issue with. Also, indicate which **distribution** you are using. +* Please include an explanation how to reproduce the issue you are pointing out. + +Following these guidelines makes it easier for us to process your issue, and ensures we won't close your issue right-away for being misfiled. + +### Older downstream versions +For older versions that are still supported by your distribution please use respective downstream tracker: +* **Fedora** - [bugzilla](https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora&component=systemd) +* **RHEL-7/CentOS-7** - [bugzilla](https://bugzilla.redhat.com/enter_bug.cgi?product=Red%20Hat%20Enterprise%20Linux%207&component=systemd) or [systemd-rhel github](https://github.com/lnykryn/systemd-rhel/issues) +* **Debian** - [bugs.debian.org](https://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=systemd) + +## Security vulnerability reports + +See [reporting of security vulnerabilities](SECURITY.md). + +## Posting Pull Requests + +* Make sure to post PRs only relative to a very recent git master. +* Follow our [Coding Style](CODING_STYLE.md) when contributing code. This is a requirement for all code we merge. +* Please make sure to test your change before submitting the PR. See the [Hacking guide](HACKING.md) for details on how to do this. +* Make sure to run the test suite locally, before posting your PR. We use a CI system, meaning we don't even look at your PR, if the build and tests don't pass. +* If you need to update the code in an existing PR, force-push into the same branch, overriding old commits with new versions. +* After you have pushed a new version, add a comment about the new version (no notification is sent just for the commits, so it's easy to miss the update without an explicit comment). If you are a member of the systemd project on GitHub, remove the `reviewed/needs-rework` label. + +## Final Words + +We'd like to apologize in advance if we are not able to process and reply to your issue or PR right-away. We have a lot of work to do, but we are trying our best! + +Thank you very much for your contributions! diff --git a/docs/DISTRO_PORTING.md b/docs/DISTRO_PORTING.md new file mode 100644 index 00000000..d14bf131 --- /dev/null +++ b/docs/DISTRO_PORTING.md @@ -0,0 +1,92 @@ +--- +title: Porting systemd To New Distributions +--- + +# Porting systemd To New Distributions + +## HOWTO + +You need to make the follow changes to adapt systemd to your +distribution: + +1. Find the right configure parameters for: + + * `-Drootprefix=` + * `-Dsysvinit-path=` + * `-Dsysvrcnd-path=` + * `-Drc-local=` + * `-Dloadkeys-path=` + * `-Dsetfont-path=` + * `-Dtty-gid=` + * `-Dntp-servers=` + * `-Ddns-servers=` + * `-Dsupport-url=` + +2. Try it out. + + Play around (as an ordinary user) with + `/usr/lib/systemd/systemd --test --system` for a test run + of systemd without booting. This will read the unit files and + print the initial transaction it would execute during boot-up. + This will also inform you about ordering loops and suchlike. + +## Compilation options + +The default configuration does not enable any optimization or hardening +options. This is suitable for development and testing, but not for end-user +installations. + +For deployment, optimization (`-O2` or `-O3` compiler options), link time +optimization (`-Db_lto=true` meson option), and hardening (e.g. +`-D_FORTIFY_SOURCE=2`, `-fstack-protector-strong`, `-fstack-clash-protection`, +`-fcf-protection`, `-pie` compiler options, and `-z relro`, `-z now`, +`--as-needed` linker options) are recommended. The most appropriate set of +options depends on the architecture and distribution specifics so no default is +provided. + +## NTP Pool + +By default, systemd-timesyncd uses the Google Public NTP servers +`time[1-4].google.com`, if no other NTP configuration is available. +They serve time that uses a +[leap second smear](https://developers.google.com/time/smear) +and can be up to .5s off from servers that use stepped leap seconds. + +If you prefer to use leap second steps, please register your own +vendor pool at ntp.org and make it the built-in default by +passing `-Dntp-servers=` to meson. Registering vendor +pools is [free](http://www.pool.ntp.org/en/vendors.html). + +Use `-Dntp-servers=` to direct systemd-timesyncd to different fallback +NTP servers. + +## DNS Servers + +By default, systemd-resolved uses Cloudflare and Google Public DNS servers +`1.1.1.1`, `8.8.8.8`, `1.0.0.1`, `8.8.4.4`, `2606:4700:4700::1111`, `2001:4860:4860::8888`, `2606:4700:4700::1001`, `2001:4860:4860::8844` +as fallback, if no other DNS configuration is available. + +Use `-Ddns-servers=` to direct systemd-resolved to different fallback +DNS servers. + +## PAM + +The default PAM config shipped by systemd is really bare bones. +It does not include many modules your distro might want to enable +to provide a more seamless experience. For example, limits set in +`/etc/security/limits.conf` will not be read unless you load `pam_limits`. +Make sure you add modules your distro expects from user services. + +Pass `-Dpamconfdir=no` to meson to avoid installing this file and +instead install your own. + +## Contributing Upstream + +We generally do no longer accept distribution-specific patches to +systemd upstream. If you have to make changes to systemd's source code +to make it work on your distribution, unless your code is generic +enough to be generally useful, we are unlikely to merge it. Please +always consider adopting the upstream defaults. If that is not +possible, please maintain the relevant patches downstream. + +Thank you for understanding. diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md new file mode 100644 index 00000000..a3837ebf --- /dev/null +++ b/docs/ENVIRONMENT.md @@ -0,0 +1,243 @@ +--- +title: Known Environment Variables +--- + +# Known Environment Variables + +A number of systemd components take additional runtime parameters via +environment variables. Many of these environment variables are not supported at +the same level as command line switches and other interfaces are: we don't +document them in the man pages and we make no stability guarantees for +them. While they generally are unlikely to be dropped any time soon again, we +do not want to guarantee that they stay around for good either. + +Below is an (incomprehensive) list of the environment variables understood by +the various tools. Note that this list only covers environment variables not +documented in the proper man pages. + +All tools: + +* `$SYSTEMD_OFFLINE=[0|1]` — if set to `1`, then `systemctl` will + refrain from talking to PID 1; this has the same effect as the historical + detection of `chroot()`. Setting this variable to `0` instead has a similar + effect as `SYSTEMD_IGNORE_CHROOT=1`; i.e. tools will try to + communicate with PID 1 even if a `chroot()` environment is detected. + You almost certainly want to set this to `1` if you maintain a package build system + or similar and are trying to use a modern container system and not plain + `chroot()`. + +* `$SYSTEMD_IGNORE_CHROOT=1` — if set, don't check whether being invoked in a + `chroot()` environment. This is particularly relevant for systemctl, as it + will not alter its behaviour for `chroot()` environments if set. Normally it + refrains from talking to PID 1 in such a case; turning most operations such + as `start` into no-ops. If that's what's explicitly desired, you might + consider setting `SYSTEMD_OFFLINE=1`. + +* `$SD_EVENT_PROFILE_DELAYS=1` — if set, the sd-event event loop implementation + will print latency information at runtime. + +* `$SYSTEMD_PROC_CMDLINE` — if set, the contents are used as the kernel command + line instead of the actual one in /proc/cmdline. This is useful for + debugging, in order to test generators and other code against specific kernel + command lines. + +* `$SYSTEMD_FSTAB` — if set, use this path instead of /etc/fstab. Only useful + for debugging. + +* `$SYSTEMD_CRYPTTAB` — if set, use this path instead of /etc/crypttab. Only + useful for debugging. Currently only supported by systemd-cryptsetup-generator. + +* `$SYSTEMD_EFI_OPTIONS` — if set, used instead of the string in the + SystemdOptions EFI variable. Analogous to `$SYSTEMD_PROC_CMDLINE`. + +* `$SYSTEMD_IN_INITRD` — takes a boolean. If set, overrides initrd detection. + This is useful for debugging and testing initrd-only programs in the main + system. + +* `$SYSTEMD_BUS_TIMEOUT=SECS` — specifies the maximum time to wait for method call + completion. If no time unit is specified, assumes seconds. The usual other units + are understood, too (us, ms, s, min, h, d, w, month, y). If it is not set or set + to 0, then the built-in default is used. + +* `$SYSTEMD_MEMPOOL=0` — if set, the internal memory caching logic employed by + hash tables is turned off, and libc malloc() is used for all allocations. + +* `$SYSTEMD_EMOJI=0` — if set, tools such as "systemd-analyze security" will + not output graphical smiley emojis, but ASCII alternatives instead. Note that + this only controls use of Unicode emoji glyphs, and has no effect on other + Unicode glyphs. + +* `$RUNTIME_DIRECTORY` — various tools use this variable to locate the + appropriate path under /run. This variable is also set by the manager when + RuntimeDirectory= is used, see systemd.exec(5). + +systemctl: + +* `$SYSTEMCTL_FORCE_BUS=1` — if set, do not connect to PID1's private D-Bus + listener, and instead always connect through the dbus-daemon D-bus broker. + +* `$SYSTEMCTL_INSTALL_CLIENT_SIDE=1` — if set, enable or disable unit files on + the client side, instead of asking PID 1 to do this. + +* `$SYSTEMCTL_SKIP_SYSV=1` — if set, do not call out to SysV compatibility hooks. + +systemd-nspawn: + +* `$SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=1` — if set, force nspawn into unified + cgroup hierarchy mode. + +* `$SYSTEMD_NSPAWN_API_VFS_WRITABLE=1` — if set, make /sys and /proc/sys and + friends writable in the container. If set to "network", leave only + /proc/sys/net writable. + +* `$SYSTEMD_NSPAWN_CONTAINER_SERVICE=…` — override the "service" name nspawn + uses to register with machined. If unset defaults to "nspawn", but with this + variable may be set to any other value. + +* `$SYSTEMD_NSPAWN_USE_CGNS=0` — if set, do not use cgroup namespacing, even if + it is available. + +* `$SYSTEMD_NSPAWN_LOCK=0` — if set, do not lock container images when running. + +* `$SYSTEMD_NSPAWN_TMPFS_TMP=0` — if set, do not overmount /tmp in the + container with a tmpfs, but leave the directory from the image in place. + +systemd-logind: + +* `$SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1` — if set, report that + hibernation is available even if the swap devices do not provide enough room + for it. + +systemd-udevd: + +* `$NET_NAMING_SCHEME=` – if set, takes a network naming scheme (i.e. one of + "v238", "v239", "v240"…, or the special value "latest") as parameter. If + specified udev's net_id builtin will follow the specified naming scheme when + determining stable network interface names. This may be used to revert to + naming schemes of older udev versions, in order to provide more stable naming + across updates. This environment variable takes precedence over the kernel + command line option `net.naming-scheme=`, except if the value is prefixed + with `:` in which case the kernel command line option takes precedence, if it + is specified as well. + +* `$SYSTEMD_REBOOT_TO_FIRMWARE_SETUP` — if set overrides systemd-logind's + built-in EFI logic of requesting a reboot into the firmware. Takes a + boolean. If set to false the functionality is turned off entirely. If set to + true instead of requesting a reboot into the firmware setup UI through EFI a + file `/run/systemd/reboot-to-firmware-setup` is created whenever this is + requested. This file may be checked for by services run during system + shutdown in order to request the appropriate operation from the firmware in + an alternative fashion. + +* `$SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU` — similar to the above, allows + overriding of systemd-logind's built-in EFI logic of requesting a reboot into + the boot loader menu. Takes a boolean. If set to false the functionality is + turned off entirely. If set to true instead of requesting a reboot into the + boot loader menu through EFI a file `/run/systemd/reboot-to-boot-loader-menu` + is created whenever this is requested. The file contains the requested boot + loader menu timeout in µs, formatted in ASCII decimals, or zero in case no + time-out is requested. This file may be checked for by services run during + system shutdown in order to request the appropriate operation from the boot + loader in an alternative fashion. + +* `$SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY` — similar to the above, allows + overriding of systemd-logind's built-in EFI logic of requesting a reboot into + a specific boot loader entry. Takes a boolean. If set to false the + functionality is turned off entirely. If set to true instead of requesting a + reboot into a specific boot loader entry through EFI a file + `/run/systemd/reboot-to-boot-loader-entry` is created whenever this is + requested. The file contains the requested boot loader entry identifier. This + file may be checked for by services run during system shutdown in order to + request the appropriate operation from the boot loader in an alternative + fashion. Note that by default only boot loader entries which follow the [Boot + Loader Specification](https://systemd.io/BOOT_LOADER_SPECIFICATION) and are + placed in the ESP or the Extended Boot Loader partition may be selected this + way. However, if a directory `/run/boot-loader-entries/` exists, the entries + are loaded from there instead. The directory should contain the usual + directory hierarchy mandated by the Boot Loader Specification, i.e. the entry + drop-ins should be placed in + `/run/boot-loader-entries/loader/entries/*.conf`, and the files referenced by + the drop-ins (including the kernels and initrds) somewhere else below + `/run/boot-loader-entries/`. Note that all these files may be (and are + supposed to be) symlinks. systemd-logind will load these files on-demand, + these files can hence be updated (ideally atomically) whenever the boot + loader configuration changes. A foreign boot loader installer script should + hence synthesize drop-in snippets and symlinks for all boot entries at boot + or whenever they change if it wants to integrate with systemd-logind's APIs. + +installed systemd tests: + +* `$SYSTEMD_TEST_DATA` — override the location of test data. This is useful if + a test executable is moved to an arbitrary location. + +nss-systemd: + +* `$SYSTEMD_NSS_BYPASS_SYNTHETIC=1` — if set, `nss-systemd` won't synthesize + user/group records for the `root` and `nobody` users if they are missing from + `/etc/passwd`. + +* `$SYSTEMD_NSS_DYNAMIC_BYPASS=1` — if set, `nss-systemd` won't return + user/group records for dynamically registered service users (i.e. users + registered through `DynamicUser=1`). + +* `$SYSTEMD_NSS_BYPASS_BUS=1` — if set, `nss-systemd` won't use D-Bus to do + dynamic user lookups. This is primarily useful to make `nss-systemd` work + safely from within `dbus-daemon`. + +systemd-timedated: + +* `$SYSTEMD_TIMEDATED_NTP_SERVICES=…` — colon-separated list of unit names of + NTP client services. If set, `timedatectl set-ntp on` enables and starts the + first existing unit listed in the environment variable, and + `timedatectl set-ntp off` disables and stops all listed units. + +systemd-sulogin-shell: + +* `$SYSTEMD_SULOGIN_FORCE=1` — This skips asking for the root password if the + root password is not available (such as when the root account is locked). + See `sulogin(8)` for more details. + +bootctl and other tools that access the EFI System Partition (ESP): + +* `$SYSTEMD_RELAX_ESP_CHECKS=1` — if set, the ESP validation checks are + relaxed. Specifically, validation checks that ensure the specified ESP path + is a FAT file system are turned off, as are checks that the path is located + on a GPT partition with the correct type UUID. + +* `$SYSTEMD_ESP_PATH=…` — override the path to the EFI System Partition. This + may be used to override ESP path auto detection, and redirect any accesses to + the ESP to the specified directory. Not that unlike with bootctl's --path= + switch only very superficial validation of the specified path is done when + this environment variable is used. + +systemd itself: + +* `$SYSTEMD_ACTIVATION_UNIT` — set for all NSS and PAM module invocations that + are done by the service manager on behalf of a specific unit, in child + processes that are later (after execve()) going to become unit + processes. Contains the full unit name (e.g. "foobar.service"). NSS and PAM + modules can use this information to determine in which context and on whose + behalf they are being called, which may be useful to avoid deadlocks, for + example to bypass IPC calls to the very service that is about to be + started. Note that NSS and PAM modules should be careful to only rely on this + data when invoked privileged, or possibly only when getppid() returns 1, as + setting environment variables is of course possible in any even unprivileged + contexts. + +* `$SYSTEMD_ACTIVATION_SCOPE` — closely related to `$SYSTEMD_ACTIVATION_UNIT`, + it is either set to `system` or `user` depending on whether the NSS/PAM + module is called by systemd in `--system` or `--user` mode. + +systemd-remount-fs: + +* `$SYSTEMD_REMOUNT_ROOT_RW=1` — if set and no entry for the root directory + exists in /etc/fstab (this file always takes precedence), then the root + directory is remounted writable. This is primarily used by + systemd-gpt-auto-generator to ensure the root partition is mounted writable + in accordance to the GPT partition flags. + +systemd-firstboot and localectl: + +* `SYSTEMD_LIST_NON_UTF8_LOCALES=1` – if set non-UTF-8 locales are listed among + the installed ones. By default non-UTF-8 locales are suppressed from the + selection, since we are living in the 21st century. diff --git a/docs/HACKING.md b/docs/HACKING.md new file mode 100644 index 00000000..7dc1eb98 --- /dev/null +++ b/docs/HACKING.md @@ -0,0 +1,131 @@ +--- +title: Hacking on systemd +--- + +# Hacking on systemd + +We welcome all contributions to systemd. If you notice a bug or a missing +feature, please feel invited to fix it, and submit your work as a GitHub Pull +Request (PR) at https://github.com/systemd/systemd/pull/new. + +Please make sure to follow our [Coding Style](CODING_STYLE.md) when submitting patches. +Also have a look at our [Contribution Guidelines](CONTRIBUTING.md). + +When adding new functionality, tests should be added. For shared functionality +(in `src/basic/` and `src/shared/`) unit tests should be sufficient. The general +policy is to keep tests in matching files underneath `src/test/`, +e.g. `src/test/test-path-util.c` contains tests for any functions in +`src/basic/path-util.c`. If adding a new source file, consider adding a matching +test executable. For features at a higher level, tests in `src/test/` are very +strongly recommended. If that is not possible, integration tests in `test/` are +encouraged. + +Please also have a look at our list of [code quality tools](CODE_QUALITY.md) we have setup for systemd, +to ensure our codebase stays in good shape. + +Please always test your work before submitting a PR. For many of the components +of systemd testing is straight-forward as you can simply compile systemd and +run the relevant tool from the build directory. + +For some components (most importantly, systemd/PID1 itself) this is not +possible, however. In order to simplify testing for cases like this we provide +a set of `mkosi` build files directly in the source tree. `mkosi` is a tool for +building clean OS images from an upstream distribution in combination with a +fresh build of the project in the local working directory. To make use of this, +please acquire `mkosi` from https://github.com/systemd/mkosi first, unless your +distribution has packaged it already and you can get it from there. After the +tool is installed it is sufficient to type `mkosi` in the systemd project +directory to generate a disk image `image.raw` you can boot either in +`systemd-nspawn` or in an UEFI-capable VM: + +``` +# systemd-nspawn -bi image.raw +``` + +or: + +``` +# qemu-system-x86_64 -enable-kvm -m 512 -smp 2 -bios /usr/share/edk2/ovmf/OVMF_CODE.fd -hda image.raw +``` + +Every time you rerun the `mkosi` command a fresh image is built, incorporating +all current changes you made to the project tree. + +Alternatively, you may install the systemd version from your git check-out +directly on top of your host system's directory tree. This mostly works fine, +but of course you should know what you are doing as you might make your system +unbootable in case of a bug in your changes. Also, you might step into your +package manager's territory with this. Be careful! + +And never forget: most distributions provide very simple and convenient ways to +install all development packages necessary to build systemd. For example, on +Fedora the following command line should be sufficient to install all of +systemd's build dependencies: + +``` +# dnf builddep systemd +``` + +Putting this all together, here's a series of commands for preparing a patch +for systemd (this example is for Fedora): + +```sh +$ sudo dnf builddep systemd # install build dependencies +$ sudo dnf install mkosi # install tool to quickly build images +$ git clone https://github.com/systemd/systemd.git +$ cd systemd +$ vim src/core/main.c # or wherever you'd like to make your changes +$ meson build # configure the build +$ ninja -C build # build it locally, see if everything compiles fine +$ ninja -C build test # run some simple regression tests +$ (umask 077; echo 123 > mkosi.rootpw) # set root password used by mkosi +$ sudo mkosi # build a test image +$ sudo systemd-nspawn -bi image.raw # boot up the test image +$ git add -p # interactively put together your patch +$ git commit # commit it +$ git push REMOTE HEAD:refs/heads/BRANCH + # where REMOTE is your "fork" on GitHub + # and BRANCH is a branch name. +``` + +And after that, head over to your repo on GitHub and click "Compare & pull request" + +Happy hacking! + + +## Fuzzers + +systemd includes fuzzers in `src/fuzz/` that use libFuzzer and are automatically +run by [OSS-Fuzz](https://github.com/google/oss-fuzz) and [Fuzzit](https://fuzzit.dev) with sanitizers. +To add a fuzz target, create a new `src/fuzz/fuzz-foo.c` file with a `LLVMFuzzerTestOneInput` +function and add it to the list in `src/fuzz/meson.build`. + +Whenever possible, a seed corpus and a dictionary should also be added with new +fuzz targets. The dictionary should be named `src/fuzz/fuzz-foo.dict` and the seed +corpus should be built and exported as `$OUT/fuzz-foo_seed_corpus.zip` in +`tools/oss-fuzz.sh`. + +The fuzzers can be built locally if you have libFuzzer installed by running +`tools/oss-fuzz.sh`. You should also confirm that the fuzzer runs in the +OSS-Fuzz environment by checking out the OSS-Fuzz repo, and then running +commands like this: + +``` +python infra/helper.py build_image systemd +python infra/helper.py build_fuzzers --sanitizer memory systemd ../systemd +python infra/helper.py run_fuzzer systemd fuzz-foo +``` + +When you add a new target you should also add the target on [Fuzzit](https://app.fuzzit.dev/admin/RxqRpGNXquIvqrmp4iJS/dashboard) + (Please ask someone with permissions). One the target is configured on Fuzzit you need to add it to + `travis-ci/managers/fuzzit.sh` so the new target will run sanity tests on every pull-request and periodic fuzzing jobs. + +If you find a bug that impacts the security of systemd, please follow the +guidance in [CONTRIBUTING.md](CONTRIBUTING.md) on how to report a security vulnerability. + +For more details on building fuzzers and integrating with OSS-Fuzz, visit: + +- https://github.com/google/oss-fuzz/blob/master/docs/new_project_guide.md +- https://llvm.org/docs/LibFuzzer.html +- https://github.com/google/fuzzer-test-suite/blob/master/tutorial/libFuzzerTutorial.md +- https://chromium.googlesource.com/chromium/src/testing/libfuzzer/+/HEAD/efficient_fuzzer.md diff --git a/docs/PORTABLE_SERVICES.md b/docs/PORTABLE_SERVICES.md new file mode 100644 index 00000000..194ef5bc --- /dev/null +++ b/docs/PORTABLE_SERVICES.md @@ -0,0 +1,285 @@ +--- +title: Portable Services Introduction +--- + +# Portable Services Introduction + +This systemd version includes a preview of the "portable service" +concept. "Portable Services" are supposed to be an incremental improvement over +traditional system services, making two specific facets of container management +available to system services more readily. Specifically: + +1. The bundling of applications, i.e. packing up multiple services, their + binaries and all their dependencies in a single image, and running them + directly from it. + +2. Stricter default security policies, i.e. sand-boxing of applications. + +The primary tool for interfacing with "portable services" is the new +"portablectl" program. It's currently shipped in /usr/lib/systemd/portablectl +(i.e. not in the `$PATH`), since it's not yet considered part of the officially +supported systemd interfaces — it's a preview still after all. + +Portable services don't bring anything inherently new to the table. All they do +is put together known concepts in a slightly nicer way to cover a specific set +of use-cases in a nicer way. + +## So, what *is* a "Portable Service"? + +A portable service is ultimately just an OS tree, either inside of a directory +tree, or inside a raw disk image containing a Linux file system. This tree is +called the "image". It can be "attached" or "detached" from the system. When +"attached" specific systemd units from the image are made available on the host +system, then behaving pretty much exactly like locally installed system +services. When "detached" these units are removed again from the host, leaving +no artifacts around (except maybe messages they might have logged). + +The OS tree/image can be created with any tool of your choice. For example, you +can use `dnf --installroot=` if you like, or `debootstrap`, the image format is +entirely generic, and doesn't have to carry any specific metadata beyond what +distribution images carry anyway. Or to say this differently: the image format +doesn't define any new metadata as unit files and OS tree directories or disk +images are already sufficient, and pretty universally available these days. One +particularly nice tool for creating suitable images is +[mkosi](https://github.com/systemd/mkosi), but many other existing tools will +do too. + +If you so will, "Portable Services" are a nicer way to manage chroot() +environments, with better security, tooling and behavior. + +## Where's the difference to a "Container"? + +"Container" is a very vague term, after all it is used for +systemd-nspawn/LXC-type OS containers, for Docker/rkt-like micro service +containers, and even certain 'lightweight' VM runtimes. + +The "portable service" concept ultimately will not provide a fully isolated +environment to the payload, like containers mostly intend to. Instead they are +from the beginning more alike regular system services, can be controlled with +the same tools, are exposed the same way in all infrastructure and so on. Their +main difference is that the use a different root directory than the rest of the +system. Hence, the intention is not to run code in a different, isolated world +from the host — like most containers would do it —, but to run it in the same +world, but with stricter access controls on what the service can see and do. + +As one point of differentiation: as programs run as "portable services" are +pretty much regular system services, they won't run as PID 1 (like Docker would +do it), but as normal process. A corollary of that is that they aren't supposed +to manage anything in their own environment (such as the network) as the +execution environment is mostly shared with the rest of the system. + +The primary focus use-case of "portable services" is to extend the host system +with encapsulated extensions, but provide almost full integration with the rest +of the system, though possibly restricted by effective security knobs. This +focus includes system extensions otherwise sometimes called "super-privileged +containers". + +Note that portable services are only available for system services, not for +user services. i.e. the functionality cannot be used for the stuff +bubblewrap/flatpak is focusing on. + +## Mode of Operation + +If you have portable service image, maybe in a raw disk image called +`foobar_0.7.23.raw`, then attaching the services to the host is as easy as: + +``` +# /usr/lib/systemd/portablectl attach foobar_0.7.23.raw +``` + +This command does the following: + +1. It dissects the image, checks and validates the `/etc/os-release` + (or `/usr/lib/os-release`, see below) data of the image, and looks for + all included unit files. + +2. It copies out all unit files with a suffix of `.service`, `.socket`, + `.target`, `.timer` and `.path`. whose name begins with the image's name + (with the .raw removed), truncated at the first underscore (if there is + one). This prefix name generated from the image name must be followed by a + ".", "-" or "@" character in the unit name. Or in other words, given the + image name of `foobar_0.7.23.raw` all unit files matching + `foobar-*.{service|socket|target|timer|path}`, + `foobar@.{service|socket|target|timer|path}` as well as + `foobar.*.{service|socket|target|timer|path}` and + `foobar.{service|socket|target|timer|path}` are copied out. These unit files + are placed in `/etc/systemd/system.attached/` (which is part of the normal + unit file search path of PID 1, and thus loaded exactly like regular unit + files). Within the images the unit files are looked for at the usual + locations, i.e. in `/usr/lib/systemd/system/` and `/etc/systemd/system/` and + so on, relative to the image's root. + +3. For each such unit file a drop-in file is created. Let's say + `foobar-waldo.service` was one of the unit files copied to + `/etc/systemd/system.attached/`, then a drop-in file + `/etc/systemd/system.attached/foobar-waldo.service.d/20-portable.conf` is + created, containing a few lines of additional configuration: + + ``` + [Service] + RootImage=/path/to/foobar.raw + Environment=PORTABLE=foobar + LogExtraFields=PORTABLE=foobar + ``` + +4. For each such unit a "profile" drop-in is linked in. This "profile" drop-in + generally contains security options that lock down the service. By default + the `default` profile is used, which provides a medium level of + security. There's also `trusted` which runs the service at the highest + privileges, i.e. host's root and everything. The `strict` profile comes with + the toughest security restrictions. Finally, `nonetwork` is like `default` + but without network access. Users may define their own profiles too (or + modify the existing ones) + +And that's already it. + +Note that the images need to stay around (and the same location) as long as the +portable service is attached. If an image is moved, the `RootImage=` line +written to the unit drop-in would point to an non-existing place, and break the +logic. + +The `portablectl detach` command executes the reverse operation: it looks for +the drop-ins and the unit files associated with the image, and removes them +again. + +Note that `portable attach` won't enable or start any of the units it copies +out. This still has to take place in a second, separate step. (That said We +might add options to do this automatically later on.). + +## Requirements on Images + +Note that portable services don't introduce any new image format, but most OS +images should just work the way they are. Specifically, the following +requirements are made for an image that can be attached/detached with +`portablectl`. + +1. It must contain an executable that shall be invoked, along with all its + dependencies. If binary code, the code needs to be compiled for an + architecture compatible with the host. + +2. The image must either be a plain sub-directory (or btrfs subvolume) + containing the binaries and its dependencies in a classic Linux OS tree, or + must be a raw disk image either containing only one, naked file system, or + an image with a partition table understood by the Linux kernel with only a + single partition defined, or alternatively, a GPT partition table with a set + of properly marked partitions following the [Discoverable Partitions + Specification](https://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/). + +3. The image must at least contain one matching unit file, with the right name + prefix and suffix (see above). The unit file is searched in the usual paths, + i.e. primarily /etc/systemd/system/ and /usr/lib/systemd/system/ within the + image. (The implementation will check a couple of other paths too, but it's + recommended to use these two paths.) + +4. The image must contain an os-release file, either in `/etc/os-release` or + `/usr/lib/os-release`. The file should follow the standard format. + +5. The image must contain the files `/etc/resolv.conf` and `/etc/machine-id` + (empty files are ok), they will be bind mounted from the host at runtime. + +6. The image must contain directories `/proc/`, `/sys/`, `/dev/`, `/run/`, + `/tmp/`, `/var/tmp/` that can be mounted over with the corresponding version + from the host. + +7. The OS might require other files or directories to be in place. For example, + if the image is built based on glibc, the dynamic loader needs to be + available in `/lib/ld-linux.so.2` or `/lib64/ld-linux-x86-64.so.2` (or + similar, depending on architecture), and if the distribution implements a + merged `/usr/` tree, this means `/lib` and/or `/lib64` need to be symlinks + to their respective counterparts below `/usr/`. For details see your + distribution's documentation. + +Note that images created by tools such as `debootstrap`, `dnf --installroot=` +or `mkosi` generally qualify for all of the above in one way or another. If you +wonder what the most minimal image would be that complies with the requirements +above, it could consist of this: + +``` +/usr/bin/minimald # a statically compiled binary +/usr/lib/systemd/system/minimal-test.service # the unit file for the service, with ExecStart=/usr/bin/minimald +/usr/lib/os-release # an os-release file explaining what this is +/etc/resolv.conf # empty file to mount over with host's version +/etc/machine-id # ditto +/proc/ # empty directory to use as mount point for host's API fs +/sys/ # ditto +/dev/ # ditto +/run/ # ditto +/tmp/ # ditto +/var/tmp/ # ditto +``` + +And that's it. + +Note that qualifying images do not have to contain an init system of their +own. If they do, it's fine, it will be ignored by the portable service logic, +but they generally don't have to, and it might make sense to avoid any, to keep +images minimal. + +If the image is writable, and some of the files or directories that are +overmounted from the host do not exist yet they are automatically created. On +read-only, immutable images (e.g. squashfs images) all files and directories to +over-mount must exist already. + +Note that as no new image format or metadata is defined, it's very +straight-forward to define images than can be made use of it a number of +different ways. For example, by using `mkosi -b` you can trivially build a +single, unified image that: + +1. Can be attached as portable service, to run any container services natively + on the host. + +2. Can be run as OS container, using `systemd-nspawn`, by booting the image + with `systemd-nspawn -i -b`. + +3. Can be booted directly as VM image, using a generic VM executor such as + `virtualbox`/`qemu`/`kvm` + +4. Can be booted directly on bare-metal systems. + +Of course, to facilitate 2, 3 and 4 you need to include an init system in the +image. To facility 3 and 4 you also need to include a boot loader in the +image. As mentioned `mkosi -b` takes care of all of that for you, but any other +image generator should work too. + +## Execution Environment + +Note that the code in portable service images is run exactly like regular +services. Hence there's no new execution environment to consider. Oh, unlike +Docker would do it, as these are regular system services they aren't run as PID +1 either, but with regular PID values. + +## Access to host resources + +If services shipped with this mechanism shall be able to access host resources +(such as files or AF_UNIX sockets for IPC), use the normal `BindPaths=` and +`BindReadOnlyPaths=` settings in unit files to mount them in. In fact the +`default` profile mentioned above makes use of this to ensure +`/etc/resolv.conf`, the D-Bus system bus socket or write access to the logging +subsystem are available to the service. + +## Instantiation + +Sometimes it makes sense to instantiate the same set of services multiple +times. The portable service concept does not introduce a new logic for this. It +is recommended to use the regular unit templating of systemd for this, i.e. to +include template units such as `foobar@.service`, so that instantiation is as +simple as: + +``` +# /usr/lib/systemd/portablectl attach foobar_0.7.23.raw +# systemctl enable --now foobar@instancea.service +# systemctl enable --now foobar@instanceb.service +… +``` + +The benefit of this approach is that templating works exactly the same for +units shipped with the OS itself as for attached portable services. + +## Immutable images with local data + +It's a good idea to keep portable service images read-only during normal +operation. In fact all but the `trusted` profile will default to this kind of +behaviour, by setting the `ProtectSystem=strict` option. In this case writable +service data may be placed on the host file system. Use `StateDirectory=` in +the unit files to enable such behaviour and add a local data directory to the +services copied onto the host. diff --git a/docs/PREDICTABLE_INTERFACE_NAMES.md b/docs/PREDICTABLE_INTERFACE_NAMES.md new file mode 100644 index 00000000..b29016f9 --- /dev/null +++ b/docs/PREDICTABLE_INTERFACE_NAMES.md @@ -0,0 +1,68 @@ +--- +title: Predictable Network Interface Names +--- + +# Predictable Network Interface Names + +Starting with v197 systemd/udev will automatically assign predictable, stable network interface names for all local Ethernet, WLAN and WWAN interfaces. This is a departure from the traditional interface naming scheme ("eth0", "eth1", "wlan0", ...), but should fix real problems. + + +## Why? + +The classic naming scheme for network interfaces applied by the kernel is to simply assign names beginning with "eth0", "eth1", ... to all interfaces as they are probed by the drivers. As the driver probing is generally not predictable for modern technology this means that as soon as multiple network interfaces are available the assignment of the names "eth0", "eth1" and so on is generally not fixed anymore and it might very well happen that "eth0" on one boot ends up being "eth1" on the next. This can have serious security implications, for example in firewall rules which are coded for certain naming schemes, and which are hence very sensitive to unpredictable changing names. + +To fix this problem multiple solutions have been proposed and implemented. For a longer time udev shipped support for assigning permanent "ethX" names to certain interfaces based on their MAC addresses. This turned out to have a multitude of problems, among them: this required a writable root directory which is generally not available; the statelessness of the system is lost as booting an OS image on a system will result in changed configuration of the image; on many systems MAC addresses are not actually fixed, such as on a lot of embedded hardware and particularly on all kinds of virtualization solutions. The biggest of all however is that the userspace components trying to assign the interface name raced against the kernel assigning new names from the same "ethX" namespace, a race condition with all kinds of weird effects, among them that assignment of names sometimes failed. As a result support for this has been removed from systemd/udev a while back. + +Another solution that has been implemented is "biosdevname" which tries to find fixed slot topology information in certain firmware interfaces and uses them to assign fixed names to interfaces which incorporate their physical location on the mainboard. In a way this naming scheme is similar to what is already done natively in udev for various device nodes via /dev/*/by-path/ symlinks. In many cases, biosdevname departs from the low-level kernel device identification schemes that udev generally uses for these symlinks, and instead invents its own enumeration schemes. + +Finally, many distributions support renaming interfaces to user-chosen names (think: "internet0", "dmz0", ...) keyed off their MAC addresses or physical locations as part of their networking scripts. This is a very good choice but does have the problem that it implies that the user is willing and capable of choosing and assigning these names. + +We believe it is a good default choice to generalize the scheme pioneered by "biosdevname". Assigning fixed names based on firmware/topology/location information has the big advantage that the names are fully automatic, fully predictable, that they stay fixed even if hardware is added or removed (i.e. no reenumeration takes place) and that broken hardware can be replaced seamlessly. That said, they admittedly are sometimes harder to read than the "eth0" or "wlan0" everybody is used to. Example: "enp5s0" + + +## What precisely has changed in v197? + +With systemd 197 we have added native support for a number of different naming policies into systemd/udevd proper and made a scheme similar to biosdevname's (but generally more powerful, and closer to kernel-internal device identification schemes) the default. The following different naming schemes for network interfaces are now supported by udev natively: + +1. Names incorporating Firmware/BIOS provided index numbers for on-board devices (example: `eno1`) +1. Names incorporating Firmware/BIOS provided PCI Express hotplug slot index numbers (example: `ens1`) +1. Names incorporating physical/geographical location of the connector of the hardware (example: `enp2s0`) +1. Names incorporating the interfaces's MAC address (example: `enx78e7d1ea46da`) +1. Classic, unpredictable kernel-native ethX naming (example: `eth0`) + +By default, systemd v197 will now name interfaces following policy 1) if that information from the firmware is applicable and available, falling back to 2) if that information from the firmware is applicable and available, falling back to 3) if applicable, falling back to 5) in all other cases. Policy 4) is not used by default, but is available if the user chooses so. + +This combined policy is only applied as last resort. That means, if the system has biosdevname installed, it will take precedence. If the user has added udev rules which change the name of the kernel devices these will take precedence too. Also, any distribution specific naming schemes generally take precedence. + + +## Come again, what good does this do? + +With this new scheme you now get: + +* Stable interface names across reboots +* Stable interface names even when hardware is added or removed, i.e. no re-enumeration takes place (to the level the firmware permits this) +* Stable interface names when kernels or drivers are updated/changed +* Stable interface names even if you have to replace broken ethernet cards by new ones +* The names are automatically determined without user configuration, they just work +* The interface names are fully predictable, i.e. just by looking at lspci you can figure out what the interface is going to be called +* Fully stateless operation, changing the hardware configuration will not result in changes in /etc +* Compatibility with read-only root +* The network interface naming now follows more closely the scheme used for aliasing block device nodes and other device nodes in /dev via symlinks +* Applicability to both x86 and non-x86 machines +* The same on all distributions that adopted systemd/udev +* It's easy to opt out of the scheme (see below) + +Does this have any drawbacks? Yes, it does. Previously it was practically guaranteed that hosts equipped with a single ethernet card only had a single "eth0" interface. With this new scheme in place, an administrator now has to check first what the local interface name is before he can invoke commands on it where previously he had a good chance that "eth0" was the right name. + + +## I don't like this, how do I disable this? + +You basically have three options: + +1. You disable the assignment of fixed names, so that the unpredictable kernel names are used again. For this, simply mask udev's .link file for the default policy: `ln -s /dev/null /etc/systemd/network/99-default.link` +1. You create your own manual naming scheme, for example by naming your interfaces "internet0", "dmz0" or "lan0". For that create your own .link files in /etc/systemd/network/, that choose an explicit name or a better naming scheme for one, some, or all of your interfaces. See [[systemd.link(5)|http://www.freedesktop.org/software/systemd/man/systemd.link.html]] for more information. +1. You pass the net.ifnames=0 on the kernel command line + +## How does the new naming scheme look like, precisely? + +That's documented in detail in a comment block [[the sources of the net_id built-in|https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-net_id.c#L20]]. Please refer to this in case you are wondering how to decode the new interface names. diff --git a/docs/RANDOM_SEEDS.md b/docs/RANDOM_SEEDS.md new file mode 100644 index 00000000..926238a3 --- /dev/null +++ b/docs/RANDOM_SEEDS.md @@ -0,0 +1,418 @@ +--- +title: Random Seeds +--- + +# Random Seeds + +systemd can help in a number of ways with providing reliable, high quality +random numbers from early boot on. + +## Linux Kernel Entropy Pool + +Today's computer systems require random number generators for numerous +cryptographic and other purposes. On Linux systems, the kernel's entropy pool +is typically used as high-quality source of random numbers. The kernel's +entropy pool combines various entropy inputs together, mixes them and provides +an API to userspace as well as to internal kernel subsystems to retrieve +it. This entropy pool needs to be initialized with a minimal level of entropy +before it can provide high quality, cryptographic random numbers to +applications. Until the entropy pool is fully initialized application requests +for high-quality random numbers cannot be fulfilled. + +The Linux kernel provides three relevant userspace APIs to request random data +from the kernel's entropy pool: + +* The [`getrandom()`](http://man7.org/linux/man-pages/man2/getrandom.2.html) + system call with its `flags` parameter set to 0. If invoked the calling + program will synchronously block until the random pool is fully initialized + and the requested bytes can be provided. + +* The `getrandom()` system call with its `flags` parameter set to + `GRND_NONBLOCK`. If invoked the request for random bytes will fail if the + pool is not initialized yet. + +* Reading from the + [`/dev/urandom`](http://man7.org/linux/man-pages/man4/urandom.4.html) + pseudo-device will always return random bytes immediately, even if the pool + is not initialized. The provided random bytes will be of low quality in this + case however. Moreover the kernel will log about all programs using this + interface in this state, and which thus potentially rely on an uninitialized + entropy pool. + +(Strictly speaking there are more APIs, for example `/dev/random`, but these +should not be used by almost any application and hence aren't mentioned here.) + +Note that the time it takes to initialize the random pool may differ between +systems. If local hardware random number generators are available, +initialization is likely quick, but particularly in embedded and virtualized +environments available entropy is small and thus random pool initialization +might take a long time (up to tens of minutes!). + +Modern hardware tends to come with a number of hardware random number +generators (hwrng), that may be used to relatively quickly fill up the entropy +pool. Specifically: + +* All recent Intel and AMD CPUs provide the CPU opcode + [RDRAND](https://en.wikipedia.org/wiki/RdRand) to acquire random bytes. Linux + includes random bytes generated this way in its entropy pool, but didn't use + to credit entropy for it (i.e. data from this source wasn't considered good + enough to consider the entropy pool properly filled even though it was + used). This has changed recently however, and most big distributions have + turned on the `CONFIG_RANDOM_TRUST_CPU=y` kernel compile time option. This + means systems with CPUs supporting this opcode will be able to very quickly + reach the "pool filled" state. + +* The TPM security chip that is available on all modern desktop systems has a + hwrng. It is also fed into the entropy pool, but generally not credited + entropy. You may use `rng_core.default_quality=1000` on the kernel command + line to change that, but note that this is a global setting affect all + hwrngs. (Yeah, that's weird.) + +* Many Intel and AMD chipsets have hwrng chips. Their Linux drivers usually + don't credit entropy. (But there's `rng_core.default_quality=1000`, see + above.) + +* Various embedded boards have hwrng chips. Some drivers automatically credit + entropy, others do not. Some WiFi chips appear to have hwrng sources too, and + they usually do not credit entropy for them. + +* `virtio-rng` is used in virtualized environments and retrieves random data + from the VM host. It credits full entropy. + +* The EFI firmware typically provides a RNG API. When transitioning from UEFI + to kernel mode Linux will query some random data through it, and feed it into + the pool, but not credit entropy to it. What kind of random source is behind + the EFI RNG API is often not entirely clear, but it hopefully is some kind of + hardware source. + +If neither of these are available (in fact, even if they are), Linux generates +entropy from various non-hwrng sources in various subsystems, all of which +ultimately are rooted in IRQ noise, a very "slow" source of entropy, in +particular in virtualized environments. + +## `systemd`'s Use of Random Numbers + +systemd is responsible for bringing up the OS. It generally runs as the first +userspace process the kernel invokes. Because of that it runs at a time where +the entropy pool is typically not yet initialized, and thus requests to acquire +random bytes will either be delayed, will fail or result in a noisy kernel log +message (see above). + +Various other components run during early boot that require random bytes. For +example, initial RAM disks nowadays communicate with encrypted networks or +access encrypted storage which might need random numbers. systemd itself +requires random numbers as well, including for the following uses: + +* systemd assigns 'invocation' UUIDs to all services it invokes that uniquely + identify each invocation. This is useful retain a global handle on a specific + service invocation and relate it to other data. For example, log data + collected by the journal usually includes the invocation UUID and thus the + runtime context the service manager maintains can be neatly matched up with + the log data a specific service invocation generated. systemd also + initializes `/etc/machine-id` with a randomized UUID. (systemd also makes use + of the randomized "boot id" the kernel exposes in + `/proc/sys/kernel/random/boot_id`). These UUIDs are exclusively Type 4 UUIDs, + i.e. randomly generated ones. + +* systemd maintains various hash tables internally. In order to harden them + against [collision + attacks](https://rt.perl.org/Public/Bug/Display.html?CSRF_Token=165691af9ddaa95f653402f1b68de728) + they are seeded with random numbers. + +* At various places systemd needs random bytes for temporary file name + generation, UID allocation randomization, and similar. + +* systemd-resolved and systemd-networkd use random number generators to harden + the protocols they implement against packet forgery. + +* systemd-udevd and systemd-nspawn can generate randomized MAC addresses for + network devices. + +Note that these cases generally do not require a cryptographic-grade random +number generator, as most of these utilize random numbers to minimize risk of +collision and not to generate secret key material. However, they usually do +require "medium-grade" random data. For example: systemd's hash-maps are +reseeded if they grow beyond certain thresholds (and thus collisions are more +likely). This means they are generally fine with low-quality (even constant) +random numbers initially as long as they get better with time, so that +collision attacks are eventually thwarted as better, non-guessable seeds are +acquired. + +## Keeping `systemd'`s Demand on the Kernel Entropy Pool Minimal + +Since most of systemd's own use of random numbers do not require +cryptographic-grade RNGs, it tries to avoid reading entropy from the kernel +entropy pool if possible. If it succeeds this has the benefit that there's no +need to delay the early boot process until entropy is available, and noisy +kernel log messages about early reading from `/dev/urandom` are avoided +too. Specifically: + +1. When generating [Type 4 + UUIDs](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_\(random\)), + systemd tries to use Intel's and AMD's RDRAND CPU opcode directly, if + available. While some doubt the quality and trustworthiness of the entropy + provided by these opcodes, they should be good enough for generating UUIDs, + if not key material (though, as mentioned, today's big distributions opted + to trust it for that too, now, see above — but we are not going to make that + decision for you, and for anything key material related will only use the + kernel's entropy pool). If RDRAND is not available or doesn't work, it will + use synchronous `getrandom()` as fallback, and `/dev/urandom` on old kernels + where that system call doesn't exist yet. This means on non-Intel/AMD + systems UUID generation will block on kernel entropy initialization. + +2. For seeding hash tables, and all the other similar purposes systemd first + tries RDRAND, and if that's not available will try to use asynchronous + `getrandom()` (if the kernel doesn't support this system call, + `/dev/urandom` is used). This may fail too in case the pool is not + initialized yet, in which case it will fall back to glibc's internal rand() + calls, i.e. weak pseudo-random numbers. This should make sure we use good + random bytes if we can, but neither delay boot nor trigger noisy kernel log + messages during early boot for these use-cases. + +## `systemd`'s Support for Filling the Kernel Entropy Pool + +systemd has various provisions to ensure the kernel entropy is filled during +boot, in order to ensure the entropy pool is filled up quickly. + +1. When systemd's PID 1 detects it runs in a virtualized environment providing + the `virtio-rng` interface it will load the necessary kernel modules to make + use of it during earliest boot, if possible — much earlier than regular + kernel module loading done by `systemd-udevd.service`. This should ensure + that in VM environments the entropy pool is quickly filled, even before + systemd invokes the first service process — as long as the VM environment + provides virtualized RNG hardware (and VM environments really should!). + +2. The + [`systemd-random-seed.service`](https://www.freedesktop.org/software/systemd/man/systemd-random-seed.service.html) + system service will load a random seed from `/var/lib/systemd/random-seed` + into the kernel entropy pool. By default it does not credit entropy for it + though, since the seed is — more often than not — not reset when 'golden' + master images of an OS are created, and thus replicated into every + installation. If OS image builders carefully reset the random seed file + before generating the image it should be safe to credit entropy, which can + be enabled by setting the `$SYSTEMD_RANDOM_SEED_CREDIT` environment variable + for the service to `1` (or even `force`, see man page). Note however, that + this service typically runs relatively late during early boot: long after + the initial RAM disk (`initrd`) completed, and after the `/var/` file system + became writable. This is usually too late for many applications, it is hence + not advised to rely exclusively on this functionality to seed the kernel's + entropy pool. Also note that this service synchronously waits until the + kernel's entropy pool is initialized before completing start-up. It may thus + be used by other services as synchronization point to order against, if they + require an initialized entropy pool to operate correctly. + +3. The + [`systemd-boot`](https://www.freedesktop.org/software/systemd/man/systemd-boot.html) + EFI boot loader included in systemd is able to maintain and provide a random + seed stored in the EFI System Partition (ESP) to the booted OS, which allows + booting up with a fully initialized entropy pool from earliest boot + on. During installation of the boot loader (or when invoking [`bootctl + random-seed`](https://www.freedesktop.org/software/systemd/man/bootctl.html#random-seed)) + a seed file with an initial seed is placed in a file `/loader/random-seed` + in the ESP. In addition, an identically sized randomized EFI variable called + the the 'system token' is set, which is written to the machine's firmware + NVRAM. During boot, when `systemd-boot` finds both the random seed file and + the system token they are combined and hashed with SHA256 (in counter mode, + to generate sufficient data), to generate a new random seed file to store in + the ESP as well as a random seed to pass to the OS kernel. The new random + seed file for the ESP is then written to the ESP, ensuring this is completed + before the OS is invoked. Very early during initialization PID 1 will read + the random seed provided in the EFI variable and credit it fully to the + kernel's entropy pool. + + This mechanism is able to safely provide an initialized entropy pool already + in the `initrd` and guarantees that different seeds are passed from the boot + loader to the OS on every boot (in a way that does not allow regeneration of + an old seed file from a new seed file). Moreover, when an OS image is + replicated between multiple images and the random seed is not reset, this + will still result in different random seeds being passed to the OS, as the + per-machine 'system token' is specific to the physical host, and not + included in OS disk images. If the 'system token' is properly initialized + and kept sufficiently secret it should not be possible to regenerate the + entropy pool of different machines, even if this seed is the only source of + entropy. + + Note that the writes to the ESP needed to maintain the random seed should be + minimal. The size of the random seed file is directly derived from the Linux + kernel's entropy pool size, which defaults to 512 bytes. This means updating + the random seed in the ESP should be doable safely with a single sector + write (since hard-disk sectors typically happen to be 512 bytes long, too), + which should be safe even with FAT file system drivers built into + low-quality EFI firmwares. + + As a special restriction: in virtualized environments PID 1 will refrain + from using this mechanism, for safety reasons. This is because on VM + environments the EFI variable space and the disk space is generally not + maintained physically separate (for example, `qemu` in EFI mode stores the + variables in the ESP itself). The robustness towards sloppy OS image + generation is the main purpose of maintaining the 'system token' however, + and if the EFI variable storage is not kept physically separate from the OS + image there's no point in it. That said, OS builders that know that they are + not going to replicate the built image on multiple systems may opt to turn + off the 'system token' concept by setting `random-seed-mode always` in the + ESP's + [`/loader/loader.conf`](https://www.freedesktop.org/software/systemd/man/loader.conf.html) + file. If done, `systemd-boot` will use the random seed file even if no + system token is found in EFI variables. + +With the three mechanisms described above it should be possible to provide +early-boot entropy in most cases. Specifically: + +1. On EFI systems, `systemd-boot`'s random seed logic should make sure good + entropy is available during earliest boot — as long as `systemd-boot` is + used as boot loader, and outside of virtualized environments. + +2. On virtualized systems, the early `virtio-rng` hookup should ensure entropy + is available early on — as long as the VM environment provides virtualized + RNG devices, which they really should all do in 2019. Complain to your + hosting provider if they don't. + +3. On Intel/AMD systems systemd's own reliance on the kernel entropy pool is + minimal (as RDRAND is used on those for UUID generation). This only works if + the CPU has RDRAND of course, which most physical CPUs do (but I hear many + virtualized CPUs do not. Pity.) + +4. In all other cases, `systemd-random-seed.service` will help a bit, but — as + mentioned — is too late to help with early boot. + +This primarily leaves two kind of systems in the cold: + +1. Some embedded systems. Many embedded chipsets have hwrng functionality these + days. Consider using them while crediting + entropy. (i.e. `rng_core.default_quality=1000` on the kernel command line is + your friend). Or accept that the system might take a bit longer to + boot. Alternatively, consider implementing a solution similar to + systemd-boot's random seed concept in your platform's boot loader. + +2. Virtualized environments that lack both virtio-rng and RDRAND. Tough + luck. Talk to your hosting provider, and ask them to fix this. + +3. Also note: if you deploy an image without any random seed and/or without + installing any 'system token' in an EFI variable, as described above, this + means that on the first boot no seed can be passed to the OS + either. However, as the boot completes (with entropy acquired elsewhere), + systemd will automatically install both a random seed in the GPT and a + 'system token' in the EFI variable space, so that any future boots will have + entropy from earliest boot on — all provided `systemd-boot` is used. + +## Frequently Asked Questions + +1. *Why don't you just use getrandom()? That's all you need!* + + Did you read any of the above? getrandom() is hooked to the kernel entropy + pool, and during early boot it's not going to be filled yet, very likely. We + do use it in many cases, but not in all. Please read the above again! + +2. *Why don't you use + [getentropy()](http://man7.org/linux/man-pages/man3/getentropy.3.html)? That's + all you need!* + + Same story. That call is just a different name for `getrandom()` with + `flags` set to zero, and some additional limitations, and thus it also needs + the kernel's entropy pool to be initialized, which is the whole problem we + are trying to address here. + +3. *Why don't you generate your UUIDs with + [`uuidd`](http://man7.org/linux/man-pages/man8/uuidd.8.html)? That's all you + need!* + + First of all, that's a system service, i.e. something that runs as "payload" + of systemd, long after systemd is already up and hence can't provide us + UUIDs during earliest boot yet. Don't forget: to assign the invocation UUID + for the `uuidd.service` start we already need a UUID that the service is + supposed to provide us. More importantly though, `uuidd` needs state/a random + seed/a MAC address/host ID to operate, all of which are not available during + early boot. + +4. *Why don't you generate your UUIDs with `/proc/sys/kernel/random/uuid`? + That's all you need!* + + This is just a different, more limited interface to `/dev/urandom`. It gains + us nothing. + +5. *Why don't you use [`rngd`](https://github.com/nhorman/rng-tools), + [`haveged`](http://www.issihosts.com/haveged/), + [`egd`](http://egd.sourceforge.net/)? That's all you need!* + + Like `uuidd` above these are system services, hence come too late for our + use-case. In addition much of what `rngd` provides appears to be equivalent + to `CONFIG_RANDOM_TRUST_CPU=y` or `rng_core.default_quality=1000`, except + being more complex and involving userspace. These services partly measure + system behavior (such as scheduling effects) which the kernel either + already feeds into its pool anyway (and thus shouldn't be fed into it a + second time, crediting entropy for it a second time) or is at least + something the kernel could much better do on its own. Hence, if what these + daemons do is still desirable today, this would be much better implemented + in kernel (which would be very welcome of course, but wouldn't really help + us here in our specific problem, see above). + +6. *Why don't you use [`arc4random()`](https://man.openbsd.org/arc4random.3)? + That's all you need!* + + This doesn't solve the issue, since it requires a nonce to start from, and + it gets that from `getrandom()`, and thus we have to wait for random pool + initialization the same way as calling `getrandom()` + directly. `arc4random()` is nothing more than optimization, in fact it + implements similar algorithms that the kernel entropy pool implements + anyway, hence besides being able to provide random bytes with higher + throughput there's little it gets us over just using `getrandom()`. Also, + it's not supported by glibc. And as long as that's the case we are not keen + on using it, as we'd have to maintain that on our own, and we don't want to + maintain our own cryptographic primitives if we don't have to. Since + systemd's uses are not performance relevant (besides the pool initialization + delay, which this doesn't solve), there's hence little benefit for us to + call these functions. That said, if glibc learns these APIs one day, we'll + certainly make use of them where appropriate. + +7. *This is boring: NetBSD had [boot loader entropy seed + support](https://netbsd.gw.com/cgi-bin/man-cgi?boot+8) since ages!* + + Yes, NetBSD has that, and the above is inspired by that (note though: this + article is about a lot more than that). NetBSD's support is not really safe, + since it neither updates the random seed before using it, nor has any + safeguards against replicating the same disk image with its random seed on + multiple machines (which the 'system token' mentioned above is supposed to + address). This means reuse of the same random seed by the boot loader is + much more likely. + +8. *Why does PID 1 upload the boot loader provided random seed into kernel + instead of kernel doing that on its own?* + + That's a good question. Ideally the kernel would do that on its own, and we + wouldn't have to involve userspace in this. + +9. *What about non-EFI?* + + The boot loader random seed logic described above uses EFI variables to pass + the seed from the boot loader to the OS. Other systems might have similar + functionality though, and it shouldn't be too hard to implement something + similar for them. Ideally, we'd have an official way to pass such a seed as + part of the `struct boot_params` from the boot loader to the kernel, but + this is currently not available. + +10. *I use a different boot loader than `systemd-boot`, I'd like to use boot + loader random seeds too!* + + Well, consider just switching to `systemd-boot`, it's worth it. See + [systemd-boot(7)](https://www.freedesktop.org/software/systemd/man/systemd-boot.html) + for an introduction why. That said, any boot loader can re-implement the + logic described above, and can pass a random seed that systemd as PID 1 + will then upload into the kernel's entropy pool. For details see the [Boot + Loader Interface](https://systemd.io/BOOT_LOADER_INTERFACE) documentation. + +11. *Why not pass the boot loader random seed via kernel command line instead + of as EFI variable?* + + The kernel command line is accessible to unprivileged processes via + `/proc/cmdline`. It's not desirable if unprivileged processes can use this + information to possibly gain too much information about the current state + of the kernel's entropy pool. + +12. *Why doesn't `systemd-boot` rewrite the 'system token' too each time + when updating the random seed file stored in the ESP?* + + The system token is stored as persistent EFI variable, i.e. in some form of + NVRAM. These memory chips tend be of low quality in many machines, and + hence we shouldn't write them too often. Writing them once during + installation should generally be OK, but rewriting them on every single + boot would probably wear the chip out too much, and we shouldn't risk that. diff --git a/docs/RELEASE.md b/docs/RELEASE.md new file mode 100644 index 00000000..56debd68 --- /dev/null +++ b/docs/RELEASE.md @@ -0,0 +1,19 @@ +--- +title: Steps to a Successful Release +--- + +# Steps to a Successful Release + +1. Add all items to NEWS +2. Update the contributors list in NEWS (`ninja -C build git-contrib`) +3. Update the time and place in NEWS +4. Update version and library numbers in `meson.build` +5. Tag the release: `version=vXXX-rcY && git tag -s "${version}" -m "systemd ${version}"` +6. Do `ninja -C build` +7. Make sure that the version string and package string match: `build/systemctl --version` +8. Upload the documentation: `ninja -C build doc-sync` +9. [After final release] Close the github milestone and open a new one (https://github.com/systemd/systemd/milestones) +10. "Draft" a new release on github (https://github.com/systemd/systemd/releases/new), mark "This is a pre-release" if appropriate. +11. Check that announcement to systemd-devel, with a copy&paste from NEWS, was sent. This should happen automatically. +12. Update IRC topic (`/msg chanserv TOPIC #systemd Version NNN released`) +13. [After final release] Also push commits to stable, create an empty -stable branch: `git push systemd-stable origin/master:master origin/master:refs/heads/${version}-stable`, and change the default branch to latest release (https://github.com/systemd/systemd-stable/settings/branches). diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 00000000..93847dcd --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,7 @@ +--- +title: Reporting of security vulnerabilities +--- + +# Reporting of security vulnerabilities + +If you discover a security vulnerability, we'd appreciate a non-public disclosure. The [issue tracker](https://github.com/systemd/systemd/issues) and [systemd-devel mailing list](https://lists.freedesktop.org/mailman/listinfo/systemd-devel) are fully public. If you need to reach systemd developers in a non-public way, report the issue to the [systemd-security@redhat.com](mailto:systemd-security@redhat.com) mailing list. The disclosure will be coordinated with distributions. diff --git a/docs/TEMPORARY_DIRECTORIES.md b/docs/TEMPORARY_DIRECTORIES.md new file mode 100644 index 00000000..9271e0e4 --- /dev/null +++ b/docs/TEMPORARY_DIRECTORIES.md @@ -0,0 +1,220 @@ +--- +title: Using /tmp/ And /var/tmp/ Safely +--- + +# Using `/tmp/` And `/var/tmp/` Safely + +`/tmp/` and `/var/tmp/` are two world-writable directories Linux systems +provide for temporary files. The former is typically on `tmpfs` and thus +backed by RAM/swap, and flushed out on each reboot. The latter is typically a +proper, persistent file system, and thus backed by physical storage. This +means: + +1. `/tmp/` should be used for smaller, size-bounded files only; `/var/tmp/` + should be used for everything else. + +2. Data that shall survive a boot cycle shouldn't be placed in `/tmp/`. + +If the `$TMPDIR` environment variable is set, use that path, and neither use +`/tmp/` nor `/var/tmp/` directly. + +See +[file-hierarchy(7)](https://www.freedesktop.org/software/systemd/man/file-hierarchy.html) +for details about these two (and most other) directories of a Linux system. + +## Common Namespace + +Note that `/tmp/` and `/var/tmp/` each define a common namespace shared by all +local software. This means guessable file or directory names below either +directory directly translate into a 🚨 Denial-of-Service (DoS) 🚨 vulnerability +or worse: if some software creates a file or directory `/tmp/foo` then any +other software that wants to create the same file or directory `/tmp/foo` +either will fail (as the file already exists) or might be tricked into using +untrusted files. Hence: do not use guessable names in `/tmp/` or `/var/tmp/` — +if you do you open yourself up to a local DoS exploit or worse. (You can get +away with using guessable names, if you pre-create subdirectories below `/tmp/` +for them, like X11 does with `/tmp/.X11-unix/` through `tmpfiles.d/` +drop-ins. However this is not recommended, as it is fully safe only if these +directories are pre-created during early boot, and thus problematic if package +installation during runtime is permitted.) + +To protect yourself against these kinds of attacks Linux provides a couple of +APIs that help you avoiding guessable names. Specifically: + +1. Use [`mkstemp()`](http://man7.org/linux/man-pages/man3/mkstemp.3.html) + (POSIX), `mkostemp()` (glibc), + [`mkdtemp()`](http://man7.org/linux/man-pages/man3/mkdtemp.3.html) (POSIX), + [`tmpfile()`](http://man7.org/linux/man-pages/man3/tmpfile.3.html) (C89) + +2. Use [`open()`](http://man7.org/linux/man-pages/man2/open.2.html) with + `O_TMPFILE` (Linux) + +3. [`memfd_create()`](http://man7.org/linux/man-pages/man2/memfd_create.2.html) + (Linux; this doesn't bother with `/tmp/` or `/var/tmp/` at all, but uses the + same RAM/swap backing as `tmpfs` uses, hence is very similar to `/tmp/` + semantics.) + +For system services systemd provides the `PrivateTmp=` boolean setting. If +turned on for a service (👍 which is highly recommended), `/tmp/` and +`/var/tmp/` are replaced by private sub-directories, implemented through Linux +file system namespacing and bind mounts. This means from the service's point of +view `/tmp/` and `/var/tmp/` look and behave like they normally do, but in +reality they are private sub-directories of the host's real `/tmp/` and +`/var/tmp/`, and thus not system-wide locations anymore, but service-specific +ones. This reduces the surface for local DoS attacks substantially. While it is +recommended to turn this option on, it's highly recommended for applications +not to rely on this solely to avoid DoS vulnerabilities, because this option is +not available in environments where file system namespaces are prohibited, for +example in certain container environments. This option is hence an extra line +of defense, but should not be used as an excuse to rely on guessable names in +`/tmp/` and `/var/tmp/`. When this option is used, the per-service temporary +directories are removed whenever the service shuts down, hence the lifecycle of +temporary files stored in it is substantially different from the case where +this option is not used. Also note that some applications use `/tmp/` and +`/var/tmp/` for sharing files and directories. If this option is turned on this +is not possible anymore as after all each service gets its own instances of +both directories. + +## Automatic Clean-Up + +By default, `systemd-tmpfiles` will apply a concept of ⚠️ "ageing" to all files +and directories stored in `/tmp/` and `/var/tmp/`. This means that files that +have neither been changed nor read within a specific time frame are +automatically removed in regular intervals. (This concept is not new to +`systemd-tmpfiles` btw, it's inherited from previous subsystems such as +`tmpwatch`.) By default files in `/tmp/` are cleaned up after 10 days, and +those in `/var/tmp` after 30 days. + +This automatic clean-up is important to ensure disk usage of these temporary +directories doesn't grow without bounds, even when programs abort unexpectedly +or otherwise don't clean up the temporary files/directories they create. On the +other hand it creates problems for long-running software that does not expect +temporary files it operates on to be suddenly removed. There are a couple of +strategies to avoid these issues: + +1. Make sure to always keep a file descriptor to the temporary files you + operate on open, and only access the files through them. This way it doesn't + matter whether the files have been unlinked from the file system: as long as + you have the file descriptor open you can still access the file for both + reading and writing. When operating this way it is recommended to delete the + files right after creating them to ensure that on unexpected program + termination the files or directories are implicitly released by the kernel. + +2. 🥇 Use `memfd_create()` or `O_TMPFILE`. This is an extension of the + suggestion above: files created this way are never linked under a filename + in the file system. This means they are not subject to ageing (as they come + unlinked out of the box), and there's no time window where a directory entry + for the file exists in the file system, and thus behaviour is fully robust + towards unexpected program termination as there are never files on disk that + need to be explicitly deleted. + +3. 🥇 Operate below a sub-directory of `/tmp/` and `/var/tmp/` you created, and + take a BSD file lock ([`flock(dir_fd, + LOCK_SH)`](http://man7.org/linux/man-pages/man2/flock.2.html)) on that + sub-directory. This is particularly interesting when operating on more than + a single file, or on file nodes that are not plain regular files, for + example when extracting a tarball to a temporary directory. The ageing + algorithm will skip all directories (and everything below them) that are + locked through a BSD file lock. As BSD file locks are automatically released + when the file descriptor they are taken on is closed, and all file + descriptors opened by a process are implicitly closed when it exits, this is + a robust mechanism that ensures all temporary files are subject to ageing + when the program that owns them dies, but not while it is still running. Use + this when decompressing tarballs that contain files with old + modification/access times, as extracted files are otherwise immediately + candidates for deletion by the ageing algorithm. The + [`flock`](http://man7.org/linux/man-pages/man1/flock.1.html) tool of the + `util-linux` packages makes this concept available to shell scripts. Note + that `systemd-tmpfiles` only checks for BSD file locks on directories, locks + on other types of file nodes (including regular files) are not considered. + +4. Keep the access time of all temporary files created current. In regular + intervals, use `utimensat()` or a related call to update the access time + ("atime") of all files that shall be kept around. Since the ageing algorithm + looks at the access time of files when deciding whether to delete them, it's + sufficient to update their access times in sufficiently frequent intervals to + ensure the files are not deleted. Since most applications (and tools such as + `ls`) primarily care for the modification time (rather than the access time) + using the access time for this purpose should be acceptable. + +5. Set the "sticky" bit on regular files. The ageing logic skips deletion of + all regular files that have the sticky bit (`chmod +t`) set. This is + honoured for regular files only however, and has no effect on directories as + the sticky bit has a different meaning for them. + +6. Don't use `/tmp/` or `/var/tmp/`, but use your own sub-directory under + `/run/` or `$XDG_RUNTIME_DIRECTORY` (the former if privileged, the latter if + unprivileged), or `/var/lib/` and `~/.config/` (similar, but with + persistency and suitable for larger data). The two temporary directories + `/tmp/` and `/var/tmp/` come with the implicit clean-up semantics described + above. When this is not desired, it's possible to create private per-package + runtime or state directories, and place all temporary files there. However, + do note that this means opting out of any kind of automatic clean-up, and it + is hence particularly essential that the program cleans up generated files + in these directories when they are no longer needed, in particular when the + program dies unexpectedly. Note: this strategy is only really suitable for + packages that operate in a "system wide singleton" fashion with "long" + persistence of its data or state, i.e. as opposed to programs that run in + multiple parallel or short-living instances. This is because a private + directory under `/run` (and the other mentioned directories) is itself + system and package specific singleton with greater longevity. + +5. Exclude your temporary files from clean-ups via a `tmpfiles.d/` drop-in + (which includes drop-ins in the runtime-only directory + `/run/tmpfiles.d/`). The `x`/`X` line types may be used to exclude files + matching the specified globbing patterns from the ageing logic. If this is + used, automatic clean-up is not done for matching files and directory, and + much like with the previous option it's hence essential that the program + generating these temporary files carefully removes the temporary files it + creates again, and in particular so if it dies unexpectedly. + +🥇 The semantics of options 2 (in case you only deal with temporary files, not +directories) and 3 (in case you deal with both) in the list above are in most +cases the most preferable. It is thus recommended to stick to these two +options. + +While the ageing logic is very useful as a safety concept to ensure unused +files and directories are eventually removed a well written program avoids even +creating files that need such a clean-up. In particular: + +1. Use `memfd_create()` or `O_TMPFILE` when creating temporary files. + +2. `unlink()` temporary files right after creating them. This is very similar + to `O_TMPFILE` behaviour: consider deleting temporary files right after + creating them, while keeping open a file descriptor to them. Unlike + `O_TMPFILE` this method also works on older Linux systems and other OSes + that do not implement `O_TMPFILE`. + +## Disk Quota + +Generally, files allocated from `/tmp/` and `/var/tmp/` are allocated from a +pool shared by all local users. Moreover the space available in `/tmp/` is +generally more restricted than `/var/tmp/`. This means, that in particular in +`/tmp/` space should be considered scarce, and programs need to be prepared +that no space is available. Essential programs might require a fallback logic +using a different location for storing temporary files hence. Non-essential +programs at least need to be prepared for `ENOSPC` errors and generate useful, +actionable error messages. + +Some setups employ per-user quota on `/var/tmp/` and possibly `/tmp/`, to make +`ENOSPC` situations less likely, and harder to trigger from unprivileged +users. However, in the general case no such per-user quota is implemented +though, in particular not when `tmpfs` is used as backing file system, because +— even today — `tmpfs` still provides no native quota support in the kernel. + +## Early Boot Considerations + +Both `/tmp/` and `/var/tmp/` are not necessarily available during early boot, +or — if they are available early — are not writable. This means software that +is intended to run during early boot (i.e. before `basic.target` — or more +specifically `local-fs.target` — is up) should not attempt to make use of +either. Interfaces such as `memfd_create()` or files below a package-specific +directory in `/run/` are much better options in this case. (Note that some +packages instead use `/dev/shm/` for temporary files during early boot; this is +not advisable however, as it offers no benefits over a private directory in +`/run/` as both are backed by the same concept: `tmpfs`. The directory +`/dev/shm/` exists to back POSIX shared memory (see +[`shm_open()`](http://man7.org/linux/man-pages/man3/shm_open.3.html) and +related calls), and not as a place for temporary files. `/dev/shm` is +problematic as it is world-writable and there's no automatic clean-up logic in +place.) diff --git a/docs/TESTING_WITH_SANITIZERS.md b/docs/TESTING_WITH_SANITIZERS.md new file mode 100644 index 00000000..7cb879aa --- /dev/null +++ b/docs/TESTING_WITH_SANITIZERS.md @@ -0,0 +1,88 @@ +--- +title: Testing systemd using sanitizers +--- + +# Testing systemd using sanitizers + +To catch the *nastier* kind of bugs, you can run your code with [Address Sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html) +and [Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html). +This is mostly done automagically by various CI systems for each PR, but you may +want to do it locally as well. The process slightly varies depending on the +compiler you want to use and which part of the test suite you want to run. + +## gcc +gcc compiles in sanitizer libraries dynamically by default, so you need to get +the shared libraries first - on Fedora these are shipped as a separate packages +(`libasan` for Address Sanitizer and `libubsan` for Undefined Behavior Sanitizer). + +The compilation itself is then a matter of simply adding `-Db_sanitize=address,undefined` +to `meson`. That's it - following executions of `meson test` and integrations tests +under `test/` subdirectory will run with sanitizers enabled. However, to get +truly useful results, you should tweak the runtime configuration of respective +sanitizers; e.g. in systemd we set the following environment variables: + +```bash +ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 +UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 +``` +## clang +In case of clang things are somewhat different - the sanitizer libraries are +compiled in statically by default. This is not an issue if you plan to run +only the unit tests, but for integration tests you'll need to convince clang +to use the dynamic versions of sanitizer libraries. + +First of all, pass `-shared-libsan` to both `clang` and `clang++`: + +```bash +CFLAGS=-shared-libasan +CXXFLAGS=-shared-libasan +``` + +The `CXXFLAGS` are necessary for `src/libsystemd/sd-bus/test-bus-vtable-cc.c`. Compilation +is then the same as in case of gcc, simply add `-Db_sanitize=address,undefined` +to the `meson` call and use the same environment variables for runtime configuration. + +```bash +ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 +UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 +``` + +After this, you'll probably notice that all compiled binaries complain about +missing `libclang_rt.asan*` library. To fix this, you have to install clang's +runtime libraries, usually shipped in the `compiler-rt` package. As these libraries +are installed in a non-standard location (non-standard for `ldconfig`), you'll +need to manually direct binaries to the respective runtime libraries. + +``` +# Optionally locate the respective runtime DSO +$ ldd build/systemd | grep libclang_rt.asan + libclang_rt.asan-x86_64.so => not found + libclang_rt.asan-x86_64.so => not found +$ find /usr/lib* /usr/local/lib* -type f -name libclang_rt.asan-x86_64.so 2>/dev/null +/usr/lib64/clang/7.0.1/lib/libclang_rt.asan-x86_64.so + +# Set the LD_LIBRARY_PATH accordingly +export LD_LIBRARY_PATH=/usr/lib64/clang/7.0.1/lib/ + +# If the path is correct, the "not found" message should change to an actual path +$ ldd build/systemd | grep libclang_rt.asan + libclang_rt.asan-x86_64.so => /usr/lib64/clang/7.0.1/lib/libclang_rt.asan-x86_64.so (0x00007fa9752fc000) +``` + +This should help binaries to correctly find necessary sanitizer DSOs. + +Also, to make the reports useful, `llvm-symbolizer` tool is required (usually +part of the `llvm` package). + +## Background notes +The reason why you need to force dynamic linking in case of `clang` is that some +applications make use of `libsystemd`, which is compiled with sanitizers as well. +However, if a *standard* (uninstrumented) application loads an instrumented library, +it will immediately fail due to unresolved symbols. To fix/workaround this, you +need to pre-load the ASan DSO using `LD_PRELOAD=/path/to/asan/dso`, which will +make things work as expected in most cases. This will, obviously, not work with +statically linked sanitizer libraries. + +These shenanigans are performed automatically when running the integration test +suite (i.e. `test/TEST-??-*`) and are located in `test/test-functions` (mainly, +but not only, in the `create_asan_wrapper` function). diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md new file mode 100644 index 00000000..6cbd03e1 --- /dev/null +++ b/docs/TRANSIENT-SETTINGS.md @@ -0,0 +1,479 @@ +--- +title: What settings are currently available for transient units? +--- + +# What settings are currently available for transient units? + +Our intention is to make all settings that are available as unit file settings +also available for transient units, through the D-Bus API. At the moment, +device, swap, and target units are not supported at all as transient units, but +others are pretty well supported. + +The lists below contain all settings currently available in unit files. The +ones currently available in transient units are prefixed with `✓`. + +## Generic Unit Settings + +Most generic unit settings are available for transient units. + +``` +✓ Description= +✓ Documentation= +✓ SourcePath= +✓ Requires= +✓ Requisite= +✓ Wants= +✓ BindsTo= +✓ Conflicts= +✓ Before= +✓ After= +✓ OnFailure= +✓ PropagatesReloadTo= +✓ ReloadPropagatedFrom= +✓ PartOf= +✓ JoinsNamespaceOf= +✓ RequiresMountsFor= +✓ StopWhenUnneeded= +✓ RefuseManualStart= +✓ RefuseManualStop= +✓ AllowIsolate= +✓ DefaultDependencies= +✓ OnFailureJobMode= +✓ IgnoreOnIsolate= +✓ JobTimeoutSec= +✓ JobRunningTimeoutSec= +✓ JobTimeoutAction= +✓ JobTimeoutRebootArgument= +✓ StartLimitIntervalSec= +✓ StartLimitBurst= +✓ StartLimitAction= +✓ FailureAction= +✓ SuccessAction= +✓ FailureActionExitStatus= +✓ SuccessActionExitStatus= +✓ RebootArgument= +✓ ConditionPathExists= +✓ ConditionPathExistsGlob= +✓ ConditionPathIsDirectory= +✓ ConditionPathIsSymbolicLink= +✓ ConditionPathIsMountPoint= +✓ ConditionPathIsReadWrite= +✓ ConditionDirectoryNotEmpty= +✓ ConditionFileNotEmpty= +✓ ConditionFileIsExecutable= +✓ ConditionNeedsUpdate= +✓ ConditionFirstBoot= +✓ ConditionKernelCommandLine= +✓ ConditionKernelVersion= +✓ ConditionArchitecture= +✓ ConditionVirtualization= +✓ ConditionSecurity= +✓ ConditionCapability= +✓ ConditionHost= +✓ ConditionACPower= +✓ ConditionUser= +✓ ConditionGroup= +✓ ConditionControlGroupController= +✓ AssertPathExists= +✓ AssertPathExistsGlob= +✓ AssertPathIsDirectory= +✓ AssertPathIsSymbolicLink= +✓ AssertPathIsMountPoint= +✓ AssertPathIsReadWrite= +✓ AssertDirectoryNotEmpty= +✓ AssertFileNotEmpty= +✓ AssertFileIsExecutable= +✓ AssertNeedsUpdate= +✓ AssertFirstBoot= +✓ AssertKernelCommandLine= +✓ AssertKernelVersion= +✓ AssertArchitecture= +✓ AssertVirtualization= +✓ AssertSecurity= +✓ AssertCapability= +✓ AssertHost= +✓ AssertACPower= +✓ AssertUser= +✓ AssertGroup= +✓ AssertControlGroupController= +✓ CollectMode= +``` + +## Execution-Related Settings + +All execution-related settings are available for transient units. + +``` +✓ WorkingDirectory= +✓ RootDirectory= +✓ RootImage= +✓ User= +✓ Group= +✓ SupplementaryGroups= +✓ Nice= +✓ OOMScoreAdjust= +✓ IOSchedulingClass= +✓ IOSchedulingPriority= +✓ CPUSchedulingPolicy= +✓ CPUSchedulingPriority= +✓ CPUSchedulingResetOnFork= +✓ CPUAffinity= +✓ UMask= +✓ Environment= +✓ EnvironmentFile= +✓ PassEnvironment= +✓ UnsetEnvironment= +✓ DynamicUser= +✓ RemoveIPC= +✓ StandardInput= +✓ StandardOutput= +✓ StandardError= +✓ StandardInputText= +✓ StandardInputData= +✓ TTYPath= +✓ TTYReset= +✓ TTYVHangup= +✓ TTYVTDisallocate= +✓ SyslogIdentifier= +✓ SyslogFacility= +✓ SyslogLevel= +✓ SyslogLevelPrefix= +✓ LogLevelMax= +✓ LogExtraFields= +✓ LogRateLimitIntervalSec= +✓ LogRateLimitBurst= +✓ SecureBits= +✓ CapabilityBoundingSet= +✓ AmbientCapabilities= +✓ TimerSlackNSec= +✓ NoNewPrivileges= +✓ KeyringMode= +✓ SystemCallFilter= +✓ SystemCallArchitectures= +✓ SystemCallErrorNumber= +✓ MemoryDenyWriteExecute= +✓ RestrictNamespaces= +✓ RestrictRealtime= +✓ RestrictSUIDSGID= +✓ RestrictAddressFamilies= +✓ LockPersonality= +✓ LimitCPU= +✓ LimitFSIZE= +✓ LimitDATA= +✓ LimitSTACK= +✓ LimitCORE= +✓ LimitRSS= +✓ LimitNOFILE= +✓ LimitAS= +✓ LimitNPROC= +✓ LimitMEMLOCK= +✓ LimitLOCKS= +✓ LimitSIGPENDING= +✓ LimitMSGQUEUE= +✓ LimitNICE= +✓ LimitRTPRIO= +✓ LimitRTTIME= +✓ ReadWritePaths= +✓ ReadOnlyPaths= +✓ InaccessiblePaths= +✓ BindPaths= +✓ BindReadOnlyPaths= +✓ TemporaryFileSystem= +✓ PrivateTmp= +✓ PrivateDevices= +✓ PrivateMounts= +✓ ProtectKernelTunables= +✓ ProtectKernelModules= +✓ ProtectKernelLogs= +✓ ProtectControlGroups= +✓ PrivateNetwork= +✓ PrivateUsers= +✓ ProtectSystem= +✓ ProtectHome= +✓ MountFlags= +✓ MountAPIVFS= +✓ Personality= +✓ RuntimeDirectoryPreserve= +✓ RuntimeDirectoryMode= +✓ RuntimeDirectory= +✓ StateDirectoryMode= +✓ StateDirectory= +✓ CacheDirectoryMode= +✓ CacheDirectory= +✓ LogsDirectoryMode= +✓ LogsDirectory= +✓ ConfigurationDirectoryMode= +✓ ConfigurationDirectory= +✓ PAMName= +✓ IgnoreSIGPIPE= +✓ UtmpIdentifier= +✓ UtmpMode= +✓ SELinuxContext= +✓ SmackProcessLabel= +✓ AppArmorProfile= +✓ Slice= +``` + +## Resource Control Settings + +All cgroup/resource control settings are available for transient units + +``` +✓ CPUAccounting= +✓ CPUWeight= +✓ StartupCPUWeight= +✓ CPUShares= +✓ StartupCPUShares= +✓ CPUQuota= +✓ CPUQuotaPeriodSec= +✓ AllowedCPUs= +✓ AllowedMemoryNodes= +✓ MemoryAccounting= +✓ DefaultMemoryMin= +✓ MemoryMin= +✓ DefaultMemoryLow= +✓ MemoryLow= +✓ MemoryHigh= +✓ MemoryMax= +✓ MemorySwapMax= +✓ MemoryLimit= +✓ DeviceAllow= +✓ DevicePolicy= +✓ IOAccounting= +✓ IOWeight= +✓ StartupIOWeight= +✓ IODeviceWeight= +✓ IOReadBandwidthMax= +✓ IOWriteBandwidthMax= +✓ IOReadIOPSMax= +✓ IOWriteIOPSMax= +✓ BlockIOAccounting= +✓ BlockIOWeight= +✓ StartupBlockIOWeight= +✓ BlockIODeviceWeight= +✓ BlockIOReadBandwidth= +✓ BlockIOWriteBandwidth= +✓ TasksAccounting= +✓ TasksMax= +✓ Delegate= +✓ DisableControllers= +✓ IPAccounting= +✓ IPAddressAllow= +✓ IPAddressDeny= +``` + +## Process Killing Settings + +All process killing settings are available for transient units: + +``` +✓ SendSIGKILL= +✓ SendSIGHUP= +✓ KillMode= +✓ KillSignal= +✓ RestartKillSignal= +✓ FinalKillSignal= +✓ WatchdogSignal= +``` + +## Service Unit Settings + +Most service unit settings are available for transient units. + +``` +✓ PIDFile= +✓ ExecCondition= +✓ ExecStartPre= +✓ ExecStart= +✓ ExecStartPost= +✓ ExecReload= +✓ ExecStop= +✓ ExecStopPost= +✓ RestartSec= +✓ TimeoutStartSec= +✓ TimeoutStopSec= +✓ TimeoutAbortSec= +✓ TimeoutSec= +✓ RuntimeMaxSec= +✓ WatchdogSec= +✓ Type= +✓ Restart= +✓ RootDirectoryStartOnly= +✓ RemainAfterExit= +✓ GuessMainPID= +✓ RestartPreventExitStatus= +✓ RestartForceExitStatus= +✓ SuccessExitStatus= +✓ NonBlocking= +✓ BusName= +✓ FileDescriptorStoreMax= +✓ NotifyAccess= + Sockets= +✓ USBFunctionDescriptors= +✓ USBFunctionStrings= +✓ OOMPolicy= +``` + +## Mount Unit Settings + +All mount unit settings are available to transient units: + +``` +✓ What= +✓ Where= +✓ Options= +✓ Type= +✓ TimeoutSec= +✓ DirectoryMode= +✓ SloppyOptions= +✓ LazyUnmount= +✓ ForceUnmount= +``` + +## Automount Unit Settings + +All automount unit setting is available to transient units: + +``` +✓ Where= +✓ DirectoryMode= +✓ TimeoutIdleSec= +``` + +## Timer Unit Settings + +Most timer unit settings are available to transient units. + +``` +✓ OnActiveSec= +✓ OnBootSec= +✓ OnCalendar= +✓ OnClockChange= +✓ OnStartupSec= +✓ OnTimezoneChange= +✓ OnUnitActiveSec= +✓ OnUnitInactiveSec= +✓ Persistent= +✓ WakeSystem= +✓ RemainAfterElapse= +✓ AccuracySec= +✓ RandomizedDelaySec= + Unit= +``` + +## Slice Unit Settings + +Slice units are fully supported as transient units, but they have no settings +of their own beyond the generic unit and resource control settings. + +## Scope Unit Settings + +Scope units are fully supported as transient units (in fact they only exist as +such). + +``` +✓ RuntimeMaxSec= +✓ TimeoutStopSec= +``` + +## Socket Unit Settings + +Most socket unit settings are available to transient units. + +``` +✓ ListenStream= +✓ ListenDatagram= +✓ ListenSequentialPacket= +✓ ListenFIFO= +✓ ListenNetlink= +✓ ListenSpecial= +✓ ListenMessageQueue= +✓ ListenUSBFunction= +✓ SocketProtocol= +✓ BindIPv6Only= +✓ Backlog= +✓ BindToDevice= +✓ ExecStartPre= +✓ ExecStartPost= +✓ ExecStopPre= +✓ ExecStopPost= +✓ TimeoutSec= +✓ SocketUser= +✓ SocketGroup= +✓ SocketMode= +✓ DirectoryMode= +✓ Accept= +✓ Writable= +✓ MaxConnections= +✓ MaxConnectionsPerSource= +✓ KeepAlive= +✓ KeepAliveTimeSec= +✓ KeepAliveIntervalSec= +✓ KeepAliveProbes= +✓ DeferAcceptSec= +✓ NoDelay= +✓ Priority= +✓ ReceiveBuffer= +✓ SendBuffer= +✓ IPTOS= +✓ IPTTL= +✓ Mark= +✓ PipeSize= +✓ FreeBind= +✓ Transparent= +✓ Broadcast= +✓ PassCredentials= +✓ PassSecurity= +✓ TCPCongestion= +✓ ReusePort= +✓ MessageQueueMaxMessages= +✓ MessageQueueMessageSize= +✓ RemoveOnStop= +✓ Symlinks= +✓ FileDescriptorName= + Service= +✓ TriggerLimitIntervalSec= +✓ TriggerLimitBurst= +✓ SmackLabel= +✓ SmackLabelIPIn= +✓ SmackLabelIPOut= +✓ SELinuxContextFromNet= +``` + +## Swap Unit Settings + +Swap units are currently not available at all as transient units: + +``` + What= + Priority= + Options= + TimeoutSec= +``` + +## Path Unit Settings + +Most path unit settings are available to transient units. + +``` +✓ PathExists= +✓ PathExistsGlob= +✓ PathChanged= +✓ PathModified= +✓ DirectoryNotEmpty= + Unit= +✓ MakeDirectory= +✓ DirectoryMode= +``` + +## Install Section + +The `[Install]` section is currently not available at all for transient units, and it probably doesn't even make sense. + +``` + Alias= + WantedBy= + RequiredBy= + Also= + DefaultInstance= +``` diff --git a/docs/TRANSLATORS.md b/docs/TRANSLATORS.md new file mode 100644 index 00000000..d155c1c8 --- /dev/null +++ b/docs/TRANSLATORS.md @@ -0,0 +1,78 @@ +--- +title: Notes for Translators +--- + +# Notes for Translators + +systemd depends on the `gettext` package for multilingual support. + +You'll find the i18n files in the `po/` directory. + +The build system (meson/ninja) can be used to generate a template (`*.pot`), +which can be used to create new translations. + +It can also merge the template into the existing translations (`*.po`), to pick +up new strings in need of translation. + +Finally, it is able to compile the translations (to `*.gmo` files), so that +they can be used by systemd software. (This step is also useful to confirm the +syntax of the `*.po` files is correct.) + +## Creating a New Translation + +To create a translation to a language not yet available, start by creating the +initial template: + +``` +$ ninja -C build/ systemd-pot +``` + +This will generate file `po/systemd.pot` in the source tree. + +Then simply copy it to a new ${lang_code}.po file, where +${lang_code} is the two-letter code for a language +(possibly followed by a two-letter uppercase country code), according to the +ISO 639 standard. + +In short: + +
+$ cp po/systemd.pot po/${lang_code}.po
+
+ +Then edit the new po/${lang_code}.po file (for example, +using the `poedit` GUI editor.) + +## Updating an Existing Translation + +Start by updating the `*.po` files from the latest template: + +``` +$ ninja -C build/ systemd-update-po +``` + +This will touch all the `*.po` files, so you'll want to pay attention when +creating a git commit from this change, to only include the one translation +you're actually updating. + +Edit the `*.po` file, looking for empty translations and translations marked as +"fuzzy" (which means the merger found a similar message that needs to be +reviewed as it's expected not to match exactly.) + +You can use any text editor to update the `*.po` files, but a good choice is +the `poedit` editor, a graphical application specifically designed for this +purpose. + +Once you're done, create a git commit for the update of the `po/*.po` file you +touched. Remember to undo the changes to the other `*.po` files (for instance, +using `git checkout -- po/` after you commit the changes you do want to keep.) + +# Recompiling Translations + +You can recompile the `*.po` files using the following command: + +``` +$ ninja -C build/ systemd-gmo +``` + +The resulting files will be saved in the `build/po/` directory. diff --git a/docs/UIDS-GIDS.md b/docs/UIDS-GIDS.md new file mode 100644 index 00000000..1f3966f4 --- /dev/null +++ b/docs/UIDS-GIDS.md @@ -0,0 +1,290 @@ +--- +title: Users, Groups, UIDs and GIDs on `systemd` Systems +--- + +# Users, Groups, UIDs and GIDs on `systemd` Systems + +Here's a summary of the requirements `systemd` (and Linux) make on UID/GID +assignments and their ranges. + +Note that while in theory UIDs and GIDs are orthogonal concepts they really +aren't IRL. With that in mind, when we discuss UIDs below it should be assumed +that whatever we say about UIDs applies to GIDs in mostly the same way, and all +the special assignments and ranges for UIDs always have mostly the same +validity for GIDs too. + +## Special Linux UIDs + +In theory, the range of the C type `uid_t` is 32bit wide on Linux, +i.e. 0…4294967295. However, four UIDs are special on Linux: + +1. 0 → The `root` super-user + +2. 65534 → The `nobody` UID, also called the "overflow" UID or similar. It's + where various subsystems map unmappable users to, for example file systems + only supporting 16bit UIDs, NFS or user namespacing. (The latter can be + changed with a sysctl during runtime, but that's not supported on + `systemd`. If you do change it you void your warranty.) Because Fedora is a + bit confused the `nobody` user is called `nfsnobody` there (and they have a + different `nobody` user at UID 99). I hope this will be corrected eventually + though. (Also, some distributions call the `nobody` group `nogroup`. I wish + they didn't.) + +3. 4294967295, aka "32bit `(uid_t) -1`" → This UID is not a valid user ID, as + `setresuid()`, `chown()` and friends treat -1 as a special request to not + change the UID of the process/file. This UID is hence not available for + assignment to users in the user database. + +4. 65535, aka "16bit `(uid_t) -1`" → Before Linux kernel 2.4 `uid_t` used to be + 16bit, and programs compiled for that would hence assume that `(uid_t) -1` + is 65535. This UID is hence not usable either. + +The `nss-systemd` glibc NSS module will synthesize user database records for +the UIDs 0 and 65534 if the system user database doesn't list them. This means +that any system where this module is enabled works to some minimal level +without `/etc/passwd`. + +## Special Distribution UID ranges + +Distributions generally split the available UID range in two: + +1. 1…999 → System users. These are users that do not map to actual "human" + users, but are used as security identities for system daemons, to implement + privilege separation and run system daemons with minimal privileges. + +2. 1000…65533 and 65536…4294967294 → Everything else, i.e. regular (human) users. + +Note that most distributions allow changing the boundary between system and +regular users, even during runtime as user configuration. Moreover, some older +systems placed the boundary at 499/500, or even 99/100. In `systemd`, the +boundary is configurable only during compilation time, as this should be a +decision for distribution builders, not for users. Moreover, we strongly +discourage downstreams to change the boundary from the upstream default of +999/1000. + +Also note that programs such as `adduser` tend to allocate from a subset of the +available regular user range only, usually 1000..60000. And it's also usually +user-configurable, too. + +Note that systemd requires that system users and groups are resolvable without +networking available — a requirement that is not made for regular users. This +means regular users may be stored in remote LDAP or NIS databases, but system +users may not (except when there's a consistent local cache kept, that is +available during earliest boot, including in the initial RAM disk). + +## Special `systemd` GIDs + +`systemd` defines no special UIDs beyond what Linux already defines (see +above). However, it does define some special group/GID assignments, which are +primarily used for `systemd-udevd`'s device management. The precise list of the +currently defined groups is found in this `sysusers.d` snippet: +[basic.conf](https://raw.githubusercontent.com/systemd/systemd/master/sysusers.d/basic.conf.in) + +It's strongly recommended that downstream distributions include these groups in +their default group databases. + +Note that the actual GID numbers assigned to these groups do not have to be +constant beyond a specific system. There's one exception however: the `tty` +group must have the GID 5. That's because it must be encoded in the `devpts` +mount parameters during earliest boot, at a time where NSS lookups are not +possible. (Note that the actual GID can be changed during `systemd` build time, +but downstreams are strongly advised against doing that.) + +## Special `systemd` UID ranges + +`systemd` defines a number of special UID ranges: + +1. 61184…65519 → UIDs for dynamic users are allocated from this range (see the + `DynamicUser=` documentation in + [`systemd.exec(5)`](https://www.freedesktop.org/software/systemd/man/systemd.exec.html)). This + range has been chosen so that it is below the 16bit boundary (i.e. below + 65535), in order to provide compatibility with container environments that + assign a 64K range of UIDs to containers using user namespacing. This range + is above the 60000 boundary, so that its allocations are unlikely to be + affected by `adduser` allocations (see above). And we leave some room + upwards for other purposes. (And if you wonder why precisely these numbers: + if you write them in hexadecimal, they might make more sense: 0xEF00 and + 0xFFEF). The `nss-systemd` module will synthesize user records implicitly + for all currently allocated dynamic users from this range. Thus, NSS-based + user record resolving works correctly without those users being in + `/etc/passwd`. + +2. 524288…1879048191 → UID range for `systemd-nspawn`'s automatic allocation of + per-container UID ranges. When the `--private-users=pick` switch is used (or + `-U`) then it will automatically find a so far unused 16bit subrange of this + range and assign it to the container. The range is picked so that the upper + 16bit of the 32bit UIDs are constant for all users of the container, while + the lower 16bit directly encode the 65536 UIDs assigned to the + container. This mode of allocation means that the upper 16bit of any UID + assigned to a container are kind of a "container ID", while the lower 16bit + directly expose the container's own UID numbers. If you wonder why precisely + these numbers, consider them in hexadecimal: 0x00080000…0x6FFFFFFF. This + range is above the 16bit boundary. Moreover it's below the 31bit boundary, + as some broken code (specifically: the kernel's `devpts` file system) + erroneously considers UIDs signed integers, and hence can't deal with values + above 2^31. The `nss-mymachines` glibc NSS module will synthesize user + database records for all UIDs assigned to a running container from this + range. + +Note for both allocation ranges: when an UID allocation takes place NSS is +checked for collisions first, and a different UID is picked if an entry is +found. Thus, the user database is used as synchronization mechanism to ensure +exclusive ownership of UIDs and UID ranges. To ensure compatibility with other +subsystems allocating from the same ranges it is hence essential that they +ensure that whatever they pick shows up in the user/group databases, either by +providing an NSS module, or by adding entries directly to `/etc/passwd` and +`/etc/group`. For performance reasons, do note that `systemd-nspawn` will only +do an NSS check for the first UID of the range it allocates, not all 65536 of +them. Also note that while the allocation logic is operating, the glibc +`lckpwdf()` user database lock is taken, in order to make this logic race-free. + +## Figuring out the system's UID boundaries + +The most important boundaries of the local system may be queried with +`pkg-config`: + +``` +$ pkg-config --variable=systemuidmax systemd +999 +$ pkg-config --variable=dynamicuidmin systemd +61184 +$ pkg-config --variable=dynamicuidmax systemd +65519 +$ pkg-config --variable=containeruidbasemin systemd +524288 +$ pkg-config --variable=containeruidbasemax systemd +1878982656 +``` + +(Note that the latter encodes the maximum UID *base* `systemd-nspawn` might +pick — given that 64K UIDs are assigned to each container according to this +allocation logic, the maximum UID used for this range is hence +1878982656+65535=1879048191.) + +Note that systemd does not make any of these values runtime-configurable. All +these boundaries are chosen during build time. That said, the system UID/GID +boundary is traditionally configured in /etc/login.defs, though systemd won't +look there during runtime. + +## Considerations for container managers + +If you hack on a container manager, and wonder how and how many UIDs best to +assign to your containers, here are a few recommendations: + +1. Definitely, don't assign less than 65536 UIDs/GIDs. After all the `nobody` +user has magic properties, and hence should be available in your container, and +given that it's assigned the UID 65534, you should really cover the full 16bit +range in your container. Note that systemd will — as mentioned — synthesize +user records for the `nobody` user, and assumes its availability in various +other parts of its codebase, too, hence assigning fewer users means you lose +compatibility with running systemd code inside your container. And most likely +other packages make similar restrictions. + +2. While it's fine to assign more than 65536 UIDs/GIDs to a container, there's +most likely not much value in doing so, as Linux distributions won't use the +higher ranges by default (as mentioned neither `adduser` nor `systemd`'s +dynamic user concept allocate from above the 16bit range). Unless you actively +care for nested containers, it's hence probably a good idea to allocate exactly +65536 UIDs per container, and neither less nor more. A pretty side-effect is +that by doing so, you expose the same number of UIDs per container as Linux 2.2 +supported for the whole system, back in the days. + +3. Consider allocating UID ranges for containers so that the first UID you +assign has the lower 16bits all set to zero. That way, the upper 16bits become +a container ID of some kind, while the lower 16bits directly encode the +internal container UID. This is the way `systemd-nspawn` allocates UID ranges +(see above). Following this allocation logic ensures best compatibility with +`systemd-nspawn` and all other container managers following the scheme, as it +is sufficient then to check NSS for the first UID you pick regarding conflicts, +as that's what they do, too. Moreover, it makes `chown()`ing container file +system trees nicely robust to interruptions: as the external UID encodes the +internal UID in a fixed way, it's very easy to adjust the container's base UID +without the need to know the original base UID: to change the container base, +just mask away the upper 16bit, and insert the upper 16bit of the new container +base instead. Here are the easy conversions to derive the internal UID, the +external UID, and the container base UID from each other: + + ``` + INTERNAL_UID = EXTERNAL_UID & 0x0000FFFF + CONTAINER_BASE_UID = EXTERNAL_UID & 0xFFFF0000 + EXTERNAL_UID = INTERNAL_UID | CONTAINER_BASE_UID + ``` + +4. When picking a UID range for containers, make sure to check NSS first, with +a simple `getpwuid()` call: if there's already a user record for the first UID +you want to pick, then it's already in use: pick a different one. Wrap that +call in a `lckpwdf()` + `ulckpwdf()` pair, to make allocation +race-free. Provide an NSS module that makes all UIDs you end up taking show up +in the user database, and make sure that the NSS module returns up-to-date +information before you release the lock, so that other system components can +safely use the NSS user database as allocation check, too. Note that if you +follow this scheme no changes to `/etc/passwd` need to be made, thus minimizing +the artifacts the container manager persistently leaves in the system. + +## Summary + +| UID/GID | Purpose | Defined By | Listed in | +|-----------------------|-----------------------|---------------|-------------------------------| +| 0 | `root` user | Linux | `/etc/passwd` + `nss-systemd` | +| 1…4 | System users | Distributions | `/etc/passwd` | +| 5 | `tty` group | `systemd` | `/etc/passwd` | +| 6…999 | System users | Distributions | `/etc/passwd` | +| 1000…60000 | Regular users | Distributions | `/etc/passwd` + LDAP/NIS/… | +| 60001…61183 | Unused | | | +| 61184…65519 | Dynamic service users | `systemd` | `nss-systemd` | +| 65520…65533 | Unused | | | +| 65534 | `nobody` user | Linux | `/etc/passwd` + `nss-systemd` | +| 65535 | 16bit `(uid_t) -1` | Linux | | +| 65536…524287 | Unused | | | +| 524288…1879048191 | Container UID ranges | `systemd` | `nss-mymachines` | +| 1879048192…2147483647 | Unused | | | +| 2147483648…4294967294 | HIC SVNT LEONES | | | +| 4294967295 | 32bit `(uid_t) -1` | Linux | | + +Note that "Unused" in the table above doesn't meant that these ranges are +really unused. It just means that these ranges have no well-established +pre-defined purposes between Linux, generic low-level distributions and +`systemd`. There might very well be other packages that allocate from these +ranges. + +Note that the range 2147483648…4294967294 (i.e. 2^31…2^32-2) should be handled +with care. Various programs (including kernel file systems, see `devpts`) have +trouble with UIDs outside of the signed 32bit range, i.e any UIDs equal to or +above 2147483648. It is thus strongly recommended to stay away from this range +in order to avoid complications. This range should be considered reserved for +future, special purposes. + +## Notes on resolvability of user and group names + +User names, UIDs, group names and GIDs don't have to be resolvable using NSS +(i.e. getpwuid() and getpwnam() and friends) all the time. However, systemd +makes the following requirements: + +System users generally have to be resolvable during early boot already. This +means they should not be provided by any networked service (as those usually +become available during late boot only), except if a local cache is kept that +makes them available during early boot too (i.e. before networking is +up). Specifically, system users need to be resolvable at least before +`systemd-udevd.service` and `systemd-tmpfiles.service` are started, as both +need to resolve system users — but note that there might be more services +requiring full resolvability of system users than just these two. + +Regular users do not need to be resolvable during early boot, it is sufficient +if they become resolvable during late boot. Specifically, regular users need to +be resolvable at the point in time the `nss-user-lookup.target` unit is +reached. This target unit is generally used as synchronization point between +providers of the user database and consumers of it. Services that require that +the user database is fully available (for example, the login service +`systemd-logind.service`) are ordered *after* it, while services that provide +parts of the user database (for example an LDAP user database client) are +ordered *before* it. Note that `nss-user-lookup.target` is a *passive* unit: in +order to minimize synchronization points on systems that don't need it the unit +is pulled into the initial transaction only if there's at least one service +that really needs it, and that means only if there's a service providing the +local user database somehow through IPC or suchlike. Or in other words: if you +hack on some networked user database project, then make sure you order your +service `Before=nss-user-lookup.target` and that you pull it in with +`Wants=nss-user-lookup.target`. However, if you hack on some project that needs +the user database to be up in full, then order your service +`After=nss-user-lookup.target`, but do *not* pull it in via a `Wants=` +dependency. diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 00000000..ee845eec --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-primer diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..ffb30b96 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,11 @@ +--- +title: systemd Documentation +--- + +# systemd Documentation + +{% for p in site.pages %} + {% if p.url != page.url and p.title %} +* [{{ p.title }}]({{ p.url | relative_url }}) + {% endif %} +{% endfor %} diff --git a/docs/sysvinit/README.in b/docs/sysvinit/README.in new file mode 100644 index 00000000..de5d80d9 --- /dev/null +++ b/docs/sysvinit/README.in @@ -0,0 +1,27 @@ +You are looking for the traditional init scripts in @SYSTEM_SYSVINIT_PATH@, +and they are gone? + +Here's an explanation on what's going on: + +You are running a systemd-based OS where traditional init scripts have +been replaced by native systemd services files. Service files provide +very similar functionality to init scripts. To make use of service +files simply invoke "systemctl", which will output a list of all +currently running services (and other units). Use "systemctl +list-unit-files" to get a listing of all known unit files, including +stopped, disabled and masked ones. Use "systemctl start +foobar.service" and "systemctl stop foobar.service" to start or stop a +service, respectively. For further details, please refer to +systemctl(1). + +Note that traditional init scripts continue to function on a systemd +system. An init script @SYSTEM_SYSVINIT_PATH@/foobar is implicitly mapped +into a service unit foobar.service during system initialization. + +Thank you! + +Further reading: + man:systemctl(1) + man:systemd(1) + http://0pointer.de/blog/projects/systemd-for-admins-3.html + https://www.freedesktop.org/wiki/Software/systemd/Incompatibilities diff --git a/docs/sysvinit/meson.build b/docs/sysvinit/meson.build new file mode 100644 index 00000000..fbac59ae --- /dev/null +++ b/docs/sysvinit/meson.build @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +file = configure_file( + input : 'README.in', + output : 'README', + configuration : substs) + +if conf.get('HAVE_SYSV_COMPAT') == 1 + install_data(file, + install_dir : sysvinit_path) +endif diff --git a/docs/var-log/README b/docs/var-log/README new file mode 100644 index 00000000..5c6c5924 --- /dev/null +++ b/docs/var-log/README @@ -0,0 +1,25 @@ +You are looking for the traditional text log files in /var/log, and they are +gone? + +Here's an explanation on what's going on: + +You are running a systemd-based OS where traditional syslog has been replaced +with the Journal. The journal stores the same (and more) information as classic +syslog. To make use of the journal and access the collected log data simply +invoke "journalctl", which will output the logs in the identical text-based +format the syslog files in /var/log used to be. For further details, please +refer to journalctl(1). + +Alternatively, consider installing one of the traditional syslog +implementations available for your distribution, which will generate the +classic log files for you. Syslog implementations such as syslog-ng or rsyslog +may be installed side-by-side with the journal and will continue to function +the way they always did. + +Thank you! + +Further reading: + man:journalctl(1) + man:systemd-journald.service(8) + man:journald.conf(5) + http://0pointer.de/blog/projects/the-journal.html diff --git a/docs/var-log/meson.build b/docs/var-log/meson.build new file mode 100644 index 00000000..81b78654 --- /dev/null +++ b/docs/var-log/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +if conf.get('HAVE_SYSV_COMPAT') == 1 and get_option('create-log-dirs') + install_data('README', + install_dir : '/var/log') +endif diff --git a/factory/etc/issue b/factory/etc/issue new file mode 100644 index 00000000..101671f8 --- /dev/null +++ b/factory/etc/issue @@ -0,0 +1,3 @@ +\S +Kernel \r on an \m (\l) + diff --git a/factory/etc/nsswitch.conf b/factory/etc/nsswitch.conf new file mode 100644 index 00000000..5470993e --- /dev/null +++ b/factory/etc/nsswitch.conf @@ -0,0 +1,15 @@ +# This file is part of systemd. + +passwd: compat mymachines systemd +group: compat mymachines systemd +shadow: compat + +hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname +networks: files + +protocols: db files +services: db files +ethers: db files +rpc: db files + +netgroup: nis diff --git a/factory/etc/pam.d/other b/factory/etc/pam.d/other new file mode 100644 index 00000000..c1f72965 --- /dev/null +++ b/factory/etc/pam.d/other @@ -0,0 +1,6 @@ +# This file is part of systemd. + +auth include system-auth +account include system-auth +password include system-auth +session include system-auth diff --git a/factory/etc/pam.d/system-auth b/factory/etc/pam.d/system-auth new file mode 100644 index 00000000..747efc1f --- /dev/null +++ b/factory/etc/pam.d/system-auth @@ -0,0 +1,19 @@ +# This file is part of systemd. + +# You really want to adjust this to your local distribution. If you use this +# unmodified you are not building systems safely and securely. + +auth sufficient pam_unix.so nullok try_first_pass +auth required pam_deny.so + +account required pam_nologin.so +account sufficient pam_unix.so +account required pam_permit.so + +password sufficient pam_unix.so nullok sha512 shadow try_first_pass try_authtok +password required pam_deny.so + +-session optional pam_keyinit.so revoke +-session optional pam_loginuid.so +-session optional pam_systemd.so +session sufficient pam_unix.so diff --git a/fuzzbuzz.yaml b/fuzzbuzz.yaml new file mode 100644 index 00000000..f64af60e --- /dev/null +++ b/fuzzbuzz.yaml @@ -0,0 +1,32 @@ +base: ubuntu:16.04 +language: c +setup: +- sudo bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe multiverse' >>/etc/apt/sources.list" +- sudo apt-get update -y +- sudo apt-get build-dep -y systemd +- sudo apt-get install -y python3-pip +- pip3 install meson ninja +- export PATH="$HOME/.local/bin/:$PATH" +- CC=$FUZZ_CC CXX=$FUZZ_CXX meson -Dfuzzbuzz=true -Dfuzzbuzz-engine-dir=$(dirname "$FUZZ_ENGINE") -Dfuzzbuzz-engine=$(cut -d. -f1 <(basename "$FUZZ_ENGINE")) -Db_lundef=false ./build +- ninja -v -C ./build fuzzers +environment: +targets: +- name: fuzz-compress + harness: + binary: ./build/fuzz-compress +- name: fuzz-unit-file + harness: + binary: ./build/fuzz-unit-file + corpus: ./test/fuzz/fuzz-unit-file +- name: fuzz-journald-syslog + harness: + binary: ./build/fuzz-journald-syslog + corpus: ./test/fuzz/fuzz-journald-syslog +- name: fuzz-netdev-parser + harness: + binary: ./build/fuzz-netdev-parser + corpus: ./test/fuzz/fuzz-netdev-parser +- name: fuzz-network-parser + harness: + binary: ./build/fuzz-network-parser + corpus: ./test/fuzz/fuzz-network-parser diff --git a/hwdb.d/.gitattributes b/hwdb.d/.gitattributes new file mode 100644 index 00000000..830cae66 --- /dev/null +++ b/hwdb.d/.gitattributes @@ -0,0 +1,2 @@ +/*.txt -whitespace +/pci.ids -whitespace diff --git a/hwdb.d/.gitignore b/hwdb.d/.gitignore new file mode 100644 index 00000000..c9a78a8c --- /dev/null +++ b/hwdb.d/.gitignore @@ -0,0 +1 @@ +/20-acpi-vendor.hwdb.base diff --git a/hwdb.d/20-OUI.hwdb b/hwdb.d/20-OUI.hwdb new file mode 100644 index 00000000..8e3e879a --- /dev/null +++ b/hwdb.d/20-OUI.hwdb @@ -0,0 +1,101934 @@ +# This file is part of systemd. +# +# Data imported from: +# https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-L&format=txt +# https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-M&format=txt +# https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-S&format=txt + +OUI:000000* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:000001* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:000002* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:000003* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:000004* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:000005* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:000006* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:000007* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:000008* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:000009* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:00000A* + ID_OUI_FROM_DATABASE=OMRON TATEISI ELECTRONICS CO. + +OUI:00000B* + ID_OUI_FROM_DATABASE=MATRIX CORPORATION + +OUI:00000C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00000D* + ID_OUI_FROM_DATABASE=FIBRONICS LTD. + +OUI:00000E* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:00000F* + ID_OUI_FROM_DATABASE=NEXT, INC. + +OUI:000010* + ID_OUI_FROM_DATABASE=SYTEK INC. + +OUI:000011* + ID_OUI_FROM_DATABASE=NORMEREL SYSTEMES + +OUI:000012* + ID_OUI_FROM_DATABASE=INFORMATION TECHNOLOGY LIMITED + +OUI:000013* + ID_OUI_FROM_DATABASE=CAMEX + +OUI:000014* + ID_OUI_FROM_DATABASE=NETRONIX + +OUI:000015* + ID_OUI_FROM_DATABASE=DATAPOINT CORPORATION + +OUI:000016* + ID_OUI_FROM_DATABASE=DU PONT PIXEL SYSTEMS . + +OUI:000017* + ID_OUI_FROM_DATABASE=Oracle + +OUI:000018* + ID_OUI_FROM_DATABASE=WEBSTER COMPUTER CORPORATION + +OUI:000019* + ID_OUI_FROM_DATABASE=APPLIED DYNAMICS INTERNATIONAL + +OUI:00001A* + ID_OUI_FROM_DATABASE=ADVANCED MICRO DEVICES + +OUI:00001B* + ID_OUI_FROM_DATABASE=Novell, Inc. + +OUI:00001C* + ID_OUI_FROM_DATABASE=BELL TECHNOLOGIES + +OUI:00001D* + ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. + +OUI:00001E* + ID_OUI_FROM_DATABASE=TELSIST INDUSTRIA ELECTRONICA + +OUI:00001F* + ID_OUI_FROM_DATABASE=Telco Systems, Inc. + +OUI:000020* + ID_OUI_FROM_DATABASE=DATAINDUSTRIER DIAB AB + +OUI:000021* + ID_OUI_FROM_DATABASE=SUREMAN COMP. & COMMUN. CORP. + +OUI:000022* + ID_OUI_FROM_DATABASE=VISUAL TECHNOLOGY INC. + +OUI:000023* + ID_OUI_FROM_DATABASE=ABB INDUSTRIAL SYSTEMS AB + +OUI:000024* + ID_OUI_FROM_DATABASE=CONNECT AS + +OUI:000025* + ID_OUI_FROM_DATABASE=RAMTEK CORP. + +OUI:000026* + ID_OUI_FROM_DATABASE=SHA-KEN CO., LTD. + +OUI:000027* + ID_OUI_FROM_DATABASE=JAPAN RADIO COMPANY + +OUI:000028* + ID_OUI_FROM_DATABASE=PRODIGY SYSTEMS CORPORATION + +OUI:000029* + ID_OUI_FROM_DATABASE=IMC NETWORKS CORP. + +OUI:00002A* + ID_OUI_FROM_DATABASE=TRW - SEDD/INP + +OUI:00002B* + ID_OUI_FROM_DATABASE=CRISP AUTOMATION, INC + +OUI:00002C* + ID_OUI_FROM_DATABASE=AUTOTOTE LIMITED + +OUI:00002D* + ID_OUI_FROM_DATABASE=CHROMATICS INC + +OUI:00002E* + ID_OUI_FROM_DATABASE=SOCIETE EVIRA + +OUI:00002F* + ID_OUI_FROM_DATABASE=TIMEPLEX INC. + +OUI:000030* + ID_OUI_FROM_DATABASE=VG LABORATORY SYSTEMS LTD + +OUI:000031* + ID_OUI_FROM_DATABASE=QPSX COMMUNICATIONS, LTD. + +OUI:000032* + ID_OUI_FROM_DATABASE=Marconi plc + +OUI:000033* + ID_OUI_FROM_DATABASE=EGAN MACHINERY COMPANY + +OUI:000034* + ID_OUI_FROM_DATABASE=NETWORK RESOURCES CORPORATION + +OUI:000035* + ID_OUI_FROM_DATABASE=SPECTRAGRAPHICS CORPORATION + +OUI:000036* + ID_OUI_FROM_DATABASE=ATARI CORPORATION + +OUI:000037* + ID_OUI_FROM_DATABASE=OXFORD METRICS LIMITED + +OUI:000038* + ID_OUI_FROM_DATABASE=CSS LABS + +OUI:000039* + ID_OUI_FROM_DATABASE=TOSHIBA CORPORATION + +OUI:00003A* + ID_OUI_FROM_DATABASE=CHYRON CORPORATION + +OUI:00003B* + ID_OUI_FROM_DATABASE=i Controls, Inc. + +OUI:00003C* + ID_OUI_FROM_DATABASE=AUSPEX SYSTEMS INC. + +OUI:00003D* + ID_OUI_FROM_DATABASE=UNISYS + +OUI:00003E* + ID_OUI_FROM_DATABASE=SIMPACT + +OUI:00003F* + ID_OUI_FROM_DATABASE=SYNTREX, INC. + +OUI:000040* + ID_OUI_FROM_DATABASE=APPLICON, INC. + +OUI:000041* + ID_OUI_FROM_DATABASE=ICE CORPORATION + +OUI:000042* + ID_OUI_FROM_DATABASE=METIER MANAGEMENT SYSTEMS LTD. + +OUI:000043* + ID_OUI_FROM_DATABASE=MICRO TECHNOLOGY + +OUI:000044* + ID_OUI_FROM_DATABASE=CASTELLE CORPORATION + +OUI:000045* + ID_OUI_FROM_DATABASE=FORD AEROSPACE & COMM. CORP. + +OUI:000046* + ID_OUI_FROM_DATABASE=OLIVETTI NORTH AMERICA + +OUI:000047* + ID_OUI_FROM_DATABASE=NICOLET INSTRUMENTS CORP. + +OUI:000048* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:000049* + ID_OUI_FROM_DATABASE=APRICOT COMPUTERS, LTD + +OUI:00004A* + ID_OUI_FROM_DATABASE=ADC CODENOLL TECHNOLOGY CORP. + +OUI:00004B* + ID_OUI_FROM_DATABASE=ICL DATA OY + +OUI:00004C* + ID_OUI_FROM_DATABASE=NEC Corporation + +OUI:00004D* + ID_OUI_FROM_DATABASE=DCI CORPORATION + +OUI:00004E* + ID_OUI_FROM_DATABASE=AMPEX CORPORATION + +OUI:00004F* + ID_OUI_FROM_DATABASE=LOGICRAFT, INC. + +OUI:000050* + ID_OUI_FROM_DATABASE=RADISYS CORPORATION + +OUI:000051* + ID_OUI_FROM_DATABASE=HOB ELECTRONIC GMBH & CO. KG + +OUI:000052* + ID_OUI_FROM_DATABASE=Intrusion.com, Inc. + +OUI:000053* + ID_OUI_FROM_DATABASE=COMPUCORP + +OUI:000054* + ID_OUI_FROM_DATABASE=Schneider Electric + +OUI:000055* + ID_OUI_FROM_DATABASE=COMMISSARIAT A L`ENERGIE ATOM. + +OUI:000056* + ID_OUI_FROM_DATABASE=DR. B. STRUCK + +OUI:000057* + ID_OUI_FROM_DATABASE=SCITEX CORPORATION LTD. + +OUI:000058* + ID_OUI_FROM_DATABASE=RACORE COMPUTER PRODUCTS INC. + +OUI:000059* + ID_OUI_FROM_DATABASE=Hellige GMBH + +OUI:00005A* + ID_OUI_FROM_DATABASE=SysKonnect GmbH + +OUI:00005B* + ID_OUI_FROM_DATABASE=ELTEC ELEKTRONIK AG + +OUI:00005C* + ID_OUI_FROM_DATABASE=TELEMATICS INTERNATIONAL INC. + +OUI:00005D* + ID_OUI_FROM_DATABASE=CS TELECOM + +OUI:00005E* + ID_OUI_FROM_DATABASE=ICANN, IANA Department + +OUI:00005F* + ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd + +OUI:000060* + ID_OUI_FROM_DATABASE=KONTRON ELEKTRONIK GMBH + +OUI:000061* + ID_OUI_FROM_DATABASE=GATEWAY COMMUNICATIONS + +OUI:000062* + ID_OUI_FROM_DATABASE=BULL HN INFORMATION SYSTEMS + +OUI:000063* + ID_OUI_FROM_DATABASE=BARCO CONTROL ROOMS GMBH + +OUI:000064* + ID_OUI_FROM_DATABASE=Yokogawa Digital Computer Corporation + +OUI:000065* + ID_OUI_FROM_DATABASE=Network General Corporation + +OUI:000066* + ID_OUI_FROM_DATABASE=TALARIS SYSTEMS, INC. + +OUI:000067* + ID_OUI_FROM_DATABASE=SOFT * RITE, INC. + +OUI:000068* + ID_OUI_FROM_DATABASE=ROSEMOUNT CONTROLS + +OUI:000069* + ID_OUI_FROM_DATABASE=CONCORD COMMUNICATIONS INC + +OUI:00006A* + ID_OUI_FROM_DATABASE=COMPUTER CONSOLES INC. + +OUI:00006B* + ID_OUI_FROM_DATABASE=Silicon Graphics + +OUI:00006C* + ID_OUI_FROM_DATABASE=Private + +OUI:00006D* + ID_OUI_FROM_DATABASE=CRAY COMMUNICATIONS, LTD. + +OUI:00006E* + ID_OUI_FROM_DATABASE=Artisoft Inc. + +OUI:00006F* + ID_OUI_FROM_DATABASE=Madge Ltd. + +OUI:000070* + ID_OUI_FROM_DATABASE=HCL LIMITED + +OUI:000071* + ID_OUI_FROM_DATABASE=ADRA SYSTEMS INC. + +OUI:000072* + ID_OUI_FROM_DATABASE=MINIWARE TECHNOLOGY + +OUI:000073* + ID_OUI_FROM_DATABASE=SIECOR CORPORATION + +OUI:000074* + ID_OUI_FROM_DATABASE=RICOH COMPANY LTD. + +OUI:000075* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000076* + ID_OUI_FROM_DATABASE=ABEKAS VIDEO SYSTEM + +OUI:000077* + ID_OUI_FROM_DATABASE=INTERPHASE CORPORATION + +OUI:000078* + ID_OUI_FROM_DATABASE=LABTAM LIMITED + +OUI:000079* + ID_OUI_FROM_DATABASE=NETWORTH INCORPORATED + +OUI:00007A* + ID_OUI_FROM_DATABASE=DANA COMPUTER INC. + +OUI:00007B* + ID_OUI_FROM_DATABASE=RESEARCH MACHINES + +OUI:00007C* + ID_OUI_FROM_DATABASE=AMPERE INCORPORATED + +OUI:00007D* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:00007E* + ID_OUI_FROM_DATABASE=CLUSTRIX CORPORATION + +OUI:00007F* + ID_OUI_FROM_DATABASE=LINOTYPE-HELL AG + +OUI:000080* + ID_OUI_FROM_DATABASE=CRAY COMMUNICATIONS A/S + +OUI:000081* + ID_OUI_FROM_DATABASE=Bay Networks + +OUI:000082* + ID_OUI_FROM_DATABASE=LECTRA SYSTEMES SA + +OUI:000083* + ID_OUI_FROM_DATABASE=TADPOLE TECHNOLOGY PLC + +OUI:000084* + ID_OUI_FROM_DATABASE=SUPERNET + +OUI:000085* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:000086* + ID_OUI_FROM_DATABASE=MEGAHERTZ CORPORATION + +OUI:000087* + ID_OUI_FROM_DATABASE=HITACHI, LTD. + +OUI:000088* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:000089* + ID_OUI_FROM_DATABASE=CAYMAN SYSTEMS INC. + +OUI:00008A* + ID_OUI_FROM_DATABASE=DATAHOUSE INFORMATION SYSTEMS + +OUI:00008B* + ID_OUI_FROM_DATABASE=INFOTRON + +OUI:00008C* + ID_OUI_FROM_DATABASE=Alloy Computer Products (Australia) Pty Ltd + +OUI:00008D* + ID_OUI_FROM_DATABASE=Cryptek Inc. + +OUI:00008E* + ID_OUI_FROM_DATABASE=SOLBOURNE COMPUTER, INC. + +OUI:00008F* + ID_OUI_FROM_DATABASE=Raytheon + +OUI:000090* + ID_OUI_FROM_DATABASE=MICROCOM + +OUI:000091* + ID_OUI_FROM_DATABASE=ANRITSU CORPORATION + +OUI:000092* + ID_OUI_FROM_DATABASE=COGENT DATA TECHNOLOGIES + +OUI:000093* + ID_OUI_FROM_DATABASE=PROTEON INC. + +OUI:000094* + ID_OUI_FROM_DATABASE=ASANTE TECHNOLOGIES + +OUI:000095* + ID_OUI_FROM_DATABASE=SONY TEKTRONIX CORP. + +OUI:000096* + ID_OUI_FROM_DATABASE=MARCONI ELECTRONICS LTD. + +OUI:000097* + ID_OUI_FROM_DATABASE=Dell EMC + +OUI:000098* + ID_OUI_FROM_DATABASE=CROSSCOMM CORPORATION + +OUI:000099* + ID_OUI_FROM_DATABASE=MTX, INC. + +OUI:00009A* + ID_OUI_FROM_DATABASE=RC COMPUTER A/S + +OUI:00009B* + ID_OUI_FROM_DATABASE=INFORMATION INTERNATIONAL, INC + +OUI:00009C* + ID_OUI_FROM_DATABASE=ROLM MIL-SPEC COMPUTERS + +OUI:00009D* + ID_OUI_FROM_DATABASE=LOCUS COMPUTING CORPORATION + +OUI:00009E* + ID_OUI_FROM_DATABASE=MARLI S.A. + +OUI:00009F* + ID_OUI_FROM_DATABASE=AMERISTAR TECHNOLOGIES INC. + +OUI:0000A0* + ID_OUI_FROM_DATABASE=SANYO Electric Co., Ltd. + +OUI:0000A1* + ID_OUI_FROM_DATABASE=MARQUETTE ELECTRIC CO. + +OUI:0000A2* + ID_OUI_FROM_DATABASE=Bay Networks + +OUI:0000A3* + ID_OUI_FROM_DATABASE=NETWORK APPLICATION TECHNOLOGY + +OUI:0000A4* + ID_OUI_FROM_DATABASE=ACORN COMPUTERS LIMITED + +OUI:0000A5* + ID_OUI_FROM_DATABASE=Tattile SRL + +OUI:0000A6* + ID_OUI_FROM_DATABASE=NETWORK GENERAL CORPORATION + +OUI:0000A7* + ID_OUI_FROM_DATABASE=NETWORK COMPUTING DEVICES INC. + +OUI:0000A8* + ID_OUI_FROM_DATABASE=Stratus Technologies + +OUI:0000A9* + ID_OUI_FROM_DATABASE=NETWORK SYSTEMS CORP. + +OUI:0000AA* + ID_OUI_FROM_DATABASE=XEROX CORPORATION + +OUI:0000AB* + ID_OUI_FROM_DATABASE=LOGIC MODELING CORPORATION + +OUI:0000AC* + ID_OUI_FROM_DATABASE=CONWARE COMPUTER CONSULTING + +OUI:0000AD* + ID_OUI_FROM_DATABASE=BRUKER INSTRUMENTS INC. + +OUI:0000AE* + ID_OUI_FROM_DATABASE=DASSAULT ELECTRONIQUE + +OUI:0000AF* + ID_OUI_FROM_DATABASE=Canberra Industries, Inc. + +OUI:0000B0* + ID_OUI_FROM_DATABASE=RND-RAD NETWORK DEVICES + +OUI:0000B1* + ID_OUI_FROM_DATABASE=Alpha Micro + +OUI:0000B2* + ID_OUI_FROM_DATABASE=TELEVIDEO SYSTEMS, INC. + +OUI:0000B3* + ID_OUI_FROM_DATABASE=CIMLINC INCORPORATED + +OUI:0000B4* + ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. + +OUI:0000B5* + ID_OUI_FROM_DATABASE=DATABILITY SOFTWARE SYS. INC. + +OUI:0000B6* + ID_OUI_FROM_DATABASE=MICRO-MATIC RESEARCH + +OUI:0000B7* + ID_OUI_FROM_DATABASE=DOVE COMPUTER CORPORATION + +OUI:0000B8* + ID_OUI_FROM_DATABASE=SEIKOSHA CO., LTD. + +OUI:0000B9* + ID_OUI_FROM_DATABASE=MCDONNELL DOUGLAS COMPUTER SYS + +OUI:0000BA* + ID_OUI_FROM_DATABASE=SIIG, INC. + +OUI:0000BB* + ID_OUI_FROM_DATABASE=TRI-DATA + +OUI:0000BC* + ID_OUI_FROM_DATABASE=Rockwell Automation + +OUI:0000BD* + ID_OUI_FROM_DATABASE=Mitsubishi Cable Industries, Ltd. / Ryosei Systems + +OUI:0000BE* + ID_OUI_FROM_DATABASE=THE NTI GROUP + +OUI:0000BF* + ID_OUI_FROM_DATABASE=SYMMETRIC COMPUTER SYSTEMS + +OUI:0000C0* + ID_OUI_FROM_DATABASE=WESTERN DIGITAL CORPORATION + +OUI:0000C1* + ID_OUI_FROM_DATABASE=Madge Ltd. + +OUI:0000C2* + ID_OUI_FROM_DATABASE=INFORMATION PRESENTATION TECH. + +OUI:0000C3* + ID_OUI_FROM_DATABASE=Harris Corporation + +OUI:0000C4* + ID_OUI_FROM_DATABASE=WATERS DIV. OF MILLIPORE + +OUI:0000C5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0000C6* + ID_OUI_FROM_DATABASE=EON SYSTEMS + +OUI:0000C7* + ID_OUI_FROM_DATABASE=ARIX CORPORATION + +OUI:0000C8* + ID_OUI_FROM_DATABASE=ALTOS COMPUTER SYSTEMS + +OUI:0000C9* + ID_OUI_FROM_DATABASE=Emulex Corporation + +OUI:0000CA* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0000CB* + ID_OUI_FROM_DATABASE=COMPU-SHACK ELECTRONIC GMBH + +OUI:0000CC* + ID_OUI_FROM_DATABASE=DENSAN CO., LTD. + +OUI:0000CD* + ID_OUI_FROM_DATABASE=Allied Telesis Labs Ltd + +OUI:0000CE* + ID_OUI_FROM_DATABASE=MEGADATA CORP. + +OUI:0000CF* + ID_OUI_FROM_DATABASE=HAYES MICROCOMPUTER PRODUCTS + +OUI:0000D0* + ID_OUI_FROM_DATABASE=DEVELCON ELECTRONICS LTD. + +OUI:0000D1* + ID_OUI_FROM_DATABASE=ADAPTEC INCORPORATED + +OUI:0000D2* + ID_OUI_FROM_DATABASE=SBE, INC. + +OUI:0000D3* + ID_OUI_FROM_DATABASE=WANG LABORATORIES INC. + +OUI:0000D4* + ID_OUI_FROM_DATABASE=PURE DATA LTD. + +OUI:0000D5* + ID_OUI_FROM_DATABASE=MICROGNOSIS INTERNATIONAL + +OUI:0000D6* + ID_OUI_FROM_DATABASE=PUNCH LINE HOLDING + +OUI:0000D7* + ID_OUI_FROM_DATABASE=DARTMOUTH COLLEGE + +OUI:0000D8* + ID_OUI_FROM_DATABASE=Novell, Inc. + +OUI:0000D9* + ID_OUI_FROM_DATABASE=NIPPON TELEGRAPH & TELEPHONE + +OUI:0000DA* + ID_OUI_FROM_DATABASE=ATEX + +OUI:0000DB* + ID_OUI_FROM_DATABASE=British Telecommunications plc + +OUI:0000DC* + ID_OUI_FROM_DATABASE=HAYES MICROCOMPUTER PRODUCTS + +OUI:0000DD* + ID_OUI_FROM_DATABASE=TCL INCORPORATED + +OUI:0000DE* + ID_OUI_FROM_DATABASE=CETIA + +OUI:0000DF* + ID_OUI_FROM_DATABASE=BELL & HOWELL PUB SYS DIV + +OUI:0000E0* + ID_OUI_FROM_DATABASE=QUADRAM CORP. + +OUI:0000E1* + ID_OUI_FROM_DATABASE=GRID SYSTEMS + +OUI:0000E2* + ID_OUI_FROM_DATABASE=ACER TECHNOLOGIES CORP. + +OUI:0000E3* + ID_OUI_FROM_DATABASE=INTEGRATED MICRO PRODUCTS LTD + +OUI:0000E4* + ID_OUI_FROM_DATABASE=IN2 GROUPE INTERTECHNIQUE + +OUI:0000E5* + ID_OUI_FROM_DATABASE=SIGMEX LTD. + +OUI:0000E6* + ID_OUI_FROM_DATABASE=APTOR PRODUITS DE COMM INDUST + +OUI:0000E7* + ID_OUI_FROM_DATABASE=Star Gate Technologies + +OUI:0000E8* + ID_OUI_FROM_DATABASE=ACCTON TECHNOLOGY CORP. + +OUI:0000E9* + ID_OUI_FROM_DATABASE=ISICAD, INC. + +OUI:0000EA* + ID_OUI_FROM_DATABASE=UPNOD AB + +OUI:0000EB* + ID_OUI_FROM_DATABASE=MATSUSHITA COMM. IND. CO. LTD. + +OUI:0000EC* + ID_OUI_FROM_DATABASE=MICROPROCESS + +OUI:0000ED* + ID_OUI_FROM_DATABASE=APRIL + +OUI:0000EE* + ID_OUI_FROM_DATABASE=NETWORK DESIGNERS, LTD. + +OUI:0000EF* + ID_OUI_FROM_DATABASE=KTI + +OUI:0000F0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0000F1* + ID_OUI_FROM_DATABASE=MAGNA COMPUTER CORPORATION + +OUI:0000F2* + ID_OUI_FROM_DATABASE=SPIDER COMMUNICATIONS + +OUI:0000F3* + ID_OUI_FROM_DATABASE=GANDALF DATA LIMITED + +OUI:0000F4* + ID_OUI_FROM_DATABASE=Allied Telesis, Inc. + +OUI:0000F5* + ID_OUI_FROM_DATABASE=DIAMOND SALES LIMITED + +OUI:0000F6* + ID_OUI_FROM_DATABASE=APPLIED MICROSYSTEMS CORP. + +OUI:0000F7* + ID_OUI_FROM_DATABASE=YOUTH KEEP ENTERPRISE CO LTD + +OUI:0000F8* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION + +OUI:0000F9* + ID_OUI_FROM_DATABASE=QUOTRON SYSTEMS INC. + +OUI:0000FA* + ID_OUI_FROM_DATABASE=MICROSAGE COMPUTER SYSTEMS INC + +OUI:0000FB* + ID_OUI_FROM_DATABASE=RECHNER ZUR KOMMUNIKATION + +OUI:0000FC* + ID_OUI_FROM_DATABASE=MEIKO + +OUI:0000FD* + ID_OUI_FROM_DATABASE=HIGH LEVEL HARDWARE + +OUI:0000FE* + ID_OUI_FROM_DATABASE=Annapolis Micro Systems, Inc. + +OUI:0000FF* + ID_OUI_FROM_DATABASE=CAMTEC ELECTRONICS LTD. + +OUI:000100* + ID_OUI_FROM_DATABASE=EQUIP'TRANS + +OUI:000101* + ID_OUI_FROM_DATABASE=Private + +OUI:000102* + ID_OUI_FROM_DATABASE=3COM + +OUI:000103* + ID_OUI_FROM_DATABASE=3COM + +OUI:000104* + ID_OUI_FROM_DATABASE=DVICO Co., Ltd. + +OUI:000105* + ID_OUI_FROM_DATABASE=Beckhoff Automation GmbH + +OUI:000106* + ID_OUI_FROM_DATABASE=Tews Datentechnik GmbH + +OUI:000107* + ID_OUI_FROM_DATABASE=Leiser GmbH + +OUI:000108* + ID_OUI_FROM_DATABASE=AVLAB Technology, Inc. + +OUI:000109* + ID_OUI_FROM_DATABASE=Nagano Japan Radio Co., Ltd. + +OUI:00010A* + ID_OUI_FROM_DATABASE=CIS TECHNOLOGY INC. + +OUI:00010B* + ID_OUI_FROM_DATABASE=Space CyberLink, Inc. + +OUI:00010C* + ID_OUI_FROM_DATABASE=System Talks Inc. + +OUI:00010D* + ID_OUI_FROM_DATABASE=Teledyne DALSA Inc. + +OUI:00010E* + ID_OUI_FROM_DATABASE=Bri-Link Technologies Co., Ltd + +OUI:00010F* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:000110* + ID_OUI_FROM_DATABASE=Gotham Networks + +OUI:000111* + ID_OUI_FROM_DATABASE=iDigm Inc. + +OUI:000112* + ID_OUI_FROM_DATABASE=Shark Multimedia Inc. + +OUI:000113* + ID_OUI_FROM_DATABASE=OLYMPUS CORPORATION + +OUI:000114* + ID_OUI_FROM_DATABASE=KANDA TSUSHIN KOGYO CO., LTD. + +OUI:000115* + ID_OUI_FROM_DATABASE=EXTRATECH CORPORATION + +OUI:000116* + ID_OUI_FROM_DATABASE=Netspect Technologies, Inc. + +OUI:000117* + ID_OUI_FROM_DATABASE=Canal + + +OUI:000118* + ID_OUI_FROM_DATABASE=EZ Digital Co., Ltd. + +OUI:000119* + ID_OUI_FROM_DATABASE=RTUnet (Australia) + +OUI:00011A* + ID_OUI_FROM_DATABASE=Hoffmann und Burmeister GbR + +OUI:00011B* + ID_OUI_FROM_DATABASE=Unizone Technologies, Inc. + +OUI:00011C* + ID_OUI_FROM_DATABASE=Universal Talkware Corporation + +OUI:00011D* + ID_OUI_FROM_DATABASE=Centillium Communications + +OUI:00011E* + ID_OUI_FROM_DATABASE=Precidia Technologies, Inc. + +OUI:00011F* + ID_OUI_FROM_DATABASE=RC Networks, Inc. + +OUI:000120* + ID_OUI_FROM_DATABASE=OSCILLOQUARTZ S.A. + +OUI:000121* + ID_OUI_FROM_DATABASE=WatchGuard Technologies, Inc. + +OUI:000122* + ID_OUI_FROM_DATABASE=Trend Communications, Ltd. + +OUI:000123* + ID_OUI_FROM_DATABASE=Schneider Electric Japan Holdings Ltd. + +OUI:000124* + ID_OUI_FROM_DATABASE=Acer Incorporated + +OUI:000125* + ID_OUI_FROM_DATABASE=YAESU MUSEN CO., LTD. + +OUI:000126* + ID_OUI_FROM_DATABASE=PAC Labs + +OUI:000127* + ID_OUI_FROM_DATABASE=OPEN Networks Pty Ltd + +OUI:000128* + ID_OUI_FROM_DATABASE=EnjoyWeb, Inc. + +OUI:000129* + ID_OUI_FROM_DATABASE=DFI Inc. + +OUI:00012A* + ID_OUI_FROM_DATABASE=Telematica Sistems Inteligente + +OUI:00012B* + ID_OUI_FROM_DATABASE=TELENET Co., Ltd. + +OUI:00012C* + ID_OUI_FROM_DATABASE=Aravox Technologies, Inc. + +OUI:00012D* + ID_OUI_FROM_DATABASE=Komodo Technology + +OUI:00012E* + ID_OUI_FROM_DATABASE=PC Partner Ltd. + +OUI:00012F* + ID_OUI_FROM_DATABASE=Twinhead International Corp + +OUI:000130* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:000131* + ID_OUI_FROM_DATABASE=Bosch Security Systems, Inc. + +OUI:000132* + ID_OUI_FROM_DATABASE=Dranetz - BMI + +OUI:000133* + ID_OUI_FROM_DATABASE=KYOWA Electronic Instruments C + +OUI:000134* + ID_OUI_FROM_DATABASE=Selectron Systems AG + +OUI:000135* + ID_OUI_FROM_DATABASE=KDC Corp. + +OUI:000136* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. + +OUI:000137* + ID_OUI_FROM_DATABASE=IT Farm Corporation + +OUI:000138* + ID_OUI_FROM_DATABASE=XAVi Technologies Corp. + +OUI:000139* + ID_OUI_FROM_DATABASE=Point Multimedia Systems + +OUI:00013A* + ID_OUI_FROM_DATABASE=SHELCAD COMMUNICATIONS, LTD. + +OUI:00013B* + ID_OUI_FROM_DATABASE=BNA SYSTEMS + +OUI:00013C* + ID_OUI_FROM_DATABASE=TIW SYSTEMS + +OUI:00013D* + ID_OUI_FROM_DATABASE=RiscStation Ltd. + +OUI:00013E* + ID_OUI_FROM_DATABASE=Ascom Tateco AB + +OUI:00013F* + ID_OUI_FROM_DATABASE=Neighbor World Co., Ltd. + +OUI:000140* + ID_OUI_FROM_DATABASE=Sendtek Corporation + +OUI:000141* + ID_OUI_FROM_DATABASE=CABLE PRINT + +OUI:000142* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000143* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000144* + ID_OUI_FROM_DATABASE=Dell EMC + +OUI:000145* + ID_OUI_FROM_DATABASE=WINSYSTEMS, INC. + +OUI:000146* + ID_OUI_FROM_DATABASE=Tesco Controls, Inc. + +OUI:000147* + ID_OUI_FROM_DATABASE=Zhone Technologies + +OUI:000148* + ID_OUI_FROM_DATABASE=X-traWeb Inc. + +OUI:000149* + ID_OUI_FROM_DATABASE=TDT AG + +OUI:00014A* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:00014B* + ID_OUI_FROM_DATABASE=Ennovate Networks, Inc. + +OUI:00014C* + ID_OUI_FROM_DATABASE=Berkeley Process Control + +OUI:00014D* + ID_OUI_FROM_DATABASE=Shin Kin Enterprises Co., Ltd + +OUI:00014E* + ID_OUI_FROM_DATABASE=WIN Enterprises, Inc. + +OUI:00014F* + ID_OUI_FROM_DATABASE=Adtran Inc + +OUI:000150* + ID_OUI_FROM_DATABASE=GILAT COMMUNICATIONS, LTD. + +OUI:000151* + ID_OUI_FROM_DATABASE=Ensemble Communications + +OUI:000152* + ID_OUI_FROM_DATABASE=CHROMATEK INC. + +OUI:000153* + ID_OUI_FROM_DATABASE=ARCHTEK TELECOM CORPORATION + +OUI:000154* + ID_OUI_FROM_DATABASE=G3M Corporation + +OUI:000155* + ID_OUI_FROM_DATABASE=Promise Technology, Inc. + +OUI:000156* + ID_OUI_FROM_DATABASE=FIREWIREDIRECT.COM, INC. + +OUI:000157* + ID_OUI_FROM_DATABASE=SYSWAVE CO., LTD + +OUI:000158* + ID_OUI_FROM_DATABASE=Electro Industries/Gauge Tech + +OUI:000159* + ID_OUI_FROM_DATABASE=S1 Corporation + +OUI:00015A* + ID_OUI_FROM_DATABASE=Digital Video Broadcasting + +OUI:00015B* + ID_OUI_FROM_DATABASE=ITALTEL S.p.A/RF-UP-I + +OUI:00015C* + ID_OUI_FROM_DATABASE=CADANT INC. + +OUI:00015D* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:00015E* + ID_OUI_FROM_DATABASE=BEST TECHNOLOGY CO., LTD. + +OUI:00015F* + ID_OUI_FROM_DATABASE=DIGITAL DESIGN GmbH + +OUI:000160* + ID_OUI_FROM_DATABASE=ELMEX Co., LTD. + +OUI:000161* + ID_OUI_FROM_DATABASE=Meta Machine Technology + +OUI:000162* + ID_OUI_FROM_DATABASE=Cygnet Technologies, Inc. + +OUI:000163* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000164* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000165* + ID_OUI_FROM_DATABASE=AirSwitch Corporation + +OUI:000166* + ID_OUI_FROM_DATABASE=TC GROUP A/S + +OUI:000167* + ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION + +OUI:000168* + ID_OUI_FROM_DATABASE=VITANA CORPORATION + +OUI:000169* + ID_OUI_FROM_DATABASE=Celestix Networks Pte Ltd. + +OUI:00016A* + ID_OUI_FROM_DATABASE=ALITEC + +OUI:00016B* + ID_OUI_FROM_DATABASE=LightChip, Inc. + +OUI:00016C* + ID_OUI_FROM_DATABASE=FOXCONN + +OUI:00016D* + ID_OUI_FROM_DATABASE=CarrierComm Inc. + +OUI:00016E* + ID_OUI_FROM_DATABASE=Conklin Corporation + +OUI:00016F* + ID_OUI_FROM_DATABASE=Inkel Corp. + +OUI:000170* + ID_OUI_FROM_DATABASE=ESE Embedded System Engineer'g + +OUI:000171* + ID_OUI_FROM_DATABASE=Allied Data Technologies + +OUI:000172* + ID_OUI_FROM_DATABASE=TechnoLand Co., LTD. + +OUI:000173* + ID_OUI_FROM_DATABASE=AMCC + +OUI:000174* + ID_OUI_FROM_DATABASE=CyberOptics Corporation + +OUI:000175* + ID_OUI_FROM_DATABASE=Radiant Communications Corp. + +OUI:000176* + ID_OUI_FROM_DATABASE=Orient Silver Enterprises + +OUI:000177* + ID_OUI_FROM_DATABASE=EDSL + +OUI:000178* + ID_OUI_FROM_DATABASE=MARGI Systems, Inc. + +OUI:000179* + ID_OUI_FROM_DATABASE=WIRELESS TECHNOLOGY, INC. + +OUI:00017A* + ID_OUI_FROM_DATABASE=Chengdu Maipu Electric Industrial Co., Ltd. + +OUI:00017B* + ID_OUI_FROM_DATABASE=Heidelberger Druckmaschinen AG + +OUI:00017C* + ID_OUI_FROM_DATABASE=AG-E GmbH + +OUI:00017D* + ID_OUI_FROM_DATABASE=ThermoQuest + +OUI:00017E* + ID_OUI_FROM_DATABASE=ADTEK System Science Co., Ltd. + +OUI:00017F* + ID_OUI_FROM_DATABASE=Experience Music Project + +OUI:000180* + ID_OUI_FROM_DATABASE=AOpen, Inc. + +OUI:000181* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000182* + ID_OUI_FROM_DATABASE=DICA TECHNOLOGIES AG + +OUI:000183* + ID_OUI_FROM_DATABASE=ANITE TELECOMS + +OUI:000184* + ID_OUI_FROM_DATABASE=SIEB & MEYER AG + +OUI:000185* + ID_OUI_FROM_DATABASE=Hitachi Aloka Medical, Ltd. + +OUI:000186* + ID_OUI_FROM_DATABASE=Uwe Disch + +OUI:000187* + ID_OUI_FROM_DATABASE=I2SE GmbH + +OUI:000188* + ID_OUI_FROM_DATABASE=LXCO Technologies ag + +OUI:000189* + ID_OUI_FROM_DATABASE=Refraction Technology, Inc. + +OUI:00018A* + ID_OUI_FROM_DATABASE=ROI COMPUTER AG + +OUI:00018B* + ID_OUI_FROM_DATABASE=NetLinks Co., Ltd. + +OUI:00018C* + ID_OUI_FROM_DATABASE=Mega Vision + +OUI:00018D* + ID_OUI_FROM_DATABASE=AudeSi Technologies + +OUI:00018E* + ID_OUI_FROM_DATABASE=Logitec Corporation + +OUI:00018F* + ID_OUI_FROM_DATABASE=Kenetec, Inc. + +OUI:000190* + ID_OUI_FROM_DATABASE=SMK-M + +OUI:000191* + ID_OUI_FROM_DATABASE=SYRED Data Systems + +OUI:000192* + ID_OUI_FROM_DATABASE=Texas Digital Systems + +OUI:000193* + ID_OUI_FROM_DATABASE=Hanbyul Telecom Co., Ltd. + +OUI:000194* + ID_OUI_FROM_DATABASE=Capital Equipment Corporation + +OUI:000195* + ID_OUI_FROM_DATABASE=Sena Technologies, Inc. + +OUI:000196* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000197* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000198* + ID_OUI_FROM_DATABASE=Darim Vision + +OUI:000199* + ID_OUI_FROM_DATABASE=HeiSei Electronics + +OUI:00019A* + ID_OUI_FROM_DATABASE=LEUNIG GmbH + +OUI:00019B* + ID_OUI_FROM_DATABASE=Kyoto Microcomputer Co., Ltd. + +OUI:00019C* + ID_OUI_FROM_DATABASE=JDS Uniphase Inc. + +OUI:00019D* + ID_OUI_FROM_DATABASE=E-Control Systems, Inc. + +OUI:00019E* + ID_OUI_FROM_DATABASE=ESS Technology, Inc. + +OUI:00019F* + ID_OUI_FROM_DATABASE=ReadyNet + +OUI:0001A0* + ID_OUI_FROM_DATABASE=Infinilink Corporation + +OUI:0001A1* + ID_OUI_FROM_DATABASE=Mag-Tek, Inc. + +OUI:0001A2* + ID_OUI_FROM_DATABASE=Logical Co., Ltd. + +OUI:0001A3* + ID_OUI_FROM_DATABASE=GENESYS LOGIC, INC. + +OUI:0001A4* + ID_OUI_FROM_DATABASE=Microlink Corporation + +OUI:0001A5* + ID_OUI_FROM_DATABASE=Nextcomm, Inc. + +OUI:0001A6* + ID_OUI_FROM_DATABASE=Scientific-Atlanta Arcodan A/S + +OUI:0001A7* + ID_OUI_FROM_DATABASE=UNEX TECHNOLOGY CORPORATION + +OUI:0001A8* + ID_OUI_FROM_DATABASE=Welltech Computer Co., Ltd. + +OUI:0001A9* + ID_OUI_FROM_DATABASE=BMW AG + +OUI:0001AA* + ID_OUI_FROM_DATABASE=Airspan Communications, Ltd. + +OUI:0001AB* + ID_OUI_FROM_DATABASE=Main Street Networks + +OUI:0001AC* + ID_OUI_FROM_DATABASE=Sitara Networks, Inc. + +OUI:0001AD* + ID_OUI_FROM_DATABASE=Coach Master International d.b.a. CMI Worldwide, Inc. + +OUI:0001AE* + ID_OUI_FROM_DATABASE=Trex Enterprises + +OUI:0001AF* + ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies + +OUI:0001B0* + ID_OUI_FROM_DATABASE=Fulltek Technology Co., Ltd. + +OUI:0001B1* + ID_OUI_FROM_DATABASE=General Bandwidth + +OUI:0001B2* + ID_OUI_FROM_DATABASE=Digital Processing Systems, Inc. + +OUI:0001B3* + ID_OUI_FROM_DATABASE=Precision Electronic Manufacturing + +OUI:0001B4* + ID_OUI_FROM_DATABASE=Wayport, Inc. + +OUI:0001B5* + ID_OUI_FROM_DATABASE=Turin Networks, Inc. + +OUI:0001B6* + ID_OUI_FROM_DATABASE=SAEJIN T&M Co., Ltd. + +OUI:0001B7* + ID_OUI_FROM_DATABASE=Centos, Inc. + +OUI:0001B8* + ID_OUI_FROM_DATABASE=Netsensity, Inc. + +OUI:0001B9* + ID_OUI_FROM_DATABASE=SKF (U.K.) Limited + +OUI:0001BA* + ID_OUI_FROM_DATABASE=IC-Net, Inc. + +OUI:0001BB* + ID_OUI_FROM_DATABASE=Frequentis + +OUI:0001BC* + ID_OUI_FROM_DATABASE=Brains Corporation + +OUI:0001BD* + ID_OUI_FROM_DATABASE=Peterson Electro-Musical Products, Inc. + +OUI:0001BE* + ID_OUI_FROM_DATABASE=Gigalink Co., Ltd. + +OUI:0001BF* + ID_OUI_FROM_DATABASE=Teleforce Co., Ltd. + +OUI:0001C0* + ID_OUI_FROM_DATABASE=CompuLab, Ltd. + +OUI:0001C1* + ID_OUI_FROM_DATABASE=Vitesse Semiconductor Corporation + +OUI:0001C2* + ID_OUI_FROM_DATABASE=ARK Research Corp. + +OUI:0001C3* + ID_OUI_FROM_DATABASE=Acromag, Inc. + +OUI:0001C4* + ID_OUI_FROM_DATABASE=NeoWave, Inc. + +OUI:0001C5* + ID_OUI_FROM_DATABASE=Simpler Networks + +OUI:0001C6* + ID_OUI_FROM_DATABASE=Quarry Technologies + +OUI:0001C7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0001C8* + ID_OUI_FROM_DATABASE=THOMAS CONRAD CORP. + +OUI:0001C9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0001CA* + ID_OUI_FROM_DATABASE=Geocast Network Systems, Inc. + +OUI:0001CB* + ID_OUI_FROM_DATABASE=EVR + +OUI:0001CC* + ID_OUI_FROM_DATABASE=Japan Total Design Communication Co., Ltd. + +OUI:0001CD* + ID_OUI_FROM_DATABASE=ARtem + +OUI:0001CE* + ID_OUI_FROM_DATABASE=Custom Micro Products, Ltd. + +OUI:0001CF* + ID_OUI_FROM_DATABASE=Alpha Data Parallel Systems, Ltd. + +OUI:0001D0* + ID_OUI_FROM_DATABASE=VitalPoint, Inc. + +OUI:0001D1* + ID_OUI_FROM_DATABASE=CoNet Communications, Inc. + +OUI:0001D2* + ID_OUI_FROM_DATABASE=inXtron, Inc. + +OUI:0001D3* + ID_OUI_FROM_DATABASE=PAXCOMM, Inc. + +OUI:0001D4* + ID_OUI_FROM_DATABASE=Leisure Time, Inc. + +OUI:0001D5* + ID_OUI_FROM_DATABASE=HAEDONG INFO & COMM CO., LTD + +OUI:0001D6* + ID_OUI_FROM_DATABASE=manroland AG + +OUI:0001D7* + ID_OUI_FROM_DATABASE=F5 Networks, Inc. + +OUI:0001D8* + ID_OUI_FROM_DATABASE=Teltronics, Inc. + +OUI:0001D9* + ID_OUI_FROM_DATABASE=Sigma, Inc. + +OUI:0001DA* + ID_OUI_FROM_DATABASE=WINCOMM Corporation + +OUI:0001DB* + ID_OUI_FROM_DATABASE=Freecom Technologies GmbH + +OUI:0001DC* + ID_OUI_FROM_DATABASE=Activetelco + +OUI:0001DD* + ID_OUI_FROM_DATABASE=Avail Networks + +OUI:0001DE* + ID_OUI_FROM_DATABASE=Trango Systems, Inc. + +OUI:0001DF* + ID_OUI_FROM_DATABASE=ISDN Communications, Ltd. + +OUI:0001E0* + ID_OUI_FROM_DATABASE=Fast Systems, Inc. + +OUI:0001E1* + ID_OUI_FROM_DATABASE=Kinpo Electronics, Inc. + +OUI:0001E2* + ID_OUI_FROM_DATABASE=Ando Electric Corporation + +OUI:0001E3* + ID_OUI_FROM_DATABASE=Siemens AG + +OUI:0001E4* + ID_OUI_FROM_DATABASE=Sitera, Inc. + +OUI:0001E5* + ID_OUI_FROM_DATABASE=Supernet, Inc. + +OUI:0001E6* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0001E7* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0001E8* + ID_OUI_FROM_DATABASE=Force10 Networks, Inc. + +OUI:0001E9* + ID_OUI_FROM_DATABASE=Litton Marine Systems B.V. + +OUI:0001EA* + ID_OUI_FROM_DATABASE=Cirilium Corp. + +OUI:0001EB* + ID_OUI_FROM_DATABASE=C-COM Corporation + +OUI:0001EC* + ID_OUI_FROM_DATABASE=Ericsson Group + +OUI:0001ED* + ID_OUI_FROM_DATABASE=SETA Corp. + +OUI:0001EE* + ID_OUI_FROM_DATABASE=Comtrol Europe, Ltd. + +OUI:0001EF* + ID_OUI_FROM_DATABASE=Camtel Technology Corp. + +OUI:0001F0* + ID_OUI_FROM_DATABASE=Tridium, Inc. + +OUI:0001F1* + ID_OUI_FROM_DATABASE=Innovative Concepts, Inc. + +OUI:0001F2* + ID_OUI_FROM_DATABASE=Mark of the Unicorn, Inc. + +OUI:0001F3* + ID_OUI_FROM_DATABASE=QPS, Inc. + +OUI:0001F4* + ID_OUI_FROM_DATABASE=Enterasys + +OUI:0001F5* + ID_OUI_FROM_DATABASE=ERIM S.A. + +OUI:0001F6* + ID_OUI_FROM_DATABASE=Association of Musical Electronics Industry + +OUI:0001F7* + ID_OUI_FROM_DATABASE=Image Display Systems, Inc. + +OUI:0001F8* + ID_OUI_FROM_DATABASE=TEXIO TECHNOLOGY CORPORATION + +OUI:0001F9* + ID_OUI_FROM_DATABASE=TeraGlobal Communications Corp. + +OUI:0001FA* + ID_OUI_FROM_DATABASE=HOROSCAS + +OUI:0001FB* + ID_OUI_FROM_DATABASE=DoTop Technology, Inc. + +OUI:0001FC* + ID_OUI_FROM_DATABASE=Keyence Corporation + +OUI:0001FD* + ID_OUI_FROM_DATABASE=Digital Voice Systems, Inc. + +OUI:0001FE* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION + +OUI:0001FF* + ID_OUI_FROM_DATABASE=Data Direct Networks, Inc. + +OUI:000200* + ID_OUI_FROM_DATABASE=Net & Sys Co., Ltd. + +OUI:000201* + ID_OUI_FROM_DATABASE=IFM Electronic gmbh + +OUI:000202* + ID_OUI_FROM_DATABASE=Amino Communications, Ltd. + +OUI:000203* + ID_OUI_FROM_DATABASE=Woonsang Telecom, Inc. + +OUI:000204* + ID_OUI_FROM_DATABASE=Bodmann Industries Elektronik GmbH + +OUI:000205* + ID_OUI_FROM_DATABASE=Hitachi Denshi, Ltd. + +OUI:000206* + ID_OUI_FROM_DATABASE=Telital R&D Denmark A/S + +OUI:000207* + ID_OUI_FROM_DATABASE=VisionGlobal Network Corp. + +OUI:000208* + ID_OUI_FROM_DATABASE=Unify Networks, Inc. + +OUI:000209* + ID_OUI_FROM_DATABASE=Shenzhen SED Information Technology Co., Ltd. + +OUI:00020A* + ID_OUI_FROM_DATABASE=Gefran Spa + +OUI:00020B* + ID_OUI_FROM_DATABASE=Native Networks, Inc. + +OUI:00020C* + ID_OUI_FROM_DATABASE=Metro-Optix + +OUI:00020D* + ID_OUI_FROM_DATABASE=Micronpc.com + +OUI:00020E* + ID_OUI_FROM_DATABASE=ECI Telecom Ltd. + +OUI:00020F* + ID_OUI_FROM_DATABASE=AATR + +OUI:000210* + ID_OUI_FROM_DATABASE=Fenecom + +OUI:000211* + ID_OUI_FROM_DATABASE=Nature Worldwide Technology Corp. + +OUI:000212* + ID_OUI_FROM_DATABASE=SierraCom + +OUI:000213* + ID_OUI_FROM_DATABASE=S.D.E.L. + +OUI:000214* + ID_OUI_FROM_DATABASE=DTVRO + +OUI:000215* + ID_OUI_FROM_DATABASE=Cotas Computer Technology A/B + +OUI:000216* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000217* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000218* + ID_OUI_FROM_DATABASE=Advanced Scientific Corp + +OUI:000219* + ID_OUI_FROM_DATABASE=Paralon Technologies + +OUI:00021A* + ID_OUI_FROM_DATABASE=Zuma Networks + +OUI:00021B* + ID_OUI_FROM_DATABASE=Kollmorgen-Servotronix + +OUI:00021C* + ID_OUI_FROM_DATABASE=Network Elements, Inc. + +OUI:00021D* + ID_OUI_FROM_DATABASE=Data General Communication Ltd. + +OUI:00021E* + ID_OUI_FROM_DATABASE=SIMTEL S.R.L. + +OUI:00021F* + ID_OUI_FROM_DATABASE=Aculab PLC + +OUI:000220* + ID_OUI_FROM_DATABASE=CANON FINETECH INC. + +OUI:000221* + ID_OUI_FROM_DATABASE=DSP Application, Ltd. + +OUI:000222* + ID_OUI_FROM_DATABASE=Chromisys, Inc. + +OUI:000223* + ID_OUI_FROM_DATABASE=ClickTV + +OUI:000224* + ID_OUI_FROM_DATABASE=C-COR + +OUI:000225* + ID_OUI_FROM_DATABASE=One Stop Systems + +OUI:000226* + ID_OUI_FROM_DATABASE=XESystems, Inc. + +OUI:000227* + ID_OUI_FROM_DATABASE=ESD Electronic System Design GmbH + +OUI:000228* + ID_OUI_FROM_DATABASE=Necsom, Ltd. + +OUI:000229* + ID_OUI_FROM_DATABASE=Adtec Corporation + +OUI:00022A* + ID_OUI_FROM_DATABASE=Asound Electronic + +OUI:00022B* + ID_OUI_FROM_DATABASE=SAXA, Inc. + +OUI:00022C* + ID_OUI_FROM_DATABASE=ABB Bomem, Inc. + +OUI:00022D* + ID_OUI_FROM_DATABASE=Agere Systems + +OUI:00022E* + ID_OUI_FROM_DATABASE=TEAC Corp. R& D + +OUI:00022F* + ID_OUI_FROM_DATABASE=P-Cube, Ltd. + +OUI:000230* + ID_OUI_FROM_DATABASE=Intersoft Electronics + +OUI:000231* + ID_OUI_FROM_DATABASE=Ingersoll-Rand + +OUI:000232* + ID_OUI_FROM_DATABASE=Avision, Inc. + +OUI:000233* + ID_OUI_FROM_DATABASE=Mantra Communications, Inc. + +OUI:000234* + ID_OUI_FROM_DATABASE=Imperial Technology, Inc. + +OUI:000235* + ID_OUI_FROM_DATABASE=Paragon Networks International + +OUI:000236* + ID_OUI_FROM_DATABASE=INIT GmbH + +OUI:000237* + ID_OUI_FROM_DATABASE=Cosmo Research Corp. + +OUI:000238* + ID_OUI_FROM_DATABASE=Serome Technology, Inc. + +OUI:000239* + ID_OUI_FROM_DATABASE=Visicom + +OUI:00023A* + ID_OUI_FROM_DATABASE=ZSK Stickmaschinen GmbH + +OUI:00023B* + ID_OUI_FROM_DATABASE=Ericsson + +OUI:00023C* + ID_OUI_FROM_DATABASE=Creative Technology, Ltd. + +OUI:00023D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00023E* + ID_OUI_FROM_DATABASE=Selta Telematica S.p.a + +OUI:00023F* + ID_OUI_FROM_DATABASE=Compal Electronics INC. + +OUI:000240* + ID_OUI_FROM_DATABASE=Seedek Co., Ltd. + +OUI:000241* + ID_OUI_FROM_DATABASE=Amer.com + +OUI:000242* + ID_OUI_FROM_DATABASE=Videoframe Systems + +OUI:000243* + ID_OUI_FROM_DATABASE=Raysis Co., Ltd. + +OUI:000244* + ID_OUI_FROM_DATABASE=SURECOM Technology Co. + +OUI:000245* + ID_OUI_FROM_DATABASE=Lampus Co, Ltd. + +OUI:000246* + ID_OUI_FROM_DATABASE=All-Win Tech Co., Ltd. + +OUI:000247* + ID_OUI_FROM_DATABASE=Great Dragon Information Technology (Group) Co., Ltd. + +OUI:000248* + ID_OUI_FROM_DATABASE=Pilz GmbH & Co. + +OUI:000249* + ID_OUI_FROM_DATABASE=Aviv Infocom Co, Ltd. + +OUI:00024A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00024B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00024C* + ID_OUI_FROM_DATABASE=SiByte, Inc. + +OUI:00024D* + ID_OUI_FROM_DATABASE=Mannesman Dematic Colby Pty. Ltd. + +OUI:00024E* + ID_OUI_FROM_DATABASE=Datacard Group + +OUI:00024F* + ID_OUI_FROM_DATABASE=IPM Datacom S.R.L. + +OUI:000250* + ID_OUI_FROM_DATABASE=Geyser Networks, Inc. + +OUI:000251* + ID_OUI_FROM_DATABASE=Soma Networks, Inc. + +OUI:000252* + ID_OUI_FROM_DATABASE=Carrier Corporation + +OUI:000253* + ID_OUI_FROM_DATABASE=Televideo, Inc. + +OUI:000254* + ID_OUI_FROM_DATABASE=WorldGate + +OUI:000255* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:000256* + ID_OUI_FROM_DATABASE=Alpha Processor, Inc. + +OUI:000257* + ID_OUI_FROM_DATABASE=Microcom Corp. + +OUI:000258* + ID_OUI_FROM_DATABASE=Flying Packets Communications + +OUI:000259* + ID_OUI_FROM_DATABASE=Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group + +OUI:00025A* + ID_OUI_FROM_DATABASE=Catena Networks + +OUI:00025B* + ID_OUI_FROM_DATABASE=Cambridge Silicon Radio + +OUI:00025C* + ID_OUI_FROM_DATABASE=SCI Systems (Kunshan) Co., Ltd. + +OUI:00025D* + ID_OUI_FROM_DATABASE=Calix Networks + +OUI:00025E* + ID_OUI_FROM_DATABASE=High Technology Ltd + +OUI:00025F* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000260* + ID_OUI_FROM_DATABASE=Accordion Networks, Inc. + +OUI:000261* + ID_OUI_FROM_DATABASE=Tilgin AB + +OUI:000262* + ID_OUI_FROM_DATABASE=Soyo Group Soyo Com Tech Co., Ltd + +OUI:000263* + ID_OUI_FROM_DATABASE=UPS Manufacturing SRL + +OUI:000264* + ID_OUI_FROM_DATABASE=AudioRamp.com + +OUI:000265* + ID_OUI_FROM_DATABASE=Virditech Co. Ltd. + +OUI:000266* + ID_OUI_FROM_DATABASE=Thermalogic Corporation + +OUI:000267* + ID_OUI_FROM_DATABASE=NODE RUNNER, INC. + +OUI:000268* + ID_OUI_FROM_DATABASE=Harris Government Communications + +OUI:000269* + ID_OUI_FROM_DATABASE=Nadatel Co., Ltd + +OUI:00026A* + ID_OUI_FROM_DATABASE=Cocess Telecom Co., Ltd. + +OUI:00026B* + ID_OUI_FROM_DATABASE=BCM Computers Co., Ltd. + +OUI:00026C* + ID_OUI_FROM_DATABASE=Philips CFT + +OUI:00026D* + ID_OUI_FROM_DATABASE=Adept Telecom + +OUI:00026E* + ID_OUI_FROM_DATABASE=NeGeN Access, Inc. + +OUI:00026F* + ID_OUI_FROM_DATABASE=Senao International Co., Ltd. + +OUI:000270* + ID_OUI_FROM_DATABASE=Crewave Co., Ltd. + +OUI:000271* + ID_OUI_FROM_DATABASE=Zhone Technologies + +OUI:000272* + ID_OUI_FROM_DATABASE=CC&C Technologies, Inc. + +OUI:000273* + ID_OUI_FROM_DATABASE=Coriolis Networks + +OUI:000274* + ID_OUI_FROM_DATABASE=Tommy Technologies Corp. + +OUI:000275* + ID_OUI_FROM_DATABASE=SMART Technologies, Inc. + +OUI:000276* + ID_OUI_FROM_DATABASE=Primax Electronics Ltd. + +OUI:000277* + ID_OUI_FROM_DATABASE=Cash Systemes Industrie + +OUI:000278* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:000279* + ID_OUI_FROM_DATABASE=Control Applications, Ltd. + +OUI:00027A* + ID_OUI_FROM_DATABASE=IOI Technology Corporation + +OUI:00027B* + ID_OUI_FROM_DATABASE=Amplify Net, Inc. + +OUI:00027C* + ID_OUI_FROM_DATABASE=Trilithic, Inc. + +OUI:00027D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00027E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00027F* + ID_OUI_FROM_DATABASE=ask-technologies.com + +OUI:000280* + ID_OUI_FROM_DATABASE=Mu Net, Inc. + +OUI:000281* + ID_OUI_FROM_DATABASE=Madge Ltd. + +OUI:000282* + ID_OUI_FROM_DATABASE=ViaClix, Inc. + +OUI:000283* + ID_OUI_FROM_DATABASE=Spectrum Controls, Inc. + +OUI:000284* + ID_OUI_FROM_DATABASE=UK Grid Solutions Limited + +OUI:000285* + ID_OUI_FROM_DATABASE=Riverstone Networks + +OUI:000286* + ID_OUI_FROM_DATABASE=Occam Networks + +OUI:000287* + ID_OUI_FROM_DATABASE=Adapcom + +OUI:000288* + ID_OUI_FROM_DATABASE=GLOBAL VILLAGE COMMUNICATION + +OUI:000289* + ID_OUI_FROM_DATABASE=DNE Technologies + +OUI:00028A* + ID_OUI_FROM_DATABASE=Ambit Microsystems Corporation + +OUI:00028B* + ID_OUI_FROM_DATABASE=VDSL Systems OY + +OUI:00028C* + ID_OUI_FROM_DATABASE=Micrel-Synergy Semiconductor + +OUI:00028D* + ID_OUI_FROM_DATABASE=Movita Technologies, Inc. + +OUI:00028E* + ID_OUI_FROM_DATABASE=Rapid 5 Networks, Inc. + +OUI:00028F* + ID_OUI_FROM_DATABASE=Globetek, Inc. + +OUI:000290* + ID_OUI_FROM_DATABASE=Woorigisool, Inc. + +OUI:000291* + ID_OUI_FROM_DATABASE=Open Network Co., Ltd. + +OUI:000292* + ID_OUI_FROM_DATABASE=Logic Innovations, Inc. + +OUI:000293* + ID_OUI_FROM_DATABASE=Solid Data Systems + +OUI:000294* + ID_OUI_FROM_DATABASE=Tokyo Sokushin Co., Ltd. + +OUI:000295* + ID_OUI_FROM_DATABASE=IP.Access Limited + +OUI:000296* + ID_OUI_FROM_DATABASE=Lectron Co,. Ltd. + +OUI:000297* + ID_OUI_FROM_DATABASE=C-COR.net + +OUI:000298* + ID_OUI_FROM_DATABASE=Broadframe Corporation + +OUI:000299* + ID_OUI_FROM_DATABASE=Apex, Inc. + +OUI:00029A* + ID_OUI_FROM_DATABASE=Storage Apps + +OUI:00029B* + ID_OUI_FROM_DATABASE=Kreatel Communications AB + +OUI:00029C* + ID_OUI_FROM_DATABASE=3COM + +OUI:00029D* + ID_OUI_FROM_DATABASE=Merix Corp. + +OUI:00029E* + ID_OUI_FROM_DATABASE=Information Equipment Co., Ltd. + +OUI:00029F* + ID_OUI_FROM_DATABASE=L-3 Communication Aviation Recorders + +OUI:0002A0* + ID_OUI_FROM_DATABASE=Flatstack Ltd. + +OUI:0002A1* + ID_OUI_FROM_DATABASE=World Wide Packets + +OUI:0002A2* + ID_OUI_FROM_DATABASE=Hilscher GmbH + +OUI:0002A3* + ID_OUI_FROM_DATABASE=ABB Switzerland Ltd, Power Systems + +OUI:0002A4* + ID_OUI_FROM_DATABASE=AddPac Technology Co., Ltd. + +OUI:0002A5* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0002A6* + ID_OUI_FROM_DATABASE=Effinet Systems Co., Ltd. + +OUI:0002A7* + ID_OUI_FROM_DATABASE=Vivace Networks + +OUI:0002A8* + ID_OUI_FROM_DATABASE=Air Link Technology + +OUI:0002A9* + ID_OUI_FROM_DATABASE=RACOM, s.r.o. + +OUI:0002AA* + ID_OUI_FROM_DATABASE=PLcom Co., Ltd. + +OUI:0002AB* + ID_OUI_FROM_DATABASE=CTC Union Technologies Co., Ltd. + +OUI:0002AC* + ID_OUI_FROM_DATABASE=3PAR data + +OUI:0002AD* + ID_OUI_FROM_DATABASE=HOYA Corporation + +OUI:0002AE* + ID_OUI_FROM_DATABASE=Scannex Electronics Ltd. + +OUI:0002AF* + ID_OUI_FROM_DATABASE=TeleCruz Technology, Inc. + +OUI:0002B0* + ID_OUI_FROM_DATABASE=Hokubu Communication & Industrial Co., Ltd. + +OUI:0002B1* + ID_OUI_FROM_DATABASE=Anritsu, Ltd. + +OUI:0002B2* + ID_OUI_FROM_DATABASE=Cablevision + +OUI:0002B3* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:0002B4* + ID_OUI_FROM_DATABASE=DAPHNE + +OUI:0002B5* + ID_OUI_FROM_DATABASE=Avnet, Inc. + +OUI:0002B6* + ID_OUI_FROM_DATABASE=Acrosser Technology Co., Ltd. + +OUI:0002B7* + ID_OUI_FROM_DATABASE=Watanabe Electric Industry Co., Ltd. + +OUI:0002B8* + ID_OUI_FROM_DATABASE=WHI KONSULT AB + +OUI:0002B9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0002BA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0002BB* + ID_OUI_FROM_DATABASE=Continuous Computing Corp + +OUI:0002BC* + ID_OUI_FROM_DATABASE=LVL 7 Systems, Inc. + +OUI:0002BD* + ID_OUI_FROM_DATABASE=Bionet Co., Ltd. + +OUI:0002BE* + ID_OUI_FROM_DATABASE=Totsu Engineering, Inc. + +OUI:0002BF* + ID_OUI_FROM_DATABASE=dotRocket, Inc. + +OUI:0002C0* + ID_OUI_FROM_DATABASE=Bencent Tzeng Industry Co., Ltd. + +OUI:0002C1* + ID_OUI_FROM_DATABASE=Innovative Electronic Designs, Inc. + +OUI:0002C2* + ID_OUI_FROM_DATABASE=Net Vision Telecom + +OUI:0002C3* + ID_OUI_FROM_DATABASE=Arelnet Ltd. + +OUI:0002C4* + ID_OUI_FROM_DATABASE=Vector International BVBA + +OUI:0002C5* + ID_OUI_FROM_DATABASE=Evertz Microsystems Ltd. + +OUI:0002C6* + ID_OUI_FROM_DATABASE=Data Track Technology PLC + +OUI:0002C7* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:0002C8* + ID_OUI_FROM_DATABASE=Technocom Communications Technology (pte) Ltd + +OUI:0002C9* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:0002CA* + ID_OUI_FROM_DATABASE=EndPoints, Inc. + +OUI:0002CB* + ID_OUI_FROM_DATABASE=TriState Ltd. + +OUI:0002CC* + ID_OUI_FROM_DATABASE=M.C.C.I + +OUI:0002CD* + ID_OUI_FROM_DATABASE=TeleDream, Inc. + +OUI:0002CE* + ID_OUI_FROM_DATABASE=FoxJet, Inc. + +OUI:0002CF* + ID_OUI_FROM_DATABASE=ZyGate Communications, Inc. + +OUI:0002D0* + ID_OUI_FROM_DATABASE=Comdial Corporation + +OUI:0002D1* + ID_OUI_FROM_DATABASE=Vivotek, Inc. + +OUI:0002D2* + ID_OUI_FROM_DATABASE=Workstation AG + +OUI:0002D3* + ID_OUI_FROM_DATABASE=NetBotz, Inc. + +OUI:0002D4* + ID_OUI_FROM_DATABASE=PDA Peripherals, Inc. + +OUI:0002D5* + ID_OUI_FROM_DATABASE=ACR + +OUI:0002D6* + ID_OUI_FROM_DATABASE=NICE Systems + +OUI:0002D7* + ID_OUI_FROM_DATABASE=EMPEG Ltd + +OUI:0002D8* + ID_OUI_FROM_DATABASE=BRECIS Communications Corporation + +OUI:0002D9* + ID_OUI_FROM_DATABASE=Reliable Controls + +OUI:0002DA* + ID_OUI_FROM_DATABASE=ExiO Communications, Inc. + +OUI:0002DB* + ID_OUI_FROM_DATABASE=NETSEC + +OUI:0002DC* + ID_OUI_FROM_DATABASE=Fujitsu General Limited + +OUI:0002DD* + ID_OUI_FROM_DATABASE=Bromax Communications, Ltd. + +OUI:0002DE* + ID_OUI_FROM_DATABASE=Astrodesign, Inc. + +OUI:0002DF* + ID_OUI_FROM_DATABASE=Net Com Systems, Inc. + +OUI:0002E0* + ID_OUI_FROM_DATABASE=ETAS GmbH + +OUI:0002E1* + ID_OUI_FROM_DATABASE=Integrated Network Corporation + +OUI:0002E2* + ID_OUI_FROM_DATABASE=NDC Infared Engineering + +OUI:0002E3* + ID_OUI_FROM_DATABASE=LITE-ON Communications, Inc. + +OUI:0002E4* + ID_OUI_FROM_DATABASE=JC HYUN Systems, Inc. + +OUI:0002E5* + ID_OUI_FROM_DATABASE=Timeware Ltd. + +OUI:0002E6* + ID_OUI_FROM_DATABASE=Gould Instrument Systems, Inc. + +OUI:0002E7* + ID_OUI_FROM_DATABASE=CAB GmbH & Co KG + +OUI:0002E8* + ID_OUI_FROM_DATABASE=E.D.&A. + +OUI:0002E9* + ID_OUI_FROM_DATABASE=CS Systemes De Securite - C3S + +OUI:0002EA* + ID_OUI_FROM_DATABASE=Focus Enhancements + +OUI:0002EB* + ID_OUI_FROM_DATABASE=Pico Communications + +OUI:0002EC* + ID_OUI_FROM_DATABASE=Maschoff Design Engineering + +OUI:0002ED* + ID_OUI_FROM_DATABASE=DXO Telecom Co., Ltd. + +OUI:0002EE* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0002EF* + ID_OUI_FROM_DATABASE=CCC Network Systems Group Ltd. + +OUI:0002F0* + ID_OUI_FROM_DATABASE=AME Optimedia Technology Co., Ltd. + +OUI:0002F1* + ID_OUI_FROM_DATABASE=Pinetron Co., Ltd. + +OUI:0002F2* + ID_OUI_FROM_DATABASE=eDevice, Inc. + +OUI:0002F3* + ID_OUI_FROM_DATABASE=Media Serve Co., Ltd. + +OUI:0002F4* + ID_OUI_FROM_DATABASE=PCTEL, Inc. + +OUI:0002F5* + ID_OUI_FROM_DATABASE=VIVE Synergies, Inc. + +OUI:0002F6* + ID_OUI_FROM_DATABASE=Equipe Communications + +OUI:0002F7* + ID_OUI_FROM_DATABASE=ARM + +OUI:0002F8* + ID_OUI_FROM_DATABASE=SEAKR Engineering, Inc. + +OUI:0002F9* + ID_OUI_FROM_DATABASE=MIMOS Berhad + +OUI:0002FA* + ID_OUI_FROM_DATABASE=DX Antenna Co., Ltd. + +OUI:0002FB* + ID_OUI_FROM_DATABASE=Baumuller Aulugen-Systemtechnik GmbH + +OUI:0002FC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0002FD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0002FE* + ID_OUI_FROM_DATABASE=Viditec, Inc. + +OUI:0002FF* + ID_OUI_FROM_DATABASE=Handan BroadInfoCom + +OUI:000300* + ID_OUI_FROM_DATABASE=Barracuda Networks, Inc. + +OUI:000301* + ID_OUI_FROM_DATABASE=EXFO + +OUI:000302* + ID_OUI_FROM_DATABASE=Charles Industries, Ltd. + +OUI:000303* + ID_OUI_FROM_DATABASE=JAMA Electronics Co., Ltd. + +OUI:000304* + ID_OUI_FROM_DATABASE=Pacific Broadband Communications + +OUI:000305* + ID_OUI_FROM_DATABASE=MSC Vertriebs GmbH + +OUI:000306* + ID_OUI_FROM_DATABASE=Fusion In Tech Co., Ltd. + +OUI:000307* + ID_OUI_FROM_DATABASE=Secure Works, Inc. + +OUI:000308* + ID_OUI_FROM_DATABASE=AM Communications, Inc. + +OUI:000309* + ID_OUI_FROM_DATABASE=Texcel Technology PLC + +OUI:00030A* + ID_OUI_FROM_DATABASE=Argus Technologies + +OUI:00030B* + ID_OUI_FROM_DATABASE=Hunter Technology, Inc. + +OUI:00030C* + ID_OUI_FROM_DATABASE=Telesoft Technologies Ltd. + +OUI:00030D* + ID_OUI_FROM_DATABASE=Uniwill Computer Corp. + +OUI:00030E* + ID_OUI_FROM_DATABASE=Core Communications Co., Ltd. + +OUI:00030F* + ID_OUI_FROM_DATABASE=Digital China (Shanghai) Networks Ltd. + +OUI:000310* + ID_OUI_FROM_DATABASE=E-Globaledge Corporation + +OUI:000311* + ID_OUI_FROM_DATABASE=Micro Technology Co., Ltd. + +OUI:000312* + ID_OUI_FROM_DATABASE=TRsystems GmbH + +OUI:000313* + ID_OUI_FROM_DATABASE=Access Media SPA + +OUI:000314* + ID_OUI_FROM_DATABASE=Teleware Network Systems + +OUI:000315* + ID_OUI_FROM_DATABASE=Cidco Incorporated + +OUI:000316* + ID_OUI_FROM_DATABASE=Nobell Communications, Inc. + +OUI:000317* + ID_OUI_FROM_DATABASE=Merlin Systems, Inc. + +OUI:000318* + ID_OUI_FROM_DATABASE=Cyras Systems, Inc. + +OUI:000319* + ID_OUI_FROM_DATABASE=Infineon AG + +OUI:00031A* + ID_OUI_FROM_DATABASE=Beijing Broad Telecom Ltd., China + +OUI:00031B* + ID_OUI_FROM_DATABASE=Cellvision Systems, Inc. + +OUI:00031C* + ID_OUI_FROM_DATABASE=Svenska Hardvarufabriken AB + +OUI:00031D* + ID_OUI_FROM_DATABASE=Taiwan Commate Computer, Inc. + +OUI:00031E* + ID_OUI_FROM_DATABASE=Optranet, Inc. + +OUI:00031F* + ID_OUI_FROM_DATABASE=Condev Ltd. + +OUI:000320* + ID_OUI_FROM_DATABASE=Xpeed, Inc. + +OUI:000321* + ID_OUI_FROM_DATABASE=Reco Research Co., Ltd. + +OUI:000322* + ID_OUI_FROM_DATABASE=IDIS Co., Ltd. + +OUI:000323* + ID_OUI_FROM_DATABASE=Cornet Technology, Inc. + +OUI:000324* + ID_OUI_FROM_DATABASE=SANYO Consumer Electronics Co., Ltd. + +OUI:000325* + ID_OUI_FROM_DATABASE=Arima Computer Corp. + +OUI:000326* + ID_OUI_FROM_DATABASE=Iwasaki Information Systems Co., Ltd. + +OUI:000327* + ID_OUI_FROM_DATABASE=ACT'L + +OUI:000328* + ID_OUI_FROM_DATABASE=Mace Group, Inc. + +OUI:000329* + ID_OUI_FROM_DATABASE=F3, Inc. + +OUI:00032A* + ID_OUI_FROM_DATABASE=UniData Communication Systems, Inc. + +OUI:00032B* + ID_OUI_FROM_DATABASE=GAI Datenfunksysteme GmbH + +OUI:00032C* + ID_OUI_FROM_DATABASE=ABB Switzerland Ltd + +OUI:00032D* + ID_OUI_FROM_DATABASE=IBASE Technology, Inc. + +OUI:00032E* + ID_OUI_FROM_DATABASE=Scope Information Management, Ltd. + +OUI:00032F* + ID_OUI_FROM_DATABASE=Global Sun Technology, Inc. + +OUI:000330* + ID_OUI_FROM_DATABASE=Imagenics, Co., Ltd. + +OUI:000331* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000332* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000333* + ID_OUI_FROM_DATABASE=Digitel Co., Ltd. + +OUI:000334* + ID_OUI_FROM_DATABASE=Newport Electronics + +OUI:000335* + ID_OUI_FROM_DATABASE=Mirae Technology + +OUI:000336* + ID_OUI_FROM_DATABASE=Zetes Technologies + +OUI:000337* + ID_OUI_FROM_DATABASE=Vaone, Inc. + +OUI:000338* + ID_OUI_FROM_DATABASE=Oak Technology + +OUI:000339* + ID_OUI_FROM_DATABASE=Eurologic Systems, Ltd. + +OUI:00033A* + ID_OUI_FROM_DATABASE=Silicon Wave, Inc. + +OUI:00033B* + ID_OUI_FROM_DATABASE=TAMI Tech Co., Ltd. + +OUI:00033C* + ID_OUI_FROM_DATABASE=Daiden Co., Ltd. + +OUI:00033D* + ID_OUI_FROM_DATABASE=ILSHin Lab + +OUI:00033E* + ID_OUI_FROM_DATABASE=Tateyama System Laboratory Co., Ltd. + +OUI:00033F* + ID_OUI_FROM_DATABASE=BigBand Networks, Ltd. + +OUI:000340* + ID_OUI_FROM_DATABASE=Floware Wireless Systems, Ltd. + +OUI:000341* + ID_OUI_FROM_DATABASE=Axon Digital Design + +OUI:000342* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000343* + ID_OUI_FROM_DATABASE=Martin Professional A/S + +OUI:000344* + ID_OUI_FROM_DATABASE=Tietech.Co., Ltd. + +OUI:000345* + ID_OUI_FROM_DATABASE=Routrek Networks Corporation + +OUI:000346* + ID_OUI_FROM_DATABASE=Hitachi Kokusai Electric, Inc. + +OUI:000347* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:000348* + ID_OUI_FROM_DATABASE=Norscan Instruments, Ltd. + +OUI:000349* + ID_OUI_FROM_DATABASE=Vidicode Datacommunicatie B.V. + +OUI:00034A* + ID_OUI_FROM_DATABASE=RIAS Corporation + +OUI:00034B* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:00034C* + ID_OUI_FROM_DATABASE=Shanghai DigiVision Technology Co., Ltd. + +OUI:00034D* + ID_OUI_FROM_DATABASE=Chiaro Networks, Ltd. + +OUI:00034E* + ID_OUI_FROM_DATABASE=Pos Data Company, Ltd. + +OUI:00034F* + ID_OUI_FROM_DATABASE=Sur-Gard Security + +OUI:000350* + ID_OUI_FROM_DATABASE=BTICINO SPA + +OUI:000351* + ID_OUI_FROM_DATABASE=Diebold, Inc. + +OUI:000352* + ID_OUI_FROM_DATABASE=Colubris Networks + +OUI:000353* + ID_OUI_FROM_DATABASE=Mitac, Inc. + +OUI:000354* + ID_OUI_FROM_DATABASE=Fiber Logic Communications + +OUI:000355* + ID_OUI_FROM_DATABASE=TeraBeam Internet Systems + +OUI:000356* + ID_OUI_FROM_DATABASE=Wincor Nixdorf International GmbH + +OUI:000357* + ID_OUI_FROM_DATABASE=Intervoice-Brite, Inc. + +OUI:000358* + ID_OUI_FROM_DATABASE=Hanyang Digitech Co.Ltd + +OUI:000359* + ID_OUI_FROM_DATABASE=DigitalSis + +OUI:00035A* + ID_OUI_FROM_DATABASE=Photron Limited + +OUI:00035B* + ID_OUI_FROM_DATABASE=BridgeWave Communications + +OUI:00035C* + ID_OUI_FROM_DATABASE=Saint Song Corp. + +OUI:00035D* + ID_OUI_FROM_DATABASE=Bosung Hi-Net Co., Ltd. + +OUI:00035E* + ID_OUI_FROM_DATABASE=Metropolitan Area Networks, Inc. + +OUI:00035F* + ID_OUI_FROM_DATABASE=Prüftechnik Condition Monitoring GmbH & Co. KG + +OUI:000360* + ID_OUI_FROM_DATABASE=PAC Interactive Technology, Inc. + +OUI:000361* + ID_OUI_FROM_DATABASE=Widcomm, Inc. + +OUI:000362* + ID_OUI_FROM_DATABASE=Vodtel Communications, Inc. + +OUI:000363* + ID_OUI_FROM_DATABASE=Miraesys Co., Ltd. + +OUI:000364* + ID_OUI_FROM_DATABASE=Scenix Semiconductor, Inc. + +OUI:000365* + ID_OUI_FROM_DATABASE=Kira Information & Communications, Ltd. + +OUI:000366* + ID_OUI_FROM_DATABASE=ASM Pacific Technology + +OUI:000367* + ID_OUI_FROM_DATABASE=Jasmine Networks, Inc. + +OUI:000368* + ID_OUI_FROM_DATABASE=Embedone Co., Ltd. + +OUI:000369* + ID_OUI_FROM_DATABASE=Nippon Antenna Co., Ltd. + +OUI:00036A* + ID_OUI_FROM_DATABASE=Mainnet, Ltd. + +OUI:00036B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00036C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00036D* + ID_OUI_FROM_DATABASE=Runtop, Inc. + +OUI:00036E* + ID_OUI_FROM_DATABASE=Nicon Systems (Pty) Limited + +OUI:00036F* + ID_OUI_FROM_DATABASE=Telsey SPA + +OUI:000370* + ID_OUI_FROM_DATABASE=NXTV, Inc. + +OUI:000371* + ID_OUI_FROM_DATABASE=Acomz Networks Corp. + +OUI:000372* + ID_OUI_FROM_DATABASE=ULAN + +OUI:000373* + ID_OUI_FROM_DATABASE=Aselsan A.S + +OUI:000374* + ID_OUI_FROM_DATABASE=Control Microsystems + +OUI:000375* + ID_OUI_FROM_DATABASE=NetMedia, Inc. + +OUI:000376* + ID_OUI_FROM_DATABASE=Graphtec Technology, Inc. + +OUI:000377* + ID_OUI_FROM_DATABASE=Gigabit Wireless + +OUI:000378* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:000379* + ID_OUI_FROM_DATABASE=Proscend Communications, Inc. + +OUI:00037A* + ID_OUI_FROM_DATABASE=Taiyo Yuden Co., Ltd. + +OUI:00037B* + ID_OUI_FROM_DATABASE=IDEC IZUMI Corporation + +OUI:00037C* + ID_OUI_FROM_DATABASE=Coax Media + +OUI:00037D* + ID_OUI_FROM_DATABASE=Stellcom + +OUI:00037E* + ID_OUI_FROM_DATABASE=PORTech Communications, Inc. + +OUI:00037F* + ID_OUI_FROM_DATABASE=Atheros Communications, Inc. + +OUI:000380* + ID_OUI_FROM_DATABASE=SSH Communications Security Corp. + +OUI:000381* + ID_OUI_FROM_DATABASE=Ingenico International + +OUI:000382* + ID_OUI_FROM_DATABASE=A-One Co., Ltd. + +OUI:000383* + ID_OUI_FROM_DATABASE=Metera Networks, Inc. + +OUI:000384* + ID_OUI_FROM_DATABASE=AETA + +OUI:000385* + ID_OUI_FROM_DATABASE=Actelis Networks, Inc. + +OUI:000386* + ID_OUI_FROM_DATABASE=Ho Net, Inc. + +OUI:000387* + ID_OUI_FROM_DATABASE=Blaze Network Products + +OUI:000388* + ID_OUI_FROM_DATABASE=Fastfame Technology Co., Ltd. + +OUI:000389* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. + +OUI:00038A* + ID_OUI_FROM_DATABASE=America Online, Inc. + +OUI:00038B* + ID_OUI_FROM_DATABASE=PLUS-ONE I&T, Inc. + +OUI:00038C* + ID_OUI_FROM_DATABASE=Total Impact + +OUI:00038D* + ID_OUI_FROM_DATABASE=PCS Revenue Control Systems, Inc. + +OUI:00038E* + ID_OUI_FROM_DATABASE=Atoga Systems, Inc. + +OUI:00038F* + ID_OUI_FROM_DATABASE=Weinschel Corporation + +OUI:000390* + ID_OUI_FROM_DATABASE=Digital Video Communications, Inc. + +OUI:000391* + ID_OUI_FROM_DATABASE=Advanced Digital Broadcast, Ltd. + +OUI:000392* + ID_OUI_FROM_DATABASE=Hyundai Teletek Co., Ltd. + +OUI:000393* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:000394* + ID_OUI_FROM_DATABASE=Connect One + +OUI:000395* + ID_OUI_FROM_DATABASE=California Amplifier + +OUI:000396* + ID_OUI_FROM_DATABASE=EZ Cast Co., Ltd. + +OUI:000397* + ID_OUI_FROM_DATABASE=FireBrick Limited + +OUI:000398* + ID_OUI_FROM_DATABASE=WISI + +OUI:000399* + ID_OUI_FROM_DATABASE=Dongju Informations & Communications Co., Ltd. + +OUI:00039A* + ID_OUI_FROM_DATABASE=SiConnect + +OUI:00039B* + ID_OUI_FROM_DATABASE=NetChip Technology, Inc. + +OUI:00039C* + ID_OUI_FROM_DATABASE=OptiMight Communications, Inc. + +OUI:00039D* + ID_OUI_FROM_DATABASE=Qisda Corporation + +OUI:00039E* + ID_OUI_FROM_DATABASE=Tera System Co., Ltd. + +OUI:00039F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0003A0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0003A1* + ID_OUI_FROM_DATABASE=HIPER Information & Communication, Inc. + +OUI:0003A2* + ID_OUI_FROM_DATABASE=Catapult Communications + +OUI:0003A3* + ID_OUI_FROM_DATABASE=MAVIX, Ltd. + +OUI:0003A4* + ID_OUI_FROM_DATABASE=Imation Corp. + +OUI:0003A5* + ID_OUI_FROM_DATABASE=Medea Corporation + +OUI:0003A6* + ID_OUI_FROM_DATABASE=Traxit Technology, Inc. + +OUI:0003A7* + ID_OUI_FROM_DATABASE=Unixtar Technology, Inc. + +OUI:0003A8* + ID_OUI_FROM_DATABASE=IDOT Computers, Inc. + +OUI:0003A9* + ID_OUI_FROM_DATABASE=AXCENT Media AG + +OUI:0003AA* + ID_OUI_FROM_DATABASE=Watlow + +OUI:0003AB* + ID_OUI_FROM_DATABASE=Bridge Information Systems + +OUI:0003AC* + ID_OUI_FROM_DATABASE=Fronius Schweissmaschinen + +OUI:0003AD* + ID_OUI_FROM_DATABASE=Emerson Energy Systems AB + +OUI:0003AE* + ID_OUI_FROM_DATABASE=Allied Advanced Manufacturing Pte, Ltd. + +OUI:0003AF* + ID_OUI_FROM_DATABASE=Paragea Communications + +OUI:0003B0* + ID_OUI_FROM_DATABASE=Xsense Technology Corp. + +OUI:0003B1* + ID_OUI_FROM_DATABASE=Hospira Inc. + +OUI:0003B2* + ID_OUI_FROM_DATABASE=Radware + +OUI:0003B3* + ID_OUI_FROM_DATABASE=IA Link Systems Co., Ltd. + +OUI:0003B4* + ID_OUI_FROM_DATABASE=Macrotek International Corp. + +OUI:0003B5* + ID_OUI_FROM_DATABASE=Entra Technology Co. + +OUI:0003B6* + ID_OUI_FROM_DATABASE=QSI Corporation + +OUI:0003B7* + ID_OUI_FROM_DATABASE=ZACCESS Systems + +OUI:0003B8* + ID_OUI_FROM_DATABASE=NetKit Solutions, LLC + +OUI:0003B9* + ID_OUI_FROM_DATABASE=Hualong Telecom Co., Ltd. + +OUI:0003BA* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:0003BB* + ID_OUI_FROM_DATABASE=Signal Communications Limited + +OUI:0003BC* + ID_OUI_FROM_DATABASE=COT GmbH + +OUI:0003BD* + ID_OUI_FROM_DATABASE=OmniCluster Technologies, Inc. + +OUI:0003BE* + ID_OUI_FROM_DATABASE=Netility + +OUI:0003BF* + ID_OUI_FROM_DATABASE=Centerpoint Broadband Technologies, Inc. + +OUI:0003C0* + ID_OUI_FROM_DATABASE=RFTNC Co., Ltd. + +OUI:0003C1* + ID_OUI_FROM_DATABASE=Packet Dynamics Ltd + +OUI:0003C2* + ID_OUI_FROM_DATABASE=Solphone K.K. + +OUI:0003C3* + ID_OUI_FROM_DATABASE=Micronik Multimedia + +OUI:0003C4* + ID_OUI_FROM_DATABASE=Tomra Systems ASA + +OUI:0003C5* + ID_OUI_FROM_DATABASE=Mobotix AG + +OUI:0003C6* + ID_OUI_FROM_DATABASE=ICUE Systems, Inc. + +OUI:0003C7* + ID_OUI_FROM_DATABASE=hopf Elektronik GmbH + +OUI:0003C8* + ID_OUI_FROM_DATABASE=CML Emergency Services + +OUI:0003C9* + ID_OUI_FROM_DATABASE=TECOM Co., Ltd. + +OUI:0003CA* + ID_OUI_FROM_DATABASE=MTS Systems Corp. + +OUI:0003CB* + ID_OUI_FROM_DATABASE=SystemGear Co., Ltd. + +OUI:0003CC* + ID_OUI_FROM_DATABASE=Momentum Computer, Inc. + +OUI:0003CD* + ID_OUI_FROM_DATABASE=Clovertech, Inc. + +OUI:0003CE* + ID_OUI_FROM_DATABASE=ETEN Technologies, Inc. + +OUI:0003CF* + ID_OUI_FROM_DATABASE=Muxcom, Inc. + +OUI:0003D0* + ID_OUI_FROM_DATABASE=KOANKEISO Co., Ltd. + +OUI:0003D1* + ID_OUI_FROM_DATABASE=Takaya Corporation + +OUI:0003D2* + ID_OUI_FROM_DATABASE=Crossbeam Systems, Inc. + +OUI:0003D3* + ID_OUI_FROM_DATABASE=Internet Energy Systems, Inc. + +OUI:0003D4* + ID_OUI_FROM_DATABASE=Alloptic, Inc. + +OUI:0003D5* + ID_OUI_FROM_DATABASE=Advanced Communications Co., Ltd. + +OUI:0003D6* + ID_OUI_FROM_DATABASE=RADVision, Ltd. + +OUI:0003D7* + ID_OUI_FROM_DATABASE=NextNet Wireless, Inc. + +OUI:0003D8* + ID_OUI_FROM_DATABASE=iMPath Networks, Inc. + +OUI:0003D9* + ID_OUI_FROM_DATABASE=Secheron SA + +OUI:0003DA* + ID_OUI_FROM_DATABASE=Takamisawa Cybernetics Co., Ltd. + +OUI:0003DB* + ID_OUI_FROM_DATABASE=Apogee Electronics Corp. + +OUI:0003DC* + ID_OUI_FROM_DATABASE=Lexar Media, Inc. + +OUI:0003DD* + ID_OUI_FROM_DATABASE=Comark Interactive Solutions + +OUI:0003DE* + ID_OUI_FROM_DATABASE=OTC Wireless + +OUI:0003DF* + ID_OUI_FROM_DATABASE=Desana Systems + +OUI:0003E0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0003E1* + ID_OUI_FROM_DATABASE=Winmate Communication, Inc. + +OUI:0003E2* + ID_OUI_FROM_DATABASE=Comspace Corporation + +OUI:0003E3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0003E4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0003E5* + ID_OUI_FROM_DATABASE=Hermstedt SG + +OUI:0003E6* + ID_OUI_FROM_DATABASE=Entone, Inc. + +OUI:0003E7* + ID_OUI_FROM_DATABASE=Logostek Co. Ltd. + +OUI:0003E8* + ID_OUI_FROM_DATABASE=Wavelength Digital Limited + +OUI:0003E9* + ID_OUI_FROM_DATABASE=Akara Canada, Inc. + +OUI:0003EA* + ID_OUI_FROM_DATABASE=Mega System Technologies, Inc. + +OUI:0003EB* + ID_OUI_FROM_DATABASE=Atrica + +OUI:0003EC* + ID_OUI_FROM_DATABASE=ICG Research, Inc. + +OUI:0003ED* + ID_OUI_FROM_DATABASE=Shinkawa Electric Co., Ltd. + +OUI:0003EE* + ID_OUI_FROM_DATABASE=MKNet Corporation + +OUI:0003EF* + ID_OUI_FROM_DATABASE=Oneline AG + +OUI:0003F0* + ID_OUI_FROM_DATABASE=Redfern Broadband Networks + +OUI:0003F1* + ID_OUI_FROM_DATABASE=Cicada Semiconductor, Inc. + +OUI:0003F2* + ID_OUI_FROM_DATABASE=Seneca Networks + +OUI:0003F3* + ID_OUI_FROM_DATABASE=Dazzle Multimedia, Inc. + +OUI:0003F4* + ID_OUI_FROM_DATABASE=NetBurner + +OUI:0003F5* + ID_OUI_FROM_DATABASE=Chip2Chip + +OUI:0003F6* + ID_OUI_FROM_DATABASE=Allegro Networks, Inc. + +OUI:0003F7* + ID_OUI_FROM_DATABASE=Plast-Control GmbH + +OUI:0003F8* + ID_OUI_FROM_DATABASE=SanCastle Technologies, Inc. + +OUI:0003F9* + ID_OUI_FROM_DATABASE=Pleiades Communications, Inc. + +OUI:0003FA* + ID_OUI_FROM_DATABASE=TiMetra Networks + +OUI:0003FB* + ID_OUI_FROM_DATABASE=ENEGATE Co.,Ltd. + +OUI:0003FC* + ID_OUI_FROM_DATABASE=Intertex Data AB + +OUI:0003FD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0003FE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0003FF* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:000400* + ID_OUI_FROM_DATABASE=LEXMARK INTERNATIONAL, INC. + +OUI:000401* + ID_OUI_FROM_DATABASE=Osaki Electric Co., Ltd. + +OUI:000402* + ID_OUI_FROM_DATABASE=Nexsan Technologies, Ltd. + +OUI:000403* + ID_OUI_FROM_DATABASE=Nexsi Corporation + +OUI:000404* + ID_OUI_FROM_DATABASE=Makino Milling Machine Co., Ltd. + +OUI:000405* + ID_OUI_FROM_DATABASE=ACN Technologies + +OUI:000406* + ID_OUI_FROM_DATABASE=Fa. Metabox AG + +OUI:000407* + ID_OUI_FROM_DATABASE=Topcon Positioning Systems, Inc. + +OUI:000408* + ID_OUI_FROM_DATABASE=Sanko Electronics Co., Ltd. + +OUI:000409* + ID_OUI_FROM_DATABASE=Cratos Networks + +OUI:00040A* + ID_OUI_FROM_DATABASE=Sage Systems + +OUI:00040B* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:00040C* + ID_OUI_FROM_DATABASE=Kanno Works, Ltd. + +OUI:00040D* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:00040E* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:00040F* + ID_OUI_FROM_DATABASE=Asus Network Technologies, Inc. + +OUI:000410* + ID_OUI_FROM_DATABASE=Spinnaker Networks, Inc. + +OUI:000411* + ID_OUI_FROM_DATABASE=Inkra Networks, Inc. + +OUI:000412* + ID_OUI_FROM_DATABASE=WaveSmith Networks, Inc. + +OUI:000413* + ID_OUI_FROM_DATABASE=snom technology GmbH + +OUI:000414* + ID_OUI_FROM_DATABASE=Umezawa Musen Denki Co., Ltd. + +OUI:000415* + ID_OUI_FROM_DATABASE=Rasteme Systems Co., Ltd. + +OUI:000416* + ID_OUI_FROM_DATABASE=Parks S/A Comunicacoes Digitais + +OUI:000417* + ID_OUI_FROM_DATABASE=ELAU AG + +OUI:000418* + ID_OUI_FROM_DATABASE=Teltronic S.A.U. + +OUI:000419* + ID_OUI_FROM_DATABASE=Fibercycle Networks, Inc. + +OUI:00041A* + ID_OUI_FROM_DATABASE=Ines Test and Measurement GmbH & CoKG + +OUI:00041B* + ID_OUI_FROM_DATABASE=Bridgeworks Ltd. + +OUI:00041C* + ID_OUI_FROM_DATABASE=ipDialog, Inc. + +OUI:00041D* + ID_OUI_FROM_DATABASE=Corega of America + +OUI:00041E* + ID_OUI_FROM_DATABASE=Shikoku Instrumentation Co., Ltd. + +OUI:00041F* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:000420* + ID_OUI_FROM_DATABASE=Slim Devices, Inc. + +OUI:000421* + ID_OUI_FROM_DATABASE=Ocular Networks + +OUI:000422* + ID_OUI_FROM_DATABASE=Studio Technologies, Inc + +OUI:000423* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:000424* + ID_OUI_FROM_DATABASE=TMC s.r.l. + +OUI:000425* + ID_OUI_FROM_DATABASE=Atmel Corporation + +OUI:000426* + ID_OUI_FROM_DATABASE=Autosys + +OUI:000427* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000428* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000429* + ID_OUI_FROM_DATABASE=Pixord Corporation + +OUI:00042A* + ID_OUI_FROM_DATABASE=Wireless Networks, Inc. + +OUI:00042B* + ID_OUI_FROM_DATABASE=IT Access Co., Ltd. + +OUI:00042C* + ID_OUI_FROM_DATABASE=Minet, Inc. + +OUI:00042D* + ID_OUI_FROM_DATABASE=Sarian Systems, Ltd. + +OUI:00042E* + ID_OUI_FROM_DATABASE=Netous Technologies, Ltd. + +OUI:00042F* + ID_OUI_FROM_DATABASE=International Communications Products, Inc. + +OUI:000430* + ID_OUI_FROM_DATABASE=Netgem + +OUI:000431* + ID_OUI_FROM_DATABASE=GlobalStreams, Inc. + +OUI:000432* + ID_OUI_FROM_DATABASE=Voyetra Turtle Beach, Inc. + +OUI:000433* + ID_OUI_FROM_DATABASE=Cyberboard A/S + +OUI:000434* + ID_OUI_FROM_DATABASE=Accelent Systems, Inc. + +OUI:000435* + ID_OUI_FROM_DATABASE=InfiNet LLC + +OUI:000436* + ID_OUI_FROM_DATABASE=ELANsat Technologies, Inc. + +OUI:000437* + ID_OUI_FROM_DATABASE=Powin Information Technology, Inc. + +OUI:000438* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000439* + ID_OUI_FROM_DATABASE=Rosco Entertainment Technology, Inc. + +OUI:00043A* + ID_OUI_FROM_DATABASE=Intelligent Telecommunications, Inc. + +OUI:00043B* + ID_OUI_FROM_DATABASE=Lava Computer Mfg., Inc. + +OUI:00043C* + ID_OUI_FROM_DATABASE=SONOS Co., Ltd. + +OUI:00043D* + ID_OUI_FROM_DATABASE=INDEL AG + +OUI:00043E* + ID_OUI_FROM_DATABASE=Telencomm + +OUI:00043F* + ID_OUI_FROM_DATABASE=ESTeem Wireless Modems, Inc + +OUI:000440* + ID_OUI_FROM_DATABASE=cyberPIXIE, Inc. + +OUI:000441* + ID_OUI_FROM_DATABASE=Half Dome Systems, Inc. + +OUI:000442* + ID_OUI_FROM_DATABASE=NACT + +OUI:000443* + ID_OUI_FROM_DATABASE=Agilent Technologies, Inc. + +OUI:000444* + ID_OUI_FROM_DATABASE=Western Multiplex Corporation + +OUI:000445* + ID_OUI_FROM_DATABASE=LMS Skalar Instruments GmbH + +OUI:000446* + ID_OUI_FROM_DATABASE=CYZENTECH Co., Ltd. + +OUI:000447* + ID_OUI_FROM_DATABASE=Acrowave Systems Co., Ltd. + +OUI:000448* + ID_OUI_FROM_DATABASE=Polaroid Corporation + +OUI:000449* + ID_OUI_FROM_DATABASE=Mapletree Networks + +OUI:00044A* + ID_OUI_FROM_DATABASE=iPolicy Networks, Inc. + +OUI:00044B* + ID_OUI_FROM_DATABASE=NVIDIA + +OUI:00044C* + ID_OUI_FROM_DATABASE=JENOPTIK + +OUI:00044D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00044E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00044F* + ID_OUI_FROM_DATABASE=Schubert System Elektronik Gmbh + +OUI:000450* + ID_OUI_FROM_DATABASE=DMD Computers SRL + +OUI:000451* + ID_OUI_FROM_DATABASE=Medrad, Inc. + +OUI:000452* + ID_OUI_FROM_DATABASE=RocketLogix, Inc. + +OUI:000453* + ID_OUI_FROM_DATABASE=YottaYotta, Inc. + +OUI:000454* + ID_OUI_FROM_DATABASE=Quadriga UK + +OUI:000455* + ID_OUI_FROM_DATABASE=ANTARA.net + +OUI:000456* + ID_OUI_FROM_DATABASE=Cambium Networks Limited + +OUI:000457* + ID_OUI_FROM_DATABASE=Universal Access Technology, Inc. + +OUI:000458* + ID_OUI_FROM_DATABASE=Fusion X Co., Ltd. + +OUI:000459* + ID_OUI_FROM_DATABASE=Veristar Corporation + +OUI:00045A* + ID_OUI_FROM_DATABASE=The Linksys Group, Inc. + +OUI:00045B* + ID_OUI_FROM_DATABASE=Techsan Electronics Co., Ltd. + +OUI:00045C* + ID_OUI_FROM_DATABASE=Mobiwave Pte Ltd + +OUI:00045D* + ID_OUI_FROM_DATABASE=BEKA Elektronik + +OUI:00045E* + ID_OUI_FROM_DATABASE=PolyTrax Information Technology AG + +OUI:00045F* + ID_OUI_FROM_DATABASE=Avalue Technology, Inc. + +OUI:000460* + ID_OUI_FROM_DATABASE=Knilink Technology, Inc. + +OUI:000461* + ID_OUI_FROM_DATABASE=EPOX Computer Co., Ltd. + +OUI:000462* + ID_OUI_FROM_DATABASE=DAKOS Data & Communication Co., Ltd. + +OUI:000463* + ID_OUI_FROM_DATABASE=Bosch Security Systems + +OUI:000464* + ID_OUI_FROM_DATABASE=Pulse-Link Inc + +OUI:000465* + ID_OUI_FROM_DATABASE=i.s.t isdn-support technik GmbH + +OUI:000466* + ID_OUI_FROM_DATABASE=ARMITEL Co. + +OUI:000467* + ID_OUI_FROM_DATABASE=Wuhan Research Institute of MII + +OUI:000468* + ID_OUI_FROM_DATABASE=Vivity, Inc. + +OUI:000469* + ID_OUI_FROM_DATABASE=Innocom, Inc. + +OUI:00046A* + ID_OUI_FROM_DATABASE=Navini Networks + +OUI:00046B* + ID_OUI_FROM_DATABASE=Palm Wireless, Inc. + +OUI:00046C* + ID_OUI_FROM_DATABASE=Cyber Technology Co., Ltd. + +OUI:00046D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00046E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00046F* + ID_OUI_FROM_DATABASE=Digitel S/A Industria Eletronica + +OUI:000470* + ID_OUI_FROM_DATABASE=ipUnplugged AB + +OUI:000471* + ID_OUI_FROM_DATABASE=IPrad + +OUI:000472* + ID_OUI_FROM_DATABASE=Telelynx, Inc. + +OUI:000473* + ID_OUI_FROM_DATABASE=Photonex Corporation + +OUI:000474* + ID_OUI_FROM_DATABASE=LEGRAND + +OUI:000475* + ID_OUI_FROM_DATABASE=3COM + +OUI:000476* + ID_OUI_FROM_DATABASE=3COM + +OUI:000477* + ID_OUI_FROM_DATABASE=Scalant Systems, Inc. + +OUI:000478* + ID_OUI_FROM_DATABASE=G. Star Technology Corporation + +OUI:000479* + ID_OUI_FROM_DATABASE=Radius Co., Ltd. + +OUI:00047A* + ID_OUI_FROM_DATABASE=AXXESSIT ASA + +OUI:00047B* + ID_OUI_FROM_DATABASE=Schlumberger + +OUI:00047C* + ID_OUI_FROM_DATABASE=Skidata AG + +OUI:00047D* + ID_OUI_FROM_DATABASE=Pelco + +OUI:00047E* + ID_OUI_FROM_DATABASE=Siqura B.V. + +OUI:00047F* + ID_OUI_FROM_DATABASE=Chr. Mayr GmbH & Co. KG + +OUI:000480* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:000481* + ID_OUI_FROM_DATABASE=Econolite Control Products, Inc. + +OUI:000482* + ID_OUI_FROM_DATABASE=Medialogic Corp. + +OUI:000483* + ID_OUI_FROM_DATABASE=Deltron Technology, Inc. + +OUI:000484* + ID_OUI_FROM_DATABASE=Amann GmbH + +OUI:000485* + ID_OUI_FROM_DATABASE=PicoLight + +OUI:000486* + ID_OUI_FROM_DATABASE=ITTC, University of Kansas + +OUI:000487* + ID_OUI_FROM_DATABASE=Cogency Semiconductor, Inc. + +OUI:000488* + ID_OUI_FROM_DATABASE=Eurotherm Controls + +OUI:000489* + ID_OUI_FROM_DATABASE=YAFO Networks, Inc. + +OUI:00048A* + ID_OUI_FROM_DATABASE=Temia Vertriebs GmbH + +OUI:00048B* + ID_OUI_FROM_DATABASE=Poscon Corporation + +OUI:00048C* + ID_OUI_FROM_DATABASE=Nayna Networks, Inc. + +OUI:00048D* + ID_OUI_FROM_DATABASE=Teo Technologies, Inc + +OUI:00048E* + ID_OUI_FROM_DATABASE=Ohm Tech Labs, Inc. + +OUI:00048F* + ID_OUI_FROM_DATABASE=TD Systems Corporation + +OUI:000490* + ID_OUI_FROM_DATABASE=Optical Access + +OUI:000491* + ID_OUI_FROM_DATABASE=Technovision, Inc. + +OUI:000492* + ID_OUI_FROM_DATABASE=Hive Internet, Ltd. + +OUI:000493* + ID_OUI_FROM_DATABASE=Tsinghua Unisplendour Co., Ltd. + +OUI:000494* + ID_OUI_FROM_DATABASE=Breezecom, Ltd. + +OUI:000495* + ID_OUI_FROM_DATABASE=Tejas Networks India Limited + +OUI:000496* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:000497* + ID_OUI_FROM_DATABASE=MacroSystem Digital Video AG + +OUI:000498* + ID_OUI_FROM_DATABASE=Mahi Networks + +OUI:000499* + ID_OUI_FROM_DATABASE=Chino Corporation + +OUI:00049A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00049B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00049C* + ID_OUI_FROM_DATABASE=Surgient Networks, Inc. + +OUI:00049D* + ID_OUI_FROM_DATABASE=Ipanema Technologies + +OUI:00049E* + ID_OUI_FROM_DATABASE=Wirelink Co., Ltd. + +OUI:00049F* + ID_OUI_FROM_DATABASE=Freescale Semiconductor + +OUI:0004A0* + ID_OUI_FROM_DATABASE=Verity Instruments, Inc. + +OUI:0004A1* + ID_OUI_FROM_DATABASE=Pathway Connectivity + +OUI:0004A2* + ID_OUI_FROM_DATABASE=L.S.I. Japan Co., Ltd. + +OUI:0004A3* + ID_OUI_FROM_DATABASE=Microchip Technology Inc. + +OUI:0004A4* + ID_OUI_FROM_DATABASE=NetEnabled, Inc. + +OUI:0004A5* + ID_OUI_FROM_DATABASE=Barco Projection Systems NV + +OUI:0004A6* + ID_OUI_FROM_DATABASE=SAF Tehnika Ltd. + +OUI:0004A7* + ID_OUI_FROM_DATABASE=FabiaTech Corporation + +OUI:0004A8* + ID_OUI_FROM_DATABASE=Broadmax Technologies, Inc. + +OUI:0004A9* + ID_OUI_FROM_DATABASE=SandStream Technologies, Inc. + +OUI:0004AA* + ID_OUI_FROM_DATABASE=Jetstream Communications + +OUI:0004AB* + ID_OUI_FROM_DATABASE=Mavenir Inc. + +OUI:0004AC* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:0004AD* + ID_OUI_FROM_DATABASE=Malibu Networks + +OUI:0004AE* + ID_OUI_FROM_DATABASE=Sullair Corporation + +OUI:0004AF* + ID_OUI_FROM_DATABASE=Digital Fountain, Inc. + +OUI:0004B0* + ID_OUI_FROM_DATABASE=ELESIGN Co., Ltd. + +OUI:0004B1* + ID_OUI_FROM_DATABASE=Signal Technology, Inc. + +OUI:0004B2* + ID_OUI_FROM_DATABASE=ESSEGI SRL + +OUI:0004B3* + ID_OUI_FROM_DATABASE=Videotek, Inc. + +OUI:0004B4* + ID_OUI_FROM_DATABASE=CIAC + +OUI:0004B5* + ID_OUI_FROM_DATABASE=Equitrac Corporation + +OUI:0004B6* + ID_OUI_FROM_DATABASE=Stratex Networks, Inc. + +OUI:0004B7* + ID_OUI_FROM_DATABASE=AMB i.t. Holding + +OUI:0004B8* + ID_OUI_FROM_DATABASE=Kumahira Co., Ltd. + +OUI:0004B9* + ID_OUI_FROM_DATABASE=S.I. Soubou, Inc. + +OUI:0004BA* + ID_OUI_FROM_DATABASE=KDD Media Will Corporation + +OUI:0004BB* + ID_OUI_FROM_DATABASE=Bardac Corporation + +OUI:0004BC* + ID_OUI_FROM_DATABASE=Giantec, Inc. + +OUI:0004BD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0004BE* + ID_OUI_FROM_DATABASE=OptXCon, Inc. + +OUI:0004BF* + ID_OUI_FROM_DATABASE=VersaLogic Corp. + +OUI:0004C0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0004C1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0004C2* + ID_OUI_FROM_DATABASE=Magnipix, Inc. + +OUI:0004C3* + ID_OUI_FROM_DATABASE=CASTOR Informatique + +OUI:0004C4* + ID_OUI_FROM_DATABASE=Audiotonix Group Limited + +OUI:0004C5* + ID_OUI_FROM_DATABASE=ASE Technologies, USA + +OUI:0004C6* + ID_OUI_FROM_DATABASE=YAMAHA MOTOR CO.,LTD + +OUI:0004C7* + ID_OUI_FROM_DATABASE=NetMount + +OUI:0004C8* + ID_OUI_FROM_DATABASE=LIBA Maschinenfabrik GmbH + +OUI:0004C9* + ID_OUI_FROM_DATABASE=Micro Electron Co., Ltd. + +OUI:0004CA* + ID_OUI_FROM_DATABASE=FreeMs Corp. + +OUI:0004CB* + ID_OUI_FROM_DATABASE=Tdsoft Communication, Ltd. + +OUI:0004CC* + ID_OUI_FROM_DATABASE=Peek Traffic B.V. + +OUI:0004CD* + ID_OUI_FROM_DATABASE=Extenway Solutions Inc + +OUI:0004CE* + ID_OUI_FROM_DATABASE=Patria Ailon + +OUI:0004CF* + ID_OUI_FROM_DATABASE=Seagate Technology + +OUI:0004D0* + ID_OUI_FROM_DATABASE=Softlink s.r.o. + +OUI:0004D1* + ID_OUI_FROM_DATABASE=Drew Technologies, Inc. + +OUI:0004D2* + ID_OUI_FROM_DATABASE=Adcon Telemetry GmbH + +OUI:0004D3* + ID_OUI_FROM_DATABASE=Toyokeiki Co., Ltd. + +OUI:0004D4* + ID_OUI_FROM_DATABASE=Proview Electronics Co., Ltd. + +OUI:0004D5* + ID_OUI_FROM_DATABASE=Hitachi Information & Communication Engineering, Ltd. + +OUI:0004D6* + ID_OUI_FROM_DATABASE=Takagi Industrial Co., Ltd. + +OUI:0004D7* + ID_OUI_FROM_DATABASE=Omitec Instrumentation Ltd. + +OUI:0004D8* + ID_OUI_FROM_DATABASE=IPWireless, Inc. + +OUI:0004D9* + ID_OUI_FROM_DATABASE=Titan Electronics, Inc. + +OUI:0004DA* + ID_OUI_FROM_DATABASE=Relax Technology, Inc. + +OUI:0004DB* + ID_OUI_FROM_DATABASE=Tellus Group Corp. + +OUI:0004DC* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0004DD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0004DE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0004DF* + ID_OUI_FROM_DATABASE=TERACOM TELEMATICA S.A + +OUI:0004E0* + ID_OUI_FROM_DATABASE=Procket Networks + +OUI:0004E1* + ID_OUI_FROM_DATABASE=Infinior Microsystems + +OUI:0004E2* + ID_OUI_FROM_DATABASE=SMC Networks, Inc. + +OUI:0004E3* + ID_OUI_FROM_DATABASE=Accton Technology Corp + +OUI:0004E4* + ID_OUI_FROM_DATABASE=Daeryung Ind., Inc. + +OUI:0004E5* + ID_OUI_FROM_DATABASE=Glonet Systems, Inc. + +OUI:0004E6* + ID_OUI_FROM_DATABASE=Banyan Network Private Limited + +OUI:0004E7* + ID_OUI_FROM_DATABASE=Lightpointe Communications, Inc + +OUI:0004E8* + ID_OUI_FROM_DATABASE=IER, Inc. + +OUI:0004E9* + ID_OUI_FROM_DATABASE=Infiniswitch Corporation + +OUI:0004EA* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0004EB* + ID_OUI_FROM_DATABASE=Paxonet Communications, Inc. + +OUI:0004EC* + ID_OUI_FROM_DATABASE=Memobox SA + +OUI:0004ED* + ID_OUI_FROM_DATABASE=Billion Electric Co., Ltd. + +OUI:0004EE* + ID_OUI_FROM_DATABASE=Lincoln Electric Company + +OUI:0004EF* + ID_OUI_FROM_DATABASE=Polestar Corp. + +OUI:0004F0* + ID_OUI_FROM_DATABASE=International Computers, Ltd + +OUI:0004F1* + ID_OUI_FROM_DATABASE=WhereNet + +OUI:0004F2* + ID_OUI_FROM_DATABASE=Polycom + +OUI:0004F3* + ID_OUI_FROM_DATABASE=FS FORTH-SYSTEME GmbH + +OUI:0004F4* + ID_OUI_FROM_DATABASE=Infinite Electronics Inc. + +OUI:0004F5* + ID_OUI_FROM_DATABASE=SnowShore Networks, Inc. + +OUI:0004F6* + ID_OUI_FROM_DATABASE=Amphus + +OUI:0004F7* + ID_OUI_FROM_DATABASE=Omega Band, Inc. + +OUI:0004F8* + ID_OUI_FROM_DATABASE=QUALICABLE TV Industria E Com., Ltda + +OUI:0004F9* + ID_OUI_FROM_DATABASE=Xtera Communications, Inc. + +OUI:0004FA* + ID_OUI_FROM_DATABASE=NBS Technologies Inc. + +OUI:0004FB* + ID_OUI_FROM_DATABASE=Commtech, Inc. + +OUI:0004FC* + ID_OUI_FROM_DATABASE=Stratus Technologies + +OUI:0004FD* + ID_OUI_FROM_DATABASE=Japan Control Engineering Co., Ltd. + +OUI:0004FE* + ID_OUI_FROM_DATABASE=Pelago Networks + +OUI:0004FF* + ID_OUI_FROM_DATABASE=Acronet Co., Ltd. + +OUI:000500* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000501* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000502* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:000503* + ID_OUI_FROM_DATABASE=ICONAG + +OUI:000504* + ID_OUI_FROM_DATABASE=Naray Information & Communication Enterprise + +OUI:000505* + ID_OUI_FROM_DATABASE=Systems Integration Solutions, Inc. + +OUI:000506* + ID_OUI_FROM_DATABASE=Reddo Networks AB + +OUI:000507* + ID_OUI_FROM_DATABASE=Fine Appliance Corp. + +OUI:000508* + ID_OUI_FROM_DATABASE=Inetcam, Inc. + +OUI:000509* + ID_OUI_FROM_DATABASE=AVOC Nishimura Ltd. + +OUI:00050A* + ID_OUI_FROM_DATABASE=ICS Spa + +OUI:00050B* + ID_OUI_FROM_DATABASE=SICOM Systems, Inc. + +OUI:00050C* + ID_OUI_FROM_DATABASE=Network Photonics, Inc. + +OUI:00050D* + ID_OUI_FROM_DATABASE=Midstream Technologies, Inc. + +OUI:00050E* + ID_OUI_FROM_DATABASE=3ware, Inc. + +OUI:00050F* + ID_OUI_FROM_DATABASE=Tanaka S/S Ltd. + +OUI:000510* + ID_OUI_FROM_DATABASE=Infinite Shanghai Communication Terminals Ltd. + +OUI:000511* + ID_OUI_FROM_DATABASE=Complementary Technologies Ltd + +OUI:000512* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc + +OUI:000513* + ID_OUI_FROM_DATABASE=VTLinx Multimedia Systems, Inc. + +OUI:000514* + ID_OUI_FROM_DATABASE=KDT Systems Co., Ltd. + +OUI:000515* + ID_OUI_FROM_DATABASE=Nuark Co., Ltd. + +OUI:000516* + ID_OUI_FROM_DATABASE=SMART Modular Technologies + +OUI:000517* + ID_OUI_FROM_DATABASE=Shellcomm, Inc. + +OUI:000518* + ID_OUI_FROM_DATABASE=Jupiters Technology + +OUI:000519* + ID_OUI_FROM_DATABASE=Siemens Building Technologies AG, + +OUI:00051A* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:00051B* + ID_OUI_FROM_DATABASE=Magic Control Technology Corporation + +OUI:00051C* + ID_OUI_FROM_DATABASE=Xnet Technology Corp. + +OUI:00051D* + ID_OUI_FROM_DATABASE=Airocon, Inc. + +OUI:00051E* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:00051F* + ID_OUI_FROM_DATABASE=Taijin Media Co., Ltd. + +OUI:000520* + ID_OUI_FROM_DATABASE=Smartronix, Inc. + +OUI:000521* + ID_OUI_FROM_DATABASE=Control Microsystems + +OUI:000522* + ID_OUI_FROM_DATABASE=LEA*D Corporation, Inc. + +OUI:000523* + ID_OUI_FROM_DATABASE=AVL List GmbH + +OUI:000524* + ID_OUI_FROM_DATABASE=BTL System (HK) Limited + +OUI:000525* + ID_OUI_FROM_DATABASE=Puretek Industrial Co., Ltd. + +OUI:000526* + ID_OUI_FROM_DATABASE=IPAS GmbH + +OUI:000527* + ID_OUI_FROM_DATABASE=SJ Tek Co. Ltd + +OUI:000528* + ID_OUI_FROM_DATABASE=New Focus, Inc. + +OUI:000529* + ID_OUI_FROM_DATABASE=Shanghai Broadan Communication Technology Co., Ltd + +OUI:00052A* + ID_OUI_FROM_DATABASE=Ikegami Tsushinki Co., Ltd. + +OUI:00052B* + ID_OUI_FROM_DATABASE=HORIBA, Ltd. + +OUI:00052C* + ID_OUI_FROM_DATABASE=Supreme Magic Corporation + +OUI:00052D* + ID_OUI_FROM_DATABASE=Zoltrix International Limited + +OUI:00052E* + ID_OUI_FROM_DATABASE=Cinta Networks + +OUI:00052F* + ID_OUI_FROM_DATABASE=Leviton Network Solutions + +OUI:000530* + ID_OUI_FROM_DATABASE=Andiamo Systems, Inc. + +OUI:000531* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000532* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000533* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:000534* + ID_OUI_FROM_DATABASE=Northstar Engineering Ltd. + +OUI:000535* + ID_OUI_FROM_DATABASE=Chip PC Ltd. + +OUI:000536* + ID_OUI_FROM_DATABASE=Danam Communications, Inc. + +OUI:000537* + ID_OUI_FROM_DATABASE=Nets Technology Co., Ltd. + +OUI:000538* + ID_OUI_FROM_DATABASE=Merilus, Inc. + +OUI:000539* + ID_OUI_FROM_DATABASE=A Brand New World in Sweden AB + +OUI:00053A* + ID_OUI_FROM_DATABASE=Willowglen Services Pte Ltd + +OUI:00053B* + ID_OUI_FROM_DATABASE=Harbour Networks Ltd., Co. Beijing + +OUI:00053C* + ID_OUI_FROM_DATABASE=XIRCOM + +OUI:00053D* + ID_OUI_FROM_DATABASE=Agere Systems + +OUI:00053E* + ID_OUI_FROM_DATABASE=KID Systeme GmbH + +OUI:00053F* + ID_OUI_FROM_DATABASE=VisionTek, Inc. + +OUI:000540* + ID_OUI_FROM_DATABASE=FAST Corporation + +OUI:000541* + ID_OUI_FROM_DATABASE=Advanced Systems Co., Ltd. + +OUI:000542* + ID_OUI_FROM_DATABASE=Otari, Inc. + +OUI:000543* + ID_OUI_FROM_DATABASE=IQ Wireless GmbH + +OUI:000544* + ID_OUI_FROM_DATABASE=Valley Technologies, Inc. + +OUI:000545* + ID_OUI_FROM_DATABASE=Internet Photonics + +OUI:000546* + ID_OUI_FROM_DATABASE=KDDI Network & Solultions Inc. + +OUI:000547* + ID_OUI_FROM_DATABASE=Starent Networks + +OUI:000548* + ID_OUI_FROM_DATABASE=Disco Corporation + +OUI:000549* + ID_OUI_FROM_DATABASE=Salira Optical Network Systems + +OUI:00054A* + ID_OUI_FROM_DATABASE=Ario Data Networks, Inc. + +OUI:00054B* + ID_OUI_FROM_DATABASE=Eaton Automation AG + +OUI:00054C* + ID_OUI_FROM_DATABASE=RF Innovations Pty Ltd + +OUI:00054D* + ID_OUI_FROM_DATABASE=Brans Technologies, Inc. + +OUI:00054E* + ID_OUI_FROM_DATABASE=Philips + +OUI:00054F* + ID_OUI_FROM_DATABASE=Garmin International + +OUI:000550* + ID_OUI_FROM_DATABASE=Vcomms Connect Limited + +OUI:000551* + ID_OUI_FROM_DATABASE=F & S Elektronik Systeme GmbH + +OUI:000552* + ID_OUI_FROM_DATABASE=Xycotec Computer GmbH + +OUI:000553* + ID_OUI_FROM_DATABASE=DVC Company, Inc. + +OUI:000554* + ID_OUI_FROM_DATABASE=Rangestar Wireless + +OUI:000555* + ID_OUI_FROM_DATABASE=Japan Cash Machine Co., Ltd. + +OUI:000556* + ID_OUI_FROM_DATABASE=360 Systems + +OUI:000557* + ID_OUI_FROM_DATABASE=Agile TV Corporation + +OUI:000558* + ID_OUI_FROM_DATABASE=Synchronous, Inc. + +OUI:000559* + ID_OUI_FROM_DATABASE=Intracom S.A. + +OUI:00055A* + ID_OUI_FROM_DATABASE=Power Dsine Ltd. + +OUI:00055B* + ID_OUI_FROM_DATABASE=Charles Industries, Ltd. + +OUI:00055C* + ID_OUI_FROM_DATABASE=Kowa Company, Ltd. + +OUI:00055D* + ID_OUI_FROM_DATABASE=D-LINK SYSTEMS, INC. + +OUI:00055E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00055F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000560* + ID_OUI_FROM_DATABASE=LEADER COMM.CO., LTD + +OUI:000561* + ID_OUI_FROM_DATABASE=nac Image Technology, Inc. + +OUI:000562* + ID_OUI_FROM_DATABASE=Digital View Limited + +OUI:000563* + ID_OUI_FROM_DATABASE=J-Works, Inc. + +OUI:000564* + ID_OUI_FROM_DATABASE=Tsinghua Bitway Co., Ltd. + +OUI:000565* + ID_OUI_FROM_DATABASE=Tailyn Communication Company Ltd. + +OUI:000566* + ID_OUI_FROM_DATABASE=Secui.com Corporation + +OUI:000567* + ID_OUI_FROM_DATABASE=Etymonic Design, Inc. + +OUI:000568* + ID_OUI_FROM_DATABASE=Piltofish Networks AB + +OUI:000569* + ID_OUI_FROM_DATABASE=VMware, Inc. + +OUI:00056A* + ID_OUI_FROM_DATABASE=Heuft Systemtechnik GmbH + +OUI:00056B* + ID_OUI_FROM_DATABASE=C.P. Technology Co., Ltd. + +OUI:00056C* + ID_OUI_FROM_DATABASE=Hung Chang Co., Ltd. + +OUI:00056D* + ID_OUI_FROM_DATABASE=Pacific Corporation + +OUI:00056E* + ID_OUI_FROM_DATABASE=National Enhance Technology, Inc. + +OUI:00056F* + ID_OUI_FROM_DATABASE=Innomedia Technologies Pvt. Ltd. + +OUI:000570* + ID_OUI_FROM_DATABASE=Baydel Ltd. + +OUI:000571* + ID_OUI_FROM_DATABASE=Seiwa Electronics Co. + +OUI:000572* + ID_OUI_FROM_DATABASE=Deonet Co., Ltd. + +OUI:000573* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000574* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000575* + ID_OUI_FROM_DATABASE=CDS-Electronics BV + +OUI:000576* + ID_OUI_FROM_DATABASE=NSM Technology Ltd. + +OUI:000577* + ID_OUI_FROM_DATABASE=SM Information & Communication + +OUI:000578* + ID_OUI_FROM_DATABASE=Private + +OUI:000579* + ID_OUI_FROM_DATABASE=Universal Control Solution Corp. + +OUI:00057A* + ID_OUI_FROM_DATABASE=Overture Networks + +OUI:00057B* + ID_OUI_FROM_DATABASE=Chung Nam Electronic Co., Ltd. + +OUI:00057C* + ID_OUI_FROM_DATABASE=RCO Security AB + +OUI:00057D* + ID_OUI_FROM_DATABASE=Sun Communications, Inc. + +OUI:00057E* + ID_OUI_FROM_DATABASE=Eckelmann Steuerungstechnik GmbH + +OUI:00057F* + ID_OUI_FROM_DATABASE=Acqis Technology + +OUI:000580* + ID_OUI_FROM_DATABASE=FibroLAN Ltd. + +OUI:000581* + ID_OUI_FROM_DATABASE=Snell + +OUI:000582* + ID_OUI_FROM_DATABASE=ClearCube Technology + +OUI:000583* + ID_OUI_FROM_DATABASE=ImageCom Limited + +OUI:000584* + ID_OUI_FROM_DATABASE=AbsoluteValue Systems, Inc. + +OUI:000585* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:000586* + ID_OUI_FROM_DATABASE=Lucent Technologies + +OUI:000587* + ID_OUI_FROM_DATABASE=Locus, Incorporated + +OUI:000588* + ID_OUI_FROM_DATABASE=Sensoria Corp. + +OUI:000589* + ID_OUI_FROM_DATABASE=National Datacomputer + +OUI:00058A* + ID_OUI_FROM_DATABASE=Netcom Co., Ltd. + +OUI:00058B* + ID_OUI_FROM_DATABASE=IPmental, Inc. + +OUI:00058C* + ID_OUI_FROM_DATABASE=Opentech Inc. + +OUI:00058D* + ID_OUI_FROM_DATABASE=Lynx Photonic Networks, Inc. + +OUI:00058E* + ID_OUI_FROM_DATABASE=Flextronics International GmbH & Co. Nfg. KG + +OUI:00058F* + ID_OUI_FROM_DATABASE=CLCsoft co. + +OUI:000590* + ID_OUI_FROM_DATABASE=Swissvoice Ltd. + +OUI:000591* + ID_OUI_FROM_DATABASE=Active Silicon Ltd + +OUI:000592* + ID_OUI_FROM_DATABASE=Pultek Corp. + +OUI:000593* + ID_OUI_FROM_DATABASE=Grammar Engine Inc. + +OUI:000594* + ID_OUI_FROM_DATABASE=HMS Industrial Networks + +OUI:000595* + ID_OUI_FROM_DATABASE=Alesis Corporation + +OUI:000596* + ID_OUI_FROM_DATABASE=Genotech Co., Ltd. + +OUI:000597* + ID_OUI_FROM_DATABASE=Eagle Traffic Control Systems + +OUI:000598* + ID_OUI_FROM_DATABASE=CRONOS S.r.l. + +OUI:000599* + ID_OUI_FROM_DATABASE=DRS Test and Energy Management or DRS-TEM + +OUI:00059A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00059B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00059C* + ID_OUI_FROM_DATABASE=Kleinknecht GmbH, Ing. Büro + +OUI:00059D* + ID_OUI_FROM_DATABASE=Daniel Computing Systems, Inc. + +OUI:00059E* + ID_OUI_FROM_DATABASE=Zinwell Corporation + +OUI:00059F* + ID_OUI_FROM_DATABASE=Yotta Networks, Inc. + +OUI:0005A0* + ID_OUI_FROM_DATABASE=MOBILINE Kft. + +OUI:0005A1* + ID_OUI_FROM_DATABASE=Zenocom + +OUI:0005A2* + ID_OUI_FROM_DATABASE=CELOX Networks + +OUI:0005A3* + ID_OUI_FROM_DATABASE=QEI, Inc. + +OUI:0005A4* + ID_OUI_FROM_DATABASE=Lucid Voice Ltd. + +OUI:0005A5* + ID_OUI_FROM_DATABASE=KOTT + +OUI:0005A6* + ID_OUI_FROM_DATABASE=Extron Electronics + +OUI:0005A7* + ID_OUI_FROM_DATABASE=HYPERCHIP Inc. + +OUI:0005A8* + ID_OUI_FROM_DATABASE=WYLE ELECTRONICS + +OUI:0005A9* + ID_OUI_FROM_DATABASE=Princeton Networks, Inc. + +OUI:0005AA* + ID_OUI_FROM_DATABASE=Moore Industries International Inc. + +OUI:0005AB* + ID_OUI_FROM_DATABASE=Cyber Fone, Inc. + +OUI:0005AC* + ID_OUI_FROM_DATABASE=Northern Digital, Inc. + +OUI:0005AD* + ID_OUI_FROM_DATABASE=Topspin Communications, Inc. + +OUI:0005AE* + ID_OUI_FROM_DATABASE=Mediaport USA + +OUI:0005AF* + ID_OUI_FROM_DATABASE=InnoScan Computing A/S + +OUI:0005B0* + ID_OUI_FROM_DATABASE=Korea Computer Technology Co., Ltd. + +OUI:0005B1* + ID_OUI_FROM_DATABASE=ASB Technology BV + +OUI:0005B2* + ID_OUI_FROM_DATABASE=Medison Co., Ltd. + +OUI:0005B3* + ID_OUI_FROM_DATABASE=Asahi-Engineering Co., Ltd. + +OUI:0005B4* + ID_OUI_FROM_DATABASE=Aceex Corporation + +OUI:0005B5* + ID_OUI_FROM_DATABASE=Broadcom Technologies + +OUI:0005B6* + ID_OUI_FROM_DATABASE=INSYS Microelectronics GmbH + +OUI:0005B7* + ID_OUI_FROM_DATABASE=Arbor Technology Corp. + +OUI:0005B8* + ID_OUI_FROM_DATABASE=Electronic Design Associates, Inc. + +OUI:0005B9* + ID_OUI_FROM_DATABASE=Airvana, Inc. + +OUI:0005BA* + ID_OUI_FROM_DATABASE=Area Netwoeks, Inc. + +OUI:0005BB* + ID_OUI_FROM_DATABASE=Myspace AB + +OUI:0005BC* + ID_OUI_FROM_DATABASE=Resource Data Management Ltd + +OUI:0005BD* + ID_OUI_FROM_DATABASE=ROAX BV + +OUI:0005BE* + ID_OUI_FROM_DATABASE=Kongsberg Seatex AS + +OUI:0005BF* + ID_OUI_FROM_DATABASE=JustEzy Technology, Inc. + +OUI:0005C0* + ID_OUI_FROM_DATABASE=Digital Network Alacarte Co., Ltd. + +OUI:0005C1* + ID_OUI_FROM_DATABASE=A-Kyung Motion, Inc. + +OUI:0005C2* + ID_OUI_FROM_DATABASE=Soronti, Inc. + +OUI:0005C3* + ID_OUI_FROM_DATABASE=Pacific Instruments, Inc. + +OUI:0005C4* + ID_OUI_FROM_DATABASE=Telect, Inc. + +OUI:0005C5* + ID_OUI_FROM_DATABASE=Flaga HF + +OUI:0005C6* + ID_OUI_FROM_DATABASE=Triz Communications + +OUI:0005C7* + ID_OUI_FROM_DATABASE=I/F-COM A/S + +OUI:0005C8* + ID_OUI_FROM_DATABASE=VERYTECH + +OUI:0005C9* + ID_OUI_FROM_DATABASE=LG Innotek Co., Ltd. + +OUI:0005CA* + ID_OUI_FROM_DATABASE=Hitron Technology, Inc. + +OUI:0005CB* + ID_OUI_FROM_DATABASE=ROIS Technologies, Inc. + +OUI:0005CC* + ID_OUI_FROM_DATABASE=Sumtel Communications, Inc. + +OUI:0005CD* + ID_OUI_FROM_DATABASE=D&M Holdings Inc. + +OUI:0005CE* + ID_OUI_FROM_DATABASE=Prolink Microsystems Corporation + +OUI:0005CF* + ID_OUI_FROM_DATABASE=Thunder River Technologies, Inc. + +OUI:0005D0* + ID_OUI_FROM_DATABASE=Solinet Systems + +OUI:0005D1* + ID_OUI_FROM_DATABASE=Metavector Technologies + +OUI:0005D2* + ID_OUI_FROM_DATABASE=DAP Technologies + +OUI:0005D3* + ID_OUI_FROM_DATABASE=eProduction Solutions, Inc. + +OUI:0005D4* + ID_OUI_FROM_DATABASE=FutureSmart Networks, Inc. + +OUI:0005D5* + ID_OUI_FROM_DATABASE=Speedcom Wireless + +OUI:0005D6* + ID_OUI_FROM_DATABASE=L-3 Linkabit + +OUI:0005D7* + ID_OUI_FROM_DATABASE=Vista Imaging, Inc. + +OUI:0005D8* + ID_OUI_FROM_DATABASE=Arescom, Inc. + +OUI:0005D9* + ID_OUI_FROM_DATABASE=Techno Valley, Inc. + +OUI:0005DA* + ID_OUI_FROM_DATABASE=Apex Automationstechnik + +OUI:0005DB* + ID_OUI_FROM_DATABASE=PSI Nentec GmbH + +OUI:0005DC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0005DD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0005DE* + ID_OUI_FROM_DATABASE=Gi Fone Korea, Inc. + +OUI:0005DF* + ID_OUI_FROM_DATABASE=Electronic Innovation, Inc. + +OUI:0005E0* + ID_OUI_FROM_DATABASE=Empirix Corp. + +OUI:0005E1* + ID_OUI_FROM_DATABASE=Trellis Photonics, Ltd. + +OUI:0005E2* + ID_OUI_FROM_DATABASE=Creativ Network Technologies + +OUI:0005E3* + ID_OUI_FROM_DATABASE=LightSand Communications, Inc. + +OUI:0005E4* + ID_OUI_FROM_DATABASE=Red Lion Controls Inc. + +OUI:0005E5* + ID_OUI_FROM_DATABASE=Renishaw PLC + +OUI:0005E6* + ID_OUI_FROM_DATABASE=Egenera, Inc. + +OUI:0005E7* + ID_OUI_FROM_DATABASE=Netrake an AudioCodes Company + +OUI:0005E8* + ID_OUI_FROM_DATABASE=TurboWave, Inc. + +OUI:0005E9* + ID_OUI_FROM_DATABASE=Unicess Network, Inc. + +OUI:0005EA* + ID_OUI_FROM_DATABASE=Rednix + +OUI:0005EB* + ID_OUI_FROM_DATABASE=Blue Ridge Networks, Inc. + +OUI:0005EC* + ID_OUI_FROM_DATABASE=Mosaic Systems Inc. + +OUI:0005ED* + ID_OUI_FROM_DATABASE=Technikum Joanneum GmbH + +OUI:0005EE* + ID_OUI_FROM_DATABASE=Vanderbilt International (SWE) AB + +OUI:0005EF* + ID_OUI_FROM_DATABASE=ADOIR Digital Technology + +OUI:0005F0* + ID_OUI_FROM_DATABASE=SATEC + +OUI:0005F1* + ID_OUI_FROM_DATABASE=Vrcom, Inc. + +OUI:0005F2* + ID_OUI_FROM_DATABASE=Power R, Inc. + +OUI:0005F3* + ID_OUI_FROM_DATABASE=Webyn + +OUI:0005F4* + ID_OUI_FROM_DATABASE=System Base Co., Ltd. + +OUI:0005F5* + ID_OUI_FROM_DATABASE=Geospace Technologies + +OUI:0005F6* + ID_OUI_FROM_DATABASE=Young Chang Co. Ltd. + +OUI:0005F7* + ID_OUI_FROM_DATABASE=Analog Devices, Inc. + +OUI:0005F8* + ID_OUI_FROM_DATABASE=Real Time Access, Inc. + +OUI:0005F9* + ID_OUI_FROM_DATABASE=TOA Corporation + +OUI:0005FA* + ID_OUI_FROM_DATABASE=IPOptical, Inc. + +OUI:0005FB* + ID_OUI_FROM_DATABASE=ShareGate, Inc. + +OUI:0005FC* + ID_OUI_FROM_DATABASE=Schenck Pegasus Corp. + +OUI:0005FD* + ID_OUI_FROM_DATABASE=PacketLight Networks Ltd. + +OUI:0005FE* + ID_OUI_FROM_DATABASE=Traficon N.V. + +OUI:0005FF* + ID_OUI_FROM_DATABASE=SNS Solutions, Inc. + +OUI:000600* + ID_OUI_FROM_DATABASE=Toshiba Teli Corporation + +OUI:000601* + ID_OUI_FROM_DATABASE=Otanikeiki Co., Ltd. + +OUI:000602* + ID_OUI_FROM_DATABASE=Cirkitech Electronics Co. + +OUI:000603* + ID_OUI_FROM_DATABASE=Baker Hughes Inc. + +OUI:000604* + ID_OUI_FROM_DATABASE=@Track Communications, Inc. + +OUI:000605* + ID_OUI_FROM_DATABASE=Inncom International, Inc. + +OUI:000606* + ID_OUI_FROM_DATABASE=RapidWAN, Inc. + +OUI:000607* + ID_OUI_FROM_DATABASE=Omni Directional Control Technology Inc. + +OUI:000608* + ID_OUI_FROM_DATABASE=At-Sky SAS + +OUI:000609* + ID_OUI_FROM_DATABASE=Crossport Systems + +OUI:00060A* + ID_OUI_FROM_DATABASE=Blue2space + +OUI:00060B* + ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies + +OUI:00060C* + ID_OUI_FROM_DATABASE=Melco Industries, Inc. + +OUI:00060D* + ID_OUI_FROM_DATABASE=Wave7 Optics + +OUI:00060E* + ID_OUI_FROM_DATABASE=IGYS Systems, Inc. + +OUI:00060F* + ID_OUI_FROM_DATABASE=Narad Networks Inc + +OUI:000610* + ID_OUI_FROM_DATABASE=Abeona Networks Inc + +OUI:000611* + ID_OUI_FROM_DATABASE=Zeus Wireless, Inc. + +OUI:000612* + ID_OUI_FROM_DATABASE=Accusys, Inc. + +OUI:000613* + ID_OUI_FROM_DATABASE=Kawasaki Microelectronics Incorporated + +OUI:000614* + ID_OUI_FROM_DATABASE=Prism Holdings + +OUI:000615* + ID_OUI_FROM_DATABASE=Kimoto Electric Co., Ltd. + +OUI:000616* + ID_OUI_FROM_DATABASE=Tel Net Co., Ltd. + +OUI:000617* + ID_OUI_FROM_DATABASE=Redswitch Inc. + +OUI:000618* + ID_OUI_FROM_DATABASE=DigiPower Manufacturing Inc. + +OUI:000619* + ID_OUI_FROM_DATABASE=Connection Technology Systems + +OUI:00061A* + ID_OUI_FROM_DATABASE=Zetari Inc. + +OUI:00061B* + ID_OUI_FROM_DATABASE=Notebook Development Lab. Lenovo Japan Ltd. + +OUI:00061C* + ID_OUI_FROM_DATABASE=Hoshino Metal Industries, Ltd. + +OUI:00061D* + ID_OUI_FROM_DATABASE=MIP Telecom, Inc. + +OUI:00061E* + ID_OUI_FROM_DATABASE=Maxan Systems + +OUI:00061F* + ID_OUI_FROM_DATABASE=Vision Components GmbH + +OUI:000620* + ID_OUI_FROM_DATABASE=Serial System Ltd. + +OUI:000621* + ID_OUI_FROM_DATABASE=Hinox, Co., Ltd. + +OUI:000622* + ID_OUI_FROM_DATABASE=Chung Fu Chen Yeh Enterprise Corp. + +OUI:000623* + ID_OUI_FROM_DATABASE=MGE UPS Systems France + +OUI:000624* + ID_OUI_FROM_DATABASE=Gentner Communications Corp. + +OUI:000625* + ID_OUI_FROM_DATABASE=The Linksys Group, Inc. + +OUI:000626* + ID_OUI_FROM_DATABASE=MWE GmbH + +OUI:000627* + ID_OUI_FROM_DATABASE=Uniwide Technologies, Inc. + +OUI:000628* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000629* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:00062A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00062B* + ID_OUI_FROM_DATABASE=INTRASERVER TECHNOLOGY + +OUI:00062C* + ID_OUI_FROM_DATABASE=Bivio Networks + +OUI:00062D* + ID_OUI_FROM_DATABASE=TouchStar Technologies, L.L.C. + +OUI:00062E* + ID_OUI_FROM_DATABASE=Aristos Logic Corp. + +OUI:00062F* + ID_OUI_FROM_DATABASE=Pivotech Systems Inc. + +OUI:000630* + ID_OUI_FROM_DATABASE=Adtranz Sweden + +OUI:000631* + ID_OUI_FROM_DATABASE=Calix Inc. + +OUI:000632* + ID_OUI_FROM_DATABASE=Mesco Engineering GmbH + +OUI:000633* + ID_OUI_FROM_DATABASE=Cross Match Technologies GmbH + +OUI:000634* + ID_OUI_FROM_DATABASE=GTE Airfone Inc. + +OUI:000635* + ID_OUI_FROM_DATABASE=PacketAir Networks, Inc. + +OUI:000636* + ID_OUI_FROM_DATABASE=Jedai Broadband Networks + +OUI:000637* + ID_OUI_FROM_DATABASE=Toptrend-Meta Information (ShenZhen) Inc. + +OUI:000638* + ID_OUI_FROM_DATABASE=Sungjin C&C Co., Ltd. + +OUI:000639* + ID_OUI_FROM_DATABASE=Newtec + +OUI:00063A* + ID_OUI_FROM_DATABASE=Dura Micro, Inc. + +OUI:00063B* + ID_OUI_FROM_DATABASE=Arcturus Networks Inc. + +OUI:00063C* + ID_OUI_FROM_DATABASE=Intrinsyc Software International Inc. + +OUI:00063D* + ID_OUI_FROM_DATABASE=Microwave Data Systems Inc. + +OUI:00063E* + ID_OUI_FROM_DATABASE=Opthos Inc. + +OUI:00063F* + ID_OUI_FROM_DATABASE=Everex Communications Inc. + +OUI:000640* + ID_OUI_FROM_DATABASE=White Rock Networks + +OUI:000641* + ID_OUI_FROM_DATABASE=ITCN + +OUI:000642* + ID_OUI_FROM_DATABASE=Genetel Systems Inc. + +OUI:000643* + ID_OUI_FROM_DATABASE=SONO Computer Co., Ltd. + +OUI:000644* + ID_OUI_FROM_DATABASE=NextGen Business Solutions, Inc + +OUI:000645* + ID_OUI_FROM_DATABASE=Meisei Electric Co. Ltd. + +OUI:000646* + ID_OUI_FROM_DATABASE=ShenZhen XunBao Network Technology Co Ltd + +OUI:000647* + ID_OUI_FROM_DATABASE=Etrali S.A. + +OUI:000648* + ID_OUI_FROM_DATABASE=Seedsware, Inc. + +OUI:000649* + ID_OUI_FROM_DATABASE=3M Deutschland GmbH + +OUI:00064A* + ID_OUI_FROM_DATABASE=Honeywell Co., Ltd. (KOREA) + +OUI:00064B* + ID_OUI_FROM_DATABASE=Alexon Co., Ltd. + +OUI:00064C* + ID_OUI_FROM_DATABASE=Invicta Networks, Inc. + +OUI:00064D* + ID_OUI_FROM_DATABASE=Sencore + +OUI:00064E* + ID_OUI_FROM_DATABASE=Broad Net Technology Inc. + +OUI:00064F* + ID_OUI_FROM_DATABASE=PRO-NETS Technology Corporation + +OUI:000650* + ID_OUI_FROM_DATABASE=Tiburon Networks, Inc. + +OUI:000651* + ID_OUI_FROM_DATABASE=Aspen Networks Inc. + +OUI:000652* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000653* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000654* + ID_OUI_FROM_DATABASE=Winpresa Building Automation Technologies GmbH + +OUI:000655* + ID_OUI_FROM_DATABASE=Yipee, Inc. + +OUI:000656* + ID_OUI_FROM_DATABASE=Tactel AB + +OUI:000657* + ID_OUI_FROM_DATABASE=Market Central, Inc. + +OUI:000658* + ID_OUI_FROM_DATABASE=Helmut Fischer GmbH Institut für Elektronik und Messtechnik + +OUI:000659* + ID_OUI_FROM_DATABASE=EAL (Apeldoorn) B.V. + +OUI:00065A* + ID_OUI_FROM_DATABASE=Strix Systems + +OUI:00065B* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:00065C* + ID_OUI_FROM_DATABASE=Malachite Technologies, Inc. + +OUI:00065D* + ID_OUI_FROM_DATABASE=Heidelberg Web Systems + +OUI:00065E* + ID_OUI_FROM_DATABASE=Photuris, Inc. + +OUI:00065F* + ID_OUI_FROM_DATABASE=ECI Telecom Ltd. + +OUI:000660* + ID_OUI_FROM_DATABASE=NADEX Co., Ltd. + +OUI:000661* + ID_OUI_FROM_DATABASE=NIA Home Technologies Corp. + +OUI:000662* + ID_OUI_FROM_DATABASE=MBM Technology Ltd. + +OUI:000663* + ID_OUI_FROM_DATABASE=Human Technology Co., Ltd. + +OUI:000664* + ID_OUI_FROM_DATABASE=Fostex Corporation + +OUI:000665* + ID_OUI_FROM_DATABASE=Sunny Giken, Inc. + +OUI:000666* + ID_OUI_FROM_DATABASE=Roving Networks + +OUI:000667* + ID_OUI_FROM_DATABASE=Tripp Lite + +OUI:000668* + ID_OUI_FROM_DATABASE=Vicon Industries Inc. + +OUI:000669* + ID_OUI_FROM_DATABASE=Datasound Laboratories Ltd + +OUI:00066A* + ID_OUI_FROM_DATABASE=InfiniCon Systems, Inc. + +OUI:00066B* + ID_OUI_FROM_DATABASE=Sysmex Corporation + +OUI:00066C* + ID_OUI_FROM_DATABASE=Robinson Corporation + +OUI:00066D* + ID_OUI_FROM_DATABASE=Compuprint S.P.A. + +OUI:00066E* + ID_OUI_FROM_DATABASE=Delta Electronics, Inc. + +OUI:00066F* + ID_OUI_FROM_DATABASE=Korea Data Systems + +OUI:000670* + ID_OUI_FROM_DATABASE=Upponetti Oy + +OUI:000671* + ID_OUI_FROM_DATABASE=Softing AG + +OUI:000672* + ID_OUI_FROM_DATABASE=Netezza + +OUI:000673* + ID_OUI_FROM_DATABASE=TKH Security Solutions USA + +OUI:000674* + ID_OUI_FROM_DATABASE=Spectrum Control, Inc. + +OUI:000675* + ID_OUI_FROM_DATABASE=Banderacom, Inc. + +OUI:000676* + ID_OUI_FROM_DATABASE=Novra Technologies Inc. + +OUI:000677* + ID_OUI_FROM_DATABASE=SICK AG + +OUI:000678* + ID_OUI_FROM_DATABASE=D&M Holdings Inc. + +OUI:000679* + ID_OUI_FROM_DATABASE=Konami Corporation + +OUI:00067A* + ID_OUI_FROM_DATABASE=JMP Systems + +OUI:00067B* + ID_OUI_FROM_DATABASE=Toplink C&C Corporation + +OUI:00067C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00067D* + ID_OUI_FROM_DATABASE=Takasago Ltd. + +OUI:00067E* + ID_OUI_FROM_DATABASE=WinCom Systems, Inc. + +OUI:00067F* + ID_OUI_FROM_DATABASE=Digeo, Inc. + +OUI:000680* + ID_OUI_FROM_DATABASE=Card Access, Inc. + +OUI:000681* + ID_OUI_FROM_DATABASE=Goepel Electronic GmbH + +OUI:000682* + ID_OUI_FROM_DATABASE=Convedia + +OUI:000683* + ID_OUI_FROM_DATABASE=Bravara Communications, Inc. + +OUI:000684* + ID_OUI_FROM_DATABASE=Biacore AB + +OUI:000685* + ID_OUI_FROM_DATABASE=NetNearU Corporation + +OUI:000686* + ID_OUI_FROM_DATABASE=ZARDCOM Co., Ltd. + +OUI:000687* + ID_OUI_FROM_DATABASE=Omnitron Systems Technology, Inc. + +OUI:000688* + ID_OUI_FROM_DATABASE=Telways Communication Co., Ltd. + +OUI:000689* + ID_OUI_FROM_DATABASE=yLez Technologies Pte Ltd + +OUI:00068A* + ID_OUI_FROM_DATABASE=NeuronNet Co. Ltd. R&D Center + +OUI:00068B* + ID_OUI_FROM_DATABASE=AirRunner Technologies, Inc. + +OUI:00068C* + ID_OUI_FROM_DATABASE=3COM + +OUI:00068D* + ID_OUI_FROM_DATABASE=SEPATON, Inc. + +OUI:00068E* + ID_OUI_FROM_DATABASE=HID Corporation + +OUI:00068F* + ID_OUI_FROM_DATABASE=Telemonitor, Inc. + +OUI:000690* + ID_OUI_FROM_DATABASE=Euracom Communication GmbH + +OUI:000691* + ID_OUI_FROM_DATABASE=PT Inovacao + +OUI:000692* + ID_OUI_FROM_DATABASE=Intruvert Networks, Inc. + +OUI:000693* + ID_OUI_FROM_DATABASE=Flexus Computer Technology, Inc. + +OUI:000694* + ID_OUI_FROM_DATABASE=Mobillian Corporation + +OUI:000695* + ID_OUI_FROM_DATABASE=Ensure Technologies, Inc. + +OUI:000696* + ID_OUI_FROM_DATABASE=Advent Networks + +OUI:000697* + ID_OUI_FROM_DATABASE=R & D Center + +OUI:000698* + ID_OUI_FROM_DATABASE=egnite GmbH + +OUI:000699* + ID_OUI_FROM_DATABASE=Vida Design Co. + +OUI:00069A* + ID_OUI_FROM_DATABASE=e & Tel + +OUI:00069B* + ID_OUI_FROM_DATABASE=AVT Audio Video Technologies GmbH + +OUI:00069C* + ID_OUI_FROM_DATABASE=Transmode Systems AB + +OUI:00069D* + ID_OUI_FROM_DATABASE=Petards Ltd + +OUI:00069E* + ID_OUI_FROM_DATABASE=UNIQA, Inc. + +OUI:00069F* + ID_OUI_FROM_DATABASE=Kuokoa Networks + +OUI:0006A0* + ID_OUI_FROM_DATABASE=Mx Imaging + +OUI:0006A1* + ID_OUI_FROM_DATABASE=Celsian Technologies, Inc. + +OUI:0006A2* + ID_OUI_FROM_DATABASE=Microtune, Inc. + +OUI:0006A3* + ID_OUI_FROM_DATABASE=Bitran Corporation + +OUI:0006A4* + ID_OUI_FROM_DATABASE=INNOWELL Corp. + +OUI:0006A5* + ID_OUI_FROM_DATABASE=PINON Corp. + +OUI:0006A6* + ID_OUI_FROM_DATABASE=Artistic Licence Engineering Ltd + +OUI:0006A7* + ID_OUI_FROM_DATABASE=Primarion + +OUI:0006A8* + ID_OUI_FROM_DATABASE=KC Technology, Inc. + +OUI:0006A9* + ID_OUI_FROM_DATABASE=Universal Instruments Corp. + +OUI:0006AA* + ID_OUI_FROM_DATABASE=VT Miltope + +OUI:0006AB* + ID_OUI_FROM_DATABASE=W-Link Systems, Inc. + +OUI:0006AC* + ID_OUI_FROM_DATABASE=Intersoft Co. + +OUI:0006AD* + ID_OUI_FROM_DATABASE=KB Electronics Ltd. + +OUI:0006AE* + ID_OUI_FROM_DATABASE=Himachal Futuristic Communications Ltd + +OUI:0006AF* + ID_OUI_FROM_DATABASE=Xalted Networks + +OUI:0006B0* + ID_OUI_FROM_DATABASE=Comtech EF Data Corp. + +OUI:0006B1* + ID_OUI_FROM_DATABASE=Sonicwall + +OUI:0006B2* + ID_OUI_FROM_DATABASE=Linxtek Co. + +OUI:0006B3* + ID_OUI_FROM_DATABASE=Diagraph Corporation + +OUI:0006B4* + ID_OUI_FROM_DATABASE=Vorne Industries, Inc. + +OUI:0006B5* + ID_OUI_FROM_DATABASE=Source Photonics, Inc. + +OUI:0006B6* + ID_OUI_FROM_DATABASE=Nir-Or Israel Ltd. + +OUI:0006B7* + ID_OUI_FROM_DATABASE=TELEM GmbH + +OUI:0006B8* + ID_OUI_FROM_DATABASE=Bandspeed Pty Ltd + +OUI:0006B9* + ID_OUI_FROM_DATABASE=A5TEK Corp. + +OUI:0006BA* + ID_OUI_FROM_DATABASE=Westwave Communications + +OUI:0006BB* + ID_OUI_FROM_DATABASE=ATI Technologies Inc. + +OUI:0006BC* + ID_OUI_FROM_DATABASE=Macrolink, Inc. + +OUI:0006BD* + ID_OUI_FROM_DATABASE=BNTECHNOLOGY Co., Ltd. + +OUI:0006BE* + ID_OUI_FROM_DATABASE=Baumer Optronic GmbH + +OUI:0006BF* + ID_OUI_FROM_DATABASE=Accella Technologies Co., Ltd. + +OUI:0006C0* + ID_OUI_FROM_DATABASE=United Internetworks, Inc. + +OUI:0006C1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0006C2* + ID_OUI_FROM_DATABASE=Smartmatic Corporation + +OUI:0006C3* + ID_OUI_FROM_DATABASE=Schindler Elevator Ltd. + +OUI:0006C4* + ID_OUI_FROM_DATABASE=Piolink Inc. + +OUI:0006C5* + ID_OUI_FROM_DATABASE=INNOVI Technologies Limited + +OUI:0006C6* + ID_OUI_FROM_DATABASE=lesswire AG + +OUI:0006C7* + ID_OUI_FROM_DATABASE=RFNET Technologies Pte Ltd (S) + +OUI:0006C8* + ID_OUI_FROM_DATABASE=Sumitomo Metal Micro Devices, Inc. + +OUI:0006C9* + ID_OUI_FROM_DATABASE=Technical Marketing Research, Inc. + +OUI:0006CA* + ID_OUI_FROM_DATABASE=American Computer & Digital Components, Inc. (ACDC) + +OUI:0006CB* + ID_OUI_FROM_DATABASE=Jotron Electronics A/S + +OUI:0006CC* + ID_OUI_FROM_DATABASE=JMI Electronics Co., Ltd. + +OUI:0006CD* + ID_OUI_FROM_DATABASE=Leaf Imaging Ltd. + +OUI:0006CE* + ID_OUI_FROM_DATABASE=DATENO + +OUI:0006CF* + ID_OUI_FROM_DATABASE=Thales Avionics In-Flight Systems, LLC + +OUI:0006D0* + ID_OUI_FROM_DATABASE=Elgar Electronics Corp. + +OUI:0006D1* + ID_OUI_FROM_DATABASE=Tahoe Networks, Inc. + +OUI:0006D2* + ID_OUI_FROM_DATABASE=Tundra Semiconductor Corp. + +OUI:0006D3* + ID_OUI_FROM_DATABASE=Alpha Telecom, Inc. U.S.A. + +OUI:0006D4* + ID_OUI_FROM_DATABASE=Interactive Objects, Inc. + +OUI:0006D5* + ID_OUI_FROM_DATABASE=Diamond Systems Corp. + +OUI:0006D6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0006D7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0006D8* + ID_OUI_FROM_DATABASE=Maple Optical Systems + +OUI:0006D9* + ID_OUI_FROM_DATABASE=IPM-Net S.p.A. + +OUI:0006DA* + ID_OUI_FROM_DATABASE=ITRAN Communications Ltd. + +OUI:0006DB* + ID_OUI_FROM_DATABASE=ICHIPS Co., Ltd. + +OUI:0006DC* + ID_OUI_FROM_DATABASE=Syabas Technology (Amquest) + +OUI:0006DD* + ID_OUI_FROM_DATABASE=AT & T Laboratories - Cambridge Ltd + +OUI:0006DE* + ID_OUI_FROM_DATABASE=Flash Technology + +OUI:0006DF* + ID_OUI_FROM_DATABASE=AIDONIC Corporation + +OUI:0006E0* + ID_OUI_FROM_DATABASE=MAT Co., Ltd. + +OUI:0006E1* + ID_OUI_FROM_DATABASE=Techno Trade s.a + +OUI:0006E2* + ID_OUI_FROM_DATABASE=Ceemax Technology Co., Ltd. + +OUI:0006E3* + ID_OUI_FROM_DATABASE=Quantitative Imaging Corporation + +OUI:0006E4* + ID_OUI_FROM_DATABASE=Citel Technologies Ltd. + +OUI:0006E5* + ID_OUI_FROM_DATABASE=Fujian Newland Computer Ltd. Co. + +OUI:0006E6* + ID_OUI_FROM_DATABASE=DongYang Telecom Co., Ltd. + +OUI:0006E7* + ID_OUI_FROM_DATABASE=Bit Blitz Communications Inc. + +OUI:0006E8* + ID_OUI_FROM_DATABASE=Optical Network Testing, Inc. + +OUI:0006E9* + ID_OUI_FROM_DATABASE=Intime Corp. + +OUI:0006EA* + ID_OUI_FROM_DATABASE=ELZET80 Mikrocomputer GmbH&Co. KG + +OUI:0006EB* + ID_OUI_FROM_DATABASE=Global Data + +OUI:0006EC* + ID_OUI_FROM_DATABASE=Harris Corporation + +OUI:0006ED* + ID_OUI_FROM_DATABASE=Inara Networks + +OUI:0006EE* + ID_OUI_FROM_DATABASE=Shenyang Neu-era Information & Technology Stock Co., Ltd + +OUI:0006EF* + ID_OUI_FROM_DATABASE=Maxxan Systems, Inc. + +OUI:0006F0* + ID_OUI_FROM_DATABASE=Digeo, Inc. + +OUI:0006F1* + ID_OUI_FROM_DATABASE=Optillion + +OUI:0006F2* + ID_OUI_FROM_DATABASE=Platys Communications + +OUI:0006F3* + ID_OUI_FROM_DATABASE=AcceLight Networks + +OUI:0006F4* + ID_OUI_FROM_DATABASE=Prime Electronics & Satellitics Inc. + +OUI:0006F5* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:0006F6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0006F7* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:0006F8* + ID_OUI_FROM_DATABASE=The Boeing Company + +OUI:0006F9* + ID_OUI_FROM_DATABASE=Mitsui Zosen Systems Research Inc. + +OUI:0006FA* + ID_OUI_FROM_DATABASE=IP SQUARE Co, Ltd. + +OUI:0006FB* + ID_OUI_FROM_DATABASE=Hitachi Printing Solutions, Ltd. + +OUI:0006FC* + ID_OUI_FROM_DATABASE=Fnet Co., Ltd. + +OUI:0006FD* + ID_OUI_FROM_DATABASE=Comjet Information Systems Corp. + +OUI:0006FE* + ID_OUI_FROM_DATABASE=Ambrado, Inc + +OUI:0006FF* + ID_OUI_FROM_DATABASE=Sheba Systems Co., Ltd. + +OUI:000700* + ID_OUI_FROM_DATABASE=Zettamedia Korea + +OUI:000701* + ID_OUI_FROM_DATABASE=RACAL-DATACOM + +OUI:000702* + ID_OUI_FROM_DATABASE=Varex Imaging + +OUI:000703* + ID_OUI_FROM_DATABASE=CSEE Transport + +OUI:000704* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:000705* + ID_OUI_FROM_DATABASE=Endress & Hauser GmbH & Co + +OUI:000706* + ID_OUI_FROM_DATABASE=Sanritz Corporation + +OUI:000707* + ID_OUI_FROM_DATABASE=Interalia Inc. + +OUI:000708* + ID_OUI_FROM_DATABASE=Bitrage Inc. + +OUI:000709* + ID_OUI_FROM_DATABASE=Westerstrand Urfabrik AB + +OUI:00070A* + ID_OUI_FROM_DATABASE=Unicom Automation Co., Ltd. + +OUI:00070B* + ID_OUI_FROM_DATABASE=Novabase SGPS, SA + +OUI:00070C* + ID_OUI_FROM_DATABASE=SVA-Intrusion.com Co. Ltd. + +OUI:00070D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00070E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00070F* + ID_OUI_FROM_DATABASE=Fujant, Inc. + +OUI:000710* + ID_OUI_FROM_DATABASE=Adax, Inc. + +OUI:000711* + ID_OUI_FROM_DATABASE=Acterna + +OUI:000712* + ID_OUI_FROM_DATABASE=JAL Information Technology + +OUI:000713* + ID_OUI_FROM_DATABASE=IP One, Inc. + +OUI:000714* + ID_OUI_FROM_DATABASE=Brightcom + +OUI:000715* + ID_OUI_FROM_DATABASE=General Research of Electronics, Inc. + +OUI:000716* + ID_OUI_FROM_DATABASE=J & S Marine Ltd. + +OUI:000717* + ID_OUI_FROM_DATABASE=Wieland Electric GmbH + +OUI:000718* + ID_OUI_FROM_DATABASE=iCanTek Co., Ltd. + +OUI:000719* + ID_OUI_FROM_DATABASE=Mobiis Co., Ltd. + +OUI:00071A* + ID_OUI_FROM_DATABASE=Finedigital Inc. + +OUI:00071B* + ID_OUI_FROM_DATABASE=CDVI Americas Ltd + +OUI:00071C* + ID_OUI_FROM_DATABASE=AT&T + +OUI:00071D* + ID_OUI_FROM_DATABASE=Satelsa Sistemas Y Aplicaciones De Telecomunicaciones, S.A. + +OUI:00071E* + ID_OUI_FROM_DATABASE=Tri-M Engineering / Nupak Dev. Corp. + +OUI:00071F* + ID_OUI_FROM_DATABASE=European Systems Integration + +OUI:000720* + ID_OUI_FROM_DATABASE=Trutzschler GmbH & Co. KG + +OUI:000721* + ID_OUI_FROM_DATABASE=Formac Elektronik GmbH + +OUI:000722* + ID_OUI_FROM_DATABASE=The Nielsen Company + +OUI:000723* + ID_OUI_FROM_DATABASE=ELCON Systemtechnik GmbH + +OUI:000724* + ID_OUI_FROM_DATABASE=Telemax Co., Ltd. + +OUI:000725* + ID_OUI_FROM_DATABASE=Bematech International Corp. + +OUI:000726* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:000727* + ID_OUI_FROM_DATABASE=Zi Corporation (HK) Ltd. + +OUI:000728* + ID_OUI_FROM_DATABASE=Neo Telecom + +OUI:000729* + ID_OUI_FROM_DATABASE=Kistler Instrumente AG + +OUI:00072A* + ID_OUI_FROM_DATABASE=Innovance Networks + +OUI:00072B* + ID_OUI_FROM_DATABASE=Jung Myung Telecom Co., Ltd. + +OUI:00072C* + ID_OUI_FROM_DATABASE=Fabricom + +OUI:00072D* + ID_OUI_FROM_DATABASE=CNSystems + +OUI:00072E* + ID_OUI_FROM_DATABASE=North Node AB + +OUI:00072F* + ID_OUI_FROM_DATABASE=Intransa, Inc. + +OUI:000730* + ID_OUI_FROM_DATABASE=Hutchison OPTEL Telecom Technology Co., Ltd. + +OUI:000731* + ID_OUI_FROM_DATABASE=Ophir-Spiricon LLC + +OUI:000732* + ID_OUI_FROM_DATABASE=AAEON Technology Inc. + +OUI:000733* + ID_OUI_FROM_DATABASE=DANCONTROL Engineering + +OUI:000734* + ID_OUI_FROM_DATABASE=ONStor, Inc. + +OUI:000735* + ID_OUI_FROM_DATABASE=Flarion Technologies, Inc. + +OUI:000736* + ID_OUI_FROM_DATABASE=Data Video Technologies Co., Ltd. + +OUI:000737* + ID_OUI_FROM_DATABASE=Soriya Co. Ltd. + +OUI:000738* + ID_OUI_FROM_DATABASE=Young Technology Co., Ltd. + +OUI:000739* + ID_OUI_FROM_DATABASE=Scotty Group Austria Gmbh + +OUI:00073A* + ID_OUI_FROM_DATABASE=INVENTEL + +OUI:00073B* + ID_OUI_FROM_DATABASE=Tenovis GmbH & Co KG + +OUI:00073C* + ID_OUI_FROM_DATABASE=Telecom Design + +OUI:00073D* + ID_OUI_FROM_DATABASE=Nanjing Postel Telecommunications Co., Ltd. + +OUI:00073E* + ID_OUI_FROM_DATABASE=China Great-Wall Computer Shenzhen Co., Ltd. + +OUI:00073F* + ID_OUI_FROM_DATABASE=Woojyun Systec Co., Ltd. + +OUI:000740* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:000741* + ID_OUI_FROM_DATABASE=Sierra Automated Systems + +OUI:000742* + ID_OUI_FROM_DATABASE=Ormazabal + +OUI:000743* + ID_OUI_FROM_DATABASE=Chelsio Communications + +OUI:000744* + ID_OUI_FROM_DATABASE=Unico, Inc. + +OUI:000745* + ID_OUI_FROM_DATABASE=Radlan Computer Communications Ltd. + +OUI:000746* + ID_OUI_FROM_DATABASE=TURCK, Inc. + +OUI:000747* + ID_OUI_FROM_DATABASE=Mecalc + +OUI:000748* + ID_OUI_FROM_DATABASE=The Imaging Source Europe + +OUI:000749* + ID_OUI_FROM_DATABASE=CENiX Inc. + +OUI:00074A* + ID_OUI_FROM_DATABASE=Carl Valentin GmbH + +OUI:00074B* + ID_OUI_FROM_DATABASE=Daihen Corporation + +OUI:00074C* + ID_OUI_FROM_DATABASE=Beicom Inc. + +OUI:00074D* + ID_OUI_FROM_DATABASE=Zebra Technologies Corp. + +OUI:00074E* + ID_OUI_FROM_DATABASE=IPFRONT Inc + +OUI:00074F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000750* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000751* + ID_OUI_FROM_DATABASE=m-u-t AG + +OUI:000752* + ID_OUI_FROM_DATABASE=Rhythm Watch Co., Ltd. + +OUI:000753* + ID_OUI_FROM_DATABASE=Beijing Qxcomm Technology Co., Ltd. + +OUI:000754* + ID_OUI_FROM_DATABASE=Xyterra Computing, Inc. + +OUI:000755* + ID_OUI_FROM_DATABASE=Lafon + +OUI:000756* + ID_OUI_FROM_DATABASE=Juyoung Telecom + +OUI:000757* + ID_OUI_FROM_DATABASE=Topcall International AG + +OUI:000758* + ID_OUI_FROM_DATABASE=DragonWave Inc. + +OUI:000759* + ID_OUI_FROM_DATABASE=Boris Manufacturing Corp. + +OUI:00075A* + ID_OUI_FROM_DATABASE=Air Products and Chemicals, Inc. + +OUI:00075B* + ID_OUI_FROM_DATABASE=Gibson Guitars + +OUI:00075C* + ID_OUI_FROM_DATABASE=Eastman Kodak Company + +OUI:00075D* + ID_OUI_FROM_DATABASE=Celleritas Inc. + +OUI:00075E* + ID_OUI_FROM_DATABASE=Ametek Power Instruments + +OUI:00075F* + ID_OUI_FROM_DATABASE=VCS Video Communication Systems AG + +OUI:000760* + ID_OUI_FROM_DATABASE=TOMIS Information & Telecom Corp. + +OUI:000761* + ID_OUI_FROM_DATABASE=29530 + +OUI:000762* + ID_OUI_FROM_DATABASE=Group Sense Limited + +OUI:000763* + ID_OUI_FROM_DATABASE=Sunniwell Cyber Tech. Co., Ltd. + +OUI:000764* + ID_OUI_FROM_DATABASE=YoungWoo Telecom Co. Ltd. + +OUI:000765* + ID_OUI_FROM_DATABASE=Jade Quantum Technologies, Inc. + +OUI:000766* + ID_OUI_FROM_DATABASE=Chou Chin Industrial Co., Ltd. + +OUI:000767* + ID_OUI_FROM_DATABASE=Yuxing Electronics Company Limited + +OUI:000768* + ID_OUI_FROM_DATABASE=Danfoss A/S + +OUI:000769* + ID_OUI_FROM_DATABASE=Italiana Macchi SpA + +OUI:00076A* + ID_OUI_FROM_DATABASE=NEXTEYE Co., Ltd. + +OUI:00076B* + ID_OUI_FROM_DATABASE=Stralfors AB + +OUI:00076C* + ID_OUI_FROM_DATABASE=Daehanet, Inc. + +OUI:00076D* + ID_OUI_FROM_DATABASE=Flexlight Networks + +OUI:00076E* + ID_OUI_FROM_DATABASE=Sinetica Corporation Limited + +OUI:00076F* + ID_OUI_FROM_DATABASE=Synoptics Limited + +OUI:000770* + ID_OUI_FROM_DATABASE=Ubiquoss Inc + +OUI:000771* + ID_OUI_FROM_DATABASE=Embedded System Corporation + +OUI:000772* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:000773* + ID_OUI_FROM_DATABASE=Ascom Powerline Communications Ltd. + +OUI:000774* + ID_OUI_FROM_DATABASE=GuangZhou Thinker Technology Co. Ltd. + +OUI:000775* + ID_OUI_FROM_DATABASE=Valence Semiconductor, Inc. + +OUI:000776* + ID_OUI_FROM_DATABASE=Federal APD + +OUI:000777* + ID_OUI_FROM_DATABASE=Motah Ltd. + +OUI:000778* + ID_OUI_FROM_DATABASE=GERSTEL GmbH & Co. KG + +OUI:000779* + ID_OUI_FROM_DATABASE=Sungil Telecom Co., Ltd. + +OUI:00077A* + ID_OUI_FROM_DATABASE=Infoware System Co., Ltd. + +OUI:00077B* + ID_OUI_FROM_DATABASE=Millimetrix Broadband Networks + +OUI:00077C* + ID_OUI_FROM_DATABASE=Westermo Network Technologies AB + +OUI:00077D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00077E* + ID_OUI_FROM_DATABASE=Elrest GmbH + +OUI:00077F* + ID_OUI_FROM_DATABASE=J Communications Co., Ltd. + +OUI:000780* + ID_OUI_FROM_DATABASE=Bluegiga Technologies OY + +OUI:000781* + ID_OUI_FROM_DATABASE=Itron Inc. + +OUI:000782* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:000783* + ID_OUI_FROM_DATABASE=SynCom Network, Inc. + +OUI:000784* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000785* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000786* + ID_OUI_FROM_DATABASE=Wireless Networks Inc. + +OUI:000787* + ID_OUI_FROM_DATABASE=Idea System Co., Ltd. + +OUI:000788* + ID_OUI_FROM_DATABASE=Clipcomm, Inc. + +OUI:000789* + ID_OUI_FROM_DATABASE=Allradio Co., Ltd + +OUI:00078A* + ID_OUI_FROM_DATABASE=Mentor Data System Inc. + +OUI:00078B* + ID_OUI_FROM_DATABASE=Wegener Communications, Inc. + +OUI:00078C* + ID_OUI_FROM_DATABASE=Elektronikspecialisten i Borlange AB + +OUI:00078D* + ID_OUI_FROM_DATABASE=NetEngines Ltd. + +OUI:00078E* + ID_OUI_FROM_DATABASE=Garz & Friche GmbH + +OUI:00078F* + ID_OUI_FROM_DATABASE=Emkay Innovative Products + +OUI:000790* + ID_OUI_FROM_DATABASE=Tri-M Technologies (s) Limited + +OUI:000791* + ID_OUI_FROM_DATABASE=International Data Communications, Inc. + +OUI:000792* + ID_OUI_FROM_DATABASE=Sütron Electronic GmbH + +OUI:000793* + ID_OUI_FROM_DATABASE=Shin Satellite Public Company Limited + +OUI:000794* + ID_OUI_FROM_DATABASE=Simple Devices, Inc. + +OUI:000795* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:000796* + ID_OUI_FROM_DATABASE=LSI Systems, Inc. + +OUI:000797* + ID_OUI_FROM_DATABASE=Netpower Co., Ltd. + +OUI:000798* + ID_OUI_FROM_DATABASE=Selea SRL + +OUI:000799* + ID_OUI_FROM_DATABASE=Tipping Point Technologies, Inc. + +OUI:00079A* + ID_OUI_FROM_DATABASE=Verint Systems Inc + +OUI:00079B* + ID_OUI_FROM_DATABASE=Aurora Networks + +OUI:00079C* + ID_OUI_FROM_DATABASE=Golden Electronics Technology Co., Ltd. + +OUI:00079D* + ID_OUI_FROM_DATABASE=Musashi Co., Ltd. + +OUI:00079E* + ID_OUI_FROM_DATABASE=Ilinx Co., Ltd. + +OUI:00079F* + ID_OUI_FROM_DATABASE=Action Digital Inc. + +OUI:0007A0* + ID_OUI_FROM_DATABASE=e-Watch Inc. + +OUI:0007A1* + ID_OUI_FROM_DATABASE=VIASYS Healthcare GmbH + +OUI:0007A2* + ID_OUI_FROM_DATABASE=Opteon Corporation + +OUI:0007A3* + ID_OUI_FROM_DATABASE=Ositis Software, Inc. + +OUI:0007A4* + ID_OUI_FROM_DATABASE=GN Netcom Ltd. + +OUI:0007A5* + ID_OUI_FROM_DATABASE=Y.D.K Co. Ltd. + +OUI:0007A6* + ID_OUI_FROM_DATABASE=Leviton Manufacturing Co., Inc. + +OUI:0007A7* + ID_OUI_FROM_DATABASE=A-Z Inc. + +OUI:0007A8* + ID_OUI_FROM_DATABASE=Haier Group Technologies Ltd + +OUI:0007A9* + ID_OUI_FROM_DATABASE=Novasonics + +OUI:0007AA* + ID_OUI_FROM_DATABASE=Quantum Data Inc. + +OUI:0007AB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0007AC* + ID_OUI_FROM_DATABASE=Eolring + +OUI:0007AD* + ID_OUI_FROM_DATABASE=Pentacon GmbH Foto-und Feinwerktechnik + +OUI:0007AE* + ID_OUI_FROM_DATABASE=Britestream Networks, Inc. + +OUI:0007AF* + ID_OUI_FROM_DATABASE=Red Lion Controls, LP + +OUI:0007B0* + ID_OUI_FROM_DATABASE=Office Details, Inc. + +OUI:0007B1* + ID_OUI_FROM_DATABASE=Equator Technologies + +OUI:0007B2* + ID_OUI_FROM_DATABASE=Transaccess S.A. + +OUI:0007B3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0007B4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0007B5* + ID_OUI_FROM_DATABASE=Any One Wireless Ltd. + +OUI:0007B6* + ID_OUI_FROM_DATABASE=Telecom Technology Ltd. + +OUI:0007B7* + ID_OUI_FROM_DATABASE=Samurai Ind. Prods Eletronicos Ltda + +OUI:0007B8* + ID_OUI_FROM_DATABASE=Corvalent Corporation + +OUI:0007B9* + ID_OUI_FROM_DATABASE=Ginganet Corporation + +OUI:0007BA* + ID_OUI_FROM_DATABASE=UTStarcom Inc + +OUI:0007BB* + ID_OUI_FROM_DATABASE=Candera Inc. + +OUI:0007BC* + ID_OUI_FROM_DATABASE=Identix Inc. + +OUI:0007BD* + ID_OUI_FROM_DATABASE=Radionet Ltd. + +OUI:0007BE* + ID_OUI_FROM_DATABASE=DataLogic SpA + +OUI:0007BF* + ID_OUI_FROM_DATABASE=Armillaire Technologies, Inc. + +OUI:0007C0* + ID_OUI_FROM_DATABASE=NetZerver Inc. + +OUI:0007C1* + ID_OUI_FROM_DATABASE=Overture Networks, Inc. + +OUI:0007C2* + ID_OUI_FROM_DATABASE=Netsys Telecom + +OUI:0007C3* + ID_OUI_FROM_DATABASE=Thomson + +OUI:0007C4* + ID_OUI_FROM_DATABASE=JEAN Co. Ltd. + +OUI:0007C5* + ID_OUI_FROM_DATABASE=Gcom, Inc. + +OUI:0007C6* + ID_OUI_FROM_DATABASE=VDS Vosskuhler GmbH + +OUI:0007C7* + ID_OUI_FROM_DATABASE=Synectics Systems Limited + +OUI:0007C8* + ID_OUI_FROM_DATABASE=Brain21, Inc. + +OUI:0007C9* + ID_OUI_FROM_DATABASE=Technol Seven Co., Ltd. + +OUI:0007CA* + ID_OUI_FROM_DATABASE=Creatix Polymedia Ges Fur Kommunikaitonssysteme + +OUI:0007CB* + ID_OUI_FROM_DATABASE=FREEBOX SAS + +OUI:0007CC* + ID_OUI_FROM_DATABASE=Kaba Benzing GmbH + +OUI:0007CD* + ID_OUI_FROM_DATABASE=Kumoh Electronic Co, Ltd + +OUI:0007CE* + ID_OUI_FROM_DATABASE=Cabletime Limited + +OUI:0007CF* + ID_OUI_FROM_DATABASE=Anoto AB + +OUI:0007D0* + ID_OUI_FROM_DATABASE=Automat Engenharia de Automação Ltda. + +OUI:0007D1* + ID_OUI_FROM_DATABASE=Spectrum Signal Processing Inc. + +OUI:0007D2* + ID_OUI_FROM_DATABASE=Logopak Systeme GmbH & Co. KG + +OUI:0007D3* + ID_OUI_FROM_DATABASE=SPGPrints B.V. + +OUI:0007D4* + ID_OUI_FROM_DATABASE=Zhejiang Yutong Network Communication Co Ltd. + +OUI:0007D5* + ID_OUI_FROM_DATABASE=3e Technologies Int;., Inc. + +OUI:0007D6* + ID_OUI_FROM_DATABASE=Commil Ltd. + +OUI:0007D7* + ID_OUI_FROM_DATABASE=Caporis Networks AG + +OUI:0007D8* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:0007D9* + ID_OUI_FROM_DATABASE=Splicecom + +OUI:0007DA* + ID_OUI_FROM_DATABASE=Neuro Telecom Co., Ltd. + +OUI:0007DB* + ID_OUI_FROM_DATABASE=Kirana Networks, Inc. + +OUI:0007DC* + ID_OUI_FROM_DATABASE=Atek Co, Ltd. + +OUI:0007DD* + ID_OUI_FROM_DATABASE=Cradle Technologies + +OUI:0007DE* + ID_OUI_FROM_DATABASE=eCopilt AB + +OUI:0007DF* + ID_OUI_FROM_DATABASE=Vbrick Systems Inc. + +OUI:0007E0* + ID_OUI_FROM_DATABASE=Palm Inc. + +OUI:0007E1* + ID_OUI_FROM_DATABASE=WIS Communications Co. Ltd. + +OUI:0007E2* + ID_OUI_FROM_DATABASE=Bitworks, Inc. + +OUI:0007E3* + ID_OUI_FROM_DATABASE=Navcom Technology, Inc. + +OUI:0007E4* + ID_OUI_FROM_DATABASE=SoftRadio Co., Ltd. + +OUI:0007E5* + ID_OUI_FROM_DATABASE=Coup Corporation + +OUI:0007E6* + ID_OUI_FROM_DATABASE=edgeflow Canada Inc. + +OUI:0007E7* + ID_OUI_FROM_DATABASE=FreeWave Technologies + +OUI:0007E8* + ID_OUI_FROM_DATABASE=EdgeWave + +OUI:0007E9* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:0007EA* + ID_OUI_FROM_DATABASE=Massana, Inc. + +OUI:0007EB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0007EC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0007ED* + ID_OUI_FROM_DATABASE=Altera Corporation + +OUI:0007EE* + ID_OUI_FROM_DATABASE=telco Informationssysteme GmbH + +OUI:0007EF* + ID_OUI_FROM_DATABASE=Lockheed Martin Tactical Systems + +OUI:0007F0* + ID_OUI_FROM_DATABASE=LogiSync LLC + +OUI:0007F1* + ID_OUI_FROM_DATABASE=TeraBurst Networks Inc. + +OUI:0007F2* + ID_OUI_FROM_DATABASE=IOA Corporation + +OUI:0007F3* + ID_OUI_FROM_DATABASE=Thinkengine Networks + +OUI:0007F4* + ID_OUI_FROM_DATABASE=Eletex Co., Ltd. + +OUI:0007F5* + ID_OUI_FROM_DATABASE=Bridgeco Co AG + +OUI:0007F6* + ID_OUI_FROM_DATABASE=Qqest Software Systems + +OUI:0007F7* + ID_OUI_FROM_DATABASE=Galtronics + +OUI:0007F8* + ID_OUI_FROM_DATABASE=ITDevices, Inc. + +OUI:0007F9* + ID_OUI_FROM_DATABASE=Sensaphone + +OUI:0007FA* + ID_OUI_FROM_DATABASE=ITT Co., Ltd. + +OUI:0007FB* + ID_OUI_FROM_DATABASE=Giga Stream UMTS Technologies GmbH + +OUI:0007FC* + ID_OUI_FROM_DATABASE=Adept Systems Inc. + +OUI:0007FD* + ID_OUI_FROM_DATABASE=LANergy Ltd. + +OUI:0007FE* + ID_OUI_FROM_DATABASE=Rigaku Corporation + +OUI:0007FF* + ID_OUI_FROM_DATABASE=Gluon Networks + +OUI:000800* + ID_OUI_FROM_DATABASE=MULTITECH SYSTEMS, INC. + +OUI:000801* + ID_OUI_FROM_DATABASE=HighSpeed Surfing Inc. + +OUI:000802* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:000803* + ID_OUI_FROM_DATABASE=Cos Tron + +OUI:000804* + ID_OUI_FROM_DATABASE=ICA Inc. + +OUI:000805* + ID_OUI_FROM_DATABASE=Techno-Holon Corporation + +OUI:000806* + ID_OUI_FROM_DATABASE=Raonet Systems, Inc. + +OUI:000807* + ID_OUI_FROM_DATABASE=Access Devices Limited + +OUI:000808* + ID_OUI_FROM_DATABASE=PPT Vision, Inc. + +OUI:000809* + ID_OUI_FROM_DATABASE=Systemonic AG + +OUI:00080A* + ID_OUI_FROM_DATABASE=Espera-Werke GmbH + +OUI:00080B* + ID_OUI_FROM_DATABASE=Birka BPA Informationssystem AB + +OUI:00080C* + ID_OUI_FROM_DATABASE=VDA Elettronica spa + +OUI:00080D* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:00080E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00080F* + ID_OUI_FROM_DATABASE=Proximion Fiber Optics AB + +OUI:000810* + ID_OUI_FROM_DATABASE=Key Technology, Inc. + +OUI:000811* + ID_OUI_FROM_DATABASE=VOIX Corporation + +OUI:000812* + ID_OUI_FROM_DATABASE=GM-2 Corporation + +OUI:000813* + ID_OUI_FROM_DATABASE=Diskbank, Inc. + +OUI:000814* + ID_OUI_FROM_DATABASE=TIL Technologies + +OUI:000815* + ID_OUI_FROM_DATABASE=CATS Co., Ltd. + +OUI:000816* + ID_OUI_FROM_DATABASE=Bluelon ApS + +OUI:000817* + ID_OUI_FROM_DATABASE=EmergeCore Networks LLC + +OUI:000818* + ID_OUI_FROM_DATABASE=Pixelworks, Inc. + +OUI:000819* + ID_OUI_FROM_DATABASE=Banksys + +OUI:00081A* + ID_OUI_FROM_DATABASE=Sanrad Intelligence Storage Communications (2000) Ltd. + +OUI:00081B* + ID_OUI_FROM_DATABASE=Windigo Systems + +OUI:00081C* + ID_OUI_FROM_DATABASE=@pos.com + +OUI:00081D* + ID_OUI_FROM_DATABASE=Ipsil, Incorporated + +OUI:00081E* + ID_OUI_FROM_DATABASE=Repeatit AB + +OUI:00081F* + ID_OUI_FROM_DATABASE=Pou Yuen Tech Corp. Ltd. + +OUI:000820* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000821* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000822* + ID_OUI_FROM_DATABASE=InPro Comm + +OUI:000823* + ID_OUI_FROM_DATABASE=Texa Corp. + +OUI:000824* + ID_OUI_FROM_DATABASE=Nuance Document Imaging + +OUI:000825* + ID_OUI_FROM_DATABASE=Acme Packet + +OUI:000826* + ID_OUI_FROM_DATABASE=Colorado Med Tech + +OUI:000827* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:000828* + ID_OUI_FROM_DATABASE=Koei Engineering Ltd. + +OUI:000829* + ID_OUI_FROM_DATABASE=TOKYO ELECTRON DEVICE NAGASAKI LIMITED + +OUI:00082A* + ID_OUI_FROM_DATABASE=Powerwallz Network Security + +OUI:00082B* + ID_OUI_FROM_DATABASE=Wooksung Electronics, Inc. + +OUI:00082C* + ID_OUI_FROM_DATABASE=Homag AG + +OUI:00082D* + ID_OUI_FROM_DATABASE=Indus Teqsite Private Limited + +OUI:00082E* + ID_OUI_FROM_DATABASE=Multitone Electronics PLC + +OUI:00082F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000830* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000831* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000832* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00084E* + ID_OUI_FROM_DATABASE=DivergeNet, Inc. + +OUI:00084F* + ID_OUI_FROM_DATABASE=Qualstar Corporation + +OUI:000850* + ID_OUI_FROM_DATABASE=Arizona Instrument Corp. + +OUI:000851* + ID_OUI_FROM_DATABASE=Canadian Bank Note Company, Ltd. + +OUI:000852* + ID_OUI_FROM_DATABASE=Davolink Co. Inc. + +OUI:000853* + ID_OUI_FROM_DATABASE=Schleicher GmbH & Co. Relaiswerke KG + +OUI:000854* + ID_OUI_FROM_DATABASE=Netronix, Inc. + +OUI:000855* + ID_OUI_FROM_DATABASE=NASA-Goddard Space Flight Center + +OUI:000856* + ID_OUI_FROM_DATABASE=Gamatronic Electronic Industries Ltd. + +OUI:000857* + ID_OUI_FROM_DATABASE=Polaris Networks, Inc. + +OUI:000858* + ID_OUI_FROM_DATABASE=Novatechnology Inc. + +OUI:000859* + ID_OUI_FROM_DATABASE=ShenZhen Unitone Electronics Co., Ltd. + +OUI:00085A* + ID_OUI_FROM_DATABASE=IntiGate Inc. + +OUI:00085B* + ID_OUI_FROM_DATABASE=Hanbit Electronics Co., Ltd. + +OUI:00085C* + ID_OUI_FROM_DATABASE=Shanghai Dare Technologies Co. Ltd. + +OUI:00085D* + ID_OUI_FROM_DATABASE=Mitel Corporation + +OUI:00085E* + ID_OUI_FROM_DATABASE=PCO AG + +OUI:00085F* + ID_OUI_FROM_DATABASE=Picanol N.V. + +OUI:000860* + ID_OUI_FROM_DATABASE=LodgeNet Entertainment Corp. + +OUI:000861* + ID_OUI_FROM_DATABASE=SoftEnergy Co., Ltd. + +OUI:000862* + ID_OUI_FROM_DATABASE=NEC Eluminant Technologies, Inc. + +OUI:000863* + ID_OUI_FROM_DATABASE=Entrisphere Inc. + +OUI:000864* + ID_OUI_FROM_DATABASE=Fasy S.p.A. + +OUI:000865* + ID_OUI_FROM_DATABASE=JASCOM CO., LTD + +OUI:000866* + ID_OUI_FROM_DATABASE=DSX Access Systems, Inc. + +OUI:000867* + ID_OUI_FROM_DATABASE=Uptime Devices + +OUI:000868* + ID_OUI_FROM_DATABASE=PurOptix + +OUI:000869* + ID_OUI_FROM_DATABASE=Command-e Technology Co.,Ltd. + +OUI:00086A* + ID_OUI_FROM_DATABASE=Securiton Gmbh + +OUI:00086B* + ID_OUI_FROM_DATABASE=MIPSYS + +OUI:00086C* + ID_OUI_FROM_DATABASE=Plasmon LMS + +OUI:00086D* + ID_OUI_FROM_DATABASE=Missouri FreeNet + +OUI:00086E* + ID_OUI_FROM_DATABASE=Hyglo AB + +OUI:00086F* + ID_OUI_FROM_DATABASE=Resources Computer Network Ltd. + +OUI:000870* + ID_OUI_FROM_DATABASE=Rasvia Systems, Inc. + +OUI:000871* + ID_OUI_FROM_DATABASE=NORTHDATA Co., Ltd. + +OUI:000872* + ID_OUI_FROM_DATABASE=Sorenson Communications + +OUI:000873* + ID_OUI_FROM_DATABASE=DapTechnology B.V. + +OUI:000874* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:000875* + ID_OUI_FROM_DATABASE=Acorp Electronics Corp. + +OUI:000876* + ID_OUI_FROM_DATABASE=SDSystem + +OUI:000877* + ID_OUI_FROM_DATABASE=Liebert-Hiross Spa + +OUI:000878* + ID_OUI_FROM_DATABASE=Benchmark Storage Innovations + +OUI:000879* + ID_OUI_FROM_DATABASE=CEM Corporation + +OUI:00087A* + ID_OUI_FROM_DATABASE=Wipotec GmbH + +OUI:00087B* + ID_OUI_FROM_DATABASE=RTX Telecom A/S + +OUI:00087C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00087D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00087E* + ID_OUI_FROM_DATABASE=Bon Electro-Telecom Inc. + +OUI:00087F* + ID_OUI_FROM_DATABASE=SPAUN electronic GmbH & Co. KG + +OUI:000880* + ID_OUI_FROM_DATABASE=BroadTel Canada Communications inc. + +OUI:000881* + ID_OUI_FROM_DATABASE=DIGITAL HANDS CO.,LTD. + +OUI:000882* + ID_OUI_FROM_DATABASE=SIGMA CORPORATION + +OUI:000883* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:000884* + ID_OUI_FROM_DATABASE=Index Braille AB + +OUI:000885* + ID_OUI_FROM_DATABASE=EMS Dr. Thomas Wünsche + +OUI:000886* + ID_OUI_FROM_DATABASE=Hansung Teliann, Inc. + +OUI:000887* + ID_OUI_FROM_DATABASE=Maschinenfabrik Reinhausen GmbH + +OUI:000888* + ID_OUI_FROM_DATABASE=OULLIM Information Technology Inc,. + +OUI:000889* + ID_OUI_FROM_DATABASE=Dish Technologies Corp + +OUI:00088A* + ID_OUI_FROM_DATABASE=Minds@Work + +OUI:00088B* + ID_OUI_FROM_DATABASE=Tropic Networks Inc. + +OUI:00088C* + ID_OUI_FROM_DATABASE=Quanta Network Systems Inc. + +OUI:00088D* + ID_OUI_FROM_DATABASE=Sigma-Links Inc. + +OUI:00088E* + ID_OUI_FROM_DATABASE=Nihon Computer Co., Ltd. + +OUI:00088F* + ID_OUI_FROM_DATABASE=ADVANCED DIGITAL TECHNOLOGY + +OUI:000890* + ID_OUI_FROM_DATABASE=AVILINKS SA + +OUI:000891* + ID_OUI_FROM_DATABASE=Lyan Inc. + +OUI:000892* + ID_OUI_FROM_DATABASE=EM Solutions + +OUI:000893* + ID_OUI_FROM_DATABASE=LE INFORMATION COMMUNICATION INC. + +OUI:000894* + ID_OUI_FROM_DATABASE=InnoVISION Multimedia Ltd. + +OUI:000895* + ID_OUI_FROM_DATABASE=DIRC Technologie GmbH & Co.KG + +OUI:000896* + ID_OUI_FROM_DATABASE=Printronix, Inc. + +OUI:000897* + ID_OUI_FROM_DATABASE=Quake Technologies + +OUI:000898* + ID_OUI_FROM_DATABASE=Gigabit Optics Corporation + +OUI:000899* + ID_OUI_FROM_DATABASE=Netbind, Inc. + +OUI:00089A* + ID_OUI_FROM_DATABASE=Alcatel Microelectronics + +OUI:00089B* + ID_OUI_FROM_DATABASE=ICP Electronics Inc. + +OUI:00089C* + ID_OUI_FROM_DATABASE=Elecs Industry Co., Ltd. + +OUI:00089D* + ID_OUI_FROM_DATABASE=UHD-Elektronik + +OUI:00089E* + ID_OUI_FROM_DATABASE=Beijing Enter-Net co.LTD + +OUI:00089F* + ID_OUI_FROM_DATABASE=EFM Networks + +OUI:0008A0* + ID_OUI_FROM_DATABASE=Stotz Feinmesstechnik GmbH + +OUI:0008A1* + ID_OUI_FROM_DATABASE=CNet Technology Inc. + +OUI:0008A2* + ID_OUI_FROM_DATABASE=ADI Engineering, Inc. + +OUI:0008A3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0008A4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0008A5* + ID_OUI_FROM_DATABASE=Peninsula Systems Inc. + +OUI:0008A6* + ID_OUI_FROM_DATABASE=Multiware & Image Co., Ltd. + +OUI:0008A7* + ID_OUI_FROM_DATABASE=iLogic Inc. + +OUI:0008A8* + ID_OUI_FROM_DATABASE=Systec Co., Ltd. + +OUI:0008A9* + ID_OUI_FROM_DATABASE=SangSang Technology, Inc. + +OUI:0008AA* + ID_OUI_FROM_DATABASE=KARAM + +OUI:0008AB* + ID_OUI_FROM_DATABASE=EnerLinx.com, Inc. + +OUI:0008AC* + ID_OUI_FROM_DATABASE=Eltromat GmbH + +OUI:0008AD* + ID_OUI_FROM_DATABASE=Toyo-Linx Co., Ltd. + +OUI:0008AE* + ID_OUI_FROM_DATABASE=PacketFront Network Products AB + +OUI:0008AF* + ID_OUI_FROM_DATABASE=Novatec Corporation + +OUI:0008B0* + ID_OUI_FROM_DATABASE=BKtel communications GmbH + +OUI:0008B1* + ID_OUI_FROM_DATABASE=ProQuent Systems + +OUI:0008B2* + ID_OUI_FROM_DATABASE=SHENZHEN COMPASS TECHNOLOGY DEVELOPMENT CO.,LTD + +OUI:0008B3* + ID_OUI_FROM_DATABASE=Fastwel + +OUI:0008B4* + ID_OUI_FROM_DATABASE=SYSPOL + +OUI:0008B5* + ID_OUI_FROM_DATABASE=TAI GUEN ENTERPRISE CO., LTD + +OUI:0008B6* + ID_OUI_FROM_DATABASE=RouteFree, Inc. + +OUI:0008B7* + ID_OUI_FROM_DATABASE=HIT Incorporated + +OUI:0008B8* + ID_OUI_FROM_DATABASE=E.F. Johnson + +OUI:0008B9* + ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD. + +OUI:0008BA* + ID_OUI_FROM_DATABASE=Erskine Systems Ltd + +OUI:0008BB* + ID_OUI_FROM_DATABASE=NetExcell + +OUI:0008BC* + ID_OUI_FROM_DATABASE=Ilevo AB + +OUI:0008BD* + ID_OUI_FROM_DATABASE=TEPG-US + +OUI:0008BE* + ID_OUI_FROM_DATABASE=XENPAK MSA Group + +OUI:0008BF* + ID_OUI_FROM_DATABASE=Aptus Elektronik AB + +OUI:0008C0* + ID_OUI_FROM_DATABASE=ASA SYSTEMS + +OUI:0008C1* + ID_OUI_FROM_DATABASE=Avistar Communications Corporation + +OUI:0008C2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0008C3* + ID_OUI_FROM_DATABASE=Contex A/S + +OUI:0008C4* + ID_OUI_FROM_DATABASE=Hikari Co.,Ltd. + +OUI:0008C5* + ID_OUI_FROM_DATABASE=Liontech Co., Ltd. + +OUI:0008C6* + ID_OUI_FROM_DATABASE=Philips Consumer Communications + +OUI:0008C7* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0008C8* + ID_OUI_FROM_DATABASE=Soneticom, Inc. + +OUI:0008C9* + ID_OUI_FROM_DATABASE=TechniSat Digital GmbH Daun + +OUI:0008CA* + ID_OUI_FROM_DATABASE=TwinHan Technology Co.,Ltd + +OUI:0008CB* + ID_OUI_FROM_DATABASE=Zeta Broadband Inc. + +OUI:0008CC* + ID_OUI_FROM_DATABASE=Remotec, Inc. + +OUI:0008CD* + ID_OUI_FROM_DATABASE=With-Net Inc + +OUI:0008CE* + ID_OUI_FROM_DATABASE=IPMobileNet Inc. + +OUI:0008CF* + ID_OUI_FROM_DATABASE=Nippon Koei Power Systems Co., Ltd. + +OUI:0008D0* + ID_OUI_FROM_DATABASE=Musashi Engineering Co., LTD. + +OUI:0008D1* + ID_OUI_FROM_DATABASE=KAREL INC. + +OUI:0008D2* + ID_OUI_FROM_DATABASE=ZOOM Networks Inc. + +OUI:0008D3* + ID_OUI_FROM_DATABASE=Hercules Technologies S.A.S. + +OUI:0008D4* + ID_OUI_FROM_DATABASE=IneoQuest Technologies, Inc + +OUI:0008D5* + ID_OUI_FROM_DATABASE=Vanguard Networks Solutions, LLC + +OUI:0008D6* + ID_OUI_FROM_DATABASE=HASSNET Inc. + +OUI:0008D7* + ID_OUI_FROM_DATABASE=HOW CORPORATION + +OUI:0008D8* + ID_OUI_FROM_DATABASE=Dowkey Microwave + +OUI:0008D9* + ID_OUI_FROM_DATABASE=Mitadenshi Co.,LTD + +OUI:0008DA* + ID_OUI_FROM_DATABASE=SofaWare Technologies Ltd. + +OUI:0008DB* + ID_OUI_FROM_DATABASE=Corrigent Systems + +OUI:0008DC* + ID_OUI_FROM_DATABASE=Wiznet + +OUI:0008DD* + ID_OUI_FROM_DATABASE=Telena Communications, Inc. + +OUI:0008DE* + ID_OUI_FROM_DATABASE=3UP Systems + +OUI:0008DF* + ID_OUI_FROM_DATABASE=Alistel Inc. + +OUI:0008E0* + ID_OUI_FROM_DATABASE=ATO Technology Ltd. + +OUI:0008E1* + ID_OUI_FROM_DATABASE=Barix AG + +OUI:0008E2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0008E3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0008E4* + ID_OUI_FROM_DATABASE=Envenergy Inc + +OUI:0008E5* + ID_OUI_FROM_DATABASE=IDK Corporation + +OUI:0008E6* + ID_OUI_FROM_DATABASE=Littlefeet + +OUI:0008E7* + ID_OUI_FROM_DATABASE=SHI ControlSystems,Ltd. + +OUI:0008E8* + ID_OUI_FROM_DATABASE=Excel Master Ltd. + +OUI:0008E9* + ID_OUI_FROM_DATABASE=NextGig + +OUI:0008EA* + ID_OUI_FROM_DATABASE=Motion Control Engineering, Inc + +OUI:0008EB* + ID_OUI_FROM_DATABASE=ROMWin Co.,Ltd. + +OUI:0008EC* + ID_OUI_FROM_DATABASE=Optical Zonu Corporation + +OUI:0008ED* + ID_OUI_FROM_DATABASE=ST&T Instrument Corp. + +OUI:0008EE* + ID_OUI_FROM_DATABASE=Logic Product Development + +OUI:0008EF* + ID_OUI_FROM_DATABASE=DIBAL,S.A. + +OUI:0008F0* + ID_OUI_FROM_DATABASE=Next Generation Systems, Inc. + +OUI:0008F1* + ID_OUI_FROM_DATABASE=Voltaire + +OUI:0008F2* + ID_OUI_FROM_DATABASE=C&S Technology + +OUI:0008F3* + ID_OUI_FROM_DATABASE=WANY + +OUI:0008F4* + ID_OUI_FROM_DATABASE=Bluetake Technology Co., Ltd. + +OUI:0008F5* + ID_OUI_FROM_DATABASE=YESTECHNOLOGY Co.,Ltd. + +OUI:0008F6* + ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd + +OUI:0008F7* + ID_OUI_FROM_DATABASE=Hitachi Ltd, Semiconductor & Integrated Circuits Gr + +OUI:0008F8* + ID_OUI_FROM_DATABASE=UTC CCS + +OUI:0008F9* + ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies + +OUI:0008FA* + ID_OUI_FROM_DATABASE=KEB Automation KG + +OUI:0008FB* + ID_OUI_FROM_DATABASE=SonoSite, Inc. + +OUI:0008FC* + ID_OUI_FROM_DATABASE=Gigaphoton Inc. + +OUI:0008FD* + ID_OUI_FROM_DATABASE=BlueKorea Co., Ltd. + +OUI:0008FE* + ID_OUI_FROM_DATABASE=UNIK C&C Co.,Ltd. + +OUI:0008FF* + ID_OUI_FROM_DATABASE=Trilogy Communications Ltd + +OUI:000900* + ID_OUI_FROM_DATABASE=TMT + +OUI:000901* + ID_OUI_FROM_DATABASE=Shenzhen Shixuntong Information & Technoligy Co + +OUI:000902* + ID_OUI_FROM_DATABASE=Redline Communications Inc. + +OUI:000903* + ID_OUI_FROM_DATABASE=Panasas, Inc + +OUI:000904* + ID_OUI_FROM_DATABASE=MONDIAL electronic + +OUI:000905* + ID_OUI_FROM_DATABASE=iTEC Technologies Ltd. + +OUI:000906* + ID_OUI_FROM_DATABASE=Esteem Networks + +OUI:000907* + ID_OUI_FROM_DATABASE=Chrysalis Development + +OUI:000908* + ID_OUI_FROM_DATABASE=VTech Technology Corp. + +OUI:000909* + ID_OUI_FROM_DATABASE=Telenor Connect A/S + +OUI:00090A* + ID_OUI_FROM_DATABASE=SnedFar Technology Co., Ltd. + +OUI:00090B* + ID_OUI_FROM_DATABASE=MTL Instruments PLC + +OUI:00090C* + ID_OUI_FROM_DATABASE=Mayekawa Mfg. Co. Ltd. + +OUI:00090D* + ID_OUI_FROM_DATABASE=LEADER ELECTRONICS CORP. + +OUI:00090E* + ID_OUI_FROM_DATABASE=Helix Technology Inc. + +OUI:00090F* + ID_OUI_FROM_DATABASE=Fortinet Inc. + +OUI:000910* + ID_OUI_FROM_DATABASE=Simple Access Inc. + +OUI:000911* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000912* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000913* + ID_OUI_FROM_DATABASE=SystemK Corporation + +OUI:000914* + ID_OUI_FROM_DATABASE=COMPUTROLS INC. + +OUI:000915* + ID_OUI_FROM_DATABASE=CAS Corp. + +OUI:000916* + ID_OUI_FROM_DATABASE=Listman Home Technologies, Inc. + +OUI:000917* + ID_OUI_FROM_DATABASE=WEM Technology Inc + +OUI:000918* + ID_OUI_FROM_DATABASE=SAMSUNG TECHWIN CO.,LTD + +OUI:000919* + ID_OUI_FROM_DATABASE=MDS Gateways + +OUI:00091A* + ID_OUI_FROM_DATABASE=Macat Optics & Electronics Co., Ltd. + +OUI:00091B* + ID_OUI_FROM_DATABASE=Digital Generation Inc. + +OUI:00091C* + ID_OUI_FROM_DATABASE=CacheVision, Inc + +OUI:00091D* + ID_OUI_FROM_DATABASE=Proteam Computer Corporation + +OUI:00091E* + ID_OUI_FROM_DATABASE=Firstech Technology Corp. + +OUI:00091F* + ID_OUI_FROM_DATABASE=A&D Co., Ltd. + +OUI:000920* + ID_OUI_FROM_DATABASE=EpoX COMPUTER CO.,LTD. + +OUI:000921* + ID_OUI_FROM_DATABASE=Planmeca Oy + +OUI:000922* + ID_OUI_FROM_DATABASE=TST Biometrics GmbH + +OUI:000923* + ID_OUI_FROM_DATABASE=Heaman System Co., Ltd + +OUI:000924* + ID_OUI_FROM_DATABASE=Telebau GmbH + +OUI:000925* + ID_OUI_FROM_DATABASE=VSN Systemen BV + +OUI:000926* + ID_OUI_FROM_DATABASE=YODA COMMUNICATIONS, INC. + +OUI:000927* + ID_OUI_FROM_DATABASE=TOYOKEIKI CO.,LTD. + +OUI:000928* + ID_OUI_FROM_DATABASE=Telecore + +OUI:000929* + ID_OUI_FROM_DATABASE=Sanyo Industries (UK) Limited + +OUI:00092A* + ID_OUI_FROM_DATABASE=MYTECS Co.,Ltd. + +OUI:00092B* + ID_OUI_FROM_DATABASE=iQstor Networks, Inc. + +OUI:00092C* + ID_OUI_FROM_DATABASE=Hitpoint Inc. + +OUI:00092D* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:00092E* + ID_OUI_FROM_DATABASE=B&Tech System Inc. + +OUI:00092F* + ID_OUI_FROM_DATABASE=Akom Technology Corporation + +OUI:000930* + ID_OUI_FROM_DATABASE=AeroConcierge Inc. + +OUI:000931* + ID_OUI_FROM_DATABASE=Future Internet, Inc. + +OUI:000932* + ID_OUI_FROM_DATABASE=Omnilux + +OUI:000933* + ID_OUI_FROM_DATABASE=Ophit Co.Ltd. + +OUI:000934* + ID_OUI_FROM_DATABASE=Dream-Multimedia-Tv GmbH + +OUI:000935* + ID_OUI_FROM_DATABASE=Sandvine Incorporated + +OUI:000936* + ID_OUI_FROM_DATABASE=Ipetronik GmbH & Co. KG + +OUI:000937* + ID_OUI_FROM_DATABASE=Inventec Appliance Corp + +OUI:000938* + ID_OUI_FROM_DATABASE=Allot Communications + +OUI:000939* + ID_OUI_FROM_DATABASE=ShibaSoku Co.,Ltd. + +OUI:00093A* + ID_OUI_FROM_DATABASE=Molex CMS + +OUI:00093B* + ID_OUI_FROM_DATABASE=HYUNDAI NETWORKS INC. + +OUI:00093C* + ID_OUI_FROM_DATABASE=Jacques Technologies P/L + +OUI:00093D* + ID_OUI_FROM_DATABASE=Newisys,Inc. + +OUI:00093E* + ID_OUI_FROM_DATABASE=C&I Technologies + +OUI:00093F* + ID_OUI_FROM_DATABASE=Double-Win Enterpirse CO., LTD + +OUI:000940* + ID_OUI_FROM_DATABASE=AGFEO GmbH & Co. KG + +OUI:000941* + ID_OUI_FROM_DATABASE=Allied Telesis R&D Center K.K. + +OUI:000942* + ID_OUI_FROM_DATABASE=Wireless Technologies, Inc + +OUI:000943* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000944* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000945* + ID_OUI_FROM_DATABASE=Palmmicro Communications Inc + +OUI:000946* + ID_OUI_FROM_DATABASE=Cluster Labs GmbH + +OUI:000947* + ID_OUI_FROM_DATABASE=Aztek, Inc. + +OUI:000948* + ID_OUI_FROM_DATABASE=Vista Control Systems, Corp. + +OUI:000949* + ID_OUI_FROM_DATABASE=Glyph Technologies Inc. + +OUI:00094A* + ID_OUI_FROM_DATABASE=Homenet Communications + +OUI:00094B* + ID_OUI_FROM_DATABASE=FillFactory NV + +OUI:00094C* + ID_OUI_FROM_DATABASE=Communication Weaver Co.,Ltd. + +OUI:00094D* + ID_OUI_FROM_DATABASE=Braintree Communications Pty Ltd + +OUI:00094E* + ID_OUI_FROM_DATABASE=BARTECH SYSTEMS INTERNATIONAL, INC + +OUI:00094F* + ID_OUI_FROM_DATABASE=elmegt GmbH & Co. KG + +OUI:000950* + ID_OUI_FROM_DATABASE=Independent Storage Corporation + +OUI:000951* + ID_OUI_FROM_DATABASE=Apogee Imaging Systems + +OUI:000952* + ID_OUI_FROM_DATABASE=Auerswald GmbH & Co. KG + +OUI:000953* + ID_OUI_FROM_DATABASE=Linkage System Integration Co.Ltd. + +OUI:000954* + ID_OUI_FROM_DATABASE=AMiT spol. s. r. o. + +OUI:000955* + ID_OUI_FROM_DATABASE=Young Generation International Corp. + +OUI:000956* + ID_OUI_FROM_DATABASE=Network Systems Group, Ltd. (NSG) + +OUI:000957* + ID_OUI_FROM_DATABASE=Supercaller, Inc. + +OUI:000958* + ID_OUI_FROM_DATABASE=INTELNET S.A. + +OUI:000959* + ID_OUI_FROM_DATABASE=Sitecsoft + +OUI:00095A* + ID_OUI_FROM_DATABASE=RACEWOOD TECHNOLOGY + +OUI:00095B* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:00095C* + ID_OUI_FROM_DATABASE=Philips Medical Systems - Cardiac and Monitoring Systems (CM + +OUI:00095D* + ID_OUI_FROM_DATABASE=Dialogue Technology Corp. + +OUI:00095E* + ID_OUI_FROM_DATABASE=Masstech Group Inc. + +OUI:00095F* + ID_OUI_FROM_DATABASE=Telebyte, Inc. + +OUI:000960* + ID_OUI_FROM_DATABASE=YOZAN Inc. + +OUI:000961* + ID_OUI_FROM_DATABASE=Switchgear and Instrumentation Ltd + +OUI:000962* + ID_OUI_FROM_DATABASE=Sonitor Technologies AS + +OUI:000963* + ID_OUI_FROM_DATABASE=Dominion Lasercom Inc. + +OUI:000964* + ID_OUI_FROM_DATABASE=Hi-Techniques, Inc. + +OUI:000965* + ID_OUI_FROM_DATABASE=HyunJu Computer Co., Ltd. + +OUI:000966* + ID_OUI_FROM_DATABASE=TRIMBLE EUROPE BV + +OUI:000967* + ID_OUI_FROM_DATABASE=Tachyon, Inc + +OUI:000968* + ID_OUI_FROM_DATABASE=TECHNOVENTURE, INC. + +OUI:000969* + ID_OUI_FROM_DATABASE=Meret Optical Communications + +OUI:00096A* + ID_OUI_FROM_DATABASE=Cloverleaf Communications Inc. + +OUI:00096B* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:00096C* + ID_OUI_FROM_DATABASE=Imedia Semiconductor Corp. + +OUI:00096D* + ID_OUI_FROM_DATABASE=Powernet Technologies Corp. + +OUI:00096E* + ID_OUI_FROM_DATABASE=GIANT ELECTRONICS LTD. + +OUI:00096F* + ID_OUI_FROM_DATABASE=Beijing Zhongqing Elegant Tech. Corp.,Limited + +OUI:000970* + ID_OUI_FROM_DATABASE=Vibration Research Corporation + +OUI:000971* + ID_OUI_FROM_DATABASE=Time Management, Inc. + +OUI:000972* + ID_OUI_FROM_DATABASE=Securebase,Inc + +OUI:000973* + ID_OUI_FROM_DATABASE=Lenten Technology Co., Ltd. + +OUI:000974* + ID_OUI_FROM_DATABASE=Innopia Technologies, Inc. + +OUI:000975* + ID_OUI_FROM_DATABASE=fSONA Communications Corporation + +OUI:000976* + ID_OUI_FROM_DATABASE=Datasoft ISDN Systems GmbH + +OUI:000977* + ID_OUI_FROM_DATABASE=Brunner Elektronik AG + +OUI:000978* + ID_OUI_FROM_DATABASE=AIJI System Co., Ltd. + +OUI:000979* + ID_OUI_FROM_DATABASE=Advanced Television Systems Committee, Inc. + +OUI:00097A* + ID_OUI_FROM_DATABASE=Louis Design Labs. + +OUI:00097B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00097C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00097D* + ID_OUI_FROM_DATABASE=SecWell Networks Oy + +OUI:00097E* + ID_OUI_FROM_DATABASE=IMI TECHNOLOGY CO., LTD + +OUI:00097F* + ID_OUI_FROM_DATABASE=Vsecure 2000 LTD. + +OUI:000980* + ID_OUI_FROM_DATABASE=Power Zenith Inc. + +OUI:000981* + ID_OUI_FROM_DATABASE=Newport Networks + +OUI:000982* + ID_OUI_FROM_DATABASE=Loewe Opta GmbH + +OUI:000983* + ID_OUI_FROM_DATABASE=GlobalTop Technology, Inc. + +OUI:000984* + ID_OUI_FROM_DATABASE=MyCasa Network Inc. + +OUI:000985* + ID_OUI_FROM_DATABASE=Auto Telecom Company + +OUI:000986* + ID_OUI_FROM_DATABASE=Metalink LTD. + +OUI:000987* + ID_OUI_FROM_DATABASE=NISHI NIPPON ELECTRIC WIRE & CABLE CO.,LTD. + +OUI:000988* + ID_OUI_FROM_DATABASE=Nudian Electron Co., Ltd. + +OUI:000989* + ID_OUI_FROM_DATABASE=VividLogic Inc. + +OUI:00098A* + ID_OUI_FROM_DATABASE=EqualLogic Inc + +OUI:00098B* + ID_OUI_FROM_DATABASE=Entropic Communications, Inc. + +OUI:00098C* + ID_OUI_FROM_DATABASE=Option Wireless Sweden + +OUI:00098D* + ID_OUI_FROM_DATABASE=Velocity Semiconductor + +OUI:00098E* + ID_OUI_FROM_DATABASE=ipcas GmbH + +OUI:00098F* + ID_OUI_FROM_DATABASE=Cetacean Networks + +OUI:000990* + ID_OUI_FROM_DATABASE=ACKSYS Communications & systems + +OUI:000991* + ID_OUI_FROM_DATABASE=Intelligent Platforms, LLC. + +OUI:000992* + ID_OUI_FROM_DATABASE=InterEpoch Technology,INC. + +OUI:000993* + ID_OUI_FROM_DATABASE=Visteon Corporation + +OUI:000994* + ID_OUI_FROM_DATABASE=Cronyx Engineering + +OUI:000995* + ID_OUI_FROM_DATABASE=Castle Technology Ltd + +OUI:000996* + ID_OUI_FROM_DATABASE=RDI + +OUI:000997* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000998* + ID_OUI_FROM_DATABASE=Capinfo Company Limited + +OUI:000999* + ID_OUI_FROM_DATABASE=CP GEORGES RENAULT + +OUI:00099A* + ID_OUI_FROM_DATABASE=ELMO COMPANY, LIMITED + +OUI:00099B* + ID_OUI_FROM_DATABASE=Western Telematic Inc. + +OUI:00099C* + ID_OUI_FROM_DATABASE=Naval Research Laboratory + +OUI:00099D* + ID_OUI_FROM_DATABASE=Haliplex Communications + +OUI:00099E* + ID_OUI_FROM_DATABASE=Testech, Inc. + +OUI:00099F* + ID_OUI_FROM_DATABASE=VIDEX INC. + +OUI:0009A0* + ID_OUI_FROM_DATABASE=Microtechno Corporation + +OUI:0009A1* + ID_OUI_FROM_DATABASE=Telewise Communications, Inc. + +OUI:0009A2* + ID_OUI_FROM_DATABASE=Interface Co., Ltd. + +OUI:0009A3* + ID_OUI_FROM_DATABASE=Leadfly Techologies Corp. Ltd. + +OUI:0009A4* + ID_OUI_FROM_DATABASE=HARTEC Corporation + +OUI:0009A5* + ID_OUI_FROM_DATABASE=HANSUNG ELETRONIC INDUSTRIES DEVELOPMENT CO., LTD + +OUI:0009A6* + ID_OUI_FROM_DATABASE=Ignis Optics, Inc. + +OUI:0009A7* + ID_OUI_FROM_DATABASE=Bang & Olufsen A/S + +OUI:0009A8* + ID_OUI_FROM_DATABASE=Eastmode Pte Ltd + +OUI:0009A9* + ID_OUI_FROM_DATABASE=Ikanos Communications + +OUI:0009AA* + ID_OUI_FROM_DATABASE=Data Comm for Business, Inc. + +OUI:0009AB* + ID_OUI_FROM_DATABASE=Netcontrol Oy + +OUI:0009AC* + ID_OUI_FROM_DATABASE=LANVOICE + +OUI:0009AD* + ID_OUI_FROM_DATABASE=HYUNDAI SYSCOMM, INC. + +OUI:0009AE* + ID_OUI_FROM_DATABASE=OKANO ELECTRIC CO.,LTD + +OUI:0009AF* + ID_OUI_FROM_DATABASE=e-generis + +OUI:0009B0* + ID_OUI_FROM_DATABASE=Onkyo Corporation + +OUI:0009B1* + ID_OUI_FROM_DATABASE=Kanematsu Electronics, Ltd. + +OUI:0009B2* + ID_OUI_FROM_DATABASE=L&F Inc. + +OUI:0009B3* + ID_OUI_FROM_DATABASE=MCM Systems Ltd + +OUI:0009B4* + ID_OUI_FROM_DATABASE=KISAN TELECOM CO., LTD. + +OUI:0009B5* + ID_OUI_FROM_DATABASE=3J Tech. Co., Ltd. + +OUI:0009B6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0009B7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0009B8* + ID_OUI_FROM_DATABASE=Entise Systems + +OUI:0009B9* + ID_OUI_FROM_DATABASE=Action Imaging Solutions + +OUI:0009BA* + ID_OUI_FROM_DATABASE=MAKU Informationstechik GmbH + +OUI:0009BB* + ID_OUI_FROM_DATABASE=MathStar, Inc. + +OUI:0009BC* + ID_OUI_FROM_DATABASE=Utility, Inc + +OUI:0009BD* + ID_OUI_FROM_DATABASE=Epygi Technologies, Ltd. + +OUI:0009BE* + ID_OUI_FROM_DATABASE=Mamiya-OP Co.,Ltd. + +OUI:0009BF* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:0009C0* + ID_OUI_FROM_DATABASE=6WIND + +OUI:0009C1* + ID_OUI_FROM_DATABASE=PROCES-DATA A/S + +OUI:0009C2* + ID_OUI_FROM_DATABASE=Onity, Inc. + +OUI:0009C3* + ID_OUI_FROM_DATABASE=NETAS + +OUI:0009C4* + ID_OUI_FROM_DATABASE=Medicore Co., Ltd + +OUI:0009C5* + ID_OUI_FROM_DATABASE=KINGENE Technology Corporation + +OUI:0009C6* + ID_OUI_FROM_DATABASE=Visionics Corporation + +OUI:0009C7* + ID_OUI_FROM_DATABASE=Movistec + +OUI:0009C8* + ID_OUI_FROM_DATABASE=SINAGAWA TSUSHIN KEISOU SERVICE + +OUI:0009C9* + ID_OUI_FROM_DATABASE=BlueWINC Co., Ltd. + +OUI:0009CA* + ID_OUI_FROM_DATABASE=iMaxNetworks(Shenzhen)Limited. + +OUI:0009CB* + ID_OUI_FROM_DATABASE=HBrain + +OUI:0009CC* + ID_OUI_FROM_DATABASE=Moog GmbH + +OUI:0009CD* + ID_OUI_FROM_DATABASE=HUDSON SOFT CO.,LTD. + +OUI:0009CE* + ID_OUI_FROM_DATABASE=SpaceBridge Semiconductor Corp. + +OUI:0009CF* + ID_OUI_FROM_DATABASE=iAd GmbH + +OUI:0009D0* + ID_OUI_FROM_DATABASE=Solacom Technologies Inc. + +OUI:0009D1* + ID_OUI_FROM_DATABASE=SERANOA NETWORKS INC + +OUI:0009D2* + ID_OUI_FROM_DATABASE=Mai Logic Inc. + +OUI:0009D3* + ID_OUI_FROM_DATABASE=Western DataCom Co., Inc. + +OUI:0009D4* + ID_OUI_FROM_DATABASE=Transtech Networks + +OUI:0009D5* + ID_OUI_FROM_DATABASE=Signal Communication, Inc. + +OUI:0009D6* + ID_OUI_FROM_DATABASE=KNC One GmbH + +OUI:0009D7* + ID_OUI_FROM_DATABASE=DC Security Products + +OUI:0009D8* + ID_OUI_FROM_DATABASE=Fält Communications AB + +OUI:0009D9* + ID_OUI_FROM_DATABASE=Neoscale Systems, Inc + +OUI:0009DA* + ID_OUI_FROM_DATABASE=Control Module Inc. + +OUI:0009DB* + ID_OUI_FROM_DATABASE=eSpace + +OUI:0009DC* + ID_OUI_FROM_DATABASE=Galaxis Technology AG + +OUI:0009DD* + ID_OUI_FROM_DATABASE=Mavin Technology Inc. + +OUI:0009DE* + ID_OUI_FROM_DATABASE=Samjin Information & Communications Co., Ltd. + +OUI:0009DF* + ID_OUI_FROM_DATABASE=Vestel Elektronik San ve Tic. A.Ş. + +OUI:0009E0* + ID_OUI_FROM_DATABASE=XEMICS S.A. + +OUI:0009E1* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:0009E2* + ID_OUI_FROM_DATABASE=Sinbon Electronics Co., Ltd. + +OUI:0009E3* + ID_OUI_FROM_DATABASE=Angel Iglesias S.A. + +OUI:0009E4* + ID_OUI_FROM_DATABASE=K Tech Infosystem Inc. + +OUI:0009E5* + ID_OUI_FROM_DATABASE=Hottinger Baldwin Messtechnik GmbH + +OUI:0009E6* + ID_OUI_FROM_DATABASE=Cyber Switching Inc. + +OUI:0009E7* + ID_OUI_FROM_DATABASE=ADC Techonology + +OUI:0009E8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0009E9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0009EA* + ID_OUI_FROM_DATABASE=YEM Inc. + +OUI:0009EB* + ID_OUI_FROM_DATABASE=HuMANDATA LTD. + +OUI:0009EC* + ID_OUI_FROM_DATABASE=Daktronics, Inc. + +OUI:0009ED* + ID_OUI_FROM_DATABASE=CipherOptics + +OUI:0009EE* + ID_OUI_FROM_DATABASE=MEIKYO ELECTRIC CO.,LTD + +OUI:0009EF* + ID_OUI_FROM_DATABASE=Vocera Communications + +OUI:0009F0* + ID_OUI_FROM_DATABASE=Shimizu Technology Inc. + +OUI:0009F1* + ID_OUI_FROM_DATABASE=Yamaki Electric Corporation + +OUI:0009F2* + ID_OUI_FROM_DATABASE=Cohu, Inc., Electronics Division + +OUI:0009F3* + ID_OUI_FROM_DATABASE=WELL Communication Corp. + +OUI:0009F4* + ID_OUI_FROM_DATABASE=Alcon Laboratories, Inc. + +OUI:0009F5* + ID_OUI_FROM_DATABASE=Emerson Network Power Co.,Ltd + +OUI:0009F6* + ID_OUI_FROM_DATABASE=Shenzhen Eastern Digital Tech Ltd. + +OUI:0009F7* + ID_OUI_FROM_DATABASE=SED, a division of Calian + +OUI:0009F8* + ID_OUI_FROM_DATABASE=UNIMO TECHNOLOGY CO., LTD. + +OUI:0009F9* + ID_OUI_FROM_DATABASE=ART JAPAN CO., LTD. + +OUI:0009FB* + ID_OUI_FROM_DATABASE=Philips Patient Monitoring + +OUI:0009FC* + ID_OUI_FROM_DATABASE=IPFLEX Inc. + +OUI:0009FD* + ID_OUI_FROM_DATABASE=Ubinetics Limited + +OUI:0009FE* + ID_OUI_FROM_DATABASE=Daisy Technologies, Inc. + +OUI:0009FF* + ID_OUI_FROM_DATABASE=X.net 2000 GmbH + +OUI:000A00* + ID_OUI_FROM_DATABASE=Mediatek Corp. + +OUI:000A01* + ID_OUI_FROM_DATABASE=SOHOware, Inc. + +OUI:000A02* + ID_OUI_FROM_DATABASE=ANNSO CO., LTD. + +OUI:000A03* + ID_OUI_FROM_DATABASE=ENDESA SERVICIOS, S.L. + +OUI:000A04* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:000A05* + ID_OUI_FROM_DATABASE=Widax Corp. + +OUI:000A06* + ID_OUI_FROM_DATABASE=Teledex LLC + +OUI:000A07* + ID_OUI_FROM_DATABASE=WebWayOne Ltd + +OUI:000A08* + ID_OUI_FROM_DATABASE=Alpine Electronics, Inc. + +OUI:000A09* + ID_OUI_FROM_DATABASE=TaraCom Integrated Products, Inc. + +OUI:000A0A* + ID_OUI_FROM_DATABASE=SUNIX Co., Ltd. + +OUI:000A0B* + ID_OUI_FROM_DATABASE=Sealevel Systems, Inc. + +OUI:000A0C* + ID_OUI_FROM_DATABASE=Scientific Research Corporation + +OUI:000A0D* + ID_OUI_FROM_DATABASE=Amphenol + +OUI:000A0E* + ID_OUI_FROM_DATABASE=Invivo Research Inc. + +OUI:000A0F* + ID_OUI_FROM_DATABASE=Ilryung Telesys, Inc + +OUI:000A10* + ID_OUI_FROM_DATABASE=FAST media integrations AG + +OUI:000A11* + ID_OUI_FROM_DATABASE=ExPet Technologies, Inc + +OUI:000A12* + ID_OUI_FROM_DATABASE=Azylex Technology, Inc + +OUI:000A13* + ID_OUI_FROM_DATABASE=Honeywell Video Systems + +OUI:000A14* + ID_OUI_FROM_DATABASE=TECO a.s. + +OUI:000A15* + ID_OUI_FROM_DATABASE=Silicon Data, Inc + +OUI:000A16* + ID_OUI_FROM_DATABASE=Lassen Research + +OUI:000A17* + ID_OUI_FROM_DATABASE=NESTAR COMMUNICATIONS, INC + +OUI:000A18* + ID_OUI_FROM_DATABASE=Vichel Inc. + +OUI:000A19* + ID_OUI_FROM_DATABASE=Valere Power, Inc. + +OUI:000A1A* + ID_OUI_FROM_DATABASE=Imerge Ltd + +OUI:000A1B* + ID_OUI_FROM_DATABASE=Stream Labs + +OUI:000A1C* + ID_OUI_FROM_DATABASE=Bridge Information Co., Ltd. + +OUI:000A1D* + ID_OUI_FROM_DATABASE=Optical Communications Products Inc. + +OUI:000A1E* + ID_OUI_FROM_DATABASE=Red-M Products Limited + +OUI:000A1F* + ID_OUI_FROM_DATABASE=ART WARE Telecommunication Co., Ltd. + +OUI:000A20* + ID_OUI_FROM_DATABASE=SVA Networks, Inc. + +OUI:000A21* + ID_OUI_FROM_DATABASE=Integra Telecom Co. Ltd + +OUI:000A22* + ID_OUI_FROM_DATABASE=Amperion Inc + +OUI:000A23* + ID_OUI_FROM_DATABASE=Parama Networks Inc + +OUI:000A24* + ID_OUI_FROM_DATABASE=Octave Communications + +OUI:000A25* + ID_OUI_FROM_DATABASE=CERAGON NETWORKS + +OUI:000A26* + ID_OUI_FROM_DATABASE=CEIA S.p.A. + +OUI:000A27* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:000A28* + ID_OUI_FROM_DATABASE=Motorola + +OUI:000A29* + ID_OUI_FROM_DATABASE=Pan Dacom Networking AG + +OUI:000A2A* + ID_OUI_FROM_DATABASE=QSI Systems Inc. + +OUI:000A2B* + ID_OUI_FROM_DATABASE=Etherstuff + +OUI:000A2C* + ID_OUI_FROM_DATABASE=Active Tchnology Corporation + +OUI:000A2D* + ID_OUI_FROM_DATABASE=Cabot Communications Limited + +OUI:000A2E* + ID_OUI_FROM_DATABASE=MAPLE NETWORKS CO., LTD + +OUI:000A2F* + ID_OUI_FROM_DATABASE=Artnix Inc. + +OUI:000A30* + ID_OUI_FROM_DATABASE=Visteon Corporation + +OUI:000A31* + ID_OUI_FROM_DATABASE=HCV Consulting + +OUI:000A32* + ID_OUI_FROM_DATABASE=Xsido Corporation + +OUI:000A33* + ID_OUI_FROM_DATABASE=Emulex Corporation + +OUI:000A34* + ID_OUI_FROM_DATABASE=Identicard Systems Incorporated + +OUI:000A35* + ID_OUI_FROM_DATABASE=Xilinx + +OUI:000A36* + ID_OUI_FROM_DATABASE=Synelec Telecom Multimedia + +OUI:000A37* + ID_OUI_FROM_DATABASE=Procera Networks, Inc. + +OUI:000A38* + ID_OUI_FROM_DATABASE=Apani Networks + +OUI:000A39* + ID_OUI_FROM_DATABASE=LoPA Information Technology + +OUI:000A3A* + ID_OUI_FROM_DATABASE=J-THREE INTERNATIONAL Holding Co., Ltd. + +OUI:000A3B* + ID_OUI_FROM_DATABASE=GCT Semiconductor, Inc + +OUI:000A3C* + ID_OUI_FROM_DATABASE=Enerpoint Ltd. + +OUI:000A3D* + ID_OUI_FROM_DATABASE=Elo Sistemas Eletronicos S.A. + +OUI:000A3E* + ID_OUI_FROM_DATABASE=EADS Telecom + +OUI:000A3F* + ID_OUI_FROM_DATABASE=Data East Corporation + +OUI:000A40* + ID_OUI_FROM_DATABASE=Crown Audio -- Harmanm International + +OUI:000A41* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000A42* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000A43* + ID_OUI_FROM_DATABASE=Chunghwa Telecom Co., Ltd. + +OUI:000A44* + ID_OUI_FROM_DATABASE=Avery Dennison Deutschland GmbH + +OUI:000A45* + ID_OUI_FROM_DATABASE=Audio-Technica Corp. + +OUI:000A46* + ID_OUI_FROM_DATABASE=ARO WELDING TECHNOLOGIES SAS + +OUI:000A47* + ID_OUI_FROM_DATABASE=Allied Vision Technologies + +OUI:000A48* + ID_OUI_FROM_DATABASE=Albatron Technology + +OUI:000A49* + ID_OUI_FROM_DATABASE=F5 Networks, Inc. + +OUI:000A4A* + ID_OUI_FROM_DATABASE=Targa Systems Ltd. + +OUI:000A4B* + ID_OUI_FROM_DATABASE=DataPower Technology, Inc. + +OUI:000A4C* + ID_OUI_FROM_DATABASE=Molecular Devices Corporation + +OUI:000A4D* + ID_OUI_FROM_DATABASE=Noritz Corporation + +OUI:000A4E* + ID_OUI_FROM_DATABASE=UNITEK Electronics INC. + +OUI:000A4F* + ID_OUI_FROM_DATABASE=Brain Boxes Limited + +OUI:000A50* + ID_OUI_FROM_DATABASE=REMOTEK CORPORATION + +OUI:000A51* + ID_OUI_FROM_DATABASE=GyroSignal Technology Co., Ltd. + +OUI:000A52* + ID_OUI_FROM_DATABASE=AsiaRF Ltd. + +OUI:000A53* + ID_OUI_FROM_DATABASE=Intronics, Incorporated + +OUI:000A54* + ID_OUI_FROM_DATABASE=Laguna Hills, Inc. + +OUI:000A55* + ID_OUI_FROM_DATABASE=MARKEM Corporation + +OUI:000A56* + ID_OUI_FROM_DATABASE=HITACHI Maxell Ltd. + +OUI:000A57* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:000A58* + ID_OUI_FROM_DATABASE=Freyer & Siegel Elektronik GmbH & Co. KG + +OUI:000A59* + ID_OUI_FROM_DATABASE=HW server + +OUI:000A5A* + ID_OUI_FROM_DATABASE=GreenNET Technologies Co.,Ltd. + +OUI:000A5B* + ID_OUI_FROM_DATABASE=Power-One as + +OUI:000A5C* + ID_OUI_FROM_DATABASE=Carel s.p.a. + +OUI:000A5D* + ID_OUI_FROM_DATABASE=FingerTec Worldwide Sdn Bhd + +OUI:000A5E* + ID_OUI_FROM_DATABASE=3COM + +OUI:000A5F* + ID_OUI_FROM_DATABASE=almedio inc. + +OUI:000A60* + ID_OUI_FROM_DATABASE=Autostar Technology Pte Ltd + +OUI:000A61* + ID_OUI_FROM_DATABASE=Cellinx Systems Inc. + +OUI:000A62* + ID_OUI_FROM_DATABASE=Crinis Networks, Inc. + +OUI:000A63* + ID_OUI_FROM_DATABASE=DHD GmbH + +OUI:000A64* + ID_OUI_FROM_DATABASE=Eracom Technologies + +OUI:000A65* + ID_OUI_FROM_DATABASE=GentechMedia.co.,ltd. + +OUI:000A66* + ID_OUI_FROM_DATABASE=MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD. + +OUI:000A67* + ID_OUI_FROM_DATABASE=OngCorp + +OUI:000A68* + ID_OUI_FROM_DATABASE=Solarflare Communications Inc. + +OUI:000A69* + ID_OUI_FROM_DATABASE=SUNNY bell Technology Co., Ltd. + +OUI:000A6A* + ID_OUI_FROM_DATABASE=SVM Microwaves s.r.o. + +OUI:000A6B* + ID_OUI_FROM_DATABASE=Tadiran Telecom Business Systems LTD + +OUI:000A6C* + ID_OUI_FROM_DATABASE=Walchem Corporation + +OUI:000A6D* + ID_OUI_FROM_DATABASE=EKS Elektronikservice GmbH + +OUI:000A6E* + ID_OUI_FROM_DATABASE=Harmonic, Inc + +OUI:000A6F* + ID_OUI_FROM_DATABASE=ZyFLEX Technologies Inc + +OUI:000A70* + ID_OUI_FROM_DATABASE=MPLS Forum + +OUI:000A71* + ID_OUI_FROM_DATABASE=Avrio Technologies, Inc + +OUI:000A72* + ID_OUI_FROM_DATABASE=STEC, INC. + +OUI:000A73* + ID_OUI_FROM_DATABASE=Scientific Atlanta + +OUI:000A74* + ID_OUI_FROM_DATABASE=Manticom Networks Inc. + +OUI:000A75* + ID_OUI_FROM_DATABASE=Caterpillar, Inc + +OUI:000A76* + ID_OUI_FROM_DATABASE=Beida Jade Bird Huaguang Technology Co.,Ltd + +OUI:000A77* + ID_OUI_FROM_DATABASE=Bluewire Technologies LLC + +OUI:000A78* + ID_OUI_FROM_DATABASE=OLITEC + +OUI:000A79* + ID_OUI_FROM_DATABASE=corega K.K + +OUI:000A7A* + ID_OUI_FROM_DATABASE=Kyoritsu Electric Co., Ltd. + +OUI:000A7B* + ID_OUI_FROM_DATABASE=Cornelius Consult + +OUI:000A7C* + ID_OUI_FROM_DATABASE=Tecton Ltd + +OUI:000A7D* + ID_OUI_FROM_DATABASE=Valo, Inc. + +OUI:000A7E* + ID_OUI_FROM_DATABASE=The Advantage Group + +OUI:000A7F* + ID_OUI_FROM_DATABASE=Teradon Industries, Inc + +OUI:000A80* + ID_OUI_FROM_DATABASE=Telkonet Inc. + +OUI:000A81* + ID_OUI_FROM_DATABASE=TEIMA Audiotex S.L. + +OUI:000A82* + ID_OUI_FROM_DATABASE=TATSUTA SYSTEM ELECTRONICS CO.,LTD. + +OUI:000A83* + ID_OUI_FROM_DATABASE=SALTO SYSTEMS S.L. + +OUI:000A84* + ID_OUI_FROM_DATABASE=Rainsun Enterprise Co., Ltd. + +OUI:000A85* + ID_OUI_FROM_DATABASE=PLAT'C2,Inc + +OUI:000A86* + ID_OUI_FROM_DATABASE=Lenze + +OUI:000A87* + ID_OUI_FROM_DATABASE=Integrated Micromachines Inc. + +OUI:000A88* + ID_OUI_FROM_DATABASE=InCypher S.A. + +OUI:000A89* + ID_OUI_FROM_DATABASE=Creval Systems, Inc. + +OUI:000A8A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000A8B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000A8C* + ID_OUI_FROM_DATABASE=Guardware Systems Ltd. + +OUI:000A8D* + ID_OUI_FROM_DATABASE=EUROTHERM LIMITED + +OUI:000A8E* + ID_OUI_FROM_DATABASE=Invacom Ltd + +OUI:000A8F* + ID_OUI_FROM_DATABASE=Aska International Inc. + +OUI:000A90* + ID_OUI_FROM_DATABASE=Bayside Interactive, Inc. + +OUI:000A91* + ID_OUI_FROM_DATABASE=HemoCue AB + +OUI:000A92* + ID_OUI_FROM_DATABASE=Presonus Corporation + +OUI:000A93* + ID_OUI_FROM_DATABASE=W2 Networks, Inc. + +OUI:000A94* + ID_OUI_FROM_DATABASE=ShangHai cellink CO., LTD + +OUI:000A95* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:000A96* + ID_OUI_FROM_DATABASE=MEWTEL TECHNOLOGY INC. + +OUI:000A97* + ID_OUI_FROM_DATABASE=SONICblue, Inc. + +OUI:000A98* + ID_OUI_FROM_DATABASE=M+F Gwinner GmbH & Co + +OUI:000A99* + ID_OUI_FROM_DATABASE=Calamp Wireless Networks Inc + +OUI:000A9A* + ID_OUI_FROM_DATABASE=Aiptek International Inc + +OUI:000A9B* + ID_OUI_FROM_DATABASE=TB Group Inc + +OUI:000A9C* + ID_OUI_FROM_DATABASE=Server Technology, Inc. + +OUI:000A9D* + ID_OUI_FROM_DATABASE=King Young Technology Co. Ltd. + +OUI:000A9E* + ID_OUI_FROM_DATABASE=BroadWeb Corportation + +OUI:000A9F* + ID_OUI_FROM_DATABASE=Pannaway Technologies, Inc. + +OUI:000AA0* + ID_OUI_FROM_DATABASE=Cedar Point Communications + +OUI:000AA1* + ID_OUI_FROM_DATABASE=V V S Limited + +OUI:000AA2* + ID_OUI_FROM_DATABASE=SYSTEK INC. + +OUI:000AA3* + ID_OUI_FROM_DATABASE=SHIMAFUJI ELECTRIC CO.,LTD. + +OUI:000AA4* + ID_OUI_FROM_DATABASE=SHANGHAI SURVEILLANCE TECHNOLOGY CO,LTD + +OUI:000AA5* + ID_OUI_FROM_DATABASE=MAXLINK INDUSTRIES LIMITED + +OUI:000AA6* + ID_OUI_FROM_DATABASE=Hochiki Corporation + +OUI:000AA7* + ID_OUI_FROM_DATABASE=FEI Electron Optics + +OUI:000AA8* + ID_OUI_FROM_DATABASE=ePipe Pty. Ltd. + +OUI:000AA9* + ID_OUI_FROM_DATABASE=Brooks Automation GmbH + +OUI:000AAA* + ID_OUI_FROM_DATABASE=AltiGen Communications Inc. + +OUI:000AAB* + ID_OUI_FROM_DATABASE=Toyota Technical Development Corporation + +OUI:000AAC* + ID_OUI_FROM_DATABASE=TerraTec Electronic GmbH + +OUI:000AAD* + ID_OUI_FROM_DATABASE=Stargames Corporation + +OUI:000AAE* + ID_OUI_FROM_DATABASE=Rosemount Process Analytical + +OUI:000AAF* + ID_OUI_FROM_DATABASE=Pipal Systems + +OUI:000AB0* + ID_OUI_FROM_DATABASE=LOYTEC electronics GmbH + +OUI:000AB1* + ID_OUI_FROM_DATABASE=GENETEC Corporation + +OUI:000AB2* + ID_OUI_FROM_DATABASE=Fresnel Wireless Systems + +OUI:000AB3* + ID_OUI_FROM_DATABASE=Fa. GIRA + +OUI:000AB4* + ID_OUI_FROM_DATABASE=ETIC Telecommunications + +OUI:000AB5* + ID_OUI_FROM_DATABASE=Digital Electronic Network + +OUI:000AB6* + ID_OUI_FROM_DATABASE=COMPUNETIX, INC + +OUI:000AB7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000AB8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000AB9* + ID_OUI_FROM_DATABASE=Astera Technologies Corp. + +OUI:000ABA* + ID_OUI_FROM_DATABASE=Arcon Technology Limited + +OUI:000ABB* + ID_OUI_FROM_DATABASE=Taiwan Secom Co,. Ltd + +OUI:000ABC* + ID_OUI_FROM_DATABASE=Seabridge Ltd. + +OUI:000ABD* + ID_OUI_FROM_DATABASE=Rupprecht & Patashnick Co. + +OUI:000ABE* + ID_OUI_FROM_DATABASE=OPNET Technologies CO., LTD. + +OUI:000ABF* + ID_OUI_FROM_DATABASE=HIROTA SS + +OUI:000AC0* + ID_OUI_FROM_DATABASE=Fuyoh Video Industry CO., LTD. + +OUI:000AC1* + ID_OUI_FROM_DATABASE=Futuretel + +OUI:000AC2* + ID_OUI_FROM_DATABASE=Wuhan FiberHome Digital Technology Co.,Ltd. + +OUI:000AC3* + ID_OUI_FROM_DATABASE=eM Technics Co., Ltd. + +OUI:000AC4* + ID_OUI_FROM_DATABASE=Daewoo Teletech Co., Ltd + +OUI:000AC5* + ID_OUI_FROM_DATABASE=Color Kinetics + +OUI:000AC6* + ID_OUI_FROM_DATABASE=Overture Networks. + +OUI:000AC7* + ID_OUI_FROM_DATABASE=Unication Group + +OUI:000AC8* + ID_OUI_FROM_DATABASE=ZPSYS CO.,LTD. (Planning&Management) + +OUI:000AC9* + ID_OUI_FROM_DATABASE=Zambeel Inc + +OUI:000ACA* + ID_OUI_FROM_DATABASE=YOKOYAMA SHOKAI CO.,Ltd. + +OUI:000ACB* + ID_OUI_FROM_DATABASE=XPAK MSA Group + +OUI:000ACC* + ID_OUI_FROM_DATABASE=Winnow Networks, Inc. + +OUI:000ACD* + ID_OUI_FROM_DATABASE=Sunrich Technology Limited + +OUI:000ACE* + ID_OUI_FROM_DATABASE=RADIANTECH, INC. + +OUI:000ACF* + ID_OUI_FROM_DATABASE=PROVIDEO Multimedia Co. Ltd. + +OUI:000AD0* + ID_OUI_FROM_DATABASE=Niigata Develoment Center, F.I.T. Co., Ltd. + +OUI:000AD1* + ID_OUI_FROM_DATABASE=MWS + +OUI:000AD2* + ID_OUI_FROM_DATABASE=JEPICO Corporation + +OUI:000AD3* + ID_OUI_FROM_DATABASE=INITECH Co., Ltd + +OUI:000AD4* + ID_OUI_FROM_DATABASE=CoreBell Systems Inc. + +OUI:000AD5* + ID_OUI_FROM_DATABASE=Brainchild Electronic Co., Ltd. + +OUI:000AD6* + ID_OUI_FROM_DATABASE=BeamReach Networks + +OUI:000AD7* + ID_OUI_FROM_DATABASE=Origin ELECTRIC CO.,LTD. + +OUI:000AD8* + ID_OUI_FROM_DATABASE=IPCserv Technology Corp. + +OUI:000AD9* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:000ADA* + ID_OUI_FROM_DATABASE=Vindicator Technologies + +OUI:000ADB* + ID_OUI_FROM_DATABASE=Trilliant + +OUI:000ADC* + ID_OUI_FROM_DATABASE=RuggedCom Inc. + +OUI:000ADD* + ID_OUI_FROM_DATABASE=Allworx Corp. + +OUI:000ADE* + ID_OUI_FROM_DATABASE=Happy Communication Co., Ltd. + +OUI:000ADF* + ID_OUI_FROM_DATABASE=Gennum Corporation + +OUI:000AE0* + ID_OUI_FROM_DATABASE=Fujitsu Softek + +OUI:000AE1* + ID_OUI_FROM_DATABASE=EG Technology + +OUI:000AE2* + ID_OUI_FROM_DATABASE=Binatone Electronics International, Ltd + +OUI:000AE3* + ID_OUI_FROM_DATABASE=YANG MEI TECHNOLOGY CO., LTD + +OUI:000AE4* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:000AE5* + ID_OUI_FROM_DATABASE=ScottCare Corporation + +OUI:000AE6* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:000AE7* + ID_OUI_FROM_DATABASE=ELIOP S.A. + +OUI:000AE8* + ID_OUI_FROM_DATABASE=Cathay Roxus Information Technology Co. LTD + +OUI:000AE9* + ID_OUI_FROM_DATABASE=AirVast Technology Inc. + +OUI:000AEA* + ID_OUI_FROM_DATABASE=ADAM ELEKTRONIK LTD. ŞTI + +OUI:000AEB* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:000AEC* + ID_OUI_FROM_DATABASE=Koatsu Gas Kogyo Co., Ltd. + +OUI:000AED* + ID_OUI_FROM_DATABASE=HARTING Electronics GmbH + +OUI:000AEE* + ID_OUI_FROM_DATABASE=GCD Hard- & Software GmbH + +OUI:000AEF* + ID_OUI_FROM_DATABASE=OTRUM ASA + +OUI:000AF0* + ID_OUI_FROM_DATABASE=SHIN-OH ELECTRONICS CO., LTD. R&D + +OUI:000AF1* + ID_OUI_FROM_DATABASE=Clarity Design, Inc. + +OUI:000AF2* + ID_OUI_FROM_DATABASE=NeoAxiom Corp. + +OUI:000AF3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000AF4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000AF5* + ID_OUI_FROM_DATABASE=Airgo Networks, Inc. + +OUI:000AF6* + ID_OUI_FROM_DATABASE=Emerson Climate Technologies Retail Solutions, Inc. + +OUI:000AF7* + ID_OUI_FROM_DATABASE=Broadcom + +OUI:000AF8* + ID_OUI_FROM_DATABASE=American Telecare Inc. + +OUI:000AF9* + ID_OUI_FROM_DATABASE=HiConnect, Inc. + +OUI:000AFA* + ID_OUI_FROM_DATABASE=Traverse Technologies Australia + +OUI:000AFB* + ID_OUI_FROM_DATABASE=Ambri Limited + +OUI:000AFC* + ID_OUI_FROM_DATABASE=Core Tec Communications, LLC + +OUI:000AFD* + ID_OUI_FROM_DATABASE=Kentec Electronics + +OUI:000AFE* + ID_OUI_FROM_DATABASE=NovaPal Ltd + +OUI:000AFF* + ID_OUI_FROM_DATABASE=Kilchherr Elektronik AG + +OUI:000B00* + ID_OUI_FROM_DATABASE=FUJIAN START COMPUTER EQUIPMENT CO.,LTD + +OUI:000B01* + ID_OUI_FROM_DATABASE=DAIICHI ELECTRONICS CO., LTD. + +OUI:000B02* + ID_OUI_FROM_DATABASE=Dallmeier electronic + +OUI:000B03* + ID_OUI_FROM_DATABASE=Taekwang Industrial Co., Ltd + +OUI:000B04* + ID_OUI_FROM_DATABASE=Volktek Corporation + +OUI:000B05* + ID_OUI_FROM_DATABASE=Pacific Broadband Networks + +OUI:000B06* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:000B07* + ID_OUI_FROM_DATABASE=Voxpath Networks + +OUI:000B08* + ID_OUI_FROM_DATABASE=Pillar Data Systems + +OUI:000B09* + ID_OUI_FROM_DATABASE=Ifoundry Systems Singapore + +OUI:000B0A* + ID_OUI_FROM_DATABASE=dBm Optics + +OUI:000B0B* + ID_OUI_FROM_DATABASE=Corrent Corporation + +OUI:000B0C* + ID_OUI_FROM_DATABASE=Agile Systems Inc. + +OUI:000B0D* + ID_OUI_FROM_DATABASE=Air2U, Inc. + +OUI:000B0E* + ID_OUI_FROM_DATABASE=Trapeze Networks + +OUI:000B0F* + ID_OUI_FROM_DATABASE=Bosch Rexroth + +OUI:000B10* + ID_OUI_FROM_DATABASE=11wave Technonlogy Co.,Ltd + +OUI:000B11* + ID_OUI_FROM_DATABASE=HIMEJI ABC TRADING CO.,LTD. + +OUI:000B12* + ID_OUI_FROM_DATABASE=NURI Telecom Co., Ltd. + +OUI:000B13* + ID_OUI_FROM_DATABASE=ZETRON INC + +OUI:000B14* + ID_OUI_FROM_DATABASE=ViewSonic Corporation + +OUI:000B15* + ID_OUI_FROM_DATABASE=Platypus Technology + +OUI:000B16* + ID_OUI_FROM_DATABASE=Communication Machinery Corporation + +OUI:000B17* + ID_OUI_FROM_DATABASE=MKS Instruments + +OUI:000B18* + ID_OUI_FROM_DATABASE=Private + +OUI:000B19* + ID_OUI_FROM_DATABASE=Vernier Networks, Inc. + +OUI:000B1A* + ID_OUI_FROM_DATABASE=Industrial Defender, Inc. + +OUI:000B1B* + ID_OUI_FROM_DATABASE=Systronix, Inc. + +OUI:000B1C* + ID_OUI_FROM_DATABASE=SIBCO bv + +OUI:000B1D* + ID_OUI_FROM_DATABASE=LayerZero Power Systems, Inc. + +OUI:000B1E* + ID_OUI_FROM_DATABASE=KAPPA opto-electronics GmbH + +OUI:000B1F* + ID_OUI_FROM_DATABASE=I CON Computer Co. + +OUI:000B20* + ID_OUI_FROM_DATABASE=Hirata corporation + +OUI:000B21* + ID_OUI_FROM_DATABASE=G-Star Communications Inc. + +OUI:000B22* + ID_OUI_FROM_DATABASE=Environmental Systems and Services + +OUI:000B23* + ID_OUI_FROM_DATABASE=Siemens Home & Office Comm. Devices + +OUI:000B24* + ID_OUI_FROM_DATABASE=AirLogic + +OUI:000B25* + ID_OUI_FROM_DATABASE=Aeluros + +OUI:000B26* + ID_OUI_FROM_DATABASE=Wetek Corporation + +OUI:000B27* + ID_OUI_FROM_DATABASE=Scion Corporation + +OUI:000B28* + ID_OUI_FROM_DATABASE=Quatech Inc. + +OUI:000B29* + ID_OUI_FROM_DATABASE=LS(LG) Industrial Systems co.,Ltd + +OUI:000B2A* + ID_OUI_FROM_DATABASE=HOWTEL Co., Ltd. + +OUI:000B2B* + ID_OUI_FROM_DATABASE=HOSTNET CORPORATION + +OUI:000B2C* + ID_OUI_FROM_DATABASE=Eiki Industrial Co. Ltd. + +OUI:000B2D* + ID_OUI_FROM_DATABASE=Danfoss Inc. + +OUI:000B2E* + ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Company Ltd. + +OUI:000B2F* + ID_OUI_FROM_DATABASE=bplan GmbH + +OUI:000B30* + ID_OUI_FROM_DATABASE=Beijing Gongye Science & Technology Co.,Ltd + +OUI:000B31* + ID_OUI_FROM_DATABASE=Yantai ZhiYang Scientific and technology industry CO., LTD + +OUI:000B32* + ID_OUI_FROM_DATABASE=VORMETRIC, INC. + +OUI:000B33* + ID_OUI_FROM_DATABASE=Vivato Technologies + +OUI:000B34* + ID_OUI_FROM_DATABASE=ShangHai Broadband Technologies CO.LTD + +OUI:000B35* + ID_OUI_FROM_DATABASE=Quad Bit System co., Ltd. + +OUI:000B36* + ID_OUI_FROM_DATABASE=Productivity Systems, Inc. + +OUI:000B37* + ID_OUI_FROM_DATABASE=MANUFACTURE DES MONTRES ROLEX SA + +OUI:000B38* + ID_OUI_FROM_DATABASE=Knürr GmbH + +OUI:000B39* + ID_OUI_FROM_DATABASE=Keisoku Giken Co.,Ltd. + +OUI:000B3A* + ID_OUI_FROM_DATABASE=QuStream Corporation + +OUI:000B3B* + ID_OUI_FROM_DATABASE=devolo AG + +OUI:000B3C* + ID_OUI_FROM_DATABASE=Cygnal Integrated Products, Inc. + +OUI:000B3D* + ID_OUI_FROM_DATABASE=CONTAL OK Ltd. + +OUI:000B3E* + ID_OUI_FROM_DATABASE=BittWare, Inc + +OUI:000B3F* + ID_OUI_FROM_DATABASE=Anthology Solutions Inc. + +OUI:000B40* + ID_OUI_FROM_DATABASE=Cambridge Industries Group (CIG) + +OUI:000B41* + ID_OUI_FROM_DATABASE=Ing. Büro Dr. Beutlhauser + +OUI:000B42* + ID_OUI_FROM_DATABASE=commax Co., Ltd. + +OUI:000B43* + ID_OUI_FROM_DATABASE=Microscan Systems, Inc. + +OUI:000B44* + ID_OUI_FROM_DATABASE=Concord IDea Corp. + +OUI:000B45* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000B46* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000B47* + ID_OUI_FROM_DATABASE=Advanced Energy + +OUI:000B48* + ID_OUI_FROM_DATABASE=sofrel + +OUI:000B49* + ID_OUI_FROM_DATABASE=RF-Link System Inc. + +OUI:000B4A* + ID_OUI_FROM_DATABASE=Visimetrics (UK) Ltd + +OUI:000B4B* + ID_OUI_FROM_DATABASE=VISIOWAVE SA + +OUI:000B4C* + ID_OUI_FROM_DATABASE=Clarion (M) Sdn Bhd + +OUI:000B4D* + ID_OUI_FROM_DATABASE=Emuzed + +OUI:000B4E* + ID_OUI_FROM_DATABASE=VertexRSI, General Dynamics SatCOM Technologies, Inc. + +OUI:000B4F* + ID_OUI_FROM_DATABASE=Verifone + +OUI:000B50* + ID_OUI_FROM_DATABASE=Oxygnet + +OUI:000B51* + ID_OUI_FROM_DATABASE=Micetek International Inc. + +OUI:000B52* + ID_OUI_FROM_DATABASE=JOYMAX ELECTRONICS CO. LTD. + +OUI:000B53* + ID_OUI_FROM_DATABASE=INITIUM Co., Ltd. + +OUI:000B54* + ID_OUI_FROM_DATABASE=BiTMICRO Networks, Inc. + +OUI:000B55* + ID_OUI_FROM_DATABASE=ADInstruments + +OUI:000B56* + ID_OUI_FROM_DATABASE=Cybernetics + +OUI:000B57* + ID_OUI_FROM_DATABASE=Silicon Laboratories + +OUI:000B58* + ID_OUI_FROM_DATABASE=Astronautics C.A LTD + +OUI:000B59* + ID_OUI_FROM_DATABASE=ScriptPro, LLC + +OUI:000B5A* + ID_OUI_FROM_DATABASE=HyperEdge + +OUI:000B5B* + ID_OUI_FROM_DATABASE=Rincon Research Corporation + +OUI:000B5C* + ID_OUI_FROM_DATABASE=Newtech Co.,Ltd + +OUI:000B5D* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:000B5E* + ID_OUI_FROM_DATABASE=Audio Engineering Society Inc. + +OUI:000B5F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000B60* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000B61* + ID_OUI_FROM_DATABASE=Friedrich Lütze GmbH & Co. KG + +OUI:000B62* + ID_OUI_FROM_DATABASE=ib-mohnen KG + +OUI:000B63* + ID_OUI_FROM_DATABASE=Kaleidescape + +OUI:000B64* + ID_OUI_FROM_DATABASE=Kieback & Peter GmbH & Co KG + +OUI:000B65* + ID_OUI_FROM_DATABASE=Sy.A.C. srl + +OUI:000B66* + ID_OUI_FROM_DATABASE=Teralink Communications + +OUI:000B67* + ID_OUI_FROM_DATABASE=Topview Technology Corporation + +OUI:000B68* + ID_OUI_FROM_DATABASE=Addvalue Communications Pte Ltd + +OUI:000B69* + ID_OUI_FROM_DATABASE=Franke Finland Oy + +OUI:000B6A* + ID_OUI_FROM_DATABASE=Asiarock Technology Limited + +OUI:000B6B* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:000B6C* + ID_OUI_FROM_DATABASE=Sychip Inc. + +OUI:000B6D* + ID_OUI_FROM_DATABASE=SOLECTRON JAPAN NAKANIIDA + +OUI:000B6E* + ID_OUI_FROM_DATABASE=Neff Instrument Corp. + +OUI:000B6F* + ID_OUI_FROM_DATABASE=Media Streaming Networks Inc + +OUI:000B70* + ID_OUI_FROM_DATABASE=Load Technology, Inc. + +OUI:000B71* + ID_OUI_FROM_DATABASE=Litchfield Communications Inc. + +OUI:000B72* + ID_OUI_FROM_DATABASE=Lawo AG + +OUI:000B73* + ID_OUI_FROM_DATABASE=Kodeos Communications + +OUI:000B74* + ID_OUI_FROM_DATABASE=Kingwave Technology Co., Ltd. + +OUI:000B75* + ID_OUI_FROM_DATABASE=Iosoft Ltd. + +OUI:000B76* + ID_OUI_FROM_DATABASE=ET&T Technology Co. Ltd. + +OUI:000B77* + ID_OUI_FROM_DATABASE=Cogent Systems, Inc. + +OUI:000B78* + ID_OUI_FROM_DATABASE=TAIFATECH INC. + +OUI:000B79* + ID_OUI_FROM_DATABASE=X-COM, Inc. + +OUI:000B7A* + ID_OUI_FROM_DATABASE=L-3 Linkabit + +OUI:000B7B* + ID_OUI_FROM_DATABASE=Test-Um Inc. + +OUI:000B7C* + ID_OUI_FROM_DATABASE=Telex Communications + +OUI:000B7D* + ID_OUI_FROM_DATABASE=SOLOMON EXTREME INTERNATIONAL LTD. + +OUI:000B7E* + ID_OUI_FROM_DATABASE=SAGINOMIYA Seisakusho Inc. + +OUI:000B7F* + ID_OUI_FROM_DATABASE=Align Engineering LLC + +OUI:000B80* + ID_OUI_FROM_DATABASE=Lycium Networks + +OUI:000B81* + ID_OUI_FROM_DATABASE=Kaparel Corporation + +OUI:000B82* + ID_OUI_FROM_DATABASE=Grandstream Networks, Inc. + +OUI:000B83* + ID_OUI_FROM_DATABASE=DATAWATT B.V. + +OUI:000B84* + ID_OUI_FROM_DATABASE=BODET + +OUI:000B85* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000B86* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:000B87* + ID_OUI_FROM_DATABASE=American Reliance Inc. + +OUI:000B88* + ID_OUI_FROM_DATABASE=Vidisco ltd. + +OUI:000B89* + ID_OUI_FROM_DATABASE=Top Global Technology, Ltd. + +OUI:000B8A* + ID_OUI_FROM_DATABASE=MITEQ Inc. + +OUI:000B8B* + ID_OUI_FROM_DATABASE=KERAJET, S.A. + +OUI:000B8C* + ID_OUI_FROM_DATABASE=Flextronics + +OUI:000B8D* + ID_OUI_FROM_DATABASE=Avvio Networks + +OUI:000B8E* + ID_OUI_FROM_DATABASE=Ascent Corporation + +OUI:000B8F* + ID_OUI_FROM_DATABASE=AKITA ELECTRONICS SYSTEMS CO.,LTD. + +OUI:000B90* + ID_OUI_FROM_DATABASE=ADVA Optical Networking Ltd. + +OUI:000B91* + ID_OUI_FROM_DATABASE=Aglaia Gesellschaft für Bildverarbeitung und Kommunikation mbH + +OUI:000B92* + ID_OUI_FROM_DATABASE=Ascom Danmark A/S + +OUI:000B93* + ID_OUI_FROM_DATABASE=Ritter Elektronik + +OUI:000B94* + ID_OUI_FROM_DATABASE=Digital Monitoring Products, Inc. + +OUI:000B95* + ID_OUI_FROM_DATABASE=eBet Gaming Systems Pty Ltd + +OUI:000B96* + ID_OUI_FROM_DATABASE=Innotrac Diagnostics Oy + +OUI:000B97* + ID_OUI_FROM_DATABASE=Matsushita Electric Industrial Co.,Ltd. + +OUI:000B98* + ID_OUI_FROM_DATABASE=NiceTechVision + +OUI:000B99* + ID_OUI_FROM_DATABASE=SensAble Technologies, Inc. + +OUI:000B9A* + ID_OUI_FROM_DATABASE=Shanghai Ulink Telecom Equipment Co. Ltd. + +OUI:000B9B* + ID_OUI_FROM_DATABASE=Sirius System Co, Ltd. + +OUI:000B9C* + ID_OUI_FROM_DATABASE=TriBeam Technologies, Inc. + +OUI:000B9D* + ID_OUI_FROM_DATABASE=TwinMOS Technologies Inc. + +OUI:000B9E* + ID_OUI_FROM_DATABASE=Yasing Technology Corp. + +OUI:000B9F* + ID_OUI_FROM_DATABASE=Neue ELSA GmbH + +OUI:000BA0* + ID_OUI_FROM_DATABASE=T&L Information Inc. + +OUI:000BA1* + ID_OUI_FROM_DATABASE=Fujikura Solutions Ltd. + +OUI:000BA2* + ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd + +OUI:000BA3* + ID_OUI_FROM_DATABASE=Siemens AG + +OUI:000BA4* + ID_OUI_FROM_DATABASE=Shiron Satellite Communications Ltd. (1996) + +OUI:000BA5* + ID_OUI_FROM_DATABASE=Quasar Cipta Mandiri, PT + +OUI:000BA6* + ID_OUI_FROM_DATABASE=Miyakawa Electric Works Ltd. + +OUI:000BA7* + ID_OUI_FROM_DATABASE=Maranti Networks + +OUI:000BA8* + ID_OUI_FROM_DATABASE=HANBACK ELECTRONICS CO., LTD. + +OUI:000BA9* + ID_OUI_FROM_DATABASE=CloudShield Technologies, Inc. + +OUI:000BAA* + ID_OUI_FROM_DATABASE=Aiphone co.,Ltd + +OUI:000BAB* + ID_OUI_FROM_DATABASE=Advantech Technology (CHINA) Co., Ltd. + +OUI:000BAC* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:000BAD* + ID_OUI_FROM_DATABASE=PC-PoS Inc. + +OUI:000BAE* + ID_OUI_FROM_DATABASE=Vitals System Inc. + +OUI:000BAF* + ID_OUI_FROM_DATABASE=WOOJU COMMUNICATIONS Co,.Ltd + +OUI:000BB0* + ID_OUI_FROM_DATABASE=Sysnet Telematica srl + +OUI:000BB1* + ID_OUI_FROM_DATABASE=Super Star Technology Co., Ltd. + +OUI:000BB2* + ID_OUI_FROM_DATABASE=SMALLBIG TECHNOLOGY + +OUI:000BB3* + ID_OUI_FROM_DATABASE=RiT technologies Ltd. + +OUI:000BB4* + ID_OUI_FROM_DATABASE=RDC Semiconductor Inc., + +OUI:000BB5* + ID_OUI_FROM_DATABASE=nStor Technologies, Inc. + +OUI:000BB6* + ID_OUI_FROM_DATABASE=Metalligence Technology Corp. + +OUI:000BB7* + ID_OUI_FROM_DATABASE=Micro Systems Co.,Ltd. + +OUI:000BB8* + ID_OUI_FROM_DATABASE=Kihoku Electronic Co. + +OUI:000BB9* + ID_OUI_FROM_DATABASE=Imsys AB + +OUI:000BBA* + ID_OUI_FROM_DATABASE=Harmonic, Inc + +OUI:000BBB* + ID_OUI_FROM_DATABASE=Etin Systems Co., Ltd + +OUI:000BBC* + ID_OUI_FROM_DATABASE=En Garde Systems, Inc. + +OUI:000BBD* + ID_OUI_FROM_DATABASE=Connexionz Limited + +OUI:000BBE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000BBF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000BC0* + ID_OUI_FROM_DATABASE=China IWNComm Co., Ltd. + +OUI:000BC1* + ID_OUI_FROM_DATABASE=Bay Microsystems, Inc. + +OUI:000BC2* + ID_OUI_FROM_DATABASE=Corinex Communication Corp. + +OUI:000BC3* + ID_OUI_FROM_DATABASE=Multiplex, Inc. + +OUI:000BC4* + ID_OUI_FROM_DATABASE=BIOTRONIK GmbH & Co + +OUI:000BC5* + ID_OUI_FROM_DATABASE=SMC Networks, Inc. + +OUI:000BC6* + ID_OUI_FROM_DATABASE=ISAC, Inc. + +OUI:000BC7* + ID_OUI_FROM_DATABASE=ICET S.p.A. + +OUI:000BC8* + ID_OUI_FROM_DATABASE=AirFlow Networks + +OUI:000BC9* + ID_OUI_FROM_DATABASE=Electroline Equipment + +OUI:000BCA* + ID_OUI_FROM_DATABASE=DATAVAN TC + +OUI:000BCB* + ID_OUI_FROM_DATABASE=Fagor Automation , S. Coop + +OUI:000BCC* + ID_OUI_FROM_DATABASE=JUSAN, S.A. + +OUI:000BCD* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:000BCE* + ID_OUI_FROM_DATABASE=Free2move AB + +OUI:000BCF* + ID_OUI_FROM_DATABASE=AGFA NDT INC. + +OUI:000BD0* + ID_OUI_FROM_DATABASE=XiMeta Technology Americas Inc. + +OUI:000BD1* + ID_OUI_FROM_DATABASE=Aeronix, Inc. + +OUI:000BD2* + ID_OUI_FROM_DATABASE=Remopro Technology Inc. + +OUI:000BD3* + ID_OUI_FROM_DATABASE=cd3o + +OUI:000BD4* + ID_OUI_FROM_DATABASE=Beijing Wise Technology & Science Development Co.Ltd + +OUI:000BD5* + ID_OUI_FROM_DATABASE=Nvergence, Inc. + +OUI:000BD6* + ID_OUI_FROM_DATABASE=Paxton Access Ltd + +OUI:000BD7* + ID_OUI_FROM_DATABASE=DORMA Time + Access GmbH + +OUI:000BD8* + ID_OUI_FROM_DATABASE=Industrial Scientific Corp. + +OUI:000BD9* + ID_OUI_FROM_DATABASE=General Hydrogen + +OUI:000BDA* + ID_OUI_FROM_DATABASE=EyeCross Co.,Inc. + +OUI:000BDB* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:000BDC* + ID_OUI_FROM_DATABASE=AKCP + +OUI:000BDD* + ID_OUI_FROM_DATABASE=TOHOKU RICOH Co., LTD. + +OUI:000BDE* + ID_OUI_FROM_DATABASE=TELDIX GmbH + +OUI:000BDF* + ID_OUI_FROM_DATABASE=Shenzhen RouterD Networks Limited + +OUI:000BE0* + ID_OUI_FROM_DATABASE=SercoNet Ltd. + +OUI:000BE1* + ID_OUI_FROM_DATABASE=Nokia NET Product Operations + +OUI:000BE2* + ID_OUI_FROM_DATABASE=Lumenera Corporation + +OUI:000BE3* + ID_OUI_FROM_DATABASE=Key Stream Co., Ltd. + +OUI:000BE4* + ID_OUI_FROM_DATABASE=Hosiden Corporation + +OUI:000BE5* + ID_OUI_FROM_DATABASE=HIMS International Corporation + +OUI:000BE6* + ID_OUI_FROM_DATABASE=Datel Electronics + +OUI:000BE7* + ID_OUI_FROM_DATABASE=COMFLUX TECHNOLOGY INC. + +OUI:000BE8* + ID_OUI_FROM_DATABASE=AOIP + +OUI:000BE9* + ID_OUI_FROM_DATABASE=Actel Corporation + +OUI:000BEA* + ID_OUI_FROM_DATABASE=Zultys Technologies + +OUI:000BEB* + ID_OUI_FROM_DATABASE=Systegra AG + +OUI:000BEC* + ID_OUI_FROM_DATABASE=NIPPON ELECTRIC INSTRUMENT, INC. + +OUI:000BED* + ID_OUI_FROM_DATABASE=ELM Inc. + +OUI:000BEE* + ID_OUI_FROM_DATABASE=inc.jet, Incorporated + +OUI:000BEF* + ID_OUI_FROM_DATABASE=Code Corporation + +OUI:000BF0* + ID_OUI_FROM_DATABASE=MoTEX Products Co., Ltd. + +OUI:000BF1* + ID_OUI_FROM_DATABASE=LAP Laser Applikations + +OUI:000BF2* + ID_OUI_FROM_DATABASE=Chih-Kan Technology Co., Ltd. + +OUI:000BF3* + ID_OUI_FROM_DATABASE=BAE SYSTEMS + +OUI:000BF4* + ID_OUI_FROM_DATABASE=Private + +OUI:000BF5* + ID_OUI_FROM_DATABASE=Shanghai Sibo Telecom Technology Co.,Ltd + +OUI:000BF6* + ID_OUI_FROM_DATABASE=Nitgen Co., Ltd + +OUI:000BF7* + ID_OUI_FROM_DATABASE=NIDEK CO.,LTD + +OUI:000BF8* + ID_OUI_FROM_DATABASE=Infinera + +OUI:000BF9* + ID_OUI_FROM_DATABASE=Gemstone Communications, Inc. + +OUI:000BFA* + ID_OUI_FROM_DATABASE=EXEMYS SRL + +OUI:000BFB* + ID_OUI_FROM_DATABASE=D-NET International Corporation + +OUI:000BFC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000BFD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000BFE* + ID_OUI_FROM_DATABASE=CASTEL Broadband Limited + +OUI:000BFF* + ID_OUI_FROM_DATABASE=Berkeley Camera Engineering + +OUI:000C00* + ID_OUI_FROM_DATABASE=BEB Industrie-Elektronik AG + +OUI:000C01* + ID_OUI_FROM_DATABASE=Abatron AG + +OUI:000C02* + ID_OUI_FROM_DATABASE=ABB Oy + +OUI:000C03* + ID_OUI_FROM_DATABASE=HDMI Licensing, LLC + +OUI:000C04* + ID_OUI_FROM_DATABASE=Tecnova + +OUI:000C05* + ID_OUI_FROM_DATABASE=RPA Reserch Co., Ltd. + +OUI:000C06* + ID_OUI_FROM_DATABASE=Nixvue Systems Pte Ltd + +OUI:000C07* + ID_OUI_FROM_DATABASE=Iftest AG + +OUI:000C08* + ID_OUI_FROM_DATABASE=HUMEX Technologies Corp. + +OUI:000C09* + ID_OUI_FROM_DATABASE=Hitachi IE Systems Co., Ltd + +OUI:000C0A* + ID_OUI_FROM_DATABASE=Guangdong Province Electronic Technology Research Institute + +OUI:000C0B* + ID_OUI_FROM_DATABASE=Broadbus Technologies + +OUI:000C0C* + ID_OUI_FROM_DATABASE=APPRO TECHNOLOGY INC. + +OUI:000C0D* + ID_OUI_FROM_DATABASE=Communications & Power Industries / Satcom Division + +OUI:000C0E* + ID_OUI_FROM_DATABASE=XtremeSpectrum, Inc. + +OUI:000C0F* + ID_OUI_FROM_DATABASE=Techno-One Co., Ltd + +OUI:000C10* + ID_OUI_FROM_DATABASE=PNI Corporation + +OUI:000C11* + ID_OUI_FROM_DATABASE=NIPPON DEMPA CO.,LTD. + +OUI:000C12* + ID_OUI_FROM_DATABASE=Micro-Optronic-Messtechnik GmbH + +OUI:000C13* + ID_OUI_FROM_DATABASE=MediaQ + +OUI:000C14* + ID_OUI_FROM_DATABASE=Diagnostic Instruments, Inc. + +OUI:000C15* + ID_OUI_FROM_DATABASE=CyberPower Systems, Inc. + +OUI:000C16* + ID_OUI_FROM_DATABASE=Concorde Microsystems Inc. + +OUI:000C17* + ID_OUI_FROM_DATABASE=AJA Video Systems Inc + +OUI:000C18* + ID_OUI_FROM_DATABASE=Zenisu Keisoku Inc. + +OUI:000C19* + ID_OUI_FROM_DATABASE=Telio Communications GmbH + +OUI:000C1A* + ID_OUI_FROM_DATABASE=Quest Technical Solutions Inc. + +OUI:000C1B* + ID_OUI_FROM_DATABASE=ORACOM Co, Ltd. + +OUI:000C1C* + ID_OUI_FROM_DATABASE=MicroWeb Co., Ltd. + +OUI:000C1D* + ID_OUI_FROM_DATABASE=Mettler & Fuchs AG + +OUI:000C1E* + ID_OUI_FROM_DATABASE=Global Cache + +OUI:000C1F* + ID_OUI_FROM_DATABASE=Glimmerglass Networks + +OUI:000C20* + ID_OUI_FROM_DATABASE=Fi WIn, Inc. + +OUI:000C21* + ID_OUI_FROM_DATABASE=Faculty of Science and Technology, Keio University + +OUI:000C22* + ID_OUI_FROM_DATABASE=Double D Electronics Ltd + +OUI:000C23* + ID_OUI_FROM_DATABASE=Beijing Lanchuan Tech. Co., Ltd. + +OUI:000C24* + ID_OUI_FROM_DATABASE=ANATOR + +OUI:000C25* + ID_OUI_FROM_DATABASE=Allied Telesis Labs, Inc. + +OUI:000C26* + ID_OUI_FROM_DATABASE=Weintek Labs. Inc. + +OUI:000C27* + ID_OUI_FROM_DATABASE=Sammy Corporation + +OUI:000C28* + ID_OUI_FROM_DATABASE=RIFATRON + +OUI:000C29* + ID_OUI_FROM_DATABASE=VMware, Inc. + +OUI:000C2A* + ID_OUI_FROM_DATABASE=OCTTEL Communication Co., Ltd. + +OUI:000C2B* + ID_OUI_FROM_DATABASE=ELIAS Technology, Inc. + +OUI:000C2C* + ID_OUI_FROM_DATABASE=Enwiser Inc. + +OUI:000C2D* + ID_OUI_FROM_DATABASE=FullWave Technology Co., Ltd. + +OUI:000C2E* + ID_OUI_FROM_DATABASE=Openet information technology(shenzhen) Co., Ltd. + +OUI:000C2F* + ID_OUI_FROM_DATABASE=SeorimTechnology Co.,Ltd. + +OUI:000C30* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000C31* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000C32* + ID_OUI_FROM_DATABASE=Avionic Design Development GmbH + +OUI:000C33* + ID_OUI_FROM_DATABASE=Compucase Enterprise Co. Ltd. + +OUI:000C34* + ID_OUI_FROM_DATABASE=Vixen Co., Ltd. + +OUI:000C35* + ID_OUI_FROM_DATABASE=KaVo Dental GmbH & Co. KG + +OUI:000C36* + ID_OUI_FROM_DATABASE=SHARP TAKAYA ELECTRONICS INDUSTRY CO.,LTD. + +OUI:000C37* + ID_OUI_FROM_DATABASE=Geomation, Inc. + +OUI:000C38* + ID_OUI_FROM_DATABASE=TelcoBridges Inc. + +OUI:000C39* + ID_OUI_FROM_DATABASE=Sentinel Wireless Inc. + +OUI:000C3A* + ID_OUI_FROM_DATABASE=Oxance + +OUI:000C3B* + ID_OUI_FROM_DATABASE=Orion Electric Co., Ltd. + +OUI:000C3C* + ID_OUI_FROM_DATABASE=MediaChorus, Inc. + +OUI:000C3D* + ID_OUI_FROM_DATABASE=Glsystech Co., Ltd. + +OUI:000C3E* + ID_OUI_FROM_DATABASE=Crest Audio + +OUI:000C3F* + ID_OUI_FROM_DATABASE=Cogent Defence & Security Networks, + +OUI:000C40* + ID_OUI_FROM_DATABASE=Altech Controls + +OUI:000C41* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:000C42* + ID_OUI_FROM_DATABASE=Routerboard.com + +OUI:000C43* + ID_OUI_FROM_DATABASE=Ralink Technology, Corp. + +OUI:000C44* + ID_OUI_FROM_DATABASE=Automated Interfaces, Inc. + +OUI:000C45* + ID_OUI_FROM_DATABASE=Animation Technologies Inc. + +OUI:000C46* + ID_OUI_FROM_DATABASE=Allied Telesyn Inc. + +OUI:000C47* + ID_OUI_FROM_DATABASE=SK Teletech(R&D Planning Team) + +OUI:000C48* + ID_OUI_FROM_DATABASE=QoStek Corporation + +OUI:000C49* + ID_OUI_FROM_DATABASE=Dangaard Telecom Denmark A/S + +OUI:000C4A* + ID_OUI_FROM_DATABASE=Cygnus Microsystems (P) Limited + +OUI:000C4B* + ID_OUI_FROM_DATABASE=Cheops Elektronik + +OUI:000C4C* + ID_OUI_FROM_DATABASE=Arcor AG&Co. + +OUI:000C4D* + ID_OUI_FROM_DATABASE=Curtiss-Wright Controls Avionics & Electronics + +OUI:000C4E* + ID_OUI_FROM_DATABASE=Winbest Technology CO,LT + +OUI:000C4F* + ID_OUI_FROM_DATABASE=UDTech Japan Corporation + +OUI:000C50* + ID_OUI_FROM_DATABASE=Seagate Technology + +OUI:000C51* + ID_OUI_FROM_DATABASE=Scientific Technologies Inc. + +OUI:000C52* + ID_OUI_FROM_DATABASE=Roll Systems Inc. + +OUI:000C53* + ID_OUI_FROM_DATABASE=Private + +OUI:000C54* + ID_OUI_FROM_DATABASE=Pedestal Networks, Inc + +OUI:000C55* + ID_OUI_FROM_DATABASE=Microlink Communications Inc. + +OUI:000C56* + ID_OUI_FROM_DATABASE=Megatel Computer (1986) Corp. + +OUI:000C57* + ID_OUI_FROM_DATABASE=MACKIE Engineering Services Belgium BVBA + +OUI:000C58* + ID_OUI_FROM_DATABASE=M&S Systems + +OUI:000C59* + ID_OUI_FROM_DATABASE=Indyme Electronics, Inc. + +OUI:000C5A* + ID_OUI_FROM_DATABASE=IBSmm Embedded Electronics Consulting + +OUI:000C5B* + ID_OUI_FROM_DATABASE=HANWANG TECHNOLOGY CO.,LTD + +OUI:000C5C* + ID_OUI_FROM_DATABASE=GTN Systems B.V. + +OUI:000C5D* + ID_OUI_FROM_DATABASE=CHIC TECHNOLOGY (CHINA) CORP. + +OUI:000C5E* + ID_OUI_FROM_DATABASE=Calypso Medical + +OUI:000C5F* + ID_OUI_FROM_DATABASE=Avtec, Inc. + +OUI:000C60* + ID_OUI_FROM_DATABASE=ACM Systems + +OUI:000C61* + ID_OUI_FROM_DATABASE=AC Tech corporation DBA Advanced Digital + +OUI:000C62* + ID_OUI_FROM_DATABASE=ABB AB, Cewe-Control + +OUI:000C63* + ID_OUI_FROM_DATABASE=Zenith Electronics Corporation + +OUI:000C64* + ID_OUI_FROM_DATABASE=X2 MSA Group + +OUI:000C65* + ID_OUI_FROM_DATABASE=Sunin Telecom + +OUI:000C66* + ID_OUI_FROM_DATABASE=Pronto Networks Inc + +OUI:000C67* + ID_OUI_FROM_DATABASE=OYO ELECTRIC CO.,LTD + +OUI:000C68* + ID_OUI_FROM_DATABASE=SigmaTel, Inc. + +OUI:000C69* + ID_OUI_FROM_DATABASE=National Radio Astronomy Observatory + +OUI:000C6A* + ID_OUI_FROM_DATABASE=MBARI + +OUI:000C6B* + ID_OUI_FROM_DATABASE=Kurz Industrie-Elektronik GmbH + +OUI:000C6C* + ID_OUI_FROM_DATABASE=Eve Systems GmbH + +OUI:000C6D* + ID_OUI_FROM_DATABASE=Edwards Ltd. + +OUI:000C6E* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:000C6F* + ID_OUI_FROM_DATABASE=Amtek system co.,LTD. + +OUI:000C70* + ID_OUI_FROM_DATABASE=ACC GmbH + +OUI:000C71* + ID_OUI_FROM_DATABASE=Wybron, Inc + +OUI:000C72* + ID_OUI_FROM_DATABASE=Tempearl Industrial Co., Ltd. + +OUI:000C73* + ID_OUI_FROM_DATABASE=TELSON ELECTRONICS CO., LTD + +OUI:000C74* + ID_OUI_FROM_DATABASE=RIVERTEC CORPORATION + +OUI:000C75* + ID_OUI_FROM_DATABASE=Oriental integrated electronics. LTD + +OUI:000C76* + ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. + +OUI:000C77* + ID_OUI_FROM_DATABASE=Life Racing Ltd + +OUI:000C78* + ID_OUI_FROM_DATABASE=In-Tech Electronics Limited + +OUI:000C79* + ID_OUI_FROM_DATABASE=Extel Communications P/L + +OUI:000C7A* + ID_OUI_FROM_DATABASE=DaTARIUS Technologies GmbH + +OUI:000C7B* + ID_OUI_FROM_DATABASE=ALPHA PROJECT Co.,Ltd. + +OUI:000C7C* + ID_OUI_FROM_DATABASE=Internet Information Image Inc. + +OUI:000C7D* + ID_OUI_FROM_DATABASE=TEIKOKU ELECTRIC MFG. CO., LTD + +OUI:000C7E* + ID_OUI_FROM_DATABASE=Tellium Incorporated + +OUI:000C7F* + ID_OUI_FROM_DATABASE=synertronixx GmbH + +OUI:000C80* + ID_OUI_FROM_DATABASE=Opelcomm Inc. + +OUI:000C81* + ID_OUI_FROM_DATABASE=Schneider Electric (Australia) + +OUI:000C82* + ID_OUI_FROM_DATABASE=NETWORK TECHNOLOGIES INC + +OUI:000C83* + ID_OUI_FROM_DATABASE=Logical Solutions + +OUI:000C84* + ID_OUI_FROM_DATABASE=Eazix, Inc. + +OUI:000C85* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000C86* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000C87* + ID_OUI_FROM_DATABASE=AMD + +OUI:000C88* + ID_OUI_FROM_DATABASE=Apache Micro Peripherals, Inc. + +OUI:000C89* + ID_OUI_FROM_DATABASE=AC Electric Vehicles, Ltd. + +OUI:000C8A* + ID_OUI_FROM_DATABASE=Bose Corporation + +OUI:000C8B* + ID_OUI_FROM_DATABASE=Connect Tech Inc + +OUI:000C8C* + ID_OUI_FROM_DATABASE=KODICOM CO.,LTD. + +OUI:000C8D* + ID_OUI_FROM_DATABASE=MATRIX VISION GmbH + +OUI:000C8E* + ID_OUI_FROM_DATABASE=Mentor Engineering Inc + +OUI:000C8F* + ID_OUI_FROM_DATABASE=Nergal s.r.l. + +OUI:000C90* + ID_OUI_FROM_DATABASE=Octasic Inc. + +OUI:000C91* + ID_OUI_FROM_DATABASE=Riverhead Networks Inc. + +OUI:000C92* + ID_OUI_FROM_DATABASE=WolfVision Gmbh + +OUI:000C93* + ID_OUI_FROM_DATABASE=Xeline Co., Ltd. + +OUI:000C94* + ID_OUI_FROM_DATABASE=United Electronic Industries, Inc. (EUI) + +OUI:000C95* + ID_OUI_FROM_DATABASE=PrimeNet + +OUI:000C96* + ID_OUI_FROM_DATABASE=OQO, Inc. + +OUI:000C97* + ID_OUI_FROM_DATABASE=NV ADB TTV Technologies SA + +OUI:000C98* + ID_OUI_FROM_DATABASE=LETEK Communications Inc. + +OUI:000C99* + ID_OUI_FROM_DATABASE=HITEL LINK Co.,Ltd + +OUI:000C9A* + ID_OUI_FROM_DATABASE=Hitech Electronics Corp. + +OUI:000C9B* + ID_OUI_FROM_DATABASE=EE Solutions, Inc + +OUI:000C9C* + ID_OUI_FROM_DATABASE=Chongho information & communications + +OUI:000C9D* + ID_OUI_FROM_DATABASE=UbeeAirWalk, Inc. + +OUI:000C9E* + ID_OUI_FROM_DATABASE=MemoryLink Corp. + +OUI:000C9F* + ID_OUI_FROM_DATABASE=NKE Corporation + +OUI:000CA0* + ID_OUI_FROM_DATABASE=StorCase Technology, Inc. + +OUI:000CA1* + ID_OUI_FROM_DATABASE=SIGMACOM Co., LTD. + +OUI:000CA2* + ID_OUI_FROM_DATABASE=Harmonic Video Network + +OUI:000CA3* + ID_OUI_FROM_DATABASE=Rancho Technology, Inc. + +OUI:000CA4* + ID_OUI_FROM_DATABASE=Prompttec Product Management GmbH + +OUI:000CA5* + ID_OUI_FROM_DATABASE=Naman NZ LTd + +OUI:000CA6* + ID_OUI_FROM_DATABASE=Mintera Corporation + +OUI:000CA7* + ID_OUI_FROM_DATABASE=Metro (Suzhou) Technologies Co., Ltd. + +OUI:000CA8* + ID_OUI_FROM_DATABASE=Garuda Networks Corporation + +OUI:000CA9* + ID_OUI_FROM_DATABASE=Ebtron Inc. + +OUI:000CAA* + ID_OUI_FROM_DATABASE=Cubic Transportation Systems Inc + +OUI:000CAB* + ID_OUI_FROM_DATABASE=Commend International GmbH + +OUI:000CAC* + ID_OUI_FROM_DATABASE=Citizen Watch Co., Ltd. + +OUI:000CAD* + ID_OUI_FROM_DATABASE=BTU International + +OUI:000CAE* + ID_OUI_FROM_DATABASE=Ailocom Oy + +OUI:000CAF* + ID_OUI_FROM_DATABASE=TRI TERM CO.,LTD. + +OUI:000CB0* + ID_OUI_FROM_DATABASE=Star Semiconductor Corporation + +OUI:000CB1* + ID_OUI_FROM_DATABASE=Salland Engineering (Europe) BV + +OUI:000CB2* + ID_OUI_FROM_DATABASE=UNION co., ltd. + +OUI:000CB3* + ID_OUI_FROM_DATABASE=ROUND Co.,Ltd. + +OUI:000CB4* + ID_OUI_FROM_DATABASE=AutoCell Laboratories, Inc. + +OUI:000CB5* + ID_OUI_FROM_DATABASE=Premier Technolgies, Inc + +OUI:000CB6* + ID_OUI_FROM_DATABASE=NANJING SEU MOBILE & INTERNET TECHNOLOGY CO.,LTD + +OUI:000CB7* + ID_OUI_FROM_DATABASE=Nanjing Huazhuo Electronics Co., Ltd. + +OUI:000CB8* + ID_OUI_FROM_DATABASE=MEDION AG + +OUI:000CB9* + ID_OUI_FROM_DATABASE=LEA + +OUI:000CBA* + ID_OUI_FROM_DATABASE=Jamex, Inc. + +OUI:000CBB* + ID_OUI_FROM_DATABASE=ISKRAEMECO + +OUI:000CBC* + ID_OUI_FROM_DATABASE=Iscutum + +OUI:000CBD* + ID_OUI_FROM_DATABASE=Interface Masters, Inc + +OUI:000CBE* + ID_OUI_FROM_DATABASE=Innominate Security Technologies AG + +OUI:000CBF* + ID_OUI_FROM_DATABASE=Holy Stone Ent. Co., Ltd. + +OUI:000CC0* + ID_OUI_FROM_DATABASE=Genera Oy + +OUI:000CC1* + ID_OUI_FROM_DATABASE=Eaton Corporation + +OUI:000CC2* + ID_OUI_FROM_DATABASE=ControlNet (India) Private Limited + +OUI:000CC3* + ID_OUI_FROM_DATABASE=BeWAN systems + +OUI:000CC4* + ID_OUI_FROM_DATABASE=Tiptel AG + +OUI:000CC5* + ID_OUI_FROM_DATABASE=Nextlink Co., Ltd. + +OUI:000CC6* + ID_OUI_FROM_DATABASE=Ka-Ro electronics GmbH + +OUI:000CC7* + ID_OUI_FROM_DATABASE=Intelligent Computer Solutions Inc. + +OUI:000CC8* + ID_OUI_FROM_DATABASE=Xytronix Research & Design, Inc. + +OUI:000CC9* + ID_OUI_FROM_DATABASE=ILWOO DATA & TECHNOLOGY CO.,LTD + +OUI:000CCA* + ID_OUI_FROM_DATABASE=HGST a Western Digital Company + +OUI:000CCB* + ID_OUI_FROM_DATABASE=Design Combus Ltd + +OUI:000CCC* + ID_OUI_FROM_DATABASE=Aeroscout Ltd. + +OUI:000CCD* + ID_OUI_FROM_DATABASE=IEC - TC57 + +OUI:000CCE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000CCF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000CD0* + ID_OUI_FROM_DATABASE=Symetrix + +OUI:000CD1* + ID_OUI_FROM_DATABASE=SFOM Technology Corp. + +OUI:000CD2* + ID_OUI_FROM_DATABASE=Schaffner EMV AG + +OUI:000CD3* + ID_OUI_FROM_DATABASE=Prettl Elektronik Radeberg GmbH + +OUI:000CD4* + ID_OUI_FROM_DATABASE=Positron Public Safety Systems inc. + +OUI:000CD5* + ID_OUI_FROM_DATABASE=Passave Inc. + +OUI:000CD6* + ID_OUI_FROM_DATABASE=PARTNER TECH + +OUI:000CD7* + ID_OUI_FROM_DATABASE=Nallatech Ltd + +OUI:000CD8* + ID_OUI_FROM_DATABASE=M. K. Juchheim GmbH & Co + +OUI:000CD9* + ID_OUI_FROM_DATABASE=Itcare Co., Ltd + +OUI:000CDA* + ID_OUI_FROM_DATABASE=FreeHand Systems, Inc. + +OUI:000CDB* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:000CDC* + ID_OUI_FROM_DATABASE=BECS Technology, Inc + +OUI:000CDD* + ID_OUI_FROM_DATABASE=AOS technologies AG + +OUI:000CDE* + ID_OUI_FROM_DATABASE=ABB STOTZ-KONTAKT GmbH + +OUI:000CDF* + ID_OUI_FROM_DATABASE=JAI Manufacturing + +OUI:000CE0* + ID_OUI_FROM_DATABASE=Trek Diagnostics Inc. + +OUI:000CE1* + ID_OUI_FROM_DATABASE=The Open Group + +OUI:000CE2* + ID_OUI_FROM_DATABASE=Rolls-Royce + +OUI:000CE3* + ID_OUI_FROM_DATABASE=Option International N.V. + +OUI:000CE4* + ID_OUI_FROM_DATABASE=NeuroCom International, Inc. + +OUI:000CE5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:000CE6* + ID_OUI_FROM_DATABASE=Fortinet Inc. + +OUI:000CE7* + ID_OUI_FROM_DATABASE=MediaTek Inc. + +OUI:000CE8* + ID_OUI_FROM_DATABASE=GuangZhou AnJuBao Co., Ltd + +OUI:000CE9* + ID_OUI_FROM_DATABASE=BLOOMBERG L.P. + +OUI:000CEA* + ID_OUI_FROM_DATABASE=aphona Kommunikationssysteme + +OUI:000CEB* + ID_OUI_FROM_DATABASE=CNMP Networks, Inc. + +OUI:000CEC* + ID_OUI_FROM_DATABASE=Spectracom Corp. + +OUI:000CED* + ID_OUI_FROM_DATABASE=Real Digital Media + +OUI:000CEE* + ID_OUI_FROM_DATABASE=jp-embedded + +OUI:000CEF* + ID_OUI_FROM_DATABASE=Open Networks Engineering Ltd + +OUI:000CF0* + ID_OUI_FROM_DATABASE=M & N GmbH + +OUI:000CF1* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:000CF2* + ID_OUI_FROM_DATABASE=GAMESA Eólica + +OUI:000CF3* + ID_OUI_FROM_DATABASE=CALL IMAGE SA + +OUI:000CF4* + ID_OUI_FROM_DATABASE=AKATSUKI ELECTRIC MFG.CO.,LTD. + +OUI:000CF5* + ID_OUI_FROM_DATABASE=InfoExpress + +OUI:000CF6* + ID_OUI_FROM_DATABASE=Sitecom Europe BV + +OUI:000CF7* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000CF8* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000CF9* + ID_OUI_FROM_DATABASE=Xylem Water Solutions + +OUI:000CFA* + ID_OUI_FROM_DATABASE=Digital Systems Corp + +OUI:000CFB* + ID_OUI_FROM_DATABASE=Korea Network Systems + +OUI:000CFC* + ID_OUI_FROM_DATABASE=S2io Technologies Corp + +OUI:000CFD* + ID_OUI_FROM_DATABASE=Hyundai ImageQuest Co.,Ltd. + +OUI:000CFE* + ID_OUI_FROM_DATABASE=Grand Electronic Co., Ltd + +OUI:000CFF* + ID_OUI_FROM_DATABASE=MRO-TEK Realty Limited + +OUI:000D00* + ID_OUI_FROM_DATABASE=Seaway Networks Inc. + +OUI:000D01* + ID_OUI_FROM_DATABASE=P&E Microcomputer Systems, Inc. + +OUI:000D02* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. + +OUI:000D03* + ID_OUI_FROM_DATABASE=Matrics, Inc. + +OUI:000D04* + ID_OUI_FROM_DATABASE=Foxboro Eckardt Development GmbH + +OUI:000D05* + ID_OUI_FROM_DATABASE=cybernet manufacturing inc. + +OUI:000D06* + ID_OUI_FROM_DATABASE=Compulogic Limited + +OUI:000D07* + ID_OUI_FROM_DATABASE=Calrec Audio Ltd + +OUI:000D08* + ID_OUI_FROM_DATABASE=AboveCable, Inc. + +OUI:000D09* + ID_OUI_FROM_DATABASE=Yuehua(Zhuhai) Electronic CO. LTD + +OUI:000D0A* + ID_OUI_FROM_DATABASE=Barco Projection Systems NV + +OUI:000D0B* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:000D0C* + ID_OUI_FROM_DATABASE=MDI Security Systems + +OUI:000D0D* + ID_OUI_FROM_DATABASE=ITSupported, LLC + +OUI:000D0E* + ID_OUI_FROM_DATABASE=Inqnet Systems, Inc. + +OUI:000D0F* + ID_OUI_FROM_DATABASE=Finlux Ltd + +OUI:000D10* + ID_OUI_FROM_DATABASE=Embedtronics Oy + +OUI:000D11* + ID_OUI_FROM_DATABASE=DENTSPLY - Gendex + +OUI:000D12* + ID_OUI_FROM_DATABASE=AXELL Corporation + +OUI:000D13* + ID_OUI_FROM_DATABASE=Wilhelm Rutenbeck GmbH&Co.KG + +OUI:000D14* + ID_OUI_FROM_DATABASE=Vtech Innovation LP dba Advanced American Telephones + +OUI:000D15* + ID_OUI_FROM_DATABASE=Voipac s.r.o. + +OUI:000D16* + ID_OUI_FROM_DATABASE=UHS Systems Pty Ltd + +OUI:000D17* + ID_OUI_FROM_DATABASE=Turbo Networks Co.Ltd + +OUI:000D18* + ID_OUI_FROM_DATABASE=Mega-Trend Electronics CO., LTD. + +OUI:000D19* + ID_OUI_FROM_DATABASE=ROBE Show lighting + +OUI:000D1A* + ID_OUI_FROM_DATABASE=Mustek System Inc. + +OUI:000D1B* + ID_OUI_FROM_DATABASE=Kyoto Electronics Manufacturing Co., Ltd. + +OUI:000D1C* + ID_OUI_FROM_DATABASE=Amesys Defense + +OUI:000D1D* + ID_OUI_FROM_DATABASE=HIGH-TEK HARNESS ENT. CO., LTD. + +OUI:000D1E* + ID_OUI_FROM_DATABASE=Control Techniques + +OUI:000D1F* + ID_OUI_FROM_DATABASE=AV Digital + +OUI:000D20* + ID_OUI_FROM_DATABASE=ASAHIKASEI TECHNOSYSTEM CO.,LTD. + +OUI:000D21* + ID_OUI_FROM_DATABASE=WISCORE Inc. + +OUI:000D22* + ID_OUI_FROM_DATABASE=Unitronics LTD + +OUI:000D23* + ID_OUI_FROM_DATABASE=Smart Solution, Inc + +OUI:000D24* + ID_OUI_FROM_DATABASE=SENTEC E&E CO., LTD. + +OUI:000D25* + ID_OUI_FROM_DATABASE=SANDEN CORPORATION + +OUI:000D26* + ID_OUI_FROM_DATABASE=Primagraphics Limited + +OUI:000D27* + ID_OUI_FROM_DATABASE=MICROPLEX Printware AG + +OUI:000D28* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000D29* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000D2A* + ID_OUI_FROM_DATABASE=Scanmatic AS + +OUI:000D2B* + ID_OUI_FROM_DATABASE=Racal Instruments + +OUI:000D2C* + ID_OUI_FROM_DATABASE=Net2Edge Limited + +OUI:000D2D* + ID_OUI_FROM_DATABASE=NCT Deutschland GmbH + +OUI:000D2E* + ID_OUI_FROM_DATABASE=Matsushita Avionics Systems Corporation + +OUI:000D2F* + ID_OUI_FROM_DATABASE=AIN Comm.Tech.Co., LTD + +OUI:000D30* + ID_OUI_FROM_DATABASE=IceFyre Semiconductor + +OUI:000D31* + ID_OUI_FROM_DATABASE=Compellent Technologies, Inc. + +OUI:000D32* + ID_OUI_FROM_DATABASE=DispenseSource, Inc. + +OUI:000D33* + ID_OUI_FROM_DATABASE=Prediwave Corp. + +OUI:000D34* + ID_OUI_FROM_DATABASE=Shell International Exploration and Production, Inc. + +OUI:000D35* + ID_OUI_FROM_DATABASE=PAC International Ltd + +OUI:000D36* + ID_OUI_FROM_DATABASE=Wu Han Routon Electronic Co., Ltd + +OUI:000D37* + ID_OUI_FROM_DATABASE=WIPLUG + +OUI:000D38* + ID_OUI_FROM_DATABASE=NISSIN INC. + +OUI:000D39* + ID_OUI_FROM_DATABASE=Network Electronics + +OUI:000D3A* + ID_OUI_FROM_DATABASE=Microsoft Corp. + +OUI:000D3B* + ID_OUI_FROM_DATABASE=Microelectronics Technology Inc. + +OUI:000D3C* + ID_OUI_FROM_DATABASE=i.Tech Dynamic Ltd + +OUI:000D3D* + ID_OUI_FROM_DATABASE=Hammerhead Systems, Inc. + +OUI:000D3E* + ID_OUI_FROM_DATABASE=APLUX Communications Ltd. + +OUI:000D3F* + ID_OUI_FROM_DATABASE=VTI Instruments Corporation + +OUI:000D40* + ID_OUI_FROM_DATABASE=Verint Loronix Video Solutions + +OUI:000D41* + ID_OUI_FROM_DATABASE=Siemens AG ICM MP UC RD IT KLF1 + +OUI:000D42* + ID_OUI_FROM_DATABASE=Newbest Development Limited + +OUI:000D43* + ID_OUI_FROM_DATABASE=DRS Tactical Systems Inc. + +OUI:000D44* + ID_OUI_FROM_DATABASE=Audio BU - Logitech + +OUI:000D45* + ID_OUI_FROM_DATABASE=Tottori SANYO Electric Co., Ltd. + +OUI:000D46* + ID_OUI_FROM_DATABASE=Parker SSD Drives + +OUI:000D47* + ID_OUI_FROM_DATABASE=Collex + +OUI:000D48* + ID_OUI_FROM_DATABASE=AEWIN Technologies Co., Ltd. + +OUI:000D49* + ID_OUI_FROM_DATABASE=Triton Systems of Delaware, Inc. + +OUI:000D4A* + ID_OUI_FROM_DATABASE=Steag ETA-Optik + +OUI:000D4B* + ID_OUI_FROM_DATABASE=Roku, Inc. + +OUI:000D4C* + ID_OUI_FROM_DATABASE=Outline Electronics Ltd. + +OUI:000D4D* + ID_OUI_FROM_DATABASE=Ninelanes + +OUI:000D4E* + ID_OUI_FROM_DATABASE=NDR Co.,LTD. + +OUI:000D4F* + ID_OUI_FROM_DATABASE=Kenwood Corporation + +OUI:000D50* + ID_OUI_FROM_DATABASE=Galazar Networks + +OUI:000D51* + ID_OUI_FROM_DATABASE=DIVR Systems, Inc. + +OUI:000D52* + ID_OUI_FROM_DATABASE=Comart system + +OUI:000D53* + ID_OUI_FROM_DATABASE=Beijing 5w Communication Corp. + +OUI:000D54* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:000D55* + ID_OUI_FROM_DATABASE=SANYCOM Technology Co.,Ltd + +OUI:000D56* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:000D57* + ID_OUI_FROM_DATABASE=Fujitsu I-Network Systems Limited. + +OUI:000D58* + ID_OUI_FROM_DATABASE=Private + +OUI:000D59* + ID_OUI_FROM_DATABASE=Amity Systems, Inc. + +OUI:000D5A* + ID_OUI_FROM_DATABASE=Tiesse SpA + +OUI:000D5B* + ID_OUI_FROM_DATABASE=Smart Empire Investments Limited + +OUI:000D5C* + ID_OUI_FROM_DATABASE=Robert Bosch GmbH, VT-ATMO + +OUI:000D5D* + ID_OUI_FROM_DATABASE=Raritan Computer, Inc + +OUI:000D5E* + ID_OUI_FROM_DATABASE=NEC Personal Products + +OUI:000D5F* + ID_OUI_FROM_DATABASE=Minds Inc + +OUI:000D60* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:000D61* + ID_OUI_FROM_DATABASE=Giga-Byte Technology Co., Ltd. + +OUI:000D62* + ID_OUI_FROM_DATABASE=Funkwerk Dabendorf GmbH + +OUI:000D63* + ID_OUI_FROM_DATABASE=DENT Instruments, Inc. + +OUI:000D64* + ID_OUI_FROM_DATABASE=COMAG Handels AG + +OUI:000D65* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000D66* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000D67* + ID_OUI_FROM_DATABASE=Ericsson + +OUI:000D68* + ID_OUI_FROM_DATABASE=Vinci Systems, Inc. + +OUI:000D69* + ID_OUI_FROM_DATABASE=TMT&D Corporation + +OUI:000D6A* + ID_OUI_FROM_DATABASE=Redwood Technologies LTD + +OUI:000D6B* + ID_OUI_FROM_DATABASE=Mita-Teknik A/S + +OUI:000D6C* + ID_OUI_FROM_DATABASE=M-Audio + +OUI:000D6D* + ID_OUI_FROM_DATABASE=K-Tech Devices Corp. + +OUI:000D6E* + ID_OUI_FROM_DATABASE=K-Patents Oy + +OUI:000D6F* + ID_OUI_FROM_DATABASE=Ember Corporation + +OUI:000D70* + ID_OUI_FROM_DATABASE=Datamax Corporation + +OUI:000D71* + ID_OUI_FROM_DATABASE=boca systems + +OUI:000D72* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:000D73* + ID_OUI_FROM_DATABASE=Technical Support, Inc. + +OUI:000D74* + ID_OUI_FROM_DATABASE=Sand Network Systems, Inc. + +OUI:000D75* + ID_OUI_FROM_DATABASE=Kobian Pte Ltd - Taiwan Branch + +OUI:000D76* + ID_OUI_FROM_DATABASE=Hokuto Denshi Co,. Ltd. + +OUI:000D77* + ID_OUI_FROM_DATABASE=FalconStor Software + +OUI:000D78* + ID_OUI_FROM_DATABASE=Engineering & Security + +OUI:000D79* + ID_OUI_FROM_DATABASE=Dynamic Solutions Co,.Ltd. + +OUI:000D7A* + ID_OUI_FROM_DATABASE=DiGATTO Asia Pacific Pte Ltd + +OUI:000D7B* + ID_OUI_FROM_DATABASE=Consensys Computers Inc. + +OUI:000D7C* + ID_OUI_FROM_DATABASE=Codian Ltd + +OUI:000D7D* + ID_OUI_FROM_DATABASE=Afco Systems + +OUI:000D7E* + ID_OUI_FROM_DATABASE=Axiowave Networks, Inc. + +OUI:000D7F* + ID_OUI_FROM_DATABASE=MIDAS COMMUNICATION TECHNOLOGIES PTE LTD ( Foreign Branch) + +OUI:000D80* + ID_OUI_FROM_DATABASE=Online Development Inc + +OUI:000D81* + ID_OUI_FROM_DATABASE=Pepperl+Fuchs GmbH + +OUI:000D82* + ID_OUI_FROM_DATABASE=PHSNET + +OUI:000D83* + ID_OUI_FROM_DATABASE=Sanmina-SCI Hungary Ltd. + +OUI:000D84* + ID_OUI_FROM_DATABASE=Makus Inc. + +OUI:000D85* + ID_OUI_FROM_DATABASE=Tapwave, Inc. + +OUI:000D86* + ID_OUI_FROM_DATABASE=Huber + Suhner AG + +OUI:000D87* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:000D88* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:000D89* + ID_OUI_FROM_DATABASE=Bils Technology Inc + +OUI:000D8A* + ID_OUI_FROM_DATABASE=Winners Electronics Co., Ltd. + +OUI:000D8B* + ID_OUI_FROM_DATABASE=T&D Corporation + +OUI:000D8C* + ID_OUI_FROM_DATABASE=Shanghai Wedone Digital Ltd. CO. + +OUI:000D8D* + ID_OUI_FROM_DATABASE=Prosoft Technology, Inc + +OUI:000D8E* + ID_OUI_FROM_DATABASE=Koden Electronics Co., Ltd. + +OUI:000D8F* + ID_OUI_FROM_DATABASE=King Tsushin Kogyo Co., LTD. + +OUI:000D90* + ID_OUI_FROM_DATABASE=Factum Electronics AB + +OUI:000D91* + ID_OUI_FROM_DATABASE=Eclipse (HQ Espana) S.L. + +OUI:000D92* + ID_OUI_FROM_DATABASE=ARIMA Communications Corp. + +OUI:000D93* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:000D94* + ID_OUI_FROM_DATABASE=AFAR Communications,Inc + +OUI:000D95* + ID_OUI_FROM_DATABASE=Opti-cell, Inc. + +OUI:000D96* + ID_OUI_FROM_DATABASE=Vtera Technology Inc. + +OUI:000D97* + ID_OUI_FROM_DATABASE=ABB Inc./Tropos + +OUI:000D98* + ID_OUI_FROM_DATABASE=S.W.A.C. Schmitt-Walter Automation Consult GmbH + +OUI:000D99* + ID_OUI_FROM_DATABASE=Orbital Sciences Corp.; Launch Systems Group + +OUI:000D9A* + ID_OUI_FROM_DATABASE=INFOTEC LTD + +OUI:000D9B* + ID_OUI_FROM_DATABASE=Heraeus Electro-Nite International N.V. + +OUI:000D9C* + ID_OUI_FROM_DATABASE=Elan GmbH & Co KG + +OUI:000D9D* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:000D9E* + ID_OUI_FROM_DATABASE=TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd. + +OUI:000D9F* + ID_OUI_FROM_DATABASE=RF Micro Devices + +OUI:000DA0* + ID_OUI_FROM_DATABASE=NEDAP N.V. + +OUI:000DA1* + ID_OUI_FROM_DATABASE=MIRAE ITS Co.,LTD. + +OUI:000DA2* + ID_OUI_FROM_DATABASE=Infrant Technologies, Inc. + +OUI:000DA3* + ID_OUI_FROM_DATABASE=Emerging Technologies Limited + +OUI:000DA4* + ID_OUI_FROM_DATABASE=DOSCH & AMAND SYSTEMS AG + +OUI:000DA5* + ID_OUI_FROM_DATABASE=Fabric7 Systems, Inc + +OUI:000DA6* + ID_OUI_FROM_DATABASE=Universal Switching Corporation + +OUI:000DA7* + ID_OUI_FROM_DATABASE=Private + +OUI:000DA8* + ID_OUI_FROM_DATABASE=Teletronics Technology Corporation + +OUI:000DA9* + ID_OUI_FROM_DATABASE=T.E.A.M. S.L. + +OUI:000DAA* + ID_OUI_FROM_DATABASE=S.A.Tehnology co.,Ltd. + +OUI:000DAB* + ID_OUI_FROM_DATABASE=Parker Hannifin GmbH Electromechanical Division Europe + +OUI:000DAC* + ID_OUI_FROM_DATABASE=Japan CBM Corporation + +OUI:000DAD* + ID_OUI_FROM_DATABASE=Dataprobe, Inc. + +OUI:000DAE* + ID_OUI_FROM_DATABASE=SAMSUNG HEAVY INDUSTRIES CO., LTD. + +OUI:000DAF* + ID_OUI_FROM_DATABASE=Plexus Corp (UK) Ltd + +OUI:000DB0* + ID_OUI_FROM_DATABASE=Olym-tech Co.,Ltd. + +OUI:000DB1* + ID_OUI_FROM_DATABASE=Japan Network Service Co., Ltd. + +OUI:000DB2* + ID_OUI_FROM_DATABASE=Ammasso, Inc. + +OUI:000DB3* + ID_OUI_FROM_DATABASE=SDO Communication Corperation + +OUI:000DB4* + ID_OUI_FROM_DATABASE=Stormshield + +OUI:000DB5* + ID_OUI_FROM_DATABASE=GLOBALSAT TECHNOLOGY CORPORATION + +OUI:000DB6* + ID_OUI_FROM_DATABASE=Broadcom + +OUI:000DB7* + ID_OUI_FROM_DATABASE=SANKO ELECTRIC CO,.LTD + +OUI:000DB8* + ID_OUI_FROM_DATABASE=SCHILLER AG + +OUI:000DB9* + ID_OUI_FROM_DATABASE=PC Engines GmbH + +OUI:000DBA* + ID_OUI_FROM_DATABASE=Océ Document Technologies GmbH + +OUI:000DBB* + ID_OUI_FROM_DATABASE=Nippon Dentsu Co.,Ltd. + +OUI:000DBC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000DBD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000DBE* + ID_OUI_FROM_DATABASE=Bel Fuse Europe Ltd.,UK + +OUI:000DBF* + ID_OUI_FROM_DATABASE=TekTone Sound & Signal Mfg., Inc. + +OUI:000DC0* + ID_OUI_FROM_DATABASE=Spagat AS + +OUI:000DC1* + ID_OUI_FROM_DATABASE=SafeWeb Inc + +OUI:000DC2* + ID_OUI_FROM_DATABASE=Private + +OUI:000DC3* + ID_OUI_FROM_DATABASE=First Communication, Inc. + +OUI:000DC4* + ID_OUI_FROM_DATABASE=Emcore Corporation + +OUI:000DC5* + ID_OUI_FROM_DATABASE=EchoStar Global B.V. + +OUI:000DC6* + ID_OUI_FROM_DATABASE=DigiRose Technology Co., Ltd. + +OUI:000DC7* + ID_OUI_FROM_DATABASE=COSMIC ENGINEERING INC. + +OUI:000DC8* + ID_OUI_FROM_DATABASE=AirMagnet, Inc + +OUI:000DC9* + ID_OUI_FROM_DATABASE=THALES Elektronik Systeme GmbH + +OUI:000DCA* + ID_OUI_FROM_DATABASE=Tait Electronics + +OUI:000DCB* + ID_OUI_FROM_DATABASE=Petcomkorea Co., Ltd. + +OUI:000DCC* + ID_OUI_FROM_DATABASE=NEOSMART Corp. + +OUI:000DCD* + ID_OUI_FROM_DATABASE=GROUPE TXCOM + +OUI:000DCE* + ID_OUI_FROM_DATABASE=Dynavac Technology Pte Ltd + +OUI:000DCF* + ID_OUI_FROM_DATABASE=Cidra Corp. + +OUI:000DD0* + ID_OUI_FROM_DATABASE=TetraTec Instruments GmbH + +OUI:000DD1* + ID_OUI_FROM_DATABASE=Stryker Corporation + +OUI:000DD2* + ID_OUI_FROM_DATABASE=Simrad Optronics ASA + +OUI:000DD3* + ID_OUI_FROM_DATABASE=SAMWOO Telecommunication Co.,Ltd. + +OUI:000DD4* + ID_OUI_FROM_DATABASE=Symantec Corporation + +OUI:000DD5* + ID_OUI_FROM_DATABASE=O'RITE TECHNOLOGY CO.,LTD + +OUI:000DD6* + ID_OUI_FROM_DATABASE=ITI LTD + +OUI:000DD7* + ID_OUI_FROM_DATABASE=Bright + +OUI:000DD8* + ID_OUI_FROM_DATABASE=BBN + +OUI:000DD9* + ID_OUI_FROM_DATABASE=Anton Paar GmbH + +OUI:000DDA* + ID_OUI_FROM_DATABASE=ALLIED TELESIS K.K. + +OUI:000DDB* + ID_OUI_FROM_DATABASE=AIRWAVE TECHNOLOGIES INC. + +OUI:000DDC* + ID_OUI_FROM_DATABASE=VAC + +OUI:000DDD* + ID_OUI_FROM_DATABASE=Profilo Telra Elektronik Sanayi ve Ticaret. A.Ş + +OUI:000DDE* + ID_OUI_FROM_DATABASE=Joyteck Co., Ltd. + +OUI:000DDF* + ID_OUI_FROM_DATABASE=Japan Image & Network Inc. + +OUI:000DE0* + ID_OUI_FROM_DATABASE=ICPDAS Co.,LTD + +OUI:000DE1* + ID_OUI_FROM_DATABASE=Control Products, Inc. + +OUI:000DE2* + ID_OUI_FROM_DATABASE=CMZ Sistemi Elettronici + +OUI:000DE3* + ID_OUI_FROM_DATABASE=AT Sweden AB + +OUI:000DE4* + ID_OUI_FROM_DATABASE=DIGINICS, Inc. + +OUI:000DE5* + ID_OUI_FROM_DATABASE=Samsung Thales + +OUI:000DE6* + ID_OUI_FROM_DATABASE=YOUNGBO ENGINEERING CO.,LTD + +OUI:000DE7* + ID_OUI_FROM_DATABASE=Snap-on OEM Group + +OUI:000DE8* + ID_OUI_FROM_DATABASE=Nasaco Electronics Pte. Ltd + +OUI:000DE9* + ID_OUI_FROM_DATABASE=Napatech Aps + +OUI:000DEA* + ID_OUI_FROM_DATABASE=Kingtel Telecommunication Corp. + +OUI:000DEB* + ID_OUI_FROM_DATABASE=CompXs Limited + +OUI:000DEC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000DED* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000DEE* + ID_OUI_FROM_DATABASE=Andrew RF Power Amplifier Group + +OUI:000DEF* + ID_OUI_FROM_DATABASE=Soc. Coop. Bilanciai + +OUI:000DF0* + ID_OUI_FROM_DATABASE=QCOM TECHNOLOGY INC. + +OUI:000DF1* + ID_OUI_FROM_DATABASE=IONIX INC. + +OUI:000DF2* + ID_OUI_FROM_DATABASE=Private + +OUI:000DF3* + ID_OUI_FROM_DATABASE=Asmax Solutions + +OUI:000DF4* + ID_OUI_FROM_DATABASE=Watertek Co. + +OUI:000DF5* + ID_OUI_FROM_DATABASE=Teletronics International Inc. + +OUI:000DF6* + ID_OUI_FROM_DATABASE=Technology Thesaurus Corp. + +OUI:000DF7* + ID_OUI_FROM_DATABASE=Space Dynamics Lab + +OUI:000DF8* + ID_OUI_FROM_DATABASE=ORGA Kartensysteme GmbH + +OUI:000DF9* + ID_OUI_FROM_DATABASE=NDS Limited + +OUI:000DFA* + ID_OUI_FROM_DATABASE=Micro Control Systems Ltd. + +OUI:000DFB* + ID_OUI_FROM_DATABASE=Komax AG + +OUI:000DFC* + ID_OUI_FROM_DATABASE=ITFOR Inc. + +OUI:000DFD* + ID_OUI_FROM_DATABASE=Huges Hi-Tech Inc., + +OUI:000DFE* + ID_OUI_FROM_DATABASE=Hauppauge Computer Works, Inc. + +OUI:000DFF* + ID_OUI_FROM_DATABASE=CHENMING MOLD INDUSTRY CORP. + +OUI:000E00* + ID_OUI_FROM_DATABASE=Atrie + +OUI:000E01* + ID_OUI_FROM_DATABASE=ASIP Technologies Inc. + +OUI:000E02* + ID_OUI_FROM_DATABASE=Advantech AMT Inc. + +OUI:000E03* + ID_OUI_FROM_DATABASE=Emulex Corporation + +OUI:000E04* + ID_OUI_FROM_DATABASE=CMA/Microdialysis AB + +OUI:000E05* + ID_OUI_FROM_DATABASE=WIRELESS MATRIX CORP. + +OUI:000E06* + ID_OUI_FROM_DATABASE=Team Simoco Ltd + +OUI:000E07* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:000E08* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:000E09* + ID_OUI_FROM_DATABASE=Shenzhen Coship Software Co.,LTD. + +OUI:000E0A* + ID_OUI_FROM_DATABASE=SAKUMA DESIGN OFFICE + +OUI:000E0B* + ID_OUI_FROM_DATABASE=Netac Technology Co., Ltd. + +OUI:000E0C* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:000E0D* + ID_OUI_FROM_DATABASE=Hesch Schröder GmbH + +OUI:000E0E* + ID_OUI_FROM_DATABASE=ESA elettronica S.P.A. + +OUI:000E0F* + ID_OUI_FROM_DATABASE=ERMME + +OUI:000E10* + ID_OUI_FROM_DATABASE=C-guys, Inc. + +OUI:000E11* + ID_OUI_FROM_DATABASE=BDT Büro und Datentechnik GmbH & Co.KG + +OUI:000E12* + ID_OUI_FROM_DATABASE=Adaptive Micro Systems Inc. + +OUI:000E13* + ID_OUI_FROM_DATABASE=Accu-Sort Systems inc. + +OUI:000E14* + ID_OUI_FROM_DATABASE=Visionary Solutions, Inc. + +OUI:000E15* + ID_OUI_FROM_DATABASE=Tadlys LTD + +OUI:000E16* + ID_OUI_FROM_DATABASE=SouthWing S.L. + +OUI:000E17* + ID_OUI_FROM_DATABASE=Private + +OUI:000E18* + ID_OUI_FROM_DATABASE=MyA Technology + +OUI:000E19* + ID_OUI_FROM_DATABASE=LogicaCMG Pty Ltd + +OUI:000E1A* + ID_OUI_FROM_DATABASE=JPS Communications + +OUI:000E1B* + ID_OUI_FROM_DATABASE=IAV GmbH + +OUI:000E1C* + ID_OUI_FROM_DATABASE=Hach Company + +OUI:000E1D* + ID_OUI_FROM_DATABASE=ARION Technology Inc. + +OUI:000E1E* + ID_OUI_FROM_DATABASE=QLogic Corporation + +OUI:000E1F* + ID_OUI_FROM_DATABASE=TCL Networks Equipment Co., Ltd. + +OUI:000E20* + ID_OUI_FROM_DATABASE=ACCESS Systems Americas, Inc. + +OUI:000E21* + ID_OUI_FROM_DATABASE=MTU Friedrichshafen GmbH + +OUI:000E22* + ID_OUI_FROM_DATABASE=Private + +OUI:000E23* + ID_OUI_FROM_DATABASE=Incipient, Inc. + +OUI:000E24* + ID_OUI_FROM_DATABASE=Huwell Technology Inc. + +OUI:000E25* + ID_OUI_FROM_DATABASE=Hannae Technology Co., Ltd + +OUI:000E26* + ID_OUI_FROM_DATABASE=Gincom Technology Corp. + +OUI:000E27* + ID_OUI_FROM_DATABASE=Crere Networks, Inc. + +OUI:000E28* + ID_OUI_FROM_DATABASE=Dynamic Ratings P/L + +OUI:000E29* + ID_OUI_FROM_DATABASE=Shester Communications Inc + +OUI:000E2A* + ID_OUI_FROM_DATABASE=Private + +OUI:000E2B* + ID_OUI_FROM_DATABASE=Safari Technologies + +OUI:000E2C* + ID_OUI_FROM_DATABASE=Netcodec co. + +OUI:000E2D* + ID_OUI_FROM_DATABASE=Hyundai Digital Technology Co.,Ltd. + +OUI:000E2E* + ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. + +OUI:000E2F* + ID_OUI_FROM_DATABASE=Roche Diagnostics GmbH + +OUI:000E30* + ID_OUI_FROM_DATABASE=AERAS Networks, Inc. + +OUI:000E31* + ID_OUI_FROM_DATABASE=Olympus Soft Imaging Solutions GmbH + +OUI:000E32* + ID_OUI_FROM_DATABASE=Kontron Medical + +OUI:000E33* + ID_OUI_FROM_DATABASE=Shuko Electronics Co.,Ltd + +OUI:000E34* + ID_OUI_FROM_DATABASE=NexGen City, LP + +OUI:000E35* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:000E36* + ID_OUI_FROM_DATABASE=HEINESYS, Inc. + +OUI:000E37* + ID_OUI_FROM_DATABASE=Harms & Wende GmbH & Co.KG + +OUI:000E38* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000E39* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000E3A* + ID_OUI_FROM_DATABASE=Cirrus Logic + +OUI:000E3B* + ID_OUI_FROM_DATABASE=Hawking Technologies, Inc. + +OUI:000E3C* + ID_OUI_FROM_DATABASE=Transact Technologies Inc + +OUI:000E3D* + ID_OUI_FROM_DATABASE=Televic N.V. + +OUI:000E3E* + ID_OUI_FROM_DATABASE=Sun Optronics Inc + +OUI:000E3F* + ID_OUI_FROM_DATABASE=Soronti, Inc. + +OUI:000E40* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000E41* + ID_OUI_FROM_DATABASE=NIHON MECHATRONICS CO.,LTD. + +OUI:000E42* + ID_OUI_FROM_DATABASE=Motic Incoporation Ltd. + +OUI:000E43* + ID_OUI_FROM_DATABASE=G-Tek Electronics Sdn. Bhd. + +OUI:000E44* + ID_OUI_FROM_DATABASE=Digital 5, Inc. + +OUI:000E45* + ID_OUI_FROM_DATABASE=Beijing Newtry Electronic Technology Ltd + +OUI:000E46* + ID_OUI_FROM_DATABASE=Niigata Seimitsu Co.,Ltd. + +OUI:000E47* + ID_OUI_FROM_DATABASE=NCI System Co.,Ltd. + +OUI:000E48* + ID_OUI_FROM_DATABASE=Lipman TransAction Solutions + +OUI:000E49* + ID_OUI_FROM_DATABASE=Forsway Scandinavia AB + +OUI:000E4A* + ID_OUI_FROM_DATABASE=Changchun Huayu WEBPAD Co.,LTD + +OUI:000E4B* + ID_OUI_FROM_DATABASE=atrium c and i + +OUI:000E4C* + ID_OUI_FROM_DATABASE=Bermai Inc. + +OUI:000E4D* + ID_OUI_FROM_DATABASE=Numesa Inc. + +OUI:000E4E* + ID_OUI_FROM_DATABASE=Waveplus Technology Co., Ltd. + +OUI:000E4F* + ID_OUI_FROM_DATABASE=Trajet GmbH + +OUI:000E50* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium + +OUI:000E51* + ID_OUI_FROM_DATABASE=tecna elettronica srl + +OUI:000E52* + ID_OUI_FROM_DATABASE=Optium Corporation + +OUI:000E53* + ID_OUI_FROM_DATABASE=AV TECH CORPORATION + +OUI:000E54* + ID_OUI_FROM_DATABASE=AlphaCell Wireless Ltd. + +OUI:000E55* + ID_OUI_FROM_DATABASE=AUVITRAN + +OUI:000E56* + ID_OUI_FROM_DATABASE=4G Systems GmbH & Co. KG + +OUI:000E57* + ID_OUI_FROM_DATABASE=Iworld Networking, Inc. + +OUI:000E58* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:000E59* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:000E5A* + ID_OUI_FROM_DATABASE=TELEFIELD inc. + +OUI:000E5B* + ID_OUI_FROM_DATABASE=ParkerVision - Direct2Data + +OUI:000E5C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:000E5D* + ID_OUI_FROM_DATABASE=Triple Play Technologies A/S + +OUI:000E5E* + ID_OUI_FROM_DATABASE=Raisecom Technology + +OUI:000E5F* + ID_OUI_FROM_DATABASE=activ-net GmbH & Co. KG + +OUI:000E60* + ID_OUI_FROM_DATABASE=360SUN Digital Broadband Corporation + +OUI:000E61* + ID_OUI_FROM_DATABASE=MICROTROL LIMITED + +OUI:000E62* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000E63* + ID_OUI_FROM_DATABASE=Lemke Diagnostics GmbH + +OUI:000E64* + ID_OUI_FROM_DATABASE=Elphel, Inc + +OUI:000E65* + ID_OUI_FROM_DATABASE=TransCore + +OUI:000E66* + ID_OUI_FROM_DATABASE=Hitachi Industry & Control Solutions, Ltd. + +OUI:000E67* + ID_OUI_FROM_DATABASE=Eltis Microelectronics Ltd. + +OUI:000E68* + ID_OUI_FROM_DATABASE=E-TOP Network Technology Inc. + +OUI:000E69* + ID_OUI_FROM_DATABASE=China Electric Power Research Institute + +OUI:000E6A* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:000E6B* + ID_OUI_FROM_DATABASE=Janitza electronics GmbH + +OUI:000E6C* + ID_OUI_FROM_DATABASE=Device Drivers Limited + +OUI:000E6D* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:000E6E* + ID_OUI_FROM_DATABASE=MAT S.A. (Mircrelec Advanced Technology) + +OUI:000E6F* + ID_OUI_FROM_DATABASE=IRIS Corporation Berhad + +OUI:000E70* + ID_OUI_FROM_DATABASE=in2 Networks + +OUI:000E71* + ID_OUI_FROM_DATABASE=Gemstar Technology Development Ltd. + +OUI:000E72* + ID_OUI_FROM_DATABASE=CTS electronics + +OUI:000E73* + ID_OUI_FROM_DATABASE=Tpack A/S + +OUI:000E74* + ID_OUI_FROM_DATABASE=Solar Telecom. Tech + +OUI:000E75* + ID_OUI_FROM_DATABASE=New York Air Brake Corp. + +OUI:000E76* + ID_OUI_FROM_DATABASE=GEMSOC INNOVISION INC. + +OUI:000E77* + ID_OUI_FROM_DATABASE=Decru, Inc. + +OUI:000E78* + ID_OUI_FROM_DATABASE=Amtelco + +OUI:000E79* + ID_OUI_FROM_DATABASE=Ample Communications Inc. + +OUI:000E7A* + ID_OUI_FROM_DATABASE=GemWon Communications Co., Ltd. + +OUI:000E7B* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:000E7C* + ID_OUI_FROM_DATABASE=Televes S.A. + +OUI:000E7D* + ID_OUI_FROM_DATABASE=Electronics Line 3000 Ltd. + +OUI:000E7E* + ID_OUI_FROM_DATABASE=ionSign Oy + +OUI:000E7F* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:000E80* + ID_OUI_FROM_DATABASE=Thomson Technology Inc + +OUI:000E81* + ID_OUI_FROM_DATABASE=Devicescape Software, Inc. + +OUI:000E82* + ID_OUI_FROM_DATABASE=Commtech Wireless + +OUI:000E83* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000E84* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000E85* + ID_OUI_FROM_DATABASE=Catalyst Enterprises, Inc. + +OUI:000E86* + ID_OUI_FROM_DATABASE=Alcatel North America + +OUI:000E87* + ID_OUI_FROM_DATABASE=adp Gauselmann GmbH + +OUI:000E88* + ID_OUI_FROM_DATABASE=VIDEOTRON CORP. + +OUI:000E89* + ID_OUI_FROM_DATABASE=CLEMATIC + +OUI:000E8A* + ID_OUI_FROM_DATABASE=Avara Technologies Pty. Ltd. + +OUI:000E8B* + ID_OUI_FROM_DATABASE=Astarte Technology Co, Ltd. + +OUI:000E8C* + ID_OUI_FROM_DATABASE=Siemens AG + +OUI:000E8D* + ID_OUI_FROM_DATABASE=Systems in Progress Holding GmbH + +OUI:000E8E* + ID_OUI_FROM_DATABASE=SparkLAN Communications, Inc. + +OUI:000E8F* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:000E90* + ID_OUI_FROM_DATABASE=PONICO CORP. + +OUI:000E91* + ID_OUI_FROM_DATABASE=Navico Auckland Ltd + +OUI:000E92* + ID_OUI_FROM_DATABASE=Open Telecom + +OUI:000E93* + ID_OUI_FROM_DATABASE=Milénio 3 Sistemas Electrónicos, Lda. + +OUI:000E94* + ID_OUI_FROM_DATABASE=Maas International BV + +OUI:000E95* + ID_OUI_FROM_DATABASE=Fujiya Denki Seisakusho Co.,Ltd. + +OUI:000E96* + ID_OUI_FROM_DATABASE=Cubic Defense Applications, Inc. + +OUI:000E97* + ID_OUI_FROM_DATABASE=Ultracker Technology CO., Inc + +OUI:000E98* + ID_OUI_FROM_DATABASE=HME Clear-Com LTD. + +OUI:000E99* + ID_OUI_FROM_DATABASE=Spectrum Digital, Inc + +OUI:000E9A* + ID_OUI_FROM_DATABASE=BOE TECHNOLOGY GROUP CO.,LTD + +OUI:000E9B* + ID_OUI_FROM_DATABASE=Ambit Microsystems Corporation + +OUI:000E9C* + ID_OUI_FROM_DATABASE=Benchmark Electronics + +OUI:000E9D* + ID_OUI_FROM_DATABASE=Tiscali UK Ltd + +OUI:000E9E* + ID_OUI_FROM_DATABASE=Topfield Co., Ltd + +OUI:000E9F* + ID_OUI_FROM_DATABASE=TEMIC SDS GmbH + +OUI:000EA0* + ID_OUI_FROM_DATABASE=NetKlass Technology Inc. + +OUI:000EA1* + ID_OUI_FROM_DATABASE=Formosa Teletek Corporation + +OUI:000EA2* + ID_OUI_FROM_DATABASE=McAfee, Inc + +OUI:000EA3* + ID_OUI_FROM_DATABASE=CNCR-IT CO.,LTD,HangZhou P.R.CHINA + +OUI:000EA4* + ID_OUI_FROM_DATABASE=Quantum Corp. + +OUI:000EA5* + ID_OUI_FROM_DATABASE=BLIP Systems + +OUI:000EA6* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:000EA7* + ID_OUI_FROM_DATABASE=Endace Technology + +OUI:000EA8* + ID_OUI_FROM_DATABASE=United Technologists Europe Limited + +OUI:000EA9* + ID_OUI_FROM_DATABASE=Shanghai Xun Shi Communications Equipment Ltd. Co. + +OUI:000EAA* + ID_OUI_FROM_DATABASE=Scalent Systems, Inc. + +OUI:000EAB* + ID_OUI_FROM_DATABASE=Cray Inc + +OUI:000EAC* + ID_OUI_FROM_DATABASE=MINTRON ENTERPRISE CO., LTD. + +OUI:000EAD* + ID_OUI_FROM_DATABASE=Metanoia Technologies, Inc. + +OUI:000EAE* + ID_OUI_FROM_DATABASE=GAWELL TECHNOLOGIES CORP. + +OUI:000EAF* + ID_OUI_FROM_DATABASE=CASTEL + +OUI:000EB0* + ID_OUI_FROM_DATABASE=Solutions Radio BV + +OUI:000EB1* + ID_OUI_FROM_DATABASE=Newcotech,Ltd + +OUI:000EB2* + ID_OUI_FROM_DATABASE=Micro-Research Finland Oy + +OUI:000EB3* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:000EB4* + ID_OUI_FROM_DATABASE=GUANGZHOU GAOKE COMMUNICATIONS TECHNOLOGY CO.LTD. + +OUI:000EB5* + ID_OUI_FROM_DATABASE=Ecastle Electronics Co., Ltd. + +OUI:000EB6* + ID_OUI_FROM_DATABASE=Riverbed Technology, Inc. + +OUI:000EB7* + ID_OUI_FROM_DATABASE=Knovative, Inc. + +OUI:000EB8* + ID_OUI_FROM_DATABASE=Iiga co.,Ltd + +OUI:000EB9* + ID_OUI_FROM_DATABASE=HASHIMOTO Electronics Industry Co.,Ltd. + +OUI:000EBA* + ID_OUI_FROM_DATABASE=HANMI SEMICONDUCTOR CO., LTD. + +OUI:000EBB* + ID_OUI_FROM_DATABASE=Everbee Networks + +OUI:000EBC* + ID_OUI_FROM_DATABASE=Paragon Fidelity GmbH + +OUI:000EBD* + ID_OUI_FROM_DATABASE=Burdick, a Quinton Compny + +OUI:000EBE* + ID_OUI_FROM_DATABASE=B&B Electronics Manufacturing Co. + +OUI:000EBF* + ID_OUI_FROM_DATABASE=Remsdaq Limited + +OUI:000EC0* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000EC1* + ID_OUI_FROM_DATABASE=MYNAH Technologies + +OUI:000EC2* + ID_OUI_FROM_DATABASE=Lowrance Electronics, Inc. + +OUI:000EC3* + ID_OUI_FROM_DATABASE=Logic Controls, Inc. + +OUI:000EC4* + ID_OUI_FROM_DATABASE=Iskra Transmission d.d. + +OUI:000EC5* + ID_OUI_FROM_DATABASE=Digital Multitools Inc + +OUI:000EC6* + ID_OUI_FROM_DATABASE=ASIX ELECTRONICS CORP. + +OUI:000EC7* + ID_OUI_FROM_DATABASE=Motorola Korea + +OUI:000EC8* + ID_OUI_FROM_DATABASE=Zoran Corporation + +OUI:000EC9* + ID_OUI_FROM_DATABASE=YOKO Technology Corp. + +OUI:000ECA* + ID_OUI_FROM_DATABASE=WTSS Inc + +OUI:000ECB* + ID_OUI_FROM_DATABASE=VineSys Technology + +OUI:000ECC* + ID_OUI_FROM_DATABASE=Tableau, LLC + +OUI:000ECD* + ID_OUI_FROM_DATABASE=SKOV A/S + +OUI:000ECE* + ID_OUI_FROM_DATABASE=S.I.T.T.I. S.p.A. + +OUI:000ECF* + ID_OUI_FROM_DATABASE=PROFIBUS Nutzerorganisation e.V. + +OUI:000ED0* + ID_OUI_FROM_DATABASE=Privaris, Inc. + +OUI:000ED1* + ID_OUI_FROM_DATABASE=Osaka Micro Computer. + +OUI:000ED2* + ID_OUI_FROM_DATABASE=Filtronic plc + +OUI:000ED3* + ID_OUI_FROM_DATABASE=Epicenter, Inc. + +OUI:000ED4* + ID_OUI_FROM_DATABASE=CRESITT INDUSTRIE + +OUI:000ED5* + ID_OUI_FROM_DATABASE=COPAN Systems Inc. + +OUI:000ED6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000ED7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000ED8* + ID_OUI_FROM_DATABASE=Positron Access Solutions Corp + +OUI:000ED9* + ID_OUI_FROM_DATABASE=Aksys, Ltd. + +OUI:000EDA* + ID_OUI_FROM_DATABASE=C-TECH UNITED CORP. + +OUI:000EDB* + ID_OUI_FROM_DATABASE=XiNCOM Corp. + +OUI:000EDC* + ID_OUI_FROM_DATABASE=Tellion INC. + +OUI:000EDD* + ID_OUI_FROM_DATABASE=SHURE INCORPORATED + +OUI:000EDE* + ID_OUI_FROM_DATABASE=REMEC, Inc. + +OUI:000EDF* + ID_OUI_FROM_DATABASE=PLX Technology + +OUI:000EE0* + ID_OUI_FROM_DATABASE=Mcharge + +OUI:000EE1* + ID_OUI_FROM_DATABASE=ExtremeSpeed Inc. + +OUI:000EE2* + ID_OUI_FROM_DATABASE=Custom Engineering + +OUI:000EE3* + ID_OUI_FROM_DATABASE=Chiyu Technology Co.,Ltd + +OUI:000EE4* + ID_OUI_FROM_DATABASE=BOE TECHNOLOGY GROUP CO.,LTD + +OUI:000EE5* + ID_OUI_FROM_DATABASE=bitWallet, Inc. + +OUI:000EE6* + ID_OUI_FROM_DATABASE=Adimos Systems LTD + +OUI:000EE7* + ID_OUI_FROM_DATABASE=AAC ELECTRONICS CORP. + +OUI:000EE8* + ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. + +OUI:000EE9* + ID_OUI_FROM_DATABASE=WayTech Development, Inc. + +OUI:000EEA* + ID_OUI_FROM_DATABASE=Shadong Luneng Jicheng Electronics,Co.,Ltd + +OUI:000EEB* + ID_OUI_FROM_DATABASE=Sandmartin(zhong shan)Electronics Co.,Ltd + +OUI:000EEC* + ID_OUI_FROM_DATABASE=Orban + +OUI:000EED* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:000EEE* + ID_OUI_FROM_DATABASE=Muco Industrie BV + +OUI:000EEF* + ID_OUI_FROM_DATABASE=Private + +OUI:000EF0* + ID_OUI_FROM_DATABASE=Festo AG & Co. KG + +OUI:000EF1* + ID_OUI_FROM_DATABASE=EZQUEST INC. + +OUI:000EF2* + ID_OUI_FROM_DATABASE=Infinico Corporation + +OUI:000EF3* + ID_OUI_FROM_DATABASE=Smartlabs, Inc. + +OUI:000EF4* + ID_OUI_FROM_DATABASE=Kasda Networks Inc + +OUI:000EF5* + ID_OUI_FROM_DATABASE=iPAC Technology Co., Ltd. + +OUI:000EF6* + ID_OUI_FROM_DATABASE=E-TEN Information Systems Co., Ltd. + +OUI:000EF7* + ID_OUI_FROM_DATABASE=Vulcan Portals Inc + +OUI:000EF8* + ID_OUI_FROM_DATABASE=SBC ASI + +OUI:000EF9* + ID_OUI_FROM_DATABASE=REA Elektronik GmbH + +OUI:000EFA* + ID_OUI_FROM_DATABASE=Optoway Technology Incorporation + +OUI:000EFB* + ID_OUI_FROM_DATABASE=Macey Enterprises + +OUI:000EFC* + ID_OUI_FROM_DATABASE=JTAG Technologies B.V. + +OUI:000EFD* + ID_OUI_FROM_DATABASE=FUJINON CORPORATION + +OUI:000EFE* + ID_OUI_FROM_DATABASE=EndRun Technologies LLC + +OUI:000EFF* + ID_OUI_FROM_DATABASE=Megasolution,Inc. + +OUI:000F00* + ID_OUI_FROM_DATABASE=Legra Systems, Inc. + +OUI:000F01* + ID_OUI_FROM_DATABASE=DIGITALKS INC + +OUI:000F02* + ID_OUI_FROM_DATABASE=Digicube Technology Co., Ltd + +OUI:000F03* + ID_OUI_FROM_DATABASE=COM&C CO., LTD + +OUI:000F04* + ID_OUI_FROM_DATABASE=cim-usa inc + +OUI:000F05* + ID_OUI_FROM_DATABASE=3B SYSTEM INC. + +OUI:000F06* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000F07* + ID_OUI_FROM_DATABASE=Mangrove Systems, Inc. + +OUI:000F08* + ID_OUI_FROM_DATABASE=Indagon Oy + +OUI:000F09* + ID_OUI_FROM_DATABASE=Private + +OUI:000F0A* + ID_OUI_FROM_DATABASE=Clear Edge Networks + +OUI:000F0B* + ID_OUI_FROM_DATABASE=Kentima Technologies AB + +OUI:000F0C* + ID_OUI_FROM_DATABASE=SYNCHRONIC ENGINEERING + +OUI:000F0D* + ID_OUI_FROM_DATABASE=Hunt Electronic Co., Ltd. + +OUI:000F0E* + ID_OUI_FROM_DATABASE=WaveSplitter Technologies, Inc. + +OUI:000F0F* + ID_OUI_FROM_DATABASE=Real ID Technology Co., Ltd. + +OUI:000F10* + ID_OUI_FROM_DATABASE=RDM Corporation + +OUI:000F11* + ID_OUI_FROM_DATABASE=Prodrive B.V. + +OUI:000F12* + ID_OUI_FROM_DATABASE=Panasonic Europe Ltd. + +OUI:000F13* + ID_OUI_FROM_DATABASE=Nisca corporation + +OUI:000F14* + ID_OUI_FROM_DATABASE=Mindray Co., Ltd. + +OUI:000F15* + ID_OUI_FROM_DATABASE=Icotera A/S + +OUI:000F16* + ID_OUI_FROM_DATABASE=JAY HOW TECHNOLOGY CO., + +OUI:000F17* + ID_OUI_FROM_DATABASE=Insta Elektro GmbH + +OUI:000F18* + ID_OUI_FROM_DATABASE=Industrial Control Systems + +OUI:000F19* + ID_OUI_FROM_DATABASE=Boston Scientific + +OUI:000F1A* + ID_OUI_FROM_DATABASE=Gaming Support B.V. + +OUI:000F1B* + ID_OUI_FROM_DATABASE=Ego Systems Inc. + +OUI:000F1C* + ID_OUI_FROM_DATABASE=DigitAll World Co., Ltd + +OUI:000F1D* + ID_OUI_FROM_DATABASE=Cosmo Techs Co., Ltd. + +OUI:000F1E* + ID_OUI_FROM_DATABASE=Chengdu KT Electric Co.of High & New Technology + +OUI:000F1F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:000F20* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:000F21* + ID_OUI_FROM_DATABASE=Scientific Atlanta, Inc + +OUI:000F22* + ID_OUI_FROM_DATABASE=Helius, Inc. + +OUI:000F23* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000F24* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000F25* + ID_OUI_FROM_DATABASE=AimValley B.V. + +OUI:000F26* + ID_OUI_FROM_DATABASE=WorldAccxx LLC + +OUI:000F27* + ID_OUI_FROM_DATABASE=TEAL Electronics, Inc. + +OUI:000F28* + ID_OUI_FROM_DATABASE=Itronix Corporation + +OUI:000F29* + ID_OUI_FROM_DATABASE=Augmentix Corporation + +OUI:000F2A* + ID_OUI_FROM_DATABASE=Cableware Electronics + +OUI:000F2B* + ID_OUI_FROM_DATABASE=GREENBELL SYSTEMS + +OUI:000F2C* + ID_OUI_FROM_DATABASE=Uplogix, Inc. + +OUI:000F2D* + ID_OUI_FROM_DATABASE=CHUNG-HSIN ELECTRIC & MACHINERY MFG.CORP. + +OUI:000F2E* + ID_OUI_FROM_DATABASE=Megapower International Corp. + +OUI:000F2F* + ID_OUI_FROM_DATABASE=W-LINX TECHNOLOGY CO., LTD. + +OUI:000F30* + ID_OUI_FROM_DATABASE=Raza Microelectronics Inc + +OUI:000F31* + ID_OUI_FROM_DATABASE=Allied Vision Technologies Canada Inc + +OUI:000F32* + ID_OUI_FROM_DATABASE=Lootom Telcovideo Network Wuxi Co Ltd + +OUI:000F33* + ID_OUI_FROM_DATABASE=DUALi Inc. + +OUI:000F34* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000F35* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000F36* + ID_OUI_FROM_DATABASE=Accurate Techhnologies, Inc. + +OUI:000F37* + ID_OUI_FROM_DATABASE=Xambala Incorporated + +OUI:000F38* + ID_OUI_FROM_DATABASE=Netstar + +OUI:000F39* + ID_OUI_FROM_DATABASE=IRIS SENSORS + +OUI:000F3A* + ID_OUI_FROM_DATABASE=HISHARP + +OUI:000F3B* + ID_OUI_FROM_DATABASE=Fuji System Machines Co., Ltd. + +OUI:000F3C* + ID_OUI_FROM_DATABASE=Endeleo Limited + +OUI:000F3D* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:000F3E* + ID_OUI_FROM_DATABASE=CardioNet, Inc + +OUI:000F3F* + ID_OUI_FROM_DATABASE=Big Bear Networks + +OUI:000F40* + ID_OUI_FROM_DATABASE=Optical Internetworking Forum + +OUI:000F41* + ID_OUI_FROM_DATABASE=Zipher Ltd + +OUI:000F42* + ID_OUI_FROM_DATABASE=Xalyo Systems + +OUI:000F43* + ID_OUI_FROM_DATABASE=Wasabi Systems Inc. + +OUI:000F44* + ID_OUI_FROM_DATABASE=Tivella Inc. + +OUI:000F45* + ID_OUI_FROM_DATABASE=Stretch, Inc. + +OUI:000F46* + ID_OUI_FROM_DATABASE=SINAR AG + +OUI:000F47* + ID_OUI_FROM_DATABASE=ROBOX SPA + +OUI:000F48* + ID_OUI_FROM_DATABASE=Polypix Inc. + +OUI:000F49* + ID_OUI_FROM_DATABASE=Northover Solutions Limited + +OUI:000F4A* + ID_OUI_FROM_DATABASE=Kyushu-kyohan co.,ltd + +OUI:000F4B* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:000F4C* + ID_OUI_FROM_DATABASE=Elextech INC + +OUI:000F4D* + ID_OUI_FROM_DATABASE=TalkSwitch + +OUI:000F4E* + ID_OUI_FROM_DATABASE=Cellink + +OUI:000F4F* + ID_OUI_FROM_DATABASE=PCS Systemtechnik GmbH + +OUI:000F50* + ID_OUI_FROM_DATABASE=StreamScale Limited + +OUI:000F51* + ID_OUI_FROM_DATABASE=Azul Systems, Inc. + +OUI:000F52* + ID_OUI_FROM_DATABASE=YORK Refrigeration, Marine & Controls + +OUI:000F53* + ID_OUI_FROM_DATABASE=Solarflare Communications Inc. + +OUI:000F54* + ID_OUI_FROM_DATABASE=Entrelogic Corporation + +OUI:000F55* + ID_OUI_FROM_DATABASE=Datawire Communication Networks Inc. + +OUI:000F56* + ID_OUI_FROM_DATABASE=Continuum Photonics Inc + +OUI:000F57* + ID_OUI_FROM_DATABASE=CABLELOGIC Co., Ltd. + +OUI:000F58* + ID_OUI_FROM_DATABASE=Adder Technology Limited + +OUI:000F59* + ID_OUI_FROM_DATABASE=Phonak AG + +OUI:000F5A* + ID_OUI_FROM_DATABASE=Peribit Networks + +OUI:000F5B* + ID_OUI_FROM_DATABASE=Delta Information Systems, Inc. + +OUI:000F5C* + ID_OUI_FROM_DATABASE=Day One Digital Media Limited + +OUI:000F5D* + ID_OUI_FROM_DATABASE=Genexis BV + +OUI:000F5E* + ID_OUI_FROM_DATABASE=Veo + +OUI:000F5F* + ID_OUI_FROM_DATABASE=Nicety Technologies Inc. (NTS) + +OUI:000F60* + ID_OUI_FROM_DATABASE=Lifetron Co.,Ltd + +OUI:000F61* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:000F62* + ID_OUI_FROM_DATABASE=Alcatel Bell Space N.V. + +OUI:000F63* + ID_OUI_FROM_DATABASE=Obzerv Technologies + +OUI:000F64* + ID_OUI_FROM_DATABASE=D&R Electronica Weesp BV + +OUI:000F65* + ID_OUI_FROM_DATABASE=icube Corp. + +OUI:000F66* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:000F67* + ID_OUI_FROM_DATABASE=West Instruments + +OUI:000F68* + ID_OUI_FROM_DATABASE=Vavic Network Technology, Inc. + +OUI:000F69* + ID_OUI_FROM_DATABASE=SEW Eurodrive GmbH & Co. KG + +OUI:000F6A* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000F6B* + ID_OUI_FROM_DATABASE=GateWare Communications GmbH + +OUI:000F6C* + ID_OUI_FROM_DATABASE=ADDI-DATA GmbH + +OUI:000F6D* + ID_OUI_FROM_DATABASE=Midas Engineering + +OUI:000F6E* + ID_OUI_FROM_DATABASE=BBox + +OUI:000F6F* + ID_OUI_FROM_DATABASE=FTA Communication Technologies + +OUI:000F70* + ID_OUI_FROM_DATABASE=Wintec Industries, inc. + +OUI:000F71* + ID_OUI_FROM_DATABASE=Sanmei Electronics Co.,Ltd + +OUI:000F72* + ID_OUI_FROM_DATABASE=Sandburst + +OUI:000F73* + ID_OUI_FROM_DATABASE=RS Automation Co., Ltd + +OUI:000F74* + ID_OUI_FROM_DATABASE=Qamcom Technology AB + +OUI:000F75* + ID_OUI_FROM_DATABASE=First Silicon Solutions + +OUI:000F76* + ID_OUI_FROM_DATABASE=Digital Keystone, Inc. + +OUI:000F77* + ID_OUI_FROM_DATABASE=DENTUM CO.,LTD + +OUI:000F78* + ID_OUI_FROM_DATABASE=Datacap Systems Inc + +OUI:000F79* + ID_OUI_FROM_DATABASE=Bluetooth Interest Group Inc. + +OUI:000F7A* + ID_OUI_FROM_DATABASE=BeiJing NuQX Technology CO.,LTD + +OUI:000F7B* + ID_OUI_FROM_DATABASE=Arce Sistemas, S.A. + +OUI:000F7C* + ID_OUI_FROM_DATABASE=ACTi Corporation + +OUI:000F7D* + ID_OUI_FROM_DATABASE=Xirrus + +OUI:000F7E* + ID_OUI_FROM_DATABASE=Ablerex Electronics Co., LTD + +OUI:000F7F* + ID_OUI_FROM_DATABASE=UBSTORAGE Co.,Ltd. + +OUI:000F80* + ID_OUI_FROM_DATABASE=Trinity Security Systems,Inc. + +OUI:000F81* + ID_OUI_FROM_DATABASE=PAL Pacific Inc. + +OUI:000F82* + ID_OUI_FROM_DATABASE=Mortara Instrument, Inc. + +OUI:000F83* + ID_OUI_FROM_DATABASE=Brainium Technologies Inc. + +OUI:000F84* + ID_OUI_FROM_DATABASE=Astute Networks, Inc. + +OUI:000F85* + ID_OUI_FROM_DATABASE=ADDO-Japan Corporation + +OUI:000F86* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:000F87* + ID_OUI_FROM_DATABASE=Maxcess International + +OUI:000F88* + ID_OUI_FROM_DATABASE=AMETEK, Inc. + +OUI:000F89* + ID_OUI_FROM_DATABASE=Winnertec System Co., Ltd. + +OUI:000F8A* + ID_OUI_FROM_DATABASE=WideView + +OUI:000F8B* + ID_OUI_FROM_DATABASE=Orion MultiSystems Inc + +OUI:000F8C* + ID_OUI_FROM_DATABASE=Gigawavetech Pte Ltd + +OUI:000F8D* + ID_OUI_FROM_DATABASE=FAST TV-Server AG + +OUI:000F8E* + ID_OUI_FROM_DATABASE=DONGYANG TELECOM CO.,LTD. + +OUI:000F8F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000F90* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000F91* + ID_OUI_FROM_DATABASE=Aerotelecom Co.,Ltd. + +OUI:000F92* + ID_OUI_FROM_DATABASE=Microhard Systems Inc. + +OUI:000F93* + ID_OUI_FROM_DATABASE=Landis+Gyr Ltd. + +OUI:000F94* + ID_OUI_FROM_DATABASE=Genexis BV + +OUI:000F95* + ID_OUI_FROM_DATABASE=ELECOM Co.,LTD Laneed Division + +OUI:000F96* + ID_OUI_FROM_DATABASE=Telco Systems, Inc. + +OUI:000F97* + ID_OUI_FROM_DATABASE=Avanex Corporation + +OUI:000F98* + ID_OUI_FROM_DATABASE=Avamax Co. Ltd. + +OUI:000F99* + ID_OUI_FROM_DATABASE=APAC opto Electronics Inc. + +OUI:000F9A* + ID_OUI_FROM_DATABASE=Synchrony, Inc. + +OUI:000F9B* + ID_OUI_FROM_DATABASE=Ross Video Limited + +OUI:000F9C* + ID_OUI_FROM_DATABASE=Panduit Corp + +OUI:000F9D* + ID_OUI_FROM_DATABASE=DisplayLink (UK) Ltd + +OUI:000F9E* + ID_OUI_FROM_DATABASE=Murrelektronik GmbH + +OUI:000F9F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:000FA0* + ID_OUI_FROM_DATABASE=CANON KOREA BUSINESS SOLUTIONS INC. + +OUI:000FA1* + ID_OUI_FROM_DATABASE=Gigabit Systems Inc. + +OUI:000FA2* + ID_OUI_FROM_DATABASE=2xWireless + +OUI:000FA3* + ID_OUI_FROM_DATABASE=Alpha Networks Inc. + +OUI:000FA4* + ID_OUI_FROM_DATABASE=Sprecher Automation GmbH + +OUI:000FA5* + ID_OUI_FROM_DATABASE=BWA Technology GmbH + +OUI:000FA6* + ID_OUI_FROM_DATABASE=S2 Security Corporation + +OUI:000FA7* + ID_OUI_FROM_DATABASE=Raptor Networks Technology + +OUI:000FA8* + ID_OUI_FROM_DATABASE=Photometrics, Inc. + +OUI:000FA9* + ID_OUI_FROM_DATABASE=PC Fabrik + +OUI:000FAA* + ID_OUI_FROM_DATABASE=Nexus Technologies + +OUI:000FAB* + ID_OUI_FROM_DATABASE=Kyushu Electronics Systems Inc. + +OUI:000FAC* + ID_OUI_FROM_DATABASE=IEEE 802.11 + +OUI:000FAD* + ID_OUI_FROM_DATABASE=FMN communications GmbH + +OUI:000FAE* + ID_OUI_FROM_DATABASE=E2O Communications + +OUI:000FAF* + ID_OUI_FROM_DATABASE=Dialog Inc. + +OUI:000FB0* + ID_OUI_FROM_DATABASE=Compal Electronics INC. + +OUI:000FB1* + ID_OUI_FROM_DATABASE=Cognio Inc. + +OUI:000FB2* + ID_OUI_FROM_DATABASE=Broadband Pacenet (India) Pvt. Ltd. + +OUI:000FB3* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:000FB4* + ID_OUI_FROM_DATABASE=Timespace Technology + +OUI:000FB5* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:000FB6* + ID_OUI_FROM_DATABASE=Europlex Technologies + +OUI:000FB7* + ID_OUI_FROM_DATABASE=Cavium + +OUI:000FB8* + ID_OUI_FROM_DATABASE=CallURL Inc. + +OUI:000FB9* + ID_OUI_FROM_DATABASE=Adaptive Instruments + +OUI:000FBA* + ID_OUI_FROM_DATABASE=Tevebox AB + +OUI:000FBB* + ID_OUI_FROM_DATABASE=Nokia Siemens Networks GmbH & Co. KG. + +OUI:000FBC* + ID_OUI_FROM_DATABASE=Onkey Technologies, Inc. + +OUI:000FBD* + ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD + +OUI:000FBE* + ID_OUI_FROM_DATABASE=e-w/you Inc. + +OUI:000FBF* + ID_OUI_FROM_DATABASE=DGT Sp. z o.o. + +OUI:000FC0* + ID_OUI_FROM_DATABASE=DELCOMp + +OUI:000FC1* + ID_OUI_FROM_DATABASE=WAVE Corporation + +OUI:000FC2* + ID_OUI_FROM_DATABASE=Uniwell Corporation + +OUI:000FC3* + ID_OUI_FROM_DATABASE=PalmPalm Technology, Inc. + +OUI:000FC4* + ID_OUI_FROM_DATABASE=NST co.,LTD. + +OUI:000FC5* + ID_OUI_FROM_DATABASE=KeyMed Ltd + +OUI:000FC6* + ID_OUI_FROM_DATABASE=Eurocom Industries A/S + +OUI:000FC7* + ID_OUI_FROM_DATABASE=Dionica R&D Ltd. + +OUI:000FC8* + ID_OUI_FROM_DATABASE=Chantry Networks + +OUI:000FC9* + ID_OUI_FROM_DATABASE=Allnet GmbH + +OUI:000FCA* + ID_OUI_FROM_DATABASE=A-JIN TECHLINE CO, LTD + +OUI:000FCB* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:000FCC* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:000FCD* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:000FCE* + ID_OUI_FROM_DATABASE=Kikusui Electronics Corp. + +OUI:000FCF* + ID_OUI_FROM_DATABASE=DataWind Research + +OUI:000FD0* + ID_OUI_FROM_DATABASE=ASTRI + +OUI:000FD1* + ID_OUI_FROM_DATABASE=Applied Wireless Identifications Group, Inc. + +OUI:000FD2* + ID_OUI_FROM_DATABASE=EWA Technologies, Inc. + +OUI:000FD3* + ID_OUI_FROM_DATABASE=Digium + +OUI:000FD4* + ID_OUI_FROM_DATABASE=Soundcraft + +OUI:000FD5* + ID_OUI_FROM_DATABASE=Schwechat - RISE + +OUI:000FD6* + ID_OUI_FROM_DATABASE=Sarotech Co., Ltd + +OUI:000FD7* + ID_OUI_FROM_DATABASE=Harman Music Group + +OUI:000FD8* + ID_OUI_FROM_DATABASE=Force, Inc. + +OUI:000FD9* + ID_OUI_FROM_DATABASE=FlexDSL Telecommunications AG + +OUI:000FDA* + ID_OUI_FROM_DATABASE=YAZAKI CORPORATION + +OUI:000FDB* + ID_OUI_FROM_DATABASE=Westell Technologies Inc. + +OUI:000FDC* + ID_OUI_FROM_DATABASE=Ueda Japan Radio Co., Ltd. + +OUI:000FDD* + ID_OUI_FROM_DATABASE=SORDIN AB + +OUI:000FDE* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:000FDF* + ID_OUI_FROM_DATABASE=SOLOMON Technology Corp. + +OUI:000FE0* + ID_OUI_FROM_DATABASE=NComputing Co.,Ltd. + +OUI:000FE1* + ID_OUI_FROM_DATABASE=ID DIGITAL CORPORATION + +OUI:000FE2* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:000FE3* + ID_OUI_FROM_DATABASE=Damm Cellular Systems A/S + +OUI:000FE4* + ID_OUI_FROM_DATABASE=Pantech Co.,Ltd + +OUI:000FE5* + ID_OUI_FROM_DATABASE=MERCURY SECURITY CORPORATION + +OUI:000FE6* + ID_OUI_FROM_DATABASE=MBTech Systems, Inc. + +OUI:000FE7* + ID_OUI_FROM_DATABASE=Lutron Electronics Co., Inc. + +OUI:000FE8* + ID_OUI_FROM_DATABASE=Lobos, Inc. + +OUI:000FE9* + ID_OUI_FROM_DATABASE=GW TECHNOLOGIES CO.,LTD. + +OUI:000FEA* + ID_OUI_FROM_DATABASE=Giga-Byte Technology Co.,LTD. + +OUI:000FEB* + ID_OUI_FROM_DATABASE=Cylon Controls + +OUI:000FEC* + ID_OUI_FROM_DATABASE=ARKUS Inc. + +OUI:000FED* + ID_OUI_FROM_DATABASE=Anam Electronics Co., Ltd + +OUI:000FEE* + ID_OUI_FROM_DATABASE=XTec, Incorporated + +OUI:000FEF* + ID_OUI_FROM_DATABASE=Thales e-Transactions GmbH + +OUI:000FF0* + ID_OUI_FROM_DATABASE=Sunray Co. Ltd. + +OUI:000FF1* + ID_OUI_FROM_DATABASE=nex-G Systems Pte.Ltd + +OUI:000FF2* + ID_OUI_FROM_DATABASE=Loud Technologies Inc. + +OUI:000FF3* + ID_OUI_FROM_DATABASE=Jung Myoung Communications&Technology + +OUI:000FF4* + ID_OUI_FROM_DATABASE=Guntermann & Drunck GmbH + +OUI:000FF5* + ID_OUI_FROM_DATABASE=GN&S company + +OUI:000FF6* + ID_OUI_FROM_DATABASE=DARFON LIGHTING CORP + +OUI:000FF7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000FF8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:000FF9* + ID_OUI_FROM_DATABASE=Valcretec, Inc. + +OUI:000FFA* + ID_OUI_FROM_DATABASE=Optinel Systems, Inc. + +OUI:000FFB* + ID_OUI_FROM_DATABASE=Nippon Denso Industry Co., Ltd. + +OUI:000FFC* + ID_OUI_FROM_DATABASE=Merit Li-Lin Ent. + +OUI:000FFD* + ID_OUI_FROM_DATABASE=Glorytek Network Inc. + +OUI:000FFE* + ID_OUI_FROM_DATABASE=G-PRO COMPUTER + +OUI:000FFF* + ID_OUI_FROM_DATABASE=Control4 + +OUI:001000* + ID_OUI_FROM_DATABASE=CABLE TELEVISION LABORATORIES, INC. + +OUI:001001* + ID_OUI_FROM_DATABASE=Citel + +OUI:001002* + ID_OUI_FROM_DATABASE=ACTIA + +OUI:001003* + ID_OUI_FROM_DATABASE=IMATRON, INC. + +OUI:001004* + ID_OUI_FROM_DATABASE=THE BRANTLEY COILE COMPANY,INC + +OUI:001005* + ID_OUI_FROM_DATABASE=UEC COMMERCIAL + +OUI:001006* + ID_OUI_FROM_DATABASE=Thales Contact Solutions Ltd. + +OUI:001007* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001008* + ID_OUI_FROM_DATABASE=VIENNA SYSTEMS CORPORATION + +OUI:001009* + ID_OUI_FROM_DATABASE=HORANET + +OUI:00100A* + ID_OUI_FROM_DATABASE=WILLIAMS COMMUNICATIONS GROUP + +OUI:00100B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00100C* + ID_OUI_FROM_DATABASE=ITO CO., LTD. + +OUI:00100D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00100E* + ID_OUI_FROM_DATABASE=MICRO LINEAR COPORATION + +OUI:00100F* + ID_OUI_FROM_DATABASE=INDUSTRIAL CPU SYSTEMS + +OUI:001010* + ID_OUI_FROM_DATABASE=INITIO CORPORATION + +OUI:001011* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001012* + ID_OUI_FROM_DATABASE=PROCESSOR SYSTEMS (I) PVT LTD + +OUI:001013* + ID_OUI_FROM_DATABASE=Kontron America, Inc. + +OUI:001014* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001015* + ID_OUI_FROM_DATABASE=OOmon Inc. + +OUI:001016* + ID_OUI_FROM_DATABASE=T.SQWARE + +OUI:001017* + ID_OUI_FROM_DATABASE=Bosch Access Systems GmbH + +OUI:001018* + ID_OUI_FROM_DATABASE=Broadcom + +OUI:001019* + ID_OUI_FROM_DATABASE=SIRONA DENTAL SYSTEMS GmbH & Co. KG + +OUI:00101A* + ID_OUI_FROM_DATABASE=PictureTel Corp. + +OUI:00101B* + ID_OUI_FROM_DATABASE=CORNET TECHNOLOGY, INC. + +OUI:00101C* + ID_OUI_FROM_DATABASE=OHM TECHNOLOGIES INTL, LLC + +OUI:00101D* + ID_OUI_FROM_DATABASE=WINBOND ELECTRONICS CORP. + +OUI:00101E* + ID_OUI_FROM_DATABASE=MATSUSHITA ELECTRONIC INSTRUMENTS CORP. + +OUI:00101F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001020* + ID_OUI_FROM_DATABASE=Hand Held Products Inc + +OUI:001021* + ID_OUI_FROM_DATABASE=ENCANTO NETWORKS, INC. + +OUI:001022* + ID_OUI_FROM_DATABASE=SatCom Media Corporation + +OUI:001023* + ID_OUI_FROM_DATABASE=Network Equipment Technologies + +OUI:001024* + ID_OUI_FROM_DATABASE=NAGOYA ELECTRIC WORKS CO., LTD + +OUI:001025* + ID_OUI_FROM_DATABASE=Grayhill, Inc + +OUI:001026* + ID_OUI_FROM_DATABASE=ACCELERATED NETWORKS, INC. + +OUI:001027* + ID_OUI_FROM_DATABASE=L-3 COMMUNICATIONS EAST + +OUI:001028* + ID_OUI_FROM_DATABASE=COMPUTER TECHNICA, INC. + +OUI:001029* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00102A* + ID_OUI_FROM_DATABASE=ZF MICROSYSTEMS, INC. + +OUI:00102B* + ID_OUI_FROM_DATABASE=UMAX DATA SYSTEMS, INC. + +OUI:00102C* + ID_OUI_FROM_DATABASE=Lasat Networks A/S + +OUI:00102D* + ID_OUI_FROM_DATABASE=HITACHI SOFTWARE ENGINEERING + +OUI:00102E* + ID_OUI_FROM_DATABASE=NETWORK SYSTEMS & TECHNOLOGIES PVT. LTD. + +OUI:00102F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001030* + ID_OUI_FROM_DATABASE=EION Inc. + +OUI:001031* + ID_OUI_FROM_DATABASE=OBJECTIVE COMMUNICATIONS, INC. + +OUI:001032* + ID_OUI_FROM_DATABASE=ALTA TECHNOLOGY + +OUI:001033* + ID_OUI_FROM_DATABASE=ACCESSLAN COMMUNICATIONS, INC. + +OUI:001034* + ID_OUI_FROM_DATABASE=GNP Computers + +OUI:001035* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:001036* + ID_OUI_FROM_DATABASE=INTER-TEL INTEGRATED SYSTEMS + +OUI:001037* + ID_OUI_FROM_DATABASE=CYQ've Technology Co., Ltd. + +OUI:001038* + ID_OUI_FROM_DATABASE=Micro Research Ltd. + +OUI:001039* + ID_OUI_FROM_DATABASE=Vectron Systems AG + +OUI:00103A* + ID_OUI_FROM_DATABASE=DIAMOND NETWORK TECH + +OUI:00103B* + ID_OUI_FROM_DATABASE=HIPPI NETWORKING FORUM + +OUI:00103C* + ID_OUI_FROM_DATABASE=IC ENSEMBLE, INC. + +OUI:00103D* + ID_OUI_FROM_DATABASE=PHASECOM, LTD. + +OUI:00103E* + ID_OUI_FROM_DATABASE=NETSCHOOLS CORPORATION + +OUI:00103F* + ID_OUI_FROM_DATABASE=TOLLGRADE COMMUNICATIONS, INC. + +OUI:001040* + ID_OUI_FROM_DATABASE=INTERMEC CORPORATION + +OUI:001041* + ID_OUI_FROM_DATABASE=BRISTOL BABCOCK, INC. + +OUI:001042* + ID_OUI_FROM_DATABASE=Alacritech, Inc. + +OUI:001043* + ID_OUI_FROM_DATABASE=A2 CORPORATION + +OUI:001044* + ID_OUI_FROM_DATABASE=InnoLabs Corporation + +OUI:001045* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001046* + ID_OUI_FROM_DATABASE=ALCORN MCBRIDE INC. + +OUI:001047* + ID_OUI_FROM_DATABASE=ECHO ELETRIC CO. LTD. + +OUI:001048* + ID_OUI_FROM_DATABASE=HTRC AUTOMATION, INC. + +OUI:001049* + ID_OUI_FROM_DATABASE=ShoreTel, Inc + +OUI:00104A* + ID_OUI_FROM_DATABASE=The Parvus Corporation + +OUI:00104B* + ID_OUI_FROM_DATABASE=3COM + +OUI:00104C* + ID_OUI_FROM_DATABASE=Teledyne LeCroy, Inc + +OUI:00104D* + ID_OUI_FROM_DATABASE=SURTEC INDUSTRIES, INC. + +OUI:00104E* + ID_OUI_FROM_DATABASE=CEOLOGIC + +OUI:00104F* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:001050* + ID_OUI_FROM_DATABASE=RION CO., LTD. + +OUI:001051* + ID_OUI_FROM_DATABASE=CMICRO CORPORATION + +OUI:001052* + ID_OUI_FROM_DATABASE=METTLER-TOLEDO (ALBSTADT) GMBH + +OUI:001053* + ID_OUI_FROM_DATABASE=COMPUTER TECHNOLOGY CORP. + +OUI:001054* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001055* + ID_OUI_FROM_DATABASE=FUJITSU MICROELECTRONICS, INC. + +OUI:001056* + ID_OUI_FROM_DATABASE=SODICK CO., LTD. + +OUI:001057* + ID_OUI_FROM_DATABASE=Rebel.com, Inc. + +OUI:001058* + ID_OUI_FROM_DATABASE=ArrowPoint Communications + +OUI:001059* + ID_OUI_FROM_DATABASE=DIABLO RESEARCH CO. LLC + +OUI:00105A* + ID_OUI_FROM_DATABASE=3COM + +OUI:00105B* + ID_OUI_FROM_DATABASE=NET INSIGHT AB + +OUI:00105C* + ID_OUI_FROM_DATABASE=QUANTUM DESIGNS (H.K.) LTD. + +OUI:00105D* + ID_OUI_FROM_DATABASE=Draeger Medical + +OUI:00105E* + ID_OUI_FROM_DATABASE=Spirent plc, Service Assurance Broadband + +OUI:00105F* + ID_OUI_FROM_DATABASE=ZODIAC DATA SYSTEMS + +OUI:001060* + ID_OUI_FROM_DATABASE=BILLIONTON SYSTEMS, INC. + +OUI:001061* + ID_OUI_FROM_DATABASE=HOSTLINK CORP. + +OUI:001062* + ID_OUI_FROM_DATABASE=NX SERVER, ILNC. + +OUI:001063* + ID_OUI_FROM_DATABASE=STARGUIDE DIGITAL NETWORKS + +OUI:001064* + ID_OUI_FROM_DATABASE=DNPG, LLC + +OUI:001065* + ID_OUI_FROM_DATABASE=RADYNE CORPORATION + +OUI:001066* + ID_OUI_FROM_DATABASE=ADVANCED CONTROL SYSTEMS, INC. + +OUI:001067* + ID_OUI_FROM_DATABASE=Ericsson + +OUI:001068* + ID_OUI_FROM_DATABASE=COMOS TELECOM + +OUI:001069* + ID_OUI_FROM_DATABASE=HELIOSS COMMUNICATIONS, INC. + +OUI:00106A* + ID_OUI_FROM_DATABASE=DIGITAL MICROWAVE CORPORATION + +OUI:00106B* + ID_OUI_FROM_DATABASE=SONUS NETWORKS, INC. + +OUI:00106C* + ID_OUI_FROM_DATABASE=EDNT GmbH + +OUI:00106D* + ID_OUI_FROM_DATABASE=Axxcelera Broadband Wireless + +OUI:00106E* + ID_OUI_FROM_DATABASE=TADIRAN COM. LTD. + +OUI:00106F* + ID_OUI_FROM_DATABASE=TRENTON TECHNOLOGY INC. + +OUI:001070* + ID_OUI_FROM_DATABASE=CARADON TREND LTD. + +OUI:001071* + ID_OUI_FROM_DATABASE=ADVANET INC. + +OUI:001072* + ID_OUI_FROM_DATABASE=GVN TECHNOLOGIES, INC. + +OUI:001073* + ID_OUI_FROM_DATABASE=TECHNOBOX, INC. + +OUI:001074* + ID_OUI_FROM_DATABASE=ATEN INTERNATIONAL CO., LTD. + +OUI:001075* + ID_OUI_FROM_DATABASE=Segate Technology LLC + +OUI:001076* + ID_OUI_FROM_DATABASE=EUREM GmbH + +OUI:001077* + ID_OUI_FROM_DATABASE=SAF DRIVE SYSTEMS, LTD. + +OUI:001078* + ID_OUI_FROM_DATABASE=NUERA COMMUNICATIONS, INC. + +OUI:001079* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00107A* + ID_OUI_FROM_DATABASE=AmbiCom, Inc. + +OUI:00107B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00107C* + ID_OUI_FROM_DATABASE=P-COM, INC. + +OUI:00107D* + ID_OUI_FROM_DATABASE=AURORA COMMUNICATIONS, LTD. + +OUI:00107E* + ID_OUI_FROM_DATABASE=BACHMANN ELECTRONIC GmbH + +OUI:00107F* + ID_OUI_FROM_DATABASE=CRESTRON ELECTRONICS, INC. + +OUI:001080* + ID_OUI_FROM_DATABASE=METAWAVE COMMUNICATIONS + +OUI:001081* + ID_OUI_FROM_DATABASE=DPS, INC. + +OUI:001082* + ID_OUI_FROM_DATABASE=JNA TELECOMMUNICATIONS LIMITED + +OUI:001083* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001084* + ID_OUI_FROM_DATABASE=K-BOT COMMUNICATIONS + +OUI:001085* + ID_OUI_FROM_DATABASE=POLARIS COMMUNICATIONS, INC. + +OUI:001086* + ID_OUI_FROM_DATABASE=ATTO Technology, Inc. + +OUI:001087* + ID_OUI_FROM_DATABASE=XSTREAMIS PLC + +OUI:001088* + ID_OUI_FROM_DATABASE=AMERICAN NETWORKS INC. + +OUI:001089* + ID_OUI_FROM_DATABASE=WebSonic + +OUI:00108A* + ID_OUI_FROM_DATABASE=TeraLogic, Inc. + +OUI:00108B* + ID_OUI_FROM_DATABASE=LASERANIMATION SOLLINGER GMBH + +OUI:00108C* + ID_OUI_FROM_DATABASE=Fujitsu Services Ltd + +OUI:00108D* + ID_OUI_FROM_DATABASE=Johnson Controls, Inc. + +OUI:00108E* + ID_OUI_FROM_DATABASE=HUGH SYMONS CONCEPT Technologies Ltd. + +OUI:00108F* + ID_OUI_FROM_DATABASE=RAPTOR SYSTEMS + +OUI:001090* + ID_OUI_FROM_DATABASE=CIMETRICS, INC. + +OUI:001091* + ID_OUI_FROM_DATABASE=NO WIRES NEEDED BV + +OUI:001092* + ID_OUI_FROM_DATABASE=NETCORE INC. + +OUI:001093* + ID_OUI_FROM_DATABASE=CMS COMPUTERS, LTD. + +OUI:001094* + ID_OUI_FROM_DATABASE=Performance Analysis Broadband, Spirent plc + +OUI:001095* + ID_OUI_FROM_DATABASE=Thomson Inc. + +OUI:001096* + ID_OUI_FROM_DATABASE=TRACEWELL SYSTEMS, INC. + +OUI:001097* + ID_OUI_FROM_DATABASE=WinNet Metropolitan Communications Systems, Inc. + +OUI:001098* + ID_OUI_FROM_DATABASE=STARNET TECHNOLOGIES, INC. + +OUI:001099* + ID_OUI_FROM_DATABASE=InnoMedia, Inc. + +OUI:00109A* + ID_OUI_FROM_DATABASE=NETLINE + +OUI:00109B* + ID_OUI_FROM_DATABASE=Emulex Corporation + +OUI:00109C* + ID_OUI_FROM_DATABASE=M-SYSTEM CO., LTD. + +OUI:00109D* + ID_OUI_FROM_DATABASE=CLARINET SYSTEMS, INC. + +OUI:00109E* + ID_OUI_FROM_DATABASE=AWARE, INC. + +OUI:00109F* + ID_OUI_FROM_DATABASE=PAVO, INC. + +OUI:0010A0* + ID_OUI_FROM_DATABASE=INNOVEX TECHNOLOGIES, INC. + +OUI:0010A1* + ID_OUI_FROM_DATABASE=KENDIN SEMICONDUCTOR, INC. + +OUI:0010A2* + ID_OUI_FROM_DATABASE=TNS + +OUI:0010A3* + ID_OUI_FROM_DATABASE=OMNITRONIX, INC. + +OUI:0010A4* + ID_OUI_FROM_DATABASE=XIRCOM + +OUI:0010A5* + ID_OUI_FROM_DATABASE=OXFORD INSTRUMENTS + +OUI:0010A6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0010A7* + ID_OUI_FROM_DATABASE=UNEX TECHNOLOGY CORPORATION + +OUI:0010A8* + ID_OUI_FROM_DATABASE=RELIANCE COMPUTER CORP. + +OUI:0010A9* + ID_OUI_FROM_DATABASE=ADHOC TECHNOLOGIES + +OUI:0010AA* + ID_OUI_FROM_DATABASE=MEDIA4, INC. + +OUI:0010AB* + ID_OUI_FROM_DATABASE=KOITO ELECTRIC INDUSTRIES, LTD. + +OUI:0010AC* + ID_OUI_FROM_DATABASE=IMCI TECHNOLOGIES + +OUI:0010AD* + ID_OUI_FROM_DATABASE=SOFTRONICS USB, INC. + +OUI:0010AE* + ID_OUI_FROM_DATABASE=SHINKO ELECTRIC INDUSTRIES CO. + +OUI:0010AF* + ID_OUI_FROM_DATABASE=TAC SYSTEMS, INC. + +OUI:0010B0* + ID_OUI_FROM_DATABASE=MERIDIAN TECHNOLOGY CORP. + +OUI:0010B1* + ID_OUI_FROM_DATABASE=FOR-A CO., LTD. + +OUI:0010B2* + ID_OUI_FROM_DATABASE=COACTIVE AESTHETICS + +OUI:0010B3* + ID_OUI_FROM_DATABASE=NOKIA MULTIMEDIA TERMINALS + +OUI:0010B4* + ID_OUI_FROM_DATABASE=ATMOSPHERE NETWORKS + +OUI:0010B5* + ID_OUI_FROM_DATABASE=Accton Technology Corp + +OUI:0010B6* + ID_OUI_FROM_DATABASE=ENTRATA COMMUNICATIONS CORP. + +OUI:0010B7* + ID_OUI_FROM_DATABASE=COYOTE TECHNOLOGIES, LLC + +OUI:0010B8* + ID_OUI_FROM_DATABASE=ISHIGAKI COMPUTER SYSTEM CO. + +OUI:0010B9* + ID_OUI_FROM_DATABASE=MAXTOR CORP. + +OUI:0010BA* + ID_OUI_FROM_DATABASE=MARTINHO-DAVIS SYSTEMS, INC. + +OUI:0010BB* + ID_OUI_FROM_DATABASE=DATA & INFORMATION TECHNOLOGY + +OUI:0010BC* + ID_OUI_FROM_DATABASE=Aastra Telecom + +OUI:0010BD* + ID_OUI_FROM_DATABASE=THE TELECOMMUNICATION TECHNOLOGY COMMITTEE (TTC) + +OUI:0010BE* + ID_OUI_FROM_DATABASE=MARCH NETWORKS CORPORATION + +OUI:0010BF* + ID_OUI_FROM_DATABASE=InterAir Wireless + +OUI:0010C0* + ID_OUI_FROM_DATABASE=ARMA, Inc. + +OUI:0010C1* + ID_OUI_FROM_DATABASE=OI ELECTRIC CO.,LTD + +OUI:0010C2* + ID_OUI_FROM_DATABASE=WILLNET, INC. + +OUI:0010C3* + ID_OUI_FROM_DATABASE=CSI-CONTROL SYSTEMS + +OUI:0010C4* + ID_OUI_FROM_DATABASE=MEDIA GLOBAL LINKS CO., LTD. + +OUI:0010C5* + ID_OUI_FROM_DATABASE=PROTOCOL TECHNOLOGIES, INC. + +OUI:0010C6* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:0010C7* + ID_OUI_FROM_DATABASE=DATA TRANSMISSION NETWORK + +OUI:0010C8* + ID_OUI_FROM_DATABASE=COMMUNICATIONS ELECTRONICS SECURITY GROUP + +OUI:0010C9* + ID_OUI_FROM_DATABASE=MITSUBISHI ELECTRONICS LOGISTIC SUPPORT CO. + +OUI:0010CA* + ID_OUI_FROM_DATABASE=Telco Systems, Inc. + +OUI:0010CB* + ID_OUI_FROM_DATABASE=FACIT K.K. + +OUI:0010CC* + ID_OUI_FROM_DATABASE=CLP COMPUTER LOGISTIK PLANUNG GmbH + +OUI:0010CD* + ID_OUI_FROM_DATABASE=INTERFACE CONCEPT + +OUI:0010CE* + ID_OUI_FROM_DATABASE=VOLAMP, LTD. + +OUI:0010CF* + ID_OUI_FROM_DATABASE=FIBERLANE COMMUNICATIONS + +OUI:0010D0* + ID_OUI_FROM_DATABASE=WITCOM, LTD. + +OUI:0010D1* + ID_OUI_FROM_DATABASE=Top Layer Networks, Inc. + +OUI:0010D2* + ID_OUI_FROM_DATABASE=NITTO TSUSHINKI CO., LTD + +OUI:0010D3* + ID_OUI_FROM_DATABASE=GRIPS ELECTRONIC GMBH + +OUI:0010D4* + ID_OUI_FROM_DATABASE=STORAGE COMPUTER CORPORATION + +OUI:0010D5* + ID_OUI_FROM_DATABASE=IMASDE CANARIAS, S.A. + +OUI:0010D6* + ID_OUI_FROM_DATABASE=Exelis + +OUI:0010D7* + ID_OUI_FROM_DATABASE=ARGOSY RESEARCH INC. + +OUI:0010D8* + ID_OUI_FROM_DATABASE=CALISTA + +OUI:0010D9* + ID_OUI_FROM_DATABASE=IBM JAPAN, FUJISAWA MT+D + +OUI:0010DA* + ID_OUI_FROM_DATABASE=Kollmorgen Corp + +OUI:0010DB* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:0010DC* + ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. + +OUI:0010DD* + ID_OUI_FROM_DATABASE=ENABLE SEMICONDUCTOR, INC. + +OUI:0010DE* + ID_OUI_FROM_DATABASE=INTERNATIONAL DATACASTING CORPORATION + +OUI:0010DF* + ID_OUI_FROM_DATABASE=RISE COMPUTER INC. + +OUI:0010E0* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:0010E1* + ID_OUI_FROM_DATABASE=S.I. TECH, INC. + +OUI:0010E2* + ID_OUI_FROM_DATABASE=ArrayComm, Inc. + +OUI:0010E3* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0010E4* + ID_OUI_FROM_DATABASE=NSI CORPORATION + +OUI:0010E5* + ID_OUI_FROM_DATABASE=SOLECTRON TEXAS + +OUI:0010E6* + ID_OUI_FROM_DATABASE=APPLIED INTELLIGENT SYSTEMS, INC. + +OUI:0010E7* + ID_OUI_FROM_DATABASE=Breezecom, Ltd. + +OUI:0010E8* + ID_OUI_FROM_DATABASE=TELOCITY, INCORPORATED + +OUI:0010E9* + ID_OUI_FROM_DATABASE=RAIDTEC LTD. + +OUI:0010EA* + ID_OUI_FROM_DATABASE=ADEPT TECHNOLOGY + +OUI:0010EB* + ID_OUI_FROM_DATABASE=SELSIUS SYSTEMS, INC. + +OUI:0010EC* + ID_OUI_FROM_DATABASE=RPCG, LLC + +OUI:0010ED* + ID_OUI_FROM_DATABASE=SUNDANCE TECHNOLOGY, INC. + +OUI:0010EE* + ID_OUI_FROM_DATABASE=CTI PRODUCTS, INC. + +OUI:0010EF* + ID_OUI_FROM_DATABASE=DBTEL INCORPORATED + +OUI:0010F0* + ID_OUI_FROM_DATABASE=RITTAL-WERK RUDOLF LOH GmbH & Co. + +OUI:0010F1* + ID_OUI_FROM_DATABASE=I-O CORPORATION + +OUI:0010F2* + ID_OUI_FROM_DATABASE=ANTEC + +OUI:0010F3* + ID_OUI_FROM_DATABASE=Nexcom International Co., Ltd. + +OUI:0010F4* + ID_OUI_FROM_DATABASE=Vertical Communications + +OUI:0010F5* + ID_OUI_FROM_DATABASE=AMHERST SYSTEMS, INC. + +OUI:0010F6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0010F7* + ID_OUI_FROM_DATABASE=IRIICHI TECHNOLOGIES Inc. + +OUI:0010F8* + ID_OUI_FROM_DATABASE=TEXIO TECHNOLOGY CORPORATION + +OUI:0010F9* + ID_OUI_FROM_DATABASE=UNIQUE SYSTEMS, INC. + +OUI:0010FA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0010FB* + ID_OUI_FROM_DATABASE=ZIDA TECHNOLOGIES LIMITED + +OUI:0010FC* + ID_OUI_FROM_DATABASE=BROADBAND NETWORKS, INC. + +OUI:0010FD* + ID_OUI_FROM_DATABASE=COCOM A/S + +OUI:0010FE* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION + +OUI:0010FF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001100* + ID_OUI_FROM_DATABASE=Schneider Electric + +OUI:001101* + ID_OUI_FROM_DATABASE=CET Technologies Pte Ltd + +OUI:001102* + ID_OUI_FROM_DATABASE=Aurora Multimedia Corp. + +OUI:001103* + ID_OUI_FROM_DATABASE=kawamura electric inc. + +OUI:001104* + ID_OUI_FROM_DATABASE=TELEXY + +OUI:001105* + ID_OUI_FROM_DATABASE=Sunplus Technology Co., Ltd. + +OUI:001106* + ID_OUI_FROM_DATABASE=Siemens NV (Belgium) + +OUI:001107* + ID_OUI_FROM_DATABASE=RGB Networks Inc. + +OUI:001108* + ID_OUI_FROM_DATABASE=Orbital Data Corporation + +OUI:001109* + ID_OUI_FROM_DATABASE=Micro-Star International + +OUI:00110A* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:00110B* + ID_OUI_FROM_DATABASE=Franklin Technology Systems + +OUI:00110C* + ID_OUI_FROM_DATABASE=Atmark Techno, Inc. + +OUI:00110D* + ID_OUI_FROM_DATABASE=SANBlaze Technology, Inc. + +OUI:00110E* + ID_OUI_FROM_DATABASE=Tsurusaki Sealand Transportation Co. Ltd. + +OUI:00110F* + ID_OUI_FROM_DATABASE=netplat,Inc. + +OUI:001110* + ID_OUI_FROM_DATABASE=Maxanna Technology Co., Ltd. + +OUI:001111* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:001112* + ID_OUI_FROM_DATABASE=Honeywell CMSS + +OUI:001113* + ID_OUI_FROM_DATABASE=Fraunhofer FOKUS + +OUI:001114* + ID_OUI_FROM_DATABASE=EverFocus Electronics Corp. + +OUI:001115* + ID_OUI_FROM_DATABASE=EPIN Technologies, Inc. + +OUI:001116* + ID_OUI_FROM_DATABASE=COTEAU VERT CO., LTD. + +OUI:001117* + ID_OUI_FROM_DATABASE=CESNET + +OUI:001118* + ID_OUI_FROM_DATABASE=BLX IC Design Corp., Ltd. + +OUI:001119* + ID_OUI_FROM_DATABASE=Solteras, Inc. + +OUI:00111A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00111B* + ID_OUI_FROM_DATABASE=Targa Systems Div L-3 Communications + +OUI:00111C* + ID_OUI_FROM_DATABASE=Pleora Technologies Inc. + +OUI:00111D* + ID_OUI_FROM_DATABASE=Hectrix Limited + +OUI:00111E* + ID_OUI_FROM_DATABASE=ETHERNET Powerlink Standarization Group (EPSG) + +OUI:00111F* + ID_OUI_FROM_DATABASE=Doremi Labs, Inc. + +OUI:001120* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001121* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001122* + ID_OUI_FROM_DATABASE=CIMSYS Inc + +OUI:001123* + ID_OUI_FROM_DATABASE=Appointech, Inc. + +OUI:001124* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001125* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:001126* + ID_OUI_FROM_DATABASE=Venstar Inc. + +OUI:001127* + ID_OUI_FROM_DATABASE=TASI, Inc + +OUI:001128* + ID_OUI_FROM_DATABASE=Streamit + +OUI:001129* + ID_OUI_FROM_DATABASE=Paradise Datacom Ltd. + +OUI:00112A* + ID_OUI_FROM_DATABASE=Niko NV + +OUI:00112B* + ID_OUI_FROM_DATABASE=NetModule AG + +OUI:00112C* + ID_OUI_FROM_DATABASE=IZT GmbH + +OUI:00112D* + ID_OUI_FROM_DATABASE=iPulse Systems + +OUI:00112E* + ID_OUI_FROM_DATABASE=CEICOM + +OUI:00112F* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:001130* + ID_OUI_FROM_DATABASE=Allied Telesis (Hong Kong) Ltd. + +OUI:001131* + ID_OUI_FROM_DATABASE=UNATECH. CO.,LTD + +OUI:001132* + ID_OUI_FROM_DATABASE=Synology Incorporated + +OUI:001133* + ID_OUI_FROM_DATABASE=Siemens AG Austria + +OUI:001134* + ID_OUI_FROM_DATABASE=MediaCell, Inc. + +OUI:001135* + ID_OUI_FROM_DATABASE=Grandeye Ltd + +OUI:001136* + ID_OUI_FROM_DATABASE=Goodrich Sensor Systems + +OUI:001137* + ID_OUI_FROM_DATABASE=AICHI ELECTRIC CO., LTD. + +OUI:001138* + ID_OUI_FROM_DATABASE=TAISHIN CO., LTD. + +OUI:001139* + ID_OUI_FROM_DATABASE=STOEBER ANTRIEBSTECHNIK GmbH + Co. KG. + +OUI:00113A* + ID_OUI_FROM_DATABASE=SHINBORAM + +OUI:00113B* + ID_OUI_FROM_DATABASE=Micronet Communications Inc. + +OUI:00113C* + ID_OUI_FROM_DATABASE=Micronas GmbH + +OUI:00113D* + ID_OUI_FROM_DATABASE=KN SOLTEC CO.,LTD. + +OUI:00113E* + ID_OUI_FROM_DATABASE=JL Corporation + +OUI:00113F* + ID_OUI_FROM_DATABASE=Alcatel DI + +OUI:001140* + ID_OUI_FROM_DATABASE=Nanometrics Inc. + +OUI:001141* + ID_OUI_FROM_DATABASE=GoodMan Corporation + +OUI:001142* + ID_OUI_FROM_DATABASE=e-SMARTCOM INC. + +OUI:001143* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:001144* + ID_OUI_FROM_DATABASE=Assurance Technology Corp + +OUI:001145* + ID_OUI_FROM_DATABASE=ValuePoint Networks + +OUI:001146* + ID_OUI_FROM_DATABASE=Telecard-Pribor Ltd + +OUI:001147* + ID_OUI_FROM_DATABASE=Secom-Industry co.LTD. + +OUI:001148* + ID_OUI_FROM_DATABASE=Prolon Control Systems + +OUI:001149* + ID_OUI_FROM_DATABASE=Proliphix Inc. + +OUI:00114A* + ID_OUI_FROM_DATABASE=KAYABA INDUSTRY Co,.Ltd. + +OUI:00114B* + ID_OUI_FROM_DATABASE=Francotyp-Postalia GmbH + +OUI:00114C* + ID_OUI_FROM_DATABASE=caffeina applied research ltd. + +OUI:00114D* + ID_OUI_FROM_DATABASE=Atsumi Electric Co.,LTD. + +OUI:00114E* + ID_OUI_FROM_DATABASE=690885 Ontario Inc. + +OUI:00114F* + ID_OUI_FROM_DATABASE=US Digital Television, Inc + +OUI:001150* + ID_OUI_FROM_DATABASE=Belkin Corporation + +OUI:001151* + ID_OUI_FROM_DATABASE=Mykotronx + +OUI:001152* + ID_OUI_FROM_DATABASE=Eidsvoll Electronics AS + +OUI:001153* + ID_OUI_FROM_DATABASE=Trident Tek, Inc. + +OUI:001154* + ID_OUI_FROM_DATABASE=Webpro Technologies Inc. + +OUI:001155* + ID_OUI_FROM_DATABASE=Sevis Systems + +OUI:001156* + ID_OUI_FROM_DATABASE=Pharos Systems NZ + +OUI:001157* + ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd. + +OUI:001158* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001159* + ID_OUI_FROM_DATABASE=MATISSE NETWORKS INC + +OUI:00115A* + ID_OUI_FROM_DATABASE=Ivoclar Vivadent AG + +OUI:00115B* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:00115C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00115D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00115E* + ID_OUI_FROM_DATABASE=ProMinent Dosiertechnik GmbH + +OUI:00115F* + ID_OUI_FROM_DATABASE=ITX Security Co., Ltd. + +OUI:001160* + ID_OUI_FROM_DATABASE=ARTDIO Company Co., LTD + +OUI:001161* + ID_OUI_FROM_DATABASE=NetStreams, LLC + +OUI:001162* + ID_OUI_FROM_DATABASE=STAR MICRONICS CO.,LTD. + +OUI:001163* + ID_OUI_FROM_DATABASE=SYSTEM SPA DEPT. ELECTRONICS + +OUI:001164* + ID_OUI_FROM_DATABASE=ACARD Technology Corp. + +OUI:001165* + ID_OUI_FROM_DATABASE=ZNYX Networks, Inc. + +OUI:001166* + ID_OUI_FROM_DATABASE=Taelim Electronics Co., Ltd. + +OUI:001167* + ID_OUI_FROM_DATABASE=Integrated System Solution Corp. + +OUI:001168* + ID_OUI_FROM_DATABASE=HomeLogic LLC + +OUI:001169* + ID_OUI_FROM_DATABASE=EMS Satcom + +OUI:00116A* + ID_OUI_FROM_DATABASE=Domo Ltd + +OUI:00116B* + ID_OUI_FROM_DATABASE=Digital Data Communications Asia Co.,Ltd + +OUI:00116C* + ID_OUI_FROM_DATABASE=Nanwang Multimedia Inc.,Ltd + +OUI:00116D* + ID_OUI_FROM_DATABASE=American Time and Signal + +OUI:00116E* + ID_OUI_FROM_DATABASE=Peplink International Ltd. + +OUI:00116F* + ID_OUI_FROM_DATABASE=Netforyou Co., LTD. + +OUI:001170* + ID_OUI_FROM_DATABASE=GSC SRL + +OUI:001171* + ID_OUI_FROM_DATABASE=DEXTER Communications, Inc. + +OUI:001172* + ID_OUI_FROM_DATABASE=COTRON CORPORATION + +OUI:001173* + ID_OUI_FROM_DATABASE=SMART Storage Systems + +OUI:001174* + ID_OUI_FROM_DATABASE=Mojo Networks, Inc. + +OUI:001175* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:001176* + ID_OUI_FROM_DATABASE=Intellambda Systems, Inc. + +OUI:001177* + ID_OUI_FROM_DATABASE=Coaxial Networks, Inc. + +OUI:001178* + ID_OUI_FROM_DATABASE=Chiron Technology Ltd + +OUI:001179* + ID_OUI_FROM_DATABASE=Singular Technology Co. Ltd. + +OUI:00117A* + ID_OUI_FROM_DATABASE=Singim International Corp. + +OUI:00117B* + ID_OUI_FROM_DATABASE=Büchi Labortechnik AG + +OUI:00117C* + ID_OUI_FROM_DATABASE=e-zy.net + +OUI:00117D* + ID_OUI_FROM_DATABASE=ZMD America, Inc. + +OUI:00117E* + ID_OUI_FROM_DATABASE=Midmark Corp + +OUI:00117F* + ID_OUI_FROM_DATABASE=Neotune Information Technology Corporation,.LTD + +OUI:001180* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001181* + ID_OUI_FROM_DATABASE=InterEnergy Co.Ltd, + +OUI:001182* + ID_OUI_FROM_DATABASE=IMI Norgren Ltd + +OUI:001183* + ID_OUI_FROM_DATABASE=Datalogic ADC, Inc. + +OUI:001184* + ID_OUI_FROM_DATABASE=Humo Laboratory,Ltd. + +OUI:001185* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001186* + ID_OUI_FROM_DATABASE=Prime Systems, Inc. + +OUI:001187* + ID_OUI_FROM_DATABASE=Category Solutions, Inc + +OUI:001188* + ID_OUI_FROM_DATABASE=Enterasys + +OUI:001189* + ID_OUI_FROM_DATABASE=Aerotech Inc + +OUI:00118A* + ID_OUI_FROM_DATABASE=Viewtran Technology Limited + +OUI:00118B* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise + +OUI:00118C* + ID_OUI_FROM_DATABASE=Missouri Department of Transportation + +OUI:00118D* + ID_OUI_FROM_DATABASE=Hanchang System Corp. + +OUI:00118E* + ID_OUI_FROM_DATABASE=Halytech Mace + +OUI:00118F* + ID_OUI_FROM_DATABASE=EUTECH INSTRUMENTS PTE. LTD. + +OUI:001190* + ID_OUI_FROM_DATABASE=Digital Design Corporation + +OUI:001191* + ID_OUI_FROM_DATABASE=CTS-Clima Temperatur Systeme GmbH + +OUI:001192* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001193* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001194* + ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc. + +OUI:001195* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:001196* + ID_OUI_FROM_DATABASE=Actuality Systems, Inc. + +OUI:001197* + ID_OUI_FROM_DATABASE=Monitoring Technologies Limited + +OUI:001198* + ID_OUI_FROM_DATABASE=Prism Media Products Limited + +OUI:001199* + ID_OUI_FROM_DATABASE=2wcom Systems GmbH + +OUI:00119A* + ID_OUI_FROM_DATABASE=Alkeria srl + +OUI:00119B* + ID_OUI_FROM_DATABASE=Telesynergy Research Inc. + +OUI:00119C* + ID_OUI_FROM_DATABASE=EP&T Energy + +OUI:00119D* + ID_OUI_FROM_DATABASE=Diginfo Technology Corporation + +OUI:00119E* + ID_OUI_FROM_DATABASE=Solectron Brazil + +OUI:00119F* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0011A0* + ID_OUI_FROM_DATABASE=Vtech Engineering Canada Ltd + +OUI:0011A1* + ID_OUI_FROM_DATABASE=VISION NETWARE CO.,LTD + +OUI:0011A2* + ID_OUI_FROM_DATABASE=Manufacturing Technology Inc + +OUI:0011A3* + ID_OUI_FROM_DATABASE=LanReady Technologies Inc. + +OUI:0011A4* + ID_OUI_FROM_DATABASE=JStream Technologies Inc. + +OUI:0011A5* + ID_OUI_FROM_DATABASE=Fortuna Electronic Corp. + +OUI:0011A6* + ID_OUI_FROM_DATABASE=Sypixx Networks + +OUI:0011A7* + ID_OUI_FROM_DATABASE=Infilco Degremont Inc. + +OUI:0011A8* + ID_OUI_FROM_DATABASE=Quest Technologies + +OUI:0011A9* + ID_OUI_FROM_DATABASE=MOIMSTONE Co., LTD + +OUI:0011AA* + ID_OUI_FROM_DATABASE=Uniclass Technology, Co., LTD + +OUI:0011AB* + ID_OUI_FROM_DATABASE=TRUSTABLE TECHNOLOGY CO.,LTD. + +OUI:0011AC* + ID_OUI_FROM_DATABASE=Simtec Electronics + +OUI:0011AD* + ID_OUI_FROM_DATABASE=Shanghai Ruijie Technology + +OUI:0011AE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0011AF* + ID_OUI_FROM_DATABASE=Medialink-i,Inc + +OUI:0011B0* + ID_OUI_FROM_DATABASE=Fortelink Inc. + +OUI:0011B1* + ID_OUI_FROM_DATABASE=BlueExpert Technology Corp. + +OUI:0011B2* + ID_OUI_FROM_DATABASE=2001 Technology Inc. + +OUI:0011B3* + ID_OUI_FROM_DATABASE=YOSHIMIYA CO.,LTD. + +OUI:0011B4* + ID_OUI_FROM_DATABASE=Westermo Network Technologies AB + +OUI:0011B5* + ID_OUI_FROM_DATABASE=Shenzhen Powercom Co.,Ltd + +OUI:0011B6* + ID_OUI_FROM_DATABASE=Open Systems International + +OUI:0011B7* + ID_OUI_FROM_DATABASE=Octalix B.V. + +OUI:0011B8* + ID_OUI_FROM_DATABASE=Liebherr - Elektronik GmbH + +OUI:0011B9* + ID_OUI_FROM_DATABASE=Inner Range Pty. Ltd. + +OUI:0011BA* + ID_OUI_FROM_DATABASE=Elexol Pty Ltd + +OUI:0011BB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0011BC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0011BD* + ID_OUI_FROM_DATABASE=Bombardier Transportation + +OUI:0011BE* + ID_OUI_FROM_DATABASE=AGP Telecom Co. Ltd + +OUI:0011BF* + ID_OUI_FROM_DATABASE=AESYS S.p.A. + +OUI:0011C0* + ID_OUI_FROM_DATABASE=Aday Technology Inc + +OUI:0011C1* + ID_OUI_FROM_DATABASE=4P MOBILE DATA PROCESSING + +OUI:0011C2* + ID_OUI_FROM_DATABASE=United Fiber Optic Communication + +OUI:0011C3* + ID_OUI_FROM_DATABASE=Transceiving System Technology Corporation + +OUI:0011C4* + ID_OUI_FROM_DATABASE=Terminales de Telecomunicacion Terrestre, S.L. + +OUI:0011C5* + ID_OUI_FROM_DATABASE=TEN Technology + +OUI:0011C6* + ID_OUI_FROM_DATABASE=Seagate Technology + +OUI:0011C7* + ID_OUI_FROM_DATABASE=Raymarine UK Ltd + +OUI:0011C8* + ID_OUI_FROM_DATABASE=Powercom Co., Ltd. + +OUI:0011C9* + ID_OUI_FROM_DATABASE=MTT Corporation + +OUI:0011CA* + ID_OUI_FROM_DATABASE=Long Range Systems, Inc. + +OUI:0011CB* + ID_OUI_FROM_DATABASE=Jacobsons AB + +OUI:0011CC* + ID_OUI_FROM_DATABASE=Guangzhou Jinpeng Group Co.,Ltd. + +OUI:0011CD* + ID_OUI_FROM_DATABASE=Axsun Technologies + +OUI:0011CE* + ID_OUI_FROM_DATABASE=Ubisense Limited + +OUI:0011CF* + ID_OUI_FROM_DATABASE=Thrane & Thrane A/S + +OUI:0011D0* + ID_OUI_FROM_DATABASE=Tandberg Data ASA + +OUI:0011D1* + ID_OUI_FROM_DATABASE=Soft Imaging System GmbH + +OUI:0011D2* + ID_OUI_FROM_DATABASE=Perception Digital Ltd + +OUI:0011D3* + ID_OUI_FROM_DATABASE=NextGenTel Holding ASA + +OUI:0011D4* + ID_OUI_FROM_DATABASE=NetEnrich, Inc + +OUI:0011D5* + ID_OUI_FROM_DATABASE=Hangzhou Sunyard System Engineering Co.,Ltd. + +OUI:0011D6* + ID_OUI_FROM_DATABASE=HandEra, Inc. + +OUI:0011D7* + ID_OUI_FROM_DATABASE=eWerks Inc + +OUI:0011D8* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:0011D9* + ID_OUI_FROM_DATABASE=TiVo + +OUI:0011DA* + ID_OUI_FROM_DATABASE=Vivaas Technology Inc. + +OUI:0011DB* + ID_OUI_FROM_DATABASE=Land-Cellular Corporation + +OUI:0011DC* + ID_OUI_FROM_DATABASE=Glunz & Jensen + +OUI:0011DD* + ID_OUI_FROM_DATABASE=FROMUS TEC. Co., Ltd. + +OUI:0011DE* + ID_OUI_FROM_DATABASE=EURILOGIC + +OUI:0011DF* + ID_OUI_FROM_DATABASE=Current Energy + +OUI:0011E0* + ID_OUI_FROM_DATABASE=U-MEDIA Communications, Inc. + +OUI:0011E1* + ID_OUI_FROM_DATABASE=Arcelik A.S + +OUI:0011E2* + ID_OUI_FROM_DATABASE=Hua Jung Components Co., Ltd. + +OUI:0011E3* + ID_OUI_FROM_DATABASE=Thomson, Inc. + +OUI:0011E4* + ID_OUI_FROM_DATABASE=Danelec Electronics A/S + +OUI:0011E5* + ID_OUI_FROM_DATABASE=KCodes Corporation + +OUI:0011E6* + ID_OUI_FROM_DATABASE=Scientific Atlanta + +OUI:0011E7* + ID_OUI_FROM_DATABASE=WORLDSAT - Texas de France + +OUI:0011E8* + ID_OUI_FROM_DATABASE=Tixi.Com + +OUI:0011E9* + ID_OUI_FROM_DATABASE=STARNEX CO., LTD. + +OUI:0011EA* + ID_OUI_FROM_DATABASE=IWICS Inc. + +OUI:0011EB* + ID_OUI_FROM_DATABASE=Innovative Integration + +OUI:0011EC* + ID_OUI_FROM_DATABASE=AVIX INC. + +OUI:0011ED* + ID_OUI_FROM_DATABASE=802 Global + +OUI:0011EE* + ID_OUI_FROM_DATABASE=Estari, Inc. + +OUI:0011EF* + ID_OUI_FROM_DATABASE=Conitec Datensysteme GmbH + +OUI:0011F0* + ID_OUI_FROM_DATABASE=Wideful Limited + +OUI:0011F1* + ID_OUI_FROM_DATABASE=QinetiQ Ltd + +OUI:0011F2* + ID_OUI_FROM_DATABASE=Institute of Network Technologies + +OUI:0011F3* + ID_OUI_FROM_DATABASE=NeoMedia Europe AG + +OUI:0011F4* + ID_OUI_FROM_DATABASE=woori-net + +OUI:0011F5* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:0011F6* + ID_OUI_FROM_DATABASE=Asia Pacific Microsystems , Inc. + +OUI:0011F7* + ID_OUI_FROM_DATABASE=Shenzhen Forward Industry Co., Ltd + +OUI:0011F8* + ID_OUI_FROM_DATABASE=AIRAYA Corp + +OUI:0011F9* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0011FA* + ID_OUI_FROM_DATABASE=Rane Corporation + +OUI:0011FB* + ID_OUI_FROM_DATABASE=Heidelberg Engineering GmbH + +OUI:0011FC* + ID_OUI_FROM_DATABASE=HARTING Electronics GmbH + +OUI:0011FD* + ID_OUI_FROM_DATABASE=KORG INC. + +OUI:0011FE* + ID_OUI_FROM_DATABASE=Keiyo System Research, Inc. + +OUI:0011FF* + ID_OUI_FROM_DATABASE=Digitro Tecnologia Ltda + +OUI:001200* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001201* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001202* + ID_OUI_FROM_DATABASE=Decrane Aerospace - Audio International Inc. + +OUI:001203* + ID_OUI_FROM_DATABASE=ActivNetworks + +OUI:001204* + ID_OUI_FROM_DATABASE=u10 Networks, Inc. + +OUI:001205* + ID_OUI_FROM_DATABASE=Terrasat Communications, Inc. + +OUI:001206* + ID_OUI_FROM_DATABASE=iQuest (NZ) Ltd + +OUI:001207* + ID_OUI_FROM_DATABASE=Head Strong International Limited + +OUI:001208* + ID_OUI_FROM_DATABASE=Gantner Instruments GmbH + +OUI:001209* + ID_OUI_FROM_DATABASE=Fastrax Ltd + +OUI:00120A* + ID_OUI_FROM_DATABASE=Emerson Climate Technologies GmbH + +OUI:00120B* + ID_OUI_FROM_DATABASE=Chinasys Technologies Limited + +OUI:00120C* + ID_OUI_FROM_DATABASE=CE-Infosys Pte Ltd + +OUI:00120D* + ID_OUI_FROM_DATABASE=Advanced Telecommunication Technologies, Inc. + +OUI:00120E* + ID_OUI_FROM_DATABASE=AboCom + +OUI:00120F* + ID_OUI_FROM_DATABASE=IEEE 802.3 + +OUI:001210* + ID_OUI_FROM_DATABASE=WideRay Corp + +OUI:001211* + ID_OUI_FROM_DATABASE=Protechna Herbst GmbH & Co. KG + +OUI:001212* + ID_OUI_FROM_DATABASE=PLUS Corporation + +OUI:001213* + ID_OUI_FROM_DATABASE=Metrohm AG + +OUI:001214* + ID_OUI_FROM_DATABASE=Koenig & Bauer AG + +OUI:001215* + ID_OUI_FROM_DATABASE=iStor Networks, Inc. + +OUI:001216* + ID_OUI_FROM_DATABASE=ICP Internet Communication Payment AG + +OUI:001217* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:001218* + ID_OUI_FROM_DATABASE=ARUZE Corporation + +OUI:001219* + ID_OUI_FROM_DATABASE=General Datacomm LLC + +OUI:00121A* + ID_OUI_FROM_DATABASE=Techno Soft Systemnics Inc. + +OUI:00121B* + ID_OUI_FROM_DATABASE=Sound Devices, LLC + +OUI:00121C* + ID_OUI_FROM_DATABASE=PARROT SA + +OUI:00121D* + ID_OUI_FROM_DATABASE=Netfabric Corporation + +OUI:00121E* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:00121F* + ID_OUI_FROM_DATABASE=Harding Instruments + +OUI:001220* + ID_OUI_FROM_DATABASE=Cadco Systems + +OUI:001221* + ID_OUI_FROM_DATABASE=B.Braun Melsungen AG + +OUI:001222* + ID_OUI_FROM_DATABASE=Skardin (UK) Ltd + +OUI:001223* + ID_OUI_FROM_DATABASE=Pixim + +OUI:001224* + ID_OUI_FROM_DATABASE=NexQL Corporation + +OUI:001225* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001226* + ID_OUI_FROM_DATABASE=Japan Direx Corporation + +OUI:001227* + ID_OUI_FROM_DATABASE=Franklin Electric Co., Inc. + +OUI:001228* + ID_OUI_FROM_DATABASE=Data Ltd. + +OUI:001229* + ID_OUI_FROM_DATABASE=BroadEasy Technologies Co.,Ltd + +OUI:00122A* + ID_OUI_FROM_DATABASE=VTech Telecommunications Ltd. + +OUI:00122B* + ID_OUI_FROM_DATABASE=Virbiage Pty Ltd + +OUI:00122C* + ID_OUI_FROM_DATABASE=Soenen Controls N.V. + +OUI:00122D* + ID_OUI_FROM_DATABASE=SiNett Corporation + +OUI:00122E* + ID_OUI_FROM_DATABASE=Signal Technology - AISD + +OUI:00122F* + ID_OUI_FROM_DATABASE=Sanei Electric Inc. + +OUI:001230* + ID_OUI_FROM_DATABASE=Picaso Infocommunication CO., LTD. + +OUI:001231* + ID_OUI_FROM_DATABASE=Motion Control Systems, Inc. + +OUI:001232* + ID_OUI_FROM_DATABASE=LeWiz Communications Inc. + +OUI:001233* + ID_OUI_FROM_DATABASE=JRC TOKKI Co.,Ltd. + +OUI:001234* + ID_OUI_FROM_DATABASE=Camille Bauer + +OUI:001235* + ID_OUI_FROM_DATABASE=Andrew Corporation + +OUI:001236* + ID_OUI_FROM_DATABASE=ConSentry Networks + +OUI:001237* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:001238* + ID_OUI_FROM_DATABASE=SetaBox Technology Co., Ltd. + +OUI:001239* + ID_OUI_FROM_DATABASE=S Net Systems Inc. + +OUI:00123A* + ID_OUI_FROM_DATABASE=Posystech Inc., Co. + +OUI:00123B* + ID_OUI_FROM_DATABASE=KeRo Systems ApS + +OUI:00123C* + ID_OUI_FROM_DATABASE=Second Rule LLC + +OUI:00123D* + ID_OUI_FROM_DATABASE=GES Co, Ltd + +OUI:00123E* + ID_OUI_FROM_DATABASE=ERUNE technology Co., Ltd. + +OUI:00123F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:001240* + ID_OUI_FROM_DATABASE=AMOI ELECTRONICS CO.,LTD + +OUI:001241* + ID_OUI_FROM_DATABASE=a2i marketing center + +OUI:001242* + ID_OUI_FROM_DATABASE=Millennial Net + +OUI:001243* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001244* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001245* + ID_OUI_FROM_DATABASE=Zellweger Analytics, Inc. + +OUI:001246* + ID_OUI_FROM_DATABASE=T.O.M TECHNOLOGY INC.. + +OUI:001247* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001248* + ID_OUI_FROM_DATABASE=Dell EMC + +OUI:001249* + ID_OUI_FROM_DATABASE=Delta Elettronica S.p.A. + +OUI:00124A* + ID_OUI_FROM_DATABASE=Dedicated Devices, Inc. + +OUI:00124B* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:00124C* + ID_OUI_FROM_DATABASE=BBWM Corporation + +OUI:00124D* + ID_OUI_FROM_DATABASE=Inducon BV + +OUI:00124E* + ID_OUI_FROM_DATABASE=XAC AUTOMATION CORP. + +OUI:00124F* + ID_OUI_FROM_DATABASE=nVent + +OUI:001250* + ID_OUI_FROM_DATABASE=Tokyo Aircaft Instrument Co., Ltd. + +OUI:001251* + ID_OUI_FROM_DATABASE=SILINK + +OUI:001252* + ID_OUI_FROM_DATABASE=Citronix, LLC + +OUI:001253* + ID_OUI_FROM_DATABASE=AudioDev AB + +OUI:001254* + ID_OUI_FROM_DATABASE=Spectra Technologies Holdings Company Ltd + +OUI:001255* + ID_OUI_FROM_DATABASE=NetEffect Incorporated + +OUI:001256* + ID_OUI_FROM_DATABASE=LG INFORMATION & COMM. + +OUI:001257* + ID_OUI_FROM_DATABASE=LeapComm Communication Technologies Inc. + +OUI:001258* + ID_OUI_FROM_DATABASE=TechVoIP Sp z o.o. + +OUI:001259* + ID_OUI_FROM_DATABASE=THERMO ELECTRON KARLSRUHE + +OUI:00125A* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:00125B* + ID_OUI_FROM_DATABASE=KAIMEI ELECTRONI + +OUI:00125C* + ID_OUI_FROM_DATABASE=Green Hills Software, Inc. + +OUI:00125D* + ID_OUI_FROM_DATABASE=CyberNet Inc. + +OUI:00125E* + ID_OUI_FROM_DATABASE=CAEN + +OUI:00125F* + ID_OUI_FROM_DATABASE=AWIND Inc. + +OUI:001260* + ID_OUI_FROM_DATABASE=Stanton Magnetics,inc. + +OUI:001261* + ID_OUI_FROM_DATABASE=Adaptix, Inc + +OUI:001262* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001263* + ID_OUI_FROM_DATABASE=Data Voice Technologies GmbH + +OUI:001264* + ID_OUI_FROM_DATABASE=daum electronic gmbh + +OUI:001265* + ID_OUI_FROM_DATABASE=Enerdyne Technologies, Inc. + +OUI:001266* + ID_OUI_FROM_DATABASE=Swisscom Hospitality Services SA + +OUI:001267* + ID_OUI_FROM_DATABASE=Panasonic Corporation + +OUI:001268* + ID_OUI_FROM_DATABASE=IPS d.o.o. + +OUI:001269* + ID_OUI_FROM_DATABASE=Value Electronics + +OUI:00126A* + ID_OUI_FROM_DATABASE=OPTOELECTRONICS Co., Ltd. + +OUI:00126B* + ID_OUI_FROM_DATABASE=Ascalade Communications Limited + +OUI:00126C* + ID_OUI_FROM_DATABASE=Visonic Technologies 1993 Ltd. + +OUI:00126D* + ID_OUI_FROM_DATABASE=University of California, Berkeley + +OUI:00126E* + ID_OUI_FROM_DATABASE=Seidel Elektronik GmbH Nfg.KG + +OUI:00126F* + ID_OUI_FROM_DATABASE=Rayson Technology Co., Ltd. + +OUI:001270* + ID_OUI_FROM_DATABASE=NGES Denro Systems + +OUI:001271* + ID_OUI_FROM_DATABASE=Measurement Computing Corp + +OUI:001272* + ID_OUI_FROM_DATABASE=Redux Communications Ltd. + +OUI:001273* + ID_OUI_FROM_DATABASE=Stoke Inc + +OUI:001274* + ID_OUI_FROM_DATABASE=NIT lab + +OUI:001275* + ID_OUI_FROM_DATABASE=Sentilla Corporation + +OUI:001276* + ID_OUI_FROM_DATABASE=CG Power Systems Ireland Limited + +OUI:001277* + ID_OUI_FROM_DATABASE=Korenix Technologies Co., Ltd. + +OUI:001278* + ID_OUI_FROM_DATABASE=International Bar Code + +OUI:001279* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:00127A* + ID_OUI_FROM_DATABASE=Sanyu Industry Co.,Ltd. + +OUI:00127B* + ID_OUI_FROM_DATABASE=VIA Networking Technologies, Inc. + +OUI:00127C* + ID_OUI_FROM_DATABASE=SWEGON AB + +OUI:00127D* + ID_OUI_FROM_DATABASE=MobileAria + +OUI:00127E* + ID_OUI_FROM_DATABASE=Digital Lifestyles Group, Inc. + +OUI:00127F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001280* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001281* + ID_OUI_FROM_DATABASE=March Networks S.p.A. + +OUI:001282* + ID_OUI_FROM_DATABASE=Qovia + +OUI:001283* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001284* + ID_OUI_FROM_DATABASE=Lab33 Srl + +OUI:001285* + ID_OUI_FROM_DATABASE=Gizmondo Europe Ltd + +OUI:001286* + ID_OUI_FROM_DATABASE=ENDEVCO CORP + +OUI:001287* + ID_OUI_FROM_DATABASE=Digital Everywhere Unterhaltungselektronik GmbH + +OUI:001288* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:001289* + ID_OUI_FROM_DATABASE=Advance Sterilization Products + +OUI:00128A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00128B* + ID_OUI_FROM_DATABASE=Sensory Networks Inc + +OUI:00128C* + ID_OUI_FROM_DATABASE=Woodward Governor + +OUI:00128D* + ID_OUI_FROM_DATABASE=STB Datenservice GmbH + +OUI:00128E* + ID_OUI_FROM_DATABASE=Q-Free ASA + +OUI:00128F* + ID_OUI_FROM_DATABASE=Montilio + +OUI:001290* + ID_OUI_FROM_DATABASE=KYOWA Electric & Machinery Corp. + +OUI:001291* + ID_OUI_FROM_DATABASE=KWS Computersysteme GmbH + +OUI:001292* + ID_OUI_FROM_DATABASE=Griffin Technology + +OUI:001293* + ID_OUI_FROM_DATABASE=GE Energy + +OUI:001294* + ID_OUI_FROM_DATABASE=SUMITOMO ELECTRIC DEVICE INNOVATIONS, INC + +OUI:001295* + ID_OUI_FROM_DATABASE=Aiware Inc. + +OUI:001296* + ID_OUI_FROM_DATABASE=Addlogix + +OUI:001297* + ID_OUI_FROM_DATABASE=O2Micro, Inc. + +OUI:001298* + ID_OUI_FROM_DATABASE=MICO ELECTRIC(SHENZHEN) LIMITED + +OUI:001299* + ID_OUI_FROM_DATABASE=Ktech Telecommunications Inc + +OUI:00129A* + ID_OUI_FROM_DATABASE=IRT Electronics Pty Ltd + +OUI:00129B* + ID_OUI_FROM_DATABASE=E2S Electronic Engineering Solutions, S.L. + +OUI:00129C* + ID_OUI_FROM_DATABASE=Yulinet + +OUI:00129D* + ID_OUI_FROM_DATABASE=First International Computer do Brasil + +OUI:00129E* + ID_OUI_FROM_DATABASE=Surf Communications Inc. + +OUI:00129F* + ID_OUI_FROM_DATABASE=RAE Systems + +OUI:0012A0* + ID_OUI_FROM_DATABASE=NeoMeridian Sdn Bhd + +OUI:0012A1* + ID_OUI_FROM_DATABASE=BluePacket Communications Co., Ltd. + +OUI:0012A2* + ID_OUI_FROM_DATABASE=VITA + +OUI:0012A3* + ID_OUI_FROM_DATABASE=Trust International B.V. + +OUI:0012A4* + ID_OUI_FROM_DATABASE=ThingMagic, LLC + +OUI:0012A5* + ID_OUI_FROM_DATABASE=Dolphin Interconnect Solutions AS + +OUI:0012A6* + ID_OUI_FROM_DATABASE=Dolby Australia + +OUI:0012A7* + ID_OUI_FROM_DATABASE=ISR TECHNOLOGIES Inc + +OUI:0012A8* + ID_OUI_FROM_DATABASE=intec GmbH + +OUI:0012A9* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:0012AA* + ID_OUI_FROM_DATABASE=IEE, Inc. + +OUI:0012AB* + ID_OUI_FROM_DATABASE=WiLife, Inc. + +OUI:0012AC* + ID_OUI_FROM_DATABASE=ONTIMETEK INC. + +OUI:0012AD* + ID_OUI_FROM_DATABASE=IDS GmbH + +OUI:0012AE* + ID_OUI_FROM_DATABASE=HLS HARD-LINE Solutions Inc. + +OUI:0012AF* + ID_OUI_FROM_DATABASE=ELPRO Technologies + +OUI:0012B0* + ID_OUI_FROM_DATABASE=Efore Oyj (Plc) + +OUI:0012B1* + ID_OUI_FROM_DATABASE=Dai Nippon Printing Co., Ltd + +OUI:0012B2* + ID_OUI_FROM_DATABASE=AVOLITES LTD. + +OUI:0012B3* + ID_OUI_FROM_DATABASE=Advance Wireless Technology Corp. + +OUI:0012B4* + ID_OUI_FROM_DATABASE=Work Microwave GmbH + +OUI:0012B5* + ID_OUI_FROM_DATABASE=Vialta, Inc. + +OUI:0012B6* + ID_OUI_FROM_DATABASE=Santa Barbara Infrared, Inc. + +OUI:0012B7* + ID_OUI_FROM_DATABASE=PTW Freiburg + +OUI:0012B8* + ID_OUI_FROM_DATABASE=G2 Microsystems + +OUI:0012B9* + ID_OUI_FROM_DATABASE=Fusion Digital Technology + +OUI:0012BA* + ID_OUI_FROM_DATABASE=FSI Systems, Inc. + +OUI:0012BB* + ID_OUI_FROM_DATABASE=Telecommunications Industry Association TR-41 Committee + +OUI:0012BC* + ID_OUI_FROM_DATABASE=Echolab LLC + +OUI:0012BD* + ID_OUI_FROM_DATABASE=Avantec Manufacturing Limited + +OUI:0012BE* + ID_OUI_FROM_DATABASE=Astek Corporation + +OUI:0012BF* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:0012C0* + ID_OUI_FROM_DATABASE=HotLava Systems, Inc. + +OUI:0012C1* + ID_OUI_FROM_DATABASE=Check Point Software Technologies + +OUI:0012C2* + ID_OUI_FROM_DATABASE=Apex Electronics Factory + +OUI:0012C3* + ID_OUI_FROM_DATABASE=WIT S.A. + +OUI:0012C4* + ID_OUI_FROM_DATABASE=Viseon, Inc. + +OUI:0012C5* + ID_OUI_FROM_DATABASE=V-Show Technology (China) Co.,Ltd + +OUI:0012C6* + ID_OUI_FROM_DATABASE=TGC America, Inc + +OUI:0012C7* + ID_OUI_FROM_DATABASE=SECURAY Technologies Ltd.Co. + +OUI:0012C8* + ID_OUI_FROM_DATABASE=Perfect tech + +OUI:0012C9* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0012CA* + ID_OUI_FROM_DATABASE=Mechatronic Brick Aps + +OUI:0012CB* + ID_OUI_FROM_DATABASE=CSS Inc. + +OUI:0012CC* + ID_OUI_FROM_DATABASE=Bitatek CO., LTD + +OUI:0012CD* + ID_OUI_FROM_DATABASE=ASEM SpA + +OUI:0012CE* + ID_OUI_FROM_DATABASE=Advanced Cybernetics Group + +OUI:0012CF* + ID_OUI_FROM_DATABASE=Accton Technology Corp + +OUI:0012D0* + ID_OUI_FROM_DATABASE=Gossen-Metrawatt-GmbH + +OUI:0012D1* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0012D2* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0012D3* + ID_OUI_FROM_DATABASE=Zetta Systems, Inc. + +OUI:0012D4* + ID_OUI_FROM_DATABASE=Princeton Technology, Ltd + +OUI:0012D5* + ID_OUI_FROM_DATABASE=Motion Reality Inc. + +OUI:0012D6* + ID_OUI_FROM_DATABASE=Jiangsu Yitong High-Tech Co.,Ltd + +OUI:0012D7* + ID_OUI_FROM_DATABASE=Invento Networks, Inc. + +OUI:0012D8* + ID_OUI_FROM_DATABASE=International Games System Co., Ltd. + +OUI:0012D9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0012DA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0012DB* + ID_OUI_FROM_DATABASE=ZIEHL industrie-elektronik GmbH + Co KG + +OUI:0012DC* + ID_OUI_FROM_DATABASE=SunCorp Industrial Limited + +OUI:0012DD* + ID_OUI_FROM_DATABASE=Shengqu Information Technology (Shanghai) Co., Ltd. + +OUI:0012DE* + ID_OUI_FROM_DATABASE=Radio Components Sweden AB + +OUI:0012DF* + ID_OUI_FROM_DATABASE=Novomatic AG + +OUI:0012E0* + ID_OUI_FROM_DATABASE=Codan Limited + +OUI:0012E1* + ID_OUI_FROM_DATABASE=Alliant Networks, Inc + +OUI:0012E2* + ID_OUI_FROM_DATABASE=ALAXALA Networks Corporation + +OUI:0012E3* + ID_OUI_FROM_DATABASE=Agat-RT, Ltd. + +OUI:0012E4* + ID_OUI_FROM_DATABASE=ZIEHL industrie-electronik GmbH + Co KG + +OUI:0012E5* + ID_OUI_FROM_DATABASE=Time America, Inc. + +OUI:0012E6* + ID_OUI_FROM_DATABASE=SPECTEC COMPUTER CO., LTD. + +OUI:0012E7* + ID_OUI_FROM_DATABASE=Projectek Networking Electronics Corp. + +OUI:0012E8* + ID_OUI_FROM_DATABASE=Fraunhofer IMS + +OUI:0012E9* + ID_OUI_FROM_DATABASE=Abbey Systems Ltd + +OUI:0012EA* + ID_OUI_FROM_DATABASE=Trane + +OUI:0012EB* + ID_OUI_FROM_DATABASE=PDH Solutions, LLC + +OUI:0012EC* + ID_OUI_FROM_DATABASE=Movacolor b.v. + +OUI:0012ED* + ID_OUI_FROM_DATABASE=AVG Advanced Technologies + +OUI:0012EE* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:0012EF* + ID_OUI_FROM_DATABASE=OneAccess SA + +OUI:0012F0* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0012F1* + ID_OUI_FROM_DATABASE=IFOTEC + +OUI:0012F2* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:0012F3* + ID_OUI_FROM_DATABASE=connectBlue AB + +OUI:0012F4* + ID_OUI_FROM_DATABASE=Belco International Co.,Ltd. + +OUI:0012F5* + ID_OUI_FROM_DATABASE=Imarda New Zealand Limited + +OUI:0012F6* + ID_OUI_FROM_DATABASE=MDK CO.,LTD. + +OUI:0012F7* + ID_OUI_FROM_DATABASE=Xiamen Xinglian Electronics Co., Ltd. + +OUI:0012F8* + ID_OUI_FROM_DATABASE=WNI Resources, LLC + +OUI:0012F9* + ID_OUI_FROM_DATABASE=URYU SEISAKU, LTD. + +OUI:0012FA* + ID_OUI_FROM_DATABASE=THX LTD + +OUI:0012FB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0012FC* + ID_OUI_FROM_DATABASE=PLANET System Co.,LTD + +OUI:0012FD* + ID_OUI_FROM_DATABASE=OPTIMUS IC S.A. + +OUI:0012FE* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:0012FF* + ID_OUI_FROM_DATABASE=Lely Industries N.V. + +OUI:001300* + ID_OUI_FROM_DATABASE=IT-FACTORY, INC. + +OUI:001301* + ID_OUI_FROM_DATABASE=IronGate S.L. + +OUI:001302* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001303* + ID_OUI_FROM_DATABASE=GateConnect + +OUI:001304* + ID_OUI_FROM_DATABASE=Flaircomm Technologies Co. LTD + +OUI:001305* + ID_OUI_FROM_DATABASE=Epicom, Inc. + +OUI:001306* + ID_OUI_FROM_DATABASE=Always On Wireless + +OUI:001307* + ID_OUI_FROM_DATABASE=Paravirtual Corporation + +OUI:001308* + ID_OUI_FROM_DATABASE=Nuvera Fuel Cells + +OUI:001309* + ID_OUI_FROM_DATABASE=Ocean Broadband Networks + +OUI:00130A* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:00130B* + ID_OUI_FROM_DATABASE=Mextal B.V. + +OUI:00130C* + ID_OUI_FROM_DATABASE=HF System Corporation + +OUI:00130D* + ID_OUI_FROM_DATABASE=GALILEO AVIONICA + +OUI:00130E* + ID_OUI_FROM_DATABASE=Focusrite Audio Engineering Limited + +OUI:00130F* + ID_OUI_FROM_DATABASE=EGEMEN Bilgisayar Muh San ve Tic LTD STI + +OUI:001310* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:001311* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001312* + ID_OUI_FROM_DATABASE=Amedia Networks Inc. + +OUI:001313* + ID_OUI_FROM_DATABASE=GuangZhou Post & Telecom Equipment ltd + +OUI:001314* + ID_OUI_FROM_DATABASE=Asiamajor Inc. + +OUI:001315* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:001316* + ID_OUI_FROM_DATABASE=L-S-B Broadcast Technologies GmbH + +OUI:001317* + ID_OUI_FROM_DATABASE=GN Netcom A/S + +OUI:001318* + ID_OUI_FROM_DATABASE=DGSTATION Co., Ltd. + +OUI:001319* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00131A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00131B* + ID_OUI_FROM_DATABASE=BeCell Innovations Corp. + +OUI:00131C* + ID_OUI_FROM_DATABASE=LiteTouch, Inc. + +OUI:00131D* + ID_OUI_FROM_DATABASE=Scanvaegt International A/S + +OUI:00131E* + ID_OUI_FROM_DATABASE=peiker acustic GmbH + +OUI:00131F* + ID_OUI_FROM_DATABASE=NxtPhase T&D, Corp. + +OUI:001320* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001321* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001322* + ID_OUI_FROM_DATABASE=DAQ Electronics, Inc. + +OUI:001323* + ID_OUI_FROM_DATABASE=Cap Co., Ltd. + +OUI:001324* + ID_OUI_FROM_DATABASE=Schneider Electric Ultra Terminal + +OUI:001325* + ID_OUI_FROM_DATABASE=Cortina Systems Inc + +OUI:001326* + ID_OUI_FROM_DATABASE=ECM Systems Ltd + +OUI:001327* + ID_OUI_FROM_DATABASE=Data Acquisitions limited + +OUI:001328* + ID_OUI_FROM_DATABASE=Westech Korea Inc., + +OUI:001329* + ID_OUI_FROM_DATABASE=VSST Co., LTD + +OUI:00132A* + ID_OUI_FROM_DATABASE=Sitronics Telecom Solutions + +OUI:00132B* + ID_OUI_FROM_DATABASE=Phoenix Digital + +OUI:00132C* + ID_OUI_FROM_DATABASE=MAZ Brandenburg GmbH + +OUI:00132D* + ID_OUI_FROM_DATABASE=iWise Communications + +OUI:00132E* + ID_OUI_FROM_DATABASE=ITian Coporation + +OUI:00132F* + ID_OUI_FROM_DATABASE=Interactek + +OUI:001330* + ID_OUI_FROM_DATABASE=EURO PROTECTION SURVEILLANCE + +OUI:001331* + ID_OUI_FROM_DATABASE=CellPoint Connect + +OUI:001332* + ID_OUI_FROM_DATABASE=Beijing Topsec Network Security Technology Co., Ltd. + +OUI:001333* + ID_OUI_FROM_DATABASE=BaudTec Corporation + +OUI:001334* + ID_OUI_FROM_DATABASE=Arkados, Inc. + +OUI:001335* + ID_OUI_FROM_DATABASE=VS Industry Berhad + +OUI:001336* + ID_OUI_FROM_DATABASE=Tianjin 712 Communication Broadcasting co., ltd. + +OUI:001337* + ID_OUI_FROM_DATABASE=Orient Power Home Network Ltd. + +OUI:001338* + ID_OUI_FROM_DATABASE=FRESENIUS-VIAL + +OUI:001339* + ID_OUI_FROM_DATABASE=CCV Deutschland GmbH + +OUI:00133A* + ID_OUI_FROM_DATABASE=VadaTech Inc. + +OUI:00133B* + ID_OUI_FROM_DATABASE=Speed Dragon Multimedia Limited + +OUI:00133C* + ID_OUI_FROM_DATABASE=QUINTRON SYSTEMS INC. + +OUI:00133D* + ID_OUI_FROM_DATABASE=Micro Memory Curtiss Wright Co + +OUI:00133E* + ID_OUI_FROM_DATABASE=MetaSwitch + +OUI:00133F* + ID_OUI_FROM_DATABASE=Eppendorf Instrumente GmbH + +OUI:001340* + ID_OUI_FROM_DATABASE=AD.EL s.r.l. + +OUI:001341* + ID_OUI_FROM_DATABASE=Shandong New Beiyang Information Technology Co.,Ltd + +OUI:001342* + ID_OUI_FROM_DATABASE=Vision Research, Inc. + +OUI:001343* + ID_OUI_FROM_DATABASE=Matsushita Electronic Components (Europe) GmbH + +OUI:001344* + ID_OUI_FROM_DATABASE=Fargo Electronics Inc. + +OUI:001345* + ID_OUI_FROM_DATABASE=Eaton Corporation + +OUI:001346* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:001347* + ID_OUI_FROM_DATABASE=Red Lion Controls, LP + +OUI:001348* + ID_OUI_FROM_DATABASE=Artila Electronics Co., Ltd. + +OUI:001349* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:00134A* + ID_OUI_FROM_DATABASE=Engim, Inc. + +OUI:00134B* + ID_OUI_FROM_DATABASE=ToGoldenNet Technology Inc. + +OUI:00134C* + ID_OUI_FROM_DATABASE=YDT Technology International + +OUI:00134D* + ID_OUI_FROM_DATABASE=Inepro BV + +OUI:00134E* + ID_OUI_FROM_DATABASE=Valox Systems, Inc. + +OUI:00134F* + ID_OUI_FROM_DATABASE=Rapidus Wireless Networks Inc. + +OUI:001350* + ID_OUI_FROM_DATABASE=Silver Spring Networks, Inc + +OUI:001351* + ID_OUI_FROM_DATABASE=Niles Audio Corporation + +OUI:001352* + ID_OUI_FROM_DATABASE=Naztec, Inc. + +OUI:001353* + ID_OUI_FROM_DATABASE=HYDAC Filtertechnik GMBH + +OUI:001354* + ID_OUI_FROM_DATABASE=Zcomax Technologies, Inc. + +OUI:001355* + ID_OUI_FROM_DATABASE=TOMEN Cyber-business Solutions, Inc. + +OUI:001356* + ID_OUI_FROM_DATABASE=FLIR Radiation Inc + +OUI:001357* + ID_OUI_FROM_DATABASE=Soyal Technology Co., Ltd. + +OUI:001358* + ID_OUI_FROM_DATABASE=Realm Systems, Inc. + +OUI:001359* + ID_OUI_FROM_DATABASE=ProTelevision Technologies A/S + +OUI:00135A* + ID_OUI_FROM_DATABASE=Project T&E Limited + +OUI:00135B* + ID_OUI_FROM_DATABASE=PanelLink Cinema, LLC + +OUI:00135C* + ID_OUI_FROM_DATABASE=OnSite Systems, Inc. + +OUI:00135D* + ID_OUI_FROM_DATABASE=NTTPC Communications, Inc. + +OUI:00135E* + ID_OUI_FROM_DATABASE=EAB/RWI/K + +OUI:00135F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001360* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001361* + ID_OUI_FROM_DATABASE=Biospace Co., Ltd. + +OUI:001362* + ID_OUI_FROM_DATABASE=ShinHeung Precision Co., Ltd. + +OUI:001363* + ID_OUI_FROM_DATABASE=Verascape, Inc. + +OUI:001364* + ID_OUI_FROM_DATABASE=Paradigm Technology Inc.. + +OUI:001365* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001366* + ID_OUI_FROM_DATABASE=Neturity Technologies Inc. + +OUI:001367* + ID_OUI_FROM_DATABASE=Narayon. Co., Ltd. + +OUI:001368* + ID_OUI_FROM_DATABASE=Saab Danmark A/S + +OUI:001369* + ID_OUI_FROM_DATABASE=Honda Electron Co., LED. + +OUI:00136A* + ID_OUI_FROM_DATABASE=Hach Lange Sarl + +OUI:00136B* + ID_OUI_FROM_DATABASE=E-TEC + +OUI:00136C* + ID_OUI_FROM_DATABASE=TomTom + +OUI:00136D* + ID_OUI_FROM_DATABASE=Tentaculus AB + +OUI:00136E* + ID_OUI_FROM_DATABASE=Techmetro Corp. + +OUI:00136F* + ID_OUI_FROM_DATABASE=PacketMotion, Inc. + +OUI:001370* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001371* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001372* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:001373* + ID_OUI_FROM_DATABASE=BLwave Electronics Co., Ltd + +OUI:001374* + ID_OUI_FROM_DATABASE=Atheros Communications, Inc. + +OUI:001375* + ID_OUI_FROM_DATABASE=American Security Products Co. + +OUI:001376* + ID_OUI_FROM_DATABASE=Tabor Electronics Ltd. + +OUI:001377* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001378* + ID_OUI_FROM_DATABASE=Qsan Technology, Inc. + +OUI:001379* + ID_OUI_FROM_DATABASE=PONDER INFORMATION INDUSTRIES LTD. + +OUI:00137A* + ID_OUI_FROM_DATABASE=Netvox Technology Co., Ltd. + +OUI:00137B* + ID_OUI_FROM_DATABASE=Movon Corporation + +OUI:00137C* + ID_OUI_FROM_DATABASE=Kaicom co., Ltd. + +OUI:00137D* + ID_OUI_FROM_DATABASE=Dynalab, Inc. + +OUI:00137E* + ID_OUI_FROM_DATABASE=CorEdge Networks, Inc. + +OUI:00137F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001380* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001381* + ID_OUI_FROM_DATABASE=CHIPS & Systems, Inc. + +OUI:001382* + ID_OUI_FROM_DATABASE=Cetacea Networks Corporation + +OUI:001383* + ID_OUI_FROM_DATABASE=Application Technologies and Engineering Research Laboratory + +OUI:001384* + ID_OUI_FROM_DATABASE=Advanced Motion Controls + +OUI:001385* + ID_OUI_FROM_DATABASE=Add-On Technology Co., LTD. + +OUI:001386* + ID_OUI_FROM_DATABASE=ABB Inc/Totalflow + +OUI:001387* + ID_OUI_FROM_DATABASE=27M Technologies AB + +OUI:001388* + ID_OUI_FROM_DATABASE=WiMedia Alliance + +OUI:001389* + ID_OUI_FROM_DATABASE=Redes de Telefonía Móvil S.A. + +OUI:00138A* + ID_OUI_FROM_DATABASE=Qingdao GoerTek Technology Co., Ltd. + +OUI:00138B* + ID_OUI_FROM_DATABASE=Phantom Technologies LLC + +OUI:00138C* + ID_OUI_FROM_DATABASE=Kumyoung.Co.Ltd + +OUI:00138D* + ID_OUI_FROM_DATABASE=Kinghold + +OUI:00138E* + ID_OUI_FROM_DATABASE=FOAB Elektronik AB + +OUI:00138F* + ID_OUI_FROM_DATABASE=Asiarock Technology Limited + +OUI:001390* + ID_OUI_FROM_DATABASE=Termtek Computer Co., Ltd + +OUI:001391* + ID_OUI_FROM_DATABASE=OUEN CO.,LTD. + +OUI:001392* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:001393* + ID_OUI_FROM_DATABASE=Panta Systems, Inc. + +OUI:001394* + ID_OUI_FROM_DATABASE=Infohand Co.,Ltd + +OUI:001395* + ID_OUI_FROM_DATABASE=congatec AG + +OUI:001396* + ID_OUI_FROM_DATABASE=Acbel Polytech Inc. + +OUI:001397* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:001398* + ID_OUI_FROM_DATABASE=TrafficSim Co.,Ltd + +OUI:001399* + ID_OUI_FROM_DATABASE=STAC Corporation. + +OUI:00139A* + ID_OUI_FROM_DATABASE=K-ubique ID Corp. + +OUI:00139B* + ID_OUI_FROM_DATABASE=ioIMAGE Ltd. + +OUI:00139C* + ID_OUI_FROM_DATABASE=Exavera Technologies, Inc. + +OUI:00139D* + ID_OUI_FROM_DATABASE=MaxLinear Hispania S.L.U. + +OUI:00139E* + ID_OUI_FROM_DATABASE=Ciara Technologies Inc. + +OUI:00139F* + ID_OUI_FROM_DATABASE=Electronics Design Services, Co., Ltd. + +OUI:0013A0* + ID_OUI_FROM_DATABASE=ALGOSYSTEM Co., Ltd. + +OUI:0013A1* + ID_OUI_FROM_DATABASE=Crow Electronic Engeneering + +OUI:0013A2* + ID_OUI_FROM_DATABASE=MaxStream, Inc + +OUI:0013A3* + ID_OUI_FROM_DATABASE=Siemens Home & Office Comm. Devices + +OUI:0013A4* + ID_OUI_FROM_DATABASE=KeyEye Communications + +OUI:0013A5* + ID_OUI_FROM_DATABASE=General Solutions, LTD. + +OUI:0013A6* + ID_OUI_FROM_DATABASE=Extricom Ltd + +OUI:0013A7* + ID_OUI_FROM_DATABASE=BATTELLE MEMORIAL INSTITUTE + +OUI:0013A8* + ID_OUI_FROM_DATABASE=Tanisys Technology + +OUI:0013A9* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:0013AA* + ID_OUI_FROM_DATABASE=ALS & TEC Ltd. + +OUI:0013AB* + ID_OUI_FROM_DATABASE=Telemotive AG + +OUI:0013AC* + ID_OUI_FROM_DATABASE=Sunmyung Electronics Co., LTD + +OUI:0013AD* + ID_OUI_FROM_DATABASE=Sendo Ltd + +OUI:0013AE* + ID_OUI_FROM_DATABASE=Radiance Technologies, Inc. + +OUI:0013AF* + ID_OUI_FROM_DATABASE=NUMA Technology,Inc. + +OUI:0013B0* + ID_OUI_FROM_DATABASE=Jablotron + +OUI:0013B1* + ID_OUI_FROM_DATABASE=Intelligent Control Systems (Asia) Pte Ltd + +OUI:0013B2* + ID_OUI_FROM_DATABASE=Carallon Limited + +OUI:0013B3* + ID_OUI_FROM_DATABASE=Ecom Communications Technology Co., Ltd. + +OUI:0013B4* + ID_OUI_FROM_DATABASE=Appear TV + +OUI:0013B5* + ID_OUI_FROM_DATABASE=Wavesat + +OUI:0013B6* + ID_OUI_FROM_DATABASE=Sling Media, Inc. + +OUI:0013B7* + ID_OUI_FROM_DATABASE=Scantech ID + +OUI:0013B8* + ID_OUI_FROM_DATABASE=RyCo Electronic Systems Limited + +OUI:0013B9* + ID_OUI_FROM_DATABASE=BM SPA + +OUI:0013BA* + ID_OUI_FROM_DATABASE=ReadyLinks Inc + +OUI:0013BB* + ID_OUI_FROM_DATABASE=Smartvue Corporation + +OUI:0013BC* + ID_OUI_FROM_DATABASE=Artimi Ltd + +OUI:0013BD* + ID_OUI_FROM_DATABASE=HYMATOM SA + +OUI:0013BE* + ID_OUI_FROM_DATABASE=Virtual Conexions + +OUI:0013BF* + ID_OUI_FROM_DATABASE=Media System Planning Corp. + +OUI:0013C0* + ID_OUI_FROM_DATABASE=Trix Tecnologia Ltda. + +OUI:0013C1* + ID_OUI_FROM_DATABASE=Asoka USA Corporation + +OUI:0013C2* + ID_OUI_FROM_DATABASE=WACOM Co.,Ltd + +OUI:0013C3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0013C4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0013C5* + ID_OUI_FROM_DATABASE=LIGHTRON FIBER-OPTIC DEVICES INC. + +OUI:0013C6* + ID_OUI_FROM_DATABASE=OpenGear, Inc + +OUI:0013C7* + ID_OUI_FROM_DATABASE=IONOS Co.,Ltd. + +OUI:0013C8* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:0013C9* + ID_OUI_FROM_DATABASE=Beyond Achieve Enterprises Ltd. + +OUI:0013CA* + ID_OUI_FROM_DATABASE=Pico Digital + +OUI:0013CB* + ID_OUI_FROM_DATABASE=Zenitel Norway AS + +OUI:0013CC* + ID_OUI_FROM_DATABASE=Tall Maple Systems + +OUI:0013CD* + ID_OUI_FROM_DATABASE=MTI co. LTD + +OUI:0013CE* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0013CF* + ID_OUI_FROM_DATABASE=4Access Communications + +OUI:0013D0* + ID_OUI_FROM_DATABASE=t+ Medical Ltd + +OUI:0013D1* + ID_OUI_FROM_DATABASE=KIRK telecom A/S + +OUI:0013D2* + ID_OUI_FROM_DATABASE=PAGE IBERICA, S.A. + +OUI:0013D3* + ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. + +OUI:0013D4* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:0013D5* + ID_OUI_FROM_DATABASE=RuggedCom + +OUI:0013D6* + ID_OUI_FROM_DATABASE=TII NETWORK TECHNOLOGIES, INC. + +OUI:0013D7* + ID_OUI_FROM_DATABASE=SPIDCOM Technologies SA + +OUI:0013D8* + ID_OUI_FROM_DATABASE=Princeton Instruments + +OUI:0013D9* + ID_OUI_FROM_DATABASE=Matrix Product Development, Inc. + +OUI:0013DA* + ID_OUI_FROM_DATABASE=Diskware Co., Ltd + +OUI:0013DB* + ID_OUI_FROM_DATABASE=SHOEI Electric Co.,Ltd + +OUI:0013DC* + ID_OUI_FROM_DATABASE=IBTEK INC. + +OUI:0013DD* + ID_OUI_FROM_DATABASE=Abbott Diagnostics + +OUI:0013DE* + ID_OUI_FROM_DATABASE=Adapt4, LLC + +OUI:0013DF* + ID_OUI_FROM_DATABASE=Ryvor Corp. + +OUI:0013E0* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:0013E1* + ID_OUI_FROM_DATABASE=Iprobe AB + +OUI:0013E2* + ID_OUI_FROM_DATABASE=GeoVision Inc. + +OUI:0013E3* + ID_OUI_FROM_DATABASE=CoVi Technologies, Inc. + +OUI:0013E4* + ID_OUI_FROM_DATABASE=YANGJAE SYSTEMS CORP. + +OUI:0013E5* + ID_OUI_FROM_DATABASE=TENOSYS, INC. + +OUI:0013E6* + ID_OUI_FROM_DATABASE=Technolution + +OUI:0013E7* + ID_OUI_FROM_DATABASE=Halcro + +OUI:0013E8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0013E9* + ID_OUI_FROM_DATABASE=VeriWave, Inc. + +OUI:0013EA* + ID_OUI_FROM_DATABASE=Kamstrup A/S + +OUI:0013EB* + ID_OUI_FROM_DATABASE=Sysmaster Corporation + +OUI:0013EC* + ID_OUI_FROM_DATABASE=Netsnapper Technologies SARL + +OUI:0013ED* + ID_OUI_FROM_DATABASE=PSIA + +OUI:0013EE* + ID_OUI_FROM_DATABASE=JBX Designs Inc. + +OUI:0013EF* + ID_OUI_FROM_DATABASE=Kingjon Digital Technology Co.,Ltd + +OUI:0013F0* + ID_OUI_FROM_DATABASE=Wavefront Semiconductor + +OUI:0013F1* + ID_OUI_FROM_DATABASE=AMOD Technology Co., Ltd. + +OUI:0013F2* + ID_OUI_FROM_DATABASE=Klas Ltd + +OUI:0013F3* + ID_OUI_FROM_DATABASE=Giga-byte Communications Inc. + +OUI:0013F4* + ID_OUI_FROM_DATABASE=Psitek (Pty) Ltd + +OUI:0013F5* + ID_OUI_FROM_DATABASE=Akimbi Systems + +OUI:0013F6* + ID_OUI_FROM_DATABASE=Cintech + +OUI:0013F7* + ID_OUI_FROM_DATABASE=SMC Networks, Inc. + +OUI:0013F8* + ID_OUI_FROM_DATABASE=Dex Security Solutions + +OUI:0013F9* + ID_OUI_FROM_DATABASE=Cavera Systems + +OUI:0013FA* + ID_OUI_FROM_DATABASE=LifeSize Communications, Inc + +OUI:0013FB* + ID_OUI_FROM_DATABASE=RKC INSTRUMENT INC. + +OUI:0013FC* + ID_OUI_FROM_DATABASE=SiCortex, Inc + +OUI:0013FD* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0013FE* + ID_OUI_FROM_DATABASE=GRANDTEC ELECTRONIC CORP. + +OUI:0013FF* + ID_OUI_FROM_DATABASE=Dage-MTI of MC, Inc. + +OUI:001400* + ID_OUI_FROM_DATABASE=MINERVA KOREA CO., LTD + +OUI:001401* + ID_OUI_FROM_DATABASE=Rivertree Networks Corp. + +OUI:001402* + ID_OUI_FROM_DATABASE=kk-electronic a/s + +OUI:001403* + ID_OUI_FROM_DATABASE=Renasis, LLC + +OUI:001404* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001405* + ID_OUI_FROM_DATABASE=OpenIB, Inc. + +OUI:001406* + ID_OUI_FROM_DATABASE=Go Networks + +OUI:001407* + ID_OUI_FROM_DATABASE=Sperian Protection Instrumentation + +OUI:001408* + ID_OUI_FROM_DATABASE=Eka Systems Inc. + +OUI:001409* + ID_OUI_FROM_DATABASE=MAGNETI MARELLI S.E. S.p.A. + +OUI:00140A* + ID_OUI_FROM_DATABASE=WEPIO Co., Ltd. + +OUI:00140B* + ID_OUI_FROM_DATABASE=FIRST INTERNATIONAL COMPUTER, INC. + +OUI:00140C* + ID_OUI_FROM_DATABASE=GKB CCTV CO., LTD. + +OUI:00140D* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:00140E* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:00140F* + ID_OUI_FROM_DATABASE=Federal State Unitary Enterprise Leningrad R&D Institute of + +OUI:001410* + ID_OUI_FROM_DATABASE=Suzhou Keda Technology CO.,Ltd + +OUI:001411* + ID_OUI_FROM_DATABASE=Deutschmann Automation GmbH & Co. KG + +OUI:001412* + ID_OUI_FROM_DATABASE=S-TEC electronics AG + +OUI:001413* + ID_OUI_FROM_DATABASE=Trebing & Himstedt Prozeßautomation GmbH & Co. KG + +OUI:001414* + ID_OUI_FROM_DATABASE=Jumpnode Systems LLC. + +OUI:001415* + ID_OUI_FROM_DATABASE=Intec Automation inc. + +OUI:001416* + ID_OUI_FROM_DATABASE=Scosche Industries, Inc. + +OUI:001417* + ID_OUI_FROM_DATABASE=RSE Informations Technologie GmbH + +OUI:001418* + ID_OUI_FROM_DATABASE=C4Line + +OUI:001419* + ID_OUI_FROM_DATABASE=SIDSA + +OUI:00141A* + ID_OUI_FROM_DATABASE=DEICY CORPORATION + +OUI:00141B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00141C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00141D* + ID_OUI_FROM_DATABASE=LTI-Motion GmbH + +OUI:00141E* + ID_OUI_FROM_DATABASE=P.A. Semi, Inc. + +OUI:00141F* + ID_OUI_FROM_DATABASE=SunKwang Electronics Co., Ltd + +OUI:001420* + ID_OUI_FROM_DATABASE=G-Links networking company + +OUI:001421* + ID_OUI_FROM_DATABASE=Total Wireless Technologies Pte. Ltd. + +OUI:001422* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:001423* + ID_OUI_FROM_DATABASE=J-S Co. NEUROCOM + +OUI:001424* + ID_OUI_FROM_DATABASE=Merry Electrics CO., LTD. + +OUI:001425* + ID_OUI_FROM_DATABASE=Galactic Computing Corp. + +OUI:001426* + ID_OUI_FROM_DATABASE=NL Technology + +OUI:001427* + ID_OUI_FROM_DATABASE=JazzMutant + +OUI:001428* + ID_OUI_FROM_DATABASE=Vocollect Inc + +OUI:001429* + ID_OUI_FROM_DATABASE=V Center Technologies Co., Ltd. + +OUI:00142A* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:00142B* + ID_OUI_FROM_DATABASE=Edata Communication Inc. + +OUI:00142C* + ID_OUI_FROM_DATABASE=Koncept International, Inc. + +OUI:00142D* + ID_OUI_FROM_DATABASE=Toradex AG + +OUI:00142E* + ID_OUI_FROM_DATABASE=77 Elektronika Kft. + +OUI:00142F* + ID_OUI_FROM_DATABASE=Savvius + +OUI:001430* + ID_OUI_FROM_DATABASE=ViPowER, Inc + +OUI:001431* + ID_OUI_FROM_DATABASE=PDL Electronics Ltd + +OUI:001432* + ID_OUI_FROM_DATABASE=Tarallax Wireless, Inc. + +OUI:001433* + ID_OUI_FROM_DATABASE=Empower Technologies(Canada) Inc. + +OUI:001434* + ID_OUI_FROM_DATABASE=Keri Systems, Inc + +OUI:001435* + ID_OUI_FROM_DATABASE=CityCom Corp. + +OUI:001436* + ID_OUI_FROM_DATABASE=Qwerty Elektronik AB + +OUI:001437* + ID_OUI_FROM_DATABASE=GSTeletech Co.,Ltd. + +OUI:001438* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:001439* + ID_OUI_FROM_DATABASE=Blonder Tongue Laboratories, Inc + +OUI:00143A* + ID_OUI_FROM_DATABASE=RAYTALK INTERNATIONAL SRL + +OUI:00143B* + ID_OUI_FROM_DATABASE=Sensovation AG + +OUI:00143C* + ID_OUI_FROM_DATABASE=Rheinmetall Canada Inc. + +OUI:00143D* + ID_OUI_FROM_DATABASE=Aevoe Inc. + +OUI:00143E* + ID_OUI_FROM_DATABASE=AirLink Communications, Inc. + +OUI:00143F* + ID_OUI_FROM_DATABASE=Hotway Technology Corporation + +OUI:001440* + ID_OUI_FROM_DATABASE=ATOMIC Corporation + +OUI:001441* + ID_OUI_FROM_DATABASE=Innovation Sound Technology Co., LTD. + +OUI:001442* + ID_OUI_FROM_DATABASE=ATTO CORPORATION + +OUI:001443* + ID_OUI_FROM_DATABASE=Consultronics Europe Ltd + +OUI:001444* + ID_OUI_FROM_DATABASE=Grundfos Holding + +OUI:001445* + ID_OUI_FROM_DATABASE=Telefon-Gradnja d.o.o. + +OUI:001446* + ID_OUI_FROM_DATABASE=SuperVision Solutions LLC + +OUI:001447* + ID_OUI_FROM_DATABASE=BOAZ Inc. + +OUI:001448* + ID_OUI_FROM_DATABASE=Inventec Multimedia & Telecom Corporation + +OUI:001449* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. + +OUI:00144A* + ID_OUI_FROM_DATABASE=Taiwan Thick-Film Ind. Corp. + +OUI:00144B* + ID_OUI_FROM_DATABASE=Hifn, Inc. + +OUI:00144C* + ID_OUI_FROM_DATABASE=General Meters Corp. + +OUI:00144D* + ID_OUI_FROM_DATABASE=Intelligent Systems + +OUI:00144E* + ID_OUI_FROM_DATABASE=SRISA + +OUI:00144F* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:001450* + ID_OUI_FROM_DATABASE=Heim Systems GmbH + +OUI:001451* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001452* + ID_OUI_FROM_DATABASE=CALCULEX,INC. + +OUI:001453* + ID_OUI_FROM_DATABASE=ADVANTECH TECHNOLOGIES CO.,LTD + +OUI:001454* + ID_OUI_FROM_DATABASE=Symwave + +OUI:001455* + ID_OUI_FROM_DATABASE=Coder Electronics Corporation + +OUI:001456* + ID_OUI_FROM_DATABASE=Edge Products + +OUI:001457* + ID_OUI_FROM_DATABASE=T-VIPS AS + +OUI:001458* + ID_OUI_FROM_DATABASE=HS Automatic ApS + +OUI:001459* + ID_OUI_FROM_DATABASE=Moram Co., Ltd. + +OUI:00145A* + ID_OUI_FROM_DATABASE=Neratec Solutions AG + +OUI:00145B* + ID_OUI_FROM_DATABASE=SeekerNet Inc. + +OUI:00145C* + ID_OUI_FROM_DATABASE=Intronics B.V. + +OUI:00145D* + ID_OUI_FROM_DATABASE=WJ Communications, Inc. + +OUI:00145E* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:00145F* + ID_OUI_FROM_DATABASE=ADITEC CO. LTD + +OUI:001460* + ID_OUI_FROM_DATABASE=Kyocera Wireless Corp. + +OUI:001461* + ID_OUI_FROM_DATABASE=CORONA CORPORATION + +OUI:001462* + ID_OUI_FROM_DATABASE=Digiwell Technology, inc + +OUI:001463* + ID_OUI_FROM_DATABASE=IDCS N.V. + +OUI:001464* + ID_OUI_FROM_DATABASE=Cryptosoft + +OUI:001465* + ID_OUI_FROM_DATABASE=Novo Nordisk A/S + +OUI:001466* + ID_OUI_FROM_DATABASE=Kleinhenz Elektronik GmbH + +OUI:001467* + ID_OUI_FROM_DATABASE=ArrowSpan Inc. + +OUI:001468* + ID_OUI_FROM_DATABASE=CelPlan International, Inc. + +OUI:001469* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00146A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00146B* + ID_OUI_FROM_DATABASE=Anagran, Inc. + +OUI:00146C* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:00146D* + ID_OUI_FROM_DATABASE=RF Technologies + +OUI:00146E* + ID_OUI_FROM_DATABASE=H. Stoll GmbH & Co. KG + +OUI:00146F* + ID_OUI_FROM_DATABASE=Kohler Co + +OUI:001470* + ID_OUI_FROM_DATABASE=Prokom Software SA + +OUI:001471* + ID_OUI_FROM_DATABASE=Eastern Asia Technology Limited + +OUI:001472* + ID_OUI_FROM_DATABASE=China Broadband Wireless IP Standard group(ChinaBWIPS) + +OUI:001473* + ID_OUI_FROM_DATABASE=Bookham Inc + +OUI:001474* + ID_OUI_FROM_DATABASE=K40 Electronics + +OUI:001475* + ID_OUI_FROM_DATABASE=Wiline Networks, Inc. + +OUI:001476* + ID_OUI_FROM_DATABASE=MultiCom Industries Limited + +OUI:001477* + ID_OUI_FROM_DATABASE=Trilliant + +OUI:001478* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:001479* + ID_OUI_FROM_DATABASE=NEC Magnus Communications,Ltd. + +OUI:00147A* + ID_OUI_FROM_DATABASE=Eubus GmbH + +OUI:00147B* + ID_OUI_FROM_DATABASE=Iteris, Inc. + +OUI:00147C* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:00147D* + ID_OUI_FROM_DATABASE=Aeon Digital International + +OUI:00147E* + ID_OUI_FROM_DATABASE=InnerWireless + +OUI:00147F* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium + +OUI:001480* + ID_OUI_FROM_DATABASE=Hitachi-LG Data Storage Korea, Inc + +OUI:001481* + ID_OUI_FROM_DATABASE=Multilink Inc + +OUI:001482* + ID_OUI_FROM_DATABASE=Aurora Networks + +OUI:001483* + ID_OUI_FROM_DATABASE=eXS Inc. + +OUI:001484* + ID_OUI_FROM_DATABASE=Cermate Technologies Inc. + +OUI:001485* + ID_OUI_FROM_DATABASE=Giga-Byte + +OUI:001486* + ID_OUI_FROM_DATABASE=Echo Digital Audio Corporation + +OUI:001487* + ID_OUI_FROM_DATABASE=American Technology Integrators + +OUI:001488* + ID_OUI_FROM_DATABASE=Akorri + +OUI:001489* + ID_OUI_FROM_DATABASE=B15402100 - JANDEI, S.L. + +OUI:00148A* + ID_OUI_FROM_DATABASE=Elin Ebg Traction Gmbh + +OUI:00148B* + ID_OUI_FROM_DATABASE=Globo Electronic GmbH & Co. KG + +OUI:00148C* + ID_OUI_FROM_DATABASE=General Dynamics Mission Systems + +OUI:00148D* + ID_OUI_FROM_DATABASE=Cubic Defense Simulation Systems + +OUI:00148E* + ID_OUI_FROM_DATABASE=Tele Power Inc. + +OUI:00148F* + ID_OUI_FROM_DATABASE=Protronic (Far East) Ltd. + +OUI:001490* + ID_OUI_FROM_DATABASE=ASP Corporation + +OUI:001491* + ID_OUI_FROM_DATABASE=Daniels Electronics Ltd. dbo Codan Rado Communications + +OUI:001492* + ID_OUI_FROM_DATABASE=Liteon, Mobile Media Solution SBU + +OUI:001493* + ID_OUI_FROM_DATABASE=Systimax Solutions + +OUI:001494* + ID_OUI_FROM_DATABASE=ESU AG + +OUI:001495* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:001496* + ID_OUI_FROM_DATABASE=Phonic Corp. + +OUI:001497* + ID_OUI_FROM_DATABASE=ZHIYUAN Eletronics co.,ltd. + +OUI:001498* + ID_OUI_FROM_DATABASE=Viking Design Technology + +OUI:001499* + ID_OUI_FROM_DATABASE=Helicomm Inc + +OUI:00149A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00149B* + ID_OUI_FROM_DATABASE=Nokota Communications, LLC + +OUI:00149C* + ID_OUI_FROM_DATABASE=HF Company + +OUI:00149D* + ID_OUI_FROM_DATABASE=Sound ID Inc. + +OUI:00149E* + ID_OUI_FROM_DATABASE=UbONE Co., Ltd + +OUI:00149F* + ID_OUI_FROM_DATABASE=System and Chips, Inc. + +OUI:0014A0* + ID_OUI_FROM_DATABASE=Accsense, Inc. + +OUI:0014A1* + ID_OUI_FROM_DATABASE=Synchronous Communication Corp + +OUI:0014A2* + ID_OUI_FROM_DATABASE=Core Micro Systems Inc. + +OUI:0014A3* + ID_OUI_FROM_DATABASE=Vitelec BV + +OUI:0014A4* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:0014A5* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:0014A6* + ID_OUI_FROM_DATABASE=Teranetics, Inc. + +OUI:0014A7* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0014A8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0014A9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0014AA* + ID_OUI_FROM_DATABASE=Ashly Audio, Inc. + +OUI:0014AB* + ID_OUI_FROM_DATABASE=Senhai Electronic Technology Co., Ltd. + +OUI:0014AC* + ID_OUI_FROM_DATABASE=Bountiful WiFi + +OUI:0014AD* + ID_OUI_FROM_DATABASE=Gassner Wiege- und Meßtechnik GmbH + +OUI:0014AE* + ID_OUI_FROM_DATABASE=Wizlogics Co., Ltd. + +OUI:0014AF* + ID_OUI_FROM_DATABASE=Datasym POS Inc. + +OUI:0014B0* + ID_OUI_FROM_DATABASE=Naeil Community + +OUI:0014B1* + ID_OUI_FROM_DATABASE=Axell Wireless Limited + +OUI:0014B2* + ID_OUI_FROM_DATABASE=mCubelogics Corporation + +OUI:0014B3* + ID_OUI_FROM_DATABASE=CoreStar International Corp + +OUI:0014B4* + ID_OUI_FROM_DATABASE=General Dynamics United Kingdom Ltd + +OUI:0014B5* + ID_OUI_FROM_DATABASE=PHYSIOMETRIX,INC + +OUI:0014B6* + ID_OUI_FROM_DATABASE=Enswer Technology Inc. + +OUI:0014B7* + ID_OUI_FROM_DATABASE=AR Infotek Inc. + +OUI:0014B8* + ID_OUI_FROM_DATABASE=Hill-Rom + +OUI:0014B9* + ID_OUI_FROM_DATABASE=MSTAR SEMICONDUCTOR + +OUI:0014BA* + ID_OUI_FROM_DATABASE=Carvers SA de CV + +OUI:0014BB* + ID_OUI_FROM_DATABASE=Open Interface North America + +OUI:0014BC* + ID_OUI_FROM_DATABASE=SYNECTIC TELECOM EXPORTS PVT. LTD. + +OUI:0014BD* + ID_OUI_FROM_DATABASE=incNETWORKS, Inc + +OUI:0014BE* + ID_OUI_FROM_DATABASE=Wink communication technology CO.LTD + +OUI:0014BF* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:0014C0* + ID_OUI_FROM_DATABASE=Symstream Technology Group Ltd + +OUI:0014C1* + ID_OUI_FROM_DATABASE=U.S. Robotics Corporation + +OUI:0014C2* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0014C3* + ID_OUI_FROM_DATABASE=Seagate Technology + +OUI:0014C4* + ID_OUI_FROM_DATABASE=Vitelcom Mobile Technology + +OUI:0014C5* + ID_OUI_FROM_DATABASE=Alive Technologies Pty Ltd + +OUI:0014C6* + ID_OUI_FROM_DATABASE=Quixant Ltd + +OUI:0014C7* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0014C8* + ID_OUI_FROM_DATABASE=Contemporary Research Corp + +OUI:0014C9* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:0014CA* + ID_OUI_FROM_DATABASE=Key Radio Systems Limited + +OUI:0014CB* + ID_OUI_FROM_DATABASE=LifeSync Corporation + +OUI:0014CC* + ID_OUI_FROM_DATABASE=Zetec, Inc. + +OUI:0014CD* + ID_OUI_FROM_DATABASE=DigitalZone Co., Ltd. + +OUI:0014CE* + ID_OUI_FROM_DATABASE=NF CORPORATION + +OUI:0014CF* + ID_OUI_FROM_DATABASE=INVISIO Communications + +OUI:0014D0* + ID_OUI_FROM_DATABASE=BTI Systems Inc. + +OUI:0014D1* + ID_OUI_FROM_DATABASE=TRENDnet, Inc. + +OUI:0014D2* + ID_OUI_FROM_DATABASE=Kyuden Technosystems Corporation + +OUI:0014D3* + ID_OUI_FROM_DATABASE=SEPSA + +OUI:0014D4* + ID_OUI_FROM_DATABASE=K Technology Corporation + +OUI:0014D5* + ID_OUI_FROM_DATABASE=Datang Telecom Technology CO. , LCD,Optical Communication Br + +OUI:0014D6* + ID_OUI_FROM_DATABASE=Jeongmin Electronics Co.,Ltd. + +OUI:0014D7* + ID_OUI_FROM_DATABASE=Datastore Technology Corp + +OUI:0014D8* + ID_OUI_FROM_DATABASE=bio-logic SA + +OUI:0014D9* + ID_OUI_FROM_DATABASE=IP Fabrics, Inc. + +OUI:0014DA* + ID_OUI_FROM_DATABASE=Huntleigh Healthcare + +OUI:0014DB* + ID_OUI_FROM_DATABASE=Elma Trenew Electronic GmbH + +OUI:0014DC* + ID_OUI_FROM_DATABASE=Communication System Design & Manufacturing (CSDM) + +OUI:0014DD* + ID_OUI_FROM_DATABASE=Covergence Inc. + +OUI:0014DE* + ID_OUI_FROM_DATABASE=Sage Instruments Inc. + +OUI:0014DF* + ID_OUI_FROM_DATABASE=HI-P Tech Corporation + +OUI:0014E0* + ID_OUI_FROM_DATABASE=LET'S Corporation + +OUI:0014E1* + ID_OUI_FROM_DATABASE=Data Display AG + +OUI:0014E2* + ID_OUI_FROM_DATABASE=datacom systems inc. + +OUI:0014E3* + ID_OUI_FROM_DATABASE=mm-lab GmbH + +OUI:0014E4* + ID_OUI_FROM_DATABASE=infinias, LLC + +OUI:0014E5* + ID_OUI_FROM_DATABASE=Alticast + +OUI:0014E6* + ID_OUI_FROM_DATABASE=AIM Infrarotmodule GmbH + +OUI:0014E7* + ID_OUI_FROM_DATABASE=Stolinx,. Inc + +OUI:0014E8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0014E9* + ID_OUI_FROM_DATABASE=Nortech International + +OUI:0014EA* + ID_OUI_FROM_DATABASE=S Digm Inc. (Safe Paradigm Inc.) + +OUI:0014EB* + ID_OUI_FROM_DATABASE=AwarePoint Corporation + +OUI:0014EC* + ID_OUI_FROM_DATABASE=Acro Telecom + +OUI:0014ED* + ID_OUI_FROM_DATABASE=Airak, Inc. + +OUI:0014EE* + ID_OUI_FROM_DATABASE=Western Digital Technologies, Inc. + +OUI:0014EF* + ID_OUI_FROM_DATABASE=TZero Technologies, Inc. + +OUI:0014F0* + ID_OUI_FROM_DATABASE=Business Security OL AB + +OUI:0014F1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0014F2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0014F3* + ID_OUI_FROM_DATABASE=ViXS Systems Inc + +OUI:0014F4* + ID_OUI_FROM_DATABASE=DekTec Digital Video B.V. + +OUI:0014F5* + ID_OUI_FROM_DATABASE=OSI Security Devices + +OUI:0014F6* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:0014F7* + ID_OUI_FROM_DATABASE=CREVIS Co., LTD + +OUI:0014F8* + ID_OUI_FROM_DATABASE=Scientific Atlanta + +OUI:0014F9* + ID_OUI_FROM_DATABASE=Vantage Controls + +OUI:0014FA* + ID_OUI_FROM_DATABASE=AsGa S.A. + +OUI:0014FB* + ID_OUI_FROM_DATABASE=Technical Solutions Inc. + +OUI:0014FC* + ID_OUI_FROM_DATABASE=Extandon, Inc. + +OUI:0014FD* + ID_OUI_FROM_DATABASE=Thecus Technology Corp. + +OUI:0014FE* + ID_OUI_FROM_DATABASE=Artech Electronics + +OUI:0014FF* + ID_OUI_FROM_DATABASE=Precise Automation, Inc. + +OUI:001500* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001501* + ID_OUI_FROM_DATABASE=LexBox + +OUI:001502* + ID_OUI_FROM_DATABASE=BETA tech + +OUI:001503* + ID_OUI_FROM_DATABASE=PROFIcomms s.r.o. + +OUI:001504* + ID_OUI_FROM_DATABASE=GAME PLUS CO., LTD. + +OUI:001505* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:001506* + ID_OUI_FROM_DATABASE=Neo Photonics + +OUI:001507* + ID_OUI_FROM_DATABASE=Renaissance Learning Inc + +OUI:001508* + ID_OUI_FROM_DATABASE=Global Target Enterprise Inc + +OUI:001509* + ID_OUI_FROM_DATABASE=Plus Technology Co., Ltd + +OUI:00150A* + ID_OUI_FROM_DATABASE=Sonoa Systems, Inc + +OUI:00150B* + ID_OUI_FROM_DATABASE=SAGE INFOTECH LTD. + +OUI:00150C* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:00150D* + ID_OUI_FROM_DATABASE=Hoana Medical, Inc. + +OUI:00150E* + ID_OUI_FROM_DATABASE=OPENBRAIN TECHNOLOGIES CO., LTD. + +OUI:00150F* + ID_OUI_FROM_DATABASE=mingjong + +OUI:001510* + ID_OUI_FROM_DATABASE=Techsphere Co., Ltd + +OUI:001511* + ID_OUI_FROM_DATABASE=Data Center Systems + +OUI:001512* + ID_OUI_FROM_DATABASE=Zurich University of Applied Sciences + +OUI:001513* + ID_OUI_FROM_DATABASE=EFS sas + +OUI:001514* + ID_OUI_FROM_DATABASE=Hu Zhou NAVA Networks&Electronics Ltd. + +OUI:001515* + ID_OUI_FROM_DATABASE=Leipold+Co.GmbH + +OUI:001516* + ID_OUI_FROM_DATABASE=URIEL SYSTEMS INC. + +OUI:001517* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001518* + ID_OUI_FROM_DATABASE=Shenzhen 10MOONS Technology Development CO.,Ltd + +OUI:001519* + ID_OUI_FROM_DATABASE=StoreAge Networking Technologies + +OUI:00151A* + ID_OUI_FROM_DATABASE=Hunter Engineering Company + +OUI:00151B* + ID_OUI_FROM_DATABASE=Isilon Systems Inc. + +OUI:00151C* + ID_OUI_FROM_DATABASE=LENECO + +OUI:00151D* + ID_OUI_FROM_DATABASE=M2I CORPORATION + +OUI:00151E* + ID_OUI_FROM_DATABASE=ETHERNET Powerlink Standarization Group (EPSG) + +OUI:00151F* + ID_OUI_FROM_DATABASE=Multivision Intelligent Surveillance (Hong Kong) Ltd + +OUI:001520* + ID_OUI_FROM_DATABASE=Radiocrafts AS + +OUI:001521* + ID_OUI_FROM_DATABASE=Horoquartz + +OUI:001522* + ID_OUI_FROM_DATABASE=Dea Security + +OUI:001523* + ID_OUI_FROM_DATABASE=Meteor Communications Corporation + +OUI:001524* + ID_OUI_FROM_DATABASE=Numatics, Inc. + +OUI:001525* + ID_OUI_FROM_DATABASE=Chamberlain Access Solutions + +OUI:001526* + ID_OUI_FROM_DATABASE=Remote Technologies Inc + +OUI:001527* + ID_OUI_FROM_DATABASE=Balboa Instruments + +OUI:001528* + ID_OUI_FROM_DATABASE=Beacon Medical Products LLC d.b.a. BeaconMedaes + +OUI:001529* + ID_OUI_FROM_DATABASE=N3 Corporation + +OUI:00152A* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:00152B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00152C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00152D* + ID_OUI_FROM_DATABASE=TenX Networks, LLC + +OUI:00152E* + ID_OUI_FROM_DATABASE=PacketHop, Inc. + +OUI:00152F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001530* + ID_OUI_FROM_DATABASE=Dell EMC + +OUI:001531* + ID_OUI_FROM_DATABASE=KOCOM + +OUI:001532* + ID_OUI_FROM_DATABASE=Consumer Technologies Group, LLC + +OUI:001533* + ID_OUI_FROM_DATABASE=NADAM.CO.,LTD + +OUI:001534* + ID_OUI_FROM_DATABASE=A Beltrónica-Companhia de Comunicações, Lda + +OUI:001535* + ID_OUI_FROM_DATABASE=OTE Spa + +OUI:001536* + ID_OUI_FROM_DATABASE=Powertech co.,Ltd + +OUI:001537* + ID_OUI_FROM_DATABASE=Ventus Networks + +OUI:001538* + ID_OUI_FROM_DATABASE=RFID, Inc. + +OUI:001539* + ID_OUI_FROM_DATABASE=Technodrive srl + +OUI:00153A* + ID_OUI_FROM_DATABASE=Shenzhen Syscan Technology Co.,Ltd. + +OUI:00153B* + ID_OUI_FROM_DATABASE=EMH metering GmbH & Co. KG + +OUI:00153C* + ID_OUI_FROM_DATABASE=Kprotech Co., Ltd. + +OUI:00153D* + ID_OUI_FROM_DATABASE=ELIM PRODUCT CO. + +OUI:00153E* + ID_OUI_FROM_DATABASE=Q-Matic Sweden AB + +OUI:00153F* + ID_OUI_FROM_DATABASE=Alcatel Alenia Space Italia + +OUI:001540* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001541* + ID_OUI_FROM_DATABASE=StrataLight Communications, Inc. + +OUI:001542* + ID_OUI_FROM_DATABASE=MICROHARD S.R.L. + +OUI:001543* + ID_OUI_FROM_DATABASE=Aberdeen Test Center + +OUI:001544* + ID_OUI_FROM_DATABASE=coM.s.a.t. AG + +OUI:001545* + ID_OUI_FROM_DATABASE=SEECODE Co., Ltd. + +OUI:001546* + ID_OUI_FROM_DATABASE=ITG Worldwide Sdn Bhd + +OUI:001547* + ID_OUI_FROM_DATABASE=AiZen Solutions Inc. + +OUI:001548* + ID_OUI_FROM_DATABASE=CUBE TECHNOLOGIES + +OUI:001549* + ID_OUI_FROM_DATABASE=Dixtal Biomedica Ind. Com. Ltda + +OUI:00154A* + ID_OUI_FROM_DATABASE=WANSHIH ELECTRONIC CO., LTD + +OUI:00154B* + ID_OUI_FROM_DATABASE=Wonde Proud Technology Co., Ltd + +OUI:00154C* + ID_OUI_FROM_DATABASE=Saunders Electronics + +OUI:00154D* + ID_OUI_FROM_DATABASE=Netronome Systems, Inc. + +OUI:00154E* + ID_OUI_FROM_DATABASE=IEC + +OUI:00154F* + ID_OUI_FROM_DATABASE=one RF Technology + +OUI:001550* + ID_OUI_FROM_DATABASE=Nits Technology Inc + +OUI:001551* + ID_OUI_FROM_DATABASE=RadioPulse Inc. + +OUI:001552* + ID_OUI_FROM_DATABASE=Wi-Gear Inc. + +OUI:001553* + ID_OUI_FROM_DATABASE=Cytyc Corporation + +OUI:001554* + ID_OUI_FROM_DATABASE=Atalum Wireless S.A. + +OUI:001555* + ID_OUI_FROM_DATABASE=DFM GmbH + +OUI:001556* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:001557* + ID_OUI_FROM_DATABASE=Olivetti + +OUI:001558* + ID_OUI_FROM_DATABASE=FOXCONN + +OUI:001559* + ID_OUI_FROM_DATABASE=Securaplane Technologies, Inc. + +OUI:00155A* + ID_OUI_FROM_DATABASE=DAINIPPON PHARMACEUTICAL CO., LTD. + +OUI:00155B* + ID_OUI_FROM_DATABASE=Sampo Corporation + +OUI:00155C* + ID_OUI_FROM_DATABASE=Dresser Wayne + +OUI:00155D* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:00155E* + ID_OUI_FROM_DATABASE=Morgan Stanley + +OUI:00155F* + ID_OUI_FROM_DATABASE=GreenPeak Technologies + +OUI:001560* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001561* + ID_OUI_FROM_DATABASE=JJPlus Corporation + +OUI:001562* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001563* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001564* + ID_OUI_FROM_DATABASE=BEHRINGER Spezielle Studiotechnik GmbH + +OUI:001565* + ID_OUI_FROM_DATABASE=XIAMEN YEALINK NETWORK TECHNOLOGY CO.,LTD + +OUI:001566* + ID_OUI_FROM_DATABASE=A-First Technology Co., Ltd. + +OUI:001567* + ID_OUI_FROM_DATABASE=RADWIN Inc. + +OUI:001568* + ID_OUI_FROM_DATABASE=Dilithium Networks + +OUI:001569* + ID_OUI_FROM_DATABASE=PECO II, Inc. + +OUI:00156A* + ID_OUI_FROM_DATABASE=DG2L Technologies Pvt. Ltd. + +OUI:00156B* + ID_OUI_FROM_DATABASE=Perfisans Networks Corp. + +OUI:00156C* + ID_OUI_FROM_DATABASE=SANE SYSTEM CO., LTD + +OUI:00156D* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:00156E* + ID_OUI_FROM_DATABASE=A. W. Communication Systems Ltd + +OUI:00156F* + ID_OUI_FROM_DATABASE=Xiranet Communications GmbH + +OUI:001570* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc + +OUI:001571* + ID_OUI_FROM_DATABASE=Nolan Systems + +OUI:001572* + ID_OUI_FROM_DATABASE=Red-Lemon + +OUI:001573* + ID_OUI_FROM_DATABASE=NewSoft Technology Corporation + +OUI:001574* + ID_OUI_FROM_DATABASE=Horizon Semiconductors Ltd. + +OUI:001575* + ID_OUI_FROM_DATABASE=Nevis Networks Inc. + +OUI:001576* + ID_OUI_FROM_DATABASE=LABiTec - Labor Biomedical Technologies GmbH + +OUI:001577* + ID_OUI_FROM_DATABASE=Allied Telesis, Inc. + +OUI:001578* + ID_OUI_FROM_DATABASE=Audio / Video Innovations + +OUI:001579* + ID_OUI_FROM_DATABASE=Lunatone Industrielle Elektronik GmbH + +OUI:00157A* + ID_OUI_FROM_DATABASE=Telefin S.p.A. + +OUI:00157B* + ID_OUI_FROM_DATABASE=Leuze electronic GmbH + Co. KG + +OUI:00157C* + ID_OUI_FROM_DATABASE=Dave Networks, Inc. + +OUI:00157D* + ID_OUI_FROM_DATABASE=POSDATA + +OUI:00157E* + ID_OUI_FROM_DATABASE=Weidmüller Interface GmbH & Co. KG + +OUI:00157F* + ID_OUI_FROM_DATABASE=ChuanG International Holding CO.,LTD. + +OUI:001580* + ID_OUI_FROM_DATABASE=U-WAY CORPORATION + +OUI:001581* + ID_OUI_FROM_DATABASE=MAKUS Inc. + +OUI:001582* + ID_OUI_FROM_DATABASE=Pulse Eight Limited + +OUI:001583* + ID_OUI_FROM_DATABASE=IVT corporation + +OUI:001584* + ID_OUI_FROM_DATABASE=Schenck Process GmbH + +OUI:001585* + ID_OUI_FROM_DATABASE=Aonvision Technolopy Corp. + +OUI:001586* + ID_OUI_FROM_DATABASE=Xiamen Overseas Chinese Electronic Co., Ltd. + +OUI:001587* + ID_OUI_FROM_DATABASE=Takenaka Seisakusho Co.,Ltd + +OUI:001588* + ID_OUI_FROM_DATABASE=Salutica Allied Solutions Sdn Bhd + +OUI:001589* + ID_OUI_FROM_DATABASE=D-MAX Technology Co.,Ltd + +OUI:00158A* + ID_OUI_FROM_DATABASE=SURECOM Technology Corp. + +OUI:00158B* + ID_OUI_FROM_DATABASE=Park Air Systems Ltd + +OUI:00158C* + ID_OUI_FROM_DATABASE=Liab ApS + +OUI:00158D* + ID_OUI_FROM_DATABASE=Jennic Ltd + +OUI:00158E* + ID_OUI_FROM_DATABASE=Plustek.INC + +OUI:00158F* + ID_OUI_FROM_DATABASE=NTT Advanced Technology Corporation + +OUI:001590* + ID_OUI_FROM_DATABASE=Hectronic GmbH + +OUI:001591* + ID_OUI_FROM_DATABASE=RLW Inc. + +OUI:001592* + ID_OUI_FROM_DATABASE=Facom UK Ltd (Melksham) + +OUI:001593* + ID_OUI_FROM_DATABASE=U4EA Technologies Inc. + +OUI:001594* + ID_OUI_FROM_DATABASE=BIXOLON CO.,LTD + +OUI:001595* + ID_OUI_FROM_DATABASE=Quester Tangent Corporation + +OUI:001596* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001597* + ID_OUI_FROM_DATABASE=AETA AUDIO SYSTEMS + +OUI:001598* + ID_OUI_FROM_DATABASE=Kolektor group + +OUI:001599* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00159A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00159B* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:00159C* + ID_OUI_FROM_DATABASE=B-KYUNG SYSTEM Co.,Ltd. + +OUI:00159D* + ID_OUI_FROM_DATABASE=Tripp Lite + +OUI:00159E* + ID_OUI_FROM_DATABASE=Mad Catz Interactive Inc + +OUI:00159F* + ID_OUI_FROM_DATABASE=Terascala, Inc. + +OUI:0015A0* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0015A1* + ID_OUI_FROM_DATABASE=ECA-SINTERS + +OUI:0015A2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0015A3* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0015A4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0015A5* + ID_OUI_FROM_DATABASE=DCI Co., Ltd. + +OUI:0015A6* + ID_OUI_FROM_DATABASE=Digital Electronics Products Ltd. + +OUI:0015A7* + ID_OUI_FROM_DATABASE=Robatech AG + +OUI:0015A8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0015A9* + ID_OUI_FROM_DATABASE=KWANG WOO I&C CO.,LTD + +OUI:0015AA* + ID_OUI_FROM_DATABASE=Rextechnik International Co., + +OUI:0015AB* + ID_OUI_FROM_DATABASE=PRO CO SOUND INC + +OUI:0015AC* + ID_OUI_FROM_DATABASE=Capelon AB + +OUI:0015AD* + ID_OUI_FROM_DATABASE=Accedian Networks + +OUI:0015AE* + ID_OUI_FROM_DATABASE=kyung il + +OUI:0015AF* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:0015B0* + ID_OUI_FROM_DATABASE=AUTOTELENET CO.,LTD + +OUI:0015B1* + ID_OUI_FROM_DATABASE=Ambient Corporation + +OUI:0015B2* + ID_OUI_FROM_DATABASE=Advanced Industrial Computer, Inc. + +OUI:0015B3* + ID_OUI_FROM_DATABASE=Caretech AB + +OUI:0015B4* + ID_OUI_FROM_DATABASE=Polymap Wireless LLC + +OUI:0015B5* + ID_OUI_FROM_DATABASE=CI Network Corp. + +OUI:0015B6* + ID_OUI_FROM_DATABASE=ShinMaywa Industries, Ltd. + +OUI:0015B7* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:0015B8* + ID_OUI_FROM_DATABASE=Tahoe + +OUI:0015B9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0015BA* + ID_OUI_FROM_DATABASE=iba AG + +OUI:0015BB* + ID_OUI_FROM_DATABASE=SMA Solar Technology AG + +OUI:0015BC* + ID_OUI_FROM_DATABASE=Develco + +OUI:0015BD* + ID_OUI_FROM_DATABASE=Group 4 Technology Ltd + +OUI:0015BE* + ID_OUI_FROM_DATABASE=Iqua Ltd. + +OUI:0015BF* + ID_OUI_FROM_DATABASE=technicob + +OUI:0015C0* + ID_OUI_FROM_DATABASE=DIGITAL TELEMEDIA CO.,LTD. + +OUI:0015C1* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:0015C2* + ID_OUI_FROM_DATABASE=3M Germany + +OUI:0015C3* + ID_OUI_FROM_DATABASE=Ruf Telematik AG + +OUI:0015C4* + ID_OUI_FROM_DATABASE=FLOVEL CO., LTD. + +OUI:0015C5* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:0015C6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0015C7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0015C8* + ID_OUI_FROM_DATABASE=FlexiPanel Ltd + +OUI:0015C9* + ID_OUI_FROM_DATABASE=Gumstix, Inc + +OUI:0015CA* + ID_OUI_FROM_DATABASE=TeraRecon, Inc. + +OUI:0015CB* + ID_OUI_FROM_DATABASE=Surf Communication Solutions Ltd. + +OUI:0015CC* + ID_OUI_FROM_DATABASE=UQUEST, LTD. + +OUI:0015CD* + ID_OUI_FROM_DATABASE=Exartech International Corp. + +OUI:0015CE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0015CF* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0015D0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0015D1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0015D2* + ID_OUI_FROM_DATABASE=Xantech Corporation + +OUI:0015D3* + ID_OUI_FROM_DATABASE=Pantech&Curitel Communications, Inc. + +OUI:0015D4* + ID_OUI_FROM_DATABASE=Emitor AB + +OUI:0015D5* + ID_OUI_FROM_DATABASE=NICEVT + +OUI:0015D6* + ID_OUI_FROM_DATABASE=OSLiNK Sp. z o.o. + +OUI:0015D7* + ID_OUI_FROM_DATABASE=Reti Corporation + +OUI:0015D8* + ID_OUI_FROM_DATABASE=Interlink Electronics + +OUI:0015D9* + ID_OUI_FROM_DATABASE=PKC Electronics Oy + +OUI:0015DA* + ID_OUI_FROM_DATABASE=IRITEL A.D. + +OUI:0015DB* + ID_OUI_FROM_DATABASE=Canesta Inc. + +OUI:0015DC* + ID_OUI_FROM_DATABASE=KT&C Co., Ltd. + +OUI:0015DD* + ID_OUI_FROM_DATABASE=IP Control Systems Ltd. + +OUI:0015DE* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0015DF* + ID_OUI_FROM_DATABASE=Clivet S.p.A. + +OUI:0015E0* + ID_OUI_FROM_DATABASE=Ericsson + +OUI:0015E1* + ID_OUI_FROM_DATABASE=Picochip Ltd + +OUI:0015E2* + ID_OUI_FROM_DATABASE=Dr.Ing. Herbert Knauer GmbH + +OUI:0015E3* + ID_OUI_FROM_DATABASE=Dream Technologies Corporation + +OUI:0015E4* + ID_OUI_FROM_DATABASE=Zimmer Elektromedizin + +OUI:0015E5* + ID_OUI_FROM_DATABASE=Cheertek Inc. + +OUI:0015E6* + ID_OUI_FROM_DATABASE=MOBILE TECHNIKA Inc. + +OUI:0015E7* + ID_OUI_FROM_DATABASE=Quantec Tontechnik + +OUI:0015E8* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0015E9* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:0015EA* + ID_OUI_FROM_DATABASE=Tellumat (Pty) Ltd + +OUI:0015EB* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:0015EC* + ID_OUI_FROM_DATABASE=Boca Devices LLC + +OUI:0015ED* + ID_OUI_FROM_DATABASE=Fulcrum Microsystems, Inc. + +OUI:0015EE* + ID_OUI_FROM_DATABASE=Omnex Control Systems + +OUI:0015EF* + ID_OUI_FROM_DATABASE=NEC TOKIN Corporation + +OUI:0015F0* + ID_OUI_FROM_DATABASE=EGO BV + +OUI:0015F1* + ID_OUI_FROM_DATABASE=KYLINK Communications Corp. + +OUI:0015F2* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:0015F3* + ID_OUI_FROM_DATABASE=PELTOR AB + +OUI:0015F4* + ID_OUI_FROM_DATABASE=Eventide + +OUI:0015F5* + ID_OUI_FROM_DATABASE=Sustainable Energy Systems + +OUI:0015F6* + ID_OUI_FROM_DATABASE=SCIENCE AND ENGINEERING SERVICES, INC. + +OUI:0015F7* + ID_OUI_FROM_DATABASE=Wintecronics Ltd. + +OUI:0015F8* + ID_OUI_FROM_DATABASE=Kingtronics Industrial Co. Ltd. + +OUI:0015F9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0015FA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0015FB* + ID_OUI_FROM_DATABASE=setex schermuly textile computer gmbh + +OUI:0015FC* + ID_OUI_FROM_DATABASE=Littelfuse Startco + +OUI:0015FD* + ID_OUI_FROM_DATABASE=Complete Media Systems + +OUI:0015FE* + ID_OUI_FROM_DATABASE=SCHILLING ROBOTICS LLC + +OUI:0015FF* + ID_OUI_FROM_DATABASE=Novatel Wireless Solutions, Inc. + +OUI:001600* + ID_OUI_FROM_DATABASE=CelleBrite Mobile Synchronization + +OUI:001601* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:001602* + ID_OUI_FROM_DATABASE=CEYON TECHNOLOGY CO.,LTD. + +OUI:001603* + ID_OUI_FROM_DATABASE=COOLKSKY Co., LTD + +OUI:001604* + ID_OUI_FROM_DATABASE=Sigpro + +OUI:001605* + ID_OUI_FROM_DATABASE=YORKVILLE SOUND INC. + +OUI:001606* + ID_OUI_FROM_DATABASE=Ideal Industries + +OUI:001607* + ID_OUI_FROM_DATABASE=Curves International Inc. + +OUI:001608* + ID_OUI_FROM_DATABASE=Sequans Communications + +OUI:001609* + ID_OUI_FROM_DATABASE=Unitech electronics co., ltd. + +OUI:00160A* + ID_OUI_FROM_DATABASE=SWEEX Europe BV + +OUI:00160B* + ID_OUI_FROM_DATABASE=TVWorks LLC + +OUI:00160C* + ID_OUI_FROM_DATABASE=LPL DEVELOPMENT S.A. DE C.V + +OUI:00160D* + ID_OUI_FROM_DATABASE=Be Here Corporation + +OUI:00160E* + ID_OUI_FROM_DATABASE=Optica Technologies Inc. + +OUI:00160F* + ID_OUI_FROM_DATABASE=BADGER METER INC + +OUI:001610* + ID_OUI_FROM_DATABASE=Carina Technology + +OUI:001611* + ID_OUI_FROM_DATABASE=Altecon Srl + +OUI:001612* + ID_OUI_FROM_DATABASE=Otsuka Electronics Co., Ltd. + +OUI:001613* + ID_OUI_FROM_DATABASE=LibreStream Technologies Inc. + +OUI:001614* + ID_OUI_FROM_DATABASE=Picosecond Pulse Labs + +OUI:001615* + ID_OUI_FROM_DATABASE=Nittan Company, Limited + +OUI:001616* + ID_OUI_FROM_DATABASE=BROWAN COMMUNICATION INC. + +OUI:001617* + ID_OUI_FROM_DATABASE=MSI + +OUI:001618* + ID_OUI_FROM_DATABASE=HIVION Co., Ltd. + +OUI:001619* + ID_OUI_FROM_DATABASE=Lancelan Technologies S.L. + +OUI:00161A* + ID_OUI_FROM_DATABASE=Dametric AB + +OUI:00161B* + ID_OUI_FROM_DATABASE=Micronet Corporation + +OUI:00161C* + ID_OUI_FROM_DATABASE=e:cue + +OUI:00161D* + ID_OUI_FROM_DATABASE=Innovative Wireless Technologies, Inc. + +OUI:00161E* + ID_OUI_FROM_DATABASE=Woojinnet + +OUI:00161F* + ID_OUI_FROM_DATABASE=SUNWAVETEC Co., Ltd. + +OUI:001620* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:001621* + ID_OUI_FROM_DATABASE=Colorado Vnet + +OUI:001622* + ID_OUI_FROM_DATABASE=BBH SYSTEMS GMBH + +OUI:001623* + ID_OUI_FROM_DATABASE=Interval Media + +OUI:001624* + ID_OUI_FROM_DATABASE=Teneros, Inc. + +OUI:001625* + ID_OUI_FROM_DATABASE=Impinj, Inc. + +OUI:001626* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001627* + ID_OUI_FROM_DATABASE=embedded-logic DESIGN AND MORE GmbH + +OUI:001628* + ID_OUI_FROM_DATABASE=Magicard Ltd + +OUI:001629* + ID_OUI_FROM_DATABASE=Nivus GmbH + +OUI:00162A* + ID_OUI_FROM_DATABASE=Antik computers & communications s.r.o. + +OUI:00162B* + ID_OUI_FROM_DATABASE=Togami Electric Mfg.co.,Ltd. + +OUI:00162C* + ID_OUI_FROM_DATABASE=Xanboo + +OUI:00162D* + ID_OUI_FROM_DATABASE=STNet Co., Ltd. + +OUI:00162E* + ID_OUI_FROM_DATABASE=Space Shuttle Hi-Tech Co., Ltd. + +OUI:00162F* + ID_OUI_FROM_DATABASE=Geutebrück GmbH + +OUI:001630* + ID_OUI_FROM_DATABASE=Vativ Technologies + +OUI:001631* + ID_OUI_FROM_DATABASE=Xteam + +OUI:001632* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001633* + ID_OUI_FROM_DATABASE=Oxford Diagnostics Ltd. + +OUI:001634* + ID_OUI_FROM_DATABASE=Mathtech, Inc. + +OUI:001635* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001636* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:001637* + ID_OUI_FROM_DATABASE=CITEL SpA + +OUI:001638* + ID_OUI_FROM_DATABASE=TECOM Co., Ltd. + +OUI:001639* + ID_OUI_FROM_DATABASE=Ubiquam Co., Ltd. + +OUI:00163A* + ID_OUI_FROM_DATABASE=YVES TECHNOLOGY CO., LTD. + +OUI:00163B* + ID_OUI_FROM_DATABASE=VertexRSI/General Dynamics + +OUI:00163C* + ID_OUI_FROM_DATABASE=Rebox B.V. + +OUI:00163D* + ID_OUI_FROM_DATABASE=Tsinghua Tongfang Legend Silicon Tech. Co., Ltd. + +OUI:00163E* + ID_OUI_FROM_DATABASE=Xensource, Inc. + +OUI:00163F* + ID_OUI_FROM_DATABASE=CReTE SYSTEMS Inc. + +OUI:001640* + ID_OUI_FROM_DATABASE=Asmobile Communication Inc. + +OUI:001641* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:001642* + ID_OUI_FROM_DATABASE=Pangolin + +OUI:001643* + ID_OUI_FROM_DATABASE=Sunhillo Corporation + +OUI:001644* + ID_OUI_FROM_DATABASE=LITE-ON Technology Corp. + +OUI:001645* + ID_OUI_FROM_DATABASE=Power Distribution, Inc. + +OUI:001646* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001647* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001648* + ID_OUI_FROM_DATABASE=SSD Company Limited + +OUI:001649* + ID_OUI_FROM_DATABASE=SetOne GmbH + +OUI:00164A* + ID_OUI_FROM_DATABASE=Vibration Technology Limited + +OUI:00164B* + ID_OUI_FROM_DATABASE=Quorion Data Systems GmbH + +OUI:00164C* + ID_OUI_FROM_DATABASE=PLANET INT Co., Ltd + +OUI:00164D* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:00164E* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:00164F* + ID_OUI_FROM_DATABASE=World Ethnic Broadcastin Inc. + +OUI:001650* + ID_OUI_FROM_DATABASE=Kratos EPD + +OUI:001651* + ID_OUI_FROM_DATABASE=Exeo Systems + +OUI:001652* + ID_OUI_FROM_DATABASE=Hoatech Technologies, Inc. + +OUI:001653* + ID_OUI_FROM_DATABASE=LEGO System A/S IE Electronics Division + +OUI:001654* + ID_OUI_FROM_DATABASE=Flex-P Industries Sdn. Bhd. + +OUI:001655* + ID_OUI_FROM_DATABASE=FUHO TECHNOLOGY Co., LTD + +OUI:001656* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:001657* + ID_OUI_FROM_DATABASE=Aegate Ltd + +OUI:001658* + ID_OUI_FROM_DATABASE=Fusiontech Technologies Inc. + +OUI:001659* + ID_OUI_FROM_DATABASE=Z.M.P. RADWAG + +OUI:00165A* + ID_OUI_FROM_DATABASE=Harman Specialty Group + +OUI:00165B* + ID_OUI_FROM_DATABASE=Grip Audio + +OUI:00165C* + ID_OUI_FROM_DATABASE=Trackflow Ltd. + +OUI:00165D* + ID_OUI_FROM_DATABASE=AirDefense, Inc. + +OUI:00165E* + ID_OUI_FROM_DATABASE=Precision I/O + +OUI:00165F* + ID_OUI_FROM_DATABASE=Fairmount Automation + +OUI:001660* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001661* + ID_OUI_FROM_DATABASE=Novatium Solutions (P) Ltd + +OUI:001662* + ID_OUI_FROM_DATABASE=Liyuh Technology Ltd. + +OUI:001663* + ID_OUI_FROM_DATABASE=KBT Mobile + +OUI:001664* + ID_OUI_FROM_DATABASE=Prod-El SpA + +OUI:001665* + ID_OUI_FROM_DATABASE=Cellon France + +OUI:001666* + ID_OUI_FROM_DATABASE=Quantier Communication Inc. + +OUI:001667* + ID_OUI_FROM_DATABASE=A-TEC Subsystem INC. + +OUI:001668* + ID_OUI_FROM_DATABASE=Eishin Electronics + +OUI:001669* + ID_OUI_FROM_DATABASE=MRV Communication (Networks) LTD + +OUI:00166A* + ID_OUI_FROM_DATABASE=TPS + +OUI:00166B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00166C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00166D* + ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + +OUI:00166E* + ID_OUI_FROM_DATABASE=Arbitron Inc. + +OUI:00166F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001670* + ID_OUI_FROM_DATABASE=SKNET Corporation + +OUI:001671* + ID_OUI_FROM_DATABASE=Symphox Information Co. + +OUI:001672* + ID_OUI_FROM_DATABASE=Zenway enterprise ltd + +OUI:001673* + ID_OUI_FROM_DATABASE=Bury GmbH & Co. KG + +OUI:001674* + ID_OUI_FROM_DATABASE=EuroCB (Phils.), Inc. + +OUI:001675* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001676* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001677* + ID_OUI_FROM_DATABASE=Bihl + Wiedemann GmbH + +OUI:001678* + ID_OUI_FROM_DATABASE=SHENZHEN BAOAN GAOKE ELECTRONICS CO., LTD + +OUI:001679* + ID_OUI_FROM_DATABASE=eOn Communications + +OUI:00167A* + ID_OUI_FROM_DATABASE=Skyworth Overseas Development Ltd. + +OUI:00167B* + ID_OUI_FROM_DATABASE=Haver&Boecker + +OUI:00167C* + ID_OUI_FROM_DATABASE=iRex Technologies BV + +OUI:00167D* + ID_OUI_FROM_DATABASE=Sky-Line Information Co., Ltd. + +OUI:00167E* + ID_OUI_FROM_DATABASE=DIBOSS.CO.,LTD + +OUI:00167F* + ID_OUI_FROM_DATABASE=Bluebird Soft Inc. + +OUI:001680* + ID_OUI_FROM_DATABASE=Bally Gaming + Systems + +OUI:001681* + ID_OUI_FROM_DATABASE=Vector Informatik GmbH + +OUI:001682* + ID_OUI_FROM_DATABASE=Pro Dex, Inc + +OUI:001683* + ID_OUI_FROM_DATABASE=WEBIO International Co.,.Ltd. + +OUI:001684* + ID_OUI_FROM_DATABASE=Donjin Co.,Ltd. + +OUI:001685* + ID_OUI_FROM_DATABASE=Elisa Oyj + +OUI:001686* + ID_OUI_FROM_DATABASE=Karl Storz Imaging + +OUI:001687* + ID_OUI_FROM_DATABASE=Chubb CSC-Vendor AP + +OUI:001688* + ID_OUI_FROM_DATABASE=ServerEngines LLC + +OUI:001689* + ID_OUI_FROM_DATABASE=Pilkor Electronics Co., Ltd + +OUI:00168A* + ID_OUI_FROM_DATABASE=id-Confirm Inc + +OUI:00168B* + ID_OUI_FROM_DATABASE=Paralan Corporation + +OUI:00168C* + ID_OUI_FROM_DATABASE=DSL Partner AS + +OUI:00168D* + ID_OUI_FROM_DATABASE=KORWIN CO., Ltd. + +OUI:00168E* + ID_OUI_FROM_DATABASE=Vimicro corporation + +OUI:00168F* + ID_OUI_FROM_DATABASE=GN Netcom A/S + +OUI:001690* + ID_OUI_FROM_DATABASE=J-TEK INCORPORATION + +OUI:001691* + ID_OUI_FROM_DATABASE=Moser-Baer AG + +OUI:001692* + ID_OUI_FROM_DATABASE=Scientific-Atlanta, Inc. + +OUI:001693* + ID_OUI_FROM_DATABASE=PowerLink Technology Inc. + +OUI:001694* + ID_OUI_FROM_DATABASE=Sennheiser Communications A/S + +OUI:001695* + ID_OUI_FROM_DATABASE=AVC Technology (International) Limited + +OUI:001696* + ID_OUI_FROM_DATABASE=QDI Technology (H.K.) Limited + +OUI:001697* + ID_OUI_FROM_DATABASE=NEC Corporation + +OUI:001698* + ID_OUI_FROM_DATABASE=T&A Mobile Phones + +OUI:001699* + ID_OUI_FROM_DATABASE=Tonic DVB Marketing Ltd + +OUI:00169A* + ID_OUI_FROM_DATABASE=Quadrics Ltd + +OUI:00169B* + ID_OUI_FROM_DATABASE=Alstom Transport + +OUI:00169C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00169D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00169E* + ID_OUI_FROM_DATABASE=TV One Ltd + +OUI:00169F* + ID_OUI_FROM_DATABASE=Vimtron Electronics Co., Ltd. + +OUI:0016A0* + ID_OUI_FROM_DATABASE=Auto-Maskin + +OUI:0016A1* + ID_OUI_FROM_DATABASE=3Leaf Networks + +OUI:0016A2* + ID_OUI_FROM_DATABASE=CentraLite Systems, Inc. + +OUI:0016A3* + ID_OUI_FROM_DATABASE=Ingeteam Transmission&Distribution, S.A. + +OUI:0016A4* + ID_OUI_FROM_DATABASE=Ezurio Ltd + +OUI:0016A5* + ID_OUI_FROM_DATABASE=Tandberg Storage ASA + +OUI:0016A6* + ID_OUI_FROM_DATABASE=Dovado FZ-LLC + +OUI:0016A7* + ID_OUI_FROM_DATABASE=AWETA G&P + +OUI:0016A8* + ID_OUI_FROM_DATABASE=CWT CO., LTD. + +OUI:0016A9* + ID_OUI_FROM_DATABASE=2EI + +OUI:0016AA* + ID_OUI_FROM_DATABASE=Kei Communication Technology Inc. + +OUI:0016AB* + ID_OUI_FROM_DATABASE=Dansensor A/S + +OUI:0016AC* + ID_OUI_FROM_DATABASE=Toho Technology Corp. + +OUI:0016AD* + ID_OUI_FROM_DATABASE=BT-Links Company Limited + +OUI:0016AE* + ID_OUI_FROM_DATABASE=INVENTEL + +OUI:0016AF* + ID_OUI_FROM_DATABASE=Shenzhen Union Networks Equipment Co.,Ltd. + +OUI:0016B0* + ID_OUI_FROM_DATABASE=VK Corporation + +OUI:0016B1* + ID_OUI_FROM_DATABASE=KBS + +OUI:0016B2* + ID_OUI_FROM_DATABASE=DriveCam Inc + +OUI:0016B3* + ID_OUI_FROM_DATABASE=Photonicbridges (China) Co., Ltd. + +OUI:0016B4* + ID_OUI_FROM_DATABASE=Private + +OUI:0016B5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0016B6* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:0016B7* + ID_OUI_FROM_DATABASE=Seoul Commtech + +OUI:0016B8* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:0016B9* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP + +OUI:0016BA* + ID_OUI_FROM_DATABASE=WEATHERNEWS INC. + +OUI:0016BB* + ID_OUI_FROM_DATABASE=Law-Chain Computer Technology Co Ltd + +OUI:0016BC* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0016BD* + ID_OUI_FROM_DATABASE=ATI Industrial Automation + +OUI:0016BE* + ID_OUI_FROM_DATABASE=INFRANET, Inc. + +OUI:0016BF* + ID_OUI_FROM_DATABASE=PaloDEx Group Oy + +OUI:0016C0* + ID_OUI_FROM_DATABASE=Semtech Corporation + +OUI:0016C1* + ID_OUI_FROM_DATABASE=Eleksen Ltd + +OUI:0016C2* + ID_OUI_FROM_DATABASE=Avtec Systems Inc + +OUI:0016C3* + ID_OUI_FROM_DATABASE=BA Systems Inc + +OUI:0016C4* + ID_OUI_FROM_DATABASE=SiRF Technology, Inc. + +OUI:0016C5* + ID_OUI_FROM_DATABASE=Shenzhen Xing Feng Industry Co.,Ltd + +OUI:0016C6* + ID_OUI_FROM_DATABASE=North Atlantic Industries + +OUI:0016C7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0016C8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0016C9* + ID_OUI_FROM_DATABASE=NAT Seattle, Inc. + +OUI:0016CA* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0016CB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0016CC* + ID_OUI_FROM_DATABASE=Xcute Mobile Corp. + +OUI:0016CD* + ID_OUI_FROM_DATABASE=HIJI HIGH-TECH CO., LTD. + +OUI:0016CE* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:0016CF* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:0016D0* + ID_OUI_FROM_DATABASE=ATech elektronika d.o.o. + +OUI:0016D1* + ID_OUI_FROM_DATABASE=ZAT a.s. + +OUI:0016D2* + ID_OUI_FROM_DATABASE=Caspian + +OUI:0016D3* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:0016D4* + ID_OUI_FROM_DATABASE=Compal Communications, Inc. + +OUI:0016D5* + ID_OUI_FROM_DATABASE=Synccom Co., Ltd + +OUI:0016D6* + ID_OUI_FROM_DATABASE=TDA Tech Pty Ltd + +OUI:0016D7* + ID_OUI_FROM_DATABASE=Sunways AG + +OUI:0016D8* + ID_OUI_FROM_DATABASE=Senea AB + +OUI:0016D9* + ID_OUI_FROM_DATABASE=NINGBO BIRD CO.,LTD. + +OUI:0016DA* + ID_OUI_FROM_DATABASE=Futronic Technology Co. Ltd. + +OUI:0016DB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0016DC* + ID_OUI_FROM_DATABASE=ARCHOS + +OUI:0016DD* + ID_OUI_FROM_DATABASE=Gigabeam Corporation + +OUI:0016DE* + ID_OUI_FROM_DATABASE=FAST Inc + +OUI:0016DF* + ID_OUI_FROM_DATABASE=Lundinova AB + +OUI:0016E0* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:0016E1* + ID_OUI_FROM_DATABASE=SiliconStor, Inc. + +OUI:0016E2* + ID_OUI_FROM_DATABASE=American Fibertek, Inc. + +OUI:0016E3* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:0016E4* + ID_OUI_FROM_DATABASE=VANGUARD SECURITY ENGINEERING CORP. + +OUI:0016E5* + ID_OUI_FROM_DATABASE=FORDLEY DEVELOPMENT LIMITED + +OUI:0016E6* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:0016E7* + ID_OUI_FROM_DATABASE=Dynamix Promotions Limited + +OUI:0016E8* + ID_OUI_FROM_DATABASE=Sigma Designs, Inc. + +OUI:0016E9* + ID_OUI_FROM_DATABASE=Tiba Medical Inc + +OUI:0016EA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0016EB* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0016EC* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:0016ED* + ID_OUI_FROM_DATABASE=Utility, Inc + +OUI:0016EE* + ID_OUI_FROM_DATABASE=Royaldigital Inc. + +OUI:0016EF* + ID_OUI_FROM_DATABASE=Koko Fitness, Inc. + +OUI:0016F0* + ID_OUI_FROM_DATABASE=Dell + +OUI:0016F1* + ID_OUI_FROM_DATABASE=OmniSense, LLC + +OUI:0016F2* + ID_OUI_FROM_DATABASE=Dmobile System Co., Ltd. + +OUI:0016F3* + ID_OUI_FROM_DATABASE=CAST Information Co., Ltd + +OUI:0016F4* + ID_OUI_FROM_DATABASE=Eidicom Co., Ltd. + +OUI:0016F5* + ID_OUI_FROM_DATABASE=Dalian Golden Hualu Digital Technology Co.,Ltd + +OUI:0016F6* + ID_OUI_FROM_DATABASE=Video Products Group + +OUI:0016F7* + ID_OUI_FROM_DATABASE=L-3 Communications, Aviation Recorders + +OUI:0016F8* + ID_OUI_FROM_DATABASE=AVIQTECH TECHNOLOGY CO., LTD. + +OUI:0016F9* + ID_OUI_FROM_DATABASE=CETRTA POT, d.o.o., Kranj + +OUI:0016FA* + ID_OUI_FROM_DATABASE=ECI Telecom Ltd. + +OUI:0016FB* + ID_OUI_FROM_DATABASE=SHENZHEN MTC CO LTD + +OUI:0016FC* + ID_OUI_FROM_DATABASE=TOHKEN CO.,LTD. + +OUI:0016FD* + ID_OUI_FROM_DATABASE=Jaty Electronics + +OUI:0016FE* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:0016FF* + ID_OUI_FROM_DATABASE=Wamin Optocomm Mfg Corp + +OUI:001700* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001701* + ID_OUI_FROM_DATABASE=KDE, Inc. + +OUI:001702* + ID_OUI_FROM_DATABASE=Osung Midicom Co., Ltd + +OUI:001703* + ID_OUI_FROM_DATABASE=MOSDAN Internation Co.,Ltd + +OUI:001704* + ID_OUI_FROM_DATABASE=Shinco Electronics Group Co.,Ltd + +OUI:001705* + ID_OUI_FROM_DATABASE=Methode Electronics + +OUI:001706* + ID_OUI_FROM_DATABASE=Techfaithwireless Communication Technology Limited. + +OUI:001707* + ID_OUI_FROM_DATABASE=InGrid, Inc + +OUI:001708* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001709* + ID_OUI_FROM_DATABASE=Exalt Communications + +OUI:00170A* + ID_OUI_FROM_DATABASE=INEW DIGITAL COMPANY + +OUI:00170B* + ID_OUI_FROM_DATABASE=Contela, Inc. + +OUI:00170C* + ID_OUI_FROM_DATABASE=Twig Com Ltd. + +OUI:00170D* + ID_OUI_FROM_DATABASE=Dust Networks Inc. + +OUI:00170E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00170F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001710* + ID_OUI_FROM_DATABASE=Casa Systems Inc. + +OUI:001711* + ID_OUI_FROM_DATABASE=GE Healthcare Bio-Sciences AB + +OUI:001712* + ID_OUI_FROM_DATABASE=ISCO International + +OUI:001713* + ID_OUI_FROM_DATABASE=Tiger NetCom + +OUI:001714* + ID_OUI_FROM_DATABASE=BR Controls Nederland bv + +OUI:001715* + ID_OUI_FROM_DATABASE=Qstik + +OUI:001716* + ID_OUI_FROM_DATABASE=Qno Technology Inc. + +OUI:001717* + ID_OUI_FROM_DATABASE=Leica Geosystems AG + +OUI:001718* + ID_OUI_FROM_DATABASE=Vansco Electronics Oy + +OUI:001719* + ID_OUI_FROM_DATABASE=Audiocodes USA, Inc + +OUI:00171A* + ID_OUI_FROM_DATABASE=Winegard Company + +OUI:00171B* + ID_OUI_FROM_DATABASE=Innovation Lab Corp. + +OUI:00171C* + ID_OUI_FROM_DATABASE=NT MicroSystems, Inc. + +OUI:00171D* + ID_OUI_FROM_DATABASE=DIGIT + +OUI:00171E* + ID_OUI_FROM_DATABASE=Theo Benning GmbH & Co. KG + +OUI:00171F* + ID_OUI_FROM_DATABASE=IMV Corporation + +OUI:001720* + ID_OUI_FROM_DATABASE=Image Sensing Systems, Inc. + +OUI:001721* + ID_OUI_FROM_DATABASE=FITRE S.p.A. + +OUI:001722* + ID_OUI_FROM_DATABASE=Hanazeder Electronic GmbH + +OUI:001723* + ID_OUI_FROM_DATABASE=Summit Data Communications + +OUI:001724* + ID_OUI_FROM_DATABASE=Studer Professional Audio GmbH + +OUI:001725* + ID_OUI_FROM_DATABASE=Liquid Computing + +OUI:001726* + ID_OUI_FROM_DATABASE=m2c Electronic Technology Ltd. + +OUI:001727* + ID_OUI_FROM_DATABASE=Thermo Ramsey Italia s.r.l. + +OUI:001728* + ID_OUI_FROM_DATABASE=Selex Communications + +OUI:001729* + ID_OUI_FROM_DATABASE=Ubicod Co.LTD + +OUI:00172A* + ID_OUI_FROM_DATABASE=Proware Technology Corp.(By Unifosa) + +OUI:00172B* + ID_OUI_FROM_DATABASE=Global Technologies Inc. + +OUI:00172C* + ID_OUI_FROM_DATABASE=TAEJIN INFOTECH + +OUI:00172D* + ID_OUI_FROM_DATABASE=Axcen Photonics Corporation + +OUI:00172E* + ID_OUI_FROM_DATABASE=FXC Inc. + +OUI:00172F* + ID_OUI_FROM_DATABASE=NeuLion Incorporated + +OUI:001730* + ID_OUI_FROM_DATABASE=Automation Electronics + +OUI:001731* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:001732* + ID_OUI_FROM_DATABASE=Science-Technical Center RISSA + +OUI:001733* + ID_OUI_FROM_DATABASE=SFR + +OUI:001734* + ID_OUI_FROM_DATABASE=ADC Telecommunications + +OUI:001735* + ID_OUI_FROM_DATABASE=Intel Wireless Network Group + +OUI:001736* + ID_OUI_FROM_DATABASE=iiTron Inc. + +OUI:001737* + ID_OUI_FROM_DATABASE=Industrie Dial Face S.p.A. + +OUI:001738* + ID_OUI_FROM_DATABASE=International Business Machines + +OUI:001739* + ID_OUI_FROM_DATABASE=Bright Headphone Electronics Company + +OUI:00173A* + ID_OUI_FROM_DATABASE=Cloudastructure Inc + +OUI:00173B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00173C* + ID_OUI_FROM_DATABASE=Extreme Engineering Solutions + +OUI:00173D* + ID_OUI_FROM_DATABASE=Neology + +OUI:00173E* + ID_OUI_FROM_DATABASE=LeucotronEquipamentos Ltda. + +OUI:00173F* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:001740* + ID_OUI_FROM_DATABASE=Bluberi Gaming Technologies Inc + +OUI:001741* + ID_OUI_FROM_DATABASE=DEFIDEV + +OUI:001742* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:001743* + ID_OUI_FROM_DATABASE=Deck Srl + +OUI:001744* + ID_OUI_FROM_DATABASE=Araneo Ltd. + +OUI:001745* + ID_OUI_FROM_DATABASE=INNOTZ CO., Ltd + +OUI:001746* + ID_OUI_FROM_DATABASE=Freedom9 Inc. + +OUI:001747* + ID_OUI_FROM_DATABASE=Trimble + +OUI:001748* + ID_OUI_FROM_DATABASE=Neokoros Brasil Ltda + +OUI:001749* + ID_OUI_FROM_DATABASE=HYUNDAE YONG-O-SA CO.,LTD + +OUI:00174A* + ID_OUI_FROM_DATABASE=SOCOMEC + +OUI:00174B* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:00174C* + ID_OUI_FROM_DATABASE=Millipore + +OUI:00174D* + ID_OUI_FROM_DATABASE=DYNAMIC NETWORK FACTORY, INC. + +OUI:00174E* + ID_OUI_FROM_DATABASE=Parama-tech Co.,Ltd. + +OUI:00174F* + ID_OUI_FROM_DATABASE=iCatch Inc. + +OUI:001750* + ID_OUI_FROM_DATABASE=GSI Group, MicroE Systems + +OUI:001751* + ID_OUI_FROM_DATABASE=Online Corporation + +OUI:001752* + ID_OUI_FROM_DATABASE=DAGS, Inc + +OUI:001753* + ID_OUI_FROM_DATABASE=nFore Technology Inc. + +OUI:001754* + ID_OUI_FROM_DATABASE=Arkino HiTOP Corporation Limited + +OUI:001755* + ID_OUI_FROM_DATABASE=GE Security + +OUI:001756* + ID_OUI_FROM_DATABASE=Vinci Labs Oy + +OUI:001757* + ID_OUI_FROM_DATABASE=RIX TECHNOLOGY LIMITED + +OUI:001758* + ID_OUI_FROM_DATABASE=ThruVision Ltd + +OUI:001759* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00175A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00175B* + ID_OUI_FROM_DATABASE=ACS Solutions Switzerland Ltd. + +OUI:00175C* + ID_OUI_FROM_DATABASE=SHARP CORPORATION + +OUI:00175D* + ID_OUI_FROM_DATABASE=Dongseo system. + +OUI:00175E* + ID_OUI_FROM_DATABASE=Zed-3 + +OUI:00175F* + ID_OUI_FROM_DATABASE=XENOLINK Communications Co., Ltd. + +OUI:001760* + ID_OUI_FROM_DATABASE=Naito Densei Machida MFG.CO.,LTD + +OUI:001761* + ID_OUI_FROM_DATABASE=Private + +OUI:001762* + ID_OUI_FROM_DATABASE=Solar Technology, Inc. + +OUI:001763* + ID_OUI_FROM_DATABASE=Essentia S.p.A. + +OUI:001764* + ID_OUI_FROM_DATABASE=ATMedia GmbH + +OUI:001765* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001766* + ID_OUI_FROM_DATABASE=Accense Technology, Inc. + +OUI:001767* + ID_OUI_FROM_DATABASE=Earforce AS + +OUI:001768* + ID_OUI_FROM_DATABASE=Zinwave Ltd + +OUI:001769* + ID_OUI_FROM_DATABASE=Cymphonix Corp + +OUI:00176A* + ID_OUI_FROM_DATABASE=Avago Technologies + +OUI:00176B* + ID_OUI_FROM_DATABASE=Kiyon, Inc. + +OUI:00176C* + ID_OUI_FROM_DATABASE=Pivot3, Inc. + +OUI:00176D* + ID_OUI_FROM_DATABASE=CORE CORPORATION + +OUI:00176E* + ID_OUI_FROM_DATABASE=DUCATI SISTEMI + +OUI:00176F* + ID_OUI_FROM_DATABASE=PAX Computer Technology(Shenzhen) Ltd. + +OUI:001770* + ID_OUI_FROM_DATABASE=Arti Industrial Electronics Ltd. + +OUI:001771* + ID_OUI_FROM_DATABASE=APD Communications Ltd + +OUI:001772* + ID_OUI_FROM_DATABASE=ASTRO Strobel Kommunikationssysteme GmbH + +OUI:001773* + ID_OUI_FROM_DATABASE=Laketune Technologies Co. Ltd + +OUI:001774* + ID_OUI_FROM_DATABASE=Elesta GmbH + +OUI:001775* + ID_OUI_FROM_DATABASE=TTE Germany GmbH + +OUI:001776* + ID_OUI_FROM_DATABASE=Meso Scale Diagnostics, LLC + +OUI:001777* + ID_OUI_FROM_DATABASE=Obsidian Research Corporation + +OUI:001778* + ID_OUI_FROM_DATABASE=Central Music Co. + +OUI:001779* + ID_OUI_FROM_DATABASE=QuickTel + +OUI:00177A* + ID_OUI_FROM_DATABASE=ASSA ABLOY AB + +OUI:00177B* + ID_OUI_FROM_DATABASE=Azalea Networks inc + +OUI:00177C* + ID_OUI_FROM_DATABASE=Smartlink Network Systems Limited + +OUI:00177D* + ID_OUI_FROM_DATABASE=IDT Technology Limited + +OUI:00177E* + ID_OUI_FROM_DATABASE=Meshcom Technologies Inc. + +OUI:00177F* + ID_OUI_FROM_DATABASE=Worldsmart Retech + +OUI:001780* + ID_OUI_FROM_DATABASE=Applied Biosystems B.V. + +OUI:001781* + ID_OUI_FROM_DATABASE=Greystone Data System, Inc. + +OUI:001782* + ID_OUI_FROM_DATABASE=LoBenn Inc. + +OUI:001783* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:001784* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001785* + ID_OUI_FROM_DATABASE=Sparr Electronics Ltd + +OUI:001786* + ID_OUI_FROM_DATABASE=wisembed + +OUI:001787* + ID_OUI_FROM_DATABASE=Brother, Brother & Sons ApS + +OUI:001788* + ID_OUI_FROM_DATABASE=Philips Lighting BV + +OUI:001789* + ID_OUI_FROM_DATABASE=Zenitron Corporation + +OUI:00178A* + ID_OUI_FROM_DATABASE=DARTS TECHNOLOGIES CORP. + +OUI:00178B* + ID_OUI_FROM_DATABASE=Teledyne Technologies Incorporated + +OUI:00178C* + ID_OUI_FROM_DATABASE=Independent Witness, Inc + +OUI:00178D* + ID_OUI_FROM_DATABASE=Checkpoint Systems, Inc. + +OUI:00178E* + ID_OUI_FROM_DATABASE=Gunnebo Cash Automation AB + +OUI:00178F* + ID_OUI_FROM_DATABASE=NINGBO YIDONG ELECTRONIC CO.,LTD. + +OUI:001790* + ID_OUI_FROM_DATABASE=HYUNDAI DIGITECH Co, Ltd. + +OUI:001791* + ID_OUI_FROM_DATABASE=LinTech GmbH + +OUI:001792* + ID_OUI_FROM_DATABASE=Falcom Wireless Comunications Gmbh + +OUI:001793* + ID_OUI_FROM_DATABASE=Tigi Corporation + +OUI:001794* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001795* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001796* + ID_OUI_FROM_DATABASE=Rittmeyer AG + +OUI:001797* + ID_OUI_FROM_DATABASE=Telsy Elettronica S.p.A. + +OUI:001798* + ID_OUI_FROM_DATABASE=Azonic Technology Co., LTD + +OUI:001799* + ID_OUI_FROM_DATABASE=SmarTire Systems Inc. + +OUI:00179A* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:00179B* + ID_OUI_FROM_DATABASE=CHANT SINCERE CO.,LTD + +OUI:00179C* + ID_OUI_FROM_DATABASE=DEPRAG SCHULZ GMBH u. CO. + +OUI:00179D* + ID_OUI_FROM_DATABASE=Kelman Limited + +OUI:00179E* + ID_OUI_FROM_DATABASE=Sirit Inc + +OUI:00179F* + ID_OUI_FROM_DATABASE=Apricorn + +OUI:0017A0* + ID_OUI_FROM_DATABASE=RoboTech srl + +OUI:0017A1* + ID_OUI_FROM_DATABASE=3soft inc. + +OUI:0017A2* + ID_OUI_FROM_DATABASE=Camrivox Ltd. + +OUI:0017A3* + ID_OUI_FROM_DATABASE=MIX s.r.l. + +OUI:0017A4* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0017A5* + ID_OUI_FROM_DATABASE=Ralink Technology Corp + +OUI:0017A6* + ID_OUI_FROM_DATABASE=YOSIN ELECTRONICS CO., LTD. + +OUI:0017A7* + ID_OUI_FROM_DATABASE=Mobile Computing Promotion Consortium + +OUI:0017A8* + ID_OUI_FROM_DATABASE=EDM Corporation + +OUI:0017A9* + ID_OUI_FROM_DATABASE=Sentivision + +OUI:0017AA* + ID_OUI_FROM_DATABASE=elab-experience inc. + +OUI:0017AB* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:0017AC* + ID_OUI_FROM_DATABASE=O'Neil Product Development Inc. + +OUI:0017AD* + ID_OUI_FROM_DATABASE=AceNet Corporation + +OUI:0017AE* + ID_OUI_FROM_DATABASE=GAI-Tronics + +OUI:0017AF* + ID_OUI_FROM_DATABASE=Enermet + +OUI:0017B0* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0017B1* + ID_OUI_FROM_DATABASE=ACIST Medical Systems, Inc. + +OUI:0017B2* + ID_OUI_FROM_DATABASE=SK Telesys + +OUI:0017B3* + ID_OUI_FROM_DATABASE=Aftek Infosys Limited + +OUI:0017B4* + ID_OUI_FROM_DATABASE=Remote Security Systems, LLC + +OUI:0017B5* + ID_OUI_FROM_DATABASE=Peerless Systems Corporation + +OUI:0017B6* + ID_OUI_FROM_DATABASE=Aquantia Corporation + +OUI:0017B7* + ID_OUI_FROM_DATABASE=Tonze Technology Co. + +OUI:0017B8* + ID_OUI_FROM_DATABASE=NOVATRON CO., LTD. + +OUI:0017B9* + ID_OUI_FROM_DATABASE=Gambro Lundia AB + +OUI:0017BA* + ID_OUI_FROM_DATABASE=SEDO CO., LTD. + +OUI:0017BB* + ID_OUI_FROM_DATABASE=Syrinx Industrial Electronics + +OUI:0017BC* + ID_OUI_FROM_DATABASE=Touchtunes Music Corporation + +OUI:0017BD* + ID_OUI_FROM_DATABASE=Tibetsystem + +OUI:0017BE* + ID_OUI_FROM_DATABASE=Tratec Telecom B.V. + +OUI:0017BF* + ID_OUI_FROM_DATABASE=Coherent Research Limited + +OUI:0017C0* + ID_OUI_FROM_DATABASE=PureTech Systems, Inc. + +OUI:0017C1* + ID_OUI_FROM_DATABASE=CM Precision Technology LTD. + +OUI:0017C2* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:0017C3* + ID_OUI_FROM_DATABASE=KTF Technologies Inc. + +OUI:0017C4* + ID_OUI_FROM_DATABASE=Quanta Microsystems, INC. + +OUI:0017C5* + ID_OUI_FROM_DATABASE=SonicWALL + +OUI:0017C6* + ID_OUI_FROM_DATABASE=Cross Match Technologies Inc + +OUI:0017C7* + ID_OUI_FROM_DATABASE=MARA Systems Consulting AB + +OUI:0017C8* + ID_OUI_FROM_DATABASE=KYOCERA Display Corporation + +OUI:0017C9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0017CA* + ID_OUI_FROM_DATABASE=Qisda Corporation + +OUI:0017CB* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:0017CC* + ID_OUI_FROM_DATABASE=Alcatel-Lucent + +OUI:0017CD* + ID_OUI_FROM_DATABASE=CEC Wireless R&D Ltd. + +OUI:0017CE* + ID_OUI_FROM_DATABASE=Screen Service Spa + +OUI:0017CF* + ID_OUI_FROM_DATABASE=iMCA-GmbH + +OUI:0017D0* + ID_OUI_FROM_DATABASE=Opticom Communications, LLC + +OUI:0017D1* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0017D2* + ID_OUI_FROM_DATABASE=THINLINX PTY LTD + +OUI:0017D3* + ID_OUI_FROM_DATABASE=Etymotic Research, Inc. + +OUI:0017D4* + ID_OUI_FROM_DATABASE=Monsoon Multimedia, Inc + +OUI:0017D5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0017D6* + ID_OUI_FROM_DATABASE=Bluechips Microhouse Co.,Ltd. + +OUI:0017D7* + ID_OUI_FROM_DATABASE=ION Geophysical Corporation Inc. + +OUI:0017D8* + ID_OUI_FROM_DATABASE=Magnum Semiconductor, Inc. + +OUI:0017D9* + ID_OUI_FROM_DATABASE=AAI Corporation + +OUI:0017DA* + ID_OUI_FROM_DATABASE=Spans Logic + +OUI:0017DB* + ID_OUI_FROM_DATABASE=CANKO TECHNOLOGIES INC. + +OUI:0017DC* + ID_OUI_FROM_DATABASE=DAEMYUNG ZERO1 + +OUI:0017DD* + ID_OUI_FROM_DATABASE=Clipsal Australia + +OUI:0017DE* + ID_OUI_FROM_DATABASE=Advantage Six Ltd + +OUI:0017DF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0017E0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0017E1* + ID_OUI_FROM_DATABASE=DACOS Technologies Co., Ltd. + +OUI:0017E2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0017E3* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0017E4* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0017E5* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0017E6* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0017E7* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0017E8* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0017E9* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0017EA* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0017EB* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0017EC* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0017ED* + ID_OUI_FROM_DATABASE=WooJooIT Ltd. + +OUI:0017EE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0017EF* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:0017F0* + ID_OUI_FROM_DATABASE=SZCOM Broadband Network Technology Co.,Ltd + +OUI:0017F1* + ID_OUI_FROM_DATABASE=Renu Electronics Pvt Ltd + +OUI:0017F2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0017F3* + ID_OUI_FROM_DATABASE=Harris Corporation + +OUI:0017F4* + ID_OUI_FROM_DATABASE=ZERON ALLIANCE + +OUI:0017F5* + ID_OUI_FROM_DATABASE=LIG NEOPTEK + +OUI:0017F6* + ID_OUI_FROM_DATABASE=Pyramid Meriden Inc. + +OUI:0017F7* + ID_OUI_FROM_DATABASE=CEM Solutions Pvt Ltd + +OUI:0017F8* + ID_OUI_FROM_DATABASE=Motech Industries Inc. + +OUI:0017F9* + ID_OUI_FROM_DATABASE=Forcom Sp. z o.o. + +OUI:0017FA* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:0017FB* + ID_OUI_FROM_DATABASE=FA + +OUI:0017FC* + ID_OUI_FROM_DATABASE=Suprema Inc. + +OUI:0017FD* + ID_OUI_FROM_DATABASE=Amulet Hotkey + +OUI:0017FE* + ID_OUI_FROM_DATABASE=TALOS SYSTEM INC. + +OUI:0017FF* + ID_OUI_FROM_DATABASE=PLAYLINE Co.,Ltd. + +OUI:001800* + ID_OUI_FROM_DATABASE=UNIGRAND LTD + +OUI:001801* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:001802* + ID_OUI_FROM_DATABASE=Alpha Networks Inc. + +OUI:001803* + ID_OUI_FROM_DATABASE=ArcSoft Shanghai Co. LTD + +OUI:001804* + ID_OUI_FROM_DATABASE=E-TEK DIGITAL TECHNOLOGY LIMITED + +OUI:001805* + ID_OUI_FROM_DATABASE=Beijing InHand Networking Technology Co.,Ltd. + +OUI:001806* + ID_OUI_FROM_DATABASE=Hokkei Industries Co., Ltd. + +OUI:001807* + ID_OUI_FROM_DATABASE=Fanstel Corp. + +OUI:001808* + ID_OUI_FROM_DATABASE=SightLogix, Inc. + +OUI:001809* + ID_OUI_FROM_DATABASE=CRESYN + +OUI:00180A* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:00180B* + ID_OUI_FROM_DATABASE=Brilliant Telecommunications + +OUI:00180C* + ID_OUI_FROM_DATABASE=Optelian Access Networks + +OUI:00180D* + ID_OUI_FROM_DATABASE=Terabytes Server Storage Tech Corp + +OUI:00180E* + ID_OUI_FROM_DATABASE=Avega Systems + +OUI:00180F* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001810* + ID_OUI_FROM_DATABASE=IPTrade S.A. + +OUI:001811* + ID_OUI_FROM_DATABASE=Neuros Technology International, LLC. + +OUI:001812* + ID_OUI_FROM_DATABASE=Beijing Xinwei Telecom Technology Co., Ltd. + +OUI:001813* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:001814* + ID_OUI_FROM_DATABASE=Mitutoyo Corporation + +OUI:001815* + ID_OUI_FROM_DATABASE=GZ Technologies, Inc. + +OUI:001816* + ID_OUI_FROM_DATABASE=Ubixon Co., Ltd. + +OUI:001817* + ID_OUI_FROM_DATABASE=D. E. Shaw Research, LLC + +OUI:001818* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001819* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00181A* + ID_OUI_FROM_DATABASE=AVerMedia Information Inc. + +OUI:00181B* + ID_OUI_FROM_DATABASE=TaiJin Metal Co., Ltd. + +OUI:00181C* + ID_OUI_FROM_DATABASE=Exterity Limited + +OUI:00181D* + ID_OUI_FROM_DATABASE=ASIA ELECTRONICS CO.,LTD + +OUI:00181E* + ID_OUI_FROM_DATABASE=GDX Technologies Ltd. + +OUI:00181F* + ID_OUI_FROM_DATABASE=Palmmicro Communications + +OUI:001820* + ID_OUI_FROM_DATABASE=w5networks + +OUI:001821* + ID_OUI_FROM_DATABASE=SINDORICOH + +OUI:001822* + ID_OUI_FROM_DATABASE=CEC TELECOM CO.,LTD. + +OUI:001823* + ID_OUI_FROM_DATABASE=Delta Electronics, Inc. + +OUI:001824* + ID_OUI_FROM_DATABASE=Kimaldi Electronics, S.L. + +OUI:001825* + ID_OUI_FROM_DATABASE=Private + +OUI:001826* + ID_OUI_FROM_DATABASE=Cale Access AB + +OUI:001827* + ID_OUI_FROM_DATABASE=NEC UNIFIED SOLUTIONS NEDERLAND B.V. + +OUI:001828* + ID_OUI_FROM_DATABASE=e2v technologies (UK) ltd. + +OUI:001829* + ID_OUI_FROM_DATABASE=Gatsometer + +OUI:00182A* + ID_OUI_FROM_DATABASE=Taiwan Video & Monitor + +OUI:00182B* + ID_OUI_FROM_DATABASE=Softier + +OUI:00182C* + ID_OUI_FROM_DATABASE=Ascend Networks, Inc. + +OUI:00182D* + ID_OUI_FROM_DATABASE=Artec Design + +OUI:00182E* + ID_OUI_FROM_DATABASE=XStreamHD + +OUI:00182F* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:001830* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:001831* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:001832* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:001833* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:001834* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:001835* + ID_OUI_FROM_DATABASE=Thoratec / ITC + +OUI:001836* + ID_OUI_FROM_DATABASE=REJ Co.,Ltd + +OUI:001837* + ID_OUI_FROM_DATABASE=Universal ABIT Co., Ltd. + +OUI:001838* + ID_OUI_FROM_DATABASE=PanAccess Communications,Inc. + +OUI:001839* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:00183A* + ID_OUI_FROM_DATABASE=Westell Technologies Inc. + +OUI:00183B* + ID_OUI_FROM_DATABASE=CENITS Co., Ltd. + +OUI:00183C* + ID_OUI_FROM_DATABASE=Encore Software Limited + +OUI:00183D* + ID_OUI_FROM_DATABASE=Vertex Link Corporation + +OUI:00183E* + ID_OUI_FROM_DATABASE=Digilent, Inc + +OUI:00183F* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:001840* + ID_OUI_FROM_DATABASE=3 Phoenix, Inc. + +OUI:001841* + ID_OUI_FROM_DATABASE=High Tech Computer Corp + +OUI:001842* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001843* + ID_OUI_FROM_DATABASE=Dawevision Ltd + +OUI:001844* + ID_OUI_FROM_DATABASE=Heads Up Technologies, Inc. + +OUI:001845* + ID_OUI_FROM_DATABASE=Pulsar-Telecom LLC. + +OUI:001846* + ID_OUI_FROM_DATABASE=Crypto S.A. + +OUI:001847* + ID_OUI_FROM_DATABASE=AceNet Technology Inc. + +OUI:001848* + ID_OUI_FROM_DATABASE=Vecima Networks Inc. + +OUI:001849* + ID_OUI_FROM_DATABASE=nVent, Schroff GmbH + +OUI:00184A* + ID_OUI_FROM_DATABASE=Catcher, Inc. + +OUI:00184B* + ID_OUI_FROM_DATABASE=Las Vegas Gaming, Inc. + +OUI:00184C* + ID_OUI_FROM_DATABASE=Bogen Communications + +OUI:00184D* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:00184E* + ID_OUI_FROM_DATABASE=Lianhe Technologies, Inc. + +OUI:00184F* + ID_OUI_FROM_DATABASE=8 Ways Technology Corp. + +OUI:001850* + ID_OUI_FROM_DATABASE=Secfone Kft + +OUI:001851* + ID_OUI_FROM_DATABASE=SWsoft + +OUI:001852* + ID_OUI_FROM_DATABASE=StorLink Semiconductors, Inc. + +OUI:001853* + ID_OUI_FROM_DATABASE=Atera Networks LTD. + +OUI:001854* + ID_OUI_FROM_DATABASE=Argard Co., Ltd + +OUI:001855* + ID_OUI_FROM_DATABASE=Aeromaritime Systembau GmbH + +OUI:001856* + ID_OUI_FROM_DATABASE=EyeFi, Inc + +OUI:001857* + ID_OUI_FROM_DATABASE=Unilever R&D + +OUI:001858* + ID_OUI_FROM_DATABASE=TagMaster AB + +OUI:001859* + ID_OUI_FROM_DATABASE=Strawberry Linux Co.,Ltd. + +OUI:00185A* + ID_OUI_FROM_DATABASE=uControl, Inc. + +OUI:00185B* + ID_OUI_FROM_DATABASE=Network Chemistry, Inc + +OUI:00185C* + ID_OUI_FROM_DATABASE=EDSLAB Technologies + +OUI:00185D* + ID_OUI_FROM_DATABASE=TAIGUEN TECHNOLOGY (SHEN-ZHEN) CO., LTD. + +OUI:00185E* + ID_OUI_FROM_DATABASE=Nexterm Inc. + +OUI:00185F* + ID_OUI_FROM_DATABASE=TAC Inc. + +OUI:001860* + ID_OUI_FROM_DATABASE=SIM Technology Group Shanghai Simcom Ltd., + +OUI:001861* + ID_OUI_FROM_DATABASE=Ooma, Inc. + +OUI:001862* + ID_OUI_FROM_DATABASE=Seagate Technology + +OUI:001863* + ID_OUI_FROM_DATABASE=Veritech Electronics Limited + +OUI:001864* + ID_OUI_FROM_DATABASE=Eaton Corporation + +OUI:001865* + ID_OUI_FROM_DATABASE=Siemens Healthcare Diagnostics Manufacturing Ltd + +OUI:001866* + ID_OUI_FROM_DATABASE=Leutron Vision + +OUI:001867* + ID_OUI_FROM_DATABASE=Datalogic ADC + +OUI:001868* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:001869* + ID_OUI_FROM_DATABASE=KINGJIM + +OUI:00186A* + ID_OUI_FROM_DATABASE=Global Link Digital Technology Co,.LTD + +OUI:00186B* + ID_OUI_FROM_DATABASE=Sambu Communics CO., LTD. + +OUI:00186C* + ID_OUI_FROM_DATABASE=Neonode AB + +OUI:00186D* + ID_OUI_FROM_DATABASE=Zhenjiang Sapphire Electronic Industry CO. + +OUI:00186E* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:00186F* + ID_OUI_FROM_DATABASE=Setha Industria Eletronica LTDA + +OUI:001870* + ID_OUI_FROM_DATABASE=E28 Shanghai Limited + +OUI:001871* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001872* + ID_OUI_FROM_DATABASE=Expertise Engineering + +OUI:001873* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001874* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001875* + ID_OUI_FROM_DATABASE=AnaCise Testnology Pte Ltd + +OUI:001876* + ID_OUI_FROM_DATABASE=WowWee Ltd. + +OUI:001877* + ID_OUI_FROM_DATABASE=Amplex A/S + +OUI:001878* + ID_OUI_FROM_DATABASE=Mackware GmbH + +OUI:001879* + ID_OUI_FROM_DATABASE=dSys + +OUI:00187A* + ID_OUI_FROM_DATABASE=Wiremold + +OUI:00187B* + ID_OUI_FROM_DATABASE=4NSYS Co. Ltd. + +OUI:00187C* + ID_OUI_FROM_DATABASE=INTERCROSS, LLC + +OUI:00187D* + ID_OUI_FROM_DATABASE=Armorlink Co .Ltd + +OUI:00187E* + ID_OUI_FROM_DATABASE=RGB Spectrum + +OUI:00187F* + ID_OUI_FROM_DATABASE=ZODIANET + +OUI:001880* + ID_OUI_FROM_DATABASE=Maxim Integrated Products + +OUI:001881* + ID_OUI_FROM_DATABASE=Buyang Electronics Industrial Co., Ltd + +OUI:001882* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:001883* + ID_OUI_FROM_DATABASE=FORMOSA21 INC. + +OUI:001884* + ID_OUI_FROM_DATABASE=Fon Technology S.L. + +OUI:001885* + ID_OUI_FROM_DATABASE=Avigilon Corporation + +OUI:001886* + ID_OUI_FROM_DATABASE=EL-TECH, INC. + +OUI:001887* + ID_OUI_FROM_DATABASE=Metasystem SpA + +OUI:001888* + ID_OUI_FROM_DATABASE=GOTIVE a.s. + +OUI:001889* + ID_OUI_FROM_DATABASE=WinNet Solutions Limited + +OUI:00188A* + ID_OUI_FROM_DATABASE=Infinova LLC + +OUI:00188B* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:00188C* + ID_OUI_FROM_DATABASE=Mobile Action Technology Inc. + +OUI:00188D* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:00188E* + ID_OUI_FROM_DATABASE=Ekahau, Inc. + +OUI:00188F* + ID_OUI_FROM_DATABASE=Montgomery Technology, Inc. + +OUI:001890* + ID_OUI_FROM_DATABASE=RadioCOM, s.r.o. + +OUI:001891* + ID_OUI_FROM_DATABASE=Zhongshan General K-mate Electronics Co., Ltd + +OUI:001892* + ID_OUI_FROM_DATABASE=ads-tec GmbH + +OUI:001893* + ID_OUI_FROM_DATABASE=SHENZHEN PHOTON BROADBAND TECHNOLOGY CO.,LTD + +OUI:001894* + ID_OUI_FROM_DATABASE=NPCore, Inc. + +OUI:001895* + ID_OUI_FROM_DATABASE=Hansun Technologies Inc. + +OUI:001896* + ID_OUI_FROM_DATABASE=Great Well Electronic LTD + +OUI:001897* + ID_OUI_FROM_DATABASE=JESS-LINK PRODUCTS Co., LTD + +OUI:001898* + ID_OUI_FROM_DATABASE=KINGSTATE ELECTRONICS CORPORATION + +OUI:001899* + ID_OUI_FROM_DATABASE=ShenZhen jieshun Science&Technology Industry CO,LTD. + +OUI:00189A* + ID_OUI_FROM_DATABASE=HANA Micron Inc. + +OUI:00189B* + ID_OUI_FROM_DATABASE=Thomson Inc. + +OUI:00189C* + ID_OUI_FROM_DATABASE=Weldex Corporation + +OUI:00189D* + ID_OUI_FROM_DATABASE=Navcast Inc. + +OUI:00189E* + ID_OUI_FROM_DATABASE=OMNIKEY GmbH. + +OUI:00189F* + ID_OUI_FROM_DATABASE=Lenntek Corporation + +OUI:0018A0* + ID_OUI_FROM_DATABASE=Cierma Ascenseurs + +OUI:0018A1* + ID_OUI_FROM_DATABASE=Tiqit Computers, Inc. + +OUI:0018A2* + ID_OUI_FROM_DATABASE=XIP Technology AB + +OUI:0018A3* + ID_OUI_FROM_DATABASE=ZIPPY TECHNOLOGY CORP. + +OUI:0018A4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0018A5* + ID_OUI_FROM_DATABASE=ADigit Technologies Corp. + +OUI:0018A6* + ID_OUI_FROM_DATABASE=Persistent Systems, LLC + +OUI:0018A7* + ID_OUI_FROM_DATABASE=Yoggie Security Systems LTD. + +OUI:0018A8* + ID_OUI_FROM_DATABASE=AnNeal Technology Inc. + +OUI:0018A9* + ID_OUI_FROM_DATABASE=Ethernet Direct Corporation + +OUI:0018AA* + ID_OUI_FROM_DATABASE=Protec Fire Detection plc + +OUI:0018AB* + ID_OUI_FROM_DATABASE=BEIJING LHWT MICROELECTRONICS INC. + +OUI:0018AC* + ID_OUI_FROM_DATABASE=Shanghai Jiao Da HISYS Technology Co. Ltd. + +OUI:0018AD* + ID_OUI_FROM_DATABASE=NIDEC SANKYO CORPORATION + +OUI:0018AE* + ID_OUI_FROM_DATABASE=TVT CO.,LTD + +OUI:0018AF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0018B0* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0018B1* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:0018B2* + ID_OUI_FROM_DATABASE=ADEUNIS RF + +OUI:0018B3* + ID_OUI_FROM_DATABASE=TEC WizHome Co., Ltd. + +OUI:0018B4* + ID_OUI_FROM_DATABASE=Dawon Media Inc. + +OUI:0018B5* + ID_OUI_FROM_DATABASE=Magna Carta + +OUI:0018B6* + ID_OUI_FROM_DATABASE=S3C, Inc. + +OUI:0018B7* + ID_OUI_FROM_DATABASE=D3 LED, LLC + +OUI:0018B8* + ID_OUI_FROM_DATABASE=New Voice International AG + +OUI:0018B9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0018BA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0018BB* + ID_OUI_FROM_DATABASE=Eliwell Controls srl + +OUI:0018BC* + ID_OUI_FROM_DATABASE=ZAO NVP Bolid + +OUI:0018BD* + ID_OUI_FROM_DATABASE=SHENZHEN DVBWORLD TECHNOLOGY CO., LTD. + +OUI:0018BE* + ID_OUI_FROM_DATABASE=ANSA Corporation + +OUI:0018BF* + ID_OUI_FROM_DATABASE=Essence Technology Solution, Inc. + +OUI:0018C0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0018C1* + ID_OUI_FROM_DATABASE=Almitec Informática e Comércio + +OUI:0018C2* + ID_OUI_FROM_DATABASE=Firetide, Inc + +OUI:0018C3* + ID_OUI_FROM_DATABASE=CS Corporation + +OUI:0018C4* + ID_OUI_FROM_DATABASE=Raba Technologies LLC + +OUI:0018C5* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0018C6* + ID_OUI_FROM_DATABASE=OPW Fuel Management Systems + +OUI:0018C7* + ID_OUI_FROM_DATABASE=Real Time Automation + +OUI:0018C8* + ID_OUI_FROM_DATABASE=ISONAS Inc. + +OUI:0018C9* + ID_OUI_FROM_DATABASE=EOps Technology Limited + +OUI:0018CA* + ID_OUI_FROM_DATABASE=Viprinet GmbH + +OUI:0018CB* + ID_OUI_FROM_DATABASE=Tecobest Technology Limited + +OUI:0018CC* + ID_OUI_FROM_DATABASE=AXIOHM SAS + +OUI:0018CD* + ID_OUI_FROM_DATABASE=Erae Electronics Industry Co., Ltd + +OUI:0018CE* + ID_OUI_FROM_DATABASE=Dreamtech Co., Ltd + +OUI:0018CF* + ID_OUI_FROM_DATABASE=Baldor Electric Company + +OUI:0018D0* + ID_OUI_FROM_DATABASE=AtRoad, A Trimble Company + +OUI:0018D1* + ID_OUI_FROM_DATABASE=Siemens Home & Office Comm. Devices + +OUI:0018D2* + ID_OUI_FROM_DATABASE=High-Gain Antennas LLC + +OUI:0018D3* + ID_OUI_FROM_DATABASE=TEAMCAST + +OUI:0018D4* + ID_OUI_FROM_DATABASE=Unified Display Interface SIG + +OUI:0018D5* + ID_OUI_FROM_DATABASE=REIGNCOM + +OUI:0018D6* + ID_OUI_FROM_DATABASE=Swirlnet A/S + +OUI:0018D7* + ID_OUI_FROM_DATABASE=JAVAD GNSS, Inc. + +OUI:0018D8* + ID_OUI_FROM_DATABASE=ARCH METER Corporation + +OUI:0018D9* + ID_OUI_FROM_DATABASE=Santosha Internatonal, Inc + +OUI:0018DA* + ID_OUI_FROM_DATABASE=Würth Elektronik eiSos GmbH & Co. KG + +OUI:0018DB* + ID_OUI_FROM_DATABASE=EPL Technology Ltd + +OUI:0018DC* + ID_OUI_FROM_DATABASE=Prostar Co., Ltd. + +OUI:0018DD* + ID_OUI_FROM_DATABASE=Silicondust Engineering Ltd + +OUI:0018DE* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0018DF* + ID_OUI_FROM_DATABASE=The Morey Corporation + +OUI:0018E0* + ID_OUI_FROM_DATABASE=ANAVEO + +OUI:0018E1* + ID_OUI_FROM_DATABASE=Verkerk Service Systemen + +OUI:0018E2* + ID_OUI_FROM_DATABASE=Topdata Sistemas de Automacao Ltda + +OUI:0018E3* + ID_OUI_FROM_DATABASE=Visualgate Systems, Inc. + +OUI:0018E4* + ID_OUI_FROM_DATABASE=YIGUANG + +OUI:0018E5* + ID_OUI_FROM_DATABASE=Adhoco AG + +OUI:0018E6* + ID_OUI_FROM_DATABASE=Computer Hardware Design SIA + +OUI:0018E7* + ID_OUI_FROM_DATABASE=Cameo Communications, INC. + +OUI:0018E8* + ID_OUI_FROM_DATABASE=Hacetron Corporation + +OUI:0018E9* + ID_OUI_FROM_DATABASE=Numata Corporation + +OUI:0018EA* + ID_OUI_FROM_DATABASE=Alltec GmbH + +OUI:0018EB* + ID_OUI_FROM_DATABASE=Blue Zen Enterprises Private Limited + +OUI:0018EC* + ID_OUI_FROM_DATABASE=Welding Technology Corporation + +OUI:0018ED* + ID_OUI_FROM_DATABASE=Accutech Ultrasystems Co., Ltd. + +OUI:0018EE* + ID_OUI_FROM_DATABASE=Videology Imaging Solutions, Inc. + +OUI:0018EF* + ID_OUI_FROM_DATABASE=Escape Communications, Inc. + +OUI:0018F0* + ID_OUI_FROM_DATABASE=JOYTOTO Co., Ltd. + +OUI:0018F1* + ID_OUI_FROM_DATABASE=Chunichi Denshi Co.,LTD. + +OUI:0018F2* + ID_OUI_FROM_DATABASE=Beijing Tianyu Communication Equipment Co., Ltd + +OUI:0018F3* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:0018F4* + ID_OUI_FROM_DATABASE=EO TECHNICS Co., Ltd. + +OUI:0018F5* + ID_OUI_FROM_DATABASE=Shenzhen Streaming Video Technology Company Limited + +OUI:0018F6* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium + +OUI:0018F7* + ID_OUI_FROM_DATABASE=Kameleon Technologies + +OUI:0018F8* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:0018F9* + ID_OUI_FROM_DATABASE=VVOND, Inc. + +OUI:0018FA* + ID_OUI_FROM_DATABASE=Yushin Precision Equipment Co.,Ltd. + +OUI:0018FB* + ID_OUI_FROM_DATABASE=Compro Technology + +OUI:0018FC* + ID_OUI_FROM_DATABASE=Altec Electronic AG + +OUI:0018FD* + ID_OUI_FROM_DATABASE=Optimal Technologies International Inc. + +OUI:0018FE* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0018FF* + ID_OUI_FROM_DATABASE=PowerQuattro Co. + +OUI:001900* + ID_OUI_FROM_DATABASE=Intelliverese - DBA Voicecom + +OUI:001901* + ID_OUI_FROM_DATABASE=F1MEDIA + +OUI:001902* + ID_OUI_FROM_DATABASE=Cambridge Consultants Ltd + +OUI:001903* + ID_OUI_FROM_DATABASE=Bigfoot Networks Inc + +OUI:001904* + ID_OUI_FROM_DATABASE=WB Electronics Sp. z o.o. + +OUI:001905* + ID_OUI_FROM_DATABASE=SCHRACK Seconet AG + +OUI:001906* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001907* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001908* + ID_OUI_FROM_DATABASE=Duaxes Corporation + +OUI:001909* + ID_OUI_FROM_DATABASE=DEVI - Danfoss A/S + +OUI:00190A* + ID_OUI_FROM_DATABASE=HASWARE INC. + +OUI:00190B* + ID_OUI_FROM_DATABASE=Southern Vision Systems, Inc. + +OUI:00190C* + ID_OUI_FROM_DATABASE=Encore Electronics, Inc. + +OUI:00190D* + ID_OUI_FROM_DATABASE=IEEE 1394c + +OUI:00190E* + ID_OUI_FROM_DATABASE=Atech Technology Co., Ltd. + +OUI:00190F* + ID_OUI_FROM_DATABASE=Advansus Corp. + +OUI:001910* + ID_OUI_FROM_DATABASE=Knick Elektronische Messgeraete GmbH & Co. KG + +OUI:001911* + ID_OUI_FROM_DATABASE=Just In Mobile Information Technologies (Shanghai) Co., Ltd. + +OUI:001912* + ID_OUI_FROM_DATABASE=Welcat Inc + +OUI:001913* + ID_OUI_FROM_DATABASE=Chuang-Yi Network Equipment Co.Ltd. + +OUI:001914* + ID_OUI_FROM_DATABASE=Winix Co., Ltd + +OUI:001915* + ID_OUI_FROM_DATABASE=TECOM Co., Ltd. + +OUI:001916* + ID_OUI_FROM_DATABASE=PayTec AG + +OUI:001917* + ID_OUI_FROM_DATABASE=Posiflex Inc. + +OUI:001918* + ID_OUI_FROM_DATABASE=Interactive Wear AG + +OUI:001919* + ID_OUI_FROM_DATABASE=ASTEL Inc. + +OUI:00191A* + ID_OUI_FROM_DATABASE=IRLINK + +OUI:00191B* + ID_OUI_FROM_DATABASE=Sputnik Engineering AG + +OUI:00191C* + ID_OUI_FROM_DATABASE=Sensicast Systems + +OUI:00191D* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:00191E* + ID_OUI_FROM_DATABASE=Beyondwiz Co., Ltd. + +OUI:00191F* + ID_OUI_FROM_DATABASE=Microlink communications Inc. + +OUI:001920* + ID_OUI_FROM_DATABASE=KUME electric Co.,Ltd. + +OUI:001921* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:001922* + ID_OUI_FROM_DATABASE=CM Comandos Lineares + +OUI:001923* + ID_OUI_FROM_DATABASE=Phonex Korea Co., LTD. + +OUI:001924* + ID_OUI_FROM_DATABASE=LBNL Engineering + +OUI:001925* + ID_OUI_FROM_DATABASE=Intelicis Corporation + +OUI:001926* + ID_OUI_FROM_DATABASE=BitsGen Co., Ltd. + +OUI:001927* + ID_OUI_FROM_DATABASE=ImCoSys Ltd + +OUI:001928* + ID_OUI_FROM_DATABASE=Siemens AG, Transportation Systems + +OUI:001929* + ID_OUI_FROM_DATABASE=2M2B Montadora de Maquinas Bahia Brasil LTDA + +OUI:00192A* + ID_OUI_FROM_DATABASE=Antiope Associates + +OUI:00192B* + ID_OUI_FROM_DATABASE=Aclara RF Systems Inc. + +OUI:00192C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00192D* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:00192E* + ID_OUI_FROM_DATABASE=Spectral Instruments, Inc. + +OUI:00192F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001930* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001931* + ID_OUI_FROM_DATABASE=Balluff GmbH + +OUI:001932* + ID_OUI_FROM_DATABASE=Gude Analog- und Digialsysteme GmbH + +OUI:001933* + ID_OUI_FROM_DATABASE=Strix Systems, Inc. + +OUI:001934* + ID_OUI_FROM_DATABASE=TRENDON TOUCH TECHNOLOGY CORP. + +OUI:001935* + ID_OUI_FROM_DATABASE=DUERR DENTAL AG + +OUI:001936* + ID_OUI_FROM_DATABASE=STERLITE OPTICAL TECHNOLOGIES LIMITED + +OUI:001937* + ID_OUI_FROM_DATABASE=CommerceGuard AB + +OUI:001938* + ID_OUI_FROM_DATABASE=UMB Communications Co., Ltd. + +OUI:001939* + ID_OUI_FROM_DATABASE=Gigamips + +OUI:00193A* + ID_OUI_FROM_DATABASE=OESOLUTIONS + +OUI:00193B* + ID_OUI_FROM_DATABASE=LigoWave + +OUI:00193C* + ID_OUI_FROM_DATABASE=HighPoint Technologies Incorporated + +OUI:00193D* + ID_OUI_FROM_DATABASE=GMC Guardian Mobility Corp. + +OUI:00193E* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:00193F* + ID_OUI_FROM_DATABASE=RDI technology(Shenzhen) Co.,LTD + +OUI:001940* + ID_OUI_FROM_DATABASE=Rackable Systems + +OUI:001941* + ID_OUI_FROM_DATABASE=Pitney Bowes, Inc + +OUI:001942* + ID_OUI_FROM_DATABASE=ON SOFTWARE INTERNATIONAL LIMITED + +OUI:001943* + ID_OUI_FROM_DATABASE=Belden + +OUI:001944* + ID_OUI_FROM_DATABASE=Fossil Partners, L.P. + +OUI:001945* + ID_OUI_FROM_DATABASE=RF COncepts, LLC + +OUI:001946* + ID_OUI_FROM_DATABASE=Cianet Industria e Comercio S/A + +OUI:001947* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:001948* + ID_OUI_FROM_DATABASE=AireSpider Networks + +OUI:001949* + ID_OUI_FROM_DATABASE=TENTEL COMTECH CO., LTD. + +OUI:00194A* + ID_OUI_FROM_DATABASE=TESTO AG + +OUI:00194B* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:00194C* + ID_OUI_FROM_DATABASE=Fujian Stelcom information & Technology CO.,Ltd + +OUI:00194D* + ID_OUI_FROM_DATABASE=Avago Technologies Sdn Bhd + +OUI:00194E* + ID_OUI_FROM_DATABASE=Ultra Electronics - TCS (Tactical Communication Systems) + +OUI:00194F* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001950* + ID_OUI_FROM_DATABASE=Harman Multimedia + +OUI:001951* + ID_OUI_FROM_DATABASE=NETCONS, s.r.o. + +OUI:001952* + ID_OUI_FROM_DATABASE=ACOGITO Co., Ltd + +OUI:001953* + ID_OUI_FROM_DATABASE=Chainleader Communications Corp. + +OUI:001954* + ID_OUI_FROM_DATABASE=Leaf Corporation. + +OUI:001955* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001956* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001957* + ID_OUI_FROM_DATABASE=Saafnet Canada Inc. + +OUI:001958* + ID_OUI_FROM_DATABASE=Bluetooth SIG, Inc. + +OUI:001959* + ID_OUI_FROM_DATABASE=Staccato Communications Inc. + +OUI:00195A* + ID_OUI_FROM_DATABASE=Jenaer Antriebstechnik GmbH + +OUI:00195B* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:00195C* + ID_OUI_FROM_DATABASE=Innotech Corporation + +OUI:00195D* + ID_OUI_FROM_DATABASE=ShenZhen XinHuaTong Opto Electronics Co.,Ltd + +OUI:00195E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00195F* + ID_OUI_FROM_DATABASE=Valemount Networks Corporation + +OUI:001960* + ID_OUI_FROM_DATABASE=DoCoMo Systems, Inc. + +OUI:001961* + ID_OUI_FROM_DATABASE=Blaupunkt Embedded Systems GmbH + +OUI:001962* + ID_OUI_FROM_DATABASE=Commerciant, LP + +OUI:001963* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:001964* + ID_OUI_FROM_DATABASE=Doorking Inc. + +OUI:001965* + ID_OUI_FROM_DATABASE=YuHua TelTech (ShangHai) Co., Ltd. + +OUI:001966* + ID_OUI_FROM_DATABASE=Asiarock Technology Limited + +OUI:001967* + ID_OUI_FROM_DATABASE=TELDAT Sp.J. + +OUI:001968* + ID_OUI_FROM_DATABASE=Digital Video Networks(Shanghai) CO. LTD. + +OUI:001969* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:00196A* + ID_OUI_FROM_DATABASE=MikroM GmbH + +OUI:00196B* + ID_OUI_FROM_DATABASE=Danpex Corporation + +OUI:00196C* + ID_OUI_FROM_DATABASE=ETROVISION TECHNOLOGY + +OUI:00196D* + ID_OUI_FROM_DATABASE=Raybit Systems Korea, Inc + +OUI:00196E* + ID_OUI_FROM_DATABASE=Metacom (Pty) Ltd. + +OUI:00196F* + ID_OUI_FROM_DATABASE=SensoPart GmbH + +OUI:001970* + ID_OUI_FROM_DATABASE=Z-Com, Inc. + +OUI:001971* + ID_OUI_FROM_DATABASE=Guangzhou Unicomp Technology Co.,Ltd + +OUI:001972* + ID_OUI_FROM_DATABASE=Plexus (Xiamen) Co.,ltd. + +OUI:001973* + ID_OUI_FROM_DATABASE=Zeugma Systems + +OUI:001974* + ID_OUI_FROM_DATABASE=16063 + +OUI:001975* + ID_OUI_FROM_DATABASE=Beijing Huisen networks technology Inc + +OUI:001976* + ID_OUI_FROM_DATABASE=Xipher Technologies, LLC + +OUI:001977* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:001978* + ID_OUI_FROM_DATABASE=Datum Systems, Inc. + +OUI:001979* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:00197A* + ID_OUI_FROM_DATABASE=MAZeT GmbH + +OUI:00197B* + ID_OUI_FROM_DATABASE=Picotest Corp. + +OUI:00197C* + ID_OUI_FROM_DATABASE=Riedel Communications GmbH + +OUI:00197D* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:00197E* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:00197F* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. + +OUI:001980* + ID_OUI_FROM_DATABASE=Gridpoint Systems + +OUI:001981* + ID_OUI_FROM_DATABASE=Vivox Inc + +OUI:001982* + ID_OUI_FROM_DATABASE=SmarDTV + +OUI:001983* + ID_OUI_FROM_DATABASE=CCT R&D Limited + +OUI:001984* + ID_OUI_FROM_DATABASE=ESTIC Corporation + +OUI:001985* + ID_OUI_FROM_DATABASE=IT Watchdogs, Inc + +OUI:001986* + ID_OUI_FROM_DATABASE=Cheng Hongjian + +OUI:001987* + ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co.,Ltd. + +OUI:001988* + ID_OUI_FROM_DATABASE=Wi2Wi, Inc + +OUI:001989* + ID_OUI_FROM_DATABASE=Sonitrol Corporation + +OUI:00198A* + ID_OUI_FROM_DATABASE=Northrop Grumman Systems Corp. + +OUI:00198B* + ID_OUI_FROM_DATABASE=Novera Optics Korea, Inc. + +OUI:00198C* + ID_OUI_FROM_DATABASE=iXSea + +OUI:00198D* + ID_OUI_FROM_DATABASE=Ocean Optics, Inc. + +OUI:00198E* + ID_OUI_FROM_DATABASE=Oticon A/S + +OUI:00198F* + ID_OUI_FROM_DATABASE=Nokia Bell N.V. + +OUI:001990* + ID_OUI_FROM_DATABASE=ELM DATA Co., Ltd. + +OUI:001991* + ID_OUI_FROM_DATABASE=avinfo + +OUI:001992* + ID_OUI_FROM_DATABASE=Adtran Inc + +OUI:001993* + ID_OUI_FROM_DATABASE=Changshu Switchgear MFG. Co.,Ltd. (Former Changshu Switchgea + +OUI:001994* + ID_OUI_FROM_DATABASE=Jorjin Technologies Inc. + +OUI:001995* + ID_OUI_FROM_DATABASE=Jurong Hi-Tech (Suzhou)Co.ltd + +OUI:001996* + ID_OUI_FROM_DATABASE=TurboChef Technologies Inc. + +OUI:001997* + ID_OUI_FROM_DATABASE=Soft Device Sdn Bhd + +OUI:001998* + ID_OUI_FROM_DATABASE=SATO CORPORATION + +OUI:001999* + ID_OUI_FROM_DATABASE=Fujitsu Technology Solutions GmbH + +OUI:00199A* + ID_OUI_FROM_DATABASE=EDO-EVI + +OUI:00199B* + ID_OUI_FROM_DATABASE=Diversified Technical Systems, Inc. + +OUI:00199C* + ID_OUI_FROM_DATABASE=CTRING + +OUI:00199D* + ID_OUI_FROM_DATABASE=Vizio, Inc + +OUI:00199E* + ID_OUI_FROM_DATABASE=Nifty + +OUI:00199F* + ID_OUI_FROM_DATABASE=DKT A/S + +OUI:0019A0* + ID_OUI_FROM_DATABASE=NIHON DATA SYSTENS, INC. + +OUI:0019A1* + ID_OUI_FROM_DATABASE=LG INFORMATION & COMM. + +OUI:0019A2* + ID_OUI_FROM_DATABASE=ORDYN TECHNOLOGIES + +OUI:0019A3* + ID_OUI_FROM_DATABASE=asteel electronique atlantique + +OUI:0019A4* + ID_OUI_FROM_DATABASE=Austar Technology (hang zhou) Co.,Ltd + +OUI:0019A5* + ID_OUI_FROM_DATABASE=RadarFind Corporation + +OUI:0019A6* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0019A7* + ID_OUI_FROM_DATABASE=ITU-T + +OUI:0019A8* + ID_OUI_FROM_DATABASE=WiQuest Communications + +OUI:0019A9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0019AA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0019AB* + ID_OUI_FROM_DATABASE=Raycom CO ., LTD + +OUI:0019AC* + ID_OUI_FROM_DATABASE=GSP SYSTEMS Inc. + +OUI:0019AD* + ID_OUI_FROM_DATABASE=BOBST SA + +OUI:0019AE* + ID_OUI_FROM_DATABASE=Hopling Technologies b.v. + +OUI:0019AF* + ID_OUI_FROM_DATABASE=Rigol Technologies, Inc. + +OUI:0019B0* + ID_OUI_FROM_DATABASE=HanYang System + +OUI:0019B1* + ID_OUI_FROM_DATABASE=Arrow7 Corporation + +OUI:0019B2* + ID_OUI_FROM_DATABASE=XYnetsoft Co.,Ltd + +OUI:0019B3* + ID_OUI_FROM_DATABASE=Stanford Research Systems + +OUI:0019B4* + ID_OUI_FROM_DATABASE=Intellio Ltd + +OUI:0019B5* + ID_OUI_FROM_DATABASE=Famar Fueguina S.A. + +OUI:0019B6* + ID_OUI_FROM_DATABASE=Euro Emme s.r.l. + +OUI:0019B7* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0019B8* + ID_OUI_FROM_DATABASE=Boundary Devices + +OUI:0019B9* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:0019BA* + ID_OUI_FROM_DATABASE=Paradox Security Systems Ltd + +OUI:0019BB* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0019BC* + ID_OUI_FROM_DATABASE=ELECTRO CHANCE SRL + +OUI:0019BD* + ID_OUI_FROM_DATABASE=New Media Life + +OUI:0019BE* + ID_OUI_FROM_DATABASE=Altai Technologies Limited + +OUI:0019BF* + ID_OUI_FROM_DATABASE=Citiway technology Co.,ltd + +OUI:0019C0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0019C1* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:0019C2* + ID_OUI_FROM_DATABASE=Equustek Solutions, Inc. + +OUI:0019C3* + ID_OUI_FROM_DATABASE=Qualitrol + +OUI:0019C4* + ID_OUI_FROM_DATABASE=Infocrypt Inc. + +OUI:0019C5* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:0019C6* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:0019C7* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:0019C8* + ID_OUI_FROM_DATABASE=AnyDATA Corporation + +OUI:0019C9* + ID_OUI_FROM_DATABASE=S&C ELECTRIC COMPANY + +OUI:0019CA* + ID_OUI_FROM_DATABASE=Broadata Communications, Inc + +OUI:0019CB* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:0019CC* + ID_OUI_FROM_DATABASE=RCG (HK) Ltd + +OUI:0019CD* + ID_OUI_FROM_DATABASE=Chengdu ethercom information technology Ltd. + +OUI:0019CE* + ID_OUI_FROM_DATABASE=Progressive Gaming International + +OUI:0019CF* + ID_OUI_FROM_DATABASE=SALICRU, S.A. + +OUI:0019D0* + ID_OUI_FROM_DATABASE=Cathexis + +OUI:0019D1* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0019D2* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0019D3* + ID_OUI_FROM_DATABASE=TRAK Microwave + +OUI:0019D4* + ID_OUI_FROM_DATABASE=ICX Technologies + +OUI:0019D5* + ID_OUI_FROM_DATABASE=IP Innovations, Inc. + +OUI:0019D6* + ID_OUI_FROM_DATABASE=LS Cable and System Ltd. + +OUI:0019D7* + ID_OUI_FROM_DATABASE=FORTUNETEK CO., LTD + +OUI:0019D8* + ID_OUI_FROM_DATABASE=MAXFOR + +OUI:0019D9* + ID_OUI_FROM_DATABASE=Zeutschel GmbH + +OUI:0019DA* + ID_OUI_FROM_DATABASE=Welltrans O&E Technology Co. , Ltd. + +OUI:0019DB* + ID_OUI_FROM_DATABASE=MICRO-STAR INTERNATIONAL CO., LTD. + +OUI:0019DC* + ID_OUI_FROM_DATABASE=ENENSYS Technologies + +OUI:0019DD* + ID_OUI_FROM_DATABASE=FEI-Zyfer, Inc. + +OUI:0019DE* + ID_OUI_FROM_DATABASE=MOBITEK + +OUI:0019DF* + ID_OUI_FROM_DATABASE=Thomson Inc. + +OUI:0019E0* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:0019E1* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0019E2* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:0019E3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0019E4* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:0019E5* + ID_OUI_FROM_DATABASE=Lynx Studio Technology, Inc. + +OUI:0019E6* + ID_OUI_FROM_DATABASE=TOYO MEDIC CO.,LTD. + +OUI:0019E7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0019E8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0019E9* + ID_OUI_FROM_DATABASE=S-Information Technolgy, Co., Ltd. + +OUI:0019EA* + ID_OUI_FROM_DATABASE=TeraMage Technologies Co., Ltd. + +OUI:0019EB* + ID_OUI_FROM_DATABASE=Pyronix Ltd + +OUI:0019EC* + ID_OUI_FROM_DATABASE=Sagamore Systems, Inc. + +OUI:0019ED* + ID_OUI_FROM_DATABASE=Axesstel Inc. + +OUI:0019EE* + ID_OUI_FROM_DATABASE=CARLO GAVAZZI CONTROLS SPA-Controls Division + +OUI:0019EF* + ID_OUI_FROM_DATABASE=SHENZHEN LINNKING ELECTRONICS CO.,LTD + +OUI:0019F0* + ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD + +OUI:0019F1* + ID_OUI_FROM_DATABASE=Star Communication Network Technology Co.,Ltd + +OUI:0019F2* + ID_OUI_FROM_DATABASE=Teradyne K.K. + +OUI:0019F3* + ID_OUI_FROM_DATABASE=Cetis, Inc + +OUI:0019F4* + ID_OUI_FROM_DATABASE=Convergens Oy Ltd + +OUI:0019F5* + ID_OUI_FROM_DATABASE=Imagination Technologies Ltd + +OUI:0019F6* + ID_OUI_FROM_DATABASE=Acconet (PTE) Ltd + +OUI:0019F7* + ID_OUI_FROM_DATABASE=Onset Computer Corporation + +OUI:0019F8* + ID_OUI_FROM_DATABASE=Embedded Systems Design, Inc. + +OUI:0019F9* + ID_OUI_FROM_DATABASE=TDK-Lambda + +OUI:0019FA* + ID_OUI_FROM_DATABASE=Cable Vision Electronics CO., LTD. + +OUI:0019FB* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:0019FC* + ID_OUI_FROM_DATABASE=PT. Ufoakses Sukses Luarbiasa + +OUI:0019FD* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:0019FE* + ID_OUI_FROM_DATABASE=SHENZHEN SEECOMM TECHNOLOGY CO.,LTD. + +OUI:0019FF* + ID_OUI_FROM_DATABASE=Finnzymes + +OUI:001A00* + ID_OUI_FROM_DATABASE=MATRIX INC. + +OUI:001A01* + ID_OUI_FROM_DATABASE=Smiths Medical + +OUI:001A02* + ID_OUI_FROM_DATABASE=SECURE CARE PRODUCTS, INC + +OUI:001A03* + ID_OUI_FROM_DATABASE=Angel Electronics Co., Ltd. + +OUI:001A04* + ID_OUI_FROM_DATABASE=Interay Solutions BV + +OUI:001A05* + ID_OUI_FROM_DATABASE=OPTIBASE LTD + +OUI:001A06* + ID_OUI_FROM_DATABASE=OpVista, Inc. + +OUI:001A07* + ID_OUI_FROM_DATABASE=Arecont Vision + +OUI:001A08* + ID_OUI_FROM_DATABASE=Simoco Ltd. + +OUI:001A09* + ID_OUI_FROM_DATABASE=Wayfarer Transit Systems Ltd + +OUI:001A0A* + ID_OUI_FROM_DATABASE=Adaptive Micro-Ware Inc. + +OUI:001A0B* + ID_OUI_FROM_DATABASE=BONA TECHNOLOGY INC. + +OUI:001A0C* + ID_OUI_FROM_DATABASE=Swe-Dish Satellite Systems AB + +OUI:001A0D* + ID_OUI_FROM_DATABASE=HandHeld entertainment, Inc. + +OUI:001A0E* + ID_OUI_FROM_DATABASE=Cheng Uei Precision Industry Co.,Ltd + +OUI:001A0F* + ID_OUI_FROM_DATABASE=Sistemas Avanzados de Control, S.A. + +OUI:001A10* + ID_OUI_FROM_DATABASE=LUCENT TRANS ELECTRONICS CO.,LTD + +OUI:001A11* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:001A12* + ID_OUI_FROM_DATABASE=Essilor + +OUI:001A13* + ID_OUI_FROM_DATABASE=Wanlida Group Co., LTD + +OUI:001A14* + ID_OUI_FROM_DATABASE=Xin Hua Control Engineering Co.,Ltd. + +OUI:001A15* + ID_OUI_FROM_DATABASE=gemalto e-Payment + +OUI:001A16* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001A17* + ID_OUI_FROM_DATABASE=Teak Technologies, Inc. + +OUI:001A18* + ID_OUI_FROM_DATABASE=Advanced Simulation Technology inc. + +OUI:001A19* + ID_OUI_FROM_DATABASE=Computer Engineering Limited + +OUI:001A1A* + ID_OUI_FROM_DATABASE=Gentex Corporation/Electro-Acoustic Products + +OUI:001A1B* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001A1C* + ID_OUI_FROM_DATABASE=GT&T Engineering Pte Ltd + +OUI:001A1D* + ID_OUI_FROM_DATABASE=PChome Online Inc. + +OUI:001A1E* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:001A1F* + ID_OUI_FROM_DATABASE=Coastal Environmental Systems + +OUI:001A20* + ID_OUI_FROM_DATABASE=CMOTECH Co. Ltd. + +OUI:001A21* + ID_OUI_FROM_DATABASE=Brookhuis Applied Technologies BV + +OUI:001A22* + ID_OUI_FROM_DATABASE=eQ-3 Entwicklung GmbH + +OUI:001A23* + ID_OUI_FROM_DATABASE=Ice Qube, Inc + +OUI:001A24* + ID_OUI_FROM_DATABASE=Galaxy Telecom Technologies Ltd + +OUI:001A25* + ID_OUI_FROM_DATABASE=DELTA DORE + +OUI:001A26* + ID_OUI_FROM_DATABASE=Deltanode Solutions AB + +OUI:001A27* + ID_OUI_FROM_DATABASE=Ubistar + +OUI:001A28* + ID_OUI_FROM_DATABASE=ASWT Co., LTD. Taiwan Branch H.K. + +OUI:001A29* + ID_OUI_FROM_DATABASE=Johnson Outdoors Marine Electronics d/b/a Minnkota + +OUI:001A2A* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:001A2B* + ID_OUI_FROM_DATABASE=Ayecom Technology Co., Ltd. + +OUI:001A2C* + ID_OUI_FROM_DATABASE=SATEC Co.,LTD + +OUI:001A2D* + ID_OUI_FROM_DATABASE=The Navvo Group + +OUI:001A2E* + ID_OUI_FROM_DATABASE=Ziova Coporation + +OUI:001A2F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001A30* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001A31* + ID_OUI_FROM_DATABASE=SCAN COIN AB + +OUI:001A32* + ID_OUI_FROM_DATABASE=ACTIVA MULTIMEDIA + +OUI:001A33* + ID_OUI_FROM_DATABASE=ASI Communications, Inc. + +OUI:001A34* + ID_OUI_FROM_DATABASE=Konka Group Co., Ltd. + +OUI:001A35* + ID_OUI_FROM_DATABASE=BARTEC GmbH + +OUI:001A36* + ID_OUI_FROM_DATABASE=Aipermon GmbH & Co. KG + +OUI:001A37* + ID_OUI_FROM_DATABASE=Lear Corporation + +OUI:001A38* + ID_OUI_FROM_DATABASE=Sanmina-SCI + +OUI:001A39* + ID_OUI_FROM_DATABASE=Merten GmbH&CoKG + +OUI:001A3A* + ID_OUI_FROM_DATABASE=Dongahelecomm + +OUI:001A3B* + ID_OUI_FROM_DATABASE=Doah Elecom Inc. + +OUI:001A3C* + ID_OUI_FROM_DATABASE=Technowave Ltd. + +OUI:001A3D* + ID_OUI_FROM_DATABASE=Ajin Vision Co.,Ltd + +OUI:001A3E* + ID_OUI_FROM_DATABASE=Faster Technology LLC + +OUI:001A3F* + ID_OUI_FROM_DATABASE=Intelbras + +OUI:001A40* + ID_OUI_FROM_DATABASE=A-FOUR TECH CO., LTD. + +OUI:001A41* + ID_OUI_FROM_DATABASE=INOCOVA Co.,Ltd + +OUI:001A42* + ID_OUI_FROM_DATABASE=Techcity Technology co., Ltd. + +OUI:001A43* + ID_OUI_FROM_DATABASE=Logical Link Communications + +OUI:001A44* + ID_OUI_FROM_DATABASE=JWTrading Co., Ltd + +OUI:001A45* + ID_OUI_FROM_DATABASE=GN Netcom A/S + +OUI:001A46* + ID_OUI_FROM_DATABASE=Digital Multimedia Technology Co., Ltd + +OUI:001A47* + ID_OUI_FROM_DATABASE=Agami Systems, Inc. + +OUI:001A48* + ID_OUI_FROM_DATABASE=Takacom Corporation + +OUI:001A49* + ID_OUI_FROM_DATABASE=Micro Vision Co.,LTD + +OUI:001A4A* + ID_OUI_FROM_DATABASE=Qumranet Inc. + +OUI:001A4B* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001A4C* + ID_OUI_FROM_DATABASE=Crossbow Technology, Inc + +OUI:001A4D* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:001A4E* + ID_OUI_FROM_DATABASE=NTI AG / LinMot + +OUI:001A4F* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:001A50* + ID_OUI_FROM_DATABASE=PheeNet Technology Corp. + +OUI:001A51* + ID_OUI_FROM_DATABASE=Alfred Mann Foundation + +OUI:001A52* + ID_OUI_FROM_DATABASE=Meshlinx Wireless Inc. + +OUI:001A53* + ID_OUI_FROM_DATABASE=Zylaya + +OUI:001A54* + ID_OUI_FROM_DATABASE=Hip Shing Electronics Ltd. + +OUI:001A55* + ID_OUI_FROM_DATABASE=ACA-Digital Corporation + +OUI:001A56* + ID_OUI_FROM_DATABASE=ViewTel Co,. Ltd. + +OUI:001A57* + ID_OUI_FROM_DATABASE=Matrix Design Group, LLC + +OUI:001A58* + ID_OUI_FROM_DATABASE=CCV Deutschland GmbH - Celectronic eHealth Div. + +OUI:001A59* + ID_OUI_FROM_DATABASE=Ircona + +OUI:001A5A* + ID_OUI_FROM_DATABASE=Korea Electric Power Data Network (KDN) Co., Ltd + +OUI:001A5B* + ID_OUI_FROM_DATABASE=NetCare Service Co., Ltd. + +OUI:001A5C* + ID_OUI_FROM_DATABASE=Euchner GmbH+Co. KG + +OUI:001A5D* + ID_OUI_FROM_DATABASE=Mobinnova Corp. + +OUI:001A5E* + ID_OUI_FROM_DATABASE=Thincom Technology Co.,Ltd + +OUI:001A5F* + ID_OUI_FROM_DATABASE=KitWorks.fi Ltd. + +OUI:001A60* + ID_OUI_FROM_DATABASE=Wave Electronics Co.,Ltd. + +OUI:001A61* + ID_OUI_FROM_DATABASE=PacStar Corp. + +OUI:001A62* + ID_OUI_FROM_DATABASE=Data Robotics, Incorporated + +OUI:001A63* + ID_OUI_FROM_DATABASE=Elster Solutions, LLC, + +OUI:001A64* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:001A65* + ID_OUI_FROM_DATABASE=Seluxit + +OUI:001A66* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001A67* + ID_OUI_FROM_DATABASE=Infinite QL Sdn Bhd + +OUI:001A68* + ID_OUI_FROM_DATABASE=Weltec Enterprise Co., Ltd. + +OUI:001A69* + ID_OUI_FROM_DATABASE=Wuhan Yangtze Optical Technology CO.,Ltd. + +OUI:001A6A* + ID_OUI_FROM_DATABASE=Tranzas, Inc. + +OUI:001A6B* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:001A6C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001A6D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001A6E* + ID_OUI_FROM_DATABASE=Impro Technologies + +OUI:001A6F* + ID_OUI_FROM_DATABASE=MI.TEL s.r.l. + +OUI:001A70* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:001A71* + ID_OUI_FROM_DATABASE=Diostech Co., Ltd. + +OUI:001A72* + ID_OUI_FROM_DATABASE=Mosart Semiconductor Corp. + +OUI:001A73* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:001A74* + ID_OUI_FROM_DATABASE=Procare International Co + +OUI:001A75* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:001A76* + ID_OUI_FROM_DATABASE=SDT information Technology Co.,LTD. + +OUI:001A77* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001A78* + ID_OUI_FROM_DATABASE=ubtos + +OUI:001A79* + ID_OUI_FROM_DATABASE=TELECOMUNICATION TECHNOLOGIES LTD. + +OUI:001A7A* + ID_OUI_FROM_DATABASE=Lismore Instruments Limited + +OUI:001A7B* + ID_OUI_FROM_DATABASE=Teleco, Inc. + +OUI:001A7C* + ID_OUI_FROM_DATABASE=Hirschmann Multimedia B.V. + +OUI:001A7D* + ID_OUI_FROM_DATABASE=cyber-blue(HK)Ltd + +OUI:001A7E* + ID_OUI_FROM_DATABASE=LN Srithai Comm Ltd. + +OUI:001A7F* + ID_OUI_FROM_DATABASE=GCI Science & Technology Co.,LTD + +OUI:001A80* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:001A81* + ID_OUI_FROM_DATABASE=Zelax + +OUI:001A82* + ID_OUI_FROM_DATABASE=PROBA Building Automation Co.,LTD + +OUI:001A83* + ID_OUI_FROM_DATABASE=Pegasus Technologies Inc. + +OUI:001A84* + ID_OUI_FROM_DATABASE=V One Multimedia Pte Ltd + +OUI:001A85* + ID_OUI_FROM_DATABASE=NV Michel Van de Wiele + +OUI:001A86* + ID_OUI_FROM_DATABASE=AdvancedIO Systems Inc + +OUI:001A87* + ID_OUI_FROM_DATABASE=Canhold International Limited + +OUI:001A88* + ID_OUI_FROM_DATABASE=Venergy,Co,Ltd + +OUI:001A89* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001A8A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001A8B* + ID_OUI_FROM_DATABASE=CHUNIL ELECTRIC IND., CO. + +OUI:001A8C* + ID_OUI_FROM_DATABASE=Sophos Ltd + +OUI:001A8D* + ID_OUI_FROM_DATABASE=AVECS Bergen GmbH + +OUI:001A8E* + ID_OUI_FROM_DATABASE=3Way Networks Ltd + +OUI:001A8F* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001A90* + ID_OUI_FROM_DATABASE=Trópico Sistemas e Telecomunicações da Amazônia LTDA. + +OUI:001A91* + ID_OUI_FROM_DATABASE=FusionDynamic Ltd. + +OUI:001A92* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:001A93* + ID_OUI_FROM_DATABASE=ERCO Leuchten GmbH + +OUI:001A94* + ID_OUI_FROM_DATABASE=Votronic GmbH + +OUI:001A95* + ID_OUI_FROM_DATABASE=Hisense Mobile Communications Technoligy Co.,Ltd. + +OUI:001A96* + ID_OUI_FROM_DATABASE=ECLER S.A. + +OUI:001A97* + ID_OUI_FROM_DATABASE=fitivision technology Inc. + +OUI:001A98* + ID_OUI_FROM_DATABASE=Asotel Communication Limited Taiwan Branch + +OUI:001A99* + ID_OUI_FROM_DATABASE=Smarty (HZ) Information Electronics Co., Ltd + +OUI:001A9A* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:001A9B* + ID_OUI_FROM_DATABASE=ADEC & Parter AG + +OUI:001A9C* + ID_OUI_FROM_DATABASE=RightHand Technologies, Inc. + +OUI:001A9D* + ID_OUI_FROM_DATABASE=Skipper Wireless, Inc. + +OUI:001A9E* + ID_OUI_FROM_DATABASE=ICON Digital International Limited + +OUI:001A9F* + ID_OUI_FROM_DATABASE=A-Link Ltd + +OUI:001AA0* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:001AA1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001AA2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001AA3* + ID_OUI_FROM_DATABASE=DELORME + +OUI:001AA4* + ID_OUI_FROM_DATABASE=Future University-Hakodate + +OUI:001AA5* + ID_OUI_FROM_DATABASE=BRN Phoenix + +OUI:001AA6* + ID_OUI_FROM_DATABASE=Telefunken Radio Communication Systems GmbH &CO.KG + +OUI:001AA7* + ID_OUI_FROM_DATABASE=Torian Wireless + +OUI:001AA8* + ID_OUI_FROM_DATABASE=Mamiya Digital Imaging Co., Ltd. + +OUI:001AA9* + ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD + +OUI:001AAA* + ID_OUI_FROM_DATABASE=Analogic Corp. + +OUI:001AAB* + ID_OUI_FROM_DATABASE=eWings s.r.l. + +OUI:001AAC* + ID_OUI_FROM_DATABASE=Corelatus AB + +OUI:001AAD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001AAE* + ID_OUI_FROM_DATABASE=Savant Systems LLC + +OUI:001AAF* + ID_OUI_FROM_DATABASE=BLUSENS TECHNOLOGY + +OUI:001AB0* + ID_OUI_FROM_DATABASE=Signal Networks Pvt. Ltd., + +OUI:001AB1* + ID_OUI_FROM_DATABASE=Asia Pacific Satellite Industries Co., Ltd. + +OUI:001AB2* + ID_OUI_FROM_DATABASE=Cyber Solutions Inc. + +OUI:001AB3* + ID_OUI_FROM_DATABASE=VISIONITE INC. + +OUI:001AB4* + ID_OUI_FROM_DATABASE=FFEI Ltd. + +OUI:001AB5* + ID_OUI_FROM_DATABASE=Home Network System + +OUI:001AB6* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:001AB7* + ID_OUI_FROM_DATABASE=Ethos Networks LTD. + +OUI:001AB8* + ID_OUI_FROM_DATABASE=Anseri Corporation + +OUI:001AB9* + ID_OUI_FROM_DATABASE=PMC + +OUI:001ABA* + ID_OUI_FROM_DATABASE=Caton Overseas Limited + +OUI:001ABB* + ID_OUI_FROM_DATABASE=Fontal Technology Incorporation + +OUI:001ABC* + ID_OUI_FROM_DATABASE=U4EA Technologies Ltd + +OUI:001ABD* + ID_OUI_FROM_DATABASE=Impatica Inc. + +OUI:001ABE* + ID_OUI_FROM_DATABASE=COMPUTER HI-TECH INC. + +OUI:001ABF* + ID_OUI_FROM_DATABASE=TRUMPF Laser Marking Systems AG + +OUI:001AC0* + ID_OUI_FROM_DATABASE=JOYBIEN TECHNOLOGIES CO., LTD. + +OUI:001AC1* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:001AC2* + ID_OUI_FROM_DATABASE=YEC Co.,Ltd. + +OUI:001AC3* + ID_OUI_FROM_DATABASE=Scientific-Atlanta, Inc + +OUI:001AC4* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:001AC5* + ID_OUI_FROM_DATABASE=Keysight Technologies, Inc. + +OUI:001AC6* + ID_OUI_FROM_DATABASE=Micro Control Designs + +OUI:001AC7* + ID_OUI_FROM_DATABASE=UNIPOINT + +OUI:001AC8* + ID_OUI_FROM_DATABASE=ISL (Instrumentation Scientifique de Laboratoire) + +OUI:001AC9* + ID_OUI_FROM_DATABASE=SUZUKEN CO.,LTD + +OUI:001ACA* + ID_OUI_FROM_DATABASE=Tilera Corporation + +OUI:001ACB* + ID_OUI_FROM_DATABASE=Autocom Products Ltd + +OUI:001ACC* + ID_OUI_FROM_DATABASE=Celestial Semiconductor, Ltd + +OUI:001ACD* + ID_OUI_FROM_DATABASE=Tidel Engineering LP + +OUI:001ACE* + ID_OUI_FROM_DATABASE=YUPITERU CORPORATION + +OUI:001ACF* + ID_OUI_FROM_DATABASE=C.T. ELETTRONICA + +OUI:001AD0* + ID_OUI_FROM_DATABASE=Albis Technologies AG + +OUI:001AD1* + ID_OUI_FROM_DATABASE=FARGO CO., LTD. + +OUI:001AD2* + ID_OUI_FROM_DATABASE=Eletronica Nitron Ltda + +OUI:001AD3* + ID_OUI_FROM_DATABASE=Vamp Ltd. + +OUI:001AD4* + ID_OUI_FROM_DATABASE=iPOX Technology Co., Ltd. + +OUI:001AD5* + ID_OUI_FROM_DATABASE=KMC CHAIN INDUSTRIAL CO., LTD. + +OUI:001AD6* + ID_OUI_FROM_DATABASE=JIAGNSU AETNA ELECTRIC CO.,LTD + +OUI:001AD7* + ID_OUI_FROM_DATABASE=Christie Digital Systems, Inc. + +OUI:001AD8* + ID_OUI_FROM_DATABASE=AlsterAero GmbH + +OUI:001AD9* + ID_OUI_FROM_DATABASE=International Broadband Electric Communications, Inc. + +OUI:001ADA* + ID_OUI_FROM_DATABASE=Biz-2-Me Inc. + +OUI:001ADB* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001ADC* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001ADD* + ID_OUI_FROM_DATABASE=PePWave Ltd + +OUI:001ADE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001ADF* + ID_OUI_FROM_DATABASE=Interactivetv Pty Limited + +OUI:001AE0* + ID_OUI_FROM_DATABASE=Mythology Tech Express Inc. + +OUI:001AE1* + ID_OUI_FROM_DATABASE=EDGE ACCESS INC + +OUI:001AE2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001AE3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001AE4* + ID_OUI_FROM_DATABASE=Medicis Technologies Corporation + +OUI:001AE5* + ID_OUI_FROM_DATABASE=Mvox Technologies Inc. + +OUI:001AE6* + ID_OUI_FROM_DATABASE=Atlanta Advanced Communications Holdings Limited + +OUI:001AE7* + ID_OUI_FROM_DATABASE=Aztek Networks, Inc. + +OUI:001AE8* + ID_OUI_FROM_DATABASE=Unify Software and Solutions GmbH & Co. KG + +OUI:001AE9* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:001AEA* + ID_OUI_FROM_DATABASE=Radio Terminal Systems Pty Ltd + +OUI:001AEB* + ID_OUI_FROM_DATABASE=Allied Telesis R&D Center K.K. + +OUI:001AEC* + ID_OUI_FROM_DATABASE=Keumbee Electronics Co.,Ltd. + +OUI:001AED* + ID_OUI_FROM_DATABASE=INCOTEC GmbH + +OUI:001AEE* + ID_OUI_FROM_DATABASE=Shenztech Ltd + +OUI:001AEF* + ID_OUI_FROM_DATABASE=Loopcomm Technology, Inc. + +OUI:001AF0* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:001AF1* + ID_OUI_FROM_DATABASE=Embedded Artists AB + +OUI:001AF2* + ID_OUI_FROM_DATABASE=Dynavisions Schweiz AG + +OUI:001AF3* + ID_OUI_FROM_DATABASE=Samyoung Electronics + +OUI:001AF4* + ID_OUI_FROM_DATABASE=Handreamnet + +OUI:001AF5* + ID_OUI_FROM_DATABASE=PENTAONE. CO., LTD. + +OUI:001AF6* + ID_OUI_FROM_DATABASE=Woven Systems, Inc. + +OUI:001AF7* + ID_OUI_FROM_DATABASE=dataschalt e+a GmbH + +OUI:001AF8* + ID_OUI_FROM_DATABASE=Copley Controls Corporation + +OUI:001AF9* + ID_OUI_FROM_DATABASE=AeroVIronment (AV Inc) + +OUI:001AFA* + ID_OUI_FROM_DATABASE=Welch Allyn, Inc. + +OUI:001AFB* + ID_OUI_FROM_DATABASE=Joby Inc. + +OUI:001AFC* + ID_OUI_FROM_DATABASE=ModusLink Corporation + +OUI:001AFD* + ID_OUI_FROM_DATABASE=EVOLIS + +OUI:001AFE* + ID_OUI_FROM_DATABASE=SOFACREAL + +OUI:001AFF* + ID_OUI_FROM_DATABASE=Wizyoung Tech. + +OUI:001B00* + ID_OUI_FROM_DATABASE=Neopost Technologies + +OUI:001B01* + ID_OUI_FROM_DATABASE=Applied Radio Technologies + +OUI:001B02* + ID_OUI_FROM_DATABASE=ED Co.Ltd + +OUI:001B03* + ID_OUI_FROM_DATABASE=Action Technology (SZ) Co., Ltd + +OUI:001B04* + ID_OUI_FROM_DATABASE=Affinity International S.p.a + +OUI:001B05* + ID_OUI_FROM_DATABASE=YMC AG + +OUI:001B06* + ID_OUI_FROM_DATABASE=Ateliers R. LAUMONIER + +OUI:001B07* + ID_OUI_FROM_DATABASE=Mendocino Software + +OUI:001B08* + ID_OUI_FROM_DATABASE=Danfoss Drives A/S + +OUI:001B09* + ID_OUI_FROM_DATABASE=Matrix Telecom Pvt. Ltd. + +OUI:001B0A* + ID_OUI_FROM_DATABASE=Intelligent Distributed Controls Ltd + +OUI:001B0B* + ID_OUI_FROM_DATABASE=Phidgets Inc. + +OUI:001B0C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001B0D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001B0E* + ID_OUI_FROM_DATABASE=InoTec GmbH Organisationssysteme + +OUI:001B0F* + ID_OUI_FROM_DATABASE=Petratec + +OUI:001B10* + ID_OUI_FROM_DATABASE=ShenZhen Kang Hui Technology Co.,ltd + +OUI:001B11* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:001B12* + ID_OUI_FROM_DATABASE=Apprion + +OUI:001B13* + ID_OUI_FROM_DATABASE=Icron Technologies Corporation + +OUI:001B14* + ID_OUI_FROM_DATABASE=Carex Lighting Equipment Factory + +OUI:001B15* + ID_OUI_FROM_DATABASE=Voxtel, Inc. + +OUI:001B16* + ID_OUI_FROM_DATABASE=Celtro Ltd. + +OUI:001B17* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:001B18* + ID_OUI_FROM_DATABASE=Tsuken Electric Ind. Co.,Ltd + +OUI:001B19* + ID_OUI_FROM_DATABASE=IEEE I&M Society TC9 + +OUI:001B1A* + ID_OUI_FROM_DATABASE=e-trees Japan, Inc. + +OUI:001B1B* + ID_OUI_FROM_DATABASE=Siemens AG, + +OUI:001B1C* + ID_OUI_FROM_DATABASE=Coherent + +OUI:001B1D* + ID_OUI_FROM_DATABASE=Phoenix International Co., Ltd + +OUI:001B1E* + ID_OUI_FROM_DATABASE=HART Communication Foundation + +OUI:001B1F* + ID_OUI_FROM_DATABASE=DELTA - Danish Electronics, Light & Acoustics + +OUI:001B20* + ID_OUI_FROM_DATABASE=TPine Technology + +OUI:001B21* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001B22* + ID_OUI_FROM_DATABASE=Palit Microsystems ( H.K.) Ltd. + +OUI:001B23* + ID_OUI_FROM_DATABASE=SimpleComTools + +OUI:001B24* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:001B25* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001B26* + ID_OUI_FROM_DATABASE=RON-Telecom ZAO + +OUI:001B27* + ID_OUI_FROM_DATABASE=Merlin CSI + +OUI:001B28* + ID_OUI_FROM_DATABASE=POLYGON, JSC + +OUI:001B29* + ID_OUI_FROM_DATABASE=Avantis.Co.,Ltd + +OUI:001B2A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001B2B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001B2C* + ID_OUI_FROM_DATABASE=ATRON electronic GmbH + +OUI:001B2D* + ID_OUI_FROM_DATABASE=Med-Eng Systems Inc. + +OUI:001B2E* + ID_OUI_FROM_DATABASE=Sinkyo Electron Inc + +OUI:001B2F* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:001B30* + ID_OUI_FROM_DATABASE=Solitech Inc. + +OUI:001B31* + ID_OUI_FROM_DATABASE=Neural Image. Co. Ltd. + +OUI:001B32* + ID_OUI_FROM_DATABASE=QLogic Corporation + +OUI:001B33* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001B34* + ID_OUI_FROM_DATABASE=Focus System Inc. + +OUI:001B35* + ID_OUI_FROM_DATABASE=ChongQing JINOU Science & Technology Development CO.,Ltd + +OUI:001B36* + ID_OUI_FROM_DATABASE=Tsubata Engineering Co.,Ltd. (Head Office) + +OUI:001B37* + ID_OUI_FROM_DATABASE=Computec Oy + +OUI:001B38* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:001B39* + ID_OUI_FROM_DATABASE=Proxicast + +OUI:001B3A* + ID_OUI_FROM_DATABASE=SIMS Corp. + +OUI:001B3B* + ID_OUI_FROM_DATABASE=Yi-Qing CO., LTD + +OUI:001B3C* + ID_OUI_FROM_DATABASE=Software Technologies Group,Inc. + +OUI:001B3D* + ID_OUI_FROM_DATABASE=EuroTel Spa + +OUI:001B3E* + ID_OUI_FROM_DATABASE=Curtis, Inc. + +OUI:001B3F* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP + +OUI:001B40* + ID_OUI_FROM_DATABASE=Network Automation mxc AB + +OUI:001B41* + ID_OUI_FROM_DATABASE=General Infinity Co.,Ltd. + +OUI:001B42* + ID_OUI_FROM_DATABASE=Wise & Blue + +OUI:001B43* + ID_OUI_FROM_DATABASE=Beijing DG Telecommunications equipment Co.,Ltd + +OUI:001B44* + ID_OUI_FROM_DATABASE=SanDisk Corporation + +OUI:001B45* + ID_OUI_FROM_DATABASE=ABB AS, Division Automation Products + +OUI:001B46* + ID_OUI_FROM_DATABASE=Blueone Technology Co.,Ltd + +OUI:001B47* + ID_OUI_FROM_DATABASE=Futarque A/S + +OUI:001B48* + ID_OUI_FROM_DATABASE=Shenzhen Lantech Electronics Co., Ltd. + +OUI:001B49* + ID_OUI_FROM_DATABASE=Roberts Radio limited + +OUI:001B4A* + ID_OUI_FROM_DATABASE=W&W Communications, Inc. + +OUI:001B4B* + ID_OUI_FROM_DATABASE=SANION Co., Ltd. + +OUI:001B4C* + ID_OUI_FROM_DATABASE=Signtech + +OUI:001B4D* + ID_OUI_FROM_DATABASE=Areca Technology Corporation + +OUI:001B4E* + ID_OUI_FROM_DATABASE=Navman New Zealand + +OUI:001B4F* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:001B50* + ID_OUI_FROM_DATABASE=Nizhny Novgorod Factory named after M.Frunze, FSUE (NZiF) + +OUI:001B51* + ID_OUI_FROM_DATABASE=Vector Technology Corp. + +OUI:001B52* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001B53* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001B54* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001B55* + ID_OUI_FROM_DATABASE=Hurco Automation Ltd. + +OUI:001B56* + ID_OUI_FROM_DATABASE=Tehuti Networks Ltd. + +OUI:001B57* + ID_OUI_FROM_DATABASE=SEMINDIA SYSTEMS PRIVATE LIMITED + +OUI:001B58* + ID_OUI_FROM_DATABASE=ACE CAD Enterprise Co., Ltd. + +OUI:001B59* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:001B5A* + ID_OUI_FROM_DATABASE=Apollo Imaging Technologies, Inc. + +OUI:001B5B* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:001B5C* + ID_OUI_FROM_DATABASE=Azuretec Co., Ltd. + +OUI:001B5D* + ID_OUI_FROM_DATABASE=Vololink Pty Ltd + +OUI:001B5E* + ID_OUI_FROM_DATABASE=BPL Limited + +OUI:001B5F* + ID_OUI_FROM_DATABASE=Alien Technology + +OUI:001B60* + ID_OUI_FROM_DATABASE=NAVIGON AG + +OUI:001B61* + ID_OUI_FROM_DATABASE=Digital Acoustics, LLC + +OUI:001B62* + ID_OUI_FROM_DATABASE=JHT Optoelectronics Co.,Ltd. + +OUI:001B63* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001B64* + ID_OUI_FROM_DATABASE=IsaacLandKorea Co., Ltd, + +OUI:001B65* + ID_OUI_FROM_DATABASE=China Gridcom Co., Ltd + +OUI:001B66* + ID_OUI_FROM_DATABASE=Sennheiser electronic GmbH & Co. KG + +OUI:001B67* + ID_OUI_FROM_DATABASE=Cisco Systems Inc + +OUI:001B68* + ID_OUI_FROM_DATABASE=Modnnet Co., Ltd + +OUI:001B69* + ID_OUI_FROM_DATABASE=Equaline Corporation + +OUI:001B6A* + ID_OUI_FROM_DATABASE=Powerwave Technologies Sweden AB + +OUI:001B6B* + ID_OUI_FROM_DATABASE=Swyx Solutions AG + +OUI:001B6C* + ID_OUI_FROM_DATABASE=LookX Digital Media BV + +OUI:001B6D* + ID_OUI_FROM_DATABASE=Midtronics, Inc. + +OUI:001B6E* + ID_OUI_FROM_DATABASE=Keysight Technologies, Inc. + +OUI:001B6F* + ID_OUI_FROM_DATABASE=Teletrak Ltd + +OUI:001B70* + ID_OUI_FROM_DATABASE=IRI Ubiteq, INC. + +OUI:001B71* + ID_OUI_FROM_DATABASE=Telular Corp. + +OUI:001B72* + ID_OUI_FROM_DATABASE=Sicep s.p.a. + +OUI:001B73* + ID_OUI_FROM_DATABASE=DTL Broadcast Ltd + +OUI:001B74* + ID_OUI_FROM_DATABASE=MiraLink Corporation + +OUI:001B75* + ID_OUI_FROM_DATABASE=Hypermedia Systems + +OUI:001B76* + ID_OUI_FROM_DATABASE=Ripcode, Inc. + +OUI:001B77* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001B78* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001B79* + ID_OUI_FROM_DATABASE=FAIVELEY TRANSPORT + +OUI:001B7A* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:001B7B* + ID_OUI_FROM_DATABASE=The Tintometer Ltd + +OUI:001B7C* + ID_OUI_FROM_DATABASE=A & R Cambridge + +OUI:001B7D* + ID_OUI_FROM_DATABASE=CXR Anderson Jacobson + +OUI:001B7E* + ID_OUI_FROM_DATABASE=Beckmann GmbH + +OUI:001B7F* + ID_OUI_FROM_DATABASE=TMN Technologies Telecomunicacoes Ltda + +OUI:001B80* + ID_OUI_FROM_DATABASE=LORD Corporation + +OUI:001B81* + ID_OUI_FROM_DATABASE=DATAQ Instruments, Inc. + +OUI:001B82* + ID_OUI_FROM_DATABASE=Taiwan Semiconductor Co., Ltd. + +OUI:001B83* + ID_OUI_FROM_DATABASE=Finsoft Ltd + +OUI:001B84* + ID_OUI_FROM_DATABASE=Scan Engineering Telecom + +OUI:001B85* + ID_OUI_FROM_DATABASE=MAN Energy Solutions + +OUI:001B86* + ID_OUI_FROM_DATABASE=Bosch Access Systems GmbH + +OUI:001B87* + ID_OUI_FROM_DATABASE=Deepsound Tech. Co., Ltd + +OUI:001B88* + ID_OUI_FROM_DATABASE=Divinet Access Technologies Ltd + +OUI:001B89* + ID_OUI_FROM_DATABASE=EMZA Visual Sense Ltd. + +OUI:001B8A* + ID_OUI_FROM_DATABASE=2M Electronic A/S + +OUI:001B8B* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. + +OUI:001B8C* + ID_OUI_FROM_DATABASE=JMicron Technology Corp. + +OUI:001B8D* + ID_OUI_FROM_DATABASE=Electronic Computer Systems, Inc. + +OUI:001B8E* + ID_OUI_FROM_DATABASE=Hulu Sweden AB + +OUI:001B8F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001B90* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001B91* + ID_OUI_FROM_DATABASE=EFKON AG + +OUI:001B92* + ID_OUI_FROM_DATABASE=l-acoustics + +OUI:001B93* + ID_OUI_FROM_DATABASE=JC Decaux SA DNT + +OUI:001B94* + ID_OUI_FROM_DATABASE=T.E.M.A. S.p.A. + +OUI:001B95* + ID_OUI_FROM_DATABASE=VIDEO SYSTEMS SRL + +OUI:001B96* + ID_OUI_FROM_DATABASE=General Sensing + +OUI:001B97* + ID_OUI_FROM_DATABASE=Violin Technologies + +OUI:001B98* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001B99* + ID_OUI_FROM_DATABASE=KS System GmbH + +OUI:001B9A* + ID_OUI_FROM_DATABASE=Apollo Fire Detectors Ltd + +OUI:001B9B* + ID_OUI_FROM_DATABASE=Hose-McCann Communications + +OUI:001B9C* + ID_OUI_FROM_DATABASE=SATEL sp. z o.o. + +OUI:001B9D* + ID_OUI_FROM_DATABASE=Novus Security Sp. z o.o. + +OUI:001B9E* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:001B9F* + ID_OUI_FROM_DATABASE=Calyptech Pty Ltd + +OUI:001BA0* + ID_OUI_FROM_DATABASE=Awox + +OUI:001BA1* + ID_OUI_FROM_DATABASE=Åmic AB + +OUI:001BA2* + ID_OUI_FROM_DATABASE=IDS Imaging Development Systems GmbH + +OUI:001BA3* + ID_OUI_FROM_DATABASE=Flexit Group GmbH + +OUI:001BA4* + ID_OUI_FROM_DATABASE=S.A.E Afikim + +OUI:001BA5* + ID_OUI_FROM_DATABASE=MyungMin Systems, Inc. + +OUI:001BA6* + ID_OUI_FROM_DATABASE=intotech inc. + +OUI:001BA7* + ID_OUI_FROM_DATABASE=Lorica Solutions + +OUI:001BA8* + ID_OUI_FROM_DATABASE=UBI&MOBI,.Inc + +OUI:001BA9* + ID_OUI_FROM_DATABASE=Brother industries, LTD. + +OUI:001BAA* + ID_OUI_FROM_DATABASE=XenICs nv + +OUI:001BAB* + ID_OUI_FROM_DATABASE=Telchemy, Incorporated + +OUI:001BAC* + ID_OUI_FROM_DATABASE=Curtiss Wright Controls Embedded Computing + +OUI:001BAD* + ID_OUI_FROM_DATABASE=iControl Incorporated + +OUI:001BAE* + ID_OUI_FROM_DATABASE=Micro Control Systems, Inc + +OUI:001BAF* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001BB0* + ID_OUI_FROM_DATABASE=Bharat Electronics Limited + +OUI:001BB1* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:001BB2* + ID_OUI_FROM_DATABASE=Intellect International NV + +OUI:001BB3* + ID_OUI_FROM_DATABASE=Condalo GmbH + +OUI:001BB4* + ID_OUI_FROM_DATABASE=Airvod Limited + +OUI:001BB5* + ID_OUI_FROM_DATABASE=Cherry GmbH + +OUI:001BB6* + ID_OUI_FROM_DATABASE=Bird Electronic Corp. + +OUI:001BB7* + ID_OUI_FROM_DATABASE=Alta Heights Technology Corp. + +OUI:001BB8* + ID_OUI_FROM_DATABASE=BLUEWAY ELECTRONIC CO;LTD + +OUI:001BB9* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:001BBA* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001BBB* + ID_OUI_FROM_DATABASE=RFTech Co.,Ltd + +OUI:001BBC* + ID_OUI_FROM_DATABASE=Silver Peak Systems, Inc. + +OUI:001BBD* + ID_OUI_FROM_DATABASE=FMC Kongsberg Subsea AS + +OUI:001BBE* + ID_OUI_FROM_DATABASE=ICOP Digital + +OUI:001BBF* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:001BC0* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:001BC1* + ID_OUI_FROM_DATABASE=HOLUX Technology, Inc. + +OUI:001BC2* + ID_OUI_FROM_DATABASE=Integrated Control Technology Limitied + +OUI:001BC3* + ID_OUI_FROM_DATABASE=Mobisolution Co.,Ltd + +OUI:001BC4* + ID_OUI_FROM_DATABASE=Ultratec, Inc. + +OUI:001BC5000* + ID_OUI_FROM_DATABASE=Converging Systems Inc. + +OUI:001BC5001* + ID_OUI_FROM_DATABASE=OpenRB.com, Direct SIA + +OUI:001BC5002* + ID_OUI_FROM_DATABASE=GORAMO - Janusz Gorecki + +OUI:001BC5003* + ID_OUI_FROM_DATABASE=MicroSigns Technologies Inc + +OUI:001BC5004* + ID_OUI_FROM_DATABASE=Intellvisions Software Ltd + +OUI:001BC5005* + ID_OUI_FROM_DATABASE=Private + +OUI:001BC5006* + ID_OUI_FROM_DATABASE=TRIAX-HIRSCHMANN Multi-Media GmbH + +OUI:001BC5007* + ID_OUI_FROM_DATABASE=Energy Aware Technology + +OUI:001BC5008* + ID_OUI_FROM_DATABASE=Dalaj Electro-Telecom + +OUI:001BC5009* + ID_OUI_FROM_DATABASE=Solomon Systech Pte Ltd + +OUI:001BC500A* + ID_OUI_FROM_DATABASE=Mercury HMI Ltd + +OUI:001BC500B* + ID_OUI_FROM_DATABASE=Private + +OUI:001BC500C* + ID_OUI_FROM_DATABASE=Quantum Technology Sciences, Inc. + +OUI:001BC500D* + ID_OUI_FROM_DATABASE=Advanced Scientific Concepts, Inc. + +OUI:001BC500E* + ID_OUI_FROM_DATABASE=Vigor Electric Corp + +OUI:001BC500F* + ID_OUI_FROM_DATABASE=Simavita Pty Ltd + +OUI:001BC5010* + ID_OUI_FROM_DATABASE=Softel SA de CV + +OUI:001BC5011* + ID_OUI_FROM_DATABASE=OOO NPP Mera + +OUI:001BC5012* + ID_OUI_FROM_DATABASE=Tokyo Cosmos Electric, Inc. + +OUI:001BC5013* + ID_OUI_FROM_DATABASE=Zamir Recognition Systems Ltd. + +OUI:001BC5014* + ID_OUI_FROM_DATABASE=Private + +OUI:001BC5015* + ID_OUI_FROM_DATABASE=Corporate Systems Engineering + +OUI:001BC5016* + ID_OUI_FROM_DATABASE=Energotechnica OOO NPP Ltd + +OUI:001BC5017* + ID_OUI_FROM_DATABASE=cPacket Networks + +OUI:001BC5019* + ID_OUI_FROM_DATABASE=Dunlop Systems & Components + +OUI:001BC501A* + ID_OUI_FROM_DATABASE=ABA ELECTRONICS TECHNOLOGY CO.,LTD + +OUI:001BC501B* + ID_OUI_FROM_DATABASE=Commonwealth Scientific and Industrial Research Organisation + +OUI:001BC501C* + ID_OUI_FROM_DATABASE=Coolit Systems, Inc. + +OUI:001BC501D* + ID_OUI_FROM_DATABASE=Rose + Herleth GbR + +OUI:001BC501E* + ID_OUI_FROM_DATABASE=Private + +OUI:001BC501F* + ID_OUI_FROM_DATABASE=Saturn Solutions Ltd + +OUI:001BC5020* + ID_OUI_FROM_DATABASE=Momentum Data Systems + +OUI:001BC5021* + ID_OUI_FROM_DATABASE=Openpeak, Inc + +OUI:001BC5022* + ID_OUI_FROM_DATABASE=CJSC STC SIMOS + +OUI:001BC5023* + ID_OUI_FROM_DATABASE=MAGO di Della Mora Walter + +OUI:001BC5024* + ID_OUI_FROM_DATABASE=ANNECY ELECTRONIQUE SAS + +OUI:001BC5025* + ID_OUI_FROM_DATABASE=andersen lighting GmbH + +OUI:001BC5026* + ID_OUI_FROM_DATABASE=DIMEP Sistemas + +OUI:001BC5027* + ID_OUI_FROM_DATABASE=CAMEA, spol. s r.o. + +OUI:001BC5028* + ID_OUI_FROM_DATABASE=STECHWIN.CO.LTD. + +OUI:001BC5029* + ID_OUI_FROM_DATABASE=2 FRANCE MARINE + +OUI:001BC502A* + ID_OUI_FROM_DATABASE=Analytical Instrument Systems, Inc. + +OUI:001BC502B* + ID_OUI_FROM_DATABASE=Saturn South Pty Ltd + +OUI:001BC502C* + ID_OUI_FROM_DATABASE=Care Everywhere LLC + +OUI:001BC502D* + ID_OUI_FROM_DATABASE=DDTRONIK Dariusz Dowgiert + +OUI:001BC502E* + ID_OUI_FROM_DATABASE=BETTINI SRL + +OUI:001BC502F* + ID_OUI_FROM_DATABASE=Fibrain Co. Ltd. + +OUI:001BC5030* + ID_OUI_FROM_DATABASE=OctoGate it Security Systems GmbH + +OUI:001BC5031* + ID_OUI_FROM_DATABASE=ADIXEIN LIMITED + +OUI:001BC5032* + ID_OUI_FROM_DATABASE=Osborne Coinage Co + +OUI:001BC5033* + ID_OUI_FROM_DATABASE=JE Suunnittelu Oy + +OUI:001BC5034* + ID_OUI_FROM_DATABASE=InterCEL Pty Ltd + +OUI:001BC5035* + ID_OUI_FROM_DATABASE=RTLS Ltd. + +OUI:001BC5036* + ID_OUI_FROM_DATABASE=LOMAR SRL + +OUI:001BC5037* + ID_OUI_FROM_DATABASE=ITW Reyflex North America + +OUI:001BC5038* + ID_OUI_FROM_DATABASE=SEED International Ltd. + +OUI:001BC5039* + ID_OUI_FROM_DATABASE=EURESYS S.A. + +OUI:001BC503A* + ID_OUI_FROM_DATABASE=MindMade Sp. z o.o. + +OUI:001BC503B* + ID_OUI_FROM_DATABASE=Promixis, LLC + +OUI:001BC503C* + ID_OUI_FROM_DATABASE=Xiphos Systems Corp. + +OUI:001BC503D* + ID_OUI_FROM_DATABASE=rioxo GmbH + +OUI:001BC503E* + ID_OUI_FROM_DATABASE=Daylight Solutions, Inc + +OUI:001BC503F* + ID_OUI_FROM_DATABASE=ELTRADE Ltd + +OUI:001BC5040* + ID_OUI_FROM_DATABASE=OOO Actidata + +OUI:001BC5041* + ID_OUI_FROM_DATABASE=DesignA Electronics Limited + +OUI:001BC5042* + ID_OUI_FROM_DATABASE=ChamSys Ltd + +OUI:001BC5043* + ID_OUI_FROM_DATABASE=Coincident, Inc. + +OUI:001BC5044* + ID_OUI_FROM_DATABASE=ZAO "RADIUS Avtomatika" + +OUI:001BC5045* + ID_OUI_FROM_DATABASE=Marvel Digital International Limited + +OUI:001BC5046* + ID_OUI_FROM_DATABASE=GÉANT + +OUI:001BC5047* + ID_OUI_FROM_DATABASE=PT. Amanindo Nusapadu + +OUI:001BC5048* + ID_OUI_FROM_DATABASE=XPossible Technologies Pte Ltd + +OUI:001BC5049* + ID_OUI_FROM_DATABASE=EUROCONTROL S.p.A. + +OUI:001BC504A* + ID_OUI_FROM_DATABASE=Certis Technology International Pte Ltd + +OUI:001BC504B* + ID_OUI_FROM_DATABASE=Silicon Controls + +OUI:001BC504C* + ID_OUI_FROM_DATABASE=Rhino Controls Ltd. + +OUI:001BC504D* + ID_OUI_FROM_DATABASE=eiraku electric corp. + +OUI:001BC504E* + ID_OUI_FROM_DATABASE=Mitsubishi Electric India PVT. LTD + +OUI:001BC504F* + ID_OUI_FROM_DATABASE=Orbital Systems, Ltd. + +OUI:001BC5050* + ID_OUI_FROM_DATABASE=TeliSwitch Solutions + +OUI:001BC5051* + ID_OUI_FROM_DATABASE=QQ Navigation AB + +OUI:001BC5052* + ID_OUI_FROM_DATABASE=Engineering Center ENERGOSERVICE + +OUI:001BC5053* + ID_OUI_FROM_DATABASE=Metrycom Communications Ltd + +OUI:001BC5054* + ID_OUI_FROM_DATABASE=Private + +OUI:001BC5055* + ID_OUI_FROM_DATABASE=LUMIPLAN TRANSPORT + +OUI:001BC5056* + ID_OUI_FROM_DATABASE=ThinKom Solutions, Inc + +OUI:001BC5057* + ID_OUI_FROM_DATABASE=EREE Electronique + +OUI:001BC5058* + ID_OUI_FROM_DATABASE=optiMEAS GmbH + +OUI:001BC5059* + ID_OUI_FROM_DATABASE=INPIXAL + +OUI:001BC505A* + ID_OUI_FROM_DATABASE=POSTEC DATA SYSTEMS + +OUI:001BC505B* + ID_OUI_FROM_DATABASE=konzeptpark GmbH + +OUI:001BC505C* + ID_OUI_FROM_DATABASE=Suretrak Global Pty Ltd + +OUI:001BC505D* + ID_OUI_FROM_DATABASE=JSC Prominform + +OUI:001BC505E* + ID_OUI_FROM_DATABASE=Ecomed-Complex + +OUI:001BC505F* + ID_OUI_FROM_DATABASE=Klingenthaler Musikelektronik GmbH + +OUI:001BC5060* + ID_OUI_FROM_DATABASE=ENSTECH + +OUI:001BC5061* + ID_OUI_FROM_DATABASE=Scientific-Technical Center Epsilon Limited company + +OUI:001BC5062* + ID_OUI_FROM_DATABASE=Sulaon Oy + +OUI:001BC5063* + ID_OUI_FROM_DATABASE=Check-It Solutions Inc + +OUI:001BC5064* + ID_OUI_FROM_DATABASE=Enkora Oy Ltd + +OUI:001BC5065* + ID_OUI_FROM_DATABASE=Plair Media Inc. + +OUI:001BC5066* + ID_OUI_FROM_DATABASE=Manufacturas y transformados AB + +OUI:001BC5067* + ID_OUI_FROM_DATABASE=Embit srl + +OUI:001BC5068* + ID_OUI_FROM_DATABASE=HCS KABLOLAMA SISTEMLERI SAN. ve TIC.A.S. + +OUI:001BC5069* + ID_OUI_FROM_DATABASE=Datasat Digital Entertainment + +OUI:001BC506A* + ID_OUI_FROM_DATABASE=IST GmbH + +OUI:001BC506B* + ID_OUI_FROM_DATABASE=Verified Energy, LLC. + +OUI:001BC506C* + ID_OUI_FROM_DATABASE=Luxcon System Limited + +OUI:001BC506D* + ID_OUI_FROM_DATABASE=TES Electronic Solutions (I) Pvt. Ltd. + +OUI:001BC506E* + ID_OUI_FROM_DATABASE=Two Dimensional Instruments, LLC + +OUI:001BC506F* + ID_OUI_FROM_DATABASE=LLC Emzior + +OUI:001BC5070* + ID_OUI_FROM_DATABASE=Siemens Industries, Inc, Retail & Commercial Systems + +OUI:001BC5071* + ID_OUI_FROM_DATABASE=Center for E-Commerce Infrastructure Development, The University of Hong Kong + +OUI:001BC5072* + ID_OUI_FROM_DATABASE=Ohio Semitronics, Inc. + +OUI:001BC5073* + ID_OUI_FROM_DATABASE=tado GmbH + +OUI:001BC5074* + ID_OUI_FROM_DATABASE=Dynasthetics + +OUI:001BC5075* + ID_OUI_FROM_DATABASE=Kitron GmbH + +OUI:001BC5076* + ID_OUI_FROM_DATABASE=PLAiR Media, Inc + +OUI:001BC5077* + ID_OUI_FROM_DATABASE=Momentum Data Systems + +OUI:001BC5078* + ID_OUI_FROM_DATABASE=Donbass Soft Ltd and Co.KG + +OUI:001BC5079* + ID_OUI_FROM_DATABASE=HPI High Pressure Instrumentation GmbH + +OUI:001BC507A* + ID_OUI_FROM_DATABASE=Servicios Electronicos Industriales Berbel s.l. + +OUI:001BC507B* + ID_OUI_FROM_DATABASE=QCORE Medical + +OUI:001BC507C* + ID_OUI_FROM_DATABASE=head + +OUI:001BC507D* + ID_OUI_FROM_DATABASE=Greatcom AG + +OUI:001BC507E* + ID_OUI_FROM_DATABASE=Bio Molecular System Pty Ltd + +OUI:001BC507F* + ID_OUI_FROM_DATABASE=Hitechlab Inc + +OUI:001BC5080* + ID_OUI_FROM_DATABASE=LUMINO GmbH + +OUI:001BC5081* + ID_OUI_FROM_DATABASE=WonATech Co., Ltd. + +OUI:001BC5082* + ID_OUI_FROM_DATABASE=TGS Geophysical Company (UK) Limited + +OUI:001BC5083* + ID_OUI_FROM_DATABASE=DIWEL + +OUI:001BC5084* + ID_OUI_FROM_DATABASE=Applied Innovations Research LLC + +OUI:001BC5085* + ID_OUI_FROM_DATABASE=Oberon microsystems, Inc. + +OUI:001BC5086* + ID_OUI_FROM_DATABASE=CAST Group of Companies Inc. + +OUI:001BC5087* + ID_OUI_FROM_DATABASE=Onnet Technologies and Innovations LLC + +OUI:001BC5088* + ID_OUI_FROM_DATABASE=UAB Kitron + +OUI:001BC5089* + ID_OUI_FROM_DATABASE=SIGNATURE CONTROL SYSTEMS, INC. + +OUI:001BC508A* + ID_OUI_FROM_DATABASE=Topicon + +OUI:001BC508B* + ID_OUI_FROM_DATABASE=Nistica + +OUI:001BC508C* + ID_OUI_FROM_DATABASE=Triax A/S + +OUI:001BC508D* + ID_OUI_FROM_DATABASE=EUREK SRL + +OUI:001BC508E* + ID_OUI_FROM_DATABASE=TrendPoint Systems + +OUI:001BC508F* + ID_OUI_FROM_DATABASE=Unilever R&D + +OUI:001BC5090* + ID_OUI_FROM_DATABASE=Seven Solutions S.L + +OUI:001BC5091* + ID_OUI_FROM_DATABASE=3green ApS + +OUI:001BC5092* + ID_OUI_FROM_DATABASE=Arnouse Digital Devices, Corp. + +OUI:001BC5093* + ID_OUI_FROM_DATABASE=Ambient Devices, Inc. + +OUI:001BC5094* + ID_OUI_FROM_DATABASE=reelyActive + +OUI:001BC5095* + ID_OUI_FROM_DATABASE=PREVAC sp. z o.o. + +OUI:001BC5096* + ID_OUI_FROM_DATABASE=Sanstreak Corp. + +OUI:001BC5097* + ID_OUI_FROM_DATABASE=Plexstar Inc. + +OUI:001BC5098* + ID_OUI_FROM_DATABASE=Cubic Systems, Inc. + +OUI:001BC5099* + ID_OUI_FROM_DATABASE=UAB Kitron + +OUI:001BC509A* + ID_OUI_FROM_DATABASE=Shenzhen Guang Lian Zhi Tong Limited + +OUI:001BC509B* + ID_OUI_FROM_DATABASE=YIK Corporation + +OUI:001BC509C* + ID_OUI_FROM_DATABASE=S.I.C.E.S. srl + +OUI:001BC509D* + ID_OUI_FROM_DATABASE=Navitar Inc + +OUI:001BC509E* + ID_OUI_FROM_DATABASE=K+K Messtechnik GmbH + +OUI:001BC509F* + ID_OUI_FROM_DATABASE=ENTE Sp. z o.o. + +OUI:001BC50A0* + ID_OUI_FROM_DATABASE=HomerSoft sp. z o.o. + +OUI:001BC50A1* + ID_OUI_FROM_DATABASE=Hangzhou Zhiping Technology Co., Ltd. + +OUI:001BC50A2* + ID_OUI_FROM_DATABASE=Hettich Benelux + +OUI:001BC50A3* + ID_OUI_FROM_DATABASE=P A Network Laboratory Co.,Ltd + +OUI:001BC50A4* + ID_OUI_FROM_DATABASE=RADMOR S.A. + +OUI:001BC50A5* + ID_OUI_FROM_DATABASE=Tesla Controls + +OUI:001BC50A6* + ID_OUI_FROM_DATABASE=Balter Security GmbH + +OUI:001BC50A7* + ID_OUI_FROM_DATABASE=L.G.L. Electronics S.p.a. + +OUI:001BC50A8* + ID_OUI_FROM_DATABASE=Link Precision + +OUI:001BC50A9* + ID_OUI_FROM_DATABASE=Elektrometal SA + +OUI:001BC50AA* + ID_OUI_FROM_DATABASE=Senceive Ltd + +OUI:001BC50AB* + ID_OUI_FROM_DATABASE=Evondos Oy + +OUI:001BC50AC* + ID_OUI_FROM_DATABASE=AVnu Alliance + +OUI:001BC50AD* + ID_OUI_FROM_DATABASE=Tierra Japan Co.,Ltd + +OUI:001BC50AE* + ID_OUI_FROM_DATABASE=Techlan Reti s.r.l. + +OUI:001BC50AF* + ID_OUI_FROM_DATABASE=Enerwise Solutions Ltd. + +OUI:001BC50B0* + ID_OUI_FROM_DATABASE=J-D.COM + +OUI:001BC50B1* + ID_OUI_FROM_DATABASE=Roslen Eco-Networking Products + +OUI:001BC50B2* + ID_OUI_FROM_DATABASE=SKODA ELECTRIC a.s. + +OUI:001BC50B3* + ID_OUI_FROM_DATABASE=FSM Solutions Limited + +OUI:001BC50B4* + ID_OUI_FROM_DATABASE=COBAN SRL + +OUI:001BC50B5* + ID_OUI_FROM_DATABASE=Exibea AB + +OUI:001BC50B6* + ID_OUI_FROM_DATABASE=VEILUX INC. + +OUI:001BC50B7* + ID_OUI_FROM_DATABASE=Autelis, LLC + +OUI:001BC50B8* + ID_OUI_FROM_DATABASE=Private + +OUI:001BC50B9* + ID_OUI_FROM_DATABASE=Denki Kogyo Company, Limited + +OUI:001BC50BA* + ID_OUI_FROM_DATABASE=NT MICROSYSTEMS + +OUI:001BC50BB* + ID_OUI_FROM_DATABASE=Triax A/S + +OUI:001BC50BC* + ID_OUI_FROM_DATABASE=kuwatec, Inc. + +OUI:001BC50BD* + ID_OUI_FROM_DATABASE=Bridge Diagnostics, Inc. + +OUI:001BC50BE* + ID_OUI_FROM_DATABASE=YESpay International Ltd + +OUI:001BC50BF* + ID_OUI_FROM_DATABASE=TN Core Co.,Ltd. + +OUI:001BC50C0* + ID_OUI_FROM_DATABASE=Digital Loggers, Inc. + +OUI:001BC50C1* + ID_OUI_FROM_DATABASE=EREE Electronique + +OUI:001BC50C2* + ID_OUI_FROM_DATABASE=TechSolutions A/S + +OUI:001BC50C3* + ID_OUI_FROM_DATABASE=inomatic GmbH + +OUI:001BC50C4* + ID_OUI_FROM_DATABASE=ELDES + +OUI:001BC50C5* + ID_OUI_FROM_DATABASE=Gill Instruments Ltd + +OUI:001BC50C6* + ID_OUI_FROM_DATABASE=Connode + +OUI:001BC50C7* + ID_OUI_FROM_DATABASE=WIZZILAB SAS + +OUI:001BC50C8* + ID_OUI_FROM_DATABASE=Dialine + +OUI:001BC50C9* + ID_OUI_FROM_DATABASE=UAB Kitron + +OUI:001BC6* + ID_OUI_FROM_DATABASE=Strato Rechenzentrum AG + +OUI:001BC7* + ID_OUI_FROM_DATABASE=StarVedia Technology Inc. + +OUI:001BC8* + ID_OUI_FROM_DATABASE=MIURA CO.,LTD + +OUI:001BC9* + ID_OUI_FROM_DATABASE=FSN DISPLAY INC + +OUI:001BCA* + ID_OUI_FROM_DATABASE=Beijing Run Technology LTD. Company + +OUI:001BCB* + ID_OUI_FROM_DATABASE=PEMPEK SYSTEMS PTY LTD + +OUI:001BCC* + ID_OUI_FROM_DATABASE=KINGTEK CCTV ALLIANCE CO., LTD. + +OUI:001BCD* + ID_OUI_FROM_DATABASE=DAVISCOMMS (S) PTE LTD + +OUI:001BCE* + ID_OUI_FROM_DATABASE=Measurement Devices Ltd + +OUI:001BCF* + ID_OUI_FROM_DATABASE=Dataupia Corporation + +OUI:001BD0* + ID_OUI_FROM_DATABASE=IDENTEC SOLUTIONS + +OUI:001BD1* + ID_OUI_FROM_DATABASE=SOGESTMATIC + +OUI:001BD2* + ID_OUI_FROM_DATABASE=ULTRA-X ASIA PACIFIC Inc. + +OUI:001BD3* + ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company + +OUI:001BD4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001BD5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001BD6* + ID_OUI_FROM_DATABASE=Kelvin Hughes Ltd + +OUI:001BD7* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:001BD8* + ID_OUI_FROM_DATABASE=FLIR Systems Inc + +OUI:001BD9* + ID_OUI_FROM_DATABASE=Edgewater Wireless Systems Inc + +OUI:001BDA* + ID_OUI_FROM_DATABASE=UTStarcom Inc + +OUI:001BDB* + ID_OUI_FROM_DATABASE=Valeo VECS + +OUI:001BDC* + ID_OUI_FROM_DATABASE=Vencer Co., Ltd. + +OUI:001BDD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001BDE* + ID_OUI_FROM_DATABASE=Renkus-Heinz, Inc. + +OUI:001BDF* + ID_OUI_FROM_DATABASE=Iskra Sistemi d.d. + +OUI:001BE0* + ID_OUI_FROM_DATABASE=TELENOT ELECTRONIC GmbH + +OUI:001BE1* + ID_OUI_FROM_DATABASE=ViaLogy + +OUI:001BE2* + ID_OUI_FROM_DATABASE=AhnLab,Inc. + +OUI:001BE3* + ID_OUI_FROM_DATABASE=Health Hero Network, Inc. + +OUI:001BE4* + ID_OUI_FROM_DATABASE=TOWNET SRL + +OUI:001BE5* + ID_OUI_FROM_DATABASE=802automation Limited + +OUI:001BE6* + ID_OUI_FROM_DATABASE=VR AG + +OUI:001BE7* + ID_OUI_FROM_DATABASE=Postek Electronics Co., Ltd. + +OUI:001BE8* + ID_OUI_FROM_DATABASE=Ultratronik GmbH + +OUI:001BE9* + ID_OUI_FROM_DATABASE=Broadcom + +OUI:001BEA* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:001BEB* + ID_OUI_FROM_DATABASE=DMP Electronics INC. + +OUI:001BEC* + ID_OUI_FROM_DATABASE=Netio Technologies Co., Ltd + +OUI:001BED* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:001BEE* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001BEF* + ID_OUI_FROM_DATABASE=Blossoms Digital Technology Co.,Ltd. + +OUI:001BF0* + ID_OUI_FROM_DATABASE=Value Platforms Limited + +OUI:001BF1* + ID_OUI_FROM_DATABASE=Nanjing SilverNet Software Co., Ltd. + +OUI:001BF2* + ID_OUI_FROM_DATABASE=KWORLD COMPUTER CO., LTD + +OUI:001BF3* + ID_OUI_FROM_DATABASE=TRANSRADIO SenderSysteme Berlin AG + +OUI:001BF4* + ID_OUI_FROM_DATABASE=KENWIN INDUSTRIAL(HK) LTD. + +OUI:001BF5* + ID_OUI_FROM_DATABASE=Tellink Sistemas de Telecomunicación S.L. + +OUI:001BF6* + ID_OUI_FROM_DATABASE=CONWISE Technology Corporation Ltd. + +OUI:001BF7* + ID_OUI_FROM_DATABASE=Lund IP Products AB + +OUI:001BF8* + ID_OUI_FROM_DATABASE=Digitrax Inc. + +OUI:001BF9* + ID_OUI_FROM_DATABASE=Intellitect Water Ltd + +OUI:001BFA* + ID_OUI_FROM_DATABASE=G.i.N. mbH + +OUI:001BFB* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:001BFC* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:001BFD* + ID_OUI_FROM_DATABASE=Dignsys Inc. + +OUI:001BFE* + ID_OUI_FROM_DATABASE=Zavio Inc. + +OUI:001BFF* + ID_OUI_FROM_DATABASE=Millennia Media inc. + +OUI:001C00* + ID_OUI_FROM_DATABASE=Entry Point, LLC + +OUI:001C01* + ID_OUI_FROM_DATABASE=ABB Oy Drives + +OUI:001C02* + ID_OUI_FROM_DATABASE=Pano Logic + +OUI:001C03* + ID_OUI_FROM_DATABASE=Betty TV Technology AG + +OUI:001C04* + ID_OUI_FROM_DATABASE=Airgain, Inc. + +OUI:001C05* + ID_OUI_FROM_DATABASE=Nonin Medical Inc. + +OUI:001C06* + ID_OUI_FROM_DATABASE=Siemens Numerical Control Ltd., Nanjing + +OUI:001C07* + ID_OUI_FROM_DATABASE=Cwlinux Limited + +OUI:001C08* + ID_OUI_FROM_DATABASE=Echo360, Inc. + +OUI:001C09* + ID_OUI_FROM_DATABASE=SAE Electronic Co.,Ltd. + +OUI:001C0A* + ID_OUI_FROM_DATABASE=Shenzhen AEE Technology Co.,Ltd. + +OUI:001C0B* + ID_OUI_FROM_DATABASE=SmartAnt Telecom + +OUI:001C0C* + ID_OUI_FROM_DATABASE=TANITA Corporation + +OUI:001C0D* + ID_OUI_FROM_DATABASE=G-Technology, Inc. + +OUI:001C0E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001C0F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001C10* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:001C11* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001C12* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001C13* + ID_OUI_FROM_DATABASE=OPTSYS TECHNOLOGY CO., LTD. + +OUI:001C14* + ID_OUI_FROM_DATABASE=VMware, Inc. + +OUI:001C15* + ID_OUI_FROM_DATABASE=iPhotonix LLC + +OUI:001C16* + ID_OUI_FROM_DATABASE=ThyssenKrupp Elevator + +OUI:001C17* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001C18* + ID_OUI_FROM_DATABASE=Sicert S.r.L. + +OUI:001C19* + ID_OUI_FROM_DATABASE=secunet Security Networks AG + +OUI:001C1A* + ID_OUI_FROM_DATABASE=Thomas Instrumentation, Inc + +OUI:001C1B* + ID_OUI_FROM_DATABASE=Hyperstone GmbH + +OUI:001C1C* + ID_OUI_FROM_DATABASE=Center Communication Systems GmbH + +OUI:001C1D* + ID_OUI_FROM_DATABASE=CHENZHOU GOSPELL DIGITAL TECHNOLOGY CO.,LTD + +OUI:001C1E* + ID_OUI_FROM_DATABASE=emtrion GmbH + +OUI:001C1F* + ID_OUI_FROM_DATABASE=Quest Retail Technology Pty Ltd + +OUI:001C20* + ID_OUI_FROM_DATABASE=CLB Benelux + +OUI:001C21* + ID_OUI_FROM_DATABASE=Nucsafe Inc. + +OUI:001C22* + ID_OUI_FROM_DATABASE=Aeris Elettronica s.r.l. + +OUI:001C23* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:001C24* + ID_OUI_FROM_DATABASE=Formosa Wireless Systems Corp. + +OUI:001C25* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:001C26* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:001C27* + ID_OUI_FROM_DATABASE=Sunell Electronics Co. + +OUI:001C28* + ID_OUI_FROM_DATABASE=Sphairon Technologies GmbH + +OUI:001C29* + ID_OUI_FROM_DATABASE=CORE DIGITAL ELECTRONICS CO., LTD + +OUI:001C2A* + ID_OUI_FROM_DATABASE=Envisacor Technologies Inc. + +OUI:001C2B* + ID_OUI_FROM_DATABASE=Alertme.com Limited + +OUI:001C2C* + ID_OUI_FROM_DATABASE=Synapse + +OUI:001C2D* + ID_OUI_FROM_DATABASE=FlexRadio Systems + +OUI:001C2E* + ID_OUI_FROM_DATABASE=HPN Supply Chain + +OUI:001C2F* + ID_OUI_FROM_DATABASE=Pfister GmbH + +OUI:001C30* + ID_OUI_FROM_DATABASE=Mode Lighting (UK ) Ltd. + +OUI:001C31* + ID_OUI_FROM_DATABASE=Mobile XP Technology Co., LTD + +OUI:001C32* + ID_OUI_FROM_DATABASE=Telian Corporation + +OUI:001C33* + ID_OUI_FROM_DATABASE=Sutron + +OUI:001C34* + ID_OUI_FROM_DATABASE=HUEY CHIAO INTERNATIONAL CO., LTD. + +OUI:001C35* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001C36* + ID_OUI_FROM_DATABASE=iNEWiT NV + +OUI:001C37* + ID_OUI_FROM_DATABASE=Callpod, Inc. + +OUI:001C38* + ID_OUI_FROM_DATABASE=Bio-Rad Laboratories, Inc. + +OUI:001C39* + ID_OUI_FROM_DATABASE=S Netsystems Inc. + +OUI:001C3A* + ID_OUI_FROM_DATABASE=Element Labs, Inc. + +OUI:001C3B* + ID_OUI_FROM_DATABASE=AmRoad Technology Inc. + +OUI:001C3C* + ID_OUI_FROM_DATABASE=Seon Design Inc. + +OUI:001C3D* + ID_OUI_FROM_DATABASE=WaveStorm + +OUI:001C3E* + ID_OUI_FROM_DATABASE=ECKey Corporation + +OUI:001C3F* + ID_OUI_FROM_DATABASE=International Police Technologies, Inc. + +OUI:001C40* + ID_OUI_FROM_DATABASE=VDG-Security bv + +OUI:001C41* + ID_OUI_FROM_DATABASE=scemtec Transponder Technology GmbH + +OUI:001C42* + ID_OUI_FROM_DATABASE=Parallels, Inc. + +OUI:001C43* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001C44* + ID_OUI_FROM_DATABASE=Bosch Security Systems BV + +OUI:001C45* + ID_OUI_FROM_DATABASE=Chenbro Micom Co., Ltd. + +OUI:001C46* + ID_OUI_FROM_DATABASE=QTUM + +OUI:001C47* + ID_OUI_FROM_DATABASE=Hangzhou Hollysys Automation Co., Ltd + +OUI:001C48* + ID_OUI_FROM_DATABASE=WiDeFi, Inc. + +OUI:001C49* + ID_OUI_FROM_DATABASE=Zoltan Technology Inc. + +OUI:001C4A* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:001C4B* + ID_OUI_FROM_DATABASE=Gener8, Inc. + +OUI:001C4C* + ID_OUI_FROM_DATABASE=Petrotest Instruments + +OUI:001C4D* + ID_OUI_FROM_DATABASE=Aplix IP Holdings Corporation + +OUI:001C4E* + ID_OUI_FROM_DATABASE=TASA International Limited + +OUI:001C4F* + ID_OUI_FROM_DATABASE=MACAB AB + +OUI:001C50* + ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd. + +OUI:001C51* + ID_OUI_FROM_DATABASE=Celeno Communications + +OUI:001C52* + ID_OUI_FROM_DATABASE=VISIONEE SRL + +OUI:001C53* + ID_OUI_FROM_DATABASE=Synergy Lighting Controls + +OUI:001C54* + ID_OUI_FROM_DATABASE=Hillstone Networks Inc + +OUI:001C55* + ID_OUI_FROM_DATABASE=Shenzhen Kaifa Technology Co. + +OUI:001C56* + ID_OUI_FROM_DATABASE=Pado Systems, Inc. + +OUI:001C57* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001C58* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001C59* + ID_OUI_FROM_DATABASE=DEVON IT + +OUI:001C5A* + ID_OUI_FROM_DATABASE=Advanced Relay Corporation + +OUI:001C5B* + ID_OUI_FROM_DATABASE=Chubb Electronic Security Systems Ltd + +OUI:001C5C* + ID_OUI_FROM_DATABASE=Integrated Medical Systems, Inc. + +OUI:001C5D* + ID_OUI_FROM_DATABASE=Leica Microsystems + +OUI:001C5E* + ID_OUI_FROM_DATABASE=ASTON France + +OUI:001C5F* + ID_OUI_FROM_DATABASE=Winland Electronics, Inc. + +OUI:001C60* + ID_OUI_FROM_DATABASE=CSP Frontier Technologies,Inc. + +OUI:001C61* + ID_OUI_FROM_DATABASE=Galaxy Microsystems LImited + +OUI:001C62* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:001C63* + ID_OUI_FROM_DATABASE=TRUEN + +OUI:001C64* + ID_OUI_FROM_DATABASE=Landis+Gyr + +OUI:001C65* + ID_OUI_FROM_DATABASE=JoeScan, Inc. + +OUI:001C66* + ID_OUI_FROM_DATABASE=UCAMP CO.,LTD + +OUI:001C67* + ID_OUI_FROM_DATABASE=Pumpkin Networks, Inc. + +OUI:001C68* + ID_OUI_FROM_DATABASE=Anhui Sun Create Electronics Co., Ltd + +OUI:001C69* + ID_OUI_FROM_DATABASE=Packet Vision Ltd + +OUI:001C6A* + ID_OUI_FROM_DATABASE=Weiss Engineering Ltd. + +OUI:001C6B* + ID_OUI_FROM_DATABASE=COVAX Co. Ltd + +OUI:001C6C* + ID_OUI_FROM_DATABASE=30805 + +OUI:001C6D* + ID_OUI_FROM_DATABASE=KYOHRITSU ELECTRONIC INDUSTRY CO., LTD. + +OUI:001C6E* + ID_OUI_FROM_DATABASE=Newbury Networks, Inc. + +OUI:001C6F* + ID_OUI_FROM_DATABASE=Emfit Ltd + +OUI:001C70* + ID_OUI_FROM_DATABASE=NOVACOMM LTDA + +OUI:001C71* + ID_OUI_FROM_DATABASE=Emergent Electronics + +OUI:001C72* + ID_OUI_FROM_DATABASE=Mayer & Cie GmbH & Co KG + +OUI:001C73* + ID_OUI_FROM_DATABASE=Arista Networks + +OUI:001C74* + ID_OUI_FROM_DATABASE=Syswan Technologies Inc. + +OUI:001C75* + ID_OUI_FROM_DATABASE=Segnet Ltd. + +OUI:001C76* + ID_OUI_FROM_DATABASE=The Wandsworth Group Ltd + +OUI:001C77* + ID_OUI_FROM_DATABASE=Prodys + +OUI:001C78* + ID_OUI_FROM_DATABASE=WYPLAY SAS + +OUI:001C79* + ID_OUI_FROM_DATABASE=Cohesive Financial Technologies LLC + +OUI:001C7A* + ID_OUI_FROM_DATABASE=Perfectone Netware Company Ltd + +OUI:001C7B* + ID_OUI_FROM_DATABASE=Castlenet Technology Inc. + +OUI:001C7C* + ID_OUI_FROM_DATABASE=PERQ SYSTEMS CORPORATION + +OUI:001C7D* + ID_OUI_FROM_DATABASE=Excelpoint Manufacturing Pte Ltd + +OUI:001C7E* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:001C7F* + ID_OUI_FROM_DATABASE=Check Point Software Technologies + +OUI:001C80* + ID_OUI_FROM_DATABASE=New Business Division/Rhea-Information CO., LTD. + +OUI:001C81* + ID_OUI_FROM_DATABASE=NextGen Venturi LTD + +OUI:001C82* + ID_OUI_FROM_DATABASE=Genew Technologies + +OUI:001C83* + ID_OUI_FROM_DATABASE=New Level Telecom Co., Ltd. + +OUI:001C84* + ID_OUI_FROM_DATABASE=STL Solution Co.,Ltd. + +OUI:001C85* + ID_OUI_FROM_DATABASE=Eunicorn + +OUI:001C86* + ID_OUI_FROM_DATABASE=Cranite Systems, Inc. + +OUI:001C87* + ID_OUI_FROM_DATABASE=Uriver Inc. + +OUI:001C88* + ID_OUI_FROM_DATABASE=TRANSYSTEM INC. + +OUI:001C89* + ID_OUI_FROM_DATABASE=Force Communications, Inc. + +OUI:001C8A* + ID_OUI_FROM_DATABASE=Cirrascale Corporation + +OUI:001C8B* + ID_OUI_FROM_DATABASE=MJ Innovations Ltd. + +OUI:001C8C* + ID_OUI_FROM_DATABASE=DIAL TECHNOLOGY LTD. + +OUI:001C8D* + ID_OUI_FROM_DATABASE=Mesa Imaging + +OUI:001C8E* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:001C8F* + ID_OUI_FROM_DATABASE=Advanced Electronic Design, Inc. + +OUI:001C90* + ID_OUI_FROM_DATABASE=Empacket Corporation + +OUI:001C91* + ID_OUI_FROM_DATABASE=Gefen Inc. + +OUI:001C92* + ID_OUI_FROM_DATABASE=Tervela + +OUI:001C93* + ID_OUI_FROM_DATABASE=ExaDigm Inc + +OUI:001C94* + ID_OUI_FROM_DATABASE=LI-COR Biosciences + +OUI:001C95* + ID_OUI_FROM_DATABASE=Opticomm Corporation + +OUI:001C96* + ID_OUI_FROM_DATABASE=Linkwise Technology Pte Ltd + +OUI:001C97* + ID_OUI_FROM_DATABASE=Enzytek Technology Inc., + +OUI:001C98* + ID_OUI_FROM_DATABASE=LUCKY TECHNOLOGY (HK) COMPANY LIMITED + +OUI:001C99* + ID_OUI_FROM_DATABASE=Shunra Software Ltd. + +OUI:001C9A* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001C9B* + ID_OUI_FROM_DATABASE=FEIG ELECTRONIC GmbH + +OUI:001C9C* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001C9D* + ID_OUI_FROM_DATABASE=Liecthi AG + +OUI:001C9E* + ID_OUI_FROM_DATABASE=Dualtech IT AB + +OUI:001C9F* + ID_OUI_FROM_DATABASE=Razorstream, LLC + +OUI:001CA0* + ID_OUI_FROM_DATABASE=Production Resource Group, LLC + +OUI:001CA1* + ID_OUI_FROM_DATABASE=AKAMAI TECHNOLOGIES, INC. + +OUI:001CA2* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:001CA3* + ID_OUI_FROM_DATABASE=Terra + +OUI:001CA4* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:001CA5* + ID_OUI_FROM_DATABASE=Zygo Corporation + +OUI:001CA6* + ID_OUI_FROM_DATABASE=Win4NET + +OUI:001CA7* + ID_OUI_FROM_DATABASE=International Quartz Limited + +OUI:001CA8* + ID_OUI_FROM_DATABASE=AirTies Wireless Networks + +OUI:001CA9* + ID_OUI_FROM_DATABASE=Audiomatica Srl + +OUI:001CAA* + ID_OUI_FROM_DATABASE=Bellon Pty Ltd + +OUI:001CAB* + ID_OUI_FROM_DATABASE=Meyer Sound Laboratories, Inc. + +OUI:001CAC* + ID_OUI_FROM_DATABASE=Qniq Technology Corp. + +OUI:001CAD* + ID_OUI_FROM_DATABASE=Wuhan Telecommunication Devices Co.,Ltd + +OUI:001CAE* + ID_OUI_FROM_DATABASE=WiChorus, Inc. + +OUI:001CAF* + ID_OUI_FROM_DATABASE=Plato Networks Inc. + +OUI:001CB0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001CB1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001CB2* + ID_OUI_FROM_DATABASE=BPT SPA + +OUI:001CB3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001CB4* + ID_OUI_FROM_DATABASE=Iridium Satellite LLC + +OUI:001CB5* + ID_OUI_FROM_DATABASE=Neihua Network Technology Co.,LTD.(NHN) + +OUI:001CB6* + ID_OUI_FROM_DATABASE=Duzon CNT Co., Ltd. + +OUI:001CB7* + ID_OUI_FROM_DATABASE=USC DigiArk Corporation + +OUI:001CB8* + ID_OUI_FROM_DATABASE=CBC Co., Ltd + +OUI:001CB9* + ID_OUI_FROM_DATABASE=KWANG SUNG ELECTRONICS CO., LTD. + +OUI:001CBA* + ID_OUI_FROM_DATABASE=VerScient, Inc. + +OUI:001CBB* + ID_OUI_FROM_DATABASE=MusicianLink + +OUI:001CBC* + ID_OUI_FROM_DATABASE=CastGrabber, LLC + +OUI:001CBD* + ID_OUI_FROM_DATABASE=Ezze Mobile Tech., Inc. + +OUI:001CBE* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:001CBF* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001CC0* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001CC1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001CC2* + ID_OUI_FROM_DATABASE=Part II Research, Inc. + +OUI:001CC3* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001CC4* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001CC5* + ID_OUI_FROM_DATABASE=3Com Ltd + +OUI:001CC6* + ID_OUI_FROM_DATABASE=ProStor Systems + +OUI:001CC7* + ID_OUI_FROM_DATABASE=Rembrandt Technologies, LLC d/b/a REMSTREAM + +OUI:001CC8* + ID_OUI_FROM_DATABASE=INDUSTRONIC Industrie-Electronic GmbH & Co. KG + +OUI:001CC9* + ID_OUI_FROM_DATABASE=Kaise Electronic Technology Co., Ltd. + +OUI:001CCA* + ID_OUI_FROM_DATABASE=Shanghai Gaozhi Science & Technology Development Co. + +OUI:001CCB* + ID_OUI_FROM_DATABASE=Forth Corporation Public Company Limited + +OUI:001CCC* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:001CCD* + ID_OUI_FROM_DATABASE=Alektrona Corporation + +OUI:001CCE* + ID_OUI_FROM_DATABASE=By Techdesign + +OUI:001CCF* + ID_OUI_FROM_DATABASE=LIMETEK + +OUI:001CD0* + ID_OUI_FROM_DATABASE=Circleone Co.,Ltd. + +OUI:001CD1* + ID_OUI_FROM_DATABASE=Waves Audio LTD + +OUI:001CD2* + ID_OUI_FROM_DATABASE=King Champion (Hong Kong) Limited + +OUI:001CD3* + ID_OUI_FROM_DATABASE=ZP Engineering SEL + +OUI:001CD4* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001CD5* + ID_OUI_FROM_DATABASE=ZeeVee, Inc. + +OUI:001CD6* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001CD7* + ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH + +OUI:001CD8* + ID_OUI_FROM_DATABASE=BlueAnt Wireless + +OUI:001CD9* + ID_OUI_FROM_DATABASE=GlobalTop Technology Inc. + +OUI:001CDA* + ID_OUI_FROM_DATABASE=Exegin Technologies Limited + +OUI:001CDB* + ID_OUI_FROM_DATABASE=CARPOINT CO.,LTD + +OUI:001CDC* + ID_OUI_FROM_DATABASE=Custom Computer Services, Inc. + +OUI:001CDD* + ID_OUI_FROM_DATABASE=COWBELL ENGINEERING CO., LTD. + +OUI:001CDE* + ID_OUI_FROM_DATABASE=Interactive Multimedia eXchange Inc. + +OUI:001CDF* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:001CE0* + ID_OUI_FROM_DATABASE=DASAN TPS + +OUI:001CE1* + ID_OUI_FROM_DATABASE=INDRA SISTEMAS, S.A. + +OUI:001CE2* + ID_OUI_FROM_DATABASE=Attero Tech, LLC. + +OUI:001CE3* + ID_OUI_FROM_DATABASE=Optimedical Systems + +OUI:001CE4* + ID_OUI_FROM_DATABASE=EleSy JSC + +OUI:001CE5* + ID_OUI_FROM_DATABASE=MBS Electronic Systems GmbH + +OUI:001CE6* + ID_OUI_FROM_DATABASE=INNES + +OUI:001CE7* + ID_OUI_FROM_DATABASE=Rocon PLC Research Centre + +OUI:001CE8* + ID_OUI_FROM_DATABASE=Cummins Inc + +OUI:001CE9* + ID_OUI_FROM_DATABASE=Galaxy Technology Limited + +OUI:001CEA* + ID_OUI_FROM_DATABASE=Scientific-Atlanta, Inc + +OUI:001CEB* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001CEC* + ID_OUI_FROM_DATABASE=Mobilesoft (Aust.) Pty Ltd + +OUI:001CED* + ID_OUI_FROM_DATABASE=ENVIRONNEMENT SA + +OUI:001CEE* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:001CEF* + ID_OUI_FROM_DATABASE=Primax Electronics Ltd. + +OUI:001CF0* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:001CF1* + ID_OUI_FROM_DATABASE=SUPoX Technology Co. , LTD. + +OUI:001CF2* + ID_OUI_FROM_DATABASE=Tenlon Technology Co.,Ltd. + +OUI:001CF3* + ID_OUI_FROM_DATABASE=EVS BROADCAST EQUIPMENT + +OUI:001CF4* + ID_OUI_FROM_DATABASE=Media Technology Systems Inc + +OUI:001CF5* + ID_OUI_FROM_DATABASE=Wiseblue Technology Limited + +OUI:001CF6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001CF7* + ID_OUI_FROM_DATABASE=AudioScience + +OUI:001CF8* + ID_OUI_FROM_DATABASE=Parade Technologies, Ltd. + +OUI:001CF9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001CFA* + ID_OUI_FROM_DATABASE=Alarm.com + +OUI:001CFB* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001CFC* + ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd + +OUI:001CFD* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. + +OUI:001CFE* + ID_OUI_FROM_DATABASE=Quartics Inc + +OUI:001CFF* + ID_OUI_FROM_DATABASE=Napera Networks Inc + +OUI:001D00* + ID_OUI_FROM_DATABASE=Brivo Systems, LLC + +OUI:001D01* + ID_OUI_FROM_DATABASE=Neptune Digital + +OUI:001D02* + ID_OUI_FROM_DATABASE=Cybertech Telecom Development + +OUI:001D03* + ID_OUI_FROM_DATABASE=Design Solutions Inc. + +OUI:001D04* + ID_OUI_FROM_DATABASE=Zipit Wireless, Inc. + +OUI:001D05* + ID_OUI_FROM_DATABASE=Eaton Corporation + +OUI:001D06* + ID_OUI_FROM_DATABASE=HM Electronics, Inc. + +OUI:001D07* + ID_OUI_FROM_DATABASE=Shenzhen Sang Fei Consumer Communications Co.,Ltd + +OUI:001D08* + ID_OUI_FROM_DATABASE=Jiangsu Yinhe Electronics Co.,Ltd. + +OUI:001D09* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:001D0A* + ID_OUI_FROM_DATABASE=Davis Instruments, Inc. + +OUI:001D0B* + ID_OUI_FROM_DATABASE=Power Standards Lab + +OUI:001D0C* + ID_OUI_FROM_DATABASE=MobileCompia + +OUI:001D0D* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:001D0E* + ID_OUI_FROM_DATABASE=Agapha Technology co., Ltd. + +OUI:001D0F* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:001D10* + ID_OUI_FROM_DATABASE=LightHaus Logic, Inc. + +OUI:001D11* + ID_OUI_FROM_DATABASE=Analogue & Micro Ltd + +OUI:001D12* + ID_OUI_FROM_DATABASE=ROHM CO., LTD. + +OUI:001D13* + ID_OUI_FROM_DATABASE=NextGTV + +OUI:001D14* + ID_OUI_FROM_DATABASE=SPERADTONE INFORMATION TECHNOLOGY LIMITED + +OUI:001D15* + ID_OUI_FROM_DATABASE=Shenzhen Dolphin Electronic Co., Ltd + +OUI:001D16* + ID_OUI_FROM_DATABASE=SFR + +OUI:001D17* + ID_OUI_FROM_DATABASE=Digital Sky Corporation + +OUI:001D18* + ID_OUI_FROM_DATABASE=Power Innovation GmbH + +OUI:001D19* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:001D1A* + ID_OUI_FROM_DATABASE=OvisLink S.A. + +OUI:001D1B* + ID_OUI_FROM_DATABASE=Sangean Electronics Inc. + +OUI:001D1C* + ID_OUI_FROM_DATABASE=Gennet s.a. + +OUI:001D1D* + ID_OUI_FROM_DATABASE=Inter-M Corporation + +OUI:001D1E* + ID_OUI_FROM_DATABASE=KYUSHU TEN CO.,LTD + +OUI:001D1F* + ID_OUI_FROM_DATABASE=Siauliu Tauro Televizoriai, JSC + +OUI:001D20* + ID_OUI_FROM_DATABASE=Comtrend Corporation + +OUI:001D21* + ID_OUI_FROM_DATABASE=Alcad SL + +OUI:001D22* + ID_OUI_FROM_DATABASE=Foss Analytical A/S + +OUI:001D23* + ID_OUI_FROM_DATABASE=SENSUS + +OUI:001D24* + ID_OUI_FROM_DATABASE=Aclara Power-Line Systems Inc. + +OUI:001D25* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001D26* + ID_OUI_FROM_DATABASE=Rockridgesound Technology Co. + +OUI:001D27* + ID_OUI_FROM_DATABASE=NAC-INTERCOM + +OUI:001D28* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:001D29* + ID_OUI_FROM_DATABASE=Doro AB + +OUI:001D2A* + ID_OUI_FROM_DATABASE=SHENZHEN BUL-TECH CO.,LTD. + +OUI:001D2B* + ID_OUI_FROM_DATABASE=Wuhan Pont Technology CO. , LTD + +OUI:001D2C* + ID_OUI_FROM_DATABASE=Wavetrend Technologies (Pty) Limited + +OUI:001D2D* + ID_OUI_FROM_DATABASE=Pylone, Inc. + +OUI:001D2E* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:001D2F* + ID_OUI_FROM_DATABASE=QuantumVision Corporation + +OUI:001D30* + ID_OUI_FROM_DATABASE=YX Wireless S.A. + +OUI:001D31* + ID_OUI_FROM_DATABASE=HIGHPRO INTERNATIONAL R&D CO,.LTD. + +OUI:001D32* + ID_OUI_FROM_DATABASE=Longkay Communication & Technology (Shanghai) Co. Ltd + +OUI:001D33* + ID_OUI_FROM_DATABASE=Maverick Systems Inc. + +OUI:001D34* + ID_OUI_FROM_DATABASE=SYRIS Technology Corp + +OUI:001D35* + ID_OUI_FROM_DATABASE=Viconics Electronics Inc. + +OUI:001D36* + ID_OUI_FROM_DATABASE=ELECTRONICS CORPORATION OF INDIA LIMITED + +OUI:001D37* + ID_OUI_FROM_DATABASE=Thales-Panda Transportation System + +OUI:001D38* + ID_OUI_FROM_DATABASE=Seagate Technology + +OUI:001D39* + ID_OUI_FROM_DATABASE=MOOHADIGITAL CO., LTD + +OUI:001D3A* + ID_OUI_FROM_DATABASE=mh acoustics LLC + +OUI:001D3B* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001D3C* + ID_OUI_FROM_DATABASE=Muscle Corporation + +OUI:001D3D* + ID_OUI_FROM_DATABASE=Avidyne Corporation + +OUI:001D3E* + ID_OUI_FROM_DATABASE=SAKA TECHNO SCIENCE CO.,LTD + +OUI:001D3F* + ID_OUI_FROM_DATABASE=Mitron Pty Ltd + +OUI:001D40* + ID_OUI_FROM_DATABASE=Intel – GE Care Innovations LLC + +OUI:001D41* + ID_OUI_FROM_DATABASE=Hardy Instruments + +OUI:001D42* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001D43* + ID_OUI_FROM_DATABASE=Shenzhen G-link Digital Technology Co., Ltd. + +OUI:001D44* + ID_OUI_FROM_DATABASE=Krohne + +OUI:001D45* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001D46* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001D47* + ID_OUI_FROM_DATABASE=Covote GmbH & Co KG + +OUI:001D48* + ID_OUI_FROM_DATABASE=Sensor-Technik Wiedemann GmbH + +OUI:001D49* + ID_OUI_FROM_DATABASE=Innovation Wireless Inc. + +OUI:001D4A* + ID_OUI_FROM_DATABASE=Carestream Health, Inc. + +OUI:001D4B* + ID_OUI_FROM_DATABASE=Grid Connect Inc. + +OUI:001D4C* + ID_OUI_FROM_DATABASE=Alcatel-Lucent + +OUI:001D4D* + ID_OUI_FROM_DATABASE=Adaptive Recognition Hungary, Inc + +OUI:001D4E* + ID_OUI_FROM_DATABASE=TCM Mobile LLC + +OUI:001D4F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001D50* + ID_OUI_FROM_DATABASE=SPINETIX SA + +OUI:001D51* + ID_OUI_FROM_DATABASE=Babcock & Wilcox Power Generation Group, Inc + +OUI:001D52* + ID_OUI_FROM_DATABASE=Defzone B.V. + +OUI:001D53* + ID_OUI_FROM_DATABASE=S&O Electronics (Malaysia) Sdn. Bhd. + +OUI:001D54* + ID_OUI_FROM_DATABASE=Sunnic Technology & Merchandise INC. + +OUI:001D55* + ID_OUI_FROM_DATABASE=ZANTAZ, Inc + +OUI:001D56* + ID_OUI_FROM_DATABASE=Kramer Electronics Ltd. + +OUI:001D57* + ID_OUI_FROM_DATABASE=CAETEC Messtechnik + +OUI:001D58* + ID_OUI_FROM_DATABASE=CQ Inc + +OUI:001D59* + ID_OUI_FROM_DATABASE=Mitra Energy & Infrastructure + +OUI:001D5A* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:001D5B* + ID_OUI_FROM_DATABASE=Tecvan Informática Ltda + +OUI:001D5C* + ID_OUI_FROM_DATABASE=Tom Communication Industrial Co.,Ltd. + +OUI:001D5D* + ID_OUI_FROM_DATABASE=Control Dynamics Pty. Ltd. + +OUI:001D5E* + ID_OUI_FROM_DATABASE=COMING MEDIA CORP. + +OUI:001D5F* + ID_OUI_FROM_DATABASE=OverSpeed SARL + +OUI:001D60* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:001D61* + ID_OUI_FROM_DATABASE=BIJ Corporation + +OUI:001D62* + ID_OUI_FROM_DATABASE=InPhase Technologies + +OUI:001D63* + ID_OUI_FROM_DATABASE=Miele & Cie. KG + +OUI:001D64* + ID_OUI_FROM_DATABASE=Adam Communications Systems Int Ltd + +OUI:001D65* + ID_OUI_FROM_DATABASE=Microwave Radio Communications + +OUI:001D66* + ID_OUI_FROM_DATABASE=Hyundai Telecom + +OUI:001D67* + ID_OUI_FROM_DATABASE=AMEC + +OUI:001D68* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium + +OUI:001D69* + ID_OUI_FROM_DATABASE=Knorr-Bremse IT-Services GmbH + +OUI:001D6A* + ID_OUI_FROM_DATABASE=Alpha Networks Inc. + +OUI:001D6B* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001D6C* + ID_OUI_FROM_DATABASE=ClariPhy Communications, Inc. + +OUI:001D6D* + ID_OUI_FROM_DATABASE=Confidant International LLC + +OUI:001D6E* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001D6F* + ID_OUI_FROM_DATABASE=Chainzone Technology Co., Ltd + +OUI:001D70* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001D71* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001D72* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:001D73* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:001D74* + ID_OUI_FROM_DATABASE=Tianjin China-Silicon Microelectronics Co., Ltd. + +OUI:001D75* + ID_OUI_FROM_DATABASE=Radioscape PLC + +OUI:001D76* + ID_OUI_FROM_DATABASE=Eyeheight Ltd. + +OUI:001D77* + ID_OUI_FROM_DATABASE=NSGate + +OUI:001D78* + ID_OUI_FROM_DATABASE=Invengo Information Technology Co.,Ltd + +OUI:001D79* + ID_OUI_FROM_DATABASE=SIGNAMAX LLC + +OUI:001D7A* + ID_OUI_FROM_DATABASE=Wideband Semiconductor, Inc. + +OUI:001D7B* + ID_OUI_FROM_DATABASE=Ice Energy, Inc. + +OUI:001D7C* + ID_OUI_FROM_DATABASE=ABE Elettronica S.p.A. + +OUI:001D7D* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:001D7E* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:001D7F* + ID_OUI_FROM_DATABASE=Tekron International Ltd + +OUI:001D80* + ID_OUI_FROM_DATABASE=Beijing Huahuan Eletronics Co.,Ltd + +OUI:001D81* + ID_OUI_FROM_DATABASE=GUANGZHOU GATEWAY ELECTRONICS CO., LTD + +OUI:001D82* + ID_OUI_FROM_DATABASE=GN Netcom A/S + +OUI:001D83* + ID_OUI_FROM_DATABASE=Emitech Corporation + +OUI:001D84* + ID_OUI_FROM_DATABASE=Gateway, Inc. + +OUI:001D85* + ID_OUI_FROM_DATABASE=Call Direct Cellular Solutions + +OUI:001D86* + ID_OUI_FROM_DATABASE=Shinwa Industries(China) Ltd. + +OUI:001D87* + ID_OUI_FROM_DATABASE=VigTech Labs Sdn Bhd + +OUI:001D88* + ID_OUI_FROM_DATABASE=Clearwire + +OUI:001D89* + ID_OUI_FROM_DATABASE=VaultStor Corporation + +OUI:001D8A* + ID_OUI_FROM_DATABASE=TechTrex Inc + +OUI:001D8B* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:001D8C* + ID_OUI_FROM_DATABASE=La Crosse Technology LTD + +OUI:001D8D* + ID_OUI_FROM_DATABASE=Fluke Process Instruments GmbH + +OUI:001D8E* + ID_OUI_FROM_DATABASE=Alereon, Inc. + +OUI:001D8F* + ID_OUI_FROM_DATABASE=PureWave Networks + +OUI:001D90* + ID_OUI_FROM_DATABASE=EMCO Flow Systems + +OUI:001D91* + ID_OUI_FROM_DATABASE=Digitize, Inc + +OUI:001D92* + ID_OUI_FROM_DATABASE=MICRO-STAR INT'L CO.,LTD. + +OUI:001D93* + ID_OUI_FROM_DATABASE=Modacom + +OUI:001D94* + ID_OUI_FROM_DATABASE=Climax Technology Co., Ltd + +OUI:001D95* + ID_OUI_FROM_DATABASE=Flash, Inc. + +OUI:001D96* + ID_OUI_FROM_DATABASE=WatchGuard Video + +OUI:001D97* + ID_OUI_FROM_DATABASE=Alertus Technologies LLC + +OUI:001D98* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001D99* + ID_OUI_FROM_DATABASE=Cyan Optic, Inc. + +OUI:001D9A* + ID_OUI_FROM_DATABASE=GODEX INTERNATIONAL CO., LTD + +OUI:001D9B* + ID_OUI_FROM_DATABASE=Hokuyo Automatic Co., Ltd. + +OUI:001D9C* + ID_OUI_FROM_DATABASE=Rockwell Automation + +OUI:001D9D* + ID_OUI_FROM_DATABASE=ARTJOY INTERNATIONAL LIMITED + +OUI:001D9E* + ID_OUI_FROM_DATABASE=AXION TECHNOLOGIES + +OUI:001D9F* + ID_OUI_FROM_DATABASE=MATT R.P.Traczynscy Sp.J. + +OUI:001DA0* + ID_OUI_FROM_DATABASE=Heng Yu Electronic Manufacturing Company Limited + +OUI:001DA1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001DA2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001DA3* + ID_OUI_FROM_DATABASE=SabiOso + +OUI:001DA4* + ID_OUI_FROM_DATABASE=Hangzhou System Technology CO., LTD + +OUI:001DA5* + ID_OUI_FROM_DATABASE=WB Electronics + +OUI:001DA6* + ID_OUI_FROM_DATABASE=Media Numerics Limited + +OUI:001DA7* + ID_OUI_FROM_DATABASE=Seamless Internet + +OUI:001DA8* + ID_OUI_FROM_DATABASE=Takahata Electronics Co.,Ltd + +OUI:001DA9* + ID_OUI_FROM_DATABASE=Castles Technology, Co., LTD + +OUI:001DAA* + ID_OUI_FROM_DATABASE=DrayTek Corp. + +OUI:001DAB* + ID_OUI_FROM_DATABASE=SwissQual License AG + +OUI:001DAC* + ID_OUI_FROM_DATABASE=Gigamon Systems LLC + +OUI:001DAD* + ID_OUI_FROM_DATABASE=Sinotech Engineering Consultants, Inc. Geotechnical Enginee + +OUI:001DAE* + ID_OUI_FROM_DATABASE=CHANG TSENG TECHNOLOGY CO., LTD + +OUI:001DAF* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001DB0* + ID_OUI_FROM_DATABASE=FuJian HengTong Information Technology Co.,Ltd + +OUI:001DB1* + ID_OUI_FROM_DATABASE=Crescendo Networks + +OUI:001DB2* + ID_OUI_FROM_DATABASE=HOKKAIDO ELECTRIC ENGINEERING CO.,LTD. + +OUI:001DB3* + ID_OUI_FROM_DATABASE=HPN Supply Chain + +OUI:001DB4* + ID_OUI_FROM_DATABASE=KUMHO ENG CO.,LTD + +OUI:001DB5* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:001DB6* + ID_OUI_FROM_DATABASE=BestComm Networks, Inc. + +OUI:001DB7* + ID_OUI_FROM_DATABASE=Tendril Networks, Inc. + +OUI:001DB8* + ID_OUI_FROM_DATABASE=Intoto Inc. + +OUI:001DB9* + ID_OUI_FROM_DATABASE=Wellspring Wireless + +OUI:001DBA* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:001DBB* + ID_OUI_FROM_DATABASE=Dynamic System Electronics Corp. + +OUI:001DBC* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:001DBD* + ID_OUI_FROM_DATABASE=Versamed Inc. + +OUI:001DBE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DBF* + ID_OUI_FROM_DATABASE=Radiient Technologies, Inc. + +OUI:001DC0* + ID_OUI_FROM_DATABASE=Enphase Energy + +OUI:001DC1* + ID_OUI_FROM_DATABASE=Audinate Pty L + +OUI:001DC2* + ID_OUI_FROM_DATABASE=XORTEC OY + +OUI:001DC3* + ID_OUI_FROM_DATABASE=RIKOR TV, Ltd + +OUI:001DC4* + ID_OUI_FROM_DATABASE=AIOI Systems Co., Ltd. + +OUI:001DC5* + ID_OUI_FROM_DATABASE=Beijing Jiaxun Feihong Electricial Co., Ltd. + +OUI:001DC6* + ID_OUI_FROM_DATABASE=SNR Inc. + +OUI:001DC7* + ID_OUI_FROM_DATABASE=L-3 Communications Geneva Aerospace + +OUI:001DC8* + ID_OUI_FROM_DATABASE=Navionics Research Inc., dba SCADAmetrics + +OUI:001DC9* + ID_OUI_FROM_DATABASE=GainSpan Corp. + +OUI:001DCA* + ID_OUI_FROM_DATABASE=PAV Electronics Limited + +OUI:001DCB* + ID_OUI_FROM_DATABASE=Exéns Development Oy + +OUI:001DCC* + ID_OUI_FROM_DATABASE=Ayon Cyber Security, Inc + +OUI:001DCD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DCE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DCF* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DD0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DD1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DD2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DD3* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DD4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DD5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DD6* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001DD7* + ID_OUI_FROM_DATABASE=Algolith + +OUI:001DD8* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:001DD9* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:001DDA* + ID_OUI_FROM_DATABASE=Mikroelektronika spol. s r. o. + +OUI:001DDB* + ID_OUI_FROM_DATABASE=C-BEL Corporation + +OUI:001DDC* + ID_OUI_FROM_DATABASE=HangZhou DeChangLong Tech&Info Co.,Ltd + +OUI:001DDD* + ID_OUI_FROM_DATABASE=DAT H.K. LIMITED + +OUI:001DDE* + ID_OUI_FROM_DATABASE=Zhejiang Broadcast&Television Technology Co.,Ltd. + +OUI:001DDF* + ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd + +OUI:001DE0* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001DE1* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001DE2* + ID_OUI_FROM_DATABASE=Radionor Communications + +OUI:001DE3* + ID_OUI_FROM_DATABASE=Intuicom + +OUI:001DE4* + ID_OUI_FROM_DATABASE=Visioneered Image Systems + +OUI:001DE5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001DE6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001DE7* + ID_OUI_FROM_DATABASE=Marine Sonic Technology, Ltd. + +OUI:001DE8* + ID_OUI_FROM_DATABASE=Nikko Denki Tsushin Corporation(NDTC) + +OUI:001DE9* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001DEA* + ID_OUI_FROM_DATABASE=Commtest Instruments Ltd + +OUI:001DEB* + ID_OUI_FROM_DATABASE=DINEC International + +OUI:001DEC* + ID_OUI_FROM_DATABASE=Marusys + +OUI:001DED* + ID_OUI_FROM_DATABASE=Grid Net, Inc. + +OUI:001DEE* + ID_OUI_FROM_DATABASE=NEXTVISION SISTEMAS DIGITAIS DE TELEVISÃO LTDA. + +OUI:001DEF* + ID_OUI_FROM_DATABASE=TRIMM, INC. + +OUI:001DF0* + ID_OUI_FROM_DATABASE=Vidient Systems, Inc. + +OUI:001DF1* + ID_OUI_FROM_DATABASE=Intego Systems, Inc. + +OUI:001DF2* + ID_OUI_FROM_DATABASE=Netflix, Inc. + +OUI:001DF3* + ID_OUI_FROM_DATABASE=SBS Science & Technology Co., Ltd + +OUI:001DF4* + ID_OUI_FROM_DATABASE=Magellan Technology Pty Limited + +OUI:001DF5* + ID_OUI_FROM_DATABASE=Sunshine Co,LTD + +OUI:001DF6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001DF7* + ID_OUI_FROM_DATABASE=R. STAHL Schaltgeräte GmbH + +OUI:001DF8* + ID_OUI_FROM_DATABASE=Webpro Vision Technology Corporation + +OUI:001DF9* + ID_OUI_FROM_DATABASE=Cybiotronics (Far East) Limited + +OUI:001DFA* + ID_OUI_FROM_DATABASE=Fujian LANDI Commercial Equipment Co.,Ltd + +OUI:001DFB* + ID_OUI_FROM_DATABASE=NETCLEUS Systems Corporation + +OUI:001DFC* + ID_OUI_FROM_DATABASE=KSIC + +OUI:001DFD* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001DFE* + ID_OUI_FROM_DATABASE=Palm, Inc + +OUI:001DFF* + ID_OUI_FROM_DATABASE=Network Critical Solutions Ltd + +OUI:001E00* + ID_OUI_FROM_DATABASE=Shantou Institute of Ultrasonic Instruments + +OUI:001E01* + ID_OUI_FROM_DATABASE=Renesas Technology Sales Co., Ltd. + +OUI:001E02* + ID_OUI_FROM_DATABASE=Sougou Keikaku Kougyou Co.,Ltd. + +OUI:001E03* + ID_OUI_FROM_DATABASE=LiComm Co., Ltd. + +OUI:001E04* + ID_OUI_FROM_DATABASE=Hanson Research Corporation + +OUI:001E05* + ID_OUI_FROM_DATABASE=Xseed Technologies & Computing + +OUI:001E06* + ID_OUI_FROM_DATABASE=WIBRAIN + +OUI:001E07* + ID_OUI_FROM_DATABASE=Winy Technology Co., Ltd. + +OUI:001E08* + ID_OUI_FROM_DATABASE=Centec Networks Inc + +OUI:001E09* + ID_OUI_FROM_DATABASE=ZEFATEK Co.,LTD + +OUI:001E0A* + ID_OUI_FROM_DATABASE=Syba Tech Limited + +OUI:001E0B* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001E0C* + ID_OUI_FROM_DATABASE=Sherwood Information Partners, Inc. + +OUI:001E0D* + ID_OUI_FROM_DATABASE=Micran Ltd. + +OUI:001E0E* + ID_OUI_FROM_DATABASE=MAXI VIEW HOLDINGS LIMITED + +OUI:001E0F* + ID_OUI_FROM_DATABASE=Briot International + +OUI:001E10* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:001E11* + ID_OUI_FROM_DATABASE=ELELUX INTERNATIONAL LTD + +OUI:001E12* + ID_OUI_FROM_DATABASE=Ecolab + +OUI:001E13* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001E14* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001E15* + ID_OUI_FROM_DATABASE=Beech Hill Electronics + +OUI:001E16* + ID_OUI_FROM_DATABASE=Keytronix + +OUI:001E17* + ID_OUI_FROM_DATABASE=STN BV + +OUI:001E18* + ID_OUI_FROM_DATABASE=Radio Activity srl + +OUI:001E19* + ID_OUI_FROM_DATABASE=GTRI + +OUI:001E1A* + ID_OUI_FROM_DATABASE=Best Source Taiwan Inc. + +OUI:001E1B* + ID_OUI_FROM_DATABASE=Digital Stream Technology, Inc. + +OUI:001E1C* + ID_OUI_FROM_DATABASE=SWS Australia Pty Limited + +OUI:001E1D* + ID_OUI_FROM_DATABASE=East Coast Datacom, Inc. + +OUI:001E1E* + ID_OUI_FROM_DATABASE=Honeywell Life Safety + +OUI:001E1F* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001E20* + ID_OUI_FROM_DATABASE=Intertain Inc. + +OUI:001E21* + ID_OUI_FROM_DATABASE=Qisda Corporation + +OUI:001E22* + ID_OUI_FROM_DATABASE=ARVOO Imaging Products BV + +OUI:001E23* + ID_OUI_FROM_DATABASE=Electronic Educational Devices, Inc + +OUI:001E24* + ID_OUI_FROM_DATABASE=Zhejiang Bell Technology Co.,ltd + +OUI:001E25* + ID_OUI_FROM_DATABASE=INTEK DIGITAL + +OUI:001E26* + ID_OUI_FROM_DATABASE=Digifriends Co. Ltd + +OUI:001E27* + ID_OUI_FROM_DATABASE=SBN TECH Co.,Ltd. + +OUI:001E28* + ID_OUI_FROM_DATABASE=Lumexis Corporation + +OUI:001E29* + ID_OUI_FROM_DATABASE=Hypertherm Inc + +OUI:001E2A* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:001E2B* + ID_OUI_FROM_DATABASE=Radio Systems Design, Inc. + +OUI:001E2C* + ID_OUI_FROM_DATABASE=CyVerse Corporation + +OUI:001E2D* + ID_OUI_FROM_DATABASE=STIM + +OUI:001E2E* + ID_OUI_FROM_DATABASE=SIRTI S.p.A. + +OUI:001E2F* + ID_OUI_FROM_DATABASE=DiMoto Pty Ltd + +OUI:001E30* + ID_OUI_FROM_DATABASE=Shireen Inc + +OUI:001E31* + ID_OUI_FROM_DATABASE=INFOMARK CO.,LTD. + +OUI:001E32* + ID_OUI_FROM_DATABASE=Zensys + +OUI:001E33* + ID_OUI_FROM_DATABASE=INVENTEC CORPORATION + +OUI:001E34* + ID_OUI_FROM_DATABASE=CryptoMetrics + +OUI:001E35* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:001E36* + ID_OUI_FROM_DATABASE=IPTE + +OUI:001E37* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:001E38* + ID_OUI_FROM_DATABASE=Bluecard Software Technology Co., Ltd. + +OUI:001E39* + ID_OUI_FROM_DATABASE=Comsys Communication Ltd. + +OUI:001E3A* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001E3B* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001E3C* + ID_OUI_FROM_DATABASE=Lyngbox Media AB + +OUI:001E3D* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:001E3E* + ID_OUI_FROM_DATABASE=KMW Inc. + +OUI:001E3F* + ID_OUI_FROM_DATABASE=TrellisWare Technologies, Inc. + +OUI:001E40* + ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co.,Ltd + +OUI:001E41* + ID_OUI_FROM_DATABASE=Microwave Communication & Component, Inc. + +OUI:001E42* + ID_OUI_FROM_DATABASE=Teltonika + +OUI:001E43* + ID_OUI_FROM_DATABASE=AISIN AW CO.,LTD. + +OUI:001E44* + ID_OUI_FROM_DATABASE=SANTEC + +OUI:001E45* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:001E46* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001E47* + ID_OUI_FROM_DATABASE=PT. Hariff Daya Tunggal Engineering + +OUI:001E48* + ID_OUI_FROM_DATABASE=Wi-Links + +OUI:001E49* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001E4A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001E4B* + ID_OUI_FROM_DATABASE=City Theatrical + +OUI:001E4C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:001E4D* + ID_OUI_FROM_DATABASE=Welkin Sciences, LLC + +OUI:001E4E* + ID_OUI_FROM_DATABASE=DAKO EDV-Ingenieur- und Systemhaus GmbH + +OUI:001E4F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:001E50* + ID_OUI_FROM_DATABASE=BATTISTONI RESEARCH + +OUI:001E51* + ID_OUI_FROM_DATABASE=Converter Industry Srl + +OUI:001E52* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001E53* + ID_OUI_FROM_DATABASE=Further Tech Co., LTD + +OUI:001E54* + ID_OUI_FROM_DATABASE=TOYO ELECTRIC Corporation + +OUI:001E55* + ID_OUI_FROM_DATABASE=COWON SYSTEMS,Inc. + +OUI:001E56* + ID_OUI_FROM_DATABASE=Bally Wulff Entertainment GmbH + +OUI:001E57* + ID_OUI_FROM_DATABASE=ALCOMA, spol. s r.o. + +OUI:001E58* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:001E59* + ID_OUI_FROM_DATABASE=Silicon Turnkey Express, LLC + +OUI:001E5A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001E5B* + ID_OUI_FROM_DATABASE=Unitron Company, Inc. + +OUI:001E5C* + ID_OUI_FROM_DATABASE=RB GeneralEkonomik + +OUI:001E5D* + ID_OUI_FROM_DATABASE=Holosys d.o.o. + +OUI:001E5E* + ID_OUI_FROM_DATABASE=COmputime Ltd. + +OUI:001E5F* + ID_OUI_FROM_DATABASE=KwikByte, LLC + +OUI:001E60* + ID_OUI_FROM_DATABASE=Digital Lighting Systems, Inc + +OUI:001E61* + ID_OUI_FROM_DATABASE=ITEC GmbH + +OUI:001E62* + ID_OUI_FROM_DATABASE=Siemon + +OUI:001E63* + ID_OUI_FROM_DATABASE=Vibro-Meter SA + +OUI:001E64* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001E65* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001E66* + ID_OUI_FROM_DATABASE=RESOL Elektronische Regelungen GmbH + +OUI:001E67* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001E68* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:001E69* + ID_OUI_FROM_DATABASE=Thomson Inc. + +OUI:001E6A* + ID_OUI_FROM_DATABASE=Beijing Bluexon Technology Co.,Ltd + +OUI:001E6B* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:001E6C* + ID_OUI_FROM_DATABASE=Opaque Systems + +OUI:001E6D* + ID_OUI_FROM_DATABASE=IT R&D Center + +OUI:001E6E* + ID_OUI_FROM_DATABASE=Shenzhen First Mile Communications Ltd + +OUI:001E6F* + ID_OUI_FROM_DATABASE=Magna-Power Electronics, Inc. + +OUI:001E70* + ID_OUI_FROM_DATABASE=Cobham Antenna Systems + +OUI:001E71* + ID_OUI_FROM_DATABASE=MIrcom Group of Companies + +OUI:001E72* + ID_OUI_FROM_DATABASE=PCS + +OUI:001E73* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:001E74* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:001E75* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:001E76* + ID_OUI_FROM_DATABASE=Thermo Fisher Scientific + +OUI:001E77* + ID_OUI_FROM_DATABASE=Air2App + +OUI:001E78* + ID_OUI_FROM_DATABASE=Owitek Technology Ltd., + +OUI:001E79* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001E7A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001E7B* + ID_OUI_FROM_DATABASE=R.I.CO. S.r.l. + +OUI:001E7C* + ID_OUI_FROM_DATABASE=Taiwick Limited + +OUI:001E7D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001E7E* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001E7F* + ID_OUI_FROM_DATABASE=CBM of America + +OUI:001E80* + ID_OUI_FROM_DATABASE=Icotera A/S + +OUI:001E81* + ID_OUI_FROM_DATABASE=CNB Technology Inc. + +OUI:001E82* + ID_OUI_FROM_DATABASE=SanDisk Corporation + +OUI:001E83* + ID_OUI_FROM_DATABASE=LAN/MAN Standards Association (LMSC) + +OUI:001E84* + ID_OUI_FROM_DATABASE=Pika Technologies Inc. + +OUI:001E85* + ID_OUI_FROM_DATABASE=Lagotek Corporation + +OUI:001E86* + ID_OUI_FROM_DATABASE=MEL Co.,Ltd. + +OUI:001E87* + ID_OUI_FROM_DATABASE=Realease Limited + +OUI:001E88* + ID_OUI_FROM_DATABASE=ANDOR SYSTEM SUPPORT CO., LTD. + +OUI:001E89* + ID_OUI_FROM_DATABASE=CRFS Limited + +OUI:001E8A* + ID_OUI_FROM_DATABASE=eCopy, Inc + +OUI:001E8B* + ID_OUI_FROM_DATABASE=Infra Access Korea Co., Ltd. + +OUI:001E8C* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:001E8D* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001E8E* + ID_OUI_FROM_DATABASE=Hunkeler AG + +OUI:001E8F* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:001E90* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:001E91* + ID_OUI_FROM_DATABASE=KIMIN Electronic Co., Ltd. + +OUI:001E92* + ID_OUI_FROM_DATABASE=JEULIN S.A. + +OUI:001E93* + ID_OUI_FROM_DATABASE=CiriTech Systems Inc + +OUI:001E94* + ID_OUI_FROM_DATABASE=SUPERCOM TECHNOLOGY CORPORATION + +OUI:001E95* + ID_OUI_FROM_DATABASE=SIGMALINK + +OUI:001E96* + ID_OUI_FROM_DATABASE=Sepura Plc + +OUI:001E97* + ID_OUI_FROM_DATABASE=Medium Link System Technology CO., LTD, + +OUI:001E98* + ID_OUI_FROM_DATABASE=GreenLine Communications + +OUI:001E99* + ID_OUI_FROM_DATABASE=Vantanol Industrial Corporation + +OUI:001E9A* + ID_OUI_FROM_DATABASE=HAMILTON Bonaduz AG + +OUI:001E9B* + ID_OUI_FROM_DATABASE=San-Eisha, Ltd. + +OUI:001E9C* + ID_OUI_FROM_DATABASE=Fidustron INC + +OUI:001E9D* + ID_OUI_FROM_DATABASE=Recall Technologies, Inc. + +OUI:001E9E* + ID_OUI_FROM_DATABASE=ddm hopt + schuler Gmbh + Co. KG + +OUI:001E9F* + ID_OUI_FROM_DATABASE=Visioneering Systems, Inc. + +OUI:001EA0* + ID_OUI_FROM_DATABASE=XLN-t + +OUI:001EA1* + ID_OUI_FROM_DATABASE=Brunata a/s + +OUI:001EA2* + ID_OUI_FROM_DATABASE=Symx Systems, Inc. + +OUI:001EA3* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001EA4* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001EA5* + ID_OUI_FROM_DATABASE=ROBOTOUS, Inc. + +OUI:001EA6* + ID_OUI_FROM_DATABASE=Best IT World (India) Pvt. Ltd. + +OUI:001EA7* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:001EA8* + ID_OUI_FROM_DATABASE=Datang Mobile Communications Equipment CO.,LTD + +OUI:001EA9* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:001EAA* + ID_OUI_FROM_DATABASE=E-Senza Technologies GmbH + +OUI:001EAB* + ID_OUI_FROM_DATABASE=TeleWell Oy + +OUI:001EAC* + ID_OUI_FROM_DATABASE=Armadeus Systems + +OUI:001EAD* + ID_OUI_FROM_DATABASE=Wingtech Group Limited + +OUI:001EAE* + ID_OUI_FROM_DATABASE=Continental Automotive Systems Inc. + +OUI:001EAF* + ID_OUI_FROM_DATABASE=Ophir Optronics Ltd + +OUI:001EB0* + ID_OUI_FROM_DATABASE=ImesD Electronica S.L. + +OUI:001EB1* + ID_OUI_FROM_DATABASE=Cryptsoft Pty Ltd + +OUI:001EB2* + ID_OUI_FROM_DATABASE=LG innotek + +OUI:001EB3* + ID_OUI_FROM_DATABASE=Primex Wireless + +OUI:001EB4* + ID_OUI_FROM_DATABASE=UNIFAT TECHNOLOGY LTD. + +OUI:001EB5* + ID_OUI_FROM_DATABASE=Ever Sparkle Technologies Ltd + +OUI:001EB6* + ID_OUI_FROM_DATABASE=TAG Heuer SA + +OUI:001EB7* + ID_OUI_FROM_DATABASE=TBTech, Co., Ltd. + +OUI:001EB8* + ID_OUI_FROM_DATABASE=Aloys, Inc + +OUI:001EB9* + ID_OUI_FROM_DATABASE=Sing Fai Technology Limited + +OUI:001EBA* + ID_OUI_FROM_DATABASE=High Density Devices AS + +OUI:001EBB* + ID_OUI_FROM_DATABASE=BLUELIGHT TECHNOLOGY INC. + +OUI:001EBC* + ID_OUI_FROM_DATABASE=WINTECH AUTOMATION CO.,LTD. + +OUI:001EBD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001EBE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001EBF* + ID_OUI_FROM_DATABASE=Haas Automation Inc. + +OUI:001EC0* + ID_OUI_FROM_DATABASE=Microchip Technology Inc. + +OUI:001EC1* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:001EC2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001EC3* + ID_OUI_FROM_DATABASE=Kozio, Inc. + +OUI:001EC4* + ID_OUI_FROM_DATABASE=Celio Corp + +OUI:001EC5* + ID_OUI_FROM_DATABASE=Middle Atlantic Products Inc + +OUI:001EC6* + ID_OUI_FROM_DATABASE=Obvius Holdings LLC + +OUI:001EC7* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:001EC8* + ID_OUI_FROM_DATABASE=Rapid Mobile (Pty) Ltd + +OUI:001EC9* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:001ECA* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001ECB* + ID_OUI_FROM_DATABASE=RPC Energoautomatika Ltd + +OUI:001ECC* + ID_OUI_FROM_DATABASE=CDVI + +OUI:001ECD* + ID_OUI_FROM_DATABASE=KYLAND Technology Co. LTD + +OUI:001ECE* + ID_OUI_FROM_DATABASE=BISA Technologies (Hong Kong) Limited + +OUI:001ECF* + ID_OUI_FROM_DATABASE=PHILIPS ELECTRONICS UK LTD + +OUI:001ED0* + ID_OUI_FROM_DATABASE=Ingespace + +OUI:001ED1* + ID_OUI_FROM_DATABASE=Keyprocessor B.V. + +OUI:001ED2* + ID_OUI_FROM_DATABASE=Ray Shine Video Technology Inc + +OUI:001ED3* + ID_OUI_FROM_DATABASE=Dot Technology Int'l Co., Ltd. + +OUI:001ED4* + ID_OUI_FROM_DATABASE=Doble Engineering + +OUI:001ED5* + ID_OUI_FROM_DATABASE=Tekon-Automatics + +OUI:001ED6* + ID_OUI_FROM_DATABASE=Alentec & Orion AB + +OUI:001ED7* + ID_OUI_FROM_DATABASE=H-Stream Wireless, Inc. + +OUI:001ED8* + ID_OUI_FROM_DATABASE=Digital United Inc. + +OUI:001ED9* + ID_OUI_FROM_DATABASE=Mitsubishi Precision Co.,LTd. + +OUI:001EDA* + ID_OUI_FROM_DATABASE=Wesemann Elektrotechniek B.V. + +OUI:001EDB* + ID_OUI_FROM_DATABASE=Giken Trastem Co., Ltd. + +OUI:001EDC* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:001EDD* + ID_OUI_FROM_DATABASE=WASKO S.A. + +OUI:001EDE* + ID_OUI_FROM_DATABASE=BYD COMPANY LIMITED + +OUI:001EDF* + ID_OUI_FROM_DATABASE=Master Industrialization Center Kista + +OUI:001EE0* + ID_OUI_FROM_DATABASE=Urmet Domus SpA + +OUI:001EE1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001EE2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001EE3* + ID_OUI_FROM_DATABASE=T&W Electronics (ShenZhen) Co.,Ltd + +OUI:001EE4* + ID_OUI_FROM_DATABASE=ACS Solutions France + +OUI:001EE5* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:001EE6* + ID_OUI_FROM_DATABASE=Shenzhen Advanced Video Info-Tech Co., Ltd. + +OUI:001EE7* + ID_OUI_FROM_DATABASE=Epic Systems Inc + +OUI:001EE8* + ID_OUI_FROM_DATABASE=Mytek + +OUI:001EE9* + ID_OUI_FROM_DATABASE=Stoneridge Electronics AB + +OUI:001EEA* + ID_OUI_FROM_DATABASE=Sensor Switch, Inc. + +OUI:001EEB* + ID_OUI_FROM_DATABASE=Talk-A-Phone Co. + +OUI:001EEC* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:001EED* + ID_OUI_FROM_DATABASE=Adventiq Ltd. + +OUI:001EEE* + ID_OUI_FROM_DATABASE=ETL Systems Ltd + +OUI:001EEF* + ID_OUI_FROM_DATABASE=Cantronic International Limited + +OUI:001EF0* + ID_OUI_FROM_DATABASE=Gigafin Networks + +OUI:001EF1* + ID_OUI_FROM_DATABASE=Servimat + +OUI:001EF2* + ID_OUI_FROM_DATABASE=Micro Motion Inc + +OUI:001EF3* + ID_OUI_FROM_DATABASE=From2 + +OUI:001EF4* + ID_OUI_FROM_DATABASE=L-3 Communications Display Systems + +OUI:001EF5* + ID_OUI_FROM_DATABASE=Hitek Automated Inc. + +OUI:001EF6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001EF7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001EF8* + ID_OUI_FROM_DATABASE=Emfinity Inc. + +OUI:001EF9* + ID_OUI_FROM_DATABASE=Pascom Kommunikations systeme GmbH. + +OUI:001EFA* + ID_OUI_FROM_DATABASE=PROTEI Ltd. + +OUI:001EFB* + ID_OUI_FROM_DATABASE=Trio Motion Technology Ltd + +OUI:001EFC* + ID_OUI_FROM_DATABASE=JSC MASSA-K + +OUI:001EFD* + ID_OUI_FROM_DATABASE=Microbit 2.0 AB + +OUI:001EFE* + ID_OUI_FROM_DATABASE=LEVEL s.r.o. + +OUI:001EFF* + ID_OUI_FROM_DATABASE=Mueller-Elektronik GmbH & Co. KG + +OUI:001F00* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001F01* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001F02* + ID_OUI_FROM_DATABASE=Pixelmetrix Corporation Pte Ltd + +OUI:001F03* + ID_OUI_FROM_DATABASE=NUM AG + +OUI:001F04* + ID_OUI_FROM_DATABASE=Granch Ltd. + +OUI:001F05* + ID_OUI_FROM_DATABASE=iTAS Technology Corp. + +OUI:001F06* + ID_OUI_FROM_DATABASE=Integrated Dispatch Solutions + +OUI:001F07* + ID_OUI_FROM_DATABASE=AZTEQ Mobile + +OUI:001F08* + ID_OUI_FROM_DATABASE=RISCO LTD + +OUI:001F09* + ID_OUI_FROM_DATABASE=Jastec + +OUI:001F0A* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001F0B* + ID_OUI_FROM_DATABASE=Federal State Unitary Enterprise Industrial UnionElectropribor + +OUI:001F0C* + ID_OUI_FROM_DATABASE=Intelligent Digital Services GmbH + +OUI:001F0D* + ID_OUI_FROM_DATABASE=L3 Communications - Telemetry West + +OUI:001F0E* + ID_OUI_FROM_DATABASE=Japan Kyastem Co., Ltd + +OUI:001F0F* + ID_OUI_FROM_DATABASE=Select Engineered Systems + +OUI:001F10* + ID_OUI_FROM_DATABASE=TOLEDO DO BRASIL INDUSTRIA DE BALANCAS LTDA + +OUI:001F11* + ID_OUI_FROM_DATABASE=OPENMOKO, INC. + +OUI:001F12* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:001F13* + ID_OUI_FROM_DATABASE=S.& A.S. Ltd. + +OUI:001F14* + ID_OUI_FROM_DATABASE=NexG + +OUI:001F15* + ID_OUI_FROM_DATABASE=Bioscrypt Inc + +OUI:001F16* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:001F17* + ID_OUI_FROM_DATABASE=IDX Company, Ltd. + +OUI:001F18* + ID_OUI_FROM_DATABASE=Hakusan.Mfg.Co,.Ltd + +OUI:001F19* + ID_OUI_FROM_DATABASE=BEN-RI ELECTRONICA S.A. + +OUI:001F1A* + ID_OUI_FROM_DATABASE=Prominvest + +OUI:001F1B* + ID_OUI_FROM_DATABASE=RoyalTek Company Ltd. + +OUI:001F1C* + ID_OUI_FROM_DATABASE=KOBISHI ELECTRIC Co.,Ltd. + +OUI:001F1D* + ID_OUI_FROM_DATABASE=Atlas Material Testing Technology LLC + +OUI:001F1E* + ID_OUI_FROM_DATABASE=Astec Technology Co., Ltd + +OUI:001F1F* + ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. + +OUI:001F20* + ID_OUI_FROM_DATABASE=Logitech Europe SA + +OUI:001F21* + ID_OUI_FROM_DATABASE=Inner Mongolia Yin An Science & Technology Development Co.,L + +OUI:001F22* + ID_OUI_FROM_DATABASE=Source Photonics, Inc. + +OUI:001F23* + ID_OUI_FROM_DATABASE=Interacoustics + +OUI:001F24* + ID_OUI_FROM_DATABASE=DIGITVIEW TECHNOLOGY CO., LTD. + +OUI:001F25* + ID_OUI_FROM_DATABASE=MBS GmbH + +OUI:001F26* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001F27* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001F28* + ID_OUI_FROM_DATABASE=HPN Supply Chain + +OUI:001F29* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:001F2A* + ID_OUI_FROM_DATABASE=ACCM + +OUI:001F2B* + ID_OUI_FROM_DATABASE=Orange Logic + +OUI:001F2C* + ID_OUI_FROM_DATABASE=Starbridge Networks + +OUI:001F2D* + ID_OUI_FROM_DATABASE=Electro-Optical Imaging, Inc. + +OUI:001F2E* + ID_OUI_FROM_DATABASE=Triangle Research Int'l Pte Ltd + +OUI:001F2F* + ID_OUI_FROM_DATABASE=Berker GmbH & Co. KG + +OUI:001F30* + ID_OUI_FROM_DATABASE=Travelping + +OUI:001F31* + ID_OUI_FROM_DATABASE=Radiocomp + +OUI:001F32* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:001F33* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:001F34* + ID_OUI_FROM_DATABASE=Lung Hwa Electronics Co., Ltd. + +OUI:001F35* + ID_OUI_FROM_DATABASE=AIR802 LLC + +OUI:001F36* + ID_OUI_FROM_DATABASE=Bellwin Information Co. Ltd., + +OUI:001F37* + ID_OUI_FROM_DATABASE=Genesis I&C + +OUI:001F38* + ID_OUI_FROM_DATABASE=POSITRON + +OUI:001F39* + ID_OUI_FROM_DATABASE=Construcciones y Auxiliar de Ferrocarriles, S.A. + +OUI:001F3A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:001F3B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001F3C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:001F3D* + ID_OUI_FROM_DATABASE=Qbit GmbH + +OUI:001F3E* + ID_OUI_FROM_DATABASE=RP-Technik e.K. + +OUI:001F3F* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:001F40* + ID_OUI_FROM_DATABASE=Speakercraft Inc. + +OUI:001F41* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:001F42* + ID_OUI_FROM_DATABASE=Etherstack plc + +OUI:001F43* + ID_OUI_FROM_DATABASE=ENTES ELEKTRONIK + +OUI:001F44* + ID_OUI_FROM_DATABASE=GE Transportation Systems + +OUI:001F45* + ID_OUI_FROM_DATABASE=Enterasys + +OUI:001F46* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001F47* + ID_OUI_FROM_DATABASE=MCS Logic Inc. + +OUI:001F48* + ID_OUI_FROM_DATABASE=Mojix Inc. + +OUI:001F49* + ID_OUI_FROM_DATABASE=Manhattan TV Ltd + +OUI:001F4A* + ID_OUI_FROM_DATABASE=Albentia Systems S.A. + +OUI:001F4B* + ID_OUI_FROM_DATABASE=Lineage Power + +OUI:001F4C* + ID_OUI_FROM_DATABASE=Roseman Engineering Ltd + +OUI:001F4D* + ID_OUI_FROM_DATABASE=Segnetics LLC + +OUI:001F4E* + ID_OUI_FROM_DATABASE=ConMed Linvatec + +OUI:001F4F* + ID_OUI_FROM_DATABASE=Thinkware Co. Ltd. + +OUI:001F50* + ID_OUI_FROM_DATABASE=Swissdis AG + +OUI:001F51* + ID_OUI_FROM_DATABASE=HD Communications Corp + +OUI:001F52* + ID_OUI_FROM_DATABASE=UVT Unternehmensberatung fur Verkehr und Technik GmbH + +OUI:001F53* + ID_OUI_FROM_DATABASE=GEMAC Chemnitz GmbH + +OUI:001F54* + ID_OUI_FROM_DATABASE=Lorex Technology Inc. + +OUI:001F55* + ID_OUI_FROM_DATABASE=Honeywell Security (China) Co., Ltd. + +OUI:001F56* + ID_OUI_FROM_DATABASE=DIGITAL FORECAST + +OUI:001F57* + ID_OUI_FROM_DATABASE=Phonik Innovation Co.,LTD + +OUI:001F58* + ID_OUI_FROM_DATABASE=EMH Energiemesstechnik GmbH + +OUI:001F59* + ID_OUI_FROM_DATABASE=Kronback Tracers + +OUI:001F5A* + ID_OUI_FROM_DATABASE=Beckwith Electric Co. + +OUI:001F5B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001F5C* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001F5D* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001F5E* + ID_OUI_FROM_DATABASE=Dyna Technology Co.,Ltd. + +OUI:001F5F* + ID_OUI_FROM_DATABASE=Blatand GmbH + +OUI:001F60* + ID_OUI_FROM_DATABASE=COMPASS SYSTEMS CORP. + +OUI:001F61* + ID_OUI_FROM_DATABASE=Talent Communication Networks Inc. + +OUI:001F62* + ID_OUI_FROM_DATABASE=JSC Stilsoft + +OUI:001F63* + ID_OUI_FROM_DATABASE=JSC Goodwin-Europa + +OUI:001F64* + ID_OUI_FROM_DATABASE=Beijing Autelan Technology Inc. + +OUI:001F65* + ID_OUI_FROM_DATABASE=KOREA ELECTRIC TERMINAL CO., LTD. + +OUI:001F66* + ID_OUI_FROM_DATABASE=PLANAR LLC + +OUI:001F67* + ID_OUI_FROM_DATABASE=Hitachi,Ltd. + +OUI:001F68* + ID_OUI_FROM_DATABASE=Martinsson Elektronik AB + +OUI:001F69* + ID_OUI_FROM_DATABASE=Pingood Technology Co., Ltd. + +OUI:001F6A* + ID_OUI_FROM_DATABASE=PacketFlux Technologies, Inc. + +OUI:001F6B* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:001F6C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001F6D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001F6E* + ID_OUI_FROM_DATABASE=Vtech Engineering Corporation + +OUI:001F6F* + ID_OUI_FROM_DATABASE=Fujian Sunnada Communication Co.,Ltd. + +OUI:001F70* + ID_OUI_FROM_DATABASE=Botik Technologies LTD + +OUI:001F71* + ID_OUI_FROM_DATABASE=xG Technology, Inc. + +OUI:001F72* + ID_OUI_FROM_DATABASE=QingDao Hiphone Technology Co,.Ltd + +OUI:001F73* + ID_OUI_FROM_DATABASE=Teraview Technology Co., Ltd. + +OUI:001F74* + ID_OUI_FROM_DATABASE=Eigen Development + +OUI:001F75* + ID_OUI_FROM_DATABASE=GiBahn Media + +OUI:001F76* + ID_OUI_FROM_DATABASE=AirLogic Systems Inc. + +OUI:001F77* + ID_OUI_FROM_DATABASE=HEOL DESIGN + +OUI:001F78* + ID_OUI_FROM_DATABASE=Blue Fox Porini Textile + +OUI:001F79* + ID_OUI_FROM_DATABASE=Lodam Electronics A/S + +OUI:001F7A* + ID_OUI_FROM_DATABASE=WiWide Inc. + +OUI:001F7B* + ID_OUI_FROM_DATABASE=TechNexion Ltd. + +OUI:001F7C* + ID_OUI_FROM_DATABASE=Witelcom AS + +OUI:001F7D* + ID_OUI_FROM_DATABASE=Embedded Wireless GmbH + +OUI:001F7E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001F7F* + ID_OUI_FROM_DATABASE=Phabrix Limited + +OUI:001F80* + ID_OUI_FROM_DATABASE=Lucas Holding bv + +OUI:001F81* + ID_OUI_FROM_DATABASE=Accel Semiconductor Corp + +OUI:001F82* + ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Company Ltd. + +OUI:001F83* + ID_OUI_FROM_DATABASE=Teleplan Technology Services Sdn Bhd + +OUI:001F84* + ID_OUI_FROM_DATABASE=Gigle Semiconductor + +OUI:001F85* + ID_OUI_FROM_DATABASE=Apriva ISS, LLC + +OUI:001F86* + ID_OUI_FROM_DATABASE=digEcor + +OUI:001F87* + ID_OUI_FROM_DATABASE=Skydigital Inc. + +OUI:001F88* + ID_OUI_FROM_DATABASE=FMS Force Measuring Systems AG + +OUI:001F89* + ID_OUI_FROM_DATABASE=Signalion GmbH + +OUI:001F8A* + ID_OUI_FROM_DATABASE=Ellion Digital Inc. + +OUI:001F8B* + ID_OUI_FROM_DATABASE=Cache IQ + +OUI:001F8C* + ID_OUI_FROM_DATABASE=CCS Inc. + +OUI:001F8D* + ID_OUI_FROM_DATABASE=Ingenieurbuero Stark GmbH und Ko. KG + +OUI:001F8E* + ID_OUI_FROM_DATABASE=Metris USA Inc. + +OUI:001F8F* + ID_OUI_FROM_DATABASE=Shanghai Bellmann Digital Source Co.,Ltd. + +OUI:001F90* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:001F91* + ID_OUI_FROM_DATABASE=DBS Lodging Technologies, LLC + +OUI:001F92* + ID_OUI_FROM_DATABASE=Avigilon Corporation + +OUI:001F93* + ID_OUI_FROM_DATABASE=Xiotech Corporation + +OUI:001F94* + ID_OUI_FROM_DATABASE=Lascar Electronics Ltd + +OUI:001F95* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:001F96* + ID_OUI_FROM_DATABASE=APROTECH CO.LTD + +OUI:001F97* + ID_OUI_FROM_DATABASE=BERTANA srl + +OUI:001F98* + ID_OUI_FROM_DATABASE=DAIICHI-DENTSU LTD. + +OUI:001F99* + ID_OUI_FROM_DATABASE=SERONICS co.ltd + +OUI:001F9A* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001F9B* + ID_OUI_FROM_DATABASE=POSBRO + +OUI:001F9C* + ID_OUI_FROM_DATABASE=LEDCO + +OUI:001F9D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001F9E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001F9F* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium + +OUI:001FA0* + ID_OUI_FROM_DATABASE=A10 Networks + +OUI:001FA1* + ID_OUI_FROM_DATABASE=Gtran Inc + +OUI:001FA2* + ID_OUI_FROM_DATABASE=Datron World Communications, Inc. + +OUI:001FA3* + ID_OUI_FROM_DATABASE=T&W Electronics(Shenzhen)Co.,Ltd. + +OUI:001FA4* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:001FA5* + ID_OUI_FROM_DATABASE=Blue-White Industries + +OUI:001FA6* + ID_OUI_FROM_DATABASE=Stilo srl + +OUI:001FA7* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:001FA8* + ID_OUI_FROM_DATABASE=Smart Energy Instruments Inc. + +OUI:001FA9* + ID_OUI_FROM_DATABASE=Atlanta DTH, Inc. + +OUI:001FAA* + ID_OUI_FROM_DATABASE=Taseon, Inc. + +OUI:001FAB* + ID_OUI_FROM_DATABASE=I.S HIGH TECH.INC + +OUI:001FAC* + ID_OUI_FROM_DATABASE=Goodmill Systems Ltd + +OUI:001FAD* + ID_OUI_FROM_DATABASE=Brown Innovations, Inc + +OUI:001FAE* + ID_OUI_FROM_DATABASE=Blick South Africa (Pty) Ltd + +OUI:001FAF* + ID_OUI_FROM_DATABASE=NextIO, Inc. + +OUI:001FB0* + ID_OUI_FROM_DATABASE=TimeIPS, Inc. + +OUI:001FB1* + ID_OUI_FROM_DATABASE=Cybertech Inc. + +OUI:001FB2* + ID_OUI_FROM_DATABASE=Sontheim Industrie Elektronik GmbH + +OUI:001FB3* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:001FB4* + ID_OUI_FROM_DATABASE=SmartShare Systems + +OUI:001FB5* + ID_OUI_FROM_DATABASE=I/O Interconnect Inc. + +OUI:001FB6* + ID_OUI_FROM_DATABASE=Chi Lin Technology Co., Ltd. + +OUI:001FB7* + ID_OUI_FROM_DATABASE=WiMate Technologies Corp. + +OUI:001FB8* + ID_OUI_FROM_DATABASE=Universal Remote Control, Inc. + +OUI:001FB9* + ID_OUI_FROM_DATABASE=Paltronics + +OUI:001FBA* + ID_OUI_FROM_DATABASE=Boyoung Tech + +OUI:001FBB* + ID_OUI_FROM_DATABASE=Xenatech Co.,LTD + +OUI:001FBC* + ID_OUI_FROM_DATABASE=EVGA Corporation + +OUI:001FBD* + ID_OUI_FROM_DATABASE=Kyocera Wireless Corp. + +OUI:001FBE* + ID_OUI_FROM_DATABASE=Shenzhen Mopnet Industrial Co.,Ltd + +OUI:001FBF* + ID_OUI_FROM_DATABASE=Fulhua Microelectronics Corp. Taiwan Branch + +OUI:001FC0* + ID_OUI_FROM_DATABASE=Control Express Finland Oy + +OUI:001FC1* + ID_OUI_FROM_DATABASE=Hanlong Technology Co.,LTD + +OUI:001FC2* + ID_OUI_FROM_DATABASE=Jow Tong Technology Co Ltd + +OUI:001FC3* + ID_OUI_FROM_DATABASE=SmartSynch, Inc + +OUI:001FC4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:001FC5* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:001FC6* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:001FC7* + ID_OUI_FROM_DATABASE=Casio Hitachi Mobile Communications Co., Ltd. + +OUI:001FC8* + ID_OUI_FROM_DATABASE=Up-Today Industrial Co., Ltd. + +OUI:001FC9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001FCA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:001FCB* + ID_OUI_FROM_DATABASE=NIW Solutions + +OUI:001FCC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001FCD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:001FCE* + ID_OUI_FROM_DATABASE=QTECH LLC + +OUI:001FCF* + ID_OUI_FROM_DATABASE=MSI Technology GmbH + +OUI:001FD0* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:001FD1* + ID_OUI_FROM_DATABASE=OPTEX CO.,LTD. + +OUI:001FD2* + ID_OUI_FROM_DATABASE=COMMTECH TECHNOLOGY MACAO COMMERCIAL OFFSHORE LTD. + +OUI:001FD3* + ID_OUI_FROM_DATABASE=RIVA Networks Inc. + +OUI:001FD4* + ID_OUI_FROM_DATABASE=4IPNET, INC. + +OUI:001FD5* + ID_OUI_FROM_DATABASE=MICRORISC s.r.o. + +OUI:001FD6* + ID_OUI_FROM_DATABASE=Shenzhen Allywll + +OUI:001FD7* + ID_OUI_FROM_DATABASE=TELERAD SA + +OUI:001FD8* + ID_OUI_FROM_DATABASE=A-TRUST COMPUTER CORPORATION + +OUI:001FD9* + ID_OUI_FROM_DATABASE=RSD Communications Ltd + +OUI:001FDA* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:001FDB* + ID_OUI_FROM_DATABASE=Network Supply Corp., + +OUI:001FDC* + ID_OUI_FROM_DATABASE=Mobile Safe Track Ltd + +OUI:001FDD* + ID_OUI_FROM_DATABASE=GDI LLC + +OUI:001FDE* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001FDF* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:001FE0* + ID_OUI_FROM_DATABASE=EdgeVelocity Corp + +OUI:001FE1* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:001FE2* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:001FE3* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:001FE4* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:001FE5* + ID_OUI_FROM_DATABASE=In-Circuit GmbH + +OUI:001FE6* + ID_OUI_FROM_DATABASE=Alphion Corporation + +OUI:001FE7* + ID_OUI_FROM_DATABASE=Simet + +OUI:001FE8* + ID_OUI_FROM_DATABASE=KURUSUGAWA Electronics Industry Inc,. + +OUI:001FE9* + ID_OUI_FROM_DATABASE=Printrex, Inc. + +OUI:001FEA* + ID_OUI_FROM_DATABASE=Applied Media Technologies Corporation + +OUI:001FEB* + ID_OUI_FROM_DATABASE=Trio Datacom Pty Ltd + +OUI:001FEC* + ID_OUI_FROM_DATABASE=Synapse Électronique + +OUI:001FED* + ID_OUI_FROM_DATABASE=Tecan Systems Inc. + +OUI:001FEE* + ID_OUI_FROM_DATABASE=ubisys technologies GmbH + +OUI:001FEF* + ID_OUI_FROM_DATABASE=SHINSEI INDUSTRIES CO.,LTD + +OUI:001FF0* + ID_OUI_FROM_DATABASE=Audio Partnership + +OUI:001FF1* + ID_OUI_FROM_DATABASE=Paradox Hellas S.A. + +OUI:001FF2* + ID_OUI_FROM_DATABASE=VIA Technologies, Inc. + +OUI:001FF3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:001FF4* + ID_OUI_FROM_DATABASE=Power Monitors, Inc. + +OUI:001FF5* + ID_OUI_FROM_DATABASE=Kongsberg Defence & Aerospace + +OUI:001FF6* + ID_OUI_FROM_DATABASE=PS Audio International + +OUI:001FF7* + ID_OUI_FROM_DATABASE=Nakajima All Precision Co., Ltd. + +OUI:001FF8* + ID_OUI_FROM_DATABASE=Siemens AG, Sector Industry, Drive Technologies, Motion Control Systems + +OUI:001FF9* + ID_OUI_FROM_DATABASE=Advanced Knowledge Associates + +OUI:001FFA* + ID_OUI_FROM_DATABASE=Coretree, Co, Ltd + +OUI:001FFB* + ID_OUI_FROM_DATABASE=Green Packet Bhd + +OUI:001FFC* + ID_OUI_FROM_DATABASE=Riccius+Sohn GmbH + +OUI:001FFD* + ID_OUI_FROM_DATABASE=Indigo Mobile Technologies Corp. + +OUI:001FFE* + ID_OUI_FROM_DATABASE=HPN Supply Chain + +OUI:001FFF* + ID_OUI_FROM_DATABASE=Respironics, Inc. + +OUI:002000* + ID_OUI_FROM_DATABASE=LEXMARK INTERNATIONAL, INC. + +OUI:002001* + ID_OUI_FROM_DATABASE=DSP SOLUTIONS, INC. + +OUI:002002* + ID_OUI_FROM_DATABASE=SERITECH ENTERPRISE CO., LTD. + +OUI:002003* + ID_OUI_FROM_DATABASE=PIXEL POWER LTD. + +OUI:002004* + ID_OUI_FROM_DATABASE=YAMATAKE-HONEYWELL CO., LTD. + +OUI:002005* + ID_OUI_FROM_DATABASE=SIMPLE TECHNOLOGY + +OUI:002006* + ID_OUI_FROM_DATABASE=GARRETT COMMUNICATIONS, INC. + +OUI:002007* + ID_OUI_FROM_DATABASE=SFA, INC. + +OUI:002008* + ID_OUI_FROM_DATABASE=CABLE & COMPUTER TECHNOLOGY + +OUI:002009* + ID_OUI_FROM_DATABASE=PACKARD BELL ELEC., INC. + +OUI:00200A* + ID_OUI_FROM_DATABASE=SOURCE-COMM CORP. + +OUI:00200B* + ID_OUI_FROM_DATABASE=OCTAGON SYSTEMS CORP. + +OUI:00200C* + ID_OUI_FROM_DATABASE=ADASTRA SYSTEMS CORP. + +OUI:00200D* + ID_OUI_FROM_DATABASE=CARL ZEISS + +OUI:00200E* + ID_OUI_FROM_DATABASE=NSSLGlobal Technologies AS + +OUI:00200F* + ID_OUI_FROM_DATABASE=EBRAINS Inc + +OUI:002010* + ID_OUI_FROM_DATABASE=JEOL SYSTEM TECHNOLOGY CO. LTD + +OUI:002011* + ID_OUI_FROM_DATABASE=CANOPUS CO., LTD. + +OUI:002012* + ID_OUI_FROM_DATABASE=CAMTRONICS MEDICAL SYSTEMS + +OUI:002013* + ID_OUI_FROM_DATABASE=DIVERSIFIED TECHNOLOGY, INC. + +OUI:002014* + ID_OUI_FROM_DATABASE=GLOBAL VIEW CO., LTD. + +OUI:002015* + ID_OUI_FROM_DATABASE=ACTIS COMPUTER SA + +OUI:002016* + ID_OUI_FROM_DATABASE=SHOWA ELECTRIC WIRE & CABLE CO + +OUI:002017* + ID_OUI_FROM_DATABASE=ORBOTECH + +OUI:002018* + ID_OUI_FROM_DATABASE=CIS TECHNOLOGY INC. + +OUI:002019* + ID_OUI_FROM_DATABASE=OHLER GMBH + +OUI:00201A* + ID_OUI_FROM_DATABASE=MRV Communications, Inc. + +OUI:00201B* + ID_OUI_FROM_DATABASE=NORTHERN TELECOM/NETWORK + +OUI:00201C* + ID_OUI_FROM_DATABASE=EXCEL, INC. + +OUI:00201D* + ID_OUI_FROM_DATABASE=KATANA PRODUCTS + +OUI:00201E* + ID_OUI_FROM_DATABASE=NETQUEST CORPORATION + +OUI:00201F* + ID_OUI_FROM_DATABASE=BEST POWER TECHNOLOGY, INC. + +OUI:002020* + ID_OUI_FROM_DATABASE=MEGATRON COMPUTER INDUSTRIES PTY, LTD. + +OUI:002021* + ID_OUI_FROM_DATABASE=ALGORITHMS SOFTWARE PVT. LTD. + +OUI:002022* + ID_OUI_FROM_DATABASE=NMS Communications + +OUI:002023* + ID_OUI_FROM_DATABASE=T.C. TECHNOLOGIES PTY. LTD + +OUI:002024* + ID_OUI_FROM_DATABASE=PACIFIC COMMUNICATION SCIENCES + +OUI:002025* + ID_OUI_FROM_DATABASE=CONTROL TECHNOLOGY, INC. + +OUI:002026* + ID_OUI_FROM_DATABASE=AMKLY SYSTEMS, INC. + +OUI:002027* + ID_OUI_FROM_DATABASE=MING FORTUNE INDUSTRY CO., LTD + +OUI:002028* + ID_OUI_FROM_DATABASE=WEST EGG SYSTEMS, INC. + +OUI:002029* + ID_OUI_FROM_DATABASE=TELEPROCESSING PRODUCTS, INC. + +OUI:00202A* + ID_OUI_FROM_DATABASE=N.V. DZINE + +OUI:00202B* + ID_OUI_FROM_DATABASE=ADVANCED TELECOMMUNICATIONS MODULES, LTD. + +OUI:00202C* + ID_OUI_FROM_DATABASE=WELLTRONIX CO., LTD. + +OUI:00202D* + ID_OUI_FROM_DATABASE=TAIYO CORPORATION + +OUI:00202E* + ID_OUI_FROM_DATABASE=DAYSTAR DIGITAL + +OUI:00202F* + ID_OUI_FROM_DATABASE=ZETA COMMUNICATIONS, LTD. + +OUI:002030* + ID_OUI_FROM_DATABASE=ANALOG & DIGITAL SYSTEMS + +OUI:002031* + ID_OUI_FROM_DATABASE=Tattile SRL + +OUI:002032* + ID_OUI_FROM_DATABASE=ALCATEL TAISEL + +OUI:002033* + ID_OUI_FROM_DATABASE=SYNAPSE TECHNOLOGIES, INC. + +OUI:002034* + ID_OUI_FROM_DATABASE=ROTEC INDUSTRIEAUTOMATION GMBH + +OUI:002035* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:002036* + ID_OUI_FROM_DATABASE=BMC SOFTWARE + +OUI:002037* + ID_OUI_FROM_DATABASE=Seagate Technology + +OUI:002038* + ID_OUI_FROM_DATABASE=VME MICROSYSTEMS INTERNATIONAL CORPORATION + +OUI:002039* + ID_OUI_FROM_DATABASE=SCINETS + +OUI:00203A* + ID_OUI_FROM_DATABASE=DIGITAL BI0METRICS INC. + +OUI:00203B* + ID_OUI_FROM_DATABASE=WISDM LTD. + +OUI:00203C* + ID_OUI_FROM_DATABASE=EUROTIME AB + +OUI:00203D* + ID_OUI_FROM_DATABASE=Honeywell Environmental & Combustion Controls + +OUI:00203E* + ID_OUI_FROM_DATABASE=LogiCan Technologies, Inc. + +OUI:00203F* + ID_OUI_FROM_DATABASE=JUKI CORPORATION + +OUI:002040* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002041* + ID_OUI_FROM_DATABASE=DATA NET + +OUI:002042* + ID_OUI_FROM_DATABASE=DATAMETRICS CORP. + +OUI:002043* + ID_OUI_FROM_DATABASE=NEURON COMPANY LIMITED + +OUI:002044* + ID_OUI_FROM_DATABASE=GENITECH PTY LTD + +OUI:002045* + ID_OUI_FROM_DATABASE=ION Networks, Inc. + +OUI:002046* + ID_OUI_FROM_DATABASE=CIPRICO, INC. + +OUI:002047* + ID_OUI_FROM_DATABASE=STEINBRECHER CORP. + +OUI:002048* + ID_OUI_FROM_DATABASE=Marconi Communications + +OUI:002049* + ID_OUI_FROM_DATABASE=COMTRON, INC. + +OUI:00204A* + ID_OUI_FROM_DATABASE=PRONET GMBH + +OUI:00204B* + ID_OUI_FROM_DATABASE=AUTOCOMPUTER CO., LTD. + +OUI:00204C* + ID_OUI_FROM_DATABASE=MITRON COMPUTER PTE LTD. + +OUI:00204D* + ID_OUI_FROM_DATABASE=INOVIS GMBH + +OUI:00204E* + ID_OUI_FROM_DATABASE=NETWORK SECURITY SYSTEMS, INC. + +OUI:00204F* + ID_OUI_FROM_DATABASE=DEUTSCHE AEROSPACE AG + +OUI:002050* + ID_OUI_FROM_DATABASE=KOREA COMPUTER INC. + +OUI:002051* + ID_OUI_FROM_DATABASE=Verilink Corporation + +OUI:002052* + ID_OUI_FROM_DATABASE=RAGULA SYSTEMS + +OUI:002053* + ID_OUI_FROM_DATABASE=HUNTSVILLE MICROSYSTEMS, INC. + +OUI:002054* + ID_OUI_FROM_DATABASE=Sycamore Networks + +OUI:002055* + ID_OUI_FROM_DATABASE=ALTECH CO., LTD. + +OUI:002056* + ID_OUI_FROM_DATABASE=NEOPRODUCTS + +OUI:002057* + ID_OUI_FROM_DATABASE=TITZE DATENTECHNIK GmbH + +OUI:002058* + ID_OUI_FROM_DATABASE=ALLIED SIGNAL INC. + +OUI:002059* + ID_OUI_FROM_DATABASE=MIRO COMPUTER PRODUCTS AG + +OUI:00205A* + ID_OUI_FROM_DATABASE=COMPUTER IDENTICS + +OUI:00205B* + ID_OUI_FROM_DATABASE=Kentrox, LLC + +OUI:00205C* + ID_OUI_FROM_DATABASE=InterNet Systems of Florida, Inc. + +OUI:00205D* + ID_OUI_FROM_DATABASE=NANOMATIC OY + +OUI:00205E* + ID_OUI_FROM_DATABASE=CASTLE ROCK, INC. + +OUI:00205F* + ID_OUI_FROM_DATABASE=GAMMADATA COMPUTER GMBH + +OUI:002060* + ID_OUI_FROM_DATABASE=ALCATEL ITALIA S.p.A. + +OUI:002061* + ID_OUI_FROM_DATABASE=GarrettCom, Inc. + +OUI:002062* + ID_OUI_FROM_DATABASE=SCORPION LOGIC, LTD. + +OUI:002063* + ID_OUI_FROM_DATABASE=WIPRO INFOTECH LTD. + +OUI:002064* + ID_OUI_FROM_DATABASE=PROTEC MICROSYSTEMS, INC. + +OUI:002065* + ID_OUI_FROM_DATABASE=SUPERNET NETWORKING INC. + +OUI:002066* + ID_OUI_FROM_DATABASE=GENERAL MAGIC, INC. + +OUI:002067* + ID_OUI_FROM_DATABASE=Private + +OUI:002068* + ID_OUI_FROM_DATABASE=ISDYNE + +OUI:002069* + ID_OUI_FROM_DATABASE=ISDN SYSTEMS CORPORATION + +OUI:00206A* + ID_OUI_FROM_DATABASE=OSAKA COMPUTER CORP. + +OUI:00206B* + ID_OUI_FROM_DATABASE=KONICA MINOLTA HOLDINGS, INC. + +OUI:00206C* + ID_OUI_FROM_DATABASE=EVERGREEN TECHNOLOGY CORP. + +OUI:00206D* + ID_OUI_FROM_DATABASE=DATA RACE, INC. + +OUI:00206E* + ID_OUI_FROM_DATABASE=XACT, INC. + +OUI:00206F* + ID_OUI_FROM_DATABASE=FLOWPOINT CORPORATION + +OUI:002070* + ID_OUI_FROM_DATABASE=HYNET, LTD. + +OUI:002071* + ID_OUI_FROM_DATABASE=IBR GMBH + +OUI:002072* + ID_OUI_FROM_DATABASE=WORKLINK INNOVATIONS + +OUI:002073* + ID_OUI_FROM_DATABASE=FUSION SYSTEMS CORPORATION + +OUI:002074* + ID_OUI_FROM_DATABASE=SUNGWOON SYSTEMS + +OUI:002075* + ID_OUI_FROM_DATABASE=MOTOROLA COMMUNICATION ISRAEL + +OUI:002076* + ID_OUI_FROM_DATABASE=REUDO CORPORATION + +OUI:002077* + ID_OUI_FROM_DATABASE=KARDIOS SYSTEMS CORP. + +OUI:002078* + ID_OUI_FROM_DATABASE=RUNTOP, INC. + +OUI:002079* + ID_OUI_FROM_DATABASE=MIKRON GMBH + +OUI:00207A* + ID_OUI_FROM_DATABASE=WiSE Communications, Inc. + +OUI:00207B* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:00207C* + ID_OUI_FROM_DATABASE=AUTEC GMBH + +OUI:00207D* + ID_OUI_FROM_DATABASE=ADVANCED COMPUTER APPLICATIONS + +OUI:00207E* + ID_OUI_FROM_DATABASE=FINECOM CO., LTD. + +OUI:00207F* + ID_OUI_FROM_DATABASE=KYOEI SANGYO CO., LTD. + +OUI:002080* + ID_OUI_FROM_DATABASE=SYNERGY (UK) LTD. + +OUI:002081* + ID_OUI_FROM_DATABASE=TITAN ELECTRONICS + +OUI:002082* + ID_OUI_FROM_DATABASE=ONEAC CORPORATION + +OUI:002083* + ID_OUI_FROM_DATABASE=PRESTICOM INCORPORATED + +OUI:002084* + ID_OUI_FROM_DATABASE=OCE PRINTING SYSTEMS, GMBH + +OUI:002085* + ID_OUI_FROM_DATABASE=Eaton Corporation + +OUI:002086* + ID_OUI_FROM_DATABASE=MICROTECH ELECTRONICS LIMITED + +OUI:002087* + ID_OUI_FROM_DATABASE=MEMOTEC, INC. + +OUI:002088* + ID_OUI_FROM_DATABASE=GLOBAL VILLAGE COMMUNICATION + +OUI:002089* + ID_OUI_FROM_DATABASE=T3PLUS NETWORKING, INC. + +OUI:00208A* + ID_OUI_FROM_DATABASE=SONIX COMMUNICATIONS, LTD. + +OUI:00208B* + ID_OUI_FROM_DATABASE=LAPIS TECHNOLOGIES, INC. + +OUI:00208C* + ID_OUI_FROM_DATABASE=GALAXY NETWORKS, INC. + +OUI:00208D* + ID_OUI_FROM_DATABASE=CMD TECHNOLOGY + +OUI:00208E* + ID_OUI_FROM_DATABASE=CHEVIN SOFTWARE ENG. LTD. + +OUI:00208F* + ID_OUI_FROM_DATABASE=ECI Telecom Ltd. + +OUI:002090* + ID_OUI_FROM_DATABASE=ADVANCED COMPRESSION TECHNOLOGY, INC. + +OUI:002091* + ID_OUI_FROM_DATABASE=J125, NATIONAL SECURITY AGENCY + +OUI:002092* + ID_OUI_FROM_DATABASE=CHESS ENGINEERING B.V. + +OUI:002093* + ID_OUI_FROM_DATABASE=LANDINGS TECHNOLOGY CORP. + +OUI:002094* + ID_OUI_FROM_DATABASE=CUBIX CORPORATION + +OUI:002095* + ID_OUI_FROM_DATABASE=RIVA ELECTRONICS + +OUI:002096* + ID_OUI_FROM_DATABASE=Invensys + +OUI:002097* + ID_OUI_FROM_DATABASE=APPLIED SIGNAL TECHNOLOGY + +OUI:002098* + ID_OUI_FROM_DATABASE=HECTRONIC AB + +OUI:002099* + ID_OUI_FROM_DATABASE=BON ELECTRIC CO., LTD. + +OUI:00209A* + ID_OUI_FROM_DATABASE=THE 3DO COMPANY + +OUI:00209B* + ID_OUI_FROM_DATABASE=ERSAT ELECTRONIC GMBH + +OUI:00209C* + ID_OUI_FROM_DATABASE=PRIMARY ACCESS CORP. + +OUI:00209D* + ID_OUI_FROM_DATABASE=LIPPERT AUTOMATIONSTECHNIK + +OUI:00209E* + ID_OUI_FROM_DATABASE=BROWN'S OPERATING SYSTEM SERVICES, LTD. + +OUI:00209F* + ID_OUI_FROM_DATABASE=MERCURY COMPUTER SYSTEMS, INC. + +OUI:0020A0* + ID_OUI_FROM_DATABASE=OA LABORATORY CO., LTD. + +OUI:0020A1* + ID_OUI_FROM_DATABASE=DOVATRON + +OUI:0020A2* + ID_OUI_FROM_DATABASE=GALCOM NETWORKING LTD. + +OUI:0020A3* + ID_OUI_FROM_DATABASE=Harmonic, Inc + +OUI:0020A4* + ID_OUI_FROM_DATABASE=MULTIPOINT NETWORKS + +OUI:0020A5* + ID_OUI_FROM_DATABASE=API ENGINEERING + +OUI:0020A6* + ID_OUI_FROM_DATABASE=Proxim Wireless + +OUI:0020A7* + ID_OUI_FROM_DATABASE=PAIRGAIN TECHNOLOGIES, INC. + +OUI:0020A8* + ID_OUI_FROM_DATABASE=SAST TECHNOLOGY CORP. + +OUI:0020A9* + ID_OUI_FROM_DATABASE=WHITE HORSE INDUSTRIAL + +OUI:0020AA* + ID_OUI_FROM_DATABASE=Ericsson Television Limited + +OUI:0020AB* + ID_OUI_FROM_DATABASE=MICRO INDUSTRIES CORP. + +OUI:0020AC* + ID_OUI_FROM_DATABASE=INTERFLEX DATENSYSTEME GMBH + +OUI:0020AD* + ID_OUI_FROM_DATABASE=LINQ SYSTEMS + +OUI:0020AE* + ID_OUI_FROM_DATABASE=ORNET DATA COMMUNICATION TECH. + +OUI:0020AF* + ID_OUI_FROM_DATABASE=3COM + +OUI:0020B0* + ID_OUI_FROM_DATABASE=GATEWAY DEVICES, INC. + +OUI:0020B1* + ID_OUI_FROM_DATABASE=COMTECH RESEARCH INC. + +OUI:0020B2* + ID_OUI_FROM_DATABASE=GKD Gesellschaft Fur Kommunikation Und Datentechnik + +OUI:0020B3* + ID_OUI_FROM_DATABASE=Tattile SRL + +OUI:0020B4* + ID_OUI_FROM_DATABASE=TERMA ELEKTRONIK AS + +OUI:0020B5* + ID_OUI_FROM_DATABASE=YASKAWA ELECTRIC CORPORATION + +OUI:0020B6* + ID_OUI_FROM_DATABASE=AGILE NETWORKS, INC. + +OUI:0020B7* + ID_OUI_FROM_DATABASE=NAMAQUA COMPUTERWARE + +OUI:0020B8* + ID_OUI_FROM_DATABASE=PRIME OPTION, INC. + +OUI:0020B9* + ID_OUI_FROM_DATABASE=METRICOM, INC. + +OUI:0020BA* + ID_OUI_FROM_DATABASE=CENTER FOR HIGH PERFORMANCE + +OUI:0020BB* + ID_OUI_FROM_DATABASE=ZAX CORPORATION + +OUI:0020BC* + ID_OUI_FROM_DATABASE=Long Reach Networks Pty Ltd + +OUI:0020BD* + ID_OUI_FROM_DATABASE=NIOBRARA R & D CORPORATION + +OUI:0020BE* + ID_OUI_FROM_DATABASE=LAN ACCESS CORP. + +OUI:0020BF* + ID_OUI_FROM_DATABASE=AEHR TEST SYSTEMS + +OUI:0020C0* + ID_OUI_FROM_DATABASE=PULSE ELECTRONICS, INC. + +OUI:0020C1* + ID_OUI_FROM_DATABASE=SAXA, Inc. + +OUI:0020C2* + ID_OUI_FROM_DATABASE=TEXAS MEMORY SYSTEMS, INC. + +OUI:0020C3* + ID_OUI_FROM_DATABASE=COUNTER SOLUTIONS LTD. + +OUI:0020C4* + ID_OUI_FROM_DATABASE=INET,INC. + +OUI:0020C5* + ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGY + +OUI:0020C6* + ID_OUI_FROM_DATABASE=NECTEC + +OUI:0020C7* + ID_OUI_FROM_DATABASE=AKAI Professional M.I. Corp. + +OUI:0020C8* + ID_OUI_FROM_DATABASE=LARSCOM INCORPORATED + +OUI:0020C9* + ID_OUI_FROM_DATABASE=VICTRON BV + +OUI:0020CA* + ID_OUI_FROM_DATABASE=DIGITAL OCEAN + +OUI:0020CB* + ID_OUI_FROM_DATABASE=PRETEC ELECTRONICS CORP. + +OUI:0020CC* + ID_OUI_FROM_DATABASE=DIGITAL SERVICES, LTD. + +OUI:0020CD* + ID_OUI_FROM_DATABASE=HYBRID NETWORKS, INC. + +OUI:0020CE* + ID_OUI_FROM_DATABASE=LOGICAL DESIGN GROUP, INC. + +OUI:0020CF* + ID_OUI_FROM_DATABASE=TEST & MEASUREMENT SYSTEMS INC + +OUI:0020D0* + ID_OUI_FROM_DATABASE=VERSALYNX CORPORATION + +OUI:0020D1* + ID_OUI_FROM_DATABASE=MICROCOMPUTER SYSTEMS (M) SDN. + +OUI:0020D2* + ID_OUI_FROM_DATABASE=RAD DATA COMMUNICATIONS, LTD. + +OUI:0020D3* + ID_OUI_FROM_DATABASE=OST (OUEST STANDARD TELEMATIQU + +OUI:0020D4* + ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. + +OUI:0020D5* + ID_OUI_FROM_DATABASE=VIPA GMBH + +OUI:0020D6* + ID_OUI_FROM_DATABASE=Breezecom, Ltd. + +OUI:0020D7* + ID_OUI_FROM_DATABASE=JAPAN MINICOMPUTER SYSTEMS CO., Ltd. + +OUI:0020D8* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0020D9* + ID_OUI_FROM_DATABASE=PANASONIC TECHNOLOGIES, INC./MIECO-US + +OUI:0020DA* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise + +OUI:0020DB* + ID_OUI_FROM_DATABASE=XNET TECHNOLOGY, INC. + +OUI:0020DC* + ID_OUI_FROM_DATABASE=DENSITRON TAIWAN LTD. + +OUI:0020DD* + ID_OUI_FROM_DATABASE=Cybertec Pty Ltd + +OUI:0020DE* + ID_OUI_FROM_DATABASE=JAPAN DIGITAL LABORAT'Y CO.LTD + +OUI:0020DF* + ID_OUI_FROM_DATABASE=KYOSAN ELECTRIC MFG. CO., LTD. + +OUI:0020E0* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:0020E1* + ID_OUI_FROM_DATABASE=ALAMAR ELECTRONICS + +OUI:0020E2* + ID_OUI_FROM_DATABASE=INFORMATION RESOURCE ENGINEERING + +OUI:0020E3* + ID_OUI_FROM_DATABASE=MCD KENCOM CORPORATION + +OUI:0020E4* + ID_OUI_FROM_DATABASE=HSING TECH ENTERPRISE CO., LTD + +OUI:0020E5* + ID_OUI_FROM_DATABASE=APEX DATA, INC. + +OUI:0020E6* + ID_OUI_FROM_DATABASE=LIDKOPING MACHINE TOOLS AB + +OUI:0020E7* + ID_OUI_FROM_DATABASE=B&W NUCLEAR SERVICE COMPANY + +OUI:0020E8* + ID_OUI_FROM_DATABASE=DATATREK CORPORATION + +OUI:0020E9* + ID_OUI_FROM_DATABASE=DANTEL + +OUI:0020EA* + ID_OUI_FROM_DATABASE=EFFICIENT NETWORKS, INC. + +OUI:0020EB* + ID_OUI_FROM_DATABASE=CINCINNATI MICROWAVE, INC. + +OUI:0020EC* + ID_OUI_FROM_DATABASE=TECHWARE SYSTEMS CORP. + +OUI:0020ED* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO., LTD. + +OUI:0020EE* + ID_OUI_FROM_DATABASE=GTECH CORPORATION + +OUI:0020EF* + ID_OUI_FROM_DATABASE=USC CORPORATION + +OUI:0020F0* + ID_OUI_FROM_DATABASE=UNIVERSAL MICROELECTRONICS CO. + +OUI:0020F1* + ID_OUI_FROM_DATABASE=ALTOS INDIA LIMITED + +OUI:0020F2* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:0020F3* + ID_OUI_FROM_DATABASE=RAYNET CORPORATION + +OUI:0020F4* + ID_OUI_FROM_DATABASE=SPECTRIX CORPORATION + +OUI:0020F5* + ID_OUI_FROM_DATABASE=PANDATEL AG + +OUI:0020F6* + ID_OUI_FROM_DATABASE=NET TEK AND KARLNET, INC. + +OUI:0020F7* + ID_OUI_FROM_DATABASE=CYBERDATA CORPORATION + +OUI:0020F8* + ID_OUI_FROM_DATABASE=CARRERA COMPUTERS, INC. + +OUI:0020F9* + ID_OUI_FROM_DATABASE=PARALINK NETWORKS, INC. + +OUI:0020FA* + ID_OUI_FROM_DATABASE=GDE SYSTEMS, INC. + +OUI:0020FB* + ID_OUI_FROM_DATABASE=OCTEL COMMUNICATIONS CORP. + +OUI:0020FC* + ID_OUI_FROM_DATABASE=MATROX + +OUI:0020FD* + ID_OUI_FROM_DATABASE=ITV TECHNOLOGIES, INC. + +OUI:0020FE* + ID_OUI_FROM_DATABASE=TOPWARE INC. / GRAND COMPUTER + +OUI:0020FF* + ID_OUI_FROM_DATABASE=SYMMETRICAL TECHNOLOGIES + +OUI:002100* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:002101* + ID_OUI_FROM_DATABASE=Aplicaciones Electronicas Quasar (AEQ) + +OUI:002102* + ID_OUI_FROM_DATABASE=UpdateLogic Inc. + +OUI:002103* + ID_OUI_FROM_DATABASE=GHI Electronics, LLC + +OUI:002104* + ID_OUI_FROM_DATABASE=Gigaset Communications GmbH + +OUI:002105* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:002106* + ID_OUI_FROM_DATABASE=RIM Testing Services + +OUI:002107* + ID_OUI_FROM_DATABASE=Seowonintech Co Ltd. + +OUI:002108* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:002109* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:00210A* + ID_OUI_FROM_DATABASE=byd:sign Corporation + +OUI:00210B* + ID_OUI_FROM_DATABASE=GEMINI TRAZE RFID PVT. LTD. + +OUI:00210C* + ID_OUI_FROM_DATABASE=Cymtec Systems, Inc. + +OUI:00210D* + ID_OUI_FROM_DATABASE=SAMSIN INNOTEC + +OUI:00210E* + ID_OUI_FROM_DATABASE=Orpak Systems L.T.D. + +OUI:00210F* + ID_OUI_FROM_DATABASE=Cernium Corp + +OUI:002110* + ID_OUI_FROM_DATABASE=Clearbox Systems + +OUI:002111* + ID_OUI_FROM_DATABASE=Uniphone Inc. + +OUI:002112* + ID_OUI_FROM_DATABASE=WISCOM SYSTEM CO.,LTD + +OUI:002113* + ID_OUI_FROM_DATABASE=Padtec S/A + +OUI:002114* + ID_OUI_FROM_DATABASE=Hylab Technology Inc. + +OUI:002115* + ID_OUI_FROM_DATABASE=PHYWE Systeme GmbH & Co. KG + +OUI:002116* + ID_OUI_FROM_DATABASE=Transcon Electronic Systems, spol. s r. o. + +OUI:002117* + ID_OUI_FROM_DATABASE=Tellord + +OUI:002118* + ID_OUI_FROM_DATABASE=Athena Tech, Inc. + +OUI:002119* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:00211A* + ID_OUI_FROM_DATABASE=LInTech Corporation + +OUI:00211B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00211C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00211D* + ID_OUI_FROM_DATABASE=Dataline AB + +OUI:00211E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00211F* + ID_OUI_FROM_DATABASE=SHINSUNG DELTATECH CO.,LTD. + +OUI:002120* + ID_OUI_FROM_DATABASE=Sequel Technologies + +OUI:002121* + ID_OUI_FROM_DATABASE=VRmagic GmbH + +OUI:002122* + ID_OUI_FROM_DATABASE=Chip-pro Ltd. + +OUI:002123* + ID_OUI_FROM_DATABASE=Aerosat Avionics + +OUI:002124* + ID_OUI_FROM_DATABASE=Optos Plc + +OUI:002125* + ID_OUI_FROM_DATABASE=KUK JE TONG SHIN Co.,LTD + +OUI:002126* + ID_OUI_FROM_DATABASE=Shenzhen Torch Equipment Co., Ltd. + +OUI:002127* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:002128* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:002129* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:00212A* + ID_OUI_FROM_DATABASE=Audiovox Corporation + +OUI:00212B* + ID_OUI_FROM_DATABASE=MSA Auer + +OUI:00212C* + ID_OUI_FROM_DATABASE=SemIndia System Private Limited + +OUI:00212D* + ID_OUI_FROM_DATABASE=SCIMOLEX CORPORATION + +OUI:00212E* + ID_OUI_FROM_DATABASE=dresden-elektronik + +OUI:00212F* + ID_OUI_FROM_DATABASE=Phoebe Micro Inc. + +OUI:002130* + ID_OUI_FROM_DATABASE=Keico Hightech Inc. + +OUI:002131* + ID_OUI_FROM_DATABASE=Blynke Inc. + +OUI:002132* + ID_OUI_FROM_DATABASE=Masterclock, Inc. + +OUI:002133* + ID_OUI_FROM_DATABASE=Building B, Inc + +OUI:002134* + ID_OUI_FROM_DATABASE=Brandywine Communications + +OUI:002135* + ID_OUI_FROM_DATABASE=ALCATEL-LUCENT + +OUI:002136* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002137* + ID_OUI_FROM_DATABASE=Bay Controls, LLC + +OUI:002138* + ID_OUI_FROM_DATABASE=Cepheid + +OUI:002139* + ID_OUI_FROM_DATABASE=Escherlogic Inc. + +OUI:00213A* + ID_OUI_FROM_DATABASE=Winchester Systems Inc. + +OUI:00213B* + ID_OUI_FROM_DATABASE=Berkshire Products, Inc + +OUI:00213C* + ID_OUI_FROM_DATABASE=AliphCom + +OUI:00213D* + ID_OUI_FROM_DATABASE=Cermetek Microelectronics, Inc. + +OUI:00213E* + ID_OUI_FROM_DATABASE=TomTom + +OUI:00213F* + ID_OUI_FROM_DATABASE=A-Team Technology Ltd. + +OUI:002140* + ID_OUI_FROM_DATABASE=EN Technologies Inc. + +OUI:002141* + ID_OUI_FROM_DATABASE=RADLIVE + +OUI:002142* + ID_OUI_FROM_DATABASE=Advanced Control Systems doo + +OUI:002143* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002144* + ID_OUI_FROM_DATABASE=SS Telecoms + +OUI:002145* + ID_OUI_FROM_DATABASE=Semptian Technologies Ltd. + +OUI:002146* + ID_OUI_FROM_DATABASE=Sanmina-SCI + +OUI:002147* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:002148* + ID_OUI_FROM_DATABASE=Kaco Solar Korea + +OUI:002149* + ID_OUI_FROM_DATABASE=China Daheng Group ,Inc. + +OUI:00214A* + ID_OUI_FROM_DATABASE=Pixel Velocity, Inc + +OUI:00214B* + ID_OUI_FROM_DATABASE=Shenzhen HAMP Science & Technology Co.,Ltd + +OUI:00214C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00214D* + ID_OUI_FROM_DATABASE=Guangzhou Skytone Transmission Technology Com. Ltd. + +OUI:00214E* + ID_OUI_FROM_DATABASE=GS Yuasa Power Supply Ltd. + +OUI:00214F* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:002150* + ID_OUI_FROM_DATABASE=EYEVIEW ELECTRONICS + +OUI:002151* + ID_OUI_FROM_DATABASE=Millinet Co., Ltd. + +OUI:002152* + ID_OUI_FROM_DATABASE=General Satellite Research & Development Limited + +OUI:002153* + ID_OUI_FROM_DATABASE=SeaMicro Inc. + +OUI:002154* + ID_OUI_FROM_DATABASE=D-TACQ Solutions Ltd + +OUI:002155* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002156* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002157* + ID_OUI_FROM_DATABASE=National Datacast, Inc. + +OUI:002158* + ID_OUI_FROM_DATABASE=Style Flying Technology Co. + +OUI:002159* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:00215A* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:00215B* + ID_OUI_FROM_DATABASE=SenseAnywhere + +OUI:00215C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:00215D* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:00215E* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:00215F* + ID_OUI_FROM_DATABASE=IHSE GmbH + +OUI:002160* + ID_OUI_FROM_DATABASE=Hidea Solutions Co. Ltd. + +OUI:002161* + ID_OUI_FROM_DATABASE=Yournet Inc. + +OUI:002162* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:002163* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:002164* + ID_OUI_FROM_DATABASE=Special Design Bureau for Seismic Instrumentation + +OUI:002165* + ID_OUI_FROM_DATABASE=Presstek Inc. + +OUI:002166* + ID_OUI_FROM_DATABASE=NovAtel Inc. + +OUI:002167* + ID_OUI_FROM_DATABASE=HWA JIN T&I Corp. + +OUI:002168* + ID_OUI_FROM_DATABASE=iVeia, LLC + +OUI:002169* + ID_OUI_FROM_DATABASE=Prologix, LLC. + +OUI:00216A* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:00216B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:00216C* + ID_OUI_FROM_DATABASE=ODVA + +OUI:00216D* + ID_OUI_FROM_DATABASE=Soltech Co., Ltd. + +OUI:00216E* + ID_OUI_FROM_DATABASE=Function ATI (Huizhou) Telecommunications Co., Ltd. + +OUI:00216F* + ID_OUI_FROM_DATABASE=SymCom, Inc. + +OUI:002170* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:002171* + ID_OUI_FROM_DATABASE=Wesung TNC Co., Ltd. + +OUI:002172* + ID_OUI_FROM_DATABASE=Seoultek Valley + +OUI:002173* + ID_OUI_FROM_DATABASE=Ion Torrent Systems, Inc. + +OUI:002174* + ID_OUI_FROM_DATABASE=AvaLAN Wireless + +OUI:002175* + ID_OUI_FROM_DATABASE=Pacific Satellite International Ltd. + +OUI:002176* + ID_OUI_FROM_DATABASE=YMax Telecom Ltd. + +OUI:002177* + ID_OUI_FROM_DATABASE=W. L. Gore & Associates + +OUI:002178* + ID_OUI_FROM_DATABASE=Matuschek Messtechnik GmbH + +OUI:002179* + ID_OUI_FROM_DATABASE=IOGEAR, Inc. + +OUI:00217A* + ID_OUI_FROM_DATABASE=Sejin Electron, Inc. + +OUI:00217B* + ID_OUI_FROM_DATABASE=Bastec AB + +OUI:00217C* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:00217D* + ID_OUI_FROM_DATABASE=PYXIS S.R.L. + +OUI:00217E* + ID_OUI_FROM_DATABASE=Telit Communication s.p.a + +OUI:00217F* + ID_OUI_FROM_DATABASE=Intraco Technology Pte Ltd + +OUI:002180* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002181* + ID_OUI_FROM_DATABASE=Si2 Microsystems Limited + +OUI:002182* + ID_OUI_FROM_DATABASE=SandLinks Systems, Ltd. + +OUI:002183* + ID_OUI_FROM_DATABASE=ANDRITZ HYDRO GmbH + +OUI:002184* + ID_OUI_FROM_DATABASE=POWERSOFT SRL + +OUI:002185* + ID_OUI_FROM_DATABASE=MICRO-STAR INT'L CO.,LTD. + +OUI:002186* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:002187* + ID_OUI_FROM_DATABASE=Imacs GmbH + +OUI:002188* + ID_OUI_FROM_DATABASE=EMC Corporation + +OUI:002189* + ID_OUI_FROM_DATABASE=AppTech, Inc. + +OUI:00218A* + ID_OUI_FROM_DATABASE=Electronic Design and Manufacturing Company + +OUI:00218B* + ID_OUI_FROM_DATABASE=Wescon Technology, Inc. + +OUI:00218C* + ID_OUI_FROM_DATABASE=TopControl GMBH + +OUI:00218D* + ID_OUI_FROM_DATABASE=AP Router Ind. Eletronica LTDA + +OUI:00218E* + ID_OUI_FROM_DATABASE=MEKICS CO., LTD. + +OUI:00218F* + ID_OUI_FROM_DATABASE=Avantgarde Acoustic Lautsprechersysteme GmbH + +OUI:002190* + ID_OUI_FROM_DATABASE=Goliath Solutions + +OUI:002191* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:002192* + ID_OUI_FROM_DATABASE=Baoding Galaxy Electronic Technology Co.,Ltd + +OUI:002193* + ID_OUI_FROM_DATABASE=Videofon MV + +OUI:002194* + ID_OUI_FROM_DATABASE=Ping Communication + +OUI:002195* + ID_OUI_FROM_DATABASE=GWD Media Limited + +OUI:002196* + ID_OUI_FROM_DATABASE=Telsey S.p.A. + +OUI:002197* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:002198* + ID_OUI_FROM_DATABASE=Thai Radio Co, LTD + +OUI:002199* + ID_OUI_FROM_DATABASE=Vacon Plc + +OUI:00219A* + ID_OUI_FROM_DATABASE=Cambridge Visual Networks Ltd + +OUI:00219B* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:00219C* + ID_OUI_FROM_DATABASE=Honeywld Technology Corp. + +OUI:00219D* + ID_OUI_FROM_DATABASE=Adesys BV + +OUI:00219E* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:00219F* + ID_OUI_FROM_DATABASE=SATEL OY + +OUI:0021A0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0021A1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0021A2* + ID_OUI_FROM_DATABASE=EKE-Electronics Ltd. + +OUI:0021A3* + ID_OUI_FROM_DATABASE=Micromint + +OUI:0021A4* + ID_OUI_FROM_DATABASE=Dbii Networks + +OUI:0021A5* + ID_OUI_FROM_DATABASE=ERLPhase Power Technologies Ltd. + +OUI:0021A6* + ID_OUI_FROM_DATABASE=Videotec Spa + +OUI:0021A7* + ID_OUI_FROM_DATABASE=Hantle System Co., Ltd. + +OUI:0021A8* + ID_OUI_FROM_DATABASE=Telephonics Corporation + +OUI:0021A9* + ID_OUI_FROM_DATABASE=Mobilink Telecom Co.,Ltd + +OUI:0021AA* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0021AB* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0021AC* + ID_OUI_FROM_DATABASE=Infrared Integrated Systems Ltd + +OUI:0021AD* + ID_OUI_FROM_DATABASE=Nordic ID Oy + +OUI:0021AE* + ID_OUI_FROM_DATABASE=ALCATEL-LUCENT FRANCE - WTD + +OUI:0021AF* + ID_OUI_FROM_DATABASE=Radio Frequency Systems + +OUI:0021B0* + ID_OUI_FROM_DATABASE=Tyco Telecommunications + +OUI:0021B1* + ID_OUI_FROM_DATABASE=DIGITAL SOLUTIONS LTD + +OUI:0021B2* + ID_OUI_FROM_DATABASE=Fiberblaze A/S + +OUI:0021B3* + ID_OUI_FROM_DATABASE=Ross Controls + +OUI:0021B4* + ID_OUI_FROM_DATABASE=APRO MEDIA CO., LTD + +OUI:0021B5* + ID_OUI_FROM_DATABASE=Galvanic Ltd + +OUI:0021B6* + ID_OUI_FROM_DATABASE=Triacta Power Technologies Inc. + +OUI:0021B7* + ID_OUI_FROM_DATABASE=LEXMARK INTERNATIONAL, INC. + +OUI:0021B8* + ID_OUI_FROM_DATABASE=Inphi Corporation + +OUI:0021B9* + ID_OUI_FROM_DATABASE=Universal Devices Inc. + +OUI:0021BA* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0021BB* + ID_OUI_FROM_DATABASE=Riken Keiki Co., Ltd. + +OUI:0021BC* + ID_OUI_FROM_DATABASE=ZALA COMPUTER + +OUI:0021BD* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:0021BE* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:0021BF* + ID_OUI_FROM_DATABASE=Hitachi High-Tech Control Systems Corporation + +OUI:0021C0* + ID_OUI_FROM_DATABASE=Mobile Appliance, Inc. + +OUI:0021C1* + ID_OUI_FROM_DATABASE=ABB Oy / Medium Voltage Products + +OUI:0021C2* + ID_OUI_FROM_DATABASE=GL Communications Inc + +OUI:0021C3* + ID_OUI_FROM_DATABASE=CORNELL Communications, Inc. + +OUI:0021C4* + ID_OUI_FROM_DATABASE=Consilium AB + +OUI:0021C5* + ID_OUI_FROM_DATABASE=3DSP Corp + +OUI:0021C6* + ID_OUI_FROM_DATABASE=CSJ Global, Inc. + +OUI:0021C7* + ID_OUI_FROM_DATABASE=Russound + +OUI:0021C8* + ID_OUI_FROM_DATABASE=LOHUIS Networks + +OUI:0021C9* + ID_OUI_FROM_DATABASE=Wavecom Asia Pacific Limited + +OUI:0021CA* + ID_OUI_FROM_DATABASE=ART System Co., Ltd. + +OUI:0021CB* + ID_OUI_FROM_DATABASE=SMS TECNOLOGIA ELETRONICA LTDA + +OUI:0021CC* + ID_OUI_FROM_DATABASE=Flextronics International + +OUI:0021CD* + ID_OUI_FROM_DATABASE=LiveTV + +OUI:0021CE* + ID_OUI_FROM_DATABASE=NTC-Metrotek + +OUI:0021CF* + ID_OUI_FROM_DATABASE=The Crypto Group + +OUI:0021D0* + ID_OUI_FROM_DATABASE=Global Display Solutions Spa + +OUI:0021D1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0021D2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0021D3* + ID_OUI_FROM_DATABASE=BOCOM SECURITY(ASIA PACIFIC) LIMITED + +OUI:0021D4* + ID_OUI_FROM_DATABASE=Vollmer Werke GmbH + +OUI:0021D5* + ID_OUI_FROM_DATABASE=X2E GmbH + +OUI:0021D6* + ID_OUI_FROM_DATABASE=LXI Consortium + +OUI:0021D7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0021D8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0021D9* + ID_OUI_FROM_DATABASE=SEKONIC CORPORATION + +OUI:0021DA* + ID_OUI_FROM_DATABASE=Automation Products Group Inc. + +OUI:0021DB* + ID_OUI_FROM_DATABASE=Santachi Video Technology (Shenzhen) Co., Ltd. + +OUI:0021DC* + ID_OUI_FROM_DATABASE=TECNOALARM S.r.l. + +OUI:0021DD* + ID_OUI_FROM_DATABASE=Northstar Systems Corp + +OUI:0021DE* + ID_OUI_FROM_DATABASE=Firepro Wireless + +OUI:0021DF* + ID_OUI_FROM_DATABASE=Martin Christ GmbH + +OUI:0021E0* + ID_OUI_FROM_DATABASE=CommAgility Ltd + +OUI:0021E1* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0021E2* + ID_OUI_FROM_DATABASE=visago Systems & Controls GmbH & Co. KG + +OUI:0021E3* + ID_OUI_FROM_DATABASE=SerialTek LLC + +OUI:0021E4* + ID_OUI_FROM_DATABASE=I-WIN + +OUI:0021E5* + ID_OUI_FROM_DATABASE=Display Solution AG + +OUI:0021E6* + ID_OUI_FROM_DATABASE=Starlight Video Limited + +OUI:0021E7* + ID_OUI_FROM_DATABASE=Informatics Services Corporation + +OUI:0021E8* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:0021E9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0021EA* + ID_OUI_FROM_DATABASE=Bystronic Laser AG + +OUI:0021EB* + ID_OUI_FROM_DATABASE=ESP SYSTEMS, LLC + +OUI:0021EC* + ID_OUI_FROM_DATABASE=Solutronic GmbH + +OUI:0021ED* + ID_OUI_FROM_DATABASE=Telegesis + +OUI:0021EE* + ID_OUI_FROM_DATABASE=Full Spectrum Inc. + +OUI:0021EF* + ID_OUI_FROM_DATABASE=Kapsys + +OUI:0021F0* + ID_OUI_FROM_DATABASE=EW3 Technologies LLC + +OUI:0021F1* + ID_OUI_FROM_DATABASE=Tutus Data AB + +OUI:0021F2* + ID_OUI_FROM_DATABASE=EASY3CALL Technology Limited + +OUI:0021F3* + ID_OUI_FROM_DATABASE=Si14 SpA + +OUI:0021F4* + ID_OUI_FROM_DATABASE=INRange Systems, Inc + +OUI:0021F5* + ID_OUI_FROM_DATABASE=Western Engravers Supply, Inc. + +OUI:0021F6* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:0021F7* + ID_OUI_FROM_DATABASE=HPN Supply Chain + +OUI:0021F8* + ID_OUI_FROM_DATABASE=Enseo, Inc. + +OUI:0021F9* + ID_OUI_FROM_DATABASE=WIRECOM Technologies + +OUI:0021FA* + ID_OUI_FROM_DATABASE=A4SP Technologies Ltd. + +OUI:0021FB* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:0021FC* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0021FD* + ID_OUI_FROM_DATABASE=LACROIX TRAFFIC S.A.U + +OUI:0021FE* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0021FF* + ID_OUI_FROM_DATABASE=Cyfrowy Polsat SA + +OUI:002200* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:002201* + ID_OUI_FROM_DATABASE=Aksys Networks Inc + +OUI:002202* + ID_OUI_FROM_DATABASE=Excito Elektronik i Skåne AB + +OUI:002203* + ID_OUI_FROM_DATABASE=Glensound Electronics Ltd + +OUI:002204* + ID_OUI_FROM_DATABASE=KORATEK + +OUI:002205* + ID_OUI_FROM_DATABASE=WeLink Solutions, Inc. + +OUI:002206* + ID_OUI_FROM_DATABASE=Cyberdyne Inc. + +OUI:002207* + ID_OUI_FROM_DATABASE=Inteno Broadband Technology AB + +OUI:002208* + ID_OUI_FROM_DATABASE=Certicom Corp + +OUI:002209* + ID_OUI_FROM_DATABASE=Omron Healthcare Co., Ltd + +OUI:00220A* + ID_OUI_FROM_DATABASE=OnLive, Inc + +OUI:00220B* + ID_OUI_FROM_DATABASE=National Source Coding Center + +OUI:00220C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00220D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00220E* + ID_OUI_FROM_DATABASE=Indigo Security Co., Ltd. + +OUI:00220F* + ID_OUI_FROM_DATABASE=MoCA (Multimedia over Coax Alliance) + +OUI:002210* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002211* + ID_OUI_FROM_DATABASE=Rohati Systems + +OUI:002212* + ID_OUI_FROM_DATABASE=CAI Networks, Inc. + +OUI:002213* + ID_OUI_FROM_DATABASE=PCI CORPORATION + +OUI:002214* + ID_OUI_FROM_DATABASE=RINNAI KOREA + +OUI:002215* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:002216* + ID_OUI_FROM_DATABASE=SHIBAURA VENDING MACHINE CORPORATION + +OUI:002217* + ID_OUI_FROM_DATABASE=Neat Electronics + +OUI:002218* + ID_OUI_FROM_DATABASE=AKAMAI TECHNOLOGIES INC + +OUI:002219* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:00221A* + ID_OUI_FROM_DATABASE=Audio Precision + +OUI:00221B* + ID_OUI_FROM_DATABASE=Morega Systems + +OUI:00221C* + ID_OUI_FROM_DATABASE=Private + +OUI:00221D* + ID_OUI_FROM_DATABASE=Freegene Technology LTD + +OUI:00221E* + ID_OUI_FROM_DATABASE=Media Devices Co., Ltd. + +OUI:00221F* + ID_OUI_FROM_DATABASE=eSang Technologies Co., Ltd. + +OUI:002220* + ID_OUI_FROM_DATABASE=Mitac Technology Corp + +OUI:002221* + ID_OUI_FROM_DATABASE=ITOH DENKI CO,LTD. + +OUI:002222* + ID_OUI_FROM_DATABASE=Schaffner Deutschland GmbH + +OUI:002223* + ID_OUI_FROM_DATABASE=TimeKeeping Systems, Inc. + +OUI:002224* + ID_OUI_FROM_DATABASE=Good Will Instrument Co., Ltd. + +OUI:002225* + ID_OUI_FROM_DATABASE=Thales Avionics Ltd + +OUI:002226* + ID_OUI_FROM_DATABASE=Avaak, Inc. + +OUI:002227* + ID_OUI_FROM_DATABASE=uv-electronic GmbH + +OUI:002228* + ID_OUI_FROM_DATABASE=Breeze Innovations Ltd. + +OUI:002229* + ID_OUI_FROM_DATABASE=Compumedics Ltd + +OUI:00222A* + ID_OUI_FROM_DATABASE=SoundEar A/S + +OUI:00222B* + ID_OUI_FROM_DATABASE=Nucomm, Inc. + +OUI:00222C* + ID_OUI_FROM_DATABASE=Ceton Corp + +OUI:00222D* + ID_OUI_FROM_DATABASE=SMC Networks Inc. + +OUI:00222E* + ID_OUI_FROM_DATABASE=maintech GmbH + +OUI:00222F* + ID_OUI_FROM_DATABASE=Open Grid Computing, Inc. + +OUI:002230* + ID_OUI_FROM_DATABASE=FutureLogic Inc. + +OUI:002231* + ID_OUI_FROM_DATABASE=SMT&C Co., Ltd. + +OUI:002232* + ID_OUI_FROM_DATABASE=Design Design Technology Ltd + +OUI:002233* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:002234* + ID_OUI_FROM_DATABASE=Corventis Inc. + +OUI:002235* + ID_OUI_FROM_DATABASE=Strukton Systems bv + +OUI:002236* + ID_OUI_FROM_DATABASE=VECTOR SP. Z O.O. + +OUI:002237* + ID_OUI_FROM_DATABASE=Shinhint Group + +OUI:002238* + ID_OUI_FROM_DATABASE=LOGIPLUS + +OUI:002239* + ID_OUI_FROM_DATABASE=Indiana Life Sciences Incorporated + +OUI:00223A* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:00223B* + ID_OUI_FROM_DATABASE=Communication Networks, LLC + +OUI:00223C* + ID_OUI_FROM_DATABASE=RATIO Entwicklungen GmbH + +OUI:00223D* + ID_OUI_FROM_DATABASE=JumpGen Systems, LLC + +OUI:00223E* + ID_OUI_FROM_DATABASE=IRTrans GmbH + +OUI:00223F* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:002240* + ID_OUI_FROM_DATABASE=Universal Telecom S/A + +OUI:002241* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:002242* + ID_OUI_FROM_DATABASE=Alacron Inc. + +OUI:002243* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:002244* + ID_OUI_FROM_DATABASE=Chengdu Linkon Communications Device Co., Ltd + +OUI:002245* + ID_OUI_FROM_DATABASE=Leine & Linde AB + +OUI:002246* + ID_OUI_FROM_DATABASE=Evoc Intelligent Technology Co.,Ltd. + +OUI:002247* + ID_OUI_FROM_DATABASE=DAC ENGINEERING CO., LTD. + +OUI:002248* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:002249* + ID_OUI_FROM_DATABASE=HOME MULTIENERGY SL + +OUI:00224A* + ID_OUI_FROM_DATABASE=RAYLASE AG + +OUI:00224B* + ID_OUI_FROM_DATABASE=AIRTECH TECHNOLOGIES, INC. + +OUI:00224C* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:00224D* + ID_OUI_FROM_DATABASE=MITAC INTERNATIONAL CORP. + +OUI:00224E* + ID_OUI_FROM_DATABASE=SEEnergy Corp. + +OUI:00224F* + ID_OUI_FROM_DATABASE=Byzoro Networks Ltd. + +OUI:002250* + ID_OUI_FROM_DATABASE=Point Six Wireless, LLC + +OUI:002251* + ID_OUI_FROM_DATABASE=Lumasense Technologies + +OUI:002252* + ID_OUI_FROM_DATABASE=ZOLL Lifecor Corporation + +OUI:002253* + ID_OUI_FROM_DATABASE=Entorian Technologies + +OUI:002254* + ID_OUI_FROM_DATABASE=Bigelow Aerospace + +OUI:002255* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002256* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002257* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:002258* + ID_OUI_FROM_DATABASE=Taiyo Yuden Co., Ltd. + +OUI:002259* + ID_OUI_FROM_DATABASE=Guangzhou New Postcom Equipment Co.,Ltd. + +OUI:00225A* + ID_OUI_FROM_DATABASE=Garde Security AB + +OUI:00225B* + ID_OUI_FROM_DATABASE=Teradici Corporation + +OUI:00225C* + ID_OUI_FROM_DATABASE=Multimedia & Communication Technology + +OUI:00225D* + ID_OUI_FROM_DATABASE=Digicable Network India Pvt. Ltd. + +OUI:00225E* + ID_OUI_FROM_DATABASE=Uwin Technologies Co.,LTD + +OUI:00225F* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:002260* + ID_OUI_FROM_DATABASE=AFREEY Inc. + +OUI:002261* + ID_OUI_FROM_DATABASE=Frontier Silicon Ltd + +OUI:002262* + ID_OUI_FROM_DATABASE=BEP Marine + +OUI:002263* + ID_OUI_FROM_DATABASE=Koos Technical Services, Inc. + +OUI:002264* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:002265* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:002266* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:002267* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:002268* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:002269* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:00226A* + ID_OUI_FROM_DATABASE=Honeywell + +OUI:00226B* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:00226C* + ID_OUI_FROM_DATABASE=LinkSprite Technologies, Inc. + +OUI:00226D* + ID_OUI_FROM_DATABASE=Shenzhen GIEC Electronics Co., Ltd. + +OUI:00226E* + ID_OUI_FROM_DATABASE=Gowell Electronic Limited + +OUI:00226F* + ID_OUI_FROM_DATABASE=3onedata Technology Co. Ltd. + +OUI:002270* + ID_OUI_FROM_DATABASE=ABK North America, LLC + +OUI:002271* + ID_OUI_FROM_DATABASE=Jäger Computergesteuerte Meßtechnik GmbH. + +OUI:002272* + ID_OUI_FROM_DATABASE=American Micro-Fuel Device Corp. + +OUI:002273* + ID_OUI_FROM_DATABASE=Techway + +OUI:002274* + ID_OUI_FROM_DATABASE=FamilyPhone AB + +OUI:002275* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:002276* + ID_OUI_FROM_DATABASE=Triple EYE B.V. + +OUI:002277* + ID_OUI_FROM_DATABASE=NEC Australia Pty Ltd + +OUI:002278* + ID_OUI_FROM_DATABASE=Shenzhen Tongfang Multimedia Technology Co.,Ltd. + +OUI:002279* + ID_OUI_FROM_DATABASE=Nippon Conlux Co., Ltd. + +OUI:00227A* + ID_OUI_FROM_DATABASE=Telecom Design + +OUI:00227B* + ID_OUI_FROM_DATABASE=Apogee Labs, Inc. + +OUI:00227C* + ID_OUI_FROM_DATABASE=Woori SMT Co.,ltd + +OUI:00227D* + ID_OUI_FROM_DATABASE=YE DATA INC. + +OUI:00227E* + ID_OUI_FROM_DATABASE=Chengdu 30Kaitian Communication Industry Co.Ltd + +OUI:00227F* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:002280* + ID_OUI_FROM_DATABASE=A2B Electronics AB + +OUI:002281* + ID_OUI_FROM_DATABASE=Daintree Networks Pty + +OUI:002282* + ID_OUI_FROM_DATABASE=8086 Consultancy + +OUI:002283* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:002284* + ID_OUI_FROM_DATABASE=DESAY A&V SCIENCE AND TECHNOLOGY CO.,LTD + +OUI:002285* + ID_OUI_FROM_DATABASE=NOMUS COMM SYSTEMS + +OUI:002286* + ID_OUI_FROM_DATABASE=ASTRON + +OUI:002287* + ID_OUI_FROM_DATABASE=Titan Wireless LLC + +OUI:002288* + ID_OUI_FROM_DATABASE=Sagrad, Inc. + +OUI:002289* + ID_OUI_FROM_DATABASE=Vandelrande APC inc. + +OUI:00228A* + ID_OUI_FROM_DATABASE=Teratronik elektronische systeme gmbh + +OUI:00228B* + ID_OUI_FROM_DATABASE=Kensington Computer Products Group + +OUI:00228C* + ID_OUI_FROM_DATABASE=Photon Europe GmbH + +OUI:00228D* + ID_OUI_FROM_DATABASE=GBS Laboratories LLC + +OUI:00228E* + ID_OUI_FROM_DATABASE=TV-NUMERIC + +OUI:00228F* + ID_OUI_FROM_DATABASE=CNRS + +OUI:002290* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002291* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002292* + ID_OUI_FROM_DATABASE=Cinetal + +OUI:002293* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:002294* + ID_OUI_FROM_DATABASE=KYOCERA CORPORATION + +OUI:002295* + ID_OUI_FROM_DATABASE=SGM Technology for lighting spa + +OUI:002296* + ID_OUI_FROM_DATABASE=LinoWave Corporation + +OUI:002297* + ID_OUI_FROM_DATABASE=XMOS Semiconductor + +OUI:002298* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:002299* + ID_OUI_FROM_DATABASE=SeaMicro Inc. + +OUI:00229A* + ID_OUI_FROM_DATABASE=Lastar, Inc. + +OUI:00229B* + ID_OUI_FROM_DATABASE=AverLogic Technologies, Inc. + +OUI:00229C* + ID_OUI_FROM_DATABASE=Verismo Networks Inc + +OUI:00229D* + ID_OUI_FROM_DATABASE=PYUNG-HWA IND.CO.,LTD + +OUI:00229E* + ID_OUI_FROM_DATABASE=Social Aid Research Co., Ltd. + +OUI:00229F* + ID_OUI_FROM_DATABASE=Sensys Traffic AB + +OUI:0022A0* + ID_OUI_FROM_DATABASE=APTIV SERVICES US, LLC + +OUI:0022A1* + ID_OUI_FROM_DATABASE=Huawei Symantec Technologies Co.,Ltd. + +OUI:0022A2* + ID_OUI_FROM_DATABASE=Xtramus Technologies + +OUI:0022A3* + ID_OUI_FROM_DATABASE=California Eastern Laboratories + +OUI:0022A4* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:0022A5* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0022A6* + ID_OUI_FROM_DATABASE=Sony Computer Entertainment America + +OUI:0022A7* + ID_OUI_FROM_DATABASE=Tyco Electronics AMP GmbH + +OUI:0022A8* + ID_OUI_FROM_DATABASE=Ouman Oy + +OUI:0022A9* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:0022AA* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:0022AB* + ID_OUI_FROM_DATABASE=Shenzhen Turbosight Technology Ltd + +OUI:0022AC* + ID_OUI_FROM_DATABASE=Hangzhou Siyuan Tech. Co., Ltd + +OUI:0022AD* + ID_OUI_FROM_DATABASE=TELESIS TECHNOLOGIES, INC. + +OUI:0022AE* + ID_OUI_FROM_DATABASE=Mattel Inc. + +OUI:0022AF* + ID_OUI_FROM_DATABASE=Safety Vision, LLC + +OUI:0022B0* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:0022B1* + ID_OUI_FROM_DATABASE=Elbit Systems Ltd. + +OUI:0022B2* + ID_OUI_FROM_DATABASE=4RF Communications Ltd + +OUI:0022B3* + ID_OUI_FROM_DATABASE=Sei S.p.A. + +OUI:0022B4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0022B5* + ID_OUI_FROM_DATABASE=NOVITA + +OUI:0022B6* + ID_OUI_FROM_DATABASE=Superflow Technologies Group + +OUI:0022B7* + ID_OUI_FROM_DATABASE=GSS Grundig SAT-Systems GmbH + +OUI:0022B8* + ID_OUI_FROM_DATABASE=Norcott + +OUI:0022B9* + ID_OUI_FROM_DATABASE=Analogix Seminconductor, Inc + +OUI:0022BA* + ID_OUI_FROM_DATABASE=HUTH Elektronik Systeme GmbH + +OUI:0022BB* + ID_OUI_FROM_DATABASE=beyerdynamic GmbH & Co. KG + +OUI:0022BC* + ID_OUI_FROM_DATABASE=JDSU France SAS + +OUI:0022BD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0022BE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0022BF* + ID_OUI_FROM_DATABASE=SieAmp Group of Companies + +OUI:0022C0* + ID_OUI_FROM_DATABASE=Shenzhen Forcelink Electronic Co, Ltd + +OUI:0022C1* + ID_OUI_FROM_DATABASE=Active Storage Inc. + +OUI:0022C2* + ID_OUI_FROM_DATABASE=Proview Eletrônica do Brasil LTDA + +OUI:0022C3* + ID_OUI_FROM_DATABASE=Zeeport Technology Inc. + +OUI:0022C4* + ID_OUI_FROM_DATABASE=epro GmbH + +OUI:0022C5* + ID_OUI_FROM_DATABASE=INFORSON Co,Ltd. + +OUI:0022C6* + ID_OUI_FROM_DATABASE=Sutus Inc + +OUI:0022C7* + ID_OUI_FROM_DATABASE=SEGGER Microcontroller GmbH & Co. KG + +OUI:0022C8* + ID_OUI_FROM_DATABASE=Applied Instruments B.V. + +OUI:0022C9* + ID_OUI_FROM_DATABASE=Lenord, Bauer & Co GmbH + +OUI:0022CA* + ID_OUI_FROM_DATABASE=Anviz Biometric Tech. Co., Ltd. + +OUI:0022CB* + ID_OUI_FROM_DATABASE=IONODES Inc. + +OUI:0022CC* + ID_OUI_FROM_DATABASE=SciLog, Inc. + +OUI:0022CD* + ID_OUI_FROM_DATABASE=Ared Technology Co., Ltd. + +OUI:0022CE* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:0022CF* + ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. + +OUI:0022D0* + ID_OUI_FROM_DATABASE=Polar Electro Oy + +OUI:0022D1* + ID_OUI_FROM_DATABASE=Albrecht Jung GmbH & Co. KG + +OUI:0022D2* + ID_OUI_FROM_DATABASE=All Earth Comércio de Eletrônicos LTDA. + +OUI:0022D3* + ID_OUI_FROM_DATABASE=Hub-Tech + +OUI:0022D4* + ID_OUI_FROM_DATABASE=ComWorth Co., Ltd. + +OUI:0022D5* + ID_OUI_FROM_DATABASE=Eaton Corp. Electrical Group Data Center Solutions - Pulizzi + +OUI:0022D6* + ID_OUI_FROM_DATABASE=Cypak AB + +OUI:0022D7* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:0022D8* + ID_OUI_FROM_DATABASE=Shenzhen GST Security and Safety Technology Limited + +OUI:0022D9* + ID_OUI_FROM_DATABASE=Fortex Industrial Ltd. + +OUI:0022DA* + ID_OUI_FROM_DATABASE=ANATEK, LLC + +OUI:0022DB* + ID_OUI_FROM_DATABASE=Translogic Corporation + +OUI:0022DC* + ID_OUI_FROM_DATABASE=Vigil Health Solutions Inc. + +OUI:0022DD* + ID_OUI_FROM_DATABASE=Protecta Electronics Ltd + +OUI:0022DE* + ID_OUI_FROM_DATABASE=OPPO Digital, Inc. + +OUI:0022DF* + ID_OUI_FROM_DATABASE=TAMUZ Monitors + +OUI:0022E0* + ID_OUI_FROM_DATABASE=Atlantic Software Technologies S.r.L. + +OUI:0022E1* + ID_OUI_FROM_DATABASE=ZORT Labs, LLC. + +OUI:0022E2* + ID_OUI_FROM_DATABASE=WABTEC Transit Division + +OUI:0022E3* + ID_OUI_FROM_DATABASE=Amerigon + +OUI:0022E4* + ID_OUI_FROM_DATABASE=APASS TECHNOLOGY CO., LTD. + +OUI:0022E5* + ID_OUI_FROM_DATABASE=Fisher-Rosemount Systems Inc. + +OUI:0022E6* + ID_OUI_FROM_DATABASE=Intelligent Data + +OUI:0022E7* + ID_OUI_FROM_DATABASE=WPS Parking Systems + +OUI:0022E8* + ID_OUI_FROM_DATABASE=Applition Co., Ltd. + +OUI:0022E9* + ID_OUI_FROM_DATABASE=ProVision Communications + +OUI:0022EA* + ID_OUI_FROM_DATABASE=Rustelcom Inc. + +OUI:0022EB* + ID_OUI_FROM_DATABASE=Data Respons A/S + +OUI:0022EC* + ID_OUI_FROM_DATABASE=IDEALBT TECHNOLOGY CORPORATION + +OUI:0022ED* + ID_OUI_FROM_DATABASE=TSI Power Corporation + +OUI:0022EE* + ID_OUI_FROM_DATABASE=Algo Communication Products Ltd + +OUI:0022EF* + ID_OUI_FROM_DATABASE=iWDL Technologies + +OUI:0022F0* + ID_OUI_FROM_DATABASE=3 Greens Aviation Limited + +OUI:0022F1* + ID_OUI_FROM_DATABASE=Private + +OUI:0022F2* + ID_OUI_FROM_DATABASE=SunPower Corp + +OUI:0022F3* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:0022F4* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:0022F5* + ID_OUI_FROM_DATABASE=Advanced Realtime Tracking GmbH + +OUI:0022F6* + ID_OUI_FROM_DATABASE=Syracuse Research Corporation + +OUI:0022F7* + ID_OUI_FROM_DATABASE=Conceptronic + +OUI:0022F8* + ID_OUI_FROM_DATABASE=PIMA Electronic Systems Ltd. + +OUI:0022F9* + ID_OUI_FROM_DATABASE=Pollin Electronic GmbH + +OUI:0022FA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0022FB* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0022FC* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0022FD* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0022FE* + ID_OUI_FROM_DATABASE=Advanced Illumination + +OUI:0022FF* + ID_OUI_FROM_DATABASE=NIVIS LLC + +OUI:002300* + ID_OUI_FROM_DATABASE=Cayee Computer Ltd. + +OUI:002301* + ID_OUI_FROM_DATABASE=Witron Technology Limited + +OUI:002302* + ID_OUI_FROM_DATABASE=Cobalt Digital, Inc. + +OUI:002303* + ID_OUI_FROM_DATABASE=LITE-ON IT Corporation + +OUI:002304* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002305* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002306* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:002307* + ID_OUI_FROM_DATABASE=FUTURE INNOVATION TECH CO.,LTD + +OUI:002308* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:002309* + ID_OUI_FROM_DATABASE=Janam Technologies LLC + +OUI:00230A* + ID_OUI_FROM_DATABASE=ARBURG GmbH & Co KG + +OUI:00230B* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00230C* + ID_OUI_FROM_DATABASE=CLOVER ELECTRONICS CO.,LTD. + +OUI:00230D* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:00230E* + ID_OUI_FROM_DATABASE=Gorba AG + +OUI:00230F* + ID_OUI_FROM_DATABASE=Hirsch Electronics Corporation + +OUI:002310* + ID_OUI_FROM_DATABASE=LNC Technology Co., Ltd. + +OUI:002311* + ID_OUI_FROM_DATABASE=Gloscom Co., Ltd. + +OUI:002312* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:002313* + ID_OUI_FROM_DATABASE=Qool Technologies Ltd. + +OUI:002314* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:002315* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:002316* + ID_OUI_FROM_DATABASE=KISAN ELECTRONICS CO + +OUI:002317* + ID_OUI_FROM_DATABASE=Lasercraft Inc + +OUI:002318* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:002319* + ID_OUI_FROM_DATABASE=Sielox LLC + +OUI:00231A* + ID_OUI_FROM_DATABASE=ITF Co., Ltd. + +OUI:00231B* + ID_OUI_FROM_DATABASE=Danaher Motion - Kollmorgen + +OUI:00231C* + ID_OUI_FROM_DATABASE=Fourier Systems Ltd. + +OUI:00231D* + ID_OUI_FROM_DATABASE=Deltacom Electronics Ltd + +OUI:00231E* + ID_OUI_FROM_DATABASE=Cezzer Multimedia Technologies + +OUI:00231F* + ID_OUI_FROM_DATABASE=Guangda Electronic & Telecommunication Technology Development Co., Ltd. + +OUI:002320* + ID_OUI_FROM_DATABASE=Nicira Networks + +OUI:002321* + ID_OUI_FROM_DATABASE=Avitech International Corp + +OUI:002322* + ID_OUI_FROM_DATABASE=KISS Teknical Solutions, Inc. + +OUI:002323* + ID_OUI_FROM_DATABASE=Zylin AS + +OUI:002324* + ID_OUI_FROM_DATABASE=G-PRO COMPUTER + +OUI:002325* + ID_OUI_FROM_DATABASE=IOLAN Holding + +OUI:002326* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:002327* + ID_OUI_FROM_DATABASE=Shouyo Electronics CO., LTD + +OUI:002328* + ID_OUI_FROM_DATABASE=ALCON TELECOMMUNICATIONS CO., LTD. + +OUI:002329* + ID_OUI_FROM_DATABASE=DDRdrive LLC + +OUI:00232A* + ID_OUI_FROM_DATABASE=eonas IT-Beratung und -Entwicklung GmbH + +OUI:00232B* + ID_OUI_FROM_DATABASE=IRD A/S + +OUI:00232C* + ID_OUI_FROM_DATABASE=Senticare + +OUI:00232D* + ID_OUI_FROM_DATABASE=SandForce + +OUI:00232E* + ID_OUI_FROM_DATABASE=Kedah Electronics Engineering, LLC + +OUI:00232F* + ID_OUI_FROM_DATABASE=Advanced Card Systems Ltd. + +OUI:002330* + ID_OUI_FROM_DATABASE=DIZIPIA, INC. + +OUI:002331* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:002332* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:002333* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002334* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002335* + ID_OUI_FROM_DATABASE=Linkflex Co.,Ltd + +OUI:002336* + ID_OUI_FROM_DATABASE=METEL s.r.o. + +OUI:002337* + ID_OUI_FROM_DATABASE=Global Star Solutions ULC + +OUI:002338* + ID_OUI_FROM_DATABASE=OJ-Electronics A/S + +OUI:002339* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00233A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00233B* + ID_OUI_FROM_DATABASE=C-Matic Systems Ltd + +OUI:00233C* + ID_OUI_FROM_DATABASE=Alflex + +OUI:00233D* + ID_OUI_FROM_DATABASE=Laird Technologies + +OUI:00233E* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:00233F* + ID_OUI_FROM_DATABASE=Purechoice Inc + +OUI:002340* + ID_OUI_FROM_DATABASE=MiXTelematics + +OUI:002341* + ID_OUI_FROM_DATABASE=Vanderbilt International (SWE) AB + +OUI:002342* + ID_OUI_FROM_DATABASE=Coffee Equipment Company + +OUI:002343* + ID_OUI_FROM_DATABASE=TEM AG + +OUI:002344* + ID_OUI_FROM_DATABASE=Objective Interface Systems, Inc. + +OUI:002345* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:002346* + ID_OUI_FROM_DATABASE=Vestac + +OUI:002347* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP + +OUI:002348* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:002349* + ID_OUI_FROM_DATABASE=Helmholtz Centre Berlin for Material and Energy + +OUI:00234A* + ID_OUI_FROM_DATABASE=Private + +OUI:00234B* + ID_OUI_FROM_DATABASE=Inyuan Technology Inc. + +OUI:00234C* + ID_OUI_FROM_DATABASE=KTC AB + +OUI:00234D* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:00234E* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:00234F* + ID_OUI_FROM_DATABASE=Luminous Power Technologies Pvt. Ltd. + +OUI:002350* + ID_OUI_FROM_DATABASE=RDC, Inc. dba LynTec + +OUI:002351* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:002352* + ID_OUI_FROM_DATABASE=DATASENSOR S.p.A. + +OUI:002353* + ID_OUI_FROM_DATABASE=F E T Elettronica snc + +OUI:002354* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:002355* + ID_OUI_FROM_DATABASE=Kinco Automation(Shanghai) Ltd. + +OUI:002356* + ID_OUI_FROM_DATABASE=Packet Forensics LLC + +OUI:002357* + ID_OUI_FROM_DATABASE=Pitronot Technologies and Engineering P.T.E. Ltd. + +OUI:002358* + ID_OUI_FROM_DATABASE=SYSTEL SA + +OUI:002359* + ID_OUI_FROM_DATABASE=Benchmark Electronics ( Thailand ) Public Company Limited + +OUI:00235A* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:00235B* + ID_OUI_FROM_DATABASE=Gulfstream + +OUI:00235C* + ID_OUI_FROM_DATABASE=Aprius, Inc. + +OUI:00235D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00235E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00235F* + ID_OUI_FROM_DATABASE=Silicon Micro Sensors GmbH + +OUI:002360* + ID_OUI_FROM_DATABASE=Lookit Technology Co., Ltd + +OUI:002361* + ID_OUI_FROM_DATABASE=Unigen Corporation + +OUI:002362* + ID_OUI_FROM_DATABASE=Goldline Controls + +OUI:002363* + ID_OUI_FROM_DATABASE=Zhuhai Raysharp Technology Co.,Ltd + +OUI:002364* + ID_OUI_FROM_DATABASE=Power Instruments Pte Ltd + +OUI:002365* + ID_OUI_FROM_DATABASE=Insta Elektro GmbH + +OUI:002366* + ID_OUI_FROM_DATABASE=Beijing Siasun Electronic System Co.,Ltd. + +OUI:002367* + ID_OUI_FROM_DATABASE=UniControls a.s. + +OUI:002368* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc + +OUI:002369* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:00236A* + ID_OUI_FROM_DATABASE=SmartRG Inc + +OUI:00236B* + ID_OUI_FROM_DATABASE=Xembedded, Inc. + +OUI:00236C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00236D* + ID_OUI_FROM_DATABASE=ResMed Ltd + +OUI:00236E* + ID_OUI_FROM_DATABASE=Burster GmbH & Co KG + +OUI:00236F* + ID_OUI_FROM_DATABASE=DAQ System + +OUI:002370* + ID_OUI_FROM_DATABASE=Snell + +OUI:002371* + ID_OUI_FROM_DATABASE=SOAM Systel + +OUI:002372* + ID_OUI_FROM_DATABASE=MORE STAR INDUSTRIAL GROUP LIMITED + +OUI:002373* + ID_OUI_FROM_DATABASE=GridIron Systems, Inc. + +OUI:002374* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002375* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002376* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:002377* + ID_OUI_FROM_DATABASE=Isotek Electronics Ltd + +OUI:002378* + ID_OUI_FROM_DATABASE=GN Netcom A/S + +OUI:002379* + ID_OUI_FROM_DATABASE=Union Business Machines Co. Ltd. + +OUI:00237A* + ID_OUI_FROM_DATABASE=RIM + +OUI:00237B* + ID_OUI_FROM_DATABASE=WHDI LLC + +OUI:00237C* + ID_OUI_FROM_DATABASE=NEOTION + +OUI:00237D* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:00237E* + ID_OUI_FROM_DATABASE=ELSTER GMBH + +OUI:00237F* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. + +OUI:002380* + ID_OUI_FROM_DATABASE=Nanoteq + +OUI:002381* + ID_OUI_FROM_DATABASE=Lengda Technology(Xiamen) Co.,Ltd. + +OUI:002382* + ID_OUI_FROM_DATABASE=Lih Rong electronic Enterprise Co., Ltd. + +OUI:002383* + ID_OUI_FROM_DATABASE=InMage Systems Inc + +OUI:002384* + ID_OUI_FROM_DATABASE=GGH Engineering s.r.l. + +OUI:002385* + ID_OUI_FROM_DATABASE=ANTIPODE + +OUI:002386* + ID_OUI_FROM_DATABASE=Tour & Andersson AB + +OUI:002387* + ID_OUI_FROM_DATABASE=ThinkFlood, Inc. + +OUI:002388* + ID_OUI_FROM_DATABASE=V.T. Telematica S.p.a. + +OUI:002389* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:00238A* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:00238B* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:00238C* + ID_OUI_FROM_DATABASE=Private + +OUI:00238D* + ID_OUI_FROM_DATABASE=Techno Design Co., Ltd. + +OUI:00238E* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:00238F* + ID_OUI_FROM_DATABASE=NIDEC COPAL CORPORATION + +OUI:002390* + ID_OUI_FROM_DATABASE=Algolware Corporation + +OUI:002391* + ID_OUI_FROM_DATABASE=Maxian + +OUI:002392* + ID_OUI_FROM_DATABASE=Proteus Industries Inc. + +OUI:002393* + ID_OUI_FROM_DATABASE=AJINEXTEK + +OUI:002394* + ID_OUI_FROM_DATABASE=Samjeon + +OUI:002395* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002396* + ID_OUI_FROM_DATABASE=ANDES TECHNOLOGY CORPORATION + +OUI:002397* + ID_OUI_FROM_DATABASE=Westell Technologies Inc. + +OUI:002398* + ID_OUI_FROM_DATABASE=Vutlan sro + +OUI:002399* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00239A* + ID_OUI_FROM_DATABASE=EasyData Hardware GmbH + +OUI:00239B* + ID_OUI_FROM_DATABASE=Elster Solutions, LLC + +OUI:00239C* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:00239D* + ID_OUI_FROM_DATABASE=Mapower Electronics Co., Ltd + +OUI:00239E* + ID_OUI_FROM_DATABASE=Jiangsu Lemote Technology Corporation Limited + +OUI:00239F* + ID_OUI_FROM_DATABASE=Institut für Prüftechnik + +OUI:0023A0* + ID_OUI_FROM_DATABASE=Hana CNS Co., LTD. + +OUI:0023A1* + ID_OUI_FROM_DATABASE=Trend Electronics Ltd + +OUI:0023A2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0023A3* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0023A4* + ID_OUI_FROM_DATABASE=New Concepts Development Corp. + +OUI:0023A5* + ID_OUI_FROM_DATABASE=SageTV, LLC + +OUI:0023A6* + ID_OUI_FROM_DATABASE=E-Mon + +OUI:0023A7* + ID_OUI_FROM_DATABASE=Redpine Signals, Inc. + +OUI:0023A8* + ID_OUI_FROM_DATABASE=Marshall Electronics + +OUI:0023A9* + ID_OUI_FROM_DATABASE=Beijing Detianquan Electromechanical Equipment Co., Ltd + +OUI:0023AA* + ID_OUI_FROM_DATABASE=HFR, Inc. + +OUI:0023AB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0023AC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0023AD* + ID_OUI_FROM_DATABASE=Xmark Corporation + +OUI:0023AE* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:0023AF* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0023B0* + ID_OUI_FROM_DATABASE=COMXION Technology Inc. + +OUI:0023B1* + ID_OUI_FROM_DATABASE=Longcheer Technology (Singapore) Pte Ltd + +OUI:0023B2* + ID_OUI_FROM_DATABASE=Intelligent Mechatronic Systems Inc + +OUI:0023B3* + ID_OUI_FROM_DATABASE=Lyyn AB + +OUI:0023B4* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0023B5* + ID_OUI_FROM_DATABASE=ORTANA LTD + +OUI:0023B6* + ID_OUI_FROM_DATABASE=SECURITE COMMUNICATIONS / HONEYWELL + +OUI:0023B7* + ID_OUI_FROM_DATABASE=Q-Light Co., Ltd. + +OUI:0023B8* + ID_OUI_FROM_DATABASE=Sichuan Jiuzhou Electronic Technology Co.,Ltd + +OUI:0023B9* + ID_OUI_FROM_DATABASE=Airbus Defence and Space Deutschland GmbH + +OUI:0023BA* + ID_OUI_FROM_DATABASE=Chroma + +OUI:0023BB* + ID_OUI_FROM_DATABASE=Schmitt Industries + +OUI:0023BC* + ID_OUI_FROM_DATABASE=EQ-SYS GmbH + +OUI:0023BD* + ID_OUI_FROM_DATABASE=Digital Ally, Inc. + +OUI:0023BE* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:0023BF* + ID_OUI_FROM_DATABASE=Mainpine, Inc. + +OUI:0023C0* + ID_OUI_FROM_DATABASE=Broadway Networks + +OUI:0023C1* + ID_OUI_FROM_DATABASE=Securitas Direct AB + +OUI:0023C2* + ID_OUI_FROM_DATABASE=SAMSUNG Electronics. Co. LTD + +OUI:0023C3* + ID_OUI_FROM_DATABASE=LogMeIn, Inc. + +OUI:0023C4* + ID_OUI_FROM_DATABASE=Lux Lumen + +OUI:0023C5* + ID_OUI_FROM_DATABASE=Radiation Safety and Control Services Inc + +OUI:0023C6* + ID_OUI_FROM_DATABASE=SMC Corporation + +OUI:0023C7* + ID_OUI_FROM_DATABASE=AVSystem + +OUI:0023C8* + ID_OUI_FROM_DATABASE=TEAM-R + +OUI:0023C9* + ID_OUI_FROM_DATABASE=Sichuan Tianyi Information Science & Technology Stock CO.,LTD + +OUI:0023CA* + ID_OUI_FROM_DATABASE=Behind The Set, LLC + +OUI:0023CB* + ID_OUI_FROM_DATABASE=Shenzhen Full-join Technology Co.,Ltd + +OUI:0023CC* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:0023CD* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:0023CE* + ID_OUI_FROM_DATABASE=KITA DENSHI CORPORATION + +OUI:0023CF* + ID_OUI_FROM_DATABASE=CUMMINS-ALLISON CORP. + +OUI:0023D0* + ID_OUI_FROM_DATABASE=Uniloc USA Inc. + +OUI:0023D1* + ID_OUI_FROM_DATABASE=TRG + +OUI:0023D2* + ID_OUI_FROM_DATABASE=Inhand Electronics, Inc. + +OUI:0023D3* + ID_OUI_FROM_DATABASE=AirLink WiFi Networking Corp. + +OUI:0023D4* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0023D5* + ID_OUI_FROM_DATABASE=WAREMA electronic GmbH + +OUI:0023D6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0023D7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0023D8* + ID_OUI_FROM_DATABASE=Ball-It Oy + +OUI:0023D9* + ID_OUI_FROM_DATABASE=Banner Engineering + +OUI:0023DA* + ID_OUI_FROM_DATABASE=Industrial Computer Source (Deutschland)GmbH + +OUI:0023DB* + ID_OUI_FROM_DATABASE=saxnet gmbh + +OUI:0023DC* + ID_OUI_FROM_DATABASE=Benein, Inc + +OUI:0023DD* + ID_OUI_FROM_DATABASE=ELGIN S.A. + +OUI:0023DE* + ID_OUI_FROM_DATABASE=Ansync Inc. + +OUI:0023DF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0023E0* + ID_OUI_FROM_DATABASE=INO Therapeutics LLC + +OUI:0023E1* + ID_OUI_FROM_DATABASE=Cavena Image Products AB + +OUI:0023E2* + ID_OUI_FROM_DATABASE=SEA Signalisation + +OUI:0023E3* + ID_OUI_FROM_DATABASE=Microtronic AG + +OUI:0023E4* + ID_OUI_FROM_DATABASE=IPnect co. ltd. + +OUI:0023E5* + ID_OUI_FROM_DATABASE=IPaXiom Networks + +OUI:0023E6* + ID_OUI_FROM_DATABASE=Innovation Farm, Inc. + +OUI:0023E7* + ID_OUI_FROM_DATABASE=Hinke A/S + +OUI:0023E8* + ID_OUI_FROM_DATABASE=Demco Corp. + +OUI:0023E9* + ID_OUI_FROM_DATABASE=F5 Networks, Inc. + +OUI:0023EA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0023EB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0023EC* + ID_OUI_FROM_DATABASE=Algorithmix GmbH + +OUI:0023ED* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0023EE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0023EF* + ID_OUI_FROM_DATABASE=Zuend Systemtechnik AG + +OUI:0023F0* + ID_OUI_FROM_DATABASE=Shanghai Jinghan Weighing Apparatus Co. Ltd. + +OUI:0023F1* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:0023F2* + ID_OUI_FROM_DATABASE=TVLogic + +OUI:0023F3* + ID_OUI_FROM_DATABASE=Glocom, Inc. + +OUI:0023F4* + ID_OUI_FROM_DATABASE=Masternaut + +OUI:0023F5* + ID_OUI_FROM_DATABASE=WILO SE + +OUI:0023F6* + ID_OUI_FROM_DATABASE=Softwell Technology Co., Ltd. + +OUI:0023F7* + ID_OUI_FROM_DATABASE=Private + +OUI:0023F8* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:0023F9* + ID_OUI_FROM_DATABASE=Double-Take Software, INC. + +OUI:0023FA* + ID_OUI_FROM_DATABASE=RG Nets, Inc. + +OUI:0023FB* + ID_OUI_FROM_DATABASE=IP Datatel, LLC. + +OUI:0023FC* + ID_OUI_FROM_DATABASE=Ultra Stereo Labs, Inc + +OUI:0023FD* + ID_OUI_FROM_DATABASE=AFT Atlas Fahrzeugtechnik GmbH + +OUI:0023FE* + ID_OUI_FROM_DATABASE=Biodevices, SA + +OUI:0023FF* + ID_OUI_FROM_DATABASE=Beijing HTTC Technology Ltd. + +OUI:002400* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:002401* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:002402* + ID_OUI_FROM_DATABASE=Op-Tection GmbH + +OUI:002403* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:002404* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:002405* + ID_OUI_FROM_DATABASE=Dilog Nordic AB + +OUI:002406* + ID_OUI_FROM_DATABASE=Pointmobile + +OUI:002407* + ID_OUI_FROM_DATABASE=TELEM SAS + +OUI:002408* + ID_OUI_FROM_DATABASE=Pacific Biosciences + +OUI:002409* + ID_OUI_FROM_DATABASE=The Toro Company + +OUI:00240A* + ID_OUI_FROM_DATABASE=US Beverage Net + +OUI:00240B* + ID_OUI_FROM_DATABASE=Virtual Computer Inc. + +OUI:00240C* + ID_OUI_FROM_DATABASE=DELEC GmbH + +OUI:00240D* + ID_OUI_FROM_DATABASE=OnePath Networks LTD. + +OUI:00240E* + ID_OUI_FROM_DATABASE=Inventec Besta Co., Ltd. + +OUI:00240F* + ID_OUI_FROM_DATABASE=Ishii Tool & Engineering Corporation + +OUI:002410* + ID_OUI_FROM_DATABASE=NUETEQ Technology,Inc. + +OUI:002411* + ID_OUI_FROM_DATABASE=PharmaSmart LLC + +OUI:002412* + ID_OUI_FROM_DATABASE=Benign Technologies Co, Ltd. + +OUI:002413* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002414* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002415* + ID_OUI_FROM_DATABASE=Magnetic Autocontrol GmbH + +OUI:002416* + ID_OUI_FROM_DATABASE=Any Use + +OUI:002417* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium + +OUI:002418* + ID_OUI_FROM_DATABASE=Nextwave Semiconductor + +OUI:002419* + ID_OUI_FROM_DATABASE=Private + +OUI:00241A* + ID_OUI_FROM_DATABASE=Red Beetle Inc. + +OUI:00241B* + ID_OUI_FROM_DATABASE=iWOW Communications Pte Ltd + +OUI:00241C* + ID_OUI_FROM_DATABASE=FuGang Electronic (DG) Co.,Ltd + +OUI:00241D* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:00241E* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:00241F* + ID_OUI_FROM_DATABASE=DCT-Delta GmbH + +OUI:002420* + ID_OUI_FROM_DATABASE=NetUP Inc. + +OUI:002421* + ID_OUI_FROM_DATABASE=MICRO-STAR INT'L CO., LTD. + +OUI:002422* + ID_OUI_FROM_DATABASE=Knapp Logistik Automation GmbH + +OUI:002423* + ID_OUI_FROM_DATABASE=AzureWave Technologies (Shanghai) Inc. + +OUI:002424* + ID_OUI_FROM_DATABASE=Ace Axis Limited + +OUI:002425* + ID_OUI_FROM_DATABASE=Shenzhenshi chuangzhicheng Technology Co.,Ltd + +OUI:002426* + ID_OUI_FROM_DATABASE=NOHMI BOSAI LTD. + +OUI:002427* + ID_OUI_FROM_DATABASE=SSI COMPUTER CORP + +OUI:002428* + ID_OUI_FROM_DATABASE=EnergyICT + +OUI:002429* + ID_OUI_FROM_DATABASE=MK MASTER INC. + +OUI:00242A* + ID_OUI_FROM_DATABASE=Hittite Microwave Corporation + +OUI:00242B* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:00242C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:00242E* + ID_OUI_FROM_DATABASE=Datastrip Inc. + +OUI:00242F* + ID_OUI_FROM_DATABASE=Micron + +OUI:002430* + ID_OUI_FROM_DATABASE=Ruby Tech Corp. + +OUI:002431* + ID_OUI_FROM_DATABASE=Uni-v co.,ltd + +OUI:002432* + ID_OUI_FROM_DATABASE=Neostar Technology Co.,LTD + +OUI:002433* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:002434* + ID_OUI_FROM_DATABASE=Lectrosonics, Inc. + +OUI:002435* + ID_OUI_FROM_DATABASE=WIDE CORPORATION + +OUI:002436* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:002437* + ID_OUI_FROM_DATABASE=Motorola - BSG + +OUI:002438* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:002439* + ID_OUI_FROM_DATABASE=Digital Barriers Advanced Technologies + +OUI:00243A* + ID_OUI_FROM_DATABASE=Ludl Electronic Products + +OUI:00243B* + ID_OUI_FROM_DATABASE=CSSI (S) Pte Ltd + +OUI:00243C* + ID_OUI_FROM_DATABASE=S.A.A.A. + +OUI:00243D* + ID_OUI_FROM_DATABASE=Emerson Appliance Motors and Controls + +OUI:00243F* + ID_OUI_FROM_DATABASE=Storwize, Inc. + +OUI:002440* + ID_OUI_FROM_DATABASE=Halo Monitoring, Inc. + +OUI:002441* + ID_OUI_FROM_DATABASE=Wanzl Metallwarenfabrik GmbH + +OUI:002442* + ID_OUI_FROM_DATABASE=Axona Limited + +OUI:002443* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:002444* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:002445* + ID_OUI_FROM_DATABASE=Adtran Inc + +OUI:002446* + ID_OUI_FROM_DATABASE=MMB Research Inc. + +OUI:002447* + ID_OUI_FROM_DATABASE=Kaztek Systems + +OUI:002448* + ID_OUI_FROM_DATABASE=SpiderCloud Wireless, Inc + +OUI:002449* + ID_OUI_FROM_DATABASE=Shen Zhen Lite Star Electronics Technology Co., Ltd + +OUI:00244A* + ID_OUI_FROM_DATABASE=Voyant International + +OUI:00244B* + ID_OUI_FROM_DATABASE=PERCEPTRON INC + +OUI:00244C* + ID_OUI_FROM_DATABASE=Solartron Metrology Ltd + +OUI:00244D* + ID_OUI_FROM_DATABASE=Hokkaido Electronics Corporation + +OUI:00244E* + ID_OUI_FROM_DATABASE=RadChips, Inc. + +OUI:00244F* + ID_OUI_FROM_DATABASE=Asantron Technologies Ltd. + +OUI:002450* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002451* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002452* + ID_OUI_FROM_DATABASE=Silicon Software GmbH + +OUI:002453* + ID_OUI_FROM_DATABASE=Initra d.o.o. + +OUI:002454* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:002455* + ID_OUI_FROM_DATABASE=MuLogic BV + +OUI:002456* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:002458* + ID_OUI_FROM_DATABASE=PA Bastion CC + +OUI:002459* + ID_OUI_FROM_DATABASE=ABB Automation products GmbH + +OUI:00245A* + ID_OUI_FROM_DATABASE=Nanjing Panda Electronics Company Limited + +OUI:00245B* + ID_OUI_FROM_DATABASE=RAIDON TECHNOLOGY, INC. + +OUI:00245C* + ID_OUI_FROM_DATABASE=Design-Com Technologies Pty. Ltd. + +OUI:00245D* + ID_OUI_FROM_DATABASE=Terberg besturingstechniek B.V. + +OUI:00245E* + ID_OUI_FROM_DATABASE=Hivision Co.,ltd + +OUI:00245F* + ID_OUI_FROM_DATABASE=Vine Telecom CO.,Ltd. + +OUI:002460* + ID_OUI_FROM_DATABASE=Giaval Science Development Co. Ltd. + +OUI:002461* + ID_OUI_FROM_DATABASE=Shin Wang Tech. + +OUI:002462* + ID_OUI_FROM_DATABASE=Rayzone Corporation + +OUI:002463* + ID_OUI_FROM_DATABASE=Phybridge Inc + +OUI:002464* + ID_OUI_FROM_DATABASE=Bridge Technologies Co AS + +OUI:002465* + ID_OUI_FROM_DATABASE=Elentec + +OUI:002466* + ID_OUI_FROM_DATABASE=Unitron nv + +OUI:002467* + ID_OUI_FROM_DATABASE=AOC International (Europe) GmbH + +OUI:002468* + ID_OUI_FROM_DATABASE=Sumavision Technologies Co.,Ltd + +OUI:002469* + ID_OUI_FROM_DATABASE=Smart Doorphones + +OUI:00246A* + ID_OUI_FROM_DATABASE=Solid Year Co., Ltd. + +OUI:00246B* + ID_OUI_FROM_DATABASE=Covia, Inc. + +OUI:00246C* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:00246D* + ID_OUI_FROM_DATABASE=Weinzierl Engineering GmbH + +OUI:00246E* + ID_OUI_FROM_DATABASE=Phihong USA Corp. + +OUI:00246F* + ID_OUI_FROM_DATABASE=Onda Communication spa + +OUI:002470* + ID_OUI_FROM_DATABASE=AUROTECH ultrasound AS. + +OUI:002471* + ID_OUI_FROM_DATABASE=Fusion MultiSystems dba Fusion-io + +OUI:002472* + ID_OUI_FROM_DATABASE=ReDriven Power Inc. + +OUI:002473* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:002474* + ID_OUI_FROM_DATABASE=Autronica Fire And Securirty + +OUI:002475* + ID_OUI_FROM_DATABASE=Compass System(Embedded Dept.) + +OUI:002476* + ID_OUI_FROM_DATABASE=TAP.tv + +OUI:002477* + ID_OUI_FROM_DATABASE=Tibbo Technology + +OUI:002478* + ID_OUI_FROM_DATABASE=Mag Tech Electronics Co Limited + +OUI:002479* + ID_OUI_FROM_DATABASE=Optec Displays, Inc. + +OUI:00247A* + ID_OUI_FROM_DATABASE=FU YI CHENG Technology Co., Ltd. + +OUI:00247B* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:00247C* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:00247D* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:00247E* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:00247F* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:002480* + ID_OUI_FROM_DATABASE=Meteocontrol GmbH + +OUI:002481* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:002482* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:002483* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:002484* + ID_OUI_FROM_DATABASE=Bang and Olufsen Medicom a/s + +OUI:002485* + ID_OUI_FROM_DATABASE=ConteXtream Ltd + +OUI:002486* + ID_OUI_FROM_DATABASE=DesignArt Networks + +OUI:002487* + ID_OUI_FROM_DATABASE=Transact Campus, Inc. + +OUI:002488* + ID_OUI_FROM_DATABASE=Centre For Development Of Telematics + +OUI:002489* + ID_OUI_FROM_DATABASE=Vodafone Omnitel N.V. + +OUI:00248A* + ID_OUI_FROM_DATABASE=Kaga Electronics Co., Ltd. + +OUI:00248B* + ID_OUI_FROM_DATABASE=HYBUS CO., LTD. + +OUI:00248C* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:00248D* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:00248E* + ID_OUI_FROM_DATABASE=Infoware ZRt. + +OUI:00248F* + ID_OUI_FROM_DATABASE=DO-MONIX + +OUI:002490* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:002491* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:002492* + ID_OUI_FROM_DATABASE=Motorola, Broadband Solutions Group + +OUI:002493* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002494* + ID_OUI_FROM_DATABASE=Shenzhen Baoxin Tech CO., Ltd. + +OUI:002495* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002496* + ID_OUI_FROM_DATABASE=Ginzinger electronic systems + +OUI:002497* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002498* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002499* + ID_OUI_FROM_DATABASE=Aquila Technologies + +OUI:00249A* + ID_OUI_FROM_DATABASE=Beijing Zhongchuang Telecommunication Test Co., Ltd. + +OUI:00249B* + ID_OUI_FROM_DATABASE=Action Star Enterprise Co., Ltd. + +OUI:00249C* + ID_OUI_FROM_DATABASE=Bimeng Comunication System Co. Ltd + +OUI:00249D* + ID_OUI_FROM_DATABASE=NES Technology Inc. + +OUI:00249E* + ID_OUI_FROM_DATABASE=ADC-Elektronik GmbH + +OUI:00249F* + ID_OUI_FROM_DATABASE=RIM Testing Services + +OUI:0024A0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0024A1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0024A2* + ID_OUI_FROM_DATABASE=Hong Kong Middleware Technology Limited + +OUI:0024A3* + ID_OUI_FROM_DATABASE=Sonim Technologies Inc + +OUI:0024A4* + ID_OUI_FROM_DATABASE=Siklu Communication + +OUI:0024A5* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:0024A6* + ID_OUI_FROM_DATABASE=TELESTAR DIGITAL GmbH + +OUI:0024A7* + ID_OUI_FROM_DATABASE=Advanced Video Communications Inc. + +OUI:0024A8* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP + +OUI:0024A9* + ID_OUI_FROM_DATABASE=Ag Leader Technology + +OUI:0024AA* + ID_OUI_FROM_DATABASE=Dycor Technologies Ltd. + +OUI:0024AB* + ID_OUI_FROM_DATABASE=A7 Engineering, Inc. + +OUI:0024AC* + ID_OUI_FROM_DATABASE=Hangzhou DPtech Technologies Co., Ltd. + +OUI:0024AD* + ID_OUI_FROM_DATABASE=Adolf Thies Gmbh & Co. KG + +OUI:0024AE* + ID_OUI_FROM_DATABASE=IDEMIA + +OUI:0024AF* + ID_OUI_FROM_DATABASE=Dish Technologies Corp + +OUI:0024B0* + ID_OUI_FROM_DATABASE=ESAB AB + +OUI:0024B1* + ID_OUI_FROM_DATABASE=Coulomb Technologies + +OUI:0024B2* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:0024B3* + ID_OUI_FROM_DATABASE=Graf-Syteco GmbH & Co. KG + +OUI:0024B4* + ID_OUI_FROM_DATABASE=ESCATRONIC GmbH + +OUI:0024B5* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:0024B6* + ID_OUI_FROM_DATABASE=Seagate Technology + +OUI:0024B7* + ID_OUI_FROM_DATABASE=GridPoint, Inc. + +OUI:0024B8* + ID_OUI_FROM_DATABASE=free alliance sdn bhd + +OUI:0024B9* + ID_OUI_FROM_DATABASE=Wuhan Higheasy Electronic Technology Development Co.Ltd + +OUI:0024BA* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0024BB* + ID_OUI_FROM_DATABASE=CENTRAL Corporation + +OUI:0024BC* + ID_OUI_FROM_DATABASE=HuRob Co.,Ltd + +OUI:0024BD* + ID_OUI_FROM_DATABASE=Hainzl Industriesysteme GmbH + +OUI:0024BE* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:0024BF* + ID_OUI_FROM_DATABASE=CIAT + +OUI:0024C0* + ID_OUI_FROM_DATABASE=NTI COMODO INC + +OUI:0024C1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0024C2* + ID_OUI_FROM_DATABASE=Asumo Co.,Ltd. + +OUI:0024C3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0024C4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0024C5* + ID_OUI_FROM_DATABASE=Meridian Audio Limited + +OUI:0024C6* + ID_OUI_FROM_DATABASE=Hager Electro SAS + +OUI:0024C7* + ID_OUI_FROM_DATABASE=Mobilarm Ltd + +OUI:0024C8* + ID_OUI_FROM_DATABASE=Broadband Solutions Group + +OUI:0024C9* + ID_OUI_FROM_DATABASE=Broadband Solutions Group + +OUI:0024CA* + ID_OUI_FROM_DATABASE=Tobii Technology AB + +OUI:0024CB* + ID_OUI_FROM_DATABASE=Autonet Mobile + +OUI:0024CC* + ID_OUI_FROM_DATABASE=Fascinations Toys and Gifts, Inc. + +OUI:0024CD* + ID_OUI_FROM_DATABASE=Willow Garage, Inc. + +OUI:0024CE* + ID_OUI_FROM_DATABASE=Exeltech Inc + +OUI:0024CF* + ID_OUI_FROM_DATABASE=Inscape Data Corporation + +OUI:0024D0* + ID_OUI_FROM_DATABASE=Shenzhen SOGOOD Industry CO.,LTD. + +OUI:0024D1* + ID_OUI_FROM_DATABASE=Thomson Inc. + +OUI:0024D2* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:0024D3* + ID_OUI_FROM_DATABASE=QUALICA Inc. + +OUI:0024D4* + ID_OUI_FROM_DATABASE=FREEBOX SAS + +OUI:0024D5* + ID_OUI_FROM_DATABASE=Winward Industrial Limited + +OUI:0024D6* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0024D7* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0024D8* + ID_OUI_FROM_DATABASE=IlSung Precision + +OUI:0024D9* + ID_OUI_FROM_DATABASE=BICOM, Inc. + +OUI:0024DA* + ID_OUI_FROM_DATABASE=Innovar Systems Limited + +OUI:0024DB* + ID_OUI_FROM_DATABASE=Alcohol Monitoring Systems + +OUI:0024DC* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:0024DD* + ID_OUI_FROM_DATABASE=Centrak, Inc. + +OUI:0024DE* + ID_OUI_FROM_DATABASE=GLOBAL Technology Inc. + +OUI:0024DF* + ID_OUI_FROM_DATABASE=Digitalbox Europe GmbH + +OUI:0024E0* + ID_OUI_FROM_DATABASE=DS Tech, LLC + +OUI:0024E1* + ID_OUI_FROM_DATABASE=Convey Computer Corp. + +OUI:0024E2* + ID_OUI_FROM_DATABASE=HASEGAWA ELECTRIC CO.,LTD. + +OUI:0024E3* + ID_OUI_FROM_DATABASE=CAO Group + +OUI:0024E4* + ID_OUI_FROM_DATABASE=Withings + +OUI:0024E5* + ID_OUI_FROM_DATABASE=Seer Technology, Inc + +OUI:0024E6* + ID_OUI_FROM_DATABASE=In Motion Technology Inc. + +OUI:0024E7* + ID_OUI_FROM_DATABASE=Plaster Networks + +OUI:0024E8* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:0024E9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0024EA* + ID_OUI_FROM_DATABASE=iris-GmbH infrared & intelligent sensors + +OUI:0024EB* + ID_OUI_FROM_DATABASE=ClearPath Networks, Inc. + +OUI:0024EC* + ID_OUI_FROM_DATABASE=United Information Technology Co.,Ltd. + +OUI:0024ED* + ID_OUI_FROM_DATABASE=YT Elec. Co,.Ltd. + +OUI:0024EE* + ID_OUI_FROM_DATABASE=Wynmax Inc. + +OUI:0024EF* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:0024F0* + ID_OUI_FROM_DATABASE=Seanodes + +OUI:0024F1* + ID_OUI_FROM_DATABASE=Shenzhen Fanhai Sanjiang Electronics Co., Ltd. + +OUI:0024F2* + ID_OUI_FROM_DATABASE=Uniphone Telecommunication Co., Ltd. + +OUI:0024F3* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:0024F4* + ID_OUI_FROM_DATABASE=Kaminario, Ltd. + +OUI:0024F5* + ID_OUI_FROM_DATABASE=NDS Surgical Imaging + +OUI:0024F6* + ID_OUI_FROM_DATABASE=MIYOSHI ELECTRONICS CORPORATION + +OUI:0024F7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0024F8* + ID_OUI_FROM_DATABASE=Technical Solutions Company Ltd. + +OUI:0024F9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0024FA* + ID_OUI_FROM_DATABASE=Hilger u. Kern GMBH + +OUI:0024FB* + ID_OUI_FROM_DATABASE=Private + +OUI:0024FC* + ID_OUI_FROM_DATABASE=QuoPin Co., Ltd. + +OUI:0024FD* + ID_OUI_FROM_DATABASE=Accedian Networks Inc + +OUI:0024FE* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:0024FF* + ID_OUI_FROM_DATABASE=QLogic Corporation + +OUI:002500* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:002501* + ID_OUI_FROM_DATABASE=JSC Supertel + +OUI:002502* + ID_OUI_FROM_DATABASE=NaturalPoint + +OUI:002503* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:002504* + ID_OUI_FROM_DATABASE=Valiant Communications Limited + +OUI:002505* + ID_OUI_FROM_DATABASE=eks Engel GmbH & Co. KG + +OUI:002506* + ID_OUI_FROM_DATABASE=A.I. ANTITACCHEGGIO ITALIA SRL + +OUI:002507* + ID_OUI_FROM_DATABASE=ASTAK Inc. + +OUI:002508* + ID_OUI_FROM_DATABASE=Maquet Cardiopulmonary AG + +OUI:002509* + ID_OUI_FROM_DATABASE=SHARETRONIC Group LTD + +OUI:00250A* + ID_OUI_FROM_DATABASE=Security Expert Co. Ltd + +OUI:00250B* + ID_OUI_FROM_DATABASE=CENTROFACTOR INC + +OUI:00250C* + ID_OUI_FROM_DATABASE=Senet Inc + +OUI:00250D* + ID_OUI_FROM_DATABASE=GZT Telkom-Telmor sp. z o.o. + +OUI:00250E* + ID_OUI_FROM_DATABASE=gt german telematics gmbh + +OUI:00250F* + ID_OUI_FROM_DATABASE=On-Ramp Wireless, Inc. + +OUI:002510* + ID_OUI_FROM_DATABASE=Pico-Tesla Magnetic Therapies + +OUI:002511* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:002512* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:002513* + ID_OUI_FROM_DATABASE=CXP DIGITAL BV + +OUI:002514* + ID_OUI_FROM_DATABASE=PC Worth Int'l Co., Ltd. + +OUI:002515* + ID_OUI_FROM_DATABASE=SFR + +OUI:002516* + ID_OUI_FROM_DATABASE=Integrated Design Tools, Inc. + +OUI:002517* + ID_OUI_FROM_DATABASE=Venntis, LLC + +OUI:002518* + ID_OUI_FROM_DATABASE=Power PLUS Communications AG + +OUI:002519* + ID_OUI_FROM_DATABASE=Viaas Inc + +OUI:00251A* + ID_OUI_FROM_DATABASE=Psiber Data Systems Inc. + +OUI:00251B* + ID_OUI_FROM_DATABASE=Philips CareServant + +OUI:00251C* + ID_OUI_FROM_DATABASE=EDT + +OUI:00251D* + ID_OUI_FROM_DATABASE=DSA Encore, LLC + +OUI:00251E* + ID_OUI_FROM_DATABASE=ROTEL TECHNOLOGIES + +OUI:00251F* + ID_OUI_FROM_DATABASE=ZYNUS VISION INC. + +OUI:002520* + ID_OUI_FROM_DATABASE=SMA Railway Technology GmbH + +OUI:002521* + ID_OUI_FROM_DATABASE=Logitek Electronic Systems, Inc. + +OUI:002522* + ID_OUI_FROM_DATABASE=ASRock Incorporation + +OUI:002523* + ID_OUI_FROM_DATABASE=OCP Inc. + +OUI:002524* + ID_OUI_FROM_DATABASE=Lightcomm Technology Co., Ltd + +OUI:002525* + ID_OUI_FROM_DATABASE=CTERA Networks Ltd. + +OUI:002526* + ID_OUI_FROM_DATABASE=Genuine Technologies Co., Ltd. + +OUI:002527* + ID_OUI_FROM_DATABASE=Bitrode Corp. + +OUI:002528* + ID_OUI_FROM_DATABASE=Daido Signal Co., Ltd. + +OUI:002529* + ID_OUI_FROM_DATABASE=COMELIT GROUP S.P.A + +OUI:00252A* + ID_OUI_FROM_DATABASE=Chengdu GeeYa Technology Co.,LTD + +OUI:00252B* + ID_OUI_FROM_DATABASE=Stirling Energy Systems + +OUI:00252C* + ID_OUI_FROM_DATABASE=Entourage Systems, Inc. + +OUI:00252D* + ID_OUI_FROM_DATABASE=Kiryung Electronics + +OUI:00252E* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:00252F* + ID_OUI_FROM_DATABASE=Energy, Inc. + +OUI:002530* + ID_OUI_FROM_DATABASE=Aetas Systems Inc. + +OUI:002531* + ID_OUI_FROM_DATABASE=Cloud Engines, Inc. + +OUI:002532* + ID_OUI_FROM_DATABASE=Digital Recorders + +OUI:002533* + ID_OUI_FROM_DATABASE=WITTENSTEIN AG + +OUI:002535* + ID_OUI_FROM_DATABASE=Minimax GmbH & Co KG + +OUI:002536* + ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd. + +OUI:002537* + ID_OUI_FROM_DATABASE=Runcom Technologies Ltd. + +OUI:002538* + ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd., Memory Division + +OUI:002539* + ID_OUI_FROM_DATABASE=IfTA GmbH + +OUI:00253A* + ID_OUI_FROM_DATABASE=CEVA, Ltd. + +OUI:00253B* + ID_OUI_FROM_DATABASE=din Dietmar Nocker Facilitymanagement GmbH + +OUI:00253C* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:00253D* + ID_OUI_FROM_DATABASE=DRS Consolidated Controls + +OUI:00253E* + ID_OUI_FROM_DATABASE=Sensus Metering Systems + +OUI:002540* + ID_OUI_FROM_DATABASE=Quasar Technologies, Inc. + +OUI:002541* + ID_OUI_FROM_DATABASE=Maquet Critical Care AB + +OUI:002542* + ID_OUI_FROM_DATABASE=Pittasoft + +OUI:002543* + ID_OUI_FROM_DATABASE=MONEYTECH + +OUI:002544* + ID_OUI_FROM_DATABASE=LoJack Corporation + +OUI:002545* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002546* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002547* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:002548* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:002549* + ID_OUI_FROM_DATABASE=Jeorich Tech. Co.,Ltd. + +OUI:00254A* + ID_OUI_FROM_DATABASE=RingCube Technologies, Inc. + +OUI:00254B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00254C* + ID_OUI_FROM_DATABASE=Videon Central, Inc. + +OUI:00254D* + ID_OUI_FROM_DATABASE=Singapore Technologies Electronics Limited + +OUI:00254E* + ID_OUI_FROM_DATABASE=Vertex Wireless Co., Ltd. + +OUI:00254F* + ID_OUI_FROM_DATABASE=ELETTROLAB Srl + +OUI:002550* + ID_OUI_FROM_DATABASE=Riverbed Technology, Inc. + +OUI:002551* + ID_OUI_FROM_DATABASE=SE-Elektronic GmbH + +OUI:002552* + ID_OUI_FROM_DATABASE=VXi Corporation + +OUI:002553* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:002554* + ID_OUI_FROM_DATABASE=Pixel8 Networks + +OUI:002555* + ID_OUI_FROM_DATABASE=Visonic Technologies 1993 Ltd. + +OUI:002556* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:002557* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:002558* + ID_OUI_FROM_DATABASE=MPEDIA + +OUI:002559* + ID_OUI_FROM_DATABASE=Syphan Technologies Ltd + +OUI:00255A* + ID_OUI_FROM_DATABASE=Tantalus Systems Corp. + +OUI:00255B* + ID_OUI_FROM_DATABASE=CoachComm, LLC + +OUI:00255C* + ID_OUI_FROM_DATABASE=NEC Corporation + +OUI:00255D* + ID_OUI_FROM_DATABASE=Morningstar Corporation + +OUI:00255E* + ID_OUI_FROM_DATABASE=Shanghai Dare Technologies Co.,Ltd. + +OUI:00255F* + ID_OUI_FROM_DATABASE=SenTec AG + +OUI:002560* + ID_OUI_FROM_DATABASE=Ibridge Networks & Communications Ltd. + +OUI:002561* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP + +OUI:002562* + ID_OUI_FROM_DATABASE=interbro Co. Ltd. + +OUI:002563* + ID_OUI_FROM_DATABASE=Luxtera Inc + +OUI:002564* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:002565* + ID_OUI_FROM_DATABASE=Vizimax Inc. + +OUI:002566* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:002567* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:002568* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:002569* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:00256A* + ID_OUI_FROM_DATABASE=inIT - Institut Industrial IT + +OUI:00256B* + ID_OUI_FROM_DATABASE=ATENIX E.E. s.r.l. + +OUI:00256C* + ID_OUI_FROM_DATABASE=Azimut Production Association JSC + +OUI:00256D* + ID_OUI_FROM_DATABASE=Broadband Forum + +OUI:00256E* + ID_OUI_FROM_DATABASE=Van Breda B.V. + +OUI:00256F* + ID_OUI_FROM_DATABASE=Dantherm Power + +OUI:002570* + ID_OUI_FROM_DATABASE=Eastern Communications Company Limited + +OUI:002571* + ID_OUI_FROM_DATABASE=Zhejiang Tianle Digital Electric Co.,Ltd + +OUI:002572* + ID_OUI_FROM_DATABASE=Nemo-Q International AB + +OUI:002573* + ID_OUI_FROM_DATABASE=ST Electronics (Info-Security) Pte Ltd + +OUI:002574* + ID_OUI_FROM_DATABASE=KUNIMI MEDIA DEVICE Co., Ltd. + +OUI:002575* + ID_OUI_FROM_DATABASE=FiberPlex Technologies, LLC + +OUI:002576* + ID_OUI_FROM_DATABASE=NELI TECHNOLOGIES + +OUI:002577* + ID_OUI_FROM_DATABASE=D-BOX Technologies + +OUI:002578* + ID_OUI_FROM_DATABASE=JSC Concern Sozvezdie + +OUI:002579* + ID_OUI_FROM_DATABASE=J & F Labs + +OUI:00257A* + ID_OUI_FROM_DATABASE=CAMCO Produktions- und Vertriebs-GmbH für Beschallungs- und Beleuchtungsanlagen + +OUI:00257B* + ID_OUI_FROM_DATABASE=STJ ELECTRONICS PVT LTD + +OUI:00257C* + ID_OUI_FROM_DATABASE=Huachentel Technology Development Co., Ltd + +OUI:00257D* + ID_OUI_FROM_DATABASE=PointRed Telecom Private Ltd. + +OUI:00257E* + ID_OUI_FROM_DATABASE=NEW POS TECHNOLOGY LIMITED + +OUI:00257F* + ID_OUI_FROM_DATABASE=CallTechSolution Co.,Ltd + +OUI:002580* + ID_OUI_FROM_DATABASE=Equipson S.A. + +OUI:002581* + ID_OUI_FROM_DATABASE=x-star networks Inc. + +OUI:002582* + ID_OUI_FROM_DATABASE=Maksat Technologies (P) Ltd + +OUI:002583* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002584* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002585* + ID_OUI_FROM_DATABASE=KOKUYO S&T Co., Ltd. + +OUI:002586* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:002587* + ID_OUI_FROM_DATABASE=Vitality, Inc. + +OUI:002588* + ID_OUI_FROM_DATABASE=Genie Industries, Inc. + +OUI:002589* + ID_OUI_FROM_DATABASE=Hills Industries Limited + +OUI:00258A* + ID_OUI_FROM_DATABASE=Pole/Zero Corporation + +OUI:00258B* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:00258C* + ID_OUI_FROM_DATABASE=ESUS ELEKTRONIK SAN. VE DIS. TIC. LTD. STI. + +OUI:00258D* + ID_OUI_FROM_DATABASE=Haier + +OUI:00258E* + ID_OUI_FROM_DATABASE=The Weather Channel + +OUI:00258F* + ID_OUI_FROM_DATABASE=Trident Microsystems, Inc. + +OUI:002590* + ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. + +OUI:002591* + ID_OUI_FROM_DATABASE=NEXTEK, Inc. + +OUI:002592* + ID_OUI_FROM_DATABASE=Guangzhou Shirui Electronic Co., Ltd + +OUI:002593* + ID_OUI_FROM_DATABASE=DatNet Informatikai Kft. + +OUI:002594* + ID_OUI_FROM_DATABASE=Eurodesign BG LTD + +OUI:002595* + ID_OUI_FROM_DATABASE=Northwest Signal Supply, Inc + +OUI:002596* + ID_OUI_FROM_DATABASE=GIGAVISION srl + +OUI:002597* + ID_OUI_FROM_DATABASE=Kalki Communication Technologies + +OUI:002598* + ID_OUI_FROM_DATABASE=Zhong Shan City Litai Electronic Industrial Co. Ltd + +OUI:002599* + ID_OUI_FROM_DATABASE=Hedon e.d. B.V. + +OUI:00259A* + ID_OUI_FROM_DATABASE=CEStronics GmbH + +OUI:00259B* + ID_OUI_FROM_DATABASE=Beijing PKUNITY Microsystems Technology Co., Ltd + +OUI:00259C* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:00259D* + ID_OUI_FROM_DATABASE=Private + +OUI:00259E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:00259F* + ID_OUI_FROM_DATABASE=TechnoDigital Technologies GmbH + +OUI:0025A0* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:0025A1* + ID_OUI_FROM_DATABASE=Enalasys + +OUI:0025A2* + ID_OUI_FROM_DATABASE=Alta Definicion LINCEO S.L. + +OUI:0025A3* + ID_OUI_FROM_DATABASE=Trimax Wireless, Inc. + +OUI:0025A4* + ID_OUI_FROM_DATABASE=EuroDesign embedded technologies GmbH + +OUI:0025A5* + ID_OUI_FROM_DATABASE=Walnut Media Network + +OUI:0025A6* + ID_OUI_FROM_DATABASE=Central Network Solution Co., Ltd. + +OUI:0025A7* + ID_OUI_FROM_DATABASE=itron + +OUI:0025A8* + ID_OUI_FROM_DATABASE=Kontron (BeiJing) Technology Co.,Ltd + +OUI:0025A9* + ID_OUI_FROM_DATABASE=Shanghai Embedway Information Technologies Co.,Ltd + +OUI:0025AA* + ID_OUI_FROM_DATABASE=Beijing Soul Technology Co.,Ltd. + +OUI:0025AB* + ID_OUI_FROM_DATABASE=AIO LCD PC BU / TPV + +OUI:0025AC* + ID_OUI_FROM_DATABASE=I-Tech corporation + +OUI:0025AD* + ID_OUI_FROM_DATABASE=Manufacturing Resources International + +OUI:0025AE* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:0025AF* + ID_OUI_FROM_DATABASE=COMFILE Technology + +OUI:0025B0* + ID_OUI_FROM_DATABASE=Schmartz Inc + +OUI:0025B1* + ID_OUI_FROM_DATABASE=Maya-Creation Corporation + +OUI:0025B2* + ID_OUI_FROM_DATABASE=MBDA Deutschland GmbH + +OUI:0025B3* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0025B4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0025B5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0025B6* + ID_OUI_FROM_DATABASE=Telecom FM + +OUI:0025B7* + ID_OUI_FROM_DATABASE=Costar electronics, inc., + +OUI:0025B8* + ID_OUI_FROM_DATABASE=Agile Communications, Inc. + +OUI:0025B9* + ID_OUI_FROM_DATABASE=Cypress Solutions Inc + +OUI:0025BA* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:0025BB* + ID_OUI_FROM_DATABASE=INNERINT Co., Ltd. + +OUI:0025BC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0025BD* + ID_OUI_FROM_DATABASE=Italdata Ingegneria dell'Idea S.p.A. + +OUI:0025BE* + ID_OUI_FROM_DATABASE=Tektrap Systems Inc. + +OUI:0025BF* + ID_OUI_FROM_DATABASE=Wireless Cables Inc. + +OUI:0025C0* + ID_OUI_FROM_DATABASE=ZillionTV Corporation + +OUI:0025C1* + ID_OUI_FROM_DATABASE=Nawoo Korea Corp. + +OUI:0025C2* + ID_OUI_FROM_DATABASE=RingBell Co.,Ltd. + +OUI:0025C3* + ID_OUI_FROM_DATABASE=21168 + +OUI:0025C4* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:0025C5* + ID_OUI_FROM_DATABASE=Star Link Communication Pvt. Ltd. + +OUI:0025C6* + ID_OUI_FROM_DATABASE=kasercorp, ltd + +OUI:0025C7* + ID_OUI_FROM_DATABASE=altek Corporation + +OUI:0025C8* + ID_OUI_FROM_DATABASE=S-Access GmbH + +OUI:0025C9* + ID_OUI_FROM_DATABASE=SHENZHEN HUAPU DIGITAL CO., LTD + +OUI:0025CA* + ID_OUI_FROM_DATABASE=LS Research, LLC + +OUI:0025CB* + ID_OUI_FROM_DATABASE=Reiner SCT + +OUI:0025CC* + ID_OUI_FROM_DATABASE=Mobile Communications Korea Incorporated + +OUI:0025CD* + ID_OUI_FROM_DATABASE=Skylane Optics + +OUI:0025CE* + ID_OUI_FROM_DATABASE=InnerSpace + +OUI:0025CF* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0025D0* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0025D1* + ID_OUI_FROM_DATABASE=Eastern Asia Technology Limited + +OUI:0025D2* + ID_OUI_FROM_DATABASE=InpegVision Co., Ltd + +OUI:0025D3* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:0025D4* + ID_OUI_FROM_DATABASE=General Dynamics Mission Systems + +OUI:0025D5* + ID_OUI_FROM_DATABASE=Robonica (Pty) Ltd + +OUI:0025D6* + ID_OUI_FROM_DATABASE=The Kroger Co. + +OUI:0025D7* + ID_OUI_FROM_DATABASE=CEDO + +OUI:0025D8* + ID_OUI_FROM_DATABASE=KOREA MAINTENANCE + +OUI:0025D9* + ID_OUI_FROM_DATABASE=DataFab Systems Inc. + +OUI:0025DA* + ID_OUI_FROM_DATABASE=Secura Key + +OUI:0025DB* + ID_OUI_FROM_DATABASE=ATI Electronics(Shenzhen) Co., LTD + +OUI:0025DC* + ID_OUI_FROM_DATABASE=Sumitomo Electric Industries,Ltd + +OUI:0025DD* + ID_OUI_FROM_DATABASE=SUNNYTEK INFORMATION CO., LTD. + +OUI:0025DE* + ID_OUI_FROM_DATABASE=Probits Co., LTD. + +OUI:0025DF* + ID_OUI_FROM_DATABASE=Private + +OUI:0025E0* + ID_OUI_FROM_DATABASE=CeedTec Sdn Bhd + +OUI:0025E1* + ID_OUI_FROM_DATABASE=SHANGHAI SEEYOO ELECTRONIC & TECHNOLOGY CO., LTD + +OUI:0025E2* + ID_OUI_FROM_DATABASE=Everspring Industry Co., Ltd. + +OUI:0025E3* + ID_OUI_FROM_DATABASE=Hanshinit Inc. + +OUI:0025E4* + ID_OUI_FROM_DATABASE=OMNI-WiFi, LLC + +OUI:0025E5* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:0025E6* + ID_OUI_FROM_DATABASE=Belgian Monitoring Systems bvba + +OUI:0025E7* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:0025E8* + ID_OUI_FROM_DATABASE=Idaho Technology + +OUI:0025E9* + ID_OUI_FROM_DATABASE=i-mate Development, Inc. + +OUI:0025EA* + ID_OUI_FROM_DATABASE=Iphion BV + +OUI:0025EB* + ID_OUI_FROM_DATABASE=Reutech Radar Systems (PTY) Ltd + +OUI:0025EC* + ID_OUI_FROM_DATABASE=Humanware + +OUI:0025ED* + ID_OUI_FROM_DATABASE=NuVo Technologies LLC + +OUI:0025EE* + ID_OUI_FROM_DATABASE=Avtex Ltd + +OUI:0025EF* + ID_OUI_FROM_DATABASE=I-TEC Co., Ltd. + +OUI:0025F0* + ID_OUI_FROM_DATABASE=Suga Electronics Limited + +OUI:0025F1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0025F2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0025F3* + ID_OUI_FROM_DATABASE=Nordwestdeutsche Zählerrevision + +OUI:0025F4* + ID_OUI_FROM_DATABASE=KoCo Connector AG + +OUI:0025F5* + ID_OUI_FROM_DATABASE=DVS Korea, Co., Ltd + +OUI:0025F6* + ID_OUI_FROM_DATABASE=netTALK.com, Inc. + +OUI:0025F7* + ID_OUI_FROM_DATABASE=Ansaldo STS USA + +OUI:0025F9* + ID_OUI_FROM_DATABASE=GMK electronic design GmbH + +OUI:0025FA* + ID_OUI_FROM_DATABASE=J&M Analytik AG + +OUI:0025FB* + ID_OUI_FROM_DATABASE=Tunstall Healthcare A/S + +OUI:0025FC* + ID_OUI_FROM_DATABASE=ENDA ENDUSTRIYEL ELEKTRONIK LTD. STI. + +OUI:0025FD* + ID_OUI_FROM_DATABASE=OBR Centrum Techniki Morskiej S.A. + +OUI:0025FE* + ID_OUI_FROM_DATABASE=Pilot Electronics Corporation + +OUI:0025FF* + ID_OUI_FROM_DATABASE=CreNova Multimedia Co., Ltd + +OUI:002600* + ID_OUI_FROM_DATABASE=TEAC Australia Pty Ltd. + +OUI:002601* + ID_OUI_FROM_DATABASE=Cutera Inc + +OUI:002602* + ID_OUI_FROM_DATABASE=SMART Temps LLC + +OUI:002603* + ID_OUI_FROM_DATABASE=Shenzhen Wistar Technology Co., Ltd + +OUI:002604* + ID_OUI_FROM_DATABASE=Audio Processing Technology Ltd + +OUI:002605* + ID_OUI_FROM_DATABASE=CC Systems AB + +OUI:002606* + ID_OUI_FROM_DATABASE=RAUMFELD GmbH + +OUI:002607* + ID_OUI_FROM_DATABASE=Enabling Technology Pty Ltd + +OUI:002608* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:002609* + ID_OUI_FROM_DATABASE=Phyllis Co., Ltd. + +OUI:00260A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00260B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00260C* + ID_OUI_FROM_DATABASE=Dataram + +OUI:00260D* + ID_OUI_FROM_DATABASE=Mercury Systems, Inc. + +OUI:00260E* + ID_OUI_FROM_DATABASE=Ablaze Systems, LLC + +OUI:00260F* + ID_OUI_FROM_DATABASE=Linn Products Ltd + +OUI:002610* + ID_OUI_FROM_DATABASE=Apacewave Technologies + +OUI:002611* + ID_OUI_FROM_DATABASE=Licera AB + +OUI:002612* + ID_OUI_FROM_DATABASE=Space Exploration Technologies + +OUI:002613* + ID_OUI_FROM_DATABASE=Engel Axil S.L. + +OUI:002614* + ID_OUI_FROM_DATABASE=KTNF + +OUI:002615* + ID_OUI_FROM_DATABASE=Teracom Limited + +OUI:002616* + ID_OUI_FROM_DATABASE=Rosemount Inc. + +OUI:002617* + ID_OUI_FROM_DATABASE=OEM Worldwide + +OUI:002618* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:002619* + ID_OUI_FROM_DATABASE=FRC + +OUI:00261A* + ID_OUI_FROM_DATABASE=Femtocomm System Technology Corp. + +OUI:00261B* + ID_OUI_FROM_DATABASE=LAUREL BANK MACHINES CO., LTD. + +OUI:00261C* + ID_OUI_FROM_DATABASE=NEOVIA INC. + +OUI:00261D* + ID_OUI_FROM_DATABASE=COP SECURITY SYSTEM CORP. + +OUI:00261E* + ID_OUI_FROM_DATABASE=QINGBANG ELEC(SZ) CO., LTD + +OUI:00261F* + ID_OUI_FROM_DATABASE=SAE Magnetics (H.K.) Ltd. + +OUI:002620* + ID_OUI_FROM_DATABASE=ISGUS GmbH + +OUI:002621* + ID_OUI_FROM_DATABASE=InteliCloud Technology Inc. + +OUI:002622* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:002623* + ID_OUI_FROM_DATABASE=JRD Communication Inc + +OUI:002624* + ID_OUI_FROM_DATABASE=Thomson Inc. + +OUI:002625* + ID_OUI_FROM_DATABASE=MediaSputnik + +OUI:002626* + ID_OUI_FROM_DATABASE=Geophysical Survey Systems, Inc. + +OUI:002627* + ID_OUI_FROM_DATABASE=Truesell + +OUI:002628* + ID_OUI_FROM_DATABASE=companytec automação e controle ltda. + +OUI:002629* + ID_OUI_FROM_DATABASE=Juphoon System Software Inc. + +OUI:00262A* + ID_OUI_FROM_DATABASE=Proxense, LLC + +OUI:00262B* + ID_OUI_FROM_DATABASE=Wongs Electronics Co. Ltd. + +OUI:00262C* + ID_OUI_FROM_DATABASE=IKT Advanced Technologies s.r.o. + +OUI:00262D* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:00262E* + ID_OUI_FROM_DATABASE=Chengdu Jiuzhou Electronic Technology Inc + +OUI:00262F* + ID_OUI_FROM_DATABASE=HAMAMATSU TOA ELECTRONICS + +OUI:002630* + ID_OUI_FROM_DATABASE=ACOREL S.A.S + +OUI:002631* + ID_OUI_FROM_DATABASE=COMMTACT LTD + +OUI:002632* + ID_OUI_FROM_DATABASE=Instrumentation Technologies d.d. + +OUI:002633* + ID_OUI_FROM_DATABASE=MIR - Medical International Research + +OUI:002634* + ID_OUI_FROM_DATABASE=Infineta Systems, Inc + +OUI:002635* + ID_OUI_FROM_DATABASE=Bluetechnix GmbH + +OUI:002636* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002637* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:002638* + ID_OUI_FROM_DATABASE=Xia Men Joyatech Co., Ltd. + +OUI:002639* + ID_OUI_FROM_DATABASE=T.M. Electronics, Inc. + +OUI:00263A* + ID_OUI_FROM_DATABASE=Digitec Systems + +OUI:00263B* + ID_OUI_FROM_DATABASE=Onbnetech + +OUI:00263C* + ID_OUI_FROM_DATABASE=Bachmann Technology GmbH & Co. KG + +OUI:00263D* + ID_OUI_FROM_DATABASE=MIA Corporation + +OUI:00263E* + ID_OUI_FROM_DATABASE=Trapeze Networks + +OUI:00263F* + ID_OUI_FROM_DATABASE=LIOS Technology GmbH + +OUI:002640* + ID_OUI_FROM_DATABASE=Baustem Broadband Technologies, Ltd. + +OUI:002641* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002642* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:002643* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:002644* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium + +OUI:002645* + ID_OUI_FROM_DATABASE=Circontrol S.A. + +OUI:002646* + ID_OUI_FROM_DATABASE=SHENYANG TONGFANG MULTIMEDIA TECHNOLOGY COMPANY LIMITED + +OUI:002647* + ID_OUI_FROM_DATABASE=WFE TECHNOLOGY CORP. + +OUI:002648* + ID_OUI_FROM_DATABASE=Emitech Corp. + +OUI:00264A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00264C* + ID_OUI_FROM_DATABASE=Shanghai DigiVision Technology Co., Ltd. + +OUI:00264D* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:00264E* + ID_OUI_FROM_DATABASE=Rail & Road Protec GmbH + +OUI:00264F* + ID_OUI_FROM_DATABASE=Krüger &Gothe GmbH + +OUI:002650* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:002651* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002652* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002653* + ID_OUI_FROM_DATABASE=DaySequerra Corporation + +OUI:002654* + ID_OUI_FROM_DATABASE=3COM + +OUI:002655* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:002656* + ID_OUI_FROM_DATABASE=Sansonic Electronics USA + +OUI:002657* + ID_OUI_FROM_DATABASE=OOO NPP EKRA + +OUI:002658* + ID_OUI_FROM_DATABASE=T-Platforms (Cyprus) Limited + +OUI:002659* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:00265A* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:00265B* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:00265C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:00265D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00265E* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:00265F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:002660* + ID_OUI_FROM_DATABASE=Logiways + +OUI:002661* + ID_OUI_FROM_DATABASE=Irumtek Co., Ltd. + +OUI:002662* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:002663* + ID_OUI_FROM_DATABASE=Shenzhen Huitaiwei Tech. Ltd, co. + +OUI:002664* + ID_OUI_FROM_DATABASE=Core System Japan + +OUI:002665* + ID_OUI_FROM_DATABASE=ProtectedLogic Corporation + +OUI:002666* + ID_OUI_FROM_DATABASE=EFM Networks + +OUI:002667* + ID_OUI_FROM_DATABASE=CARECOM CO.,LTD. + +OUI:002668* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:002669* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:00266A* + ID_OUI_FROM_DATABASE=ESSENSIUM NV + +OUI:00266B* + ID_OUI_FROM_DATABASE=SHINE UNION ENTERPRISE LIMITED + +OUI:00266C* + ID_OUI_FROM_DATABASE=INVENTEC CORPORATION + +OUI:00266D* + ID_OUI_FROM_DATABASE=MobileAccess Networks + +OUI:00266E* + ID_OUI_FROM_DATABASE=Nissho-denki Co.,LTD. + +OUI:00266F* + ID_OUI_FROM_DATABASE=Coordiwise Technology Corp. + +OUI:002670* + ID_OUI_FROM_DATABASE=Cinch Connectors + +OUI:002671* + ID_OUI_FROM_DATABASE=AUTOVISION Co., Ltd + +OUI:002672* + ID_OUI_FROM_DATABASE=AAMP of America + +OUI:002673* + ID_OUI_FROM_DATABASE=RICOH COMPANY,LTD. + +OUI:002674* + ID_OUI_FROM_DATABASE=Hunter Douglas + +OUI:002675* + ID_OUI_FROM_DATABASE=Aztech Electronics Pte Ltd + +OUI:002676* + ID_OUI_FROM_DATABASE=COMMidt AS + +OUI:002677* + ID_OUI_FROM_DATABASE=DEIF A/S + +OUI:002678* + ID_OUI_FROM_DATABASE=Logic Instrument SA + +OUI:002679* + ID_OUI_FROM_DATABASE=Euphonic Technologies, Inc. + +OUI:00267A* + ID_OUI_FROM_DATABASE=wuhan hongxin telecommunication technologies co.,ltd + +OUI:00267B* + ID_OUI_FROM_DATABASE=GSI Helmholtzzentrum für Schwerionenforschung GmbH + +OUI:00267C* + ID_OUI_FROM_DATABASE=Metz-Werke GmbH & Co KG + +OUI:00267D* + ID_OUI_FROM_DATABASE=A-Max Technology Macao Commercial Offshore Company Limited + +OUI:00267E* + ID_OUI_FROM_DATABASE=PARROT SA + +OUI:00267F* + ID_OUI_FROM_DATABASE=Zenterio AB + +OUI:002680* + ID_OUI_FROM_DATABASE=SIL3 Pty.Ltd + +OUI:002681* + ID_OUI_FROM_DATABASE=Interspiro AB + +OUI:002682* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:002683* + ID_OUI_FROM_DATABASE=Ajoho Enterprise Co., Ltd. + +OUI:002684* + ID_OUI_FROM_DATABASE=KISAN SYSTEM + +OUI:002685* + ID_OUI_FROM_DATABASE=Digital Innovation + +OUI:002686* + ID_OUI_FROM_DATABASE=Quantenna Communcations, Inc. + +OUI:002687* + ID_OUI_FROM_DATABASE=corega K.K + +OUI:002688* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:002689* + ID_OUI_FROM_DATABASE=General Dynamics Robotic Systems + +OUI:00268A* + ID_OUI_FROM_DATABASE=Terrier SC Ltd + +OUI:00268B* + ID_OUI_FROM_DATABASE=Guangzhou Escene Computer Technology Limited + +OUI:00268C* + ID_OUI_FROM_DATABASE=StarLeaf Ltd. + +OUI:00268D* + ID_OUI_FROM_DATABASE=CellTel S.p.A. + +OUI:00268E* + ID_OUI_FROM_DATABASE=Alta Solutions, Inc. + +OUI:00268F* + ID_OUI_FROM_DATABASE=MTA SpA + +OUI:002690* + ID_OUI_FROM_DATABASE=I DO IT + +OUI:002691* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:002692* + ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation + +OUI:002693* + ID_OUI_FROM_DATABASE=QVidium Technologies, Inc. + +OUI:002694* + ID_OUI_FROM_DATABASE=Senscient Ltd + +OUI:002695* + ID_OUI_FROM_DATABASE=ZT Group Int'l Inc + +OUI:002696* + ID_OUI_FROM_DATABASE=NOOLIX Co., Ltd + +OUI:002697* + ID_OUI_FROM_DATABASE=Alpha Technologies Inc. + +OUI:002698* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002699* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00269A* + ID_OUI_FROM_DATABASE=Carina System Co., Ltd. + +OUI:00269B* + ID_OUI_FROM_DATABASE=SOKRAT Ltd. + +OUI:00269C* + ID_OUI_FROM_DATABASE=ITUS JAPAN CO. LTD + +OUI:00269D* + ID_OUI_FROM_DATABASE=M2Mnet Co., Ltd. + +OUI:00269E* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:00269F* + ID_OUI_FROM_DATABASE=Private + +OUI:0026A0* + ID_OUI_FROM_DATABASE=moblic + +OUI:0026A1* + ID_OUI_FROM_DATABASE=Megger + +OUI:0026A2* + ID_OUI_FROM_DATABASE=Instrumentation Technology Systems + +OUI:0026A3* + ID_OUI_FROM_DATABASE=FQ Ingenieria Electronica S.A. + +OUI:0026A4* + ID_OUI_FROM_DATABASE=Novus Produtos Eletronicos Ltda + +OUI:0026A5* + ID_OUI_FROM_DATABASE=MICROROBOT.CO.,LTD + +OUI:0026A6* + ID_OUI_FROM_DATABASE=TRIXELL + +OUI:0026A7* + ID_OUI_FROM_DATABASE=CONNECT SRL + +OUI:0026A8* + ID_OUI_FROM_DATABASE=DAEHAP HYPER-TECH + +OUI:0026A9* + ID_OUI_FROM_DATABASE=Strong Technologies Pty Ltd + +OUI:0026AA* + ID_OUI_FROM_DATABASE=Kenmec Mechanical Engineering Co., Ltd. + +OUI:0026AB* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:0026AC* + ID_OUI_FROM_DATABASE=Shanghai LUSTER Teraband photonic Co., Ltd. + +OUI:0026AD* + ID_OUI_FROM_DATABASE=Arada Systems, Inc. + +OUI:0026AE* + ID_OUI_FROM_DATABASE=Wireless Measurement Ltd + +OUI:0026AF* + ID_OUI_FROM_DATABASE=Duelco A/S + +OUI:0026B0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0026B1* + ID_OUI_FROM_DATABASE=Navis Auto Motive Systems, Inc. + +OUI:0026B2* + ID_OUI_FROM_DATABASE=Setrix GmbH + +OUI:0026B3* + ID_OUI_FROM_DATABASE=Thales Communications Inc + +OUI:0026B4* + ID_OUI_FROM_DATABASE=Ford Motor Company + +OUI:0026B5* + ID_OUI_FROM_DATABASE=ICOMM Tele Ltd + +OUI:0026B6* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:0026B7* + ID_OUI_FROM_DATABASE=Kingston Technology Company, Inc. + +OUI:0026B8* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:0026B9* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:0026BA* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0026BB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0026BC* + ID_OUI_FROM_DATABASE=General Jack Technology Ltd. + +OUI:0026BD* + ID_OUI_FROM_DATABASE=JTEC Card & Communication Co., Ltd + +OUI:0026BE* + ID_OUI_FROM_DATABASE=Schoonderbeek Elektronica Systemen B.V. + +OUI:0026BF* + ID_OUI_FROM_DATABASE=ShenZhen Temobi Science&Tech Development Co.,Ltd + +OUI:0026C0* + ID_OUI_FROM_DATABASE=EnergyHub + +OUI:0026C1* + ID_OUI_FROM_DATABASE=ARTRAY CO., LTD. + +OUI:0026C2* + ID_OUI_FROM_DATABASE=SCDI Co. LTD + +OUI:0026C3* + ID_OUI_FROM_DATABASE=Insightek Corp. + +OUI:0026C4* + ID_OUI_FROM_DATABASE=Cadmos microsystems S.r.l. + +OUI:0026C5* + ID_OUI_FROM_DATABASE=Guangdong Gosun Telecommunications Co.,Ltd + +OUI:0026C6* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0026C7* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0026C8* + ID_OUI_FROM_DATABASE=System Sensor + +OUI:0026C9* + ID_OUI_FROM_DATABASE=Proventix Systems, Inc. + +OUI:0026CA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0026CB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0026CC* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:0026CD* + ID_OUI_FROM_DATABASE=PurpleComm, Inc. + +OUI:0026CE* + ID_OUI_FROM_DATABASE=Kozumi USA Corp. + +OUI:0026CF* + ID_OUI_FROM_DATABASE=DEKA R&D + +OUI:0026D0* + ID_OUI_FROM_DATABASE=Semihalf + +OUI:0026D1* + ID_OUI_FROM_DATABASE=S Squared Innovations Inc. + +OUI:0026D2* + ID_OUI_FROM_DATABASE=Pcube Systems, Inc. + +OUI:0026D3* + ID_OUI_FROM_DATABASE=Zeno Information System + +OUI:0026D4* + ID_OUI_FROM_DATABASE=IRCA SpA + +OUI:0026D5* + ID_OUI_FROM_DATABASE=Ory Solucoes em Comercio de Informatica Ltda. + +OUI:0026D6* + ID_OUI_FROM_DATABASE=Ningbo Andy Optoelectronic Co., Ltd. + +OUI:0026D7* + ID_OUI_FROM_DATABASE=KM Electornic Technology Co., Ltd. + +OUI:0026D8* + ID_OUI_FROM_DATABASE=Magic Point Inc. + +OUI:0026D9* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0026DA* + ID_OUI_FROM_DATABASE=Universal Media Corporation /Slovakia/ s.r.o. + +OUI:0026DB* + ID_OUI_FROM_DATABASE=Ionics EMS Inc. + +OUI:0026DC* + ID_OUI_FROM_DATABASE=Optical Systems Design + +OUI:0026DD* + ID_OUI_FROM_DATABASE=Fival Science & Technology Co.,Ltd. + +OUI:0026DE* + ID_OUI_FROM_DATABASE=FDI MATELEC + +OUI:0026DF* + ID_OUI_FROM_DATABASE=TaiDoc Technology Corp. + +OUI:0026E0* + ID_OUI_FROM_DATABASE=ASITEQ + +OUI:0026E1* + ID_OUI_FROM_DATABASE=Stanford University, OpenFlow Group + +OUI:0026E2* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:0026E3* + ID_OUI_FROM_DATABASE=DTI + +OUI:0026E4* + ID_OUI_FROM_DATABASE=Canal + + +OUI:0026E5* + ID_OUI_FROM_DATABASE=AEG Power Solutions + +OUI:0026E6* + ID_OUI_FROM_DATABASE=Visionhitech Co., Ltd. + +OUI:0026E7* + ID_OUI_FROM_DATABASE=Shanghai ONLAN Communication Tech. Co., Ltd. + +OUI:0026E8* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:0026E9* + ID_OUI_FROM_DATABASE=SP Corp + +OUI:0026EA* + ID_OUI_FROM_DATABASE=Cheerchip Electronic Technology (ShangHai) Co., Ltd. + +OUI:0026EB* + ID_OUI_FROM_DATABASE=Advanced Spectrum Technology Co., Ltd. + +OUI:0026EC* + ID_OUI_FROM_DATABASE=Legrand Home Systems, Inc + +OUI:0026ED* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:0026EE* + ID_OUI_FROM_DATABASE=TKM GmbH + +OUI:0026EF* + ID_OUI_FROM_DATABASE=Technology Advancement Group, Inc. + +OUI:0026F0* + ID_OUI_FROM_DATABASE=cTrixs International GmbH. + +OUI:0026F1* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP + +OUI:0026F2* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:0026F3* + ID_OUI_FROM_DATABASE=SMC Networks + +OUI:0026F4* + ID_OUI_FROM_DATABASE=Nesslab + +OUI:0026F5* + ID_OUI_FROM_DATABASE=XRPLUS Inc. + +OUI:0026F6* + ID_OUI_FROM_DATABASE=Military Communication Institute + +OUI:0026F7* + ID_OUI_FROM_DATABASE=Nivetti Systems Pvt. Ltd. + +OUI:0026F8* + ID_OUI_FROM_DATABASE=Golden Highway Industry Development Co., Ltd. + +OUI:0026F9* + ID_OUI_FROM_DATABASE=S.E.M. srl + +OUI:0026FA* + ID_OUI_FROM_DATABASE=BandRich Inc. + +OUI:0026FB* + ID_OUI_FROM_DATABASE=AirDio Wireless, Inc. + +OUI:0026FC* + ID_OUI_FROM_DATABASE=AcSiP Technology Corp. + +OUI:0026FD* + ID_OUI_FROM_DATABASE=Interactive Intelligence + +OUI:0026FE* + ID_OUI_FROM_DATABASE=MKD Technology Inc. + +OUI:0026FF* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:002700* + ID_OUI_FROM_DATABASE=Shenzhen Siglent Technology Co., Ltd. + +OUI:002701* + ID_OUI_FROM_DATABASE=INCOstartec GmbH + +OUI:002702* + ID_OUI_FROM_DATABASE=SolarEdge Technologies + +OUI:002703* + ID_OUI_FROM_DATABASE=Testech Electronics Pte Ltd + +OUI:002704* + ID_OUI_FROM_DATABASE=Accelerated Concepts, Inc + +OUI:002705* + ID_OUI_FROM_DATABASE=Sectronic + +OUI:002706* + ID_OUI_FROM_DATABASE=YOISYS + +OUI:002707* + ID_OUI_FROM_DATABASE=Lift Complex DS, JSC + +OUI:002708* + ID_OUI_FROM_DATABASE=Nordiag ASA + +OUI:002709* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:00270A* + ID_OUI_FROM_DATABASE=IEE S.A. + +OUI:00270B* + ID_OUI_FROM_DATABASE=Adura Technologies + +OUI:00270C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00270D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00270E* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:00270F* + ID_OUI_FROM_DATABASE=Envisionnovation Inc + +OUI:002710* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:002711* + ID_OUI_FROM_DATABASE=LanPro Inc + +OUI:002712* + ID_OUI_FROM_DATABASE=MaxVision LLC + +OUI:002713* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:002714* + ID_OUI_FROM_DATABASE=Grainmustards, Co,ltd. + +OUI:002715* + ID_OUI_FROM_DATABASE=Rebound Telecom. Co., Ltd + +OUI:002716* + ID_OUI_FROM_DATABASE=Adachi-Syokai Co., Ltd. + +OUI:002717* + ID_OUI_FROM_DATABASE=CE Digital(Zhenjiang)Co.,Ltd + +OUI:002718* + ID_OUI_FROM_DATABASE=Suzhou NEW SEAUNION Video Technology Co.,Ltd + +OUI:002719* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:00271A* + ID_OUI_FROM_DATABASE=Geenovo Technology Ltd. + +OUI:00271B* + ID_OUI_FROM_DATABASE=Alec Sicherheitssysteme GmbH + +OUI:00271C* + ID_OUI_FROM_DATABASE=MERCURY CORPORATION + +OUI:00271D* + ID_OUI_FROM_DATABASE=Comba Telecom Systems (China) Ltd. + +OUI:00271E* + ID_OUI_FROM_DATABASE=Xagyl Communications + +OUI:00271F* + ID_OUI_FROM_DATABASE=MIPRO Electronics Co., Ltd + +OUI:002720* + ID_OUI_FROM_DATABASE=NEW-SOL COM + +OUI:002721* + ID_OUI_FROM_DATABASE=Shenzhen Baoan Fenda Industrial Co., Ltd + +OUI:002722* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:002790* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0027E3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0027F8* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:00289F* + ID_OUI_FROM_DATABASE=Semptian Co., Ltd. + +OUI:0028F8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:002926* + ID_OUI_FROM_DATABASE=Applied Optoelectronics, Inc Taiwan Branch + +OUI:0029C2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002A10* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002A6A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002AAF* + ID_OUI_FROM_DATABASE=LARsys-Automation GmbH + +OUI:002CC8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002D76* + ID_OUI_FROM_DATABASE=TITECH GmbH + +OUI:002EC7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:002F5C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:002FD9* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:003000* + ID_OUI_FROM_DATABASE=ALLWELL TECHNOLOGY CORP. + +OUI:003001* + ID_OUI_FROM_DATABASE=SMP + +OUI:003002* + ID_OUI_FROM_DATABASE=Expand Networks + +OUI:003003* + ID_OUI_FROM_DATABASE=Phasys Ltd. + +OUI:003004* + ID_OUI_FROM_DATABASE=LEADTEK RESEARCH INC. + +OUI:003005* + ID_OUI_FROM_DATABASE=Fujitsu Siemens Computers + +OUI:003006* + ID_OUI_FROM_DATABASE=SUPERPOWER COMPUTER + +OUI:003007* + ID_OUI_FROM_DATABASE=OPTI, INC. + +OUI:003008* + ID_OUI_FROM_DATABASE=AVIO DIGITAL, INC. + +OUI:003009* + ID_OUI_FROM_DATABASE=Tachion Networks, Inc. + +OUI:00300A* + ID_OUI_FROM_DATABASE=Aztech Electronics Pte Ltd + +OUI:00300B* + ID_OUI_FROM_DATABASE=mPHASE Technologies, Inc. + +OUI:00300C* + ID_OUI_FROM_DATABASE=CONGRUENCY, LTD. + +OUI:00300D* + ID_OUI_FROM_DATABASE=MMC Technology, Inc. + +OUI:00300E* + ID_OUI_FROM_DATABASE=Klotz Digital AG + +OUI:00300F* + ID_OUI_FROM_DATABASE=IMT - Information Management T + +OUI:003010* + ID_OUI_FROM_DATABASE=VISIONETICS INTERNATIONAL + +OUI:003011* + ID_OUI_FROM_DATABASE=HMS Industrial Networks + +OUI:003012* + ID_OUI_FROM_DATABASE=DIGITAL ENGINEERING LTD. + +OUI:003013* + ID_OUI_FROM_DATABASE=NEC Corporation + +OUI:003014* + ID_OUI_FROM_DATABASE=DIVIO, INC. + +OUI:003015* + ID_OUI_FROM_DATABASE=CP CLARE CORP. + +OUI:003016* + ID_OUI_FROM_DATABASE=ISHIDA CO., LTD. + +OUI:003017* + ID_OUI_FROM_DATABASE=BlueArc UK Ltd + +OUI:003018* + ID_OUI_FROM_DATABASE=Jetway Information Co., Ltd. + +OUI:003019* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00301A* + ID_OUI_FROM_DATABASE=SMARTBRIDGES PTE. LTD. + +OUI:00301B* + ID_OUI_FROM_DATABASE=SHUTTLE, INC. + +OUI:00301C* + ID_OUI_FROM_DATABASE=ALTVATER AIRDATA SYSTEMS + +OUI:00301D* + ID_OUI_FROM_DATABASE=SKYSTREAM, INC. + +OUI:00301E* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:00301F* + ID_OUI_FROM_DATABASE=OPTICAL NETWORKS, INC. + +OUI:003020* + ID_OUI_FROM_DATABASE=TSI, Inc.. + +OUI:003021* + ID_OUI_FROM_DATABASE=HSING TECH. ENTERPRISE CO.,LTD + +OUI:003022* + ID_OUI_FROM_DATABASE=Fong Kai Industrial Co., Ltd. + +OUI:003023* + ID_OUI_FROM_DATABASE=COGENT COMPUTER SYSTEMS, INC. + +OUI:003024* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003025* + ID_OUI_FROM_DATABASE=CHECKOUT COMPUTER SYSTEMS, LTD + +OUI:003026* + ID_OUI_FROM_DATABASE=HeiTel Digital Video GmbH + +OUI:003027* + ID_OUI_FROM_DATABASE=KERBANGO, INC. + +OUI:003028* + ID_OUI_FROM_DATABASE=FASE Saldatura srl + +OUI:003029* + ID_OUI_FROM_DATABASE=OPICOM + +OUI:00302A* + ID_OUI_FROM_DATABASE=SOUTHERN INFORMATION + +OUI:00302B* + ID_OUI_FROM_DATABASE=INALP NETWORKS, INC. + +OUI:00302C* + ID_OUI_FROM_DATABASE=SYLANTRO SYSTEMS CORPORATION + +OUI:00302D* + ID_OUI_FROM_DATABASE=QUANTUM BRIDGE COMMUNICATIONS + +OUI:00302E* + ID_OUI_FROM_DATABASE=Hoft & Wessel AG + +OUI:00302F* + ID_OUI_FROM_DATABASE=GE Aviation System + +OUI:003030* + ID_OUI_FROM_DATABASE=HARMONIX CORPORATION + +OUI:003031* + ID_OUI_FROM_DATABASE=LIGHTWAVE COMMUNICATIONS, INC. + +OUI:003032* + ID_OUI_FROM_DATABASE=MagicRam, Inc. + +OUI:003033* + ID_OUI_FROM_DATABASE=ORIENT TELECOM CO., LTD. + +OUI:003034* + ID_OUI_FROM_DATABASE=SET ENGINEERING + +OUI:003035* + ID_OUI_FROM_DATABASE=Corning Incorporated + +OUI:003036* + ID_OUI_FROM_DATABASE=RMP ELEKTRONIKSYSTEME GMBH + +OUI:003037* + ID_OUI_FROM_DATABASE=Packard Bell Nec Services + +OUI:003038* + ID_OUI_FROM_DATABASE=XCP, INC. + +OUI:003039* + ID_OUI_FROM_DATABASE=SOFTBOOK PRESS + +OUI:00303A* + ID_OUI_FROM_DATABASE=MAATEL + +OUI:00303B* + ID_OUI_FROM_DATABASE=PowerCom Technology + +OUI:00303C* + ID_OUI_FROM_DATABASE=ONNTO CORP. + +OUI:00303D* + ID_OUI_FROM_DATABASE=IVA CORPORATION + +OUI:00303E* + ID_OUI_FROM_DATABASE=Radcom Ltd. + +OUI:00303F* + ID_OUI_FROM_DATABASE=TurboComm Tech Inc. + +OUI:003040* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003041* + ID_OUI_FROM_DATABASE=SAEJIN T & M CO., LTD. + +OUI:003042* + ID_OUI_FROM_DATABASE=DeTeWe-Deutsche Telephonwerke + +OUI:003043* + ID_OUI_FROM_DATABASE=IDREAM TECHNOLOGIES, PTE. LTD. + +OUI:003044* + ID_OUI_FROM_DATABASE=CradlePoint, Inc + +OUI:003045* + ID_OUI_FROM_DATABASE=Village Networks, Inc. (VNI) + +OUI:003046* + ID_OUI_FROM_DATABASE=Controlled Electronic Manageme + +OUI:003047* + ID_OUI_FROM_DATABASE=NISSEI ELECTRIC CO., LTD. + +OUI:003048* + ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. + +OUI:003049* + ID_OUI_FROM_DATABASE=BRYANT TECHNOLOGY, LTD. + +OUI:00304A* + ID_OUI_FROM_DATABASE=Fraunhofer IPMS + +OUI:00304B* + ID_OUI_FROM_DATABASE=ORBACOM SYSTEMS, INC. + +OUI:00304C* + ID_OUI_FROM_DATABASE=APPIAN COMMUNICATIONS, INC. + +OUI:00304D* + ID_OUI_FROM_DATABASE=ESI + +OUI:00304E* + ID_OUI_FROM_DATABASE=BUSTEC PRODUCTION LTD. + +OUI:00304F* + ID_OUI_FROM_DATABASE=PLANET Technology Corporation + +OUI:003050* + ID_OUI_FROM_DATABASE=Versa Technology + +OUI:003051* + ID_OUI_FROM_DATABASE=ORBIT AVIONIC & COMMUNICATION + +OUI:003052* + ID_OUI_FROM_DATABASE=ELASTIC NETWORKS + +OUI:003053* + ID_OUI_FROM_DATABASE=Basler AG + +OUI:003054* + ID_OUI_FROM_DATABASE=CASTLENET TECHNOLOGY, INC. + +OUI:003055* + ID_OUI_FROM_DATABASE=Renesas Technology America, Inc. + +OUI:003056* + ID_OUI_FROM_DATABASE=HMS Industrial Networks + +OUI:003057* + ID_OUI_FROM_DATABASE=QTelNet, Inc. + +OUI:003058* + ID_OUI_FROM_DATABASE=API MOTION + +OUI:003059* + ID_OUI_FROM_DATABASE=KONTRON COMPACT COMPUTERS AG + +OUI:00305A* + ID_OUI_FROM_DATABASE=TELGEN CORPORATION + +OUI:00305B* + ID_OUI_FROM_DATABASE=Toko Inc. + +OUI:00305C* + ID_OUI_FROM_DATABASE=SMAR Laboratories Corp. + +OUI:00305D* + ID_OUI_FROM_DATABASE=DIGITRA SYSTEMS, INC. + +OUI:00305E* + ID_OUI_FROM_DATABASE=Abelko Innovation + +OUI:00305F* + ID_OUI_FROM_DATABASE=Hasselblad + +OUI:003060* + ID_OUI_FROM_DATABASE=Powerfile, Inc. + +OUI:003061* + ID_OUI_FROM_DATABASE=MobyTEL + +OUI:003062* + ID_OUI_FROM_DATABASE=IP Video Networks Inc + +OUI:003063* + ID_OUI_FROM_DATABASE=SANTERA SYSTEMS, INC. + +OUI:003064* + ID_OUI_FROM_DATABASE=ADLINK TECHNOLOGY, INC. + +OUI:003065* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:003066* + ID_OUI_FROM_DATABASE=RFM + +OUI:003067* + ID_OUI_FROM_DATABASE=BIOSTAR Microtech Int'l Corp. + +OUI:003068* + ID_OUI_FROM_DATABASE=CYBERNETICS TECH. CO., LTD. + +OUI:003069* + ID_OUI_FROM_DATABASE=IMPACCT TECHNOLOGY CORP. + +OUI:00306A* + ID_OUI_FROM_DATABASE=PENTA MEDIA CO., LTD. + +OUI:00306B* + ID_OUI_FROM_DATABASE=CMOS SYSTEMS, INC. + +OUI:00306C* + ID_OUI_FROM_DATABASE=Hitex Holding GmbH + +OUI:00306D* + ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES + +OUI:00306E* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:00306F* + ID_OUI_FROM_DATABASE=SEYEON TECH. CO., LTD. + +OUI:003070* + ID_OUI_FROM_DATABASE=1Net Corporation + +OUI:003071* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003072* + ID_OUI_FROM_DATABASE=Intellibyte Inc. + +OUI:003073* + ID_OUI_FROM_DATABASE=International Microsystems, In + +OUI:003074* + ID_OUI_FROM_DATABASE=EQUIINET LTD. + +OUI:003075* + ID_OUI_FROM_DATABASE=ADTECH + +OUI:003076* + ID_OUI_FROM_DATABASE=Akamba Corporation + +OUI:003077* + ID_OUI_FROM_DATABASE=ONPREM NETWORKS + +OUI:003078* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003079* + ID_OUI_FROM_DATABASE=CQOS, INC. + +OUI:00307A* + ID_OUI_FROM_DATABASE=Advanced Technology & Systems + +OUI:00307B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00307C* + ID_OUI_FROM_DATABASE=ADID SA + +OUI:00307D* + ID_OUI_FROM_DATABASE=GRE AMERICA, INC. + +OUI:00307E* + ID_OUI_FROM_DATABASE=Redflex Communication Systems + +OUI:00307F* + ID_OUI_FROM_DATABASE=IRLAN LTD. + +OUI:003080* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003081* + ID_OUI_FROM_DATABASE=ALTOS C&C + +OUI:003082* + ID_OUI_FROM_DATABASE=TAIHAN ELECTRIC WIRE CO., LTD. + +OUI:003083* + ID_OUI_FROM_DATABASE=Ivron Systems + +OUI:003084* + ID_OUI_FROM_DATABASE=ALLIED TELESYN INTERNAIONAL + +OUI:003085* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003086* + ID_OUI_FROM_DATABASE=Transistor Devices, Inc. + +OUI:003087* + ID_OUI_FROM_DATABASE=VEGA GRIESHABER KG + +OUI:003088* + ID_OUI_FROM_DATABASE=Ericsson + +OUI:003089* + ID_OUI_FROM_DATABASE=Spectrapoint Wireless, LLC + +OUI:00308A* + ID_OUI_FROM_DATABASE=NICOTRA SISTEMI S.P.A + +OUI:00308B* + ID_OUI_FROM_DATABASE=Brix Networks + +OUI:00308C* + ID_OUI_FROM_DATABASE=Quantum Corporation + +OUI:00308D* + ID_OUI_FROM_DATABASE=Pinnacle Systems, Inc. + +OUI:00308E* + ID_OUI_FROM_DATABASE=CROSS MATCH TECHNOLOGIES, INC. + +OUI:00308F* + ID_OUI_FROM_DATABASE=MICRILOR, Inc. + +OUI:003090* + ID_OUI_FROM_DATABASE=CYRA TECHNOLOGIES, INC. + +OUI:003091* + ID_OUI_FROM_DATABASE=TAIWAN FIRST LINE ELEC. CORP. + +OUI:003092* + ID_OUI_FROM_DATABASE=Kontron Electronics AG + +OUI:003093* + ID_OUI_FROM_DATABASE=Sonnet Technologies, Inc + +OUI:003094* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003095* + ID_OUI_FROM_DATABASE=Procomp Informatics, Ltd. + +OUI:003096* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003097* + ID_OUI_FROM_DATABASE=AB Regin + +OUI:003098* + ID_OUI_FROM_DATABASE=Global Converging Technologies + +OUI:003099* + ID_OUI_FROM_DATABASE=BOENIG UND KALLENBACH OHG + +OUI:00309A* + ID_OUI_FROM_DATABASE=ASTRO TERRA CORP. + +OUI:00309B* + ID_OUI_FROM_DATABASE=Smartware + +OUI:00309C* + ID_OUI_FROM_DATABASE=Timing Applications, Inc. + +OUI:00309D* + ID_OUI_FROM_DATABASE=Nimble Microsystems, Inc. + +OUI:00309E* + ID_OUI_FROM_DATABASE=WORKBIT CORPORATION. + +OUI:00309F* + ID_OUI_FROM_DATABASE=AMBER NETWORKS + +OUI:0030A0* + ID_OUI_FROM_DATABASE=TYCO SUBMARINE SYSTEMS, LTD. + +OUI:0030A1* + ID_OUI_FROM_DATABASE=WEBGATE Inc. + +OUI:0030A2* + ID_OUI_FROM_DATABASE=Lightner Engineering + +OUI:0030A3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0030A4* + ID_OUI_FROM_DATABASE=Woodwind Communications System + +OUI:0030A5* + ID_OUI_FROM_DATABASE=ACTIVE POWER + +OUI:0030A6* + ID_OUI_FROM_DATABASE=VIANET TECHNOLOGIES, LTD. + +OUI:0030A7* + ID_OUI_FROM_DATABASE=SCHWEITZER ENGINEERING + +OUI:0030A8* + ID_OUI_FROM_DATABASE=OL'E COMMUNICATIONS, INC. + +OUI:0030A9* + ID_OUI_FROM_DATABASE=Netiverse, Inc. + +OUI:0030AA* + ID_OUI_FROM_DATABASE=AXUS MICROSYSTEMS, INC. + +OUI:0030AB* + ID_OUI_FROM_DATABASE=DELTA NETWORKS, INC. + +OUI:0030AC* + ID_OUI_FROM_DATABASE=Systeme Lauer GmbH & Co., Ltd. + +OUI:0030AD* + ID_OUI_FROM_DATABASE=SHANGHAI COMMUNICATION + +OUI:0030AE* + ID_OUI_FROM_DATABASE=Times N System, Inc. + +OUI:0030AF* + ID_OUI_FROM_DATABASE=Honeywell GmbH + +OUI:0030B0* + ID_OUI_FROM_DATABASE=Convergenet Technologies + +OUI:0030B1* + ID_OUI_FROM_DATABASE=TrunkNet + +OUI:0030B2* + ID_OUI_FROM_DATABASE=L-3 Sonoma EO + +OUI:0030B3* + ID_OUI_FROM_DATABASE=San Valley Systems, Inc. + +OUI:0030B4* + ID_OUI_FROM_DATABASE=INTERSIL CORP. + +OUI:0030B5* + ID_OUI_FROM_DATABASE=Tadiran Microwave Networks + +OUI:0030B6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0030B7* + ID_OUI_FROM_DATABASE=Teletrol Systems, Inc. + +OUI:0030B8* + ID_OUI_FROM_DATABASE=RiverDelta Networks + +OUI:0030B9* + ID_OUI_FROM_DATABASE=ECTEL + +OUI:0030BA* + ID_OUI_FROM_DATABASE=AC&T SYSTEM CO., LTD. + +OUI:0030BB* + ID_OUI_FROM_DATABASE=CacheFlow, Inc. + +OUI:0030BC* + ID_OUI_FROM_DATABASE=Optronic AG + +OUI:0030BD* + ID_OUI_FROM_DATABASE=BELKIN COMPONENTS + +OUI:0030BE* + ID_OUI_FROM_DATABASE=City-Net Technology, Inc. + +OUI:0030BF* + ID_OUI_FROM_DATABASE=MULTIDATA GMBH + +OUI:0030C0* + ID_OUI_FROM_DATABASE=Lara Technology, Inc. + +OUI:0030C1* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0030C2* + ID_OUI_FROM_DATABASE=COMONE + +OUI:0030C3* + ID_OUI_FROM_DATABASE=FLUECKIGER ELEKTRONIK AG + +OUI:0030C4* + ID_OUI_FROM_DATABASE=Canon Imaging Systems Inc. + +OUI:0030C5* + ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS, INC. + +OUI:0030C6* + ID_OUI_FROM_DATABASE=CONTROL SOLUTIONS, INC. + +OUI:0030C7* + ID_OUI_FROM_DATABASE=Macromate Corp. + +OUI:0030C8* + ID_OUI_FROM_DATABASE=GAD LINE, LTD. + +OUI:0030C9* + ID_OUI_FROM_DATABASE=LuxN, N + +OUI:0030CA* + ID_OUI_FROM_DATABASE=Discovery Com + +OUI:0030CB* + ID_OUI_FROM_DATABASE=OMNI FLOW COMPUTERS, INC. + +OUI:0030CC* + ID_OUI_FROM_DATABASE=Tenor Networks, Inc. + +OUI:0030CD* + ID_OUI_FROM_DATABASE=CONEXANT SYSTEMS, INC. + +OUI:0030CE* + ID_OUI_FROM_DATABASE=Zaffire + +OUI:0030CF* + ID_OUI_FROM_DATABASE=TWO TECHNOLOGIES, INC. + +OUI:0030D0* + ID_OUI_FROM_DATABASE=Tellabs + +OUI:0030D1* + ID_OUI_FROM_DATABASE=INOVA CORPORATION + +OUI:0030D2* + ID_OUI_FROM_DATABASE=WIN TECHNOLOGIES, CO., LTD. + +OUI:0030D3* + ID_OUI_FROM_DATABASE=Agilent Technologies, Inc. + +OUI:0030D4* + ID_OUI_FROM_DATABASE=AAE Systems, Inc. + +OUI:0030D5* + ID_OUI_FROM_DATABASE=DResearch GmbH + +OUI:0030D6* + ID_OUI_FROM_DATABASE=MSC VERTRIEBS GMBH + +OUI:0030D7* + ID_OUI_FROM_DATABASE=Innovative Systems, L.L.C. + +OUI:0030D8* + ID_OUI_FROM_DATABASE=SITEK + +OUI:0030D9* + ID_OUI_FROM_DATABASE=DATACORE SOFTWARE CORP. + +OUI:0030DA* + ID_OUI_FROM_DATABASE=Comtrend Corporation + +OUI:0030DB* + ID_OUI_FROM_DATABASE=Mindready Solutions, Inc. + +OUI:0030DC* + ID_OUI_FROM_DATABASE=RIGHTECH CORPORATION + +OUI:0030DD* + ID_OUI_FROM_DATABASE=INDIGITA CORPORATION + +OUI:0030DE* + ID_OUI_FROM_DATABASE=WAGO Kontakttechnik GmbH + +OUI:0030DF* + ID_OUI_FROM_DATABASE=KB/TEL TELECOMUNICACIONES + +OUI:0030E0* + ID_OUI_FROM_DATABASE=OXFORD SEMICONDUCTOR LTD. + +OUI:0030E1* + ID_OUI_FROM_DATABASE=Network Equipment Technologies, Inc. + +OUI:0030E2* + ID_OUI_FROM_DATABASE=GARNET SYSTEMS CO., LTD. + +OUI:0030E3* + ID_OUI_FROM_DATABASE=SEDONA NETWORKS CORP. + +OUI:0030E4* + ID_OUI_FROM_DATABASE=CHIYODA SYSTEM RIKEN + +OUI:0030E5* + ID_OUI_FROM_DATABASE=Amper Datos S.A. + +OUI:0030E6* + ID_OUI_FROM_DATABASE=Draeger Medical Systems, Inc. + +OUI:0030E7* + ID_OUI_FROM_DATABASE=CNF MOBILE SOLUTIONS, INC. + +OUI:0030E8* + ID_OUI_FROM_DATABASE=ENSIM CORP. + +OUI:0030E9* + ID_OUI_FROM_DATABASE=GMA COMMUNICATION MANUFACT'G + +OUI:0030EA* + ID_OUI_FROM_DATABASE=TeraForce Technology Corporation + +OUI:0030EB* + ID_OUI_FROM_DATABASE=TURBONET COMMUNICATIONS, INC. + +OUI:0030EC* + ID_OUI_FROM_DATABASE=BORGARDT + +OUI:0030ED* + ID_OUI_FROM_DATABASE=Expert Magnetics Corp. + +OUI:0030EE* + ID_OUI_FROM_DATABASE=DSG Technology, Inc. + +OUI:0030EF* + ID_OUI_FROM_DATABASE=NEON TECHNOLOGY, INC. + +OUI:0030F0* + ID_OUI_FROM_DATABASE=Uniform Industrial Corp. + +OUI:0030F1* + ID_OUI_FROM_DATABASE=Accton Technology Corp + +OUI:0030F2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0030F3* + ID_OUI_FROM_DATABASE=At Work Computers + +OUI:0030F4* + ID_OUI_FROM_DATABASE=STARDOT TECHNOLOGIES + +OUI:0030F5* + ID_OUI_FROM_DATABASE=Wild Lab. Ltd. + +OUI:0030F6* + ID_OUI_FROM_DATABASE=SECURELOGIX CORPORATION + +OUI:0030F7* + ID_OUI_FROM_DATABASE=RAMIX INC. + +OUI:0030F8* + ID_OUI_FROM_DATABASE=Dynapro Systems, Inc. + +OUI:0030F9* + ID_OUI_FROM_DATABASE=Sollae Systems Co., Ltd. + +OUI:0030FA* + ID_OUI_FROM_DATABASE=TELICA, INC. + +OUI:0030FB* + ID_OUI_FROM_DATABASE=AZS Technology AG + +OUI:0030FC* + ID_OUI_FROM_DATABASE=Terawave Communications, Inc. + +OUI:0030FD* + ID_OUI_FROM_DATABASE=INTEGRATED SYSTEMS DESIGN + +OUI:0030FE* + ID_OUI_FROM_DATABASE=DSA GmbH + +OUI:0030FF* + ID_OUI_FROM_DATABASE=DataFab Systems Inc. + +OUI:003146* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:003217* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00323A* + ID_OUI_FROM_DATABASE=so-logic + +OUI:00336C* + ID_OUI_FROM_DATABASE=SynapSense Corporation + +OUI:0034DA* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:0034F1* + ID_OUI_FROM_DATABASE=Radicom Research, Inc. + +OUI:0034FE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:00351A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003532* + ID_OUI_FROM_DATABASE=Electro-Metrics Corporation + +OUI:003560* + ID_OUI_FROM_DATABASE=Rosen Aviation + +OUI:0035FF* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:003676* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0036F8* + ID_OUI_FROM_DATABASE=Conti Temic microelectronic GmbH + +OUI:0036FE* + ID_OUI_FROM_DATABASE=SuperVision + +OUI:00376D* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:0037B7* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:0038DF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003A7D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003A98* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003A99* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003A9A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003A9B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003A9C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003A9D* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. + +OUI:003AAF* + ID_OUI_FROM_DATABASE=BlueBit Ltd. + +OUI:003C10* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:003CC5* + ID_OUI_FROM_DATABASE=WONWOO Engineering Co., Ltd + +OUI:003D41* + ID_OUI_FROM_DATABASE=Hatteland Computer AS + +OUI:003DE8* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:003EE1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:004000* + ID_OUI_FROM_DATABASE=PCI COMPONENTES DA AMZONIA LTD + +OUI:004001* + ID_OUI_FROM_DATABASE=Zero One Technology Co. Ltd. + +OUI:004002* + ID_OUI_FROM_DATABASE=PERLE SYSTEMS LIMITED + +OUI:004003* + ID_OUI_FROM_DATABASE=Emerson Process Management Power & Water Solutions, Inc. + +OUI:004004* + ID_OUI_FROM_DATABASE=ICM CO. LTD. + +OUI:004005* + ID_OUI_FROM_DATABASE=ANI COMMUNICATIONS INC. + +OUI:004006* + ID_OUI_FROM_DATABASE=SAMPO TECHNOLOGY CORPORATION + +OUI:004007* + ID_OUI_FROM_DATABASE=TELMAT INFORMATIQUE + +OUI:004008* + ID_OUI_FROM_DATABASE=A PLUS INFO CORPORATION + +OUI:004009* + ID_OUI_FROM_DATABASE=TACHIBANA TECTRON CO., LTD. + +OUI:00400A* + ID_OUI_FROM_DATABASE=PIVOTAL TECHNOLOGIES, INC. + +OUI:00400B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00400C* + ID_OUI_FROM_DATABASE=GENERAL MICRO SYSTEMS, INC. + +OUI:00400D* + ID_OUI_FROM_DATABASE=LANNET DATA COMMUNICATIONS,LTD + +OUI:00400E* + ID_OUI_FROM_DATABASE=MEMOTEC, INC. + +OUI:00400F* + ID_OUI_FROM_DATABASE=DATACOM TECHNOLOGIES + +OUI:004010* + ID_OUI_FROM_DATABASE=SONIC SYSTEMS, INC. + +OUI:004011* + ID_OUI_FROM_DATABASE=ANDOVER CONTROLS CORPORATION + +OUI:004012* + ID_OUI_FROM_DATABASE=WINDATA, INC. + +OUI:004013* + ID_OUI_FROM_DATABASE=NTT DATA COMM. SYSTEMS CORP. + +OUI:004014* + ID_OUI_FROM_DATABASE=COMSOFT GMBH + +OUI:004015* + ID_OUI_FROM_DATABASE=ASCOM INFRASYS AG + +OUI:004016* + ID_OUI_FROM_DATABASE=ADC - Global Connectivity Solutions Division + +OUI:004017* + ID_OUI_FROM_DATABASE=Silex Technology America + +OUI:004018* + ID_OUI_FROM_DATABASE=ADOBE SYSTEMS, INC. + +OUI:004019* + ID_OUI_FROM_DATABASE=AEON SYSTEMS, INC. + +OUI:00401A* + ID_OUI_FROM_DATABASE=FUJI ELECTRIC CO., LTD. + +OUI:00401B* + ID_OUI_FROM_DATABASE=PRINTER SYSTEMS CORP. + +OUI:00401C* + ID_OUI_FROM_DATABASE=AST RESEARCH, INC. + +OUI:00401D* + ID_OUI_FROM_DATABASE=INVISIBLE SOFTWARE, INC. + +OUI:00401E* + ID_OUI_FROM_DATABASE=ICC + +OUI:00401F* + ID_OUI_FROM_DATABASE=COLORGRAPH LTD + +OUI:004020* + ID_OUI_FROM_DATABASE=CommScope Inc + +OUI:004021* + ID_OUI_FROM_DATABASE=RASTER GRAPHICS + +OUI:004022* + ID_OUI_FROM_DATABASE=KLEVER COMPUTERS, INC. + +OUI:004023* + ID_OUI_FROM_DATABASE=LOGIC CORPORATION + +OUI:004024* + ID_OUI_FROM_DATABASE=COMPAC INC. + +OUI:004025* + ID_OUI_FROM_DATABASE=MOLECULAR DYNAMICS + +OUI:004026* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:004027* + ID_OUI_FROM_DATABASE=SMC MASSACHUSETTS, INC. + +OUI:004028* + ID_OUI_FROM_DATABASE=NETCOMM LIMITED + +OUI:004029* + ID_OUI_FROM_DATABASE=Compex + +OUI:00402A* + ID_OUI_FROM_DATABASE=Canoga Perkins Corporation + +OUI:00402B* + ID_OUI_FROM_DATABASE=TRIGEM COMPUTER, INC. + +OUI:00402C* + ID_OUI_FROM_DATABASE=ISIS DISTRIBUTED SYSTEMS, INC. + +OUI:00402D* + ID_OUI_FROM_DATABASE=HARRIS ADACOM CORPORATION + +OUI:00402E* + ID_OUI_FROM_DATABASE=PRECISION SOFTWARE, INC. + +OUI:00402F* + ID_OUI_FROM_DATABASE=XLNT DESIGNS INC. + +OUI:004030* + ID_OUI_FROM_DATABASE=GK COMPUTER + +OUI:004031* + ID_OUI_FROM_DATABASE=KOKUSAI ELECTRIC CO., LTD + +OUI:004032* + ID_OUI_FROM_DATABASE=DIGITAL COMMUNICATIONS + +OUI:004033* + ID_OUI_FROM_DATABASE=ADDTRON TECHNOLOGY CO., LTD. + +OUI:004034* + ID_OUI_FROM_DATABASE=BUSTEK CORPORATION + +OUI:004035* + ID_OUI_FROM_DATABASE=OPCOM + +OUI:004036* + ID_OUI_FROM_DATABASE=Zoom Telephonics, Inc + +OUI:004037* + ID_OUI_FROM_DATABASE=SEA-ILAN, INC. + +OUI:004038* + ID_OUI_FROM_DATABASE=TALENT ELECTRIC INCORPORATED + +OUI:004039* + ID_OUI_FROM_DATABASE=OPTEC DAIICHI DENKO CO., LTD. + +OUI:00403A* + ID_OUI_FROM_DATABASE=IMPACT TECHNOLOGIES + +OUI:00403B* + ID_OUI_FROM_DATABASE=SYNERJET INTERNATIONAL CORP. + +OUI:00403C* + ID_OUI_FROM_DATABASE=FORKS, INC. + +OUI:00403D* + ID_OUI_FROM_DATABASE=Teradata Corporation + +OUI:00403E* + ID_OUI_FROM_DATABASE=RASTER OPS CORPORATION + +OUI:00403F* + ID_OUI_FROM_DATABASE=SSANGYONG COMPUTER SYSTEMS + +OUI:004040* + ID_OUI_FROM_DATABASE=RING ACCESS, INC. + +OUI:004041* + ID_OUI_FROM_DATABASE=FUJIKURA LTD. + +OUI:004042* + ID_OUI_FROM_DATABASE=N.A.T. GMBH + +OUI:004043* + ID_OUI_FROM_DATABASE=Nokia Siemens Networks GmbH & Co. KG. + +OUI:004044* + ID_OUI_FROM_DATABASE=QNIX COMPUTER CO., LTD. + +OUI:004045* + ID_OUI_FROM_DATABASE=TWINHEAD CORPORATION + +OUI:004046* + ID_OUI_FROM_DATABASE=UDC RESEARCH LIMITED + +OUI:004047* + ID_OUI_FROM_DATABASE=WIND RIVER SYSTEMS + +OUI:004048* + ID_OUI_FROM_DATABASE=SMD INFORMATICA S.A. + +OUI:004049* + ID_OUI_FROM_DATABASE=Roche Diagnostics International Ltd. + +OUI:00404A* + ID_OUI_FROM_DATABASE=WEST AUSTRALIAN DEPARTMENT + +OUI:00404B* + ID_OUI_FROM_DATABASE=MAPLE COMPUTER SYSTEMS + +OUI:00404C* + ID_OUI_FROM_DATABASE=HYPERTEC PTY LTD. + +OUI:00404D* + ID_OUI_FROM_DATABASE=TELECOMMUNICATIONS TECHNIQUES + +OUI:00404E* + ID_OUI_FROM_DATABASE=FLUENT, INC. + +OUI:00404F* + ID_OUI_FROM_DATABASE=SPACE & NAVAL WARFARE SYSTEMS + +OUI:004050* + ID_OUI_FROM_DATABASE=IRONICS, INCORPORATED + +OUI:004051* + ID_OUI_FROM_DATABASE=Garbee and Garbee + +OUI:004052* + ID_OUI_FROM_DATABASE=STAR TECHNOLOGIES, INC. + +OUI:004053* + ID_OUI_FROM_DATABASE=AMPRO COMPUTERS + +OUI:004054* + ID_OUI_FROM_DATABASE=CONNECTION MACHINES SERVICES + +OUI:004055* + ID_OUI_FROM_DATABASE=METRONIX GMBH + +OUI:004056* + ID_OUI_FROM_DATABASE=MCM JAPAN LTD. + +OUI:004057* + ID_OUI_FROM_DATABASE=LOCKHEED - SANDERS + +OUI:004058* + ID_OUI_FROM_DATABASE=KRONOS, INC. + +OUI:004059* + ID_OUI_FROM_DATABASE=YOSHIDA KOGYO K. K. + +OUI:00405A* + ID_OUI_FROM_DATABASE=GOLDSTAR INFORMATION & COMM. + +OUI:00405B* + ID_OUI_FROM_DATABASE=FUNASSET LIMITED + +OUI:00405C* + ID_OUI_FROM_DATABASE=FUTURE SYSTEMS, INC. + +OUI:00405D* + ID_OUI_FROM_DATABASE=STAR-TEK, INC. + +OUI:00405E* + ID_OUI_FROM_DATABASE=NORTH HILLS ISRAEL + +OUI:00405F* + ID_OUI_FROM_DATABASE=AFE COMPUTERS LTD. + +OUI:004060* + ID_OUI_FROM_DATABASE=COMENDEC LTD + +OUI:004061* + ID_OUI_FROM_DATABASE=DATATECH ENTERPRISES CO., LTD. + +OUI:004062* + ID_OUI_FROM_DATABASE=E-SYSTEMS, INC./GARLAND DIV. + +OUI:004063* + ID_OUI_FROM_DATABASE=VIA TECHNOLOGIES, INC. + +OUI:004064* + ID_OUI_FROM_DATABASE=KLA INSTRUMENTS CORPORATION + +OUI:004065* + ID_OUI_FROM_DATABASE=GTE SPACENET + +OUI:004066* + ID_OUI_FROM_DATABASE=APRESIA Systems Ltd + +OUI:004067* + ID_OUI_FROM_DATABASE=OMNIBYTE CORPORATION + +OUI:004068* + ID_OUI_FROM_DATABASE=EXTENDED SYSTEMS + +OUI:004069* + ID_OUI_FROM_DATABASE=LEMCOM SYSTEMS, INC. + +OUI:00406A* + ID_OUI_FROM_DATABASE=KENTEK INFORMATION SYSTEMS,INC + +OUI:00406B* + ID_OUI_FROM_DATABASE=SYSGEN + +OUI:00406C* + ID_OUI_FROM_DATABASE=COPERNIQUE + +OUI:00406D* + ID_OUI_FROM_DATABASE=LANCO, INC. + +OUI:00406E* + ID_OUI_FROM_DATABASE=COROLLARY, INC. + +OUI:00406F* + ID_OUI_FROM_DATABASE=SYNC RESEARCH INC. + +OUI:004070* + ID_OUI_FROM_DATABASE=INTERWARE CO., LTD. + +OUI:004071* + ID_OUI_FROM_DATABASE=ATM COMPUTER GMBH + +OUI:004072* + ID_OUI_FROM_DATABASE=Applied Innovation Inc. + +OUI:004073* + ID_OUI_FROM_DATABASE=BASS ASSOCIATES + +OUI:004074* + ID_OUI_FROM_DATABASE=CABLE AND WIRELESS + +OUI:004075* + ID_OUI_FROM_DATABASE=Tattile SRL + +OUI:004076* + ID_OUI_FROM_DATABASE=Sun Conversion Technologies + +OUI:004077* + ID_OUI_FROM_DATABASE=MAXTON TECHNOLOGY CORPORATION + +OUI:004078* + ID_OUI_FROM_DATABASE=WEARNES AUTOMATION PTE LTD + +OUI:004079* + ID_OUI_FROM_DATABASE=JUKO MANUFACTURE COMPANY, LTD. + +OUI:00407A* + ID_OUI_FROM_DATABASE=SOCIETE D'EXPLOITATION DU CNIT + +OUI:00407B* + ID_OUI_FROM_DATABASE=SCIENTIFIC ATLANTA + +OUI:00407C* + ID_OUI_FROM_DATABASE=QUME CORPORATION + +OUI:00407D* + ID_OUI_FROM_DATABASE=EXTENSION TECHNOLOGY CORP. + +OUI:00407E* + ID_OUI_FROM_DATABASE=EVERGREEN SYSTEMS, INC. + +OUI:00407F* + ID_OUI_FROM_DATABASE=FLIR Systems + +OUI:004080* + ID_OUI_FROM_DATABASE=ATHENIX CORPORATION + +OUI:004081* + ID_OUI_FROM_DATABASE=MANNESMANN SCANGRAPHIC GMBH + +OUI:004082* + ID_OUI_FROM_DATABASE=LABORATORY EQUIPMENT CORP. + +OUI:004083* + ID_OUI_FROM_DATABASE=TDA INDUSTRIA DE PRODUTOS + +OUI:004084* + ID_OUI_FROM_DATABASE=Honeywell International HPS + +OUI:004085* + ID_OUI_FROM_DATABASE=SAAB INSTRUMENTS AB + +OUI:004086* + ID_OUI_FROM_DATABASE=MICHELS & KLEBERHOFF COMPUTER + +OUI:004087* + ID_OUI_FROM_DATABASE=UBITREX CORPORATION + +OUI:004088* + ID_OUI_FROM_DATABASE=MOBIUS TECHNOLOGIES, INC. + +OUI:004089* + ID_OUI_FROM_DATABASE=MEIDENSHA CORPORATION + +OUI:00408A* + ID_OUI_FROM_DATABASE=TPS TELEPROCESSING SYS. GMBH + +OUI:00408B* + ID_OUI_FROM_DATABASE=RAYLAN CORPORATION + +OUI:00408C* + ID_OUI_FROM_DATABASE=AXIS COMMUNICATIONS AB + +OUI:00408D* + ID_OUI_FROM_DATABASE=THE GOODYEAR TIRE & RUBBER CO. + +OUI:00408E* + ID_OUI_FROM_DATABASE=Tattile SRL + +OUI:00408F* + ID_OUI_FROM_DATABASE=WM-DATA MINFO AB + +OUI:004090* + ID_OUI_FROM_DATABASE=ANSEL COMMUNICATIONS + +OUI:004091* + ID_OUI_FROM_DATABASE=PROCOMP INDUSTRIA ELETRONICA + +OUI:004092* + ID_OUI_FROM_DATABASE=ASP COMPUTER PRODUCTS, INC. + +OUI:004093* + ID_OUI_FROM_DATABASE=PAXDATA NETWORKS LTD. + +OUI:004094* + ID_OUI_FROM_DATABASE=SHOGRAPHICS, INC. + +OUI:004095* + ID_OUI_FROM_DATABASE=R.P.T. INTERGROUPS INT'L LTD. + +OUI:004096* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:004097* + ID_OUI_FROM_DATABASE=DATEX DIVISION OF + +OUI:004098* + ID_OUI_FROM_DATABASE=DRESSLER GMBH & CO. + +OUI:004099* + ID_OUI_FROM_DATABASE=NEWGEN SYSTEMS CORP. + +OUI:00409A* + ID_OUI_FROM_DATABASE=NETWORK EXPRESS, INC. + +OUI:00409B* + ID_OUI_FROM_DATABASE=HAL COMPUTER SYSTEMS INC. + +OUI:00409C* + ID_OUI_FROM_DATABASE=TRANSWARE + +OUI:00409D* + ID_OUI_FROM_DATABASE=DigiBoard + +OUI:00409E* + ID_OUI_FROM_DATABASE=CONCURRENT TECHNOLOGIES LTD. + +OUI:00409F* + ID_OUI_FROM_DATABASE=Telco Systems, Inc. + +OUI:0040A0* + ID_OUI_FROM_DATABASE=GOLDSTAR CO., LTD. + +OUI:0040A1* + ID_OUI_FROM_DATABASE=ERGO COMPUTING + +OUI:0040A2* + ID_OUI_FROM_DATABASE=KINGSTAR TECHNOLOGY INC. + +OUI:0040A3* + ID_OUI_FROM_DATABASE=MICROUNITY SYSTEMS ENGINEERING + +OUI:0040A4* + ID_OUI_FROM_DATABASE=ROSE ELECTRONICS + +OUI:0040A5* + ID_OUI_FROM_DATABASE=CLINICOMP INTL. + +OUI:0040A6* + ID_OUI_FROM_DATABASE=Cray, Inc. + +OUI:0040A7* + ID_OUI_FROM_DATABASE=ITAUTEC PHILCO S.A. + +OUI:0040A8* + ID_OUI_FROM_DATABASE=IMF INTERNATIONAL LTD. + +OUI:0040A9* + ID_OUI_FROM_DATABASE=DATACOM INC. + +OUI:0040AA* + ID_OUI_FROM_DATABASE=Valmet Automation + +OUI:0040AB* + ID_OUI_FROM_DATABASE=ROLAND DG CORPORATION + +OUI:0040AC* + ID_OUI_FROM_DATABASE=SUPER WORKSTATION, INC. + +OUI:0040AD* + ID_OUI_FROM_DATABASE=SMA REGELSYSTEME GMBH + +OUI:0040AE* + ID_OUI_FROM_DATABASE=DELTA CONTROLS, INC. + +OUI:0040AF* + ID_OUI_FROM_DATABASE=DIGITAL PRODUCTS, INC. + +OUI:0040B0* + ID_OUI_FROM_DATABASE=BYTEX CORPORATION, ENGINEERING + +OUI:0040B1* + ID_OUI_FROM_DATABASE=CODONICS INC. + +OUI:0040B2* + ID_OUI_FROM_DATABASE=SYSTEMFORSCHUNG + +OUI:0040B3* + ID_OUI_FROM_DATABASE=ParTech Inc. + +OUI:0040B4* + ID_OUI_FROM_DATABASE=NEXTCOM K.K. + +OUI:0040B5* + ID_OUI_FROM_DATABASE=VIDEO TECHNOLOGY COMPUTERS LTD + +OUI:0040B6* + ID_OUI_FROM_DATABASE=COMPUTERM CORPORATION + +OUI:0040B7* + ID_OUI_FROM_DATABASE=STEALTH COMPUTER SYSTEMS + +OUI:0040B8* + ID_OUI_FROM_DATABASE=IDEA ASSOCIATES + +OUI:0040B9* + ID_OUI_FROM_DATABASE=MACQ ELECTRONIQUE SA + +OUI:0040BA* + ID_OUI_FROM_DATABASE=ALLIANT COMPUTER SYSTEMS CORP. + +OUI:0040BB* + ID_OUI_FROM_DATABASE=GOLDSTAR CABLE CO., LTD. + +OUI:0040BC* + ID_OUI_FROM_DATABASE=ALGORITHMICS LTD. + +OUI:0040BD* + ID_OUI_FROM_DATABASE=STARLIGHT NETWORKS, INC. + +OUI:0040BE* + ID_OUI_FROM_DATABASE=BOEING DEFENSE & SPACE + +OUI:0040BF* + ID_OUI_FROM_DATABASE=CHANNEL SYSTEMS INTERN'L INC. + +OUI:0040C0* + ID_OUI_FROM_DATABASE=VISTA CONTROLS CORPORATION + +OUI:0040C1* + ID_OUI_FROM_DATABASE=BIZERBA-WERKE WILHEIM KRAUT + +OUI:0040C2* + ID_OUI_FROM_DATABASE=APPLIED COMPUTING DEVICES + +OUI:0040C3* + ID_OUI_FROM_DATABASE=FISCHER AND PORTER CO. + +OUI:0040C4* + ID_OUI_FROM_DATABASE=KINKEI SYSTEM CORPORATION + +OUI:0040C5* + ID_OUI_FROM_DATABASE=MICOM COMMUNICATIONS INC. + +OUI:0040C6* + ID_OUI_FROM_DATABASE=FIBERNET RESEARCH, INC. + +OUI:0040C7* + ID_OUI_FROM_DATABASE=RUBY TECH CORPORATION + +OUI:0040C8* + ID_OUI_FROM_DATABASE=MILAN TECHNOLOGY CORPORATION + +OUI:0040C9* + ID_OUI_FROM_DATABASE=NCUBE + +OUI:0040CA* + ID_OUI_FROM_DATABASE=FIRST INTERNAT'L COMPUTER, INC + +OUI:0040CB* + ID_OUI_FROM_DATABASE=LANWAN TECHNOLOGIES + +OUI:0040CC* + ID_OUI_FROM_DATABASE=SILCOM MANUF'G TECHNOLOGY INC. + +OUI:0040CD* + ID_OUI_FROM_DATABASE=TERA MICROSYSTEMS, INC. + +OUI:0040CE* + ID_OUI_FROM_DATABASE=NET-SOURCE, INC. + +OUI:0040CF* + ID_OUI_FROM_DATABASE=STRAWBERRY TREE, INC. + +OUI:0040D0* + ID_OUI_FROM_DATABASE=MITAC INTERNATIONAL CORP. + +OUI:0040D1* + ID_OUI_FROM_DATABASE=FUKUDA DENSHI CO., LTD. + +OUI:0040D2* + ID_OUI_FROM_DATABASE=PAGINE CORPORATION + +OUI:0040D3* + ID_OUI_FROM_DATABASE=KIMPSION INTERNATIONAL CORP. + +OUI:0040D4* + ID_OUI_FROM_DATABASE=GAGE TALKER CORP. + +OUI:0040D5* + ID_OUI_FROM_DATABASE=Sartorius Mechatronics T&H GmbH + +OUI:0040D6* + ID_OUI_FROM_DATABASE=LOCAMATION B.V. + +OUI:0040D7* + ID_OUI_FROM_DATABASE=STUDIO GEN INC. + +OUI:0040D8* + ID_OUI_FROM_DATABASE=OCEAN OFFICE AUTOMATION LTD. + +OUI:0040D9* + ID_OUI_FROM_DATABASE=AMERICAN MEGATRENDS INC. + +OUI:0040DA* + ID_OUI_FROM_DATABASE=TELSPEC LTD + +OUI:0040DB* + ID_OUI_FROM_DATABASE=ADVANCED TECHNICAL SOLUTIONS + +OUI:0040DC* + ID_OUI_FROM_DATABASE=TRITEC ELECTRONIC GMBH + +OUI:0040DD* + ID_OUI_FROM_DATABASE=HONG TECHNOLOGIES + +OUI:0040DE* + ID_OUI_FROM_DATABASE=Elsag Datamat spa + +OUI:0040DF* + ID_OUI_FROM_DATABASE=DIGALOG SYSTEMS, INC. + +OUI:0040E0* + ID_OUI_FROM_DATABASE=ATOMWIDE LTD. + +OUI:0040E1* + ID_OUI_FROM_DATABASE=MARNER INTERNATIONAL, INC. + +OUI:0040E2* + ID_OUI_FROM_DATABASE=MESA RIDGE TECHNOLOGIES, INC. + +OUI:0040E3* + ID_OUI_FROM_DATABASE=QUIN SYSTEMS LTD + +OUI:0040E4* + ID_OUI_FROM_DATABASE=E-M TECHNOLOGY, INC. + +OUI:0040E5* + ID_OUI_FROM_DATABASE=SYBUS CORPORATION + +OUI:0040E6* + ID_OUI_FROM_DATABASE=C.A.E.N. + +OUI:0040E7* + ID_OUI_FROM_DATABASE=ARNOS INSTRUMENTS & COMPUTER + +OUI:0040E8* + ID_OUI_FROM_DATABASE=CHARLES RIVER DATA SYSTEMS,INC + +OUI:0040E9* + ID_OUI_FROM_DATABASE=ACCORD SYSTEMS, INC. + +OUI:0040EA* + ID_OUI_FROM_DATABASE=PLAIN TREE SYSTEMS INC + +OUI:0040EB* + ID_OUI_FROM_DATABASE=MARTIN MARIETTA CORPORATION + +OUI:0040EC* + ID_OUI_FROM_DATABASE=MIKASA SYSTEM ENGINEERING + +OUI:0040ED* + ID_OUI_FROM_DATABASE=NETWORK CONTROLS INT'NATL INC. + +OUI:0040EE* + ID_OUI_FROM_DATABASE=OPTIMEM + +OUI:0040EF* + ID_OUI_FROM_DATABASE=HYPERCOM, INC. + +OUI:0040F0* + ID_OUI_FROM_DATABASE=MicroBrain,Inc. + +OUI:0040F1* + ID_OUI_FROM_DATABASE=CHUO ELECTRONICS CO., LTD. + +OUI:0040F2* + ID_OUI_FROM_DATABASE=JANICH & KLASS COMPUTERTECHNIK + +OUI:0040F3* + ID_OUI_FROM_DATABASE=NETCOR + +OUI:0040F4* + ID_OUI_FROM_DATABASE=CAMEO COMMUNICATIONS, INC. + +OUI:0040F5* + ID_OUI_FROM_DATABASE=OEM ENGINES + +OUI:0040F6* + ID_OUI_FROM_DATABASE=KATRON COMPUTERS INC. + +OUI:0040F7* + ID_OUI_FROM_DATABASE=Polaroid Corporation + +OUI:0040F8* + ID_OUI_FROM_DATABASE=SYSTEMHAUS DISCOM + +OUI:0040F9* + ID_OUI_FROM_DATABASE=COMBINET + +OUI:0040FA* + ID_OUI_FROM_DATABASE=MICROBOARDS, INC. + +OUI:0040FB* + ID_OUI_FROM_DATABASE=CASCADE COMMUNICATIONS + +OUI:0040FC* + ID_OUI_FROM_DATABASE=IBR COMPUTER TECHNIK GMBH + +OUI:0040FD* + ID_OUI_FROM_DATABASE=LXE + +OUI:0040FE* + ID_OUI_FROM_DATABASE=SYMPLEX COMMUNICATIONS + +OUI:0040FF* + ID_OUI_FROM_DATABASE=TELEBIT CORPORATION + +OUI:0041B4* + ID_OUI_FROM_DATABASE=Wuxi Zhongxing Optoelectronics Technology Co.,Ltd. + +OUI:0041D2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:004252* + ID_OUI_FROM_DATABASE=RLX Technologies + +OUI:00425A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:004268* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:004279* + ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd + +OUI:0043FF* + ID_OUI_FROM_DATABASE=KETRON S.R.L. + +OUI:004501* + ID_OUI_FROM_DATABASE=Midmark RTLS + +OUI:00451D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0045E2* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. + +OUI:00464B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:004A77* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:004BF3* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:004D32* + ID_OUI_FROM_DATABASE=Andon Health Co.,Ltd. + +OUI:004E01* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:004E35* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:005000* + ID_OUI_FROM_DATABASE=NEXO COMMUNICATIONS, INC. + +OUI:005001* + ID_OUI_FROM_DATABASE=YAMASHITA SYSTEMS CORP. + +OUI:005002* + ID_OUI_FROM_DATABASE=OMNISEC AG + +OUI:005003* + ID_OUI_FROM_DATABASE=Xrite Inc + +OUI:005004* + ID_OUI_FROM_DATABASE=3COM + +OUI:005006* + ID_OUI_FROM_DATABASE=TAC AB + +OUI:005007* + ID_OUI_FROM_DATABASE=SIEMENS TELECOMMUNICATION SYSTEMS LIMITED + +OUI:005008* + ID_OUI_FROM_DATABASE=TIVA MICROCOMPUTER CORP. (TMC) + +OUI:005009* + ID_OUI_FROM_DATABASE=PHILIPS BROADBAND NETWORKS + +OUI:00500A* + ID_OUI_FROM_DATABASE=IRIS TECHNOLOGIES, INC. + +OUI:00500B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00500C* + ID_OUI_FROM_DATABASE=e-Tek Labs, Inc. + +OUI:00500D* + ID_OUI_FROM_DATABASE=SATORI ELECTORIC CO., LTD. + +OUI:00500E* + ID_OUI_FROM_DATABASE=CHROMATIS NETWORKS, INC. + +OUI:00500F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:005010* + ID_OUI_FROM_DATABASE=NovaNET Learning, Inc. + +OUI:005012* + ID_OUI_FROM_DATABASE=CBL - GMBH + +OUI:005013* + ID_OUI_FROM_DATABASE=Seagate Cloud Systems Inc + +OUI:005014* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:005015* + ID_OUI_FROM_DATABASE=BRIGHT STAR ENGINEERING + +OUI:005016* + ID_OUI_FROM_DATABASE=Molex Canada Ltd + +OUI:005017* + ID_OUI_FROM_DATABASE=RSR S.R.L. + +OUI:005018* + ID_OUI_FROM_DATABASE=AMIT, Inc. + +OUI:005019* + ID_OUI_FROM_DATABASE=SPRING TIDE NETWORKS, INC. + +OUI:00501A* + ID_OUI_FROM_DATABASE=IQinVision + +OUI:00501B* + ID_OUI_FROM_DATABASE=ABL CANADA, INC. + +OUI:00501C* + ID_OUI_FROM_DATABASE=JATOM SYSTEMS, INC. + +OUI:00501E* + ID_OUI_FROM_DATABASE=Grass Valley, A Belden Brand + +OUI:00501F* + ID_OUI_FROM_DATABASE=MRG SYSTEMS, LTD. + +OUI:005020* + ID_OUI_FROM_DATABASE=MEDIASTAR CO., LTD. + +OUI:005021* + ID_OUI_FROM_DATABASE=EIS INTERNATIONAL, INC. + +OUI:005022* + ID_OUI_FROM_DATABASE=ZONET TECHNOLOGY, INC. + +OUI:005023* + ID_OUI_FROM_DATABASE=PG DESIGN ELECTRONICS, INC. + +OUI:005024* + ID_OUI_FROM_DATABASE=NAVIC SYSTEMS, INC. + +OUI:005026* + ID_OUI_FROM_DATABASE=COSYSTEMS, INC. + +OUI:005027* + ID_OUI_FROM_DATABASE=GENICOM CORPORATION + +OUI:005028* + ID_OUI_FROM_DATABASE=AVAL COMMUNICATIONS + +OUI:005029* + ID_OUI_FROM_DATABASE=1394 PRINTER WORKING GROUP + +OUI:00502A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00502B* + ID_OUI_FROM_DATABASE=GENRAD LTD. + +OUI:00502C* + ID_OUI_FROM_DATABASE=SOYO COMPUTER, INC. + +OUI:00502D* + ID_OUI_FROM_DATABASE=ACCEL, INC. + +OUI:00502E* + ID_OUI_FROM_DATABASE=CAMBEX CORPORATION + +OUI:00502F* + ID_OUI_FROM_DATABASE=TollBridge Technologies, Inc. + +OUI:005030* + ID_OUI_FROM_DATABASE=FUTURE PLUS SYSTEMS + +OUI:005031* + ID_OUI_FROM_DATABASE=AEROFLEX LABORATORIES, INC. + +OUI:005032* + ID_OUI_FROM_DATABASE=PICAZO COMMUNICATIONS, INC. + +OUI:005033* + ID_OUI_FROM_DATABASE=MAYAN NETWORKS + +OUI:005036* + ID_OUI_FROM_DATABASE=NETCAM, LTD. + +OUI:005037* + ID_OUI_FROM_DATABASE=KOGA ELECTRONICS CO. + +OUI:005038* + ID_OUI_FROM_DATABASE=DAIN TELECOM CO., LTD. + +OUI:005039* + ID_OUI_FROM_DATABASE=MARINER NETWORKS + +OUI:00503A* + ID_OUI_FROM_DATABASE=DATONG ELECTRONICS LTD. + +OUI:00503B* + ID_OUI_FROM_DATABASE=MEDIAFIRE CORPORATION + +OUI:00503C* + ID_OUI_FROM_DATABASE=TSINGHUA NOVEL ELECTRONICS + +OUI:00503E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00503F* + ID_OUI_FROM_DATABASE=ANCHOR GAMES + +OUI:005040* + ID_OUI_FROM_DATABASE=Panasonic Electric Works Co., Ltd. + +OUI:005041* + ID_OUI_FROM_DATABASE=Coretronic Corporation + +OUI:005042* + ID_OUI_FROM_DATABASE=SCI MANUFACTURING SINGAPORE PTE, LTD. + +OUI:005043* + ID_OUI_FROM_DATABASE=MARVELL SEMICONDUCTOR, INC. + +OUI:005044* + ID_OUI_FROM_DATABASE=ASACA CORPORATION + +OUI:005045* + ID_OUI_FROM_DATABASE=RIOWORKS SOLUTIONS, INC. + +OUI:005046* + ID_OUI_FROM_DATABASE=MENICX INTERNATIONAL CO., LTD. + +OUI:005047* + ID_OUI_FROM_DATABASE=Private + +OUI:005048* + ID_OUI_FROM_DATABASE=INFOLIBRIA + +OUI:005049* + ID_OUI_FROM_DATABASE=Arbor Networks Inc + +OUI:00504A* + ID_OUI_FROM_DATABASE=ELTECO A.S. + +OUI:00504B* + ID_OUI_FROM_DATABASE=BARCONET N.V. + +OUI:00504C* + ID_OUI_FROM_DATABASE=Galil Motion Control + +OUI:00504D* + ID_OUI_FROM_DATABASE=Tokyo Electron Device Limited + +OUI:00504E* + ID_OUI_FROM_DATABASE=SIERRA MONITOR CORP. + +OUI:00504F* + ID_OUI_FROM_DATABASE=OLENCOM ELECTRONICS + +OUI:005050* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:005051* + ID_OUI_FROM_DATABASE=IWATSU ELECTRIC CO., LTD. + +OUI:005052* + ID_OUI_FROM_DATABASE=TIARA NETWORKS, INC. + +OUI:005053* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:005054* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:005055* + ID_OUI_FROM_DATABASE=DOMS A/S + +OUI:005056* + ID_OUI_FROM_DATABASE=VMware, Inc. + +OUI:005057* + ID_OUI_FROM_DATABASE=BROADBAND ACCESS SYSTEMS + +OUI:005058* + ID_OUI_FROM_DATABASE=Sangoma Technologies + +OUI:005059* + ID_OUI_FROM_DATABASE=iBAHN + +OUI:00505A* + ID_OUI_FROM_DATABASE=NETWORK ALCHEMY, INC. + +OUI:00505B* + ID_OUI_FROM_DATABASE=KAWASAKI LSI U.S.A., INC. + +OUI:00505C* + ID_OUI_FROM_DATABASE=TUNDO CORPORATION + +OUI:00505E* + ID_OUI_FROM_DATABASE=DIGITEK MICROLOGIC S.A. + +OUI:00505F* + ID_OUI_FROM_DATABASE=BRAND INNOVATORS + +OUI:005060* + ID_OUI_FROM_DATABASE=TANDBERG TELECOM AS + +OUI:005062* + ID_OUI_FROM_DATABASE=KOUWELL ELECTRONICS CORP. ** + +OUI:005063* + ID_OUI_FROM_DATABASE=OY COMSEL SYSTEM AB + +OUI:005064* + ID_OUI_FROM_DATABASE=CAE ELECTRONICS + +OUI:005065* + ID_OUI_FROM_DATABASE=TDK-Lambda Corporation + +OUI:005066* + ID_OUI_FROM_DATABASE=AtecoM GmbH advanced telecomunication modules + +OUI:005067* + ID_OUI_FROM_DATABASE=AEROCOMM, INC. + +OUI:005068* + ID_OUI_FROM_DATABASE=ELECTRONIC INDUSTRIES ASSOCIATION + +OUI:005069* + ID_OUI_FROM_DATABASE=PixStream Incorporated + +OUI:00506A* + ID_OUI_FROM_DATABASE=EDEVA, INC. + +OUI:00506B* + ID_OUI_FROM_DATABASE=SPX-ATEG + +OUI:00506C* + ID_OUI_FROM_DATABASE=Beijer Electronics Products AB + +OUI:00506D* + ID_OUI_FROM_DATABASE=VIDEOJET SYSTEMS + +OUI:00506E* + ID_OUI_FROM_DATABASE=CORDER ENGINEERING CORPORATION + +OUI:00506F* + ID_OUI_FROM_DATABASE=G-CONNECT + +OUI:005070* + ID_OUI_FROM_DATABASE=CHAINTECH COMPUTER CO., LTD. + +OUI:005071* + ID_OUI_FROM_DATABASE=AIWA CO., LTD. + +OUI:005072* + ID_OUI_FROM_DATABASE=CORVIS CORPORATION + +OUI:005073* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:005074* + ID_OUI_FROM_DATABASE=ADVANCED HI-TECH CORP. + +OUI:005075* + ID_OUI_FROM_DATABASE=KESTREL SOLUTIONS + +OUI:005076* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:005077* + ID_OUI_FROM_DATABASE=PROLIFIC TECHNOLOGY, INC. + +OUI:005078* + ID_OUI_FROM_DATABASE=MEGATON HOUSE, LTD. + +OUI:005079* + ID_OUI_FROM_DATABASE=Private + +OUI:00507A* + ID_OUI_FROM_DATABASE=XPEED, INC. + +OUI:00507B* + ID_OUI_FROM_DATABASE=MERLOT COMMUNICATIONS + +OUI:00507C* + ID_OUI_FROM_DATABASE=VIDEOCON AG + +OUI:00507D* + ID_OUI_FROM_DATABASE=IFP + +OUI:00507E* + ID_OUI_FROM_DATABASE=NEWER TECHNOLOGY + +OUI:00507F* + ID_OUI_FROM_DATABASE=DrayTek Corp. + +OUI:005080* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:005081* + ID_OUI_FROM_DATABASE=MURATA MACHINERY, LTD. + +OUI:005082* + ID_OUI_FROM_DATABASE=FORESSON CORPORATION + +OUI:005083* + ID_OUI_FROM_DATABASE=GILBARCO, INC. + +OUI:005084* + ID_OUI_FROM_DATABASE=Quantum Corp. + +OUI:005086* + ID_OUI_FROM_DATABASE=TELKOM SA, LTD. + +OUI:005087* + ID_OUI_FROM_DATABASE=TERASAKI ELECTRIC CO., LTD. + +OUI:005088* + ID_OUI_FROM_DATABASE=AMANO CORPORATION + +OUI:005089* + ID_OUI_FROM_DATABASE=SAFETY MANAGEMENT SYSTEMS + +OUI:00508B* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:00508C* + ID_OUI_FROM_DATABASE=RSI SYSTEMS + +OUI:00508D* + ID_OUI_FROM_DATABASE=ABIT COMPUTER CORPORATION + +OUI:00508E* + ID_OUI_FROM_DATABASE=OPTIMATION, INC. + +OUI:00508F* + ID_OUI_FROM_DATABASE=ASITA TECHNOLOGIES INT'L LTD. + +OUI:005090* + ID_OUI_FROM_DATABASE=DCTRI + +OUI:005091* + ID_OUI_FROM_DATABASE=NETACCESS, INC. + +OUI:005092* + ID_OUI_FROM_DATABASE=Rigaku Corporation Osaka Plant + +OUI:005093* + ID_OUI_FROM_DATABASE=BOEING + +OUI:005094* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:005095* + ID_OUI_FROM_DATABASE=PERACOM NETWORKS + +OUI:005096* + ID_OUI_FROM_DATABASE=SALIX TECHNOLOGIES, INC. + +OUI:005097* + ID_OUI_FROM_DATABASE=MMC-EMBEDDED COMPUTERTECHNIK GmbH + +OUI:005098* + ID_OUI_FROM_DATABASE=GLOBALOOP, LTD. + +OUI:005099* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:00509A* + ID_OUI_FROM_DATABASE=TAG ELECTRONIC SYSTEMS + +OUI:00509B* + ID_OUI_FROM_DATABASE=SWITCHCORE AB + +OUI:00509C* + ID_OUI_FROM_DATABASE=BETA RESEARCH + +OUI:00509D* + ID_OUI_FROM_DATABASE=THE INDUSTREE B.V. + +OUI:00509E* + ID_OUI_FROM_DATABASE=Les Technologies SoftAcoustik Inc. + +OUI:00509F* + ID_OUI_FROM_DATABASE=HORIZON COMPUTER + +OUI:0050A0* + ID_OUI_FROM_DATABASE=DELTA COMPUTER SYSTEMS, INC. + +OUI:0050A1* + ID_OUI_FROM_DATABASE=CARLO GAVAZZI, INC. + +OUI:0050A2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0050A3* + ID_OUI_FROM_DATABASE=TransMedia Communications, Inc. + +OUI:0050A4* + ID_OUI_FROM_DATABASE=IO TECH, INC. + +OUI:0050A5* + ID_OUI_FROM_DATABASE=CAPITOL BUSINESS SYSTEMS, LTD. + +OUI:0050A6* + ID_OUI_FROM_DATABASE=OPTRONICS + +OUI:0050A7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0050A8* + ID_OUI_FROM_DATABASE=OpenCon Systems, Inc. + +OUI:0050A9* + ID_OUI_FROM_DATABASE=MOLDAT WIRELESS TECHNOLGIES + +OUI:0050AA* + ID_OUI_FROM_DATABASE=KONICA MINOLTA HOLDINGS, INC. + +OUI:0050AB* + ID_OUI_FROM_DATABASE=NALTEC, Inc. + +OUI:0050AC* + ID_OUI_FROM_DATABASE=MAPLE COMPUTER CORPORATION + +OUI:0050AD* + ID_OUI_FROM_DATABASE=CommUnique Wireless Corp. + +OUI:0050AE* + ID_OUI_FROM_DATABASE=FDK Co., Ltd + +OUI:0050AF* + ID_OUI_FROM_DATABASE=INTERGON, INC. + +OUI:0050B0* + ID_OUI_FROM_DATABASE=TECHNOLOGY ATLANTA CORPORATION + +OUI:0050B1* + ID_OUI_FROM_DATABASE=GIDDINGS & LEWIS + +OUI:0050B2* + ID_OUI_FROM_DATABASE=BRODEL GmbH + +OUI:0050B3* + ID_OUI_FROM_DATABASE=VOICEBOARD CORPORATION + +OUI:0050B4* + ID_OUI_FROM_DATABASE=SATCHWELL CONTROL SYSTEMS, LTD + +OUI:0050B5* + ID_OUI_FROM_DATABASE=FICHET SECURITE ELECTRONIQUE + +OUI:0050B6* + ID_OUI_FROM_DATABASE=GOOD WAY IND. CO., LTD. + +OUI:0050B7* + ID_OUI_FROM_DATABASE=BOSER TECHNOLOGY CO., LTD. + +OUI:0050B8* + ID_OUI_FROM_DATABASE=INOVA COMPUTERS GMBH & CO. KG + +OUI:0050B9* + ID_OUI_FROM_DATABASE=XITRON TECHNOLOGIES, INC. + +OUI:0050BA* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:0050BB* + ID_OUI_FROM_DATABASE=CMS TECHNOLOGIES + +OUI:0050BC* + ID_OUI_FROM_DATABASE=HAMMER STORAGE SOLUTIONS + +OUI:0050BD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0050BE* + ID_OUI_FROM_DATABASE=FAST MULTIMEDIA AG + +OUI:0050BF* + ID_OUI_FROM_DATABASE=Metalligence Technology Corp. + +OUI:0050C0* + ID_OUI_FROM_DATABASE=GATAN, INC. + +OUI:0050C1* + ID_OUI_FROM_DATABASE=GEMFLEX NETWORKS, LTD. + +OUI:0050C2* + ID_OUI_FROM_DATABASE=IEEE Registration Authority + +OUI:0050C4* + ID_OUI_FROM_DATABASE=IMD + +OUI:0050C5* + ID_OUI_FROM_DATABASE=ADS Technologies, Inc + +OUI:0050C6* + ID_OUI_FROM_DATABASE=LOOP TELECOMMUNICATION INTERNATIONAL, INC. + +OUI:0050C7* + ID_OUI_FROM_DATABASE=Private + +OUI:0050C8* + ID_OUI_FROM_DATABASE=Addonics Technologies, Inc. + +OUI:0050C9* + ID_OUI_FROM_DATABASE=MASPRO DENKOH CORP. + +OUI:0050CA* + ID_OUI_FROM_DATABASE=NET TO NET TECHNOLOGIES + +OUI:0050CB* + ID_OUI_FROM_DATABASE=JETTER + +OUI:0050CC* + ID_OUI_FROM_DATABASE=Seagate Cloud Systems Inc + +OUI:0050CD* + ID_OUI_FROM_DATABASE=DIGIANSWER A/S + +OUI:0050CE* + ID_OUI_FROM_DATABASE=LG INTERNATIONAL CORP. + +OUI:0050CF* + ID_OUI_FROM_DATABASE=VANLINK COMMUNICATION TECHNOLOGY RESEARCH INSTITUTE + +OUI:0050D0* + ID_OUI_FROM_DATABASE=MINERVA SYSTEMS + +OUI:0050D1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0050D2* + ID_OUI_FROM_DATABASE=CMC Electronics Inc + +OUI:0050D3* + ID_OUI_FROM_DATABASE=DIGITAL AUDIO PROCESSING PTY. LTD. + +OUI:0050D4* + ID_OUI_FROM_DATABASE=JOOHONG INFORMATION & + +OUI:0050D5* + ID_OUI_FROM_DATABASE=AD SYSTEMS CORP. + +OUI:0050D6* + ID_OUI_FROM_DATABASE=ATLAS COPCO TOOLS AB + +OUI:0050D7* + ID_OUI_FROM_DATABASE=TELSTRAT + +OUI:0050D8* + ID_OUI_FROM_DATABASE=UNICORN COMPUTER CORP. + +OUI:0050D9* + ID_OUI_FROM_DATABASE=ENGETRON-ENGENHARIA ELETRONICA IND. e COM. LTDA + +OUI:0050DA* + ID_OUI_FROM_DATABASE=3COM + +OUI:0050DB* + ID_OUI_FROM_DATABASE=CONTEMPORARY CONTROL + +OUI:0050DC* + ID_OUI_FROM_DATABASE=TAS TELEFONBAU A. SCHWABE GMBH & CO. KG + +OUI:0050DD* + ID_OUI_FROM_DATABASE=SERRA SOLDADURA, S.A. + +OUI:0050DE* + ID_OUI_FROM_DATABASE=SIGNUM SYSTEMS CORP. + +OUI:0050DF* + ID_OUI_FROM_DATABASE=AirFiber, Inc. + +OUI:0050E1* + ID_OUI_FROM_DATABASE=NS TECH ELECTRONICS SDN BHD + +OUI:0050E2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0050E3* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0050E4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0050E6* + ID_OUI_FROM_DATABASE=HAKUSAN CORPORATION + +OUI:0050E7* + ID_OUI_FROM_DATABASE=PARADISE INNOVATIONS (ASIA) + +OUI:0050E8* + ID_OUI_FROM_DATABASE=NOMADIX INC. + +OUI:0050EA* + ID_OUI_FROM_DATABASE=XEL COMMUNICATIONS, INC. + +OUI:0050EB* + ID_OUI_FROM_DATABASE=ALPHA-TOP CORPORATION + +OUI:0050EC* + ID_OUI_FROM_DATABASE=OLICOM A/S + +OUI:0050ED* + ID_OUI_FROM_DATABASE=ANDA NETWORKS + +OUI:0050EE* + ID_OUI_FROM_DATABASE=TEK DIGITEL CORPORATION + +OUI:0050EF* + ID_OUI_FROM_DATABASE=SPE Systemhaus GmbH + +OUI:0050F0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0050F1* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:0050F2* + ID_OUI_FROM_DATABASE=MICROSOFT CORP. + +OUI:0050F3* + ID_OUI_FROM_DATABASE=GLOBAL NET INFORMATION CO., Ltd. + +OUI:0050F4* + ID_OUI_FROM_DATABASE=SIGMATEK GMBH & CO. KG + +OUI:0050F6* + ID_OUI_FROM_DATABASE=PAN-INTERNATIONAL INDUSTRIAL CORP. + +OUI:0050F7* + ID_OUI_FROM_DATABASE=VENTURE MANUFACTURING (SINGAPORE) LTD. + +OUI:0050F8* + ID_OUI_FROM_DATABASE=ENTREGA TECHNOLOGIES, INC. + +OUI:0050F9* + ID_OUI_FROM_DATABASE=Sensormatic Electronics LLC + +OUI:0050FA* + ID_OUI_FROM_DATABASE=OXTEL, LTD. + +OUI:0050FB* + ID_OUI_FROM_DATABASE=VSK ELECTRONICS + +OUI:0050FC* + ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. + +OUI:0050FD* + ID_OUI_FROM_DATABASE=VISIONCOMM CO., LTD. + +OUI:0050FE* + ID_OUI_FROM_DATABASE=PCTVnet ASA + +OUI:0050FF* + ID_OUI_FROM_DATABASE=HAKKO ELECTRONICS CO., LTD. + +OUI:0051ED* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:005218* + ID_OUI_FROM_DATABASE=Wuxi Keboda Electron Co.Ltd + +OUI:0052C2* + ID_OUI_FROM_DATABASE=peiker acustic GmbH + +OUI:00549F* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:0054AF* + ID_OUI_FROM_DATABASE=Continental Automotive Systems Inc. + +OUI:0054BD* + ID_OUI_FROM_DATABASE=Swelaser AB + +OUI:0055DA0* + ID_OUI_FROM_DATABASE=Shinko Technos co.,ltd. + +OUI:0055DA1* + ID_OUI_FROM_DATABASE=KoolPOS Inc. + +OUI:0055DA2* + ID_OUI_FROM_DATABASE=Beijing Connected Information Technology Co.,Ltd. + +OUI:0055DA3* + ID_OUI_FROM_DATABASE=Novexx Solutions GmbH + +OUI:0055DA4* + ID_OUI_FROM_DATABASE=Datapath Limited + +OUI:0055DA5* + ID_OUI_FROM_DATABASE=Nanoleaf + +OUI:0055DA6* + ID_OUI_FROM_DATABASE=OOO DEKATRON + +OUI:0055DA7* + ID_OUI_FROM_DATABASE=LUCISTECHNOLOGIES(SHANGHAI)CO.,LTD + +OUI:0055DA8* + ID_OUI_FROM_DATABASE=BroadSoft, Inc. + +OUI:0055DA9* + ID_OUI_FROM_DATABASE=Quantum Communication Technology Co., Ltd.,Anhui + +OUI:0055DAA* + ID_OUI_FROM_DATABASE=Speechlab + +OUI:0055DAB* + ID_OUI_FROM_DATABASE=Interaxon Inc + +OUI:0055DAC* + ID_OUI_FROM_DATABASE=Donguan WideLink Communication Technology Co.,Ltd. + +OUI:0055DAD* + ID_OUI_FROM_DATABASE=Arrow Electronics,Inc. + +OUI:0055DAE* + ID_OUI_FROM_DATABASE=Victorsure Limited + +OUI:0055DAF* + ID_OUI_FROM_DATABASE=Private + +OUI:00562B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0056CD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0057C1* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:0057D2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00583F* + ID_OUI_FROM_DATABASE=PC Aquarius + +OUI:005907* + ID_OUI_FROM_DATABASE=LenovoEMC Products USA, LLC + +OUI:005979* + ID_OUI_FROM_DATABASE=Networked Energy Services + +OUI:0059AC* + ID_OUI_FROM_DATABASE=KPN. B.V. + +OUI:0059DC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:005A13* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:005A39* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:005B94* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:005BA1* + ID_OUI_FROM_DATABASE=shanghai huayuan chuangxin software CO., LTD. + +OUI:005C86* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:005CB1* + ID_OUI_FROM_DATABASE=Gospell DIGITAL TECHNOLOGY CO., LTD + +OUI:005D03* + ID_OUI_FROM_DATABASE=Xilinx, Inc + +OUI:005D73* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:005E0C* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:005F86* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:006000* + ID_OUI_FROM_DATABASE=XYCOM INC. + +OUI:006001* + ID_OUI_FROM_DATABASE=InnoSys, Inc. + +OUI:006002* + ID_OUI_FROM_DATABASE=SCREEN SUBTITLING SYSTEMS, LTD + +OUI:006003* + ID_OUI_FROM_DATABASE=TERAOKA WEIGH SYSTEM PTE, LTD. + +OUI:006004* + ID_OUI_FROM_DATABASE=COMPUTADORES MODULARES SA + +OUI:006005* + ID_OUI_FROM_DATABASE=FEEDBACK DATA LTD. + +OUI:006006* + ID_OUI_FROM_DATABASE=SOTEC CO., LTD + +OUI:006007* + ID_OUI_FROM_DATABASE=ACRES GAMING, INC. + +OUI:006008* + ID_OUI_FROM_DATABASE=3COM + +OUI:006009* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00600A* + ID_OUI_FROM_DATABASE=SORD COMPUTER CORPORATION + +OUI:00600B* + ID_OUI_FROM_DATABASE=LOGWARE GmbH + +OUI:00600C* + ID_OUI_FROM_DATABASE=Eurotech Inc. + +OUI:00600D* + ID_OUI_FROM_DATABASE=Digital Logic GmbH + +OUI:00600E* + ID_OUI_FROM_DATABASE=WAVENET INTERNATIONAL, INC. + +OUI:00600F* + ID_OUI_FROM_DATABASE=Westell Technologies Inc. + +OUI:006010* + ID_OUI_FROM_DATABASE=NETWORK MACHINES, INC. + +OUI:006011* + ID_OUI_FROM_DATABASE=CRYSTAL SEMICONDUCTOR CORP. + +OUI:006012* + ID_OUI_FROM_DATABASE=POWER COMPUTING CORPORATION + +OUI:006013* + ID_OUI_FROM_DATABASE=NETSTAL MASCHINEN AG + +OUI:006014* + ID_OUI_FROM_DATABASE=EDEC CO., LTD. + +OUI:006015* + ID_OUI_FROM_DATABASE=NET2NET CORPORATION + +OUI:006016* + ID_OUI_FROM_DATABASE=CLARIION + +OUI:006017* + ID_OUI_FROM_DATABASE=TOKIMEC INC. + +OUI:006018* + ID_OUI_FROM_DATABASE=STELLAR ONE CORPORATION + +OUI:006019* + ID_OUI_FROM_DATABASE=Roche Diagnostics + +OUI:00601A* + ID_OUI_FROM_DATABASE=KEITHLEY INSTRUMENTS + +OUI:00601B* + ID_OUI_FROM_DATABASE=MESA ELECTRONICS + +OUI:00601C* + ID_OUI_FROM_DATABASE=TELXON CORPORATION + +OUI:00601D* + ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES + +OUI:00601E* + ID_OUI_FROM_DATABASE=SOFTLAB, INC. + +OUI:00601F* + ID_OUI_FROM_DATABASE=STALLION TECHNOLOGIES + +OUI:006020* + ID_OUI_FROM_DATABASE=PIVOTAL NETWORKING, INC. + +OUI:006021* + ID_OUI_FROM_DATABASE=DSC CORPORATION + +OUI:006022* + ID_OUI_FROM_DATABASE=VICOM SYSTEMS, INC. + +OUI:006023* + ID_OUI_FROM_DATABASE=PERICOM SEMICONDUCTOR CORP. + +OUI:006024* + ID_OUI_FROM_DATABASE=GRADIENT TECHNOLOGIES, INC. + +OUI:006025* + ID_OUI_FROM_DATABASE=ACTIVE IMAGING PLC + +OUI:006026* + ID_OUI_FROM_DATABASE=VIKING Modular Solutions + +OUI:006027* + ID_OUI_FROM_DATABASE=Superior Modular Products + +OUI:006028* + ID_OUI_FROM_DATABASE=MACROVISION CORPORATION + +OUI:006029* + ID_OUI_FROM_DATABASE=CARY PERIPHERALS INC. + +OUI:00602A* + ID_OUI_FROM_DATABASE=SYMICRON COMPUTER COMMUNICATIONS, LTD. + +OUI:00602B* + ID_OUI_FROM_DATABASE=PEAK AUDIO + +OUI:00602C* + ID_OUI_FROM_DATABASE=LINX Data Terminals, Inc. + +OUI:00602D* + ID_OUI_FROM_DATABASE=ALERTON TECHNOLOGIES, INC. + +OUI:00602E* + ID_OUI_FROM_DATABASE=CYCLADES CORPORATION + +OUI:00602F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:006030* + ID_OUI_FROM_DATABASE=VILLAGE TRONIC ENTWICKLUNG + +OUI:006031* + ID_OUI_FROM_DATABASE=HRK SYSTEMS + +OUI:006032* + ID_OUI_FROM_DATABASE=I-CUBE, INC. + +OUI:006033* + ID_OUI_FROM_DATABASE=ACUITY IMAGING, INC. + +OUI:006034* + ID_OUI_FROM_DATABASE=ROBERT BOSCH GmbH + +OUI:006035* + ID_OUI_FROM_DATABASE=DALLAS SEMICONDUCTOR, INC. + +OUI:006036* + ID_OUI_FROM_DATABASE=AIT Austrian Institute of Technology GmbH + +OUI:006037* + ID_OUI_FROM_DATABASE=NXP Semiconductors + +OUI:006038* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:006039* + ID_OUI_FROM_DATABASE=SanCom Technology, Inc. + +OUI:00603A* + ID_OUI_FROM_DATABASE=QUICK CONTROLS LTD. + +OUI:00603B* + ID_OUI_FROM_DATABASE=AMTEC spa + +OUI:00603C* + ID_OUI_FROM_DATABASE=HAGIWARA SYS-COM CO., LTD. + +OUI:00603D* + ID_OUI_FROM_DATABASE=3CX + +OUI:00603E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00603F* + ID_OUI_FROM_DATABASE=PATAPSCO DESIGNS + +OUI:006040* + ID_OUI_FROM_DATABASE=NETRO CORP. + +OUI:006041* + ID_OUI_FROM_DATABASE=Yokogawa Digital Computer Corporation + +OUI:006042* + ID_OUI_FROM_DATABASE=TKS (USA), INC. + +OUI:006043* + ID_OUI_FROM_DATABASE=iDirect, INC. + +OUI:006044* + ID_OUI_FROM_DATABASE=LITTON/POLY-SCIENTIFIC + +OUI:006045* + ID_OUI_FROM_DATABASE=PATHLIGHT TECHNOLOGIES + +OUI:006046* + ID_OUI_FROM_DATABASE=VMETRO, INC. + +OUI:006047* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:006048* + ID_OUI_FROM_DATABASE=Dell EMC + +OUI:006049* + ID_OUI_FROM_DATABASE=VINA TECHNOLOGIES + +OUI:00604A* + ID_OUI_FROM_DATABASE=SAIC IDEAS GROUP + +OUI:00604B* + ID_OUI_FROM_DATABASE=Safe-com GmbH & Co. KG + +OUI:00604C* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:00604D* + ID_OUI_FROM_DATABASE=MMC NETWORKS, INC. + +OUI:00604E* + ID_OUI_FROM_DATABASE=CYCLE COMPUTER CORPORATION, INC. + +OUI:00604F* + ID_OUI_FROM_DATABASE=Tattile SRL + +OUI:006050* + ID_OUI_FROM_DATABASE=INTERNIX INC. + +OUI:006051* + ID_OUI_FROM_DATABASE=QUALITY SEMICONDUCTOR + +OUI:006052* + ID_OUI_FROM_DATABASE=PERIPHERALS ENTERPRISE CO., Ltd. + +OUI:006053* + ID_OUI_FROM_DATABASE=TOYODA MACHINE WORKS, LTD. + +OUI:006054* + ID_OUI_FROM_DATABASE=CONTROLWARE GMBH + +OUI:006055* + ID_OUI_FROM_DATABASE=CORNELL UNIVERSITY + +OUI:006056* + ID_OUI_FROM_DATABASE=NETWORK TOOLS, INC. + +OUI:006057* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:006058* + ID_OUI_FROM_DATABASE=COPPER MOUNTAIN COMMUNICATIONS, INC. + +OUI:006059* + ID_OUI_FROM_DATABASE=TECHNICAL COMMUNICATIONS CORP. + +OUI:00605A* + ID_OUI_FROM_DATABASE=CELCORE, INC. + +OUI:00605B* + ID_OUI_FROM_DATABASE=IntraServer Technology, Inc. + +OUI:00605C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00605D* + ID_OUI_FROM_DATABASE=SCANIVALVE CORP. + +OUI:00605E* + ID_OUI_FROM_DATABASE=LIBERTY TECHNOLOGY NETWORKING + +OUI:00605F* + ID_OUI_FROM_DATABASE=NIPPON UNISOFT CORPORATION + +OUI:006060* + ID_OUI_FROM_DATABASE=Data Innovations North America + +OUI:006061* + ID_OUI_FROM_DATABASE=WHISTLE COMMUNICATIONS CORP. + +OUI:006062* + ID_OUI_FROM_DATABASE=TELESYNC, INC. + +OUI:006063* + ID_OUI_FROM_DATABASE=PSION DACOM PLC. + +OUI:006064* + ID_OUI_FROM_DATABASE=NETCOMM LIMITED + +OUI:006065* + ID_OUI_FROM_DATABASE=BERNECKER & RAINER INDUSTRIE-ELEKTRONIC GmbH + +OUI:006066* + ID_OUI_FROM_DATABASE=LACROIX Trafic + +OUI:006067* + ID_OUI_FROM_DATABASE=ACER NETXUS INC. + +OUI:006068* + ID_OUI_FROM_DATABASE=Dialogic Corporation + +OUI:006069* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:00606A* + ID_OUI_FROM_DATABASE=MITSUBISHI WIRELESS COMMUNICATIONS. INC. + +OUI:00606B* + ID_OUI_FROM_DATABASE=Synclayer Inc. + +OUI:00606C* + ID_OUI_FROM_DATABASE=ARESCOM + +OUI:00606D* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORP. + +OUI:00606E* + ID_OUI_FROM_DATABASE=DAVICOM SEMICONDUCTOR, INC. + +OUI:00606F* + ID_OUI_FROM_DATABASE=CLARION CORPORATION OF AMERICA + +OUI:006070* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:006071* + ID_OUI_FROM_DATABASE=MIDAS LAB, INC. + +OUI:006072* + ID_OUI_FROM_DATABASE=VXL INSTRUMENTS, LIMITED + +OUI:006073* + ID_OUI_FROM_DATABASE=REDCREEK COMMUNICATIONS, INC. + +OUI:006074* + ID_OUI_FROM_DATABASE=QSC LLC + +OUI:006075* + ID_OUI_FROM_DATABASE=PENTEK, INC. + +OUI:006076* + ID_OUI_FROM_DATABASE=SCHLUMBERGER TECHNOLOGIES RETAIL PETROLEUM SYSTEMS + +OUI:006077* + ID_OUI_FROM_DATABASE=PRISA NETWORKS + +OUI:006078* + ID_OUI_FROM_DATABASE=POWER MEASUREMENT LTD. + +OUI:006079* + ID_OUI_FROM_DATABASE=Mainstream Data, Inc. + +OUI:00607A* + ID_OUI_FROM_DATABASE=DVS GMBH + +OUI:00607B* + ID_OUI_FROM_DATABASE=FORE SYSTEMS, INC. + +OUI:00607C* + ID_OUI_FROM_DATABASE=WaveAccess, Ltd. + +OUI:00607D* + ID_OUI_FROM_DATABASE=SENTIENT NETWORKS INC. + +OUI:00607E* + ID_OUI_FROM_DATABASE=GIGALABS, INC. + +OUI:00607F* + ID_OUI_FROM_DATABASE=AURORA TECHNOLOGIES, INC. + +OUI:006080* + ID_OUI_FROM_DATABASE=MICROTRONIX DATACOM LTD. + +OUI:006081* + ID_OUI_FROM_DATABASE=TV/COM INTERNATIONAL + +OUI:006082* + ID_OUI_FROM_DATABASE=NOVALINK TECHNOLOGIES, INC. + +OUI:006083* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:006084* + ID_OUI_FROM_DATABASE=DIGITAL VIDEO + +OUI:006085* + ID_OUI_FROM_DATABASE=Storage Concepts + +OUI:006086* + ID_OUI_FROM_DATABASE=LOGIC REPLACEMENT TECH. LTD. + +OUI:006087* + ID_OUI_FROM_DATABASE=KANSAI ELECTRIC CO., LTD. + +OUI:006088* + ID_OUI_FROM_DATABASE=Analog Devices, Inc. + +OUI:006089* + ID_OUI_FROM_DATABASE=XATA + +OUI:00608A* + ID_OUI_FROM_DATABASE=CITADEL COMPUTER + +OUI:00608B* + ID_OUI_FROM_DATABASE=ConferTech International + +OUI:00608C* + ID_OUI_FROM_DATABASE=3COM + +OUI:00608D* + ID_OUI_FROM_DATABASE=UNIPULSE CORP. + +OUI:00608E* + ID_OUI_FROM_DATABASE=HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH + +OUI:00608F* + ID_OUI_FROM_DATABASE=TEKRAM TECHNOLOGY CO., LTD. + +OUI:006090* + ID_OUI_FROM_DATABASE=Artiza Networks Inc + +OUI:006091* + ID_OUI_FROM_DATABASE=FIRST PACIFIC NETWORKS, INC. + +OUI:006092* + ID_OUI_FROM_DATABASE=MICRO/SYS, INC. + +OUI:006093* + ID_OUI_FROM_DATABASE=VARIAN + +OUI:006094* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:006095* + ID_OUI_FROM_DATABASE=ACCU-TIME SYSTEMS, INC. + +OUI:006096* + ID_OUI_FROM_DATABASE=T.S. MICROTECH INC. + +OUI:006097* + ID_OUI_FROM_DATABASE=3COM + +OUI:006098* + ID_OUI_FROM_DATABASE=HT COMMUNICATIONS + +OUI:006099* + ID_OUI_FROM_DATABASE=SBE, Inc. + +OUI:00609A* + ID_OUI_FROM_DATABASE=NJK TECHNO CO. + +OUI:00609B* + ID_OUI_FROM_DATABASE=AstroNova, Inc + +OUI:00609C* + ID_OUI_FROM_DATABASE=Perkin-Elmer Incorporated + +OUI:00609D* + ID_OUI_FROM_DATABASE=PMI FOOD EQUIPMENT GROUP + +OUI:00609E* + ID_OUI_FROM_DATABASE=ASC X3 - INFORMATION TECHNOLOGY STANDARDS SECRETARIATS + +OUI:00609F* + ID_OUI_FROM_DATABASE=PHAST CORPORATION + +OUI:0060A0* + ID_OUI_FROM_DATABASE=SWITCHED NETWORK TECHNOLOGIES, INC. + +OUI:0060A1* + ID_OUI_FROM_DATABASE=VPNet, Inc. + +OUI:0060A2* + ID_OUI_FROM_DATABASE=NIHON UNISYS LIMITED CO. + +OUI:0060A3* + ID_OUI_FROM_DATABASE=CONTINUUM TECHNOLOGY CORP. + +OUI:0060A4* + ID_OUI_FROM_DATABASE=GEW Technologies (PTY)Ltd + +OUI:0060A5* + ID_OUI_FROM_DATABASE=PERFORMANCE TELECOM CORP. + +OUI:0060A6* + ID_OUI_FROM_DATABASE=PARTICLE MEASURING SYSTEMS + +OUI:0060A7* + ID_OUI_FROM_DATABASE=MICROSENS GmbH & CO. KG + +OUI:0060A8* + ID_OUI_FROM_DATABASE=TIDOMAT AB + +OUI:0060A9* + ID_OUI_FROM_DATABASE=GESYTEC MBH + +OUI:0060AA* + ID_OUI_FROM_DATABASE=INTELLIGENT DEVICES INC. (IDI) + +OUI:0060AB* + ID_OUI_FROM_DATABASE=LARSCOM INCORPORATED + +OUI:0060AC* + ID_OUI_FROM_DATABASE=RESILIENCE CORPORATION + +OUI:0060AD* + ID_OUI_FROM_DATABASE=MegaChips Corporation + +OUI:0060AE* + ID_OUI_FROM_DATABASE=TRIO INFORMATION SYSTEMS AB + +OUI:0060AF* + ID_OUI_FROM_DATABASE=PACIFIC MICRO DATA, INC. + +OUI:0060B0* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0060B1* + ID_OUI_FROM_DATABASE=Input/Output, Inc. + +OUI:0060B2* + ID_OUI_FROM_DATABASE=PROCESS CONTROL CORP. + +OUI:0060B3* + ID_OUI_FROM_DATABASE=Z-COM, INC. + +OUI:0060B4* + ID_OUI_FROM_DATABASE=GLENAYRE R&D INC. + +OUI:0060B5* + ID_OUI_FROM_DATABASE=KEBA GmbH + +OUI:0060B6* + ID_OUI_FROM_DATABASE=LAND COMPUTER CO., LTD. + +OUI:0060B7* + ID_OUI_FROM_DATABASE=CHANNELMATIC, INC. + +OUI:0060B8* + ID_OUI_FROM_DATABASE=CORELIS Inc. + +OUI:0060B9* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd + +OUI:0060BA* + ID_OUI_FROM_DATABASE=SAHARA NETWORKS, INC. + +OUI:0060BB* + ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. + +OUI:0060BC* + ID_OUI_FROM_DATABASE=KeunYoung Electronics & Communication Co., Ltd. + +OUI:0060BD* + ID_OUI_FROM_DATABASE=Enginuity Communications + +OUI:0060BE* + ID_OUI_FROM_DATABASE=WEBTRONICS + +OUI:0060BF* + ID_OUI_FROM_DATABASE=MACRAIGOR SYSTEMS, INC. + +OUI:0060C0* + ID_OUI_FROM_DATABASE=Nera Networks AS + +OUI:0060C1* + ID_OUI_FROM_DATABASE=WaveSpan Corporation + +OUI:0060C2* + ID_OUI_FROM_DATABASE=MPL AG + +OUI:0060C3* + ID_OUI_FROM_DATABASE=NETVISION CORPORATION + +OUI:0060C4* + ID_OUI_FROM_DATABASE=SOLITON SYSTEMS K.K. + +OUI:0060C5* + ID_OUI_FROM_DATABASE=ANCOT CORP. + +OUI:0060C6* + ID_OUI_FROM_DATABASE=DCS AG + +OUI:0060C7* + ID_OUI_FROM_DATABASE=AMATI COMMUNICATIONS CORP. + +OUI:0060C8* + ID_OUI_FROM_DATABASE=KUKA WELDING SYSTEMS & ROBOTS + +OUI:0060C9* + ID_OUI_FROM_DATABASE=ControlNet, Inc. + +OUI:0060CA* + ID_OUI_FROM_DATABASE=HARMONIC SYSTEMS INCORPORATED + +OUI:0060CB* + ID_OUI_FROM_DATABASE=HITACHI ZOSEN CORPORATION + +OUI:0060CC* + ID_OUI_FROM_DATABASE=EMTRAK, INCORPORATED + +OUI:0060CD* + ID_OUI_FROM_DATABASE=VideoServer, Inc. + +OUI:0060CE* + ID_OUI_FROM_DATABASE=ACCLAIM COMMUNICATIONS + +OUI:0060CF* + ID_OUI_FROM_DATABASE=ALTEON NETWORKS, INC. + +OUI:0060D0* + ID_OUI_FROM_DATABASE=SNMP RESEARCH INCORPORATED + +OUI:0060D1* + ID_OUI_FROM_DATABASE=CASCADE COMMUNICATIONS + +OUI:0060D2* + ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES TAIWAN TELECOMMUNICATIONS CO., LTD. + +OUI:0060D3* + ID_OUI_FROM_DATABASE=AT&T + +OUI:0060D4* + ID_OUI_FROM_DATABASE=ELDAT COMMUNICATION LTD. + +OUI:0060D5* + ID_OUI_FROM_DATABASE=AMADA MIYACHI Co., Ltd + +OUI:0060D6* + ID_OUI_FROM_DATABASE=NovAtel Inc. + +OUI:0060D7* + ID_OUI_FROM_DATABASE=ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE (EPFL) + +OUI:0060D8* + ID_OUI_FROM_DATABASE=ELMIC SYSTEMS, INC. + +OUI:0060D9* + ID_OUI_FROM_DATABASE=TRANSYS NETWORKS INC. + +OUI:0060DA* + ID_OUI_FROM_DATABASE=Red Lion Controls, LP + +OUI:0060DB* + ID_OUI_FROM_DATABASE=NTP ELEKTRONIK A/S + +OUI:0060DC* + ID_OUI_FROM_DATABASE=NEC Magnus Communications,Ltd. + +OUI:0060DD* + ID_OUI_FROM_DATABASE=MYRICOM, INC. + +OUI:0060DE* + ID_OUI_FROM_DATABASE=Kayser-Threde GmbH + +OUI:0060DF* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:0060E0* + ID_OUI_FROM_DATABASE=AXIOM TECHNOLOGY CO., LTD. + +OUI:0060E1* + ID_OUI_FROM_DATABASE=ORCKIT COMMUNICATIONS LTD. + +OUI:0060E2* + ID_OUI_FROM_DATABASE=QUEST ENGINEERING & DEVELOPMENT + +OUI:0060E3* + ID_OUI_FROM_DATABASE=ARBIN INSTRUMENTS + +OUI:0060E4* + ID_OUI_FROM_DATABASE=COMPUSERVE, INC. + +OUI:0060E5* + ID_OUI_FROM_DATABASE=FUJI AUTOMATION CO., LTD. + +OUI:0060E6* + ID_OUI_FROM_DATABASE=SHOMITI SYSTEMS INCORPORATED + +OUI:0060E7* + ID_OUI_FROM_DATABASE=RANDATA + +OUI:0060E8* + ID_OUI_FROM_DATABASE=HITACHI COMPUTER PRODUCTS (AMERICA), INC. + +OUI:0060E9* + ID_OUI_FROM_DATABASE=ATOP TECHNOLOGIES, INC. + +OUI:0060EA* + ID_OUI_FROM_DATABASE=StreamLogic + +OUI:0060EB* + ID_OUI_FROM_DATABASE=FOURTHTRACK SYSTEMS + +OUI:0060EC* + ID_OUI_FROM_DATABASE=HERMARY OPTO ELECTRONICS INC. + +OUI:0060ED* + ID_OUI_FROM_DATABASE=RICARDO TEST AUTOMATION LTD. + +OUI:0060EE* + ID_OUI_FROM_DATABASE=APOLLO + +OUI:0060EF* + ID_OUI_FROM_DATABASE=FLYTECH TECHNOLOGY CO., LTD. + +OUI:0060F0* + ID_OUI_FROM_DATABASE=JOHNSON & JOHNSON MEDICAL, INC + +OUI:0060F1* + ID_OUI_FROM_DATABASE=EXP COMPUTER, INC. + +OUI:0060F2* + ID_OUI_FROM_DATABASE=LASERGRAPHICS, INC. + +OUI:0060F3* + ID_OUI_FROM_DATABASE=Performance Analysis Broadband, Spirent plc + +OUI:0060F4* + ID_OUI_FROM_DATABASE=ADVANCED COMPUTER SOLUTIONS, Inc. + +OUI:0060F5* + ID_OUI_FROM_DATABASE=ICON WEST, INC. + +OUI:0060F6* + ID_OUI_FROM_DATABASE=NEXTEST COMMUNICATIONS PRODUCTS, INC. + +OUI:0060F7* + ID_OUI_FROM_DATABASE=DATAFUSION SYSTEMS + +OUI:0060F8* + ID_OUI_FROM_DATABASE=Loran International Technologies Inc. + +OUI:0060F9* + ID_OUI_FROM_DATABASE=DIAMOND LANE COMMUNICATIONS + +OUI:0060FA* + ID_OUI_FROM_DATABASE=EDUCATIONAL TECHNOLOGY RESOURCES, INC. + +OUI:0060FB* + ID_OUI_FROM_DATABASE=PACKETEER, INC. + +OUI:0060FC* + ID_OUI_FROM_DATABASE=CONSERVATION THROUGH INNOVATION LTD. + +OUI:0060FD* + ID_OUI_FROM_DATABASE=NetICs, Inc. + +OUI:0060FE* + ID_OUI_FROM_DATABASE=LYNX SYSTEM DEVELOPERS, INC. + +OUI:0060FF* + ID_OUI_FROM_DATABASE=QuVis, Inc. + +OUI:006171* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0062EC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:006440* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0064A6* + ID_OUI_FROM_DATABASE=Maquet CardioVascular + +OUI:006619* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:00664B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:006762* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:0068EB* + ID_OUI_FROM_DATABASE=HP Inc. + +OUI:00692D* + ID_OUI_FROM_DATABASE=Sunnovo International Limited + +OUI:0069670* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:0069671* + ID_OUI_FROM_DATABASE=miliwave + +OUI:0069672* + ID_OUI_FROM_DATABASE=Ningbo Shen Link Communication Technology Co.,Ltd + +OUI:0069673* + ID_OUI_FROM_DATABASE=Suzhou Radiant Lighting Technology Co.,Ltd + +OUI:0069674* + ID_OUI_FROM_DATABASE=Command Alkon, Inc + +OUI:0069675* + ID_OUI_FROM_DATABASE=Shenzhen Xiao Bi En Culture Education Technology Co.,Ltd. + +OUI:0069676* + ID_OUI_FROM_DATABASE=Comcast-SRL + +OUI:0069677* + ID_OUI_FROM_DATABASE=PANGAEA SOLUTION INC + +OUI:0069678* + ID_OUI_FROM_DATABASE=Ambient-System sp. z o.o. + +OUI:0069679* + ID_OUI_FROM_DATABASE=Hangzhou Wise IOT Technology Co.,Ltd + +OUI:006967A* + ID_OUI_FROM_DATABASE=Zhejiang Holip Electronic Technology Co.,Ltd + +OUI:006967B* + ID_OUI_FROM_DATABASE=Datapan d.o.o. + +OUI:006967C* + ID_OUI_FROM_DATABASE=Desird Design R&D + +OUI:006967D* + ID_OUI_FROM_DATABASE=aversix + +OUI:006967E* + ID_OUI_FROM_DATABASE=Tianjin Lianwu Technology Co., Ltd. + +OUI:006B8E* + ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd. + +OUI:006B9E* + ID_OUI_FROM_DATABASE=Vizio, Inc + +OUI:006BA0* + ID_OUI_FROM_DATABASE=SHENZHEN UNIVERSAL INTELLISYS PTE LTD + +OUI:006BF1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:006CBC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:006CFD* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. + +OUI:006D52* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:006D61* + ID_OUI_FROM_DATABASE=Guangzhou V-SOLUTION Electronic Technology Co., Ltd. + +OUI:006DFB* + ID_OUI_FROM_DATABASE=Vutrix Technologies Ltd + +OUI:006F64* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:006FF2* + ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD. + +OUI:0070B0* + ID_OUI_FROM_DATABASE=M/A-COM INC. COMPANIES + +OUI:0070B3* + ID_OUI_FROM_DATABASE=DATA RECALL LTD. + +OUI:007147* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:0071C2* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:0071CC* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:007204* + ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. ARTIK + +OUI:007263* + ID_OUI_FROM_DATABASE=Netcore Technology Inc. + +OUI:007278* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00738D* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:0073E0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00749C* + ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD + +OUI:007532* + ID_OUI_FROM_DATABASE=INID BV + +OUI:0075E1* + ID_OUI_FROM_DATABASE=Ampt, LLC + +OUI:00763D* + ID_OUI_FROM_DATABASE=Veea + +OUI:007686* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0076B1* + ID_OUI_FROM_DATABASE=Somfy-Protect By Myfox SAS + +OUI:00778D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0077E4* + ID_OUI_FROM_DATABASE=Nokia + +OUI:007888* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00789E* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:0078CD* + ID_OUI_FROM_DATABASE=Ignition Design Labs + +OUI:007B18* + ID_OUI_FROM_DATABASE=SENTRY Co., LTD. + +OUI:007C2D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:007DFA* + ID_OUI_FROM_DATABASE=Volkswagen Group of America + +OUI:007E56* + ID_OUI_FROM_DATABASE=China Dragon Technology Limited + +OUI:007E95* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:007F28* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:008000* + ID_OUI_FROM_DATABASE=MULTITECH SYSTEMS, INC. + +OUI:008001* + ID_OUI_FROM_DATABASE=PERIPHONICS CORPORATION + +OUI:008002* + ID_OUI_FROM_DATABASE=SATELCOM (UK) LTD + +OUI:008003* + ID_OUI_FROM_DATABASE=HYTEC ELECTRONICS LTD. + +OUI:008004* + ID_OUI_FROM_DATABASE=ANTLOW COMMUNICATIONS, LTD. + +OUI:008005* + ID_OUI_FROM_DATABASE=CACTUS COMPUTER INC. + +OUI:008006* + ID_OUI_FROM_DATABASE=COMPUADD CORPORATION + +OUI:008007* + ID_OUI_FROM_DATABASE=DLOG NC-SYSTEME + +OUI:008008* + ID_OUI_FROM_DATABASE=DYNATECH COMPUTER SYSTEMS + +OUI:008009* + ID_OUI_FROM_DATABASE=JUPITER SYSTEMS, INC. + +OUI:00800A* + ID_OUI_FROM_DATABASE=JAPAN COMPUTER CORP. + +OUI:00800B* + ID_OUI_FROM_DATABASE=CSK CORPORATION + +OUI:00800C* + ID_OUI_FROM_DATABASE=VIDECOM LIMITED + +OUI:00800D* + ID_OUI_FROM_DATABASE=VOSSWINKEL F.U. + +OUI:00800E* + ID_OUI_FROM_DATABASE=ATLANTIX CORPORATION + +OUI:00800F* + ID_OUI_FROM_DATABASE=STANDARD MICROSYSTEMS + +OUI:008010* + ID_OUI_FROM_DATABASE=COMMODORE INTERNATIONAL + +OUI:008011* + ID_OUI_FROM_DATABASE=DIGITAL SYSTEMS INT'L. INC. + +OUI:008012* + ID_OUI_FROM_DATABASE=INTEGRATED MEASUREMENT SYSTEMS + +OUI:008013* + ID_OUI_FROM_DATABASE=THOMAS-CONRAD CORPORATION + +OUI:008014* + ID_OUI_FROM_DATABASE=ESPRIT SYSTEMS + +OUI:008015* + ID_OUI_FROM_DATABASE=SEIKO SYSTEMS, INC. + +OUI:008016* + ID_OUI_FROM_DATABASE=WANDEL AND GOLTERMANN + +OUI:008017* + ID_OUI_FROM_DATABASE=PFU LIMITED + +OUI:008018* + ID_OUI_FROM_DATABASE=KOBE STEEL, LTD. + +OUI:008019* + ID_OUI_FROM_DATABASE=DAYNA COMMUNICATIONS, INC. + +OUI:00801A* + ID_OUI_FROM_DATABASE=BELL ATLANTIC + +OUI:00801B* + ID_OUI_FROM_DATABASE=KODIAK TECHNOLOGY + +OUI:00801C* + ID_OUI_FROM_DATABASE=NEWPORT SYSTEMS SOLUTIONS + +OUI:00801D* + ID_OUI_FROM_DATABASE=INTEGRATED INFERENCE MACHINES + +OUI:00801E* + ID_OUI_FROM_DATABASE=XINETRON, INC. + +OUI:00801F* + ID_OUI_FROM_DATABASE=KRUPP ATLAS ELECTRONIK GMBH + +OUI:008020* + ID_OUI_FROM_DATABASE=NETWORK PRODUCTS + +OUI:008021* + ID_OUI_FROM_DATABASE=Alcatel Canada Inc. + +OUI:008022* + ID_OUI_FROM_DATABASE=SCAN-OPTICS + +OUI:008023* + ID_OUI_FROM_DATABASE=INTEGRATED BUSINESS NETWORKS + +OUI:008024* + ID_OUI_FROM_DATABASE=KALPANA, INC. + +OUI:008025* + ID_OUI_FROM_DATABASE=Telit Wireless Solutions GmbH + +OUI:008026* + ID_OUI_FROM_DATABASE=NETWORK PRODUCTS CORPORATION + +OUI:008027* + ID_OUI_FROM_DATABASE=ADAPTIVE SYSTEMS, INC. + +OUI:008028* + ID_OUI_FROM_DATABASE=TRADPOST (HK) LTD + +OUI:008029* + ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGY, INC. + +OUI:00802A* + ID_OUI_FROM_DATABASE=TEST SYSTEMS & SIMULATIONS INC + +OUI:00802B* + ID_OUI_FROM_DATABASE=INTEGRATED MARKETING CO + +OUI:00802C* + ID_OUI_FROM_DATABASE=THE SAGE GROUP PLC + +OUI:00802D* + ID_OUI_FROM_DATABASE=XYLOGICS INC + +OUI:00802E* + ID_OUI_FROM_DATABASE=CASTLE ROCK COMPUTING + +OUI:00802F* + ID_OUI_FROM_DATABASE=NATIONAL INSTRUMENTS CORP. + +OUI:008030* + ID_OUI_FROM_DATABASE=NEXUS ELECTRONICS + +OUI:008031* + ID_OUI_FROM_DATABASE=BASYS, CORP. + +OUI:008032* + ID_OUI_FROM_DATABASE=ACCESS CO., LTD. + +OUI:008033* + ID_OUI_FROM_DATABASE=EMS Aviation, Inc. + +OUI:008034* + ID_OUI_FROM_DATABASE=SMT GOUPIL + +OUI:008035* + ID_OUI_FROM_DATABASE=TECHNOLOGY WORKS, INC. + +OUI:008036* + ID_OUI_FROM_DATABASE=REFLEX MANUFACTURING SYSTEMS + +OUI:008037* + ID_OUI_FROM_DATABASE=Ericsson Group + +OUI:008038* + ID_OUI_FROM_DATABASE=DATA RESEARCH & APPLICATIONS + +OUI:008039* + ID_OUI_FROM_DATABASE=ALCATEL STC AUSTRALIA + +OUI:00803A* + ID_OUI_FROM_DATABASE=VARITYPER, INC. + +OUI:00803B* + ID_OUI_FROM_DATABASE=APT COMMUNICATIONS, INC. + +OUI:00803C* + ID_OUI_FROM_DATABASE=TVS ELECTRONICS LTD + +OUI:00803D* + ID_OUI_FROM_DATABASE=SURIGIKEN CO., LTD. + +OUI:00803E* + ID_OUI_FROM_DATABASE=SYNERNETICS + +OUI:00803F* + ID_OUI_FROM_DATABASE=TATUNG COMPANY + +OUI:008040* + ID_OUI_FROM_DATABASE=JOHN FLUKE MANUFACTURING CO. + +OUI:008041* + ID_OUI_FROM_DATABASE=VEB KOMBINAT ROBOTRON + +OUI:008042* + ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies + +OUI:008043* + ID_OUI_FROM_DATABASE=NETWORLD, INC. + +OUI:008044* + ID_OUI_FROM_DATABASE=SYSTECH COMPUTER CORP. + +OUI:008045* + ID_OUI_FROM_DATABASE=MATSUSHITA ELECTRIC IND. CO + +OUI:008046* + ID_OUI_FROM_DATABASE=Tattile SRL + +OUI:008047* + ID_OUI_FROM_DATABASE=IN-NET CORP. + +OUI:008048* + ID_OUI_FROM_DATABASE=COMPEX INCORPORATED + +OUI:008049* + ID_OUI_FROM_DATABASE=NISSIN ELECTRIC CO., LTD. + +OUI:00804A* + ID_OUI_FROM_DATABASE=PRO-LOG + +OUI:00804B* + ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGIES PTY.LTD. + +OUI:00804C* + ID_OUI_FROM_DATABASE=CONTEC CO., LTD. + +OUI:00804D* + ID_OUI_FROM_DATABASE=CYCLONE MICROSYSTEMS, INC. + +OUI:00804E* + ID_OUI_FROM_DATABASE=APEX COMPUTER COMPANY + +OUI:00804F* + ID_OUI_FROM_DATABASE=DAIKIN INDUSTRIES, LTD. + +OUI:008050* + ID_OUI_FROM_DATABASE=ZIATECH CORPORATION + +OUI:008051* + ID_OUI_FROM_DATABASE=FIBERMUX + +OUI:008052* + ID_OUI_FROM_DATABASE=TECHNICALLY ELITE CONCEPTS + +OUI:008053* + ID_OUI_FROM_DATABASE=INTELLICOM, INC. + +OUI:008054* + ID_OUI_FROM_DATABASE=FRONTIER TECHNOLOGIES CORP. + +OUI:008055* + ID_OUI_FROM_DATABASE=FERMILAB + +OUI:008056* + ID_OUI_FROM_DATABASE=SPHINX Electronics GmbH & Co KG + +OUI:008057* + ID_OUI_FROM_DATABASE=ADSOFT, LTD. + +OUI:008058* + ID_OUI_FROM_DATABASE=PRINTER SYSTEMS CORP. + +OUI:008059* + ID_OUI_FROM_DATABASE=STANLEY ELECTRIC CO., LTD + +OUI:00805A* + ID_OUI_FROM_DATABASE=TULIP COMPUTERS INTERNAT'L B.V + +OUI:00805B* + ID_OUI_FROM_DATABASE=CONDOR SYSTEMS, INC. + +OUI:00805C* + ID_OUI_FROM_DATABASE=AGILIS CORPORATION + +OUI:00805D* + ID_OUI_FROM_DATABASE=CANSTAR + +OUI:00805E* + ID_OUI_FROM_DATABASE=LSI LOGIC CORPORATION + +OUI:00805F* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:008060* + ID_OUI_FROM_DATABASE=NETWORK INTERFACE CORPORATION + +OUI:008061* + ID_OUI_FROM_DATABASE=LITTON SYSTEMS, INC. + +OUI:008062* + ID_OUI_FROM_DATABASE=INTERFACE CO. + +OUI:008063* + ID_OUI_FROM_DATABASE=Hirschmann Automation and Control GmbH + +OUI:008064* + ID_OUI_FROM_DATABASE=WYSE TECHNOLOGY LLC + +OUI:008065* + ID_OUI_FROM_DATABASE=CYBERGRAPHIC SYSTEMS PTY LTD. + +OUI:008066* + ID_OUI_FROM_DATABASE=ARCOM CONTROL SYSTEMS, LTD. + +OUI:008067* + ID_OUI_FROM_DATABASE=SQUARE D COMPANY + +OUI:008068* + ID_OUI_FROM_DATABASE=YAMATECH SCIENTIFIC LTD. + +OUI:008069* + ID_OUI_FROM_DATABASE=COMPUTONE SYSTEMS + +OUI:00806A* + ID_OUI_FROM_DATABASE=ERI (EMPAC RESEARCH INC.) + +OUI:00806B* + ID_OUI_FROM_DATABASE=SCHMID TELECOMMUNICATION + +OUI:00806C* + ID_OUI_FROM_DATABASE=Secure Systems & Services + +OUI:00806D* + ID_OUI_FROM_DATABASE=CENTURY SYSTEMS CORP. + +OUI:00806E* + ID_OUI_FROM_DATABASE=NIPPON STEEL CORPORATION + +OUI:00806F* + ID_OUI_FROM_DATABASE=ONELAN LTD. + +OUI:008070* + ID_OUI_FROM_DATABASE=COMPUTADORAS MICRON + +OUI:008071* + ID_OUI_FROM_DATABASE=SAI TECHNOLOGY + +OUI:008072* + ID_OUI_FROM_DATABASE=MICROPLEX SYSTEMS LTD. + +OUI:008073* + ID_OUI_FROM_DATABASE=DWB ASSOCIATES + +OUI:008074* + ID_OUI_FROM_DATABASE=FISHER CONTROLS + +OUI:008075* + ID_OUI_FROM_DATABASE=PARSYTEC GMBH + +OUI:008076* + ID_OUI_FROM_DATABASE=MCNC + +OUI:008077* + ID_OUI_FROM_DATABASE=Brother industries, LTD. + +OUI:008078* + ID_OUI_FROM_DATABASE=PRACTICAL PERIPHERALS, INC. + +OUI:008079* + ID_OUI_FROM_DATABASE=MICROBUS DESIGNS LTD. + +OUI:00807A* + ID_OUI_FROM_DATABASE=AITECH SYSTEMS LTD. + +OUI:00807B* + ID_OUI_FROM_DATABASE=ARTEL COMMUNICATIONS CORP. + +OUI:00807C* + ID_OUI_FROM_DATABASE=FIBERCOM, INC. + +OUI:00807D* + ID_OUI_FROM_DATABASE=EQUINOX SYSTEMS INC. + +OUI:00807E* + ID_OUI_FROM_DATABASE=SOUTHERN PACIFIC LTD. + +OUI:00807F* + ID_OUI_FROM_DATABASE=DY-4 INCORPORATED + +OUI:008080* + ID_OUI_FROM_DATABASE=DATAMEDIA CORPORATION + +OUI:008081* + ID_OUI_FROM_DATABASE=KENDALL SQUARE RESEARCH CORP. + +OUI:008082* + ID_OUI_FROM_DATABASE=PEP MODULAR COMPUTERS GMBH + +OUI:008083* + ID_OUI_FROM_DATABASE=AMDAHL + +OUI:008084* + ID_OUI_FROM_DATABASE=THE CLOUD INC. + +OUI:008085* + ID_OUI_FROM_DATABASE=H-THREE SYSTEMS CORPORATION + +OUI:008086* + ID_OUI_FROM_DATABASE=COMPUTER GENERATION INC. + +OUI:008087* + ID_OUI_FROM_DATABASE=OKI ELECTRIC INDUSTRY CO., LTD + +OUI:008088* + ID_OUI_FROM_DATABASE=VICTOR COMPANY OF JAPAN, LTD. + +OUI:008089* + ID_OUI_FROM_DATABASE=TECNETICS (PTY) LTD. + +OUI:00808A* + ID_OUI_FROM_DATABASE=SUMMIT MICROSYSTEMS CORP. + +OUI:00808B* + ID_OUI_FROM_DATABASE=DACOLL LIMITED + +OUI:00808C* + ID_OUI_FROM_DATABASE=NetAlly + +OUI:00808D* + ID_OUI_FROM_DATABASE=WESTCOAST TECHNOLOGY B.V. + +OUI:00808E* + ID_OUI_FROM_DATABASE=RADSTONE TECHNOLOGY + +OUI:00808F* + ID_OUI_FROM_DATABASE=C. ITOH ELECTRONICS, INC. + +OUI:008090* + ID_OUI_FROM_DATABASE=MICROTEK INTERNATIONAL, INC. + +OUI:008091* + ID_OUI_FROM_DATABASE=TOKYO ELECTRIC CO.,LTD + +OUI:008092* + ID_OUI_FROM_DATABASE=Silex Technology, Inc. + +OUI:008093* + ID_OUI_FROM_DATABASE=XYRON CORPORATION + +OUI:008094* + ID_OUI_FROM_DATABASE=ALFA LAVAL AUTOMATION AB + +OUI:008095* + ID_OUI_FROM_DATABASE=BASIC MERTON HANDELSGES.M.B.H. + +OUI:008096* + ID_OUI_FROM_DATABASE=HUMAN DESIGNED SYSTEMS, INC. + +OUI:008097* + ID_OUI_FROM_DATABASE=CENTRALP AUTOMATISMES + +OUI:008098* + ID_OUI_FROM_DATABASE=TDK CORPORATION + +OUI:008099* + ID_OUI_FROM_DATABASE=Eaton Industries GmbH + +OUI:00809A* + ID_OUI_FROM_DATABASE=NOVUS NETWORKS LTD + +OUI:00809B* + ID_OUI_FROM_DATABASE=JUSTSYSTEM CORPORATION + +OUI:00809C* + ID_OUI_FROM_DATABASE=LUXCOM, INC. + +OUI:00809D* + ID_OUI_FROM_DATABASE=Commscraft Ltd. + +OUI:00809E* + ID_OUI_FROM_DATABASE=DATUS GMBH + +OUI:00809F* + ID_OUI_FROM_DATABASE=ALE International + +OUI:0080A0* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:0080A1* + ID_OUI_FROM_DATABASE=MICROTEST, INC. + +OUI:0080A2* + ID_OUI_FROM_DATABASE=CREATIVE ELECTRONIC SYSTEMS + +OUI:0080A3* + ID_OUI_FROM_DATABASE=Lantronix + +OUI:0080A4* + ID_OUI_FROM_DATABASE=LIBERTY ELECTRONICS + +OUI:0080A5* + ID_OUI_FROM_DATABASE=SPEED INTERNATIONAL + +OUI:0080A6* + ID_OUI_FROM_DATABASE=REPUBLIC TECHNOLOGY, INC. + +OUI:0080A7* + ID_OUI_FROM_DATABASE=Honeywell International Inc + +OUI:0080A8* + ID_OUI_FROM_DATABASE=VITACOM CORPORATION + +OUI:0080A9* + ID_OUI_FROM_DATABASE=CLEARPOINT RESEARCH + +OUI:0080AA* + ID_OUI_FROM_DATABASE=MAXPEED + +OUI:0080AB* + ID_OUI_FROM_DATABASE=DUKANE NETWORK INTEGRATION + +OUI:0080AC* + ID_OUI_FROM_DATABASE=IMLOGIX, DIVISION OF GENESYS + +OUI:0080AD* + ID_OUI_FROM_DATABASE=CNET TECHNOLOGY, INC. + +OUI:0080AE* + ID_OUI_FROM_DATABASE=HUGHES NETWORK SYSTEMS + +OUI:0080AF* + ID_OUI_FROM_DATABASE=ALLUMER CO., LTD. + +OUI:0080B0* + ID_OUI_FROM_DATABASE=ADVANCED INFORMATION + +OUI:0080B1* + ID_OUI_FROM_DATABASE=SOFTCOM A/S + +OUI:0080B2* + ID_OUI_FROM_DATABASE=NETWORK EQUIPMENT TECHNOLOGIES + +OUI:0080B3* + ID_OUI_FROM_DATABASE=AVAL DATA CORPORATION + +OUI:0080B4* + ID_OUI_FROM_DATABASE=SOPHIA SYSTEMS + +OUI:0080B5* + ID_OUI_FROM_DATABASE=UNITED NETWORKS INC. + +OUI:0080B6* + ID_OUI_FROM_DATABASE=Mercury Systems – Trusted Mission Solutions, Inc. + +OUI:0080B7* + ID_OUI_FROM_DATABASE=STELLAR COMPUTER + +OUI:0080B8* + ID_OUI_FROM_DATABASE=DMG MORI B.U.G. CO., LTD. + +OUI:0080B9* + ID_OUI_FROM_DATABASE=ARCHE TECHNOLIGIES INC. + +OUI:0080BA* + ID_OUI_FROM_DATABASE=SPECIALIX (ASIA) PTE, LTD + +OUI:0080BB* + ID_OUI_FROM_DATABASE=HUGHES LAN SYSTEMS + +OUI:0080BC* + ID_OUI_FROM_DATABASE=HITACHI ENGINEERING CO., LTD + +OUI:0080BD* + ID_OUI_FROM_DATABASE=THE FURUKAWA ELECTRIC CO., LTD + +OUI:0080BE* + ID_OUI_FROM_DATABASE=ARIES RESEARCH + +OUI:0080BF* + ID_OUI_FROM_DATABASE=TAKAOKA ELECTRIC MFG. CO. LTD. + +OUI:0080C0* + ID_OUI_FROM_DATABASE=PENRIL DATACOMM + +OUI:0080C1* + ID_OUI_FROM_DATABASE=LANEX CORPORATION + +OUI:0080C2* + ID_OUI_FROM_DATABASE=IEEE 802.1 Working Group + +OUI:0080C3* + ID_OUI_FROM_DATABASE=BICC INFORMATION SYSTEMS & SVC + +OUI:0080C4* + ID_OUI_FROM_DATABASE=DOCUMENT TECHNOLOGIES, INC. + +OUI:0080C5* + ID_OUI_FROM_DATABASE=NOVELLCO DE MEXICO + +OUI:0080C6* + ID_OUI_FROM_DATABASE=NATIONAL DATACOMM CORPORATION + +OUI:0080C7* + ID_OUI_FROM_DATABASE=XIRCOM + +OUI:0080C8* + ID_OUI_FROM_DATABASE=D-LINK SYSTEMS, INC. + +OUI:0080C9* + ID_OUI_FROM_DATABASE=ALBERTA MICROELECTRONIC CENTRE + +OUI:0080CA* + ID_OUI_FROM_DATABASE=NETCOM RESEARCH INCORPORATED + +OUI:0080CB* + ID_OUI_FROM_DATABASE=FALCO DATA PRODUCTS + +OUI:0080CC* + ID_OUI_FROM_DATABASE=MICROWAVE BYPASS SYSTEMS + +OUI:0080CD* + ID_OUI_FROM_DATABASE=MICRONICS COMPUTER, INC. + +OUI:0080CE* + ID_OUI_FROM_DATABASE=BROADCAST TELEVISION SYSTEMS + +OUI:0080CF* + ID_OUI_FROM_DATABASE=EMBEDDED PERFORMANCE INC. + +OUI:0080D0* + ID_OUI_FROM_DATABASE=COMPUTER PERIPHERALS, INC. + +OUI:0080D1* + ID_OUI_FROM_DATABASE=KIMTRON CORPORATION + +OUI:0080D2* + ID_OUI_FROM_DATABASE=SHINNIHONDENKO CO., LTD. + +OUI:0080D3* + ID_OUI_FROM_DATABASE=SHIVA CORP. + +OUI:0080D4* + ID_OUI_FROM_DATABASE=CHASE RESEARCH LTD. + +OUI:0080D5* + ID_OUI_FROM_DATABASE=CADRE TECHNOLOGIES + +OUI:0080D6* + ID_OUI_FROM_DATABASE=NUVOTECH, INC. + +OUI:0080D7* + ID_OUI_FROM_DATABASE=Fantum Engineering + +OUI:0080D8* + ID_OUI_FROM_DATABASE=NETWORK PERIPHERALS INC. + +OUI:0080D9* + ID_OUI_FROM_DATABASE=EMK Elektronik GmbH & Co. KG + +OUI:0080DA* + ID_OUI_FROM_DATABASE=Bruel & Kjaer Sound & Vibration Measurement A/S + +OUI:0080DB* + ID_OUI_FROM_DATABASE=GRAPHON CORPORATION + +OUI:0080DC* + ID_OUI_FROM_DATABASE=PICKER INTERNATIONAL + +OUI:0080DD* + ID_OUI_FROM_DATABASE=GMX INC/GIMIX + +OUI:0080DE* + ID_OUI_FROM_DATABASE=GIPSI S.A. + +OUI:0080DF* + ID_OUI_FROM_DATABASE=ADC CODENOLL TECHNOLOGY CORP. + +OUI:0080E0* + ID_OUI_FROM_DATABASE=XTP SYSTEMS, INC. + +OUI:0080E1* + ID_OUI_FROM_DATABASE=STMicroelectronics SRL + +OUI:0080E2* + ID_OUI_FROM_DATABASE=T.D.I. CO., LTD. + +OUI:0080E3* + ID_OUI_FROM_DATABASE=CORAL NETWORK CORPORATION + +OUI:0080E4* + ID_OUI_FROM_DATABASE=NORTHWEST DIGITAL SYSTEMS, INC + +OUI:0080E5* + ID_OUI_FROM_DATABASE=NetApp + +OUI:0080E6* + ID_OUI_FROM_DATABASE=PEER NETWORKS, INC. + +OUI:0080E7* + ID_OUI_FROM_DATABASE=Leonardo Tactical Systems. + +OUI:0080E8* + ID_OUI_FROM_DATABASE=CUMULUS CORPORATIION + +OUI:0080E9* + ID_OUI_FROM_DATABASE=Madge Ltd. + +OUI:0080EA* + ID_OUI_FROM_DATABASE=ADVA Optical Networking Ltd. + +OUI:0080EB* + ID_OUI_FROM_DATABASE=COMPCONTROL B.V. + +OUI:0080EC* + ID_OUI_FROM_DATABASE=SUPERCOMPUTING SOLUTIONS, INC. + +OUI:0080ED* + ID_OUI_FROM_DATABASE=IQ TECHNOLOGIES, INC. + +OUI:0080EE* + ID_OUI_FROM_DATABASE=THOMSON CSF + +OUI:0080EF* + ID_OUI_FROM_DATABASE=RATIONAL + +OUI:0080F0* + ID_OUI_FROM_DATABASE=Panasonic Communications Co., Ltd. + +OUI:0080F1* + ID_OUI_FROM_DATABASE=OPUS SYSTEMS + +OUI:0080F2* + ID_OUI_FROM_DATABASE=RAYCOM SYSTEMS INC + +OUI:0080F3* + ID_OUI_FROM_DATABASE=SUN ELECTRONICS CORP. + +OUI:0080F4* + ID_OUI_FROM_DATABASE=TELEMECANIQUE ELECTRIQUE + +OUI:0080F5* + ID_OUI_FROM_DATABASE=Quantel Ltd + +OUI:0080F6* + ID_OUI_FROM_DATABASE=SYNERGY MICROSYSTEMS + +OUI:0080F7* + ID_OUI_FROM_DATABASE=Zenith Electronics Corporation + +OUI:0080F8* + ID_OUI_FROM_DATABASE=MIZAR, INC. + +OUI:0080F9* + ID_OUI_FROM_DATABASE=HEURIKON CORPORATION + +OUI:0080FA* + ID_OUI_FROM_DATABASE=RWT GMBH + +OUI:0080FB* + ID_OUI_FROM_DATABASE=BVM LIMITED + +OUI:0080FC* + ID_OUI_FROM_DATABASE=AVATAR CORPORATION + +OUI:0080FD* + ID_OUI_FROM_DATABASE=EXSCEED CORPRATION + +OUI:0080FE* + ID_OUI_FROM_DATABASE=AZURE TECHNOLOGIES, INC. + +OUI:0080FF* + ID_OUI_FROM_DATABASE=SOC. DE TELEINFORMATIQUE RTC + +OUI:0081C4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0081F9* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0084ED* + ID_OUI_FROM_DATABASE=Private + +OUI:00869C* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:0086A0* + ID_OUI_FROM_DATABASE=Private + +OUI:008701* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:008731* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:008764* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:008865* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0088BA* + ID_OUI_FROM_DATABASE=NC&C + +OUI:008A96* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:008B43* + ID_OUI_FROM_DATABASE=RFTECH + +OUI:008BFC* + ID_OUI_FROM_DATABASE=mixi,Inc. + +OUI:008C10* + ID_OUI_FROM_DATABASE=Black Box Corp. + +OUI:008C54* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:008CFA* + ID_OUI_FROM_DATABASE=INVENTEC CORPORATION + +OUI:008D4E* + ID_OUI_FROM_DATABASE=CJSC NII STT + +OUI:008DDA* + ID_OUI_FROM_DATABASE=Link One Co., Ltd. + +OUI:008E73* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:008EF2* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:009000* + ID_OUI_FROM_DATABASE=DIAMOND MULTIMEDIA + +OUI:009001* + ID_OUI_FROM_DATABASE=NISHIMU ELECTRONICS INDUSTRIES CO., LTD. + +OUI:009002* + ID_OUI_FROM_DATABASE=ALLGON AB + +OUI:009003* + ID_OUI_FROM_DATABASE=APLIO + +OUI:009004* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:009005* + ID_OUI_FROM_DATABASE=PROTECH SYSTEMS CO., LTD. + +OUI:009006* + ID_OUI_FROM_DATABASE=Hamamatsu Photonics K.K. + +OUI:009007* + ID_OUI_FROM_DATABASE=DOMEX TECHNOLOGY CORP. + +OUI:009008* + ID_OUI_FROM_DATABASE=HanA Systems Inc. + +OUI:009009* + ID_OUI_FROM_DATABASE=I Controls, Inc. + +OUI:00900A* + ID_OUI_FROM_DATABASE=PROTON ELECTRONIC INDUSTRIAL CO., LTD. + +OUI:00900B* + ID_OUI_FROM_DATABASE=LANNER ELECTRONICS, INC. + +OUI:00900C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00900D* + ID_OUI_FROM_DATABASE=Overland Storage Inc. + +OUI:00900E* + ID_OUI_FROM_DATABASE=HANDLINK TECHNOLOGIES, INC. + +OUI:00900F* + ID_OUI_FROM_DATABASE=KAWASAKI HEAVY INDUSTRIES, LTD + +OUI:009010* + ID_OUI_FROM_DATABASE=SIMULATION LABORATORIES, INC. + +OUI:009011* + ID_OUI_FROM_DATABASE=WAVTrace, Inc. + +OUI:009012* + ID_OUI_FROM_DATABASE=GLOBESPAN SEMICONDUCTOR, INC. + +OUI:009013* + ID_OUI_FROM_DATABASE=SAMSAN CORP. + +OUI:009014* + ID_OUI_FROM_DATABASE=ROTORK INSTRUMENTS, LTD. + +OUI:009015* + ID_OUI_FROM_DATABASE=CENTIGRAM COMMUNICATIONS CORP. + +OUI:009016* + ID_OUI_FROM_DATABASE=ZAC + +OUI:009017* + ID_OUI_FROM_DATABASE=Zypcom, Inc + +OUI:009018* + ID_OUI_FROM_DATABASE=ITO ELECTRIC INDUSTRY CO, LTD. + +OUI:009019* + ID_OUI_FROM_DATABASE=HERMES ELECTRONICS CO., LTD. + +OUI:00901A* + ID_OUI_FROM_DATABASE=UNISPHERE SOLUTIONS + +OUI:00901B* + ID_OUI_FROM_DATABASE=DIGITAL CONTROLS + +OUI:00901C* + ID_OUI_FROM_DATABASE=mps Software Gmbh + +OUI:00901D* + ID_OUI_FROM_DATABASE=PEC (NZ) LTD. + +OUI:00901E* + ID_OUI_FROM_DATABASE=Selesta Ingegneria S.p.A. + +OUI:00901F* + ID_OUI_FROM_DATABASE=ADTEC PRODUCTIONS, INC. + +OUI:009020* + ID_OUI_FROM_DATABASE=PHILIPS ANALYTICAL X-RAY B.V. + +OUI:009021* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:009022* + ID_OUI_FROM_DATABASE=IVEX + +OUI:009023* + ID_OUI_FROM_DATABASE=ZILOG INC. + +OUI:009024* + ID_OUI_FROM_DATABASE=PIPELINKS, INC. + +OUI:009025* + ID_OUI_FROM_DATABASE=BAE Systems Australia (Electronic Systems) Pty Ltd + +OUI:009026* + ID_OUI_FROM_DATABASE=ADVANCED SWITCHING COMMUNICATIONS, INC. + +OUI:009027* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:009028* + ID_OUI_FROM_DATABASE=NIPPON SIGNAL CO., LTD. + +OUI:009029* + ID_OUI_FROM_DATABASE=CRYPTO AG + +OUI:00902A* + ID_OUI_FROM_DATABASE=COMMUNICATION DEVICES, INC. + +OUI:00902B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00902C* + ID_OUI_FROM_DATABASE=DATA & CONTROL EQUIPMENT LTD. + +OUI:00902D* + ID_OUI_FROM_DATABASE=DATA ELECTRONICS (AUST.) PTY, LTD. + +OUI:00902E* + ID_OUI_FROM_DATABASE=NAMCO LIMITED + +OUI:00902F* + ID_OUI_FROM_DATABASE=NETCORE SYSTEMS, INC. + +OUI:009030* + ID_OUI_FROM_DATABASE=HONEYWELL-DATING + +OUI:009031* + ID_OUI_FROM_DATABASE=MYSTICOM, LTD. + +OUI:009032* + ID_OUI_FROM_DATABASE=PELCOMBE GROUP LTD. + +OUI:009033* + ID_OUI_FROM_DATABASE=INNOVAPHONE AG + +OUI:009034* + ID_OUI_FROM_DATABASE=IMAGIC, INC. + +OUI:009035* + ID_OUI_FROM_DATABASE=ALPHA TELECOM, INC. + +OUI:009036* + ID_OUI_FROM_DATABASE=ens, inc. + +OUI:009037* + ID_OUI_FROM_DATABASE=ACUCOMM, INC. + +OUI:009038* + ID_OUI_FROM_DATABASE=FOUNTAIN TECHNOLOGIES, INC. + +OUI:009039* + ID_OUI_FROM_DATABASE=SHASTA NETWORKS + +OUI:00903A* + ID_OUI_FROM_DATABASE=NIHON MEDIA TOOL INC. + +OUI:00903B* + ID_OUI_FROM_DATABASE=TriEMS Research Lab, Inc. + +OUI:00903C* + ID_OUI_FROM_DATABASE=ATLANTIC NETWORK SYSTEMS + +OUI:00903D* + ID_OUI_FROM_DATABASE=BIOPAC SYSTEMS, INC. + +OUI:00903E* + ID_OUI_FROM_DATABASE=N.V. PHILIPS INDUSTRIAL ACTIVITIES + +OUI:00903F* + ID_OUI_FROM_DATABASE=AZTEC RADIOMEDIA + +OUI:009040* + ID_OUI_FROM_DATABASE=Siemens Network Convergence LLC + +OUI:009041* + ID_OUI_FROM_DATABASE=APPLIED DIGITAL ACCESS + +OUI:009042* + ID_OUI_FROM_DATABASE=ECCS, Inc. + +OUI:009043* + ID_OUI_FROM_DATABASE=Tattile SRL + +OUI:009044* + ID_OUI_FROM_DATABASE=ASSURED DIGITAL, INC. + +OUI:009045* + ID_OUI_FROM_DATABASE=Marconi Communications + +OUI:009046* + ID_OUI_FROM_DATABASE=DEXDYNE, LTD. + +OUI:009047* + ID_OUI_FROM_DATABASE=GIGA FAST E. LTD. + +OUI:009048* + ID_OUI_FROM_DATABASE=ZEAL CORPORATION + +OUI:009049* + ID_OUI_FROM_DATABASE=ENTRIDIA CORPORATION + +OUI:00904A* + ID_OUI_FROM_DATABASE=CONCUR SYSTEM TECHNOLOGIES + +OUI:00904B* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:00904C* + ID_OUI_FROM_DATABASE=Epigram, Inc. + +OUI:00904D* + ID_OUI_FROM_DATABASE=SPEC S.A. + +OUI:00904E* + ID_OUI_FROM_DATABASE=DELEM BV + +OUI:00904F* + ID_OUI_FROM_DATABASE=ABB POWER T&D COMPANY, INC. + +OUI:009050* + ID_OUI_FROM_DATABASE=Teleste Corporation + +OUI:009051* + ID_OUI_FROM_DATABASE=ULTIMATE TECHNOLOGY CORP. + +OUI:009052* + ID_OUI_FROM_DATABASE=SELCOM ELETTRONICA S.R.L. + +OUI:009053* + ID_OUI_FROM_DATABASE=DAEWOO ELECTRONICS CO., LTD. + +OUI:009054* + ID_OUI_FROM_DATABASE=INNOVATIVE SEMICONDUCTORS, INC + +OUI:009055* + ID_OUI_FROM_DATABASE=PARKER HANNIFIN CORPORATION COMPUMOTOR DIVISION + +OUI:009056* + ID_OUI_FROM_DATABASE=TELESTREAM, INC. + +OUI:009057* + ID_OUI_FROM_DATABASE=AANetcom, Inc. + +OUI:009058* + ID_OUI_FROM_DATABASE=Ultra Electronics Command & Control Systems + +OUI:009059* + ID_OUI_FROM_DATABASE=TELECOM DEVICE K.K. + +OUI:00905A* + ID_OUI_FROM_DATABASE=DEARBORN GROUP, INC. + +OUI:00905B* + ID_OUI_FROM_DATABASE=RAYMOND AND LAE ENGINEERING + +OUI:00905C* + ID_OUI_FROM_DATABASE=EDMI + +OUI:00905D* + ID_OUI_FROM_DATABASE=NETCOM SICHERHEITSTECHNIK GMBH + +OUI:00905E* + ID_OUI_FROM_DATABASE=RAULAND-BORG CORPORATION + +OUI:00905F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:009060* + ID_OUI_FROM_DATABASE=SYSTEM CREATE CORP. + +OUI:009061* + ID_OUI_FROM_DATABASE=PACIFIC RESEARCH & ENGINEERING CORPORATION + +OUI:009062* + ID_OUI_FROM_DATABASE=ICP VORTEX COMPUTERSYSTEME GmbH + +OUI:009063* + ID_OUI_FROM_DATABASE=COHERENT COMMUNICATIONS SYSTEMS CORPORATION + +OUI:009064* + ID_OUI_FROM_DATABASE=Thomson Inc. + +OUI:009065* + ID_OUI_FROM_DATABASE=FINISAR CORPORATION + +OUI:009066* + ID_OUI_FROM_DATABASE=Troika Networks, Inc. + +OUI:009067* + ID_OUI_FROM_DATABASE=WalkAbout Computers, Inc. + +OUI:009068* + ID_OUI_FROM_DATABASE=DVT CORP. + +OUI:009069* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:00906A* + ID_OUI_FROM_DATABASE=TURNSTONE SYSTEMS, INC. + +OUI:00906B* + ID_OUI_FROM_DATABASE=APPLIED RESOURCES, INC. + +OUI:00906C* + ID_OUI_FROM_DATABASE=Sartorius Hamburg GmbH + +OUI:00906D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00906E* + ID_OUI_FROM_DATABASE=PRAXON, INC. + +OUI:00906F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:009070* + ID_OUI_FROM_DATABASE=NEO NETWORKS, INC. + +OUI:009071* + ID_OUI_FROM_DATABASE=Applied Innovation Inc. + +OUI:009072* + ID_OUI_FROM_DATABASE=SIMRAD AS + +OUI:009073* + ID_OUI_FROM_DATABASE=GAIO TECHNOLOGY + +OUI:009074* + ID_OUI_FROM_DATABASE=ARGON NETWORKS, INC. + +OUI:009075* + ID_OUI_FROM_DATABASE=NEC DO BRASIL S.A. + +OUI:009076* + ID_OUI_FROM_DATABASE=FMT AIRCRAFT GATE SUPPORT SYSTEMS AB + +OUI:009077* + ID_OUI_FROM_DATABASE=ADVANCED FIBRE COMMUNICATIONS + +OUI:009078* + ID_OUI_FROM_DATABASE=MER TELEMANAGEMENT SOLUTIONS, LTD. + +OUI:009079* + ID_OUI_FROM_DATABASE=ClearOne, Inc. + +OUI:00907A* + ID_OUI_FROM_DATABASE=Spectralink, Inc + +OUI:00907B* + ID_OUI_FROM_DATABASE=E-TECH, INC. + +OUI:00907C* + ID_OUI_FROM_DATABASE=DIGITALCAST, INC. + +OUI:00907D* + ID_OUI_FROM_DATABASE=Lake Communications + +OUI:00907E* + ID_OUI_FROM_DATABASE=VETRONIX CORP. + +OUI:00907F* + ID_OUI_FROM_DATABASE=WatchGuard Technologies, Inc. + +OUI:009080* + ID_OUI_FROM_DATABASE=NOT LIMITED, INC. + +OUI:009081* + ID_OUI_FROM_DATABASE=ALOHA NETWORKS, INC. + +OUI:009082* + ID_OUI_FROM_DATABASE=FORCE INSTITUTE + +OUI:009083* + ID_OUI_FROM_DATABASE=TURBO COMMUNICATION, INC. + +OUI:009084* + ID_OUI_FROM_DATABASE=ATECH SYSTEM + +OUI:009085* + ID_OUI_FROM_DATABASE=GOLDEN ENTERPRISES, INC. + +OUI:009086* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:009087* + ID_OUI_FROM_DATABASE=ITIS + +OUI:009088* + ID_OUI_FROM_DATABASE=BAXALL SECURITY LTD. + +OUI:009089* + ID_OUI_FROM_DATABASE=SOFTCOM MICROSYSTEMS, INC. + +OUI:00908A* + ID_OUI_FROM_DATABASE=BAYLY COMMUNICATIONS, INC. + +OUI:00908B* + ID_OUI_FROM_DATABASE=Tattile SRL + +OUI:00908C* + ID_OUI_FROM_DATABASE=ETREND ELECTRONICS, INC. + +OUI:00908D* + ID_OUI_FROM_DATABASE=VICKERS ELECTRONICS SYSTEMS + +OUI:00908E* + ID_OUI_FROM_DATABASE=Nortel Networks Broadband Access + +OUI:00908F* + ID_OUI_FROM_DATABASE=AUDIO CODES LTD. + +OUI:009090* + ID_OUI_FROM_DATABASE=I-BUS + +OUI:009091* + ID_OUI_FROM_DATABASE=DigitalScape, Inc. + +OUI:009092* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:009093* + ID_OUI_FROM_DATABASE=EIZO Corporation + +OUI:009094* + ID_OUI_FROM_DATABASE=OSPREY TECHNOLOGIES, INC. + +OUI:009095* + ID_OUI_FROM_DATABASE=UNIVERSAL AVIONICS + +OUI:009096* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:009097* + ID_OUI_FROM_DATABASE=Sycamore Networks + +OUI:009098* + ID_OUI_FROM_DATABASE=SBC DESIGNS, INC. + +OUI:009099* + ID_OUI_FROM_DATABASE=ALLIED TELESIS, K.K. + +OUI:00909A* + ID_OUI_FROM_DATABASE=ONE WORLD SYSTEMS, INC. + +OUI:00909B* + ID_OUI_FROM_DATABASE=MARKEM-IMAJE + +OUI:00909C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00909D* + ID_OUI_FROM_DATABASE=NovaTech Process Solutions, LLC + +OUI:00909E* + ID_OUI_FROM_DATABASE=Critical IO, LLC + +OUI:00909F* + ID_OUI_FROM_DATABASE=DIGI-DATA CORPORATION + +OUI:0090A0* + ID_OUI_FROM_DATABASE=8X8 INC. + +OUI:0090A1* + ID_OUI_FROM_DATABASE=Flying Pig Systems/High End Systems Inc. + +OUI:0090A2* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. + +OUI:0090A3* + ID_OUI_FROM_DATABASE=Corecess Inc. + +OUI:0090A4* + ID_OUI_FROM_DATABASE=ALTIGA NETWORKS + +OUI:0090A5* + ID_OUI_FROM_DATABASE=SPECTRA LOGIC + +OUI:0090A6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0090A7* + ID_OUI_FROM_DATABASE=CLIENTEC CORPORATION + +OUI:0090A8* + ID_OUI_FROM_DATABASE=NineTiles Networks, Ltd. + +OUI:0090A9* + ID_OUI_FROM_DATABASE=WESTERN DIGITAL + +OUI:0090AA* + ID_OUI_FROM_DATABASE=INDIGO ACTIVE VISION SYSTEMS LIMITED + +OUI:0090AB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0090AC* + ID_OUI_FROM_DATABASE=OPTIVISION, INC. + +OUI:0090AD* + ID_OUI_FROM_DATABASE=ASPECT ELECTRONICS, INC. + +OUI:0090AE* + ID_OUI_FROM_DATABASE=ITALTEL S.p.A/RF-UP-I + +OUI:0090AF* + ID_OUI_FROM_DATABASE=J. MORITA MFG. CORP. + +OUI:0090B0* + ID_OUI_FROM_DATABASE=VADEM + +OUI:0090B1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0090B2* + ID_OUI_FROM_DATABASE=AVICI SYSTEMS INC. + +OUI:0090B3* + ID_OUI_FROM_DATABASE=AGRANAT SYSTEMS + +OUI:0090B4* + ID_OUI_FROM_DATABASE=WILLOWBROOK TECHNOLOGIES + +OUI:0090B5* + ID_OUI_FROM_DATABASE=NIKON CORPORATION + +OUI:0090B6* + ID_OUI_FROM_DATABASE=FIBEX SYSTEMS + +OUI:0090B7* + ID_OUI_FROM_DATABASE=DIGITAL LIGHTWAVE, INC. + +OUI:0090B8* + ID_OUI_FROM_DATABASE=ROHDE & SCHWARZ GMBH & CO. KG + +OUI:0090B9* + ID_OUI_FROM_DATABASE=BERAN INSTRUMENTS LTD. + +OUI:0090BA* + ID_OUI_FROM_DATABASE=VALID NETWORKS, INC. + +OUI:0090BB* + ID_OUI_FROM_DATABASE=TAINET COMMUNICATION SYSTEM Corp. + +OUI:0090BC* + ID_OUI_FROM_DATABASE=TELEMANN CO., LTD. + +OUI:0090BD* + ID_OUI_FROM_DATABASE=OMNIA COMMUNICATIONS, INC. + +OUI:0090BE* + ID_OUI_FROM_DATABASE=IBC/INTEGRATED BUSINESS COMPUTERS + +OUI:0090BF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0090C0* + ID_OUI_FROM_DATABASE=K.J. LAW ENGINEERS, INC. + +OUI:0090C1* + ID_OUI_FROM_DATABASE=Peco II, Inc. + +OUI:0090C2* + ID_OUI_FROM_DATABASE=JK microsystems, Inc. + +OUI:0090C3* + ID_OUI_FROM_DATABASE=TOPIC SEMICONDUCTOR CORP. + +OUI:0090C4* + ID_OUI_FROM_DATABASE=JAVELIN SYSTEMS, INC. + +OUI:0090C5* + ID_OUI_FROM_DATABASE=INTERNET MAGIC, INC. + +OUI:0090C6* + ID_OUI_FROM_DATABASE=OPTIM SYSTEMS, INC. + +OUI:0090C7* + ID_OUI_FROM_DATABASE=ICOM INC. + +OUI:0090C8* + ID_OUI_FROM_DATABASE=WAVERIDER COMMUNICATIONS (CANADA) INC. + +OUI:0090C9* + ID_OUI_FROM_DATABASE=DPAC Technologies + +OUI:0090CA* + ID_OUI_FROM_DATABASE=ACCORD VIDEO TELECOMMUNICATIONS, LTD. + +OUI:0090CB* + ID_OUI_FROM_DATABASE=Wireless OnLine, Inc. + +OUI:0090CC* + ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. + +OUI:0090CD* + ID_OUI_FROM_DATABASE=ENT-EMPRESA NACIONAL DE TELECOMMUNICACOES, S.A. + +OUI:0090CE* + ID_OUI_FROM_DATABASE=avateramedical Mechatronics GmbH + +OUI:0090CF* + ID_OUI_FROM_DATABASE=NORTEL + +OUI:0090D0* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium + +OUI:0090D1* + ID_OUI_FROM_DATABASE=LEICHU ENTERPRISE CO., LTD. + +OUI:0090D2* + ID_OUI_FROM_DATABASE=ARTEL VIDEO SYSTEMS + +OUI:0090D3* + ID_OUI_FROM_DATABASE=GIESECKE & DEVRIENT GmbH + +OUI:0090D4* + ID_OUI_FROM_DATABASE=BindView Development Corp. + +OUI:0090D5* + ID_OUI_FROM_DATABASE=EUPHONIX, INC. + +OUI:0090D6* + ID_OUI_FROM_DATABASE=Crystal Group, Inc. + +OUI:0090D7* + ID_OUI_FROM_DATABASE=NetBoost Corp. + +OUI:0090D8* + ID_OUI_FROM_DATABASE=WHITECROSS SYSTEMS + +OUI:0090D9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0090DA* + ID_OUI_FROM_DATABASE=DYNARC, INC. + +OUI:0090DB* + ID_OUI_FROM_DATABASE=NEXT LEVEL COMMUNICATIONS + +OUI:0090DC* + ID_OUI_FROM_DATABASE=TECO INFORMATION SYSTEMS + +OUI:0090DD* + ID_OUI_FROM_DATABASE=MIHARU COMMUNICATIONS Inc + +OUI:0090DE* + ID_OUI_FROM_DATABASE=CARDKEY SYSTEMS, INC. + +OUI:0090DF* + ID_OUI_FROM_DATABASE=MITSUBISHI CHEMICAL AMERICA, INC. + +OUI:0090E0* + ID_OUI_FROM_DATABASE=SYSTRAN CORP. + +OUI:0090E1* + ID_OUI_FROM_DATABASE=TELENA S.P.A. + +OUI:0090E2* + ID_OUI_FROM_DATABASE=DISTRIBUTED PROCESSING TECHNOLOGY + +OUI:0090E3* + ID_OUI_FROM_DATABASE=AVEX ELECTRONICS INC. + +OUI:0090E4* + ID_OUI_FROM_DATABASE=NEC AMERICA, INC. + +OUI:0090E5* + ID_OUI_FROM_DATABASE=TEKNEMA, INC. + +OUI:0090E6* + ID_OUI_FROM_DATABASE=ALi Corporation + +OUI:0090E7* + ID_OUI_FROM_DATABASE=HORSCH ELEKTRONIK AG + +OUI:0090E8* + ID_OUI_FROM_DATABASE=MOXA TECHNOLOGIES CORP., LTD. + +OUI:0090E9* + ID_OUI_FROM_DATABASE=JANZ COMPUTER AG + +OUI:0090EA* + ID_OUI_FROM_DATABASE=ALPHA TECHNOLOGIES, INC. + +OUI:0090EB* + ID_OUI_FROM_DATABASE=SENTRY TELECOM SYSTEMS + +OUI:0090EC* + ID_OUI_FROM_DATABASE=PYRESCOM + +OUI:0090ED* + ID_OUI_FROM_DATABASE=CENTRAL SYSTEM RESEARCH CO., LTD. + +OUI:0090EE* + ID_OUI_FROM_DATABASE=PERSONAL COMMUNICATIONS TECHNOLOGIES + +OUI:0090EF* + ID_OUI_FROM_DATABASE=INTEGRIX, INC. + +OUI:0090F0* + ID_OUI_FROM_DATABASE=Harmonic Video Systems Ltd. + +OUI:0090F1* + ID_OUI_FROM_DATABASE=Seagate Cloud Systems Inc + +OUI:0090F2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0090F3* + ID_OUI_FROM_DATABASE=ASPECT COMMUNICATIONS + +OUI:0090F4* + ID_OUI_FROM_DATABASE=LIGHTNING INSTRUMENTATION + +OUI:0090F5* + ID_OUI_FROM_DATABASE=CLEVO CO. + +OUI:0090F6* + ID_OUI_FROM_DATABASE=ESCALATE NETWORKS, INC. + +OUI:0090F7* + ID_OUI_FROM_DATABASE=NBASE COMMUNICATIONS LTD. + +OUI:0090F8* + ID_OUI_FROM_DATABASE=MEDIATRIX TELECOM + +OUI:0090F9* + ID_OUI_FROM_DATABASE=Imagine Communications + +OUI:0090FA* + ID_OUI_FROM_DATABASE=Emulex Corporation + +OUI:0090FB* + ID_OUI_FROM_DATABASE=PORTWELL, INC. + +OUI:0090FC* + ID_OUI_FROM_DATABASE=NETWORK COMPUTING DEVICES + +OUI:0090FD* + ID_OUI_FROM_DATABASE=CopperCom, Inc. + +OUI:0090FE* + ID_OUI_FROM_DATABASE=ELECOM CO., LTD. (LANEED DIV.) + +OUI:0090FF* + ID_OUI_FROM_DATABASE=TELLUS TECHNOLOGY INC. + +OUI:0091D6* + ID_OUI_FROM_DATABASE=Crystal Group, Inc. + +OUI:0091FA* + ID_OUI_FROM_DATABASE=Synapse Product Development + +OUI:0092FA* + ID_OUI_FROM_DATABASE=SHENZHEN WISKY TECHNOLOGY CO.,LTD + +OUI:009363* + ID_OUI_FROM_DATABASE=Uni-Link Technology Co., Ltd. + +OUI:0094A1* + ID_OUI_FROM_DATABASE=F5 Networks, Inc. + +OUI:009569* + ID_OUI_FROM_DATABASE=LSD Science and Technology Co.,Ltd. + +OUI:0097FF* + ID_OUI_FROM_DATABASE=Heimann Sensor GmbH + +OUI:009ACD* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:009AD2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:009C02* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:009D6B* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:009D8E* + ID_OUI_FROM_DATABASE=CARDIAC RECORDERS, INC. + +OUI:009E1E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:009EC8* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:009EEE* + ID_OUI_FROM_DATABASE=Positivo Tecnologia S.A. + +OUI:00A000* + ID_OUI_FROM_DATABASE=CENTILLION NETWORKS, INC. + +OUI:00A001* + ID_OUI_FROM_DATABASE=DRS Signal Solutions + +OUI:00A002* + ID_OUI_FROM_DATABASE=LEEDS & NORTHRUP AUSTRALIA PTY LTD + +OUI:00A003* + ID_OUI_FROM_DATABASE=Siemens Switzerland Ltd., I B T HVP + +OUI:00A004* + ID_OUI_FROM_DATABASE=NETPOWER, INC. + +OUI:00A005* + ID_OUI_FROM_DATABASE=DANIEL INSTRUMENTS, LTD. + +OUI:00A006* + ID_OUI_FROM_DATABASE=IMAGE DATA PROCESSING SYSTEM GROUP + +OUI:00A007* + ID_OUI_FROM_DATABASE=APEXX TECHNOLOGY, INC. + +OUI:00A008* + ID_OUI_FROM_DATABASE=NETCORP + +OUI:00A009* + ID_OUI_FROM_DATABASE=WHITETREE NETWORK + +OUI:00A00A* + ID_OUI_FROM_DATABASE=Airspan + +OUI:00A00B* + ID_OUI_FROM_DATABASE=COMPUTEX CO., LTD. + +OUI:00A00C* + ID_OUI_FROM_DATABASE=KINGMAX TECHNOLOGY, INC. + +OUI:00A00D* + ID_OUI_FROM_DATABASE=THE PANDA PROJECT + +OUI:00A00E* + ID_OUI_FROM_DATABASE=NetAlly + +OUI:00A00F* + ID_OUI_FROM_DATABASE=Broadband Technologies + +OUI:00A010* + ID_OUI_FROM_DATABASE=SYSLOGIC DATENTECHNIK AG + +OUI:00A011* + ID_OUI_FROM_DATABASE=MUTOH INDUSTRIES LTD. + +OUI:00A012* + ID_OUI_FROM_DATABASE=Telco Systems, Inc. + +OUI:00A013* + ID_OUI_FROM_DATABASE=TELTREND LTD. + +OUI:00A014* + ID_OUI_FROM_DATABASE=CSIR + +OUI:00A015* + ID_OUI_FROM_DATABASE=WYLE + +OUI:00A016* + ID_OUI_FROM_DATABASE=MICROPOLIS CORP. + +OUI:00A017* + ID_OUI_FROM_DATABASE=J B M CORPORATION + +OUI:00A018* + ID_OUI_FROM_DATABASE=CREATIVE CONTROLLERS, INC. + +OUI:00A019* + ID_OUI_FROM_DATABASE=NEBULA CONSULTANTS, INC. + +OUI:00A01A* + ID_OUI_FROM_DATABASE=BINAR ELEKTRONIK AB + +OUI:00A01B* + ID_OUI_FROM_DATABASE=PREMISYS COMMUNICATIONS, INC. + +OUI:00A01C* + ID_OUI_FROM_DATABASE=NASCENT NETWORKS CORPORATION + +OUI:00A01D* + ID_OUI_FROM_DATABASE=Red Lion Controls, LP + +OUI:00A01E* + ID_OUI_FROM_DATABASE=EST CORPORATION + +OUI:00A01F* + ID_OUI_FROM_DATABASE=TRICORD SYSTEMS, INC. + +OUI:00A020* + ID_OUI_FROM_DATABASE=CITICORP/TTI + +OUI:00A021* + ID_OUI_FROM_DATABASE=General Dynamics Mission Systems + +OUI:00A022* + ID_OUI_FROM_DATABASE=CENTRE FOR DEVELOPMENT OF ADVANCED COMPUTING + +OUI:00A023* + ID_OUI_FROM_DATABASE=APPLIED CREATIVE TECHNOLOGY, INC. + +OUI:00A024* + ID_OUI_FROM_DATABASE=3COM + +OUI:00A025* + ID_OUI_FROM_DATABASE=REDCOM LABS INC. + +OUI:00A026* + ID_OUI_FROM_DATABASE=TELDAT, S.A. + +OUI:00A027* + ID_OUI_FROM_DATABASE=FIREPOWER SYSTEMS, INC. + +OUI:00A028* + ID_OUI_FROM_DATABASE=CONNER PERIPHERALS + +OUI:00A029* + ID_OUI_FROM_DATABASE=COULTER CORPORATION + +OUI:00A02A* + ID_OUI_FROM_DATABASE=TRANCELL SYSTEMS + +OUI:00A02B* + ID_OUI_FROM_DATABASE=TRANSITIONS RESEARCH CORP. + +OUI:00A02C* + ID_OUI_FROM_DATABASE=interWAVE Communications + +OUI:00A02D* + ID_OUI_FROM_DATABASE=1394 Trade Association + +OUI:00A02E* + ID_OUI_FROM_DATABASE=BRAND COMMUNICATIONS, LTD. + +OUI:00A02F* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:00A030* + ID_OUI_FROM_DATABASE=CAPTOR NV/SA + +OUI:00A031* + ID_OUI_FROM_DATABASE=HAZELTINE CORPORATION, MS 1-17 + +OUI:00A032* + ID_OUI_FROM_DATABASE=GES SINGAPORE PTE. LTD. + +OUI:00A033* + ID_OUI_FROM_DATABASE=imc MeBsysteme GmbH + +OUI:00A034* + ID_OUI_FROM_DATABASE=AXEL + +OUI:00A035* + ID_OUI_FROM_DATABASE=CYLINK CORPORATION + +OUI:00A036* + ID_OUI_FROM_DATABASE=APPLIED NETWORK TECHNOLOGY + +OUI:00A037* + ID_OUI_FROM_DATABASE=Mindray DS USA, Inc. + +OUI:00A038* + ID_OUI_FROM_DATABASE=EMAIL ELECTRONICS + +OUI:00A039* + ID_OUI_FROM_DATABASE=ROSS TECHNOLOGY, INC. + +OUI:00A03A* + ID_OUI_FROM_DATABASE=KUBOTEK CORPORATION + +OUI:00A03B* + ID_OUI_FROM_DATABASE=TOSHIN ELECTRIC CO., LTD. + +OUI:00A03C* + ID_OUI_FROM_DATABASE=EG&G NUCLEAR INSTRUMENTS + +OUI:00A03D* + ID_OUI_FROM_DATABASE=OPTO-22 + +OUI:00A03E* + ID_OUI_FROM_DATABASE=ATM FORUM + +OUI:00A03F* + ID_OUI_FROM_DATABASE=COMPUTER SOCIETY MICROPROCESSOR & MICROPROCESSOR STANDARDS C + +OUI:00A040* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00A041* + ID_OUI_FROM_DATABASE=INFICON + +OUI:00A042* + ID_OUI_FROM_DATABASE=SPUR PRODUCTS CORP. + +OUI:00A043* + ID_OUI_FROM_DATABASE=AMERICAN TECHNOLOGY LABS, INC. + +OUI:00A044* + ID_OUI_FROM_DATABASE=NTT IT CO., LTD. + +OUI:00A045* + ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH + +OUI:00A046* + ID_OUI_FROM_DATABASE=SCITEX CORP. LTD. + +OUI:00A047* + ID_OUI_FROM_DATABASE=INTEGRATED FITNESS CORP. + +OUI:00A048* + ID_OUI_FROM_DATABASE=QUESTECH, LTD. + +OUI:00A049* + ID_OUI_FROM_DATABASE=DIGITECH INDUSTRIES, INC. + +OUI:00A04A* + ID_OUI_FROM_DATABASE=NISSHIN ELECTRIC CO., LTD. + +OUI:00A04B* + ID_OUI_FROM_DATABASE=TFL LAN INC. + +OUI:00A04C* + ID_OUI_FROM_DATABASE=INNOVATIVE SYSTEMS & TECHNOLOGIES, INC. + +OUI:00A04D* + ID_OUI_FROM_DATABASE=EDA INSTRUMENTS, INC. + +OUI:00A04E* + ID_OUI_FROM_DATABASE=VOELKER TECHNOLOGIES, INC. + +OUI:00A04F* + ID_OUI_FROM_DATABASE=AMERITEC CORP. + +OUI:00A050* + ID_OUI_FROM_DATABASE=CYPRESS SEMICONDUCTOR + +OUI:00A051* + ID_OUI_FROM_DATABASE=ANGIA COMMUNICATIONS. INC. + +OUI:00A052* + ID_OUI_FROM_DATABASE=STANILITE ELECTRONICS PTY. LTD + +OUI:00A053* + ID_OUI_FROM_DATABASE=COMPACT DEVICES, INC. + +OUI:00A054* + ID_OUI_FROM_DATABASE=Private + +OUI:00A055* + ID_OUI_FROM_DATABASE=Data Device Corporation + +OUI:00A056* + ID_OUI_FROM_DATABASE=MICROPROSS + +OUI:00A057* + ID_OUI_FROM_DATABASE=LANCOM Systems GmbH + +OUI:00A058* + ID_OUI_FROM_DATABASE=GLORY, LTD. + +OUI:00A059* + ID_OUI_FROM_DATABASE=HAMILTON HALLMARK + +OUI:00A05A* + ID_OUI_FROM_DATABASE=KOFAX IMAGE PRODUCTS + +OUI:00A05B* + ID_OUI_FROM_DATABASE=MARQUIP, INC. + +OUI:00A05C* + ID_OUI_FROM_DATABASE=INVENTORY CONVERSION, INC./ + +OUI:00A05D* + ID_OUI_FROM_DATABASE=CS COMPUTER SYSTEME GmbH + +OUI:00A05E* + ID_OUI_FROM_DATABASE=MYRIAD LOGIC INC. + +OUI:00A05F* + ID_OUI_FROM_DATABASE=BTG Electronics Design BV + +OUI:00A060* + ID_OUI_FROM_DATABASE=ACER PERIPHERALS, INC. + +OUI:00A061* + ID_OUI_FROM_DATABASE=PURITAN BENNETT + +OUI:00A062* + ID_OUI_FROM_DATABASE=AES PRODATA + +OUI:00A063* + ID_OUI_FROM_DATABASE=JRL SYSTEMS, INC. + +OUI:00A064* + ID_OUI_FROM_DATABASE=KVB/ANALECT + +OUI:00A065* + ID_OUI_FROM_DATABASE=Symantec Corporation + +OUI:00A066* + ID_OUI_FROM_DATABASE=ISA CO., LTD. + +OUI:00A067* + ID_OUI_FROM_DATABASE=NETWORK SERVICES GROUP + +OUI:00A068* + ID_OUI_FROM_DATABASE=BHP LIMITED + +OUI:00A069* + ID_OUI_FROM_DATABASE=Symmetricom, Inc. + +OUI:00A06A* + ID_OUI_FROM_DATABASE=Verilink Corporation + +OUI:00A06B* + ID_OUI_FROM_DATABASE=DMS DORSCH MIKROSYSTEM GMBH + +OUI:00A06C* + ID_OUI_FROM_DATABASE=SHINDENGEN ELECTRIC MFG. CO., LTD. + +OUI:00A06D* + ID_OUI_FROM_DATABASE=MANNESMANN TALLY CORPORATION + +OUI:00A06E* + ID_OUI_FROM_DATABASE=AUSTRON, INC. + +OUI:00A06F* + ID_OUI_FROM_DATABASE=Color Sentinel Systems, LLC + +OUI:00A070* + ID_OUI_FROM_DATABASE=COASTCOM + +OUI:00A071* + ID_OUI_FROM_DATABASE=VIDEO LOTTERY TECHNOLOGIES,INC + +OUI:00A072* + ID_OUI_FROM_DATABASE=OVATION SYSTEMS LTD. + +OUI:00A073* + ID_OUI_FROM_DATABASE=COM21, INC. + +OUI:00A074* + ID_OUI_FROM_DATABASE=PERCEPTION TECHNOLOGY + +OUI:00A075* + ID_OUI_FROM_DATABASE=MICRON TECHNOLOGY, INC. + +OUI:00A076* + ID_OUI_FROM_DATABASE=CARDWARE LAB, INC. + +OUI:00A077* + ID_OUI_FROM_DATABASE=FUJITSU NEXION, INC. + +OUI:00A078* + ID_OUI_FROM_DATABASE=Marconi Communications + +OUI:00A079* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC (USA), INC. + +OUI:00A07A* + ID_OUI_FROM_DATABASE=ADVANCED PERIPHERALS TECHNOLOGIES, INC. + +OUI:00A07B* + ID_OUI_FROM_DATABASE=DAWN COMPUTER INCORPORATION + +OUI:00A07C* + ID_OUI_FROM_DATABASE=TONYANG NYLON CO., LTD. + +OUI:00A07D* + ID_OUI_FROM_DATABASE=SEEQ TECHNOLOGY, INC. + +OUI:00A07E* + ID_OUI_FROM_DATABASE=AVID TECHNOLOGY, INC. + +OUI:00A07F* + ID_OUI_FROM_DATABASE=GSM-SYNTEL, LTD. + +OUI:00A080* + ID_OUI_FROM_DATABASE=Tattile SRL + +OUI:00A081* + ID_OUI_FROM_DATABASE=ALCATEL DATA NETWORKS + +OUI:00A082* + ID_OUI_FROM_DATABASE=NKT ELEKTRONIK A/S + +OUI:00A083* + ID_OUI_FROM_DATABASE=ASIMMPHONY TURKEY + +OUI:00A084* + ID_OUI_FROM_DATABASE=Dataplex Pty Ltd + +OUI:00A085* + ID_OUI_FROM_DATABASE=Private + +OUI:00A086* + ID_OUI_FROM_DATABASE=AMBER WAVE SYSTEMS, INC. + +OUI:00A087* + ID_OUI_FROM_DATABASE=Microsemi Corporation + +OUI:00A088* + ID_OUI_FROM_DATABASE=ESSENTIAL COMMUNICATIONS + +OUI:00A089* + ID_OUI_FROM_DATABASE=XPOINT TECHNOLOGIES, INC. + +OUI:00A08A* + ID_OUI_FROM_DATABASE=BROOKTROUT TECHNOLOGY, INC. + +OUI:00A08B* + ID_OUI_FROM_DATABASE=ASTON ELECTRONIC DESIGNS LTD. + +OUI:00A08C* + ID_OUI_FROM_DATABASE=MultiMedia LANs, Inc. + +OUI:00A08D* + ID_OUI_FROM_DATABASE=JACOMO CORPORATION + +OUI:00A08E* + ID_OUI_FROM_DATABASE=Check Point Software Technologies + +OUI:00A08F* + ID_OUI_FROM_DATABASE=DESKNET SYSTEMS, INC. + +OUI:00A090* + ID_OUI_FROM_DATABASE=TimeStep Corporation + +OUI:00A091* + ID_OUI_FROM_DATABASE=APPLICOM INTERNATIONAL + +OUI:00A092* + ID_OUI_FROM_DATABASE=H. BOLLMANN MANUFACTURERS, LTD + +OUI:00A093* + ID_OUI_FROM_DATABASE=B/E AEROSPACE, Inc. + +OUI:00A094* + ID_OUI_FROM_DATABASE=COMSAT CORPORATION + +OUI:00A095* + ID_OUI_FROM_DATABASE=ACACIA NETWORKS, INC. + +OUI:00A096* + ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD. + +OUI:00A097* + ID_OUI_FROM_DATABASE=JC INFORMATION SYSTEMS + +OUI:00A098* + ID_OUI_FROM_DATABASE=NetApp + +OUI:00A099* + ID_OUI_FROM_DATABASE=K-NET LTD. + +OUI:00A09A* + ID_OUI_FROM_DATABASE=NIHON KOHDEN AMERICA + +OUI:00A09B* + ID_OUI_FROM_DATABASE=QPSX COMMUNICATIONS, LTD. + +OUI:00A09C* + ID_OUI_FROM_DATABASE=Xyplex, Inc. + +OUI:00A09D* + ID_OUI_FROM_DATABASE=JOHNATHON FREEMAN TECHNOLOGIES + +OUI:00A09E* + ID_OUI_FROM_DATABASE=ICTV + +OUI:00A09F* + ID_OUI_FROM_DATABASE=COMMVISION CORP. + +OUI:00A0A0* + ID_OUI_FROM_DATABASE=COMPACT DATA, LTD. + +OUI:00A0A1* + ID_OUI_FROM_DATABASE=EPIC DATA INC. + +OUI:00A0A2* + ID_OUI_FROM_DATABASE=DIGICOM S.P.A. + +OUI:00A0A3* + ID_OUI_FROM_DATABASE=RELIABLE POWER METERS + +OUI:00A0A4* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:00A0A5* + ID_OUI_FROM_DATABASE=TEKNOR MICROSYSTEME, INC. + +OUI:00A0A6* + ID_OUI_FROM_DATABASE=M.I. SYSTEMS, K.K. + +OUI:00A0A7* + ID_OUI_FROM_DATABASE=VORAX CORPORATION + +OUI:00A0A8* + ID_OUI_FROM_DATABASE=RENEX CORPORATION + +OUI:00A0A9* + ID_OUI_FROM_DATABASE=NAVTEL COMMUNICATIONS INC. + +OUI:00A0AA* + ID_OUI_FROM_DATABASE=SPACELABS MEDICAL + +OUI:00A0AB* + ID_OUI_FROM_DATABASE=NETCS INFORMATIONSTECHNIK GMBH + +OUI:00A0AC* + ID_OUI_FROM_DATABASE=GILAT SATELLITE NETWORKS, LTD. + +OUI:00A0AD* + ID_OUI_FROM_DATABASE=MARCONI SPA + +OUI:00A0AE* + ID_OUI_FROM_DATABASE=NUCOM SYSTEMS, INC. + +OUI:00A0AF* + ID_OUI_FROM_DATABASE=WMS INDUSTRIES + +OUI:00A0B0* + ID_OUI_FROM_DATABASE=I-O DATA DEVICE,INC. + +OUI:00A0B1* + ID_OUI_FROM_DATABASE=FIRST VIRTUAL CORPORATION + +OUI:00A0B2* + ID_OUI_FROM_DATABASE=SHIMA SEIKI + +OUI:00A0B3* + ID_OUI_FROM_DATABASE=ZYKRONIX + +OUI:00A0B4* + ID_OUI_FROM_DATABASE=TEXAS MICROSYSTEMS, INC. + +OUI:00A0B5* + ID_OUI_FROM_DATABASE=3H TECHNOLOGY + +OUI:00A0B6* + ID_OUI_FROM_DATABASE=SANRITZ AUTOMATION CO., LTD. + +OUI:00A0B7* + ID_OUI_FROM_DATABASE=CORDANT, INC. + +OUI:00A0B8* + ID_OUI_FROM_DATABASE=NetApp + +OUI:00A0B9* + ID_OUI_FROM_DATABASE=EAGLE TECHNOLOGY, INC. + +OUI:00A0BA* + ID_OUI_FROM_DATABASE=PATTON ELECTRONICS CO. + +OUI:00A0BB* + ID_OUI_FROM_DATABASE=HILAN GMBH + +OUI:00A0BC* + ID_OUI_FROM_DATABASE=VIASAT, INCORPORATED + +OUI:00A0BD* + ID_OUI_FROM_DATABASE=I-TECH CORP. + +OUI:00A0BE* + ID_OUI_FROM_DATABASE=INTEGRATED CIRCUIT SYSTEMS, INC. COMMUNICATIONS GROUP + +OUI:00A0BF* + ID_OUI_FROM_DATABASE=WIRELESS DATA GROUP MOTOROLA + +OUI:00A0C0* + ID_OUI_FROM_DATABASE=DIGITAL LINK CORP. + +OUI:00A0C1* + ID_OUI_FROM_DATABASE=ORTIVUS MEDICAL AB + +OUI:00A0C2* + ID_OUI_FROM_DATABASE=R.A. SYSTEMS CO., LTD. + +OUI:00A0C3* + ID_OUI_FROM_DATABASE=UNICOMPUTER GMBH + +OUI:00A0C4* + ID_OUI_FROM_DATABASE=CRISTIE ELECTRONICS LTD. + +OUI:00A0C5* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:00A0C6* + ID_OUI_FROM_DATABASE=Qualcomm Inc. + +OUI:00A0C7* + ID_OUI_FROM_DATABASE=TADIRAN TELECOMMUNICATIONS + +OUI:00A0C8* + ID_OUI_FROM_DATABASE=Adtran Inc + +OUI:00A0C9* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:00A0CA* + ID_OUI_FROM_DATABASE=FUJITSU DENSO LTD. + +OUI:00A0CB* + ID_OUI_FROM_DATABASE=ARK TELECOMMUNICATIONS, INC. + +OUI:00A0CC* + ID_OUI_FROM_DATABASE=LITE-ON COMMUNICATIONS, INC. + +OUI:00A0CD* + ID_OUI_FROM_DATABASE=DR. JOHANNES HEIDENHAIN GmbH + +OUI:00A0CE* + ID_OUI_FROM_DATABASE=Ecessa + +OUI:00A0CF* + ID_OUI_FROM_DATABASE=SOTAS, INC. + +OUI:00A0D0* + ID_OUI_FROM_DATABASE=TEN X TECHNOLOGY, INC. + +OUI:00A0D1* + ID_OUI_FROM_DATABASE=INVENTEC CORPORATION + +OUI:00A0D2* + ID_OUI_FROM_DATABASE=ALLIED TELESIS INTERNATIONAL CORPORATION + +OUI:00A0D3* + ID_OUI_FROM_DATABASE=INSTEM COMPUTER SYSTEMS, LTD. + +OUI:00A0D4* + ID_OUI_FROM_DATABASE=RADIOLAN, INC. + +OUI:00A0D5* + ID_OUI_FROM_DATABASE=Sierra Wireless + +OUI:00A0D6* + ID_OUI_FROM_DATABASE=SBE, Inc. + +OUI:00A0D7* + ID_OUI_FROM_DATABASE=KASTEN CHASE APPLIED RESEARCH + +OUI:00A0D8* + ID_OUI_FROM_DATABASE=SPECTRA - TEK + +OUI:00A0D9* + ID_OUI_FROM_DATABASE=CONVEX COMPUTER CORPORATION + +OUI:00A0DA* + ID_OUI_FROM_DATABASE=INTEGRATED SYSTEMS Technology, Inc. + +OUI:00A0DB* + ID_OUI_FROM_DATABASE=FISHER & PAYKEL PRODUCTION + +OUI:00A0DC* + ID_OUI_FROM_DATABASE=O.N. ELECTRONIC CO., LTD. + +OUI:00A0DD* + ID_OUI_FROM_DATABASE=AZONIX CORPORATION + +OUI:00A0DE* + ID_OUI_FROM_DATABASE=YAMAHA CORPORATION + +OUI:00A0DF* + ID_OUI_FROM_DATABASE=STS TECHNOLOGIES, INC. + +OUI:00A0E0* + ID_OUI_FROM_DATABASE=TENNYSON TECHNOLOGIES PTY LTD + +OUI:00A0E1* + ID_OUI_FROM_DATABASE=WESTPORT RESEARCH ASSOCIATES, INC. + +OUI:00A0E2* + ID_OUI_FROM_DATABASE=Keisokugiken Corporation + +OUI:00A0E3* + ID_OUI_FROM_DATABASE=XKL SYSTEMS CORP. + +OUI:00A0E4* + ID_OUI_FROM_DATABASE=OPTIQUEST + +OUI:00A0E5* + ID_OUI_FROM_DATABASE=NHC COMMUNICATIONS + +OUI:00A0E6* + ID_OUI_FROM_DATABASE=DIALOGIC CORPORATION + +OUI:00A0E7* + ID_OUI_FROM_DATABASE=CENTRAL DATA CORPORATION + +OUI:00A0E8* + ID_OUI_FROM_DATABASE=REUTERS HOLDINGS PLC + +OUI:00A0E9* + ID_OUI_FROM_DATABASE=ELECTRONIC RETAILING SYSTEMS INTERNATIONAL + +OUI:00A0EA* + ID_OUI_FROM_DATABASE=ETHERCOM CORP. + +OUI:00A0EB* + ID_OUI_FROM_DATABASE=Encore Networks, Inc. + +OUI:00A0EC* + ID_OUI_FROM_DATABASE=TRANSMITTON LTD. + +OUI:00A0ED* + ID_OUI_FROM_DATABASE=Brooks Automation, Inc. + +OUI:00A0EE* + ID_OUI_FROM_DATABASE=NASHOBA NETWORKS + +OUI:00A0EF* + ID_OUI_FROM_DATABASE=LUCIDATA LTD. + +OUI:00A0F0* + ID_OUI_FROM_DATABASE=TORONTO MICROELECTRONICS INC. + +OUI:00A0F1* + ID_OUI_FROM_DATABASE=MTI + +OUI:00A0F2* + ID_OUI_FROM_DATABASE=INFOTEK COMMUNICATIONS, INC. + +OUI:00A0F3* + ID_OUI_FROM_DATABASE=STAUBLI + +OUI:00A0F4* + ID_OUI_FROM_DATABASE=GE + +OUI:00A0F5* + ID_OUI_FROM_DATABASE=RADGUARD LTD. + +OUI:00A0F6* + ID_OUI_FROM_DATABASE=AutoGas Systems Inc. + +OUI:00A0F7* + ID_OUI_FROM_DATABASE=V.I COMPUTER CORP. + +OUI:00A0F8* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc + +OUI:00A0F9* + ID_OUI_FROM_DATABASE=BINTEC COMMUNICATIONS GMBH + +OUI:00A0FA* + ID_OUI_FROM_DATABASE=Marconi Communication GmbH + +OUI:00A0FB* + ID_OUI_FROM_DATABASE=TORAY ENGINEERING CO., LTD. + +OUI:00A0FC* + ID_OUI_FROM_DATABASE=IMAGE SCIENCES, INC. + +OUI:00A0FD* + ID_OUI_FROM_DATABASE=SCITEX DIGITAL PRINTING, INC. + +OUI:00A0FE* + ID_OUI_FROM_DATABASE=BOSTON TECHNOLOGY, INC. + +OUI:00A0FF* + ID_OUI_FROM_DATABASE=TELLABS OPERATIONS, INC. + +OUI:00A1DE* + ID_OUI_FROM_DATABASE=ShenZhen ShiHua Technology CO.,LTD + +OUI:00A289* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00A2DA* + ID_OUI_FROM_DATABASE=INAT GmbH + +OUI:00A2EE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00A2F5* + ID_OUI_FROM_DATABASE=Guangzhou Yuanyun Network Technology Co.,Ltd + +OUI:00A2FF* + ID_OUI_FROM_DATABASE=abatec group AG + +OUI:00A38E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00A3D1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00A509* + ID_OUI_FROM_DATABASE=WigWag Inc. + +OUI:00A5BF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00A6CA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00A742* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00A784* + ID_OUI_FROM_DATABASE=ITX security + +OUI:00AA00* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:00AA01* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:00AA02* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:00AA3C* + ID_OUI_FROM_DATABASE=OLIVETTI TELECOM SPA (OLTECO) + +OUI:00AA6E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00AA70* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:00AB48* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:00ACE0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00AD24* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:00AD63* + ID_OUI_FROM_DATABASE=Dedicated Micros Malta LTD + +OUI:00ADD5* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:00AECD* + ID_OUI_FROM_DATABASE=Pensando Systems + +OUI:00AEFA* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:00AF1F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00B009* + ID_OUI_FROM_DATABASE=Grass Valley, A Belden Brand + +OUI:00B017* + ID_OUI_FROM_DATABASE=InfoGear Technology Corp. + +OUI:00B019* + ID_OUI_FROM_DATABASE=UTC CCS + +OUI:00B01C* + ID_OUI_FROM_DATABASE=Westport Technologies + +OUI:00B01E* + ID_OUI_FROM_DATABASE=Rantic Labs, Inc. + +OUI:00B02A* + ID_OUI_FROM_DATABASE=ORSYS GmbH + +OUI:00B02D* + ID_OUI_FROM_DATABASE=ViaGate Technologies, Inc. + +OUI:00B033* + ID_OUI_FROM_DATABASE=OAO Izhevskiy radiozavod + +OUI:00B03B* + ID_OUI_FROM_DATABASE=HiQ Networks + +OUI:00B048* + ID_OUI_FROM_DATABASE=Marconi Communications Inc. + +OUI:00B04A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00B052* + ID_OUI_FROM_DATABASE=Atheros Communications + +OUI:00B064* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00B069* + ID_OUI_FROM_DATABASE=Honewell Oy + +OUI:00B06D* + ID_OUI_FROM_DATABASE=Jones Futurex Inc. + +OUI:00B080* + ID_OUI_FROM_DATABASE=Mannesmann Ipulsys B.V. + +OUI:00B086* + ID_OUI_FROM_DATABASE=LocSoft Limited + +OUI:00B08E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00B091* + ID_OUI_FROM_DATABASE=Transmeta Corp. + +OUI:00B094* + ID_OUI_FROM_DATABASE=Alaris, Inc. + +OUI:00B09A* + ID_OUI_FROM_DATABASE=Morrow Technologies Corp. + +OUI:00B09D* + ID_OUI_FROM_DATABASE=Point Grey Research Inc. + +OUI:00B0AC* + ID_OUI_FROM_DATABASE=SIAE-Microelettronica S.p.A. + +OUI:00B0AE* + ID_OUI_FROM_DATABASE=Symmetricom + +OUI:00B0B3* + ID_OUI_FROM_DATABASE=XSTREAMIS PLC + +OUI:00B0C2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00B0C7* + ID_OUI_FROM_DATABASE=Tellabs Operations, Inc. + +OUI:00B0CE* + ID_OUI_FROM_DATABASE=Viveris Technologies + +OUI:00B0D0* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:00B0DB* + ID_OUI_FROM_DATABASE=Nextcell, Inc. + +OUI:00B0DF* + ID_OUI_FROM_DATABASE=Starboard Storage Systems + +OUI:00B0E1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00B0E7* + ID_OUI_FROM_DATABASE=British Federal Ltd. + +OUI:00B0EC* + ID_OUI_FROM_DATABASE=EACEM + +OUI:00B0EE* + ID_OUI_FROM_DATABASE=Ajile Systems, Inc. + +OUI:00B0F0* + ID_OUI_FROM_DATABASE=CALY NETWORKS + +OUI:00B0F5* + ID_OUI_FROM_DATABASE=NetWorth Technologies, Inc. + +OUI:00B1E3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00B338* + ID_OUI_FROM_DATABASE=Kontron Asia Pacific Design Sdn. Bhd + +OUI:00B342* + ID_OUI_FROM_DATABASE=MacroSAN Technologies Co., Ltd. + +OUI:00B362* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00B4F5* + ID_OUI_FROM_DATABASE=DongGuan Siyoto Electronics Co., Ltd + +OUI:00B56D* + ID_OUI_FROM_DATABASE=David Electronics Co., LTD. + +OUI:00B5D0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00B5D6* + ID_OUI_FROM_DATABASE=Omnibit Inc. + +OUI:00B600* + ID_OUI_FROM_DATABASE=VOIM Co., Ltd. + +OUI:00B670* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00B69F* + ID_OUI_FROM_DATABASE=Latch + +OUI:00B771* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00B78D* + ID_OUI_FROM_DATABASE=Nanjing Shining Electric Automation Co., Ltd + +OUI:00B7A8* + ID_OUI_FROM_DATABASE=Heinzinger electronic GmbH + +OUI:00B810* + ID_OUI_FROM_DATABASE=Yichip Microelectronics (Hangzhou) Co.,Ltd + +OUI:00B8B3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00B8C2* + ID_OUI_FROM_DATABASE=Heights Telecom T ltd + +OUI:00B9F6* + ID_OUI_FROM_DATABASE=Shenzhen Super Rich Electronics Co.,Ltd + +OUI:00BAC0* + ID_OUI_FROM_DATABASE=Biometric Access Company + +OUI:00BB01* + ID_OUI_FROM_DATABASE=OCTOTHORPE CORP. + +OUI:00BB1C* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:00BB3A* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:00BB60* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:00BB8E* + ID_OUI_FROM_DATABASE=HME Co., Ltd. + +OUI:00BBC1* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:00BBF0* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00BC60* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00BD27* + ID_OUI_FROM_DATABASE=Exar Corp. + +OUI:00BD3A* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:00BD82* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:00BE3B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:00BE75* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00BE9E* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:00BF15* + ID_OUI_FROM_DATABASE=Genetec Inc. + +OUI:00BF61* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00BF77* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00C000* + ID_OUI_FROM_DATABASE=LANOPTICS, LTD. + +OUI:00C001* + ID_OUI_FROM_DATABASE=DIATEK PATIENT MANAGMENT + +OUI:00C002* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:00C003* + ID_OUI_FROM_DATABASE=GLOBALNET COMMUNICATIONS + +OUI:00C004* + ID_OUI_FROM_DATABASE=JAPAN BUSINESS COMPUTER CO.LTD + +OUI:00C005* + ID_OUI_FROM_DATABASE=LIVINGSTON ENTERPRISES, INC. + +OUI:00C006* + ID_OUI_FROM_DATABASE=NIPPON AVIONICS CO., LTD. + +OUI:00C007* + ID_OUI_FROM_DATABASE=PINNACLE DATA SYSTEMS, INC. + +OUI:00C008* + ID_OUI_FROM_DATABASE=SECO SRL + +OUI:00C009* + ID_OUI_FROM_DATABASE=KT TECHNOLOGY (S) PTE LTD + +OUI:00C00A* + ID_OUI_FROM_DATABASE=MICRO CRAFT + +OUI:00C00B* + ID_OUI_FROM_DATABASE=NORCONTROL A.S. + +OUI:00C00C* + ID_OUI_FROM_DATABASE=RELIA TECHNOLGIES + +OUI:00C00D* + ID_OUI_FROM_DATABASE=ADVANCED LOGIC RESEARCH, INC. + +OUI:00C00E* + ID_OUI_FROM_DATABASE=PSITECH, INC. + +OUI:00C00F* + ID_OUI_FROM_DATABASE=QUANTUM SOFTWARE SYSTEMS LTD. + +OUI:00C010* + ID_OUI_FROM_DATABASE=HIRAKAWA HEWTECH CORP. + +OUI:00C011* + ID_OUI_FROM_DATABASE=INTERACTIVE COMPUTING DEVICES + +OUI:00C012* + ID_OUI_FROM_DATABASE=NETSPAN CORPORATION + +OUI:00C013* + ID_OUI_FROM_DATABASE=NETRIX + +OUI:00C014* + ID_OUI_FROM_DATABASE=TELEMATICS CALABASAS INT'L,INC + +OUI:00C015* + ID_OUI_FROM_DATABASE=NEW MEDIA CORPORATION + +OUI:00C016* + ID_OUI_FROM_DATABASE=ELECTRONIC THEATRE CONTROLS + +OUI:00C017* + ID_OUI_FROM_DATABASE=NetAlly + +OUI:00C018* + ID_OUI_FROM_DATABASE=LANART CORPORATION + +OUI:00C019* + ID_OUI_FROM_DATABASE=LEAP TECHNOLOGY, INC. + +OUI:00C01A* + ID_OUI_FROM_DATABASE=COROMETRICS MEDICAL SYSTEMS + +OUI:00C01B* + ID_OUI_FROM_DATABASE=SOCKET COMMUNICATIONS, INC. + +OUI:00C01C* + ID_OUI_FROM_DATABASE=INTERLINK COMMUNICATIONS LTD. + +OUI:00C01D* + ID_OUI_FROM_DATABASE=GRAND JUNCTION NETWORKS, INC. + +OUI:00C01E* + ID_OUI_FROM_DATABASE=LA FRANCAISE DES JEUX + +OUI:00C01F* + ID_OUI_FROM_DATABASE=S.E.R.C.E.L. + +OUI:00C020* + ID_OUI_FROM_DATABASE=ARCO ELECTRONIC, CONTROL LTD. + +OUI:00C021* + ID_OUI_FROM_DATABASE=NETEXPRESS + +OUI:00C022* + ID_OUI_FROM_DATABASE=LASERMASTER TECHNOLOGIES, INC. + +OUI:00C023* + ID_OUI_FROM_DATABASE=TUTANKHAMON ELECTRONICS + +OUI:00C024* + ID_OUI_FROM_DATABASE=EDEN SISTEMAS DE COMPUTACAO SA + +OUI:00C025* + ID_OUI_FROM_DATABASE=DATAPRODUCTS CORPORATION + +OUI:00C026* + ID_OUI_FROM_DATABASE=LANS TECHNOLOGY CO., LTD. + +OUI:00C027* + ID_OUI_FROM_DATABASE=CIPHER SYSTEMS, INC. + +OUI:00C028* + ID_OUI_FROM_DATABASE=JASCO CORPORATION + +OUI:00C029* + ID_OUI_FROM_DATABASE=Nexans Deutschland GmbH - ANS + +OUI:00C02A* + ID_OUI_FROM_DATABASE=OHKURA ELECTRIC CO., LTD. + +OUI:00C02B* + ID_OUI_FROM_DATABASE=GERLOFF GESELLSCHAFT FUR + +OUI:00C02C* + ID_OUI_FROM_DATABASE=CENTRUM COMMUNICATIONS, INC. + +OUI:00C02D* + ID_OUI_FROM_DATABASE=FUJI PHOTO FILM CO., LTD. + +OUI:00C02E* + ID_OUI_FROM_DATABASE=NETWIZ + +OUI:00C02F* + ID_OUI_FROM_DATABASE=OKUMA CORPORATION + +OUI:00C030* + ID_OUI_FROM_DATABASE=INTEGRATED ENGINEERING B. V. + +OUI:00C031* + ID_OUI_FROM_DATABASE=DESIGN RESEARCH SYSTEMS, INC. + +OUI:00C032* + ID_OUI_FROM_DATABASE=I-CUBED LIMITED + +OUI:00C033* + ID_OUI_FROM_DATABASE=TELEBIT COMMUNICATIONS APS + +OUI:00C034* + ID_OUI_FROM_DATABASE=TRANSACTION NETWORK + +OUI:00C035* + ID_OUI_FROM_DATABASE=QUINTAR COMPANY + +OUI:00C036* + ID_OUI_FROM_DATABASE=RAYTECH ELECTRONIC CORP. + +OUI:00C037* + ID_OUI_FROM_DATABASE=DYNATEM + +OUI:00C038* + ID_OUI_FROM_DATABASE=RASTER IMAGE PROCESSING SYSTEM + +OUI:00C039* + ID_OUI_FROM_DATABASE=Teridian Semiconductor Corporation + +OUI:00C03A* + ID_OUI_FROM_DATABASE=MEN-MIKRO ELEKTRONIK GMBH + +OUI:00C03B* + ID_OUI_FROM_DATABASE=MULTIACCESS COMPUTING CORP. + +OUI:00C03C* + ID_OUI_FROM_DATABASE=TOWER TECH S.R.L. + +OUI:00C03D* + ID_OUI_FROM_DATABASE=WIESEMANN & THEIS GMBH + +OUI:00C03E* + ID_OUI_FROM_DATABASE=FA. GEBR. HELLER GMBH + +OUI:00C03F* + ID_OUI_FROM_DATABASE=STORES AUTOMATED SYSTEMS, INC. + +OUI:00C040* + ID_OUI_FROM_DATABASE=ECCI + +OUI:00C041* + ID_OUI_FROM_DATABASE=DIGITAL TRANSMISSION SYSTEMS + +OUI:00C042* + ID_OUI_FROM_DATABASE=DATALUX CORP. + +OUI:00C043* + ID_OUI_FROM_DATABASE=STRATACOM + +OUI:00C044* + ID_OUI_FROM_DATABASE=EMCOM CORPORATION + +OUI:00C045* + ID_OUI_FROM_DATABASE=ISOLATION SYSTEMS, LTD. + +OUI:00C046* + ID_OUI_FROM_DATABASE=Blue Chip Technology Ltd + +OUI:00C047* + ID_OUI_FROM_DATABASE=UNIMICRO SYSTEMS, INC. + +OUI:00C048* + ID_OUI_FROM_DATABASE=BAY TECHNICAL ASSOCIATES + +OUI:00C049* + ID_OUI_FROM_DATABASE=U.S. ROBOTICS, INC. + +OUI:00C04A* + ID_OUI_FROM_DATABASE=GROUP 2000 AG + +OUI:00C04B* + ID_OUI_FROM_DATABASE=CREATIVE MICROSYSTEMS + +OUI:00C04C* + ID_OUI_FROM_DATABASE=DEPARTMENT OF FOREIGN AFFAIRS + +OUI:00C04D* + ID_OUI_FROM_DATABASE=MITEC, INC. + +OUI:00C04E* + ID_OUI_FROM_DATABASE=COMTROL CORPORATION + +OUI:00C04F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:00C050* + ID_OUI_FROM_DATABASE=TOYO DENKI SEIZO K.K. + +OUI:00C051* + ID_OUI_FROM_DATABASE=ADVANCED INTEGRATION RESEARCH + +OUI:00C052* + ID_OUI_FROM_DATABASE=BURR-BROWN + +OUI:00C053* + ID_OUI_FROM_DATABASE=Aspect Software Inc. + +OUI:00C054* + ID_OUI_FROM_DATABASE=NETWORK PERIPHERALS, LTD. + +OUI:00C055* + ID_OUI_FROM_DATABASE=MODULAR COMPUTING TECHNOLOGIES + +OUI:00C056* + ID_OUI_FROM_DATABASE=SOMELEC + +OUI:00C057* + ID_OUI_FROM_DATABASE=MYCO ELECTRONICS + +OUI:00C058* + ID_OUI_FROM_DATABASE=DATAEXPERT CORP. + +OUI:00C059* + ID_OUI_FROM_DATABASE=DENSO CORPORATION + +OUI:00C05A* + ID_OUI_FROM_DATABASE=SEMAPHORE COMMUNICATIONS CORP. + +OUI:00C05B* + ID_OUI_FROM_DATABASE=NETWORKS NORTHWEST, INC. + +OUI:00C05C* + ID_OUI_FROM_DATABASE=ELONEX PLC + +OUI:00C05D* + ID_OUI_FROM_DATABASE=L&N TECHNOLOGIES + +OUI:00C05E* + ID_OUI_FROM_DATABASE=VARI-LITE, INC. + +OUI:00C05F* + ID_OUI_FROM_DATABASE=FINE-PAL COMPANY LIMITED + +OUI:00C060* + ID_OUI_FROM_DATABASE=ID SCANDINAVIA AS + +OUI:00C061* + ID_OUI_FROM_DATABASE=SOLECTEK CORPORATION + +OUI:00C062* + ID_OUI_FROM_DATABASE=IMPULSE TECHNOLOGY + +OUI:00C063* + ID_OUI_FROM_DATABASE=MORNING STAR TECHNOLOGIES, INC + +OUI:00C064* + ID_OUI_FROM_DATABASE=General Datacomm LLC + +OUI:00C065* + ID_OUI_FROM_DATABASE=SCOPE COMMUNICATIONS, INC. + +OUI:00C066* + ID_OUI_FROM_DATABASE=DOCUPOINT, INC. + +OUI:00C067* + ID_OUI_FROM_DATABASE=UNITED BARCODE INDUSTRIES + +OUI:00C068* + ID_OUI_FROM_DATABASE=HME Clear-Com LTD. + +OUI:00C069* + ID_OUI_FROM_DATABASE=Axxcelera Broadband Wireless + +OUI:00C06A* + ID_OUI_FROM_DATABASE=ZAHNER-ELEKTRIK GMBH & CO. KG + +OUI:00C06B* + ID_OUI_FROM_DATABASE=OSI PLUS CORPORATION + +OUI:00C06C* + ID_OUI_FROM_DATABASE=SVEC COMPUTER CORP. + +OUI:00C06D* + ID_OUI_FROM_DATABASE=BOCA RESEARCH, INC. + +OUI:00C06E* + ID_OUI_FROM_DATABASE=HAFT TECHNOLOGY, INC. + +OUI:00C06F* + ID_OUI_FROM_DATABASE=KOMATSU LTD. + +OUI:00C070* + ID_OUI_FROM_DATABASE=SECTRA SECURE-TRANSMISSION AB + +OUI:00C071* + ID_OUI_FROM_DATABASE=AREANEX COMMUNICATIONS, INC. + +OUI:00C072* + ID_OUI_FROM_DATABASE=KNX LTD. + +OUI:00C073* + ID_OUI_FROM_DATABASE=XEDIA CORPORATION + +OUI:00C074* + ID_OUI_FROM_DATABASE=TOYODA AUTOMATIC LOOM + +OUI:00C075* + ID_OUI_FROM_DATABASE=XANTE CORPORATION + +OUI:00C076* + ID_OUI_FROM_DATABASE=I-DATA INTERNATIONAL A-S + +OUI:00C077* + ID_OUI_FROM_DATABASE=DAEWOO TELECOM LTD. + +OUI:00C078* + ID_OUI_FROM_DATABASE=COMPUTER SYSTEMS ENGINEERING + +OUI:00C079* + ID_OUI_FROM_DATABASE=FONSYS CO.,LTD. + +OUI:00C07A* + ID_OUI_FROM_DATABASE=PRIVA B.V. + +OUI:00C07B* + ID_OUI_FROM_DATABASE=ASCEND COMMUNICATIONS, INC. + +OUI:00C07C* + ID_OUI_FROM_DATABASE=HIGHTECH INFORMATION + +OUI:00C07D* + ID_OUI_FROM_DATABASE=RISC DEVELOPMENTS LTD. + +OUI:00C07E* + ID_OUI_FROM_DATABASE=KUBOTA CORPORATION ELECTRONIC + +OUI:00C07F* + ID_OUI_FROM_DATABASE=NUPON COMPUTING CORP. + +OUI:00C080* + ID_OUI_FROM_DATABASE=NETSTAR, INC. + +OUI:00C081* + ID_OUI_FROM_DATABASE=METRODATA LTD. + +OUI:00C082* + ID_OUI_FROM_DATABASE=MOORE PRODUCTS CO. + +OUI:00C083* + ID_OUI_FROM_DATABASE=TRACE MOUNTAIN PRODUCTS, INC. + +OUI:00C084* + ID_OUI_FROM_DATABASE=DATA LINK CORP. LTD. + +OUI:00C085* + ID_OUI_FROM_DATABASE=ELECTRONICS FOR IMAGING, INC. + +OUI:00C086* + ID_OUI_FROM_DATABASE=THE LYNK CORPORATION + +OUI:00C087* + ID_OUI_FROM_DATABASE=UUNET TECHNOLOGIES, INC. + +OUI:00C088* + ID_OUI_FROM_DATABASE=EKF ELEKTRONIK GMBH + +OUI:00C089* + ID_OUI_FROM_DATABASE=TELINDUS DISTRIBUTION + +OUI:00C08A* + ID_OUI_FROM_DATABASE=Lauterbach GmbH + +OUI:00C08B* + ID_OUI_FROM_DATABASE=RISQ MODULAR SYSTEMS, INC. + +OUI:00C08C* + ID_OUI_FROM_DATABASE=PERFORMANCE TECHNOLOGIES, INC. + +OUI:00C08D* + ID_OUI_FROM_DATABASE=TRONIX PRODUCT DEVELOPMENT + +OUI:00C08E* + ID_OUI_FROM_DATABASE=NETWORK INFORMATION TECHNOLOGY + +OUI:00C08F* + ID_OUI_FROM_DATABASE=Panasonic Electric Works Co., Ltd. + +OUI:00C090* + ID_OUI_FROM_DATABASE=PRAIM S.R.L. + +OUI:00C091* + ID_OUI_FROM_DATABASE=JABIL CIRCUIT, INC. + +OUI:00C092* + ID_OUI_FROM_DATABASE=MENNEN MEDICAL INC. + +OUI:00C093* + ID_OUI_FROM_DATABASE=ALTA RESEARCH CORP. + +OUI:00C094* + ID_OUI_FROM_DATABASE=VMX INC. + +OUI:00C095* + ID_OUI_FROM_DATABASE=ZNYX Networks, Inc. + +OUI:00C096* + ID_OUI_FROM_DATABASE=TAMURA CORPORATION + +OUI:00C097* + ID_OUI_FROM_DATABASE=ARCHIPEL SA + +OUI:00C098* + ID_OUI_FROM_DATABASE=CHUNTEX ELECTRONIC CO., LTD. + +OUI:00C099* + ID_OUI_FROM_DATABASE=YOSHIKI INDUSTRIAL CO.,LTD. + +OUI:00C09A* + ID_OUI_FROM_DATABASE=PHOTONICS CORPORATION + +OUI:00C09B* + ID_OUI_FROM_DATABASE=RELIANCE COMM/TEC, R-TEC + +OUI:00C09C* + ID_OUI_FROM_DATABASE=HIOKI E.E. CORPORATION + +OUI:00C09D* + ID_OUI_FROM_DATABASE=DISTRIBUTED SYSTEMS INT'L, INC + +OUI:00C09E* + ID_OUI_FROM_DATABASE=CACHE COMPUTERS, INC. + +OUI:00C09F* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:00C0A0* + ID_OUI_FROM_DATABASE=ADVANCE MICRO RESEARCH, INC. + +OUI:00C0A1* + ID_OUI_FROM_DATABASE=TOKYO DENSHI SEKEI CO. + +OUI:00C0A2* + ID_OUI_FROM_DATABASE=INTERMEDIUM A/S + +OUI:00C0A3* + ID_OUI_FROM_DATABASE=DUAL ENTERPRISES CORPORATION + +OUI:00C0A4* + ID_OUI_FROM_DATABASE=UNIGRAF OY + +OUI:00C0A5* + ID_OUI_FROM_DATABASE=DICKENS DATA SYSTEMS + +OUI:00C0A6* + ID_OUI_FROM_DATABASE=EXICOM AUSTRALIA PTY. LTD + +OUI:00C0A7* + ID_OUI_FROM_DATABASE=SEEL LTD. + +OUI:00C0A8* + ID_OUI_FROM_DATABASE=GVC CORPORATION + +OUI:00C0A9* + ID_OUI_FROM_DATABASE=BARRON MCCANN LTD. + +OUI:00C0AA* + ID_OUI_FROM_DATABASE=SILICON VALLEY COMPUTER + +OUI:00C0AB* + ID_OUI_FROM_DATABASE=Telco Systems, Inc. + +OUI:00C0AC* + ID_OUI_FROM_DATABASE=GAMBIT COMPUTER COMMUNICATIONS + +OUI:00C0AD* + ID_OUI_FROM_DATABASE=MARBEN COMMUNICATION SYSTEMS + +OUI:00C0AE* + ID_OUI_FROM_DATABASE=TOWERCOM CO. INC. DBA PC HOUSE + +OUI:00C0AF* + ID_OUI_FROM_DATABASE=TEKLOGIX INC. + +OUI:00C0B0* + ID_OUI_FROM_DATABASE=GCC TECHNOLOGIES,INC. + +OUI:00C0B1* + ID_OUI_FROM_DATABASE=GENIUS NET CO. + +OUI:00C0B2* + ID_OUI_FROM_DATABASE=NORAND CORPORATION + +OUI:00C0B3* + ID_OUI_FROM_DATABASE=COMSTAT DATACOMM CORPORATION + +OUI:00C0B4* + ID_OUI_FROM_DATABASE=MYSON TECHNOLOGY, INC. + +OUI:00C0B5* + ID_OUI_FROM_DATABASE=CORPORATE NETWORK SYSTEMS,INC. + +OUI:00C0B6* + ID_OUI_FROM_DATABASE=HVE, Inc. + +OUI:00C0B7* + ID_OUI_FROM_DATABASE=AMERICAN POWER CONVERSION CORP + +OUI:00C0B8* + ID_OUI_FROM_DATABASE=FRASER'S HILL LTD. + +OUI:00C0B9* + ID_OUI_FROM_DATABASE=FUNK SOFTWARE, INC. + +OUI:00C0BA* + ID_OUI_FROM_DATABASE=NETVANTAGE + +OUI:00C0BB* + ID_OUI_FROM_DATABASE=FORVAL CREATIVE, INC. + +OUI:00C0BC* + ID_OUI_FROM_DATABASE=TELECOM AUSTRALIA/CSSC + +OUI:00C0BD* + ID_OUI_FROM_DATABASE=INEX TECHNOLOGIES, INC. + +OUI:00C0BE* + ID_OUI_FROM_DATABASE=ALCATEL - SEL + +OUI:00C0BF* + ID_OUI_FROM_DATABASE=TECHNOLOGY CONCEPTS, LTD. + +OUI:00C0C0* + ID_OUI_FROM_DATABASE=SHORE MICROSYSTEMS, INC. + +OUI:00C0C1* + ID_OUI_FROM_DATABASE=QUAD/GRAPHICS, INC. + +OUI:00C0C2* + ID_OUI_FROM_DATABASE=INFINITE NETWORKS LTD. + +OUI:00C0C3* + ID_OUI_FROM_DATABASE=ACUSON COMPUTED SONOGRAPHY + +OUI:00C0C4* + ID_OUI_FROM_DATABASE=COMPUTER OPERATIONAL + +OUI:00C0C5* + ID_OUI_FROM_DATABASE=SID INFORMATICA + +OUI:00C0C6* + ID_OUI_FROM_DATABASE=PERSONAL MEDIA CORP. + +OUI:00C0C7* + ID_OUI_FROM_DATABASE=SPARKTRUM MICROSYSTEMS, INC. + +OUI:00C0C8* + ID_OUI_FROM_DATABASE=MICRO BYTE PTY. LTD. + +OUI:00C0C9* + ID_OUI_FROM_DATABASE=ELSAG BAILEY PROCESS + +OUI:00C0CA* + ID_OUI_FROM_DATABASE=ALFA, INC. + +OUI:00C0CB* + ID_OUI_FROM_DATABASE=CONTROL TECHNOLOGY CORPORATION + +OUI:00C0CC* + ID_OUI_FROM_DATABASE=TELESCIENCES CO SYSTEMS, INC. + +OUI:00C0CD* + ID_OUI_FROM_DATABASE=COMELTA, S.A. + +OUI:00C0CE* + ID_OUI_FROM_DATABASE=CEI SYSTEMS & ENGINEERING PTE + +OUI:00C0CF* + ID_OUI_FROM_DATABASE=IMATRAN VOIMA OY + +OUI:00C0D0* + ID_OUI_FROM_DATABASE=RATOC SYSTEM INC. + +OUI:00C0D1* + ID_OUI_FROM_DATABASE=COMTREE TECHNOLOGY CORPORATION + +OUI:00C0D2* + ID_OUI_FROM_DATABASE=SYNTELLECT, INC. + +OUI:00C0D3* + ID_OUI_FROM_DATABASE=OLYMPUS IMAGE SYSTEMS, INC. + +OUI:00C0D4* + ID_OUI_FROM_DATABASE=AXON NETWORKS, INC. + +OUI:00C0D5* + ID_OUI_FROM_DATABASE=Werbeagentur Jürgen Siebert + +OUI:00C0D6* + ID_OUI_FROM_DATABASE=J1 SYSTEMS, INC. + +OUI:00C0D7* + ID_OUI_FROM_DATABASE=TAIWAN TRADING CENTER DBA + +OUI:00C0D8* + ID_OUI_FROM_DATABASE=UNIVERSAL DATA SYSTEMS + +OUI:00C0D9* + ID_OUI_FROM_DATABASE=QUINTE NETWORK CONFIDENTIALITY + +OUI:00C0DA* + ID_OUI_FROM_DATABASE=NICE SYSTEMS LTD. + +OUI:00C0DB* + ID_OUI_FROM_DATABASE=IPC CORPORATION (PTE) LTD. + +OUI:00C0DC* + ID_OUI_FROM_DATABASE=EOS TECHNOLOGIES, INC. + +OUI:00C0DD* + ID_OUI_FROM_DATABASE=QLogic Corporation + +OUI:00C0DE* + ID_OUI_FROM_DATABASE=ZCOMM, INC. + +OUI:00C0DF* + ID_OUI_FROM_DATABASE=KYE Systems Corp. + +OUI:00C0E0* + ID_OUI_FROM_DATABASE=DSC COMMUNICATION CORP. + +OUI:00C0E1* + ID_OUI_FROM_DATABASE=SONIC SOLUTIONS + +OUI:00C0E2* + ID_OUI_FROM_DATABASE=CALCOMP, INC. + +OUI:00C0E3* + ID_OUI_FROM_DATABASE=OSITECH COMMUNICATIONS, INC. + +OUI:00C0E4* + ID_OUI_FROM_DATABASE=SIEMENS BUILDING + +OUI:00C0E5* + ID_OUI_FROM_DATABASE=GESPAC, S.A. + +OUI:00C0E6* + ID_OUI_FROM_DATABASE=Verilink Corporation + +OUI:00C0E7* + ID_OUI_FROM_DATABASE=FIBERDATA AB + +OUI:00C0E8* + ID_OUI_FROM_DATABASE=PLEXCOM, INC. + +OUI:00C0E9* + ID_OUI_FROM_DATABASE=OAK SOLUTIONS, LTD. + +OUI:00C0EA* + ID_OUI_FROM_DATABASE=ARRAY TECHNOLOGY LTD. + +OUI:00C0EB* + ID_OUI_FROM_DATABASE=SEH COMPUTERTECHNIK GMBH + +OUI:00C0EC* + ID_OUI_FROM_DATABASE=DAUPHIN TECHNOLOGY + +OUI:00C0ED* + ID_OUI_FROM_DATABASE=US ARMY ELECTRONIC + +OUI:00C0EE* + ID_OUI_FROM_DATABASE=KYOCERA Display Corporation + +OUI:00C0EF* + ID_OUI_FROM_DATABASE=ABIT CORPORATION + +OUI:00C0F0* + ID_OUI_FROM_DATABASE=Kingston Technology Company, Inc. + +OUI:00C0F1* + ID_OUI_FROM_DATABASE=SHINKO ELECTRIC CO., LTD. + +OUI:00C0F2* + ID_OUI_FROM_DATABASE=TRANSITION NETWORKS + +OUI:00C0F3* + ID_OUI_FROM_DATABASE=NETWORK COMMUNICATIONS CORP. + +OUI:00C0F4* + ID_OUI_FROM_DATABASE=INTERLINK SYSTEM CO., LTD. + +OUI:00C0F5* + ID_OUI_FROM_DATABASE=METACOMP, INC. + +OUI:00C0F6* + ID_OUI_FROM_DATABASE=CELAN TECHNOLOGY INC. + +OUI:00C0F7* + ID_OUI_FROM_DATABASE=ENGAGE COMMUNICATION, INC. + +OUI:00C0F8* + ID_OUI_FROM_DATABASE=ABOUT COMPUTING INC. + +OUI:00C0F9* + ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies + +OUI:00C0FA* + ID_OUI_FROM_DATABASE=CANARY COMMUNICATIONS, INC. + +OUI:00C0FB* + ID_OUI_FROM_DATABASE=ADVANCED TECHNOLOGY LABS + +OUI:00C0FC* + ID_OUI_FROM_DATABASE=ELASTIC REALITY, INC. + +OUI:00C0FD* + ID_OUI_FROM_DATABASE=PROSUM + +OUI:00C0FE* + ID_OUI_FROM_DATABASE=APTEC COMPUTER SYSTEMS, INC. + +OUI:00C0FF* + ID_OUI_FROM_DATABASE=Seagate Cloud Systems Inc + +OUI:00C14F* + ID_OUI_FROM_DATABASE=DDL Co,.ltd. + +OUI:00C164* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00C1B1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00C2C6* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:00C3F4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00C5DB* + ID_OUI_FROM_DATABASE=Datatech Sistemas Digitales Avanzados SL + +OUI:00C610* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00C88B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00CAE5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00CB00* + ID_OUI_FROM_DATABASE=Private + +OUI:00CB51* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:00CBB4* + ID_OUI_FROM_DATABASE=SHENZHEN ATEKO PHOTOELECTRICITY CO.,LTD + +OUI:00CBBD* + ID_OUI_FROM_DATABASE=Cambridge Broadband Networks Ltd. + +OUI:00CC3F* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. + +OUI:00CCFC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00CD90* + ID_OUI_FROM_DATABASE=MAS Elektronik AG + +OUI:00CDFE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00CF1C* + ID_OUI_FROM_DATABASE=Communication Machinery Corporation + +OUI:00CFC0* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:00D000* + ID_OUI_FROM_DATABASE=FERRAN SCIENTIFIC, INC. + +OUI:00D001* + ID_OUI_FROM_DATABASE=VST TECHNOLOGIES, INC. + +OUI:00D002* + ID_OUI_FROM_DATABASE=DITECH CORPORATION + +OUI:00D003* + ID_OUI_FROM_DATABASE=COMDA ENTERPRISES CORP. + +OUI:00D004* + ID_OUI_FROM_DATABASE=PENTACOM LTD. + +OUI:00D005* + ID_OUI_FROM_DATABASE=ZHS ZEITMANAGEMENTSYSTEME + +OUI:00D006* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D007* + ID_OUI_FROM_DATABASE=MIC ASSOCIATES, INC. + +OUI:00D008* + ID_OUI_FROM_DATABASE=MACTELL CORPORATION + +OUI:00D009* + ID_OUI_FROM_DATABASE=HSING TECH. ENTERPRISE CO. LTD + +OUI:00D00A* + ID_OUI_FROM_DATABASE=LANACCESS TELECOM S.A. + +OUI:00D00B* + ID_OUI_FROM_DATABASE=RHK TECHNOLOGY, INC. + +OUI:00D00C* + ID_OUI_FROM_DATABASE=SNIJDER MICRO SYSTEMS + +OUI:00D00D* + ID_OUI_FROM_DATABASE=MICROMERITICS INSTRUMENT + +OUI:00D00E* + ID_OUI_FROM_DATABASE=PLURIS, INC. + +OUI:00D00F* + ID_OUI_FROM_DATABASE=SPEECH DESIGN GMBH + +OUI:00D010* + ID_OUI_FROM_DATABASE=CONVERGENT NETWORKS, INC. + +OUI:00D011* + ID_OUI_FROM_DATABASE=PRISM VIDEO, INC. + +OUI:00D012* + ID_OUI_FROM_DATABASE=GATEWORKS CORP. + +OUI:00D013* + ID_OUI_FROM_DATABASE=PRIMEX AEROSPACE COMPANY + +OUI:00D014* + ID_OUI_FROM_DATABASE=ROOT, INC. + +OUI:00D015* + ID_OUI_FROM_DATABASE=UNIVEX MICROTECHNOLOGY CORP. + +OUI:00D016* + ID_OUI_FROM_DATABASE=SCM MICROSYSTEMS, INC. + +OUI:00D017* + ID_OUI_FROM_DATABASE=SYNTECH INFORMATION CO., LTD. + +OUI:00D018* + ID_OUI_FROM_DATABASE=QWES. COM, INC. + +OUI:00D019* + ID_OUI_FROM_DATABASE=DAINIPPON SCREEN CORPORATE + +OUI:00D01A* + ID_OUI_FROM_DATABASE=URMET TLC S.P.A. + +OUI:00D01B* + ID_OUI_FROM_DATABASE=MIMAKI ENGINEERING CO., LTD. + +OUI:00D01C* + ID_OUI_FROM_DATABASE=SBS TECHNOLOGIES, + +OUI:00D01D* + ID_OUI_FROM_DATABASE=FURUNO ELECTRIC CO., LTD. + +OUI:00D01E* + ID_OUI_FROM_DATABASE=PINGTEL CORP. + +OUI:00D01F* + ID_OUI_FROM_DATABASE=Senetas Corporation Ltd + +OUI:00D020* + ID_OUI_FROM_DATABASE=AIM SYSTEM, INC. + +OUI:00D021* + ID_OUI_FROM_DATABASE=REGENT ELECTRONICS CORP. + +OUI:00D022* + ID_OUI_FROM_DATABASE=INCREDIBLE TECHNOLOGIES, INC. + +OUI:00D023* + ID_OUI_FROM_DATABASE=INFORTREND TECHNOLOGY, INC. + +OUI:00D024* + ID_OUI_FROM_DATABASE=Cognex Corporation + +OUI:00D025* + ID_OUI_FROM_DATABASE=XROSSTECH, INC. + +OUI:00D026* + ID_OUI_FROM_DATABASE=HIRSCHMANN AUSTRIA GMBH + +OUI:00D027* + ID_OUI_FROM_DATABASE=APPLIED AUTOMATION, INC. + +OUI:00D028* + ID_OUI_FROM_DATABASE=Harmonic, Inc + +OUI:00D029* + ID_OUI_FROM_DATABASE=WAKEFERN FOOD CORPORATION + +OUI:00D02A* + ID_OUI_FROM_DATABASE=Voxent Systems Ltd. + +OUI:00D02B* + ID_OUI_FROM_DATABASE=JETCELL, INC. + +OUI:00D02C* + ID_OUI_FROM_DATABASE=CAMPBELL SCIENTIFIC, INC. + +OUI:00D02D* + ID_OUI_FROM_DATABASE=Resideo + +OUI:00D02E* + ID_OUI_FROM_DATABASE=COMMUNICATION AUTOMATION CORP. + +OUI:00D02F* + ID_OUI_FROM_DATABASE=VLSI TECHNOLOGY INC. + +OUI:00D030* + ID_OUI_FROM_DATABASE=Safetran Systems Corp + +OUI:00D031* + ID_OUI_FROM_DATABASE=INDUSTRIAL LOGIC CORPORATION + +OUI:00D032* + ID_OUI_FROM_DATABASE=YANO ELECTRIC CO., LTD. + +OUI:00D033* + ID_OUI_FROM_DATABASE=DALIAN DAXIAN NETWORK + +OUI:00D034* + ID_OUI_FROM_DATABASE=ORMEC SYSTEMS CORP. + +OUI:00D035* + ID_OUI_FROM_DATABASE=BEHAVIOR TECH. COMPUTER CORP. + +OUI:00D036* + ID_OUI_FROM_DATABASE=TECHNOLOGY ATLANTA CORP. + +OUI:00D037* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00D038* + ID_OUI_FROM_DATABASE=FIVEMERE, LTD. + +OUI:00D039* + ID_OUI_FROM_DATABASE=UTILICOM, INC. + +OUI:00D03A* + ID_OUI_FROM_DATABASE=ZONEWORX, INC. + +OUI:00D03B* + ID_OUI_FROM_DATABASE=VISION PRODUCTS PTY. LTD. + +OUI:00D03C* + ID_OUI_FROM_DATABASE=Vieo, Inc. + +OUI:00D03D* + ID_OUI_FROM_DATABASE=GALILEO TECHNOLOGY, LTD. + +OUI:00D03E* + ID_OUI_FROM_DATABASE=ROCKETCHIPS, INC. + +OUI:00D03F* + ID_OUI_FROM_DATABASE=AMERICAN COMMUNICATION + +OUI:00D040* + ID_OUI_FROM_DATABASE=SYSMATE CO., LTD. + +OUI:00D041* + ID_OUI_FROM_DATABASE=AMIGO TECHNOLOGY CO., LTD. + +OUI:00D042* + ID_OUI_FROM_DATABASE=MAHLO GMBH & CO. UG + +OUI:00D043* + ID_OUI_FROM_DATABASE=ZONAL RETAIL DATA SYSTEMS + +OUI:00D044* + ID_OUI_FROM_DATABASE=ALIDIAN NETWORKS, INC. + +OUI:00D045* + ID_OUI_FROM_DATABASE=KVASER AB + +OUI:00D046* + ID_OUI_FROM_DATABASE=DOLBY LABORATORIES, INC. + +OUI:00D047* + ID_OUI_FROM_DATABASE=XN TECHNOLOGIES + +OUI:00D048* + ID_OUI_FROM_DATABASE=ECTON, INC. + +OUI:00D049* + ID_OUI_FROM_DATABASE=IMPRESSTEK CO., LTD. + +OUI:00D04A* + ID_OUI_FROM_DATABASE=PRESENCE TECHNOLOGY GMBH + +OUI:00D04B* + ID_OUI_FROM_DATABASE=LA CIE GROUP S.A. + +OUI:00D04C* + ID_OUI_FROM_DATABASE=EUROTEL TELECOM LTD. + +OUI:00D04D* + ID_OUI_FROM_DATABASE=DIV OF RESEARCH & STATISTICS + +OUI:00D04E* + ID_OUI_FROM_DATABASE=LOGIBAG + +OUI:00D04F* + ID_OUI_FROM_DATABASE=BITRONICS, INC. + +OUI:00D050* + ID_OUI_FROM_DATABASE=Iskratel d.o.o. + +OUI:00D051* + ID_OUI_FROM_DATABASE=O2 MICRO, INC. + +OUI:00D052* + ID_OUI_FROM_DATABASE=ASCEND COMMUNICATIONS, INC. + +OUI:00D053* + ID_OUI_FROM_DATABASE=CONNECTED SYSTEMS + +OUI:00D054* + ID_OUI_FROM_DATABASE=SAS INSTITUTE INC. + +OUI:00D055* + ID_OUI_FROM_DATABASE=KATHREIN-WERKE KG + +OUI:00D056* + ID_OUI_FROM_DATABASE=SOMAT CORPORATION + +OUI:00D057* + ID_OUI_FROM_DATABASE=ULTRAK, INC. + +OUI:00D058* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D059* + ID_OUI_FROM_DATABASE=AMBIT MICROSYSTEMS CORP. + +OUI:00D05A* + ID_OUI_FROM_DATABASE=SYMBIONICS, LTD. + +OUI:00D05B* + ID_OUI_FROM_DATABASE=ACROLOOP MOTION CONTROL + +OUI:00D05C* + ID_OUI_FROM_DATABASE=KATHREIN TechnoTrend GmbH + +OUI:00D05D* + ID_OUI_FROM_DATABASE=INTELLIWORXX, INC. + +OUI:00D05E* + ID_OUI_FROM_DATABASE=STRATABEAM TECHNOLOGY, INC. + +OUI:00D05F* + ID_OUI_FROM_DATABASE=VALCOM, INC. + +OUI:00D060* + ID_OUI_FROM_DATABASE=Panasonic Europe Ltd. + +OUI:00D061* + ID_OUI_FROM_DATABASE=TREMON ENTERPRISES CO., LTD. + +OUI:00D062* + ID_OUI_FROM_DATABASE=DIGIGRAM + +OUI:00D063* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D064* + ID_OUI_FROM_DATABASE=MULTITEL + +OUI:00D065* + ID_OUI_FROM_DATABASE=TOKO ELECTRIC + +OUI:00D066* + ID_OUI_FROM_DATABASE=WINTRISS ENGINEERING CORP. + +OUI:00D067* + ID_OUI_FROM_DATABASE=CAMPIO COMMUNICATIONS + +OUI:00D068* + ID_OUI_FROM_DATABASE=IWILL CORPORATION + +OUI:00D069* + ID_OUI_FROM_DATABASE=TECHNOLOGIC SYSTEMS + +OUI:00D06A* + ID_OUI_FROM_DATABASE=LINKUP SYSTEMS CORPORATION + +OUI:00D06B* + ID_OUI_FROM_DATABASE=SR TELECOM INC. + +OUI:00D06C* + ID_OUI_FROM_DATABASE=SHAREWAVE, INC. + +OUI:00D06D* + ID_OUI_FROM_DATABASE=ACRISON, INC. + +OUI:00D06E* + ID_OUI_FROM_DATABASE=TRENDVIEW RECORDERS LTD. + +OUI:00D06F* + ID_OUI_FROM_DATABASE=KMC CONTROLS + +OUI:00D070* + ID_OUI_FROM_DATABASE=LONG WELL ELECTRONICS CORP. + +OUI:00D071* + ID_OUI_FROM_DATABASE=ECHELON CORP. + +OUI:00D072* + ID_OUI_FROM_DATABASE=BROADLOGIC + +OUI:00D073* + ID_OUI_FROM_DATABASE=ACN ADVANCED COMMUNICATIONS + +OUI:00D074* + ID_OUI_FROM_DATABASE=TAQUA SYSTEMS, INC. + +OUI:00D075* + ID_OUI_FROM_DATABASE=ALARIS MEDICAL SYSTEMS, INC. + +OUI:00D076* + ID_OUI_FROM_DATABASE=Bank of America + +OUI:00D077* + ID_OUI_FROM_DATABASE=LUCENT TECHNOLOGIES + +OUI:00D078* + ID_OUI_FROM_DATABASE=Eltex of Sweden AB + +OUI:00D079* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D07A* + ID_OUI_FROM_DATABASE=AMAQUEST COMPUTER CORP. + +OUI:00D07B* + ID_OUI_FROM_DATABASE=COMCAM INTERNATIONAL INC + +OUI:00D07C* + ID_OUI_FROM_DATABASE=KOYO ELECTRONICS INC. CO.,LTD. + +OUI:00D07D* + ID_OUI_FROM_DATABASE=COSINE COMMUNICATIONS + +OUI:00D07E* + ID_OUI_FROM_DATABASE=KEYCORP LTD. + +OUI:00D07F* + ID_OUI_FROM_DATABASE=STRATEGY & TECHNOLOGY, LIMITED + +OUI:00D080* + ID_OUI_FROM_DATABASE=EXABYTE CORPORATION + +OUI:00D081* + ID_OUI_FROM_DATABASE=RTD Embedded Technologies, Inc. + +OUI:00D082* + ID_OUI_FROM_DATABASE=IOWAVE INC. + +OUI:00D083* + ID_OUI_FROM_DATABASE=INVERTEX, INC. + +OUI:00D084* + ID_OUI_FROM_DATABASE=NEXCOMM SYSTEMS, INC. + +OUI:00D085* + ID_OUI_FROM_DATABASE=OTIS ELEVATOR COMPANY + +OUI:00D086* + ID_OUI_FROM_DATABASE=FOVEON, INC. + +OUI:00D087* + ID_OUI_FROM_DATABASE=MICROFIRST INC. + +OUI:00D088* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00D089* + ID_OUI_FROM_DATABASE=DYNACOLOR, INC. + +OUI:00D08A* + ID_OUI_FROM_DATABASE=PHOTRON USA + +OUI:00D08B* + ID_OUI_FROM_DATABASE=ADVA Optical Networking Ltd. + +OUI:00D08C* + ID_OUI_FROM_DATABASE=GENOA TECHNOLOGY, INC. + +OUI:00D08D* + ID_OUI_FROM_DATABASE=PHOENIX GROUP, INC. + +OUI:00D08E* + ID_OUI_FROM_DATABASE=Grass Valley, A Belden Brand + +OUI:00D08F* + ID_OUI_FROM_DATABASE=ARDENT TECHNOLOGIES, INC. + +OUI:00D090* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D091* + ID_OUI_FROM_DATABASE=SMARTSAN SYSTEMS, INC. + +OUI:00D092* + ID_OUI_FROM_DATABASE=GLENAYRE WESTERN MULTIPLEX + +OUI:00D093* + ID_OUI_FROM_DATABASE=TQ - COMPONENTS GMBH + +OUI:00D094* + ID_OUI_FROM_DATABASE=Seeion Control LLC + +OUI:00D095* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise + +OUI:00D096* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:00D097* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D098* + ID_OUI_FROM_DATABASE=Photon Dynamics Canada Inc. + +OUI:00D099* + ID_OUI_FROM_DATABASE=Elcard Wireless Systems Oy + +OUI:00D09A* + ID_OUI_FROM_DATABASE=FILANET CORPORATION + +OUI:00D09B* + ID_OUI_FROM_DATABASE=SPECTEL LTD. + +OUI:00D09C* + ID_OUI_FROM_DATABASE=KAPADIA COMMUNICATIONS + +OUI:00D09D* + ID_OUI_FROM_DATABASE=VERIS INDUSTRIES + +OUI:00D09E* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:00D09F* + ID_OUI_FROM_DATABASE=NOVTEK TEST SYSTEMS + +OUI:00D0A0* + ID_OUI_FROM_DATABASE=MIPS DENMARK + +OUI:00D0A1* + ID_OUI_FROM_DATABASE=OSKAR VIERLING GMBH + CO. KG + +OUI:00D0A2* + ID_OUI_FROM_DATABASE=INTEGRATED DEVICE + +OUI:00D0A3* + ID_OUI_FROM_DATABASE=VOCAL DATA, INC. + +OUI:00D0A4* + ID_OUI_FROM_DATABASE=ALANTRO COMMUNICATIONS + +OUI:00D0A5* + ID_OUI_FROM_DATABASE=AMERICAN ARIUM + +OUI:00D0A6* + ID_OUI_FROM_DATABASE=LANBIRD TECHNOLOGY CO., LTD. + +OUI:00D0A7* + ID_OUI_FROM_DATABASE=TOKYO SOKKI KENKYUJO CO., LTD. + +OUI:00D0A8* + ID_OUI_FROM_DATABASE=NETWORK ENGINES, INC. + +OUI:00D0A9* + ID_OUI_FROM_DATABASE=SHINANO KENSHI CO., LTD. + +OUI:00D0AA* + ID_OUI_FROM_DATABASE=CHASE COMMUNICATIONS + +OUI:00D0AB* + ID_OUI_FROM_DATABASE=DELTAKABEL TELECOM CV + +OUI:00D0AC* + ID_OUI_FROM_DATABASE=Commscope, Inc + +OUI:00D0AD* + ID_OUI_FROM_DATABASE=TL INDUSTRIES + +OUI:00D0AE* + ID_OUI_FROM_DATABASE=ORESIS COMMUNICATIONS, INC. + +OUI:00D0AF* + ID_OUI_FROM_DATABASE=CUTLER-HAMMER, INC. + +OUI:00D0B0* + ID_OUI_FROM_DATABASE=BITSWITCH LTD. + +OUI:00D0B1* + ID_OUI_FROM_DATABASE=OMEGA ELECTRONICS SA + +OUI:00D0B2* + ID_OUI_FROM_DATABASE=Xiotech Corporation + +OUI:00D0B3* + ID_OUI_FROM_DATABASE=DRS Technologies Canada Ltd + +OUI:00D0B4* + ID_OUI_FROM_DATABASE=KATSUJIMA CO., LTD. + +OUI:00D0B5* + ID_OUI_FROM_DATABASE=IPricot formerly DotCom + +OUI:00D0B6* + ID_OUI_FROM_DATABASE=CRESCENT NETWORKS, INC. + +OUI:00D0B7* + ID_OUI_FROM_DATABASE=Intel Corporation + +OUI:00D0B8* + ID_OUI_FROM_DATABASE=Iomega Corporation + +OUI:00D0B9* + ID_OUI_FROM_DATABASE=MICROTEK INTERNATIONAL, INC. + +OUI:00D0BA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D0BB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D0BC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D0BD* + ID_OUI_FROM_DATABASE=Lattice Semiconductor Corp. (LPA) + +OUI:00D0BE* + ID_OUI_FROM_DATABASE=EMUTEC INC. + +OUI:00D0BF* + ID_OUI_FROM_DATABASE=PIVOTAL TECHNOLOGIES + +OUI:00D0C0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D0C1* + ID_OUI_FROM_DATABASE=HARMONIC DATA SYSTEMS, LTD. + +OUI:00D0C2* + ID_OUI_FROM_DATABASE=BALTHAZAR TECHNOLOGY AB + +OUI:00D0C3* + ID_OUI_FROM_DATABASE=VIVID TECHNOLOGY PTE, LTD. + +OUI:00D0C4* + ID_OUI_FROM_DATABASE=TERATECH CORPORATION + +OUI:00D0C5* + ID_OUI_FROM_DATABASE=COMPUTATIONAL SYSTEMS, INC. + +OUI:00D0C6* + ID_OUI_FROM_DATABASE=THOMAS & BETTS CORP. + +OUI:00D0C7* + ID_OUI_FROM_DATABASE=PATHWAY, INC. + +OUI:00D0C8* + ID_OUI_FROM_DATABASE=Prevas A/S + +OUI:00D0C9* + ID_OUI_FROM_DATABASE=ADVANTECH CO., LTD. + +OUI:00D0CA* + ID_OUI_FROM_DATABASE=Intrinsyc Software International Inc. + +OUI:00D0CB* + ID_OUI_FROM_DATABASE=DASAN CO., LTD. + +OUI:00D0CC* + ID_OUI_FROM_DATABASE=TECHNOLOGIES LYRE INC. + +OUI:00D0CD* + ID_OUI_FROM_DATABASE=ATAN TECHNOLOGY INC. + +OUI:00D0CE* + ID_OUI_FROM_DATABASE=iSystem Labs + +OUI:00D0CF* + ID_OUI_FROM_DATABASE=MORETON BAY + +OUI:00D0D0* + ID_OUI_FROM_DATABASE=ZHONGXING TELECOM LTD. + +OUI:00D0D1* + ID_OUI_FROM_DATABASE=Sycamore Networks + +OUI:00D0D2* + ID_OUI_FROM_DATABASE=EPILOG CORPORATION + +OUI:00D0D3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D0D4* + ID_OUI_FROM_DATABASE=V-BITS, INC. + +OUI:00D0D5* + ID_OUI_FROM_DATABASE=GRUNDIG AG + +OUI:00D0D6* + ID_OUI_FROM_DATABASE=AETHRA TELECOMUNICAZIONI + +OUI:00D0D7* + ID_OUI_FROM_DATABASE=B2C2, INC. + +OUI:00D0D8* + ID_OUI_FROM_DATABASE=3COM + +OUI:00D0D9* + ID_OUI_FROM_DATABASE=DEDICATED MICROCOMPUTERS + +OUI:00D0DA* + ID_OUI_FROM_DATABASE=TAICOM DATA SYSTEMS CO., LTD. + +OUI:00D0DB* + ID_OUI_FROM_DATABASE=MCQUAY INTERNATIONAL + +OUI:00D0DC* + ID_OUI_FROM_DATABASE=MODULAR MINING SYSTEMS, INC. + +OUI:00D0DD* + ID_OUI_FROM_DATABASE=SUNRISE TELECOM, INC. + +OUI:00D0DE* + ID_OUI_FROM_DATABASE=PHILIPS MULTIMEDIA NETWORK + +OUI:00D0DF* + ID_OUI_FROM_DATABASE=KUZUMI ELECTRONICS, INC. + +OUI:00D0E0* + ID_OUI_FROM_DATABASE=DOOIN ELECTRONICS CO. + +OUI:00D0E1* + ID_OUI_FROM_DATABASE=AVIONITEK ISRAEL INC. + +OUI:00D0E2* + ID_OUI_FROM_DATABASE=MRT MICRO, INC. + +OUI:00D0E3* + ID_OUI_FROM_DATABASE=ELE-CHEM ENGINEERING CO., LTD. + +OUI:00D0E4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D0E5* + ID_OUI_FROM_DATABASE=SOLIDUM SYSTEMS CORP. + +OUI:00D0E6* + ID_OUI_FROM_DATABASE=IBOND INC. + +OUI:00D0E7* + ID_OUI_FROM_DATABASE=VCON TELECOMMUNICATION LTD. + +OUI:00D0E8* + ID_OUI_FROM_DATABASE=MAC SYSTEM CO., LTD. + +OUI:00D0E9* + ID_OUI_FROM_DATABASE=Advantage Century Telecommunication Corp. + +OUI:00D0EA* + ID_OUI_FROM_DATABASE=NEXTONE COMMUNICATIONS, INC. + +OUI:00D0EB* + ID_OUI_FROM_DATABASE=LIGHTERA NETWORKS, INC. + +OUI:00D0EC* + ID_OUI_FROM_DATABASE=NAKAYO Inc + +OUI:00D0ED* + ID_OUI_FROM_DATABASE=XIOX + +OUI:00D0EE* + ID_OUI_FROM_DATABASE=DICTAPHONE CORPORATION + +OUI:00D0EF* + ID_OUI_FROM_DATABASE=IGT + +OUI:00D0F0* + ID_OUI_FROM_DATABASE=CONVISION TECHNOLOGY GMBH + +OUI:00D0F1* + ID_OUI_FROM_DATABASE=SEGA ENTERPRISES, LTD. + +OUI:00D0F2* + ID_OUI_FROM_DATABASE=MONTEREY NETWORKS + +OUI:00D0F3* + ID_OUI_FROM_DATABASE=SOLARI DI UDINE SPA + +OUI:00D0F4* + ID_OUI_FROM_DATABASE=CARINTHIAN TECH INSTITUTE + +OUI:00D0F5* + ID_OUI_FROM_DATABASE=ORANGE MICRO, INC. + +OUI:00D0F6* + ID_OUI_FROM_DATABASE=Nokia + +OUI:00D0F7* + ID_OUI_FROM_DATABASE=NEXT NETS CORPORATION + +OUI:00D0F8* + ID_OUI_FROM_DATABASE=FUJIAN STAR TERMINAL + +OUI:00D0F9* + ID_OUI_FROM_DATABASE=ACUTE COMMUNICATIONS CORP. + +OUI:00D0FA* + ID_OUI_FROM_DATABASE=Thales e-Security Ltd. + +OUI:00D0FB* + ID_OUI_FROM_DATABASE=TEK MICROSYSTEMS, INCORPORATED + +OUI:00D0FC* + ID_OUI_FROM_DATABASE=GRANITE MICROSYSTEMS + +OUI:00D0FD* + ID_OUI_FROM_DATABASE=OPTIMA TELE.COM, INC. + +OUI:00D0FE* + ID_OUI_FROM_DATABASE=ASTRAL POINT + +OUI:00D0FF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D11C* + ID_OUI_FROM_DATABASE=ACETEL + +OUI:00D279* + ID_OUI_FROM_DATABASE=VINGROUP JOINT STOCK COMPANY + +OUI:00D2B1* + ID_OUI_FROM_DATABASE=TPV Display Technology (Xiamen) Co.,Ltd. + +OUI:00D318* + ID_OUI_FROM_DATABASE=SPG Controls + +OUI:00D38D* + ID_OUI_FROM_DATABASE=Hotel Technology Next Generation + +OUI:00D632* + ID_OUI_FROM_DATABASE=GE Energy + +OUI:00D6FE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D78F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00D861* + ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD. + +OUI:00D9D1* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:00DA55* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00DB1E* + ID_OUI_FROM_DATABASE=Albedo Telecom SL + +OUI:00DB45* + ID_OUI_FROM_DATABASE=THAMWAY CO.,LTD. + +OUI:00DB70* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00DBDF* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:00DD00* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD01* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD02* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD03* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD04* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD05* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD06* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD07* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD08* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD09* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD0A* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD0B* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD0C* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD0D* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD0E* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD0F* + ID_OUI_FROM_DATABASE=UNGERMANN-BASS INC. + +OUI:00DD25* + ID_OUI_FROM_DATABASE=Shenzhen hechengdong Technology Co., Ltd + +OUI:00DEFB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E000* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:00E001* + ID_OUI_FROM_DATABASE=STRAND LIGHTING LIMITED + +OUI:00E002* + ID_OUI_FROM_DATABASE=CROSSROADS SYSTEMS, INC. + +OUI:00E003* + ID_OUI_FROM_DATABASE=NOKIA WIRELESS BUSINESS COMMUN + +OUI:00E004* + ID_OUI_FROM_DATABASE=PMC-SIERRA, INC. + +OUI:00E005* + ID_OUI_FROM_DATABASE=TECHNICAL CORP. + +OUI:00E006* + ID_OUI_FROM_DATABASE=SILICON INTEGRATED SYS. CORP. + +OUI:00E007* + ID_OUI_FROM_DATABASE=Avaya ECS Ltd + +OUI:00E008* + ID_OUI_FROM_DATABASE=AMAZING CONTROLS! INC. + +OUI:00E009* + ID_OUI_FROM_DATABASE=Stratus Technologies + +OUI:00E00A* + ID_OUI_FROM_DATABASE=DIBA, INC. + +OUI:00E00B* + ID_OUI_FROM_DATABASE=ROOFTOP COMMUNICATIONS CORP. + +OUI:00E00C* + ID_OUI_FROM_DATABASE=MOTOROLA + +OUI:00E00D* + ID_OUI_FROM_DATABASE=RADIANT SYSTEMS + +OUI:00E00E* + ID_OUI_FROM_DATABASE=AVALON IMAGING SYSTEMS, INC. + +OUI:00E00F* + ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd. + +OUI:00E010* + ID_OUI_FROM_DATABASE=HESS SB-AUTOMATENBAU GmbH + +OUI:00E011* + ID_OUI_FROM_DATABASE=UNIDEN CORPORATION + +OUI:00E012* + ID_OUI_FROM_DATABASE=PLUTO TECHNOLOGIES INTERNATIONAL INC. + +OUI:00E013* + ID_OUI_FROM_DATABASE=EASTERN ELECTRONIC CO., LTD. + +OUI:00E014* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E015* + ID_OUI_FROM_DATABASE=HEIWA CORPORATION + +OUI:00E016* + ID_OUI_FROM_DATABASE=RAPID CITY COMMUNICATIONS + +OUI:00E017* + ID_OUI_FROM_DATABASE=EXXACT GmbH + +OUI:00E018* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:00E019* + ID_OUI_FROM_DATABASE=ING. GIORDANO ELETTRONICA + +OUI:00E01A* + ID_OUI_FROM_DATABASE=COMTEC SYSTEMS. CO., LTD. + +OUI:00E01B* + ID_OUI_FROM_DATABASE=SPHERE COMMUNICATIONS, INC. + +OUI:00E01C* + ID_OUI_FROM_DATABASE=Cradlepoint, Inc + +OUI:00E01D* + ID_OUI_FROM_DATABASE=WebTV NETWORKS, INC. + +OUI:00E01E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E01F* + ID_OUI_FROM_DATABASE=AVIDIA Systems, Inc. + +OUI:00E020* + ID_OUI_FROM_DATABASE=TECNOMEN OY + +OUI:00E021* + ID_OUI_FROM_DATABASE=FREEGATE CORP. + +OUI:00E022* + ID_OUI_FROM_DATABASE=Analog Devices, Inc. + +OUI:00E023* + ID_OUI_FROM_DATABASE=TELRAD + +OUI:00E024* + ID_OUI_FROM_DATABASE=GADZOOX NETWORKS + +OUI:00E025* + ID_OUI_FROM_DATABASE=dit Co., Ltd. + +OUI:00E026* + ID_OUI_FROM_DATABASE=Redlake MASD LLC + +OUI:00E027* + ID_OUI_FROM_DATABASE=DUX, INC. + +OUI:00E028* + ID_OUI_FROM_DATABASE=APTIX CORPORATION + +OUI:00E029* + ID_OUI_FROM_DATABASE=STANDARD MICROSYSTEMS CORP. + +OUI:00E02A* + ID_OUI_FROM_DATABASE=TANDBERG TELEVISION AS + +OUI:00E02B* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:00E02C* + ID_OUI_FROM_DATABASE=AST COMPUTER + +OUI:00E02D* + ID_OUI_FROM_DATABASE=InnoMediaLogic, Inc. + +OUI:00E02E* + ID_OUI_FROM_DATABASE=SPC ELECTRONICS CORPORATION + +OUI:00E02F* + ID_OUI_FROM_DATABASE=MCNS HOLDINGS, L.P. + +OUI:00E030* + ID_OUI_FROM_DATABASE=MELITA INTERNATIONAL CORP. + +OUI:00E031* + ID_OUI_FROM_DATABASE=HAGIWARA ELECTRIC CO., LTD. + +OUI:00E032* + ID_OUI_FROM_DATABASE=MISYS FINANCIAL SYSTEMS, LTD. + +OUI:00E033* + ID_OUI_FROM_DATABASE=E.E.P.D. GmbH + +OUI:00E034* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E035* + ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies + +OUI:00E036* + ID_OUI_FROM_DATABASE=PIONEER CORPORATION + +OUI:00E037* + ID_OUI_FROM_DATABASE=CENTURY CORPORATION + +OUI:00E038* + ID_OUI_FROM_DATABASE=PROXIMA CORPORATION + +OUI:00E039* + ID_OUI_FROM_DATABASE=PARADYNE CORP. + +OUI:00E03A* + ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. + +OUI:00E03B* + ID_OUI_FROM_DATABASE=PROMINET CORPORATION + +OUI:00E03C* + ID_OUI_FROM_DATABASE=AdvanSys + +OUI:00E03D* + ID_OUI_FROM_DATABASE=FOCON ELECTRONIC SYSTEMS A/S + +OUI:00E03E* + ID_OUI_FROM_DATABASE=ALFATECH, INC. + +OUI:00E03F* + ID_OUI_FROM_DATABASE=JATON CORPORATION + +OUI:00E040* + ID_OUI_FROM_DATABASE=DeskStation Technology, Inc. + +OUI:00E041* + ID_OUI_FROM_DATABASE=CSPI + +OUI:00E042* + ID_OUI_FROM_DATABASE=Pacom Systems Ltd. + +OUI:00E043* + ID_OUI_FROM_DATABASE=VitalCom + +OUI:00E044* + ID_OUI_FROM_DATABASE=LSICS CORPORATION + +OUI:00E045* + ID_OUI_FROM_DATABASE=TOUCHWAVE, INC. + +OUI:00E046* + ID_OUI_FROM_DATABASE=BENTLY NEVADA CORP. + +OUI:00E047* + ID_OUI_FROM_DATABASE=InFocus Corporation + +OUI:00E048* + ID_OUI_FROM_DATABASE=SDL COMMUNICATIONS, INC. + +OUI:00E049* + ID_OUI_FROM_DATABASE=MICROWI ELECTRONIC GmbH + +OUI:00E04A* + ID_OUI_FROM_DATABASE=ZX Technologies, Inc + +OUI:00E04B* + ID_OUI_FROM_DATABASE=JUMP INDUSTRIELLE COMPUTERTECHNIK GmbH + +OUI:00E04C* + ID_OUI_FROM_DATABASE=REALTEK SEMICONDUCTOR CORP. + +OUI:00E04D* + ID_OUI_FROM_DATABASE=INTERNET INITIATIVE JAPAN, INC + +OUI:00E04E* + ID_OUI_FROM_DATABASE=SANYO DENKI CO., LTD. + +OUI:00E04F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E050* + ID_OUI_FROM_DATABASE=EXECUTONE INFORMATION SYSTEMS, INC. + +OUI:00E051* + ID_OUI_FROM_DATABASE=TALX CORPORATION + +OUI:00E052* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:00E053* + ID_OUI_FROM_DATABASE=CELLPORT LABS, INC. + +OUI:00E054* + ID_OUI_FROM_DATABASE=KODAI HITEC CO., LTD. + +OUI:00E055* + ID_OUI_FROM_DATABASE=INGENIERIA ELECTRONICA COMERCIAL INELCOM S.A. + +OUI:00E056* + ID_OUI_FROM_DATABASE=HOLONTECH CORPORATION + +OUI:00E057* + ID_OUI_FROM_DATABASE=HAN MICROTELECOM. CO., LTD. + +OUI:00E058* + ID_OUI_FROM_DATABASE=PHASE ONE DENMARK A/S + +OUI:00E059* + ID_OUI_FROM_DATABASE=CONTROLLED ENVIRONMENTS, LTD. + +OUI:00E05A* + ID_OUI_FROM_DATABASE=GALEA NETWORK SECURITY + +OUI:00E05B* + ID_OUI_FROM_DATABASE=WEST END SYSTEMS CORP. + +OUI:00E05C* + ID_OUI_FROM_DATABASE=PHC Corporation + +OUI:00E05D* + ID_OUI_FROM_DATABASE=UNITEC CO., LTD. + +OUI:00E05E* + ID_OUI_FROM_DATABASE=JAPAN AVIATION ELECTRONICS INDUSTRY, LTD. + +OUI:00E05F* + ID_OUI_FROM_DATABASE=e-Net, Inc. + +OUI:00E060* + ID_OUI_FROM_DATABASE=SHERWOOD + +OUI:00E061* + ID_OUI_FROM_DATABASE=EdgePoint Networks, Inc. + +OUI:00E062* + ID_OUI_FROM_DATABASE=HOST ENGINEERING + +OUI:00E063* + ID_OUI_FROM_DATABASE=Cabletron Systems, Inc. + +OUI:00E064* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRONICS + +OUI:00E065* + ID_OUI_FROM_DATABASE=OPTICAL ACCESS INTERNATIONAL + +OUI:00E066* + ID_OUI_FROM_DATABASE=ProMax Systems, Inc. + +OUI:00E067* + ID_OUI_FROM_DATABASE=eac AUTOMATION-CONSULTING GmbH + +OUI:00E068* + ID_OUI_FROM_DATABASE=MERRIMAC SYSTEMS INC. + +OUI:00E069* + ID_OUI_FROM_DATABASE=JAYCOR + +OUI:00E06A* + ID_OUI_FROM_DATABASE=KAPSCH AG + +OUI:00E06B* + ID_OUI_FROM_DATABASE=W&G SPECIAL PRODUCTS + +OUI:00E06C* + ID_OUI_FROM_DATABASE=Ultra Electronics Command & Control Systems + +OUI:00E06D* + ID_OUI_FROM_DATABASE=COMPUWARE CORPORATION + +OUI:00E06E* + ID_OUI_FROM_DATABASE=FAR SYSTEMS S.p.A. + +OUI:00E06F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:00E070* + ID_OUI_FROM_DATABASE=DH TECHNOLOGY + +OUI:00E071* + ID_OUI_FROM_DATABASE=EPIS MICROCOMPUTER + +OUI:00E072* + ID_OUI_FROM_DATABASE=LYNK + +OUI:00E073* + ID_OUI_FROM_DATABASE=NATIONAL AMUSEMENT NETWORK, INC. + +OUI:00E074* + ID_OUI_FROM_DATABASE=TIERNAN COMMUNICATIONS, INC. + +OUI:00E075* + ID_OUI_FROM_DATABASE=Verilink Corporation + +OUI:00E076* + ID_OUI_FROM_DATABASE=DEVELOPMENT CONCEPTS, INC. + +OUI:00E077* + ID_OUI_FROM_DATABASE=WEBGEAR, INC. + +OUI:00E078* + ID_OUI_FROM_DATABASE=BERKELEY NETWORKS + +OUI:00E079* + ID_OUI_FROM_DATABASE=A.T.N.R. + +OUI:00E07A* + ID_OUI_FROM_DATABASE=MIKRODIDAKT AB + +OUI:00E07B* + ID_OUI_FROM_DATABASE=BAY NETWORKS + +OUI:00E07C* + ID_OUI_FROM_DATABASE=METTLER-TOLEDO, INC. + +OUI:00E07D* + ID_OUI_FROM_DATABASE=NETRONIX, INC. + +OUI:00E07E* + ID_OUI_FROM_DATABASE=WALT DISNEY IMAGINEERING + +OUI:00E07F* + ID_OUI_FROM_DATABASE=LOGISTISTEM s.r.l. + +OUI:00E080* + ID_OUI_FROM_DATABASE=CONTROL RESOURCES CORPORATION + +OUI:00E081* + ID_OUI_FROM_DATABASE=TYAN COMPUTER CORP. + +OUI:00E082* + ID_OUI_FROM_DATABASE=ANERMA + +OUI:00E083* + ID_OUI_FROM_DATABASE=JATO TECHNOLOGIES, INC. + +OUI:00E084* + ID_OUI_FROM_DATABASE=COMPULITE R&D + +OUI:00E085* + ID_OUI_FROM_DATABASE=GLOBAL MAINTECH, INC. + +OUI:00E086* + ID_OUI_FROM_DATABASE=Emerson Network Power, Avocent Division + +OUI:00E087* + ID_OUI_FROM_DATABASE=LeCroy - Networking Productions Division + +OUI:00E088* + ID_OUI_FROM_DATABASE=LTX-Credence CORPORATION + +OUI:00E089* + ID_OUI_FROM_DATABASE=ION Networks, Inc. + +OUI:00E08A* + ID_OUI_FROM_DATABASE=GEC AVERY, LTD. + +OUI:00E08B* + ID_OUI_FROM_DATABASE=QLogic Corporation + +OUI:00E08C* + ID_OUI_FROM_DATABASE=NEOPARADIGM LABS, INC. + +OUI:00E08D* + ID_OUI_FROM_DATABASE=PRESSURE SYSTEMS, INC. + +OUI:00E08E* + ID_OUI_FROM_DATABASE=UTSTARCOM + +OUI:00E08F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E090* + ID_OUI_FROM_DATABASE=BECKMAN LAB. AUTOMATION DIV. + +OUI:00E091* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:00E092* + ID_OUI_FROM_DATABASE=ADMTEK INCORPORATED + +OUI:00E093* + ID_OUI_FROM_DATABASE=ACKFIN NETWORKS + +OUI:00E094* + ID_OUI_FROM_DATABASE=OSAI SRL + +OUI:00E095* + ID_OUI_FROM_DATABASE=ADVANCED-VISION TECHNOLGIES CORP. + +OUI:00E096* + ID_OUI_FROM_DATABASE=SHIMADZU CORPORATION + +OUI:00E097* + ID_OUI_FROM_DATABASE=CARRIER ACCESS CORPORATION + +OUI:00E098* + ID_OUI_FROM_DATABASE=AboCom + +OUI:00E099* + ID_OUI_FROM_DATABASE=SAMSON AG + +OUI:00E09A* + ID_OUI_FROM_DATABASE=Positron Inc. + +OUI:00E09B* + ID_OUI_FROM_DATABASE=ENGAGE NETWORKS, INC. + +OUI:00E09C* + ID_OUI_FROM_DATABASE=MII + +OUI:00E09D* + ID_OUI_FROM_DATABASE=SARNOFF CORPORATION + +OUI:00E09E* + ID_OUI_FROM_DATABASE=Quantum Corporation + +OUI:00E09F* + ID_OUI_FROM_DATABASE=PIXEL VISION + +OUI:00E0A0* + ID_OUI_FROM_DATABASE=WILTRON CO. + +OUI:00E0A1* + ID_OUI_FROM_DATABASE=HIMA PAUL HILDEBRANDT GmbH Co. KG + +OUI:00E0A2* + ID_OUI_FROM_DATABASE=MICROSLATE INC. + +OUI:00E0A3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E0A4* + ID_OUI_FROM_DATABASE=ESAOTE S.p.A. + +OUI:00E0A5* + ID_OUI_FROM_DATABASE=ComCore Semiconductor, Inc. + +OUI:00E0A6* + ID_OUI_FROM_DATABASE=TELOGY NETWORKS, INC. + +OUI:00E0A7* + ID_OUI_FROM_DATABASE=IPC INFORMATION SYSTEMS, INC. + +OUI:00E0A8* + ID_OUI_FROM_DATABASE=SAT GmbH & Co. + +OUI:00E0A9* + ID_OUI_FROM_DATABASE=FUNAI ELECTRIC CO., LTD. + +OUI:00E0AA* + ID_OUI_FROM_DATABASE=ELECTROSONIC LTD. + +OUI:00E0AB* + ID_OUI_FROM_DATABASE=DIMAT S.A. + +OUI:00E0AC* + ID_OUI_FROM_DATABASE=MIDSCO, INC. + +OUI:00E0AD* + ID_OUI_FROM_DATABASE=EES TECHNOLOGY, LTD. + +OUI:00E0AE* + ID_OUI_FROM_DATABASE=XAQTI CORPORATION + +OUI:00E0AF* + ID_OUI_FROM_DATABASE=GENERAL DYNAMICS INFORMATION SYSTEMS + +OUI:00E0B0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E0B1* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise + +OUI:00E0B2* + ID_OUI_FROM_DATABASE=TELMAX COMMUNICATIONS CORP. + +OUI:00E0B3* + ID_OUI_FROM_DATABASE=EtherWAN Systems, Inc. + +OUI:00E0B4* + ID_OUI_FROM_DATABASE=TECHNO SCOPE CO., LTD. + +OUI:00E0B5* + ID_OUI_FROM_DATABASE=ARDENT COMMUNICATIONS CORP. + +OUI:00E0B6* + ID_OUI_FROM_DATABASE=Entrada Networks + +OUI:00E0B7* + ID_OUI_FROM_DATABASE=PI GROUP, LTD. + +OUI:00E0B8* + ID_OUI_FROM_DATABASE=GATEWAY 2000 + +OUI:00E0B9* + ID_OUI_FROM_DATABASE=BYAS SYSTEMS + +OUI:00E0BA* + ID_OUI_FROM_DATABASE=BERGHOF AUTOMATIONSTECHNIK GmbH + +OUI:00E0BB* + ID_OUI_FROM_DATABASE=NBX CORPORATION + +OUI:00E0BC* + ID_OUI_FROM_DATABASE=SYMON COMMUNICATIONS, INC. + +OUI:00E0BD* + ID_OUI_FROM_DATABASE=INTERFACE SYSTEMS, INC. + +OUI:00E0BE* + ID_OUI_FROM_DATABASE=GENROCO INTERNATIONAL, INC. + +OUI:00E0BF* + ID_OUI_FROM_DATABASE=TORRENT NETWORKING TECHNOLOGIES CORP. + +OUI:00E0C0* + ID_OUI_FROM_DATABASE=SEIWA ELECTRIC MFG. CO., LTD. + +OUI:00E0C1* + ID_OUI_FROM_DATABASE=MEMOREX TELEX JAPAN, LTD. + +OUI:00E0C2* + ID_OUI_FROM_DATABASE=NECSY S.p.A. + +OUI:00E0C3* + ID_OUI_FROM_DATABASE=SAKAI SYSTEM DEVELOPMENT CORP. + +OUI:00E0C4* + ID_OUI_FROM_DATABASE=HORNER ELECTRIC, INC. + +OUI:00E0C5* + ID_OUI_FROM_DATABASE=BCOM ELECTRONICS INC. + +OUI:00E0C6* + ID_OUI_FROM_DATABASE=LINK2IT, L.L.C. + +OUI:00E0C7* + ID_OUI_FROM_DATABASE=EUROTECH SRL + +OUI:00E0C8* + ID_OUI_FROM_DATABASE=VIRTUAL ACCESS, LTD. + +OUI:00E0C9* + ID_OUI_FROM_DATABASE=AutomatedLogic Corporation + +OUI:00E0CA* + ID_OUI_FROM_DATABASE=BEST DATA PRODUCTS + +OUI:00E0CB* + ID_OUI_FROM_DATABASE=RESON, INC. + +OUI:00E0CC* + ID_OUI_FROM_DATABASE=HERO SYSTEMS, LTD. + +OUI:00E0CD* + ID_OUI_FROM_DATABASE=SAAB SENSIS CORPORATION + +OUI:00E0CE* + ID_OUI_FROM_DATABASE=ARN + +OUI:00E0CF* + ID_OUI_FROM_DATABASE=INTEGRATED DEVICE + +OUI:00E0D0* + ID_OUI_FROM_DATABASE=NETSPEED, INC. + +OUI:00E0D1* + ID_OUI_FROM_DATABASE=TELSIS LIMITED + +OUI:00E0D2* + ID_OUI_FROM_DATABASE=VERSANET COMMUNICATIONS, INC. + +OUI:00E0D3* + ID_OUI_FROM_DATABASE=DATENTECHNIK GmbH + +OUI:00E0D4* + ID_OUI_FROM_DATABASE=EXCELLENT COMPUTER + +OUI:00E0D5* + ID_OUI_FROM_DATABASE=Emulex Corporation + +OUI:00E0D6* + ID_OUI_FROM_DATABASE=COMPUTER & COMMUNICATION RESEARCH LAB. + +OUI:00E0D7* + ID_OUI_FROM_DATABASE=SUNSHINE ELECTRONICS, INC. + +OUI:00E0D8* + ID_OUI_FROM_DATABASE=LANBit Computer, Inc. + +OUI:00E0D9* + ID_OUI_FROM_DATABASE=TAZMO CO., LTD. + +OUI:00E0DA* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise + +OUI:00E0DB* + ID_OUI_FROM_DATABASE=ViaVideo Communications, Inc. + +OUI:00E0DC* + ID_OUI_FROM_DATABASE=NEXWARE CORP. + +OUI:00E0DD* + ID_OUI_FROM_DATABASE=Zenith Electronics Corporation + +OUI:00E0DE* + ID_OUI_FROM_DATABASE=DATAX NV + +OUI:00E0DF* + ID_OUI_FROM_DATABASE=KEYMILE GmbH + +OUI:00E0E0* + ID_OUI_FROM_DATABASE=SI ELECTRONICS, LTD. + +OUI:00E0E1* + ID_OUI_FROM_DATABASE=G2 NETWORKS, INC. + +OUI:00E0E2* + ID_OUI_FROM_DATABASE=INNOVA CORP. + +OUI:00E0E3* + ID_OUI_FROM_DATABASE=SK-ELEKTRONIK GMBH + +OUI:00E0E4* + ID_OUI_FROM_DATABASE=FANUC ROBOTICS NORTH AMERICA, Inc. + +OUI:00E0E5* + ID_OUI_FROM_DATABASE=CINCO NETWORKS, INC. + +OUI:00E0E6* + ID_OUI_FROM_DATABASE=INCAA Computers + +OUI:00E0E7* + ID_OUI_FROM_DATABASE=RAYTHEON E-SYSTEMS, INC. + +OUI:00E0E8* + ID_OUI_FROM_DATABASE=GRETACODER Data Systems AG + +OUI:00E0E9* + ID_OUI_FROM_DATABASE=DATA LABS, INC. + +OUI:00E0EA* + ID_OUI_FROM_DATABASE=INNOVAT COMMUNICATIONS, INC. + +OUI:00E0EB* + ID_OUI_FROM_DATABASE=DIGICOM SYSTEMS, INCORPORATED + +OUI:00E0EC* + ID_OUI_FROM_DATABASE=CELESTICA INC. + +OUI:00E0ED* + ID_OUI_FROM_DATABASE=SILICOM, LTD. + +OUI:00E0EE* + ID_OUI_FROM_DATABASE=MAREL HF + +OUI:00E0EF* + ID_OUI_FROM_DATABASE=DIONEX + +OUI:00E0F0* + ID_OUI_FROM_DATABASE=ABLER TECHNOLOGY, INC. + +OUI:00E0F1* + ID_OUI_FROM_DATABASE=THAT CORPORATION + +OUI:00E0F2* + ID_OUI_FROM_DATABASE=ARLOTTO COMNET, INC. + +OUI:00E0F3* + ID_OUI_FROM_DATABASE=WebSprint Communications, Inc. + +OUI:00E0F4* + ID_OUI_FROM_DATABASE=INSIDE Technology A/S + +OUI:00E0F5* + ID_OUI_FROM_DATABASE=TELES AG + +OUI:00E0F6* + ID_OUI_FROM_DATABASE=DECISION EUROPE + +OUI:00E0F7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E0F8* + ID_OUI_FROM_DATABASE=DICNA CONTROL AB + +OUI:00E0F9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E0FA* + ID_OUI_FROM_DATABASE=TRL TECHNOLOGY, LTD. + +OUI:00E0FB* + ID_OUI_FROM_DATABASE=LEIGHTRONIX, INC. + +OUI:00E0FC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:00E0FD* + ID_OUI_FROM_DATABASE=A-TREND TECHNOLOGY CO., LTD. + +OUI:00E0FE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E0FF* + ID_OUI_FROM_DATABASE=SECURITY DYNAMICS TECHNOLOGIES, Inc. + +OUI:00E16D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00E175* + ID_OUI_FROM_DATABASE=AK-Systems Ltd + +OUI:00E18C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:00E3B2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00E400* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. + +OUI:00E666* + ID_OUI_FROM_DATABASE=ARIMA Communications Corp. + +OUI:00E6D3* + ID_OUI_FROM_DATABASE=NIXDORF COMPUTER CORP. + +OUI:00E6E8* + ID_OUI_FROM_DATABASE=Netzin Technology Corporation,.Ltd. + +OUI:00E8AB* + ID_OUI_FROM_DATABASE=Meggitt Training Systems, Inc. + +OUI:00EABD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00EB2D* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:00EBD5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00EC0A* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:00EDB8* + ID_OUI_FROM_DATABASE=KYOCERA Corporation + +OUI:00EEAB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00EEBD* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:00F051* + ID_OUI_FROM_DATABASE=KWB Gmbh + +OUI:00F22C* + ID_OUI_FROM_DATABASE=Shanghai B-star Technology Co.,Ltd. + +OUI:00F28B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00F3DB* + ID_OUI_FROM_DATABASE=WOO Sports + +OUI:00F403* + ID_OUI_FROM_DATABASE=Orbis Systems Oy + +OUI:00F46F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00F48D* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:00F4B9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00F620* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:00F663* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00F76F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:00F81C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:00F82C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00F860* + ID_OUI_FROM_DATABASE=PT. Panggung Electric Citrabuana + +OUI:00F871* + ID_OUI_FROM_DATABASE=DGS Denmark A/S + +OUI:00FA21* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:00FA3B* + ID_OUI_FROM_DATABASE=CLOOS ELECTRONIC GMBH + +OUI:00FC58* + ID_OUI_FROM_DATABASE=WebSilicon Ltd. + +OUI:00FC70* + ID_OUI_FROM_DATABASE=Intrepid Control Systems, Inc. + +OUI:00FC8B* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:00FC8D* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:00FCBA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00FD22* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:00FD45* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:00FD4C* + ID_OUI_FROM_DATABASE=NEVATEC + +OUI:00FEC8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:020701* + ID_OUI_FROM_DATABASE=RACAL-DATACOM + +OUI:021C7C* + ID_OUI_FROM_DATABASE=PERQ SYSTEMS CORPORATION + +OUI:026086* + ID_OUI_FROM_DATABASE=LOGIC REPLACEMENT TECH. LTD. + +OUI:02608C* + ID_OUI_FROM_DATABASE=3COM + +OUI:027001* + ID_OUI_FROM_DATABASE=RACAL-DATACOM + +OUI:0270B0* + ID_OUI_FROM_DATABASE=M/A-COM INC. COMPANIES + +OUI:0270B3* + ID_OUI_FROM_DATABASE=DATA RECALL LTD. + +OUI:029D8E* + ID_OUI_FROM_DATABASE=CARDIAC RECORDERS, INC. + +OUI:02AA3C* + ID_OUI_FROM_DATABASE=OLIVETTI TELECOMM SPA (OLTECO) + +OUI:02BB01* + ID_OUI_FROM_DATABASE=OCTOTHORPE CORP. + +OUI:02C08C* + ID_OUI_FROM_DATABASE=3COM + +OUI:02CF1C* + ID_OUI_FROM_DATABASE=Communication Machinery Corporation + +OUI:02E6D3* + ID_OUI_FROM_DATABASE=NIXDORF COMPUTER CORP. + +OUI:04021F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0402CA* + ID_OUI_FROM_DATABASE=Shenzhen Vtsonic Co.,ltd + +OUI:0403D6* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:0404EA* + ID_OUI_FROM_DATABASE=Valens Semiconductor Ltd. + +OUI:04072E* + ID_OUI_FROM_DATABASE=VTech Electronics Ltd. + +OUI:040973* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:0409A5* + ID_OUI_FROM_DATABASE=HFR, Inc. + +OUI:040A83* + ID_OUI_FROM_DATABASE=Alcatel-Lucent + +OUI:040AE0* + ID_OUI_FROM_DATABASE=XMIT AG COMPUTER NETWORKS + +OUI:040CCE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:040E3C* + ID_OUI_FROM_DATABASE=HP Inc. + +OUI:040EC2* + ID_OUI_FROM_DATABASE=ViewSonic Mobile China Limited + +OUI:041552* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0415D9* + ID_OUI_FROM_DATABASE=Viwone + +OUI:04180F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0418B6* + ID_OUI_FROM_DATABASE=Private + +OUI:0418D6* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:04197F* + ID_OUI_FROM_DATABASE=Grasphere Japan + +OUI:041A04* + ID_OUI_FROM_DATABASE=WaveIP + +OUI:041B6D* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:041B94* + ID_OUI_FROM_DATABASE=Host Mobility AB + +OUI:041BBA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:041D10* + ID_OUI_FROM_DATABASE=Dream Ware Inc. + +OUI:041DC7* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:041E64* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:041E7A* + ID_OUI_FROM_DATABASE=DSPWorks + +OUI:041EFA* + ID_OUI_FROM_DATABASE=BISSELL Homecare, Inc. + +OUI:04209A* + ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company + +OUI:04214C* + ID_OUI_FROM_DATABASE=Insight Energy Ventures LLC + +OUI:042234* + ID_OUI_FROM_DATABASE=Wireless Standard Extensions + +OUI:0425C5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:042605* + ID_OUI_FROM_DATABASE=GFR Gesellschaft für Regelungstechnik und Energieeinsparung mbH + +OUI:042665* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:042758* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:042AE2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:042BBB* + ID_OUI_FROM_DATABASE=PicoCELA, Inc. + +OUI:042DB4* + ID_OUI_FROM_DATABASE=First Property (Beijing) Co., Ltd Modern MOMA Branch + +OUI:042F56* + ID_OUI_FROM_DATABASE=ATOCS (Shenzhen) LTD + +OUI:043110* + ID_OUI_FROM_DATABASE=Inspur Group Co., Ltd. + +OUI:0432F4* + ID_OUI_FROM_DATABASE=Partron + +OUI:043385* + ID_OUI_FROM_DATABASE=Nanchang BlackShark Co.,Ltd. + +OUI:043389* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0433C2* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:043604* + ID_OUI_FROM_DATABASE=Gyeyoung I&T + +OUI:043A0D* + ID_OUI_FROM_DATABASE=SM Optics S.r.l. + +OUI:043D98* + ID_OUI_FROM_DATABASE=ChongQing QingJia Electronics CO.,LTD + +OUI:043F72* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:0440A9* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:044169* + ID_OUI_FROM_DATABASE=GoPro + +OUI:0444A1* + ID_OUI_FROM_DATABASE=TELECON GALICIA,S.A. + +OUI:0445A1* + ID_OUI_FROM_DATABASE=NIRIT- Xinwei Telecom Technology Co., Ltd. + +OUI:044665* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:04489A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:044A50* + ID_OUI_FROM_DATABASE=Ramaxel Technology (Shenzhen) limited company + +OUI:044A6C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:044BED* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:044BFF* + ID_OUI_FROM_DATABASE=GuangZhou Hedy Digital Technology Co., Ltd + +OUI:044CEF* + ID_OUI_FROM_DATABASE=Fujian Sanao Technology Co.,Ltd + +OUI:044E06* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:044E5A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:044EAF* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:044F17* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:044F4C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:044F8B* + ID_OUI_FROM_DATABASE=Adapteva, Inc. + +OUI:044FAA* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:0450DA* + ID_OUI_FROM_DATABASE=Qiku Internet Network Scientific (Shenzhen) Co., Ltd + +OUI:0452C7* + ID_OUI_FROM_DATABASE=Bose Corporation + +OUI:0452F3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0453D5* + ID_OUI_FROM_DATABASE=Sysorex Global Holdings + +OUI:045453* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0455CA* + ID_OUI_FROM_DATABASE=BriView (Xiamen) Corp. + +OUI:045604* + ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co.,Ltd. + +OUI:04572F* + ID_OUI_FROM_DATABASE=Sertel Electronics UK Ltd + +OUI:04586F* + ID_OUI_FROM_DATABASE=Sichuan Whayer information industry Co.,LTD + +OUI:045A95* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:045C06* + ID_OUI_FROM_DATABASE=Zmodo Technology Corporation + +OUI:045C6C* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:045C8E* + ID_OUI_FROM_DATABASE=gosund GROUP CO.,LTD + +OUI:045D4B* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:045D56* + ID_OUI_FROM_DATABASE=camtron industrial inc. + +OUI:045EA4* + ID_OUI_FROM_DATABASE=SHENZHEN NETIS TECHNOLOGY CO.,LTD + +OUI:045FA7* + ID_OUI_FROM_DATABASE=Shenzhen Yichen Technology Development Co.,LTD + +OUI:046169* + ID_OUI_FROM_DATABASE=MEDIA GLOBAL LINKS CO., LTD. + +OUI:046273* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0462D7* + ID_OUI_FROM_DATABASE=ALSTOM HYDRO FRANCE + +OUI:0463E0* + ID_OUI_FROM_DATABASE=Nome Oy + +OUI:046565* + ID_OUI_FROM_DATABASE=Testop + +OUI:046785* + ID_OUI_FROM_DATABASE=scemtec Hard- und Software fuer Mess- und Steuerungstechnik GmbH + +OUI:0469F8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:046B1B* + ID_OUI_FROM_DATABASE=SYSDINE Co., Ltd. + +OUI:046B25* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOM CO.,LTD + +OUI:046C9D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:046D42* + ID_OUI_FROM_DATABASE=Bryston Ltd. + +OUI:046E02* + ID_OUI_FROM_DATABASE=OpenRTLS Group + +OUI:046E49* + ID_OUI_FROM_DATABASE=TaiYear Electronic Technology (Suzhou) Co., Ltd + +OUI:0470BC* + ID_OUI_FROM_DATABASE=Globalstar Inc. + +OUI:04714B0* + ID_OUI_FROM_DATABASE=Neurio Technology Inc. + +OUI:04714B1* + ID_OUI_FROM_DATABASE=uAvionix Corporation + +OUI:04714B2* + ID_OUI_FROM_DATABASE=Shenzhen WayOS Technology Crop., Ltd. + +OUI:04714B3* + ID_OUI_FROM_DATABASE=Griesser Electronic AG + +OUI:04714B4* + ID_OUI_FROM_DATABASE=Apparatebau Gauting GmbH + +OUI:04714B5* + ID_OUI_FROM_DATABASE=Bureau Electronique Appliquee + +OUI:04714B6* + ID_OUI_FROM_DATABASE=Armstrong Fluid Technology + +OUI:04714B7* + ID_OUI_FROM_DATABASE=Omylis Pte Ltd + +OUI:04714B8* + ID_OUI_FROM_DATABASE=Energport Inc + +OUI:04714B9* + ID_OUI_FROM_DATABASE=Lighthouse AI, Inc + +OUI:04714BA* + ID_OUI_FROM_DATABASE=Observables, Inc. + +OUI:04714BB* + ID_OUI_FROM_DATABASE=DIGIBEST TECHNOLOGY CO., LTD. + +OUI:04714BC* + ID_OUI_FROM_DATABASE=KittyHawk Corporation + +OUI:04714BD* + ID_OUI_FROM_DATABASE=Shenzhen BoClouds Technology Co.,Ltd. + +OUI:04714BE* + ID_OUI_FROM_DATABASE=Gimso Mobile Ltd + +OUI:047295* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0474A1* + ID_OUI_FROM_DATABASE=Aligera Equipamentos Digitais Ltda + +OUI:047503* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0475F5* + ID_OUI_FROM_DATABASE=CSST + +OUI:04766E* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:047863* + ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd. + +OUI:047970* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0479B7* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:047D50* + ID_OUI_FROM_DATABASE=Shenzhen Kang Ying Technology Co.Ltd. + +OUI:047D7B* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:047E4A* + ID_OUI_FROM_DATABASE=moobox CO., Ltd. + +OUI:047F0E* + ID_OUI_FROM_DATABASE=Barrot Technology Limited + +OUI:04819B* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:0481AE* + ID_OUI_FROM_DATABASE=Clack Corporation + +OUI:04848A* + ID_OUI_FROM_DATABASE=7INOVA TECHNOLOGY LIMITED + +OUI:04885F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:04888C* + ID_OUI_FROM_DATABASE=Eifelwerk Butler Systeme GmbH + +OUI:0488E2* + ID_OUI_FROM_DATABASE=Beats Electronics LLC + +OUI:048A15* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:048AE1* + ID_OUI_FROM_DATABASE=FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + +OUI:048B42* + ID_OUI_FROM_DATABASE=Skspruce Technologies + +OUI:048C03* + ID_OUI_FROM_DATABASE=ThinPAD Technology (Shenzhen)CO.,LTD + +OUI:048C16* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:048C9A* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:048D38* + ID_OUI_FROM_DATABASE=Netcore Technology Inc. + +OUI:049162* + ID_OUI_FROM_DATABASE=Microchip Technology Inc. + +OUI:049226* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:0492EE* + ID_OUI_FROM_DATABASE=iway AG + +OUI:04946B* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:0494A1* + ID_OUI_FROM_DATABASE=CATCH THE WIND INC + +OUI:049573* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:0495E6* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:049645* + ID_OUI_FROM_DATABASE=WUXI SKY CHIP INTERCONNECTION TECHNOLOGY CO.,LTD. + +OUI:049790* + ID_OUI_FROM_DATABASE=Lartech telecom LLC + +OUI:0498F3* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:0499E6* + ID_OUI_FROM_DATABASE=Shenzhen Yoostar Technology Co., Ltd + +OUI:049B9C* + ID_OUI_FROM_DATABASE=Eadingcore Intelligent Technology Co., Ltd. + +OUI:049C62* + ID_OUI_FROM_DATABASE=BMT Medical Technology s.r.o. + +OUI:049DFE* + ID_OUI_FROM_DATABASE=Hivesystem + +OUI:049F06* + ID_OUI_FROM_DATABASE=Smobile Co., Ltd. + +OUI:049F81* + ID_OUI_FROM_DATABASE=NetAlly + +OUI:049FCA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:04A151* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:04A222* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:04A316* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:04A3F3* + ID_OUI_FROM_DATABASE=Emicon + +OUI:04A82A* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:04AAE1* + ID_OUI_FROM_DATABASE=BEIJING MICROVISION TECHNOLOGY CO.,LTD + +OUI:04AB18* + ID_OUI_FROM_DATABASE=ELECOM CO.,LTD. + +OUI:04AB6A* + ID_OUI_FROM_DATABASE=Chun-il Co.,Ltd. + +OUI:04AC44* + ID_OUI_FROM_DATABASE=Holtek Semiconductor Inc. + +OUI:04B0E7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:04B167* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:04B1A1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:04B3B6* + ID_OUI_FROM_DATABASE=Seamap (UK) Ltd + +OUI:04B429* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:04B466* + ID_OUI_FROM_DATABASE=BSP Co., Ltd. + +OUI:04B648* + ID_OUI_FROM_DATABASE=ZENNER + +OUI:04BA36* + ID_OUI_FROM_DATABASE=Li Seng Technology Ltd + +OUI:04BA8D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:04BBF9* + ID_OUI_FROM_DATABASE=Pavilion Data Systems Inc + +OUI:04BC87* + ID_OUI_FROM_DATABASE=Shenzhen JustLink Technology Co., LTD + +OUI:04BD70* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:04BD88* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:04BDBF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:04BF6D* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:04BFA8* + ID_OUI_FROM_DATABASE=ISB Corporation + +OUI:04C05B* + ID_OUI_FROM_DATABASE=Tigo Energy + +OUI:04C06F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:04C09C* + ID_OUI_FROM_DATABASE=Tellabs Inc. + +OUI:04C103* + ID_OUI_FROM_DATABASE=Clover Network, Inc. + +OUI:04C1B9* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:04C23E* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:04C241* + ID_OUI_FROM_DATABASE=Nokia + +OUI:04C3E60* + ID_OUI_FROM_DATABASE=DREAMKAS LLC + +OUI:04C3E61* + ID_OUI_FROM_DATABASE=Guangdong New Pulse Electric Co., Ltd. + +OUI:04C3E62* + ID_OUI_FROM_DATABASE=SiS Technology + +OUI:04C3E63* + ID_OUI_FROM_DATABASE=Extech Electronics Co., LTD. + +OUI:04C3E64* + ID_OUI_FROM_DATABASE=Innovusion Inc. + +OUI:04C3E65* + ID_OUI_FROM_DATABASE=Invasys + +OUI:04C3E66* + ID_OUI_FROM_DATABASE=Shenzhen Shuotian Information Technology Co., LTD + +OUI:04C3E67* + ID_OUI_FROM_DATABASE=Advanced Digital Technologies, s.r.o. + +OUI:04C3E68* + ID_OUI_FROM_DATABASE=SLOC GmbH + +OUI:04C3E69* + ID_OUI_FROM_DATABASE=Ekin Teknoloji San ve Tic A.S. + +OUI:04C3E6A* + ID_OUI_FROM_DATABASE=Sealed Unit Parts Co., Inc. + +OUI:04C3E6B* + ID_OUI_FROM_DATABASE=Flintec UK Ltd. + +OUI:04C3E6C* + ID_OUI_FROM_DATABASE=SHANTOU YINGSHENG IMPORT & EXPORT TRADING CO.,LTD. + +OUI:04C3E6D* + ID_OUI_FROM_DATABASE=Amiosec Ltd + +OUI:04C3E6E* + ID_OUI_FROM_DATABASE=Teleepoch Ltd + +OUI:04C5A4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:04C807* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:04C880* + ID_OUI_FROM_DATABASE=Samtec Inc + +OUI:04C991* + ID_OUI_FROM_DATABASE=Phistek INC. + +OUI:04C9D9* + ID_OUI_FROM_DATABASE=Dish Technologies Corp + +OUI:04CB1D* + ID_OUI_FROM_DATABASE=Traka plc + +OUI:04CE14* + ID_OUI_FROM_DATABASE=Wilocity LTD. + +OUI:04CE7E* + ID_OUI_FROM_DATABASE=NXP France Semiconductors France + +OUI:04CF25* + ID_OUI_FROM_DATABASE=MANYCOLORS, INC. + +OUI:04CF8C* + ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD + +OUI:04D13A* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:04D16E0* + ID_OUI_FROM_DATABASE=INTRIPLE, a.s. + +OUI:04D16E1* + ID_OUI_FROM_DATABASE=Launch Tech Co., Ltd. + +OUI:04D16E2* + ID_OUI_FROM_DATABASE=s.d.i. s.p.a. + +OUI:04D16E3* + ID_OUI_FROM_DATABASE=Beijing Huaxia Qixin Technology Co., Ltd. + +OUI:04D16E4* + ID_OUI_FROM_DATABASE=ShenZhen Huafu Information technology Co.?Ltd + +OUI:04D16E5* + ID_OUI_FROM_DATABASE=Dspread Technology (Beijing) Inc. + +OUI:04D16E6* + ID_OUI_FROM_DATABASE=ETL Elektrotechnik Lauter GmbH + +OUI:04D16E7* + ID_OUI_FROM_DATABASE=Envision Energy + +OUI:04D16E8* + ID_OUI_FROM_DATABASE=CHENGDU INTERLINK SCIENCE AND TECHNOLOGY CO.,LTD + +OUI:04D16E9* + ID_OUI_FROM_DATABASE=FUZHOU ZHUOYI ELECTRONIC CO.,LTD + +OUI:04D16EA* + ID_OUI_FROM_DATABASE=Metra Electronics + +OUI:04D16EB* + ID_OUI_FROM_DATABASE=National Radio & Telecommunication Corporation - NRTC + +OUI:04D16EC* + ID_OUI_FROM_DATABASE=PacPort Corporation + +OUI:04D16ED* + ID_OUI_FROM_DATABASE=Elotec Fischer Elektronik GmbH + +OUI:04D16EE* + ID_OUI_FROM_DATABASE=Evolute Systems Private Limited + +OUI:04D395* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:04D3B0* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:04D3B5* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:04D3CF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:04D437* + ID_OUI_FROM_DATABASE=ZNV + +OUI:04D4C4* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:04D590* + ID_OUI_FROM_DATABASE=Fortinet, Inc. + +OUI:04D6AA* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:04D783* + ID_OUI_FROM_DATABASE=Y&H E&C Co.,LTD. + +OUI:04D7A5* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:04D9F5* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:04DAD2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:04DB56* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:04DB8A* + ID_OUI_FROM_DATABASE=Suntech International Ltd. + +OUI:04DD4C* + ID_OUI_FROM_DATABASE=Velocytech + +OUI:04DEDB* + ID_OUI_FROM_DATABASE=Rockport Networks Inc + +OUI:04DEF2* + ID_OUI_FROM_DATABASE=Shenzhen ECOM Technology Co. Ltd + +OUI:04DF69* + ID_OUI_FROM_DATABASE=Car Connectivity Consortium + +OUI:04E0B0* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:04E0C4* + ID_OUI_FROM_DATABASE=TRIUMPH-ADLER AG + +OUI:04E1C8* + ID_OUI_FROM_DATABASE=IMS Soluções em Energia Ltda. + +OUI:04E229* + ID_OUI_FROM_DATABASE=Qingdao Haier Technology Co.,Ltd + +OUI:04E2F8* + ID_OUI_FROM_DATABASE=AEP Ticketing solutions srl + +OUI:04E451* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:04E536* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:04E548* + ID_OUI_FROM_DATABASE=Cohda Wireless Pty Ltd + +OUI:04E56E* + ID_OUI_FROM_DATABASE=THUB Co., ltd. + +OUI:04E598* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:04E662* + ID_OUI_FROM_DATABASE=Acroname Inc. + +OUI:04E676* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:04E9E5* + ID_OUI_FROM_DATABASE=PJRC.COM, LLC + +OUI:04EA56* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:04EB40* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:04ECBB* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:04ED33* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:04EE03* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:04EE91* + ID_OUI_FROM_DATABASE=x-fabric GmbH + +OUI:04F021* + ID_OUI_FROM_DATABASE=Compex Systems Pte Ltd + +OUI:04F128* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:04F13E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:04F169* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:04F17D* + ID_OUI_FROM_DATABASE=Tarana Wireless + +OUI:04F4BC* + ID_OUI_FROM_DATABASE=Xena Networks + +OUI:04F7E4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:04F8C2* + ID_OUI_FROM_DATABASE=Flaircomm Microelectronics, Inc. + +OUI:04F938* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:04F9D9* + ID_OUI_FROM_DATABASE=Speaker Electronic(Jiashan) Co.,Ltd + +OUI:04FA3F* + ID_OUI_FROM_DATABASE=Opticore Inc. + +OUI:04FA83* + ID_OUI_FROM_DATABASE=Qingdao Haier Technology Co.,Ltd + +OUI:04FE31* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:04FE7F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:04FE8D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:04FEA1* + ID_OUI_FROM_DATABASE=Fihonest communication co.,Ltd + +OUI:04FF51* + ID_OUI_FROM_DATABASE=NOVAMEDIA INNOVISION SP. Z O.O. + +OUI:080001* + ID_OUI_FROM_DATABASE=COMPUTERVISION CORPORATION + +OUI:080002* + ID_OUI_FROM_DATABASE=BRIDGE COMMUNICATIONS INC. + +OUI:080003* + ID_OUI_FROM_DATABASE=ADVANCED COMPUTER COMM. + +OUI:080004* + ID_OUI_FROM_DATABASE=CROMEMCO INCORPORATED + +OUI:080005* + ID_OUI_FROM_DATABASE=SYMBOLICS INC. + +OUI:080006* + ID_OUI_FROM_DATABASE=SIEMENS AG + +OUI:080007* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:080008* + ID_OUI_FROM_DATABASE=BOLT BERANEK AND NEWMAN INC. + +OUI:080009* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:08000A* + ID_OUI_FROM_DATABASE=NESTAR SYSTEMS INCORPORATED + +OUI:08000B* + ID_OUI_FROM_DATABASE=UNISYS CORPORATION + +OUI:08000C* + ID_OUI_FROM_DATABASE=MIKLYN DEVELOPMENT CO. + +OUI:08000D* + ID_OUI_FROM_DATABASE=International Computers, Ltd + +OUI:08000E* + ID_OUI_FROM_DATABASE=NCR CORPORATION + +OUI:08000F* + ID_OUI_FROM_DATABASE=MITEL CORPORATION + +OUI:080011* + ID_OUI_FROM_DATABASE=TEKTRONIX INC. + +OUI:080012* + ID_OUI_FROM_DATABASE=BELL ATLANTIC INTEGRATED SYST. + +OUI:080013* + ID_OUI_FROM_DATABASE=Exxon + +OUI:080014* + ID_OUI_FROM_DATABASE=EXCELAN + +OUI:080015* + ID_OUI_FROM_DATABASE=STC BUSINESS SYSTEMS + +OUI:080016* + ID_OUI_FROM_DATABASE=BARRISTER INFO SYS CORP + +OUI:080017* + ID_OUI_FROM_DATABASE=NATIONAL SEMICONDUCTOR + +OUI:080018* + ID_OUI_FROM_DATABASE=PIRELLI FOCOM NETWORKS + +OUI:080019* + ID_OUI_FROM_DATABASE=GENERAL ELECTRIC CORPORATION + +OUI:08001A* + ID_OUI_FROM_DATABASE=TIARA/ 10NET + +OUI:08001B* + ID_OUI_FROM_DATABASE=Dell EMC + +OUI:08001C* + ID_OUI_FROM_DATABASE=KDD-KOKUSAI DEBNSIN DENWA CO. + +OUI:08001D* + ID_OUI_FROM_DATABASE=ABLE COMMUNICATIONS INC. + +OUI:08001E* + ID_OUI_FROM_DATABASE=APOLLO COMPUTER INC. + +OUI:08001F* + ID_OUI_FROM_DATABASE=SHARP CORPORATION + +OUI:080020* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:080021* + ID_OUI_FROM_DATABASE=3M COMPANY + +OUI:080022* + ID_OUI_FROM_DATABASE=NBI INC. + +OUI:080023* + ID_OUI_FROM_DATABASE=Panasonic Communications Co., Ltd. + +OUI:080024* + ID_OUI_FROM_DATABASE=10NET COMMUNICATIONS/DCA + +OUI:080025* + ID_OUI_FROM_DATABASE=CONTROL DATA + +OUI:080026* + ID_OUI_FROM_DATABASE=NORSK DATA A.S. + +OUI:080027* + ID_OUI_FROM_DATABASE=PCS Systemtechnik GmbH + +OUI:080028* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:080029* + ID_OUI_FROM_DATABASE=Megatek Corporation + +OUI:08002A* + ID_OUI_FROM_DATABASE=MOSAIC TECHNOLOGIES INC. + +OUI:08002B* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION + +OUI:08002C* + ID_OUI_FROM_DATABASE=BRITTON LEE INC. + +OUI:08002D* + ID_OUI_FROM_DATABASE=LAN-TEC INC. + +OUI:08002E* + ID_OUI_FROM_DATABASE=METAPHOR COMPUTER SYSTEMS + +OUI:08002F* + ID_OUI_FROM_DATABASE=PRIME COMPUTER INC. + +OUI:080030* + ID_OUI_FROM_DATABASE=NETWORK RESEARCH CORPORATION + +OUI:080031* + ID_OUI_FROM_DATABASE=LITTLE MACHINES INC. + +OUI:080032* + ID_OUI_FROM_DATABASE=TIGAN INCORPORATED + +OUI:080033* + ID_OUI_FROM_DATABASE=BAUSCH & LOMB + +OUI:080034* + ID_OUI_FROM_DATABASE=FILENET CORPORATION + +OUI:080035* + ID_OUI_FROM_DATABASE=MICROFIVE CORPORATION + +OUI:080036* + ID_OUI_FROM_DATABASE=INTERGRAPH CORPORATION + +OUI:080037* + ID_OUI_FROM_DATABASE=FUJI-XEROX CO. LTD. + +OUI:080038* + ID_OUI_FROM_DATABASE=BULL S.A.S. + +OUI:080039* + ID_OUI_FROM_DATABASE=SPIDER SYSTEMS LIMITED + +OUI:08003A* + ID_OUI_FROM_DATABASE=ORCATECH INC. + +OUI:08003B* + ID_OUI_FROM_DATABASE=TORUS SYSTEMS LIMITED + +OUI:08003C* + ID_OUI_FROM_DATABASE=SCHLUMBERGER WELL SERVICES + +OUI:08003D* + ID_OUI_FROM_DATABASE=CADNETIX CORPORATIONS + +OUI:08003E* + ID_OUI_FROM_DATABASE=CODEX CORPORATION + +OUI:08003F* + ID_OUI_FROM_DATABASE=FRED KOSCHARA ENTERPRISES + +OUI:080040* + ID_OUI_FROM_DATABASE=FERRANTI COMPUTER SYS. LIMITED + +OUI:080041* + ID_OUI_FROM_DATABASE=RACAL-MILGO INFORMATION SYS.. + +OUI:080042* + ID_OUI_FROM_DATABASE=JAPAN MACNICS CORP. + +OUI:080043* + ID_OUI_FROM_DATABASE=PIXEL COMPUTER INC. + +OUI:080044* + ID_OUI_FROM_DATABASE=DAVID SYSTEMS INC. + +OUI:080045* + ID_OUI_FROM_DATABASE=CONCURRENT COMPUTER CORP. + +OUI:080046* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:080047* + ID_OUI_FROM_DATABASE=SEQUENT COMPUTER SYSTEMS INC. + +OUI:080048* + ID_OUI_FROM_DATABASE=EUROTHERM GAUGING SYSTEMS + +OUI:080049* + ID_OUI_FROM_DATABASE=UNIVATION + +OUI:08004A* + ID_OUI_FROM_DATABASE=BANYAN SYSTEMS INC. + +OUI:08004B* + ID_OUI_FROM_DATABASE=Planning Research Corp. + +OUI:08004C* + ID_OUI_FROM_DATABASE=HYDRA COMPUTER SYSTEMS INC. + +OUI:08004D* + ID_OUI_FROM_DATABASE=CORVUS SYSTEMS INC. + +OUI:08004E* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:08004F* + ID_OUI_FROM_DATABASE=CYGNET SYSTEMS + +OUI:080050* + ID_OUI_FROM_DATABASE=DAISY SYSTEMS CORP. + +OUI:080051* + ID_OUI_FROM_DATABASE=ExperData + +OUI:080052* + ID_OUI_FROM_DATABASE=INSYSTEC + +OUI:080053* + ID_OUI_FROM_DATABASE=MIDDLE EAST TECH. UNIVERSITY + +OUI:080055* + ID_OUI_FROM_DATABASE=STANFORD TELECOMM. INC. + +OUI:080056* + ID_OUI_FROM_DATABASE=STANFORD LINEAR ACCEL. CENTER + +OUI:080057* + ID_OUI_FROM_DATABASE=Evans & Sutherland + +OUI:080058* + ID_OUI_FROM_DATABASE=SYSTEMS CONCEPTS + +OUI:080059* + ID_OUI_FROM_DATABASE=A/S MYCRON + +OUI:08005A* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:08005B* + ID_OUI_FROM_DATABASE=VTA TECHNOLOGIES INC. + +OUI:08005C* + ID_OUI_FROM_DATABASE=FOUR PHASE SYSTEMS + +OUI:08005D* + ID_OUI_FROM_DATABASE=GOULD INC. + +OUI:08005E* + ID_OUI_FROM_DATABASE=COUNTERPOINT COMPUTER INC. + +OUI:08005F* + ID_OUI_FROM_DATABASE=SABER TECHNOLOGY CORP. + +OUI:080060* + ID_OUI_FROM_DATABASE=INDUSTRIAL NETWORKING INC. + +OUI:080061* + ID_OUI_FROM_DATABASE=JAROGATE LTD. + +OUI:080062* + ID_OUI_FROM_DATABASE=General Dynamics + +OUI:080063* + ID_OUI_FROM_DATABASE=PLESSEY + +OUI:080064* + ID_OUI_FROM_DATABASE=Sitasys AG + +OUI:080065* + ID_OUI_FROM_DATABASE=GENRAD INC. + +OUI:080066* + ID_OUI_FROM_DATABASE=AGFA CORPORATION + +OUI:080067* + ID_OUI_FROM_DATABASE=ComDesign + +OUI:080068* + ID_OUI_FROM_DATABASE=RIDGE COMPUTERS + +OUI:080069* + ID_OUI_FROM_DATABASE=Silicon Graphics + +OUI:08006A* + ID_OUI_FROM_DATABASE=AT&T + +OUI:08006B* + ID_OUI_FROM_DATABASE=ACCEL TECHNOLOGIES INC. + +OUI:08006C* + ID_OUI_FROM_DATABASE=SUNTEK TECHNOLOGY INT'L + +OUI:08006D* + ID_OUI_FROM_DATABASE=WHITECHAPEL COMPUTER WORKS + +OUI:08006E* + ID_OUI_FROM_DATABASE=MASSCOMP + +OUI:08006F* + ID_OUI_FROM_DATABASE=PHILIPS APELDOORN B.V. + +OUI:080070* + ID_OUI_FROM_DATABASE=Mitsubishi Precision Co.,LTd. + +OUI:080071* + ID_OUI_FROM_DATABASE=MATRA (DSIE) + +OUI:080072* + ID_OUI_FROM_DATABASE=XEROX CORP UNIV GRANT PROGRAM + +OUI:080073* + ID_OUI_FROM_DATABASE=TECMAR INC. + +OUI:080074* + ID_OUI_FROM_DATABASE=CASIO COMPUTER CO. LTD. + +OUI:080075* + ID_OUI_FROM_DATABASE=DANSK DATA ELECTRONIK + +OUI:080076* + ID_OUI_FROM_DATABASE=PC LAN TECHNOLOGIES + +OUI:080077* + ID_OUI_FROM_DATABASE=TSL COMMUNICATIONS LTD. + +OUI:080078* + ID_OUI_FROM_DATABASE=ACCELL CORPORATION + +OUI:080079* + ID_OUI_FROM_DATABASE=THE DROID WORKS + +OUI:08007A* + ID_OUI_FROM_DATABASE=INDATA + +OUI:08007B* + ID_OUI_FROM_DATABASE=SANYO ELECTRIC CO. LTD. + +OUI:08007C* + ID_OUI_FROM_DATABASE=VITALINK COMMUNICATIONS CORP. + +OUI:08007E* + ID_OUI_FROM_DATABASE=AMALGAMATED WIRELESS(AUS) LTD + +OUI:08007F* + ID_OUI_FROM_DATABASE=CARNEGIE-MELLON UNIVERSITY + +OUI:080080* + ID_OUI_FROM_DATABASE=AES DATA INC. + +OUI:080081* + ID_OUI_FROM_DATABASE=ASTECH INC. + +OUI:080082* + ID_OUI_FROM_DATABASE=VERITAS SOFTWARE + +OUI:080083* + ID_OUI_FROM_DATABASE=Seiko Instruments Inc. + +OUI:080084* + ID_OUI_FROM_DATABASE=TOMEN ELECTRONICS CORP. + +OUI:080085* + ID_OUI_FROM_DATABASE=ELXSI + +OUI:080086* + ID_OUI_FROM_DATABASE=KONICA MINOLTA HOLDINGS, INC. + +OUI:080087* + ID_OUI_FROM_DATABASE=Xyplex, Inc. + +OUI:080088* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:080089* + ID_OUI_FROM_DATABASE=Kinetics + +OUI:08008A* + ID_OUI_FROM_DATABASE=PerfTech, Inc. + +OUI:08008B* + ID_OUI_FROM_DATABASE=PYRAMID TECHNOLOGY CORP. + +OUI:08008C* + ID_OUI_FROM_DATABASE=NETWORK RESEARCH CORPORATION + +OUI:08008D* + ID_OUI_FROM_DATABASE=XYVISION INC. + +OUI:08008E* + ID_OUI_FROM_DATABASE=Tandem Computers + +OUI:08008F* + ID_OUI_FROM_DATABASE=CHIPCOM CORPORATION + +OUI:080090* + ID_OUI_FROM_DATABASE=SONOMA SYSTEMS + +OUI:08010F* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:08028E* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:080371* + ID_OUI_FROM_DATABASE=KRG CORPORATE + +OUI:080581* + ID_OUI_FROM_DATABASE=Roku, Inc. + +OUI:0805CD* + ID_OUI_FROM_DATABASE=DongGuang EnMai Electronic Product Co.Ltd. + +OUI:0808C2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0808EA* + ID_OUI_FROM_DATABASE=AMSC + +OUI:0809B6* + ID_OUI_FROM_DATABASE=Masimo Corp + +OUI:0809C7* + ID_OUI_FROM_DATABASE=Zhuhai Unitech Power Technology Co., Ltd. + +OUI:080A4E* + ID_OUI_FROM_DATABASE=Planet Bingo® — 3rd Rock Gaming® + +OUI:080C0B* + ID_OUI_FROM_DATABASE=SysMik GmbH Dresden + +OUI:080CC9* + ID_OUI_FROM_DATABASE=Mission Technology Group, dba Magma + +OUI:080D84* + ID_OUI_FROM_DATABASE=GECO, Inc. + +OUI:080EA8* + ID_OUI_FROM_DATABASE=Velex s.r.l. + +OUI:080FFA* + ID_OUI_FROM_DATABASE=KSP INC. + +OUI:08115E* + ID_OUI_FROM_DATABASE=Bitel Co., Ltd. + +OUI:081196* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0812A5* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:081443* + ID_OUI_FROM_DATABASE=UNIBRAIN S.A. + +OUI:08152F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. ARTIK + +OUI:081651* + ID_OUI_FROM_DATABASE=SHENZHEN SEA STAR TECHNOLOGY CO.,LTD + +OUI:081735* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0817F4* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:08181A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:08184C* + ID_OUI_FROM_DATABASE=A. S. Thomas, Inc. + +OUI:0819A6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:081DC4* + ID_OUI_FROM_DATABASE=Thermo Fisher Scientific Messtechnik GmbH + +OUI:081DFB* + ID_OUI_FROM_DATABASE=Shanghai Mexon Communication Technology Co.,Ltd + +OUI:081F3F* + ID_OUI_FROM_DATABASE=WondaLink Inc. + +OUI:081F71* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:081FEB* + ID_OUI_FROM_DATABASE=BinCube + +OUI:081FF3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0821EF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0823B2* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:082522* + ID_OUI_FROM_DATABASE=ADVANSEE + +OUI:082525* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:082697* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:082719* + ID_OUI_FROM_DATABASE=APS systems/electronic AG + +OUI:0827CE* + ID_OUI_FROM_DATABASE=NAGANO KEIKI CO., LTD. + +OUI:082AD0* + ID_OUI_FROM_DATABASE=SRD Innovations Inc. + +OUI:082CB0* + ID_OUI_FROM_DATABASE=Network Instruments + +OUI:082CB6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:082E5F* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:08306B* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:08318B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:08351B* + ID_OUI_FROM_DATABASE=Shenzhen Jialihua Electronic Technology Co., Ltd + +OUI:083571* + ID_OUI_FROM_DATABASE=CASwell INC. + +OUI:0835B2* + ID_OUI_FROM_DATABASE=CoreEdge Networks Co., Ltd + +OUI:0836C9* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:08373D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:08379C* + ID_OUI_FROM_DATABASE=Topaz Co. LTD. + +OUI:0838A5* + ID_OUI_FROM_DATABASE=Funkwerk plettac electronic GmbH + +OUI:083A2F* + ID_OUI_FROM_DATABASE=Guangzhou Juan Intelligent Tech Joint Stock Co.,Ltd + +OUI:083A5C* + ID_OUI_FROM_DATABASE=Junilab, Inc. + +OUI:083A88* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:083AB8* + ID_OUI_FROM_DATABASE=Shinoda Plasma Co., Ltd. + +OUI:083D88* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:083E0C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:083E5D* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:083E8E* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:083F3E* + ID_OUI_FROM_DATABASE=WSH GmbH + +OUI:083F76* + ID_OUI_FROM_DATABASE=Intellian Technologies, Inc. + +OUI:083FBC* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:084027* + ID_OUI_FROM_DATABASE=Gridstore Inc. + +OUI:0840F3* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:084656* + ID_OUI_FROM_DATABASE=VEO-LABS + +OUI:0847D0* + ID_OUI_FROM_DATABASE=Nokia Shanghai Bell Co., Ltd. + +OUI:08482C* + ID_OUI_FROM_DATABASE=Raycore Taiwan Co., LTD. + +OUI:084ACF* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:084E1C* + ID_OUI_FROM_DATABASE=H2A Systems, LLC + +OUI:084EBF* + ID_OUI_FROM_DATABASE=Broad Net Mux Corporation + +OUI:084F0A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:084FA9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:084FF9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:085114* + ID_OUI_FROM_DATABASE=QINGDAO TOPSCOMM COMMUNICATION CO., LTD + +OUI:08512E* + ID_OUI_FROM_DATABASE=Orion Diagnostica Oy + +OUI:085240* + ID_OUI_FROM_DATABASE=EbV Elektronikbau- und Vertriebs GmbH + +OUI:085700* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:085AE0* + ID_OUI_FROM_DATABASE=Recovision Technology Co., Ltd. + +OUI:085B0E* + ID_OUI_FROM_DATABASE=Fortinet, Inc. + +OUI:085BDA* + ID_OUI_FROM_DATABASE=CliniCare LTD + +OUI:085DDD* + ID_OUI_FROM_DATABASE=MERCURY CORPORATION + +OUI:08606E* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:086083* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:086195* + ID_OUI_FROM_DATABASE=Rockwell Automation + +OUI:086266* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:086361* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:08661F* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:086698* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:08674E* + ID_OUI_FROM_DATABASE=Hisense broadband multimedia technology Co.,Ltd + +OUI:08688D* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:0868D0* + ID_OUI_FROM_DATABASE=Japan System Design + +OUI:0868EA* + ID_OUI_FROM_DATABASE=EITO ELECTRONICS CO., LTD. + +OUI:086A0A* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:086BD1* + ID_OUI_FROM_DATABASE=Shenzhen SuperElectron Technology Co.,Ltd. + +OUI:086BD7* + ID_OUI_FROM_DATABASE=Silicon Laboratories + +OUI:086D41* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:086DF2* + ID_OUI_FROM_DATABASE=Shenzhen MIMOWAVE Technology Co.,Ltd + +OUI:087045* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:087190* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:087402* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0874F6* + ID_OUI_FROM_DATABASE=Winterhalter Gastronom GmbH + +OUI:087572* + ID_OUI_FROM_DATABASE=Obelux Oy + +OUI:087618* + ID_OUI_FROM_DATABASE=ViE Technologies Sdn. Bhd. + +OUI:087695* + ID_OUI_FROM_DATABASE=Auto Industrial Co., Ltd. + +OUI:0876FF* + ID_OUI_FROM_DATABASE=Thomson Telecom Belgium + +OUI:087808* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:087999* + ID_OUI_FROM_DATABASE=AIM GmbH + +OUI:087A4C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:087BAA* + ID_OUI_FROM_DATABASE=SVYAZKOMPLEKTSERVICE, LLC + +OUI:087CBE* + ID_OUI_FROM_DATABASE=Quintic Corp. + +OUI:087D21* + ID_OUI_FROM_DATABASE=Altasec technology corporation + +OUI:087E64* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:087F98* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:088039* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:0881BC* + ID_OUI_FROM_DATABASE=HongKong Ipro Technology Co., Limited + +OUI:0881F4* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:088466* + ID_OUI_FROM_DATABASE=Novartis Pharma AG + +OUI:08849D* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:088620* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:08863B* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:0887C6* + ID_OUI_FROM_DATABASE=INGRAM MICRO SERVICES + +OUI:088C2C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:088DC8* + ID_OUI_FROM_DATABASE=Ryowa Electronics Co.,Ltd + +OUI:088E4F* + ID_OUI_FROM_DATABASE=SF Software Solutions + +OUI:088F2C* + ID_OUI_FROM_DATABASE=Hills Sound Vision & Lighting + +OUI:0890BA* + ID_OUI_FROM_DATABASE=Danlaw Inc + +OUI:0894EF* + ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation + +OUI:08952A* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:0896AD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0896D7* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:089734* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:089758* + ID_OUI_FROM_DATABASE=Shenzhen Strong Rising Electronics Co.,Ltd DongGuan Subsidiary + +OUI:089798* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:089B4B* + ID_OUI_FROM_DATABASE=iKuai Networks + +OUI:089C86* + ID_OUI_FROM_DATABASE=Nokia Shanghai Bell Co., Ltd. + +OUI:089E01* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:089E08* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:089F97* + ID_OUI_FROM_DATABASE=LEROY AUTOMATION + +OUI:08A12B* + ID_OUI_FROM_DATABASE=ShenZhen EZL Technology Co., Ltd + +OUI:08A5C8* + ID_OUI_FROM_DATABASE=Sunnovo International Limited + +OUI:08A6BC* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:08A8A1* + ID_OUI_FROM_DATABASE=Cyclotronics Power Concepts, Inc + +OUI:08A95A* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:08ACA5* + ID_OUI_FROM_DATABASE=Benu Video, Inc. + +OUI:08AED6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:08AF78* + ID_OUI_FROM_DATABASE=Totus Solutions, Inc. + +OUI:08B258* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:08B2A3* + ID_OUI_FROM_DATABASE=Cynny Italia S.r.L. + +OUI:08B3AF* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:08B4CF* + ID_OUI_FROM_DATABASE=Abicom International + +OUI:08B738* + ID_OUI_FROM_DATABASE=Lite-On Technogy Corp. + +OUI:08B7EC* + ID_OUI_FROM_DATABASE=Wireless Seismic + +OUI:08BA22* + ID_OUI_FROM_DATABASE=Swaive Corporation + +OUI:08BA5F* + ID_OUI_FROM_DATABASE=Qingdao Hisense Electronics Co.,Ltd. + +OUI:08BBCC* + ID_OUI_FROM_DATABASE=AK-NORD EDV VERTRIEBSGES. mbH + +OUI:08BC20* + ID_OUI_FROM_DATABASE=Hangzhou Royal Cloud Technology Co., Ltd + +OUI:08BD43* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:08BE09* + ID_OUI_FROM_DATABASE=Astrol Electronic AG + +OUI:08BE77* + ID_OUI_FROM_DATABASE=Green Electronics + +OUI:08BEAC* + ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. + +OUI:08BFA0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:08C021* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:08C0EB* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:08C5E1* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:08C6B3* + ID_OUI_FROM_DATABASE=QTECH LLC + +OUI:08CA45* + ID_OUI_FROM_DATABASE=Toyou Feiji Electronics Co., Ltd. + +OUI:08CC27* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:08CC68* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:08CCA7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:08CD9B* + ID_OUI_FROM_DATABASE=samtec automotive electronics & software GmbH + +OUI:08D09F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:08D0B7* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:08D23E* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:08D29A* + ID_OUI_FROM_DATABASE=Proformatique + +OUI:08D34B* + ID_OUI_FROM_DATABASE=Techman Electronics (Changshu) Co., Ltd. + +OUI:08D40C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:08D42B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:08D46A* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:08D59D* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:08D5C0* + ID_OUI_FROM_DATABASE=Seers Technology Co., Ltd + +OUI:08D833* + ID_OUI_FROM_DATABASE=Shenzhen RF Technology Co., Ltd + +OUI:08DF1F* + ID_OUI_FROM_DATABASE=Bose Corporation + +OUI:08DFCB* + ID_OUI_FROM_DATABASE=Systrome Networks + +OUI:08E5DA* + ID_OUI_FROM_DATABASE=NANJING FUJITSU COMPUTER PRODUCTS CO.,LTD. + +OUI:08E672* + ID_OUI_FROM_DATABASE=JEBSEE ELECTRONICS CO.,LTD. + +OUI:08E689* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:08E84F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:08EA40* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD + +OUI:08EA44* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:08EB29* + ID_OUI_FROM_DATABASE=Jiangsu Huitong Group Co.,Ltd. + +OUI:08EB74* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:08EBED* + ID_OUI_FROM_DATABASE=World Elite Technology Co.,LTD + +OUI:08ECA9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:08ECF5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:08ED020* + ID_OUI_FROM_DATABASE=D2SLink Systems + +OUI:08ED021* + ID_OUI_FROM_DATABASE=Imperx, Inc + +OUI:08ED022* + ID_OUI_FROM_DATABASE=TES Touch Embedded Solutions Inc. + +OUI:08ED023* + ID_OUI_FROM_DATABASE=Jiangsu Logread Network Technology Co., LTD. + +OUI:08ED024* + ID_OUI_FROM_DATABASE=Fio Corporation + +OUI:08ED025* + ID_OUI_FROM_DATABASE=Vigitron Inc. + +OUI:08ED026* + ID_OUI_FROM_DATABASE=SANGO ELECTRONICS CO + +OUI:08ED027* + ID_OUI_FROM_DATABASE=Eleven Engineering Incorporated + +OUI:08ED028* + ID_OUI_FROM_DATABASE=HANTAS CO., LTD. + +OUI:08ED029* + ID_OUI_FROM_DATABASE=Savox Communications + +OUI:08ED02A* + ID_OUI_FROM_DATABASE=Victiana SRL + +OUI:08ED02B* + ID_OUI_FROM_DATABASE=Szok Energy and Communication Co., Ltd. + +OUI:08ED02C* + ID_OUI_FROM_DATABASE=Guard RFID Solutions + +OUI:08ED02D* + ID_OUI_FROM_DATABASE=Origami Energy Ltd + +OUI:08ED02E* + ID_OUI_FROM_DATABASE=Telstra Corporation Limited + +OUI:08EDB9* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:08EDED* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:08EE8B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:08EF3B* + ID_OUI_FROM_DATABASE=MCS Logic Inc. + +OUI:08EFAB* + ID_OUI_FROM_DATABASE=SAYME WIRELESS SENSOR NETWORK + +OUI:08F1B7* + ID_OUI_FROM_DATABASE=Towerstream Corpration + +OUI:08F1EA* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:08F2F4* + ID_OUI_FROM_DATABASE=Net One Partners Co.,Ltd. + +OUI:08F458* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:08F4AB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:08F69C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:08F6F8* + ID_OUI_FROM_DATABASE=GET Engineering + +OUI:08F728* + ID_OUI_FROM_DATABASE=GLOBO Multimedia Sp. z o.o. Sp.k. + +OUI:08F7E9* + ID_OUI_FROM_DATABASE=HRCP Research and Development Partnership + +OUI:08F8BC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:08FAE0* + ID_OUI_FROM_DATABASE=Fohhn Audio AG + +OUI:08FC52* + ID_OUI_FROM_DATABASE=OpenXS BV + +OUI:08FC88* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:08FD0E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0C01DB* + ID_OUI_FROM_DATABASE=Infinix mobility limited + +OUI:0C0227* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:0C0400* + ID_OUI_FROM_DATABASE=Jantar d.o.o. + +OUI:0C0535* + ID_OUI_FROM_DATABASE=Juniper Systems + +OUI:0C08B4* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:0C1105* + ID_OUI_FROM_DATABASE=AKUVOX (XIAMEN) NETWORKS CO., LTD + +OUI:0C1167* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0C1262* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:0C130B* + ID_OUI_FROM_DATABASE=Uniqoteq Ltd. + +OUI:0C1420* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0C1539* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C15C5* + ID_OUI_FROM_DATABASE=SDTEC Co., Ltd. + +OUI:0C17F1* + ID_OUI_FROM_DATABASE=TELECSYS + +OUI:0C191F* + ID_OUI_FROM_DATABASE=Inform Electronik + +OUI:0C1A10* + ID_OUI_FROM_DATABASE=Acoustic Stream + +OUI:0C1C19* + ID_OUI_FROM_DATABASE=LONGCONN ELECTRONICS(SHENZHEN) CO.,LTD + +OUI:0C1C20* + ID_OUI_FROM_DATABASE=Kakao Corp + +OUI:0C1C57* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0C1DAF* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:0C1DC2* + ID_OUI_FROM_DATABASE=SeAH Networks + +OUI:0C2026* + ID_OUI_FROM_DATABASE=noax Technologies AG + +OUI:0C20D3* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:0C2138* + ID_OUI_FROM_DATABASE=Hengstler GmbH + +OUI:0C2369* + ID_OUI_FROM_DATABASE=Honeywell SPS + +OUI:0C2576* + ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED + +OUI:0C2724* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0C2755* + ID_OUI_FROM_DATABASE=Valuable Techologies Limited + +OUI:0C29EF* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:0C2A69* + ID_OUI_FROM_DATABASE=electric imp, incorporated + +OUI:0C2A86* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:0C2AE7* + ID_OUI_FROM_DATABASE=Beijing General Research Institute of Mining and Metallurgy + +OUI:0C2C54* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0C2D89* + ID_OUI_FROM_DATABASE=QiiQ Communications Inc. + +OUI:0C2FB0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0C3021* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C35FE* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:0C3747* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:0C3796* + ID_OUI_FROM_DATABASE=BIZLINK TECHNOLOGY, INC. + +OUI:0C37DC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0C383E* + ID_OUI_FROM_DATABASE=Fanvil Technology Co., Ltd. + +OUI:0C3956* + ID_OUI_FROM_DATABASE=Observator instruments + +OUI:0C3C65* + ID_OUI_FROM_DATABASE=Dome Imaging Inc + +OUI:0C3CCD* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:0C3E9F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C4101* + ID_OUI_FROM_DATABASE=Ruichi Auto Technology (Guangzhou) Co., Ltd. + +OUI:0C413E* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:0C41E9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0C42A1* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:0C45BA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0C469D* + ID_OUI_FROM_DATABASE=MS Sedco + +OUI:0C473D* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:0C47C9* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:0C4885* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:0C48C6* + ID_OUI_FROM_DATABASE=CELESTICA INC. + +OUI:0C4933* + ID_OUI_FROM_DATABASE=Sichuan Jiuzhou Electronic Technology Co., Ltd. + +OUI:0C4B54* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:0C4C39* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:0C4DE9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C4F5A* + ID_OUI_FROM_DATABASE=ASA-RT s.r.l. + +OUI:0C5101* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C51F7* + ID_OUI_FROM_DATABASE=CHAUVIN ARNOUX + +OUI:0C5203* + ID_OUI_FROM_DATABASE=AGM GROUP LIMITED + +OUI:0C5331* + ID_OUI_FROM_DATABASE=ETH Zurich + +OUI:0C5415* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0C54A5* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:0C54B9* + ID_OUI_FROM_DATABASE=Nokia + +OUI:0C5521* + ID_OUI_FROM_DATABASE=Axiros GmbH + +OUI:0C565C* + ID_OUI_FROM_DATABASE=HyBroad Vision (Hong Kong) Technology Co Ltd + +OUI:0C57EB* + ID_OUI_FROM_DATABASE=Mueller Systems + +OUI:0C5842* + ID_OUI_FROM_DATABASE=DME Micro + +OUI:0C5A19* + ID_OUI_FROM_DATABASE=Axtion Sdn Bhd + +OUI:0C5A9E* + ID_OUI_FROM_DATABASE=Wi-SUN Alliance + +OUI:0C5CD8* + ID_OUI_FROM_DATABASE=DOLI Elektronik GmbH + +OUI:0C5F35* + ID_OUI_FROM_DATABASE=Niagara Video Corporation + +OUI:0C6076* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:0C6111* + ID_OUI_FROM_DATABASE=Anda Technologies SAC + +OUI:0C6127* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:0C61CF* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0C62A6* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:0C63FC* + ID_OUI_FROM_DATABASE=Nanjing Signway Technology Co., Ltd + +OUI:0C6803* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0C6ABC* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:0C6AE6* + ID_OUI_FROM_DATABASE=Stanley Security Solutions + +OUI:0C6E4F* + ID_OUI_FROM_DATABASE=PrimeVOLT Co., Ltd. + +OUI:0C6F9C* + ID_OUI_FROM_DATABASE=Shaw Communications Inc. + +OUI:0C704A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0C715D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0C722C* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:0C72D9* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:0C73BE* + ID_OUI_FROM_DATABASE=Dongguan Haimai Electronie Technology Co.,Ltd + +OUI:0C73EB0* + ID_OUI_FROM_DATABASE=Gemini Data Loggers (UK) Limited + +OUI:0C73EB1* + ID_OUI_FROM_DATABASE=EVERSEC TECHNOLOGY CORPORATION + +OUI:0C73EB2* + ID_OUI_FROM_DATABASE=Deltapath, Inc. + +OUI:0C73EB3* + ID_OUI_FROM_DATABASE=Tiinlab Acoustic Technology (Shenzhen) Co., Ltd. + +OUI:0C73EB4* + ID_OUI_FROM_DATABASE=U-PASS.CO.,LTD + +OUI:0C73EB5* + ID_OUI_FROM_DATABASE=Husty M.Styczen J.Hupert Sp.J. + +OUI:0C73EB6* + ID_OUI_FROM_DATABASE=Green Fox Electro AS + +OUI:0C73EB7* + ID_OUI_FROM_DATABASE=Dinkle Enterprise Co., Ltd. + +OUI:0C73EB8* + ID_OUI_FROM_DATABASE=Beijing Miiiw Technology Co., Ltd + +OUI:0C73EB9* + ID_OUI_FROM_DATABASE=Beijing L&S Lancom Platform Tech. Co., Ltd. + +OUI:0C73EBA* + ID_OUI_FROM_DATABASE=Pi Innovo LLC + +OUI:0C73EBB* + ID_OUI_FROM_DATABASE=Synaccess Networks + +OUI:0C73EBC* + ID_OUI_FROM_DATABASE=Shenzhen Samchung Video Technology Co., Ltd. + +OUI:0C73EBD* + ID_OUI_FROM_DATABASE=D-Link (Shanghai)Limited Corp. + +OUI:0C73EBE* + ID_OUI_FROM_DATABASE=Taiwan Pulse Motion Co., Ltd. + +OUI:0C74C2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C7512* + ID_OUI_FROM_DATABASE=Shenzhen Kunlun TongTai Technology Co.,Ltd. + +OUI:0C7523* + ID_OUI_FROM_DATABASE=BEIJING GEHUA CATV NETWORK CO.,LTD + +OUI:0C756C* + ID_OUI_FROM_DATABASE=Anaren Microwave, Inc. + +OUI:0C75BD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0C771A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0C7A15* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0C7C28* + ID_OUI_FROM_DATABASE=Nokia + +OUI:0C7D7C* + ID_OUI_FROM_DATABASE=Kexiang Information Technology Co, Ltd. + +OUI:0C8063* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:0C8112* + ID_OUI_FROM_DATABASE=Private + +OUI:0C8126* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:0C8230* + ID_OUI_FROM_DATABASE=SHENZHEN MAGNUS TECHNOLOGIES CO.,LTD + +OUI:0C8268* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:0C826A* + ID_OUI_FROM_DATABASE=Wuhan Huagong Genuine Optics Technology Co., Ltd + +OUI:0C839A* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:0C8411* + ID_OUI_FROM_DATABASE=A.O. Smith Water Products + +OUI:0C8447* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:0C8484* + ID_OUI_FROM_DATABASE=Zenovia Electronics Inc. + +OUI:0C84DC* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:0C8525* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0C8610* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:0C8910* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0C8A87* + ID_OUI_FROM_DATABASE=AgLogica Holdings, Inc + +OUI:0C8BD3* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:0C8BFD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0C8C24* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD + +OUI:0C8C8F* + ID_OUI_FROM_DATABASE=Kamo Technology Limited + +OUI:0C8CDC* + ID_OUI_FROM_DATABASE=Suunto Oy + +OUI:0C8D98* + ID_OUI_FROM_DATABASE=TOP EIGHT IND CORP + +OUI:0C8DDB* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:0C8E29* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:0C8FFF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0C9160* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:0C924E* + ID_OUI_FROM_DATABASE=Rice Lake Weighing Systems + +OUI:0C9301* + ID_OUI_FROM_DATABASE=PT. Prasimax Inovasi Teknologi + +OUI:0C93FB* + ID_OUI_FROM_DATABASE=BNS Solutions + +OUI:0C9541* + ID_OUI_FROM_DATABASE=CHIPSEA TECHNOLOGIES (SHENZHEN) CORP. + +OUI:0C96BF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0C96E6* + ID_OUI_FROM_DATABASE=Cloud Network Technology (Samoa) Limited + +OUI:0C9838* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:0C9A42* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:0C9B13* + ID_OUI_FROM_DATABASE=Shanghai Magic Mobile Telecommunication Co.Ltd. + +OUI:0C9D56* + ID_OUI_FROM_DATABASE=Consort Controls Ltd + +OUI:0C9D92* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:0C9E91* + ID_OUI_FROM_DATABASE=Sankosha Corporation + +OUI:0CA06C* + ID_OUI_FROM_DATABASE=Industrial Cyber Sensing Inc. + +OUI:0CA138* + ID_OUI_FROM_DATABASE=Blinq Wireless Inc. + +OUI:0CA2F4* + ID_OUI_FROM_DATABASE=Chameleon Technology (UK) Limited + +OUI:0CA402* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:0CA42A* + ID_OUI_FROM_DATABASE=OB Telecom Electronic Technology Co., Ltd + +OUI:0CA694* + ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd + +OUI:0CA8A7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0CAC05* + ID_OUI_FROM_DATABASE=Unitend Technologies Inc. + +OUI:0CAE7D* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0CAF5A* + ID_OUI_FROM_DATABASE=GENUS POWER INFRASTRUCTURES LIMITED + +OUI:0CB2B7* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:0CB319* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0CB34F* + ID_OUI_FROM_DATABASE=Shenzhen Xiaoqi Intelligent Technology Co., Ltd. + +OUI:0CB459* + ID_OUI_FROM_DATABASE=Marketech International Corp. + +OUI:0CB4A4* + ID_OUI_FROM_DATABASE=Xintai Automobile Intelligent Network Technology + +OUI:0CB4EF* + ID_OUI_FROM_DATABASE=Digience Co.,Ltd. + +OUI:0CB527* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0CB5DE* + ID_OUI_FROM_DATABASE=Alcatel Lucent + +OUI:0CB6D2* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:0CB771* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0CB912* + ID_OUI_FROM_DATABASE=JM-DATA GmbH + +OUI:0CB937* + ID_OUI_FROM_DATABASE=Ubee Interactive Co., Limited + +OUI:0CBC9F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0CBD51* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:0CBF15* + ID_OUI_FROM_DATABASE=Genetec Inc. + +OUI:0CBF3F* + ID_OUI_FROM_DATABASE=Shenzhen Lencotion Technology Co.,Ltd + +OUI:0CBF74* + ID_OUI_FROM_DATABASE=Morse Micro + +OUI:0CC0C0* + ID_OUI_FROM_DATABASE=MAGNETI MARELLI SISTEMAS ELECTRONICOS MEXICO + +OUI:0CC3A7* + ID_OUI_FROM_DATABASE=Meritec + +OUI:0CC47A* + ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. + +OUI:0CC47E* + ID_OUI_FROM_DATABASE=EUCAST Co., Ltd. + +OUI:0CC655* + ID_OUI_FROM_DATABASE=Wuxi YSTen Technology Co.,Ltd. + +OUI:0CC66A* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:0CC6AC* + ID_OUI_FROM_DATABASE=DAGS + +OUI:0CC6CC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0CC731* + ID_OUI_FROM_DATABASE=Currant, Inc. + +OUI:0CC81F* + ID_OUI_FROM_DATABASE=Summer Infant, Inc. + +OUI:0CC9C6* + ID_OUI_FROM_DATABASE=Samwin Hong Kong Limited + +OUI:0CCB85* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:0CCB8D* + ID_OUI_FROM_DATABASE=ASCO Numatics GmbH + +OUI:0CCC26* + ID_OUI_FROM_DATABASE=Airenetworks + +OUI:0CCDD3* + ID_OUI_FROM_DATABASE=EASTRIVER TECHNOLOGY CO., LTD. + +OUI:0CCDFB* + ID_OUI_FROM_DATABASE=EDIC Systems Inc. + +OUI:0CCEF6* + ID_OUI_FROM_DATABASE=Guizhou Fortuneship Technology Co., Ltd + +OUI:0CCFD1* + ID_OUI_FROM_DATABASE=SPRINGWAVE Co., Ltd + +OUI:0CD0F8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0CD292* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0CD2B5* + ID_OUI_FROM_DATABASE=Binatone Telecommunication Pvt. Ltd + +OUI:0CD502* + ID_OUI_FROM_DATABASE=Westell Technologies Inc. + +OUI:0CD696* + ID_OUI_FROM_DATABASE=Amimon Ltd + +OUI:0CD6BD* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:0CD746* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:0CD7C2* + ID_OUI_FROM_DATABASE=Axium Technologies, Inc. + +OUI:0CD86C* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:0CD996* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0CD9C1* + ID_OUI_FROM_DATABASE=Visteon Corporation + +OUI:0CDA41* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:0CDCCC* + ID_OUI_FROM_DATABASE=Inala Technologies + +OUI:0CDD24* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:0CDDEF* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:0CDFA4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0CE041* + ID_OUI_FROM_DATABASE=iDruide + +OUI:0CE0DC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:0CE0E4* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. + +OUI:0CE4A0* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:0CE5D3* + ID_OUI_FROM_DATABASE=DH electronics GmbH + +OUI:0CE709* + ID_OUI_FROM_DATABASE=Fox Crypto B.V. + +OUI:0CE725* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:0CE82F* + ID_OUI_FROM_DATABASE=Bonfiglioli Vectron GmbH + +OUI:0CE936* + ID_OUI_FROM_DATABASE=ELIMOS srl + +OUI:0CE99A* + ID_OUI_FROM_DATABASE=ATLS ALTEC + +OUI:0CEAC9* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0CEC84* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:0CEE99* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:0CEEE6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:0CEF7C* + ID_OUI_FROM_DATABASE=AnaCom Inc + +OUI:0CEFAF0* + ID_OUI_FROM_DATABASE=Kenmore + +OUI:0CEFAF1* + ID_OUI_FROM_DATABASE=Goerlitz AG + +OUI:0CEFAF2* + ID_OUI_FROM_DATABASE=LUMEL S.A. + +OUI:0CEFAF3* + ID_OUI_FROM_DATABASE=Engineering Center ENERGOSERVICE + +OUI:0CEFAF4* + ID_OUI_FROM_DATABASE=Sentry360 + +OUI:0CEFAF5* + ID_OUI_FROM_DATABASE=PREMIUM SA + +OUI:0CEFAF6* + ID_OUI_FROM_DATABASE=Firmware Design AS + +OUI:0CEFAF7* + ID_OUI_FROM_DATABASE=Syntrans AB + +OUI:0CEFAF8* + ID_OUI_FROM_DATABASE=BSX Athletics + +OUI:0CEFAF9* + ID_OUI_FROM_DATABASE=Rotel + +OUI:0CEFAFA* + ID_OUI_FROM_DATABASE=chengdu joyotime Technology Co., Ltd. + +OUI:0CEFAFB* + ID_OUI_FROM_DATABASE=Hubei Century Network Technology Co., Ltd + +OUI:0CEFAFC* + ID_OUI_FROM_DATABASE=GainStrong Industry Co.,Ltd + +OUI:0CEFAFD* + ID_OUI_FROM_DATABASE=CJSC «Svyaz Engineering» + +OUI:0CEFAFE* + ID_OUI_FROM_DATABASE=Infinisource Inc. + +OUI:0CEFAFF* + ID_OUI_FROM_DATABASE=Private + +OUI:0CF019* + ID_OUI_FROM_DATABASE=Malgn Technology Co., Ltd. + +OUI:0CF0B4* + ID_OUI_FROM_DATABASE=Globalsat International Technology Ltd + +OUI:0CF346* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:0CF361* + ID_OUI_FROM_DATABASE=Java Information + +OUI:0CF3EE* + ID_OUI_FROM_DATABASE=EM Microelectronic + +OUI:0CF405* + ID_OUI_FROM_DATABASE=Beijing Signalway Technologies Co.,Ltd + +OUI:0CF475* + ID_OUI_FROM_DATABASE=Zliide Technologies ApS + +OUI:0CF4D5* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:0CF5A4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:0CF893* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:0CF9C0* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:0CFC83* + ID_OUI_FROM_DATABASE=Airoha Technology Corp., + +OUI:0CFD37* + ID_OUI_FROM_DATABASE=SUSE Linux GmbH + +OUI:0CFE45* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:0CFE5D0* + ID_OUI_FROM_DATABASE=Chengdu Ledong Information & Technology Co., Ltd. + +OUI:0CFE5D1* + ID_OUI_FROM_DATABASE=Fender Musical Instrument + +OUI:0CFE5D2* + ID_OUI_FROM_DATABASE=Dspread International Co.,Limited + +OUI:0CFE5D3* + ID_OUI_FROM_DATABASE=Beijing WayClouds Technology Co., Ltd. + +OUI:0CFE5D4* + ID_OUI_FROM_DATABASE=Yantai Dongfang Wisdom Electic Co.,Ltd. + +OUI:0CFE5D5* + ID_OUI_FROM_DATABASE=SELECTRIC Nachrichten-Systeme GmbH + +OUI:0CFE5D6* + ID_OUI_FROM_DATABASE=Antailiye Technology Co.,Ltd + +OUI:0CFE5D7* + ID_OUI_FROM_DATABASE=Vermes Microdispensing GmbH + +OUI:0CFE5D8* + ID_OUI_FROM_DATABASE=CTK Contact Electronics co., Ltd. + +OUI:0CFE5D9* + ID_OUI_FROM_DATABASE=Celerway Communication AS + +OUI:0CFE5DA* + ID_OUI_FROM_DATABASE=Fujian Jieyu Computer Technology Co., Ltd. + +OUI:0CFE5DB* + ID_OUI_FROM_DATABASE=YINUO-LINK LIMITED + +OUI:0CFE5DC* + ID_OUI_FROM_DATABASE=Bepal Technology Co.,Ltd. + +OUI:0CFE5DD* + ID_OUI_FROM_DATABASE=Maksat Technologies P Ltd + +OUI:0CFE5DE* + ID_OUI_FROM_DATABASE=NEWGREEN TECH CO., LTD. + +OUI:100000* + ID_OUI_FROM_DATABASE=Private + +OUI:10005A* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:1000E8* + ID_OUI_FROM_DATABASE=NATIONAL SEMICONDUCTOR + +OUI:1000FD* + ID_OUI_FROM_DATABASE=LaonPeople + +OUI:100177* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1001CA* + ID_OUI_FROM_DATABASE=Ashley Butterworth + +OUI:1002B5* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:100501* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:1005B1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:1005CA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1005E1* + ID_OUI_FROM_DATABASE=Nokia + +OUI:1007230* + ID_OUI_FROM_DATABASE=RippleTek Tech Ltd + +OUI:1007231* + ID_OUI_FROM_DATABASE=Beijing Assem Technology Co., ltd + +OUI:1007232* + ID_OUI_FROM_DATABASE=Diginet Control Systems Pty Ltd + +OUI:1007233* + ID_OUI_FROM_DATABASE=Tongfang computer co.Ltd. + +OUI:1007234* + ID_OUI_FROM_DATABASE=Audio Engineering Ltd. + +OUI:1007235* + ID_OUI_FROM_DATABASE=BEIJING SOOALL INFORMATION TECHNOLOGY CO.,LTD + +OUI:1007236* + ID_OUI_FROM_DATABASE=ESTONE TECHNOLOGY INC + +OUI:1007237* + ID_OUI_FROM_DATABASE=nanoTech Co., Ltd. + +OUI:1007238* + ID_OUI_FROM_DATABASE=Ion Professional Solutions + +OUI:1007239* + ID_OUI_FROM_DATABASE=Wireless input technology Inc. + +OUI:100723A* + ID_OUI_FROM_DATABASE=TESSERA TECHNOLOGY INC. + +OUI:100723B* + ID_OUI_FROM_DATABASE=Fujian Quanzhou Dong Ang Electronics Co., Ltd. + +OUI:100723C* + ID_OUI_FROM_DATABASE=Shenzhen Xinfa Electronic Co.,ltd + +OUI:100723E* + ID_OUI_FROM_DATABASE=First Chair Acoustics Co., Ltd. + +OUI:100723F* + ID_OUI_FROM_DATABASE=Private + +OUI:1007B6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:10082C* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:1008B1* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:10090C* + ID_OUI_FROM_DATABASE=Janome Sewing Machine Co., Ltd. + +OUI:100BA9* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:100C24* + ID_OUI_FROM_DATABASE=pomdevices, LLC + +OUI:100C6B* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:100D2F* + ID_OUI_FROM_DATABASE=Online Security Pty. Ltd. + +OUI:100D32* + ID_OUI_FROM_DATABASE=Embedian, Inc. + +OUI:100D7F* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:100E2B* + ID_OUI_FROM_DATABASE=NEC CASIO Mobile Communications + +OUI:100E7E* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:100F18* + ID_OUI_FROM_DATABASE=Fu Gang Electronic(KunShan)CO.,LTD + +OUI:1010B6* + ID_OUI_FROM_DATABASE=McCain Inc + +OUI:101212* + ID_OUI_FROM_DATABASE=Vivo International Corporation Pty Ltd + +OUI:101218* + ID_OUI_FROM_DATABASE=Korins Inc. + +OUI:101248* + ID_OUI_FROM_DATABASE=ITG, Inc. + +OUI:101250* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:1012B4* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOM CO.,LTD + +OUI:101331* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:1013EE* + ID_OUI_FROM_DATABASE=Justec International Technology INC. + +OUI:10189E* + ID_OUI_FROM_DATABASE=Elmo Motion Control + +OUI:101B54* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:101C0C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:101D51* + ID_OUI_FROM_DATABASE=8Mesh Networks Limited + +OUI:101DC0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:101F74* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:102279* + ID_OUI_FROM_DATABASE=ZeroDesktop, Inc. + +OUI:1027BE* + ID_OUI_FROM_DATABASE=TVIP + +OUI:102831* + ID_OUI_FROM_DATABASE=Morion Inc. + +OUI:102959* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:102AB3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:102C6B* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:102C83* + ID_OUI_FROM_DATABASE=XIMEA + +OUI:102D96* + ID_OUI_FROM_DATABASE=Looxcie Inc. + +OUI:102EAF* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:102F6B* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:102FA3* + ID_OUI_FROM_DATABASE=Shenzhen Uvision-tech Technology Co.Ltd + +OUI:103025* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:103034* + ID_OUI_FROM_DATABASE=Cara Systems + +OUI:103047* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:10327E* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:103378* + ID_OUI_FROM_DATABASE=FLECTRON Co., LTD + +OUI:1033BF* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:10364A* + ID_OUI_FROM_DATABASE=Boston Dynamics + +OUI:103711* + ID_OUI_FROM_DATABASE=Simlink AS + +OUI:1039E9* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:103B59* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:103D0A* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:103D3E* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:103DEA* + ID_OUI_FROM_DATABASE=HFC Technology (Beijing) Ltd. Co. + +OUI:1040F3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:10417F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:104369* + ID_OUI_FROM_DATABASE=Soundmax Electronic Limited + +OUI:104400* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:10445A* + ID_OUI_FROM_DATABASE=Shaanxi Hitech Electronic Co., LTD + +OUI:1045BE* + ID_OUI_FROM_DATABASE=Norphonic AS + +OUI:1045F8* + ID_OUI_FROM_DATABASE=LNT-Automation GmbH + +OUI:1046B4* + ID_OUI_FROM_DATABASE=FormericaOE + +OUI:104780* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1048B1* + ID_OUI_FROM_DATABASE=Beijing Duokan Technology Limited + +OUI:104963* + ID_OUI_FROM_DATABASE=HARTING K.K. + +OUI:104A7D* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:104B46* + ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation + +OUI:104D77* + ID_OUI_FROM_DATABASE=Innovative Computer Engineering + +OUI:104E07* + ID_OUI_FROM_DATABASE=Shanghai Genvision Industries Co.,Ltd + +OUI:104E89* + ID_OUI_FROM_DATABASE=Garmin International + +OUI:104F58* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:104FA8* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:105072* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:105172* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:10521C* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:105611* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:1056CA* + ID_OUI_FROM_DATABASE=Peplink International Ltd. + +OUI:105887* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:105917* + ID_OUI_FROM_DATABASE=Tonal + +OUI:105932* + ID_OUI_FROM_DATABASE=Roku, Inc + +OUI:105AF7* + ID_OUI_FROM_DATABASE=ADB Italia + +OUI:105BAD* + ID_OUI_FROM_DATABASE=Mega Well Limited + +OUI:105C3B* + ID_OUI_FROM_DATABASE=Perma-Pipe, Inc. + +OUI:105CBF* + ID_OUI_FROM_DATABASE=DuroByte Inc + +OUI:105F06* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:105F49* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:105FD4* + ID_OUI_FROM_DATABASE=Tendyron Corporation + +OUI:10604B* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:1062C9* + ID_OUI_FROM_DATABASE=Adatis GmbH & Co. KG + +OUI:1062D0* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:1062E5* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:1062EB* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:1063C8* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:1064E2* + ID_OUI_FROM_DATABASE=ADFweb.com s.r.l. + +OUI:106530* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:1065A3* + ID_OUI_FROM_DATABASE=Core Brands LLC + +OUI:1065CF* + ID_OUI_FROM_DATABASE=IQSIM + +OUI:106682* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. + +OUI:10683F* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:106F3F* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:106FEF* + ID_OUI_FROM_DATABASE=Ad-Sol Nissin Corp + +OUI:1070FD* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:1071F9* + ID_OUI_FROM_DATABASE=Cloud Telecomputers, LLC + +OUI:107223* + ID_OUI_FROM_DATABASE=TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO + +OUI:10768A* + ID_OUI_FROM_DATABASE=EoCell + +OUI:107717* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + +OUI:1077B0* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:1077B1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:10785B* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:107873* + ID_OUI_FROM_DATABASE=Shenzhen Jinkeyi Communication Co., Ltd. + +OUI:1078CE* + ID_OUI_FROM_DATABASE=Hanvit SI, Inc. + +OUI:1078D2* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:107A86* + ID_OUI_FROM_DATABASE=U&U ENGINEERING INC. + +OUI:107B44* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:107BA4* + ID_OUI_FROM_DATABASE=Olive & Dove Co.,Ltd. + +OUI:107BEF* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:107D1A* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:1081B4* + ID_OUI_FROM_DATABASE=Hunan Greatwall Galaxy Science and Technology Co.,Ltd. + +OUI:108286* + ID_OUI_FROM_DATABASE=Luxshare Precision Industry Co.,Ltd + +OUI:1083D2* + ID_OUI_FROM_DATABASE=Microseven Systems, LLC + +OUI:10868C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:10880F* + ID_OUI_FROM_DATABASE=Daruma Telecomunicações e Informática S.A. + +OUI:1088CE* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:1089FB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:108A1B* + ID_OUI_FROM_DATABASE=RAONIX Inc. + +OUI:108CCF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:108EBA* + ID_OUI_FROM_DATABASE=Molekule + +OUI:108EE0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:109266* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:109397* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:1093E9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1094BB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:10954B* + ID_OUI_FROM_DATABASE=Megabyte Ltd. + +OUI:109836* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:1098C3* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:109AB9* + ID_OUI_FROM_DATABASE=Tosibox Oy + +OUI:109ADD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:109C70* + ID_OUI_FROM_DATABASE=Prusa Research s.r.o. + +OUI:109E3A* + ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd. + +OUI:109FA9* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:10A13B* + ID_OUI_FROM_DATABASE=FUJIKURA RUBBER LTD. + +OUI:10A24E* + ID_OUI_FROM_DATABASE=GOLD3LINK ELECTRONICS CO., LTD + +OUI:10A3B8* + ID_OUI_FROM_DATABASE=Iskratel d.o.o. + +OUI:10A4B9* + ID_OUI_FROM_DATABASE=Baidu Online Network Technology (Beijing) Co., Ltd + +OUI:10A4BE* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD + +OUI:10A5D0* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:10A659* + ID_OUI_FROM_DATABASE=Mobile Create Co.,Ltd. + +OUI:10A743* + ID_OUI_FROM_DATABASE=SK Mtek Limited + +OUI:10A932* + ID_OUI_FROM_DATABASE=Beijing Cyber Cloud Technology Co. ,Ltd. + +OUI:10AE60* + ID_OUI_FROM_DATABASE=Private + +OUI:10AF78* + ID_OUI_FROM_DATABASE=Shenzhen ATUE Technology Co., Ltd + +OUI:10B1F8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:10B26B* + ID_OUI_FROM_DATABASE=base Co.,Ltd. + +OUI:10B36F* + ID_OUI_FROM_DATABASE=Bowei Technology Company Limited + +OUI:10B3C6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:10B3D5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:10B3D6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:10B713* + ID_OUI_FROM_DATABASE=Private + +OUI:10B7F6* + ID_OUI_FROM_DATABASE=Plastoform Industries Ltd. + +OUI:10B9F7* + ID_OUI_FROM_DATABASE=Niko-Servodan + +OUI:10B9FE* + ID_OUI_FROM_DATABASE=Lika srl + +OUI:10BAA5* + ID_OUI_FROM_DATABASE=GANA I&C CO., LTD + +OUI:10BD18* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:10BD55* + ID_OUI_FROM_DATABASE=Q-Lab Corporation + +OUI:10BEF5* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:10BF48* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:10C07C* + ID_OUI_FROM_DATABASE=Blu-ray Disc Association + +OUI:10C172* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:10C22F* + ID_OUI_FROM_DATABASE=China Entropy Co., Ltd. + +OUI:10C25A* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:10C2BA* + ID_OUI_FROM_DATABASE=UTT Co., Ltd. + +OUI:10C37B* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:10C3AB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:10C586* + ID_OUI_FROM_DATABASE=BIO SOUND LAB CO., LTD. + +OUI:10C595* + ID_OUI_FROM_DATABASE=Lenovo + +OUI:10C60C* + ID_OUI_FROM_DATABASE=Domino UK Ltd + +OUI:10C61F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:10C65E* + ID_OUI_FROM_DATABASE=Adapt-IP + +OUI:10C67E* + ID_OUI_FROM_DATABASE=SHENZHEN JUCHIN TECHNOLOGY CO., LTD + +OUI:10C6FC* + ID_OUI_FROM_DATABASE=Garmin International + +OUI:10C73F* + ID_OUI_FROM_DATABASE=Midas Klark Teknik Ltd + +OUI:10C753* + ID_OUI_FROM_DATABASE=Qingdao Intelligent&Precise Electronics Co.,Ltd. + +OUI:10CA81* + ID_OUI_FROM_DATABASE=PRECIA + +OUI:10CC1B* + ID_OUI_FROM_DATABASE=Liverock technologies,INC + +OUI:10CCDB* + ID_OUI_FROM_DATABASE=AXIMUM PRODUITS ELECTRONIQUES + +OUI:10CD6E* + ID_OUI_FROM_DATABASE=FISYS + +OUI:10CDAE* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:10CDB6* + ID_OUI_FROM_DATABASE=Essential Products, Inc. + +OUI:10CE45* + ID_OUI_FROM_DATABASE=Miromico AG + +OUI:10CEA9* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:10D07A* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:10D0AB* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:10D1DC* + ID_OUI_FROM_DATABASE=INSTAR Deutschland GmbH + +OUI:10D38A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:10D542* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:10DA43* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:10DC4A* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:10DCB60* + ID_OUI_FROM_DATABASE=Private + +OUI:10DCB61* + ID_OUI_FROM_DATABASE=ABB Switzerland Ltd. + +OUI:10DCB62* + ID_OUI_FROM_DATABASE=CAL-COMP INDUSTRIA E COMERCIO DE ELETRONICOS E INFORMATICA LTDA + +OUI:10DCB63* + ID_OUI_FROM_DATABASE=HANACNS + +OUI:10DCB64* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:10DCB65* + ID_OUI_FROM_DATABASE=Milesight Taiwan + +OUI:10DCB66* + ID_OUI_FROM_DATABASE=Prolan Zrt. + +OUI:10DCB67* + ID_OUI_FROM_DATABASE=Moya Commumication Technology (Shenzhen) Co.,Ltd. + +OUI:10DCB68* + ID_OUI_FROM_DATABASE=Sanofi (Beijing) Pharmaceutical Co., Ltd. + +OUI:10DCB69* + ID_OUI_FROM_DATABASE=Fuzhou Rockchip Electronics Co.,Ltd + +OUI:10DCB6A* + ID_OUI_FROM_DATABASE=Pickering Interfaces Ltd + +OUI:10DCB6B* + ID_OUI_FROM_DATABASE=Eyeball Fintech Company + +OUI:10DCB6C* + ID_OUI_FROM_DATABASE=BBPOS International Limited + +OUI:10DCB6D* + ID_OUI_FROM_DATABASE=LeoLabs + +OUI:10DCB6E* + ID_OUI_FROM_DATABASE=Shenzhen Sunwoda intelligent hardware Co.,Ltd + +OUI:10DDB1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:10DDF4* + ID_OUI_FROM_DATABASE=Maxway Electronics CO.,LTD + +OUI:10DEE4* + ID_OUI_FROM_DATABASE=automationNEXT GmbH + +OUI:10DF8B* + ID_OUI_FROM_DATABASE=Shenzhen CareDear Communication Technology Co.,Ltd + +OUI:10DFFC* + ID_OUI_FROM_DATABASE=Siemens AG + +OUI:10E2D5* + ID_OUI_FROM_DATABASE=Qi Hardware Inc. + +OUI:10E3C7* + ID_OUI_FROM_DATABASE=Seohwa Telecom + +OUI:10E4AF* + ID_OUI_FROM_DATABASE=APR, LLC + +OUI:10E68F* + ID_OUI_FROM_DATABASE=KWANGSUNG ELECTRONICS KOREA CO.,LTD. + +OUI:10E6AE* + ID_OUI_FROM_DATABASE=Source Technologies, LLC + +OUI:10E7C6* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:10E878* + ID_OUI_FROM_DATABASE=Nokia + +OUI:10E8EE* + ID_OUI_FROM_DATABASE=PhaseSpace + +OUI:10E953* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:10EA59* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:10EED9* + ID_OUI_FROM_DATABASE=Canoga Perkins Corporation + +OUI:10F005* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:10F163* + ID_OUI_FROM_DATABASE=TNK CO.,LTD + +OUI:10F1F2* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:10F311* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:10F3DB* + ID_OUI_FROM_DATABASE=Gridco Systems, Inc. + +OUI:10F49A* + ID_OUI_FROM_DATABASE=T3 Innovation + +OUI:10F681* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:10F96F* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:10F9EB* + ID_OUI_FROM_DATABASE=Industria Fueguina de Relojería Electrónica s.a. + +OUI:10F9EE* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:10FACE* + ID_OUI_FROM_DATABASE=Reacheng Communication Technology Co.,Ltd + +OUI:10FBF0* + ID_OUI_FROM_DATABASE=KangSheng LTD. + +OUI:10FC54* + ID_OUI_FROM_DATABASE=Shany Electronic Co., Ltd. + +OUI:10FCB6* + ID_OUI_FROM_DATABASE=mirusystems CO.,LTD + +OUI:10FEED* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:1100AA* + ID_OUI_FROM_DATABASE=Private + +OUI:111111* + ID_OUI_FROM_DATABASE=Private + +OUI:1402EC* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:140467* + ID_OUI_FROM_DATABASE=SNK Technologies Co.,Ltd. + +OUI:140708* + ID_OUI_FROM_DATABASE=Private + +OUI:1407E0* + ID_OUI_FROM_DATABASE=Abrantix AG + +OUI:1409DC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:140AC5* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:140C5B* + ID_OUI_FROM_DATABASE=PLNetworks + +OUI:140C76* + ID_OUI_FROM_DATABASE=FREEBOX SAS + +OUI:140D4F* + ID_OUI_FROM_DATABASE=Flextronics International + +OUI:140F42* + ID_OUI_FROM_DATABASE=Nokia + +OUI:14109F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:141114* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:14115D* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:141330* + ID_OUI_FROM_DATABASE=Anakreon UK LLP + +OUI:141346* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:141357* + ID_OUI_FROM_DATABASE=ATP Electronics, Inc. + +OUI:14144B* + ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD + +OUI:141459* + ID_OUI_FROM_DATABASE=Vodafone Italia S.p.A. + +OUI:1414E6* + ID_OUI_FROM_DATABASE=Ningbo Sanhe Digital Co.,Ltd + +OUI:14157C* + ID_OUI_FROM_DATABASE=TOKYO COSMOS ELECTRIC CO.,LTD. + +OUI:14169D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:14169E* + ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited + +OUI:141877* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:141A51* + ID_OUI_FROM_DATABASE=Treetech Sistemas Digitais + +OUI:141AA3* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:141BBD* + ID_OUI_FROM_DATABASE=Volex Inc. + +OUI:141BF0* + ID_OUI_FROM_DATABASE=Intellimedia Systems Ltd + +OUI:141F78* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:141FBA0* + ID_OUI_FROM_DATABASE=Shenzhen Mining Technology Co.,Ltd. + +OUI:141FBA1* + ID_OUI_FROM_DATABASE=GloQuad + +OUI:141FBA2* + ID_OUI_FROM_DATABASE=Deutsche Energieversorgung GmbH + +OUI:141FBA3* + ID_OUI_FROM_DATABASE=Private + +OUI:141FBA4* + ID_OUI_FROM_DATABASE=BYZERO + +OUI:141FBA5* + ID_OUI_FROM_DATABASE=Inttelix Brasil Tecnologia e Sistemas Ltda + +OUI:141FBA6* + ID_OUI_FROM_DATABASE=Thales Communications & Security SAS + +OUI:141FBA7* + ID_OUI_FROM_DATABASE=Wisnetworks Technologies Co., Ltd. + +OUI:141FBA8* + ID_OUI_FROM_DATABASE=Shenzhen CATIC Information Technology Industry Co.,Ltd + +OUI:141FBA9* + ID_OUI_FROM_DATABASE=Black Moth Technologies + +OUI:141FBAA* + ID_OUI_FROM_DATABASE=Winsonic Electronics Co., Ltd. + +OUI:141FBAB* + ID_OUI_FROM_DATABASE=Newings Communication CO., LTD. + +OUI:141FBAC* + ID_OUI_FROM_DATABASE=Swiss Electronic (Shenzhen) Co., Ltd + +OUI:141FBAD* + ID_OUI_FROM_DATABASE=AJIS(DALIAN)co.,LTD + +OUI:141FBAE* + ID_OUI_FROM_DATABASE=POS Systema LLC + +OUI:141FBAF* + ID_OUI_FROM_DATABASE=Private + +OUI:14205E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:142233* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:1422DB* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:1423D7* + ID_OUI_FROM_DATABASE=EUTRONIX CO., LTD. + +OUI:142475* + ID_OUI_FROM_DATABASE=4DReplay, Inc + +OUI:142882* + ID_OUI_FROM_DATABASE=MIDICOM ELECTRONICS CO.LTD + +OUI:142971* + ID_OUI_FROM_DATABASE=NEMOA ELECTRONICS (HK) CO. LTD + +OUI:142A14* + ID_OUI_FROM_DATABASE=ShenZhen Selenview Digital Technology Co.,Ltd + +OUI:142BD2* + ID_OUI_FROM_DATABASE=Armtel Ltd. + +OUI:142BD6* + ID_OUI_FROM_DATABASE=Guangdong Appscomm Co.,Ltd + +OUI:142D27* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:142D8B* + ID_OUI_FROM_DATABASE=Incipio Technologies, Inc + +OUI:142DF5* + ID_OUI_FROM_DATABASE=Amphitech + +OUI:142E5E* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:142FFD* + ID_OUI_FROM_DATABASE=LT SECURITY INC + +OUI:143004* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:14307A* + ID_OUI_FROM_DATABASE=Avermetrics + +OUI:1430C6* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:1432D1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:143365* + ID_OUI_FROM_DATABASE=TEM Mobile Limited + +OUI:14358B* + ID_OUI_FROM_DATABASE=Mediabridge Products, LLC. + +OUI:1435B3* + ID_OUI_FROM_DATABASE=Future Designs, Inc. + +OUI:143605* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:1436C6* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:143719* + ID_OUI_FROM_DATABASE=PT Prakarsa Visi Valutama + +OUI:14373B* + ID_OUI_FROM_DATABASE=PROCOM Systems + +OUI:143AEA* + ID_OUI_FROM_DATABASE=Dynapower Company LLC + +OUI:143CC3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:143DF2* + ID_OUI_FROM_DATABASE=Beijing Shidai Hongyuan Network Communication Co.,Ltd + +OUI:143E60* + ID_OUI_FROM_DATABASE=Nokia + +OUI:143EBF* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:143F27* + ID_OUI_FROM_DATABASE=Noccela Oy + +OUI:144146* + ID_OUI_FROM_DATABASE=Honeywell (China) Co., LTD + +OUI:1441E2* + ID_OUI_FROM_DATABASE=Monaco Enterprises, Inc. + +OUI:1442FC* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:144319* + ID_OUI_FROM_DATABASE=Creative&Link Technology Limited + +OUI:14444A* + ID_OUI_FROM_DATABASE=Apollo Seiko Ltd. + +OUI:1446E4* + ID_OUI_FROM_DATABASE=AVISTEL + +OUI:14472D* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:144802* + ID_OUI_FROM_DATABASE=THE YEOLRIM Co.,Ltd. + +OUI:14488B* + ID_OUI_FROM_DATABASE=Shenzhen Doov Technology Co.,Ltd + +OUI:144978* + ID_OUI_FROM_DATABASE=Digital Control Incorporated + +OUI:1449BC* + ID_OUI_FROM_DATABASE=DrayTek Corp. + +OUI:1449E0* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:144C1A* + ID_OUI_FROM_DATABASE=Max Communication GmbH + +OUI:144D67* + ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. + +OUI:144E2A* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:144E34* + ID_OUI_FROM_DATABASE=Remote Solution + +OUI:144F8A* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:144FD70* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:144FD71* + ID_OUI_FROM_DATABASE=Zehnder Group AG + +OUI:144FD72* + ID_OUI_FROM_DATABASE=FedEx Services OTI + +OUI:144FD73* + ID_OUI_FROM_DATABASE=Qingdao Wodatong Electronics Co., Ltd. + +OUI:144FD74* + ID_OUI_FROM_DATABASE=Red Technology Limited + +OUI:144FD75* + ID_OUI_FROM_DATABASE=FLS FINLAND OY + +OUI:144FD76* + ID_OUI_FROM_DATABASE=i-SENS, Inc. + +OUI:144FD77* + ID_OUI_FROM_DATABASE=Shenzhen V-Streaming Technology Co., Ltd. + +OUI:144FD78* + ID_OUI_FROM_DATABASE=NPort Networks Inc., + +OUI:144FD79* + ID_OUI_FROM_DATABASE=Emerson Network Power (India) Pvt. Ltd. + +OUI:144FD7A* + ID_OUI_FROM_DATABASE=Unirobot Corporation + +OUI:144FD7B* + ID_OUI_FROM_DATABASE=Arkus-ST Ltd + +OUI:144FD7C* + ID_OUI_FROM_DATABASE=D&S Cable Industries (HK) Limited + +OUI:144FD7D* + ID_OUI_FROM_DATABASE=Shanghai B&A Technology Co., Ltd + +OUI:144FD7E* + ID_OUI_FROM_DATABASE=Edan Instruments, Inc. + +OUI:145290* + ID_OUI_FROM_DATABASE=KNS Group LLC (YADRO Company) + +OUI:145412* + ID_OUI_FROM_DATABASE=Entis Co., Ltd. + +OUI:145645* + ID_OUI_FROM_DATABASE=Savitech Corp. + +OUI:14568E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:14579F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1458D0* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:1459C0* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:1459C3* + ID_OUI_FROM_DATABASE=Creative Chips GmbH + +OUI:145A05* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:145A83* + ID_OUI_FROM_DATABASE=Logi-D inc + +OUI:145BD1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:145BE1* + ID_OUI_FROM_DATABASE=nyantec GmbH + +OUI:145E45* + ID_OUI_FROM_DATABASE=Kaleao Limited + +OUI:145F94* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:146080* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:1460CB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:146102* + ID_OUI_FROM_DATABASE=Alpine Electronics, Inc. + +OUI:14612F* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:146308* + ID_OUI_FROM_DATABASE=JABIL CIRCUIT (SHANGHAI) LTD. + +OUI:1469A2* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOM CO.,LTD + +OUI:146A0B* + ID_OUI_FROM_DATABASE=Cypress Electronics Limited + +OUI:146B72* + ID_OUI_FROM_DATABASE=Shenzhen Fortune Ship Technology Co., Ltd. + +OUI:146B9C* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD + +OUI:146E0A* + ID_OUI_FROM_DATABASE=Private + +OUI:147373* + ID_OUI_FROM_DATABASE=TUBITAK UEKAE + +OUI:147411* + ID_OUI_FROM_DATABASE=RIM + +OUI:147590* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:147740* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:14780B* + ID_OUI_FROM_DATABASE=Varex Imaging Deutschland AG + +OUI:1479F3* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:147BAC* + ID_OUI_FROM_DATABASE=Nokia + +OUI:147DB3* + ID_OUI_FROM_DATABASE=JOA TELECOM.CO.,LTD + +OUI:147DC5* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:14825B* + ID_OUI_FROM_DATABASE=Hefei Radio Communication Technology Co., Ltd + +OUI:148430* + ID_OUI_FROM_DATABASE=MITAC COMPUTING TECHNOLOGY CORPORATION + +OUI:148692* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:14876A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:14893E* + ID_OUI_FROM_DATABASE=VIXTEL TECHNOLOGIES LIMTED + +OUI:1489FD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:148A70* + ID_OUI_FROM_DATABASE=ADS GmbH + +OUI:148F21* + ID_OUI_FROM_DATABASE=Garmin International + +OUI:148FC6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:149090* + ID_OUI_FROM_DATABASE=KongTop industrial(shen zhen)CO.,LTD + +OUI:149138* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:149182* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:149346* + ID_OUI_FROM_DATABASE=PNI sensor corporation + +OUI:14942F* + ID_OUI_FROM_DATABASE=USYS CO.,LTD. + +OUI:149448* + ID_OUI_FROM_DATABASE=BLU CASTLE S.A. + +OUI:1495CE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1496E5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:14987D* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:1499E2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:149A10* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:149B2F* + ID_OUI_FROM_DATABASE=JiangSu ZhongXie Intelligent Technology co., LTD + +OUI:149D09* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:149D99* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:149ECF* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:149F3C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:149FB6* + ID_OUI_FROM_DATABASE=GUANGDONG GENIUS TECHNOLOGY CO., LTD. + +OUI:149FE8* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:14A0F8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:14A1BF* + ID_OUI_FROM_DATABASE=ASSA ABLOY Korea Co., Ltd Unilock + +OUI:14A2A0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:14A32F* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:14A364* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:14A51A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:14A62C* + ID_OUI_FROM_DATABASE=S.M. Dezac S.A. + +OUI:14A72B* + ID_OUI_FROM_DATABASE=currentoptronics Pvt.Ltd + +OUI:14A78B* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:14A86B* + ID_OUI_FROM_DATABASE=ShenZhen Telacom Science&Technology Co., Ltd + +OUI:14A9E3* + ID_OUI_FROM_DATABASE=MST CORPORATION + +OUI:14AB56* + ID_OUI_FROM_DATABASE=WUXI FUNIDE DIGITAL CO.,LTD + +OUI:14ABC5* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:14ABF0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:14ADCA* + ID_OUI_FROM_DATABASE=China Mobile Iot Limited company + +OUI:14AE850* + ID_OUI_FROM_DATABASE=Kayamatics Limited + +OUI:14AE851* + ID_OUI_FROM_DATABASE=Henfred Technology Co., Ltd. + +OUI:14AE852* + ID_OUI_FROM_DATABASE=Qingdao iTechene Technologies Co., Ltd. + +OUI:14AE853* + ID_OUI_FROM_DATABASE=IFLYTEK CO.,LTD. + +OUI:14AE854* + ID_OUI_FROM_DATABASE=CENTERVUE SPA + +OUI:14AE855* + ID_OUI_FROM_DATABASE=AZ-TECHNOLOGY SDN BHD + +OUI:14AE856* + ID_OUI_FROM_DATABASE=TMG TE GmbH + +OUI:14AE857* + ID_OUI_FROM_DATABASE=SHENZHEN HONOR ELECTRONIC CO.,LTD + +OUI:14AE858* + ID_OUI_FROM_DATABASE=Trimble LEM + +OUI:14AE859* + ID_OUI_FROM_DATABASE=Veo Technologies + +OUI:14AE85A* + ID_OUI_FROM_DATABASE=MTA Systems + +OUI:14AE85B* + ID_OUI_FROM_DATABASE=NTC SOFT + +OUI:14AE85C* + ID_OUI_FROM_DATABASE=IO Industries Inc. + +OUI:14AE85D* + ID_OUI_FROM_DATABASE=iSolution Technologies Co.,Ltd. + +OUI:14AE85E* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:14AEDB* + ID_OUI_FROM_DATABASE=VTech Telecommunications Ltd. + +OUI:14B126* + ID_OUI_FROM_DATABASE=Industrial Software Co + +OUI:14B1C8* + ID_OUI_FROM_DATABASE=InfiniWing, Inc. + +OUI:14B31F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:14B370* + ID_OUI_FROM_DATABASE=Gigaset Digital Technology (Shenzhen) Co., Ltd. + +OUI:14B457* + ID_OUI_FROM_DATABASE=Silicon Laboratories + +OUI:14B484* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:14B73D* + ID_OUI_FROM_DATABASE=ARCHEAN Technologies + +OUI:14B7F8* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:14B837* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:14B968* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:14BB6E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:14BD61* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:14C03E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:14C089* + ID_OUI_FROM_DATABASE=DUNE HD LTD + +OUI:14C126* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:14C1FF* + ID_OUI_FROM_DATABASE=ShenZhen QianHai Comlan communication Co.,LTD + +OUI:14C213* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:14C21D* + ID_OUI_FROM_DATABASE=Sabtech Industries + +OUI:14C3C2* + ID_OUI_FROM_DATABASE=K.A. Schmersal GmbH & Co. KG + +OUI:14C697* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:14C913* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:14CAA0* + ID_OUI_FROM_DATABASE=Hu&Co + +OUI:14CC20* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:14CF8D* + ID_OUI_FROM_DATABASE=OHSUNG + +OUI:14CF92* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:14CFE2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:14D00D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:14D11F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:14D169* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:14D4FE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:14D64D* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:14D76E* + ID_OUI_FROM_DATABASE=CONCH ELECTRONIC Co.,Ltd + +OUI:14DAE9* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:14DB85* + ID_OUI_FROM_DATABASE=S NET MEDIA + +OUI:14DDA9* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:14DDE5* + ID_OUI_FROM_DATABASE=MPMKVVCL + +OUI:14E4EC* + ID_OUI_FROM_DATABASE=mLogic LLC + +OUI:14E6E4* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:14E7C8* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:14E9B2* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:14EB33* + ID_OUI_FROM_DATABASE=BSMediasoft Co., Ltd. + +OUI:14EDA5* + ID_OUI_FROM_DATABASE=Wächter GmbH Sicherheitssysteme + +OUI:14EDBB* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:14EDE4* + ID_OUI_FROM_DATABASE=Kaiam Corporation + +OUI:14EE9D* + ID_OUI_FROM_DATABASE=AirNav Systems LLC + +OUI:14EFCF* + ID_OUI_FROM_DATABASE=SCHREDER + +OUI:14F0C5* + ID_OUI_FROM_DATABASE=Xtremio Ltd. + +OUI:14F28E* + ID_OUI_FROM_DATABASE=ShenYang ZhongKe-Allwin Technology Co.LTD + +OUI:14F42A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:14F65A* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:14F6D8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:14F893* + ID_OUI_FROM_DATABASE=Wuhan FiberHome Digital Technology Co.,Ltd. + +OUI:14FEAF* + ID_OUI_FROM_DATABASE=SAGITTAR LIMITED + +OUI:14FEB5* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:18002D* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:1800DB* + ID_OUI_FROM_DATABASE=Fitbit Inc. + +OUI:18017D* + ID_OUI_FROM_DATABASE=Harbin Arteor technology co., LTD + +OUI:1801E3* + ID_OUI_FROM_DATABASE=Bittium Wireless Ltd + +OUI:1801F1* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:18022D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1802AE* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:180373* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:1803FA* + ID_OUI_FROM_DATABASE=IBT Interfaces + +OUI:1804ED* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:180675* + ID_OUI_FROM_DATABASE=Dilax Intelcom GmbH + +OUI:1806F5* + ID_OUI_FROM_DATABASE=RAD Data Communications, Ltd. + +OUI:1806FF* + ID_OUI_FROM_DATABASE=Acer Computer(Shanghai) Limited. + +OUI:180B52* + ID_OUI_FROM_DATABASE=Nanotron Technologies GmbH + +OUI:180C14* + ID_OUI_FROM_DATABASE=iSonea Limited + +OUI:180C77* + ID_OUI_FROM_DATABASE=Westinghouse Electric Company, LLC + +OUI:180CAC* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:180D2C* + ID_OUI_FROM_DATABASE=Intelbras + +OUI:180F76* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:18104E* + ID_OUI_FROM_DATABASE=CEDINT-UPM + +OUI:181212* + ID_OUI_FROM_DATABASE=Cepton Technologies + +OUI:18132D* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:181420* + ID_OUI_FROM_DATABASE=TEB SAS + +OUI:181456* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:1816C9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:181714* + ID_OUI_FROM_DATABASE=DAEWOOIS + +OUI:181725* + ID_OUI_FROM_DATABASE=Cameo Communications, Inc. + +OUI:18193F* + ID_OUI_FROM_DATABASE=Tamtron Oy + +OUI:1819D6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:181BEB* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:181DEA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:181E78* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:181E95* + ID_OUI_FROM_DATABASE=AuVerte + +OUI:181EB0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:182012* + ID_OUI_FROM_DATABASE=Aztech Associates Inc. + +OUI:182032* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:18204C* + ID_OUI_FROM_DATABASE=Kummler+Matter AG + +OUI:1820A6* + ID_OUI_FROM_DATABASE=Sage Co., Ltd. + +OUI:1820D5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:182195* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:18227E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:182666* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:182861* + ID_OUI_FROM_DATABASE=AirTies Wireless Networks + +OUI:182A44* + ID_OUI_FROM_DATABASE=HIROSE ELECTRONIC SYSTEM + +OUI:182A7B* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:182AD3* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:182B05* + ID_OUI_FROM_DATABASE=8D Technologies + +OUI:182C91* + ID_OUI_FROM_DATABASE=Concept Development, Inc. + +OUI:182CB4* + ID_OUI_FROM_DATABASE=Nectarsoft Co., Ltd. + +OUI:182D98* + ID_OUI_FROM_DATABASE=Jinwoo Industrial system + +OUI:183009* + ID_OUI_FROM_DATABASE=Woojin Industrial Systems Co., Ltd. + +OUI:18300C* + ID_OUI_FROM_DATABASE=Hisense Electric Co.,Ltd + +OUI:1831BF* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:1832A2* + ID_OUI_FROM_DATABASE=LAON TECHNOLOGY CO., LTD. + +OUI:18339D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:183451* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1835D1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:1836FC* + ID_OUI_FROM_DATABASE=Elecsys International Corporation + +OUI:183825* + ID_OUI_FROM_DATABASE=Wuhan Lingjiu High-tech Co.,Ltd. + +OUI:183864* + ID_OUI_FROM_DATABASE=CAP-TECH INTERNATIONAL CO., LTD. + +OUI:1838AE* + ID_OUI_FROM_DATABASE=CONSPIN SOLUTION + +OUI:183919* + ID_OUI_FROM_DATABASE=Unicoi Systems + +OUI:18396E* + ID_OUI_FROM_DATABASE=SUNSEA TELECOMMUNICATIONS CO.,LTD. + +OUI:18399C* + ID_OUI_FROM_DATABASE=Skorpios Technologies + +OUI:183A2D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:183A48* + ID_OUI_FROM_DATABASE=VostroNet + +OUI:183BD2* + ID_OUI_FROM_DATABASE=BYD Precision Manufacture Company Ltd. + +OUI:183D5E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:183DA2* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:183F47* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1840A4* + ID_OUI_FROM_DATABASE=Shenzhen Trylong Smart Science and Technology Co., Ltd. + +OUI:18421D* + ID_OUI_FROM_DATABASE=Private + +OUI:18422F* + ID_OUI_FROM_DATABASE=Alcatel Lucent + +OUI:184462* + ID_OUI_FROM_DATABASE=Riava Networks, Inc. + +OUI:1844E6* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:184617* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:184644* + ID_OUI_FROM_DATABASE=Home Control Singapore Pte Ltd + +OUI:1848D8* + ID_OUI_FROM_DATABASE=Fastback Networks + +OUI:184A6F* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:184B0D* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:184BDF* + ID_OUI_FROM_DATABASE=Caavo Inc + +OUI:184C08* + ID_OUI_FROM_DATABASE=Rockwell Automation + +OUI:184E94* + ID_OUI_FROM_DATABASE=MESSOA TECHNOLOGIES INC. + +OUI:184F32* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:18502A* + ID_OUI_FROM_DATABASE=SOARNEX + +OUI:185207* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:185253* + ID_OUI_FROM_DATABASE=Pixord Corporation + +OUI:185282* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:1853E0* + ID_OUI_FROM_DATABASE=Hanyang Digitech Co.Ltd + +OUI:1854CF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:18550F* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:1855E3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:185644* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:185680* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:185869* + ID_OUI_FROM_DATABASE=Sailer Electronic Co., Ltd + +OUI:185933* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:185936* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:185A58* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:185AE8* + ID_OUI_FROM_DATABASE=Zenotech.Co.,Ltd + +OUI:185D9A* + ID_OUI_FROM_DATABASE=BobjGear LLC + +OUI:185E0F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:186024* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:1861C7* + ID_OUI_FROM_DATABASE=lemonbeat GmbH + +OUI:18622C* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:1862E4* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:186472* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:186571* + ID_OUI_FROM_DATABASE=Top Victory Electronics (Taiwan) Co., Ltd. + +OUI:186590* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1866C7* + ID_OUI_FROM_DATABASE=Shenzhen Libre Technology Co., Ltd + +OUI:1866DA* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:1866E3* + ID_OUI_FROM_DATABASE=Veros Systems, Inc. + +OUI:18673F* + ID_OUI_FROM_DATABASE=Hanover Displays Limited + +OUI:186751* + ID_OUI_FROM_DATABASE=KOMEG Industrielle Messtechnik GmbH + +OUI:1867B0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:18686A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:186882* + ID_OUI_FROM_DATABASE=Beward R&D Co., Ltd. + +OUI:1868CB* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:1869D8* + ID_OUI_FROM_DATABASE=HANGZHOU AIXIANGJI TECHNOLOGY CO., LTD + +OUI:1869DA* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:186D99* + ID_OUI_FROM_DATABASE=Adanis Inc. + +OUI:186F2D* + ID_OUI_FROM_DATABASE=Shenzhen Sundray Technologies Company Limited + +OUI:18703B* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:187117* + ID_OUI_FROM_DATABASE=eta plus electronic gmbh + +OUI:1871D5* + ID_OUI_FROM_DATABASE=Hazens Automotive Electronics(SZ)Co.,Ltd. + +OUI:18742E* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:187532* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:1878D4* + ID_OUI_FROM_DATABASE=Verizon + +OUI:1879A2* + ID_OUI_FROM_DATABASE=GMJ ELECTRIC LIMITED + +OUI:187A93* + ID_OUI_FROM_DATABASE=AMICCOM Electronics Corporation + +OUI:187C0B* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:187C81* + ID_OUI_FROM_DATABASE=Valeo Vision Systems + +OUI:187EB9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:187ED5* + ID_OUI_FROM_DATABASE=shenzhen kaism technology Co. Ltd + +OUI:188090* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1880CE* + ID_OUI_FROM_DATABASE=Barberry Solutions Ltd + +OUI:1880F5* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:18810E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:188219* + ID_OUI_FROM_DATABASE=Alibaba Cloud Computing Ltd. + +OUI:18828C* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:188331* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1883BF* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:188410* + ID_OUI_FROM_DATABASE=CoreTrust Inc. + +OUI:18863A* + ID_OUI_FROM_DATABASE=DIGITAL ART SYSTEM + +OUI:1886AC* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:188796* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:188857* + ID_OUI_FROM_DATABASE=Beijing Jinhong Xi-Dian Information Technology Corp. + +OUI:18895B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1889A0* + ID_OUI_FROM_DATABASE=Wuhan Funshion Online Technologies Co.,Ltd + +OUI:1889DF* + ID_OUI_FROM_DATABASE=CerebrEX Inc. + +OUI:188A6A* + ID_OUI_FROM_DATABASE=AVPro Global Hldgs + +OUI:188B15* + ID_OUI_FROM_DATABASE=ShenZhen ZhongRuiJing Technology co.,LTD + +OUI:188B45* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:188B9D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:188ED5* + ID_OUI_FROM_DATABASE=TP Vision Belgium N.V. - innovation site Brugge + +OUI:188EF9* + ID_OUI_FROM_DATABASE=G2C Co. Ltd. + +OUI:189088* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:1890D8* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:18922C* + ID_OUI_FROM_DATABASE=Virtual Instruments + +OUI:1892A4* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:18937F* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:1893D7* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:1894C6* + ID_OUI_FROM_DATABASE=ShenZhen Chenyee Technology Co., Ltd. + +OUI:1897FF* + ID_OUI_FROM_DATABASE=TechFaith Wireless Technology Limited + +OUI:1899F5* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. + +OUI:189A67* + ID_OUI_FROM_DATABASE=CSE-Servelec Limited + +OUI:189BA50* + ID_OUI_FROM_DATABASE=Dectris Ltd. + +OUI:189BA51* + ID_OUI_FROM_DATABASE=ChengDu Vantron Technology, Ltd. + +OUI:189BA52* + ID_OUI_FROM_DATABASE=Airprotec + +OUI:189BA53* + ID_OUI_FROM_DATABASE=PHINETWORKS + +OUI:189BA54* + ID_OUI_FROM_DATABASE=Innominds Software Inc + +OUI:189BA55* + ID_OUI_FROM_DATABASE=Starfire Industries LLC + +OUI:189BA56* + ID_OUI_FROM_DATABASE=Mantra Softech India Pvt Ltd + +OUI:189BA57* + ID_OUI_FROM_DATABASE=Beijing Xinertel Technology Co., Ltd. + +OUI:189BA58* + ID_OUI_FROM_DATABASE=Shenzhen Tong Tai Yi information Technology Co.,Ltd + +OUI:189BA59* + ID_OUI_FROM_DATABASE=APANA Inc. + +OUI:189BA5A* + ID_OUI_FROM_DATABASE=SHENZHEN FIONEXX TECHNOLOGIES LTD. + +OUI:189BA5B* + ID_OUI_FROM_DATABASE=Eutron SPA + +OUI:189BA5C* + ID_OUI_FROM_DATABASE=Christ Electronic System GmbH + +OUI:189BA5D* + ID_OUI_FROM_DATABASE=legendsky tech + +OUI:189BA5E* + ID_OUI_FROM_DATABASE=Taiwan Name Plate Co.,LTD + +OUI:189C27* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:189C5D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:189E2C* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:189EFC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:18A28A* + ID_OUI_FROM_DATABASE=Essel-T Co., Ltd + +OUI:18A3E8* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:18A4A9* + ID_OUI_FROM_DATABASE=Vanu Inc. + +OUI:18A6F7* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:18A7F1* + ID_OUI_FROM_DATABASE=Qingdao Haier Technology Co.,Ltd + +OUI:18A905* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:18A958* + ID_OUI_FROM_DATABASE=PROVISION THAI CO., LTD. + +OUI:18A99B* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:18AA45* + ID_OUI_FROM_DATABASE=Fon Technology + +OUI:18AACA* + ID_OUI_FROM_DATABASE=Sichuan tianyi kanghe communications co., LTD + +OUI:18ABF5* + ID_OUI_FROM_DATABASE=Ultra Electronics Electrics + +OUI:18AC9E* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:18AD4D* + ID_OUI_FROM_DATABASE=Polostar Technology Corporation + +OUI:18AEBB* + ID_OUI_FROM_DATABASE=Siemens Convergence Creators GmbH&Co.KG + +OUI:18AF61* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:18AF8F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:18AF9F* + ID_OUI_FROM_DATABASE=DIGITRONIC Automationsanlagen GmbH + +OUI:18B169* + ID_OUI_FROM_DATABASE=Sonicwall + +OUI:18B209* + ID_OUI_FROM_DATABASE=Torrey Pines Logic, Inc + +OUI:18B3BA* + ID_OUI_FROM_DATABASE=Netlogic AB + +OUI:18B430* + ID_OUI_FROM_DATABASE=Nest Labs Inc. + +OUI:18B591* + ID_OUI_FROM_DATABASE=I-Storm + +OUI:18B6F7* + ID_OUI_FROM_DATABASE=NEW POS TECHNOLOGY LIMITED + +OUI:18B79E* + ID_OUI_FROM_DATABASE=Invoxia + +OUI:18B81F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:18B905* + ID_OUI_FROM_DATABASE=Hong Kong Bouffalo Lab Limited + +OUI:18BB26* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:18BC5A* + ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd. + +OUI:18BDAD* + ID_OUI_FROM_DATABASE=L-TECH CORPORATION + +OUI:18BE92* + ID_OUI_FROM_DATABASE=Delta Networks, Inc. + +OUI:18BF1C* + ID_OUI_FROM_DATABASE=Jiangsu Huitong Group Co.,Ltd. + +OUI:18C04D* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:18C086* + ID_OUI_FROM_DATABASE=Broadcom + +OUI:18C19D* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:18C2BF* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:18C451* + ID_OUI_FROM_DATABASE=Tucson Embedded Systems + +OUI:18C501* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:18C58A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:18C8E7* + ID_OUI_FROM_DATABASE=Shenzhen Hualistone Technology Co.,Ltd + +OUI:18CC23* + ID_OUI_FROM_DATABASE=Philio Technology Corporation + +OUI:18CC88* + ID_OUI_FROM_DATABASE=Hitachi Johnson Controls Air + +OUI:18CF24* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:18CF5E* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:18D071* + ID_OUI_FROM_DATABASE=DASAN CO., LTD. + +OUI:18D0C5* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:18D225* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:18D276* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:18D5B6* + ID_OUI_FROM_DATABASE=SMG Holdings LLC + +OUI:18D66A* + ID_OUI_FROM_DATABASE=Inmarsat + +OUI:18D6C7* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:18D6CF* + ID_OUI_FROM_DATABASE=Kurth Electronic GmbH + +OUI:18D717* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:18D949* + ID_OUI_FROM_DATABASE=Qvis Labs, LLC + +OUI:18D98F* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:18D9EF* + ID_OUI_FROM_DATABASE=Shuttle Inc. + +OUI:18DBF2* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:18DC56* + ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + +OUI:18DED7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:18DFB4* + ID_OUI_FROM_DATABASE=BOSUNG POWERTEC CO.,LTD. + +OUI:18E1CA* + ID_OUI_FROM_DATABASE=wanze + +OUI:18E288* + ID_OUI_FROM_DATABASE=STT Condigi + +OUI:18E29F* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:18E2C2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:18E3BC* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:18E728* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:18E777* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:18E7F4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:18E80F* + ID_OUI_FROM_DATABASE=Viking Electronics Inc. + +OUI:18E829* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:18E8DD* + ID_OUI_FROM_DATABASE=MODULETEK + +OUI:18EE69* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:18EF63* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:18F0E4* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:18F145* + ID_OUI_FROM_DATABASE=NetComm Wireless Limited + +OUI:18F18E* + ID_OUI_FROM_DATABASE=ChipER Technology co. ltd + +OUI:18F1D8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:18F292* + ID_OUI_FROM_DATABASE=Shannon Systems + +OUI:18F46A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:18F643* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:18F650* + ID_OUI_FROM_DATABASE=Multimedia Pacific Limited + +OUI:18F76B* + ID_OUI_FROM_DATABASE=Zhejiang Winsight Technology CO.,LTD + +OUI:18F87A* + ID_OUI_FROM_DATABASE=i3 International Inc. + +OUI:18F9C4* + ID_OUI_FROM_DATABASE=BAE Systems + +OUI:18FA6F* + ID_OUI_FROM_DATABASE=ISC applied systems corp + +OUI:18FB7B* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:18FC9F* + ID_OUI_FROM_DATABASE=Changhe Electronics Co., Ltd. + +OUI:18FE34* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:18FF0F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:18FF2E* + ID_OUI_FROM_DATABASE=Shenzhen Rui Ying Da Technology Co., Ltd + +OUI:1C0042* + ID_OUI_FROM_DATABASE=NARI Technology Co., Ltd. + +OUI:1C0219* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:1C05B7* + ID_OUI_FROM_DATABASE=Chongqing Trantor Technology Co., Ltd. + +OUI:1C0656* + ID_OUI_FROM_DATABASE=IDY Corporation + +OUI:1C08C1* + ID_OUI_FROM_DATABASE=Lg Innotek + +OUI:1C0B52* + ID_OUI_FROM_DATABASE=EPICOM S.A + +OUI:1C0FAF* + ID_OUI_FROM_DATABASE=Lucid Vision Labs + +OUI:1C0FCF* + ID_OUI_FROM_DATABASE=Sypro Optics GmbH + +OUI:1C1161* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:1C11E1* + ID_OUI_FROM_DATABASE=Wartsila Finland Oy + +OUI:1C129D* + ID_OUI_FROM_DATABASE=IEEE PES PSRC/SUB + +OUI:1C12B0* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:1C1386* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:1C1448* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:1C14B3* + ID_OUI_FROM_DATABASE=Airwire Technologies + +OUI:1C151F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1C17D3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1C184A* + ID_OUI_FROM_DATABASE=ShenZhen RicherLink Technologies Co.,LTD + +OUI:1C19DE* + ID_OUI_FROM_DATABASE=eyevis GmbH + +OUI:1C1AC0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1C1ADF* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:1C1B0D* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:1C1B68* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:1C1BB5* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:1C1CFD* + ID_OUI_FROM_DATABASE=Dalian Hi-Think Computer Technology, Corp + +OUI:1C1D67* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1C1D86* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1C1E38* + ID_OUI_FROM_DATABASE=PCCW Global, Inc. + +OUI:1C1EE3* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:1C1FD4* + ID_OUI_FROM_DATABASE=LifeBEAM Technologies LTD + +OUI:1C20DB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1C21D10* + ID_OUI_FROM_DATABASE=Toyo System CO.,LTD. + +OUI:1C21D11* + ID_OUI_FROM_DATABASE=Ognios GmbH + +OUI:1C21D12* + ID_OUI_FROM_DATABASE=Varaani Works Oy + +OUI:1C21D13* + ID_OUI_FROM_DATABASE=Microview Science and Technology Co.,Ltd + +OUI:1C21D14* + ID_OUI_FROM_DATABASE=Scientific-Production Enterprise Dynamics + +OUI:1C21D15* + ID_OUI_FROM_DATABASE=B-Scada Inc. + +OUI:1C21D16* + ID_OUI_FROM_DATABASE=Wuhan TieChi Detection Technology Co., Ltd. + +OUI:1C21D17* + ID_OUI_FROM_DATABASE=Soundtrack Your Brand Sweden AB + +OUI:1C21D18* + ID_OUI_FROM_DATABASE=Reliatronics Inc. + +OUI:1C21D19* + ID_OUI_FROM_DATABASE=Dynojet Research + +OUI:1C21D1A* + ID_OUI_FROM_DATABASE=LG CNS + +OUI:1C21D1B* + ID_OUI_FROM_DATABASE=Global Design Solutions Ltd + +OUI:1C21D1C* + ID_OUI_FROM_DATABASE=Private + +OUI:1C21D1D* + ID_OUI_FROM_DATABASE=Liscotech System Co., Ltd. + +OUI:1C21D1E* + ID_OUI_FROM_DATABASE=p2-plus inc. + +OUI:1C21D1F* + ID_OUI_FROM_DATABASE=Private + +OUI:1C232C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1C234F* + ID_OUI_FROM_DATABASE=EDMI Europe Ltd + +OUI:1C24CD* + ID_OUI_FROM_DATABASE=Askey Computer Corp. + +OUI:1C24EB* + ID_OUI_FROM_DATABASE=Burlywood + +OUI:1C25E1* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:1C2704* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:1C27DD* + ID_OUI_FROM_DATABASE=Datang Gohighsec(zhejiang)Information Technology Co.,Ltd. + +OUI:1C2AA3* + ID_OUI_FROM_DATABASE=Shenzhen HongRui Optical Technology Co., Ltd. + +OUI:1C2E1B* + ID_OUI_FROM_DATABASE=Suzhou Tremenet Communication Technology Co., Ltd. + +OUI:1C330E* + ID_OUI_FROM_DATABASE=PernixData + +OUI:1C334D* + ID_OUI_FROM_DATABASE=ITS Telecom + +OUI:1C3477* + ID_OUI_FROM_DATABASE=Innovation Wireless + +OUI:1C34DA* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:1C35F1* + ID_OUI_FROM_DATABASE=NEW Lift Neue Elektronische Wege Steuerungsbau GmbH + +OUI:1C36BB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1C37BF* + ID_OUI_FROM_DATABASE=Cloudium Systems Ltd. + +OUI:1C3947* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:1C398A* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:1C3A4F* + ID_OUI_FROM_DATABASE=AccuSpec Electronics, LLC + +OUI:1C3A60* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:1C3ADE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1C3B8F* + ID_OUI_FROM_DATABASE=Selve GmbH & Co. KG + +OUI:1C3BF3* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:1C3DE7* + ID_OUI_FROM_DATABASE=Sigma Koki Co.,Ltd. + +OUI:1C3E84* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:1C4024* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:1C40E8* + ID_OUI_FROM_DATABASE=SHENZHEN PROGRESS&WIN TECHNOLOGY CO.,LTD + +OUI:1C4158* + ID_OUI_FROM_DATABASE=Gemalto M2M GmbH + +OUI:1C4176* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:1C427D* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:1C4363* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1C43EC* + ID_OUI_FROM_DATABASE=JAPAN CIRCUIT CO.,LTD + +OUI:1C4419* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:1C4455* + ID_OUI_FROM_DATABASE=Sieb & Meyer AG + +OUI:1C4593* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:1C4840* + ID_OUI_FROM_DATABASE=IMS Messsysteme GmbH + +OUI:1C48CE* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:1C48F9* + ID_OUI_FROM_DATABASE=GN Netcom A/S + +OUI:1C497B* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:1C4AF7* + ID_OUI_FROM_DATABASE=AMON INC + +OUI:1C4BB9* + ID_OUI_FROM_DATABASE=SMG ENTERPRISE, LLC + +OUI:1C4BD6* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:1C4D66* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:1C4D70* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:1C51B5* + ID_OUI_FROM_DATABASE=Techaya LTD + +OUI:1C5216* + ID_OUI_FROM_DATABASE=DONGGUAN HELE ELECTRONICS CO., LTD + +OUI:1C52D6* + ID_OUI_FROM_DATABASE=FLAT DISPLAY TECHNOLOGY CORPORATION + +OUI:1C549E* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. + +OUI:1C553A* + ID_OUI_FROM_DATABASE=QianGua Corp. + +OUI:1C56FE* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:1C57D8* + ID_OUI_FROM_DATABASE=Kraftway Corporation PLC + +OUI:1C599B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1C5A0B* + ID_OUI_FROM_DATABASE=Tegile Systems + +OUI:1C5A3E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1C5A6B* + ID_OUI_FROM_DATABASE=Philips Electronics Nederland BV + +OUI:1C5C55* + ID_OUI_FROM_DATABASE=PRIMA Cinema, Inc + +OUI:1C5C60* + ID_OUI_FROM_DATABASE=Shenzhen Belzon Technology Co.,LTD. + +OUI:1C5CF2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1C5F2B* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:1C5FFF* + ID_OUI_FROM_DATABASE=Beijing Ereneben Information Technology Co.,Ltd Shenzhen Branch + +OUI:1C60D2* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:1C60DE* + ID_OUI_FROM_DATABASE=MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:1C62B8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1C63B7* + ID_OUI_FROM_DATABASE=OpenProducts 237 AB + +OUI:1C63BF* + ID_OUI_FROM_DATABASE=SHENZHEN BROADTEL TELECOM CO.,LTD + +OUI:1C6499* + ID_OUI_FROM_DATABASE=Comtrend Corporation + +OUI:1C659D* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:1C666D* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:1C66AA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1C6758* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1C687E* + ID_OUI_FROM_DATABASE=Shenzhen Qihu Intelligent Technology Company Limited + +OUI:1C697A* + ID_OUI_FROM_DATABASE=EliteGroup Computer Systems Co., LTD + +OUI:1C69A5* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:1C6A7A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1C6BCA* + ID_OUI_FROM_DATABASE=Mitsunami Co., Ltd. + +OUI:1C6E4C* + ID_OUI_FROM_DATABASE=Logistic Service & Engineering Co.,Ltd + +OUI:1C6E76* + ID_OUI_FROM_DATABASE=Quarion Technology Inc + +OUI:1C6F65* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:1C7022* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:1C721D* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:1C7328* + ID_OUI_FROM_DATABASE=Connected Home + +OUI:1C7370* + ID_OUI_FROM_DATABASE=Neotech + +OUI:1C740D* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:1C7508* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:1C76CA* + ID_OUI_FROM_DATABASE=Terasic Technologies Inc. + +OUI:1C77F6* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:1C7839* + ID_OUI_FROM_DATABASE=Shenzhen Tencent Computer System Co., Ltd. + +OUI:1C784E* + ID_OUI_FROM_DATABASE=China Mobile Iot Limited company + +OUI:1C7B21* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:1C7B23* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:1C7C11* + ID_OUI_FROM_DATABASE=EID + +OUI:1C7C45* + ID_OUI_FROM_DATABASE=Vitek Industrial Video Products, Inc. + +OUI:1C7CC7* + ID_OUI_FROM_DATABASE=Coriant GmbH + +OUI:1C7D22* + ID_OUI_FROM_DATABASE=Fuji Xerox Co., Ltd. + +OUI:1C7E51* + ID_OUI_FROM_DATABASE=3bumen.com + +OUI:1C7EE5* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:1C7F2C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1C82590* + ID_OUI_FROM_DATABASE=Shandong Luneng Intelligence Technology CO., Ltd + +OUI:1C82591* + ID_OUI_FROM_DATABASE=3xLOGIC Inc. + +OUI:1C82592* + ID_OUI_FROM_DATABASE=Diatrend Corporation + +OUI:1C82593* + ID_OUI_FROM_DATABASE=C&A Marketing, INC. + +OUI:1C82594* + ID_OUI_FROM_DATABASE=winsun AG + +OUI:1C82595* + ID_OUI_FROM_DATABASE=Fagus-GreCon Greten GmbH & Co. KG + +OUI:1C82596* + ID_OUI_FROM_DATABASE=CGI IT UK LIMITED + +OUI:1C82597* + ID_OUI_FROM_DATABASE=Jump Trading + +OUI:1C82598* + ID_OUI_FROM_DATABASE=SHENZHEN AOA TECHNOLOGY CO.,LTD + +OUI:1C82599* + ID_OUI_FROM_DATABASE=Shanghai Xiaoyan Technology Co., Ltd. + +OUI:1C8259A* + ID_OUI_FROM_DATABASE=ESTec Corporation + +OUI:1C8259B* + ID_OUI_FROM_DATABASE=KeyWest Networks, Inc + +OUI:1C8259C* + ID_OUI_FROM_DATABASE=Evondos Oy + +OUI:1C8259D* + ID_OUI_FROM_DATABASE=Applied Concepts, Inc. + +OUI:1C8259E* + ID_OUI_FROM_DATABASE=Microtronics Engineering GmbH + +OUI:1C8341* + ID_OUI_FROM_DATABASE=Hefei Bitland Information Technology Co.Ltd + +OUI:1C83B0* + ID_OUI_FROM_DATABASE=Linked IP GmbH + +OUI:1C8464* + ID_OUI_FROM_DATABASE=FORMOSA WIRELESS COMMUNICATION CORP. + +OUI:1C86AD* + ID_OUI_FROM_DATABASE=MCT CO., LTD. + +OUI:1C872C* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:1C87740* + ID_OUI_FROM_DATABASE=Philips Personal Health Solutions + +OUI:1C87741* + ID_OUI_FROM_DATABASE=SIGFOX + +OUI:1C87742* + ID_OUI_FROM_DATABASE=Nichigaku + +OUI:1C87743* + ID_OUI_FROM_DATABASE=Silora R&D + +OUI:1C87744* + ID_OUI_FROM_DATABASE=Weber Marking Systems GmbH + +OUI:1C87745* + ID_OUI_FROM_DATABASE=Xiaoxinge (Tangshan) Electronic Technology Co., Ltd. + +OUI:1C87746* + ID_OUI_FROM_DATABASE=Schawbel Technologies LLC + +OUI:1C87747* + ID_OUI_FROM_DATABASE=Ing Buero Ziegler + +OUI:1C87748* + ID_OUI_FROM_DATABASE=Surtec Industries, Inc + +OUI:1C87749* + ID_OUI_FROM_DATABASE=Wide World Trade HK ltd. + +OUI:1C8774A* + ID_OUI_FROM_DATABASE=Nebbiolo Technologies + +OUI:1C8774B* + ID_OUI_FROM_DATABASE=HABEY USA Inc. + +OUI:1C8774C* + ID_OUI_FROM_DATABASE=New Nordic Engineering + +OUI:1C8774D* + ID_OUI_FROM_DATABASE=CLABER SPA + +OUI:1C8774E* + ID_OUI_FROM_DATABASE=Quest Integrity + +OUI:1C87760* + ID_OUI_FROM_DATABASE=Dspread Technology (Beijing) Inc. + +OUI:1C87761* + ID_OUI_FROM_DATABASE=EBS Sp. z o.o. + +OUI:1C87762* + ID_OUI_FROM_DATABASE=Ibeo Automotive Systems GmbH + +OUI:1C87763* + ID_OUI_FROM_DATABASE=Unjo AB + +OUI:1C87764* + ID_OUI_FROM_DATABASE=RDP.RU + +OUI:1C87765* + ID_OUI_FROM_DATABASE=Zhuhai MYZR Technology Co.,Ltd + +OUI:1C87766* + ID_OUI_FROM_DATABASE=philandro Software GmbH + +OUI:1C87767* + ID_OUI_FROM_DATABASE=Corporate Systems Engineering + +OUI:1C87768* + ID_OUI_FROM_DATABASE=Guangzhou Video-Star Electronics Co.,Ltd. + +OUI:1C87769* + ID_OUI_FROM_DATABASE=Tokyo Drawing Ltd. + +OUI:1C8776A* + ID_OUI_FROM_DATABASE=Jiangsu ETERN COMMUNICATION Co.,ltd + +OUI:1C8776B* + ID_OUI_FROM_DATABASE=Hekatron Vertriebs GmbH + +OUI:1C8776C* + ID_OUI_FROM_DATABASE=Strone Technology + +OUI:1C8776D* + ID_OUI_FROM_DATABASE=Qivivo + +OUI:1C8776E* + ID_OUI_FROM_DATABASE=Artis GmbH + +OUI:1C87790* + ID_OUI_FROM_DATABASE=Wurm GmbH & Co. KG Elektronische Systeme + +OUI:1C87791* + ID_OUI_FROM_DATABASE=A-GEAR COMPANY LIMITED + +OUI:1C87792* + ID_OUI_FROM_DATABASE=SMARTMOVT TECHNOLOGY Co., LTD + +OUI:1C87793* + ID_OUI_FROM_DATABASE=Visual Land Inc. + +OUI:1C87794* + ID_OUI_FROM_DATABASE=Novetta + +OUI:1C87795* + ID_OUI_FROM_DATABASE=BEIDIAN GROUP + +OUI:1C87796* + ID_OUI_FROM_DATABASE=Shenzhen Shouxin Tongda Technology Co.,Ltd + +OUI:1C87797* + ID_OUI_FROM_DATABASE=TASC Systems Inc. + +OUI:1C87798* + ID_OUI_FROM_DATABASE=ZHEJIANG ITENAL TECHNOLOGY CO.,LTD + +OUI:1C87799* + ID_OUI_FROM_DATABASE=Istria soluciones de criptografia, S. A. + +OUI:1C8779A* + ID_OUI_FROM_DATABASE=Hangzhou Xiaowen Intelligent Technology Co., Ltd. + +OUI:1C8779B* + ID_OUI_FROM_DATABASE=Beijing Geedeen Technology Co., Ltd + +OUI:1C8779C* + ID_OUI_FROM_DATABASE=AllThingsTalk + +OUI:1C8779D* + ID_OUI_FROM_DATABASE=Shenzhen Innovaconn Systems Co.,Ltd + +OUI:1C8779E* + ID_OUI_FROM_DATABASE=ASSYSTEM France + +OUI:1C88790* + ID_OUI_FROM_DATABASE=Newps co.,ltd + +OUI:1C88791* + ID_OUI_FROM_DATABASE=ANDRA Sp. z o.o. + +OUI:1C88792* + ID_OUI_FROM_DATABASE=Airsmart System Co.,Ltd + +OUI:1C88793* + ID_OUI_FROM_DATABASE=Shenzhen Xiaoxi Technology Co., Ltd. + +OUI:1C88794* + ID_OUI_FROM_DATABASE=Ultraflux + +OUI:1C88795* + ID_OUI_FROM_DATABASE=SHENZHENFREELINK ELECTRONIC CO.,LTD + +OUI:1C88796* + ID_OUI_FROM_DATABASE=Eolos IT Corp + +OUI:1C88797* + ID_OUI_FROM_DATABASE=Sensys Networks, Inc. + +OUI:1C88798* + ID_OUI_FROM_DATABASE=Toshiba Toko Meter Systems Co., LTD. + +OUI:1C88799* + ID_OUI_FROM_DATABASE=Xingtera China Ltd + +OUI:1C8879A* + ID_OUI_FROM_DATABASE=ITW-FEG + +OUI:1C8879B* + ID_OUI_FROM_DATABASE=gekartel AG + +OUI:1C8879C* + ID_OUI_FROM_DATABASE=Accriva + +OUI:1C8879D* + ID_OUI_FROM_DATABASE=Beijing Raycores Technology Co.,Ltd + +OUI:1C8879E* + ID_OUI_FROM_DATABASE=Orion Labs inc + +OUI:1C8E5C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1C8E8E* + ID_OUI_FROM_DATABASE=DB Communication & Systems Co., ltd. + +OUI:1C8F8A* + ID_OUI_FROM_DATABASE=Phase Motion Control SpA + +OUI:1C9148* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1C9179* + ID_OUI_FROM_DATABASE=Integrated System Technologies Ltd + +OUI:1C919D* + ID_OUI_FROM_DATABASE=Dongguan Liesheng Electronic Co., Ltd. + +OUI:1C9492* + ID_OUI_FROM_DATABASE=RUAG Schweiz AG + +OUI:1C955D* + ID_OUI_FROM_DATABASE=I-LAX ELECTRONICS INC. + +OUI:1C959F* + ID_OUI_FROM_DATABASE=Veethree Electronics And Marine LLC + +OUI:1C965A* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:1C973D* + ID_OUI_FROM_DATABASE=PRICOM Design + +OUI:1C97C5* + ID_OUI_FROM_DATABASE=Ynomia Pty Ltd + +OUI:1C98EC* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:1C994C* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:1C9C26* + ID_OUI_FROM_DATABASE=Zoovel Technologies + +OUI:1C9C8C* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:1C9D3E* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:1C9E46* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1C9ECB* + ID_OUI_FROM_DATABASE=Beijing Nari Smartchip Microelectronics Company Limited + +OUI:1CA0B8* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co., Ltd. + +OUI:1CA0D30* + ID_OUI_FROM_DATABASE=OOO Tekhnotronika + +OUI:1CA0D31* + ID_OUI_FROM_DATABASE=Jabil circuit italia srl + +OUI:1CA0D32* + ID_OUI_FROM_DATABASE=NovTech, Inc. + +OUI:1CA0D33* + ID_OUI_FROM_DATABASE=SAVELEC + +OUI:1CA0D34* + ID_OUI_FROM_DATABASE=NPO TELECOM JSC + +OUI:1CA0D35* + ID_OUI_FROM_DATABASE=Dynamic Connect (Suzhou) Hi-Tech Electronic Co.,Ltd. + +OUI:1CA0D36* + ID_OUI_FROM_DATABASE=Intertecno SRL NISUTA + +OUI:1CA0D37* + ID_OUI_FROM_DATABASE=Private + +OUI:1CA0D38* + ID_OUI_FROM_DATABASE=Desarrollos y Soluciones Guinea I+D S.L. + +OUI:1CA0D39* + ID_OUI_FROM_DATABASE=Cirque Audio Technology Co., Ltd + +OUI:1CA0D3A* + ID_OUI_FROM_DATABASE=DSM Messtechnik GmbH + +OUI:1CA0D3B* + ID_OUI_FROM_DATABASE=Guang Dong He Zheng Network Technology Co.,Ltd + +OUI:1CA0D3C* + ID_OUI_FROM_DATABASE=LYT inc. + +OUI:1CA0D3D* + ID_OUI_FROM_DATABASE=ERATO (HK) Corporation Limited + +OUI:1CA0D3E* + ID_OUI_FROM_DATABASE=Exicom Tele-Systems Ltd. + +OUI:1CA2B1* + ID_OUI_FROM_DATABASE=ruwido austria gmbh + +OUI:1CA532* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:1CA770* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + +OUI:1CAA07* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1CAB01* + ID_OUI_FROM_DATABASE=Innovolt + +OUI:1CAB34* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:1CABA7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1CABC0* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:1CADD1* + ID_OUI_FROM_DATABASE=Bosung Electronics Co., Ltd. + +OUI:1CAECB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1CAF05* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:1CAFF7* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:1CB044* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:1CB094* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:1CB17F* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. + +OUI:1CB243* + ID_OUI_FROM_DATABASE=TDC A/S + +OUI:1CB3E9* + ID_OUI_FROM_DATABASE=Shenzhen Zhongke United Communication Technology + +OUI:1CB72C* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:1CB796* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:1CB857* + ID_OUI_FROM_DATABASE=Becon Technologies Co,.Ltd. + +OUI:1CB9C4* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:1CBA8C* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:1CBBA8* + ID_OUI_FROM_DATABASE=OJSC Ufimskiy Zavod Promsvyaz + +OUI:1CBD0E* + ID_OUI_FROM_DATABASE=Amplified Engineering Pty Ltd + +OUI:1CBDB9* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:1CBFC0* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:1CBFCE* + ID_OUI_FROM_DATABASE=Shenzhen Century Xinyang Technology Co., Ltd + +OUI:1CC035* + ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. + +OUI:1CC0E10* + ID_OUI_FROM_DATABASE=Shenzhen Highsharp Electronics Ltd. + +OUI:1CC0E11* + ID_OUI_FROM_DATABASE=Hangzhou Kaierda Electric Welding Machine Co.,Ltd + +OUI:1CC0E12* + ID_OUI_FROM_DATABASE=Abbott Medical Optics Inc. + +OUI:1CC0E13* + ID_OUI_FROM_DATABASE=HANGZHOU SOFTEL OPTIC CO., LTD + +OUI:1CC0E14* + ID_OUI_FROM_DATABASE=Videri Inc. + +OUI:1CC0E15* + ID_OUI_FROM_DATABASE=Kids Wireless Inc + +OUI:1CC0E16* + ID_OUI_FROM_DATABASE=Monument Labs, Inc. + +OUI:1CC0E17* + ID_OUI_FROM_DATABASE=SHENZHEN KINSTONE D&T DEVELOP CO.,LTD + +OUI:1CC0E18* + ID_OUI_FROM_DATABASE=LX Corporation Pty Ltd + +OUI:1CC0E19* + ID_OUI_FROM_DATABASE=Ospicon Company Limited + +OUI:1CC0E1A* + ID_OUI_FROM_DATABASE=SECHERON SA + +OUI:1CC0E1B* + ID_OUI_FROM_DATABASE=Exigent Sensors + +OUI:1CC0E1C* + ID_OUI_FROM_DATABASE=Nitto Seiko + +OUI:1CC0E1D* + ID_OUI_FROM_DATABASE=NewLand (NZ) Communication Tech Limited + +OUI:1CC0E1E* + ID_OUI_FROM_DATABASE=Yun Yang Fire Safety Equipment Co.,Ltd. + +OUI:1CC11A* + ID_OUI_FROM_DATABASE=Wavetronix + +OUI:1CC1BC* + ID_OUI_FROM_DATABASE=Yichip Microelectronics (Hangzhou) Co.,Ltd + +OUI:1CC1DE* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:1CC316* + ID_OUI_FROM_DATABASE=MileSight Technology Co., Ltd. + +OUI:1CC3EB* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:1CC586* + ID_OUI_FROM_DATABASE=Absolute Acoustics + +OUI:1CC63C* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:1CC72D* + ID_OUI_FROM_DATABASE=Shenzhen Huapu Digital CO.,Ltd + +OUI:1CCAE30* + ID_OUI_FROM_DATABASE=Private + +OUI:1CCAE31* + ID_OUI_FROM_DATABASE=PGA ELECTRONIC + +OUI:1CCAE32* + ID_OUI_FROM_DATABASE=Insigma Inc + +OUI:1CCAE33* + ID_OUI_FROM_DATABASE=Shenzhen Smart Device Technology Co.,LTD + +OUI:1CCAE34* + ID_OUI_FROM_DATABASE=Sunray Medical Apparatus Co.,Ltd. + +OUI:1CCAE35* + ID_OUI_FROM_DATABASE=TengFeng + +OUI:1CCAE36* + ID_OUI_FROM_DATABASE=TOKAI RIKA CO., LTD. + +OUI:1CCAE37* + ID_OUI_FROM_DATABASE=Bird Home Automation GmbH + +OUI:1CCAE38* + ID_OUI_FROM_DATABASE=OxySec S.r.l. + +OUI:1CCAE39* + ID_OUI_FROM_DATABASE=SHIN-YOSHA CORPORATION + +OUI:1CCAE3A* + ID_OUI_FROM_DATABASE=SIREA + +OUI:1CCAE3B* + ID_OUI_FROM_DATABASE=Dream Visions Co., LTD + +OUI:1CCAE3C* + ID_OUI_FROM_DATABASE=Gahdeung Elecom + +OUI:1CCAE3D* + ID_OUI_FROM_DATABASE=eSight Corporation + +OUI:1CCAE3E* + ID_OUI_FROM_DATABASE=Dabi Atlante S/A Industrias Medico Odontológicas + +OUI:1CCAE3F* + ID_OUI_FROM_DATABASE=Private + +OUI:1CCB99* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:1CCCD6* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:1CCDE5* + ID_OUI_FROM_DATABASE=Shanghai Wind Technologies Co.,Ltd + +OUI:1CD40C* + ID_OUI_FROM_DATABASE=Kriwan Industrie-Elektronik GmbH + +OUI:1CD5E2* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:1CD6BD* + ID_OUI_FROM_DATABASE=LEEDARSON LIGHTING CO., LTD. + +OUI:1CDA27* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:1CDDEA* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:1CDE57* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:1CDEA7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1CDF0F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1CDF52* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:1CE165* + ID_OUI_FROM_DATABASE=Marshal Corporation + +OUI:1CE192* + ID_OUI_FROM_DATABASE=Qisda Corporation + +OUI:1CE2CC* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:1CE62B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:1CE6C7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1CE85D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:1CEA0B* + ID_OUI_FROM_DATABASE=Edgecore Networks Corporation + +OUI:1CEA1B* + ID_OUI_FROM_DATABASE=Nokia + +OUI:1CEEC9* + ID_OUI_FROM_DATABASE=Elo touch solutions + +OUI:1CEEE8* + ID_OUI_FROM_DATABASE=Ilshin Elecom + +OUI:1CEFCE* + ID_OUI_FROM_DATABASE=bebro electronic GmbH + +OUI:1CF03E* + ID_OUI_FROM_DATABASE=Wearhaus Inc. + +OUI:1CF061* + ID_OUI_FROM_DATABASE=SCAPS GmbH + +OUI:1CF29A* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:1CF4CA* + ID_OUI_FROM_DATABASE=Private + +OUI:1CF5E7* + ID_OUI_FROM_DATABASE=Turtle Industry Co., Ltd. + +OUI:1CFA68* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:1CFCBB* + ID_OUI_FROM_DATABASE=Realfiction ApS + +OUI:1CFD080* + ID_OUI_FROM_DATABASE=InSeat Solutions, LLC + +OUI:1CFD081* + ID_OUI_FROM_DATABASE=Shenzhen SEWO Technology Co.,Ltd. + +OUI:1CFD082* + ID_OUI_FROM_DATABASE=HiHi Ltd + +OUI:1CFD083* + ID_OUI_FROM_DATABASE=Umeox Innovations Co.,Ltd + +OUI:1CFD084* + ID_OUI_FROM_DATABASE=SABIK Offshore GmbH + +OUI:1CFD085* + ID_OUI_FROM_DATABASE=Beijing Hengxin Rainbow Information Technology Co.,Ltd + +OUI:1CFD086* + ID_OUI_FROM_DATABASE=A&B Technology + +OUI:1CFD087* + ID_OUI_FROM_DATABASE=sunweit industrial limited + +OUI:1CFD088* + ID_OUI_FROM_DATABASE=ShenZhen DeLippo Technology Co., LTD + +OUI:1CFD089* + ID_OUI_FROM_DATABASE=Cobham Slip Rings + +OUI:1CFD08A* + ID_OUI_FROM_DATABASE=Banmak Technogies Co.,Ltd + +OUI:1CFD08B* + ID_OUI_FROM_DATABASE=guangzhou huiqun intelligent technology co. LTD + +OUI:1CFD08C* + ID_OUI_FROM_DATABASE=Shanghai YottaTech Co Ltd (上海尧它科技有限公司) + +OUI:1CFD08D* + ID_OUI_FROM_DATABASE=Tianjin Keyvia Electric Co.,Ltd + +OUI:1CFD08E* + ID_OUI_FROM_DATABASE=MESHBOX FOUNDATION PTE. LTD. + +OUI:1CFEA7* + ID_OUI_FROM_DATABASE=IDentytech Solutins Ltd. + +OUI:20014F* + ID_OUI_FROM_DATABASE=Linea Research Ltd + +OUI:2002AF* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:20040F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:200505* + ID_OUI_FROM_DATABASE=RADMAX COMMUNICATION PRIVATE LIMITED + +OUI:2005E8* + ID_OUI_FROM_DATABASE=OOO InProMedia + +OUI:2008ED* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:200A0D0* + ID_OUI_FROM_DATABASE=halstrup-walcher GmbH + +OUI:200A0D1* + ID_OUI_FROM_DATABASE=Wideband Systems, Inc. + +OUI:200A0D2* + ID_OUI_FROM_DATABASE=Netinovo Technologies(Shenzhen) Ltd + +OUI:200A0D3* + ID_OUI_FROM_DATABASE=Clearly IP Inc + +OUI:200A0D4* + ID_OUI_FROM_DATABASE=Virtium + +OUI:200A0D5* + ID_OUI_FROM_DATABASE=Shenzhen Zhangyue Technology Co.,Ltd + +OUI:200A0D6* + ID_OUI_FROM_DATABASE=Austin Hughes Electronics Ltd. + +OUI:200A0D7* + ID_OUI_FROM_DATABASE=Tecnint HTE SRL + +OUI:200A0D8* + ID_OUI_FROM_DATABASE=bcheck NV + +OUI:200A0D9* + ID_OUI_FROM_DATABASE=Welzek (Beijing) Technologies Co, Ltd + +OUI:200A0DA* + ID_OUI_FROM_DATABASE=IRSAP + +OUI:200A0DB* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:200A0DC* + ID_OUI_FROM_DATABASE=sehwa + +OUI:200A0DD* + ID_OUI_FROM_DATABASE=Bently & EL Co. Ltd. + +OUI:200A0DE* + ID_OUI_FROM_DATABASE=HANGZHOU DANGBEI NETWORK TECH.Co.,Ltd + +OUI:200A5E* + ID_OUI_FROM_DATABASE=Xiangshan Giant Eagle Technology Developing Co., Ltd. + +OUI:200BC7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:200CC8* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:200DB0* + ID_OUI_FROM_DATABASE=Shenzhen Four Seas Global Link Network Technology Co., Ltd. + +OUI:200E95* + ID_OUI_FROM_DATABASE=IEC – TC9 WG43 + +OUI:200F70* + ID_OUI_FROM_DATABASE=FOXTECH + +OUI:20107A* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:20114E* + ID_OUI_FROM_DATABASE=MeteRSit S.R.L. + +OUI:201257* + ID_OUI_FROM_DATABASE=Most Lucky Trading Ltd + +OUI:2012D5* + ID_OUI_FROM_DATABASE=Scientech Materials Corporation + +OUI:2013E0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:20163D* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:2016B9* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:2016D8* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:201742* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:20180E* + ID_OUI_FROM_DATABASE=Shenzhen Sunchip Technology Co., Ltd + +OUI:201A06* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:201BC9* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:201D03* + ID_OUI_FROM_DATABASE=Elatec GmbH + +OUI:201F31* + ID_OUI_FROM_DATABASE=Inteno Broadband Technology AB + +OUI:2021A5* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:202564* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:202598* + ID_OUI_FROM_DATABASE=Teleview + +OUI:202681* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:20283E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2028BC* + ID_OUI_FROM_DATABASE=Visionscape Co,. Ltd. + +OUI:202AC5* + ID_OUI_FROM_DATABASE=Petite-En + +OUI:202BC1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:202CB7* + ID_OUI_FROM_DATABASE=Kong Yue Electronics & Information Industry (Xinhui) Ltd. + +OUI:202D07* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:202D23* + ID_OUI_FROM_DATABASE=Collinear Networks Inc. + +OUI:202DF8* + ID_OUI_FROM_DATABASE=Digital Media Cartridge Ltd. + +OUI:20311C* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:2031EB* + ID_OUI_FROM_DATABASE=HDSN + +OUI:203233* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD + +OUI:20326C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:2034FB* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:20365B* + ID_OUI_FROM_DATABASE=Megafone Limited + +OUI:2036D7* + ID_OUI_FROM_DATABASE=Shanghai Reacheng Communication Technology Co.,Ltd + +OUI:203706* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2037BC* + ID_OUI_FROM_DATABASE=Kuipers Electronic Engineering BV + +OUI:203956* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:203A07* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:203AEF* + ID_OUI_FROM_DATABASE=Sivantos GmbH + +OUI:203CAE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:203D66* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:203DB2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:203DBD* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:204005* + ID_OUI_FROM_DATABASE=feno GmbH + +OUI:20415A* + ID_OUI_FROM_DATABASE=Smarteh d.o.o. + +OUI:20443A* + ID_OUI_FROM_DATABASE=Schneider Electric Asia Pacific Ltd + +OUI:2046A1* + ID_OUI_FROM_DATABASE=VECOW Co., Ltd + +OUI:2046F9* + ID_OUI_FROM_DATABASE=Advanced Network Devices (dba:AND) + +OUI:204747* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:2047DA* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:2047ED* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:204AAA* + ID_OUI_FROM_DATABASE=Hanscan Spain S.A. + +OUI:204C03* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:204C6D* + ID_OUI_FROM_DATABASE=Hugo Brennenstuhl Gmbh & Co. KG. + +OUI:204C9E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:204E6B* + ID_OUI_FROM_DATABASE=Axxana(israel) ltd + +OUI:204E71* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:204E7F* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:2050E7* + ID_OUI_FROM_DATABASE=AMPAK Technology,Inc. + +OUI:2053CA* + ID_OUI_FROM_DATABASE=Risk Technology Ltd + +OUI:205476* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:2054FA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:205531* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:205532* + ID_OUI_FROM_DATABASE=Gotech International Technology Limited + +OUI:205721* + ID_OUI_FROM_DATABASE=Salix Technology CO., Ltd. + +OUI:2057AF* + ID_OUI_FROM_DATABASE=Shenzhen FH-NET OPTOELECTRONICS CO.,LTD + +OUI:205869* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:2059A0* + ID_OUI_FROM_DATABASE=Paragon Technologies Inc. + +OUI:205A00* + ID_OUI_FROM_DATABASE=Coval + +OUI:205B2A* + ID_OUI_FROM_DATABASE=Private + +OUI:205B5E* + ID_OUI_FROM_DATABASE=Shenzhen Wonhe Technology Co., Ltd + +OUI:205CFA* + ID_OUI_FROM_DATABASE=Yangzhou ChangLian Network Technology Co,ltd. + +OUI:205D47* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:205EF7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:205F3D* + ID_OUI_FROM_DATABASE=Cambridge Communication Systems Ltd + +OUI:206274* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:20635F* + ID_OUI_FROM_DATABASE=Abeeway + +OUI:206432* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:20658E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:20677C* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:2067B1* + ID_OUI_FROM_DATABASE=Pluto inc. + +OUI:20689D* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:206A8A* + ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation + +OUI:206AFF* + ID_OUI_FROM_DATABASE=Atlas Elektronik UK Limited + +OUI:206BE7* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:206C8A* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:206D31* + ID_OUI_FROM_DATABASE=FIREWALLA INC + +OUI:206E9C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:206FEC* + ID_OUI_FROM_DATABASE=Braemac CA LLC + +OUI:20719E* + ID_OUI_FROM_DATABASE=SF Technology Co.,Ltd + +OUI:207355* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:207454* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:2074CF* + ID_OUI_FROM_DATABASE=Shenzhen Voxtech Co.,Ltd + +OUI:207600* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:20768F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:207693* + ID_OUI_FROM_DATABASE=Lenovo (Beijing) Limited. + +OUI:207759* + ID_OUI_FROM_DATABASE=OPTICAL NETWORK VIDEO TECHNOLOGIES (SHENZHEN) CO., LTD. + +OUI:20780B* + ID_OUI_FROM_DATABASE=Delta Faucet Company + +OUI:207852* + ID_OUI_FROM_DATABASE=Nokia + +OUI:2078F0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:207918* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:207C8F* + ID_OUI_FROM_DATABASE=Quanta Microsystems,Inc. + +OUI:207D74* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:208058* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:20826A* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:2082C0* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:2083F8* + ID_OUI_FROM_DATABASE=Advanced Digital Broadcast SA + +OUI:20858C* + ID_OUI_FROM_DATABASE=Assa + +OUI:2085930* + ID_OUI_FROM_DATABASE=Hemina Spa + +OUI:2085931* + ID_OUI_FROM_DATABASE=Networking Services Corp + +OUI:2085932* + ID_OUI_FROM_DATABASE=Mid Continent Controls, Inc. + +OUI:2085933* + ID_OUI_FROM_DATABASE=UNILUMIN GROUP CO.,LTD + +OUI:2085934* + ID_OUI_FROM_DATABASE=Kloudspot Inc + +OUI:2085935* + ID_OUI_FROM_DATABASE=Wave-In Communication + +OUI:2085936* + ID_OUI_FROM_DATABASE=Eilersen Electric A/S + +OUI:2085937* + ID_OUI_FROM_DATABASE=Great Lite International + +OUI:2085938* + ID_OUI_FROM_DATABASE=AASSET SECURITY + +OUI:2085939* + ID_OUI_FROM_DATABASE=Private + +OUI:208593A* + ID_OUI_FROM_DATABASE=H3 Industries, Inc. + +OUI:208593B* + ID_OUI_FROM_DATABASE=IOG Products LLC + +OUI:208593C* + ID_OUI_FROM_DATABASE=Regloplas AG + +OUI:208593D* + ID_OUI_FROM_DATABASE=Shanghai Kenmyond Industrial Network Equipment Co.,Ltd + +OUI:208593E* + ID_OUI_FROM_DATABASE=Dynaudio + +OUI:208756* + ID_OUI_FROM_DATABASE=SIEMENS AG + +OUI:2087AC* + ID_OUI_FROM_DATABASE=AES motomation + +OUI:20896F* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:208984* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:208986* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:208B37* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:20906F* + ID_OUI_FROM_DATABASE=Shenzhen Tencent Computer System Co., Ltd. + +OUI:209148* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:20918A* + ID_OUI_FROM_DATABASE=PROFALUX + +OUI:2091D9* + ID_OUI_FROM_DATABASE=I'M SPA + +OUI:20934D* + ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD + +OUI:20968A* + ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd. + +OUI:209AE9* + ID_OUI_FROM_DATABASE=Volacomm Co., Ltd + +OUI:209BA5* + ID_OUI_FROM_DATABASE=JIAXING GLEAD Electronics Co.,Ltd + +OUI:209BCD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:209EF7* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:20A2E4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:20A2E7* + ID_OUI_FROM_DATABASE=Lee-Dickens Ltd + +OUI:20A60C* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:20A680* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:20A6CD* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:20A783* + ID_OUI_FROM_DATABASE=miControl GmbH + +OUI:20A787* + ID_OUI_FROM_DATABASE=Bointec Taiwan Corporation Limited + +OUI:20A8B9* + ID_OUI_FROM_DATABASE=SIEMENS AG + +OUI:20A90E* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:20A99B* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:20AA25* + ID_OUI_FROM_DATABASE=IP-NET LLC + +OUI:20AA4B* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:20AB37* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:20AD56* + ID_OUI_FROM_DATABASE=Continental Automotive Systems Inc. + +OUI:20B001* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:20B0F7* + ID_OUI_FROM_DATABASE=Enclustra GmbH + +OUI:20B399* + ID_OUI_FROM_DATABASE=Enterasys + +OUI:20B5C6* + ID_OUI_FROM_DATABASE=Mimosa Networks + +OUI:20B780* + ID_OUI_FROM_DATABASE=Toshiba Visual Solutions Corporation Co.,Ltd + +OUI:20B7C0* + ID_OUI_FROM_DATABASE=OMICRON electronics GmbH + +OUI:20BB76* + ID_OUI_FROM_DATABASE=COL GIOVANNI PAOLO SpA + +OUI:20BBC0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:20BBC6* + ID_OUI_FROM_DATABASE=Jabil Circuit Hungary Ltd. + +OUI:20BFDB* + ID_OUI_FROM_DATABASE=DVL + +OUI:20C047* + ID_OUI_FROM_DATABASE=Verizon + +OUI:20C06D* + ID_OUI_FROM_DATABASE=SHENZHEN SPACETEK TECHNOLOGY CO.,LTD + +OUI:20C1AF* + ID_OUI_FROM_DATABASE=i Wit Digital Co., Limited + +OUI:20C38F* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:20C3A4* + ID_OUI_FROM_DATABASE=RetailNext + +OUI:20C60D* + ID_OUI_FROM_DATABASE=Shanghai annijie Information technology Co.,LTD + +OUI:20C6EB* + ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company + +OUI:20C8B3* + ID_OUI_FROM_DATABASE=SHENZHEN BUL-TECH CO.,LTD. + +OUI:20C9D0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:20CD39* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:20CEC4* + ID_OUI_FROM_DATABASE=Peraso Technologies + +OUI:20CF30* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:20D160* + ID_OUI_FROM_DATABASE=Private + +OUI:20D21F* + ID_OUI_FROM_DATABASE=Wincal Technology Corp. + +OUI:20D25F* + ID_OUI_FROM_DATABASE=SmartCap Technologies + +OUI:20D390* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:20D5AB* + ID_OUI_FROM_DATABASE=Korea Infocom Co.,Ltd. + +OUI:20D5BF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:20D607* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:20D75A* + ID_OUI_FROM_DATABASE=Posh Mobile Limited + +OUI:20D80B* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:20D906* + ID_OUI_FROM_DATABASE=Iota, Inc. + +OUI:20DA22* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:20DBAB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. + +OUI:20DC93* + ID_OUI_FROM_DATABASE=Cheetah Hi-Tech, Inc. + +OUI:20DCE6* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:20DE88* + ID_OUI_FROM_DATABASE=IC Realtime LLC + +OUI:20DF3F* + ID_OUI_FROM_DATABASE=Nanjing SAC Power Grid Automation Co., Ltd. + +OUI:20DFB9* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:20E09C* + ID_OUI_FROM_DATABASE=Nokia + +OUI:20E407* + ID_OUI_FROM_DATABASE=Spark srl + +OUI:20E52A* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:20E564* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:20E791* + ID_OUI_FROM_DATABASE=Siemens Healthcare Diagnostics, Inc + +OUI:20E874* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:20E882* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:20EAC7* + ID_OUI_FROM_DATABASE=SHENZHEN RIOPINE ELECTRONICS CO., LTD + +OUI:20ED74* + ID_OUI_FROM_DATABASE=Ability enterprise co.,Ltd. + +OUI:20EE28* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:20EEC6* + ID_OUI_FROM_DATABASE=Elefirst Science & Tech Co ., ltd + +OUI:20F002* + ID_OUI_FROM_DATABASE=MTData Developments Pty. Ltd. + +OUI:20F17C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:20F19E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:20F375* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:20F3A3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:20F41B* + ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD + +OUI:20F452* + ID_OUI_FROM_DATABASE=Shanghai IUV Software Development Co. Ltd + +OUI:20F478* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:20F510* + ID_OUI_FROM_DATABASE=Codex Digital Limited + +OUI:20F543* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:20F77C* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:20F85E* + ID_OUI_FROM_DATABASE=Delta Electronics + +OUI:20FABB* + ID_OUI_FROM_DATABASE=Cambridge Executive Limited + +OUI:20FDF1* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:20FECD* + ID_OUI_FROM_DATABASE=System In Frontier Inc. + +OUI:20FEDB* + ID_OUI_FROM_DATABASE=M2M Solution S.A.S. + +OUI:2400BA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2401C7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:24050F* + ID_OUI_FROM_DATABASE=MTN Electronic Co. Ltd + +OUI:240588* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:2405F5* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:240917* + ID_OUI_FROM_DATABASE=Devlin Electronics Limited + +OUI:240995* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:240A11* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:240A63* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:240A64* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:240AC4* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:240B0A* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:240B2A* + ID_OUI_FROM_DATABASE=Viettel Group + +OUI:240BB1* + ID_OUI_FROM_DATABASE=KOSTAL Industrie Elektrik GmbH + +OUI:240D65* + ID_OUI_FROM_DATABASE=Shenzhen Vsun Communication Technology Co., Ltd. + +OUI:240D6C* + ID_OUI_FROM_DATABASE=SMND + +OUI:240DC2* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:241064* + ID_OUI_FROM_DATABASE=Shenzhen Ecsino Tecnical Co. Ltd + +OUI:241125* + ID_OUI_FROM_DATABASE=Hutek Co., Ltd. + +OUI:241148* + ID_OUI_FROM_DATABASE=Entropix, LLC + +OUI:2411D0* + ID_OUI_FROM_DATABASE=Chongqing Ehs Science and Technology Development Co.,Ltd. + +OUI:2415100* + ID_OUI_FROM_DATABASE=Safetrust Inc + +OUI:2415101* + ID_OUI_FROM_DATABASE=SMaBiT GmbH + +OUI:2415102* + ID_OUI_FROM_DATABASE=Nile Global Inc + +OUI:2415103* + ID_OUI_FROM_DATABASE=Kaiyun + +OUI:2415104* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:2415105* + ID_OUI_FROM_DATABASE=GANZHOU DEHUIDA TECHNOLOGY CO., LTD + +OUI:2415106* + ID_OUI_FROM_DATABASE=SHANDONG KEHUI POWER AUTOMATION CO. LTD. + +OUI:2415107* + ID_OUI_FROM_DATABASE=SuZhou A-rack Information Technology Co.,Ltd + +OUI:2415108* + ID_OUI_FROM_DATABASE=Private + +OUI:2415109* + ID_OUI_FROM_DATABASE=Topgolf Sweden AB + +OUI:241510A* + ID_OUI_FROM_DATABASE=Unitronux(Shenzhen) Intelligence Technology Co.,Ltd + +OUI:241510B* + ID_OUI_FROM_DATABASE=Teknic, Inc. + +OUI:241510C* + ID_OUI_FROM_DATABASE=Shenzhen Xtooltech Co., Ltd + +OUI:241510D* + ID_OUI_FROM_DATABASE=Helen of Troy + +OUI:241510E* + ID_OUI_FROM_DATABASE=Satellite Link Technology CO.,LTD + +OUI:24166D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:24169D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:24181D* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:241A8C* + ID_OUI_FROM_DATABASE=Squarehead Technology AS + +OUI:241B13* + ID_OUI_FROM_DATABASE=Shanghai Nutshell Electronic Co., Ltd. + +OUI:241B44* + ID_OUI_FROM_DATABASE=Hangzhou Tuners Electronics Co., Ltd + +OUI:241B7A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:241C04* + ID_OUI_FROM_DATABASE=SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD. + +OUI:241EEB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:241F2C* + ID_OUI_FROM_DATABASE=Calsys, Inc. + +OUI:241FA0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2420C7* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:242124* + ID_OUI_FROM_DATABASE=Nokia + +OUI:2421AB* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:24240E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:242642* + ID_OUI_FROM_DATABASE=SHARP Corporation. + +OUI:2429FE* + ID_OUI_FROM_DATABASE=KYOCERA Corporation + +OUI:242E02* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:242E90* + ID_OUI_FROM_DATABASE=PALIT MICROSYSTEMS, LTD + +OUI:242FFA* + ID_OUI_FROM_DATABASE=Toshiba Global Commerce Solutions + +OUI:243154* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:243184* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:24336C* + ID_OUI_FROM_DATABASE=Private + +OUI:2435CC* + ID_OUI_FROM_DATABASE=Zhongshan Scinan Internet of Things Co.,Ltd. + +OUI:24374C* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:2437EF* + ID_OUI_FROM_DATABASE=EMC Electronic Media Communication SA + +OUI:243A82* + ID_OUI_FROM_DATABASE=IRTS + +OUI:243C20* + ID_OUI_FROM_DATABASE=Dynamode Group + +OUI:243F30* + ID_OUI_FROM_DATABASE=Oxygen Broadband s.a. + +OUI:2440AE* + ID_OUI_FROM_DATABASE=NIIC Technology Co., Ltd. + +OUI:24418C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:2442BC* + ID_OUI_FROM_DATABASE=Alinco,incorporated + +OUI:244427* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:244597* + ID_OUI_FROM_DATABASE=GEMUE Gebr. Mueller Apparatebau + +OUI:2446C8* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:24470E* + ID_OUI_FROM_DATABASE=PentronicAB + +OUI:24497B* + ID_OUI_FROM_DATABASE=Innovative Converged Devices Inc + +OUI:244B03* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:244B81* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:244C07* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:244CE3* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:244E7B0* + ID_OUI_FROM_DATABASE=Tekelek Europe Ltd + +OUI:244E7B1* + ID_OUI_FROM_DATABASE=sonoscape + +OUI:244E7B2* + ID_OUI_FROM_DATABASE=RCC TIME CO .,LIMITED + +OUI:244E7B3* + ID_OUI_FROM_DATABASE=Shenzhen Ruixunyun Technology Co.,Ltd. + +OUI:244E7B4* + ID_OUI_FROM_DATABASE=Leshi Internet Information & Technology (Beijing) Corp. + +OUI:244E7B5* + ID_OUI_FROM_DATABASE=Jiangsu Xuanbo Electronic Technologies Co.,Ltd + +OUI:244E7B6* + ID_OUI_FROM_DATABASE=Owasys Advanced Wireless Devices + +OUI:244E7B7* + ID_OUI_FROM_DATABASE=Nanjing Wanlida Technology Co., Ltd. + +OUI:244E7B8* + ID_OUI_FROM_DATABASE=Cyber1st + +OUI:244E7B9* + ID_OUI_FROM_DATABASE=UniMAT Automation Technology Co., Ltd. + +OUI:244E7BA* + ID_OUI_FROM_DATABASE=Shenzhen AWT science & technology limited + +OUI:244E7BB* + ID_OUI_FROM_DATABASE=Mighty Audio, Inc. + +OUI:244E7BC* + ID_OUI_FROM_DATABASE=CHUNGHSIN TECHNOLOGY GROUP CO.,LTD + +OUI:244E7BD* + ID_OUI_FROM_DATABASE=Church & Dwight Co., Inc. + +OUI:244E7BE* + ID_OUI_FROM_DATABASE=WithWin Technology ShenZhen CO.,LTD + +OUI:244F1D* + ID_OUI_FROM_DATABASE=iRule LLC + +OUI:24526A* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:2453BF* + ID_OUI_FROM_DATABASE=Enernet + +OUI:24586E* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:245880* + ID_OUI_FROM_DATABASE=VIZEO + +OUI:24590B* + ID_OUI_FROM_DATABASE=White Sky Inc. Limited + +OUI:245AB5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:245BA7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:245BF0* + ID_OUI_FROM_DATABASE=Liteon, Inc. + +OUI:245CBF* + ID_OUI_FROM_DATABASE=NCSE + +OUI:245CCB* + ID_OUI_FROM_DATABASE=AXIe Consortium, Inc. + +OUI:245EBE* + ID_OUI_FROM_DATABASE=QNAP Systems, Inc. + +OUI:245FDF* + ID_OUI_FROM_DATABASE=KYOCERA CORPORATION + +OUI:246081* + ID_OUI_FROM_DATABASE=razberi technologies + +OUI:24615A* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:246278* + ID_OUI_FROM_DATABASE=sysmocom - systems for mobile communications GmbH + +OUI:2462AB* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:2464EF* + ID_OUI_FROM_DATABASE=CYG SUNRI CO.,LTD. + +OUI:246511* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:246880* + ID_OUI_FROM_DATABASE=Braveridge.co.,ltd. + +OUI:24693E* + ID_OUI_FROM_DATABASE=innodisk Corporation + +OUI:24694A* + ID_OUI_FROM_DATABASE=Jasmine Systems Inc. + +OUI:246968* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:2469A5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:246AAB* + ID_OUI_FROM_DATABASE=IT-IS International + +OUI:246C8A* + ID_OUI_FROM_DATABASE=YUKAI Engineering + +OUI:246E96* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:246F28* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:246F8C* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:247189* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:247260* + ID_OUI_FROM_DATABASE=IOTTECH Corp + +OUI:2474F7* + ID_OUI_FROM_DATABASE=GoPro + +OUI:247656* + ID_OUI_FROM_DATABASE=Shanghai Net Miles Fiber Optics Technology Co., LTD. + +OUI:24767D* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:247703* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:24792A* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:2479F3* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:2479F8* + ID_OUI_FROM_DATABASE=KUPSON spol. s r.o. + +OUI:247C4C* + ID_OUI_FROM_DATABASE=Herman Miller + +OUI:247D4D* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:247E12* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:247E51* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:247F20* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:247F3C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:248000* + ID_OUI_FROM_DATABASE=Westcontrol AS + +OUI:2481AA* + ID_OUI_FROM_DATABASE=KSH International Co., Ltd. + +OUI:24828A* + ID_OUI_FROM_DATABASE=Prowave Technologies Ltd. + +OUI:248498* + ID_OUI_FROM_DATABASE=Beijing Jiaoda Microunion Tech.Co.,Ltd. + +OUI:2486F4* + ID_OUI_FROM_DATABASE=Ctek, Inc. + +OUI:248707* + ID_OUI_FROM_DATABASE=SEnergy Corporation + +OUI:248894* + ID_OUI_FROM_DATABASE=shenzhen lensun Communication Technology LTD + +OUI:248A07* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:248BE0* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:24920E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:2493CA* + ID_OUI_FROM_DATABASE=Voxtronic Austria + +OUI:249442* + ID_OUI_FROM_DATABASE=OPEN ROAD SOLUTIONS , INC. + +OUI:249504* + ID_OUI_FROM_DATABASE=SFR + +OUI:2497ED* + ID_OUI_FROM_DATABASE=Techvision Intelligent Technology Limited + +OUI:249EAB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:24A074* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:24A2E1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:24A42C* + ID_OUI_FROM_DATABASE=KOUKAAM a.s. + +OUI:24A43C* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:24A495* + ID_OUI_FROM_DATABASE=Thales Canada Inc. + +OUI:24A52C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:24A534* + ID_OUI_FROM_DATABASE=SynTrust Tech International Ltd. + +OUI:24A7DC* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:24A87D* + ID_OUI_FROM_DATABASE=Panasonic Automotive Systems Asia Pacific(Thailand)Co.,Ltd. + +OUI:24A937* + ID_OUI_FROM_DATABASE=PURE Storage + +OUI:24AB81* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:24AF4A* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:24AF54* + ID_OUI_FROM_DATABASE=NEXGEN Mediatech Inc. + +OUI:24B0A9* + ID_OUI_FROM_DATABASE=Shanghai Mobiletek Communication Ltd. + +OUI:24B209* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:24B2DE* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:24B657* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:24B6B8* + ID_OUI_FROM_DATABASE=FRIEM SPA + +OUI:24B6FD* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:24B88C* + ID_OUI_FROM_DATABASE=Crenus Co.,Ltd. + +OUI:24B8D2* + ID_OUI_FROM_DATABASE=Opzoon Technology Co.,Ltd. + +OUI:24BA13* + ID_OUI_FROM_DATABASE=RISO KAGAKU CORPORATION + +OUI:24BA30* + ID_OUI_FROM_DATABASE=Technical Consumer Products, Inc. + +OUI:24BBC1* + ID_OUI_FROM_DATABASE=Absolute Analysis + +OUI:24BC82* + ID_OUI_FROM_DATABASE=Dali Wireless, Inc. + +OUI:24BCF8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:24BE05* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:24BE18* + ID_OUI_FROM_DATABASE=DADOUTEK COMPANY LIMITED + +OUI:24BF74* + ID_OUI_FROM_DATABASE=Private + +OUI:24C0B3* + ID_OUI_FROM_DATABASE=RSF + +OUI:24C17A* + ID_OUI_FROM_DATABASE=BEIJING IACTIVE NETWORK CO.,LTD + +OUI:24C1BD* + ID_OUI_FROM_DATABASE=CRRC DALIAN R&D CO.,LTD. + +OUI:24C3F9* + ID_OUI_FROM_DATABASE=Securitas Direct AB + +OUI:24C42F* + ID_OUI_FROM_DATABASE=Philips Lifeline + +OUI:24C44A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:24C696* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:24C848* + ID_OUI_FROM_DATABASE=mywerk Portal GmbH + +OUI:24C86E* + ID_OUI_FROM_DATABASE=Chaney Instrument Co. + +OUI:24C9A1* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:24C9DE* + ID_OUI_FROM_DATABASE=Genoray + +OUI:24CACB* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:24CBE7* + ID_OUI_FROM_DATABASE=MYK, Inc. + +OUI:24CF21* + ID_OUI_FROM_DATABASE=Shenzhen State Micro Technology Co., Ltd + +OUI:24D0DF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:24D13F* + ID_OUI_FROM_DATABASE=MEXUS CO.,LTD + +OUI:24D2CC* + ID_OUI_FROM_DATABASE=SmartDrive Systems Inc. + +OUI:24D3F2* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:24D51C* + ID_OUI_FROM_DATABASE=Zhongtian broadband technology co., LTD + +OUI:24D76B* + ID_OUI_FROM_DATABASE=Syntronic AB + +OUI:24D921* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:24DA11* + ID_OUI_FROM_DATABASE=NO NDA Inc + +OUI:24DA33* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:24DA9B* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:24DAB6* + ID_OUI_FROM_DATABASE=Sistemas de Gestión Energética S.A. de C.V + +OUI:24DBAC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:24DBAD* + ID_OUI_FROM_DATABASE=ShopperTrak RCT Corporation + +OUI:24DBED* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:24DEC6* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:24DF6A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:24DFA7* + ID_OUI_FROM_DATABASE=Hangzhou BroadLink Technology Co.,Ltd + +OUI:24E124* + ID_OUI_FROM_DATABASE=Xiamen Ursaconn Technology Co. , Ltd. + +OUI:24E271* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:24E314* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:24E43F* + ID_OUI_FROM_DATABASE=Wenzhou Kunmei Communication Technology Co.,Ltd. + +OUI:24E5AA* + ID_OUI_FROM_DATABASE=Philips Oral Healthcare, Inc. + +OUI:24E6BA* + ID_OUI_FROM_DATABASE=JSC Zavod im. Kozitsky + +OUI:24E9B3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:24EA40* + ID_OUI_FROM_DATABASE=Helmholz GmbH & Co. KG + +OUI:24EB65* + ID_OUI_FROM_DATABASE=SAET I.S. S.r.l. + +OUI:24EC51* + ID_OUI_FROM_DATABASE=ADF Technologies Sdn Bhd + +OUI:24EC99* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:24ECD6* + ID_OUI_FROM_DATABASE=CSG Science & Technology Co.,Ltd.Hefei + +OUI:24EE3A* + ID_OUI_FROM_DATABASE=Chengdu Yingji Electronic Hi-tech Co Ltd + +OUI:24EE9A* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:24F094* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:24F0FF* + ID_OUI_FROM_DATABASE=GHT Co., Ltd. + +OUI:24F128* + ID_OUI_FROM_DATABASE=Telstra + +OUI:24F27F* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:24F2DD* + ID_OUI_FROM_DATABASE=Radiant Zemax LLC + +OUI:24F57E* + ID_OUI_FROM_DATABASE=HWH CO., LTD. + +OUI:24F5A2* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:24F5AA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:24F677* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:24FAF3* + ID_OUI_FROM_DATABASE=Shanghai Flexem Technology Co.,Ltd. + +OUI:24FB65* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:24FCE5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:24FD0D* + ID_OUI_FROM_DATABASE=INDÚSTRIA DE TELECOMUNICAÇÃO ELETRÔNICA + +OUI:24FD52* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:24FD5B* + ID_OUI_FROM_DATABASE=SmartThings, Inc. + +OUI:280245* + ID_OUI_FROM_DATABASE=Konze System Technology Co.,Ltd. + +OUI:2802D8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:2804E0* + ID_OUI_FROM_DATABASE=FERMAX ELECTRONICA S.A.U. + +OUI:28061E* + ID_OUI_FROM_DATABASE=NINGBO GLOBAL USEFUL ELECTRIC CO.,LTD + +OUI:28068D* + ID_OUI_FROM_DATABASE=ITL, LLC + +OUI:28070D* + ID_OUI_FROM_DATABASE=GUANGZHOU WINSOUND INFORMATION TECHNOLOGY CO.,LTD. + +OUI:280B5C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:280C28* + ID_OUI_FROM_DATABASE=Unigen DataStorage Corporation + +OUI:280CB8* + ID_OUI_FROM_DATABASE=Mikrosay Yazilim ve Elektronik A.S. + +OUI:280DFC* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:280E8B* + ID_OUI_FROM_DATABASE=Beijing Spirit Technology Development Co., Ltd. + +OUI:28101B* + ID_OUI_FROM_DATABASE=MagnaCom + +OUI:28107B* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:2811A5* + ID_OUI_FROM_DATABASE=Bose Corporation + +OUI:2811EC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:281471* + ID_OUI_FROM_DATABASE=Lantis co., LTD. + +OUI:28162E* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:28167F* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:2816A8* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:2816AD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:2817CE* + ID_OUI_FROM_DATABASE=Omnisense Ltd + +OUI:281878* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:2818FD* + ID_OUI_FROM_DATABASE=Aditya Infotech Ltd. + +OUI:282246* + ID_OUI_FROM_DATABASE=Beijing Sinoix Communication Co., LTD + +OUI:282373* + ID_OUI_FROM_DATABASE=Digita + +OUI:2823F5* + ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd. + +OUI:2824FF* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:282536* + ID_OUI_FROM_DATABASE=SHENZHEN HOLATEK CO.,LTD + +OUI:2826A6* + ID_OUI_FROM_DATABASE=PBR electronics GmbH + +OUI:2827BF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:28285D* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:282986* + ID_OUI_FROM_DATABASE=APC by Schneider Electric + +OUI:2829CC* + ID_OUI_FROM_DATABASE=Corsa Technology Incorporated + +OUI:2829D9* + ID_OUI_FROM_DATABASE=GlobalBeiMing technology (Beijing)Co. Ltd + +OUI:282C020* + ID_OUI_FROM_DATABASE=SAKATA DENKI Co., Ltd. + +OUI:282C021* + ID_OUI_FROM_DATABASE=Astronics AES + +OUI:282C022* + ID_OUI_FROM_DATABASE=Shenzhen emb-star technology co. LTD + +OUI:282C023* + ID_OUI_FROM_DATABASE=Dexin Digital Technology Corp. Ltd. + +OUI:282C024* + ID_OUI_FROM_DATABASE=EFENTO T P SZYDŁOWSKI K ZARĘBA SPÓŁKA JAWNA + +OUI:282C025* + ID_OUI_FROM_DATABASE=LLC MICROTEH + +OUI:282C026* + ID_OUI_FROM_DATABASE=Lookman Electroplast Industries Ltd + +OUI:282C027* + ID_OUI_FROM_DATABASE=Telecom and Microelectonic Industries + +OUI:282C028* + ID_OUI_FROM_DATABASE=Shenzhen Neoway Technology Co.,Ltd. + +OUI:282C029* + ID_OUI_FROM_DATABASE=Systec Intelligent Building Technology (Tianjin) Co.,Ltd. + +OUI:282C02A* + ID_OUI_FROM_DATABASE=Tokin Limited + +OUI:282C02B* + ID_OUI_FROM_DATABASE=ThirdReality, Inc + +OUI:282C02C* + ID_OUI_FROM_DATABASE=Epoch International Enterprises, Inc. + +OUI:282C02D* + ID_OUI_FROM_DATABASE=SHENZHEN DOMENOR TECHNOLOGY LLC + +OUI:282C02E* + ID_OUI_FROM_DATABASE=Capintec, Inc. + +OUI:282CB2* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:282FC2* + ID_OUI_FROM_DATABASE=Automotive Data Solutions + +OUI:2830AC* + ID_OUI_FROM_DATABASE=Frontiir Co. Ltd. + +OUI:283152* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:283166* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:28317E* + ID_OUI_FROM_DATABASE=Hongkong Nano IC Technologies Co., Ltd + +OUI:2832C5* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:283334* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:283410* + ID_OUI_FROM_DATABASE=Enigma Diagnostics Limited + +OUI:2834A2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:283545* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + +OUI:2836380* + ID_OUI_FROM_DATABASE=Knowles Electronics LLC + +OUI:2836381* + ID_OUI_FROM_DATABASE=Panasonic System Solutions Europe + +OUI:2836382* + ID_OUI_FROM_DATABASE=SHENZHEN GOSPELL SMARTHOME ELECTRONIC CO., LTD. + +OUI:2836383* + ID_OUI_FROM_DATABASE=Sabinetek + +OUI:2836384* + ID_OUI_FROM_DATABASE=Dspread Technology (Beijing) Inc. + +OUI:2836385* + ID_OUI_FROM_DATABASE=CHARGELIB + +OUI:2836386* + ID_OUI_FROM_DATABASE=Georg Neumann GmbH + +OUI:2836387* + ID_OUI_FROM_DATABASE=Innovative Technology Ltd + +OUI:2836388* + ID_OUI_FROM_DATABASE=Havells India Limited + +OUI:2836389* + ID_OUI_FROM_DATABASE=Shenzhen Zhi Hua Creative Technology Co., Ltd. + +OUI:283638A* + ID_OUI_FROM_DATABASE=Bluekey Pty Ltd + +OUI:283638B* + ID_OUI_FROM_DATABASE=ShangHai Canall Information Technology Co.,Ltd + +OUI:283638C* + ID_OUI_FROM_DATABASE=Swisson AG + +OUI:283638D* + ID_OUI_FROM_DATABASE=APPEAK Technology System Co.Ltd. + +OUI:283638E* + ID_OUI_FROM_DATABASE=SCA Hygiene Products AB + +OUI:283713* + ID_OUI_FROM_DATABASE=Shenzhen 3Nod Digital Technology Co., Ltd. + +OUI:283737* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28385C* + ID_OUI_FROM_DATABASE=FLEXTRONICS + +OUI:2838CF* + ID_OUI_FROM_DATABASE=Gen2wave + +OUI:283926* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. + +OUI:28395E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:2839E7* + ID_OUI_FROM_DATABASE=Preceno Technology Pte.Ltd. + +OUI:283A4D* + ID_OUI_FROM_DATABASE=Cloud Network Technology (Samoa) Limited + +OUI:283B82* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:283B96* + ID_OUI_FROM_DATABASE=Cool Control LTD + +OUI:283CE4* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:283E76* + ID_OUI_FROM_DATABASE=Common Networks + +OUI:283F69* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:28401A* + ID_OUI_FROM_DATABASE=C8 MediSensors, Inc. + +OUI:284121* + ID_OUI_FROM_DATABASE=OptiSense Network, LLC + +OUI:2841C6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:284430* + ID_OUI_FROM_DATABASE=GenesisTechnical Systems (UK) Ltd + +OUI:2847AA* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:284846* + ID_OUI_FROM_DATABASE=GridCentric Inc. + +OUI:284C53* + ID_OUI_FROM_DATABASE=Intune Networks + +OUI:284D92* + ID_OUI_FROM_DATABASE=Luminator + +OUI:284ED7* + ID_OUI_FROM_DATABASE=OutSmart Power Systems, Inc. + +OUI:284FCE* + ID_OUI_FROM_DATABASE=Liaoning Wontel Science and Technology Development Co.,Ltd. + +OUI:285132* + ID_OUI_FROM_DATABASE=Shenzhen Prayfly Technology Co.,Ltd + +OUI:285261* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2852E0* + ID_OUI_FROM_DATABASE=Layon international Electronic & Telecom Co.,Ltd + +OUI:2852F9* + ID_OUI_FROM_DATABASE=Zhongxin Intelligent Times (Shenzhen) Co., Ltd. + +OUI:285471* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:28565A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:2856C1* + ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH + +OUI:285767* + ID_OUI_FROM_DATABASE=Dish Technologies Corp + +OUI:2857BE* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:285AEB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:285F2F* + ID_OUI_FROM_DATABASE=RNware Co.,Ltd. + +OUI:285FDB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:286046* + ID_OUI_FROM_DATABASE=Lantech Communications Global, Inc. + +OUI:286094* + ID_OUI_FROM_DATABASE=CAPELEC + +OUI:286336* + ID_OUI_FROM_DATABASE=Siemens AG + +OUI:2863BD* + ID_OUI_FROM_DATABASE=APTIV SERVICES US, LLC + +OUI:2864B0* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:28656B* + ID_OUI_FROM_DATABASE=Keystone Microtech Corporation + +OUI:2866E3* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:286AB8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:286ABA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:286C07* + ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD + +OUI:286D97* + ID_OUI_FROM_DATABASE=SAMJIN Co., Ltd. + +OUI:286DCD* + ID_OUI_FROM_DATABASE=Beijing Winner Microelectronics Co.,Ltd. + +OUI:286ED4* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:286F7F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:287184* + ID_OUI_FROM_DATABASE=Spire Payments + +OUI:2872C5* + ID_OUI_FROM_DATABASE=Smartmatic Corp + +OUI:2872F0* + ID_OUI_FROM_DATABASE=ATHENA + +OUI:2875D8* + ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD + +OUI:287610* + ID_OUI_FROM_DATABASE=IgniteNet + +OUI:2876CD* + ID_OUI_FROM_DATABASE=Funshion Online Technologies Co.,Ltd + +OUI:2877F1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:287994* + ID_OUI_FROM_DATABASE=Realplay Digital Technology(Shenzhen) Co.,Ltd + +OUI:287AEE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:287B09* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:287CDB* + ID_OUI_FROM_DATABASE=Hefei Toycloud Technology Co.,ltd + +OUI:287FCF* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:288023* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:288088* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:2880A2* + ID_OUI_FROM_DATABASE=Novatel Wireless Solutions, Inc. + +OUI:288335* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:28840E* + ID_OUI_FROM_DATABASE=silicon valley immigration service + +OUI:2884FA* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:28852D* + ID_OUI_FROM_DATABASE=Touch Networks + +OUI:288915* + ID_OUI_FROM_DATABASE=CashGuard Sverige AB + +OUI:288A1C* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:288CB8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:2891D0* + ID_OUI_FROM_DATABASE=Stage Tec Entwicklungsgesellschaft für professionelle Audiotechnik mbH + +OUI:28924A* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:2893FE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:28940F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2894AF* + ID_OUI_FROM_DATABASE=Samhwa Telecom + +OUI:28987B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:28993A* + ID_OUI_FROM_DATABASE=Arista Networks + +OUI:2899C7* + ID_OUI_FROM_DATABASE=LINDSAY BROADBAND INC + +OUI:289A4B* + ID_OUI_FROM_DATABASE=SteelSeries ApS + +OUI:289AF7* + ID_OUI_FROM_DATABASE=ADVA Optical Networking Ltd. + +OUI:289AFA* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:289E97* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:289EDF* + ID_OUI_FROM_DATABASE=Danfoss Turbocor Compressors, Inc + +OUI:289EFC* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:28A02B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28A183* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:28A186* + ID_OUI_FROM_DATABASE=enblink + +OUI:28A192* + ID_OUI_FROM_DATABASE=GERP Solution + +OUI:28A1EB* + ID_OUI_FROM_DATABASE=ETEK TECHNOLOGY (SHENZHEN) CO.,LTD + +OUI:28A241* + ID_OUI_FROM_DATABASE=exlar corp + +OUI:28A24B* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:28A574* + ID_OUI_FROM_DATABASE=Miller Electric Mfg. Co. + +OUI:28A5EE* + ID_OUI_FROM_DATABASE=Shenzhen SDGI CATV Co., Ltd + +OUI:28A6AC* + ID_OUI_FROM_DATABASE=seca gmbh & co. kg + +OUI:28A6DB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:28AC67* + ID_OUI_FROM_DATABASE=Mach Power, Rappresentanze Internazionali s.r.l. + +OUI:28AC9E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:28AD3E* + ID_OUI_FROM_DATABASE=Shenzhen TONG BO WEI Technology CO.,LTD + +OUI:28AF0A* + ID_OUI_FROM_DATABASE=Sirius XM Radio Inc + +OUI:28B0CC* + ID_OUI_FROM_DATABASE=Xenya d.o.o. + +OUI:28B2BD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:28B3AB* + ID_OUI_FROM_DATABASE=Genmark Automation + +OUI:28B448* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:28B4FB* + ID_OUI_FROM_DATABASE=Sprocomm Technologies CO.,LTD. + +OUI:28B9D9* + ID_OUI_FROM_DATABASE=Radisys Corporation + +OUI:28BA18* + ID_OUI_FROM_DATABASE=NextNav, LLC + +OUI:28BAB5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:28BB59* + ID_OUI_FROM_DATABASE=RNET Technologies, Inc. + +OUI:28BC18* + ID_OUI_FROM_DATABASE=SourcingOverseas Co. Ltd + +OUI:28BC56* + ID_OUI_FROM_DATABASE=EMAC, Inc. + +OUI:28BD89* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:28BE03* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:28BE9B* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:28BF89* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:28C0DA* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:28C13C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co., Ltd. + +OUI:28C2DD* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:28C63F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:28C671* + ID_OUI_FROM_DATABASE=Yota Devices OY + +OUI:28C68E* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:28C718* + ID_OUI_FROM_DATABASE=Altierre + +OUI:28C7CE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:28C825* + ID_OUI_FROM_DATABASE=DellKing Industrial Co., Ltd + +OUI:28C87A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:28C914* + ID_OUI_FROM_DATABASE=Taimag Corporation + +OUI:28CA09* + ID_OUI_FROM_DATABASE=ThyssenKrupp Elevators (Shanghai) Co.,Ltd + +OUI:28CBEB* + ID_OUI_FROM_DATABASE=One + +OUI:28CC01* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:28CCFF* + ID_OUI_FROM_DATABASE=Corporacion Empresarial Altra SL + +OUI:28CD1C* + ID_OUI_FROM_DATABASE=Espotel Oy + +OUI:28CD4C* + ID_OUI_FROM_DATABASE=Individual Computers GmbH + +OUI:28CD9C* + ID_OUI_FROM_DATABASE=Shenzhen Dynamax Software Development Co.,Ltd. + +OUI:28CDC4* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:28CF08* + ID_OUI_FROM_DATABASE=ESSYS + +OUI:28CFDA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28CFE9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28D0CB* + ID_OUI_FROM_DATABASE=Cambridge Communication Systems Ltd + +OUI:28D1AF* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:28D1B7* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:28D244* + ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology Co., Ltd. + +OUI:28D436* + ID_OUI_FROM_DATABASE=Jiangsu dewosi electric co., LTD + +OUI:28D576* + ID_OUI_FROM_DATABASE=Premier Wireless, Inc. + +OUI:28D93E* + ID_OUI_FROM_DATABASE=Telecor Inc. + +OUI:28D98A* + ID_OUI_FROM_DATABASE=Hangzhou Konke Technology Co.,Ltd. + +OUI:28D997* + ID_OUI_FROM_DATABASE=Yuduan Mobile Co., Ltd. + +OUI:28DB81* + ID_OUI_FROM_DATABASE=Shanghai Guao Electronic Technology Co., Ltd + +OUI:28DEE5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:28DEF6* + ID_OUI_FROM_DATABASE=bioMerieux Inc. + +OUI:28E02C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28E14C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28E297* + ID_OUI_FROM_DATABASE=Shanghai InfoTM Microelectronics Co.,Ltd. + +OUI:28E31F* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:28E347* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:28E34E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:28E476* + ID_OUI_FROM_DATABASE=Pi-Coral + +OUI:28E608* + ID_OUI_FROM_DATABASE=Tokheim + +OUI:28E6E9* + ID_OUI_FROM_DATABASE=SIS Sat Internet Services GmbH + +OUI:28E794* + ID_OUI_FROM_DATABASE=Microtime Computer Inc. + +OUI:28E7CF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28E98E* + ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation + +OUI:28EC9A* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:28ED58* + ID_OUI_FROM_DATABASE=JAG Jakob AG + +OUI:28ED6A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28EDE0* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:28EE2C* + ID_OUI_FROM_DATABASE=Frontline Test Equipment + +OUI:28EE52* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:28EED3* + ID_OUI_FROM_DATABASE=Shenzhen Super D Technology Co., Ltd + +OUI:28EF01* + ID_OUI_FROM_DATABASE=Private + +OUI:28F033* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28F076* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28F10E* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:28F358* + ID_OUI_FROM_DATABASE=2C - Trifonov & Co + +OUI:28F366* + ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD + +OUI:28F532* + ID_OUI_FROM_DATABASE=ADD-Engineering BV + +OUI:28F5370* + ID_OUI_FROM_DATABASE=Valeo Siemens eAutomotive Norway + +OUI:28F5371* + ID_OUI_FROM_DATABASE=Umojo + +OUI:28F5372* + ID_OUI_FROM_DATABASE=Unicair Communication Tec Co., Ltd. + +OUI:28F5373* + ID_OUI_FROM_DATABASE=PRIMETECH ENGINEERING CORP. + +OUI:28F5374* + ID_OUI_FROM_DATABASE=Phyn LLC + +OUI:28F5375* + ID_OUI_FROM_DATABASE=Atomrock LLC + +OUI:28F5376* + ID_OUI_FROM_DATABASE=MyOmega Systems GmbH + +OUI:28F5377* + ID_OUI_FROM_DATABASE=Shenzhen Modern Cowboy Technology Co.,Ltd. + +OUI:28F5378* + ID_OUI_FROM_DATABASE=1MORE + +OUI:28F5379* + ID_OUI_FROM_DATABASE=Herbert Waldmann GmbH & Co. KG + +OUI:28F537A* + ID_OUI_FROM_DATABASE=Honeywell Safety Products USA, Inc + +OUI:28F537B* + ID_OUI_FROM_DATABASE=LogiM GmbH Software und Entwicklung + +OUI:28F537C* + ID_OUI_FROM_DATABASE=Matricx Singapore Pte Ltd + +OUI:28F537D* + ID_OUI_FROM_DATABASE=Skyrockettoys LLC + +OUI:28F537E* + ID_OUI_FROM_DATABASE=Performance Motion Devices + +OUI:28F606* + ID_OUI_FROM_DATABASE=Syes srl + +OUI:28FA7A* + ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd. + +OUI:28FAA0* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:28FBD3* + ID_OUI_FROM_DATABASE=Ragentek Technology Group + +OUI:28FC51* + ID_OUI_FROM_DATABASE=The Electric Controller and Manufacturing Co., LLC + +OUI:28FCF6* + ID_OUI_FROM_DATABASE=Shenzhen Xin KingBrand enterprises Co.,Ltd + +OUI:28FD800* + ID_OUI_FROM_DATABASE=Millcode + +OUI:28FD801* + ID_OUI_FROM_DATABASE=Galileo, Inc. + +OUI:28FD802* + ID_OUI_FROM_DATABASE=Zhixiang Technology Co., Ltd. + +OUI:28FD803* + ID_OUI_FROM_DATABASE=NUUO, Inc. + +OUI:28FD804* + ID_OUI_FROM_DATABASE=Digital Signal Corp + +OUI:28FD805* + ID_OUI_FROM_DATABASE=Xiaocong Network Limited + +OUI:28FD806* + ID_OUI_FROM_DATABASE=Vigil Monitoring + +OUI:28FD807* + ID_OUI_FROM_DATABASE=University of York + +OUI:28FD808* + ID_OUI_FROM_DATABASE=Jasco Products Company + +OUI:28FD809* + ID_OUI_FROM_DATABASE=JINLITONG INTERNATIONAL CO.,LTD + +OUI:28FD80A* + ID_OUI_FROM_DATABASE=Apollo Digital (Taiwan) Ltd. + +OUI:28FD80B* + ID_OUI_FROM_DATABASE=Poket Hardware GmbH + +OUI:28FD80C* + ID_OUI_FROM_DATABASE=Airbus Defence and Space Oy + +OUI:28FD80D* + ID_OUI_FROM_DATABASE=Grandway Technology (Shenzhen) Limited + +OUI:28FD80E* + ID_OUI_FROM_DATABASE=T-Radio AS + +OUI:28FD80F* + ID_OUI_FROM_DATABASE=Private + +OUI:28FE65* + ID_OUI_FROM_DATABASE=DongGuan Siyoto Electronics Co., Ltd + +OUI:28FECD* + ID_OUI_FROM_DATABASE=Lemobile Information Technology (Beijing) Co., Ltd. + +OUI:28FEDE* + ID_OUI_FROM_DATABASE=COMESTA, Inc. + +OUI:28FF3C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:28FF3E* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:28FFB2* + ID_OUI_FROM_DATABASE=Toshiba Corp. + +OUI:2C002C* + ID_OUI_FROM_DATABASE=UNOWHY + +OUI:2C0033* + ID_OUI_FROM_DATABASE=EControls, LLC + +OUI:2C00F7* + ID_OUI_FROM_DATABASE=XOS + +OUI:2C010B* + ID_OUI_FROM_DATABASE=NASCENT Technology, LLC - RemKon + +OUI:2C01B5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C029F* + ID_OUI_FROM_DATABASE=3ALogics + +OUI:2C0623* + ID_OUI_FROM_DATABASE=Win Leader Inc. + +OUI:2C073C* + ID_OUI_FROM_DATABASE=DEVLINE LIMITED + +OUI:2C081C* + ID_OUI_FROM_DATABASE=OVH + +OUI:2C088C* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:2C094D* + ID_OUI_FROM_DATABASE=Raptor Engineering, LLC + +OUI:2C09CB* + ID_OUI_FROM_DATABASE=COBS AB + +OUI:2C0BE9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C0E3D* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:2C10C1* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:2C15E1* + ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd. + +OUI:2C16BD0* + ID_OUI_FROM_DATABASE=Beijing Jishi Huitong Technology Co., Ltd. + +OUI:2C16BD1* + ID_OUI_FROM_DATABASE=Curtiss-Wright Drive Technology + +OUI:2C16BD2* + ID_OUI_FROM_DATABASE=AIMCO + +OUI:2C16BD3* + ID_OUI_FROM_DATABASE=Saft AB + +OUI:2C16BD4* + ID_OUI_FROM_DATABASE=Sunit Oy + +OUI:2C16BD5* + ID_OUI_FROM_DATABASE=Beijing Zhijian Link Technology Co., Ltd. + +OUI:2C16BD6* + ID_OUI_FROM_DATABASE=CLOUDWALK TECHNOLOGY CO.,LTD + +OUI:2C16BD7* + ID_OUI_FROM_DATABASE=SCT OPTRONICS CO., LTD + +OUI:2C16BD8* + ID_OUI_FROM_DATABASE=Shenzhen elink smart Co., ltd + +OUI:2C16BD9* + ID_OUI_FROM_DATABASE=Shanghai Walktech Information Technology Co.,Ltd. + +OUI:2C16BDA* + ID_OUI_FROM_DATABASE=Shenzhen Haiying Wire Tech Co., Ltd. + +OUI:2C16BDB* + ID_OUI_FROM_DATABASE=LINGDONG TECHNOLOGY (BEIJING) CO. LTD + +OUI:2C16BDC* + ID_OUI_FROM_DATABASE=Beijing CHJ Automotive Co., Ltd. + +OUI:2C16BDD* + ID_OUI_FROM_DATABASE=Hangzhou Yanzhi Technology Co.,Ltd. + +OUI:2C16BDE* + ID_OUI_FROM_DATABASE=Molex Incorporated + +OUI:2C1875* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:2C18AE* + ID_OUI_FROM_DATABASE=Trend Electronics Co., Ltd. + +OUI:2C1984* + ID_OUI_FROM_DATABASE=IDN Telecom, Inc. + +OUI:2C1A01* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2C1A31* + ID_OUI_FROM_DATABASE=Electronics Company Limited + +OUI:2C1BC8* + ID_OUI_FROM_DATABASE=Hunan Topview Network System CO.,LTD + +OUI:2C1CF6* + ID_OUI_FROM_DATABASE=Alien Green LLC + +OUI:2C1DB8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:2C1E4F* + ID_OUI_FROM_DATABASE=Chengdu Qianli Network Technology Co., Ltd. + +OUI:2C1EEA* + ID_OUI_FROM_DATABASE=AERODEV + +OUI:2C1F23* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:2C200B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:2C2131* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:2C2172* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:2C21D7* + ID_OUI_FROM_DATABASE=IMAX Corporation + +OUI:2C228B* + ID_OUI_FROM_DATABASE=CTR SRL + +OUI:2C233A* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:2C245F* + ID_OUI_FROM_DATABASE=Babolat VS + +OUI:2C2617* + ID_OUI_FROM_DATABASE=Oculus VR, LLC + +OUI:2C265F0* + ID_OUI_FROM_DATABASE=XIAMEN VORLINK IOT TECHNOLOGY CO.,LTD. + +OUI:2C265F1* + ID_OUI_FROM_DATABASE=Griessbach + +OUI:2C265F2* + ID_OUI_FROM_DATABASE=Jiangsu JARI Technology Group Co., LTD + +OUI:2C265F3* + ID_OUI_FROM_DATABASE=shenzhen Clever Electronic Co., Ltd. + +OUI:2C265F4* + ID_OUI_FROM_DATABASE=GTA Electronics Co., Ltd. + +OUI:2C265F5* + ID_OUI_FROM_DATABASE=Motec GmbH + +OUI:2C265F6* + ID_OUI_FROM_DATABASE=Appostar Technology Co. Ltd + +OUI:2C265F7* + ID_OUI_FROM_DATABASE=Coremate Technical Co., Ltd + +OUI:2C265F8* + ID_OUI_FROM_DATABASE=Itus Networks, LLC + +OUI:2C265F9* + ID_OUI_FROM_DATABASE=Brüel & Kjaer Vibro GmbH + +OUI:2C265FA* + ID_OUI_FROM_DATABASE=Polara Engineering + +OUI:2C265FB* + ID_OUI_FROM_DATABASE=Rexgen Inc. + +OUI:2C265FC* + ID_OUI_FROM_DATABASE=AATON DIGITAL + +OUI:2C265FD* + ID_OUI_FROM_DATABASE=E Core Corporation + +OUI:2C265FE* + ID_OUI_FROM_DATABASE=Hysentel Technology Co., Ltd + +OUI:2C265FF* + ID_OUI_FROM_DATABASE=Private + +OUI:2C26C5* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:2C279E0* + ID_OUI_FROM_DATABASE=Changzhou WEBO Weighing Device & System CO.,LTD + +OUI:2C279E1* + ID_OUI_FROM_DATABASE=Electronique Bluewave Inc. + +OUI:2C279E2* + ID_OUI_FROM_DATABASE=Kunyi electronic technology (Shanghai) Co., Ltd. + +OUI:2C279E3* + ID_OUI_FROM_DATABASE=Private + +OUI:2C279E4* + ID_OUI_FROM_DATABASE=Shijiazhuang King Transportation Equipment Co.,Ltd + +OUI:2C279E5* + ID_OUI_FROM_DATABASE=AudioNord Distribution A/S + +OUI:2C279E6* + ID_OUI_FROM_DATABASE=Rutledge Omni Services Pte Ltd + +OUI:2C279E7* + ID_OUI_FROM_DATABASE=FOCAL-JMLab + +OUI:2C279E8* + ID_OUI_FROM_DATABASE=Institut Dr. Foerster GmbH & Co. KG + +OUI:2C279E9* + ID_OUI_FROM_DATABASE=octoScope, Inc. + +OUI:2C279EA* + ID_OUI_FROM_DATABASE=Exegy Inc + +OUI:2C279EB* + ID_OUI_FROM_DATABASE=Forties Inc. + +OUI:2C279EC* + ID_OUI_FROM_DATABASE=WAYCOM Technology Co.,Ltd + +OUI:2C279ED* + ID_OUI_FROM_DATABASE=Jiangsu JianHu Science & Technology Co., Ltd. + +OUI:2C279EE* + ID_OUI_FROM_DATABASE=Amaryllo International Inc. + +OUI:2C27D7* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:2C282D* + ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + +OUI:2C28B7* + ID_OUI_FROM_DATABASE=Hangzhou Ruiying technology co., LTD + +OUI:2C2997* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:2C2BF9* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:2C2D48* + ID_OUI_FROM_DATABASE=bct electronic GesmbH + +OUI:2C3033* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:2C3068* + ID_OUI_FROM_DATABASE=Pantech Co.,Ltd + +OUI:2C3124* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C3311* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C3361* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:2C337A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:2C3427* + ID_OUI_FROM_DATABASE=ERCO & GENER + +OUI:2C3557* + ID_OUI_FROM_DATABASE=ELLIY Power CO..Ltd + +OUI:2C36A0* + ID_OUI_FROM_DATABASE=Capisco Limited + +OUI:2C36F8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C3731* + ID_OUI_FROM_DATABASE=SHENZHEN YIFANG DIGITAL TECHNOLOGY CO.,LTD. + +OUI:2C3796* + ID_OUI_FROM_DATABASE=CYBO CO.,LTD. + +OUI:2C37C5* + ID_OUI_FROM_DATABASE=Qingdao Haier Intelligent Home Appliance Technology Co.,Ltd + +OUI:2C3996* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:2C39C1* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:2C3A28* + ID_OUI_FROM_DATABASE=Fagor Electrónica + +OUI:2C3AE8* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:2C3AFD* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:2C3BFD* + ID_OUI_FROM_DATABASE=Netstor Technology Co., Ltd. + +OUI:2C3ECF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C3F0B* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:2C3F38* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C3F3E* + ID_OUI_FROM_DATABASE=Alge-Timing GmbH + +OUI:2C402B* + ID_OUI_FROM_DATABASE=Smart iBlue Technology Limited + +OUI:2C4053* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:2C4138* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:2C41A1* + ID_OUI_FROM_DATABASE=Bose Corporation + +OUI:2C4205* + ID_OUI_FROM_DATABASE=Lytx + +OUI:2C431A* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:2C4401* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:2C441B* + ID_OUI_FROM_DATABASE=Spectrum Medical Limited + +OUI:2C44FD* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:2C4759* + ID_OUI_FROM_DATABASE=Beijing MEGA preponderance Science & Technology Co. Ltd + +OUI:2C48350* + ID_OUI_FROM_DATABASE=Progress Rail Services, Inspection and Information Systems + +OUI:2C48351* + ID_OUI_FROM_DATABASE=Advanced Electronics Company Ltd + +OUI:2C48352* + ID_OUI_FROM_DATABASE=Rheonik Messtechnik GmbH + +OUI:2C48353* + ID_OUI_FROM_DATABASE=Newtrax Technologies Inc + +OUI:2C48354* + ID_OUI_FROM_DATABASE=GEARTECH LTD + +OUI:2C48355* + ID_OUI_FROM_DATABASE=Scout Security, Inc. + +OUI:2C48356* + ID_OUI_FROM_DATABASE=Exertus Oy + +OUI:2C48357* + ID_OUI_FROM_DATABASE=FAST + +OUI:2C48358* + ID_OUI_FROM_DATABASE=DPS Electronics + +OUI:2C48359* + ID_OUI_FROM_DATABASE=SureFlap Ltd + +OUI:2C4835A* + ID_OUI_FROM_DATABASE=Collatz+Trojan GmbH + +OUI:2C4835B* + ID_OUI_FROM_DATABASE=Shanghai Visteon Automotive Electronics System CO. Ltd. + +OUI:2C4835C* + ID_OUI_FROM_DATABASE=Santec Corporation + +OUI:2C4835D* + ID_OUI_FROM_DATABASE=Phasor Solutions Ltd + +OUI:2C4835E* + ID_OUI_FROM_DATABASE=IROOTECH TECHNOLOGY CO.,LTD + +OUI:2C4CC6* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:2C4D54* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:2C4D79* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:2C4E7D* + ID_OUI_FROM_DATABASE=Chunghua Intelligent Network Equipment Inc. + +OUI:2C4F52* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C5089* + ID_OUI_FROM_DATABASE=Shenzhen Kaixuan Visual Technology Co.,Limited + +OUI:2C534A* + ID_OUI_FROM_DATABASE=Shenzhen Winyao Electronic Limited + +OUI:2C542D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C5491* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:2C54CF* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:2C553C* + ID_OUI_FROM_DATABASE=Gainspeed, Inc. + +OUI:2C557C* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:2C55D3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2C56DC* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:2C5731* + ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited + +OUI:2C5741* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C584F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:2C58E8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2C598A* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:2C59E5* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:2C5A05* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:2C5A0F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C5A8D* + ID_OUI_FROM_DATABASE=SYSTRONIK Elektronik u. Systemtechnik GmbH + +OUI:2C5AA3* + ID_OUI_FROM_DATABASE=PROMATE ELECTRONIC CO.LTD + +OUI:2C5BB8* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:2C5BE1* + ID_OUI_FROM_DATABASE=Centripetal Networks, Inc + +OUI:2C5D34* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:2C5D93* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:2C5FF3* + ID_OUI_FROM_DATABASE=Pertronic Industries + +OUI:2C600C* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:2C6104* + ID_OUI_FROM_DATABASE=SHENZHEN FENGLIAN TECHNOLOGY CO., LTD. + +OUI:2C61F6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:2C625A* + ID_OUI_FROM_DATABASE=Finest Security Systems Co., Ltd + +OUI:2C6289* + ID_OUI_FROM_DATABASE=Regenersis (Glenrothes) Ltd + +OUI:2C6373* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:2C641F* + ID_OUI_FROM_DATABASE=Vizio, Inc + +OUI:2C6798* + ID_OUI_FROM_DATABASE=InTalTech Ltd. + +OUI:2C67FB* + ID_OUI_FROM_DATABASE=ShenZhen Zhengjili Electronics Co., LTD + +OUI:2C69BA* + ID_OUI_FROM_DATABASE=RF Controls, LLC + +OUI:2C6A6F0* + ID_OUI_FROM_DATABASE=Shanghai Shuncom Electronic Technology Co.,Ltd + +OUI:2C6A6F1* + ID_OUI_FROM_DATABASE=ELKO EP, s.r.o. + +OUI:2C6A6F2* + ID_OUI_FROM_DATABASE=NanChang LangJie Technology Co.,Ltd + +OUI:2C6A6F3* + ID_OUI_FROM_DATABASE=Cloudproject Generation Srl + +OUI:2C6A6F4* + ID_OUI_FROM_DATABASE=TINYCO + +OUI:2C6A6F5* + ID_OUI_FROM_DATABASE=SHEN ZHEN SIS SCIENCE & TECHNOLOGY LTD. + +OUI:2C6A6F6* + ID_OUI_FROM_DATABASE=Beep, Inc. + +OUI:2C6A6F7* + ID_OUI_FROM_DATABASE=SM DSP CO.,LTD. + +OUI:2C6A6F8* + ID_OUI_FROM_DATABASE=Milbank Manufacturing Co. + +OUI:2C6A6F9* + ID_OUI_FROM_DATABASE=Logic IO Aps + +OUI:2C6A6FA* + ID_OUI_FROM_DATABASE=Wellntel, Inc. + +OUI:2C6A6FB* + ID_OUI_FROM_DATABASE=Schneider Electric Korea + +OUI:2C6A6FC* + ID_OUI_FROM_DATABASE=Sensity Systems + +OUI:2C6A6FD* + ID_OUI_FROM_DATABASE=Holjeron + +OUI:2C6A6FE* + ID_OUI_FROM_DATABASE=EATON FHF Funke + Huster Fernsig GmbH + +OUI:2C6A6FF* + ID_OUI_FROM_DATABASE=Private + +OUI:2C6B7D* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:2C6BF5* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:2C6E85* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:2C6FC9* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:2C7155* + ID_OUI_FROM_DATABASE=HiveMotion + +OUI:2C72C3* + ID_OUI_FROM_DATABASE=Soundmatters + +OUI:2C7360* + ID_OUI_FROM_DATABASE=Earda Technologies co Ltd + +OUI:2C73A0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C750F* + ID_OUI_FROM_DATABASE=Shanghai Dongzhou-Lawton Communication Technology Co. Ltd. + +OUI:2C768A* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:2C780E* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:2C79D7* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:2C7B5A* + ID_OUI_FROM_DATABASE=Milper Ltd + +OUI:2C7B84* + ID_OUI_FROM_DATABASE=OOO Petr Telegin + +OUI:2C7CE4* + ID_OUI_FROM_DATABASE=Wuhan Tianyu Information Industry Co., Ltd. + +OUI:2C7E81* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:2C7ECF* + ID_OUI_FROM_DATABASE=Onzo Ltd + +OUI:2C8065* + ID_OUI_FROM_DATABASE=HARTING Inc. of North America + +OUI:2C8158* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:2C86D2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2C8A72* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:2C8BF2* + ID_OUI_FROM_DATABASE=Hitachi Metals America Ltd + +OUI:2C9127* + ID_OUI_FROM_DATABASE=Eintechno Corporation + +OUI:2C91AB* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:2C922C* + ID_OUI_FROM_DATABASE=Kishu Giken Kogyou Company Ltd,. + +OUI:2C9464* + ID_OUI_FROM_DATABASE=Cincoze Co., Ltd. + +OUI:2C9569* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:2C957F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:2C9662* + ID_OUI_FROM_DATABASE=Invenit BV + +OUI:2C9717* + ID_OUI_FROM_DATABASE=I.C.Y. B.V. + +OUI:2C97B1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2C97ED* + ID_OUI_FROM_DATABASE=Sony Imaging Products & Solutions Inc. + +OUI:2C9924* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:2C9AA4* + ID_OUI_FROM_DATABASE=Eolo SpA + +OUI:2C9D1E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2C9E5F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:2C9EEC* + ID_OUI_FROM_DATABASE=Jabil Circuit Penang + +OUI:2C9EFC* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:2CA02F* + ID_OUI_FROM_DATABASE=Veroguard Systems Pty Ltd + +OUI:2CA157* + ID_OUI_FROM_DATABASE=acromate, Inc. + +OUI:2CA17D* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:2CA2B4* + ID_OUI_FROM_DATABASE=Fortify Technologies, LLC + +OUI:2CA30E* + ID_OUI_FROM_DATABASE=POWER DRAGON DEVELOPMENT LIMITED + +OUI:2CA539* + ID_OUI_FROM_DATABASE=Parallel Wireless, Inc + +OUI:2CA780* + ID_OUI_FROM_DATABASE=True Technologies Inc. + +OUI:2CA835* + ID_OUI_FROM_DATABASE=RIM + +OUI:2CA89C* + ID_OUI_FROM_DATABASE=Creatz inc. + +OUI:2CA9F0* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:2CAA8E* + ID_OUI_FROM_DATABASE=Wyze Labs Inc + +OUI:2CAB00* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2CAB25* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:2CAB33* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:2CABA4* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:2CABEB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2CAC44* + ID_OUI_FROM_DATABASE=CONEXTOP + +OUI:2CAD13* + ID_OUI_FROM_DATABASE=SHENZHEN ZHILU TECHNOLOGY CO.,LTD + +OUI:2CAE2B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:2CB05D* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:2CB0DF* + ID_OUI_FROM_DATABASE=Soliton Technologies Pvt Ltd + +OUI:2CB115* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:2CB21A* + ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd. + +OUI:2CB43A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:2CB693* + ID_OUI_FROM_DATABASE=Radware + +OUI:2CB69D* + ID_OUI_FROM_DATABASE=RED Digital Cinema + +OUI:2CB8ED* + ID_OUI_FROM_DATABASE=SonicWall + +OUI:2CBABA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:2CBE08* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:2CBE97* + ID_OUI_FROM_DATABASE=Ingenieurbuero Bickele und Buehler GmbH + +OUI:2CC260* + ID_OUI_FROM_DATABASE=Oracle Corporation + +OUI:2CC407* + ID_OUI_FROM_DATABASE=machineQ + +OUI:2CC546* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:2CC548* + ID_OUI_FROM_DATABASE=IAdea Corporation + +OUI:2CC5D3* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:2CCA0C* + ID_OUI_FROM_DATABASE=WITHUS PLANET + +OUI:2CCC15* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:2CCC44* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:2CCCE6* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:2CCD27* + ID_OUI_FROM_DATABASE=Precor Inc + +OUI:2CCD43* + ID_OUI_FROM_DATABASE=Summit Technology Group + +OUI:2CCD69* + ID_OUI_FROM_DATABASE=Aqavi.com + +OUI:2CCF58* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:2CD02D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2CD05A* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:2CD1410* + ID_OUI_FROM_DATABASE=iCIRROUND Inc + +OUI:2CD1411* + ID_OUI_FROM_DATABASE=Ezee Systems Limited + +OUI:2CD1412* + ID_OUI_FROM_DATABASE=IntelliLUM + +OUI:2CD1413* + ID_OUI_FROM_DATABASE=AOptix Technologies, Inc + +OUI:2CD1414* + ID_OUI_FROM_DATABASE=Shanghai RW ELE&TEC CO.,LTD + +OUI:2CD1415* + ID_OUI_FROM_DATABASE=ZENIC INC. + +OUI:2CD1416* + ID_OUI_FROM_DATABASE=Bowei Technology Company Limited + +OUI:2CD1417* + ID_OUI_FROM_DATABASE=XiaMen 35.com Technology Co,.Ltd. + +OUI:2CD1418* + ID_OUI_FROM_DATABASE=Minno LLC + +OUI:2CD1419* + ID_OUI_FROM_DATABASE=Beijing Hexing Chuangxiang Technology Co., Ltd. + +OUI:2CD141A* + ID_OUI_FROM_DATABASE=Fiberroad Technology Co., Ltd. + +OUI:2CD141B* + ID_OUI_FROM_DATABASE=Resus Industries + +OUI:2CD141C* + ID_OUI_FROM_DATABASE=PIN SHANG LED Co., LTD. + +OUI:2CD141D* + ID_OUI_FROM_DATABASE=Private + +OUI:2CD141E* + ID_OUI_FROM_DATABASE=CITA SMART SOLUTIONS LTD + +OUI:2CD141F* + ID_OUI_FROM_DATABASE=Private + +OUI:2CD1DA* + ID_OUI_FROM_DATABASE=Sanjole, Inc. + +OUI:2CD2E3* + ID_OUI_FROM_DATABASE=Guangzhou Aoshi Electronic Co.,Ltd + +OUI:2CD2E7* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:2CD444* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:2CD974* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:2CDCAD* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:2CDCD7* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:2CDD0C* + ID_OUI_FROM_DATABASE=Discovergy GmbH + +OUI:2CDD95* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:2CDDA3* + ID_OUI_FROM_DATABASE=Point Grey Research Inc. + +OUI:2CE2A8* + ID_OUI_FROM_DATABASE=DeviceDesign + +OUI:2CE310* + ID_OUI_FROM_DATABASE=Stratacache + +OUI:2CE412* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:2CE6CC* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:2CE871* + ID_OUI_FROM_DATABASE=Alert Metalguard ApS + +OUI:2CEA7F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:2CEDEB* + ID_OUI_FROM_DATABASE=Alpheus Digital Company Limited + +OUI:2CEE26* + ID_OUI_FROM_DATABASE=Petroleum Geo-Services + +OUI:2CF05D* + ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD. + +OUI:2CF0A2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:2CF0EE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:2CF203* + ID_OUI_FROM_DATABASE=EMKO ELEKTRONIK SAN VE TIC AS + +OUI:2CF432* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:2CF4C5* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:2CF7F1* + ID_OUI_FROM_DATABASE=Seeed Technology Inc. + +OUI:2CF89B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:2CFAA2* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise + +OUI:2CFCE4* + ID_OUI_FROM_DATABASE=CTEK Sweden AB + +OUI:2CFD37* + ID_OUI_FROM_DATABASE=Blue Calypso, Inc. + +OUI:2CFDA1* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:2CFDAB* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:2CFF65* + ID_OUI_FROM_DATABASE=Oki Electric Industry Co., Ltd. + +OUI:2CFFEE* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:30053F* + ID_OUI_FROM_DATABASE=JTI Co.,Ltd. + +OUI:30055C* + ID_OUI_FROM_DATABASE=Brother industries, LTD. + +OUI:30074D* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:3009F90* + ID_OUI_FROM_DATABASE=Hurray Cloud Technology Co., Ltd. + +OUI:3009F91* + ID_OUI_FROM_DATABASE=Shenzhen Sunvell Electronics Co., Ltd. + +OUI:3009F92* + ID_OUI_FROM_DATABASE=Beijing Netswift Technology Co.,Ltd. + +OUI:3009F93* + ID_OUI_FROM_DATABASE=OOO Microlink-Svyaz + +OUI:3009F94* + ID_OUI_FROM_DATABASE=Punkt Tronics AG + +OUI:3009F95* + ID_OUI_FROM_DATABASE=VELSITEC-CLIBASE + +OUI:3009F96* + ID_OUI_FROM_DATABASE=Beijing Mydreamplus Information Technology Co., Ltd. + +OUI:3009F97* + ID_OUI_FROM_DATABASE=Maytronics Ltd. + +OUI:3009F98* + ID_OUI_FROM_DATABASE=essence security + +OUI:3009F99* + ID_OUI_FROM_DATABASE=Bonraybio + +OUI:3009F9A* + ID_OUI_FROM_DATABASE=Shenzhen Tencent Computer System Co., Ltd. + +OUI:3009F9B* + ID_OUI_FROM_DATABASE=Sichuan Nebula Networks Co.,LTD. + +OUI:3009F9C* + ID_OUI_FROM_DATABASE=Honeywell + +OUI:3009F9D* + ID_OUI_FROM_DATABASE=Technology for Humankind + +OUI:3009F9E* + ID_OUI_FROM_DATABASE=ZhongLi HengFeng (Shenzhen) Technology co.,Ltd. + +OUI:300A600* + ID_OUI_FROM_DATABASE=KAZUtechnica Co.,Ltd. + +OUI:300A601* + ID_OUI_FROM_DATABASE=Beijing Ruiteng Zhongtian TECH Ltd.,Co + +OUI:300A602* + ID_OUI_FROM_DATABASE=Advanced Electronic Designs, Inc. + +OUI:300A603* + ID_OUI_FROM_DATABASE=Private + +OUI:300A604* + ID_OUI_FROM_DATABASE=AVIC JONHON OPTRONIC TECHNOLOGY CO., LTD. + +OUI:300A605* + ID_OUI_FROM_DATABASE=A9 + +OUI:300A606* + ID_OUI_FROM_DATABASE=Realtime biometrics India pvt ltd + +OUI:300A607* + ID_OUI_FROM_DATABASE=Newtons4th Ltd + +OUI:300A608* + ID_OUI_FROM_DATABASE=Bronkhorst High-Tech BV + +OUI:300A609* + ID_OUI_FROM_DATABASE=WINTEK System Co., Ltd + +OUI:300A60A* + ID_OUI_FROM_DATABASE=Ampetronic Ltd + +OUI:300A60B* + ID_OUI_FROM_DATABASE=Giax GmbH + +OUI:300A60C* + ID_OUI_FROM_DATABASE=Thermo Process Instruments, LP + +OUI:300A60D* + ID_OUI_FROM_DATABASE=Sixth Energy Technologies Private Limited + +OUI:300A60E* + ID_OUI_FROM_DATABASE=Imageo s.r.o. + +OUI:300AC5* + ID_OUI_FROM_DATABASE=Ruio telecommunication technologies Co., Limited + +OUI:300B9C* + ID_OUI_FROM_DATABASE=Delta Mobile Systems, Inc. + +OUI:300C23* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:300D2A* + ID_OUI_FROM_DATABASE=Zhejiang Wellcom Technology Co.,Ltd. + +OUI:300D43* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:300D9E* + ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD + +OUI:300ED5* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:300EE3* + ID_OUI_FROM_DATABASE=Aquantia Corporation + +OUI:3010B3* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:3010E4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:301389* + ID_OUI_FROM_DATABASE=Siemens AG, Automations & Drives, + +OUI:30142D* + ID_OUI_FROM_DATABASE=Piciorgros GmbH + +OUI:30144A* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:301518* + ID_OUI_FROM_DATABASE=Ubiquitous Communication Co. ltd. + +OUI:30168D* + ID_OUI_FROM_DATABASE=ProLon + +OUI:3017C8* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:3018CF* + ID_OUI_FROM_DATABASE=DEOS control systems GmbH + +OUI:301966* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:301A28* + ID_OUI_FROM_DATABASE=Mako Networks Ltd + +OUI:301B97* + ID_OUI_FROM_DATABASE=Lierda Science & Technology Group Co.,Ltd + +OUI:301F9A0* + ID_OUI_FROM_DATABASE=ILSAN ELECTRONICS + +OUI:301F9A1* + ID_OUI_FROM_DATABASE=Dewesoft d.o.o. + +OUI:301F9A2* + ID_OUI_FROM_DATABASE=CHISON Medical Technologies Co., Ltd. + +OUI:301F9A3* + ID_OUI_FROM_DATABASE=MICOMSOFT CO.,LTD. + +OUI:301F9A4* + ID_OUI_FROM_DATABASE=NCM Supplies, Inc. + +OUI:301F9A5* + ID_OUI_FROM_DATABASE=Beijing Surestar Technology Co. Ltd, + +OUI:301F9A6* + ID_OUI_FROM_DATABASE=YiSheng technology co.,LTD + +OUI:301F9A7* + ID_OUI_FROM_DATABASE=Triax A/S + +OUI:301F9A8* + ID_OUI_FROM_DATABASE=FINE TRIUMPH TECHNOLOGY CORP.,LTD. + +OUI:301F9A9* + ID_OUI_FROM_DATABASE=Private + +OUI:301F9AA* + ID_OUI_FROM_DATABASE=HUNAN CHANGSHA HENGJIAN TECHNOLDGY DEVELPMENT CO.,LTD. + +OUI:301F9AB* + ID_OUI_FROM_DATABASE=Smart Component Technologies LTD + +OUI:301F9AC* + ID_OUI_FROM_DATABASE=Origami Group Limited + +OUI:301F9AD* + ID_OUI_FROM_DATABASE=OLIMEX Ltd + +OUI:301F9AE* + ID_OUI_FROM_DATABASE=Shenzhen Fengliyuan Energy Conservating Technology Co. Ltd + +OUI:30215B* + ID_OUI_FROM_DATABASE=Shenzhen Ostar Display Electronic Co.,Ltd + +OUI:302303* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:302432* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:302478* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:3027CF* + ID_OUI_FROM_DATABASE=Private + +OUI:302952* + ID_OUI_FROM_DATABASE=Hillstone Networks Inc + +OUI:3029BE* + ID_OUI_FROM_DATABASE=Shanghai MRDcom Co.,Ltd + +OUI:302DE8* + ID_OUI_FROM_DATABASE=JDA, LLC (JDA Systems) + +OUI:30317D* + ID_OUI_FROM_DATABASE=Hosiden Corporation + +OUI:303294* + ID_OUI_FROM_DATABASE=W-IE-NE-R Plein & Baus GmbH + +OUI:3032D4* + ID_OUI_FROM_DATABASE=Hanilstm Co., Ltd. + +OUI:303335* + ID_OUI_FROM_DATABASE=Boosty + +OUI:3034D2* + ID_OUI_FROM_DATABASE=Availink, Inc. + +OUI:3035AD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3037A6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:303855* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:303926* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:303955* + ID_OUI_FROM_DATABASE=Shenzhen Jinhengjia Electronic Co., Ltd. + +OUI:3039F2* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:303A64* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:303ABA* + ID_OUI_FROM_DATABASE=Guangzhou BaoLun Electronics Co., Ltd + +OUI:303D08* + ID_OUI_FROM_DATABASE=GLINTT TES S.A. + +OUI:303EAD* + ID_OUI_FROM_DATABASE=Sonavox Canada Inc + +OUI:304174* + ID_OUI_FROM_DATABASE=ALTEC LANSING LLC + +OUI:304225* + ID_OUI_FROM_DATABASE=BURG-WÄCHTER KG + +OUI:3042A1* + ID_OUI_FROM_DATABASE=ilumisys Inc. DBA Toggled + +OUI:304449* + ID_OUI_FROM_DATABASE=PLATH GmbH + +OUI:304487* + ID_OUI_FROM_DATABASE=Hefei Radio Communication Technology Co., Ltd + +OUI:3044A1* + ID_OUI_FROM_DATABASE=Shanghai Nanchao Information Technology + +OUI:304511* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:304596* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:30469A* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:30493B* + ID_OUI_FROM_DATABASE=Nanjing Z-Com Wireless Co.,Ltd + +OUI:304A26* + ID_OUI_FROM_DATABASE=Shenzhen Trolink Technology CO, LTD + +OUI:304B07* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:304C7E* + ID_OUI_FROM_DATABASE=Panasonic Electric Works Automation Controls Techno Co.,Ltd. + +OUI:304EC3* + ID_OUI_FROM_DATABASE=Tianjin Techua Technology Co., Ltd. + +OUI:304F75* + ID_OUI_FROM_DATABASE=DASAN Network Solutions + +OUI:305075* + ID_OUI_FROM_DATABASE=GN Audio A/S + +OUI:3050FD* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:3051F8* + ID_OUI_FROM_DATABASE=BYK-Gardner GmbH + +OUI:30525A* + ID_OUI_FROM_DATABASE=NST Co., LTD + +OUI:3052CB* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:3055ED* + ID_OUI_FROM_DATABASE=Trex Network LLC + +OUI:305714* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3057AC* + ID_OUI_FROM_DATABASE=IRLAB LTD. + +OUI:305890* + ID_OUI_FROM_DATABASE=Frontier Silicon Ltd + +OUI:30595B* + ID_OUI_FROM_DATABASE=streamnow AG + +OUI:3059B7* + ID_OUI_FROM_DATABASE=Microsoft + +OUI:305A3A* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:305D38* + ID_OUI_FROM_DATABASE=Beissbarth + +OUI:305DA6* + ID_OUI_FROM_DATABASE=ADVALY SYSTEM Inc. + +OUI:306023* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:306112* + ID_OUI_FROM_DATABASE=PAV GmbH + +OUI:306118* + ID_OUI_FROM_DATABASE=Paradom Inc. + +OUI:30636B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3065EC* + ID_OUI_FROM_DATABASE=Wistron (ChongQing) + +OUI:30688C* + ID_OUI_FROM_DATABASE=Reach Technology Inc. + +OUI:30694B* + ID_OUI_FROM_DATABASE=RIM + +OUI:306A85* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:306CBE* + ID_OUI_FROM_DATABASE=Skymotion Technology (HK) Limited + +OUI:306E5C* + ID_OUI_FROM_DATABASE=Validus Technologies + +OUI:306F07* + ID_OUI_FROM_DATABASE=Nations Technologies Inc. + +OUI:3071B2* + ID_OUI_FROM_DATABASE=Hangzhou Prevail Optoelectronic Equipment Co.,LTD. + +OUI:307350* + ID_OUI_FROM_DATABASE=Inpeco SA + +OUI:307496* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:307512* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:30766F* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:3077CB* + ID_OUI_FROM_DATABASE=Maike Industry(Shenzhen)CO.,LTD + +OUI:30785C* + ID_OUI_FROM_DATABASE=Partow Tamas Novin (Parman) + +OUI:30786B* + ID_OUI_FROM_DATABASE=TIANJIN Golden Pentagon Electronics Co., Ltd. + +OUI:3078C2* + ID_OUI_FROM_DATABASE=Innowireless / QUCELL Networks + +OUI:307BAC* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:307C30* + ID_OUI_FROM_DATABASE=RIM + +OUI:307C5E* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:307CB2* + ID_OUI_FROM_DATABASE=ANOV FRANCE + +OUI:307ECB* + ID_OUI_FROM_DATABASE=SFR + +OUI:30809B* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:308454* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:3085A9* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:30862D* + ID_OUI_FROM_DATABASE=Arista Network, Inc. + +OUI:308730* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3087D9* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:308841* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:308944* + ID_OUI_FROM_DATABASE=DEVA Broadcast Ltd. + +OUI:308976* + ID_OUI_FROM_DATABASE=DALIAN LAMBA TECHNOLOGY CO.,LTD + +OUI:308999* + ID_OUI_FROM_DATABASE=Guangdong East Power Co., + +OUI:3089D3* + ID_OUI_FROM_DATABASE=HONGKONG UCLOUDLINK NETWORK TECHNOLOGY LIMITED + +OUI:308BB2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:308CFB* + ID_OUI_FROM_DATABASE=Dropcam + +OUI:308D99* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:309048* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3090AB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:309176* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:30918F* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:3092F6* + ID_OUI_FROM_DATABASE=SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD + +OUI:3093BC* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:309435* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:3095E3* + ID_OUI_FROM_DATABASE=SHANGHAI SIMCOM LIMITED + +OUI:3096FB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:309935* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:309BAD* + ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + +OUI:309C23* + ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD. + +OUI:309FFB* + ID_OUI_FROM_DATABASE=Ardomus Networks Corporation + +OUI:30A1FA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:30A220* + ID_OUI_FROM_DATABASE=ARG Telecom + +OUI:30A243* + ID_OUI_FROM_DATABASE=Shenzhen Prifox Innovation Technology Co., Ltd. + +OUI:30A2C2* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:30A889* + ID_OUI_FROM_DATABASE=DECIMATOR DESIGN + +OUI:30A8DB* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:30A9DE* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:30AABD* + ID_OUI_FROM_DATABASE=Shanghai Reallytek Information Technology Co.,Ltd + +OUI:30AAE4* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:30AB6A* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:30AE7B* + ID_OUI_FROM_DATABASE=Deqing Dusun Electron CO., LTD + +OUI:30AEA4* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:30AEF6* + ID_OUI_FROM_DATABASE=Radio Mobile Access + +OUI:30B164* + ID_OUI_FROM_DATABASE=Power Electronics International Inc. + +OUI:30B216* + ID_OUI_FROM_DATABASE=ABB Power Grids Germany AG – Grid Automation + +OUI:30B3A2* + ID_OUI_FROM_DATABASE=Shenzhen Heguang Measurement & Control Technology Co.,Ltd + +OUI:30B49E* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:30B4B8* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:30B5C2* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:30B5F1* + ID_OUI_FROM_DATABASE=Aitexin Technology Co., Ltd + +OUI:30B62D* + ID_OUI_FROM_DATABASE=Mojo Networks, Inc. + +OUI:30B64F* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:30B7D4* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:30B9B0* + ID_OUI_FROM_DATABASE=Intracom Asia Co., Ltd + +OUI:30C01B* + ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + +OUI:30C3D9* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:30C507* + ID_OUI_FROM_DATABASE=ECI Telecom Ltd. + +OUI:30C750* + ID_OUI_FROM_DATABASE=MIC Technology Group + +OUI:30C7AE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:30C82A* + ID_OUI_FROM_DATABASE=WI-BIZ srl + +OUI:30CBF8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:30CDA7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:30D16B* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:30D17E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:30D32D* + ID_OUI_FROM_DATABASE=devolo AG + +OUI:30D357* + ID_OUI_FROM_DATABASE=Logosol, Inc. + +OUI:30D386* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:30D46A* + ID_OUI_FROM_DATABASE=Autosales Incorporated + +OUI:30D587* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:30D659* + ID_OUI_FROM_DATABASE=Merging Technologies SA + +OUI:30D6C9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:30D9D9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:30DE86* + ID_OUI_FROM_DATABASE=Cedac Software S.r.l. + +OUI:30DF8D* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:30E090* + ID_OUI_FROM_DATABASE=Linctronix Ltd, + +OUI:30E171* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:30E37A* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:30E3D6* + ID_OUI_FROM_DATABASE=Spotify USA Inc. + +OUI:30E48E* + ID_OUI_FROM_DATABASE=Vodafone UK + +OUI:30E4DB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:30E98E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:30EA26* + ID_OUI_FROM_DATABASE=Sycada BV + +OUI:30EB1F* + ID_OUI_FROM_DATABASE=Skylab M&C Technology Co.,Ltd + +OUI:30EB25* + ID_OUI_FROM_DATABASE=INTEK DIGITAL + +OUI:30EB5A* + ID_OUI_FROM_DATABASE=LANDIS + GYR + +OUI:30EFD1* + ID_OUI_FROM_DATABASE=Alstom Strongwish (Shenzhen) Co., Ltd. + +OUI:30F31D* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:30F335* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:30F33A* + ID_OUI_FROM_DATABASE=+plugg srl + +OUI:30F42F* + ID_OUI_FROM_DATABASE=ESP + +OUI:30F6B9* + ID_OUI_FROM_DATABASE=Ecocentric Energy + +OUI:30F70D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:30F772* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:30F77F* + ID_OUI_FROM_DATABASE=S Mobile Devices Limited + +OUI:30F7C5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:30F7D7* + ID_OUI_FROM_DATABASE=Thread Technology Co., Ltd + +OUI:30F9ED* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:30FAB7* + ID_OUI_FROM_DATABASE=Tunai Creative + +OUI:30FB94* + ID_OUI_FROM_DATABASE=Shanghai Fangzhiwei Information Technology CO.,Ltd. + +OUI:30FBB8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:30FC68* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:30FD11* + ID_OUI_FROM_DATABASE=MACROTECH (USA) INC. + +OUI:30FD38* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:30FD65* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:30FE31* + ID_OUI_FROM_DATABASE=Nokia + +OUI:30FFF6* + ID_OUI_FROM_DATABASE=HangZhou KuoHeng Technology Co.,ltd + +OUI:34008A0* + ID_OUI_FROM_DATABASE=Angee Technologies Ltd. + +OUI:34008A1* + ID_OUI_FROM_DATABASE=ZQAM Communications + +OUI:34008A2* + ID_OUI_FROM_DATABASE=RPE Monitor + +OUI:34008A3* + ID_OUI_FROM_DATABASE=Globex 99 LTD + +OUI:34008A4* + ID_OUI_FROM_DATABASE=Fotonic i Norden AB + +OUI:34008A5* + ID_OUI_FROM_DATABASE=Federal Aviation Administration + +OUI:34008A6* + ID_OUI_FROM_DATABASE=Sithon Technologies SAS + +OUI:34008A7* + ID_OUI_FROM_DATABASE=uberGARD Pte. Ltd. + +OUI:34008A8* + ID_OUI_FROM_DATABASE=Shenzhen Andakai Technologies Co., Ltd. + +OUI:34008A9* + ID_OUI_FROM_DATABASE=Keruyun Technoligies(Beijing) Corporation Limited + +OUI:34008AA* + ID_OUI_FROM_DATABASE=Hibertek International Limited + +OUI:34008AB* + ID_OUI_FROM_DATABASE=Project Engineering srl + +OUI:34008AC* + ID_OUI_FROM_DATABASE=Shenzhen Eternal Idea Tech Co.,Ltd + +OUI:34008AD* + ID_OUI_FROM_DATABASE=ChengDu HuiZhong Cloud Information Technology Co., Ltd. + +OUI:34008AE* + ID_OUI_FROM_DATABASE=SHENZHEN WXL ELECTRONICS CO., LTD. + +OUI:3400A3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:340286* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:34029B* + ID_OUI_FROM_DATABASE=Plexonics Technologies LImited + +OUI:3403DE* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:34049E0* + ID_OUI_FROM_DATABASE=GoChip Inc. + +OUI:34049E1* + ID_OUI_FROM_DATABASE=Connected IO + +OUI:34049E2* + ID_OUI_FROM_DATABASE=EFD Induction + +OUI:34049E3* + ID_OUI_FROM_DATABASE=Nanjing Mythware Information Technology Co., Ltd. + +OUI:34049E4* + ID_OUI_FROM_DATABASE=Harbin Yantuo Science and Technology Development Co., Ltd + +OUI:34049E5* + ID_OUI_FROM_DATABASE=Seeiner Technology Co.,LTD + +OUI:34049E6* + ID_OUI_FROM_DATABASE=Life Interface Co., Ltd. + +OUI:34049E7* + ID_OUI_FROM_DATABASE=Pebble Technology + +OUI:34049E8* + ID_OUI_FROM_DATABASE=Eclipse Information Technologies + +OUI:34049E9* + ID_OUI_FROM_DATABASE=Private + +OUI:34049EA* + ID_OUI_FROM_DATABASE=i3 International Inc. + +OUI:34049EB* + ID_OUI_FROM_DATABASE=Eginity, Inc. + +OUI:34049EC* + ID_OUI_FROM_DATABASE=Private + +OUI:34049ED* + ID_OUI_FROM_DATABASE=uikismart + +OUI:34049EE* + ID_OUI_FROM_DATABASE=ND SatCom GmbH + +OUI:34074F* + ID_OUI_FROM_DATABASE=AccelStor, Inc. + +OUI:3407FB* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:340804* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:3408BC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:340A22* + ID_OUI_FROM_DATABASE=TOP-ACCESS ELECTRONICS CO LTD + +OUI:340A98* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:340AFF* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:340B40* + ID_OUI_FROM_DATABASE=MIOS ELETTRONICA SRL + +OUI:340CED* + ID_OUI_FROM_DATABASE=Moduel AB + +OUI:340F66* + ID_OUI_FROM_DATABASE=MicroArx Corporation + +OUI:341290* + ID_OUI_FROM_DATABASE=Treeview Co.,Ltd. + +OUI:341298* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3412F9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3413A8* + ID_OUI_FROM_DATABASE=Mediplan Limited + +OUI:3413E8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:34145F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3414B5* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:341513* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:34159E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3417EB* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:341A35* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:341A4C* + ID_OUI_FROM_DATABASE=SHENZHEN WEIBU ELECTRONICS CO.,LTD. + +OUI:341B22* + ID_OUI_FROM_DATABASE=Grandbeing Technology Co., Ltd + +OUI:341E6B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:341FE4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:342003* + ID_OUI_FROM_DATABASE=Shenzhen Feitengyun Technology Co.,LTD + +OUI:342109* + ID_OUI_FROM_DATABASE=Jensen Scandinavia AS + +OUI:342387* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:3423BA* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:34255D* + ID_OUI_FROM_DATABASE=Shenzhen Loadcom Technology Co.,Ltd + +OUI:342606* + ID_OUI_FROM_DATABASE=CarePredict, Inc. + +OUI:342792* + ID_OUI_FROM_DATABASE=FREEBOX SAS + +OUI:3428F0* + ID_OUI_FROM_DATABASE=ATN International Limited + +OUI:342912* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:34298F0* + ID_OUI_FROM_DATABASE=BlackEdge Capital + +OUI:34298F1* + ID_OUI_FROM_DATABASE=Chengdu Meross Technology Co., Ltd. + +OUI:34298F2* + ID_OUI_FROM_DATABASE=Shenzhen Advance River System Technology Co., Ltd + +OUI:34298F3* + ID_OUI_FROM_DATABASE=Beijing Vorx Telecommunications Co., Ltd. + +OUI:34298F4* + ID_OUI_FROM_DATABASE=ISRA Vision AG + +OUI:34298F5* + ID_OUI_FROM_DATABASE=Highlite International B.V. + +OUI:34298F6* + ID_OUI_FROM_DATABASE=Bellman & Symfon + +OUI:34298F7* + ID_OUI_FROM_DATABASE=Dongguan Kingtron Electronics Tech Co., Ltd + +OUI:34298F8* + ID_OUI_FROM_DATABASE=Nanjing Sandemarine Electric Co.,Ltd + +OUI:34298F9* + ID_OUI_FROM_DATABASE=Wiesheu GmbH + +OUI:34298FA* + ID_OUI_FROM_DATABASE=Virtual Trunk Pte Ltd + +OUI:34298FB* + ID_OUI_FROM_DATABASE=Schnick-Schnack-Systems GmbH + +OUI:34298FC* + ID_OUI_FROM_DATABASE=Albert Handtmann Maschinenfabrik GmbH&Co.KG + +OUI:34298FD* + ID_OUI_FROM_DATABASE=Keystone Electronic Solutions + +OUI:34298FE* + ID_OUI_FROM_DATABASE=ARC Technology Co., Ltd + +OUI:3429EA* + ID_OUI_FROM_DATABASE=MCD ELECTRONICS SP. Z O.O. + +OUI:342AF1* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:342CC4* + ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. + +OUI:342D0D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:342EB6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:342F6E* + ID_OUI_FROM_DATABASE=Anywire corporation + +OUI:342FBD* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:343111* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3431C4* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:3432E6* + ID_OUI_FROM_DATABASE=Panasonic Industrial Devices Europe GmbH + +OUI:34363B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:343759* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:343794* + ID_OUI_FROM_DATABASE=Hamee Corp. + +OUI:3438AF* + ID_OUI_FROM_DATABASE=Inlab Software GmbH + +OUI:3438B7* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:343D98* + ID_OUI_FROM_DATABASE=JinQianMao Technology Co.,Ltd. + +OUI:343DC4* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:3440B5* + ID_OUI_FROM_DATABASE=IBM + +OUI:34415D* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:3441A8* + ID_OUI_FROM_DATABASE=ER-Telecom + +OUI:344262* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:34466F* + ID_OUI_FROM_DATABASE=HiTEM Engineering + +OUI:3446EC* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:3448ED* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:34495B* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:344B3D* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:344B50* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:344CA4* + ID_OUI_FROM_DATABASE=amazipoint technology Ltd. + +OUI:344CC8* + ID_OUI_FROM_DATABASE=Echodyne Corp + +OUI:344DEA* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:344DF7* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:344F3F* + ID_OUI_FROM_DATABASE=IO-Power Technology Co., Ltd. + +OUI:344F5C* + ID_OUI_FROM_DATABASE=R&M AG + +OUI:344F69* + ID_OUI_FROM_DATABASE=EKINOPS SAS + +OUI:345180* + ID_OUI_FROM_DATABASE=TCL King Electrical Appliances (Huizhou) Co., Ltd + +OUI:3451AA* + ID_OUI_FROM_DATABASE=JID GLOBAL + +OUI:3451C9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:34543C* + ID_OUI_FROM_DATABASE=TAKAOKA TOKO CO.,LTD. + +OUI:3456FE* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:345760* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:345A06* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:345ABA* + ID_OUI_FROM_DATABASE=tcloud intelligence + +OUI:345B11* + ID_OUI_FROM_DATABASE=EVI HEAT AB + +OUI:345BBB* + ID_OUI_FROM_DATABASE=GD Midea Air-Conditioning Equipment Co.,Ltd. + +OUI:345C40* + ID_OUI_FROM_DATABASE=Cargt Holdings LLC + +OUI:345D10* + ID_OUI_FROM_DATABASE=Wytek + +OUI:346178* + ID_OUI_FROM_DATABASE=The Boeing Company + +OUI:346288* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3463D4* + ID_OUI_FROM_DATABASE=BIONIX SUPPLYCHAIN TECHNOLOGIES SLU + +OUI:3464A9* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:3466EA* + ID_OUI_FROM_DATABASE=VERTU INTERNATIONAL CORPORATION LIMITED + +OUI:34684A* + ID_OUI_FROM_DATABASE=Teraworks Co., Ltd. + +OUI:346895* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:346987* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:346AC2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:346B46* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:346B5B* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:346BD3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:346C0F* + ID_OUI_FROM_DATABASE=Pramod Telecom Pvt. Ltd + +OUI:346E8A* + ID_OUI_FROM_DATABASE=Ecosense + +OUI:346E9D* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:346F90* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:346F92* + ID_OUI_FROM_DATABASE=White Rodgers Division + +OUI:346FED* + ID_OUI_FROM_DATABASE=Enovation Controls + +OUI:347146* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:347563* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:3475C7* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:3476C5* + ID_OUI_FROM_DATABASE=I-O DATA DEVICE,INC. + +OUI:347839* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:347877* + ID_OUI_FROM_DATABASE=O-Net Communications (Shenzhen) Limited + +OUI:3478D7* + ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co.,Ltd. + +OUI:347916* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:347A60* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:347C25* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:347E00* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:347E39* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:347E5C* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:347ECA* + ID_OUI_FROM_DATABASE=NEXTWILL + +OUI:34800D* + ID_OUI_FROM_DATABASE=Cavium Inc + +OUI:3480B3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:348137* + ID_OUI_FROM_DATABASE=UNICARD SA + +OUI:3481C4* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:3481F4* + ID_OUI_FROM_DATABASE=SST Taiwan Ltd. + +OUI:3482DE* + ID_OUI_FROM_DATABASE=Kiio Inc + +OUI:348302* + ID_OUI_FROM_DATABASE=iFORCOM Co., Ltd + +OUI:348446* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:348584* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:34862A* + ID_OUI_FROM_DATABASE=Heinz Lackmann GmbH & Co KG + +OUI:34873D* + ID_OUI_FROM_DATABASE=Quectel Wireless Solution Co.,Ltd. + +OUI:34885D* + ID_OUI_FROM_DATABASE=Logitech Far East + +OUI:348A7B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:348AAE* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:348B75* + ID_OUI_FROM_DATABASE=LAVA INTERNATIONAL(H.K) LIMITED + +OUI:348F27* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:349342* + ID_OUI_FROM_DATABASE=TTE Corporation + +OUI:3495DB* + ID_OUI_FROM_DATABASE=Logitec Corporation + +OUI:349672* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:3497F6* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:3497FB* + ID_OUI_FROM_DATABASE=ADVANCED RF TECHNOLOGIES INC + +OUI:34996F* + ID_OUI_FROM_DATABASE=VPI Engineering + +OUI:349971* + ID_OUI_FROM_DATABASE=Quanta Storage Inc. + +OUI:3499D7* + ID_OUI_FROM_DATABASE=Universal Flow Monitors, Inc. + +OUI:349A0D* + ID_OUI_FROM_DATABASE=ZBD Displays Ltd + +OUI:349B5B* + ID_OUI_FROM_DATABASE=Maquet GmbH + +OUI:349D90* + ID_OUI_FROM_DATABASE=Heinzmann GmbH & CO. KG + +OUI:349E34* + ID_OUI_FROM_DATABASE=Evervictory Electronic Co.Ltd + +OUI:349F7B* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:34A183* + ID_OUI_FROM_DATABASE=AWare, Inc + +OUI:34A2A2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:34A395* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:34A3BF* + ID_OUI_FROM_DATABASE=Terewave. Inc. + +OUI:34A55D* + ID_OUI_FROM_DATABASE=TECHNOSOFT INTERNATIONAL SRL + +OUI:34A5E1* + ID_OUI_FROM_DATABASE=Sensorist ApS + +OUI:34A68C* + ID_OUI_FROM_DATABASE=Shine Profit Development Limited + +OUI:34A709* + ID_OUI_FROM_DATABASE=Trevil srl + +OUI:34A7BA* + ID_OUI_FROM_DATABASE=Fischer International Systems Corporation + +OUI:34A843* + ID_OUI_FROM_DATABASE=KYOCERA Display Corporation + +OUI:34A84E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:34A8EB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:34AA8B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:34AA99* + ID_OUI_FROM_DATABASE=Nokia + +OUI:34AAEE* + ID_OUI_FROM_DATABASE=Mikrovisatos Servisas UAB + +OUI:34AB37* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:34ADE4* + ID_OUI_FROM_DATABASE=Shanghai Chint Power Systems Co., Ltd. + +OUI:34AF2C* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:34B1F7* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:34B20A* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:34B354* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:34B571* + ID_OUI_FROM_DATABASE=PLDS + +OUI:34B5A3* + ID_OUI_FROM_DATABASE=CIG SHANGHAI CO LTD + +OUI:34B7FD* + ID_OUI_FROM_DATABASE=Guangzhou Younghead Electronic Technology Co.,Ltd + +OUI:34BA38* + ID_OUI_FROM_DATABASE=PAL MOHAN ELECTRONICS PVT LTD + +OUI:34BA51* + ID_OUI_FROM_DATABASE=Se-Kure Controls, Inc. + +OUI:34BA75* + ID_OUI_FROM_DATABASE=Everest Networks, Inc + +OUI:34BA9A* + ID_OUI_FROM_DATABASE=Asiatelco Technologies Co. + +OUI:34BB1F* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:34BB26* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:34BCA6* + ID_OUI_FROM_DATABASE=Beijing Ding Qing Technology, Ltd. + +OUI:34BDC8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:34BDF9* + ID_OUI_FROM_DATABASE=Shanghai WDK Industrial Co.,Ltd. + +OUI:34BDFA* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:34BE00* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:34BF90* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:34C059* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:34C0F9* + ID_OUI_FROM_DATABASE=Rockwell Automation + +OUI:34C3AC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:34C3D2* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:34C5D0* + ID_OUI_FROM_DATABASE=Hagleitner Hygiene International GmbH + +OUI:34C69A* + ID_OUI_FROM_DATABASE=Enecsys Ltd + +OUI:34C731* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:34C803* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:34C99D* + ID_OUI_FROM_DATABASE=EIDOLON COMMUNICATIONS TECHNOLOGY CO. LTD. + +OUI:34C9F0* + ID_OUI_FROM_DATABASE=LM Technologies Ltd + +OUI:34CB1A* + ID_OUI_FROM_DATABASE=Procter & Gamble Company + +OUI:34CC28* + ID_OUI_FROM_DATABASE=Nexpring Co. LTD., + +OUI:34CD6D* + ID_OUI_FROM_DATABASE=CommSky Technologies + +OUI:34CDBE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:34CE00* + ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD + +OUI:34CE94* + ID_OUI_FROM_DATABASE=Parsec (Pty) Ltd + +OUI:34CFF6* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:34D09B* + ID_OUI_FROM_DATABASE=MobilMAX Technology Inc. + +OUI:34D0B80* + ID_OUI_FROM_DATABASE=Captec Ltd + +OUI:34D0B81* + ID_OUI_FROM_DATABASE=Shenzhen Bao Lai Wei Intelligent Technology Co., L + +OUI:34D0B82* + ID_OUI_FROM_DATABASE=Blustream Pty Ltd + +OUI:34D0B83* + ID_OUI_FROM_DATABASE=Tascent, Inc. + +OUI:34D0B84* + ID_OUI_FROM_DATABASE=EQPlay Intelligent Technology(Kunshan) Co,Ltd. + +OUI:34D0B85* + ID_OUI_FROM_DATABASE=eesy-innovation GmbH + +OUI:34D0B86* + ID_OUI_FROM_DATABASE=NumberFour AG + +OUI:34D0B87* + ID_OUI_FROM_DATABASE=Shenzhen Rikomagic Tech Corp.,Ltd + +OUI:34D0B88* + ID_OUI_FROM_DATABASE=Vtrek Group International Ltd. + +OUI:34D0B89* + ID_OUI_FROM_DATABASE=Skytech Creations Limited + +OUI:34D0B8A* + ID_OUI_FROM_DATABASE=Meatest sro + +OUI:34D0B8B* + ID_OUI_FROM_DATABASE=OROSOUND SAS + +OUI:34D0B8C* + ID_OUI_FROM_DATABASE=Glory Mark Electronic Ltd. Taiwan Branch (B.V.I.) + +OUI:34D0B8D* + ID_OUI_FROM_DATABASE=NTX Embedded + +OUI:34D0B8E* + ID_OUI_FROM_DATABASE=Kongqiguanjia (Beijing)Technology co.,ltd + +OUI:34D262* + ID_OUI_FROM_DATABASE=SZ DJI TECHNOLOGY CO.,LTD + +OUI:34D270* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:34D2C4* + ID_OUI_FROM_DATABASE=RENA GmbH Print Systeme + +OUI:34D712* + ID_OUI_FROM_DATABASE=Smartisan Digital Co., Ltd + +OUI:34D772* + ID_OUI_FROM_DATABASE=Xiamen Yudian Automation Technology Co., Ltd + +OUI:34D7B4* + ID_OUI_FROM_DATABASE=Tributary Systems, Inc. + +OUI:34D954* + ID_OUI_FROM_DATABASE=WiBotic Inc. + +OUI:34DAB7* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:34DAC1* + ID_OUI_FROM_DATABASE=SAE Technologies Development(Dongguan) Co., Ltd. + +OUI:34DB9C* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:34DBFD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:34DD7E* + ID_OUI_FROM_DATABASE=Umeox Innovations Co.,Ltd + +OUI:34DE1A* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:34DE34* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:34DF2A* + ID_OUI_FROM_DATABASE=Fujikon Industrial Co.,Limited + +OUI:34E0CF* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:34E0D7* + ID_OUI_FROM_DATABASE=DONGGUAN QISHENG ELECTRONICS INDUSTRIAL CO., LTD + +OUI:34E12D* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:34E1D10* + ID_OUI_FROM_DATABASE=Tianjin Sublue Ocean Science & Technology Co., Ltd + +OUI:34E1D11* + ID_OUI_FROM_DATABASE=SAMA NextGen PTE Limited + +OUI:34E1D12* + ID_OUI_FROM_DATABASE=Teton Camera LLC + +OUI:34E1D13* + ID_OUI_FROM_DATABASE=Rinco Ultrasonics AG + +OUI:34E1D14* + ID_OUI_FROM_DATABASE=ASA Innovation & Technology Ltd. + +OUI:34E1D15* + ID_OUI_FROM_DATABASE=Doki Technologies Limited + +OUI:34E1D16* + ID_OUI_FROM_DATABASE=Ningbo Hua Gao Mdt Info Tech Ltd + +OUI:34E1D17* + ID_OUI_FROM_DATABASE=Genius Pros + +OUI:34E1D18* + ID_OUI_FROM_DATABASE=Hubitat Inc. + +OUI:34E1D19* + ID_OUI_FROM_DATABASE=Apart Audio NV + +OUI:34E1D1A* + ID_OUI_FROM_DATABASE=OrCam Technologies + +OUI:34E1D1B* + ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC + +OUI:34E1D1C* + ID_OUI_FROM_DATABASE=CREW by True Rowing, Inc. + +OUI:34E1D1D* + ID_OUI_FROM_DATABASE=HI-TECH.ORG + +OUI:34E1D1E* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:34E2FD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:34E380* + ID_OUI_FROM_DATABASE=Genexis B.V. + +OUI:34E3DA* + ID_OUI_FROM_DATABASE=Hoval Aktiengesellschaft + +OUI:34E42A* + ID_OUI_FROM_DATABASE=Automatic Bar Controls Inc. + +OUI:34E5EC* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:34E6AD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:34E6D7* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:34E70B* + ID_OUI_FROM_DATABASE=HAN Networks Co., Ltd + +OUI:34E71C* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:34E894* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:34E911* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:34EA34* + ID_OUI_FROM_DATABASE=HangZhou Gubei Electronics Technology Co.,Ltd + +OUI:34ED0B* + ID_OUI_FROM_DATABASE=Shanghai XZ-COM.CO.,Ltd. + +OUI:34ED1B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:34EF44* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:34EF8B* + ID_OUI_FROM_DATABASE=NTT Communications Corporation + +OUI:34F0CA* + ID_OUI_FROM_DATABASE=Shenzhen Linghangyuan Digital Technology Co.,Ltd. + +OUI:34F150* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:34F39A* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:34F39B* + ID_OUI_FROM_DATABASE=WizLAN Ltd. + +OUI:34F62D* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:34F64B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:34F6D2* + ID_OUI_FROM_DATABASE=Panasonic Taiwan Co.,Ltd. + +OUI:34F8E7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:34F968* + ID_OUI_FROM_DATABASE=ATEK Products, LLC + +OUI:34FA40* + ID_OUI_FROM_DATABASE=Guangzhou Robustel Technologies Co., Limited + +OUI:34FA9F* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:34FC6F* + ID_OUI_FROM_DATABASE=ALCEA + +OUI:34FCB9* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:34FCEF* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:380025* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:380118* + ID_OUI_FROM_DATABASE=ULVAC,Inc. + +OUI:380146* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD + +OUI:380195* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:380197* + ID_OUI_FROM_DATABASE=TSST Global,Inc + +OUI:38019F* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:380546* + ID_OUI_FROM_DATABASE=Foctek Photonics, Inc. + +OUI:3805AC* + ID_OUI_FROM_DATABASE=Piller Group GmbH + +OUI:3806B4* + ID_OUI_FROM_DATABASE=A.D.C. GmbH + +OUI:3807D4* + ID_OUI_FROM_DATABASE=Zeppelin Systems GmbH + +OUI:3808FD* + ID_OUI_FROM_DATABASE=Silca Spa + +OUI:3809A4* + ID_OUI_FROM_DATABASE=Firefly Integrations + +OUI:380A0A* + ID_OUI_FROM_DATABASE=Sky-City Communication and Electronics Limited Company + +OUI:380A94* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:380AAB* + ID_OUI_FROM_DATABASE=Formlabs + +OUI:380B3C* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:380B40* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:380DD4* + ID_OUI_FROM_DATABASE=Primax Electronics Ltd. + +OUI:380E4D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:380E7B* + ID_OUI_FROM_DATABASE=V.P.S. Thai Co., Ltd + +OUI:380F4A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:380FE4* + ID_OUI_FROM_DATABASE=Dedicated Network Partners Oy + +OUI:3810D5* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:38144E* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:3816D1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:381730* + ID_OUI_FROM_DATABASE=Ulrich Lippert GmbH & Co KG + +OUI:381766* + ID_OUI_FROM_DATABASE=PROMZAKAZ LTD. + +OUI:3817C3* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:3817E1* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:38184C* + ID_OUI_FROM_DATABASE=Sony Home Entertainment&Sound Products Inc + +OUI:38192F* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:381A52* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:381C1A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:381C23* + ID_OUI_FROM_DATABASE=Hilan Technology CO.,LTD + +OUI:381C4A* + ID_OUI_FROM_DATABASE=SIMCom Wireless Solutions Co.,Ltd. + +OUI:381D14* + ID_OUI_FROM_DATABASE=Skydio Inc. + +OUI:381DD9* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:382056* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3820A8* + ID_OUI_FROM_DATABASE=ColorTokens, Inc. + +OUI:382187* + ID_OUI_FROM_DATABASE=Midea Group Co., Ltd. + +OUI:3821C7* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:38229D* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:3822D6* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:3822E2* + ID_OUI_FROM_DATABASE=HP Inc. + +OUI:38256B* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:38262B* + ID_OUI_FROM_DATABASE=UTran Technology + +OUI:3826CD* + ID_OUI_FROM_DATABASE=ANDTEK + +OUI:3828EA* + ID_OUI_FROM_DATABASE=Fujian Netcom Technology Co., LTD + +OUI:38295A* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:3829DD* + ID_OUI_FROM_DATABASE=ONvocal Inc + +OUI:382A19* + ID_OUI_FROM_DATABASE=Technica Engineering GmbH + +OUI:382B78* + ID_OUI_FROM_DATABASE=ECO PLUGS ENTERPRISE CO., LTD + +OUI:382C4A* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:382DD1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:382DE8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3830F9* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:3831AC* + ID_OUI_FROM_DATABASE=WEG + +OUI:3835FB* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:38378B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:383A210* + ID_OUI_FROM_DATABASE=R3C Information(Shenzhen) Co.,Ltd. + +OUI:383A211* + ID_OUI_FROM_DATABASE=HOBART GmbH + +OUI:383A212* + ID_OUI_FROM_DATABASE=Shenzhen HS Fiber Communication Equipment CO., LTD + +OUI:383A213* + ID_OUI_FROM_DATABASE=Shanghai Greatwall Safety System Co.,Ltd + +OUI:383A214* + ID_OUI_FROM_DATABASE=Dongguan Innovation Technology Co Ltd + +OUI:383A215* + ID_OUI_FROM_DATABASE=OOO NPP Uraltechnologiya + +OUI:383A216* + ID_OUI_FROM_DATABASE=Shenzhen Smart-core Technology co., Ltd. + +OUI:383A217* + ID_OUI_FROM_DATABASE=Chengdu Krosslan Technology Inc. + +OUI:383A218* + ID_OUI_FROM_DATABASE=Alicat Scientific + +OUI:383A219* + ID_OUI_FROM_DATABASE=Skylark Wireless LLC + +OUI:383A21A* + ID_OUI_FROM_DATABASE=Foresight Sports + +OUI:383A21B* + ID_OUI_FROM_DATABASE=Pactron + +OUI:383A21C* + ID_OUI_FROM_DATABASE=Mission Embedded GmbH + +OUI:383A21D* + ID_OUI_FROM_DATABASE=Colooc AB + +OUI:383A21E* + ID_OUI_FROM_DATABASE=SDNware technology co.,LTD + +OUI:383B26* + ID_OUI_FROM_DATABASE=Jiangsu Qinheng Co., Ltd. + +OUI:383BC8* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:383C9C* + ID_OUI_FROM_DATABASE=Fujian Newland Payment Technology Co.,Ltd. + +OUI:383F10* + ID_OUI_FROM_DATABASE=DBL Technology Ltd. + +OUI:383FB3* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:384233* + ID_OUI_FROM_DATABASE=Wildeboer Bauteile GmbH + +OUI:3842A6* + ID_OUI_FROM_DATABASE=Ingenieurbuero Stahlkopf + +OUI:384369* + ID_OUI_FROM_DATABASE=Patrol Products Consortium LLC + +OUI:38437D* + ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. + +OUI:3843E5* + ID_OUI_FROM_DATABASE=Grotech Inc + +OUI:38454C* + ID_OUI_FROM_DATABASE=Light Labs, Inc. + +OUI:38458C* + ID_OUI_FROM_DATABASE=MyCloud Technology corporation + +OUI:384608* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:3847BC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:38484C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:384B5B* + ID_OUI_FROM_DATABASE=ZTRON TECHNOLOGY LIMITED + +OUI:384B76* + ID_OUI_FROM_DATABASE=AIRTAME ApS + +OUI:384C4F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:384C90* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:384F49* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:384FF0* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:38521A* + ID_OUI_FROM_DATABASE=Nokia + +OUI:38539C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:385610* + ID_OUI_FROM_DATABASE=CANDY HOUSE, Inc. + +OUI:3856B5* + ID_OUI_FROM_DATABASE=Peerbridge Health Inc + +OUI:38580C* + ID_OUI_FROM_DATABASE=Panaccess Systems GmbH + +OUI:3859F8* + ID_OUI_FROM_DATABASE=MindMade Sp. z o.o. + +OUI:3859F9* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:385AA8* + ID_OUI_FROM_DATABASE=Beijing Zhongdun Security Technology Development Co. + +OUI:385F66* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:385FC3* + ID_OUI_FROM_DATABASE=Yu Jeong System, Co.Ltd + +OUI:386077* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:3863BB* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:3863F6* + ID_OUI_FROM_DATABASE=3NOD MULTIMEDIA(SHENZHEN)CO.,LTD + +OUI:386645* + ID_OUI_FROM_DATABASE=OOSIC Technology CO.,Ltd + +OUI:3866F0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:386793* + ID_OUI_FROM_DATABASE=Asia Optical Co., Inc. + +OUI:3868A4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,LTD + +OUI:3868DD* + ID_OUI_FROM_DATABASE=INVENTEC CORPORATION + +OUI:386A77* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:386B1C* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:386BBB* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:386C9B* + ID_OUI_FROM_DATABASE=Ivy Biomedical + +OUI:386E21* + ID_OUI_FROM_DATABASE=Wasion Group Ltd. + +OUI:386E88* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:386EA2* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:38700C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:3871DE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3872C0* + ID_OUI_FROM_DATABASE=Comtrend Corporation + +OUI:3873EA0* + ID_OUI_FROM_DATABASE=L-3 Communications Mobile-Vision, Inc. + +OUI:3873EA1* + ID_OUI_FROM_DATABASE=KingWay Information Co.,Ltd. + +OUI:3873EA2* + ID_OUI_FROM_DATABASE=Eyesight(Shanghai)Communication Technology Co.,Ltd. + +OUI:3873EA3* + ID_OUI_FROM_DATABASE=Proch plastic Co., Ltd. + +OUI:3873EA4* + ID_OUI_FROM_DATABASE=Light Blue Optics Ltd. + +OUI:3873EA5* + ID_OUI_FROM_DATABASE=ISTCONTROL + +OUI:3873EA6* + ID_OUI_FROM_DATABASE=Live Sentinel + +OUI:3873EA7* + ID_OUI_FROM_DATABASE=PingGPS Inc + +OUI:3873EA8* + ID_OUI_FROM_DATABASE=Rock Electronic Co., Ltd. + +OUI:3873EA9* + ID_OUI_FROM_DATABASE=Lightform, Inc. + +OUI:3873EAA* + ID_OUI_FROM_DATABASE=SHENZHEN CSE TECHNOLOGY CO., LTD + +OUI:3873EAB* + ID_OUI_FROM_DATABASE=Shanghai ZoomSmart Technology Co., Ltd. + +OUI:3873EAC* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:3873EAD* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:3873EAE* + ID_OUI_FROM_DATABASE=Shenzhen Jixian Technology Co., Ltd. + +OUI:3876CA* + ID_OUI_FROM_DATABASE=Shenzhen Smart Intelligent Technology Co.Ltd + +OUI:3876D1* + ID_OUI_FROM_DATABASE=Euronda SpA + +OUI:387862* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:387B47* + ID_OUI_FROM_DATABASE=AKELA, Inc. + +OUI:3880DF* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:3881D7* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:388345* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:38839A* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:388479* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:388602* + ID_OUI_FROM_DATABASE=Flexoptix GmbH + +OUI:38892C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3889DC* + ID_OUI_FROM_DATABASE=Opticon Sensors Europe B.V. + +OUI:388AB7* + ID_OUI_FROM_DATABASE=ITC Networks + +OUI:388B59* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:388C50* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:388E7A* + ID_OUI_FROM_DATABASE=AUTOIT + +OUI:388EE7* + ID_OUI_FROM_DATABASE=Fanhattan LLC + +OUI:3890A5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3891D5* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:3891FB* + ID_OUI_FROM_DATABASE=Xenox Holding BV + +OUI:389496* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3894E0* + ID_OUI_FROM_DATABASE=Syrotech Networks. Ltd. + +OUI:3894ED* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:389592* + ID_OUI_FROM_DATABASE=Beijing Tendyron Corporation + +OUI:3897D6* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:3898D8* + ID_OUI_FROM_DATABASE=MERITECH CO.,LTD + +OUI:389AF6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:389D92* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:389F5A* + ID_OUI_FROM_DATABASE=C-Kur TV Inc. + +OUI:389F83* + ID_OUI_FROM_DATABASE=OTN Systems N.V. + +OUI:38A28C* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:38A4ED* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:38A53C* + ID_OUI_FROM_DATABASE=COMECER Netherlands + +OUI:38A5B6* + ID_OUI_FROM_DATABASE=SHENZHEN MEGMEET ELECTRICAL CO.,LTD + +OUI:38A6CE* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:38A851* + ID_OUI_FROM_DATABASE=Moog, Ing + +OUI:38A86B* + ID_OUI_FROM_DATABASE=Orga BV + +OUI:38A95F* + ID_OUI_FROM_DATABASE=Actifio Inc + +OUI:38AA3C* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:38AC3D* + ID_OUI_FROM_DATABASE=Nephos Inc + +OUI:38AD8E* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:38ADBE* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:38AF29* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:38AFD0* + ID_OUI_FROM_DATABASE=Private + +OUI:38AFD7* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:38B12D* + ID_OUI_FROM_DATABASE=Sonotronic Nagel GmbH + +OUI:38B19E0* + ID_OUI_FROM_DATABASE=Triple Jump Medical + +OUI:38B19E1* + ID_OUI_FROM_DATABASE=Freedompro Srl + +OUI:38B19E2* + ID_OUI_FROM_DATABASE=HDANYWHERE + +OUI:38B19E3* + ID_OUI_FROM_DATABASE=AVO DEVELOPMENT LTD + +OUI:38B19E4* + ID_OUI_FROM_DATABASE=Basalte BVBA + +OUI:38B19E5* + ID_OUI_FROM_DATABASE=Star Electronics GmbH & CoKG + +OUI:38B19E6* + ID_OUI_FROM_DATABASE=Thrust Networks + +OUI:38B19E7* + ID_OUI_FROM_DATABASE=Beijing Memblaze Technology Co Ltd + +OUI:38B19E8* + ID_OUI_FROM_DATABASE=BoCo Inc. + +OUI:38B19E9* + ID_OUI_FROM_DATABASE=Doepke Schaltgeräte GmbH + +OUI:38B19EA* + ID_OUI_FROM_DATABASE=Aeroespacial Guosheng Technology Co., Ltd + +OUI:38B19EB* + ID_OUI_FROM_DATABASE=System Q Ltd + +OUI:38B19EC* + ID_OUI_FROM_DATABASE=Gesellschaft industrieller Technologien + +OUI:38B19ED* + ID_OUI_FROM_DATABASE=Dallas Delta Corporation + +OUI:38B19EE* + ID_OUI_FROM_DATABASE=ShenZhen ShuaiXian Electronic Equipment Co.Ltd + +OUI:38B1DB* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:38B4D3* + ID_OUI_FROM_DATABASE=BSH Hausgeraete GmbH + +OUI:38B54D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:38B5BD* + ID_OUI_FROM_DATABASE=E.G.O. Elektro-Ger + +OUI:38B725* + ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation + +OUI:38B74D* + ID_OUI_FROM_DATABASE=Fijowave Limited + +OUI:38B8EB0* + ID_OUI_FROM_DATABASE=Bumjin C&L Co., Ltd. + +OUI:38B8EB1* + ID_OUI_FROM_DATABASE=1.A Connect GmbH + +OUI:38B8EB2* + ID_OUI_FROM_DATABASE=barox Kommunikation GmbH + +OUI:38B8EB3* + ID_OUI_FROM_DATABASE=Aina Wireless Inc + +OUI:38B8EB4* + ID_OUI_FROM_DATABASE=UMLOGICS + +OUI:38B8EB5* + ID_OUI_FROM_DATABASE=Dojo-Labs Ltd + +OUI:38B8EB6* + ID_OUI_FROM_DATABASE=MATRIXSTREAM TECHNOLOGIES, INC. + +OUI:38B8EB7* + ID_OUI_FROM_DATABASE=Private + +OUI:38B8EB8* + ID_OUI_FROM_DATABASE=CeeNex Inc + +OUI:38B8EB9* + ID_OUI_FROM_DATABASE=NHS Sistemas de Energia + +OUI:38B8EBA* + ID_OUI_FROM_DATABASE=SECAD SA + +OUI:38B8EBB* + ID_OUI_FROM_DATABASE=ExaScaler Inc. + +OUI:38B8EBC* + ID_OUI_FROM_DATABASE=Ajax Systems Inc + +OUI:38B8EBD* + ID_OUI_FROM_DATABASE=Yellowbrick Data, Inc. + +OUI:38B8EBE* + ID_OUI_FROM_DATABASE=Wyres SAS + +OUI:38BAB0* + ID_OUI_FROM_DATABASE=Broadcom + +OUI:38BAF8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:38BB23* + ID_OUI_FROM_DATABASE=OzVision America LLC + +OUI:38BB3C* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:38BC01* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:38BC1A* + ID_OUI_FROM_DATABASE=MEIZU Technology Co., Ltd. + +OUI:38BF2F* + ID_OUI_FROM_DATABASE=Espec Corp. + +OUI:38BF33* + ID_OUI_FROM_DATABASE=NEC CASIO Mobile Communications + +OUI:38C096* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:38C2BA* + ID_OUI_FROM_DATABASE=CCTV NEOTECH + +OUI:38C4E8* + ID_OUI_FROM_DATABASE=NSS Sp. z o.o. + +OUI:38C70A* + ID_OUI_FROM_DATABASE=WiFiSong + +OUI:38C7BA* + ID_OUI_FROM_DATABASE=CS Services Co.,Ltd. + +OUI:38C85C* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:38C986* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:38C9A9* + ID_OUI_FROM_DATABASE=SMART High Reliability Solutions, Inc. + +OUI:38CA97* + ID_OUI_FROM_DATABASE=Contour Design LLC + +OUI:38CADA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:38CD07* + ID_OUI_FROM_DATABASE=Beijing FaceCam Technology Co., Ltd. + +OUI:38D135* + ID_OUI_FROM_DATABASE=EasyIO Corporation Sdn. Bhd. + +OUI:38D269* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:38D2CA* + ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd. + +OUI:38D40B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:38D547* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:38D620* + ID_OUI_FROM_DATABASE=Limidea Concept Pte. Ltd. + +OUI:38D7CA* + ID_OUI_FROM_DATABASE=7HUGS LABS + +OUI:38D82F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:38D9A5* + ID_OUI_FROM_DATABASE=Mikotek Information Inc. + +OUI:38DBBB* + ID_OUI_FROM_DATABASE=Sunbow Telecom Co., Ltd. + +OUI:38DE60* + ID_OUI_FROM_DATABASE=Mohlenhoff GmbH + +OUI:38DEAD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:38E08E* + ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation + +OUI:38E1AA* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:38E26E* + ID_OUI_FROM_DATABASE=ShenZhen Sweet Rain Electronics Co.,Ltd. + +OUI:38E2DD* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:38E3C5* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:38E595* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:38E60A* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:38E7D8* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:38E8DF* + ID_OUI_FROM_DATABASE=b gmbh medien + datenbanken + +OUI:38E8EE* + ID_OUI_FROM_DATABASE=Nanjing Youkuo Electric Technology Co., Ltd + +OUI:38E98C* + ID_OUI_FROM_DATABASE=Reco S.p.A. + +OUI:38EAA7* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:38EB47* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:38EC0D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:38EC11* + ID_OUI_FROM_DATABASE=Novatek Microelectronics Corp. + +OUI:38ECE4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:38ED18* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:38EE9D* + ID_OUI_FROM_DATABASE=Anedo Ltd. + +OUI:38EFE3* + ID_OUI_FROM_DATABASE=INGENICO TERMINALS SAS + +OUI:38F098* + ID_OUI_FROM_DATABASE=Vapor Stone Rail Systems + +OUI:38F0C8* + ID_OUI_FROM_DATABASE=Livestream + +OUI:38F135* + ID_OUI_FROM_DATABASE=SensorTec-Canada + +OUI:38F23E* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:38F32E* + ID_OUI_FROM_DATABASE=Skullcandy + +OUI:38F33F* + ID_OUI_FROM_DATABASE=TATSUNO CORPORATION + +OUI:38F554* + ID_OUI_FROM_DATABASE=HISENSE ELECTRIC CO.,LTD + +OUI:38F557* + ID_OUI_FROM_DATABASE=JOLATA, INC. + +OUI:38F597* + ID_OUI_FROM_DATABASE=home2net GmbH + +OUI:38F601* + ID_OUI_FROM_DATABASE=Solid State Storage Technology Corporation + +OUI:38F708* + ID_OUI_FROM_DATABASE=National Resource Management, Inc. + +OUI:38F73D* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:38F7B2* + ID_OUI_FROM_DATABASE=SEOJUN ELECTRIC + +OUI:38F85E* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:38F889* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:38F8B7* + ID_OUI_FROM_DATABASE=V2COM PARTICIPACOES S.A. + +OUI:38F8CA* + ID_OUI_FROM_DATABASE=OWIN Inc. + +OUI:38F9D3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:38FACA* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:38FB14* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:38FDFE0* + ID_OUI_FROM_DATABASE=Edge I&D Co., Ltd. + +OUI:38FDFE1* + ID_OUI_FROM_DATABASE=WAYTONE (BEIIJNG) COMMUNICATIONS CO.,LTD + +OUI:38FDFE2* + ID_OUI_FROM_DATABASE=Smart Solution Technology, Inc + +OUI:38FDFE3* + ID_OUI_FROM_DATABASE=Siemens AG, PG IE R&D + +OUI:38FDFE4* + ID_OUI_FROM_DATABASE=New Telecom Solutions LLC + +OUI:38FDFE5* + ID_OUI_FROM_DATABASE=CaptiveAire Systems Inc. + +OUI:38FDFE6* + ID_OUI_FROM_DATABASE=Inspero Inc + +OUI:38FDFE7* + ID_OUI_FROM_DATABASE=Rademacher Geraete-Elektronik GmbH + +OUI:38FDFE8* + ID_OUI_FROM_DATABASE=Indra Navia AS + +OUI:38FDFE9* + ID_OUI_FROM_DATABASE=OOO Group of Industrial Technologies + +OUI:38FDFEA* + ID_OUI_FROM_DATABASE=Management Service Corporation + +OUI:38FDFEB* + ID_OUI_FROM_DATABASE=Swedish Adrenaline AB + +OUI:38FDFEC* + ID_OUI_FROM_DATABASE=New Garden Co., Ltd. + +OUI:38FDFED* + ID_OUI_FROM_DATABASE=FUBA Automotive Electronics GmbH + +OUI:38FDFEE* + ID_OUI_FROM_DATABASE=iSmart electronic technology co.,LTD + +OUI:38FEC5* + ID_OUI_FROM_DATABASE=Ellips B.V. + +OUI:38FF36* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:3C01EF* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:3C02B1* + ID_OUI_FROM_DATABASE=Creation Technologies LP + +OUI:3C0461* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:3C04BF* + ID_OUI_FROM_DATABASE=PRAVIS SYSTEMS Co.Ltd., + +OUI:3C0518* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3C05AB* + ID_OUI_FROM_DATABASE=Product Creation Studio + +OUI:3C0754* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3C0771* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:3C081E* + ID_OUI_FROM_DATABASE=Beijing Yupont Electric Power Technology Co.,Ltd + +OUI:3C08F6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3C096D* + ID_OUI_FROM_DATABASE=Powerhouse Dynamics + +OUI:3C0C48* + ID_OUI_FROM_DATABASE=Servergy, Inc. + +OUI:3C0C7D* + ID_OUI_FROM_DATABASE=Tiny Mesh AS + +OUI:3C0CDB* + ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD + +OUI:3C0E23* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3C0FC1* + ID_OUI_FROM_DATABASE=KBC Networks + +OUI:3C1040* + ID_OUI_FROM_DATABASE=daesung network + +OUI:3C106F* + ID_OUI_FROM_DATABASE=ALBAHITH TECHNOLOGIES + +OUI:3C10E6* + ID_OUI_FROM_DATABASE=PHAZR Inc. + +OUI:3C11B2* + ID_OUI_FROM_DATABASE=Fraunhofer FIT + +OUI:3C15C2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3C15EA* + ID_OUI_FROM_DATABASE=TESCOM CO., LTD. + +OUI:3C15FB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3C1710* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:3C189F* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:3C18A0* + ID_OUI_FROM_DATABASE=Luxshare Precision Industry Company Limited + +OUI:3C1915* + ID_OUI_FROM_DATABASE=GFI Chrono Time + +OUI:3C197D* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:3C1A0F* + ID_OUI_FROM_DATABASE=ClearSky Data + +OUI:3C1A57* + ID_OUI_FROM_DATABASE=Cardiopulmonary Corp + +OUI:3C1A79* + ID_OUI_FROM_DATABASE=Huayuan Technology CO.,LTD + +OUI:3C1CBE* + ID_OUI_FROM_DATABASE=JADAK LLC + +OUI:3C1E04* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:3C1E13* + ID_OUI_FROM_DATABASE=HANGZHOU SUNRISE TECHNOLOGY CO., LTD + +OUI:3C20F6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3C22FB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3C24F00* + ID_OUI_FROM_DATABASE=SHENZHEN PINSIDA TECHNOLOGY CO.,LTD. + +OUI:3C24F01* + ID_OUI_FROM_DATABASE=Abrites Ltd. + +OUI:3C24F02* + ID_OUI_FROM_DATABASE=Laipac Technology Inc. + +OUI:3C24F03* + ID_OUI_FROM_DATABASE=Wisycom + +OUI:3C24F04* + ID_OUI_FROM_DATABASE=Inter-Coastal Electronics + +OUI:3C24F05* + ID_OUI_FROM_DATABASE=CASKY eTech Co., Ltd. + +OUI:3C24F06* + ID_OUI_FROM_DATABASE=Inter Action Corporation + +OUI:3C24F07* + ID_OUI_FROM_DATABASE=Swissdotnet SA + +OUI:3C24F08* + ID_OUI_FROM_DATABASE=Sivat Technology Co.,Ltd. + +OUI:3C24F09* + ID_OUI_FROM_DATABASE=Siemens AG - Siemens Deutschland Mobility + +OUI:3C24F0A* + ID_OUI_FROM_DATABASE=Shenzhen Bestway Technology Co., Ltd + +OUI:3C24F0B* + ID_OUI_FROM_DATABASE=COMATIS + +OUI:3C24F0C* + ID_OUI_FROM_DATABASE=Authentico Technologies + +OUI:3C24F0D* + ID_OUI_FROM_DATABASE=Travis Holding B.V. + +OUI:3C24F0E* + ID_OUI_FROM_DATABASE=GETMOBIT LLC + +OUI:3C25D7* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:3C26D5* + ID_OUI_FROM_DATABASE=Sotera Wireless + +OUI:3C2763* + ID_OUI_FROM_DATABASE=SLE quality engineering GmbH & Co. KG + +OUI:3C286D* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:3C28A6* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise (China) + +OUI:3C2AF4* + ID_OUI_FROM_DATABASE=Brother Industries, LTD. + +OUI:3C2C30* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:3C2C94* + ID_OUI_FROM_DATABASE=杭州德澜科技有限公司(HangZhou Delan Technology Co.,Ltd) + +OUI:3C2C99* + ID_OUI_FROM_DATABASE=Edgecore Networks Corporation + +OUI:3C2DB7* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:3C2EF9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3C2EFF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3C2F3A* + ID_OUI_FROM_DATABASE=SFORZATO Corp. + +OUI:3C300C* + ID_OUI_FROM_DATABASE=Dewar Electronics Pty Ltd + +OUI:3C3178* + ID_OUI_FROM_DATABASE=Qolsys Inc. + +OUI:3C3300* + ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD + +OUI:3C3556* + ID_OUI_FROM_DATABASE=Cognitec Systems GmbH + +OUI:3C363D* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:3C36E4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:3C3786* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:3C3888* + ID_OUI_FROM_DATABASE=ConnectQuest, llc + +OUI:3C39C3* + ID_OUI_FROM_DATABASE=JW Electronics Co., Ltd. + +OUI:3C39E70* + ID_OUI_FROM_DATABASE=Hannstar Display Corp + +OUI:3C39E71* + ID_OUI_FROM_DATABASE=BEWATEC Kommunikationstechnik GmbH + +OUI:3C39E72* + ID_OUI_FROM_DATABASE=HomeWizard B.V. + +OUI:3C39E73* + ID_OUI_FROM_DATABASE=ELSA Japan Inc. + +OUI:3C39E74* + ID_OUI_FROM_DATABASE=University of British Columbia + +OUI:3C39E75* + ID_OUI_FROM_DATABASE=Attrackting AG + +OUI:3C39E76* + ID_OUI_FROM_DATABASE=RO.VE.R. Laboratories S.p.A + +OUI:3C39E77* + ID_OUI_FROM_DATABASE=Sensor to Image GmbH + +OUI:3C39E78* + ID_OUI_FROM_DATABASE=Martem AS + +OUI:3C39E79* + ID_OUI_FROM_DATABASE=Zone Controls AB + +OUI:3C39E7A* + ID_OUI_FROM_DATABASE=iiM AG + +OUI:3C39E7B* + ID_OUI_FROM_DATABASE=chipsguide technology Co.,LTD + +OUI:3C39E7C* + ID_OUI_FROM_DATABASE=VANSTONE ELECTRONIC (BEIJING)CO,. LTD. + +OUI:3C39E7E* + ID_OUI_FROM_DATABASE=MARPOSS SPA + +OUI:3C39E7F* + ID_OUI_FROM_DATABASE=Private + +OUI:3C3A73* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:3C3F51* + ID_OUI_FROM_DATABASE=2CRSI + +OUI:3C404F* + ID_OUI_FROM_DATABASE=GUANGDONG PISEN ELECTRONICS CO.,LTD + +OUI:3C410E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3C427E0* + ID_OUI_FROM_DATABASE=Grandway Technology (Shenzhen) Limited + +OUI:3C427E1* + ID_OUI_FROM_DATABASE=Dongguan Taide Industrial Co.,Ltd. + +OUI:3C427E2* + ID_OUI_FROM_DATABASE=Starloop Tech Co., Ltd. + +OUI:3C427E3* + ID_OUI_FROM_DATABASE=Shenzhen VETAS Communication Technology Co , Ltd. + +OUI:3C427E4* + ID_OUI_FROM_DATABASE=Teknoware Oy + +OUI:3C427E5* + ID_OUI_FROM_DATABASE=Geoplan Korea + +OUI:3C427E6* + ID_OUI_FROM_DATABASE=Edit Srl + +OUI:3C427E7* + ID_OUI_FROM_DATABASE=GJS Co., Ltd. + +OUI:3C427E8* + ID_OUI_FROM_DATABASE=UBTECH ROBOTICS CORP + +OUI:3C427E9* + ID_OUI_FROM_DATABASE=TAITEX CORPORATION + +OUI:3C427EA* + ID_OUI_FROM_DATABASE=snap40 Ltd + +OUI:3C427EB* + ID_OUI_FROM_DATABASE=Compal Electronics INC. + +OUI:3C427EC* + ID_OUI_FROM_DATABASE=Privacy Labs + +OUI:3C427ED* + ID_OUI_FROM_DATABASE=ROBOX SMART MOTION (WUHU) CO.,LTD + +OUI:3C427EE* + ID_OUI_FROM_DATABASE=Xiaoniu network technology (Shanghai) Co., Ltd. + +OUI:3C438E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:3C46D8* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:3C4711* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3C479B* + ID_OUI_FROM_DATABASE=Theissen Training Systems, Inc. + +OUI:3C4937* + ID_OUI_FROM_DATABASE=ASSMANN Electronic GmbH + +OUI:3C4A92* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:3C4C69* + ID_OUI_FROM_DATABASE=Infinity System S.L. + +OUI:3C4CD0* + ID_OUI_FROM_DATABASE=CERAGON NETWORKS + +OUI:3C4E47* + ID_OUI_FROM_DATABASE=Etronic A/S + +OUI:3C510E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3C5282* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:3C5731* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3C574F* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:3C576C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3C57BD* + ID_OUI_FROM_DATABASE=Kessler Crane Inc. + +OUI:3C57D5* + ID_OUI_FROM_DATABASE=FiveCo + +OUI:3C58C2* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:3C591E* + ID_OUI_FROM_DATABASE=TCL King Electrical Appliances (Huizhou) Co., Ltd + +OUI:3C5A37* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3C5AB4* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:3C5CC3* + ID_OUI_FROM_DATABASE=Shenzhen First Blue Chip Technology Ltd + +OUI:3C5CC4* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:3C5CF1* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:3C5EC3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3C5F01* + ID_OUI_FROM_DATABASE=Synerchip Co., Ltd. + +OUI:3C6104* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:3C6200* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3C6278* + ID_OUI_FROM_DATABASE=SHENZHEN JETNET TECHNOLOGY CO.,LTD. + +OUI:3C6716* + ID_OUI_FROM_DATABASE=Lily Robotics + +OUI:3C672C* + ID_OUI_FROM_DATABASE=Sciovid Inc. + +OUI:3C678C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3C6816* + ID_OUI_FROM_DATABASE=VXi Corporation + +OUI:3C6A2C0* + ID_OUI_FROM_DATABASE=Rio Lago Technologies LLC + +OUI:3C6A2C1* + ID_OUI_FROM_DATABASE=Olibra LLC + +OUI:3C6A2C2* + ID_OUI_FROM_DATABASE=Bosch Automotive Products (Suzhou) Co., Ltd. + +OUI:3C6A2C3* + ID_OUI_FROM_DATABASE=figur8, Inc. + +OUI:3C6A2C4* + ID_OUI_FROM_DATABASE=XI'AN YEP TELECOM TECHNOLOGY CO.,LTD + +OUI:3C6A2C5* + ID_OUI_FROM_DATABASE=Qingdao iGuan Technology Co., Ltd. + +OUI:3C6A2C6* + ID_OUI_FROM_DATABASE=La Barrière Automatique + +OUI:3C6A2C7* + ID_OUI_FROM_DATABASE=Homegear GmbH + +OUI:3C6A2C8* + ID_OUI_FROM_DATABASE=TP Radio + +OUI:3C6A2C9* + ID_OUI_FROM_DATABASE=WICKS Co., Ltd. + +OUI:3C6A2CA* + ID_OUI_FROM_DATABASE=Metro + +OUI:3C6A2CB* + ID_OUI_FROM_DATABASE=Phytium Technology Co., Ltd. + +OUI:3C6A2CC* + ID_OUI_FROM_DATABASE=Eltov System + +OUI:3C6A2CD* + ID_OUI_FROM_DATABASE=Xiamen Smarttek CO., Ltd. + +OUI:3C6A2CE* + ID_OUI_FROM_DATABASE=Beijing Donghua Hongtai Polytron Technologies Inc + +OUI:3C6A7D* + ID_OUI_FROM_DATABASE=Niigata Power Systems Co., Ltd. + +OUI:3C6A9D* + ID_OUI_FROM_DATABASE=Dexatek Technology LTD. + +OUI:3C6AA7* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:3C6E63* + ID_OUI_FROM_DATABASE=Mitron OY + +OUI:3C6F45* + ID_OUI_FROM_DATABASE=Fiberpro Inc. + +OUI:3C6FEA* + ID_OUI_FROM_DATABASE=Panasonic India Pvt. Ltd. + +OUI:3C6FF7* + ID_OUI_FROM_DATABASE=EnTek Systems, Inc. + +OUI:3C7059* + ID_OUI_FROM_DATABASE=MakerBot Industries + +OUI:3C71BF* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:3C7437* + ID_OUI_FROM_DATABASE=RIM + +OUI:3C754A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:3C77E6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:3C7843* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3C7873* + ID_OUI_FROM_DATABASE=Airsonics + +OUI:3C7A8A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:3C7D0A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3C7DB1* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:3C7F6F* + ID_OUI_FROM_DATABASE=Telechips, Inc. + +OUI:3C806B* + ID_OUI_FROM_DATABASE=Hunan Voc Acoustics Technology Co., Ltd. + +OUI:3C80AA* + ID_OUI_FROM_DATABASE=Ransnet Singapore Pte Ltd + +OUI:3C81D8* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:3C831E* + ID_OUI_FROM_DATABASE=CKD Corporation + +OUI:3C8375* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:3C83B5* + ID_OUI_FROM_DATABASE=Advance Vision Electronics Co. Ltd. + +OUI:3C86A8* + ID_OUI_FROM_DATABASE=Sangshin elecom .co,, LTD + +OUI:3C86D1* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:3C894D* + ID_OUI_FROM_DATABASE=Dr. Ing. h.c. F. Porsche AG + +OUI:3C8970* + ID_OUI_FROM_DATABASE=Neosfar + +OUI:3C8994* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:3C89A6* + ID_OUI_FROM_DATABASE=KAPELSE + +OUI:3C8AB0* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:3C8AE5* + ID_OUI_FROM_DATABASE=Tensun Information Technology(Hangzhou) Co.,LTD + +OUI:3C8BCD* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:3C8BFE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3C8C40* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:3C8C93* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:3C8CF8* + ID_OUI_FROM_DATABASE=TRENDnet, Inc. + +OUI:3C8D20* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:3C8F06* + ID_OUI_FROM_DATABASE=Shenzhen Libtor Technology Co.,Ltd + +OUI:3C9066* + ID_OUI_FROM_DATABASE=SmartRG, Inc. + +OUI:3C912B* + ID_OUI_FROM_DATABASE=Vexata Inc + +OUI:3C9157* + ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + +OUI:3C9174* + ID_OUI_FROM_DATABASE=ALONG COMMUNICATION TECHNOLOGY + +OUI:3C9180* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:3C92DC* + ID_OUI_FROM_DATABASE=Octopod Technology Co. Ltd. + +OUI:3C94D5* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:3C9509* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:3C970E* + ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd. + +OUI:3C977E* + ID_OUI_FROM_DATABASE=IPS Technology Limited + +OUI:3C9872* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:3C98BF* + ID_OUI_FROM_DATABASE=Quest Controls, Inc. + +OUI:3C99F7* + ID_OUI_FROM_DATABASE=Lansentechnology AB + +OUI:3C9A77* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:3C9BD6* + ID_OUI_FROM_DATABASE=Vizio, Inc + +OUI:3C9D56* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3C9F81* + ID_OUI_FROM_DATABASE=Shenzhen CATIC Bit Communications Technology Co.,Ltd + +OUI:3CA067* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:3CA10D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3CA308* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:3CA315* + ID_OUI_FROM_DATABASE=Bless Information & Communications Co., Ltd + +OUI:3CA31A* + ID_OUI_FROM_DATABASE=Oilfind International LLC + +OUI:3CA348* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:3CA581* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:3CA616* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:3CA72B* + ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD + +OUI:3CA82A* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:3CA9F4* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:3CAA3F* + ID_OUI_FROM_DATABASE=iKey, Ltd. + +OUI:3CAB8E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3CAE69* + ID_OUI_FROM_DATABASE=ESA Elektroschaltanlagen Grimma GmbH + +OUI:3CB15B* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:3CB17F* + ID_OUI_FROM_DATABASE=Wattwatchers Pty Ld + +OUI:3CB53D* + ID_OUI_FROM_DATABASE=HUNAN GOKE MICROELECTRONICS CO.,LTD + +OUI:3CB6B7* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:3CB72B* + ID_OUI_FROM_DATABASE=PLUMgrid Inc + +OUI:3CB74B* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:3CB792* + ID_OUI_FROM_DATABASE=Hitachi Maxell, Ltd., Optronics Division + +OUI:3CB87A* + ID_OUI_FROM_DATABASE=Private + +OUI:3CB9A6* + ID_OUI_FROM_DATABASE=Belden Deutschland GmbH + +OUI:3CBB73* + ID_OUI_FROM_DATABASE=Shenzhen Xinguodu Technology Co., Ltd. + +OUI:3CBBFD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3CBD3E* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd. + +OUI:3CBDD8* + ID_OUI_FROM_DATABASE=LG ELECTRONICS INC + +OUI:3CBEE1* + ID_OUI_FROM_DATABASE=NIKON CORPORATION + +OUI:3CBF60* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3CC079* + ID_OUI_FROM_DATABASE=Shenzhen One-Nine Intelligent Electronic Science and Technology Co., Ltd + +OUI:3CC0C6* + ID_OUI_FROM_DATABASE=d&b audiotechnik GmbH + +OUI:3CC12C* + ID_OUI_FROM_DATABASE=AES Corporation + +OUI:3CC1F6* + ID_OUI_FROM_DATABASE=Melange Systems Pvt. Ltd. + +OUI:3CC243* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:3CC2E1* + ID_OUI_FROM_DATABASE=XINHUA CONTROL ENGINEERING CO.,LTD + +OUI:3CC99E* + ID_OUI_FROM_DATABASE=Huiyang Technology Co., Ltd + +OUI:3CCA87* + ID_OUI_FROM_DATABASE=Iders Incorporated + +OUI:3CCB7C* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:3CCD36* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3CCD5A* + ID_OUI_FROM_DATABASE=Technische Alternative GmbH + +OUI:3CCD5D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3CCD93* + ID_OUI_FROM_DATABASE=LG ELECTRONICS INC + +OUI:3CCE15* + ID_OUI_FROM_DATABASE=Mercedes-Benz USA, LLC + +OUI:3CCE73* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3CCF5B* + ID_OUI_FROM_DATABASE=ICOMM HK LIMITED + +OUI:3CD0F8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3CD16E* + ID_OUI_FROM_DATABASE=Telepower Communication Co., Ltd + +OUI:3CD4D6* + ID_OUI_FROM_DATABASE=WirelessWERX, Inc + +OUI:3CD7DA* + ID_OUI_FROM_DATABASE=SK Mtek microelectronics(shenzhen)limited + +OUI:3CD92B* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:3CD9CE* + ID_OUI_FROM_DATABASE=Eclipse WiFi + +OUI:3CDA2A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:3CDA6D* + ID_OUI_FROM_DATABASE=Tiandy Technologies CO.,LTD + +OUI:3CDCBC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3CDD89* + ID_OUI_FROM_DATABASE=SOMO HOLDINGS & TECH. CO.,LTD. + +OUI:3CDF1E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:3CDFA9* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:3CDFBD* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3CE072* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:3CE1A1* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:3CE5A6* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:3CE5B4* + ID_OUI_FROM_DATABASE=KIDASEN INDUSTRIA E COMERCIO DE ANTENAS LTDA + +OUI:3CE624* + ID_OUI_FROM_DATABASE=LG Display + +OUI:3CE824* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3CEA4F* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:3CEAF9* + ID_OUI_FROM_DATABASE=JUBIXCOLTD + +OUI:3CEAFB* + ID_OUI_FROM_DATABASE=NSE AG + +OUI:3CECEF* + ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. + +OUI:3CEF8C* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:3CF011* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:3CF392* + ID_OUI_FROM_DATABASE=Virtualtek. Co. Ltd + +OUI:3CF4F9* + ID_OUI_FROM_DATABASE=Moda-InnoChips + +OUI:3CF52C* + ID_OUI_FROM_DATABASE=DSPECIALISTS GmbH + +OUI:3CF591* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:3CF5CC* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:3CF72A* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:3CF748* + ID_OUI_FROM_DATABASE=Shenzhen Linsn Technology Development Co.,Ltd + +OUI:3CF7A4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:3CF808* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3CF862* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:3CFA43* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:3CFAD30* + ID_OUI_FROM_DATABASE=Home Control AS + +OUI:3CFAD31* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:3CFAD32* + ID_OUI_FROM_DATABASE=Naruida Technology Ltd. + +OUI:3CFAD33* + ID_OUI_FROM_DATABASE=Harman Connected Services, Inc. + +OUI:3CFAD34* + ID_OUI_FROM_DATABASE=GRG Banking Technology Co.,Ltd + +OUI:3CFAD35* + ID_OUI_FROM_DATABASE=Gulf Security Technology Co., Ltd + +OUI:3CFAD36* + ID_OUI_FROM_DATABASE=Nox Medical + +OUI:3CFAD37* + ID_OUI_FROM_DATABASE=LIPS Corporation + +OUI:3CFAD38* + ID_OUI_FROM_DATABASE=Energous Corporation + +OUI:3CFAD39* + ID_OUI_FROM_DATABASE=Shenzhen Vplus Communication Intelligent Co., Ltd. + +OUI:3CFAD3A* + ID_OUI_FROM_DATABASE=UltiMachine + +OUI:3CFAD3B* + ID_OUI_FROM_DATABASE=Corelink Technology Co.,Ltd + +OUI:3CFAD3C* + ID_OUI_FROM_DATABASE=Shenzhen zhong ju Fiber optical Co.Ltd + +OUI:3CFAD3D* + ID_OUI_FROM_DATABASE=AMobile Solutions (Xiamen) CO. , LTD. + +OUI:3CFAD3E* + ID_OUI_FROM_DATABASE=Mirico + +OUI:3CFB5C* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:3CFB96* + ID_OUI_FROM_DATABASE=Emcraft Systems LLC + +OUI:3CFDFE* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:4000E0* + ID_OUI_FROM_DATABASE=Derek(Shaoguan)Limited + +OUI:400107* + ID_OUI_FROM_DATABASE=Arista Corp + +OUI:40017A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4001C6* + ID_OUI_FROM_DATABASE=3COM EUROPE LTD + +OUI:40040C* + ID_OUI_FROM_DATABASE=A&T + +OUI:4006A0* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:4007C0* + ID_OUI_FROM_DATABASE=Railtec Systems GmbH + +OUI:400D10* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:400E67* + ID_OUI_FROM_DATABASE=Tremol Ltd. + +OUI:400E85* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:4011750* + ID_OUI_FROM_DATABASE=Lexi Devices, Inc. + +OUI:4011751* + ID_OUI_FROM_DATABASE=Fujian Kuke3D Technology Co.,LTD + +OUI:4011752* + ID_OUI_FROM_DATABASE=Kanda Kogyo + +OUI:4011753* + ID_OUI_FROM_DATABASE=Beijing Hexinruitong Electric Power Technology Co., Ltd. + +OUI:4011754* + ID_OUI_FROM_DATABASE=Table Trac Inc + +OUI:4011755* + ID_OUI_FROM_DATABASE=MIRC ELECTRONICS LTD + +OUI:4011756* + ID_OUI_FROM_DATABASE=ShenZhen LanShuo Communication Equipment CO.,LTD. + +OUI:4011757* + ID_OUI_FROM_DATABASE=Guangzhou RALID Information System Co.Ltd + +OUI:4011758* + ID_OUI_FROM_DATABASE=Beijing Gemotech Intelligent Technology Co., Ltd. + +OUI:4011759* + ID_OUI_FROM_DATABASE=ADH Guardian USA + +OUI:401175A* + ID_OUI_FROM_DATABASE=BWT Tianjin Ltd. + +OUI:401175B* + ID_OUI_FROM_DATABASE=Chongqing IQIYI Intelligence Technology Co., Ltd. + +OUI:401175C* + ID_OUI_FROM_DATABASE=disguise Technologies Limited + +OUI:401175D* + ID_OUI_FROM_DATABASE=NanJing HuaStart Network Technology Co.,Ltd. + +OUI:401175E* + ID_OUI_FROM_DATABASE=NIBBLE + +OUI:4011DC* + ID_OUI_FROM_DATABASE=Sonance + +OUI:4012E4* + ID_OUI_FROM_DATABASE=Compass-EOS + +OUI:4013D9* + ID_OUI_FROM_DATABASE=Global ES + +OUI:401597* + ID_OUI_FROM_DATABASE=Protect America, Inc. + +OUI:40163B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:40167E* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:40169F* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:4016FA* + ID_OUI_FROM_DATABASE=EKM Metering + +OUI:4017E2* + ID_OUI_FROM_DATABASE=INTAI TECHNOLOGY CORP. + +OUI:4018B1* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:4018D7* + ID_OUI_FROM_DATABASE=Smartronix, Inc. + +OUI:401920* + ID_OUI_FROM_DATABASE=Movon Corporation + +OUI:401B5F* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:401D59* + ID_OUI_FROM_DATABASE=Biometric Associates, LP + +OUI:4022ED* + ID_OUI_FROM_DATABASE=Digital Projection Ltd + +OUI:402343* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:4025C2* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:402619* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:40270B* + ID_OUI_FROM_DATABASE=Mobileeco Co., Ltd + +OUI:402814* + ID_OUI_FROM_DATABASE=RFI Engineering + +OUI:402B50* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:402B69* + ID_OUI_FROM_DATABASE=Kumho Electric Inc. + +OUI:402BA1* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:402C760* + ID_OUI_FROM_DATABASE=Lista AG + +OUI:402C761* + ID_OUI_FROM_DATABASE=Shanghai Dahua Scale Factory + +OUI:402C762* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:402C764* + ID_OUI_FROM_DATABASE=Beijing Smarot Technology Co., Ltd. + +OUI:402C765* + ID_OUI_FROM_DATABASE=Baumer Bourdon-Haenni + +OUI:402C766* + ID_OUI_FROM_DATABASE=Guangzhou LANGO Electronics Technology Co., Ltd. + +OUI:402C767* + ID_OUI_FROM_DATABASE=Zhejiang Guoli Security Technology Co., Ltd. + +OUI:402C768* + ID_OUI_FROM_DATABASE=Suteng Innovation Technology Co., Ltd. + +OUI:402C769* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:402C76A* + ID_OUI_FROM_DATABASE=NowTechnologies Zrt + +OUI:402C76B* + ID_OUI_FROM_DATABASE=Beijing Kuaiyu Electronic Co., Ltd. + +OUI:402C76C* + ID_OUI_FROM_DATABASE=gridX GmbH + +OUI:402C76D* + ID_OUI_FROM_DATABASE=Guangzhou Qi'an Technology Co., Ltd. + +OUI:402C76E* + ID_OUI_FROM_DATABASE=LS Energy Solutions + +OUI:402CF4* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:402E28* + ID_OUI_FROM_DATABASE=MiXTelematics + +OUI:402E71* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:402F86* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:403004* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:403067* + ID_OUI_FROM_DATABASE=Conlog (Pty) Ltd + +OUI:40313C* + ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD + +OUI:40331A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:40336C* + ID_OUI_FROM_DATABASE=Godrej & Boyce Mfg. co. ltd + +OUI:4037AD* + ID_OUI_FROM_DATABASE=Macro Image Technology, Inc. + +OUI:403CFC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:403DEC* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:403F8C* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:404022* + ID_OUI_FROM_DATABASE=ZIV + +OUI:40406B* + ID_OUI_FROM_DATABASE=Icomera + +OUI:4040A7* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:404229* + ID_OUI_FROM_DATABASE=Layer3TV, Inc + +OUI:4045DA* + ID_OUI_FROM_DATABASE=Spreadtrum Communications (Shanghai) Co., Ltd. + +OUI:40476A* + ID_OUI_FROM_DATABASE=Astro Gaming + +OUI:4048FD0* + ID_OUI_FROM_DATABASE=BEIJING C&W ELECTRONICS(GROUP)CO.,LTD + +OUI:4048FD1* + ID_OUI_FROM_DATABASE=Fast Programming + +OUI:4048FD2* + ID_OUI_FROM_DATABASE=MITHRAS Technology Co., LTD + +OUI:4048FD3* + ID_OUI_FROM_DATABASE=RL Controls LLC. + +OUI:4048FD4* + ID_OUI_FROM_DATABASE=Dynamic Engineering + +OUI:4048FD5* + ID_OUI_FROM_DATABASE=The 52nd Research Institute of China Electronic Technology Group Corporation + +OUI:4048FD6* + ID_OUI_FROM_DATABASE=Swarco Technology ApS + +OUI:4048FD7* + ID_OUI_FROM_DATABASE=Cloud4Wi + +OUI:4048FD8* + ID_OUI_FROM_DATABASE=Dorel Juvenile + +OUI:4048FD9* + ID_OUI_FROM_DATABASE=Plus One Global Ltd. + +OUI:4048FDA* + ID_OUI_FROM_DATABASE=Shenzhen Yifang Digital Technology Co., LTD. + +OUI:4048FDB* + ID_OUI_FROM_DATABASE=Magenta Labs, Inc. + +OUI:4048FDC* + ID_OUI_FROM_DATABASE=Ecotap B.V. + +OUI:4048FDD* + ID_OUI_FROM_DATABASE=NOX Systems AG + +OUI:4048FDE* + ID_OUI_FROM_DATABASE=SMART SENSOR DEVICES AB + +OUI:40490F* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:40498A* + ID_OUI_FROM_DATABASE=Synapticon GmbH + +OUI:404A03* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:404A18* + ID_OUI_FROM_DATABASE=Addrek Smart Solutions + +OUI:404AD4* + ID_OUI_FROM_DATABASE=Widex A/S + +OUI:404C77* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:404D7F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:404D8E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:404E36* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:404EEB* + ID_OUI_FROM_DATABASE=Higher Way Electronic Co., Ltd. + +OUI:4050B5* + ID_OUI_FROM_DATABASE=Shenzhen New Species Technology Co., Ltd. + +OUI:4050E0* + ID_OUI_FROM_DATABASE=Milton Security Group LLC + +OUI:40516C* + ID_OUI_FROM_DATABASE=Grandex International Corporation + +OUI:40520D* + ID_OUI_FROM_DATABASE=Pico Technology + +OUI:4054E4* + ID_OUI_FROM_DATABASE=Wearsafe Labs Inc + +OUI:405539* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:405582* + ID_OUI_FROM_DATABASE=Nokia + +OUI:40560C* + ID_OUI_FROM_DATABASE=In Home Displays Ltd + +OUI:40562D* + ID_OUI_FROM_DATABASE=Smartron India Pvt ltd + +OUI:405662* + ID_OUI_FROM_DATABASE=GuoTengShengHua Electronics LTD. + +OUI:405A9B* + ID_OUI_FROM_DATABASE=ANOVO + +OUI:405BD8* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:405CFD* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:405D82* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:405EE1* + ID_OUI_FROM_DATABASE=Shenzhen H&T Intelligent Control Co.,Ltd. + +OUI:405FBE* + ID_OUI_FROM_DATABASE=RIM + +OUI:405FC2* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:40605A* + ID_OUI_FROM_DATABASE=Hawkeye Tech Co. Ltd + +OUI:406186* + ID_OUI_FROM_DATABASE=MICRO-STAR INT'L CO.,LTD + +OUI:40618E* + ID_OUI_FROM_DATABASE=Stella-Green Co + +OUI:406231* + ID_OUI_FROM_DATABASE=GIFA + +OUI:4062B6* + ID_OUI_FROM_DATABASE=Tele system communication + +OUI:4062EA* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:4064A4* + ID_OUI_FROM_DATABASE=THE FURUKAWA ELECTRIC CO., LTD + +OUI:4065A3* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:40667A* + ID_OUI_FROM_DATABASE=mediola - connected living AG + +OUI:406826* + ID_OUI_FROM_DATABASE=Thales UK Limited + +OUI:406A8E* + ID_OUI_FROM_DATABASE=Hangzhou Puwell OE Tech Ltd. + +OUI:406AAB* + ID_OUI_FROM_DATABASE=RIM + +OUI:406C8F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:406F2A* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:407009* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:40704A* + ID_OUI_FROM_DATABASE=Power Idea Technology Limited + +OUI:407074* + ID_OUI_FROM_DATABASE=Life Technology (China) Co., Ltd + +OUI:4070F5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:407183* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:407496* + ID_OUI_FROM_DATABASE=aFUN TECHNOLOGY INC. + +OUI:4074E0* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:4077A9* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:40786A* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:407875* + ID_OUI_FROM_DATABASE=IMBEL - Industria de Material Belico do Brasil + +OUI:407A80* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:407B1B* + ID_OUI_FROM_DATABASE=Mettle Networks Inc. + +OUI:407C7D* + ID_OUI_FROM_DATABASE=Nokia + +OUI:407D0F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:407FE0* + ID_OUI_FROM_DATABASE=Glory Star Technics (ShenZhen) Limited + +OUI:408256* + ID_OUI_FROM_DATABASE=Continental Automotive GmbH + +OUI:40831D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4083DE* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc + +OUI:408493* + ID_OUI_FROM_DATABASE=Clavister AB + +OUI:40862E* + ID_OUI_FROM_DATABASE=JDM MOBILE INTERNET SOLUTION CO., LTD. + +OUI:408805* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:4088E0* + ID_OUI_FROM_DATABASE=Beijing Ereneben Information Technology Limited Shenzhen Branch + +OUI:408A9A* + ID_OUI_FROM_DATABASE=TITENG CO., Ltd. + +OUI:408B07* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:408BF6* + ID_OUI_FROM_DATABASE=Shenzhen TCL New Technology Co., Ltd + +OUI:408D5C* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:409558* + ID_OUI_FROM_DATABASE=Aisino Corporation + +OUI:4095BD* + ID_OUI_FROM_DATABASE=NTmore.Co.,Ltd + +OUI:4097D1* + ID_OUI_FROM_DATABASE=BK Electronics cc + +OUI:40984C* + ID_OUI_FROM_DATABASE=Casacom Solutions AG + +OUI:40984E* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:40987B* + ID_OUI_FROM_DATABASE=Aisino Corporation + +OUI:4098AD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:409922* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:409B0D* + ID_OUI_FROM_DATABASE=Shenzhen Yourf Kwan Industrial Co., Ltd + +OUI:409BCD* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:409C28* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:409F38* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:409F87* + ID_OUI_FROM_DATABASE=Jide Technology (Hong Kong) Limited + +OUI:409FC7* + ID_OUI_FROM_DATABASE=BAEKCHUN I&C Co., Ltd. + +OUI:40A108* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:40A2DB* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:40A36B0* + ID_OUI_FROM_DATABASE=Fin Robotics Inc + +OUI:40A36B1* + ID_OUI_FROM_DATABASE=TW-TeamWare + +OUI:40A36B2* + ID_OUI_FROM_DATABASE=TOPROOTTechnology Corp. Ltd. + +OUI:40A36B3* + ID_OUI_FROM_DATABASE=Omnitracs, LLC + +OUI:40A36B4* + ID_OUI_FROM_DATABASE=SKS-Kinkel Elektronik GmbH + +OUI:40A36B5* + ID_OUI_FROM_DATABASE=National Research Council of Canada + +OUI:40A36B6* + ID_OUI_FROM_DATABASE=Securiton AG + +OUI:40A36B7* + ID_OUI_FROM_DATABASE=Pella Corporation + +OUI:40A36B8* + ID_OUI_FROM_DATABASE=SFT Co., Ltd. + +OUI:40A36B9* + ID_OUI_FROM_DATABASE=PH Technical Labs + +OUI:40A36BA* + ID_OUI_FROM_DATABASE=Embrionix Design Inc. + +OUI:40A36BB* + ID_OUI_FROM_DATABASE=Amobile Intelligent Corp. + +OUI:40A36BC* + ID_OUI_FROM_DATABASE=Onion Corporation + +OUI:40A36BD* + ID_OUI_FROM_DATABASE=FAOD Co.,Ltd. + +OUI:40A3CC* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:40A5EF* + ID_OUI_FROM_DATABASE=Shenzhen Four Seas Global Link Network Technology Co., Ltd. + +OUI:40A677* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:40A6A4* + ID_OUI_FROM_DATABASE=PassivSystems Ltd + +OUI:40A6B7* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:40A6D9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:40A6E8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:40A8F0* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:40A93F* + ID_OUI_FROM_DATABASE=Pivotal Commware, Inc. + +OUI:40AC8D* + ID_OUI_FROM_DATABASE=Data Management, Inc. + +OUI:40B034* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:40B076* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:40B0FA* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:40B2C8* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:40B30E* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:40B395* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:40B3CD* + ID_OUI_FROM_DATABASE=Chiyoda Electronics Co.,Ltd. + +OUI:40B3FC* + ID_OUI_FROM_DATABASE=Logital Co. Limited + +OUI:40B4CD* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:40B4F0* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:40B688* + ID_OUI_FROM_DATABASE=LEGIC Identsystems AG + +OUI:40B6B1* + ID_OUI_FROM_DATABASE=SUNGSAM CO,.Ltd + +OUI:40B6E7* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:40B7F3* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:40B837* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:40B89A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:40B93C* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:40BA61* + ID_OUI_FROM_DATABASE=ARIMA Communications Corp. + +OUI:40BC60* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:40BC68* + ID_OUI_FROM_DATABASE=Wuhan Funshion Online Technologies Co.,Ltd + +OUI:40BC73* + ID_OUI_FROM_DATABASE=Cronoplast S.L. + +OUI:40BC8B* + ID_OUI_FROM_DATABASE=itelio GmbH + +OUI:40BD32* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:40BD9E* + ID_OUI_FROM_DATABASE=Physio-Control, Inc + +OUI:40BF17* + ID_OUI_FROM_DATABASE=Digistar Telecom. SA + +OUI:40C245* + ID_OUI_FROM_DATABASE=Shenzhen Hexicom Technology Co., Ltd. + +OUI:40C3C6* + ID_OUI_FROM_DATABASE=SnapRoute + +OUI:40C4D6* + ID_OUI_FROM_DATABASE=ChongQing Camyu Technology Development Co.,Ltd. + +OUI:40C62A* + ID_OUI_FROM_DATABASE=Shanghai Jing Ren Electronic Technology Co., Ltd. + +OUI:40C729* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:40C7C9* + ID_OUI_FROM_DATABASE=Naviit Inc. + +OUI:40C81F* + ID_OUI_FROM_DATABASE=Shenzhen Xinguodu Technology Co., Ltd. + +OUI:40C8CB* + ID_OUI_FROM_DATABASE=AM Telecom co., Ltd. + +OUI:40CBA8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:40CBC0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:40CD3A* + ID_OUI_FROM_DATABASE=Z3 Technology + +OUI:40CD7A* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:40CE24* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:40D28A* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:40D32D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:40D357* + ID_OUI_FROM_DATABASE=Ison Technology Co., Ltd. + +OUI:40D3AE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:40D40E* + ID_OUI_FROM_DATABASE=Biodata Ltd + +OUI:40D559* + ID_OUI_FROM_DATABASE=MICRO S.E.R.I. + +OUI:40D63C* + ID_OUI_FROM_DATABASE=Equitech Industrial(DongGuan)Co.,Ltd + +OUI:40D855* + ID_OUI_FROM_DATABASE=IEEE Registration Authority + +OUI:40DC9D* + ID_OUI_FROM_DATABASE=HAJEN + +OUI:40DEAD* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:40DF02* + ID_OUI_FROM_DATABASE=LINE BIZ Plus + +OUI:40E230* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:40E3D6* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:40E730* + ID_OUI_FROM_DATABASE=DEY Storage Systems, Inc. + +OUI:40E793* + ID_OUI_FROM_DATABASE=Shenzhen Siviton Technology Co.,Ltd + +OUI:40EACE* + ID_OUI_FROM_DATABASE=FOUNDER BROADBAND NETWORK SERVICE CO.,LTD + +OUI:40EC99* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:40ECF8* + ID_OUI_FROM_DATABASE=Siemens AG + +OUI:40ED980* + ID_OUI_FROM_DATABASE=Tsinghua Tongfang Co., LTD + +OUI:40ED981* + ID_OUI_FROM_DATABASE=GuangZhou FiiO Electronics Technology Co.,Ltd + +OUI:40ED982* + ID_OUI_FROM_DATABASE=A-IOX INC. + +OUI:40ED983* + ID_OUI_FROM_DATABASE=Knox Company + +OUI:40ED984* + ID_OUI_FROM_DATABASE=Kendrion Kuhnke Automation GmbH + +OUI:40ED985* + ID_OUI_FROM_DATABASE=Cape + +OUI:40ED986* + ID_OUI_FROM_DATABASE=Shanghai Broadwan Communications Co.,Ltd + +OUI:40ED987* + ID_OUI_FROM_DATABASE=Vaisala Oyj + +OUI:40ED988* + ID_OUI_FROM_DATABASE=GUANGZHOU AURIC INTELLIGENT TECHNOLOGY CO.,LTD. + +OUI:40ED989* + ID_OUI_FROM_DATABASE=TeraTron GmbH + +OUI:40ED98A* + ID_OUI_FROM_DATABASE=Integrated Design Ltd + +OUI:40ED98B* + ID_OUI_FROM_DATABASE=Siebert Industrieelektronik GmbH + +OUI:40ED98C* + ID_OUI_FROM_DATABASE=BloomSky,Inc. + +OUI:40ED98D* + ID_OUI_FROM_DATABASE=Hangzhou GANX Technology Co.,Ltd. + +OUI:40ED98E* + ID_OUI_FROM_DATABASE=BORDA TECHNOLOGY + +OUI:40EEDD* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:40EF4C* + ID_OUI_FROM_DATABASE=Fihonest communication co.,Ltd + +OUI:40F02F* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:40F04E* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:40F14C* + ID_OUI_FROM_DATABASE=ISE Europe SPRL + +OUI:40F201* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:40F21C* + ID_OUI_FROM_DATABASE=DASAN Zhone Solutions + +OUI:40F2E9* + ID_OUI_FROM_DATABASE=IBM + +OUI:40F308* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:40F3850* + ID_OUI_FROM_DATABASE=SubPac + +OUI:40F3851* + ID_OUI_FROM_DATABASE=Johnson Matthey + +OUI:40F3852* + ID_OUI_FROM_DATABASE=Beijing Zongheng Electro-Mechanical Technology Development Co. + +OUI:40F3853* + ID_OUI_FROM_DATABASE=IntelliDesign Pty Ltd + +OUI:40F3854* + ID_OUI_FROM_DATABASE=Embedded IQ + +OUI:40F3855* + ID_OUI_FROM_DATABASE=KATO ENGINEERING INC. + +OUI:40F3856* + ID_OUI_FROM_DATABASE=Lennox International Incorporated + +OUI:40F3857* + ID_OUI_FROM_DATABASE=PALAZZETTI LELIO SPA + +OUI:40F3858* + ID_OUI_FROM_DATABASE=Teleepoch Ltd + +OUI:40F3859* + ID_OUI_FROM_DATABASE=Fast Precision Technologies Co. Ltd. + +OUI:40F385A* + ID_OUI_FROM_DATABASE=Creanord + +OUI:40F385B* + ID_OUI_FROM_DATABASE=URMET Home & Building Solutions Pty Ltd + +OUI:40F385C* + ID_OUI_FROM_DATABASE=Clixxo Broadband Private Limited + +OUI:40F385D* + ID_OUI_FROM_DATABASE=Digital Bros S.p.A. + +OUI:40F385E* + ID_OUI_FROM_DATABASE=BBB Inc. + +OUI:40F407* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:40F413* + ID_OUI_FROM_DATABASE=Rubezh + +OUI:40F420* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:40F4EC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:40F520* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:40F52E* + ID_OUI_FROM_DATABASE=Leica Microsystems (Schweiz) AG + +OUI:40F9D5* + ID_OUI_FROM_DATABASE=Tecore Networks + +OUI:40FA7F* + ID_OUI_FROM_DATABASE=Preh Car Connect GmbH + +OUI:40FC89* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:40FE0D* + ID_OUI_FROM_DATABASE=MAXIO + +OUI:440010* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:440049* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:44004D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:44032C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:4403770* + ID_OUI_FROM_DATABASE=Musashi Seimitsu Industry Co.,Ltd + +OUI:4403771* + ID_OUI_FROM_DATABASE=Atari, Inc. + +OUI:4403772* + ID_OUI_FROM_DATABASE=Exsom Computers LLC + +OUI:4403773* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:4403774* + ID_OUI_FROM_DATABASE=Lenovo Image(Tianjin) Technology Ltd. + +OUI:4403775* + ID_OUI_FROM_DATABASE=Norden Communication UK Ltd. + +OUI:4403776* + ID_OUI_FROM_DATABASE=SHEN ZHEN HUAWANG TECHNOLOGY CO; LTD + +OUI:4403777* + ID_OUI_FROM_DATABASE=Stara S/A Indústria de Implementos Agrícolas + +OUI:4403778* + ID_OUI_FROM_DATABASE=Gemmy Electronics (Shenzhen) Co, Ltd + +OUI:4403779* + ID_OUI_FROM_DATABASE=SHENZHEN UT-KING TECHNOLOGY CO.,LTD + +OUI:440377A* + ID_OUI_FROM_DATABASE=symplr + +OUI:440377B* + ID_OUI_FROM_DATABASE=Hangzhou Asia Infrastructure Tech. Co., Ltd. + +OUI:440377C* + ID_OUI_FROM_DATABASE=BIG Climatic Manufacture, Co. LTD, Zhongshan Branch + +OUI:440377D* + ID_OUI_FROM_DATABASE=OMNISENSE SYSTEMS PRIVATE LIMITED TAIWAN BRANCH + +OUI:440377E* + ID_OUI_FROM_DATABASE=Bolin Technology Co., Ltd + +OUI:4403A7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:440444* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:44070B* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:4409B8* + ID_OUI_FROM_DATABASE=Salcomp (Shenzhen) CO., LTD. + +OUI:440CFD* + ID_OUI_FROM_DATABASE=NetMan Co., Ltd. + +OUI:4410FE* + ID_OUI_FROM_DATABASE=Huizhou Foryou General Electronics Co., Ltd. + +OUI:441102* + ID_OUI_FROM_DATABASE=EDMI Europe Ltd + +OUI:4411C2* + ID_OUI_FROM_DATABASE=Telegartner Karl Gartner GmbH + +OUI:441319* + ID_OUI_FROM_DATABASE=WKK TECHNOLOGY LTD. + +OUI:4413D0* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:441441* + ID_OUI_FROM_DATABASE=AudioControl Inc. + +OUI:441847* + ID_OUI_FROM_DATABASE=HUNAN SCROWN ELECTRONIC INFORMATION TECH.CO.,LTD + +OUI:44184F* + ID_OUI_FROM_DATABASE=Fitview + +OUI:4418FD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4419B6* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:441AFA* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:441C12* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:441CA8* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:441E91* + ID_OUI_FROM_DATABASE=ARVIDA Intelligent Electronics Technology Co.,Ltd. + +OUI:441E98* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:441EA1* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:442295* + ID_OUI_FROM_DATABASE=China Mobile Iot Limited company + +OUI:4422F1* + ID_OUI_FROM_DATABASE=S.FAC, INC + +OUI:44237C* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd + +OUI:4423AA* + ID_OUI_FROM_DATABASE=Farmage Co., Ltd. + +OUI:4425BB* + ID_OUI_FROM_DATABASE=Bamboo Entertainment Corporation + +OUI:4428A3* + ID_OUI_FROM_DATABASE=Jiangsu fulian Communication Technology Co., Ltd. + +OUI:442938* + ID_OUI_FROM_DATABASE=NietZsche enterprise Co.Ltd. + +OUI:442A60* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:442AFF* + ID_OUI_FROM_DATABASE=E3 Technology, Inc. + +OUI:442B03* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:442C05* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:443192* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:44322A* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:4432C8* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:44334C* + ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD + +OUI:44348F* + ID_OUI_FROM_DATABASE=MXT INDUSTRIAL LTDA + +OUI:4434A7* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:44356F* + ID_OUI_FROM_DATABASE=Neterix + +OUI:443708* + ID_OUI_FROM_DATABASE=MRV Comunications + +OUI:443719* + ID_OUI_FROM_DATABASE=2 Save Energy Ltd + +OUI:44376F* + ID_OUI_FROM_DATABASE=Young Electric Sign Co + +OUI:4437E6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:443839* + ID_OUI_FROM_DATABASE=Cumulus Networks, inc + +OUI:4439C4* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:443C88* + ID_OUI_FROM_DATABASE=FICOSA MAROC INTERNATIONAL + +OUI:443C9C* + ID_OUI_FROM_DATABASE=Pintsch Tiefenbach GmbH + +OUI:443D21* + ID_OUI_FROM_DATABASE=Nuvolt + +OUI:443E07* + ID_OUI_FROM_DATABASE=Electrolux + +OUI:443EB2* + ID_OUI_FROM_DATABASE=DEOTRON Co., LTD. + +OUI:44422F* + ID_OUI_FROM_DATABASE=TESTOP CO.,LTD. + +OUI:444450* + ID_OUI_FROM_DATABASE=OttoQ + +OUI:444687* + ID_OUI_FROM_DATABASE=Realme Chongqing MobileTelecommunications Corp Ltd + +OUI:4447CC* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:444891* + ID_OUI_FROM_DATABASE=HDMI Licensing, LLC + +OUI:4448C1* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:444A65* + ID_OUI_FROM_DATABASE=Silverflare Ltd. + +OUI:444AB0* + ID_OUI_FROM_DATABASE=Zhejiang Moorgen Intelligence Technology Co., Ltd + +OUI:444ADB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:444B5D* + ID_OUI_FROM_DATABASE=GE Healthcare + +OUI:444B7E* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:444C0C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:444CA8* + ID_OUI_FROM_DATABASE=Arista Networks + +OUI:444E1A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:444E6D* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:444F5E* + ID_OUI_FROM_DATABASE=Pan Studios Co.,Ltd. + +OUI:4451DB* + ID_OUI_FROM_DATABASE=Raytheon BBN Technologies + +OUI:4454C0* + ID_OUI_FROM_DATABASE=Thompson Aerospace + +OUI:4455B1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4455C4* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:44568D* + ID_OUI_FROM_DATABASE=PNC Technologies Co., Ltd. + +OUI:4456B7* + ID_OUI_FROM_DATABASE=Spawn Labs, Inc + +OUI:445829* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:44599F* + ID_OUI_FROM_DATABASE=Criticare Systems, Inc + +OUI:4459E3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:445CE9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:445D5E* + ID_OUI_FROM_DATABASE=SHENZHEN Coolkit Technology CO.,LTD + +OUI:445ECD* + ID_OUI_FROM_DATABASE=Razer Inc + +OUI:445EF3* + ID_OUI_FROM_DATABASE=Tonalite Holding B.V. + +OUI:445F7A* + ID_OUI_FROM_DATABASE=Shihlin Electric & Engineering Corp. + +OUI:445F8C* + ID_OUI_FROM_DATABASE=Intercel Group Limited + +OUI:446132* + ID_OUI_FROM_DATABASE=ecobee inc + +OUI:44619C* + ID_OUI_FROM_DATABASE=FONsystem co. ltd. + +OUI:446246* + ID_OUI_FROM_DATABASE=Comat AG + +OUI:44650D* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:44656A* + ID_OUI_FROM_DATABASE=Mega Video Electronic(HK) Industry Co., Ltd + +OUI:44657F* + ID_OUI_FROM_DATABASE=Calix Inc. + +OUI:44666E* + ID_OUI_FROM_DATABASE=IP-LINE + +OUI:4466FC* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:446747* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:446755* + ID_OUI_FROM_DATABASE=Orbit Irrigation + +OUI:4468AB* + ID_OUI_FROM_DATABASE=JUIN COMPANY, LIMITED + +OUI:446A2E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:446AB7* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:446C24* + ID_OUI_FROM_DATABASE=Reallin Electronic Co.,Ltd + +OUI:446D57* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:446D6C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:446EE5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:44700B* + ID_OUI_FROM_DATABASE=IFFU + +OUI:447098* + ID_OUI_FROM_DATABASE=MING HONG TECHNOLOGY (SHEN ZHEN) LIMITED + +OUI:4473D6* + ID_OUI_FROM_DATABASE=Logitech + +OUI:44746C* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:447654* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:44783E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:447BBB* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:447BC4* + ID_OUI_FROM_DATABASE=DualShine Technology(SZ)Co.,Ltd + +OUI:447C7F* + ID_OUI_FROM_DATABASE=Innolight Technology Corporation + +OUI:447DA5* + ID_OUI_FROM_DATABASE=VTION INFORMATION TECHNOLOGY (FUJIAN) CO.,LTD + +OUI:447E76* + ID_OUI_FROM_DATABASE=Trek Technology (S) Pte Ltd + +OUI:447E95* + ID_OUI_FROM_DATABASE=Alpha and Omega, Inc + +OUI:447F77* + ID_OUI_FROM_DATABASE=Connected Home + +OUI:4480EB* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:4482E5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:448312* + ID_OUI_FROM_DATABASE=Star-Net + +OUI:448500* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:4486C1* + ID_OUI_FROM_DATABASE=Siemens Low Voltage & Products + +OUI:448723* + ID_OUI_FROM_DATABASE=HOYA SERVICE CORPORATION + +OUI:4487FC* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:4488CB* + ID_OUI_FROM_DATABASE=Camco Technologies NV + +OUI:448A5B* + ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD. + +OUI:448C52* + ID_OUI_FROM_DATABASE=KTIS CO., Ltd + +OUI:448E12* + ID_OUI_FROM_DATABASE=DT Research, Inc. + +OUI:448E81* + ID_OUI_FROM_DATABASE=VIG + +OUI:448F17* + ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd. ARTIK + +OUI:449160* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:4491DB* + ID_OUI_FROM_DATABASE=Shanghai Huaqin Telecom Technology Co.,Ltd + +OUI:4494FC* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:4495FA* + ID_OUI_FROM_DATABASE=Qingdao Santong Digital Technology Co.Ltd + +OUI:44962B* + ID_OUI_FROM_DATABASE=Aidon Oy + +OUI:44975A* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:449B78* + ID_OUI_FROM_DATABASE=The Now Factory + +OUI:449CB5* + ID_OUI_FROM_DATABASE=Alcomp, Inc + +OUI:449EF9* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:449F7F* + ID_OUI_FROM_DATABASE=DataCore Software Corporation + +OUI:44A191* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:44A42D* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:44A466* + ID_OUI_FROM_DATABASE=GROUPE LDLC + +OUI:44A56E* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:44A61E* + ID_OUI_FROM_DATABASE=INGRAM MICRO SERVICES + +OUI:44A689* + ID_OUI_FROM_DATABASE=PROMAX ELECTRONICA SA + +OUI:44A6E5* + ID_OUI_FROM_DATABASE=THINKING TECHNOLOGY CO.,LTD + +OUI:44A7CF* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:44A842* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:44A8C2* + ID_OUI_FROM_DATABASE=SEWOO TECH CO., LTD + +OUI:44AA27* + ID_OUI_FROM_DATABASE=udworks Co., Ltd. + +OUI:44AA50* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:44AAE8* + ID_OUI_FROM_DATABASE=Nanotec Electronic GmbH & Co. KG + +OUI:44AAF5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:44AD19* + ID_OUI_FROM_DATABASE=XINGFEI (H.K)LIMITED + +OUI:44ADD9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:44AEAB* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:44B295* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:44B32D* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:44B382* + ID_OUI_FROM_DATABASE=Kuang-chi Institute of Advanced Technology + +OUI:44B412* + ID_OUI_FROM_DATABASE=SIUS AG + +OUI:44B433* + ID_OUI_FROM_DATABASE=tide.co.,ltd + +OUI:44B462* + ID_OUI_FROM_DATABASE=Flextronics Tech.(Ind) Pvt Ltd + +OUI:44B994* + ID_OUI_FROM_DATABASE=Douglas Lighting Controls + +OUI:44BA46* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:44BFE3* + ID_OUI_FROM_DATABASE=Shenzhen Longtech Electronics Co.,Ltd + +OUI:44C15C* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:44C233* + ID_OUI_FROM_DATABASE=Guangzhou Comet Technology Development Co.Ltd + +OUI:44C306* + ID_OUI_FROM_DATABASE=SIFROM Inc. + +OUI:44C346* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:44C39B* + ID_OUI_FROM_DATABASE=OOO RUBEZH NPO + +OUI:44C4A9* + ID_OUI_FROM_DATABASE=Opticom Communication, LLC + +OUI:44C56F* + ID_OUI_FROM_DATABASE=NGN Easy Satfinder (Tianjin) Electronic Co., Ltd + +OUI:44C65D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:44C69B* + ID_OUI_FROM_DATABASE=Wuhan Feng Tian Information Network CO.,LTD + +OUI:44C7FC* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:44C874* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:44C9A2* + ID_OUI_FROM_DATABASE=Greenwald Industries + +OUI:44CB8B* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:44CD0E* + ID_OUI_FROM_DATABASE=FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + +OUI:44CE7D* + ID_OUI_FROM_DATABASE=SFR + +OUI:44D15E* + ID_OUI_FROM_DATABASE=Shanghai Kingto Information Technology Ltd + +OUI:44D1FA* + ID_OUI_FROM_DATABASE=Shenzhen Yunlink Technology Co., Ltd + +OUI:44D244* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:44D2CA* + ID_OUI_FROM_DATABASE=Anvia TV Oy + +OUI:44D3AD* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:44D3CA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:44D437* + ID_OUI_FROM_DATABASE=Inteno Broadband Technology AB + +OUI:44D4E0* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:44D5A5* + ID_OUI_FROM_DATABASE=AddOn Computer + +OUI:44D5F20* + ID_OUI_FROM_DATABASE=TIBA Research & Development (1986) LTD + +OUI:44D5F21* + ID_OUI_FROM_DATABASE=SIMPLERED TECHNOLOGY LTD. + +OUI:44D5F22* + ID_OUI_FROM_DATABASE=Shenzhen Hebang Electronic Co., Ltd + +OUI:44D5F23* + ID_OUI_FROM_DATABASE=VURO LLC + +OUI:44D5F24* + ID_OUI_FROM_DATABASE=APPOTRONICS CO., LTD + +OUI:44D5F25* + ID_OUI_FROM_DATABASE=tiga.eleven GmbH + +OUI:44D5F26* + ID_OUI_FROM_DATABASE=Beam Communications Pty Ltd + +OUI:44D5F27* + ID_OUI_FROM_DATABASE=Shenzhen Qiutian Technology Co.,Ltd + +OUI:44D5F28* + ID_OUI_FROM_DATABASE=CETC Avionics.L td + +OUI:44D5F29* + ID_OUI_FROM_DATABASE=Auctus Technologies Co.,Ltd. + +OUI:44D5F2A* + ID_OUI_FROM_DATABASE=SYS TEC electronic GmbH + +OUI:44D5F2B* + ID_OUI_FROM_DATABASE=Valeo Interior Controls (Shenzhen) Co.,Ltd + +OUI:44D5F2C* + ID_OUI_FROM_DATABASE=neocontrol soluções em automação + +OUI:44D5F2D* + ID_OUI_FROM_DATABASE=Shenzhen Nation RFID Technology Co.,Ltd. + +OUI:44D5F2E* + ID_OUI_FROM_DATABASE=Joint-Stock Company Research and Development Center ELVEES + +OUI:44D63D* + ID_OUI_FROM_DATABASE=Talari Networks + +OUI:44D6E1* + ID_OUI_FROM_DATABASE=Snuza International Pty. Ltd. + +OUI:44D791* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:44D832* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:44D878* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:44D884* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:44D9E7* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:44DC4E* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:44DC91* + ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. + +OUI:44DCCB* + ID_OUI_FROM_DATABASE=SEMINDIA SYSTEMS PVT LTD + +OUI:44E08E* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:44E137* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:44E49A* + ID_OUI_FROM_DATABASE=OMNITRONICS PTY LTD + +OUI:44E4D9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:44E4EE* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:44E66E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:44E8A5* + ID_OUI_FROM_DATABASE=Myreka Technologies Sdn. Bhd. + +OUI:44E9DD* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:44EA4B* + ID_OUI_FROM_DATABASE=Actlas Inc. + +OUI:44EAD8* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:44ECCE* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:44ED57* + ID_OUI_FROM_DATABASE=Longicorn, inc. + +OUI:44EE02* + ID_OUI_FROM_DATABASE=MTI Ltd. + +OUI:44EE30* + ID_OUI_FROM_DATABASE=Budelmann Elektronik GmbH + +OUI:44EFBF* + ID_OUI_FROM_DATABASE=China Dragon Technology Limited + +OUI:44EFCF* + ID_OUI_FROM_DATABASE=UGENE SOLUTION inc. + +OUI:44F034* + ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD. + +OUI:44F436* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:44F459* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:44F477* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:44F849* + ID_OUI_FROM_DATABASE=Union Pacific Railroad + +OUI:44F971* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:44FB42* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:44FB5A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:44FDA3* + ID_OUI_FROM_DATABASE=Everysight LTD. + +OUI:44FE3B* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:44FFBA* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:480031* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:480033* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:4801C5* + ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd + +OUI:48022A* + ID_OUI_FROM_DATABASE=B-Link Electronic Limited + +OUI:480362* + ID_OUI_FROM_DATABASE=DESAY ELECTRONICS(HUIZHOU)CO.,LTD + +OUI:48049F* + ID_OUI_FROM_DATABASE=ELECOM CO., LTD + +OUI:48066A* + ID_OUI_FROM_DATABASE=Tempered Networks, Inc. + +OUI:480BB20* + ID_OUI_FROM_DATABASE=Ridango AS + +OUI:480BB21* + ID_OUI_FROM_DATABASE=BAJA ELECTRONICS TECHNOLOGY LIMITED + +OUI:480BB22* + ID_OUI_FROM_DATABASE=Thales CETCA Avionics CO., Ltd + +OUI:480BB23* + ID_OUI_FROM_DATABASE=shanghai Rinlink Intelligent Technology Co., Ltd. + +OUI:480BB24* + ID_OUI_FROM_DATABASE=Hangzhou Freely Communication Co., Ltd. + +OUI:480BB25* + ID_OUI_FROM_DATABASE=Solaredge LTD. + +OUI:480BB26* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:480BB27* + ID_OUI_FROM_DATABASE=Beijing Dragon Resources Limited. + +OUI:480BB28* + ID_OUI_FROM_DATABASE=BravoCom(xiamen)TechCo.Ltd + +OUI:480BB29* + ID_OUI_FROM_DATABASE=Microprogram Information Co., Ltd + +OUI:480BB2A* + ID_OUI_FROM_DATABASE=XIAMEN RONGTA TECHNOLOGY CO.,LTD. + +OUI:480BB2B* + ID_OUI_FROM_DATABASE=Popit Oy + +OUI:480BB2C* + ID_OUI_FROM_DATABASE=SHENZHEN TOPWELL TECHNOLOGY CO..LTD + +OUI:480BB2D* + ID_OUI_FROM_DATABASE=M2Lab Ltd. + +OUI:480BB2E* + ID_OUI_FROM_DATABASE=Beijing MFOX technology Co., Ltd. + +OUI:480C49* + ID_OUI_FROM_DATABASE=NAKAYO Inc + +OUI:480EEC* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:480FCF* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:481063* + ID_OUI_FROM_DATABASE=NTT Innovation Institute, Inc. + +OUI:481249* + ID_OUI_FROM_DATABASE=Luxcom Technologies Inc. + +OUI:48137E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:4813F3* + ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + +OUI:48174C* + ID_OUI_FROM_DATABASE=MicroPower technologies + +OUI:481842* + ID_OUI_FROM_DATABASE=Shanghai Winaas Co. Equipment Co. Ltd. + +OUI:4818FA* + ID_OUI_FROM_DATABASE=Nocsys + +OUI:481A84* + ID_OUI_FROM_DATABASE=Pointer Telocation Ltd + +OUI:481BD2* + ID_OUI_FROM_DATABASE=Intron Scientific co., ltd. + +OUI:481D70* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:48210B* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:48216C* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:4826E8* + ID_OUI_FROM_DATABASE=Tek-Air Systems, Inc. + +OUI:482759* + ID_OUI_FROM_DATABASE=Levven Electronics Ltd. + +OUI:4827EA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:48282F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:482AE3* + ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd. + +OUI:482CA0* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:482CEA* + ID_OUI_FROM_DATABASE=Motorola Inc Business Light Radios + +OUI:4833DD* + ID_OUI_FROM_DATABASE=ZENNIO AVANCE Y TECNOLOGIA, S.L. + +OUI:48343D* + ID_OUI_FROM_DATABASE=IEP GmbH + +OUI:48352E* + ID_OUI_FROM_DATABASE=Shenzhen Wolck Network Product Co.,LTD + +OUI:48365F* + ID_OUI_FROM_DATABASE=Wintecronics Ltd. + +OUI:483974* + ID_OUI_FROM_DATABASE=Proware Technologies Co., Ltd. + +OUI:483B38* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:483C0C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:483D32* + ID_OUI_FROM_DATABASE=Syscor Controls & Automation + +OUI:483FDA* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:483FE9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:48435A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:48437C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:484487* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:4844F7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:484520* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:4846C1* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:4846F1* + ID_OUI_FROM_DATABASE=Uros Oy + +OUI:4846FB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4849C7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:484A30* + ID_OUI_FROM_DATABASE=George Robotics Limited + +OUI:484AE9* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:484BAA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:484C86* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:484D7E* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:484EFC* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:485073* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:485169* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:4851B7* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:485261* + ID_OUI_FROM_DATABASE=SOREEL + +OUI:485415* + ID_OUI_FROM_DATABASE=NET RULES TECNOLOGIA EIRELI + +OUI:48555C* + ID_OUI_FROM_DATABASE=Wu Qi Technologies,Inc. + +OUI:48555F* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:485702* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4857DD* + ID_OUI_FROM_DATABASE=Facebook Inc + +OUI:485929* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:4859A4* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:485A3F* + ID_OUI_FROM_DATABASE=WISOL + +OUI:485AB6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:485B39* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:485D36* + ID_OUI_FROM_DATABASE=Verizon + +OUI:485D60* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:485DEB* + ID_OUI_FROM_DATABASE=Just Add Power + +OUI:485F99* + ID_OUI_FROM_DATABASE=Cloud Network Technology (Samoa) Limited + +OUI:48605F* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:4860BC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4861A3* + ID_OUI_FROM_DATABASE=Concern Axion JSC + +OUI:486276* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4865EE0* + ID_OUI_FROM_DATABASE=DefPower Ltd + +OUI:4865EE1* + ID_OUI_FROM_DATABASE=Gopod Group Limited + +OUI:4865EE2* + ID_OUI_FROM_DATABASE=CaptionCall + +OUI:4865EE3* + ID_OUI_FROM_DATABASE=Data Technology Inc. + +OUI:4865EE4* + ID_OUI_FROM_DATABASE=Mission Microwave Technologies, Inc + +OUI:4865EE5* + ID_OUI_FROM_DATABASE=Swistec Systems AG + +OUI:4865EE6* + ID_OUI_FROM_DATABASE=shenzhen sunflower technologies CO., LIMITED + +OUI:4865EE7* + ID_OUI_FROM_DATABASE=Venture Research Inc. + +OUI:4865EE8* + ID_OUI_FROM_DATABASE=SmartDisplayer Technology Co., Ltd. + +OUI:4865EE9* + ID_OUI_FROM_DATABASE=VideoStitch, Inc + +OUI:4865EEA* + ID_OUI_FROM_DATABASE=Shenzhen Inpor cloud Computing Co., Ltd. + +OUI:4865EEB* + ID_OUI_FROM_DATABASE=EnBW Energie Baden-Württemberg AG + +OUI:4865EEC* + ID_OUI_FROM_DATABASE=DNV GL + +OUI:4865EED* + ID_OUI_FROM_DATABASE=Winn Technology Co.,Ltd + +OUI:4865EEE* + ID_OUI_FROM_DATABASE=CNU + +OUI:486834* + ID_OUI_FROM_DATABASE=Silicon Motion, Inc. + +OUI:486B2C* + ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + +OUI:486B91* + ID_OUI_FROM_DATABASE=Fleetwood Group Inc. + +OUI:486DBB* + ID_OUI_FROM_DATABASE=Vestel Elektronik San ve Tic. A.Ş. + +OUI:486E70* + ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd. + +OUI:486E73* + ID_OUI_FROM_DATABASE=Pica8, Inc. + +OUI:486EFB* + ID_OUI_FROM_DATABASE=Davit System Technology Co., Ltd. + +OUI:486FD2* + ID_OUI_FROM_DATABASE=StorSimple Inc + +OUI:487119* + ID_OUI_FROM_DATABASE=SGB GROUP LTD. + +OUI:48746E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:487583* + ID_OUI_FROM_DATABASE=Intellion AG + +OUI:487604* + ID_OUI_FROM_DATABASE=Private + +OUI:487746* + ID_OUI_FROM_DATABASE=Calix Inc. + +OUI:48794D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:487A55* + ID_OUI_FROM_DATABASE=ALE International + +OUI:487ADA* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:487AF6* + ID_OUI_FROM_DATABASE=NCS ELECTRICAL SDN BHD + +OUI:487AFF* + ID_OUI_FROM_DATABASE=ESSYS + +OUI:487B5E* + ID_OUI_FROM_DATABASE=SMT TELECOMM HK + +OUI:487B6B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:487D2E* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:488244* + ID_OUI_FROM_DATABASE=Life Fitness / Div. of Brunswick + +OUI:4882F2* + ID_OUI_FROM_DATABASE=Appel Elektronik GmbH + +OUI:4883B4* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:4883C7* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:4886E8* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:48872D* + ID_OUI_FROM_DATABASE=SHEN ZHEN DA XIA LONG QUE TECHNOLOGY CO.,LTD + +OUI:488764* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:488803* + ID_OUI_FROM_DATABASE=ManTechnology Inc. + +OUI:48881E* + ID_OUI_FROM_DATABASE=EthoSwitch LLC + +OUI:4888CA* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:4889E7* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:488AD2* + ID_OUI_FROM_DATABASE=MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:488D36* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:488E42* + ID_OUI_FROM_DATABASE=DIGALOG GmbH + +OUI:488EEF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:489153* + ID_OUI_FROM_DATABASE=Weinmann Geräte für Medizin GmbH + Co. KG + +OUI:4891F6* + ID_OUI_FROM_DATABASE=Shenzhen Reach software technology CO.,LTD + +OUI:489507* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:4898CA* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:489A42* + ID_OUI_FROM_DATABASE=Technomate Ltd + +OUI:489BD5* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:489BE2* + ID_OUI_FROM_DATABASE=SCI Innovations Ltd + +OUI:489D18* + ID_OUI_FROM_DATABASE=Flashbay Limited + +OUI:489D24* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:489DD1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:48A0F8* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:48A195* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:48A22D* + ID_OUI_FROM_DATABASE=Shenzhen Huaxuchang Telecom Technology Co.,Ltd + +OUI:48A2B7* + ID_OUI_FROM_DATABASE=Kodofon JSC + +OUI:48A2E6* + ID_OUI_FROM_DATABASE=Resideo + +OUI:48A380* + ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co.,Ltd. + +OUI:48A472* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:48A493* + ID_OUI_FROM_DATABASE=TAIYO YUDEN CO.,LTD + +OUI:48A5E7* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:48A6B8* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:48A6D2* + ID_OUI_FROM_DATABASE=GJsun Optical Science and Tech Co.,Ltd. + +OUI:48A73C* + ID_OUI_FROM_DATABASE=Sichuan tianyi kanghe communications co., LTD + +OUI:48A74E* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:48A91C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:48A9D2* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:48AA5D* + ID_OUI_FROM_DATABASE=Store Electronic Systems + +OUI:48AD08* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:48B02D* + ID_OUI_FROM_DATABASE=NVIDIA Corporation + +OUI:48B253* + ID_OUI_FROM_DATABASE=Marketaxess Corporation + +OUI:48B5A7* + ID_OUI_FROM_DATABASE=Glory Horse Industries Ltd. + +OUI:48B620* + ID_OUI_FROM_DATABASE=ROLI Ltd. + +OUI:48B8A3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:48B8DE* + ID_OUI_FROM_DATABASE=HOMEWINS TECHNOLOGY CO.,LTD. + +OUI:48B977* + ID_OUI_FROM_DATABASE=PulseOn Oy + +OUI:48B9C2* + ID_OUI_FROM_DATABASE=Teletics Inc. + +OUI:48BA4E* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:48BCA6* + ID_OUI_FROM_DATABASE=​ASUNG TECHNO CO.,Ltd + +OUI:48BD0E* + ID_OUI_FROM_DATABASE=Quanta Storage Inc. + +OUI:48BD3D* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:48BE2D* + ID_OUI_FROM_DATABASE=Symanitron + +OUI:48BF6B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:48BF74* + ID_OUI_FROM_DATABASE=Baicells Technologies Co.,LTD + +OUI:48C049* + ID_OUI_FROM_DATABASE=Broad Telecom SA + +OUI:48C093* + ID_OUI_FROM_DATABASE=Xirrus, Inc. + +OUI:48C1AC* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. + +OUI:48C3B0* + ID_OUI_FROM_DATABASE=Pharos Co.Ltd + +OUI:48C58D* + ID_OUI_FROM_DATABASE=Lear Corporation GmbH + +OUI:48C663* + ID_OUI_FROM_DATABASE=GTO Access Systems LLC + +OUI:48C796* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:48C862* + ID_OUI_FROM_DATABASE=Simo Wireless,Inc. + +OUI:48C8B6* + ID_OUI_FROM_DATABASE=SysTec GmbH + +OUI:48CB6E* + ID_OUI_FROM_DATABASE=Cello Electronics (UK) Ltd + +OUI:48D0CF* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. + +OUI:48D18E* + ID_OUI_FROM_DATABASE=Metis Communication Co.,Ltd + +OUI:48D224* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:48D24F* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:48D343* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:48D35D* + ID_OUI_FROM_DATABASE=Private + +OUI:48D539* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:48D54C* + ID_OUI_FROM_DATABASE=Jeda Networks + +OUI:48D6D5* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:48D705* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:48D7FF* + ID_OUI_FROM_DATABASE=BLANKOM Antennentechnik GmbH + +OUI:48D845* + ID_OUI_FROM_DATABASE=Shenzhen Mainuoke Electronics Co., Ltd + +OUI:48D855* + ID_OUI_FROM_DATABASE=Telvent + +OUI:48D875* + ID_OUI_FROM_DATABASE=China TransInfo Technology Co., Ltd + +OUI:48D8FE* + ID_OUI_FROM_DATABASE=ClarIDy Solutions, Inc. + +OUI:48DA96* + ID_OUI_FROM_DATABASE=Eddy Smart Home Solutions Inc. + +OUI:48DB50* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:48DC2D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:48DCFB* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:48DD0C* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:48DD9D* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:48DF1C* + ID_OUI_FROM_DATABASE=Wuhan NEC Fibre Optic Communications industry Co. Ltd + +OUI:48DF37* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:48E1AF* + ID_OUI_FROM_DATABASE=Vity + +OUI:48E1E9* + ID_OUI_FROM_DATABASE=Chengdu Meross Technology Co., Ltd. + +OUI:48E244* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:48E3C3* + ID_OUI_FROM_DATABASE=JENOPTIK Advanced Systems GmbH + +OUI:48E695* + ID_OUI_FROM_DATABASE=Insigma Inc + +OUI:48E6C0* + ID_OUI_FROM_DATABASE=SIMCom Wireless Solutions Co.,Ltd. + +OUI:48E9F1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:48EA63* + ID_OUI_FROM_DATABASE=Zhejiang Uniview Technologies Co., Ltd. + +OUI:48EB30* + ID_OUI_FROM_DATABASE=ETERNA TECHNOLOGY, INC. + +OUI:48EB62* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:48EC5B* + ID_OUI_FROM_DATABASE=Nokia + +OUI:48ED80* + ID_OUI_FROM_DATABASE=daesung eltec + +OUI:48EE07* + ID_OUI_FROM_DATABASE=Silver Palm Technologies LLC + +OUI:48EE0C* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:48EE86* + ID_OUI_FROM_DATABASE=UTStarcom (China) Co.,Ltd + +OUI:48F027* + ID_OUI_FROM_DATABASE=Chengdu newifi Co.,Ltd + +OUI:48F07B* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:48F17F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:48F230* + ID_OUI_FROM_DATABASE=Ubizcore Co.,LTD + +OUI:48F317* + ID_OUI_FROM_DATABASE=Private + +OUI:48F47D* + ID_OUI_FROM_DATABASE=TechVision Holding Internation Limited + +OUI:48F7C0* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:48F7F1* + ID_OUI_FROM_DATABASE=Nokia + +OUI:48F8B3* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:48F8DB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:48F8E1* + ID_OUI_FROM_DATABASE=Nokia + +OUI:48F925* + ID_OUI_FROM_DATABASE=Maestronic + +OUI:48F97C* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:48FCB6* + ID_OUI_FROM_DATABASE=LAVA INTERNATIONAL(H.K) LIMITED + +OUI:48FCB8* + ID_OUI_FROM_DATABASE=Woodstream Corporation + +OUI:48FD8E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:48FDA3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:48FEEA* + ID_OUI_FROM_DATABASE=HOMA B.V. + +OUI:4C0082* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4C0143* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:4C022E* + ID_OUI_FROM_DATABASE=CMR KOREA CO., LTD + +OUI:4C0289* + ID_OUI_FROM_DATABASE=LEX COMPUTECH CO., LTD + +OUI:4C068A* + ID_OUI_FROM_DATABASE=Basler Electric Company + +OUI:4C07C9* + ID_OUI_FROM_DATABASE=COMPUTER OFFICE Co.,Ltd. + +OUI:4C09B4* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:4C09D4* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:4C0A3D* + ID_OUI_FROM_DATABASE=ADNACOM INC. + +OUI:4C0B3A* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:4C0BBE* + ID_OUI_FROM_DATABASE=Microsoft + +OUI:4C0DEE* + ID_OUI_FROM_DATABASE=JABIL CIRCUIT (SHANGHAI) LTD. + +OUI:4C0F6E* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:4C0FC7* + ID_OUI_FROM_DATABASE=Earda Technologies co Ltd + +OUI:4C1159* + ID_OUI_FROM_DATABASE=Vision Information & Communications + +OUI:4C11AE* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:4C11BF* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:4C1265* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:4C1365* + ID_OUI_FROM_DATABASE=Emplus Technologies + +OUI:4C1480* + ID_OUI_FROM_DATABASE=NOREGON SYSTEMS, INC + +OUI:4C14A3* + ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd. + +OUI:4C1694* + ID_OUI_FROM_DATABASE=shenzhen sibituo Technology Co., Ltd + +OUI:4C16F1* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:4C16FC* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:4C1744* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:4C17EB* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:4C189A* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:4C1A3A* + ID_OUI_FROM_DATABASE=PRIMA Research And Production Enterprise Ltd. + +OUI:4C1A3D* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:4C1A95* + ID_OUI_FROM_DATABASE=Novakon Co., Ltd. + +OUI:4C1B86* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:4C1D96* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:4C1FCC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4C218C* + ID_OUI_FROM_DATABASE=Panasonic India Private limited + +OUI:4C21D0* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:4C2258* + ID_OUI_FROM_DATABASE=cozybit, Inc. + +OUI:4C2498* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:4C2578* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:4C26E7* + ID_OUI_FROM_DATABASE=Welgate Co., Ltd. + +OUI:4C2C80* + ID_OUI_FROM_DATABASE=Beijing Skyway Technologies Co.,Ltd + +OUI:4C2C83* + ID_OUI_FROM_DATABASE=Zhejiang KaNong Network Technology Co.,Ltd. + +OUI:4C2F9D* + ID_OUI_FROM_DATABASE=ICM Controls + +OUI:4C3089* + ID_OUI_FROM_DATABASE=Thales Transportation Systems GmbH + +OUI:4C322D* + ID_OUI_FROM_DATABASE=TELEDATA NETWORKS + +OUI:4C3275* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4C32D9* + ID_OUI_FROM_DATABASE=M Rutty Holdings Pty. Ltd. + +OUI:4C334E* + ID_OUI_FROM_DATABASE=HIGHTECH + +OUI:4C3488* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:4C364E* + ID_OUI_FROM_DATABASE=Panasonic Corporation Connected Solutions Company + +OUI:4C38D5* + ID_OUI_FROM_DATABASE=MITAC COMPUTING TECHNOLOGY CORPORATION + +OUI:4C38D8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:4C3909* + ID_OUI_FROM_DATABASE=HPL Electric & Power Private Limited + +OUI:4C3910* + ID_OUI_FROM_DATABASE=Newtek Electronics co., Ltd. + +OUI:4C3B74* + ID_OUI_FROM_DATABASE=VOGTEC(H.K.) Co., Ltd + +OUI:4C3C16* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:4C3FD3* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:4C4576* + ID_OUI_FROM_DATABASE=China Mobile(Hangzhou) Information Technology Co.,Ltd. + +OUI:4C48DA* + ID_OUI_FROM_DATABASE=Beijing Autelan Technology Co.,Ltd + +OUI:4C494F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:4C49E3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:4C4B68* + ID_OUI_FROM_DATABASE=Mobile Device, Inc. + +OUI:4C4BF90* + ID_OUI_FROM_DATABASE=Multitek Elektronik Sanayi ve Ticaret A.S. + +OUI:4C4BF91* + ID_OUI_FROM_DATABASE=Jiangsu acrel Co., Ltd. + +OUI:4C4BF92* + ID_OUI_FROM_DATABASE=Shenzhen HommPro Technology Co.,Ltd + +OUI:4C4BF93* + ID_OUI_FROM_DATABASE=Power Active Co., Ltd + +OUI:4C4BF94* + ID_OUI_FROM_DATABASE=Shenzhen dingsheng technology co., LTD + +OUI:4C4BF95* + ID_OUI_FROM_DATABASE=Remedee Labs + +OUI:4C4BF96* + ID_OUI_FROM_DATABASE=Shandong Linkotech Electronic Co., Ltd. + +OUI:4C4BF97* + ID_OUI_FROM_DATABASE=GLONEXS + +OUI:4C4BF98* + ID_OUI_FROM_DATABASE=Zivid AS + +OUI:4C4BF99* + ID_OUI_FROM_DATABASE=Tecnoplus Srl + +OUI:4C4BF9A* + ID_OUI_FROM_DATABASE=Electrolux Professional AB + +OUI:4C4BF9B* + ID_OUI_FROM_DATABASE=Stored Energy Systems + +OUI:4C4BF9C* + ID_OUI_FROM_DATABASE=Connected IO + +OUI:4C4BF9D* + ID_OUI_FROM_DATABASE=Shenzhen Haichuan Intelligent Information Technology Co., Ltd. + +OUI:4C4BF9E* + ID_OUI_FROM_DATABASE=Beijing AutoAi Technology co. LTD + +OUI:4C4D66* + ID_OUI_FROM_DATABASE=Nanjing Jiahao Technology Co., Ltd. + +OUI:4C4E03* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:4C4E35* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4C4FEE* + ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd + +OUI:4C5077* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:4C5262* + ID_OUI_FROM_DATABASE=Fujitsu Technology Solutions GmbH + +OUI:4C5427* + ID_OUI_FROM_DATABASE=Linepro Sp. z o.o. + +OUI:4C5499* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4C5585* + ID_OUI_FROM_DATABASE=Hamilton Systems + +OUI:4C55B8* + ID_OUI_FROM_DATABASE=Turkcell Teknoloji + +OUI:4C55CC* + ID_OUI_FROM_DATABASE=Zentri Pty Ltd + +OUI:4C569D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4C56DF* + ID_OUI_FROM_DATABASE=Targus US LLC + +OUI:4C57CA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4C5DCD* + ID_OUI_FROM_DATABASE=Oy Finnish Electric Vehicle Technologies Ltd + +OUI:4C5E0C* + ID_OUI_FROM_DATABASE=Routerboard.com + +OUI:4C5FD2* + ID_OUI_FROM_DATABASE=Alcatel-Lucent + +OUI:4C60D5* + ID_OUI_FROM_DATABASE=airPointe of New Hampshire + +OUI:4C60DE* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:4C6255* + ID_OUI_FROM_DATABASE=SANMINA-SCI SYSTEM DE MEXICO S.A. DE C.V. + +OUI:4C6371* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:4C63EB* + ID_OUI_FROM_DATABASE=Application Solutions (Electronics and Vision) Ltd + +OUI:4C64D9* + ID_OUI_FROM_DATABASE=Guangdong Leawin Group Co., Ltd + +OUI:4C65A80* + ID_OUI_FROM_DATABASE=WELT Corporation + +OUI:4C65A81* + ID_OUI_FROM_DATABASE=Beijing Bluehalo Internet Inc. + +OUI:4C65A82* + ID_OUI_FROM_DATABASE=Orica Europe Pty Ltd & Co KG + +OUI:4C65A83* + ID_OUI_FROM_DATABASE=Roost + +OUI:4C65A84* + ID_OUI_FROM_DATABASE=Plus One Japan Limited + +OUI:4C65A85* + ID_OUI_FROM_DATABASE=TEL-Electronics Ltd + +OUI:4C65A86* + ID_OUI_FROM_DATABASE=Nuviz Oy + +OUI:4C65A87* + ID_OUI_FROM_DATABASE=Wuhan MoreQuick Network Technology Co., Ltd. + +OUI:4C65A88* + ID_OUI_FROM_DATABASE=Instant Byte, S.L. + +OUI:4C65A89* + ID_OUI_FROM_DATABASE=SHENZHEN LISAIER TRONICS CO.,LTD + +OUI:4C65A8A* + ID_OUI_FROM_DATABASE=Suzhou Embedded Electronic Technology Co., Ltd. + +OUI:4C65A8B* + ID_OUI_FROM_DATABASE=ZMIN Technologies + +OUI:4C65A8C* + ID_OUI_FROM_DATABASE=Fuse + +OUI:4C65A8D* + ID_OUI_FROM_DATABASE=Qingping Technology (Beijing) Co., Ltd. + +OUI:4C65A8E* + ID_OUI_FROM_DATABASE=High Infinity Germany + +OUI:4C6641* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:4C6AF6* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:4C6BE8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4C6C13* + ID_OUI_FROM_DATABASE=IoT Company Solucoes Tecnologicas Ltda + +OUI:4C6E6E* + ID_OUI_FROM_DATABASE=Comnect Technology CO.,LTD + +OUI:4C6F9C* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:4C710C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4C710D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4C72B9* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:4C7367* + ID_OUI_FROM_DATABASE=Genius Bytes Software Solutions GmbH + +OUI:4C73A5* + ID_OUI_FROM_DATABASE=KOVE + +OUI:4C7403* + ID_OUI_FROM_DATABASE=BQ + +OUI:4C7487* + ID_OUI_FROM_DATABASE=Leader Phone Communication Technology Co., Ltd. + +OUI:4C74BF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4C7625* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:4C774F* + ID_OUI_FROM_DATABASE=Embedded Wireless Labs + +OUI:4C776D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4C7872* + ID_OUI_FROM_DATABASE=Cav. Uff. Giacomo Cimberio S.p.A. + +OUI:4C7897* + ID_OUI_FROM_DATABASE=Arrowhead Alarm Products Ltd + +OUI:4C79BA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:4C7A48* + ID_OUI_FROM_DATABASE=Nippon Seiki (Europe) B.V. + +OUI:4C7C5F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4C7F62* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:4C804F* + ID_OUI_FROM_DATABASE=Armstrong Monitoring Corp + +OUI:4C8093* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:4C80BA* + ID_OUI_FROM_DATABASE=Wuhan Tianyu Information Industry Co., Ltd. + +OUI:4C8120* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:4C82CF* + ID_OUI_FROM_DATABASE=Dish Technologies Corp + +OUI:4C83DE* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:4C875D* + ID_OUI_FROM_DATABASE=Bose Corporation + +OUI:4C8B30* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:4C8B55* + ID_OUI_FROM_DATABASE=Grupo Digicon + +OUI:4C8BEF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4C8D79* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4C8ECC* + ID_OUI_FROM_DATABASE=SILKAN SA + +OUI:4C8FA5* + ID_OUI_FROM_DATABASE=Jastec + +OUI:4C90DB* + ID_OUI_FROM_DATABASE=JL Audio + +OUI:4C910C* + ID_OUI_FROM_DATABASE=Lanix Internacional, S.A. de C.V. + +OUI:4C9157* + ID_OUI_FROM_DATABASE=Fujian LANDI Commercial Equipment Co.,Ltd + +OUI:4C917A0* + ID_OUI_FROM_DATABASE=Shenzhen Dangs Science & Technology CO.,LTD + +OUI:4C917A1* + ID_OUI_FROM_DATABASE=Inster Tecnología y Comunicaciones SAU + +OUI:4C917A2* + ID_OUI_FROM_DATABASE=Chongqing Unisinsight Technology Co.,Ltd. + +OUI:4C917A3* + ID_OUI_FROM_DATABASE=Smart Access + +OUI:4C917A4* + ID_OUI_FROM_DATABASE=LumiGrow Inc. + +OUI:4C917A5* + ID_OUI_FROM_DATABASE=mtekvision + +OUI:4C917A6* + ID_OUI_FROM_DATABASE=Openeye + +OUI:4C917A7* + ID_OUI_FROM_DATABASE=S.I.C.E.S. srl + +OUI:4C917A8* + ID_OUI_FROM_DATABASE=Camsat Przemysław Gralak + +OUI:4C917A9* + ID_OUI_FROM_DATABASE=Hangzhou Hangtu Technology Co.,Ltd. + +OUI:4C917AA* + ID_OUI_FROM_DATABASE=Erlab DFS SAS + +OUI:4C917AB* + ID_OUI_FROM_DATABASE=AvertX + +OUI:4C917AC* + ID_OUI_FROM_DATABASE=Alibaba (Beijing) Software Service Inc. + +OUI:4C917AD* + ID_OUI_FROM_DATABASE=Shenzhen bankledger Technology Co, Ltd + +OUI:4C917AE* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:4C9614* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:4C962D* + ID_OUI_FROM_DATABASE=Fresh AB + +OUI:4C98EF* + ID_OUI_FROM_DATABASE=Zeo + +OUI:4C9E80* + ID_OUI_FROM_DATABASE=KYOKKO ELECTRIC Co., Ltd. + +OUI:4C9EE4* + ID_OUI_FROM_DATABASE=Hanyang Navicom Co.,Ltd. + +OUI:4C9EFF* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:4CA003* + ID_OUI_FROM_DATABASE=VITEC + +OUI:4CA161* + ID_OUI_FROM_DATABASE=Rain Bird Corporation + +OUI:4CA515* + ID_OUI_FROM_DATABASE=Baikal Electronics JSC + +OUI:4CA56D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:4CA64D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4CA74B* + ID_OUI_FROM_DATABASE=Alcatel Lucent + +OUI:4CA928* + ID_OUI_FROM_DATABASE=Insensi + +OUI:4CAA16* + ID_OUI_FROM_DATABASE=AzureWave Technologies (Shanghai) Inc. + +OUI:4CAB33* + ID_OUI_FROM_DATABASE=KST technology + +OUI:4CABFC* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:4CAC0A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:4CADA8* + ID_OUI_FROM_DATABASE=PANOPTICS CORP. + +OUI:4CAE1C* + ID_OUI_FROM_DATABASE=SaiNXT Technologies LLP + +OUI:4CAE31* + ID_OUI_FROM_DATABASE=ShengHai Electronics (Shenzhen) Ltd + +OUI:4CAEA3* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:4CB008* + ID_OUI_FROM_DATABASE=Shenzhen Gwelltimes Technology Co.,Ltd + +OUI:4CB0E8* + ID_OUI_FROM_DATABASE=Beijing RongZhi xinghua technology co., LTD + +OUI:4CB16C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4CB199* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:4CB1CD* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:4CB21C* + ID_OUI_FROM_DATABASE=Maxphotonics Co.,Ltd + +OUI:4CB44A* + ID_OUI_FROM_DATABASE=NANOWAVE Technologies Inc. + +OUI:4CB4EA* + ID_OUI_FROM_DATABASE=HRD (S) PTE., LTD. + +OUI:4CB76D* + ID_OUI_FROM_DATABASE=Novi Security + +OUI:4CB81C* + ID_OUI_FROM_DATABASE=SAM Electronics GmbH + +OUI:4CB82C* + ID_OUI_FROM_DATABASE=Cambridge Mobile Telematics, Inc. + +OUI:4CB8B5* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:4CB911* + ID_OUI_FROM_DATABASE=Raisecom Technology CO.,LTD + +OUI:4CB9C8* + ID_OUI_FROM_DATABASE=CONET CO., LTD. + +OUI:4CBAA3* + ID_OUI_FROM_DATABASE=Bison Electronics Inc. + +OUI:4CBB58* + ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd. + +OUI:4CBC42* + ID_OUI_FROM_DATABASE=Shenzhen Hangsheng Electronics Co.,Ltd. + +OUI:4CBC48* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4CBC72* + ID_OUI_FROM_DATABASE=Primex Wireless + +OUI:4CBC980* + ID_OUI_FROM_DATABASE=Charge-Amps AB + +OUI:4CBC981* + ID_OUI_FROM_DATABASE=JSC NIC + +OUI:4CBC982* + ID_OUI_FROM_DATABASE=Quake Global Inc + +OUI:4CBC983* + ID_OUI_FROM_DATABASE=Machine Max + +OUI:4CBC984* + ID_OUI_FROM_DATABASE=Nemon Co., Ltd. + +OUI:4CBC985* + ID_OUI_FROM_DATABASE=Gronic Systems GmbH + +OUI:4CBC986* + ID_OUI_FROM_DATABASE=Humanplus Intelligent Robotics Technology Co.,Ltd. + +OUI:4CBC987* + ID_OUI_FROM_DATABASE=Voegtlin Instruments GmbH + +OUI:4CBC988* + ID_OUI_FROM_DATABASE=Shenzhen Shanling Digital Technology Development Co.,Ltd. + +OUI:4CBC989* + ID_OUI_FROM_DATABASE=Airtex Manufacturing Partnership + +OUI:4CBC98A* + ID_OUI_FROM_DATABASE=Shenzhen Cogitation Technology Co.,Ltd. + +OUI:4CBC98B* + ID_OUI_FROM_DATABASE=Dongguan SmartAction Technology Co.,Ltd + +OUI:4CBC98C* + ID_OUI_FROM_DATABASE=Heliotis AG + +OUI:4CBC98D* + ID_OUI_FROM_DATABASE=Elink Technology (Shenzhen) Co., Limited + +OUI:4CBC98E* + ID_OUI_FROM_DATABASE=Wonder Workshop + +OUI:4CBCA5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:4CBCB4* + ID_OUI_FROM_DATABASE=ABB SpA - DIN Rail + +OUI:4CBD8F* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:4CC00A* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:4CC206* + ID_OUI_FROM_DATABASE=Somfy + +OUI:4CC452* + ID_OUI_FROM_DATABASE=Shang Hai Tyd. Electon Technology Ltd. + +OUI:4CC53E* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:4CC602* + ID_OUI_FROM_DATABASE=Radios, Inc. + +OUI:4CC681* + ID_OUI_FROM_DATABASE=Shenzhen Aisat Electronic Co., Ltd. + +OUI:4CC7D6* + ID_OUI_FROM_DATABASE=FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + +OUI:4CC8A1* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:4CC94F* + ID_OUI_FROM_DATABASE=Nokia + +OUI:4CCA53* + ID_OUI_FROM_DATABASE=Skyera, Inc. + +OUI:4CCBF5* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:4CCC34* + ID_OUI_FROM_DATABASE=Motorola Solutions Inc. + +OUI:4CCC6A* + ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD. + +OUI:4CCE2D* + ID_OUI_FROM_DATABASE=Danlaw Inc + +OUI:4CD08A* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:4CD0CB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4CD1A1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4CD637* + ID_OUI_FROM_DATABASE=Qsono Electronics Co., Ltd + +OUI:4CD7B6* + ID_OUI_FROM_DATABASE=Helmer Scientific + +OUI:4CD98F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:4CD9C4* + ID_OUI_FROM_DATABASE=Magneti Marelli Automotive Electronics (Guangzhou) Co. Ltd + +OUI:4CDC0D* + ID_OUI_FROM_DATABASE=Coral Telecom Limited + +OUI:4CDD31* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:4CDD7D* + ID_OUI_FROM_DATABASE=LHP Telematics LLC + +OUI:4CDF3D* + ID_OUI_FROM_DATABASE=TEAM ENGINEERS ADVANCE TECHNOLOGIES INDIA PVT LTD + +OUI:4CE1730* + ID_OUI_FROM_DATABASE=Beijing Sutongwang E-Business Co., Ltd + +OUI:4CE1731* + ID_OUI_FROM_DATABASE=Nexoforge Inc. + +OUI:4CE1732* + ID_OUI_FROM_DATABASE=Lenovo Data Center Group + +OUI:4CE1733* + ID_OUI_FROM_DATABASE=outpaceIO + +OUI:4CE1734* + ID_OUI_FROM_DATABASE=Huizhou Dehong Technology Co., Ltd. + +OUI:4CE1735* + ID_OUI_FROM_DATABASE=NewVastek + +OUI:4CE1736* + ID_OUI_FROM_DATABASE=DAIKOKU DENKI CO.,LTD. + +OUI:4CE1737* + ID_OUI_FROM_DATABASE=Ersúles Limited + +OUI:4CE1738* + ID_OUI_FROM_DATABASE=Nanjing Tongke Technology Development Co., LTD + +OUI:4CE1739* + ID_OUI_FROM_DATABASE=Shenzhen Evolution Dynamics Co., Ltd. + +OUI:4CE173A* + ID_OUI_FROM_DATABASE=jvi + +OUI:4CE173B* + ID_OUI_FROM_DATABASE=Shanghai Ehong Technology Co.,Ltd + +OUI:4CE173C* + ID_OUI_FROM_DATABASE=REMONDE NETWORK + +OUI:4CE173D* + ID_OUI_FROM_DATABASE=KTC(K-TEL) + +OUI:4CE173E* + ID_OUI_FROM_DATABASE=Plus One Japan Limited + +OUI:4CE175* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4CE176* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:4CE19E* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:4CE1BB* + ID_OUI_FROM_DATABASE=Zhuhai HiFocus Technology Co., Ltd. + +OUI:4CE2F1* + ID_OUI_FROM_DATABASE=sclak srl + +OUI:4CE5AE* + ID_OUI_FROM_DATABASE=Tianjin Beebox Intelligent Technology Co.,Ltd. + +OUI:4CE676* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:4CE933* + ID_OUI_FROM_DATABASE=RailComm, LLC + +OUI:4CE9E4* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:4CEB42* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:4CEBBD* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:4CECEF* + ID_OUI_FROM_DATABASE=Soraa, Inc. + +OUI:4CEDDE* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:4CEDFB* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:4CEEB0* + ID_OUI_FROM_DATABASE=SHC Netzwerktechnik GmbH + +OUI:4CEFC0* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:4CF02E* + ID_OUI_FROM_DATABASE=Vifa Denmark A/S + +OUI:4CF19E* + ID_OUI_FROM_DATABASE=Groupe Atlantic + +OUI:4CF2BF* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:4CF45B* + ID_OUI_FROM_DATABASE=Blue Clover Devices + +OUI:4CF55B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4CF5A0* + ID_OUI_FROM_DATABASE=Scalable Network Technologies Inc + +OUI:4CF737* + ID_OUI_FROM_DATABASE=SamJi Electronics Co., Ltd + +OUI:4CF95D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4CFACA* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:4CFB45* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:4CFBFE* + ID_OUI_FROM_DATABASE=Sercomm Japan Corporation + +OUI:4CFCAA* + ID_OUI_FROM_DATABASE=Tesla,Inc. + +OUI:4CFF12* + ID_OUI_FROM_DATABASE=Fuze Entertainment Co., ltd + +OUI:500084* + ID_OUI_FROM_DATABASE=Siemens Canada + +OUI:50008C* + ID_OUI_FROM_DATABASE=Hong Kong Telecommunications (HKT) Limited + +OUI:50016B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5001BB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5001D9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:500291* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:5004B8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:50053D* + ID_OUI_FROM_DATABASE=CyWee Group Ltd + +OUI:500604* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5006AB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:500959* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:500B32* + ID_OUI_FROM_DATABASE=Foxda Technology Industrial(ShenZhen)Co.,LTD + +OUI:500B910* + ID_OUI_FROM_DATABASE=Igor, Inc. + +OUI:500B911* + ID_OUI_FROM_DATABASE=SPD Development Company Ltd + +OUI:500B912* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:500B913* + ID_OUI_FROM_DATABASE=EWIN TECHNOLOGY LIMITED + +OUI:500B914* + ID_OUI_FROM_DATABASE=Sinope technologies Inc + +OUI:500B915* + ID_OUI_FROM_DATABASE=jiangsu zhongling high-tech CO.,LTD. + +OUI:500B916* + ID_OUI_FROM_DATABASE=Security Alarms & Co. S.A. + +OUI:500B917* + ID_OUI_FROM_DATABASE=Shenzhen Xinfa Electronic Co.,ltd + +OUI:500B918* + ID_OUI_FROM_DATABASE=Panasonic Enterprise Solutions Company + +OUI:500B919* + ID_OUI_FROM_DATABASE=Machfu, Inc. + +OUI:500B91A* + ID_OUI_FROM_DATABASE=New Audio LLC + +OUI:500B91B* + ID_OUI_FROM_DATABASE=thumbzup UK Limited + +OUI:500B91C* + ID_OUI_FROM_DATABASE=Diamond Traffic Products, Inc + +OUI:500B91D* + ID_OUI_FROM_DATABASE=Shenzhen Lucky Sonics Co .,Ltd + +OUI:500B91E* + ID_OUI_FROM_DATABASE=Shenzhen zhong ju Fiber optical Co.Ltd + +OUI:500E6D* + ID_OUI_FROM_DATABASE=TrafficCast International + +OUI:500F80* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:500FF5* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:5011EB* + ID_OUI_FROM_DATABASE=SilverNet Ltd + +OUI:501395* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:501408* + ID_OUI_FROM_DATABASE=AiNET + +OUI:501479* + ID_OUI_FROM_DATABASE=iRobot Corporation + +OUI:5014B5* + ID_OUI_FROM_DATABASE=Richfit Information Technology Co., Ltd + +OUI:5017FF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:50184C* + ID_OUI_FROM_DATABASE=Platina Systems Inc. + +OUI:501AA5* + ID_OUI_FROM_DATABASE=GN Netcom A/S + +OUI:501AC5* + ID_OUI_FROM_DATABASE=Microsoft + +OUI:501B32* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:501CB0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:501CBF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:501D93* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:501E2D* + ID_OUI_FROM_DATABASE=StreamUnlimited Engineering GmbH + +OUI:50206B* + ID_OUI_FROM_DATABASE=Emerson Climate Technologies Transportation Solutions + +OUI:5021EC* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:502267* + ID_OUI_FROM_DATABASE=PixeLINK + +OUI:50252B* + ID_OUI_FROM_DATABASE=Nethra Imaging Incorporated + +OUI:502690* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:5027C7* + ID_OUI_FROM_DATABASE=TECHNART Co.,Ltd + +OUI:50294D* + ID_OUI_FROM_DATABASE=NANJING IOT SENSOR TECHNOLOGY CO,LTD + +OUI:5029F5* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:502A7E* + ID_OUI_FROM_DATABASE=Smart electronic GmbH + +OUI:502A8B* + ID_OUI_FROM_DATABASE=Telekom Research and Development Sdn Bhd + +OUI:502B73* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:502B98* + ID_OUI_FROM_DATABASE=Es-tech International + +OUI:502CC6* + ID_OUI_FROM_DATABASE=GREE ELECTRIC APPLIANCES, INC. OF ZHUHAI + +OUI:502D1D* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:502DA2* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:502DBB* + ID_OUI_FROM_DATABASE=GD Midea Air-Conditioning Equipment Co.,Ltd. + +OUI:502DF4* + ID_OUI_FROM_DATABASE=Phytec Messtechnik GmbH + +OUI:502E5C* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:502ECE* + ID_OUI_FROM_DATABASE=Asahi Electronics Co.,Ltd + +OUI:502FA8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5031AD* + ID_OUI_FROM_DATABASE=ABB Global Industries and Services Private Limited + +OUI:503237* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:503275* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50338B* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:5033F0* + ID_OUI_FROM_DATABASE=YICHEN (SHENZHEN) TECHNOLOGY CO.LTD + +OUI:503955* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:503A7D* + ID_OUI_FROM_DATABASE=AlphaTech PLC Int’l Co., Ltd. + +OUI:503AA0* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:503CC4* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:503CEA* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:503DA1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:503DE5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:503E7C* + ID_OUI_FROM_DATABASE=LeiShen Intelligent System Co.Ltd + +OUI:503EAA* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:503F56* + ID_OUI_FROM_DATABASE=Syncmold Enterprise Corp + +OUI:503F98* + ID_OUI_FROM_DATABASE=CMITECH + +OUI:504061* + ID_OUI_FROM_DATABASE=Nokia + +OUI:5041B9* + ID_OUI_FROM_DATABASE=I-O DATA DEVICE,INC. + +OUI:5043B9* + ID_OUI_FROM_DATABASE=OktoInform RUS + +OUI:5045F7* + ID_OUI_FROM_DATABASE=Liuhe Intelligence Technology Ltd. + +OUI:50465D* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:5048EB* + ID_OUI_FROM_DATABASE=BEIJING HAIHEJINSHENG NETWORK TECHNOLOGY CO. LTD. + +OUI:504A5E* + ID_OUI_FROM_DATABASE=Masimo Corporation + +OUI:504A6E* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:504B5B* + ID_OUI_FROM_DATABASE=CONTROLtronic GmbH + +OUI:504C7E* + ID_OUI_FROM_DATABASE=THE 41ST INSTITUTE OF CETC + +OUI:504EDC* + ID_OUI_FROM_DATABASE=Ping Communication + +OUI:504F94* + ID_OUI_FROM_DATABASE=Loxone Electronics GmbH + +OUI:50502A* + ID_OUI_FROM_DATABASE=Egardia + +OUI:505065* + ID_OUI_FROM_DATABASE=TAKT Corporation + +OUI:5050A4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5050CE* + ID_OUI_FROM_DATABASE=Hangzhou Dianyixia Communication Technology Co. Ltd. + +OUI:5051A9* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:5052D2* + ID_OUI_FROM_DATABASE=Hangzhou Telin Technologies Co., Limited + +OUI:505527* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:505663* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:5056A8* + ID_OUI_FROM_DATABASE=Jolla Ltd + +OUI:5056BF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50579C* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:5057A8* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:505800* + ID_OUI_FROM_DATABASE=WyTec International, Inc. + +OUI:50584F* + ID_OUI_FROM_DATABASE=waytotec,Inc. + +OUI:505967* + ID_OUI_FROM_DATABASE=Intent Solutions Inc + +OUI:505AC6* + ID_OUI_FROM_DATABASE=GUANGDONG SUPER TELECOM CO.,LTD. + +OUI:505BC2* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:505DAC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:505FB5* + ID_OUI_FROM_DATABASE=Askey Computer Corp. + +OUI:506028* + ID_OUI_FROM_DATABASE=Xirrus Inc. + +OUI:506184* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:5061BF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5061D6* + ID_OUI_FROM_DATABASE=Indu-Sol GmbH + +OUI:5062550* + ID_OUI_FROM_DATABASE=Ufanet SC + +OUI:5062551* + ID_OUI_FROM_DATABASE=Hagiwara Solutions Co., Ltd + +OUI:5062552* + ID_OUI_FROM_DATABASE=ShenZhen ChuangMo Electronics Technology Co., Ltd + +OUI:5062553* + ID_OUI_FROM_DATABASE=Hypertech Advance Co., LTD + +OUI:5062554* + ID_OUI_FROM_DATABASE=XSLAB Inc. + +OUI:5062555* + ID_OUI_FROM_DATABASE=Suzhou Ruixinjie Information Technology Co.,Ltd + +OUI:5062556* + ID_OUI_FROM_DATABASE=Shenzhen Sinway South Technology Co., Ltd + +OUI:5062557* + ID_OUI_FROM_DATABASE=AVTECH Software, Inc. + +OUI:5062558* + ID_OUI_FROM_DATABASE=Roda industrial development Co.,Ltd. + +OUI:5062559* + ID_OUI_FROM_DATABASE=Southern Ground Audio LLC + +OUI:506255A* + ID_OUI_FROM_DATABASE=CCTV Manufacturer + +OUI:506255B* + ID_OUI_FROM_DATABASE=CHENGDU COVE TECHNOLOGY CO.,LTD + +OUI:506255C* + ID_OUI_FROM_DATABASE=AED Distribution + +OUI:506255D* + ID_OUI_FROM_DATABASE=COTT Electronics + +OUI:506255E* + ID_OUI_FROM_DATABASE=SHINSOFT CO., LTD. + +OUI:506313* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:50642B* + ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD + +OUI:506441* + ID_OUI_FROM_DATABASE=Greenlee + +OUI:506583* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:5065F3* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:506787* + ID_OUI_FROM_DATABASE=Planet Networks + +OUI:5067AE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5067F0* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:50680A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:506A03* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:506B4B* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:506B8D* + ID_OUI_FROM_DATABASE=Nutanix + +OUI:506CBE* + ID_OUI_FROM_DATABASE=InnosiliconTechnology Ltd + +OUI:506E92* + ID_OUI_FROM_DATABASE=Innocent Technology Co., Ltd. + +OUI:506F77* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:506F98* + ID_OUI_FROM_DATABASE=Sehaj Synergy Technologies Private Limited + +OUI:506F9A* + ID_OUI_FROM_DATABASE=Wi-Fi Alliance + +OUI:5070E5* + ID_OUI_FROM_DATABASE=He Shan World Fair Electronics Technology Limited + +OUI:507224* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:50724D* + ID_OUI_FROM_DATABASE=BEG Brueck Electronic GmbH + +OUI:5075F1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:507691* + ID_OUI_FROM_DATABASE=Tekpea, Inc. + +OUI:5076A6* + ID_OUI_FROM_DATABASE=Ecil Informatica Ind. Com. Ltda + +OUI:5076AF* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:507705* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5078B3* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:50795B* + ID_OUI_FROM_DATABASE=Interexport Telecomunicaciones S.A. + +OUI:507A55* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:507AC5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:507B9D* + ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd + +OUI:507D02* + ID_OUI_FROM_DATABASE=BIODIT + +OUI:507E5D* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:50804A* + ID_OUI_FROM_DATABASE=Quectel Wireless Solutions Co., Ltd. + +OUI:5082D5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:508569* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:508789* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5087B8* + ID_OUI_FROM_DATABASE=Nuvyyo Inc + +OUI:508965* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:508A0F* + ID_OUI_FROM_DATABASE=SHENZHEN FISE TECHNOLOGY HOLDING CO.,LTD. + +OUI:508A42* + ID_OUI_FROM_DATABASE=Uptmate Technology Co., LTD + +OUI:508ACB* + ID_OUI_FROM_DATABASE=SHENZHEN MAXMADE TECHNOLOGY CO., LTD. + +OUI:508C77* + ID_OUI_FROM_DATABASE=DIRMEIER Schanktechnik GmbH &Co KG + +OUI:508CB1* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:508CF5* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:508D6F* + ID_OUI_FROM_DATABASE=CHAHOO Limited + +OUI:508F4C* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:5092B9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50934F* + ID_OUI_FROM_DATABASE=Gradual Tecnologia Ltda. + +OUI:509551* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:509744* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:509772* + ID_OUI_FROM_DATABASE=Westinghouse Digital + +OUI:509871* + ID_OUI_FROM_DATABASE=Inventum Technologies Private Limited + +OUI:5098B8* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:5098F3* + ID_OUI_FROM_DATABASE=Rheem Australia Pty Ltd + +OUI:509A4C* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:509EA7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:509F27* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:509F3B* + ID_OUI_FROM_DATABASE=OI ELECTRIC CO.,LTD + +OUI:50A009* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:50A054* + ID_OUI_FROM_DATABASE=Actineon + +OUI:50A0A4* + ID_OUI_FROM_DATABASE=Nokia + +OUI:50A0BF* + ID_OUI_FROM_DATABASE=Alba Fiber Systems Inc. + +OUI:50A132* + ID_OUI_FROM_DATABASE=Shenzhen MiaoMing Intelligent Technology Co.,Ltd + +OUI:50A4C8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50A4D00* + ID_OUI_FROM_DATABASE=TRAXENS + +OUI:50A4D01* + ID_OUI_FROM_DATABASE=Beijing ANTVR Technology Co., LTD + +OUI:50A4D02* + ID_OUI_FROM_DATABASE=Seneco A/S + +OUI:50A4D03* + ID_OUI_FROM_DATABASE=Guangzhou Hysoon Electronic Co., Ltd. + +OUI:50A4D04* + ID_OUI_FROM_DATABASE=Raven Industries Inc. + +OUI:50A4D05* + ID_OUI_FROM_DATABASE=TREXOM S.r.l. + +OUI:50A4D06* + ID_OUI_FROM_DATABASE=PointGrab + +OUI:50A4D07* + ID_OUI_FROM_DATABASE=Shanghai Pujiang Smart Card Systems Co., Ltd. + +OUI:50A4D08* + ID_OUI_FROM_DATABASE=XinLian'AnBao(Beijing)Technology Co.,LTD. + +OUI:50A4D09* + ID_OUI_FROM_DATABASE=OEM PRODUCTION INC. + +OUI:50A4D0A* + ID_OUI_FROM_DATABASE=Changsha SinoCare, Inc + +OUI:50A4D0B* + ID_OUI_FROM_DATABASE=ZHENG DIAN ELECTRONICS LIMITED + +OUI:50A4D0C* + ID_OUI_FROM_DATABASE=Beijing YangLian Networks Technology co., LTD + +OUI:50A4D0D* + ID_OUI_FROM_DATABASE=Axel Technology + +OUI:50A4D0E* + ID_OUI_FROM_DATABASE=Sagetech Corporation + +OUI:50A67F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:50A6E3* + ID_OUI_FROM_DATABASE=David Clark Company + +OUI:50A715* + ID_OUI_FROM_DATABASE=Aboundi, Inc. + +OUI:50A72B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:50A733* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:50A83A* + ID_OUI_FROM_DATABASE=S Mobile Devices Limited + +OUI:50A9DE* + ID_OUI_FROM_DATABASE=Smartcom - Bulgaria AD + +OUI:50AB3E* + ID_OUI_FROM_DATABASE=Qibixx AG + +OUI:50ABBF* + ID_OUI_FROM_DATABASE=Hoseo Telecom + +OUI:50AD71* + ID_OUI_FROM_DATABASE=Tessolve Semiconductor Private Limited + +OUI:50AD92* + ID_OUI_FROM_DATABASE=NX Technologies + +OUI:50ADD5* + ID_OUI_FROM_DATABASE=Dynalec Corporation + +OUI:50AF4D* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:50AF73* + ID_OUI_FROM_DATABASE=Shenzhen Bitland Information Technology Co., Ltd. + +OUI:50B363* + ID_OUI_FROM_DATABASE=Digitron da Amazonia S/A + +OUI:50B695* + ID_OUI_FROM_DATABASE=Micropoint Biotechnologies,Inc. + +OUI:50B7C3* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50B888* + ID_OUI_FROM_DATABASE=wi2be Tecnologia S/A + +OUI:50B8A2* + ID_OUI_FROM_DATABASE=ImTech Technologies LLC, + +OUI:50BC96* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:50BD5F* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:50C006* + ID_OUI_FROM_DATABASE=Carmanah Signs + +OUI:50C271* + ID_OUI_FROM_DATABASE=SECURETECH INC + +OUI:50C4DD* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:50C58D* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:50C6AD* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:50C7BF* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:50C8E5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50C971* + ID_OUI_FROM_DATABASE=GN Netcom A/S + +OUI:50C9A0* + ID_OUI_FROM_DATABASE=SKIPPER AS + +OUI:50CCF8* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:50CD22* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:50CD32* + ID_OUI_FROM_DATABASE=NanJing Chaoran Science & Technology Co.,Ltd. + +OUI:50CE75* + ID_OUI_FROM_DATABASE=Measy Electronics Co., Ltd. + +OUI:50CEE3* + ID_OUI_FROM_DATABASE=Gigafirm.co.LTD + +OUI:50D213* + ID_OUI_FROM_DATABASE=CviLux Corporation + +OUI:50D274* + ID_OUI_FROM_DATABASE=Steffes Corporation + +OUI:50D2F5* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd + +OUI:50D37F* + ID_OUI_FROM_DATABASE=Yu Fly Mikly Way Science and Technology Co., Ltd. + +OUI:50D4F7* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:50D59C* + ID_OUI_FROM_DATABASE=Thai Habel Industrial Co., Ltd. + +OUI:50D6D7* + ID_OUI_FROM_DATABASE=Takahata Precision + +OUI:50D753* + ID_OUI_FROM_DATABASE=CONELCOM GmbH + +OUI:50DA00* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:50DB3F* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:50DCE7* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:50DCFC* + ID_OUI_FROM_DATABASE=ECOCOM + +OUI:50DD4F* + ID_OUI_FROM_DATABASE=Automation Components, Inc + +OUI:50DE06* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:50DE190* + ID_OUI_FROM_DATABASE=Telic AG + +OUI:50DE191* + ID_OUI_FROM_DATABASE=Clear Flow by Antiference + +OUI:50DE192* + ID_OUI_FROM_DATABASE=SPII SPA + +OUI:50DE193* + ID_OUI_FROM_DATABASE=TRAXENS + +OUI:50DE194* + ID_OUI_FROM_DATABASE=Langogo Technology Co., Ltd. + +OUI:50DE195* + ID_OUI_FROM_DATABASE=Bliq B.V. + +OUI:50DE196* + ID_OUI_FROM_DATABASE=OCEANCCTV LTD + +OUI:50DE197* + ID_OUI_FROM_DATABASE=Tianjin Natianal Health Technology Co.,Ltd + +OUI:50DE198* + ID_OUI_FROM_DATABASE=IVATIV, INC + +OUI:50DE199* + ID_OUI_FROM_DATABASE=AEG Identifikationssysteme GmbH + +OUI:50DE19A* + ID_OUI_FROM_DATABASE=Tannak International AB + +OUI:50DE19B* + ID_OUI_FROM_DATABASE=BRAINWARE TERAHERTA INFORMATION TECHNOLOGY CO.,LTD. + +OUI:50DE19C* + ID_OUI_FROM_DATABASE=Shenzhen Vipstech Co., Ltd + +OUI:50DE19D* + ID_OUI_FROM_DATABASE=Penny & Giles Aerospace Ltd + +OUI:50DE19E* + ID_OUI_FROM_DATABASE=Private + +OUI:50DF95* + ID_OUI_FROM_DATABASE=Lytx + +OUI:50E085* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:50E0C7* + ID_OUI_FROM_DATABASE=TurControlSystme AG + +OUI:50E0EF* + ID_OUI_FROM_DATABASE=Nokia + +OUI:50E14A* + ID_OUI_FROM_DATABASE=Private + +OUI:50E549* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:50E666* + ID_OUI_FROM_DATABASE=Shenzhen Techtion Electronics Co., Ltd. + +OUI:50E971* + ID_OUI_FROM_DATABASE=Jibo, Inc. + +OUI:50EAD6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:50EB1A* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:50EB71* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:50EC50* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd + +OUI:50ED78* + ID_OUI_FROM_DATABASE=Changzhou Yongse Infotech Co.,Ltd + +OUI:50ED94* + ID_OUI_FROM_DATABASE=EGATEL SL + +OUI:50F003* + ID_OUI_FROM_DATABASE=Open Stack, Inc. + +OUI:50F0D3* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50F14A* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:50F43C* + ID_OUI_FROM_DATABASE=Leeo Inc + +OUI:50F520* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50F5DA* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:50F61A* + ID_OUI_FROM_DATABASE=Kunshan JADE Technologies co., Ltd. + +OUI:50F722* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:50F8A5* + ID_OUI_FROM_DATABASE=eWBM Co., Ltd. + +OUI:50FA84* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:50FAAB* + ID_OUI_FROM_DATABASE=L-tek d.o.o. + +OUI:50FC30* + ID_OUI_FROM_DATABASE=Treehouse Labs + +OUI:50FC9F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:50FEF2* + ID_OUI_FROM_DATABASE=Sify Technologies Ltd + +OUI:50FF20* + ID_OUI_FROM_DATABASE=Keenetic Limited + +OUI:50FF990* + ID_OUI_FROM_DATABASE=Simicon + +OUI:50FF991* + ID_OUI_FROM_DATABASE=Coyote Sytem + +OUI:50FF992* + ID_OUI_FROM_DATABASE=SHENZHEN KINGVT ELECTRONICS CO.,LTD + +OUI:50FF993* + ID_OUI_FROM_DATABASE=Yongjing Shanghai Electronic Science and Technology + +OUI:50FF994* + ID_OUI_FROM_DATABASE=IPC Global + +OUI:50FF995* + ID_OUI_FROM_DATABASE=Garrison Technology + +OUI:50FF996* + ID_OUI_FROM_DATABASE=LEGEND WINNER LIMITED + +OUI:50FF997* + ID_OUI_FROM_DATABASE=Honeywell International + +OUI:50FF998* + ID_OUI_FROM_DATABASE=Dolphin Concepts Limited + +OUI:50FF999* + ID_OUI_FROM_DATABASE=Sea Eagle Optoelectronic Information Technology(Tianjin)co,Ltd + +OUI:50FF99A* + ID_OUI_FROM_DATABASE=metraTec GmbH + +OUI:50FF99B* + ID_OUI_FROM_DATABASE=Sichuan Dowlab Electronics Technology Co. Ltd + +OUI:50FF99C* + ID_OUI_FROM_DATABASE=Goetting KG + +OUI:50FF99D* + ID_OUI_FROM_DATABASE=Shenzhen Haipengxin Electronic Co., Ltd. + +OUI:50FF99E* + ID_OUI_FROM_DATABASE=Informa LLC + +OUI:540237* + ID_OUI_FROM_DATABASE=Teltronic AG + +OUI:540384* + ID_OUI_FROM_DATABASE=Hongkong Nano IC Technologies Co., Ltd + +OUI:5403F5* + ID_OUI_FROM_DATABASE=EBN Technology Corp. + +OUI:540496* + ID_OUI_FROM_DATABASE=Gigawave LTD + +OUI:5404A6* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:540536* + ID_OUI_FROM_DATABASE=Vivago Oy + +OUI:54055F* + ID_OUI_FROM_DATABASE=Alcatel Lucent + +OUI:540593* + ID_OUI_FROM_DATABASE=WOORI ELEC Co.,Ltd + +OUI:54068B* + ID_OUI_FROM_DATABASE=Ningbo Deli Kebei Technology Co.LTD + +OUI:540955* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:54098D* + ID_OUI_FROM_DATABASE=deister electronic GmbH + +OUI:540DF9* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:541031* + ID_OUI_FROM_DATABASE=SMARTO + +OUI:5410EC* + ID_OUI_FROM_DATABASE=Microchip Technology Inc. + +OUI:54112F* + ID_OUI_FROM_DATABASE=Sulzer Pump Solutions Finland Oy + +OUI:54115F* + ID_OUI_FROM_DATABASE=Atamo Pty Ltd + +OUI:541310* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:541379* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:541473* + ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited + +OUI:5414FD* + ID_OUI_FROM_DATABASE=Orbbec 3D Technology International + +OUI:541589* + ID_OUI_FROM_DATABASE=MCS Logic Inc. + +OUI:5419C8* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:541B5D* + ID_OUI_FROM_DATABASE=Techno-Innov + +OUI:541DFB* + ID_OUI_FROM_DATABASE=Freestyle Energy Ltd + +OUI:541E56* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:541FD5* + ID_OUI_FROM_DATABASE=Advantage Electronics + +OUI:542018* + ID_OUI_FROM_DATABASE=Tely Labs + +OUI:542160* + ID_OUI_FROM_DATABASE=Alula + +OUI:5422F8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:5425EA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:542696* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:54271E* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:542758* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:54276C* + ID_OUI_FROM_DATABASE=Jiangsu Houge Technology Corp. + +OUI:54278D* + ID_OUI_FROM_DATABASE=NXP (China) Management Ltd. + +OUI:542A1B* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:542A9C* + ID_OUI_FROM_DATABASE=LSY Defense, LLC. + +OUI:542AA2* + ID_OUI_FROM_DATABASE=Alpha Networks Inc. + +OUI:542B57* + ID_OUI_FROM_DATABASE=Night Owl SP + +OUI:542B8D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:542BDE* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:542CEA* + ID_OUI_FROM_DATABASE=PROTECTRON + +OUI:542F89* + ID_OUI_FROM_DATABASE=Euclid Laboratories, Inc. + +OUI:542F8A* + ID_OUI_FROM_DATABASE=TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO + +OUI:543131* + ID_OUI_FROM_DATABASE=Raster Vision Ltd + +OUI:5433CB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5434EF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:543530* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:5435DF* + ID_OUI_FROM_DATABASE=Symeo GmbH + +OUI:54369B* + ID_OUI_FROM_DATABASE=1Verge Internet Technology (Beijing) Co., Ltd. + +OUI:543968* + ID_OUI_FROM_DATABASE=Edgewater Networks Inc + +OUI:5439DF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:543B30* + ID_OUI_FROM_DATABASE=duagon AG + +OUI:543D37* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:543E64* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:5440AD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:544249* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:544408* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:54466B* + ID_OUI_FROM_DATABASE=Shenzhen CZTIC Electronic Technology Co., Ltd + +OUI:544741* + ID_OUI_FROM_DATABASE=XCHENG HOLDING + +OUI:5447D3* + ID_OUI_FROM_DATABASE=TSAT AS + +OUI:544810* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:54489C* + ID_OUI_FROM_DATABASE=CDOUBLES ELECTRONICS CO. LTD. + +OUI:5448E6* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co.,Ltd + +OUI:544A00* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:544A05* + ID_OUI_FROM_DATABASE=wenglor sensoric gmbh + +OUI:544A16* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:544B8C* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:544E45* + ID_OUI_FROM_DATABASE=Private + +OUI:544E90* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:54511B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:545146* + ID_OUI_FROM_DATABASE=AMG Systems Ltd. + +OUI:5453ED* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:545414* + ID_OUI_FROM_DATABASE=Digital RF Corea, Inc + +OUI:5454CF* + ID_OUI_FROM_DATABASE=PROBEDIGITAL CO.,LTD + +OUI:545AA6* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:545EBD* + ID_OUI_FROM_DATABASE=NL Technologies + +OUI:545FA9* + ID_OUI_FROM_DATABASE=Teracom Limited + +OUI:546009* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:546172* + ID_OUI_FROM_DATABASE=ZODIAC AEROSPACE SAS + +OUI:5461EA* + ID_OUI_FROM_DATABASE=Zaplox AB + +OUI:5462E2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5464D9* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:546503* + ID_OUI_FROM_DATABASE=Quectel Wireless Solutions Co., Ltd. + +OUI:5465DE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:54666C* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:546751* + ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. + +OUI:546AD8* + ID_OUI_FROM_DATABASE=Elster Water Metering + +OUI:546C0E* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:546D52* + ID_OUI_FROM_DATABASE=TOPVIEW OPTRONICS CORP. + +OUI:5471DD* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:54724F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:547398* + ID_OUI_FROM_DATABASE=Toyo Electronics Corporation + +OUI:5474E6* + ID_OUI_FROM_DATABASE=Webtech Wireless + +OUI:547595* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:5475D0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:54781A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:547975* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:547A52* + ID_OUI_FROM_DATABASE=CTE International srl + +OUI:547C69* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:547DCD* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:547F54* + ID_OUI_FROM_DATABASE=INGENICO + +OUI:547FA8* + ID_OUI_FROM_DATABASE=TELCO systems, s.r.o. + +OUI:547FBC* + ID_OUI_FROM_DATABASE=iodyne + +OUI:547FEE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:548028* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:54812D* + ID_OUI_FROM_DATABASE=PAX Computer Technology(Shenzhen) Ltd. + +OUI:5481AD* + ID_OUI_FROM_DATABASE=Eagle Research Corporation + +OUI:54833A* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:54847B* + ID_OUI_FROM_DATABASE=Digital Devices GmbH + +OUI:5486BC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:54880E* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:548922* + ID_OUI_FROM_DATABASE=Zelfy Inc + +OUI:548998* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:548CA0* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:548D5A* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:549209* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5492BE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:549359* + ID_OUI_FROM_DATABASE=SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. + +OUI:549478* + ID_OUI_FROM_DATABASE=Silvershore Technology Partners + +OUI:549963* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:549A110* + ID_OUI_FROM_DATABASE=Shenzhen Excera Technology Co.,Ltd. + +OUI:549A111* + ID_OUI_FROM_DATABASE=SpearX Inc. + +OUI:549A112* + ID_OUI_FROM_DATABASE=Torrap Design Limited + +OUI:549A113* + ID_OUI_FROM_DATABASE=Royal Boon Edam International BV + +OUI:549A114* + ID_OUI_FROM_DATABASE=eTauro LLC + +OUI:549A115* + ID_OUI_FROM_DATABASE=Elotech Industrieelektronik GmbH + +OUI:549A116* + ID_OUI_FROM_DATABASE=Orient Direct, Inc. + +OUI:549A117* + ID_OUI_FROM_DATABASE=Niveo International BV + +OUI:549A118* + ID_OUI_FROM_DATABASE=Tite, Inc. + +OUI:549A119* + ID_OUI_FROM_DATABASE=Alfen BV + +OUI:549A11A* + ID_OUI_FROM_DATABASE=VendNovation LLC + +OUI:549A11B* + ID_OUI_FROM_DATABASE=Elite Silicon Technology, Inc. + +OUI:549A11C* + ID_OUI_FROM_DATABASE=Xi'an Hua Fan Technology Co.,Ltd. + +OUI:549A11D* + ID_OUI_FROM_DATABASE=Hangzhou duotin Technology Co., Ltd. + +OUI:549A11E* + ID_OUI_FROM_DATABASE=Beijing HTSmartech Co.,Ltd + +OUI:549A11F* + ID_OUI_FROM_DATABASE=Private + +OUI:549A16* + ID_OUI_FROM_DATABASE=Uzushio Electric Co.,Ltd. + +OUI:549A4C* + ID_OUI_FROM_DATABASE=GUANGDONG HOMECARE TECHNOLOGY CO.,LTD. + +OUI:549B12* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:549B72* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:549C27* + ID_OUI_FROM_DATABASE=Plasma Cloud Limited + +OUI:549D85* + ID_OUI_FROM_DATABASE=EnerAccess inc + +OUI:549F13* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:549F35* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:549FAE* + ID_OUI_FROM_DATABASE=iBASE Gaming Inc + +OUI:54A04F* + ID_OUI_FROM_DATABASE=t-mac Technologies Ltd + +OUI:54A050* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:54A274* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:54A31B* + ID_OUI_FROM_DATABASE=Shenzhen Linkworld Technology Co,.LTD + +OUI:54A3FA* + ID_OUI_FROM_DATABASE=BQT Solutions (Australia)Pty Ltd + +OUI:54A4930* + ID_OUI_FROM_DATABASE=Intelligent Surveillance Corp + +OUI:54A4931* + ID_OUI_FROM_DATABASE=ShenZhen Smart&Aspiration Co.,LTD + +OUI:54A4932* + ID_OUI_FROM_DATABASE=genua GmbH + +OUI:54A4933* + ID_OUI_FROM_DATABASE=I-MOON TECHNOLOGY CO., LIMITED + +OUI:54A4934* + ID_OUI_FROM_DATABASE=Shenzhen C & D Electronics Co., Ltd. + +OUI:54A4935* + ID_OUI_FROM_DATABASE=AUSOUNDS INTELLIGENCE, LLC + +OUI:54A4936* + ID_OUI_FROM_DATABASE=Hannto Technology Co., Ltd + +OUI:54A4937* + ID_OUI_FROM_DATABASE=RED Hydrogen LLC + +OUI:54A4938* + ID_OUI_FROM_DATABASE=Chengdu EVECCA Technology Co.,Ltd. + +OUI:54A4939* + ID_OUI_FROM_DATABASE=Do Easy International Limited + +OUI:54A493A* + ID_OUI_FROM_DATABASE=Wonders Technology Co., Ltd. + +OUI:54A493B* + ID_OUI_FROM_DATABASE=Advice + +OUI:54A493C* + ID_OUI_FROM_DATABASE=BJ COTYTECH TECHNOLOGY CO.,LTD + +OUI:54A493D* + ID_OUI_FROM_DATABASE=ASSEM TECHNOLOGY CO.,LTD. + +OUI:54A493E* + ID_OUI_FROM_DATABASE=Nederman Holding AB + +OUI:54A51B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:54A54B* + ID_OUI_FROM_DATABASE=NSC Communications Siberia Ltd + +OUI:54A619* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:54A65C* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:54A703* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:54A9D4* + ID_OUI_FROM_DATABASE=Minibar Systems + +OUI:54AB3A* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:54AE27* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:54AED0* + ID_OUI_FROM_DATABASE=DASAN Networks, Inc. + +OUI:54B121* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:54B203* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:54B56C* + ID_OUI_FROM_DATABASE=Xi'an NovaStar Tech Co., Ltd + +OUI:54B620* + ID_OUI_FROM_DATABASE=SUHDOL E&C Co.Ltd. + +OUI:54B753* + ID_OUI_FROM_DATABASE=Hunan Fenghui Yinjia Science And Technology Co.,Ltd + +OUI:54B7E5* + ID_OUI_FROM_DATABASE=Rayson Technology Co., Ltd. + +OUI:54B802* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:54B80A* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:54BAD6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:54BD79* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:54BE53* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:54BEF7* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:54BF64* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:54C33E* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:54C415* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:54C57A* + ID_OUI_FROM_DATABASE=Sunnovo International Limited + +OUI:54C80F* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:54C9DF* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:54CD10* + ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co.,Ltd. + +OUI:54CDA7* + ID_OUI_FROM_DATABASE=Fujian Shenzhou Electronic Co.,Ltd + +OUI:54CDEE* + ID_OUI_FROM_DATABASE=ShenZhen Apexis Electronic Co.,Ltd + +OUI:54CE69* + ID_OUI_FROM_DATABASE=Hikari Trading Co.,Ltd. + +OUI:54D0B4* + ID_OUI_FROM_DATABASE=Xiamen Four-Faith Communication Technology Co.,Ltd + +OUI:54D0ED* + ID_OUI_FROM_DATABASE=AXIM Communications + +OUI:54D163* + ID_OUI_FROM_DATABASE=MAX-TECH,INC + +OUI:54D1B0* + ID_OUI_FROM_DATABASE=Universal Laser Systems, Inc + +OUI:54D272* + ID_OUI_FROM_DATABASE=Nuki Home Solutions GmbH + +OUI:54D46F* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:54D751* + ID_OUI_FROM_DATABASE=Proximus + +OUI:54D9E4* + ID_OUI_FROM_DATABASE=BRILLIANTTS CO., LTD + +OUI:54DC1D* + ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + +OUI:54DED0* + ID_OUI_FROM_DATABASE=Sevio Srl + +OUI:54DF00* + ID_OUI_FROM_DATABASE=Ulterius Technologies, LLC + +OUI:54DF24* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:54DF63* + ID_OUI_FROM_DATABASE=Intrakey technologies GmbH + +OUI:54E019* + ID_OUI_FROM_DATABASE=Ring LLC + +OUI:54E032* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:54E061* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:54E140* + ID_OUI_FROM_DATABASE=INGENICO + +OUI:54E1AD* + ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd + +OUI:54E2C8* + ID_OUI_FROM_DATABASE=Dongguan Aoyuan Electronics Technology Co., Ltd + +OUI:54E2E0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:54E3B0* + ID_OUI_FROM_DATABASE=JVL Industri Elektronik + +OUI:54E3F6* + ID_OUI_FROM_DATABASE=Alcatel-Lucent + +OUI:54E43A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:54E4A9* + ID_OUI_FROM_DATABASE=BHR Tech GmbH + +OUI:54E4BD* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:54E63F* + ID_OUI_FROM_DATABASE=ShenZhen LingKeWeiEr Technology Co., Ltd. + +OUI:54E6FC* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:54E7D5* + ID_OUI_FROM_DATABASE=Sun Cupid Technology (HK) LTD + +OUI:54EAA8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:54EC2F* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:54EDA3* + ID_OUI_FROM_DATABASE=Navdy, Inc. + +OUI:54EE75* + ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd. + +OUI:54EF44* + ID_OUI_FROM_DATABASE=Lumi United Technology Co., Ltd + +OUI:54EF92* + ID_OUI_FROM_DATABASE=Shenzhen Elink Technology Co., LTD + +OUI:54EFFE* + ID_OUI_FROM_DATABASE=Fullpower Technologies, Inc. + +OUI:54F201* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:54F294* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:54F5B6* + ID_OUI_FROM_DATABASE=ORIENTAL PACIFIC INTERNATIONAL LIMITED + +OUI:54F666* + ID_OUI_FROM_DATABASE=Berthold Technologies GmbH and Co.KG + +OUI:54F6C5* + ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD + +OUI:54F876* + ID_OUI_FROM_DATABASE=ABB AG + +OUI:54FA3E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:54FA96* + ID_OUI_FROM_DATABASE=Nokia + +OUI:54FB58* + ID_OUI_FROM_DATABASE=WISEWARE, Lda + +OUI:54FCF0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:54FDBF* + ID_OUI_FROM_DATABASE=Scheidt & Bachmann GmbH + +OUI:54FF82* + ID_OUI_FROM_DATABASE=Davit Solution co. + +OUI:54FFCF* + ID_OUI_FROM_DATABASE=Mopria Alliance + +OUI:5800BB* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:5800E3* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:5803FB* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:580454* + ID_OUI_FROM_DATABASE=ICOMM HK LIMITED + +OUI:5804CB* + ID_OUI_FROM_DATABASE=Tianjin Huisun Technology Co.,Ltd. + +OUI:580528* + ID_OUI_FROM_DATABASE=LABRIS NETWORKS + +OUI:580556* + ID_OUI_FROM_DATABASE=Elettronica GF S.r.L. + +OUI:5808FA* + ID_OUI_FROM_DATABASE=Fiber Optic & telecommunication INC. + +OUI:580943* + ID_OUI_FROM_DATABASE=Private + +OUI:5809E5* + ID_OUI_FROM_DATABASE=Kivic Inc. + +OUI:580A20* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:58108C* + ID_OUI_FROM_DATABASE=Intelbras + +OUI:581243* + ID_OUI_FROM_DATABASE=AcSiP Technology Corp. + +OUI:581626* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:5816D7* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:58170C* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:5819F8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:581CBD* + ID_OUI_FROM_DATABASE=Affinegy + +OUI:581D91* + ID_OUI_FROM_DATABASE=Advanced Mobile Telecom co.,ltd. + +OUI:581F28* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:581F67* + ID_OUI_FROM_DATABASE=Open-m technology limited + +OUI:581FAA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:581FEF* + ID_OUI_FROM_DATABASE=Tuttnaer LTD + +OUI:582059* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:5820B1* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:582136* + ID_OUI_FROM_DATABASE=KMB systems, s.r.o. + +OUI:5821E9* + ID_OUI_FROM_DATABASE=TWPI + +OUI:58238C* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:582575* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:58278C* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:582AF7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:582BDB* + ID_OUI_FROM_DATABASE=Pax AB + +OUI:582D34* + ID_OUI_FROM_DATABASE=Qingping Electronics (Suzhou) Co., Ltd + +OUI:582EFE* + ID_OUI_FROM_DATABASE=Lighting Science Group + +OUI:582F40* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:582F42* + ID_OUI_FROM_DATABASE=Universal Electric Corporation + +OUI:583112* + ID_OUI_FROM_DATABASE=DRUST + +OUI:583277* + ID_OUI_FROM_DATABASE=Reliance Communications LLC + +OUI:58343B* + ID_OUI_FROM_DATABASE=Glovast Technology Ltd. + +OUI:583526* + ID_OUI_FROM_DATABASE=DEEPLET TECHNOLOGY CORP + +OUI:5835D9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:583879* + ID_OUI_FROM_DATABASE=RICOH COMPANY, LTD. + +OUI:583BD9* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:583CC6* + ID_OUI_FROM_DATABASE=Omneality Ltd. + +OUI:583F54* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:58404E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5842E4* + ID_OUI_FROM_DATABASE=Baxter International Inc + +OUI:584498* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:58468F* + ID_OUI_FROM_DATABASE=Koncar Electronics and Informatics + +OUI:5846E1* + ID_OUI_FROM_DATABASE=Baxter International Inc + +OUI:584704* + ID_OUI_FROM_DATABASE=Shenzhen Webridge Technology Co.,Ltd + +OUI:584822* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:5848C0* + ID_OUI_FROM_DATABASE=COFLEC + +OUI:584925* + ID_OUI_FROM_DATABASE=E3 Enterprise + +OUI:58493B* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:5849BA* + ID_OUI_FROM_DATABASE=Chitai Electronic Corp. + +OUI:584C19* + ID_OUI_FROM_DATABASE=Chongqing Guohong Technology Development Company Limited + +OUI:584CEE* + ID_OUI_FROM_DATABASE=Digital One Technologies, Limited + +OUI:585076* + ID_OUI_FROM_DATABASE=Linear Equipamentos Eletronicos SA + +OUI:5850AB* + ID_OUI_FROM_DATABASE=TLS Corporation + +OUI:5850E6* + ID_OUI_FROM_DATABASE=Best Buy Corporation + +OUI:58528A* + ID_OUI_FROM_DATABASE=Mitsubishi Electric Corporation + +OUI:5853C0* + ID_OUI_FROM_DATABASE=Beijing Guang Runtong Technology Development Company co.,Ltd + +OUI:5855CA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5856E8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:58570D* + ID_OUI_FROM_DATABASE=Danfoss Solar Inverters + +OUI:5859C2* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:585FF6* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:58605F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:586163* + ID_OUI_FROM_DATABASE=Quantum Networks (SG) Pte. Ltd. + +OUI:586356* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:58639A* + ID_OUI_FROM_DATABASE=TPL SYSTEMES + +OUI:5865E6* + ID_OUI_FROM_DATABASE=INFOMARK CO., LTD. + +OUI:5866BA* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:58671A* + ID_OUI_FROM_DATABASE=Barnes&Noble + +OUI:58677F* + ID_OUI_FROM_DATABASE=Clare Controls Inc. + +OUI:58685D* + ID_OUI_FROM_DATABASE=Tempo Australia Pty Ltd + +OUI:58696C* + ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD + +OUI:5869F9* + ID_OUI_FROM_DATABASE=Fusion Transactive Ltd. + +OUI:586AB1* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:586B14* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:586D8F* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:586ED6* + ID_OUI_FROM_DATABASE=Private + +OUI:5870C6* + ID_OUI_FROM_DATABASE=Shanghai Xiaoyi Technology Co., Ltd. + +OUI:587521* + ID_OUI_FROM_DATABASE=CJSC RTSoft + +OUI:587675* + ID_OUI_FROM_DATABASE=Beijing ECHO Technologies Co.,Ltd + +OUI:5876C5* + ID_OUI_FROM_DATABASE=DIGI I'S LTD + +OUI:587A4D* + ID_OUI_FROM_DATABASE=Stonesoft Corporation + +OUI:587A62* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:587A6A* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:587BE9* + ID_OUI_FROM_DATABASE=AirPro Technology India Pvt. Ltd + +OUI:587E61* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:587F57* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:587F66* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:587FB7* + ID_OUI_FROM_DATABASE=SONAR INDUSTRIAL CO., LTD. + +OUI:587FC8* + ID_OUI_FROM_DATABASE=S2M + +OUI:58821D* + ID_OUI_FROM_DATABASE=H. Schomäcker GmbH + +OUI:5882A8* + ID_OUI_FROM_DATABASE=Microsoft + +OUI:5884E4* + ID_OUI_FROM_DATABASE=IP500 Alliance e.V. + +OUI:58856E* + ID_OUI_FROM_DATABASE=QSC AG + +OUI:5885A2* + ID_OUI_FROM_DATABASE=Realme Chongqing MobileTelecommunications Corp Ltd + +OUI:5885E9* + ID_OUI_FROM_DATABASE=Realme Chongqing MobileTelecommunications Corp Ltd + +OUI:58874C* + ID_OUI_FROM_DATABASE=LITE-ON CLEAN ENERGY TECHNOLOGY CORP. + +OUI:5887E2* + ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd. + +OUI:588A5A* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:588BF3* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:588D09* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:588D64* + ID_OUI_FROM_DATABASE=Xi'an Clevbee Technology Co.,Ltd + +OUI:588E81* + ID_OUI_FROM_DATABASE=Silicon Laboratories + +OUI:589043* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:5891CF* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:58920D* + ID_OUI_FROM_DATABASE=Kinetic Avionics Limited + +OUI:589396* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:5893D8* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:58946B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:5894B2* + ID_OUI_FROM_DATABASE=BrainCo + +OUI:5894CF* + ID_OUI_FROM_DATABASE=Vertex Standard LMR, Inc. + +OUI:58961D* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:589630* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:58971E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5897BD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:589835* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:58986F* + ID_OUI_FROM_DATABASE=Revolution Display + +OUI:589B0B* + ID_OUI_FROM_DATABASE=Shineway Technologies, Inc. + +OUI:589CFC* + ID_OUI_FROM_DATABASE=FreeBSD Foundation + +OUI:589EC6* + ID_OUI_FROM_DATABASE=Gigaset Communications GmbH + +OUI:58A023* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:58A0CB* + ID_OUI_FROM_DATABASE=TrackNet, Inc + +OUI:58A2B5* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:58A48E* + ID_OUI_FROM_DATABASE=PixArt Imaging Inc. + +OUI:58A76F* + ID_OUI_FROM_DATABASE=iD corporation + +OUI:58A839* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:58AC78* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:58B035* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:58B0D4* + ID_OUI_FROM_DATABASE=ZuniData Systems Inc. + +OUI:58B10F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:58B3FC* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:58B42D* + ID_OUI_FROM_DATABASE=YSTen Technology Co.,Ltd + +OUI:58B568* + ID_OUI_FROM_DATABASE=SECURITAS DIRECT ESPAÑA, SAU + +OUI:58B633* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:58B961* + ID_OUI_FROM_DATABASE=SOLEM Electronique + +OUI:58B9E1* + ID_OUI_FROM_DATABASE=Crystalfontz America, Inc. + +OUI:58BAD4* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:58BC27* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:58BC8F* + ID_OUI_FROM_DATABASE=Cognitive Systems Corp. + +OUI:58BDA3* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:58BDF9* + ID_OUI_FROM_DATABASE=Sigrand + +OUI:58BFEA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:58C17A* + ID_OUI_FROM_DATABASE=Cambium Networks Limited + +OUI:58C232* + ID_OUI_FROM_DATABASE=NEC Corporation + +OUI:58C38B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:58C583* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:58C5CB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:58C6F0* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:58C876* + ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd. + +OUI:58C935* + ID_OUI_FROM_DATABASE=Chiun Mai Communication Systems, Inc + +OUI:58CB52* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:58CF4B* + ID_OUI_FROM_DATABASE=Lufkin Industries + +OUI:58D071* + ID_OUI_FROM_DATABASE=BW Broadcast + +OUI:58D08F* + ID_OUI_FROM_DATABASE=IEEE 1904.1 Working Group + +OUI:58D50A* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:58D56E* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:58D67A* + ID_OUI_FROM_DATABASE=TCPlink + +OUI:58D6D3* + ID_OUI_FROM_DATABASE=Dairy Cheq Inc + +OUI:58D759* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:58D9C3* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:58D9D5* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:58DB15* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:58DB8D* + ID_OUI_FROM_DATABASE=Fast Co., Ltd. + +OUI:58DC6D* + ID_OUI_FROM_DATABASE=Exceptional Innovation, Inc. + +OUI:58E02C* + ID_OUI_FROM_DATABASE=Micro Technic A/S + +OUI:58E16C* + ID_OUI_FROM_DATABASE=Ying Hua Information Technology (Shanghai)Co., LTD + +OUI:58E28F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:58E326* + ID_OUI_FROM_DATABASE=Compass Technologies Inc. + +OUI:58E476* + ID_OUI_FROM_DATABASE=CENTRON COMMUNICATIONS TECHNOLOGIES FUJIAN CO.,LTD + +OUI:58E636* + ID_OUI_FROM_DATABASE=EVRsafe Technologies + +OUI:58E6BA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:58E747* + ID_OUI_FROM_DATABASE=Deltanet AG + +OUI:58E808* + ID_OUI_FROM_DATABASE=AUTONICS CORPORATION + +OUI:58E8760* + ID_OUI_FROM_DATABASE=Private + +OUI:58E8761* + ID_OUI_FROM_DATABASE=Beijing Perabytes IS Technology Co., Ltd + +OUI:58E8762* + ID_OUI_FROM_DATABASE=Coala Life AB + +OUI:58E8763* + ID_OUI_FROM_DATABASE=McWong International Inc + +OUI:58E8764* + ID_OUI_FROM_DATABASE=PROBIT SRL + +OUI:58E8765* + ID_OUI_FROM_DATABASE=Broad Air Technology Co., LTD. + +OUI:58E8766* + ID_OUI_FROM_DATABASE=DivioTec Inc. + +OUI:58E8767* + ID_OUI_FROM_DATABASE=Chronos Technology Ltd. + +OUI:58E8768* + ID_OUI_FROM_DATABASE=Chengdu Vision-Zenith Technology Co.,Ltd + +OUI:58E8769* + ID_OUI_FROM_DATABASE=TEM Mobile Limited + +OUI:58E876A* + ID_OUI_FROM_DATABASE=SHENZHEN DIGISSIN TECHNOLOGY + +OUI:58E876B* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:58E876C* + ID_OUI_FROM_DATABASE=KUSTOM SIGNALS INC + +OUI:58E876D* + ID_OUI_FROM_DATABASE=Xiamen Cacamle Technology Co.,Ltd. + +OUI:58E876E* + ID_OUI_FROM_DATABASE=Baoruh Electronic Co., Ltd. + +OUI:58EAFC* + ID_OUI_FROM_DATABASE=ELL-IoT Inc + +OUI:58EB14* + ID_OUI_FROM_DATABASE=Proteus Digital Health + +OUI:58ECE1* + ID_OUI_FROM_DATABASE=Newport Corporation + +OUI:58ECED* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:58EECE* + ID_OUI_FROM_DATABASE=Icon Time Systems + +OUI:58EF68* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:58F102* + ID_OUI_FROM_DATABASE=BLU Products Inc. + +OUI:58F387* + ID_OUI_FROM_DATABASE=HCCP + +OUI:58F39C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:58F496* + ID_OUI_FROM_DATABASE=Source Chain + +OUI:58F67B* + ID_OUI_FROM_DATABASE=Xia Men UnionCore Technology LTD. + +OUI:58F6BF* + ID_OUI_FROM_DATABASE=Kyoto University + +OUI:58F987* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:58F98E* + ID_OUI_FROM_DATABASE=SECUDOS GmbH + +OUI:58FB84* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:58FC73* + ID_OUI_FROM_DATABASE=Arria Live Media, Inc. + +OUI:58FCDB0* + ID_OUI_FROM_DATABASE=Spang Power Electronics + +OUI:58FCDB1* + ID_OUI_FROM_DATABASE=Certis Technology International + +OUI:58FCDB2* + ID_OUI_FROM_DATABASE=Beseye Cloud Security Co. Ltd. + +OUI:58FCDB3* + ID_OUI_FROM_DATABASE=Custom Biogenic Systems + +OUI:58FCDB4* + ID_OUI_FROM_DATABASE=Inforce Computing Inc. + +OUI:58FCDB5* + ID_OUI_FROM_DATABASE=Shenzhen Siecom Communication Technology Development Co.,Ltd. + +OUI:58FCDB6* + ID_OUI_FROM_DATABASE=Timex Group USA Inc + +OUI:58FCDB7* + ID_OUI_FROM_DATABASE=Open Roads Consulting, Inc. + +OUI:58FCDB8* + ID_OUI_FROM_DATABASE=Shanghai Qianjin Electronic Equipment Co. Ltd + +OUI:58FCDB9* + ID_OUI_FROM_DATABASE=Hi-Target Surveying Instrument Co., Ltd. + +OUI:58FCDBA* + ID_OUI_FROM_DATABASE=Xmodus Systems GmbH + +OUI:58FCDBB* + ID_OUI_FROM_DATABASE=SWARCO TRAFFIC SYSTEMS GMBH + +OUI:58FCDBC* + ID_OUI_FROM_DATABASE=Excenon Mobile Technology Co., Ltd. + +OUI:58FCDBD* + ID_OUI_FROM_DATABASE=XIAMEN LEELEN TECHNOLOGY CO.,LTD + +OUI:58FCDBE* + ID_OUI_FROM_DATABASE=Applied Device Technologies + +OUI:58FCDBF* + ID_OUI_FROM_DATABASE=Private + +OUI:58FD20* + ID_OUI_FROM_DATABASE=Bravida Sakerhet AB + +OUI:58FDBE* + ID_OUI_FROM_DATABASE=Shenzhen Taikaida Technology Co., Ltd + +OUI:5C0038* + ID_OUI_FROM_DATABASE=Viasat Group S.p.A. + +OUI:5C026A* + ID_OUI_FROM_DATABASE=Applied Vision Corporation + +OUI:5C0339* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5C076F* + ID_OUI_FROM_DATABASE=Thought Creator + +OUI:5C0947* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5C0979* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5C0A5B* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:5C0BCA* + ID_OUI_FROM_DATABASE=Tunstall Nordic AB + +OUI:5C0C0E* + ID_OUI_FROM_DATABASE=Guizhou Huaxintong Semiconductor Technology Co Ltd + +OUI:5C0CBB* + ID_OUI_FROM_DATABASE=CELIZION Inc. + +OUI:5C0E8B* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:5C1193* + ID_OUI_FROM_DATABASE=Seal One AG + +OUI:5C1437* + ID_OUI_FROM_DATABASE=Thyssenkrupp Aufzugswerke GmbH + +OUI:5C1515* + ID_OUI_FROM_DATABASE=ADVAN + +OUI:5C15E1* + ID_OUI_FROM_DATABASE=AIDC TECHNOLOGY (S) PTE LTD + +OUI:5C16C7* + ID_OUI_FROM_DATABASE=Big Switch Networks + +OUI:5C1737* + ID_OUI_FROM_DATABASE=I-View Now, LLC. + +OUI:5C17CF* + ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd + +OUI:5C17D3* + ID_OUI_FROM_DATABASE=LGE + +OUI:5C18B5* + ID_OUI_FROM_DATABASE=Talon Communications + +OUI:5C1A6F* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:5C1CB9* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:5C1DD9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5C20D0* + ID_OUI_FROM_DATABASE=Asoni Communication Co., Ltd. + +OUI:5C22C4* + ID_OUI_FROM_DATABASE=DAE EUN ELETRONICS CO., LTD + +OUI:5C2443* + ID_OUI_FROM_DATABASE=O-Sung Telecom Co., Ltd. + +OUI:5C2479* + ID_OUI_FROM_DATABASE=Baltech AG + +OUI:5C254C* + ID_OUI_FROM_DATABASE=Avire Global Pte Ltd + +OUI:5C260A* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:5C2623* + ID_OUI_FROM_DATABASE=WaveLynx Technologies Corporation + +OUI:5C27D4* + ID_OUI_FROM_DATABASE=Shenzhen Qihu Intelligent Technology Company Limited + +OUI:5C2AEF* + ID_OUI_FROM_DATABASE=r2p Asia-Pacific Pty Ltd + +OUI:5C2BF5* + ID_OUI_FROM_DATABASE=Vivint Wireless Inc. + +OUI:5C2E59* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5C2ED2* + ID_OUI_FROM_DATABASE=ABC(XiSheng) Electronics Co.,Ltd + +OUI:5C313E* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:5C32C5* + ID_OUI_FROM_DATABASE=Teracom Ltd. + +OUI:5C3327* + ID_OUI_FROM_DATABASE=Spazio Italia srl + +OUI:5C335C* + ID_OUI_FROM_DATABASE=Swissphone Telecom AG + +OUI:5C338E* + ID_OUI_FROM_DATABASE=Alpha Networks Inc. + +OUI:5C353B* + ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. + +OUI:5C35DA* + ID_OUI_FROM_DATABASE=There Corporation Oy + +OUI:5C36B8* + ID_OUI_FROM_DATABASE=TCL King Electrical Appliances (Huizhou) Co., Ltd + +OUI:5C38E0* + ID_OUI_FROM_DATABASE=Shanghai Super Electronics Technology Co.,LTD + +OUI:5C3A3D* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:5C3A45* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:5C3B35* + ID_OUI_FROM_DATABASE=Gehirn Inc. + +OUI:5C3C27* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5C4058* + ID_OUI_FROM_DATABASE=Jefferson Audio Video Systems, Inc. + +OUI:5C415A* + ID_OUI_FROM_DATABASE=Amazon.com, LLC + +OUI:5C41E7* + ID_OUI_FROM_DATABASE=Wiatec International Ltd. + +OUI:5C43D2* + ID_OUI_FROM_DATABASE=HAZEMEYER + +OUI:5C4527* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:5C4979* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:5C497D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5C4A1F* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:5C4A26* + ID_OUI_FROM_DATABASE=Enguity Technology Corp + +OUI:5C4CA9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5C5015* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5C514F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:5C5181* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5C5188* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:5C521E* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:5C546D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5C5578* + ID_OUI_FROM_DATABASE=iryx corp + +OUI:5C56ED* + ID_OUI_FROM_DATABASE=3pleplay Electronics Private Limited + +OUI:5C571A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:5C57C8* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:5C5819* + ID_OUI_FROM_DATABASE=Jingsheng Technology Co., Ltd. + +OUI:5C5948* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5C5AC7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5C5AEA* + ID_OUI_FROM_DATABASE=FORD + +OUI:5C5B35* + ID_OUI_FROM_DATABASE=Mist Systems, Inc. + +OUI:5C5BC2* + ID_OUI_FROM_DATABASE=YIK Corporation + +OUI:5C5EAB* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:5C5F67* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:5C63BF* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:5C63C9* + ID_OUI_FROM_DATABASE=Intellithings Ltd. + +OUI:5C666C* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:5C6776* + ID_OUI_FROM_DATABASE=IDS Imaging Development Systems GmbH + +OUI:5C68D0* + ID_OUI_FROM_DATABASE=Aurora Innovation Inc. + +OUI:5C6984* + ID_OUI_FROM_DATABASE=NUVICO + +OUI:5C6A7D* + ID_OUI_FROM_DATABASE=KENTKART EGE ELEKTRONIK SAN. VE TIC. LTD. STI. + +OUI:5C6A80* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:5C6B32* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:5C6B4F* + ID_OUI_FROM_DATABASE=Hello Inc. + +OUI:5C6D20* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:5C6F4F* + ID_OUI_FROM_DATABASE=S.A. SISTEL + +OUI:5C70A3* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:5C710D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5C75AF* + ID_OUI_FROM_DATABASE=Fitbit, Inc. + +OUI:5C7695* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:5C7757* + ID_OUI_FROM_DATABASE=Haivision Network Video + +OUI:5C7776* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:5C78F8* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:5C7D5E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5C80B6* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:5C81A7* + ID_OUI_FROM_DATABASE=Network Devices Pty Ltd + +OUI:5C838F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5C8486* + ID_OUI_FROM_DATABASE=Brightsource Industries Israel LTD + +OUI:5C8613* + ID_OUI_FROM_DATABASE=Beijing Zhoenet Technology Co., Ltd + +OUI:5C864A* + ID_OUI_FROM_DATABASE=Secret Labs LLC + +OUI:5C865C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5C86C1* + ID_OUI_FROM_DATABASE=DONGGUAN SOLUM ELECTRONICS CO.,LTD + +OUI:5C8778* + ID_OUI_FROM_DATABASE=Cybertelbridge co.,ltd + +OUI:5C879C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:5C8816* + ID_OUI_FROM_DATABASE=Rockwell Automation + +OUI:5C899A* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:5C89D4* + ID_OUI_FROM_DATABASE=Beijing Banner Electric Co.,Ltd + +OUI:5C8A38* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:5C8D2D* + ID_OUI_FROM_DATABASE=Shanghai Wellpay Information Technology Co., Ltd + +OUI:5C8D4E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5C8FE0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:5C925E* + ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. + +OUI:5C93A2* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:5C95AE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5C9656* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:5C966A* + ID_OUI_FROM_DATABASE=RTNET + +OUI:5C969D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5C97F3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5C9960* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5C9AD8* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:5CA176* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:5CA178* + ID_OUI_FROM_DATABASE=TableTop Media (dba Ziosk) + +OUI:5CA1E0* + ID_OUI_FROM_DATABASE=EmbedWay Technologies + +OUI:5CA39D* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:5CA3EB* + ID_OUI_FROM_DATABASE=Lokel s.r.o. + +OUI:5CA48A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5CA62D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5CA86A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5CA933* + ID_OUI_FROM_DATABASE=Luma Home + +OUI:5CAAFD* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:5CAC4C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:5CAD76* + ID_OUI_FROM_DATABASE=Shenzhen TCL New Technology Co., Ltd + +OUI:5CADCF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5CAF06* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:5CB066* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:5CB13E* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:5CB15F* + ID_OUI_FROM_DATABASE=Oceanblue Cloud Technology Limited + +OUI:5CB29E* + ID_OUI_FROM_DATABASE=ASCO Power Technologies + +OUI:5CB395* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5CB3F6* + ID_OUI_FROM_DATABASE=Human, Incorporated + +OUI:5CB43E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5CB4E2* + ID_OUI_FROM_DATABASE=Inspur Software Group Ltd. + +OUI:5CB524* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:5CB559* + ID_OUI_FROM_DATABASE=CNEX Labs + +OUI:5CB6CC* + ID_OUI_FROM_DATABASE=NovaComm Technologies Inc. + +OUI:5CB8CB* + ID_OUI_FROM_DATABASE=Allis Communications + +OUI:5CB901* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:5CBA2C* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:5CBA37* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:5CBAEF* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:5CBD9E* + ID_OUI_FROM_DATABASE=HONGKONG MIRACLE EAGLE TECHNOLOGY(GROUP) LIMITED + +OUI:5CC1D7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5CC213* + ID_OUI_FROM_DATABASE=Fr. Sauter AG + +OUI:5CC307* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5CC5D4* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:5CC6D0* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:5CC6E9* + ID_OUI_FROM_DATABASE=Edifier International + +OUI:5CC7D7* + ID_OUI_FROM_DATABASE=AZROAD TECHNOLOGY COMPANY LIMITED + +OUI:5CC999* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:5CC9D3* + ID_OUI_FROM_DATABASE=PALLADIUM ENERGY ELETRONICA DA AMAZONIA LTDA + +OUI:5CCA1A* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:5CCA32* + ID_OUI_FROM_DATABASE=Theben AG + +OUI:5CCAD3* + ID_OUI_FROM_DATABASE=CHIPSEA TECHNOLOGIES (SHENZHEN) CORP. + +OUI:5CCB99* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5CCBCA* + ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD + +OUI:5CCCA0* + ID_OUI_FROM_DATABASE=Gridwiz Inc. + +OUI:5CCCFF* + ID_OUI_FROM_DATABASE=Techroutes Network Pvt Ltd + +OUI:5CCD5B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:5CCD7C* + ID_OUI_FROM_DATABASE=MEIZU Technology Co.,Ltd. + +OUI:5CCEAD* + ID_OUI_FROM_DATABASE=CDYNE Corporation + +OUI:5CCF7F* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:5CD135* + ID_OUI_FROM_DATABASE=Xtreme Power Systems + +OUI:5CD20B* + ID_OUI_FROM_DATABASE=Yytek Co., Ltd. + +OUI:5CD2E4* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:5CD41B* + ID_OUI_FROM_DATABASE=UCZOON Technology Co., LTD + +OUI:5CD4AB* + ID_OUI_FROM_DATABASE=Zektor + +OUI:5CD61F* + ID_OUI_FROM_DATABASE=Qardio, Inc + +OUI:5CD998* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:5CDAD4* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:5CDC96* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:5CDD70* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:5CE0C5* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:5CE0CA* + ID_OUI_FROM_DATABASE=FeiTian United (Beijing) System Technology Co., Ltd. + +OUI:5CE0F6* + ID_OUI_FROM_DATABASE=NIC.br- Nucleo de Informacao e Coordenacao do Ponto BR + +OUI:5CE176* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5CE223* + ID_OUI_FROM_DATABASE=Delphin Technology AG + +OUI:5CE286* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:5CE28C* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:5CE2F4* + ID_OUI_FROM_DATABASE=AcSiP Technology Corp. + +OUI:5CE30E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:5CE3B6* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:5CE50C* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd + +OUI:5CE7A0* + ID_OUI_FROM_DATABASE=Nokia + +OUI:5CE7BF* + ID_OUI_FROM_DATABASE=New Singularity International Technical Development Co.,Ltd + +OUI:5CE883* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5CE8B7* + ID_OUI_FROM_DATABASE=Oraimo Technology Limited + +OUI:5CE8EB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5CEA1D* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:5CEB4E* + ID_OUI_FROM_DATABASE=R. STAHL HMI Systems GmbH + +OUI:5CEB68* + ID_OUI_FROM_DATABASE=Cheerstar Technology Co., Ltd + +OUI:5CEE79* + ID_OUI_FROM_DATABASE=Global Digitech Co LTD + +OUI:5CF207* + ID_OUI_FROM_DATABASE=Speco Technologies + +OUI:5CF2860* + ID_OUI_FROM_DATABASE=Hangzhou Signwei Electronics Technology Co., Ltd + +OUI:5CF2861* + ID_OUI_FROM_DATABASE=iSon Tech + +OUI:5CF2862* + ID_OUI_FROM_DATABASE=Shanghai Notion Information Technology CO.,LTD. + +OUI:5CF2863* + ID_OUI_FROM_DATABASE=beijing your wonderful control system technology co.,ltd + +OUI:5CF2864* + ID_OUI_FROM_DATABASE=CHIPSEN Co.,Ltd. + +OUI:5CF2865* + ID_OUI_FROM_DATABASE=EUROIMMUN Medizinische Labordiagnostika AG + +OUI:5CF2866* + ID_OUI_FROM_DATABASE=VPInstruments + +OUI:5CF2867* + ID_OUI_FROM_DATABASE=Access IS + +OUI:5CF2868* + ID_OUI_FROM_DATABASE=SHENZHEN HIVT TECHNOLOGY CO.,LTD + +OUI:5CF2869* + ID_OUI_FROM_DATABASE=Shenzhen VST Automotive Electronics Co., LTD + +OUI:5CF286A* + ID_OUI_FROM_DATABASE=Unfors Raysafe AB + +OUI:5CF286B* + ID_OUI_FROM_DATABASE=Itron UK Limited + +OUI:5CF286C* + ID_OUI_FROM_DATABASE=Sunpet Industries Limited + +OUI:5CF286D* + ID_OUI_FROM_DATABASE=BrightSky, LLC + +OUI:5CF286E* + ID_OUI_FROM_DATABASE=Daisen Electronic Industrial Co., Ltd. + +OUI:5CF370* + ID_OUI_FROM_DATABASE=CC&C Technologies, Inc + +OUI:5CF3FC* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:5CF4AB* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:5CF50D* + ID_OUI_FROM_DATABASE=Institute of microelectronic applications + +OUI:5CF5DA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5CF6DC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:5CF7C3* + ID_OUI_FROM_DATABASE=SYNTECH (HK) TECHNOLOGY LIMITED + +OUI:5CF7E6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5CF821* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:5CF8A1* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:5CF938* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:5CF96A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:5CF9DD* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:5CF9F0* + ID_OUI_FROM_DATABASE=Atomos Engineering P/L + +OUI:5CFAFB* + ID_OUI_FROM_DATABASE=Acubit + +OUI:5CFB7C* + ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + +OUI:5CFC66* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:5CFF35* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:5CFFFF* + ID_OUI_FROM_DATABASE=Shenzhen Kezhonglong Optoelectronic Technology Co., Ltd + +OUI:600194* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:600292* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:6002B4* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:600308* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:600347* + ID_OUI_FROM_DATABASE=Billion Electric Co. Ltd. + +OUI:6003A6* + ID_OUI_FROM_DATABASE=Inteno Broadband Technology AB + +OUI:600417* + ID_OUI_FROM_DATABASE=POSBANK CO.,LTD + +OUI:60058A* + ID_OUI_FROM_DATABASE=Hitachi Metals, Ltd. + +OUI:600810* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:600837* + ID_OUI_FROM_DATABASE=ivvi Scientific(Nanchang)Co.Ltd + +OUI:6009C3* + ID_OUI_FROM_DATABASE=u-blox AG + +OUI:600B03* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:600F77* + ID_OUI_FROM_DATABASE=SilverPlus, Inc + +OUI:6010A2* + ID_OUI_FROM_DATABASE=Crompton Instruments + +OUI:601199* + ID_OUI_FROM_DATABASE=Siama Systems Inc + +OUI:60123C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:601283* + ID_OUI_FROM_DATABASE=TSB REAL TIME LOCATION SYSTEMS S.L. + +OUI:60128B* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:601466* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:6014B3* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. + +OUI:6015C7* + ID_OUI_FROM_DATABASE=IdaTech + +OUI:601803* + ID_OUI_FROM_DATABASE=Daikin Air-conditioning (Shanghai) Co., Ltd. + +OUI:60182E* + ID_OUI_FROM_DATABASE=ShenZhen Protruly Electronic Ltd co. + +OUI:601888* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:60190C* + ID_OUI_FROM_DATABASE=RRAMAC + +OUI:601929* + ID_OUI_FROM_DATABASE=VOLTRONIC POWER TECHNOLOGY(SHENZHEN) CORP. + +OUI:601970* + ID_OUI_FROM_DATABASE=HUIZHOU QIAOXING ELECTRONICS TECHNOLOGY CO., LTD. + +OUI:601971* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:601D0F* + ID_OUI_FROM_DATABASE=Midnite Solar + +OUI:601D91* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:601D9D* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:601E02* + ID_OUI_FROM_DATABASE=EltexAlatau + +OUI:602101* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:602103* + ID_OUI_FROM_DATABASE=I4VINE, INC + +OUI:6021C0* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:6023A4* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:6024C1* + ID_OUI_FROM_DATABASE=Jiangsu Zhongxun Electronic Technology Co., Ltd + +OUI:60271C* + ID_OUI_FROM_DATABASE=VIDEOR E. Hartig GmbH + +OUI:6029D5* + ID_OUI_FROM_DATABASE=DAVOLINK Inc. + +OUI:602A54* + ID_OUI_FROM_DATABASE=CardioTek B.V. + +OUI:602AD0* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:602E20* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:6030D4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60313B* + ID_OUI_FROM_DATABASE=Sunnovo International Limited + +OUI:603197* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:6032F0* + ID_OUI_FROM_DATABASE=Mplus technology + +OUI:60334B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:603553* + ID_OUI_FROM_DATABASE=Buwon Technology + +OUI:6035C0* + ID_OUI_FROM_DATABASE=SFR + +OUI:603696* + ID_OUI_FROM_DATABASE=The Sapling Company + +OUI:6036DD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:60380E* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:6038E0* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:60391F* + ID_OUI_FROM_DATABASE=ABB Ltd + +OUI:603A7C* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:603D26* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:603E7B* + ID_OUI_FROM_DATABASE=Gafachi, Inc. + +OUI:603ECA* + ID_OUI_FROM_DATABASE=Cambridge Medical Robotics Ltd + +OUI:603FC5* + ID_OUI_FROM_DATABASE=COX CO., LTD + +OUI:60427F* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + +OUI:60447A* + ID_OUI_FROM_DATABASE=Water-i.d. GmbH + +OUI:6044F5* + ID_OUI_FROM_DATABASE=Easy Digital Ltd. + +OUI:60455E* + ID_OUI_FROM_DATABASE=Liptel s.r.o. + +OUI:6045BD* + ID_OUI_FROM_DATABASE=Microsoft + +OUI:6045CB* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:604616* + ID_OUI_FROM_DATABASE=XIAMEN VANN INTELLIGENT CO., LTD + +OUI:604762* + ID_OUI_FROM_DATABASE=Beijing Sensoro Technology Co.,Ltd. + +OUI:6047D4* + ID_OUI_FROM_DATABASE=FORICS Electronic Technology Co., Ltd. + +OUI:604826* + ID_OUI_FROM_DATABASE=Newbridge Technologies Int. Ltd. + +OUI:6049C1* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:604A1C* + ID_OUI_FROM_DATABASE=SUYIN Corporation + +OUI:604BAA* + ID_OUI_FROM_DATABASE=Magic Leap, Inc. + +OUI:6050C1* + ID_OUI_FROM_DATABASE=Kinetek Sports + +OUI:60512C* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:6052D0* + ID_OUI_FROM_DATABASE=FACTS Engineering + +OUI:605317* + ID_OUI_FROM_DATABASE=Sandstone Technologies + +OUI:605464* + ID_OUI_FROM_DATABASE=Eyedro Green Solutions Inc. + +OUI:605718* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:605BB4* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:605F8D* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:60601F* + ID_OUI_FROM_DATABASE=SZ DJI TECHNOLOGY CO.,LTD + +OUI:6061DF* + ID_OUI_FROM_DATABASE=Z-meta Research LLC + +OUI:60634C* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:6063F9* + ID_OUI_FROM_DATABASE=Ciholas, Inc. + +OUI:6063FD* + ID_OUI_FROM_DATABASE=Transcend Communication Beijing Co.,Ltd. + +OUI:606405* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:606453* + ID_OUI_FROM_DATABASE=AOD Co.,Ltd. + +OUI:6064A1* + ID_OUI_FROM_DATABASE=RADiflow Ltd. + +OUI:606720* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:60684E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:606944* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60699B* + ID_OUI_FROM_DATABASE=isepos GmbH + +OUI:606BBD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:606BFF* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:606C66* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:606D3C* + ID_OUI_FROM_DATABASE=Luxshare Precision Industry Company Limited + +OUI:606DC7* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:606ED0* + ID_OUI_FROM_DATABASE=SEAL AG + +OUI:6070C0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60720B* + ID_OUI_FROM_DATABASE=BLU Products Inc + +OUI:60735C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6073BC* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:60748D* + ID_OUI_FROM_DATABASE=Atmaca Elektronik + +OUI:607688* + ID_OUI_FROM_DATABASE=Velodyne + +OUI:607771* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:6077E2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:607EDD* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:60812B* + ID_OUI_FROM_DATABASE=Custom Control Concepts + +OUI:6081F9* + ID_OUI_FROM_DATABASE=Helium Systems, Inc + +OUI:608334* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:608373* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6083B2* + ID_OUI_FROM_DATABASE=GkWare e.K. + +OUI:60843B* + ID_OUI_FROM_DATABASE=Soladigm, Inc. + +OUI:6084BD* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:608645* + ID_OUI_FROM_DATABASE=Avery Weigh-Tronix, LLC + +OUI:60893C* + ID_OUI_FROM_DATABASE=Thermo Fisher Scientific P.O.A. + +OUI:6089B1* + ID_OUI_FROM_DATABASE=Key Digital Systems + +OUI:6089B7* + ID_OUI_FROM_DATABASE=KAEL MÜHENDİSLİK ELEKTRONİK TİCARET SANAYİ LİMİTED ŞİRKETİ + +OUI:608B0E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:608C2B* + ID_OUI_FROM_DATABASE=Hanson Technology + +OUI:608C4A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:608CDF* + ID_OUI_FROM_DATABASE=Private + +OUI:608CE6* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:608D17* + ID_OUI_FROM_DATABASE=Sentrus Government Systems Division, Inc + +OUI:608E08* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:608F5C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:609084* + ID_OUI_FROM_DATABASE=DSSD Inc + +OUI:6091F3* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:609217* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6092F5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:6095CE0* + ID_OUI_FROM_DATABASE=Siema Applications + +OUI:6095CE1* + ID_OUI_FROM_DATABASE=Ponoor Experiments Inc. + +OUI:6095CE2* + ID_OUI_FROM_DATABASE=Q-SENTECH Co.,Ltd. + +OUI:6095CE3* + ID_OUI_FROM_DATABASE=Robot S.A. + +OUI:6095CE4* + ID_OUI_FROM_DATABASE=Untangle, Inc. + +OUI:6095CE5* + ID_OUI_FROM_DATABASE=AdvanWISE Corporation + +OUI:6095CE6* + ID_OUI_FROM_DATABASE=Xiamen Sigmastar Technology Ltd. + +OUI:6095CE7* + ID_OUI_FROM_DATABASE=Cadmo Soluciones SAC + +OUI:6095CE8* + ID_OUI_FROM_DATABASE=Trophy SAS + +OUI:6095CE9* + ID_OUI_FROM_DATABASE=Jlztlink Industry(ShenZhen)Co.,Ltd. + +OUI:6095CEA* + ID_OUI_FROM_DATABASE=(UN)MANNED + +OUI:6095CEB* + ID_OUI_FROM_DATABASE=Beijing Sinomedisite Bio-tech Co.,Ltd + +OUI:6095CEC* + ID_OUI_FROM_DATABASE=Synamedia + +OUI:6095CED* + ID_OUI_FROM_DATABASE=GovComm + +OUI:6095CEE* + ID_OUI_FROM_DATABASE=VNS Inc. + +OUI:609620* + ID_OUI_FROM_DATABASE=Private + +OUI:6097DD* + ID_OUI_FROM_DATABASE=MicroSys Electronics GmbH + +OUI:609813* + ID_OUI_FROM_DATABASE=Shanghai Visking Digital Technology Co. LTD + +OUI:6099D1* + ID_OUI_FROM_DATABASE=Vuzix / Lenovo + +OUI:609AA4* + ID_OUI_FROM_DATABASE=GVI SECURITY INC. + +OUI:609AC1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:609B2D* + ID_OUI_FROM_DATABASE=JMACS Japan Co., Ltd. + +OUI:609BC8* + ID_OUI_FROM_DATABASE=Hipad Intelligent Technology Co., Ltd. + +OUI:609C9F* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:609E64* + ID_OUI_FROM_DATABASE=Vivonic GmbH + +OUI:609F9D* + ID_OUI_FROM_DATABASE=CloudSwitch + +OUI:60A10A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:60A11E* + ID_OUI_FROM_DATABASE=Wuhan Maxsine Electric Co.,Ltd. + +OUI:60A37D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60A44C* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:60A4D0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:60A730* + ID_OUI_FROM_DATABASE=Shenzhen Yipinfang Internet Technology Co.,Ltd + +OUI:60A8FE* + ID_OUI_FROM_DATABASE=Nokia + +OUI:60A9B0* + ID_OUI_FROM_DATABASE=Merchandising Technologies, Inc + +OUI:60AB14* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:60AB67* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:60ABD2* + ID_OUI_FROM_DATABASE=Bose Corporation + +OUI:60ACC8* + ID_OUI_FROM_DATABASE=KunTeng Inc. + +OUI:60AF6D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:60B185* + ID_OUI_FROM_DATABASE=ATH system + +OUI:60B387* + ID_OUI_FROM_DATABASE=Synergics Technologies GmbH + +OUI:60B3C4* + ID_OUI_FROM_DATABASE=Elber Srl + +OUI:60B4F7* + ID_OUI_FROM_DATABASE=Plume Design Inc + +OUI:60B606* + ID_OUI_FROM_DATABASE=Phorus + +OUI:60B617* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:60B933* + ID_OUI_FROM_DATABASE=Deutron Electronics Corp. + +OUI:60B982* + ID_OUI_FROM_DATABASE=RO.VE.R. Laboratories S.p.A. + +OUI:60BA18* + ID_OUI_FROM_DATABASE=nextLAP GmbH + +OUI:60BB0C* + ID_OUI_FROM_DATABASE=Beijing HuaqinWorld Technology Co,Ltd + +OUI:60BC4C* + ID_OUI_FROM_DATABASE=EWM Hightec Welding GmbH + +OUI:60BD91* + ID_OUI_FROM_DATABASE=Move Innovation + +OUI:60BEB5* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:60C0BF* + ID_OUI_FROM_DATABASE=ON Semiconductor + +OUI:60C1CB* + ID_OUI_FROM_DATABASE=Fujian Great Power PLC Equipment Co.,Ltd + +OUI:60C397* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:60C547* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60C5A8* + ID_OUI_FROM_DATABASE=Beijing LT Honway Technology Co.,Ltd + +OUI:60C5AD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:60C658* + ID_OUI_FROM_DATABASE=PHYTRONIX Co.,Ltd. + +OUI:60C798* + ID_OUI_FROM_DATABASE=Verifone + +OUI:60C980* + ID_OUI_FROM_DATABASE=Trymus + +OUI:60CBFB* + ID_OUI_FROM_DATABASE=AirScape Inc. + +OUI:60CDA9* + ID_OUI_FROM_DATABASE=Abloomy + +OUI:60CDC5* + ID_OUI_FROM_DATABASE=Taiwan Carol Electronics., Ltd + +OUI:60CE86* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:60CE92* + ID_OUI_FROM_DATABASE=The Refined Industry Company Limited + +OUI:60D02C* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:60D0A9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:60D1AA* + ID_OUI_FROM_DATABASE=Vishal Telecommunications Pvt Ltd + +OUI:60D21C* + ID_OUI_FROM_DATABASE=Sunnovo International Limited + +OUI:60D248* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:60D262* + ID_OUI_FROM_DATABASE=Tzukuri Pty Ltd + +OUI:60D2B9* + ID_OUI_FROM_DATABASE=REALAND BIO CO., LTD. + +OUI:60D2DD* + ID_OUI_FROM_DATABASE=Shenzhen Baitong Putian Technology Co.,Ltd. + +OUI:60D30A* + ID_OUI_FROM_DATABASE=Quatius Limited + +OUI:60D755* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:60D7E30* + ID_OUI_FROM_DATABASE=Avalun + +OUI:60D7E31* + ID_OUI_FROM_DATABASE=Elap s.r.l. + +OUI:60D7E32* + ID_OUI_FROM_DATABASE=Novo innovations Ltd + +OUI:60D7E33* + ID_OUI_FROM_DATABASE=SKS Automaatio oy + +OUI:60D7E34* + ID_OUI_FROM_DATABASE=Hemisphere GNSS + +OUI:60D7E35* + ID_OUI_FROM_DATABASE=Revol Technologies inc + +OUI:60D7E36* + ID_OUI_FROM_DATABASE=Ameli s.r.l. + +OUI:60D7E37* + ID_OUI_FROM_DATABASE=Phase One A/S + +OUI:60D7E38* + ID_OUI_FROM_DATABASE=HindlePower, Inc + +OUI:60D7E39* + ID_OUI_FROM_DATABASE=LongSung Technology (Shanghai) Co.,Ltd. + +OUI:60D7E3A* + ID_OUI_FROM_DATABASE=Wilderness Labs Inc. + +OUI:60D7E3B* + ID_OUI_FROM_DATABASE=Nextivity + +OUI:60D7E3C* + ID_OUI_FROM_DATABASE=Zhejiang Send Intelligent Technology,Ltd + +OUI:60D7E3D* + ID_OUI_FROM_DATABASE=Quantronix, Inc. + +OUI:60D7E3E* + ID_OUI_FROM_DATABASE=HuBDIC CO.,LTD + +OUI:60D819* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:60D89C* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:60D9A0* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:60D9C7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60DA23* + ID_OUI_FROM_DATABASE=Estech Co.,Ltd + +OUI:60DA83* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:60DB2A* + ID_OUI_FROM_DATABASE=HNS + +OUI:60DE35* + ID_OUI_FROM_DATABASE=GITSN, Inc. + +OUI:60DE44* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:60DEF3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:60E00E* + ID_OUI_FROM_DATABASE=SHINSEI ELECTRONICS CO LTD + +OUI:60E327* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:60E3AC* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:60E6BC* + ID_OUI_FROM_DATABASE=Sino-Telecom Technology Co.,Ltd. + +OUI:60E701* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:60E78A* + ID_OUI_FROM_DATABASE=UNISEM + +OUI:60E956* + ID_OUI_FROM_DATABASE=Ayla Networks, Inc + +OUI:60EB69* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:60EE5C* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:60EFC6* + ID_OUI_FROM_DATABASE=Shenzhen Chima Technologies Co Limited + +OUI:60F13D* + ID_OUI_FROM_DATABASE=JABLOCOM s.r.o. + +OUI:60F189* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:60F18A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:60F262* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:60F281* + ID_OUI_FROM_DATABASE=TRANWO TECHNOLOGY CO., LTD. + +OUI:60F2EF* + ID_OUI_FROM_DATABASE=VisionVera International Co., Ltd. + +OUI:60F3DA* + ID_OUI_FROM_DATABASE=Logic Way GmbH + +OUI:60F445* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60F494* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:60F59C* + ID_OUI_FROM_DATABASE=CRU-Dataport + +OUI:60F673* + ID_OUI_FROM_DATABASE=TERUMO CORPORATION + +OUI:60F677* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:60F81D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60FA9D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:60FACD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60FB42* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60FD56* + ID_OUI_FROM_DATABASE=WOORISYSTEMS CO., Ltd + +OUI:60FE1E* + ID_OUI_FROM_DATABASE=China Palms Telecom.Ltd + +OUI:60FE20* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:60FEC5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:60FEF9* + ID_OUI_FROM_DATABASE=Thomas & Betts + +OUI:60FFDD* + ID_OUI_FROM_DATABASE=C.E. ELECTRONICS, INC + +OUI:64002D* + ID_OUI_FROM_DATABASE=Powerlinq Co., LTD + +OUI:64006A* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:6400F1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6402CB* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:6405BE* + ID_OUI_FROM_DATABASE=NEW LIGHT LED + +OUI:6405E9* + ID_OUI_FROM_DATABASE=Shenzhen WayOS Technology Crop., Ltd. + +OUI:64094C* + ID_OUI_FROM_DATABASE=Beijing Superbee Wireless Technology Co.,Ltd + +OUI:640980* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:6409AC* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:640B4A* + ID_OUI_FROM_DATABASE=Digital Telecom Technology Limited + +OUI:640DCE* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:640DE6* + ID_OUI_FROM_DATABASE=Petra Systems + +OUI:640E36* + ID_OUI_FROM_DATABASE=TAZTAG + +OUI:640E94* + ID_OUI_FROM_DATABASE=Pluribus Networks, Inc. + +OUI:640F28* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:641084* + ID_OUI_FROM_DATABASE=HEXIUM Technical Development Co., Ltd. + +OUI:641225* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:641236* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:641269* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:641331* + ID_OUI_FROM_DATABASE=Bosch Car Multimedia (Wuhu) Co. Ltd. + +OUI:64136C* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:641666* + ID_OUI_FROM_DATABASE=Nest Labs Inc. + +OUI:64167F* + ID_OUI_FROM_DATABASE=Polycom + +OUI:64168D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6416F0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:641A22* + ID_OUI_FROM_DATABASE=Heliospectra AB + +OUI:641C67* + ID_OUI_FROM_DATABASE=DIGIBRAS INDUSTRIA DO BRASILS/A + +OUI:641CAE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:641CB0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:641E81* + ID_OUI_FROM_DATABASE=Dowslake Microsystems + +OUI:64200C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:64209F* + ID_OUI_FROM_DATABASE=Tilgin AB + +OUI:642184* + ID_OUI_FROM_DATABASE=Nippon Denki Kagaku Co.,LTD + +OUI:642216* + ID_OUI_FROM_DATABASE=Shandong Taixin Electronic co.,Ltd + +OUI:642400* + ID_OUI_FROM_DATABASE=Xorcom Ltd. + +OUI:64255E* + ID_OUI_FROM_DATABASE=Observint Technologies, Inc. + +OUI:642737* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:6429ED* + ID_OUI_FROM_DATABASE=AO PKK Milandr + +OUI:642B8A* + ID_OUI_FROM_DATABASE=ALL BEST Industrial Co., Ltd. + +OUI:642CAC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:642DB7* + ID_OUI_FROM_DATABASE=SEUNGIL ELECTRONICS + +OUI:6431390* + ID_OUI_FROM_DATABASE=SHENZHEN EMEET INTELLIGENT TECHNOLOGY CO., LTD. + +OUI:6431391* + ID_OUI_FROM_DATABASE=Livongo Health + +OUI:6431392* + ID_OUI_FROM_DATABASE=Smartplus Inc. + +OUI:6431393* + ID_OUI_FROM_DATABASE=KOANGYOW INTEGRATION MACHINE CO., LTD. + +OUI:6431394* + ID_OUI_FROM_DATABASE=Active Brains + +OUI:6431395* + ID_OUI_FROM_DATABASE=Shenzhen He&e Technology Co.,Ltd. + +OUI:6431396* + ID_OUI_FROM_DATABASE=Hunan Voc Acoustics Technology Co., Ltd. + +OUI:6431397* + ID_OUI_FROM_DATABASE=Dongguan Huili electroacoustic Industrial Co.,ltd + +OUI:6431398* + ID_OUI_FROM_DATABASE=Shenzhen Huanyin Electronics Ltd. + +OUI:643139A* + ID_OUI_FROM_DATABASE=Product Development Associates, Inc. + +OUI:643139C* + ID_OUI_FROM_DATABASE=SHEN ZHEN FUCHANG TECHNOLOGY Co.,Ltd. + +OUI:643139D* + ID_OUI_FROM_DATABASE=ZHEJIANG MOORGEN INTELLIGENT TECHNOLOGY CO.,LTD + +OUI:643139E* + ID_OUI_FROM_DATABASE=ATG UV Technology + +OUI:643150* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:64317E* + ID_OUI_FROM_DATABASE=Dexin Corporation + +OUI:6432A8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:643409* + ID_OUI_FROM_DATABASE=BITwave Pte Ltd + +OUI:64351C* + ID_OUI_FROM_DATABASE=e-CON SYSTEMS INDIA PVT LTD + +OUI:643AB1* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:643E8C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:643F5F* + ID_OUI_FROM_DATABASE=Exablaze + +OUI:644214* + ID_OUI_FROM_DATABASE=Swisscom Energy Solutions AG + +OUI:644346* + ID_OUI_FROM_DATABASE=GuangDong Quick Network Computer CO.,LTD + +OUI:6447E0* + ID_OUI_FROM_DATABASE=Feitian Technologies Co., Ltd + +OUI:644BC3* + ID_OUI_FROM_DATABASE=Shanghai WOASiS Telecommunications Ltd., Co. + +OUI:644BF0* + ID_OUI_FROM_DATABASE=CalDigit, Inc + +OUI:644C36* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:644D70* + ID_OUI_FROM_DATABASE=dSPACE GmbH + +OUI:644F42* + ID_OUI_FROM_DATABASE=JETTER CO., Ltd. + +OUI:644F74* + ID_OUI_FROM_DATABASE=LENUS Co., Ltd. + +OUI:644FB0* + ID_OUI_FROM_DATABASE=Hyunjin.com + +OUI:645106* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:64517E* + ID_OUI_FROM_DATABASE=LONG BEN (DONGGUAN) ELECTRONIC TECHNOLOGY CO.,LTD. + +OUI:645299* + ID_OUI_FROM_DATABASE=The Chamberlain Group, Inc + +OUI:64535D* + ID_OUI_FROM_DATABASE=Frauscher Sensortechnik + +OUI:645422* + ID_OUI_FROM_DATABASE=Equinox Payments + +OUI:645563* + ID_OUI_FROM_DATABASE=Intelight Inc. + +OUI:64557F* + ID_OUI_FROM_DATABASE=NSFOCUS Information Technology Co., Ltd. + +OUI:6455B1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:645601* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:6458AD* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:6459F8* + ID_OUI_FROM_DATABASE=Vodafone Omnitel B.V. + +OUI:645A04* + ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd. + +OUI:645AED* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:645CF3* + ID_OUI_FROM_DATABASE=ParanTek Inc. + +OUI:645D86* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:645D92* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:645DD7* + ID_OUI_FROM_DATABASE=Shenzhen Lifesense Medical Electronics Co., Ltd. + +OUI:645E2C* + ID_OUI_FROM_DATABASE=IRay Technology Co., Ltd. + +OUI:645EBE* + ID_OUI_FROM_DATABASE=Yahoo! JAPAN + +OUI:645FFF* + ID_OUI_FROM_DATABASE=Nicolet Neuro + +OUI:646038* + ID_OUI_FROM_DATABASE=Hirschmann Automation and Control GmbH + +OUI:646184* + ID_OUI_FROM_DATABASE=VELUX + +OUI:646223* + ID_OUI_FROM_DATABASE=Cellient Co., Ltd. + +OUI:6462660* + ID_OUI_FROM_DATABASE=MiiVii Dynamics Technology CO.,LTD + +OUI:6462661* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:6462662* + ID_OUI_FROM_DATABASE=Protectli + +OUI:6462663* + ID_OUI_FROM_DATABASE=FaceHeart Inc. + +OUI:6462664* + ID_OUI_FROM_DATABASE=Redstone Systems, Inc. + +OUI:6462665* + ID_OUI_FROM_DATABASE=Bühler AG + +OUI:6462666* + ID_OUI_FROM_DATABASE=Pass & Seymour, Inc d/b/a Legrand + +OUI:6462667* + ID_OUI_FROM_DATABASE=Shenzhen C & D Electronics Co., Ltd. + +OUI:6462668* + ID_OUI_FROM_DATABASE=Leontech Limited + +OUI:6462669* + ID_OUI_FROM_DATABASE=Chunghwa System Integration Co., Ltd. + +OUI:646266A* + ID_OUI_FROM_DATABASE=Sensoro Co., Ltd. + +OUI:646266B* + ID_OUI_FROM_DATABASE=Signal Hound + +OUI:646266C* + ID_OUI_FROM_DATABASE=Jiangsu Aisida Electronic Co.,Ltd + +OUI:646266D* + ID_OUI_FROM_DATABASE=Kobol Innovations Pte. Ltd. + +OUI:646266E* + ID_OUI_FROM_DATABASE=Shenzhen Jie Shi Lian Industrial Co., LTD + +OUI:64628A* + ID_OUI_FROM_DATABASE=evon GmbH + +OUI:64649B* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:6465C0* + ID_OUI_FROM_DATABASE=Nuvon, Inc + +OUI:646624* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:6466B3* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:646707* + ID_OUI_FROM_DATABASE=Beijing Omnific Technology, Ltd. + +OUI:64680C* + ID_OUI_FROM_DATABASE=Comtrend Corporation + +OUI:64694E* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:6469BC* + ID_OUI_FROM_DATABASE=Hytera Communications Co .,ltd + +OUI:646A52* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:646A74* + ID_OUI_FROM_DATABASE=AUTH-SERVERS, LLC + +OUI:646CB2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:646D6C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:646E69* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:646E6C* + ID_OUI_FROM_DATABASE=Radio Datacom LLC + +OUI:646E97* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:646EEA* + ID_OUI_FROM_DATABASE=Iskratel d.o.o. + +OUI:647002* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:647033* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6472D8* + ID_OUI_FROM_DATABASE=GooWi Technology Co.,Limited + +OUI:647366* + ID_OUI_FROM_DATABASE=Shenzhen Siera Technology Ltd + +OUI:6473E2* + ID_OUI_FROM_DATABASE=Arbiter Systems, Inc. + +OUI:6474F6* + ID_OUI_FROM_DATABASE=Shooter Detection Systems + +OUI:647657* + ID_OUI_FROM_DATABASE=Innovative Security Designs + +OUI:6476BA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:64777D* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:647791* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6479A7* + ID_OUI_FROM_DATABASE=Phison Electronics Corp. + +OUI:647BCE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:647BD4* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:647C34* + ID_OUI_FROM_DATABASE=Ubee Interactive Co., Limited + +OUI:647D81* + ID_OUI_FROM_DATABASE=YOKOTA INDUSTRIAL CO,.LTD + +OUI:647FDA* + ID_OUI_FROM_DATABASE=TEKTELIC Communications Inc. + +OUI:64808B* + ID_OUI_FROM_DATABASE=VG Controls, Inc. + +OUI:648099* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:648125* + ID_OUI_FROM_DATABASE=Alphatron Marine BV + +OUI:648788* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:6487D7* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:6488FF* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. + +OUI:64899A* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:6489F1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:648D9E* + ID_OUI_FROM_DATABASE=IVT Electronic Co.,Ltd + +OUI:6490C1* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd + +OUI:64956C* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:649829* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:64995D* + ID_OUI_FROM_DATABASE=LGE + +OUI:649968* + ID_OUI_FROM_DATABASE=Elentec + +OUI:6499A0* + ID_OUI_FROM_DATABASE=AG Elektronik AB + +OUI:649A08* + ID_OUI_FROM_DATABASE=Shenzhen SuperElectron Technology Co.,LTD + +OUI:649A12* + ID_OUI_FROM_DATABASE=P2 Mobile Technologies Limited + +OUI:649ABE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:649B24* + ID_OUI_FROM_DATABASE=V Technology Co., Ltd. + +OUI:649C81* + ID_OUI_FROM_DATABASE=Qualcomm Inc. + +OUI:649C8E* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:649D99* + ID_OUI_FROM_DATABASE=FS COM INC + +OUI:649EF3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:649FF7* + ID_OUI_FROM_DATABASE=Kone OYj + +OUI:64A0E7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:64A232* + ID_OUI_FROM_DATABASE=OOO Samlight + +OUI:64A2F9* + ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd + +OUI:64A341* + ID_OUI_FROM_DATABASE=Wonderlan (Beijing) Technology Co., Ltd. + +OUI:64A3CB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:64A5C3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:64A651* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:64A68F* + ID_OUI_FROM_DATABASE=Zhongshan Readboy Electronics Co.,Ltd + +OUI:64A769* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:64A7DD* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:64A837* + ID_OUI_FROM_DATABASE=Juni Korea Co., Ltd + +OUI:64AE0C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:64AE88* + ID_OUI_FROM_DATABASE=Polytec GmbH + +OUI:64AEF1* + ID_OUI_FROM_DATABASE=Qingdao Hisense Electronics Co.,Ltd. + +OUI:64B0A6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:64B21D* + ID_OUI_FROM_DATABASE=Chengdu Phycom Tech Co., Ltd. + +OUI:64B310* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:64B370* + ID_OUI_FROM_DATABASE=PowerComm Solutions LLC + +OUI:64B473* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:64B5C6* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:64B64A* + ID_OUI_FROM_DATABASE=ViVOtech, Inc. + +OUI:64B853* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:64B9E8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:64BABD* + ID_OUI_FROM_DATABASE=SDJ Technologies, Inc. + +OUI:64BC0C* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:64BC11* + ID_OUI_FROM_DATABASE=CombiQ AB + +OUI:64BC58* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:64C2DE* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:64C354* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:64C3D6* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:64C5AA* + ID_OUI_FROM_DATABASE=South African Broadcasting Corporation + +OUI:64C667* + ID_OUI_FROM_DATABASE=Barnes&Noble + +OUI:64C6AF* + ID_OUI_FROM_DATABASE=AXERRA Networks Ltd + +OUI:64C753* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:64C901* + ID_OUI_FROM_DATABASE=INVENTEC Corporation + +OUI:64C944* + ID_OUI_FROM_DATABASE=LARK Technologies, Inc + +OUI:64CB5D* + ID_OUI_FROM_DATABASE=SIA TeleSet + +OUI:64CB9F* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:64CBA3* + ID_OUI_FROM_DATABASE=Pointmobile + +OUI:64CC22* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:64CC2E* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:64CE6E* + ID_OUI_FROM_DATABASE=Sierra Wireless + +OUI:64CFD9* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:64D02D* + ID_OUI_FROM_DATABASE=Next Generation Integration (NGI) + +OUI:64D154* + ID_OUI_FROM_DATABASE=Routerboard.com + +OUI:64D1A3* + ID_OUI_FROM_DATABASE=Sitecom Europe BV + +OUI:64D241* + ID_OUI_FROM_DATABASE=Keith & Koep GmbH + +OUI:64D4BD* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:64D4DA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:64D814* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:64D912* + ID_OUI_FROM_DATABASE=Solidica, Inc. + +OUI:64D954* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:64D989* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:64DAA0* + ID_OUI_FROM_DATABASE=Robert Bosch Smart Home GmbH + +OUI:64DB18* + ID_OUI_FROM_DATABASE=OpenPattern + +OUI:64DB43* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:64DB81* + ID_OUI_FROM_DATABASE=Syszone Co., Ltd. + +OUI:64DB8B* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:64DBA0* + ID_OUI_FROM_DATABASE=Select Comfort + +OUI:64DC01* + ID_OUI_FROM_DATABASE=Static Systems Group PLC + +OUI:64DE1C* + ID_OUI_FROM_DATABASE=Kingnetic Pte Ltd + +OUI:64DF10* + ID_OUI_FROM_DATABASE=JingLue Semiconductor(SH) Ltd. + +OUI:64DFE9* + ID_OUI_FROM_DATABASE=ATEME + +OUI:64E161* + ID_OUI_FROM_DATABASE=DEP Corp. + +OUI:64E599* + ID_OUI_FROM_DATABASE=EFM Networks + +OUI:64E625* + ID_OUI_FROM_DATABASE=Woxu Wireless Co., Ltd + +OUI:64E682* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:64E84F* + ID_OUI_FROM_DATABASE=Serialway Communication Technology Co. Ltd + +OUI:64E892* + ID_OUI_FROM_DATABASE=Morio Denki Co., Ltd. + +OUI:64E8E6* + ID_OUI_FROM_DATABASE=global moisture management system + +OUI:64E950* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:64EAC5* + ID_OUI_FROM_DATABASE=SiboTech Automation Co., Ltd. + +OUI:64EB8C* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:64ED57* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:64ED62* + ID_OUI_FROM_DATABASE=WOORI SYSTEMS Co., Ltd + +OUI:64EEB7* + ID_OUI_FROM_DATABASE=Netcore Technology Inc + +OUI:64F242* + ID_OUI_FROM_DATABASE=Gerdes Aktiengesellschaft + +OUI:64F2FB* + ID_OUI_FROM_DATABASE=Hangzhou Ezviz Software Co.,Ltd. + +OUI:64F50E* + ID_OUI_FROM_DATABASE=Kinion Technology Company Limited + +OUI:64F69D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:64F6BB* + ID_OUI_FROM_DATABASE=Fibocom Wireless Inc. + +OUI:64F6F7* + ID_OUI_FROM_DATABASE=Anhui Dynamic Power Co., Ltd. + +OUI:64F81C* + ID_OUI_FROM_DATABASE=Huawei Technologies Co., Ltd. + +OUI:64F88A* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:64F970* + ID_OUI_FROM_DATABASE=Kenade Electronics Technology Co.,LTD. + +OUI:64F987* + ID_OUI_FROM_DATABASE=Avvasi Inc. + +OUI:64F9C0* + ID_OUI_FROM_DATABASE=ANALOG DEVICES + +OUI:64FB50* + ID_OUI_FROM_DATABASE=RoomReady/Zdi, Inc. + +OUI:64FB810* + ID_OUI_FROM_DATABASE=SHANGHAI SIMCOM LIMITED + +OUI:64FB811* + ID_OUI_FROM_DATABASE=Narrative AB + +OUI:64FB812* + ID_OUI_FROM_DATABASE=Seven Solutions S.L + +OUI:64FB813* + ID_OUI_FROM_DATABASE=MOBILUS Inc. + +OUI:64FB814* + ID_OUI_FROM_DATABASE=Pricer AB + +OUI:64FB815* + ID_OUI_FROM_DATABASE=Kay Schulze & Karsten Pohle GbR + +OUI:64FB816* + ID_OUI_FROM_DATABASE=XIMO Communication Technology Co., Ltd + +OUI:64FB817* + ID_OUI_FROM_DATABASE=Securosys SA + +OUI:64FB818* + ID_OUI_FROM_DATABASE=NPG Technology S.A. + +OUI:64FB819* + ID_OUI_FROM_DATABASE=hiQview Corporation + +OUI:64FB81A* + ID_OUI_FROM_DATABASE=Bronkhorst High-Tech BV + +OUI:64FB81B* + ID_OUI_FROM_DATABASE=Sichuan Haige Actec Communication Technology Co.,Ltd. + +OUI:64FB81C* + ID_OUI_FROM_DATABASE=Bridgeport Instruments, LLC + +OUI:64FB81D* + ID_OUI_FROM_DATABASE=Dongyang unitech.co.ltd + +OUI:64FB81E* + ID_OUI_FROM_DATABASE=ChengDu KeChuang LongXin Sci-tech Co.,Ltd + +OUI:64FB81F* + ID_OUI_FROM_DATABASE=Private + +OUI:64FB92* + ID_OUI_FROM_DATABASE=PPC Broadband Inc. + +OUI:64FC8C* + ID_OUI_FROM_DATABASE=Zonar Systems + +OUI:64FF0A* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:680235* + ID_OUI_FROM_DATABASE=Konten Networks Inc. + +OUI:6802B8* + ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. + +OUI:680571* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6805CA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:68070A* + ID_OUI_FROM_DATABASE=TPVision Europe B.V + +OUI:680715* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:680927* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:680AD7* + ID_OUI_FROM_DATABASE=Yancheng Kecheng Optoelectronic Technology Co., Ltd + +OUI:680AE2* + ID_OUI_FROM_DATABASE=Silicon Laboratories + +OUI:68122D* + ID_OUI_FROM_DATABASE=Special Instrument Development Co., Ltd. + +OUI:681295* + ID_OUI_FROM_DATABASE=Lupine Lighting Systems GmbH + +OUI:681401* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:681590* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:6815D3* + ID_OUI_FROM_DATABASE=Zaklady Elektroniki i Mechaniki Precyzyjnej R&G S.A. + +OUI:681605* + ID_OUI_FROM_DATABASE=Systems And Electronic Development FZCO + +OUI:681729* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:68193F* + ID_OUI_FROM_DATABASE=Digital Airways + +OUI:6819AC* + ID_OUI_FROM_DATABASE=Guangzhou Xianyou Intelligent Technogoly CO., LTD + +OUI:681AB2* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:681CA2* + ID_OUI_FROM_DATABASE=Rosewill Inc. + +OUI:681D64* + ID_OUI_FROM_DATABASE=Sunwave Communications Co., Ltd + +OUI:681DEF* + ID_OUI_FROM_DATABASE=Shenzhen CYX Technology Co., Ltd. + +OUI:681E8B* + ID_OUI_FROM_DATABASE=InfoSight Corporation + +OUI:681F40* + ID_OUI_FROM_DATABASE=Blu Wireless Technology Ltd + +OUI:681FD8* + ID_OUI_FROM_DATABASE=Siemens Industry, Inc. + +OUI:68215F* + ID_OUI_FROM_DATABASE=Edgecore Networks Corporation + +OUI:68234B* + ID_OUI_FROM_DATABASE=Nihon Dengyo Kousaku + +OUI:68262A* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:682719* + ID_OUI_FROM_DATABASE=Microchip Technology Inc. + +OUI:682737* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6828BA* + ID_OUI_FROM_DATABASE=Dejai + +OUI:6828F6* + ID_OUI_FROM_DATABASE=Vubiq Networks, Inc. + +OUI:6829DC* + ID_OUI_FROM_DATABASE=Ficosa Electronics S.L.U. + +OUI:682C7B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:682DDC* + ID_OUI_FROM_DATABASE=Wuhan Changjiang Electro-Communication Equipment CO.,LTD + +OUI:6831FE* + ID_OUI_FROM_DATABASE=Teladin Co.,Ltd. + +OUI:683489* + ID_OUI_FROM_DATABASE=LEA Professional + +OUI:683563* + ID_OUI_FROM_DATABASE=SHENZHEN LIOWN ELECTRONICS CO.,LTD. + +OUI:6836B5* + ID_OUI_FROM_DATABASE=DriveScale, Inc. + +OUI:6837E9* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:683943* + ID_OUI_FROM_DATABASE=ittim + +OUI:683A1E* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:683B1E* + ID_OUI_FROM_DATABASE=Countwise LTD + +OUI:683B78* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:683C7D* + ID_OUI_FROM_DATABASE=Magic Intelligence Technology Limited + +OUI:683E02* + ID_OUI_FROM_DATABASE=SIEMENS AG, Digital Factory, Motion Control System + +OUI:683E34* + ID_OUI_FROM_DATABASE=MEIZU Technology Co., Ltd. + +OUI:683EEC* + ID_OUI_FROM_DATABASE=ERECA + +OUI:683F1E* + ID_OUI_FROM_DATABASE=EFFECT Photonics B.V. + +OUI:684352* + ID_OUI_FROM_DATABASE=Bhuu Limited + +OUI:6843D7* + ID_OUI_FROM_DATABASE=Agilecom Photonics Solutions Guangdong Limited + +OUI:6845F1* + ID_OUI_FROM_DATABASE=TOSHIBA CLIENT SOLUTIONS CO., LTD. + +OUI:684749* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:684898* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6849B2* + ID_OUI_FROM_DATABASE=CARLO GAVAZZI LTD + +OUI:684A76* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:684AAE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:684B88* + ID_OUI_FROM_DATABASE=Galtronics Telemetry Inc. + +OUI:684CA8* + ID_OUI_FROM_DATABASE=Shenzhen Herotel Tech. Co., Ltd. + +OUI:684F64* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:6851B7* + ID_OUI_FROM_DATABASE=PowerCloud Systems, Inc. + +OUI:68536C* + ID_OUI_FROM_DATABASE=SPnS Co.,Ltd + +OUI:685388* + ID_OUI_FROM_DATABASE=P&S Technology + +OUI:6854C1* + ID_OUI_FROM_DATABASE=ColorTokens, Inc. + +OUI:6854ED* + ID_OUI_FROM_DATABASE=Alcatel-Lucent + +OUI:6854F5* + ID_OUI_FROM_DATABASE=enLighted Inc + +OUI:6854FD* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:68572D* + ID_OUI_FROM_DATABASE=HANGZHOU AIXIANGJI TECHNOLOGY CO., LTD + +OUI:6858C5* + ID_OUI_FROM_DATABASE=ZF TRW Automotive + +OUI:68597F* + ID_OUI_FROM_DATABASE=Alcatel Lucent + +OUI:685ACF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:685B35* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:685B36* + ID_OUI_FROM_DATABASE=POWERTECH INDUSTRIAL CO., LTD. + +OUI:685D43* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:685E6B* + ID_OUI_FROM_DATABASE=PowerRay Co., Ltd. + +OUI:686350* + ID_OUI_FROM_DATABASE=Hella India Automotive Pvt Ltd + +OUI:686359* + ID_OUI_FROM_DATABASE=Advanced Digital Broadcast SA + +OUI:68644B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:68692E* + ID_OUI_FROM_DATABASE=Zycoo Co.,Ltd + +OUI:686975* + ID_OUI_FROM_DATABASE=Angler Labs Inc + +OUI:6869CA* + ID_OUI_FROM_DATABASE=Hitachi, Ltd. + +OUI:6869F2* + ID_OUI_FROM_DATABASE=ComAp s.r.o. + +OUI:686DBC* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:686E23* + ID_OUI_FROM_DATABASE=Wi3 Inc. + +OUI:686E48* + ID_OUI_FROM_DATABASE=Prophet Electronic Technology Corp.,Ltd + +OUI:687251* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:6872DC* + ID_OUI_FROM_DATABASE=CETORY.TV Company Limited + +OUI:68764F* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:687848* + ID_OUI_FROM_DATABASE=Westunitis Co., Ltd. + +OUI:68784C* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:687924* + ID_OUI_FROM_DATABASE=ELS-GmbH & Co. KG + +OUI:6879ED* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:687CC8* + ID_OUI_FROM_DATABASE=Measurement Systems S. de R.L. + +OUI:687CD5* + ID_OUI_FROM_DATABASE=Y Soft Corporation, a.s. + +OUI:687D6B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:687F74* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:6882F2* + ID_OUI_FROM_DATABASE=grandcentrix GmbH + +OUI:68831A* + ID_OUI_FROM_DATABASE=Pandora Mobility Corporation + +OUI:688470* + ID_OUI_FROM_DATABASE=eSSys Co.,Ltd + +OUI:68847E* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:688540* + ID_OUI_FROM_DATABASE=IGI Mobile, Inc. + +OUI:68856A* + ID_OUI_FROM_DATABASE=OuterLink Corporation + +OUI:6886A7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6886E7* + ID_OUI_FROM_DATABASE=Orbotix, Inc. + +OUI:68876B* + ID_OUI_FROM_DATABASE=INQ Mobile Limited + +OUI:688975* + ID_OUI_FROM_DATABASE=nuoxc + +OUI:6889C1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:688AB5* + ID_OUI_FROM_DATABASE=EDP Servicos + +OUI:688AF0* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:688B0F* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:688DB6* + ID_OUI_FROM_DATABASE=AETEK INC. + +OUI:688F2E* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:688F84* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:688FC9* + ID_OUI_FROM_DATABASE=Zhuolian (Shenzhen) Communication Co., Ltd + +OUI:6891D00* + ID_OUI_FROM_DATABASE=Central Railway Manufacturing + +OUI:6891D01* + ID_OUI_FROM_DATABASE=Multi Alarm Zrt. + +OUI:6891D02* + ID_OUI_FROM_DATABASE=Shenzhen NeaTech Intelligence Technology Co., Ltd. + +OUI:6891D03* + ID_OUI_FROM_DATABASE=Ambitio LLC + +OUI:6891D04* + ID_OUI_FROM_DATABASE=G-TECH Instruments Inc. + +OUI:6891D05* + ID_OUI_FROM_DATABASE=NIPK Electron Co. + +OUI:6891D06* + ID_OUI_FROM_DATABASE=femrice + +OUI:6891D07* + ID_OUI_FROM_DATABASE=Omniimpex GmbH + +OUI:6891D08* + ID_OUI_FROM_DATABASE=solvimus GmbH + +OUI:6891D09* + ID_OUI_FROM_DATABASE=QUANTEX + +OUI:6891D0A* + ID_OUI_FROM_DATABASE=WiseCube + +OUI:6891D0B* + ID_OUI_FROM_DATABASE=Altis Technology + +OUI:6891D0C* + ID_OUI_FROM_DATABASE=Spraying Systems Co. + +OUI:6891D0D* + ID_OUI_FROM_DATABASE=Fuzhou x-speed information technology Co.,Ltd. + +OUI:6891D0E* + ID_OUI_FROM_DATABASE=Outstanding Technology Co., Ltd. + +OUI:689234* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:689361* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:689423* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:68967B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:68974B* + ID_OUI_FROM_DATABASE=Shenzhen Costar Electronics Co. Ltd. + +OUI:6897E8* + ID_OUI_FROM_DATABASE=Society of Motion Picture & Television Engineers + +OUI:689861* + ID_OUI_FROM_DATABASE=Beacon Inc + +OUI:6899CD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:689A87* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:689AB7* + ID_OUI_FROM_DATABASE=Atelier Vision Corporation + +OUI:689C5E* + ID_OUI_FROM_DATABASE=AcSiP Technology Corp. + +OUI:689C70* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:689CE2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:689E19* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:689FF0* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:68A03E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:68A0F6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:68A1B7* + ID_OUI_FROM_DATABASE=Honghao Mingchuan Technology (Beijing) CO.,Ltd. + +OUI:68A378* + ID_OUI_FROM_DATABASE=FREEBOX SAS + +OUI:68A3C4* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:68A40E* + ID_OUI_FROM_DATABASE=BSH Hausgeräte GmbH + +OUI:68A47D* + ID_OUI_FROM_DATABASE=Sun Cupid Technology (HK) LTD + +OUI:68A682* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:68A828* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:68A86D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:68A8E1* + ID_OUI_FROM_DATABASE=Wacom Co.,Ltd. + +OUI:68AAD2* + ID_OUI_FROM_DATABASE=DATECS LTD., + +OUI:68AB09* + ID_OUI_FROM_DATABASE=Nokia + +OUI:68AB1E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:68AB8A* + ID_OUI_FROM_DATABASE=RF IDeas + +OUI:68AE20* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:68AF13* + ID_OUI_FROM_DATABASE=Futura Mobility + +OUI:68AFFF* + ID_OUI_FROM_DATABASE=Shanghai Cambricon Information Technology Co., Ltd. + +OUI:68B094* + ID_OUI_FROM_DATABASE=INESA ELECTRON CO.,LTD + +OUI:68B35E* + ID_OUI_FROM_DATABASE=Shenzhen Neostra Technology Co.Ltd + +OUI:68B43A* + ID_OUI_FROM_DATABASE=WaterFurnace International, Inc. + +OUI:68B599* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:68B6FC* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:68B8D9* + ID_OUI_FROM_DATABASE=Act KDE, Inc. + +OUI:68B983* + ID_OUI_FROM_DATABASE=b-plus GmbH + +OUI:68B9D3* + ID_OUI_FROM_DATABASE=Shenzhen Trolink Technology CO, LTD + +OUI:68BC0C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:68BDAB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:68BFC4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:68C44D* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:68C63A* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:68C90B* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:68CA00* + ID_OUI_FROM_DATABASE=Octopus Systems Limited + +OUI:68CAE4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:68CC6E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:68CC9C* + ID_OUI_FROM_DATABASE=Mine Site Technologies + +OUI:68CD0F* + ID_OUI_FROM_DATABASE=U Tek Company Limited + +OUI:68CE4E* + ID_OUI_FROM_DATABASE=L-3 Communications Infrared Products + +OUI:68D1BA* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:68D1FD* + ID_OUI_FROM_DATABASE=Shenzhen Trimax Technology Co.,Ltd + +OUI:68D247* + ID_OUI_FROM_DATABASE=Portalis LC + +OUI:68D482* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:68D79A* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:68D925* + ID_OUI_FROM_DATABASE=ProSys Development Services + +OUI:68D93C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:68DB54* + ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd. + +OUI:68DB67* + ID_OUI_FROM_DATABASE=Nantong Coship Electronics Co., Ltd. + +OUI:68DB96* + ID_OUI_FROM_DATABASE=OPWILL Technologies CO .,LTD + +OUI:68DBCA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:68DBF5* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:68DCE8* + ID_OUI_FROM_DATABASE=PacketStorm Communications + +OUI:68DD26* + ID_OUI_FROM_DATABASE=Shanghai Focus Vision Security Technology Co.,Ltd + +OUI:68DFDD* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:68E166* + ID_OUI_FROM_DATABASE=Private + +OUI:68E41F* + ID_OUI_FROM_DATABASE=Unglaube Identech GmbH + +OUI:68E7C2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:68E8EB* + ID_OUI_FROM_DATABASE=Linktel Technologies Co.,Ltd + +OUI:68EBAE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:68EBC5* + ID_OUI_FROM_DATABASE=Angstrem Telecom + +OUI:68EC62* + ID_OUI_FROM_DATABASE=YODO Technology Corp. Ltd. + +OUI:68ECC5* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:68ED43* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:68EDA4* + ID_OUI_FROM_DATABASE=Shenzhen Seavo Technology Co.,Ltd + +OUI:68EE96* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:68EF43* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:68EFBD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:68F06D* + ID_OUI_FROM_DATABASE=ALONG INDUSTRIAL CO., LIMITED + +OUI:68F0BC* + ID_OUI_FROM_DATABASE=Shenzhen LiWiFi Technology Co., Ltd + +OUI:68F125* + ID_OUI_FROM_DATABASE=Data Controls Inc. + +OUI:68F728* + ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd + +OUI:68F895* + ID_OUI_FROM_DATABASE=Redflow Limited + +OUI:68F956* + ID_OUI_FROM_DATABASE=Objetivos y Servicio de Valor Añadido + +OUI:68FB7E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:68FB95* + ID_OUI_FROM_DATABASE=Generalplus Technology Inc. + +OUI:68FCB3* + ID_OUI_FROM_DATABASE=Next Level Security Systems, Inc. + +OUI:68FEDA* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:68FEF7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:68FF7B* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:6C006B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6C0273* + ID_OUI_FROM_DATABASE=Shenzhen Jin Yun Video Equipment Co., Ltd. + +OUI:6C0460* + ID_OUI_FROM_DATABASE=RBH Access Technologies Inc. + +OUI:6C05D5* + ID_OUI_FROM_DATABASE=Ethertronics Inc + +OUI:6C06D6* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:6C090A* + ID_OUI_FROM_DATABASE=GEMATICA SRL + +OUI:6C09D6* + ID_OUI_FROM_DATABASE=Digiquest Electronics LTD + +OUI:6C0B84* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:6C0D34* + ID_OUI_FROM_DATABASE=Nokia + +OUI:6C0E0D* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:6C0EE6* + ID_OUI_FROM_DATABASE=Chengdu Xiyida Electronic Technology Co,.Ltd + +OUI:6C0F6A* + ID_OUI_FROM_DATABASE=JDC Tech Co., Ltd. + +OUI:6C14F7* + ID_OUI_FROM_DATABASE=Erhardt+Leimer GmbH + +OUI:6C15F9* + ID_OUI_FROM_DATABASE=Nautronix Limited + +OUI:6C160E* + ID_OUI_FROM_DATABASE=ShotTracker + +OUI:6C1632* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:6C1811* + ID_OUI_FROM_DATABASE=Decatur Electronics + +OUI:6C198F* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:6C19C0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C1C71* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:6C1DEB* + ID_OUI_FROM_DATABASE=u-blox AG + +OUI:6C1E70* + ID_OUI_FROM_DATABASE=Guangzhou YBDS IT Co.,Ltd + +OUI:6C1E90* + ID_OUI_FROM_DATABASE=Hansol Technics Co., Ltd. + +OUI:6C2056* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C21A2* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:6C22AB* + ID_OUI_FROM_DATABASE=Ainsworth Game Technology + +OUI:6C23B9* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:6C23CB* + ID_OUI_FROM_DATABASE=Wattty Corporation + +OUI:6C2483* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:6C24A6* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:6C25B9* + ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + +OUI:6C2779* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:6C2990* + ID_OUI_FROM_DATABASE=WiZ Connected Lighting Company Limited + +OUI:6C2995* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:6C2ACB* + ID_OUI_FROM_DATABASE=Paxton Access Ltd + +OUI:6C2B59* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:6C2C06* + ID_OUI_FROM_DATABASE=OOO NPP Systemotechnika-NN + +OUI:6C2CDC* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:6C2E33* + ID_OUI_FROM_DATABASE=Accelink Technologies Co.,Ltd. + +OUI:6C2E72* + ID_OUI_FROM_DATABASE=B&B EXPORTING LIMITED + +OUI:6C2E85* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:6C2F2C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6C310E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C32DE* + ID_OUI_FROM_DATABASE=Indieon Technologies Pvt. Ltd. + +OUI:6C33A9* + ID_OUI_FROM_DATABASE=Magicjack LP + +OUI:6C3838* + ID_OUI_FROM_DATABASE=Marking System Technology Co., Ltd. + +OUI:6C3845* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:6C38A1* + ID_OUI_FROM_DATABASE=Ubee Interactive Co., Limited + +OUI:6C391D* + ID_OUI_FROM_DATABASE=Beijing ZhongHuaHun Network Information center + +OUI:6C3A84* + ID_OUI_FROM_DATABASE=Shenzhen Aero-Startech. Co.Ltd + +OUI:6C3B6B* + ID_OUI_FROM_DATABASE=Routerboard.com + +OUI:6C3BE5* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:6C3C53* + ID_OUI_FROM_DATABASE=SoundHawk Corp + +OUI:6C3E6D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C3E9C* + ID_OUI_FROM_DATABASE=KE Knestel Elektronik GmbH + +OUI:6C4008* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C40C6* + ID_OUI_FROM_DATABASE=Nimbus Data, Inc. + +OUI:6C410E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C416A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C42AB* + ID_OUI_FROM_DATABASE=Subscriber Networks, Inc. + +OUI:6C4418* + ID_OUI_FROM_DATABASE=Zappware + +OUI:6C4598* + ID_OUI_FROM_DATABASE=Antex Electronic Corp. + +OUI:6C49C1* + ID_OUI_FROM_DATABASE=o2ones Co., Ltd. + +OUI:6C4A39* + ID_OUI_FROM_DATABASE=BITA + +OUI:6C4A85* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C4B7F* + ID_OUI_FROM_DATABASE=Vossloh-Schwabe Deutschland GmbH + +OUI:6C4B90* + ID_OUI_FROM_DATABASE=LiteON + +OUI:6C4D51* + ID_OUI_FROM_DATABASE=Shenzhen Ceres Technology Co., Ltd. + +OUI:6C4D73* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C4E86* + ID_OUI_FROM_DATABASE=Third Millennium Systems Ltd. + +OUI:6C504D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C54CD* + ID_OUI_FROM_DATABASE=LAMPEX ELECTRONICS LIMITED + +OUI:6C55E8* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:6C5697* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:6C5779* + ID_OUI_FROM_DATABASE=Aclima, Inc. + +OUI:6C5940* + ID_OUI_FROM_DATABASE=MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:6C5976* + ID_OUI_FROM_DATABASE=Shanghai Tricheer Technology Co.,Ltd. + +OUI:6C5A34* + ID_OUI_FROM_DATABASE=Shenzhen Haitianxiong Electronic Co., Ltd. + +OUI:6C5AB5* + ID_OUI_FROM_DATABASE=TCL Technoly Electronics (Huizhou) Co., Ltd. + +OUI:6C5C14* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:6C5C3D0* + ID_OUI_FROM_DATABASE=ShenZhen Hugsun Technology Co.,Ltd. + +OUI:6C5C3D1* + ID_OUI_FROM_DATABASE=Shenzhen Justek Technology Co., Ltd + +OUI:6C5C3D2* + ID_OUI_FROM_DATABASE=Vertiv Industrial Systems + +OUI:6C5C3D3* + ID_OUI_FROM_DATABASE=KWONG MING ELECTRICAL MANUFACTORY LIMITED + +OUI:6C5C3D4* + ID_OUI_FROM_DATABASE=HTI Co., LTD. + +OUI:6C5C3D5* + ID_OUI_FROM_DATABASE=Unitel Engineering + +OUI:6C5C3D6* + ID_OUI_FROM_DATABASE=Hangzhou Netease Yanxuan Trading Co.,Ltd + +OUI:6C5C3D7* + ID_OUI_FROM_DATABASE=SOUNDKING ELECTRONICS&SOUND CO., LTD. + +OUI:6C5C3D8* + ID_OUI_FROM_DATABASE=GUANGZHOU GUANGRI ELEVATOR INDUSTRY CO.,LTD + +OUI:6C5C3D9* + ID_OUI_FROM_DATABASE=IskraUralTEL + +OUI:6C5C3DA* + ID_OUI_FROM_DATABASE=krtkl inc. + +OUI:6C5C3DB* + ID_OUI_FROM_DATABASE=Reconova Technologies + +OUI:6C5C3DC* + ID_OUI_FROM_DATABASE=choyang powertech + +OUI:6C5C3DD* + ID_OUI_FROM_DATABASE=Syowatsusinkougyo Co.,Ltd. + +OUI:6C5C3DE* + ID_OUI_FROM_DATABASE=Clinton Electronics Corporation + +OUI:6C5CDE* + ID_OUI_FROM_DATABASE=SunReports, Inc. + +OUI:6C5D3A* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:6C5D63* + ID_OUI_FROM_DATABASE=ShenZhen Rapoo Technology Co., Ltd. + +OUI:6C5E3B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C5E7A* + ID_OUI_FROM_DATABASE=Ubiquitous Internet Telecom Co., Ltd + +OUI:6C5F1C* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:6C60EB* + ID_OUI_FROM_DATABASE=ZHI YUAN ELECTRONICS CO., LIMITED + +OUI:6C6126* + ID_OUI_FROM_DATABASE=Rinicom Holdings + +OUI:6C61F4* + ID_OUI_FROM_DATABASE=SFR + +OUI:6C626D* + ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD + +OUI:6C639C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:6C641A* + ID_OUI_FROM_DATABASE=Penguin Computing + +OUI:6C6A77* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:6C6CD3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C6EFE* + ID_OUI_FROM_DATABASE=Core Logic Inc. + +OUI:6C6F18* + ID_OUI_FROM_DATABASE=Stereotaxis, Inc. + +OUI:6C7039* + ID_OUI_FROM_DATABASE=Novar GmbH + +OUI:6C709F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C710D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C71BD* + ID_OUI_FROM_DATABASE=EZELINK TELECOM + +OUI:6C71D9* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:6C7220* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:6C72E7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C750D* + ID_OUI_FROM_DATABASE=WiFiSONG + +OUI:6C7660* + ID_OUI_FROM_DATABASE=KYOCERA CORPORATION + +OUI:6C81FE* + ID_OUI_FROM_DATABASE=Mitsuba Corporation + +OUI:6C8336* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6C8366* + ID_OUI_FROM_DATABASE=Nanjing SAC Power Grid Automation Co., Ltd. + +OUI:6C8686* + ID_OUI_FROM_DATABASE=Technonia + +OUI:6C8814* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:6C8AEC* + ID_OUI_FROM_DATABASE=Nantong Coship Electronics Co., Ltd. + +OUI:6C8B2F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:6C8BD3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C8CDB* + ID_OUI_FROM_DATABASE=Otus Technologies Ltd + +OUI:6C8D65* + ID_OUI_FROM_DATABASE=Wireless Glue Networks, Inc. + +OUI:6C8DC1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C8FB5* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:6C90B1* + ID_OUI_FROM_DATABASE=SanLogic Inc + +OUI:6C92BF* + ID_OUI_FROM_DATABASE=Inspur Electronic Information Industry Co.,Ltd. + +OUI:6C9354* + ID_OUI_FROM_DATABASE=Yaojin Technology (Shenzhen) Co., LTD. + +OUI:6C94F8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C9522* + ID_OUI_FROM_DATABASE=Scalys + +OUI:6C96CF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6C98EB* + ID_OUI_FROM_DATABASE=Riverbed Technology, Inc. + +OUI:6C9989* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C9AC9* + ID_OUI_FROM_DATABASE=Valentine Research, Inc. + +OUI:6C9B02* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:6C9BC0* + ID_OUI_FROM_DATABASE=Chemoptics Inc. + +OUI:6C9CE9* + ID_OUI_FROM_DATABASE=Nimble Storage + +OUI:6C9CED* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6C9E7C* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:6CA100* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:6CA604* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:6CA682* + ID_OUI_FROM_DATABASE=EDAM information & communications + +OUI:6CA75F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:6CA780* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:6CA7FA* + ID_OUI_FROM_DATABASE=YOUNGBO ENGINEERING INC. + +OUI:6CA849* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:6CA858* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:6CA906* + ID_OUI_FROM_DATABASE=Telefield Ltd + +OUI:6CA928* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:6CA936* + ID_OUI_FROM_DATABASE=DisplayLink (UK) Ltd + +OUI:6CA96F* + ID_OUI_FROM_DATABASE=TransPacket AS + +OUI:6CAAB3* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:6CAB05* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6CAB31* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6CAB4D* + ID_OUI_FROM_DATABASE=Digital Payment Technologies + +OUI:6CAC60* + ID_OUI_FROM_DATABASE=Venetex Corp + +OUI:6CAD3F* + ID_OUI_FROM_DATABASE=Hubbell Building Automation, Inc. + +OUI:6CADEF* + ID_OUI_FROM_DATABASE=KZ Broadband Technologies, Ltd. + +OUI:6CADF8* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:6CAE8B* + ID_OUI_FROM_DATABASE=IBM Corporation + +OUI:6CAEF6* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:6CAF15* + ID_OUI_FROM_DATABASE=Webasto SE + +OUI:6CB0CE* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:6CB227* + ID_OUI_FROM_DATABASE=Sony Video & Sound Products Inc. + +OUI:6CB2AE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6CB311* + ID_OUI_FROM_DATABASE=Shenzhen Lianrui Electronics Co.,Ltd + +OUI:6CB350* + ID_OUI_FROM_DATABASE=Anhui comhigher tech co.,ltd + +OUI:6CB4A7* + ID_OUI_FROM_DATABASE=Landauer, Inc. + +OUI:6CB56B* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:6CB6CA* + ID_OUI_FROM_DATABASE=DIVUS GmbH + +OUI:6CB749* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:6CB7F4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6CB9C5* + ID_OUI_FROM_DATABASE=Delta Networks, Inc. + +OUI:6CBEE9* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:6CBFB5* + ID_OUI_FROM_DATABASE=Noon Technology Co., Ltd + +OUI:6CC147* + ID_OUI_FROM_DATABASE=Xiamen Hanin Electronic Technology Co., Ltd + +OUI:6CC1D2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:6CC217* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:6CC26B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6CC374* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:6CC4D5* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:6CC63B* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:6CC7EC* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:6CCA08* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:6CD032* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:6CD146* + ID_OUI_FROM_DATABASE=FRAMOS GmbH + +OUI:6CD1B0* + ID_OUI_FROM_DATABASE=WING SING ELECTRONICS HONG KONG LIMITED + +OUI:6CD2BA* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:6CD68A* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:6CD71F* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:6CD94C* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:6CDC6A* + ID_OUI_FROM_DATABASE=Promethean Limited + +OUI:6CDD30* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6CDDBC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6CDFFB0* + ID_OUI_FROM_DATABASE=Shenzhen HDCVT Technology + +OUI:6CDFFB1* + ID_OUI_FROM_DATABASE=Chongqing Baoli Yota Technologies Limited + +OUI:6CDFFB2* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:6CDFFB3* + ID_OUI_FROM_DATABASE=Beijing Ainemo Co Ltd + +OUI:6CDFFB4* + ID_OUI_FROM_DATABASE=Lineable Inc + +OUI:6CDFFB5* + ID_OUI_FROM_DATABASE=Greenbird Vertriebs GmbH + +OUI:6CDFFB6* + ID_OUI_FROM_DATABASE=AAON + +OUI:6CDFFB7* + ID_OUI_FROM_DATABASE=Hashtrend AG + +OUI:6CDFFB8* + ID_OUI_FROM_DATABASE=Hardmeier + +OUI:6CDFFB9* + ID_OUI_FROM_DATABASE=YongTechs Electric Co. Ltd + +OUI:6CDFFBA* + ID_OUI_FROM_DATABASE=Guilin Zhishen Information TechonlogyCO.,Ltd + +OUI:6CDFFBB* + ID_OUI_FROM_DATABASE=CELL System Co.,Ltd. + +OUI:6CDFFBC* + ID_OUI_FROM_DATABASE=Toucan Systems Ltd + +OUI:6CDFFBD* + ID_OUI_FROM_DATABASE=Nanjing Buruike Electronics Technology Co., Ltd. + +OUI:6CDFFBE* + ID_OUI_FROM_DATABASE=Beijing Fimi Technology Co., Ltd. + +OUI:6CE01E* + ID_OUI_FROM_DATABASE=Modcam AB + +OUI:6CE0B0* + ID_OUI_FROM_DATABASE=SOUND4 + +OUI:6CE3B6* + ID_OUI_FROM_DATABASE=Nera Telecommunications Ltd. + +OUI:6CE4CE* + ID_OUI_FROM_DATABASE=Villiger Security Solutions AG + +OUI:6CE4DA* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. + +OUI:6CE85C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:6CE873* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:6CE8C6* + ID_OUI_FROM_DATABASE=Earda Technologies co Ltd + +OUI:6CE907* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:6CE983* + ID_OUI_FROM_DATABASE=Gastron Co., LTD. + +OUI:6CEBB2* + ID_OUI_FROM_DATABASE=Dongguan Sen DongLv Electronics Co.,Ltd + +OUI:6CEBB6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:6CEC5A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. CO.,Ltd. + +OUI:6CECA1* + ID_OUI_FROM_DATABASE=SHENZHEN CLOU ELECTRONICS CO. LTD. + +OUI:6CECEB* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:6CED51* + ID_OUI_FROM_DATABASE=NEXCONTROL Co.,Ltd + +OUI:6CEFC6* + ID_OUI_FROM_DATABASE=SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. + +OUI:6CF049* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:6CF17E* + ID_OUI_FROM_DATABASE=Zhejiang Uniview Technologies Co.,Ltd. + +OUI:6CF373* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:6CF37F* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:6CF5E8* + ID_OUI_FROM_DATABASE=Mooredoll Inc. + +OUI:6CF712* + ID_OUI_FROM_DATABASE=Nokia + +OUI:6CF97C* + ID_OUI_FROM_DATABASE=Nanoptix Inc. + +OUI:6CF9D2* + ID_OUI_FROM_DATABASE=CHENGDU POVODO ELECTRONIC TECHNOLOGY CO., LTD + +OUI:6CFA58* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:6CFA89* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:6CFAA7* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:6CFDB9* + ID_OUI_FROM_DATABASE=Proware Technologies Co Ltd. + +OUI:6CFFBE* + ID_OUI_FROM_DATABASE=MPB Communications Inc. + +OUI:700136* + ID_OUI_FROM_DATABASE=FATEK Automation Corporation + +OUI:7001B5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:700258* + ID_OUI_FROM_DATABASE=01DB-METRAVIB + +OUI:70037E* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:700433* + ID_OUI_FROM_DATABASE=California Things Inc. + +OUI:700514* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:7006AC* + ID_OUI_FROM_DATABASE=Eastcompeace Technology Co., Ltd + +OUI:700B01* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:700B4F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:700BC0* + ID_OUI_FROM_DATABASE=Dewav Technology Company + +OUI:700F6A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:700FC7* + ID_OUI_FROM_DATABASE=SHENZHEN IKINLOOP TECHNOLOGY CO.,LTD. + +OUI:700FEC* + ID_OUI_FROM_DATABASE=Poindus Systems Corp. + +OUI:70105C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70106F* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:701124* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7011AE* + ID_OUI_FROM_DATABASE=Music Life LTD + +OUI:701404* + ID_OUI_FROM_DATABASE=Limited Liability Company + +OUI:7014A6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70169F* + ID_OUI_FROM_DATABASE=EtherCAT Technology Group + +OUI:70188B* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:7018A7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70192F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:701A04* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:701AED* + ID_OUI_FROM_DATABASE=ADVAS CO., LTD. + +OUI:701BFB* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:701CE7* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:701D08* + ID_OUI_FROM_DATABASE=99IOT Shenzhen co.,ltd + +OUI:701D7F* + ID_OUI_FROM_DATABASE=Comtech Technology Co., Ltd. + +OUI:701DC4* + ID_OUI_FROM_DATABASE=NorthStar Battery Company, LLC + +OUI:701E68* + ID_OUI_FROM_DATABASE=Hanna Instruments, Inc. + +OUI:701F3C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:701F53* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:702084* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co., Ltd. + +OUI:702393* + ID_OUI_FROM_DATABASE=fos4X GmbH + +OUI:702526* + ID_OUI_FROM_DATABASE=Nokia + +OUI:702559* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. + +OUI:702605* + ID_OUI_FROM_DATABASE=SONY Visual Products Inc. + +OUI:70288B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:702900* + ID_OUI_FROM_DATABASE=Shenzhen ChipTrip Technology Co,Ltd + +OUI:702A7D* + ID_OUI_FROM_DATABASE=EpSpot AB + +OUI:702AD5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:702B1D* + ID_OUI_FROM_DATABASE=E-Domus International Limited + +OUI:702C1F* + ID_OUI_FROM_DATABASE=Wisol + +OUI:702D84* + ID_OUI_FROM_DATABASE=i4C Innovations + +OUI:702DD1* + ID_OUI_FROM_DATABASE=Newings Communication CO., LTD. + +OUI:702E22* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:702E80* + ID_OUI_FROM_DATABASE=DIEHL Connectivity Solutions + +OUI:702ED9* + ID_OUI_FROM_DATABASE=Guangzhou Shiyuan Electronics Co., Ltd. + +OUI:702F35* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:702F4B* + ID_OUI_FROM_DATABASE=PolyVision Inc. + +OUI:702F97* + ID_OUI_FROM_DATABASE=Aava Mobile Oy + +OUI:703018* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:70305D* + ID_OUI_FROM_DATABASE=Ubiquoss Inc + +OUI:70305E* + ID_OUI_FROM_DATABASE=Nanjing Zhongke Menglian Information Technology Co.,LTD + +OUI:703187* + ID_OUI_FROM_DATABASE=ACX GmbH + +OUI:7032D5* + ID_OUI_FROM_DATABASE=Athena Wireless Communications Inc + +OUI:703509* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:703811* + ID_OUI_FROM_DATABASE=Siemens Mobility Limited + +OUI:7038B4* + ID_OUI_FROM_DATABASE=Low Tech Solutions + +OUI:7038EE* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:703A0E* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:703A51* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:703A73* + ID_OUI_FROM_DATABASE=Shenzhen Sundray Technologies Company Limited + +OUI:703ACB* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:703AD8* + ID_OUI_FROM_DATABASE=Shenzhen Afoundry Electronic Co., Ltd + +OUI:703C03* + ID_OUI_FROM_DATABASE=RadiAnt Co.,Ltd + +OUI:703C39* + ID_OUI_FROM_DATABASE=SEAWING Kft + +OUI:703C69* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:703D15* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:703EAC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7041B7* + ID_OUI_FROM_DATABASE=Edwards Lifesciences LLC + +OUI:70441C* + ID_OUI_FROM_DATABASE=SHENZHEN KAIFA TECHNOLOGY CO.,LTD. + +OUI:704642* + ID_OUI_FROM_DATABASE=CHYNG HONG ELECTRONIC CO., LTD. + +OUI:7047E9* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:70480F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7048F7* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:704A0E* + ID_OUI_FROM_DATABASE=AMPAK Technology,Inc. + +OUI:704AAE* + ID_OUI_FROM_DATABASE=Xstream Flow (Pty) Ltd + +OUI:704AE4* + ID_OUI_FROM_DATABASE=Rinstrum Pty Ltd + +OUI:704CA5* + ID_OUI_FROM_DATABASE=Fortinet, Inc. + +OUI:704CED* + ID_OUI_FROM_DATABASE=TMRG, Inc. + +OUI:704D7B* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:704E01* + ID_OUI_FROM_DATABASE=KWANGWON TECH CO., LTD. + +OUI:704E66* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:704F08* + ID_OUI_FROM_DATABASE=Shenzhen Huisheng Information Technology Co., Ltd. + +OUI:704F57* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:704FB8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:7050AF* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:7052C5* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:70533F* + ID_OUI_FROM_DATABASE=Alfa Instrumentos Eletronicos Ltda. + +OUI:705425* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:7054B4* + ID_OUI_FROM_DATABASE=Vestel Elektronik San ve Tic. A.Ş. + +OUI:7054D2* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:7054F5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7055F8* + ID_OUI_FROM_DATABASE=Cerebras Systems Inc + +OUI:705681* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7057BF* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:705812* + ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company + +OUI:705896* + ID_OUI_FROM_DATABASE=InShow Technology + +OUI:705957* + ID_OUI_FROM_DATABASE=Medallion Instrumentation Systems + +OUI:705986* + ID_OUI_FROM_DATABASE=OOO TTV + +OUI:705A0F* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:705A9E* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:705AAC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:705AB6* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:705B2E* + ID_OUI_FROM_DATABASE=M2Communication Inc. + +OUI:705CAD* + ID_OUI_FROM_DATABASE=Konami Gaming Inc + +OUI:705DCC* + ID_OUI_FROM_DATABASE=EFM Networks + +OUI:705E55* + ID_OUI_FROM_DATABASE=Realme Chongqing MobileTelecommunications Corp Ltd + +OUI:705EAA* + ID_OUI_FROM_DATABASE=Action Target, Inc. + +OUI:7060DE* + ID_OUI_FROM_DATABASE=LaVision GmbH + +OUI:706173* + ID_OUI_FROM_DATABASE=Calantec GmbH + +OUI:7062B8* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:706417* + ID_OUI_FROM_DATABASE=ORBIS TECNOLOGIA ELECTRICA S.A. + +OUI:706582* + ID_OUI_FROM_DATABASE=Suzhou Hanming Technologies Co., Ltd. + +OUI:7065A3* + ID_OUI_FROM_DATABASE=Kandao lightforge Co., Ltd. + +OUI:70661B* + ID_OUI_FROM_DATABASE=Sonova AG + +OUI:706655* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:706879* + ID_OUI_FROM_DATABASE=Saijo Denki International Co., Ltd. + +OUI:70695A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:706BB9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:706D15* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:706DEC* + ID_OUI_FROM_DATABASE=Wifi-soft LLC + +OUI:706E6D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:706F81* + ID_OUI_FROM_DATABASE=Private + +OUI:70700D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70704C* + ID_OUI_FROM_DATABASE=Purple Communications, Inc + +OUI:70708B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7071B3* + ID_OUI_FROM_DATABASE=Brain Corporation + +OUI:7071BC* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:70720D* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:70723C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7072CF* + ID_OUI_FROM_DATABASE=EdgeCore Networks + +OUI:7073CB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:707630* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:7076DD* + ID_OUI_FROM_DATABASE=OxyGuard Internation A/S + +OUI:7076F0* + ID_OUI_FROM_DATABASE=LevelOne Communications (India) Private Limited + +OUI:7076FF* + ID_OUI_FROM_DATABASE=KERLINK + +OUI:707781* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:70788B* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:707938* + ID_OUI_FROM_DATABASE=Wuxi Zhanrui Electronic Technology Co.,LTD + +OUI:707990* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7079B3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:707BE8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:707C18* + ID_OUI_FROM_DATABASE=ADATA Technology Co., Ltd + +OUI:707C69* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:707D95* + ID_OUI_FROM_DATABASE=Shenzhen City LinwlanTechnology Co. Ltd. + +OUI:707DB9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:707E43* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:707EDE* + ID_OUI_FROM_DATABASE=NASTEC LTD. + +OUI:708105* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7081EB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70820E* + ID_OUI_FROM_DATABASE=as electronics GmbH + +OUI:70828E* + ID_OUI_FROM_DATABASE=OleumTech Corporation + +OUI:708540* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:7085C2* + ID_OUI_FROM_DATABASE=ASRock Incorporation + +OUI:7085C6* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:7086C1* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:70879E* + ID_OUI_FROM_DATABASE=Beken Corporation + +OUI:70884D* + ID_OUI_FROM_DATABASE=JAPAN RADIO CO., LTD. + +OUI:70886B0* + ID_OUI_FROM_DATABASE=Veracity UK Ltd + +OUI:70886B1* + ID_OUI_FROM_DATABASE=Bitfinder Inc + +OUI:70886B2* + ID_OUI_FROM_DATABASE=CVnet + +OUI:70886B4* + ID_OUI_FROM_DATABASE=HORI CO., LTD. + +OUI:70886B5* + ID_OUI_FROM_DATABASE=Chengdu Ophylink Communication Technology Ltd. + +OUI:70886B6* + ID_OUI_FROM_DATABASE=Church & Dwight Co., Inc. + +OUI:70886B8* + ID_OUI_FROM_DATABASE=Cable Matters Inc. + +OUI:70886B9* + ID_OUI_FROM_DATABASE=Shenzhen Coolhear Information Technology Co., Ltd. + +OUI:70886BA* + ID_OUI_FROM_DATABASE=RHXTune Technology Co.,Ltd + +OUI:70886BB* + ID_OUI_FROM_DATABASE=Beijing Strongleader Science & Technology Co., Ltd. + +OUI:70886BC* + ID_OUI_FROM_DATABASE=MAX4G, Inc. + +OUI:7089CC* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:708A09* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:708B78* + ID_OUI_FROM_DATABASE=citygrow technology co., ltd + +OUI:708BCD* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:708D09* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:70918F* + ID_OUI_FROM_DATABASE=Weber-Stephen Products LLC + +OUI:7091F3* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. + +OUI:709383* + ID_OUI_FROM_DATABASE=Intelligent Optical Network High Tech CO.,LTD. + +OUI:7093F8* + ID_OUI_FROM_DATABASE=Space Monkey, Inc. + +OUI:709756* + ID_OUI_FROM_DATABASE=Happyelectronics Co.,Ltd + +OUI:70991C* + ID_OUI_FROM_DATABASE=Shenzhen Honesty Electronics Co.,Ltd + +OUI:709A0B* + ID_OUI_FROM_DATABASE=Italian Institute of Technology + +OUI:709BA5* + ID_OUI_FROM_DATABASE=Shenzhen Y&D Electronics Co.,LTD. + +OUI:709BFC* + ID_OUI_FROM_DATABASE=Bryton Inc. + +OUI:709C8F* + ID_OUI_FROM_DATABASE=Nero AG + +OUI:709E29* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:709E86* + ID_OUI_FROM_DATABASE=X6D Limited + +OUI:709F2D* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:709FA9* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:70A191* + ID_OUI_FROM_DATABASE=Trendsetter Medical, LLC + +OUI:70A2B3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70A41C* + ID_OUI_FROM_DATABASE=Advanced Wireless Dynamics S.L. + +OUI:70A66A* + ID_OUI_FROM_DATABASE=Prox Dynamics AS + +OUI:70A84C* + ID_OUI_FROM_DATABASE=MONAD., Inc. + +OUI:70A8E3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:70AAB2* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:70ACD7* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:70AD54* + ID_OUI_FROM_DATABASE=Malvern Instruments Ltd + +OUI:70AF24* + ID_OUI_FROM_DATABASE=TP Vision Belgium NV + +OUI:70AF25* + ID_OUI_FROM_DATABASE=Nishiyama Industry Co.,LTD. + +OUI:70AF6A* + ID_OUI_FROM_DATABASE=SHENZHEN FENGLIAN TECHNOLOGY CO., LTD. + +OUI:70B035* + ID_OUI_FROM_DATABASE=Shenzhen Zowee Technology Co., Ltd + +OUI:70B08C* + ID_OUI_FROM_DATABASE=Shenou Communication Equipment Co.,Ltd + +OUI:70B14E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:70B265* + ID_OUI_FROM_DATABASE=Hiltron s.r.l. + +OUI:70B317* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70B3D5001* + ID_OUI_FROM_DATABASE=SOREDI touch systems GmbH + +OUI:70B3D5002* + ID_OUI_FROM_DATABASE=Gogo BA + +OUI:70B3D5003* + ID_OUI_FROM_DATABASE=ANYROAM + +OUI:70B3D5006* + ID_OUI_FROM_DATABASE=Piranha EMS Inc. + +OUI:70B3D5007* + ID_OUI_FROM_DATABASE=SENSONEO + +OUI:70B3D5008* + ID_OUI_FROM_DATABASE=ESYSE GmbH Embedded Systems Engineering + +OUI:70B3D5009* + ID_OUI_FROM_DATABASE=HolidayCoro + +OUI:70B3D500A* + ID_OUI_FROM_DATABASE=FUJICOM Co.,Ltd. + +OUI:70B3D500B* + ID_OUI_FROM_DATABASE=AXING AG + +OUI:70B3D500C* + ID_OUI_FROM_DATABASE=EXARA Group + +OUI:70B3D500D* + ID_OUI_FROM_DATABASE=Scrona AG + +OUI:70B3D500E* + ID_OUI_FROM_DATABASE=Magosys Systems LTD + +OUI:70B3D5010* + ID_OUI_FROM_DATABASE=Hanwa Electronic Ind.Co.,Ltd. + +OUI:70B3D5011* + ID_OUI_FROM_DATABASE=Sumer Data S.L + +OUI:70B3D5012* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D5013* + ID_OUI_FROM_DATABASE=Sportsbeams Lighting, Inc. + +OUI:70B3D5014* + ID_OUI_FROM_DATABASE=FRAKO Kondensatoren und Anlagenbau GmbH + +OUI:70B3D5015* + ID_OUI_FROM_DATABASE=EN ElectronicNetwork Hamburg GmbH + +OUI:70B3D5016* + ID_OUI_FROM_DATABASE=Guardian Controls International Ltd + +OUI:70B3D5017* + ID_OUI_FROM_DATABASE=FTG Corporation + +OUI:70B3D5019* + ID_OUI_FROM_DATABASE=Transit Solutions, LLC. + +OUI:70B3D501A* + ID_OUI_FROM_DATABASE=Cubro Acronet GesmbH + +OUI:70B3D501B* + ID_OUI_FROM_DATABASE=AUDI AG + +OUI:70B3D501C* + ID_OUI_FROM_DATABASE=Kumu Networks + +OUI:70B3D501D* + ID_OUI_FROM_DATABASE=Weigl Elektronik & Mediaprojekte + +OUI:70B3D501E* + ID_OUI_FROM_DATABASE=ePOINT Embedded Computing Limited + +OUI:70B3D501F* + ID_OUI_FROM_DATABASE=SPX Flow Technology BV + +OUI:70B3D5020* + ID_OUI_FROM_DATABASE=MICRO DEBUG, Y.K. + +OUI:70B3D5021* + ID_OUI_FROM_DATABASE=HGL Dynamics Ltd + +OUI:70B3D5022* + ID_OUI_FROM_DATABASE=Ravelin Ltd + +OUI:70B3D5023* + ID_OUI_FROM_DATABASE=Cambridge Pixel + +OUI:70B3D5024* + ID_OUI_FROM_DATABASE=G+D Mobile Security + +OUI:70B3D5025* + ID_OUI_FROM_DATABASE=Elsuhd Net Ltd Co. + +OUI:70B3D5026* + ID_OUI_FROM_DATABASE=Telstra + +OUI:70B3D5027* + ID_OUI_FROM_DATABASE=Redcap Solutions s.r.o. + +OUI:70B3D5028* + ID_OUI_FROM_DATABASE=AT-Automation Technology GmbH + +OUI:70B3D5029* + ID_OUI_FROM_DATABASE=Marimo electronics Co.,Ltd. + +OUI:70B3D502A* + ID_OUI_FROM_DATABASE=BAE Systems Surface Ships Limited + +OUI:70B3D502B* + ID_OUI_FROM_DATABASE=Scorpion Precision Industry (HK)CO. Ltd. + +OUI:70B3D502D* + ID_OUI_FROM_DATABASE=NEXTtec srl + +OUI:70B3D502E* + ID_OUI_FROM_DATABASE=Monnit Corporation + +OUI:70B3D502F* + ID_OUI_FROM_DATABASE=LEGENDAIRE TECHNOLOGY CO., LTD. + +OUI:70B3D5030* + ID_OUI_FROM_DATABASE=Tresent Technologies + +OUI:70B3D5031* + ID_OUI_FROM_DATABASE=SHENZHEN GAONA ELECTRONIC CO.LTD + +OUI:70B3D5032* + ID_OUI_FROM_DATABASE=iFreecomm Technology Co., Ltd + +OUI:70B3D5033* + ID_OUI_FROM_DATABASE=Sailmon BV + +OUI:70B3D5034* + ID_OUI_FROM_DATABASE=Digital Systems Engineering + +OUI:70B3D5035* + ID_OUI_FROM_DATABASE=HKW-Elektronik GmbH + +OUI:70B3D5037* + ID_OUI_FROM_DATABASE=EIFFAGE ENERGIE ELECTRONIQUE + +OUI:70B3D5038* + ID_OUI_FROM_DATABASE=DONG IL VISION Co., Ltd. + +OUI:70B3D5039* + ID_OUI_FROM_DATABASE=DoWoo Digitech + +OUI:70B3D503A* + ID_OUI_FROM_DATABASE=Ochno AB + +OUI:70B3D503B* + ID_OUI_FROM_DATABASE=SSL - Electrical Aerospace Ground Equipment Section + +OUI:70B3D503C* + ID_OUI_FROM_DATABASE=Ultimate Software + +OUI:70B3D503D* + ID_OUI_FROM_DATABASE=QUERCUS TECHNOLOGIES, S.L. + +OUI:70B3D503E* + ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd. + +OUI:70B3D503F* + ID_OUI_FROM_DATABASE=Elesar Limited + +OUI:70B3D5040* + ID_OUI_FROM_DATABASE=Savari Inc + +OUI:70B3D5041* + ID_OUI_FROM_DATABASE=FIBERNET LTD + +OUI:70B3D5042* + ID_OUI_FROM_DATABASE=Coveloz Technologies Inc. + +OUI:70B3D5043* + ID_OUI_FROM_DATABASE=cal4care Pte Ltd + +OUI:70B3D5044* + ID_OUI_FROM_DATABASE=Don Electronics Ltd + +OUI:70B3D5045* + ID_OUI_FROM_DATABASE=Navaero Avionics AB + +OUI:70B3D5046* + ID_OUI_FROM_DATABASE=Shenzhen Rihuida Electronics Co,. Ltd + +OUI:70B3D5048* + ID_OUI_FROM_DATABASE=AvMap srlu + +OUI:70B3D5049* + ID_OUI_FROM_DATABASE=APP Engineering, Inc. + +OUI:70B3D504A* + ID_OUI_FROM_DATABASE=Gecko Robotics Inc + +OUI:70B3D504B* + ID_OUI_FROM_DATABASE=Dream I System Co., Ltd + +OUI:70B3D504C* + ID_OUI_FROM_DATABASE=mapna group + +OUI:70B3D504D* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D504E* + ID_OUI_FROM_DATABASE=HUGEL GmbH + +OUI:70B3D5050* + ID_OUI_FROM_DATABASE=Compusign Systems Pty Ltd + +OUI:70B3D5052* + ID_OUI_FROM_DATABASE=Sudo Premium Engineering + +OUI:70B3D5053* + ID_OUI_FROM_DATABASE=YAMAKATSU ELECTRONICS INDUSTRY CO., LTD. + +OUI:70B3D5054* + ID_OUI_FROM_DATABASE=Groupeer Technologies + +OUI:70B3D5056* + ID_OUI_FROM_DATABASE=MIRAE INFORMATION TECHNOLOGY CO., LTD. + +OUI:70B3D5057* + ID_OUI_FROM_DATABASE=RCH ITALIA SPA + +OUI:70B3D5058* + ID_OUI_FROM_DATABASE=Telink Semiconductor CO, Limtied, Taiwan + +OUI:70B3D5059* + ID_OUI_FROM_DATABASE=Pro-Digital Projetos Eletronicos Ltda + +OUI:70B3D505A* + ID_OUI_FROM_DATABASE=Uni Control System Sp. z o. o. + +OUI:70B3D505B* + ID_OUI_FROM_DATABASE=PAL Inc. + +OUI:70B3D505C* + ID_OUI_FROM_DATABASE=Amber Kinetics Inc + +OUI:70B3D505D* + ID_OUI_FROM_DATABASE=KOMS Co.,Ltd. + +OUI:70B3D505E* + ID_OUI_FROM_DATABASE=VITEC + +OUI:70B3D505F* + ID_OUI_FROM_DATABASE=UNISOR MULTISYSTEMS LTD + +OUI:70B3D5060* + ID_OUI_FROM_DATABASE=RCH Vietnam Limited Liability Company + +OUI:70B3D5061* + ID_OUI_FROM_DATABASE=IntelliDesign Pty Ltd + +OUI:70B3D5062* + ID_OUI_FROM_DATABASE=RM Michaelides Software & Elektronik GmbH + +OUI:70B3D5063* + ID_OUI_FROM_DATABASE=PoolDigital GmbH & Co. KG + +OUI:70B3D5064* + ID_OUI_FROM_DATABASE=AB PRECISION (POOLE) LTD + +OUI:70B3D5066* + ID_OUI_FROM_DATABASE=North Pole Engineering, Inc. + +OUI:70B3D5067* + ID_OUI_FROM_DATABASE=NEOPATH INTEGRATED SYSTEMS LTDA + +OUI:70B3D5068* + ID_OUI_FROM_DATABASE=Onethinx BV + +OUI:70B3D5069* + ID_OUI_FROM_DATABASE=ONDEMAND LABORATORY Co., Ltd. + +OUI:70B3D506A* + ID_OUI_FROM_DATABASE=Guangdong Centnet Technology Co.,Ltd + +OUI:70B3D506B* + ID_OUI_FROM_DATABASE=U-Tech + +OUI:70B3D506C* + ID_OUI_FROM_DATABASE=AppTek + +OUI:70B3D506E* + ID_OUI_FROM_DATABASE=GLOBAL-KING INTERNATIONAL CO., LTD. + +OUI:70B3D506F* + ID_OUI_FROM_DATABASE=Beijing Daswell Science and Technology Co.LTD + +OUI:70B3D5070* + ID_OUI_FROM_DATABASE=Lumiplan Duhamel + +OUI:70B3D5071* + ID_OUI_FROM_DATABASE=FSR, INC. + +OUI:70B3D5072* + ID_OUI_FROM_DATABASE=Lightdrop + +OUI:70B3D5073* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:70B3D5074* + ID_OUI_FROM_DATABASE=Orlaco Products B.V. + +OUI:70B3D5075* + ID_OUI_FROM_DATABASE=Mo-Sys Engineering Ltd + +OUI:70B3D5077* + ID_OUI_FROM_DATABASE=InAccess Networks SA + +OUI:70B3D5078* + ID_OUI_FROM_DATABASE=OrbiWise SA + +OUI:70B3D5079* + ID_OUI_FROM_DATABASE=CheckBill Co,Ltd. + +OUI:70B3D507A* + ID_OUI_FROM_DATABASE=ZAO ZEO + +OUI:70B3D507B* + ID_OUI_FROM_DATABASE=wallbe GmbH + +OUI:70B3D507C* + ID_OUI_FROM_DATABASE=ISAC SRL + +OUI:70B3D507D* + ID_OUI_FROM_DATABASE=PANORAMIC POWER + +OUI:70B3D507E* + ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic CO., LTD + +OUI:70B3D507F* + ID_OUI_FROM_DATABASE=Abalance Corporation + +OUI:70B3D5080* + ID_OUI_FROM_DATABASE=ABB + +OUI:70B3D5081* + ID_OUI_FROM_DATABASE=IST Technologies (SHENZHEN) Limited + +OUI:70B3D5082* + ID_OUI_FROM_DATABASE=Sakura Seiki Co.,Ltd. + +OUI:70B3D5083* + ID_OUI_FROM_DATABASE=ZAO ZEO + +OUI:70B3D5084* + ID_OUI_FROM_DATABASE=Rako Controls Ltd + +OUI:70B3D5085* + ID_OUI_FROM_DATABASE=Human Systems Integration + +OUI:70B3D5086* + ID_OUI_FROM_DATABASE=Husty M.Styczen J.Hupert Sp.J. + +OUI:70B3D5087* + ID_OUI_FROM_DATABASE=Tempus Fugit Consoles bvba + +OUI:70B3D5088* + ID_OUI_FROM_DATABASE=OptiScan Biomedical Corp. + +OUI:70B3D508A* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D508B* + ID_OUI_FROM_DATABASE=Peter Huber Kaeltemaschinenbau AG + +OUI:70B3D508C* + ID_OUI_FROM_DATABASE=Airmar Technology Corp + +OUI:70B3D508D* + ID_OUI_FROM_DATABASE=Clover Electronics Technology Co., Ltd. + +OUI:70B3D508E* + ID_OUI_FROM_DATABASE=Beijing CONvision Technology Co.,Ltd + +OUI:70B3D508F* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D5090* + ID_OUI_FROM_DATABASE=POWERCRAFT ELECTRONICS PVT. LTD. + +OUI:70B3D5091* + ID_OUI_FROM_DATABASE=PROFITT Ltd + +OUI:70B3D5092* + ID_OUI_FROM_DATABASE=inomed Medizintechnik GmbH + +OUI:70B3D5093* + ID_OUI_FROM_DATABASE=Legrand Electric Ltd + +OUI:70B3D5094* + ID_OUI_FROM_DATABASE=Circuitlink Pty Ltd + +OUI:70B3D5096* + ID_OUI_FROM_DATABASE=HAVELSAN A.Ş. + +OUI:70B3D5097* + ID_OUI_FROM_DATABASE=Avant Technologies + +OUI:70B3D5098* + ID_OUI_FROM_DATABASE=Alcodex Technologies Private Limited + +OUI:70B3D5099* + ID_OUI_FROM_DATABASE=Schwer+Kopka GmbH + +OUI:70B3D509A* + ID_OUI_FROM_DATABASE=Akse srl + +OUI:70B3D509B* + ID_OUI_FROM_DATABASE=Jacarta Ltd + +OUI:70B3D509D* + ID_OUI_FROM_DATABASE=P&S GmbH + +OUI:70B3D509E* + ID_OUI_FROM_DATABASE=MobiPromo + +OUI:70B3D509F* + ID_OUI_FROM_DATABASE=COMTECH Kft. + +OUI:70B3D50A0* + ID_OUI_FROM_DATABASE=Cominfo, Inc. + +OUI:70B3D50A1* + ID_OUI_FROM_DATABASE=PTN Electronics Limited + +OUI:70B3D50A2* + ID_OUI_FROM_DATABASE=TechSigno srl + +OUI:70B3D50A3* + ID_OUI_FROM_DATABASE=Solace Systems Inc. + +OUI:70B3D50A4* + ID_OUI_FROM_DATABASE=Communication Technology Ltd. + +OUI:70B3D50A5* + ID_OUI_FROM_DATABASE=FUELCELLPOWER + +OUI:70B3D50A6* + ID_OUI_FROM_DATABASE=PA CONSULTING SERVICES + +OUI:70B3D50A7* + ID_OUI_FROM_DATABASE=Traffic and Parking Control Co, Inc. + +OUI:70B3D50A8* + ID_OUI_FROM_DATABASE=Symetrics Industries d.b.a. Extant Aerospace + +OUI:70B3D50A9* + ID_OUI_FROM_DATABASE=ProConnections, Inc. + +OUI:70B3D50AA* + ID_OUI_FROM_DATABASE=Wanco Inc + +OUI:70B3D50AB* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D50AC* + ID_OUI_FROM_DATABASE=RoboCore Tecnologia + +OUI:70B3D50AD* + ID_OUI_FROM_DATABASE=Vega-Absolute + +OUI:70B3D50AE* + ID_OUI_FROM_DATABASE=Norsat International Inc. + +OUI:70B3D50AF* + ID_OUI_FROM_DATABASE=KMtronic ltd + +OUI:70B3D50B0* + ID_OUI_FROM_DATABASE=Raven Systems Design, Inc + +OUI:70B3D50B1* + ID_OUI_FROM_DATABASE=AirBie AG + +OUI:70B3D50B2* + ID_OUI_FROM_DATABASE=ndb technologies + +OUI:70B3D50B3* + ID_OUI_FROM_DATABASE=Reonix Automation + +OUI:70B3D50B4* + ID_OUI_FROM_DATABASE=AVER + +OUI:70B3D50B5* + ID_OUI_FROM_DATABASE=Capgemini Netherlands + +OUI:70B3D50B6* + ID_OUI_FROM_DATABASE=Landis Gyr + +OUI:70B3D50B8* + ID_OUI_FROM_DATABASE=Lucas-Nülle GmbH + +OUI:70B3D50B9* + ID_OUI_FROM_DATABASE=Easy Digital Concept + +OUI:70B3D50BA* + ID_OUI_FROM_DATABASE=Ayre Acoustics, Inc. + +OUI:70B3D50BC* + ID_OUI_FROM_DATABASE=Practical Software Studio LLC + +OUI:70B3D50BD* + ID_OUI_FROM_DATABASE=Andium + +OUI:70B3D50BE* + ID_OUI_FROM_DATABASE=ChamSys Ltd + +OUI:70B3D50BF* + ID_OUI_FROM_DATABASE=Den Automation + +OUI:70B3D50C0* + ID_OUI_FROM_DATABASE=Molu Technology Inc., LTD. + +OUI:70B3D50C1* + ID_OUI_FROM_DATABASE=Nexus Technologies Pty Ltd + +OUI:70B3D50C2* + ID_OUI_FROM_DATABASE=LOOK EASY INTERNATIONAL LIMITED + +OUI:70B3D50C3* + ID_OUI_FROM_DATABASE=Aug. Winkhaus GmbH & Co. KG + +OUI:70B3D50C4* + ID_OUI_FROM_DATABASE=TIAMA + +OUI:70B3D50C5* + ID_OUI_FROM_DATABASE=Precitec Optronik GmbH + +OUI:70B3D50C6* + ID_OUI_FROM_DATABASE=Embedded Arts Co., Ltd. + +OUI:70B3D50C7* + ID_OUI_FROM_DATABASE=PEEK TRAFFIC + +OUI:70B3D50C8* + ID_OUI_FROM_DATABASE=Fin Robotics Inc + +OUI:70B3D50C9* + ID_OUI_FROM_DATABASE=LINEAGE POWER PVT LTD., + +OUI:70B3D50CA* + ID_OUI_FROM_DATABASE=VITEC + +OUI:70B3D50CB* + ID_OUI_FROM_DATABASE=NIRECO CORPORATION + +OUI:70B3D50CC* + ID_OUI_FROM_DATABASE=ADMiTAS CCTV Taiwan Co. Ltd + +OUI:70B3D50CD* + ID_OUI_FROM_DATABASE=AML Oceanographic + +OUI:70B3D50CE* + ID_OUI_FROM_DATABASE=Innominds Software Inc + +OUI:70B3D50CF* + ID_OUI_FROM_DATABASE=sohonet ltd + +OUI:70B3D50D0* + ID_OUI_FROM_DATABASE=ProHound Controles Eirelli + +OUI:70B3D50D1* + ID_OUI_FROM_DATABASE=Common Sense Monitoring Solutions Ltd. + +OUI:70B3D50D2* + ID_OUI_FROM_DATABASE=UNMANNED SPA + +OUI:70B3D50D3* + ID_OUI_FROM_DATABASE=TSAT AS + +OUI:70B3D50D4* + ID_OUI_FROM_DATABASE=Guangzhou Male Industrial Animation Technology Co.,Ltd. + +OUI:70B3D50D5* + ID_OUI_FROM_DATABASE=Kahler Automation + +OUI:70B3D50D6* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D50D7* + ID_OUI_FROM_DATABASE=Russian Telecom Equipment Company + +OUI:70B3D50D8* + ID_OUI_FROM_DATABASE=Laser Imagineering GmbH + +OUI:70B3D50D9* + ID_OUI_FROM_DATABASE=Brechbuehler AG + +OUI:70B3D50DA* + ID_OUI_FROM_DATABASE=Aquavision Distribution Ltd + +OUI:70B3D50DB* + ID_OUI_FROM_DATABASE=Cryptotronix LLC + +OUI:70B3D50DC* + ID_OUI_FROM_DATABASE=Talleres de Escoriaza + +OUI:70B3D50DD* + ID_OUI_FROM_DATABASE=Shenzhen Virtual Clusters Information Technology Co.,Ltd. + +OUI:70B3D50DE* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D50DF* + ID_OUI_FROM_DATABASE=B.E.A. sa + +OUI:70B3D50E0* + ID_OUI_FROM_DATABASE=PLCiS + +OUI:70B3D50E1* + ID_OUI_FROM_DATABASE=MiWave Consulting, LLC + +OUI:70B3D50E3* + ID_OUI_FROM_DATABASE=SinTau SrL + +OUI:70B3D50E5* + ID_OUI_FROM_DATABASE=Delta Solutions LLC + +OUI:70B3D50E6* + ID_OUI_FROM_DATABASE=Nasdaq + +OUI:70B3D50E7* + ID_OUI_FROM_DATABASE=Pure Air Filtration + +OUI:70B3D50E8* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D50E9* + ID_OUI_FROM_DATABASE=VNT electronics s.r.o. + +OUI:70B3D50EA* + ID_OUI_FROM_DATABASE=AEV Broadcast Srl + +OUI:70B3D50EC* + ID_OUI_FROM_DATABASE=ACS MOTION CONTROL + +OUI:70B3D50ED* + ID_OUI_FROM_DATABASE=Lupa Tecnologia e Sistemas Ltda + +OUI:70B3D50EE* + ID_OUI_FROM_DATABASE=Picture Elements, Inc. + +OUI:70B3D50EF* + ID_OUI_FROM_DATABASE=Dextera Labs + +OUI:70B3D50F0* + ID_OUI_FROM_DATABASE=Avionica + +OUI:70B3D50F1* + ID_OUI_FROM_DATABASE=Beijing One City Science & Technology Co., LTD + +OUI:70B3D50F2* + ID_OUI_FROM_DATABASE=TrexEdge, Inc. + +OUI:70B3D50F3* + ID_OUI_FROM_DATABASE=MonsoonRF, Inc. + +OUI:70B3D50F4* + ID_OUI_FROM_DATABASE=Visual Robotics + +OUI:70B3D50F6* + ID_OUI_FROM_DATABASE=KSE GmbH + +OUI:70B3D50F7* + ID_OUI_FROM_DATABASE=Bespoon + +OUI:70B3D50F8* + ID_OUI_FROM_DATABASE=Special Services Group, LLC + +OUI:70B3D50F9* + ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies + +OUI:70B3D50FA* + ID_OUI_FROM_DATABASE=InsideRF Co., Ltd. + +OUI:70B3D50FB* + ID_OUI_FROM_DATABASE=Cygnus LLC + +OUI:70B3D50FC* + ID_OUI_FROM_DATABASE=vitalcare + +OUI:70B3D50FE* + ID_OUI_FROM_DATABASE=Vocality International Ltd + +OUI:70B3D50FF* + ID_OUI_FROM_DATABASE=INTERNET PROTOCOLO LOGICA SL + +OUI:70B3D5100* + ID_OUI_FROM_DATABASE=Gupsy GmbH + +OUI:70B3D5101* + ID_OUI_FROM_DATABASE=Adolf Nissen Elektrobau GmbH + Co. KG + +OUI:70B3D5102* + ID_OUI_FROM_DATABASE=Oxford Monitoring Solutions Ltd + +OUI:70B3D5103* + ID_OUI_FROM_DATABASE=HANYOUNG NUX CO.,LTD + +OUI:70B3D5104* + ID_OUI_FROM_DATABASE=Plum sp. z o.o + +OUI:70B3D5105* + ID_OUI_FROM_DATABASE=Beijing Nacao Technology Co., Ltd. + +OUI:70B3D5106* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5107* + ID_OUI_FROM_DATABASE=OOO Alyans + +OUI:70B3D5108* + ID_OUI_FROM_DATABASE=TEX COMPUTER SRL + +OUI:70B3D5109* + ID_OUI_FROM_DATABASE=DiTEST Fahrzeugdiagnose GmbH + +OUI:70B3D510A* + ID_OUI_FROM_DATABASE=SEASON DESIGN TECHNOLOGY + +OUI:70B3D510C* + ID_OUI_FROM_DATABASE=Vocality International Ltd + +OUI:70B3D510E* + ID_OUI_FROM_DATABASE=Colorimetry Research, Inc + +OUI:70B3D510F* + ID_OUI_FROM_DATABASE=neQis + +OUI:70B3D5111* + ID_OUI_FROM_DATABASE=Leonardo Sistemi Integrati S.r.l. + +OUI:70B3D5112* + ID_OUI_FROM_DATABASE=DiTEST Fahrzeugdiagnose GmbH + +OUI:70B3D5113* + ID_OUI_FROM_DATABASE=iREA System Industry + +OUI:70B3D5114* + ID_OUI_FROM_DATABASE=Project H Pty Ltd + +OUI:70B3D5115* + ID_OUI_FROM_DATABASE=Welltec Corp. + +OUI:70B3D5117* + ID_OUI_FROM_DATABASE=SysCom Automationstechnik GmbH + +OUI:70B3D5119* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D511A* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D511B* + ID_OUI_FROM_DATABASE=HoseoTelnet Inc... + +OUI:70B3D511C* + ID_OUI_FROM_DATABASE=Samriddi Automations Pvt. Ltd. + +OUI:70B3D511D* + ID_OUI_FROM_DATABASE=Dakton Microlabs LLC + +OUI:70B3D511F* + ID_OUI_FROM_DATABASE=Geppetto Electronics + +OUI:70B3D5120* + ID_OUI_FROM_DATABASE=GSP Sprachtechnologie GmbH + +OUI:70B3D5121* + ID_OUI_FROM_DATABASE=Shenzhen Luxurite Smart Home Ltd + +OUI:70B3D5122* + ID_OUI_FROM_DATABASE=Henri Systems Holland bv + +OUI:70B3D5123* + ID_OUI_FROM_DATABASE=Amfitech ApS + +OUI:70B3D5124* + ID_OUI_FROM_DATABASE=Forschungs- und Transferzentrum Leipzig e.V. + +OUI:70B3D5125* + ID_OUI_FROM_DATABASE=Securolytics, Inc. + +OUI:70B3D5126* + ID_OUI_FROM_DATABASE=AddSecure Smart Grids + +OUI:70B3D5127* + ID_OUI_FROM_DATABASE=VITEC + +OUI:70B3D5129* + ID_OUI_FROM_DATABASE=OOO Microlink-Svyaz + +OUI:70B3D512A* + ID_OUI_FROM_DATABASE=Elvys s.r.o + +OUI:70B3D512B* + ID_OUI_FROM_DATABASE=RIC Electronics + +OUI:70B3D512C* + ID_OUI_FROM_DATABASE=CIELLE S.R.L. + +OUI:70B3D512D* + ID_OUI_FROM_DATABASE=S.E.I. CO.,LTD. + +OUI:70B3D512E* + ID_OUI_FROM_DATABASE=GreenFlux + +OUI:70B3D512F* + ID_OUI_FROM_DATABASE=DSP4YOU LTd + +OUI:70B3D5131* + ID_OUI_FROM_DATABASE=Inova Design Solutions Ltd + +OUI:70B3D5132* + ID_OUI_FROM_DATABASE=Hagenuk KMT Kabelmesstechnik GmbH + +OUI:70B3D5133* + ID_OUI_FROM_DATABASE=Vidisys GmbH + +OUI:70B3D5134* + ID_OUI_FROM_DATABASE=Conjing Networks Inc. + +OUI:70B3D5135* + ID_OUI_FROM_DATABASE=DORLET SAU + +OUI:70B3D5136* + ID_OUI_FROM_DATABASE=Miguel Corporate Services Pte Ltd + +OUI:70B3D5138* + ID_OUI_FROM_DATABASE=SMITEC S.p.A. + +OUI:70B3D5139* + ID_OUI_FROM_DATABASE=Tunstall A/S + +OUI:70B3D513A* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D513B* + ID_OUI_FROM_DATABASE=Sienna Corporation + +OUI:70B3D513C* + ID_OUI_FROM_DATABASE=Detec Systems Ltd + +OUI:70B3D513D* + ID_OUI_FROM_DATABASE=Elsist Srl + +OUI:70B3D513E* + ID_OUI_FROM_DATABASE=Stara S/A Indústria de Implementos Agrícolas + +OUI:70B3D513F* + ID_OUI_FROM_DATABASE=Farmobile + +OUI:70B3D5140* + ID_OUI_FROM_DATABASE=Virta Laboratories, Inc. + +OUI:70B3D5141* + ID_OUI_FROM_DATABASE=M.T. S.R.L. + +OUI:70B3D5142* + ID_OUI_FROM_DATABASE=DAVE SRL + +OUI:70B3D5143* + ID_OUI_FROM_DATABASE=A & T Technologies + +OUI:70B3D5144* + ID_OUI_FROM_DATABASE=GS Elektromedizinsiche Geräte G. Stemple GmbH + +OUI:70B3D5145* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D5146* + ID_OUI_FROM_DATABASE=3City Electronics + +OUI:70B3D5147* + ID_OUI_FROM_DATABASE=ROMO Wind A/S + +OUI:70B3D5148* + ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. + +OUI:70B3D5149* + ID_OUI_FROM_DATABASE=eleven-x + +OUI:70B3D514A* + ID_OUI_FROM_DATABASE=ExSens Technology (Pty) Ltd. + +OUI:70B3D514B* + ID_OUI_FROM_DATABASE=C21 Systems Ltd + +OUI:70B3D514C* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D514D* + ID_OUI_FROM_DATABASE=2-Observe + +OUI:70B3D514E* + ID_OUI_FROM_DATABASE=Innosonix GmbH + +OUI:70B3D514F* + ID_OUI_FROM_DATABASE=Mobile Devices Unlimited + +OUI:70B3D5150* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D5151* + ID_OUI_FROM_DATABASE=Virsae Group Ltd + +OUI:70B3D5152* + ID_OUI_FROM_DATABASE=Xped Corporation Pty Ltd + +OUI:70B3D5153* + ID_OUI_FROM_DATABASE=Schneider Electric Motion USA + +OUI:70B3D5154* + ID_OUI_FROM_DATABASE=Walk Horizon Technology (Beijing) Co., Ltd. + +OUI:70B3D5155* + ID_OUI_FROM_DATABASE=Sanwa New Tec Co.,Ltd + +OUI:70B3D5158* + ID_OUI_FROM_DATABASE=EAX Labs s.r.o. + +OUI:70B3D5159* + ID_OUI_FROM_DATABASE=RCH Vietnam Limited Liability Company + +OUI:70B3D515B* + ID_OUI_FROM_DATABASE=Armstrong International, Inc. + +OUI:70B3D515C* + ID_OUI_FROM_DATABASE=Woods Hole Oceanographic Institution + +OUI:70B3D515D* + ID_OUI_FROM_DATABASE=Vtron Pty Ltd + +OUI:70B3D515E* + ID_OUI_FROM_DATABASE=Season Electronics Ltd + +OUI:70B3D515F* + ID_OUI_FROM_DATABASE=SAVRONİK ELEKTRONİK + +OUI:70B3D5161* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5162* + ID_OUI_FROM_DATABASE=ESPAI DE PRODUCCIÓ I ELECTRÓNI + +OUI:70B3D5163* + ID_OUI_FROM_DATABASE=BHARAT HEAVY ELECTRICALS LIMITED + +OUI:70B3D5164* + ID_OUI_FROM_DATABASE=Tokyo Drawing Ltd. + +OUI:70B3D5166* + ID_OUI_FROM_DATABASE=SERIAL IMAGE INC. + +OUI:70B3D5167* + ID_OUI_FROM_DATABASE=Eiden Co.,Ltd. + +OUI:70B3D5168* + ID_OUI_FROM_DATABASE=Biwave Technologies, Inc. + +OUI:70B3D5169* + ID_OUI_FROM_DATABASE=Service Plus LLC + +OUI:70B3D516A* + ID_OUI_FROM_DATABASE=4Jtech s.r.o. + +OUI:70B3D516B* + ID_OUI_FROM_DATABASE=IOT Engineering + +OUI:70B3D516C* + ID_OUI_FROM_DATABASE=OCEAN + +OUI:70B3D516E* + ID_OUI_FROM_DATABASE=Jemac Sweden AB + +OUI:70B3D516F* + ID_OUI_FROM_DATABASE=NimbeLink Corp + +OUI:70B3D5170* + ID_OUI_FROM_DATABASE=Mutelcor GmbH + +OUI:70B3D5171* + ID_OUI_FROM_DATABASE=Aetina Corporation + +OUI:70B3D5172* + ID_OUI_FROM_DATABASE=LumiGrow, Inc + +OUI:70B3D5173* + ID_OUI_FROM_DATABASE=National TeleConsultants LLC + +OUI:70B3D5174* + ID_OUI_FROM_DATABASE=Carlson Wireless Technologies Inc. + +OUI:70B3D5175* + ID_OUI_FROM_DATABASE=Akribis Systems + +OUI:70B3D5178* + ID_OUI_FROM_DATABASE=Gamber Johnson-LLC + +OUI:70B3D5179* + ID_OUI_FROM_DATABASE=ALTRAN UK + +OUI:70B3D517A* + ID_OUI_FROM_DATABASE=Gencoa Ltd + +OUI:70B3D517B* + ID_OUI_FROM_DATABASE=Vistec Electron Beam GmbH + +OUI:70B3D517D* + ID_OUI_FROM_DATABASE=Entech Electronics + +OUI:70B3D517E* + ID_OUI_FROM_DATABASE=OCULI VISION + +OUI:70B3D517F* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5180* + ID_OUI_FROM_DATABASE=LHA Systems (Pty) Ltd + +OUI:70B3D5181* + ID_OUI_FROM_DATABASE=Task Sistemas + +OUI:70B3D5182* + ID_OUI_FROM_DATABASE=Kitron UAB + +OUI:70B3D5183* + ID_OUI_FROM_DATABASE=Evco S.p.a. + +OUI:70B3D5184* + ID_OUI_FROM_DATABASE=XV360 Optical Information Systems Ltd. + +OUI:70B3D5185* + ID_OUI_FROM_DATABASE=R&D Gran-System-S LLC + +OUI:70B3D5186* + ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA + +OUI:70B3D5187* + ID_OUI_FROM_DATABASE=Elektronik & Präzisionsbau Saalfeld GmbH + +OUI:70B3D5188* + ID_OUI_FROM_DATABASE=Birket Engineering + +OUI:70B3D5189* + ID_OUI_FROM_DATABASE=DAVE SRL + +OUI:70B3D518A* + ID_OUI_FROM_DATABASE=NSP Europe Ltd + +OUI:70B3D518B* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D518C* + ID_OUI_FROM_DATABASE=CMC Industrial Electronics Ltd + +OUI:70B3D518D* + ID_OUI_FROM_DATABASE=Foro Tel + +OUI:70B3D518E* + ID_OUI_FROM_DATABASE=NIPPON SEIKI CO., LTD. + +OUI:70B3D518F* + ID_OUI_FROM_DATABASE=Newtec A/S + +OUI:70B3D5190* + ID_OUI_FROM_DATABASE=Fantom Wireless, Inc. + +OUI:70B3D5192* + ID_OUI_FROM_DATABASE=ASPT, INC. + +OUI:70B3D5193* + ID_OUI_FROM_DATABASE=ERA TOYS LIMITED + +OUI:70B3D5194* + ID_OUI_FROM_DATABASE=Husty M.Styczen J.Hupert Sp.J. + +OUI:70B3D5197* + ID_OUI_FROM_DATABASE=Lattech Systems Pty Ltd + +OUI:70B3D5199* + ID_OUI_FROM_DATABASE=Smart Controls LLC + +OUI:70B3D519A* + ID_OUI_FROM_DATABASE=WiSuite USA + +OUI:70B3D519B* + ID_OUI_FROM_DATABASE=Global Technical Systems + +OUI:70B3D519C* + ID_OUI_FROM_DATABASE=Kubu, Inc. + +OUI:70B3D519E* + ID_OUI_FROM_DATABASE=J-Factor Embedded Technologies + +OUI:70B3D519F* + ID_OUI_FROM_DATABASE=Koizumi Lighting Technology Corp. + +OUI:70B3D51A0* + ID_OUI_FROM_DATABASE=UFATECH LTD + +OUI:70B3D51A1* + ID_OUI_FROM_DATABASE=HMicro Inc + +OUI:70B3D51A3* + ID_OUI_FROM_DATABASE=Telairity Semiconductor + +OUI:70B3D51A4* + ID_OUI_FROM_DATABASE=DAVEY BICKFORD + +OUI:70B3D51A5* + ID_OUI_FROM_DATABASE=METRONIC APARATURA KONTROLNO - POMIAROWA + +OUI:70B3D51A6* + ID_OUI_FROM_DATABASE=Robotelf Technologies (Chengdu) Co., Ltd. + +OUI:70B3D51A8* + ID_OUI_FROM_DATABASE=STC Rainbow Ltd. + +OUI:70B3D51A9* + ID_OUI_FROM_DATABASE=OCEANIX INC. + +OUI:70B3D51AA* + ID_OUI_FROM_DATABASE=Echo Ridge, LLC + +OUI:70B3D51AB* + ID_OUI_FROM_DATABASE=Access Control Systems JSC + +OUI:70B3D51AC* + ID_OUI_FROM_DATABASE=SVP Broadcast Microwave S.L. + +OUI:70B3D51AD* + ID_OUI_FROM_DATABASE=Techworld Industries Ltd + +OUI:70B3D51AF* + ID_OUI_FROM_DATABASE=Teenage Engineering AB + +OUI:70B3D51B1* + ID_OUI_FROM_DATABASE=Shanghai Danyan Information Technology Co., Ltd. + +OUI:70B3D51B3* + ID_OUI_FROM_DATABASE=Graphcore Ltd + +OUI:70B3D51B4* + ID_OUI_FROM_DATABASE=5nines + +OUI:70B3D51B5* + ID_OUI_FROM_DATABASE=StarBridge, Inc. + +OUI:70B3D51B6* + ID_OUI_FROM_DATABASE=DACOM West GmbH + +OUI:70B3D51B8* + ID_OUI_FROM_DATABASE=OES Inc. + +OUI:70B3D51B9* + ID_OUI_FROM_DATABASE=RELISTE Ges.m.b.H. + +OUI:70B3D51BB* + ID_OUI_FROM_DATABASE=EFENTO T P SZYDŁOWSKI K ZARĘBA SPÓŁKA JAWNA + +OUI:70B3D51BD* + ID_OUI_FROM_DATABASE=Shenzhen Siera Technology Ltd + +OUI:70B3D51BE* + ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC + +OUI:70B3D51BF* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D51C0* + ID_OUI_FROM_DATABASE=W. H. Leary Co., Inc. + +OUI:70B3D51C2* + ID_OUI_FROM_DATABASE=CENSIS, Uiversity of Glasgow + +OUI:70B3D51C3* + ID_OUI_FROM_DATABASE=Shanghai Tiancheng Communication Technology Corporation + +OUI:70B3D51C4* + ID_OUI_FROM_DATABASE=Smeg S.p.A. + +OUI:70B3D51C5* + ID_OUI_FROM_DATABASE=ELSAG + +OUI:70B3D51C7* + ID_OUI_FROM_DATABASE=Hoshin Electronics Co., Ltd. + +OUI:70B3D51C8* + ID_OUI_FROM_DATABASE=LDA audio video profesional S.L. + +OUI:70B3D51C9* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D51CB* + ID_OUI_FROM_DATABASE=MatchX GmbH + +OUI:70B3D51CC* + ID_OUI_FROM_DATABASE=AooGee Controls Co., LTD. + +OUI:70B3D51CD* + ID_OUI_FROM_DATABASE=ELEUSI GmbH + +OUI:70B3D51CE* + ID_OUI_FROM_DATABASE=Clear Flow by Antiference + +OUI:70B3D51CF* + ID_OUI_FROM_DATABASE=Dalcnet srl + +OUI:70B3D51D0* + ID_OUI_FROM_DATABASE=Shenzhen INVT Electric Co.,Ltd + +OUI:70B3D51D1* + ID_OUI_FROM_DATABASE=Eurotek Srl + +OUI:70B3D51D2* + ID_OUI_FROM_DATABASE=Xacti Corporation + +OUI:70B3D51D3* + ID_OUI_FROM_DATABASE=AIROBOT OÜ + +OUI:70B3D51D4* + ID_OUI_FROM_DATABASE=Brinkmann Audio GmbH + +OUI:70B3D51D5* + ID_OUI_FROM_DATABASE=MIVO Technology AB + +OUI:70B3D51D6* + ID_OUI_FROM_DATABASE=MacGray Services + +OUI:70B3D51D7* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D51D8* + ID_OUI_FROM_DATABASE=Blue Skies Global LLC + +OUI:70B3D51D9* + ID_OUI_FROM_DATABASE=MondeF + +OUI:70B3D51DA* + ID_OUI_FROM_DATABASE=Promess Inc. + +OUI:70B3D51DB* + ID_OUI_FROM_DATABASE=Hudson Robotics + +OUI:70B3D51DC* + ID_OUI_FROM_DATABASE=TEKVEL Ltd. + +OUI:70B3D51DD* + ID_OUI_FROM_DATABASE=RF CREATIONS LTD + +OUI:70B3D51DE* + ID_OUI_FROM_DATABASE=DYCEC, S.A. + +OUI:70B3D51DF* + ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD. + +OUI:70B3D51E0* + ID_OUI_FROM_DATABASE=TOPROOTTechnology Corp. Ltd. + +OUI:70B3D51E1* + ID_OUI_FROM_DATABASE=TEX COMPUTER SRL + +OUI:70B3D51E2* + ID_OUI_FROM_DATABASE=Shenzhen CAMERAY ELECTRONIC CO., LTD + +OUI:70B3D51E3* + ID_OUI_FROM_DATABASE=Hatel Elektronik LTD. STI. + +OUI:70B3D51E4* + ID_OUI_FROM_DATABASE=Tecnologix s.r.l. + +OUI:70B3D51E5* + ID_OUI_FROM_DATABASE=VendNovation LLC + +OUI:70B3D51E6* + ID_OUI_FROM_DATABASE=Sanmina Israel + +OUI:70B3D51E7* + ID_OUI_FROM_DATABASE=DogWatch Inc + +OUI:70B3D51E8* + ID_OUI_FROM_DATABASE=Gogo BA + +OUI:70B3D51E9* + ID_OUI_FROM_DATABASE=comtime GmbH + +OUI:70B3D51EA* + ID_OUI_FROM_DATABASE=Sense For Innovation + +OUI:70B3D51EB* + ID_OUI_FROM_DATABASE=Xavant + +OUI:70B3D51EE* + ID_OUI_FROM_DATABASE=MEGGITT + +OUI:70B3D51EF* + ID_OUI_FROM_DATABASE=ADTEK + +OUI:70B3D51F0* + ID_OUI_FROM_DATABASE=Harmonic Design GmbH + +OUI:70B3D51F1* + ID_OUI_FROM_DATABASE=DIEHL Connectivity Solutions + +OUI:70B3D51F2* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D51F3* + ID_OUI_FROM_DATABASE=Smart Energy Code Company Limited + +OUI:70B3D51F4* + ID_OUI_FROM_DATABASE=Hangzhou Woosiyuan Communication Co.,Ltd. + +OUI:70B3D51F5* + ID_OUI_FROM_DATABASE=Martec S.p.A. + +OUI:70B3D51F7* + ID_OUI_FROM_DATABASE=Morgan Schaffer Inc. + +OUI:70B3D51F8* + ID_OUI_FROM_DATABASE=Convergent Design + +OUI:70B3D51F9* + ID_OUI_FROM_DATABASE=Automata GmbH & Co. KG + +OUI:70B3D51FC* + ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd. + +OUI:70B3D51FD* + ID_OUI_FROM_DATABASE=BRS Sistemas Eletrônicos + +OUI:70B3D51FE* + ID_OUI_FROM_DATABASE=MobiPromo + +OUI:70B3D51FF* + ID_OUI_FROM_DATABASE=Audiodo AB + +OUI:70B3D5200* + ID_OUI_FROM_DATABASE=NextEV Co., Ltd. + +OUI:70B3D5201* + ID_OUI_FROM_DATABASE=Leontech Limited + +OUI:70B3D5202* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D5203* + ID_OUI_FROM_DATABASE=WOOJIN Inc + +OUI:70B3D5204* + ID_OUI_FROM_DATABASE=TWC + +OUI:70B3D5205* + ID_OUI_FROM_DATABASE=Esource Srl + +OUI:70B3D5206* + ID_OUI_FROM_DATABASE=ard sa + +OUI:70B3D5207* + ID_OUI_FROM_DATABASE=Savari Inc + +OUI:70B3D5208* + ID_OUI_FROM_DATABASE=DSP DESIGN LTD + +OUI:70B3D5209* + ID_OUI_FROM_DATABASE=SmartNodes + +OUI:70B3D520A* + ID_OUI_FROM_DATABASE=Golden Grid Systems + +OUI:70B3D520C* + ID_OUI_FROM_DATABASE=Siemens Healthcare Diagnostics + +OUI:70B3D520D* + ID_OUI_FROM_DATABASE=Engage Technologies + +OUI:70B3D520E* + ID_OUI_FROM_DATABASE=Amrehn & Partner EDV-Service GmbH + +OUI:70B3D520F* + ID_OUI_FROM_DATABASE=Tieline Research Pty Ltd + +OUI:70B3D5210* + ID_OUI_FROM_DATABASE=Eastone Century Technology Co.,Ltd. + +OUI:70B3D5211* + ID_OUI_FROM_DATABASE=Fracarro srl + +OUI:70B3D5213* + ID_OUI_FROM_DATABASE=ETON Deutschland Electro Acoustic GmbH + +OUI:70B3D5214* + ID_OUI_FROM_DATABASE=signalparser + +OUI:70B3D5215* + ID_OUI_FROM_DATABASE=Dataspeed Inc + +OUI:70B3D5216* + ID_OUI_FROM_DATABASE=FLEXTRONICS + +OUI:70B3D5217* + ID_OUI_FROM_DATABASE=Tecnint HTE SRL + +OUI:70B3D5218* + ID_OUI_FROM_DATABASE=Gremesh.com + +OUI:70B3D5219* + ID_OUI_FROM_DATABASE=D-E-K GmbH & Co.KG + +OUI:70B3D521A* + ID_OUI_FROM_DATABASE=Acutronic Link Robotics AG + +OUI:70B3D521B* + ID_OUI_FROM_DATABASE=Lab241 Co.,Ltd. + +OUI:70B3D521C* + ID_OUI_FROM_DATABASE=Enyx SA + +OUI:70B3D521D* + ID_OUI_FROM_DATABASE=iRF - Intelligent RF Solutions, LLC + +OUI:70B3D521E* + ID_OUI_FROM_DATABASE=Hildebrand Technology Limited + +OUI:70B3D521F* + ID_OUI_FROM_DATABASE=CHRONOMEDIA + +OUI:70B3D5220* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5221* + ID_OUI_FROM_DATABASE=LX Design House + +OUI:70B3D5222* + ID_OUI_FROM_DATABASE=Marioff Corporation Oy + +OUI:70B3D5224* + ID_OUI_FROM_DATABASE=Urbana Smart Solutions Pte Ltd + +OUI:70B3D5225* + ID_OUI_FROM_DATABASE=RCD Radiokomunikace + +OUI:70B3D5226* + ID_OUI_FROM_DATABASE=Yaviar + +OUI:70B3D5227* + ID_OUI_FROM_DATABASE=Montalvo + +OUI:70B3D5228* + ID_OUI_FROM_DATABASE=HEITEC AG + +OUI:70B3D5229* + ID_OUI_FROM_DATABASE=CONTROL SYSTEMS Srl + +OUI:70B3D522A* + ID_OUI_FROM_DATABASE=Shishido Electrostatic, Ltd. + +OUI:70B3D522B* + ID_OUI_FROM_DATABASE=VITEC + +OUI:70B3D522C* + ID_OUI_FROM_DATABASE=Hiquel Elektronik- und Anlagenbau GmbH + +OUI:70B3D522D* + ID_OUI_FROM_DATABASE=Leder Elektronik Design + +OUI:70B3D522E* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D522F* + ID_OUI_FROM_DATABASE=Instec, Inc. + +OUI:70B3D5230* + ID_OUI_FROM_DATABASE=CT Company + +OUI:70B3D5231* + ID_OUI_FROM_DATABASE=DELTA TAU DATA SYSTEMS, INC. + +OUI:70B3D5232* + ID_OUI_FROM_DATABASE=UCONSYS + +OUI:70B3D5234* + ID_OUI_FROM_DATABASE=EDFelectronics JRMM Sp z o.o. sp.k. + +OUI:70B3D5235* + ID_OUI_FROM_DATABASE=CAMEON S.A. + +OUI:70B3D5236* + ID_OUI_FROM_DATABASE=Monnit Corporation + +OUI:70B3D5237* + ID_OUI_FROM_DATABASE=Sikom AS + +OUI:70B3D5238* + ID_OUI_FROM_DATABASE=Arete Associates + +OUI:70B3D5239* + ID_OUI_FROM_DATABASE=Applied Silver + +OUI:70B3D523A* + ID_OUI_FROM_DATABASE=Mesa Labs, Inc. + +OUI:70B3D523B* + ID_OUI_FROM_DATABASE=Fink Telecom Services + +OUI:70B3D523C* + ID_OUI_FROM_DATABASE=Quasonix, LLC + +OUI:70B3D523E* + ID_OUI_FROM_DATABASE=Tornado Modular Systems + +OUI:70B3D523F* + ID_OUI_FROM_DATABASE=ETA-USA + +OUI:70B3D5240* + ID_OUI_FROM_DATABASE=Orlaco Products B.V. + +OUI:70B3D5241* + ID_OUI_FROM_DATABASE=Bolide Technology Group, Inc. + +OUI:70B3D5243* + ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA + +OUI:70B3D5244* + ID_OUI_FROM_DATABASE=DAT Informatics Pvt Ltd + +OUI:70B3D5245* + ID_OUI_FROM_DATABASE=Newtec A/S + +OUI:70B3D5246* + ID_OUI_FROM_DATABASE=Saline Lectronics, Inc. + +OUI:70B3D5248* + ID_OUI_FROM_DATABASE=GL TECH CO.,LTD + +OUI:70B3D5249* + ID_OUI_FROM_DATABASE=Kospel S.A. + +OUI:70B3D524A* + ID_OUI_FROM_DATABASE=Unmukti Technology Pvt Ltd + +OUI:70B3D524B* + ID_OUI_FROM_DATABASE=TOSEI ENGINEERING CORP. + +OUI:70B3D524C* + ID_OUI_FROM_DATABASE=Astronomical Research Cameras, Inc. + +OUI:70B3D524D* + ID_OUI_FROM_DATABASE=INFO CREATIVE (HK) LTD + +OUI:70B3D524E* + ID_OUI_FROM_DATABASE=Chengdu Cove Technology CO.,LTD + +OUI:70B3D524F* + ID_OUI_FROM_DATABASE=ELBIT SYSTEMS BMD AND LAND EW - ELISRA LTD + +OUI:70B3D5250* + ID_OUI_FROM_DATABASE=Datum Electronics Limited + +OUI:70B3D5251* + ID_OUI_FROM_DATABASE=PixelApps s.r.o. + +OUI:70B3D5252* + ID_OUI_FROM_DATABASE=Sierra Nevada Corporation + +OUI:70B3D5253* + ID_OUI_FROM_DATABASE=Wimate Technology Solutions Private Limited + +OUI:70B3D5254* + ID_OUI_FROM_DATABASE=Spectrum Brands + +OUI:70B3D5255* + ID_OUI_FROM_DATABASE=Asystems Corporation + +OUI:70B3D5257* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:70B3D5258* + ID_OUI_FROM_DATABASE=BAYKON Endüstriyel Kontrol Sistemleri San. ve Tic. A.Ş. + +OUI:70B3D5259* + ID_OUI_FROM_DATABASE=Zebra Elektronik A.S. + +OUI:70B3D525A* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D525B* + ID_OUI_FROM_DATABASE=GID Industrial + +OUI:70B3D525C* + ID_OUI_FROM_DATABASE=ARCLAN'SYSTEM + +OUI:70B3D525D* + ID_OUI_FROM_DATABASE=Mimo Networks + +OUI:70B3D525F* + ID_OUI_FROM_DATABASE=COPPERNIC SAS + +OUI:70B3D5260* + ID_OUI_FROM_DATABASE=ModuSystems, Inc + +OUI:70B3D5261* + ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC + +OUI:70B3D5262* + ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies + +OUI:70B3D5264* + ID_OUI_FROM_DATABASE=ifak technology + service GmbH + +OUI:70B3D5266* + ID_OUI_FROM_DATABASE=Spectra Displays Ltd + +OUI:70B3D5267* + ID_OUI_FROM_DATABASE=Zehntner Testing Instruments + +OUI:70B3D5268* + ID_OUI_FROM_DATABASE=Cardinal Scale Mfg Co + +OUI:70B3D5269* + ID_OUI_FROM_DATABASE=Gilbarco Veeder-Root ‎ + +OUI:70B3D526A* + ID_OUI_FROM_DATABASE=Talleres de Escoriaza SA + +OUI:70B3D526B* + ID_OUI_FROM_DATABASE=Sorama BV + +OUI:70B3D526C* + ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG + +OUI:70B3D526D* + ID_OUI_FROM_DATABASE=Sorion Electronics ltd + +OUI:70B3D526E* + ID_OUI_FROM_DATABASE=HI-TECH SYSTEM Co. Ltd. + +OUI:70B3D526F* + ID_OUI_FROM_DATABASE=COMPAL ELECTRONICS, INC. + +OUI:70B3D5270* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:70B3D5272* + ID_OUI_FROM_DATABASE=TELECOM SANTE + +OUI:70B3D5273* + ID_OUI_FROM_DATABASE=WeVo Tech + +OUI:70B3D5274* + ID_OUI_FROM_DATABASE=Stercom Power Solutions GmbH + +OUI:70B3D5275* + ID_OUI_FROM_DATABASE=INTERNET PROTOCOLO LOGICA SL + +OUI:70B3D5276* + ID_OUI_FROM_DATABASE=TELL Software Hungaria Kft. + +OUI:70B3D5277* + ID_OUI_FROM_DATABASE=Voltaware Limited + +OUI:70B3D5278* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5279* + ID_OUI_FROM_DATABASE=Medicomp, Inc + +OUI:70B3D527A* + ID_OUI_FROM_DATABASE=TD ECOPHISIKA + +OUI:70B3D527C* + ID_OUI_FROM_DATABASE=MOTION LIB,Inc. + +OUI:70B3D527D* + ID_OUI_FROM_DATABASE=Telenor Connexion AB + +OUI:70B3D527E* + ID_OUI_FROM_DATABASE=Mettler Toledo + +OUI:70B3D527F* + ID_OUI_FROM_DATABASE=ST Aerospace Systems + +OUI:70B3D5280* + ID_OUI_FROM_DATABASE=Computech International + +OUI:70B3D5281* + ID_OUI_FROM_DATABASE=ITG.CO.LTD + +OUI:70B3D5282* + ID_OUI_FROM_DATABASE=SAMBO HITECH + +OUI:70B3D5283* + ID_OUI_FROM_DATABASE=TextNinja Co. + +OUI:70B3D5284* + ID_OUI_FROM_DATABASE=Globalcom Engineering SPA + +OUI:70B3D5285* + ID_OUI_FROM_DATABASE=Bentec GmbH Drilling & Oilfield Systems + +OUI:70B3D5286* + ID_OUI_FROM_DATABASE=Pedax Danmark + +OUI:70B3D5287* + ID_OUI_FROM_DATABASE=Hypex Electronics BV + +OUI:70B3D5288* + ID_OUI_FROM_DATABASE=Bresslergroup + +OUI:70B3D5289* + ID_OUI_FROM_DATABASE=Shenzhen Rongda Computer Co.,Ltd + +OUI:70B3D528A* + ID_OUI_FROM_DATABASE=Transit Solutions, LLC. + +OUI:70B3D528B* + ID_OUI_FROM_DATABASE=Arnouse Digital Devices, Corp. + +OUI:70B3D528C* + ID_OUI_FROM_DATABASE=Step Technica Co., Ltd. + +OUI:70B3D528D* + ID_OUI_FROM_DATABASE=Technica Engineering GmbH + +OUI:70B3D528E* + ID_OUI_FROM_DATABASE=TEX COMPUTER SRL + +OUI:70B3D528F* + ID_OUI_FROM_DATABASE=Overline Systems + +OUI:70B3D5292* + ID_OUI_FROM_DATABASE=Boston Dynamics + +OUI:70B3D5293* + ID_OUI_FROM_DATABASE=Solar RIg Technologies + +OUI:70B3D5295* + ID_OUI_FROM_DATABASE=Cello Electronics (UK) Ltd + +OUI:70B3D5296* + ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA + +OUI:70B3D5297* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D5299* + ID_OUI_FROM_DATABASE=KMtronic ltd + +OUI:70B3D529B* + ID_OUI_FROM_DATABASE=DermaLumics S.L. + +OUI:70B3D529C* + ID_OUI_FROM_DATABASE=Teko Telecom Srl + +OUI:70B3D529D* + ID_OUI_FROM_DATABASE=XTech2 SIA + +OUI:70B3D529F* + ID_OUI_FROM_DATABASE=Code Hardware SA + +OUI:70B3D52A0* + ID_OUI_FROM_DATABASE=Airthings + +OUI:70B3D52A1* + ID_OUI_FROM_DATABASE=Blink Services AB + +OUI:70B3D52A2* + ID_OUI_FROM_DATABASE=Visualware, Inc. + +OUI:70B3D52A3* + ID_OUI_FROM_DATABASE=ATT Nussbaum Prüftechnik GmbH + +OUI:70B3D52A4* + ID_OUI_FROM_DATABASE=GSP Sprachtechnologie GmbH + +OUI:70B3D52A5* + ID_OUI_FROM_DATABASE=Taitotekniikka + +OUI:70B3D52A6* + ID_OUI_FROM_DATABASE=GSI Technology + +OUI:70B3D52A7* + ID_OUI_FROM_DATABASE=Plasmability, LLC + +OUI:70B3D52A8* + ID_OUI_FROM_DATABASE=Dynamic Perspective GmbH + +OUI:70B3D52A9* + ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. + +OUI:70B3D52AA* + ID_OUI_FROM_DATABASE=Flirtey Inc + +OUI:70B3D52AB* + ID_OUI_FROM_DATABASE=NASA Johnson Space Center + +OUI:70B3D52AC* + ID_OUI_FROM_DATABASE=New Imaging Technologies + +OUI:70B3D52AD* + ID_OUI_FROM_DATABASE=Opgal Optronic Industries + +OUI:70B3D52AE* + ID_OUI_FROM_DATABASE=Alere Technologies AS + +OUI:70B3D52B0* + ID_OUI_FROM_DATABASE=Beijing Zhongyi Yue Tai Technology Co., Ltd + +OUI:70B3D52B1* + ID_OUI_FROM_DATABASE=WIXCON Co., Ltd + +OUI:70B3D52B2* + ID_OUI_FROM_DATABASE=Sun Creative (ZheJiang) Technology INC. + +OUI:70B3D52B3* + ID_OUI_FROM_DATABASE=HAS co.,ltd. + +OUI:70B3D52B4* + ID_OUI_FROM_DATABASE=Foerster-Technik GmbH + +OUI:70B3D52B5* + ID_OUI_FROM_DATABASE=Dosepack India LLP + +OUI:70B3D52B7* + ID_OUI_FROM_DATABASE=Matrix Orbital Corporation + +OUI:70B3D52B8* + ID_OUI_FROM_DATABASE=WideNorth AS + +OUI:70B3D52B9* + ID_OUI_FROM_DATABASE=BELECTRIC GmbH + +OUI:70B3D52BA* + ID_OUI_FROM_DATABASE=Active Brains + +OUI:70B3D52BB* + ID_OUI_FROM_DATABASE=Automation Networks & Solutions LLC + +OUI:70B3D52BC* + ID_OUI_FROM_DATABASE=EQUIPOS DE TELECOMUNICACIÓN OPTOELECTRÓNICOS, S.A. + +OUI:70B3D52BD* + ID_OUI_FROM_DATABASE=mg-sensor GmbH + +OUI:70B3D52BE* + ID_OUI_FROM_DATABASE=Coherent Logix, Inc. + +OUI:70B3D52BF* + ID_OUI_FROM_DATABASE=FOSHAN VOHOM + +OUI:70B3D52C0* + ID_OUI_FROM_DATABASE=Sensative AB + +OUI:70B3D52C2* + ID_OUI_FROM_DATABASE=Quantum Detectors + +OUI:70B3D52C3* + ID_OUI_FROM_DATABASE=Proterra + +OUI:70B3D52C4* + ID_OUI_FROM_DATABASE=Hodwa Co., Ltd + +OUI:70B3D52C7* + ID_OUI_FROM_DATABASE=Worldsensing + +OUI:70B3D52C9* + ID_OUI_FROM_DATABASE=SEASON DESIGN TECHNOLOGY + +OUI:70B3D52CA* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D52CC* + ID_OUI_FROM_DATABASE=WeWork Companies, Inc. + +OUI:70B3D52CD* + ID_OUI_FROM_DATABASE=Korea Airports Corporation + +OUI:70B3D52CE* + ID_OUI_FROM_DATABASE=KDT + +OUI:70B3D52CF* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D52D0* + ID_OUI_FROM_DATABASE=ijin co.,ltd. + +OUI:70B3D52D2* + ID_OUI_FROM_DATABASE=SHANGHAI IRISIAN OPTRONICS TECHNOLOGY CO.,LTD. + +OUI:70B3D52D4* + ID_OUI_FROM_DATABASE=CT Company + +OUI:70B3D52D5* + ID_OUI_FROM_DATABASE=Teuco Guzzini + +OUI:70B3D52D6* + ID_OUI_FROM_DATABASE=Kvazar LLC + +OUI:70B3D52D7* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D52D8* + ID_OUI_FROM_DATABASE=Unisight Digital Products + +OUI:70B3D52DA* + ID_OUI_FROM_DATABASE=Skywave Networks Private Limited + +OUI:70B3D52DB* + ID_OUI_FROM_DATABASE=ProtoPixel SL + +OUI:70B3D52DC* + ID_OUI_FROM_DATABASE=Bolide Technology Group, Inc. + +OUI:70B3D52DE* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D52E0* + ID_OUI_FROM_DATABASE=Peter Huber + +OUI:70B3D52E1* + ID_OUI_FROM_DATABASE=hiSky S.C.S LTD + +OUI:70B3D52E2* + ID_OUI_FROM_DATABASE=Spark Lasers + +OUI:70B3D52E3* + ID_OUI_FROM_DATABASE=Meiknologic GmbH + +OUI:70B3D52E5* + ID_OUI_FROM_DATABASE=Fläkt Woods AB + +OUI:70B3D52E6* + ID_OUI_FROM_DATABASE=IPG Photonics Corporation + +OUI:70B3D52E7* + ID_OUI_FROM_DATABASE=Atos spa + +OUI:70B3D52E8* + ID_OUI_FROM_DATABASE=Telefire + +OUI:70B3D52E9* + ID_OUI_FROM_DATABASE=NeurIT s.r.o. + +OUI:70B3D52EA* + ID_OUI_FROM_DATABASE=Schneider Electric Motion + +OUI:70B3D52EB* + ID_OUI_FROM_DATABASE=BRNET CO.,LTD. + +OUI:70B3D52EC* + ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. + +OUI:70B3D52ED* + ID_OUI_FROM_DATABASE=Signals and systems india pvt ltd + +OUI:70B3D52EE* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D52EF* + ID_OUI_FROM_DATABASE=IEM SA + +OUI:70B3D52F0* + ID_OUI_FROM_DATABASE=Clock-O-Matic + +OUI:70B3D52F1* + ID_OUI_FROM_DATABASE=Inspike S.R.L. + +OUI:70B3D52F2* + ID_OUI_FROM_DATABASE=Health Care Originals, Inc. + +OUI:70B3D52F3* + ID_OUI_FROM_DATABASE=Scame Sistemi srl + +OUI:70B3D52F4* + ID_OUI_FROM_DATABASE=Radixon s.r.o. + +OUI:70B3D52F5* + ID_OUI_FROM_DATABASE=eze System, Inc. + +OUI:70B3D52F6* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D52F8* + ID_OUI_FROM_DATABASE=Tunstall A/S + +OUI:70B3D52F9* + ID_OUI_FROM_DATABASE=CONSOSPY + +OUI:70B3D52FA* + ID_OUI_FROM_DATABASE=Toray Medical Co.,Ltd + +OUI:70B3D52FC* + ID_OUI_FROM_DATABASE=Loanguard T/A SE Controls + +OUI:70B3D52FD* + ID_OUI_FROM_DATABASE=Special Projects Group, Inc + +OUI:70B3D52FE* + ID_OUI_FROM_DATABASE=Yaham Optoelectronics Co., Ltd + +OUI:70B3D52FF* + ID_OUI_FROM_DATABASE=Sunstone Engineering + +OUI:70B3D5300* + ID_OUI_FROM_DATABASE=Novo DR Ltd. + +OUI:70B3D5302* + ID_OUI_FROM_DATABASE=DogWatch Inc + +OUI:70B3D5303* + ID_OUI_FROM_DATABASE=Fuchu Giken, Inc. + +OUI:70B3D5304* + ID_OUI_FROM_DATABASE=Wartsila Voyage Limited + +OUI:70B3D5305* + ID_OUI_FROM_DATABASE=CAITRON Industrial Solutions GmbH + +OUI:70B3D5306* + ID_OUI_FROM_DATABASE=LEMZ-T, LLC + +OUI:70B3D5307* + ID_OUI_FROM_DATABASE=Energi innovation Aps + +OUI:70B3D5308* + ID_OUI_FROM_DATABASE=DSD MICROTECHNOLOGY,INC. + +OUI:70B3D530B* + ID_OUI_FROM_DATABASE=Ash Technologies + +OUI:70B3D530C* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D530D* + ID_OUI_FROM_DATABASE=Fiberbase + +OUI:70B3D530E* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D530F* + ID_OUI_FROM_DATABASE=Cardinal Scales Manufacturing Co + +OUI:70B3D5310* + ID_OUI_FROM_DATABASE=Conserv Solutions + +OUI:70B3D5313* + ID_OUI_FROM_DATABASE=DIEHL Controls + +OUI:70B3D5317* + ID_OUI_FROM_DATABASE=Iotopia Solutions + +OUI:70B3D5319* + ID_OUI_FROM_DATABASE=ISO/TC 22/SC 31 + +OUI:70B3D531B* + ID_OUI_FROM_DATABASE=SilTerra Malaysia Sdn. Bhd. + +OUI:70B3D531C* + ID_OUI_FROM_DATABASE=FINANCIERE DE L'OMBREE (eolane) + +OUI:70B3D531D* + ID_OUI_FROM_DATABASE=AVA Monitoring AB + +OUI:70B3D531E* + ID_OUI_FROM_DATABASE=GILLAM-FEI S.A. + +OUI:70B3D531F* + ID_OUI_FROM_DATABASE=Elcoma + +OUI:70B3D5320* + ID_OUI_FROM_DATABASE=CYNIX Systems Inc + +OUI:70B3D5321* + ID_OUI_FROM_DATABASE=Yite technology + +OUI:70B3D5323* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5324* + ID_OUI_FROM_DATABASE=Thales Nederland BV + +OUI:70B3D5325* + ID_OUI_FROM_DATABASE=BlueMark Innovations BV + +OUI:70B3D5326* + ID_OUI_FROM_DATABASE=NEMEUS-SAS + +OUI:70B3D5327* + ID_OUI_FROM_DATABASE=Seneco A/S + +OUI:70B3D5328* + ID_OUI_FROM_DATABASE=HIPODROMO DE AGUA CALIENTE SA CV + +OUI:70B3D5329* + ID_OUI_FROM_DATABASE=Primalucelab isrl + +OUI:70B3D532A* + ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd + +OUI:70B3D532C* + ID_OUI_FROM_DATABASE=ATION Corporation + +OUI:70B3D532D* + ID_OUI_FROM_DATABASE=Hanwell Technology Co., Ltd. + +OUI:70B3D532E* + ID_OUI_FROM_DATABASE=A&T Corporation + +OUI:70B3D532F* + ID_OUI_FROM_DATABASE=Movidius SRL + +OUI:70B3D5330* + ID_OUI_FROM_DATABASE=iOne + +OUI:70B3D5331* + ID_OUI_FROM_DATABASE=Firecom, Inc. + +OUI:70B3D5332* + ID_OUI_FROM_DATABASE=InnoSenT + +OUI:70B3D5334* + ID_OUI_FROM_DATABASE=Dokuen Co. Ltd. + +OUI:70B3D5335* + ID_OUI_FROM_DATABASE=Jonsa Australia Pty Ltd + +OUI:70B3D5336* + ID_OUI_FROM_DATABASE=Synaccess Networks Inc. + +OUI:70B3D5337* + ID_OUI_FROM_DATABASE=Laborie + +OUI:70B3D5338* + ID_OUI_FROM_DATABASE=Opti-Sciences, Inc. + +OUI:70B3D5339* + ID_OUI_FROM_DATABASE=Sierra Nevada Corporation + +OUI:70B3D533B* + ID_OUI_FROM_DATABASE=Seal Shield, LLC + +OUI:70B3D533C* + ID_OUI_FROM_DATABASE=Videri Inc. + +OUI:70B3D533E* + ID_OUI_FROM_DATABASE=Dynamic Connect (Suzhou) Hi-Tech Electronic Co.,Ltd. + +OUI:70B3D533F* + ID_OUI_FROM_DATABASE=XANTIA SA + +OUI:70B3D5340* + ID_OUI_FROM_DATABASE=Renesas Electronics + +OUI:70B3D5341* + ID_OUI_FROM_DATABASE=Vtron Pty Ltd + +OUI:70B3D5342* + ID_OUI_FROM_DATABASE=Solectrix + +OUI:70B3D5343* + ID_OUI_FROM_DATABASE=Elektro-System s.c. + +OUI:70B3D5344* + ID_OUI_FROM_DATABASE=IHI Inspection & Instrumentation Co., Ltd. + +OUI:70B3D5345* + ID_OUI_FROM_DATABASE=AT-Automation Technology GmbH + +OUI:70B3D5346* + ID_OUI_FROM_DATABASE=Ultamation Limited + +OUI:70B3D5347* + ID_OUI_FROM_DATABASE=OAS Sweden AB + +OUI:70B3D5348* + ID_OUI_FROM_DATABASE=BÄR Bahnsicherung AG + +OUI:70B3D5349* + ID_OUI_FROM_DATABASE=SLAT + +OUI:70B3D534A* + ID_OUI_FROM_DATABASE=PAVO TASARIM ÜRETİM TİC A.Ş. + +OUI:70B3D534B* + ID_OUI_FROM_DATABASE=LEAFF ENGINEERING SRL + +OUI:70B3D534C* + ID_OUI_FROM_DATABASE=GLT Exports Ltd + +OUI:70B3D534D* + ID_OUI_FROM_DATABASE=Equos Research Co., Ltd + +OUI:70B3D534E* + ID_OUI_FROM_DATABASE=Risk Expert sarl + +OUI:70B3D5350* + ID_OUI_FROM_DATABASE=Tickster AB + +OUI:70B3D5351* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D5352* + ID_OUI_FROM_DATABASE=Globalcom Engineering SPA + +OUI:70B3D5353* + ID_OUI_FROM_DATABASE=Digital Outfit + +OUI:70B3D5354* + ID_OUI_FROM_DATABASE=IMP-Computer Systems + +OUI:70B3D5355* + ID_OUI_FROM_DATABASE=Hongin., Ltd + +OUI:70B3D5356* + ID_OUI_FROM_DATABASE=BRS Sistemas Eletrônicos + +OUI:70B3D5357* + ID_OUI_FROM_DATABASE=Movimento Group AB + +OUI:70B3D5358* + ID_OUI_FROM_DATABASE=Nevotek + +OUI:70B3D5359* + ID_OUI_FROM_DATABASE=Boutronic + +OUI:70B3D535A* + ID_OUI_FROM_DATABASE=Applied Radar, Inc. + +OUI:70B3D535C* + ID_OUI_FROM_DATABASE=ACS electronics srl + +OUI:70B3D535D* + ID_OUI_FROM_DATABASE=Fresh Idea Factory BV + +OUI:70B3D535E* + ID_OUI_FROM_DATABASE=EIDOS s.p.a. + +OUI:70B3D535F* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5360* + ID_OUI_FROM_DATABASE=PT. Emsonic Indonesia + +OUI:70B3D5361* + ID_OUI_FROM_DATABASE=Parent Power + +OUI:70B3D5362* + ID_OUI_FROM_DATABASE=Asiga + +OUI:70B3D5363* + ID_OUI_FROM_DATABASE=Contec Americas Inc. + +OUI:70B3D5364* + ID_OUI_FROM_DATABASE=ADAMCZEWSKI elektronische Messtechnik GmbH + +OUI:70B3D5365* + ID_OUI_FROM_DATABASE=CircuitMeter Inc. + +OUI:70B3D5366* + ID_OUI_FROM_DATABASE=Solarlytics, Inc. + +OUI:70B3D5367* + ID_OUI_FROM_DATABASE=Living Water + +OUI:70B3D5368* + ID_OUI_FROM_DATABASE=White Matter LLC + +OUI:70B3D536A* + ID_OUI_FROM_DATABASE=Becton Dickinson + +OUI:70B3D536C* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D536D* + ID_OUI_FROM_DATABASE=Cyberteam Sp z o o + +OUI:70B3D536E* + ID_OUI_FROM_DATABASE=Electrónica Falcón S.A.U + +OUI:70B3D536F* + ID_OUI_FROM_DATABASE=BuddyGuard GmbH + +OUI:70B3D5370* + ID_OUI_FROM_DATABASE=Inphi Corporation + +OUI:70B3D5371* + ID_OUI_FROM_DATABASE=BEDEROV GmbH + +OUI:70B3D5372* + ID_OUI_FROM_DATABASE=MATELEX + +OUI:70B3D5374* + ID_OUI_FROM_DATABASE=OOO NPP Mars-Energo + +OUI:70B3D5375* + ID_OUI_FROM_DATABASE=Adel System srl + +OUI:70B3D5376* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5377* + ID_OUI_FROM_DATABASE=Monnit Corporation + +OUI:70B3D5378* + ID_OUI_FROM_DATABASE=synchrotron SOLEIL + +OUI:70B3D5379* + ID_OUI_FROM_DATABASE=Vensi, Inc. + +OUI:70B3D537A* + ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC + +OUI:70B3D537B* + ID_OUI_FROM_DATABASE=Power Ltd. + +OUI:70B3D537C* + ID_OUI_FROM_DATABASE=Merus Power Dynamics Ltd. + +OUI:70B3D537D* + ID_OUI_FROM_DATABASE=The DX Shop Limited + +OUI:70B3D537E* + ID_OUI_FROM_DATABASE=ELINKGATE JSC + +OUI:70B3D537F* + ID_OUI_FROM_DATABASE=IDS Innomic GmbH + +OUI:70B3D5381* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5382* + ID_OUI_FROM_DATABASE=Naval Group + +OUI:70B3D5383* + ID_OUI_FROM_DATABASE=LPA Excil Electronics + +OUI:70B3D5384* + ID_OUI_FROM_DATABASE=Sensohive Technologies + +OUI:70B3D5385* + ID_OUI_FROM_DATABASE=Kamacho Scale Co., Ltd. + +OUI:70B3D5387* + ID_OUI_FROM_DATABASE=GWF MessSysteme AG + +OUI:70B3D5388* + ID_OUI_FROM_DATABASE=Xitron + +OUI:70B3D5389* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D538A* + ID_OUI_FROM_DATABASE=KSE GmbH + +OUI:70B3D538B* + ID_OUI_FROM_DATABASE=Lookman Electroplast Industries Ltd + +OUI:70B3D538C* + ID_OUI_FROM_DATABASE=MiraeSignal Co., Ltd + +OUI:70B3D538D* + ID_OUI_FROM_DATABASE=IMP-TELEKOMUNIKACIJE DOO + +OUI:70B3D538F* + ID_OUI_FROM_DATABASE=Sorynorydotcom Inc + +OUI:70B3D5391* + ID_OUI_FROM_DATABASE=Changshu Ruite Electric Co.,Ltd. + +OUI:70B3D5392* + ID_OUI_FROM_DATABASE=Contec Americas Inc. + +OUI:70B3D5394* + ID_OUI_FROM_DATABASE=Romteck Australia + +OUI:70B3D5396* + ID_OUI_FROM_DATABASE=CTG sp. z o. o. + +OUI:70B3D5397* + ID_OUI_FROM_DATABASE=Guangxi Hunter Information Industry Co.,Ltd + +OUI:70B3D5398* + ID_OUI_FROM_DATABASE=SIPRO s.r.l. + +OUI:70B3D539A* + ID_OUI_FROM_DATABASE=Videotrend srl + +OUI:70B3D539B* + ID_OUI_FROM_DATABASE=IROC AB + +OUI:70B3D539C* + ID_OUI_FROM_DATABASE=GD Mission Systems + +OUI:70B3D539D* + ID_OUI_FROM_DATABASE=Comark Interactive Solutions + +OUI:70B3D539E* + ID_OUI_FROM_DATABASE=Lanmark Controls Inc. + +OUI:70B3D53A0* + ID_OUI_FROM_DATABASE=chiconypower + +OUI:70B3D53A1* + ID_OUI_FROM_DATABASE=Reckeen HDP Media sp. z o.o. sp. k. + +OUI:70B3D53A4* + ID_OUI_FROM_DATABASE=Ascenix Corporation + +OUI:70B3D53A5* + ID_OUI_FROM_DATABASE=KMtronic ltd + +OUI:70B3D53A7* + ID_OUI_FROM_DATABASE=Varikorea + +OUI:70B3D53A8* + ID_OUI_FROM_DATABASE=JamHub Corp. + +OUI:70B3D53A9* + ID_OUI_FROM_DATABASE=Vivalnk + +OUI:70B3D53AA* + ID_OUI_FROM_DATABASE=RCATSONE + +OUI:70B3D53AD* + ID_OUI_FROM_DATABASE=CT Company + +OUI:70B3D53AE* + ID_OUI_FROM_DATABASE=Exicom Technologies fze + +OUI:70B3D53AF* + ID_OUI_FROM_DATABASE=Turbo Technologies Corporation + +OUI:70B3D53B0* + ID_OUI_FROM_DATABASE=Millennial Net, Inc. + +OUI:70B3D53B2* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D53B5* + ID_OUI_FROM_DATABASE=Preston Industries dba PolyScience + +OUI:70B3D53B7* + ID_OUI_FROM_DATABASE=Paul Scherrer Institut (PSI) + +OUI:70B3D53B8* + ID_OUI_FROM_DATABASE=nVideon, Inc. + +OUI:70B3D53BA* + ID_OUI_FROM_DATABASE=Silex Inside + +OUI:70B3D53BB* + ID_OUI_FROM_DATABASE=A-M Systems + +OUI:70B3D53BC* + ID_OUI_FROM_DATABASE=SciTronix + +OUI:70B3D53BD* + ID_OUI_FROM_DATABASE=DAO QIN TECHNOLOGY CO.LTD. + +OUI:70B3D53BE* + ID_OUI_FROM_DATABASE=MyDefence Communication ApS + +OUI:70B3D53BF* + ID_OUI_FROM_DATABASE=Star Electronics GmbH & Co. KG + +OUI:70B3D53C0* + ID_OUI_FROM_DATABASE=DK-Technologies A/S + +OUI:70B3D53C1* + ID_OUI_FROM_DATABASE=thingdust AG + +OUI:70B3D53C2* + ID_OUI_FROM_DATABASE=Cellular Specialties, Inc. + +OUI:70B3D53C3* + ID_OUI_FROM_DATABASE=AIMCO + +OUI:70B3D53C4* + ID_OUI_FROM_DATABASE=Hagiwara Solutions Co., Ltd. + +OUI:70B3D53C5* + ID_OUI_FROM_DATABASE=P4Q ELECTRONICS, S.L. + +OUI:70B3D53C6* + ID_OUI_FROM_DATABASE=ACD Elekronik GmbH + +OUI:70B3D53C7* + ID_OUI_FROM_DATABASE=SOFTCREATE CORP. + +OUI:70B3D53C9* + ID_OUI_FROM_DATABASE=Duerkopp-Adler + +OUI:70B3D53CA* + ID_OUI_FROM_DATABASE=TTI Ltd + +OUI:70B3D53CB* + ID_OUI_FROM_DATABASE=GeoSpectrum Technologies Inc + +OUI:70B3D53CC* + ID_OUI_FROM_DATABASE=TerOpta Ltd + +OUI:70B3D53CE* + ID_OUI_FROM_DATABASE=Aditec GmbH + +OUI:70B3D53CF* + ID_OUI_FROM_DATABASE=Systems Engineering Arts Pty Ltd + +OUI:70B3D53D0* + ID_OUI_FROM_DATABASE=ORtek Technology, Inc. + +OUI:70B3D53D2* + ID_OUI_FROM_DATABASE=Imagine Inc. + +OUI:70B3D53D4* + ID_OUI_FROM_DATABASE=Sanmina Israel + +OUI:70B3D53D5* + ID_OUI_FROM_DATABASE=oxynet Solutions + +OUI:70B3D53D7* + ID_OUI_FROM_DATABASE=Remote Sensing Solutions, Inc. + +OUI:70B3D53D8* + ID_OUI_FROM_DATABASE=Abitsoftware, Ltd. + +OUI:70B3D53D9* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D53DA* + ID_OUI_FROM_DATABASE=Loop Labs, Inc. + +OUI:70B3D53DB* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D53DD* + ID_OUI_FROM_DATABASE=Kniggendorf + Kögler Security GmbH + +OUI:70B3D53DE* + ID_OUI_FROM_DATABASE=ELOMAC Elektronik GmbH + +OUI:70B3D53DF* + ID_OUI_FROM_DATABASE=MultiDyne + +OUI:70B3D53E1* + ID_OUI_FROM_DATABASE=Barnstormer Softworks + +OUI:70B3D53E2* + ID_OUI_FROM_DATABASE=AVI Pty Ltd + +OUI:70B3D53E3* + ID_OUI_FROM_DATABASE=Head + +OUI:70B3D53E4* + ID_OUI_FROM_DATABASE=Neptec Technologies Corp. + +OUI:70B3D53E5* + ID_OUI_FROM_DATABASE=ATEME + +OUI:70B3D53E6* + ID_OUI_FROM_DATABASE=machineQ + +OUI:70B3D53E7* + ID_OUI_FROM_DATABASE=JNR Sports Holdings, LLC + +OUI:70B3D53E8* + ID_OUI_FROM_DATABASE=COSMOS web Co., Ltd. + +OUI:70B3D53E9* + ID_OUI_FROM_DATABASE=APOLLO GIKEN Co.,Ltd. + +OUI:70B3D53EA* + ID_OUI_FROM_DATABASE=DAVE SRL + +OUI:70B3D53EB* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D53EC* + ID_OUI_FROM_DATABASE=Outsight SA + +OUI:70B3D53ED* + ID_OUI_FROM_DATABASE=Ultra Electronics Sonar System Division + +OUI:70B3D53EF* + ID_OUI_FROM_DATABASE=Vtron Pty Ltd + +OUI:70B3D53F0* + ID_OUI_FROM_DATABASE=Intervala + +OUI:70B3D53F1* + ID_OUI_FROM_DATABASE=Olympus NDT Canada + +OUI:70B3D53F2* + ID_OUI_FROM_DATABASE=H3D, Inc. + +OUI:70B3D53F3* + ID_OUI_FROM_DATABASE=SPEA SPA + +OUI:70B3D53F4* + ID_OUI_FROM_DATABASE=Wincode Technology Co., Ltd. + +OUI:70B3D53F5* + ID_OUI_FROM_DATABASE=DOLBY LABORATORIES, INC. + +OUI:70B3D53F6* + ID_OUI_FROM_DATABASE=Sycomp Electronic GmbH + +OUI:70B3D53F7* + ID_OUI_FROM_DATABASE=Advansid + +OUI:70B3D53F8* + ID_OUI_FROM_DATABASE=The Fire Horn, Inc. + +OUI:70B3D53F9* + ID_OUI_FROM_DATABASE=Herrick Tech Labs + +OUI:70B3D53FA* + ID_OUI_FROM_DATABASE=Zaklad Energoelektroniki Twerd + +OUI:70B3D53FB* + ID_OUI_FROM_DATABASE=Liberty Reach + +OUI:70B3D53FC* + ID_OUI_FROM_DATABASE=TangRen C&S CO., Ltd + +OUI:70B3D53FE* + ID_OUI_FROM_DATABASE=Mentor Graphics + +OUI:70B3D53FF* + ID_OUI_FROM_DATABASE=Hydra Controls + +OUI:70B3D5400* + ID_OUI_FROM_DATABASE=Vtron Pty Ltd + +OUI:70B3D5401* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5402* + ID_OUI_FROM_DATABASE=AKIS technologies + +OUI:70B3D5403* + ID_OUI_FROM_DATABASE=Mighty Cube Co., Ltd. + +OUI:70B3D5404* + ID_OUI_FROM_DATABASE=RANIX,Inc. + +OUI:70B3D5405* + ID_OUI_FROM_DATABASE=MG s.r.l. + +OUI:70B3D5406* + ID_OUI_FROM_DATABASE=Acrodea, Inc. + +OUI:70B3D5407* + ID_OUI_FROM_DATABASE=IDOSENS + +OUI:70B3D5408* + ID_OUI_FROM_DATABASE=Comrod AS + +OUI:70B3D5409* + ID_OUI_FROM_DATABASE=Beijing Yutian Technology Co., Ltd. + +OUI:70B3D540A* + ID_OUI_FROM_DATABASE=Monroe Electronics, Inc. + +OUI:70B3D540B* + ID_OUI_FROM_DATABASE=QUERCUS TECHNOLOGIES, S.L. + +OUI:70B3D540E* + ID_OUI_FROM_DATABASE=Liaoyun Information Technology Co., Ltd. + +OUI:70B3D540F* + ID_OUI_FROM_DATABASE=NEXELEC + +OUI:70B3D5410* + ID_OUI_FROM_DATABASE=Avant Technologies, Inc + +OUI:70B3D5412* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5413* + ID_OUI_FROM_DATABASE=Axess AG + +OUI:70B3D5414* + ID_OUI_FROM_DATABASE=Smith Meter, Inc. + +OUI:70B3D5415* + ID_OUI_FROM_DATABASE=IDEA SPA + +OUI:70B3D5417* + ID_OUI_FROM_DATABASE=Figment Design Laboratories + +OUI:70B3D5418* + ID_OUI_FROM_DATABASE=DEV Systemtechnik GmbH& Co KG + +OUI:70B3D541A* + ID_OUI_FROM_DATABASE=HYOSUNG Power & Industrial Systems + +OUI:70B3D541B* + ID_OUI_FROM_DATABASE=SYS TEC electronic GmbH + +OUI:70B3D541D* + ID_OUI_FROM_DATABASE=Azmoon Keifiat + +OUI:70B3D541E* + ID_OUI_FROM_DATABASE=Redler Computers + +OUI:70B3D541F* + ID_OUI_FROM_DATABASE=Orion S.r.l. + +OUI:70B3D5420* + ID_OUI_FROM_DATABASE=ECOINET + +OUI:70B3D5421* + ID_OUI_FROM_DATABASE=North Star Bestech Co., + +OUI:70B3D5422* + ID_OUI_FROM_DATABASE=SUS Corporation + +OUI:70B3D5425* + ID_OUI_FROM_DATABASE=SinterCast + +OUI:70B3D5426* + ID_OUI_FROM_DATABASE=Zehnder Group Nederland + +OUI:70B3D5427* + ID_OUI_FROM_DATABASE=Key Chemical & Equipment Company + +OUI:70B3D5428* + ID_OUI_FROM_DATABASE=Presentation Switchers, Inc. + +OUI:70B3D5429* + ID_OUI_FROM_DATABASE=Redco Audio Inc + +OUI:70B3D542A* + ID_OUI_FROM_DATABASE=Critical Link LLC + +OUI:70B3D542B* + ID_OUI_FROM_DATABASE=Guangzhou Haoxiang Computer Technology Co.,Ltd. + +OUI:70B3D542C* + ID_OUI_FROM_DATABASE=D.Marchiori Srl + +OUI:70B3D542D* + ID_OUI_FROM_DATABASE=RCH ITALIA SPA + +OUI:70B3D542E* + ID_OUI_FROM_DATABASE=Dr. Zinngrebe GmbH + +OUI:70B3D542F* + ID_OUI_FROM_DATABASE=SINTOKOGIO, LTD + +OUI:70B3D5430* + ID_OUI_FROM_DATABASE=Algodue Elettronica Srl + +OUI:70B3D5431* + ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. + +OUI:70B3D5432* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D5433* + ID_OUI_FROM_DATABASE=Flexsolution APS + +OUI:70B3D5434* + ID_OUI_FROM_DATABASE=Wit.com Inc + +OUI:70B3D5435* + ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd + +OUI:70B3D5436* + ID_OUI_FROM_DATABASE=Henrich Electronics Corporation + +OUI:70B3D5437* + ID_OUI_FROM_DATABASE=Digital Way + +OUI:70B3D5439* + ID_OUI_FROM_DATABASE=TriLED + +OUI:70B3D543B* + ID_OUI_FROM_DATABASE=Kalycito Infotech Private Limited + +OUI:70B3D543D* + ID_OUI_FROM_DATABASE=Veryx Technologies Private Limited + +OUI:70B3D543E* + ID_OUI_FROM_DATABASE=Peloton Technology + +OUI:70B3D543F* + ID_OUI_FROM_DATABASE=biosilver .co.,ltd + +OUI:70B3D5440* + ID_OUI_FROM_DATABASE=Discover Video + +OUI:70B3D5441* + ID_OUI_FROM_DATABASE=Videoport S.A. + +OUI:70B3D5442* + ID_OUI_FROM_DATABASE=Blair Companies + +OUI:70B3D5443* + ID_OUI_FROM_DATABASE=Slot3 GmbH + +OUI:70B3D5444* + ID_OUI_FROM_DATABASE=AMS Controls, Inc. + +OUI:70B3D5445* + ID_OUI_FROM_DATABASE=Advanced Devices SpA + +OUI:70B3D5446* + ID_OUI_FROM_DATABASE=Santa Barbara Imaging Systems + +OUI:70B3D5447* + ID_OUI_FROM_DATABASE=Avid Controls Inc + +OUI:70B3D5448* + ID_OUI_FROM_DATABASE=B/E Aerospace, Inc. + +OUI:70B3D5449* + ID_OUI_FROM_DATABASE=Edgeware AB + +OUI:70B3D544B* + ID_OUI_FROM_DATABASE=Open System Solutions Limited + +OUI:70B3D544D* + ID_OUI_FROM_DATABASE=Vessel Technology Ltd + +OUI:70B3D544E* + ID_OUI_FROM_DATABASE=Solace Systems Inc. + +OUI:70B3D5454* + ID_OUI_FROM_DATABASE=Golding Audio Ltd + +OUI:70B3D5455* + ID_OUI_FROM_DATABASE=Heartlandmicropayments + +OUI:70B3D5456* + ID_OUI_FROM_DATABASE=Technological Application and Production One Member Liability Company (Tecapro company) + +OUI:70B3D5457* + ID_OUI_FROM_DATABASE=Vivaldi Clima Srl + +OUI:70B3D5458* + ID_OUI_FROM_DATABASE=Ongisul Co.,Ltd. + +OUI:70B3D5459* + ID_OUI_FROM_DATABASE=Protium Technologies, Inc. + +OUI:70B3D545A* + ID_OUI_FROM_DATABASE=Palarum LLC + +OUI:70B3D545B* + ID_OUI_FROM_DATABASE=KOMZ - IZMERENIYA + +OUI:70B3D545C* + ID_OUI_FROM_DATABASE=AlyTech + +OUI:70B3D545D* + ID_OUI_FROM_DATABASE=Sensapex Oy + +OUI:70B3D545E* + ID_OUI_FROM_DATABASE=eSOL Co.,Ltd. + +OUI:70B3D545F* + ID_OUI_FROM_DATABASE=Cloud4Wi + +OUI:70B3D5460* + ID_OUI_FROM_DATABASE=Guilin Tryin Technology Co.,Ltd + +OUI:70B3D5461* + ID_OUI_FROM_DATABASE=TESEC Corporation + +OUI:70B3D5462* + ID_OUI_FROM_DATABASE=EarTex + +OUI:70B3D5463* + ID_OUI_FROM_DATABASE=WARECUBE,INC + +OUI:70B3D5465* + ID_OUI_FROM_DATABASE=ENERGISME + +OUI:70B3D5466* + ID_OUI_FROM_DATABASE=SYLink Technologie + +OUI:70B3D5467* + ID_OUI_FROM_DATABASE=GreenWake Technologies + +OUI:70B3D5469* + ID_OUI_FROM_DATABASE=Gentec Systems Co. + +OUI:70B3D546B* + ID_OUI_FROM_DATABASE=Airborne Engineering Limited + +OUI:70B3D546C* + ID_OUI_FROM_DATABASE=SHANGHAI CHENZHU INSTRUMENT CO., LTD. + +OUI:70B3D546E* + ID_OUI_FROM_DATABASE=Zamir Recognition Systems Ltd. + +OUI:70B3D546F* + ID_OUI_FROM_DATABASE=serva transport systems GmbH + +OUI:70B3D5470* + ID_OUI_FROM_DATABASE=KITRON UAB + +OUI:70B3D5471* + ID_OUI_FROM_DATABASE=SYSCO Sicherheitssysteme GmbH + +OUI:70B3D5472* + ID_OUI_FROM_DATABASE=Quadio Devices Private Limited + +OUI:70B3D5475* + ID_OUI_FROM_DATABASE=EWATTCH + +OUI:70B3D5476* + ID_OUI_FROM_DATABASE=FR-Team International SA + +OUI:70B3D5477* + ID_OUI_FROM_DATABASE=digitrol limited + +OUI:70B3D5478* + ID_OUI_FROM_DATABASE=Touchnet/OneCard + +OUI:70B3D5479* + ID_OUI_FROM_DATABASE=LINEAGE POWER PVT LTD., + +OUI:70B3D547A* + ID_OUI_FROM_DATABASE=GlooVir Inc. + +OUI:70B3D547B* + ID_OUI_FROM_DATABASE=Monixo + +OUI:70B3D547C* + ID_OUI_FROM_DATABASE=Par-Tech, Inc. + +OUI:70B3D547E* + ID_OUI_FROM_DATABASE=Fiber Optika Technologies Pvt. Ltd. + +OUI:70B3D547F* + ID_OUI_FROM_DATABASE=ASE GmbH + +OUI:70B3D5480* + ID_OUI_FROM_DATABASE=Emergency Lighting Products Limited + +OUI:70B3D5482* + ID_OUI_FROM_DATABASE=Aeryon Labs Inc + +OUI:70B3D5486* + ID_OUI_FROM_DATABASE=ChongQing JianTao Technology Co., Ltd. + +OUI:70B3D5487* + ID_OUI_FROM_DATABASE=ECS s.r.l. + +OUI:70B3D5488* + ID_OUI_FROM_DATABASE=Cardinal Scale Mfg Co + +OUI:70B3D5489* + ID_OUI_FROM_DATABASE=ard sa + +OUI:70B3D548A* + ID_OUI_FROM_DATABASE=George Wilson Industries Ltd + +OUI:70B3D548B* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D548C* + ID_OUI_FROM_DATABASE=Integrated Systems Engineering, Inc. + +OUI:70B3D548D* + ID_OUI_FROM_DATABASE=OMEGA BILANCE SRL SOCIETA' UNIPERSONALE + +OUI:70B3D548E* + ID_OUI_FROM_DATABASE=Allim System Co,.Ltd. + +OUI:70B3D548F* + ID_OUI_FROM_DATABASE=Seiwa Giken + +OUI:70B3D5490* + ID_OUI_FROM_DATABASE=Xiamen Beogold Technology Co. Ltd. + +OUI:70B3D5492* + ID_OUI_FROM_DATABASE=Jiangsu Jinheng Information Technology Co.,Ltd. + +OUI:70B3D5493* + ID_OUI_FROM_DATABASE=Impulse Networks Pte Ltd + +OUI:70B3D5494* + ID_OUI_FROM_DATABASE=Schildknecht AG + +OUI:70B3D5495* + ID_OUI_FROM_DATABASE=Fiem Industries Ltd. + +OUI:70B3D5496* + ID_OUI_FROM_DATABASE=Profcon AB + +OUI:70B3D5497* + ID_OUI_FROM_DATABASE=ALBIRAL DISPLAY SOLUTIONS SL + +OUI:70B3D5498* + ID_OUI_FROM_DATABASE=XGEM SAS + +OUI:70B3D5499* + ID_OUI_FROM_DATABASE=Pycom Ltd + +OUI:70B3D549A* + ID_OUI_FROM_DATABASE=HAXE SYSTEME + +OUI:70B3D549B* + ID_OUI_FROM_DATABASE=Algodue Elettronica Srl + +OUI:70B3D549D* + ID_OUI_FROM_DATABASE=Shenzhen Chanslink Network Technology Co., Ltd + +OUI:70B3D549E* + ID_OUI_FROM_DATABASE=CAPTEMP, Lda + +OUI:70B3D549F* + ID_OUI_FROM_DATABASE=B.P.A. SRL + +OUI:70B3D54A0* + ID_OUI_FROM_DATABASE=FLUDIA + +OUI:70B3D54A1* + ID_OUI_FROM_DATABASE=Herholdt Controls srl + +OUI:70B3D54A2* + ID_OUI_FROM_DATABASE=DEVAU Lemppenau GmbH + +OUI:70B3D54A4* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D54A5* + ID_OUI_FROM_DATABASE=Intermind Inc. + +OUI:70B3D54A6* + ID_OUI_FROM_DATABASE=HZHY TECHNOLOGY + +OUI:70B3D54A7* + ID_OUI_FROM_DATABASE=aelettronica group srl + +OUI:70B3D54A8* + ID_OUI_FROM_DATABASE=Acrodea, Inc. + +OUI:70B3D54A9* + ID_OUI_FROM_DATABASE=WARECUBE,INC + +OUI:70B3D54AA* + ID_OUI_FROM_DATABASE=Twoway Communications, Inc. + +OUI:70B3D54AB* + ID_OUI_FROM_DATABASE=TruTeq Wireless (Pty) Ltd + +OUI:70B3D54AC* + ID_OUI_FROM_DATABASE=Microsoft Research + +OUI:70B3D54AD* + ID_OUI_FROM_DATABASE=GACI + +OUI:70B3D54AE* + ID_OUI_FROM_DATABASE=Reinhardt System- und Messelectronic GmbH + +OUI:70B3D54AF* + ID_OUI_FROM_DATABASE=Agramkow Fluid Systems A/S + +OUI:70B3D54B0* + ID_OUI_FROM_DATABASE=Tecogen Inc. + +OUI:70B3D54B1* + ID_OUI_FROM_DATABASE=LACE LLC. + +OUI:70B3D54B2* + ID_OUI_FROM_DATABASE=Certus Operations Ltd + +OUI:70B3D54B3* + ID_OUI_FROM_DATABASE=Bacsoft + +OUI:70B3D54B4* + ID_OUI_FROM_DATABASE=Hi Tech Systems Ltd + +OUI:70B3D54B6* + ID_OUI_FROM_DATABASE=VEILUX INC. + +OUI:70B3D54B7* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D54B8* + ID_OUI_FROM_DATABASE=International Roll-Call Corporation + +OUI:70B3D54B9* + ID_OUI_FROM_DATABASE=SHEN ZHEN TTK TECHNOLOGY CO,LTD + +OUI:70B3D54BA* + ID_OUI_FROM_DATABASE=Sinftech LLC + +OUI:70B3D54BB* + ID_OUI_FROM_DATABASE=Plazma-T + +OUI:70B3D54BC* + ID_OUI_FROM_DATABASE=TIAMA + +OUI:70B3D54BD* + ID_OUI_FROM_DATABASE=Boulder Amplifiers, Inc. + +OUI:70B3D54BE* + ID_OUI_FROM_DATABASE=GY-FX SAS + +OUI:70B3D54BF* + ID_OUI_FROM_DATABASE=Exsom Computers LLC + +OUI:70B3D54C0* + ID_OUI_FROM_DATABASE=Technica Engineering GmbH + +OUI:70B3D54C1* + ID_OUI_FROM_DATABASE=QUERCUS TECHNOLOGIES, S. L. + +OUI:70B3D54C2* + ID_OUI_FROM_DATABASE=hera Laborsysteme GmbH + +OUI:70B3D54C4* + ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies + +OUI:70B3D54C5* + ID_OUI_FROM_DATABASE=Moving iMage Technologies LLC + +OUI:70B3D54C6* + ID_OUI_FROM_DATABASE=BlueBox Video Limited + +OUI:70B3D54C7* + ID_OUI_FROM_DATABASE=SOLVERIS sp. z o.o. + +OUI:70B3D54C8* + ID_OUI_FROM_DATABASE=Hosokawa Micron Powder Systems + +OUI:70B3D54C9* + ID_OUI_FROM_DATABASE=Elsist Srl + +OUI:70B3D54CC* + ID_OUI_FROM_DATABASE=FRESENIUS MEDICAL CARE + +OUI:70B3D54CD* + ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. + +OUI:70B3D54CE* + ID_OUI_FROM_DATABASE=Agilack + +OUI:70B3D54CF* + ID_OUI_FROM_DATABASE=GREEN HOUSE CO., LTD. + +OUI:70B3D54D1* + ID_OUI_FROM_DATABASE=Contraves Advanced Devices Sdn. Bhd. + +OUI:70B3D54D2* + ID_OUI_FROM_DATABASE=Biotage Sweden AB + +OUI:70B3D54D3* + ID_OUI_FROM_DATABASE=Hefei STAROT Technology Co.,Ltd + +OUI:70B3D54D4* + ID_OUI_FROM_DATABASE=Nortek Global HVAC + +OUI:70B3D54D5* + ID_OUI_FROM_DATABASE=Moog Rekofa GmbH + +OUI:70B3D54D6* + ID_OUI_FROM_DATABASE=Operational Technology Solutions + +OUI:70B3D54D8* + ID_OUI_FROM_DATABASE=Versilis Inc. + +OUI:70B3D54DB* + ID_OUI_FROM_DATABASE=Temperature@lert + +OUI:70B3D54DC* + ID_OUI_FROM_DATABASE=JK DEVICE CORPORATION + +OUI:70B3D54DD* + ID_OUI_FROM_DATABASE=Road-iQ, LLC + +OUI:70B3D54DE* + ID_OUI_FROM_DATABASE=Oso Technologies, Inc. + +OUI:70B3D54DF* + ID_OUI_FROM_DATABASE=Nidec Avtron Automation Corp + +OUI:70B3D54E0* + ID_OUI_FROM_DATABASE=Microvideo + +OUI:70B3D54E1* + ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. + +OUI:70B3D54E4* + ID_OUI_FROM_DATABASE=W.A. Benjamin Electric Co. + +OUI:70B3D54E5* + ID_OUI_FROM_DATABASE=viZaar industrial imaging AG + +OUI:70B3D54E7* + ID_OUI_FROM_DATABASE=Digital Domain + +OUI:70B3D54E8* + ID_OUI_FROM_DATABASE=Copious Imaging LLC + +OUI:70B3D54E9* + ID_OUI_FROM_DATABASE=ADETEC SAS + +OUI:70B3D54EA* + ID_OUI_FROM_DATABASE=Vocality international T/A Cubic + +OUI:70B3D54EB* + ID_OUI_FROM_DATABASE=INFOSOFT DIGITAL DESIGN & SERVICES PRIVATE LIMITED + +OUI:70B3D54EC* + ID_OUI_FROM_DATABASE=Hangzhou Youshi Industry Co., Ltd. + +OUI:70B3D54EE* + ID_OUI_FROM_DATABASE=NOA Co., Ltd. + +OUI:70B3D54EF* + ID_OUI_FROM_DATABASE=CMI, Inc. + +OUI:70B3D54F0* + ID_OUI_FROM_DATABASE=Li Seng Technology Ltd., + +OUI:70B3D54F1* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:70B3D54F2* + ID_OUI_FROM_DATABASE=COMPAL ELECTRONICS, INC. + +OUI:70B3D54F3* + ID_OUI_FROM_DATABASE=XPS ELETRONICA LTDA + +OUI:70B3D54F4* + ID_OUI_FROM_DATABASE=WiTagg, Inc + +OUI:70B3D54F6* + ID_OUI_FROM_DATABASE=DORLET SAU + +OUI:70B3D54F7* + ID_OUI_FROM_DATABASE=Foxtel srl + +OUI:70B3D54F8* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D54F9* + ID_OUI_FROM_DATABASE=OptoPrecision GmbH + +OUI:70B3D54FA* + ID_OUI_FROM_DATABASE=Thruvision Limited + +OUI:70B3D54FC* + ID_OUI_FROM_DATABASE=Mettler Toledo + +OUI:70B3D54FD* + ID_OUI_FROM_DATABASE=ENLESS WIRELESS + +OUI:70B3D54FE* + ID_OUI_FROM_DATABASE=WiTagg, Inc + +OUI:70B3D54FF* + ID_OUI_FROM_DATABASE=Shanghai AiGentoo Information Technology Co.,Ltd. + +OUI:70B3D5500* + ID_OUI_FROM_DATABASE=Mistral Solutions Pvt. LTD + +OUI:70B3D5501* + ID_OUI_FROM_DATABASE=Peek Traffic + +OUI:70B3D5502* + ID_OUI_FROM_DATABASE=Glidewell Laboratories + +OUI:70B3D5503* + ID_OUI_FROM_DATABASE=Itest communication Tech Co., LTD + +OUI:70B3D5504* + ID_OUI_FROM_DATABASE=Xsight Systems Ltd. + +OUI:70B3D5505* + ID_OUI_FROM_DATABASE=MC2-Technologies + +OUI:70B3D5506* + ID_OUI_FROM_DATABASE=Tonbo Imaging Pte Ltd + +OUI:70B3D5507* + ID_OUI_FROM_DATABASE=Human Oriented Technology, Inc. + +OUI:70B3D5508* + ID_OUI_FROM_DATABASE=INSEVIS GmbH + +OUI:70B3D550A* + ID_OUI_FROM_DATABASE=AMEDTEC Medizintechnik Aue GmbH + +OUI:70B3D550C* + ID_OUI_FROM_DATABASE=Hangzhou landesker digital technology co. LTD + +OUI:70B3D550D* + ID_OUI_FROM_DATABASE=CT Company + +OUI:70B3D550E* + ID_OUI_FROM_DATABASE=Micro Trend Automation Co., LTD + +OUI:70B3D5510* + ID_OUI_FROM_DATABASE=PSL ELEKTRONİK SANAYİ VE TİCARET A.S. + +OUI:70B3D5511* + ID_OUI_FROM_DATABASE=Next Sight srl + +OUI:70B3D5512* + ID_OUI_FROM_DATABASE=Techno Broad,Inc + +OUI:70B3D5513* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5514* + ID_OUI_FROM_DATABASE=Intelligent Security Systems (ISS) + +OUI:70B3D5515* + ID_OUI_FROM_DATABASE=PCSC + +OUI:70B3D5516* + ID_OUI_FROM_DATABASE=LINEAGE POWER PVT LTD., + +OUI:70B3D5517* + ID_OUI_FROM_DATABASE=ISPHER + +OUI:70B3D5518* + ID_OUI_FROM_DATABASE=CRUXELL Corp. + +OUI:70B3D5519* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D551A* + ID_OUI_FROM_DATABASE=Shachihata Inc. + +OUI:70B3D551B* + ID_OUI_FROM_DATABASE=Vitrea Smart Home Technologies + +OUI:70B3D551C* + ID_OUI_FROM_DATABASE=ATX Networks Corp + +OUI:70B3D551D* + ID_OUI_FROM_DATABASE=Tecnint HTE SRL + +OUI:70B3D551E* + ID_OUI_FROM_DATABASE=Fundación Cardiovascular de Colombia + +OUI:70B3D5521* + ID_OUI_FROM_DATABASE=Selex ES Inc. + +OUI:70B3D5522* + ID_OUI_FROM_DATABASE=Syncopated Engineering Inc + +OUI:70B3D5523* + ID_OUI_FROM_DATABASE=Tibit Communications + +OUI:70B3D5524* + ID_OUI_FROM_DATABASE=Wuxi New Optical Communication Co.,Ltd. + +OUI:70B3D5525* + ID_OUI_FROM_DATABASE=Plantiga Technologies Inc + +OUI:70B3D5526* + ID_OUI_FROM_DATABASE=FlowNet LLC + +OUI:70B3D5528* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5529* + ID_OUI_FROM_DATABASE=Inventeq B.V. + +OUI:70B3D552A* + ID_OUI_FROM_DATABASE=Dataflex International BV + +OUI:70B3D552B* + ID_OUI_FROM_DATABASE=GE Aviation Cheltenham + +OUI:70B3D552C* + ID_OUI_FROM_DATABASE=Centuryarks Ltd., + +OUI:70B3D552D* + ID_OUI_FROM_DATABASE=Tanaka Electric Industry Co., Ltd. + +OUI:70B3D552E* + ID_OUI_FROM_DATABASE=Swissponic Sagl + +OUI:70B3D552F* + ID_OUI_FROM_DATABASE=R.C. Systems Inc + +OUI:70B3D5530* + ID_OUI_FROM_DATABASE=iSiS-Ex Limited + +OUI:70B3D5531* + ID_OUI_FROM_DATABASE=ATEME + +OUI:70B3D5532* + ID_OUI_FROM_DATABASE=Talleres de Escoriaza SA + +OUI:70B3D5533* + ID_OUI_FROM_DATABASE=Nippon Marine Enterprises, Ltd. + +OUI:70B3D5535* + ID_OUI_FROM_DATABASE=SITA Messtechnik GmbH + +OUI:70B3D5537* + ID_OUI_FROM_DATABASE=Biennebi s.r.l. + +OUI:70B3D5538* + ID_OUI_FROM_DATABASE=sydetion UG (h.b.) + +OUI:70B3D5539* + ID_OUI_FROM_DATABASE=Tempris GmbH + +OUI:70B3D553A* + ID_OUI_FROM_DATABASE=Pano0ramic Power + +OUI:70B3D553B* + ID_OUI_FROM_DATABASE=Mr.Loop + +OUI:70B3D553C* + ID_OUI_FROM_DATABASE=Airthings + +OUI:70B3D553D* + ID_OUI_FROM_DATABASE=ACCEL CORP + +OUI:70B3D5541* + ID_OUI_FROM_DATABASE=Nanjing Pingguang Electronic Technology Co., Ltd + +OUI:70B3D5542* + ID_OUI_FROM_DATABASE=RTDS Technologies Inc. + +OUI:70B3D5543* + ID_OUI_FROM_DATABASE=wallbe GmbH + +OUI:70B3D5544* + ID_OUI_FROM_DATABASE=Silicon Safe Ltd + +OUI:70B3D5545* + ID_OUI_FROM_DATABASE=Airity Technologies Inc. + +OUI:70B3D5546* + ID_OUI_FROM_DATABASE=Sensefarm AB + +OUI:70B3D5547* + ID_OUI_FROM_DATABASE=CE LINK LIMITED + +OUI:70B3D5548* + ID_OUI_FROM_DATABASE=DIGIVERV INC + +OUI:70B3D5549* + ID_OUI_FROM_DATABASE=Procon automatic systems GmbH + +OUI:70B3D554A* + ID_OUI_FROM_DATABASE=Digital Instrument Transformers + +OUI:70B3D554B* + ID_OUI_FROM_DATABASE=Brakels IT + +OUI:70B3D554C* + ID_OUI_FROM_DATABASE=Husty M.Styczen J.Hupert Sp.J. + +OUI:70B3D554D* + ID_OUI_FROM_DATABASE=Qingdao Haitian Weiye Automation Control System Co., Ltd + +OUI:70B3D554E* + ID_OUI_FROM_DATABASE=RFL Electronics, Inc. + +OUI:70B3D554F* + ID_OUI_FROM_DATABASE=Assembly Contracts Limited + +OUI:70B3D5550* + ID_OUI_FROM_DATABASE=Merten GmbH&CoKG + +OUI:70B3D5551* + ID_OUI_FROM_DATABASE=infrachip + +OUI:70B3D5553* + ID_OUI_FROM_DATABASE=TAALEX Systemtechnik GmbH + +OUI:70B3D5554* + ID_OUI_FROM_DATABASE=Teletypes Manufacturing Plant + +OUI:70B3D5555* + ID_OUI_FROM_DATABASE=SoftLab-NSK + +OUI:70B3D5556* + ID_OUI_FROM_DATABASE=OHASHI ENGINEERING CO.,LTD. + +OUI:70B3D5557* + ID_OUI_FROM_DATABASE=HEITEC AG + +OUI:70B3D5558* + ID_OUI_FROM_DATABASE=Multiple Access Communications Ltd + +OUI:70B3D5559* + ID_OUI_FROM_DATABASE=Eagle Mountain Technology + +OUI:70B3D555A* + ID_OUI_FROM_DATABASE=Sontay Ltd. + +OUI:70B3D555B* + ID_OUI_FROM_DATABASE=Procon Electronics Pty Ltd + +OUI:70B3D555C* + ID_OUI_FROM_DATABASE=Saratoga Speed, Inc. + +OUI:70B3D555D* + ID_OUI_FROM_DATABASE=LunaNexus Inc + +OUI:70B3D555E* + ID_OUI_FROM_DATABASE=BRS Sistemas Eletrônicos + +OUI:70B3D555F* + ID_OUI_FROM_DATABASE=Deep BV + +OUI:70B3D5563* + ID_OUI_FROM_DATABASE=Zhejiang Hao Teng Electronic Technology Co., Ltd. + +OUI:70B3D5564* + ID_OUI_FROM_DATABASE=christmann informationstechnik + medien GmbH & Co. KG + +OUI:70B3D5565* + ID_OUI_FROM_DATABASE=Clecell + +OUI:70B3D5566* + ID_OUI_FROM_DATABASE=Data Informs LLC + +OUI:70B3D5568* + ID_OUI_FROM_DATABASE=Small Data Garden Oy + +OUI:70B3D5569* + ID_OUI_FROM_DATABASE=Nuance Hearing Ltd. + +OUI:70B3D556A* + ID_OUI_FROM_DATABASE=Harvard Technology Ltd + +OUI:70B3D556B* + ID_OUI_FROM_DATABASE=S.E.I. CO.,LTD. + +OUI:70B3D556C* + ID_OUI_FROM_DATABASE=Telensa Ltd + +OUI:70B3D556D* + ID_OUI_FROM_DATABASE=Pro-Digital Projetos Eletronicos Ltda + +OUI:70B3D556E* + ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. + +OUI:70B3D556F* + ID_OUI_FROM_DATABASE=Radikal d.o.o. + +OUI:70B3D5570* + ID_OUI_FROM_DATABASE=Bayern Engineering GmbH & Co. KG + +OUI:70B3D5571* + ID_OUI_FROM_DATABASE=Echogear + +OUI:70B3D5572* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5574* + ID_OUI_FROM_DATABASE=Cloud Intelligence Pty Ltd + +OUI:70B3D5575* + ID_OUI_FROM_DATABASE=Konrad GmbH + +OUI:70B3D5576* + ID_OUI_FROM_DATABASE=Shandong Hospot IOT Technology Co.,Ltd. + +OUI:70B3D5577* + ID_OUI_FROM_DATABASE=DSILOG + +OUI:70B3D5578* + ID_OUI_FROM_DATABASE=IMAGE TECH CO.,LTD + +OUI:70B3D5579* + ID_OUI_FROM_DATABASE=Chelsea Technologies Group Ltd + +OUI:70B3D557A* + ID_OUI_FROM_DATABASE=Rhythm Engineering, LLC. + +OUI:70B3D557B* + ID_OUI_FROM_DATABASE=ELAMAKATO GmbH + +OUI:70B3D557C* + ID_OUI_FROM_DATABASE=Automata GmbH & Co. KG + +OUI:70B3D557D* + ID_OUI_FROM_DATABASE=WICOM1 GmbH + +OUI:70B3D557E* + ID_OUI_FROM_DATABASE=Ascon Tecnologic S.r.l. + +OUI:70B3D557F* + ID_OUI_FROM_DATABASE=MBio Diagnostics, Inc. + +OUI:70B3D5580* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5582* + ID_OUI_FROM_DATABASE=VAGLER International Sdn Bhd + +OUI:70B3D5583* + ID_OUI_FROM_DATABASE=Ducommun Inc. + +OUI:70B3D5584* + ID_OUI_FROM_DATABASE=Sertone, a division of Opti-Knights Ltd + +OUI:70B3D5585* + ID_OUI_FROM_DATABASE=Nefteavtomatika + +OUI:70B3D5587* + ID_OUI_FROM_DATABASE=INCAA Computers + +OUI:70B3D5588* + ID_OUI_FROM_DATABASE=LLC NPO Svyazkomplektservis + +OUI:70B3D5589* + ID_OUI_FROM_DATABASE=Cityntel OU + +OUI:70B3D558A* + ID_OUI_FROM_DATABASE=ITK Dr. Kassen GmbH + +OUI:70B3D558C* + ID_OUI_FROM_DATABASE=OPTSYS + +OUI:70B3D558D* + ID_OUI_FROM_DATABASE=DORLET SAU + +OUI:70B3D558E* + ID_OUI_FROM_DATABASE=VEILUX INC. + +OUI:70B3D558F* + ID_OUI_FROM_DATABASE=LSL systems + +OUI:70B3D5590* + ID_OUI_FROM_DATABASE=812th AITS + +OUI:70B3D5591* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5592* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5593* + ID_OUI_FROM_DATABASE=Asis Pro + +OUI:70B3D5594* + ID_OUI_FROM_DATABASE=ATE Systems Inc + +OUI:70B3D5595* + ID_OUI_FROM_DATABASE=PLR Prueftechnik Linke und Ruehe GmbH + +OUI:70B3D5596* + ID_OUI_FROM_DATABASE=Mencom Corporation + +OUI:70B3D5597* + ID_OUI_FROM_DATABASE=VAPE RAIL INTERNATIONAL + +OUI:70B3D5598* + ID_OUI_FROM_DATABASE=Ruag Defence France SAS + +OUI:70B3D5599* + ID_OUI_FROM_DATABASE=LECO Corporation + +OUI:70B3D559A* + ID_OUI_FROM_DATABASE=Wagner Group GmbH + +OUI:70B3D559B* + ID_OUI_FROM_DATABASE=AUTOMATIZACION Y CONECTIVIDAD SA DE CV + +OUI:70B3D559C* + ID_OUI_FROM_DATABASE=DAVE SRL + +OUI:70B3D559D* + ID_OUI_FROM_DATABASE=servicios de consultoria independiente S.L. + +OUI:70B3D55A0* + ID_OUI_FROM_DATABASE=Ascon Tecnologic S.r.l. + +OUI:70B3D55A2* + ID_OUI_FROM_DATABASE=Wallner Automation GmbH + +OUI:70B3D55A3* + ID_OUI_FROM_DATABASE=CT Company + +OUI:70B3D55A5* + ID_OUI_FROM_DATABASE=Rehwork GmbH + +OUI:70B3D55A6* + ID_OUI_FROM_DATABASE=TimeMachines Inc. + +OUI:70B3D55A7* + ID_OUI_FROM_DATABASE=ABB S.p.A. + +OUI:70B3D55A8* + ID_OUI_FROM_DATABASE=Farmobile + +OUI:70B3D55A9* + ID_OUI_FROM_DATABASE=Bunka Shutter Co., Ltd. + +OUI:70B3D55AA* + ID_OUI_FROM_DATABASE=Chugoku Electric Manufacturing Co.,Inc + +OUI:70B3D55AB* + ID_OUI_FROM_DATABASE=Sea Air and Land Communications Ltd + +OUI:70B3D55AD* + ID_OUI_FROM_DATABASE=Profotech + +OUI:70B3D55AE* + ID_OUI_FROM_DATABASE=TinTec Co., Ltd. + +OUI:70B3D55AF* + ID_OUI_FROM_DATABASE=JENG IoT BV + +OUI:70B3D55B0* + ID_OUI_FROM_DATABASE=Qxperts Italia S.r.l. + +OUI:70B3D55B1* + ID_OUI_FROM_DATABASE=EPD Electronics + +OUI:70B3D55B2* + ID_OUI_FROM_DATABASE=Peter Huber Kaeltemaschinenbau AG + +OUI:70B3D55B4* + ID_OUI_FROM_DATABASE=Systems Technologies + +OUI:70B3D55B5* + ID_OUI_FROM_DATABASE=Lehigh Electric Products Co + +OUI:70B3D55B6* + ID_OUI_FROM_DATABASE=Ethical Lighting and Sensor Solutions Limited + +OUI:70B3D55B8* + ID_OUI_FROM_DATABASE=Hella Gutmann Solutions GmbH + +OUI:70B3D55BA* + ID_OUI_FROM_DATABASE=INFRASAFE/ ADVANTOR SYSTEMS + +OUI:70B3D55BB* + ID_OUI_FROM_DATABASE=Olympus NDT Canada + +OUI:70B3D55BC* + ID_OUI_FROM_DATABASE=LAMTEC Meß- und Regeltechnik für Feuerungen GmbH & Co. KG + +OUI:70B3D55BE* + ID_OUI_FROM_DATABASE=CASWA + +OUI:70B3D55BF* + ID_OUI_FROM_DATABASE=Aton srl + +OUI:70B3D55C1* + ID_OUI_FROM_DATABASE=Shanghai JaWay Information Technology Co., Ltd. + +OUI:70B3D55C4* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D55C5* + ID_OUI_FROM_DATABASE=Haag-Streit AG + +OUI:70B3D55C8* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D55CA* + ID_OUI_FROM_DATABASE=ACD Elekronik GmbH + +OUI:70B3D55CC* + ID_OUI_FROM_DATABASE=Akse srl + +OUI:70B3D55CD* + ID_OUI_FROM_DATABASE=MVT Video Technologies R + H Maedler GbR + +OUI:70B3D55CF* + ID_OUI_FROM_DATABASE=PROEL TSI s.r.l. + +OUI:70B3D55D0* + ID_OUI_FROM_DATABASE=InterTalk Critical Information Systems + +OUI:70B3D55D1* + ID_OUI_FROM_DATABASE=Software Motor Corp + +OUI:70B3D55D2* + ID_OUI_FROM_DATABASE=Contec Americas Inc. + +OUI:70B3D55D3* + ID_OUI_FROM_DATABASE=Supracon AG + +OUI:70B3D55D4* + ID_OUI_FROM_DATABASE=RCH ITALIA SPA + +OUI:70B3D55D5* + ID_OUI_FROM_DATABASE=CT Company + +OUI:70B3D55D6* + ID_OUI_FROM_DATABASE=BMT Messtechnik Gmbh + +OUI:70B3D55D8* + ID_OUI_FROM_DATABASE=LYNX Technik AG + +OUI:70B3D55DA* + ID_OUI_FROM_DATABASE=Valk Welding B.V. + +OUI:70B3D55DB* + ID_OUI_FROM_DATABASE=Movicom LLC + +OUI:70B3D55DC* + ID_OUI_FROM_DATABASE=FactoryLab B.V. + +OUI:70B3D55DD* + ID_OUI_FROM_DATABASE=Theatrixx Technologies, Inc. + +OUI:70B3D55DE* + ID_OUI_FROM_DATABASE=Hangzhou AwareTec Technology Co., Ltd + +OUI:70B3D55DF* + ID_OUI_FROM_DATABASE=Semacon Business Machines + +OUI:70B3D55E0* + ID_OUI_FROM_DATABASE=Hexagon Metrology SAS + +OUI:70B3D55E1* + ID_OUI_FROM_DATABASE=Arevita + +OUI:70B3D55E2* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D55E3* + ID_OUI_FROM_DATABASE=Imecon Engineering SrL + +OUI:70B3D55E4* + ID_OUI_FROM_DATABASE=DSP DESIGN + +OUI:70B3D55E5* + ID_OUI_FROM_DATABASE=HAIYANG OLIX CO.,LTD. + +OUI:70B3D55E6* + ID_OUI_FROM_DATABASE=Mechatronics Systems Private Limited + +OUI:70B3D55E7* + ID_OUI_FROM_DATABASE=Heroic Technologies Inc. + +OUI:70B3D55E8* + ID_OUI_FROM_DATABASE=VITEC + +OUI:70B3D55E9* + ID_OUI_FROM_DATABASE=Zehetner-Elektronik GmbH + +OUI:70B3D55EA* + ID_OUI_FROM_DATABASE=KYS,INC + +OUI:70B3D55EB* + ID_OUI_FROM_DATABASE=Loma Systems s.r.o. + +OUI:70B3D55EC* + ID_OUI_FROM_DATABASE=Creative Electronics Ltd + +OUI:70B3D55ED* + ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG + +OUI:70B3D55EE* + ID_OUI_FROM_DATABASE=Mikrotron Mikrocomputer, Digital- und Analogtechnik GmbH + +OUI:70B3D55EF* + ID_OUI_FROM_DATABASE=Star Systems International + +OUI:70B3D55F0* + ID_OUI_FROM_DATABASE=managee GmbH & Co KG + +OUI:70B3D55F1* + ID_OUI_FROM_DATABASE=Fater Rasa Noor + +OUI:70B3D55F2* + ID_OUI_FROM_DATABASE=Invisible Systems Limited + +OUI:70B3D55F3* + ID_OUI_FROM_DATABASE=Rtone + +OUI:70B3D55F4* + ID_OUI_FROM_DATABASE=FDSTiming + +OUI:70B3D55F6* + ID_OUI_FROM_DATABASE=FreeFlight Systems + +OUI:70B3D55F7* + ID_OUI_FROM_DATABASE=JFA Electronics Industry and Commerce EIRELI + +OUI:70B3D55F8* + ID_OUI_FROM_DATABASE=Forcite Helmet Systems Pty Ltd + +OUI:70B3D55F9* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D55FA* + ID_OUI_FROM_DATABASE=TEX COMPUTER SRL + +OUI:70B3D55FB* + ID_OUI_FROM_DATABASE=TELEPLATFORMS + +OUI:70B3D55FC* + ID_OUI_FROM_DATABASE=SURTEC + +OUI:70B3D55FD* + ID_OUI_FROM_DATABASE=Windar Photonics + +OUI:70B3D55FF* + ID_OUI_FROM_DATABASE=Vaisala Oyj + +OUI:70B3D5600* + ID_OUI_FROM_DATABASE=Stellwerk GmbH + +OUI:70B3D5601* + ID_OUI_FROM_DATABASE=Tricom Research Inc. + +OUI:70B3D5602* + ID_OUI_FROM_DATABASE=Quantum Opus, LLC + +OUI:70B3D5603* + ID_OUI_FROM_DATABASE=EGISTECH CO.,LTD. + +OUI:70B3D5605* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5606* + ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies + +OUI:70B3D5607* + ID_OUI_FROM_DATABASE=ATEME + +OUI:70B3D5608* + ID_OUI_FROM_DATABASE=EIIT SA + +OUI:70B3D5609* + ID_OUI_FROM_DATABASE=PBSI Group Limited + +OUI:70B3D560A* + ID_OUI_FROM_DATABASE=TATA POWER SED + +OUI:70B3D560B* + ID_OUI_FROM_DATABASE=Edgeware AB + +OUI:70B3D560C* + ID_OUI_FROM_DATABASE=IST ElektronikgesmbH + +OUI:70B3D560D* + ID_OUI_FROM_DATABASE=Link Electric & Safety Control Co. + +OUI:70B3D560E* + ID_OUI_FROM_DATABASE=HDANYWHERE + +OUI:70B3D560F* + ID_OUI_FROM_DATABASE=Tanaka Information System, LLC. + +OUI:70B3D5610* + ID_OUI_FROM_DATABASE=POLVISION + +OUI:70B3D5611* + ID_OUI_FROM_DATABASE=Avionica + +OUI:70B3D5613* + ID_OUI_FROM_DATABASE=Suprock Technologies + +OUI:70B3D5614* + ID_OUI_FROM_DATABASE=QUALITTEQ LLC + +OUI:70B3D5615* + ID_OUI_FROM_DATABASE=JSC OTZVUK + +OUI:70B3D5616* + ID_OUI_FROM_DATABASE=Axxess Identification Ltd + +OUI:70B3D5617* + ID_OUI_FROM_DATABASE=Cominfo, Inc. + +OUI:70B3D5618* + ID_OUI_FROM_DATABASE=Motec Pty Ltd + +OUI:70B3D561A* + ID_OUI_FROM_DATABASE=Rocket Lab Ltd. + +OUI:70B3D561B* + ID_OUI_FROM_DATABASE=Nubewell Networks Pvt Ltd + +OUI:70B3D561C* + ID_OUI_FROM_DATABASE=Earth Works + +OUI:70B3D561D* + ID_OUI_FROM_DATABASE=Telonic Berkeley Inc + +OUI:70B3D561E* + ID_OUI_FROM_DATABASE=PKE Electronics AG + +OUI:70B3D561F* + ID_OUI_FROM_DATABASE=Labotect Labor-Technik-Göttingen GmbH + +OUI:70B3D5620* + ID_OUI_FROM_DATABASE=Orlaco Products B.V. + +OUI:70B3D5623* + ID_OUI_FROM_DATABASE=Beijing HuaLian Technology Co, Ltd. + +OUI:70B3D5625* + ID_OUI_FROM_DATABASE=VX Instruments GmbH + +OUI:70B3D5628* + ID_OUI_FROM_DATABASE=MECT SRL + +OUI:70B3D562A* + ID_OUI_FROM_DATABASE=DOGA + +OUI:70B3D562B* + ID_OUI_FROM_DATABASE=Silicann Systems GmbH + +OUI:70B3D562C* + ID_OUI_FROM_DATABASE=OOO NTC Rotek + +OUI:70B3D562D* + ID_OUI_FROM_DATABASE=elements + +OUI:70B3D562F* + ID_OUI_FROM_DATABASE=BARCO, s.r.o. + +OUI:70B3D5630* + ID_OUI_FROM_DATABASE=LGE + +OUI:70B3D5631* + ID_OUI_FROM_DATABASE=SENSO2ME + +OUI:70B3D5633* + ID_OUI_FROM_DATABASE=OBSERVER FOUNDATION + +OUI:70B3D5634* + ID_OUI_FROM_DATABASE=idaqs Co.,Ltd. + +OUI:70B3D5635* + ID_OUI_FROM_DATABASE=Cosylab d.d. + +OUI:70B3D5636* + ID_OUI_FROM_DATABASE=Globalcom Engineering SPA + +OUI:70B3D5637* + ID_OUI_FROM_DATABASE=INEO-SENSE + +OUI:70B3D5638* + ID_OUI_FROM_DATABASE=Parkalot Denmark ApS + +OUI:70B3D563A* + ID_OUI_FROM_DATABASE=DAVE SRL + +OUI:70B3D563B* + ID_OUI_FROM_DATABASE=Lazer Safe Pty Ltd + +OUI:70B3D563C* + ID_OUI_FROM_DATABASE=Pivothead + +OUI:70B3D563D* + ID_OUI_FROM_DATABASE=Storbyte, Inc. + +OUI:70B3D563E* + ID_OUI_FROM_DATABASE=RIKEN OPTECH CORPORATION + +OUI:70B3D563F* + ID_OUI_FROM_DATABASE=YG COMPANY CO., LTD + +OUI:70B3D5640* + ID_OUI_FROM_DATABASE=Electronic Equipment Company Pvt. Ltd. + +OUI:70B3D5641* + ID_OUI_FROM_DATABASE=Burk Technology + +OUI:70B3D5642* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5643* + ID_OUI_FROM_DATABASE=Marques,S.A. + +OUI:70B3D5644* + ID_OUI_FROM_DATABASE=ATX Networks Corp + +OUI:70B3D5645* + ID_OUI_FROM_DATABASE=Project Decibel, Inc. + +OUI:70B3D5647* + ID_OUI_FROM_DATABASE=KZTA + +OUI:70B3D5648* + ID_OUI_FROM_DATABASE=Magnamed Tecnologia Medica S/A + +OUI:70B3D5649* + ID_OUI_FROM_DATABASE=swissled technologies AG + +OUI:70B3D564A* + ID_OUI_FROM_DATABASE=Netbric Technology Co.,Ltd. + +OUI:70B3D564B* + ID_OUI_FROM_DATABASE=Kalfire + +OUI:70B3D564C* + ID_OUI_FROM_DATABASE=ACEMIS FRANCE + +OUI:70B3D564E* + ID_OUI_FROM_DATABASE=BigStuff3, Inc. + +OUI:70B3D5650* + ID_OUI_FROM_DATABASE=GIFAS-ELECTRIC GmbH + +OUI:70B3D5651* + ID_OUI_FROM_DATABASE=Roxford + +OUI:70B3D5652* + ID_OUI_FROM_DATABASE=Robert Bosch, LLC + +OUI:70B3D5653* + ID_OUI_FROM_DATABASE=Luxar Tech, Inc. + +OUI:70B3D5654* + ID_OUI_FROM_DATABASE=EMAC, Inc. + +OUI:70B3D5655* + ID_OUI_FROM_DATABASE=AOT System GmbH + +OUI:70B3D5656* + ID_OUI_FROM_DATABASE=SonoSound ApS + +OUI:70B3D5658* + ID_OUI_FROM_DATABASE=emperor brands + +OUI:70B3D5659* + ID_OUI_FROM_DATABASE=E2G srl + +OUI:70B3D565A* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D565B* + ID_OUI_FROM_DATABASE=Roush + +OUI:70B3D565C* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D565D* + ID_OUI_FROM_DATABASE=GEGA ELECTRONIQUE + +OUI:70B3D565E* + ID_OUI_FROM_DATABASE=Season Electronics Ltd + +OUI:70B3D565F* + ID_OUI_FROM_DATABASE=Axnes AS + +OUI:70B3D5660* + ID_OUI_FROM_DATABASE=Smart Service Technologies CO., LTD + +OUI:70B3D5661* + ID_OUI_FROM_DATABASE=DesignA Electronics Limited + +OUI:70B3D5662* + ID_OUI_FROM_DATABASE=Icon Industrial Engineering + +OUI:70B3D5664* + ID_OUI_FROM_DATABASE=Sankyo Intec co.,ltd + +OUI:70B3D5665* + ID_OUI_FROM_DATABASE=CertUsus GmbH + +OUI:70B3D5666* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5667* + ID_OUI_FROM_DATABASE=CT Company + +OUI:70B3D5669* + ID_OUI_FROM_DATABASE=Pano0ramic Power + +OUI:70B3D566A* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D566B* + ID_OUI_FROM_DATABASE=Innitive B.V. + +OUI:70B3D566C* + ID_OUI_FROM_DATABASE=KRISTECH Krzysztof Kajstura + +OUI:70B3D566D* + ID_OUI_FROM_DATABASE=Sanmina Israel + +OUI:70B3D5670* + ID_OUI_FROM_DATABASE=Particle sizing systems + +OUI:70B3D5671* + ID_OUI_FROM_DATABASE=Sea Shell Corporation + +OUI:70B3D5672* + ID_OUI_FROM_DATABASE=KLEIBER Infrared GmbH + +OUI:70B3D5673* + ID_OUI_FROM_DATABASE=ACD Elekronik GmbH + +OUI:70B3D5674* + ID_OUI_FROM_DATABASE=Fortress Cyber Security + +OUI:70B3D5675* + ID_OUI_FROM_DATABASE=alfamation spa + +OUI:70B3D5676* + ID_OUI_FROM_DATABASE=samwooeleco + +OUI:70B3D5677* + ID_OUI_FROM_DATABASE=Fraunhofer-Institut IIS + +OUI:70B3D5678* + ID_OUI_FROM_DATABASE=The Dini Group, La Jolla inc. + +OUI:70B3D5679* + ID_OUI_FROM_DATABASE=EMAC, Inc. + +OUI:70B3D567A* + ID_OUI_FROM_DATABASE=Micatu + +OUI:70B3D567B* + ID_OUI_FROM_DATABASE=Stesalit Systems Ltd + +OUI:70B3D567D* + ID_OUI_FROM_DATABASE=Acrodea, Inc. + +OUI:70B3D567E* + ID_OUI_FROM_DATABASE=Season Electronics Ltd + +OUI:70B3D567F* + ID_OUI_FROM_DATABASE=IAAN Co., Ltd + +OUI:70B3D5680* + ID_OUI_FROM_DATABASE=BASF Corporation + +OUI:70B3D5682* + ID_OUI_FROM_DATABASE=Rosslare Enterprises Limited + +OUI:70B3D5684* + ID_OUI_FROM_DATABASE=LECO Corporation + +OUI:70B3D5686* + ID_OUI_FROM_DATABASE=Access Protocol Pty Ltd + +OUI:70B3D5688* + ID_OUI_FROM_DATABASE=MG s.r.l. + +OUI:70B3D5689* + ID_OUI_FROM_DATABASE=Prisma Telecom Testing Srl + +OUI:70B3D568B* + ID_OUI_FROM_DATABASE=Sadel S.p.A. + +OUI:70B3D568C* + ID_OUI_FROM_DATABASE=ND METER + +OUI:70B3D568D* + ID_OUI_FROM_DATABASE=Meta-chrom Co. Ltd. + +OUI:70B3D568E* + ID_OUI_FROM_DATABASE=CEA Technologies Pty Ltd + +OUI:70B3D568F* + ID_OUI_FROM_DATABASE=PEEK TRAFFIC + +OUI:70B3D5691* + ID_OUI_FROM_DATABASE=PEEK TRAFFIC + +OUI:70B3D5692* + ID_OUI_FROM_DATABASE=HOSIN INDUSTRIAL LIMITED + +OUI:70B3D5693* + ID_OUI_FROM_DATABASE=Altron, a.s. + +OUI:70B3D5694* + ID_OUI_FROM_DATABASE=MoviTHERM + +OUI:70B3D5695* + ID_OUI_FROM_DATABASE=GSP Sprachtechnologie GmbH + +OUI:70B3D5696* + ID_OUI_FROM_DATABASE=Open Grow + +OUI:70B3D5697* + ID_OUI_FROM_DATABASE=Alazar Technologies Inc. + +OUI:70B3D5699* + ID_OUI_FROM_DATABASE=Flextronics International Kft + +OUI:70B3D569A* + ID_OUI_FROM_DATABASE=Altaneos + +OUI:70B3D569B* + ID_OUI_FROM_DATABASE=TAIYO SEIKI CO.,LTD. + +OUI:70B3D569C* + ID_OUI_FROM_DATABASE=Keepen + +OUI:70B3D569E* + ID_OUI_FROM_DATABASE=PTYPE Co., LTD. + +OUI:70B3D569F* + ID_OUI_FROM_DATABASE=T+A elektroakustik GmbH & Co.KG + +OUI:70B3D56A0* + ID_OUI_FROM_DATABASE=Active Research Limited + +OUI:70B3D56A1* + ID_OUI_FROM_DATABASE=GLIAL TECHNOLOGY + +OUI:70B3D56A2* + ID_OUI_FROM_DATABASE=Root Automation + +OUI:70B3D56A3* + ID_OUI_FROM_DATABASE=OutdoorLink + +OUI:70B3D56A4* + ID_OUI_FROM_DATABASE=Acrodea, Inc. + +OUI:70B3D56A5* + ID_OUI_FROM_DATABASE=Akenori PTE LTD + +OUI:70B3D56A6* + ID_OUI_FROM_DATABASE=WOW System + +OUI:70B3D56A8* + ID_OUI_FROM_DATABASE=Vitsch Electronics + +OUI:70B3D56A9* + ID_OUI_FROM_DATABASE=OHMORI ELECTRIC INDUSTRIES CO.LTD + +OUI:70B3D56AB* + ID_OUI_FROM_DATABASE=ARROW (CHINA) ELECTRONICS TRADING CO., LTD. + +OUI:70B3D56AD* + ID_OUI_FROM_DATABASE=CONNIT + +OUI:70B3D56AE* + ID_OUI_FROM_DATABASE=Hangzhou Weimu Technology Co,.Ltd. + +OUI:70B3D56AF* + ID_OUI_FROM_DATABASE=Sensorberg GmbH + +OUI:70B3D56B0* + ID_OUI_FROM_DATABASE=PTYPE Co., LTD. + +OUI:70B3D56B1* + ID_OUI_FROM_DATABASE=TTC TELEKOMUNIKACE, s.r.o. + +OUI:70B3D56B2* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D56B3* + ID_OUI_FROM_DATABASE=DuraComm Corporation + +OUI:70B3D56B5* + ID_OUI_FROM_DATABASE=ART SPA + +OUI:70B3D56B6* + ID_OUI_FROM_DATABASE=INRADIOS GmbH + +OUI:70B3D56B7* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D56B8* + ID_OUI_FROM_DATABASE=BT9 + +OUI:70B3D56B9* + ID_OUI_FROM_DATABASE=Becton Dickinson + +OUI:70B3D56BA* + ID_OUI_FROM_DATABASE=Integrotech sp. z o.o. + +OUI:70B3D56BB* + ID_OUI_FROM_DATABASE=LUCEO + +OUI:70B3D56BC* + ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG + +OUI:70B3D56BD* + ID_OUI_FROM_DATABASE=RCH Vietnam Limited Liability Company + +OUI:70B3D56BE* + ID_OUI_FROM_DATABASE=VANTAGE INTEGRATED SECURITY SOLUTIONS PVT LTD + +OUI:70B3D56BF* + ID_OUI_FROM_DATABASE=Otto Bihler Maschinenfabrik GmbH & Co. KG + +OUI:70B3D56C1* + ID_OUI_FROM_DATABASE=Labtronik s.r.l. + +OUI:70B3D56C2* + ID_OUI_FROM_DATABASE=TEX COMPUTER SRL + +OUI:70B3D56C3* + ID_OUI_FROM_DATABASE=BEIJING ZGH SECURITY RESEARCH INSTITUTE CO., LTD + +OUI:70B3D56C5* + ID_OUI_FROM_DATABASE=CJSC «Russian telecom equipment company» (CJSC RTEC) + +OUI:70B3D56C6* + ID_OUI_FROM_DATABASE=Abbott Diagnostics Technologies AS + +OUI:70B3D56C7* + ID_OUI_FROM_DATABASE=Becton Dickinson + +OUI:70B3D56CA* + ID_OUI_FROM_DATABASE=LINEAGE POWER PVT LTD., + +OUI:70B3D56CB* + ID_OUI_FROM_DATABASE=NAJIN automation + +OUI:70B3D56CD* + ID_OUI_FROM_DATABASE=NORTHBOUND NETWORKS PTY. LTD. + +OUI:70B3D56CE* + ID_OUI_FROM_DATABASE=Eredi Giuseppe Mercuri SPA + +OUI:70B3D56CF* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D56D0* + ID_OUI_FROM_DATABASE=Code Blue Corporation + +OUI:70B3D56D1* + ID_OUI_FROM_DATABASE=Visual Engineering Technologies Ltd + +OUI:70B3D56D2* + ID_OUI_FROM_DATABASE=Ahrens & Birner Company GmbH + +OUI:70B3D56D3* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D56D6* + ID_OUI_FROM_DATABASE=KMtronic Ltd. + +OUI:70B3D56D8* + ID_OUI_FROM_DATABASE=Shanghai YuanAn Environmental Protection Technology Co.,Ltd + +OUI:70B3D56D9* + ID_OUI_FROM_DATABASE=VECTARE Inc + +OUI:70B3D56DA* + ID_OUI_FROM_DATABASE=Enovative Networks, Inc. + +OUI:70B3D56DD* + ID_OUI_FROM_DATABASE=Abbott Diagnostics Technologies AS + +OUI:70B3D56DE* + ID_OUI_FROM_DATABASE=Ametek Solidstate Controls + +OUI:70B3D56DF* + ID_OUI_FROM_DATABASE=Mango DSP, Inc. + +OUI:70B3D56E0* + ID_OUI_FROM_DATABASE=ABB SPA - DMPC + +OUI:70B3D56E1* + ID_OUI_FROM_DATABASE=Shanghai Holystar Information Technology Co.,Ltd + +OUI:70B3D56E3* + ID_OUI_FROM_DATABASE=SHEN ZHEN QLS ELECTRONIC TECHNOLOGY CO.,LTD. + +OUI:70B3D56E4* + ID_OUI_FROM_DATABASE=Institute of Power Engineering, Gdansk Division + +OUI:70B3D56E5* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D56E6* + ID_OUI_FROM_DATABASE=Eleven Engineering Incorporated + +OUI:70B3D56E7* + ID_OUI_FROM_DATABASE=AML + +OUI:70B3D56E8* + ID_OUI_FROM_DATABASE=Blu Wireless Technology Ltd + +OUI:70B3D56E9* + ID_OUI_FROM_DATABASE=Krontech + +OUI:70B3D56EA* + ID_OUI_FROM_DATABASE=Edgeware AB + +OUI:70B3D56EB* + ID_OUI_FROM_DATABASE=QUANTAFLOW + +OUI:70B3D56EC* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D56ED* + ID_OUI_FROM_DATABASE=Wiingtech International Co. LTD. + +OUI:70B3D56EE* + ID_OUI_FROM_DATABASE=HANKOOK CTEC CO,. LTD. + +OUI:70B3D56F0* + ID_OUI_FROM_DATABASE=iTelaSoft Pvt Ltd + +OUI:70B3D56F1* + ID_OUI_FROM_DATABASE=Discover Battery + +OUI:70B3D56F2* + ID_OUI_FROM_DATABASE=P&C Micro's Pty Ltd + +OUI:70B3D56F3* + ID_OUI_FROM_DATABASE=iungo + +OUI:70B3D56F4* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D56F6* + ID_OUI_FROM_DATABASE=Acco Brands Europe + +OUI:70B3D56F7* + ID_OUI_FROM_DATABASE=EGICON SRL + +OUI:70B3D56F8* + ID_OUI_FROM_DATABASE=SENSEON Corporation + +OUI:70B3D56F9* + ID_OUI_FROM_DATABASE=ENVItech s.r.o. + +OUI:70B3D56FA* + ID_OUI_FROM_DATABASE=Dataforth Corporation + +OUI:70B3D56FB* + ID_OUI_FROM_DATABASE=Shachihata Inc. + +OUI:70B3D56FC* + ID_OUI_FROM_DATABASE=MI Inc. + +OUI:70B3D56FD* + ID_OUI_FROM_DATABASE=Core Akıllı Ev Sistemleri + +OUI:70B3D56FE* + ID_OUI_FROM_DATABASE=NTO IRE-POLUS + +OUI:70B3D56FF* + ID_OUI_FROM_DATABASE=AKEO PLUS + +OUI:70B3D5700* + ID_OUI_FROM_DATABASE=University Of Groningen + +OUI:70B3D5701* + ID_OUI_FROM_DATABASE=COMPAR Computer GmbH + +OUI:70B3D5702* + ID_OUI_FROM_DATABASE=Sensor Highway Ltd + +OUI:70B3D5703* + ID_OUI_FROM_DATABASE=StromIdee GmbH + +OUI:70B3D5704* + ID_OUI_FROM_DATABASE=Melecs EWS GmbH + +OUI:70B3D5705* + ID_OUI_FROM_DATABASE=Digital Matter Pty Ltd + +OUI:70B3D5706* + ID_OUI_FROM_DATABASE=Smith Meter, Inc. + +OUI:70B3D5707* + ID_OUI_FROM_DATABASE=Koco Motion US LLC + +OUI:70B3D5708* + ID_OUI_FROM_DATABASE=IBM Research GmbH + +OUI:70B3D5709* + ID_OUI_FROM_DATABASE=AML + +OUI:70B3D570A* + ID_OUI_FROM_DATABASE=PULLNET TECHNOLOGY, SA DE CV SSC1012302S73 + +OUI:70B3D570B* + ID_OUI_FROM_DATABASE=Alere Technologies AS + +OUI:70B3D570E* + ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd + +OUI:70B3D570F* + ID_OUI_FROM_DATABASE=Alion Science & Technology + +OUI:70B3D5710* + ID_OUI_FROM_DATABASE=Guardian Controls International Ltd + +OUI:70B3D5711* + ID_OUI_FROM_DATABASE=X-Laser LLC + +OUI:70B3D5712* + ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC + +OUI:70B3D5714* + ID_OUI_FROM_DATABASE=Alturna Networks + +OUI:70B3D5715* + ID_OUI_FROM_DATABASE=RIOT + +OUI:70B3D5716* + ID_OUI_FROM_DATABASE=Lode BV + +OUI:70B3D5717* + ID_OUI_FROM_DATABASE=Secure Systems & Services + +OUI:70B3D5718* + ID_OUI_FROM_DATABASE=PEEK TRAFFIC + +OUI:70B3D5719* + ID_OUI_FROM_DATABASE=2M Technology + +OUI:70B3D571B* + ID_OUI_FROM_DATABASE=elsys + +OUI:70B3D571E* + ID_OUI_FROM_DATABASE=Motec Pty Ltd + +OUI:70B3D5720* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5721* + ID_OUI_FROM_DATABASE=Zoe Medical + +OUI:70B3D5722* + ID_OUI_FROM_DATABASE=UMAN + +OUI:70B3D5723* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:70B3D5724* + ID_OUI_FROM_DATABASE=Quan International Co., Ltd. + +OUI:70B3D5726* + ID_OUI_FROM_DATABASE=ATGS + +OUI:70B3D5727* + ID_OUI_FROM_DATABASE=LP Technologies Inc. + +OUI:70B3D5728* + ID_OUI_FROM_DATABASE=BCD Audio + +OUI:70B3D5729* + ID_OUI_FROM_DATABASE=EMAC, Inc. + +OUI:70B3D572A* + ID_OUI_FROM_DATABASE=MRC Systems GmbH + +OUI:70B3D572C* + ID_OUI_FROM_DATABASE=NuRi&G Engineering co,.Ltd. + +OUI:70B3D572D* + ID_OUI_FROM_DATABASE=Kron Medidores + +OUI:70B3D572E* + ID_OUI_FROM_DATABASE=Maharsystem + +OUI:70B3D572F* + ID_OUI_FROM_DATABASE=AVA Technologies Inc. + +OUI:70B3D5730* + ID_OUI_FROM_DATABASE=Videogenix + +OUI:70B3D5731* + ID_OUI_FROM_DATABASE=Phoniro Systems AB + +OUI:70B3D5732* + ID_OUI_FROM_DATABASE=TOFWERK AG + +OUI:70B3D5733* + ID_OUI_FROM_DATABASE=SA Instrumentation Limited + +OUI:70B3D5734* + ID_OUI_FROM_DATABASE=MANSION INDUSTRY CO., LTD. + +OUI:70B3D5735* + ID_OUI_FROM_DATABASE=Swiss Audio + +OUI:70B3D5737* + ID_OUI_FROM_DATABASE=SD Biosensor + +OUI:70B3D5738* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5739* + ID_OUI_FROM_DATABASE=Zigencorp, Inc + +OUI:70B3D573A* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D573B* + ID_OUI_FROM_DATABASE=S-I-C + +OUI:70B3D573C* + ID_OUI_FROM_DATABASE=Centro de Ingenieria y Desarrollo industrial + +OUI:70B3D573D* + ID_OUI_FROM_DATABASE=NETWAYS GmbH + +OUI:70B3D573E* + ID_OUI_FROM_DATABASE=Trident RFID Pty Ltd + +OUI:70B3D5740* + ID_OUI_FROM_DATABASE=Prisma Telecom Testing Srl + +OUI:70B3D5741* + ID_OUI_FROM_DATABASE=HOW-E + +OUI:70B3D5742* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D5743* + ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG + +OUI:70B3D5745* + ID_OUI_FROM_DATABASE=TMSI LLC + +OUI:70B3D5747* + ID_OUI_FROM_DATABASE=Eva Automation + +OUI:70B3D5748* + ID_OUI_FROM_DATABASE=KDT + +OUI:70B3D5749* + ID_OUI_FROM_DATABASE=Granite River Labs Inc + +OUI:70B3D574A* + ID_OUI_FROM_DATABASE=Mettler Toledo + +OUI:70B3D574B* + ID_OUI_FROM_DATABASE=Code Blue Corporation + +OUI:70B3D574C* + ID_OUI_FROM_DATABASE=Kwant Controls BV + +OUI:70B3D574D* + ID_OUI_FROM_DATABASE=SPEECH TECHNOLOGY CENTER LIMITED + +OUI:70B3D574E* + ID_OUI_FROM_DATABASE=PushCorp, Inc. + +OUI:70B3D574F* + ID_OUI_FROM_DATABASE=United States Technologies Inc. + +OUI:70B3D5750* + ID_OUI_FROM_DATABASE=Neurio Technology Inc. + +OUI:70B3D5751* + ID_OUI_FROM_DATABASE=GNF + +OUI:70B3D5752* + ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd. + +OUI:70B3D5753* + ID_OUI_FROM_DATABASE=HCH. Kündig & CIE. AG + +OUI:70B3D5754* + ID_OUI_FROM_DATABASE=COSMOIT.CO.LTD + +OUI:70B3D5755* + ID_OUI_FROM_DATABASE=LandmarkTech Systems Technology Co.,Ltd. + +OUI:70B3D5757* + ID_OUI_FROM_DATABASE=GABO + +OUI:70B3D5758* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D5759* + ID_OUI_FROM_DATABASE=AML + +OUI:70B3D575A* + ID_OUI_FROM_DATABASE=Standard Backhaul Communications + +OUI:70B3D575B* + ID_OUI_FROM_DATABASE=Netool LLC + +OUI:70B3D575C* + ID_OUI_FROM_DATABASE=UPM Technology, Inc + +OUI:70B3D575D* + ID_OUI_FROM_DATABASE=Nanjing Magewell Electronics Co., Ltd. + +OUI:70B3D575E* + ID_OUI_FROM_DATABASE=Cardinal Health + +OUI:70B3D575F* + ID_OUI_FROM_DATABASE=Vocality international T/A Cubic + +OUI:70B3D5760* + ID_OUI_FROM_DATABASE=QUALITTEQ LLC + +OUI:70B3D5761* + ID_OUI_FROM_DATABASE=Critical Link LLC + +OUI:70B3D5763* + ID_OUI_FROM_DATABASE=A Trap, USA + +OUI:70B3D5764* + ID_OUI_FROM_DATABASE=SCHMID electronic + +OUI:70B3D5765* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:70B3D5766* + ID_OUI_FROM_DATABASE=Tirasoft Nederland + +OUI:70B3D5767* + ID_OUI_FROM_DATABASE=FRANKLIN FRANCE + +OUI:70B3D5768* + ID_OUI_FROM_DATABASE=Kazan Networks Corporation + +OUI:70B3D576A* + ID_OUI_FROM_DATABASE=Swiftnet SOC Ltd + +OUI:70B3D576B* + ID_OUI_FROM_DATABASE=EMPELOR GmbH + +OUI:70B3D576C* + ID_OUI_FROM_DATABASE=Aural Ltd + +OUI:70B3D576D* + ID_OUI_FROM_DATABASE=Trimble + +OUI:70B3D576E* + ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. + +OUI:70B3D576F* + ID_OUI_FROM_DATABASE=OTI LTD + +OUI:70B3D5770* + ID_OUI_FROM_DATABASE=STREGA + +OUI:70B3D5771* + ID_OUI_FROM_DATABASE=Apator Miitors ApS + +OUI:70B3D5772* + ID_OUI_FROM_DATABASE=enModus + +OUI:70B3D5773* + ID_OUI_FROM_DATABASE=Rugged Science + +OUI:70B3D5774* + ID_OUI_FROM_DATABASE=Micram Instruments Ltd + +OUI:70B3D5775* + ID_OUI_FROM_DATABASE=Sonel S.A. + +OUI:70B3D5776* + ID_OUI_FROM_DATABASE=Power Ltd. + +OUI:70B3D5777* + ID_OUI_FROM_DATABASE=QUERCUS TECHNOLOGIES, S.L. + +OUI:70B3D5778* + ID_OUI_FROM_DATABASE=Lumacron Technology Ltd. + +OUI:70B3D5779* + ID_OUI_FROM_DATABASE=DR.BRIDGE AQUATECH + +OUI:70B3D577A* + ID_OUI_FROM_DATABASE=Tecsag Innovation AG + +OUI:70B3D577B* + ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc. + +OUI:70B3D577C* + ID_OUI_FROM_DATABASE=HUSTY M.Styczen J.Hupert Sp.J. + +OUI:70B3D577D* + ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC + +OUI:70B3D577E* + ID_OUI_FROM_DATABASE=Blue Marble Communications, Inc. + +OUI:70B3D577F* + ID_OUI_FROM_DATABASE=Microchip Technology Germany II GmbH&Co.KG + +OUI:70B3D5780* + ID_OUI_FROM_DATABASE=NIDEC LEROY-SOMER + +OUI:70B3D5781* + ID_OUI_FROM_DATABASE=Project Service S.a.s. + +OUI:70B3D5782* + ID_OUI_FROM_DATABASE=thou&tech + +OUI:70B3D5783* + ID_OUI_FROM_DATABASE=CHIeru., CO., Ltd. + +OUI:70B3D5784* + ID_OUI_FROM_DATABASE=Shenzhen bayue software co. LTD + +OUI:70B3D5785* + ID_OUI_FROM_DATABASE=Density Inc. + +OUI:70B3D5786* + ID_OUI_FROM_DATABASE=RCH Vietnam Limited Liability Company + +OUI:70B3D5787* + ID_OUI_FROM_DATABASE=Den Automation + +OUI:70B3D5788* + ID_OUI_FROM_DATABASE=Slan + +OUI:70B3D5789* + ID_OUI_FROM_DATABASE=SEMEX-EngCon GmbH + +OUI:70B3D578A* + ID_OUI_FROM_DATABASE=Hills Health Solutions + +OUI:70B3D578B* + ID_OUI_FROM_DATABASE=Jingtu Printing Systems Co., Ltd + +OUI:70B3D578C* + ID_OUI_FROM_DATABASE=Survalent Technology Corporation + +OUI:70B3D578E* + ID_OUI_FROM_DATABASE=effectas GmbH + +OUI:70B3D578F* + ID_OUI_FROM_DATABASE=SoFiHa + +OUI:70B3D5790* + ID_OUI_FROM_DATABASE=AVI Pty Ltd + +OUI:70B3D5791* + ID_OUI_FROM_DATABASE=Romteck Australia + +OUI:70B3D5793* + ID_OUI_FROM_DATABASE=Gastech Australia Pty Ltd + +OUI:70B3D5794* + ID_OUI_FROM_DATABASE=Shadin Avionics + +OUI:70B3D5795* + ID_OUI_FROM_DATABASE=TIECHE Engineered Systems + +OUI:70B3D5796* + ID_OUI_FROM_DATABASE=GAMPT mbH + +OUI:70B3D5797* + ID_OUI_FROM_DATABASE=Mitsubishi Electric India Pvt. Ltd. + +OUI:70B3D5799* + ID_OUI_FROM_DATABASE=Vitec System Engineering Inc. + +OUI:70B3D579A* + ID_OUI_FROM_DATABASE=Innerspec Technologies Inc. + +OUI:70B3D579B* + ID_OUI_FROM_DATABASE=Soniclean Pty Ltd + +OUI:70B3D579D* + ID_OUI_FROM_DATABASE=Editech Co., Ltd + +OUI:70B3D579E* + ID_OUI_FROM_DATABASE=CW2. Gmbh & Co. KG + +OUI:70B3D579F* + ID_OUI_FROM_DATABASE=Green Instruments A/S + +OUI:70B3D57A0* + ID_OUI_FROM_DATABASE=Reactec Ltd + +OUI:70B3D57A1* + ID_OUI_FROM_DATABASE=Excelfore Corporation + +OUI:70B3D57A2* + ID_OUI_FROM_DATABASE=Alpha ESS Co., Ltd. + +OUI:70B3D57A3* + ID_OUI_FROM_DATABASE=Impulse Automation + +OUI:70B3D57A4* + ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC + +OUI:70B3D57A5* + ID_OUI_FROM_DATABASE=Triton Electronics Ltd + +OUI:70B3D57A6* + ID_OUI_FROM_DATABASE=Electrolux + +OUI:70B3D57A7* + ID_OUI_FROM_DATABASE=Symbicon Ltd + +OUI:70B3D57A8* + ID_OUI_FROM_DATABASE=dieEntwickler Elektronik GmbH + +OUI:70B3D57A9* + ID_OUI_FROM_DATABASE=adidas AG + +OUI:70B3D57AA* + ID_OUI_FROM_DATABASE=Sadel S.p.A. + +OUI:70B3D57AB* + ID_OUI_FROM_DATABASE=Microgate Srl + +OUI:70B3D57AC* + ID_OUI_FROM_DATABASE=Verity Studios AG + +OUI:70B3D57AD* + ID_OUI_FROM_DATABASE=Insitu, Inc + +OUI:70B3D57AE* + ID_OUI_FROM_DATABASE=Exi Flow Measurement Ltd + +OUI:70B3D57AF* + ID_OUI_FROM_DATABASE=Hessware GmbH + +OUI:70B3D57B0* + ID_OUI_FROM_DATABASE=Medisafe International + +OUI:70B3D57B2* + ID_OUI_FROM_DATABASE=Rail Power Systems GmbH + +OUI:70B3D57B3* + ID_OUI_FROM_DATABASE=BroadSoft Inc + +OUI:70B3D57B4* + ID_OUI_FROM_DATABASE=Zumbach Electronic AG + +OUI:70B3D57B6* + ID_OUI_FROM_DATABASE=Amada Miyachi America Inc. + +OUI:70B3D57B7* + ID_OUI_FROM_DATABASE=LSB - LA SALLE BLANCHE + +OUI:70B3D57B8* + ID_OUI_FROM_DATABASE=SerEnergy A/S + +OUI:70B3D57B9* + ID_OUI_FROM_DATABASE=QIAGEN Instruments AG + +OUI:70B3D57BA* + ID_OUI_FROM_DATABASE=Decentlab GmbH + +OUI:70B3D57BB* + ID_OUI_FROM_DATABASE=Aloxy + +OUI:70B3D57BC* + ID_OUI_FROM_DATABASE=FIRST RF Corporation + +OUI:70B3D57BE* + ID_OUI_FROM_DATABASE=Phytron GmbH + +OUI:70B3D57BF* + ID_OUI_FROM_DATABASE=Stone Three + +OUI:70B3D57C0* + ID_OUI_FROM_DATABASE=TORGOVYY DOM TEHNOLOGIY LLC + +OUI:70B3D57C1* + ID_OUI_FROM_DATABASE=Data Sciences International + +OUI:70B3D57C2* + ID_OUI_FROM_DATABASE=Morgan Schaffer Inc. + +OUI:70B3D57C3* + ID_OUI_FROM_DATABASE=Flexim Security Oy + +OUI:70B3D57C4* + ID_OUI_FROM_DATABASE=MECT SRL + +OUI:70B3D57C6* + ID_OUI_FROM_DATABASE=Utrend Technology (Shanghai) Co., Ltd + +OUI:70B3D57C7* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D57C8* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D57C9* + ID_OUI_FROM_DATABASE=Council Rock + +OUI:70B3D57CA* + ID_OUI_FROM_DATABASE=Hunan Shengyun Photoelectric Technology Co., Ltd. + +OUI:70B3D57CB* + ID_OUI_FROM_DATABASE=KeyW Corporation + +OUI:70B3D57CD* + ID_OUI_FROM_DATABASE=Molekuler Goruntuleme A.S. + +OUI:70B3D57CE* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D57CF* + ID_OUI_FROM_DATABASE=ORCA Technologies, LLC + +OUI:70B3D57D0* + ID_OUI_FROM_DATABASE=Cubitech + +OUI:70B3D57D1* + ID_OUI_FROM_DATABASE=Schneider Electric Motion USA + +OUI:70B3D57D2* + ID_OUI_FROM_DATABASE=SDK Kristall + +OUI:70B3D57D5* + ID_OUI_FROM_DATABASE=SICS Swedish ICT + +OUI:70B3D57D6* + ID_OUI_FROM_DATABASE=Yukilab + +OUI:70B3D57D7* + ID_OUI_FROM_DATABASE=Gedomo GmbH + +OUI:70B3D57D9* + ID_OUI_FROM_DATABASE=ATOM GIKEN Co.,Ltd. + +OUI:70B3D57DA* + ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. + +OUI:70B3D57DB* + ID_OUI_FROM_DATABASE=aquila biolabs GmbH + +OUI:70B3D57DC* + ID_OUI_FROM_DATABASE=Software Systems Plus + +OUI:70B3D57DD* + ID_OUI_FROM_DATABASE=Excel Medical Electronics LLC + +OUI:70B3D57DE* + ID_OUI_FROM_DATABASE=Telaeris, Inc. + +OUI:70B3D57DF* + ID_OUI_FROM_DATABASE=RDT Ltd + +OUI:70B3D57E0* + ID_OUI_FROM_DATABASE=Sanko-sha,inc. + +OUI:70B3D57E1* + ID_OUI_FROM_DATABASE=Applied Materials + +OUI:70B3D57E2* + ID_OUI_FROM_DATABASE=Depro Électronique inc + +OUI:70B3D57E3* + ID_OUI_FROM_DATABASE=RedLeaf Security + +OUI:70B3D57E4* + ID_OUI_FROM_DATABASE=C21 Systems Ltd + +OUI:70B3D57E5* + ID_OUI_FROM_DATABASE=Megaflex Oy + +OUI:70B3D57E7* + ID_OUI_FROM_DATABASE=Atessa, Inc. + +OUI:70B3D57E8* + ID_OUI_FROM_DATABASE=Mannkind Corporation + +OUI:70B3D57E9* + ID_OUI_FROM_DATABASE=Mecsel Oy + +OUI:70B3D57EA* + ID_OUI_FROM_DATABASE=Waterkotte GmbH + +OUI:70B3D57EB* + ID_OUI_FROM_DATABASE=Xerox International Partners + +OUI:70B3D57EC* + ID_OUI_FROM_DATABASE=GRIDSMART Technologies + +OUI:70B3D57ED* + ID_OUI_FROM_DATABASE=The Things Network Foundation + +OUI:70B3D57EE* + ID_OUI_FROM_DATABASE=ADVEEZ + +OUI:70B3D57EF* + ID_OUI_FROM_DATABASE=CRAVIS CO., LIMITED + +OUI:70B3D57F1* + ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc. + +OUI:70B3D57F2* + ID_OUI_FROM_DATABASE=TCI + +OUI:70B3D57F3* + ID_OUI_FROM_DATABASE=Shenzhen Virtual Clusters Information Technology Co.,Ltd. + +OUI:70B3D57F4* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D57F5* + ID_OUI_FROM_DATABASE=Incusense + +OUI:70B3D57F7* + ID_OUI_FROM_DATABASE=JASCO Applied Sciences Canada Ltd + +OUI:70B3D57F8* + ID_OUI_FROM_DATABASE=Solvera Lynx d.d. + +OUI:70B3D57F9* + ID_OUI_FROM_DATABASE=Communication Systems Solutions + +OUI:70B3D57FB* + ID_OUI_FROM_DATABASE=db Broadcast Products Ltd + +OUI:70B3D57FD* + ID_OUI_FROM_DATABASE=SYS TEC electronic GmbH + +OUI:70B3D57FE* + ID_OUI_FROM_DATABASE=RCH ITALIA SPA + +OUI:70B3D57FF* + ID_OUI_FROM_DATABASE=eumig industrie-TV GmbH. + +OUI:70B3D5800* + ID_OUI_FROM_DATABASE=HeadsafeIP PTY LTD + +OUI:70B3D5802* + ID_OUI_FROM_DATABASE=Qingdao CNR HITACH Railway Signal&communication co.,ltd + +OUI:70B3D5803* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D5804* + ID_OUI_FROM_DATABASE=PMT Corporation + +OUI:70B3D5805* + ID_OUI_FROM_DATABASE=Eurotronik Kranj d.o.o. + +OUI:70B3D5807* + ID_OUI_FROM_DATABASE=Camsat Przemysław Gralak + +OUI:70B3D5808* + ID_OUI_FROM_DATABASE=Becton Dickinson + +OUI:70B3D5809* + ID_OUI_FROM_DATABASE=Tecnint HTE SRL + +OUI:70B3D580A* + ID_OUI_FROM_DATABASE=SENSING LABS + +OUI:70B3D580B* + ID_OUI_FROM_DATABASE=Fischer Block, Inc. + +OUI:70B3D580D* + ID_OUI_FROM_DATABASE=Data Physics Corporation + +OUI:70B3D580F* + ID_OUI_FROM_DATABASE=Quickware Eng & Des LLC + +OUI:70B3D5810* + ID_OUI_FROM_DATABASE=Advice + +OUI:70B3D5811* + ID_OUI_FROM_DATABASE=CJSC «INTERSET» + +OUI:70B3D5813* + ID_OUI_FROM_DATABASE=Wavemed srl + +OUI:70B3D5814* + ID_OUI_FROM_DATABASE=Ingenieurbuero SOMTRONIK + +OUI:70B3D5815* + ID_OUI_FROM_DATABASE=Waco Giken Co., Ltd. + +OUI:70B3D5816* + ID_OUI_FROM_DATABASE=Smith Meter, Inc. + +OUI:70B3D5817* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5818* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5819* + ID_OUI_FROM_DATABASE=«Intellect module» LLC + +OUI:70B3D581A* + ID_OUI_FROM_DATABASE=Joehl & Koeferli AG + +OUI:70B3D581B* + ID_OUI_FROM_DATABASE=bobz GmbH + +OUI:70B3D581D* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D581E* + ID_OUI_FROM_DATABASE=Novathings + +OUI:70B3D5820* + ID_OUI_FROM_DATABASE=Becker Nachrichtentechnik GmbH + +OUI:70B3D5821* + ID_OUI_FROM_DATABASE=HL2 group + +OUI:70B3D5822* + ID_OUI_FROM_DATABASE=Angora Networks + +OUI:70B3D5823* + ID_OUI_FROM_DATABASE=SP Controls + +OUI:70B3D5824* + ID_OUI_FROM_DATABASE=Songwoo Information & Technology Co., Ltd + +OUI:70B3D5825* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5826* + ID_OUI_FROM_DATABASE=Elbit Systems of America + +OUI:70B3D5827* + ID_OUI_FROM_DATABASE=Metromatics Pty Ltd + +OUI:70B3D5828* + ID_OUI_FROM_DATABASE=Xacti Corporation + +OUI:70B3D582C* + ID_OUI_FROM_DATABASE=NELS Ltd. + +OUI:70B3D582D* + ID_OUI_FROM_DATABASE=Elektronik Art S.C. + +OUI:70B3D582E* + ID_OUI_FROM_DATABASE=PlayAlive A/S + +OUI:70B3D5830* + ID_OUI_FROM_DATABASE=Nordson Corporation + +OUI:70B3D5831* + ID_OUI_FROM_DATABASE=Arnouse Digital Devices Corp + +OUI:70B3D5832* + ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC + +OUI:70B3D5833* + ID_OUI_FROM_DATABASE=Alpiq InTec Management AG + +OUI:70B3D5834* + ID_OUI_FROM_DATABASE=NCE Network Consulting Engineering srl + +OUI:70B3D5835* + ID_OUI_FROM_DATABASE=CommBox P/L + +OUI:70B3D5836* + ID_OUI_FROM_DATABASE=Authenticdata + +OUI:70B3D5837* + ID_OUI_FROM_DATABASE=HiDes, Inc. + +OUI:70B3D5838* + ID_OUI_FROM_DATABASE=Tofino + +OUI:70B3D5839* + ID_OUI_FROM_DATABASE=Rockwell Collins Canada + +OUI:70B3D583A* + ID_OUI_FROM_DATABASE=EMDEP CENTRO TECNOLOGICO MEXICO + +OUI:70B3D583B* + ID_OUI_FROM_DATABASE=Telefonix Incorporated + +OUI:70B3D583C* + ID_OUI_FROM_DATABASE=Sinoembed + +OUI:70B3D583E* + ID_OUI_FROM_DATABASE=The Dini Group, La Jolla inc. + +OUI:70B3D583F* + ID_OUI_FROM_DATABASE=Lumine Lighting Solutions Oy + +OUI:70B3D5840* + ID_OUI_FROM_DATABASE=xm + +OUI:70B3D5841* + ID_OUI_FROM_DATABASE=Stanet Co.,Ltd + +OUI:70B3D5842* + ID_OUI_FROM_DATABASE=PLUTO Solution co.,ltd. + +OUI:70B3D5843* + ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies + +OUI:70B3D5844* + ID_OUI_FROM_DATABASE=SANSFIL Technologies + +OUI:70B3D5845* + ID_OUI_FROM_DATABASE=Harborside Technology + +OUI:70B3D5847* + ID_OUI_FROM_DATABASE=Ai-Lynx + +OUI:70B3D5848* + ID_OUI_FROM_DATABASE=Aldridge Electrical Industries + +OUI:70B3D5849* + ID_OUI_FROM_DATABASE=RF-Tuote Oy + +OUI:70B3D584A* + ID_OUI_FROM_DATABASE=MOG Laboratories Pty Ltd + +OUI:70B3D584B* + ID_OUI_FROM_DATABASE=QuestHouse, Inc. + +OUI:70B3D584C* + ID_OUI_FROM_DATABASE=CoreKinect + +OUI:70B3D584D* + ID_OUI_FROM_DATABASE=Quantum Design Inc. + +OUI:70B3D584E* + ID_OUI_FROM_DATABASE=Chromalox, Inc. + +OUI:70B3D584F* + ID_OUI_FROM_DATABASE=Mettler Toledo + +OUI:70B3D5850* + ID_OUI_FROM_DATABASE=REO AG + +OUI:70B3D5851* + ID_OUI_FROM_DATABASE=EXASCEND (Wuhan) Co., Ltd + +OUI:70B3D5852* + ID_OUI_FROM_DATABASE=NetBoxSC, LLC + +OUI:70B3D5853* + ID_OUI_FROM_DATABASE=HGH SYSTEMES INFRAROUGES + +OUI:70B3D5854* + ID_OUI_FROM_DATABASE=Adimec Advanced Image Systems + +OUI:70B3D5855* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5857* + ID_OUI_FROM_DATABASE=RCH ITALIA SPA + +OUI:70B3D5858* + ID_OUI_FROM_DATABASE=Hubbell Power Systems + +OUI:70B3D585A* + ID_OUI_FROM_DATABASE=BRUSHIES + +OUI:70B3D585B* + ID_OUI_FROM_DATABASE=TSUBAKIMOTO CHAIN CO. + +OUI:70B3D585C* + ID_OUI_FROM_DATABASE=Robot Pub Group + +OUI:70B3D585D* + ID_OUI_FROM_DATABASE=ATHREYA INC + +OUI:70B3D585E* + ID_OUI_FROM_DATABASE=XLOGIC srl + +OUI:70B3D585F* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D5860* + ID_OUI_FROM_DATABASE=KBS Industrieelektronik GmbH + +OUI:70B3D5861* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D5862* + ID_OUI_FROM_DATABASE=TripleOre + +OUI:70B3D5863* + ID_OUI_FROM_DATABASE=Shenzhen Wesion Technology Co., Ltd + +OUI:70B3D5865* + ID_OUI_FROM_DATABASE=Insitu, Inc. + +OUI:70B3D5866* + ID_OUI_FROM_DATABASE=MEPS Realtime + +OUI:70B3D5868* + ID_OUI_FROM_DATABASE=U-JIN Mesco Co., Ltd. + +OUI:70B3D5869* + ID_OUI_FROM_DATABASE=chargeBIG + +OUI:70B3D586A* + ID_OUI_FROM_DATABASE=Stealth Communications + +OUI:70B3D586B* + ID_OUI_FROM_DATABASE=AVL DiTEST + +OUI:70B3D586C* + ID_OUI_FROM_DATABASE=eeas gmbh + +OUI:70B3D586D* + ID_OUI_FROM_DATABASE=Census Digital Incorporated + +OUI:70B3D586E* + ID_OUI_FROM_DATABASE=Profcon AB + +OUI:70B3D586F* + ID_OUI_FROM_DATABASE=LLC NTC ACTOR + +OUI:70B3D5870* + ID_OUI_FROM_DATABASE=bentrup Industriesteuerungen + +OUI:70B3D5871* + ID_OUI_FROM_DATABASE=Oso Technologies + +OUI:70B3D5873* + ID_OUI_FROM_DATABASE=Vishay Nobel AB + +OUI:70B3D5874* + ID_OUI_FROM_DATABASE=NORTHBOUND NETWORKS PTY. LTD. + +OUI:70B3D5875* + ID_OUI_FROM_DATABASE=Peek Traffic + +OUI:70B3D5876* + ID_OUI_FROM_DATABASE=IONETECH + +OUI:70B3D5877* + ID_OUI_FROM_DATABASE=Polynet Telecommunications Consulting and Contractor Ltd. + +OUI:70B3D5878* + ID_OUI_FROM_DATABASE=Package Guard, Inc + +OUI:70B3D5879* + ID_OUI_FROM_DATABASE=ZIGPOS GmbH + +OUI:70B3D587B* + ID_OUI_FROM_DATABASE=Liquid Instruments Pty Ltd + +OUI:70B3D587C* + ID_OUI_FROM_DATABASE=Nautel Limited + +OUI:70B3D587D* + ID_OUI_FROM_DATABASE=INVIXIUM ACCESS INC. + +OUI:70B3D587E* + ID_OUI_FROM_DATABASE=Septentrio NV + +OUI:70B3D587F* + ID_OUI_FROM_DATABASE=NAC Planning Co., Ltd. + +OUI:70B3D5880* + ID_OUI_FROM_DATABASE=Skopei B.V. + +OUI:70B3D5881* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5882* + ID_OUI_FROM_DATABASE=SIMON TECH, S.L. + +OUI:70B3D5884* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:70B3D5885* + ID_OUI_FROM_DATABASE=QuirkLogic + +OUI:70B3D5888* + ID_OUI_FROM_DATABASE=Zetechtics Ltd + +OUI:70B3D5889* + ID_OUI_FROM_DATABASE=Innovative Circuit Technology + +OUI:70B3D588A* + ID_OUI_FROM_DATABASE=Perceptics, LLC + +OUI:70B3D588B* + ID_OUI_FROM_DATABASE=WUHAN EASYLINKIN TECHNOLOGY co.,LTD + +OUI:70B3D588D* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:70B3D588E* + ID_OUI_FROM_DATABASE=RCH Vietnam Limited Liability Company + +OUI:70B3D588F* + ID_OUI_FROM_DATABASE=Quaesta Instruments, LLC + +OUI:70B3D5890* + ID_OUI_FROM_DATABASE=EIDOS s.r.l. + +OUI:70B3D5891* + ID_OUI_FROM_DATABASE=neocontrol soluções em automação + +OUI:70B3D5892* + ID_OUI_FROM_DATABASE=ABB + +OUI:70B3D5893* + ID_OUI_FROM_DATABASE=Cubitech + +OUI:70B3D5894* + ID_OUI_FROM_DATABASE=UnI Systech Co.,Ltd + +OUI:70B3D5895* + ID_OUI_FROM_DATABASE=Integrated Control Corp. + +OUI:70B3D5896* + ID_OUI_FROM_DATABASE=Shanghai Longpal Communication Equipment Co., Ltd. + +OUI:70B3D5897* + ID_OUI_FROM_DATABASE=EFG CZ spol. s r.o. + +OUI:70B3D5899* + ID_OUI_FROM_DATABASE=Viotec USA + +OUI:70B3D589A* + ID_OUI_FROM_DATABASE=Algodue Elettronica Srl + +OUI:70B3D589B* + ID_OUI_FROM_DATABASE=ControlWorks, Inc. + +OUI:70B3D589C* + ID_OUI_FROM_DATABASE=IHI Rotating Machinery Engineering Co.,Ltd. + +OUI:70B3D589D* + ID_OUI_FROM_DATABASE=e-Matix Corporation + +OUI:70B3D589E* + ID_OUI_FROM_DATABASE=Innovative Control Systems, LP + +OUI:70B3D58A0* + ID_OUI_FROM_DATABASE=DM RADIOCOM + +OUI:70B3D58A2* + ID_OUI_FROM_DATABASE=WINNERS DIGITAL CORPORATION + +OUI:70B3D58A4* + ID_OUI_FROM_DATABASE=Phyton, Inc. Microsystems and Development Tools + +OUI:70B3D58A5* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D58A6* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D58A7* + ID_OUI_FROM_DATABASE=Tucsen Photonics Co., Ltd. + +OUI:70B3D58A8* + ID_OUI_FROM_DATABASE=megatec electronic GmbH + +OUI:70B3D58A9* + ID_OUI_FROM_DATABASE=WoKa-Elektronik GmbH + +OUI:70B3D58AA* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D58AB* + ID_OUI_FROM_DATABASE=EMAC, Inc. + +OUI:70B3D58AC* + ID_OUI_FROM_DATABASE=​ASUNG TECHNO CO.,Ltd + +OUI:70B3D58AD* + ID_OUI_FROM_DATABASE=Global Communications Technology LLC + +OUI:70B3D58AE* + ID_OUI_FROM_DATABASE=FARECO + +OUI:70B3D58AF* + ID_OUI_FROM_DATABASE=QBIC COMMUNICATIONS DMCC + +OUI:70B3D58B0* + ID_OUI_FROM_DATABASE=IES S.r.l. + +OUI:70B3D58B1* + ID_OUI_FROM_DATABASE=M-Tech Innovations Limited + +OUI:70B3D58B2* + ID_OUI_FROM_DATABASE=NPF Modem, LLC + +OUI:70B3D58B3* + ID_OUI_FROM_DATABASE=Firefly RFID Solutions + +OUI:70B3D58B4* + ID_OUI_FROM_DATABASE=Scenario Automation + +OUI:70B3D58B7* + ID_OUI_FROM_DATABASE=Contec Americas Inc. + +OUI:70B3D58B8* + ID_OUI_FROM_DATABASE=GDI Technology Inc + +OUI:70B3D58B9* + ID_OUI_FROM_DATABASE=Toptech Systems, Inc. + +OUI:70B3D58BA* + ID_OUI_FROM_DATABASE=TIAMA + +OUI:70B3D58BB* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D58BC* + ID_OUI_FROM_DATABASE=GSI GeoSolutions International Ltd + +OUI:70B3D58BE* + ID_OUI_FROM_DATABASE=Connoiseur Electronics Private Limited + +OUI:70B3D58BF* + ID_OUI_FROM_DATABASE=Hangzhou Leaper Technology Co. Ltd. + +OUI:70B3D58C0* + ID_OUI_FROM_DATABASE=SenseNL + +OUI:70B3D58C1* + ID_OUI_FROM_DATABASE=Rievtech Electronic Co.,Ltd + +OUI:70B3D58C2* + ID_OUI_FROM_DATABASE=F-domain corporation + +OUI:70B3D58C3* + ID_OUI_FROM_DATABASE=Wyebot, Inc. + +OUI:70B3D58C4* + ID_OUI_FROM_DATABASE=APE GmbH + +OUI:70B3D58C5* + ID_OUI_FROM_DATABASE=HMicro Inc + +OUI:70B3D58C6* + ID_OUI_FROM_DATABASE=Onosokki Co.,Ltd + +OUI:70B3D58C7* + ID_OUI_FROM_DATABASE=Henschel-Robotics GmbH + +OUI:70B3D58C8* + ID_OUI_FROM_DATABASE=KRONOTECH SRL + +OUI:70B3D58CA* + ID_OUI_FROM_DATABASE=Allied Data Systems + +OUI:70B3D58CB* + ID_OUI_FROM_DATABASE=WELT Corporation + +OUI:70B3D58CC* + ID_OUI_FROM_DATABASE=Piranha EMS Inc. + +OUI:70B3D58CD* + ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG + +OUI:70B3D58CE* + ID_OUI_FROM_DATABASE=CORES Corporation + +OUI:70B3D58CF* + ID_OUI_FROM_DATABASE=Dainichi Denshi Co.,LTD + +OUI:70B3D58D0* + ID_OUI_FROM_DATABASE=Raft Technologies + +OUI:70B3D58D3* + ID_OUI_FROM_DATABASE=PERFORMANCE CONTROLS, INC. + +OUI:70B3D58D7* + ID_OUI_FROM_DATABASE=Schneider Electric Motion USA + +OUI:70B3D58D8* + ID_OUI_FROM_DATABASE=VNG Corporation + +OUI:70B3D58D9* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D58DA* + ID_OUI_FROM_DATABASE=MicroElectronics System Co.Ltd + +OUI:70B3D58DB* + ID_OUI_FROM_DATABASE=Kratos Analytical Ltd + +OUI:70B3D58DC* + ID_OUI_FROM_DATABASE=Niveo International BV + +OUI:70B3D58DF* + ID_OUI_FROM_DATABASE=DORLET SAU + +OUI:70B3D58E0* + ID_OUI_FROM_DATABASE=SOUDAX EQUIPEMENTS + +OUI:70B3D58E1* + ID_OUI_FROM_DATABASE=WoKa-Elektronik GmbH + +OUI:70B3D58E2* + ID_OUI_FROM_DATABASE=Zhiye Electronics Co., Ltd. + +OUI:70B3D58E3* + ID_OUI_FROM_DATABASE=DORLET SAU + +OUI:70B3D58E4* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D58E6* + ID_OUI_FROM_DATABASE=Mothonic AB + +OUI:70B3D58EA* + ID_OUI_FROM_DATABASE=JLCooper Electronics + +OUI:70B3D58EB* + ID_OUI_FROM_DATABASE=Procon Electronics Pty Ltd + +OUI:70B3D58EC* + ID_OUI_FROM_DATABASE=Rudy Tellert + +OUI:70B3D58ED* + ID_OUI_FROM_DATABASE=NanoSense + +OUI:70B3D58EE* + ID_OUI_FROM_DATABASE=Network Additions + +OUI:70B3D58EF* + ID_OUI_FROM_DATABASE=Beeper Communications Ltd. + +OUI:70B3D58F0* + ID_OUI_FROM_DATABASE=ERAESEEDS co.,ltd. + +OUI:70B3D58F2* + ID_OUI_FROM_DATABASE=Rimota Limited + +OUI:70B3D58F3* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D58F4* + ID_OUI_FROM_DATABASE=ACQUA-SYSTEMS srls + +OUI:70B3D58F5* + ID_OUI_FROM_DATABASE=Stmovic + +OUI:70B3D58F6* + ID_OUI_FROM_DATABASE=Dofuntech Co.,LTD. + +OUI:70B3D58F7* + ID_OUI_FROM_DATABASE=I.E. Sevko A.V. + +OUI:70B3D58F8* + ID_OUI_FROM_DATABASE=Wi6labs + +OUI:70B3D58FA* + ID_OUI_FROM_DATABASE=DEA SYSTEM SPA + +OUI:70B3D58FF* + ID_OUI_FROM_DATABASE=IMST GmbH + +OUI:70B3D5901* + ID_OUI_FROM_DATABASE=ATS-CONVERS + +OUI:70B3D5902* + ID_OUI_FROM_DATABASE=Unlimiterhear co.,ltd. taiwan branch + +OUI:70B3D5903* + ID_OUI_FROM_DATABASE=Cymtec Ltd + +OUI:70B3D5904* + ID_OUI_FROM_DATABASE=PHB Eletronica Ltda. + +OUI:70B3D5906* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5907* + ID_OUI_FROM_DATABASE=NINGBO CRRC TIMES TRANSDUCER TECHNOLOGY CO., LTD + +OUI:70B3D5908* + ID_OUI_FROM_DATABASE=Accusonic + +OUI:70B3D590A* + ID_OUI_FROM_DATABASE=Hangzhou SunTown Intelligent Science & Technology Co.,Ltd. + +OUI:70B3D590B* + ID_OUI_FROM_DATABASE=Matrix Switch Corporation + +OUI:70B3D590C* + ID_OUI_FROM_DATABASE=ANTEK GmbH + +OUI:70B3D590D* + ID_OUI_FROM_DATABASE=Modtronix Engineering + +OUI:70B3D590E* + ID_OUI_FROM_DATABASE=Maytronics Ltd. + +OUI:70B3D590F* + ID_OUI_FROM_DATABASE=DTRON Communications (Pty) Ltd + +OUI:70B3D5910* + ID_OUI_FROM_DATABASE=Eginity, Inc. + +OUI:70B3D5911* + ID_OUI_FROM_DATABASE=Equatel + +OUI:70B3D5913* + ID_OUI_FROM_DATABASE=Shenzhen Riitek Technology Co.,Ltd + +OUI:70B3D5914* + ID_OUI_FROM_DATABASE=Contec Americas Inc. + +OUI:70B3D5916* + ID_OUI_FROM_DATABASE=Techno Mathematical Co.,Ltd + +OUI:70B3D5917* + ID_OUI_FROM_DATABASE=KSJ Co.Ltd + +OUI:70B3D5918* + ID_OUI_FROM_DATABASE=Glova Rail A/S + +OUI:70B3D591A* + ID_OUI_FROM_DATABASE=Fujian Landfone Information Technology Co.,Ltd + +OUI:70B3D591B* + ID_OUI_FROM_DATABASE=Dolotron d.o.o. + +OUI:70B3D591C* + ID_OUI_FROM_DATABASE=Alere Technologies AS + +OUI:70B3D591D* + ID_OUI_FROM_DATABASE=Cubitech + +OUI:70B3D591E* + ID_OUI_FROM_DATABASE=Creotech Instruments S.A. + +OUI:70B3D591F* + ID_OUI_FROM_DATABASE=JSC InformInvestGroup + +OUI:70B3D5920* + ID_OUI_FROM_DATABASE=SLAT + +OUI:70B3D5922* + ID_OUI_FROM_DATABASE=Adcole Maryland Aerospace + +OUI:70B3D5923* + ID_OUI_FROM_DATABASE=eumig industrie-tv GmbH + +OUI:70B3D5924* + ID_OUI_FROM_DATABASE=Meridian Technologies Inc + +OUI:70B3D5925* + ID_OUI_FROM_DATABASE=Diamante Lighting Srl + +OUI:70B3D5926* + ID_OUI_FROM_DATABASE=Advice + +OUI:70B3D5927* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:70B3D5929* + ID_OUI_FROM_DATABASE=OutSys + +OUI:70B3D592A* + ID_OUI_FROM_DATABASE=Miravue + +OUI:70B3D592B* + ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD. + +OUI:70B3D592C* + ID_OUI_FROM_DATABASE=DISMUNTEL SAL + +OUI:70B3D592D* + ID_OUI_FROM_DATABASE=Suzhou Wansong Electric Co.,Ltd + +OUI:70B3D592E* + ID_OUI_FROM_DATABASE=Medical Monitoring Center OOD + +OUI:70B3D592F* + ID_OUI_FROM_DATABASE=SiFive + +OUI:70B3D5930* + ID_OUI_FROM_DATABASE=The Institute of Mine Seismology + +OUI:70B3D5931* + ID_OUI_FROM_DATABASE=MARINE INSTRUMENTS, S.A. + +OUI:70B3D5932* + ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA + +OUI:70B3D5933* + ID_OUI_FROM_DATABASE=SARL S@TIS + +OUI:70B3D5934* + ID_OUI_FROM_DATABASE=RBS Netkom GmbH + +OUI:70B3D5935* + ID_OUI_FROM_DATABASE=Sensor Developments + +OUI:70B3D5936* + ID_OUI_FROM_DATABASE=FARO TECHNOLOGIES, INC. + +OUI:70B3D5937* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5938* + ID_OUI_FROM_DATABASE=JETI Technische Instrumente GmbH + +OUI:70B3D5939* + ID_OUI_FROM_DATABASE=Invertek Drives Ltd + +OUI:70B3D593A* + ID_OUI_FROM_DATABASE=Braemar Manufacturing, LLC + +OUI:70B3D593B* + ID_OUI_FROM_DATABASE=Changchun FAW Yanfeng Visteon Automotive Electronics.,Ltd. + +OUI:70B3D593E* + ID_OUI_FROM_DATABASE=Systems With Intelligence Inc. + +OUI:70B3D5940* + ID_OUI_FROM_DATABASE=Paradigm Technology Services B.V. + +OUI:70B3D5941* + ID_OUI_FROM_DATABASE=Triax A/S + +OUI:70B3D5942* + ID_OUI_FROM_DATABASE=TruTeq Devices (Pty) Ltd + +OUI:70B3D5943* + ID_OUI_FROM_DATABASE=Abbott Medical Optics Inc. + +OUI:70B3D5945* + ID_OUI_FROM_DATABASE=Symboticware Incorporated + +OUI:70B3D5946* + ID_OUI_FROM_DATABASE=GREATWALL Infotech Co., Ltd. + +OUI:70B3D5947* + ID_OUI_FROM_DATABASE=Checkbill Co,Ltd. + +OUI:70B3D5948* + ID_OUI_FROM_DATABASE=VISION SYSTEMS AURTOMOTIVE (SAFETY TECH) + +OUI:70B3D5949* + ID_OUI_FROM_DATABASE=National Radio & Telecommunication Corporation - NRTC + +OUI:70B3D594A* + ID_OUI_FROM_DATABASE=SHENZHEN WISEWING INTERNET TECHNOLOGY CO.,LTD + +OUI:70B3D594B* + ID_OUI_FROM_DATABASE=RF Code + +OUI:70B3D594D* + ID_OUI_FROM_DATABASE=SEASON DESIGN TECHNOLOGY + +OUI:70B3D594E* + ID_OUI_FROM_DATABASE=BP Lubricants USA, Inc. + +OUI:70B3D594F* + ID_OUI_FROM_DATABASE=MART NETWORK SOLUTIONS LTD + +OUI:70B3D5950* + ID_OUI_FROM_DATABASE=CMT Medical technologies + +OUI:70B3D5951* + ID_OUI_FROM_DATABASE=Trident Systems Inc + +OUI:70B3D5952* + ID_OUI_FROM_DATABASE=REQUEA + +OUI:70B3D5953* + ID_OUI_FROM_DATABASE=Spectrum Techniques, LLC + +OUI:70B3D5954* + ID_OUI_FROM_DATABASE=Dot System S.r.l. + +OUI:70B3D5955* + ID_OUI_FROM_DATABASE=Dynacard Co., Ltd. + +OUI:70B3D5956* + ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc. + +OUI:70B3D5957* + ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG + +OUI:70B3D5958* + ID_OUI_FROM_DATABASE=pureLiFi Ltd + +OUI:70B3D5959* + ID_OUI_FROM_DATABASE=Zulex International Co.,Ltd. + +OUI:70B3D595A* + ID_OUI_FROM_DATABASE=Sigmann Elektronik GmbH + +OUI:70B3D595B* + ID_OUI_FROM_DATABASE=SRS Group s.r.o. + +OUI:70B3D595C* + ID_OUI_FROM_DATABASE=Wilson Electronics + +OUI:70B3D595E* + ID_OUI_FROM_DATABASE=BLOCKSI LLC + +OUI:70B3D595F* + ID_OUI_FROM_DATABASE=WiFi Nation Ltd + +OUI:70B3D5960* + ID_OUI_FROM_DATABASE=HORIZON TELECOM + +OUI:70B3D5961* + ID_OUI_FROM_DATABASE=TASK SISTEMAS DE COMPUTACAO LTDA + +OUI:70B3D5963* + ID_OUI_FROM_DATABASE=Triax A/S + +OUI:70B3D5964* + ID_OUI_FROM_DATABASE=Visility + +OUI:70B3D5966* + ID_OUI_FROM_DATABASE=dA Tomato Limited + +OUI:70B3D5967* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5968* + ID_OUI_FROM_DATABASE=LGM Ingénierie + +OUI:70B3D5969* + ID_OUI_FROM_DATABASE=Emtel System Sp. z o.o. + +OUI:70B3D596B* + ID_OUI_FROM_DATABASE=FOCAL-JMLab + +OUI:70B3D596D* + ID_OUI_FROM_DATABASE=MSB Elektronik und Gerätebau GmbH + +OUI:70B3D596E* + ID_OUI_FROM_DATABASE=Myostat Motion Control Inc + +OUI:70B3D596F* + ID_OUI_FROM_DATABASE=4CAM GmbH + +OUI:70B3D5970* + ID_OUI_FROM_DATABASE=Bintel AB + +OUI:70B3D5971* + ID_OUI_FROM_DATABASE=RCH ITALIA SPA + +OUI:70B3D5972* + ID_OUI_FROM_DATABASE=AixControl GmbH + +OUI:70B3D5973* + ID_OUI_FROM_DATABASE=Autonomic Controls, Inc. + +OUI:70B3D5974* + ID_OUI_FROM_DATABASE=Jireh Industries Ltd. + +OUI:70B3D5975* + ID_OUI_FROM_DATABASE=Coester Automação Ltda + +OUI:70B3D5976* + ID_OUI_FROM_DATABASE=Atonarp Micro-Systems India Pvt. Ltd. + +OUI:70B3D5977* + ID_OUI_FROM_DATABASE=Engage Technologies + +OUI:70B3D5978* + ID_OUI_FROM_DATABASE=Satixfy Israel Ltd. + +OUI:70B3D5979* + ID_OUI_FROM_DATABASE=eSMART Technologies SA + +OUI:70B3D597A* + ID_OUI_FROM_DATABASE=Orion Corporation + +OUI:70B3D597B* + ID_OUI_FROM_DATABASE=WIKA Alexander Wiegand SE & Co. KG + +OUI:70B3D597C* + ID_OUI_FROM_DATABASE=Nu-Tek Power Controls and Automation + +OUI:70B3D597D* + ID_OUI_FROM_DATABASE=RCH Vietnam Limited Liability Company + +OUI:70B3D597E* + ID_OUI_FROM_DATABASE=Public Joint Stock Company Morion + +OUI:70B3D597F* + ID_OUI_FROM_DATABASE=BISTOS.,Co.,Ltd + +OUI:70B3D5980* + ID_OUI_FROM_DATABASE=Beijing Yourong Runda Rechnology Development Co.Ltd. + +OUI:70B3D5981* + ID_OUI_FROM_DATABASE=Zamir Recognition Systems Ltd. + +OUI:70B3D5982* + ID_OUI_FROM_DATABASE=3S - Sensors, Signal Processing, Systems GmbH + +OUI:70B3D5983* + ID_OUI_FROM_DATABASE=ENS Engineered Network Systems + +OUI:70B3D5984* + ID_OUI_FROM_DATABASE=Sanmina Israel + +OUI:70B3D5985* + ID_OUI_FROM_DATABASE=Burk Technology + +OUI:70B3D5986* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5987* + ID_OUI_FROM_DATABASE=AXIS CORPORATION + +OUI:70B3D5989* + ID_OUI_FROM_DATABASE=DCNS + +OUI:70B3D598A* + ID_OUI_FROM_DATABASE=vision systems safety tech + +OUI:70B3D598B* + ID_OUI_FROM_DATABASE=Richard Paul Russell Ltd + +OUI:70B3D598C* + ID_OUI_FROM_DATABASE=University of Wisconsin Madison - Department of High Energy Physics + +OUI:70B3D598E* + ID_OUI_FROM_DATABASE=Autocom Diagnostic Partner AB + +OUI:70B3D598F* + ID_OUI_FROM_DATABASE=Spaceflight Industries + +OUI:70B3D5990* + ID_OUI_FROM_DATABASE=Energy Wall + +OUI:70B3D5991* + ID_OUI_FROM_DATABASE=Javasparrow Inc. + +OUI:70B3D5993* + ID_OUI_FROM_DATABASE=ioThings + +OUI:70B3D5994* + ID_OUI_FROM_DATABASE=KeFF Networks + +OUI:70B3D5995* + ID_OUI_FROM_DATABASE=LayTec AG + +OUI:70B3D5996* + ID_OUI_FROM_DATABASE=XpertSea Solutions inc. + +OUI:70B3D5997* + ID_OUI_FROM_DATABASE=ProTom International + +OUI:70B3D5999* + ID_OUI_FROM_DATABASE=LOGICUBE INC + +OUI:70B3D599A* + ID_OUI_FROM_DATABASE=KEVIC. inc, + +OUI:70B3D599B* + ID_OUI_FROM_DATABASE=RCH ITALIA SPA + +OUI:70B3D599C* + ID_OUI_FROM_DATABASE=Enerwise Solutions Ltd. + +OUI:70B3D599E* + ID_OUI_FROM_DATABASE=Trinity College Dublin + +OUI:70B3D599F* + ID_OUI_FROM_DATABASE=Confed Holding B.V. + +OUI:70B3D59A0* + ID_OUI_FROM_DATABASE=ELDES + +OUI:70B3D59A1* + ID_OUI_FROM_DATABASE=ITS Industrial Turbine Services GmbH + +OUI:70B3D59A2* + ID_OUI_FROM_DATABASE=O-Net Communications(Shenzhen)Limited + +OUI:70B3D59A4* + ID_OUI_FROM_DATABASE=Nordmann International GmbH + +OUI:70B3D59A5* + ID_OUI_FROM_DATABASE=Softel + +OUI:70B3D59A7* + ID_OUI_FROM_DATABASE=Honeywell + +OUI:70B3D59A9* + ID_OUI_FROM_DATABASE=PABLO AIR Co., LTD + +OUI:70B3D59AA* + ID_OUI_FROM_DATABASE=Tecsys do Brasil Industrial Ltda + +OUI:70B3D59AB* + ID_OUI_FROM_DATABASE=Groupe Paris-Turf + +OUI:70B3D59AC* + ID_OUI_FROM_DATABASE=Suzhou Sapa Automotive Technology Co.,Ltd + +OUI:70B3D59AD* + ID_OUI_FROM_DATABASE=Fortuna Impex Pvt ltd + +OUI:70B3D59AE* + ID_OUI_FROM_DATABASE=Volansys technologies pvt ltd + +OUI:70B3D59AF* + ID_OUI_FROM_DATABASE=Shanghai Brellet Telecommunication Technology Co., Ltd. + +OUI:70B3D59B0* + ID_OUI_FROM_DATABASE=Clearly IP Inc + +OUI:70B3D59B1* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D59B2* + ID_OUI_FROM_DATABASE=CONTINENT, Ltd + +OUI:70B3D59B3* + ID_OUI_FROM_DATABASE=K&J Schmittschneider AG + +OUI:70B3D59B4* + ID_OUI_FROM_DATABASE=MyoungSung System + +OUI:70B3D59B5* + ID_OUI_FROM_DATABASE=Ideetron b.v. + +OUI:70B3D59B6* + ID_OUI_FROM_DATABASE=Intercomp S.p.A. + +OUI:70B3D59B7* + ID_OUI_FROM_DATABASE=Itronics Ltd + +OUI:70B3D59B8* + ID_OUI_FROM_DATABASE=Loma Systems s.r.o. + +OUI:70B3D59B9* + ID_OUI_FROM_DATABASE=Aethera Technologies + +OUI:70B3D59BA* + ID_OUI_FROM_DATABASE=ATIM Radiocommunication + +OUI:70B3D59BD* + ID_OUI_FROM_DATABASE=Signal Processing Devices Sweden AB + +OUI:70B3D59BE* + ID_OUI_FROM_DATABASE=Izome + +OUI:70B3D59BF* + ID_OUI_FROM_DATABASE=Xiris Automation Inc. + +OUI:70B3D59C0* + ID_OUI_FROM_DATABASE=Schneider Displaytechnik GmbH + +OUI:70B3D59C1* + ID_OUI_FROM_DATABASE=Zeroplus Technology Co.,Ltd. + +OUI:70B3D59C3* + ID_OUI_FROM_DATABASE=Sevensense Robotics AG + +OUI:70B3D59C4* + ID_OUI_FROM_DATABASE=aelettronica group srl + +OUI:70B3D59C5* + ID_OUI_FROM_DATABASE=LINEAGE POWER PVT LTD., + +OUI:70B3D59C6* + ID_OUI_FROM_DATABASE=Overspeed SARL + +OUI:70B3D59C7* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D59C8* + ID_OUI_FROM_DATABASE=Applied Systems Engineering, Inc. + +OUI:70B3D59C9* + ID_OUI_FROM_DATABASE=PK Sound + +OUI:70B3D59CA* + ID_OUI_FROM_DATABASE=KOMSIS ELEKTRONIK SISTEMLERI SAN. TIC. LTD.STI + +OUI:70B3D59CB* + ID_OUI_FROM_DATABASE=Alligator Communications + +OUI:70B3D59CC* + ID_OUI_FROM_DATABASE=Zaxcom Inc + +OUI:70B3D59CE* + ID_OUI_FROM_DATABASE=Terragene S.A + +OUI:70B3D59CF* + ID_OUI_FROM_DATABASE=IOTIZE + +OUI:70B3D59D0* + ID_OUI_FROM_DATABASE=RJ45 Technologies + +OUI:70B3D59D1* + ID_OUI_FROM_DATABASE=OS42 UG (haftungsbeschraenkt) + +OUI:70B3D59D2* + ID_OUI_FROM_DATABASE=ACS MOTION CONTROL + +OUI:70B3D59D3* + ID_OUI_FROM_DATABASE=Communication Technology Ltd. + +OUI:70B3D59D4* + ID_OUI_FROM_DATABASE=Wartsila Voyage Limited + +OUI:70B3D59D5* + ID_OUI_FROM_DATABASE=Southern Tier Technologies + +OUI:70B3D59D6* + ID_OUI_FROM_DATABASE=Crown Solar Power Fencing Systems + +OUI:70B3D59D7* + ID_OUI_FROM_DATABASE=KM OptoElektronik GmbH + +OUI:70B3D59D9* + ID_OUI_FROM_DATABASE=ATX Networks Corp + +OUI:70B3D59DA* + ID_OUI_FROM_DATABASE=Blake UK + +OUI:70B3D59DB* + ID_OUI_FROM_DATABASE=CAS Medical Systems, Inc + +OUI:70B3D59DC* + ID_OUI_FROM_DATABASE=Shanghai Daorech Industry Developmnet Co.,Ltd + +OUI:70B3D59DD* + ID_OUI_FROM_DATABASE=HumanEyes Technologies Ltd. + +OUI:70B3D59DE* + ID_OUI_FROM_DATABASE=System 11 Sp. z o.o. + +OUI:70B3D59DF* + ID_OUI_FROM_DATABASE=DOBE Computing + +OUI:70B3D59E0* + ID_OUI_FROM_DATABASE=ES Industrial Systems Co., Ltd. + +OUI:70B3D59E1* + ID_OUI_FROM_DATABASE=Bolide Technology Group, Inc. + +OUI:70B3D59E2* + ID_OUI_FROM_DATABASE=Ofil USA + +OUI:70B3D59E3* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:70B3D59E6* + ID_OUI_FROM_DATABASE=BLOCKSI LLC + +OUI:70B3D59E7* + ID_OUI_FROM_DATABASE=Xiamen Maxincom Technologies Co., Ltd. + +OUI:70B3D59E8* + ID_OUI_FROM_DATABASE=Zerospace ICT Services B.V. + +OUI:70B3D59EA* + ID_OUI_FROM_DATABASE=Blue Storm Associates, Inc. + +OUI:70B3D59EB* + ID_OUI_FROM_DATABASE=Preston Industries dba PolyScience + +OUI:70B3D59EC* + ID_OUI_FROM_DATABASE=eSoftThings + +OUI:70B3D59ED* + ID_OUI_FROM_DATABASE=Benchmark Electronics BV + +OUI:70B3D59EE* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D59EF* + ID_OUI_FROM_DATABASE=Cottonwood Creek Technologies, Inc. + +OUI:70B3D59F0* + ID_OUI_FROM_DATABASE=FUJICOM Co.,Ltd. + +OUI:70B3D59F1* + ID_OUI_FROM_DATABASE=RFEL Ltd + +OUI:70B3D59F2* + ID_OUI_FROM_DATABASE=Acorde Technologies + +OUI:70B3D59F3* + ID_OUI_FROM_DATABASE=IEEE Registration Authority + +OUI:70B3D59F4* + ID_OUI_FROM_DATABASE=Tband srl + +OUI:70B3D59F5* + ID_OUI_FROM_DATABASE=Vickers Electronics Ltd + +OUI:70B3D59F6* + ID_OUI_FROM_DATABASE=Edgeware AB + +OUI:70B3D59F7* + ID_OUI_FROM_DATABASE=Foerster-Technik GmbH + +OUI:70B3D59F8* + ID_OUI_FROM_DATABASE=Asymmetric Technologies + +OUI:70B3D59F9* + ID_OUI_FROM_DATABASE=Fluid Components Intl + +OUI:70B3D59FA* + ID_OUI_FROM_DATABASE=Ideas srl + +OUI:70B3D59FB* + ID_OUI_FROM_DATABASE=Unicom Global, Inc. + +OUI:70B3D59FC* + ID_OUI_FROM_DATABASE=Truecom Telesoft Private Limited + +OUI:70B3D59FD* + ID_OUI_FROM_DATABASE=amakidenki + +OUI:70B3D59FE* + ID_OUI_FROM_DATABASE=SURUGA SEIKI CO., LTD. + +OUI:70B3D5A00* + ID_OUI_FROM_DATABASE=ATX NETWORKS LTD + +OUI:70B3D5A01* + ID_OUI_FROM_DATABASE=FeldTech GmbH + +OUI:70B3D5A03* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5A04* + ID_OUI_FROM_DATABASE=Galea Electric S.L. + +OUI:70B3D5A05* + ID_OUI_FROM_DATABASE=Wartsila Voyage Limited + +OUI:70B3D5A06* + ID_OUI_FROM_DATABASE=Kopis Mobile LLC + +OUI:70B3D5A07* + ID_OUI_FROM_DATABASE=IoTrek Technology Private Limited + +OUI:70B3D5A08* + ID_OUI_FROM_DATABASE=BioBusiness + +OUI:70B3D5A09* + ID_OUI_FROM_DATABASE=Smart Embedded Systems + +OUI:70B3D5A0A* + ID_OUI_FROM_DATABASE=CAPSYS + +OUI:70B3D5A0B* + ID_OUI_FROM_DATABASE=ambiHome GmbH + +OUI:70B3D5A0D* + ID_OUI_FROM_DATABASE=Globalcom Engineering SPA + +OUI:70B3D5A0E* + ID_OUI_FROM_DATABASE=Vetaphone A/S + +OUI:70B3D5A0F* + ID_OUI_FROM_DATABASE=OSAKI DATATECH CO., LTD. + +OUI:70B3D5A10* + ID_OUI_FROM_DATABASE=w-tec AG + +OUI:70B3D5A12* + ID_OUI_FROM_DATABASE=QUERCUS TECHNOLOGIES, S.L. + +OUI:70B3D5A13* + ID_OUI_FROM_DATABASE=Uplevel Systems Inc + +OUI:70B3D5A15* + ID_OUI_FROM_DATABASE=Intercore GmbH + +OUI:70B3D5A17* + ID_OUI_FROM_DATABASE=Tunstall A/S + +OUI:70B3D5A18* + ID_OUI_FROM_DATABASE=Embedded Systems Lukasz Panasiuk + +OUI:70B3D5A19* + ID_OUI_FROM_DATABASE=Qualitronix Madrass Pvt Ltd + +OUI:70B3D5A1B* + ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC + +OUI:70B3D5A1C* + ID_OUI_FROM_DATABASE=MECA SYSTEM + +OUI:70B3D5A1D* + ID_OUI_FROM_DATABASE=Fluid Components International + +OUI:70B3D5A1F* + ID_OUI_FROM_DATABASE=GlobalTest LLC + +OUI:70B3D5A20* + ID_OUI_FROM_DATABASE=Design For Life Systems + +OUI:70B3D5A21* + ID_OUI_FROM_DATABASE=PPI Inc. + +OUI:70B3D5A22* + ID_OUI_FROM_DATABASE=eSys Solutions Sweden AB + +OUI:70B3D5A24* + ID_OUI_FROM_DATABASE=Booz Allen Hamilton + +OUI:70B3D5A25* + ID_OUI_FROM_DATABASE=PulseTor LLC + +OUI:70B3D5A26* + ID_OUI_FROM_DATABASE=Hear Gear, Inc. + +OUI:70B3D5A27* + ID_OUI_FROM_DATABASE=HDL da Amazônia Industria Eletrônica Ltda + +OUI:70B3D5A28* + ID_OUI_FROM_DATABASE=PEEK TRAFFIC + +OUI:70B3D5A29* + ID_OUI_FROM_DATABASE=QIAGEN Instruments AG + +OUI:70B3D5A2A* + ID_OUI_FROM_DATABASE=Redwood Systems + +OUI:70B3D5A2B* + ID_OUI_FROM_DATABASE=Clever Devices + +OUI:70B3D5A2C* + ID_OUI_FROM_DATABASE=TLV CO., LTD. + +OUI:70B3D5A2D* + ID_OUI_FROM_DATABASE=Project Service S.r.l. + +OUI:70B3D5A2E* + ID_OUI_FROM_DATABASE=Kokam Co., Ltd + +OUI:70B3D5A2F* + ID_OUI_FROM_DATABASE=Botek Systems AB + +OUI:70B3D5A30* + ID_OUI_FROM_DATABASE=SHEN ZHEN HUAWANG TECHNOLOGY CO; LTD + +OUI:70B3D5A32* + ID_OUI_FROM_DATABASE=Toughdog Security Systems + +OUI:70B3D5A33* + ID_OUI_FROM_DATABASE=TIAMA + +OUI:70B3D5A34* + ID_OUI_FROM_DATABASE=RCH ITALIA SPA + +OUI:70B3D5A35* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D5A36* + ID_OUI_FROM_DATABASE=Beijing DamingWuzhou Science&Technology Co., Ltd. + +OUI:70B3D5A37* + ID_OUI_FROM_DATABASE=MITSUBISHI HEAVY INDUSTRIES THERMAL SYSTEMS, LTD. + +OUI:70B3D5A38* + ID_OUI_FROM_DATABASE=Aditec GmbH + +OUI:70B3D5A39* + ID_OUI_FROM_DATABASE=SPETSSTROY-SVYAZ Ltd + +OUI:70B3D5A3A* + ID_OUI_FROM_DATABASE=EPSOFT Co., Ltd + +OUI:70B3D5A3B* + ID_OUI_FROM_DATABASE=Grace Design/Lunatec LLC + +OUI:70B3D5A3C* + ID_OUI_FROM_DATABASE=Wave Music Ltd + +OUI:70B3D5A3D* + ID_OUI_FROM_DATABASE=SMART IN OVATION GmbH + +OUI:70B3D5A3F* + ID_OUI_FROM_DATABASE=PHPower Srl + +OUI:70B3D5A40* + ID_OUI_FROM_DATABASE=STRACK LIFT AUTOMATION GmbH + +OUI:70B3D5A41* + ID_OUI_FROM_DATABASE=THELIGHT Luminary for Cine and TV S.L. + +OUI:70B3D5A42* + ID_OUI_FROM_DATABASE=iMAR Navigation GmbH + +OUI:70B3D5A43* + ID_OUI_FROM_DATABASE=OLEDCOMM + +OUI:70B3D5A44* + ID_OUI_FROM_DATABASE=FSR, INC. + +OUI:70B3D5A45* + ID_OUI_FROM_DATABASE=Viper Innovations Ltd + +OUI:70B3D5A46* + ID_OUI_FROM_DATABASE=Foxconn 4Tech + +OUI:70B3D5A47* + ID_OUI_FROM_DATABASE=KANOA INC + +OUI:70B3D5A48* + ID_OUI_FROM_DATABASE=Applied Satellite Engineering + +OUI:70B3D5A49* + ID_OUI_FROM_DATABASE=Unipower AB + +OUI:70B3D5A4A* + ID_OUI_FROM_DATABASE=Beijing Arrow SEED Technology Co,.Ltd. + +OUI:70B3D5A4B* + ID_OUI_FROM_DATABASE=McKay Brothers LLC + +OUI:70B3D5A4C* + ID_OUI_FROM_DATABASE=Alere Technologies AS + +OUI:70B3D5A4D* + ID_OUI_FROM_DATABASE=LANSITEC TECHNOLOGY CO., LTD + +OUI:70B3D5A4E* + ID_OUI_FROM_DATABASE=Array Technologies Inc. + +OUI:70B3D5A4F* + ID_OUI_FROM_DATABASE=Weltek Technologies Co. Ltd. + +OUI:70B3D5A50* + ID_OUI_FROM_DATABASE=LECIP CORPORATION + +OUI:70B3D5A51* + ID_OUI_FROM_DATABASE=RF Code + +OUI:70B3D5A52* + ID_OUI_FROM_DATABASE=APEX Stabilizations GmbH + +OUI:70B3D5A53* + ID_OUI_FROM_DATABASE=GS Industrie-Elektronik GmbH + +OUI:70B3D5A54* + ID_OUI_FROM_DATABASE=provedo + +OUI:70B3D5A55* + ID_OUI_FROM_DATABASE=Embest Technology Co., Ltd + +OUI:70B3D5A56* + ID_OUI_FROM_DATABASE=DORLET SAU + +OUI:70B3D5A57* + ID_OUI_FROM_DATABASE=PCSC + +OUI:70B3D5A58* + ID_OUI_FROM_DATABASE=MCQ TECH GmbH + +OUI:70B3D5A59* + ID_OUI_FROM_DATABASE=Muuntosähkö Oy - Trafox + +OUI:70B3D5A5A* + ID_OUI_FROM_DATABASE=RCS Energy Management Ltd + +OUI:70B3D5A5B* + ID_OUI_FROM_DATABASE=Christ Elektronik GmbH + +OUI:70B3D5A5C* + ID_OUI_FROM_DATABASE=Molekule + +OUI:70B3D5A5D* + ID_OUI_FROM_DATABASE=Position Imaging + +OUI:70B3D5A5E* + ID_OUI_FROM_DATABASE=ConectaIP Tecnologia S.L. + +OUI:70B3D5A5F* + ID_OUI_FROM_DATABASE=Daatrics LTD + +OUI:70B3D5A60* + ID_OUI_FROM_DATABASE=Pneumax S.p.A. + +OUI:70B3D5A62* + ID_OUI_FROM_DATABASE=Environexus + +OUI:70B3D5A64* + ID_OUI_FROM_DATABASE=Newshine + +OUI:70B3D5A66* + ID_OUI_FROM_DATABASE=Trapeze Software Group Inc + +OUI:70B3D5A67* + ID_OUI_FROM_DATABASE=Gstar Creation Co .,Ltd + +OUI:70B3D5A68* + ID_OUI_FROM_DATABASE=Zhejiang Zhaolong Interconnect Technology Co.,Ltd + +OUI:70B3D5A69* + ID_OUI_FROM_DATABASE=Leviathan Solutions Ltd. + +OUI:70B3D5A6A* + ID_OUI_FROM_DATABASE=Privafy, Inc + +OUI:70B3D5A6B* + ID_OUI_FROM_DATABASE=xmi systems + +OUI:70B3D5A6C* + ID_OUI_FROM_DATABASE=Controles S.A. + +OUI:70B3D5A6D* + ID_OUI_FROM_DATABASE=Metek Meteorologische Messtechnik GmbH + +OUI:70B3D5A6E* + ID_OUI_FROM_DATABASE=JSC Electrical Equipment Factory + +OUI:70B3D5A6F* + ID_OUI_FROM_DATABASE=8Cups + +OUI:70B3D5A70* + ID_OUI_FROM_DATABASE=Gateview Technologies + +OUI:70B3D5A71* + ID_OUI_FROM_DATABASE=Samwell International Inc + +OUI:70B3D5A72* + ID_OUI_FROM_DATABASE=Business Marketers Group, Inc. + +OUI:70B3D5A73* + ID_OUI_FROM_DATABASE=MobiPromo + +OUI:70B3D5A74* + ID_OUI_FROM_DATABASE=Sadel S.p.A. + +OUI:70B3D5A75* + ID_OUI_FROM_DATABASE=Taejin InfoTech + +OUI:70B3D5A76* + ID_OUI_FROM_DATABASE=Pietro Fiorentini + +OUI:70B3D5A78* + ID_OUI_FROM_DATABASE=Bionics co.,ltd. + +OUI:70B3D5A7A* + ID_OUI_FROM_DATABASE=Fluid Management Technology + +OUI:70B3D5A7B* + ID_OUI_FROM_DATABASE=SmartSafe + +OUI:70B3D5A7C* + ID_OUI_FROM_DATABASE=Transelektronik Messgeräte GmbH + +OUI:70B3D5A7D* + ID_OUI_FROM_DATABASE=Prior Scientific Instruments Ltd + +OUI:70B3D5A7E* + ID_OUI_FROM_DATABASE=QUICCO SOUND Corporation + +OUI:70B3D5A7F* + ID_OUI_FROM_DATABASE=AUDIO VISUAL DIGITAL SYSTEMS + +OUI:70B3D5A80* + ID_OUI_FROM_DATABASE=EVCO SPA + +OUI:70B3D5A81* + ID_OUI_FROM_DATABASE=Sienda New Media Technologies GmbH + +OUI:70B3D5A82* + ID_OUI_FROM_DATABASE=Telefrank GmbH + +OUI:70B3D5A83* + ID_OUI_FROM_DATABASE=SHENZHEN HUINENGYUAN Technology Co., Ltd + +OUI:70B3D5A84* + ID_OUI_FROM_DATABASE=SOREL GmbH Mikroelektronik + +OUI:70B3D5A85* + ID_OUI_FROM_DATABASE=exceet electronics GesmbH + +OUI:70B3D5A86* + ID_OUI_FROM_DATABASE=Divigraph (Pty) LTD + +OUI:70B3D5A87* + ID_OUI_FROM_DATABASE=Tornado Modular Systems + +OUI:70B3D5A88* + ID_OUI_FROM_DATABASE=Shangdong Bosure Automation Technology Ltd + +OUI:70B3D5A89* + ID_OUI_FROM_DATABASE=GBS COMMUNICATIONS, LLC + +OUI:70B3D5A8A* + ID_OUI_FROM_DATABASE=JSC VIST Group + +OUI:70B3D5A8B* + ID_OUI_FROM_DATABASE=Giant Power Technology Biomedical Corporation + +OUI:70B3D5A8D* + ID_OUI_FROM_DATABASE=Code Blue Corporation + +OUI:70B3D5A8E* + ID_OUI_FROM_DATABASE=OMESH CITY GROUP + +OUI:70B3D5A90* + ID_OUI_FROM_DATABASE=ERA a.s. + +OUI:70B3D5A91* + ID_OUI_FROM_DATABASE=IDEAL INDUSTRIES Ltd t/a Casella + +OUI:70B3D5A92* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D5A93* + ID_OUI_FROM_DATABASE=Mes Communication Co., Ltd + +OUI:70B3D5A94* + ID_OUI_FROM_DATABASE=ETA Technology Pvt Ltd + +OUI:70B3D5A95* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D5A96* + ID_OUI_FROM_DATABASE=Östling Marking Systems GmbH + +OUI:70B3D5A97* + ID_OUI_FROM_DATABASE=Bizwerks, LLC + +OUI:70B3D5A98* + ID_OUI_FROM_DATABASE=Pantec AG + +OUI:70B3D5A99* + ID_OUI_FROM_DATABASE=Bandelin electronic GmbH & Co. KG + +OUI:70B3D5A9A* + ID_OUI_FROM_DATABASE=Amphenol Advanced Sensors + +OUI:70B3D5A9B* + ID_OUI_FROM_DATABASE=OSMOZIS + +OUI:70B3D5A9C* + ID_OUI_FROM_DATABASE=Veo Technologies + +OUI:70B3D5A9D* + ID_OUI_FROM_DATABASE=VITEC MULTIMEDIA + +OUI:70B3D5A9E* + ID_OUI_FROM_DATABASE=Argon ST + +OUI:70B3D5A9F* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5AA0* + ID_OUI_FROM_DATABASE=Simple Works, Inc. + +OUI:70B3D5AA1* + ID_OUI_FROM_DATABASE=Shenzhen Weema TV Technology Co.,Ltd. + +OUI:70B3D5AA2* + ID_OUI_FROM_DATABASE=eumig industrie-TV GmbH. + +OUI:70B3D5AA3* + ID_OUI_FROM_DATABASE=LINEAGE POWER PVT LTD., + +OUI:70B3D5AA4* + ID_OUI_FROM_DATABASE=Pullnet Technology,S.L. + +OUI:70B3D5AA5* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5AA6* + ID_OUI_FROM_DATABASE=Proximus + +OUI:70B3D5AA7* + ID_OUI_FROM_DATABASE=ATEME + +OUI:70B3D5AA8* + ID_OUI_FROM_DATABASE=West-Com Nurse Call Systems, Inc. + +OUI:70B3D5AA9* + ID_OUI_FROM_DATABASE=Datamars SA + +OUI:70B3D5AAA* + ID_OUI_FROM_DATABASE=Xemex NV + +OUI:70B3D5AAC* + ID_OUI_FROM_DATABASE=SensoTec GmbH + +OUI:70B3D5AAD* + ID_OUI_FROM_DATABASE=Bartec GmbH + +OUI:70B3D5AAE* + ID_OUI_FROM_DATABASE=Nuviz Oy + +OUI:70B3D5AAF* + ID_OUI_FROM_DATABASE=Exi Flow Measurement Ltd + +OUI:70B3D5AB0* + ID_OUI_FROM_DATABASE=OSR R&D ISRAEL LTD + +OUI:70B3D5AB2* + ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. + +OUI:70B3D5AB3* + ID_OUI_FROM_DATABASE=MICAS AG + +OUI:70B3D5AB4* + ID_OUI_FROM_DATABASE=SYS TEC electronic GmbH + +OUI:70B3D5AB5* + ID_OUI_FROM_DATABASE=BroadSoft Inc + +OUI:70B3D5AB6* + ID_OUI_FROM_DATABASE=SmartD Technologies Inc + +OUI:70B3D5AB7* + ID_OUI_FROM_DATABASE=SIGLEAD INC + +OUI:70B3D5AB8* + ID_OUI_FROM_DATABASE=HORIBA ABX SAS + +OUI:70B3D5AB9* + ID_OUI_FROM_DATABASE=Dynamic Controls + +OUI:70B3D5ABA* + ID_OUI_FROM_DATABASE=CL International + +OUI:70B3D5ABB* + ID_OUI_FROM_DATABASE=David Horn Communications Ltd + +OUI:70B3D5ABC* + ID_OUI_FROM_DATABASE=BKM-Micronic Richtfunkanlagen GmbH + +OUI:70B3D5ABD* + ID_OUI_FROM_DATABASE=wtec GmbH + +OUI:70B3D5ABE* + ID_OUI_FROM_DATABASE=MART NETWORK SOLUTIONS LTD + +OUI:70B3D5ABF* + ID_OUI_FROM_DATABASE=AGR International + +OUI:70B3D5AC0* + ID_OUI_FROM_DATABASE=RITEC + +OUI:70B3D5AC1* + ID_OUI_FROM_DATABASE=AEM Singapore Pte. Ltd. + +OUI:70B3D5AC3* + ID_OUI_FROM_DATABASE=Novoptel GmbH + +OUI:70B3D5AC4* + ID_OUI_FROM_DATABASE=Lexi Devices, Inc. + +OUI:70B3D5AC5* + ID_OUI_FROM_DATABASE=ATOM GIKEN Co.,Ltd. + +OUI:70B3D5AC6* + ID_OUI_FROM_DATABASE=SMTC Corporation + +OUI:70B3D5AC7* + ID_OUI_FROM_DATABASE=vivaMOS + +OUI:70B3D5AC8* + ID_OUI_FROM_DATABASE=Heartland.Data Inc. + +OUI:70B3D5AC9* + ID_OUI_FROM_DATABASE=Trinity Solutions LLC + +OUI:70B3D5ACA* + ID_OUI_FROM_DATABASE=Tecnint HTE SRL + +OUI:70B3D5ACB* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5ACC* + ID_OUI_FROM_DATABASE=Schneider Electric Motion USA + +OUI:70B3D5ACD* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5ACF* + ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC + +OUI:70B3D5AD1* + ID_OUI_FROM_DATABASE=Sensile Technologies SA + +OUI:70B3D5AD2* + ID_OUI_FROM_DATABASE=Wart-Elektronik + +OUI:70B3D5AD5* + ID_OUI_FROM_DATABASE=Birdland Audio + +OUI:70B3D5AD6* + ID_OUI_FROM_DATABASE=Lemonade Lab Inc + +OUI:70B3D5AD8* + ID_OUI_FROM_DATABASE=Euklis by GSG International + +OUI:70B3D5ADA* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5ADB* + ID_OUI_FROM_DATABASE=RF Code + +OUI:70B3D5ADC* + ID_OUI_FROM_DATABASE=SODAQ + +OUI:70B3D5ADD* + ID_OUI_FROM_DATABASE=GHL Systems Berhad + +OUI:70B3D5ADE* + ID_OUI_FROM_DATABASE=ISAC SRL + +OUI:70B3D5ADF* + ID_OUI_FROM_DATABASE=Seraphim Optronics Ltd + +OUI:70B3D5AE0* + ID_OUI_FROM_DATABASE=AnyComm.Co.,Ltd. + +OUI:70B3D5AE1* + ID_OUI_FROM_DATABASE=DimoCore Corporation + +OUI:70B3D5AE2* + ID_OUI_FROM_DATABASE=Wartsila Voyage Limited + +OUI:70B3D5AE3* + ID_OUI_FROM_DATABASE=Zhejiang Wellsun Electric Meter Co.,Ltd + +OUI:70B3D5AE5* + ID_OUI_FROM_DATABASE=BeatCraft, Inc. + +OUI:70B3D5AE6* + ID_OUI_FROM_DATABASE=Ya Batho Trading (Pty) Ltd + +OUI:70B3D5AE7* + ID_OUI_FROM_DATABASE=E-T-A Elektrotechnische Apparate GmbH + +OUI:70B3D5AE9* + ID_OUI_FROM_DATABASE=Cari Electronic + +OUI:70B3D5AEA* + ID_OUI_FROM_DATABASE=BBR Verkehrstechnik GmbH + +OUI:70B3D5AEB* + ID_OUI_FROM_DATABASE=Association Romandix + +OUI:70B3D5AEC* + ID_OUI_FROM_DATABASE=Paratec Ltd. + +OUI:70B3D5AED* + ID_OUI_FROM_DATABASE=Cubitech + +OUI:70B3D5AEE* + ID_OUI_FROM_DATABASE=DiTEST Fahrzeugdiagnose GmbH + +OUI:70B3D5AEF* + ID_OUI_FROM_DATABASE=Baumtec GmbH + +OUI:70B3D5AF0* + ID_OUI_FROM_DATABASE=SEASON DESIGN TECHNOLOGY + +OUI:70B3D5AF1* + ID_OUI_FROM_DATABASE=Emka Technologies + +OUI:70B3D5AF2* + ID_OUI_FROM_DATABASE=True Networks Ltd. + +OUI:70B3D5AF3* + ID_OUI_FROM_DATABASE=New Japan Radio Co., Ltd + +OUI:70B3D5AF4* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5AF5* + ID_OUI_FROM_DATABASE=Net And Print Inc. + +OUI:70B3D5AF6* + ID_OUI_FROM_DATABASE=S.C.E. srl + +OUI:70B3D5AF7* + ID_OUI_FROM_DATABASE=DimoSystems BV + +OUI:70B3D5AF8* + ID_OUI_FROM_DATABASE=boekel + +OUI:70B3D5AF9* + ID_OUI_FROM_DATABASE=Critical Link LLC + +OUI:70B3D5AFA* + ID_OUI_FROM_DATABASE=Power Security Systems Ltd. + +OUI:70B3D5AFB* + ID_OUI_FROM_DATABASE=Shanghai Tianhe Automation Instrumentation Co., Ltd. + +OUI:70B3D5AFE* + ID_OUI_FROM_DATABASE=MESOTECHNIC + +OUI:70B3D5AFF* + ID_OUI_FROM_DATABASE=digital-spice + +OUI:70B3D5B00* + ID_OUI_FROM_DATABASE=HORIBA ABX SAS + +OUI:70B3D5B02* + ID_OUI_FROM_DATABASE=Nordic Automation Systems AS + +OUI:70B3D5B04* + ID_OUI_FROM_DATABASE=Herrmann Datensysteme GmbH + +OUI:70B3D5B05* + ID_OUI_FROM_DATABASE=E-PLUS TECHNOLOGY CO., LTD + +OUI:70B3D5B06* + ID_OUI_FROM_DATABASE=MULTIVOICE LLC + +OUI:70B3D5B07* + ID_OUI_FROM_DATABASE=Arrowvale Electronics + +OUI:70B3D5B08* + ID_OUI_FROM_DATABASE=Secuinfo Co. Ltd + +OUI:70B3D5B09* + ID_OUI_FROM_DATABASE=FIRST LIGHT IMAGING + +OUI:70B3D5B0B* + ID_OUI_FROM_DATABASE=INTERNET PROTOCOLO LOGICA SL + +OUI:70B3D5B0C* + ID_OUI_FROM_DATABASE=Vigilate srl + +OUI:70B3D5B0F* + ID_OUI_FROM_DATABASE=merkur Funksysteme AG + +OUI:70B3D5B10* + ID_OUI_FROM_DATABASE=Zumbach Electronic AG + +OUI:70B3D5B11* + ID_OUI_FROM_DATABASE=CAB S.R.L. + +OUI:70B3D5B13* + ID_OUI_FROM_DATABASE=Omwave + +OUI:70B3D5B15* + ID_OUI_FROM_DATABASE=Eta Beta Srl + +OUI:70B3D5B16* + ID_OUI_FROM_DATABASE=XI'AN SHENMING ELECTRON TECHNOLOGY CO.,LTD + +OUI:70B3D5B17* + ID_OUI_FROM_DATABASE=Intesens + +OUI:70B3D5B18* + ID_OUI_FROM_DATABASE=Abbas, a.s. + +OUI:70B3D5B19* + ID_OUI_FROM_DATABASE=Brayden Automation Corp + +OUI:70B3D5B1A* + ID_OUI_FROM_DATABASE=Aaronia AG + +OUI:70B3D5B1B* + ID_OUI_FROM_DATABASE=Technology Link Corporation + +OUI:70B3D5B1D* + ID_OUI_FROM_DATABASE=Safelet BV + +OUI:70B3D5B1E* + ID_OUI_FROM_DATABASE=Fen Systems Ltd + +OUI:70B3D5B1F* + ID_OUI_FROM_DATABASE=TECNOWATT + +OUI:70B3D5B20* + ID_OUI_FROM_DATABASE=ICT BUSINESS GROUP of Humanrights Center for disabled people + +OUI:70B3D5B21* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5B23* + ID_OUI_FROM_DATABASE=Supervision Test et Pilotage + +OUI:70B3D5B24* + ID_OUI_FROM_DATABASE=Datasat Digital Entertainment + +OUI:70B3D5B25* + ID_OUI_FROM_DATABASE=Hifocus Electronics India Private Limited + +OUI:70B3D5B26* + ID_OUI_FROM_DATABASE=INTEC International GmbH + +OUI:70B3D5B28* + ID_OUI_FROM_DATABASE=HUSTY M.Styczen J.Hupert sp.j. + +OUI:70B3D5B29* + ID_OUI_FROM_DATABASE=WiViCom Co., Ltd. + +OUI:70B3D5B2A* + ID_OUI_FROM_DATABASE=Myro Control, LLC + +OUI:70B3D5B2B* + ID_OUI_FROM_DATABASE=Vtron Pty Ltd + +OUI:70B3D5B2D* + ID_OUI_FROM_DATABASE=Plexus + +OUI:70B3D5B2E* + ID_OUI_FROM_DATABASE=Green Access Ltd + +OUI:70B3D5B2F* + ID_OUI_FROM_DATABASE=Hermann Automation GmbH + +OUI:70B3D5B30* + ID_OUI_FROM_DATABASE=Systolé Hardware B.V. + +OUI:70B3D5B31* + ID_OUI_FROM_DATABASE=Qwave Inc + +OUI:70B3D5B33* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5B34* + ID_OUI_FROM_DATABASE=Medtronic + +OUI:70B3D5B35* + ID_OUI_FROM_DATABASE=Rexxam Co.,Ltd. + +OUI:70B3D5B36* + ID_OUI_FROM_DATABASE=Cetitec GmbH + +OUI:70B3D5B37* + ID_OUI_FROM_DATABASE=CODEC Co., Ltd. + +OUI:70B3D5B38* + ID_OUI_FROM_DATABASE=GoTrustID Inc. + +OUI:70B3D5B39* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5B3A* + ID_OUI_FROM_DATABASE=Adigitalmedia + +OUI:70B3D5B3B* + ID_OUI_FROM_DATABASE=Insitu, Inc + +OUI:70B3D5B3C* + ID_OUI_FROM_DATABASE=DORLET SAU + +OUI:70B3D5B3D* + ID_OUI_FROM_DATABASE=Inras GmbH + +OUI:70B3D5B3E* + ID_OUI_FROM_DATABASE=Paradigm Communication Systems Ltd + +OUI:70B3D5B3F* + ID_OUI_FROM_DATABASE=Orbit International + +OUI:70B3D5B40* + ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd + +OUI:70B3D5B41* + ID_OUI_FROM_DATABASE=T&M Media Pty Ltd + +OUI:70B3D5B43* + ID_OUI_FROM_DATABASE=ZAO ZEO + +OUI:70B3D5B44* + ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD. + +OUI:70B3D5B46* + ID_OUI_FROM_DATABASE=FAS Electronics (Fujian) Co.,LTD. + +OUI:70B3D5B47* + ID_OUI_FROM_DATABASE=DSIT Solutions LTD + +OUI:70B3D5B48* + ID_OUI_FROM_DATABASE=DWQ Informatikai Tanacsado es Vezerlestechnikai KFT + +OUI:70B3D5B49* + ID_OUI_FROM_DATABASE=ANALOGICS TECH INDIA LTD + +OUI:70B3D5B4A* + ID_OUI_FROM_DATABASE=MEDEX + +OUI:70B3D5B4D* + ID_OUI_FROM_DATABASE=Avidbots Corporation + +OUI:70B3D5B4F* + ID_OUI_FROM_DATABASE=AvMap srlu + +OUI:70B3D5B50* + ID_OUI_FROM_DATABASE=iGrid T&D + +OUI:70B3D5B51* + ID_OUI_FROM_DATABASE=Critical Link LLC + +OUI:70B3D5B52* + ID_OUI_FROM_DATABASE=AEye, Inc. + +OUI:70B3D5B53* + ID_OUI_FROM_DATABASE=Revolution Retail Systems, LLC + +OUI:70B3D5B55* + ID_OUI_FROM_DATABASE=CTAG - ESG36871424 + +OUI:70B3D5B56* + ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. + +OUI:70B3D5B58* + ID_OUI_FROM_DATABASE=INTERNET PROTOCOLO LOGICA SL + +OUI:70B3D5B59* + ID_OUI_FROM_DATABASE=FutureTechnologyLaboratories INC. + +OUI:70B3D5B5A* + ID_OUI_FROM_DATABASE=GTI Technologies Inc + +OUI:70B3D5B5B* + ID_OUI_FROM_DATABASE=DynaMount LLC + +OUI:70B3D5B5C* + ID_OUI_FROM_DATABASE=Prozess Technologie + +OUI:70B3D5B5D* + ID_OUI_FROM_DATABASE=SHANDHAI LANDLEAF ARCHITECTURE TECHNOLOGY CO.,LTD + +OUI:70B3D5B5E* + ID_OUI_FROM_DATABASE=Dynics + +OUI:70B3D5B5F* + ID_OUI_FROM_DATABASE=CRDMDEVEOPPEMENTS + +OUI:70B3D5B60* + ID_OUI_FROM_DATABASE=ZAO ZEO + +OUI:70B3D5B62* + ID_OUI_FROM_DATABASE=Sakura Seiki Co.,Ltd. + +OUI:70B3D5B64* + ID_OUI_FROM_DATABASE=OSUNG LST CO.,LTD. + +OUI:70B3D5B65* + ID_OUI_FROM_DATABASE=Rotem Industry LTD + +OUI:70B3D5B66* + ID_OUI_FROM_DATABASE=Silent Gliss International Ltd + +OUI:70B3D5B67* + ID_OUI_FROM_DATABASE=RedWave Labs Ltd + +OUI:70B3D5B6A* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D5B6B* + ID_OUI_FROM_DATABASE=Cambria Corporation + +OUI:70B3D5B6C* + ID_OUI_FROM_DATABASE=GHM-Messtechnik GmbH (Standort IMTRON) + +OUI:70B3D5B6D* + ID_OUI_FROM_DATABASE=Movis + +OUI:70B3D5B6E* + ID_OUI_FROM_DATABASE=Edgeware AB + +OUI:70B3D5B71* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5B72* + ID_OUI_FROM_DATABASE=UB330.net d.o.o. + +OUI:70B3D5B73* + ID_OUI_FROM_DATABASE=Cetto Industries + +OUI:70B3D5B74* + ID_OUI_FROM_DATABASE=OnYield Inc Ltd + +OUI:70B3D5B75* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D5B76* + ID_OUI_FROM_DATABASE=ATL-SD + +OUI:70B3D5B77* + ID_OUI_FROM_DATABASE=Motec Pty Ltd + +OUI:70B3D5B78* + ID_OUI_FROM_DATABASE=HOERMANN GmbH + +OUI:70B3D5B7A* + ID_OUI_FROM_DATABASE=MAHLE + +OUI:70B3D5B7C* + ID_OUI_FROM_DATABASE=Electronic Navigation Ltd + +OUI:70B3D5B7D* + ID_OUI_FROM_DATABASE=LOGIX ITS Inc + +OUI:70B3D5B7E* + ID_OUI_FROM_DATABASE=Elbit Systems of America + +OUI:70B3D5B7F* + ID_OUI_FROM_DATABASE=JSK System + +OUI:70B3D5B80* + ID_OUI_FROM_DATABASE=BIGHOUSE.,INC. + +OUI:70B3D5B81* + ID_OUI_FROM_DATABASE=Instro Precision Limited + +OUI:70B3D5B82* + ID_OUI_FROM_DATABASE=Lookout Portable Security + +OUI:70B3D5B84* + ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies + +OUI:70B3D5B85* + ID_OUI_FROM_DATABASE=Fenotech Inc. + +OUI:70B3D5B87* + ID_OUI_FROM_DATABASE=CAITRON GmbH + +OUI:70B3D5B88* + ID_OUI_FROM_DATABASE=ARP Corporation + +OUI:70B3D5B89* + ID_OUI_FROM_DATABASE=IDA + +OUI:70B3D5B8A* + ID_OUI_FROM_DATABASE=Nexus Tech. VN + +OUI:70B3D5B8B* + ID_OUI_FROM_DATABASE=Profound Medical Inc. + +OUI:70B3D5B8C* + ID_OUI_FROM_DATABASE=ePOINT Embedded Computing Limited + +OUI:70B3D5B8D* + ID_OUI_FROM_DATABASE=JungwooEng Co., Ltd + +OUI:70B3D5B8E* + ID_OUI_FROM_DATABASE=UR FOG S.R.L. + +OUI:70B3D5B8F* + ID_OUI_FROM_DATABASE=Assembly Contracts Ltd + +OUI:70B3D5B91* + ID_OUI_FROM_DATABASE=Dynetics, Inc. + +OUI:70B3D5B93* + ID_OUI_FROM_DATABASE=INTERNET PROTOCOLO LOGICA SL + +OUI:70B3D5B94* + ID_OUI_FROM_DATABASE=Cygnetic Technologies (Pty) Ltd + +OUI:70B3D5B96* + ID_OUI_FROM_DATABASE=Oculii + +OUI:70B3D5B97* + ID_OUI_FROM_DATABASE=Canam Technology, Inc. + +OUI:70B3D5B98* + ID_OUI_FROM_DATABASE=GSF Corporation Pte Ltd + +OUI:70B3D5B99* + ID_OUI_FROM_DATABASE=DomoSafety S.A. + +OUI:70B3D5B9A* + ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC + +OUI:70B3D5B9B* + ID_OUI_FROM_DATABASE=Elektronik Art + +OUI:70B3D5B9C* + ID_OUI_FROM_DATABASE=EDCO Technology 1993 ltd + +OUI:70B3D5B9D* + ID_OUI_FROM_DATABASE=Conclusive Engineering + +OUI:70B3D5B9E* + ID_OUI_FROM_DATABASE=POLSYSTEM SI SP. Z O.O., S.K.A. + +OUI:70B3D5B9F* + ID_OUI_FROM_DATABASE=Yuksek Kapasite Radyolink Sistemleri San. ve Tic. A.S. + +OUI:70B3D5BA1* + ID_OUI_FROM_DATABASE=Cathwell AS + +OUI:70B3D5BA2* + ID_OUI_FROM_DATABASE=MAMAC Systems, Inc. + +OUI:70B3D5BA3* + ID_OUI_FROM_DATABASE=TIAMA + +OUI:70B3D5BA4* + ID_OUI_FROM_DATABASE=EIWA GIKEN INC. + +OUI:70B3D5BA5* + ID_OUI_FROM_DATABASE=fpgalabs.com + +OUI:70B3D5BA6* + ID_OUI_FROM_DATABASE=Gluon Solutions Inc. + +OUI:70B3D5BA7* + ID_OUI_FROM_DATABASE=Digital Yacht Ltd + +OUI:70B3D5BA8* + ID_OUI_FROM_DATABASE=Controlled Power Company + +OUI:70B3D5BA9* + ID_OUI_FROM_DATABASE=Alma + +OUI:70B3D5BAA* + ID_OUI_FROM_DATABASE=Device Solutions Ltd + +OUI:70B3D5BAB* + ID_OUI_FROM_DATABASE=Axotec Technologies GmbH + +OUI:70B3D5BAC* + ID_OUI_FROM_DATABASE=AdInte, inc. + +OUI:70B3D5BAD* + ID_OUI_FROM_DATABASE=Technik & Design GmbH + +OUI:70B3D5BAE* + ID_OUI_FROM_DATABASE=WARECUBE,INC + +OUI:70B3D5BAF* + ID_OUI_FROM_DATABASE=SYS TEC electronic GmbH + +OUI:70B3D5BB0* + ID_OUI_FROM_DATABASE=WICELL TECHNOLOGY + +OUI:70B3D5BB1* + ID_OUI_FROM_DATABASE=Lumiplan Duhamel + +OUI:70B3D5BB2* + ID_OUI_FROM_DATABASE=Mettler Toledo + +OUI:70B3D5BB3* + ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC + +OUI:70B3D5BB4* + ID_OUI_FROM_DATABASE=Integritech + +OUI:70B3D5BB5* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D5BB6* + ID_OUI_FROM_DATABASE=Franke Aquarotter GmbH + +OUI:70B3D5BB7* + ID_OUI_FROM_DATABASE=Innoflight, Inc. + +OUI:70B3D5BB8* + ID_OUI_FROM_DATABASE=Al Kamel Systems S.L. + +OUI:70B3D5BB9* + ID_OUI_FROM_DATABASE=KOSMEK.Ltd + +OUI:70B3D5BBA* + ID_OUI_FROM_DATABASE=Samriddi Automations Pvt. Ltd. + +OUI:70B3D5BBB* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D5BBD* + ID_OUI_FROM_DATABASE=Providius Corp + +OUI:70B3D5BBE* + ID_OUI_FROM_DATABASE=Sunrise Systems Electronics Co. Inc. + +OUI:70B3D5BBF* + ID_OUI_FROM_DATABASE=Ensys srl + +OUI:70B3D5BC0* + ID_OUI_FROM_DATABASE=SENSO2ME + +OUI:70B3D5BC1* + ID_OUI_FROM_DATABASE=Abionic + +OUI:70B3D5BC2* + ID_OUI_FROM_DATABASE=DWEWOONG ELECTRIC Co., Ltd. + +OUI:70B3D5BC3* + ID_OUI_FROM_DATABASE=eWireless + +OUI:70B3D5BC4* + ID_OUI_FROM_DATABASE=Digital Media Professionals + +OUI:70B3D5BC5* + ID_OUI_FROM_DATABASE=U&R GmbH Hardware- und Systemdesign + +OUI:70B3D5BC6* + ID_OUI_FROM_DATABASE=Hatteland Display AS + +OUI:70B3D5BC9* + ID_OUI_FROM_DATABASE=Yite technology + +OUI:70B3D5BCA* + ID_OUI_FROM_DATABASE=Deymed Diagnostic + +OUI:70B3D5BCB* + ID_OUI_FROM_DATABASE=Smart Vision Lights + +OUI:70B3D5BCC* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5BCD* + ID_OUI_FROM_DATABASE=Sasken Technologies Ltd + +OUI:70B3D5BCE* + ID_OUI_FROM_DATABASE=YAWATA ELECTRIC INDUSTRIAL CO.,LTD. + +OUI:70B3D5BCF* + ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC + +OUI:70B3D5BD0* + ID_OUI_FROM_DATABASE=SHS SRL + +OUI:70B3D5BD1* + ID_OUI_FROM_DATABASE=CableLabs + +OUI:70B3D5BD2* + ID_OUI_FROM_DATABASE=Burk Technology + +OUI:70B3D5BD3* + ID_OUI_FROM_DATABASE=FOTONA D.D. + +OUI:70B3D5BD4* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D5BD5* + ID_OUI_FROM_DATABASE=Synics AG + +OUI:70B3D5BD6* + ID_OUI_FROM_DATABASE=Consarc Corporation + +OUI:70B3D5BD8* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5BD9* + ID_OUI_FROM_DATABASE=SolwayTech + +OUI:70B3D5BDA* + ID_OUI_FROM_DATABASE=5-D Systems, Inc. + +OUI:70B3D5BDD* + ID_OUI_FROM_DATABASE=CDR SRL + +OUI:70B3D5BDF* + ID_OUI_FROM_DATABASE=H2O-YUG LLC + +OUI:70B3D5BE0* + ID_OUI_FROM_DATABASE=Cognosos, Inc. + +OUI:70B3D5BE1* + ID_OUI_FROM_DATABASE=FeCon GmbH + +OUI:70B3D5BE3* + ID_OUI_FROM_DATABASE=Saratov Electrounit Production Plant named after Sergo Ordzhonikidze, OJSC + +OUI:70B3D5BE4* + ID_OUI_FROM_DATABASE=Kunshan excellent Intelligent Technology Co., Ltd. + +OUI:70B3D5BE5* + ID_OUI_FROM_DATABASE=Pantec Engineering AG + +OUI:70B3D5BE6* + ID_OUI_FROM_DATABASE=CCII Systems (Pty) Ltd + +OUI:70B3D5BE7* + ID_OUI_FROM_DATABASE=Syscom Instruments SA + +OUI:70B3D5BE8* + ID_OUI_FROM_DATABASE=AndFun Co.,Ltd. + +OUI:70B3D5BE9* + ID_OUI_FROM_DATABASE=Telecast Inc. + +OUI:70B3D5BEA* + ID_OUI_FROM_DATABASE=Virtuosys Ltd + +OUI:70B3D5BEC* + ID_OUI_FROM_DATABASE=Tokyo Communication Equipment MFG Co.,ltd. + +OUI:70B3D5BED* + ID_OUI_FROM_DATABASE=Itrinegy Ltd. + +OUI:70B3D5BEE* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D5BEF* + ID_OUI_FROM_DATABASE=Sensortech Systems Inc. + +OUI:70B3D5BF1* + ID_OUI_FROM_DATABASE=Flashnet SRL + +OUI:70B3D5BF2* + ID_OUI_FROM_DATABASE=TWIN DEVELOPMENT + +OUI:70B3D5BF3* + ID_OUI_FROM_DATABASE=CG-WIRELESS + +OUI:70B3D5BF5* + ID_OUI_FROM_DATABASE=Acacia Research + +OUI:70B3D5BF6* + ID_OUI_FROM_DATABASE=comtac AG + +OUI:70B3D5BF8* + ID_OUI_FROM_DATABASE=RCH ITALIA SPA + +OUI:70B3D5BF9* + ID_OUI_FROM_DATABASE=Okolab Srl + +OUI:70B3D5BFA* + ID_OUI_FROM_DATABASE=NESA SRL + +OUI:70B3D5BFB* + ID_OUI_FROM_DATABASE=Sensor 42 + +OUI:70B3D5BFC* + ID_OUI_FROM_DATABASE=Vishay Nobel AB + +OUI:70B3D5BFD* + ID_OUI_FROM_DATABASE=Lumentum + +OUI:70B3D5BFE* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5BFF* + ID_OUI_FROM_DATABASE=Sunsa, Inc + +OUI:70B3D5C00* + ID_OUI_FROM_DATABASE=BESO sp. z o.o. + +OUI:70B3D5C01* + ID_OUI_FROM_DATABASE=SmartGuard LLC + +OUI:70B3D5C03* + ID_OUI_FROM_DATABASE=XAVi Technologies Corp. + +OUI:70B3D5C04* + ID_OUI_FROM_DATABASE=Prolan Zrt. + +OUI:70B3D5C05* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D5C06* + ID_OUI_FROM_DATABASE=XotonicsMED GmbH + +OUI:70B3D5C07* + ID_OUI_FROM_DATABASE=ARECO + +OUI:70B3D5C08* + ID_OUI_FROM_DATABASE=Talleres de Escoriaza SA + +OUI:70B3D5C09* + ID_OUI_FROM_DATABASE=RCH Vietnam Limited Liability Company + +OUI:70B3D5C0A* + ID_OUI_FROM_DATABASE=Infosocket Co., Ltd. + +OUI:70B3D5C0B* + ID_OUI_FROM_DATABASE=FSTUDIO CO LTD + +OUI:70B3D5C0C* + ID_OUI_FROM_DATABASE=Tech4Race + +OUI:70B3D5C0E* + ID_OUI_FROM_DATABASE=SYSDEV Srl + +OUI:70B3D5C0F* + ID_OUI_FROM_DATABASE=Honeywell Safety Products USA, Inc + +OUI:70B3D5C10* + ID_OUI_FROM_DATABASE=Scanvaegt Systems A/S + +OUI:70B3D5C11* + ID_OUI_FROM_DATABASE=Ariston Thermo s.p.a. + +OUI:70B3D5C12* + ID_OUI_FROM_DATABASE=Beijing Wisetone Information Technology Co.,Ltd. + +OUI:70B3D5C14* + ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. + +OUI:70B3D5C15* + ID_OUI_FROM_DATABASE=Sensobox GmbH + +OUI:70B3D5C16* + ID_OUI_FROM_DATABASE=Southern Innovation + +OUI:70B3D5C17* + ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC + +OUI:70B3D5C1A* + ID_OUI_FROM_DATABASE=Xylon + +OUI:70B3D5C1B* + ID_OUI_FROM_DATABASE=Labinvent JSC + +OUI:70B3D5C1C* + ID_OUI_FROM_DATABASE=D.E.M. SPA + +OUI:70B3D5C1D* + ID_OUI_FROM_DATABASE=Kranze Technology Solutions + +OUI:70B3D5C1F* + ID_OUI_FROM_DATABASE=Behr Technologies Inc + +OUI:70B3D5C20* + ID_OUI_FROM_DATABASE=Mipot S.p.a. + +OUI:70B3D5C21* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5C22* + ID_OUI_FROM_DATABASE=Skyriver Communications Inc. + +OUI:70B3D5C24* + ID_OUI_FROM_DATABASE=Elbit Systems of America + +OUI:70B3D5C25* + ID_OUI_FROM_DATABASE=speedsignal GmbH + +OUI:70B3D5C26* + ID_OUI_FROM_DATABASE=Triple Play Communications + +OUI:70B3D5C27* + ID_OUI_FROM_DATABASE=GD Mission Systems + +OUI:70B3D5C29* + ID_OUI_FROM_DATABASE=SOFTLAND INDIA LTD + +OUI:70B3D5C2A* + ID_OUI_FROM_DATABASE=Array Telepresence + +OUI:70B3D5C2B* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D5C2C* + ID_OUI_FROM_DATABASE=Dromont S.p.A. + +OUI:70B3D5C2D* + ID_OUI_FROM_DATABASE=Ensotech Limited + +OUI:70B3D5C2E* + ID_OUI_FROM_DATABASE=Triax A/S + +OUI:70B3D5C2F* + ID_OUI_FROM_DATABASE=ATBiS Co.,Ltd + +OUI:70B3D5C31* + ID_OUI_FROM_DATABASE=German Power GmbH + +OUI:70B3D5C32* + ID_OUI_FROM_DATABASE=INFRASAFE/ ADVANTOR SYSTEMS + +OUI:70B3D5C33* + ID_OUI_FROM_DATABASE=Dandong Dongfang Measurement & Control Technology Co., Ltd. + +OUI:70B3D5C34* + ID_OUI_FROM_DATABASE=Technical Panels Co. Ltd. + +OUI:70B3D5C35* + ID_OUI_FROM_DATABASE=Vibrationmaster + +OUI:70B3D5C37* + ID_OUI_FROM_DATABASE=Keycom Corp. + +OUI:70B3D5C38* + ID_OUI_FROM_DATABASE=CRESPRIT INC. + +OUI:70B3D5C39* + ID_OUI_FROM_DATABASE=MeshWorks Wireless Oy + +OUI:70B3D5C3A* + ID_OUI_FROM_DATABASE=HAN CHANG + +OUI:70B3D5C3B* + ID_OUI_FROM_DATABASE=Vironova AB + +OUI:70B3D5C3C* + ID_OUI_FROM_DATABASE=PEEK TRAFFIC + +OUI:70B3D5C3D* + ID_OUI_FROM_DATABASE=CISTECH Solutions + +OUI:70B3D5C3E* + ID_OUI_FROM_DATABASE=DOSADORES ALLTRONIC + +OUI:70B3D5C3F* + ID_OUI_FROM_DATABASE=Code Blue Corporation + +OUI:70B3D5C40* + ID_OUI_FROM_DATABASE=HongSeok Ltd. + +OUI:70B3D5C41* + ID_OUI_FROM_DATABASE=Merlin CSI + +OUI:70B3D5C42* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5C43* + ID_OUI_FROM_DATABASE=Future Skies + +OUI:70B3D5C44* + ID_OUI_FROM_DATABASE=Franz Kessler GmbH + +OUI:70B3D5C45* + ID_OUI_FROM_DATABASE=Stiebel Eltron GmbH + +OUI:70B3D5C49* + ID_OUI_FROM_DATABASE=BTG Instruments AB + +OUI:70B3D5C4A* + ID_OUI_FROM_DATABASE=TIAMA + +OUI:70B3D5C4B* + ID_OUI_FROM_DATABASE=ANKER-EAST + +OUI:70B3D5C4C* + ID_OUI_FROM_DATABASE=VTC Digicom + +OUI:70B3D5C4D* + ID_OUI_FROM_DATABASE=RADA Electronics Industries Ltd. + +OUI:70B3D5C4E* + ID_OUI_FROM_DATABASE=ARKRAY, Inc. Kyoto Laboratory + +OUI:70B3D5C4F* + ID_OUI_FROM_DATABASE=AE Van de Vliet BVBA + +OUI:70B3D5C50* + ID_OUI_FROM_DATABASE=Combilent + +OUI:70B3D5C51* + ID_OUI_FROM_DATABASE=Innotas Elektronik GmbH + +OUI:70B3D5C52* + ID_OUI_FROM_DATABASE=sensorway + +OUI:70B3D5C53* + ID_OUI_FROM_DATABASE=S Labs sp. z o.o. + +OUI:70B3D5C54* + ID_OUI_FROM_DATABASE=Flexsolution APS + +OUI:70B3D5C55* + ID_OUI_FROM_DATABASE=Intelligent Energy Ltd + +OUI:70B3D5C56* + ID_OUI_FROM_DATABASE=TELETASK + +OUI:70B3D5C58* + ID_OUI_FROM_DATABASE=RMI Laser LLC + +OUI:70B3D5C59* + ID_OUI_FROM_DATABASE=R Cubed Engineering, LLC + +OUI:70B3D5C5A* + ID_OUI_FROM_DATABASE=Commsignia Ltd. + +OUI:70B3D5C5B* + ID_OUI_FROM_DATABASE=ACD Elektronik GmbH + +OUI:70B3D5C5C* + ID_OUI_FROM_DATABASE=Layer Logic Inc + +OUI:70B3D5C5D* + ID_OUI_FROM_DATABASE=FOSHAN SHILANTIAN NETWORK S.T. CO., LTD. + +OUI:70B3D5C5F* + ID_OUI_FROM_DATABASE=Clean-Lasersysteme GmbH + +OUI:70B3D5C60* + ID_OUI_FROM_DATABASE=Gogo BA + +OUI:70B3D5C61* + ID_OUI_FROM_DATABASE=JC HUNTER TECHNOLOGIES + +OUI:70B3D5C62* + ID_OUI_FROM_DATABASE=WIZNOVA + +OUI:70B3D5C63* + ID_OUI_FROM_DATABASE=Xentech Solutions Limited + +OUI:70B3D5C64* + ID_OUI_FROM_DATABASE=SYS TEC electronic GmbH + +OUI:70B3D5C65* + ID_OUI_FROM_DATABASE=PEEK TRAFFIC + +OUI:70B3D5C66* + ID_OUI_FROM_DATABASE=Blue Access Inc + +OUI:70B3D5C67* + ID_OUI_FROM_DATABASE=Collini Dienstleistungs GmbH + +OUI:70B3D5C68* + ID_OUI_FROM_DATABASE=Mini Solution Co. Ltd. + +OUI:70B3D5C69* + ID_OUI_FROM_DATABASE=AZ-TECHNOLOGY SDN BHD + +OUI:70B3D5C6A* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5C6C* + ID_OUI_FROM_DATABASE=McQ Inc + +OUI:70B3D5C6D* + ID_OUI_FROM_DATABASE=Cyviz AS + +OUI:70B3D5C6E* + ID_OUI_FROM_DATABASE=Orion Technologies, LLC + +OUI:70B3D5C6F* + ID_OUI_FROM_DATABASE=nyantec GmbH + +OUI:70B3D5C70* + ID_OUI_FROM_DATABASE=Magnetek + +OUI:70B3D5C73* + ID_OUI_FROM_DATABASE=C.D.N.CORPORATION + +OUI:70B3D5C74* + ID_OUI_FROM_DATABASE=Qtechnology A/S + +OUI:70B3D5C76* + ID_OUI_FROM_DATABASE=ELA INNOVATION + +OUI:70B3D5C77* + ID_OUI_FROM_DATABASE=Yönnet Akıllı Bina ve Otomasyon Sistemleri + +OUI:70B3D5C78* + ID_OUI_FROM_DATABASE=NETA Elektronik AS + +OUI:70B3D5C79* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5C7A* + ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD. + +OUI:70B3D5C7B* + ID_OUI_FROM_DATABASE=EM Clarity Pty Ltd + +OUI:70B3D5C7D* + ID_OUI_FROM_DATABASE=Metatronics B.V. + +OUI:70B3D5C7E* + ID_OUI_FROM_DATABASE=BirdDog Australia + +OUI:70B3D5C7F* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5C80* + ID_OUI_FROM_DATABASE=Link Care Services + +OUI:70B3D5C81* + ID_OUI_FROM_DATABASE=DSP DESIGN + +OUI:70B3D5C82* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D5C83* + ID_OUI_FROM_DATABASE=CertusNet Inc. + +OUI:70B3D5C84* + ID_OUI_FROM_DATABASE=Linc Technology Corporation dba Data-Linc Group + +OUI:70B3D5C85* + ID_OUI_FROM_DATABASE=Solid State Disks Ltd + +OUI:70B3D5C86* + ID_OUI_FROM_DATABASE=Woodam Co., Ltd. + +OUI:70B3D5C87* + ID_OUI_FROM_DATABASE=Siemens AG + +OUI:70B3D5C88* + ID_OUI_FROM_DATABASE=SINED srl + +OUI:70B3D5C89* + ID_OUI_FROM_DATABASE=ARD + +OUI:70B3D5C8A* + ID_OUI_FROM_DATABASE=WTE Limited + +OUI:70B3D5C8B* + ID_OUI_FROM_DATABASE=Asia Pacific Satellite Coummunication Inc. + +OUI:70B3D5C8C* + ID_OUI_FROM_DATABASE=Rollogo Limited + +OUI:70B3D5C8D* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D5C8E* + ID_OUI_FROM_DATABASE=Coral Telecom Limited + +OUI:70B3D5C8F* + ID_OUI_FROM_DATABASE=TRIDENT INFOSOL PVT LTD + +OUI:70B3D5C91* + ID_OUI_FROM_DATABASE=Grossenbacher Systeme AG + +OUI:70B3D5C92* + ID_OUI_FROM_DATABASE=Unitro Fleischmann + +OUI:70B3D5C93* + ID_OUI_FROM_DATABASE=GMI Ltd + +OUI:70B3D5C94* + ID_OUI_FROM_DATABASE=Vars Technology + +OUI:70B3D5C95* + ID_OUI_FROM_DATABASE=Chengdu Meihuan Technology Co., Ltd + +OUI:70B3D5C96* + ID_OUI_FROM_DATABASE=UNI DIMENXI SDN BHD + +OUI:70B3D5C97* + ID_OUI_FROM_DATABASE=CSINFOTEL + +OUI:70B3D5C98* + ID_OUI_FROM_DATABASE=Trust Automation + +OUI:70B3D5C9A* + ID_OUI_FROM_DATABASE=Todd Digital Limited + +OUI:70B3D5C9B* + ID_OUI_FROM_DATABASE=Tieto Sweden AB + +OUI:70B3D5C9C* + ID_OUI_FROM_DATABASE=Connected Response + +OUI:70B3D5C9D* + ID_OUI_FROM_DATABASE=APG Cash Drawer, LLC + +OUI:70B3D5C9E* + ID_OUI_FROM_DATABASE=FUKUDA SANGYO CO., LTD. + +OUI:70B3D5C9F* + ID_OUI_FROM_DATABASE=Triax A/S + +OUI:70B3D5CA1* + ID_OUI_FROM_DATABASE=Waldo System + +OUI:70B3D5CA2* + ID_OUI_FROM_DATABASE=De Haardt bv + +OUI:70B3D5CA3* + ID_OUI_FROM_DATABASE=Saankhya Labs Private Limited + +OUI:70B3D5CA4* + ID_OUI_FROM_DATABASE=Netemera Sp. z o.o. + +OUI:70B3D5CA5* + ID_OUI_FROM_DATABASE=PTS Technologies Pte Ltd + +OUI:70B3D5CA7* + ID_OUI_FROM_DATABASE=i-View Communication Inc. + +OUI:70B3D5CA8* + ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. + +OUI:70B3D5CA9* + ID_OUI_FROM_DATABASE=Nxcontrol system Co., Ltd. + +OUI:70B3D5CAA* + ID_OUI_FROM_DATABASE=Bel Power Solutions GmbH + +OUI:70B3D5CAB* + ID_OUI_FROM_DATABASE=NOTICE Co., Ltd. + +OUI:70B3D5CAC* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5CAE* + ID_OUI_FROM_DATABASE=THEMA + +OUI:70B3D5CAF* + ID_OUI_FROM_DATABASE=DAVE SRL + +OUI:70B3D5CB0* + ID_OUI_FROM_DATABASE=Ossiaco + +OUI:70B3D5CB1* + ID_OUI_FROM_DATABASE=RADAR + +OUI:70B3D5CB2* + ID_OUI_FROM_DATABASE=SECLAB + +OUI:70B3D5CB3* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D5CB4* + ID_OUI_FROM_DATABASE=Planewave Instruments + +OUI:70B3D5CB6* + ID_OUI_FROM_DATABASE=Kuebrich Ingeniergesellschaft mbh & Co. KG + +OUI:70B3D5CB7* + ID_OUI_FROM_DATABASE=HKC Limited + +OUI:70B3D5CB8* + ID_OUI_FROM_DATABASE=Verti Tecnologia + +OUI:70B3D5CB9* + ID_OUI_FROM_DATABASE=JSC «SATIS-TL-94» + +OUI:70B3D5CBA* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D5CBC* + ID_OUI_FROM_DATABASE=Procon Electronics Pty Ltd + +OUI:70B3D5CBD* + ID_OUI_FROM_DATABASE=Preo Industries Far East Limited + +OUI:70B3D5CBE* + ID_OUI_FROM_DATABASE=Ensura Solutions BV + +OUI:70B3D5CC1* + ID_OUI_FROM_DATABASE=BEEcube Inc. + +OUI:70B3D5CC2* + ID_OUI_FROM_DATABASE=LSC Lighting Systems (Aust) Pty Ltd + +OUI:70B3D5CC3* + ID_OUI_FROM_DATABASE=Fidalia Networks Inc + +OUI:70B3D5CC4* + ID_OUI_FROM_DATABASE=Benchmark Electronics BV + +OUI:70B3D5CC5* + ID_OUI_FROM_DATABASE=Intecom + +OUI:70B3D5CC6* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5CC8* + ID_OUI_FROM_DATABASE=PROFEN COMMUNICATIONS + +OUI:70B3D5CC9* + ID_OUI_FROM_DATABASE=Rapiscan Systems + +OUI:70B3D5CCA* + ID_OUI_FROM_DATABASE=SIEMENS AS + +OUI:70B3D5CCB* + ID_OUI_FROM_DATABASE=RealD + +OUI:70B3D5CCC* + ID_OUI_FROM_DATABASE=AEC s.r.l. + +OUI:70B3D5CCD* + ID_OUI_FROM_DATABASE=Suzhou PowerCore Technology Co.,Ltd. + +OUI:70B3D5CCE* + ID_OUI_FROM_DATABASE=Proconex 2010 Inc. + +OUI:70B3D5CCF* + ID_OUI_FROM_DATABASE=Netberg + +OUI:70B3D5CD0* + ID_OUI_FROM_DATABASE=Ellenex Pty Ltd + +OUI:70B3D5CD1* + ID_OUI_FROM_DATABASE=Cannex Technology Inc. + +OUI:70B3D5CD2* + ID_OUI_FROM_DATABASE=HBH Microwave GmbH + +OUI:70B3D5CD3* + ID_OUI_FROM_DATABASE=Controlrad + +OUI:70B3D5CD4* + ID_OUI_FROM_DATABASE=Southern Ground Audio LLC + +OUI:70B3D5CD5* + ID_OUI_FROM_DATABASE=Apantac LLC + +OUI:70B3D5CD6* + ID_OUI_FROM_DATABASE=VideoRay LLC + +OUI:70B3D5CD7* + ID_OUI_FROM_DATABASE=AutomationX GmbH + +OUI:70B3D5CD9* + ID_OUI_FROM_DATABASE=Peter Huber Kaeltemaschinenbau GmbH + +OUI:70B3D5CDA* + ID_OUI_FROM_DATABASE=VITEC + +OUI:70B3D5CDB* + ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd + +OUI:70B3D5CDC* + ID_OUI_FROM_DATABASE=Dat-Con d.o.o. + +OUI:70B3D5CDE* + ID_OUI_FROM_DATABASE=Multipure International + +OUI:70B3D5CDF* + ID_OUI_FROM_DATABASE=3D Printing Specialists + +OUI:70B3D5CE1* + ID_OUI_FROM_DATABASE=EA Elektroautomatik GmbH & Co. KG + +OUI:70B3D5CE2* + ID_OUI_FROM_DATABASE=Centero + +OUI:70B3D5CE3* + ID_OUI_FROM_DATABASE=Dalcnet srl + +OUI:70B3D5CE4* + ID_OUI_FROM_DATABASE=WAVES SYSTEM + +OUI:70B3D5CE5* + ID_OUI_FROM_DATABASE=GridBridge Inc + +OUI:70B3D5CE7* + ID_OUI_FROM_DATABASE=June Automation Singapore Pte. Ltd. + +OUI:70B3D5CE9* + ID_OUI_FROM_DATABASE=KINEMETRICS + +OUI:70B3D5CEA* + ID_OUI_FROM_DATABASE=Computerwise, Inc. + +OUI:70B3D5CED* + ID_OUI_FROM_DATABASE=Advanced Products Corporation Pte Ltd + +OUI:70B3D5CEF* + ID_OUI_FROM_DATABASE=Ellego Powertec Oy + +OUI:70B3D5CF0* + ID_OUI_FROM_DATABASE=SHENZHEN WITLINK CO.,LTD. + +OUI:70B3D5CF1* + ID_OUI_FROM_DATABASE=LightDec GmbH & Co. KG + +OUI:70B3D5CF2* + ID_OUI_FROM_DATABASE=tinnos + +OUI:70B3D5CF3* + ID_OUI_FROM_DATABASE=Mesh Motion Inc + +OUI:70B3D5CF4* + ID_OUI_FROM_DATABASE=Harbin Cheng Tian Technology Development Co., Ltd. + +OUI:70B3D5CF5* + ID_OUI_FROM_DATABASE=Petring Energietechnik GmbH + +OUI:70B3D5CF6* + ID_OUI_FROM_DATABASE=Tornado Modular Systems + +OUI:70B3D5CF7* + ID_OUI_FROM_DATABASE=GENTEC ELECTRO-OPTICS + +OUI:70B3D5CF8* + ID_OUI_FROM_DATABASE=Idneo Technologies S.A.U. + +OUI:70B3D5CFB* + ID_OUI_FROM_DATABASE=Screen Innovations + +OUI:70B3D5CFC* + ID_OUI_FROM_DATABASE=VEILUX INC. + +OUI:70B3D5CFD* + ID_OUI_FROM_DATABASE=iLOQ Oy + +OUI:70B3D5CFE* + ID_OUI_FROM_DATABASE=Secturion Systems + +OUI:70B3D5CFF* + ID_OUI_FROM_DATABASE=DTECH Labs, Inc. + +OUI:70B3D5D00* + ID_OUI_FROM_DATABASE=DKI Technology Co., Ltd + +OUI:70B3D5D01* + ID_OUI_FROM_DATABASE=Vision4ce Ltd + +OUI:70B3D5D02* + ID_OUI_FROM_DATABASE=Arctos Showlasertechnik GmbH + +OUI:70B3D5D05* + ID_OUI_FROM_DATABASE=Colmek + +OUI:70B3D5D07* + ID_OUI_FROM_DATABASE=Waversa Systems + +OUI:70B3D5D08* + ID_OUI_FROM_DATABASE=Veeco Instruments + +OUI:70B3D5D09* + ID_OUI_FROM_DATABASE=Rishaad Brown + +OUI:70B3D5D0A* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5D0C* + ID_OUI_FROM_DATABASE=Connor Winfield LTD + +OUI:70B3D5D0D* + ID_OUI_FROM_DATABASE=Logiwaste AB + +OUI:70B3D5D0E* + ID_OUI_FROM_DATABASE=Beijing Aumiwalker technology CO.,LTD + +OUI:70B3D5D10* + ID_OUI_FROM_DATABASE=Contec Americas Inc. + +OUI:70B3D5D11* + ID_OUI_FROM_DATABASE=EREE Electronique + +OUI:70B3D5D12* + ID_OUI_FROM_DATABASE=FIDELTRONIK POLAND SP. Z O.O. + +OUI:70B3D5D15* + ID_OUI_FROM_DATABASE=3DGence sp. z o.o. + +OUI:70B3D5D16* + ID_OUI_FROM_DATABASE=Monnit Corporation + +OUI:70B3D5D1A* + ID_OUI_FROM_DATABASE=Monnit Corporation + +OUI:70B3D5D1B* + ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. + +OUI:70B3D5D1C* + ID_OUI_FROM_DATABASE=Specialised Imaging Limited + +OUI:70B3D5D1E* + ID_OUI_FROM_DATABASE=Houston Radar LLC + +OUI:70B3D5D1F* + ID_OUI_FROM_DATABASE=Embsec AB + +OUI:70B3D5D20* + ID_OUI_FROM_DATABASE=Rheonics GmbH + +OUI:70B3D5D22* + ID_OUI_FROM_DATABASE=DEK Technologies + +OUI:70B3D5D23* + ID_OUI_FROM_DATABASE=COTT Electronics + +OUI:70B3D5D24* + ID_OUI_FROM_DATABASE=Microtronics Engineering GmbH + +OUI:70B3D5D25* + ID_OUI_FROM_DATABASE=ENGenesis + +OUI:70B3D5D26* + ID_OUI_FROM_DATABASE=MI Inc. + +OUI:70B3D5D27* + ID_OUI_FROM_DATABASE=Light field Lab + +OUI:70B3D5D28* + ID_OUI_FROM_DATABASE=Toshiba Electron Tubes & Devices Co., Ltd. + +OUI:70B3D5D29* + ID_OUI_FROM_DATABASE=Sportzcast + +OUI:70B3D5D2A* + ID_OUI_FROM_DATABASE=ITsynergy Ltd + +OUI:70B3D5D2B* + ID_OUI_FROM_DATABASE=StreamPlay Oy Ltd + +OUI:70B3D5D2D* + ID_OUI_FROM_DATABASE=Evolute Systems Private Limited + +OUI:70B3D5D2E* + ID_OUI_FROM_DATABASE=Coheros Oy + +OUI:70B3D5D2F* + ID_OUI_FROM_DATABASE=L.I.F.E. Corporation SA + +OUI:70B3D5D30* + ID_OUI_FROM_DATABASE=Leica Microsystems Ltd. Shanghai + +OUI:70B3D5D31* + ID_OUI_FROM_DATABASE=Solace Systems Inc. + +OUI:70B3D5D32* + ID_OUI_FROM_DATABASE=Euklis by GSG International + +OUI:70B3D5D33* + ID_OUI_FROM_DATABASE=VECTOR.CO.,LTD. + +OUI:70B3D5D34* + ID_OUI_FROM_DATABASE=G-PHILOS CO.,LTD + +OUI:70B3D5D36* + ID_OUI_FROM_DATABASE=Insitu Inc. + +OUI:70B3D5D37* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D5D38* + ID_OUI_FROM_DATABASE=Vista Research, Inc. + +OUI:70B3D5D39* + ID_OUI_FROM_DATABASE=ASHIDA Electronics Pvt. Ltd + +OUI:70B3D5D3A* + ID_OUI_FROM_DATABASE=PROMOMED RUS LLC + +OUI:70B3D5D3B* + ID_OUI_FROM_DATABASE=NimbeLink Corp + +OUI:70B3D5D3C* + ID_OUI_FROM_DATABASE=HRT + +OUI:70B3D5D3D* + ID_OUI_FROM_DATABASE=Netzikon GmbH + +OUI:70B3D5D3F* + ID_OUI_FROM_DATABASE=GLOBALCOM ENGINEERING SPA + +OUI:70B3D5D40* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5D41* + ID_OUI_FROM_DATABASE=KSE GmbH + +OUI:70B3D5D42* + ID_OUI_FROM_DATABASE=DSP DESIGN + +OUI:70B3D5D43* + ID_OUI_FROM_DATABASE=EZSYS Co., Ltd. + +OUI:70B3D5D44* + ID_OUI_FROM_DATABASE=ic-automation GmbH + +OUI:70B3D5D46* + ID_OUI_FROM_DATABASE=Contineo s.r.o. + +OUI:70B3D5D47* + ID_OUI_FROM_DATABASE=YotaScope Technologies Co., Ltd. + +OUI:70B3D5D48* + ID_OUI_FROM_DATABASE=HEADROOM Broadcast GmbH + +OUI:70B3D5D49* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:70B3D5D4A* + ID_OUI_FROM_DATABASE=OÜ ELIKO Tehnoloogia Arenduskeskus + +OUI:70B3D5D4B* + ID_OUI_FROM_DATABASE=Hermann Lümmen GmbH + +OUI:70B3D5D4C* + ID_OUI_FROM_DATABASE=Elystec Technology Co., Ltd + +OUI:70B3D5D4D* + ID_OUI_FROM_DATABASE=The Morey Corporation + +OUI:70B3D5D4E* + ID_OUI_FROM_DATABASE=FLSmidth + +OUI:70B3D5D4F* + ID_OUI_FROM_DATABASE=C-COM Satellite Systems Inc. + +OUI:70B3D5D50* + ID_OUI_FROM_DATABASE=GRIDSMART Technologies + +OUI:70B3D5D51* + ID_OUI_FROM_DATABASE=Azcom Technology S.r.l. + +OUI:70B3D5D54* + ID_OUI_FROM_DATABASE=JL World Corporation Limited + +OUI:70B3D5D55* + ID_OUI_FROM_DATABASE=WM Design s.r.o + +OUI:70B3D5D56* + ID_OUI_FROM_DATABASE=KRONOTECH SRL + +OUI:70B3D5D57* + ID_OUI_FROM_DATABASE=TRIUMPH BOARD a.s. + +OUI:70B3D5D58* + ID_OUI_FROM_DATABASE=Idyllic Engineering Pte Ltd + +OUI:70B3D5D59* + ID_OUI_FROM_DATABASE=WyreStorm Technologies Ltd + +OUI:70B3D5D5A* + ID_OUI_FROM_DATABASE=WyreStorm Technologies Ltd + +OUI:70B3D5D5B* + ID_OUI_FROM_DATABASE=WyreStorm Technologies Ltd + +OUI:70B3D5D5C* + ID_OUI_FROM_DATABASE=Critical Link LLC + +OUI:70B3D5D5F* + ID_OUI_FROM_DATABASE=Core Balance Co., Ltd. + +OUI:70B3D5D60* + ID_OUI_FROM_DATABASE=Flintab AB + +OUI:70B3D5D61* + ID_OUI_FROM_DATABASE=VITEC + +OUI:70B3D5D62* + ID_OUI_FROM_DATABASE=Andasis Elektronik San. ve Tic. A.Ş. + +OUI:70B3D5D63* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5D64* + ID_OUI_FROM_DATABASE=Mettler Toledo + +OUI:70B3D5D65* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5D66* + ID_OUI_FROM_DATABASE=Ascendent Technology Group + +OUI:70B3D5D67* + ID_OUI_FROM_DATABASE=ALPHA Corporation + +OUI:70B3D5D69* + ID_OUI_FROM_DATABASE=Thermo Fisher Scientific + +OUI:70B3D5D6A* + ID_OUI_FROM_DATABASE=KnowRoaming + +OUI:70B3D5D6B* + ID_OUI_FROM_DATABASE=Uwinloc + +OUI:70B3D5D6C* + ID_OUI_FROM_DATABASE=GP Systems GmbH + +OUI:70B3D5D6E* + ID_OUI_FROM_DATABASE=ard sa + +OUI:70B3D5D6F* + ID_OUI_FROM_DATABASE=X-SPEX GmbH + +OUI:70B3D5D70* + ID_OUI_FROM_DATABASE=Rational Production srl Unipersonale + +OUI:70B3D5D71* + ID_OUI_FROM_DATABASE=RZB Rudolf Zimmermann, Bamberg GmbH + +OUI:70B3D5D72* + ID_OUI_FROM_DATABASE=OnYield Inc Ltd + +OUI:70B3D5D73* + ID_OUI_FROM_DATABASE=ERMINE Corporation + +OUI:70B3D5D74* + ID_OUI_FROM_DATABASE=Sandia National Laboratories + +OUI:70B3D5D75* + ID_OUI_FROM_DATABASE=Hyundai MNSOFT + +OUI:70B3D5D76* + ID_OUI_FROM_DATABASE=attocube systems AG + +OUI:70B3D5D77* + ID_OUI_FROM_DATABASE=Portrait Displays, Inc. + +OUI:70B3D5D79* + ID_OUI_FROM_DATABASE=GOMA ELETTRONICA SpA + +OUI:70B3D5D7A* + ID_OUI_FROM_DATABASE=Speedifi Inc + +OUI:70B3D5D7B* + ID_OUI_FROM_DATABASE=Peter Huber Kaeltemaschinenbau AG + +OUI:70B3D5D7C* + ID_OUI_FROM_DATABASE=D.T.S Illuminazione Srl + +OUI:70B3D5D7E* + ID_OUI_FROM_DATABASE=Triax A/S + +OUI:70B3D5D7F* + ID_OUI_FROM_DATABASE=ConectaIP Tecnologia S.L. + +OUI:70B3D5D80* + ID_OUI_FROM_DATABASE=AMMT GmbH + +OUI:70B3D5D81* + ID_OUI_FROM_DATABASE=PDD Group Ltd + +OUI:70B3D5D84* + ID_OUI_FROM_DATABASE=Sentry360 + +OUI:70B3D5D86* + ID_OUI_FROM_DATABASE=WPGSYS Pte Ltd + +OUI:70B3D5D87* + ID_OUI_FROM_DATABASE=Zigen Corp + +OUI:70B3D5D89* + ID_OUI_FROM_DATABASE=Resolution Systems + +OUI:70B3D5D8A* + ID_OUI_FROM_DATABASE=JIANGSU HORAINTEL CO.,LTD + +OUI:70B3D5D8B* + ID_OUI_FROM_DATABASE=Lenoxi Automation s.r.o. + +OUI:70B3D5D8C* + ID_OUI_FROM_DATABASE=Damerell Design Limited (DCL) + +OUI:70B3D5D8D* + ID_OUI_FROM_DATABASE=Pullnet Technology,S.L. + +OUI:70B3D5D8E* + ID_OUI_FROM_DATABASE=Axatel SrL + +OUI:70B3D5D8F* + ID_OUI_FROM_DATABASE=Molu Technology Inc., LTD. + +OUI:70B3D5D90* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5D91* + ID_OUI_FROM_DATABASE=FoodALYT GmbH + +OUI:70B3D5D92* + ID_OUI_FROM_DATABASE=Zamir Recognition Systems Ltd. + +OUI:70B3D5D93* + ID_OUI_FROM_DATABASE=PAMIR Inc + +OUI:70B3D5D94* + ID_OUI_FROM_DATABASE=Dewetron GmbH + +OUI:70B3D5D95* + ID_OUI_FROM_DATABASE=SANO SERVICE Co.,Ltd + +OUI:70B3D5D97* + ID_OUI_FROM_DATABASE=BRS Sistemas Eletronicos + +OUI:70B3D5D98* + ID_OUI_FROM_DATABASE=ACD Elekronik GmbH + +OUI:70B3D5D9A* + ID_OUI_FROM_DATABASE=Wuhan Xingtuxinke ELectronic Co.,Ltd + +OUI:70B3D5D9B* + ID_OUI_FROM_DATABASE=Russian Telecom Equipment Company + +OUI:70B3D5D9C* + ID_OUI_FROM_DATABASE=Subinitial LLC + +OUI:70B3D5D9D* + ID_OUI_FROM_DATABASE=Electroimpact, Inc. + +OUI:70B3D5D9E* + ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. + +OUI:70B3D5D9F* + ID_OUI_FROM_DATABASE=Digital Solutions JSC + +OUI:70B3D5DA1* + ID_OUI_FROM_DATABASE=Qprel srl + +OUI:70B3D5DA2* + ID_OUI_FROM_DATABASE=ACD Elekronik GmbH + +OUI:70B3D5DA3* + ID_OUI_FROM_DATABASE=Voleatech GmbH + +OUI:70B3D5DA4* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5DA5* + ID_OUI_FROM_DATABASE=Roboteq + +OUI:70B3D5DA6* + ID_OUI_FROM_DATABASE=Redfish Group Pty Ltd + +OUI:70B3D5DA8* + ID_OUI_FROM_DATABASE=Tagarno AS + +OUI:70B3D5DA9* + ID_OUI_FROM_DATABASE=RCH Vietnam Limited Liability Company + +OUI:70B3D5DAA* + ID_OUI_FROM_DATABASE=AmTote Australasia + +OUI:70B3D5DAB* + ID_OUI_FROM_DATABASE=SET Power Systems GmbH + +OUI:70B3D5DAC* + ID_OUI_FROM_DATABASE=Dalian Laike Technology Development Co., Ltd + +OUI:70B3D5DAD* + ID_OUI_FROM_DATABASE=GD Mission Systems + +OUI:70B3D5DAE* + ID_OUI_FROM_DATABASE=LGE + +OUI:70B3D5DAF* + ID_OUI_FROM_DATABASE=INNOVATIVE CONCEPTS AND DESIGN LLC + +OUI:70B3D5DB0* + ID_OUI_FROM_DATABASE=Arnouse Digital Devices Corp + +OUI:70B3D5DB1* + ID_OUI_FROM_DATABASE=Biovigil Hygiene Technologies + +OUI:70B3D5DB2* + ID_OUI_FROM_DATABASE=Micro Electroninc Products + +OUI:70B3D5DB4* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D5DB5* + ID_OUI_FROM_DATABASE=Xiamen Point Circle Technologh Co,ltd + +OUI:70B3D5DB6* + ID_OUI_FROM_DATABASE=csintech + +OUI:70B3D5DB7* + ID_OUI_FROM_DATABASE=Pengo Technology Co., Ltd + +OUI:70B3D5DB8* + ID_OUI_FROM_DATABASE=SISTEM SA + +OUI:70B3D5DBC* + ID_OUI_FROM_DATABASE=Gamber Johnson-LLC + +OUI:70B3D5DBD* + ID_OUI_FROM_DATABASE=TRANSLITE GLOBAL LLC + +OUI:70B3D5DBE* + ID_OUI_FROM_DATABASE=Hiber + +OUI:70B3D5DBF* + ID_OUI_FROM_DATABASE=Infodev Electronic Designers Intl. + +OUI:70B3D5DC0* + ID_OUI_FROM_DATABASE=ATEME + +OUI:70B3D5DC1* + ID_OUI_FROM_DATABASE=Metralight, Inc. + +OUI:70B3D5DC2* + ID_OUI_FROM_DATABASE=SwineTech, Inc. + +OUI:70B3D5DC3* + ID_OUI_FROM_DATABASE=Fath Mechatronics + +OUI:70B3D5DC5* + ID_OUI_FROM_DATABASE=Excel Medical Electronics LLC + +OUI:70B3D5DC6* + ID_OUI_FROM_DATABASE=IDEM INC. + +OUI:70B3D5DC8* + ID_OUI_FROM_DATABASE=Enertex Bayern GmbH + +OUI:70B3D5DC9* + ID_OUI_FROM_DATABASE=Sensoterra BV + +OUI:70B3D5DCA* + ID_OUI_FROM_DATABASE=DSan Corporation + +OUI:70B3D5DCC* + ID_OUI_FROM_DATABASE=Eutron SPA + +OUI:70B3D5DCD* + ID_OUI_FROM_DATABASE=C Tech Bilişim Teknolojileri San. ve Tic. AŞ + +OUI:70B3D5DCE* + ID_OUI_FROM_DATABASE=Stahl GmbH + +OUI:70B3D5DCF* + ID_OUI_FROM_DATABASE=KLS Netherlands B.V. + +OUI:70B3D5DD1* + ID_OUI_FROM_DATABASE=em-tec GmbH + +OUI:70B3D5DD2* + ID_OUI_FROM_DATABASE=Insitu, Inc + +OUI:70B3D5DD3* + ID_OUI_FROM_DATABASE=VITEC + +OUI:70B3D5DD4* + ID_OUI_FROM_DATABASE=ResIOT UBLSOFTWARE SRL + +OUI:70B3D5DD5* + ID_OUI_FROM_DATABASE=Cooltera Limited + +OUI:70B3D5DD6* + ID_OUI_FROM_DATABASE=Umweltanalytik Holbach GmbH + +OUI:70B3D5DD7* + ID_OUI_FROM_DATABASE=DETECT Australia + +OUI:70B3D5DD8* + ID_OUI_FROM_DATABASE=EMSCAN Corp. + +OUI:70B3D5DD9* + ID_OUI_FROM_DATABASE=MaNima Technologies BV + +OUI:70B3D5DDB* + ID_OUI_FROM_DATABASE=Intra Corporation + +OUI:70B3D5DDC* + ID_OUI_FROM_DATABASE=Syscom Instruments SA + +OUI:70B3D5DDD* + ID_OUI_FROM_DATABASE=BIO RAD LABORATORIES + +OUI:70B3D5DDF* + ID_OUI_FROM_DATABASE=AeroVision Avionics, Inc. + +OUI:70B3D5DE0* + ID_OUI_FROM_DATABASE=eCozy GmbH + +OUI:70B3D5DE1* + ID_OUI_FROM_DATABASE=Duplomatic MS spa + +OUI:70B3D5DE2* + ID_OUI_FROM_DATABASE=ACD Elekronik GmbH + +OUI:70B3D5DE3* + ID_OUI_FROM_DATABASE=ETL Elektrotechnik Lauter GmbH + +OUI:70B3D5DE4* + ID_OUI_FROM_DATABASE=MAVILI ELEKTRONIK TIC. VE SAN. A.S. + +OUI:70B3D5DE5* + ID_OUI_FROM_DATABASE=ASML + +OUI:70B3D5DE6* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5DE7* + ID_OUI_FROM_DATABASE=Innominds Software Private Limited + +OUI:70B3D5DE8* + ID_OUI_FROM_DATABASE=Nation-E Ltd. + +OUI:70B3D5DE9* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5DEA* + ID_OUI_FROM_DATABASE=Advanced Ventilation Applications, Inc. + +OUI:70B3D5DEC* + ID_OUI_FROM_DATABASE=Condev-Automation GmbH + +OUI:70B3D5DED* + ID_OUI_FROM_DATABASE=Simpulse + +OUI:70B3D5DEE* + ID_OUI_FROM_DATABASE=CRDE + +OUI:70B3D5DF0* + ID_OUI_FROM_DATABASE=astozi consulting Tomasz Zieba + +OUI:70B3D5DF1* + ID_OUI_FROM_DATABASE=CoXlab Inc. + +OUI:70B3D5DF2* + ID_OUI_FROM_DATABASE=AML + +OUI:70B3D5DF3* + ID_OUI_FROM_DATABASE=SPC Bioclinicum + +OUI:70B3D5DF4* + ID_OUI_FROM_DATABASE=Heim- & Bürokommunikation Ilmert e.K. + +OUI:70B3D5DF5* + ID_OUI_FROM_DATABASE=Beijing Huanyu Zhilian Science &Technology Co., Ltd. + +OUI:70B3D5DF6* + ID_OUI_FROM_DATABASE=Tiab Limited + +OUI:70B3D5DF7* + ID_OUI_FROM_DATABASE=Refecor Oy + +OUI:70B3D5DF8* + ID_OUI_FROM_DATABASE=RMA Mess- und Regeltechnik GmbH & Co.KG + +OUI:70B3D5DF9* + ID_OUI_FROM_DATABASE=Korea Plant Maintenance + +OUI:70B3D5DFA* + ID_OUI_FROM_DATABASE=Newtouch Electronics (Shanghai) Co.,Ltd. + +OUI:70B3D5DFB* + ID_OUI_FROM_DATABASE=Yamamoto Works Ltd. + +OUI:70B3D5DFC* + ID_OUI_FROM_DATABASE=ELECTRONIC SYSTEMS DESIGN SPRL + +OUI:70B3D5DFD* + ID_OUI_FROM_DATABASE=Contiweb + +OUI:70B3D5DFE* + ID_OUI_FROM_DATABASE=microtec Sicherheitstechnik GmbH + +OUI:70B3D5DFF* + ID_OUI_FROM_DATABASE=Spanawave Corporation + +OUI:70B3D5E00* + ID_OUI_FROM_DATABASE=Jeaway CCTV Security Ltd,. + +OUI:70B3D5E02* + ID_OUI_FROM_DATABASE=YEHL & JORDAN LLC + +OUI:70B3D5E04* + ID_OUI_FROM_DATABASE=Combilent + +OUI:70B3D5E06* + ID_OUI_FROM_DATABASE=System West dba ICS Electronics + +OUI:70B3D5E07* + ID_OUI_FROM_DATABASE=Baader Planetarium GmbH + +OUI:70B3D5E08* + ID_OUI_FROM_DATABASE=Olssen + +OUI:70B3D5E09* + ID_OUI_FROM_DATABASE=L-3 communications ComCept Division + +OUI:70B3D5E0A* + ID_OUI_FROM_DATABASE=Acouva, Inc. + +OUI:70B3D5E0B* + ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD. + +OUI:70B3D5E0C* + ID_OUI_FROM_DATABASE=Communication Systems Solutions + +OUI:70B3D5E0D* + ID_OUI_FROM_DATABASE=Sigma Connectivity AB + +OUI:70B3D5E0F* + ID_OUI_FROM_DATABASE=Vtron Pty Ltd + +OUI:70B3D5E10* + ID_OUI_FROM_DATABASE=Leidos + +OUI:70B3D5E12* + ID_OUI_FROM_DATABASE=SNK, Inc. + +OUI:70B3D5E14* + ID_OUI_FROM_DATABASE=Automata Spa + +OUI:70B3D5E15* + ID_OUI_FROM_DATABASE=Benetel + +OUI:70B3D5E16* + ID_OUI_FROM_DATABASE=China Entropy Co., Ltd. + +OUI:70B3D5E17* + ID_OUI_FROM_DATABASE=SA Photonics + +OUI:70B3D5E18* + ID_OUI_FROM_DATABASE=Plasmapp Co.,Ltd. + +OUI:70B3D5E1A* + ID_OUI_FROM_DATABASE=BIZERBA LUCEO + +OUI:70B3D5E1B* + ID_OUI_FROM_DATABASE=Neuron GmbH + +OUI:70B3D5E1C* + ID_OUI_FROM_DATABASE=Xcenter AS + +OUI:70B3D5E1E* + ID_OUI_FROM_DATABASE=Umano Medical Inc. + +OUI:70B3D5E1F* + ID_OUI_FROM_DATABASE=THETA432 + +OUI:70B3D5E20* + ID_OUI_FROM_DATABASE=Signature Control Systems, LLC. + +OUI:70B3D5E21* + ID_OUI_FROM_DATABASE=LLVISION TECHNOLOGY CO.,LTD + +OUI:70B3D5E22* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5E23* + ID_OUI_FROM_DATABASE=Smith Meter, Inc. + +OUI:70B3D5E24* + ID_OUI_FROM_DATABASE=Gogo Business Aviation + +OUI:70B3D5E25* + ID_OUI_FROM_DATABASE=GJD Manufacturing + +OUI:70B3D5E26* + ID_OUI_FROM_DATABASE=FEITIAN CO.,LTD. + +OUI:70B3D5E27* + ID_OUI_FROM_DATABASE=Woodside Electronics + +OUI:70B3D5E28* + ID_OUI_FROM_DATABASE=iotec GmbH + +OUI:70B3D5E29* + ID_OUI_FROM_DATABASE=Invent Vision - iVision Sistemas de Imagem e Visão S.A. + +OUI:70B3D5E2A* + ID_OUI_FROM_DATABASE=CONTES, spol. s r.o. + +OUI:70B3D5E2B* + ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd. + +OUI:70B3D5E2C* + ID_OUI_FROM_DATABASE=Fourth Frontier Technologies Private Limited + +OUI:70B3D5E2D* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5E2E* + ID_OUI_FROM_DATABASE=Merz s.r.o. + +OUI:70B3D5E30* + ID_OUI_FROM_DATABASE=QUISS AG + +OUI:70B3D5E32* + ID_OUI_FROM_DATABASE=HERUTU ELECTRONICS CORPORATION + +OUI:70B3D5E33* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D5E34* + ID_OUI_FROM_DATABASE=Gamber Johnson-LLC + +OUI:70B3D5E35* + ID_OUI_FROM_DATABASE=Nanospeed Technologies Limited + +OUI:70B3D5E36* + ID_OUI_FROM_DATABASE=Guidance Navigation Limited + +OUI:70B3D5E38* + ID_OUI_FROM_DATABASE=Cursor Systems NV + +OUI:70B3D5E39* + ID_OUI_FROM_DATABASE=Thinnect, Inc, + +OUI:70B3D5E3A* + ID_OUI_FROM_DATABASE=Cyanview + +OUI:70B3D5E3B* + ID_OUI_FROM_DATABASE=ComNav Technology Ltd. + +OUI:70B3D5E3C* + ID_OUI_FROM_DATABASE=Densitron Technologies Ltd + +OUI:70B3D5E3D* + ID_OUI_FROM_DATABASE=Leo Bodnar Electronics Ltd + +OUI:70B3D5E3E* + ID_OUI_FROM_DATABASE=Sol Welding srl + +OUI:70B3D5E3F* + ID_OUI_FROM_DATABASE=BESTCODE LLC + +OUI:70B3D5E40* + ID_OUI_FROM_DATABASE=Siemens Mobility GmbH - MO TI SPA + +OUI:70B3D5E43* + ID_OUI_FROM_DATABASE=SL Audio A/S + +OUI:70B3D5E45* + ID_OUI_FROM_DATABASE=Momentum Data Systems + +OUI:70B3D5E47* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D5E48* + ID_OUI_FROM_DATABASE=TDI. Co., LTD + +OUI:70B3D5E49* + ID_OUI_FROM_DATABASE=Kendrion Mechatronics Center GmbH + +OUI:70B3D5E4A* + ID_OUI_FROM_DATABASE=ICP NewTech Ltd + +OUI:70B3D5E4B* + ID_OUI_FROM_DATABASE=DELTA + +OUI:70B3D5E4C* + ID_OUI_FROM_DATABASE=IAI-Israel Aerospace Industries MBT + +OUI:70B3D5E4D* + ID_OUI_FROM_DATABASE=Vulcan Wireless Inc. + +OUI:70B3D5E4E* + ID_OUI_FROM_DATABASE=Midfin Systems + +OUI:70B3D5E4F* + ID_OUI_FROM_DATABASE=RWS Automation GmbH + +OUI:70B3D5E50* + ID_OUI_FROM_DATABASE=Advanced Vision Technology Ltd + +OUI:70B3D5E52* + ID_OUI_FROM_DATABASE=Guangzhou Moblin Technology Co., Ltd. + +OUI:70B3D5E53* + ID_OUI_FROM_DATABASE=MI INC. + +OUI:70B3D5E54* + ID_OUI_FROM_DATABASE=Beijing PanGu Company + +OUI:70B3D5E55* + ID_OUI_FROM_DATABASE=BELT S.r.l. + +OUI:70B3D5E56* + ID_OUI_FROM_DATABASE=HIPODROMO DE AGUA CALIENTE, S.A. DE C.V. + +OUI:70B3D5E57* + ID_OUI_FROM_DATABASE=Iradimed + +OUI:70B3D5E58* + ID_OUI_FROM_DATABASE=Thurlby Thandar Instruments LTD + +OUI:70B3D5E59* + ID_OUI_FROM_DATABASE=Fracarro srl + +OUI:70B3D5E5B* + ID_OUI_FROM_DATABASE=Argosy Labs Inc. + +OUI:70B3D5E5C* + ID_OUI_FROM_DATABASE=Walton Hi-Tech Industries Ltd. + +OUI:70B3D5E5D* + ID_OUI_FROM_DATABASE=Boffins Technologies AB + +OUI:70B3D5E5E* + ID_OUI_FROM_DATABASE=Critical Link LLC + +OUI:70B3D5E61* + ID_OUI_FROM_DATABASE=Adeli + +OUI:70B3D5E63* + ID_OUI_FROM_DATABASE=Potomac Electric Corporation + +OUI:70B3D5E67* + ID_OUI_FROM_DATABASE=APPLIED PROCESSING + +OUI:70B3D5E69* + ID_OUI_FROM_DATABASE=Fire4 Systems UK Ltd + +OUI:70B3D5E6A* + ID_OUI_FROM_DATABASE=MAC Solutions (UK) Ltd + +OUI:70B3D5E6C* + ID_OUI_FROM_DATABASE=Fusar Technologies inc + +OUI:70B3D5E6D* + ID_OUI_FROM_DATABASE=Domus S.C. + +OUI:70B3D5E6E* + ID_OUI_FROM_DATABASE=Lieron BVBA + +OUI:70B3D5E6F* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:70B3D5E70* + ID_OUI_FROM_DATABASE=DISK Multimedia s.r.o. + +OUI:70B3D5E71* + ID_OUI_FROM_DATABASE=SiS Technology + +OUI:70B3D5E72* + ID_OUI_FROM_DATABASE=KDT Corp. + +OUI:70B3D5E74* + ID_OUI_FROM_DATABASE=Exfrontier Co., Ltd. + +OUI:70B3D5E75* + ID_OUI_FROM_DATABASE=Nke + +OUI:70B3D5E76* + ID_OUI_FROM_DATABASE=Dorsett Technologies, Inc. + +OUI:70B3D5E77* + ID_OUI_FROM_DATABASE=OPTIX JSC + +OUI:70B3D5E78* + ID_OUI_FROM_DATABASE=Camwell India LLP + +OUI:70B3D5E79* + ID_OUI_FROM_DATABASE=Acrodea, Inc. + +OUI:70B3D5E7A* + ID_OUI_FROM_DATABASE=ART SPA + +OUI:70B3D5E7B* + ID_OUI_FROM_DATABASE=Shenzhen SanYeCao Electronics Co.,Ltd + +OUI:70B3D5E7C* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5E7D* + ID_OUI_FROM_DATABASE=Nanjing Dandick Science&technology development co., LTD + +OUI:70B3D5E7E* + ID_OUI_FROM_DATABASE=Groupe Citypassenger Inc + +OUI:70B3D5E80* + ID_OUI_FROM_DATABASE=Changzhou Rapid Information Technology Co,Ltd + +OUI:70B3D5E81* + ID_OUI_FROM_DATABASE=SLAT + +OUI:70B3D5E82* + ID_OUI_FROM_DATABASE=RF Track + +OUI:70B3D5E84* + ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD. + +OUI:70B3D5E85* + ID_OUI_FROM_DATABASE=Explorer Inc. + +OUI:70B3D5E86* + ID_OUI_FROM_DATABASE=YUYAMA MFG Co.,Ltd + +OUI:70B3D5E88* + ID_OUI_FROM_DATABASE=Breas Medical AB + +OUI:70B3D5E89* + ID_OUI_FROM_DATABASE=JSC Kaluga Astral + +OUI:70B3D5E8A* + ID_OUI_FROM_DATABASE=Melecs EWS GmbH + +OUI:70B3D5E8B* + ID_OUI_FROM_DATABASE=Dream D&S Co.,Ltd + +OUI:70B3D5E8C* + ID_OUI_FROM_DATABASE=Fracarro srl + +OUI:70B3D5E8D* + ID_OUI_FROM_DATABASE=Natav Services Ltd. + +OUI:70B3D5E8E* + ID_OUI_FROM_DATABASE=Macnica Technology + +OUI:70B3D5E8F* + ID_OUI_FROM_DATABASE=DISMUNTEL, S.A. + +OUI:70B3D5E90* + ID_OUI_FROM_DATABASE=Getein Biotechnology Co.,ltd + +OUI:70B3D5E91* + ID_OUI_FROM_DATABASE=NAS Australia P/L + +OUI:70B3D5E92* + ID_OUI_FROM_DATABASE=FUJI DATA SYSTEM CO.,LTD. + +OUI:70B3D5E93* + ID_OUI_FROM_DATABASE=ECON Technology Co.Ltd + +OUI:70B3D5E94* + ID_OUI_FROM_DATABASE=Lumiplan Duhamel + +OUI:70B3D5E95* + ID_OUI_FROM_DATABASE=BroadSoft Inc + +OUI:70B3D5E96* + ID_OUI_FROM_DATABASE=Cellier Domesticus inc + +OUI:70B3D5E97* + ID_OUI_FROM_DATABASE=Toptech Systems, Inc. + +OUI:70B3D5E98* + ID_OUI_FROM_DATABASE=JSC Kaluga Astral + +OUI:70B3D5E99* + ID_OUI_FROM_DATABASE=Advitronics telecom bv + +OUI:70B3D5E9A* + ID_OUI_FROM_DATABASE=Meta Computing Services, Corp + +OUI:70B3D5E9B* + ID_OUI_FROM_DATABASE=NUMATA R&D Co.,Ltd + +OUI:70B3D5E9C* + ID_OUI_FROM_DATABASE=ATG UV Technology + +OUI:70B3D5E9D* + ID_OUI_FROM_DATABASE=INTECH + +OUI:70B3D5E9E* + ID_OUI_FROM_DATABASE=MSB Elektronik und Gerätebau GmbH + +OUI:70B3D5EA0* + ID_OUI_FROM_DATABASE=PARK24 + +OUI:70B3D5EA1* + ID_OUI_FROM_DATABASE=Qntra Technology + +OUI:70B3D5EA2* + ID_OUI_FROM_DATABASE=Transportal Solutions Ltd + +OUI:70B3D5EA3* + ID_OUI_FROM_DATABASE=Gridless Power Corperation + +OUI:70B3D5EA4* + ID_OUI_FROM_DATABASE=Grupo Epelsa S.L. + +OUI:70B3D5EA5* + ID_OUI_FROM_DATABASE=LOTES TM OOO + +OUI:70B3D5EA6* + ID_OUI_FROM_DATABASE=Galios + +OUI:70B3D5EA7* + ID_OUI_FROM_DATABASE=S.I.C.E.S. srl + +OUI:70B3D5EA8* + ID_OUI_FROM_DATABASE=Dia-Stron Limited + +OUI:70B3D5EA9* + ID_OUI_FROM_DATABASE=Zhuhai Lonl electric Co.,Ltd. + +OUI:70B3D5EAB* + ID_OUI_FROM_DATABASE=APEN GROUP SpA (VAT IT08767740155) + +OUI:70B3D5EAC* + ID_OUI_FROM_DATABASE=Kentech Instruments Limited + +OUI:70B3D5EAD* + ID_OUI_FROM_DATABASE=Cobo, Inc. + +OUI:70B3D5EAE* + ID_OUI_FROM_DATABASE=Orlaco Products B.V. + +OUI:70B3D5EB0* + ID_OUI_FROM_DATABASE=Nautel Limted + +OUI:70B3D5EB1* + ID_OUI_FROM_DATABASE=CP contech electronic GmbH + +OUI:70B3D5EB2* + ID_OUI_FROM_DATABASE=Shooter Detection Systems + +OUI:70B3D5EB3* + ID_OUI_FROM_DATABASE=KWS-Electronic GmbH + +OUI:70B3D5EB4* + ID_OUI_FROM_DATABASE=Robotic Research, LLC + +OUI:70B3D5EB5* + ID_OUI_FROM_DATABASE=JUSTEK INC + +OUI:70B3D5EB7* + ID_OUI_FROM_DATABASE=Skreens + +OUI:70B3D5EB8* + ID_OUI_FROM_DATABASE=Emporia Renewable Energy Corp + +OUI:70B3D5EB9* + ID_OUI_FROM_DATABASE=Thiel Audio Products Company, LLC + +OUI:70B3D5EBA* + ID_OUI_FROM_DATABASE=Last Mile Gear + +OUI:70B3D5EBB* + ID_OUI_FROM_DATABASE=Beijing Wing ICT Technology Co., Ltd. + +OUI:70B3D5EBC* + ID_OUI_FROM_DATABASE=Refine Technology, LLC + +OUI:70B3D5EBD* + ID_OUI_FROM_DATABASE=midBit Technologies, LLC + +OUI:70B3D5EBE* + ID_OUI_FROM_DATABASE=Sierra Pacific Innovations Corp + +OUI:70B3D5EBF* + ID_OUI_FROM_DATABASE=AUTOMATICA Y REGULACION S.A. + +OUI:70B3D5EC1* + ID_OUI_FROM_DATABASE=Xafax Nederland bv + +OUI:70B3D5EC3* + ID_OUI_FROM_DATABASE=Virtual Control Systems Ltd + +OUI:70B3D5EC4* + ID_OUI_FROM_DATABASE=hmt telematik GmbH + +OUI:70B3D5EC5* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5EC6* + ID_OUI_FROM_DATABASE=ESII + +OUI:70B3D5EC7* + ID_OUI_FROM_DATABASE=Neoptix Inc. + +OUI:70B3D5EC8* + ID_OUI_FROM_DATABASE=Viko Elektrik-Elektronik A.Ş. + +OUI:70B3D5ECA* + ID_OUI_FROM_DATABASE=Transtronic AB + +OUI:70B3D5ECB* + ID_OUI_FROM_DATABASE=Re spa - Controlli Industriali - IT01782300154 + +OUI:70B3D5ECC* + ID_OUI_FROM_DATABASE=Digifocus Technology Inc. + +OUI:70B3D5ECD* + ID_OUI_FROM_DATABASE=SBS-Feintechnik GmbH & Co. KG + +OUI:70B3D5ECE* + ID_OUI_FROM_DATABASE=COMM-connect A/S + +OUI:70B3D5ECF* + ID_OUI_FROM_DATABASE=Ipitek + +OUI:70B3D5ED0* + ID_OUI_FROM_DATABASE=shanghai qiaoqi zhinengkeji + +OUI:70B3D5ED1* + ID_OUI_FROM_DATABASE=Przemyslowy Instytut Automatyki i Pomiarow + +OUI:70B3D5ED5* + ID_OUI_FROM_DATABASE=hangzhou battle link technology Co.,Ltd + +OUI:70B3D5ED7* + ID_OUI_FROM_DATABASE=WAVE + +OUI:70B3D5ED8* + ID_OUI_FROM_DATABASE=Wartsila Voyage Limited + +OUI:70B3D5EDB* + ID_OUI_FROM_DATABASE=Netfort Solutions + +OUI:70B3D5EDC* + ID_OUI_FROM_DATABASE=J.D. Koftinoff Software, Ltd. + +OUI:70B3D5EDD* + ID_OUI_FROM_DATABASE=Solar Network & Partners + +OUI:70B3D5EDE* + ID_OUI_FROM_DATABASE=Agrident GmbH + +OUI:70B3D5EDF* + ID_OUI_FROM_DATABASE=GridNavigator + +OUI:70B3D5EE1* + ID_OUI_FROM_DATABASE=allora Factory BVBA + +OUI:70B3D5EE2* + ID_OUI_FROM_DATABASE=MONTRADE SPA + +OUI:70B3D5EE3* + ID_OUI_FROM_DATABASE=Lithe Technology, LLC + +OUI:70B3D5EE4* + ID_OUI_FROM_DATABASE=O-Net Automation Technology (Shenzhen)Limited + +OUI:70B3D5EE5* + ID_OUI_FROM_DATABASE=Beijing Hzhytech Technology Co.Ltd + +OUI:70B3D5EE6* + ID_OUI_FROM_DATABASE=Vaunix Technology Corporation + +OUI:70B3D5EE7* + ID_OUI_FROM_DATABASE=BLUE-SOLUTIONS CANADA INC. + +OUI:70B3D5EE8* + ID_OUI_FROM_DATABASE=robert juliat + +OUI:70B3D5EE9* + ID_OUI_FROM_DATABASE=SC3 Automation + +OUI:70B3D5EEA* + ID_OUI_FROM_DATABASE=Dameca a/s + +OUI:70B3D5EEB* + ID_OUI_FROM_DATABASE=shenzhen suofeixiang technology Co.,Ltd + +OUI:70B3D5EEC* + ID_OUI_FROM_DATABASE=Impolux GmbH + +OUI:70B3D5EED* + ID_OUI_FROM_DATABASE=COMM-connect A/S + +OUI:70B3D5EEE* + ID_OUI_FROM_DATABASE=SOCIEDAD IBERICA DE CONSTRUCCIONES ELECTRICAS, S.A. (SICE) + +OUI:70B3D5EEF* + ID_OUI_FROM_DATABASE=TATTILE SRL + +OUI:70B3D5EF1* + ID_OUI_FROM_DATABASE=Nanotok LLC + +OUI:70B3D5EF2* + ID_OUI_FROM_DATABASE=Kongsberg Intergrated Tactical Systems + +OUI:70B3D5EF3* + ID_OUI_FROM_DATABASE=octoScope + +OUI:70B3D5EF4* + ID_OUI_FROM_DATABASE=Orange Tree Technologies Ltd + +OUI:70B3D5EF5* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D5EF6* + ID_OUI_FROM_DATABASE=CHARGELIB + +OUI:70B3D5EF7* + ID_OUI_FROM_DATABASE=DAVE SRL + +OUI:70B3D5EF8* + ID_OUI_FROM_DATABASE=DKS Dienstl.ges. f. Komm.anl. d. Stadt- u. Reg.verk. mbH + +OUI:70B3D5EF9* + ID_OUI_FROM_DATABASE=Critical Link LLC + +OUI:70B3D5EFA* + ID_OUI_FROM_DATABASE=NextEra Energy Resources, LLC + +OUI:70B3D5EFB* + ID_OUI_FROM_DATABASE=PXM sp.k. + +OUI:70B3D5EFC* + ID_OUI_FROM_DATABASE=Absolent AB + +OUI:70B3D5EFD* + ID_OUI_FROM_DATABASE=Cambridge Technology, Inc. + +OUI:70B3D5EFE* + ID_OUI_FROM_DATABASE=MEIDEN SYSTEM SOLUTIONS + +OUI:70B3D5EFF* + ID_OUI_FROM_DATABASE=Carlo Gavazzi Industri + +OUI:70B3D5F00* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5F01* + ID_OUI_FROM_DATABASE=Software Systems Plus + +OUI:70B3D5F03* + ID_OUI_FROM_DATABASE=GMI Ltd + +OUI:70B3D5F04* + ID_OUI_FROM_DATABASE=Scame Sistemi srl + +OUI:70B3D5F05* + ID_OUI_FROM_DATABASE=Motomuto Aps + +OUI:70B3D5F06* + ID_OUI_FROM_DATABASE=WARECUBE,INC + +OUI:70B3D5F07* + ID_OUI_FROM_DATABASE=DUVAL MESSIEN + +OUI:70B3D5F08* + ID_OUI_FROM_DATABASE=Szabo Software & Engineering UK Ltd + +OUI:70B3D5F0A* + ID_OUI_FROM_DATABASE=Neuronal Innovation Control S.L. + +OUI:70B3D5F0B* + ID_OUI_FROM_DATABASE=RF Industries + +OUI:70B3D5F0C* + ID_OUI_FROM_DATABASE=ModulaTeam GmbH + +OUI:70B3D5F0D* + ID_OUI_FROM_DATABASE=MeQ Inc. + +OUI:70B3D5F0F* + ID_OUI_FROM_DATABASE=Kyoto Denkiki + +OUI:70B3D5F10* + ID_OUI_FROM_DATABASE=Riegl Laser Measurement Systems GmbH + +OUI:70B3D5F11* + ID_OUI_FROM_DATABASE=BroadSoft Inc + +OUI:70B3D5F12* + ID_OUI_FROM_DATABASE=Incoil Induktion AB + +OUI:70B3D5F13* + ID_OUI_FROM_DATABASE=MEDIAM Sp. z o.o. + +OUI:70B3D5F14* + ID_OUI_FROM_DATABASE=SANYU SWITCH CO., LTD. + +OUI:70B3D5F16* + ID_OUI_FROM_DATABASE=BRS Sistemas Eletrônicos + +OUI:70B3D5F17* + ID_OUI_FROM_DATABASE=VITEC + +OUI:70B3D5F18* + ID_OUI_FROM_DATABASE=HD Vision Systems GmbH + +OUI:70B3D5F19* + ID_OUI_FROM_DATABASE=Vitro Technology Corporation + +OUI:70B3D5F1A* + ID_OUI_FROM_DATABASE=Sator Controls s.r.o. + +OUI:70B3D5F1C* + ID_OUI_FROM_DATABASE=Bavaria Digital Technik GmbH + +OUI:70B3D5F1D* + ID_OUI_FROM_DATABASE=Critical Link LLC + +OUI:70B3D5F1E* + ID_OUI_FROM_DATABASE=ATX NETWORKS LTD + +OUI:70B3D5F1F* + ID_OUI_FROM_DATABASE=HKC Limited + +OUI:70B3D5F21* + ID_OUI_FROM_DATABASE=dds + +OUI:70B3D5F22* + ID_OUI_FROM_DATABASE=Shengli Financial Software Development + +OUI:70B3D5F23* + ID_OUI_FROM_DATABASE=Lyse AS + +OUI:70B3D5F24* + ID_OUI_FROM_DATABASE=Daavlin + +OUI:70B3D5F25* + ID_OUI_FROM_DATABASE=JSC “Scientific Industrial Enterprise Rubin + +OUI:70B3D5F27* + ID_OUI_FROM_DATABASE=NIRIT- Xinwei Telecom Technology Co., Ltd. + +OUI:70B3D5F28* + ID_OUI_FROM_DATABASE=Yi An Electronics Co., Ltd + +OUI:70B3D5F29* + ID_OUI_FROM_DATABASE=SamabaNova Systems + +OUI:70B3D5F2A* + ID_OUI_FROM_DATABASE=WIBOND Informationssysteme GmbH + +OUI:70B3D5F2B* + ID_OUI_FROM_DATABASE=SENSYS GmbH + +OUI:70B3D5F2C* + ID_OUI_FROM_DATABASE=Hengen Technologies GmbH + +OUI:70B3D5F2D* + ID_OUI_FROM_DATABASE=ID Lock AS + +OUI:70B3D5F2E* + ID_OUI_FROM_DATABASE=Shanghai JCY Technology Company + +OUI:70B3D5F2F* + ID_OUI_FROM_DATABASE=TELEPLATFORMS + +OUI:70B3D5F30* + ID_OUI_FROM_DATABASE=ADE Technology Inc. + +OUI:70B3D5F34* + ID_OUI_FROM_DATABASE=MacGray Services + +OUI:70B3D5F35* + ID_OUI_FROM_DATABASE=carbonTRACK + +OUI:70B3D5F36* + ID_OUI_FROM_DATABASE=dinosys + +OUI:70B3D5F37* + ID_OUI_FROM_DATABASE=Mitsubishi Electric Micro-Computer Application Software Co.,Ltd. + +OUI:70B3D5F38* + ID_OUI_FROM_DATABASE=Scanvaegt Nordic A/S + +OUI:70B3D5F39* + ID_OUI_FROM_DATABASE=Zenros ApS + +OUI:70B3D5F3A* + ID_OUI_FROM_DATABASE=OOO Research and Production Center Computer Technologies + +OUI:70B3D5F3B* + ID_OUI_FROM_DATABASE=Epdm Pty Ltd + +OUI:70B3D5F3C* + ID_OUI_FROM_DATABASE=Gigaray + +OUI:70B3D5F3E* + ID_OUI_FROM_DATABASE=ООО РОНЕКС + +OUI:70B3D5F3F* + ID_OUI_FROM_DATABASE=comtac AG + +OUI:70B3D5F42* + ID_OUI_FROM_DATABASE=Matsuhisa Corporation + +OUI:70B3D5F43* + ID_OUI_FROM_DATABASE=Divelbiss Corporation + +OUI:70B3D5F44* + ID_OUI_FROM_DATABASE=Magneti Marelli S.p.A. Electronics + +OUI:70B3D5F45* + ID_OUI_FROM_DATABASE=Norbit ODM AS + +OUI:70B3D5F47* + ID_OUI_FROM_DATABASE=TXMission Ltd. + +OUI:70B3D5F48* + ID_OUI_FROM_DATABASE=HEITEC AG + +OUI:70B3D5F4B* + ID_OUI_FROM_DATABASE=Chengdu Lingya Technology Co., Ltd. + +OUI:70B3D5F4C* + ID_OUI_FROM_DATABASE=PolyTech A/S + +OUI:70B3D5F4D* + ID_OUI_FROM_DATABASE=Honeywell + +OUI:70B3D5F4F* + ID_OUI_FROM_DATABASE=Power Electronics Espana, S.L. + +OUI:70B3D5F50* + ID_OUI_FROM_DATABASE=Vectology,Inc + +OUI:70B3D5F51* + ID_OUI_FROM_DATABASE=IoT Routers Limited + +OUI:70B3D5F52* + ID_OUI_FROM_DATABASE=Alere Technologies AS + +OUI:70B3D5F53* + ID_OUI_FROM_DATABASE=HighTechSystem Co.,Ltd. + +OUI:70B3D5F54* + ID_OUI_FROM_DATABASE=Revolution Retail Systems + +OUI:70B3D5F55* + ID_OUI_FROM_DATABASE=Kohler Mira Ltd + +OUI:70B3D5F56* + ID_OUI_FROM_DATABASE=VirtualHere Pty. Ltd. + +OUI:70B3D5F57* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5F58* + ID_OUI_FROM_DATABASE=CDR SRL + +OUI:70B3D5F5A* + ID_OUI_FROM_DATABASE=HAMEG GmbH + +OUI:70B3D5F5B* + ID_OUI_FROM_DATABASE=A.F.MENSAH, INC + +OUI:70B3D5F5C* + ID_OUI_FROM_DATABASE=Nable Communications, Inc. + +OUI:70B3D5F5D* + ID_OUI_FROM_DATABASE=Potter Electric Signal Co. LLC + +OUI:70B3D5F5E* + ID_OUI_FROM_DATABASE=Selex ES Inc. + +OUI:70B3D5F5F* + ID_OUI_FROM_DATABASE=RFRain LLC + +OUI:70B3D5F61* + ID_OUI_FROM_DATABASE=Power Diagnostic Service + +OUI:70B3D5F62* + ID_OUI_FROM_DATABASE=FRS GmbH & Co. KG + +OUI:70B3D5F63* + ID_OUI_FROM_DATABASE=Ars Products + +OUI:70B3D5F64* + ID_OUI_FROM_DATABASE=silicom + +OUI:70B3D5F65* + ID_OUI_FROM_DATABASE=MARKUS LABS + +OUI:70B3D5F67* + ID_OUI_FROM_DATABASE=winsun AG + +OUI:70B3D5F68* + ID_OUI_FROM_DATABASE=AL ZAJEL MODERN TELECOMM + +OUI:70B3D5F69* + ID_OUI_FROM_DATABASE=Copper Labs, Inc. + +OUI:70B3D5F6A* + ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd. + +OUI:70B3D5F6C* + ID_OUI_FROM_DATABASE=VisioGreen + +OUI:70B3D5F6D* + ID_OUI_FROM_DATABASE=Qowisio + +OUI:70B3D5F6E* + ID_OUI_FROM_DATABASE=Streambox Inc + +OUI:70B3D5F6F* + ID_OUI_FROM_DATABASE=Smashtag Ltd + +OUI:70B3D5F70* + ID_OUI_FROM_DATABASE=Honeywell + +OUI:70B3D5F71* + ID_OUI_FROM_DATABASE=Sonel S.A. + +OUI:70B3D5F72* + ID_OUI_FROM_DATABASE=Hanshin Electronics + +OUI:70B3D5F73* + ID_OUI_FROM_DATABASE=ASL Holdings + +OUI:70B3D5F75* + ID_OUI_FROM_DATABASE=Enlaps + +OUI:70B3D5F76* + ID_OUI_FROM_DATABASE=Thermo Fisher Scientific + +OUI:70B3D5F77* + ID_OUI_FROM_DATABASE=Satcube AB + +OUI:70B3D5F78* + ID_OUI_FROM_DATABASE=Manvish eTech Pvt. Ltd. + +OUI:70B3D5F79* + ID_OUI_FROM_DATABASE=Firehose Labs, Inc. + +OUI:70B3D5F7A* + ID_OUI_FROM_DATABASE=SENSO2ME + +OUI:70B3D5F7B* + ID_OUI_FROM_DATABASE=KST technology + +OUI:70B3D5F7C* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5F7E* + ID_OUI_FROM_DATABASE=Alpha Elettronica s.r.l. + +OUI:70B3D5F80* + ID_OUI_FROM_DATABASE=Guan Show Technologe Co., Ltd. + +OUI:70B3D5F81* + ID_OUI_FROM_DATABASE=Littlemore Scientific + +OUI:70B3D5F82* + ID_OUI_FROM_DATABASE=Preston Industries dba PolyScience + +OUI:70B3D5F83* + ID_OUI_FROM_DATABASE=Tata Communications Ltd. + +OUI:70B3D5F84* + ID_OUI_FROM_DATABASE=DEUTA-WERKE GmbH + +OUI:70B3D5F85* + ID_OUI_FROM_DATABASE=Solystic + +OUI:70B3D5F86* + ID_OUI_FROM_DATABASE=Wireless Systems Solutions LLC + +OUI:70B3D5F87* + ID_OUI_FROM_DATABASE=SHINWA INDUSTRIES, INC. + +OUI:70B3D5F88* + ID_OUI_FROM_DATABASE=ODAWARAKIKI AUTO-MACHINE MFG.CO.,LTD + +OUI:70B3D5F89* + ID_OUI_FROM_DATABASE=Soehnle Industrial Solutions GmbH + +OUI:70B3D5F8A* + ID_OUI_FROM_DATABASE=FRS GmbH & Co. KG + +OUI:70B3D5F8B* + ID_OUI_FROM_DATABASE=IOOOTA Srl + +OUI:70B3D5F8C* + ID_OUI_FROM_DATABASE=EUROPEAN ADVANCED TECHNOLOGIES + +OUI:70B3D5F8D* + ID_OUI_FROM_DATABASE=Flextronics Canafa Design Services + +OUI:70B3D5F8E* + ID_OUI_FROM_DATABASE=Isabellenhütte Heusler Gmbh &Co KG + +OUI:70B3D5F8F* + ID_OUI_FROM_DATABASE=DIMASTEC GESTAO DE PONTO E ACESSO EIRELI-ME + +OUI:70B3D5F91* + ID_OUI_FROM_DATABASE=Solid State Disks Ltd + +OUI:70B3D5F92* + ID_OUI_FROM_DATABASE=TechOne + +OUI:70B3D5F93* + ID_OUI_FROM_DATABASE=Hella Gutmann Solutions GmbH + +OUI:70B3D5F94* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5F95* + ID_OUI_FROM_DATABASE=Get SAT + +OUI:70B3D5F96* + ID_OUI_FROM_DATABASE=Ecologicsense + +OUI:70B3D5F97* + ID_OUI_FROM_DATABASE=Typhon Treatment Systems Ltd + +OUI:70B3D5F98* + ID_OUI_FROM_DATABASE=Metrum Sweden AB + +OUI:70B3D5F99* + ID_OUI_FROM_DATABASE=TEX COMPUTER SRL + +OUI:70B3D5F9A* + ID_OUI_FROM_DATABASE=Krabbenhøft og Ingolfsson + +OUI:70B3D5F9B* + ID_OUI_FROM_DATABASE=EvoLogics GmbH + +OUI:70B3D5F9C* + ID_OUI_FROM_DATABASE=SureFlap Ltd + +OUI:70B3D5F9E* + ID_OUI_FROM_DATABASE=International Center for Elementary Particle Physics, The University of Tokyo + +OUI:70B3D5F9F* + ID_OUI_FROM_DATABASE=M.A.C. Solutions (UK) Ltd + +OUI:70B3D5FA0* + ID_OUI_FROM_DATABASE=TIAMA + +OUI:70B3D5FA1* + ID_OUI_FROM_DATABASE=BBI Engineering, Inc. + +OUI:70B3D5FA2* + ID_OUI_FROM_DATABASE=Sarokal Test Systems Oy + +OUI:70B3D5FA3* + ID_OUI_FROM_DATABASE=ELVA-1 MICROWAVE HANDELSBOLAG + +OUI:70B3D5FA4* + ID_OUI_FROM_DATABASE=Energybox Limited + +OUI:70B3D5FA5* + ID_OUI_FROM_DATABASE=Shenzhen Hui Rui Tianyan Technology Co., Ltd. + +OUI:70B3D5FA6* + ID_OUI_FROM_DATABASE=RFL Electronics, Inc. + +OUI:70B3D5FA7* + ID_OUI_FROM_DATABASE=Nordson Corporation + +OUI:70B3D5FA8* + ID_OUI_FROM_DATABASE=Munters + +OUI:70B3D5FA9* + ID_OUI_FROM_DATABASE=CorDes, LLC + +OUI:70B3D5FAA* + ID_OUI_FROM_DATABASE=LogiM GmbH Software und Entwicklung + +OUI:70B3D5FAB* + ID_OUI_FROM_DATABASE=Open System Solutions Limited + +OUI:70B3D5FAD* + ID_OUI_FROM_DATABASE=ARC Technology Solutions, LLC + +OUI:70B3D5FAE* + ID_OUI_FROM_DATABASE=Silixa Ltd + +OUI:70B3D5FAF* + ID_OUI_FROM_DATABASE=Radig Hard & Software + +OUI:70B3D5FB0* + ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA + +OUI:70B3D5FB1* + ID_OUI_FROM_DATABASE=TOMEI TSUSHIN KOGYO CO,.LTD + +OUI:70B3D5FB2* + ID_OUI_FROM_DATABASE=KJ3 Elektronik AB + +OUI:70B3D5FB3* + ID_OUI_FROM_DATABASE=3PS Inc + +OUI:70B3D5FB5* + ID_OUI_FROM_DATABASE=Orange Tree Technologies Ltd + +OUI:70B3D5FB6* + ID_OUI_FROM_DATABASE=KRONOTECH SRL + +OUI:70B3D5FB7* + ID_OUI_FROM_DATABASE=SAICE + +OUI:70B3D5FB8* + ID_OUI_FROM_DATABASE=Hyannis Port Research + +OUI:70B3D5FB9* + ID_OUI_FROM_DATABASE=EYEDEA + +OUI:70B3D5FBA* + ID_OUI_FROM_DATABASE=Apogee Applied Research, Inc. + +OUI:70B3D5FBB* + ID_OUI_FROM_DATABASE=Vena Engineering Corporation + +OUI:70B3D5FBC* + ID_OUI_FROM_DATABASE=Twoway Communications, Inc. + +OUI:70B3D5FBD* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5FBE* + ID_OUI_FROM_DATABASE=Hanbat National University + +OUI:70B3D5FBF* + ID_OUI_FROM_DATABASE=SenSys (Design Electronics Ltd) + +OUI:70B3D5FC0* + ID_OUI_FROM_DATABASE=CODESYSTEM Co.,Ltd + +OUI:70B3D5FC1* + ID_OUI_FROM_DATABASE=InDiCor + +OUI:70B3D5FC2* + ID_OUI_FROM_DATABASE=HUNTER LIBERTY CORPORATION + +OUI:70B3D5FC5* + ID_OUI_FROM_DATABASE=Eltwin A/S + +OUI:70B3D5FC6* + ID_OUI_FROM_DATABASE=Tecnint HTE SRL + +OUI:70B3D5FC8* + ID_OUI_FROM_DATABASE=Moduware PTY LTD + +OUI:70B3D5FC9* + ID_OUI_FROM_DATABASE=Shanghai EICT Global Service Co., Ltd + +OUI:70B3D5FCA* + ID_OUI_FROM_DATABASE=M2M Cybernetics Pvt Ltd + +OUI:70B3D5FCB* + ID_OUI_FROM_DATABASE=Tieline Research Pty Ltd + +OUI:70B3D5FCC* + ID_OUI_FROM_DATABASE=DIgSILENT GmbH + +OUI:70B3D5FCD* + ID_OUI_FROM_DATABASE=Engage Technologies + +OUI:70B3D5FCE* + ID_OUI_FROM_DATABASE=FX TECHNOLOGY LIMITED + +OUI:70B3D5FCF* + ID_OUI_FROM_DATABASE=Acc+Ess Ltd + +OUI:70B3D5FD0* + ID_OUI_FROM_DATABASE=Alcohol Countermeasure Systems + +OUI:70B3D5FD1* + ID_OUI_FROM_DATABASE=RedRat Ltd + +OUI:70B3D5FD2* + ID_OUI_FROM_DATABASE=DALIAN LEVEAR ELECTRIC CO., LTD + +OUI:70B3D5FD3* + ID_OUI_FROM_DATABASE=AKIS technologies + +OUI:70B3D5FD4* + ID_OUI_FROM_DATABASE=GETRALINE + +OUI:70B3D5FD5* + ID_OUI_FROM_DATABASE=OCEANCCTV LTD + +OUI:70B3D5FD6* + ID_OUI_FROM_DATABASE=Visual Fan + +OUI:70B3D5FD7* + ID_OUI_FROM_DATABASE=Centum Adetel Group + +OUI:70B3D5FD8* + ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme + +OUI:70B3D5FDA* + ID_OUI_FROM_DATABASE=ACD Elektronik GmbH + +OUI:70B3D5FDB* + ID_OUI_FROM_DATABASE=Design SHIFT + +OUI:70B3D5FDC* + ID_OUI_FROM_DATABASE=Tapdn + +OUI:70B3D5FDD* + ID_OUI_FROM_DATABASE=Laser Imagineering Vertriebs GmbH + +OUI:70B3D5FDE* + ID_OUI_FROM_DATABASE=AERONAUTICAL & GENERAL INSTRUMENTS LTD. + +OUI:70B3D5FDF* + ID_OUI_FROM_DATABASE=NARA CONTROLS INC. + +OUI:70B3D5FE2* + ID_OUI_FROM_DATABASE=Galileo Tıp Teknolojileri San. ve Tic. A.S. + +OUI:70B3D5FE3* + ID_OUI_FROM_DATABASE=CSM MACHINERY srl + +OUI:70B3D5FE4* + ID_OUI_FROM_DATABASE=CARE PVT LTD + +OUI:70B3D5FE6* + ID_OUI_FROM_DATABASE=SHIZUKI ELECTRIC CO.,INC + +OUI:70B3D5FE7* + ID_OUI_FROM_DATABASE=VEILUX INC. + +OUI:70B3D5FE8* + ID_OUI_FROM_DATABASE=PCME Ltd. + +OUI:70B3D5FE9* + ID_OUI_FROM_DATABASE=Camsat Przemysław Gralak + +OUI:70B3D5FEA* + ID_OUI_FROM_DATABASE=Heng Dian Technology Co., Ltd + +OUI:70B3D5FEB* + ID_OUI_FROM_DATABASE=Les distributions Multi-Secure incorporee + +OUI:70B3D5FEC* + ID_OUI_FROM_DATABASE=Finder SpA + +OUI:70B3D5FED* + ID_OUI_FROM_DATABASE=Niron systems & Projects + +OUI:70B3D5FEE* + ID_OUI_FROM_DATABASE=Kawasaki Robot Service,Ltd. + +OUI:70B3D5FEF* + ID_OUI_FROM_DATABASE=HANGZHOU HUALAN MICROELECTRONIQUE CO.,LTD + +OUI:70B3D5FF0* + ID_OUI_FROM_DATABASE=E-MetroTel + +OUI:70B3D5FF1* + ID_OUI_FROM_DATABASE=Data Strategy Limited + +OUI:70B3D5FF2* + ID_OUI_FROM_DATABASE=tiga.eleven GmbH + +OUI:70B3D5FF3* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:70B3D5FF4* + ID_OUI_FROM_DATABASE=Serveron Corporation + +OUI:70B3D5FF5* + ID_OUI_FROM_DATABASE=Prolan Process Control Co. + +OUI:70B3D5FF6* + ID_OUI_FROM_DATABASE=Elektro Adrian + +OUI:70B3D5FF7* + ID_OUI_FROM_DATABASE=Cybercom AB + +OUI:70B3D5FF8* + ID_OUI_FROM_DATABASE=Dutile, Glines and Higgins Corporation + +OUI:70B3D5FF9* + ID_OUI_FROM_DATABASE=InOut Communication Systems + +OUI:70B3D5FFA* + ID_OUI_FROM_DATABASE=Barracuda Measurement Solutions + +OUI:70B3D5FFC* + ID_OUI_FROM_DATABASE=Symetrics Industries d.b.a. Extant Aerospace + +OUI:70B3D5FFE* + ID_OUI_FROM_DATABASE=Private + +OUI:70B3D5FFF* + ID_OUI_FROM_DATABASE=Private + +OUI:70B599* + ID_OUI_FROM_DATABASE=Embedded Technologies s.r.o. + +OUI:70B7AA* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:70B7E2* + ID_OUI_FROM_DATABASE=Jiangsu Miter Technology Co.,Ltd. + +OUI:70B921* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:70BAEF* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:70BBE9* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:70BC10* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:70BF3E* + ID_OUI_FROM_DATABASE=Charles River Laboratories + +OUI:70BF92* + ID_OUI_FROM_DATABASE=GN Audio A/S + +OUI:70C6AC* + ID_OUI_FROM_DATABASE=Bosch Automotive Aftermarket + +OUI:70C76F* + ID_OUI_FROM_DATABASE=INNO S + +OUI:70C7F2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:70C833* + ID_OUI_FROM_DATABASE=Wirepas Oy + +OUI:70C94E* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:70C9C6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70CA4D* + ID_OUI_FROM_DATABASE=Shenzhen lnovance Technology Co.,Ltd. + +OUI:70CA97* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:70CA9B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70CD60* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70CD91* + ID_OUI_FROM_DATABASE=TERACOM TELEMATICA S.A + +OUI:70CE8C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:70D081* + ID_OUI_FROM_DATABASE=Beijing Netpower Technologies Inc. + +OUI:70D313* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:70D379* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70D4F2* + ID_OUI_FROM_DATABASE=RIM + +OUI:70D57E* + ID_OUI_FROM_DATABASE=Scalar Corporation + +OUI:70D5E7* + ID_OUI_FROM_DATABASE=Wellcore Corporation + +OUI:70D6B6* + ID_OUI_FROM_DATABASE=Metrum Technologies + +OUI:70D880* + ID_OUI_FROM_DATABASE=Upos System sp. z o.o. + +OUI:70D923* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:70D931* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:70DA9C* + ID_OUI_FROM_DATABASE=TECSEN + +OUI:70DB98* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70DDA1* + ID_OUI_FROM_DATABASE=Tellabs + +OUI:70DDA8* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:70DEE2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70DEF9* + ID_OUI_FROM_DATABASE=FAI WAH INTERNATIONAL (HONG KONG) LIMITED + +OUI:70DF2F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70E027* + ID_OUI_FROM_DATABASE=HONGYU COMMUNICATION TECHNOLOGY LIMITED + +OUI:70E139* + ID_OUI_FROM_DATABASE=3view Ltd + +OUI:70E1FD* + ID_OUI_FROM_DATABASE=FLEXTRONICS + +OUI:70E24C* + ID_OUI_FROM_DATABASE=SAE IT-systems GmbH & Co. KG + +OUI:70E284* + ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation + +OUI:70E422* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70E56E* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:70E72C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70E843* + ID_OUI_FROM_DATABASE=Beijing C&W Optical Communication Technology Co.,Ltd. + +OUI:70EA1A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70EA5A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70ECE4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70EE50* + ID_OUI_FROM_DATABASE=Netatmo + +OUI:70EEA3* + ID_OUI_FROM_DATABASE=Eoptolink Technology Inc. Ltd, + +OUI:70EF00* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70F087* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:70F11C* + ID_OUI_FROM_DATABASE=Shenzhen Ogemray Technology Co.,Ltd + +OUI:70F176* + ID_OUI_FROM_DATABASE=Data Modul AG + +OUI:70F196* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:70F1A1* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:70F1E5* + ID_OUI_FROM_DATABASE=Xetawave LLC + +OUI:70F220* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:70F35A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:70F395* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:70F754* + ID_OUI_FROM_DATABASE=AMPAK Technology,Inc. + +OUI:70F82B* + ID_OUI_FROM_DATABASE=DWnet Technologies(Suzhou) Corporation + +OUI:70F8E70* + ID_OUI_FROM_DATABASE=SHENZHEN Xin JiuNing Electronics Co Ltd + +OUI:70F8E71* + ID_OUI_FROM_DATABASE=System Level Solutions (India) Pvt. + +OUI:70F8E72* + ID_OUI_FROM_DATABASE=VOXX International + +OUI:70F8E73* + ID_OUI_FROM_DATABASE=Dr. Simon Consulting GmbH + +OUI:70F8E74* + ID_OUI_FROM_DATABASE=CLIP Inc. + +OUI:70F8E75* + ID_OUI_FROM_DATABASE=Beijing Eehuu Technology Co.,Ltd. + +OUI:70F8E76* + ID_OUI_FROM_DATABASE=Flexim Security Oy + +OUI:70F8E77* + ID_OUI_FROM_DATABASE=NST Technology Limited Co.,Ltd. + +OUI:70F8E78* + ID_OUI_FROM_DATABASE=Eclipse Security + +OUI:70F8E79* + ID_OUI_FROM_DATABASE=Kontech Electronics Co., Ltd + +OUI:70F8E7A* + ID_OUI_FROM_DATABASE=TiVACI CORPORATION PTE LTD + +OUI:70F8E7B* + ID_OUI_FROM_DATABASE=Photonfocus AG + +OUI:70F8E7C* + ID_OUI_FROM_DATABASE=Fixstars Corporation + +OUI:70F8E7D* + ID_OUI_FROM_DATABASE=System-on-Chip engineering + +OUI:70F8E7E* + ID_OUI_FROM_DATABASE=CUAV + +OUI:70F927* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:70F96D* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:70FC8C* + ID_OUI_FROM_DATABASE=OneAccess SA + +OUI:70FC8F* + ID_OUI_FROM_DATABASE=FREEBOX SAS + +OUI:70FD45* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:70FD46* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:70FF5C* + ID_OUI_FROM_DATABASE=Cheerzing Communication(Xiamen)Technology Co.,Ltd + +OUI:70FF76* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:7403BD* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:74042B* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication (Wuhan) Company Limited + +OUI:7405A5* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:740ABC* + ID_OUI_FROM_DATABASE=LightwaveRF Technology Ltd + +OUI:740AE1* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:740EDB* + ID_OUI_FROM_DATABASE=Optowiz Co., Ltd + +OUI:7412BB* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:741489* + ID_OUI_FROM_DATABASE=SRT Wireless + +OUI:7415E2* + ID_OUI_FROM_DATABASE=Tri-Sen Systems Corporation + +OUI:741865* + ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co.,Ltd + +OUI:7419F80* + ID_OUI_FROM_DATABASE=Marmitek + +OUI:7419F81* + ID_OUI_FROM_DATABASE=Trend-tech Technology Co., Limited + +OUI:7419F82* + ID_OUI_FROM_DATABASE=Symtop Instrument Co. + +OUI:7419F83* + ID_OUI_FROM_DATABASE=Essential Trading Systems Corp + +OUI:7419F84* + ID_OUI_FROM_DATABASE=Cloudvue Technologies Corporation + +OUI:7419F85* + ID_OUI_FROM_DATABASE=Starcor Beijing Co.,Limited + +OUI:7419F86* + ID_OUI_FROM_DATABASE=Baudisch Electronic GmbH + +OUI:7419F87* + ID_OUI_FROM_DATABASE=Heptagon Systems PTY. LTD. + +OUI:7419F88* + ID_OUI_FROM_DATABASE=Quest Payment Systems + +OUI:7419F89* + ID_OUI_FROM_DATABASE=Princip a.s. + +OUI:7419F8A* + ID_OUI_FROM_DATABASE=Tanjarine + +OUI:7419F8B* + ID_OUI_FROM_DATABASE=IDEXX Laboratories, Inc + +OUI:7419F8C* + ID_OUI_FROM_DATABASE=Bach Icon ApS + +OUI:7419F8D* + ID_OUI_FROM_DATABASE=Ansjer Electronics Co., Ltd. + +OUI:7419F8E* + ID_OUI_FROM_DATABASE=Volacomm Co., Ltd + +OUI:7419F8F* + ID_OUI_FROM_DATABASE=Private + +OUI:741AE00* + ID_OUI_FROM_DATABASE=Huano International Technology Limited + +OUI:741AE01* + ID_OUI_FROM_DATABASE=Socionext Inc. + +OUI:741AE02* + ID_OUI_FROM_DATABASE=NURA HOLDINGS PTY LTD + +OUI:741AE03* + ID_OUI_FROM_DATABASE=Philips Personal Health Solutions + +OUI:741AE04* + ID_OUI_FROM_DATABASE=Revl Inc. + +OUI:741AE05* + ID_OUI_FROM_DATABASE=FUJIAN TAILI COMMUNICATION TECHNOLOGY CO.,LTD + +OUI:741AE06* + ID_OUI_FROM_DATABASE=Blocks Wearables Inc. + +OUI:741AE07* + ID_OUI_FROM_DATABASE=BÄR Bahnsicherung AG + +OUI:741AE08* + ID_OUI_FROM_DATABASE=Broadcast Wireless Systems Ltd + +OUI:741AE09* + ID_OUI_FROM_DATABASE=Private + +OUI:741AE0A* + ID_OUI_FROM_DATABASE=SAIERCOM CORPORATION + +OUI:741AE0B* + ID_OUI_FROM_DATABASE=SHEN ZHEN YINGJIACHUANG ELECTRONICS TECHNOLOGY CO.,LTD. + +OUI:741AE0C* + ID_OUI_FROM_DATABASE=bistos.co.ltd + +OUI:741AE0D* + ID_OUI_FROM_DATABASE=Voltaware Services Limited + +OUI:741AE0E* + ID_OUI_FROM_DATABASE=ITS Partner (O.B.S) S.L. + +OUI:741BB2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:741C27* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:741E93* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:741F4A* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:741F79* + ID_OUI_FROM_DATABASE=YOUNGKOOK ELECTRONICS CO.,LTD + +OUI:7422BB* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:742344* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:74258A* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:7426AC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:74273C* + ID_OUI_FROM_DATABASE=ChangYang Technology (Nanjing) Co., LTD + +OUI:7427EA* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:742857* + ID_OUI_FROM_DATABASE=Mayfield Robotics + +OUI:7429AF* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:742B0F* + ID_OUI_FROM_DATABASE=Infinidat Ltd. + +OUI:742B62* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:742D0A* + ID_OUI_FROM_DATABASE=Norfolk Elektronik AG + +OUI:742EDB* + ID_OUI_FROM_DATABASE=Perinet GmbH + +OUI:742EFC* + ID_OUI_FROM_DATABASE=DirectPacket Research, Inc, + +OUI:742F68* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:743170* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:743256* + ID_OUI_FROM_DATABASE=NT-ware Systemprg GmbH + +OUI:743400* + ID_OUI_FROM_DATABASE=MTG Co., Ltd. + +OUI:7434AE* + ID_OUI_FROM_DATABASE=this is engineering Inc. + +OUI:74366D* + ID_OUI_FROM_DATABASE=Vodafone Italia S.p.A. + +OUI:74372F* + ID_OUI_FROM_DATABASE=Tongfang Shenzhen Cloudcomputing Technology Co.,Ltd + +OUI:74373B* + ID_OUI_FROM_DATABASE=UNINET Co.,Ltd. + +OUI:743889* + ID_OUI_FROM_DATABASE=ANNAX Anzeigesysteme GmbH + +OUI:7438B7* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:743A65* + ID_OUI_FROM_DATABASE=NEC Corporation + +OUI:743AEF* + ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD. + +OUI:743C18* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:743E2B* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:743ECB* + ID_OUI_FROM_DATABASE=Gentrice tech + +OUI:7440BB* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:7440BE* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:74428B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:744401* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:74458A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7445CE* + ID_OUI_FROM_DATABASE=CRESYN + +OUI:7446A0* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:744AA4* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:744BE9* + ID_OUI_FROM_DATABASE=EXPLORER HYPERTECH CO.,LTD + +OUI:744D28* + ID_OUI_FROM_DATABASE=Routerboard.com + +OUI:744D79* + ID_OUI_FROM_DATABASE=Arrive Systems Inc. + +OUI:7451BA* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:745327* + ID_OUI_FROM_DATABASE=COMMSEN CO., LIMITED + +OUI:745427* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:74547D* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:745612* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:745798* + ID_OUI_FROM_DATABASE=TRUMPF Laser GmbH + Co. KG + +OUI:745909* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:745933* + ID_OUI_FROM_DATABASE=Danal Entertainment + +OUI:745AAA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:745BC50* + ID_OUI_FROM_DATABASE=IRS Systementwicklung GmbH + +OUI:745BC51* + ID_OUI_FROM_DATABASE=Beijing Inspiry Technology Co., Ltd. + +OUI:745BC52* + ID_OUI_FROM_DATABASE=SIGLENT TECHNOLOGIES CO., LTD. + +OUI:745BC53* + ID_OUI_FROM_DATABASE=OXON AG + +OUI:745BC54* + ID_OUI_FROM_DATABASE=uGrid Network Inc. + +OUI:745BC55* + ID_OUI_FROM_DATABASE=SpringCard + +OUI:745BC56* + ID_OUI_FROM_DATABASE=Yekani Manufacturing PTY Ltd + +OUI:745BC57* + ID_OUI_FROM_DATABASE=SHENZHEN ATX TECHNOLOGY CO.,LTD + +OUI:745BC58* + ID_OUI_FROM_DATABASE=EDOMO Systems GmbH + +OUI:745BC59* + ID_OUI_FROM_DATABASE=Haikou Frun Flash&Mcu Microcontrol Technology Development Co.,Ltd + +OUI:745BC5A* + ID_OUI_FROM_DATABASE=Fournie Grospaud Energie SASU + +OUI:745BC5B* + ID_OUI_FROM_DATABASE=Smartiply Inc. + +OUI:745BC5C* + ID_OUI_FROM_DATABASE=ComNot + +OUI:745BC5D* + ID_OUI_FROM_DATABASE=CELYSS SAS + +OUI:745BC5E* + ID_OUI_FROM_DATABASE=Qingdao Wintec System Co., Ltd + +OUI:745C4B* + ID_OUI_FROM_DATABASE=GN Audio A/S + +OUI:745C9F* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:745E1C* + ID_OUI_FROM_DATABASE=PIONEER CORPORATION + +OUI:745F00* + ID_OUI_FROM_DATABASE=Samsung Semiconductor Inc. + +OUI:745F90* + ID_OUI_FROM_DATABASE=LAM Technologies + +OUI:745FAE* + ID_OUI_FROM_DATABASE=TSL PPL + +OUI:7460FA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:74614B* + ID_OUI_FROM_DATABASE=Chongqing Huijiatong Information Technology Co., Ltd. + +OUI:7463DF* + ID_OUI_FROM_DATABASE=VTS GmbH + +OUI:7465D1* + ID_OUI_FROM_DATABASE=Atlinks + +OUI:746630* + ID_OUI_FROM_DATABASE=T:mi Ytti + +OUI:7467F7* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:746A3A* + ID_OUI_FROM_DATABASE=Aperi Corporation + +OUI:746A89* + ID_OUI_FROM_DATABASE=Rezolt Corporation + +OUI:746A8F* + ID_OUI_FROM_DATABASE=VS Vision Systems GmbH + +OUI:746B82* + ID_OUI_FROM_DATABASE=MOVEK + +OUI:746BAB* + ID_OUI_FROM_DATABASE=GUANGDONG ENOK COMMUNICATION CO., LTD + +OUI:746EE4* + ID_OUI_FROM_DATABASE=Asia Vital Components Co.,Ltd. + +OUI:746F19* + ID_OUI_FROM_DATABASE=ICARVISIONS (SHENZHEN) TECHNOLOGY CO., LTD. + +OUI:746F3D* + ID_OUI_FROM_DATABASE=Contec GmbH + +OUI:746FF7* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:7470FD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:74721E* + ID_OUI_FROM_DATABASE=Edison Labs Inc. + +OUI:7472B0* + ID_OUI_FROM_DATABASE=Guangzhou Shiyuan Electronics Co., Ltd. + +OUI:7472F2* + ID_OUI_FROM_DATABASE=Chipsip Technology Co., Ltd. + +OUI:747336* + ID_OUI_FROM_DATABASE=MICRODIGTAL Inc + +OUI:747548* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:747818* + ID_OUI_FROM_DATABASE=Jurumani Solutions + +OUI:747B7A* + ID_OUI_FROM_DATABASE=ETH Inc. + +OUI:747D24* + ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd. + +OUI:747DB6* + ID_OUI_FROM_DATABASE=Aliwei Communications, Inc + +OUI:747E1A* + ID_OUI_FROM_DATABASE=Red Embedded Design Limited + +OUI:747E2D* + ID_OUI_FROM_DATABASE=Beijing Thomson CITIC Digital Technology Co. LTD. + +OUI:748114* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:74819A* + ID_OUI_FROM_DATABASE=PT. Hartono Istana Teknologi + +OUI:7483C2* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:7483EF* + ID_OUI_FROM_DATABASE=Arista Networks + +OUI:7484E1* + ID_OUI_FROM_DATABASE=Dongguan Haoyuan Electronics Co.,Ltd + +OUI:74852A* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:7485C4* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:74860B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:74867A* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:7487A9* + ID_OUI_FROM_DATABASE=OCT Technology Co., Ltd. + +OUI:7487BB* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:74882A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:74888B* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:7488BB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:748A0D* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:748A28* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:748A69* + ID_OUI_FROM_DATABASE=Korea Image Technology Co., Ltd + +OUI:748B34* + ID_OUI_FROM_DATABASE=Shanghai Smart System Technology Co., Ltd + +OUI:748D08* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:748E08* + ID_OUI_FROM_DATABASE=Bestek Corp. + +OUI:748EF8* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:748F1B* + ID_OUI_FROM_DATABASE=MasterImage 3D + +OUI:748F4D* + ID_OUI_FROM_DATABASE=MEN Mikro Elektronik GmbH + +OUI:749050* + ID_OUI_FROM_DATABASE=Renesas Electronics Corporation + +OUI:74911A* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:7491BD* + ID_OUI_FROM_DATABASE=Four systems Co.,Ltd. + +OUI:7493A4* + ID_OUI_FROM_DATABASE=Zebra Technologies Corp. + +OUI:74943D* + ID_OUI_FROM_DATABASE=AgJunction + +OUI:7495EC* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:749637* + ID_OUI_FROM_DATABASE=Todaair Electronic Co., Ltd + +OUI:749781* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:749975* + ID_OUI_FROM_DATABASE=IBM Corporation + +OUI:749BE8* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:749C52* + ID_OUI_FROM_DATABASE=Huizhou Desay SV Automotive Co., Ltd. + +OUI:749CE3* + ID_OUI_FROM_DATABASE=KodaCloud Canada, Inc + +OUI:749D79* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:749D8F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:749DDC* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:749EA5* + ID_OUI_FROM_DATABASE=OHSUNG + +OUI:749EAF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:749EF5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:74A02F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:74A063* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:74A2E6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:74A34A* + ID_OUI_FROM_DATABASE=ZIMI CORPORATION + +OUI:74A4A7* + ID_OUI_FROM_DATABASE=QRS Music Technologies, Inc. + +OUI:74A4B5* + ID_OUI_FROM_DATABASE=Powerleader Science and Technology Co. Ltd. + +OUI:74A528* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:74A722* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:74A78E* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:74AC5F* + ID_OUI_FROM_DATABASE=Qiku Internet Network Scientific (Shenzhen) Co., Ltd. + +OUI:74ACB9* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:74ADB7* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:74AE76* + ID_OUI_FROM_DATABASE=iNovo Broadband, Inc. + +OUI:74B00C* + ID_OUI_FROM_DATABASE=Network Video Technologies, Inc + +OUI:74B472* + ID_OUI_FROM_DATABASE=CIESSE + +OUI:74B57E* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:74B587* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:74B6B6* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:74B91E* + ID_OUI_FROM_DATABASE=Nanjing Bestway Automation System Co., Ltd + +OUI:74B9EB* + ID_OUI_FROM_DATABASE=JinQianMao Technology Co.,Ltd. + +OUI:74BADB* + ID_OUI_FROM_DATABASE=Longconn Electornics(shenzhen)Co.,Ltd + +OUI:74BBD3* + ID_OUI_FROM_DATABASE=Shenzhen xeme Communication Co., Ltd. + +OUI:74BE08* + ID_OUI_FROM_DATABASE=ATEK Products, LLC + +OUI:74BFA1* + ID_OUI_FROM_DATABASE=HYUNTECK + +OUI:74BFB7* + ID_OUI_FROM_DATABASE=Nusoft Corporation + +OUI:74BFC0* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:74C14F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:74C17D* + ID_OUI_FROM_DATABASE=Infinix mobility limited + +OUI:74C246* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:74C330* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:74C621* + ID_OUI_FROM_DATABASE=Zhejiang Hite Renewable Energy Co.,LTD + +OUI:74C63B* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:74C929* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:74C99A* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:74C9A3* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:74CA25* + ID_OUI_FROM_DATABASE=Calxeda, Inc. + +OUI:74CC39* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:74CD0C* + ID_OUI_FROM_DATABASE=Smith Myers Communications Ltd. + +OUI:74CE56* + ID_OUI_FROM_DATABASE=Packet Force Technology Limited Company + +OUI:74D02B* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:74D0DC* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:74D21D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:74D435* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:74D637* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:74D654* + ID_OUI_FROM_DATABASE=GINT + +OUI:74D675* + ID_OUI_FROM_DATABASE=WYMA Tecnologia + +OUI:74D6EA* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:74D7CA* + ID_OUI_FROM_DATABASE=Panasonic Corporation Automotive + +OUI:74D83E* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:74D850* + ID_OUI_FROM_DATABASE=Evrisko Systems + +OUI:74DA38* + ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. + +OUI:74DA88* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:74DADA* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:74DAEA* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:74DBD1* + ID_OUI_FROM_DATABASE=Ebay Inc + +OUI:74DE2B* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:74DFBF* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:74E06E* + ID_OUI_FROM_DATABASE=Ergophone GmbH + +OUI:74E14A0* + ID_OUI_FROM_DATABASE=Altenburger Electronic GmbH + +OUI:74E14A1* + ID_OUI_FROM_DATABASE=Cerevo Inc. + +OUI:74E14A2* + ID_OUI_FROM_DATABASE=KLIMAT SOLEC Sp. z o.o. + +OUI:74E14A3* + ID_OUI_FROM_DATABASE=emz-Hanauer GmbH & Co. KGaA + +OUI:74E14A4* + ID_OUI_FROM_DATABASE=open joint stock company YUG-SISTEMA plus + +OUI:74E14A5* + ID_OUI_FROM_DATABASE=UTU Oy + +OUI:74E14A6* + ID_OUI_FROM_DATABASE=Emerging Technology (Holdings) Ltd. + +OUI:74E14A7* + ID_OUI_FROM_DATABASE=APM Technologies (DongGuan) Ltd + +OUI:74E14A8* + ID_OUI_FROM_DATABASE=aritec gmbh + +OUI:74E14A9* + ID_OUI_FROM_DATABASE=Kanto Aircraft Instrument Co., Ltd. + +OUI:74E14AA* + ID_OUI_FROM_DATABASE=AStar Design Service Technologies Co., Ltd. + +OUI:74E14AB* + ID_OUI_FROM_DATABASE=Loctek Visual Technology Corp. + +OUI:74E14AC* + ID_OUI_FROM_DATABASE=Wuhan Shenghong Laser Projection Technology Co.,LTD + +OUI:74E14AD* + ID_OUI_FROM_DATABASE=Knog Pty Ltd + +OUI:74E14AE* + ID_OUI_FROM_DATABASE=Diamond Kinetics + +OUI:74E14AF* + ID_OUI_FROM_DATABASE=Private + +OUI:74E182* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:74E19A* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:74E1B6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:74E277* + ID_OUI_FROM_DATABASE=Vizmonet Pte Ltd + +OUI:74E28C* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:74E2F5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:74E424* + ID_OUI_FROM_DATABASE=APISTE CORPORATION + +OUI:74E50B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:74E537* + ID_OUI_FROM_DATABASE=RADSPIN + +OUI:74E543* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:74E5F9* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:74E60F* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:74E6E2* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:74E7C6* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:74EA3A* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:74EAC8* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:74EACB* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:74EAE8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:74EB80* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:74EC42* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:74ECF1* + ID_OUI_FROM_DATABASE=Acumen + +OUI:74EE2A* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD + +OUI:74F06D* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:74F07D* + ID_OUI_FROM_DATABASE=BnCOM Co.,Ltd + +OUI:74F102* + ID_OUI_FROM_DATABASE=Beijing HCHCOM Technology Co., Ltd + +OUI:74F413* + ID_OUI_FROM_DATABASE=Maxwell Forest + +OUI:74F612* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:74F61C* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:74F661* + ID_OUI_FROM_DATABASE=Schneider Electric Fire & Security Oy + +OUI:74F726* + ID_OUI_FROM_DATABASE=Neuron Robotics + +OUI:74F737* + ID_OUI_FROM_DATABASE=KCE + +OUI:74F85D* + ID_OUI_FROM_DATABASE=Berkeley Nucleonics Corp + +OUI:74F8DB0* + ID_OUI_FROM_DATABASE=Enercon Technologies + +OUI:74F8DB1* + ID_OUI_FROM_DATABASE=GHL Advanced Technology GmbH & Co. KG + +OUI:74F8DB2* + ID_OUI_FROM_DATABASE=Shenzhen Ruishi Information Technology Co.,Ltd. + +OUI:74F8DB3* + ID_OUI_FROM_DATABASE=InnoTrans Communications + +OUI:74F8DB4* + ID_OUI_FROM_DATABASE=WiFi Hotspots, SL + +OUI:74F8DB5* + ID_OUI_FROM_DATABASE=Provision-ISR + +OUI:74F8DB6* + ID_OUI_FROM_DATABASE=Shenzhen Melon Electronics Co.,Ltd + +OUI:74F8DB7* + ID_OUI_FROM_DATABASE=Wuhan Tianyu Information Industry Co., Ltd. + +OUI:74F8DB8* + ID_OUI_FROM_DATABASE=Songam Syscom Co. LTD. + +OUI:74F8DB9* + ID_OUI_FROM_DATABASE=Avantree Corporation + +OUI:74F8DBA* + ID_OUI_FROM_DATABASE=Ballard Technology, Inc, + +OUI:74F8DBB* + ID_OUI_FROM_DATABASE=Capwave Technologies Inc + +OUI:74F8DBC* + ID_OUI_FROM_DATABASE=TBM CO., LTD. + +OUI:74F8DBD* + ID_OUI_FROM_DATABASE=Simon Electric (China) Co.,ltd + +OUI:74F8DBE* + ID_OUI_FROM_DATABASE=Bernard Krone Holding GmbH & Co. KG + +OUI:74F8DBF* + ID_OUI_FROM_DATABASE=Private + +OUI:74F91A* + ID_OUI_FROM_DATABASE=Onface + +OUI:74FDA0* + ID_OUI_FROM_DATABASE=Compupal (Group) Corporation + +OUI:74FE48* + ID_OUI_FROM_DATABASE=ADVANTECH CO., LTD. + +OUI:74FF4C* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:74FF7D* + ID_OUI_FROM_DATABASE=Wren Sound Systems, LLC + +OUI:78009E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:78028F* + ID_OUI_FROM_DATABASE=Adaptive Spectrum and Signal Alignment (ASSIA), Inc. + +OUI:7802B1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7802B7* + ID_OUI_FROM_DATABASE=ShenZhen Ultra Easy Technology CO.,LTD + +OUI:7802F8* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:780473* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:780541* + ID_OUI_FROM_DATABASE=Queclink Wireless Solutions Co., Ltd + +OUI:78055F* + ID_OUI_FROM_DATABASE=Shenzhen WYC Technology Co., Ltd. + +OUI:780738* + ID_OUI_FROM_DATABASE=Z.U.K. Elzab S.A. + +OUI:780AC7* + ID_OUI_FROM_DATABASE=Baofeng TV Co., Ltd. + +OUI:780CB8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:780CF0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:780ED1* + ID_OUI_FROM_DATABASE=TRUMPF Werkzeugmaschinen GmbH+Co.KG + +OUI:780F77* + ID_OUI_FROM_DATABASE=HangZhou Gubei Electronics Technology Co.,Ltd + +OUI:781185* + ID_OUI_FROM_DATABASE=NBS Payment Solutions Inc. + +OUI:7811DC* + ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD + +OUI:7812B8* + ID_OUI_FROM_DATABASE=ORANTEK LIMITED + +OUI:781735* + ID_OUI_FROM_DATABASE=Nokia Shanghai Bell Co., Ltd. + +OUI:7817BE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:781881* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:78192E* + ID_OUI_FROM_DATABASE=NASCENT Technology + +OUI:7819F7* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:781C5A* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:781D4A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:781DBA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:781DFD* + ID_OUI_FROM_DATABASE=Jabil Inc + +OUI:781FDB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:782079* + ID_OUI_FROM_DATABASE=ID Tech + +OUI:78223D* + ID_OUI_FROM_DATABASE=Affirmed Networks + +OUI:782327* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7823AE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:7824AF* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:782544* + ID_OUI_FROM_DATABASE=Omnima Limited + +OUI:78257A* + ID_OUI_FROM_DATABASE=LEO Innovation Lab + +OUI:7825AD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7828CA* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:7829ED* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:782A79* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:782BCB* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:782C29* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:782D7E* + ID_OUI_FROM_DATABASE=TRENDnet, Inc. + +OUI:782EEF* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:782F17* + ID_OUI_FROM_DATABASE=Xlab Co.,Ltd + +OUI:78303B* + ID_OUI_FROM_DATABASE=Stephen Technologies Co.,Limited + +OUI:7830E1* + ID_OUI_FROM_DATABASE=UltraClenz, LLC + +OUI:78312B* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:7831C1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:78321B* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:78324F* + ID_OUI_FROM_DATABASE=Millennium Group, Inc. + +OUI:7835A0* + ID_OUI_FROM_DATABASE=Zurn Industries LLC + +OUI:783607* + ID_OUI_FROM_DATABASE=Cermate Technologies Inc. + +OUI:783690* + ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + +OUI:7836CC* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:783A6C* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:783A84* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:783CE3* + ID_OUI_FROM_DATABASE=Kai-EE + +OUI:783D5B* + ID_OUI_FROM_DATABASE=TELNET Redes Inteligentes S.A. + +OUI:783E53* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:783F15* + ID_OUI_FROM_DATABASE=EasySYNC Ltd. + +OUI:7840E4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:784405* + ID_OUI_FROM_DATABASE=FUJITU(HONG KONG) ELECTRONIC Co.,LTD. + +OUI:784476* + ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. + +OUI:7844FD* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:784501* + ID_OUI_FROM_DATABASE=Biamp Systems + +OUI:784561* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. + +OUI:7845C4* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:7846C4* + ID_OUI_FROM_DATABASE=DAEHAP HYPER-TECH + +OUI:78471D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7847E3* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOM CO.,LTD + +OUI:784859* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:78491D* + ID_OUI_FROM_DATABASE=The Will-Burt Company + +OUI:784B08* + ID_OUI_FROM_DATABASE=f.robotics acquisitions ltd + +OUI:784B87* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:784F43* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:784F9B* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:78507C* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:78510C* + ID_OUI_FROM_DATABASE=LiveU Ltd. + +OUI:78521A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:78524A* + ID_OUI_FROM_DATABASE=Ensenso GmbH + +OUI:785262* + ID_OUI_FROM_DATABASE=Shenzhen Hojy Software Co., Ltd. + +OUI:78530D* + ID_OUI_FROM_DATABASE=Shenzhen Skyworth Digital Technology CO., Ltd + +OUI:785364* + ID_OUI_FROM_DATABASE=SHIFT GmbH + +OUI:7853F2* + ID_OUI_FROM_DATABASE=ROXTON Ltd. + +OUI:78542E* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:785517* + ID_OUI_FROM_DATABASE=SankyuElectronics + +OUI:785712* + ID_OUI_FROM_DATABASE=Mobile Integration Workgroup + +OUI:785860* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7858F3* + ID_OUI_FROM_DATABASE=Vachen Co.,Ltd + +OUI:78593E* + ID_OUI_FROM_DATABASE=RAFI GmbH & Co.KG + +OUI:78595E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:785968* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:785C28* + ID_OUI_FROM_DATABASE=Prime Motion Inc. + +OUI:785C72* + ID_OUI_FROM_DATABASE=Hioso Technology Co., Ltd. + +OUI:785DC8* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:785F4C* + ID_OUI_FROM_DATABASE=Argox Information Co., Ltd. + +OUI:78617C* + ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD. + +OUI:786256* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7864E6* + ID_OUI_FROM_DATABASE=Green Motive Technology Limited + +OUI:786559* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:7866AE* + ID_OUI_FROM_DATABASE=ZTEC Instruments, Inc. + +OUI:7867D7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7868F7* + ID_OUI_FROM_DATABASE=YSTen Technology Co.,Ltd + +OUI:7869D4* + ID_OUI_FROM_DATABASE=Shenyang Vibrotech Instruments Inc. + +OUI:786A89* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:786C1C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:786D94* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:786DEB* + ID_OUI_FROM_DATABASE=GE Lighting + +OUI:787052* + ID_OUI_FROM_DATABASE=Welotec GmbH + +OUI:78719C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:78725D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:787B8A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:787D48* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:787D53* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:787E61* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:787F62* + ID_OUI_FROM_DATABASE=GiK mbH + +OUI:788038* + ID_OUI_FROM_DATABASE=FUNAI ELECTRIC CO., LTD. + +OUI:788102* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:78818F* + ID_OUI_FROM_DATABASE=Server Racks Australia Pty Ltd + +OUI:7881CE* + ID_OUI_FROM_DATABASE=China Mobile Iot Limited company + +OUI:78843C* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:7884EE* + ID_OUI_FROM_DATABASE=INDRA ESPACIO S.A. + +OUI:7885F4* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:78870D* + ID_OUI_FROM_DATABASE=Unifiedgateways India Private Limited + +OUI:78886D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:78888A* + ID_OUI_FROM_DATABASE=CDR Sp. z o.o. Sp. k. + +OUI:788973* + ID_OUI_FROM_DATABASE=CMC + +OUI:788A20* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:788B2A* + ID_OUI_FROM_DATABASE=Zhen Shi Information Technology (Shanghai) Co., Ltd. + +OUI:788B77* + ID_OUI_FROM_DATABASE=Standar Telecom + +OUI:788C4D* + ID_OUI_FROM_DATABASE=Indyme Solutions, LLC + +OUI:788C54* + ID_OUI_FROM_DATABASE=Ping Communication + +OUI:788C77* + ID_OUI_FROM_DATABASE=LEXMARK INTERNATIONAL, INC. + +OUI:788DF7* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:788E33* + ID_OUI_FROM_DATABASE=Jiangsu SEUIC Technology Co.,Ltd + +OUI:78923E* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:78929C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:7894B4* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:7894E8* + ID_OUI_FROM_DATABASE=Radio Bridge + +OUI:789682* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:789684* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:7897C3* + ID_OUI_FROM_DATABASE=DINGXIN INFORMATION TECHNOLOGY CO.,LTD + +OUI:7898FD* + ID_OUI_FROM_DATABASE=Q9 Networks Inc. + +OUI:78995C* + ID_OUI_FROM_DATABASE=Nationz Technologies Inc + +OUI:789966* + ID_OUI_FROM_DATABASE=Musilab Electronics (DongGuan)Co.,Ltd. + +OUI:78998F* + ID_OUI_FROM_DATABASE=MEDILINE ITALIA SRL + +OUI:789C85* + ID_OUI_FROM_DATABASE=August Home, Inc. + +OUI:789CE7* + ID_OUI_FROM_DATABASE=Shenzhen Aikede Technology Co., Ltd + +OUI:789ED0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:789F4C* + ID_OUI_FROM_DATABASE=HOERBIGER Elektronik GmbH + +OUI:789F70* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:789F87* + ID_OUI_FROM_DATABASE=Siemens AG I IA PP PRM + +OUI:78A051* + ID_OUI_FROM_DATABASE=iiNet Labs Pty Ltd + +OUI:78A106* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:78A183* + ID_OUI_FROM_DATABASE=Advidia + +OUI:78A2A0* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:78A351* + ID_OUI_FROM_DATABASE=SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD + +OUI:78A3E4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:78A504* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:78A5DD* + ID_OUI_FROM_DATABASE=Shenzhen Smarteye Digital Electronics Co., Ltd + +OUI:78A683* + ID_OUI_FROM_DATABASE=Precidata + +OUI:78A6BD* + ID_OUI_FROM_DATABASE=DAEYEON Control&Instrument Co,.Ltd + +OUI:78A6E1* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:78A714* + ID_OUI_FROM_DATABASE=Amphenol + +OUI:78A7EB* + ID_OUI_FROM_DATABASE=1MORE + +OUI:78A873* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:78AA82* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:78AB60* + ID_OUI_FROM_DATABASE=ABB Australia + +OUI:78ABBB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:78AC44* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:78ACBF* + ID_OUI_FROM_DATABASE=Igneous Systems + +OUI:78ACC0* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:78AE0C* + ID_OUI_FROM_DATABASE=Far South Networks + +OUI:78AF58* + ID_OUI_FROM_DATABASE=GIMASI SA + +OUI:78AFE4* + ID_OUI_FROM_DATABASE=Comau S.p.A + +OUI:78B213* + ID_OUI_FROM_DATABASE=DWnet Technologies(Suzhou) Corporation + +OUI:78B28D* + ID_OUI_FROM_DATABASE=Beijing Tengling Technology CO.Ltd + +OUI:78B3B9* + ID_OUI_FROM_DATABASE=ShangHai sunup lighting CO.,LTD + +OUI:78B3CE* + ID_OUI_FROM_DATABASE=Elo touch solutions + +OUI:78B46A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:78B5D2* + ID_OUI_FROM_DATABASE=Ever Treasure Industrial Limited + +OUI:78B6C1* + ID_OUI_FROM_DATABASE=AOBO Telecom Co.,Ltd + +OUI:78B6EC* + ID_OUI_FROM_DATABASE=Scuf Gaming International LLC + +OUI:78B81A* + ID_OUI_FROM_DATABASE=INTER SALES A/S + +OUI:78B84B* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:78B8D6* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc. + +OUI:78BAD0* + ID_OUI_FROM_DATABASE=Shinybow Technology Co. Ltd. + +OUI:78BAF9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:78BC1A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:78BDBC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:78BEB6* + ID_OUI_FROM_DATABASE=Enhanced Vision + +OUI:78BEBD* + ID_OUI_FROM_DATABASE=STULZ GmbH + +OUI:78C1A7* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:78C2C00* + ID_OUI_FROM_DATABASE=Shenzhen ELI Technology co.,ltd + +OUI:78C2C01* + ID_OUI_FROM_DATABASE=XRONOS-INC + +OUI:78C2C02* + ID_OUI_FROM_DATABASE=RONIX incorporated + +OUI:78C2C03* + ID_OUI_FROM_DATABASE=Ningbo Sanxing Electric Co., Ltd. + +OUI:78C2C04* + ID_OUI_FROM_DATABASE=Ory Laboratory Co., Ltd. + +OUI:78C2C05* + ID_OUI_FROM_DATABASE=ShenZhen TuLing Robot CO.,LTD + +OUI:78C2C06* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:78C2C07* + ID_OUI_FROM_DATABASE=Guangzhou Hongcai Stage Equipment co.,ltd + +OUI:78C2C08* + ID_OUI_FROM_DATABASE=Beijing Coilabs technology co.,ltd + +OUI:78C2C09* + ID_OUI_FROM_DATABASE=SES + +OUI:78C2C0A* + ID_OUI_FROM_DATABASE=Ombitron, Inc. + +OUI:78C2C0B* + ID_OUI_FROM_DATABASE=Wan Chao An (Beijing) Technology Co., Ltd. + +OUI:78C2C0C* + ID_OUI_FROM_DATABASE=Shanghai Hanyi Technologies Co,.Ltd. + +OUI:78C2C0D* + ID_OUI_FROM_DATABASE=KORF Inc. + +OUI:78C2C0E* + ID_OUI_FROM_DATABASE=Huwomobility + +OUI:78C2C0F* + ID_OUI_FROM_DATABASE=Private + +OUI:78C313* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:78C3E9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:78C40E* + ID_OUI_FROM_DATABASE=H&D Wireless + +OUI:78C4AB* + ID_OUI_FROM_DATABASE=Shenzhen Runsil Technology Co.,Ltd + +OUI:78C5E5* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:78C5F8* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:78C6BB* + ID_OUI_FROM_DATABASE=Innovasic, Inc. + +OUI:78C881* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:78CA04* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:78CA39* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:78CA5E* + ID_OUI_FROM_DATABASE=ELNO + +OUI:78CA830* + ID_OUI_FROM_DATABASE=DAINCUBE + +OUI:78CA831* + ID_OUI_FROM_DATABASE=Excelocity Inc. + +OUI:78CA832* + ID_OUI_FROM_DATABASE=APC + +OUI:78CA833* + ID_OUI_FROM_DATABASE=Neofon GmbH + +OUI:78CA834* + ID_OUI_FROM_DATABASE=Pinhole (Beijing) Technology Co., Ltd. + +OUI:78CA835* + ID_OUI_FROM_DATABASE=Huatune Technology (Shanghai) Co., Ltd. + +OUI:78CA836* + ID_OUI_FROM_DATABASE=Nomiku + +OUI:78CA837* + ID_OUI_FROM_DATABASE=Beijing CarePulse Electronic Technology + +OUI:78CA838* + ID_OUI_FROM_DATABASE=IHM + +OUI:78CA839* + ID_OUI_FROM_DATABASE=Louroe Electronics + +OUI:78CA83A* + ID_OUI_FROM_DATABASE=Eksagate Elektronik Mühendislik ve Bilgisayar San. Tic. A.Ş. + +OUI:78CA83B* + ID_OUI_FROM_DATABASE=Zhejiang Science Electronic Tech Co., Ltd + +OUI:78CA83C* + ID_OUI_FROM_DATABASE=Elanview Technology Co.,Ltd + +OUI:78CA83D* + ID_OUI_FROM_DATABASE=Hubei Boyuan Zhijia Network Media Co. Ltd. + +OUI:78CA83E* + ID_OUI_FROM_DATABASE=Konecranes + +OUI:78CB33* + ID_OUI_FROM_DATABASE=DHC Software Co.,Ltd + +OUI:78CB68* + ID_OUI_FROM_DATABASE=DAEHAP HYPER-TECH + +OUI:78CC2B* + ID_OUI_FROM_DATABASE=SINEWY TECHNOLOGY CO., LTD + +OUI:78CD8E* + ID_OUI_FROM_DATABASE=SMC Networks Inc + +OUI:78D004* + ID_OUI_FROM_DATABASE=Neousys Technology Inc. + +OUI:78D129* + ID_OUI_FROM_DATABASE=Vicos + +OUI:78D162* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:78D294* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:78D347* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:78D34F* + ID_OUI_FROM_DATABASE=Pace-O-Matic, Inc. + +OUI:78D38D* + ID_OUI_FROM_DATABASE=HONGKONG YUNLINK TECHNOLOGY LIMITED + +OUI:78D5B5* + ID_OUI_FROM_DATABASE=NAVIELEKTRO KY + +OUI:78D66F* + ID_OUI_FROM_DATABASE=Aristocrat Technologies Australia Pty. Ltd. + +OUI:78D6B2* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:78D6F0* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:78D752* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:78D75F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:78D8000* + ID_OUI_FROM_DATABASE=Kverneland Group Mechatronics + +OUI:78D8001* + ID_OUI_FROM_DATABASE=Shenzhen Envicool Information Technology Co., Ltd + +OUI:78D8002* + ID_OUI_FROM_DATABASE=Shanghai Espacetime Technology Co.,Ltd. + +OUI:78D8003* + ID_OUI_FROM_DATABASE=Shenzhen Scodeno Technology Co,. Ltd. + +OUI:78D8004* + ID_OUI_FROM_DATABASE=CS Instruments GmbH + +OUI:78D8005* + ID_OUI_FROM_DATABASE=Björkviks Consulting AB + +OUI:78D8006* + ID_OUI_FROM_DATABASE=Alango Technologies Ltd + +OUI:78D8007* + ID_OUI_FROM_DATABASE=NimbeLink Corp + +OUI:78D8008* + ID_OUI_FROM_DATABASE=Salunda Ltd + +OUI:78D8009* + ID_OUI_FROM_DATABASE=SightLine Applications + +OUI:78D800A* + ID_OUI_FROM_DATABASE=Insignal Co., Ltd. + +OUI:78D800B* + ID_OUI_FROM_DATABASE=Maddalena S.p.A. + +OUI:78D800C* + ID_OUI_FROM_DATABASE=Shenzhen Chenzhuo Technology Co., Ltd. + +OUI:78D800D* + ID_OUI_FROM_DATABASE=Korea Micro Wireless Co.,Ltd. + +OUI:78D800E* + ID_OUI_FROM_DATABASE=CL International + +OUI:78D99F* + ID_OUI_FROM_DATABASE=NuCom HK Ltd. + +OUI:78DA07* + ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd. + +OUI:78DA6E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:78DAA2* + ID_OUI_FROM_DATABASE=Cynosure Technologies Co.,Ltd + +OUI:78DAB3* + ID_OUI_FROM_DATABASE=GBO Technology + +OUI:78DB2F* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:78DD08* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:78DD12* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:78DDD6* + ID_OUI_FROM_DATABASE=c-scape + +OUI:78DDD9* + ID_OUI_FROM_DATABASE=Guangzhou Shiyuan Electronics Co., Ltd. + +OUI:78DEE4* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:78E103* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:78E2BD* + ID_OUI_FROM_DATABASE=Vodafone Automotive S.p.A. + +OUI:78E3B5* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:78E400* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:78E7D1* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:78E8B6* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:78E980* + ID_OUI_FROM_DATABASE=RainUs Co.,Ltd + +OUI:78EB14* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:78EB39* + ID_OUI_FROM_DATABASE=Instituto Nacional de Tecnología Industrial + +OUI:78EC22* + ID_OUI_FROM_DATABASE=Shanghai Qihui Telecom Technology Co., LTD + +OUI:78EC74* + ID_OUI_FROM_DATABASE=Kyland-USA + +OUI:78EF4C* + ID_OUI_FROM_DATABASE=Unetconvergence Co., Ltd. + +OUI:78F29E* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:78F557* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:78F5E5* + ID_OUI_FROM_DATABASE=BEGA Gantenbrink-Leuchten KG + +OUI:78F5FD* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:78F7BE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:78F7D0* + ID_OUI_FROM_DATABASE=Silverbrook Research + +OUI:78F882* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:78F944* + ID_OUI_FROM_DATABASE=Private + +OUI:78F9B4* + ID_OUI_FROM_DATABASE=Nokia + +OUI:78FC14* + ID_OUI_FROM_DATABASE=Family Zone Cyber Safety Ltd + +OUI:78FD94* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:78FE3D* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:78FE41* + ID_OUI_FROM_DATABASE=Socus networks + +OUI:78FEE2* + ID_OUI_FROM_DATABASE=Shanghai Diveo Technology Co., Ltd + +OUI:78FF57* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:78FFCA* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:7C010A* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:7C0187* + ID_OUI_FROM_DATABASE=Curtis Instruments, Inc. + +OUI:7C0191* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7C02BC* + ID_OUI_FROM_DATABASE=Hansung Electronics Co. LTD + +OUI:7C034C* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:7C035E* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:7C03AB* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:7C03C9* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:7C03D8* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:7C04D0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7C0507* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:7C051E* + ID_OUI_FROM_DATABASE=RAFAEL LTD. + +OUI:7C0623* + ID_OUI_FROM_DATABASE=Ultra Electronics Sonar System Division + +OUI:7C08D9* + ID_OUI_FROM_DATABASE=Shanghai B-Star Technology Co + +OUI:7C092B* + ID_OUI_FROM_DATABASE=Bekey A/S + +OUI:7C0A50* + ID_OUI_FROM_DATABASE=J-MEX Inc. + +OUI:7C0BC6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C0CF6* + ID_OUI_FROM_DATABASE=Guangdong Huiwei High-tech Co., Ltd. + +OUI:7C0ECE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7C1015* + ID_OUI_FROM_DATABASE=Brilliant Home Technology, Inc. + +OUI:7C11BE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7C11CB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7C11CD* + ID_OUI_FROM_DATABASE=QianTang Technology + +OUI:7C1476* + ID_OUI_FROM_DATABASE=Damall Technologies SAS + +OUI:7C160D* + ID_OUI_FROM_DATABASE=Saia-Burgess Controls AG + +OUI:7C18CD* + ID_OUI_FROM_DATABASE=E-TRON Co.,Ltd. + +OUI:7C1A03* + ID_OUI_FROM_DATABASE=8Locations Co., Ltd. + +OUI:7C1AFC* + ID_OUI_FROM_DATABASE=Dalian Co-Edifice Video Technology Co., Ltd + +OUI:7C1C4E* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:7C1C68* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C1CF1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7C1DD9* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:7C1E06* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:7C1E52* + ID_OUI_FROM_DATABASE=Microsoft + +OUI:7C1EB3* + ID_OUI_FROM_DATABASE=2N TELEKOMUNIKACE a.s. + +OUI:7C2048* + ID_OUI_FROM_DATABASE=KoamTac + +OUI:7C2064* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:7C210D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7C210E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7C21D8* + ID_OUI_FROM_DATABASE=Shenzhen Think Will Communication Technology co., LTD. + +OUI:7C2302* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C240C* + ID_OUI_FROM_DATABASE=Telechips, Inc. + +OUI:7C2586* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:7C2587* + ID_OUI_FROM_DATABASE=chaowifi.com + +OUI:7C2634* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:7C2664* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:7C2A31* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:7C2BE1* + ID_OUI_FROM_DATABASE=Shenzhen Ferex Electrical Co.,Ltd + +OUI:7C2CF3* + ID_OUI_FROM_DATABASE=Secure Electrans Ltd + +OUI:7C2E0D* + ID_OUI_FROM_DATABASE=Blackmagic Design + +OUI:7C2EBD* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:7C2EDD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C2F80* + ID_OUI_FROM_DATABASE=Gigaset Communications GmbH + +OUI:7C310E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7C336E* + ID_OUI_FROM_DATABASE=MEG Electronics Inc. + +OUI:7C3548* + ID_OUI_FROM_DATABASE=Transcend Information + +OUI:7C3866* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:7C386C* + ID_OUI_FROM_DATABASE=Real Time Logic + +OUI:7C38AD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C3920* + ID_OUI_FROM_DATABASE=SSOMA SECURITY + +OUI:7C3953* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:7C3BD5* + ID_OUI_FROM_DATABASE=Imago Group + +OUI:7C3CB6* + ID_OUI_FROM_DATABASE=Shenzhen Homecare Technology Co.,Ltd. + +OUI:7C3E9D* + ID_OUI_FROM_DATABASE=PATECH + +OUI:7C41A2* + ID_OUI_FROM_DATABASE=Nokia + +OUI:7C438F* + ID_OUI_FROM_DATABASE=E-Band Communications Corp. + +OUI:7C444C* + ID_OUI_FROM_DATABASE=Entertainment Solutions, S.L. + +OUI:7C4685* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:7C477C0* + ID_OUI_FROM_DATABASE=BungBungame Inc + +OUI:7C477C1* + ID_OUI_FROM_DATABASE=Photosynth Inc. + +OUI:7C477C2* + ID_OUI_FROM_DATABASE=POWERLAND LIMITED + +OUI:7C477C3* + ID_OUI_FROM_DATABASE=EyeLock LLC + +OUI:7C477C4* + ID_OUI_FROM_DATABASE=RLC Electronics Systems + +OUI:7C477C5* + ID_OUI_FROM_DATABASE=Midwest Microwave Solutions + +OUI:7C477C6* + ID_OUI_FROM_DATABASE=Zerosystem LTD.Co + +OUI:7C477C7* + ID_OUI_FROM_DATABASE=BlueSmart Technology Corporation + +OUI:7C477C8* + ID_OUI_FROM_DATABASE=Shenzhen Eunicum Electric Co.,Ltd. + +OUI:7C477C9* + ID_OUI_FROM_DATABASE=DaLian Cheering Tech Co.,Ltd + +OUI:7C477CA* + ID_OUI_FROM_DATABASE=Dspread Technology (Beijing) Inc. + +OUI:7C477CB* + ID_OUI_FROM_DATABASE=Hangzhou Yiyitaidi Information Technology Co., Ltd. + +OUI:7C477CC* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:7C477CD* + ID_OUI_FROM_DATABASE=Speedifi Inc + +OUI:7C477CE* + ID_OUI_FROM_DATABASE=I-Convergence.com + +OUI:7C48B2* + ID_OUI_FROM_DATABASE=Vida Resources Lte Ltd + +OUI:7C49B9* + ID_OUI_FROM_DATABASE=Plexus Manufacturing Sdn Bhd + +OUI:7C49EB* + ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD + +OUI:7C4A82* + ID_OUI_FROM_DATABASE=Portsmith LLC + +OUI:7C4AA8* + ID_OUI_FROM_DATABASE=MindTree Wireless PVT Ltd + +OUI:7C4B78* + ID_OUI_FROM_DATABASE=Red Sun Synthesis Pte Ltd + +OUI:7C4C58* + ID_OUI_FROM_DATABASE=Scale Computing, Inc. + +OUI:7C4CA5* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:7C4F7D* + ID_OUI_FROM_DATABASE=Sawwave + +OUI:7C4FB5* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:7C5049* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7C50DA* + ID_OUI_FROM_DATABASE=Private + +OUI:7C5189* + ID_OUI_FROM_DATABASE=SG Wireless Limited + +OUI:7C5259* + ID_OUI_FROM_DATABASE=Sichuan Jiuzhou Electronic Technology Co., Ltd. + +OUI:7C534A* + ID_OUI_FROM_DATABASE=Metamako + +OUI:7C55E7* + ID_OUI_FROM_DATABASE=YSI, Inc. + +OUI:7C573C* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:7C574E* + ID_OUI_FROM_DATABASE=COBI GmbH + +OUI:7C5A1C* + ID_OUI_FROM_DATABASE=Sophos Ltd + +OUI:7C5A67* + ID_OUI_FROM_DATABASE=JNC Systems, Inc. + +OUI:7C5CF8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:7C604A* + ID_OUI_FROM_DATABASE=Avelon + +OUI:7C6097* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7C6166* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:7C6193* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:7C6456* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C669D* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:7C67A2* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:7C696B* + ID_OUI_FROM_DATABASE=Atmosic Technologies + +OUI:7C69F6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7C6AB3* + ID_OUI_FROM_DATABASE=IBC TECHNOLOGIES INC. + +OUI:7C6AC3* + ID_OUI_FROM_DATABASE=GatesAir, Inc + +OUI:7C6ADB* + ID_OUI_FROM_DATABASE=SafeTone Technology Co.,Ltd + +OUI:7C6AF3* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:7C6B33* + ID_OUI_FROM_DATABASE=Tenyu Tech Co. Ltd. + +OUI:7C6B52* + ID_OUI_FROM_DATABASE=Tigaro Wireless + +OUI:7C6B9C* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:7C6BF7* + ID_OUI_FROM_DATABASE=NTI co., ltd. + +OUI:7C6C39* + ID_OUI_FROM_DATABASE=PIXSYS SRL + +OUI:7C6C8F* + ID_OUI_FROM_DATABASE=AMS NEVE LTD + +OUI:7C6D62* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7C6DA6* + ID_OUI_FROM_DATABASE=Superwave Group LLC + +OUI:7C6DF8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7C6F06* + ID_OUI_FROM_DATABASE=Caterpillar Trimble Control Technologies + +OUI:7C6FF8* + ID_OUI_FROM_DATABASE=ShenZhen ACTO Digital Video Technology Co.,Ltd. + +OUI:7C70BC0* + ID_OUI_FROM_DATABASE=Shanghai magcomm communication technology co ltd + +OUI:7C70BC1* + ID_OUI_FROM_DATABASE=XD-GE Automation CO.,LTD + +OUI:7C70BC2* + ID_OUI_FROM_DATABASE=Digital Lumens + +OUI:7C70BC3* + ID_OUI_FROM_DATABASE=FLEXIM GmbH + +OUI:7C70BC4* + ID_OUI_FROM_DATABASE=K-Vision Technology (Shanghai), Ltd + +OUI:7C70BC5* + ID_OUI_FROM_DATABASE=Canary Connect, Inc. + +OUI:7C70BC6* + ID_OUI_FROM_DATABASE=Bidgely + +OUI:7C70BC7* + ID_OUI_FROM_DATABASE=Nomad Digital Ltd. + +OUI:7C70BC8* + ID_OUI_FROM_DATABASE=Mennekes Elektrotechnik GmbH & Co. KG + +OUI:7C70BC9* + ID_OUI_FROM_DATABASE=dogtra + +OUI:7C70BCA* + ID_OUI_FROM_DATABASE=Ametek VIS + +OUI:7C70BCB* + ID_OUI_FROM_DATABASE=Tohan Engineering Corporation + +OUI:7C70BCC* + ID_OUI_FROM_DATABASE=Lukup Media + +OUI:7C70BCD* + ID_OUI_FROM_DATABASE=mk-messtechnik GmbH + +OUI:7C70BCE* + ID_OUI_FROM_DATABASE=HOPERUN MMAX DIGITAL PTE. LTD. + +OUI:7C70BCF* + ID_OUI_FROM_DATABASE=Private + +OUI:7C7176* + ID_OUI_FROM_DATABASE=Wuxi iData Technology Company Ltd. + +OUI:7C72E4* + ID_OUI_FROM_DATABASE=Unikey Technologies + +OUI:7C738B* + ID_OUI_FROM_DATABASE=Cocoon Alarm Ltd + +OUI:7C7630* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:7C7635* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:7C7668* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7C7673* + ID_OUI_FROM_DATABASE=ENMAS GmbH + +OUI:7C787E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C79E8* + ID_OUI_FROM_DATABASE=PayRange Inc. + +OUI:7C7A53* + ID_OUI_FROM_DATABASE=Phytrex Technology Corp. + +OUI:7C7A91* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:7C7B8B* + ID_OUI_FROM_DATABASE=Control Concepts, Inc. + +OUI:7C7BE4* + ID_OUI_FROM_DATABASE=Z'SEDAI KENKYUSHO CORPORATION + +OUI:7C7D3D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7C7D41* + ID_OUI_FROM_DATABASE=Jinmuyu Electronics Co., Ltd. + +OUI:7C822D* + ID_OUI_FROM_DATABASE=Nortec + +OUI:7C8274* + ID_OUI_FROM_DATABASE=Shenzhen Hikeen Technology CO.,LTD + +OUI:7C8306* + ID_OUI_FROM_DATABASE=Glen Dimplex Nordic as + +OUI:7C8956* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C89C1* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:7C8AE1* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:7C8BB5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C8BCA* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:7C8D91* + ID_OUI_FROM_DATABASE=Shanghai Hongzhuo Information Technology co.,LTD + +OUI:7C8EE4* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:7C9122* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7C942A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7C94B2* + ID_OUI_FROM_DATABASE=Philips Healthcare PCCI + +OUI:7C95B1* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:7C95F3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7C96D2* + ID_OUI_FROM_DATABASE=Fihonest communication co.,Ltd + +OUI:7C9763* + ID_OUI_FROM_DATABASE=Openmatics s.r.o. + +OUI:7C9A1D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7C9A54* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:7C9A9B* + ID_OUI_FROM_DATABASE=VSE valencia smart energy + +OUI:7C9EBD* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:7CA15D* + ID_OUI_FROM_DATABASE=GN ReSound A/S + +OUI:7CA177* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7CA1AE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7CA237* + ID_OUI_FROM_DATABASE=King Slide Technology CO., LTD. + +OUI:7CA23E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7CA29B* + ID_OUI_FROM_DATABASE=D.SignT GmbH & Co. KG + +OUI:7CA61D* + ID_OUI_FROM_DATABASE=MHL, LLC + +OUI:7CA7B0* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD + +OUI:7CA97D* + ID_OUI_FROM_DATABASE=Objenious + +OUI:7CAB25* + ID_OUI_FROM_DATABASE=MESMO TECHNOLOGY INC. + +OUI:7CAB60* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7CACB2* + ID_OUI_FROM_DATABASE=Bosch Software Innovations GmbH + +OUI:7CAD74* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:7CB03E* + ID_OUI_FROM_DATABASE=OSRAM GmbH + +OUI:7CB0C2* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:7CB15D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7CB177* + ID_OUI_FROM_DATABASE=Satelco AG + +OUI:7CB21B* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:7CB232* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:7CB25C* + ID_OUI_FROM_DATABASE=Acacia Communications + +OUI:7CB27D* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:7CB37B* + ID_OUI_FROM_DATABASE=Qingdao Intelligent&Precise Electronics Co.,Ltd. + +OUI:7CB542* + ID_OUI_FROM_DATABASE=ACES Technology + +OUI:7CB59B* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:7CB733* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:7CB77B* + ID_OUI_FROM_DATABASE=Paradigm Electronics Inc + +OUI:7CB960* + ID_OUI_FROM_DATABASE=Shanghai X-Cheng telecom LTD + +OUI:7CBACC0* + ID_OUI_FROM_DATABASE=TGT Limited + +OUI:7CBACC1* + ID_OUI_FROM_DATABASE=Changsha SUNYE Electric Co., Ltd. + +OUI:7CBACC2* + ID_OUI_FROM_DATABASE=Maco Lighting Pty. Ltd. + +OUI:7CBACC3* + ID_OUI_FROM_DATABASE=Izkare + +OUI:7CBACC4* + ID_OUI_FROM_DATABASE=Sun Asia Trade Co. + +OUI:7CBACC5* + ID_OUI_FROM_DATABASE=Fortem Technologies, Inc. + +OUI:7CBACC6* + ID_OUI_FROM_DATABASE=Fossil Power Systems Inc + +OUI:7CBACC7* + ID_OUI_FROM_DATABASE=Virgin Orbit + +OUI:7CBACC8* + ID_OUI_FROM_DATABASE=Collinear Networks Inc. + +OUI:7CBACC9* + ID_OUI_FROM_DATABASE=Yongguan Electronic Technology (D.G)LTD + +OUI:7CBACCA* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:7CBACCB* + ID_OUI_FROM_DATABASE=Briowireless Inc. + +OUI:7CBACCC* + ID_OUI_FROM_DATABASE=Flying Loft Inc. + +OUI:7CBACCD* + ID_OUI_FROM_DATABASE=SIGMA-ELEKTRO GmbH + +OUI:7CBACCE* + ID_OUI_FROM_DATABASE=ALPHA TECHNOLOGIES, LLC + +OUI:7CBB6F* + ID_OUI_FROM_DATABASE=Cosco Electronics Co., Ltd. + +OUI:7CBB8A* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:7CBC840* + ID_OUI_FROM_DATABASE=AG Neovo + +OUI:7CBC841* + ID_OUI_FROM_DATABASE=Xiamen Mage Information Technology Co.,Ltd. + +OUI:7CBC842* + ID_OUI_FROM_DATABASE=3S Technology Co., Ltd. + +OUI:7CBC843* + ID_OUI_FROM_DATABASE=Shanghai Yitu Technology Co. Ltd + +OUI:7CBC844* + ID_OUI_FROM_DATABASE=CONTINENTAL + +OUI:7CBC845* + ID_OUI_FROM_DATABASE=Nanning auto digital technology co.,LTD + +OUI:7CBC846* + ID_OUI_FROM_DATABASE=Société de Transport de Montréal + +OUI:7CBC847* + ID_OUI_FROM_DATABASE=Xuji Changnan Communication Equipment Co., Ltd. + +OUI:7CBC848* + ID_OUI_FROM_DATABASE=Shenzhen Kuang-chi Space Technology Co., Ltd. + +OUI:7CBC849* + ID_OUI_FROM_DATABASE=HITIQ LIMITED + +OUI:7CBC84A* + ID_OUI_FROM_DATABASE=OPNT BV + +OUI:7CBC84B* + ID_OUI_FROM_DATABASE=Guangzhou Puppyrobot Technology Co.Ltd Beijing Branch + +OUI:7CBC84C* + ID_OUI_FROM_DATABASE=Tibit Communications + +OUI:7CBC84D* + ID_OUI_FROM_DATABASE=VANTAGE INTEGRATED SECURITY SOLUTIONS PVT LTD + +OUI:7CBC84E* + ID_OUI_FROM_DATABASE=Beijing Topnew Group Co., Ltd + +OUI:7CBD06* + ID_OUI_FROM_DATABASE=AE REFUsol + +OUI:7CBF88* + ID_OUI_FROM_DATABASE=Mobilicom LTD + +OUI:7CBFB1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:7CC385* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7CC3A1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7CC4EF* + ID_OUI_FROM_DATABASE=Devialet + +OUI:7CC537* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7CC6C4* + ID_OUI_FROM_DATABASE=Kolff Computer Supplies b.v. + +OUI:7CC709* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:7CC8AB* + ID_OUI_FROM_DATABASE=Acro Associates, Inc. + +OUI:7CC8D0* + ID_OUI_FROM_DATABASE=TIANJIN YAAN TECHNOLOGY CO., LTD. + +OUI:7CC8D7* + ID_OUI_FROM_DATABASE=Damalisk + +OUI:7CC926* + ID_OUI_FROM_DATABASE=Wuhan GreeNet Information Service Co.,Ltd. + +OUI:7CC95A* + ID_OUI_FROM_DATABASE=Dell EMC + +OUI:7CCB0D* + ID_OUI_FROM_DATABASE=Antaira Technologies, LLC + +OUI:7CCBE20* + ID_OUI_FROM_DATABASE=Heyuan Yongyida Technology Holdings Co.,Ltd. + +OUI:7CCBE21* + ID_OUI_FROM_DATABASE=CeoTronics AG + +OUI:7CCBE22* + ID_OUI_FROM_DATABASE=1000eyes GmbH + +OUI:7CCBE23* + ID_OUI_FROM_DATABASE=Astrum Technologies CC + +OUI:7CCBE24* + ID_OUI_FROM_DATABASE=Ningbo bird sales co.,LTD + +OUI:7CCBE25* + ID_OUI_FROM_DATABASE=DTECH Labs, Inc. + +OUI:7CCBE26* + ID_OUI_FROM_DATABASE=SY Electronics Limited + +OUI:7CCBE27* + ID_OUI_FROM_DATABASE=Hangzhou Kaicom Communication Co.,Ltd + +OUI:7CCBE28* + ID_OUI_FROM_DATABASE=Polarteknik Oy + +OUI:7CCBE29* + ID_OUI_FROM_DATABASE=Hangzhou Haohaokaiche Technology Co.,Ltd. + +OUI:7CCBE2A* + ID_OUI_FROM_DATABASE=Shanghai Institute of Applied Physics, Chinese Academy of Sciences + +OUI:7CCBE2B* + ID_OUI_FROM_DATABASE=Easy Broadband Technology Co., Ltd. + +OUI:7CCBE2C* + ID_OUI_FROM_DATABASE=mirakonta s.l. + +OUI:7CCBE2D* + ID_OUI_FROM_DATABASE=optilink networks pvt ltd + +OUI:7CCBE2E* + ID_OUI_FROM_DATABASE=Aplex Technology Inc. + +OUI:7CCC1F* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:7CCCB8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:7CCD11* + ID_OUI_FROM_DATABASE=MS-Magnet + +OUI:7CCD3C* + ID_OUI_FROM_DATABASE=Guangzhou Juzing Technology Co., Ltd + +OUI:7CCFCF* + ID_OUI_FROM_DATABASE=Shanghai SEARI Intelligent System Co., Ltd + +OUI:7CD1C3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7CD30A* + ID_OUI_FROM_DATABASE=INVENTEC CORPORATION + +OUI:7CD566* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:7CD661* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:7CD762* + ID_OUI_FROM_DATABASE=Freestyle Technology Pty Ltd + +OUI:7CD844* + ID_OUI_FROM_DATABASE=Enmotus Inc + +OUI:7CD95C* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:7CD9A0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:7CD9FE* + ID_OUI_FROM_DATABASE=New Cosmos Electric Co., Ltd. + +OUI:7CDA84* + ID_OUI_FROM_DATABASE=Dongnian Networks Inc. + +OUI:7CDB98* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:7CDD11* + ID_OUI_FROM_DATABASE=Chongqing MAS SCI&TECH.Co.,Ltd + +OUI:7CDD20* + ID_OUI_FROM_DATABASE=IOXOS Technologies S.A. + +OUI:7CDD76* + ID_OUI_FROM_DATABASE=Suzhou Hanming Technologies Co., Ltd. + +OUI:7CDD90* + ID_OUI_FROM_DATABASE=Shenzhen Ogemray Technology Co., Ltd. + +OUI:7CDFA1* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:7CE044* + ID_OUI_FROM_DATABASE=NEON Inc + +OUI:7CE1FF* + ID_OUI_FROM_DATABASE=Computer Performance, Inc. DBA Digital Loggers, Inc. + +OUI:7CE2CA* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:7CE4AA* + ID_OUI_FROM_DATABASE=Private + +OUI:7CE524* + ID_OUI_FROM_DATABASE=Quirky, Inc. + +OUI:7CE56B* + ID_OUI_FROM_DATABASE=ESEN Optoelectronics Technology Co.,Ltd. + +OUI:7CE97C* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:7CE9D3* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:7CEB7F* + ID_OUI_FROM_DATABASE=Dmet Products Corp. + +OUI:7CEBAE* + ID_OUI_FROM_DATABASE=Ridgeline Instruments + +OUI:7CEBEA* + ID_OUI_FROM_DATABASE=ASCT + +OUI:7CEC79* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:7CEC9B* + ID_OUI_FROM_DATABASE=Fuzhou Teraway Information Technology Co.,Ltd + +OUI:7CED8D* + ID_OUI_FROM_DATABASE=Microsoft + +OUI:7CEF18* + ID_OUI_FROM_DATABASE=Creative Product Design Pty. Ltd. + +OUI:7CEF8A* + ID_OUI_FROM_DATABASE=Inhon International Ltd. + +OUI:7CF05F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7CF098* + ID_OUI_FROM_DATABASE=Bee Beans Technologies, Inc. + +OUI:7CF0BA* + ID_OUI_FROM_DATABASE=Linkwell Telesystems Pvt Ltd + +OUI:7CF31B* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:7CF429* + ID_OUI_FROM_DATABASE=NUUO Inc. + +OUI:7CF854* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7CF90E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:7CF95C* + ID_OUI_FROM_DATABASE=U.I. Lapp GmbH + +OUI:7CFADF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:7CFC3C* + ID_OUI_FROM_DATABASE=Visteon Corporation + +OUI:7CFD82* + ID_OUI_FROM_DATABASE=GUANGDONG GENIUS TECHNOLOGY CO., LTD. + +OUI:7CFE28* + ID_OUI_FROM_DATABASE=Salutron Inc. + +OUI:7CFE4E* + ID_OUI_FROM_DATABASE=Shenzhen Safe vision Technology Co.,LTD + +OUI:7CFE90* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:7CFF4D* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:7CFF62* + ID_OUI_FROM_DATABASE=Huizhou Super Electron Technology Co.,Ltd. + +OUI:80000B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:800010* + ID_OUI_FROM_DATABASE=AT&T + +OUI:80006E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:800184* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:80029C* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:8002DF* + ID_OUI_FROM_DATABASE=ORA Inc. + +OUI:800588* + ID_OUI_FROM_DATABASE=Ruijie Networks Co.,LTD + +OUI:8005DF* + ID_OUI_FROM_DATABASE=Montage Technology Group Limited + +OUI:8007A2* + ID_OUI_FROM_DATABASE=Esson Technology Inc. + +OUI:800902* + ID_OUI_FROM_DATABASE=Keysight Technologies, Inc. + +OUI:800A06* + ID_OUI_FROM_DATABASE=COMTEC co.,ltd + +OUI:800A800* + ID_OUI_FROM_DATABASE=Golana Technology (Shenzhen) Co., Ltd. + +OUI:800A801* + ID_OUI_FROM_DATABASE=Dongguan I-Chime electrinics Co.,Ltd + +OUI:800A802* + ID_OUI_FROM_DATABASE=Sumitomo Wiring Systems, Ltd. + +OUI:800A803* + ID_OUI_FROM_DATABASE=Beijing VControl Technology Co., Ltd. + +OUI:800A804* + ID_OUI_FROM_DATABASE=LLVISION TECHNOLOGY CO.,LTD + +OUI:800A805* + ID_OUI_FROM_DATABASE=Shenzhen Zidoo Technology Co., Ltd. + +OUI:800A806* + ID_OUI_FROM_DATABASE=Beijing Gooagoo Technical Service Co.,Ltd. + +OUI:800A80F* + ID_OUI_FROM_DATABASE=Private + +OUI:800B51* + ID_OUI_FROM_DATABASE=Chengdu XGimi Technology Co.,Ltd + +OUI:800C67* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:800DD7* + ID_OUI_FROM_DATABASE=Latticework, Inc + +OUI:800E24* + ID_OUI_FROM_DATABASE=ForgetBox + +OUI:801382* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:801440* + ID_OUI_FROM_DATABASE=Sunlit System Technology Corp + +OUI:8014A8* + ID_OUI_FROM_DATABASE=Guangzhou V-SOLUTION Electronic Technology Co., Ltd. + +OUI:801609* + ID_OUI_FROM_DATABASE=Sleep Number + +OUI:8016B7* + ID_OUI_FROM_DATABASE=Brunel University + +OUI:80177D* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:801844* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:8018A7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:801934* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:801967* + ID_OUI_FROM_DATABASE=Shanghai Reallytek Information Technology Co.,Ltd + +OUI:8019FE* + ID_OUI_FROM_DATABASE=JianLing Technology CO., LTD + +OUI:801DAA* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:801F02* + ID_OUI_FROM_DATABASE=Edimax Technology Co. Ltd. + +OUI:801F12* + ID_OUI_FROM_DATABASE=Microchip Technology Inc. + +OUI:8020AF* + ID_OUI_FROM_DATABASE=Trade FIDES, a.s. + +OUI:8020DA* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:8020E1* + ID_OUI_FROM_DATABASE=BVBA DPTechnics + +OUI:8020FD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:802275* + ID_OUI_FROM_DATABASE=Beijing Beny Wave Technology Co Ltd + +OUI:802689* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:802994* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:802AA8* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:802AFA* + ID_OUI_FROM_DATABASE=Germaneers GmbH + +OUI:802BF9* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:802DE1* + ID_OUI_FROM_DATABASE=Solarbridge Technologies + +OUI:802E14* + ID_OUI_FROM_DATABASE=azeti Networks AG + +OUI:802FDE* + ID_OUI_FROM_DATABASE=Zurich Instruments AG + +OUI:803049* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:8030DC* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:8030E0* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:8031F0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:803253* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:803457* + ID_OUI_FROM_DATABASE=OT Systems Limited + +OUI:8035C1* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:803773* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:803896* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:8038BC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8038FD* + ID_OUI_FROM_DATABASE=LeapFrog Enterprises, Inc. + +OUI:8039E5* + ID_OUI_FROM_DATABASE=PATLITE CORPORATION + +OUI:803A0A* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:803A59* + ID_OUI_FROM_DATABASE=AT&T + +OUI:803AF4* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:803B2A* + ID_OUI_FROM_DATABASE=ABB Xiamen Low Voltage Equipment Co.,Ltd. + +OUI:803B9A* + ID_OUI_FROM_DATABASE=ghe-ces electronic ag + +OUI:803BF6* + ID_OUI_FROM_DATABASE=LOOK EASY INTERNATIONAL LIMITED + +OUI:803E48* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:803F5D* + ID_OUI_FROM_DATABASE=Winstars Technology Ltd + +OUI:803FD6* + ID_OUI_FROM_DATABASE=bytes at work AG + +OUI:804126* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:80414E* + ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + +OUI:80427C* + ID_OUI_FROM_DATABASE=Adolf Tedsen GmbH & Co. KG + +OUI:804731* + ID_OUI_FROM_DATABASE=Packet Design, Inc. + +OUI:8048A5* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:804971* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:804A14* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:804B20* + ID_OUI_FROM_DATABASE=Ventilation Control + +OUI:804E70* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:804E81* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:804F58* + ID_OUI_FROM_DATABASE=ThinkEco, Inc. + +OUI:80501B* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:805067* + ID_OUI_FROM_DATABASE=W & D TECHNOLOGY CORPORATION + +OUI:8050F6* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:80546A* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:8056F2* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:805719* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8058C5* + ID_OUI_FROM_DATABASE=NovaTec Kommunikationstechnik GmbH + +OUI:8058F8* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:8059FD* + ID_OUI_FROM_DATABASE=Noviga + +OUI:805A04* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:805E0C* + ID_OUI_FROM_DATABASE=YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD. + +OUI:805E4F* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:805EC0* + ID_OUI_FROM_DATABASE=YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD. + +OUI:806007* + ID_OUI_FROM_DATABASE=RIM + +OUI:80615F* + ID_OUI_FROM_DATABASE=Beijing Sinead Technology Co., Ltd. + +OUI:80618F* + ID_OUI_FROM_DATABASE=Shenzhen sangfei consumer communications co.,ltd + +OUI:806459* + ID_OUI_FROM_DATABASE=Nimbus Inc. + +OUI:80647A* + ID_OUI_FROM_DATABASE=Ola Sense Inc + +OUI:80656D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8065E9* + ID_OUI_FROM_DATABASE=BenQ Corporation + +OUI:806629* + ID_OUI_FROM_DATABASE=Prescope Technologies CO.,LTD. + +OUI:806933* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:806940* + ID_OUI_FROM_DATABASE=LEXAR CO.,LIMITED + +OUI:806AB0* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:806C1B* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:806C8B* + ID_OUI_FROM_DATABASE=KAESER KOMPRESSOREN AG + +OUI:806CBC* + ID_OUI_FROM_DATABASE=NET New Electronic Technology GmbH + +OUI:806FB0* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:80711F* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:80717A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:807215* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:80739F* + ID_OUI_FROM_DATABASE=KYOCERA CORPORATION + +OUI:807459* + ID_OUI_FROM_DATABASE=K's Co.,Ltd. + +OUI:80751F* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:807693* + ID_OUI_FROM_DATABASE=Newag SA + +OUI:807871* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:80795D* + ID_OUI_FROM_DATABASE=Infinix mobility limited + +OUI:8079AE* + ID_OUI_FROM_DATABASE=ShanDong Tecsunrise Co.,Ltd + +OUI:807A7F* + ID_OUI_FROM_DATABASE=ABB Genway Xiamen Electrical Equipment CO., LTD + +OUI:807ABF* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:807B1E* + ID_OUI_FROM_DATABASE=Corsair Memory, Inc. + +OUI:807B3E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:807B850* + ID_OUI_FROM_DATABASE=Shiroshita Industrial Co., Ltd. + +OUI:807B851* + ID_OUI_FROM_DATABASE=Hangzhou Synway Information Engineering Co., Ltd + +OUI:807B852* + ID_OUI_FROM_DATABASE=Phoenix Co.,Ltd. + +OUI:807B853* + ID_OUI_FROM_DATABASE=Zhuhai TOP Intelligence Electric Co., Ltd. + +OUI:807B854* + ID_OUI_FROM_DATABASE=Quantel USA, Inc. + +OUI:807B855* + ID_OUI_FROM_DATABASE=EFCO + +OUI:807B856* + ID_OUI_FROM_DATABASE=Quickte Technology Co.,Ltd + +OUI:807B857* + ID_OUI_FROM_DATABASE=Chendu Ningshui Technology Co.,Ltd + +OUI:807B858* + ID_OUI_FROM_DATABASE=IDair, LLC + +OUI:807B859* + ID_OUI_FROM_DATABASE=SMART ELECTRONICS NZ LIMITED + +OUI:807B85A* + ID_OUI_FROM_DATABASE=Interplan Co., Ltd. + +OUI:807B85B* + ID_OUI_FROM_DATABASE=Oliotalo Oy + +OUI:807B85C* + ID_OUI_FROM_DATABASE=Ningbo Plus and Popscreens electronic Technology Co.,LTD + +OUI:807B85D* + ID_OUI_FROM_DATABASE=Kaynes Technology India Pvt Ltd + +OUI:807B85E* + ID_OUI_FROM_DATABASE=Mersen + +OUI:807B85F* + ID_OUI_FROM_DATABASE=Private + +OUI:807D14* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:807D1B* + ID_OUI_FROM_DATABASE=Neosystem Co. Ltd. + +OUI:807D3A* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:807DE3* + ID_OUI_FROM_DATABASE=Chongqing Sichuan Instrument Microcircuit Co.LTD. + +OUI:807FF8* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:8081A5* + ID_OUI_FROM_DATABASE=TONGQING COMMUNICATION EQUIPMENT (SHENZHEN) Co.,Ltd + +OUI:808223* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:808287* + ID_OUI_FROM_DATABASE=ATCOM Technology Co.Ltd. + +OUI:8084A9* + ID_OUI_FROM_DATABASE=oshkosh Corporation + +OUI:808698* + ID_OUI_FROM_DATABASE=Netronics Technologies Inc. + +OUI:8086D9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8086F2* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:808917* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:808A8B* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:808B5C* + ID_OUI_FROM_DATABASE=Shenzhen Runhuicheng Technology Co., Ltd + +OUI:808C97* + ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD. + +OUI:808DB7* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:808F1D* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:80912A* + ID_OUI_FROM_DATABASE=Lih Rong electronic Enterprise Co., Ltd. + +OUI:809133* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:8091C0* + ID_OUI_FROM_DATABASE=AgileMesh, Inc. + +OUI:80929F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:809393* + ID_OUI_FROM_DATABASE=Xapt GmbH + +OUI:80946C* + ID_OUI_FROM_DATABASE=TOKYO RADAR CORPORATION + +OUI:809621* + ID_OUI_FROM_DATABASE=Lenovo + +OUI:8096B1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:8096CA* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:80971B* + ID_OUI_FROM_DATABASE=Altenergy Power System,Inc. + +OUI:809B20* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:809F9B* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:809FAB* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:80A036* + ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd. + +OUI:80A1AB* + ID_OUI_FROM_DATABASE=Intellisis + +OUI:80A1D7* + ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co.,Ltd + +OUI:80A235* + ID_OUI_FROM_DATABASE=Edgecore Networks Corporation + +OUI:80A589* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:80A796* + ID_OUI_FROM_DATABASE=Neurotek LLC + +OUI:80A85D* + ID_OUI_FROM_DATABASE=Osterhout Design Group + +OUI:80AAA4* + ID_OUI_FROM_DATABASE=USAG + +OUI:80AC7C* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:80ACAC* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:80AD16* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:80AD67* + ID_OUI_FROM_DATABASE=Kasda Networks Inc + +OUI:80B03D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:80B07B* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:80B219* + ID_OUI_FROM_DATABASE=ELEKTRON TECHNOLOGY UK LIMITED + +OUI:80B234* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:80B289* + ID_OUI_FROM_DATABASE=Forworld Electronics Ltd. + +OUI:80B32A* + ID_OUI_FROM_DATABASE=UK Grid Solutions Ltd + +OUI:80B575* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:80B624* + ID_OUI_FROM_DATABASE=IVS + +OUI:80B686* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:80B708* + ID_OUI_FROM_DATABASE=Blue Danube Systems, Inc + +OUI:80B709* + ID_OUI_FROM_DATABASE=Viptela, Inc + +OUI:80B95C* + ID_OUI_FROM_DATABASE=ELFTECH Co., Ltd. + +OUI:80BAAC* + ID_OUI_FROM_DATABASE=TeleAdapt Ltd + +OUI:80BAE6* + ID_OUI_FROM_DATABASE=Neets + +OUI:80BBEB* + ID_OUI_FROM_DATABASE=Satmap Systems Ltd + +OUI:80BE05* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:80C16E* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:80C548* + ID_OUI_FROM_DATABASE=Shenzhen Zowee Technology Co.,Ltd + +OUI:80C5E6* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:80C5F2* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:80C63F* + ID_OUI_FROM_DATABASE=Remec Broadband Wireless , LLC + +OUI:80C6AB* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:80C6CA* + ID_OUI_FROM_DATABASE=Endian s.r.l. + +OUI:80C755* + ID_OUI_FROM_DATABASE=Panasonic Appliances Company + +OUI:80C7C5* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:80C862* + ID_OUI_FROM_DATABASE=Openpeak, Inc + +OUI:80CE62* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:80CEB1* + ID_OUI_FROM_DATABASE=Theissen Training Systems GmbH + +OUI:80CEB9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:80CF41* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:80D019* + ID_OUI_FROM_DATABASE=Embed, Inc + +OUI:80D04A* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:80D065* + ID_OUI_FROM_DATABASE=CKS Corporation + +OUI:80D09B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:80D160* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:80D18B* + ID_OUI_FROM_DATABASE=Hangzhou I'converge Technology Co.,Ltd + +OUI:80D21D* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:80D336* + ID_OUI_FROM_DATABASE=CERN + +OUI:80D433* + ID_OUI_FROM_DATABASE=LzLabs GmbH + +OUI:80D4A5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:80D605* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:80D733* + ID_OUI_FROM_DATABASE=QSR Automations, Inc. + +OUI:80DA13* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:80DABC* + ID_OUI_FROM_DATABASE=Megafone Limited + +OUI:80DB31* + ID_OUI_FROM_DATABASE=Power Quotient International Co., Ltd. + +OUI:80E01D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:80E455* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:80E4DA0* + ID_OUI_FROM_DATABASE=Wheatstone Corporation + +OUI:80E4DA1* + ID_OUI_FROM_DATABASE=Guangzhou Pinzhong Electronic Technology CO., LTD + +OUI:80E4DA2* + ID_OUI_FROM_DATABASE=Thurlby Thandar Instruments LTD + +OUI:80E4DA3* + ID_OUI_FROM_DATABASE=Beijing Gaokezhongtian Technology Co Ltd + +OUI:80E4DA4* + ID_OUI_FROM_DATABASE=Beijing Yuantel Technolgy Co.,Ltd-Shenzhen Branch + +OUI:80E4DA5* + ID_OUI_FROM_DATABASE=CAVALRY STORAGE INC + +OUI:80E4DA6* + ID_OUI_FROM_DATABASE=BroadMedia Co., Ltd. + +OUI:80E4DA7* + ID_OUI_FROM_DATABASE=Shortcut Labs + +OUI:80E4DA8* + ID_OUI_FROM_DATABASE=Krizer international Co,. Ltd. + +OUI:80E4DA9* + ID_OUI_FROM_DATABASE=Elcus + +OUI:80E4DAA* + ID_OUI_FROM_DATABASE=Neutronics + +OUI:80E4DAB* + ID_OUI_FROM_DATABASE=Nanjing LILO Technology Co. Ltd. + +OUI:80E4DAC* + ID_OUI_FROM_DATABASE=EVER Sp. z o.o. + +OUI:80E4DAD* + ID_OUI_FROM_DATABASE=Dalian Roiland Technology Co.,Ltd + +OUI:80E4DAE* + ID_OUI_FROM_DATABASE=Akenori PTE LTD + +OUI:80E4DAF* + ID_OUI_FROM_DATABASE=Private + +OUI:80E540* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:80E650* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:80E82C* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:80E86F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:80EA23* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:80EA96* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:80EACA* + ID_OUI_FROM_DATABASE=Dialog Semiconductor Hellas SA + +OUI:80EB77* + ID_OUI_FROM_DATABASE=Wistron Corporation + +OUI:80ED2C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:80EE73* + ID_OUI_FROM_DATABASE=Shuttle Inc. + +OUI:80F25E* + ID_OUI_FROM_DATABASE=Kyynel + +OUI:80F503* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:80F593* + ID_OUI_FROM_DATABASE=IRCO Sistemas de Telecomunicación S.A. + +OUI:80F62E* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:80F8EB* + ID_OUI_FROM_DATABASE=RayTight + +OUI:80FA5B* + ID_OUI_FROM_DATABASE=CLEVO CO. + +OUI:80FB06* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:80FBF0* + ID_OUI_FROM_DATABASE=Quectel Wireless Solutions Co., Ltd. + +OUI:80FD7A* + ID_OUI_FROM_DATABASE=BLU Products Inc + +OUI:80FFA8* + ID_OUI_FROM_DATABASE=UNIDIS + +OUI:84002D* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:8400D2* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:8401A7* + ID_OUI_FROM_DATABASE=Greyware Automation Products, Inc + +OUI:8404D2* + ID_OUI_FROM_DATABASE=Kirale Technologies SL + +OUI:840B2D* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:840B7C* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:840D8E* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:840F45* + ID_OUI_FROM_DATABASE=Shanghai GMT Digital Technologies Co., Ltd + +OUI:84100D* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:84119E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:84139F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:8416F9* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:841715* + ID_OUI_FROM_DATABASE=GP Electronics (HK) Ltd. + +OUI:841766* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:8417EF* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:841826* + ID_OUI_FROM_DATABASE=Osram GmbH + +OUI:84183A* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:841888* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:841B38* + ID_OUI_FROM_DATABASE=Shenzhen Excelsecu Data Technology Co.,Ltd + +OUI:841B5E* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:841C70* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:841E26* + ID_OUI_FROM_DATABASE=KERNEL-I Co.,LTD + +OUI:842096* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:842141* + ID_OUI_FROM_DATABASE=Shenzhen Ginwave Technologies Ltd. + +OUI:8421F1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:84248D* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc + +OUI:842519* + ID_OUI_FROM_DATABASE=Samsung Electronics + +OUI:84253F* + ID_OUI_FROM_DATABASE=silex technology, Inc. + +OUI:8425A4* + ID_OUI_FROM_DATABASE=Tariox Limited + +OUI:8425DB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:842615* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:84262B* + ID_OUI_FROM_DATABASE=Nokia + +OUI:842690* + ID_OUI_FROM_DATABASE=BEIJING THOUGHT SCIENCE CO.,LTD. + +OUI:8427CE* + ID_OUI_FROM_DATABASE=Corporation of the Presiding Bishop of The Church of Jesus Christ of Latter-day Saints + +OUI:84285A* + ID_OUI_FROM_DATABASE=Saffron Solutions Inc + +OUI:842914* + ID_OUI_FROM_DATABASE=EMPORIA TELECOM Produktions- und VertriebsgesmbH & Co KG + +OUI:842999* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:842B2B* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:842B50* + ID_OUI_FROM_DATABASE=Huria Co.,Ltd. + +OUI:842BBC* + ID_OUI_FROM_DATABASE=Modelleisenbahn GmbH + +OUI:842C80* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. + +OUI:842E14* + ID_OUI_FROM_DATABASE=Silicon Laboratories + +OUI:842E27* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:842F75* + ID_OUI_FROM_DATABASE=Innokas Group + +OUI:8430E5* + ID_OUI_FROM_DATABASE=SkyHawke Technologies, LLC + +OUI:84326F* + ID_OUI_FROM_DATABASE=GUANGZHOU AVA ELECTRONICS TECHNOLOGY CO.,LTD + +OUI:8432EA* + ID_OUI_FROM_DATABASE=ANHUI WANZTEN P&T CO., LTD + +OUI:843497* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:843611* + ID_OUI_FROM_DATABASE=hyungseul publishing networks + +OUI:843835* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:843838* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:8439BE0* + ID_OUI_FROM_DATABASE=HINO ENGINEERING, INC + +OUI:8439BE1* + ID_OUI_FROM_DATABASE=Guangzhou Heygears Technology Ltd + +OUI:8439BE2* + ID_OUI_FROM_DATABASE=Cheng Du virtual world Technology Limited. + +OUI:8439BE3* + ID_OUI_FROM_DATABASE=ShenZhen Fudeyu Technology co.,Ltd + +OUI:8439BE4* + ID_OUI_FROM_DATABASE=Shenzhen Ramos Digital Technology Co,.Ltd. + +OUI:8439BE5* + ID_OUI_FROM_DATABASE=Neat S.r.l. + +OUI:8439BE6* + ID_OUI_FROM_DATABASE=Shenzhen IP3 Century Intelligent Technology Co., Ltd + +OUI:8439BE8* + ID_OUI_FROM_DATABASE=Diamond Products LLC + +OUI:8439BE9* + ID_OUI_FROM_DATABASE=Guangdong SunMeng Information Technology Co. Ltd. + +OUI:8439BEA* + ID_OUI_FROM_DATABASE=Emotiq s.r.l. + +OUI:8439BEB* + ID_OUI_FROM_DATABASE=Shenzhen Horn Audio Co.,Ltd. + +OUI:8439BEC* + ID_OUI_FROM_DATABASE=EDC Electronic Design Chemnitz GmbH + +OUI:8439BED* + ID_OUI_FROM_DATABASE=Shenzhen Lidaxun Digital Technology Co.,Ltd + +OUI:843A4B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:843DC6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:843E79* + ID_OUI_FROM_DATABASE=Shenzhen Belon Technology CO.,LTD + +OUI:843F4E* + ID_OUI_FROM_DATABASE=Tri-Tech Manufacturing, Inc. + +OUI:844076* + ID_OUI_FROM_DATABASE=Drivenets + +OUI:844167* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:844464* + ID_OUI_FROM_DATABASE=ServerU Inc + +OUI:8446FE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:844765* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:844823* + ID_OUI_FROM_DATABASE=WOXTER TECHNOLOGY Co. Ltd + +OUI:844915* + ID_OUI_FROM_DATABASE=vArmour Networks, Inc. + +OUI:844BB7* + ID_OUI_FROM_DATABASE=Beijing Sankuai Online Technology Co.,Ltd + +OUI:844BF5* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:844F03* + ID_OUI_FROM_DATABASE=Ablelink Electronics Ltd + +OUI:84509A* + ID_OUI_FROM_DATABASE=Easy Soft TV Co., Ltd + +OUI:845181* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8455A5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:84569C* + ID_OUI_FROM_DATABASE=Coho Data, Inc., + +OUI:845733* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:845787* + ID_OUI_FROM_DATABASE=DVR C&C Co., Ltd. + +OUI:845A81* + ID_OUI_FROM_DATABASE=ffly4u + +OUI:845B12* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:845C93* + ID_OUI_FROM_DATABASE=Chabrier Services + +OUI:845DD7* + ID_OUI_FROM_DATABASE=Shenzhen Netcom Electronics Co.,Ltd + +OUI:8461A0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:846223* + ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd. + +OUI:8462A6* + ID_OUI_FROM_DATABASE=EuroCB (Phils), Inc. + +OUI:8463D6* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:84683E* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:846878* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8468C8* + ID_OUI_FROM_DATABASE=TOTOLINK TECHNOLOGY INT‘L LIMITED + +OUI:846991* + ID_OUI_FROM_DATABASE=Nokia + +OUI:846A66* + ID_OUI_FROM_DATABASE=Sumitomo Kizai Co.,Ltd. + +OUI:846AED* + ID_OUI_FROM_DATABASE=Wireless Tsukamoto.,co.LTD + +OUI:846EB1* + ID_OUI_FROM_DATABASE=Park Assist LLC + +OUI:846FCE* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:847207* + ID_OUI_FROM_DATABASE=I&C Technology + +OUI:847303* + ID_OUI_FROM_DATABASE=Letv Mobile and Intelligent Information Technology (Beijing) Corporation Ltd. + +OUI:84742A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:847460* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:847616* + ID_OUI_FROM_DATABASE=Addat s.r.o. + +OUI:847637* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:847778* + ID_OUI_FROM_DATABASE=Cochlear Limited + +OUI:84788B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8478AC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:847933* + ID_OUI_FROM_DATABASE=profichip GmbH + +OUI:847973* + ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd. + +OUI:847A88* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:847BEB* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:847C9B* + ID_OUI_FROM_DATABASE=GD Midea Air-Conditioning Equipment Co.,Ltd. + +OUI:847D50* + ID_OUI_FROM_DATABASE=Holley Metering Limited + +OUI:847E40* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:847F3D* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:84802D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:848094* + ID_OUI_FROM_DATABASE=Meter, Inc. + +OUI:8482F4* + ID_OUI_FROM_DATABASE=Beijing Huasun Unicreate Technology Co., Ltd + +OUI:848319* + ID_OUI_FROM_DATABASE=Hangzhou Zero Zero Technology Co., Ltd. + +OUI:848336* + ID_OUI_FROM_DATABASE=Newrun + +OUI:848371* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:848433* + ID_OUI_FROM_DATABASE=Paradox Engineering SA + +OUI:848506* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:84850A* + ID_OUI_FROM_DATABASE=Hella Sonnen- und Wetterschutztechnik GmbH + +OUI:8485E6* + ID_OUI_FROM_DATABASE=Guangdong Asano Technology CO.,Ltd. + +OUI:8486F3* + ID_OUI_FROM_DATABASE=Greenvity Communications + +OUI:8489AD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8489EC0* + ID_OUI_FROM_DATABASE=SmartGiant Technology + +OUI:8489EC1* + ID_OUI_FROM_DATABASE=Research Electronics International, LLC. + +OUI:8489EC2* + ID_OUI_FROM_DATABASE=thousand star tech LTD. + +OUI:8489EC3* + ID_OUI_FROM_DATABASE=Aerionics Inc. + +OUI:8489EC4* + ID_OUI_FROM_DATABASE=Vayyar Imaging Ltd. + +OUI:8489EC5* + ID_OUI_FROM_DATABASE=Zephyr Engineering, Inc. + +OUI:8489EC6* + ID_OUI_FROM_DATABASE=POCT biotechnology + +OUI:8489EC7* + ID_OUI_FROM_DATABASE=BYDA Co. Ltd., + +OUI:8489EC8* + ID_OUI_FROM_DATABASE=Arts Digital Technology (HK) Ltd. + +OUI:8489EC9* + ID_OUI_FROM_DATABASE=Shenzhen Xtooltech Co., Ltd + +OUI:8489ECA* + ID_OUI_FROM_DATABASE=Newell Brands + +OUI:8489ECB* + ID_OUI_FROM_DATABASE=EPSa Elektronik & Präzisionsbau Saalfeld GmbH + +OUI:8489ECC* + ID_OUI_FROM_DATABASE=SHINKAWA LTD. + +OUI:8489ECD* + ID_OUI_FROM_DATABASE=Price Industries Limited + +OUI:8489ECE* + ID_OUI_FROM_DATABASE=Shenzhen Intellifusion Technologies Co., Ltd. + +OUI:848A8D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:848BCD0* + ID_OUI_FROM_DATABASE=SouXin Corporate + +OUI:848BCD1* + ID_OUI_FROM_DATABASE=Shenzhen LTIME In-Vehicle Entertainment System Company Limited + +OUI:848BCD2* + ID_OUI_FROM_DATABASE=CCX Technologies Inc. + +OUI:848BCD3* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:848BCD4* + ID_OUI_FROM_DATABASE=Logic Supply + +OUI:848BCD5* + ID_OUI_FROM_DATABASE=exodraft a/s + +OUI:848BCD6* + ID_OUI_FROM_DATABASE=TWTG R&D B.V. + +OUI:848BCD7* + ID_OUI_FROM_DATABASE=Smart Code (Shenzhen) Technology Co.,Ltd + +OUI:848BCD8* + ID_OUI_FROM_DATABASE=Dunst tronic GmbH + +OUI:848BCD9* + ID_OUI_FROM_DATABASE=NORALSY + +OUI:848BCDA* + ID_OUI_FROM_DATABASE=Sphera Telecom + +OUI:848BCDB* + ID_OUI_FROM_DATABASE=CHONGQING HUAYI KANGDAO TECHNOLOGY CO.,LTD. + +OUI:848BCDC* + ID_OUI_FROM_DATABASE=WORMIT + +OUI:848BCDD* + ID_OUI_FROM_DATABASE=ENGISAT LDA + +OUI:848BCDE* + ID_OUI_FROM_DATABASE=Emotiv Inc + +OUI:848D84* + ID_OUI_FROM_DATABASE=Rajant Corporation + +OUI:848DC7* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:848E0C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:848E96* + ID_OUI_FROM_DATABASE=Embertec Pty Ltd + +OUI:848EDF* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:848F69* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:849000* + ID_OUI_FROM_DATABASE=Arnold & Richter Cine Technik + +OUI:84930C* + ID_OUI_FROM_DATABASE=InCoax Networks Europe AB + +OUI:84948C* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:849681* + ID_OUI_FROM_DATABASE=Cathay Communication Co.,Ltd + +OUI:8496D8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:8497B8* + ID_OUI_FROM_DATABASE=Memjet Inc. + +OUI:849866* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:849A40* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:849CA6* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:849D64* + ID_OUI_FROM_DATABASE=SMC Corporation + +OUI:849DC5* + ID_OUI_FROM_DATABASE=Centera Photonics Inc. + +OUI:849FB5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:84A06E* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:84A134* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:84A1D1* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:84A24D* + ID_OUI_FROM_DATABASE=Birds Eye Systems Private Limited + +OUI:84A423* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:84A466* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:84A6C8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:84A783* + ID_OUI_FROM_DATABASE=Alcatel Lucent + +OUI:84A788* + ID_OUI_FROM_DATABASE=Perples + +OUI:84A8E4* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:84A93E* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:84A991* + ID_OUI_FROM_DATABASE=Cyber Trans Japan Co.,Ltd. + +OUI:84A9C4* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:84A9EA* + ID_OUI_FROM_DATABASE=Career Technologies USA + +OUI:84AA9C* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:84AB1A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:84ACA4* + ID_OUI_FROM_DATABASE=Beijing Novel Super Digital TV Technology Co., Ltd + +OUI:84ACFB* + ID_OUI_FROM_DATABASE=Crouzet Automatismes + +OUI:84AD58* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:84AD8D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:84AF1F* + ID_OUI_FROM_DATABASE=Beat System Service Co,. Ltd. + +OUI:84AFEC* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:84B153* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:84B261* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:84B31B* + ID_OUI_FROM_DATABASE=Kinexon GmbH + +OUI:84B517* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:84B541* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:84B59C* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:84B802* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:84B866* + ID_OUI_FROM_DATABASE=Beijing XiaoLu technology co. LTD + +OUI:84B8B8* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:84BA3B* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:84BB69* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:84BE52* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:84C0EF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:84C1C1* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:84C2E4* + ID_OUI_FROM_DATABASE=Jiangsu Qinheng Co., Ltd. + +OUI:84C3E8* + ID_OUI_FROM_DATABASE=Vaillant GmbH + +OUI:84C5A6* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:84C727* + ID_OUI_FROM_DATABASE=Gnodal Ltd + +OUI:84C78F* + ID_OUI_FROM_DATABASE=STORDIS GmbH + +OUI:84C7A9* + ID_OUI_FROM_DATABASE=C3PO S.A. + +OUI:84C7EA* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:84C807* + ID_OUI_FROM_DATABASE=ADVA Optical Networking Ltd. + +OUI:84C8B1* + ID_OUI_FROM_DATABASE=Incognito Software Systems Inc. + +OUI:84C9B2* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:84C9C6* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:84CD62* + ID_OUI_FROM_DATABASE=ShenZhen IDWELL Technology CO.,Ltd + +OUI:84CFBF* + ID_OUI_FROM_DATABASE=Fairphone + +OUI:84D15A* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:84D32A* + ID_OUI_FROM_DATABASE=IEEE 1905.1 + +OUI:84D412* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:84D47E* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:84D4C8* + ID_OUI_FROM_DATABASE=Widex A/S + +OUI:84D6C5* + ID_OUI_FROM_DATABASE=SolarEdge Technologies + +OUI:84D6D0* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:84D931* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:84D9C8* + ID_OUI_FROM_DATABASE=Unipattern Co., + +OUI:84DB2F* + ID_OUI_FROM_DATABASE=Sierra Wireless + +OUI:84DB9E* + ID_OUI_FROM_DATABASE=Aifloo AB + +OUI:84DBAC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:84DBFC* + ID_OUI_FROM_DATABASE=Nokia + +OUI:84DD20* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:84DDB7* + ID_OUI_FROM_DATABASE=Cilag GmbH International + +OUI:84DE3D* + ID_OUI_FROM_DATABASE=Crystal Vision Ltd + +OUI:84DF0C* + ID_OUI_FROM_DATABASE=NET2GRID BV + +OUI:84DF19* + ID_OUI_FROM_DATABASE=Chuango Security Technology Corporation + +OUI:84E058* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:84E0F40* + ID_OUI_FROM_DATABASE=ShenZhen Panrich Technology Limited + +OUI:84E0F41* + ID_OUI_FROM_DATABASE=MedicusTek Inc. + +OUI:84E0F42* + ID_OUI_FROM_DATABASE=Hangzhou Uni-Ubi Co.,Ltd. + +OUI:84E0F43* + ID_OUI_FROM_DATABASE=ASL Intercom B.V. + +OUI:84E0F44* + ID_OUI_FROM_DATABASE=PetroInTrade + +OUI:84E0F45* + ID_OUI_FROM_DATABASE=Hangzhou Nationalchip Science & Technology Co.,Ltd. + +OUI:84E0F46* + ID_OUI_FROM_DATABASE=Liaoning IK'SONYA Science and Technology Co., Ltd. + +OUI:84E0F47* + ID_OUI_FROM_DATABASE=Dantherm + +OUI:84E0F48* + ID_OUI_FROM_DATABASE=RAY Co.,LTD + +OUI:84E0F49* + ID_OUI_FROM_DATABASE=SHENZHEN HCN.ELECTRONICS CO.,LTD. + +OUI:84E0F4A* + ID_OUI_FROM_DATABASE=iSolution Technologies Co.,Ltd. + +OUI:84E0F4B* + ID_OUI_FROM_DATABASE=Orchard Electronics Co., Ltd. + +OUI:84E0F4C* + ID_OUI_FROM_DATABASE=AIMTRON CORPORATION + +OUI:84E0F4D* + ID_OUI_FROM_DATABASE=Logos01 Srl + +OUI:84E0F4E* + ID_OUI_FROM_DATABASE=Scale-Tec Ltd. + +OUI:84E323* + ID_OUI_FROM_DATABASE=Green Wave Telecommunication SDN BHD + +OUI:84E327* + ID_OUI_FROM_DATABASE=TAILYN TECHNOLOGIES INC + +OUI:84E4D9* + ID_OUI_FROM_DATABASE=Shenzhen NEED technology Ltd. + +OUI:84E5D8* + ID_OUI_FROM_DATABASE=Guangdong UNIPOE IoT Technology Co.,Ltd. + +OUI:84E629* + ID_OUI_FROM_DATABASE=Bluwan SA + +OUI:84E714* + ID_OUI_FROM_DATABASE=Liang Herng Enterprise,Co.Ltd. + +OUI:84E892* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:84EA97* + ID_OUI_FROM_DATABASE=Shenzhen iComm Semiconductor Co., Ltd. + +OUI:84EA99* + ID_OUI_FROM_DATABASE=Vieworks + +OUI:84EB18* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:84EB3E* + ID_OUI_FROM_DATABASE=Vivint Smart Home + +OUI:84ED33* + ID_OUI_FROM_DATABASE=BBMC Co.,Ltd + +OUI:84EF18* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:84F129* + ID_OUI_FROM_DATABASE=Metrascale Inc. + +OUI:84F3EB* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:84F493* + ID_OUI_FROM_DATABASE=OMS spol. s.r.o. + +OUI:84F64C* + ID_OUI_FROM_DATABASE=Cross Point BV + +OUI:84F6FA* + ID_OUI_FROM_DATABASE=Miovision Technologies Incorporated + +OUI:84F883* + ID_OUI_FROM_DATABASE=Luminar Technologies + +OUI:84FCAC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:84FCFE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:84FDD1* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:84FE9E* + ID_OUI_FROM_DATABASE=RTC Industries, Inc. + +OUI:84FEDC* + ID_OUI_FROM_DATABASE=Borqs Beijing Ltd. + +OUI:880118* + ID_OUI_FROM_DATABASE=BLT Co + +OUI:8801F2* + ID_OUI_FROM_DATABASE=Vitec System Engineering Inc. + +OUI:880355* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:88074B* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:880905* + ID_OUI_FROM_DATABASE=MTMCommunications + +OUI:880907* + ID_OUI_FROM_DATABASE=MKT Systemtechnik GmbH & Co. KG + +OUI:8809AF* + ID_OUI_FROM_DATABASE=Masimo Corporation + +OUI:880F10* + ID_OUI_FROM_DATABASE=Huami Information Technology Co.,Ltd. + +OUI:880FB6* + ID_OUI_FROM_DATABASE=Jabil Circuits India Pvt Ltd,-EHTP unit + +OUI:881036* + ID_OUI_FROM_DATABASE=Panodic(ShenZhen) Electronics Limted + +OUI:88108F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:881196* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88123D* + ID_OUI_FROM_DATABASE=Suzhou Aquila Solutions Inc. + +OUI:88124E* + ID_OUI_FROM_DATABASE=Qualcomm Inc. + +OUI:88142B* + ID_OUI_FROM_DATABASE=Protonic Holland + +OUI:881544* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:8817A3* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:8818AE* + ID_OUI_FROM_DATABASE=Tamron Co., Ltd + +OUI:881908* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:881B99* + ID_OUI_FROM_DATABASE=SHENZHEN XIN FEI JIA ELECTRONIC CO. LTD. + +OUI:881DFC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:881FA1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:882012* + ID_OUI_FROM_DATABASE=LMI Technologies + +OUI:8821E3* + ID_OUI_FROM_DATABASE=Nebusens, S.L. + +OUI:882364* + ID_OUI_FROM_DATABASE=Watchnet DVR Inc + +OUI:8823FE* + ID_OUI_FROM_DATABASE=TTTech Computertechnik AG + +OUI:88252C* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:882593* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:8828B3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:882950* + ID_OUI_FROM_DATABASE=Netmoon Technology Co., Ltd + +OUI:88299C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:882BD7* + ID_OUI_FROM_DATABASE=ADDÉNERGIE TECHNOLOGIES + +OUI:882D53* + ID_OUI_FROM_DATABASE=Baidu Online Network Technology (Beijing) Co., Ltd. + +OUI:882E5A* + ID_OUI_FROM_DATABASE=storONE + +OUI:88308A* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:88329B* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:883314* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:8833BE* + ID_OUI_FROM_DATABASE=Ivenix, Inc. + +OUI:8834FE* + ID_OUI_FROM_DATABASE=Bosch Automotive Products (Suzhou) Co. Ltd + +OUI:88354C* + ID_OUI_FROM_DATABASE=Transics + +OUI:8835C1* + ID_OUI_FROM_DATABASE=OI ELECTRIC CO.,LTD + +OUI:883612* + ID_OUI_FROM_DATABASE=SRC Computers, LLC + +OUI:88365F* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:88366C* + ID_OUI_FROM_DATABASE=EFM Networks + +OUI:8836CF* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:883A30* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:883B8B* + ID_OUI_FROM_DATABASE=Cheering Connection Co. Ltd. + +OUI:883C1C* + ID_OUI_FROM_DATABASE=MERCURY CORPORATION + +OUI:883D24* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:883F4A* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:883F99* + ID_OUI_FROM_DATABASE=Siemens AG + +OUI:883FD3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88403B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:884157* + ID_OUI_FROM_DATABASE=Shenzhen Atsmart Technology Co.,Ltd. + +OUI:8841C1* + ID_OUI_FROM_DATABASE=ORBISAT DA AMAZONIA IND E AEROL SA + +OUI:8841FC* + ID_OUI_FROM_DATABASE=AirTies Wireless Networks + +OUI:8843E1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:884477* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8844F6* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:88462A* + ID_OUI_FROM_DATABASE=Telechips Inc. + +OUI:884A18* + ID_OUI_FROM_DATABASE=Opulinks + +OUI:884A70* + ID_OUI_FROM_DATABASE=Wacom Co.,Ltd. + +OUI:884AEA* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:884B39* + ID_OUI_FROM_DATABASE=Siemens AG, Healthcare Sector + +OUI:884CCF* + ID_OUI_FROM_DATABASE=Pulzze Systems, Inc + +OUI:8850DD* + ID_OUI_FROM_DATABASE=Infiniband Trade Association + +OUI:8850F6* + ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + +OUI:88517A* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:8851FB* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:88532E* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:885395* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8853D4* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88541F* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:88571D* + ID_OUI_FROM_DATABASE=Seongji Industry Company + +OUI:88576D* + ID_OUI_FROM_DATABASE=XTA Electronics Ltd + +OUI:8857EE* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:885A06* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:885A92* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:885BDD* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:885C47* + ID_OUI_FROM_DATABASE=Alcatel Lucent + +OUI:885D900* + ID_OUI_FROM_DATABASE=FOSHAN HUAGUO OPTICAL CO.,LTD + +OUI:885D901* + ID_OUI_FROM_DATABASE=ShenZhen Yuyangsheng technology company LTD + +OUI:885D902* + ID_OUI_FROM_DATABASE=DAIDONG Industrial System Co., Ltd. + +OUI:885D903* + ID_OUI_FROM_DATABASE=CPAC Systems + +OUI:885D904* + ID_OUI_FROM_DATABASE=Wuhan Strong Electronics Co., Ltd + +OUI:885D905* + ID_OUI_FROM_DATABASE=Shenzhen JingHanDa Electronics Co.Ltd + +OUI:885D906* + ID_OUI_FROM_DATABASE=Hi-Profile Achievement (M) Sdn Bhd + +OUI:885D907* + ID_OUI_FROM_DATABASE=Schmidt & Co.,(H.K.)Ltd. + +OUI:885D908* + ID_OUI_FROM_DATABASE=Creative Sensor Inc. + +OUI:885D909* + ID_OUI_FROM_DATABASE=Gigatech R&D Corp. + +OUI:885D90A* + ID_OUI_FROM_DATABASE=Shenzhen Speedrun Technologies Co.,Ltd. + +OUI:885D90B* + ID_OUI_FROM_DATABASE=Premier Merchandises Limited + +OUI:885D90C* + ID_OUI_FROM_DATABASE=iRoom GmbH + +OUI:885D90D* + ID_OUI_FROM_DATABASE=Hexaglobe + +OUI:885D90E* + ID_OUI_FROM_DATABASE=Unitac Technology Limited + +OUI:885D90F* + ID_OUI_FROM_DATABASE=Private + +OUI:885DFB* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:885FE80* + ID_OUI_FROM_DATABASE=Jungheinrich Norderstedt AG & Co. KG + +OUI:885FE81* + ID_OUI_FROM_DATABASE=Apoidea Technology Co., Ltd. + +OUI:885FE82* + ID_OUI_FROM_DATABASE=Opto Engineering + +OUI:885FE83* + ID_OUI_FROM_DATABASE=Sonnet Labs Inc. + +OUI:885FE84* + ID_OUI_FROM_DATABASE=Beijing laiwei Technology Co.,Ltd + +OUI:885FE85* + ID_OUI_FROM_DATABASE=Hauch & Bach ApS + +OUI:885FE86* + ID_OUI_FROM_DATABASE=Shenzhen Xin Kingbrand Enterprises Co.,Ltd + +OUI:885FE87* + ID_OUI_FROM_DATABASE=Red Technologies, LLC. + +OUI:885FE88* + ID_OUI_FROM_DATABASE=Changsha Xiangji-Haidun Technology Co., Ltd + +OUI:885FE89* + ID_OUI_FROM_DATABASE=Sowee + +OUI:885FE8A* + ID_OUI_FROM_DATABASE=Lisle Design Ltd + +OUI:885FE8B* + ID_OUI_FROM_DATABASE=Shenzhen ORVIBO Technology Co., Ltd + +OUI:885FE8C* + ID_OUI_FROM_DATABASE=Inor Process AB + +OUI:885FE8D* + ID_OUI_FROM_DATABASE=zhejiang yuanwang communication technolgy co.,ltd + +OUI:885FE8E* + ID_OUI_FROM_DATABASE=Unicom Global, Inc. + +OUI:88615A* + ID_OUI_FROM_DATABASE=Siano Mobile Silicon Ltd. + +OUI:8863DF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:886440* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:886639* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8866A5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:88685C* + ID_OUI_FROM_DATABASE=Shenzhen ChuangDao & Perpetual Eternal Technology Co.,Ltd + +OUI:886AB1* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:886AE3* + ID_OUI_FROM_DATABASE=Alpha Networks Inc. + +OUI:886B0F* + ID_OUI_FROM_DATABASE=Bluegiga Technologies OY + +OUI:886B44* + ID_OUI_FROM_DATABASE=Sunnovo International Limited + +OUI:886B6E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:886B76* + ID_OUI_FROM_DATABASE=CHINA HOPEFUL GROUP HOPEFUL ELECTRIC CO.,LTD + +OUI:886FD4* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:887033* + ID_OUI_FROM_DATABASE=Hangzhou Silan Microelectronic Inc + +OUI:88708C* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:8870EF* + ID_OUI_FROM_DATABASE=SC Professional Trading Co., Ltd. + +OUI:8871B1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:8871E5* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:887384* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:887398* + ID_OUI_FROM_DATABASE=K2E Tekpoint + +OUI:887556* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:887598* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:887873* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:88789C* + ID_OUI_FROM_DATABASE=Game Technologies SA + +OUI:88795B* + ID_OUI_FROM_DATABASE=Konka Group Co., Ltd. + +OUI:88797E* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:887A31* + ID_OUI_FROM_DATABASE=Velankani Electronics Pvt. Ltd. + +OUI:887E25* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:887F03* + ID_OUI_FROM_DATABASE=Comper Technology Investment Limited + +OUI:888279* + ID_OUI_FROM_DATABASE=Shenzhen RB-LINK Intelligent Technology Co.Ltd + +OUI:888322* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:88835D* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:888603* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8886A0* + ID_OUI_FROM_DATABASE=Simton Technologies, Ltd. + +OUI:8886C2* + ID_OUI_FROM_DATABASE=STABILO International GmbH + +OUI:888717* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:8887DD* + ID_OUI_FROM_DATABASE=DarbeeVision Inc. + +OUI:888914* + ID_OUI_FROM_DATABASE=All Components Incorporated + +OUI:888964* + ID_OUI_FROM_DATABASE=GSI Electronics Inc. + +OUI:888B5D* + ID_OUI_FROM_DATABASE=Storage Appliance Corporation + +OUI:888C19* + ID_OUI_FROM_DATABASE=Brady Corp Asia Pacific Ltd + +OUI:88908D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:889166* + ID_OUI_FROM_DATABASE=Viewcooper Corp. + +OUI:8891DD* + ID_OUI_FROM_DATABASE=Racktivity + +OUI:889471* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:88947E* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:8894F9* + ID_OUI_FROM_DATABASE=Gemicom Technology, Inc. + +OUI:8895B9* + ID_OUI_FROM_DATABASE=Unified Packet Systems Crop + +OUI:88964E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:889655* + ID_OUI_FROM_DATABASE=Zitte corporation + +OUI:889676* + ID_OUI_FROM_DATABASE=TTC MARCONI s.r.o. + +OUI:8896B6* + ID_OUI_FROM_DATABASE=Global Fire Equipment S.A. + +OUI:8896F2* + ID_OUI_FROM_DATABASE=Valeo Schalter und Sensoren GmbH + +OUI:889746* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:889765* + ID_OUI_FROM_DATABASE=exands + +OUI:8897DF* + ID_OUI_FROM_DATABASE=Entrypass Corporation Sdn. Bhd. + +OUI:889821* + ID_OUI_FROM_DATABASE=TERAON + +OUI:889B39* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:889CA6* + ID_OUI_FROM_DATABASE=BTB Korea INC + +OUI:889D98* + ID_OUI_FROM_DATABASE=Allied-telesisK.K. + +OUI:889E33* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:889E68* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:889F6F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:889FAA* + ID_OUI_FROM_DATABASE=Hella Gutmann Solutions GmbH + +OUI:889FFA* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:88A084* + ID_OUI_FROM_DATABASE=Formation Data Systems + +OUI:88A25E* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:88A2D7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88A303* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:88A3CC* + ID_OUI_FROM_DATABASE=Amatis Controls + +OUI:88A479* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:88A5BD* + ID_OUI_FROM_DATABASE=QPCOM INC. + +OUI:88A6C6* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:88A73C* + ID_OUI_FROM_DATABASE=Ragentek Technology Group + +OUI:88A9A70* + ID_OUI_FROM_DATABASE=Shenzhenshi kechuangzhixian technology Co.LTD + +OUI:88A9A71* + ID_OUI_FROM_DATABASE=Solaredge LTD. + +OUI:88A9A72* + ID_OUI_FROM_DATABASE=Honeywell spol. s.r.o. HTS CZ o.z. + +OUI:88A9A73* + ID_OUI_FROM_DATABASE=Mikroelektronika + +OUI:88A9A74* + ID_OUI_FROM_DATABASE=Thomas & Darden, Inc + +OUI:88A9A75* + ID_OUI_FROM_DATABASE=Volterman Inc. + +OUI:88A9A76* + ID_OUI_FROM_DATABASE=Sieper Lüdenscheid GmbH & Co. KG + +OUI:88A9A77* + ID_OUI_FROM_DATABASE=kimura giken corporation + +OUI:88A9A78* + ID_OUI_FROM_DATABASE=psb intralogistics GmbH + +OUI:88A9A79* + ID_OUI_FROM_DATABASE=FlashForge Corporation + +OUI:88A9A7A* + ID_OUI_FROM_DATABASE=Zhejiang Haoteng Electronic Technology Co.,Ltd. + +OUI:88A9A7B* + ID_OUI_FROM_DATABASE=TWK-ELEKTRONIK + +OUI:88A9A7C* + ID_OUI_FROM_DATABASE=AndroVideo Inc. + +OUI:88A9A7D* + ID_OUI_FROM_DATABASE=AVLINK INDUSTRIAL CO., LTD + +OUI:88A9A7E* + ID_OUI_FROM_DATABASE=Impact Distribution + +OUI:88A9B7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:88ACC0* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:88ACC1* + ID_OUI_FROM_DATABASE=Generiton Co., Ltd. + +OUI:88AD43* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:88ADD2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:88AE07* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:88AE1D* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:88B111* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:88B168* + ID_OUI_FROM_DATABASE=Delta Control GmbH + +OUI:88B1E1* + ID_OUI_FROM_DATABASE=Mojo Networks, Inc. + +OUI:88B291* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:88B362* + ID_OUI_FROM_DATABASE=Nokia Shanghai Bell Co., Ltd. + +OUI:88B436* + ID_OUI_FROM_DATABASE=Private + +OUI:88B4A6* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:88B627* + ID_OUI_FROM_DATABASE=Gembird Europe BV + +OUI:88B66B* + ID_OUI_FROM_DATABASE=easynetworks + +OUI:88B6EE* + ID_OUI_FROM_DATABASE=Dish Technologies Corp + +OUI:88B8D0* + ID_OUI_FROM_DATABASE=Dongguan Koppo Electronic Co.,Ltd + +OUI:88BA7F* + ID_OUI_FROM_DATABASE=Qfiednet Co., Ltd. + +OUI:88BCC1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88BD45* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:88BD78* + ID_OUI_FROM_DATABASE=Flaircomm Microelectronics,Inc. + +OUI:88BFD5* + ID_OUI_FROM_DATABASE=Simple Audio Ltd + +OUI:88BFE4* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88C242* + ID_OUI_FROM_DATABASE=Poynt Co. + +OUI:88C255* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:88C36E* + ID_OUI_FROM_DATABASE=Beijing Ereneben lnformation Technology Limited + +OUI:88C397* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd + +OUI:88C3B3* + ID_OUI_FROM_DATABASE=SOVICO + +OUI:88C626* + ID_OUI_FROM_DATABASE=Logitech, Inc + +OUI:88C663* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:88C9D0* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:88CB87* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:88CBA5* + ID_OUI_FROM_DATABASE=Suzhou Torchstar Intelligent Technology Co.,Ltd + +OUI:88CC45* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:88CEFA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88CF98* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88D039* + ID_OUI_FROM_DATABASE=TCL Technoly Electronics(Huizhou).,Ltd + +OUI:88D171* + ID_OUI_FROM_DATABASE=BEGHELLI S.P.A + +OUI:88D211* + ID_OUI_FROM_DATABASE=Eko Devices, Inc. + +OUI:88D274* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:88D2BF* + ID_OUI_FROM_DATABASE=German Autolabs + +OUI:88D37B* + ID_OUI_FROM_DATABASE=FirmTek, LLC + +OUI:88D50C* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:88D5A8* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:88D652* + ID_OUI_FROM_DATABASE=AMERGINT Technologies + +OUI:88D7BC* + ID_OUI_FROM_DATABASE=DEP Company + +OUI:88D7F6* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:88D962* + ID_OUI_FROM_DATABASE=Canopus Systems US LLC + +OUI:88D98F* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:88DA1A* + ID_OUI_FROM_DATABASE=Redpine Signals, Inc. + +OUI:88DA33* + ID_OUI_FROM_DATABASE=Beijing Xiaoyuer Network Technology Co., Ltd + +OUI:88DC96* + ID_OUI_FROM_DATABASE=SENAO Networks, Inc. + +OUI:88DD79* + ID_OUI_FROM_DATABASE=Voltaire + +OUI:88DE7C* + ID_OUI_FROM_DATABASE=Askey Computer Corp. + +OUI:88DEA9* + ID_OUI_FROM_DATABASE=Roku, Inc. + +OUI:88DF9E* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:88E034* + ID_OUI_FROM_DATABASE=Shinwa industries(China) ltd. + +OUI:88E0A0* + ID_OUI_FROM_DATABASE=Shenzhen VisionSTOR Technologies Co., Ltd + +OUI:88E0F3* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:88E161* + ID_OUI_FROM_DATABASE=Art Beijing Science and Technology Development Co., Ltd. + +OUI:88E3AB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88E603* + ID_OUI_FROM_DATABASE=Avotek corporation + +OUI:88E628* + ID_OUI_FROM_DATABASE=Shenzhen Kezhonglong Optoelectronic Technology Co.,Ltd + +OUI:88E64B* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:88E712* + ID_OUI_FROM_DATABASE=Whirlpool Corporation + +OUI:88E7A6* + ID_OUI_FROM_DATABASE=iKnowledge Integration Corp. + +OUI:88E87F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:88E8F8* + ID_OUI_FROM_DATABASE=YONG TAI ELECTRONIC (DONGGUAN) LTD. + +OUI:88E90F* + ID_OUI_FROM_DATABASE=innomdlelab + +OUI:88E917* + ID_OUI_FROM_DATABASE=Tamaggo + +OUI:88E9A4* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:88E9FE* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:88ED1C* + ID_OUI_FROM_DATABASE=Cudo Communication Co., Ltd. + +OUI:88EF16* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:88F031* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:88F077* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:88F488* + ID_OUI_FROM_DATABASE=cellon communications technology(shenzhen)Co.,Ltd. + +OUI:88F490* + ID_OUI_FROM_DATABASE=Jetmobile Pte Ltd + +OUI:88F56E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88F7BF* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:88F7C7* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:88F872* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:88FD15* + ID_OUI_FROM_DATABASE=LINEEYE CO., LTD + +OUI:88FED6* + ID_OUI_FROM_DATABASE=ShangHai WangYong Software Co., Ltd. + +OUI:8C006D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C02FA* + ID_OUI_FROM_DATABASE=COMMANDO Networks Limited + +OUI:8C04BA* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:8C04FF* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:8C0551* + ID_OUI_FROM_DATABASE=Koubachi AG + +OUI:8C078C* + ID_OUI_FROM_DATABASE=FLOW DATA INC + +OUI:8C088B* + ID_OUI_FROM_DATABASE=Remote Solution + +OUI:8C09F4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:8C0C87* + ID_OUI_FROM_DATABASE=Nokia + +OUI:8C0C90* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:8C0CA3* + ID_OUI_FROM_DATABASE=Amper + +OUI:8C0D76* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8C0EE3* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:8C0F6F* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:8C0F83* + ID_OUI_FROM_DATABASE=Angie Hospitality LLC + +OUI:8C0FA0* + ID_OUI_FROM_DATABASE=di-soric GmbH & Co. KG + +OUI:8C0FFA* + ID_OUI_FROM_DATABASE=Hutec co.,ltd + +OUI:8C10D4* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:8C11CB* + ID_OUI_FROM_DATABASE=ABUS Security-Center GmbH & Co. KG + +OUI:8C147D0* + ID_OUI_FROM_DATABASE=Nio + +OUI:8C147D1* + ID_OUI_FROM_DATABASE=Private + +OUI:8C147D2* + ID_OUI_FROM_DATABASE=Agilent S.p.A + +OUI:8C147D3* + ID_OUI_FROM_DATABASE=Remotec Technology Limited + +OUI:8C147D4* + ID_OUI_FROM_DATABASE=Nanjing bilian information Technology Co.,Ltd. + +OUI:8C147D5* + ID_OUI_FROM_DATABASE=Unwired Networks + +OUI:8C147D6* + ID_OUI_FROM_DATABASE=Shenzhen Meidou Technology Co, Ltd. + +OUI:8C147D7* + ID_OUI_FROM_DATABASE=UrbanHello + +OUI:8C147D8* + ID_OUI_FROM_DATABASE=V2 S.p.A. + +OUI:8C147D9* + ID_OUI_FROM_DATABASE=Anyware Solutions ApS + +OUI:8C147DA* + ID_OUI_FROM_DATABASE=Bluemega Document & Print Services + +OUI:8C147DB* + ID_OUI_FROM_DATABASE=Bausch Datacom NV/SA + +OUI:8C147DC* + ID_OUI_FROM_DATABASE=Reynaers Aluminium + +OUI:8C147DD* + ID_OUI_FROM_DATABASE=Shenzhen Lanxus technology Co. Ltd. + +OUI:8C147DE* + ID_OUI_FROM_DATABASE=Electrical & Automation Larsen & Toubro Limited + +OUI:8C14B4* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:8C15C7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8C1645* + ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd + +OUI:8C1850* + ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd. + +OUI:8C18D9* + ID_OUI_FROM_DATABASE=Shenzhen RF Technology Co., Ltd + +OUI:8C192D0* + ID_OUI_FROM_DATABASE=Noritsu Precision Co., Ltd. + +OUI:8C192D1* + ID_OUI_FROM_DATABASE=Shenzhen Huanuo Internet Technology Co.,Ltd + +OUI:8C192D2* + ID_OUI_FROM_DATABASE=DataRemote Inc. + +OUI:8C192D3* + ID_OUI_FROM_DATABASE=Greenfield Technology + +OUI:8C192D4* + ID_OUI_FROM_DATABASE=Charmlink Tech(HK) Co.,Limited + +OUI:8C192D5* + ID_OUI_FROM_DATABASE=ELCO(TIANJIN)ELECTRONICS CO.,LTD. + +OUI:8C192D6* + ID_OUI_FROM_DATABASE=smartHome Partner GmbH + +OUI:8C192D7* + ID_OUI_FROM_DATABASE=SRETT + +OUI:8C192D8* + ID_OUI_FROM_DATABASE=Shenzhen Cylan Technology Co.,Ltd + +OUI:8C192D9* + ID_OUI_FROM_DATABASE=ViaWear, Inc. + +OUI:8C192DA* + ID_OUI_FROM_DATABASE=TeleAlarm SA + +OUI:8C192DB* + ID_OUI_FROM_DATABASE=Abside Networks, Inc. + +OUI:8C192DC* + ID_OUI_FROM_DATABASE=You Zhengcheng co.,ltd + +OUI:8C192DD* + ID_OUI_FROM_DATABASE=Pyras Technology Inc. + +OUI:8C192DE* + ID_OUI_FROM_DATABASE=Elcon AB + +OUI:8C1ABF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8C1CDA0* + ID_OUI_FROM_DATABASE=CEOS Pty Ltd + +OUI:8C1CDA1* + ID_OUI_FROM_DATABASE=GESAS GmbH + +OUI:8C1CDA2* + ID_OUI_FROM_DATABASE=GEOMC + +OUI:8C1CDA3* + ID_OUI_FROM_DATABASE=Structura Technology & Innovation + +OUI:8C1CDA4* + ID_OUI_FROM_DATABASE=Anntec (Beijing) Technology Co.,Ltd. + +OUI:8C1CDA5* + ID_OUI_FROM_DATABASE=Septentrio NV + +OUI:8C1CDA6* + ID_OUI_FROM_DATABASE=LocoLabs LLC + +OUI:8C1CDA7* + ID_OUI_FROM_DATABASE=K Technology Corporation + +OUI:8C1CDA8* + ID_OUI_FROM_DATABASE=ATOL LLC + +OUI:8C1CDA9* + ID_OUI_FROM_DATABASE=Raychem RPG PVT. LTD. + +OUI:8C1CDAA* + ID_OUI_FROM_DATABASE=China Potevio Co., Ltd + +OUI:8C1CDAB* + ID_OUI_FROM_DATABASE=T+A elektroakustik GmbH & Co.KG + +OUI:8C1CDAC* + ID_OUI_FROM_DATABASE=Alcidae Inc + +OUI:8C1CDAD* + ID_OUI_FROM_DATABASE=Riegl Laser Measurement Systems GmbH + +OUI:8C1CDAE* + ID_OUI_FROM_DATABASE=Electronic Controlled Systems, Inc. + +OUI:8C1F94* + ID_OUI_FROM_DATABASE=RF Surgical System Inc. + +OUI:8C210A* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:8C2505* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8C271D* + ID_OUI_FROM_DATABASE=QuantHouse + +OUI:8C278A* + ID_OUI_FROM_DATABASE=Vocollect Inc + +OUI:8C2937* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C2DAA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C2F39* + ID_OUI_FROM_DATABASE=IBA Dosimetry GmbH + +OUI:8C2FA6* + ID_OUI_FROM_DATABASE=Solid Optics B.V. + +OUI:8C3330* + ID_OUI_FROM_DATABASE=EmFirst Co., Ltd. + +OUI:8C3357* + ID_OUI_FROM_DATABASE=HiteVision Digital Media Technology Co.,Ltd. + +OUI:8C34FD* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8C3579* + ID_OUI_FROM_DATABASE=QDIQO Sp. z o.o. + +OUI:8C395C* + ID_OUI_FROM_DATABASE=Bit4id Srl + +OUI:8C3A7E* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. + +OUI:8C3AE3* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:8C3B32* + ID_OUI_FROM_DATABASE=Microfan B.V. + +OUI:8C3BAD* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:8C3C07* + ID_OUI_FROM_DATABASE=Skiva Technologies, Inc. + +OUI:8C3C4A* + ID_OUI_FROM_DATABASE=NAKAYO Inc + +OUI:8C41F2* + ID_OUI_FROM_DATABASE=RDA Technologies Ltd. + +OUI:8C41F4* + ID_OUI_FROM_DATABASE=IPmotion GmbH + +OUI:8C426D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8C4435* + ID_OUI_FROM_DATABASE=Shanghai BroadMobi Communication Technology Co., Ltd. + +OUI:8C444F* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:8C4500* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:8C4962* + ID_OUI_FROM_DATABASE=Roku, Inc + +OUI:8C4AEE* + ID_OUI_FROM_DATABASE=GIGA TMS INC + +OUI:8C4B59* + ID_OUI_FROM_DATABASE=3D Imaging & Simulations Corp + +OUI:8C4CAD* + ID_OUI_FROM_DATABASE=Evoluzn Inc. + +OUI:8C4CDC* + ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. + +OUI:8C4DB9* + ID_OUI_FROM_DATABASE=Unmonday Ltd + +OUI:8C4DEA* + ID_OUI_FROM_DATABASE=Cerio Corporation + +OUI:8C5105* + ID_OUI_FROM_DATABASE=Shenzhen ireadygo Information Technology CO.,LTD. + +OUI:8C53C3* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Mobile Software Co., Ltd + +OUI:8C53D2* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:8C53F7* + ID_OUI_FROM_DATABASE=A&D ENGINEERING CO., LTD. + +OUI:8C541D* + ID_OUI_FROM_DATABASE=LGE + +OUI:8C569D* + ID_OUI_FROM_DATABASE=Imaging Solutions Group + +OUI:8C56C5* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:8C579B* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:8C57FD* + ID_OUI_FROM_DATABASE=LVX Western + +OUI:8C5877* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C593C0* + ID_OUI_FROM_DATABASE=Fujian Chaozhi Group Co., Ltd. + +OUI:8C593C1* + ID_OUI_FROM_DATABASE=Future Robot Technology Co., Limited + +OUI:8C593C2* + ID_OUI_FROM_DATABASE=Beida Jade Bird Universal Fire Alarm Device CO.,LTD. + +OUI:8C593C3* + ID_OUI_FROM_DATABASE=Chongqing beimoting technology co.ltd + +OUI:8C593C4* + ID_OUI_FROM_DATABASE=Guralp Systems Limited + +OUI:8C593C5* + ID_OUI_FROM_DATABASE=Spectranetix + +OUI:8C593C6* + ID_OUI_FROM_DATABASE=Qbic Technology Co., Ltd + +OUI:8C593C7* + ID_OUI_FROM_DATABASE=OBO Pro.2 Inc. + +OUI:8C593C8* + ID_OUI_FROM_DATABASE=Nanonord A/S + +OUI:8C593C9* + ID_OUI_FROM_DATABASE=GENIS + +OUI:8C593CA* + ID_OUI_FROM_DATABASE=ecom instruments GmbH + +OUI:8C593CB* + ID_OUI_FROM_DATABASE=Scharfe-Sicht GmbH + +OUI:8C593CC* + ID_OUI_FROM_DATABASE=Dantherm Cooling Inc. + +OUI:8C593CD* + ID_OUI_FROM_DATABASE=IDRO-ELETTRICA S.P.A. + +OUI:8C593CE* + ID_OUI_FROM_DATABASE=Shenzhen Tian-Power Technology Co.,Ltd. + +OUI:8C5973* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:8C598B* + ID_OUI_FROM_DATABASE=C Technologies AB + +OUI:8C59C3* + ID_OUI_FROM_DATABASE=ADB Italia + +OUI:8C59DC* + ID_OUI_FROM_DATABASE=ASR Microelectronics (Shanghai) Co., Ltd. + +OUI:8C5A25* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:8C5AC1* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:8C5AF0* + ID_OUI_FROM_DATABASE=Exeltech Solar Products + +OUI:8C5AF8* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd. + +OUI:8C5BF0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:8C5CA1* + ID_OUI_FROM_DATABASE=d-broad,INC + +OUI:8C5D60* + ID_OUI_FROM_DATABASE=UCI Corporation Co.,Ltd. + +OUI:8C5F48* + ID_OUI_FROM_DATABASE=Continental Intelligent Transportation Systems LLC + +OUI:8C5FAD* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:8C5FDF* + ID_OUI_FROM_DATABASE=Beijing Railway Signal Factory + +OUI:8C604F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:8C6078* + ID_OUI_FROM_DATABASE=Swissbit AG + +OUI:8C60E7* + ID_OUI_FROM_DATABASE=MPGIO CO.,LTD + +OUI:8C6102* + ID_OUI_FROM_DATABASE=Beijing Baofengmojing Technologies Co., Ltd + +OUI:8C61A3* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:8C640B* + ID_OUI_FROM_DATABASE=Beyond Devices d.o.o. + +OUI:8C6422* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:8C683A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8C6878* + ID_OUI_FROM_DATABASE=Nortek-AS + +OUI:8C68C8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:8C6AE4* + ID_OUI_FROM_DATABASE=Viogem Limited + +OUI:8C6D50* + ID_OUI_FROM_DATABASE=SHENZHEN MTC CO LTD + +OUI:8C6D77* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8C6DC4* + ID_OUI_FROM_DATABASE=Megapixel VR + +OUI:8C705A* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:8C71F8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8C736E* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:8C76C1* + ID_OUI_FROM_DATABASE=Goden Tech Limited + +OUI:8C7712* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8C7716* + ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED + +OUI:8C78D7* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:8C7967* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:8C79F5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8C7B9D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C7BF0* + ID_OUI_FROM_DATABASE=Xufeng Development Limited + +OUI:8C7C92* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C7CB5* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:8C7CFF* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:8C7EB3* + ID_OUI_FROM_DATABASE=Lytro, Inc. + +OUI:8C7F3B* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:8C8126* + ID_OUI_FROM_DATABASE=ARCOM + +OUI:8C82A8* + ID_OUI_FROM_DATABASE=Insigma Technology Co.,Ltd + +OUI:8C839D* + ID_OUI_FROM_DATABASE=SHENZHEN XINYUPENG ELECTRONIC TECHNOLOGY CO., LTD + +OUI:8C83DF* + ID_OUI_FROM_DATABASE=Nokia + +OUI:8C83E1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8C8401* + ID_OUI_FROM_DATABASE=Private + +OUI:8C8580* + ID_OUI_FROM_DATABASE=Smart Innovation LLC + +OUI:8C8590* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C85E6* + ID_OUI_FROM_DATABASE=Cleondris GmbH + +OUI:8C861E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C873B* + ID_OUI_FROM_DATABASE=Leica Camera AG + +OUI:8C897A* + ID_OUI_FROM_DATABASE=AUGTEK + +OUI:8C89A5* + ID_OUI_FROM_DATABASE=Micro-Star INT'L CO., LTD + +OUI:8C89FA* + ID_OUI_FROM_DATABASE=Zhejiang Hechuan Technology Co., Ltd. + +OUI:8C8A6E* + ID_OUI_FROM_DATABASE=ESTUN AUTOMATION TECHNOLOY CO., LTD + +OUI:8C8ABB* + ID_OUI_FROM_DATABASE=Beijing Orient View Technology Co., Ltd. + +OUI:8C8B83* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:8C8E76* + ID_OUI_FROM_DATABASE=taskit GmbH + +OUI:8C8EF2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C8F8B* + ID_OUI_FROM_DATABASE=China Mobile Chongqing branch + +OUI:8C8FE9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8C90D3* + ID_OUI_FROM_DATABASE=Nokia + +OUI:8C9109* + ID_OUI_FROM_DATABASE=Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd. + +OUI:8C9236* + ID_OUI_FROM_DATABASE=Aus.Linx Technology Co., Ltd. + +OUI:8C9246* + ID_OUI_FROM_DATABASE=Oerlikon Textile Gmbh&Co.KG + +OUI:8C9351* + ID_OUI_FROM_DATABASE=Jigowatts Inc. + +OUI:8C94CF* + ID_OUI_FROM_DATABASE=Encell Technology, Inc. + +OUI:8C965F* + ID_OUI_FROM_DATABASE=Shandong Zhongan Technology Co., Ltd. + +OUI:8C97EA* + ID_OUI_FROM_DATABASE=FREEBOX SAS + +OUI:8C99E6* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:8C9F3B* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:8CA048* + ID_OUI_FROM_DATABASE=Beijing NeTopChip Technology Co.,LTD + +OUI:8CA2FD* + ID_OUI_FROM_DATABASE=Starry, Inc. + +OUI:8CA5A1* + ID_OUI_FROM_DATABASE=Oregano Systems - Design & Consulting GmbH + +OUI:8CA6DF* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:8CA96F* + ID_OUI_FROM_DATABASE=D&M Holdings Inc. + +OUI:8CA982* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:8CAAB5* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:8CAB8E* + ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd. + +OUI:8CAE4C* + ID_OUI_FROM_DATABASE=Plugable Technologies + +OUI:8CAE89* + ID_OUI_FROM_DATABASE=Y-cam Solutions Ltd + +OUI:8CAEDB* + ID_OUI_FROM_DATABASE=NAG LLC + +OUI:8CB094* + ID_OUI_FROM_DATABASE=Airtech I&C Co., Ltd + +OUI:8CB0E9* + ID_OUI_FROM_DATABASE=Samsung Electronics.,LTD + +OUI:8CB64F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:8CB7F7* + ID_OUI_FROM_DATABASE=Shenzhen UniStrong Science & Technology Co., Ltd + +OUI:8CB82C* + ID_OUI_FROM_DATABASE=IPitomy Communications + +OUI:8CB84A* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:8CB864* + ID_OUI_FROM_DATABASE=AcSiP Technology Corp. + +OUI:8CBA25* + ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD + +OUI:8CBE24* + ID_OUI_FROM_DATABASE=Tashang Semiconductor(Shanghai) Co., Ltd. + +OUI:8CBEBE* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:8CBF9D* + ID_OUI_FROM_DATABASE=Shanghai Xinyou Information Technology Ltd. Co. + +OUI:8CBFA6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8CC121* + ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company + +OUI:8CC5E1* + ID_OUI_FROM_DATABASE=ShenZhen Konka Telecommunication Technology Co.,Ltd + +OUI:8CC661* + ID_OUI_FROM_DATABASE=Current, powered by GE + +OUI:8CC681* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:8CC7AA* + ID_OUI_FROM_DATABASE=Radinet Communications Inc. + +OUI:8CC7D0* + ID_OUI_FROM_DATABASE=zhejiang ebang communication co.,ltd + +OUI:8CC84B* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:8CC8CD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8CC8F40* + ID_OUI_FROM_DATABASE=Guardtec,Inc + +OUI:8CC8F41* + ID_OUI_FROM_DATABASE=Lanhomex Technology(Shen Zhen)Co.,Ltd. + +OUI:8CC8F42* + ID_OUI_FROM_DATABASE=Dark Horse Connect LLC + +OUI:8CC8F43* + ID_OUI_FROM_DATABASE=TOHO DENKI IND.CO.,LTD + +OUI:8CC8F44* + ID_OUI_FROM_DATABASE=ITECH Electronic Co.,ltd. + +OUI:8CC8F45* + ID_OUI_FROM_DATABASE=Beijing KXWELL Technology CO., LTD + +OUI:8CC8F46* + ID_OUI_FROM_DATABASE=SHENZHEN D-light Technolgy Limited + +OUI:8CC8F47* + ID_OUI_FROM_DATABASE=Private + +OUI:8CC8F48* + ID_OUI_FROM_DATABASE=Strongbyte Solutions Limited + +OUI:8CC8F49* + ID_OUI_FROM_DATABASE=Swift Navigation Inc + +OUI:8CC8F4A* + ID_OUI_FROM_DATABASE=Trilux Group Management GmbH + +OUI:8CC8F4B* + ID_OUI_FROM_DATABASE=PTYPE Co., LTD. + +OUI:8CC8F4C* + ID_OUI_FROM_DATABASE=Shenzhen KSTAR Science and Technology Co., Ltd + +OUI:8CC8F4D* + ID_OUI_FROM_DATABASE=Beijing Xinxunxintong Eletronics Co.,Ltd + +OUI:8CC8F4E* + ID_OUI_FROM_DATABASE=Evaporcool Solutions + +OUI:8CCDA2* + ID_OUI_FROM_DATABASE=ACTP, Inc. + +OUI:8CCDE8* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:8CCF09* + ID_OUI_FROM_DATABASE=Dell EMC + +OUI:8CCF5C* + ID_OUI_FROM_DATABASE=BEFEGA GmbH + +OUI:8CCF8F* + ID_OUI_FROM_DATABASE=ITC Systems + +OUI:8CD17B* + ID_OUI_FROM_DATABASE=CG Mobile + +OUI:8CD2E9* + ID_OUI_FROM_DATABASE=YOKOTE SEIKO CO., LTD. + +OUI:8CD3A2* + ID_OUI_FROM_DATABASE=VisSim AS + +OUI:8CD48E* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:8CD628* + ID_OUI_FROM_DATABASE=Ikor Metering + +OUI:8CDB25* + ID_OUI_FROM_DATABASE=ESG Solutions + +OUI:8CDC02* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:8CDCD4* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:8CDD8D* + ID_OUI_FROM_DATABASE=Wifly-City System Inc. + +OUI:8CDE52* + ID_OUI_FROM_DATABASE=ISSC Technologies Corp. + +OUI:8CDE99* + ID_OUI_FROM_DATABASE=Comlab Inc. + +OUI:8CDF9D* + ID_OUI_FROM_DATABASE=NEC Corporation + +OUI:8CE081* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:8CE117* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:8CE2DA* + ID_OUI_FROM_DATABASE=Circle Media Inc + +OUI:8CE38E* + ID_OUI_FROM_DATABASE=Kioxia Corporation + +OUI:8CE5C0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:8CE5EF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8CE748* + ID_OUI_FROM_DATABASE=Private + +OUI:8CE78C* + ID_OUI_FROM_DATABASE=DK Networks + +OUI:8CE7B3* + ID_OUI_FROM_DATABASE=Sonardyne International Ltd + +OUI:8CEA1B* + ID_OUI_FROM_DATABASE=Edgecore Networks Corporation + +OUI:8CEBC6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8CEC4B* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:8CEEC6* + ID_OUI_FROM_DATABASE=Precepscion Pty. Ltd. + +OUI:8CF112* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:8CF228* + ID_OUI_FROM_DATABASE=MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:8CF5A3* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:8CF710* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:8CF773* + ID_OUI_FROM_DATABASE=Nokia + +OUI:8CF813* + ID_OUI_FROM_DATABASE=ORANGE POLSKA + +OUI:8CF945* + ID_OUI_FROM_DATABASE=Power Automation pte Ltd + +OUI:8CF957* + ID_OUI_FROM_DATABASE=RuiXingHengFang Network (Shenzhen) Co.,Ltd + +OUI:8CF9C9* + ID_OUI_FROM_DATABASE=MESADA Technology Co.,Ltd. + +OUI:8CFABA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8CFCA0* + ID_OUI_FROM_DATABASE=Shenzhen Smart Device Technology Co., LTD. + +OUI:8CFD18* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:8CFDF0* + ID_OUI_FROM_DATABASE=Qualcomm Inc. + +OUI:8CFE57* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:8CFE74* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:8CFEB4* + ID_OUI_FROM_DATABASE=VSOONTECH ELECTRONICS CO., LIMITED + +OUI:90004E* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:9000DB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:90013B* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:900218* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:90028A* + ID_OUI_FROM_DATABASE=Shenzhen Shidean Legrand Electronic Products Co.,Ltd + +OUI:9002A9* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:900325* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:900372* + ID_OUI_FROM_DATABASE=Longnan Junya Digital Technology Co. Ltd. + +OUI:9003B7* + ID_OUI_FROM_DATABASE=PARROT SA + +OUI:900628* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:900917* + ID_OUI_FROM_DATABASE=Far-sighted mobile + +OUI:900A1A* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:900A39* + ID_OUI_FROM_DATABASE=Wiio, Inc. + +OUI:900A3A* + ID_OUI_FROM_DATABASE=PSG Plastic Service GmbH + +OUI:900A84* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:900BC1* + ID_OUI_FROM_DATABASE=Sprocomm Technologies CO.,Ltd + +OUI:900CB4* + ID_OUI_FROM_DATABASE=Alinket Electronic Technology Co., Ltd + +OUI:900CC8* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:900D66* + ID_OUI_FROM_DATABASE=Digimore Electronics Co., Ltd + +OUI:900DCB* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:900E83* + ID_OUI_FROM_DATABASE=Monico Monitoring, Inc. + +OUI:900EB3* + ID_OUI_FROM_DATABASE=Shenzhen Amediatech Technology Co., Ltd. + +OUI:901234* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:9013DA* + ID_OUI_FROM_DATABASE=Athom B.V. + +OUI:901711* + ID_OUI_FROM_DATABASE=Hagenuk Marinekommunikation GmbH + +OUI:90179B* + ID_OUI_FROM_DATABASE=Nanomegas + +OUI:9017AC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9017C8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:90185E* + ID_OUI_FROM_DATABASE=Apex Tool Group GmbH & Co OHG + +OUI:90187C* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:9018AE* + ID_OUI_FROM_DATABASE=Shanghai Meridian Technologies, Co. Ltd. + +OUI:901900* + ID_OUI_FROM_DATABASE=SCS SA + +OUI:901A4F* + ID_OUI_FROM_DATABASE=EM Microelectronic + +OUI:901ACA* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:901B0E* + ID_OUI_FROM_DATABASE=Fujitsu Technology Solutions GmbH + +OUI:901D27* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:901EDD* + ID_OUI_FROM_DATABASE=GREAT COMPUTER CORPORATION + +OUI:90203A* + ID_OUI_FROM_DATABASE=BYD Precision Manufacture Co.,Ltd + +OUI:902083* + ID_OUI_FROM_DATABASE=General Engine Management Systems Ltd. + +OUI:9020C2* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:902106* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:902155* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:902181* + ID_OUI_FROM_DATABASE=Shanghai Huaqin Telecom Technology Co.,Ltd + +OUI:9023EC* + ID_OUI_FROM_DATABASE=Availink, Inc. + +OUI:90272B* + ID_OUI_FROM_DATABASE=Algorab S.r.l. + +OUI:9027E4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:902B34* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:902BD2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:902CC7* + ID_OUI_FROM_DATABASE=C-MAX Asia Limited + +OUI:902E1C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:902E87* + ID_OUI_FROM_DATABASE=LabJack + +OUI:9031CD* + ID_OUI_FROM_DATABASE=Onyx Healthcare Inc. + +OUI:90324B* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:90342B* + ID_OUI_FROM_DATABASE=Gatekeeper Systems, Inc. + +OUI:9034FC* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:90356E* + ID_OUI_FROM_DATABASE=Vodafone Omnitel N.V. + +OUI:903809* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:9038DF* + ID_OUI_FROM_DATABASE=Changzhou Tiannengbo System Co. Ltd. + +OUI:903A72* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:903AA0* + ID_OUI_FROM_DATABASE=Nokia + +OUI:903AE6* + ID_OUI_FROM_DATABASE=PARROT SA + +OUI:903C92* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:903CAE* + ID_OUI_FROM_DATABASE=Yunnan KSEC Digital Technology Co.,Ltd. + +OUI:903D5A* + ID_OUI_FROM_DATABASE=Shenzhen Wision Technology Holding Limited + +OUI:903D68* + ID_OUI_FROM_DATABASE=G-Printec, Inc. + +OUI:903D6B* + ID_OUI_FROM_DATABASE=Zicon Technology Corp. + +OUI:903DBD* + ID_OUI_FROM_DATABASE=SECURE METERS LIMITED + +OUI:903EAB* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:9043E2* + ID_OUI_FROM_DATABASE=Cornami, Inc + +OUI:904506* + ID_OUI_FROM_DATABASE=Tokyo Boeki Medisys Inc. + +OUI:9046A2* + ID_OUI_FROM_DATABASE=Tedipay UK Ltd + +OUI:9046B7* + ID_OUI_FROM_DATABASE=Vadaro Pte Ltd + +OUI:904716* + ID_OUI_FROM_DATABASE=RORZE CORPORATION + +OUI:90473C* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:90489A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:9049FA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:904C81* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:904CE5* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:904D4A* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:904DC3* + ID_OUI_FROM_DATABASE=Flonidan A/S + +OUI:904E2B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:904E910* + ID_OUI_FROM_DATABASE=Spirtech + +OUI:904E911* + ID_OUI_FROM_DATABASE=Apollo Video Technology + +OUI:904E912* + ID_OUI_FROM_DATABASE=North Pole Engineering, Inc. + +OUI:904E913* + ID_OUI_FROM_DATABASE=Teleepoch Ltd + +OUI:904E914* + ID_OUI_FROM_DATABASE=Wrtnode technology Inc. + +OUI:904E915* + ID_OUI_FROM_DATABASE=mcf88 SRL + +OUI:904E916* + ID_OUI_FROM_DATABASE=Nuwa Robotics (HK) Limited Taiwan Branch + +OUI:904E917* + ID_OUI_FROM_DATABASE=IBM + +OUI:904E918* + ID_OUI_FROM_DATABASE=CommandScape, Inc. + +OUI:904E919* + ID_OUI_FROM_DATABASE=CUTTER Systems spol. s r.o. + +OUI:904E91A* + ID_OUI_FROM_DATABASE=Kaertech Limited + +OUI:904E91B* + ID_OUI_FROM_DATABASE=Shanghai JaWay Information Technology Co., Ltd. + +OUI:904E91C* + ID_OUI_FROM_DATABASE=Showtacle s.r.o. + +OUI:904E91D* + ID_OUI_FROM_DATABASE=SKODA ELECTRIC a.s. + +OUI:904E91E* + ID_OUI_FROM_DATABASE=Shenzhen Cloudynamo Internet Technologies Co.,LTD. + +OUI:90505A* + ID_OUI_FROM_DATABASE=unGlue, Inc + +OUI:90507B* + ID_OUI_FROM_DATABASE=Advanced PANMOBIL Systems GmbH & Co. KG + +OUI:9050CA* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:90513F* + ID_OUI_FROM_DATABASE=Elettronica Santerno SpA + +OUI:905446* + ID_OUI_FROM_DATABASE=TES ELECTRONIC SOLUTIONS + +OUI:9055AE* + ID_OUI_FROM_DATABASE=Ericsson, EAB/RWI/K + +OUI:9055DE* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:905682* + ID_OUI_FROM_DATABASE=Lenbrook Industries Limited + +OUI:905692* + ID_OUI_FROM_DATABASE=Autotalks Ltd. + +OUI:9056FC* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:905851* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:9059AF* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:905C34* + ID_OUI_FROM_DATABASE=Sirius Electronic Systems Srl + +OUI:905C44* + ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. + +OUI:905D7C* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:905F2E* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:905F8D* + ID_OUI_FROM_DATABASE=modas GmbH + +OUI:9060F1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90610C* + ID_OUI_FROM_DATABASE=Fida International (S) Pte Ltd + +OUI:9061AE* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:90633B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:906717* + ID_OUI_FROM_DATABASE=Alphion India Private Limited + +OUI:90671C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9067B5* + ID_OUI_FROM_DATABASE=Alcatel-Lucent + +OUI:9067F3* + ID_OUI_FROM_DATABASE=Alcatel Lucent + +OUI:9068C3* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:906CAC* + ID_OUI_FROM_DATABASE=Fortinet, Inc. + +OUI:906D05* + ID_OUI_FROM_DATABASE=BXB ELECTRONICS CO., LTD + +OUI:906DC8* + ID_OUI_FROM_DATABASE=DLG Automação Industrial Ltda + +OUI:906EBB* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:906F18* + ID_OUI_FROM_DATABASE=Private + +OUI:906FA9* + ID_OUI_FROM_DATABASE=NANJING PUTIAN TELECOMMUNICATIONS TECHNOLOGY CO.,LTD. + +OUI:907025* + ID_OUI_FROM_DATABASE=Garea Microsys Co.,Ltd. + +OUI:907065* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:907240* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:907282* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:90735A* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:90749D* + ID_OUI_FROM_DATABASE=IRay Technology Co., Ltd. + +OUI:907841* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:9078B2* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:907910* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:907990* + ID_OUI_FROM_DATABASE=Benchmark Electronics Romania SRL + +OUI:907A0A* + ID_OUI_FROM_DATABASE=Gebr. Bode GmbH & Co KG + +OUI:907A28* + ID_OUI_FROM_DATABASE=Beijing Morncloud Information And Technology Co. Ltd. + +OUI:907A58* + ID_OUI_FROM_DATABASE=Zegna-Daidong Limited + +OUI:907AF1* + ID_OUI_FROM_DATABASE=Wally + +OUI:907E30* + ID_OUI_FROM_DATABASE=LARS + +OUI:907EBA* + ID_OUI_FROM_DATABASE=UTEK TECHNOLOGY (SHENZHEN) CO.,LTD + +OUI:907F61* + ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd. + +OUI:90812A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:908260* + ID_OUI_FROM_DATABASE=IEEE 1904.1 Working Group + +OUI:90834B* + ID_OUI_FROM_DATABASE=BEIJING YUNYI TIMES TECHNOLOGY CO,.LTD + +OUI:90837A* + ID_OUI_FROM_DATABASE=General Electric Water & Process Technologies + +OUI:90840D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90842B* + ID_OUI_FROM_DATABASE=LEGO System A/S + +OUI:90848B* + ID_OUI_FROM_DATABASE=HDR10+ Technologies, LLC + +OUI:908674* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:90869B* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:9088A2* + ID_OUI_FROM_DATABASE=IONICS TECHNOLOGY ME LTDA + +OUI:90895F* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:908C09* + ID_OUI_FROM_DATABASE=Total Phase + +OUI:908C43* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:908C44* + ID_OUI_FROM_DATABASE=H.K ZONGMU TECHNOLOGY CO., LTD. + +OUI:908C63* + ID_OUI_FROM_DATABASE=GZ Weedong Networks Technology Co. , Ltd + +OUI:908D1D* + ID_OUI_FROM_DATABASE=GH Technologies + +OUI:908D6C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:908D78* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:908FCF* + ID_OUI_FROM_DATABASE=UNO System Co., Ltd + +OUI:90903C* + ID_OUI_FROM_DATABASE=TRISON TECHNOLOGY CORPORATION + +OUI:909060* + ID_OUI_FROM_DATABASE=RSI VIDEO TECHNOLOGIES + +OUI:9092B4* + ID_OUI_FROM_DATABASE=Diehl BGT Defence GmbH & Co. KG + +OUI:90940A* + ID_OUI_FROM_DATABASE=Analog Devices, Inc + +OUI:909497* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9094E4* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:9097D5* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:9097F3* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:909864* + ID_OUI_FROM_DATABASE=Impex-Sat GmbH&Co KG + +OUI:909916* + ID_OUI_FROM_DATABASE=ELVEES NeoTek OJSC + +OUI:909A77* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:909C4A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:909D7D* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:909DE0* + ID_OUI_FROM_DATABASE=Newland Design + Assoc. Inc. + +OUI:909F33* + ID_OUI_FROM_DATABASE=EFM Networks + +OUI:909F43* + ID_OUI_FROM_DATABASE=Accutron Instruments Inc. + +OUI:90A137* + ID_OUI_FROM_DATABASE=Beijing Splendidtel Communication Technology Co,. Ltd + +OUI:90A210* + ID_OUI_FROM_DATABASE=United Telecoms Ltd + +OUI:90A25B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90A2DA* + ID_OUI_FROM_DATABASE=GHEO SA + +OUI:90A365* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:90A46A* + ID_OUI_FROM_DATABASE=SISNET CO., LTD + +OUI:90A4DE* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:90A62F* + ID_OUI_FROM_DATABASE=NAVER + +OUI:90A783* + ID_OUI_FROM_DATABASE=JSW PACIFIC CORPORATION + +OUI:90A7C1* + ID_OUI_FROM_DATABASE=Pakedge Device and Software Inc. + +OUI:90AC3F* + ID_OUI_FROM_DATABASE=BrightSign LLC + +OUI:90ADF7* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:90ADFC* + ID_OUI_FROM_DATABASE=Telechips, Inc. + +OUI:90AE1B* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:90AFD1* + ID_OUI_FROM_DATABASE=netKTI Co., Ltd + +OUI:90B0ED* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90B11C* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:90B134* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:90B144* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:90B1E0* + ID_OUI_FROM_DATABASE=Beijing Nebula Link Technology Co., Ltd + +OUI:90B21F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90B686* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:90B832* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:90B8D0* + ID_OUI_FROM_DATABASE=Joyent, Inc. + +OUI:90B8E0* + ID_OUI_FROM_DATABASE=SHENZHEN YANRAY TECHNOLOGY CO.,LTD + +OUI:90B931* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90B97D* + ID_OUI_FROM_DATABASE=Johnson Outdoors Marine Electronics d/b/a Minnkota + +OUI:90BDE6* + ID_OUI_FROM_DATABASE=Quectel Wireless Solutions Co., Ltd. + +OUI:90C115* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:90C1C6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90C35F* + ID_OUI_FROM_DATABASE=Nanjing Jiahao Technology Co., Ltd. + +OUI:90C54A* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:90C6820* + ID_OUI_FROM_DATABASE=Shenzhen Lencotion Technology Co.,Ltd + +OUI:90C6821* + ID_OUI_FROM_DATABASE=Shenzhen Photon Broadband Technology CO., LTD + +OUI:90C6822* + ID_OUI_FROM_DATABASE=ekey biometric systems gmbh + +OUI:90C6823* + ID_OUI_FROM_DATABASE=Innovative Electronic Technology + +OUI:90C6824* + ID_OUI_FROM_DATABASE=Neone, Inc. + +OUI:90C6825* + ID_OUI_FROM_DATABASE=S.A.E.T. S.R.L. + +OUI:90C6826* + ID_OUI_FROM_DATABASE=Nanjing Jiexi Technologies Co., Ltd. + +OUI:90C6827* + ID_OUI_FROM_DATABASE=Cinet Inc + +OUI:90C6828* + ID_OUI_FROM_DATABASE=Teletek Electronics + +OUI:90C6829* + ID_OUI_FROM_DATABASE=ACT + +OUI:90C682A* + ID_OUI_FROM_DATABASE=Beijing Acorn Networks Corporation + +OUI:90C682B* + ID_OUI_FROM_DATABASE=Lachmann & Rink GmbH + +OUI:90C682C* + ID_OUI_FROM_DATABASE=Li Seng Technology Ltd. + +OUI:90C682D* + ID_OUI_FROM_DATABASE=PowerShield Limited + +OUI:90C682E* + ID_OUI_FROM_DATABASE=Shanghai HuRong Communication Technology Development Co., Ltd. + +OUI:90C682F* + ID_OUI_FROM_DATABASE=Private + +OUI:90C792* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:90C7D8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:90C99B* + ID_OUI_FROM_DATABASE=Tesorion Nederland B.V. + +OUI:90CC24* + ID_OUI_FROM_DATABASE=Synaptics, Inc + +OUI:90CDB6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:90CF15* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:90CF6F* + ID_OUI_FROM_DATABASE=Dlogixs Co Ltd + +OUI:90CF7D* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:90D11B* + ID_OUI_FROM_DATABASE=Palomar Medical Technologies + +OUI:90D74F* + ID_OUI_FROM_DATABASE=Bookeen + +OUI:90D7BE* + ID_OUI_FROM_DATABASE=Wavelab Global Inc. + +OUI:90D7EB* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:90D852* + ID_OUI_FROM_DATABASE=Comtec Co., Ltd. + +OUI:90D8F3* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:90D92C* + ID_OUI_FROM_DATABASE=HUG-WITSCHI AG + +OUI:90DA4E* + ID_OUI_FROM_DATABASE=AVANU + +OUI:90DA6A* + ID_OUI_FROM_DATABASE=FOCUS H&S Co., Ltd. + +OUI:90DB46* + ID_OUI_FROM_DATABASE=E-LEAD ELECTRONIC CO., LTD + +OUI:90DD5D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90DFB7* + ID_OUI_FROM_DATABASE=s.m.s smart microwave sensors GmbH + +OUI:90DFFB* + ID_OUI_FROM_DATABASE=HOMERIDER SYSTEMS + +OUI:90E0F0* + ID_OUI_FROM_DATABASE=IEEE 1722a Working Group + +OUI:90E17B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90E202* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:90E2BA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:90E2FC0* + ID_OUI_FROM_DATABASE=Pars Ertebat Afzar Co. + +OUI:90E2FC1* + ID_OUI_FROM_DATABASE=Yite technology + +OUI:90E2FC2* + ID_OUI_FROM_DATABASE=ShenZhen Temwey Innovation Technology Co.,Ltd. + +OUI:90E2FC3* + ID_OUI_FROM_DATABASE=Shenzhen Hisource Technology Development CO.,Ltd. + +OUI:90E2FC4* + ID_OUI_FROM_DATABASE=Dongguan Kangyong electronics technology Co. Ltd + +OUI:90E2FC5* + ID_OUI_FROM_DATABASE=TOTALONE TECHNOLOGY CO., LTD. + +OUI:90E2FC6* + ID_OUI_FROM_DATABASE=Sindoh Techno Co., Ltd. + +OUI:90E2FC7* + ID_OUI_FROM_DATABASE=Fair Winds Digital srl + +OUI:90E2FC8* + ID_OUI_FROM_DATABASE=bitsensing Inc. + +OUI:90E2FC9* + ID_OUI_FROM_DATABASE=Huddly AS + +OUI:90E2FCA* + ID_OUI_FROM_DATABASE=Power Engineering & Manufacturing, Inc. + +OUI:90E2FCB* + ID_OUI_FROM_DATABASE=Shenzhen Dingsheng Intelligent Technology Co., Ltd + +OUI:90E2FCC* + ID_OUI_FROM_DATABASE=Stanley Security + +OUI:90E2FCD* + ID_OUI_FROM_DATABASE=Beijing Lanxum Computer Technology CO.,LTD. + +OUI:90E2FCE* + ID_OUI_FROM_DATABASE=DevCom spol. s r.o. + +OUI:90E6BA* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:90E710* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:90E7C4* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:90EA60* + ID_OUI_FROM_DATABASE=SPI Lasers Ltd + +OUI:90EC50* + ID_OUI_FROM_DATABASE=C.O.B.O. SPA + +OUI:90EC77* + ID_OUI_FROM_DATABASE=silicom + +OUI:90EED9* + ID_OUI_FROM_DATABASE=UNIVERSAL DE DESARROLLOS ELECTRÓNICOS, SA + +OUI:90EF68* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:90F052* + ID_OUI_FROM_DATABASE=MEIZU Technology Co., Ltd. + +OUI:90F1AA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:90F1B0* + ID_OUI_FROM_DATABASE=Hangzhou Anheng Info&Tech CO.,LTD + +OUI:90F278* + ID_OUI_FROM_DATABASE=Radius Gateway + +OUI:90F305* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:90F3B7* + ID_OUI_FROM_DATABASE=Kirisun Communications Co., Ltd. + +OUI:90F4C1* + ID_OUI_FROM_DATABASE=Rand McNally + +OUI:90F652* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:90F72F* + ID_OUI_FROM_DATABASE=Phillips Machine & Welding Co., Inc. + +OUI:90F891* + ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD. + +OUI:90FB5B* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:90FBA6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:90FD61* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:90FD73* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:90FD9F* + ID_OUI_FROM_DATABASE=Silicon Laboratories + +OUI:90FF79* + ID_OUI_FROM_DATABASE=Metro Ethernet Forum + +OUI:940006* + ID_OUI_FROM_DATABASE=jinyoung + +OUI:940070* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:940149* + ID_OUI_FROM_DATABASE=AutoHotBox + +OUI:9401C2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:94049C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9405B6* + ID_OUI_FROM_DATABASE=Liling FullRiver Electronics & Technology Ltd + +OUI:9405BB0* + ID_OUI_FROM_DATABASE=Qingdao Maotran Electronics co., ltd + +OUI:9405BB1* + ID_OUI_FROM_DATABASE=Dongguan Kingtron Electronics Tech Co., Ltd + +OUI:9405BB2* + ID_OUI_FROM_DATABASE=Dongguan CXWE Technology Co.,Ltd. + +OUI:9405BB3* + ID_OUI_FROM_DATABASE=Neurik AG + +OUI:9405BB4* + ID_OUI_FROM_DATABASE=Shenzhen Baolijie Technology Co., Ltd. + +OUI:9405BB5* + ID_OUI_FROM_DATABASE=Chengdu Zhongheng Network Co.,Ltd. + +OUI:9405BB6* + ID_OUI_FROM_DATABASE=ZIGPOS GmbH + +OUI:9405BB7* + ID_OUI_FROM_DATABASE=LTE-X, Inc + +OUI:9405BB8* + ID_OUI_FROM_DATABASE=iungo + +OUI:9405BB9* + ID_OUI_FROM_DATABASE=Zimmer GmbH + +OUI:9405BBA* + ID_OUI_FROM_DATABASE=SolarEdge Technologies + +OUI:9405BBB* + ID_OUI_FROM_DATABASE=AUSTAR HEARING SCIENCE AND TECHNILIGY(XIAMEN)CO.,LTD + +OUI:9405BBC* + ID_OUI_FROM_DATABASE=LAO INDUSTRIA LTDA + +OUI:9405BBD* + ID_OUI_FROM_DATABASE=Sunthink S&T Development Co.,Ltd + +OUI:9405BBE* + ID_OUI_FROM_DATABASE=BAE Systems + +OUI:940937* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:940B19* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:940B2D* + ID_OUI_FROM_DATABASE=NetView Technologies(Shenzhen) Co., Ltd + +OUI:940BD5* + ID_OUI_FROM_DATABASE=Himax Technologies, Inc + +OUI:940C6D* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:940C98* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:940E6B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:94103E* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:9411DA* + ID_OUI_FROM_DATABASE=ITF Fröschl GmbH + +OUI:94147A* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:941625* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:941673* + ID_OUI_FROM_DATABASE=Point Core SARL + +OUI:941882* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:94193A* + ID_OUI_FROM_DATABASE=Elvaco AB + +OUI:941C56* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:941D1C* + ID_OUI_FROM_DATABASE=TLab West Systems AB + +OUI:942053* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:942197* + ID_OUI_FROM_DATABASE=Stalmart Technology Limited + +OUI:94236E* + ID_OUI_FROM_DATABASE=Shenzhen Junlan Electronic Ltd + +OUI:9424B8* + ID_OUI_FROM_DATABASE=GREE ELECTRIC APPLIANCES, INC. OF ZHUHAI + +OUI:9424E1* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise + +OUI:942790* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:94282E* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:94290C* + ID_OUI_FROM_DATABASE=Shenyang wisdom Foundation Technology Development Co., Ltd. + +OUI:94292F* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:94298D* + ID_OUI_FROM_DATABASE=Shanghai AdaptComm Technology Co., Ltd. + +OUI:942A3F* + ID_OUI_FROM_DATABASE=Diversey Inc + +OUI:942CB3* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:942DDC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:942E17* + ID_OUI_FROM_DATABASE=Schneider Electric Canada Inc + +OUI:942E63* + ID_OUI_FROM_DATABASE=Finsécur + +OUI:94319B* + ID_OUI_FROM_DATABASE=Alphatronics BV + +OUI:9433DD* + ID_OUI_FROM_DATABASE=Taco Inc + +OUI:94350A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9436E0* + ID_OUI_FROM_DATABASE=Sichuan Bihong Broadcast & Television New Technologies Co.,Ltd + +OUI:9439E5* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:943AF0* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:943BB0* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:943BB1* + ID_OUI_FROM_DATABASE=Kaonmedia CO., LTD. + +OUI:943DC9* + ID_OUI_FROM_DATABASE=Asahi Net, Inc. + +OUI:943FC2* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:9440A2* + ID_OUI_FROM_DATABASE=Anywave Communication Technologies, Inc. + +OUI:9440C9* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:9441C1* + ID_OUI_FROM_DATABASE=Mini-Cam Limited + +OUI:944444* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:944452* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:944696* + ID_OUI_FROM_DATABASE=BaudTec Corporation + +OUI:944996* + ID_OUI_FROM_DATABASE=WiSilica Inc + +OUI:944A09* + ID_OUI_FROM_DATABASE=BitWise Controls + +OUI:944A0C* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:944F4C* + ID_OUI_FROM_DATABASE=Sound United LLC + +OUI:945047* + ID_OUI_FROM_DATABASE=Rechnerbetriebsgruppe + +OUI:945089* + ID_OUI_FROM_DATABASE=SimonsVoss Technologies GmbH + +OUI:945103* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:94513D* + ID_OUI_FROM_DATABASE=iSmart Alarm, Inc. + +OUI:9451BF* + ID_OUI_FROM_DATABASE=Hyundai ESG + +OUI:945330* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:945493* + ID_OUI_FROM_DATABASE=Rigado, LLC + +OUI:9454DF* + ID_OUI_FROM_DATABASE=YST CORP. + +OUI:9457A5* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:9458CB* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:945907* + ID_OUI_FROM_DATABASE=Shanghai HITE-BELDEN Network Technology Co., Ltd. + +OUI:94592D* + ID_OUI_FROM_DATABASE=EKE Building Technology Systems Ltd + +OUI:945B7E* + ID_OUI_FROM_DATABASE=TRILOBIT LTDA. + +OUI:94611E* + ID_OUI_FROM_DATABASE=Wata Electronics Co.,Ltd. + +OUI:946124* + ID_OUI_FROM_DATABASE=Pason Systems + +OUI:946269* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:946372* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:9463D1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:94652D* + ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd + +OUI:94659C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:9466E7* + ID_OUI_FROM_DATABASE=WOM Engineering + +OUI:94677E* + ID_OUI_FROM_DATABASE=Belden India Private Limited + +OUI:946A77* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:946AB0* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:9470D2* + ID_OUI_FROM_DATABASE=WINFIRM TECHNOLOGY + +OUI:9471AC* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:94756E* + ID_OUI_FROM_DATABASE=QinetiQ North America + +OUI:9476B7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:94772B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:947BBE* + ID_OUI_FROM_DATABASE=Ubicquia + +OUI:947BE7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:947C3E* + ID_OUI_FROM_DATABASE=Polewall Norge AS + +OUI:947EB9* + ID_OUI_FROM_DATABASE=National Narrowband Network Communications Pty Ltd + +OUI:9481A4* + ID_OUI_FROM_DATABASE=Azuray Technologies + +OUI:9483C4* + ID_OUI_FROM_DATABASE=GL Technologies (Hong Kong) Limited + +OUI:94857A* + ID_OUI_FROM_DATABASE=Evantage Industries Corp + +OUI:9486CD* + ID_OUI_FROM_DATABASE=SEOUL ELECTRONICS&TELECOM + +OUI:9486D4* + ID_OUI_FROM_DATABASE=Surveillance Pro Corporation + +OUI:94877C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:9487E0* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:948815* + ID_OUI_FROM_DATABASE=Infinique Worldwide Inc + +OUI:948854* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:94885E* + ID_OUI_FROM_DATABASE=Surfilter Network Technology Co., Ltd. + +OUI:948B03* + ID_OUI_FROM_DATABASE=EAGET Innovation and Technology Co., Ltd. + +OUI:948BC1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:948D50* + ID_OUI_FROM_DATABASE=Beamex Oy Ab + +OUI:948DEF* + ID_OUI_FROM_DATABASE=Oetiker Schweiz AG + +OUI:948E89* + ID_OUI_FROM_DATABASE=INDUSTRIAS UNIDAS SA DE CV + +OUI:948FCF* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:948FEE* + ID_OUI_FROM_DATABASE=Verizon Telematics + +OUI:949034* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + +OUI:94917F* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:9492BC* + ID_OUI_FROM_DATABASE=SYNTECH(HK) TECHNOLOGY LIMITED + +OUI:9492D2* + ID_OUI_FROM_DATABASE=KCF Technologies, Inc. + +OUI:949426* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9495A0* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:9498A2* + ID_OUI_FROM_DATABASE=Shanghai LISTEN TECH.LTD + +OUI:949901* + ID_OUI_FROM_DATABASE=Shenzhen YITOA Digital Appliance CO.,LTD + +OUI:949990* + ID_OUI_FROM_DATABASE=VTC Telecommunications + +OUI:949AA9* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:949B2C* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:949BFD* + ID_OUI_FROM_DATABASE=Trans New Technology, Inc. + +OUI:949C55* + ID_OUI_FROM_DATABASE=Alta Data Technologies + +OUI:949D57* + ID_OUI_FROM_DATABASE=Panasonic do Brasil Limitada + +OUI:949F3E* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:949F3F* + ID_OUI_FROM_DATABASE=Optek Digital Technology company limited + +OUI:949FB4* + ID_OUI_FROM_DATABASE=ChengDu JiaFaAnTai Technology Co.,Ltd + +OUI:94A04E* + ID_OUI_FROM_DATABASE=Bostex Technology Co., LTD + +OUI:94A1A2* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:94A3CA* + ID_OUI_FROM_DATABASE=KonnectONE, LLC + +OUI:94A40C* + ID_OUI_FROM_DATABASE=Diehl Metering GmbH + +OUI:94A7B7* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:94A7BC* + ID_OUI_FROM_DATABASE=BodyMedia, Inc. + +OUI:94AAB8* + ID_OUI_FROM_DATABASE=Joview(Beijing) Technology Co. Ltd. + +OUI:94ABDE* + ID_OUI_FROM_DATABASE=OMX Technology - FZE + +OUI:94ACCA* + ID_OUI_FROM_DATABASE=trivum technologies GmbH + +OUI:94AE61* + ID_OUI_FROM_DATABASE=Alcatel Lucent + +OUI:94AEE3* + ID_OUI_FROM_DATABASE=Belden Hirschmann Industries (Suzhou) Ltd. + +OUI:94B01F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:94B10A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:94B2CC* + ID_OUI_FROM_DATABASE=PIONEER CORPORATION + +OUI:94B40F* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:94B819* + ID_OUI_FROM_DATABASE=Nokia + +OUI:94B86D* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:94B8C5* + ID_OUI_FROM_DATABASE=RuggedCom Inc. + +OUI:94B9B4* + ID_OUI_FROM_DATABASE=Aptos Technology + +OUI:94BA31* + ID_OUI_FROM_DATABASE=Visiontec da Amazônia Ltda. + +OUI:94BA56* + ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd. + +OUI:94BBAE* + ID_OUI_FROM_DATABASE=Husqvarna AB + +OUI:94BE46* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:94BF1E* + ID_OUI_FROM_DATABASE=eflow Inc. / Smart Device Planning and Development Division + +OUI:94BF2D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:94BF80* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:94BF95* + ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd + +OUI:94BFC4* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:94C014* + ID_OUI_FROM_DATABASE=Sorter Sp. j. Konrad Grzeszczyk MichaA, Ziomek + +OUI:94C038* + ID_OUI_FROM_DATABASE=Tallac Networks + +OUI:94C150* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:94C2BD* + ID_OUI_FROM_DATABASE=TECNOBIT + +OUI:94C3E4* + ID_OUI_FROM_DATABASE=Atlas Copco IAS GmbH + +OUI:94C4E9* + ID_OUI_FROM_DATABASE=PowerLayer Microsystems HongKong Limited + +OUI:94C691* + ID_OUI_FROM_DATABASE=EliteGroup Computer Systems Co., LTD + +OUI:94C6EB* + ID_OUI_FROM_DATABASE=NOVA electronics, Inc. + +OUI:94C7AF* + ID_OUI_FROM_DATABASE=Raylios Technology + +OUI:94C960* + ID_OUI_FROM_DATABASE=Zhongshan B&T technology.co.,ltd + +OUI:94C962* + ID_OUI_FROM_DATABASE=Teseq AG + +OUI:94CA0F* + ID_OUI_FROM_DATABASE=Honeywell Analytics + +OUI:94CC040* + ID_OUI_FROM_DATABASE=Hangzhou Yongkong Technology Co., Ltd. + +OUI:94CC041* + ID_OUI_FROM_DATABASE=GOCOAX, INC + +OUI:94CC042* + ID_OUI_FROM_DATABASE=Nanjing Yacer Communication Technology Co. Ltd. + +OUI:94CC043* + ID_OUI_FROM_DATABASE=Shenzhen Link technology Co.,Ltd + +OUI:94CC044* + ID_OUI_FROM_DATABASE=ProConnections, Inc. + +OUI:94CC045* + ID_OUI_FROM_DATABASE=SHENZHEN SANRAY TECHNOLOGY CO.,LTD + +OUI:94CC046* + ID_OUI_FROM_DATABASE=Sam Nazarko Trading Ltd + +OUI:94CC047* + ID_OUI_FROM_DATABASE=Gowing Business And Contracting Wenzhou Co., LTD + +OUI:94CC048* + ID_OUI_FROM_DATABASE=CircuitWerkes, Inc. + +OUI:94CC049* + ID_OUI_FROM_DATABASE=ENTEC Electric & Electronic Co., LTD. + +OUI:94CC04A* + ID_OUI_FROM_DATABASE=hyBee Inc. + +OUI:94CC04B* + ID_OUI_FROM_DATABASE=Shandong free optical technology co., ltd. + +OUI:94CC04C* + ID_OUI_FROM_DATABASE=Shanxi Baixin Information Technology Co., Ltd. + +OUI:94CC04D* + ID_OUI_FROM_DATABASE=Hanzhuo Information Technology(Shanghai) Ltd. + +OUI:94CC04E* + ID_OUI_FROM_DATABASE=SynchronicIT BV + +OUI:94CCB9* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:94CDAC* + ID_OUI_FROM_DATABASE=Creowave Oy + +OUI:94CE2C* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:94CE31* + ID_OUI_FROM_DATABASE=CTS Limited + +OUI:94D00D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:94D019* + ID_OUI_FROM_DATABASE=Cydle Corp. + +OUI:94D029* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:94D075* + ID_OUI_FROM_DATABASE=CIS Crypto + +OUI:94D299* + ID_OUI_FROM_DATABASE=Techmation Co.,Ltd. + +OUI:94D417* + ID_OUI_FROM_DATABASE=GPI KOREA INC. + +OUI:94D469* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:94D505* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:94D60E* + ID_OUI_FROM_DATABASE=shenzhen yunmao information technologies co., ltd + +OUI:94D6DB* + ID_OUI_FROM_DATABASE=NexFi + +OUI:94D723* + ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co.,Ltd + +OUI:94D771* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:94D859* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:94D93C* + ID_OUI_FROM_DATABASE=ENELPS + +OUI:94D9B3* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:94DB49* + ID_OUI_FROM_DATABASE=SITCORP + +OUI:94DB56* + ID_OUI_FROM_DATABASE=Sony Home Entertainment&Sound Products Inc + +OUI:94DBC9* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:94DBDA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:94DC4E* + ID_OUI_FROM_DATABASE=AEV, spol. s r. o. + +OUI:94DD3F* + ID_OUI_FROM_DATABASE=A+V Link Technologies, Corp. + +OUI:94DE0E* + ID_OUI_FROM_DATABASE=SmartOptics AS + +OUI:94DE80* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:94DF4E* + ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd. + +OUI:94DF58* + ID_OUI_FROM_DATABASE=IJ Electron CO.,Ltd. + +OUI:94E0D0* + ID_OUI_FROM_DATABASE=HealthStream Taiwan Inc. + +OUI:94E0D6* + ID_OUI_FROM_DATABASE=China Dragon Technology Limited + +OUI:94E1AC* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:94E226* + ID_OUI_FROM_DATABASE=D. ORtiz Consulting, LLC + +OUI:94E2FD* + ID_OUI_FROM_DATABASE=Boge Kompressoren OTTO Boge GmbH & Co. KG + +OUI:94E36D* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:94E4BA* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:94E6F7* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:94E711* + ID_OUI_FROM_DATABASE=Xirka Dama Persada PT + +OUI:94E7EA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:94E848* + ID_OUI_FROM_DATABASE=FYLDE MICRO LTD + +OUI:94E8C5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:94E96A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:94E979* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:94E98C* + ID_OUI_FROM_DATABASE=Nokia + +OUI:94E9EE* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:94EAEA* + ID_OUI_FROM_DATABASE=TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO + +OUI:94EB2C* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:94EBCD* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:94EE9F* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:94F128* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:94F19E* + ID_OUI_FROM_DATABASE=HUIZHOU MAORONG INTELLIGENT TECHNOLOGY CO.,LTD + +OUI:94F278* + ID_OUI_FROM_DATABASE=Elma Electronic + +OUI:94F551* + ID_OUI_FROM_DATABASE=Cadi Scientific Pte Ltd + +OUI:94F665* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:94F692* + ID_OUI_FROM_DATABASE=Geminico co.,Ltd. + +OUI:94F6A3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:94F6D6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:94F720* + ID_OUI_FROM_DATABASE=Tianjin Deviser Electronics Instrument Co., Ltd + +OUI:94F7AD* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:94FAE8* + ID_OUI_FROM_DATABASE=Shenzhen Eycom Technology Co., Ltd + +OUI:94FB29* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc. + +OUI:94FBB2* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:94FD1D* + ID_OUI_FROM_DATABASE=WhereWhen Corp + +OUI:94FD2E* + ID_OUI_FROM_DATABASE=Shanghai Uniscope Technologies Co.,Ltd + +OUI:94FE22* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:94FE9D* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:94FEF4* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:98006A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:980074* + ID_OUI_FROM_DATABASE=Raisecom Technology CO., LTD + +OUI:9800C1* + ID_OUI_FROM_DATABASE=GuangZhou CREATOR Technology Co.,Ltd.(CHINA) + +OUI:9800C6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9801A7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:980284* + ID_OUI_FROM_DATABASE=Theobroma Systems GmbH + +OUI:9802D80* + ID_OUI_FROM_DATABASE=Stoerk-Tronic, Stoerk GmbH & Co.KG + +OUI:9802D81* + ID_OUI_FROM_DATABASE=SHENZHEN ATEKO PHOTOELECTRICITY CO LTD + +OUI:9802D82* + ID_OUI_FROM_DATABASE=United Power Research Technology Corp. + +OUI:9802D83* + ID_OUI_FROM_DATABASE=Grammer EiA Electronics nv + +OUI:9802D84* + ID_OUI_FROM_DATABASE=Zedi, Inc. + +OUI:9802D85* + ID_OUI_FROM_DATABASE=EBI Ltd. + +OUI:9802D86* + ID_OUI_FROM_DATABASE=Fritz Kuebler GmbH + +OUI:9802D87* + ID_OUI_FROM_DATABASE=Ormazabal Protection&Automation + +OUI:9802D88* + ID_OUI_FROM_DATABASE=Simplo Technology Co.,LTD + +OUI:9802D89* + ID_OUI_FROM_DATABASE=Navroom Beijing, China + +OUI:9802D8A* + ID_OUI_FROM_DATABASE=HySecurity + +OUI:9802D8B* + ID_OUI_FROM_DATABASE=HANSHIN MEDICAL CO., LTD. + +OUI:9802D8C* + ID_OUI_FROM_DATABASE=AGV spa + +OUI:9802D8D* + ID_OUI_FROM_DATABASE=Promicon Elektronik GmbH + Co.KG + +OUI:9802D8E* + ID_OUI_FROM_DATABASE=Private + +OUI:9802D8F* + ID_OUI_FROM_DATABASE=Private + +OUI:98039B* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:9803A0* + ID_OUI_FROM_DATABASE=ABB n.v. Power Quality Products + +OUI:9803D8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9806370* + ID_OUI_FROM_DATABASE=Zoleo Inc. + +OUI:9806371* + ID_OUI_FROM_DATABASE=E. P. Schlumberger + +OUI:9806372* + ID_OUI_FROM_DATABASE=Summa nv + +OUI:9806373* + ID_OUI_FROM_DATABASE=Hangzhou Sanxin Network Technology Co.,Ltd + +OUI:9806374* + ID_OUI_FROM_DATABASE=Chengdu Shuwei Communication Technology Co.,Ltd + +OUI:9806375* + ID_OUI_FROM_DATABASE=GS GLOBAL SECURITY INC + +OUI:9806376* + ID_OUI_FROM_DATABASE=BOEING SSG + +OUI:9806377* + ID_OUI_FROM_DATABASE=SAMWONTECH + +OUI:9806378* + ID_OUI_FROM_DATABASE=Shenzhen Y&D Electronics Information Co., Ltd + +OUI:9806379* + ID_OUI_FROM_DATABASE=NAB co,.LTD + +OUI:980637A* + ID_OUI_FROM_DATABASE=Angora Networks + +OUI:980637B* + ID_OUI_FROM_DATABASE=Petersime + +OUI:980637C* + ID_OUI_FROM_DATABASE=HwaCom Systems Inc. + +OUI:980637D* + ID_OUI_FROM_DATABASE=VR Technology(Shenzhen) Limited + +OUI:980637E* + ID_OUI_FROM_DATABASE=Shanghai Jinnian information technology Co. Ltd + +OUI:98072D* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:9809CF* + ID_OUI_FROM_DATABASE=OnePlus Technology (Shenzhen) Co., Ltd + +OUI:980C82* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:980CA5* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:980D2E* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:980D51* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:980D67* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:980EE4* + ID_OUI_FROM_DATABASE=Private + +OUI:981094* + ID_OUI_FROM_DATABASE=Shenzhen Vsun communication technology Co.,ltd + +OUI:9810E8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:981333* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:9814D2* + ID_OUI_FROM_DATABASE=Avonic + +OUI:9816EC* + ID_OUI_FROM_DATABASE=IC Intracom + +OUI:981888* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:981BB5* + ID_OUI_FROM_DATABASE=ASSA ABLOY Korea Co., Ltd iRevo + +OUI:981DFA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:981E0F* + ID_OUI_FROM_DATABASE=Jeelan (Shanghai Jeelan Technology Information Inc + +OUI:981E19* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:981FB1* + ID_OUI_FROM_DATABASE=Shenzhen Lemon Network Technology Co.,Ltd + +OUI:98208E* + ID_OUI_FROM_DATABASE=Definium Technologies + +OUI:9822EF* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:98234E* + ID_OUI_FROM_DATABASE=Micromedia AG + +OUI:98262A* + ID_OUI_FROM_DATABASE=Applied Research Associates, Inc + +OUI:9828A6* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:98291D* + ID_OUI_FROM_DATABASE=Jaguar de Mexico, SA de CV + +OUI:98293F* + ID_OUI_FROM_DATABASE=Fujian Start Computer Equipment Co.,Ltd + +OUI:9829A6* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:982CBC* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:982CBE* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:982D56* + ID_OUI_FROM_DATABASE=Resolution Audio + +OUI:982D68* + ID_OUI_FROM_DATABASE=Samsung Electronics Co., Ltd + +OUI:982DBA* + ID_OUI_FROM_DATABASE=Fibergate Inc. + +OUI:982F3C* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. + +OUI:983000* + ID_OUI_FROM_DATABASE=Beijing KEMACOM Technologies Co., Ltd. + +OUI:983071* + ID_OUI_FROM_DATABASE=DAIKYUNG VASCOM + +OUI:98349D* + ID_OUI_FROM_DATABASE=Krauss Maffei Technologies GmbH + +OUI:983571* + ID_OUI_FROM_DATABASE=Sub10 Systems Ltd + +OUI:9835B8* + ID_OUI_FROM_DATABASE=Assembled Products Corporation + +OUI:9835ED* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:983713* + ID_OUI_FROM_DATABASE=PT.Navicom Indonesia + +OUI:98398E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:983B16* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:983B8F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:983F9F* + ID_OUI_FROM_DATABASE=China SSJ (Suzhou) Network Technology Inc. + +OUI:9840BB* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:98415C* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:984246* + ID_OUI_FROM_DATABASE=SOL INDUSTRY PTE., LTD + +OUI:9843DA* + ID_OUI_FROM_DATABASE=INTERTECH + +OUI:9844B6* + ID_OUI_FROM_DATABASE=INFRANOR SAS + +OUI:984562* + ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd. + +OUI:98460A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:98473C* + ID_OUI_FROM_DATABASE=SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD + +OUI:984827* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:984914* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:9849E1* + ID_OUI_FROM_DATABASE=Boeing Defence Australia + +OUI:984A47* + ID_OUI_FROM_DATABASE=CHG Hospital Beds + +OUI:984B4A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:984BE1* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:984C04* + ID_OUI_FROM_DATABASE=Zhangzhou Keneng Electrical Equipment Co Ltd + +OUI:984CD3* + ID_OUI_FROM_DATABASE=Mantis Deposition + +OUI:984E97* + ID_OUI_FROM_DATABASE=Starlight Marketing (H. K.) Ltd. + +OUI:984FEE* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:98523D* + ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd + +OUI:98524A* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:9852B1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:98541B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:9857D3* + ID_OUI_FROM_DATABASE=HON HAI-CCPBG PRECISION IND.CO.,LTD. + +OUI:98588A* + ID_OUI_FROM_DATABASE=SYSGRATION Ltd. + +OUI:985945* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:985AEB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:985BB0* + ID_OUI_FROM_DATABASE=KMDATA INC. + +OUI:985C93* + ID_OUI_FROM_DATABASE=SBG Systems SAS + +OUI:985D46* + ID_OUI_FROM_DATABASE=PeopleNet Communication + +OUI:985D82* + ID_OUI_FROM_DATABASE=Arista Networks + +OUI:985DAD* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:985E1B* + ID_OUI_FROM_DATABASE=ConversDigital Co., Ltd. + +OUI:985FD3* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:986022* + ID_OUI_FROM_DATABASE=EMW Co., Ltd. + +OUI:9866EA* + ID_OUI_FROM_DATABASE=Industrial Control Communications, Inc. + +OUI:986B3D* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:986C5C* + ID_OUI_FROM_DATABASE=Jiangxi Gosun Guard Security Co.,Ltd + +OUI:986CF5* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:986D350* + ID_OUI_FROM_DATABASE=Shenzhen MALATA Mobile Communication Co.,LTD + +OUI:986D351* + ID_OUI_FROM_DATABASE=Shenzhen cositea electronics technology co.,LTD + +OUI:986D352* + ID_OUI_FROM_DATABASE=SHENZHEN FISE TECHNOLOGY HOLDING CO.,LTD. + +OUI:986D353* + ID_OUI_FROM_DATABASE=DH Mechatronic AG + +OUI:986D354* + ID_OUI_FROM_DATABASE=blossom communications corp. + +OUI:986D355* + ID_OUI_FROM_DATABASE=PDAHL + +OUI:986D356* + ID_OUI_FROM_DATABASE=Vitronic Dr.-Ing. Stein Bildverarbeitungssysteme GmbH + +OUI:986D357* + ID_OUI_FROM_DATABASE=Zhejiang Hanshow Technology Co., Ltd. + +OUI:986D358* + ID_OUI_FROM_DATABASE=Beijing 3CAVI Tech Co.,Ltd + +OUI:986D359* + ID_OUI_FROM_DATABASE=Private + +OUI:986D35A* + ID_OUI_FROM_DATABASE=iWave Japan, Inc. + +OUI:986D35B* + ID_OUI_FROM_DATABASE=INTECH + +OUI:986D35C* + ID_OUI_FROM_DATABASE=my-PV GmbH + +OUI:986D35D* + ID_OUI_FROM_DATABASE=Praesideo B.V. + +OUI:986D35E* + ID_OUI_FROM_DATABASE=BAYCOM OPTO-ELECTRONICS TECHNOLGY CO., LTD. + +OUI:986DC8* + ID_OUI_FROM_DATABASE=TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION + +OUI:986F60* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:9870E8* + ID_OUI_FROM_DATABASE=INNATECH SDN BHD + +OUI:9873C4* + ID_OUI_FROM_DATABASE=Sage Electronic Engineering LLC + +OUI:98743D* + ID_OUI_FROM_DATABASE=Shenzhen Jun Kai Hengye Technology Co. Ltd + +OUI:9874DA* + ID_OUI_FROM_DATABASE=Infinix mobility limited + +OUI:9876B6* + ID_OUI_FROM_DATABASE=Adafruit + +OUI:987770* + ID_OUI_FROM_DATABASE=Pep Digital Technology (Guangzhou) Co., Ltd + +OUI:987A10* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:987A14* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:987BF3* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:987E46* + ID_OUI_FROM_DATABASE=Emizon Networks Limited + +OUI:988217* + ID_OUI_FROM_DATABASE=Disruptive Ltd + +OUI:988389* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9884E3* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:98865D* + ID_OUI_FROM_DATABASE=Nokia Shanghai Bell Co., Ltd. + +OUI:9886B1* + ID_OUI_FROM_DATABASE=Flyaudio corporation (China) + +OUI:988744* + ID_OUI_FROM_DATABASE=Wuxi Hongda Science and Technology Co.,LTD + +OUI:9889ED* + ID_OUI_FROM_DATABASE=Anadem Information Inc. + +OUI:988B0A* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:988B5D* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:988BAD* + ID_OUI_FROM_DATABASE=Corintech Ltd. + +OUI:988E34* + ID_OUI_FROM_DATABASE=ZHEJIANG BOXSAM ELECTRONIC CO.,LTD + +OUI:988E4A* + ID_OUI_FROM_DATABASE=NOXUS(BEIJING) TECHNOLOGY CO.,LTD + +OUI:988ED4* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:988EDD* + ID_OUI_FROM_DATABASE=TE Connectivity Limerick + +OUI:989080* + ID_OUI_FROM_DATABASE=Linkpower Network System Inc Ltd. + +OUI:989096* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:9893CC* + ID_OUI_FROM_DATABASE=LG ELECTRONICS INC + +OUI:989449* + ID_OUI_FROM_DATABASE=Skyworth Wireless Technology Ltd. + +OUI:9897D1* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:989BCB* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:989C57* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:989E63* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:98A404* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:98A40E* + ID_OUI_FROM_DATABASE=Snap, Inc. + +OUI:98A7B0* + ID_OUI_FROM_DATABASE=MCST ZAO + +OUI:98AA3C* + ID_OUI_FROM_DATABASE=Will i-tech Co., Ltd. + +OUI:98AAD7* + ID_OUI_FROM_DATABASE=BLUE WAVE NETWORKING CO LTD + +OUI:98AAFC0* + ID_OUI_FROM_DATABASE=Dalian Eastern Display Co., Ltd. + +OUI:98AAFC1* + ID_OUI_FROM_DATABASE=SURTEC + +OUI:98AAFC2* + ID_OUI_FROM_DATABASE=Shenzhen UniStrong Science & Technology Co., Ltd + +OUI:98AAFC3* + ID_OUI_FROM_DATABASE=Nexus Electrical(Jiaxing) Limited + +OUI:98AAFC4* + ID_OUI_FROM_DATABASE=RPE RADICO + +OUI:98AAFC5* + ID_OUI_FROM_DATABASE=SPM Instrument AB + +OUI:98AAFC6* + ID_OUI_FROM_DATABASE=Mekotronics Co., Ltd + +OUI:98AAFC7* + ID_OUI_FROM_DATABASE=Shenzhen Hubsan Technology Co.,LTD. + +OUI:98AAFC8* + ID_OUI_FROM_DATABASE=Beijing Tiandi-Marco Electro-Hydraulic Control System Company Ltd. + +OUI:98AAFC9* + ID_OUI_FROM_DATABASE=BEAM Authentic + +OUI:98AAFCA* + ID_OUI_FROM_DATABASE=SENKO Co.,Ltd. + +OUI:98AAFCB* + ID_OUI_FROM_DATABASE=Resonant Systems Inc. + +OUI:98AAFCC* + ID_OUI_FROM_DATABASE=dots Inc. + +OUI:98AAFCD* + ID_OUI_FROM_DATABASE=MCS Micronic Computer Systeme GmbH + +OUI:98AAFCE* + ID_OUI_FROM_DATABASE=Comarch S.A. + +OUI:98AE71* + ID_OUI_FROM_DATABASE=VVDN Technologies Pvt Ltd + +OUI:98AF65* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:98B039* + ID_OUI_FROM_DATABASE=Nokia + +OUI:98B6E9* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:98B8BA* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:98B8E3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:98BA39* + ID_OUI_FROM_DATABASE=Doro AB + +OUI:98BB1E* + ID_OUI_FROM_DATABASE=BYD Precision Manufacture Company Ltd. + +OUI:98BB99* + ID_OUI_FROM_DATABASE=Phicomm (Sichuan) Co.,Ltd. + +OUI:98BC57* + ID_OUI_FROM_DATABASE=SVA TECHNOLOGIES CO.LTD + +OUI:98BC99* + ID_OUI_FROM_DATABASE=Edeltech Co.,Ltd. + +OUI:98BE94* + ID_OUI_FROM_DATABASE=IBM + +OUI:98C0EB* + ID_OUI_FROM_DATABASE=Global Regency Ltd + +OUI:98C5DB* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:98C845* + ID_OUI_FROM_DATABASE=PacketAccess + +OUI:98C8B8* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:98CA33* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:98CB27* + ID_OUI_FROM_DATABASE=Galore Networks Pvt. Ltd. + +OUI:98CC4D* + ID_OUI_FROM_DATABASE=Shenzhen mantunsci co., LTD + +OUI:98CDB4* + ID_OUI_FROM_DATABASE=Virident Systems, Inc. + +OUI:98CF53* + ID_OUI_FROM_DATABASE=BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + +OUI:98D293* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:98D331* + ID_OUI_FROM_DATABASE=Shenzhen Bolutek Technology Co.,Ltd. + +OUI:98D3D2* + ID_OUI_FROM_DATABASE=MEKRA Lang GmbH & Co. KG + +OUI:98D3E7* + ID_OUI_FROM_DATABASE=Netafim L + +OUI:98D686* + ID_OUI_FROM_DATABASE=Chyi Lee industry Co., ltd. + +OUI:98D6BB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:98D6F7* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:98D863* + ID_OUI_FROM_DATABASE=Shanghai High-Flying Electronics Technology Co., Ltd + +OUI:98D88C* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:98DA92* + ID_OUI_FROM_DATABASE=Vuzix Corporation + +OUI:98DAC4* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:98DCD9* + ID_OUI_FROM_DATABASE=UNITEC Co., Ltd. + +OUI:98DD5B* + ID_OUI_FROM_DATABASE=TAKUMI JAPAN LTD + +OUI:98DDEA* + ID_OUI_FROM_DATABASE=Infinix mobility limited + +OUI:98DED0* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:98DF82* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:98E0D9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:98E165* + ID_OUI_FROM_DATABASE=Accutome + +OUI:98E476* + ID_OUI_FROM_DATABASE=Zentan + +OUI:98E743* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:98E79A* + ID_OUI_FROM_DATABASE=Foxconn(NanJing) Communication Co.,Ltd. + +OUI:98E7F4* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:98E7F5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:98E848* + ID_OUI_FROM_DATABASE=Axiim + +OUI:98E8FA* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:98EC65* + ID_OUI_FROM_DATABASE=Cosesy ApS + +OUI:98ED5C* + ID_OUI_FROM_DATABASE=Tesla,Inc. + +OUI:98EECB* + ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation + +OUI:98EF9B* + ID_OUI_FROM_DATABASE=OHSUNG + +OUI:98F058* + ID_OUI_FROM_DATABASE=Lynxspring, Incl. + +OUI:98F0AB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:98F170* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:98F199* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. + +OUI:98F2B3* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:98F428* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:98F4AB* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:98F537* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:98F5A9* + ID_OUI_FROM_DATABASE=OHSUNG + +OUI:98F781* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:98F7D7* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:98F8C1* + ID_OUI_FROM_DATABASE=IDT Technology Limited + +OUI:98F8DB* + ID_OUI_FROM_DATABASE=Marini Impianti Industriali s.r.l. + +OUI:98F9C70* + ID_OUI_FROM_DATABASE=SHENZHEN HUNTKEY ELECTRIC CO., LTD. + +OUI:98F9C71* + ID_OUI_FROM_DATABASE=HighSecLabs + +OUI:98F9C72* + ID_OUI_FROM_DATABASE=Pozyx NV + +OUI:98F9C73* + ID_OUI_FROM_DATABASE=Beijing Horizon Information Technology Co., Ltd + +OUI:98F9C74* + ID_OUI_FROM_DATABASE=Promess GmbH + +OUI:98F9C75* + ID_OUI_FROM_DATABASE=Tonycore Technology Co.,Ltd. + +OUI:98F9C76* + ID_OUI_FROM_DATABASE=GoodBox + +OUI:98F9C77* + ID_OUI_FROM_DATABASE=ARIMA Communications Corp. + +OUI:98F9C78* + ID_OUI_FROM_DATABASE=Renalsense + +OUI:98F9C79* + ID_OUI_FROM_DATABASE=Koala Technology CO., LTD. + +OUI:98F9C7A* + ID_OUI_FROM_DATABASE=MSB Elektronik und Gerätebau GmbH + +OUI:98F9C7B* + ID_OUI_FROM_DATABASE=HIROIA Communications Pte. Ltd. Taiwan Branch + +OUI:98F9C7C* + ID_OUI_FROM_DATABASE=ShenZhen Chuangwei Electronic Appliance Co.,Ltd + +OUI:98F9C7D* + ID_OUI_FROM_DATABASE=hangzhou soar security technologies limited liability company + +OUI:98F9C7E* + ID_OUI_FROM_DATABASE=NC-LINK Technology Co., Ltd. + +OUI:98FA9B* + ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd + +OUI:98FAA7* + ID_OUI_FROM_DATABASE=INNONET + +OUI:98FAE3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:98FB12* + ID_OUI_FROM_DATABASE=Grand Electronics (HK) Ltd + +OUI:98FC11* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:98FD74* + ID_OUI_FROM_DATABASE=ACT.CO.LTD + +OUI:98FDB4* + ID_OUI_FROM_DATABASE=Primax Electronics Ltd. + +OUI:98FE03* + ID_OUI_FROM_DATABASE=Ericsson - North America + +OUI:98FE94* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:98FF6A* + ID_OUI_FROM_DATABASE=OTEC(Shanghai)Technology Co.,Ltd. + +OUI:98FFD0* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:9C0111* + ID_OUI_FROM_DATABASE=Shenzhen Newabel Electronic Co., Ltd. + +OUI:9C0298* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9C039E* + ID_OUI_FROM_DATABASE=Beijing Winchannel Software Technology Co., Ltd + +OUI:9C0473* + ID_OUI_FROM_DATABASE=Tecmobile (International) Ltd. + +OUI:9C04EB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9C061B* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:9C066E* + ID_OUI_FROM_DATABASE=Hytera Communications Corporation Limited + +OUI:9C0CDF* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:9C0DAC* + ID_OUI_FROM_DATABASE=Tymphany HK Limited + +OUI:9C0E4A* + ID_OUI_FROM_DATABASE=Shenzhen Vastking Electronic Co.,Ltd. + +OUI:9C13AB* + ID_OUI_FROM_DATABASE=Chanson Water Co., Ltd. + +OUI:9C1463* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:9C1465* + ID_OUI_FROM_DATABASE=Edata Elektronik San. ve Tic. A.Ş. + +OUI:9C1874* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:9C1C12* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:9C1D36* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9C1D58* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:9C1E95* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:9C1FDD* + ID_OUI_FROM_DATABASE=Accupix Inc. + +OUI:9C207B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9C216A* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:9C220E* + ID_OUI_FROM_DATABASE=TASCAN Systems GmbH + +OUI:9C25BE* + ID_OUI_FROM_DATABASE=Wildlife Acoustics, Inc. + +OUI:9C2840* + ID_OUI_FROM_DATABASE=Discovery Technology,LTD.. + +OUI:9C28BF* + ID_OUI_FROM_DATABASE=Continental Automotive Czech Republic s.r.o. + +OUI:9C28EF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9C28F7* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:9C293F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9C2A70* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:9C2A83* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9C2DCF* + ID_OUI_FROM_DATABASE=Shishi Tongyun Technology(Chengdu)Co.,Ltd. + +OUI:9C2EA1* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:9C2F4E* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:9C2F73* + ID_OUI_FROM_DATABASE=Universal Tiancheng Technology (Beijing) Co., Ltd. + +OUI:9C305B* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:9C3066* + ID_OUI_FROM_DATABASE=RWE Effizienz GmbH + +OUI:9C3178* + ID_OUI_FROM_DATABASE=Foshan Huadian Intelligent Communications Teachnologies Co.,Ltd + +OUI:9C31B6* + ID_OUI_FROM_DATABASE=Kulite Semiconductor Products Inc + +OUI:9C31C3* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:9C32A9* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:9C32CE* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:9C3426* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:9C3583* + ID_OUI_FROM_DATABASE=Nipro Diagnostics, Inc + +OUI:9C35EB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9C37F4* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9C3A9A* + ID_OUI_FROM_DATABASE=Shenzhen Sundray Technologies Company Limited + +OUI:9C3AAF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9C3DCF* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:9C3EAA* + ID_OUI_FROM_DATABASE=EnvyLogic Co.,Ltd. + +OUI:9C417C* + ID_OUI_FROM_DATABASE=Hame Technology Co., Limited + +OUI:9C431E0* + ID_OUI_FROM_DATABASE=Antailiye Technology Co.,Ltd + +OUI:9C431E1* + ID_OUI_FROM_DATABASE=Symfun Telecom Ltd + +OUI:9C431E2* + ID_OUI_FROM_DATABASE=HAESUNG DS + +OUI:9C431E3* + ID_OUI_FROM_DATABASE=Advanced Logic Technology (ALT) sa + +OUI:9C431E4* + ID_OUI_FROM_DATABASE=Wireless Environment, LLC + +OUI:9C431E5* + ID_OUI_FROM_DATABASE=ProMOS Technologies Inc. + +OUI:9C431E6* + ID_OUI_FROM_DATABASE=R-S-I Elektrotechnik GmbH CO KG + +OUI:9C431E7* + ID_OUI_FROM_DATABASE=Optris GmbH + +OUI:9C431E8* + ID_OUI_FROM_DATABASE=Wunda Group plc + +OUI:9C431E9* + ID_OUI_FROM_DATABASE=CONTINENT Co. Ltd + +OUI:9C431EA* + ID_OUI_FROM_DATABASE=ST Access Control System Corp. + +OUI:9C431EB* + ID_OUI_FROM_DATABASE=JNL Technologies Inc + +OUI:9C431EC* + ID_OUI_FROM_DATABASE=SuZhou Jinruiyang Information Technology CO.,LTD + +OUI:9C431ED* + ID_OUI_FROM_DATABASE=HK ELEPHONE Communication Tech Co.,Limited + +OUI:9C431EE* + ID_OUI_FROM_DATABASE=Midas Technology DBA Phoenix Audio Technologies + +OUI:9C443D* + ID_OUI_FROM_DATABASE=CHENGDU XUGUANG TECHNOLOGY CO, LTD + +OUI:9C44A6* + ID_OUI_FROM_DATABASE=SwiftTest, Inc. + +OUI:9C4563* + ID_OUI_FROM_DATABASE=DIMEP Sistemas + +OUI:9C497F* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:9C4A7B* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:9C4CAE* + ID_OUI_FROM_DATABASE=Mesa Labs + +OUI:9C4E20* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:9C4E36* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:9C4E8E* + ID_OUI_FROM_DATABASE=ALT Systems Ltd + +OUI:9C4EBF* + ID_OUI_FROM_DATABASE=BoxCast + +OUI:9C4FCF* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:9C4FDA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9C50EE* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:9C52F8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9C53CD* + ID_OUI_FROM_DATABASE=ENGICAM s.r.l. + +OUI:9C541C* + ID_OUI_FROM_DATABASE=Shenzhen My-power Technology Co.,Ltd + +OUI:9C54CA* + ID_OUI_FROM_DATABASE=Zhengzhou VCOM Science and Technology Co.,Ltd + +OUI:9C54DA* + ID_OUI_FROM_DATABASE=SkyBell Technologies Inc. + +OUI:9C55B4* + ID_OUI_FROM_DATABASE=I.S.E. S.r.l. + +OUI:9C5711* + ID_OUI_FROM_DATABASE=Feitian Xunda(Beijing) Aeronautical Information Technology Co., Ltd. + +OUI:9C57AD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:9C5A44* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:9C5B96* + ID_OUI_FROM_DATABASE=NMR Corporation + +OUI:9C5C8D* + ID_OUI_FROM_DATABASE=FIREMAX INDÚSTRIA E COMÉRCIO DE PRODUTOS ELETRÔNICOS LTDA + +OUI:9C5C8E* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:9C5CF9* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:9C5D12* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:9C5D95* + ID_OUI_FROM_DATABASE=VTC Electronics Corp. + +OUI:9C5E73* + ID_OUI_FROM_DATABASE=Calibre UK LTD + +OUI:9C5F5A* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:9C611D* + ID_OUI_FROM_DATABASE=Panasonic Corporation of North America + +OUI:9C6121* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:9C62AB* + ID_OUI_FROM_DATABASE=Sumavision Technologies Co.,Ltd + +OUI:9C63ED* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:9C645E* + ID_OUI_FROM_DATABASE=Harman Consumer Group + +OUI:9C648B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9C65B0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9C65EE* + ID_OUI_FROM_DATABASE=DASAN Network Solutions + +OUI:9C65F9* + ID_OUI_FROM_DATABASE=AcSiP Technology Corp. + +OUI:9C6650* + ID_OUI_FROM_DATABASE=Glodio Technolies Co.,Ltd Tianjin Branch + +OUI:9C685B* + ID_OUI_FROM_DATABASE=Octonion SA + +OUI:9C6937* + ID_OUI_FROM_DATABASE=Qorvo Utrecht B.V. + +OUI:9C69B40* + ID_OUI_FROM_DATABASE=Suzhou Fitcan Technology Co.,LTD + +OUI:9C69B41* + ID_OUI_FROM_DATABASE=EA Technology Ltd + +OUI:9C69B42* + ID_OUI_FROM_DATABASE=MOZI (Shenzhen) Artificial Intelligence Technology Co., Ltd. + +OUI:9C69B43* + ID_OUI_FROM_DATABASE=Appareo Systems, LLC + +OUI:9C69B44* + ID_OUI_FROM_DATABASE=Globalcom Engineering SPA + +OUI:9C69B45* + ID_OUI_FROM_DATABASE=Elesta GmbH + +OUI:9C69B46* + ID_OUI_FROM_DATABASE=Shenzhen jiahua zhongli technology co.LTD + +OUI:9C69B47* + ID_OUI_FROM_DATABASE=PCI Limited + +OUI:9C69B48* + ID_OUI_FROM_DATABASE=Skydock do Brasil Ltda + +OUI:9C69B49* + ID_OUI_FROM_DATABASE=Teptron AB + +OUI:9C69B4A* + ID_OUI_FROM_DATABASE=BEIJING PICOHOOD TECHNOLOGY CO.,LTD + +OUI:9C69B4B* + ID_OUI_FROM_DATABASE=Toughdog Security Systems + +OUI:9C69B4C* + ID_OUI_FROM_DATABASE=Guangdong Hanwei intergration Co.,Ltd + +OUI:9C69B4D* + ID_OUI_FROM_DATABASE=Intellect module LLC + +OUI:9C69B4E* + ID_OUI_FROM_DATABASE=NINGBO SHEN LINK COMMUNICATION TECHNOLOGY CO., LTD + +OUI:9C69D1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9C6ABE* + ID_OUI_FROM_DATABASE=QEES ApS. + +OUI:9C6B72* + ID_OUI_FROM_DATABASE=Realme Chongqing MobileTelecommunications Corp Ltd + +OUI:9C6C15* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:9C6F52* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:9C713A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9C741A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9C7514* + ID_OUI_FROM_DATABASE=Wildix srl + +OUI:9C77AA* + ID_OUI_FROM_DATABASE=NADASNV + +OUI:9C79AC* + ID_OUI_FROM_DATABASE=Suntec Software(Shanghai) Co., Ltd. + +OUI:9C7A03* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:9C7BD2* + ID_OUI_FROM_DATABASE=NEOLAB Convergence + +OUI:9C7BEF* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:9C7DA3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9C7F57* + ID_OUI_FROM_DATABASE=UNIC Memory Technology Co Ltd + +OUI:9C807D* + ID_OUI_FROM_DATABASE=SYSCABLE Korea Inc. + +OUI:9C80DF* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:9C8275* + ID_OUI_FROM_DATABASE=Yichip Microelectronics (Hangzhou) Co.,Ltd + +OUI:9C83BF* + ID_OUI_FROM_DATABASE=PRO-VISION, Inc. + +OUI:9C84BF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9C86DA* + ID_OUI_FROM_DATABASE=Phoenix Geophysics Ltd. + +OUI:9C8888* + ID_OUI_FROM_DATABASE=Simac Techniek NV + +OUI:9C88AD* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:9C8ACB* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:9C8BA0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9C8BF1* + ID_OUI_FROM_DATABASE=The Warehouse Limited + +OUI:9C8C6E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9C8CD8* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:9C8D1A* + ID_OUI_FROM_DATABASE=INTEG process group inc + +OUI:9C8D7C* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:9C8DD3* + ID_OUI_FROM_DATABASE=Leonton Technologies + +OUI:9C8E99* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:9C8ECD* + ID_OUI_FROM_DATABASE=Amcrest Technologies + +OUI:9C8EDC* + ID_OUI_FROM_DATABASE=Teracom Limited + +OUI:9C934E* + ID_OUI_FROM_DATABASE=Xerox Corporation + +OUI:9C93B0* + ID_OUI_FROM_DATABASE=Megatronix (Beijing) Technology Co., Ltd. + +OUI:9C93E4* + ID_OUI_FROM_DATABASE=Private + +OUI:9C95F8* + ID_OUI_FROM_DATABASE=SmartDoor Systems, LLC + +OUI:9C9726* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:9C9789* + ID_OUI_FROM_DATABASE=1MORE + +OUI:9C9811* + ID_OUI_FROM_DATABASE=Guangzhou Sunrise Electronics Development Co., Ltd + +OUI:9C99A0* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:9C99CD* + ID_OUI_FROM_DATABASE=Voippartners + +OUI:9C9C1D* + ID_OUI_FROM_DATABASE=Starkey Labs Inc. + +OUI:9C9C40* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:9C9D5D* + ID_OUI_FROM_DATABASE=Raden Inc + +OUI:9CA10A* + ID_OUI_FROM_DATABASE=SCLE SFE + +OUI:9CA134* + ID_OUI_FROM_DATABASE=Nike, Inc. + +OUI:9CA3A9* + ID_OUI_FROM_DATABASE=Guangzhou Juan Optical and Electronical Tech Joint Stock Co., Ltd + +OUI:9CA3BA* + ID_OUI_FROM_DATABASE=SAKURA Internet Inc. + +OUI:9CA513* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9CA525* + ID_OUI_FROM_DATABASE=Shandong USR IOT Technology Limited + +OUI:9CA577* + ID_OUI_FROM_DATABASE=Osorno Enterprises Inc. + +OUI:9CA5C0* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:9CA615* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:9CA69D* + ID_OUI_FROM_DATABASE=Whaley Technology Co.Ltd + +OUI:9CA9E4* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:9CAA1B* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:9CAC6D* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. + +OUI:9CAD97* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:9CADEF* + ID_OUI_FROM_DATABASE=Obihai Technology, Inc. + +OUI:9CAED3* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:9CAF6F* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:9CAFCA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:9CB008* + ID_OUI_FROM_DATABASE=Ubiquitous Computing Technology Corporation + +OUI:9CB206* + ID_OUI_FROM_DATABASE=PROCENTEC + +OUI:9CB2B2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9CB654* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:9CB6D0* + ID_OUI_FROM_DATABASE=Rivet Networks + +OUI:9CB70D* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:9CB793* + ID_OUI_FROM_DATABASE=Creatcomm Technology Inc. + +OUI:9CBB98* + ID_OUI_FROM_DATABASE=Shen Zhen RND Electronic Co.,LTD + +OUI:9CBD9D* + ID_OUI_FROM_DATABASE=SkyDisk, Inc. + +OUI:9CBEE0* + ID_OUI_FROM_DATABASE=Biosoundlab Co., Ltd. + +OUI:9CC077* + ID_OUI_FROM_DATABASE=PrintCounts, LLC + +OUI:9CC0D2* + ID_OUI_FROM_DATABASE=Conductix-Wampfler GmbH + +OUI:9CC172* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9CC7A6* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:9CC7D1* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:9CC8AE* + ID_OUI_FROM_DATABASE=Becton, Dickinson and Company + +OUI:9CC8FC* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:9CC950* + ID_OUI_FROM_DATABASE=Baumer Holding + +OUI:9CC9EB* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:9CCAD9* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:9CCC83* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:9CCD82* + ID_OUI_FROM_DATABASE=CHENG UEI PRECISION INDUSTRY CO.,LTD + +OUI:9CD21E* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:9CD24B* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:9CD332* + ID_OUI_FROM_DATABASE=PLC Technology Ltd + +OUI:9CD35B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9CD36D* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:9CD48B* + ID_OUI_FROM_DATABASE=Innolux Technology Europe BV + +OUI:9CD643* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:9CD917* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:9CD9CB* + ID_OUI_FROM_DATABASE=Lesira Manufacturing Pty Ltd + +OUI:9CDA3E* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:9CDB07* + ID_OUI_FROM_DATABASE=Thum+Mahr GmbH + +OUI:9CDC71* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:9CDD1F* + ID_OUI_FROM_DATABASE=Intelligent Steward Co.,Ltd + +OUI:9CDF03* + ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH + +OUI:9CDFB1* + ID_OUI_FROM_DATABASE=Shenzhen Crave Communication Co., LTD + +OUI:9CE063* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9CE10E* + ID_OUI_FROM_DATABASE=NCTech Ltd + +OUI:9CE176* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:9CE1D6* + ID_OUI_FROM_DATABASE=Junger Audio-Studiotechnik GmbH + +OUI:9CE230* + ID_OUI_FROM_DATABASE=JULONG CO,.LTD. + +OUI:9CE33F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9CE374* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:9CE635* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:9CE65E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9CE6E7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:9CE7BD* + ID_OUI_FROM_DATABASE=Winduskorea co., Ltd + +OUI:9CE82B* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:9CE895* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:9CE91C* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:9CE951* + ID_OUI_FROM_DATABASE=Shenzhen Sang Fei Consumer Communications Ltd., Co. + +OUI:9CEBE8* + ID_OUI_FROM_DATABASE=BizLink (Kunshan) Co.,Ltd + +OUI:9CEFD5* + ID_OUI_FROM_DATABASE=Panda Wireless, Inc. + +OUI:9CF029* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:9CF387* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9CF48E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9CF531* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:9CF61A* + ID_OUI_FROM_DATABASE=UTC Fire and Security + +OUI:9CF67D* + ID_OUI_FROM_DATABASE=Ricardo Prague, s.r.o. + +OUI:9CF6DD0* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:9CF6DD1* + ID_OUI_FROM_DATABASE=Ithor IT Co.,Ltd. + +OUI:9CF6DD2* + ID_OUI_FROM_DATABASE=Beijing Sifang Automation Co., Ltd. + +OUI:9CF6DD3* + ID_OUI_FROM_DATABASE=RYEEX Technology Co.,Ltd. + +OUI:9CF6DD4* + ID_OUI_FROM_DATABASE=Capital Engineering & Research Incorporation Ltd. + +OUI:9CF6DD5* + ID_OUI_FROM_DATABASE=b8ta Inc. + +OUI:9CF6DD6* + ID_OUI_FROM_DATABASE=Shenzhen Xtooltech Co., Ltd + +OUI:9CF6DD7* + ID_OUI_FROM_DATABASE=KXT Technology Co., Ltd. + +OUI:9CF6DD8* + ID_OUI_FROM_DATABASE=Savari Inc + +OUI:9CF6DD9* + ID_OUI_FROM_DATABASE=CAMA(Luoyang)Electronics Co.,Ltd + +OUI:9CF6DDA* + ID_OUI_FROM_DATABASE=AVI Pty Ltd + +OUI:9CF6DDB* + ID_OUI_FROM_DATABASE=Guangzhou LANGO Electronics Technology Co., Ltd. + +OUI:9CF6DDC* + ID_OUI_FROM_DATABASE=Lighting New Energy Technology Co., Ltd. + +OUI:9CF6DDD* + ID_OUI_FROM_DATABASE=Foshan Synwit Technology Co.,Ltd. + +OUI:9CF6DDE* + ID_OUI_FROM_DATABASE=Shanxi ZhuoZhi fei High Electronic Technology Co. Ltd. + +OUI:9CF8DB* + ID_OUI_FROM_DATABASE=shenzhen eyunmei technology co,.ltd + +OUI:9CF938* + ID_OUI_FROM_DATABASE=AREVA NP GmbH + +OUI:9CFBD5* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:9CFBF1* + ID_OUI_FROM_DATABASE=MESOMATIC GmbH & Co.KG + +OUI:9CFC01* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:9CFCD1* + ID_OUI_FROM_DATABASE=Aetheris Technology (Shanghai) Co., Ltd. + +OUI:9CFCE8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:9CFEA1* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:9CFFBE* + ID_OUI_FROM_DATABASE=OTSL Inc. + +OUI:9CFFC2* + ID_OUI_FROM_DATABASE=AVI Systems GmbH + +OUI:A002DC* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:A00363* + ID_OUI_FROM_DATABASE=Robert Bosch Healthcare GmbH + +OUI:A0043E* + ID_OUI_FROM_DATABASE=Parker Hannifin Manufacturing Germany GmbH & Co. KG + +OUI:A00460* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:A00627* + ID_OUI_FROM_DATABASE=NEXPA System + +OUI:A00798* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A007B6* + ID_OUI_FROM_DATABASE=Advanced Technical Support, Inc. + +OUI:A0086F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A0094C* + ID_OUI_FROM_DATABASE=CenturyLink + +OUI:A009ED* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:A00ABF* + ID_OUI_FROM_DATABASE=Wieson Technologies Co., Ltd. + +OUI:A00BBA* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:A00CA1* + ID_OUI_FROM_DATABASE=SKTB SKiT + +OUI:A01081* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A01290* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:A012DB* + ID_OUI_FROM_DATABASE=TABUCHI ELECTRIC CO.,LTD + +OUI:A0133B* + ID_OUI_FROM_DATABASE=HiTi Digital, Inc. + +OUI:A013CB* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:A0143D* + ID_OUI_FROM_DATABASE=PARROT SA + +OUI:A0165C* + ID_OUI_FROM_DATABASE=Triteka LTD + +OUI:A01828* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A01859* + ID_OUI_FROM_DATABASE=Shenzhen Yidashi Electronics Co Ltd + +OUI:A01917* + ID_OUI_FROM_DATABASE=Bertel S.p.a. + +OUI:A019B20* + ID_OUI_FROM_DATABASE=Vast Production Services + +OUI:A019B21* + ID_OUI_FROM_DATABASE=El Sewedy Electrometer Egypt S.A.E. + +OUI:A019B22* + ID_OUI_FROM_DATABASE=Beijing Deephi Intelligent Technology Co., Ltd + +OUI:A019B23* + ID_OUI_FROM_DATABASE=Power Diagnostic Service Co., LTD. + +OUI:A019B24* + ID_OUI_FROM_DATABASE=Osatec + +OUI:A019B25* + ID_OUI_FROM_DATABASE=SZBROAD TECHNOLOGY (HK) CO.,LTMITED + +OUI:A019B26* + ID_OUI_FROM_DATABASE=GfG mbH + +OUI:A019B27* + ID_OUI_FROM_DATABASE=ARIMA Communications Corp. + +OUI:A019B28* + ID_OUI_FROM_DATABASE=MIS Industrie Systeme GmbH & Co. KG + +OUI:A019B29* + ID_OUI_FROM_DATABASE=Lon Microsystems Inc. + +OUI:A019B2A* + ID_OUI_FROM_DATABASE=Adomi + +OUI:A019B2B* + ID_OUI_FROM_DATABASE=HangZhou iMagic Technology Co., Ltd + +OUI:A019B2C* + ID_OUI_FROM_DATABASE=LDA Technologies + +OUI:A019B2D* + ID_OUI_FROM_DATABASE=RYD Electronic Technology Co.,Ltd. + +OUI:A019B2E* + ID_OUI_FROM_DATABASE=Ahgora Sistemas SA + +OUI:A01B29* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:A01C05* + ID_OUI_FROM_DATABASE=NIMAX TELECOM CO.,LTD. + +OUI:A01C8D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A01D48* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:A01E0B* + ID_OUI_FROM_DATABASE=MINIX Technology Limited + +OUI:A020A6* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:A02195* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A021B7* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:A0224E0* + ID_OUI_FROM_DATABASE=Kyung In Electronics + +OUI:A0224E1* + ID_OUI_FROM_DATABASE=rNET Controls + +OUI:A0224E2* + ID_OUI_FROM_DATABASE=Closed Joint-Stock Company NORSI-TRANS + +OUI:A0224E3* + ID_OUI_FROM_DATABASE=ProPhotonix + +OUI:A0224E4* + ID_OUI_FROM_DATABASE=TMGcore LLC + +OUI:A0224E5* + ID_OUI_FROM_DATABASE=Zhuhai Cheer Technology Co., LTD. + +OUI:A0224E6* + ID_OUI_FROM_DATABASE=MESIT asd, s.r.o. + +OUI:A0224E7* + ID_OUI_FROM_DATABASE=Applied Information, Inc. + +OUI:A0224E8* + ID_OUI_FROM_DATABASE=EISST International Ltd + +OUI:A0224E9* + ID_OUI_FROM_DATABASE=Delta Tau Data Systems, Inc. + +OUI:A0224EA* + ID_OUI_FROM_DATABASE=IST ElektronikgesmbH + +OUI:A0224EB* + ID_OUI_FROM_DATABASE=All Inspire Health Inc. + +OUI:A0224EC* + ID_OUI_FROM_DATABASE=Standartoptic, Limited Liability Company + +OUI:A0224ED* + ID_OUI_FROM_DATABASE=Digifocus Technology Inc. + +OUI:A0224EE* + ID_OUI_FROM_DATABASE=Hunan Youmei Science&Technology Development Co.,Ltd. + +OUI:A0231B* + ID_OUI_FROM_DATABASE=TeleComp R&D Corp. + +OUI:A0239F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A028330* + ID_OUI_FROM_DATABASE=GERSYS GmbH + +OUI:A028331* + ID_OUI_FROM_DATABASE=Ordercube GmbH + +OUI:A028332* + ID_OUI_FROM_DATABASE=Shanghai Nohmi Secom Fire Protection Equipment Co.,Ltd. + +OUI:A028333* + ID_OUI_FROM_DATABASE=SHANGHAI XUNTAI INFORMATION TECHNOLOGY CO.,LTD. + +OUI:A028334* + ID_OUI_FROM_DATABASE=Firm INFORMTEST Ltd. + +OUI:A028335* + ID_OUI_FROM_DATABASE=JGR Optics Inc + +OUI:A028336* + ID_OUI_FROM_DATABASE=Xiamen Caimore Communication Technology Co.,Ltd. + +OUI:A028337* + ID_OUI_FROM_DATABASE=Kryptus Information Security S/A + +OUI:A028338* + ID_OUI_FROM_DATABASE=HZHY TECHNOLOGY + +OUI:A028339* + ID_OUI_FROM_DATABASE=IMESHX CORPORATION LIMITED + +OUI:A02833A* + ID_OUI_FROM_DATABASE=Medical Evolution Kft + +OUI:A02833B* + ID_OUI_FROM_DATABASE=FlexLink AB + +OUI:A02833C* + ID_OUI_FROM_DATABASE=Kalray S.A. + +OUI:A02833D* + ID_OUI_FROM_DATABASE=Audix + +OUI:A02833E* + ID_OUI_FROM_DATABASE=Precision Planting, LLC. + +OUI:A028ED* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:A02BB8* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:A02C36* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:A02D13* + ID_OUI_FROM_DATABASE=AirTies Wireless Networks + +OUI:A02EF3* + ID_OUI_FROM_DATABASE=United Integrated Services Co., Led. + +OUI:A03299* + ID_OUI_FROM_DATABASE=Lenovo (Beijing) Co., Ltd. + +OUI:A0341B* + ID_OUI_FROM_DATABASE=Adero Inc + +OUI:A0369F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A036F0* + ID_OUI_FROM_DATABASE=Comprehensive Power + +OUI:A036FA* + ID_OUI_FROM_DATABASE=Ettus Research LLC + +OUI:A038F8* + ID_OUI_FROM_DATABASE=OURA Health Oy + +OUI:A039EE* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:A039F7* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:A03A75* + ID_OUI_FROM_DATABASE=PSS Belgium N.V. + +OUI:A03B1B* + ID_OUI_FROM_DATABASE=Inspire Tech + +OUI:A03BE3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A03C31* + ID_OUI_FROM_DATABASE=Shenzhen Belon Technology CO.,LTD + +OUI:A03D6F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A03E6B0* + ID_OUI_FROM_DATABASE=s&t embedded GmbH + +OUI:A03E6B1* + ID_OUI_FROM_DATABASE=Business Support Consultant Co.,Ltd + +OUI:A03E6B2* + ID_OUI_FROM_DATABASE=Videx Electronics S.p.A. + +OUI:A03E6B3* + ID_OUI_FROM_DATABASE=iLoda Solutions Limited + +OUI:A03E6B4* + ID_OUI_FROM_DATABASE=Shenzhen Nufilo Inc. + +OUI:A03E6B5* + ID_OUI_FROM_DATABASE=Friday Lab, UAB + +OUI:A03E6B6* + ID_OUI_FROM_DATABASE=Wuhan Rui Ying Tong Network Technology Co., Ltd(China) + +OUI:A03E6B7* + ID_OUI_FROM_DATABASE=SinoGrid Software Systems Inc. + +OUI:A03E6B8* + ID_OUI_FROM_DATABASE=718th Research Institute of CSIC + +OUI:A03E6B9* + ID_OUI_FROM_DATABASE=Incogniteam Ltd. + +OUI:A03E6BA* + ID_OUI_FROM_DATABASE=Shenzhen Neostra Technology Co.Ltd + +OUI:A03E6BB* + ID_OUI_FROM_DATABASE=KoCoS Messtechnik AG + +OUI:A03E6BC* + ID_OUI_FROM_DATABASE=Qunar.com + +OUI:A03E6BD* + ID_OUI_FROM_DATABASE=Jining SmartCity Infotech Co.Ltd. + +OUI:A03E6BE* + ID_OUI_FROM_DATABASE=Nanjing zhanyi software technology co., LTD + +OUI:A03E6BF* + ID_OUI_FROM_DATABASE=Private + +OUI:A04025* + ID_OUI_FROM_DATABASE=Actioncable, Inc. + +OUI:A04041* + ID_OUI_FROM_DATABASE=SAMWONFA Co.,Ltd. + +OUI:A040A0* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:A04147* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:A0415E* + ID_OUI_FROM_DATABASE=Opsens Solution Inc. + +OUI:A041A7* + ID_OUI_FROM_DATABASE=NL Ministry of Defense + +OUI:A0423F* + ID_OUI_FROM_DATABASE=Tyan Computer Corp + +OUI:A04246* + ID_OUI_FROM_DATABASE=IT Telecom Co., Ltd. + +OUI:A043B0* + ID_OUI_FROM_DATABASE=Hangzhou BroadLink Technology Co.,Ltd + +OUI:A043DB* + ID_OUI_FROM_DATABASE=Sitael S.p.A. + +OUI:A047D7* + ID_OUI_FROM_DATABASE=Best IT World (India) Pvt Ltd + +OUI:A0481C* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:A04C5B* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:A04CC1* + ID_OUI_FROM_DATABASE=Helixtech Corp. + +OUI:A04E01* + ID_OUI_FROM_DATABASE=CENTRAL ENGINEERING co.,ltd. + +OUI:A04E04* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:A04EA7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A04F85* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:A04FD4* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:A0510B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A051C6* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:A0554F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A055DE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A056B2* + ID_OUI_FROM_DATABASE=Harman/Becker Automotive Systems GmbH + +OUI:A056F3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A057E3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A0593A* + ID_OUI_FROM_DATABASE=V.D.S. Video Display Systems srl + +OUI:A05AA4* + ID_OUI_FROM_DATABASE=Grand Products Nevada, Inc. + +OUI:A05B21* + ID_OUI_FROM_DATABASE=ENVINET GmbH + +OUI:A05DC1* + ID_OUI_FROM_DATABASE=TMCT Co., LTD. + +OUI:A05DE7* + ID_OUI_FROM_DATABASE=DIRECTV, Inc. + +OUI:A05E6B* + ID_OUI_FROM_DATABASE=MELPER Co., Ltd. + +OUI:A06090* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A06391* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:A0648F* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:A06518* + ID_OUI_FROM_DATABASE=VNPT TECHNOLOGY + +OUI:A06610* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:A067BE* + ID_OUI_FROM_DATABASE=Sicon srl + +OUI:A0687E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A06986* + ID_OUI_FROM_DATABASE=Wellav Technologies Ltd + +OUI:A06A00* + ID_OUI_FROM_DATABASE=Verilink Corporation + +OUI:A06A44* + ID_OUI_FROM_DATABASE=Vizio, Inc + +OUI:A06CEC* + ID_OUI_FROM_DATABASE=RIM + +OUI:A06D09* + ID_OUI_FROM_DATABASE=Intelcan Technosystems Inc. + +OUI:A06E50* + ID_OUI_FROM_DATABASE=Nanotek Elektronik Sistemler Ltd. Sti. + +OUI:A06FAA* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:A07099* + ID_OUI_FROM_DATABASE=Beijing Huacan Electronics Co., Ltd + +OUI:A071A9* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:A0722C* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:A072E4* + ID_OUI_FROM_DATABASE=NJ SYSTEM CO.,LTD + +OUI:A07332* + ID_OUI_FROM_DATABASE=Cashmaster International Limited + +OUI:A073FC* + ID_OUI_FROM_DATABASE=Rancore Technologies Private Limited + +OUI:A07591* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A075EA* + ID_OUI_FROM_DATABASE=BoxLock, Inc. + +OUI:A07771* + ID_OUI_FROM_DATABASE=Vialis BV + +OUI:A078BA* + ID_OUI_FROM_DATABASE=Pantech Co., Ltd. + +OUI:A0821F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A082AC* + ID_OUI_FROM_DATABASE=Linear DMS Solutions Sdn. Bhd. + +OUI:A082C7* + ID_OUI_FROM_DATABASE=P.T.I Co.,LTD + +OUI:A084CB* + ID_OUI_FROM_DATABASE=SonicSensory,Inc. + +OUI:A0861D* + ID_OUI_FROM_DATABASE=Chengdu Fuhuaxin Technology co.,Ltd + +OUI:A086C6* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:A086EC* + ID_OUI_FROM_DATABASE=SAEHAN HITEC Co., Ltd + +OUI:A08869* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A088B4* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A089E4* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:A08A87* + ID_OUI_FROM_DATABASE=HuiZhou KaiYue Electronic Co.,Ltd + +OUI:A08C15* + ID_OUI_FROM_DATABASE=Gerhard D. Wempe KG + +OUI:A08C9B* + ID_OUI_FROM_DATABASE=Xtreme Technologies Corp + +OUI:A08CF8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A08CFD* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:A08D16* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A08E78* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:A090DE* + ID_OUI_FROM_DATABASE=VEEDIMS,LLC + +OUI:A09169* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:A091A2* + ID_OUI_FROM_DATABASE=OnePlus Electronics (Shenzhen) Co., Ltd. + +OUI:A091C8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:A09347* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:A09351* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A0946A* + ID_OUI_FROM_DATABASE=Shenzhen XGTEC Technology Co,.Ltd. + +OUI:A0950C* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:A09805* + ID_OUI_FROM_DATABASE=OpenVox Communication Co Ltd + +OUI:A098ED* + ID_OUI_FROM_DATABASE=Shandong Intelligent Optical Communication Development Co., Ltd. + +OUI:A0999B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A09A5A* + ID_OUI_FROM_DATABASE=Time Domain + +OUI:A09BBD* + ID_OUI_FROM_DATABASE=Total Aviation Solutions Pty Ltd + +OUI:A09D86* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:A09D91* + ID_OUI_FROM_DATABASE=SoundBridge + +OUI:A09DC1* + ID_OUI_FROM_DATABASE=China Dragon Technology Limited + +OUI:A09E1A* + ID_OUI_FROM_DATABASE=Polar Electro Oy + +OUI:A0A130* + ID_OUI_FROM_DATABASE=DLI Taiwan Branch office + +OUI:A0A23C* + ID_OUI_FROM_DATABASE=GPMS + +OUI:A0A33B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A0A3B8* + ID_OUI_FROM_DATABASE=WISCLOUD + +OUI:A0A3E2* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:A0A4C5* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A0A65C* + ID_OUI_FROM_DATABASE=Supercomputing Systems AG + +OUI:A0A763* + ID_OUI_FROM_DATABASE=Polytron Vertrieb GmbH + +OUI:A0A8CD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A0AAFD* + ID_OUI_FROM_DATABASE=EraThink Technologies Corp. + +OUI:A0AB1B* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:A0AB51* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:A0AC69* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A0ADA1* + ID_OUI_FROM_DATABASE=JMR Electronics, Inc + +OUI:A0AFBD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A0B045* + ID_OUI_FROM_DATABASE=Halong Mining + +OUI:A0B100* + ID_OUI_FROM_DATABASE=ShenZhen Cando Electronics Co.,Ltd + +OUI:A0B3CC* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:A0B437* + ID_OUI_FROM_DATABASE=GD Mission Systems + +OUI:A0B439* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A0B4A5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A0B549* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:A0B5DA* + ID_OUI_FROM_DATABASE=HongKong THTF Co., Ltd + +OUI:A0B662* + ID_OUI_FROM_DATABASE=Acutvista Innovation Co., Ltd. + +OUI:A0B8F8* + ID_OUI_FROM_DATABASE=Amgen U.S.A. Inc. + +OUI:A0B9ED* + ID_OUI_FROM_DATABASE=Skytap + +OUI:A0BAB8* + ID_OUI_FROM_DATABASE=Pixon Imaging + +OUI:A0BB3E0* + ID_OUI_FROM_DATABASE=Link Labs + +OUI:A0BB3E1* + ID_OUI_FROM_DATABASE=IVision Electronics Co.,Ltd + +OUI:A0BB3E2* + ID_OUI_FROM_DATABASE=DirectOut GmbH + +OUI:A0BB3E3* + ID_OUI_FROM_DATABASE=WiteRiver Technology LLC + +OUI:A0BB3E4* + ID_OUI_FROM_DATABASE=COMSYS Communications Systems Service GmbH + +OUI:A0BB3E5* + ID_OUI_FROM_DATABASE=ManTech International Corporation + +OUI:A0BB3E6* + ID_OUI_FROM_DATABASE=Xiamen Kehua Hengsheng Co.,Ltd + +OUI:A0BB3E7* + ID_OUI_FROM_DATABASE=SIMTEC Elektronik GmbH + +OUI:A0BB3E8* + ID_OUI_FROM_DATABASE=AutarcTech GmbH + +OUI:A0BB3E9* + ID_OUI_FROM_DATABASE=Sandal Plc + +OUI:A0BB3EA* + ID_OUI_FROM_DATABASE=Filo SRL + +OUI:A0BB3EB* + ID_OUI_FROM_DATABASE=Beijing Techshino Technology Co., Ltd. + +OUI:A0BB3EC* + ID_OUI_FROM_DATABASE=Ewig Industries Macao Commercial Offshore Ltd + +OUI:A0BB3ED* + ID_OUI_FROM_DATABASE=Shenzhen Talent Technology company limited + +OUI:A0BB3EE* + ID_OUI_FROM_DATABASE=Messtechnik Sachs GmbH + +OUI:A0BB3EF* + ID_OUI_FROM_DATABASE=Private + +OUI:A0BD1D* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:A0BDCD* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:A0BF50* + ID_OUI_FROM_DATABASE=S.C. ADD-PRODUCTION S.R.L. + +OUI:A0BFA5* + ID_OUI_FROM_DATABASE=CORESYS + +OUI:A0C2DE* + ID_OUI_FROM_DATABASE=Costar Video Systems + +OUI:A0C3DE* + ID_OUI_FROM_DATABASE=Triton Electronic Systems Ltd. + +OUI:A0C4A5* + ID_OUI_FROM_DATABASE=SYGN HOUSE CO.,LTD + +OUI:A0C562* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A0C589* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A0C5F20* + ID_OUI_FROM_DATABASE=Quantlab Financial, LLC + +OUI:A0C5F21* + ID_OUI_FROM_DATABASE=KNS Group LLC (YADRO Company) + +OUI:A0C5F22* + ID_OUI_FROM_DATABASE=Speedgoat GmbH + +OUI:A0C5F23* + ID_OUI_FROM_DATABASE=Shenzhen Feima Robotics Technology Co.,Ltd + +OUI:A0C5F24* + ID_OUI_FROM_DATABASE=AiCare Corp. + +OUI:A0C5F25* + ID_OUI_FROM_DATABASE=Spacepath Communications Ltd + +OUI:A0C5F26* + ID_OUI_FROM_DATABASE=ShenZhen JuWangShi Tech + +OUI:A0C5F27* + ID_OUI_FROM_DATABASE=Viettronimex JSC + +OUI:A0C5F28* + ID_OUI_FROM_DATABASE=CoolR Group Inc + +OUI:A0C5F29* + ID_OUI_FROM_DATABASE=Impulse Networks Pte Ltd + +OUI:A0C5F2A* + ID_OUI_FROM_DATABASE=Serious Integrated, Inc. + +OUI:A0C5F2B* + ID_OUI_FROM_DATABASE=Oray.com co., LTD. + +OUI:A0C5F2C* + ID_OUI_FROM_DATABASE=Glooko inc + +OUI:A0C5F2D* + ID_OUI_FROM_DATABASE=UnaliWear, Inc. + +OUI:A0C5F2E* + ID_OUI_FROM_DATABASE=Synapsys Solutions Ltd. + +OUI:A0C6EC* + ID_OUI_FROM_DATABASE=ShenZhen ANYK Technology Co.,LTD + +OUI:A0C9A0* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:A0CBFD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A0CC2B* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:A0CEC8* + ID_OUI_FROM_DATABASE=CE LINK LIMITED + +OUI:A0CF5B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A0D12A* + ID_OUI_FROM_DATABASE=AXPRO Technology Inc. + +OUI:A0D37A* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A0D385* + ID_OUI_FROM_DATABASE=AUMA Riester GmbH & Co. KG + +OUI:A0D3C1* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:A0D635* + ID_OUI_FROM_DATABASE=WBS Technology + +OUI:A0D795* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A0D807* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:A0D86F* + ID_OUI_FROM_DATABASE=ARGO AI, LLC + +OUI:A0DA92* + ID_OUI_FROM_DATABASE=Nanjing Glarun Atten Technology Co. Ltd. + +OUI:A0DC04* + ID_OUI_FROM_DATABASE=Becker-Antriebe GmbH + +OUI:A0DD97* + ID_OUI_FROM_DATABASE=PolarLink Technologies, Ltd + +OUI:A0DDE5* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:A0DE05* + ID_OUI_FROM_DATABASE=JSC Irbis-T + +OUI:A0DF15* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A0E0AF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A0E201* + ID_OUI_FROM_DATABASE=AVTrace Ltd.(China) + +OUI:A0E25A* + ID_OUI_FROM_DATABASE=Amicus SK, s.r.o. + +OUI:A0E295* + ID_OUI_FROM_DATABASE=DAT System Co.,Ltd + +OUI:A0E453* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:A0E4CB* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:A0E534* + ID_OUI_FROM_DATABASE=Stratec Biomedical AG + +OUI:A0E5E9* + ID_OUI_FROM_DATABASE=enimai Inc + +OUI:A0E617* + ID_OUI_FROM_DATABASE=MATIS + +OUI:A0E6F8* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:A0E9DB* + ID_OUI_FROM_DATABASE=Ningbo FreeWings Technologies Co.,Ltd + +OUI:A0EB76* + ID_OUI_FROM_DATABASE=AirCUVE Inc. + +OUI:A0EC80* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:A0ECF9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A0EDCD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A0EF84* + ID_OUI_FROM_DATABASE=Seine Image Int'l Co., Ltd + +OUI:A0F217* + ID_OUI_FROM_DATABASE=GE Medical System(China) Co., Ltd. + +OUI:A0F3C1* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:A0F3E4* + ID_OUI_FROM_DATABASE=Alcatel-Lucent IPD + +OUI:A0F419* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:A0F450* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:A0F459* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:A0F479* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A0F6FD* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:A0F849* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A0F895* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:A0F9B7* + ID_OUI_FROM_DATABASE=Ademco Smart Homes Technology(Tianjin)Co.,Ltd. + +OUI:A0F9E0* + ID_OUI_FROM_DATABASE=VIVATEL COMPANY LIMITED + +OUI:A0FC6E* + ID_OUI_FROM_DATABASE=Telegrafia a.s. + +OUI:A0FE61* + ID_OUI_FROM_DATABASE=Vivint Wireless Inc. + +OUI:A0FE91* + ID_OUI_FROM_DATABASE=AVAT Automation GmbH + +OUI:A400E2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A40130* + ID_OUI_FROM_DATABASE=ABIsystems Co., LTD + +OUI:A402B9* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A40450* + ID_OUI_FROM_DATABASE=nFore Technology Inc. + +OUI:A4059E* + ID_OUI_FROM_DATABASE=STA Infinity LLP + +OUI:A407B6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A40801* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:A408EA* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:A408F5* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:A409CB* + ID_OUI_FROM_DATABASE=Alfred Kaercher GmbH & Co KG + +OUI:A40BED* + ID_OUI_FROM_DATABASE=Carry Technology Co.,Ltd + +OUI:A40C66* + ID_OUI_FROM_DATABASE=Shenzhen Colorful Yugong Technology and Development Co., Ltd. + +OUI:A40CC3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A40DBC* + ID_OUI_FROM_DATABASE=Xiamen Intretech Inc. + +OUI:A40E2B* + ID_OUI_FROM_DATABASE=Facebook Inc + +OUI:A41115* + ID_OUI_FROM_DATABASE=Robert Bosch Engineering and Business Solutions pvt. Ltd. + +OUI:A41162* + ID_OUI_FROM_DATABASE=Arlo Technology + +OUI:A411630* + ID_OUI_FROM_DATABASE=Adetel Equipment + +OUI:A411631* + ID_OUI_FROM_DATABASE=INTER CONTROL Hermann Köhler Elektrik GmbH & Co.KG + +OUI:A411632* + ID_OUI_FROM_DATABASE=Allgo Tech. (Beijing) Co.,Ltd + +OUI:A411633* + ID_OUI_FROM_DATABASE=Pax + +OUI:A411634* + ID_OUI_FROM_DATABASE=AlterG, Inc. + +OUI:A411635* + ID_OUI_FROM_DATABASE=Carbon, Inc. + +OUI:A411636* + ID_OUI_FROM_DATABASE=Beijing XiaoRui Technology Co., Ltd + +OUI:A411637* + ID_OUI_FROM_DATABASE=SHENZHEN YIWANJIA INFORMATION TECHNOLOGY CO.,LTD + +OUI:A411638* + ID_OUI_FROM_DATABASE=Dspread Technology (Beijing) Inc. + +OUI:A411639* + ID_OUI_FROM_DATABASE=accesso Technology Group + +OUI:A41163A* + ID_OUI_FROM_DATABASE=ISE GmbH + +OUI:A41163B* + ID_OUI_FROM_DATABASE=Moog Music Inc. + +OUI:A41163C* + ID_OUI_FROM_DATABASE=Viloc + +OUI:A41163D* + ID_OUI_FROM_DATABASE=SHENZHEN ZHISHI TECHNOLOGY CO., LTD. + +OUI:A41163E* + ID_OUI_FROM_DATABASE=tinylogics + +OUI:A41194* + ID_OUI_FROM_DATABASE=Lenovo + +OUI:A41232* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:A41242* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. + +OUI:A4134E* + ID_OUI_FROM_DATABASE=Luxul + +OUI:A41437* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:A41566* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:A41588* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A416E7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A41731* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:A41791* + ID_OUI_FROM_DATABASE=Shenzhen Decnta Technology Co.,LTD. + +OUI:A41875* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A41908* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:A41BC0* + ID_OUI_FROM_DATABASE=Fastec Imaging Corporation + +OUI:A41F72* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:A4218A* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:A42305* + ID_OUI_FROM_DATABASE=Open Networking Laboratory + +OUI:A424B3* + ID_OUI_FROM_DATABASE=FlatFrog Laboratories AB + +OUI:A424DD* + ID_OUI_FROM_DATABASE=Cambrionix Ltd + +OUI:A4251B* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:A42618* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:A42655* + ID_OUI_FROM_DATABASE=LTI Motion (Shanghai) Co., Ltd. + +OUI:A428B7* + ID_OUI_FROM_DATABASE=Yangtze Memory Technologies Co., Ltd. + +OUI:A42940* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:A42983* + ID_OUI_FROM_DATABASE=Boeing Defence Australia + +OUI:A42985* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:A429B7* + ID_OUI_FROM_DATABASE=bluesky + +OUI:A42B8C* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:A42BB0* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:A42C08* + ID_OUI_FROM_DATABASE=Masterwork Automodules + +OUI:A4307A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A43111* + ID_OUI_FROM_DATABASE=ZIV + +OUI:A43135* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A433D1* + ID_OUI_FROM_DATABASE=Fibrlink Communications Co.,Ltd. + +OUI:A433D7* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:A43412* + ID_OUI_FROM_DATABASE=Thales Alenia Space + +OUI:A434D9* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A434F1* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:A43523* + ID_OUI_FROM_DATABASE=Guangdong Donyan Network Technologies Co.,Ltd. + +OUI:A43831* + ID_OUI_FROM_DATABASE=RF elements s.r.o. + +OUI:A438CC* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:A438FC* + ID_OUI_FROM_DATABASE=Plastic Logic + +OUI:A43A69* + ID_OUI_FROM_DATABASE=Vers Inc + +OUI:A43BFA0* + ID_OUI_FROM_DATABASE=Chengdu Territory Technology Co.,Ltd + +OUI:A43BFA1* + ID_OUI_FROM_DATABASE=Beijing Uniwill Science and Technology Co,Ltd + +OUI:A43BFA2* + ID_OUI_FROM_DATABASE=Powell Industries + +OUI:A43BFA3* + ID_OUI_FROM_DATABASE=Circus World Displays Ltd + +OUI:A43BFA4* + ID_OUI_FROM_DATABASE=Maxon Australia + +OUI:A43BFA5* + ID_OUI_FROM_DATABASE=BOI Solutions + +OUI:A43BFA6* + ID_OUI_FROM_DATABASE=Recognition Systems LLC + +OUI:A43BFA7* + ID_OUI_FROM_DATABASE=Deatronic srl + +OUI:A43BFA8* + ID_OUI_FROM_DATABASE=Alpwise + +OUI:A43BFA9* + ID_OUI_FROM_DATABASE=SHEN ZHEN PASUN TECH CO.LTD. + +OUI:A43BFAA* + ID_OUI_FROM_DATABASE=Plus One Japan Ltd. + +OUI:A43BFAB* + ID_OUI_FROM_DATABASE=ALSTOM Strongwish (Shenzhen) Co., Ltd + +OUI:A43BFAC* + ID_OUI_FROM_DATABASE=SHANGHAI XIETONG TECHNOLOGY INC. + +OUI:A43BFAD* + ID_OUI_FROM_DATABASE=JSC “Component-ASU” + +OUI:A43BFAE* + ID_OUI_FROM_DATABASE=The Magstim Company Ltd. + +OUI:A43BFAF* + ID_OUI_FROM_DATABASE=Private + +OUI:A43D78* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:A43E51* + ID_OUI_FROM_DATABASE=ANOV FRANCE + +OUI:A43EA0* + ID_OUI_FROM_DATABASE=iComm HK LIMITED + +OUI:A44027* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:A444D1* + ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited + +OUI:A44519* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:A445CD* + ID_OUI_FROM_DATABASE=IoT Diagnostics + +OUI:A4466B* + ID_OUI_FROM_DATABASE=EOC Technology + +OUI:A446FA* + ID_OUI_FROM_DATABASE=AmTRAN Video Corporation + +OUI:A44AD3* + ID_OUI_FROM_DATABASE=ST Electronics(Shanghai) Co.,Ltd + +OUI:A44B15* + ID_OUI_FROM_DATABASE=Sun Cupid Technology (HK) LTD + +OUI:A44BD5* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:A44C11* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A44CC8* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:A44E2D* + ID_OUI_FROM_DATABASE=Adaptive Wireless Solutions, LLC + +OUI:A44E31* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A44F290* + ID_OUI_FROM_DATABASE=Dermalog Identification Systems GmbH + +OUI:A44F291* + ID_OUI_FROM_DATABASE=Olssen B.V. + +OUI:A44F292* + ID_OUI_FROM_DATABASE=LUCEOR + +OUI:A44F293* + ID_OUI_FROM_DATABASE=Comsel System Ltd + +OUI:A44F294* + ID_OUI_FROM_DATABASE=DGC Access AB + +OUI:A44F295* + ID_OUI_FROM_DATABASE=Shanghai KuanYu Industrial Network Equipment Co.,Ltd + +OUI:A44F296* + ID_OUI_FROM_DATABASE=Selektro Power Inc + +OUI:A44F297* + ID_OUI_FROM_DATABASE=Protean Payment + +OUI:A44F298* + ID_OUI_FROM_DATABASE=Innovations in Optics, Inc. + +OUI:A44F299* + ID_OUI_FROM_DATABASE=Certi Networks Sdn Bhd + +OUI:A44F29A* + ID_OUI_FROM_DATABASE=HTD + +OUI:A44F29B* + ID_OUI_FROM_DATABASE=GUANGDONG REAL-DESIGN INTELLIGENT TECHNOLOGY CO.,LTD + +OUI:A44F29C* + ID_OUI_FROM_DATABASE=Shenzhen Huadoo Bright Group Limitied + +OUI:A44F29D* + ID_OUI_FROM_DATABASE=HALLIBURTON + +OUI:A44F29E* + ID_OUI_FROM_DATABASE=Neotech Systems Pvt. Ltd. + +OUI:A44F29F* + ID_OUI_FROM_DATABASE=Private + +OUI:A45046* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:A45055* + ID_OUI_FROM_DATABASE=BUSWARE.DE + +OUI:A4516F* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:A4526F* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:A4530E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A45385* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:A45602* + ID_OUI_FROM_DATABASE=fenglian Technology Co.,Ltd. + +OUI:A4561B* + ID_OUI_FROM_DATABASE=MCOT Corporation + +OUI:A45630* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A456CC* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:A4580F0* + ID_OUI_FROM_DATABASE=INNOPRO + +OUI:A4580F1* + ID_OUI_FROM_DATABASE=Stone Lock Global, Inc. + +OUI:A4580F2* + ID_OUI_FROM_DATABASE=BLOKS. GmbH + +OUI:A4580F3* + ID_OUI_FROM_DATABASE=Engineered SA + +OUI:A4580F4* + ID_OUI_FROM_DATABASE=Shenzhen City billion Leiden science and Technology Co., Ltd. + +OUI:A4580F5* + ID_OUI_FROM_DATABASE=CoAsia Microelectronics Corp. + +OUI:A4580F6* + ID_OUI_FROM_DATABASE=Astro, Inc + +OUI:A4580F7* + ID_OUI_FROM_DATABASE=Changsha Tai Hui Network Technology Co.,Ltd + +OUI:A4580F8* + ID_OUI_FROM_DATABASE=AIR LIQUIDE MEDICAL SYSTEMS + +OUI:A4580F9* + ID_OUI_FROM_DATABASE=Ksenia Security srl + +OUI:A4580FA* + ID_OUI_FROM_DATABASE=GUANGZHOU OPTICAL BRIDGE COMMUNICATION EQUIPMENT CO.,LTD. + +OUI:A4580FB* + ID_OUI_FROM_DATABASE=ABB AB PGHV + +OUI:A4580FC* + ID_OUI_FROM_DATABASE=Homebeaver + +OUI:A4580FD* + ID_OUI_FROM_DATABASE=EYE IO, LLC + +OUI:A4580FE* + ID_OUI_FROM_DATABASE=Finetree Communications Inc + +OUI:A45A1C* + ID_OUI_FROM_DATABASE=smart-electronic GmbH + +OUI:A45C27* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:A45D36* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:A45DA1* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:A45E60* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A45F9B* + ID_OUI_FROM_DATABASE=Nexell + +OUI:A46011* + ID_OUI_FROM_DATABASE=Verifone + +OUI:A46032* + ID_OUI_FROM_DATABASE=MRV Communications (Networks) LTD + +OUI:A46191* + ID_OUI_FROM_DATABASE=NamJunSa + +OUI:A462DF* + ID_OUI_FROM_DATABASE=DS Global. Co., LTD + +OUI:A463A1* + ID_OUI_FROM_DATABASE=Inventus Power Eletronica do Brasil LTDA + +OUI:A46706* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A468BC* + ID_OUI_FROM_DATABASE=Private + +OUI:A46C2A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A46CC1* + ID_OUI_FROM_DATABASE=LTi REEnergy GmbH + +OUI:A46CF1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A46E79* + ID_OUI_FROM_DATABASE=DFT System Co.Ltd + +OUI:A470D6* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:A47174* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A47733* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:A47758* + ID_OUI_FROM_DATABASE=Ningbo Freewings Technologies Co.,Ltd + +OUI:A47760* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:A47886* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:A479E4* + ID_OUI_FROM_DATABASE=KLINFO Corp + +OUI:A47AA4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A47ACF* + ID_OUI_FROM_DATABASE=VIBICOM COMMUNICATIONS INC. + +OUI:A47B2C* + ID_OUI_FROM_DATABASE=Nokia + +OUI:A47B85* + ID_OUI_FROM_DATABASE=ULTIMEDIA Co Ltd, + +OUI:A47B9D* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:A47C14* + ID_OUI_FROM_DATABASE=ChargeStorm AB + +OUI:A47C1F* + ID_OUI_FROM_DATABASE=Cobham plc + +OUI:A47E39* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:A4817A* + ID_OUI_FROM_DATABASE=CIG SHANGHAI CO LTD + +OUI:A481EE* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:A48269* + ID_OUI_FROM_DATABASE=Datrium, Inc. + +OUI:A483E7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A48431* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A4856B* + ID_OUI_FROM_DATABASE=Q Electronics Ltd + +OUI:A486AE* + ID_OUI_FROM_DATABASE=Quectel Wireless Solutions + +OUI:A4895B* + ID_OUI_FROM_DATABASE=ARK INFOSOLUTIONS PVT LTD + +OUI:A48CC0* + ID_OUI_FROM_DATABASE=JLG Industries, Inc. + +OUI:A48CDB* + ID_OUI_FROM_DATABASE=Lenovo + +OUI:A48D3B* + ID_OUI_FROM_DATABASE=Vizio, Inc + +OUI:A48E0A* + ID_OUI_FROM_DATABASE=DeLaval International AB + +OUI:A49005* + ID_OUI_FROM_DATABASE=CHINA GREATWALL COMPUTER SHENZHEN CO.,LTD + +OUI:A491B1* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:A492CB* + ID_OUI_FROM_DATABASE=Nokia + +OUI:A4933F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A4934C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A49426* + ID_OUI_FROM_DATABASE=Elgama-Elektronika Ltd. + +OUI:A4975C* + ID_OUI_FROM_DATABASE=VTech Telecommunications Ltd. + +OUI:A497BB* + ID_OUI_FROM_DATABASE=Hitachi Industrial Equipment Systems Co.,Ltd + +OUI:A49813* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A49947* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A49981* + ID_OUI_FROM_DATABASE=FuJian Elite Power Tech CO.,LTD. + +OUI:A49A58* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A49B13* + ID_OUI_FROM_DATABASE=Digital Check + +OUI:A49B4F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A49BF5* + ID_OUI_FROM_DATABASE=Hybridserver Tec GmbH + +OUI:A49D49* + ID_OUI_FROM_DATABASE=Ketra, Inc. + +OUI:A49EDB* + ID_OUI_FROM_DATABASE=AutoCrib, Inc. + +OUI:A49F85* + ID_OUI_FROM_DATABASE=Lyve Minds, Inc + +OUI:A49F89* + ID_OUI_FROM_DATABASE=Shanghai Rui Rui Communication Technology Co.Ltd. + +OUI:A4A179* + ID_OUI_FROM_DATABASE=Nanjing dianyan electric power automation co. LTD + +OUI:A4A1C2* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:A4A1E4* + ID_OUI_FROM_DATABASE=Innotube, Inc. + +OUI:A4A24A* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:A4A4D3* + ID_OUI_FROM_DATABASE=Bluebank Communication Technology Co.Ltd + +OUI:A4A6A9* + ID_OUI_FROM_DATABASE=Private + +OUI:A4A80F* + ID_OUI_FROM_DATABASE=Shenzhen Coship Electronics Co., Ltd. + +OUI:A4AD00* + ID_OUI_FROM_DATABASE=Ragsdale Technology + +OUI:A4ADB8* + ID_OUI_FROM_DATABASE=Vitec Group, Camera Dynamics Ltd + +OUI:A4AE11* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co., Ltd. + +OUI:A4AE9A* + ID_OUI_FROM_DATABASE=Maestro Wireless Solutions ltd. + +OUI:A4B121* + ID_OUI_FROM_DATABASE=Arantia 2010 S.L. + +OUI:A4B197* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A4B1E9* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:A4B1EE* + ID_OUI_FROM_DATABASE=H. ZANDER GmbH & Co. KG + +OUI:A4B239* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A4B2A7* + ID_OUI_FROM_DATABASE=Adaxys Solutions AG + +OUI:A4B36A* + ID_OUI_FROM_DATABASE=JSC SDO Chromatec + +OUI:A4B439* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A4B52E* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:A4B61E* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:A4B805* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A4B818* + ID_OUI_FROM_DATABASE=PENTA Gesellschaft für elektronische Industriedatenverarbeitung mbH + +OUI:A4B980* + ID_OUI_FROM_DATABASE=Parking BOXX Inc. + +OUI:A4BA76* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A4BADB* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:A4BB6D* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:A4BBAF* + ID_OUI_FROM_DATABASE=Lime Instruments + +OUI:A4BE2B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A4BE61* + ID_OUI_FROM_DATABASE=EutroVision System, Inc. + +OUI:A4BF01* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A4C0C7* + ID_OUI_FROM_DATABASE=ShenZhen Hitom Communication Technology Co..LTD + +OUI:A4C0E1* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:A4C138* + ID_OUI_FROM_DATABASE=Telink Semiconductor (Taipei) Co. Ltd. + +OUI:A4C2AB* + ID_OUI_FROM_DATABASE=Hangzhou LEAD-IT Information & Technology Co.,Ltd + +OUI:A4C361* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A4C3F0* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A4C494* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A4C54E* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:A4C64F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A4C7DE* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:A4C939* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:A4CAA0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A4CC32* + ID_OUI_FROM_DATABASE=Inficomm Co., Ltd + +OUI:A4CD23* + ID_OUI_FROM_DATABASE=Shenzhenshi Xinzhongxin Co., Ltd + +OUI:A4CF12* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:A4CFD2* + ID_OUI_FROM_DATABASE=Ubee Interactive Co., Limited + +OUI:A4D094* + ID_OUI_FROM_DATABASE=Erwin Peters Systemtechnik GmbH + +OUI:A4D18C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A4D18F* + ID_OUI_FROM_DATABASE=Shenzhen Skyee Optical Fiber Communication Technology Ltd. + +OUI:A4D1D1* + ID_OUI_FROM_DATABASE=ECOtality North America + +OUI:A4D1D2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A4D3B5* + ID_OUI_FROM_DATABASE=GLITEL Stropkov, s.r.o. + +OUI:A4D4B2* + ID_OUI_FROM_DATABASE=Shenzhen MeiG Smart Technology Co.,Ltd + +OUI:A4D578* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:A4D856* + ID_OUI_FROM_DATABASE=Gimbal, Inc + +OUI:A4D8CA* + ID_OUI_FROM_DATABASE=HONG KONG WATER WORLD TECHNOLOGY CO. LIMITED + +OUI:A4D931* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A4D990* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A4D9A4* + ID_OUI_FROM_DATABASE=neXus ID Solutions AB + +OUI:A4DA220* + ID_OUI_FROM_DATABASE=General Electric Company + +OUI:A4DA221* + ID_OUI_FROM_DATABASE=T2T System + +OUI:A4DA222* + ID_OUI_FROM_DATABASE=Wyze Labs Inc + +OUI:A4DA223* + ID_OUI_FROM_DATABASE=DURATECH Enterprise,LLC + +OUI:A4DA224* + ID_OUI_FROM_DATABASE=LORIOT AG + +OUI:A4DA225* + ID_OUI_FROM_DATABASE=Original Products Pvt. Ltd. + +OUI:A4DA226* + ID_OUI_FROM_DATABASE=AURANEXT + +OUI:A4DA227* + ID_OUI_FROM_DATABASE=Hydro Electronic Devices, Inc. + +OUI:A4DA228* + ID_OUI_FROM_DATABASE=SolidPro Technology Corporation + +OUI:A4DA229* + ID_OUI_FROM_DATABASE=Malldon Technology Limited + +OUI:A4DA22A* + ID_OUI_FROM_DATABASE=Abetechs GmbH + +OUI:A4DA22B* + ID_OUI_FROM_DATABASE=Klashwerks Inc. + +OUI:A4DA22C* + ID_OUI_FROM_DATABASE=EHO.LINK + +OUI:A4DA22D* + ID_OUI_FROM_DATABASE=Shen Zhen City YaKun Electronics Co., Ltd + +OUI:A4DA22E* + ID_OUI_FROM_DATABASE=Quuppa Oy + +OUI:A4DA32* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:A4DA3F* + ID_OUI_FROM_DATABASE=Bionics Corp. + +OUI:A4DB2E* + ID_OUI_FROM_DATABASE=Kingspan Environmental Ltd + +OUI:A4DB30* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:A4DCBE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A4DE50* + ID_OUI_FROM_DATABASE=Total Walther GmbH + +OUI:A4DEC9* + ID_OUI_FROM_DATABASE=QLove Mobile Intelligence Information Technology (W.H.) Co. Ltd. + +OUI:A4E0E6* + ID_OUI_FROM_DATABASE=FILIZOLA S.A. PESAGEM E AUTOMACAO + +OUI:A4E31B* + ID_OUI_FROM_DATABASE=Nokia + +OUI:A4E32E* + ID_OUI_FROM_DATABASE=Silicon & Software Systems Ltd. + +OUI:A4E391* + ID_OUI_FROM_DATABASE=DENY FONTAINE + +OUI:A4E4B8* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:A4E597* + ID_OUI_FROM_DATABASE=Gessler GmbH + +OUI:A4E615* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + +OUI:A4E6B1* + ID_OUI_FROM_DATABASE=Shanghai Joindata Technology Co.,Ltd. + +OUI:A4E731* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:A4E7E4* + ID_OUI_FROM_DATABASE=Connex GmbH + +OUI:A4E975* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A4E991* + ID_OUI_FROM_DATABASE=SISTEMAS AUDIOVISUALES ITELSIS S.L. + +OUI:A4E9A3* + ID_OUI_FROM_DATABASE=Honest Technology Co., Ltd + +OUI:A4EA8E* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:A4EBD3* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A4ED430* + ID_OUI_FROM_DATABASE=Sweam AB + +OUI:A4ED431* + ID_OUI_FROM_DATABASE=INGELABS S.L. + +OUI:A4ED432* + ID_OUI_FROM_DATABASE=Shanghai Mission Information Technologies (Group) Co.,Ltd + +OUI:A4ED433* + ID_OUI_FROM_DATABASE=Dongguan Mingji Electronics technology Group Co., Ltd. + +OUI:A4ED434* + ID_OUI_FROM_DATABASE=NETAS TELEKOMUNIKASYON A.S. + +OUI:A4ED435* + ID_OUI_FROM_DATABASE=Beijing ICPC CO.,Ltd. + +OUI:A4ED436* + ID_OUI_FROM_DATABASE=Shanghai Facom Electronics Technology Co, ltd. + +OUI:A4ED437* + ID_OUI_FROM_DATABASE=Wuxi Junction Infomation Technology Incorporated Company + +OUI:A4ED438* + ID_OUI_FROM_DATABASE=Linseis Messgeraete GmbH + +OUI:A4ED439* + ID_OUI_FROM_DATABASE=Heyuan intelligence technology CO.,Ltd + +OUI:A4ED43A* + ID_OUI_FROM_DATABASE=Guangzhou Maxfaith Communication Technology Co.,LTD. + +OUI:A4ED43B* + ID_OUI_FROM_DATABASE=Paragon Business Solutions Ltd. + +OUI:A4ED43C* + ID_OUI_FROM_DATABASE=leakSMART + +OUI:A4ED43D* + ID_OUI_FROM_DATABASE=Brand New Brand Nordic AB + +OUI:A4ED43E* + ID_OUI_FROM_DATABASE=TOEC TECHNOLOGY CO.,LTD. + +OUI:A4ED4E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A4EE57* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:A4EF52* + ID_OUI_FROM_DATABASE=Telewave Co., Ltd. + +OUI:A4F05E* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:A4F1E8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A4F3C1* + ID_OUI_FROM_DATABASE=Open Source Robotics Foundation, Inc. + +OUI:A4F3E7* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:A4F465* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:A4F4C2* + ID_OUI_FROM_DATABASE=VNPT TECHNOLOGY + +OUI:A4F522* + ID_OUI_FROM_DATABASE=CHOFU SEISAKUSHO CO.,LTD + +OUI:A4F7D0* + ID_OUI_FROM_DATABASE=LAN Accessories Co., Ltd. + +OUI:A4FA76* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:A4FB8D* + ID_OUI_FROM_DATABASE=Hangzhou Dunchong Technology Co.Ltd + +OUI:A4FC77* + ID_OUI_FROM_DATABASE=Mega Well Limited + +OUI:A4FCCE* + ID_OUI_FROM_DATABASE=Security Expert Ltd. + +OUI:A8016D* + ID_OUI_FROM_DATABASE=Aiwa Corporation + +OUI:A80180* + ID_OUI_FROM_DATABASE=IMAGO Technologies GmbH + +OUI:A80600* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A80C0D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A80C63* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A80CCA* + ID_OUI_FROM_DATABASE=Shenzhen Sundray Technologies Company Limited + +OUI:A81087* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:A811FC* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A81374* + ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company + +OUI:A8154D* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:A81559* + ID_OUI_FROM_DATABASE=Breathometer, Inc. + +OUI:A815D6* + ID_OUI_FROM_DATABASE=Shenzhen Meione Technology CO., LTD + +OUI:A816B2* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:A816D0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A81758* + ID_OUI_FROM_DATABASE=Elektronik System i Umeå AB + +OUI:A81B18* + ID_OUI_FROM_DATABASE=XTS CORP + +OUI:A81B5A* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:A81B5D* + ID_OUI_FROM_DATABASE=Foxtel Management Pty Ltd + +OUI:A81B6A* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:A81D16* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:A81E84* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:A81FAF* + ID_OUI_FROM_DATABASE=KRYPTON POLSKA + +OUI:A82066* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A823FE* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:A824B8* + ID_OUI_FROM_DATABASE=Nokia + +OUI:A824EB* + ID_OUI_FROM_DATABASE=ZAO NPO Introtest + +OUI:A825EB* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:A826D9* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:A8294C* + ID_OUI_FROM_DATABASE=Precision Optical Transceivers, Inc. + +OUI:A82BB5* + ID_OUI_FROM_DATABASE=Edgecore Networks Corporation + +OUI:A82BB9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A82BCD* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A82BD6* + ID_OUI_FROM_DATABASE=Shina System Co., Ltd + +OUI:A830AD* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:A8329A* + ID_OUI_FROM_DATABASE=Digicom Futuristic Technologies Ltd. + +OUI:A8346A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A8367A* + ID_OUI_FROM_DATABASE=frogblue TECHNOLOGY GmbH + +OUI:A83944* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:A83CCB* + ID_OUI_FROM_DATABASE=ROSSMA + +OUI:A83E0E* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:A83FA10* + ID_OUI_FROM_DATABASE=Imecon Engineering SrL + +OUI:A83FA11* + ID_OUI_FROM_DATABASE=GTDevice LLC + +OUI:A83FA12* + ID_OUI_FROM_DATABASE=MEDCAPTAIN MEDICAL TECHNOLOGY CO., LTD. + +OUI:A83FA13* + ID_OUI_FROM_DATABASE=Guangzhou Tupu Internet Technology Co., Ltd. + +OUI:A83FA14* + ID_OUI_FROM_DATABASE=Zhejiang Wellsun Intelligent Technology Co.,Ltd. + +OUI:A83FA15* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:A83FA16* + ID_OUI_FROM_DATABASE=BEGLEC + +OUI:A83FA17* + ID_OUI_FROM_DATABASE=Plejd AB + +OUI:A83FA18* + ID_OUI_FROM_DATABASE=Neos Ventures Limited + +OUI:A83FA19* + ID_OUI_FROM_DATABASE=Shenzhen ITLONG Intelligent Technology Co.,Ltd + +OUI:A83FA1A* + ID_OUI_FROM_DATABASE=Shanghai East China Computer Co., Ltd + +OUI:A83FA1B* + ID_OUI_FROM_DATABASE=Exel s.r.l. unipersonale + +OUI:A83FA1C* + ID_OUI_FROM_DATABASE=Laonz Co.,Ltd + +OUI:A83FA1D* + ID_OUI_FROM_DATABASE=Shenzhen BIO I/E Co.,Ltd + +OUI:A83FA1E* + ID_OUI_FROM_DATABASE=Guangzhou Navigateworx Technologies Co., Limited + +OUI:A84041* + ID_OUI_FROM_DATABASE=Dragino Technology Co., Limited + +OUI:A84122* + ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co.,Ltd. + +OUI:A84481* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:A845CD* + ID_OUI_FROM_DATABASE=Siselectron Technology LTD. + +OUI:A845E9* + ID_OUI_FROM_DATABASE=Firich Enterprises CO., LTD. + +OUI:A8474A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:A8494D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A849A5* + ID_OUI_FROM_DATABASE=Lisantech Co., Ltd. + +OUI:A84D4A* + ID_OUI_FROM_DATABASE=Audiowise Technology Inc. + +OUI:A84E3F* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:A8515B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A854B2* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:A8556A* + ID_OUI_FROM_DATABASE=Pocketnet Technology Inc. + +OUI:A8574E* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:A85840* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:A85AE0* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:A85AF3* + ID_OUI_FROM_DATABASE=Shanghai Siflower Communication Technology Co., Ltd + +OUI:A85B6C* + ID_OUI_FROM_DATABASE=Robert Bosch Gmbh, CM-CI2 + +OUI:A85B78* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A85BB0* + ID_OUI_FROM_DATABASE=Shenzhen Dehoo Technology Co.,Ltd + +OUI:A85BF3* + ID_OUI_FROM_DATABASE=Audivo GmbH + +OUI:A85C2C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A85E45* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:A85EE4* + ID_OUI_FROM_DATABASE=12Sided Technology, LLC + +OUI:A860B6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A8610A* + ID_OUI_FROM_DATABASE=ARDUINO AG + +OUI:A861AA* + ID_OUI_FROM_DATABASE=Cloudview Limited + +OUI:A862A2* + ID_OUI_FROM_DATABASE=JIWUMEDIA CO., LTD. + +OUI:A863DF* + ID_OUI_FROM_DATABASE=DISPLAIRE CORPORATION + +OUI:A863F2* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:A86405* + ID_OUI_FROM_DATABASE=nimbus 9, Inc + +OUI:A865B2* + ID_OUI_FROM_DATABASE=DONGGUAN YISHANG ELECTRONIC TECHNOLOGY CO., LIMITED + +OUI:A8667F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A86A6F* + ID_OUI_FROM_DATABASE=RIM + +OUI:A86AC1* + ID_OUI_FROM_DATABASE=HanbitEDS Co., Ltd. + +OUI:A86B7C* + ID_OUI_FROM_DATABASE=SHENZHEN FENGLIAN TECHNOLOGY CO., LTD. + +OUI:A86BAD* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:A86D5F* + ID_OUI_FROM_DATABASE=Raisecom Technology CO., LTD + +OUI:A86DAA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A8705D* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A870A5* + ID_OUI_FROM_DATABASE=UniComm Inc. + +OUI:A87285* + ID_OUI_FROM_DATABASE=IDT, INC. + +OUI:A8741D* + ID_OUI_FROM_DATABASE=PHOENIX CONTACT Electronics GmbH + +OUI:A875D6* + ID_OUI_FROM_DATABASE=FreeTek International Co., Ltd. + +OUI:A875E2* + ID_OUI_FROM_DATABASE=Aventura Technologies, Inc. + +OUI:A8776F* + ID_OUI_FROM_DATABASE=Zonoff + +OUI:A87B39* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:A87C01* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A87D12* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A87E33* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:A87EEA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:A88038* + ID_OUI_FROM_DATABASE=ShenZhen MovingComm Technology Co., Limited + +OUI:A88195* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A881F1* + ID_OUI_FROM_DATABASE=BMEYE B.V. + +OUI:A88200* + ID_OUI_FROM_DATABASE=Hisense Electric Co.,Ltd + +OUI:A8827F* + ID_OUI_FROM_DATABASE=CIBN Oriental Network(Beijing) CO.,Ltd + +OUI:A885D7* + ID_OUI_FROM_DATABASE=Sangfor Technologies Inc. + +OUI:A886DD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A88792* + ID_OUI_FROM_DATABASE=Broadband Antenna Tracking Systems + +OUI:A887B3* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A887ED* + ID_OUI_FROM_DATABASE=ARC Wireless LLC + +OUI:A88808* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A88CEE* + ID_OUI_FROM_DATABASE=MicroMade Galka i Drozdz sp.j. + +OUI:A88D7B* + ID_OUI_FROM_DATABASE=SunDroid Global limited. + +OUI:A88E24* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A89008* + ID_OUI_FROM_DATABASE=Beijing Yuecheng Technology Co. Ltd. + +OUI:A89042* + ID_OUI_FROM_DATABASE=Beijing Wanwei Intelligent Technology Co., Ltd. + +OUI:A8922C* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:A89352* + ID_OUI_FROM_DATABASE=SHANGHAI ZHONGMI COMMUNICATION TECHNOLOGY CO.,LTD + +OUI:A893E6* + ID_OUI_FROM_DATABASE=JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LTD + +OUI:A895B0* + ID_OUI_FROM_DATABASE=Aker Subsea Ltd + +OUI:A89675* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:A8968A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A897CD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A897DC* + ID_OUI_FROM_DATABASE=IBM + +OUI:A898C6* + ID_OUI_FROM_DATABASE=Shinbo Co., Ltd. + +OUI:A8995C* + ID_OUI_FROM_DATABASE=aizo ag + +OUI:A89969* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:A89A93* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:A89B10* + ID_OUI_FROM_DATABASE=inMotion Ltd. + +OUI:A89CA4* + ID_OUI_FROM_DATABASE=Furrion Limited + +OUI:A89CED* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:A89D21* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A89DD2* + ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co.,Ltd + +OUI:A89FBA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A89FEC* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A8A089* + ID_OUI_FROM_DATABASE=Tactical Communications + +OUI:A8A097* + ID_OUI_FROM_DATABASE=ScioTeq bvba + +OUI:A8A159* + ID_OUI_FROM_DATABASE=ASRock Incorporation + +OUI:A8A198* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:A8A5E2* + ID_OUI_FROM_DATABASE=MSF-Vathauer Antriebstechnik GmbH & Co KG + +OUI:A8A648* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:A8A668* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:A8A795* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:A8AD3D* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:A8B0AE* + ID_OUI_FROM_DATABASE=LEONI + +OUI:A8B1D4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A8B2DA* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:A8B456* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:A8B86E* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:A8B9B3* + ID_OUI_FROM_DATABASE=ESSYS + +OUI:A8BB50* + ID_OUI_FROM_DATABASE=WiZ IoT Company Limited + +OUI:A8BBCF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A8BC9C* + ID_OUI_FROM_DATABASE=Cloud Light Technology Limited + +OUI:A8BD1A* + ID_OUI_FROM_DATABASE=Honey Bee (Hong Kong) Limited + +OUI:A8BD27* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:A8BD3A* + ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD + +OUI:A8BE27* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A8BF3C* + ID_OUI_FROM_DATABASE=HDV Phoelectron Technology Limited + +OUI:A8C0EA* + ID_OUI_FROM_DATABASE=Pepwave Limited + +OUI:A8C222* + ID_OUI_FROM_DATABASE=TM-Research Inc. + +OUI:A8C252* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:A8C83A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A8C87F* + ID_OUI_FROM_DATABASE=Roqos, Inc. + +OUI:A8CA7B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A8CAB9* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:A8CB95* + ID_OUI_FROM_DATABASE=EAST BEST CO., LTD. + +OUI:A8CCC5* + ID_OUI_FROM_DATABASE=Saab AB (publ) + +OUI:A8CE90* + ID_OUI_FROM_DATABASE=CVC + +OUI:A8D0E3* + ID_OUI_FROM_DATABASE=Systech Electronics Ltd + +OUI:A8D0E5* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:A8D236* + ID_OUI_FROM_DATABASE=Lightware Visual Engineering + +OUI:A8D3C8* + ID_OUI_FROM_DATABASE=Topcon Electronics GmbH & Co. KG + +OUI:A8D3F7* + ID_OUI_FROM_DATABASE=Arcadyan Technology Corporation + +OUI:A8D409* + ID_OUI_FROM_DATABASE=USA 111 Inc + +OUI:A8D498* + ID_OUI_FROM_DATABASE=Avira Operations GmbH & Co. KG + +OUI:A8D579* + ID_OUI_FROM_DATABASE=Beijing Chushang Science and Technology Co.,Ltd + +OUI:A8D828* + ID_OUI_FROM_DATABASE=Ascensia Diabetes Care + +OUI:A8D88A* + ID_OUI_FROM_DATABASE=Wyconn + +OUI:A8DA01* + ID_OUI_FROM_DATABASE=Shenzhen NUOLIJIA Digital Technology Co.,Ltd + +OUI:A8DB03* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:A8E018* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:A8E2C1* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:A8E2C3* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:A8E3EE* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:A8E539* + ID_OUI_FROM_DATABASE=Moimstone Co.,Ltd + +OUI:A8E544* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A8E552* + ID_OUI_FROM_DATABASE=JUWEL Aquarium AG & Co. KG + +OUI:A8E705* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:A8E77D* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:A8E824* + ID_OUI_FROM_DATABASE=INIM ELECTRONICS S.R.L. + +OUI:A8EEC6* + ID_OUI_FROM_DATABASE=Muuselabs NV/SA + +OUI:A8EF26* + ID_OUI_FROM_DATABASE=Tritonwave + +OUI:A8F038* + ID_OUI_FROM_DATABASE=SHEN ZHEN SHI JIN HUA TAI ELECTRONICS CO.,LTD + +OUI:A8F274* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:A8F470* + ID_OUI_FROM_DATABASE=Fujian Newland Communication Science Technologies Co.,Ltd. + +OUI:A8F5AC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:A8F5DD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:A8F7E0* + ID_OUI_FROM_DATABASE=PLANET Technology Corporation + +OUI:A8F94B* + ID_OUI_FROM_DATABASE=Eltex Enterprise Ltd. + +OUI:A8FAD8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:A8FB70* + ID_OUI_FROM_DATABASE=WiseSec L.t.d + +OUI:A8FCB7* + ID_OUI_FROM_DATABASE=Consolidated Resource Imaging + +OUI:AA0000* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION + +OUI:AA0001* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION + +OUI:AA0002* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION + +OUI:AA0003* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION + +OUI:AA0004* + ID_OUI_FROM_DATABASE=DIGITAL EQUIPMENT CORPORATION + +OUI:AC00D0* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:AC0142* + ID_OUI_FROM_DATABASE=Uriel Technologies SIA + +OUI:AC02CA* + ID_OUI_FROM_DATABASE=HI Solutions, Inc. + +OUI:AC02CF* + ID_OUI_FROM_DATABASE=RW Tecnologia Industria e Comercio Ltda + +OUI:AC02EF* + ID_OUI_FROM_DATABASE=Comsis + +OUI:AC040B* + ID_OUI_FROM_DATABASE=Peloton Interactive, Inc + +OUI:AC0481* + ID_OUI_FROM_DATABASE=Jiangsu Huaxing Electronics Co., Ltd. + +OUI:AC0613* + ID_OUI_FROM_DATABASE=Senselogix Ltd + +OUI:AC06C7* + ID_OUI_FROM_DATABASE=ServerNet S.r.l. + +OUI:AC075F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:AC0A61* + ID_OUI_FROM_DATABASE=Labor S.r.L. + +OUI:AC0D1B* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:AC0DFE* + ID_OUI_FROM_DATABASE=Ekon GmbH - myGEKKO + +OUI:AC11D3* + ID_OUI_FROM_DATABASE=Suzhou HOTEK Video Technology Co. Ltd + +OUI:AC1203* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:AC1461* + ID_OUI_FROM_DATABASE=ATAW Co., Ltd. + +OUI:AC14D2* + ID_OUI_FROM_DATABASE=wi-daq, inc. + +OUI:AC1585* + ID_OUI_FROM_DATABASE=silergy corp + +OUI:AC15F4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC162D* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:AC1702* + ID_OUI_FROM_DATABASE=Fibar Group sp. z o.o. + +OUI:AC17C8* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:AC1826* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:AC199F* + ID_OUI_FROM_DATABASE=SUNGROW POWER SUPPLY CO.,LTD. + +OUI:AC1DDF0* + ID_OUI_FROM_DATABASE=PiOctave Solutions Pvt Ltd + +OUI:AC1DDF1* + ID_OUI_FROM_DATABASE=HellaStorm, Inc. + +OUI:AC1DDF2* + ID_OUI_FROM_DATABASE=ConectaIP Tecnologia S.L. + +OUI:AC1DDF3* + ID_OUI_FROM_DATABASE=CRDE + +OUI:AC1DDF4* + ID_OUI_FROM_DATABASE=Motec Pty Ltd + +OUI:AC1DDF5* + ID_OUI_FROM_DATABASE=Shenzhen Ouzheng Electronic Tech Co,.Ltd + +OUI:AC1DDF6* + ID_OUI_FROM_DATABASE=Shenzheng SenseTime Technology Co. Ltd + +OUI:AC1DDF7* + ID_OUI_FROM_DATABASE=Green IT Korea Co., Ltd. + +OUI:AC1DDF8* + ID_OUI_FROM_DATABASE=Sichuan Odot Automation System Co.,Ltd. + +OUI:AC1DDF9* + ID_OUI_FROM_DATABASE=Solare Datensysteme GmbH + +OUI:AC1DDFA* + ID_OUI_FROM_DATABASE=WESCO INTEGRATED SUPPLY + +OUI:AC1DDFB* + ID_OUI_FROM_DATABASE=Fine Inc. + +OUI:AC1DDFC* + ID_OUI_FROM_DATABASE=Beijing Chunhong Technology Co., Ltd. + +OUI:AC1DDFD* + ID_OUI_FROM_DATABASE=Elekon AG + +OUI:AC1DDFE* + ID_OUI_FROM_DATABASE=Duravit AG + +OUI:AC1E92* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,LTD + +OUI:AC1ED0* + ID_OUI_FROM_DATABASE=Temic Automotive Philippines Inc. + +OUI:AC1F6B* + ID_OUI_FROM_DATABASE=Super Micro Computer, Inc. + +OUI:AC1F74* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC1FD7* + ID_OUI_FROM_DATABASE=Real Vision Technology Co.,Ltd. + +OUI:AC202E* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:AC203E* + ID_OUI_FROM_DATABASE=Wuhan Tianyu Information Industry Co., Ltd. + +OUI:AC20AA* + ID_OUI_FROM_DATABASE=DMATEK Co., Ltd. + +OUI:AC2205* + ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. + +OUI:AC220B* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:AC233F* + ID_OUI_FROM_DATABASE=Shenzhen Minew Technologies Co., Ltd. + +OUI:AC293A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC2A0C* + ID_OUI_FROM_DATABASE=CSR ZHUZHOU INSTITUTE CO.,LTD. + +OUI:AC2B6E* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:AC2DA3* + ID_OUI_FROM_DATABASE=TXTR GmbH + +OUI:AC2DA9* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:AC2FA8* + ID_OUI_FROM_DATABASE=Humannix Co.,Ltd. + +OUI:AC319D* + ID_OUI_FROM_DATABASE=Shenzhen TG-NET Botone Technology Co.,Ltd. + +OUI:AC34CB* + ID_OUI_FROM_DATABASE=Shanhai GBCOM Communication Technology Co. Ltd + +OUI:AC35EE* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:AC3613* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:AC3651* + ID_OUI_FROM_DATABASE=Jiangsu Hengtong Terahertz Technology Co., Ltd. + +OUI:AC3743* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:AC37C9* + ID_OUI_FROM_DATABASE=RAID Incorporated + +OUI:AC3870* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:AC3A67* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:AC3A7A* + ID_OUI_FROM_DATABASE=Roku, Inc. + +OUI:AC3B77* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:AC3C0B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC3CB4* + ID_OUI_FROM_DATABASE=Nilan A/S + +OUI:AC3D05* + ID_OUI_FROM_DATABASE=Instorescreen Aisa + +OUI:AC3D75* + ID_OUI_FROM_DATABASE=HANGZHOU ZHIWAY TECHNOLOGIES CO.,LTD. + +OUI:AC3FA4* + ID_OUI_FROM_DATABASE=TAIYO YUDEN CO.,LTD + +OUI:AC40EA* + ID_OUI_FROM_DATABASE=C&T Solution Inc. + +OUI:AC4122* + ID_OUI_FROM_DATABASE=Eclipse Electronic Systems Inc. + +OUI:AC4228* + ID_OUI_FROM_DATABASE=Parta Networks + +OUI:AC4330* + ID_OUI_FROM_DATABASE=Versa Networks + +OUI:AC44F2* + ID_OUI_FROM_DATABASE=YAMAHA CORPORATION + +OUI:AC4723* + ID_OUI_FROM_DATABASE=Genelec + +OUI:AC482D* + ID_OUI_FROM_DATABASE=Ralinwi Nanjing Electronic Technology Co., Ltd. + +OUI:AC4A56* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:AC4A67* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:AC4AFE* + ID_OUI_FROM_DATABASE=Hisense Broadband Multimedia Technology Co.,Ltd. + +OUI:AC4B1E* + ID_OUI_FROM_DATABASE=Integri-Sys.Com LLC + +OUI:AC4BC8* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:AC4E2E* + ID_OUI_FROM_DATABASE=Shenzhen JingHanDa Electronics Co.Ltd + +OUI:AC4E91* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:AC4FFC* + ID_OUI_FROM_DATABASE=SVS-VISTEK GmbH + +OUI:AC5036* + ID_OUI_FROM_DATABASE=Pi-Coral Inc + +OUI:AC5093* + ID_OUI_FROM_DATABASE=Magna Electronics Europe GmbH & Co. OHG + +OUI:AC512C* + ID_OUI_FROM_DATABASE=Infinix mobility limited + +OUI:AC5135* + ID_OUI_FROM_DATABASE=MPI TECH + +OUI:AC51EE* + ID_OUI_FROM_DATABASE=Cambridge Communication Systems Ltd + +OUI:AC5474* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:AC54EC* + ID_OUI_FROM_DATABASE=IEEE P1823 Standards Working Group + +OUI:AC562C* + ID_OUI_FROM_DATABASE=LAVA INTERNATIONAL(H.K) LIMITED + +OUI:AC5775* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:AC583B* + ID_OUI_FROM_DATABASE=Human Assembler, Inc. + +OUI:AC587B* + ID_OUI_FROM_DATABASE=JCT Healthcare + +OUI:AC5A14* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:AC5AEE* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:AC5D10* + ID_OUI_FROM_DATABASE=Pace Americas + +OUI:AC5D5C* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:AC5E8C* + ID_OUI_FROM_DATABASE=Utillink + +OUI:AC5F3E* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:AC60B6* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:AC6123* + ID_OUI_FROM_DATABASE=Drivven, Inc. + +OUI:AC6175* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:AC61B9* + ID_OUI_FROM_DATABASE=WAMA Technology Limited + +OUI:AC61EA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC620D* + ID_OUI_FROM_DATABASE=Jabil Circuit(Wuxi) Co.,Ltd + +OUI:AC63BE* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:AC6417* + ID_OUI_FROM_DATABASE=Siemens AG + +OUI:AC6462* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:AC64CF* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:AC64DD0* + ID_OUI_FROM_DATABASE=Jia-Teng + +OUI:AC64DD1* + ID_OUI_FROM_DATABASE=JSC InfoTeCS + +OUI:AC64DD2* + ID_OUI_FROM_DATABASE=Shenzhen PuHua Technology Co., Ltd + +OUI:AC64DD3* + ID_OUI_FROM_DATABASE=infypower Co., Ltd + +OUI:AC64DD4* + ID_OUI_FROM_DATABASE=8Cups + +OUI:AC64DD5* + ID_OUI_FROM_DATABASE=SHANGHAI ZTE TECHNOLOGIES CO.,LTD + +OUI:AC64DD6* + ID_OUI_FROM_DATABASE=Kpnetworks Ltd. + +OUI:AC64DD7* + ID_OUI_FROM_DATABASE=Wittmann Kunststoffgeräte GmbH + +OUI:AC64DD8* + ID_OUI_FROM_DATABASE=PFDC ELANCYL + +OUI:AC64DD9* + ID_OUI_FROM_DATABASE=Micro Connect Pty Ltd + +OUI:AC64DDA* + ID_OUI_FROM_DATABASE=Bluewave Global Manufacturing Limited + +OUI:AC64DDB* + ID_OUI_FROM_DATABASE=Groupe Citypassenger Inc + +OUI:AC64DDC* + ID_OUI_FROM_DATABASE=Beijing Hamigua Technology Co., Ltd. + +OUI:AC64DDD* + ID_OUI_FROM_DATABASE=HMicro Inc + +OUI:AC64DDE* + ID_OUI_FROM_DATABASE=DIGIBIRD TECHNOLOGY CO., LTD. + +OUI:AC6706* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:AC676F* + ID_OUI_FROM_DATABASE=Electrocompaniet A.S. + +OUI:AC6B0F* + ID_OUI_FROM_DATABASE=CADENCE DESIGN SYSTEMS INC + +OUI:AC6BAC* + ID_OUI_FROM_DATABASE=Jenny Science AG + +OUI:AC6E1A* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:AC6F4F* + ID_OUI_FROM_DATABASE=Enspert Inc + +OUI:AC6FBB* + ID_OUI_FROM_DATABASE=TATUNG Technology Inc. + +OUI:AC6FD9* + ID_OUI_FROM_DATABASE=Valueplus Inc. + +OUI:AC710C* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:AC7236* + ID_OUI_FROM_DATABASE=Lexking Technology Co., Ltd. + +OUI:AC7289* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:AC7409* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:AC751D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:AC7713* + ID_OUI_FROM_DATABASE=Honeywell Safety Products (Shanghai) Co.,Ltd + +OUI:AC7A42* + ID_OUI_FROM_DATABASE=iConnectivity + +OUI:AC7A4D* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:AC7BA1* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:AC7E8A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:AC7F3E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC80D6* + ID_OUI_FROM_DATABASE=Hexatronic AB + +OUI:AC8112* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:AC81F3* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:AC8317* + ID_OUI_FROM_DATABASE=Shenzhen Furtunetel Communication Co., Ltd + +OUI:AC83E9* + ID_OUI_FROM_DATABASE=Beijing Zile Technology Co., Ltd + +OUI:AC83F0* + ID_OUI_FROM_DATABASE=ImmediaTV Corporation + +OUI:AC83F3* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:AC84C6* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:AC84C9* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:AC853D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:AC8674* + ID_OUI_FROM_DATABASE=Open Mesh, Inc. + +OUI:AC867E* + ID_OUI_FROM_DATABASE=Create New Technology (HK) Limited Company + +OUI:AC87A3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC88FD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC8995* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:AC8ACD* + ID_OUI_FROM_DATABASE=ROGER D.Wensker, G.Wensker sp.j. + +OUI:AC8B9C* + ID_OUI_FROM_DATABASE=Primera Technology, Inc. + +OUI:AC8D14* + ID_OUI_FROM_DATABASE=Smartrove Inc + +OUI:AC8D34* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:AC8FF8* + ID_OUI_FROM_DATABASE=Nokia + +OUI:AC9085* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:AC9232* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:AC932F* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:AC9403* + ID_OUI_FROM_DATABASE=Envision Peripherals Inc + +OUI:AC9A22* + ID_OUI_FROM_DATABASE=NXP Semiconductors + +OUI:AC9A96* + ID_OUI_FROM_DATABASE=Lantiq Deutschland GmbH + +OUI:AC9B0A* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:AC9B84* + ID_OUI_FROM_DATABASE=Smak Tecnologia e Automacao + +OUI:AC9CE4* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:AC9E17* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:ACA016* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:ACA213* + ID_OUI_FROM_DATABASE=Shenzhen Bilian electronic CO.,LTD + +OUI:ACA22C* + ID_OUI_FROM_DATABASE=Baycity Technologies Ltd + +OUI:ACA31E* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:ACA430* + ID_OUI_FROM_DATABASE=Peerless AV + +OUI:ACA46E* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:ACA667* + ID_OUI_FROM_DATABASE=Electronic Systems Protection, Inc. + +OUI:ACA88E* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:ACA919* + ID_OUI_FROM_DATABASE=TrekStor GmbH + +OUI:ACA9A0* + ID_OUI_FROM_DATABASE=Audioengine, Ltd. + +OUI:ACAB2E* + ID_OUI_FROM_DATABASE=Beijing LasNubes Technology Co., Ltd. + +OUI:ACAB8D* + ID_OUI_FROM_DATABASE=Lyngso Marine A/S + +OUI:ACABBF* + ID_OUI_FROM_DATABASE=AthenTek Inc. + +OUI:ACAE19* + ID_OUI_FROM_DATABASE=Roku, Inc + +OUI:ACAFB9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:ACB1EE* + ID_OUI_FROM_DATABASE=SHENZHEN FENDA TECHNOLOGY CO., LTD + +OUI:ACB313* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:ACB3B5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:ACB57D* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:ACB74F* + ID_OUI_FROM_DATABASE=METEL s.r.o. + +OUI:ACB859* + ID_OUI_FROM_DATABASE=Uniband Electronic Corp, + +OUI:ACBB61* + ID_OUI_FROM_DATABASE=YSTen Technology Co.,Ltd + +OUI:ACBC32* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:ACBD0B* + ID_OUI_FROM_DATABASE=Leimac Ltd. + +OUI:ACBD70* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:ACBE75* + ID_OUI_FROM_DATABASE=Ufine Technologies Co.,Ltd. + +OUI:ACBEB6* + ID_OUI_FROM_DATABASE=Visualedge Technology Co., Ltd. + +OUI:ACC1EE* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:ACC25D* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:ACC2EC* + ID_OUI_FROM_DATABASE=CLT INT'L IND. CORP. + +OUI:ACC33A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:ACC358* + ID_OUI_FROM_DATABASE=Continental Automotive Czech Republic s.r.o. + +OUI:ACC51B* + ID_OUI_FROM_DATABASE=Zhuhai Pantum Electronics Co., Ltd. + +OUI:ACC595* + ID_OUI_FROM_DATABASE=Graphite Systems + +OUI:ACC662* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:ACC698* + ID_OUI_FROM_DATABASE=Kohzu Precision Co., Ltd. + +OUI:ACC73F* + ID_OUI_FROM_DATABASE=VITSMO CO., LTD. + +OUI:ACC935* + ID_OUI_FROM_DATABASE=Ness Corporation + +OUI:ACCA54* + ID_OUI_FROM_DATABASE=Telldus Technologies AB + +OUI:ACCA8E* + ID_OUI_FROM_DATABASE=ODA Technologies + +OUI:ACCAAB* + ID_OUI_FROM_DATABASE=Virtual Electric Inc + +OUI:ACCABA* + ID_OUI_FROM_DATABASE=Midokura Co., Ltd. + +OUI:ACCB09* + ID_OUI_FROM_DATABASE=Hefcom Metering (Pty) Ltd + +OUI:ACCB51* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:ACCC8E* + ID_OUI_FROM_DATABASE=Axis Communications AB + +OUI:ACCE8F* + ID_OUI_FROM_DATABASE=HWA YAO TECHNOLOGIES CO., LTD + +OUI:ACCF23* + ID_OUI_FROM_DATABASE=Hi-flying electronics technology Co.,Ltd + +OUI:ACCF5C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:ACCF85* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:ACD074* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:ACD180* + ID_OUI_FROM_DATABASE=Crexendo Business Solutions, Inc. + +OUI:ACD1B8* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:ACD364* + ID_OUI_FROM_DATABASE=ABB SPA, ABB SACE DIV. + +OUI:ACD564* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:ACD657* + ID_OUI_FROM_DATABASE=Shaanxi GuoLian Digital TV Technology Co.,Ltd. + +OUI:ACD9D6* + ID_OUI_FROM_DATABASE=tci GmbH + +OUI:ACDB48* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:ACDBDA* + ID_OUI_FROM_DATABASE=Shenzhen Geniatech Inc, Ltd + +OUI:ACDCE5* + ID_OUI_FROM_DATABASE=Procter & Gamble Company + +OUI:ACDE48* + ID_OUI_FROM_DATABASE=Private + +OUI:ACE010* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:ACE069* + ID_OUI_FROM_DATABASE=ISAAC Instruments + +OUI:ACE215* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:ACE2D3* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:ACE342* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:ACE348* + ID_OUI_FROM_DATABASE=MadgeTech, Inc + +OUI:ACE42E* + ID_OUI_FROM_DATABASE=SK hynix + +OUI:ACE4B5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:ACE5F0* + ID_OUI_FROM_DATABASE=Doppler Labs + +OUI:ACE64B* + ID_OUI_FROM_DATABASE=Shenzhen Baojia Battery Technology Co., Ltd. + +OUI:ACE77B* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:ACE87B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:ACE87E* + ID_OUI_FROM_DATABASE=Bytemark Computer Consulting Ltd + +OUI:ACE97F* + ID_OUI_FROM_DATABASE=IoT Tech Limited + +OUI:ACE9AA* + ID_OUI_FROM_DATABASE=Hay Systems Ltd + +OUI:ACEA6A* + ID_OUI_FROM_DATABASE=GENIX INFOCOMM CO., LTD. + +OUI:ACEB51* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. + +OUI:ACEC80* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:ACED5C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:ACEE3B* + ID_OUI_FROM_DATABASE=6harmonics Inc + +OUI:ACEE70* + ID_OUI_FROM_DATABASE=Fontem Ventures BV + +OUI:ACEE9E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:ACF0B2* + ID_OUI_FROM_DATABASE=Becker Electronics Taiwan Ltd. + +OUI:ACF1DF* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:ACF2C5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:ACF5E6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:ACF6F7* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:ACF7F3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:ACF85C* + ID_OUI_FROM_DATABASE=Private + +OUI:ACF8CC* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:ACF970* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:ACF97E* + ID_OUI_FROM_DATABASE=ELESYS INC. + +OUI:ACFD93* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:ACFDCE* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:ACFDEC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:ACFE05* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:B00073* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:B000B4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B00247* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:B0027E* + ID_OUI_FROM_DATABASE=MULLER SERVICES + +OUI:B00594* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:B00875* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B008BF* + ID_OUI_FROM_DATABASE=Vital Connect, Inc. + +OUI:B009D3* + ID_OUI_FROM_DATABASE=Avizia + +OUI:B009DA* + ID_OUI_FROM_DATABASE=Ring Solutions + +OUI:B00AD5* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:B00CD1* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:B01041* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:B01203* + ID_OUI_FROM_DATABASE=Dynamics Hong Kong Limited + +OUI:B01266* + ID_OUI_FROM_DATABASE=Futaba-Kikaku + +OUI:B01408* + ID_OUI_FROM_DATABASE=LIGHTSPEED INTERNATIONAL CO. + +OUI:B01743* + ID_OUI_FROM_DATABASE=EDISON GLOBAL CIRCUITS LLC + +OUI:B01886* + ID_OUI_FROM_DATABASE=SmarDTV + +OUI:B019C6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B01B7C* + ID_OUI_FROM_DATABASE=Ontrol A.S. + +OUI:B01BD2* + ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited + +OUI:B01C91* + ID_OUI_FROM_DATABASE=Elim Co + +OUI:B01F29* + ID_OUI_FROM_DATABASE=Helvetia INC. + +OUI:B01F810* + ID_OUI_FROM_DATABASE=Dalian GigaTec Electronics Co.,Ltd + +OUI:B01F811* + ID_OUI_FROM_DATABASE=Uvax Concepts + +OUI:B01F812* + ID_OUI_FROM_DATABASE=Private + +OUI:B01F813* + ID_OUI_FROM_DATABASE=Sound United + +OUI:B01F814* + ID_OUI_FROM_DATABASE=SHENZHEN YIFANG DIGITAL TECHNOLOGY CO.,LTD. + +OUI:B01F815* + ID_OUI_FROM_DATABASE=SHENZHEN GRID TECHNOLOGY CO.,LTD + +OUI:B01F816* + ID_OUI_FROM_DATABASE=COMOTA Co., Ltd. + +OUI:B01F817* + ID_OUI_FROM_DATABASE=Aether Services, Inc. + +OUI:B01F818* + ID_OUI_FROM_DATABASE=Technion Oy + +OUI:B01F819* + ID_OUI_FROM_DATABASE=CIDE Interactive + +OUI:B01F81A* + ID_OUI_FROM_DATABASE=Steffens Systems GmbH + +OUI:B01F81B* + ID_OUI_FROM_DATABASE=Rademacher Geraete-Elektronik GmbH + +OUI:B01F81C* + ID_OUI_FROM_DATABASE=Access Device Integrated Communications Corp. + +OUI:B01F81D* + ID_OUI_FROM_DATABASE=TAIWAN Anjie Electronics Co.,Ltd. + +OUI:B01F81E* + ID_OUI_FROM_DATABASE=Advanced & Wise Technology Corp. + +OUI:B01F81F* + ID_OUI_FROM_DATABASE=Private + +OUI:B024F3* + ID_OUI_FROM_DATABASE=Progeny Systems + +OUI:B025AA* + ID_OUI_FROM_DATABASE=Private + +OUI:B02628* + ID_OUI_FROM_DATABASE=Broadcom Limited + +OUI:B02680* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B02A1F* + ID_OUI_FROM_DATABASE=Wingtech Group (HongKong)Limited + +OUI:B02A43* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:B03055* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:B033A6* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:B03495* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B0350B* + ID_OUI_FROM_DATABASE=MOBIWIRE MOBILES (NINGBO) CO.,LTD + +OUI:B0358D* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:B0359F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B035B5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B03829* + ID_OUI_FROM_DATABASE=Siliconware Precision Industries Co., Ltd. + +OUI:B03850* + ID_OUI_FROM_DATABASE=Nanjing CAS-ZDC IOT SYSTEM CO.,LTD + +OUI:B03956* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:B03D96* + ID_OUI_FROM_DATABASE=Vision Valley FZ LLC + +OUI:B03E51* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:B03EB0* + ID_OUI_FROM_DATABASE=MICRODIA Ltd. + +OUI:B04089* + ID_OUI_FROM_DATABASE=Senient Systems LTD + +OUI:B0411D* + ID_OUI_FROM_DATABASE=ITTIM Technologies + +OUI:B0416F* + ID_OUI_FROM_DATABASE=Shenzhen Maxtang Computer Co.,Ltd + +OUI:B0435D* + ID_OUI_FROM_DATABASE=NuLEDs, Inc. + +OUI:B04515* + ID_OUI_FROM_DATABASE=mira fitness,LLC. + +OUI:B04519* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:B04545* + ID_OUI_FROM_DATABASE=YACOUB Automation GmbH + +OUI:B046FC* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:B047BF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B0481A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B0487A* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:B0495F* + ID_OUI_FROM_DATABASE=OMRON HEALTHCARE Co., Ltd. + +OUI:B04BBF* + ID_OUI_FROM_DATABASE=PT HAN SUNG ELECTORONICS INDONESIA + +OUI:B04C05* + ID_OUI_FROM_DATABASE=Fresenius Medical Care Deutschland GmbH + +OUI:B04E26* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:B04FC3* + ID_OUI_FROM_DATABASE=Shenzhen NVC Cloud Technology Co., Ltd. + +OUI:B050BC* + ID_OUI_FROM_DATABASE=SHENZHEN BASICOM ELECTRONIC CO.,LTD. + +OUI:B0518E* + ID_OUI_FROM_DATABASE=Holl technology CO.Ltd. + +OUI:B05216* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:B05365* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:B05508* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B05706* + ID_OUI_FROM_DATABASE=Vallox Oy + +OUI:B058C4* + ID_OUI_FROM_DATABASE=Broadcast Microwave Services, Inc + +OUI:B05947* + ID_OUI_FROM_DATABASE=Shenzhen Qihu Intelligent Technology Company Limited + +OUI:B05ADA* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:B05B1F* + ID_OUI_FROM_DATABASE=THERMO FISHER SCIENTIFIC S.P.A. + +OUI:B05B67* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B05CE5* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:B061C7* + ID_OUI_FROM_DATABASE=Ericsson-LG Enterprise + +OUI:B06563* + ID_OUI_FROM_DATABASE=Shanghai Railway Communication Factory + +OUI:B065BD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B065F1* + ID_OUI_FROM_DATABASE=WIO Manufacturing HK Limited + +OUI:B0672F* + ID_OUI_FROM_DATABASE=Bowers & Wilkins + +OUI:B068B6* + ID_OUI_FROM_DATABASE=Hangzhou OYE Technology Co. Ltd + +OUI:B068E6* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:B06971* + ID_OUI_FROM_DATABASE=DEI Sales, Inc. + +OUI:B06CBF* + ID_OUI_FROM_DATABASE=3ality Digital Systems GmbH + +OUI:B06EBF* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:B06FE0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B0700D* + ID_OUI_FROM_DATABASE=Nokia + +OUI:B0702D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B072BF* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:B0735D* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:B0750C* + ID_OUI_FROM_DATABASE=QA Cafe + +OUI:B0754D* + ID_OUI_FROM_DATABASE=Nokia + +OUI:B075D5* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:B077AC* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:B07870* + ID_OUI_FROM_DATABASE=Wi-NEXT, Inc. + +OUI:B078F0* + ID_OUI_FROM_DATABASE=Beijing HuaqinWorld Technology Co.,Ltd. + +OUI:B07908* + ID_OUI_FROM_DATABASE=Cummings Engineering + +OUI:B0793C* + ID_OUI_FROM_DATABASE=Revolv Inc + +OUI:B07994* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:B07D47* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B07D62* + ID_OUI_FROM_DATABASE=Dipl.-Ing. H. Horstmann GmbH + +OUI:B07E11* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:B07E70* + ID_OUI_FROM_DATABASE=Zadara Storage Ltd. + +OUI:B07FB9* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:B0808C* + ID_OUI_FROM_DATABASE=Laser Light Engines + +OUI:B081D8* + ID_OUI_FROM_DATABASE=I-sys Corp + +OUI:B083D6* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:B083FE* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:B0869E* + ID_OUI_FROM_DATABASE=Chloride S.r.L + +OUI:B08807* + ID_OUI_FROM_DATABASE=Strata Worldwide + +OUI:B08900* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B08991* + ID_OUI_FROM_DATABASE=LGE + +OUI:B089C2* + ID_OUI_FROM_DATABASE=Zyptonite + +OUI:B08BCF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B08E1A* + ID_OUI_FROM_DATABASE=URadio Systems Co., Ltd + +OUI:B09074* + ID_OUI_FROM_DATABASE=Fulan Electronics Limited + +OUI:B0907E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B090D4* + ID_OUI_FROM_DATABASE=Shenzhen Hoin Internet Technology Co., Ltd + +OUI:B09122* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:B09134* + ID_OUI_FROM_DATABASE=Taleo + +OUI:B09137* + ID_OUI_FROM_DATABASE=ISis ImageStream Internet Solutions, Inc + +OUI:B0935B* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:B09575* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:B0958E* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:B0966C* + ID_OUI_FROM_DATABASE=Lanbowan Technology Ltd. + +OUI:B0973A* + ID_OUI_FROM_DATABASE=E-Fuel Corporation + +OUI:B0982B* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:B0989F* + ID_OUI_FROM_DATABASE=LG CNS + +OUI:B09928* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:B09AE2* + ID_OUI_FROM_DATABASE=STEMMER IMAGING GmbH + +OUI:B09BD4* + ID_OUI_FROM_DATABASE=GNH Software India Private Limited + +OUI:B09FBA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B0A10A* + ID_OUI_FROM_DATABASE=Pivotal Systems Corporation + +OUI:B0A2E7* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:B0A37E* + ID_OUI_FROM_DATABASE=QING DAO HAIER TELECOM CO.,LTD. + +OUI:B0A454* + ID_OUI_FROM_DATABASE=Tripwire Inc. + +OUI:B0A6F5* + ID_OUI_FROM_DATABASE=Xaptum, Inc. + +OUI:B0A72A* + ID_OUI_FROM_DATABASE=Ensemble Designs, Inc. + +OUI:B0A737* + ID_OUI_FROM_DATABASE=Roku, Inc. + +OUI:B0A86E* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:B0AA36* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:B0AA77* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B0AAD2* + ID_OUI_FROM_DATABASE=Sichuan tianyi kanghe communications co., LTD + +OUI:B0ACD2* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:B0ACFA* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:B0ADAA* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:B0AE25* + ID_OUI_FROM_DATABASE=Varikorea + +OUI:B0B194* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:B0B28F* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:B0B2DC* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:B0B32B* + ID_OUI_FROM_DATABASE=Slican Sp. z o.o. + +OUI:B0B3530* + ID_OUI_FROM_DATABASE=Blake UK + +OUI:B0B3531* + ID_OUI_FROM_DATABASE=Sprocomm Technologies CO.,LTD. + +OUI:B0B3532* + ID_OUI_FROM_DATABASE=Rizhao SUNWAM International Co., Ltd. + +OUI:B0B3533* + ID_OUI_FROM_DATABASE=AD HOC DEVELOPMENTS S.L + +OUI:B0B3534* + ID_OUI_FROM_DATABASE=Innotas Elektronik GmbH + +OUI:B0B3535* + ID_OUI_FROM_DATABASE=Zenlayer + +OUI:B0B3536* + ID_OUI_FROM_DATABASE=Hangzhou Hikrobot Technology Co., Ltd. + +OUI:B0B3537* + ID_OUI_FROM_DATABASE=WUUK LABS CORP. + +OUI:B0B3538* + ID_OUI_FROM_DATABASE=VOXISCOM + +OUI:B0B3539* + ID_OUI_FROM_DATABASE=HANMECIPS CO. + +OUI:B0B353A* + ID_OUI_FROM_DATABASE=Ledger + +OUI:B0B353B* + ID_OUI_FROM_DATABASE=Zoox + +OUI:B0B353C* + ID_OUI_FROM_DATABASE=Beijing Geekplus Technology Co.,Ltd. + +OUI:B0B353D* + ID_OUI_FROM_DATABASE=IPvideo Corporation + +OUI:B0B353E* + ID_OUI_FROM_DATABASE=Nanjing Yining Intelligent Technology Co., Ltd. + +OUI:B0B3AD* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:B0B448* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:B0B5C3* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:B0B5E8* + ID_OUI_FROM_DATABASE=Ruroc LTD + +OUI:B0B867* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:B0B8D5* + ID_OUI_FROM_DATABASE=Nanjing Nengrui Auto Equipment CO.,Ltd + +OUI:B0B98A* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:B0BB8B* + ID_OUI_FROM_DATABASE=WAVETEL TECHNOLOGY LIMITED + +OUI:B0BD6D* + ID_OUI_FROM_DATABASE=Echostreams Innovative Solutions + +OUI:B0BDA1* + ID_OUI_FROM_DATABASE=ZAKLAD ELEKTRONICZNY SIMS + +OUI:B0BE76* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:B0BF99* + ID_OUI_FROM_DATABASE=WIZITDONGDO + +OUI:B0C090* + ID_OUI_FROM_DATABASE=Chicony Electronics Co., Ltd. + +OUI:B0C128* + ID_OUI_FROM_DATABASE=Adler ELREHA GmbH + +OUI:B0C19E* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:B0C205* + ID_OUI_FROM_DATABASE=BIONIME + +OUI:B0C287* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:B0C387* + ID_OUI_FROM_DATABASE=GOEFER, Inc. + +OUI:B0C46C* + ID_OUI_FROM_DATABASE=Senseit + +OUI:B0C4E7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B0C554* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:B0C559* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B0C5CA0* + ID_OUI_FROM_DATABASE=EM-Tech + +OUI:B0C5CA1* + ID_OUI_FROM_DATABASE=IVK-SAYANY + +OUI:B0C5CA2* + ID_OUI_FROM_DATABASE=LOWOTEC GmbH + +OUI:B0C5CA3* + ID_OUI_FROM_DATABASE=abode systems, inc. + +OUI:B0C5CA4* + ID_OUI_FROM_DATABASE=shanghai University Ding-Tech software Corp.,ltd + +OUI:B0C5CA5* + ID_OUI_FROM_DATABASE=SYSTOVI + +OUI:B0C5CA6* + ID_OUI_FROM_DATABASE=SunTech Medical, Inc. + +OUI:B0C5CA7* + ID_OUI_FROM_DATABASE=SHENZHEN KTC TECHNOLOGY GROUP + +OUI:B0C5CA8* + ID_OUI_FROM_DATABASE=Astyx GmbH + +OUI:B0C5CA9* + ID_OUI_FROM_DATABASE=D&T Inc. + +OUI:B0C5CAA* + ID_OUI_FROM_DATABASE=TEM Mobile Limited + +OUI:B0C5CAB* + ID_OUI_FROM_DATABASE=RISECOMM (HK) TECHNOLOGY CO. LIMITED + +OUI:B0C5CAC* + ID_OUI_FROM_DATABASE=XMetrics + +OUI:B0C5CAD* + ID_OUI_FROM_DATABASE=Private + +OUI:B0C5CAE* + ID_OUI_FROM_DATABASE=Audio Elektronik İthalat İhracat San ve Tic A.Ş. + +OUI:B0C5CAF* + ID_OUI_FROM_DATABASE=Private + +OUI:B0C69A* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:B0C745* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:B0C83F* + ID_OUI_FROM_DATABASE=Jiangsu Cynray IOT Co., Ltd. + +OUI:B0C8AD* + ID_OUI_FROM_DATABASE=People Power Company + +OUI:B0C95B* + ID_OUI_FROM_DATABASE=Beijing Symtech CO.,LTD + +OUI:B0CA68* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B0CCFE* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:B0CE18* + ID_OUI_FROM_DATABASE=Zhejiang shenghui lighting co.,Ltd + +OUI:B0CF4D* + ID_OUI_FROM_DATABASE=MI-Zone Technology Ireland + +OUI:B0D09C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B0D2F5* + ID_OUI_FROM_DATABASE=Vello Systems, Inc. + +OUI:B0D568* + ID_OUI_FROM_DATABASE=Shenzhen Cultraview Digital Technology Co., Ltd + +OUI:B0D59D* + ID_OUI_FROM_DATABASE=Shenzhen Zowee Technology Co., Ltd + +OUI:B0D5CC* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:B0D7C5* + ID_OUI_FROM_DATABASE=Logipix Ltd + +OUI:B0D7CC* + ID_OUI_FROM_DATABASE=Tridonic GmbH & Co KG + +OUI:B0DA00* + ID_OUI_FROM_DATABASE=CERA ELECTRONIQUE + +OUI:B0DAF9* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:B0DF3A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B0DFC1* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:B0E03C* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:B0E17E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B0E235* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:B0E2E5* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:B0E39D* + ID_OUI_FROM_DATABASE=CAT SYSTEM CO.,LTD. + +OUI:B0E4D5* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:B0E50E* + ID_OUI_FROM_DATABASE=NRG SYSTEMS INC + +OUI:B0E5ED* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B0E71D* + ID_OUI_FROM_DATABASE=Shanghai Maigantech Co.,Ltd + +OUI:B0E754* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:B0E7DE* + ID_OUI_FROM_DATABASE=Homa Technologies JSC + +OUI:B0E892* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:B0E97E* + ID_OUI_FROM_DATABASE=Advanced Micro Peripherals + +OUI:B0EABC* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:B0EB57* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B0EC71* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B0EC8F* + ID_OUI_FROM_DATABASE=GMX SAS + +OUI:B0ECE1* + ID_OUI_FROM_DATABASE=Private + +OUI:B0EE45* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:B0EE7B* + ID_OUI_FROM_DATABASE=Roku, Inc + +OUI:B0F1A3* + ID_OUI_FROM_DATABASE=Fengfan (BeiJing) Technology Co., Ltd. + +OUI:B0F1BC* + ID_OUI_FROM_DATABASE=Dhemax Ingenieros Ltda + +OUI:B0F1EC* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:B0F530* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:B0F893* + ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd. + +OUI:B0F963* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:B0FAEB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B0FC0D* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:B0FC36* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. + +OUI:B0FD0B0* + ID_OUI_FROM_DATABASE=TAE HYUNG Industrial Electronics Co., Ltd. + +OUI:B0FD0B1* + ID_OUI_FROM_DATABASE=IDspire Corporation Ltd. + +OUI:B0FD0B2* + ID_OUI_FROM_DATABASE=Vista Manufacturing + +OUI:B0FD0B3* + ID_OUI_FROM_DATABASE=DMAC Security LLC + +OUI:B0FD0B4* + ID_OUI_FROM_DATABASE=Fasii Information Technology (Shanghai) Ltd. + +OUI:B0FD0B5* + ID_OUI_FROM_DATABASE=Taian Yuqi Communication Technology Co., Ltd + +OUI:B0FD0B6* + ID_OUI_FROM_DATABASE=DNESO TEN Ltd. + +OUI:B0FD0B7* + ID_OUI_FROM_DATABASE=Everynet Oy + +OUI:B0FD0B8* + ID_OUI_FROM_DATABASE=eSenseLab Ltd. + +OUI:B0FD0B9* + ID_OUI_FROM_DATABASE=Eagle Acoustics Manufacturing, LLC + +OUI:B0FD0BA* + ID_OUI_FROM_DATABASE=TEMCO JAPAN CO., LTD. + +OUI:B0FD0BB* + ID_OUI_FROM_DATABASE=MartinLogan, Ltd. + +OUI:B0FD0BC* + ID_OUI_FROM_DATABASE=Haltian Products Oy + +OUI:B0FD0BD* + ID_OUI_FROM_DATABASE=Habana Labs LTD + +OUI:B0FD0BE* + ID_OUI_FROM_DATABASE=Shenzhen FEIBIT Electronic Technology Co.,LTD + +OUI:B0FEBD* + ID_OUI_FROM_DATABASE=Private + +OUI:B40016* + ID_OUI_FROM_DATABASE=INGENICO TERMINALS SAS + +OUI:B4009C* + ID_OUI_FROM_DATABASE=CableWorld Ltd. + +OUI:B40142* + ID_OUI_FROM_DATABASE=GCI Science & Technology Co.,LTD + +OUI:B40216* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B40418* + ID_OUI_FROM_DATABASE=Smartchip Integrated Inc. + +OUI:B4055D* + ID_OUI_FROM_DATABASE=Inspur Electronic Information Industry Co.,Ltd. + +OUI:B40566* + ID_OUI_FROM_DATABASE=SP Best Corporation Co., LTD. + +OUI:B407F9* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:B40832* + ID_OUI_FROM_DATABASE=TC Communications + +OUI:B40931* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B40AC6* + ID_OUI_FROM_DATABASE=DEXON Systems Ltd. + +OUI:B40B44* + ID_OUI_FROM_DATABASE=Smartisan Technology Co., Ltd. + +OUI:B40B78* + ID_OUI_FROM_DATABASE=Brusa Elektronik AG + +OUI:B40B7A* + ID_OUI_FROM_DATABASE=Brusa Elektronik AG + +OUI:B40C25* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:B40E96* + ID_OUI_FROM_DATABASE=HERAN + +OUI:B40EDC* + ID_OUI_FROM_DATABASE=LG-Ericsson Co.,Ltd. + +OUI:B40F3B* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:B40FB3* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:B41489* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B41513* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B4157E* + ID_OUI_FROM_DATABASE=Celona Inc. + +OUI:B41780* + ID_OUI_FROM_DATABASE=DTI Group Ltd + +OUI:B418D1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B41A1D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B41C30* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:B41D2B* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:B41DEF* + ID_OUI_FROM_DATABASE=Internet Laboratories, Inc. + +OUI:B4211D* + ID_OUI_FROM_DATABASE=Beijing GuangXin Technology Co., Ltd + +OUI:B4218A* + ID_OUI_FROM_DATABASE=Dog Hunter LLC + +OUI:B42200* + ID_OUI_FROM_DATABASE=Brother Industries, LTD. + +OUI:B424E7* + ID_OUI_FROM_DATABASE=Codetek Technology Co.,Ltd + +OUI:B4265D* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:B428F1* + ID_OUI_FROM_DATABASE=E-Prime Co., Ltd. + +OUI:B4293D* + ID_OUI_FROM_DATABASE=Shenzhen Urovo Technology Co.,Ltd. + +OUI:B42A0E* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:B42A39* + ID_OUI_FROM_DATABASE=ORBIT MERRET, spol. s r. o. + +OUI:B42C92* + ID_OUI_FROM_DATABASE=Zhejiang Weirong Electronic Co., Ltd + +OUI:B42CBE* + ID_OUI_FROM_DATABASE=Direct Payment Solutions Limited + +OUI:B42D56* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:B42E99* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:B42EF8* + ID_OUI_FROM_DATABASE=Eline Technology co.Ltd + +OUI:B43052* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B430C0* + ID_OUI_FROM_DATABASE=York Instruments Ltd + +OUI:B431B8* + ID_OUI_FROM_DATABASE=Aviwest + +OUI:B4346C* + ID_OUI_FROM_DATABASE=MATSUNICHI DIGITAL TECHNOLOGY (HONG KONG) LIMITED + +OUI:B43564* + ID_OUI_FROM_DATABASE=Fujian Tian Cheng Electron Science & Technical Development Co.,Ltd. + +OUI:B435F7* + ID_OUI_FROM_DATABASE=Zhejiang Pearmain Electronics Co.ltd. + +OUI:B436A9* + ID_OUI_FROM_DATABASE=Fibocom Wireless Inc. + +OUI:B436E3* + ID_OUI_FROM_DATABASE=KBVISION GROUP + +OUI:B43741* + ID_OUI_FROM_DATABASE=Consert, Inc. + +OUI:B437D10* + ID_OUI_FROM_DATABASE=Lezyne INC USA + +OUI:B437D11* + ID_OUI_FROM_DATABASE=Alturna Networks + +OUI:B437D12* + ID_OUI_FROM_DATABASE=Fibersystem AB + +OUI:B437D13* + ID_OUI_FROM_DATABASE=DIMTON CO.,LTD. + +OUI:B437D14* + ID_OUI_FROM_DATABASE=KOMSIS ELEKTRONIK SISTEMLERI SAN. TIC. LTD.STI + +OUI:B437D15* + ID_OUI_FROM_DATABASE=Stratom, Inc. + +OUI:B437D16* + ID_OUI_FROM_DATABASE=Yireh Auto Tech Co.,Ltd. + +OUI:B437D17* + ID_OUI_FROM_DATABASE=GE Power Management + +OUI:B437D18* + ID_OUI_FROM_DATABASE=eInfochips Limited + +OUI:B437D19* + ID_OUI_FROM_DATABASE=Nanjing yuekong Intelligent Technology + +OUI:B437D1A* + ID_OUI_FROM_DATABASE=Axiomatic Technologies Corporation + +OUI:B437D1B* + ID_OUI_FROM_DATABASE=NSI Co., Ltd. + +OUI:B437D1C* + ID_OUI_FROM_DATABASE=NANJING PUTIAN TELECOMMUNICATIONS TECHNOLOGY CO.,LTD. + +OUI:B437D1D* + ID_OUI_FROM_DATABASE=ZXY Sport Tracking + +OUI:B437D1E* + ID_OUI_FROM_DATABASE=Union Tecnologica Noxium S.L. + +OUI:B437D1F* + ID_OUI_FROM_DATABASE=Private + +OUI:B43934* + ID_OUI_FROM_DATABASE=Pen Generations, Inc. + +OUI:B43939* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:B439D6* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP + +OUI:B43A28* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B43DB2* + ID_OUI_FROM_DATABASE=Degreane Horizon + +OUI:B43E3B* + ID_OUI_FROM_DATABASE=Viableware, Inc + +OUI:B440A4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B4417A* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:B4430D* + ID_OUI_FROM_DATABASE=Broadlink Pty Ltd + +OUI:B44326* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B4475E* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:B447F5* + ID_OUI_FROM_DATABASE=Earda Technologies co Ltd + +OUI:B44BD2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B44BD60* + ID_OUI_FROM_DATABASE=G4S Monitoring Technologies Ltd + +OUI:B44BD61* + ID_OUI_FROM_DATABASE=SHENZHEN TITA INTERACTIVE TECHNOLOGY CO.,LTD + +OUI:B44BD62* + ID_OUI_FROM_DATABASE=Shenzhen Cudy Technology Co., Ltd. + +OUI:B44BD63* + ID_OUI_FROM_DATABASE=Huizhou Sunoda Technology Co. Ltd + +OUI:B44BD64* + ID_OUI_FROM_DATABASE=Shenzhen Hi-Net Technology Co., Ltd. + +OUI:B44BD65* + ID_OUI_FROM_DATABASE=ShenZhen Comstar Technology Company + +OUI:B44BD66* + ID_OUI_FROM_DATABASE=Perspicace Intellegince Technology + +OUI:B44BD67* + ID_OUI_FROM_DATABASE=Taizhou convergence Information technology Co.,LTD + +OUI:B44BD68* + ID_OUI_FROM_DATABASE=Arnouse Digital Devices Corp + +OUI:B44BD69* + ID_OUI_FROM_DATABASE=Qstar Technology Co,Ltd + +OUI:B44BD6A* + ID_OUI_FROM_DATABASE=Shenzhen Huabai Intelligent Technology Co., Ltd. + +OUI:B44BD6B* + ID_OUI_FROM_DATABASE=DongYoung media + +OUI:B44BD6C* + ID_OUI_FROM_DATABASE=Impakt S.A. + +OUI:B44BD6D* + ID_OUI_FROM_DATABASE=ELLETA SOLUTIONS LTD + +OUI:B44BD6E* + ID_OUI_FROM_DATABASE=CHUNGHSIN INTERNATIONAL ELECTRONICS CO.,LTD. + +OUI:B44C3B* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:B44CC2* + ID_OUI_FROM_DATABASE=NR ELECTRIC CO., LTD + +OUI:B44F96* + ID_OUI_FROM_DATABASE=Zhejiang Xinzailing Technology co., ltd + +OUI:B45062* + ID_OUI_FROM_DATABASE=EmBestor Technology Inc. + +OUI:B451F9* + ID_OUI_FROM_DATABASE=NB Software + +OUI:B45253* + ID_OUI_FROM_DATABASE=Seagate Technology + +OUI:B4527D* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:B4527E* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:B452A9* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:B45459* + ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd. + +OUI:B45570* + ID_OUI_FROM_DATABASE=Borea + +OUI:B456B9* + ID_OUI_FROM_DATABASE=Teraspek Technologies Co.,Ltd + +OUI:B45861* + ID_OUI_FROM_DATABASE=CRemote, LLC + +OUI:B45CA4* + ID_OUI_FROM_DATABASE=Thing-talk Wireless Communication Technologies Corporation Limited + +OUI:B45D50* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:B46077* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. + +OUI:B461FF* + ID_OUI_FROM_DATABASE=Lumigon A/S + +OUI:B46238* + ID_OUI_FROM_DATABASE=Exablox + +OUI:B46293* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B462AD* + ID_OUI_FROM_DATABASE=Elysia Germany GmbH + +OUI:B46698* + ID_OUI_FROM_DATABASE=Zealabs srl + +OUI:B467E9* + ID_OUI_FROM_DATABASE=Qingdao GoerTek Technology Co., Ltd. + +OUI:B46921* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B46BFC* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B46C47* + ID_OUI_FROM_DATABASE=Panasonic Appliances Company + +OUI:B46D35* + ID_OUI_FROM_DATABASE=Dalian Seasky Automation Co;Ltd + +OUI:B46D83* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B46E08* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B47356* + ID_OUI_FROM_DATABASE=Hangzhou Treebear Networking Co., Ltd. + +OUI:B47443* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B47447* + ID_OUI_FROM_DATABASE=CoreOS + +OUI:B4749F* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:B4750E* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:B47748* + ID_OUI_FROM_DATABASE=Shenzhen Neoway Technology Co.,Ltd. + +OUI:B479A7* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:B479C8* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:B47AF1* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:B47C29* + ID_OUI_FROM_DATABASE=Shenzhen Guzidi Technology Co.,Ltd + +OUI:B47C59* + ID_OUI_FROM_DATABASE=Jiangsu Hengxin Technology Co.,Ltd. + +OUI:B47C9C* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:B47F5E* + ID_OUI_FROM_DATABASE=Foresight Manufacture (S) Pte Ltd + +OUI:B48107* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + +OUI:B481BF* + ID_OUI_FROM_DATABASE=Meta-Networks, LLC + +OUI:B48255* + ID_OUI_FROM_DATABASE=Research Products Corporation + +OUI:B4827B* + ID_OUI_FROM_DATABASE=AKG Acoustics GmbH + +OUI:B482C5* + ID_OUI_FROM_DATABASE=Relay2, Inc. + +OUI:B482FE* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:B48547* + ID_OUI_FROM_DATABASE=Amptown System Company GmbH + +OUI:B48655* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B48910* + ID_OUI_FROM_DATABASE=Coster T.E. S.P.A. + +OUI:B48B19* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B4944E* + ID_OUI_FROM_DATABASE=WeTelecom Co., Ltd. + +OUI:B49691* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B49842* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:B4994C* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:B499BA* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:B49A95* + ID_OUI_FROM_DATABASE=Shenzhen Boomtech Industrial Corporation + +OUI:B49CDF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B49D0B* + ID_OUI_FROM_DATABASE=BQ + +OUI:B49DB4* + ID_OUI_FROM_DATABASE=Axion Technologies Inc. + +OUI:B49EAC* + ID_OUI_FROM_DATABASE=Imagik Int'l Corp + +OUI:B49EE6* + ID_OUI_FROM_DATABASE=SHENZHEN TECHNOLOGY CO LTD + +OUI:B4A2EB0* + ID_OUI_FROM_DATABASE=QKM Technology(Dongguan)Co.,Ltd + +OUI:B4A2EB1* + ID_OUI_FROM_DATABASE=DCI International, LLC. + +OUI:B4A2EB2* + ID_OUI_FROM_DATABASE=Katerra Inc + +OUI:B4A2EB3* + ID_OUI_FROM_DATABASE=Canaan Creative Co.,Ltd. + +OUI:B4A2EB4* + ID_OUI_FROM_DATABASE=Softel SA de CV + +OUI:B4A2EB5* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:B4A2EB6* + ID_OUI_FROM_DATABASE=ShenZhen Lark Acoustics Co., Ltd. + +OUI:B4A2EB7* + ID_OUI_FROM_DATABASE=Kona I + +OUI:B4A2EB8* + ID_OUI_FROM_DATABASE=SHENZHEN ZHUIFENGMA TECHNOLOGY CO., LTD + +OUI:B4A2EB9* + ID_OUI_FROM_DATABASE=CURRENT WAYS, INC. + +OUI:B4A2EBA* + ID_OUI_FROM_DATABASE=Hengkang(Hangzhou)Co.,Ltd + +OUI:B4A2EBB* + ID_OUI_FROM_DATABASE=Quantitec GmbH + +OUI:B4A2EBC* + ID_OUI_FROM_DATABASE=Shanghai Shenou Communication Equipment Co., Ltd. + +OUI:B4A2EBD* + ID_OUI_FROM_DATABASE=SALZBRENNER media GmbH + +OUI:B4A2EBE* + ID_OUI_FROM_DATABASE=Dongguan Finslink Communication Technology Co.,Ltd. + +OUI:B4A305* + ID_OUI_FROM_DATABASE=XIAMEN YAXON NETWORK CO., LTD. + +OUI:B4A382* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:B4A4B5* + ID_OUI_FROM_DATABASE=Zen Eye Co.,Ltd + +OUI:B4A4E3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B4A5A9* + ID_OUI_FROM_DATABASE=MODI GmbH + +OUI:B4A5AC* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:B4A5EF* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:B4A828* + ID_OUI_FROM_DATABASE=Shenzhen Concox Information Technology Co., Ltd + +OUI:B4A82B* + ID_OUI_FROM_DATABASE=Histar Digital Electronics Co., Ltd. + +OUI:B4A898* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:B4A8B9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B4A94F* + ID_OUI_FROM_DATABASE=MERCURY CORPORATION + +OUI:B4A95A* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:B4A984* + ID_OUI_FROM_DATABASE=Symantec Corporation + +OUI:B4A9FC* + ID_OUI_FROM_DATABASE=Quanta Computer Inc. + +OUI:B4A9FE* + ID_OUI_FROM_DATABASE=GHIA Technology (Shenzhen) LTD + +OUI:B4AA4D* + ID_OUI_FROM_DATABASE=Ensequence, Inc. + +OUI:B4AB2C* + ID_OUI_FROM_DATABASE=MtM Technology Corporation + +OUI:B4AE2B* + ID_OUI_FROM_DATABASE=Microsoft + +OUI:B4AE6F* + ID_OUI_FROM_DATABASE=Circle Reliance, Inc DBA Cranberry Networks + +OUI:B4B017* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:B4B055* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B4B15A* + ID_OUI_FROM_DATABASE=Siemens AG Energy Management Division + +OUI:B4B265* + ID_OUI_FROM_DATABASE=DAEHO I&T + +OUI:B4B362* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:B4B384* + ID_OUI_FROM_DATABASE=ShenZhen Figigantic Electronic Co.,Ltd + +OUI:B4B52F* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:B4B542* + ID_OUI_FROM_DATABASE=Hubbell Power Systems, Inc. + +OUI:B4B5AF* + ID_OUI_FROM_DATABASE=Minsung Electronics + +OUI:B4B676* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B4B686* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:B4B859* + ID_OUI_FROM_DATABASE=Texa Spa + +OUI:B4B88D* + ID_OUI_FROM_DATABASE=Thuh Company + +OUI:B4BC7C* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:B4BFF6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B4C0F5* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:B4C170* + ID_OUI_FROM_DATABASE=Yi chip Microelectronics (Hangzhou) Co., Ltd + +OUI:B4C44E* + ID_OUI_FROM_DATABASE=VXL eTech Pvt Ltd + +OUI:B4C476* + ID_OUI_FROM_DATABASE=Wuhan Maritime Communication Research Institute + +OUI:B4C4FC* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:B4C62E* + ID_OUI_FROM_DATABASE=Molex CMS + +OUI:B4C6F8* + ID_OUI_FROM_DATABASE=Axilspot Communication + +OUI:B4C799* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:B4C810* + ID_OUI_FROM_DATABASE=UMPI Elettronica + +OUI:B4C9B9* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:B4CB57* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:B4CC04* + ID_OUI_FROM_DATABASE=Piranti + +OUI:B4CCE9* + ID_OUI_FROM_DATABASE=PROSYST + +OUI:B4CD27* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B4CE40* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B4CEF6* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:B4CEFE* + ID_OUI_FROM_DATABASE=James Czekaj + +OUI:B4CFDB* + ID_OUI_FROM_DATABASE=Shenzhen Jiuzhou Electric Co.,LTD + +OUI:B4CFE0* + ID_OUI_FROM_DATABASE=Sichuan tianyi kanghe communications co., LTD + +OUI:B4D0A9* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:B4D135* + ID_OUI_FROM_DATABASE=Cloudistics + +OUI:B4D5BD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B4D64E* + ID_OUI_FROM_DATABASE=Caldero Limited + +OUI:B4D8A9* + ID_OUI_FROM_DATABASE=BetterBots + +OUI:B4D8DE* + ID_OUI_FROM_DATABASE=iota Computing, Inc. + +OUI:B4DC09* + ID_OUI_FROM_DATABASE=Guangzhou Dawei Communication Co.,Ltd + +OUI:B4DD15* + ID_OUI_FROM_DATABASE=ControlThings Oy Ab + +OUI:B4DDD0* + ID_OUI_FROM_DATABASE=Continental Automotive Hungary Kft + +OUI:B4DE31* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B4DEDF* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:B4DF3B* + ID_OUI_FROM_DATABASE=Chromlech + +OUI:B4DFFA* + ID_OUI_FROM_DATABASE=Litemax Electronics Inc. + +OUI:B4E01D* + ID_OUI_FROM_DATABASE=CONCEPTION ELECTRONIQUE + +OUI:B4E0CD* + ID_OUI_FROM_DATABASE=Fusion-io, Inc + +OUI:B4E10F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:B4E1C4* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:B4E1EB* + ID_OUI_FROM_DATABASE=Private + +OUI:B4E62A* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:B4E62D* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:B4E782* + ID_OUI_FROM_DATABASE=Vivalnk + +OUI:B4E842* + ID_OUI_FROM_DATABASE=Hong Kong Bouffalo Lab Limited + +OUI:B4E8C9* + ID_OUI_FROM_DATABASE=XADA Technologies + +OUI:B4E9A3* + ID_OUI_FROM_DATABASE=port industrial automation GmbH + +OUI:B4E9B0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B4EC02* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:B4ECF2* + ID_OUI_FROM_DATABASE=Shanghai Listent Medical Tech Co., Ltd. + +OUI:B4ED19* + ID_OUI_FROM_DATABASE=Pie Digital, Inc. + +OUI:B4ED54* + ID_OUI_FROM_DATABASE=Wohler Technologies + +OUI:B4EE25* + ID_OUI_FROM_DATABASE=Shenzhen Belon Technology CO.,LTD + +OUI:B4EEB4* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:B4EED4* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:B4EF04* + ID_OUI_FROM_DATABASE=DAIHAN Scientific Co., Ltd. + +OUI:B4EF39* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B4EFFA* + ID_OUI_FROM_DATABASE=Lemobile Information Technology (Beijing) Co., Ltd. + +OUI:B4F0AB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B4F18C* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:B4F1DA* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:B4F2E8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:B4F323* + ID_OUI_FROM_DATABASE=PETATEL INC. + +OUI:B4F58E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B4F61C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B4F7A1* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:B4F81E* + ID_OUI_FROM_DATABASE=Kinova + +OUI:B4F949* + ID_OUI_FROM_DATABASE=optilink networks pvt ltd + +OUI:B4FBE4* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:B4FBF9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B4FC75* + ID_OUI_FROM_DATABASE=SEMA Electronics(HK) CO.,LTD + +OUI:B4FE8C* + ID_OUI_FROM_DATABASE=Centro Sicurezza Italia SpA + +OUI:B80018* + ID_OUI_FROM_DATABASE=Htel + +OUI:B802A4* + ID_OUI_FROM_DATABASE=Aeonsemi, Inc. + +OUI:B80305* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B80415* + ID_OUI_FROM_DATABASE=Bayan Audio + +OUI:B805AB* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:B80716* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:B80756* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:B808CF* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B808D7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B8098A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B80B9D* + ID_OUI_FROM_DATABASE=ROPEX Industrie-Elektronik GmbH + +OUI:B810D4* + ID_OUI_FROM_DATABASE=Masimo Corporation + +OUI:B813E9* + ID_OUI_FROM_DATABASE=Trace Live Network + +OUI:B81413* + ID_OUI_FROM_DATABASE=Keen High Holding(HK) Ltd. + +OUI:B81619* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:B816DB* + ID_OUI_FROM_DATABASE=CHANT SINCERE CO.,LTD + +OUI:B817C2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B8186F* + ID_OUI_FROM_DATABASE=ORIENTAL MOTOR CO., LTD. + +OUI:B81904* + ID_OUI_FROM_DATABASE=Nokia Shanghai Bell Co., Ltd. + +OUI:B81999* + ID_OUI_FROM_DATABASE=Nesys + +OUI:B81DAA* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:B81F5E* + ID_OUI_FROM_DATABASE=Apption Labs Limited + +OUI:B820E7* + ID_OUI_FROM_DATABASE=Guangzhou Horizontal Information & Network Integration Co. Ltd + +OUI:B8224F* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:B82410* + ID_OUI_FROM_DATABASE=Magneti Marelli Slovakia s.r.o. + +OUI:B8241A* + ID_OUI_FROM_DATABASE=SWEDA INFORMATICA LTDA + +OUI:B824F0* + ID_OUI_FROM_DATABASE=SOYO Technology Development Co., Ltd. + +OUI:B8259A* + ID_OUI_FROM_DATABASE=Thalmic Labs + +OUI:B8266C* + ID_OUI_FROM_DATABASE=ANOV France + +OUI:B826D4* + ID_OUI_FROM_DATABASE=Furukawa Industrial S.A. Produtos Elétricos + +OUI:B827C5* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:B827EB* + ID_OUI_FROM_DATABASE=Raspberry Pi Foundation + +OUI:B8288B* + ID_OUI_FROM_DATABASE=Parker Hannifin Manufacturing (UK) Ltd + +OUI:B829F7* + ID_OUI_FROM_DATABASE=Blaster Tech + +OUI:B82A72* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:B82ADC* + ID_OUI_FROM_DATABASE=EFR Europäische Funk-Rundsteuerung GmbH + +OUI:B82CA0* + ID_OUI_FROM_DATABASE=Resideo + +OUI:B82FCB* + ID_OUI_FROM_DATABASE=CMS Electracom + +OUI:B830A8* + ID_OUI_FROM_DATABASE=Road-Track Telematics Development + +OUI:B831B5* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:B83241* + ID_OUI_FROM_DATABASE=Wuhan Tianyu Information Industry Co., Ltd. + +OUI:B836D8* + ID_OUI_FROM_DATABASE=Videoswitch + +OUI:B83765* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:B83861* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B838CA* + ID_OUI_FROM_DATABASE=Kyokko Tsushin System CO.,LTD + +OUI:B83A08* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:B83A5A* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:B83A7B* + ID_OUI_FROM_DATABASE=Worldplay (Canada) Inc. + +OUI:B83A9D* + ID_OUI_FROM_DATABASE=Alarm.com + +OUI:B83D4E* + ID_OUI_FROM_DATABASE=Shenzhen Cultraview Digital Technology Co.,Ltd Shanghai Branch + +OUI:B83E59* + ID_OUI_FROM_DATABASE=Roku, Inc. + +OUI:B8415F* + ID_OUI_FROM_DATABASE=ASP AG + +OUI:B841A4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B843E4* + ID_OUI_FROM_DATABASE=Vlatacom + +OUI:B844D9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B847C6* + ID_OUI_FROM_DATABASE=SanJet Technology Corp. + +OUI:B84DEE* + ID_OUI_FROM_DATABASE=Hisense broadband multimedia technology Co.,Ltd + +OUI:B84FD5* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:B85001* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:B853AC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B85510* + ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. + +OUI:B856BD* + ID_OUI_FROM_DATABASE=ITT LLC + +OUI:B857D8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B85810* + ID_OUI_FROM_DATABASE=NUMERA, INC. + +OUI:B8599F* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:B85A73* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B85AF7* + ID_OUI_FROM_DATABASE=Ouya, Inc + +OUI:B85AFE* + ID_OUI_FROM_DATABASE=Handaer Communication Technology (Beijing) Co., Ltd + +OUI:B85D0A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B85E7B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B86091* + ID_OUI_FROM_DATABASE=Onnet Technologies and Innovations LLC + +OUI:B86142* + ID_OUI_FROM_DATABASE=Beijing Tricolor Technology Co., Ltd + +OUI:B8616F* + ID_OUI_FROM_DATABASE=Accton Technology Corp + +OUI:B8621F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B8634D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B86392* + ID_OUI_FROM_DATABASE=GUANGDONG GENIUS TECHNOLOGY CO., LTD. + +OUI:B863BC* + ID_OUI_FROM_DATABASE=ROBOTIS, Co, Ltd + +OUI:B86491* + ID_OUI_FROM_DATABASE=CK Telecom Ltd + +OUI:B8653B* + ID_OUI_FROM_DATABASE=Bolymin, Inc. + +OUI:B86685* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:B869C2* + ID_OUI_FROM_DATABASE=Sunitec Enterprise Co., Ltd. + +OUI:B869F4* + ID_OUI_FROM_DATABASE=Routerboard.com + +OUI:B86A97* + ID_OUI_FROM_DATABASE=Edgecore Networks Corporation + +OUI:B86B23* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:B86CE8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B870F4* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:B87424* + ID_OUI_FROM_DATABASE=Viessmann Elektronik GmbH + +OUI:B87447* + ID_OUI_FROM_DATABASE=Convergence Technologies + +OUI:B875C0* + ID_OUI_FROM_DATABASE=PayPal, Inc. + +OUI:B8763F* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:B877C3* + ID_OUI_FROM_DATABASE=METER Group + +OUI:B87826* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:B8782E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B87879* + ID_OUI_FROM_DATABASE=Roche Diagnostics GmbH + +OUI:B8797E* + ID_OUI_FROM_DATABASE=Secure Meters (UK) Limited + +OUI:B87AC9* + ID_OUI_FROM_DATABASE=Siemens Ltd. + +OUI:B87BC5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B87C6F* + ID_OUI_FROM_DATABASE=NXP (China) Management Ltd. + +OUI:B87CF2* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:B88198* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B88303* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:B88584* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:B88687* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:B8871E* + ID_OUI_FROM_DATABASE=Good Mind Industries Co., Ltd. + +OUI:B887A8* + ID_OUI_FROM_DATABASE=Step Ahead Innovations Inc. + +OUI:B887C6* + ID_OUI_FROM_DATABASE=Prudential Technology co.,LTD + +OUI:B888E3* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:B88981* + ID_OUI_FROM_DATABASE=Chengdu InnoThings Technology Co., Ltd. + +OUI:B889CA* + ID_OUI_FROM_DATABASE=ILJIN ELECTRIC Co., Ltd. + +OUI:B88A60* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B88AEC* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:B88D12* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B88E3A* + ID_OUI_FROM_DATABASE=Infinite Technologies JLT + +OUI:B88E82* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:B88EC6* + ID_OUI_FROM_DATABASE=Stateless Networks + +OUI:B88EDF* + ID_OUI_FROM_DATABASE=Zencheer Communication Technology Co., Ltd. + +OUI:B88F14* + ID_OUI_FROM_DATABASE=Analytica GmbH + +OUI:B88FB4* + ID_OUI_FROM_DATABASE=JABIL CIRCUIT ITALIA S.R.L + +OUI:B89047* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B891C9* + ID_OUI_FROM_DATABASE=Handreamnet + +OUI:B8921D* + ID_OUI_FROM_DATABASE=BG T&A + +OUI:B89436* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B894D2* + ID_OUI_FROM_DATABASE=Retail Innovation HTT AB + +OUI:B89674* + ID_OUI_FROM_DATABASE=AllDSP GmbH & Co. KG + +OUI:B8975A* + ID_OUI_FROM_DATABASE=BIOSTAR Microtech Int'l Corp. + +OUI:B898B0* + ID_OUI_FROM_DATABASE=Atlona Inc. + +OUI:B898F7* + ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co,Ltd.ShenZhen + +OUI:B89919* + ID_OUI_FROM_DATABASE=7signal Solutions, Inc + +OUI:B899AE* + ID_OUI_FROM_DATABASE=Shenzhen MiaoMing Intelligent Technology Co.,Ltd + +OUI:B899B0* + ID_OUI_FROM_DATABASE=Cohere Technologies + +OUI:B89A2A* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B89A9A* + ID_OUI_FROM_DATABASE=Xin Shi Jia Technology (Beijing) Co.,Ltd + +OUI:B89ACD* + ID_OUI_FROM_DATABASE=ELITE OPTOELECTRONIC(ASIA)CO.,LTD + +OUI:B89AED* + ID_OUI_FROM_DATABASE=OceanServer Technology, Inc + +OUI:B89BC9* + ID_OUI_FROM_DATABASE=SMC Networks Inc + +OUI:B89BE4* + ID_OUI_FROM_DATABASE=ABB Power Systems Power Generation + +OUI:B89F09* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:B8A175* + ID_OUI_FROM_DATABASE=Roku, Inc. + +OUI:B8A386* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:B8A3E0* + ID_OUI_FROM_DATABASE=BenRui Technology Co.,Ltd + +OUI:B8A44F* + ID_OUI_FROM_DATABASE=Axis Communications AB + +OUI:B8A58D* + ID_OUI_FROM_DATABASE=Axe Group Holdings Limited + +OUI:B8A8AF* + ID_OUI_FROM_DATABASE=Logic S.p.A. + +OUI:B8AC6F* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:B8AD3E* + ID_OUI_FROM_DATABASE=BLUECOM + +OUI:B8AE6E* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:B8AEED* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:B8AF67* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:B8B1C7* + ID_OUI_FROM_DATABASE=BT&COM CO.,LTD + +OUI:B8B2EB* + ID_OUI_FROM_DATABASE=Googol Technology (HK) Limited + +OUI:B8B2F8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B8B3DC* + ID_OUI_FROM_DATABASE=DEREK (SHAOGUAN) LIMITED + +OUI:B8B42E* + ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co,Ltd.ShenZhen + +OUI:B8B7D7* + ID_OUI_FROM_DATABASE=2GIG Technologies + +OUI:B8B7F1* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:B8B81E* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B8B94E* + ID_OUI_FROM_DATABASE=Shenzhen iBaby Labs, Inc. + +OUI:B8BA68* + ID_OUI_FROM_DATABASE=Xi'an Jizhong Digital Communication Co.,Ltd + +OUI:B8BA72* + ID_OUI_FROM_DATABASE=Cynove + +OUI:B8BB23* + ID_OUI_FROM_DATABASE=Guangdong Nufront CSC Co., Ltd + +OUI:B8BB6D* + ID_OUI_FROM_DATABASE=ENERES Co.,Ltd. + +OUI:B8BBAF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B8BC1B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B8BC5B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B8BD79* + ID_OUI_FROM_DATABASE=TrendPoint Systems + +OUI:B8BEBF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:B8BEF4* + ID_OUI_FROM_DATABASE=devolo AG + +OUI:B8BF83* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:B8C111* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B8C1A2* + ID_OUI_FROM_DATABASE=Dragon Path Technologies Co., Limited + +OUI:B8C227* + ID_OUI_FROM_DATABASE=PSTec + +OUI:B8C253* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:B8C385* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B8C3BF* + ID_OUI_FROM_DATABASE=Henan Chengshi NetWork Technology Co.,Ltd + +OUI:B8C46F* + ID_OUI_FROM_DATABASE=PRIMMCON INDUSTRIES INC + +OUI:B8C68E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B8C6AA* + ID_OUI_FROM_DATABASE=Earda Technologies co Ltd + +OUI:B8C716* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:B8C74A* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:B8C75D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B8C855* + ID_OUI_FROM_DATABASE=Shanghai GBCOM Communication Technology Co.,Ltd. + +OUI:B8C8EB* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:B8C9B5* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:B8CA04* + ID_OUI_FROM_DATABASE=Holtek Semiconductor Inc. + +OUI:B8CA3A* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:B8CD93* + ID_OUI_FROM_DATABASE=Penetek, Inc + +OUI:B8CDA7* + ID_OUI_FROM_DATABASE=Maxeler Technologies Ltd. + +OUI:B8CEF6* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:B8D06F* + ID_OUI_FROM_DATABASE=GUANGZHOU HKUST FOK YING TUNG RESEARCH INSTITUTE + +OUI:B8D49D* + ID_OUI_FROM_DATABASE=M Seven System Ltd. + +OUI:B8D4E7* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:B8D50B* + ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd + +OUI:B8D526* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:B8D7AF* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:B8D8120* + ID_OUI_FROM_DATABASE=Glamo Inc. + +OUI:B8D8121* + ID_OUI_FROM_DATABASE=VOTEM + +OUI:B8D8122* + ID_OUI_FROM_DATABASE=IPM Sales and service Co.,Ltd. + +OUI:B8D8123* + ID_OUI_FROM_DATABASE=iModesty Technology Corp. + +OUI:B8D8124* + ID_OUI_FROM_DATABASE=V5 Technology Corporation + +OUI:B8D8125* + ID_OUI_FROM_DATABASE=XIAMEN XINDECO LTD. + +OUI:B8D8126* + ID_OUI_FROM_DATABASE=Vonger Electronic Technology Co.,Ltd. + +OUI:B8D8127* + ID_OUI_FROM_DATABASE=Neuropace Inc. + +OUI:B8D8128* + ID_OUI_FROM_DATABASE=Visual Productions BV + +OUI:B8D8129* + ID_OUI_FROM_DATABASE=Entotem LTD + +OUI:B8D812A* + ID_OUI_FROM_DATABASE=Kiwigrid GmbH + +OUI:B8D812B* + ID_OUI_FROM_DATABASE=Docobo Limited + +OUI:B8D812C* + ID_OUI_FROM_DATABASE=Yuwei Info&Tech Development Co.,Ltd + +OUI:B8D812D* + ID_OUI_FROM_DATABASE=Lam Research + +OUI:B8D812E* + ID_OUI_FROM_DATABASE=ZheJiang FangTai Electirc Co., Ltd + +OUI:B8D812F* + ID_OUI_FROM_DATABASE=Private + +OUI:B8D94D* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:B8D9CE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:B8DAF1* + ID_OUI_FROM_DATABASE=Strahlenschutz- Entwicklungs- und Ausruestungsgesellschaft mbH + +OUI:B8DAF7* + ID_OUI_FROM_DATABASE=Advanced Photonics, Inc. + +OUI:B8DB1C* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:B8DC87* + ID_OUI_FROM_DATABASE=IAI Corporation + +OUI:B8DE5E* + ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED + +OUI:B8DF6B* + ID_OUI_FROM_DATABASE=SpotCam Co., Ltd. + +OUI:B8E3B1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:B8E589* + ID_OUI_FROM_DATABASE=Payter BV + +OUI:B8E625* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:B8E779* + ID_OUI_FROM_DATABASE=9Solutions Oy + +OUI:B8E856* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B8E937* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:B8EAAA* + ID_OUI_FROM_DATABASE=ICG NETWORKS CO.,ltd + +OUI:B8ECA3* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:B8EE0E* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:B8EE65* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:B8EE79* + ID_OUI_FROM_DATABASE=YWire Technologies, Inc. + +OUI:B8EF8B* + ID_OUI_FROM_DATABASE=SHENZHEN CANNICE TECHNOLOGY CO.,LTD + +OUI:B8F080* + ID_OUI_FROM_DATABASE=SPS, INC. + +OUI:B8F12A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B8F317* + ID_OUI_FROM_DATABASE=iSun Smasher Communications Private Limited + +OUI:B8F4D0* + ID_OUI_FROM_DATABASE=Herrmann Ultraschalltechnik GmbH & Co. Kg + +OUI:B8F5E7* + ID_OUI_FROM_DATABASE=WayTools, LLC + +OUI:B8F653* + ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + +OUI:B8F6B1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B8F732* + ID_OUI_FROM_DATABASE=Aryaka Networks Inc + +OUI:B8F74A* + ID_OUI_FROM_DATABASE=RCNTEC + +OUI:B8F828* + ID_OUI_FROM_DATABASE=Changshu Gaoshida Optoelectronic Technology Co. Ltd. + +OUI:B8F853* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:B8F883* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:B8F8BE* + ID_OUI_FROM_DATABASE=BLUECOM + +OUI:B8F934* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:B8FC9A* + ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited + +OUI:B8FD32* + ID_OUI_FROM_DATABASE=Zhejiang ROICX Microelectronics + +OUI:B8FF61* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:B8FF6F* + ID_OUI_FROM_DATABASE=Shanghai Typrotech Technology Co.Ltd + +OUI:B8FFB3* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:B8FFFE* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:BC0200* + ID_OUI_FROM_DATABASE=Stewart Audio + +OUI:BC024A* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:BC0543* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:BC0963* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BC0DA5* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:BC0F2B* + ID_OUI_FROM_DATABASE=FORTUNE TECHGROUP CO.,LTD + +OUI:BC0F64* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:BC0FA7* + ID_OUI_FROM_DATABASE=Ouster + +OUI:BC125E* + ID_OUI_FROM_DATABASE=Beijing WisVideo INC. + +OUI:BC1401* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:BC1485* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC14EF* + ID_OUI_FROM_DATABASE=ITON Technology Limited + +OUI:BC15A6* + ID_OUI_FROM_DATABASE=Taiwan Jantek Electronics,Ltd. + +OUI:BC15AC* + ID_OUI_FROM_DATABASE=Vodafone Italia S.p.A. + +OUI:BC1665* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:BC1695* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:BC16F5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:BC1A67* + ID_OUI_FROM_DATABASE=YF Technology Co., Ltd + +OUI:BC1AE4* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:BC1C81* + ID_OUI_FROM_DATABASE=Sichuan iLink Technology Co., Ltd. + +OUI:BC20A4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC20BA* + ID_OUI_FROM_DATABASE=Inspur (Shandong) Electronic Information Co., Ltd + +OUI:BC22FB* + ID_OUI_FROM_DATABASE=RF Industries + +OUI:BC2392* + ID_OUI_FROM_DATABASE=BYD Precision Manufacture Company Ltd. + +OUI:BC25E0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BC25F0* + ID_OUI_FROM_DATABASE=3D Display Technologies Co., Ltd. + +OUI:BC261D* + ID_OUI_FROM_DATABASE=HONG KONG TECON TECHNOLOGY + +OUI:BC2643* + ID_OUI_FROM_DATABASE=Elprotronic Inc. + +OUI:BC26C7* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:BC282C* + ID_OUI_FROM_DATABASE=e-Smart Systems Pvt. Ltd + +OUI:BC2846* + ID_OUI_FROM_DATABASE=NextBIT Computing Pvt. Ltd. + +OUI:BC28D6* + ID_OUI_FROM_DATABASE=Rowley Associates Limited + +OUI:BC2B6B* + ID_OUI_FROM_DATABASE=Beijing Haier IC Design Co.,Ltd + +OUI:BC2BD7* + ID_OUI_FROM_DATABASE=Revogi Innovation Co., Ltd. + +OUI:BC2C55* + ID_OUI_FROM_DATABASE=Bear Flag Design, Inc. + +OUI:BC2D98* + ID_OUI_FROM_DATABASE=ThinGlobal LLC + +OUI:BC2DEF* + ID_OUI_FROM_DATABASE=Realme Chongqing Mobile Telecommunications Corp.,Ltd. + +OUI:BC2E48* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:BC2EF6* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:BC2F3D* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:BC305B* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:BC307D* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:BC307E* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:BC30D9* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:BC325F* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:BC34000* + ID_OUI_FROM_DATABASE=Redvision CCTV + +OUI:BC34001* + ID_OUI_FROM_DATABASE=IPLINK Technology Corp + +OUI:BC34002* + ID_OUI_FROM_DATABASE=LifeSmart + +OUI:BC34003* + ID_OUI_FROM_DATABASE=Altronix Corporation + +OUI:BC34004* + ID_OUI_FROM_DATABASE=Dexcel Design Pvt Ltd + +OUI:BC34005* + ID_OUI_FROM_DATABASE=NDSL, Inc. + +OUI:BC34006* + ID_OUI_FROM_DATABASE=Cameron + +OUI:BC34007* + ID_OUI_FROM_DATABASE=Q-PRODUCTS a. s. + +OUI:BC34008* + ID_OUI_FROM_DATABASE=MATICA TECHNOLOGIES AG + +OUI:BC34009* + ID_OUI_FROM_DATABASE=Shenzhen PHilorise Technical Limited + +OUI:BC3400A* + ID_OUI_FROM_DATABASE=AURALIC LIMITED + +OUI:BC3400B* + ID_OUI_FROM_DATABASE=FARO TECHNOLOGIES, INC. + +OUI:BC3400C* + ID_OUI_FROM_DATABASE=Parlay Labs dba Highfive + +OUI:BC3400D* + ID_OUI_FROM_DATABASE=Hangzhou Linker Digital Technology Co., Ltd + +OUI:BC3400E* + ID_OUI_FROM_DATABASE=LLD Technology Ltd. + +OUI:BC3400F* + ID_OUI_FROM_DATABASE=Private + +OUI:BC35E5* + ID_OUI_FROM_DATABASE=Hydro Systems Company + +OUI:BC3865* + ID_OUI_FROM_DATABASE=JWCNETWORKS + +OUI:BC38D2* + ID_OUI_FROM_DATABASE=Pandachip Limited + +OUI:BC39A6* + ID_OUI_FROM_DATABASE=CSUN System Technology Co.,LTD + +OUI:BC39D9* + ID_OUI_FROM_DATABASE=Z-TEC + +OUI:BC3AEA* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:BC3BAF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BC3D85* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BC3E07* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:BC3E13* + ID_OUI_FROM_DATABASE=Accordance Systems Inc. + +OUI:BC3F4E* + ID_OUI_FROM_DATABASE=Teleepoch Ltd + +OUI:BC3F8F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BC4100* + ID_OUI_FROM_DATABASE=CODACO ELECTRONIC s.r.o. + +OUI:BC4101* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:BC428C* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:BC4377* + ID_OUI_FROM_DATABASE=Hang Zhou Huite Technology Co.,ltd. + +OUI:BC4434* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:BC4486* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC44B0* + ID_OUI_FROM_DATABASE=Elastifile + +OUI:BC452E* + ID_OUI_FROM_DATABASE=Knowledge Development for POF S.L. + +OUI:BC4699* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:BC4760* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC4A56* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:BC4B79* + ID_OUI_FROM_DATABASE=SensingTek + +OUI:BC4CC4* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BC4DFB* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:BC4E3C* + ID_OUI_FROM_DATABASE=CORE STAFF CO., LTD. + +OUI:BC4E5D* + ID_OUI_FROM_DATABASE=ZhongMiao Technology Co., Ltd. + +OUI:BC51FE* + ID_OUI_FROM_DATABASE=Swann communications Pty Ltd + +OUI:BC52B4* + ID_OUI_FROM_DATABASE=Nokia + +OUI:BC52B7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BC542F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:BC5436* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BC5451* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC54F9* + ID_OUI_FROM_DATABASE=Drogoo Technology Co., Ltd. + +OUI:BC54FC* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:BC5C4C* + ID_OUI_FROM_DATABASE=ELECOM CO.,LTD. + +OUI:BC5EA1* + ID_OUI_FROM_DATABASE=PsiKick, Inc. + +OUI:BC5FF4* + ID_OUI_FROM_DATABASE=ASRock Incorporation + +OUI:BC5FF6* + ID_OUI_FROM_DATABASE=MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:BC6010* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:BC60A7* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:BC620E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BC629F* + ID_OUI_FROM_DATABASE=Telenet Systems P. Ltd. + +OUI:BC62D2* + ID_OUI_FROM_DATABASE=Genexis International B.V. + +OUI:BC644B* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:BC66410* + ID_OUI_FROM_DATABASE=InSync Technology Ltd + +OUI:BC66411* + ID_OUI_FROM_DATABASE=Global China Technology Limited + +OUI:BC66412* + ID_OUI_FROM_DATABASE=Process-Electronic Sp. z o.o. + +OUI:BC66413* + ID_OUI_FROM_DATABASE=Solectria Renewables, LLC + +OUI:BC66414* + ID_OUI_FROM_DATABASE=ARGUS-SPECTRUM + +OUI:BC66415* + ID_OUI_FROM_DATABASE=Scientific Games + +OUI:BC66416* + ID_OUI_FROM_DATABASE=Intuitive Surgical, Inc + +OUI:BC66417* + ID_OUI_FROM_DATABASE=VSN Mobil + +OUI:BC66418* + ID_OUI_FROM_DATABASE=Shenzhen Yaguang communication CO.,LTD + +OUI:BC66419* + ID_OUI_FROM_DATABASE=Shenzhen General Measure Technology Co., Ltd + +OUI:BC6641A* + ID_OUI_FROM_DATABASE=EBlink + +OUI:BC6641B* + ID_OUI_FROM_DATABASE=Sidus Novum Sp. z o. o. + +OUI:BC6641C* + ID_OUI_FROM_DATABASE=Shenzhen Crave Communication Co.,ltd + +OUI:BC6641D* + ID_OUI_FROM_DATABASE=UtilLighting Co.,Ltd. + +OUI:BC6641E* + ID_OUI_FROM_DATABASE=Lucent Trans Electronics Co., Ltd + +OUI:BC6641F* + ID_OUI_FROM_DATABASE=Private + +OUI:BC66DE* + ID_OUI_FROM_DATABASE=Shadow Creator Information Technology Co.,Ltd. + +OUI:BC671C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:BC6778* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BC6784* + ID_OUI_FROM_DATABASE=Environics Oy + +OUI:BC6A16* + ID_OUI_FROM_DATABASE=tdvine + +OUI:BC6A29* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:BC6A2F* + ID_OUI_FROM_DATABASE=Henge Docks LLC + +OUI:BC6A44* + ID_OUI_FROM_DATABASE=Commend International GmbH + +OUI:BC6B4D* + ID_OUI_FROM_DATABASE=Nokia + +OUI:BC6C21* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BC6E64* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:BC6E76* + ID_OUI_FROM_DATABASE=Green Energy Options Ltd + +OUI:BC71C1* + ID_OUI_FROM_DATABASE=XTrillion, Inc. + +OUI:BC72B1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC74D7* + ID_OUI_FROM_DATABASE=HangZhou JuRu Technology CO.,LTD + +OUI:BC7536* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:BC7574* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BC7596* + ID_OUI_FROM_DATABASE=Beijing Broadwit Technology Co., Ltd. + +OUI:BC764E* + ID_OUI_FROM_DATABASE=Rackspace US, Inc. + +OUI:BC765E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC7670* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BC7737* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:BC779F* + ID_OUI_FROM_DATABASE=SBM Co., Ltd. + +OUI:BC79AD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC7ABF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC7DD1* + ID_OUI_FROM_DATABASE=Radio Data Comms + +OUI:BC7FA4* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:BC811F* + ID_OUI_FROM_DATABASE=Ingate Systems + +OUI:BC8199* + ID_OUI_FROM_DATABASE=BASIC Co.,Ltd. + +OUI:BC825D* + ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD. + +OUI:BC8385* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:BC83A7* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + +OUI:BC851F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BC8556* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:BC8893* + ID_OUI_FROM_DATABASE=VILLBAU Ltd. + +OUI:BC88C3* + ID_OUI_FROM_DATABASE=Ningbo Dooya Mechanic & Electronic Technology Co., Ltd + +OUI:BC8AA3* + ID_OUI_FROM_DATABASE=NHN Entertainment + +OUI:BC8AE8* + ID_OUI_FROM_DATABASE=QING DAO HAIER TELECOM CO.,LTD. + +OUI:BC8B55* + ID_OUI_FROM_DATABASE=NPP ELIKS America Inc. DBA T&M Atlantic + +OUI:BC8CCD* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:BC8D0E* + ID_OUI_FROM_DATABASE=Nokia + +OUI:BC903A* + ID_OUI_FROM_DATABASE=Robert Bosch GmbH + +OUI:BC91B5* + ID_OUI_FROM_DATABASE=Infinix mobility limited + +OUI:BC926B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BC9325* + ID_OUI_FROM_DATABASE=Ningbo Joyson Preh Car Connect Co.,Ltd. + +OUI:BC9680* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:BC97400* + ID_OUI_FROM_DATABASE=Alpha ESS Co., Ltd. + +OUI:BC97401* + ID_OUI_FROM_DATABASE=comtac AG + +OUI:BC97402* + ID_OUI_FROM_DATABASE=Lattec I/S + +OUI:BC97403* + ID_OUI_FROM_DATABASE=Precision Galaxy Pvt. Ltd + +OUI:BC97404* + ID_OUI_FROM_DATABASE=Wind Mobility Technology (Beijing) Co., Ltd + +OUI:BC97405* + ID_OUI_FROM_DATABASE=Shanghai Laisi Information Technology Co.,Ltd + +OUI:BC97406* + ID_OUI_FROM_DATABASE=Shenzhen Colorwin Optical Technology Co.,Ltd + +OUI:BC97407* + ID_OUI_FROM_DATABASE=Airfi Oy AB + +OUI:BC97408* + ID_OUI_FROM_DATABASE=Gaodi Rus + +OUI:BC97409* + ID_OUI_FROM_DATABASE=Direct Communication Solutions + +OUI:BC9740A* + ID_OUI_FROM_DATABASE=Amap Information Technology Co., Ltd + +OUI:BC9740B* + ID_OUI_FROM_DATABASE=ForoTel + +OUI:BC9740C* + ID_OUI_FROM_DATABASE=LISTEC GmbH + +OUI:BC9740D* + ID_OUI_FROM_DATABASE=Rollock Oy + +OUI:BC9740E* + ID_OUI_FROM_DATABASE=B4ComTechnologies LLC + +OUI:BC97E1* + ID_OUI_FROM_DATABASE=Broadcom Limited + +OUI:BC9889* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:BC98DF* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:BC9911* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:BC99BC* + ID_OUI_FROM_DATABASE=FonSee Technology Inc. + +OUI:BC9B68* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:BC9C31* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BC9CC5* + ID_OUI_FROM_DATABASE=Beijing Huafei Technology Co., Ltd. + +OUI:BC9DA5* + ID_OUI_FROM_DATABASE=DASCOM Europe GmbH + +OUI:BC9FE4* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:BC9FEF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BCA042* + ID_OUI_FROM_DATABASE=SHANGHAI FLYCO ELECTRICAL APPLIANCE CO.,LTD + +OUI:BCA13A* + ID_OUI_FROM_DATABASE=SES-imagotag + +OUI:BCA4E1* + ID_OUI_FROM_DATABASE=Nabto + +OUI:BCA511* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:BCA58B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BCA8A6* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:BCA920* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BCA9D6* + ID_OUI_FROM_DATABASE=Cyber-Rain, Inc. + +OUI:BCAB7C* + ID_OUI_FROM_DATABASE=TRnP KOREA Co Ltd + +OUI:BCAD28* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:BCADAB* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:BCAEC5* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:BCAF91* + ID_OUI_FROM_DATABASE=TE Connectivity Sensor Solutions + +OUI:BCB0E7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BCB181* + ID_OUI_FROM_DATABASE=SHARP CORPORATION + +OUI:BCB1F3* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BCB22B* + ID_OUI_FROM_DATABASE=EM-Tech + +OUI:BCB308* + ID_OUI_FROM_DATABASE=HONGKONG RAGENTEK COMMUNICATION TECHNOLOGY CO.,LIMITED + +OUI:BCB852* + ID_OUI_FROM_DATABASE=Cybera, Inc. + +OUI:BCB863* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BCBAC2* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:BCBAE1* + ID_OUI_FROM_DATABASE=AREC Inc. + +OUI:BCBBC9* + ID_OUI_FROM_DATABASE=Kellendonk Elektronik GmbH + +OUI:BCBC46* + ID_OUI_FROM_DATABASE=SKS Welding Systems GmbH + +OUI:BCC00F* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:BCC168* + ID_OUI_FROM_DATABASE=DinBox Sverige AB + +OUI:BCC23A* + ID_OUI_FROM_DATABASE=Thomson Video Networks + +OUI:BCC31B* + ID_OUI_FROM_DATABASE=Kygo Life A + +OUI:BCC342* + ID_OUI_FROM_DATABASE=Panasonic Communications Co., Ltd. + +OUI:BCC493* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:BCC61A* + ID_OUI_FROM_DATABASE=SPECTRA EMBEDDED SYSTEMS + +OUI:BCC6DB* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:BCC810* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:BCCAB5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:BCCD45* + ID_OUI_FROM_DATABASE=VOISMART + +OUI:BCCF4F* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:BCCFCC* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:BCD11F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BCD165* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:BCD177* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:BCD1D3* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:BCD5B6* + ID_OUI_FROM_DATABASE=d2d technologies + +OUI:BCD713* + ID_OUI_FROM_DATABASE=Owl Labs + +OUI:BCD767* + ID_OUI_FROM_DATABASE=Private + +OUI:BCD940* + ID_OUI_FROM_DATABASE=ASR Co,.Ltd. + +OUI:BCDDC2* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:BCE09D* + ID_OUI_FROM_DATABASE=Eoslink + +OUI:BCE143* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BCE265* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:BCE59F* + ID_OUI_FROM_DATABASE=WATERWORLD Technology Co.,LTD + +OUI:BCE63F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:BCE67C* + ID_OUI_FROM_DATABASE=Cambium Networks Limited + +OUI:BCE767* + ID_OUI_FROM_DATABASE=Quanzhou TDX Electronics Co., Ltd + +OUI:BCE796* + ID_OUI_FROM_DATABASE=Wireless CCTV Ltd + +OUI:BCEA2B* + ID_OUI_FROM_DATABASE=CityCom GmbH + +OUI:BCEAFA* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:BCEB5F* + ID_OUI_FROM_DATABASE=Fujian Beifeng Telecom Technology Co., Ltd. + +OUI:BCEC23* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + +OUI:BCEC5D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BCEE7B* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:BCF1F2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:BCF292* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. + +OUI:BCF2AF* + ID_OUI_FROM_DATABASE=devolo AG + +OUI:BCF310* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:BCF5AC* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:BCF61C* + ID_OUI_FROM_DATABASE=Geomodeling Wuxi Technology Co. Ltd. + +OUI:BCF685* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:BCF811* + ID_OUI_FROM_DATABASE=Xiamen DNAKE Technology Co.,Ltd + +OUI:BCF9F2* + ID_OUI_FROM_DATABASE=TEKO + +OUI:BCFE8C* + ID_OUI_FROM_DATABASE=Altronic, LLC + +OUI:BCFED9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:BCFF21* + ID_OUI_FROM_DATABASE=Smart Code(shenzhen)Technology Co.,Ltd + +OUI:BCFFAC* + ID_OUI_FROM_DATABASE=TOPCON CORPORATION + +OUI:BCFFEB* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:C0028D* + ID_OUI_FROM_DATABASE=WINSTAR Display CO.,Ltd + +OUI:C00380* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:C005C2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:C0074A* + ID_OUI_FROM_DATABASE=Brita GmbH + +OUI:C00D7E* + ID_OUI_FROM_DATABASE=Additech, Inc. + +OUI:C010B1* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:C01173* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C011A6* + ID_OUI_FROM_DATABASE=Fort-Telecom ltd. + +OUI:C01242* + ID_OUI_FROM_DATABASE=Alpha Security Products + +OUI:C0132B* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. + +OUI:C0143D* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:C014B8* + ID_OUI_FROM_DATABASE=Nokia + +OUI:C01692* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:C0174D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C01885* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:C01ADA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C01B23* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOM CO.,LTD + +OUI:C01E9B* + ID_OUI_FROM_DATABASE=Pixavi AS + +OUI:C0210D* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:C02250* + ID_OUI_FROM_DATABASE=Koss Corporation + +OUI:C02506* + ID_OUI_FROM_DATABASE=AVM GmbH + +OUI:C0255C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C02567* + ID_OUI_FROM_DATABASE=Nexxt Solutions + +OUI:C025A2* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. + +OUI:C025E9* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:C027B9* + ID_OUI_FROM_DATABASE=Beijing National Railway Research & Design Institute of Signal & Communication Co., Ltd. + +OUI:C0288D* + ID_OUI_FROM_DATABASE=Logitech, Inc + +OUI:C02973* + ID_OUI_FROM_DATABASE=Audyssey Laboratories Inc. + +OUI:C029F3* + ID_OUI_FROM_DATABASE=XySystem + +OUI:C02BFC* + ID_OUI_FROM_DATABASE=iNES. applied informatics GmbH + +OUI:C02C7A* + ID_OUI_FROM_DATABASE=Shenzhen Horn Audio Co.,Ltd. + +OUI:C02DEE* + ID_OUI_FROM_DATABASE=Cuff + +OUI:C02E25* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:C02E26* + ID_OUI_FROM_DATABASE=Private + +OUI:C02FF1* + ID_OUI_FROM_DATABASE=Volta Networks + +OUI:C0335E* + ID_OUI_FROM_DATABASE=Microsoft + +OUI:C034B4* + ID_OUI_FROM_DATABASE=Gigastone Corporation + +OUI:C03580* + ID_OUI_FROM_DATABASE=A&R TECH + +OUI:C035BD* + ID_OUI_FROM_DATABASE=Velocytech Aps + +OUI:C035C5* + ID_OUI_FROM_DATABASE=Prosoft Systems LTD + +OUI:C03656* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:C03896* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:C038F9* + ID_OUI_FROM_DATABASE=Nokia Danmark A/S + +OUI:C03937* + ID_OUI_FROM_DATABASE=GREE ELECTRIC APPLIANCES, INC. OF ZHUHAI + +OUI:C03B8F* + ID_OUI_FROM_DATABASE=Minicom Digital Signage + +OUI:C03D46* + ID_OUI_FROM_DATABASE=Shanghai Sango Network Technology Co.,Ltd + +OUI:C03DD9* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:C03E0F* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:C03F0E* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:C03F2A* + ID_OUI_FROM_DATABASE=Biscotti, Inc. + +OUI:C03FD5* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:C04004* + ID_OUI_FROM_DATABASE=Medicaroid Corporation + +OUI:C04121* + ID_OUI_FROM_DATABASE=Nokia + +OUI:C041F6* + ID_OUI_FROM_DATABASE=LG ELECTRONICS INC + +OUI:C042D0* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:C04301* + ID_OUI_FROM_DATABASE=Epec Oy + +OUI:C044E3* + ID_OUI_FROM_DATABASE=Shenzhen Sinkna Electronics Co., LTD + +OUI:C048E6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C048FB* + ID_OUI_FROM_DATABASE=Shenzhen JingHanDa Electronics Co.Ltd + +OUI:C0493D* + ID_OUI_FROM_DATABASE=MAITRISE TECHNOLOGIQUE + +OUI:C04A00* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:C04A09* + ID_OUI_FROM_DATABASE=Zhejiang Everbright Communication Equip. Co,. Ltd + +OUI:C04DF7* + ID_OUI_FROM_DATABASE=SERELEC + +OUI:C05336* + ID_OUI_FROM_DATABASE=Beijing National Railway Research & Design Institute of Signal & Communication Group Co..Ltd. + +OUI:C05627* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:C056E3* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:C057BC* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:C058A7* + ID_OUI_FROM_DATABASE=Pico Systems Co., Ltd. + +OUI:C05E6F* + ID_OUI_FROM_DATABASE=V. Stonkaus firma Kodinis Raktas + +OUI:C05E79* + ID_OUI_FROM_DATABASE=SHENZHEN HUAXUN ARK TECHNOLOGIES CO.,LTD + +OUI:C06118* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:C0626B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C06394* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C064C6* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:C064E4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C06599* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C067AF* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C06C0F* + ID_OUI_FROM_DATABASE=Dobbs Stanford + +OUI:C06C6D* + ID_OUI_FROM_DATABASE=MagneMotion, Inc. + +OUI:C06D1A* + ID_OUI_FROM_DATABASE=Tianjin Henxinhuifeng Technology Co.,Ltd. + +OUI:C07009* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C0742B* + ID_OUI_FROM_DATABASE=SHENZHEN XUNLONG SOFTWARE CO.,LIMITED + +OUI:C074AD* + ID_OUI_FROM_DATABASE=Grandstream Networks, Inc. + +OUI:C07878* + ID_OUI_FROM_DATABASE=FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + +OUI:C07BBC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C07CD1* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:C07E40* + ID_OUI_FROM_DATABASE=SHENZHEN XDK COMMUNICATION EQUIPMENT CO.,LTD + +OUI:C08135* + ID_OUI_FROM_DATABASE=Ningbo Forfan technology Co., LTD + +OUI:C08170* + ID_OUI_FROM_DATABASE=Effigis GeoSolutions + +OUI:C0830A* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:C083590* + ID_OUI_FROM_DATABASE=CHONGQING JIUYU SMART TECHNOLOGY CO.LTD. + +OUI:C083591* + ID_OUI_FROM_DATABASE=Gemvax Technology ,. Co.Ltd + +OUI:C083592* + ID_OUI_FROM_DATABASE=Huaxin SM Optics Co. LTD. + +OUI:C083593* + ID_OUI_FROM_DATABASE=PCH Engineering A/S + +OUI:C083594* + ID_OUI_FROM_DATABASE=ANTS + +OUI:C083595* + ID_OUI_FROM_DATABASE=Viper Design, LLC + +OUI:C083596* + ID_OUI_FROM_DATABASE=Beijing Cloud Fly Technology Development Co.Ltd + +OUI:C083597* + ID_OUI_FROM_DATABASE=Fuzhou Fdlinker Technology Co.,LTD + +OUI:C083598* + ID_OUI_FROM_DATABASE=ista International GmbH + +OUI:C083599* + ID_OUI_FROM_DATABASE=Shenzhen Pay Device Technology Co., Ltd. + +OUI:C08359A* + ID_OUI_FROM_DATABASE=SHANGHAI CHARMHOPE INFORMATION TECHNOLOGY CO.,LTD. + +OUI:C08359B* + ID_OUI_FROM_DATABASE=Suzhou Siheng Science and Technology Ltd. + +OUI:C08359C* + ID_OUI_FROM_DATABASE=Private + +OUI:C08359D* + ID_OUI_FROM_DATABASE=Gardner Denver Thomas GmbH + +OUI:C08359E* + ID_OUI_FROM_DATABASE=Cyber Sciences, Inc. + +OUI:C0847A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C0847D* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:C08488* + ID_OUI_FROM_DATABASE=Finis Inc + +OUI:C0854C* + ID_OUI_FROM_DATABASE=Ragentek Technology Group + +OUI:C087EB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C0885B* + ID_OUI_FROM_DATABASE=SnD Tech Co., Ltd. + +OUI:C08997* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C089AB* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:C08ACD* + ID_OUI_FROM_DATABASE=Guangzhou Shiyuan Electronic Technology Company Limited + +OUI:C08ADE* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:C08B6F* + ID_OUI_FROM_DATABASE=S I Sistemas Inteligentes Eletrônicos Ltda + +OUI:C08C60* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C08C71* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:C09132* + ID_OUI_FROM_DATABASE=Patriot Memory + +OUI:C09134* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP + +OUI:C095DA* + ID_OUI_FROM_DATABASE=NXP India Private Limited + +OUI:C09727* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:C09879* + ID_OUI_FROM_DATABASE=Acer Inc. + +OUI:C098DA* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:C098E5* + ID_OUI_FROM_DATABASE=University of Michigan + +OUI:C09A71* + ID_OUI_FROM_DATABASE=XIAMEN MEITU MOBILE TECHNOLOGY CO.LTD + +OUI:C09AD0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C09C04* + ID_OUI_FROM_DATABASE=Shaanxi GuoLian Digital TV Technology Co.,Ltd. + +OUI:C09C92* + ID_OUI_FROM_DATABASE=COBY + +OUI:C09D26* + ID_OUI_FROM_DATABASE=Topicon HK Lmd. + +OUI:C09F05* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:C09F42* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C09FE1* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:C0A00D* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:C0A0BB* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:C0A0C7* + ID_OUI_FROM_DATABASE=FAIRFIELD INDUSTRIES + +OUI:C0A0DE* + ID_OUI_FROM_DATABASE=Multi Touch Oy + +OUI:C0A0E2* + ID_OUI_FROM_DATABASE=Eden Innovations + +OUI:C0A1A2* + ID_OUI_FROM_DATABASE=MarqMetrix + +OUI:C0A26D* + ID_OUI_FROM_DATABASE=Abbott Point of Care + +OUI:C0A364* + ID_OUI_FROM_DATABASE=3D Systems Massachusetts + +OUI:C0A39E* + ID_OUI_FROM_DATABASE=EarthCam, Inc. + +OUI:C0A53E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C0A5DD* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:C0A600* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C0A8F0* + ID_OUI_FROM_DATABASE=Adamson Systems Engineering + +OUI:C0AA68* + ID_OUI_FROM_DATABASE=OSASI Technos Inc. + +OUI:C0AC54* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:C0B339* + ID_OUI_FROM_DATABASE=Comigo Ltd. + +OUI:C0B357* + ID_OUI_FROM_DATABASE=Yoshiki Electronics Industry Ltd. + +OUI:C0B47D* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:C0B5CD* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:C0B5D7* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:C0B658* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C0B6F9* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:C0B713* + ID_OUI_FROM_DATABASE=Beijing Xiaoyuer Technology Co. Ltd. + +OUI:C0B883* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:C0B8B1* + ID_OUI_FROM_DATABASE=BitBox Ltd + +OUI:C0BAE6* + ID_OUI_FROM_DATABASE=Application Solutions (Electronics and Vision) Ltd + +OUI:C0BD42* + ID_OUI_FROM_DATABASE=ZPA Smart Energy a.s. + +OUI:C0BDC8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C0BDD1* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:C0BFA7* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:C0BFC0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C0C1C0* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:C0C3B6* + ID_OUI_FROM_DATABASE=Automatic Systems + +OUI:C0C520* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:C0C522* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:C0C569* + ID_OUI_FROM_DATABASE=SHANGHAI LYNUC CNC TECHNOLOGY CO.,LTD + +OUI:C0C687* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:C0C946* + ID_OUI_FROM_DATABASE=MITSUYA LABORATORIES INC. + +OUI:C0C976* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:C0CB38* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:C0CBF1* + ID_OUI_FROM_DATABASE=Mobiwire Mobiles (NingBo) Co., LTD + +OUI:C0CCF8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C0CECD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C0CFA3* + ID_OUI_FROM_DATABASE=Creative Electronics & Software, Inc. + +OUI:C0D012* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C0D044* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:C0D0FF* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:C0D2DD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C0D2F3* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:C0D3910* + ID_OUI_FROM_DATABASE=Fuzhou Jinshi Technology Co.,Ltd. + +OUI:C0D3911* + ID_OUI_FROM_DATABASE=B9Creations + +OUI:C0D3912* + ID_OUI_FROM_DATABASE=Hofon Automation Co.,Ltd + +OUI:C0D3913* + ID_OUI_FROM_DATABASE=IXON B.V. + +OUI:C0D3914* + ID_OUI_FROM_DATABASE=Vernier Software & Technology + +OUI:C0D3915* + ID_OUI_FROM_DATABASE=WiTagg, Inc + +OUI:C0D3916* + ID_OUI_FROM_DATABASE=Ernitec + +OUI:C0D3917* + ID_OUI_FROM_DATABASE=ALNETz Co.,LTD + +OUI:C0D3918* + ID_OUI_FROM_DATABASE=XENA SECURITY LIMITED + +OUI:C0D3919* + ID_OUI_FROM_DATABASE=xxter bv + +OUI:C0D391A* + ID_OUI_FROM_DATABASE=Alpha Audiotronics, Inc. + +OUI:C0D391B* + ID_OUI_FROM_DATABASE=Private + +OUI:C0D391C* + ID_OUI_FROM_DATABASE=Zhinengguo technology company limited + +OUI:C0D391D* + ID_OUI_FROM_DATABASE=REGULUS CO.,LTD. + +OUI:C0D391E* + ID_OUI_FROM_DATABASE=SAMSARA NETWORKS INC + +OUI:C0D3C0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C0D682* + ID_OUI_FROM_DATABASE=Arista Networks + +OUI:C0D834* + ID_OUI_FROM_DATABASE=xvtec ltd + +OUI:C0D962* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:C0D9F7* + ID_OUI_FROM_DATABASE=ShanDong Domor Intelligent S&T CO.,Ltd + +OUI:C0DA74* + ID_OUI_FROM_DATABASE=Hangzhou Sunyard Technology Co., Ltd. + +OUI:C0DC6A* + ID_OUI_FROM_DATABASE=Qingdao Eastsoft Communication Technology Co.,LTD + +OUI:C0DCDA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C0DF77* + ID_OUI_FROM_DATABASE=Conrad Electronic SE + +OUI:C0E422* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:C0E42D* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:C0E434* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:C0E54E* + ID_OUI_FROM_DATABASE=ARIES Embedded GmbH + +OUI:C0E862* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C0EAE4* + ID_OUI_FROM_DATABASE=Sonicwall + +OUI:C0EE40* + ID_OUI_FROM_DATABASE=Laird Technologies + +OUI:C0EEB5* + ID_OUI_FROM_DATABASE=Enice Network. + +OUI:C0EEFB* + ID_OUI_FROM_DATABASE=OnePlus Tech (Shenzhen) Ltd + +OUI:C0F1C4* + ID_OUI_FROM_DATABASE=Pacidal Corporation Ltd. + +OUI:C0F2FB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C0F4E6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C0F636* + ID_OUI_FROM_DATABASE=Hangzhou Kuaiyue Technologies, Ltd. + +OUI:C0F79D* + ID_OUI_FROM_DATABASE=Powercode + +OUI:C0F8DA* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:C0F945* + ID_OUI_FROM_DATABASE=Toshiba Toko Meter Systems Co., LTD. + +OUI:C0F991* + ID_OUI_FROM_DATABASE=GME Standard Communications P/L + +OUI:C0FD84* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:C0FFD4* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:C40006* + ID_OUI_FROM_DATABASE=Lipi Data Systems Ltd. + +OUI:C40049* + ID_OUI_FROM_DATABASE=Kamama + +OUI:C400AD* + ID_OUI_FROM_DATABASE=Advantech Technology (CHINA) Co., Ltd. + +OUI:C40142* + ID_OUI_FROM_DATABASE=MaxMedia Technology Limited + +OUI:C4017C* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:C401B1* + ID_OUI_FROM_DATABASE=SeekTech INC + +OUI:C401CE* + ID_OUI_FROM_DATABASE=PRESITION (2000) CO., LTD. + +OUI:C402E1* + ID_OUI_FROM_DATABASE=Khwahish Technologies Private Limited + +OUI:C40415* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:C4047B* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:C40528* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C40683* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C4072F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C4084A* + ID_OUI_FROM_DATABASE=Nokia + +OUI:C40880* + ID_OUI_FROM_DATABASE=Shenzhen UTEPO Tech Co., Ltd. + +OUI:C40938* + ID_OUI_FROM_DATABASE=FUJIAN STAR-NET COMMUNICATION CO.,LTD + +OUI:C40ACB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C40BCB* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:C40E45* + ID_OUI_FROM_DATABASE=ACK Networks,Inc. + +OUI:C40F09* + ID_OUI_FROM_DATABASE=Hermes electronic GmbH + +OUI:C4108A* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:C411E0* + ID_OUI_FROM_DATABASE=Bull Group Co., Ltd + +OUI:C412F5* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:C413E2* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:C4143C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C416FA* + ID_OUI_FROM_DATABASE=Prysm Inc + +OUI:C417FE* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:C4198B* + ID_OUI_FROM_DATABASE=Dominion Voting Systems Corporation + +OUI:C419D1* + ID_OUI_FROM_DATABASE=Telink Semiconductor (Shanghai) Co., Ltd. + +OUI:C419EC* + ID_OUI_FROM_DATABASE=Qualisys AB + +OUI:C41CFF* + ID_OUI_FROM_DATABASE=Vizio, Inc + +OUI:C41ECE* + ID_OUI_FROM_DATABASE=HMI Sources Ltd. + +OUI:C421C8* + ID_OUI_FROM_DATABASE=KYOCERA CORPORATION + +OUI:C4237A* + ID_OUI_FROM_DATABASE=WhizNets Inc. + +OUI:C423A2* + ID_OUI_FROM_DATABASE=PT. Emsonic Indonesia + +OUI:C4242E* + ID_OUI_FROM_DATABASE=Galvanic Applied Sciences Inc + +OUI:C42456* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:C42628* + ID_OUI_FROM_DATABASE=Airo Wireless + +OUI:C42795* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:C4282D* + ID_OUI_FROM_DATABASE=Embedded Intellect Pty Ltd + +OUI:C4291D* + ID_OUI_FROM_DATABASE=KLEMSAN ELEKTRIK ELEKTRONIK SAN.VE TIC.AS. + +OUI:C42996* + ID_OUI_FROM_DATABASE=Signify B.V. + +OUI:C42AD0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C42C03* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C42C4F* + ID_OUI_FROM_DATABASE=Qingdao Hisense Mobile Communication Technology Co,Ltd + +OUI:C42F90* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:C43018* + ID_OUI_FROM_DATABASE=MCS Logic Inc. + +OUI:C432D1* + ID_OUI_FROM_DATABASE=Farlink Technology Limited + +OUI:C43306* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:C4346B* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:C43655* + ID_OUI_FROM_DATABASE=Shenzhen Fenglian Technology Co., Ltd. + +OUI:C4366C* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:C436DA* + ID_OUI_FROM_DATABASE=Rusteletech Ltd. + +OUI:C438D3* + ID_OUI_FROM_DATABASE=TAGATEC CO.,LTD + +OUI:C4393A* + ID_OUI_FROM_DATABASE=SMC Networks Inc + +OUI:C43A35* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:C43A9F* + ID_OUI_FROM_DATABASE=Siconix Inc. + +OUI:C43ABE* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:C43C3C* + ID_OUI_FROM_DATABASE=CYBELEC SA + +OUI:C43DC7* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:C44044* + ID_OUI_FROM_DATABASE=RackTop Systems Inc. + +OUI:C4411E* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:C44202* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C44268* + ID_OUI_FROM_DATABASE=CRESTRON ELECTRONICS, INC. + +OUI:C4438F* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:C4447D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C444A0* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C44567* + ID_OUI_FROM_DATABASE=SAMBON PRECISON and ELECTRONICS + +OUI:C445EC* + ID_OUI_FROM_DATABASE=Shanghai Yali Electron Co.,LTD + +OUI:C44619* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:C4473F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C44838* + ID_OUI_FROM_DATABASE=Satcom Direct, Inc. + +OUI:C449BB* + ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD. + +OUI:C44AD0* + ID_OUI_FROM_DATABASE=FIREFLIES SYSTEMS + +OUI:C44B44* + ID_OUI_FROM_DATABASE=Omniprint Inc. + +OUI:C44BD1* + ID_OUI_FROM_DATABASE=Wallys Communications Teachnologies Co.,Ltd. + +OUI:C44E1F* + ID_OUI_FROM_DATABASE=BlueN + +OUI:C44EAC* + ID_OUI_FROM_DATABASE=Shenzhen Shiningworth Technology Co., Ltd. + +OUI:C44F33* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:C45006* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C4518D* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:C45444* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:C455A6* + ID_OUI_FROM_DATABASE=Cadac Holdings Ltd + +OUI:C455C2* + ID_OUI_FROM_DATABASE=Bach-Simpson + +OUI:C45600* + ID_OUI_FROM_DATABASE=Galleon Embedded Computing + +OUI:C456FE* + ID_OUI_FROM_DATABASE=Lava International Ltd. + +OUI:C4571F* + ID_OUI_FROM_DATABASE=June Life Inc + +OUI:C4576E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C458C2* + ID_OUI_FROM_DATABASE=Shenzhen TATFOOK Technology Co., Ltd. + +OUI:C45976* + ID_OUI_FROM_DATABASE=Fugoo Coorporation + +OUI:C45BF7* + ID_OUI_FROM_DATABASE=ants + +OUI:C45DD8* + ID_OUI_FROM_DATABASE=HDMI Forum + +OUI:C46044* + ID_OUI_FROM_DATABASE=Everex Electronics Limited + +OUI:C4618B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C4626B* + ID_OUI_FROM_DATABASE=ZPT Vigantice + +OUI:C462EA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C46354* + ID_OUI_FROM_DATABASE=U-Raku, Inc. + +OUI:C463FB* + ID_OUI_FROM_DATABASE=Neatframe AS + +OUI:C46413* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C464B7* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:C464E3* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:C46516* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:C46699* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:C467B5* + ID_OUI_FROM_DATABASE=Libratone A/S + +OUI:C467D1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C468D0* + ID_OUI_FROM_DATABASE=VTech Telecommunications Ltd. + +OUI:C4693E* + ID_OUI_FROM_DATABASE=Turbulence Design Inc. + +OUI:C46AB7* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:C46BB4* + ID_OUI_FROM_DATABASE=myIDkey + +OUI:C46DF1* + ID_OUI_FROM_DATABASE=DataGravity + +OUI:C46E1F* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:C46E7B* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:C4700B* + ID_OUI_FROM_DATABASE=GUANGZHOU CHIP TECHNOLOGIES CO.,LTD + +OUI:C47130* + ID_OUI_FROM_DATABASE=Fon Technology S.L. + +OUI:C47154* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:C471FE* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C47295* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C4731E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C4741E* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:C474F8* + ID_OUI_FROM_DATABASE=Hot Pepper, Inc. + +OUI:C477AB* + ID_OUI_FROM_DATABASE=Beijing ASU Tech Co.,Ltd + +OUI:C477AF* + ID_OUI_FROM_DATABASE=Advanced Digital Broadcast SA + +OUI:C47B2F* + ID_OUI_FROM_DATABASE=Beijing JoinHope Image Technology Ltd. + +OUI:C47BA3* + ID_OUI_FROM_DATABASE=NAVIS Inc. + +OUI:C47C8D0* + ID_OUI_FROM_DATABASE=ATI + +OUI:C47C8D1* + ID_OUI_FROM_DATABASE=LYNX INNOVATION LITIMED + +OUI:C47C8D2* + ID_OUI_FROM_DATABASE=Star2Star Communications, LLC + +OUI:C47C8D3* + ID_OUI_FROM_DATABASE=Watec Co., Ltd. + +OUI:C47C8D4* + ID_OUI_FROM_DATABASE=ROBOSTAR + +OUI:C47C8D5* + ID_OUI_FROM_DATABASE=PASCAL Co., Ltd. + +OUI:C47C8D6* + ID_OUI_FROM_DATABASE=HHCC Plant Technology Co.,Ltd. + +OUI:C47C8D7* + ID_OUI_FROM_DATABASE=Awiselink Co., Ltd. + +OUI:C47C8D8* + ID_OUI_FROM_DATABASE=GETEMED Medizin- und Informationstechnik AG + +OUI:C47C8D9* + ID_OUI_FROM_DATABASE=Airbus DS - SLC + +OUI:C47C8DA* + ID_OUI_FROM_DATABASE=Silvus technologies inc + +OUI:C47C8DB* + ID_OUI_FROM_DATABASE=GC AUTOMATION CO,LTD + +OUI:C47C8DC* + ID_OUI_FROM_DATABASE=INOTEC Sicherheitstechnik GmbH + +OUI:C47C8DD* + ID_OUI_FROM_DATABASE=Anhui GuangXing Linked-Video Communication Technology Co, Ltd. + +OUI:C47C8DE* + ID_OUI_FROM_DATABASE=Labor Strauss Sicherungsanlagenbau GmbH + +OUI:C47D46* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:C47D4F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C47DCC* + ID_OUI_FROM_DATABASE=Zebra Technologies Inc + +OUI:C47DFE* + ID_OUI_FROM_DATABASE=A.N. Solutions GmbH + +OUI:C47F51* + ID_OUI_FROM_DATABASE=Inventek Systems + +OUI:C4823F* + ID_OUI_FROM_DATABASE=Fujian Newland Auto-ID Tech. Co,.Ltd. + +OUI:C4824E* + ID_OUI_FROM_DATABASE=Changzhou Uchip Electronics Co., LTD. + +OUI:C4836F* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:C48466* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C48508* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:C486E9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C488E5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C48A5A* + ID_OUI_FROM_DATABASE=JFCONTROL + +OUI:C48E8F* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:C48F07* + ID_OUI_FROM_DATABASE=Shenzhen Yihao Hulian Science and Technology Co., Ltd. + +OUI:C48FC1* + ID_OUI_FROM_DATABASE=DEEPTRACK S.L.U. + +OUI:C4913A* + ID_OUI_FROM_DATABASE=Shenzhen Sanland Electronic Co., ltd. + +OUI:C4924C* + ID_OUI_FROM_DATABASE=KEISOKUKI CENTER CO.,LTD. + +OUI:C49300* + ID_OUI_FROM_DATABASE=8Devices + +OUI:C49313* + ID_OUI_FROM_DATABASE=100fio networks technology llc + +OUI:C49380* + ID_OUI_FROM_DATABASE=Speedytel technology + +OUI:C493D9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C49500* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:C4954D0* + ID_OUI_FROM_DATABASE=BA International Electronics Co. Ltd. + +OUI:C4954D1* + ID_OUI_FROM_DATABASE=Teletronik AG + +OUI:C4954D2* + ID_OUI_FROM_DATABASE=Shen Zhen Euse Technology Co.,Ltd + +OUI:C4954D3* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:C4954D4* + ID_OUI_FROM_DATABASE=GL Solutions Inc. + +OUI:C4954D5* + ID_OUI_FROM_DATABASE=Marble Automation + +OUI:C4954D6* + ID_OUI_FROM_DATABASE=AKKA Germany GmbH + +OUI:C4954D7* + ID_OUI_FROM_DATABASE=LLC TechnoEnergo + +OUI:C4954D8* + ID_OUI_FROM_DATABASE=Xinjiang Golden Calf Energy IOT Technology Co., Ltd + +OUI:C4954D9* + ID_OUI_FROM_DATABASE=Shenzhen Xtooltech Co., Ltd + +OUI:C4954DA* + ID_OUI_FROM_DATABASE=KAT Mekatronik Urunleri AS + +OUI:C4954DB* + ID_OUI_FROM_DATABASE=Multicom, Inc + +OUI:C4954DC* + ID_OUI_FROM_DATABASE=SolidGear Corporation + +OUI:C4954DD* + ID_OUI_FROM_DATABASE=Newland Era Edu Hi-Tech(BeiJing)Co.,Ltd + +OUI:C4954DE* + ID_OUI_FROM_DATABASE=Canare Electric Co., Ltd. + +OUI:C495A2* + ID_OUI_FROM_DATABASE=SHENZHEN WEIJIU INDUSTRY AND TRADE DEVELOPMENT CO., LTD + +OUI:C49805* + ID_OUI_FROM_DATABASE=Minieum Networks, Inc + +OUI:C4985C* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:C49878* + ID_OUI_FROM_DATABASE=SHANGHAI MOAAN INTELLIGENT TECHNOLOGY CO.,LTD + +OUI:C49880* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C49A02* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:C49DED* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:C49E41* + ID_OUI_FROM_DATABASE=G24 Power Limited + +OUI:C49F4C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C49FF3* + ID_OUI_FROM_DATABASE=Mciao Technologies, Inc. + +OUI:C4A366* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:C4A81D* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:C4AAA1* + ID_OUI_FROM_DATABASE=SUMMIT DEVELOPMENT, spol.s r.o. + +OUI:C4ABB2* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:C4AC59* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:C4AD21* + ID_OUI_FROM_DATABASE=MEDIAEDGE Corporation + +OUI:C4AD34* + ID_OUI_FROM_DATABASE=Routerboard.com + +OUI:C4ADF1* + ID_OUI_FROM_DATABASE=GOPEACE Inc. + +OUI:C4AE12* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C4B239* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C4B301* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C4B36A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C4B512* + ID_OUI_FROM_DATABASE=General Electric Digital Energy + +OUI:C4B8B4* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C4B9CD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C4BA99* + ID_OUI_FROM_DATABASE=I+ME Actia Informatik und Mikro-Elektronik GmbH + +OUI:C4BAA3* + ID_OUI_FROM_DATABASE=Beijing Winicssec Technologies Co., Ltd. + +OUI:C4BB4C* + ID_OUI_FROM_DATABASE=Zebra Information Tech Co. Ltd + +OUI:C4BBEA* + ID_OUI_FROM_DATABASE=Pakedge Device and Software Inc + +OUI:C4BD6A* + ID_OUI_FROM_DATABASE=SKF GmbH + +OUI:C4BE84* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:C4BED4* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:C4C0AE* + ID_OUI_FROM_DATABASE=MIDORI ELECTRONIC CO., LTD. + +OUI:C4C138* + ID_OUI_FROM_DATABASE=OWLink Technology Inc + +OUI:C4C19F* + ID_OUI_FROM_DATABASE=National Oilwell Varco Instrumentation, Monitoring, and Optimization (NOV IMO) + +OUI:C4C563* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:C4C603* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C4C755* + ID_OUI_FROM_DATABASE=Beijing HuaqinWorld Technology Co.,Ltd + +OUI:C4C919* + ID_OUI_FROM_DATABASE=Energy Imports Ltd + +OUI:C4C9EC* + ID_OUI_FROM_DATABASE=Gugaoo HK Limited + +OUI:C4CAD9* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:C4CB6B* + ID_OUI_FROM_DATABASE=Airista Flow, Inc. + +OUI:C4CD45* + ID_OUI_FROM_DATABASE=Beijing Boomsense Technology CO.,LTD. + +OUI:C4CD82* + ID_OUI_FROM_DATABASE=Hangzhou Lowan Information Technology Co., Ltd. + +OUI:C4D197* + ID_OUI_FROM_DATABASE=Ventia Utility Services + +OUI:C4D489* + ID_OUI_FROM_DATABASE=JiangSu Joyque Information Industry Co.,Ltd + +OUI:C4D655* + ID_OUI_FROM_DATABASE=Tercel technology co.,ltd + +OUI:C4D8F3* + ID_OUI_FROM_DATABASE=iZotope + +OUI:C4D987* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:C4DA26* + ID_OUI_FROM_DATABASE=NOBLEX SA + +OUI:C4DA7D* + ID_OUI_FROM_DATABASE=Ivium Technologies B.V. + +OUI:C4E032* + ID_OUI_FROM_DATABASE=IEEE 1904.1 Working Group + +OUI:C4E0DE* + ID_OUI_FROM_DATABASE=Zhengzhou XindaJiean Information Technology Co.,Ltd. + +OUI:C4E17C* + ID_OUI_FROM_DATABASE=U2S co. + +OUI:C4E1A1* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:C4E39F* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:C4E506* + ID_OUI_FROM_DATABASE=Piper Networks, Inc. + +OUI:C4E510* + ID_OUI_FROM_DATABASE=Mechatro, Inc. + +OUI:C4E7BE* + ID_OUI_FROM_DATABASE=SCSpro Co.,Ltd + +OUI:C4E90A* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:C4E92F* + ID_OUI_FROM_DATABASE=AB Sciex + +OUI:C4E984* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:C4EA1D* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:C4EBE3* + ID_OUI_FROM_DATABASE=RRCN SAS + +OUI:C4EDBA* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:C4EEAE* + ID_OUI_FROM_DATABASE=VSS Monitoring + +OUI:C4EEF5* + ID_OUI_FROM_DATABASE=II-VI Incorporated + +OUI:C4EF70* + ID_OUI_FROM_DATABASE=Home Skinovations + +OUI:C4F081* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C4F0EC* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:C4F1D1* + ID_OUI_FROM_DATABASE=BEIJING SOGOU TECHNOLOGY DEVELOPMENT CO., LTD. + +OUI:C4F312* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:C4F464* + ID_OUI_FROM_DATABASE=Spica international + +OUI:C4F57C* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:C4F5A5* + ID_OUI_FROM_DATABASE=Kumalift Co., Ltd. + +OUI:C4F7D5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C4F839* + ID_OUI_FROM_DATABASE=Actia Automotive + +OUI:C4FCE4* + ID_OUI_FROM_DATABASE=DishTV NZ Ltd + +OUI:C4FDE6* + ID_OUI_FROM_DATABASE=DRTECH + +OUI:C4FE5B* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:C4FEE2* + ID_OUI_FROM_DATABASE=AMICCOM Electronics Corporation + +OUI:C4FF1F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C4FFBC0* + ID_OUI_FROM_DATABASE=Danego BV + +OUI:C4FFBC1* + ID_OUI_FROM_DATABASE=VISATECH C0., LTD. + +OUI:C4FFBC2* + ID_OUI_FROM_DATABASE=Mobiletron Electronics Co., Ltd + +OUI:C4FFBC3* + ID_OUI_FROM_DATABASE=SHENZHEN KALIF ELECTRONICS CO.,LTD + +OUI:C4FFBC4* + ID_OUI_FROM_DATABASE=iMageTech CO.,LTD. + +OUI:C4FFBC5* + ID_OUI_FROM_DATABASE=comtime GmbH + +OUI:C4FFBC6* + ID_OUI_FROM_DATABASE=Shenzhen C & D Electronics Co., Ltd. + +OUI:C4FFBC7* + ID_OUI_FROM_DATABASE=Critical Link + +OUI:C4FFBC8* + ID_OUI_FROM_DATABASE=ShenZhen ZYT Technology co., Ltd + +OUI:C4FFBC9* + ID_OUI_FROM_DATABASE=GSM Innovations Pty Ltd + +OUI:C4FFBCA* + ID_OUI_FROM_DATABASE=Advanced Navigation + +OUI:C4FFBCB* + ID_OUI_FROM_DATABASE=KAGA ELECTRONICS CO.,LTD. + +OUI:C4FFBCC* + ID_OUI_FROM_DATABASE=KyongBo Electric Co., Ltd. + +OUI:C4FFBCD* + ID_OUI_FROM_DATABASE=Beijing KDF information technology co. LTD. + +OUI:C4FFBCE* + ID_OUI_FROM_DATABASE=viRaTec GmbH + +OUI:C80084* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C80210* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:C80258* + ID_OUI_FROM_DATABASE=ITW GSE ApS + +OUI:C8028F* + ID_OUI_FROM_DATABASE=Nova Electronics (Shanghai) Co., Ltd. + +OUI:C802A6* + ID_OUI_FROM_DATABASE=Beijing Newmine Technology + +OUI:C803F5* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:C80718* + ID_OUI_FROM_DATABASE=TDSi + +OUI:C80873* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:C808E9* + ID_OUI_FROM_DATABASE=LG Electronics + +OUI:C809A8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:C80AA9* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:C80CC8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C80D32* + ID_OUI_FROM_DATABASE=Holoplot GmbH + +OUI:C80E14* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:C80E77* + ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited + +OUI:C80E95* + ID_OUI_FROM_DATABASE=OmniLync Inc. + +OUI:C81073* + ID_OUI_FROM_DATABASE=CENTURY OPTICOMM CO.,LTD + +OUI:C81451* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C81479* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C816A5* + ID_OUI_FROM_DATABASE=Masimo Corporation + +OUI:C816BD* + ID_OUI_FROM_DATABASE=Qingdao Hisense Communications Co.,Ltd. + +OUI:C819F7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C81AFE* + ID_OUI_FROM_DATABASE=DLOGIC GmbH + +OUI:C81B5C* + ID_OUI_FROM_DATABASE=BCTech + +OUI:C81B6B* + ID_OUI_FROM_DATABASE=Innova Security + +OUI:C81E8E* + ID_OUI_FROM_DATABASE=ADV Security (S) Pte Ltd + +OUI:C81EE7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C81F66* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:C81FBE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C81FEA* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:C8208E* + ID_OUI_FROM_DATABASE=Storagedata + +OUI:C82158* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:C821DA* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:C825E1* + ID_OUI_FROM_DATABASE=Lemobile Information Technology (Beijing) Co., Ltd + +OUI:C82832* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd. + +OUI:C8292A* + ID_OUI_FROM_DATABASE=Barun Electronics + +OUI:C82A14* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C82B96* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:C82C2B0* + ID_OUI_FROM_DATABASE=Fungible, Inc. + +OUI:C82C2B1* + ID_OUI_FROM_DATABASE=Galgus + +OUI:C82C2B2* + ID_OUI_FROM_DATABASE=Repp Health + +OUI:C82C2B3* + ID_OUI_FROM_DATABASE=RF Engineering and Energy Resource + +OUI:C82C2B4* + ID_OUI_FROM_DATABASE=iWave Systems Tech Pvt Ltd + +OUI:C82C2B5* + ID_OUI_FROM_DATABASE=DALCO AG + +OUI:C82C2B6* + ID_OUI_FROM_DATABASE=Grav I.T. + +OUI:C82C2B7* + ID_OUI_FROM_DATABASE=Merpa Bilgi Islem Ltd.Sti + +OUI:C82C2B8* + ID_OUI_FROM_DATABASE=Verifone Systems (China),lnc. + +OUI:C82C2B9* + ID_OUI_FROM_DATABASE=BIOT Sp. z o.o. + +OUI:C82C2BA* + ID_OUI_FROM_DATABASE=Shiftall Inc. + +OUI:C82C2BB* + ID_OUI_FROM_DATABASE=Kunshan SVL Electric Co.,Ltd + +OUI:C82C2BC* + ID_OUI_FROM_DATABASE=Smart Wires Inc + +OUI:C82C2BD* + ID_OUI_FROM_DATABASE=UBITRON Co.,LTD + +OUI:C82C2BE* + ID_OUI_FROM_DATABASE=Fränkische Rohrwerke Gebr. Kirchner GmbH & Co. KG + +OUI:C82E47* + ID_OUI_FROM_DATABASE=Suzhou SmartChip Semiconductor Co., LTD + +OUI:C82E94* + ID_OUI_FROM_DATABASE=Halfa Enterprise Co., Ltd. + +OUI:C83168* + ID_OUI_FROM_DATABASE=eZEX corporation + +OUI:C83232* + ID_OUI_FROM_DATABASE=Hunting Innova + +OUI:C8334B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C8348E* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:C835B8* + ID_OUI_FROM_DATABASE=Ericsson, EAB/RWI/K + +OUI:C83870* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C83A35* + ID_OUI_FROM_DATABASE=Tenda Technology Co., Ltd. + +OUI:C83A6B* + ID_OUI_FROM_DATABASE=Roku, Inc + +OUI:C83B45* + ID_OUI_FROM_DATABASE=JRI + +OUI:C83C85* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C83D97* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:C83DD4* + ID_OUI_FROM_DATABASE=CyberTAN Technology Inc. + +OUI:C83DDC* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:C83DFC* + ID_OUI_FROM_DATABASE=Pioneer DJ Corporation + +OUI:C83E99* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:C83EA7* + ID_OUI_FROM_DATABASE=KUNBUS GmbH + +OUI:C83F26* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:C83FB4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:C84029* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:C84529* + ID_OUI_FROM_DATABASE=IMK Networks Co.,Ltd + +OUI:C84544* + ID_OUI_FROM_DATABASE=Asia Pacific CIS (Wuxi) Co, Ltd + +OUI:C8458F* + ID_OUI_FROM_DATABASE=Wyler AG + +OUI:C84782* + ID_OUI_FROM_DATABASE=Areson Technology Corp. + +OUI:C8478C* + ID_OUI_FROM_DATABASE=Beken Corporation + +OUI:C848F5* + ID_OUI_FROM_DATABASE=MEDISON Xray Co., Ltd + +OUI:C84C75* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C84F0E* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:C84F86* + ID_OUI_FROM_DATABASE=Sophos Ltd + +OUI:C850CE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C850E9* + ID_OUI_FROM_DATABASE=Raisecom Technology CO., LTD + +OUI:C85195* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C85261* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:C853E1* + ID_OUI_FROM_DATABASE=Beijing Bytedance Network Technology Co., Ltd + +OUI:C8544B* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:C85645* + ID_OUI_FROM_DATABASE=Intermas France + +OUI:C85663* + ID_OUI_FROM_DATABASE=Sunflex Europe GmbH + +OUI:C858C0* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:C85A9F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:C85B76* + ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd + +OUI:C85D38* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:C86000* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:C863140* + ID_OUI_FROM_DATABASE=Western Reserve Controls, Inc. + +OUI:C863141* + ID_OUI_FROM_DATABASE=Autonics Co., Ltd. + +OUI:C863142* + ID_OUI_FROM_DATABASE=Tymphany Acoustic Technology (Huizhou) Co., Ltd. + +OUI:C863143* + ID_OUI_FROM_DATABASE=TrackMan + +OUI:C863144* + ID_OUI_FROM_DATABASE=Shenzhen Zero Zero Infinity Technology Co.,Ltd. + +OUI:C863145* + ID_OUI_FROM_DATABASE=Meyer Electronics Limited + +OUI:C863146* + ID_OUI_FROM_DATABASE=GRINBI PARTNERS + +OUI:C863147* + ID_OUI_FROM_DATABASE=Shenzhen Wesion Technology Co., Ltd + +OUI:C863148* + ID_OUI_FROM_DATABASE=Thinci, Inc. + +OUI:C863149* + ID_OUI_FROM_DATABASE=Maxcom S.A. + +OUI:C86314A* + ID_OUI_FROM_DATABASE=Optictimes Co.,Ltd + +OUI:C86314B* + ID_OUI_FROM_DATABASE=Shenzhen Lihewei Electronics Co.,Ltd.Hunan Branch + +OUI:C86314C* + ID_OUI_FROM_DATABASE=Freeus LLC + +OUI:C86314D* + ID_OUI_FROM_DATABASE=Telematix AG + +OUI:C86314E* + ID_OUI_FROM_DATABASE=Taylor Dynamometer + +OUI:C863F1* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:C863FC* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:C864C7* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:C8662C* + ID_OUI_FROM_DATABASE=Beijing Haitai Fangyuan High Technology Co,.Ltd. + +OUI:C8665D* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:C8675E* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:C869CD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C86C1E* + ID_OUI_FROM_DATABASE=Display Systems Ltd + +OUI:C86C87* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:C86CB6* + ID_OUI_FROM_DATABASE=Optcom Co., Ltd. + +OUI:C86F1D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C87248* + ID_OUI_FROM_DATABASE=Aplicom Oy + +OUI:C87324* + ID_OUI_FROM_DATABASE=Sow Cheng Technology Co. Ltd. + +OUI:C8755B* + ID_OUI_FROM_DATABASE=Quantify Technology Pty. Ltd. + +OUI:C87765* + ID_OUI_FROM_DATABASE=Tiesse SpA + +OUI:C8778B* + ID_OUI_FROM_DATABASE=Mercury Systems – Trusted Mission Solutions, Inc. + +OUI:C87B5B* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:C87CBC* + ID_OUI_FROM_DATABASE=Valink Co., Ltd. + +OUI:C87D77* + ID_OUI_FROM_DATABASE=Shenzhen Kingtech Communication Equipment Co.,Ltd + +OUI:C87E75* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C88439* + ID_OUI_FROM_DATABASE=Sunrise Technologies + +OUI:C88447* + ID_OUI_FROM_DATABASE=Beautiful Enterprise Co., Ltd + +OUI:C88550* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C88629* + ID_OUI_FROM_DATABASE=Shenzhen Duubee Intelligent Technologies Co.,LTD. + +OUI:C88722* + ID_OUI_FROM_DATABASE=Lumenpulse + +OUI:C8873B* + ID_OUI_FROM_DATABASE=Net Optics + +OUI:C88A83* + ID_OUI_FROM_DATABASE=Dongguan HuaHong Electronics Co.,Ltd + +OUI:C88B47* + ID_OUI_FROM_DATABASE=Nolangroup S.P.A con Socio Unico + +OUI:C88D83* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C88ED10* + ID_OUI_FROM_DATABASE=AISWORLD PRIVATE LIMITED + +OUI:C88ED11* + ID_OUI_FROM_DATABASE=German Pipe GmbH + +OUI:C88ED12* + ID_OUI_FROM_DATABASE=ROTRONIC AG + +OUI:C88ED13* + ID_OUI_FROM_DATABASE=Linx Technologies + +OUI:C88ED14* + ID_OUI_FROM_DATABASE=Comlab AG + +OUI:C88ED15* + ID_OUI_FROM_DATABASE=Fibergate.Inc + +OUI:C88ED16* + ID_OUI_FROM_DATABASE=Shenyang Machine Tool(Group) Research & Design Institute Co., Ltd, Shanghai Branch + +OUI:C88ED17* + ID_OUI_FROM_DATABASE=Ube, Inc. (dba Plum) + +OUI:C88ED18* + ID_OUI_FROM_DATABASE=Electronic Controls Design, Inc. + +OUI:C88ED19* + ID_OUI_FROM_DATABASE=Focalcrest, Ltd. + +OUI:C88ED1A* + ID_OUI_FROM_DATABASE=AP Sensing GmbH + +OUI:C88ED1B* + ID_OUI_FROM_DATABASE=Advanced Micro Controls Inc. + +OUI:C88ED1C* + ID_OUI_FROM_DATABASE=Shanghai Bwave Technology Co.,Ltd + +OUI:C88ED1D* + ID_OUI_FROM_DATABASE=PHOENIX ENGINEERING CORP. + +OUI:C88ED1E* + ID_OUI_FROM_DATABASE=Aventics GmbH + +OUI:C88ED1F* + ID_OUI_FROM_DATABASE=Private + +OUI:C88F26* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:C8903E* + ID_OUI_FROM_DATABASE=Pakton Technologies + +OUI:C891F9* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:C89346* + ID_OUI_FROM_DATABASE=MXCHIP Company Limited + +OUI:C89383* + ID_OUI_FROM_DATABASE=Embedded Automation, Inc. + +OUI:C894BB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C894D2* + ID_OUI_FROM_DATABASE=Jiangsu Datang Electronic Products Co., Ltd + +OUI:C8979F* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:C89C13* + ID_OUI_FROM_DATABASE=Inspiremobile + +OUI:C89C1D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C89CDC* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:C89F1D* + ID_OUI_FROM_DATABASE=SHENZHEN COMMUNICATION TECHNOLOGIES CO.,LTD + +OUI:C89F42* + ID_OUI_FROM_DATABASE=VDII Innovation AB + +OUI:C8A030* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:C8A1B6* + ID_OUI_FROM_DATABASE=Shenzhen Longway Technologies Co., Ltd + +OUI:C8A1BA* + ID_OUI_FROM_DATABASE=Neul Ltd + +OUI:C8A2CE* + ID_OUI_FROM_DATABASE=Oasis Media Systems LLC + +OUI:C8A620* + ID_OUI_FROM_DATABASE=Nebula, Inc + +OUI:C8A70A* + ID_OUI_FROM_DATABASE=Verizon Business + +OUI:C8A729* + ID_OUI_FROM_DATABASE=SYStronics Co., Ltd. + +OUI:C8A776* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C8A823* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C8A9FC* + ID_OUI_FROM_DATABASE=Goyoo Networks Inc. + +OUI:C8AA21* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:C8AA55* + ID_OUI_FROM_DATABASE=Hunan Comtom Electronic Incorporated Co.,Ltd + +OUI:C8AACC* + ID_OUI_FROM_DATABASE=Private + +OUI:C8AE9C* + ID_OUI_FROM_DATABASE=Shanghai TYD Elecronic Technology Co. Ltd + +OUI:C8AF40* + ID_OUI_FROM_DATABASE=marco Systemanalyse und Entwicklung GmbH + +OUI:C8AFE3* + ID_OUI_FROM_DATABASE=Hefei Radio Communication Technology Co., Ltd + +OUI:C8B1CD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C8B1EE* + ID_OUI_FROM_DATABASE=Qorvo + +OUI:C8B21E* + ID_OUI_FROM_DATABASE=CHIPSEA TECHNOLOGIES (SHENZHEN) CORP. + +OUI:C8B373* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:C8B422* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:C8B5AD* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:C8B5B7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C8BA94* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:C8BAE9* + ID_OUI_FROM_DATABASE=QDIS + +OUI:C8BBD3* + ID_OUI_FROM_DATABASE=Embrane + +OUI:C8BCC8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C8BE19* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:C8C126* + ID_OUI_FROM_DATABASE=ZPM Industria e Comercio Ltda + +OUI:C8C13C* + ID_OUI_FROM_DATABASE=RuggedTek Hangzhou Co., Ltd + +OUI:C8C2C6* + ID_OUI_FROM_DATABASE=Shanghai Airm2m Communication Technology Co., Ltd + +OUI:C8C2F5* + ID_OUI_FROM_DATABASE=FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + +OUI:C8C2FA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C8C465* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C8C50E* + ID_OUI_FROM_DATABASE=Shenzhen Primestone Network Technologies.Co., Ltd. + +OUI:C8C64A* + ID_OUI_FROM_DATABASE=Flextronics Tech.(Ind) Pvt Ltd + +OUI:C8C750* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:C8C791* + ID_OUI_FROM_DATABASE=Zero1.tv GmbH + +OUI:C8CBB8* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:C8CD72* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:C8D019* + ID_OUI_FROM_DATABASE=Shanghai Tigercel Communication Technology Co.,Ltd + +OUI:C8D083* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C8D10B* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:C8D12A* + ID_OUI_FROM_DATABASE=Comtrend Corporation + +OUI:C8D15E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:C8D1D1* + ID_OUI_FROM_DATABASE=AGAiT Technology Corporation + +OUI:C8D2C1* + ID_OUI_FROM_DATABASE=Jetlun (Shenzhen) Corporation + +OUI:C8D3A3* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:C8D3FF* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:C8D429* + ID_OUI_FROM_DATABASE=Muehlbauer AG + +OUI:C8D590* + ID_OUI_FROM_DATABASE=FLIGHT DATA SYSTEMS + +OUI:C8D5FE* + ID_OUI_FROM_DATABASE=Shenzhen Zowee Technology Co., Ltd + +OUI:C8D69D* + ID_OUI_FROM_DATABASE=Arab International Optronics + +OUI:C8D719* + ID_OUI_FROM_DATABASE=Cisco-Linksys, LLC + +OUI:C8D778* + ID_OUI_FROM_DATABASE=BSH Hausgeraete GmbH + +OUI:C8D779* + ID_OUI_FROM_DATABASE=QING DAO HAIER TELECOM CO.,LTD. + +OUI:C8D7B0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:C8D9D2* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:C8DB26* + ID_OUI_FROM_DATABASE=Logitech + +OUI:C8DDC9* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:C8DE51* + ID_OUI_FROM_DATABASE=IntegraOptics + +OUI:C8DEC9* + ID_OUI_FROM_DATABASE=Coriant + +OUI:C8DF7C* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:C8DF84* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:C8E0EB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C8E130* + ID_OUI_FROM_DATABASE=Milkyway Group Ltd + +OUI:C8E1A7* + ID_OUI_FROM_DATABASE=Vertu Corporation Limited + +OUI:C8E42F* + ID_OUI_FROM_DATABASE=Technical Research Design and Development + +OUI:C8E776* + ID_OUI_FROM_DATABASE=PTCOM Technology + +OUI:C8E7D8* + ID_OUI_FROM_DATABASE=MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:C8E7F0* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:C8EAF8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:C8EE08* + ID_OUI_FROM_DATABASE=TANGTOP TECHNOLOGY CO.,LTD + +OUI:C8EE75* + ID_OUI_FROM_DATABASE=Pishion International Co. Ltd + +OUI:C8EEA6* + ID_OUI_FROM_DATABASE=Shenzhen SHX Technology Co., Ltd + +OUI:C8EF2E* + ID_OUI_FROM_DATABASE=Beijing Gefei Tech. Co., Ltd + +OUI:C8F230* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:C8F319* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:C8F36B* + ID_OUI_FROM_DATABASE=Yamato Scale Co.,Ltd. + +OUI:C8F386* + ID_OUI_FROM_DATABASE=Shenzhen Xiaoniao Technology Co.,Ltd + +OUI:C8F406* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:C8F650* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:C8F68D* + ID_OUI_FROM_DATABASE=S.E.TECHNOLOGIES LIMITED + +OUI:C8F6C8* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:C8F704* + ID_OUI_FROM_DATABASE=Building Block Video + +OUI:C8F733* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:C8F742* + ID_OUI_FROM_DATABASE=HangZhou Gubei Electronics Technology Co.,Ltd + +OUI:C8F750* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:C8F86D* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:C8F946* + ID_OUI_FROM_DATABASE=LOCOSYS Technology Inc. + +OUI:C8F981* + ID_OUI_FROM_DATABASE=Seneca s.r.l. + +OUI:C8F9C8* + ID_OUI_FROM_DATABASE=NewSharp Technology(SuZhou)Co,Ltd + +OUI:C8F9F9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:C8FA84* + ID_OUI_FROM_DATABASE=Trusonus corp. + +OUI:C8FAE1* + ID_OUI_FROM_DATABASE=ARQ Digital LLC + +OUI:C8FB26* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:C8FD19* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:C8FE30* + ID_OUI_FROM_DATABASE=Bejing DAYO Mobile Communication Technology Ltd. + +OUI:C8FF28* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:C8FF77* + ID_OUI_FROM_DATABASE=Dyson Limited + +OUI:CC0080* + ID_OUI_FROM_DATABASE=BETTINI SRL + +OUI:CC03D9* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:CC03FA* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:CC047C* + ID_OUI_FROM_DATABASE=G-WAY Microwave + +OUI:CC04B4* + ID_OUI_FROM_DATABASE=Select Comfort + +OUI:CC051B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:CC0577* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:CC0677* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:CC07AB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:CC07E4* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:CC088D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CC08E0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CC08FB* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:CC09C8* + ID_OUI_FROM_DATABASE=IMAQLIQ LTD + +OUI:CC0CDA* + ID_OUI_FROM_DATABASE=Miljovakt AS + +OUI:CC0DEC* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:CC10A3* + ID_OUI_FROM_DATABASE=Beijing Nan Bao Technology Co., Ltd. + +OUI:CC14A6* + ID_OUI_FROM_DATABASE=Yichun MyEnergy Domain, Inc + +OUI:CC167E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CC187B* + ID_OUI_FROM_DATABASE=Manzanita Systems, Inc. + +OUI:CC19A8* + ID_OUI_FROM_DATABASE=PT Inovação e Sistemas SA + +OUI:CC1AFA* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:CC1BE00* + ID_OUI_FROM_DATABASE=Microtech System,Inc + +OUI:CC1BE01* + ID_OUI_FROM_DATABASE=Beijing Daotongtianxia Co.Ltd. + +OUI:CC1BE02* + ID_OUI_FROM_DATABASE=i-Trinetech Co.,Ltd. + +OUI:CC1BE03* + ID_OUI_FROM_DATABASE=Shenzhen Vanstor Technology Co.,Ltd + +OUI:CC1BE04* + ID_OUI_FROM_DATABASE=Laserworld (Switzerland) AG + +OUI:CC1BE05* + ID_OUI_FROM_DATABASE=Earphone Connection, Ubc. + +OUI:CC1BE06* + ID_OUI_FROM_DATABASE=IC RealTech + +OUI:CC1BE07* + ID_OUI_FROM_DATABASE=Sichuan Dianjia network technology Co.Ltd. + +OUI:CC1BE08* + ID_OUI_FROM_DATABASE=MDT technologies GmbH + +OUI:CC1BE09* + ID_OUI_FROM_DATABASE=MobiStor Technology Inc. + +OUI:CC1BE0A* + ID_OUI_FROM_DATABASE=Matter Labs Pty Ltd + +OUI:CC1BE0B* + ID_OUI_FROM_DATABASE=ART&CORE Inc + +OUI:CC1BE0C* + ID_OUI_FROM_DATABASE=Guangzhou Southelectric Power Science Technology Development Co.,Ltd. + +OUI:CC1BE0D* + ID_OUI_FROM_DATABASE=NEWSTAR (HK) ELECTRONIC DEVELOPMENT LIMITED + +OUI:CC1BE0E* + ID_OUI_FROM_DATABASE=Cassia Networks + +OUI:CC1BE0F* + ID_OUI_FROM_DATABASE=Private + +OUI:CC1EFF* + ID_OUI_FROM_DATABASE=Metrological Group BV + +OUI:CC1FC4* + ID_OUI_FROM_DATABASE=InVue + +OUI:CC20E8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CC2119* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:CC2218* + ID_OUI_FROM_DATABASE=InnoDigital Co., Ltd. + +OUI:CC22370* + ID_OUI_FROM_DATABASE=MEDCOM sp. z o.o. + +OUI:CC22371* + ID_OUI_FROM_DATABASE=Terma Sp. z o.o. + +OUI:CC22372* + ID_OUI_FROM_DATABASE=Apeiron Data Systems + +OUI:CC22373* + ID_OUI_FROM_DATABASE=XConnect Professional Services + +OUI:CC22374* + ID_OUI_FROM_DATABASE=SHANGHAI CARGOA M.&E.EQUIPMENT CO.LTD + +OUI:CC22375* + ID_OUI_FROM_DATABASE=Beijing Safesoft Greatmaker Co.,ltd + +OUI:CC22376* + ID_OUI_FROM_DATABASE=Siemens AG Austria + +OUI:CC22377* + ID_OUI_FROM_DATABASE=Shanghai Doit IOT Technology Co.,Ltd. + +OUI:CC22378* + ID_OUI_FROM_DATABASE=Safilo S.p.A. + +OUI:CC22379* + ID_OUI_FROM_DATABASE=E Ink Corp + +OUI:CC2237A* + ID_OUI_FROM_DATABASE=shenzhen zonglian network technology limited + +OUI:CC2237B* + ID_OUI_FROM_DATABASE=Tolomatic, Inc. + +OUI:CC2237C* + ID_OUI_FROM_DATABASE=Hebei ZHSF Technology Co.,Ltd. + +OUI:CC2237D* + ID_OUI_FROM_DATABASE=SHENZHEN HOOENERGY TECHNOLOGY CO.,LTD + +OUI:CC2237E* + ID_OUI_FROM_DATABASE=MANUFACTURAS Y TRANSFORMADOS AB, S.L. + +OUI:CC25EF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CC262D* + ID_OUI_FROM_DATABASE=Verifi, LLC + +OUI:CC29F5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CC2A80* + ID_OUI_FROM_DATABASE=Micro-Biz intelligence solutions Co.,Ltd + +OUI:CC2C83* + ID_OUI_FROM_DATABASE=DarkMatter L.L.C + +OUI:CC2D1B* + ID_OUI_FROM_DATABASE=SFR + +OUI:CC2D21* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:CC2D83* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:CC2D8C* + ID_OUI_FROM_DATABASE=LG ELECTRONICS INC + +OUI:CC2DB7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CC2DE0* + ID_OUI_FROM_DATABASE=Routerboard.com + +OUI:CC2F71* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:CC3080* + ID_OUI_FROM_DATABASE=VAIO Corporation + +OUI:CC32E5* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:CC33BB* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:CC3429* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:CC34D7* + ID_OUI_FROM_DATABASE=GEWISS S.P.A. + +OUI:CC3540* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:CC355A* + ID_OUI_FROM_DATABASE=SecuGen Corporation + +OUI:CC37AB* + ID_OUI_FROM_DATABASE=Edgecore Networks Corporation + +OUI:CC398C* + ID_OUI_FROM_DATABASE=Shiningtek + +OUI:CC3A61* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:CC3ADF* + ID_OUI_FROM_DATABASE=Private + +OUI:CC3B3E* + ID_OUI_FROM_DATABASE=Lester Electrical + +OUI:CC3B58* + ID_OUI_FROM_DATABASE=Curiouser Products Inc + +OUI:CC3C3F* + ID_OUI_FROM_DATABASE=SA.S.S. Datentechnik AG + +OUI:CC3D82* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:CC3E5F* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:CC3F1D* + ID_OUI_FROM_DATABASE=Intesis Software SL + +OUI:CC3FEA* + ID_OUI_FROM_DATABASE=BAE Systems, Inc + +OUI:CC40D0* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:CC418E* + ID_OUI_FROM_DATABASE=MSA Innovation + +OUI:CC43E3* + ID_OUI_FROM_DATABASE=Trump s.a. + +OUI:CC4463* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CC4639* + ID_OUI_FROM_DATABASE=WAAV, Inc. + +OUI:CC464E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:CC46D6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CC4703* + ID_OUI_FROM_DATABASE=Intercon Systems Co., Ltd. + +OUI:CC4AE1* + ID_OUI_FROM_DATABASE=fourtec -Fourier Technologies + +OUI:CC4B73* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:CC4BFB* + ID_OUI_FROM_DATABASE=Hellberg Safety AB + +OUI:CC4D38* + ID_OUI_FROM_DATABASE=Carnegie Technologies + +OUI:CC4E24* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:CC4EEC* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:CC500A* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:CC501C* + ID_OUI_FROM_DATABASE=KVH Industries, Inc. + +OUI:CC5076* + ID_OUI_FROM_DATABASE=Ocom Communications, Inc. + +OUI:CC50E3* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:CC51B4* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:CC5289* + ID_OUI_FROM_DATABASE=SHENZHEN OPTFOCUS TECHNOLOGY.,LTD + +OUI:CC52AF* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:CC53B5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:CC5459* + ID_OUI_FROM_DATABASE=OnTime Networks AS + +OUI:CC55AD* + ID_OUI_FROM_DATABASE=RIM + +OUI:CC593E* + ID_OUI_FROM_DATABASE=Sensium Healthcare Limited + +OUI:CC5A53* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CC5C75* + ID_OUI_FROM_DATABASE=Weightech Com. Imp. Exp. Equip. Pesagem Ltda + +OUI:CC5CDE* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:CC5D4E* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:CC5D57* + ID_OUI_FROM_DATABASE=Information System Research Institute,Inc. + +OUI:CC5D78* + ID_OUI_FROM_DATABASE=JTD Consulting + +OUI:CC5FBF* + ID_OUI_FROM_DATABASE=Topwise 3G Communication Co., Ltd. + +OUI:CC60BB* + ID_OUI_FROM_DATABASE=Empower RF Systems + +OUI:CC61E5* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:CC64A6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:CC65AD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:CC660A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CC66B2* + ID_OUI_FROM_DATABASE=Nokia + +OUI:CC69B0* + ID_OUI_FROM_DATABASE=Global Traffic Technologies, LLC + +OUI:CC6A10* + ID_OUI_FROM_DATABASE=The Chamberlain Group, Inc + +OUI:CC6B98* + ID_OUI_FROM_DATABASE=Minetec Wireless Technologies + +OUI:CC6BF1* + ID_OUI_FROM_DATABASE=Sound Masking Inc. + +OUI:CC6DA0* + ID_OUI_FROM_DATABASE=Roku, Inc. + +OUI:CC6DEF* + ID_OUI_FROM_DATABASE=TJK Tietolaite Oy + +OUI:CC6EA4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:CC70ED* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CC720F* + ID_OUI_FROM_DATABASE=Viscount Systems Inc. + +OUI:CC7286* + ID_OUI_FROM_DATABASE=Xi'an Fengyu Information Technology Co., Ltd. + +OUI:CC7314* + ID_OUI_FROM_DATABASE=HONG KONG WHEATEK TECHNOLOGY LIMITED + +OUI:CC7498* + ID_OUI_FROM_DATABASE=Filmetrics Inc. + +OUI:CC75E2* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:CC7669* + ID_OUI_FROM_DATABASE=SEETECH + +OUI:CC785F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CC78AB* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:CC794A* + ID_OUI_FROM_DATABASE=BLU Products Inc. + +OUI:CC79CF* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:CC7A30* + ID_OUI_FROM_DATABASE=CMAX Wireless Co., Ltd. + +OUI:CC7B35* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:CC7B61* + ID_OUI_FROM_DATABASE=NIKKISO CO., LTD. + +OUI:CC7D37* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:CC7EE7* + ID_OUI_FROM_DATABASE=Panasonic Corporation AVC Networks Company + +OUI:CC7F75* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CC7F76* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CC81DA* + ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd. + +OUI:CC82EB* + ID_OUI_FROM_DATABASE=KYOCERA CORPORATION + +OUI:CC856C* + ID_OUI_FROM_DATABASE=SHENZHEN MDK DIGITAL TECHNOLOGY CO.,LTD + +OUI:CC8826* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:CC89FD* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:CC8CDA* + ID_OUI_FROM_DATABASE=Shenzhen Wei Da Intelligent Technology Go.,Ltd + +OUI:CC8CE3* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:CC8E71* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CC9070* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CC9093* + ID_OUI_FROM_DATABASE=Hansong Tehnologies + +OUI:CC90E8* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:CC912B* + ID_OUI_FROM_DATABASE=TE Connectivity Touch Solutions + +OUI:CC934A* + ID_OUI_FROM_DATABASE=Sierra Wireless + +OUI:CC944A* + ID_OUI_FROM_DATABASE=Pfeiffer Vacuum GmbH + +OUI:CC9470* + ID_OUI_FROM_DATABASE=Kinestral Technologies, Inc. + +OUI:CC95D7* + ID_OUI_FROM_DATABASE=Vizio, Inc + +OUI:CC9635* + ID_OUI_FROM_DATABASE=LVS Co.,Ltd. + +OUI:CC96A0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:CC988B* + ID_OUI_FROM_DATABASE=SONY Visual Products Inc. + +OUI:CC9891* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CC9916* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:CC9E00* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:CC9EA2* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:CC9F35* + ID_OUI_FROM_DATABASE=Transbit Sp. z o.o. + +OUI:CC9F7A* + ID_OUI_FROM_DATABASE=Chiun Mai Communication Systems, Inc + +OUI:CCA0E5* + ID_OUI_FROM_DATABASE=DZG Metering GmbH + +OUI:CCA12B* + ID_OUI_FROM_DATABASE=TCL King Electrical Appliances (Huizhou) Co., Ltd + +OUI:CCA219* + ID_OUI_FROM_DATABASE=SHENZHEN ALONG INVESTMENT CO.,LTD + +OUI:CCA223* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:CCA260* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:CCA374* + ID_OUI_FROM_DATABASE=Guangdong Guanglian Electronic Technology Co.Ltd + +OUI:CCA462* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:CCA4AF* + ID_OUI_FROM_DATABASE=Shenzhen Sowell Technology Co., LTD + +OUI:CCA614* + ID_OUI_FROM_DATABASE=AIFA TECHNOLOGY CORP. + +OUI:CCA7C1* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:CCAF78* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:CCB0DA* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:CCB11A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:CCB255* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:CCB3AB* + ID_OUI_FROM_DATABASE=shenzhen Biocare Bio-Medical Equipment Co.,Ltd. + +OUI:CCB3F8* + ID_OUI_FROM_DATABASE=FUJITSU ISOTEC LIMITED + +OUI:CCB55A* + ID_OUI_FROM_DATABASE=Fraunhofer ITWM + +OUI:CCB691* + ID_OUI_FROM_DATABASE=NECMagnusCommunications + +OUI:CCB888* + ID_OUI_FROM_DATABASE=AnB Securite s.a. + +OUI:CCB8A8* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:CCB8F1* + ID_OUI_FROM_DATABASE=EAGLE KINGDOM TECHNOLOGIES LIMITED + +OUI:CCBBFE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:CCBD35* + ID_OUI_FROM_DATABASE=Steinel GmbH + +OUI:CCBDD3* + ID_OUI_FROM_DATABASE=Ultimaker B.V. + +OUI:CCBE59* + ID_OUI_FROM_DATABASE=Calix Inc. + +OUI:CCBE71* + ID_OUI_FROM_DATABASE=OptiLogix BV + +OUI:CCC079* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:CCC104* + ID_OUI_FROM_DATABASE=Applied Technical Systems + +OUI:CCC2E0* + ID_OUI_FROM_DATABASE=Raisecom Technology CO., LTD + +OUI:CCC3EA* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:CCC50A* + ID_OUI_FROM_DATABASE=SHENZHEN DAJIAHAO TECHNOLOGY CO.,LTD + +OUI:CCC5E5* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:CCC5EF* + ID_OUI_FROM_DATABASE=Co-Comm Servicios Telecomunicaciones S.L. + +OUI:CCC62B* + ID_OUI_FROM_DATABASE=Tri-Systems Corporation + +OUI:CCC760* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CCC8D7* + ID_OUI_FROM_DATABASE=CIAS Elettronica srl + +OUI:CCC92C* + ID_OUI_FROM_DATABASE=Schindler - PORT Technology + +OUI:CCCC4E* + ID_OUI_FROM_DATABASE=Sun Fountainhead USA. Corp + +OUI:CCCC81* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:CCCCCC* + ID_OUI_FROM_DATABASE=Silicon Laboratories + +OUI:CCCD64* + ID_OUI_FROM_DATABASE=SM-Electronic GmbH + +OUI:CCCE1E* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:CCCE40* + ID_OUI_FROM_DATABASE=Janteq Corp + +OUI:CCD281* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:CCD29B* + ID_OUI_FROM_DATABASE=Shenzhen Bopengfa Elec&Technology CO.,Ltd + +OUI:CCD31E0* + ID_OUI_FROM_DATABASE=SAMIM Co + +OUI:CCD31E1* + ID_OUI_FROM_DATABASE=Rondo Burgdorf AG + +OUI:CCD31E2* + ID_OUI_FROM_DATABASE=Neptune Systems + +OUI:CCD31E3* + ID_OUI_FROM_DATABASE=KEN A/S + +OUI:CCD31E4* + ID_OUI_FROM_DATABASE=PJG Systementwicklung GmbH + +OUI:CCD31E5* + ID_OUI_FROM_DATABASE=NTmore.Co.,Ltd + +OUI:CCD31E6* + ID_OUI_FROM_DATABASE=BBPOS International Limited + +OUI:CCD31E7* + ID_OUI_FROM_DATABASE=Shenzhen Decnta Technology Co.,LTD. + +OUI:CCD31E8* + ID_OUI_FROM_DATABASE=inoage GmbH + +OUI:CCD31E9* + ID_OUI_FROM_DATABASE=Siemens AG, MO MLT BG + +OUI:CCD31EA* + ID_OUI_FROM_DATABASE=Haishu Technology LIMITED + +OUI:CCD31EB* + ID_OUI_FROM_DATABASE=Elk Products + +OUI:CCD31EC* + ID_OUI_FROM_DATABASE=NantEnergy + +OUI:CCD31ED* + ID_OUI_FROM_DATABASE=CUJO LLC + +OUI:CCD31EE* + ID_OUI_FROM_DATABASE=ShenZhenBoryNet Co.,LTD. + +OUI:CCD39D0* + ID_OUI_FROM_DATABASE=INX CO.,LTD. + +OUI:CCD39D1* + ID_OUI_FROM_DATABASE=Evoko Unlimited AB + +OUI:CCD39D2* + ID_OUI_FROM_DATABASE=Continental Control Systems + +OUI:CCD39D3* + ID_OUI_FROM_DATABASE=MagTarget LLC + +OUI:CCD39D4* + ID_OUI_FROM_DATABASE=Shenzhen Chenggu Technology Co., Ltd + +OUI:CCD39D5* + ID_OUI_FROM_DATABASE=SHENZHEN ROYOLE TECHNOLOGIES CO., LTD. + +OUI:CCD39D6* + ID_OUI_FROM_DATABASE=Krontech + +OUI:CCD39D7* + ID_OUI_FROM_DATABASE=Glenair + +OUI:CCD39D8* + ID_OUI_FROM_DATABASE=Obelisk Inc. + +OUI:CCD39D9* + ID_OUI_FROM_DATABASE=Bejing Nexsec Inc. + +OUI:CCD39DA* + ID_OUI_FROM_DATABASE=Lubelskie Fabryki Wag FAWAG S.A. + +OUI:CCD39DB* + ID_OUI_FROM_DATABASE=Q-Branch Labs, Inc. + +OUI:CCD39DC* + ID_OUI_FROM_DATABASE=Hangzhou Scooper Technology Co.,Ltd. + +OUI:CCD39DD* + ID_OUI_FROM_DATABASE=Ethernity Networks + +OUI:CCD39DE* + ID_OUI_FROM_DATABASE=Shanghai tongli information technology co. LTD + +OUI:CCD3C1* + ID_OUI_FROM_DATABASE=Vestel Elektronik San ve Tic. A.Ş. + +OUI:CCD3E2* + ID_OUI_FROM_DATABASE=Jiangsu Yinhe Electronics Co.,Ltd. + +OUI:CCD42E* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:CCD4A1* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:CCD539* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CCD811* + ID_OUI_FROM_DATABASE=Aiconn Technology Corporation + +OUI:CCD81F* + ID_OUI_FROM_DATABASE=Maipu Communication Technology Co.,Ltd. + +OUI:CCD8C1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CCD9E9* + ID_OUI_FROM_DATABASE=SCR Engineers Ltd. + +OUI:CCDC55* + ID_OUI_FROM_DATABASE=Dragonchip Limited + +OUI:CCE0C3* + ID_OUI_FROM_DATABASE=EXTEN Technologies, Inc. + +OUI:CCE17F* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:CCE194* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:CCE1D5* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:CCE798* + ID_OUI_FROM_DATABASE=My Social Stuff + +OUI:CCE7DF* + ID_OUI_FROM_DATABASE=American Magnetics, Inc. + +OUI:CCE8AC* + ID_OUI_FROM_DATABASE=SOYEA Technology Co.,Ltd. + +OUI:CCEA1C* + ID_OUI_FROM_DATABASE=DCONWORKS Co., Ltd + +OUI:CCEDDC* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:CCEED9* + ID_OUI_FROM_DATABASE=VAHLE Automation GmbH + +OUI:CCEF03* + ID_OUI_FROM_DATABASE=Hunan Keyshare Communication Technology Co., Ltd. + +OUI:CCEF48* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:CCF0FD* + ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd. + +OUI:CCF3A5* + ID_OUI_FROM_DATABASE=Chi Mei Communication Systems, Inc + +OUI:CCF407* + ID_OUI_FROM_DATABASE=EUKREA ELECTROMATIQUE SARL + +OUI:CCF411* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:CCF538* + ID_OUI_FROM_DATABASE=3isysnetworks + +OUI:CCF67A* + ID_OUI_FROM_DATABASE=Ayecka Communication Systems LTD + +OUI:CCF735* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:CCF841* + ID_OUI_FROM_DATABASE=Lumewave + +OUI:CCF8F0* + ID_OUI_FROM_DATABASE=Xi'an HISU Multimedia Technology Co.,Ltd. + +OUI:CCF954* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:CCF957* + ID_OUI_FROM_DATABASE=u-blox AG + +OUI:CCF9E4* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:CCF9E8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:CCFA00* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:CCFB65* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:CCFC6D* + ID_OUI_FROM_DATABASE=RIZ TRANSMITTERS + +OUI:CCFCB1* + ID_OUI_FROM_DATABASE=Wireless Technology, Inc. + +OUI:CCFD17* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:CCFE3C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D0034B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D003DF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D003EB* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D00401* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:D00492* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:D0052A* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:D005E4* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:D00790* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D007CA* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:D00AAB* + ID_OUI_FROM_DATABASE=Yokogawa Digital Computer Corporation + +OUI:D00EA4* + ID_OUI_FROM_DATABASE=Porsche Cars North America + +OUI:D00ED9* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:D00F6D* + ID_OUI_FROM_DATABASE=T&W Electronics Company + +OUI:D01242* + ID_OUI_FROM_DATABASE=BIOS Corporation + +OUI:D0131E* + ID_OUI_FROM_DATABASE=Sunrex Technology Corp + +OUI:D013FD* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:D0154A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D015A6* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:D016B4* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D0176A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D017C2* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:D0196A* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:D01AA7* + ID_OUI_FROM_DATABASE=UniPrint + +OUI:D01C3C* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:D01CBB* + ID_OUI_FROM_DATABASE=Beijing Ctimes Digital Technology Co., Ltd. + +OUI:D022120* + ID_OUI_FROM_DATABASE=Spirit IT B.V. + +OUI:D022121* + ID_OUI_FROM_DATABASE=AIM + +OUI:D022122* + ID_OUI_FROM_DATABASE=RHENAC Systems GmbH + +OUI:D022124* + ID_OUI_FROM_DATABASE=Viatron GmbH + +OUI:D022125* + ID_OUI_FROM_DATABASE=Shanghai Routech Co., Ltd + +OUI:D022126* + ID_OUI_FROM_DATABASE=URANO INDUSTRIA DE BALANCAS E EQUIPAMENTOS LTDA + +OUI:D022127* + ID_OUI_FROM_DATABASE=Cliptech Industria e Comercio Ltda + +OUI:D022128* + ID_OUI_FROM_DATABASE=Shenzhen SIC Technology. Co., Ltd. + +OUI:D022129* + ID_OUI_FROM_DATABASE=UAB "SALDA" + +OUI:D02212A* + ID_OUI_FROM_DATABASE=GNS-GmbH + +OUI:D02212B* + ID_OUI_FROM_DATABASE=Schleifenbauer Holding BV + +OUI:D02212C* + ID_OUI_FROM_DATABASE=Xperio Labs Ltd. + +OUI:D02212D* + ID_OUI_FROM_DATABASE=SHENZHEN ZHONGXI SECURITY CO.,LTD + +OUI:D02212E* + ID_OUI_FROM_DATABASE=u::Lux GmbH + +OUI:D02212F* + ID_OUI_FROM_DATABASE=Private + +OUI:D022BE* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:D023DB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D02516* + ID_OUI_FROM_DATABASE=MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:D02544* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:D02598* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D02788* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:D028BA* + ID_OUI_FROM_DATABASE=Realme Chongqing MobileTelecommunications Corp Ltd + +OUI:D02B20* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D02C45* + ID_OUI_FROM_DATABASE=littleBits Electronics, Inc. + +OUI:D02DB3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D03110* + ID_OUI_FROM_DATABASE=Ingenic Semiconductor Co.,Ltd + +OUI:D03169* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D03311* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D03742* + ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + +OUI:D03745* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:D03761* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D03972* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D039B3* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D039EA* + ID_OUI_FROM_DATABASE=NetApp + +OUI:D03D52* + ID_OUI_FROM_DATABASE=Vaion Limited + +OUI:D03DC3* + ID_OUI_FROM_DATABASE=AQ Corporation + +OUI:D03E5C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D03FAA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D041C9* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:D0431E* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:D046DC* + ID_OUI_FROM_DATABASE=Southwest Research Institute + +OUI:D048F3* + ID_OUI_FROM_DATABASE=DATTUS Inc + +OUI:D0498B* + ID_OUI_FROM_DATABASE=ZOOM SERVER + +OUI:D04CC1* + ID_OUI_FROM_DATABASE=SINTRONES Technology Corp. + +OUI:D04D2C* + ID_OUI_FROM_DATABASE=Roku, Inc. + +OUI:D04E50* + ID_OUI_FROM_DATABASE=Mobiwire Mobiles (NingBo) Co., LTD + +OUI:D04F7E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D05099* + ID_OUI_FROM_DATABASE=ASRock Incorporation + +OUI:D05157* + ID_OUI_FROM_DATABASE=LEAX Arkivator Telecom + +OUI:D05162* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:D052A8* + ID_OUI_FROM_DATABASE=Physical Graph Corporation + +OUI:D05349* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:D0542D* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:D055B2* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:D0574C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D0577B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D05785* + ID_OUI_FROM_DATABASE=Pantech Co., Ltd. + +OUI:D05794* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:D057A1* + ID_OUI_FROM_DATABASE=Werma Signaltechnik GmbH & Co. KG + +OUI:D05875* + ID_OUI_FROM_DATABASE=Active Control Technology Inc. + +OUI:D058A8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D058C0* + ID_OUI_FROM_DATABASE=Qingdao Haier Multimedia Limited. + +OUI:D058FC* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:D05995* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:D059C3* + ID_OUI_FROM_DATABASE=CeraMicro Technology Corporation + +OUI:D059E4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D05A00* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:D05A0F* + ID_OUI_FROM_DATABASE=I-BT DIGITAL CO.,LTD + +OUI:D05AF1* + ID_OUI_FROM_DATABASE=Shenzhen Pulier Tech CO.,Ltd + +OUI:D05BA8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D05C7A* + ID_OUI_FROM_DATABASE=Sartura d.o.o. + +OUI:D05F640* + ID_OUI_FROM_DATABASE=Decathlon SA + +OUI:D05F641* + ID_OUI_FROM_DATABASE=Hangzhou ToupTek Photonics Co., Ltd. + +OUI:D05F642* + ID_OUI_FROM_DATABASE=SHANGHAI ZHONGMI COMMUNICATION TECHNOLOGY CO.,LTD + +OUI:D05F643* + ID_OUI_FROM_DATABASE=HUAQIN TELECOM HONG KONG LTD + +OUI:D05F644* + ID_OUI_FROM_DATABASE=wallbe GmbH + +OUI:D05F645* + ID_OUI_FROM_DATABASE=Atoll Solutions Private Limited + +OUI:D05F646* + ID_OUI_FROM_DATABASE=Cyrus Technology GmbH + +OUI:D05F647* + ID_OUI_FROM_DATABASE=Beijing Core Shield Group Co., Ltd. + +OUI:D05F648* + ID_OUI_FROM_DATABASE=TytoCare LTD. + +OUI:D05F649* + ID_OUI_FROM_DATABASE=Shanghai Luying International Trade Co.,Ltd + +OUI:D05F64A* + ID_OUI_FROM_DATABASE=PartnerNET LTD + +OUI:D05F64B* + ID_OUI_FROM_DATABASE=North American Blue Tiger Company, LLC + +OUI:D05F64C* + ID_OUI_FROM_DATABASE=Nanjing Huamai Technology Co.,Ltd + +OUI:D05F64D* + ID_OUI_FROM_DATABASE=Shenzhen Canzone Technology Co.,Ltd. + +OUI:D05F64E* + ID_OUI_FROM_DATABASE=Montblanc-Simplo GmbH + +OUI:D05FB8* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D05FCE* + ID_OUI_FROM_DATABASE=Hitachi Data Systems + +OUI:D0608C* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D062A0* + ID_OUI_FROM_DATABASE=China Essence Technology (Zhumadian) Co., Ltd. + +OUI:D0634D* + ID_OUI_FROM_DATABASE=Meiko Maschinenbau GmbH & Co. KG + +OUI:D063B4* + ID_OUI_FROM_DATABASE=SolidRun Ltd. + +OUI:D06544* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D065CA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D0666D* + ID_OUI_FROM_DATABASE=Shenzhen Bus-Lan Technology Co., Ltd. + +OUI:D0667B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D06726* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:D067E5* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:D0699E* + ID_OUI_FROM_DATABASE=LUMINEX Lighting Control Equipment + +OUI:D069D0* + ID_OUI_FROM_DATABASE=Verto Medical Solutions, LLC + +OUI:D06A1F* + ID_OUI_FROM_DATABASE=BSE CO.,LTD. + +OUI:D06EDE* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:D06F4A* + ID_OUI_FROM_DATABASE=TOPWELL INTERNATIONAL HOLDINGS LIMITED + +OUI:D06F82* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D071C4* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D072DC* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D0737F* + ID_OUI_FROM_DATABASE=Mini-Circuits + +OUI:D0738E* + ID_OUI_FROM_DATABASE=DONG OH PRECISION CO., LTD. + +OUI:D073D5* + ID_OUI_FROM_DATABASE=LIFI LABS MANAGEMENT PTY LTD + +OUI:D075BE* + ID_OUI_FROM_DATABASE=Reno A&E + +OUI:D076500* + ID_OUI_FROM_DATABASE=CentrAlert, Inc. + +OUI:D076501* + ID_OUI_FROM_DATABASE=DAIKEN AUTOMACAO LTDA + +OUI:D076502* + ID_OUI_FROM_DATABASE=Happo Solutions Oy + +OUI:D076503* + ID_OUI_FROM_DATABASE=TAPKO Technologies GmbH + +OUI:D076504* + ID_OUI_FROM_DATABASE=Private + +OUI:D076505* + ID_OUI_FROM_DATABASE=Annapurna Labs + +OUI:D076506* + ID_OUI_FROM_DATABASE=Picobrew LLC + +OUI:D076507* + ID_OUI_FROM_DATABASE=ENCORED Technologies, Inc. + +OUI:D076508* + ID_OUI_FROM_DATABASE=Accumulate AB + +OUI:D076509* + ID_OUI_FROM_DATABASE=Greenwave Scientific + +OUI:D07650A* + ID_OUI_FROM_DATABASE=InventDesign + +OUI:D07650B* + ID_OUI_FROM_DATABASE=PelKorea + +OUI:D07650C* + ID_OUI_FROM_DATABASE=Electro-Motive Diesel + +OUI:D07650D* + ID_OUI_FROM_DATABASE=tecnotron elekronik gmbh + +OUI:D07650E* + ID_OUI_FROM_DATABASE=Revox Inc. + +OUI:D07650F* + ID_OUI_FROM_DATABASE=Private + +OUI:D076E7* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:D07714* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:D07AB5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D07C2D* + ID_OUI_FROM_DATABASE=Leie IOT technology Co., Ltd + +OUI:D07DE5* + ID_OUI_FROM_DATABASE=Forward Pay Systems, Inc. + +OUI:D07E28* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:D07E35* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D07FA0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D07FC4* + ID_OUI_FROM_DATABASE=Ou Wei Technology Co.,Ltd. of Shenzhen City + +OUI:D0817A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D083D4* + ID_OUI_FROM_DATABASE=Xtel Wireless ApS + +OUI:D084B0* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:D087E2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D08999* + ID_OUI_FROM_DATABASE=APCON, Inc. + +OUI:D08A55* + ID_OUI_FROM_DATABASE=Skullcandy + +OUI:D08A91* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:D08B7E* + ID_OUI_FROM_DATABASE=Passif Semiconductor + +OUI:D08CB5* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D08CFF* + ID_OUI_FROM_DATABASE=UPWIS AB + +OUI:D0929E* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:D092FA* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:D09380* + ID_OUI_FROM_DATABASE=Ducere Technologies Pvt. Ltd. + +OUI:D093F8* + ID_OUI_FROM_DATABASE=Stonestreet One LLC + +OUI:D09466* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:D095C7* + ID_OUI_FROM_DATABASE=Pantech Co., Ltd. + +OUI:D096FB* + ID_OUI_FROM_DATABASE=DASAN Network Solutions + +OUI:D099D5* + ID_OUI_FROM_DATABASE=Alcatel-Lucent + +OUI:D09B05* + ID_OUI_FROM_DATABASE=Emtronix + +OUI:D09C30* + ID_OUI_FROM_DATABASE=Foster Electric Company, Limited + +OUI:D09C7A* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:D09D0A* + ID_OUI_FROM_DATABASE=LINKCOM + +OUI:D09DAB* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:D0A0D6* + ID_OUI_FROM_DATABASE=Chengdu TD Tech Ltd. + +OUI:D0A311* + ID_OUI_FROM_DATABASE=Neuberger Gebäudeautomation GmbH + +OUI:D0A4B1* + ID_OUI_FROM_DATABASE=Sonifex Ltd. + +OUI:D0A5A6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D0A637* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D0ABD5* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D0AEEC* + ID_OUI_FROM_DATABASE=Alpha Networks Inc. + +OUI:D0AFB6* + ID_OUI_FROM_DATABASE=Linktop Technology Co., LTD + +OUI:D0B0CD* + ID_OUI_FROM_DATABASE=Moen + +OUI:D0B128* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D0B214* + ID_OUI_FROM_DATABASE=PoeWit Inc + +OUI:D0B2C4* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:D0B33F* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:D0B45D* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:D0B498* + ID_OUI_FROM_DATABASE=Robert Bosch LLC Automotive Electronics + +OUI:D0B523* + ID_OUI_FROM_DATABASE=Bestcare Cloucal Corp. + +OUI:D0B53D* + ID_OUI_FROM_DATABASE=SEPRO ROBOTIQUE + +OUI:D0B5C2* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D0B60A* + ID_OUI_FROM_DATABASE=Xingluo Technology Company Limited + +OUI:D0BAE4* + ID_OUI_FROM_DATABASE=Shanghai MXCHIP Information Technology Co., Ltd. + +OUI:D0BB80* + ID_OUI_FROM_DATABASE=SHL Telemedicine International Ltd. + +OUI:D0BD01* + ID_OUI_FROM_DATABASE=DS International + +OUI:D0BE2C* + ID_OUI_FROM_DATABASE=CNSLink Co., Ltd. + +OUI:D0BF9C* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:D0C0BF* + ID_OUI_FROM_DATABASE=Actions Microelectronics Co., Ltd + +OUI:D0C193* + ID_OUI_FROM_DATABASE=SKYBELL, INC + +OUI:D0C1B1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D0C282* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D0C42F* + ID_OUI_FROM_DATABASE=Tamagawa Seiki Co.,Ltd. + +OUI:D0C5D3* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:D0C5D8* + ID_OUI_FROM_DATABASE=LATECOERE + +OUI:D0C5F3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D0C637* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D0C65B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D0C789* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D0C7C0* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:D0C8570* + ID_OUI_FROM_DATABASE=YUAN High-Tech Development Co., Ltd. + +OUI:D0C8571* + ID_OUI_FROM_DATABASE=DALI A/S + +OUI:D0C8572* + ID_OUI_FROM_DATABASE=FORGAMERS INC. + +OUI:D0C8573* + ID_OUI_FROM_DATABASE=Mobicon + +OUI:D0C8574* + ID_OUI_FROM_DATABASE=Imin Technology Pte Ltd + +OUI:D0C8575* + ID_OUI_FROM_DATABASE=Beijing Inspiry Technology Co., Ltd. + +OUI:D0C8576* + ID_OUI_FROM_DATABASE=Innovative Industrial(HK)Co., Limited + +OUI:D0C8577* + ID_OUI_FROM_DATABASE=Eco Mobile + +OUI:D0C8578* + ID_OUI_FROM_DATABASE=Nanjing Magewell Electronics Co.,Ltd + +OUI:D0C8579* + ID_OUI_FROM_DATABASE=Shenzhen xiaosha Intelligence Technology Co. Ltd + +OUI:D0C857A* + ID_OUI_FROM_DATABASE=shenzhen cnsun + +OUI:D0C857B* + ID_OUI_FROM_DATABASE=CHUNGHSIN INTERNATIONAL ELECTRONICS CO.,LTD. + +OUI:D0C857C* + ID_OUI_FROM_DATABASE=Dante Security Inc. + +OUI:D0C857D* + ID_OUI_FROM_DATABASE=IFLYTEK CO.,LTD. + +OUI:D0C857E* + ID_OUI_FROM_DATABASE=E-T-A Elektrotechnische Apparate GmbH + +OUI:D0CDE1* + ID_OUI_FROM_DATABASE=Scientech Electronics + +OUI:D0CF5E* + ID_OUI_FROM_DATABASE=Energy Micro AS + +OUI:D0D003* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,LTD + +OUI:D0D04B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D0D0FD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D0D212* + ID_OUI_FROM_DATABASE=K2NET Co.,Ltd. + +OUI:D0D286* + ID_OUI_FROM_DATABASE=Beckman Coulter K.K. + +OUI:D0D2B0* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D0D3E0* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:D0D3FC* + ID_OUI_FROM_DATABASE=Mios, Ltd. + +OUI:D0D412* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:D0D471* + ID_OUI_FROM_DATABASE=MVTECH co., Ltd + +OUI:D0D6CC* + ID_OUI_FROM_DATABASE=Wintop + +OUI:D0D783* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D0D94F0* + ID_OUI_FROM_DATABASE=Perfant Technology Co., Ltd + +OUI:D0D94F1* + ID_OUI_FROM_DATABASE=mycable GmbH + +OUI:D0D94F2* + ID_OUI_FROM_DATABASE=Teco Image Systems Co., Ltd. + +OUI:D0D94F3* + ID_OUI_FROM_DATABASE=Beijing Yiwangxuntong Technology + +OUI:D0D94F4* + ID_OUI_FROM_DATABASE=peiker CEE + +OUI:D0D94F5* + ID_OUI_FROM_DATABASE=Optigo Networks + +OUI:D0D94F6* + ID_OUI_FROM_DATABASE=Hyundai Autohow + +OUI:D0D94F7* + ID_OUI_FROM_DATABASE=Private + +OUI:D0D94F8* + ID_OUI_FROM_DATABASE=Apption Labs Limited + +OUI:D0D94F9* + ID_OUI_FROM_DATABASE=Hangzhou xiaoben technology co.,Ltd + +OUI:D0D94FA* + ID_OUI_FROM_DATABASE=Shenzhen FDC Electuonic Co.,Ltd. + +OUI:D0D94FB* + ID_OUI_FROM_DATABASE=MAX Smart Home, LLC + +OUI:D0D94FC* + ID_OUI_FROM_DATABASE=ARROWAVE TECHNOLOGIES LIMITED + +OUI:D0D94FD* + ID_OUI_FROM_DATABASE=DUKSANMECASYS CO., LTD. + +OUI:D0D94FE* + ID_OUI_FROM_DATABASE=APPOTRONICS CO., LTD + +OUI:D0DB32* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:D0DD49* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:D0DF9A* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:D0DFB2* + ID_OUI_FROM_DATABASE=Genie Networks Limited + +OUI:D0DFC7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D0E140* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D0E347* + ID_OUI_FROM_DATABASE=Yoga + +OUI:D0E40B* + ID_OUI_FROM_DATABASE=Wearable Inc. + +OUI:D0E44A* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:D0E54D* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D0E782* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:D0EB03* + ID_OUI_FROM_DATABASE=Zhehua technology limited + +OUI:D0EB9E* + ID_OUI_FROM_DATABASE=Seowoo Inc. + +OUI:D0EC35* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D0EFC1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D0F0DB* + ID_OUI_FROM_DATABASE=Ericsson + +OUI:D0F27F* + ID_OUI_FROM_DATABASE=SteadyServ Technoligies, LLC + +OUI:D0F73B* + ID_OUI_FROM_DATABASE=Helmut Mauell GmbH Werk Weida + +OUI:D0F88C* + ID_OUI_FROM_DATABASE=Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + +OUI:D0FA1D* + ID_OUI_FROM_DATABASE=Qihoo 360 Technology Co.,Ltd + +OUI:D0FCCC* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D0FF50* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D0FF98* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D4000D* + ID_OUI_FROM_DATABASE=Phoenix Broadband Technologies, LLC. + +OUI:D40057* + ID_OUI_FROM_DATABASE=MC Technologies GmbH + +OUI:D40129* + ID_OUI_FROM_DATABASE=Broadcom + +OUI:D4016D* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:D4024A* + ID_OUI_FROM_DATABASE=Delphian Systems LLC + +OUI:D404CD* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D404FF* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:D40598* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D40AA9* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D40B1A* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:D40BB9* + ID_OUI_FROM_DATABASE=Solid Semecs bv. + +OUI:D40FB2* + ID_OUI_FROM_DATABASE=Applied Micro Electronics AME bv + +OUI:D41090* + ID_OUI_FROM_DATABASE=iNFORM Systems AG + +OUI:D410CF* + ID_OUI_FROM_DATABASE=Huanshun Network Science and Technology Co., Ltd. + +OUI:D411A3* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D411D6* + ID_OUI_FROM_DATABASE=ShotSpotter, Inc. + +OUI:D41243* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:D41296* + ID_OUI_FROM_DATABASE=Anobit Technologies Ltd. + +OUI:D412BB* + ID_OUI_FROM_DATABASE=Quadrant Components Inc. Ltd + +OUI:D4136F* + ID_OUI_FROM_DATABASE=Asia Pacific Brands + +OUI:D41A3F* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:D41C1C* + ID_OUI_FROM_DATABASE=RCF S.P.A. + +OUI:D41D71* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:D41E35* + ID_OUI_FROM_DATABASE=TOHO Electronics INC. + +OUI:D41F0C* + ID_OUI_FROM_DATABASE=JAI Manufacturing + +OUI:D4206D* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:D420B0* + ID_OUI_FROM_DATABASE=Mist Systems, Inc. + +OUI:D42122* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:D4223F* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:D4224E* + ID_OUI_FROM_DATABASE=Alcatel Lucent + +OUI:D422CD* + ID_OUI_FROM_DATABASE=Xsens Technologies B.V. + +OUI:D42493* + ID_OUI_FROM_DATABASE=GW Technologies Co.,Ltd + +OUI:D4258B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D425CC0* + ID_OUI_FROM_DATABASE=NORDI TELEKOMMUNIKATSIOONI OÜ + +OUI:D425CC1* + ID_OUI_FROM_DATABASE=Eware Information Technology com.,Ltd + +OUI:D425CC2* + ID_OUI_FROM_DATABASE=MusicLens Inc. + +OUI:D425CC3* + ID_OUI_FROM_DATABASE=EISST Ltd + +OUI:D425CC4* + ID_OUI_FROM_DATABASE=Barobo, Inc. + +OUI:D425CC5* + ID_OUI_FROM_DATABASE=bvk technology + +OUI:D425CC6* + ID_OUI_FROM_DATABASE=Nanjing LES Information Technology Co., Ltd + +OUI:D425CC7* + ID_OUI_FROM_DATABASE=BlueCats US, LLC + +OUI:D425CC8* + ID_OUI_FROM_DATABASE=DOLBY LABORATORIES, INC. + +OUI:D425CC9* + ID_OUI_FROM_DATABASE=TAKUMI JAPAN LTD + +OUI:D425CCA* + ID_OUI_FROM_DATABASE=E-MetroTel + +OUI:D425CCB* + ID_OUI_FROM_DATABASE=Veea + +OUI:D425CCC* + ID_OUI_FROM_DATABASE=POSNET Polska S.A. + +OUI:D425CCD* + ID_OUI_FROM_DATABASE=Combined Energy Technologies Pty Ltd + +OUI:D425CCE* + ID_OUI_FROM_DATABASE=Coperion + +OUI:D42751* + ID_OUI_FROM_DATABASE=Infopia Co., Ltd + +OUI:D428B2* + ID_OUI_FROM_DATABASE=ioBridge, Inc. + +OUI:D428D5* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:D429EA* + ID_OUI_FROM_DATABASE=Zimory GmbH + +OUI:D42C0F* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D42C3D* + ID_OUI_FROM_DATABASE=Sky Light Digital Limited + +OUI:D42C44* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D42DC5* + ID_OUI_FROM_DATABASE=Panasonic i-PRO Sensing Solutions Co., Ltd. + +OUI:D42F23* + ID_OUI_FROM_DATABASE=Akenori PTE Ltd + +OUI:D4319D* + ID_OUI_FROM_DATABASE=Sinwatec + +OUI:D43260* + ID_OUI_FROM_DATABASE=GoPro + +OUI:D43266* + ID_OUI_FROM_DATABASE=Fike Corporation + +OUI:D4351D* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:D43639* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D436DB* + ID_OUI_FROM_DATABASE=Jiangsu Toppower Automotive Electronics Co., Ltd + +OUI:D437D7* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D4389C* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:D43A2E* + ID_OUI_FROM_DATABASE=SHENZHEN MTC CO LTD + +OUI:D43A65* + ID_OUI_FROM_DATABASE=IGRS Engineering Lab Ltd. + +OUI:D43AE9* + ID_OUI_FROM_DATABASE=DONGGUAN ipt INDUSTRIAL CO., LTD + +OUI:D43B04* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D43D39* + ID_OUI_FROM_DATABASE=Dialog Semiconductor + +OUI:D43D67* + ID_OUI_FROM_DATABASE=Carma Industries Inc. + +OUI:D43D7E* + ID_OUI_FROM_DATABASE=Micro-Star Int'l Co, Ltd + +OUI:D43FCB* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D440F0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D44165* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:D443A8* + ID_OUI_FROM_DATABASE=Changzhou Haojie Electric Co., Ltd. + +OUI:D445E8* + ID_OUI_FROM_DATABASE=Jiangxi Hongpai Technology Co., Ltd. + +OUI:D446E1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D44B5E* + ID_OUI_FROM_DATABASE=TAIYO YUDEN CO., LTD. + +OUI:D44BB6* + ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd. + +OUI:D44C24* + ID_OUI_FROM_DATABASE=Vuppalamritha Magnetic Components LTD + +OUI:D44C9C* + ID_OUI_FROM_DATABASE=Shenzhen YOOBAO Technology Co.Ltd + +OUI:D44CA7* + ID_OUI_FROM_DATABASE=Informtekhnika & Communication, LLC + +OUI:D44DA4* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:D44F68* + ID_OUI_FROM_DATABASE=Eidetic Communications Inc + +OUI:D44F80* + ID_OUI_FROM_DATABASE=Kemper Digital GmbH + +OUI:D4503F* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:D4507A* + ID_OUI_FROM_DATABASE=CEIVA Logic, Inc + +OUI:D4522A* + ID_OUI_FROM_DATABASE=TangoWiFi.com + +OUI:D45251* + ID_OUI_FROM_DATABASE=IBT Ingenieurbureau Broennimann Thun + +OUI:D45297* + ID_OUI_FROM_DATABASE=nSTREAMS Technologies, Inc. + +OUI:D452EE* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:D45383* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:D453AF* + ID_OUI_FROM_DATABASE=VIGO System S.A. + +OUI:D45556* + ID_OUI_FROM_DATABASE=Fiber Mountain Inc. + +OUI:D455BE* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:D45800* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:D45AB2* + ID_OUI_FROM_DATABASE=Galleon Systems + +OUI:D45C70* + ID_OUI_FROM_DATABASE=Wi-Fi Alliance + +OUI:D45D42* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:D45D64* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:D45DDF* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:D45EEC* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd. + +OUI:D45F25* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:D46075* + ID_OUI_FROM_DATABASE=Baidu Online Network Technology (Beijing) Co., Ltd + +OUI:D460E3* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:D4612E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D46132* + ID_OUI_FROM_DATABASE=Pro Concept Manufacturer Co.,Ltd. + +OUI:D4619D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D461DA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D461FE* + ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited + +OUI:D462EA* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D463C6* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:D463FE* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:D464F7* + ID_OUI_FROM_DATABASE=CHENGDU USEE DIGITAL TECHNOLOGY CO., LTD + +OUI:D466A8* + ID_OUI_FROM_DATABASE=Riedo Networks Ltd + +OUI:D46761* + ID_OUI_FROM_DATABASE=United Gulf Gate Co. + +OUI:D467D3* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:D467E7* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:D4684D* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:D46867* + ID_OUI_FROM_DATABASE=Neoventus Design Group + +OUI:D468BA* + ID_OUI_FROM_DATABASE=Shenzhen Sundray Technologies Company Limited + +OUI:D469A5* + ID_OUI_FROM_DATABASE=Miura Systems Ltd. + +OUI:D46A35* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D46A6A* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:D46A91* + ID_OUI_FROM_DATABASE=Snap AV + +OUI:D46AA8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D46BA6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D46CBF* + ID_OUI_FROM_DATABASE=Goodrich ISR + +OUI:D46CDA* + ID_OUI_FROM_DATABASE=CSM GmbH + +OUI:D46D50* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D46D6D* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D46E0E* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:D46E5C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D46F42* + ID_OUI_FROM_DATABASE=WAXESS USA Inc + +OUI:D47208* + ID_OUI_FROM_DATABASE=Bragi GmbH + +OUI:D47226* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D4741B* + ID_OUI_FROM_DATABASE=Beijing HuaDa ZhiBao Electronic System Co.,Ltd. + +OUI:D476EA* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D4772B* + ID_OUI_FROM_DATABASE=Nanjing Ztlink Network Technology Co.,Ltd + +OUI:D47856* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:D4789B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D479C3* + ID_OUI_FROM_DATABASE=Cameronet GmbH & Co. KG + +OUI:D47AE2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D47B35* + ID_OUI_FROM_DATABASE=NEO Monitors AS + +OUI:D47B75* + ID_OUI_FROM_DATABASE=HARTING Electronics GmbH + +OUI:D47BB0* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:D47C440* + ID_OUI_FROM_DATABASE=Exafore Oy + +OUI:D47C441* + ID_OUI_FROM_DATABASE=Innoviz Technologies LTD + +OUI:D47C442* + ID_OUI_FROM_DATABASE=YunDing Network Technology (Beijing) Co., Ltd + +OUI:D47C443* + ID_OUI_FROM_DATABASE=OMRON SENTECH CO., LTD. + +OUI:D47C444* + ID_OUI_FROM_DATABASE=Sammi Onformation Systems + +OUI:D47C445* + ID_OUI_FROM_DATABASE=LS Communication Co.,Ltd. + +OUI:D47C446* + ID_OUI_FROM_DATABASE=ASDA ICT Co., Ltd. + +OUI:D47C447* + ID_OUI_FROM_DATABASE=Pongee Industries Co., Ltd. + +OUI:D47C448* + ID_OUI_FROM_DATABASE=Beijing Maystar Information Technology Co., Ltd. + +OUI:D47C449* + ID_OUI_FROM_DATABASE=Suzhou Wan Dian Zhang Network Technology Co., Ltd + +OUI:D47C44A* + ID_OUI_FROM_DATABASE=Tendzone International Pte Ltd + +OUI:D47C44B* + ID_OUI_FROM_DATABASE=OPTiM Corporation + +OUI:D47C44C* + ID_OUI_FROM_DATABASE=STRIVE ORTHOPEDICS INC + +OUI:D47C44D* + ID_OUI_FROM_DATABASE=Huaqin Telecom Technology Co.,Ltd. + +OUI:D47C44E* + ID_OUI_FROM_DATABASE=SHENZHEN ANYSEC TECHNOLOGY CO. LTD + +OUI:D47DFC* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:D481CA* + ID_OUI_FROM_DATABASE=iDevices, LLC + +OUI:D481D7* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:D4823E* + ID_OUI_FROM_DATABASE=Argosy Technologies, Ltd. + +OUI:D48304* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:D48564* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:D487D8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D4883F* + ID_OUI_FROM_DATABASE=HDPRO CO., LTD. + +OUI:D48890* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D48A39* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D48CB5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D48DD9* + ID_OUI_FROM_DATABASE=Meld Technology, Inc + +OUI:D48F33* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:D48FAA* + ID_OUI_FROM_DATABASE=Sogecam Industrial, S.A. + +OUI:D4909C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D490E0* + ID_OUI_FROM_DATABASE=Topcon Electronics GmbH & Co. KG + +OUI:D491AF* + ID_OUI_FROM_DATABASE=Electroacustica General Iberica, S.A. + +OUI:D49234* + ID_OUI_FROM_DATABASE=NEC Corporation + +OUI:D49398* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:D493A0* + ID_OUI_FROM_DATABASE=Fidelix Oy + +OUI:D4945A* + ID_OUI_FROM_DATABASE=COSMO CO., LTD + +OUI:D494A1* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D494E8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D49524* + ID_OUI_FROM_DATABASE=Clover Network, Inc. + +OUI:D496DF* + ID_OUI_FROM_DATABASE=SUNGJIN C&T CO.,LTD + +OUI:D4970B* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:D49A20* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D49AA0* + ID_OUI_FROM_DATABASE=VNPT TECHNOLOGY + +OUI:D49B5C* + ID_OUI_FROM_DATABASE=Chongqing Miedu Technology Co., Ltd. + +OUI:D49C28* + ID_OUI_FROM_DATABASE=JayBird LLC + +OUI:D49C8E* + ID_OUI_FROM_DATABASE=University of FUKUI + +OUI:D49CDD* + ID_OUI_FROM_DATABASE=AMPAK Technology,Inc. + +OUI:D49CF4* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:D49DC0* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D49E05* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D49E3B* + ID_OUI_FROM_DATABASE=Guangzhou Shiyuan Electronic Technology Company Limited + +OUI:D49E6D* + ID_OUI_FROM_DATABASE=Wuhan Zhongyuan Huadian Science & Technology Co., + +OUI:D4A02A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D4A148* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D4A33D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D4A425* + ID_OUI_FROM_DATABASE=SMAX Technology Co., Ltd. + +OUI:D4A499* + ID_OUI_FROM_DATABASE=InView Technology Corporation + +OUI:D4A928* + ID_OUI_FROM_DATABASE=GreenWave Reality Inc + +OUI:D4AAFF* + ID_OUI_FROM_DATABASE=MICRO WORLD + +OUI:D4AB82* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D4AC4E* + ID_OUI_FROM_DATABASE=BODi rS, LLC + +OUI:D4AD2D* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:D4AD71* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D4ADBD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D4AE05* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D4AE52* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:D4B110* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D4B169* + ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited + +OUI:D4B27A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D4B43E* + ID_OUI_FROM_DATABASE=Messcomp Datentechnik GmbH + +OUI:D4B709* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D4B761* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:D4B8FF* + ID_OUI_FROM_DATABASE=Home Control Singapore Pte Ltd + +OUI:D4B92F* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:D4BBC8* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:D4BBE6* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:D4BD1E* + ID_OUI_FROM_DATABASE=5VT Technologies,Taiwan LTd. + +OUI:D4BED9* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:D4BF2D* + ID_OUI_FROM_DATABASE=SE Controls Asia Pacific Ltd + +OUI:D4BF7F* + ID_OUI_FROM_DATABASE=UPVEL + +OUI:D4C19E* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:D4C1C8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D4C1FC* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:D4C766* + ID_OUI_FROM_DATABASE=Acentic GmbH + +OUI:D4C8B0* + ID_OUI_FROM_DATABASE=Prime Electronics & Satellitics Inc. + +OUI:D4C93C* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D4C94B* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:D4C9B2* + ID_OUI_FROM_DATABASE=Quanergy Systems Inc + +OUI:D4C9EF* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:D4CA6D* + ID_OUI_FROM_DATABASE=Routerboard.com + +OUI:D4CA6E* + ID_OUI_FROM_DATABASE=u-blox AG + +OUI:D4CBAF* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:D4CEB8* + ID_OUI_FROM_DATABASE=Enatel LTD + +OUI:D4CF37* + ID_OUI_FROM_DATABASE=Symbolic IO + +OUI:D4CFF9* + ID_OUI_FROM_DATABASE=Shenzhen SEI Robotics Co.,Ltd + +OUI:D4D184* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:D4D249* + ID_OUI_FROM_DATABASE=Power Ethernet + +OUI:D4D252* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D4D2D6* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:D4D2E5* + ID_OUI_FROM_DATABASE=BKAV Corporation + +OUI:D4D50D* + ID_OUI_FROM_DATABASE=Southwest Microwave, Inc + +OUI:D4D748* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D4D7A9* + ID_OUI_FROM_DATABASE=Shanghai Kaixiang Info Tech LTD + +OUI:D4D898* + ID_OUI_FROM_DATABASE=Korea CNO Tech Co., Ltd + +OUI:D4D919* + ID_OUI_FROM_DATABASE=GoPro + +OUI:D4DACD* + ID_OUI_FROM_DATABASE=BSkyB Ltd + +OUI:D4DC09* + ID_OUI_FROM_DATABASE=Mist Systems, Inc. + +OUI:D4DCCD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D4DF57* + ID_OUI_FROM_DATABASE=Alpinion Medical Systems + +OUI:D4E08E* + ID_OUI_FROM_DATABASE=ValueHD Corporation + +OUI:D4E32C* + ID_OUI_FROM_DATABASE=S. Siedle & Sohne + +OUI:D4E33F* + ID_OUI_FROM_DATABASE=Nokia + +OUI:D4E6B7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D4E880* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D4E8B2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D4E90B* + ID_OUI_FROM_DATABASE=CVT CO.,LTD + +OUI:D4EA0E* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:D4EC0C* + ID_OUI_FROM_DATABASE=Harley-Davidson Motor Company + +OUI:D4EC86* + ID_OUI_FROM_DATABASE=LinkedHope Intelligent Technologies Co., Ltd + +OUI:D4EE07* + ID_OUI_FROM_DATABASE=HIWIFI Co., Ltd. + +OUI:D4F027* + ID_OUI_FROM_DATABASE=Trust Power Ltd. + +OUI:D4F057* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:D4F0B4* + ID_OUI_FROM_DATABASE=Napco Security Technologies + +OUI:D4F143* + ID_OUI_FROM_DATABASE=IPROAD.,Inc + +OUI:D4F207* + ID_OUI_FROM_DATABASE=DIAODIAO(Beijing)Technology CO.,Ltd + +OUI:D4F46F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D4F4BE* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:D4F513* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D4F527* + ID_OUI_FROM_DATABASE=SIEMENS AG + +OUI:D4F547* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:D4F5EF* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:D4F63F* + ID_OUI_FROM_DATABASE=IEA S.R.L. + +OUI:D4F786* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:D4F9A1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D4FC13* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:D8004D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D8052E* + ID_OUI_FROM_DATABASE=Skyviia Corporation + +OUI:D806D1* + ID_OUI_FROM_DATABASE=Honeywell Fire System (Shanghai) Co,. Ltd. + +OUI:D807B6* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:D80831* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D808F5* + ID_OUI_FROM_DATABASE=Arcadia Networks Co. Ltd. + +OUI:D809C3* + ID_OUI_FROM_DATABASE=Cercacor Labs + +OUI:D80B9A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D80BCB* + ID_OUI_FROM_DATABASE=Telink Semiconductor (Shanghai) Co., Ltd. + +OUI:D80CCF* + ID_OUI_FROM_DATABASE=C.G.V. S.A.S. + +OUI:D80D17* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:D80DE3* + ID_OUI_FROM_DATABASE=FXI TECHNOLOGIES AS + +OUI:D80F99* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:D81265* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:D81399* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:D814D6* + ID_OUI_FROM_DATABASE=SURE SYSTEM Co Ltd + +OUI:D8150D* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:D8160A* + ID_OUI_FROM_DATABASE=Nippon Electro-Sensory Devices + +OUI:D816C1* + ID_OUI_FROM_DATABASE=DEWAV (HK) ELECTRONICS LIMITED + +OUI:D8182B* + ID_OUI_FROM_DATABASE=Conti Temic Microelectronic GmbH + +OUI:D818D3* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:D8197A* + ID_OUI_FROM_DATABASE=Nuheara Ltd + +OUI:D819CE* + ID_OUI_FROM_DATABASE=Telesquare + +OUI:D81BFE* + ID_OUI_FROM_DATABASE=TWINLINX CORPORATION + +OUI:D81C14* + ID_OUI_FROM_DATABASE=Compacta International, Ltd. + +OUI:D81C79* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D81D72* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D81EDD* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:D81EDE* + ID_OUI_FROM_DATABASE=B&W Group Ltd + +OUI:D81FCC* + ID_OUI_FROM_DATABASE=Brocade Communications Systems, Inc. + +OUI:D8209F* + ID_OUI_FROM_DATABASE=Cubro Acronet GesmbH + +OUI:D822F4* + ID_OUI_FROM_DATABASE=Avnet Silica + +OUI:D82477* + ID_OUI_FROM_DATABASE=Universal Electric Corporation + +OUI:D824BD* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D82522* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:D825B0* + ID_OUI_FROM_DATABASE=Rockeetech Systems Co.,Ltd. + +OUI:D826B9* + ID_OUI_FROM_DATABASE=Guangdong Coagent Electronics S&T Co.,Ltd. + +OUI:D8270C* + ID_OUI_FROM_DATABASE=MaxTronic International Co., Ltd. + +OUI:D828C9* + ID_OUI_FROM_DATABASE=General Electric Consumer and Industrial + +OUI:D82916* + ID_OUI_FROM_DATABASE=Ascent Communication Technology + +OUI:D82918* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D82986* + ID_OUI_FROM_DATABASE=Best Wish Technology LTD + +OUI:D82A15* + ID_OUI_FROM_DATABASE=Leitner SpA + +OUI:D82A7E* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:D82D9B* + ID_OUI_FROM_DATABASE=Shenzhen G.Credit Communication Technology Co., Ltd + +OUI:D82DE1* + ID_OUI_FROM_DATABASE=Tricascade Inc. + +OUI:D82FE6* + ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd. + +OUI:D83062* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D83134* + ID_OUI_FROM_DATABASE=Roku, Inc + +OUI:D831CF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D83214* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:D8325A* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:D832E3* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:D8337F* + ID_OUI_FROM_DATABASE=Office FA.com Co.,Ltd. + +OUI:D837BE* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:D8380D* + ID_OUI_FROM_DATABASE=SHENZHEN IP-COM Network Co.,Ltd + +OUI:D838FC* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:D83AF5* + ID_OUI_FROM_DATABASE=Wideband Labs LLC + +OUI:D83BBF* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D83C69* + ID_OUI_FROM_DATABASE=Shenzhen TINNO Mobile Technology Corp. + +OUI:D842AC* + ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd. + +OUI:D842E2* + ID_OUI_FROM_DATABASE=Canary Connect, Inc. + +OUI:D843ED* + ID_OUI_FROM_DATABASE=Suzuken + +OUI:D8445C* + ID_OUI_FROM_DATABASE=DEV Tecnologia Ind Com Man Eq LTDA + +OUI:D8452B* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:D84606* + ID_OUI_FROM_DATABASE=Silicon Valley Global Marketing + +OUI:D84710* + ID_OUI_FROM_DATABASE=Sichuan Changhong Electric Ltd. + +OUI:D84732* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:D848EE* + ID_OUI_FROM_DATABASE=Hangzhou Xueji Technology Co., Ltd. + +OUI:D8490B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D8492F* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:D84A87* + ID_OUI_FROM_DATABASE=OI ELECTRIC CO.,LTD + +OUI:D84B2A* + ID_OUI_FROM_DATABASE=Cognitas Technologies, Inc. + +OUI:D84C90* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D84DB9* + ID_OUI_FROM_DATABASE=Wu Qi Technologies,Inc. + +OUI:D84FB8* + ID_OUI_FROM_DATABASE=LG ELECTRONICS + +OUI:D850E6* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:D8543A* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D854A2* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:D85575* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D855A3* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D857EF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D858D7* + ID_OUI_FROM_DATABASE=CZ.NIC, z.s.p.o. + +OUI:D85B2A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D85D4C* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:D85D84* + ID_OUI_FROM_DATABASE=CAx soft GmbH + +OUI:D85DE2* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:D85DEF* + ID_OUI_FROM_DATABASE=Busch-Jaeger Elektro GmbH + +OUI:D85DFB* + ID_OUI_FROM_DATABASE=Private + +OUI:D85F77* + ID_OUI_FROM_DATABASE=Telink Semiconductor (Shanghai) Co., Ltd. + +OUI:D860B0* + ID_OUI_FROM_DATABASE=bioMérieux Italia S.p.A. + +OUI:D860B3* + ID_OUI_FROM_DATABASE=Guangdong Global Electronic Technology CO.,LTD + +OUI:D86162* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:D86194* + ID_OUI_FROM_DATABASE=Objetivos y Sevicios de Valor Añadido + +OUI:D862DB* + ID_OUI_FROM_DATABASE=Eno Inc. + +OUI:D86375* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:D86595* + ID_OUI_FROM_DATABASE=Toy's Myth Inc. + +OUI:D866C6* + ID_OUI_FROM_DATABASE=Shenzhen Daystar Technology Co.,ltd + +OUI:D866EE* + ID_OUI_FROM_DATABASE=BOXIN COMMUNICATION CO.,LTD. + +OUI:D867D9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D868C3* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D86960* + ID_OUI_FROM_DATABASE=Steinsvik + +OUI:D86BF7* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:D86C02* + ID_OUI_FROM_DATABASE=Huaqin Telecom Technology Co.,Ltd + +OUI:D86C63* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:D86CE9* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:D87157* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:D87495* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D87533* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:D8760A* + ID_OUI_FROM_DATABASE=Escort, Inc. + +OUI:D878E5* + ID_OUI_FROM_DATABASE=KUHN SA + +OUI:D87988* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:D87CDD* + ID_OUI_FROM_DATABASE=SANIX INCORPORATED + +OUI:D87D7F* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:D87E76* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:D87EB1* + ID_OUI_FROM_DATABASE=x.o.ware, inc. + +OUI:D88039* + ID_OUI_FROM_DATABASE=Microchip Technology Inc. + +OUI:D8803C* + ID_OUI_FROM_DATABASE=Anhui Huami Information Technology Company Limited + +OUI:D881CE* + ID_OUI_FROM_DATABASE=AHN INC. + +OUI:D88466* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:D8860B0* + ID_OUI_FROM_DATABASE=Inspur Group Co., Ltd. + +OUI:D8860B1* + ID_OUI_FROM_DATABASE=Krspace + +OUI:D8860B2* + ID_OUI_FROM_DATABASE=Get SAT + +OUI:D8860B3* + ID_OUI_FROM_DATABASE=Auvidea GmbH + +OUI:D8860B4* + ID_OUI_FROM_DATABASE=Teplovodokhran Ltd. + +OUI:D8860B5* + ID_OUI_FROM_DATABASE=CAMTRACE + +OUI:D8860B6* + ID_OUI_FROM_DATABASE=SCANMATIK + +OUI:D8860B7* + ID_OUI_FROM_DATABASE=Grünbeck Wasseraufbereitung GmbH + +OUI:D8860B8* + ID_OUI_FROM_DATABASE=VRINDA NANO TECHNOLOGIES PVT LTD + +OUI:D8860B9* + ID_OUI_FROM_DATABASE=DIGITAL CONCEPTS + +OUI:D8860BA* + ID_OUI_FROM_DATABASE=GLO Science + +OUI:D8860BB* + ID_OUI_FROM_DATABASE=Library Ideas + +OUI:D8860BC* + ID_OUI_FROM_DATABASE=YUSAN INDUSTRIES LIMITED + +OUI:D8860BD* + ID_OUI_FROM_DATABASE=ComNav Technology Ltd. + +OUI:D8860BE* + ID_OUI_FROM_DATABASE=Shenzhen Yidong Technology Co.,Ltd + +OUI:D887D5* + ID_OUI_FROM_DATABASE=Leadcore Technology CO.,LTD + +OUI:D888CE* + ID_OUI_FROM_DATABASE=RF Technology Pty Ltd + +OUI:D88A3B* + ID_OUI_FROM_DATABASE=UNIT-EM + +OUI:D88ADC* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:D88B4C* + ID_OUI_FROM_DATABASE=KingTing Tech. + +OUI:D88D5C* + ID_OUI_FROM_DATABASE=Elentec + +OUI:D88DC8* + ID_OUI_FROM_DATABASE=Atil Technology Co., LTD + +OUI:D88F76* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D890E8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D8912A* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:D89341* + ID_OUI_FROM_DATABASE=General Electric Global Research + +OUI:D89403* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:D8952F* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D89685* + ID_OUI_FROM_DATABASE=GoPro + +OUI:D89695* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D896E0* + ID_OUI_FROM_DATABASE=Alibaba Cloud Computing Ltd. + +OUI:D8973B* + ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies + +OUI:D89760* + ID_OUI_FROM_DATABASE=C2 Development, Inc. + +OUI:D8977C* + ID_OUI_FROM_DATABASE=Grey Innovation + +OUI:D89790* + ID_OUI_FROM_DATABASE=Commonwealth Scientific and Industrial Research Organisation + +OUI:D897BA* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:D89A34* + ID_OUI_FROM_DATABASE=Beijing SHENQI Technology Co., Ltd. + +OUI:D89B3B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D89C67* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:D89D67* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:D89DB9* + ID_OUI_FROM_DATABASE=eMegatech International Corp. + +OUI:D89E3F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D89E61* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:D89EF3* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:D8A01D* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:D8A105* + ID_OUI_FROM_DATABASE=Syslane, Co., Ltd. + +OUI:D8A25E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D8A315* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:D8A534* + ID_OUI_FROM_DATABASE=Spectronix Corporation + +OUI:D8A6FD* + ID_OUI_FROM_DATABASE=Ghost Locomotion + +OUI:D8A756* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:D8A8C8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:D8A98B* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D8ADDD* + ID_OUI_FROM_DATABASE=Sonavation, Inc. + +OUI:D8AE90* + ID_OUI_FROM_DATABASE=Itibia Technologies + +OUI:D8AED0* + ID_OUI_FROM_DATABASE=Shanghai Engineering Science & Technology Co.,LTD CGNPC + +OUI:D8AF3B* + ID_OUI_FROM_DATABASE=Hangzhou Bigbright Integrated communications system Co.,Ltd + +OUI:D8AF81* + ID_OUI_FROM_DATABASE=ZAO NPK Rotek + +OUI:D8AFF1* + ID_OUI_FROM_DATABASE=Panasonic Appliances Company + +OUI:D8B02E* + ID_OUI_FROM_DATABASE=Guangzhou Zonerich Business Machine Co., LTD. + +OUI:D8B04C* + ID_OUI_FROM_DATABASE=Jinan USR IOT Technology Co., Ltd. + +OUI:D8B122* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:D8B12A* + ID_OUI_FROM_DATABASE=Panasonic Mobile Communications Co.,Ltd. + +OUI:D8B190* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:D8B377* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:D8B6B7* + ID_OUI_FROM_DATABASE=Comtrend Corporation + +OUI:D8B6C1* + ID_OUI_FROM_DATABASE=NetworkAccountant, Inc. + +OUI:D8B6D6* + ID_OUI_FROM_DATABASE=Blu Tether Limited + +OUI:D8B8F6* + ID_OUI_FROM_DATABASE=Nantworks + +OUI:D8B90E* + ID_OUI_FROM_DATABASE=Triple Domain Vision Co.,Ltd. + +OUI:D8BB2C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D8BC59* + ID_OUI_FROM_DATABASE=Shenzhen DAPU Microelectronics Co., Ltd + +OUI:D8BF4C* + ID_OUI_FROM_DATABASE=Victory Concept Electronics Limited + +OUI:D8BFC0* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:D8C068* + ID_OUI_FROM_DATABASE=Netgenetech.co.,ltd. + +OUI:D8C06A* + ID_OUI_FROM_DATABASE=Hunantv.com Interactive Entertainment Media Co.,Ltd. + +OUI:D8C3FB* + ID_OUI_FROM_DATABASE=DETRACOM + +OUI:D8C46A* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:D8C497* + ID_OUI_FROM_DATABASE=Quanta Computer Inc. + +OUI:D8C4E9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D8C561* + ID_OUI_FROM_DATABASE=CommFront Communications Pte Ltd + +OUI:D8C691* + ID_OUI_FROM_DATABASE=Hichan Technology Corp. + +OUI:D8C771* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:D8C7C8* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:D8C8E9* + ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd. + +OUI:D8C99D* + ID_OUI_FROM_DATABASE=EA DISPLAY LIMITED + +OUI:D8CA06* + ID_OUI_FROM_DATABASE=Titan DataCenters France + +OUI:D8CB8A* + ID_OUI_FROM_DATABASE=Micro-Star INTL CO., LTD. + +OUI:D8CE3A* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:D8CF89* + ID_OUI_FROM_DATABASE=Beijing DoSee Science and Technology Co., Ltd. + +OUI:D8CF9C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D8D090* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:D8D1CB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:D8D27C* + ID_OUI_FROM_DATABASE=JEMA ENERGY, SA + +OUI:D8D385* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:D8D43C* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:D8D4E6* + ID_OUI_FROM_DATABASE=Hytec Inter Co., Ltd. + +OUI:D8D5B9* + ID_OUI_FROM_DATABASE=Rainforest Automation, Inc. + +OUI:D8D67E* + ID_OUI_FROM_DATABASE=GSK CNC EQUIPMENT CO.,LTD + +OUI:D8D6F3* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:D8D723* + ID_OUI_FROM_DATABASE=IDS, Inc + +OUI:D8D775* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:D8D866* + ID_OUI_FROM_DATABASE=SHENZHEN TOZED TECHNOLOGIES CO.,LTD. + +OUI:D8DA52* + ID_OUI_FROM_DATABASE=APATOR S.A. + +OUI:D8DCE9* + ID_OUI_FROM_DATABASE=Kunshan Erlab ductless filtration system Co.,Ltd + +OUI:D8DD5F* + ID_OUI_FROM_DATABASE=BALMUDA Inc. + +OUI:D8DDFD* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:D8DECE* + ID_OUI_FROM_DATABASE=ISUNG CO.,LTD + +OUI:D8DF0D* + ID_OUI_FROM_DATABASE=beroNet GmbH + +OUI:D8DF7A* + ID_OUI_FROM_DATABASE=Quest Software, Inc. + +OUI:D8E004* + ID_OUI_FROM_DATABASE=Vodia Networks Inc + +OUI:D8E0B8* + ID_OUI_FROM_DATABASE=BULAT LLC + +OUI:D8E0E1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:D8E3AE* + ID_OUI_FROM_DATABASE=CIRTEC MEDICAL SYSTEMS + +OUI:D8E56D* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:D8E72B* + ID_OUI_FROM_DATABASE=NetAlly + +OUI:D8E743* + ID_OUI_FROM_DATABASE=Wush, Inc + +OUI:D8E952* + ID_OUI_FROM_DATABASE=KEOPSYS + +OUI:D8EB97* + ID_OUI_FROM_DATABASE=TRENDnet, Inc. + +OUI:D8ED1C* + ID_OUI_FROM_DATABASE=Magna Technology SL + +OUI:D8EE78* + ID_OUI_FROM_DATABASE=Moog Protokraft + +OUI:D8EFCD* + ID_OUI_FROM_DATABASE=Nokia + +OUI:D8F0F2* + ID_OUI_FROM_DATABASE=Zeebo Inc + +OUI:D8F15B* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:D8F1F0* + ID_OUI_FROM_DATABASE=Pepxim International Limited + +OUI:D8F2CA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D8F3DB* + ID_OUI_FROM_DATABASE=Post CH AG + +OUI:D8F710* + ID_OUI_FROM_DATABASE=Libre Wireless Technologies Inc. + +OUI:D8FB11* + ID_OUI_FROM_DATABASE=AXACORE + +OUI:D8FB5E* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:D8FB68* + ID_OUI_FROM_DATABASE=Cloud Corner Ltd. + +OUI:D8FC38* + ID_OUI_FROM_DATABASE=Giantec Semiconductor Inc + +OUI:D8FC93* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:D8FE8F* + ID_OUI_FROM_DATABASE=IDFone Co., Ltd. + +OUI:D8FEE3* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:DC0077* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:DC0265* + ID_OUI_FROM_DATABASE=Meditech Kft + +OUI:DC028E* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:DC052F* + ID_OUI_FROM_DATABASE=National Products Inc. + +OUI:DC0575* + ID_OUI_FROM_DATABASE=SIEMENS ENERGY AUTOMATION + +OUI:DC05ED* + ID_OUI_FROM_DATABASE=Nabtesco Corporation + +OUI:DC07C1* + ID_OUI_FROM_DATABASE=HangZhou QiYang Technology Co.,Ltd. + +OUI:DC080F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC0856* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise + +OUI:DC0914* + ID_OUI_FROM_DATABASE=Talk-A-Phone Co. + +OUI:DC094C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DC0B1A* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:DC0B34* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:DC0C2D* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:DC0C5C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC0D30* + ID_OUI_FROM_DATABASE=Shenzhen Feasycom Technology Co., Ltd. + +OUI:DC0EA1* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:DC15DB* + ID_OUI_FROM_DATABASE=Ge Ruili Intelligent Technology ( Beijing ) Co., Ltd. + +OUI:DC16A2* + ID_OUI_FROM_DATABASE=Medtronic Diabetes + +OUI:DC16B2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DC175A* + ID_OUI_FROM_DATABASE=Hitachi High-Technologies Corporation + +OUI:DC1792* + ID_OUI_FROM_DATABASE=Captivate Network + +OUI:DC1A01* + ID_OUI_FROM_DATABASE=Ecoliv Technology ( Shenzhen ) Ltd. + +OUI:DC1AC5* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:DC1D9F* + ID_OUI_FROM_DATABASE=U & B tech + +OUI:DC1DD4* + ID_OUI_FROM_DATABASE=Microstep-MIS spol. s r.o. + +OUI:DC1EA3* + ID_OUI_FROM_DATABASE=Accensus LLC + +OUI:DC2008* + ID_OUI_FROM_DATABASE=ASD Electronics Ltd + +OUI:DC21B9* + ID_OUI_FROM_DATABASE=Sentec Co.Ltd + +OUI:DC21E2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DC2834* + ID_OUI_FROM_DATABASE=HAKKO Corporation + +OUI:DC2919* + ID_OUI_FROM_DATABASE=AltoBeam (Xiamen) Technology Ltd, Co. + +OUI:DC293A* + ID_OUI_FROM_DATABASE=Shenzhen Nuoshi Technology Co., LTD. + +OUI:DC2A14* + ID_OUI_FROM_DATABASE=Shanghai Longjing Technology Co. + +OUI:DC2AA1* + ID_OUI_FROM_DATABASE=MedHab LLC + +OUI:DC2B2A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC2B61* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC2B66* + ID_OUI_FROM_DATABASE=InfoBLOCK S.A. de C.V. + +OUI:DC2BCA* + ID_OUI_FROM_DATABASE=Zera GmbH + +OUI:DC2C26* + ID_OUI_FROM_DATABASE=Iton Technology Limited + +OUI:DC2DCB* + ID_OUI_FROM_DATABASE=Beijing Unis HengYue Technology Co., Ltd. + +OUI:DC2E6A* + ID_OUI_FROM_DATABASE=HCT. Co., Ltd. + +OUI:DC2F03* + ID_OUI_FROM_DATABASE=Step forward Group Co., Ltd. + +OUI:DC309C* + ID_OUI_FROM_DATABASE=Heyrex Limited + +OUI:DC31D1* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:DC330D* + ID_OUI_FROM_DATABASE=QING DAO HAIER TELECOM CO.,LTD. + +OUI:DC333D* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:DC3350* + ID_OUI_FROM_DATABASE=TechSAT GmbH + +OUI:DC35F1* + ID_OUI_FROM_DATABASE=Positivo Tecnologia S.A. + +OUI:DC3714* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC3752* + ID_OUI_FROM_DATABASE=GE + +OUI:DC3757* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:DC37D2* + ID_OUI_FROM_DATABASE=Hunan HKT Electronic Technology Co., Ltd + +OUI:DC38E1* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:DC396F* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:DC3979* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:DC3A5E* + ID_OUI_FROM_DATABASE=Roku, Inc. + +OUI:DC3C2E* + ID_OUI_FROM_DATABASE=Manufacturing System Insights, Inc. + +OUI:DC3C84* + ID_OUI_FROM_DATABASE=Ticom Geomatics, Inc. + +OUI:DC3CF6* + ID_OUI_FROM_DATABASE=Atomic Rules LLC + +OUI:DC3E51* + ID_OUI_FROM_DATABASE=Solberg & Andersen AS + +OUI:DC3EF8* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:DC415F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC41E5* + ID_OUI_FROM_DATABASE=Shenzhen Zhixin Data Service Co., Ltd. + +OUI:DC44270* + ID_OUI_FROM_DATABASE=Suritel + +OUI:DC44271* + ID_OUI_FROM_DATABASE=Tesla,Inc. + +OUI:DC44272* + ID_OUI_FROM_DATABASE=Skywave Technology Co,.Ltd. + +OUI:DC44273* + ID_OUI_FROM_DATABASE=General Microsystems Sdn Bhd + +OUI:DC44274* + ID_OUI_FROM_DATABASE=Nex Technologies PTY LTD + +OUI:DC44275* + ID_OUI_FROM_DATABASE=Century Audio, Inc. + +OUI:DC44276* + ID_OUI_FROM_DATABASE=EK-TEAM Elektronik- u. Kunststoff-Technik GmbH + +OUI:DC44277* + ID_OUI_FROM_DATABASE=EcoGuard AB + +OUI:DC44278* + ID_OUI_FROM_DATABASE=Wharton Electronics Ltd + +OUI:DC44279* + ID_OUI_FROM_DATABASE=Neusoft Corporation + +OUI:DC4427A* + ID_OUI_FROM_DATABASE=Shanghai Huahong Integrated Circuit Co.,Ltd + +OUI:DC4427B* + ID_OUI_FROM_DATABASE=Nautilus Infotech CO., Ltd. + +OUI:DC4427C* + ID_OUI_FROM_DATABASE=Pyrexx Technologies GmbH + +OUI:DC4427D* + ID_OUI_FROM_DATABASE=Rohde&Schwarz Topex SA + +OUI:DC4427E* + ID_OUI_FROM_DATABASE=VerifEye Technologies + +OUI:DC4427F* + ID_OUI_FROM_DATABASE=Private + +OUI:DC446D* + ID_OUI_FROM_DATABASE=Allwinner Technology Co., Ltd + +OUI:DC44B6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:DC4517* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:DC48B2* + ID_OUI_FROM_DATABASE=Baraja Pty. Ltd. + +OUI:DC49C9* + ID_OUI_FROM_DATABASE=CASCO SIGNAL LTD + +OUI:DC4A3E* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:DC4BDD* + ID_OUI_FROM_DATABASE=Shenzhen SuperElectron Technology Co.,Ltd. + +OUI:DC4BFE* + ID_OUI_FROM_DATABASE=Shenzhen Belon Technology CO.,LTD + +OUI:DC4D23* + ID_OUI_FROM_DATABASE=MRV Comunications + +OUI:DC4EDE* + ID_OUI_FROM_DATABASE=SHINYEI TECHNOLOGY CO., LTD. + +OUI:DC4EF4* + ID_OUI_FROM_DATABASE=Shenzhen MTN Electronics CO., Ltd + +OUI:DC4F22* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:DC5360* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:DC537C* + ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc. + +OUI:DC543D* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:DC54D7* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:DC5583* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:DC56E6* + ID_OUI_FROM_DATABASE=Shenzhen Bococom Technology Co.,LTD + +OUI:DC56E7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC5726* + ID_OUI_FROM_DATABASE=Power-One + +OUI:DC58BC* + ID_OUI_FROM_DATABASE=Thomas-Krenn.AG + +OUI:DC5E36* + ID_OUI_FROM_DATABASE=Paterson Technology + +OUI:DC60A1* + ID_OUI_FROM_DATABASE=Teledyne DALSA Professional Imaging + +OUI:DC647C* + ID_OUI_FROM_DATABASE=C.R.S. iiMotion GmbH + +OUI:DC64B8* + ID_OUI_FROM_DATABASE=Shenzhen JingHanDa Electronics Co.Ltd + +OUI:DC663A* + ID_OUI_FROM_DATABASE=Apacer Technology Inc. + +OUI:DC6672* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:DC6723* + ID_OUI_FROM_DATABASE=barox Kommunikation GmbH + +OUI:DC680C* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:DC68EB* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:DC6AEA* + ID_OUI_FROM_DATABASE=Infinix mobility limited + +OUI:DC6DCD* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:DC6F00* + ID_OUI_FROM_DATABASE=Livescribe, Inc. + +OUI:DC6F08* + ID_OUI_FROM_DATABASE=Bay Storage Technology + +OUI:DC7014* + ID_OUI_FROM_DATABASE=Private + +OUI:DC7137* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:DC7144* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:DC7196* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:DC729B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DC74A8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:DC7834* + ID_OUI_FROM_DATABASE=LOGICOM SA + +OUI:DC7B94* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:DC7FA4* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:DC825B* + ID_OUI_FROM_DATABASE=JANUS, spol. s r.o. + +OUI:DC82F6* + ID_OUI_FROM_DATABASE=iPort + +OUI:DC85DE* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:DC86D8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC8983* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:DC8B28* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:DC8C37* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:DC9088* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DC962C* + ID_OUI_FROM_DATABASE=NST Audio Ltd + +OUI:DC9840* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:DC9914* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DC9A8E* + ID_OUI_FROM_DATABASE=Nanjing Cocomm electronics co., LTD + +OUI:DC9B1E* + ID_OUI_FROM_DATABASE=Intercom, Inc. + +OUI:DC9B9C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DC9C52* + ID_OUI_FROM_DATABASE=Sapphire Technology Limited. + +OUI:DC9C9F* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:DC9FA4* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:DC9FDB* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:DCA266* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:DCA333* + ID_OUI_FROM_DATABASE=Shenzhen YOUHUA Technology Co., Ltd + +OUI:DCA3AC* + ID_OUI_FROM_DATABASE=RBcloudtech + +OUI:DCA4CA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DCA5F4* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:DCA632* + ID_OUI_FROM_DATABASE=Raspberry Pi Trading Ltd + +OUI:DCA6BD* + ID_OUI_FROM_DATABASE=Beijing Lanbo Technology Co., Ltd. + +OUI:DCA7D9* + ID_OUI_FROM_DATABASE=Compressor Controls Corp + +OUI:DCA8CF* + ID_OUI_FROM_DATABASE=New Spin Golf, LLC. + +OUI:DCA904* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DCA971* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:DCA989* + ID_OUI_FROM_DATABASE=MACANDC + +OUI:DCAD9E* + ID_OUI_FROM_DATABASE=GreenPriz + +OUI:DCAE04* + ID_OUI_FROM_DATABASE=CELOXICA Ltd + +OUI:DCAF68* + ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD + +OUI:DCB058* + ID_OUI_FROM_DATABASE=Bürkert Werke GmbH + +OUI:DCB082* + ID_OUI_FROM_DATABASE=Nokia + +OUI:DCB3B4* + ID_OUI_FROM_DATABASE=Honeywell Environmental & Combustion Controls (Tianjin) Co., Ltd. + +OUI:DCB4AC* + ID_OUI_FROM_DATABASE=FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + +OUI:DCB4C4* + ID_OUI_FROM_DATABASE=Microsoft XCG + +OUI:DCB808* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:DCBE7A* + ID_OUI_FROM_DATABASE=Zhejiang Nurotron Biotechnology Co. + +OUI:DCBF90* + ID_OUI_FROM_DATABASE=HUIZHOU QIAOXING TELECOMMUNICATION INDUSTRY CO.,LTD. + +OUI:DCBFE9* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:DCC0DB* + ID_OUI_FROM_DATABASE=Shenzhen Kaiboer Technology Co., Ltd. + +OUI:DCC0EB* + ID_OUI_FROM_DATABASE=ASSA ABLOY CÔTE PICARDE + +OUI:DCC101* + ID_OUI_FROM_DATABASE=SOLiD Technologies, Inc. + +OUI:DCC422* + ID_OUI_FROM_DATABASE=Systembase Limited + +OUI:DCC622* + ID_OUI_FROM_DATABASE=BUHEUNG SYSTEM + +OUI:DCC64B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DCC793* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:DCC8F5* + ID_OUI_FROM_DATABASE=Shanghai UMEinfo CO.,LTD. + +OUI:DCCBA8* + ID_OUI_FROM_DATABASE=Explora Technologies Inc + +OUI:DCCC8D* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:DCCE41* + ID_OUI_FROM_DATABASE=FE GLOBAL HONG KONG LIMITED + +OUI:DCCEBC* + ID_OUI_FROM_DATABASE=Shenzhen JSR Technology Co.,Ltd. + +OUI:DCCEC1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:DCCF94* + ID_OUI_FROM_DATABASE=Beijing Rongcheng Hutong Technology Co., Ltd. + +OUI:DCCF96* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:DCD0F7* + ID_OUI_FROM_DATABASE=Bentek Systems Ltd. + +OUI:DCD255* + ID_OUI_FROM_DATABASE=Kinpo Electronics, Inc. + +OUI:DCD2FC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DCD321* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:DCD3A2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:DCD52A* + ID_OUI_FROM_DATABASE=Sunny Heart Limited + +OUI:DCD87C* + ID_OUI_FROM_DATABASE=Beijing Jingdong Century Trading Co., LTD. + +OUI:DCD87F* + ID_OUI_FROM_DATABASE=Shenzhen JoinCyber Telecom Equipment Ltd + +OUI:DCD916* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DCDA4F* + ID_OUI_FROM_DATABASE=GETCK TECHNOLOGY, INC + +OUI:DCDA80* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:DCDB70* + ID_OUI_FROM_DATABASE=Tonfunk Systementwicklung und Service GmbH + +OUI:DCDC07* + ID_OUI_FROM_DATABASE=TRP Systems BV + +OUI:DCDCE2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:DCDD24* + ID_OUI_FROM_DATABASE=Energica Motor Company SpA + +OUI:DCDE4F* + ID_OUI_FROM_DATABASE=Gionee Communication Equipment Co Ltd + +OUI:DCDECA* + ID_OUI_FROM_DATABASE=Akyllor + +OUI:DCDFD6* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:DCE026* + ID_OUI_FROM_DATABASE=Patrol Tag, Inc + +OUI:DCE0EB* + ID_OUI_FROM_DATABASE=Nanjing Aozheng Information Technology Co.Ltd + +OUI:DCE1AD* + ID_OUI_FROM_DATABASE=Shenzhen Wintop Photoelectric Technology Co., Ltd + +OUI:DCE2AC* + ID_OUI_FROM_DATABASE=Lumens Digital Optics Inc. + +OUI:DCE305* + ID_OUI_FROM_DATABASE=ZAO NPK Rotek + +OUI:DCE5330* + ID_OUI_FROM_DATABASE=FLYHT Aerospace + +OUI:DCE5331* + ID_OUI_FROM_DATABASE=Ambi Labs Limited + +OUI:DCE5332* + ID_OUI_FROM_DATABASE=Remko GmbH & Co. KG + +OUI:DCE5333* + ID_OUI_FROM_DATABASE=ShenZhen C&D Electronics CO.Ltd. + +OUI:DCE5334* + ID_OUI_FROM_DATABASE=shenzhen bangying electronics co,.ltd + +OUI:DCE5335* + ID_OUI_FROM_DATABASE=Controls Inc + +OUI:DCE5336* + ID_OUI_FROM_DATABASE=WECAN Solution Inc. + +OUI:DCE5337* + ID_OUI_FROM_DATABASE=SAN Engineering + +OUI:DCE5338* + ID_OUI_FROM_DATABASE=JB-Lighting Lichtanlagen GmbH + +OUI:DCE5339* + ID_OUI_FROM_DATABASE=Tiertime Corporation + +OUI:DCE533A* + ID_OUI_FROM_DATABASE=Private + +OUI:DCE533B* + ID_OUI_FROM_DATABASE=Tintel Hongkong Co.Ltd + +OUI:DCE533C* + ID_OUI_FROM_DATABASE=BRCK + +OUI:DCE533D* + ID_OUI_FROM_DATABASE=Suzhou ATES electronic technology co.LTD + +OUI:DCE533E* + ID_OUI_FROM_DATABASE=Giant Power Technology Biomedical Corporation + +OUI:DCE578* + ID_OUI_FROM_DATABASE=Experimental Factory of Scientific Engineering and Special Design Department + +OUI:DCE71C* + ID_OUI_FROM_DATABASE=AUG Elektronik GmbH + +OUI:DCE838* + ID_OUI_FROM_DATABASE=CK Telecom (Shenzhen) Limited + +OUI:DCEB53* + ID_OUI_FROM_DATABASE=Wuhan QianXiao Elecronic Technology CO.,LTD + +OUI:DCEB69* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:DCEB94* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:DCEC06* + ID_OUI_FROM_DATABASE=Heimi Network Technology Co., Ltd. + +OUI:DCED84* + ID_OUI_FROM_DATABASE=Haverford Systems Inc + +OUI:DCEE06* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:DCEF09* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:DCEFCA* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:DCF05D* + ID_OUI_FROM_DATABASE=Letta Teknoloji + +OUI:DCF090* + ID_OUI_FROM_DATABASE=Nubia Technology Co.,Ltd. + +OUI:DCF110* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:DCF401* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:DCF505* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:DCF719* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:DCF755* + ID_OUI_FROM_DATABASE=SITRONIK + +OUI:DCF756* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:DCF858* + ID_OUI_FROM_DATABASE=Lorent Networks, Inc. + +OUI:DCF8B9* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:DCFAD5* + ID_OUI_FROM_DATABASE=STRONG Ges.m.b.H. + +OUI:DCFB02* + ID_OUI_FROM_DATABASE=BUFFALO.INC + +OUI:DCFB48* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:DCFE07* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:DCFE18* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:E00084* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E002A5* + ID_OUI_FROM_DATABASE=ABB Robotics + +OUI:E00370* + ID_OUI_FROM_DATABASE=ShenZhen Continental Wireless Technology Co., Ltd. + +OUI:E005C5* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:E006E6* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:E0071B* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:E009BF* + ID_OUI_FROM_DATABASE=SHENZHEN TONG BO WEI TECHNOLOGY Co.,LTD + +OUI:E00B28* + ID_OUI_FROM_DATABASE=Inovonics + +OUI:E00C7F* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:E00DB9* + ID_OUI_FROM_DATABASE=Cree, Inc. + +OUI:E00EDA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E00EE1* + ID_OUI_FROM_DATABASE=We Corporation Inc. + +OUI:E0107F* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:E01283* + ID_OUI_FROM_DATABASE=Shenzhen Fanzhuo Communication Technology Co., Lt + +OUI:E013B5* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:E0143E* + ID_OUI_FROM_DATABASE=Modoosis Inc. + +OUI:E01877* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:E0189F* + ID_OUI_FROM_DATABASE=EM Microelectronic + +OUI:E0191D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E01954* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E019D8* + ID_OUI_FROM_DATABASE=BH TECHNOLOGIES + +OUI:E01AEA* + ID_OUI_FROM_DATABASE=Allied Telesis, Inc. + +OUI:E01C41* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:E01CEE* + ID_OUI_FROM_DATABASE=Bravo Tech, Inc. + +OUI:E01D38* + ID_OUI_FROM_DATABASE=Beijing HuaqinWorld Technology Co.,Ltd + +OUI:E01D3B* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:E01E07* + ID_OUI_FROM_DATABASE=Anite Telecoms US. Inc + +OUI:E01F0A* + ID_OUI_FROM_DATABASE=Xslent Energy Technologies. LLC + +OUI:E01F88* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:E02202* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E023FF* + ID_OUI_FROM_DATABASE=Fortinet, Inc. + +OUI:E0247F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E02481* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E02538* + ID_OUI_FROM_DATABASE=Titan Pet Products + +OUI:E02630* + ID_OUI_FROM_DATABASE=Intrigue Technologies, Inc. + +OUI:E02636* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:E0271A* + ID_OUI_FROM_DATABASE=TTC Next-generation Home Network System WG + +OUI:E02861* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E0286D* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:E02A82* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:E02AE6* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:E02CB2* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication (Wuhan) Company Limited + +OUI:E02CF3* + ID_OUI_FROM_DATABASE=MRS Electronic GmbH + +OUI:E02F6D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E03005* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:E0319E* + ID_OUI_FROM_DATABASE=Valve Corporation + +OUI:E031D0* + ID_OUI_FROM_DATABASE=SZ Telstar CO., LTD + +OUI:E0338E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E034E4* + ID_OUI_FROM_DATABASE=Feit Electric Company, Inc. + +OUI:E03560* + ID_OUI_FROM_DATABASE=Challenger Supply Holdings, LLC + +OUI:E03676* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E036E3* + ID_OUI_FROM_DATABASE=Stage One International Co., Ltd. + +OUI:E03717* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:E037BF* + ID_OUI_FROM_DATABASE=Wistron Neweb Corporation + +OUI:E0383F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E039D7* + ID_OUI_FROM_DATABASE=Plexxi, Inc. + +OUI:E03C5B* + ID_OUI_FROM_DATABASE=SHENZHEN JIAXINJIE ELECTRON CO.,LTD + +OUI:E03E44* + ID_OUI_FROM_DATABASE=Broadcom + +OUI:E03E4A* + ID_OUI_FROM_DATABASE=Cavanagh Group International + +OUI:E03E7D* + ID_OUI_FROM_DATABASE=data-complex GmbH + +OUI:E03F49* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:E04007* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:E04136* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:E043DB* + ID_OUI_FROM_DATABASE=Shenzhen ViewAt Technology Co.,Ltd. + +OUI:E0456D* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:E0469A* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:E046E5* + ID_OUI_FROM_DATABASE=Gosuncn Technology Group Co., Ltd. + +OUI:E048AF* + ID_OUI_FROM_DATABASE=Premietech Limited + +OUI:E048D3* + ID_OUI_FROM_DATABASE=MOBIWIRE MOBILES (NINGBO) CO.,LTD + +OUI:E049ED* + ID_OUI_FROM_DATABASE=Audeze LLC + +OUI:E04B45* + ID_OUI_FROM_DATABASE=Hi-P Electronics Pte Ltd + +OUI:E04F43* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:E04FBD* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:E0508B* + ID_OUI_FROM_DATABASE=Zhejiang Dahua Technology Co., Ltd. + +OUI:E05124* + ID_OUI_FROM_DATABASE=NXP Semiconductors + +OUI:E05163* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:E0553D* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:E05597* + ID_OUI_FROM_DATABASE=Emergent Vision Technologies Inc. + +OUI:E056F4* + ID_OUI_FROM_DATABASE=AxesNetwork Solutions inc. + +OUI:E0589E* + ID_OUI_FROM_DATABASE=Laerdal Medical + +OUI:E05A9F0* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:E05A9F1* + ID_OUI_FROM_DATABASE=AITEC SYSTEM CO., LTD. + +OUI:E05A9F2* + ID_OUI_FROM_DATABASE=Chengdu Song Yuan Electronic Technology Co.,Ltd + +OUI:E05A9F3* + ID_OUI_FROM_DATABASE=Link of Things Co., Ltd. + +OUI:E05A9F4* + ID_OUI_FROM_DATABASE=Hale Products + +OUI:E05A9F5* + ID_OUI_FROM_DATABASE=TRYEN + +OUI:E05A9F6* + ID_OUI_FROM_DATABASE=Fibrain + +OUI:E05A9F7* + ID_OUI_FROM_DATABASE=OMB Guitars LLC + +OUI:E05A9F8* + ID_OUI_FROM_DATABASE=Fujian Newland Auto-ID Tech. Co.,Ltd. + +OUI:E05A9F9* + ID_OUI_FROM_DATABASE=Gemalto Document Readers + +OUI:E05A9FA* + ID_OUI_FROM_DATABASE=Contemporary Amperex Technology Co., Limited + +OUI:E05A9FB* + ID_OUI_FROM_DATABASE=Shenzhen Rongan Networks Technology Co.,Ltd + +OUI:E05A9FC* + ID_OUI_FROM_DATABASE=ShenZhen Mornsun Smartlinker Limited Co., LTD + +OUI:E05A9FD* + ID_OUI_FROM_DATABASE=Mountz, Inc. + +OUI:E05A9FE* + ID_OUI_FROM_DATABASE=ShenZhen Arts Changhua Intelligent Technology Co., Ltd + +OUI:E05B70* + ID_OUI_FROM_DATABASE=Innovid, Co., Ltd. + +OUI:E05D5C* + ID_OUI_FROM_DATABASE=Oy Everon Ab + +OUI:E05DA6* + ID_OUI_FROM_DATABASE=Detlef Fink Elektronik & Softwareentwicklung + +OUI:E05F45* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E05FB9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E06066* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:E06089* + ID_OUI_FROM_DATABASE=Cloudleaf, Inc. + +OUI:E061B2* + ID_OUI_FROM_DATABASE=HANGZHOU ZENOINTEL TECHNOLOGY CO., LTD + +OUI:E06267* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:E06290* + ID_OUI_FROM_DATABASE=Jinan Jovision Science & Technology Co., Ltd. + +OUI:E063DA* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:E063E5* + ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc + +OUI:E064BB* + ID_OUI_FROM_DATABASE=DigiView S.r.l. + +OUI:E06678* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E067B3* + ID_OUI_FROM_DATABASE=Shenzhen C-Data Technology Co., Ltd + +OUI:E0686D* + ID_OUI_FROM_DATABASE=Raybased AB + +OUI:E06995* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:E0735F* + ID_OUI_FROM_DATABASE=NUCOM + +OUI:E0750A* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:E0757D* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:E076D0* + ID_OUI_FROM_DATABASE=AMPAK Technology, Inc. + +OUI:E078A3* + ID_OUI_FROM_DATABASE=Shanghai Winner Information Technology Co.,Inc + +OUI:E0795E* + ID_OUI_FROM_DATABASE=Wuxi Xiaohu Technology Co.,Ltd. + +OUI:E07C13* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E07C62* + ID_OUI_FROM_DATABASE=Whistle Labs, Inc. + +OUI:E07DEA* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:E07F53* + ID_OUI_FROM_DATABASE=TECHBOARD SRL + +OUI:E07F88* + ID_OUI_FROM_DATABASE=EVIDENCE Network SIA + +OUI:E08177* + ID_OUI_FROM_DATABASE=GreenBytes, Inc. + +OUI:E084F3* + ID_OUI_FROM_DATABASE=High Grade Controls Corporation + +OUI:E0859A* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:E087B1* + ID_OUI_FROM_DATABASE=Nata-Info Ltd. + +OUI:E0885D* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:E0897E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0899D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E08A7E* + ID_OUI_FROM_DATABASE=Exponent + +OUI:E08E3C* + ID_OUI_FROM_DATABASE=Aztech Electronics Pte Ltd + +OUI:E08FEC* + ID_OUI_FROM_DATABASE=REPOTEC CO., LTD. + +OUI:E09153* + ID_OUI_FROM_DATABASE=XAVi Technologies Corp. + +OUI:E091F5* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:E09467* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E09579* + ID_OUI_FROM_DATABASE=ORTHOsoft inc, d/b/a Zimmer CAS + +OUI:E09796* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E097F2* + ID_OUI_FROM_DATABASE=Atomax Inc. + +OUI:E09806* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:E09861* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:E09971* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E09D31* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E09DB8* + ID_OUI_FROM_DATABASE=PLANEX COMMUNICATIONS INC. + +OUI:E09DFA* + ID_OUI_FROM_DATABASE=Wanan Hongsheng Electronic Co.Ltd + +OUI:E09F2A* + ID_OUI_FROM_DATABASE=Iton Technology Corp. + +OUI:E0A198* + ID_OUI_FROM_DATABASE=NOJA Power Switchgear Pty Ltd + +OUI:E0A1D7* + ID_OUI_FROM_DATABASE=SFR + +OUI:E0A30F* + ID_OUI_FROM_DATABASE=Pevco + +OUI:E0A3AC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E0A509* + ID_OUI_FROM_DATABASE=Bitmain Technologies Inc + +OUI:E0A670* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:E0A700* + ID_OUI_FROM_DATABASE=Verkada Inc + +OUI:E0A8B8* + ID_OUI_FROM_DATABASE=Le Shi Zhi Xin Electronic Technology (Tianjin) Limited + +OUI:E0AA96* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E0AAB0* + ID_OUI_FROM_DATABASE=SUNTAILI ENTERPRISE CO. LTD, + +OUI:E0AADB* + ID_OUI_FROM_DATABASE=Nanjing PANENG Technology Development Co.,Ltd + +OUI:E0ABFE* + ID_OUI_FROM_DATABASE=Orb Networks, Inc. + +OUI:E0ACCB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0ACF1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E0AE5E* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:E0AEB2* + ID_OUI_FROM_DATABASE=Bender GmbH & Co.KG + +OUI:E0AEED* + ID_OUI_FROM_DATABASE=LOENK + +OUI:E0AF4B* + ID_OUI_FROM_DATABASE=Pluribus Networks, Inc. + +OUI:E0AF4F* + ID_OUI_FROM_DATABASE=Deutsche Telekom AG + +OUI:E0B2F1* + ID_OUI_FROM_DATABASE=FN-LINK TECHNOLOGY LIMITED + +OUI:E0B52D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0B55F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0B655* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd. + +OUI:E0B6F50* + ID_OUI_FROM_DATABASE=BeSTAR Corporation + +OUI:E0B6F51* + ID_OUI_FROM_DATABASE=START TODAY CO.,LTD. + +OUI:E0B6F52* + ID_OUI_FROM_DATABASE=Shanghai- British Information Technology Co., Ltd + +OUI:E0B6F53* + ID_OUI_FROM_DATABASE=Huizhou GISUN Industrial CO. LTD + +OUI:E0B6F54* + ID_OUI_FROM_DATABASE=Agora + +OUI:E0B6F55* + ID_OUI_FROM_DATABASE=Shenzhen Civicom Technology Co.,Limited + +OUI:E0B6F56* + ID_OUI_FROM_DATABASE=POMCube Inc. + +OUI:E0B6F57* + ID_OUI_FROM_DATABASE=Shenzhen Xrinda Technology Ltd + +OUI:E0B6F58* + ID_OUI_FROM_DATABASE=Yuneec International(China)Co.,Ltd + +OUI:E0B6F59* + ID_OUI_FROM_DATABASE=Motiveprime Consumer Electronics Pvt Ltd + +OUI:E0B6F5A* + ID_OUI_FROM_DATABASE=Folksam AB + +OUI:E0B6F5B* + ID_OUI_FROM_DATABASE=Moog Crossbow + +OUI:E0B6F5C* + ID_OUI_FROM_DATABASE=funktel GmbH + +OUI:E0B6F5D* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:E0B6F5E* + ID_OUI_FROM_DATABASE=Advatek Lighting Pty Ltd + +OUI:E0B70A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E0B7B1* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E0B94D* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD + +OUI:E0B9A5* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:E0B9BA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0B9E5* + ID_OUI_FROM_DATABASE=Technicolor + +OUI:E0BAB4* + ID_OUI_FROM_DATABASE=Arrcus, Inc + +OUI:E0BB9E* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:E0BC43* + ID_OUI_FROM_DATABASE=C2 Microsystems, Inc. + +OUI:E0C0D1* + ID_OUI_FROM_DATABASE=CK Telecom (Shenzhen) Limited + +OUI:E0C286* + ID_OUI_FROM_DATABASE=Aisai Communication Technology Co., Ltd. + +OUI:E0C2B7* + ID_OUI_FROM_DATABASE=Masimo Corporation + +OUI:E0C3F3* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E0C63C* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:E0C6B3* + ID_OUI_FROM_DATABASE=MilDef AB + +OUI:E0C767* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0C79D* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:E0C86A* + ID_OUI_FROM_DATABASE=SHENZHEN TW-SCIE Co., Ltd + +OUI:E0C922* + ID_OUI_FROM_DATABASE=Jireh Energy Tech., Ltd. + +OUI:E0C97A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0CA4D* + ID_OUI_FROM_DATABASE=Shenzhen Unistar Communication Co.,LTD + +OUI:E0CA94* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:E0CB1D* + ID_OUI_FROM_DATABASE=Private + +OUI:E0CB4E* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:E0CBBC* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:E0CBEE* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E0CC7A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E0CCF8* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:E0CDFD* + ID_OUI_FROM_DATABASE=Beijing E3Control Technology Co, LTD + +OUI:E0CEC3* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:E0CF2D* + ID_OUI_FROM_DATABASE=Gemintek Corporation + +OUI:E0D083* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E0D10A* + ID_OUI_FROM_DATABASE=Katoudenkikougyousyo co ltd + +OUI:E0D173* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E0D1E6* + ID_OUI_FROM_DATABASE=Aliph dba Jawbone + +OUI:E0D31A* + ID_OUI_FROM_DATABASE=EQUES Technology Co., Limited + +OUI:E0D4E8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E0D55E* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:E0D7BA* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:E0D848* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:E0D9A2* + ID_OUI_FROM_DATABASE=Hippih aps + +OUI:E0D9E3* + ID_OUI_FROM_DATABASE=Eltex Enterprise Ltd. + +OUI:E0DADC* + ID_OUI_FROM_DATABASE=JVC KENWOOD Corporation + +OUI:E0DB10* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E0DB55* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:E0DB88* + ID_OUI_FROM_DATABASE=Open Standard Digital-IF Interface for SATCOM Systems + +OUI:E0DCA0* + ID_OUI_FROM_DATABASE=Siemens Industrial Automation Products Ltd Chengdu + +OUI:E0DCFF* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:E0DDC0* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:E0E0FC* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:E0E5CF* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:E0E62E* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:E0E631* + ID_OUI_FROM_DATABASE=SNB TECHNOLOGIES LIMITED + +OUI:E0E751* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:E0E7BB* + ID_OUI_FROM_DATABASE=Nureva, Inc. + +OUI:E0E8E6* + ID_OUI_FROM_DATABASE=Shenzhen C-Data Technology Co., Ltd. + +OUI:E0E8E8* + ID_OUI_FROM_DATABASE=Olive Telecommunication Pvt. Ltd + +OUI:E0EB40* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0EB62* + ID_OUI_FROM_DATABASE=Shanghai Hulu Devices Co., Ltd + +OUI:E0ED1A* + ID_OUI_FROM_DATABASE=vastriver Technology Co., Ltd + +OUI:E0EDC7* + ID_OUI_FROM_DATABASE=Shenzhen Friendcom Technology Development Co., Ltd + +OUI:E0EE1B* + ID_OUI_FROM_DATABASE=Panasonic Automotive Systems Company of America + +OUI:E0EF25* + ID_OUI_FROM_DATABASE=Lintes Technology Co., Ltd. + +OUI:E0F211* + ID_OUI_FROM_DATABASE=Digitalwatt + +OUI:E0F379* + ID_OUI_FROM_DATABASE=Vaddio + +OUI:E0F442* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:E0F5C6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0F5CA* + ID_OUI_FROM_DATABASE=CHENG UEI PRECISION INDUSTRY CO.,LTD. + +OUI:E0F847* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E0F9BE* + ID_OUI_FROM_DATABASE=Cloudena Corp. + +OUI:E0FAEC* + ID_OUI_FROM_DATABASE=Platan sp. z o.o. sp. k. + +OUI:E0FFF7* + ID_OUI_FROM_DATABASE=Softiron Inc. + +OUI:E4029B* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E40439* + ID_OUI_FROM_DATABASE=TomTom Software Ltd + +OUI:E405F8* + ID_OUI_FROM_DATABASE=Delta Innovation Technology Co., Ltd. + +OUI:E40EEE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E4115B* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:E41218* + ID_OUI_FROM_DATABASE=ShenZhen Rapoo Technology Co., Ltd. + +OUI:E4121D* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E41289* + ID_OUI_FROM_DATABASE=topsystem Systemhaus GmbH + +OUI:E415F6* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:E417D8* + ID_OUI_FROM_DATABASE=8BITDO TECHNOLOGY HK LIMITED + +OUI:E4186B* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:E419C1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E41A2C* + ID_OUI_FROM_DATABASE=ZPE Systems, Inc. + +OUI:E41C4B* + ID_OUI_FROM_DATABASE=V2 TECHNOLOGY, INC. + +OUI:E41D2D* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:E41E0A0* + ID_OUI_FROM_DATABASE=Zavod № 423 + +OUI:E41E0A1* + ID_OUI_FROM_DATABASE=Connected Cars A/S + +OUI:E41E0A2* + ID_OUI_FROM_DATABASE=IDvaco Private Limited + +OUI:E41E0A3* + ID_OUI_FROM_DATABASE=Avast Software s.r.o. + +OUI:E41E0A4* + ID_OUI_FROM_DATABASE=XPR Group + +OUI:E41E0A5* + ID_OUI_FROM_DATABASE=Aeroel srl + +OUI:E41E0A6* + ID_OUI_FROM_DATABASE=SFC Energy AG + +OUI:E41E0A7* + ID_OUI_FROM_DATABASE=Tritium Pty Ltd + +OUI:E41E0A8* + ID_OUI_FROM_DATABASE=SAGE Glass + +OUI:E41E0A9* + ID_OUI_FROM_DATABASE=B METERS S.R.L. + +OUI:E41E0AA* + ID_OUI_FROM_DATABASE=FireAngel Safety Technology Ltd + +OUI:E41E0AB* + ID_OUI_FROM_DATABASE=Safety Vision, LLC + +OUI:E41E0AC* + ID_OUI_FROM_DATABASE=TELETASK BELGIUM + +OUI:E41E0AD* + ID_OUI_FROM_DATABASE=ROMO Wind A/S + +OUI:E41E0AE* + ID_OUI_FROM_DATABASE=Shanghai LeXiang Technology Co., Ltd + +OUI:E41F13* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:E41FE9* + ID_OUI_FROM_DATABASE=Dunkermotoren GmbH + +OUI:E422A5* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. + +OUI:E42354* + ID_OUI_FROM_DATABASE=SHENZHEN FUZHI SOFTWARE TECHNOLOGY CO.,LTD + +OUI:E425E7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E425E9* + ID_OUI_FROM_DATABASE=Color-Chip + +OUI:E42686* + ID_OUI_FROM_DATABASE=DWnet Technologies(Suzhou) Corporation + +OUI:E42771* + ID_OUI_FROM_DATABASE=Smartlabs + +OUI:E42AD3* + ID_OUI_FROM_DATABASE=Magneti Marelli S.p.A. Powertrain + +OUI:E42B34* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E42C56* + ID_OUI_FROM_DATABASE=Lilee Systems, Ltd. + +OUI:E42D02* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:E42D7B* + ID_OUI_FROM_DATABASE=China Mobile IOT Company Limited + +OUI:E42F26* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:E42F56* + ID_OUI_FROM_DATABASE=OptoMET GmbH + +OUI:E42FF6* + ID_OUI_FROM_DATABASE=Unicore communication Inc. + +OUI:E43022* + ID_OUI_FROM_DATABASE=Hanwha Techwin Security Vietnam + +OUI:E432CB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E43493* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E43593* + ID_OUI_FROM_DATABASE=Hangzhou GoTo technology Co.Ltd + +OUI:E435C8* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E435FB* + ID_OUI_FROM_DATABASE=Sabre Technology (Hull) Ltd + +OUI:E437D7* + ID_OUI_FROM_DATABASE=HENRI DEPAEPE S.A.S. + +OUI:E4388C* + ID_OUI_FROM_DATABASE=Digital Products Limited + +OUI:E438F2* + ID_OUI_FROM_DATABASE=Advantage Controls + +OUI:E43A6E* + ID_OUI_FROM_DATABASE=Shenzhen Zeroone Technology CO.,LTD + +OUI:E43C80* + ID_OUI_FROM_DATABASE=University of Oklahoma + +OUI:E43ED7* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:E43FA2* + ID_OUI_FROM_DATABASE=Wuxi DSP Technologies Inc. + +OUI:E440E2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E441E6* + ID_OUI_FROM_DATABASE=Ottec Technology GmbH + +OUI:E442A6* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E4434B* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:E446BD* + ID_OUI_FROM_DATABASE=C&C TECHNIC TAIWAN CO., LTD. + +OUI:E446DA* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:E44790* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:E447B3* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E448C7* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:E44C6C* + ID_OUI_FROM_DATABASE=Shenzhen Guo Wei Electronic Co,. Ltd. + +OUI:E44CC70* + ID_OUI_FROM_DATABASE=Alert Alarm AB + +OUI:E44CC71* + ID_OUI_FROM_DATABASE=ACS-Solutions GmbH + +OUI:E44CC72* + ID_OUI_FROM_DATABASE=Doowon Electronics & Telecom Co.,Ltd + +OUI:E44CC73* + ID_OUI_FROM_DATABASE=JSC Svyaz Inginiring M + +OUI:E44CC74* + ID_OUI_FROM_DATABASE=Beijing Zhongchuangwei Nanjing Quantum Communication Technology Co., Ltd. + +OUI:E44CC75* + ID_OUI_FROM_DATABASE=CE LABS, LLC + +OUI:E44CC76* + ID_OUI_FROM_DATABASE=HANGZHOU OLE-SYSTEMS CO., LTD + +OUI:E44CC77* + ID_OUI_FROM_DATABASE=Channel Enterprises (HK) Ltd. + +OUI:E44CC78* + ID_OUI_FROM_DATABASE=IAG GROUP LTD + +OUI:E44CC79* + ID_OUI_FROM_DATABASE=Ottomate International Pvt. Ltd. + +OUI:E44CC7A* + ID_OUI_FROM_DATABASE=Muzik Inc + +OUI:E44CC7B* + ID_OUI_FROM_DATABASE=SmallHD + +OUI:E44CC7C* + ID_OUI_FROM_DATABASE=EPS Bio + +OUI:E44CC7D* + ID_OUI_FROM_DATABASE=Telo Systems Limitd + +OUI:E44CC7E* + ID_OUI_FROM_DATABASE=FLK information security technology Co,. Ltd + +OUI:E44E18* + ID_OUI_FROM_DATABASE=Gardasoft VisionLimited + +OUI:E44E76* + ID_OUI_FROM_DATABASE=CHAMPIONTECH ENTERPRISE (SHENZHEN) INC + +OUI:E44F29* + ID_OUI_FROM_DATABASE=MA Lighting Technology GmbH + +OUI:E44F5F* + ID_OUI_FROM_DATABASE=EDS Elektronik Destek San.Tic.Ltd.Sti + +OUI:E4509A* + ID_OUI_FROM_DATABASE=HW Communications Ltd + +OUI:E450EB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E454E8* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:E455EA* + ID_OUI_FROM_DATABASE=Dedicated Computing + +OUI:E45614* + ID_OUI_FROM_DATABASE=Suttle Apparatus + +OUI:E45740* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E457A8* + ID_OUI_FROM_DATABASE=Stuart Manufacturing, Inc. + +OUI:E458B8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E458E7* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E45AA2* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:E45D37* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:E45D51* + ID_OUI_FROM_DATABASE=SFR + +OUI:E45D52* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:E45D75* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E45E37* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E46059* + ID_OUI_FROM_DATABASE=Pingtek Co., Ltd. + +OUI:E46251* + ID_OUI_FROM_DATABASE=HAO CHENG GROUP LIMITED + +OUI:E46449* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E4671E* + ID_OUI_FROM_DATABASE=SHEN ZHEN NUO XIN CHENG TECHNOLOGY co., Ltd. + +OUI:E467BA* + ID_OUI_FROM_DATABASE=Danish Interpretation Systems A/S + +OUI:E468A3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E4695A* + ID_OUI_FROM_DATABASE=Dictum Health, Inc. + +OUI:E46C21* + ID_OUI_FROM_DATABASE=messMa GmbH + +OUI:E46F13* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:E470B8* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E47185* + ID_OUI_FROM_DATABASE=Securifi Ltd + +OUI:E472E2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E4751E* + ID_OUI_FROM_DATABASE=Getinge Sterilization AB + +OUI:E47684* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E47723* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E4776B* + ID_OUI_FROM_DATABASE=AARTESYS AG + +OUI:E477D4* + ID_OUI_FROM_DATABASE=Minrray Industry Co.,Ltd + +OUI:E47B3F* + ID_OUI_FROM_DATABASE=BEIJING CO-CLOUD TECHNOLOGY LTD. + +OUI:E47C65* + ID_OUI_FROM_DATABASE=Sunstar Communication Technology Co., Ltd + +OUI:E47CF9* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E47D5A* + ID_OUI_FROM_DATABASE=Beijing Hanbang Technology Corp. + +OUI:E47DBD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E47DEB* + ID_OUI_FROM_DATABASE=Shanghai Notion Information Technology CO.,LTD. + +OUI:E47E66* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E47E9A* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E47FB2* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:E48184* + ID_OUI_FROM_DATABASE=Nokia + +OUI:E481B3* + ID_OUI_FROM_DATABASE=Shenzhen ACT Industrial Co.,Ltd. + +OUI:E482CC* + ID_OUI_FROM_DATABASE=Jumptronic GmbH + +OUI:E48326* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E48399* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E48501* + ID_OUI_FROM_DATABASE=Geberit International AG + +OUI:E48AD5* + ID_OUI_FROM_DATABASE=RF WINDOW CO., LTD. + +OUI:E48B7F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E48C0F* + ID_OUI_FROM_DATABASE=Discovery Insure + +OUI:E48D8C* + ID_OUI_FROM_DATABASE=Routerboard.com + +OUI:E48F34* + ID_OUI_FROM_DATABASE=Vodafone Italia S.p.A. + +OUI:E48F65* + ID_OUI_FROM_DATABASE=Yelatma Instrument Making Enterprise, JSC + +OUI:E49069* + ID_OUI_FROM_DATABASE=Rockwell Automation + +OUI:E4907E* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:E490FD* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E4922A* + ID_OUI_FROM_DATABASE=DBG HOLDINGS LIMITED + +OUI:E492E7* + ID_OUI_FROM_DATABASE=Gridlink Tech. Co.,Ltd. + +OUI:E492FB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E4956E0* + ID_OUI_FROM_DATABASE=SMC Networks, Inc + +OUI:E4956E1* + ID_OUI_FROM_DATABASE=Tband srl + +OUI:E4956E2* + ID_OUI_FROM_DATABASE=Shanghai Hoping Technology Co., Ltd. + +OUI:E4956E3* + ID_OUI_FROM_DATABASE=Shanghai DGE Co., Ltd + +OUI:E4956E4* + ID_OUI_FROM_DATABASE=Guang Lian Zhi Tong Technology Limited + +OUI:E4956E5* + ID_OUI_FROM_DATABASE=ELAN SYSTEMS + +OUI:E4956E6* + ID_OUI_FROM_DATABASE=SHENZHEN JOYETECH ELECTRONICS CO., LTD. + +OUI:E4956E7* + ID_OUI_FROM_DATABASE=NationalchipKorea + +OUI:E4956E8* + ID_OUI_FROM_DATABASE=PT.MLWTelecom + +OUI:E4956E9* + ID_OUI_FROM_DATABASE=eZeLink LLC + +OUI:E4956EA* + ID_OUI_FROM_DATABASE=Red Point Positioning, Corp. + +OUI:E4956EB* + ID_OUI_FROM_DATABASE=iConservo Inc + +OUI:E4956EC* + ID_OUI_FROM_DATABASE=Shenzhen Arronna Telecom Co.,Ltd + +OUI:E4956ED* + ID_OUI_FROM_DATABASE=Shanghai Tieda Telecommunications Equipment Co.,LTD. + +OUI:E4956EE* + ID_OUI_FROM_DATABASE=Tacom Projetos Bilhetagem Inteligente ltda + +OUI:E4956EF* + ID_OUI_FROM_DATABASE=Private + +OUI:E496AE* + ID_OUI_FROM_DATABASE=ALTOGRAPHICS Inc. + +OUI:E497F0* + ID_OUI_FROM_DATABASE=Shanghai VLC Technologies Ltd. Co. + +OUI:E498BB* + ID_OUI_FROM_DATABASE=Phyplus Microelectronics Limited + +OUI:E498D1* + ID_OUI_FROM_DATABASE=Microsoft Mobile Oy + +OUI:E498D6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E49A79* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E49ADC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E49E12* + ID_OUI_FROM_DATABASE=FREEBOX SAS + +OUI:E49F1E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E4A1E6* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:E4A32F* + ID_OUI_FROM_DATABASE=Shanghai Artimen Technology Co., Ltd. + +OUI:E4A387* + ID_OUI_FROM_DATABASE=Control Solutions LLC + +OUI:E4A471* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E4A5EF* + ID_OUI_FROM_DATABASE=TRON LINK ELECTRONICS CO., LTD. + +OUI:E4A749* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:E4A7A0* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E4A7C5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E4A7FD* + ID_OUI_FROM_DATABASE=Cellco Partnership + +OUI:E4A8B6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E4A8DF* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:E4AA5D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E4AAEA* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:E4AAEC* + ID_OUI_FROM_DATABASE=Tianjin Hualai Technology Co., Ltd + +OUI:E4AB46* + ID_OUI_FROM_DATABASE=UAB Selteka + +OUI:E4AB89* + ID_OUI_FROM_DATABASE=MitraStar Technology Corp. + +OUI:E4AD7D* + ID_OUI_FROM_DATABASE=SCL Elements + +OUI:E4AFA1* + ID_OUI_FROM_DATABASE=HES-SO + +OUI:E4B005* + ID_OUI_FROM_DATABASE=Beijing IQIYI Science & Technology Co., Ltd. + +OUI:E4B021* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E4B2FB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E4B318* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E4B97A* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:E4BAD9* + ID_OUI_FROM_DATABASE=360 Fly Inc. + +OUI:E4BD4B* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E4BEED* + ID_OUI_FROM_DATABASE=Netcore Technology Inc. + +OUI:E4C0CC* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:E4C146* + ID_OUI_FROM_DATABASE=Objetivos y Servicios de Valor A + +OUI:E4C1F1* + ID_OUI_FROM_DATABASE=SHENZHEN SPOTMAU INFORMATION TECHNOLIGY CO., Ltd + +OUI:E4C2D1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E4C483* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:E4C62B* + ID_OUI_FROM_DATABASE=Airware + +OUI:E4C63D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E4C6E6* + ID_OUI_FROM_DATABASE=Mophie, LLC + +OUI:E4C722* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E4C801* + ID_OUI_FROM_DATABASE=BLU Products Inc + +OUI:E4C806* + ID_OUI_FROM_DATABASE=Ceiec Electric Technology Inc. + +OUI:E4CA12* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E4CB59* + ID_OUI_FROM_DATABASE=Beijing Loveair Science and Technology Co. Ltd. + +OUI:E4CC9D* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:E4CE02* + ID_OUI_FROM_DATABASE=WyreStorm Technologies Ltd + +OUI:E4CE70* + ID_OUI_FROM_DATABASE=Health & Life co., Ltd. + +OUI:E4CE8F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E4D124* + ID_OUI_FROM_DATABASE=Mojo Networks, Inc. + +OUI:E4D332* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:E4D3AA* + ID_OUI_FROM_DATABASE=FUJITSU CONNECTED TECHNOLOGIES LIMITED + +OUI:E4D3F1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E4D53D* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:E4D71D* + ID_OUI_FROM_DATABASE=Oraya Therapeutics + +OUI:E4DB6D* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd. + +OUI:E4DD79* + ID_OUI_FROM_DATABASE=En-Vision America, Inc. + +OUI:E4E0A6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E4E0C5* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E4E112* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:E4E130* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:E4E409* + ID_OUI_FROM_DATABASE=LEIFHEIT AG + +OUI:E4E4AB* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E4E749* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:E4EA83* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:E4EC10* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:E4EEFD* + ID_OUI_FROM_DATABASE=MR&D Manufacturing + +OUI:E4F004* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:E4F042* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:E4F14C* + ID_OUI_FROM_DATABASE=Private + +OUI:E4F327* + ID_OUI_FROM_DATABASE=ATOL LLC + +OUI:E4F365* + ID_OUI_FROM_DATABASE=Time-O-Matic, Inc. + +OUI:E4F3C4* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E4F3E3* + ID_OUI_FROM_DATABASE=Shanghai iComhome Co.,Ltd. + +OUI:E4F3E8* + ID_OUI_FROM_DATABASE=Shenzhen SuperElectron Technology Co.,Ltd. + +OUI:E4F3F5* + ID_OUI_FROM_DATABASE=SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:E4F4C6* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:E4F7A1* + ID_OUI_FROM_DATABASE=Datafox GmbH + +OUI:E4F89C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E4F8EF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E4F939* + ID_OUI_FROM_DATABASE=Minxon Hotel Technology INC. + +OUI:E4FA1D* + ID_OUI_FROM_DATABASE=PAD Peripheral Advanced Design Inc. + +OUI:E4FAED* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E4FAFD* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E4FB5D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E4FB8F* + ID_OUI_FROM_DATABASE=MOBIWIRE MOBILES (NINGBO) CO.,LTD + +OUI:E4FC82* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:E4FDA1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E4FED9* + ID_OUI_FROM_DATABASE=EDMI Europe Ltd + +OUI:E4FFDD* + ID_OUI_FROM_DATABASE=ELECTRON INDIA + +OUI:E80036* + ID_OUI_FROM_DATABASE=Befs co,. ltd + +OUI:E8018D* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:E8039A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E8040B* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E80410* + ID_OUI_FROM_DATABASE=Private + +OUI:E80462* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E804F3* + ID_OUI_FROM_DATABASE=Throughtek Co., Ltd. + +OUI:E8056D* + ID_OUI_FROM_DATABASE=Nortel Networks + +OUI:E80688* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E80734* + ID_OUI_FROM_DATABASE=Champion Optical Network Engineering, LLC + +OUI:E807BF* + ID_OUI_FROM_DATABASE=SHENZHEN BOOMTECH INDUSTRY CO.,LTD + +OUI:E8088B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E80945* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:E80959* + ID_OUI_FROM_DATABASE=Guoguang Electric Co.,Ltd + +OUI:E80B13* + ID_OUI_FROM_DATABASE=Akib Systems Taiwan, INC + +OUI:E80C38* + ID_OUI_FROM_DATABASE=DAEYOUNG INFORMATION SYSTEM CO., LTD + +OUI:E80C75* + ID_OUI_FROM_DATABASE=Syncbak, Inc. + +OUI:E80FC8* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. + +OUI:E8102E* + ID_OUI_FROM_DATABASE=Really Simple Software, Inc + +OUI:E81132* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E811CA* + ID_OUI_FROM_DATABASE=SHANDONG KAER ELECTRIC.CO.,LTD + +OUI:E81324* + ID_OUI_FROM_DATABASE=GuangZhou Bonsoninfo System CO.,LTD + +OUI:E81363* + ID_OUI_FROM_DATABASE=Comstock RD, Inc. + +OUI:E81367* + ID_OUI_FROM_DATABASE=AIRSOUND Inc. + +OUI:E8150E* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:E8162B* + ID_OUI_FROM_DATABASE=IDEO Security Co., Ltd. + +OUI:E817FC* + ID_OUI_FROM_DATABASE=Fujitsu Cloud Technologies Limited + +OUI:E818630* + ID_OUI_FROM_DATABASE=DigiMagus Technology (Shenzhen) Co., Ltd + +OUI:E818631* + ID_OUI_FROM_DATABASE=clabsys + +OUI:E818632* + ID_OUI_FROM_DATABASE=AVCON Information Technology Co.,Ltd + +OUI:E818633* + ID_OUI_FROM_DATABASE=DongGuan Pengxun Electronics Technology Co., Ltd. + +OUI:E818634* + ID_OUI_FROM_DATABASE=Guangzhou Tianyi Electronics Co., Ltd + +OUI:E818635* + ID_OUI_FROM_DATABASE=WETEK ELECTRONICS LIMITED + +OUI:E818636* + ID_OUI_FROM_DATABASE=ARTECH SOLUTION CO.,LTD + +OUI:E818637* + ID_OUI_FROM_DATABASE=Siliconcube + +OUI:E818639* + ID_OUI_FROM_DATABASE=BSM Wireless Inc. + +OUI:E81863A* + ID_OUI_FROM_DATABASE=JDM Mobile Internet Solution(Shanghai) Co., Ltd. + +OUI:E81863B* + ID_OUI_FROM_DATABASE=Protek Electronics Group Co.,LTD + +OUI:E81863C* + ID_OUI_FROM_DATABASE=Shenzhen Hipad Telecommunication Technology Co.,Ltd + +OUI:E81863D* + ID_OUI_FROM_DATABASE=DIGITAL DYNAMICS, INC. + +OUI:E81863E* + ID_OUI_FROM_DATABASE=Acopian Technical Company + +OUI:E81863F* + ID_OUI_FROM_DATABASE=Private + +OUI:E81A58* + ID_OUI_FROM_DATABASE=TECHNOLOGIC SYSTEMS + +OUI:E81AAC* + ID_OUI_FROM_DATABASE=ORFEO SOUNDWORKS Inc. + +OUI:E81B4B* + ID_OUI_FROM_DATABASE=amnimo Inc. + +OUI:E81CBA* + ID_OUI_FROM_DATABASE=Fortinet, Inc. + +OUI:E81DA8* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:E820E2* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:E82689* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:E826B6* + ID_OUI_FROM_DATABASE=Inside Biometrics International Limited + +OUI:E82877* + ID_OUI_FROM_DATABASE=TMY Co., Ltd. + +OUI:E828C1* + ID_OUI_FROM_DATABASE=Eltex Enterprise Ltd. + +OUI:E828D5* + ID_OUI_FROM_DATABASE=Cots Technology + +OUI:E82A44* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:E82AEA* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E82C6D* + ID_OUI_FROM_DATABASE=SmartRG, Inc. + +OUI:E82E0C* + ID_OUI_FROM_DATABASE=NETINT Technologies Inc. + +OUI:E82E24* + ID_OUI_FROM_DATABASE=Out of the Fog Research LLC + +OUI:E8330D* + ID_OUI_FROM_DATABASE=Xaptec GmbH + +OUI:E83381* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E8343E* + ID_OUI_FROM_DATABASE=Beijing Infosec Technologies Co., LTD. + +OUI:E83617* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E8361D* + ID_OUI_FROM_DATABASE=Sense Labs, Inc. + +OUI:E8377A* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:E83935* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:E839DF* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:E83A12* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E83A97* + ID_OUI_FROM_DATABASE=Toshiba Corporation + +OUI:E83EB6* + ID_OUI_FROM_DATABASE=RIM + +OUI:E83EFB* + ID_OUI_FROM_DATABASE=GEODESIC LTD. + +OUI:E83EFC* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E83F67* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:E84040* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E840F2* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:E843B6* + ID_OUI_FROM_DATABASE=QNAP Systems, Inc. + +OUI:E8447E* + ID_OUI_FROM_DATABASE=Bitdefender SRL + +OUI:E8481F* + ID_OUI_FROM_DATABASE=Advanced Automotive Antennas + +OUI:E84943* + ID_OUI_FROM_DATABASE=YUGE Information technology Co. Ltd + +OUI:E84C56* + ID_OUI_FROM_DATABASE=INTERCEPT SERVICES LIMITED + +OUI:E84DD0* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E84E06* + ID_OUI_FROM_DATABASE=EDUP INTERNATIONAL (HK) CO., LTD + +OUI:E84E84* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E84ECE* + ID_OUI_FROM_DATABASE=Nintendo Co., Ltd. + +OUI:E8508B* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:E8516E* + ID_OUI_FROM_DATABASE=TSMART Inc. + +OUI:E8519D* + ID_OUI_FROM_DATABASE=Yeonhab Precision Co.,LTD + +OUI:E85484* + ID_OUI_FROM_DATABASE=NEO Information Systems Co., Ltd. + +OUI:E855B4* + ID_OUI_FROM_DATABASE=SAI Technology Inc. + +OUI:E85659* + ID_OUI_FROM_DATABASE=Advanced-Connectek Inc. + +OUI:E856D6* + ID_OUI_FROM_DATABASE=NCTech Ltd + +OUI:E85A8B* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:E85AA7* + ID_OUI_FROM_DATABASE=LLC Emzior + +OUI:E85AD1* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:E85B5B* + ID_OUI_FROM_DATABASE=LG ELECTRONICS INC + +OUI:E85BB7* + ID_OUI_FROM_DATABASE=Ample Systems Inc. + +OUI:E85BF0* + ID_OUI_FROM_DATABASE=Imaging Diagnostics + +OUI:E85D6B* + ID_OUI_FROM_DATABASE=Luminate Wireless + +OUI:E85D86* + ID_OUI_FROM_DATABASE=CHANG YOW TECHNOLOGIES INTERNATIONAL CO.,LTD. + +OUI:E85E53* + ID_OUI_FROM_DATABASE=Infratec Datentechnik GmbH + +OUI:E8611F* + ID_OUI_FROM_DATABASE=Dawning Information Industry Co.,Ltd + +OUI:E8617E* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:E86183* + ID_OUI_FROM_DATABASE=Black Diamond Advanced Technology, LLC + +OUI:E861BE* + ID_OUI_FROM_DATABASE=Melec Inc. + +OUI:E86549* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E865D4* + ID_OUI_FROM_DATABASE=Tenda Technology Co.,Ltd.Dongguan branch + +OUI:E866C4* + ID_OUI_FROM_DATABASE=Diamanti + +OUI:E86819* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E86A64* + ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd + +OUI:E86CDA* + ID_OUI_FROM_DATABASE=Supercomputers and Neurocomputers Research Center + +OUI:E86D52* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E86D54* + ID_OUI_FROM_DATABASE=Digit Mobile Inc + +OUI:E86D65* + ID_OUI_FROM_DATABASE=AUDIO MOBIL Elektronik GmbH + +OUI:E86D6E* + ID_OUI_FROM_DATABASE=voestalpine SIGNALING Fareham Ltd. + +OUI:E86F38* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:E86FF2* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:E8718D* + ID_OUI_FROM_DATABASE=Elsys Equipamentos Eletronicos Ltda + +OUI:E874E6* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:E8757F* + ID_OUI_FROM_DATABASE=FIRS Technologies(Shenzhen) Co., Ltd + +OUI:E878A1* + ID_OUI_FROM_DATABASE=BEOVIEW INTERCOM DOO + +OUI:E87AF3* + ID_OUI_FROM_DATABASE=S5 Tech S.r.l. + +OUI:E8802E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E880D8* + ID_OUI_FROM_DATABASE=GNTEK Electronics Co.,Ltd. + +OUI:E8825B* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E884C6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E887A3* + ID_OUI_FROM_DATABASE=Loxley Public Company Limited + +OUI:E8886C* + ID_OUI_FROM_DATABASE=Shenzhen SC Technologies Co.,LTD + +OUI:E8892C* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E88D28* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E88DF5* + ID_OUI_FROM_DATABASE=ZNYX Networks, Inc. + +OUI:E88E60* + ID_OUI_FROM_DATABASE=NSD Corporation + +OUI:E8910F* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:E89120* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:E89218* + ID_OUI_FROM_DATABASE=Arcontia International AB + +OUI:E892A4* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:E89309* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E89363* + ID_OUI_FROM_DATABASE=Nokia + +OUI:E8944C* + ID_OUI_FROM_DATABASE=Cogent Healthcare Systems Ltd + +OUI:E894F6* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:E89606* + ID_OUI_FROM_DATABASE=testo Instruments (Shenzhen) Co., Ltd. + +OUI:E8986D* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:E8995A* + ID_OUI_FROM_DATABASE=PiiGAB, Processinformation i Goteborg AB + +OUI:E899C4* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:E89A8F* + ID_OUI_FROM_DATABASE=QUANTA COMPUTER INC. + +OUI:E89AFF* + ID_OUI_FROM_DATABASE=Fujian LANDI Commercial Equipment Co.,Ltd + +OUI:E89D87* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:E89E0C* + ID_OUI_FROM_DATABASE=Private + +OUI:E89EB4* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:E89FEC* + ID_OUI_FROM_DATABASE=CHENGDU KT ELECTRONIC HI-TECH CO.,LTD + +OUI:E8A364* + ID_OUI_FROM_DATABASE=Signal Path International / Peachtree Audio + +OUI:E8A4C1* + ID_OUI_FROM_DATABASE=Deep Sea Electronics Ltd + +OUI:E8A788* + ID_OUI_FROM_DATABASE=XIAMEN LEELEN TECHNOLOGY CO., LTD + +OUI:E8A7F2* + ID_OUI_FROM_DATABASE=sTraffic + +OUI:E8ABF3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E8ABFA* + ID_OUI_FROM_DATABASE=Shenzhen Reecam Tech.Ltd. + +OUI:E8ACAD* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E8ADA6* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:E8B1FC* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:E8B2AC* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E8B2FE* + ID_OUI_FROM_DATABASE=HUMAX Co., Ltd. + +OUI:E8B4AE* + ID_OUI_FROM_DATABASE=Shenzhen C&D Electronics Co.,Ltd + +OUI:E8B4C8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E8B541* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:E8B6C2* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:E8B748* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E8BA70* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E8BB3D* + ID_OUI_FROM_DATABASE=Sino Prime-Tech Limited + +OUI:E8BBA8* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:E8BDD1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E8BE81* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:E8C1B8* + ID_OUI_FROM_DATABASE=Nanjing Bangzhong Electronic Commerce Limited + +OUI:E8C1D7* + ID_OUI_FROM_DATABASE=Philips + +OUI:E8C229* + ID_OUI_FROM_DATABASE=H-Displays (MSC) Bhd + +OUI:E8C320* + ID_OUI_FROM_DATABASE=Austco Communication Systems Pty Ltd + +OUI:E8C417* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:E8C57A* + ID_OUI_FROM_DATABASE=Ufispace Co., LTD. + +OUI:E8C74F* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:E8CBA1* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:E8CC18* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:E8CC32* + ID_OUI_FROM_DATABASE=Micronet LTD + +OUI:E8CD2D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:E8CE06* + ID_OUI_FROM_DATABASE=SkyHawke Technologies, LLC. + +OUI:E8D03C* + ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + +OUI:E8D099* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:E8D0B9* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:E8D0FA* + ID_OUI_FROM_DATABASE=MKS Instruments Deutschland GmbH + +OUI:E8D0FC* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:E8D11B* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:E8D483* + ID_OUI_FROM_DATABASE=ULTIMATE Europe Transportation Equipment GmbH + +OUI:E8D4E0* + ID_OUI_FROM_DATABASE=Beijing BenyWave Technology Co., Ltd. + +OUI:E8D819* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:E8D8D1* + ID_OUI_FROM_DATABASE=HP Inc. + +OUI:E8DA96* + ID_OUI_FROM_DATABASE=Zhuhai Tianrui Electrical Power Tech. Co., Ltd. + +OUI:E8DAAA* + ID_OUI_FROM_DATABASE=VideoHome Technology Corp. + +OUI:E8DE00* + ID_OUI_FROM_DATABASE=ChongQing GuanFang Technology Co.,LTD + +OUI:E8DE27* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:E8DE8E* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:E8DED6* + ID_OUI_FROM_DATABASE=Intrising Networks, Inc. + +OUI:E8DEFB* + ID_OUI_FROM_DATABASE=MESOTIC SAS + +OUI:E8DF70* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:E8DFF2* + ID_OUI_FROM_DATABASE=PRF Co., Ltd. + +OUI:E8E08F* + ID_OUI_FROM_DATABASE=GRAVOTECH MARKING SAS + +OUI:E8E0B7* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:E8E1E1* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:E8E1E2* + ID_OUI_FROM_DATABASE=Energotest + +OUI:E8E5D6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:E8E732* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Enterprise + +OUI:E8E770* + ID_OUI_FROM_DATABASE=Warp9 Tech Design, Inc. + +OUI:E8E776* + ID_OUI_FROM_DATABASE=Shenzhen Kootion Technology Co., Ltd + +OUI:E8E875* + ID_OUI_FROM_DATABASE=iS5 Communications Inc. + +OUI:E8E8B7* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:E8E98E* + ID_OUI_FROM_DATABASE=SOLAR controls s.r.o. + +OUI:E8EA6A* + ID_OUI_FROM_DATABASE=StarTech.com + +OUI:E8EADA* + ID_OUI_FROM_DATABASE=Denkovi Assembly Electronics LTD + +OUI:E8EB11* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:E8ECA3* + ID_OUI_FROM_DATABASE=Dongguan Liesheng Electronic Co.Ltd + +OUI:E8ED05* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:E8EDF3* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:E8EF89* + ID_OUI_FROM_DATABASE=OPMEX Tech. + +OUI:E8F1B0* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:E8F226* + ID_OUI_FROM_DATABASE=MILLSON CUSTOM SOLUTIONS INC. + +OUI:E8F2E2* + ID_OUI_FROM_DATABASE=LG Innotek + +OUI:E8F2E3* + ID_OUI_FROM_DATABASE=Starcor Beijing Co.,Limited + +OUI:E8F724* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:E8F928* + ID_OUI_FROM_DATABASE=RFTECH SRL + +OUI:E8FAF7* + ID_OUI_FROM_DATABASE=Guangdong Uniteddata Holding Group Co., Ltd. + +OUI:E8FBE9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:E8FC60* + ID_OUI_FROM_DATABASE=ELCOM Innovations Private Limited + +OUI:E8FCAF* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:E8FD72* + ID_OUI_FROM_DATABASE=SHANGHAI LINGUO TECHNOLOGY CO., LTD. + +OUI:E8FD90* + ID_OUI_FROM_DATABASE=Turbostor + +OUI:E8FDE8* + ID_OUI_FROM_DATABASE=CeLa Link Corporation + +OUI:EC0133* + ID_OUI_FROM_DATABASE=TRINUS SYSTEMS INC. + +OUI:EC01E2* + ID_OUI_FROM_DATABASE=FOXCONN INTERCONNECT TECHNOLOGY + +OUI:EC01EE* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:EC0441* + ID_OUI_FROM_DATABASE=ShenZhen TIGO Semiconductor Co., Ltd. + +OUI:EC086B* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:EC0D9A* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:EC0EC4* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:EC0ED6* + ID_OUI_FROM_DATABASE=ITECH INSTRUMENTS SAS + +OUI:EC107B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:EC1120* + ID_OUI_FROM_DATABASE=FloDesign Wind Turbine Corporation + +OUI:EC1127* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:EC13B2* + ID_OUI_FROM_DATABASE=Netonix + +OUI:EC13DB* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:EC14F6* + ID_OUI_FROM_DATABASE=BioControl AS + +OUI:EC172F* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:EC1766* + ID_OUI_FROM_DATABASE=Research Centre Module + +OUI:EC1A59* + ID_OUI_FROM_DATABASE=Belkin International Inc. + +OUI:EC1BBD* + ID_OUI_FROM_DATABASE=Silicon Laboratories + +OUI:EC1D7F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:EC1D8B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:EC1F72* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:EC219F* + ID_OUI_FROM_DATABASE=VidaBox LLC + +OUI:EC21E5* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:EC2257* + ID_OUI_FROM_DATABASE=JiangSu NanJing University Electronic Information Technology Co.,Ltd + +OUI:EC2280* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:EC233D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:EC2368* + ID_OUI_FROM_DATABASE=IntelliVoice Co.,Ltd. + +OUI:EC237B* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:EC24B8* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:EC26CA* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:EC26FB* + ID_OUI_FROM_DATABASE=TECC CO.,LTD. + +OUI:EC2AF0* + ID_OUI_FROM_DATABASE=Ypsomed AG + +OUI:EC2C49* + ID_OUI_FROM_DATABASE=University of Tokyo + +OUI:EC2CE2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:EC2E4E* + ID_OUI_FROM_DATABASE=HITACHI-LG DATA STORAGE INC + +OUI:EC3091* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:EC316D* + ID_OUI_FROM_DATABASE=Hansgrohe + +OUI:EC3586* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:EC363F* + ID_OUI_FROM_DATABASE=Markov Corporation + +OUI:EC3873* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:EC388F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:EC3BF0* + ID_OUI_FROM_DATABASE=NovelSat + +OUI:EC3C5A* + ID_OUI_FROM_DATABASE=SHEN ZHEN HENG SHENG HUI DIGITAL TECHNOLOGY CO.,LTD + +OUI:EC3C88* + ID_OUI_FROM_DATABASE=MCNEX Co.,Ltd. + +OUI:EC3CBB* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:EC3DFD* + ID_OUI_FROM_DATABASE=SHENZHEN BILIAN ELECTRONIC CO.,LTD + +OUI:EC3E09* + ID_OUI_FROM_DATABASE=PERFORMANCE DESIGNED PRODUCTS, LLC + +OUI:EC3EF7* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:EC3F05* + ID_OUI_FROM_DATABASE=Institute 706, The Second Academy China Aerospace Science & Industry Corp + +OUI:EC4118* + ID_OUI_FROM_DATABASE=XIAOMI Electronics,CO.,LTD + +OUI:EC42B4* + ID_OUI_FROM_DATABASE=ADC Corporation + +OUI:EC42F0* + ID_OUI_FROM_DATABASE=ADL Embedded Solutions, Inc. + +OUI:EC438B* + ID_OUI_FROM_DATABASE=YAPTV + +OUI:EC43E6* + ID_OUI_FROM_DATABASE=AWCER Ltd. + +OUI:EC43F6* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:EC4476* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:EC4644* + ID_OUI_FROM_DATABASE=TTK SAS + +OUI:EC4670* + ID_OUI_FROM_DATABASE=Meinberg Funkuhren GmbH & Co. KG + +OUI:EC473C* + ID_OUI_FROM_DATABASE=Redwire, LLC + +OUI:EC4993* + ID_OUI_FROM_DATABASE=Qihan Technology Co., Ltd + +OUI:EC4C4D* + ID_OUI_FROM_DATABASE=ZAO NPK RoTeK + +OUI:EC4D47* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:EC4F82* + ID_OUI_FROM_DATABASE=Calix Inc. + +OUI:EC51BC* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:EC52DC* + ID_OUI_FROM_DATABASE=WORLD MEDIA AND TECHNOLOGY Corp. + +OUI:EC542E* + ID_OUI_FROM_DATABASE=Shanghai XiMei Electronic Technology Co. Ltd + +OUI:EC55F9* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:EC5623* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:EC58EA* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:EC59E7* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:EC5A86* + ID_OUI_FROM_DATABASE=Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + +OUI:EC5B73* + ID_OUI_FROM_DATABASE=Advanced & Wise Technology Corp. + +OUI:EC5C68* + ID_OUI_FROM_DATABASE=CHONGQING FUGUI ELECTRONICS CO.,LTD. + +OUI:EC5C69* + ID_OUI_FROM_DATABASE=MITSUBISHI HEAVY INDUSTRIES MECHATRONICS SYSTEMS,LTD. + +OUI:EC5F23* + ID_OUI_FROM_DATABASE=Qinghai Kimascend Electronics Technology Co. Ltd. + +OUI:EC60E0* + ID_OUI_FROM_DATABASE=AVI-ON LABS + +OUI:EC6264* + ID_OUI_FROM_DATABASE=Global411 Internet Services, LLC + +OUI:EC63E5* + ID_OUI_FROM_DATABASE=ePBoard Design LLC + +OUI:EC64E7* + ID_OUI_FROM_DATABASE=MOCACARE Corporation + +OUI:EC65CC* + ID_OUI_FROM_DATABASE=Panasonic Automotive Systems Company of America + +OUI:EC66D1* + ID_OUI_FROM_DATABASE=B&W Group LTD + +OUI:EC6881* + ID_OUI_FROM_DATABASE=Palo Alto Networks + +OUI:EC6C9F* + ID_OUI_FROM_DATABASE=Chengdu Volans Technology CO.,LTD + +OUI:EC6F0B* + ID_OUI_FROM_DATABASE=FADU, Inc. + +OUI:EC7097* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:EC71DB* + ID_OUI_FROM_DATABASE=Shenzhen Baichuan Digital Technology Co., Ltd. + +OUI:EC74BA* + ID_OUI_FROM_DATABASE=Hirschmann Automation and Control GmbH + +OUI:EC7949* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:EC79F2* + ID_OUI_FROM_DATABASE=Startel + +OUI:EC7C74* + ID_OUI_FROM_DATABASE=Justone Technologies Co., Ltd. + +OUI:EC7D11* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:EC7D9D* + ID_OUI_FROM_DATABASE=CPI + +OUI:EC7FC6* + ID_OUI_FROM_DATABASE=ECCEL CORPORATION SAS + +OUI:EC8009* + ID_OUI_FROM_DATABASE=NovaSparks + +OUI:EC8193* + ID_OUI_FROM_DATABASE=Logitech, Inc + +OUI:EC8263* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:EC8350* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:EC836C* + ID_OUI_FROM_DATABASE=RM Tech Co., Ltd. + +OUI:EC83D5* + ID_OUI_FROM_DATABASE=GIRD Systems Inc + +OUI:EC84B4* + ID_OUI_FROM_DATABASE=CIG SHANGHAI CO LTD + +OUI:EC852F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:EC888F* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:EC8892* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:EC8914* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:EC89F5* + ID_OUI_FROM_DATABASE=Lenovo Mobile Communication Technology Ltd. + +OUI:EC8A4C* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:EC8AC7* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:EC8C9A* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:EC8CA2* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:EC8EAD* + ID_OUI_FROM_DATABASE=DLX + +OUI:EC8EAE* + ID_OUI_FROM_DATABASE=Nagravision SA + +OUI:EC8EB5* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:EC9233* + ID_OUI_FROM_DATABASE=Eddyfi NDT Inc + +OUI:EC9327* + ID_OUI_FROM_DATABASE=MEMMERT GmbH + Co. KG + +OUI:EC9365* + ID_OUI_FROM_DATABASE=Mapper.ai, Inc. + +OUI:EC93ED* + ID_OUI_FROM_DATABASE=DDoS-Guard LTD + +OUI:EC9681* + ID_OUI_FROM_DATABASE=2276427 Ontario Inc + +OUI:EC97B2* + ID_OUI_FROM_DATABASE=SUMEC Machinery & Electric Co.,Ltd. + +OUI:EC986C* + ID_OUI_FROM_DATABASE=Lufft Mess- und Regeltechnik GmbH + +OUI:EC98C1* + ID_OUI_FROM_DATABASE=Beijing Risbo Network Technology Co.,Ltd + +OUI:EC9A74* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:EC9B5B* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:EC9B8B* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:EC9BF3* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:EC9C32* + ID_OUI_FROM_DATABASE=Sichuan AI-Link Technology Co., Ltd. + +OUI:EC9ECD* + ID_OUI_FROM_DATABASE=Artesyn Embedded Technologies + +OUI:EC9F0D0* + ID_OUI_FROM_DATABASE=Hesai Photonics Technology Co., Ltd + +OUI:EC9F0D1* + ID_OUI_FROM_DATABASE=Simula Technology Inc. + +OUI:EC9F0D2* + ID_OUI_FROM_DATABASE=DRB Systems + +OUI:EC9F0D3* + ID_OUI_FROM_DATABASE=Waverly Labs Inc. + +OUI:EC9F0D4* + ID_OUI_FROM_DATABASE=WisIOE + +OUI:EC9F0D5* + ID_OUI_FROM_DATABASE=Paw-Taw-John Services, Inc. + +OUI:EC9F0D6* + ID_OUI_FROM_DATABASE=Shenzhen Compare Electronics Co., Ltd + +OUI:EC9F0D7* + ID_OUI_FROM_DATABASE=Bei jing Lian Shan times Techonology Co.Ltd + +OUI:EC9F0D8* + ID_OUI_FROM_DATABASE=Zhejiang HEJU Communication Technology Co., Ltd + +OUI:EC9F0D9* + ID_OUI_FROM_DATABASE=FCI + +OUI:EC9F0DA* + ID_OUI_FROM_DATABASE=flexlog GmbH + +OUI:EC9F0DB* + ID_OUI_FROM_DATABASE=CRRC QINGDAO SIFANG ROLLING STOCK RESEARCH INSTITUTE CO.,LTD + +OUI:EC9F0DC* + ID_OUI_FROM_DATABASE=Sarcos Corp + +OUI:EC9F0DD* + ID_OUI_FROM_DATABASE=SKS Control Oy + +OUI:EC9F0DE* + ID_OUI_FROM_DATABASE=MAX Technologies + +OUI:ECA29B* + ID_OUI_FROM_DATABASE=Kemppi Oy + +OUI:ECA5DE* + ID_OUI_FROM_DATABASE=ONYX WIFI Inc + +OUI:ECA86B* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:ECA940* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:ECA9FA* + ID_OUI_FROM_DATABASE=GUANGDONG GENIUS TECHNOLOGY CO., LTD. + +OUI:ECAA25* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:ECAAA0* + ID_OUI_FROM_DATABASE=PEGATRON CORPORATION + +OUI:ECADB8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:ECADE0* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:ECAF97* + ID_OUI_FROM_DATABASE=GIT + +OUI:ECB0E1* + ID_OUI_FROM_DATABASE=Ciena Corporation + +OUI:ECB106* + ID_OUI_FROM_DATABASE=Acuro Networks, Inc + +OUI:ECB1D7* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:ECB313* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:ECB541* + ID_OUI_FROM_DATABASE=SHINANO E and E Co.Ltd. + +OUI:ECB5FA* + ID_OUI_FROM_DATABASE=Philips Lighting BV + +OUI:ECB870* + ID_OUI_FROM_DATABASE=Beijing Heweinet Technology Co.,Ltd. + +OUI:ECB907* + ID_OUI_FROM_DATABASE=CloudGenix Inc + +OUI:ECBAFE* + ID_OUI_FROM_DATABASE=GIROPTIC + +OUI:ECBBAE* + ID_OUI_FROM_DATABASE=Digivoice Tecnologia em Eletronica Ltda + +OUI:ECBD09* + ID_OUI_FROM_DATABASE=FUSION Electronics Ltd + +OUI:ECBD1D* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:ECBEDD* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:ECC06A* + ID_OUI_FROM_DATABASE=PowerChord Group Limited + +OUI:ECC38A* + ID_OUI_FROM_DATABASE=Accuenergy (CANADA) Inc + +OUI:ECC40D* + ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd + +OUI:ECC57F* + ID_OUI_FROM_DATABASE=Suzhou Pairlink Network Technology + +OUI:ECC882* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:ECCB30* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:ECCD6D* + ID_OUI_FROM_DATABASE=Allied Telesis, Inc. + +OUI:ECCED7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:ECD00E* + ID_OUI_FROM_DATABASE=MiraeRecognition Co., Ltd. + +OUI:ECD040* + ID_OUI_FROM_DATABASE=GEA Farm Technologies GmbH + +OUI:ECD09F* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:ECD19A* + ID_OUI_FROM_DATABASE=Zhuhai Liming Industries Co., Ltd + +OUI:ECD68A* + ID_OUI_FROM_DATABASE=Shenzhen JMicron Intelligent Technology Developmen + +OUI:ECD925* + ID_OUI_FROM_DATABASE=RAMI + +OUI:ECD950* + ID_OUI_FROM_DATABASE=IRT SA + +OUI:ECD9D1* + ID_OUI_FROM_DATABASE=Shenzhen TG-NET Botone Technology Co.,Ltd. + +OUI:ECDE3D* + ID_OUI_FROM_DATABASE=Lamprey Networks, Inc. + +OUI:ECDF3A* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:ECE09B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:ECE154* + ID_OUI_FROM_DATABASE=Beijing Unisound Information Technology Co.,Ltd. + +OUI:ECE1A9* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:ECE2FD* + ID_OUI_FROM_DATABASE=SKG Electric Group(Thailand) Co., Ltd. + +OUI:ECE512* + ID_OUI_FROM_DATABASE=tado GmbH + +OUI:ECE555* + ID_OUI_FROM_DATABASE=Hirschmann Automation + +OUI:ECE744* + ID_OUI_FROM_DATABASE=Omntec mfg. inc + +OUI:ECE90B* + ID_OUI_FROM_DATABASE=SISTEMA SOLUCOES ELETRONICAS LTDA - EASYTECH + +OUI:ECE915* + ID_OUI_FROM_DATABASE=STI Ltd + +OUI:ECE9F8* + ID_OUI_FROM_DATABASE=Guang Zhou TRI-SUN Electronics Technology Co., Ltd + +OUI:ECEA03* + ID_OUI_FROM_DATABASE=DARFON LIGHTING CORP + +OUI:ECEBB8* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:ECEED8* + ID_OUI_FROM_DATABASE=ZTLX Network Technology Co.,Ltd + +OUI:ECF00E* + ID_OUI_FROM_DATABASE=AboCom + +OUI:ECF0FE* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:ECF236* + ID_OUI_FROM_DATABASE=NEOMONTANA ELECTRONICS + +OUI:ECF342* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:ECF35B* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:ECF451* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:ECF4BB* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:ECF6BD* + ID_OUI_FROM_DATABASE=SNCF MOBILITÉS + +OUI:ECF72B* + ID_OUI_FROM_DATABASE=HD DIGITAL TECH CO., LTD. + +OUI:ECF8EB* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:ECFA03* + ID_OUI_FROM_DATABASE=FCA + +OUI:ECFA5C* + ID_OUI_FROM_DATABASE=Beijing Xiaomi Electronics Co., Ltd. + +OUI:ECFAAA* + ID_OUI_FROM_DATABASE=The IMS Company + +OUI:ECFABC* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:ECFAF4* + ID_OUI_FROM_DATABASE=SenRa Tech Pvt. Ltd + +OUI:ECFC55* + ID_OUI_FROM_DATABASE=A. Eberle GmbH & Co. KG + +OUI:ECFE7E* + ID_OUI_FROM_DATABASE=BlueRadios, Inc. + +OUI:F0007F* + ID_OUI_FROM_DATABASE=Janz - Contadores de Energia, SA + +OUI:F0022B* + ID_OUI_FROM_DATABASE=Chrontel + +OUI:F00248* + ID_OUI_FROM_DATABASE=SmarteBuilding + +OUI:F0038C* + ID_OUI_FROM_DATABASE=AzureWave Technology Inc. + +OUI:F00786* + ID_OUI_FROM_DATABASE=Shandong Bittel Electronics Co., Ltd + +OUI:F008D1* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:F008F1* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F00D5C* + ID_OUI_FROM_DATABASE=JinQianMao Technology Co.,Ltd. + +OUI:F00DF5* + ID_OUI_FROM_DATABASE=ACOMA Medical Industry Co,. Ltd. + +OUI:F00E1D* + ID_OUI_FROM_DATABASE=Megafone Limited + +OUI:F00EBF* + ID_OUI_FROM_DATABASE=ZettaHash Inc. + +OUI:F00FEC* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F01090* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:F010AB* + ID_OUI_FROM_DATABASE=China Mobile (Hangzhou) Information Technology Co., Ltd. + +OUI:F013C3* + ID_OUI_FROM_DATABASE=SHENZHEN FENDA TECHNOLOGY CO., LTD + +OUI:F015A0* + ID_OUI_FROM_DATABASE=KyungDong One Co., Ltd. + +OUI:F015B9* + ID_OUI_FROM_DATABASE=PlayFusion Limited + +OUI:F0182B* + ID_OUI_FROM_DATABASE=LG Chem + +OUI:F01898* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F01B6C* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:F01C13* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:F01C2D* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:F01DBC* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:F01E34* + ID_OUI_FROM_DATABASE=ORICO Technologies Co., Ltd + +OUI:F01FAF* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:F0219D* + ID_OUI_FROM_DATABASE=Cal-Comp Electronics & Communications Company Ltd. + +OUI:F0224E* + ID_OUI_FROM_DATABASE=Esan electronic co. + +OUI:F02329* + ID_OUI_FROM_DATABASE=SHOWA DENKI CO.,LTD. + +OUI:F023B90* + ID_OUI_FROM_DATABASE=Aquametro AG + +OUI:F023B91* + ID_OUI_FROM_DATABASE=Ubiant + +OUI:F023B92* + ID_OUI_FROM_DATABASE=Raysgem Electronics and Technology Co.Ltd + +OUI:F023B93* + ID_OUI_FROM_DATABASE=BSP RUS Ltd. + +OUI:F023B94* + ID_OUI_FROM_DATABASE=EZVIS LIMITED + +OUI:F023B95* + ID_OUI_FROM_DATABASE=Audeara Pty. Ltd. + +OUI:F023B96* + ID_OUI_FROM_DATABASE=Xiamen Jinhaode Electronic Co.,Ltd + +OUI:F023B97* + ID_OUI_FROM_DATABASE=Transcend Building Automation control network corporation + +OUI:F023B98* + ID_OUI_FROM_DATABASE=G3 TECHNOLOGIES< INC + +OUI:F023B99* + ID_OUI_FROM_DATABASE=Emu Technology + +OUI:F023B9A* + ID_OUI_FROM_DATABASE=Annapurna labs + +OUI:F023B9B* + ID_OUI_FROM_DATABASE=Q Core Medical Ltd + +OUI:F023B9C* + ID_OUI_FROM_DATABASE=Shenzhen Lachesis Mhealth Co., Ltd. + +OUI:F023B9D* + ID_OUI_FROM_DATABASE=Private + +OUI:F023B9E* + ID_OUI_FROM_DATABASE=Domotz Ltd + +OUI:F02405* + ID_OUI_FROM_DATABASE=OPUS High Technology Corporation + +OUI:F02408* + ID_OUI_FROM_DATABASE=Talaris (Sweden) AB + +OUI:F02475* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F02572* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F025B7* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:F02624* + ID_OUI_FROM_DATABASE=WAFA TECHNOLOGIES CO., LTD. + +OUI:F0264C* + ID_OUI_FROM_DATABASE=Sigrist-Photometer AG + +OUI:F0272D* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:F02745* + ID_OUI_FROM_DATABASE=F-Secure Corporation + +OUI:F02765* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:F02929* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F02A23* + ID_OUI_FROM_DATABASE=Creative Next Design + +OUI:F02A61* + ID_OUI_FROM_DATABASE=Waldo Networks, Inc. + +OUI:F02FA7* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F02FD8* + ID_OUI_FROM_DATABASE=Bi2-Vision + +OUI:F0321A* + ID_OUI_FROM_DATABASE=Mita-Teknik A/S + +OUI:F033E5* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F03404* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:F037A1* + ID_OUI_FROM_DATABASE=Huike Electronics (SHENZHEN) CO., LTD. + +OUI:F03A4B* + ID_OUI_FROM_DATABASE=Bloombase, Inc. + +OUI:F03A55* + ID_OUI_FROM_DATABASE=Omega Elektronik AS + +OUI:F03D03* + ID_OUI_FROM_DATABASE=TECNO MOBILE LIMITED + +OUI:F03D29* + ID_OUI_FROM_DATABASE=Actility + +OUI:F03E90* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:F03EBF* + ID_OUI_FROM_DATABASE=GOGORO TAIWAN LIMITED + +OUI:F03F95* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F03FF8* + ID_OUI_FROM_DATABASE=R L Drake + +OUI:F0407B* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:F041C80* + ID_OUI_FROM_DATABASE=LINPA ACOUSTIC TECHNOLOGY CO.,LTD + +OUI:F041C81* + ID_OUI_FROM_DATABASE=DongGuan Siyoto Electronics Co., Ltd + +OUI:F041C82* + ID_OUI_FROM_DATABASE=Shenzhen Medica Technology Development Co., Ltd. + +OUI:F041C83* + ID_OUI_FROM_DATABASE=SHENZHEN WISEWING INTERNET TECHNOLOGY CO.,LTD + +OUI:F041C84* + ID_OUI_FROM_DATABASE=Candelic Limited + +OUI:F041C85* + ID_OUI_FROM_DATABASE=XI'AN MEI SHANG MEI WIRELESS TECHNOLOGY.Co., Ltd. + +OUI:F041C86* + ID_OUI_FROM_DATABASE=AED Engineering GmbH + +OUI:F041C87* + ID_OUI_FROM_DATABASE=Nanchang BlackShark Co.,Ltd. + +OUI:F041C88* + ID_OUI_FROM_DATABASE=POSTIUM KOREA CO., LTD. + +OUI:F041C89* + ID_OUI_FROM_DATABASE=Shenzhen Nufilo Electronic Technology Co., Ltd. + +OUI:F041C8A* + ID_OUI_FROM_DATABASE=Telstra + +OUI:F041C8B* + ID_OUI_FROM_DATABASE=Powervault Ltd + +OUI:F041C8C* + ID_OUI_FROM_DATABASE=Shanghai Think-Force Electronic Technology Co. Ltd + +OUI:F041C8D* + ID_OUI_FROM_DATABASE=ATN Media Group FZ LLC + +OUI:F041C8E* + ID_OUI_FROM_DATABASE=Shenzhen Umind Technology Co., Ltd. + +OUI:F0421C* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F04335* + ID_OUI_FROM_DATABASE=DVN(Shanghai)Ltd. + +OUI:F04347* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F045DA* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F0463B* + ID_OUI_FROM_DATABASE=Comcast Cable Corporation + +OUI:F04A2B* + ID_OUI_FROM_DATABASE=PYRAMID Computer GmbH + +OUI:F04B3A* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:F04B6A* + ID_OUI_FROM_DATABASE=Scientific Production Association Siberian Arsenal, Ltd. + +OUI:F04BF2* + ID_OUI_FROM_DATABASE=JTECH Communications, Inc. + +OUI:F04CD5* + ID_OUI_FROM_DATABASE=Maxlinear, Inc + +OUI:F04DA2* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:F04F7C* + ID_OUI_FROM_DATABASE=Private + +OUI:F05136* + ID_OUI_FROM_DATABASE=TCT mobile ltd + +OUI:F051EA* + ID_OUI_FROM_DATABASE=Fitbit, Inc. + +OUI:F05494* + ID_OUI_FROM_DATABASE=Honeywell Connected Building + +OUI:F05849* + ID_OUI_FROM_DATABASE=CareView Communications + +OUI:F05A09* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F05B7B* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F05C19* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:F05C77* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:F05CD5* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F05D89* + ID_OUI_FROM_DATABASE=Dycon Limited + +OUI:F05DC8* + ID_OUI_FROM_DATABASE=Duracell Powermat + +OUI:F05F5A* + ID_OUI_FROM_DATABASE=Getriebebau NORD GmbH and Co. KG + +OUI:F06130* + ID_OUI_FROM_DATABASE=Advantage Pharmacy Services, LLC + +OUI:F0620D* + ID_OUI_FROM_DATABASE=Shenzhen Egreat Tech Corp.,Ltd + +OUI:F06281* + ID_OUI_FROM_DATABASE=ProCurve Networking by HP + +OUI:F063F9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F065C2* + ID_OUI_FROM_DATABASE=Yanfeng Visteon Electronics Technology (Shanghai) Co.,Ltd. + +OUI:F065DD* + ID_OUI_FROM_DATABASE=Primax Electronics Ltd. + +OUI:F06728* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:F06853* + ID_OUI_FROM_DATABASE=Integrated Corporation + +OUI:F06865* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:F06BCA* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F06D78* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:F06E0B* + ID_OUI_FROM_DATABASE=Microsoft Corporation + +OUI:F06E32* + ID_OUI_FROM_DATABASE=MICROTEL INNOVATION S.R.L. + +OUI:F0728C* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F072EA* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:F073AE* + ID_OUI_FROM_DATABASE=PEAK-System Technik + +OUI:F07485* + ID_OUI_FROM_DATABASE=NGD Systems, Inc. + +OUI:F074E4* + ID_OUI_FROM_DATABASE=Thundercomm Technology Co., Ltd + +OUI:F0761C* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:F0766F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F07765* + ID_OUI_FROM_DATABASE=Sourcefire, Inc + +OUI:F077D0* + ID_OUI_FROM_DATABASE=Xcellen + +OUI:F07807* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F07816* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F07959* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:F07960* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F079E8* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:F07BCB* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:F07CC7* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:F07D68* + ID_OUI_FROM_DATABASE=D-Link Corporation + +OUI:F07F06* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F07F0C* + ID_OUI_FROM_DATABASE=Leopold Kostal GmbH &Co. KG + +OUI:F08173* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:F08175* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:F081AF* + ID_OUI_FROM_DATABASE=IRZ AUTOMATION TECHNOLOGIES LTD + +OUI:F08261* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:F0842F* + ID_OUI_FROM_DATABASE=ADB Broadband Italia + +OUI:F084C9* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:F085C1* + ID_OUI_FROM_DATABASE=SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + +OUI:F08620* + ID_OUI_FROM_DATABASE=Arcadyan Corporation + +OUI:F08A28* + ID_OUI_FROM_DATABASE=JIANGSU HENGSION ELECTRONIC S and T CO.,LTD + +OUI:F08A76* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F08BFE* + ID_OUI_FROM_DATABASE=COSTEL.,CO.LTD + +OUI:F08CFB* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:F08EDB* + ID_OUI_FROM_DATABASE=VeloCloud Networks + +OUI:F0921C* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:F092B4* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO., LTD + +OUI:F0933A* + ID_OUI_FROM_DATABASE=NxtConect + +OUI:F093C5* + ID_OUI_FROM_DATABASE=Garland Technology + +OUI:F095F1* + ID_OUI_FROM_DATABASE=Carl Zeiss AG + +OUI:F097E5* + ID_OUI_FROM_DATABASE=TAMIO, INC + +OUI:F09838* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F0989D* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F09919* + ID_OUI_FROM_DATABASE=Garmin International + +OUI:F099B6* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F099BF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F09A51* + ID_OUI_FROM_DATABASE=Shanghai Viroyal Electronic Technology Company Limited + +OUI:F09CBB* + ID_OUI_FROM_DATABASE=RaonThink Inc. + +OUI:F09CD7* + ID_OUI_FROM_DATABASE=Guangzhou Blue Cheetah Intelligent Technology Co., Ltd. + +OUI:F09CE9* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:F09E63* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F09FC2* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:F09FFC* + ID_OUI_FROM_DATABASE=SHARP Corporation + +OUI:F0A225* + ID_OUI_FROM_DATABASE=Private + +OUI:F0A35A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0A764* + ID_OUI_FROM_DATABASE=GST Co., Ltd. + +OUI:F0A7B2* + ID_OUI_FROM_DATABASE=FUTABA CORPORATION + +OUI:F0A968* + ID_OUI_FROM_DATABASE=Antailiye Technology Co.,Ltd + +OUI:F0AB54* + ID_OUI_FROM_DATABASE=MITSUMI ELECTRIC CO.,LTD. + +OUI:F0ACA4* + ID_OUI_FROM_DATABASE=HBC-radiomatic + +OUI:F0ACD70* + ID_OUI_FROM_DATABASE=Guilin glsun Science and Tech Co.,LTD + +OUI:F0ACD71* + ID_OUI_FROM_DATABASE=Intenta GmbH + +OUI:F0ACD72* + ID_OUI_FROM_DATABASE=QUANTUM POWER SYSTEMS + +OUI:F0ACD73* + ID_OUI_FROM_DATABASE=Med-Pat/Inn-Phone + +OUI:F0ACD74* + ID_OUI_FROM_DATABASE=Sercomm Corporation. + +OUI:F0ACD75* + ID_OUI_FROM_DATABASE=PAVO TASARIM URETIM TICARET A.S. + +OUI:F0ACD76* + ID_OUI_FROM_DATABASE=Suzhou Pairlink Network Technology + +OUI:F0ACD77* + ID_OUI_FROM_DATABASE=Hanju Network Technologies Co. + +OUI:F0ACD78* + ID_OUI_FROM_DATABASE=Telefonix Incorporated + +OUI:F0ACD79* + ID_OUI_FROM_DATABASE=U3storage Technologies Co., Ltd + +OUI:F0ACD7A* + ID_OUI_FROM_DATABASE=Groupeer Technologies + +OUI:F0ACD7B* + ID_OUI_FROM_DATABASE=Zhejiang Makepower Electronics,Inc. + +OUI:F0ACD7C* + ID_OUI_FROM_DATABASE=Simprints Technology Ltd + +OUI:F0ACD7D* + ID_OUI_FROM_DATABASE=Smart Power Technology Co., Ltd. + +OUI:F0ACD7E* + ID_OUI_FROM_DATABASE=Fiziico Co., Ltd. + +OUI:F0AD4E* + ID_OUI_FROM_DATABASE=Globalscale Technologies, Inc. + +OUI:F0AE51* + ID_OUI_FROM_DATABASE=Xi3 Corp + +OUI:F0AF50* + ID_OUI_FROM_DATABASE=Phantom Intelligence + +OUI:F0AF85* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F0B014* + ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH + +OUI:F0B052* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:F0B0E7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0B107* + ID_OUI_FROM_DATABASE=Ericsson AB + +OUI:F0B2E5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F0B31E* + ID_OUI_FROM_DATABASE=Universal Electronics, Inc. + +OUI:F0B429* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:F0B479* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0B4D2* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:F0B5B7* + ID_OUI_FROM_DATABASE=Disruptive Technologies Research AS + +OUI:F0B5D1* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F0B6EB* + ID_OUI_FROM_DATABASE=Poslab Technology Co., Ltd. + +OUI:F0B968* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:F0BCC8* + ID_OUI_FROM_DATABASE=MaxID (Pty) Ltd + +OUI:F0BCC9* + ID_OUI_FROM_DATABASE=PFU LIMITED + +OUI:F0BD2E* + ID_OUI_FROM_DATABASE=H+S Polatis Ltd + +OUI:F0BDF1* + ID_OUI_FROM_DATABASE=Sipod Inc. + +OUI:F0BF97* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:F0C1F1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0C24C* + ID_OUI_FROM_DATABASE=Zhejiang FeiYue Digital Technology Co., Ltd + +OUI:F0C27C* + ID_OUI_FROM_DATABASE=Mianyang Netop Telecom Equipment Co.,Ltd. + +OUI:F0C371* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0C42F* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:F0C77F* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F0C850* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F0C88C* + ID_OUI_FROM_DATABASE=LeddarTech Inc. + +OUI:F0C9D1* + ID_OUI_FROM_DATABASE=GD Midea Air-Conditioning Equipment Co.,Ltd. + +OUI:F0CBA1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0D14F* + ID_OUI_FROM_DATABASE=LINEAR LLC + +OUI:F0D1A9* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0D1B8* + ID_OUI_FROM_DATABASE=LEDVANCE + +OUI:F0D2F1* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:F0D3A7* + ID_OUI_FROM_DATABASE=CobaltRay Co., Ltd + +OUI:F0D3E7* + ID_OUI_FROM_DATABASE=Sensometrix SA + +OUI:F0D4E2* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:F0D4F6* + ID_OUI_FROM_DATABASE=Lars Thrane A/S + +OUI:F0D4F7* + ID_OUI_FROM_DATABASE=varram system + +OUI:F0D5BF* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F0D657* + ID_OUI_FROM_DATABASE=ECHOSENS + +OUI:F0D767* + ID_OUI_FROM_DATABASE=Axema Passagekontroll AB + +OUI:F0D7AA* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:F0D7DC* + ID_OUI_FROM_DATABASE=Wesine (Wuhan) Technology Co., Ltd. + +OUI:F0D9B2* + ID_OUI_FROM_DATABASE=EXO S.A. + +OUI:F0DA7C* + ID_OUI_FROM_DATABASE=RLH INDUSTRIES,INC. + +OUI:F0DB30* + ID_OUI_FROM_DATABASE=Yottabyte + +OUI:F0DBE2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0DBF8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0DCE2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0DE71* + ID_OUI_FROM_DATABASE=Shanghai EDO Technologies Co.,Ltd. + +OUI:F0DEB9* + ID_OUI_FROM_DATABASE=ShangHai Y&Y Electronics Co., Ltd + +OUI:F0DEF1* + ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation + +OUI:F0E3DC* + ID_OUI_FROM_DATABASE=Tecon MT, LLC + +OUI:F0E4A2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F0E5C3* + ID_OUI_FROM_DATABASE=Drägerwerk AG & Co. KG aA + +OUI:F0E77E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F0EBD0* + ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd. + +OUI:F0EC39* + ID_OUI_FROM_DATABASE=Essec + +OUI:F0ED1E* + ID_OUI_FROM_DATABASE=Bilkon Bilgisayar Kontrollu Cih. Im.Ltd. + +OUI:F0EE10* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F0EE58* + ID_OUI_FROM_DATABASE=PACE Telematics GmbH + +OUI:F0EEBB* + ID_OUI_FROM_DATABASE=VIPAR GmbH + +OUI:F0EF86* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:F0EFD2* + ID_OUI_FROM_DATABASE=TF PAYMENT SERVICE CO., LTD + +OUI:F0F002* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:F0F08F* + ID_OUI_FROM_DATABASE=Nextek Solutions Pte Ltd + +OUI:F0F0A4* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:F0F249* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:F0F260* + ID_OUI_FROM_DATABASE=Mobitec AB + +OUI:F0F336* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:F0F5AE* + ID_OUI_FROM_DATABASE=Adaptrum Inc. + +OUI:F0F61C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F0F644* + ID_OUI_FROM_DATABASE=Whitesky Science & Technology Co.,Ltd. + +OUI:F0F669* + ID_OUI_FROM_DATABASE=Motion Analysis Corporation + +OUI:F0F6C1* + ID_OUI_FROM_DATABASE=Sonos, Inc. + +OUI:F0F755* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F0F7B3* + ID_OUI_FROM_DATABASE=Phorm + +OUI:F0F842* + ID_OUI_FROM_DATABASE=KEEBOX, Inc. + +OUI:F0F8F2* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F0F9F7* + ID_OUI_FROM_DATABASE=IES GmbH & Co. KG + +OUI:F0FCC8* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F0FDA0* + ID_OUI_FROM_DATABASE=Acurix Networks Pty Ltd + +OUI:F0FE6B* + ID_OUI_FROM_DATABASE=Shanghai High-Flying Electronics Technology Co., Ltd + +OUI:F40270* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:F40304* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:F40321* + ID_OUI_FROM_DATABASE=BeNeXt B.V. + +OUI:F4032A* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:F4032F* + ID_OUI_FROM_DATABASE=Reduxio Systems + +OUI:F40343* + ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise + +OUI:F4044C* + ID_OUI_FROM_DATABASE=ValenceTech Limited + +OUI:F40616* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F40669* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F4068D* + ID_OUI_FROM_DATABASE=devolo AG + +OUI:F406A5* + ID_OUI_FROM_DATABASE=Hangzhou Bianfeng Networking Technology Co., Ltd. + +OUI:F409D8* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:F40A4A* + ID_OUI_FROM_DATABASE=INDUSNET Communication Technology Co.,LTD + +OUI:F40B93* + ID_OUI_FROM_DATABASE=BlackBerry RTS + +OUI:F40E01* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F40E110* + ID_OUI_FROM_DATABASE=realphone technology co.,ltd + +OUI:F40E111* + ID_OUI_FROM_DATABASE=BEIJING DONGJIN AERO-TECH CO., LTD + +OUI:F40E112* + ID_OUI_FROM_DATABASE=Axel srl + +OUI:F40E113* + ID_OUI_FROM_DATABASE=Shenzhen headsun technology + +OUI:F40E114* + ID_OUI_FROM_DATABASE=Dayang Technology Development Inc. + +OUI:F40E115* + ID_OUI_FROM_DATABASE=E-SONG + +OUI:F40E116* + ID_OUI_FROM_DATABASE=Alpha Design Technologies Pvt Ltd + +OUI:F40E117* + ID_OUI_FROM_DATABASE=Shenzhen Grandsun Electronic Co.,Ltd. + +OUI:F40E118* + ID_OUI_FROM_DATABASE=Zeepro Inc. + +OUI:F40E119* + ID_OUI_FROM_DATABASE=Sterna Security + +OUI:F40E11A* + ID_OUI_FROM_DATABASE=Kodpro Ltd. + +OUI:F40E11B* + ID_OUI_FROM_DATABASE=BRADAR INDUSTRIA SA + +OUI:F40E11C* + ID_OUI_FROM_DATABASE=NIHON MEGA LOGIC CO.,LTD. + +OUI:F40E11D* + ID_OUI_FROM_DATABASE=DXG Technology Corp. + +OUI:F40E11E* + ID_OUI_FROM_DATABASE=Elektronika Naglic d.o.o. + +OUI:F40E11F* + ID_OUI_FROM_DATABASE=Private + +OUI:F40E22* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F40E83* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F40F1B* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F40F24* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F40F9B* + ID_OUI_FROM_DATABASE=WAVELINK + +OUI:F41535* + ID_OUI_FROM_DATABASE=SPON Communication Technology Co.,Ltd + +OUI:F41563* + ID_OUI_FROM_DATABASE=F5 Networks, Inc. + +OUI:F415FD* + ID_OUI_FROM_DATABASE=Shanghai Pateo Electronic Equipment Manufacturing Co., Ltd. + +OUI:F417B8* + ID_OUI_FROM_DATABASE=AirTies Wireless Networks + +OUI:F419E2* + ID_OUI_FROM_DATABASE=Volterra + +OUI:F41BA1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F41C95* + ID_OUI_FROM_DATABASE=BEIJING YUNYI TIMES TECHNOLOGY CO,.LTD + +OUI:F41D6B* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F41E26* + ID_OUI_FROM_DATABASE=Simon-Kaloi Engineering + +OUI:F41E5E* + ID_OUI_FROM_DATABASE=RtBrick Inc. + +OUI:F41F0B* + ID_OUI_FROM_DATABASE=YAMABISHI Corporation + +OUI:F41F88* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:F41FC2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F42012* + ID_OUI_FROM_DATABASE=Cuciniale GmbH + +OUI:F42833* + ID_OUI_FROM_DATABASE=MMPC Inc. + +OUI:F42853* + ID_OUI_FROM_DATABASE=Zioncom Electronics (Shenzhen) Ltd. + +OUI:F42896* + ID_OUI_FROM_DATABASE=SPECTO PAINEIS ELETRONICOS LTDA + +OUI:F42981* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:F42B48* + ID_OUI_FROM_DATABASE=Ubiqam + +OUI:F42C56* + ID_OUI_FROM_DATABASE=SENOR TECH CO LTD + +OUI:F42E7F* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:F430B9* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:F431C3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F4323D* + ID_OUI_FROM_DATABASE=Sichuan tianyi kanghe communications co., LTD + +OUI:F43328* + ID_OUI_FROM_DATABASE=CIMCON Lighting Inc. + +OUI:F436E1* + ID_OUI_FROM_DATABASE=Abilis Systems SARL + +OUI:F437B7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F43814* + ID_OUI_FROM_DATABASE=Shanghai Howell Electronic Co.,Ltd + +OUI:F43909* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:F43D80* + ID_OUI_FROM_DATABASE=FAG Industrial Services GmbH + +OUI:F43E61* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:F43E66* + ID_OUI_FROM_DATABASE=Bee Computing (HK) Limited + +OUI:F43E9D* + ID_OUI_FROM_DATABASE=Benu Networks, Inc. + +OUI:F44156* + ID_OUI_FROM_DATABASE=Arrikto Inc. + +OUI:F44227* + ID_OUI_FROM_DATABASE=S & S Research Inc. + +OUI:F4428F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F44450* + ID_OUI_FROM_DATABASE=BND Co., Ltd. + +OUI:F445ED* + ID_OUI_FROM_DATABASE=Portable Innovation Technology Ltd. + +OUI:F44713* + ID_OUI_FROM_DATABASE=Leading Public Performance Co., Ltd. + +OUI:F4472A* + ID_OUI_FROM_DATABASE=Nanjing Rousing Sci. and Tech. Industrial Co., Ltd + +OUI:F44848* + ID_OUI_FROM_DATABASE=Amscreen Group Ltd + +OUI:F44955* + ID_OUI_FROM_DATABASE=MIMO TECH Co., Ltd. + +OUI:F449EF* + ID_OUI_FROM_DATABASE=EMSTONE + +OUI:F44B2A* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:F44C70* + ID_OUI_FROM_DATABASE=Skyworth Digital Technology(Shenzhen) Co.,Ltd + +OUI:F44C7F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F44D17* + ID_OUI_FROM_DATABASE=GOLDCARD HIGH-TECH CO.,LTD. + +OUI:F44D30* + ID_OUI_FROM_DATABASE=Elitegroup Computer Systems Co.,Ltd. + +OUI:F44E05* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F44EFD* + ID_OUI_FROM_DATABASE=Actions Semiconductor Co.,Ltd.(Cayman Islands) + +OUI:F450EB* + ID_OUI_FROM_DATABASE=Telechips Inc + +OUI:F45214* + ID_OUI_FROM_DATABASE=Mellanox Technologies, Inc. + +OUI:F45433* + ID_OUI_FROM_DATABASE=Rockwell Automation + +OUI:F45595* + ID_OUI_FROM_DATABASE=HENGBAO Corporation LTD. + +OUI:F4559C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F455E0* + ID_OUI_FROM_DATABASE=Niceway CNC Technology Co.,Ltd.Hunan Province + +OUI:F4573E* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:F45842* + ID_OUI_FROM_DATABASE=Boxx TV Ltd + +OUI:F45B73* + ID_OUI_FROM_DATABASE=Wanjiaan Interconnected Technology Co., Ltd + +OUI:F45C89* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F45EAB* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F45F69* + ID_OUI_FROM_DATABASE=Matsufu Electronics distribution Company + +OUI:F45FD4* + ID_OUI_FROM_DATABASE=Cisco SPVTG + +OUI:F45FF7* + ID_OUI_FROM_DATABASE=DQ Technology Inc. + +OUI:F4600D* + ID_OUI_FROM_DATABASE=Panoptic Technology, Inc + +OUI:F460E2* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:F462D0* + ID_OUI_FROM_DATABASE=Not for Radio, LLC + +OUI:F4631F* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F46349* + ID_OUI_FROM_DATABASE=Diffon Corporation + +OUI:F4645D* + ID_OUI_FROM_DATABASE=Toshiba + +OUI:F4672D* + ID_OUI_FROM_DATABASE=ShenZhen Topstar Technology Company + +OUI:F46A92* + ID_OUI_FROM_DATABASE=SHENZHEN FAST TECHNOLOGIES CO.,LTD + +OUI:F46ABC* + ID_OUI_FROM_DATABASE=Adonit Corp. Ltd. + +OUI:F46BEF* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:F46D04* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:F46DE2* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:F46E24* + ID_OUI_FROM_DATABASE=NEC Personal Computers, Ltd. + +OUI:F46E95* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:F46F4E* + ID_OUI_FROM_DATABASE=Echowell + +OUI:F470AB* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:F47190* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F47335* + ID_OUI_FROM_DATABASE=Logitech Far East + +OUI:F473CA* + ID_OUI_FROM_DATABASE=Conversion Sound Inc. + +OUI:F47488* + ID_OUI_FROM_DATABASE=New H3C Technologies Co., Ltd + +OUI:F47626* + ID_OUI_FROM_DATABASE=Viltechmeda UAB + +OUI:F47960* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F47A4E* + ID_OUI_FROM_DATABASE=Woojeon&Handan + +OUI:F47ACC* + ID_OUI_FROM_DATABASE=SolidFire, Inc. + +OUI:F47B5E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F47DEF* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F47F35* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F48139* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:F483CD* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:F483E1* + ID_OUI_FROM_DATABASE=Shanghai Clouder Semiconductor Co.,Ltd + +OUI:F4844C* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F485C6* + ID_OUI_FROM_DATABASE=FDT Technologies + +OUI:F48771* + ID_OUI_FROM_DATABASE=Infoblox + +OUI:F48B32* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:F48C50* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F48CEB* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:F48E09* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:F48E38* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:F48E92* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F490CA* + ID_OUI_FROM_DATABASE=Tensorcom + +OUI:F490CB3* + ID_OUI_FROM_DATABASE=Ricker Lyman Robotic + +OUI:F490CB4* + ID_OUI_FROM_DATABASE=OmniNet + +OUI:F490CB5* + ID_OUI_FROM_DATABASE=Avilution + +OUI:F490CB6* + ID_OUI_FROM_DATABASE=Airbeam Wireless Technologies Inc. + +OUI:F490CB7* + ID_OUI_FROM_DATABASE=TEQ SA + +OUI:F490CBB* + ID_OUI_FROM_DATABASE=A-dec Inc. + +OUI:F490CBC* + ID_OUI_FROM_DATABASE=Cheetah Medical + +OUI:F490CBD* + ID_OUI_FROM_DATABASE=Simavita (Aust) Pty Ltd + +OUI:F490EA* + ID_OUI_FROM_DATABASE=Deciso B.V. + +OUI:F4911E* + ID_OUI_FROM_DATABASE=ZHUHAI EWPE INFORMATION TECHNOLOGY INC + +OUI:F492BF* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:F4939F* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co., Ltd. + +OUI:F49461* + ID_OUI_FROM_DATABASE=NexGen Storage + +OUI:F49466* + ID_OUI_FROM_DATABASE=CountMax, ltd + +OUI:F4951B* + ID_OUI_FROM_DATABASE=Hefei Radio Communication Technology Co., Ltd + +OUI:F49634* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F49651* + ID_OUI_FROM_DATABASE=NAKAYO Inc + +OUI:F497C2* + ID_OUI_FROM_DATABASE=Nebulon Inc + +OUI:F499AC* + ID_OUI_FROM_DATABASE=WEBER Schraubautomaten GmbH + +OUI:F49C12* + ID_OUI_FROM_DATABASE=Structab AB + +OUI:F49EEF* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:F49F54* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F49FF3* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F4A294* + ID_OUI_FROM_DATABASE=EAGLE WORLD DEVELOPMENT CO., LIMITED + +OUI:F4A4D6* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F4A52A* + ID_OUI_FROM_DATABASE=Hawa Technologies Inc + +OUI:F4A59D* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:F4A739* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:F4A997* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:F4ACC1* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F4AFE7* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F4B164* + ID_OUI_FROM_DATABASE=Lightning Telecommunications Technology Co. Ltd + +OUI:F4B381* + ID_OUI_FROM_DATABASE=WindowMaster A/S + +OUI:F4B520* + ID_OUI_FROM_DATABASE=Biostar Microtech international corp. + +OUI:F4B52F* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:F4B549* + ID_OUI_FROM_DATABASE=Xiamen Yeastar Information Technology Co., Ltd. + +OUI:F4B5AA* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:F4B5BB* + ID_OUI_FROM_DATABASE=CERAGON NETWORKS + +OUI:F4B688* + ID_OUI_FROM_DATABASE=PLANTRONICS, INC. + +OUI:F4B6E5* + ID_OUI_FROM_DATABASE=TerraSem Co.,Ltd + +OUI:F4B72A* + ID_OUI_FROM_DATABASE=TIME INTERCONNECT LTD + +OUI:F4B78D* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F4B7B3* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:F4B7E2* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:F4B85E* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F4B8A7* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:F4BC97* + ID_OUI_FROM_DATABASE=Shenzhen Crave Communication Co., LTD + +OUI:F4BCDA* + ID_OUI_FROM_DATABASE=Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + +OUI:F4BD7C* + ID_OUI_FROM_DATABASE=Chengdu jinshi communication Co., LTD + +OUI:F4BD9E* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F4BF80* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F4C248* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F4C447* + ID_OUI_FROM_DATABASE=Coagent International Enterprise Limited + +OUI:F4C4D6* + ID_OUI_FROM_DATABASE=Shenzhen Xinfa Electronic Co.,ltd + +OUI:F4C613* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Shanghai Bell Co., Ltd + +OUI:F4C6D7* + ID_OUI_FROM_DATABASE=blackned GmbH + +OUI:F4C714* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F4C795* + ID_OUI_FROM_DATABASE=WEY Elektronik AG + +OUI:F4C7C8* + ID_OUI_FROM_DATABASE=Kelvin Inc. + +OUI:F4CA24* + ID_OUI_FROM_DATABASE=FreeBit Co., Ltd. + +OUI:F4CAE5* + ID_OUI_FROM_DATABASE=FREEBOX SAS + +OUI:F4CB52* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F4CC55* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:F4CD90* + ID_OUI_FROM_DATABASE=Vispiron Rotec GmbH + +OUI:F4CE36* + ID_OUI_FROM_DATABASE=Nordic Semiconductor ASA + +OUI:F4CE46* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:F4CFA2* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:F4CFE2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F4D032* + ID_OUI_FROM_DATABASE=Yunnan Ideal Information&Technology.,Ltd + +OUI:F4D108* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F4D261* + ID_OUI_FROM_DATABASE=SEMOCON Co., Ltd + +OUI:F4D620* + ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + +OUI:F4D7B2* + ID_OUI_FROM_DATABASE=LGS Innovations, LLC + +OUI:F4D9C6* + ID_OUI_FROM_DATABASE=UNIONMAN TECHNOLOGY CO.,LTD + +OUI:F4D9FB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F4DBE3* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F4DBE6* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F4DC41* + ID_OUI_FROM_DATABASE=YOUNGZONE CULTURE (SHANGHAI) CORP + +OUI:F4DC4D* + ID_OUI_FROM_DATABASE=Beijing CCD Digital Technology Co., Ltd + +OUI:F4DCA5* + ID_OUI_FROM_DATABASE=DAWON DNS + +OUI:F4DCDA* + ID_OUI_FROM_DATABASE=Zhuhai Jiahe Communication Technology Co., limited + +OUI:F4DCF9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F4DD9E* + ID_OUI_FROM_DATABASE=GoPro + +OUI:F4DE0C* + ID_OUI_FROM_DATABASE=ESPOD Ltd. + +OUI:F4DEAF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F4E11E* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F4E142* + ID_OUI_FROM_DATABASE=Delta Elektronika BV + +OUI:F4E204* + ID_OUI_FROM_DATABASE=Traqueur + +OUI:F4E3FB* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F4E4AD* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:F4E5F2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F4E6D7* + ID_OUI_FROM_DATABASE=Solar Power Technologies, Inc. + +OUI:F4E926* + ID_OUI_FROM_DATABASE=Tianjin Zanpu Technology Inc. + +OUI:F4E9D4* + ID_OUI_FROM_DATABASE=QLogic Corporation + +OUI:F4EA67* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F4EAB5* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:F4EB38* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:F4EC38* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:F4ED5F* + ID_OUI_FROM_DATABASE=SHENZHEN KTC TECHNOLOGY GROUP + +OUI:F4EE14* + ID_OUI_FROM_DATABASE=MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + +OUI:F4EF9E* + ID_OUI_FROM_DATABASE=SGSG SCIENCE & TECHNOLOGY CO. LTD + +OUI:F4F15A* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F4F197* + ID_OUI_FROM_DATABASE=EMTAKE Inc + +OUI:F4F1E1* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:F4F26D* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:F4F3AA* + ID_OUI_FROM_DATABASE=JBL GmbH & Co. KG + +OUI:F4F524* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:F4F5A5* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:F4F5D8* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:F4F5DB* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:F4F5E8* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:F4F646* + ID_OUI_FROM_DATABASE=Dediprog Technology Co. Ltd. + +OUI:F4F951* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F4FC32* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F4FCB1* + ID_OUI_FROM_DATABASE=JJ Corp + +OUI:F4FD2B* + ID_OUI_FROM_DATABASE=ZOYI Company + +OUI:F4FEFB* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F80113* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F802780* + ID_OUI_FROM_DATABASE=Digatron Power Electronics GmbH + +OUI:F802781* + ID_OUI_FROM_DATABASE=Reason Tecnologia SA + +OUI:F802782* + ID_OUI_FROM_DATABASE=Innodisk + +OUI:F802783* + ID_OUI_FROM_DATABASE=3Shape Holding A/S + +OUI:F802784* + ID_OUI_FROM_DATABASE=CLARUS Korea Co., Ltd + +OUI:F802785* + ID_OUI_FROM_DATABASE=Electric Objects + +OUI:F802786* + ID_OUI_FROM_DATABASE=Witium Co., Ltd + +OUI:F802787* + ID_OUI_FROM_DATABASE=BETTINI SRL + +OUI:F802788* + ID_OUI_FROM_DATABASE=EMBUX Technology Co., Ltd. + +OUI:F802789* + ID_OUI_FROM_DATABASE=Beijing Redcdn Technology, Co., Ltd + +OUI:F80278A* + ID_OUI_FROM_DATABASE=Luxul Technology Inc + +OUI:F80278B* + ID_OUI_FROM_DATABASE=Rosemount Analytical + +OUI:F80278C* + ID_OUI_FROM_DATABASE=Technology Research, LLC + +OUI:F80278D* + ID_OUI_FROM_DATABASE=Dueton Systems s.r.o. + +OUI:F80278E* + ID_OUI_FROM_DATABASE=Lit Technologies + +OUI:F80278F* + ID_OUI_FROM_DATABASE=Private + +OUI:F80332* + ID_OUI_FROM_DATABASE=Khomp + +OUI:F80377* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F8042E* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND) + +OUI:F8051C* + ID_OUI_FROM_DATABASE=DRS Imaging and Targeting Solutions + +OUI:F8084F* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:F80BBE* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F80BCB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F80BD0* + ID_OUI_FROM_DATABASE=Datang Telecom communication terminal (Tianjin) Co., Ltd. + +OUI:F80CF3* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:F80D43* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:F80D60* + ID_OUI_FROM_DATABASE=CANON INC. + +OUI:F80DEA* + ID_OUI_FROM_DATABASE=ZyCast Technology Inc. + +OUI:F80DF0* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:F80DF1* + ID_OUI_FROM_DATABASE=Sontex SA + +OUI:F80F41* + ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation + +OUI:F80F6F* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F80F84* + ID_OUI_FROM_DATABASE=Natural Security SAS + +OUI:F80FF9* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:F81037* + ID_OUI_FROM_DATABASE=Atopia Systems, LP + +OUI:F81308* + ID_OUI_FROM_DATABASE=Nokia + +OUI:F81547* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:F81654* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F81897* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:F81A67* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:F81CE5* + ID_OUI_FROM_DATABASE=Telefonbau Behnke GmbH + +OUI:F81D0F* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:F81D780* + ID_OUI_FROM_DATABASE=Dongguan Shun Hing Plastics Limited + +OUI:F81D781* + ID_OUI_FROM_DATABASE=ADTECHNO Inc. + +OUI:F81D782* + ID_OUI_FROM_DATABASE=Xperio Labs Limited + +OUI:F81D783* + ID_OUI_FROM_DATABASE=SHANGHAI SUN TELECOMMUNICATION CO., LTD. + +OUI:F81D784* + ID_OUI_FROM_DATABASE=Digital Imaging Technology + +OUI:F81D785* + ID_OUI_FROM_DATABASE=DACONS + +OUI:F81D786* + ID_OUI_FROM_DATABASE=Zengge Co., Limited + +OUI:F81D787* + ID_OUI_FROM_DATABASE=WUHAN GUIDE INFRARED CO.,LTD + +OUI:F81D788* + ID_OUI_FROM_DATABASE=TELEOFIS + +OUI:F81D789* + ID_OUI_FROM_DATABASE=Ophrys Systèmes + +OUI:F81D78A* + ID_OUI_FROM_DATABASE=AVPro Global Holdings LLC + +OUI:F81D78B* + ID_OUI_FROM_DATABASE=SigmaConnectivityAB + +OUI:F81D78C* + ID_OUI_FROM_DATABASE=SHENZHUOYUE TECHNOLOGY.,LTD + +OUI:F81D78D* + ID_OUI_FROM_DATABASE=Tofino + +OUI:F81D78E* + ID_OUI_FROM_DATABASE=GUANGDONG ENOK COMMUNICATION CO., LTD. + +OUI:F81D90* + ID_OUI_FROM_DATABASE=Solidwintech + +OUI:F81D93* + ID_OUI_FROM_DATABASE=Longdhua(Beijing) Controls Technology Co.,Ltd + +OUI:F81E6F* + ID_OUI_FROM_DATABASE=EBG compleo GmbH + +OUI:F81EDF* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F81F32* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:F82055* + ID_OUI_FROM_DATABASE=Green Information System + +OUI:F82285* + ID_OUI_FROM_DATABASE=Cypress Technology CO., LTD. + +OUI:F82387* + ID_OUI_FROM_DATABASE=Shenzhen Horn Audio Co.,Ltd. + +OUI:F823B2* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F82441* + ID_OUI_FROM_DATABASE=Yeelink + +OUI:F8272E* + ID_OUI_FROM_DATABASE=Mercku + +OUI:F82793* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F82819* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:F82BC8* + ID_OUI_FROM_DATABASE=Jiangsu Switter Co., Ltd + +OUI:F82C18* + ID_OUI_FROM_DATABASE=2Wire Inc + +OUI:F82D7C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F82DC0* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F82E8E* + ID_OUI_FROM_DATABASE=Nanjing Kechen Electric Co., Ltd. + +OUI:F82EDB* + ID_OUI_FROM_DATABASE=RTW GmbH & Co. KG + +OUI:F82F08* + ID_OUI_FROM_DATABASE=Molex CMS + +OUI:F82F5B* + ID_OUI_FROM_DATABASE=eGauge Systems LLC + +OUI:F82F6A* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:F82FA8* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:F83002* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F83094* + ID_OUI_FROM_DATABASE=Alcatel-Lucent Telecom Limited + +OUI:F8313E* + ID_OUI_FROM_DATABASE=endeavour GmbH + +OUI:F832E4* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:F83331* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F83376* + ID_OUI_FROM_DATABASE=Good Mind Innovation Co., Ltd. + +OUI:F83441* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F83553* + ID_OUI_FROM_DATABASE=Magenta Research Ltd. + +OUI:F835DD* + ID_OUI_FROM_DATABASE=Gemtek Technology Co., Ltd. + +OUI:F8369B* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F83880* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F83CBF* + ID_OUI_FROM_DATABASE=BOTATO ELECTRONICS SDN BHD + +OUI:F83D4E* + ID_OUI_FROM_DATABASE=Softlink Automation System Co., Ltd + +OUI:F83DFF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F83F51* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F842FB* + ID_OUI_FROM_DATABASE=Yasuda Joho Co.,ltd. + +OUI:F844E3* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:F845AD* + ID_OUI_FROM_DATABASE=Konka Group Co., Ltd. + +OUI:F8461C* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:F8462D* + ID_OUI_FROM_DATABASE=SYNTEC Incorporation + +OUI:F8472D* + ID_OUI_FROM_DATABASE=X2gen Digital Corp. Ltd + +OUI:F84897* + ID_OUI_FROM_DATABASE=Hitachi, Ltd. + +OUI:F848FD* + ID_OUI_FROM_DATABASE=China Mobile Group Device Co.,Ltd. + +OUI:F84A73* + ID_OUI_FROM_DATABASE=EUMTECH CO., LTD + +OUI:F84A7F* + ID_OUI_FROM_DATABASE=Innometriks Inc + +OUI:F84ABF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F84D33* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:F84DFC* + ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd. + +OUI:F84E73* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F84F57* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F84FAD* + ID_OUI_FROM_DATABASE=Hui Zhou Gaoshengda Technology Co.,LTD + +OUI:F8501C* + ID_OUI_FROM_DATABASE=Tianjin Geneuo Technology Co.,Ltd + +OUI:F85063* + ID_OUI_FROM_DATABASE=Verathon + +OUI:F8516D* + ID_OUI_FROM_DATABASE=Denwa Technology Corp. + +OUI:F852DF* + ID_OUI_FROM_DATABASE=VNL Europe AB + +OUI:F854AF* + ID_OUI_FROM_DATABASE=ECI Telecom Ltd. + +OUI:F854B8* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:F855CD* + ID_OUI_FROM_DATABASE=Visteon Corporation + +OUI:F8572E* + ID_OUI_FROM_DATABASE=Core Brands, LLC + +OUI:F85971* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F85A00* + ID_OUI_FROM_DATABASE=Sanford LP + +OUI:F85B3B* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:F85B9C* + ID_OUI_FROM_DATABASE=SB SYSTEMS Co.,Ltd + +OUI:F85BC9* + ID_OUI_FROM_DATABASE=M-Cube Spa + +OUI:F85C45* + ID_OUI_FROM_DATABASE=IC Nexus Co. Ltd. + +OUI:F85C4D* + ID_OUI_FROM_DATABASE=Nokia + +OUI:F85E3C* + ID_OUI_FROM_DATABASE=SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD + +OUI:F85F2A* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:F860F0* + ID_OUI_FROM_DATABASE=Aruba, a Hewlett Packard Enterprise Company + +OUI:F86214* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F862AA* + ID_OUI_FROM_DATABASE=xn systems + +OUI:F8633F* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F86465* + ID_OUI_FROM_DATABASE=Anova Applied Electronics, Inc. + +OUI:F86601* + ID_OUI_FROM_DATABASE=Suzhou Chi-tek information technology Co., Ltd + +OUI:F866D1* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:F866F2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F86971* + ID_OUI_FROM_DATABASE=Seibu Electric Co., + +OUI:F86CE1* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:F86ECF* + ID_OUI_FROM_DATABASE=Arcx Inc + +OUI:F86EEE* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F86FC1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F86FDE* + ID_OUI_FROM_DATABASE=Shenzhen Goodix Technology Co.,Ltd. + +OUI:F871FE* + ID_OUI_FROM_DATABASE=The Goldman Sachs Group, Inc. + +OUI:F872EA* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F87394* + ID_OUI_FROM_DATABASE=NETGEAR + +OUI:F873A2* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:F87588* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F875A4* + ID_OUI_FROM_DATABASE=LCFC(HeFei) Electronics Technology co., ltd + +OUI:F8769B* + ID_OUI_FROM_DATABASE=Neopis Co., Ltd. + +OUI:F877B8* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F87AEF* + ID_OUI_FROM_DATABASE=Rosonix Technology, Inc. + +OUI:F87B20* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F87B62* + ID_OUI_FROM_DATABASE=FASTWEL INTERNATIONAL CO., LTD. Taiwan Branch + +OUI:F87B7A* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F87B8C* + ID_OUI_FROM_DATABASE=Amped Wireless + +OUI:F88096* + ID_OUI_FROM_DATABASE=Elsys Equipamentos Eletrônicos Ltda + +OUI:F8811A* + ID_OUI_FROM_DATABASE=OVERKIZ + +OUI:F88479* + ID_OUI_FROM_DATABASE=Yaojin Technology(Shenzhen)Co.,Ltd + +OUI:F884F2* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F887F1* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F8893C* + ID_OUI_FROM_DATABASE=Inventec Appliances Corp. + +OUI:F88A3C0* + ID_OUI_FROM_DATABASE=ART SPA + +OUI:F88A3C1* + ID_OUI_FROM_DATABASE=Carefree of Colorado + +OUI:F88A3C2* + ID_OUI_FROM_DATABASE=KLATU Networks Inc + +OUI:F88A3C3* + ID_OUI_FROM_DATABASE=Shenzhen Shengyuan Tech Ltd. + +OUI:F88A3C4* + ID_OUI_FROM_DATABASE=GO-LINK TECHNOLOGY CO., LTD. + +OUI:F88A3C5* + ID_OUI_FROM_DATABASE=KOKKIA INC + +OUI:F88A3C6* + ID_OUI_FROM_DATABASE=Beijing Zhong Chuang Communication Technology Ltd. + +OUI:F88A3C7* + ID_OUI_FROM_DATABASE=Josh.ai + +OUI:F88A3C8* + ID_OUI_FROM_DATABASE=Cadmus Electronic Co.,Ltd. + +OUI:F88A3C9* + ID_OUI_FROM_DATABASE=withus + +OUI:F88A3CA* + ID_OUI_FROM_DATABASE=Protos GmbH + +OUI:F88A3CB* + ID_OUI_FROM_DATABASE=FARA AS + +OUI:F88A3CC* + ID_OUI_FROM_DATABASE=EXCETOP TECHNOLOGY (BEIJING) CO., LTD. + +OUI:F88A3CD* + ID_OUI_FROM_DATABASE=THK Co.,LTD. + +OUI:F88A3CE* + ID_OUI_FROM_DATABASE=Avateq Corp. + +OUI:F88A5E* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:F88B37* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F88C1C* + ID_OUI_FROM_DATABASE=KAISHUN ELECTRONIC TECHNOLOGY CO., LTD. BEIJING + +OUI:F88DEF* + ID_OUI_FROM_DATABASE=Tenebraex + +OUI:F88E85* + ID_OUI_FROM_DATABASE=Comtrend Corporation + +OUI:F88FCA* + ID_OUI_FROM_DATABASE=Google, Inc. + +OUI:F89066* + ID_OUI_FROM_DATABASE=Nain Inc. + +OUI:F8912A* + ID_OUI_FROM_DATABASE=GLP German Light Products GmbH + +OUI:F89173* + ID_OUI_FROM_DATABASE=AEDLE SAS + +OUI:F893F3* + ID_OUI_FROM_DATABASE=VOLANS + +OUI:F894C2* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F89550* + ID_OUI_FROM_DATABASE=Proton Products Chengdu Ltd + +OUI:F895C7* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:F895EA* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F897CF* + ID_OUI_FROM_DATABASE=DAESHIN-INFORMATION TECHNOLOGY CO., LTD. + +OUI:F8983A* + ID_OUI_FROM_DATABASE=Leeman International (HongKong) Limited + +OUI:F898B9* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F898EF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F89910* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:F89955* + ID_OUI_FROM_DATABASE=Fortress Technology Inc + +OUI:F89A78* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F89D0D* + ID_OUI_FROM_DATABASE=Control Technology Inc. + +OUI:F89DBB* + ID_OUI_FROM_DATABASE=Tintri + +OUI:F89E28* + ID_OUI_FROM_DATABASE=Cisco Meraki + +OUI:F89FB8* + ID_OUI_FROM_DATABASE=YAZAKI Energy System Corporation + +OUI:F8A03D* + ID_OUI_FROM_DATABASE=Dinstar Technologies Co., Ltd. + +OUI:F8A097* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F8A188* + ID_OUI_FROM_DATABASE=LED Roadway Lighting + +OUI:F8A2B4* + ID_OUI_FROM_DATABASE=RHEWA-WAAGENFABRIK August Freudewald GmbH &Co. KG + +OUI:F8A2D6* + ID_OUI_FROM_DATABASE=Liteon Technology Corporation + +OUI:F8A34F* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:F8A45F* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:F8A5C5* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F8A763* + ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd. + +OUI:F8A963* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:F8A9D0* + ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications) + +OUI:F8A9DE* + ID_OUI_FROM_DATABASE=PUISSANCE PLUS + +OUI:F8AA8A* + ID_OUI_FROM_DATABASE=Axview Technology (Shenzhen) Co.,Ltd + +OUI:F8AB05* + ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS + +OUI:F8AC6D* + ID_OUI_FROM_DATABASE=Deltenna Ltd + +OUI:F8ADCB* + ID_OUI_FROM_DATABASE=HMD Global Oy + +OUI:F8AE27* + ID_OUI_FROM_DATABASE=John Deere Electronic Solutions + +OUI:F8AF05* + ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd. + +OUI:F8AFDB* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:F8B156* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:F8B2F3* + ID_OUI_FROM_DATABASE=GUANGZHOU BOSMA TECHNOLOGY CO.,LTD + +OUI:F8B46A* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:F8B5680* + ID_OUI_FROM_DATABASE=LifePrint Products, Inc. + +OUI:F8B5681* + ID_OUI_FROM_DATABASE=PT. Eyro Digital Teknologi + +OUI:F8B5682* + ID_OUI_FROM_DATABASE=Shenzhen New-Bund Technology Co., Ltd. + +OUI:F8B5683* + ID_OUI_FROM_DATABASE=Dongwoo Engineering Co.,Ltd + +OUI:F8B5684* + ID_OUI_FROM_DATABASE=Combiwins Technology Co.,Limited + +OUI:F8B5685* + ID_OUI_FROM_DATABASE=etectRx + +OUI:F8B5686* + ID_OUI_FROM_DATABASE=Package Guard, Inc + +OUI:F8B5687* + ID_OUI_FROM_DATABASE=CloudMinds (Shenzhen) Holdings Co., Ltd + +OUI:F8B5688* + ID_OUI_FROM_DATABASE=Maven Wireless AB + +OUI:F8B5689* + ID_OUI_FROM_DATABASE=Beijing Wanji Techonology Co., Ltd. + +OUI:F8B568A* + ID_OUI_FROM_DATABASE=SinePulse GmbH + +OUI:F8B568B* + ID_OUI_FROM_DATABASE=Whizpace Pte. Ltd. + +OUI:F8B568C* + ID_OUI_FROM_DATABASE=3SI Security Systems, Inc + +OUI:F8B568D* + ID_OUI_FROM_DATABASE=Solarius + +OUI:F8B568E* + ID_OUI_FROM_DATABASE=ZAO "RADIUS Avtomatika" + +OUI:F8B599* + ID_OUI_FROM_DATABASE=Guangzhou CHNAVS Digital Technology Co.,Ltd + +OUI:F8B797* + ID_OUI_FROM_DATABASE=NEC Platforms, Ltd. + +OUI:F8B7E2* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F8BBBF* + ID_OUI_FROM_DATABASE=eero inc. + +OUI:F8BC12* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:F8BC41* + ID_OUI_FROM_DATABASE=Rosslare Enterprises Limited + +OUI:F8BE0D* + ID_OUI_FROM_DATABASE=A2UICT Co.,Ltd. + +OUI:F8BF09* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F8C001* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:F8C091* + ID_OUI_FROM_DATABASE=Highgates Technology + +OUI:F8C120* + ID_OUI_FROM_DATABASE=Xi'an Link-Science Technology Co.,Ltd + +OUI:F8C249* + ID_OUI_FROM_DATABASE=Private + +OUI:F8C288* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:F8C372* + ID_OUI_FROM_DATABASE=TSUZUKI DENKI + +OUI:F8C397* + ID_OUI_FROM_DATABASE=NZXT Corp. Ltd. + +OUI:F8C39E* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F8C4F3* + ID_OUI_FROM_DATABASE=Shanghai Infinity Wireless Technologies Co.,Ltd. + +OUI:F8C678* + ID_OUI_FROM_DATABASE=Carefusion + +OUI:F8C96C* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:F8CA59* + ID_OUI_FROM_DATABASE=NetComm Wireless + +OUI:F8CAB8* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:F8CC6E* + ID_OUI_FROM_DATABASE=DEPO Electronics Ltd + +OUI:F8CFC5* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:F8D027* + ID_OUI_FROM_DATABASE=Seiko Epson Corporation + +OUI:F8D0AC* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:F8D0BD* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F8D111* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:F8D3A9* + ID_OUI_FROM_DATABASE=AXAN Networks + +OUI:F8D462* + ID_OUI_FROM_DATABASE=Pumatronix Equipamentos Eletronicos Ltda. + +OUI:F8D478* + ID_OUI_FROM_DATABASE=Flextronics Tech.(Ind) Pvt Ltd + +OUI:F8D756* + ID_OUI_FROM_DATABASE=Simm Tronic Limited + +OUI:F8D7BF* + ID_OUI_FROM_DATABASE=REV Ritter GmbH + +OUI:F8D9B8* + ID_OUI_FROM_DATABASE=Open Mesh, Inc. + +OUI:F8DA0C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:F8DADF* + ID_OUI_FROM_DATABASE=EcoTech, Inc. + +OUI:F8DAE2* + ID_OUI_FROM_DATABASE=NDC Technologies + +OUI:F8DAF4* + ID_OUI_FROM_DATABASE=Taishan Online Technology Co., Ltd. + +OUI:F8DB4C* + ID_OUI_FROM_DATABASE=PNY Technologies, INC. + +OUI:F8DB7F* + ID_OUI_FROM_DATABASE=HTC Corporation + +OUI:F8DB88* + ID_OUI_FROM_DATABASE=Dell Inc. + +OUI:F8DC7A* + ID_OUI_FROM_DATABASE=Variscite LTD + +OUI:F8DF15* + ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd + +OUI:F8DFA8* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:F8DFE1* + ID_OUI_FROM_DATABASE=MyLight Systems + +OUI:F8E079* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:F8E44E* + ID_OUI_FROM_DATABASE=MCOT INC. + +OUI:F8E4E3* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F8E4FB* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:F8E5CF* + ID_OUI_FROM_DATABASE=CGI IT UK LIMITED + +OUI:F8E61A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F8E71E* + ID_OUI_FROM_DATABASE=Ruckus Wireless + +OUI:F8E7A0* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:F8E7B5* + ID_OUI_FROM_DATABASE=µTech Tecnologia LTDA + +OUI:F8E811* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:F8E903* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:F8E94E* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:F8E968* + ID_OUI_FROM_DATABASE=Egker Kft. + +OUI:F8EA0A* + ID_OUI_FROM_DATABASE=Dipl.-Math. Michael Rauch + +OUI:F8EDA5* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F8F005* + ID_OUI_FROM_DATABASE=Newport Media Inc. + +OUI:F8F014* + ID_OUI_FROM_DATABASE=RackWare Inc. + +OUI:F8F082* + ID_OUI_FROM_DATABASE=NAG LLC + +OUI:F8F1B6* + ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company + +OUI:F8F1E6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:F8F21E* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:F8F25A* + ID_OUI_FROM_DATABASE=G-Lab GmbH + +OUI:F8F464* + ID_OUI_FROM_DATABASE=Rawe Electonic GmbH + +OUI:F8F532* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:F8F7D3* + ID_OUI_FROM_DATABASE=International Communications Corporation + +OUI:F8F7FF* + ID_OUI_FROM_DATABASE=SYN-TECH SYSTEMS INC + +OUI:F8FB2F* + ID_OUI_FROM_DATABASE=Santur Corporation + +OUI:F8FE5C* + ID_OUI_FROM_DATABASE=Reciprocal Labs Corp + +OUI:F8FEA8* + ID_OUI_FROM_DATABASE=Technico Japan Corporation + +OUI:F8FF0B* + ID_OUI_FROM_DATABASE=Electronic Technology Inc. + +OUI:F8FF5F* + ID_OUI_FROM_DATABASE=Shenzhen Communication Technology Co.,Ltd + +OUI:F8FFC2* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:FC0012* + ID_OUI_FROM_DATABASE=Toshiba Samsung Storage Technolgoy Korea Corporation + +OUI:FC017C* + ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd. + +OUI:FC019E* + ID_OUI_FROM_DATABASE=VIEVU + +OUI:FC01CD* + ID_OUI_FROM_DATABASE=FUNDACION TEKNIKER + +OUI:FC039F* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FC0647* + ID_OUI_FROM_DATABASE=Cortland Research, LLC + +OUI:FC06ED* + ID_OUI_FROM_DATABASE=M2Motive Technology Inc. + +OUI:FC07A0* + ID_OUI_FROM_DATABASE=LRE Medical GmbH + +OUI:FC084A* + ID_OUI_FROM_DATABASE=FUJITSU LIMITED + +OUI:FC0877* + ID_OUI_FROM_DATABASE=Prentke Romich Company + +OUI:FC09D8* + ID_OUI_FROM_DATABASE=ACTEON Group + +OUI:FC09F6* + ID_OUI_FROM_DATABASE=GUANGDONG TONZE ELECTRIC CO.,LTD + +OUI:FC0A81* + ID_OUI_FROM_DATABASE=Extreme Networks, Inc. + +OUI:FC0F4B* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:FC0FE6* + ID_OUI_FROM_DATABASE=Sony Interactive Entertainment Inc. + +OUI:FC10BD* + ID_OUI_FROM_DATABASE=Control Sistematizado S.A. + +OUI:FC10C6* + ID_OUI_FROM_DATABASE=Taicang T&W Electronics + +OUI:FC1186* + ID_OUI_FROM_DATABASE=Logic3 plc + +OUI:FC1349* + ID_OUI_FROM_DATABASE=Global Apps Corp. + +OUI:FC15B4* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:FC1607* + ID_OUI_FROM_DATABASE=Taian Technology(Wuxi) Co.,Ltd. + +OUI:FC1794* + ID_OUI_FROM_DATABASE=InterCreative Co., Ltd + +OUI:FC183C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:FC1910* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FC19D0* + ID_OUI_FROM_DATABASE=Cloud Vision Networks Technology Co.,Ltd. + +OUI:FC1A11* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:FC1BD1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:FC1BFF* + ID_OUI_FROM_DATABASE=V-ZUG AG + +OUI:FC1CA1* + ID_OUI_FROM_DATABASE=Nokia + +OUI:FC1D43* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:FC1D59* + ID_OUI_FROM_DATABASE=I Smart Cities HK Ltd + +OUI:FC1D84* + ID_OUI_FROM_DATABASE=Autobase + +OUI:FC1E16* + ID_OUI_FROM_DATABASE=IPEVO corp + +OUI:FC1F19* + ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO MECHANICS CO., LTD. + +OUI:FC1FC0* + ID_OUI_FROM_DATABASE=EURECAM + +OUI:FC229C* + ID_OUI_FROM_DATABASE=Han Kyung I Net Co.,Ltd. + +OUI:FC2325* + ID_OUI_FROM_DATABASE=EosTek (Shenzhen) Co., Ltd. + +OUI:FC253F* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:FC27A2* + ID_OUI_FROM_DATABASE=TRANS ELECTRIC CO., LTD. + +OUI:FC29F3* + ID_OUI_FROM_DATABASE=McPay Co.,LTD. + +OUI:FC2A54* + ID_OUI_FROM_DATABASE=Connected Data, Inc. + +OUI:FC2A9C* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:FC2BB2* + ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc + +OUI:FC2D5E* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:FC2E2D* + ID_OUI_FROM_DATABASE=Lorom Industrial Co.LTD. + +OUI:FC2F40* + ID_OUI_FROM_DATABASE=Calxeda, Inc. + +OUI:FC2F6B* + ID_OUI_FROM_DATABASE=Everspin Technologies, Inc. + +OUI:FC2FAA* + ID_OUI_FROM_DATABASE=Nokia + +OUI:FC2FEF* + ID_OUI_FROM_DATABASE=UTT Technologies Co., Ltd. + +OUI:FC3288* + ID_OUI_FROM_DATABASE=CELOT Wireless Co., Ltd + +OUI:FC3342* + ID_OUI_FROM_DATABASE=Juniper Networks + +OUI:FC335F* + ID_OUI_FROM_DATABASE=Polyera + +OUI:FC3598* + ID_OUI_FROM_DATABASE=Favite Inc. + +OUI:FC35E6* + ID_OUI_FROM_DATABASE=Visteon corp + +OUI:FC372B* + ID_OUI_FROM_DATABASE=SICHUAN TIANYI COMHEART TELECOMCO.,LTD + +OUI:FC3964* + ID_OUI_FROM_DATABASE=ITEL MOBILE LIMITED + +OUI:FC3CE9* + ID_OUI_FROM_DATABASE=Tsingtong Technologies Co, Ltd. + +OUI:FC3D93* + ID_OUI_FROM_DATABASE=LONGCHEER TELECOMMUNICATION LIMITED + +OUI:FC3F7C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:FC3FAB* + ID_OUI_FROM_DATABASE=Henan Lanxin Technology Co., Ltd + +OUI:FC3FDB* + ID_OUI_FROM_DATABASE=Hewlett Packard + +OUI:FC4203* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FC4463* + ID_OUI_FROM_DATABASE=Universal Audio, Inc + +OUI:FC4499* + ID_OUI_FROM_DATABASE=Swarco LEA d.o.o. + +OUI:FC455F* + ID_OUI_FROM_DATABASE=JIANGXI SHANSHUI OPTOELECTRONIC TECHNOLOGY CO.,LTD + +OUI:FC4596* + ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD. + +OUI:FC48EF* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:FC492D* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:FC4AE9* + ID_OUI_FROM_DATABASE=Castlenet Technology Inc. + +OUI:FC4B1C* + ID_OUI_FROM_DATABASE=INTERSENSOR S.R.L. + +OUI:FC4BBC* + ID_OUI_FROM_DATABASE=Sunplus Technology Co., Ltd. + +OUI:FC4D8C* + ID_OUI_FROM_DATABASE=SHENZHEN PANTE ELECTRONICS TECHNOLOGY CO., LTD + +OUI:FC4DD4* + ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd. + +OUI:FC5090* + ID_OUI_FROM_DATABASE=SIMEX Sp. z o.o. + +OUI:FC51A4* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:FC528D* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:FC52CE* + ID_OUI_FROM_DATABASE=Control iD + +OUI:FC539E* + ID_OUI_FROM_DATABASE=Shanghai Wind Technologies Co.,Ltd + +OUI:FC55DC* + ID_OUI_FROM_DATABASE=Baltic Latvian Universal Electronics LLC + +OUI:FC589A* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:FC58FA* + ID_OUI_FROM_DATABASE=Shen Zhen Shi Xin Zhong Xin Technology Co.,Ltd. + +OUI:FC5A1D* + ID_OUI_FROM_DATABASE=Hitron Technologies. Inc + +OUI:FC5B24* + ID_OUI_FROM_DATABASE=Weibel Scientific A/S + +OUI:FC5B26* + ID_OUI_FROM_DATABASE=MikroBits + +OUI:FC5B39* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:FC6018* + ID_OUI_FROM_DATABASE=Zhejiang Kangtai Electric Co., Ltd. + +OUI:FC6198* + ID_OUI_FROM_DATABASE=NEC Personal Products, Ltd + +OUI:FC61E9* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:FC626E* + ID_OUI_FROM_DATABASE=Beijing MDC Telecom + +OUI:FC62B9* + ID_OUI_FROM_DATABASE=ALPS ELECTRIC CO., LTD. + +OUI:FC643A* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FC64BA* + ID_OUI_FROM_DATABASE=Xiaomi Communications Co Ltd + +OUI:FC65DE* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:FC683E* + ID_OUI_FROM_DATABASE=Directed Perception, Inc + +OUI:FC6947* + ID_OUI_FROM_DATABASE=Texas Instruments + +OUI:FC6BF0* + ID_OUI_FROM_DATABASE=TOPWELL INTERNATIONAL HOLDINDS LIMITED + +OUI:FC6C31* + ID_OUI_FROM_DATABASE=LXinstruments GmbH + +OUI:FC6DC0* + ID_OUI_FROM_DATABASE=BME CORPORATION + +OUI:FC6FB7* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:FC7516* + ID_OUI_FROM_DATABASE=D-Link International + +OUI:FC75E6* + ID_OUI_FROM_DATABASE=Handreamnet + +OUI:FC7774* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:FC790B* + ID_OUI_FROM_DATABASE=Hitachi High Technologies America, Inc. + +OUI:FC7C02* + ID_OUI_FROM_DATABASE=Phicomm (Shanghai) Co., Ltd. + +OUI:FC7CE7* + ID_OUI_FROM_DATABASE=FCI USA LLC + +OUI:FC7D6C* + ID_OUI_FROM_DATABASE=HYESUNG TECHWIN Co., Ltd + +OUI:FC7F56* + ID_OUI_FROM_DATABASE=CoSyst Control Systems GmbH + +OUI:FC8329* + ID_OUI_FROM_DATABASE=Trei technics + +OUI:FC8399* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:FC83C6* + ID_OUI_FROM_DATABASE=N-Radio Technologies Co., Ltd. + +OUI:FC8596* + ID_OUI_FROM_DATABASE=Axonne Inc. + +OUI:FC8743* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:FC8B97* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:FC8E5B* + ID_OUI_FROM_DATABASE=China Mobile Iot Limited company + +OUI:FC8E6E* + ID_OUI_FROM_DATABASE=StreamCCTV, LLC + +OUI:FC8E7E* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:FC8F7D* + ID_OUI_FROM_DATABASE=SHENZHEN GONGJIN ELECTRONICS CO.,LT + +OUI:FC8F90* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FC8FC4* + ID_OUI_FROM_DATABASE=Intelligent Technology Inc. + +OUI:FC90FA* + ID_OUI_FROM_DATABASE=Independent Technologies + +OUI:FC9114* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:FC923B* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:FC9435* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:FC946C* + ID_OUI_FROM_DATABASE=UBIVELOX + +OUI:FC94CE* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:FC94E3* + ID_OUI_FROM_DATABASE=Technicolor CH USA Inc. + +OUI:FC9947* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:FC9AFA* + ID_OUI_FROM_DATABASE=Motus Global Inc. + +OUI:FC9BC6* + ID_OUI_FROM_DATABASE=Sumavision Technologies Co.,Ltd + +OUI:FC9DD8* + ID_OUI_FROM_DATABASE=Beijing TongTongYiLian Science and Technology Ltd. + +OUI:FC9FAE* + ID_OUI_FROM_DATABASE=Fidus Systems Inc + +OUI:FC9FE1* + ID_OUI_FROM_DATABASE=CONWIN.Tech. Ltd + +OUI:FCA13E* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FCA183* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:FCA22A* + ID_OUI_FROM_DATABASE=PT. Callysta Multi Engineering + +OUI:FCA386* + ID_OUI_FROM_DATABASE=SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + +OUI:FCA47A0* + ID_OUI_FROM_DATABASE=Broadcom Inc. + +OUI:FCA47A1* + ID_OUI_FROM_DATABASE=Shenzhen VMAX New Energy Co., Ltd. + +OUI:FCA47A2* + ID_OUI_FROM_DATABASE=Ant Financial(Hang Zhou)Network Technology Co.,Ltd. + +OUI:FCA47A3* + ID_OUI_FROM_DATABASE=Cliptech Industria e Comercio Ltda + +OUI:FCA47A4* + ID_OUI_FROM_DATABASE=HOOC AG + +OUI:FCA47A5* + ID_OUI_FROM_DATABASE=Syfer + +OUI:FCA47A6* + ID_OUI_FROM_DATABASE=Token + +OUI:FCA47A7* + ID_OUI_FROM_DATABASE=Innovative Advantage + +OUI:FCA47A8* + ID_OUI_FROM_DATABASE=KARRY COMMUNICATION LIMITED + +OUI:FCA47A9* + ID_OUI_FROM_DATABASE=Oberix Group Pty Ltd + +OUI:FCA47AA* + ID_OUI_FROM_DATABASE=Shenzhen Elebao Technology Co., Ltd + +OUI:FCA47AB* + ID_OUI_FROM_DATABASE=Shenzhen Nokelock Technology Co, Ltd. + +OUI:FCA47AC* + ID_OUI_FROM_DATABASE=Shenzhen ALFEYE Technology CO.,Ltd + +OUI:FCA47AD* + ID_OUI_FROM_DATABASE=SHENZHEN KUKU TECHNOLOGY CO.,LTD + +OUI:FCA47AE* + ID_OUI_FROM_DATABASE=Hefei Feier Smart Science&Technology Co. Ltd + +OUI:FCA621* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FCA667* + ID_OUI_FROM_DATABASE=Amazon Technologies Inc. + +OUI:FCA6CD* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:FCA841* + ID_OUI_FROM_DATABASE=Avaya Inc + +OUI:FCA89A* + ID_OUI_FROM_DATABASE=Sunitec Enterprise Co.,Ltd + +OUI:FCA9B0* + ID_OUI_FROM_DATABASE=MIARTECH (SHANGHAI),INC. + +OUI:FCAA14* + ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD. + +OUI:FCAAB6* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FCAB90* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:FCAD0F* + ID_OUI_FROM_DATABASE=QTS NETWORKS + +OUI:FCAE34* + ID_OUI_FROM_DATABASE=ARRIS Group, Inc. + +OUI:FCAF6A* + ID_OUI_FROM_DATABASE=Qulsar Inc + +OUI:FCAFAC* + ID_OUI_FROM_DATABASE=Socionext Inc. + +OUI:FCB0C4* + ID_OUI_FROM_DATABASE=Shanghai DareGlobal Technologies Co.,Ltd + +OUI:FCB10D* + ID_OUI_FROM_DATABASE=Shenzhen Tian Kun Technology Co.,LTD. + +OUI:FCB4E6* + ID_OUI_FROM_DATABASE=ASKEY COMPUTER CORP + +OUI:FCB58A* + ID_OUI_FROM_DATABASE=Wapice Ltd. + +OUI:FCB662* + ID_OUI_FROM_DATABASE=IC Holdings LLC + +OUI:FCB698* + ID_OUI_FROM_DATABASE=Cambridge Industries(Group) Co.,Ltd. + +OUI:FCB6D8* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:FCB7F0* + ID_OUI_FROM_DATABASE=Idaho National Laboratory + +OUI:FCBBA1* + ID_OUI_FROM_DATABASE=Shenzhen Minicreate Technology Co.,Ltd + +OUI:FCBC9C* + ID_OUI_FROM_DATABASE=Vimar Spa + +OUI:FCBCD1* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:FCBD67* + ID_OUI_FROM_DATABASE=Arista Networks + +OUI:FCBE7B* + ID_OUI_FROM_DATABASE=vivo Mobile Communication Co., Ltd. + +OUI:FCC233* + ID_OUI_FROM_DATABASE=ASUSTek COMPUTER INC. + +OUI:FCC23D* + ID_OUI_FROM_DATABASE=Atmel Corporation + +OUI:FCC2DE* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:FCC734* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FCC897* + ID_OUI_FROM_DATABASE=zte corporation + +OUI:FCCAC4* + ID_OUI_FROM_DATABASE=LifeHealth, LLC + +OUI:FCCCE4* + ID_OUI_FROM_DATABASE=Ascon Ltd. + +OUI:FCCF43* + ID_OUI_FROM_DATABASE=HUIZHOU CITY HUIYANG DISTRICT MEISIQI INDUSTRY DEVELOPMENT CO,.LTD + +OUI:FCCF62* + ID_OUI_FROM_DATABASE=IBM Corp + +OUI:FCD2B60* + ID_OUI_FROM_DATABASE=CG POWER AND INDUSTRIAL SOLUTIONS LTD + +OUI:FCD2B61* + ID_OUI_FROM_DATABASE=LINK (FAR-EAST) CORPORATION + +OUI:FCD2B62* + ID_OUI_FROM_DATABASE=Soma GmbH + +OUI:FCD2B63* + ID_OUI_FROM_DATABASE=Coet Costruzioni Elettrotecniche + +OUI:FCD2B64* + ID_OUI_FROM_DATABASE=SHEN ZHEN XIN HAO YUAN PRECISION TECHNOLOGY CO.,L TD + +OUI:FCD2B65* + ID_OUI_FROM_DATABASE=Grandway Technology (Shenzhen) Limited + +OUI:FCD2B66* + ID_OUI_FROM_DATABASE=Cirque Audio Technology Co.,Ltd + +OUI:FCD2B67* + ID_OUI_FROM_DATABASE=Teamly Digital + +OUI:FCD2B68* + ID_OUI_FROM_DATABASE=Oviss Labs Inc. + +OUI:FCD2B69* + ID_OUI_FROM_DATABASE=Winglet Systems Inc. + +OUI:FCD2B6A* + ID_OUI_FROM_DATABASE=NREAL TECHNOLOGY LIMITED + +OUI:FCD2B6B* + ID_OUI_FROM_DATABASE=T CHIP DIGITAL TECHNOLOGY CO.LTD + +OUI:FCD2B6C* + ID_OUI_FROM_DATABASE=Silicon (Shenzhen) Electronic Technology Co.,Ltd. + +OUI:FCD2B6D* + ID_OUI_FROM_DATABASE=Bee Smart(Changzhou) Information Technology Co., Ltd + +OUI:FCD2B6E* + ID_OUI_FROM_DATABASE=Univer S.p.A. + +OUI:FCD4F2* + ID_OUI_FROM_DATABASE=The Coca Cola Company + +OUI:FCD4F6* + ID_OUI_FROM_DATABASE=Messana Air.Ray Conditioning s.r.l. + +OUI:FCD5D9* + ID_OUI_FROM_DATABASE=Shenzhen SDMC Technology Co., Ltd. + +OUI:FCD6BD* + ID_OUI_FROM_DATABASE=Robert Bosch GmbH + +OUI:FCD733* + ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD. + +OUI:FCD817* + ID_OUI_FROM_DATABASE=Beijing Hesun Technologies Co.Ltd. + +OUI:FCD848* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:FCDB21* + ID_OUI_FROM_DATABASE=SAMSARA NETWORKS INC + +OUI:FCDB96* + ID_OUI_FROM_DATABASE=ENERVALLEY CO., LTD + +OUI:FCDBB3* + ID_OUI_FROM_DATABASE=Murata Manufacturing Co., Ltd. + +OUI:FCDC4A* + ID_OUI_FROM_DATABASE=G-Wearables Corp. + +OUI:FCDD55* + ID_OUI_FROM_DATABASE=Shenzhen WeWins wireless Co.,Ltd + +OUI:FCDE90* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FCE14F* + ID_OUI_FROM_DATABASE=BRK Brands, Inc. + +OUI:FCE186* + ID_OUI_FROM_DATABASE=A3M Co., LTD + +OUI:FCE192* + ID_OUI_FROM_DATABASE=Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd + +OUI:FCE1D9* + ID_OUI_FROM_DATABASE=Stable Imaging Solutions LLC + +OUI:FCE1FB* + ID_OUI_FROM_DATABASE=Array Networks + +OUI:FCE23F* + ID_OUI_FROM_DATABASE=CLAY PAKY SPA + +OUI:FCE33C* + ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD + +OUI:FCE557* + ID_OUI_FROM_DATABASE=Nokia Corporation + +OUI:FCE66A* + ID_OUI_FROM_DATABASE=Industrial Software Co + +OUI:FCE892* + ID_OUI_FROM_DATABASE=Hangzhou Lancable Technology Co.,Ltd + +OUI:FCE998* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:FCEA50* + ID_OUI_FROM_DATABASE=Integrated Device Technology (Malaysia) Sdn. Bhd. + +OUI:FCECDA* + ID_OUI_FROM_DATABASE=Ubiquiti Networks Inc. + +OUI:FCEDB9* + ID_OUI_FROM_DATABASE=Arrayent + +OUI:FCEEE6* + ID_OUI_FROM_DATABASE=FORMIKE ELECTRONIC CO., LTD + +OUI:FCF136* + ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd + +OUI:FCF152* + ID_OUI_FROM_DATABASE=Sony Corporation + +OUI:FCF1CD* + ID_OUI_FROM_DATABASE=OPTEX-FA CO.,LTD. + +OUI:FCF29F* + ID_OUI_FROM_DATABASE=China Mobile Iot Limited company + +OUI:FCF528* + ID_OUI_FROM_DATABASE=Zyxel Communications Corporation + +OUI:FCF5C4* + ID_OUI_FROM_DATABASE=Espressif Inc. + +OUI:FCF647* + ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD + +OUI:FCF8AE* + ID_OUI_FROM_DATABASE=Intel Corporate + +OUI:FCF8B7* + ID_OUI_FROM_DATABASE=TRONTEQ Electronic + +OUI:FCFAF7* + ID_OUI_FROM_DATABASE=Shanghai Baud Data Communication Co.,Ltd. + +OUI:FCFBFB* + ID_OUI_FROM_DATABASE=Cisco Systems, Inc + +OUI:FCFC48* + ID_OUI_FROM_DATABASE=Apple, Inc. + +OUI:FCFE77* + ID_OUI_FROM_DATABASE=Hitachi Reftechno, Inc. + +OUI:FCFEC2* + ID_OUI_FROM_DATABASE=Invensys Controls UK Limited + +OUI:FCFFAA* + ID_OUI_FROM_DATABASE=IEEE Registration Authority diff --git a/hwdb.d/20-acpi-vendor.hwdb b/hwdb.d/20-acpi-vendor.hwdb new file mode 100644 index 00000000..2b55c61a --- /dev/null +++ b/hwdb.d/20-acpi-vendor.hwdb @@ -0,0 +1,7705 @@ +# This file is part of systemd. +# +# Data imported from: +# https://uefi.org/uefi-pnp-export +# https://uefi.org/uefi-acpi-export +# +# With various additions from other sources + +acpi:3GVR*: + ID_VENDOR_FROM_DATABASE=VR Technology Holdings Limited + +acpi:3NOD*: + ID_VENDOR_FROM_DATABASE=Shenzhen three Connaught Information Technology Co., Ltd. (3nod Group) + +acpi:AANT*: + ID_VENDOR_FROM_DATABASE=AAEON Technology Inc. + +acpi:AAVA*: + ID_VENDOR_FROM_DATABASE=Aava Mobile Oy + +acpi:AMDI*: + ID_VENDOR_FROM_DATABASE=AMD + +acpi:AMPC*: + ID_VENDOR_FROM_DATABASE=Ampere Computing + +acpi:AMZN*: + ID_VENDOR_FROM_DATABASE=Amazon Corporation + +acpi:APMC*: + ID_VENDOR_FROM_DATABASE=Applied Micro Circuits Corporation + +acpi:APTA*: + ID_VENDOR_FROM_DATABASE=Aptina Imaging Corporation + +acpi:ARMH*: + ID_VENDOR_FROM_DATABASE=ARM Ltd. + +acpi:ARML*: + ID_VENDOR_FROM_DATABASE=ARM Ltd. + +acpi:ASEM*: + ID_VENDOR_FROM_DATABASE=ASEM S.p.A. + +acpi:ASUS*: + ID_VENDOR_FROM_DATABASE=ASUS + +acpi:ATML*: + ID_VENDOR_FROM_DATABASE=Atmel + +acpi:AUTH*: + ID_VENDOR_FROM_DATABASE=AuthenTec + +acpi:BOOT*: + ID_VENDOR_FROM_DATABASE=Coreboot Project + +acpi:BOSC*: + ID_VENDOR_FROM_DATABASE=Robert Bosch GmbH + +acpi:BRCM*: + ID_VENDOR_FROM_DATABASE=Broadcom Corporation + +acpi:CMHR*: + ID_VENDOR_FROM_DATABASE=COMHEAR, INC. + +acpi:CORE*: + ID_VENDOR_FROM_DATABASE=CoreOS, Inc + +acpi:CPLM*: + ID_VENDOR_FROM_DATABASE=Capella Microsystems Inc. + +acpi:DELL*: + ID_VENDOR_FROM_DATABASE=Dell, Inc. + +acpi:DLGS*: + ID_VENDOR_FROM_DATABASE=Dialog Semiconductor PLC + +acpi:DLLK*: + ID_VENDOR_FROM_DATABASE=Dell, Inc. + +acpi:DMST*: + ID_VENDOR_FROM_DATABASE=DMIST RESEARCH LTD + +acpi:DSUO*: + ID_VENDOR_FROM_DATABASE=Shenzhen DSO Microelectronics Co.,Ltd. + +acpi:ELAN*: + ID_VENDOR_FROM_DATABASE=ELAN MICROELECTRONICS CORPORATION + +acpi:ESSX*: + ID_VENDOR_FROM_DATABASE=Everest Semiconductor Co., Ltd. + +acpi:EXAR*: + ID_VENDOR_FROM_DATABASE=Exar Corporation + +acpi:FRSC*: + ID_VENDOR_FROM_DATABASE=Freescale, Inc + +acpi:FTSC*: + ID_VENDOR_FROM_DATABASE=FocalTech Systems Co., Ltd. + +acpi:FUJI*: + ID_VENDOR_FROM_DATABASE=Fujitsu Limited + +acpi:GHSW*: + ID_VENDOR_FROM_DATABASE=Green Hills Software + +acpi:GOOG*: + ID_VENDOR_FROM_DATABASE=Google, Inc. + +acpi:GTCH*: + ID_VENDOR_FROM_DATABASE=G2touch Co., LTD + +acpi:HIMX*: + ID_VENDOR_FROM_DATABASE=Himax Technologies, Inc. + +acpi:HISI*: + ID_VENDOR_FROM_DATABASE=HiSilicon Technologies Co., Ltd. + +acpi:HPIC*: + ID_VENDOR_FROM_DATABASE=HP Inc. + +acpi:HPQC*: + ID_VENDOR_FROM_DATABASE=Hewlett-Packard Company + +acpi:HTLM*: + ID_VENDOR_FROM_DATABASE=HTBLuVA Mödling + +acpi:HWPE*: + ID_VENDOR_FROM_DATABASE=Hewlett Packard Enterprise + +acpi:HXTS*: + ID_VENDOR_FROM_DATABASE=Guizhou Huaxintong Semiconductor Technology Co., Ltd + +acpi:IBMX*: + ID_VENDOR_FROM_DATABASE=IBM + +acpi:IDEA*: + ID_VENDOR_FROM_DATABASE=Lenovo Beijing Co. Ltd. + +acpi:IDEM*: + ID_VENDOR_FROM_DATABASE=IDEMIA + +acpi:IHSE*: + ID_VENDOR_FROM_DATABASE=IHSE GmbH + +acpi:IMPJ*: + ID_VENDOR_FROM_DATABASE=Impinj + +acpi:INSY*: + ID_VENDOR_FROM_DATABASE=Insyde Software + +acpi:INTC*: + ID_VENDOR_FROM_DATABASE=Intel Corporation + +acpi:INTL*: + ID_VENDOR_FROM_DATABASE=Intel Corporation + +acpi:INVN*: + ID_VENDOR_FROM_DATABASE=Invensense, Inc + +acpi:IP3T*: + ID_VENDOR_FROM_DATABASE=IP3 Technology Ltd. + +acpi:IPHI*: + ID_VENDOR_FROM_DATABASE=Inphi Corporation + +acpi:KIOX*: + ID_VENDOR_FROM_DATABASE=Kionix, Inc. + +acpi:LNRO*: + ID_VENDOR_FROM_DATABASE=Linaro, Ltd. + +acpi:LNUX*: + ID_VENDOR_FROM_DATABASE=The Linux Foundation + +acpi:MCHP*: + ID_VENDOR_FROM_DATABASE=Microchip Technology Inc + +acpi:MIPI*: + ID_VENDOR_FROM_DATABASE=MIPI Alliance + +acpi:MRVL*: + ID_VENDOR_FROM_DATABASE=Marvell Technology Group Ltd. + +acpi:MSAY*: + ID_VENDOR_FROM_DATABASE=Microsoft Corporation + +acpi:MSFT*: + ID_VENDOR_FROM_DATABASE=Microsoft Corporation + +acpi:MSHW*: + ID_VENDOR_FROM_DATABASE=Microsoft Corporation + +acpi:MXIM*: + ID_VENDOR_FROM_DATABASE=Maxim Integrated + +acpi:NVDA*: + ID_VENDOR_FROM_DATABASE=Nvidia + +acpi:NVTN*: + ID_VENDOR_FROM_DATABASE=Nuvoton Technology Corporation + +acpi:NXGO*: + ID_VENDOR_FROM_DATABASE=Nexstgo Company Limited + +acpi:OBDA*: + ID_VENDOR_FROM_DATABASE=REALTEK Semiconductor Corp. + +acpi:OMPS*: + ID_VENDOR_FROM_DATABASE=OmniPreSense + +acpi:OVTI*: + ID_VENDOR_FROM_DATABASE=OmniVision Technologies, Inc. + +acpi:PEGA*: + ID_VENDOR_FROM_DATABASE=Pegatron Corporation + +acpi:QCOM*: + ID_VENDOR_FROM_DATABASE=Qualcomm Inc + +acpi:QEMU*: + ID_VENDOR_FROM_DATABASE=Red Hat, Inc. + +acpi:RAYD*: + ID_VENDOR_FROM_DATABASE=Raydium Semiconductor Corporation + +acpi:RKCP*: + ID_VENDOR_FROM_DATABASE=Fuzhou Rockchip Electronics Co., Ltd. + +acpi:RZSN*: + ID_VENDOR_FROM_DATABASE=Rozsnyó, s.r.o. + +acpi:SHRP*: + ID_VENDOR_FROM_DATABASE=Sharp Corporation + +acpi:SNSL*: + ID_VENDOR_FROM_DATABASE=Sensel, Inc. + +acpi:SONY*: + ID_VENDOR_FROM_DATABASE=Sony Corporation + +acpi:ST86*: + ID_VENDOR_FROM_DATABASE=Shenzhen South-Top Computer Co., Ltd. + +acpi:SWEM*: + ID_VENDOR_FROM_DATABASE=Sierra Wireless + +acpi:SYNA*: + ID_VENDOR_FROM_DATABASE=Synaptics Inc + +acpi:TCAG*: + ID_VENDOR_FROM_DATABASE=Teracue AG + +acpi:TOSB*: + ID_VENDOR_FROM_DATABASE=Toshiba Corporation + +acpi:TXNW*: + ID_VENDOR_FROM_DATABASE=Texas Instruments + +acpi:UBLX*: + ID_VENDOR_FROM_DATABASE=u-blox AG + +acpi:VAIO*: + ID_VENDOR_FROM_DATABASE=VAIO Corporation + +acpi:VFSI*: + ID_VENDOR_FROM_DATABASE=Validity Sensors, Inc + +acpi:VSHY*: + ID_VENDOR_FROM_DATABASE=Vishay Intertechnology, Inc. + +acpi:WCOM*: + ID_VENDOR_FROM_DATABASE=Wacom + +acpi:WSDR*: + ID_VENDOR_FROM_DATABASE=Winsider Seminars & Solutions Inc. + +acpi:XMCC*: + ID_VENDOR_FROM_DATABASE=Xiaomi Inc. + +acpi:AAA*: + ID_VENDOR_FROM_DATABASE=Avolites Ltd + +acpi:AAC*: + ID_VENDOR_FROM_DATABASE=AcerView + +acpi:AAE*: + ID_VENDOR_FROM_DATABASE=Anatek Electronics Inc. + +acpi:AAM*: + ID_VENDOR_FROM_DATABASE=Aava Mobile Oy + +acpi:AAN*: + ID_VENDOR_FROM_DATABASE=AAEON Technology Inc. + +acpi:AAT*: + ID_VENDOR_FROM_DATABASE=Ann Arbor Technologies + +acpi:ABA*: + ID_VENDOR_FROM_DATABASE=ABBAHOME INC. + +acpi:ABC*: + ID_VENDOR_FROM_DATABASE=AboCom System Inc. + +acpi:ABD*: + ID_VENDOR_FROM_DATABASE=Allen Bradley Company + +acpi:ABE*: + ID_VENDOR_FROM_DATABASE=Alcatel Bell + +acpi:ABO*: + ID_VENDOR_FROM_DATABASE=D-Link Systems Inc + +acpi:ABP*: + ID_VENDOR_FROM_DATABASE=Advansys + +acpi:ABS*: + ID_VENDOR_FROM_DATABASE=Abaco Systems, Inc. + +acpi:ABT*: + ID_VENDOR_FROM_DATABASE=Anchor Bay Technologies, Inc. + +acpi:ABV*: + ID_VENDOR_FROM_DATABASE=Advanced Research Technology + +acpi:ACA*: + ID_VENDOR_FROM_DATABASE=Ariel Corporation + +acpi:ACB*: + ID_VENDOR_FROM_DATABASE=Aculab Ltd + +acpi:ACC*: + ID_VENDOR_FROM_DATABASE=Accton Technology Corporation + +acpi:ACD*: + ID_VENDOR_FROM_DATABASE=AWETA BV + +acpi:ACE*: + ID_VENDOR_FROM_DATABASE=Actek Engineering Pty Ltd + +acpi:ACG*: + ID_VENDOR_FROM_DATABASE=A&R Cambridge Ltd. + +acpi:ACH*: + ID_VENDOR_FROM_DATABASE=Archtek Telecom Corporation + +acpi:ACI*: + ID_VENDOR_FROM_DATABASE=Ancor Communications Inc + +acpi:ACK*: + ID_VENDOR_FROM_DATABASE=Acksys + +acpi:ACL*: + ID_VENDOR_FROM_DATABASE=Apricot Computers + +acpi:ACM*: + ID_VENDOR_FROM_DATABASE=Acroloop Motion Control Systems Inc + +acpi:ACO*: + ID_VENDOR_FROM_DATABASE=Allion Computer Inc. + +acpi:ACP[0-9A-F]*: + ID_VENDOR_FROM_DATABASE=Aspen Tech Inc + +acpi:ACR*: + ID_VENDOR_FROM_DATABASE=Acer Technologies + +acpi:ACS*: + ID_VENDOR_FROM_DATABASE=Altos Computer Systems + +acpi:ACT*: + ID_VENDOR_FROM_DATABASE=Applied Creative Technology + +acpi:ACU*: + ID_VENDOR_FROM_DATABASE=Acculogic + +acpi:ACV*: + ID_VENDOR_FROM_DATABASE=ActivCard S.A + +acpi:ADA*: + ID_VENDOR_FROM_DATABASE=Addi-Data GmbH + +acpi:ADB*: + ID_VENDOR_FROM_DATABASE=Aldebbaron + +acpi:ADC*: + ID_VENDOR_FROM_DATABASE=Acnhor Datacomm + +acpi:ADD*: + ID_VENDOR_FROM_DATABASE=Advanced Peripheral Devices Inc + +acpi:ADE*: + ID_VENDOR_FROM_DATABASE=Arithmos, Inc. + +acpi:ADH*: + ID_VENDOR_FROM_DATABASE=Aerodata Holdings Ltd + +acpi:ADI*: + ID_VENDOR_FROM_DATABASE=ADI Systems Inc + +acpi:ADK*: + ID_VENDOR_FROM_DATABASE=Adtek System Science Company Ltd + +acpi:ADL*: + ID_VENDOR_FROM_DATABASE=ASTRA Security Products Ltd + +acpi:ADM*: + ID_VENDOR_FROM_DATABASE=Ad Lib MultiMedia Inc + +acpi:ADN*: + ID_VENDOR_FROM_DATABASE=Analog & Digital Devices Tel. Inc + +acpi:ADP*: + ID_VENDOR_FROM_DATABASE=Adaptec Inc + +acpi:ADR*: + ID_VENDOR_FROM_DATABASE=Nasa Ames Research Center + +acpi:ADS*: + ID_VENDOR_FROM_DATABASE=Analog Devices Inc + +acpi:ADT*: + ID_VENDOR_FROM_DATABASE=Adtek + +acpi:ADV*: + ID_VENDOR_FROM_DATABASE=Advanced Micro Devices Inc + +acpi:ADX*: + ID_VENDOR_FROM_DATABASE=Adax Inc + +acpi:ADZ*: + ID_VENDOR_FROM_DATABASE=ADDER TECHNOLOGY LTD + +acpi:AEC*: + ID_VENDOR_FROM_DATABASE=Antex Electronics Corporation + +acpi:AED*: + ID_VENDOR_FROM_DATABASE=Advanced Electronic Designs, Inc. + +acpi:AEI*: + ID_VENDOR_FROM_DATABASE=Actiontec Electric Inc + +acpi:AEJ*: + ID_VENDOR_FROM_DATABASE=Alpha Electronics Company + +acpi:AEM*: + ID_VENDOR_FROM_DATABASE=ASEM S.p.A. + +acpi:AEN*: + ID_VENDOR_FROM_DATABASE=Avencall + +acpi:AEP*: + ID_VENDOR_FROM_DATABASE=Aetas Peripheral International + +acpi:AET*: + ID_VENDOR_FROM_DATABASE=Aethra Telecomunicazioni S.r.l. + +acpi:AFA*: + ID_VENDOR_FROM_DATABASE=Alfa Inc + +acpi:AGC*: + ID_VENDOR_FROM_DATABASE=Beijing Aerospace Golden Card Electronic Engineering Co.,Ltd. + +acpi:AGI*: + ID_VENDOR_FROM_DATABASE=Artish Graphics Inc + +acpi:AGL*: + ID_VENDOR_FROM_DATABASE=Argolis + +acpi:AGM*: + ID_VENDOR_FROM_DATABASE=Advan Int'l Corporation + +acpi:AGO*: + ID_VENDOR_FROM_DATABASE=AlgolTek, Inc. + +acpi:AGT*: + ID_VENDOR_FROM_DATABASE=Agilent Technologies + +acpi:AHC*: + ID_VENDOR_FROM_DATABASE=Advantech Co., Ltd. + +acpi:AHQ*: + ID_VENDOR_FROM_DATABASE=Astro HQ LLC + +acpi:AHS*: + ID_VENDOR_FROM_DATABASE=Beijing AnHeng SecoTech Information Technology Co., Ltd. + +acpi:AIC*: + ID_VENDOR_FROM_DATABASE=Arnos Insturments & Computer Systems + +acpi:AIE*: + ID_VENDOR_FROM_DATABASE=Altmann Industrieelektronik + +acpi:AII*: + ID_VENDOR_FROM_DATABASE=Amptron International Inc. + +acpi:AIK*: + ID_VENDOR_FROM_DATABASE=Dongguan Alllike Electronics Co., Ltd. + +acpi:AIL*: + ID_VENDOR_FROM_DATABASE=Altos India Ltd + +acpi:AIM*: + ID_VENDOR_FROM_DATABASE=AIMS Lab Inc + +acpi:AIR*: + ID_VENDOR_FROM_DATABASE=Advanced Integ. Research Inc + +acpi:AIS*: + ID_VENDOR_FROM_DATABASE=Alien Internet Services + +acpi:AIW*: + ID_VENDOR_FROM_DATABASE=Aiwa Company Ltd + +acpi:AIX*: + ID_VENDOR_FROM_DATABASE=ALTINEX, INC. + +acpi:AJA*: + ID_VENDOR_FROM_DATABASE=AJA Video Systems, Inc. + +acpi:AKB*: + ID_VENDOR_FROM_DATABASE=Akebia Ltd + +acpi:AKE*: + ID_VENDOR_FROM_DATABASE=AKAMI Electric Co.,Ltd + +acpi:AKI*: + ID_VENDOR_FROM_DATABASE=AKIA Corporation + +acpi:AKL*: + ID_VENDOR_FROM_DATABASE=AMiT Ltd + +acpi:AKM*: + ID_VENDOR_FROM_DATABASE=Asahi Kasei Microsystems Company Ltd + +acpi:AKP*: + ID_VENDOR_FROM_DATABASE=Atom Komplex Prylad + +acpi:AKY*: + ID_VENDOR_FROM_DATABASE=Askey Computer Corporation + +acpi:ALA*: + ID_VENDOR_FROM_DATABASE=Alacron Inc + +acpi:ALC*: + ID_VENDOR_FROM_DATABASE=Altec Corporation + +acpi:ALD*: + ID_VENDOR_FROM_DATABASE=In4S Inc + +acpi:ALE*: + ID_VENDOR_FROM_DATABASE=Alenco BV + +acpi:ALG*: + ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corp. + +acpi:ALH*: + ID_VENDOR_FROM_DATABASE=AL Systems + +acpi:ALI*: + ID_VENDOR_FROM_DATABASE=Acer Labs + +acpi:ALJ*: + ID_VENDOR_FROM_DATABASE=Altec Lansing + +acpi:ALK*: + ID_VENDOR_FROM_DATABASE=Acrolink Inc + +acpi:ALL*: + ID_VENDOR_FROM_DATABASE=Alliance Semiconductor Corporation + +acpi:ALM*: + ID_VENDOR_FROM_DATABASE=Acutec Ltd. + +acpi:ALN*: + ID_VENDOR_FROM_DATABASE=Alana Technologies + +acpi:ALO*: + ID_VENDOR_FROM_DATABASE=Algolith Inc. + +acpi:ALP*: + ID_VENDOR_FROM_DATABASE=Alps Electric Company Ltd + +acpi:ALR*: + ID_VENDOR_FROM_DATABASE=Advanced Logic + +acpi:ALS*: + ID_VENDOR_FROM_DATABASE=Avance Logic Inc + +acpi:ALT*: + ID_VENDOR_FROM_DATABASE=Altra + +acpi:ALV*: + ID_VENDOR_FROM_DATABASE=AlphaView LCD + +acpi:ALX*: + ID_VENDOR_FROM_DATABASE=ALEXON Co.,Ltd. + +acpi:AMA*: + ID_VENDOR_FROM_DATABASE=Asia Microelectronic Development Inc + +acpi:AMB*: + ID_VENDOR_FROM_DATABASE=Ambient Technologies, Inc. + +acpi:AMC*: + ID_VENDOR_FROM_DATABASE=Attachmate Corporation + +acpi:AMD*: + ID_VENDOR_FROM_DATABASE=Amdek Corporation + +acpi:AMI*: + ID_VENDOR_FROM_DATABASE=American Megatrends Inc + +acpi:AML*: + ID_VENDOR_FROM_DATABASE=Anderson Multimedia Communications (HK) Limited + +acpi:AMN*: + ID_VENDOR_FROM_DATABASE=Amimon LTD. + +acpi:AMO*: + ID_VENDOR_FROM_DATABASE=Amino Technologies PLC and Amino Communications Limited + +acpi:AMP*: + ID_VENDOR_FROM_DATABASE=AMP Inc + +acpi:AMR*: + ID_VENDOR_FROM_DATABASE=AmTRAN Technology Co., Ltd. + +acpi:AMS*: + ID_VENDOR_FROM_DATABASE=ARMSTEL, Inc. + +acpi:AMT*: + ID_VENDOR_FROM_DATABASE=AMT International Industry + +acpi:AMW*: + ID_VENDOR_FROM_DATABASE=AMW + +acpi:AMX*: + ID_VENDOR_FROM_DATABASE=AMX LLC + +acpi:ANA*: + ID_VENDOR_FROM_DATABASE=Anakron + +acpi:ANC*: + ID_VENDOR_FROM_DATABASE=Ancot + +acpi:AND*: + ID_VENDOR_FROM_DATABASE=Adtran Inc + +acpi:ANI*: + ID_VENDOR_FROM_DATABASE=Anigma Inc + +acpi:ANK*: + ID_VENDOR_FROM_DATABASE=Anko Electronic Company Ltd + +acpi:ANL*: + ID_VENDOR_FROM_DATABASE=Analogix Semiconductor, Inc + +acpi:ANO*: + ID_VENDOR_FROM_DATABASE=Anorad Corporation + +acpi:ANP*: + ID_VENDOR_FROM_DATABASE=Andrew Network Production + +acpi:ANR*: + ID_VENDOR_FROM_DATABASE=ANR Ltd + +acpi:ANS*: + ID_VENDOR_FROM_DATABASE=Ansel Communication Company + +acpi:ANT*: + ID_VENDOR_FROM_DATABASE=Ace CAD Enterprise Company Ltd + +acpi:ANV*: + ID_VENDOR_FROM_DATABASE=Beijing ANTVR Technology Co., Ltd. + +acpi:ANW*: + ID_VENDOR_FROM_DATABASE=Analog Way SAS + +acpi:ANX*: + ID_VENDOR_FROM_DATABASE=Acer Netxus Inc + +acpi:AOA*: + ID_VENDOR_FROM_DATABASE=AOpen Inc. + +acpi:AOC*: + ID_VENDOR_FROM_DATABASE=AOC + +acpi:AOE*: + ID_VENDOR_FROM_DATABASE=Advanced Optics Electronics, Inc. + +acpi:AOL*: + ID_VENDOR_FROM_DATABASE=America OnLine + +acpi:AOT*: + ID_VENDOR_FROM_DATABASE=Alcatel + +acpi:APA*: + ID_VENDOR_FROM_DATABASE=Adaptec + +acpi:APC*: + ID_VENDOR_FROM_DATABASE=American Power Conversion + +acpi:APD*: + ID_VENDOR_FROM_DATABASE=AppliAdata + +acpi:APE*: + ID_VENDOR_FROM_DATABASE=Alpine Electronics, Inc. + +acpi:APG*: + ID_VENDOR_FROM_DATABASE=Horner Electric Inc + +acpi:API*: + ID_VENDOR_FROM_DATABASE=A Plus Info Corporation + +acpi:APL*: + ID_VENDOR_FROM_DATABASE=Aplicom Oy + +acpi:APM*: + ID_VENDOR_FROM_DATABASE=Applied Memory Tech + +acpi:APN*: + ID_VENDOR_FROM_DATABASE=Appian Tech Inc + +acpi:APP*: + ID_VENDOR_FROM_DATABASE=Apple Computer Inc + +acpi:APR*: + ID_VENDOR_FROM_DATABASE=Aprilia s.p.a. + +acpi:APS*: + ID_VENDOR_FROM_DATABASE=Autologic Inc + +acpi:APT*: + ID_VENDOR_FROM_DATABASE=Audio Processing Technology Ltd + +acpi:APV*: + ID_VENDOR_FROM_DATABASE=A+V Link + +acpi:APX*: + ID_VENDOR_FROM_DATABASE=AP Designs Ltd + +acpi:ARC*: + ID_VENDOR_FROM_DATABASE=Alta Research Corporation + +acpi:ARD*: + ID_VENDOR_FROM_DATABASE=AREC Inc. + +acpi:ARE*: + ID_VENDOR_FROM_DATABASE=ICET S.p.A. + +acpi:ARG*: + ID_VENDOR_FROM_DATABASE=Argus Electronics Co., LTD + +acpi:ARI*: + ID_VENDOR_FROM_DATABASE=Argosy Research Inc + +acpi:ARK*: + ID_VENDOR_FROM_DATABASE=Ark Logic Inc + +acpi:ARL*: + ID_VENDOR_FROM_DATABASE=Arlotto Comnet Inc + +acpi:ARM*: + ID_VENDOR_FROM_DATABASE=Arima + +acpi:ARO*: + ID_VENDOR_FROM_DATABASE=Poso International B.V. + +acpi:ARR*: + ID_VENDOR_FROM_DATABASE=ARRIS Group, Inc. + +acpi:ARS*: + ID_VENDOR_FROM_DATABASE=Arescom Inc + +acpi:ART*: + ID_VENDOR_FROM_DATABASE=Corion Industrial Corporation + +acpi:ASC*: + ID_VENDOR_FROM_DATABASE=Ascom Strategic Technology Unit + +acpi:ASD*: + ID_VENDOR_FROM_DATABASE=USC Information Sciences Institute + +acpi:ASE*: + ID_VENDOR_FROM_DATABASE=AseV Display Labs + +acpi:ASH*: + ID_VENDOR_FROM_DATABASE=Ashton Bentley Concepts + +acpi:ASI*: + ID_VENDOR_FROM_DATABASE=Ahead Systems + +acpi:ASK*: + ID_VENDOR_FROM_DATABASE=Ask A/S + +acpi:ASL*: + ID_VENDOR_FROM_DATABASE=AccuScene Corporation Ltd + +acpi:ASM*: + ID_VENDOR_FROM_DATABASE=ASEM S.p.A. + +acpi:ASN*: + ID_VENDOR_FROM_DATABASE=Asante Tech Inc + +acpi:ASP*: + ID_VENDOR_FROM_DATABASE=ASP Microelectronics Ltd + +acpi:AST*: + ID_VENDOR_FROM_DATABASE=AST Research Inc + +acpi:ASU*: + ID_VENDOR_FROM_DATABASE=Asuscom Network Inc + +acpi:ASX*: + ID_VENDOR_FROM_DATABASE=AudioScience + +acpi:ASY*: + ID_VENDOR_FROM_DATABASE=Rockwell Collins / Airshow Systems + +acpi:ATA*: + ID_VENDOR_FROM_DATABASE=Allied Telesyn International (Asia) Pte Ltd + +acpi:ATC*: + ID_VENDOR_FROM_DATABASE=Ably-Tech Corporation + +acpi:ATD*: + ID_VENDOR_FROM_DATABASE=Alpha Telecom Inc + +acpi:ATE*: + ID_VENDOR_FROM_DATABASE=Innovate Ltd + +acpi:ATH*: + ID_VENDOR_FROM_DATABASE=Athena Informatica S.R.L. + +acpi:ATI*: + ID_VENDOR_FROM_DATABASE=Allied Telesis KK + +acpi:ATJ*: + ID_VENDOR_FROM_DATABASE=ArchiTek Corporation + +acpi:ATK*: + ID_VENDOR_FROM_DATABASE=Allied Telesyn Int'l + +acpi:ATL*: + ID_VENDOR_FROM_DATABASE=Arcus Technology Ltd + +acpi:ATM*: + ID_VENDOR_FROM_DATABASE=ATM Ltd + +acpi:ATN*: + ID_VENDOR_FROM_DATABASE=Athena Smartcard Solutions Ltd. + +acpi:ATO*: + ID_VENDOR_FROM_DATABASE=ASTRO DESIGN, INC. + +acpi:ATP*: + ID_VENDOR_FROM_DATABASE=Alpha-Top Corporation + +acpi:ATT*: + ID_VENDOR_FROM_DATABASE=AT&T + +acpi:ATV*: + ID_VENDOR_FROM_DATABASE=Office Depot, Inc. + +acpi:ATX*: + ID_VENDOR_FROM_DATABASE=Athenix Corporation + +acpi:AUG*: + ID_VENDOR_FROM_DATABASE=August Home, Inc. + +acpi:AUI*: + ID_VENDOR_FROM_DATABASE=Alps Electric Inc + +acpi:AUO*: + ID_VENDOR_FROM_DATABASE=AU Optronics + +acpi:AUR*: + ID_VENDOR_FROM_DATABASE=Aureal Semiconductor + +acpi:AUS*: + ID_VENDOR_FROM_DATABASE=ASUSTek COMPUTER INC + +acpi:AUT*: + ID_VENDOR_FROM_DATABASE=Autotime Corporation + +acpi:AUV*: + ID_VENDOR_FROM_DATABASE=Auvidea GmbH + +acpi:AVA*: + ID_VENDOR_FROM_DATABASE=Avaya Communication + +acpi:AVC*: + ID_VENDOR_FROM_DATABASE=Auravision Corporation + +acpi:AVD*: + ID_VENDOR_FROM_DATABASE=Avid Electronics Corporation + +acpi:AVE*: + ID_VENDOR_FROM_DATABASE=Add Value Enterpises (Asia) Pte Ltd + +acpi:AVG*: + ID_VENDOR_FROM_DATABASE=Avegant Corporation + +acpi:AVI*: + ID_VENDOR_FROM_DATABASE=Nippon Avionics Co.,Ltd + +acpi:AVJ*: + ID_VENDOR_FROM_DATABASE=Atelier Vision Corporation + +acpi:AVL*: + ID_VENDOR_FROM_DATABASE=Avalue Technology Inc. + +acpi:AVM*: + ID_VENDOR_FROM_DATABASE=AVM GmbH + +acpi:AVN*: + ID_VENDOR_FROM_DATABASE=Advance Computer Corporation + +acpi:AVO*: + ID_VENDOR_FROM_DATABASE=Avocent Corporation + +acpi:AVR*: + ID_VENDOR_FROM_DATABASE=AVer Information Inc. + +acpi:AVS*: + ID_VENDOR_FROM_DATABASE=Avatron Software Inc. + +acpi:AVT*: + ID_VENDOR_FROM_DATABASE=Avtek (Electronics) Pty Ltd + +acpi:AVV*: + ID_VENDOR_FROM_DATABASE=SBS Technologies (Canada), Inc. (was Avvida Systems, Inc.) + +acpi:AVX*: + ID_VENDOR_FROM_DATABASE=A/Vaux Electronics + +acpi:AWC*: + ID_VENDOR_FROM_DATABASE=Access Works Comm Inc + +acpi:AWL*: + ID_VENDOR_FROM_DATABASE=Aironet Wireless Communications, Inc + +acpi:AWS*: + ID_VENDOR_FROM_DATABASE=Wave Systems + +acpi:AXB*: + ID_VENDOR_FROM_DATABASE=Adrienne Electronics Corporation + +acpi:AXC*: + ID_VENDOR_FROM_DATABASE=AXIOMTEK CO., LTD. + +acpi:AXE*: + ID_VENDOR_FROM_DATABASE=Axell Corporation + +acpi:AXE*: + ID_VENDOR_FROM_DATABASE=D-Link Systems Inc + +acpi:AXI*: + ID_VENDOR_FROM_DATABASE=American Magnetics + +acpi:AXL*: + ID_VENDOR_FROM_DATABASE=Axel + +acpi:AXO*: + ID_VENDOR_FROM_DATABASE=Axonic Labs LLC + +acpi:AXP*: + ID_VENDOR_FROM_DATABASE=American Express + +acpi:AXT*: + ID_VENDOR_FROM_DATABASE=Axtend Technologies Inc + +acpi:AXX*: + ID_VENDOR_FROM_DATABASE=Axxon Computer Corporation + +acpi:AXY*: + ID_VENDOR_FROM_DATABASE=AXYZ Automation Services, Inc + +acpi:AYD*: + ID_VENDOR_FROM_DATABASE=Aydin Displays + +acpi:AYR*: + ID_VENDOR_FROM_DATABASE=Airlib, Inc + +acpi:AZH*: + ID_VENDOR_FROM_DATABASE=Shenzhen three Connaught Information Technology Co., Ltd. (3nod Group) + +acpi:AZM*: + ID_VENDOR_FROM_DATABASE=AZ Middelheim - Radiotherapy + +acpi:AZT*: + ID_VENDOR_FROM_DATABASE=Aztech Systems Ltd + +acpi:BAC*: + ID_VENDOR_FROM_DATABASE=Biometric Access Corporation + +acpi:BAN*: + ID_VENDOR_FROM_DATABASE=Banyan + +acpi:BBB*: + ID_VENDOR_FROM_DATABASE=an-najah university + +acpi:BBH*: + ID_VENDOR_FROM_DATABASE=B&Bh + +acpi:BBL*: + ID_VENDOR_FROM_DATABASE=Brain Boxes Limited + +acpi:BBV*: + ID_VENDOR_FROM_DATABASE=BlueBox Video Limited + +acpi:BBX*: + ID_VENDOR_FROM_DATABASE=Black Box Corporation + +acpi:BCC*: + ID_VENDOR_FROM_DATABASE=Beaver Computer Corporaton + +acpi:BCD*: + ID_VENDOR_FROM_DATABASE=Barco GmbH + +acpi:BCI*: + ID_VENDOR_FROM_DATABASE=Broadata Communications Inc. + +acpi:BCM*: + ID_VENDOR_FROM_DATABASE=Broadcom + +acpi:BCQ*: + ID_VENDOR_FROM_DATABASE=Deutsche Telekom Berkom GmbH + +acpi:BCS*: + ID_VENDOR_FROM_DATABASE=Booria CAD/CAM systems + +acpi:BDO*: + ID_VENDOR_FROM_DATABASE=Brahler ICS + +acpi:BDR*: + ID_VENDOR_FROM_DATABASE=Blonder Tongue Labs, Inc. + +acpi:BDS*: + ID_VENDOR_FROM_DATABASE=Barco Display Systems + +acpi:BEC*: + ID_VENDOR_FROM_DATABASE=Beckhoff Automation + +acpi:BEI*: + ID_VENDOR_FROM_DATABASE=Beckworth Enterprises Inc + +acpi:BEK*: + ID_VENDOR_FROM_DATABASE=Beko Elektronik A.S. + +acpi:BEL*: + ID_VENDOR_FROM_DATABASE=Beltronic Industrieelektronik GmbH + +acpi:BEO*: + ID_VENDOR_FROM_DATABASE=Baug & Olufsen + +acpi:BFE*: + ID_VENDOR_FROM_DATABASE=B.F. Engineering Corporation + +acpi:BGB*: + ID_VENDOR_FROM_DATABASE=Barco Graphics N.V + +acpi:BGT*: + ID_VENDOR_FROM_DATABASE=Budzetron Inc + +acpi:BHZ*: + ID_VENDOR_FROM_DATABASE=BitHeadz, Inc. + +acpi:BIA*: + ID_VENDOR_FROM_DATABASE=Biamp Systems Corporation + +acpi:BIC*: + ID_VENDOR_FROM_DATABASE=Big Island Communications + +acpi:BII*: + ID_VENDOR_FROM_DATABASE=Boeckeler Instruments Inc + +acpi:BIL*: + ID_VENDOR_FROM_DATABASE=Billion Electric Company Ltd + +acpi:BIO*: + ID_VENDOR_FROM_DATABASE=BioLink Technologies International, Inc. + +acpi:BIT*: + ID_VENDOR_FROM_DATABASE=Bit 3 Computer + +acpi:BLD*: + ID_VENDOR_FROM_DATABASE=BILD INNOVATIVE TECHNOLOGY LLC + +acpi:BLI*: + ID_VENDOR_FROM_DATABASE=Busicom + +acpi:BLN*: + ID_VENDOR_FROM_DATABASE=BioLink Technologies + +acpi:BLP*: + ID_VENDOR_FROM_DATABASE=Bloomberg L.P. + +acpi:BMD*: + ID_VENDOR_FROM_DATABASE=Blackmagic Design + +acpi:BMI*: + ID_VENDOR_FROM_DATABASE=Benson Medical Instruments Company + +acpi:BML*: + ID_VENDOR_FROM_DATABASE=BIOMED Lab + +acpi:BMM*: + ID_VENDOR_FROM_DATABASE=BMM + +acpi:BMS*: + ID_VENDOR_FROM_DATABASE=BIOMEDISYS + +acpi:BNE*: + ID_VENDOR_FROM_DATABASE=Bull AB + +acpi:BNK*: + ID_VENDOR_FROM_DATABASE=Banksia Tech Pty Ltd + +acpi:BNO*: + ID_VENDOR_FROM_DATABASE=Bang & Olufsen + +acpi:BNQ*: + ID_VENDOR_FROM_DATABASE=BenQ Corporation + +acpi:BNS*: + ID_VENDOR_FROM_DATABASE=Boulder Nonlinear Systems + +acpi:BOB*: + ID_VENDOR_FROM_DATABASE=Rainy Orchard + +acpi:BOE*: + ID_VENDOR_FROM_DATABASE=BOE + +acpi:BOI*: + ID_VENDOR_FROM_DATABASE=NINGBO BOIGLE DIGITAL TECHNOLOGY CO.,LTD + +acpi:BOS*: + ID_VENDOR_FROM_DATABASE=BOS + +acpi:BPD*: + ID_VENDOR_FROM_DATABASE=Micro Solutions, Inc. + +acpi:BPS*: + ID_VENDOR_FROM_DATABASE=Barco, N.V. + +acpi:BPU*: + ID_VENDOR_FROM_DATABASE=Best Power + +acpi:BRA*: + ID_VENDOR_FROM_DATABASE=Braemac Pty Ltd + +acpi:BRC*: + ID_VENDOR_FROM_DATABASE=BARC + +acpi:BRG*: + ID_VENDOR_FROM_DATABASE=Bridge Information Co., Ltd + +acpi:BRI*: + ID_VENDOR_FROM_DATABASE=Boca Research Inc + +acpi:BRM*: + ID_VENDOR_FROM_DATABASE=Braemar Inc + +acpi:BRO*: + ID_VENDOR_FROM_DATABASE=BROTHER INDUSTRIES,LTD. + +acpi:BSE*: + ID_VENDOR_FROM_DATABASE=Bose Corporation + +acpi:BSG*: + ID_VENDOR_FROM_DATABASE=Robert Bosch GmbH + +acpi:BSL*: + ID_VENDOR_FROM_DATABASE=Biomedical Systems Laboratory + +acpi:BSN*: + ID_VENDOR_FROM_DATABASE=BRIGHTSIGN, LLC + +acpi:BST*: + ID_VENDOR_FROM_DATABASE=BodySound Technologies, Inc. + +acpi:BTC*: + ID_VENDOR_FROM_DATABASE=Bit 3 Computer + +acpi:BTE*: + ID_VENDOR_FROM_DATABASE=Brilliant Technology + +acpi:BTF*: + ID_VENDOR_FROM_DATABASE=Bitfield Oy + +acpi:BTI*: + ID_VENDOR_FROM_DATABASE=BusTech Inc + +acpi:BTO*: + ID_VENDOR_FROM_DATABASE=BioTao Ltd + +acpi:BUF*: + ID_VENDOR_FROM_DATABASE=Yasuhiko Shirai Melco Inc + +acpi:BUG*: + ID_VENDOR_FROM_DATABASE=B.U.G., Inc. + +acpi:BUJ*: + ID_VENDOR_FROM_DATABASE=ATI Tech Inc + +acpi:BUL*: + ID_VENDOR_FROM_DATABASE=Bull + +acpi:BUR*: + ID_VENDOR_FROM_DATABASE=Bernecker & Rainer Ind-Eletronik GmbH + +acpi:BUS*: + ID_VENDOR_FROM_DATABASE=BusTek + +acpi:BUT*: + ID_VENDOR_FROM_DATABASE=21ST CENTURY ENTERTAINMENT + +acpi:BWK*: + ID_VENDOR_FROM_DATABASE=Bitworks Inc. + +acpi:BXE*: + ID_VENDOR_FROM_DATABASE=Buxco Electronics + +acpi:BYD*: + ID_VENDOR_FROM_DATABASE=byd:sign corporation + +acpi:CAA*: + ID_VENDOR_FROM_DATABASE=Castles Automation Co., Ltd + +acpi:CAC*: + ID_VENDOR_FROM_DATABASE=CA & F Elettronica + +acpi:CAG*: + ID_VENDOR_FROM_DATABASE=CalComp + +acpi:CAI*: + ID_VENDOR_FROM_DATABASE=Canon Inc. + +acpi:CAL*: + ID_VENDOR_FROM_DATABASE=Acon + +acpi:CAM*: + ID_VENDOR_FROM_DATABASE=Cambridge Audio + +acpi:CAN*: + ID_VENDOR_FROM_DATABASE=Canopus Company Ltd + +acpi:CAR*: + ID_VENDOR_FROM_DATABASE=Cardinal Company Ltd + +acpi:CAS*: + ID_VENDOR_FROM_DATABASE=CASIO COMPUTER CO.,LTD + +acpi:CAT*: + ID_VENDOR_FROM_DATABASE=Consultancy in Advanced Technology + +acpi:CAV*: + ID_VENDOR_FROM_DATABASE=Cavium Networks, Inc + +acpi:CBI*: + ID_VENDOR_FROM_DATABASE=ComputerBoards Inc + +acpi:CBR*: + ID_VENDOR_FROM_DATABASE=Cebra Tech A/S + +acpi:CBT*: + ID_VENDOR_FROM_DATABASE=Cabletime Ltd + +acpi:CBX*: + ID_VENDOR_FROM_DATABASE=Cybex Computer Products Corporation + +acpi:CCC*: + ID_VENDOR_FROM_DATABASE=C-Cube Microsystems + +acpi:CCI*: + ID_VENDOR_FROM_DATABASE=Cache + +acpi:CCJ*: + ID_VENDOR_FROM_DATABASE=CONTEC CO.,LTD. + +acpi:CCL*: + ID_VENDOR_FROM_DATABASE=CCL/ITRI + +acpi:CCP*: + ID_VENDOR_FROM_DATABASE=Capetronic USA Inc + +acpi:CDC*: + ID_VENDOR_FROM_DATABASE=Core Dynamics Corporation + +acpi:CDD*: + ID_VENDOR_FROM_DATABASE=Convergent Data Devices + +acpi:CDE*: + ID_VENDOR_FROM_DATABASE=Colin.de + +acpi:CDG*: + ID_VENDOR_FROM_DATABASE=Christie Digital Systems Inc + +acpi:CDI*: + ID_VENDOR_FROM_DATABASE=Concept Development Inc + +acpi:CDK*: + ID_VENDOR_FROM_DATABASE=Cray Communications + +acpi:CDN*: + ID_VENDOR_FROM_DATABASE=Codenoll Technical Corporation + +acpi:CDP*: + ID_VENDOR_FROM_DATABASE=CalComp + +acpi:CDS*: + ID_VENDOR_FROM_DATABASE=Computer Diagnostic Systems + +acpi:CDT*: + ID_VENDOR_FROM_DATABASE=IBM Corporation + +acpi:CDV*: + ID_VENDOR_FROM_DATABASE=Convergent Design Inc. + +acpi:CEA*: + ID_VENDOR_FROM_DATABASE=Consumer Electronics Association + +acpi:CEC*: + ID_VENDOR_FROM_DATABASE=Chicony Electronics Company Ltd + +acpi:CED*: + ID_VENDOR_FROM_DATABASE=Cambridge Electronic Design Ltd + +acpi:CEF*: + ID_VENDOR_FROM_DATABASE=Cefar Digital Vision + +acpi:CEI*: + ID_VENDOR_FROM_DATABASE=Crestron Electronics, Inc. + +acpi:CEM*: + ID_VENDOR_FROM_DATABASE=MEC Electronics GmbH + +acpi:CEN*: + ID_VENDOR_FROM_DATABASE=Centurion Technologies P/L + +acpi:CEP*: + ID_VENDOR_FROM_DATABASE=C-DAC + +acpi:CER*: + ID_VENDOR_FROM_DATABASE=Ceronix + +acpi:CET*: + ID_VENDOR_FROM_DATABASE=TEC CORPORATION + +acpi:CFG*: + ID_VENDOR_FROM_DATABASE=Atlantis + +acpi:CGA*: + ID_VENDOR_FROM_DATABASE=Chunghwa Picture Tubes, LTD + +acpi:CGS*: + ID_VENDOR_FROM_DATABASE=Chyron Corp + +acpi:CGT*: + ID_VENDOR_FROM_DATABASE=congatec AG + +acpi:CHA*: + ID_VENDOR_FROM_DATABASE=Chase Research PLC + +acpi:CHC*: + ID_VENDOR_FROM_DATABASE=Chic Technology Corp. + +acpi:CHD*: + ID_VENDOR_FROM_DATABASE=ChangHong Electric Co.,Ltd + +acpi:CHE*: + ID_VENDOR_FROM_DATABASE=Acer Inc + +acpi:CHG*: + ID_VENDOR_FROM_DATABASE=Sichuan Changhong Electric CO, LTD. + +acpi:CHI*: + ID_VENDOR_FROM_DATABASE=Chrontel Inc + +acpi:CHL*: + ID_VENDOR_FROM_DATABASE=Chloride-R&D + +acpi:CHM*: + ID_VENDOR_FROM_DATABASE=CHIC TECHNOLOGY CORP. + +acpi:CHO*: + ID_VENDOR_FROM_DATABASE=Sichuang Changhong Corporation + +acpi:CHP*: + ID_VENDOR_FROM_DATABASE=CH Products + +acpi:CHR*: + ID_VENDOR_FROM_DATABASE=christmann informationstechnik + medien GmbH & Co. KG + +acpi:CHS*: + ID_VENDOR_FROM_DATABASE=Agentur Chairos + +acpi:CHT*: + ID_VENDOR_FROM_DATABASE=Chunghwa Picture Tubes,LTD. + +acpi:CHY*: + ID_VENDOR_FROM_DATABASE=Cherry GmbH + +acpi:CIC*: + ID_VENDOR_FROM_DATABASE=Comm. Intelligence Corporation + +acpi:CIE*: + ID_VENDOR_FROM_DATABASE=Convergent Engineering, Inc. + +acpi:CII*: + ID_VENDOR_FROM_DATABASE=Cromack Industries Inc + +acpi:CIL*: + ID_VENDOR_FROM_DATABASE=Citicom Infotech Private Limited + +acpi:CIN*: + ID_VENDOR_FROM_DATABASE=Citron GmbH + +acpi:CIP*: + ID_VENDOR_FROM_DATABASE=Ciprico Inc + +acpi:CIR*: + ID_VENDOR_FROM_DATABASE=Cirrus Logic Inc + +acpi:CIS*: + ID_VENDOR_FROM_DATABASE=Cisco Systems Inc + +acpi:CIT*: + ID_VENDOR_FROM_DATABASE=Citifax Limited + +acpi:CKC*: + ID_VENDOR_FROM_DATABASE=The Concept Keyboard Company Ltd + +acpi:CKJ*: + ID_VENDOR_FROM_DATABASE=Carina System Co., Ltd. + +acpi:CLA*: + ID_VENDOR_FROM_DATABASE=Clarion Company Ltd + +acpi:CLD*: + ID_VENDOR_FROM_DATABASE=COMMAT L.t.d. + +acpi:CLE*: + ID_VENDOR_FROM_DATABASE=Classe Audio + +acpi:CLG*: + ID_VENDOR_FROM_DATABASE=CoreLogic + +acpi:CLI*: + ID_VENDOR_FROM_DATABASE=Cirrus Logic Inc + +acpi:CLM*: + ID_VENDOR_FROM_DATABASE=CrystaLake Multimedia + +acpi:CLO*: + ID_VENDOR_FROM_DATABASE=Clone Computers + +acpi:CLT*: + ID_VENDOR_FROM_DATABASE=automated computer control systems + +acpi:CLV*: + ID_VENDOR_FROM_DATABASE=Clevo Company + +acpi:CLX*: + ID_VENDOR_FROM_DATABASE=CardLogix + +acpi:CMC*: + ID_VENDOR_FROM_DATABASE=CMC Ltd + +acpi:CMD*: + ID_VENDOR_FROM_DATABASE=Colorado MicroDisplay, Inc. + +acpi:CMG*: + ID_VENDOR_FROM_DATABASE=Chenming Mold Ind. Corp. + +acpi:CMI*: + ID_VENDOR_FROM_DATABASE=C-Media Electronics + +acpi:CMM*: + ID_VENDOR_FROM_DATABASE=Comtime GmbH + +acpi:CMN*: + ID_VENDOR_FROM_DATABASE=Chimei Innolux Corporation + +acpi:CMO*: + ID_VENDOR_FROM_DATABASE=Chi Mei Optoelectronics corp. + +acpi:CMR*: + ID_VENDOR_FROM_DATABASE=Cambridge Research Systems Ltd + +acpi:CMS*: + ID_VENDOR_FROM_DATABASE=CompuMaster Srl + +acpi:CMX*: + ID_VENDOR_FROM_DATABASE=Comex Electronics AB + +acpi:CNB*: + ID_VENDOR_FROM_DATABASE=American Power Conversion + +acpi:CNC*: + ID_VENDOR_FROM_DATABASE=Alvedon Computers Ltd + +acpi:CNE*: + ID_VENDOR_FROM_DATABASE=Cine-tal + +acpi:CNI*: + ID_VENDOR_FROM_DATABASE=Connect Int'l A/S + +acpi:CNN*: + ID_VENDOR_FROM_DATABASE=Canon Inc + +acpi:CNT*: + ID_VENDOR_FROM_DATABASE=COINT Multimedia Systems + +acpi:COB*: + ID_VENDOR_FROM_DATABASE=COBY Electronics Co., Ltd + +acpi:COD*: + ID_VENDOR_FROM_DATABASE=CODAN Pty. Ltd. + +acpi:COG*: + ID_VENDOR_FROM_DATABASE=Cogent + +acpi:COI*: + ID_VENDOR_FROM_DATABASE=Codec Inc. + +acpi:COL*: + ID_VENDOR_FROM_DATABASE=Rockwell Collins, Inc. + +acpi:COM*: + ID_VENDOR_FROM_DATABASE=Comtrol Corporation + +acpi:CON*: + ID_VENDOR_FROM_DATABASE=Contec Company Ltd + +acpi:COO*: + ID_VENDOR_FROM_DATABASE=coolux GmbH + +acpi:COR*: + ID_VENDOR_FROM_DATABASE=Corollary Inc + +acpi:COS*: + ID_VENDOR_FROM_DATABASE=CoStar Corporation + +acpi:COT*: + ID_VENDOR_FROM_DATABASE=Core Technology Inc + +acpi:COW*: + ID_VENDOR_FROM_DATABASE=Polycow Productions + +acpi:COX*: + ID_VENDOR_FROM_DATABASE=Comrex + +acpi:CPC*: + ID_VENDOR_FROM_DATABASE=Ciprico Inc + +acpi:CPD*: + ID_VENDOR_FROM_DATABASE=CompuAdd + +acpi:CPI*: + ID_VENDOR_FROM_DATABASE=Computer Peripherals Inc + +acpi:CPL*: + ID_VENDOR_FROM_DATABASE=Compal Electronics Inc + +acpi:CPM*: + ID_VENDOR_FROM_DATABASE=Capella Microsystems Inc. + +acpi:CPP*: + ID_VENDOR_FROM_DATABASE=Compound Photonics + +acpi:CPQ*: + ID_VENDOR_FROM_DATABASE=Compaq Computer Company + +acpi:CPT*: + ID_VENDOR_FROM_DATABASE=cPATH + +acpi:CPX*: + ID_VENDOR_FROM_DATABASE=Powermatic Data Systems + +acpi:CRA*: + ID_VENDOR_FROM_DATABASE=CRALTECH ELECTRONICA, S.L. + +acpi:CRC*: + ID_VENDOR_FROM_DATABASE=CONRAC GmbH + +acpi:CRD*: + ID_VENDOR_FROM_DATABASE=Cardinal Technical Inc + +acpi:CRE*: + ID_VENDOR_FROM_DATABASE=Creative Labs Inc + +acpi:CRH*: + ID_VENDOR_FROM_DATABASE=Contemporary Research Corp. + +acpi:CRI*: + ID_VENDOR_FROM_DATABASE=Crio Inc. + +acpi:CRL*: + ID_VENDOR_FROM_DATABASE=Creative Logic + +acpi:CRN*: + ID_VENDOR_FROM_DATABASE=Cornerstone Imaging + +acpi:CRO*: + ID_VENDOR_FROM_DATABASE=Extraordinary Technologies PTY Limited + +acpi:CRQ*: + ID_VENDOR_FROM_DATABASE=Cirque Corporation + +acpi:CRS*: + ID_VENDOR_FROM_DATABASE=Crescendo Communication Inc + +acpi:CRV*: + ID_VENDOR_FROM_DATABASE=Cerevo Inc. + +acpi:CRW*: + ID_VENDOR_FROM_DATABASE=Cammegh Limited + +acpi:CRX*: + ID_VENDOR_FROM_DATABASE=Cyrix Corporation + +acpi:CSB*: + ID_VENDOR_FROM_DATABASE=Transtex SA + +acpi:CSC*: + ID_VENDOR_FROM_DATABASE=Crystal Semiconductor + +acpi:CSD*: + ID_VENDOR_FROM_DATABASE=Cresta Systems Inc + +acpi:CSE*: + ID_VENDOR_FROM_DATABASE=Concept Solutions & Engineering + +acpi:CSI*: + ID_VENDOR_FROM_DATABASE=Cabletron System Inc + +acpi:CSL*: + ID_VENDOR_FROM_DATABASE=Cloudium Systems Ltd. + +acpi:CSM*: + ID_VENDOR_FROM_DATABASE=Cosmic Engineering Inc. + +acpi:CSO*: + ID_VENDOR_FROM_DATABASE=California Institute of Technology + +acpi:CSS*: + ID_VENDOR_FROM_DATABASE=CSS Laboratories + +acpi:CST*: + ID_VENDOR_FROM_DATABASE=CSTI Inc + +acpi:CTA*: + ID_VENDOR_FROM_DATABASE=CoSystems Inc + +acpi:CTC*: + ID_VENDOR_FROM_DATABASE=CTC Communication Development Company Ltd + +acpi:CTE*: + ID_VENDOR_FROM_DATABASE=Chunghwa Telecom Co., Ltd. + +acpi:CTL*: + ID_VENDOR_FROM_DATABASE=Creative Technology Ltd + +acpi:CTM*: + ID_VENDOR_FROM_DATABASE=Computerm Corporation + +acpi:CTN*: + ID_VENDOR_FROM_DATABASE=Computone Products + +acpi:CTP*: + ID_VENDOR_FROM_DATABASE=Computer Technology Corporation + +acpi:CTR*: + ID_VENDOR_FROM_DATABASE=Control4 Corporation + +acpi:CTS*: + ID_VENDOR_FROM_DATABASE=Comtec Systems Co., Ltd. + +acpi:CTX*: + ID_VENDOR_FROM_DATABASE=Creatix Polymedia GmbH + +acpi:CUB*: + ID_VENDOR_FROM_DATABASE=Cubix Corporation + +acpi:CUK*: + ID_VENDOR_FROM_DATABASE=Calibre UK Ltd + +acpi:CVA*: + ID_VENDOR_FROM_DATABASE=Covia Inc. + +acpi:CVI*: + ID_VENDOR_FROM_DATABASE=Colorado Video, Inc. + +acpi:CVP*: + ID_VENDOR_FROM_DATABASE=Chromatec Video Products Ltd + +acpi:CVS*: + ID_VENDOR_FROM_DATABASE=Clarity Visual Systems + +acpi:CWC*: + ID_VENDOR_FROM_DATABASE=Curtiss-Wright Controls, Inc. + +acpi:CWR*: + ID_VENDOR_FROM_DATABASE=Connectware Inc + +acpi:CXT*: + ID_VENDOR_FROM_DATABASE=Conexant Systems + +acpi:CYB*: + ID_VENDOR_FROM_DATABASE=CyberVision + +acpi:CYC*: + ID_VENDOR_FROM_DATABASE=Cylink Corporation + +acpi:CYD*: + ID_VENDOR_FROM_DATABASE=Cyclades Corporation + +acpi:CYL*: + ID_VENDOR_FROM_DATABASE=Cyberlabs + +acpi:CYP*: + ID_VENDOR_FROM_DATABASE=CYPRESS SEMICONDUCTOR CORPORATION + +acpi:CYT*: + ID_VENDOR_FROM_DATABASE=Cytechinfo Inc + +acpi:CYV*: + ID_VENDOR_FROM_DATABASE=Cyviz AS + +acpi:CYW*: + ID_VENDOR_FROM_DATABASE=Cyberware + +acpi:CYX*: + ID_VENDOR_FROM_DATABASE=Cyrix Corporation + +acpi:CZC*: + ID_VENDOR_FROM_DATABASE=Shenzhen ChuangZhiCheng Technology Co., Ltd. + +acpi:CZE*: + ID_VENDOR_FROM_DATABASE=Carl Zeiss AG + +acpi:DAC*: + ID_VENDOR_FROM_DATABASE=Digital Acoustics Corporation + +acpi:DAE*: + ID_VENDOR_FROM_DATABASE=Digatron Industrie Elektronik GmbH + +acpi:DAI*: + ID_VENDOR_FROM_DATABASE=DAIS SET Ltd. + +acpi:DAK*: + ID_VENDOR_FROM_DATABASE=Daktronics + +acpi:DAL*: + ID_VENDOR_FROM_DATABASE=Digital Audio Labs Inc + +acpi:DAN*: + ID_VENDOR_FROM_DATABASE=Danelec Marine A/S + +acpi:DAS*: + ID_VENDOR_FROM_DATABASE=DAVIS AS + +acpi:DAT*: + ID_VENDOR_FROM_DATABASE=Datel Inc + +acpi:DAU*: + ID_VENDOR_FROM_DATABASE=Daou Tech Inc + +acpi:DAV*: + ID_VENDOR_FROM_DATABASE=Davicom Semiconductor Inc + +acpi:DAW*: + ID_VENDOR_FROM_DATABASE=DA2 Technologies Inc + +acpi:DAX*: + ID_VENDOR_FROM_DATABASE=Data Apex Ltd + +acpi:DBD*: + ID_VENDOR_FROM_DATABASE=Diebold Inc. + +acpi:DBI*: + ID_VENDOR_FROM_DATABASE=DigiBoard Inc + +acpi:DBK*: + ID_VENDOR_FROM_DATABASE=Databook Inc + +acpi:DBL*: + ID_VENDOR_FROM_DATABASE=Doble Engineering Company + +acpi:DBN*: + ID_VENDOR_FROM_DATABASE=DB Networks Inc + +acpi:DCA*: + ID_VENDOR_FROM_DATABASE=Digital Communications Association + +acpi:DCC*: + ID_VENDOR_FROM_DATABASE=Dale Computer Corporation + +acpi:DCD*: + ID_VENDOR_FROM_DATABASE=Datacast LLC + +acpi:DCE*: + ID_VENDOR_FROM_DATABASE=dSPACE GmbH + +acpi:DCI*: + ID_VENDOR_FROM_DATABASE=Concepts Inc + +acpi:DCL*: + ID_VENDOR_FROM_DATABASE=Dynamic Controls Ltd + +acpi:DCM*: + ID_VENDOR_FROM_DATABASE=DCM Data Products + +acpi:DCO*: + ID_VENDOR_FROM_DATABASE=Dialogue Technology Corporation + +acpi:DCR*: + ID_VENDOR_FROM_DATABASE=Decros Ltd + +acpi:DCS*: + ID_VENDOR_FROM_DATABASE=Diamond Computer Systems Inc + +acpi:DCT*: + ID_VENDOR_FROM_DATABASE=Dancall Telecom A/S + +acpi:DCV*: + ID_VENDOR_FROM_DATABASE=Datatronics Technology Inc + +acpi:DDA*: + ID_VENDOR_FROM_DATABASE=DA2 Technologies Corporation + +acpi:DDD*: + ID_VENDOR_FROM_DATABASE=Danka Data Devices + +acpi:DDE*: + ID_VENDOR_FROM_DATABASE=Datasat Digital Entertainment + +acpi:DDI*: + ID_VENDOR_FROM_DATABASE=Data Display AG + +acpi:DDS*: + ID_VENDOR_FROM_DATABASE=Barco, N.V. + +acpi:DDT*: + ID_VENDOR_FROM_DATABASE=Datadesk Technologies Inc + +acpi:DDV*: + ID_VENDOR_FROM_DATABASE=Delta Information Systems, Inc + +acpi:DEC*: + ID_VENDOR_FROM_DATABASE=Digital Equipment Corporation + +acpi:DEI*: + ID_VENDOR_FROM_DATABASE=Deico Electronics + +acpi:DEL*: + ID_VENDOR_FROM_DATABASE=Dell Inc. + +acpi:DEN*: + ID_VENDOR_FROM_DATABASE=Densitron Computers Ltd + +acpi:DEX*: + ID_VENDOR_FROM_DATABASE=idex displays + +acpi:DFI*: + ID_VENDOR_FROM_DATABASE=DFI + +acpi:DFK*: + ID_VENDOR_FROM_DATABASE=SharkTec A/S + +acpi:DFT*: + ID_VENDOR_FROM_DATABASE=DEI Holdings dba Definitive Technology + +acpi:DGA*: + ID_VENDOR_FROM_DATABASE=Digiital Arts Inc + +acpi:DGC*: + ID_VENDOR_FROM_DATABASE=Data General Corporation + +acpi:DGI*: + ID_VENDOR_FROM_DATABASE=DIGI International + +acpi:DGK*: + ID_VENDOR_FROM_DATABASE=DugoTech Co., LTD + +acpi:DGP*: + ID_VENDOR_FROM_DATABASE=Digicorp European sales S.A. + +acpi:DGS*: + ID_VENDOR_FROM_DATABASE=Diagsoft Inc + +acpi:DGT*: + ID_VENDOR_FROM_DATABASE=Dearborn Group Technology + +acpi:DHD*: + ID_VENDOR_FROM_DATABASE=Dension Audio Systems + +acpi:DHP*: + ID_VENDOR_FROM_DATABASE=DH Print + +acpi:DHQ*: + ID_VENDOR_FROM_DATABASE=Quadram + +acpi:DHT*: + ID_VENDOR_FROM_DATABASE=Projectavision Inc + +acpi:DIA*: + ID_VENDOR_FROM_DATABASE=Diadem + +acpi:DIG*: + ID_VENDOR_FROM_DATABASE=Digicom S.p.A. + +acpi:DII*: + ID_VENDOR_FROM_DATABASE=Dataq Instruments Inc + +acpi:DIM*: + ID_VENDOR_FROM_DATABASE=dPict Imaging, Inc. + +acpi:DIN*: + ID_VENDOR_FROM_DATABASE=Daintelecom Co., Ltd + +acpi:DIS*: + ID_VENDOR_FROM_DATABASE=Diseda S.A. + +acpi:DIT*: + ID_VENDOR_FROM_DATABASE=Dragon Information Technology + +acpi:DJE*: + ID_VENDOR_FROM_DATABASE=Capstone Visual Product Development + +acpi:DJP*: + ID_VENDOR_FROM_DATABASE=Maygay Machines, Ltd + +acpi:DKY*: + ID_VENDOR_FROM_DATABASE=Datakey Inc + +acpi:DLB*: + ID_VENDOR_FROM_DATABASE=Dolby Laboratories Inc. + +acpi:DLC*: + ID_VENDOR_FROM_DATABASE=Diamond Lane Comm. Corporation + +acpi:DLG*: + ID_VENDOR_FROM_DATABASE=Digital-Logic GmbH + +acpi:DLK*: + ID_VENDOR_FROM_DATABASE=D-Link Systems Inc + +acpi:DLL*: + ID_VENDOR_FROM_DATABASE=Dell Inc + +acpi:DLO*: + ID_VENDOR_FROM_DATABASE=Shenzhen Dlodlo Technologies Co., Ltd. + +acpi:DLT*: + ID_VENDOR_FROM_DATABASE=Digitelec Informatique Park Cadera + +acpi:DMB*: + ID_VENDOR_FROM_DATABASE=Digicom Systems Inc + +acpi:DMC*: + ID_VENDOR_FROM_DATABASE=Dune Microsystems Corporation + +acpi:DMM*: + ID_VENDOR_FROM_DATABASE=Dimond Multimedia Systems Inc + +acpi:DMN*: + ID_VENDOR_FROM_DATABASE=Dimension Engineering LLC + +acpi:DMO*: + ID_VENDOR_FROM_DATABASE=Data Modul AG + +acpi:DMP*: + ID_VENDOR_FROM_DATABASE=D&M Holdings Inc, Professional Business Company + +acpi:DMS*: + ID_VENDOR_FROM_DATABASE=DOME imaging systems + +acpi:DMT*: + ID_VENDOR_FROM_DATABASE=Distributed Management Task Force, Inc. (DMTF) + +acpi:DMV*: + ID_VENDOR_FROM_DATABASE=NDS Ltd + +acpi:DNA*: + ID_VENDOR_FROM_DATABASE=DNA Enterprises, Inc. + +acpi:DNG*: + ID_VENDOR_FROM_DATABASE=Apache Micro Peripherals Inc + +acpi:DNI*: + ID_VENDOR_FROM_DATABASE=Deterministic Networks Inc. + +acpi:DNT*: + ID_VENDOR_FROM_DATABASE=Dr. Neuhous Telekommunikation GmbH + +acpi:DNV*: + ID_VENDOR_FROM_DATABASE=DiCon + +acpi:DOL*: + ID_VENDOR_FROM_DATABASE=Dolman Technologies Group Inc + +acpi:DOM*: + ID_VENDOR_FROM_DATABASE=Dome Imaging Systems + +acpi:DON*: + ID_VENDOR_FROM_DATABASE=DENON, Ltd. + +acpi:DOT*: + ID_VENDOR_FROM_DATABASE=Dotronic Mikroelektronik GmbH + +acpi:DPA*: + ID_VENDOR_FROM_DATABASE=DigiTalk Pro AV + +acpi:DPC*: + ID_VENDOR_FROM_DATABASE=Delta Electronics Inc + +acpi:DPH*: + ID_VENDOR_FROM_DATABASE=Delphi Automotive LLP + +acpi:DPI*: + ID_VENDOR_FROM_DATABASE=DocuPoint + +acpi:DPL*: + ID_VENDOR_FROM_DATABASE=Digital Projection Limited + +acpi:DPM*: + ID_VENDOR_FROM_DATABASE=ADPM Synthesis sas + +acpi:DPN*: + ID_VENDOR_FROM_DATABASE=Shanghai Lexiang Technology Limited + +acpi:DPS*: + ID_VENDOR_FROM_DATABASE=Digital Processing Systems + +acpi:DPT*: + ID_VENDOR_FROM_DATABASE=DPT + +acpi:DPX*: + ID_VENDOR_FROM_DATABASE=DpiX, Inc. + +acpi:DQB*: + ID_VENDOR_FROM_DATABASE=Datacube Inc + +acpi:DRB*: + ID_VENDOR_FROM_DATABASE=Dr. Bott KG + +acpi:DRC*: + ID_VENDOR_FROM_DATABASE=Data Ray Corp. + +acpi:DRD*: + ID_VENDOR_FROM_DATABASE=DIGITAL REFLECTION INC. + +acpi:DRI*: + ID_VENDOR_FROM_DATABASE=Data Race Inc + +acpi:DRS*: + ID_VENDOR_FROM_DATABASE=DRS Defense Solutions, LLC + +acpi:DSA*: + ID_VENDOR_FROM_DATABASE=Display Solution AG + +acpi:DSD*: + ID_VENDOR_FROM_DATABASE=DS Multimedia Pte Ltd + +acpi:DSG*: + ID_VENDOR_FROM_DATABASE=Disguise Technologies + +acpi:DSI*: + ID_VENDOR_FROM_DATABASE=Digitan Systems Inc + +acpi:DSJ*: + ID_VENDOR_FROM_DATABASE=VR Technology Holdings Limited + +acpi:DSM*: + ID_VENDOR_FROM_DATABASE=DSM Digital Services GmbH + +acpi:DSP*: + ID_VENDOR_FROM_DATABASE=Domain Technology Inc + +acpi:DTA*: + ID_VENDOR_FROM_DATABASE=DELTATEC + +acpi:DTC*: + ID_VENDOR_FROM_DATABASE=DTC Tech Corporation + +acpi:DTE*: + ID_VENDOR_FROM_DATABASE=Dimension Technologies, Inc. + +acpi:DTI*: + ID_VENDOR_FROM_DATABASE=Diversified Technology, Inc. + +acpi:DTK*: + ID_VENDOR_FROM_DATABASE=Dynax Electronics (HK) Ltd + +acpi:DTL*: + ID_VENDOR_FROM_DATABASE=e-Net Inc + +acpi:DTN*: + ID_VENDOR_FROM_DATABASE=Datang Telephone Co + +acpi:DTO*: + ID_VENDOR_FROM_DATABASE=Deutsche Thomson OHG + +acpi:DTT*: + ID_VENDOR_FROM_DATABASE=Design & Test Technology, Inc. + +acpi:DTX*: + ID_VENDOR_FROM_DATABASE=Data Translation + +acpi:DUA*: + ID_VENDOR_FROM_DATABASE=Dosch & Amand GmbH & Company KG + +acpi:DUN*: + ID_VENDOR_FROM_DATABASE=NCR Corporation + +acpi:DVD*: + ID_VENDOR_FROM_DATABASE=Dictaphone Corporation + +acpi:DVL*: + ID_VENDOR_FROM_DATABASE=Devolo AG + +acpi:DVS*: + ID_VENDOR_FROM_DATABASE=Digital Video System + +acpi:DVT*: + ID_VENDOR_FROM_DATABASE=Data Video + +acpi:DWE*: + ID_VENDOR_FROM_DATABASE=Daewoo Electronics Company Ltd + +acpi:DXC*: + ID_VENDOR_FROM_DATABASE=Digipronix Control Systems + +acpi:DXD*: + ID_VENDOR_FROM_DATABASE=DECIMATOR DESIGN PTY LTD + +acpi:DXL*: + ID_VENDOR_FROM_DATABASE=Dextera Labs Inc + +acpi:DXP*: + ID_VENDOR_FROM_DATABASE=Data Expert Corporation + +acpi:DXS*: + ID_VENDOR_FROM_DATABASE=Signet + +acpi:DYC*: + ID_VENDOR_FROM_DATABASE=Dycam Inc + +acpi:DYM*: + ID_VENDOR_FROM_DATABASE=Dymo-CoStar Corporation + +acpi:DYN*: + ID_VENDOR_FROM_DATABASE=Askey Computer Corporation + +acpi:DYX*: + ID_VENDOR_FROM_DATABASE=Dynax Electronics (HK) Ltd + +acpi:EAG*: + ID_VENDOR_FROM_DATABASE=ELTEC Elektronik AG + +acpi:EAS*: + ID_VENDOR_FROM_DATABASE=Evans and Sutherland Computer + +acpi:EBH*: + ID_VENDOR_FROM_DATABASE=Data Price Informatica + +acpi:EBS*: + ID_VENDOR_FROM_DATABASE=EBS Euchner Büro- und Schulsysteme GmbH + +acpi:EBT*: + ID_VENDOR_FROM_DATABASE=HUALONG TECHNOLOGY CO., LTD + +acpi:ECA*: + ID_VENDOR_FROM_DATABASE=Electro Cam Corp. + +acpi:ECC*: + ID_VENDOR_FROM_DATABASE=ESSential Comm. Corporation + +acpi:ECH*: + ID_VENDOR_FROM_DATABASE=EchoStar Corporation + +acpi:ECI*: + ID_VENDOR_FROM_DATABASE=Enciris Technologies + +acpi:ECK*: + ID_VENDOR_FROM_DATABASE=Eugene Chukhlomin Sole Proprietorship, d.b.a. + +acpi:ECL*: + ID_VENDOR_FROM_DATABASE=Excel Company Ltd + +acpi:ECM*: + ID_VENDOR_FROM_DATABASE=E-Cmos Tech Corporation + +acpi:ECO*: + ID_VENDOR_FROM_DATABASE=Echo Speech Corporation + +acpi:ECP*: + ID_VENDOR_FROM_DATABASE=Elecom Company Ltd + +acpi:ECS*: + ID_VENDOR_FROM_DATABASE=Elitegroup Computer Systems Company Ltd + +acpi:ECT*: + ID_VENDOR_FROM_DATABASE=Enciris Technologies + +acpi:EDC*: + ID_VENDOR_FROM_DATABASE=e.Digital Corporation + +acpi:EDG*: + ID_VENDOR_FROM_DATABASE=Electronic-Design GmbH + +acpi:EDI*: + ID_VENDOR_FROM_DATABASE=Edimax Tech. Company Ltd + +acpi:EDM*: + ID_VENDOR_FROM_DATABASE=EDMI + +acpi:EDT*: + ID_VENDOR_FROM_DATABASE=Emerging Display Technologies Corp + +acpi:EEE*: + ID_VENDOR_FROM_DATABASE=ET&T Technology Company Ltd + +acpi:EEH*: + ID_VENDOR_FROM_DATABASE=EEH Datalink GmbH + +acpi:EEP*: + ID_VENDOR_FROM_DATABASE=E.E.P.D. GmbH + +acpi:EES*: + ID_VENDOR_FROM_DATABASE=EE Solutions, Inc. + +acpi:EGA*: + ID_VENDOR_FROM_DATABASE=Elgato Systems LLC + +acpi:EGD*: + ID_VENDOR_FROM_DATABASE=EIZO GmbH Display Technologies + +acpi:EGL*: + ID_VENDOR_FROM_DATABASE=Eagle Technology + +acpi:EGN*: + ID_VENDOR_FROM_DATABASE=Egenera, Inc. + +acpi:EGO*: + ID_VENDOR_FROM_DATABASE=Ergo Electronics + +acpi:EHJ*: + ID_VENDOR_FROM_DATABASE=Epson Research + +acpi:EHN*: + ID_VENDOR_FROM_DATABASE=Enhansoft + +acpi:EIC*: + ID_VENDOR_FROM_DATABASE=Eicon Technology Corporation + +acpi:EIN*: + ID_VENDOR_FROM_DATABASE=Elegant Invention + +acpi:EIZ*: + ID_VENDOR_FROM_DATABASE=Eizo + +acpi:EKA*: + ID_VENDOR_FROM_DATABASE=MagTek Inc. + +acpi:EKC*: + ID_VENDOR_FROM_DATABASE=Eastman Kodak Company + +acpi:EKS*: + ID_VENDOR_FROM_DATABASE=EKSEN YAZILIM + +acpi:ELA*: + ID_VENDOR_FROM_DATABASE=ELAD srl + +acpi:ELC*: + ID_VENDOR_FROM_DATABASE=Electro Scientific Ind + +acpi:ELD*: + ID_VENDOR_FROM_DATABASE=Express Luck, Inc. + +acpi:ELE*: + ID_VENDOR_FROM_DATABASE=Elecom Company Ltd + +acpi:ELG*: + ID_VENDOR_FROM_DATABASE=Elmeg GmbH Kommunikationstechnik + +acpi:ELI*: + ID_VENDOR_FROM_DATABASE=Edsun Laboratories + +acpi:ELL*: + ID_VENDOR_FROM_DATABASE=Electrosonic Ltd + +acpi:ELM*: + ID_VENDOR_FROM_DATABASE=Elmic Systems Inc + +acpi:ELO*: + ID_VENDOR_FROM_DATABASE=Elo TouchSystems Inc + +acpi:ELS*: + ID_VENDOR_FROM_DATABASE=ELSA GmbH + +acpi:ELT*: + ID_VENDOR_FROM_DATABASE=Element Labs, Inc. + +acpi:ELU*: + ID_VENDOR_FROM_DATABASE=Express Industrial, Ltd. + +acpi:ELX*: + ID_VENDOR_FROM_DATABASE=Elonex PLC + +acpi:EMB*: + ID_VENDOR_FROM_DATABASE=Embedded computing inc ltd + +acpi:EMC*: + ID_VENDOR_FROM_DATABASE=eMicro Corporation + +acpi:EMD*: + ID_VENDOR_FROM_DATABASE=Embrionix Design Inc. + +acpi:EME*: + ID_VENDOR_FROM_DATABASE=EMiNE TECHNOLOGY COMPANY, LTD. + +acpi:EMG*: + ID_VENDOR_FROM_DATABASE=EMG Consultants Inc + +acpi:EMI*: + ID_VENDOR_FROM_DATABASE=Ex Machina Inc + +acpi:EMK*: + ID_VENDOR_FROM_DATABASE=Emcore Corporation + +acpi:EMO*: + ID_VENDOR_FROM_DATABASE=ELMO COMPANY, LIMITED + +acpi:EMU*: + ID_VENDOR_FROM_DATABASE=Emulex Corporation + +acpi:ENC*: + ID_VENDOR_FROM_DATABASE=Eizo Nanao Corporation + +acpi:END*: + ID_VENDOR_FROM_DATABASE=ENIDAN Technologies Ltd + +acpi:ENE*: + ID_VENDOR_FROM_DATABASE=ENE Technology Inc. + +acpi:ENI*: + ID_VENDOR_FROM_DATABASE=Efficient Networks + +acpi:ENS*: + ID_VENDOR_FROM_DATABASE=Ensoniq Corporation + +acpi:ENT*: + ID_VENDOR_FROM_DATABASE=Enterprise Comm. & Computing Inc + +acpi:EON*: + ID_VENDOR_FROM_DATABASE=Eon Instrumentation, Inc. + +acpi:EPC*: + ID_VENDOR_FROM_DATABASE=Empac + +acpi:EPH*: + ID_VENDOR_FROM_DATABASE=Epiphan Systems Inc. + +acpi:EPI*: + ID_VENDOR_FROM_DATABASE=Envision Peripherals, Inc + +acpi:EPN*: + ID_VENDOR_FROM_DATABASE=EPiCON Inc. + +acpi:EPS*: + ID_VENDOR_FROM_DATABASE=KEPS + +acpi:EQP*: + ID_VENDOR_FROM_DATABASE=Equipe Electronics Ltd. + +acpi:EQX*: + ID_VENDOR_FROM_DATABASE=Equinox Systems Inc + +acpi:ERG*: + ID_VENDOR_FROM_DATABASE=Ergo System + +acpi:ERI*: + ID_VENDOR_FROM_DATABASE=Ericsson Mobile Communications AB + +acpi:ERN*: + ID_VENDOR_FROM_DATABASE=Ericsson, Inc. + +acpi:ERP*: + ID_VENDOR_FROM_DATABASE=Euraplan GmbH + +acpi:ERS*: + ID_VENDOR_FROM_DATABASE=Eizo Rugged Solutions + +acpi:ERT*: + ID_VENDOR_FROM_DATABASE=Escort Insturments Corporation + +acpi:ESA*: + ID_VENDOR_FROM_DATABASE=Elbit Systems of America + +acpi:ESB*: + ID_VENDOR_FROM_DATABASE=Esterline Belgium BVBA + +acpi:ESC*: + ID_VENDOR_FROM_DATABASE=Eden Sistemas de Computacao S/A + +acpi:ESD*: + ID_VENDOR_FROM_DATABASE=Ensemble Designs, Inc + +acpi:ESG*: + ID_VENDOR_FROM_DATABASE=ELCON Systemtechnik GmbH + +acpi:ESI*: + ID_VENDOR_FROM_DATABASE=Extended Systems, Inc. + +acpi:ESK*: + ID_VENDOR_FROM_DATABASE=ES&S + +acpi:ESL*: + ID_VENDOR_FROM_DATABASE=Esterline Technologies + +acpi:ESN*: + ID_VENDOR_FROM_DATABASE=eSATURNUS + +acpi:ESS*: + ID_VENDOR_FROM_DATABASE=ESS Technology Inc + +acpi:EST*: + ID_VENDOR_FROM_DATABASE=Embedded Solution Technology + +acpi:ESY*: + ID_VENDOR_FROM_DATABASE=E-Systems Inc + +acpi:ETC*: + ID_VENDOR_FROM_DATABASE=Everton Technology Company Ltd + +acpi:ETD*: + ID_VENDOR_FROM_DATABASE=ELAN MICROELECTRONICS CORPORATION + +acpi:ETH*: + ID_VENDOR_FROM_DATABASE=Etherboot Project + +acpi:ETI*: + ID_VENDOR_FROM_DATABASE=Eclipse Tech Inc + +acpi:ETK*: + ID_VENDOR_FROM_DATABASE=eTEK Labs Inc. + +acpi:ETL*: + ID_VENDOR_FROM_DATABASE=Evertz Microsystems Ltd. + +acpi:ETS*: + ID_VENDOR_FROM_DATABASE=Electronic Trade Solutions Ltd + +acpi:ETT*: + ID_VENDOR_FROM_DATABASE=E-Tech Inc + +acpi:EUT*: + ID_VENDOR_FROM_DATABASE=Ericsson Mobile Networks B.V. + +acpi:EVE*: + ID_VENDOR_FROM_DATABASE=Advanced Micro Peripherals Ltd + +acpi:EVI*: + ID_VENDOR_FROM_DATABASE=eviateg GmbH + +acpi:EVX*: + ID_VENDOR_FROM_DATABASE=Everex + +acpi:EXA*: + ID_VENDOR_FROM_DATABASE=Exabyte + +acpi:EXC*: + ID_VENDOR_FROM_DATABASE=Excession Audio + +acpi:EXI*: + ID_VENDOR_FROM_DATABASE=Exide Electronics + +acpi:EXN*: + ID_VENDOR_FROM_DATABASE=RGB Systems, Inc. dba Extron Electronics + +acpi:EXP*: + ID_VENDOR_FROM_DATABASE=Data Export Corporation + +acpi:EXR*: + ID_VENDOR_FROM_DATABASE=Explorer Inc. + +acpi:EXT*: + ID_VENDOR_FROM_DATABASE=Exatech Computadores & Servicos Ltda + +acpi:EXX*: + ID_VENDOR_FROM_DATABASE=Exxact GmbH + +acpi:EXY*: + ID_VENDOR_FROM_DATABASE=Exterity Ltd + +acpi:EYE*: + ID_VENDOR_FROM_DATABASE=eyevis GmbH + +acpi:EYF*: + ID_VENDOR_FROM_DATABASE=eyefactive Gmbh + +acpi:EZE*: + ID_VENDOR_FROM_DATABASE=EzE Technologies + +acpi:EZP*: + ID_VENDOR_FROM_DATABASE=Storm Technology + +acpi:FAN*: + ID_VENDOR_FROM_DATABASE=Fantalooks Co., Ltd. + +acpi:FAR*: + ID_VENDOR_FROM_DATABASE=Farallon Computing + +acpi:FBI*: + ID_VENDOR_FROM_DATABASE=Interface Corporation + +acpi:FCB*: + ID_VENDOR_FROM_DATABASE=Furukawa Electric Company Ltd + +acpi:FCG*: + ID_VENDOR_FROM_DATABASE=First International Computer Ltd + +acpi:FCM*: + ID_VENDOR_FROM_DATABASE=Funai + +acpi:FCS*: + ID_VENDOR_FROM_DATABASE=Focus Enhancements, Inc. + +acpi:FDC*: + ID_VENDOR_FROM_DATABASE=Future Domain + +acpi:FDD*: + ID_VENDOR_FROM_DATABASE=Forth Dimension Displays Ltd + +acpi:FDI*: + ID_VENDOR_FROM_DATABASE=Future Designs, Inc. + +acpi:FDT*: + ID_VENDOR_FROM_DATABASE=Fujitsu Display Technologies Corp. + +acpi:FDX*: + ID_VENDOR_FROM_DATABASE=Findex, Inc. + +acpi:FEC*: + ID_VENDOR_FROM_DATABASE=FURUNO ELECTRIC CO., LTD. + +acpi:FEL*: + ID_VENDOR_FROM_DATABASE=Fellowes & Questec + +acpi:FEN*: + ID_VENDOR_FROM_DATABASE=Fen Systems Ltd. + +acpi:FER*: + ID_VENDOR_FROM_DATABASE=Ferranti Int'L + +acpi:FFC*: + ID_VENDOR_FROM_DATABASE=FUJIFILM Corporation + +acpi:FFI*: + ID_VENDOR_FROM_DATABASE=Fairfield Industries + +acpi:FGD*: + ID_VENDOR_FROM_DATABASE=Lisa Draexlmaier GmbH + +acpi:FGL*: + ID_VENDOR_FROM_DATABASE=Fujitsu General Limited. + +acpi:FHL*: + ID_VENDOR_FROM_DATABASE=FHLP + +acpi:FIC*: + ID_VENDOR_FROM_DATABASE=Formosa Industrial Computing Inc + +acpi:FIL*: + ID_VENDOR_FROM_DATABASE=Forefront Int'l Ltd + +acpi:FIN*: + ID_VENDOR_FROM_DATABASE=Finecom Co., Ltd. + +acpi:FIR*: + ID_VENDOR_FROM_DATABASE=Chaplet Systems Inc + +acpi:FIS*: + ID_VENDOR_FROM_DATABASE=FLY-IT Simulators + +acpi:FIT*: + ID_VENDOR_FROM_DATABASE=Feature Integration Technology Inc. + +acpi:FJC*: + ID_VENDOR_FROM_DATABASE=Fujitsu Takamisawa Component Limited + +acpi:FJS*: + ID_VENDOR_FROM_DATABASE=Fujitsu Spain + +acpi:FJT*: + ID_VENDOR_FROM_DATABASE=F.J. Tieman BV + +acpi:FLE*: + ID_VENDOR_FROM_DATABASE=ADTI Media, Inc + +acpi:FLI*: + ID_VENDOR_FROM_DATABASE=Faroudja Laboratories + +acpi:FLY*: + ID_VENDOR_FROM_DATABASE=Butterfly Communications + +acpi:FMA*: + ID_VENDOR_FROM_DATABASE=Fast Multimedia AG + +acpi:FMC*: + ID_VENDOR_FROM_DATABASE=Ford Microelectronics Inc + +acpi:FMI*: + ID_VENDOR_FROM_DATABASE=Fellowes, Inc. + +acpi:FML*: + ID_VENDOR_FROM_DATABASE=Fujitsu Microelect Ltd + +acpi:FMZ*: + ID_VENDOR_FROM_DATABASE=Formoza-Altair + +acpi:FNC*: + ID_VENDOR_FROM_DATABASE=Fanuc LTD + +acpi:FNI*: + ID_VENDOR_FROM_DATABASE=Funai Electric Co., Ltd. + +acpi:FOA*: + ID_VENDOR_FROM_DATABASE=FOR-A Company Limited + +acpi:FOK*: + ID_VENDOR_FROM_DATABASE=Fokus Technologies GmbH + +acpi:FOS*: + ID_VENDOR_FROM_DATABASE=Foss Tecator + +acpi:FOV*: + ID_VENDOR_FROM_DATABASE=FOVE INC + +acpi:FOX*: + ID_VENDOR_FROM_DATABASE=HON HAI PRECISON IND.CO.,LTD. + +acpi:FPC*: + ID_VENDOR_FROM_DATABASE=Fingerprint Cards AB + +acpi:FPE*: + ID_VENDOR_FROM_DATABASE=Fujitsu Peripherals Ltd + +acpi:FPS*: + ID_VENDOR_FROM_DATABASE=Deltec Corporation + +acpi:FPX*: + ID_VENDOR_FROM_DATABASE=Cirel Systemes + +acpi:FRC*: + ID_VENDOR_FROM_DATABASE=Force Computers + +acpi:FRD*: + ID_VENDOR_FROM_DATABASE=Freedom Scientific BLV + +acpi:FRE*: + ID_VENDOR_FROM_DATABASE=Forvus Research Inc + +acpi:FRI*: + ID_VENDOR_FROM_DATABASE=Fibernet Research Inc + +acpi:FRO*: + ID_VENDOR_FROM_DATABASE=FARO Technologies + +acpi:FRS*: + ID_VENDOR_FROM_DATABASE=South Mountain Technologies, LTD + +acpi:FSC*: + ID_VENDOR_FROM_DATABASE=Future Systems Consulting KK + +acpi:FSI*: + ID_VENDOR_FROM_DATABASE=Fore Systems Inc + +acpi:FST*: + ID_VENDOR_FROM_DATABASE=Modesto PC Inc + +acpi:FTC*: + ID_VENDOR_FROM_DATABASE=Futuretouch Corporation + +acpi:FTE*: + ID_VENDOR_FROM_DATABASE=Frontline Test Equipment Inc. + +acpi:FTG*: + ID_VENDOR_FROM_DATABASE=FTG Data Systems + +acpi:FTI*: + ID_VENDOR_FROM_DATABASE=FastPoint Technologies, Inc. + +acpi:FTL*: + ID_VENDOR_FROM_DATABASE=FUJITSU TEN LIMITED + +acpi:FTN*: + ID_VENDOR_FROM_DATABASE=Fountain Technologies Inc + +acpi:FTR*: + ID_VENDOR_FROM_DATABASE=Mediasonic + +acpi:FTS*: + ID_VENDOR_FROM_DATABASE=FocalTech Systems Co., Ltd. + +acpi:FTW*: + ID_VENDOR_FROM_DATABASE=MindTribe Product Engineering, Inc. + +acpi:FUJ*: + ID_VENDOR_FROM_DATABASE=Fujitsu Ltd + +acpi:FUN*: + ID_VENDOR_FROM_DATABASE=sisel muhendislik + +acpi:FUS*: + ID_VENDOR_FROM_DATABASE=Fujitsu Siemens Computers GmbH + +acpi:FVC*: + ID_VENDOR_FROM_DATABASE=First Virtual Corporation + +acpi:FVX*: + ID_VENDOR_FROM_DATABASE=C-C-C Group Plc + +acpi:FWA*: + ID_VENDOR_FROM_DATABASE=Attero Tech, LLC + +acpi:FWR*: + ID_VENDOR_FROM_DATABASE=Flat Connections Inc + +acpi:FXX*: + ID_VENDOR_FROM_DATABASE=Fuji Xerox + +acpi:FZC*: + ID_VENDOR_FROM_DATABASE=Founder Group Shenzhen Co. + +acpi:FZI*: + ID_VENDOR_FROM_DATABASE=FZI Forschungszentrum Informatik + +acpi:GAC*: + ID_VENDOR_FROM_DATABASE=GreenArrays, Inc. + +acpi:GAG*: + ID_VENDOR_FROM_DATABASE=Gage Applied Sciences Inc + +acpi:GAL*: + ID_VENDOR_FROM_DATABASE=Galil Motion Control + +acpi:GAU*: + ID_VENDOR_FROM_DATABASE=Gaudi Co., Ltd. + +acpi:GBT*: + ID_VENDOR_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO., LTD. + +acpi:GCC*: + ID_VENDOR_FROM_DATABASE=GCC Technologies Inc + +acpi:GCI*: + ID_VENDOR_FROM_DATABASE=Gateway Comm. Inc + +acpi:GCS*: + ID_VENDOR_FROM_DATABASE=Grey Cell Systems Ltd + +acpi:GDC*: + ID_VENDOR_FROM_DATABASE=General Datacom + +acpi:GDI*: + ID_VENDOR_FROM_DATABASE=G. Diehl ISDN GmbH + +acpi:GDS*: + ID_VENDOR_FROM_DATABASE=GDS + +acpi:GDT*: + ID_VENDOR_FROM_DATABASE=Vortex Computersysteme GmbH + +acpi:GEC*: + ID_VENDOR_FROM_DATABASE=Gechic Corporation + +acpi:GED*: + ID_VENDOR_FROM_DATABASE=General Dynamics C4 Systems + +acpi:GEF*: + ID_VENDOR_FROM_DATABASE=GE Fanuc Embedded Systems + +acpi:GEH*: + ID_VENDOR_FROM_DATABASE=Abaco Systems, Inc. + +acpi:GEM*: + ID_VENDOR_FROM_DATABASE=Gem Plus + +acpi:GEN*: + ID_VENDOR_FROM_DATABASE=Genesys ATE Inc + +acpi:GEO*: + ID_VENDOR_FROM_DATABASE=GEO Sense + +acpi:GER*: + ID_VENDOR_FROM_DATABASE=GERMANEERS GmbH + +acpi:GES*: + ID_VENDOR_FROM_DATABASE=GES Singapore Pte Ltd + +acpi:GET*: + ID_VENDOR_FROM_DATABASE=Getac Technology Corporation + +acpi:GFM*: + ID_VENDOR_FROM_DATABASE=GFMesstechnik GmbH + +acpi:GFN*: + ID_VENDOR_FROM_DATABASE=Gefen Inc. + +acpi:GGL*: + ID_VENDOR_FROM_DATABASE=Google Inc. + +acpi:GGT*: + ID_VENDOR_FROM_DATABASE=G2TOUCH KOREA + +acpi:GIC*: + ID_VENDOR_FROM_DATABASE=General Inst. Corporation + +acpi:GIM*: + ID_VENDOR_FROM_DATABASE=Guillemont International + +acpi:GIP*: + ID_VENDOR_FROM_DATABASE=GI Provision Ltd + +acpi:GIS*: + ID_VENDOR_FROM_DATABASE=AT&T Global Info Solutions + +acpi:GJN*: + ID_VENDOR_FROM_DATABASE=Grand Junction Networks + +acpi:GLD*: + ID_VENDOR_FROM_DATABASE=Goldmund - Digital Audio SA + +acpi:GLE*: + ID_VENDOR_FROM_DATABASE=AD electronics + +acpi:GLM*: + ID_VENDOR_FROM_DATABASE=Genesys Logic + +acpi:GLS*: + ID_VENDOR_FROM_DATABASE=Gadget Labs LLC + +acpi:GMK*: + ID_VENDOR_FROM_DATABASE=GMK Electronic Design GmbH + +acpi:GML*: + ID_VENDOR_FROM_DATABASE=General Information Systems + +acpi:GMM*: + ID_VENDOR_FROM_DATABASE=GMM Research Inc + +acpi:GMN*: + ID_VENDOR_FROM_DATABASE=GEMINI 2000 Ltd + +acpi:GMX*: + ID_VENDOR_FROM_DATABASE=GMX Inc + +acpi:GND*: + ID_VENDOR_FROM_DATABASE=Gennum Corporation + +acpi:GNN*: + ID_VENDOR_FROM_DATABASE=GN Nettest Inc + +acpi:GNZ*: + ID_VENDOR_FROM_DATABASE=Gunze Ltd + +acpi:GOE*: + ID_VENDOR_FROM_DATABASE=GOEPEL electronic GmbH + +acpi:GPR*: + ID_VENDOR_FROM_DATABASE=GoPro, Inc. + +acpi:GRA*: + ID_VENDOR_FROM_DATABASE=Graphica Computer + +acpi:GRE*: + ID_VENDOR_FROM_DATABASE=GOLD RAIN ENTERPRISES CORP. + +acpi:GRH*: + ID_VENDOR_FROM_DATABASE=Granch Ltd + +acpi:GRM*: + ID_VENDOR_FROM_DATABASE=Garmin International + +acpi:GRV*: + ID_VENDOR_FROM_DATABASE=Advanced Gravis + +acpi:GRY*: + ID_VENDOR_FROM_DATABASE=Robert Gray Company + +acpi:GSB*: + ID_VENDOR_FROM_DATABASE=NIPPONDENCHI CO,.LTD + +acpi:GSC*: + ID_VENDOR_FROM_DATABASE=General Standards Corporation + +acpi:GSM*: + ID_VENDOR_FROM_DATABASE=LG Electronics + +acpi:GSN*: + ID_VENDOR_FROM_DATABASE=Grandstream Networks, Inc. + +acpi:GST*: + ID_VENDOR_FROM_DATABASE=Graphic SystemTechnology + +acpi:GSY*: + ID_VENDOR_FROM_DATABASE=Grossenbacher Systeme AG + +acpi:GTC*: + ID_VENDOR_FROM_DATABASE=Graphtec Corporation + +acpi:GTI*: + ID_VENDOR_FROM_DATABASE=Goldtouch + +acpi:GTK*: + ID_VENDOR_FROM_DATABASE=G-Tech Corporation + +acpi:GTM*: + ID_VENDOR_FROM_DATABASE=Garnet System Company Ltd + +acpi:GTS*: + ID_VENDOR_FROM_DATABASE=Geotest Marvin Test Systems Inc + +acpi:GTT*: + ID_VENDOR_FROM_DATABASE=General Touch Technology Co., Ltd. + +acpi:GUD*: + ID_VENDOR_FROM_DATABASE=Guntermann & Drunck GmbH + +acpi:GUZ*: + ID_VENDOR_FROM_DATABASE=Guzik Technical Enterprises + +acpi:GVC*: + ID_VENDOR_FROM_DATABASE=GVC Corporation + +acpi:GVL*: + ID_VENDOR_FROM_DATABASE=Global Village Communication + +acpi:GWI*: + ID_VENDOR_FROM_DATABASE=GW Instruments + +acpi:GWK*: + ID_VENDOR_FROM_DATABASE=Gateworks Corporation + +acpi:GWY*: + ID_VENDOR_FROM_DATABASE=Gateway 2000 + +acpi:GZE*: + ID_VENDOR_FROM_DATABASE=GUNZE Limited + +acpi:HAE*: + ID_VENDOR_FROM_DATABASE=Haider electronics + +acpi:HAI*: + ID_VENDOR_FROM_DATABASE=Haivision Systems Inc. + +acpi:HAL*: + ID_VENDOR_FROM_DATABASE=Halberthal + +acpi:HAN*: + ID_VENDOR_FROM_DATABASE=Hanchang System Corporation + +acpi:HAR*: + ID_VENDOR_FROM_DATABASE=Harris Corporation + +acpi:HAY*: + ID_VENDOR_FROM_DATABASE=Hayes Microcomputer Products Inc + +acpi:HCA*: + ID_VENDOR_FROM_DATABASE=DAT + +acpi:HCE*: + ID_VENDOR_FROM_DATABASE=Hitachi Consumer Electronics Co., Ltd + +acpi:HCL*: + ID_VENDOR_FROM_DATABASE=HCL America Inc + +acpi:HCM*: + ID_VENDOR_FROM_DATABASE=HCL Peripherals + +acpi:HCP*: + ID_VENDOR_FROM_DATABASE=Hitachi Computer Products Inc + +acpi:HCW*: + ID_VENDOR_FROM_DATABASE=Hauppauge Computer Works Inc + +acpi:HDC*: + ID_VENDOR_FROM_DATABASE=HardCom Elektronik & Datateknik + +acpi:HDI*: + ID_VENDOR_FROM_DATABASE=HD-INFO d.o.o. + +acpi:HDV*: + ID_VENDOR_FROM_DATABASE=Holografika kft. + +acpi:HEC*: + ID_VENDOR_FROM_DATABASE=Hisense Electric Co., Ltd. + +acpi:HEI*: + ID_VENDOR_FROM_DATABASE=Hyundai + +acpi:HEL*: + ID_VENDOR_FROM_DATABASE=Hitachi Micro Systems Europe Ltd + +acpi:HER*: + ID_VENDOR_FROM_DATABASE=Ascom Business Systems + +acpi:HET*: + ID_VENDOR_FROM_DATABASE=HETEC Datensysteme GmbH + +acpi:HHC*: + ID_VENDOR_FROM_DATABASE=HIRAKAWA HEWTECH CORP. + +acpi:HHI*: + ID_VENDOR_FROM_DATABASE=Fraunhofer Heinrich-Hertz-Institute + +acpi:HIB*: + ID_VENDOR_FROM_DATABASE=Hibino Corporation + +acpi:HIC*: + ID_VENDOR_FROM_DATABASE=Hitachi Information Technology Co., Ltd. + +acpi:HII*: + ID_VENDOR_FROM_DATABASE=Harman International Industries, Inc + +acpi:HIK*: + ID_VENDOR_FROM_DATABASE=Hikom Co., Ltd. + +acpi:HIL*: + ID_VENDOR_FROM_DATABASE=Hilevel Technology + +acpi:HIQ*: + ID_VENDOR_FROM_DATABASE=Kaohsiung Opto Electronics Americas, Inc. + +acpi:HIS*: + ID_VENDOR_FROM_DATABASE=Hope Industrial Systems, Inc. + +acpi:HIT*: + ID_VENDOR_FROM_DATABASE=Hitachi America Ltd + +acpi:HJI*: + ID_VENDOR_FROM_DATABASE=Harris & Jeffries Inc + +acpi:HKA*: + ID_VENDOR_FROM_DATABASE=HONKO MFG. CO., LTD. + +acpi:HKC*: + ID_VENDOR_FROM_DATABASE=HKC OVERSEAS LIMITED + +acpi:HKG*: + ID_VENDOR_FROM_DATABASE=Josef Heim KG + +acpi:HLG*: + ID_VENDOR_FROM_DATABASE=China Hualu Group Co., Ltd. + +acpi:HMC*: + ID_VENDOR_FROM_DATABASE=Hualon Microelectric Corporation + +acpi:HMK*: + ID_VENDOR_FROM_DATABASE=hmk Daten-System-Technik BmbH + +acpi:HMX*: + ID_VENDOR_FROM_DATABASE=HUMAX Co., Ltd. + +acpi:HNS*: + ID_VENDOR_FROM_DATABASE=Hughes Network Systems + +acpi:HOB*: + ID_VENDOR_FROM_DATABASE=HOB Electronic GmbH + +acpi:HOE*: + ID_VENDOR_FROM_DATABASE=Hosiden Corporation + +acpi:HOL*: + ID_VENDOR_FROM_DATABASE=Holoeye Photonics AG + +acpi:HON*: + ID_VENDOR_FROM_DATABASE=Sonitronix + +acpi:HPA*: + ID_VENDOR_FROM_DATABASE=Zytor Communications + +acpi:HPC*: + ID_VENDOR_FROM_DATABASE=Hewlett-Packard Co. + +acpi:HPD*: + ID_VENDOR_FROM_DATABASE=Hewlett Packard + +acpi:HPE*: + ID_VENDOR_FROM_DATABASE=Hewlett Packard Enterprise + +acpi:HPI*: + ID_VENDOR_FROM_DATABASE=Headplay, Inc. + +acpi:HPK*: + ID_VENDOR_FROM_DATABASE=HAMAMATSU PHOTONICS K.K. + +acpi:HPN*: + ID_VENDOR_FROM_DATABASE=HP Inc. + +acpi:HPQ*: + ID_VENDOR_FROM_DATABASE=Hewlett-Packard Co. + +acpi:HPR*: + ID_VENDOR_FROM_DATABASE=H.P.R. Electronics GmbH + +acpi:HRC*: + ID_VENDOR_FROM_DATABASE=Hercules + +acpi:HRE*: + ID_VENDOR_FROM_DATABASE=Qingdao Haier Electronics Co., Ltd. + +acpi:HRI*: + ID_VENDOR_FROM_DATABASE=Hall Research + +acpi:HRL*: + ID_VENDOR_FROM_DATABASE=Herolab GmbH + +acpi:HRS*: + ID_VENDOR_FROM_DATABASE=Harris Semiconductor + +acpi:HRT*: + ID_VENDOR_FROM_DATABASE=HERCULES + +acpi:HSC*: + ID_VENDOR_FROM_DATABASE=Hagiwara Sys-Com Company Ltd + +acpi:HSD*: + ID_VENDOR_FROM_DATABASE=HannStar Display Corp + +acpi:HSL*: + ID_VENDOR_FROM_DATABASE=Hansol + +acpi:HSM*: + ID_VENDOR_FROM_DATABASE=AT&T Microelectronics + +acpi:HSP*: + ID_VENDOR_FROM_DATABASE=HannStar Display Corp + +acpi:HST*: + ID_VENDOR_FROM_DATABASE=Horsent Technology Co., Ltd. + +acpi:HTC*: + ID_VENDOR_FROM_DATABASE=Hitachi Ltd + +acpi:HTI*: + ID_VENDOR_FROM_DATABASE=Hampshire Company, Inc. + +acpi:HTK*: + ID_VENDOR_FROM_DATABASE=Holtek Microelectronics Inc + +acpi:HTL*: + ID_VENDOR_FROM_DATABASE=HTBLuVA Mödling + +acpi:HTR*: + ID_VENDOR_FROM_DATABASE=Shenzhen ZhuoYi HengTong Computer Technology Limited + +acpi:HTX*: + ID_VENDOR_FROM_DATABASE=Hitex Systementwicklung GmbH + +acpi:HUB*: + ID_VENDOR_FROM_DATABASE=GAI-Tronics, A Hubbell Company + +acpi:HUK*: + ID_VENDOR_FROM_DATABASE=Hoffmann + Krippner GmbH + +acpi:HUM*: + ID_VENDOR_FROM_DATABASE=IMP Electronics Ltd. + +acpi:HVR*: + ID_VENDOR_FROM_DATABASE=HTC Corportation + +acpi:HWA*: + ID_VENDOR_FROM_DATABASE=Harris Canada Inc + +acpi:HWC*: + ID_VENDOR_FROM_DATABASE=DBA Hans Wedemeyer + +acpi:HWD*: + ID_VENDOR_FROM_DATABASE=Highwater Designs Ltd + +acpi:HWP*: + ID_VENDOR_FROM_DATABASE=Hewlett Packard + +acpi:HWV*: + ID_VENDOR_FROM_DATABASE=Huawei Technologies Co., Inc. + +acpi:HXM*: + ID_VENDOR_FROM_DATABASE=Hexium Ltd. + +acpi:HYC*: + ID_VENDOR_FROM_DATABASE=Hypercope Gmbh Aachen + +acpi:HYD*: + ID_VENDOR_FROM_DATABASE=Hydis Technologies.Co.,LTD + +acpi:HYL*: + ID_VENDOR_FROM_DATABASE=Shanghai Chai Ming Huang Info&Tech Co, Ltd + +acpi:HYO*: + ID_VENDOR_FROM_DATABASE=HYC CO., LTD. + +acpi:HYP*: + ID_VENDOR_FROM_DATABASE=Hyphen Ltd + +acpi:HYR*: + ID_VENDOR_FROM_DATABASE=Hypertec Pty Ltd + +acpi:HYT*: + ID_VENDOR_FROM_DATABASE=Heng Yu Technology (HK) Limited + +acpi:HYV*: + ID_VENDOR_FROM_DATABASE=Hynix Semiconductor + +acpi:IAD*: + ID_VENDOR_FROM_DATABASE=IAdea Corporation + +acpi:IAF*: + ID_VENDOR_FROM_DATABASE=Institut f r angewandte Funksystemtechnik GmbH + +acpi:IAI*: + ID_VENDOR_FROM_DATABASE=Integration Associates, Inc. + +acpi:IAT*: + ID_VENDOR_FROM_DATABASE=IAT Germany GmbH + +acpi:IBC*: + ID_VENDOR_FROM_DATABASE=Integrated Business Systems + +acpi:IBI*: + ID_VENDOR_FROM_DATABASE=INBINE.CO.LTD + +acpi:IBM*: + ID_VENDOR_FROM_DATABASE=IBM Brasil + +acpi:IBP*: + ID_VENDOR_FROM_DATABASE=IBP Instruments GmbH + +acpi:IBR*: + ID_VENDOR_FROM_DATABASE=IBR GmbH + +acpi:ICA*: + ID_VENDOR_FROM_DATABASE=ICA Inc + +acpi:ICC*: + ID_VENDOR_FROM_DATABASE=BICC Data Networks Ltd + +acpi:ICD*: + ID_VENDOR_FROM_DATABASE=ICD Inc + +acpi:ICE*: + ID_VENDOR_FROM_DATABASE=IC Ensemble + +acpi:ICI*: + ID_VENDOR_FROM_DATABASE=Infotek Communication Inc + +acpi:ICL*: + ID_VENDOR_FROM_DATABASE=Fujitsu ICL + +acpi:ICM*: + ID_VENDOR_FROM_DATABASE=Intracom SA + +acpi:ICN*: + ID_VENDOR_FROM_DATABASE=Sanyo Icon + +acpi:ICO*: + ID_VENDOR_FROM_DATABASE=Intel Corp + +acpi:ICP*: + ID_VENDOR_FROM_DATABASE=ICP Electronics, Inc./iEi Technology Corp. + +acpi:ICR*: + ID_VENDOR_FROM_DATABASE=Icron + +acpi:ICS*: + ID_VENDOR_FROM_DATABASE=Integrated Circuit Systems + +acpi:ICV*: + ID_VENDOR_FROM_DATABASE=Inside Contactless + +acpi:ICX*: + ID_VENDOR_FROM_DATABASE=ICCC A/S + +acpi:IDC*: + ID_VENDOR_FROM_DATABASE=International Datacasting Corporation + +acpi:IDE*: + ID_VENDOR_FROM_DATABASE=IDE Associates + +acpi:IDK*: + ID_VENDOR_FROM_DATABASE=IDK Corporation + +acpi:IDN*: + ID_VENDOR_FROM_DATABASE=Idneo Technologies + +acpi:IDO*: + ID_VENDOR_FROM_DATABASE=IDEO Product Development + +acpi:IDP*: + ID_VENDOR_FROM_DATABASE=Integrated Device Technology, Inc. + +acpi:IDS*: + ID_VENDOR_FROM_DATABASE=Interdigital Sistemas de Informacao + +acpi:IDT*: + ID_VENDOR_FROM_DATABASE=International Display Technology + +acpi:IDX*: + ID_VENDOR_FROM_DATABASE=IDEXX Labs + +acpi:IEC*: + ID_VENDOR_FROM_DATABASE=Interlace Engineering Corporation + +acpi:IEE*: + ID_VENDOR_FROM_DATABASE=IEE + +acpi:IEI*: + ID_VENDOR_FROM_DATABASE=Interlink Electronics + +acpi:IFS*: + ID_VENDOR_FROM_DATABASE=In Focus Systems Inc + +acpi:IFT*: + ID_VENDOR_FROM_DATABASE=Informtech + +acpi:IFX*: + ID_VENDOR_FROM_DATABASE=Infineon Technologies AG + +acpi:IFZ*: + ID_VENDOR_FROM_DATABASE=Infinite Z + +acpi:IGC*: + ID_VENDOR_FROM_DATABASE=Intergate Pty Ltd + +acpi:IGM*: + ID_VENDOR_FROM_DATABASE=IGM Communi + +acpi:IHE*: + ID_VENDOR_FROM_DATABASE=InHand Electronics + +acpi:IIC*: + ID_VENDOR_FROM_DATABASE=ISIC Innoscan Industrial Computers A/S + +acpi:III*: + ID_VENDOR_FROM_DATABASE=Intelligent Instrumentation + +acpi:IIN*: + ID_VENDOR_FROM_DATABASE=IINFRA Co., Ltd + +acpi:IIT*: + ID_VENDOR_FROM_DATABASE=Informatik Information Technologies + +acpi:IKE*: + ID_VENDOR_FROM_DATABASE=Ikegami Tsushinki Co. Ltd. + +acpi:IKN*: + ID_VENDOR_FROM_DATABASE=IKON + +acpi:IKS*: + ID_VENDOR_FROM_DATABASE=Ikos Systems Inc + +acpi:ILC*: + ID_VENDOR_FROM_DATABASE=Image Logic Corporation + +acpi:ILS*: + ID_VENDOR_FROM_DATABASE=Innotech Corporation + +acpi:IMA*: + ID_VENDOR_FROM_DATABASE=Imagraph + +acpi:IMB*: + ID_VENDOR_FROM_DATABASE=ART s.r.l. + +acpi:IMC*: + ID_VENDOR_FROM_DATABASE=IMC Networks + +acpi:IMD*: + ID_VENDOR_FROM_DATABASE=ImasDe Canarias S.A. + +acpi:IME*: + ID_VENDOR_FROM_DATABASE=Imagraph + +acpi:IMF*: + ID_VENDOR_FROM_DATABASE=Immersive Audio Technologies France + +acpi:IMG*: + ID_VENDOR_FROM_DATABASE=IMAGENICS Co., Ltd. + +acpi:IMI*: + ID_VENDOR_FROM_DATABASE=International Microsystems Inc + +acpi:IMM*: + ID_VENDOR_FROM_DATABASE=Immersion Corporation + +acpi:IMN*: + ID_VENDOR_FROM_DATABASE=Impossible Production + +acpi:IMP*: + ID_VENDOR_FROM_DATABASE=Impinj + +acpi:IMT*: + ID_VENDOR_FROM_DATABASE=Inmax Technology Corporation + +acpi:IMS*: + ID_VENDOR_FROM_DATABASE=Integrated Micro Solution Inc. + +acpi:INA*: + ID_VENDOR_FROM_DATABASE=Inventec Corporation + +acpi:INC*: + ID_VENDOR_FROM_DATABASE=Home Row Inc + +acpi:IND*: + ID_VENDOR_FROM_DATABASE=ILC + +acpi:INE*: + ID_VENDOR_FROM_DATABASE=Inventec Electronics (M) Sdn. Bhd. + +acpi:INF*: + ID_VENDOR_FROM_DATABASE=Inframetrics Inc + +acpi:ING*: + ID_VENDOR_FROM_DATABASE=Integraph Corporation + +acpi:INI*: + ID_VENDOR_FROM_DATABASE=Initio Corporation + +acpi:INK*: + ID_VENDOR_FROM_DATABASE=Indtek Co., Ltd. + +acpi:INL*: + ID_VENDOR_FROM_DATABASE=InnoLux Display Corporation + +acpi:INM*: + ID_VENDOR_FROM_DATABASE=InnoMedia Inc + +acpi:INN*: + ID_VENDOR_FROM_DATABASE=Innovent Systems, Inc. + +acpi:INO*: + ID_VENDOR_FROM_DATABASE=Innolab Pte Ltd + +acpi:INP*: + ID_VENDOR_FROM_DATABASE=Interphase Corporation + +acpi:INS*: + ID_VENDOR_FROM_DATABASE=Ines GmbH + +acpi:INT*: + ID_VENDOR_FROM_DATABASE=Interphase Corporation + +acpi:INV*: + ID_VENDOR_FROM_DATABASE=Inviso, Inc. + +acpi:INX*: + ID_VENDOR_FROM_DATABASE=Communications Supply Corporation (A division of WESCO) + +acpi:INZ*: + ID_VENDOR_FROM_DATABASE=Best Buy + +acpi:IOA*: + ID_VENDOR_FROM_DATABASE=CRE Technology Corporation + +acpi:IOD*: + ID_VENDOR_FROM_DATABASE=I-O Data Device Inc + +acpi:IOM*: + ID_VENDOR_FROM_DATABASE=Iomega + +acpi:ION*: + ID_VENDOR_FROM_DATABASE=Inside Out Networks + +acpi:IOS*: + ID_VENDOR_FROM_DATABASE=i-O Display System + +acpi:IOT*: + ID_VENDOR_FROM_DATABASE=I/OTech Inc + +acpi:IPC*: + ID_VENDOR_FROM_DATABASE=IPC Corporation + +acpi:IPD*: + ID_VENDOR_FROM_DATABASE=Industrial Products Design, Inc. + +acpi:IPI*: + ID_VENDOR_FROM_DATABASE=Intelligent Platform Management Interface (IPMI) forum (Intel, HP, NEC, Dell) + +acpi:IPM*: + ID_VENDOR_FROM_DATABASE=IPM Industria Politecnica Meridionale SpA + +acpi:IPN*: + ID_VENDOR_FROM_DATABASE=Performance Technologies + +acpi:IPP*: + ID_VENDOR_FROM_DATABASE=IP Power Technologies GmbH + +acpi:IPQ*: + ID_VENDOR_FROM_DATABASE=IP3 Technology Ltd. + +acpi:IPR*: + ID_VENDOR_FROM_DATABASE=Ithaca Peripherals + +acpi:IPS*: + ID_VENDOR_FROM_DATABASE=IPS, Inc. (Intellectual Property Solutions, Inc.) + +acpi:IPT*: + ID_VENDOR_FROM_DATABASE=International Power Technologies + +acpi:IPW*: + ID_VENDOR_FROM_DATABASE=IPWireless, Inc + +acpi:IQI*: + ID_VENDOR_FROM_DATABASE=IneoQuest Technologies, Inc + +acpi:IQT*: + ID_VENDOR_FROM_DATABASE=IMAGEQUEST Co., Ltd + +acpi:IRD*: + ID_VENDOR_FROM_DATABASE=Irdata + +acpi:ISA*: + ID_VENDOR_FROM_DATABASE=Symbol Technologies + +acpi:ISC*: + ID_VENDOR_FROM_DATABASE=Id3 Semiconductors + +acpi:ISG*: + ID_VENDOR_FROM_DATABASE=Insignia Solutions Inc + +acpi:ISI*: + ID_VENDOR_FROM_DATABASE=Interface Solutions + +acpi:ISL*: + ID_VENDOR_FROM_DATABASE=Isolation Systems + +acpi:ISM*: + ID_VENDOR_FROM_DATABASE=Image Stream Medical + +acpi:ISP*: + ID_VENDOR_FROM_DATABASE=IntreSource Systems Pte Ltd + +acpi:ISR*: + ID_VENDOR_FROM_DATABASE=INSIS Co., LTD. + +acpi:ISS*: + ID_VENDOR_FROM_DATABASE=ISS Inc + +acpi:IST*: + ID_VENDOR_FROM_DATABASE=Intersolve Technologies + +acpi:ISY*: + ID_VENDOR_FROM_DATABASE=International Integrated Systems,Inc.(IISI) + +acpi:ITA*: + ID_VENDOR_FROM_DATABASE=Itausa Export North America + +acpi:ITC*: + ID_VENDOR_FROM_DATABASE=Intercom Inc + +acpi:ITD*: + ID_VENDOR_FROM_DATABASE=Internet Technology Corporation + +acpi:ITE*: + ID_VENDOR_FROM_DATABASE=Integrated Tech Express Inc + +acpi:ITI*: + ID_VENDOR_FROM_DATABASE=VanErum Group + +acpi:ITK*: + ID_VENDOR_FROM_DATABASE=ITK Telekommunikation AG + +acpi:ITL*: + ID_VENDOR_FROM_DATABASE=Inter-Tel + +acpi:ITM*: + ID_VENDOR_FROM_DATABASE=ITM inc. + +acpi:ITN*: + ID_VENDOR_FROM_DATABASE=The NTI Group + +acpi:ITP*: + ID_VENDOR_FROM_DATABASE=IT-PRO Consulting und Systemhaus GmbH + +acpi:ITR*: + ID_VENDOR_FROM_DATABASE=Infotronic America, Inc. + +acpi:ITS*: + ID_VENDOR_FROM_DATABASE=IDTECH + +acpi:ITT*: + ID_VENDOR_FROM_DATABASE=I&T Telecom. + +acpi:ITX*: + ID_VENDOR_FROM_DATABASE=integrated Technology Express Inc + +acpi:IUC*: + ID_VENDOR_FROM_DATABASE=ICSL + +acpi:IVI*: + ID_VENDOR_FROM_DATABASE=Intervoice Inc + +acpi:IVM*: + ID_VENDOR_FROM_DATABASE=Iiyama North America + +acpi:IVR*: + ID_VENDOR_FROM_DATABASE=Inlife-Handnet Co., Ltd. + +acpi:IVS*: + ID_VENDOR_FROM_DATABASE=Intevac Photonics Inc. + +acpi:IWR*: + ID_VENDOR_FROM_DATABASE=Icuiti Corporation + +acpi:IWX*: + ID_VENDOR_FROM_DATABASE=Intelliworxx, Inc. + +acpi:IXD*: + ID_VENDOR_FROM_DATABASE=Intertex Data AB + +acpi:IXN*: + ID_VENDOR_FROM_DATABASE=Shenzhen Inet Mobile Internet Technology Co., LTD + +acpi:JAC*: + ID_VENDOR_FROM_DATABASE=Astec Inc + +acpi:JAE*: + ID_VENDOR_FROM_DATABASE=Japan Aviation Electronics Industry, Limited + +acpi:JAS*: + ID_VENDOR_FROM_DATABASE=Janz Automationssysteme AG + +acpi:JAT*: + ID_VENDOR_FROM_DATABASE=Jaton Corporation + +acpi:JAZ*: + ID_VENDOR_FROM_DATABASE=Carrera Computer Inc + +acpi:JCE*: + ID_VENDOR_FROM_DATABASE=Jace Tech Inc + +acpi:JDI*: + ID_VENDOR_FROM_DATABASE=Japan Display Inc. + +acpi:JDL*: + ID_VENDOR_FROM_DATABASE=Japan Digital Laboratory Co.,Ltd. + +acpi:JEM*: + ID_VENDOR_FROM_DATABASE=Japan E.M.Solutions Co., Ltd. + +acpi:JEN*: + ID_VENDOR_FROM_DATABASE=N-Vision + +acpi:JET*: + ID_VENDOR_FROM_DATABASE=JET POWER TECHNOLOGY CO., LTD. + +acpi:JFX*: + ID_VENDOR_FROM_DATABASE=Jones Futurex Inc + +acpi:JGD*: + ID_VENDOR_FROM_DATABASE=University College + +acpi:JIC*: + ID_VENDOR_FROM_DATABASE=Jaeik Information & Communication Co., Ltd. + +acpi:JKC*: + ID_VENDOR_FROM_DATABASE=JVC KENWOOD Corporation + +acpi:JMT*: + ID_VENDOR_FROM_DATABASE=Micro Technical Company Ltd + +acpi:JPC*: + ID_VENDOR_FROM_DATABASE=JPC Technology Limited + +acpi:JPW*: + ID_VENDOR_FROM_DATABASE=Wallis Hamilton Industries + +acpi:JQE*: + ID_VENDOR_FROM_DATABASE=CNet Technical Inc + +acpi:JSD*: + ID_VENDOR_FROM_DATABASE=JS DigiTech, Inc + +acpi:JSI*: + ID_VENDOR_FROM_DATABASE=Jupiter Systems, Inc. + +acpi:JSK*: + ID_VENDOR_FROM_DATABASE=SANKEN ELECTRIC CO., LTD + +acpi:JTS*: + ID_VENDOR_FROM_DATABASE=JS Motorsports + +acpi:JTY*: + ID_VENDOR_FROM_DATABASE=jetway security micro,inc + +acpi:JUK*: + ID_VENDOR_FROM_DATABASE=Janich & Klass Computertechnik GmbH + +acpi:JUP*: + ID_VENDOR_FROM_DATABASE=Jupiter Systems + +acpi:JVC*: + ID_VENDOR_FROM_DATABASE=JVC + +acpi:JWD*: + ID_VENDOR_FROM_DATABASE=Video International Inc. + +acpi:JWL*: + ID_VENDOR_FROM_DATABASE=Jewell Instruments, LLC + +acpi:JWS*: + ID_VENDOR_FROM_DATABASE=JWSpencer & Co. + +acpi:JWY*: + ID_VENDOR_FROM_DATABASE=Jetway Information Co., Ltd + +acpi:KAR*: + ID_VENDOR_FROM_DATABASE=Karna + +acpi:KBI*: + ID_VENDOR_FROM_DATABASE=Kidboard Inc + +acpi:KBL*: + ID_VENDOR_FROM_DATABASE=Kobil Systems GmbH + +acpi:KCD*: + ID_VENDOR_FROM_DATABASE=Chunichi Denshi Co.,LTD. + +acpi:KCL*: + ID_VENDOR_FROM_DATABASE=Keycorp Ltd + +acpi:KDE*: + ID_VENDOR_FROM_DATABASE=KDE + +acpi:KDK*: + ID_VENDOR_FROM_DATABASE=Kodiak Tech + +acpi:KDM*: + ID_VENDOR_FROM_DATABASE=Korea Data Systems Co., Ltd. + +acpi:KDS*: + ID_VENDOR_FROM_DATABASE=KDS USA + +acpi:KDT*: + ID_VENDOR_FROM_DATABASE=KDDI Technology Corporation + +acpi:KEC*: + ID_VENDOR_FROM_DATABASE=Kyushu Electronics Systems Inc + +acpi:KEM*: + ID_VENDOR_FROM_DATABASE=Kontron Embedded Modules GmbH + +acpi:KES*: + ID_VENDOR_FROM_DATABASE=Kesa Corporation + +acpi:KEU*: + ID_VENDOR_FROM_DATABASE=Kontron Europe GmbH + +acpi:KEY*: + ID_VENDOR_FROM_DATABASE=Key Tech Inc + +acpi:KFC*: + ID_VENDOR_FROM_DATABASE=SCD Tech + +acpi:KFE*: + ID_VENDOR_FROM_DATABASE=Komatsu Forest + +acpi:KFX*: + ID_VENDOR_FROM_DATABASE=Kofax Image Products + +acpi:KGI*: + ID_VENDOR_FROM_DATABASE=Klipsch Group, Inc + +acpi:KGL*: + ID_VENDOR_FROM_DATABASE=KEISOKU GIKEN Co.,Ltd. + +acpi:KIO*: + ID_VENDOR_FROM_DATABASE=Kionix, Inc. + +acpi:KIS*: + ID_VENDOR_FROM_DATABASE=KiSS Technology A/S + +acpi:KMC*: + ID_VENDOR_FROM_DATABASE=Mitsumi Company Ltd + +acpi:KME*: + ID_VENDOR_FROM_DATABASE=KIMIN Electronics Co., Ltd. + +acpi:KML*: + ID_VENDOR_FROM_DATABASE=Kensington Microware Ltd + +acpi:KMR*: + ID_VENDOR_FROM_DATABASE=Kramer Electronics Ltd. International + +acpi:KNC*: + ID_VENDOR_FROM_DATABASE=Konica corporation + +acpi:KNX*: + ID_VENDOR_FROM_DATABASE=Nutech Marketing PTL + +acpi:KOB*: + ID_VENDOR_FROM_DATABASE=Kobil Systems GmbH + +acpi:KOD*: + ID_VENDOR_FROM_DATABASE=Eastman Kodak Company + +acpi:KOE*: + ID_VENDOR_FROM_DATABASE=KOLTER ELECTRONIC + +acpi:KOL*: + ID_VENDOR_FROM_DATABASE=Kollmorgen Motion Technologies Group + +acpi:KOM*: + ID_VENDOR_FROM_DATABASE=Kontron GmbH + +acpi:KOU*: + ID_VENDOR_FROM_DATABASE=KOUZIRO Co.,Ltd. + +acpi:KOW*: + ID_VENDOR_FROM_DATABASE=KOWA Company,LTD. + +acpi:KPC*: + ID_VENDOR_FROM_DATABASE=King Phoenix Company + +acpi:KPT*: + ID_VENDOR_FROM_DATABASE=TPK Holding Co., Ltd + +acpi:KRL*: + ID_VENDOR_FROM_DATABASE=Krell Industries Inc. + +acpi:KRM*: + ID_VENDOR_FROM_DATABASE=Kroma Telecom + +acpi:KRY*: + ID_VENDOR_FROM_DATABASE=Kroy LLC + +acpi:KSC*: + ID_VENDOR_FROM_DATABASE=Kinetic Systems Corporation + +acpi:KSG*: + ID_VENDOR_FROM_DATABASE=KUPA China Shenzhen Micro Technology Co., Ltd. Gold Institute + +acpi:KSL*: + ID_VENDOR_FROM_DATABASE=Karn Solutions Ltd. + +acpi:KSX*: + ID_VENDOR_FROM_DATABASE=King Tester Corporation + +acpi:KTC*: + ID_VENDOR_FROM_DATABASE=Kingston Tech Corporation + +acpi:KTD*: + ID_VENDOR_FROM_DATABASE=Takahata Electronics Co.,Ltd. + +acpi:KTE*: + ID_VENDOR_FROM_DATABASE=K-Tech + +acpi:KTG*: + ID_VENDOR_FROM_DATABASE=Kayser-Threde GmbH + +acpi:KTI*: + ID_VENDOR_FROM_DATABASE=Konica Technical Inc + +acpi:KTK*: + ID_VENDOR_FROM_DATABASE=Key Tronic Corporation + +acpi:KTN*: + ID_VENDOR_FROM_DATABASE=Katron Tech Inc + +acpi:KUR*: + ID_VENDOR_FROM_DATABASE=Kurta Corporation + +acpi:KVA*: + ID_VENDOR_FROM_DATABASE=Kvaser AB + +acpi:KVX*: + ID_VENDOR_FROM_DATABASE=KeyView + +acpi:KWD*: + ID_VENDOR_FROM_DATABASE=Kenwood Corporation + +acpi:KYC*: + ID_VENDOR_FROM_DATABASE=Kyocera Corporation + +acpi:KYE*: + ID_VENDOR_FROM_DATABASE=KYE Syst Corporation + +acpi:KYK*: + ID_VENDOR_FROM_DATABASE=Samsung Electronics America Inc + +acpi:KYN*: + ID_VENDOR_FROM_DATABASE=KEYENCE CORPORATION + +acpi:KZI*: + ID_VENDOR_FROM_DATABASE=K-Zone International co. Ltd. + +acpi:KZN*: + ID_VENDOR_FROM_DATABASE=K-Zone International + +acpi:LAB*: + ID_VENDOR_FROM_DATABASE=ACT Labs Ltd + +acpi:LAC*: + ID_VENDOR_FROM_DATABASE=LaCie + +acpi:LAF*: + ID_VENDOR_FROM_DATABASE=Microline + +acpi:LAG*: + ID_VENDOR_FROM_DATABASE=Laguna Systems + +acpi:LAN*: + ID_VENDOR_FROM_DATABASE=Sodeman Lancom Inc + +acpi:LAP*: + ID_VENDOR_FROM_DATABASE=BenQ + +acpi:LAS*: + ID_VENDOR_FROM_DATABASE=LASAT Comm. A/S + +acpi:LAV*: + ID_VENDOR_FROM_DATABASE=Lava Computer MFG Inc + +acpi:LBO*: + ID_VENDOR_FROM_DATABASE=Lubosoft + +acpi:LCC*: + ID_VENDOR_FROM_DATABASE=LCI + +acpi:LCD*: + ID_VENDOR_FROM_DATABASE=Toshiba Matsushita Display Technology Co., Ltd + +acpi:LCE*: + ID_VENDOR_FROM_DATABASE=La Commande Electronique + +acpi:LCI*: + ID_VENDOR_FROM_DATABASE=Lite-On Communication Inc + +acpi:LCM*: + ID_VENDOR_FROM_DATABASE=Latitude Comm. + +acpi:LCN*: + ID_VENDOR_FROM_DATABASE=LEXICON + +acpi:LCS*: + ID_VENDOR_FROM_DATABASE=Longshine Electronics Company + +acpi:LCT*: + ID_VENDOR_FROM_DATABASE=Labcal Technologies + +acpi:LDN*: + ID_VENDOR_FROM_DATABASE=Laserdyne Technologies + +acpi:LDT*: + ID_VENDOR_FROM_DATABASE=LogiDataTech Electronic GmbH + +acpi:LEC*: + ID_VENDOR_FROM_DATABASE=Lectron Company Ltd + +acpi:LED*: + ID_VENDOR_FROM_DATABASE=Long Engineering Design Inc + +acpi:LED*: + ID_VENDOR_FROM_DATABASE=LeafNet + +acpi:LEG*: + ID_VENDOR_FROM_DATABASE=Legerity, Inc + +acpi:LEN*: + ID_VENDOR_FROM_DATABASE=Lenovo Group Limited + +acpi:LEO*: + ID_VENDOR_FROM_DATABASE=First International Computer Inc + +acpi:LEX*: + ID_VENDOR_FROM_DATABASE=Lexical Ltd + +acpi:LGC*: + ID_VENDOR_FROM_DATABASE=Logic Ltd + +acpi:LGD*: + ID_VENDOR_FROM_DATABASE=LG Display + +acpi:LGI*: + ID_VENDOR_FROM_DATABASE=Logitech Inc + +acpi:LGS*: + ID_VENDOR_FROM_DATABASE=LG Semicom Company Ltd + +acpi:LGX*: + ID_VENDOR_FROM_DATABASE=Lasergraphics, Inc. + +acpi:LHA*: + ID_VENDOR_FROM_DATABASE=Lars Haagh ApS + +acpi:LHC*: + ID_VENDOR_FROM_DATABASE=Beihai Century Joint Innovation Technology Co.,Ltd + +acpi:LHE*: + ID_VENDOR_FROM_DATABASE=Lung Hwa Electronics Company Ltd + +acpi:LHT*: + ID_VENDOR_FROM_DATABASE=Lighthouse Technologies Limited + +acpi:LIN*: + ID_VENDOR_FROM_DATABASE=Lenovo Beijing Co. Ltd. + +acpi:LIP*: + ID_VENDOR_FROM_DATABASE=Linked IP GmbH + +acpi:LIT*: + ID_VENDOR_FROM_DATABASE=Lithics Silicon Technology + +acpi:LJX*: + ID_VENDOR_FROM_DATABASE=Datalogic Corporation + +acpi:LKM*: + ID_VENDOR_FROM_DATABASE=Likom Technology Sdn. Bhd. + +acpi:LLL*: + ID_VENDOR_FROM_DATABASE=L-3 Communications + +acpi:LMG*: + ID_VENDOR_FROM_DATABASE=Lucent Technologies + +acpi:LMI*: + ID_VENDOR_FROM_DATABASE=Lexmark Int'l Inc + +acpi:LMP*: + ID_VENDOR_FROM_DATABASE=Leda Media Products + +acpi:LMT*: + ID_VENDOR_FROM_DATABASE=Laser Master + +acpi:LND*: + ID_VENDOR_FROM_DATABASE=Land Computer Company Ltd + +acpi:LNE*: + ID_VENDOR_FROM_DATABASE=Linksys + +acpi:LNK*: + ID_VENDOR_FROM_DATABASE=Link Tech Inc + +acpi:LNR*: + ID_VENDOR_FROM_DATABASE=Linear Systems Ltd. + +acpi:LNT*: + ID_VENDOR_FROM_DATABASE=LANETCO International + +acpi:LNV*: + ID_VENDOR_FROM_DATABASE=Lenovo + +acpi:LNX*: + ID_VENDOR_FROM_DATABASE=The Linux Foundation + +acpi:LOC*: + ID_VENDOR_FROM_DATABASE=Locamation B.V. + +acpi:LOE*: + ID_VENDOR_FROM_DATABASE=Loewe Opta GmbH + +acpi:LOG*: + ID_VENDOR_FROM_DATABASE=Logicode Technology Inc + +acpi:LOL*: + ID_VENDOR_FROM_DATABASE=Litelogic Operations Ltd + +acpi:LPE*: + ID_VENDOR_FROM_DATABASE=El-PUSK Co., Ltd. + +acpi:LPI*: + ID_VENDOR_FROM_DATABASE=Design Technology + +acpi:LPL*: + ID_VENDOR_FROM_DATABASE=LG Philips + +acpi:LSC*: + ID_VENDOR_FROM_DATABASE=LifeSize Communications + +acpi:LSD*: + ID_VENDOR_FROM_DATABASE=Intersil Corporation + +acpi:LSI*: + ID_VENDOR_FROM_DATABASE=Loughborough Sound Images + +acpi:LSJ*: + ID_VENDOR_FROM_DATABASE=LSI Japan Company Ltd + +acpi:LSL*: + ID_VENDOR_FROM_DATABASE=Logical Solutions + +acpi:LSP*: + ID_VENDOR_FROM_DATABASE=Lightspace Technologies + +acpi:LSY*: + ID_VENDOR_FROM_DATABASE=LSI Systems Inc + +acpi:LTC*: + ID_VENDOR_FROM_DATABASE=Labtec Inc + +acpi:LTI*: + ID_VENDOR_FROM_DATABASE=Jongshine Tech Inc + +acpi:LTK*: + ID_VENDOR_FROM_DATABASE=Lucidity Technology Company Ltd + +acpi:LTN*: + ID_VENDOR_FROM_DATABASE=Litronic Inc + +acpi:LTS*: + ID_VENDOR_FROM_DATABASE=LTS Scale LLC + +acpi:LTV*: + ID_VENDOR_FROM_DATABASE=Leitch Technology International Inc. + +acpi:LTW*: + ID_VENDOR_FROM_DATABASE=Lightware, Inc + +acpi:LUC*: + ID_VENDOR_FROM_DATABASE=Lucent Technologies + +acpi:LUM*: + ID_VENDOR_FROM_DATABASE=Lumagen, Inc. + +acpi:LUX*: + ID_VENDOR_FROM_DATABASE=Luxxell Research Inc + +acpi:LVI*: + ID_VENDOR_FROM_DATABASE=LVI Low Vision International AB + +acpi:LWC*: + ID_VENDOR_FROM_DATABASE=Labway Corporation + +acpi:LWR*: + ID_VENDOR_FROM_DATABASE=Lightware Visual Engineering + +acpi:LWW*: + ID_VENDOR_FROM_DATABASE=Lanier Worldwide + +acpi:LXC*: + ID_VENDOR_FROM_DATABASE=LXCO Technologies AG + +acpi:LXN*: + ID_VENDOR_FROM_DATABASE=Luxeon + +acpi:LXS*: + ID_VENDOR_FROM_DATABASE=ELEA CardWare + +acpi:LZX*: + ID_VENDOR_FROM_DATABASE=Lightwell Company Ltd + +acpi:MAC*: + ID_VENDOR_FROM_DATABASE=MAC System Company Ltd + +acpi:MAD*: + ID_VENDOR_FROM_DATABASE=Xedia Corporation + +acpi:MAE*: + ID_VENDOR_FROM_DATABASE=Maestro Pty Ltd + +acpi:MAG*: + ID_VENDOR_FROM_DATABASE=MAG InnoVision + +acpi:MAI*: + ID_VENDOR_FROM_DATABASE=Mutoh America Inc + +acpi:MAL*: + ID_VENDOR_FROM_DATABASE=Meridian Audio Ltd + +acpi:MAN*: + ID_VENDOR_FROM_DATABASE=LGIC + +acpi:MAS*: + ID_VENDOR_FROM_DATABASE=Mass Inc. + +acpi:MAT*: + ID_VENDOR_FROM_DATABASE=Matsushita Electric Ind. Company Ltd + +acpi:MAX*: + ID_VENDOR_FROM_DATABASE=Rogen Tech Distribution Inc + +acpi:MAY*: + ID_VENDOR_FROM_DATABASE=Maynard Electronics + +acpi:MAZ*: + ID_VENDOR_FROM_DATABASE=MAZeT GmbH + +acpi:MBC*: + ID_VENDOR_FROM_DATABASE=MBC + +acpi:MBD*: + ID_VENDOR_FROM_DATABASE=Microbus PLC + +acpi:MBM*: + ID_VENDOR_FROM_DATABASE=Marshall Electronics + +acpi:MBV*: + ID_VENDOR_FROM_DATABASE=Moreton Bay + +acpi:MCA*: + ID_VENDOR_FROM_DATABASE=American Nuclear Systems Inc + +acpi:MCC*: + ID_VENDOR_FROM_DATABASE=Micro Industries + +acpi:MCD*: + ID_VENDOR_FROM_DATABASE=McDATA Corporation + +acpi:MCE*: + ID_VENDOR_FROM_DATABASE=Metz-Werke GmbH & Co KG + +acpi:MCG*: + ID_VENDOR_FROM_DATABASE=Motorola Computer Group + +acpi:MCI*: + ID_VENDOR_FROM_DATABASE=Micronics Computers + +acpi:MCJ*: + ID_VENDOR_FROM_DATABASE=Medicaroid Corporation + +acpi:MCL*: + ID_VENDOR_FROM_DATABASE=Motorola Communications Israel + +acpi:MCM*: + ID_VENDOR_FROM_DATABASE=Metricom Inc + +acpi:MCN*: + ID_VENDOR_FROM_DATABASE=Micron Electronics Inc + +acpi:MCO*: + ID_VENDOR_FROM_DATABASE=Motion Computing Inc. + +acpi:MCP*: + ID_VENDOR_FROM_DATABASE=Magni Systems Inc + +acpi:MCQ*: + ID_VENDOR_FROM_DATABASE=Mat's Computers + +acpi:MCR*: + ID_VENDOR_FROM_DATABASE=Marina Communicaitons + +acpi:MCS*: + ID_VENDOR_FROM_DATABASE=Micro Computer Systems + +acpi:MCT*: + ID_VENDOR_FROM_DATABASE=Microtec + +acpi:MCX*: + ID_VENDOR_FROM_DATABASE=Millson Custom Solutions Inc. + +acpi:MCY*: + ID_VENDOR_FROM_DATABASE=Microdyne + +acpi:MDA*: + ID_VENDOR_FROM_DATABASE=Media4 Inc + +acpi:MDC*: + ID_VENDOR_FROM_DATABASE=Midori Electronics + +acpi:MDD*: + ID_VENDOR_FROM_DATABASE=MODIS + +acpi:MDF*: + ID_VENDOR_FROM_DATABASE=MILDEF AB + +acpi:MDG*: + ID_VENDOR_FROM_DATABASE=Madge Networks + +acpi:MDI*: + ID_VENDOR_FROM_DATABASE=Micro Design Inc + +acpi:MDK*: + ID_VENDOR_FROM_DATABASE=Mediatek Corporation + +acpi:MDO*: + ID_VENDOR_FROM_DATABASE=Panasonic + +acpi:MDR*: + ID_VENDOR_FROM_DATABASE=Medar Inc + +acpi:MDS*: + ID_VENDOR_FROM_DATABASE=Micro Display Systems Inc + +acpi:MDT*: + ID_VENDOR_FROM_DATABASE=Magus Data Tech + +acpi:MDV*: + ID_VENDOR_FROM_DATABASE=MET Development Inc + +acpi:MDX*: + ID_VENDOR_FROM_DATABASE=MicroDatec GmbH + +acpi:MDY*: + ID_VENDOR_FROM_DATABASE=Microdyne Inc + +acpi:MEC*: + ID_VENDOR_FROM_DATABASE=Mega System Technologies Inc + +acpi:MED*: + ID_VENDOR_FROM_DATABASE=Messeltronik Dresden GmbH + +acpi:MEE*: + ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Engineering Co., Ltd. + +acpi:MEG*: + ID_VENDOR_FROM_DATABASE=Abeam Tech Ltd. + +acpi:MEI*: + ID_VENDOR_FROM_DATABASE=Panasonic Industry Company + +acpi:MEJ*: + ID_VENDOR_FROM_DATABASE=Mac-Eight Co., LTD. + +acpi:MEK*: + ID_VENDOR_FROM_DATABASE=Mediaedge Corporation + +acpi:MEL*: + ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Corporation + +acpi:MEN*: + ID_VENDOR_FROM_DATABASE=MEN Mikroelectronik Nueruberg GmbH + +acpi:MEP*: + ID_VENDOR_FROM_DATABASE=Meld Technology + +acpi:MEQ*: + ID_VENDOR_FROM_DATABASE=Matelect Ltd. + +acpi:MET*: + ID_VENDOR_FROM_DATABASE=Metheus Corporation + +acpi:MEU*: + ID_VENDOR_FROM_DATABASE=MPL AG, Elektronik-Unternehmen + +acpi:MEX*: + ID_VENDOR_FROM_DATABASE=MSC Vertriebs GmbH + +acpi:MFG*: + ID_VENDOR_FROM_DATABASE=MicroField Graphics Inc + +acpi:MFI*: + ID_VENDOR_FROM_DATABASE=Micro Firmware + +acpi:MFR*: + ID_VENDOR_FROM_DATABASE=MediaFire Corp. + +acpi:MGA*: + ID_VENDOR_FROM_DATABASE=Mega System Technologies, Inc. + +acpi:MGC*: + ID_VENDOR_FROM_DATABASE=Mentor Graphics Corporation + +acpi:MGE*: + ID_VENDOR_FROM_DATABASE=Schneider Electric S.A. + +acpi:MGL*: + ID_VENDOR_FROM_DATABASE=M-G Technology Ltd + +acpi:MGT*: + ID_VENDOR_FROM_DATABASE=Megatech R & D Company + +acpi:MHQ*: + ID_VENDOR_FROM_DATABASE=Moxa Inc. + +acpi:MIC*: + ID_VENDOR_FROM_DATABASE=Micom Communications Inc + +acpi:MID*: + ID_VENDOR_FROM_DATABASE=miro Displays + +acpi:MII*: + ID_VENDOR_FROM_DATABASE=Mitec Inc + +acpi:MIL*: + ID_VENDOR_FROM_DATABASE=Marconi Instruments Ltd + +acpi:MIM*: + ID_VENDOR_FROM_DATABASE=Mimio – A Newell Rubbermaid Company + +acpi:MIN*: + ID_VENDOR_FROM_DATABASE=Minicom Digital Signage + +acpi:MIP*: + ID_VENDOR_FROM_DATABASE=micronpc.com + +acpi:MIR*: + ID_VENDOR_FROM_DATABASE=Miro Computer Prod. + +acpi:MIS*: + ID_VENDOR_FROM_DATABASE=Modular Industrial Solutions Inc + +acpi:MIT*: + ID_VENDOR_FROM_DATABASE=MCM Industrial Technology GmbH + +acpi:MIV*: + ID_VENDOR_FROM_DATABASE=MicroImage Video Systems + +acpi:MJI*: + ID_VENDOR_FROM_DATABASE=MARANTZ JAPAN, INC. + +acpi:MJS*: + ID_VENDOR_FROM_DATABASE=MJS Designs + +acpi:MKC*: + ID_VENDOR_FROM_DATABASE=Media Tek Inc. + +acpi:MKS*: + ID_VENDOR_FROM_DATABASE=MK Seiko Co., Ltd. + +acpi:MKT*: + ID_VENDOR_FROM_DATABASE=MICROTEK Inc. + +acpi:MKV*: + ID_VENDOR_FROM_DATABASE=Trtheim Technology + +acpi:MLD*: + ID_VENDOR_FROM_DATABASE=Deep Video Imaging Ltd + +acpi:MLG*: + ID_VENDOR_FROM_DATABASE=Micrologica AG + +acpi:MLI*: + ID_VENDOR_FROM_DATABASE=McIntosh Laboratory Inc. + +acpi:MLL*: + ID_VENDOR_FROM_DATABASE=Millogic Ltd. + +acpi:MLM*: + ID_VENDOR_FROM_DATABASE=Millennium Engineering Inc + +acpi:MLN*: + ID_VENDOR_FROM_DATABASE=Mark Levinson + +acpi:MLP*: + ID_VENDOR_FROM_DATABASE=Magic Leap + +acpi:MLS*: + ID_VENDOR_FROM_DATABASE=Milestone EPE + +acpi:MLT*: + ID_VENDOR_FROM_DATABASE=Wanlida Group Co., Ltd. + +acpi:MLX*: + ID_VENDOR_FROM_DATABASE=Mylex Corporation + +acpi:MMA*: + ID_VENDOR_FROM_DATABASE=Micromedia AG + +acpi:MMD*: + ID_VENDOR_FROM_DATABASE=Micromed Biotecnologia Ltd + +acpi:MMF*: + ID_VENDOR_FROM_DATABASE=Minnesota Mining and Manufacturing + +acpi:MMI*: + ID_VENDOR_FROM_DATABASE=Multimax + +acpi:MMM*: + ID_VENDOR_FROM_DATABASE=Electronic Measurements + +acpi:MMN*: + ID_VENDOR_FROM_DATABASE=MiniMan Inc + +acpi:MMS*: + ID_VENDOR_FROM_DATABASE=MMS Electronics + +acpi:MMT*: + ID_VENDOR_FROM_DATABASE=MIMO Monitors + +acpi:MNC*: + ID_VENDOR_FROM_DATABASE=Mini Micro Methods Ltd + +acpi:MNI*: + ID_VENDOR_FROM_DATABASE=Marseille, Inc. + +acpi:MNL*: + ID_VENDOR_FROM_DATABASE=Monorail Inc + +acpi:MNP*: + ID_VENDOR_FROM_DATABASE=Microcom + +acpi:MOC*: + ID_VENDOR_FROM_DATABASE=Matrix Orbital Corporation + +acpi:MOD*: + ID_VENDOR_FROM_DATABASE=Modular Technology + +acpi:MOM*: + ID_VENDOR_FROM_DATABASE=Momentum Data Systems + +acpi:MON*: + ID_VENDOR_FROM_DATABASE=Daewoo + +acpi:MOS*: + ID_VENDOR_FROM_DATABASE=Moses Corporation + +acpi:MOT*: + ID_VENDOR_FROM_DATABASE=Motorola UDS + +acpi:MPC*: + ID_VENDOR_FROM_DATABASE=M-Pact Inc + +acpi:MPI*: + ID_VENDOR_FROM_DATABASE=Mediatrix Peripherals Inc + +acpi:MPJ*: + ID_VENDOR_FROM_DATABASE=Microlab + +acpi:MPL*: + ID_VENDOR_FROM_DATABASE=Maple Research Inst. Company Ltd + +acpi:MPN*: + ID_VENDOR_FROM_DATABASE=Mainpine Limited + +acpi:MPS*: + ID_VENDOR_FROM_DATABASE=mps Software GmbH + +acpi:MPX*: + ID_VENDOR_FROM_DATABASE=Micropix Technologies, Ltd. + +acpi:MQP*: + ID_VENDOR_FROM_DATABASE=MultiQ Products AB + +acpi:MRA*: + ID_VENDOR_FROM_DATABASE=Miranda Technologies Inc + +acpi:MRC*: + ID_VENDOR_FROM_DATABASE=Marconi Simulation & Ty-Coch Way Training + +acpi:MRD*: + ID_VENDOR_FROM_DATABASE=MicroDisplay Corporation + +acpi:MRK*: + ID_VENDOR_FROM_DATABASE=Maruko & Company Ltd + +acpi:MRL*: + ID_VENDOR_FROM_DATABASE=Miratel + +acpi:MRO*: + ID_VENDOR_FROM_DATABASE=Medikro Oy + +acpi:MRT*: + ID_VENDOR_FROM_DATABASE=Merging Technologies + +acpi:MSA*: + ID_VENDOR_FROM_DATABASE=Micro Systemation AB + +acpi:MSC*: + ID_VENDOR_FROM_DATABASE=Mouse Systems Corporation + +acpi:MSD*: + ID_VENDOR_FROM_DATABASE=Datenerfassungs- und Informationssysteme + +acpi:MSF*: + ID_VENDOR_FROM_DATABASE=M-Systems Flash Disk Pioneers + +acpi:MSG*: + ID_VENDOR_FROM_DATABASE=MSI GmbH + +acpi:MSH*: + ID_VENDOR_FROM_DATABASE=Microsoft + +acpi:MSI*: + ID_VENDOR_FROM_DATABASE=Microstep + +acpi:MSK*: + ID_VENDOR_FROM_DATABASE=Megasoft Inc + +acpi:MSL*: + ID_VENDOR_FROM_DATABASE=MicroSlate Inc. + +acpi:MSM*: + ID_VENDOR_FROM_DATABASE=Advanced Digital Systems + +acpi:MSP*: + ID_VENDOR_FROM_DATABASE=Mistral Solutions [P] Ltd. + +acpi:MSR*: + ID_VENDOR_FROM_DATABASE=MASPRO DENKOH Corp. + +acpi:MST*: + ID_VENDOR_FROM_DATABASE=MS Telematica + +acpi:MSU*: + ID_VENDOR_FROM_DATABASE=motorola + +acpi:MSV*: + ID_VENDOR_FROM_DATABASE=Mosgi Corporation + +acpi:MSX*: + ID_VENDOR_FROM_DATABASE=Micomsoft Co., Ltd. + +acpi:MSY*: + ID_VENDOR_FROM_DATABASE=MicroTouch Systems Inc + +acpi:MTA*: + ID_VENDOR_FROM_DATABASE=Meta Watch Ltd + +acpi:MTB*: + ID_VENDOR_FROM_DATABASE=Media Technologies Ltd. + +acpi:MTC*: + ID_VENDOR_FROM_DATABASE=Mars-Tech Corporation + +acpi:MTD*: + ID_VENDOR_FROM_DATABASE=MindTech Display Co. Ltd + +acpi:MTE*: + ID_VENDOR_FROM_DATABASE=MediaTec GmbH + +acpi:MTH*: + ID_VENDOR_FROM_DATABASE=Micro-Tech Hearing Instruments + +acpi:MTI*: + ID_VENDOR_FROM_DATABASE=MaxCom Technical Inc + +acpi:MTJ*: + ID_VENDOR_FROM_DATABASE=MicroTechnica Co.,Ltd. + +acpi:MTK*: + ID_VENDOR_FROM_DATABASE=Microtek International Inc. + +acpi:MTL*: + ID_VENDOR_FROM_DATABASE=Mitel Corporation + +acpi:MTM*: + ID_VENDOR_FROM_DATABASE=Motium + +acpi:MTN*: + ID_VENDOR_FROM_DATABASE=Mtron Storage Technology Co., Ltd. + +acpi:MTR*: + ID_VENDOR_FROM_DATABASE=Mitron computer Inc + +acpi:MTS*: + ID_VENDOR_FROM_DATABASE=Multi-Tech Systems + +acpi:MTU*: + ID_VENDOR_FROM_DATABASE=Mark of the Unicorn Inc + +acpi:MTX*: + ID_VENDOR_FROM_DATABASE=Matrox + +acpi:MUD*: + ID_VENDOR_FROM_DATABASE=Multi-Dimension Institute + +acpi:MUK*: + ID_VENDOR_FROM_DATABASE=Mainpine Limited + +acpi:MVD*: + ID_VENDOR_FROM_DATABASE=Microvitec PLC + +acpi:MVI*: + ID_VENDOR_FROM_DATABASE=Media Vision Inc + +acpi:MVM*: + ID_VENDOR_FROM_DATABASE=SOBO VISION + +acpi:MVN*: + ID_VENDOR_FROM_DATABASE=Meta Company + +acpi:MVR*: + ID_VENDOR_FROM_DATABASE=MediCapture, Inc. + +acpi:MVS*: + ID_VENDOR_FROM_DATABASE=Microvision + +acpi:MVX*: + ID_VENDOR_FROM_DATABASE=COM 1 + +acpi:MWI*: + ID_VENDOR_FROM_DATABASE=Multiwave Innovation Pte Ltd + +acpi:MWR*: + ID_VENDOR_FROM_DATABASE=mware + +acpi:MWY*: + ID_VENDOR_FROM_DATABASE=Microway Inc + +acpi:MXD*: + ID_VENDOR_FROM_DATABASE=MaxData Computer GmbH & Co.KG + +acpi:MXI*: + ID_VENDOR_FROM_DATABASE=Macronix Inc + +acpi:MXL*: + ID_VENDOR_FROM_DATABASE=Hitachi Maxell, Ltd. + +acpi:MXP*: + ID_VENDOR_FROM_DATABASE=Maxpeed Corporation + +acpi:MXT*: + ID_VENDOR_FROM_DATABASE=Maxtech Corporation + +acpi:MXV*: + ID_VENDOR_FROM_DATABASE=MaxVision Corporation + +acpi:MYA*: + ID_VENDOR_FROM_DATABASE=Monydata + +acpi:MYR*: + ID_VENDOR_FROM_DATABASE=Myriad Solutions Ltd + +acpi:MYX*: + ID_VENDOR_FROM_DATABASE=Micronyx Inc + +acpi:NAC*: + ID_VENDOR_FROM_DATABASE=Ncast Corporation + +acpi:NAD*: + ID_VENDOR_FROM_DATABASE=NAD Electronics + +acpi:NAK*: + ID_VENDOR_FROM_DATABASE=Nakano Engineering Co.,Ltd. + +acpi:NAL*: + ID_VENDOR_FROM_DATABASE=Network Alchemy + +acpi:NAN*: + ID_VENDOR_FROM_DATABASE=Nanao + +acpi:NAT*: + ID_VENDOR_FROM_DATABASE=NaturalPoint Inc. + +acpi:NAV*: + ID_VENDOR_FROM_DATABASE=Navigation Corporation + +acpi:NAX*: + ID_VENDOR_FROM_DATABASE=Naxos Tecnologia + +acpi:NBL*: + ID_VENDOR_FROM_DATABASE=N*Able Technologies Inc + +acpi:NBS*: + ID_VENDOR_FROM_DATABASE=National Key Lab. on ISN + +acpi:NBT*: + ID_VENDOR_FROM_DATABASE=NingBo Bestwinning Technology CO., Ltd + +acpi:NCA*: + ID_VENDOR_FROM_DATABASE=Nixdorf Company + +acpi:NCC*: + ID_VENDOR_FROM_DATABASE=NCR Corporation + +acpi:NCE*: + ID_VENDOR_FROM_DATABASE=Norcent Technology, Inc. + +acpi:NCI*: + ID_VENDOR_FROM_DATABASE=NewCom Inc + +acpi:NCL*: + ID_VENDOR_FROM_DATABASE=NetComm Ltd + +acpi:NCP*: + ID_VENDOR_FROM_DATABASE=Najing CEC Panda FPD Technology CO. ltd + +acpi:NCR*: + ID_VENDOR_FROM_DATABASE=NCR Electronics + +acpi:NCS*: + ID_VENDOR_FROM_DATABASE=Northgate Computer Systems + +acpi:NCT*: + ID_VENDOR_FROM_DATABASE=NEC CustomTechnica, Ltd. + +acpi:NDC*: + ID_VENDOR_FROM_DATABASE=National DataComm Corporaiton + +acpi:NDF*: + ID_VENDOR_FROM_DATABASE=NDF Special Light Products B.V. + +acpi:NDI*: + ID_VENDOR_FROM_DATABASE=National Display Systems + +acpi:NDK*: + ID_VENDOR_FROM_DATABASE=Naitoh Densei CO., LTD. + +acpi:NDL*: + ID_VENDOR_FROM_DATABASE=Network Designers + +acpi:NDS*: + ID_VENDOR_FROM_DATABASE=Nokia Data + +acpi:NEC*: + ID_VENDOR_FROM_DATABASE=NEC Corporation + +acpi:NEO*: + ID_VENDOR_FROM_DATABASE=NEO TELECOM CO.,LTD. + +acpi:NES*: + ID_VENDOR_FROM_DATABASE=INNES + +acpi:NET*: + ID_VENDOR_FROM_DATABASE=Mettler Toledo + +acpi:NEU*: + ID_VENDOR_FROM_DATABASE=NEUROTEC - EMPRESA DE PESQUISA E DESENVOLVIMENTO EM BIOMEDICINA + +acpi:NEX*: + ID_VENDOR_FROM_DATABASE=Nexgen Mediatech Inc., + +acpi:NFC*: + ID_VENDOR_FROM_DATABASE=BTC Korea Co., Ltd + +acpi:NFS*: + ID_VENDOR_FROM_DATABASE=Number Five Software + +acpi:NGC*: + ID_VENDOR_FROM_DATABASE=Network General + +acpi:NGS*: + ID_VENDOR_FROM_DATABASE=A D S Exports + +acpi:NHT*: + ID_VENDOR_FROM_DATABASE=Vinci Labs + +acpi:NIC*: + ID_VENDOR_FROM_DATABASE=National Instruments Corporation + +acpi:NIS*: + ID_VENDOR_FROM_DATABASE=Nissei Electric Company + +acpi:NIT*: + ID_VENDOR_FROM_DATABASE=Network Info Technology + +acpi:NIX*: + ID_VENDOR_FROM_DATABASE=Seanix Technology Inc + +acpi:NLC*: + ID_VENDOR_FROM_DATABASE=Next Level Communications + +acpi:NME*: + ID_VENDOR_FROM_DATABASE=Navico, Inc. + +acpi:NMP*: + ID_VENDOR_FROM_DATABASE=Nokia Mobile Phones + +acpi:NMS*: + ID_VENDOR_FROM_DATABASE=Natural Micro System + +acpi:NMV*: + ID_VENDOR_FROM_DATABASE=NEC-Mitsubishi Electric Visual Systems Corporation + +acpi:NMX*: + ID_VENDOR_FROM_DATABASE=Neomagic + +acpi:NNC*: + ID_VENDOR_FROM_DATABASE=NNC + +acpi:NOD*: + ID_VENDOR_FROM_DATABASE=3NOD Digital Technology Co. Ltd. + +acpi:NOE*: + ID_VENDOR_FROM_DATABASE=NordicEye AB + +acpi:NOI*: + ID_VENDOR_FROM_DATABASE=North Invent A/S + +acpi:NOK*: + ID_VENDOR_FROM_DATABASE=Nokia Display Products + +acpi:NOR*: + ID_VENDOR_FROM_DATABASE=Norand Corporation + +acpi:NOT*: + ID_VENDOR_FROM_DATABASE=Not Limited Inc + +acpi:NPA*: + ID_VENDOR_FROM_DATABASE=Arvanics + +acpi:NPI*: + ID_VENDOR_FROM_DATABASE=Network Peripherals Inc + +acpi:NRI*: + ID_VENDOR_FROM_DATABASE=Noritake Itron Corporation + +acpi:NRL*: + ID_VENDOR_FROM_DATABASE=U.S. Naval Research Lab + +acpi:NRT*: + ID_VENDOR_FROM_DATABASE=Beijing Northern Radiantelecom Co. + +acpi:NRV*: + ID_VENDOR_FROM_DATABASE=Taugagreining hf + +acpi:NSA*: + ID_VENDOR_FROM_DATABASE=NeuroSky, Inc. + +acpi:NSC*: + ID_VENDOR_FROM_DATABASE=National Semiconductor Corporation + +acpi:NSI*: + ID_VENDOR_FROM_DATABASE=NISSEI ELECTRIC CO.,LTD + +acpi:NSP*: + ID_VENDOR_FROM_DATABASE=Nspire System Inc. + +acpi:NSS*: + ID_VENDOR_FROM_DATABASE=Newport Systems Solutions + +acpi:NST*: + ID_VENDOR_FROM_DATABASE=Network Security Technology Co + +acpi:NTC*: + ID_VENDOR_FROM_DATABASE=NeoTech S.R.L + +acpi:NTI*: + ID_VENDOR_FROM_DATABASE=New Tech Int'l Company + +acpi:NTK*: + ID_VENDOR_FROM_DATABASE=NewTek + +acpi:NTL*: + ID_VENDOR_FROM_DATABASE=National Transcomm. Ltd + +acpi:NTN*: + ID_VENDOR_FROM_DATABASE=Nuvoton Technology Corporation + +acpi:NTR*: + ID_VENDOR_FROM_DATABASE=N-trig Innovative Technologies, Inc. + +acpi:NTS*: + ID_VENDOR_FROM_DATABASE=Nits Technology Inc. + +acpi:NTT*: + ID_VENDOR_FROM_DATABASE=NTT Advanced Technology Corporation + +acpi:NTW*: + ID_VENDOR_FROM_DATABASE=Networth Inc + +acpi:NTX*: + ID_VENDOR_FROM_DATABASE=Netaccess Inc + +acpi:NUG*: + ID_VENDOR_FROM_DATABASE=NU Technology, Inc. + +acpi:NUI*: + ID_VENDOR_FROM_DATABASE=NU Inc. + +acpi:NVC*: + ID_VENDOR_FROM_DATABASE=NetVision Corporation + +acpi:NVD*: + ID_VENDOR_FROM_DATABASE=Nvidia + +acpi:NVI*: + ID_VENDOR_FROM_DATABASE=NuVision US, Inc. + +acpi:NVL*: + ID_VENDOR_FROM_DATABASE=Novell Inc + +acpi:NVT*: + ID_VENDOR_FROM_DATABASE=Navatek Engineering Corporation + +acpi:NWC*: + ID_VENDOR_FROM_DATABASE=NW Computer Engineering + +acpi:NWP*: + ID_VENDOR_FROM_DATABASE=NovaWeb Technologies Inc + +acpi:NWS*: + ID_VENDOR_FROM_DATABASE=Newisys, Inc. + +acpi:NXC*: + ID_VENDOR_FROM_DATABASE=NextCom K.K. + +acpi:NXG*: + ID_VENDOR_FROM_DATABASE=Nexgen + +acpi:NXP*: + ID_VENDOR_FROM_DATABASE=NXP Semiconductors bv. + +acpi:NXQ*: + ID_VENDOR_FROM_DATABASE=Nexiq Technologies, Inc. + +acpi:NXS*: + ID_VENDOR_FROM_DATABASE=Technology Nexus Secure Open Systems AB + +acpi:NYC*: + ID_VENDOR_FROM_DATABASE=Nakayo Relecommunications, Inc. + +acpi:OAK*: + ID_VENDOR_FROM_DATABASE=Oak Tech Inc + +acpi:OAS*: + ID_VENDOR_FROM_DATABASE=Oasys Technology Company + +acpi:OBS*: + ID_VENDOR_FROM_DATABASE=Optibase Technologies + +acpi:OCD*: + ID_VENDOR_FROM_DATABASE=Macraigor Systems Inc + +acpi:OCN*: + ID_VENDOR_FROM_DATABASE=Olfan + +acpi:OCS*: + ID_VENDOR_FROM_DATABASE=Open Connect Solutions + +acpi:ODM*: + ID_VENDOR_FROM_DATABASE=ODME Inc. + +acpi:ODR*: + ID_VENDOR_FROM_DATABASE=Odrac + +acpi:OEC*: + ID_VENDOR_FROM_DATABASE=ORION ELECTRIC CO.,LTD + +acpi:OEI*: + ID_VENDOR_FROM_DATABASE=Optum Engineering Inc. + +acpi:OHW*: + ID_VENDOR_FROM_DATABASE=M-Labs Limited + +acpi:OIC*: + ID_VENDOR_FROM_DATABASE=Option Industrial Computers + +acpi:OIM*: + ID_VENDOR_FROM_DATABASE=Option International + +acpi:OIN*: + ID_VENDOR_FROM_DATABASE=Option International + +acpi:OKI*: + ID_VENDOR_FROM_DATABASE=OKI Electric Industrial Company Ltd + +acpi:OLC*: + ID_VENDOR_FROM_DATABASE=Olicom A/S + +acpi:OLD*: + ID_VENDOR_FROM_DATABASE=Olidata S.p.A. + +acpi:OLI*: + ID_VENDOR_FROM_DATABASE=Olivetti + +acpi:OLT*: + ID_VENDOR_FROM_DATABASE=Olitec S.A. + +acpi:OLV*: + ID_VENDOR_FROM_DATABASE=Olitec S.A. + +acpi:OLY*: + ID_VENDOR_FROM_DATABASE=OLYMPUS CORPORATION + +acpi:OMC*: + ID_VENDOR_FROM_DATABASE=OBJIX Multimedia Corporation + +acpi:OMN*: + ID_VENDOR_FROM_DATABASE=Omnitel + +acpi:OMR*: + ID_VENDOR_FROM_DATABASE=Omron Corporation + +acpi:ONE*: + ID_VENDOR_FROM_DATABASE=Oneac Corporation + +acpi:ONK*: + ID_VENDOR_FROM_DATABASE=ONKYO Corporation + +acpi:ONL*: + ID_VENDOR_FROM_DATABASE=OnLive, Inc + +acpi:ONS*: + ID_VENDOR_FROM_DATABASE=On Systems Inc + +acpi:ONW*: + ID_VENDOR_FROM_DATABASE=OPEN Networks Ltd + +acpi:ONX*: + ID_VENDOR_FROM_DATABASE=SOMELEC Z.I. Du Vert Galanta + +acpi:OOS*: + ID_VENDOR_FROM_DATABASE=OSRAM + +acpi:OPC*: + ID_VENDOR_FROM_DATABASE=Opcode Inc + +acpi:OPI*: + ID_VENDOR_FROM_DATABASE=D.N.S. Corporation + +acpi:OPP*: + ID_VENDOR_FROM_DATABASE=OPPO Digital, Inc. + +acpi:OPT*: + ID_VENDOR_FROM_DATABASE=OPTi Inc + +acpi:OPV*: + ID_VENDOR_FROM_DATABASE=Optivision Inc + +acpi:OQI*: + ID_VENDOR_FROM_DATABASE=Oksori Company Ltd + +acpi:ORG*: + ID_VENDOR_FROM_DATABASE=ORGA Kartensysteme GmbH + +acpi:ORI*: + ID_VENDOR_FROM_DATABASE=OSR Open Systems Resources, Inc. + +acpi:ORN*: + ID_VENDOR_FROM_DATABASE=ORION ELECTRIC CO., LTD. + +acpi:OSA*: + ID_VENDOR_FROM_DATABASE=OSAKA Micro Computer, Inc. + +acpi:OSD*: + ID_VENDOR_FROM_DATABASE=Optical Systems Design Pty Ltd + +acpi:OSI*: + ID_VENDOR_FROM_DATABASE=Open Stack, Inc. + +acpi:OSP*: + ID_VENDOR_FROM_DATABASE=OPTI-UPS Corporation + +acpi:OSR*: + ID_VENDOR_FROM_DATABASE=Oksori Company Ltd + +acpi:OTB*: + ID_VENDOR_FROM_DATABASE=outsidetheboxstuff.com + +acpi:OTI*: + ID_VENDOR_FROM_DATABASE=Orchid Technology + +acpi:OTK*: + ID_VENDOR_FROM_DATABASE=OmniTek + +acpi:OTM*: + ID_VENDOR_FROM_DATABASE=Optoma Corporation + +acpi:OTT*: + ID_VENDOR_FROM_DATABASE=OPTO22, Inc. + +acpi:OUK*: + ID_VENDOR_FROM_DATABASE=OUK Company Ltd + +acpi:OVR*: + ID_VENDOR_FROM_DATABASE=Oculus VR, Inc. + +acpi:OWL*: + ID_VENDOR_FROM_DATABASE=Mediacom Technologies Pte Ltd + +acpi:OXU*: + ID_VENDOR_FROM_DATABASE=Oxus Research S.A. + +acpi:OYO*: + ID_VENDOR_FROM_DATABASE=Shadow Systems + +acpi:OZC*: + ID_VENDOR_FROM_DATABASE=OZ Corporation + +acpi:OZO*: + ID_VENDOR_FROM_DATABASE=Tribe Computer Works Inc + +acpi:PAC*: + ID_VENDOR_FROM_DATABASE=Pacific Avionics Corporation + +acpi:PAD*: + ID_VENDOR_FROM_DATABASE=Promotion and Display Technology Ltd. + +acpi:PAK*: + ID_VENDOR_FROM_DATABASE=Many CNC System Co., Ltd. + +acpi:PAM*: + ID_VENDOR_FROM_DATABASE=Peter Antesberger Messtechnik + +acpi:PAN*: + ID_VENDOR_FROM_DATABASE=The Panda Project + +acpi:PAR*: + ID_VENDOR_FROM_DATABASE=Parallan Comp Inc + +acpi:PBI*: + ID_VENDOR_FROM_DATABASE=Pitney Bowes + +acpi:PBL*: + ID_VENDOR_FROM_DATABASE=Packard Bell Electronics + +acpi:PBN*: + ID_VENDOR_FROM_DATABASE=Packard Bell NEC + +acpi:PBV*: + ID_VENDOR_FROM_DATABASE=Pitney Bowes + +acpi:PCA*: + ID_VENDOR_FROM_DATABASE=Philips BU Add On Card + +acpi:PCB*: + ID_VENDOR_FROM_DATABASE=OCTAL S.A. + +acpi:PCC*: + ID_VENDOR_FROM_DATABASE=PowerCom Technology Company Ltd + +acpi:PCG*: + ID_VENDOR_FROM_DATABASE=First Industrial Computer Inc + +acpi:PCI*: + ID_VENDOR_FROM_DATABASE=Pioneer Computer Inc + +acpi:PCK*: + ID_VENDOR_FROM_DATABASE=PCBANK21 + +acpi:PCL*: + ID_VENDOR_FROM_DATABASE=pentel.co.,ltd + +acpi:PCM*: + ID_VENDOR_FROM_DATABASE=PCM Systems Corporation + +acpi:PCO*: + ID_VENDOR_FROM_DATABASE=Performance Concepts Inc., + +acpi:PCP*: + ID_VENDOR_FROM_DATABASE=Procomp USA Inc + +acpi:PCS*: + ID_VENDOR_FROM_DATABASE=TOSHIBA PERSONAL COMPUTER SYSTEM CORPRATION + +acpi:PCT*: + ID_VENDOR_FROM_DATABASE=PC-Tel Inc + +acpi:PCW*: + ID_VENDOR_FROM_DATABASE=Pacific CommWare Inc + +acpi:PCX*: + ID_VENDOR_FROM_DATABASE=PC Xperten + +acpi:PDC*: + ID_VENDOR_FROM_DATABASE=Polaroid + +acpi:PDM*: + ID_VENDOR_FROM_DATABASE=Psion Dacom Plc. + +acpi:PDN*: + ID_VENDOR_FROM_DATABASE=AT&T Paradyne + +acpi:PDR*: + ID_VENDOR_FROM_DATABASE=Pure Data Inc + +acpi:PDS*: + ID_VENDOR_FROM_DATABASE=PD Systems International Ltd + +acpi:PDT*: + ID_VENDOR_FROM_DATABASE=PDTS - Prozessdatentechnik und Systeme + +acpi:PDV*: + ID_VENDOR_FROM_DATABASE=Prodrive B.V. + +acpi:PEC*: + ID_VENDOR_FROM_DATABASE=POTRANS Electrical Corp. + +acpi:PEG*: + ID_VENDOR_FROM_DATABASE=Pegatron Corporation + +acpi:PEI*: + ID_VENDOR_FROM_DATABASE=PEI Electronics Inc + +acpi:PEL*: + ID_VENDOR_FROM_DATABASE=Primax Electric Ltd + +acpi:PEN*: + ID_VENDOR_FROM_DATABASE=Interactive Computer Products Inc + +acpi:PEP*: + ID_VENDOR_FROM_DATABASE=Peppercon AG + +acpi:PER*: + ID_VENDOR_FROM_DATABASE=Perceptive Signal Technologies + +acpi:PET*: + ID_VENDOR_FROM_DATABASE=Practical Electronic Tools + +acpi:PFT*: + ID_VENDOR_FROM_DATABASE=Telia ProSoft AB + +acpi:PGI*: + ID_VENDOR_FROM_DATABASE=PACSGEAR, Inc. + +acpi:PGM*: + ID_VENDOR_FROM_DATABASE=Paradigm Advanced Research Centre + +acpi:PGP*: + ID_VENDOR_FROM_DATABASE=propagamma kommunikation + +acpi:PGS*: + ID_VENDOR_FROM_DATABASE=Princeton Graphic Systems + +acpi:PHC*: + ID_VENDOR_FROM_DATABASE=Pijnenburg Beheer N.V. + +acpi:PHE*: + ID_VENDOR_FROM_DATABASE=Philips Medical Systems Boeblingen GmbH + +acpi:PHL*: + ID_VENDOR_FROM_DATABASE=Philips Consumer Electronics Company + +acpi:PHO*: + ID_VENDOR_FROM_DATABASE=Photonics Systems Inc. + +acpi:PHS*: + ID_VENDOR_FROM_DATABASE=Philips Communication Systems + +acpi:PHY*: + ID_VENDOR_FROM_DATABASE=Phylon Communications + +acpi:PIC*: + ID_VENDOR_FROM_DATABASE=Picturall Ltd. + +acpi:PIE*: + ID_VENDOR_FROM_DATABASE=Pacific Image Electronics Company Ltd + +acpi:PIM*: + ID_VENDOR_FROM_DATABASE=Prism, LLC + +acpi:PIO*: + ID_VENDOR_FROM_DATABASE=Pioneer Electronic Corporation + +acpi:PIS*: + ID_VENDOR_FROM_DATABASE=TECNART CO.,LTD. + +acpi:PIX*: + ID_VENDOR_FROM_DATABASE=Pixie Tech Inc + +acpi:PJA*: + ID_VENDOR_FROM_DATABASE=Projecta + +acpi:PJD*: + ID_VENDOR_FROM_DATABASE=Projectiondesign AS + +acpi:PJT*: + ID_VENDOR_FROM_DATABASE=Pan Jit International Inc. + +acpi:PKA*: + ID_VENDOR_FROM_DATABASE=Acco UK Ltd. + +acpi:PLC*: + ID_VENDOR_FROM_DATABASE=Pro-Log Corporation + +acpi:PLF*: + ID_VENDOR_FROM_DATABASE=Panasonic Avionics Corporation + +acpi:PLM*: + ID_VENDOR_FROM_DATABASE=PROLINK Microsystems Corp. + +acpi:PLT*: + ID_VENDOR_FROM_DATABASE=PT Hartono Istana Teknologi + +acpi:PLV*: + ID_VENDOR_FROM_DATABASE=PLUS Vision Corp. + +acpi:PLX*: + ID_VENDOR_FROM_DATABASE=Parallax Graphics + +acpi:PLY*: + ID_VENDOR_FROM_DATABASE=Polycom Inc. + +acpi:PMC*: + ID_VENDOR_FROM_DATABASE=PMC Consumer Electronics Ltd + +acpi:PMD*: + ID_VENDOR_FROM_DATABASE=TDK USA Corporation + +acpi:PMM*: + ID_VENDOR_FROM_DATABASE=Point Multimedia System + +acpi:PMS*: + ID_VENDOR_FROM_DATABASE=Pabian Embedded Systems + +acpi:PMT*: + ID_VENDOR_FROM_DATABASE=Promate Electronic Co., Ltd. + +acpi:PMX*: + ID_VENDOR_FROM_DATABASE=Photomatrix + +acpi:PNG*: + ID_VENDOR_FROM_DATABASE=Microsoft + +acpi:PNL*: + ID_VENDOR_FROM_DATABASE=Panelview, Inc. + +acpi:PNR*: + ID_VENDOR_FROM_DATABASE=Planar Systems, Inc. + +acpi:PNS*: + ID_VENDOR_FROM_DATABASE=PanaScope + +acpi:PNT*: + ID_VENDOR_FROM_DATABASE=HOYA Corporation PENTAX Lifecare Division + +acpi:PNX*: + ID_VENDOR_FROM_DATABASE=Phoenix Technologies, Ltd. + +acpi:POL*: + ID_VENDOR_FROM_DATABASE=PolyComp (PTY) Ltd. + +acpi:PON*: + ID_VENDOR_FROM_DATABASE=Perpetual Technologies, LLC + +acpi:POR*: + ID_VENDOR_FROM_DATABASE=Portalis LC + +acpi:POS*: + ID_VENDOR_FROM_DATABASE=Positivo Tecnologia S.A. + +acpi:POT*: + ID_VENDOR_FROM_DATABASE=Parrot + +acpi:PPC*: + ID_VENDOR_FROM_DATABASE=Phoenixtec Power Company Ltd + +acpi:PPD*: + ID_VENDOR_FROM_DATABASE=MEPhI + +acpi:PPI*: + ID_VENDOR_FROM_DATABASE=Practical Peripherals + +acpi:PPM*: + ID_VENDOR_FROM_DATABASE=Clinton Electronics Corp. + +acpi:PPP*: + ID_VENDOR_FROM_DATABASE=Purup Prepress AS + +acpi:PPR*: + ID_VENDOR_FROM_DATABASE=PicPro + +acpi:PPX*: + ID_VENDOR_FROM_DATABASE=Perceptive Pixel Inc. + +acpi:PQI*: + ID_VENDOR_FROM_DATABASE=Pixel Qi + +acpi:PRA*: + ID_VENDOR_FROM_DATABASE=PRO/AUTOMATION + +acpi:PRC*: + ID_VENDOR_FROM_DATABASE=PerComm + +acpi:PRD*: + ID_VENDOR_FROM_DATABASE=Praim S.R.L. + +acpi:PRF*: + ID_VENDOR_FROM_DATABASE=Schneider Electric Japan Holdings, Ltd. + +acpi:PRG*: + ID_VENDOR_FROM_DATABASE=The Phoenix Research Group Inc + +acpi:PRI*: + ID_VENDOR_FROM_DATABASE=Priva Hortimation BV + +acpi:PRM*: + ID_VENDOR_FROM_DATABASE=Prometheus + +acpi:PRO*: + ID_VENDOR_FROM_DATABASE=Proteon + +acpi:PRP*: + ID_VENDOR_FROM_DATABASE=UEFI Forum + +acpi:PRS*: + ID_VENDOR_FROM_DATABASE=Leutron Vision + +acpi:PRT*: + ID_VENDOR_FROM_DATABASE=Parade Technologies, Ltd. + +acpi:PRX*: + ID_VENDOR_FROM_DATABASE=Proxima Corporation + +acpi:PSA*: + ID_VENDOR_FROM_DATABASE=Advanced Signal Processing Technologies + +acpi:PSC*: + ID_VENDOR_FROM_DATABASE=Philips Semiconductors + +acpi:PSD*: + ID_VENDOR_FROM_DATABASE=Peus-Systems GmbH + +acpi:PSE*: + ID_VENDOR_FROM_DATABASE=Practical Solutions Pte., Ltd. + +acpi:PSI*: + ID_VENDOR_FROM_DATABASE=PSI-Perceptive Solutions Inc + +acpi:PSL*: + ID_VENDOR_FROM_DATABASE=Perle Systems Limited + +acpi:PSM*: + ID_VENDOR_FROM_DATABASE=Prosum + +acpi:PST*: + ID_VENDOR_FROM_DATABASE=Global Data SA + +acpi:PSY*: + ID_VENDOR_FROM_DATABASE=Prodea Systems Inc. + +acpi:PTA*: + ID_VENDOR_FROM_DATABASE=PAR Tech Inc. + +acpi:PTC*: + ID_VENDOR_FROM_DATABASE=PS Technology Corporation + +acpi:PTG*: + ID_VENDOR_FROM_DATABASE=Cipher Systems Inc + +acpi:PTH*: + ID_VENDOR_FROM_DATABASE=Pathlight Technology Inc + +acpi:PTI*: + ID_VENDOR_FROM_DATABASE=Promise Technology Inc + +acpi:PTL*: + ID_VENDOR_FROM_DATABASE=Pantel Inc + +acpi:PTS*: + ID_VENDOR_FROM_DATABASE=Plain Tree Systems Inc + +acpi:PUL*: + ID_VENDOR_FROM_DATABASE=Pulse-Eight Ltd + +acpi:PVG*: + ID_VENDOR_FROM_DATABASE=Proview Global Co., Ltd + +acpi:PVI*: + ID_VENDOR_FROM_DATABASE=Prime view international Co., Ltd + +acpi:PVM*: + ID_VENDOR_FROM_DATABASE=Penta Studiotechnik GmbH + +acpi:PVN*: + ID_VENDOR_FROM_DATABASE=Pixel Vision + +acpi:PVP*: + ID_VENDOR_FROM_DATABASE=Klos Technologies, Inc. + +acpi:PVR*: + ID_VENDOR_FROM_DATABASE=Pimax Tech. CO., LTD + +acpi:PXC*: + ID_VENDOR_FROM_DATABASE=Phoenix Contact + +acpi:PXE*: + ID_VENDOR_FROM_DATABASE=PIXELA CORPORATION + +acpi:PXL*: + ID_VENDOR_FROM_DATABASE=The Moving Pixel Company + +acpi:PXM*: + ID_VENDOR_FROM_DATABASE=Proxim Inc + +acpi:PXN*: + ID_VENDOR_FROM_DATABASE=PixelNext Inc + +acpi:QCC*: + ID_VENDOR_FROM_DATABASE=QuakeCom Company Ltd + +acpi:QCH*: + ID_VENDOR_FROM_DATABASE=Metronics Inc + +acpi:QCI*: + ID_VENDOR_FROM_DATABASE=Quanta Computer Inc + +acpi:QCK*: + ID_VENDOR_FROM_DATABASE=Quick Corporation + +acpi:QCL*: + ID_VENDOR_FROM_DATABASE=Quadrant Components Inc + +acpi:QCP*: + ID_VENDOR_FROM_DATABASE=Qualcomm Inc + +acpi:QDI*: + ID_VENDOR_FROM_DATABASE=Quantum Data Incorporated + +acpi:QDL*: + ID_VENDOR_FROM_DATABASE=QD Laser, Inc. + +acpi:QDM*: + ID_VENDOR_FROM_DATABASE=Quadram + +acpi:QDS*: + ID_VENDOR_FROM_DATABASE=Quanta Display Inc. + +acpi:QFF*: + ID_VENDOR_FROM_DATABASE=Padix Co., Inc. + +acpi:QFI*: + ID_VENDOR_FROM_DATABASE=Quickflex, Inc + +acpi:QLC*: + ID_VENDOR_FROM_DATABASE=Q-Logic + +acpi:QQQ*: + ID_VENDOR_FROM_DATABASE=Chuomusen Co., Ltd. + +acpi:QSC*: + ID_VENDOR_FROM_DATABASE=QSC, LLC + +acpi:QSI*: + ID_VENDOR_FROM_DATABASE=Quantum Solutions, Inc. + +acpi:QTD*: + ID_VENDOR_FROM_DATABASE=Quantum 3D Inc + +acpi:QTH*: + ID_VENDOR_FROM_DATABASE=Questech Ltd + +acpi:QTI*: + ID_VENDOR_FROM_DATABASE=Quicknet Technologies Inc + +acpi:QTM*: + ID_VENDOR_FROM_DATABASE=Quantum + +acpi:QTR*: + ID_VENDOR_FROM_DATABASE=Qtronix Corporation + +acpi:QUA*: + ID_VENDOR_FROM_DATABASE=Quatographic AG + +acpi:QUE*: + ID_VENDOR_FROM_DATABASE=Questra Consulting + +acpi:QVU*: + ID_VENDOR_FROM_DATABASE=Quartics + +acpi:RAC*: + ID_VENDOR_FROM_DATABASE=Racore Computer Products Inc + +acpi:RAD*: + ID_VENDOR_FROM_DATABASE=Radisys Corporation + +acpi:RAI*: + ID_VENDOR_FROM_DATABASE=Rockwell Automation/Intecolor + +acpi:RAN*: + ID_VENDOR_FROM_DATABASE=Rancho Tech Inc + +acpi:RAR*: + ID_VENDOR_FROM_DATABASE=Raritan, Inc. + +acpi:RAS*: + ID_VENDOR_FROM_DATABASE=RAScom Inc + +acpi:RAT*: + ID_VENDOR_FROM_DATABASE=Rent-A-Tech + +acpi:RAY*: + ID_VENDOR_FROM_DATABASE=Raylar Design, Inc. + +acpi:RCE*: + ID_VENDOR_FROM_DATABASE=Parc d'Activite des Bellevues + +acpi:RCH*: + ID_VENDOR_FROM_DATABASE=Reach Technology Inc + +acpi:RCI*: + ID_VENDOR_FROM_DATABASE=RC International + +acpi:RCN*: + ID_VENDOR_FROM_DATABASE=Radio Consult SRL + +acpi:RCO*: + ID_VENDOR_FROM_DATABASE=Rockwell Collins + +acpi:RDI*: + ID_VENDOR_FROM_DATABASE=Rainbow Displays, Inc. + +acpi:RDM*: + ID_VENDOR_FROM_DATABASE=Tremon Enterprises Company Ltd + +acpi:RDN*: + ID_VENDOR_FROM_DATABASE=RADIODATA GmbH + +acpi:RDS*: + ID_VENDOR_FROM_DATABASE=Radius Inc + +acpi:REA*: + ID_VENDOR_FROM_DATABASE=Real D + +acpi:REC*: + ID_VENDOR_FROM_DATABASE=ReCom + +acpi:RED*: + ID_VENDOR_FROM_DATABASE=Research Electronics Development Inc + +acpi:REF*: + ID_VENDOR_FROM_DATABASE=Reflectivity, Inc. + +acpi:REH*: + ID_VENDOR_FROM_DATABASE=Rehan Electronics Ltd. + +acpi:REL*: + ID_VENDOR_FROM_DATABASE=Reliance Electric Ind Corporation + +acpi:REM*: + ID_VENDOR_FROM_DATABASE=SCI Systems Inc. + +acpi:REN*: + ID_VENDOR_FROM_DATABASE=Renesas Technology Corp. + +acpi:RES*: + ID_VENDOR_FROM_DATABASE=ResMed Pty Ltd + +acpi:RET*: + ID_VENDOR_FROM_DATABASE=Resonance Technology, Inc. + +acpi:REV*: + ID_VENDOR_FROM_DATABASE=Revolution Display, Inc. + +acpi:REX*: + ID_VENDOR_FROM_DATABASE=RATOC Systems, Inc. + +acpi:RFI*: + ID_VENDOR_FROM_DATABASE=RAFI GmbH & Co. KG + +acpi:RFX*: + ID_VENDOR_FROM_DATABASE=Redfox Technologies Inc. + +acpi:RGB*: + ID_VENDOR_FROM_DATABASE=RGB Spectrum + +acpi:RGL*: + ID_VENDOR_FROM_DATABASE=Robertson Geologging Ltd + +acpi:RHD*: + ID_VENDOR_FROM_DATABASE=RightHand Technologies + +acpi:RHM*: + ID_VENDOR_FROM_DATABASE=Rohm Company Ltd + +acpi:RHT*: + ID_VENDOR_FROM_DATABASE=Red Hat, Inc. + +acpi:RIC*: + ID_VENDOR_FROM_DATABASE=RICOH COMPANY, LTD. + +acpi:RII*: + ID_VENDOR_FROM_DATABASE=Racal Interlan Inc + +acpi:RIO*: + ID_VENDOR_FROM_DATABASE=Rios Systems Company Ltd + +acpi:RIT*: + ID_VENDOR_FROM_DATABASE=Ritech Inc + +acpi:RIV*: + ID_VENDOR_FROM_DATABASE=Rivulet Communications + +acpi:RJA*: + ID_VENDOR_FROM_DATABASE=Roland Corporation + +acpi:RJS*: + ID_VENDOR_FROM_DATABASE=Advanced Engineering + +acpi:RKC*: + ID_VENDOR_FROM_DATABASE=Reakin Technolohy Corporation + +acpi:RLD*: + ID_VENDOR_FROM_DATABASE=MEPCO + +acpi:RLN*: + ID_VENDOR_FROM_DATABASE=RadioLAN Inc + +acpi:RMC*: + ID_VENDOR_FROM_DATABASE=Raritan Computer, Inc + +acpi:RMP*: + ID_VENDOR_FROM_DATABASE=Research Machines + +acpi:RMS*: + ID_VENDOR_FROM_DATABASE=Shenzhen Ramos Digital Technology Co., Ltd + +acpi:RMT*: + ID_VENDOR_FROM_DATABASE=Roper Mobile + +acpi:RNB*: + ID_VENDOR_FROM_DATABASE=Rainbow Technologies + +acpi:ROB*: + ID_VENDOR_FROM_DATABASE=Robust Electronics GmbH + +acpi:ROH*: + ID_VENDOR_FROM_DATABASE=Rohm Co., Ltd. + +acpi:ROK*: + ID_VENDOR_FROM_DATABASE=Rockwell International + +acpi:ROP*: + ID_VENDOR_FROM_DATABASE=Roper International Ltd + +acpi:ROS*: + ID_VENDOR_FROM_DATABASE=Rohde & Schwarz + +acpi:RPI*: + ID_VENDOR_FROM_DATABASE=RoomPro Technologies + +acpi:RPT*: + ID_VENDOR_FROM_DATABASE=R.P.T.Intergroups + +acpi:RRI*: + ID_VENDOR_FROM_DATABASE=Radicom Research Inc + +acpi:RSC*: + ID_VENDOR_FROM_DATABASE=PhotoTelesis + +acpi:RSH*: + ID_VENDOR_FROM_DATABASE=ADC-Centre + +acpi:RSI*: + ID_VENDOR_FROM_DATABASE=Rampage Systems Inc + +acpi:RSN*: + ID_VENDOR_FROM_DATABASE=Radiospire Networks, Inc. + +acpi:RSQ*: + ID_VENDOR_FROM_DATABASE=R Squared + +acpi:RSR*: + ID_VENDOR_FROM_DATABASE=Zhong Shan City Richsound Electronic Industrial Ltd. + +acpi:RSS*: + ID_VENDOR_FROM_DATABASE=Rockwell Semiconductor Systems + +acpi:RSV*: + ID_VENDOR_FROM_DATABASE=Ross Video Ltd + +acpi:RSX*: + ID_VENDOR_FROM_DATABASE=Rapid Tech Corporation + +acpi:RTC*: + ID_VENDOR_FROM_DATABASE=Relia Technologies + +acpi:RTI*: + ID_VENDOR_FROM_DATABASE=Rancho Tech Inc + +acpi:RTL*: + ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Company Ltd + +acpi:RTS*: + ID_VENDOR_FROM_DATABASE=Raintree Systems + +acpi:RUN*: + ID_VENDOR_FROM_DATABASE=RUNCO International + +acpi:RUP*: + ID_VENDOR_FROM_DATABASE=Ups Manufactoring s.r.l. + +acpi:RVC*: + ID_VENDOR_FROM_DATABASE=RSI Systems Inc + +acpi:RVI*: + ID_VENDOR_FROM_DATABASE=Realvision Inc + +acpi:RVL*: + ID_VENDOR_FROM_DATABASE=Reveal Computer Prod + +acpi:RWC*: + ID_VENDOR_FROM_DATABASE=Red Wing Corporation + +acpi:RXT*: + ID_VENDOR_FROM_DATABASE=Tectona SoftSolutions (P) Ltd., + +acpi:RZR*: + ID_VENDOR_FROM_DATABASE=Razer Taiwan Co. Ltd. + +acpi:RZS*: + ID_VENDOR_FROM_DATABASE=Rozsnyó, s.r.o. + +acpi:SAA*: + ID_VENDOR_FROM_DATABASE=Sanritz Automation Co.,Ltd. + +acpi:SAE*: + ID_VENDOR_FROM_DATABASE=Saab Aerotech + +acpi:SAG*: + ID_VENDOR_FROM_DATABASE=Sedlbauer + +acpi:SAI*: + ID_VENDOR_FROM_DATABASE=Sage Inc + +acpi:SAK*: + ID_VENDOR_FROM_DATABASE=Saitek Ltd + +acpi:SAM*: + ID_VENDOR_FROM_DATABASE=Samsung Electric Company + +acpi:SAN*: + ID_VENDOR_FROM_DATABASE=Sanyo Electric Co.,Ltd. + +acpi:SAS*: + ID_VENDOR_FROM_DATABASE=Stores Automated Systems Inc + +acpi:SAT*: + ID_VENDOR_FROM_DATABASE=Shuttle Tech + +acpi:SBC*: + ID_VENDOR_FROM_DATABASE=Shanghai Bell Telephone Equip Mfg Co + +acpi:SBD*: + ID_VENDOR_FROM_DATABASE=Softbed - Consulting & Development Ltd + +acpi:SBI*: + ID_VENDOR_FROM_DATABASE=SMART Technologies Inc. + +acpi:SBS*: + ID_VENDOR_FROM_DATABASE=SBS-or Industrial Computers GmbH + +acpi:SBT*: + ID_VENDOR_FROM_DATABASE=Senseboard Technologies AB + +acpi:SCB*: + ID_VENDOR_FROM_DATABASE=SeeCubic B.V. + +acpi:SCC*: + ID_VENDOR_FROM_DATABASE=SORD Computer Corporation + +acpi:SCD*: + ID_VENDOR_FROM_DATABASE=Sanyo Electric Company Ltd + +acpi:SCE*: + ID_VENDOR_FROM_DATABASE=Sun Corporation + +acpi:SCH*: + ID_VENDOR_FROM_DATABASE=Schlumberger Cards + +acpi:SCI*: + ID_VENDOR_FROM_DATABASE=System Craft + +acpi:SCL*: + ID_VENDOR_FROM_DATABASE=Sigmacom Co., Ltd. + +acpi:SCM*: + ID_VENDOR_FROM_DATABASE=SCM Microsystems Inc + +acpi:SCN*: + ID_VENDOR_FROM_DATABASE=Scanport, Inc. + +acpi:SCO*: + ID_VENDOR_FROM_DATABASE=SORCUS Computer GmbH + +acpi:SCP*: + ID_VENDOR_FROM_DATABASE=Scriptel Corporation + +acpi:SCR*: + ID_VENDOR_FROM_DATABASE=Systran Corporation + +acpi:SCS*: + ID_VENDOR_FROM_DATABASE=Nanomach Anstalt + +acpi:SCT*: + ID_VENDOR_FROM_DATABASE=Smart Card Technology + +acpi:SCX*: + ID_VENDOR_FROM_DATABASE=Socionext Inc. + +acpi:SDA*: + ID_VENDOR_FROM_DATABASE=SAT (Societe Anonyme) + +acpi:SDD*: + ID_VENDOR_FROM_DATABASE=Intrada-SDD Ltd + +acpi:SDE*: + ID_VENDOR_FROM_DATABASE=Sherwood Digital Electronics Corporation + +acpi:SDF*: + ID_VENDOR_FROM_DATABASE=SODIFF E&T CO., Ltd. + +acpi:SDH*: + ID_VENDOR_FROM_DATABASE=Communications Specialies, Inc. + +acpi:SDI*: + ID_VENDOR_FROM_DATABASE=Samtron Displays Inc + +acpi:SDK*: + ID_VENDOR_FROM_DATABASE=SAIT-Devlonics + +acpi:SDR*: + ID_VENDOR_FROM_DATABASE=SDR Systems + +acpi:SDS*: + ID_VENDOR_FROM_DATABASE=SunRiver Data System + +acpi:SDT*: + ID_VENDOR_FROM_DATABASE=Siemens AG + +acpi:SDX*: + ID_VENDOR_FROM_DATABASE=SDX Business Systems Ltd + +acpi:SEA*: + ID_VENDOR_FROM_DATABASE=Seanix Technology Inc. + +acpi:SEB*: + ID_VENDOR_FROM_DATABASE=system elektronik GmbH + +acpi:SEC*: + ID_VENDOR_FROM_DATABASE=Seiko Epson Corporation + +acpi:SEE*: + ID_VENDOR_FROM_DATABASE=SeeColor Corporation + +acpi:SEI*: + ID_VENDOR_FROM_DATABASE=Seitz & Associates Inc + +acpi:SEL*: + ID_VENDOR_FROM_DATABASE=Way2Call Communications + +acpi:SEM*: + ID_VENDOR_FROM_DATABASE=Samsung Electronics Company Ltd + +acpi:SEN*: + ID_VENDOR_FROM_DATABASE=Sencore + +acpi:SEO*: + ID_VENDOR_FROM_DATABASE=SEOS Ltd + +acpi:SEP*: + ID_VENDOR_FROM_DATABASE=SEP Eletronica Ltda. + +acpi:SER*: + ID_VENDOR_FROM_DATABASE=Sony Ericsson Mobile Communications Inc. + +acpi:SES*: + ID_VENDOR_FROM_DATABASE=Session Control LLC + +acpi:SET*: + ID_VENDOR_FROM_DATABASE=SendTek Corporation + +acpi:SFM*: + ID_VENDOR_FROM_DATABASE=TORNADO Company + +acpi:SFT*: + ID_VENDOR_FROM_DATABASE=Mikroforum Ring 3 + +acpi:SGC*: + ID_VENDOR_FROM_DATABASE=Spectragraphics Corporation + +acpi:SGD*: + ID_VENDOR_FROM_DATABASE=Sigma Designs, Inc. + +acpi:SGE*: + ID_VENDOR_FROM_DATABASE=Kansai Electric Company Ltd + +acpi:SGI*: + ID_VENDOR_FROM_DATABASE=Scan Group Ltd + +acpi:SGL*: + ID_VENDOR_FROM_DATABASE=Super Gate Technology Company Ltd + +acpi:SGM*: + ID_VENDOR_FROM_DATABASE=SAGEM + +acpi:SGO*: + ID_VENDOR_FROM_DATABASE=Logos Design A/S + +acpi:SGT*: + ID_VENDOR_FROM_DATABASE=Stargate Technology + +acpi:SGW*: + ID_VENDOR_FROM_DATABASE=Shanghai Guowei Science and Technology Co., Ltd. + +acpi:SGX*: + ID_VENDOR_FROM_DATABASE=Silicon Graphics Inc + +acpi:SGZ*: + ID_VENDOR_FROM_DATABASE=Systec Computer GmbH + +acpi:SHC*: + ID_VENDOR_FROM_DATABASE=ShibaSoku Co., Ltd. + +acpi:SHG*: + ID_VENDOR_FROM_DATABASE=Soft & Hardware development Goldammer GmbH + +acpi:SHI*: + ID_VENDOR_FROM_DATABASE=Jiangsu Shinco Electronic Group Co., Ltd + +acpi:SHP*: + ID_VENDOR_FROM_DATABASE=Sharp Corporation + +acpi:SHR*: + ID_VENDOR_FROM_DATABASE=Digital Discovery + +acpi:SHT*: + ID_VENDOR_FROM_DATABASE=Shin Ho Tech + +acpi:SIA*: + ID_VENDOR_FROM_DATABASE=SIEMENS AG + +acpi:SIB*: + ID_VENDOR_FROM_DATABASE=Sanyo Electric Company Ltd + +acpi:SIC*: + ID_VENDOR_FROM_DATABASE=Sysmate Corporation + +acpi:SID*: + ID_VENDOR_FROM_DATABASE=Seiko Instruments Information Devices Inc + +acpi:SIE*: + ID_VENDOR_FROM_DATABASE=Siemens + +acpi:SIG*: + ID_VENDOR_FROM_DATABASE=Sigma Designs Inc + +acpi:SII*: + ID_VENDOR_FROM_DATABASE=Silicon Image, Inc. + +acpi:SIL*: + ID_VENDOR_FROM_DATABASE=Silicon Laboratories, Inc + +acpi:SIM*: + ID_VENDOR_FROM_DATABASE=S3 Inc + +acpi:SIN*: + ID_VENDOR_FROM_DATABASE=Singular Technology Co., Ltd. + +acpi:SIR*: + ID_VENDOR_FROM_DATABASE=Sirius Technologies Pty Ltd + +acpi:SIS*: + ID_VENDOR_FROM_DATABASE=Silicon Integrated Systems Corporation + +acpi:SIT*: + ID_VENDOR_FROM_DATABASE=Sitintel + +acpi:SIU*: + ID_VENDOR_FROM_DATABASE=Seiko Instruments USA Inc + +acpi:SIX*: + ID_VENDOR_FROM_DATABASE=Zuniq Data Corporation + +acpi:SJE*: + ID_VENDOR_FROM_DATABASE=Sejin Electron Inc + +acpi:SKD*: + ID_VENDOR_FROM_DATABASE=Schneider & Koch + +acpi:SKI*: + ID_VENDOR_FROM_DATABASE=LLC SKTB “SKIT” + +acpi:SKM*: + ID_VENDOR_FROM_DATABASE=Guangzhou Teclast Information Technology Limited + +acpi:SKT*: + ID_VENDOR_FROM_DATABASE=Samsung Electro-Mechanics Company Ltd + +acpi:SKY*: + ID_VENDOR_FROM_DATABASE=SKYDATA S.P.A. + +acpi:SLA*: + ID_VENDOR_FROM_DATABASE=Systeme Lauer GmbH&Co KG + +acpi:SLB*: + ID_VENDOR_FROM_DATABASE=Shlumberger Ltd + +acpi:SLC*: + ID_VENDOR_FROM_DATABASE=Syslogic Datentechnik AG + +acpi:SLF*: + ID_VENDOR_FROM_DATABASE=StarLeaf + +acpi:SLH*: + ID_VENDOR_FROM_DATABASE=Silicon Library Inc. + +acpi:SLI*: + ID_VENDOR_FROM_DATABASE=Symbios Logic Inc + +acpi:SLK*: + ID_VENDOR_FROM_DATABASE=Silitek Corporation + +acpi:SLM*: + ID_VENDOR_FROM_DATABASE=Solomon Technology Corporation + +acpi:SLR*: + ID_VENDOR_FROM_DATABASE=Schlumberger Technology Corporate + +acpi:SLS*: + ID_VENDOR_FROM_DATABASE=Schnick-Schnack-Systems GmbH + +acpi:SLT*: + ID_VENDOR_FROM_DATABASE=Salt Internatioinal Corp. + +acpi:SLX*: + ID_VENDOR_FROM_DATABASE=Specialix + +acpi:SMA*: + ID_VENDOR_FROM_DATABASE=SMART Modular Technologies + +acpi:SMB*: + ID_VENDOR_FROM_DATABASE=Schlumberger + +acpi:SMC*: + ID_VENDOR_FROM_DATABASE=Standard Microsystems Corporation + +acpi:SME*: + ID_VENDOR_FROM_DATABASE=Sysmate Company + +acpi:SMI*: + ID_VENDOR_FROM_DATABASE=SpaceLabs Medical Inc + +acpi:SMK*: + ID_VENDOR_FROM_DATABASE=SMK CORPORATION + +acpi:SML*: + ID_VENDOR_FROM_DATABASE=Sumitomo Metal Industries, Ltd. + +acpi:SMM*: + ID_VENDOR_FROM_DATABASE=Shark Multimedia Inc + +acpi:SMO*: + ID_VENDOR_FROM_DATABASE=STMicroelectronics + +acpi:SMP*: + ID_VENDOR_FROM_DATABASE=Simple Computing + +acpi:SMR*: + ID_VENDOR_FROM_DATABASE=B.& V. s.r.l. + +acpi:SMS*: + ID_VENDOR_FROM_DATABASE=Silicom Multimedia Systems Inc + +acpi:SMT*: + ID_VENDOR_FROM_DATABASE=Silcom Manufacturing Tech Inc + +acpi:SNC*: + ID_VENDOR_FROM_DATABASE=Sentronic International Corp. + +acpi:SNI*: + ID_VENDOR_FROM_DATABASE=Siemens Microdesign GmbH + +acpi:SNK*: + ID_VENDOR_FROM_DATABASE=S&K Electronics + +acpi:SNN*: + ID_VENDOR_FROM_DATABASE=SUNNY ELEKTRONIK + +acpi:SNO*: + ID_VENDOR_FROM_DATABASE=SINOSUN TECHNOLOGY CO., LTD + +acpi:SNP*: + ID_VENDOR_FROM_DATABASE=Siemens Nixdorf Info Systems + +acpi:SNS*: + ID_VENDOR_FROM_DATABASE=Cirtech (UK) Ltd + +acpi:SNT*: + ID_VENDOR_FROM_DATABASE=SuperNet Inc + +acpi:SNV*: + ID_VENDOR_FROM_DATABASE=SONOVE GmbH + +acpi:SNW*: + ID_VENDOR_FROM_DATABASE=Snell & Wilcox + +acpi:SNX*: + ID_VENDOR_FROM_DATABASE=Sonix Comm. Ltd + +acpi:SNY*: + ID_VENDOR_FROM_DATABASE=Sony + +acpi:SOC*: + ID_VENDOR_FROM_DATABASE=Santec Corporation + +acpi:SOI*: + ID_VENDOR_FROM_DATABASE=Silicon Optix Corporation + +acpi:SOL*: + ID_VENDOR_FROM_DATABASE=Solitron Technologies Inc + +acpi:SON*: + ID_VENDOR_FROM_DATABASE=Sony + +acpi:SOR*: + ID_VENDOR_FROM_DATABASE=Sorcus Computer GmbH + +acpi:SOT*: + ID_VENDOR_FROM_DATABASE=Sotec Company Ltd + +acpi:SOY*: + ID_VENDOR_FROM_DATABASE=SOYO Group, Inc + +acpi:SPC*: + ID_VENDOR_FROM_DATABASE=SpinCore Technologies, Inc + +acpi:SPE*: + ID_VENDOR_FROM_DATABASE=SPEA Software AG + +acpi:SPH*: + ID_VENDOR_FROM_DATABASE=G&W Instruments GmbH + +acpi:SPI*: + ID_VENDOR_FROM_DATABASE=SPACE-I Co., Ltd. + +acpi:SPK*: + ID_VENDOR_FROM_DATABASE=SpeakerCraft + +acpi:SPL*: + ID_VENDOR_FROM_DATABASE=Smart Silicon Systems Pty Ltd + +acpi:SPN*: + ID_VENDOR_FROM_DATABASE=Sapience Corporation + +acpi:SPR*: + ID_VENDOR_FROM_DATABASE=pmns GmbH + +acpi:SPS*: + ID_VENDOR_FROM_DATABASE=Synopsys Inc + +acpi:SPT*: + ID_VENDOR_FROM_DATABASE=Sceptre Tech Inc + +acpi:SPU*: + ID_VENDOR_FROM_DATABASE=SIM2 Multimedia S.P.A. + +acpi:SPX*: + ID_VENDOR_FROM_DATABASE=Simplex Time Recorder Co. + +acpi:SQT*: + ID_VENDOR_FROM_DATABASE=Sequent Computer Systems Inc + +acpi:SRC*: + ID_VENDOR_FROM_DATABASE=Integrated Tech Express Inc + +acpi:SRD*: + ID_VENDOR_FROM_DATABASE=Setred + +acpi:SRF*: + ID_VENDOR_FROM_DATABASE=Surf Communication Solutions Ltd + +acpi:SRG*: + ID_VENDOR_FROM_DATABASE=Intuitive Surgical, Inc. + +acpi:SRS*: + ID_VENDOR_FROM_DATABASE=SR-Systems e.K. + +acpi:SRT*: + ID_VENDOR_FROM_DATABASE=SeeReal Technologies GmbH + +acpi:SSC*: + ID_VENDOR_FROM_DATABASE=Sierra Semiconductor Inc + +acpi:SSD*: + ID_VENDOR_FROM_DATABASE=FlightSafety International + +acpi:SSE*: + ID_VENDOR_FROM_DATABASE=Samsung Electronic Co. + +acpi:SSI*: + ID_VENDOR_FROM_DATABASE=S-S Technology Inc + +acpi:SSJ*: + ID_VENDOR_FROM_DATABASE=Sankyo Seiki Mfg.co., Ltd + +acpi:SSL*: + ID_VENDOR_FROM_DATABASE=Shenzhen South-Top Computer Co., Ltd. + +acpi:SSP*: + ID_VENDOR_FROM_DATABASE=Spectrum Signal Proecessing Inc + +acpi:SSS*: + ID_VENDOR_FROM_DATABASE=S3 Inc + +acpi:SST*: + ID_VENDOR_FROM_DATABASE=SystemSoft Corporation + +acpi:STA*: + ID_VENDOR_FROM_DATABASE=ST Electronics Systems Assembly Pte Ltd + +acpi:STB*: + ID_VENDOR_FROM_DATABASE=STB Systems Inc + +acpi:STC*: + ID_VENDOR_FROM_DATABASE=STAC Electronics + +acpi:STD*: + ID_VENDOR_FROM_DATABASE=STD Computer Inc + +acpi:STE*: + ID_VENDOR_FROM_DATABASE=SII Ido-Tsushin Inc + +acpi:STF*: + ID_VENDOR_FROM_DATABASE=Starflight Electronics + +acpi:STG*: + ID_VENDOR_FROM_DATABASE=StereoGraphics Corp. + +acpi:STH*: + ID_VENDOR_FROM_DATABASE=Semtech Corporation + +acpi:STI*: + ID_VENDOR_FROM_DATABASE=Smart Tech Inc + +acpi:STK*: + ID_VENDOR_FROM_DATABASE=SANTAK CORP. + +acpi:STL*: + ID_VENDOR_FROM_DATABASE=SigmaTel Inc + +acpi:STM*: + ID_VENDOR_FROM_DATABASE=SGS Thomson Microelectronics + +acpi:STN*: + ID_VENDOR_FROM_DATABASE=Samsung Electronics America + +acpi:STO*: + ID_VENDOR_FROM_DATABASE=Stollmann E+V GmbH + +acpi:STP*: + ID_VENDOR_FROM_DATABASE=StreamPlay Ltd + +acpi:STQ*: + ID_VENDOR_FROM_DATABASE=Synthetel Corporation + +acpi:STR*: + ID_VENDOR_FROM_DATABASE=Starlight Networks Inc + +acpi:STS*: + ID_VENDOR_FROM_DATABASE=SITECSYSTEM CO., LTD. + +acpi:STT*: + ID_VENDOR_FROM_DATABASE=Star Paging Telecom Tech (Shenzhen) Co. Ltd. + +acpi:STU*: + ID_VENDOR_FROM_DATABASE=Sentelic Corporation + +acpi:STW*: + ID_VENDOR_FROM_DATABASE=Starwin Inc. + +acpi:STX*: + ID_VENDOR_FROM_DATABASE=ST-Ericsson + +acpi:STY*: + ID_VENDOR_FROM_DATABASE=SDS Technologies + +acpi:SUB*: + ID_VENDOR_FROM_DATABASE=Subspace Comm. Inc + +acpi:SUM*: + ID_VENDOR_FROM_DATABASE=Summagraphics Corporation + +acpi:SUN*: + ID_VENDOR_FROM_DATABASE=Sun Electronics Corporation + +acpi:SUP*: + ID_VENDOR_FROM_DATABASE=Supra Corporation + +acpi:SUR*: + ID_VENDOR_FROM_DATABASE=Surenam Computer Corporation + +acpi:SVA*: + ID_VENDOR_FROM_DATABASE=SGEG + +acpi:SVC*: + ID_VENDOR_FROM_DATABASE=Intellix Corp. + +acpi:SVD*: + ID_VENDOR_FROM_DATABASE=SVD Computer + +acpi:SVE*: + ID_VENDOR_FROM_DATABASE=SVEC + +acpi:SVI*: + ID_VENDOR_FROM_DATABASE=Sun Microsystems + +acpi:SVR*: + ID_VENDOR_FROM_DATABASE=Sensics, Inc. + +acpi:SVS*: + ID_VENDOR_FROM_DATABASE=SVSI + +acpi:SVT*: + ID_VENDOR_FROM_DATABASE=SEVIT Co., Ltd. + +acpi:SWC*: + ID_VENDOR_FROM_DATABASE=Software Café + +acpi:SWI*: + ID_VENDOR_FROM_DATABASE=Sierra Wireless Inc. + +acpi:SWL*: + ID_VENDOR_FROM_DATABASE=Sharedware Ltd + +acpi:SWO*: + ID_VENDOR_FROM_DATABASE=Guangzhou Shirui Electronics Co., Ltd. + +acpi:SWS*: + ID_VENDOR_FROM_DATABASE=Static + +acpi:SWT*: + ID_VENDOR_FROM_DATABASE=Software Technologies Group,Inc. + +acpi:SXB*: + ID_VENDOR_FROM_DATABASE=Syntax-Brillian + +acpi:SXD*: + ID_VENDOR_FROM_DATABASE=Silex technology, Inc. + +acpi:SXG*: + ID_VENDOR_FROM_DATABASE=SELEX GALILEO + +acpi:SXI*: + ID_VENDOR_FROM_DATABASE=Silex Inside + +acpi:SXL*: + ID_VENDOR_FROM_DATABASE=SolutionInside + +acpi:SXT*: + ID_VENDOR_FROM_DATABASE=SHARP TAKAYA ELECTRONIC INDUSTRY CO.,LTD. + +acpi:SYC*: + ID_VENDOR_FROM_DATABASE=Sysmic + +acpi:SYE*: + ID_VENDOR_FROM_DATABASE=SY Electronics Ltd + +acpi:SYK*: + ID_VENDOR_FROM_DATABASE=Stryker Communications + +acpi:SYL*: + ID_VENDOR_FROM_DATABASE=Sylvania Computer Products + +acpi:SYM*: + ID_VENDOR_FROM_DATABASE=Symicron Computer Communications Ltd. + +acpi:SYN*: + ID_VENDOR_FROM_DATABASE=Synaptics Inc + +acpi:SYP*: + ID_VENDOR_FROM_DATABASE=SYPRO Co Ltd + +acpi:SYS*: + ID_VENDOR_FROM_DATABASE=Sysgration Ltd + +acpi:SYT*: + ID_VENDOR_FROM_DATABASE=Seyeon Tech Company Ltd + +acpi:SYV*: + ID_VENDOR_FROM_DATABASE=SYVAX Inc + +acpi:SYX*: + ID_VENDOR_FROM_DATABASE=Prime Systems, Inc. + +acpi:SZM*: + ID_VENDOR_FROM_DATABASE=Shenzhen MTC Co., Ltd + +acpi:SZV*: + ID_VENDOR_FROM_DATABASE=OvisLink + +acpi:TAA*: + ID_VENDOR_FROM_DATABASE=Tandberg + +acpi:TAB*: + ID_VENDOR_FROM_DATABASE=Todos Data System AB + +acpi:TAG*: + ID_VENDOR_FROM_DATABASE=Teles AG + +acpi:TAI*: + ID_VENDOR_FROM_DATABASE=Toshiba America Info Systems Inc + +acpi:TAM*: + ID_VENDOR_FROM_DATABASE=Tamura Seisakusyo Ltd + +acpi:TAS*: + ID_VENDOR_FROM_DATABASE=Taskit Rechnertechnik GmbH + +acpi:TAT*: + ID_VENDOR_FROM_DATABASE=Teleliaison Inc + +acpi:TAV*: + ID_VENDOR_FROM_DATABASE=Thales Avionics + +acpi:TAX*: + ID_VENDOR_FROM_DATABASE=Taxan (Europe) Ltd + +acpi:TBB*: + ID_VENDOR_FROM_DATABASE=Triple S Engineering Inc + +acpi:TBC*: + ID_VENDOR_FROM_DATABASE=Turbo Communication, Inc + +acpi:TBS*: + ID_VENDOR_FROM_DATABASE=Turtle Beach System + +acpi:TCC*: + ID_VENDOR_FROM_DATABASE=Tandon Corporation + +acpi:TCD*: + ID_VENDOR_FROM_DATABASE=Taicom Data Systems Co., Ltd. + +acpi:TCE*: + ID_VENDOR_FROM_DATABASE=Century Corporation + +acpi:TCF*: + ID_VENDOR_FROM_DATABASE=Televic Conference + +acpi:TCH*: + ID_VENDOR_FROM_DATABASE=Interaction Systems, Inc + +acpi:TCI*: + ID_VENDOR_FROM_DATABASE=Tulip Computers Int'l B.V. + +acpi:TCJ*: + ID_VENDOR_FROM_DATABASE=TEAC America Inc + +acpi:TCL*: + ID_VENDOR_FROM_DATABASE=Technical Concepts Ltd + +acpi:TCM*: + ID_VENDOR_FROM_DATABASE=3Com Corporation + +acpi:TCN*: + ID_VENDOR_FROM_DATABASE=Tecnetics (PTY) Ltd + +acpi:TCO*: + ID_VENDOR_FROM_DATABASE=Thomas-Conrad Corporation + +acpi:TCR*: + ID_VENDOR_FROM_DATABASE=Thomson Consumer Electronics + +acpi:TCS*: + ID_VENDOR_FROM_DATABASE=Tatung Company of America Inc + +acpi:TCT*: + ID_VENDOR_FROM_DATABASE=Telecom Technology Centre Co. Ltd. + +acpi:TCX*: + ID_VENDOR_FROM_DATABASE=FREEMARS Heavy Industries + +acpi:TDC*: + ID_VENDOR_FROM_DATABASE=Teradici + +acpi:TDD*: + ID_VENDOR_FROM_DATABASE=Tandberg Data Display AS + +acpi:TDG*: + ID_VENDOR_FROM_DATABASE=Six15 Technologies + +acpi:TDK*: + ID_VENDOR_FROM_DATABASE=TDK USA Corporation + +acpi:TDM*: + ID_VENDOR_FROM_DATABASE=Tandem Computer Europe Inc + +acpi:TDP*: + ID_VENDOR_FROM_DATABASE=3D Perception + +acpi:TDS*: + ID_VENDOR_FROM_DATABASE=Tri-Data Systems Inc + +acpi:TDT*: + ID_VENDOR_FROM_DATABASE=TDT + +acpi:TDV*: + ID_VENDOR_FROM_DATABASE=TDVision Systems, Inc. + +acpi:TDY*: + ID_VENDOR_FROM_DATABASE=Tandy Electronics + +acpi:TEA*: + ID_VENDOR_FROM_DATABASE=TEAC System Corporation + +acpi:TEC*: + ID_VENDOR_FROM_DATABASE=Tecmar Inc + +acpi:TEK*: + ID_VENDOR_FROM_DATABASE=Tektronix Inc + +acpi:TEL*: + ID_VENDOR_FROM_DATABASE=Promotion and Display Technology Ltd. + +acpi:TEN*: + ID_VENDOR_FROM_DATABASE=Tencent + +acpi:TER*: + ID_VENDOR_FROM_DATABASE=TerraTec Electronic GmbH + +acpi:TET*: + ID_VENDOR_FROM_DATABASE=TETRADYNE CO., LTD. + +acpi:TEV*: + ID_VENDOR_FROM_DATABASE=Televés, S.A. + +acpi:TEX*: + ID_VENDOR_FROM_DATABASE=Texas Instruments + +acpi:TEZ*: + ID_VENDOR_FROM_DATABASE=Tech Source Inc. + +acpi:TGC*: + ID_VENDOR_FROM_DATABASE=Toshiba Global Commerce Solutions, Inc. + +acpi:TGI*: + ID_VENDOR_FROM_DATABASE=TriGem Computer Inc + +acpi:TGM*: + ID_VENDOR_FROM_DATABASE=TriGem Computer,Inc. + +acpi:TGS*: + ID_VENDOR_FROM_DATABASE=Torus Systems Ltd + +acpi:TGV*: + ID_VENDOR_FROM_DATABASE=Grass Valley Germany GmbH + +acpi:THN*: + ID_VENDOR_FROM_DATABASE=Thundercom Holdings Sdn. Bhd. + +acpi:TIC*: + ID_VENDOR_FROM_DATABASE=Trigem KinfoComm + +acpi:TIL*: + ID_VENDOR_FROM_DATABASE=Technical Illusions Inc. + +acpi:TIP*: + ID_VENDOR_FROM_DATABASE=TIPTEL AG + +acpi:TIV*: + ID_VENDOR_FROM_DATABASE=OOO Technoinvest + +acpi:TIX*: + ID_VENDOR_FROM_DATABASE=Tixi.Com GmbH + +acpi:TKC*: + ID_VENDOR_FROM_DATABASE=Taiko Electric Works.LTD + +acpi:TKG*: + ID_VENDOR_FROM_DATABASE=Tek Gear + +acpi:TKN*: + ID_VENDOR_FROM_DATABASE=Teknor Microsystem Inc + +acpi:TKO*: + ID_VENDOR_FROM_DATABASE=TouchKo, Inc. + +acpi:TKS*: + ID_VENDOR_FROM_DATABASE=TimeKeeping Systems, Inc. + +acpi:TLA*: + ID_VENDOR_FROM_DATABASE=Ferrari Electronic GmbH + +acpi:TLD*: + ID_VENDOR_FROM_DATABASE=Telindus + +acpi:TLE*: + ID_VENDOR_FROM_DATABASE=Zhejiang Tianle Digital Electric Co., Ltd. + +acpi:TLF*: + ID_VENDOR_FROM_DATABASE=Teleforce.,co,ltd + +acpi:TLI*: + ID_VENDOR_FROM_DATABASE=TOSHIBA TELI CORPORATION + +acpi:TLK*: + ID_VENDOR_FROM_DATABASE=Telelink AG + +acpi:TLL*: + ID_VENDOR_FROM_DATABASE=Thinklogical + +acpi:TLN*: + ID_VENDOR_FROM_DATABASE=Techlogix Networx + +acpi:TLS*: + ID_VENDOR_FROM_DATABASE=Teleste Educational OY + +acpi:TLT*: + ID_VENDOR_FROM_DATABASE=Dai Telecom S.p.A. + +acpi:TLV*: + ID_VENDOR_FROM_DATABASE=S3 Inc + +acpi:TLX*: + ID_VENDOR_FROM_DATABASE=Telxon Corporation + +acpi:TMC*: + ID_VENDOR_FROM_DATABASE=Techmedia Computer Systems Corporation + +acpi:TME*: + ID_VENDOR_FROM_DATABASE=AT&T Microelectronics + +acpi:TMI*: + ID_VENDOR_FROM_DATABASE=Texas Microsystem + +acpi:TMM*: + ID_VENDOR_FROM_DATABASE=Time Management, Inc. + +acpi:TMR*: + ID_VENDOR_FROM_DATABASE=Taicom International Inc + +acpi:TMS*: + ID_VENDOR_FROM_DATABASE=Trident Microsystems Ltd + +acpi:TMT*: + ID_VENDOR_FROM_DATABASE=T-Metrics Inc. + +acpi:TMX*: + ID_VENDOR_FROM_DATABASE=Thermotrex Corporation + +acpi:TNC*: + ID_VENDOR_FROM_DATABASE=TNC Industrial Company Ltd + +acpi:TNM*: + ID_VENDOR_FROM_DATABASE=TECNIMAGEN SA + +acpi:TNY*: + ID_VENDOR_FROM_DATABASE=Tennyson Tech Pty Ltd + +acpi:TOE*: + ID_VENDOR_FROM_DATABASE=TOEI Electronics Co., Ltd. + +acpi:TOG*: + ID_VENDOR_FROM_DATABASE=The OPEN Group + +acpi:TOL*: + ID_VENDOR_FROM_DATABASE=TCL Corporation + +acpi:TOM*: + ID_VENDOR_FROM_DATABASE=Ceton Corporation + +acpi:TON*: + ID_VENDOR_FROM_DATABASE=TONNA + +acpi:TOP*: + ID_VENDOR_FROM_DATABASE=Orion Communications Co., Ltd. + +acpi:TOS*: + ID_VENDOR_FROM_DATABASE=Toshiba Corporation + +acpi:TOU*: + ID_VENDOR_FROM_DATABASE=Touchstone Technology + +acpi:TPC*: + ID_VENDOR_FROM_DATABASE=Touch Panel Systems Corporation + +acpi:TPD*: + ID_VENDOR_FROM_DATABASE=Times (Shanghai) Computer Co., Ltd. + +acpi:TPE*: + ID_VENDOR_FROM_DATABASE=Technology Power Enterprises Inc + +acpi:TPJ*: + ID_VENDOR_FROM_DATABASE=Junnila + +acpi:TPK*: + ID_VENDOR_FROM_DATABASE=TOPRE CORPORATION + +acpi:TPR*: + ID_VENDOR_FROM_DATABASE=Topro Technology Inc + +acpi:TPS*: + ID_VENDOR_FROM_DATABASE=Teleprocessing Systeme GmbH + +acpi:TPT*: + ID_VENDOR_FROM_DATABASE=Thruput Ltd + +acpi:TPV*: + ID_VENDOR_FROM_DATABASE=Top Victory Electronics ( Fujian ) Company Ltd + +acpi:TPZ*: + ID_VENDOR_FROM_DATABASE=Ypoaz Systems Inc + +acpi:TRA*: + ID_VENDOR_FROM_DATABASE=TriTech Microelectronics International + +acpi:TRB*: + ID_VENDOR_FROM_DATABASE=Triumph Board a.s. + +acpi:TRC*: + ID_VENDOR_FROM_DATABASE=Trioc AB + +acpi:TRD*: + ID_VENDOR_FROM_DATABASE=Trident Microsystem Inc + +acpi:TRE*: + ID_VENDOR_FROM_DATABASE=Tremetrics + +acpi:TRI*: + ID_VENDOR_FROM_DATABASE=Tricord Systems + +acpi:TRL*: + ID_VENDOR_FROM_DATABASE=Royal Information + +acpi:TRM*: + ID_VENDOR_FROM_DATABASE=Tekram Technology Company Ltd + +acpi:TRN*: + ID_VENDOR_FROM_DATABASE=Datacommunicatie Tron B.V. + +acpi:TRP*: + ID_VENDOR_FROM_DATABASE=TRAPEZE GROUP + +acpi:TRS*: + ID_VENDOR_FROM_DATABASE=Torus Systems Ltd + +acpi:TRT*: + ID_VENDOR_FROM_DATABASE=Tritec Electronic AG + +acpi:TRU*: + ID_VENDOR_FROM_DATABASE=Aashima Technology B.V. + +acpi:TRV*: + ID_VENDOR_FROM_DATABASE=Trivisio Prototyping GmbH + +acpi:TRX*: + ID_VENDOR_FROM_DATABASE=Trex Enterprises + +acpi:TSB*: + ID_VENDOR_FROM_DATABASE=Toshiba America Info Systems Inc + +acpi:TSC*: + ID_VENDOR_FROM_DATABASE=Sanyo Electric Company Ltd + +acpi:TSD*: + ID_VENDOR_FROM_DATABASE=TechniSat Digital GmbH + +acpi:TSE*: + ID_VENDOR_FROM_DATABASE=Tottori Sanyo Electric + +acpi:TSF*: + ID_VENDOR_FROM_DATABASE=Racal-Airtech Software Forge Ltd + +acpi:TSG*: + ID_VENDOR_FROM_DATABASE=The Software Group Ltd + +acpi:TSH*: + ID_VENDOR_FROM_DATABASE=ELAN MICROELECTRONICS CORPORATION + +acpi:TSI*: + ID_VENDOR_FROM_DATABASE=TeleVideo Systems + +acpi:TSL*: + ID_VENDOR_FROM_DATABASE=Tottori SANYO Electric Co., Ltd. + +acpi:TSP*: + ID_VENDOR_FROM_DATABASE=U.S. Navy + +acpi:TST*: + ID_VENDOR_FROM_DATABASE=Transtream Inc + +acpi:TSV*: + ID_VENDOR_FROM_DATABASE=TRANSVIDEO + +acpi:TSW*: + ID_VENDOR_FROM_DATABASE=VRSHOW Technology Limited + +acpi:TSY*: + ID_VENDOR_FROM_DATABASE=TouchSystems + +acpi:TTA*: + ID_VENDOR_FROM_DATABASE=Topson Technology Co., Ltd. + +acpi:TTB*: + ID_VENDOR_FROM_DATABASE=National Semiconductor Japan Ltd + +acpi:TTC*: + ID_VENDOR_FROM_DATABASE=Telecommunications Techniques Corporation + +acpi:TTE*: + ID_VENDOR_FROM_DATABASE=TTE, Inc. + +acpi:TTI*: + ID_VENDOR_FROM_DATABASE=Trenton Terminals Inc + +acpi:TTK*: + ID_VENDOR_FROM_DATABASE=Totoku Electric Company Ltd + +acpi:TTL*: + ID_VENDOR_FROM_DATABASE=2-Tel B.V + +acpi:TTP*: + ID_VENDOR_FROM_DATABASE=Toshiba Corporation + +acpi:TTS*: + ID_VENDOR_FROM_DATABASE=TechnoTrend Systemtechnik GmbH + +acpi:TTX*: + ID_VENDOR_FROM_DATABASE=Taitex Corporation + +acpi:TTY*: + ID_VENDOR_FROM_DATABASE=TRIDELITY Display Solutions GmbH + +acpi:TUA*: + ID_VENDOR_FROM_DATABASE=T+A elektroakustik GmbH + +acpi:TUT*: + ID_VENDOR_FROM_DATABASE=Tut Systems + +acpi:TVD*: + ID_VENDOR_FROM_DATABASE=Tecnovision + +acpi:TVI*: + ID_VENDOR_FROM_DATABASE=Truevision + +acpi:TVL*: + ID_VENDOR_FROM_DATABASE=Total Vision LTD + +acpi:TVM*: + ID_VENDOR_FROM_DATABASE=Taiwan Video & Monitor Corporation + +acpi:TVO*: + ID_VENDOR_FROM_DATABASE=TV One Ltd + +acpi:TVR*: + ID_VENDOR_FROM_DATABASE=TV Interactive Corporation + +acpi:TVS*: + ID_VENDOR_FROM_DATABASE=TVS Electronics Limited + +acpi:TVV*: + ID_VENDOR_FROM_DATABASE=TV1 GmbH + +acpi:TWA*: + ID_VENDOR_FROM_DATABASE=Tidewater Association + +acpi:TWE*: + ID_VENDOR_FROM_DATABASE=Kontron Electronik + +acpi:TWH*: + ID_VENDOR_FROM_DATABASE=Twinhead International Corporation + +acpi:TWI*: + ID_VENDOR_FROM_DATABASE=Easytel oy + +acpi:TWK*: + ID_VENDOR_FROM_DATABASE=TOWITOKO electronics GmbH + +acpi:TWX*: + ID_VENDOR_FROM_DATABASE=TEKWorx Limited + +acpi:TXL*: + ID_VENDOR_FROM_DATABASE=Trixel Ltd + +acpi:TXN*: + ID_VENDOR_FROM_DATABASE=Texas Insturments + +acpi:TXT*: + ID_VENDOR_FROM_DATABASE=Textron Defense System + +acpi:TYN*: + ID_VENDOR_FROM_DATABASE=Tyan Computer Corporation + +acpi:UAS*: + ID_VENDOR_FROM_DATABASE=Ultima Associates Pte Ltd + +acpi:UBI*: + ID_VENDOR_FROM_DATABASE=Ungermann-Bass Inc + +acpi:UBL*: + ID_VENDOR_FROM_DATABASE=Ubinetics Ltd. + +acpi:UBU*: + ID_VENDOR_FROM_DATABASE=Canonical Ltd. + +acpi:UDN*: + ID_VENDOR_FROM_DATABASE=Uniden Corporation + +acpi:UEC*: + ID_VENDOR_FROM_DATABASE=Ultima Electronics Corporation + +acpi:UEG*: + ID_VENDOR_FROM_DATABASE=Elitegroup Computer Systems Company Ltd + +acpi:UEI*: + ID_VENDOR_FROM_DATABASE=Universal Electronics Inc + +acpi:UET*: + ID_VENDOR_FROM_DATABASE=Universal Empowering Technologies + +acpi:UFG*: + ID_VENDOR_FROM_DATABASE=UNIGRAF-USA + +acpi:UFO*: + ID_VENDOR_FROM_DATABASE=UFO Systems Inc + +acpi:UHB*: + ID_VENDOR_FROM_DATABASE=XOCECO + +acpi:UIC*: + ID_VENDOR_FROM_DATABASE=Uniform Industrial Corporation + +acpi:UJR*: + ID_VENDOR_FROM_DATABASE=Ueda Japan Radio Co., Ltd. + +acpi:ULT*: + ID_VENDOR_FROM_DATABASE=Ultra Network Tech + +acpi:UMC*: + ID_VENDOR_FROM_DATABASE=United Microelectr Corporation + +acpi:UMG*: + ID_VENDOR_FROM_DATABASE=Umezawa Giken Co.,Ltd + +acpi:UMM*: + ID_VENDOR_FROM_DATABASE=Universal Multimedia + +acpi:UMT*: + ID_VENDOR_FROM_DATABASE=UltiMachine + +acpi:UNA*: + ID_VENDOR_FROM_DATABASE=Unisys DSD + +acpi:UNB*: + ID_VENDOR_FROM_DATABASE=Unisys Corporation + +acpi:UNC*: + ID_VENDOR_FROM_DATABASE=Unisys Corporation + +acpi:UND* + ID_VENDOR_FROM_DATABASE=Unisys Corporation + +acpi:UNE* + ID_VENDOR_FROM_DATABASE=Unisys Corporation + +acpi:UNF* + ID_VENDOR_FROM_DATABASE=Unisys Corporation + +acpi:UNI*: + ID_VENDOR_FROM_DATABASE=Uniform Industry Corp. + +acpi:UNM*: + ID_VENDOR_FROM_DATABASE=Unisys Corporation + +acpi:UNO*: + ID_VENDOR_FROM_DATABASE=Unisys Corporation + +acpi:UNP*: + ID_VENDOR_FROM_DATABASE=Unitop + +acpi:UNS*: + ID_VENDOR_FROM_DATABASE=Unisys Corporation + +acpi:UNT*: + ID_VENDOR_FROM_DATABASE=Unisys Corporation + +acpi:UNY*: + ID_VENDOR_FROM_DATABASE=Unicate + +acpi:UPP*: + ID_VENDOR_FROM_DATABASE=UPPI + +acpi:UPS*: + ID_VENDOR_FROM_DATABASE=Systems Enhancement + +acpi:URD*: + ID_VENDOR_FROM_DATABASE=Video Computer S.p.A. + +acpi:USA*: + ID_VENDOR_FROM_DATABASE=Utimaco Safeware AG + +acpi:USC*: + ID_VENDOR_FROM_DATABASE=UltraStor + +acpi:USD*: + ID_VENDOR_FROM_DATABASE=U.S. Digital Corporation + +acpi:USE*: + ID_VENDOR_FROM_DATABASE=U. S. Electronics Inc. + +acpi:USI*: + ID_VENDOR_FROM_DATABASE=Universal Scientific Industrial Co., Ltd. + +acpi:USR*: + ID_VENDOR_FROM_DATABASE=U.S. Robotics Inc + +acpi:UTD*: + ID_VENDOR_FROM_DATABASE=Up to Date Tech + +acpi:UWC*: + ID_VENDOR_FROM_DATABASE=Uniwill Computer Corp. + +acpi:VAD*: + ID_VENDOR_FROM_DATABASE=Vaddio, LLC + +acpi:VAI*: + ID_VENDOR_FROM_DATABASE=VAIO Corporation + +acpi:VAL*: + ID_VENDOR_FROM_DATABASE=Valence Computing Corporation + +acpi:VAR*: + ID_VENDOR_FROM_DATABASE=Varian Australia Pty Ltd + +acpi:VAT*: + ID_VENDOR_FROM_DATABASE=VADATECH INC + +acpi:VBR*: + ID_VENDOR_FROM_DATABASE=VBrick Systems Inc. + +acpi:VBT*: + ID_VENDOR_FROM_DATABASE=Valley Board Ltda + +acpi:VCC*: + ID_VENDOR_FROM_DATABASE=Virtual Computer Corporation + +acpi:VCI*: + ID_VENDOR_FROM_DATABASE=VistaCom Inc + +acpi:VCJ*: + ID_VENDOR_FROM_DATABASE=Victor Company of Japan, Limited + +acpi:VCM*: + ID_VENDOR_FROM_DATABASE=Vector Magnetics, LLC + +acpi:VCX*: + ID_VENDOR_FROM_DATABASE=VCONEX + +acpi:VDA*: + ID_VENDOR_FROM_DATABASE=Victor Data Systems + +acpi:VDC*: + ID_VENDOR_FROM_DATABASE=VDC Display Systems + +acpi:VDM*: + ID_VENDOR_FROM_DATABASE=Vadem + +acpi:VDO*: + ID_VENDOR_FROM_DATABASE=Video & Display Oriented Corporation + +acpi:VDS*: + ID_VENDOR_FROM_DATABASE=Vidisys GmbH & Company + +acpi:VDT*: + ID_VENDOR_FROM_DATABASE=Viditec, Inc. + +acpi:VEC*: + ID_VENDOR_FROM_DATABASE=Vector Informatik GmbH + +acpi:VEK*: + ID_VENDOR_FROM_DATABASE=Vektrex + +acpi:VES*: + ID_VENDOR_FROM_DATABASE=Vestel Elektronik Sanayi ve Ticaret A. S. + +acpi:VFI*: + ID_VENDOR_FROM_DATABASE=VeriFone Inc + +acpi:VHI*: + ID_VENDOR_FROM_DATABASE=Macrocad Development Inc. + +acpi:VIA*: + ID_VENDOR_FROM_DATABASE=VIA Tech Inc + +acpi:VIB*: + ID_VENDOR_FROM_DATABASE=Tatung UK Ltd + +acpi:VIC*: + ID_VENDOR_FROM_DATABASE=Victron B.V. + +acpi:VID*: + ID_VENDOR_FROM_DATABASE=Ingram Macrotron Germany + +acpi:VIK*: + ID_VENDOR_FROM_DATABASE=Viking Connectors + +acpi:VIM*: + ID_VENDOR_FROM_DATABASE=Via Mons Ltd. + +acpi:VIN*: + ID_VENDOR_FROM_DATABASE=Vine Micros Ltd + +acpi:VIR*: + ID_VENDOR_FROM_DATABASE=Visual Interface, Inc + +acpi:VIS*: + ID_VENDOR_FROM_DATABASE=Visioneer + +acpi:VIT*: + ID_VENDOR_FROM_DATABASE=Visitech AS + +acpi:VIZ*: + ID_VENDOR_FROM_DATABASE=VIZIO, Inc + +acpi:VLB*: + ID_VENDOR_FROM_DATABASE=ValleyBoard Ltda. + +acpi:VLC*: + ID_VENDOR_FROM_DATABASE=VersaLogic Corporation + +acpi:VLK*: + ID_VENDOR_FROM_DATABASE=Vislink International Ltd + +acpi:VLM*: + ID_VENDOR_FROM_DATABASE=LENOVO BEIJING CO. LTD. + +acpi:VLT*: + ID_VENDOR_FROM_DATABASE=VideoLan Technologies + +acpi:VLV*: + ID_VENDOR_FROM_DATABASE=Valve Corporation + +acpi:VMI*: + ID_VENDOR_FROM_DATABASE=Vermont Microsystems + +acpi:VML*: + ID_VENDOR_FROM_DATABASE=Vine Micros Limited + +acpi:VMW*: + ID_VENDOR_FROM_DATABASE=VMware Inc., + +acpi:VNC*: + ID_VENDOR_FROM_DATABASE=Vinca Corporation + +acpi:VOB*: + ID_VENDOR_FROM_DATABASE=MaxData Computer AG + +acpi:VPI*: + ID_VENDOR_FROM_DATABASE=Video Products Inc + +acpi:VPR*: + ID_VENDOR_FROM_DATABASE=Best Buy + +acpi:VPX*: + ID_VENDOR_FROM_DATABASE=VPixx Technologies Inc. + +acpi:VQ@*: + ID_VENDOR_FROM_DATABASE=Vision Quest + +acpi:VRC*: + ID_VENDOR_FROM_DATABASE=Virtual Resources Corporation + +acpi:VRG*: + ID_VENDOR_FROM_DATABASE=VRgineers, Inc. + +acpi:VRM*: + ID_VENDOR_FROM_DATABASE=VRmagic Holding AG + +acpi:VRS*: + ID_VENDOR_FROM_DATABASE=VRstudios, Inc. + +acpi:VRT*: + ID_VENDOR_FROM_DATABASE=Varjo Technologies + +acpi:VSC*: + ID_VENDOR_FROM_DATABASE=ViewSonic Corporation + +acpi:VSD*: + ID_VENDOR_FROM_DATABASE=3M + +acpi:VSI*: + ID_VENDOR_FROM_DATABASE=VideoServer + +acpi:VSN*: + ID_VENDOR_FROM_DATABASE=Ingram Macrotron + +acpi:VSP*: + ID_VENDOR_FROM_DATABASE=Vision Systems GmbH + +acpi:VSR*: + ID_VENDOR_FROM_DATABASE=V-Star Electronics Inc. + +acpi:VTB*: + ID_VENDOR_FROM_DATABASE=Videotechnik Breithaupt + +acpi:VTC*: + ID_VENDOR_FROM_DATABASE=VTel Corporation + +acpi:VTG*: + ID_VENDOR_FROM_DATABASE=Voice Technologies Group Inc + +acpi:VTI*: + ID_VENDOR_FROM_DATABASE=VLSI Tech Inc + +acpi:VTK*: + ID_VENDOR_FROM_DATABASE=Viewteck Co., Ltd. + +acpi:VTL*: + ID_VENDOR_FROM_DATABASE=Vivid Technology Pte Ltd + +acpi:VTM*: + ID_VENDOR_FROM_DATABASE=Miltope Corporation + +acpi:VTN*: + ID_VENDOR_FROM_DATABASE=VIDEOTRON CORP. + +acpi:VTS*: + ID_VENDOR_FROM_DATABASE=VTech Computers Ltd + +acpi:VTV*: + ID_VENDOR_FROM_DATABASE=VATIV Technologies + +acpi:VTX*: + ID_VENDOR_FROM_DATABASE=Vestax Corporation + +acpi:VUT*: + ID_VENDOR_FROM_DATABASE=Vutrix (UK) Ltd + +acpi:VWB*: + ID_VENDOR_FROM_DATABASE=Vweb Corp. + +acpi:WAC*: + ID_VENDOR_FROM_DATABASE=Wacom Tech + +acpi:WAL*: + ID_VENDOR_FROM_DATABASE=Wave Access + +acpi:WAV*: + ID_VENDOR_FROM_DATABASE=Wavephore + +acpi:WBN*: + ID_VENDOR_FROM_DATABASE=MicroSoftWare + +acpi:WBS*: + ID_VENDOR_FROM_DATABASE=WB Systemtechnik GmbH + +acpi:WCI*: + ID_VENDOR_FROM_DATABASE=Wisecom Inc + +acpi:WCS*: + ID_VENDOR_FROM_DATABASE=Woodwind Communications Systems Inc + +acpi:WDC*: + ID_VENDOR_FROM_DATABASE=Western Digital + +acpi:WDE*: + ID_VENDOR_FROM_DATABASE=Westinghouse Digital Electronics + +acpi:WEB*: + ID_VENDOR_FROM_DATABASE=WebGear Inc + +acpi:WEC*: + ID_VENDOR_FROM_DATABASE=Winbond Electronics Corporation + +acpi:WEL*: + ID_VENDOR_FROM_DATABASE=W-DEV + +acpi:WEY*: + ID_VENDOR_FROM_DATABASE=WEY Design AG + +acpi:WHI*: + ID_VENDOR_FROM_DATABASE=Whistle Communications + +acpi:WII*: + ID_VENDOR_FROM_DATABASE=Innoware Inc + +acpi:WIL*: + ID_VENDOR_FROM_DATABASE=WIPRO Information Technology Ltd + +acpi:WIN*: + ID_VENDOR_FROM_DATABASE=Wintop Technology Inc + +acpi:WIP*: + ID_VENDOR_FROM_DATABASE=Wipro Infotech + +acpi:WKH*: + ID_VENDOR_FROM_DATABASE=Uni-Take Int'l Inc. + +acpi:WLD*: + ID_VENDOR_FROM_DATABASE=Wildfire Communications Inc + +acpi:WLF*: + ID_VENDOR_FROM_DATABASE=WOLF Advanced Technology + +acpi:WML*: + ID_VENDOR_FROM_DATABASE=Wolfson Microelectronics Ltd + +acpi:WMO*: + ID_VENDOR_FROM_DATABASE=Westermo Teleindustri AB + +acpi:WMT*: + ID_VENDOR_FROM_DATABASE=Winmate Communication Inc + +acpi:WNI*: + ID_VENDOR_FROM_DATABASE=WillNet Inc. + +acpi:WNV*: + ID_VENDOR_FROM_DATABASE=Winnov L.P. + +acpi:WNX*: + ID_VENDOR_FROM_DATABASE=Diebold Nixdorf Systems GmbH + +acpi:WPA*: + ID_VENDOR_FROM_DATABASE=Matsushita Communication Industrial Co., Ltd. + +acpi:WPI*: + ID_VENDOR_FROM_DATABASE=Wearnes Peripherals International (Pte) Ltd + +acpi:WRC*: + ID_VENDOR_FROM_DATABASE=WiNRADiO Communications + +acpi:WSC*: + ID_VENDOR_FROM_DATABASE=CIS Technology Inc + +acpi:WSP*: + ID_VENDOR_FROM_DATABASE=Wireless And Smart Products Inc. + +acpi:WST*: + ID_VENDOR_FROM_DATABASE=Wistron Corporation + +acpi:WTC*: + ID_VENDOR_FROM_DATABASE=ACC Microelectronics + +acpi:WTI*: + ID_VENDOR_FROM_DATABASE=WorkStation Tech + +acpi:WTK*: + ID_VENDOR_FROM_DATABASE=Wearnes Thakral Pte + +acpi:WTS*: + ID_VENDOR_FROM_DATABASE=Restek Electric Company Ltd + +acpi:WVM*: + ID_VENDOR_FROM_DATABASE=Wave Systems Corporation + +acpi:WVV*: + ID_VENDOR_FROM_DATABASE=WolfVision GmbH + +acpi:WWP*: + ID_VENDOR_FROM_DATABASE=Wipotec Wiege- und Positioniersysteme GmbH + +acpi:WWV*: + ID_VENDOR_FROM_DATABASE=World Wide Video, Inc. + +acpi:WXT*: + ID_VENDOR_FROM_DATABASE=Woxter Technology Co. Ltd + +acpi:WYR*: + ID_VENDOR_FROM_DATABASE=WyreStorm Technologies LLC + +acpi:WYS*: + ID_VENDOR_FROM_DATABASE=Wyse Technology + +acpi:WYT*: + ID_VENDOR_FROM_DATABASE=Wooyoung Image & Information Co.,Ltd. + +acpi:XAC*: + ID_VENDOR_FROM_DATABASE=XAC Automation Corp + +acpi:XAD*: + ID_VENDOR_FROM_DATABASE=Alpha Data + +acpi:XDM*: + ID_VENDOR_FROM_DATABASE=XDM Ltd. + +acpi:XES*: + ID_VENDOR_FROM_DATABASE=Extreme Engineering Solutions, Inc. + +acpi:XFG*: + ID_VENDOR_FROM_DATABASE=Jan Strapko - FOTO + +acpi:XFO*: + ID_VENDOR_FROM_DATABASE=EXFO Electro Optical Engineering + +acpi:XIN*: + ID_VENDOR_FROM_DATABASE=Xinex Networks Inc + +acpi:XIO*: + ID_VENDOR_FROM_DATABASE=Xiotech Corporation + +acpi:XIR*: + ID_VENDOR_FROM_DATABASE=Xirocm Inc + +acpi:XIT*: + ID_VENDOR_FROM_DATABASE=Xitel Pty ltd + +acpi:XLX*: + ID_VENDOR_FROM_DATABASE=Xilinx, Inc. + +acpi:XMM*: + ID_VENDOR_FROM_DATABASE=C3PO S.L. + +acpi:XNT*: + ID_VENDOR_FROM_DATABASE=XN Technologies, Inc. + +acpi:XQU*: + ID_VENDOR_FROM_DATABASE=SHANGHAI SVA-DAV ELECTRONICS CO., LTD + +acpi:XRC*: + ID_VENDOR_FROM_DATABASE=Xircom Inc + +acpi:XRO*: + ID_VENDOR_FROM_DATABASE=XORO ELECTRONICS (CHENGDU) LIMITED + +acpi:XSN*: + ID_VENDOR_FROM_DATABASE=Xscreen AS + +acpi:XST*: + ID_VENDOR_FROM_DATABASE=XS Technologies Inc + +acpi:XSY*: + ID_VENDOR_FROM_DATABASE=XSYS + +acpi:XTD*: + ID_VENDOR_FROM_DATABASE=Icuiti Corporation + +acpi:XTE*: + ID_VENDOR_FROM_DATABASE=X2E GmbH + +acpi:XTL*: + ID_VENDOR_FROM_DATABASE=Crystal Computer + +acpi:XTN*: + ID_VENDOR_FROM_DATABASE=X-10 (USA) Inc + +acpi:XYC*: + ID_VENDOR_FROM_DATABASE=Xycotec Computer GmbH + +acpi:XYE*: + ID_VENDOR_FROM_DATABASE=Shenzhen Zhuona Technology Co., Ltd. + +acpi:YED*: + ID_VENDOR_FROM_DATABASE=Y-E Data Inc + +acpi:YHQ*: + ID_VENDOR_FROM_DATABASE=Yokogawa Electric Corporation + +acpi:YHW*: + ID_VENDOR_FROM_DATABASE=Exacom SA + +acpi:YMH*: + ID_VENDOR_FROM_DATABASE=Yamaha Corporation + +acpi:YOW*: + ID_VENDOR_FROM_DATABASE=American Biometric Company + +acpi:ZAN*: + ID_VENDOR_FROM_DATABASE=Zandar Technologies plc + +acpi:ZAX*: + ID_VENDOR_FROM_DATABASE=Zefiro Acoustics + +acpi:ZAZ*: + ID_VENDOR_FROM_DATABASE=ZeeVee, Inc. + +acpi:ZBR*: + ID_VENDOR_FROM_DATABASE=Zebra Technologies International, LLC + +acpi:ZBX*: + ID_VENDOR_FROM_DATABASE=Zebax Technologies + +acpi:ZCM*: + ID_VENDOR_FROM_DATABASE=Zenith + +acpi:ZCT*: + ID_VENDOR_FROM_DATABASE=ZeitControl cardsystems GmbH + +acpi:ZDS*: + ID_VENDOR_FROM_DATABASE=Zenith Data Systems + +acpi:ZEN*: + ID_VENDOR_FROM_DATABASE=ZENIC Inc. + +acpi:ZGT*: + ID_VENDOR_FROM_DATABASE=Zenith Data Systems + +acpi:ZIC*: + ID_VENDOR_FROM_DATABASE=Nationz Technologies Inc. + +acpi:ZMC*: + ID_VENDOR_FROM_DATABASE=HangZhou ZMCHIVIN + +acpi:ZMT*: + ID_VENDOR_FROM_DATABASE=Zalman Tech Co., Ltd. + +acpi:ZMZ*: + ID_VENDOR_FROM_DATABASE=Z Microsystems + +acpi:ZNI*: + ID_VENDOR_FROM_DATABASE=Zetinet Inc + +acpi:ZNX*: + ID_VENDOR_FROM_DATABASE=Znyx Adv. Systems + +acpi:ZOW*: + ID_VENDOR_FROM_DATABASE=Zowie Intertainment, Inc + +acpi:ZRN*: + ID_VENDOR_FROM_DATABASE=Zoran Corporation + +acpi:ZSE*: + ID_VENDOR_FROM_DATABASE=Zenith Data Systems + +acpi:ZTC*: + ID_VENDOR_FROM_DATABASE=ZyDAS Technology Corporation + +acpi:ZTE*: + ID_VENDOR_FROM_DATABASE=ZTE Corporation + +acpi:ZTI*: + ID_VENDOR_FROM_DATABASE=Zoom Telephonics Inc + +acpi:ZTM*: + ID_VENDOR_FROM_DATABASE=ZT Group Int'l Inc. + +acpi:ZTT*: + ID_VENDOR_FROM_DATABASE=Z3 Technology + +acpi:ZWE*: + ID_VENDOR_FROM_DATABASE=Shenzhen Zowee Technology Co., LTD + +acpi:ZYD*: + ID_VENDOR_FROM_DATABASE=Zydacron Inc + +acpi:ZYP*: + ID_VENDOR_FROM_DATABASE=Zypcom Inc + +acpi:ZYT*: + ID_VENDOR_FROM_DATABASE=Zytex Computers + +acpi:ZYX*: + ID_VENDOR_FROM_DATABASE=Zyxel + +acpi:ZZZ*: + ID_VENDOR_FROM_DATABASE=Boca Research Inc + +acpi:inu*: + ID_VENDOR_FROM_DATABASE=Inovatec S.p.A. diff --git a/hwdb.d/20-acpi-vendor.hwdb.patch b/hwdb.d/20-acpi-vendor.hwdb.patch new file mode 100644 index 00000000..84ea0fd5 --- /dev/null +++ b/hwdb.d/20-acpi-vendor.hwdb.patch @@ -0,0 +1,502 @@ +--- 20-acpi-vendor.hwdb.base 2020-02-04 18:26:50.552863816 +0100 ++++ 20-acpi-vendor.hwdb 2020-02-04 18:26:50.569863967 +0100 +@@ -3,6 +3,8 @@ + # Data imported from: + # https://uefi.org/uefi-pnp-export + # https://uefi.org/uefi-acpi-export ++# ++# With various additions from other sources + + acpi:3GVR*: + ID_VENDOR_FROM_DATABASE=VR Technology Holdings Limited +@@ -16,9 +18,6 @@ + acpi:AAVA*: + ID_VENDOR_FROM_DATABASE=Aava Mobile Oy + +-acpi:ACPI*: +- ID_VENDOR_FROM_DATABASE=Intel Corporation +- + acpi:AMDI*: + ID_VENDOR_FROM_DATABASE=AMD + +@@ -283,6 +282,9 @@ + acpi:AAA*: + ID_VENDOR_FROM_DATABASE=Avolites Ltd + ++acpi:AAC*: ++ ID_VENDOR_FROM_DATABASE=AcerView ++ + acpi:AAE*: + ID_VENDOR_FROM_DATABASE=Anatek Electronics Inc. + +@@ -310,6 +312,9 @@ + acpi:ABO*: + ID_VENDOR_FROM_DATABASE=D-Link Systems Inc + ++acpi:ABP*: ++ ID_VENDOR_FROM_DATABASE=Advansys ++ + acpi:ABS*: + ID_VENDOR_FROM_DATABASE=Abaco Systems, Inc. + +@@ -355,7 +360,7 @@ + acpi:ACO*: + ID_VENDOR_FROM_DATABASE=Allion Computer Inc. + +-acpi:ACP*: ++acpi:ACP[0-9A-F]*: + ID_VENDOR_FROM_DATABASE=Aspen Tech Inc + + acpi:ACR*: +@@ -628,6 +633,9 @@ + acpi:AMT*: + ID_VENDOR_FROM_DATABASE=AMT International Industry + ++acpi:AMW*: ++ ID_VENDOR_FROM_DATABASE=AMW ++ + acpi:AMX*: + ID_VENDOR_FROM_DATABASE=AMX LLC + +@@ -676,6 +684,9 @@ + acpi:AOA*: + ID_VENDOR_FROM_DATABASE=AOpen Inc. + ++acpi:AOC*: ++ ID_VENDOR_FROM_DATABASE=AOC ++ + acpi:AOE*: + ID_VENDOR_FROM_DATABASE=Advanced Optics Electronics, Inc. + +@@ -685,6 +696,9 @@ + acpi:AOT*: + ID_VENDOR_FROM_DATABASE=Alcatel + ++acpi:APA*: ++ ID_VENDOR_FROM_DATABASE=Adaptec ++ + acpi:APC*: + ID_VENDOR_FROM_DATABASE=American Power Conversion + +@@ -860,7 +874,7 @@ + ID_VENDOR_FROM_DATABASE=Alps Electric Inc + + acpi:AUO*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - AUO ++ ID_VENDOR_FROM_DATABASE=AU Optronics + + acpi:AUR*: + ID_VENDOR_FROM_DATABASE=Aureal Semiconductor +@@ -940,6 +954,9 @@ + acpi:AXE*: + ID_VENDOR_FROM_DATABASE=Axell Corporation + ++acpi:AXE*: ++ ID_VENDOR_FROM_DATABASE=D-Link Systems Inc ++ + acpi:AXI*: + ID_VENDOR_FROM_DATABASE=American Magnetics + +@@ -1090,6 +1107,9 @@ + acpi:BML*: + ID_VENDOR_FROM_DATABASE=BIOMED Lab + ++acpi:BMM*: ++ ID_VENDOR_FROM_DATABASE=BMM ++ + acpi:BMS*: + ID_VENDOR_FROM_DATABASE=BIOMEDISYS + +@@ -1102,6 +1122,9 @@ + acpi:BNO*: + ID_VENDOR_FROM_DATABASE=Bang & Olufsen + ++acpi:BNQ*: ++ ID_VENDOR_FROM_DATABASE=BenQ Corporation ++ + acpi:BNS*: + ID_VENDOR_FROM_DATABASE=Boulder Nonlinear Systems + +@@ -1342,6 +1365,9 @@ + acpi:CHA*: + ID_VENDOR_FROM_DATABASE=Chase Research PLC + ++acpi:CHC*: ++ ID_VENDOR_FROM_DATABASE=Chic Technology Corp. ++ + acpi:CHD*: + ID_VENDOR_FROM_DATABASE=ChangHong Electric Co.,Ltd + +@@ -1495,6 +1521,9 @@ + acpi:COD*: + ID_VENDOR_FROM_DATABASE=CODAN Pty. Ltd. + ++acpi:COG*: ++ ID_VENDOR_FROM_DATABASE=Cogent ++ + acpi:COI*: + ID_VENDOR_FROM_DATABASE=Codec Inc. + +@@ -1901,7 +1930,7 @@ + ID_VENDOR_FROM_DATABASE=Dragon Information Technology + + acpi:DJE*: +- ID_VENDOR_FROM_DATABASE=Capstone Visua lProduct Development ++ ID_VENDOR_FROM_DATABASE=Capstone Visual Product Development + + acpi:DJP*: + ID_VENDOR_FROM_DATABASE=Maygay Machines, Ltd +@@ -2233,6 +2262,9 @@ + acpi:EIN*: + ID_VENDOR_FROM_DATABASE=Elegant Invention + ++acpi:EIZ*: ++ ID_VENDOR_FROM_DATABASE=Eizo ++ + acpi:EKA*: + ID_VENDOR_FROM_DATABASE=MagTek Inc. + +@@ -2494,6 +2526,9 @@ + acpi:FCG*: + ID_VENDOR_FROM_DATABASE=First International Computer Ltd + ++acpi:FCM*: ++ ID_VENDOR_FROM_DATABASE=Funai ++ + acpi:FCS*: + ID_VENDOR_FROM_DATABASE=Focus Enhancements, Inc. + +@@ -2867,7 +2902,7 @@ + ID_VENDOR_FROM_DATABASE=General Standards Corporation + + acpi:GSM*: +- ID_VENDOR_FROM_DATABASE=Goldstar Company Ltd ++ ID_VENDOR_FROM_DATABASE=LG Electronics + + acpi:GSN*: + ID_VENDOR_FROM_DATABASE=Grandstream Networks, Inc. +@@ -2968,6 +3003,9 @@ + acpi:HEC*: + ID_VENDOR_FROM_DATABASE=Hisense Electric Co., Ltd. + ++acpi:HEI*: ++ ID_VENDOR_FROM_DATABASE=Hyundai ++ + acpi:HEL*: + ID_VENDOR_FROM_DATABASE=Hitachi Micro Systems Europe Ltd + +@@ -3097,6 +3135,9 @@ + acpi:HSD*: + ID_VENDOR_FROM_DATABASE=HannStar Display Corp + ++acpi:HSL*: ++ ID_VENDOR_FROM_DATABASE=Hansol ++ + acpi:HSM*: + ID_VENDOR_FROM_DATABASE=AT&T Microelectronics + +@@ -3220,6 +3261,9 @@ + acpi:ICI*: + ID_VENDOR_FROM_DATABASE=Infotek Communication Inc + ++acpi:ICL*: ++ ID_VENDOR_FROM_DATABASE=Fujitsu ICL ++ + acpi:ICM*: + ID_VENDOR_FROM_DATABASE=Intracom SA + +@@ -3316,6 +3360,9 @@ + acpi:IKE*: + ID_VENDOR_FROM_DATABASE=Ikegami Tsushinki Co. Ltd. + ++acpi:IKN*: ++ ID_VENDOR_FROM_DATABASE=IKON ++ + acpi:IKS*: + ID_VENDOR_FROM_DATABASE=Ikos Systems Inc + +@@ -3361,6 +3408,9 @@ + acpi:IMT*: + ID_VENDOR_FROM_DATABASE=Inmax Technology Corporation + ++acpi:IMS*: ++ ID_VENDOR_FROM_DATABASE=Integrated Micro Solution Inc. ++ + acpi:INA*: + ID_VENDOR_FROM_DATABASE=Inventec Corporation + +@@ -3868,6 +3918,9 @@ + acpi:LAN*: + ID_VENDOR_FROM_DATABASE=Sodeman Lancom Inc + ++acpi:LAP*: ++ ID_VENDOR_FROM_DATABASE=BenQ ++ + acpi:LAS*: + ID_VENDOR_FROM_DATABASE=LASAT Comm. A/S + +@@ -3913,6 +3966,9 @@ + acpi:LED*: + ID_VENDOR_FROM_DATABASE=Long Engineering Design Inc + ++acpi:LED*: ++ ID_VENDOR_FROM_DATABASE=LeafNet ++ + acpi:LEG*: + ID_VENDOR_FROM_DATABASE=Legerity, Inc + +@@ -3928,6 +3984,9 @@ + acpi:LGC*: + ID_VENDOR_FROM_DATABASE=Logic Ltd + ++acpi:LGD*: ++ ID_VENDOR_FROM_DATABASE=LG Display ++ + acpi:LGI*: + ID_VENDOR_FROM_DATABASE=Logitech Inc + +@@ -3982,6 +4041,9 @@ + acpi:LND*: + ID_VENDOR_FROM_DATABASE=Land Computer Company Ltd + ++acpi:LNE*: ++ ID_VENDOR_FROM_DATABASE=Linksys ++ + acpi:LNK*: + ID_VENDOR_FROM_DATABASE=Link Tech Inc + +@@ -4016,7 +4078,7 @@ + ID_VENDOR_FROM_DATABASE=Design Technology + + acpi:LPL*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - LPL ++ ID_VENDOR_FROM_DATABASE=LG Philips + + acpi:LSC*: + ID_VENDOR_FROM_DATABASE=LifeSize Communications +@@ -4192,6 +4254,9 @@ + acpi:MCX*: + ID_VENDOR_FROM_DATABASE=Millson Custom Solutions Inc. + ++acpi:MCY*: ++ ID_VENDOR_FROM_DATABASE=Microdyne ++ + acpi:MDA*: + ID_VENDOR_FROM_DATABASE=Media4 Inc + +@@ -4429,6 +4494,9 @@ + acpi:MOM*: + ID_VENDOR_FROM_DATABASE=Momentum Data Systems + ++acpi:MON*: ++ ID_VENDOR_FROM_DATABASE=Daewoo ++ + acpi:MOS*: + ID_VENDOR_FROM_DATABASE=Moses Corporation + +@@ -4654,6 +4722,9 @@ + acpi:NAL*: + ID_VENDOR_FROM_DATABASE=Network Alchemy + ++acpi:NAN*: ++ ID_VENDOR_FROM_DATABASE=Nanao ++ + acpi:NAT*: + ID_VENDOR_FROM_DATABASE=NaturalPoint Inc. + +@@ -5158,6 +5229,9 @@ + acpi:PCX*: + ID_VENDOR_FROM_DATABASE=PC Xperten + ++acpi:PDC*: ++ ID_VENDOR_FROM_DATABASE=Polaroid ++ + acpi:PDM*: + ID_VENDOR_FROM_DATABASE=Psion Dacom Plc. + +@@ -5221,9 +5295,6 @@ + acpi:PHE*: + ID_VENDOR_FROM_DATABASE=Philips Medical Systems Boeblingen GmbH + +-acpi:PHI*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - PHI +- + acpi:PHL*: + ID_VENDOR_FROM_DATABASE=Philips Consumer Electronics Company + +@@ -5311,9 +5382,6 @@ + acpi:PNL*: + ID_VENDOR_FROM_DATABASE=Panelview, Inc. + +-acpi:PNP*: +- ID_VENDOR_FROM_DATABASE=Microsoft +- + acpi:PNR*: + ID_VENDOR_FROM_DATABASE=Planar Systems, Inc. + +@@ -5449,15 +5517,9 @@ + acpi:PTS*: + ID_VENDOR_FROM_DATABASE=Plain Tree Systems Inc + +-acpi:PTW*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - PTW +- + acpi:PUL*: + ID_VENDOR_FROM_DATABASE=Pulse-Eight Ltd + +-acpi:PVC*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - PVC +- + acpi:PVG*: + ID_VENDOR_FROM_DATABASE=Proview Global Co., Ltd + +@@ -5773,9 +5835,6 @@ + acpi:RTI*: + ID_VENDOR_FROM_DATABASE=Rancho Tech Inc + +-acpi:RTK*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - RTK +- + acpi:RTL*: + ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Company Ltd + +@@ -5941,9 +6000,6 @@ + acpi:SEE*: + ID_VENDOR_FROM_DATABASE=SeeColor Corporation + +-acpi:SEG*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - SEG +- + acpi:SEI*: + ID_VENDOR_FROM_DATABASE=Seitz & Associates Inc + +@@ -6400,6 +6456,9 @@ + acpi:SVD*: + ID_VENDOR_FROM_DATABASE=SVD Computer + ++acpi:SVE*: ++ ID_VENDOR_FROM_DATABASE=SVEC ++ + acpi:SVI*: + ID_VENDOR_FROM_DATABASE=Sun Microsystems + +@@ -6484,6 +6543,9 @@ + acpi:SZM*: + ID_VENDOR_FROM_DATABASE=Shenzhen MTC Co., Ltd + ++acpi:SZV*: ++ ID_VENDOR_FROM_DATABASE=OvisLink ++ + acpi:TAA*: + ID_VENDOR_FROM_DATABASE=Tandberg + +@@ -6574,6 +6636,9 @@ + acpi:TDG*: + ID_VENDOR_FROM_DATABASE=Six15 Technologies + ++acpi:TDK*: ++ ID_VENDOR_FROM_DATABASE=TDK USA Corporation ++ + acpi:TDM*: + ID_VENDOR_FROM_DATABASE=Tandem Computer Europe Inc + +@@ -6616,6 +6681,9 @@ + acpi:TEV*: + ID_VENDOR_FROM_DATABASE=Televés, S.A. + ++acpi:TEX*: ++ ID_VENDOR_FROM_DATABASE=Texas Instruments ++ + acpi:TEZ*: + ID_VENDOR_FROM_DATABASE=Tech Source Inc. + +@@ -6730,9 +6798,6 @@ + acpi:TNC*: + ID_VENDOR_FROM_DATABASE=TNC Industrial Company Ltd + +-acpi:TNJ*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - TNJ +- + acpi:TNM*: + ID_VENDOR_FROM_DATABASE=TECNIMAGEN SA + +@@ -7039,14 +7104,14 @@ + acpi:UNC*: + ID_VENDOR_FROM_DATABASE=Unisys Corporation + +-acpi:UND*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - UND ++acpi:UND* ++ ID_VENDOR_FROM_DATABASE=Unisys Corporation + +-acpi:UNE*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - UNE ++acpi:UNE* ++ ID_VENDOR_FROM_DATABASE=Unisys Corporation + +-acpi:UNF*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - UNF ++acpi:UNF* ++ ID_VENDOR_FROM_DATABASE=Unisys Corporation + + acpi:UNI*: + ID_VENDOR_FROM_DATABASE=Uniform Industry Corp. +@@ -7081,6 +7146,9 @@ + acpi:USA*: + ID_VENDOR_FROM_DATABASE=Utimaco Safeware AG + ++acpi:USC*: ++ ID_VENDOR_FROM_DATABASE=UltraStor ++ + acpi:USD*: + ID_VENDOR_FROM_DATABASE=U.S. Digital Corporation + +@@ -7324,9 +7392,6 @@ + acpi:WAL*: + ID_VENDOR_FROM_DATABASE=Wave Access + +-acpi:WAN*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - WAN +- + acpi:WAV*: + ID_VENDOR_FROM_DATABASE=Wavephore + +@@ -7451,7 +7516,7 @@ + ID_VENDOR_FROM_DATABASE=WyreStorm Technologies LLC + + acpi:WYS*: +- ID_VENDOR_FROM_DATABASE=Myse Technology ++ ID_VENDOR_FROM_DATABASE=Wyse Technology + + acpi:WYT*: + ID_VENDOR_FROM_DATABASE=Wooyoung Image & Information Co.,Ltd. +@@ -7465,9 +7530,6 @@ + acpi:XDM*: + ID_VENDOR_FROM_DATABASE=XDM Ltd. + +-acpi:XER*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - XER +- + acpi:XES*: + ID_VENDOR_FROM_DATABASE=Extreme Engineering Solutions, Inc. + +@@ -7498,9 +7560,6 @@ + acpi:XNT*: + ID_VENDOR_FROM_DATABASE=XN Technologies, Inc. + +-acpi:XOC*: +- ID_VENDOR_FROM_DATABASE=DO NOT USE - XOC +- + acpi:XQU*: + ID_VENDOR_FROM_DATABASE=SHANGHAI SVA-DAV ELECTRONICS CO., LTD + +@@ -7567,6 +7626,9 @@ + acpi:ZBX*: + ID_VENDOR_FROM_DATABASE=Zebax Technologies + ++acpi:ZCM*: ++ ID_VENDOR_FROM_DATABASE=Zenith ++ + acpi:ZCT*: + ID_VENDOR_FROM_DATABASE=ZeitControl cardsystems GmbH + diff --git a/hwdb.d/20-bluetooth-vendor-product.hwdb b/hwdb.d/20-bluetooth-vendor-product.hwdb new file mode 100644 index 00000000..9cba3bfc --- /dev/null +++ b/hwdb.d/20-bluetooth-vendor-product.hwdb @@ -0,0 +1,3121 @@ +# This file is part of systemd. +# +# Data imported from: +# http://www.bluetooth.org/Technical/AssignedNumbers/identifiers.htm + +bluetooth:v0000* + ID_VENDOR_FROM_DATABASE=Ericsson Technology Licensing + +bluetooth:v0001* + ID_VENDOR_FROM_DATABASE=Nokia Mobile Phones + +bluetooth:v0002* + ID_VENDOR_FROM_DATABASE=Intel Corp. + +bluetooth:v0003* + ID_VENDOR_FROM_DATABASE=IBM Corp. + +bluetooth:v0004* + ID_VENDOR_FROM_DATABASE=Toshiba Corp. + +bluetooth:v0005* + ID_VENDOR_FROM_DATABASE=3Com + +bluetooth:v0006* + ID_VENDOR_FROM_DATABASE=Microsoft + +bluetooth:v0007* + ID_VENDOR_FROM_DATABASE=Lucent + +bluetooth:v0008* + ID_VENDOR_FROM_DATABASE=Motorola + +bluetooth:v0009* + ID_VENDOR_FROM_DATABASE=Infineon Technologies AG + +bluetooth:v000A* + ID_VENDOR_FROM_DATABASE=Cambridge Silicon Radio + +bluetooth:v000B* + ID_VENDOR_FROM_DATABASE=Silicon Wave + +bluetooth:v000C* + ID_VENDOR_FROM_DATABASE=Digianswer A/S + +bluetooth:v000D* + ID_VENDOR_FROM_DATABASE=Texas Instruments Inc. + +bluetooth:v000E* + ID_VENDOR_FROM_DATABASE=Ceva, Inc. (formerly Parthus Technologies, Inc.) + +bluetooth:v000F* + ID_VENDOR_FROM_DATABASE=Broadcom Corporation + +bluetooth:v0010* + ID_VENDOR_FROM_DATABASE=Mitel Semiconductor + +bluetooth:v0011* + ID_VENDOR_FROM_DATABASE=Widcomm, Inc + +bluetooth:v0012* + ID_VENDOR_FROM_DATABASE=Zeevo, Inc. + +bluetooth:v0013* + ID_VENDOR_FROM_DATABASE=Atmel Corporation + +bluetooth:v0014* + ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Corporation + +bluetooth:v0015* + ID_VENDOR_FROM_DATABASE=RTX Telecom A/S + +bluetooth:v0016* + ID_VENDOR_FROM_DATABASE=KC Technology Inc. + +bluetooth:v0017* + ID_VENDOR_FROM_DATABASE=NewLogic + +bluetooth:v0018* + ID_VENDOR_FROM_DATABASE=Transilica, Inc. + +bluetooth:v0019* + ID_VENDOR_FROM_DATABASE=Rohde & Schwarz GmbH & Co. KG + +bluetooth:v001A* + ID_VENDOR_FROM_DATABASE=TTPCom Limited + +bluetooth:v001B* + ID_VENDOR_FROM_DATABASE=Signia Technologies, Inc. + +bluetooth:v001C* + ID_VENDOR_FROM_DATABASE=Conexant Systems Inc. + +bluetooth:v001D* + ID_VENDOR_FROM_DATABASE=Qualcomm + +bluetooth:v001E* + ID_VENDOR_FROM_DATABASE=Inventel + +bluetooth:v001F* + ID_VENDOR_FROM_DATABASE=AVM Berlin + +bluetooth:v0020* + ID_VENDOR_FROM_DATABASE=BandSpeed, Inc. + +bluetooth:v0021* + ID_VENDOR_FROM_DATABASE=Mansella Ltd + +bluetooth:v0022* + ID_VENDOR_FROM_DATABASE=NEC Corporation + +bluetooth:v0023* + ID_VENDOR_FROM_DATABASE=WavePlus Technology Co., Ltd. + +bluetooth:v0024* + ID_VENDOR_FROM_DATABASE=Alcatel + +bluetooth:v0025* + ID_VENDOR_FROM_DATABASE=NXP Semiconductors (formerly Philips Semiconductors) + +bluetooth:v0026* + ID_VENDOR_FROM_DATABASE=C Technologies + +bluetooth:v0027* + ID_VENDOR_FROM_DATABASE=Open Interface + +bluetooth:v0028* + ID_VENDOR_FROM_DATABASE=R F Micro Devices + +bluetooth:v0029* + ID_VENDOR_FROM_DATABASE=Hitachi Ltd + +bluetooth:v002A* + ID_VENDOR_FROM_DATABASE=Symbol Technologies, Inc. + +bluetooth:v002B* + ID_VENDOR_FROM_DATABASE=Tenovis + +bluetooth:v002C* + ID_VENDOR_FROM_DATABASE=Macronix International Co. Ltd. + +bluetooth:v002D* + ID_VENDOR_FROM_DATABASE=GCT Semiconductor + +bluetooth:v002E* + ID_VENDOR_FROM_DATABASE=Norwood Systems + +bluetooth:v002F* + ID_VENDOR_FROM_DATABASE=MewTel Technology Inc. + +bluetooth:v0030* + ID_VENDOR_FROM_DATABASE=ST Microelectronics + +bluetooth:v0031* + ID_VENDOR_FROM_DATABASE=Synopsys, Inc. + +bluetooth:v0032* + ID_VENDOR_FROM_DATABASE=Red-M (Communications) Ltd + +bluetooth:v0033* + ID_VENDOR_FROM_DATABASE=Commil Ltd + +bluetooth:v0034* + ID_VENDOR_FROM_DATABASE=Computer Access Technology Corporation (CATC) + +bluetooth:v0035* + ID_VENDOR_FROM_DATABASE=Eclipse (HQ Espana) S.L. + +bluetooth:v0036* + ID_VENDOR_FROM_DATABASE=Renesas Electronics Corporation + +bluetooth:v0037* + ID_VENDOR_FROM_DATABASE=Mobilian Corporation + +bluetooth:v0038* + ID_VENDOR_FROM_DATABASE=Terax + +bluetooth:v0039* + ID_VENDOR_FROM_DATABASE=Integrated System Solution Corp. + +bluetooth:v003A* + ID_VENDOR_FROM_DATABASE=Matsushita Electric Industrial Co., Ltd. + +bluetooth:v003B* + ID_VENDOR_FROM_DATABASE=Gennum Corporation + +bluetooth:v003C* + ID_VENDOR_FROM_DATABASE=BlackBerry Limited (formerly Research In Motion) + +bluetooth:v003D* + ID_VENDOR_FROM_DATABASE=IPextreme, Inc. + +bluetooth:v003E* + ID_VENDOR_FROM_DATABASE=Systems and Chips, Inc. + +bluetooth:v003F* + ID_VENDOR_FROM_DATABASE=Bluetooth SIG, Inc. + +bluetooth:v0040* + ID_VENDOR_FROM_DATABASE=Seiko Epson Corporation + +bluetooth:v0041* + ID_VENDOR_FROM_DATABASE=Integrated Silicon Solution Taiwan, Inc. + +bluetooth:v0042* + ID_VENDOR_FROM_DATABASE=CONWISE Technology Corporation Ltd + +bluetooth:v0043* + ID_VENDOR_FROM_DATABASE=PARROT SA + +bluetooth:v0044* + ID_VENDOR_FROM_DATABASE=Socket Mobile + +bluetooth:v0045* + ID_VENDOR_FROM_DATABASE=Atheros Communications, Inc. + +bluetooth:v0046* + ID_VENDOR_FROM_DATABASE=MediaTek, Inc. + +bluetooth:v0047* + ID_VENDOR_FROM_DATABASE=Bluegiga + +bluetooth:v0048* + ID_VENDOR_FROM_DATABASE=Marvell Technology Group Ltd. + +bluetooth:v0049* + ID_VENDOR_FROM_DATABASE=3DSP Corporation + +bluetooth:v004A* + ID_VENDOR_FROM_DATABASE=Accel Semiconductor Ltd. + +bluetooth:v004B* + ID_VENDOR_FROM_DATABASE=Continental Automotive Systems + +bluetooth:v004C* + ID_VENDOR_FROM_DATABASE=Apple, Inc. + +bluetooth:v004D* + ID_VENDOR_FROM_DATABASE=Staccato Communications, Inc. + +bluetooth:v004E* + ID_VENDOR_FROM_DATABASE=Avago Technologies + +bluetooth:v004F* + ID_VENDOR_FROM_DATABASE=APT Licensing Ltd. + +bluetooth:v0050* + ID_VENDOR_FROM_DATABASE=SiRF Technology + +bluetooth:v0051* + ID_VENDOR_FROM_DATABASE=Tzero Technologies, Inc. + +bluetooth:v0052* + ID_VENDOR_FROM_DATABASE=J&M Corporation + +bluetooth:v0053* + ID_VENDOR_FROM_DATABASE=Free2move AB + +bluetooth:v0054* + ID_VENDOR_FROM_DATABASE=3DiJoy Corporation + +bluetooth:v0055* + ID_VENDOR_FROM_DATABASE=Plantronics, Inc. + +bluetooth:v0056* + ID_VENDOR_FROM_DATABASE=Sony Ericsson Mobile Communications + +bluetooth:v0057* + ID_VENDOR_FROM_DATABASE=Harman International Industries, Inc. + +bluetooth:v0058* + ID_VENDOR_FROM_DATABASE=Vizio, Inc. + +bluetooth:v0059* + ID_VENDOR_FROM_DATABASE=Nordic Semiconductor ASA + +bluetooth:v005A* + ID_VENDOR_FROM_DATABASE=EM Microelectronic-Marin SA + +bluetooth:v005B* + ID_VENDOR_FROM_DATABASE=Ralink Technology Corporation + +bluetooth:v005C* + ID_VENDOR_FROM_DATABASE=Belkin International, Inc. + +bluetooth:v005D* + ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corporation + +bluetooth:v005E* + ID_VENDOR_FROM_DATABASE=Stonestreet One, LLC + +bluetooth:v005F* + ID_VENDOR_FROM_DATABASE=Wicentric, Inc. + +bluetooth:v0060* + ID_VENDOR_FROM_DATABASE=RivieraWaves S.A.S + +bluetooth:v0061* + ID_VENDOR_FROM_DATABASE=RDA Microelectronics + +bluetooth:v0062* + ID_VENDOR_FROM_DATABASE=Gibson Guitars + +bluetooth:v0063* + ID_VENDOR_FROM_DATABASE=MiCommand Inc. + +bluetooth:v0064* + ID_VENDOR_FROM_DATABASE=Band XI International, LLC + +bluetooth:v0065* + ID_VENDOR_FROM_DATABASE=Hewlett-Packard Company + +bluetooth:v0066* + ID_VENDOR_FROM_DATABASE=9Solutions Oy + +bluetooth:v0067* + ID_VENDOR_FROM_DATABASE=GN Netcom A/S + +bluetooth:v0068* + ID_VENDOR_FROM_DATABASE=General Motors + +bluetooth:v0069* + ID_VENDOR_FROM_DATABASE=A&D Engineering, Inc. + +bluetooth:v006A* + ID_VENDOR_FROM_DATABASE=MindTree Ltd. + +bluetooth:v006B* + ID_VENDOR_FROM_DATABASE=Polar Electro OY + +bluetooth:v006C* + ID_VENDOR_FROM_DATABASE=Beautiful Enterprise Co., Ltd. + +bluetooth:v006D* + ID_VENDOR_FROM_DATABASE=BriarTek, Inc. + +bluetooth:v006E* + ID_VENDOR_FROM_DATABASE=Summit Data Communications, Inc. + +bluetooth:v006F* + ID_VENDOR_FROM_DATABASE=Sound ID + +bluetooth:v0070* + ID_VENDOR_FROM_DATABASE=Monster, LLC + +bluetooth:v0071* + ID_VENDOR_FROM_DATABASE=connectBlue AB + +bluetooth:v0072* + ID_VENDOR_FROM_DATABASE=ShangHai Super Smart Electronics Co. Ltd. + +bluetooth:v0073* + ID_VENDOR_FROM_DATABASE=Group Sense Ltd. + +bluetooth:v0074* + ID_VENDOR_FROM_DATABASE=Zomm, LLC + +bluetooth:v0075* + ID_VENDOR_FROM_DATABASE=Samsung Electronics Co. Ltd. + +bluetooth:v0076* + ID_VENDOR_FROM_DATABASE=Creative Technology Ltd. + +bluetooth:v0077* + ID_VENDOR_FROM_DATABASE=Laird Technologies + +bluetooth:v0078* + ID_VENDOR_FROM_DATABASE=Nike, Inc. + +bluetooth:v0078p0001* + ID_PRODUCT_FROM_DATABASE=Nike+ FuelBand + +bluetooth:v0079* + ID_VENDOR_FROM_DATABASE=lesswire AG + +bluetooth:v007A* + ID_VENDOR_FROM_DATABASE=MStar Semiconductor, Inc. + +bluetooth:v007B* + ID_VENDOR_FROM_DATABASE=Hanlynn Technologies + +bluetooth:v007C* + ID_VENDOR_FROM_DATABASE=A & R Cambridge + +bluetooth:v007D* + ID_VENDOR_FROM_DATABASE=Seers Technology Co. Ltd + +bluetooth:v007E* + ID_VENDOR_FROM_DATABASE=Sports Tracking Technologies Ltd. + +bluetooth:v007F* + ID_VENDOR_FROM_DATABASE=Autonet Mobile + +bluetooth:v0080* + ID_VENDOR_FROM_DATABASE=DeLorme Publishing Company, Inc. + +bluetooth:v0081* + ID_VENDOR_FROM_DATABASE=WuXi Vimicro + +bluetooth:v0082* + ID_VENDOR_FROM_DATABASE=Sennheiser Communications A/S + +bluetooth:v0083* + ID_VENDOR_FROM_DATABASE=TimeKeeping Systems, Inc. + +bluetooth:v0084* + ID_VENDOR_FROM_DATABASE=Ludus Helsinki Ltd. + +bluetooth:v0085* + ID_VENDOR_FROM_DATABASE=BlueRadios, Inc. + +bluetooth:v0086* + ID_VENDOR_FROM_DATABASE=equinox AG + +bluetooth:v0087* + ID_VENDOR_FROM_DATABASE=Garmin International, Inc. + +bluetooth:v0088* + ID_VENDOR_FROM_DATABASE=Ecotest + +bluetooth:v0089* + ID_VENDOR_FROM_DATABASE=GN ReSound A/S + +bluetooth:v008A* + ID_VENDOR_FROM_DATABASE=Jawbone + +bluetooth:v008B* + ID_VENDOR_FROM_DATABASE=Topcon Positioning Systems, LLC + +bluetooth:v008C* + ID_VENDOR_FROM_DATABASE=Gimbal Inc. (formerly Qualcomm Labs, Inc. and Qualcomm Retail Solutions, Inc.) + +bluetooth:v008D* + ID_VENDOR_FROM_DATABASE=Zscan Software + +bluetooth:v008E* + ID_VENDOR_FROM_DATABASE=Quintic Corp. + +bluetooth:v008F* + ID_VENDOR_FROM_DATABASE=Telit Wireless Solutions GmbH (Formerly Stollman E+V GmbH) + +bluetooth:v0090* + ID_VENDOR_FROM_DATABASE=Funai Electric Co., Ltd. + +bluetooth:v0091* + ID_VENDOR_FROM_DATABASE=Advanced PANMOBIL Systems GmbH & Co. KG + +bluetooth:v0092* + ID_VENDOR_FROM_DATABASE=ThinkOptics, Inc. + +bluetooth:v0093* + ID_VENDOR_FROM_DATABASE=Universal Electronics, Inc. + +bluetooth:v0094* + ID_VENDOR_FROM_DATABASE=Airoha Technology Corp. + +bluetooth:v0095* + ID_VENDOR_FROM_DATABASE=NEC Lighting, Ltd. + +bluetooth:v0096* + ID_VENDOR_FROM_DATABASE=ODM Technology, Inc. + +bluetooth:v0097* + ID_VENDOR_FROM_DATABASE=ConnecteDevice Ltd. + +bluetooth:v0098* + ID_VENDOR_FROM_DATABASE=zer01.tv GmbH + +bluetooth:v0099* + ID_VENDOR_FROM_DATABASE=i.Tech Dynamic Global Distribution Ltd. + +bluetooth:v009A* + ID_VENDOR_FROM_DATABASE=Alpwise + +bluetooth:v009B* + ID_VENDOR_FROM_DATABASE=Jiangsu Toppower Automotive Electronics Co., Ltd. + +bluetooth:v009C* + ID_VENDOR_FROM_DATABASE=Colorfy, Inc. + +bluetooth:v009D* + ID_VENDOR_FROM_DATABASE=Geoforce Inc. + +bluetooth:v009E* + ID_VENDOR_FROM_DATABASE=Bose Corporation + +bluetooth:v009F* + ID_VENDOR_FROM_DATABASE=Suunto Oy + +bluetooth:v00A0* + ID_VENDOR_FROM_DATABASE=Kensington Computer Products Group + +bluetooth:v00A1* + ID_VENDOR_FROM_DATABASE=SR-Medizinelektronik + +bluetooth:v00A2* + ID_VENDOR_FROM_DATABASE=Vertu Corporation Limited + +bluetooth:v00A3* + ID_VENDOR_FROM_DATABASE=Meta Watch Ltd. + +bluetooth:v00A4* + ID_VENDOR_FROM_DATABASE=LINAK A/S + +bluetooth:v00A5* + ID_VENDOR_FROM_DATABASE=OTL Dynamics LLC + +bluetooth:v00A6* + ID_VENDOR_FROM_DATABASE=Panda Ocean Inc. + +bluetooth:v00A7* + ID_VENDOR_FROM_DATABASE=Visteon Corporation + +bluetooth:v00A8* + ID_VENDOR_FROM_DATABASE=ARP Devices Limited + +bluetooth:v00A9* + ID_VENDOR_FROM_DATABASE=Magneti Marelli S.p.A + +bluetooth:v00AA* + ID_VENDOR_FROM_DATABASE=CAEN RFID srl + +bluetooth:v00AB* + ID_VENDOR_FROM_DATABASE=Ingenieur-Systemgruppe Zahn GmbH + +bluetooth:v00AC* + ID_VENDOR_FROM_DATABASE=Green Throttle Games + +bluetooth:v00AD* + ID_VENDOR_FROM_DATABASE=Peter Systemtechnik GmbH + +bluetooth:v00AE* + ID_VENDOR_FROM_DATABASE=Omegawave Oy + +bluetooth:v00AF* + ID_VENDOR_FROM_DATABASE=Cinetix + +bluetooth:v00B0* + ID_VENDOR_FROM_DATABASE=Passif Semiconductor Corp + +bluetooth:v00B1* + ID_VENDOR_FROM_DATABASE=Saris Cycling Group, Inc + +bluetooth:v00B2* + ID_VENDOR_FROM_DATABASE=Bekey A/S + +bluetooth:v00B3* + ID_VENDOR_FROM_DATABASE=Clarinox Technologies Pty. Ltd. + +bluetooth:v00B4* + ID_VENDOR_FROM_DATABASE=BDE Technology Co., Ltd. + +bluetooth:v00B5* + ID_VENDOR_FROM_DATABASE=Swirl Networks + +bluetooth:v00B6* + ID_VENDOR_FROM_DATABASE=Meso international + +bluetooth:v00B7* + ID_VENDOR_FROM_DATABASE=TreLab Ltd + +bluetooth:v00B8* + ID_VENDOR_FROM_DATABASE=Qualcomm Innovation Center, Inc. (QuIC) + +bluetooth:v00B9* + ID_VENDOR_FROM_DATABASE=Johnson Controls, Inc. + +bluetooth:v00BA* + ID_VENDOR_FROM_DATABASE=Starkey Laboratories Inc. + +bluetooth:v00BB* + ID_VENDOR_FROM_DATABASE=S-Power Electronics Limited + +bluetooth:v00BC* + ID_VENDOR_FROM_DATABASE=Ace Sensor Inc + +bluetooth:v00BD* + ID_VENDOR_FROM_DATABASE=Aplix Corporation + +bluetooth:v00BE* + ID_VENDOR_FROM_DATABASE=AAMP of America + +bluetooth:v00BF* + ID_VENDOR_FROM_DATABASE=Stalmart Technology Limited + +bluetooth:v00C0* + ID_VENDOR_FROM_DATABASE=AMICCOM Electronics Corporation + +bluetooth:v00C1* + ID_VENDOR_FROM_DATABASE=Shenzhen Excelsecu Data Technology Co.,Ltd + +bluetooth:v00C2* + ID_VENDOR_FROM_DATABASE=Geneq Inc. + +bluetooth:v00C3* + ID_VENDOR_FROM_DATABASE=adidas AG + +bluetooth:v00C4* + ID_VENDOR_FROM_DATABASE=LG Electronics + +bluetooth:v00C5* + ID_VENDOR_FROM_DATABASE=Onset Computer Corporation + +bluetooth:v00C6* + ID_VENDOR_FROM_DATABASE=Selfly BV + +bluetooth:v00C7* + ID_VENDOR_FROM_DATABASE=Quuppa Oy. + +bluetooth:v00C8* + ID_VENDOR_FROM_DATABASE=GeLo Inc + +bluetooth:v00C9* + ID_VENDOR_FROM_DATABASE=Evluma + +bluetooth:v00CA* + ID_VENDOR_FROM_DATABASE=MC10 + +bluetooth:v00CB* + ID_VENDOR_FROM_DATABASE=Binauric SE + +bluetooth:v00CC* + ID_VENDOR_FROM_DATABASE=Beats Electronics + +bluetooth:v00CD* + ID_VENDOR_FROM_DATABASE=Microchip Technology Inc. + +bluetooth:v00CE* + ID_VENDOR_FROM_DATABASE=Elgato Systems GmbH + +bluetooth:v00CF* + ID_VENDOR_FROM_DATABASE=ARCHOS SA + +bluetooth:v00D0* + ID_VENDOR_FROM_DATABASE=Dexcom, Inc. + +bluetooth:v00D1* + ID_VENDOR_FROM_DATABASE=Polar Electro Europe B.V. + +bluetooth:v00D2* + ID_VENDOR_FROM_DATABASE=Dialog Semiconductor B.V. + +bluetooth:v00D3* + ID_VENDOR_FROM_DATABASE=Taixingbang Technology (HK) Co,. LTD. + +bluetooth:v00D4* + ID_VENDOR_FROM_DATABASE=Kawantech + +bluetooth:v00D5* + ID_VENDOR_FROM_DATABASE=Austco Communication Systems + +bluetooth:v00D6* + ID_VENDOR_FROM_DATABASE=Timex Group USA, Inc. + +bluetooth:v00D7* + ID_VENDOR_FROM_DATABASE=Qualcomm Technologies, Inc. + +bluetooth:v00D8* + ID_VENDOR_FROM_DATABASE=Qualcomm Connected Experiences, Inc. + +bluetooth:v00D9* + ID_VENDOR_FROM_DATABASE=Voyetra Turtle Beach + +bluetooth:v00DA* + ID_VENDOR_FROM_DATABASE=txtr GmbH + +bluetooth:v00DB* + ID_VENDOR_FROM_DATABASE=Biosentronics + +bluetooth:v00DC* + ID_VENDOR_FROM_DATABASE=Procter & Gamble + +bluetooth:v00DD* + ID_VENDOR_FROM_DATABASE=Hosiden Corporation + +bluetooth:v00DE* + ID_VENDOR_FROM_DATABASE=Muzik LLC + +bluetooth:v00DF* + ID_VENDOR_FROM_DATABASE=Misfit Wearables Corp + +bluetooth:v00E0* + ID_VENDOR_FROM_DATABASE=Google + +bluetooth:v00E1* + ID_VENDOR_FROM_DATABASE=Danlers Ltd + +bluetooth:v00E2* + ID_VENDOR_FROM_DATABASE=Semilink Inc + +bluetooth:v00E3* + ID_VENDOR_FROM_DATABASE=inMusic Brands, Inc + +bluetooth:v00E4* + ID_VENDOR_FROM_DATABASE=L.S. Research Inc. + +bluetooth:v00E5* + ID_VENDOR_FROM_DATABASE=Eden Software Consultants Ltd. + +bluetooth:v00E6* + ID_VENDOR_FROM_DATABASE=Freshtemp + +bluetooth:v00E7* + ID_VENDOR_FROM_DATABASE=KS Technologies + +bluetooth:v00E8* + ID_VENDOR_FROM_DATABASE=ACTS Technologies + +bluetooth:v00E9* + ID_VENDOR_FROM_DATABASE=Vtrack Systems + +bluetooth:v00EA* + ID_VENDOR_FROM_DATABASE=Nielsen-Kellerman Company + +bluetooth:v00EB* + ID_VENDOR_FROM_DATABASE=Server Technology, Inc. + +bluetooth:v00EC* + ID_VENDOR_FROM_DATABASE=BioResearch Associates + +bluetooth:v00ED* + ID_VENDOR_FROM_DATABASE=Jolly Logic, LLC + +bluetooth:v00EE* + ID_VENDOR_FROM_DATABASE=Above Average Outcomes, Inc. + +bluetooth:v00EF* + ID_VENDOR_FROM_DATABASE=Bitsplitters GmbH + +bluetooth:v00F0* + ID_VENDOR_FROM_DATABASE=PayPal, Inc. + +bluetooth:v00F1* + ID_VENDOR_FROM_DATABASE=Witron Technology Limited + +bluetooth:v00F2* + ID_VENDOR_FROM_DATABASE=Aether Things Inc. (formerly Morse Project Inc.) + +bluetooth:v00F3* + ID_VENDOR_FROM_DATABASE=Kent Displays Inc. + +bluetooth:v00F4* + ID_VENDOR_FROM_DATABASE=Nautilus Inc. + +bluetooth:v00F5* + ID_VENDOR_FROM_DATABASE=Smartifier Oy + +bluetooth:v00F6* + ID_VENDOR_FROM_DATABASE=Elcometer Limited + +bluetooth:v00F7* + ID_VENDOR_FROM_DATABASE=VSN Technologies Inc. + +bluetooth:v00F8* + ID_VENDOR_FROM_DATABASE=AceUni Corp., Ltd. + +bluetooth:v00F9* + ID_VENDOR_FROM_DATABASE=StickNFind + +bluetooth:v00FA* + ID_VENDOR_FROM_DATABASE=Crystal Code AB + +bluetooth:v00FB* + ID_VENDOR_FROM_DATABASE=KOUKAAM a.s. + +bluetooth:v00FC* + ID_VENDOR_FROM_DATABASE=Delphi Corporation + +bluetooth:v00FD* + ID_VENDOR_FROM_DATABASE=ValenceTech Limited + +bluetooth:v00FE* + ID_VENDOR_FROM_DATABASE=Reserved + +bluetooth:v00FF* + ID_VENDOR_FROM_DATABASE=Typo Products, LLC + +bluetooth:v0100* + ID_VENDOR_FROM_DATABASE=TomTom International BV + +bluetooth:v0101* + ID_VENDOR_FROM_DATABASE=Fugoo, Inc + +bluetooth:v0102* + ID_VENDOR_FROM_DATABASE=Keiser Corporation + +bluetooth:v0103* + ID_VENDOR_FROM_DATABASE=Bang & Olufsen A/S + +bluetooth:v0104* + ID_VENDOR_FROM_DATABASE=PLUS Locations Systems Pty Ltd + +bluetooth:v0105* + ID_VENDOR_FROM_DATABASE=Ubiquitous Computing Technology Corporation + +bluetooth:v0106* + ID_VENDOR_FROM_DATABASE=Innovative Yachtter Solutions + +bluetooth:v0107* + ID_VENDOR_FROM_DATABASE=William Demant Holding A/S + +bluetooth:v0108* + ID_VENDOR_FROM_DATABASE=Chicony Electronics Co., Ltd. + +bluetooth:v0109* + ID_VENDOR_FROM_DATABASE=Atus BV + +bluetooth:v010A* + ID_VENDOR_FROM_DATABASE=Codegate Ltd. + +bluetooth:v010B* + ID_VENDOR_FROM_DATABASE=ERi, Inc. + +bluetooth:v010C* + ID_VENDOR_FROM_DATABASE=Transducers Direct, LLC + +bluetooth:v010D* + ID_VENDOR_FROM_DATABASE=Fujitsu Ten Limited + +bluetooth:v010E* + ID_VENDOR_FROM_DATABASE=Audi AG + +bluetooth:v010F* + ID_VENDOR_FROM_DATABASE=HiSilicon Technologies Co., Ltd. + +bluetooth:v0110* + ID_VENDOR_FROM_DATABASE=Nippon Seiki Co., Ltd. + +bluetooth:v0111* + ID_VENDOR_FROM_DATABASE=Steelseries ApS + +bluetooth:v0112* + ID_VENDOR_FROM_DATABASE=Visybl Inc. + +bluetooth:v0113* + ID_VENDOR_FROM_DATABASE=Openbrain Technologies, Co., Ltd. + +bluetooth:v0114* + ID_VENDOR_FROM_DATABASE=Xensr + +bluetooth:v0115* + ID_VENDOR_FROM_DATABASE=e.solutions + +bluetooth:v0116* + ID_VENDOR_FROM_DATABASE=1OAK Technologies + +bluetooth:v0117* + ID_VENDOR_FROM_DATABASE=Wimoto Technologies Inc + +bluetooth:v0118* + ID_VENDOR_FROM_DATABASE=Radius Networks, Inc. + +bluetooth:v0119* + ID_VENDOR_FROM_DATABASE=Wize Technology Co., Ltd. + +bluetooth:v011A* + ID_VENDOR_FROM_DATABASE=Qualcomm Labs, Inc. + +bluetooth:v011B* + ID_VENDOR_FROM_DATABASE=Aruba Networks + +bluetooth:v011C* + ID_VENDOR_FROM_DATABASE=Baidu + +bluetooth:v011D* + ID_VENDOR_FROM_DATABASE=Arendi AG + +bluetooth:v011E* + ID_VENDOR_FROM_DATABASE=Skoda Auto a.s. + +bluetooth:v011F* + ID_VENDOR_FROM_DATABASE=Volkswagen AG + +bluetooth:v0120* + ID_VENDOR_FROM_DATABASE=Porsche AG + +bluetooth:v0121* + ID_VENDOR_FROM_DATABASE=Sino Wealth Electronic Ltd. + +bluetooth:v0122* + ID_VENDOR_FROM_DATABASE=AirTurn, Inc. + +bluetooth:v0123* + ID_VENDOR_FROM_DATABASE=Kinsa, Inc. + +bluetooth:v0124* + ID_VENDOR_FROM_DATABASE=HID Global + +bluetooth:v0125* + ID_VENDOR_FROM_DATABASE=SEAT es + +bluetooth:v0126* + ID_VENDOR_FROM_DATABASE=Promethean Ltd. + +bluetooth:v0127* + ID_VENDOR_FROM_DATABASE=Salutica Allied Solutions + +bluetooth:v0128* + ID_VENDOR_FROM_DATABASE=GPSI Group Pty Ltd + +bluetooth:v0129* + ID_VENDOR_FROM_DATABASE=Nimble Devices Oy + +bluetooth:v012A* + ID_VENDOR_FROM_DATABASE=Changzhou Yongse Infotech Co., Ltd + +bluetooth:v012B* + ID_VENDOR_FROM_DATABASE=SportIQ + +bluetooth:v012C* + ID_VENDOR_FROM_DATABASE=TEMEC Instruments B.V. + +bluetooth:v012D* + ID_VENDOR_FROM_DATABASE=Sony Corporation + +bluetooth:v012E* + ID_VENDOR_FROM_DATABASE=ASSA ABLOY + +bluetooth:v012F* + ID_VENDOR_FROM_DATABASE=Clarion Co., Ltd. + +bluetooth:v0130* + ID_VENDOR_FROM_DATABASE=Warehouse Innovations + +bluetooth:v0131* + ID_VENDOR_FROM_DATABASE=Cypress Semiconductor Corporation + +bluetooth:v0132* + ID_VENDOR_FROM_DATABASE=MADS Inc + +bluetooth:v0133* + ID_VENDOR_FROM_DATABASE=Blue Maestro Limited + +bluetooth:v0134* + ID_VENDOR_FROM_DATABASE=Resolution Products, Inc. + +bluetooth:v0135* + ID_VENDOR_FROM_DATABASE=Airewear LLC + +bluetooth:v0136* + ID_VENDOR_FROM_DATABASE=Seed Labs, Inc. (formerly ETC sp. z.o.o.) + +bluetooth:v0137* + ID_VENDOR_FROM_DATABASE=Prestigio Plaza Ltd. + +bluetooth:v0138* + ID_VENDOR_FROM_DATABASE=NTEO Inc. + +bluetooth:v0139* + ID_VENDOR_FROM_DATABASE=Focus Systems Corporation + +bluetooth:v013A* + ID_VENDOR_FROM_DATABASE=Tencent Holdings Limited + +bluetooth:v013B* + ID_VENDOR_FROM_DATABASE=Allegion + +bluetooth:v013C* + ID_VENDOR_FROM_DATABASE=Murata Manufacuring Co., Ltd. + +bluetooth:v013D* + ID_VENDOR_FROM_DATABASE=WirelessWERX + +bluetooth:v013E* + ID_VENDOR_FROM_DATABASE=Nod, Inc. + +bluetooth:v013F* + ID_VENDOR_FROM_DATABASE=B&B Manufacturing Company + +bluetooth:v0140* + ID_VENDOR_FROM_DATABASE=Alpine Electronics (China) Co., Ltd + +bluetooth:v0141* + ID_VENDOR_FROM_DATABASE=FedEx Services + +bluetooth:v0142* + ID_VENDOR_FROM_DATABASE=Grape Systems Inc. + +bluetooth:v0143* + ID_VENDOR_FROM_DATABASE=Bkon Connect + +bluetooth:v0144* + ID_VENDOR_FROM_DATABASE=Lintech GmbH + +bluetooth:v0145* + ID_VENDOR_FROM_DATABASE=Novatel Wireless + +bluetooth:v0146* + ID_VENDOR_FROM_DATABASE=Ciright + +bluetooth:v0147* + ID_VENDOR_FROM_DATABASE=Mighty Cast, Inc. + +bluetooth:v0148* + ID_VENDOR_FROM_DATABASE=Ambimat Electronics + +bluetooth:v0149* + ID_VENDOR_FROM_DATABASE=Perytons Ltd. + +bluetooth:v014A* + ID_VENDOR_FROM_DATABASE=Tivoli Audio, LLC + +bluetooth:v014B* + ID_VENDOR_FROM_DATABASE=Master Lock + +bluetooth:v014C* + ID_VENDOR_FROM_DATABASE=Mesh-Net Ltd + +bluetooth:v014D* + ID_VENDOR_FROM_DATABASE=Huizhou Desay SV Automotive CO., LTD. + +bluetooth:v014E* + ID_VENDOR_FROM_DATABASE=Tangerine, Inc. + +bluetooth:v014F* + ID_VENDOR_FROM_DATABASE=B&W Group Ltd. + +bluetooth:v0150* + ID_VENDOR_FROM_DATABASE=Pioneer Corporation + +bluetooth:v0151* + ID_VENDOR_FROM_DATABASE=OnBeep + +bluetooth:v0152* + ID_VENDOR_FROM_DATABASE=Vernier Software & Technology + +bluetooth:v0153* + ID_VENDOR_FROM_DATABASE=ROL Ergo + +bluetooth:v0154* + ID_VENDOR_FROM_DATABASE=Pebble Technology + +bluetooth:v0155* + ID_VENDOR_FROM_DATABASE=NETATMO + +bluetooth:v0156* + ID_VENDOR_FROM_DATABASE=Accumulate AB + +bluetooth:v0157* + ID_VENDOR_FROM_DATABASE=Anhui Huami Information Technology Co., Ltd. + +bluetooth:v0158* + ID_VENDOR_FROM_DATABASE=Inmite s.r.o. + +bluetooth:v0159* + ID_VENDOR_FROM_DATABASE=ChefSteps, Inc. + +bluetooth:v015A* + ID_VENDOR_FROM_DATABASE=micas AG + +bluetooth:v015B* + ID_VENDOR_FROM_DATABASE=Biomedical Research Ltd. + +bluetooth:v015C* + ID_VENDOR_FROM_DATABASE=Pitius Tec S.L. + +bluetooth:v015D* + ID_VENDOR_FROM_DATABASE=Estimote, Inc. + +bluetooth:v015E* + ID_VENDOR_FROM_DATABASE=Unikey Technologies, Inc. + +bluetooth:v015F* + ID_VENDOR_FROM_DATABASE=Timer Cap Co. + +bluetooth:v0160* + ID_VENDOR_FROM_DATABASE=AwoX + +bluetooth:v0161* + ID_VENDOR_FROM_DATABASE=yikes + +bluetooth:v0162* + ID_VENDOR_FROM_DATABASE=MADSGlobal NZ Ltd. + +bluetooth:v0163* + ID_VENDOR_FROM_DATABASE=PCH International + +bluetooth:v0164* + ID_VENDOR_FROM_DATABASE=Qingdao Yeelink Information Technology Co., Ltd. + +bluetooth:v0165* + ID_VENDOR_FROM_DATABASE=Milwaukee Tool (formerly Milwaukee Electric Tools) + +bluetooth:v0166* + ID_VENDOR_FROM_DATABASE=MISHIK Pte Ltd + +bluetooth:v0167* + ID_VENDOR_FROM_DATABASE=Bayer HealthCare + +bluetooth:v0168* + ID_VENDOR_FROM_DATABASE=Spicebox LLC + +bluetooth:v0169* + ID_VENDOR_FROM_DATABASE=emberlight + +bluetooth:v016A* + ID_VENDOR_FROM_DATABASE=Cooper-Atkins Corporation + +bluetooth:v016B* + ID_VENDOR_FROM_DATABASE=Qblinks + +bluetooth:v016C* + ID_VENDOR_FROM_DATABASE=MYSPHERA + +bluetooth:v016D* + ID_VENDOR_FROM_DATABASE=LifeScan Inc + +bluetooth:v016E* + ID_VENDOR_FROM_DATABASE=Volantic AB + +bluetooth:v016F* + ID_VENDOR_FROM_DATABASE=Podo Labs, Inc + +bluetooth:v0170* + ID_VENDOR_FROM_DATABASE=F. Hoffmann-La Roche AG + +bluetooth:v0171* + ID_VENDOR_FROM_DATABASE=Amazon Fulfillment Service + +bluetooth:v0172* + ID_VENDOR_FROM_DATABASE=Connovate Technology Private Limited + +bluetooth:v0173* + ID_VENDOR_FROM_DATABASE=Kocomojo, LLC + +bluetooth:v0174* + ID_VENDOR_FROM_DATABASE=Everykey LLC + +bluetooth:v0175* + ID_VENDOR_FROM_DATABASE=Dynamic Controls + +bluetooth:v0176* + ID_VENDOR_FROM_DATABASE=SentriLock + +bluetooth:v0177* + ID_VENDOR_FROM_DATABASE=I-SYST inc. + +bluetooth:v0178* + ID_VENDOR_FROM_DATABASE=CASIO COMPUTER CO., LTD. + +bluetooth:v0179* + ID_VENDOR_FROM_DATABASE=LAPIS Semiconductor Co., Ltd. + +bluetooth:v017A* + ID_VENDOR_FROM_DATABASE=Telemonitor, Inc. + +bluetooth:v017B* + ID_VENDOR_FROM_DATABASE=taskit GmbH + +bluetooth:v017C* + ID_VENDOR_FROM_DATABASE=Daimler AG + +bluetooth:v017D* + ID_VENDOR_FROM_DATABASE=BatAndCat + +bluetooth:v017E* + ID_VENDOR_FROM_DATABASE=BluDotz Ltd + +bluetooth:v017F* + ID_VENDOR_FROM_DATABASE=XTel ApS + +bluetooth:v0180* + ID_VENDOR_FROM_DATABASE=Gigaset Communications GmbH + +bluetooth:v0181* + ID_VENDOR_FROM_DATABASE=Gecko Health Innovations, Inc. + +bluetooth:v0182* + ID_VENDOR_FROM_DATABASE=HOP Ubiquitous + +bluetooth:v0183* + ID_VENDOR_FROM_DATABASE=To Be Assigned + +bluetooth:v0184* + ID_VENDOR_FROM_DATABASE=Nectar + +bluetooth:v0185* + ID_VENDOR_FROM_DATABASE=bel'apps LLC + +bluetooth:v0186* + ID_VENDOR_FROM_DATABASE=CORE Lighting Ltd + +bluetooth:v0187* + ID_VENDOR_FROM_DATABASE=Seraphim Sense Ltd + +bluetooth:v0188* + ID_VENDOR_FROM_DATABASE=Unico RBC + +bluetooth:v0189* + ID_VENDOR_FROM_DATABASE=Physical Enterprises Inc. + +bluetooth:v018A* + ID_VENDOR_FROM_DATABASE=Able Trend Technology Limited + +bluetooth:v018B* + ID_VENDOR_FROM_DATABASE=Konica Minolta, Inc. + +bluetooth:v018C* + ID_VENDOR_FROM_DATABASE=Wilo SE + +bluetooth:v018D* + ID_VENDOR_FROM_DATABASE=Extron Design Services + +bluetooth:v018E* + ID_VENDOR_FROM_DATABASE=Fitbit, Inc. + +bluetooth:v018F* + ID_VENDOR_FROM_DATABASE=Fireflies Systems + +bluetooth:v0190* + ID_VENDOR_FROM_DATABASE=Intelletto Technologies Inc. + +bluetooth:v0191* + ID_VENDOR_FROM_DATABASE=FDK CORPORATION + +bluetooth:v0192* + ID_VENDOR_FROM_DATABASE=Cloudleaf, Inc + +bluetooth:v0193* + ID_VENDOR_FROM_DATABASE=Maveric Automation LLC + +bluetooth:v0194* + ID_VENDOR_FROM_DATABASE=Acoustic Stream Corporation + +bluetooth:v0195* + ID_VENDOR_FROM_DATABASE=Zuli + +bluetooth:v0196* + ID_VENDOR_FROM_DATABASE=Paxton Access Ltd + +bluetooth:v0197* + ID_VENDOR_FROM_DATABASE=WiSilica Inc + +bluetooth:v0198* + ID_VENDOR_FROM_DATABASE=VENGIT Korlátolt Felelősségű Társaság + +bluetooth:v0199* + ID_VENDOR_FROM_DATABASE=SALTO SYSTEMS S.L. + +bluetooth:v019A* + ID_VENDOR_FROM_DATABASE=TRON Forum (formerly T-Engine Forum) + +bluetooth:v019B* + ID_VENDOR_FROM_DATABASE=CUBETECH s.r.o. + +bluetooth:v019C* + ID_VENDOR_FROM_DATABASE=Cokiya Incorporated + +bluetooth:v019D* + ID_VENDOR_FROM_DATABASE=CVS Health + +bluetooth:v019E* + ID_VENDOR_FROM_DATABASE=Ceruus + +bluetooth:v019F* + ID_VENDOR_FROM_DATABASE=Strainstall Ltd + +bluetooth:v01A0* + ID_VENDOR_FROM_DATABASE=Channel Enterprises (HK) Ltd. + +bluetooth:v01A1* + ID_VENDOR_FROM_DATABASE=FIAMM + +bluetooth:v01A2* + ID_VENDOR_FROM_DATABASE=GIGALANE.CO.,LTD + +bluetooth:v01A3* + ID_VENDOR_FROM_DATABASE=EROAD + +bluetooth:v01A4* + ID_VENDOR_FROM_DATABASE=Mine Safety Appliances + +bluetooth:v01A5* + ID_VENDOR_FROM_DATABASE=Icon Health and Fitness + +bluetooth:v01A6* + ID_VENDOR_FROM_DATABASE=Asandoo GmbH + +bluetooth:v01A7* + ID_VENDOR_FROM_DATABASE=ENERGOUS CORPORATION + +bluetooth:v01A8* + ID_VENDOR_FROM_DATABASE=Taobao + +bluetooth:v01A9* + ID_VENDOR_FROM_DATABASE=Canon Inc. + +bluetooth:v01AA* + ID_VENDOR_FROM_DATABASE=Geophysical Technology Inc. + +bluetooth:v01AB* + ID_VENDOR_FROM_DATABASE=Facebook, Inc. + +bluetooth:v01AC* + ID_VENDOR_FROM_DATABASE=Nipro Diagnostics, Inc. + +bluetooth:v01AD* + ID_VENDOR_FROM_DATABASE=FlightSafety International + +bluetooth:v01AE* + ID_VENDOR_FROM_DATABASE=Earlens Corporation + +bluetooth:v01AF* + ID_VENDOR_FROM_DATABASE=Sunrise Micro Devices, Inc. + +bluetooth:v01B0* + ID_VENDOR_FROM_DATABASE=Star Micronics Co., Ltd. + +bluetooth:v01B1* + ID_VENDOR_FROM_DATABASE=Netizens Sp. z o.o. + +bluetooth:v01B2* + ID_VENDOR_FROM_DATABASE=Nymi Inc. + +bluetooth:v01B3* + ID_VENDOR_FROM_DATABASE=Nytec, Inc. + +bluetooth:v01B4* + ID_VENDOR_FROM_DATABASE=Trineo Sp. z o.o. + +bluetooth:v01B5* + ID_VENDOR_FROM_DATABASE=Nest Labs Inc. + +bluetooth:v01B6* + ID_VENDOR_FROM_DATABASE=LM Technologies Ltd + +bluetooth:v01B7* + ID_VENDOR_FROM_DATABASE=General Electric Company + +bluetooth:v01B8* + ID_VENDOR_FROM_DATABASE=i+D3 S.L. + +bluetooth:v01B9* + ID_VENDOR_FROM_DATABASE=HANA Micron + +bluetooth:v01BA* + ID_VENDOR_FROM_DATABASE=Stages Cycling LLC + +bluetooth:v01BB* + ID_VENDOR_FROM_DATABASE=Cochlear Bone Anchored Solutions AB + +bluetooth:v01BC* + ID_VENDOR_FROM_DATABASE=SenionLab AB + +bluetooth:v01BD* + ID_VENDOR_FROM_DATABASE=Syszone Co., Ltd + +bluetooth:v01BE* + ID_VENDOR_FROM_DATABASE=Pulsate Mobile Ltd. + +bluetooth:v01BF* + ID_VENDOR_FROM_DATABASE=Hong Kong HunterSun Electronic Limited + +bluetooth:v01C0* + ID_VENDOR_FROM_DATABASE=pironex GmbH + +bluetooth:v01C1* + ID_VENDOR_FROM_DATABASE=BRADATECH Corp. + +bluetooth:v01C2* + ID_VENDOR_FROM_DATABASE=Transenergooil AG + +bluetooth:v01C3* + ID_VENDOR_FROM_DATABASE=Bunch + +bluetooth:v01C4* + ID_VENDOR_FROM_DATABASE=DME Microelectronics + +bluetooth:v01C5* + ID_VENDOR_FROM_DATABASE=Bitcraze AB + +bluetooth:v01C6* + ID_VENDOR_FROM_DATABASE=HASWARE Inc. + +bluetooth:v01C7* + ID_VENDOR_FROM_DATABASE=Abiogenix Inc. + +bluetooth:v01C8* + ID_VENDOR_FROM_DATABASE=Poly-Control ApS + +bluetooth:v01C9* + ID_VENDOR_FROM_DATABASE=Avi-on + +bluetooth:v01CA* + ID_VENDOR_FROM_DATABASE=Laerdal Medical AS + +bluetooth:v01CB* + ID_VENDOR_FROM_DATABASE=Fetch My Pet + +bluetooth:v01CC* + ID_VENDOR_FROM_DATABASE=Sam Labs Ltd. + +bluetooth:v01CD* + ID_VENDOR_FROM_DATABASE=Chengdu Synwing Technology Ltd + +bluetooth:v01CE* + ID_VENDOR_FROM_DATABASE=HOUWA SYSTEM DESIGN, k.k. + +bluetooth:v01CF* + ID_VENDOR_FROM_DATABASE=BSH + +bluetooth:v01D0* + ID_VENDOR_FROM_DATABASE=Primus Inter Pares Ltd + +bluetooth:v01D1* + ID_VENDOR_FROM_DATABASE=August + +bluetooth:v01D2* + ID_VENDOR_FROM_DATABASE=Gill Electronics + +bluetooth:v01D3* + ID_VENDOR_FROM_DATABASE=Sky Wave Design + +bluetooth:v01D4* + ID_VENDOR_FROM_DATABASE=Newlab S.r.l. + +bluetooth:v01D5* + ID_VENDOR_FROM_DATABASE=ELAD srl + +bluetooth:v01D6* + ID_VENDOR_FROM_DATABASE=G-wearables inc. + +bluetooth:v01D7* + ID_VENDOR_FROM_DATABASE=Squadrone Systems Inc. + +bluetooth:v01D8* + ID_VENDOR_FROM_DATABASE=Code Corporation + +bluetooth:v01D9* + ID_VENDOR_FROM_DATABASE=Savant Systems LLC + +bluetooth:v01DA* + ID_VENDOR_FROM_DATABASE=Logitech International SA + +bluetooth:v01DB* + ID_VENDOR_FROM_DATABASE=Innblue Consulting + +bluetooth:v01DC* + ID_VENDOR_FROM_DATABASE=iParking Ltd. + +bluetooth:v01DD* + ID_VENDOR_FROM_DATABASE=Koninklijke Philips Electronics N.V. + +bluetooth:v01DE* + ID_VENDOR_FROM_DATABASE=Minelab Electronics Pty Limited + +bluetooth:v01DF* + ID_VENDOR_FROM_DATABASE=Bison Group Ltd. + +bluetooth:v01E0* + ID_VENDOR_FROM_DATABASE=Widex A/S + +bluetooth:v01E1* + ID_VENDOR_FROM_DATABASE=Jolla Ltd + +bluetooth:v01E2* + ID_VENDOR_FROM_DATABASE=Lectronix, Inc. + +bluetooth:v01E3* + ID_VENDOR_FROM_DATABASE=Caterpillar Inc + +bluetooth:v01E4* + ID_VENDOR_FROM_DATABASE=Freedom Innovations + +bluetooth:v01E5* + ID_VENDOR_FROM_DATABASE=Dynamic Devices Ltd + +bluetooth:v01E6* + ID_VENDOR_FROM_DATABASE=Technology Solutions (UK) Ltd + +bluetooth:v01E7* + ID_VENDOR_FROM_DATABASE=IPS Group Inc. + +bluetooth:v01E8* + ID_VENDOR_FROM_DATABASE=STIR + +bluetooth:v01E9* + ID_VENDOR_FROM_DATABASE=Sano, Inc + +bluetooth:v01EA* + ID_VENDOR_FROM_DATABASE=Advanced Application Design, Inc. + +bluetooth:v01EB* + ID_VENDOR_FROM_DATABASE=AutoMap LLC + +bluetooth:v01EC* + ID_VENDOR_FROM_DATABASE=Spreadtrum Communications Shanghai Ltd + +bluetooth:v01ED* + ID_VENDOR_FROM_DATABASE=CuteCircuit LTD + +bluetooth:v01EE* + ID_VENDOR_FROM_DATABASE=Valeo Service + +bluetooth:v01EF* + ID_VENDOR_FROM_DATABASE=Fullpower Technologies, Inc. + +bluetooth:v01F0* + ID_VENDOR_FROM_DATABASE=KloudNation + +bluetooth:v01F1* + ID_VENDOR_FROM_DATABASE=Zebra Technologies Corporation + +bluetooth:v01F2* + ID_VENDOR_FROM_DATABASE=Itron, Inc. + +bluetooth:v01F3* + ID_VENDOR_FROM_DATABASE=The University of Tokyo + +bluetooth:v01F4* + ID_VENDOR_FROM_DATABASE=UTC Fire and Security + +bluetooth:v01F5* + ID_VENDOR_FROM_DATABASE=Cool Webthings Limited + +bluetooth:v01F6* + ID_VENDOR_FROM_DATABASE=DJO Global + +bluetooth:v01F7* + ID_VENDOR_FROM_DATABASE=Gelliner Limited + +bluetooth:v01F8* + ID_VENDOR_FROM_DATABASE=Anyka (Guangzhou) Microelectronics Technology Co, LTD + +bluetooth:v01F9* + ID_VENDOR_FROM_DATABASE=Medtronic, Inc. + +bluetooth:v01FA* + ID_VENDOR_FROM_DATABASE=Gozio, Inc. + +bluetooth:v01FB* + ID_VENDOR_FROM_DATABASE=Form Lifting, LLC + +bluetooth:v01FC* + ID_VENDOR_FROM_DATABASE=Wahoo Fitness, LLC + +bluetooth:v01FD* + ID_VENDOR_FROM_DATABASE=Kontakt Micro-Location Sp. z o.o. + +bluetooth:v01FE* + ID_VENDOR_FROM_DATABASE=Radio System Corporation + +bluetooth:v01FF* + ID_VENDOR_FROM_DATABASE=Freescale Semiconductor, Inc. + +bluetooth:v0200* + ID_VENDOR_FROM_DATABASE=Verifone Systems PTe Ltd. Taiwan Branch + +bluetooth:v0201* + ID_VENDOR_FROM_DATABASE=AR Timing + +bluetooth:v0202* + ID_VENDOR_FROM_DATABASE=Rigado LLC + +bluetooth:v0203* + ID_VENDOR_FROM_DATABASE=Kemppi Oy + +bluetooth:v0204* + ID_VENDOR_FROM_DATABASE=Tapcentive Inc. + +bluetooth:v0205* + ID_VENDOR_FROM_DATABASE=Smartbotics Inc. + +bluetooth:v0206* + ID_VENDOR_FROM_DATABASE=Otter Products, LLC + +bluetooth:v0207* + ID_VENDOR_FROM_DATABASE=STEMP Inc. + +bluetooth:v0208* + ID_VENDOR_FROM_DATABASE=LumiGeek LLC + +bluetooth:v0209* + ID_VENDOR_FROM_DATABASE=InvisionHeart Inc. + +bluetooth:v020A* + ID_VENDOR_FROM_DATABASE=Macnica Inc. + +bluetooth:v020B* + ID_VENDOR_FROM_DATABASE=Jaguar Land Rover Limited + +bluetooth:v020C* + ID_VENDOR_FROM_DATABASE=CoroWare Technologies, Inc + +bluetooth:v020D* + ID_VENDOR_FROM_DATABASE=Simplo Technology Co., LTD + +bluetooth:v020E* + ID_VENDOR_FROM_DATABASE=Omron Healthcare Co., LTD + +bluetooth:v020F* + ID_VENDOR_FROM_DATABASE=Comodule GMBH + +bluetooth:v0210* + ID_VENDOR_FROM_DATABASE=ikeGPS + +bluetooth:v0211* + ID_VENDOR_FROM_DATABASE=Telink Semiconductor Co. Ltd + +bluetooth:v0212* + ID_VENDOR_FROM_DATABASE=Interplan Co., Ltd + +bluetooth:v0213* + ID_VENDOR_FROM_DATABASE=Wyler AG + +bluetooth:v0214* + ID_VENDOR_FROM_DATABASE=IK Multimedia Production srl + +bluetooth:v0215* + ID_VENDOR_FROM_DATABASE=Lukoton Experience Oy + +bluetooth:v0216* + ID_VENDOR_FROM_DATABASE=MTI Ltd + +bluetooth:v0217* + ID_VENDOR_FROM_DATABASE=Tech4home, Lda + +bluetooth:v0218* + ID_VENDOR_FROM_DATABASE=Hiotech AB + +bluetooth:v0219* + ID_VENDOR_FROM_DATABASE=DOTT Limited + +bluetooth:v021A* + ID_VENDOR_FROM_DATABASE=Blue Speck Labs, LLC + +bluetooth:v021B* + ID_VENDOR_FROM_DATABASE=Cisco Systems Inc + +bluetooth:v021C* + ID_VENDOR_FROM_DATABASE=Mobicomm Inc + +bluetooth:v021D* + ID_VENDOR_FROM_DATABASE=Edamic + +bluetooth:v021E* + ID_VENDOR_FROM_DATABASE=Goodnet Ltd + +bluetooth:v021F* + ID_VENDOR_FROM_DATABASE=Luster Leaf Products Inc + +bluetooth:v0220* + ID_VENDOR_FROM_DATABASE=Manus Machina BV + +bluetooth:v0221* + ID_VENDOR_FROM_DATABASE=Mobiquity Networks Inc + +bluetooth:v0222* + ID_VENDOR_FROM_DATABASE=Praxis Dynamics + +bluetooth:v0223* + ID_VENDOR_FROM_DATABASE=Philip Morris Products S.A. + +bluetooth:v0224* + ID_VENDOR_FROM_DATABASE=Comarch SA + +bluetooth:v0225* + ID_VENDOR_FROM_DATABASE=Nestlé Nespresso S.A. + +bluetooth:v0226* + ID_VENDOR_FROM_DATABASE=Merlinia A/S + +bluetooth:v0227* + ID_VENDOR_FROM_DATABASE=LifeBEAM Technologies + +bluetooth:v0228* + ID_VENDOR_FROM_DATABASE=Twocanoes Labs, LLC + +bluetooth:v0229* + ID_VENDOR_FROM_DATABASE=Muoverti Limited + +bluetooth:v022A* + ID_VENDOR_FROM_DATABASE=Stamer Musikanlagen GMBH + +bluetooth:v022B* + ID_VENDOR_FROM_DATABASE=Tesla Motors + +bluetooth:v022C* + ID_VENDOR_FROM_DATABASE=Pharynks Corporation + +bluetooth:v022D* + ID_VENDOR_FROM_DATABASE=Lupine + +bluetooth:v022E* + ID_VENDOR_FROM_DATABASE=Siemens AG + +bluetooth:v022F* + ID_VENDOR_FROM_DATABASE=Huami (Shanghai) Culture Communication CO., LTD + +bluetooth:v0230* + ID_VENDOR_FROM_DATABASE=Foster Electric Company, Ltd + +bluetooth:v0231* + ID_VENDOR_FROM_DATABASE=ETA SA + +bluetooth:v0232* + ID_VENDOR_FROM_DATABASE=x-Senso Solutions Kft + +bluetooth:v0233* + ID_VENDOR_FROM_DATABASE=Shenzhen SuLong Communication Ltd + +bluetooth:v0234* + ID_VENDOR_FROM_DATABASE=FengFan (BeiJing) Technology Co, Ltd + +bluetooth:v0235* + ID_VENDOR_FROM_DATABASE=Qrio Inc + +bluetooth:v0236* + ID_VENDOR_FROM_DATABASE=Pitpatpet Ltd + +bluetooth:v0237* + ID_VENDOR_FROM_DATABASE=MSHeli s.r.l. + +bluetooth:v0238* + ID_VENDOR_FROM_DATABASE=Trakm8 Ltd + +bluetooth:v0239* + ID_VENDOR_FROM_DATABASE=JIN CO, Ltd + +bluetooth:v023A* + ID_VENDOR_FROM_DATABASE=Alatech Technology + +bluetooth:v023B* + ID_VENDOR_FROM_DATABASE=Beijing CarePulse Electronic Technology Co, Ltd + +bluetooth:v023C* + ID_VENDOR_FROM_DATABASE=Awarepoint + +bluetooth:v023D* + ID_VENDOR_FROM_DATABASE=ViCentra B.V. + +bluetooth:v023E* + ID_VENDOR_FROM_DATABASE=Raven Industries + +bluetooth:v023F* + ID_VENDOR_FROM_DATABASE=WaveWare Technologies + +bluetooth:v0240* + ID_VENDOR_FROM_DATABASE=Argenox Technologies + +bluetooth:v0241* + ID_VENDOR_FROM_DATABASE=Bragi GmbH + +bluetooth:v0242* + ID_VENDOR_FROM_DATABASE=16Lab Inc + +bluetooth:v0243* + ID_VENDOR_FROM_DATABASE=Masimo Corp + +bluetooth:v0244* + ID_VENDOR_FROM_DATABASE=Iotera Inc. + +bluetooth:v0245* + ID_VENDOR_FROM_DATABASE=Endress+Hauser + +bluetooth:v0246* + ID_VENDOR_FROM_DATABASE=ACKme Networks, Inc. + +bluetooth:v0247* + ID_VENDOR_FROM_DATABASE=FiftyThree Inc. + +bluetooth:v0248* + ID_VENDOR_FROM_DATABASE=Parker Hannifin Corp + +bluetooth:v0249* + ID_VENDOR_FROM_DATABASE=Transcranial Ltd + +bluetooth:v024A* + ID_VENDOR_FROM_DATABASE=Uwatec AG + +bluetooth:v024B* + ID_VENDOR_FROM_DATABASE=Orlan LLC + +bluetooth:v024C* + ID_VENDOR_FROM_DATABASE=Blue Clover Devices + +bluetooth:v024D* + ID_VENDOR_FROM_DATABASE=M-Way Solutions GmbH + +bluetooth:v024E* + ID_VENDOR_FROM_DATABASE=Microtronics Engineering GmbH + +bluetooth:v024F* + ID_VENDOR_FROM_DATABASE=Schneider Schreibgeräte GmbH + +bluetooth:v0250* + ID_VENDOR_FROM_DATABASE=Sapphire Circuits LLC + +bluetooth:v0251* + ID_VENDOR_FROM_DATABASE=Lumo Bodytech Inc. + +bluetooth:v0252* + ID_VENDOR_FROM_DATABASE=UKC Technosolution + +bluetooth:v0253* + ID_VENDOR_FROM_DATABASE=Xicato Inc. + +bluetooth:v0254* + ID_VENDOR_FROM_DATABASE=Playbrush + +bluetooth:v0255* + ID_VENDOR_FROM_DATABASE=Dai Nippon Printing Co., Ltd. + +bluetooth:v0256* + ID_VENDOR_FROM_DATABASE=G24 Power Limited + +bluetooth:v0257* + ID_VENDOR_FROM_DATABASE=AdBabble Local Commerce Inc. + +bluetooth:v0258* + ID_VENDOR_FROM_DATABASE=Devialet SA + +bluetooth:v0259* + ID_VENDOR_FROM_DATABASE=ALTYOR + +bluetooth:v025A* + ID_VENDOR_FROM_DATABASE=University of Applied Sciences Valais/Haute Ecole Valaisanne + +bluetooth:v025B* + ID_VENDOR_FROM_DATABASE=Five Interactive, LLC dba Zendo + +bluetooth:v025C* + ID_VENDOR_FROM_DATABASE=NetEase (Hangzhou) Network co.Ltd. + +bluetooth:v025D* + ID_VENDOR_FROM_DATABASE=Lexmark International Inc. + +bluetooth:v025E* + ID_VENDOR_FROM_DATABASE=Fluke Corporation + +bluetooth:v025F* + ID_VENDOR_FROM_DATABASE=Yardarm Technologies + +bluetooth:v0260* + ID_VENDOR_FROM_DATABASE=SensaRx + +bluetooth:v0261* + ID_VENDOR_FROM_DATABASE=SECVRE GmbH + +bluetooth:v0262* + ID_VENDOR_FROM_DATABASE=Glacial Ridge Technologies + +bluetooth:v0263* + ID_VENDOR_FROM_DATABASE=Identiv, Inc. + +bluetooth:v0264* + ID_VENDOR_FROM_DATABASE=DDS, Inc. + +bluetooth:v0265* + ID_VENDOR_FROM_DATABASE=SMK Corporation + +bluetooth:v0266* + ID_VENDOR_FROM_DATABASE=Schawbel Technologies LLC + +bluetooth:v0267* + ID_VENDOR_FROM_DATABASE=XMI Systems SA + +bluetooth:v0268* + ID_VENDOR_FROM_DATABASE=Cerevo + +bluetooth:v0269* + ID_VENDOR_FROM_DATABASE=Torrox GmbH & Co KG + +bluetooth:v026A* + ID_VENDOR_FROM_DATABASE=Gemalto + +bluetooth:v026B* + ID_VENDOR_FROM_DATABASE=DEKA Research & Development Corp. + +bluetooth:v026C* + ID_VENDOR_FROM_DATABASE=Domster Tadeusz Szydlowski + +bluetooth:v026D* + ID_VENDOR_FROM_DATABASE=Technogym SPA + +bluetooth:v026E* + ID_VENDOR_FROM_DATABASE=FLEURBAEY BVBA + +bluetooth:v026F* + ID_VENDOR_FROM_DATABASE=Aptcode Solutions + +bluetooth:v0270* + ID_VENDOR_FROM_DATABASE=LSI ADL Technology + +bluetooth:v0271* + ID_VENDOR_FROM_DATABASE=Animas Corp + +bluetooth:v0272* + ID_VENDOR_FROM_DATABASE=Alps Electric Co., Ltd. + +bluetooth:v0273* + ID_VENDOR_FROM_DATABASE=OCEASOFT + +bluetooth:v0274* + ID_VENDOR_FROM_DATABASE=Motsai Research + +bluetooth:v0275* + ID_VENDOR_FROM_DATABASE=Geotab + +bluetooth:v0276* + ID_VENDOR_FROM_DATABASE=E.G.O. Elektro-Gerätebau GmbH + +bluetooth:v0277* + ID_VENDOR_FROM_DATABASE=bewhere inc + +bluetooth:v0278* + ID_VENDOR_FROM_DATABASE=Johnson Outdoors Inc + +bluetooth:v0279* + ID_VENDOR_FROM_DATABASE=steute Schaltgerate GmbH & Co. KG + +bluetooth:v027A* + ID_VENDOR_FROM_DATABASE=Ekomini inc. + +bluetooth:v027B* + ID_VENDOR_FROM_DATABASE=DEFA AS + +bluetooth:v027C* + ID_VENDOR_FROM_DATABASE=Aseptika Ltd + +bluetooth:v027D* + ID_VENDOR_FROM_DATABASE=HUAWEI Technologies Co., Ltd. ( 华为技术有限公司 ) + +bluetooth:v027E* + ID_VENDOR_FROM_DATABASE=HabitAware, LLC + +bluetooth:v027F* + ID_VENDOR_FROM_DATABASE=ruwido austria gmbh + +bluetooth:v0280* + ID_VENDOR_FROM_DATABASE=ITEC corporation + +bluetooth:v0281* + ID_VENDOR_FROM_DATABASE=StoneL + +bluetooth:v0282* + ID_VENDOR_FROM_DATABASE=Sonova AG + +bluetooth:v0283* + ID_VENDOR_FROM_DATABASE=Maven Machines, Inc. + +bluetooth:v0284* + ID_VENDOR_FROM_DATABASE=Synapse Electronics + +bluetooth:v0285* + ID_VENDOR_FROM_DATABASE=Standard Innovation Inc. + +bluetooth:v0286* + ID_VENDOR_FROM_DATABASE=RF Code, Inc. + +bluetooth:v0287* + ID_VENDOR_FROM_DATABASE=Wally Ventures S.L. + +bluetooth:v0288* + ID_VENDOR_FROM_DATABASE=Willowbank Electronics Ltd + +bluetooth:v0289* + ID_VENDOR_FROM_DATABASE=SK Telecom + +bluetooth:v028A* + ID_VENDOR_FROM_DATABASE=Jetro AS + +bluetooth:v028B* + ID_VENDOR_FROM_DATABASE=Code Gears LTD + +bluetooth:v028C* + ID_VENDOR_FROM_DATABASE=NANOLINK APS + +bluetooth:v028D* + ID_VENDOR_FROM_DATABASE=IF, LLC + +bluetooth:v028E* + ID_VENDOR_FROM_DATABASE=RF Digital Corp + +bluetooth:v028F* + ID_VENDOR_FROM_DATABASE=Church & Dwight Co., Inc + +bluetooth:v0290* + ID_VENDOR_FROM_DATABASE=Multibit Oy + +bluetooth:v0291* + ID_VENDOR_FROM_DATABASE=CliniCloud Inc + +bluetooth:v0292* + ID_VENDOR_FROM_DATABASE=SwiftSensors + +bluetooth:v0293* + ID_VENDOR_FROM_DATABASE=Blue Bite + +bluetooth:v0294* + ID_VENDOR_FROM_DATABASE=ELIAS GmbH + +bluetooth:v0295* + ID_VENDOR_FROM_DATABASE=Sivantos GmbH + +bluetooth:v0296* + ID_VENDOR_FROM_DATABASE=Petzl + +bluetooth:v0297* + ID_VENDOR_FROM_DATABASE=storm power ltd + +bluetooth:v0298* + ID_VENDOR_FROM_DATABASE=EISST Ltd + +bluetooth:v0299* + ID_VENDOR_FROM_DATABASE=Inexess Technology Simma KG + +bluetooth:v029A* + ID_VENDOR_FROM_DATABASE=Currant, Inc. + +bluetooth:v029B* + ID_VENDOR_FROM_DATABASE=C2 Development, Inc. + +bluetooth:v029C* + ID_VENDOR_FROM_DATABASE=Blue Sky Scientific, LLC + +bluetooth:v029D* + ID_VENDOR_FROM_DATABASE=ALOTTAZS LABS, LLC + +bluetooth:v029E* + ID_VENDOR_FROM_DATABASE=Kupson spol. s r.o. + +bluetooth:v029F* + ID_VENDOR_FROM_DATABASE=Areus Engineering GmbH + +bluetooth:v02A0* + ID_VENDOR_FROM_DATABASE=Impossible Camera GmbH + +bluetooth:v02A1* + ID_VENDOR_FROM_DATABASE=InventureTrack Systems + +bluetooth:v02A2* + ID_VENDOR_FROM_DATABASE=LockedUp + +bluetooth:v02A3* + ID_VENDOR_FROM_DATABASE=Itude + +bluetooth:v02A4* + ID_VENDOR_FROM_DATABASE=Pacific Lock Company + +bluetooth:v02A5* + ID_VENDOR_FROM_DATABASE=Tendyron Corporation ( 天地融科技股份有限公司 ) + +bluetooth:v02A6* + ID_VENDOR_FROM_DATABASE=Robert Bosch GmbH + +bluetooth:v02A7* + ID_VENDOR_FROM_DATABASE=Illuxtron international B.V. + +bluetooth:v02A8* + ID_VENDOR_FROM_DATABASE=miSport Ltd. + +bluetooth:v02A9* + ID_VENDOR_FROM_DATABASE=Chargelib + +bluetooth:v02AA* + ID_VENDOR_FROM_DATABASE=Doppler Lab + +bluetooth:v02AB* + ID_VENDOR_FROM_DATABASE=BBPOS Limited + +bluetooth:v02AC* + ID_VENDOR_FROM_DATABASE=RTB Elektronik GmbH & Co. KG + +bluetooth:v02AD* + ID_VENDOR_FROM_DATABASE=Rx Networks, Inc. + +bluetooth:v02AE* + ID_VENDOR_FROM_DATABASE=WeatherFlow, Inc. + +bluetooth:v02AF* + ID_VENDOR_FROM_DATABASE=Technicolor USA Inc. + +bluetooth:v02B0* + ID_VENDOR_FROM_DATABASE=Bestechnic(Shanghai),Ltd + +bluetooth:v02B1* + ID_VENDOR_FROM_DATABASE=Raden Inc + +bluetooth:v02B2* + ID_VENDOR_FROM_DATABASE=JouZen Oy + +bluetooth:v02B3* + ID_VENDOR_FROM_DATABASE=CLABER S.P.A. + +bluetooth:v02B4* + ID_VENDOR_FROM_DATABASE=Hyginex, Inc. + +bluetooth:v02B5* + ID_VENDOR_FROM_DATABASE=HANSHIN ELECTRIC RAILWAY CO.,LTD. + +bluetooth:v02B6* + ID_VENDOR_FROM_DATABASE=Schneider Electric + +bluetooth:v02B7* + ID_VENDOR_FROM_DATABASE=Oort Technologies LLC + +bluetooth:v02B8* + ID_VENDOR_FROM_DATABASE=Chrono Therapeutics + +bluetooth:v02B9* + ID_VENDOR_FROM_DATABASE=Rinnai Corporation + +bluetooth:v02BA* + ID_VENDOR_FROM_DATABASE=Swissprime Technologies AG + +bluetooth:v02BB* + ID_VENDOR_FROM_DATABASE=Koha.,Co.Ltd + +bluetooth:v02BC* + ID_VENDOR_FROM_DATABASE=Genevac Ltd + +bluetooth:v02BD* + ID_VENDOR_FROM_DATABASE=Chemtronics + +bluetooth:v02BE* + ID_VENDOR_FROM_DATABASE=Seguro Technology Sp. z o.o. + +bluetooth:v02BF* + ID_VENDOR_FROM_DATABASE=Redbird Flight Simulations + +bluetooth:v02C0* + ID_VENDOR_FROM_DATABASE=Dash Robotics + +bluetooth:v02C1* + ID_VENDOR_FROM_DATABASE=LINE Corporation + +bluetooth:v02C2* + ID_VENDOR_FROM_DATABASE=Guillemot Corporation + +bluetooth:v02C3* + ID_VENDOR_FROM_DATABASE=Techtronic Power Tools Technology Limited + +bluetooth:v02C4* + ID_VENDOR_FROM_DATABASE=Wilson Sporting Goods + +bluetooth:v02C5* + ID_VENDOR_FROM_DATABASE=Lenovo (Singapore) Pte Ltd. ( 联想(新加坡) ) + +bluetooth:v02C6* + ID_VENDOR_FROM_DATABASE=Ayatan Sensors + +bluetooth:v02C7* + ID_VENDOR_FROM_DATABASE=Electronics Tomorrow Limited + +bluetooth:v02C8* + ID_VENDOR_FROM_DATABASE=VASCO Data Security International, Inc. + +bluetooth:v02C9* + ID_VENDOR_FROM_DATABASE=PayRange Inc. + +bluetooth:v02CA* + ID_VENDOR_FROM_DATABASE=ABOV Semiconductor + +bluetooth:v02CB* + ID_VENDOR_FROM_DATABASE=AINA-Wireless Inc. + +bluetooth:v02CC* + ID_VENDOR_FROM_DATABASE=Eijkelkamp Soil & Water + +bluetooth:v02CD* + ID_VENDOR_FROM_DATABASE=BMA ergonomics b.v. + +bluetooth:v02CE* + ID_VENDOR_FROM_DATABASE=Teva Branded Pharmaceutical Products R&D, Inc. + +bluetooth:v02CF* + ID_VENDOR_FROM_DATABASE=Anima + +bluetooth:v02D0* + ID_VENDOR_FROM_DATABASE=3M + +bluetooth:v02D1* + ID_VENDOR_FROM_DATABASE=Empatica Srl + +bluetooth:v02D2* + ID_VENDOR_FROM_DATABASE=Afero, Inc. + +bluetooth:v02D3* + ID_VENDOR_FROM_DATABASE=Powercast Corporation + +bluetooth:v02D4* + ID_VENDOR_FROM_DATABASE=Secuyou ApS + +bluetooth:v02D5* + ID_VENDOR_FROM_DATABASE=OMRON Corporation + +bluetooth:v02D6* + ID_VENDOR_FROM_DATABASE=Send Solutions + +bluetooth:v02D7* + ID_VENDOR_FROM_DATABASE=NIPPON SYSTEMWARE CO.,LTD. + +bluetooth:v02D8* + ID_VENDOR_FROM_DATABASE=Neosfar + +bluetooth:v02D9* + ID_VENDOR_FROM_DATABASE=Fliegl Agrartechnik GmbH + +bluetooth:v02DA* + ID_VENDOR_FROM_DATABASE=Gilvader + +bluetooth:v02DB* + ID_VENDOR_FROM_DATABASE=Digi International Inc (R) + +bluetooth:v02DC* + ID_VENDOR_FROM_DATABASE=DeWalch Technologies, Inc. + +bluetooth:v02DD* + ID_VENDOR_FROM_DATABASE=Flint Rehabilitation Devices, LLC + +bluetooth:v02DE* + ID_VENDOR_FROM_DATABASE=Samsung SDS Co., Ltd. + +bluetooth:v02DF* + ID_VENDOR_FROM_DATABASE=Blur Product Development + +bluetooth:v02E0* + ID_VENDOR_FROM_DATABASE=University of Michigan + +bluetooth:v02E1* + ID_VENDOR_FROM_DATABASE=Victron Energy BV + +bluetooth:v02E2* + ID_VENDOR_FROM_DATABASE=NTT docomo + +bluetooth:v02E3* + ID_VENDOR_FROM_DATABASE=Carmanah Technologies Corp. + +bluetooth:v02E4* + ID_VENDOR_FROM_DATABASE=Bytestorm Ltd. + +bluetooth:v02E5* + ID_VENDOR_FROM_DATABASE=Espressif Incorporated ( 乐鑫信息科技(上海)有限公司 ) + +bluetooth:v02E6* + ID_VENDOR_FROM_DATABASE=Unwire + +bluetooth:v02E7* + ID_VENDOR_FROM_DATABASE=Connected Yard, Inc. + +bluetooth:v02E8* + ID_VENDOR_FROM_DATABASE=American Music Environments + +bluetooth:v02E9* + ID_VENDOR_FROM_DATABASE=Sensogram Technologies, Inc. + +bluetooth:v02EA* + ID_VENDOR_FROM_DATABASE=Fujitsu Limited + +bluetooth:v02EB* + ID_VENDOR_FROM_DATABASE=Ardic Technology + +bluetooth:v02EC* + ID_VENDOR_FROM_DATABASE=Delta Systems, Inc + +bluetooth:v02ED* + ID_VENDOR_FROM_DATABASE=HTC Corporation + +bluetooth:v02EE* + ID_VENDOR_FROM_DATABASE=Citizen Holdings Co., Ltd. + +bluetooth:v02EF* + ID_VENDOR_FROM_DATABASE=SMART-INNOVATION.inc + +bluetooth:v02F0* + ID_VENDOR_FROM_DATABASE=Blackrat Software + +bluetooth:v02F1* + ID_VENDOR_FROM_DATABASE=The Idea Cave, LLC + +bluetooth:v02F2* + ID_VENDOR_FROM_DATABASE=GoPro, Inc. + +bluetooth:v02F3* + ID_VENDOR_FROM_DATABASE=AuthAir, Inc + +bluetooth:v02F4* + ID_VENDOR_FROM_DATABASE=Vensi, Inc. + +bluetooth:v02F5* + ID_VENDOR_FROM_DATABASE=Indagem Tech LLC + +bluetooth:v02F6* + ID_VENDOR_FROM_DATABASE=Intemo Technologies + +bluetooth:v02F7* + ID_VENDOR_FROM_DATABASE=DreamVisions co., Ltd. + +bluetooth:v02F8* + ID_VENDOR_FROM_DATABASE=Runteq Oy Ltd + +bluetooth:v02F9* + ID_VENDOR_FROM_DATABASE=IMAGINATION TECHNOLOGIES LTD + +bluetooth:v02FA* + ID_VENDOR_FROM_DATABASE=CoSTAR Technologies + +bluetooth:v02FB* + ID_VENDOR_FROM_DATABASE=Clarius Mobile Health Corp. + +bluetooth:v02FC* + ID_VENDOR_FROM_DATABASE=Shanghai Frequen Microelectronics Co., Ltd. + +bluetooth:v02FD* + ID_VENDOR_FROM_DATABASE=Uwanna, Inc. + +bluetooth:v02FE* + ID_VENDOR_FROM_DATABASE=Lierda Science & Technology Group Co., Ltd. + +bluetooth:v02FF* + ID_VENDOR_FROM_DATABASE=Silicon Laboratories + +bluetooth:v0300* + ID_VENDOR_FROM_DATABASE=World Moto Inc. + +bluetooth:v0301* + ID_VENDOR_FROM_DATABASE=Giatec Scientific Inc. + +bluetooth:v0302* + ID_VENDOR_FROM_DATABASE=Loop Devices, Inc + +bluetooth:v0303* + ID_VENDOR_FROM_DATABASE=IACA electronique + +bluetooth:v0304* + ID_VENDOR_FROM_DATABASE=Martians Inc + +bluetooth:v0305* + ID_VENDOR_FROM_DATABASE=Swipp ApS + +bluetooth:v0306* + ID_VENDOR_FROM_DATABASE=Life Laboratory Inc. + +bluetooth:v0307* + ID_VENDOR_FROM_DATABASE=FUJI INDUSTRIAL CO.,LTD. + +bluetooth:v0308* + ID_VENDOR_FROM_DATABASE=Surefire, LLC + +bluetooth:v0309* + ID_VENDOR_FROM_DATABASE=Dolby Labs + +bluetooth:v030A* + ID_VENDOR_FROM_DATABASE=Ellisys + +bluetooth:v030B* + ID_VENDOR_FROM_DATABASE=Magnitude Lighting Converters + +bluetooth:v030C* + ID_VENDOR_FROM_DATABASE=Hilti AG + +bluetooth:v030D* + ID_VENDOR_FROM_DATABASE=Devdata S.r.l. + +bluetooth:v030E* + ID_VENDOR_FROM_DATABASE=Deviceworx + +bluetooth:v030F* + ID_VENDOR_FROM_DATABASE=Shortcut Labs + +bluetooth:v0310* + ID_VENDOR_FROM_DATABASE=SGL Italia S.r.l. + +bluetooth:v0311* + ID_VENDOR_FROM_DATABASE=PEEQ DATA + +bluetooth:v0312* + ID_VENDOR_FROM_DATABASE=Ducere Technologies Pvt Ltd + +bluetooth:v0313* + ID_VENDOR_FROM_DATABASE=DiveNav, Inc. + +bluetooth:v0314* + ID_VENDOR_FROM_DATABASE=RIIG AI Sp. z o.o. + +bluetooth:v0315* + ID_VENDOR_FROM_DATABASE=Thermo Fisher Scientific + +bluetooth:v0316* + ID_VENDOR_FROM_DATABASE=AG Measurematics Pvt. Ltd. + +bluetooth:v0317* + ID_VENDOR_FROM_DATABASE=CHUO Electronics CO., LTD. + +bluetooth:v0318* + ID_VENDOR_FROM_DATABASE=Aspenta International + +bluetooth:v0319* + ID_VENDOR_FROM_DATABASE=Eugster Frismag AG + +bluetooth:v031A* + ID_VENDOR_FROM_DATABASE=Amber wireless GmbH + +bluetooth:v031B* + ID_VENDOR_FROM_DATABASE=HQ Inc + +bluetooth:v031C* + ID_VENDOR_FROM_DATABASE=Lab Sensor Solutions + +bluetooth:v031D* + ID_VENDOR_FROM_DATABASE=Enterlab ApS + +bluetooth:v031E* + ID_VENDOR_FROM_DATABASE=Eyefi, Inc. + +bluetooth:v031F* + ID_VENDOR_FROM_DATABASE=MetaSystem S.p.A + +bluetooth:v0320* + ID_VENDOR_FROM_DATABASE=SONO ELECTRONICS. CO., LTD + +bluetooth:v0321* + ID_VENDOR_FROM_DATABASE=Jewelbots + +bluetooth:v0322* + ID_VENDOR_FROM_DATABASE=Compumedics Limited + +bluetooth:v0323* + ID_VENDOR_FROM_DATABASE=Rotor Bike Components + +bluetooth:v0324* + ID_VENDOR_FROM_DATABASE=Astro, Inc. + +bluetooth:v0325* + ID_VENDOR_FROM_DATABASE=Amotus Solutions + +bluetooth:v0326* + ID_VENDOR_FROM_DATABASE=Healthwear Technologies (Changzhou)Ltd + +bluetooth:v0327* + ID_VENDOR_FROM_DATABASE=Essex Electronics + +bluetooth:v0328* + ID_VENDOR_FROM_DATABASE=Grundfos A/S + +bluetooth:v0329* + ID_VENDOR_FROM_DATABASE=Eargo, Inc. + +bluetooth:v032A* + ID_VENDOR_FROM_DATABASE=Electronic Design Lab + +bluetooth:v032B* + ID_VENDOR_FROM_DATABASE=ESYLUX + +bluetooth:v032C* + ID_VENDOR_FROM_DATABASE=NIPPON SMT.CO.,Ltd + +bluetooth:v032D* + ID_VENDOR_FROM_DATABASE=BM innovations GmbH + +bluetooth:v032E* + ID_VENDOR_FROM_DATABASE=indoormap + +bluetooth:v032F* + ID_VENDOR_FROM_DATABASE=OttoQ Inc + +bluetooth:v0330* + ID_VENDOR_FROM_DATABASE=North Pole Engineering + +bluetooth:v0331* + ID_VENDOR_FROM_DATABASE=3flares Technologies Inc. + +bluetooth:v0332* + ID_VENDOR_FROM_DATABASE=Electrocompaniet A.S. + +bluetooth:v0333* + ID_VENDOR_FROM_DATABASE=Mul-T-Lock + +bluetooth:v0334* + ID_VENDOR_FROM_DATABASE=Corentium AS + +bluetooth:v0335* + ID_VENDOR_FROM_DATABASE=Enlighted Inc + +bluetooth:v0336* + ID_VENDOR_FROM_DATABASE=GISTIC + +bluetooth:v0337* + ID_VENDOR_FROM_DATABASE=AJP2 Holdings, LLC + +bluetooth:v0338* + ID_VENDOR_FROM_DATABASE=COBI GmbH + +bluetooth:v0339* + ID_VENDOR_FROM_DATABASE=Blue Sky Scientific, LLC + +bluetooth:v033A* + ID_VENDOR_FROM_DATABASE=Appception, Inc. + +bluetooth:v033B* + ID_VENDOR_FROM_DATABASE=Courtney Thorne Limited + +bluetooth:v033C* + ID_VENDOR_FROM_DATABASE=Virtuosys + +bluetooth:v033D* + ID_VENDOR_FROM_DATABASE=TPV Technology Limited + +bluetooth:v033E* + ID_VENDOR_FROM_DATABASE=Monitra SA + +bluetooth:v033F* + ID_VENDOR_FROM_DATABASE=Automation Components, Inc. + +bluetooth:v0340* + ID_VENDOR_FROM_DATABASE=Letsense s.r.l. + +bluetooth:v0341* + ID_VENDOR_FROM_DATABASE=Etesian Technologies LLC + +bluetooth:v0342* + ID_VENDOR_FROM_DATABASE=GERTEC BRASIL LTDA. + +bluetooth:v0343* + ID_VENDOR_FROM_DATABASE=Drekker Development Pty. Ltd. + +bluetooth:v0344* + ID_VENDOR_FROM_DATABASE=Whirl Inc + +bluetooth:v0345* + ID_VENDOR_FROM_DATABASE=Locus Positioning + +bluetooth:v0346* + ID_VENDOR_FROM_DATABASE=Acuity Brands Lighting, Inc + +bluetooth:v0347* + ID_VENDOR_FROM_DATABASE=Prevent Biometrics + +bluetooth:v0348* + ID_VENDOR_FROM_DATABASE=Arioneo + +bluetooth:v0349* + ID_VENDOR_FROM_DATABASE=VersaMe + +bluetooth:v034A* + ID_VENDOR_FROM_DATABASE=Vaddio + +bluetooth:v034B* + ID_VENDOR_FROM_DATABASE=Libratone A/S + +bluetooth:v034C* + ID_VENDOR_FROM_DATABASE=HM Electronics, Inc. + +bluetooth:v034D* + ID_VENDOR_FROM_DATABASE=TASER International, Inc. + +bluetooth:v034E* + ID_VENDOR_FROM_DATABASE=Safe Trust Inc. + +bluetooth:v034F* + ID_VENDOR_FROM_DATABASE=Heartland Payment Systems + +bluetooth:v0350* + ID_VENDOR_FROM_DATABASE=Bitstrata Systems Inc. + +bluetooth:v0351* + ID_VENDOR_FROM_DATABASE=Pieps GmbH + +bluetooth:v0352* + ID_VENDOR_FROM_DATABASE=iRiding(Xiamen)Technology Co.,Ltd. + +bluetooth:v0353* + ID_VENDOR_FROM_DATABASE=Alpha Audiotronics, Inc. + +bluetooth:v0354* + ID_VENDOR_FROM_DATABASE=TOPPAN FORMS CO.,LTD. + +bluetooth:v0355* + ID_VENDOR_FROM_DATABASE=Sigma Designs, Inc. + +bluetooth:v0356* + ID_VENDOR_FROM_DATABASE=Spectrum Brands, Inc. + +bluetooth:v0357* + ID_VENDOR_FROM_DATABASE=Polymap Wireless + +bluetooth:v0358* + ID_VENDOR_FROM_DATABASE=MagniWare Ltd. + +bluetooth:v0359* + ID_VENDOR_FROM_DATABASE=Novotec Medical GmbH + +bluetooth:v035A* + ID_VENDOR_FROM_DATABASE=Medicom Innovation Partner a/s + +bluetooth:v035B* + ID_VENDOR_FROM_DATABASE=Matrix Inc. + +bluetooth:v035C* + ID_VENDOR_FROM_DATABASE=Eaton Corporation + +bluetooth:v035D* + ID_VENDOR_FROM_DATABASE=KYS + +bluetooth:v035E* + ID_VENDOR_FROM_DATABASE=Naya Health, Inc. + +bluetooth:v035F* + ID_VENDOR_FROM_DATABASE=Acromag + +bluetooth:v0360* + ID_VENDOR_FROM_DATABASE=Insulet Corporation + +bluetooth:v0361* + ID_VENDOR_FROM_DATABASE=Wellinks Inc. + +bluetooth:v0362* + ID_VENDOR_FROM_DATABASE=ON Semiconductor + +bluetooth:v0363* + ID_VENDOR_FROM_DATABASE=FREELAP SA + +bluetooth:v0364* + ID_VENDOR_FROM_DATABASE=Favero Electronics Srl + +bluetooth:v0365* + ID_VENDOR_FROM_DATABASE=BioMech Sensor LLC + +bluetooth:v0366* + ID_VENDOR_FROM_DATABASE=BOLTT Sports technologies Private limited + +bluetooth:v0367* + ID_VENDOR_FROM_DATABASE=Saphe International + +bluetooth:v0368* + ID_VENDOR_FROM_DATABASE=Metormote AB + +bluetooth:v0369* + ID_VENDOR_FROM_DATABASE=littleBits + +bluetooth:v036A* + ID_VENDOR_FROM_DATABASE=SetPoint Medical + +bluetooth:v036B* + ID_VENDOR_FROM_DATABASE=BRControls Products BV + +bluetooth:v036C* + ID_VENDOR_FROM_DATABASE=Zipcar + +bluetooth:v036D* + ID_VENDOR_FROM_DATABASE=AirBolt Pty Ltd + +bluetooth:v036E* + ID_VENDOR_FROM_DATABASE=KeepTruckin Inc + +bluetooth:v036F* + ID_VENDOR_FROM_DATABASE=Motiv, Inc. + +bluetooth:v0370* + ID_VENDOR_FROM_DATABASE=Wazombi Labs OÜ + +bluetooth:v0371* + ID_VENDOR_FROM_DATABASE=ORBCOMM + +bluetooth:v0372* + ID_VENDOR_FROM_DATABASE=Nixie Labs, Inc. + +bluetooth:v0373* + ID_VENDOR_FROM_DATABASE=AppNearMe Ltd + +bluetooth:v0374* + ID_VENDOR_FROM_DATABASE=Holman Industries + +bluetooth:v0375* + ID_VENDOR_FROM_DATABASE=Expain AS + +bluetooth:v0376* + ID_VENDOR_FROM_DATABASE=Electronic Temperature Instruments Ltd + +bluetooth:v0377* + ID_VENDOR_FROM_DATABASE=Plejd AB + +bluetooth:v0378* + ID_VENDOR_FROM_DATABASE=Propeller Health + +bluetooth:v0379* + ID_VENDOR_FROM_DATABASE=Shenzhen iMCO Electronic Technology Co.,Ltd + +bluetooth:v037A* + ID_VENDOR_FROM_DATABASE=Algoria + +bluetooth:v037B* + ID_VENDOR_FROM_DATABASE=Apption Labs Inc. + +bluetooth:v037C* + ID_VENDOR_FROM_DATABASE=Cronologics Corporation + +bluetooth:v037D* + ID_VENDOR_FROM_DATABASE=MICRODIA Ltd. + +bluetooth:v037E* + ID_VENDOR_FROM_DATABASE=lulabytes S.L. + +bluetooth:v037F* + ID_VENDOR_FROM_DATABASE=Nestec S.A. + +bluetooth:v0380* + ID_VENDOR_FROM_DATABASE=LLC "MEGA-F service" + +bluetooth:v0381* + ID_VENDOR_FROM_DATABASE=Sharp Corporation + +bluetooth:v0382* + ID_VENDOR_FROM_DATABASE=Precision Outcomes Ltd + +bluetooth:v0383* + ID_VENDOR_FROM_DATABASE=Kronos Incorporated + +bluetooth:v0384* + ID_VENDOR_FROM_DATABASE=OCOSMOS Co., Ltd. + +bluetooth:v0385* + ID_VENDOR_FROM_DATABASE=Embedded Electronic Solutions Ltd. dba e2Solutions + +bluetooth:v0386* + ID_VENDOR_FROM_DATABASE=Aterica Inc. + +bluetooth:v0387* + ID_VENDOR_FROM_DATABASE=BluStor PMC, Inc. + +bluetooth:v0388* + ID_VENDOR_FROM_DATABASE=Kapsch TrafficCom AB + +bluetooth:v0389* + ID_VENDOR_FROM_DATABASE=ActiveBlu Corporation + +bluetooth:v038A* + ID_VENDOR_FROM_DATABASE=Kohler Mira Limited + +bluetooth:v038B* + ID_VENDOR_FROM_DATABASE=Noke + +bluetooth:v038C* + ID_VENDOR_FROM_DATABASE=Appion Inc. + +bluetooth:v038D* + ID_VENDOR_FROM_DATABASE=Resmed Ltd + +bluetooth:v038E* + ID_VENDOR_FROM_DATABASE=Crownstone B.V. + +bluetooth:v038F* + ID_VENDOR_FROM_DATABASE=Xiaomi Inc. + +bluetooth:v0390* + ID_VENDOR_FROM_DATABASE=INFOTECH s.r.o. + +bluetooth:v0391* + ID_VENDOR_FROM_DATABASE=Thingsquare AB + +bluetooth:v0392* + ID_VENDOR_FROM_DATABASE=T&D + +bluetooth:v0393* + ID_VENDOR_FROM_DATABASE=LAVAZZA S.p.A. + +bluetooth:v0394* + ID_VENDOR_FROM_DATABASE=Netclearance Systems, Inc. + +bluetooth:v0395* + ID_VENDOR_FROM_DATABASE=SDATAWAY + +bluetooth:v0396* + ID_VENDOR_FROM_DATABASE=BLOKS GmbH + +bluetooth:v0397* + ID_VENDOR_FROM_DATABASE=LEGO System A/S + +bluetooth:v0398* + ID_VENDOR_FROM_DATABASE=Thetatronics Ltd + +bluetooth:v0399* + ID_VENDOR_FROM_DATABASE=Nikon Corporation + +bluetooth:v039A* + ID_VENDOR_FROM_DATABASE=NeST + +bluetooth:v039B* + ID_VENDOR_FROM_DATABASE=South Silicon Valley Microelectronics + +bluetooth:v039C* + ID_VENDOR_FROM_DATABASE=ALE International + +bluetooth:v039D* + ID_VENDOR_FROM_DATABASE=CareView Communications, Inc. + +bluetooth:v039E* + ID_VENDOR_FROM_DATABASE=SchoolBoard Limited + +bluetooth:v039F* + ID_VENDOR_FROM_DATABASE=Molex Corporation + +bluetooth:v03A0* + ID_VENDOR_FROM_DATABASE=IVT Wireless Limited + +bluetooth:v03A1* + ID_VENDOR_FROM_DATABASE=Alpine Labs LLC + +bluetooth:v03A2* + ID_VENDOR_FROM_DATABASE=Candura Instruments + +bluetooth:v03A3* + ID_VENDOR_FROM_DATABASE=SmartMovt Technology Co., Ltd + +bluetooth:v03A4* + ID_VENDOR_FROM_DATABASE=Token Zero Ltd + +bluetooth:v03A5* + ID_VENDOR_FROM_DATABASE=ACE CAD Enterprise Co., Ltd. (ACECAD) + +bluetooth:v03A6* + ID_VENDOR_FROM_DATABASE=Medela, Inc + +bluetooth:v03A7* + ID_VENDOR_FROM_DATABASE=AeroScout + +bluetooth:v03A8* + ID_VENDOR_FROM_DATABASE=Esrille Inc. + +bluetooth:v03A9* + ID_VENDOR_FROM_DATABASE=THINKERLY SRL + +bluetooth:v03AA* + ID_VENDOR_FROM_DATABASE=Exon Sp. z o.o. + +bluetooth:v03AB* + ID_VENDOR_FROM_DATABASE=Meizu Technology Co., Ltd. + +bluetooth:v03AC* + ID_VENDOR_FROM_DATABASE=Smablo LTD + +bluetooth:v03AD* + ID_VENDOR_FROM_DATABASE=XiQ + +bluetooth:v03AE* + ID_VENDOR_FROM_DATABASE=Allswell Inc. + +bluetooth:v03AF* + ID_VENDOR_FROM_DATABASE=Comm-N-Sense Corp DBA Verigo + +bluetooth:v03B0* + ID_VENDOR_FROM_DATABASE=VIBRADORM GmbH + +bluetooth:v03B1* + ID_VENDOR_FROM_DATABASE=Otodata Wireless Network Inc. + +bluetooth:v03B2* + ID_VENDOR_FROM_DATABASE=Propagation Systems Limited + +bluetooth:v03B3* + ID_VENDOR_FROM_DATABASE=Midwest Instruments & Controls + +bluetooth:v03B4* + ID_VENDOR_FROM_DATABASE=Alpha Nodus, inc. + +bluetooth:v03B5* + ID_VENDOR_FROM_DATABASE=petPOMM, Inc + +bluetooth:v03B6* + ID_VENDOR_FROM_DATABASE=Mattel + +bluetooth:v03B7* + ID_VENDOR_FROM_DATABASE=Airbly Inc. + +bluetooth:v03B8* + ID_VENDOR_FROM_DATABASE=A-Safe Limited + +bluetooth:v03B9* + ID_VENDOR_FROM_DATABASE=FREDERIQUE CONSTANT SA + +bluetooth:v03BA* + ID_VENDOR_FROM_DATABASE=Maxscend Microelectronics Company Limited + +bluetooth:v03BB* + ID_VENDOR_FROM_DATABASE=Abbott Diabetes Care + +bluetooth:v03BC* + ID_VENDOR_FROM_DATABASE=ASB Bank Ltd + +bluetooth:v03BD* + ID_VENDOR_FROM_DATABASE=amadas + +bluetooth:v03BE* + ID_VENDOR_FROM_DATABASE=Applied Science, Inc. + +bluetooth:v03BF* + ID_VENDOR_FROM_DATABASE=iLumi Solutions Inc. + +bluetooth:v03C0* + ID_VENDOR_FROM_DATABASE=Arch Systems Inc. + +bluetooth:v03C1* + ID_VENDOR_FROM_DATABASE=Ember Technologies, Inc. + +bluetooth:v03C2* + ID_VENDOR_FROM_DATABASE=Snapchat Inc + +bluetooth:v03C3* + ID_VENDOR_FROM_DATABASE=Casambi Technologies Oy + +bluetooth:v03C4* + ID_VENDOR_FROM_DATABASE=Pico Technology Inc. + +bluetooth:v03C5* + ID_VENDOR_FROM_DATABASE=St. Jude Medical, Inc. + +bluetooth:v03C6* + ID_VENDOR_FROM_DATABASE=Intricon + +bluetooth:v03C7* + ID_VENDOR_FROM_DATABASE=Structural Health Systems, Inc. + +bluetooth:v03C8* + ID_VENDOR_FROM_DATABASE=Avvel International + +bluetooth:v03C9* + ID_VENDOR_FROM_DATABASE=Gallagher Group + +bluetooth:v03CA* + ID_VENDOR_FROM_DATABASE=In2things Automation Pvt. Ltd. + +bluetooth:v03CB* + ID_VENDOR_FROM_DATABASE=SYSDEV Srl + +bluetooth:v03CC* + ID_VENDOR_FROM_DATABASE=Vonkil Technologies Ltd + +bluetooth:v03CD* + ID_VENDOR_FROM_DATABASE=Wynd Technologies, Inc. + +bluetooth:v03CE* + ID_VENDOR_FROM_DATABASE=CONTRINEX S.A. + +bluetooth:v03CF* + ID_VENDOR_FROM_DATABASE=MIRA, Inc. + +bluetooth:v03D0* + ID_VENDOR_FROM_DATABASE=Watteam Ltd + +bluetooth:v03D1* + ID_VENDOR_FROM_DATABASE=Density Inc. + +bluetooth:v03D2* + ID_VENDOR_FROM_DATABASE=IOT Pot India Private Limited + +bluetooth:v03D3* + ID_VENDOR_FROM_DATABASE=Sigma Connectivity AB + +bluetooth:v03D4* + ID_VENDOR_FROM_DATABASE=PEG PEREGO SPA + +bluetooth:v03D5* + ID_VENDOR_FROM_DATABASE=Wyzelink Systems Inc. + +bluetooth:v03D6* + ID_VENDOR_FROM_DATABASE=Yota Devices LTD + +bluetooth:v03D7* + ID_VENDOR_FROM_DATABASE=FINSECUR + +bluetooth:v03D8* + ID_VENDOR_FROM_DATABASE=Zen-Me Labs Ltd + +bluetooth:v03D9* + ID_VENDOR_FROM_DATABASE=3IWare Co., Ltd. + +bluetooth:v03DA* + ID_VENDOR_FROM_DATABASE=EnOcean GmbH + +bluetooth:v03DB* + ID_VENDOR_FROM_DATABASE=Instabeat, Inc + +bluetooth:v03DC* + ID_VENDOR_FROM_DATABASE=Nima Labs + +bluetooth:v03DD* + ID_VENDOR_FROM_DATABASE=Andreas Stihl AG & Co. KG + +bluetooth:v03DE* + ID_VENDOR_FROM_DATABASE=Nathan Rhoades LLC + +bluetooth:v03DF* + ID_VENDOR_FROM_DATABASE=Grob Technologies, LLC + +bluetooth:v03E0* + ID_VENDOR_FROM_DATABASE=Actions (Zhuhai) Technology Co., Limited + +bluetooth:v03E1* + ID_VENDOR_FROM_DATABASE=SPD Development Company Ltd + +bluetooth:v03E2* + ID_VENDOR_FROM_DATABASE=Sensoan Oy + +bluetooth:v03E3* + ID_VENDOR_FROM_DATABASE=Qualcomm Life Inc + +bluetooth:v03E4* + ID_VENDOR_FROM_DATABASE=Chip-ing AG + +bluetooth:v03E5* + ID_VENDOR_FROM_DATABASE=ffly4u + +bluetooth:v03E6* + ID_VENDOR_FROM_DATABASE=IoT Instruments Oy + +bluetooth:v03E7* + ID_VENDOR_FROM_DATABASE=TRUE Fitness Technology + +bluetooth:v03E8* + ID_VENDOR_FROM_DATABASE=Reiner Kartengeraete GmbH & Co. KG. + +bluetooth:v03E9* + ID_VENDOR_FROM_DATABASE=SHENZHEN LEMONJOY TECHNOLOGY CO., LTD. + +bluetooth:v03EA* + ID_VENDOR_FROM_DATABASE=Hello Inc. + +bluetooth:v03EB* + ID_VENDOR_FROM_DATABASE=Evollve Inc. + +bluetooth:v03EC* + ID_VENDOR_FROM_DATABASE=Jigowatts Inc. + +bluetooth:v03ED* + ID_VENDOR_FROM_DATABASE=BASIC MICRO.COM,INC. + +bluetooth:v03EE* + ID_VENDOR_FROM_DATABASE=CUBE TECHNOLOGIES + +bluetooth:v03EF* + ID_VENDOR_FROM_DATABASE=foolography GmbH + +bluetooth:v03F0* + ID_VENDOR_FROM_DATABASE=CLINK + +bluetooth:v03F1* + ID_VENDOR_FROM_DATABASE=Hestan Smart Cooking Inc. + +bluetooth:v03F2* + ID_VENDOR_FROM_DATABASE=WindowMaster A/S + +bluetooth:v03F3* + ID_VENDOR_FROM_DATABASE=Flowscape AB + +bluetooth:v03F4* + ID_VENDOR_FROM_DATABASE=PAL Technologies Ltd + +bluetooth:v03F5* + ID_VENDOR_FROM_DATABASE=WHERE, Inc. + +bluetooth:v03F6* + ID_VENDOR_FROM_DATABASE=Iton Technology Corp. + +bluetooth:v03F7* + ID_VENDOR_FROM_DATABASE=Owl Labs Inc. + +bluetooth:v03F8* + ID_VENDOR_FROM_DATABASE=Rockford Corp. + +bluetooth:v03F9* + ID_VENDOR_FROM_DATABASE=Becon Technologies Co.,Ltd. + +bluetooth:v03FA* + ID_VENDOR_FROM_DATABASE=Vyassoft Technologies Inc + +bluetooth:v03FB* + ID_VENDOR_FROM_DATABASE=Nox Medical + +bluetooth:v03FC* + ID_VENDOR_FROM_DATABASE=Kimberly-Clark + +bluetooth:v03FD* + ID_VENDOR_FROM_DATABASE=Trimble Navigation Ltd. + +bluetooth:v03FE* + ID_VENDOR_FROM_DATABASE=Littelfuse + +bluetooth:v03FF* + ID_VENDOR_FROM_DATABASE=Withings + +bluetooth:v0400* + ID_VENDOR_FROM_DATABASE=i-developer IT Beratung UG + +bluetooth:v0401* + ID_VENDOR_FROM_DATABASE=リレーションズ株式会社 + +bluetooth:v0402* + ID_VENDOR_FROM_DATABASE=Sears Holdings Corporation + +bluetooth:v0403* + ID_VENDOR_FROM_DATABASE=Gantner Electronic GmbH + +bluetooth:v0404* + ID_VENDOR_FROM_DATABASE=Authomate Inc + +bluetooth:v0405* + ID_VENDOR_FROM_DATABASE=Vertex International, Inc. + +bluetooth:v0406* + ID_VENDOR_FROM_DATABASE=Airtago + +bluetooth:v0407* + ID_VENDOR_FROM_DATABASE=Swiss Audio SA + +bluetooth:v0408* + ID_VENDOR_FROM_DATABASE=ToGetHome Inc. + +bluetooth:v0409* + ID_VENDOR_FROM_DATABASE=AXIS + +bluetooth:v040A* + ID_VENDOR_FROM_DATABASE=Openmatics + +bluetooth:v040B* + ID_VENDOR_FROM_DATABASE=Jana Care Inc. + +bluetooth:v040C* + ID_VENDOR_FROM_DATABASE=Senix Corporation + +bluetooth:v040D* + ID_VENDOR_FROM_DATABASE=NorthStar Battery Company, LLC diff --git a/hwdb.d/20-net-ifname.hwdb b/hwdb.d/20-net-ifname.hwdb new file mode 100644 index 00000000..2408dc17 --- /dev/null +++ b/hwdb.d/20-net-ifname.hwdb @@ -0,0 +1,5 @@ +# This file is part of systemd. + +# Dell iDRAC Virtual USB NIC +usb:v413CpA102* + ID_NET_NAME_FROM_DATABASE=idrac diff --git a/hwdb.d/20-pci-classes.hwdb b/hwdb.d/20-pci-classes.hwdb new file mode 100644 index 00000000..b81fa2c3 --- /dev/null +++ b/hwdb.d/20-pci-classes.hwdb @@ -0,0 +1,600 @@ +# This file is part of systemd. +# +# Data imported from: http://pci-ids.ucw.cz/v2.2/pci.ids + +pci:v*d*sv*sd*bc00* + ID_PCI_CLASS_FROM_DATABASE=Unclassified device + +pci:v*d*sv*sd*bc00sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=Non-VGA unclassified device + +pci:v*d*sv*sd*bc00sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=VGA compatible unclassified device + +pci:v*d*sv*sd*bc01* + ID_PCI_CLASS_FROM_DATABASE=Mass storage controller + +pci:v*d*sv*sd*bc01sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=SCSI storage controller + +pci:v*d*sv*sd*bc01sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=IDE interface + +pci:v*d*sv*sd*bc01sc01i00* + ID_PCI_INTERFACE_FROM_DATABASE=ISA Compatibility mode-only controller + +pci:v*d*sv*sd*bc01sc01i05* + ID_PCI_INTERFACE_FROM_DATABASE=PCI native mode-only controller + +pci:v*d*sv*sd*bc01sc01i0A* + ID_PCI_INTERFACE_FROM_DATABASE=ISA Compatibility mode controller, supports both channels switched to PCI native mode + +pci:v*d*sv*sd*bc01sc01i0F* + ID_PCI_INTERFACE_FROM_DATABASE=PCI native mode controller, supports both channels switched to ISA compatibility mode + +pci:v*d*sv*sd*bc01sc01i80* + ID_PCI_INTERFACE_FROM_DATABASE=ISA Compatibility mode-only controller, supports bus mastering + +pci:v*d*sv*sd*bc01sc01i85* + ID_PCI_INTERFACE_FROM_DATABASE=PCI native mode-only controller, supports bus mastering + +pci:v*d*sv*sd*bc01sc01i8A* + ID_PCI_INTERFACE_FROM_DATABASE=ISA Compatibility mode controller, supports both channels switched to PCI native mode, supports bus mastering + +pci:v*d*sv*sd*bc01sc01i8F* + ID_PCI_INTERFACE_FROM_DATABASE=PCI native mode controller, supports both channels switched to ISA compatibility mode, supports bus mastering + +pci:v*d*sv*sd*bc01sc02* + ID_PCI_SUBCLASS_FROM_DATABASE=Floppy disk controller + +pci:v*d*sv*sd*bc01sc03* + ID_PCI_SUBCLASS_FROM_DATABASE=IPI bus controller + +pci:v*d*sv*sd*bc01sc04* + ID_PCI_SUBCLASS_FROM_DATABASE=RAID bus controller + +pci:v*d*sv*sd*bc01sc05* + ID_PCI_SUBCLASS_FROM_DATABASE=ATA controller + +pci:v*d*sv*sd*bc01sc05i20* + ID_PCI_INTERFACE_FROM_DATABASE=ADMA single stepping + +pci:v*d*sv*sd*bc01sc05i30* + ID_PCI_INTERFACE_FROM_DATABASE=ADMA continuous operation + +pci:v*d*sv*sd*bc01sc06* + ID_PCI_SUBCLASS_FROM_DATABASE=SATA controller + +pci:v*d*sv*sd*bc01sc06i00* + ID_PCI_INTERFACE_FROM_DATABASE=Vendor specific + +pci:v*d*sv*sd*bc01sc06i01* + ID_PCI_INTERFACE_FROM_DATABASE=AHCI 1.0 + +pci:v*d*sv*sd*bc01sc06i02* + ID_PCI_INTERFACE_FROM_DATABASE=Serial Storage Bus + +pci:v*d*sv*sd*bc01sc07* + ID_PCI_SUBCLASS_FROM_DATABASE=Serial Attached SCSI controller + +pci:v*d*sv*sd*bc01sc07i01* + ID_PCI_INTERFACE_FROM_DATABASE=Serial Storage Bus + +pci:v*d*sv*sd*bc01sc08* + ID_PCI_SUBCLASS_FROM_DATABASE=Non-Volatile memory controller + +pci:v*d*sv*sd*bc01sc08i01* + ID_PCI_INTERFACE_FROM_DATABASE=NVMHCI + +pci:v*d*sv*sd*bc01sc08i02* + ID_PCI_INTERFACE_FROM_DATABASE=NVM Express + +pci:v*d*sv*sd*bc01sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Mass storage controller + +pci:v*d*sv*sd*bc02* + ID_PCI_CLASS_FROM_DATABASE=Network controller + +pci:v*d*sv*sd*bc02sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controller + +pci:v*d*sv*sd*bc02sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=Token ring network controller + +pci:v*d*sv*sd*bc02sc02* + ID_PCI_SUBCLASS_FROM_DATABASE=FDDI network controller + +pci:v*d*sv*sd*bc02sc03* + ID_PCI_SUBCLASS_FROM_DATABASE=ATM network controller + +pci:v*d*sv*sd*bc02sc04* + ID_PCI_SUBCLASS_FROM_DATABASE=ISDN controller + +pci:v*d*sv*sd*bc02sc05* + ID_PCI_SUBCLASS_FROM_DATABASE=WorldFip controller + +pci:v*d*sv*sd*bc02sc06* + ID_PCI_SUBCLASS_FROM_DATABASE=PICMG controller + +pci:v*d*sv*sd*bc02sc07* + ID_PCI_SUBCLASS_FROM_DATABASE=Infiniband controller + +pci:v*d*sv*sd*bc02sc08* + ID_PCI_SUBCLASS_FROM_DATABASE=Fabric controller + +pci:v*d*sv*sd*bc02sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Network controller + +pci:v*d*sv*sd*bc03* + ID_PCI_CLASS_FROM_DATABASE=Display controller + +pci:v*d*sv*sd*bc03sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=VGA compatible controller + +pci:v*d*sv*sd*bc03sc00i00* + ID_PCI_INTERFACE_FROM_DATABASE=VGA controller + +pci:v*d*sv*sd*bc03sc00i01* + ID_PCI_INTERFACE_FROM_DATABASE=8514 controller + +pci:v*d*sv*sd*bc03sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=XGA compatible controller + +pci:v*d*sv*sd*bc03sc02* + ID_PCI_SUBCLASS_FROM_DATABASE=3D controller + +pci:v*d*sv*sd*bc03sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Display controller + +pci:v*d*sv*sd*bc04* + ID_PCI_CLASS_FROM_DATABASE=Multimedia controller + +pci:v*d*sv*sd*bc04sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=Multimedia video controller + +pci:v*d*sv*sd*bc04sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=Multimedia audio controller + +pci:v*d*sv*sd*bc04sc02* + ID_PCI_SUBCLASS_FROM_DATABASE=Computer telephony device + +pci:v*d*sv*sd*bc04sc03* + ID_PCI_SUBCLASS_FROM_DATABASE=Audio device + +pci:v*d*sv*sd*bc04sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Multimedia controller + +pci:v*d*sv*sd*bc05* + ID_PCI_CLASS_FROM_DATABASE=Memory controller + +pci:v*d*sv*sd*bc05sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=RAM memory + +pci:v*d*sv*sd*bc05sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=FLASH memory + +pci:v*d*sv*sd*bc05sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Memory controller + +pci:v*d*sv*sd*bc06* + ID_PCI_CLASS_FROM_DATABASE=Bridge + +pci:v*d*sv*sd*bc06sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=Host bridge + +pci:v*d*sv*sd*bc06sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=ISA bridge + +pci:v*d*sv*sd*bc06sc02* + ID_PCI_SUBCLASS_FROM_DATABASE=EISA bridge + +pci:v*d*sv*sd*bc06sc03* + ID_PCI_SUBCLASS_FROM_DATABASE=MicroChannel bridge + +pci:v*d*sv*sd*bc06sc04* + ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge + +pci:v*d*sv*sd*bc06sc04i00* + ID_PCI_INTERFACE_FROM_DATABASE=Normal decode + +pci:v*d*sv*sd*bc06sc04i01* + ID_PCI_INTERFACE_FROM_DATABASE=Subtractive decode + +pci:v*d*sv*sd*bc06sc05* + ID_PCI_SUBCLASS_FROM_DATABASE=PCMCIA bridge + +pci:v*d*sv*sd*bc06sc06* + ID_PCI_SUBCLASS_FROM_DATABASE=NuBus bridge + +pci:v*d*sv*sd*bc06sc07* + ID_PCI_SUBCLASS_FROM_DATABASE=CardBus bridge + +pci:v*d*sv*sd*bc06sc08* + ID_PCI_SUBCLASS_FROM_DATABASE=RACEway bridge + +pci:v*d*sv*sd*bc06sc08i00* + ID_PCI_INTERFACE_FROM_DATABASE=Transparent mode + +pci:v*d*sv*sd*bc06sc08i01* + ID_PCI_INTERFACE_FROM_DATABASE=Endpoint mode + +pci:v*d*sv*sd*bc06sc09* + ID_PCI_SUBCLASS_FROM_DATABASE=Semi-transparent PCI-to-PCI bridge + +pci:v*d*sv*sd*bc06sc09i40* + ID_PCI_INTERFACE_FROM_DATABASE=Primary bus towards host CPU + +pci:v*d*sv*sd*bc06sc09i80* + ID_PCI_INTERFACE_FROM_DATABASE=Secondary bus towards host CPU + +pci:v*d*sv*sd*bc06sc0A* + ID_PCI_SUBCLASS_FROM_DATABASE=InfiniBand to PCI host bridge + +pci:v*d*sv*sd*bc06sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Bridge + +pci:v*d*sv*sd*bc07* + ID_PCI_CLASS_FROM_DATABASE=Communication controller + +pci:v*d*sv*sd*bc07sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=Serial controller + +pci:v*d*sv*sd*bc07sc00i00* + ID_PCI_INTERFACE_FROM_DATABASE=8250 + +pci:v*d*sv*sd*bc07sc00i01* + ID_PCI_INTERFACE_FROM_DATABASE=16450 + +pci:v*d*sv*sd*bc07sc00i02* + ID_PCI_INTERFACE_FROM_DATABASE=16550 + +pci:v*d*sv*sd*bc07sc00i03* + ID_PCI_INTERFACE_FROM_DATABASE=16650 + +pci:v*d*sv*sd*bc07sc00i04* + ID_PCI_INTERFACE_FROM_DATABASE=16750 + +pci:v*d*sv*sd*bc07sc00i05* + ID_PCI_INTERFACE_FROM_DATABASE=16850 + +pci:v*d*sv*sd*bc07sc00i06* + ID_PCI_INTERFACE_FROM_DATABASE=16950 + +pci:v*d*sv*sd*bc07sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=Parallel controller + +pci:v*d*sv*sd*bc07sc01i00* + ID_PCI_INTERFACE_FROM_DATABASE=SPP + +pci:v*d*sv*sd*bc07sc01i01* + ID_PCI_INTERFACE_FROM_DATABASE=BiDir + +pci:v*d*sv*sd*bc07sc01i02* + ID_PCI_INTERFACE_FROM_DATABASE=ECP + +pci:v*d*sv*sd*bc07sc01i03* + ID_PCI_INTERFACE_FROM_DATABASE=IEEE1284 + +pci:v*d*sv*sd*bc07sc01iFE* + ID_PCI_INTERFACE_FROM_DATABASE=IEEE1284 Target + +pci:v*d*sv*sd*bc07sc02* + ID_PCI_SUBCLASS_FROM_DATABASE=Multiport serial controller + +pci:v*d*sv*sd*bc07sc03* + ID_PCI_SUBCLASS_FROM_DATABASE=Modem + +pci:v*d*sv*sd*bc07sc03i00* + ID_PCI_INTERFACE_FROM_DATABASE=Generic + +pci:v*d*sv*sd*bc07sc03i01* + ID_PCI_INTERFACE_FROM_DATABASE=Hayes/16450 + +pci:v*d*sv*sd*bc07sc03i02* + ID_PCI_INTERFACE_FROM_DATABASE=Hayes/16550 + +pci:v*d*sv*sd*bc07sc03i03* + ID_PCI_INTERFACE_FROM_DATABASE=Hayes/16650 + +pci:v*d*sv*sd*bc07sc03i04* + ID_PCI_INTERFACE_FROM_DATABASE=Hayes/16750 + +pci:v*d*sv*sd*bc07sc04* + ID_PCI_SUBCLASS_FROM_DATABASE=GPIB controller + +pci:v*d*sv*sd*bc07sc05* + ID_PCI_SUBCLASS_FROM_DATABASE=Smard Card controller + +pci:v*d*sv*sd*bc07sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Communication controller + +pci:v*d*sv*sd*bc08* + ID_PCI_CLASS_FROM_DATABASE=Generic system peripheral + +pci:v*d*sv*sd*bc08sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=PIC + +pci:v*d*sv*sd*bc08sc00i00* + ID_PCI_INTERFACE_FROM_DATABASE=8259 + +pci:v*d*sv*sd*bc08sc00i01* + ID_PCI_INTERFACE_FROM_DATABASE=ISA PIC + +pci:v*d*sv*sd*bc08sc00i02* + ID_PCI_INTERFACE_FROM_DATABASE=EISA PIC + +pci:v*d*sv*sd*bc08sc00i10* + ID_PCI_INTERFACE_FROM_DATABASE=IO-APIC + +pci:v*d*sv*sd*bc08sc00i20* + ID_PCI_INTERFACE_FROM_DATABASE=IO(X)-APIC + +pci:v*d*sv*sd*bc08sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=DMA controller + +pci:v*d*sv*sd*bc08sc01i00* + ID_PCI_INTERFACE_FROM_DATABASE=8237 + +pci:v*d*sv*sd*bc08sc01i01* + ID_PCI_INTERFACE_FROM_DATABASE=ISA DMA + +pci:v*d*sv*sd*bc08sc01i02* + ID_PCI_INTERFACE_FROM_DATABASE=EISA DMA + +pci:v*d*sv*sd*bc08sc02* + ID_PCI_SUBCLASS_FROM_DATABASE=Timer + +pci:v*d*sv*sd*bc08sc02i00* + ID_PCI_INTERFACE_FROM_DATABASE=8254 + +pci:v*d*sv*sd*bc08sc02i01* + ID_PCI_INTERFACE_FROM_DATABASE=ISA Timer + +pci:v*d*sv*sd*bc08sc02i02* + ID_PCI_INTERFACE_FROM_DATABASE=EISA Timers + +pci:v*d*sv*sd*bc08sc02i03* + ID_PCI_INTERFACE_FROM_DATABASE=HPET + +pci:v*d*sv*sd*bc08sc03* + ID_PCI_SUBCLASS_FROM_DATABASE=RTC + +pci:v*d*sv*sd*bc08sc03i00* + ID_PCI_INTERFACE_FROM_DATABASE=Generic + +pci:v*d*sv*sd*bc08sc03i01* + ID_PCI_INTERFACE_FROM_DATABASE=ISA RTC + +pci:v*d*sv*sd*bc08sc04* + ID_PCI_SUBCLASS_FROM_DATABASE=PCI Hot-plug controller + +pci:v*d*sv*sd*bc08sc05* + ID_PCI_SUBCLASS_FROM_DATABASE=SD Host controller + +pci:v*d*sv*sd*bc08sc06* + ID_PCI_SUBCLASS_FROM_DATABASE=IOMMU + +pci:v*d*sv*sd*bc08sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=System peripheral + +pci:v*d*sv*sd*bc09* + ID_PCI_CLASS_FROM_DATABASE=Input device controller + +pci:v*d*sv*sd*bc09sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=Keyboard controller + +pci:v*d*sv*sd*bc09sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=Digitizer Pen + +pci:v*d*sv*sd*bc09sc02* + ID_PCI_SUBCLASS_FROM_DATABASE=Mouse controller + +pci:v*d*sv*sd*bc09sc03* + ID_PCI_SUBCLASS_FROM_DATABASE=Scanner controller + +pci:v*d*sv*sd*bc09sc04* + ID_PCI_SUBCLASS_FROM_DATABASE=Gameport controller + +pci:v*d*sv*sd*bc09sc04i00* + ID_PCI_INTERFACE_FROM_DATABASE=Generic + +pci:v*d*sv*sd*bc09sc04i10* + ID_PCI_INTERFACE_FROM_DATABASE=Extended + +pci:v*d*sv*sd*bc09sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Input device controller + +pci:v*d*sv*sd*bc0A* + ID_PCI_CLASS_FROM_DATABASE=Docking station + +pci:v*d*sv*sd*bc0Asc00* + ID_PCI_SUBCLASS_FROM_DATABASE=Generic Docking Station + +pci:v*d*sv*sd*bc0Asc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Docking Station + +pci:v*d*sv*sd*bc0B* + ID_PCI_CLASS_FROM_DATABASE=Processor + +pci:v*d*sv*sd*bc0Bsc00* + ID_PCI_SUBCLASS_FROM_DATABASE=386 + +pci:v*d*sv*sd*bc0Bsc01* + ID_PCI_SUBCLASS_FROM_DATABASE=486 + +pci:v*d*sv*sd*bc0Bsc02* + ID_PCI_SUBCLASS_FROM_DATABASE=Pentium + +pci:v*d*sv*sd*bc0Bsc10* + ID_PCI_SUBCLASS_FROM_DATABASE=Alpha + +pci:v*d*sv*sd*bc0Bsc20* + ID_PCI_SUBCLASS_FROM_DATABASE=Power PC + +pci:v*d*sv*sd*bc0Bsc30* + ID_PCI_SUBCLASS_FROM_DATABASE=MIPS + +pci:v*d*sv*sd*bc0Bsc40* + ID_PCI_SUBCLASS_FROM_DATABASE=Co-processor + +pci:v*d*sv*sd*bc0C* + ID_PCI_CLASS_FROM_DATABASE=Serial bus controller + +pci:v*d*sv*sd*bc0Csc00* + ID_PCI_SUBCLASS_FROM_DATABASE=FireWire (IEEE 1394) + +pci:v*d*sv*sd*bc0Csc00i00* + ID_PCI_INTERFACE_FROM_DATABASE=Generic + +pci:v*d*sv*sd*bc0Csc00i10* + ID_PCI_INTERFACE_FROM_DATABASE=OHCI + +pci:v*d*sv*sd*bc0Csc01* + ID_PCI_SUBCLASS_FROM_DATABASE=ACCESS Bus + +pci:v*d*sv*sd*bc0Csc02* + ID_PCI_SUBCLASS_FROM_DATABASE=SSA + +pci:v*d*sv*sd*bc0Csc03* + ID_PCI_SUBCLASS_FROM_DATABASE=USB controller + +pci:v*d*sv*sd*bc0Csc03i00* + ID_PCI_INTERFACE_FROM_DATABASE=UHCI + +pci:v*d*sv*sd*bc0Csc03i10* + ID_PCI_INTERFACE_FROM_DATABASE=OHCI + +pci:v*d*sv*sd*bc0Csc03i20* + ID_PCI_INTERFACE_FROM_DATABASE=EHCI + +pci:v*d*sv*sd*bc0Csc03i30* + ID_PCI_INTERFACE_FROM_DATABASE=XHCI + +pci:v*d*sv*sd*bc0Csc03i80* + ID_PCI_INTERFACE_FROM_DATABASE=Unspecified + +pci:v*d*sv*sd*bc0Csc03iFE* + ID_PCI_INTERFACE_FROM_DATABASE=USB Device + +pci:v*d*sv*sd*bc0Csc04* + ID_PCI_SUBCLASS_FROM_DATABASE=Fibre Channel + +pci:v*d*sv*sd*bc0Csc05* + ID_PCI_SUBCLASS_FROM_DATABASE=SMBus + +pci:v*d*sv*sd*bc0Csc06* + ID_PCI_SUBCLASS_FROM_DATABASE=InfiniBand + +pci:v*d*sv*sd*bc0Csc07* + ID_PCI_SUBCLASS_FROM_DATABASE=IPMI Interface + +pci:v*d*sv*sd*bc0Csc07i00* + ID_PCI_INTERFACE_FROM_DATABASE=SMIC + +pci:v*d*sv*sd*bc0Csc07i01* + ID_PCI_INTERFACE_FROM_DATABASE=KCS + +pci:v*d*sv*sd*bc0Csc07i02* + ID_PCI_INTERFACE_FROM_DATABASE=BT (Block Transfer) + +pci:v*d*sv*sd*bc0Csc08* + ID_PCI_SUBCLASS_FROM_DATABASE=SERCOS interface + +pci:v*d*sv*sd*bc0Csc09* + ID_PCI_SUBCLASS_FROM_DATABASE=CANBUS + +pci:v*d*sv*sd*bc0D* + ID_PCI_CLASS_FROM_DATABASE=Wireless controller + +pci:v*d*sv*sd*bc0Dsc00* + ID_PCI_SUBCLASS_FROM_DATABASE=IRDA controller + +pci:v*d*sv*sd*bc0Dsc01* + ID_PCI_SUBCLASS_FROM_DATABASE=Consumer IR controller + +pci:v*d*sv*sd*bc0Dsc10* + ID_PCI_SUBCLASS_FROM_DATABASE=RF controller + +pci:v*d*sv*sd*bc0Dsc11* + ID_PCI_SUBCLASS_FROM_DATABASE=Bluetooth + +pci:v*d*sv*sd*bc0Dsc12* + ID_PCI_SUBCLASS_FROM_DATABASE=Broadband + +pci:v*d*sv*sd*bc0Dsc20* + ID_PCI_SUBCLASS_FROM_DATABASE=802.1a controller + +pci:v*d*sv*sd*bc0Dsc21* + ID_PCI_SUBCLASS_FROM_DATABASE=802.1b controller + +pci:v*d*sv*sd*bc0Dsc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Wireless controller + +pci:v*d*sv*sd*bc0E* + ID_PCI_CLASS_FROM_DATABASE=Intelligent controller + +pci:v*d*sv*sd*bc0Esc00* + ID_PCI_SUBCLASS_FROM_DATABASE=I2O + +pci:v*d*sv*sd*bc0F* + ID_PCI_CLASS_FROM_DATABASE=Satellite communications controller + +pci:v*d*sv*sd*bc0Fsc01* + ID_PCI_SUBCLASS_FROM_DATABASE=Satellite TV controller + +pci:v*d*sv*sd*bc0Fsc02* + ID_PCI_SUBCLASS_FROM_DATABASE=Satellite audio communication controller + +pci:v*d*sv*sd*bc0Fsc03* + ID_PCI_SUBCLASS_FROM_DATABASE=Satellite voice communication controller + +pci:v*d*sv*sd*bc0Fsc04* + ID_PCI_SUBCLASS_FROM_DATABASE=Satellite data communication controller + +pci:v*d*sv*sd*bc10* + ID_PCI_CLASS_FROM_DATABASE=Encryption controller + +pci:v*d*sv*sd*bc10sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=Network and computing encryption device + +pci:v*d*sv*sd*bc10sc10* + ID_PCI_SUBCLASS_FROM_DATABASE=Entertainment encryption device + +pci:v*d*sv*sd*bc10sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Encryption controller + +pci:v*d*sv*sd*bc11* + ID_PCI_CLASS_FROM_DATABASE=Signal processing controller + +pci:v*d*sv*sd*bc11sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=DPIO module + +pci:v*d*sv*sd*bc11sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=Performance counters + +pci:v*d*sv*sd*bc11sc10* + ID_PCI_SUBCLASS_FROM_DATABASE=Communication synchronizer + +pci:v*d*sv*sd*bc11sc20* + ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing management + +pci:v*d*sv*sd*bc11sc80* + ID_PCI_SUBCLASS_FROM_DATABASE=Signal processing controller + +pci:v*d*sv*sd*bc12* + ID_PCI_CLASS_FROM_DATABASE=Processing accelerators + +pci:v*d*sv*sd*bc12sc00* + ID_PCI_SUBCLASS_FROM_DATABASE=Processing accelerators + +pci:v*d*sv*sd*bc12sc01* + ID_PCI_SUBCLASS_FROM_DATABASE=AI Inference Accelerator + +pci:v*d*sv*sd*bc13* + ID_PCI_CLASS_FROM_DATABASE=Non-Essential Instrumentation + +pci:v*d*sv*sd*bc40* + ID_PCI_CLASS_FROM_DATABASE=Coprocessor + +pci:v*d*sv*sd*bcFF* + ID_PCI_CLASS_FROM_DATABASE=Unassigned class diff --git a/hwdb.d/20-pci-vendor-model.hwdb b/hwdb.d/20-pci-vendor-model.hwdb new file mode 100644 index 00000000..495ebb5c --- /dev/null +++ b/hwdb.d/20-pci-vendor-model.hwdb @@ -0,0 +1,95073 @@ +# This file is part of systemd. +# +# Data imported from: http://pci-ids.ucw.cz/v2.2/pci.ids + +pci:v00000001* + ID_VENDOR_FROM_DATABASE=SafeNet (wrong ID) + +pci:v00000010* + ID_VENDOR_FROM_DATABASE=Allied Telesis, Inc (Wrong ID) + +pci:v00000010d00008139* + ID_MODEL_FROM_DATABASE=AT-2500TX V3 Ethernet + +pci:v00000014* + ID_VENDOR_FROM_DATABASE=Loongson Technology LLC + +pci:v00000014d00007A00* + ID_MODEL_FROM_DATABASE=Hyper Transport Bridge Controller + +pci:v00000014d00007A02* + ID_MODEL_FROM_DATABASE=APB (Advanced Peripheral Bus) Controller + +pci:v00000014d00007A03* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Controller + +pci:v00000014d00007A04* + ID_MODEL_FROM_DATABASE=OTG USB Controller + +pci:v00000014d00007A05* + ID_MODEL_FROM_DATABASE=Vivante GPU (Graphics Processing Unit) + +pci:v00000014d00007A06* + ID_MODEL_FROM_DATABASE=DC (Display Controller) + +pci:v00000014d00007A07* + ID_MODEL_FROM_DATABASE=HDA (High Definition Audio) Controller + +pci:v00000014d00007A08* + ID_MODEL_FROM_DATABASE=SATA AHCI Controller + +pci:v00000014d00007A09* + ID_MODEL_FROM_DATABASE=PCI-to-PCI Bridge + +pci:v00000014d00007A0B* + ID_MODEL_FROM_DATABASE=SPI Controller + +pci:v00000014d00007A0C* + ID_MODEL_FROM_DATABASE=LPC Controller + +pci:v00000014d00007A0F* + ID_MODEL_FROM_DATABASE=DMA (Direct Memory Access) Controller + +pci:v00000014d00007A14* + ID_MODEL_FROM_DATABASE=EHCI USB Controller + +pci:v00000014d00007A15* + ID_MODEL_FROM_DATABASE=Vivante GPU (Graphics Processing Unit) + +pci:v00000014d00007A19* + ID_MODEL_FROM_DATABASE=PCI-to-PCI Bridge + +pci:v00000014d00007A24* + ID_MODEL_FROM_DATABASE=OHCI USB Controller + +pci:v00000014d00007A29* + ID_MODEL_FROM_DATABASE=PCI-to-PCI Bridge + +pci:v0000001C* + ID_VENDOR_FROM_DATABASE=PEAK-System Technik GmbH + +pci:v0000001Cd00000001* + ID_MODEL_FROM_DATABASE=PCAN-PCI CAN-Bus controller + +pci:v0000001Cd00000001sv0000001Csd00000004* + ID_MODEL_FROM_DATABASE=PCAN-PCI CAN-Bus controller (2 Channel CAN Bus SJC1000) + +pci:v0000001Cd00000001sv0000001Csd00000005* + ID_MODEL_FROM_DATABASE=PCAN-PCI CAN-Bus controller (2 Channel CAN Bus SJC1000 (Optically Isolated)) + +pci:v0000003D* + ID_VENDOR_FROM_DATABASE=Lockheed Martin-Marietta Corp + +pci:v00000059* + ID_VENDOR_FROM_DATABASE=Tiger Jet Network Inc. (Wrong ID) + +pci:v00000070* + ID_VENDOR_FROM_DATABASE=Hauppauge computer works Inc. + +pci:v00000070d00007801* + ID_MODEL_FROM_DATABASE=WinTV HVR-1800 MCE + +pci:v00000071* + ID_VENDOR_FROM_DATABASE=Nebula Electronics Ltd. + +pci:v00000095* + ID_VENDOR_FROM_DATABASE=Silicon Image, Inc. (Wrong ID) + +pci:v00000095d00000680* + ID_MODEL_FROM_DATABASE=Ultra ATA/133 IDE RAID CONTROLLER CARD + +pci:v000000A7* + ID_VENDOR_FROM_DATABASE=Teles AG (Wrong ID) + +pci:v00000100* + ID_VENDOR_FROM_DATABASE=nCipher Security + +pci:v00000123* + ID_VENDOR_FROM_DATABASE=General Dynamics + +pci:v00000128* + ID_VENDOR_FROM_DATABASE=Dell (wrong ID) + +pci:v0000018A* + ID_VENDOR_FROM_DATABASE=LevelOne + +pci:v0000018Ad00000106* + ID_MODEL_FROM_DATABASE=FPC-0106TX misprogrammed [RTL81xx] + +pci:v0000021B* + ID_VENDOR_FROM_DATABASE=Compaq Computer Corporation + +pci:v0000021Bd00008139* + ID_MODEL_FROM_DATABASE=HNE-300 (RealTek RTL8139c) [iPaq Networking] + +pci:v00000270* + ID_VENDOR_FROM_DATABASE=Hauppauge computer works Inc. (Wrong ID) + +pci:v00000291* + ID_VENDOR_FROM_DATABASE=Davicom Semiconductor, Inc. (Wrong ID) + +pci:v000002AC* + ID_VENDOR_FROM_DATABASE=SpeedStream + +pci:v000002ACd00001012* + ID_MODEL_FROM_DATABASE=1012 PCMCIA 10/100 Ethernet Card [RTL81xx] + +pci:v000002E0* + ID_VENDOR_FROM_DATABASE=XFX Pine Group Inc. (Wrong ID) + +pci:v00000303* + ID_VENDOR_FROM_DATABASE=Hewlett-Packard Company (Wrong ID) + +pci:v00000308* + ID_VENDOR_FROM_DATABASE=ZyXEL Communications Corporation (Wrong ID) + +pci:v00000315* + ID_VENDOR_FROM_DATABASE=SK-Electronics Co., Ltd. + +pci:v00000357* + ID_VENDOR_FROM_DATABASE=TTTech Computertechnik AG (Wrong ID) + +pci:v00000357d0000000A* + ID_MODEL_FROM_DATABASE=TTP-Monitoring Card V2.0 + +pci:v00000432* + ID_VENDOR_FROM_DATABASE=SCM Microsystems, Inc. + +pci:v00000432d00000001* + ID_MODEL_FROM_DATABASE=Pluto2 DVB-T Receiver for PCMCIA [EasyWatch MobilSet] + +pci:v00000497* + ID_VENDOR_FROM_DATABASE=Dell Inc. (wrong ID) + +pci:v00000675* + ID_VENDOR_FROM_DATABASE=Dynalink + +pci:v00000675d00001700* + ID_MODEL_FROM_DATABASE=IS64PH ISDN Adapter + +pci:v00000675d00001702* + ID_MODEL_FROM_DATABASE=IS64PH ISDN Adapter + +pci:v00000675d00001703* + ID_MODEL_FROM_DATABASE=ISDN Adapter (PCI Bus, DV, W) + +pci:v00000675d00001704* + ID_MODEL_FROM_DATABASE=ISDN Adapter (PCI Bus, D, C) + +pci:v00000721* + ID_VENDOR_FROM_DATABASE=Sapphire, Inc. + +pci:v00000777* + ID_VENDOR_FROM_DATABASE=Ubiquiti Networks, Inc. + +pci:v00000795* + ID_VENDOR_FROM_DATABASE=Wired Inc. + +pci:v00000795d00006663* + ID_MODEL_FROM_DATABASE=Butane II (MPEG2 encoder board) + +pci:v00000795d00006666* + ID_MODEL_FROM_DATABASE=MediaPress (MPEG2 encoder board) + +pci:v000007D1* + ID_VENDOR_FROM_DATABASE=D-Link System Inc + +pci:v00000824* + ID_VENDOR_FROM_DATABASE=T1042 [Freescale] + +pci:v00000925* + ID_VENDOR_FROM_DATABASE=VIA Technologies, Inc. (Wrong ID) + +pci:v00000A89* + ID_VENDOR_FROM_DATABASE=BREA Technologies Inc + +pci:v00000B0B* + ID_VENDOR_FROM_DATABASE=Rhino Equipment Corp. + +pci:v00000B0Bd00000105* + ID_MODEL_FROM_DATABASE=R1T1 + +pci:v00000B0Bd00000205* + ID_MODEL_FROM_DATABASE=R4FXO + +pci:v00000B0Bd00000206* + ID_MODEL_FROM_DATABASE=RCB4FXO 4-channel FXO analog telephony card + +pci:v00000B0Bd00000305* + ID_MODEL_FROM_DATABASE=R4T1 + +pci:v00000B0Bd00000405* + ID_MODEL_FROM_DATABASE=R8FXX + +pci:v00000B0Bd00000406* + ID_MODEL_FROM_DATABASE=RCB8FXX 8-channel modular analog telephony card + +pci:v00000B0Bd00000505* + ID_MODEL_FROM_DATABASE=R24FXX + +pci:v00000B0Bd00000506* + ID_MODEL_FROM_DATABASE=RCB24FXS 24-Channel FXS analog telephony card + +pci:v00000B0Bd00000605* + ID_MODEL_FROM_DATABASE=R2T1 + +pci:v00000B0Bd00000705* + ID_MODEL_FROM_DATABASE=R24FXS + +pci:v00000B0Bd00000706* + ID_MODEL_FROM_DATABASE=RCB24FXO 24-Channel FXO analog telephony card + +pci:v00000B0Bd00000905* + ID_MODEL_FROM_DATABASE=R1T3 Single T3 Digital Telephony Card + +pci:v00000B0Bd00000906* + ID_MODEL_FROM_DATABASE=RCB24FXX 24-channel modular analog telephony card + +pci:v00000B0Bd00000A06* + ID_MODEL_FROM_DATABASE=RCB672FXX 672-channel modular analog telephony card + +pci:v00000E11* + ID_VENDOR_FROM_DATABASE=Compaq Computer Corporation + +pci:v00000E11d00000001* + ID_MODEL_FROM_DATABASE=PCI to EISA Bridge + +pci:v00000E11d00000002* + ID_MODEL_FROM_DATABASE=PCI to ISA Bridge + +pci:v00000E11d00000046* + ID_MODEL_FROM_DATABASE=Smart Array 64xx + +pci:v00000E11d00000046sv00000E11sd00004091* + ID_MODEL_FROM_DATABASE=Smart Array 64xx (Smart Array 6i) + +pci:v00000E11d00000046sv00000E11sd0000409A* + ID_MODEL_FROM_DATABASE=Smart Array 64xx (Smart Array 641) + +pci:v00000E11d00000046sv00000E11sd0000409B* + ID_MODEL_FROM_DATABASE=Smart Array 64xx (Smart Array 642) + +pci:v00000E11d00000046sv00000E11sd0000409C* + ID_MODEL_FROM_DATABASE=Smart Array 64xx (Smart Array 6400) + +pci:v00000E11d00000046sv00000E11sd0000409D* + ID_MODEL_FROM_DATABASE=Smart Array 64xx (Smart Array 6400 EM) + +pci:v00000E11d00000049* + ID_MODEL_FROM_DATABASE=NC7132 Gigabit Upgrade Module + +pci:v00000E11d0000004A* + ID_MODEL_FROM_DATABASE=NC6136 Gigabit Server Adapter + +pci:v00000E11d0000005A* + ID_MODEL_FROM_DATABASE=Remote Insight II board - Lights-Out + +pci:v00000E11d0000007C* + ID_MODEL_FROM_DATABASE=NC7770 1000BaseTX + +pci:v00000E11d0000007D* + ID_MODEL_FROM_DATABASE=NC6770 1000BaseTX + +pci:v00000E11d00000085* + ID_MODEL_FROM_DATABASE=NC7780 1000BaseTX + +pci:v00000E11d000000B1* + ID_MODEL_FROM_DATABASE=Remote Insight II board - PCI device + +pci:v00000E11d000000BB* + ID_MODEL_FROM_DATABASE=NC7760 + +pci:v00000E11d000000CA* + ID_MODEL_FROM_DATABASE=NC7771 + +pci:v00000E11d000000CB* + ID_MODEL_FROM_DATABASE=NC7781 + +pci:v00000E11d000000CF* + ID_MODEL_FROM_DATABASE=NC7772 + +pci:v00000E11d000000D0* + ID_MODEL_FROM_DATABASE=NC7782 + +pci:v00000E11d000000D1* + ID_MODEL_FROM_DATABASE=NC7783 + +pci:v00000E11d000000E3* + ID_MODEL_FROM_DATABASE=NC7761 + +pci:v00000E11d00000508* + ID_MODEL_FROM_DATABASE=Netelligent 4/16 Token Ring + +pci:v00000E11d00001000* + ID_MODEL_FROM_DATABASE=Triflex/Pentium Bridge, Model 1000 + +pci:v00000E11d00002000* + ID_MODEL_FROM_DATABASE=Triflex/Pentium Bridge, Model 2000 + +pci:v00000E11d00003032* + ID_MODEL_FROM_DATABASE=QVision 1280/p + +pci:v00000E11d00003033* + ID_MODEL_FROM_DATABASE=QVision 1280/p + +pci:v00000E11d00003034* + ID_MODEL_FROM_DATABASE=QVision 1280/p + +pci:v00000E11d00004000* + ID_MODEL_FROM_DATABASE=4000 [Triflex] + +pci:v00000E11d00004040* + ID_MODEL_FROM_DATABASE=Integrated Array + +pci:v00000E11d00004048* + ID_MODEL_FROM_DATABASE=Compaq Raid LC2 + +pci:v00000E11d00004050* + ID_MODEL_FROM_DATABASE=Smart Array 4200 + +pci:v00000E11d00004051* + ID_MODEL_FROM_DATABASE=Smart Array 4250ES + +pci:v00000E11d00004058* + ID_MODEL_FROM_DATABASE=Smart Array 431 + +pci:v00000E11d00004070* + ID_MODEL_FROM_DATABASE=Smart Array 5300 + +pci:v00000E11d00004080* + ID_MODEL_FROM_DATABASE=Smart Array 5i + +pci:v00000E11d00004082* + ID_MODEL_FROM_DATABASE=Smart Array 532 + +pci:v00000E11d00004083* + ID_MODEL_FROM_DATABASE=Smart Array 5312 + +pci:v00000E11d00004091* + ID_MODEL_FROM_DATABASE=Smart Array 6i + +pci:v00000E11d0000409A* + ID_MODEL_FROM_DATABASE=Smart Array 641 + +pci:v00000E11d0000409B* + ID_MODEL_FROM_DATABASE=Smart Array 642 + +pci:v00000E11d0000409C* + ID_MODEL_FROM_DATABASE=Smart Array 6400 + +pci:v00000E11d0000409D* + ID_MODEL_FROM_DATABASE=Smart Array 6400 EM + +pci:v00000E11d00006010* + ID_MODEL_FROM_DATABASE=HotPlug PCI Bridge 6010 + +pci:v00000E11d00007020* + ID_MODEL_FROM_DATABASE=USB Controller + +pci:v00000E11d0000A0EC* + ID_MODEL_FROM_DATABASE=Fibre Channel Host Controller + +pci:v00000E11d0000A0F0* + ID_MODEL_FROM_DATABASE=Advanced System Management Controller + +pci:v00000E11d0000A0F0sv00000E11sd0000B0F3* + ID_MODEL_FROM_DATABASE=Advanced System Management Controller (ProLiant DL360) + +pci:v00000E11d0000A0F3* + ID_MODEL_FROM_DATABASE=Triflex PCI to ISA Bridge + +pci:v00000E11d0000A0F7* + ID_MODEL_FROM_DATABASE=PCI Hotplug Controller + +pci:v00000E11d0000A0F7sv00008086sd0000002A* + ID_MODEL_FROM_DATABASE=PCI Hotplug Controller (A) + +pci:v00000E11d0000A0F7sv00008086sd0000002B* + ID_MODEL_FROM_DATABASE=PCI Hotplug Controller (B) + +pci:v00000E11d0000A0F8* + ID_MODEL_FROM_DATABASE=ZFMicro Chipset USB + +pci:v00000E11d0000A0FC* + ID_MODEL_FROM_DATABASE=FibreChannel HBA Tachyon + +pci:v00000E11d0000AE10* + ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller + +pci:v00000E11d0000AE10sv00000E11sd00004030* + ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller (Smart-2/P Array Controller) + +pci:v00000E11d0000AE10sv00000E11sd00004031* + ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller (Smart-2SL Array Controller) + +pci:v00000E11d0000AE10sv00000E11sd00004032* + ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller (Smart Array 3200 Controller) + +pci:v00000E11d0000AE10sv00000E11sd00004033* + ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller (Smart Array 3100ES Controller) + +pci:v00000E11d0000AE10sv00000E11sd00004034* + ID_MODEL_FROM_DATABASE=Smart-2/P RAID Controller (Smart Array 221 Controller) + +pci:v00000E11d0000AE29* + ID_MODEL_FROM_DATABASE=MIS-L + +pci:v00000E11d0000AE2A* + ID_MODEL_FROM_DATABASE=MPC + +pci:v00000E11d0000AE2B* + ID_MODEL_FROM_DATABASE=MIS-E + +pci:v00000E11d0000AE31* + ID_MODEL_FROM_DATABASE=System Management Controller + +pci:v00000E11d0000AE32* + ID_MODEL_FROM_DATABASE=Netelligent 10/100 TX PCI UTP + +pci:v00000E11d0000AE33* + ID_MODEL_FROM_DATABASE=Triflex Dual EIDE Controller + +pci:v00000E11d0000AE34* + ID_MODEL_FROM_DATABASE=Netelligent 10 T PCI UTP + +pci:v00000E11d0000AE35* + ID_MODEL_FROM_DATABASE=Integrated NetFlex-3/P + +pci:v00000E11d0000AE40* + ID_MODEL_FROM_DATABASE=Netelligent Dual 10/100 TX PCI UTP + +pci:v00000E11d0000AE43* + ID_MODEL_FROM_DATABASE=Netelligent Integrated 10/100 TX UTP + +pci:v00000E11d0000AE69* + ID_MODEL_FROM_DATABASE=CETUS-L + +pci:v00000E11d0000AE6C* + ID_MODEL_FROM_DATABASE=Northstar + +pci:v00000E11d0000AE6D* + ID_MODEL_FROM_DATABASE=NorthStar CPU to PCI Bridge + +pci:v00000E11d0000B011* + ID_MODEL_FROM_DATABASE=Netelligent 10/100 TX Embedded UTP + +pci:v00000E11d0000B012* + ID_MODEL_FROM_DATABASE=Netelligent 10 T/2 PCI UTP/Coax + +pci:v00000E11d0000B01E* + ID_MODEL_FROM_DATABASE=NC3120 Fast Ethernet NIC + +pci:v00000E11d0000B01F* + ID_MODEL_FROM_DATABASE=NC3122 Fast Ethernet NIC + +pci:v00000E11d0000B02F* + ID_MODEL_FROM_DATABASE=NC1120 Ethernet NIC + +pci:v00000E11d0000B030* + ID_MODEL_FROM_DATABASE=Netelligent 10/100 TX UTP + +pci:v00000E11d0000B04A* + ID_MODEL_FROM_DATABASE=10/100 TX PCI Intel WOL UTP Controller + +pci:v00000E11d0000B060* + ID_MODEL_FROM_DATABASE=Smart Array 5300 Controller + +pci:v00000E11d0000B0C6* + ID_MODEL_FROM_DATABASE=NC3161 Fast Ethernet NIC + +pci:v00000E11d0000B0C7* + ID_MODEL_FROM_DATABASE=NC3160 Fast Ethernet NIC + +pci:v00000E11d0000B0D7* + ID_MODEL_FROM_DATABASE=NC3121 Fast Ethernet NIC + +pci:v00000E11d0000B0DD* + ID_MODEL_FROM_DATABASE=NC3131 Fast Ethernet NIC + +pci:v00000E11d0000B0DE* + ID_MODEL_FROM_DATABASE=NC3132 Fast Ethernet Module + +pci:v00000E11d0000B0DF* + ID_MODEL_FROM_DATABASE=NC6132 Gigabit Module + +pci:v00000E11d0000B0E0* + ID_MODEL_FROM_DATABASE=NC6133 Gigabit Module + +pci:v00000E11d0000B0E1* + ID_MODEL_FROM_DATABASE=NC3133 Fast Ethernet Module + +pci:v00000E11d0000B123* + ID_MODEL_FROM_DATABASE=NC6134 Gigabit NIC + +pci:v00000E11d0000B134* + ID_MODEL_FROM_DATABASE=NC3163 Fast Ethernet NIC + +pci:v00000E11d0000B13C* + ID_MODEL_FROM_DATABASE=NC3162 Fast Ethernet NIC + +pci:v00000E11d0000B144* + ID_MODEL_FROM_DATABASE=NC3123 Fast Ethernet NIC + +pci:v00000E11d0000B163* + ID_MODEL_FROM_DATABASE=NC3134 Fast Ethernet NIC + +pci:v00000E11d0000B164* + ID_MODEL_FROM_DATABASE=NC3165 Fast Ethernet Upgrade Module + +pci:v00000E11d0000B178* + ID_MODEL_FROM_DATABASE=Smart Array 5i/532 + +pci:v00000E11d0000B178sv00000E11sd00004080* + ID_MODEL_FROM_DATABASE=Smart Array 5i/532 (Smart Array 5i) + +pci:v00000E11d0000B178sv00000E11sd00004082* + ID_MODEL_FROM_DATABASE=Smart Array 5i/532 (Smart Array 532) + +pci:v00000E11d0000B178sv00000E11sd00004083* + ID_MODEL_FROM_DATABASE=Smart Array 5i/532 (Smart Array 5312) + +pci:v00000E11d0000B1A4* + ID_MODEL_FROM_DATABASE=NC7131 Gigabit Server Adapter + +pci:v00000E11d0000B200* + ID_MODEL_FROM_DATABASE=Memory Hot-Plug Controller + +pci:v00000E11d0000B203* + ID_MODEL_FROM_DATABASE=Integrated Lights Out Controller + +pci:v00000E11d0000B204* + ID_MODEL_FROM_DATABASE=Integrated Lights Out Processor + +pci:v00000E11d0000C000* + ID_MODEL_FROM_DATABASE=Remote Insight Lights-Out Edition + +pci:v00000E11d0000F130* + ID_MODEL_FROM_DATABASE=NetFlex-3/P ThunderLAN 1.0 + +pci:v00000E11d0000F150* + ID_MODEL_FROM_DATABASE=NetFlex-3/P ThunderLAN 2.3 + +pci:v00000E55* + ID_VENDOR_FROM_DATABASE=HaSoTec GmbH + +pci:v00000EAC* + ID_VENDOR_FROM_DATABASE=SHF Communication Technologies AG + +pci:v00000EACd00000008* + ID_MODEL_FROM_DATABASE=Ethernet Powerlink Managing Node 01 + +pci:v00000F62* + ID_VENDOR_FROM_DATABASE=Acrox Technologies Co., Ltd. + +pci:v00001000* + ID_VENDOR_FROM_DATABASE=Broadcom / LSI + +pci:v00001000d00000001* + ID_MODEL_FROM_DATABASE=53c810 + +pci:v00001000d00000001sv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53c810 (LSI53C810AE PCI to SCSI I/O Processor) + +pci:v00001000d00000002* + ID_MODEL_FROM_DATABASE=53c820 + +pci:v00001000d00000003* + ID_MODEL_FROM_DATABASE=53c825 + +pci:v00001000d00000003sv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53c825 (LSI53C825AE PCI to SCSI I/O Processor (Ultra Wide)) + +pci:v00001000d00000004* + ID_MODEL_FROM_DATABASE=53c815 + +pci:v00001000d00000005* + ID_MODEL_FROM_DATABASE=53c810AP + +pci:v00001000d00000006* + ID_MODEL_FROM_DATABASE=53c860 + +pci:v00001000d00000006sv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53c860 (LSI53C860E PCI to Ultra SCSI I/O Processor) + +pci:v00001000d0000000A* + ID_MODEL_FROM_DATABASE=53c1510 + +pci:v00001000d0000000Asv00000E11sd0000B143* + ID_MODEL_FROM_DATABASE=53c1510 (Integrated Dual Channel Wide Ultra2 SCSI Controller) + +pci:v00001000d0000000Asv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53c1510 (LSI53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Nonintelligent mode)) + +pci:v00001000d0000000B* + ID_MODEL_FROM_DATABASE=53C896/897 + +pci:v00001000d0000000Bsv00000E11sd00006004* + ID_MODEL_FROM_DATABASE=53C896/897 (EOB003 Series SCSI host adapter) + +pci:v00001000d0000000Bsv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53C896/897 (LSI53C896/7 PCI to Dual Channel Ultra2 SCSI Multifunction Controller) + +pci:v00001000d0000000Bsv00001000sd00001010* + ID_MODEL_FROM_DATABASE=53C896/897 (LSI22910 PCI to Dual Channel Ultra2 SCSI host adapter) + +pci:v00001000d0000000Bsv00001000sd00001020* + ID_MODEL_FROM_DATABASE=53C896/897 (LSI21002 PCI to Dual Channel Ultra2 SCSI host adapter) + +pci:v00001000d0000000Bsv000013E9sd00001000* + ID_MODEL_FROM_DATABASE=53C896/897 (6221L-4U (Dual U2W SCSI, dual 10/100TX, graphics)) + +pci:v00001000d0000000C* + ID_MODEL_FROM_DATABASE=53c895 + +pci:v00001000d0000000Csv00001000sd00001010* + ID_MODEL_FROM_DATABASE=53c895 (LSI8951U PCI to Ultra2 SCSI host adapter) + +pci:v00001000d0000000Csv00001000sd00001020* + ID_MODEL_FROM_DATABASE=53c895 (LSI8952U PCI to Ultra2 SCSI host adapter) + +pci:v00001000d0000000Csv00001DE1sd00003906* + ID_MODEL_FROM_DATABASE=53c895 (DC-390U2B SCSI adapter) + +pci:v00001000d0000000Csv00001DE1sd00003907* + ID_MODEL_FROM_DATABASE=53c895 (DC-390U2W) + +pci:v00001000d0000000D* + ID_MODEL_FROM_DATABASE=53c885 + +pci:v00001000d0000000F* + ID_MODEL_FROM_DATABASE=53c875 + +pci:v00001000d0000000Fsv00000E11sd00007004* + ID_MODEL_FROM_DATABASE=53c875 (Embedded Ultra Wide SCSI Controller) + +pci:v00001000d0000000Fsv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53c875 (LSI53C876/E PCI to Dual Channel SCSI Controller) + +pci:v00001000d0000000Fsv00001000sd00001010* + ID_MODEL_FROM_DATABASE=53c875 (LSI22801 PCI to Dual Channel Ultra SCSI host adapter) + +pci:v00001000d0000000Fsv00001000sd00001020* + ID_MODEL_FROM_DATABASE=53c875 (LSI22802 PCI to Dual Channel Ultra SCSI host adapter) + +pci:v00001000d0000000Fsv00001092sd00008760* + ID_MODEL_FROM_DATABASE=53c875 (FirePort 40 Dual SCSI Controller) + +pci:v00001000d0000000Fsv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=53c875 (V5D Single Board Computer Wide Ultra SCSI) + +pci:v00001000d0000000Fsv00001775sd000010D1* + ID_MODEL_FROM_DATABASE=53c875 (V5D Single Board Computer Ultra SCSI) + +pci:v00001000d0000000Fsv00001DE1sd00003904* + ID_MODEL_FROM_DATABASE=53c875 (DC390F/U Ultra Wide SCSI Adapter) + +pci:v00001000d0000000Fsv00004C53sd00001000* + ID_MODEL_FROM_DATABASE=53c875 (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) + +pci:v00001000d0000000Fsv00004C53sd00001050* + ID_MODEL_FROM_DATABASE=53c875 (CT7 mainboard) + +pci:v00001000d00000010* + ID_MODEL_FROM_DATABASE=53C1510 + +pci:v00001000d00000010sv00000E11sd00004040* + ID_MODEL_FROM_DATABASE=53C1510 (Integrated Smart Array Controller) + +pci:v00001000d00000010sv00000E11sd00004048* + ID_MODEL_FROM_DATABASE=53C1510 (RAID LC2 Controller) + +pci:v00001000d00000010sv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53C1510 (PCI to Dual Channel Wide Ultra2 SCSI Controller (Intelligent mode)) + +pci:v00001000d00000012* + ID_MODEL_FROM_DATABASE=53c895a + +pci:v00001000d00000012sv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53c895a (LSI53C895A PCI to Ultra2 SCSI Controller) + +pci:v00001000d00000013* + ID_MODEL_FROM_DATABASE=53c875a + +pci:v00001000d00000013sv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53c875a (LSI53C875A PCI to Ultra SCSI Controller) + +pci:v00001000d00000014* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 + +pci:v00001000d00000014sv00001028sd00001F3A* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (PERC H745 Adapter) + +pci:v00001000d00000014sv00001028sd00001F3B* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (PERC H745 Front) + +pci:v00001000d00000014sv00001028sd00001FD4* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (PERC H745P MX) + +pci:v00001000d00000014sv00001137sd0000020E* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (UCSC-RAID-M5 12G Modular RAID Controller) + +pci:v00001000d00000014sv00001D49sd00000602* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (ThinkSystem RAID 930-16i 4GB Flash PCIe 12Gb Adapter) + +pci:v00001000d00000014sv00001D49sd00000604* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (ThinkSystem RAID 930-8e 4GB Flash PCIe 12Gb Adapter) + +pci:v00001000d00000014sv00001D49sd00000607* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (ThinkSystem RAID 930-16i 8GB Flash PCIe 12Gb Adapter) + +pci:v00001000d00000014sv00008086sd0000352D* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (Integrated RAID Module RMSP3AD160F) + +pci:v00001000d00000014sv00008086sd00009460* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (RAID Controller RSP3TD160F) + +pci:v00001000d00000014sv00008086sd00009480* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3516 (RAID Controller RSP3MD088F) + +pci:v00001000d00000015* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3416 + +pci:v00001000d00000015sv00001028sd00001F3C* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3416 (PERC H345 Adapter) + +pci:v00001000d00000015sv00001028sd00001F3D* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3416 (PERC H345 Front) + +pci:v00001000d00000015sv00001D49sd00000503* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3416 (ThinkSystem RAID 530-16i PCIe 12Gb Adapter) + +pci:v00001000d00000016* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 + +pci:v00001000d00000016sv00001028sd00001FC9* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (PERC H840 Adapter) + +pci:v00001000d00000016sv00001028sd00001FCB* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (PERC H740P Adapter) + +pci:v00001000d00000016sv00001028sd00001FCD* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (PERC H740P Mini) + +pci:v00001000d00000016sv00001028sd00001FCF* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (PERC H740P Mini) + +pci:v00001000d00000016sv00001D49sd00000601* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (ThinkSystem RAID 930-8i 2GB Flash PCIe 12Gb Adapter) + +pci:v00001000d00000016sv00001D49sd00000603* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (ThinkSystem RAID 930-24i 4GB Flash PCIe 12Gb Adapter) + +pci:v00001000d00000016sv00008086sd0000352E* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (Integrated RAID Module RMSP3CD080F) + +pci:v00001000d00000016sv00008086sd0000352F* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (Integrated RAID Module RMSP3HD080E) + +pci:v00001000d00000016sv00008086sd00009461* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3508 (RAID Controller RSP3DD080F) + +pci:v00001000d00000017* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3408 + +pci:v00001000d00000017sv00001D49sd00000500* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3408 (ThinkSystem RAID 530-8i PCIe 12Gb Adapter) + +pci:v00001000d00000017sv00001D49sd00000502* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3408 (ThinkSystem RAID 530-8i Dense Adapter) + +pci:v00001000d00000017sv00008086sd00003528* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3408 (Integrated RAID RMSP3LD060) + +pci:v00001000d00000017sv00008086sd00003529* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3408 (Integrated RAID RMSP3LD060) + +pci:v00001000d00000017sv00008086sd00009441* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3408 (RAID Controller RSP3WD080E) + +pci:v00001000d0000001B* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3504 + +pci:v00001000d0000001Bsv00001D49sd00000605* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3504 (ThinkSystem RAID 930-4i 2GB Flash Flex Adapter) + +pci:v00001000d0000001C* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3404 + +pci:v00001000d0000001Csv00001D49sd00000501* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3404 (ThinkSystem RAID 530-4i Flex Adapter) + +pci:v00001000d00000020* + ID_MODEL_FROM_DATABASE=53c1010 Ultra3 SCSI Adapter + +pci:v00001000d00000020sv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53c1010 Ultra3 SCSI Adapter (LSI53C1010-33 PCI to Dual Channel Ultra160 SCSI Controller) + +pci:v00001000d00000020sv0000107Bsd00001040* + ID_MODEL_FROM_DATABASE=53c1010 Ultra3 SCSI Adapter (Server Onboard 53C1010-33) + +pci:v00001000d00000020sv00001DE1sd00001020* + ID_MODEL_FROM_DATABASE=53c1010 Ultra3 SCSI Adapter (DC-390U3W) + +pci:v00001000d00000021* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter + +pci:v00001000d00000021sv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (LSI53C1000/1000R/1010R/1010-66 PCI to Ultra160 SCSI Controller) + +pci:v00001000d00000021sv00001000sd00001010* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (Asus TR-DLS onboard 53C1010-66) + +pci:v00001000d00000021sv0000103Csd00001300* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (Ultra160 SCSI [AB306A]) + +pci:v00001000d00000021sv0000103Csd00001310* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (Ultra160 SCSI [A9918A]) + +pci:v00001000d00000021sv0000103Csd00001330* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (Ultra160 SCSI [A7059A]) + +pci:v00001000d00000021sv0000103Csd00001340* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (Ultra160 SCSI [A7060A]) + +pci:v00001000d00000021sv0000124Bsd00001070* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (PMC-USCSI3) + +pci:v00001000d00000021sv00004C53sd00001080* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (CT8 mainboard) + +pci:v00001000d00000021sv00004C53sd00001300* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (P017 mezzanine (32-bit PMC)) + +pci:v00001000d00000021sv00004C53sd00001310* + ID_MODEL_FROM_DATABASE=53c1010 66MHz Ultra3 SCSI Adapter (P017 mezzanine (64-bit PMC)) + +pci:v00001000d0000002F* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 IOV [Thunderbolt] + +pci:v00001000d0000002Fsv00001028sd00001F39* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 IOV [Thunderbolt] (SPERC8-e) + +pci:v00001000d0000002Fsv00001028sd00001F3E* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 IOV [Thunderbolt] (SPERC 8) + +pci:v00001000d00000030* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI + +pci:v00001000d00000030sv00000E11sd000000DA* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (ProLiant ML 350) + +pci:v00001000d00000030sv00001028sd00000123* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI Logic 1020/1030) + +pci:v00001000d00000030sv00001028sd0000014A* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI Logic 1020/1030) + +pci:v00001000d00000030sv00001028sd0000016C* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (PowerEdge 1850 MPT Fusion SCSI/RAID (Perc 4)) + +pci:v00001000d00000030sv00001028sd00000183* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI Logic 1020/1030) + +pci:v00001000d00000030sv00001028sd0000018A* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (PERC 4/IM) + +pci:v00001000d00000030sv00001028sd00001010* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI U320 SCSI Controller) + +pci:v00001000d00000030sv0000103Csd000012C5* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (Ultra320 SCSI [A7173A]) + +pci:v00001000d00000030sv0000103Csd00001323* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (Core I/O LAN/SCSI Combo [AB314A]) + +pci:v00001000d00000030sv0000103Csd00003108* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (Single Channel Ultra320 SCSI HBA G2) + +pci:v00001000d00000030sv0000103Csd0000322A* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (SC11Xe Ultra320 Single Channel PCIe x4 SCSI Host Bus Adapter (412911-B21)) + +pci:v00001000d00000030sv0000124Bsd00001170* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (PMC-USCSI320) + +pci:v00001000d00000030sv000015ADsd00001976* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI Logic Parallel SCSI Controller) + +pci:v00001000d00000030sv00001734sd00001052* + ID_MODEL_FROM_DATABASE=53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (PRIMERGY BX/RX/TX S2 series onboard SCSI(IME)) + +pci:v00001000d00000031* + ID_MODEL_FROM_DATABASE=53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI + +pci:v00001000d00000032* + ID_MODEL_FROM_DATABASE=53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI + +pci:v00001000d00000032sv00001000sd00001000* + ID_MODEL_FROM_DATABASE=53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI (LSI53C1020/1030 PCI-X to Ultra320 SCSI Controller) + +pci:v00001000d00000033* + ID_MODEL_FROM_DATABASE=1030ZC_53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI + +pci:v00001000d00000040* + ID_MODEL_FROM_DATABASE=53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI + +pci:v00001000d00000040sv00001000sd00000033* + ID_MODEL_FROM_DATABASE=53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI (MegaRAID SCSI 320-2XR) + +pci:v00001000d00000040sv00001000sd00000066* + ID_MODEL_FROM_DATABASE=53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI (MegaRAID SCSI 320-2XRWS) + +pci:v00001000d00000041* + ID_MODEL_FROM_DATABASE=53C1035ZC PCI-X Fusion-MPT Dual Ultra320 SCSI + +pci:v00001000d00000050* + ID_MODEL_FROM_DATABASE=SAS1064 PCI-X Fusion-MPT SAS + +pci:v00001000d00000050sv00001028sd00001F04* + ID_MODEL_FROM_DATABASE=SAS1064 PCI-X Fusion-MPT SAS (SAS 5/E) + +pci:v00001000d00000050sv00001028sd00001F09* + ID_MODEL_FROM_DATABASE=SAS1064 PCI-X Fusion-MPT SAS (SAS 5i/R) + +pci:v00001000d00000052* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3216/3224 [Cutlass] + +pci:v00001000d00000053* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3216/3224 [Cutlass] + +pci:v00001000d00000053sv00001000sd00009350* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3216/3224 [Cutlass] (MegaRAID SAS 9341-16i) + +pci:v00001000d00000053sv00001000sd00009351* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3216/3224 [Cutlass] (MegaRAID SAS 9341-24i) + +pci:v00001000d00000054* + ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS + +pci:v00001000d00000054sv00001028sd00001F04* + ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/E Adapter Controller) + +pci:v00001000d00000054sv00001028sd00001F05* + ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/i Adapter Controller) + +pci:v00001000d00000054sv00001028sd00001F06* + ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/i Integrated Controller) + +pci:v00001000d00000054sv00001028sd00001F07* + ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/iR Integrated RAID Controller) + +pci:v00001000d00000054sv00001028sd00001F08* + ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/iR Integrated RAID Controller) + +pci:v00001000d00000054sv00001028sd00001F09* + ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS 5/iR Adapter RAID Controller) + +pci:v00001000d00000054sv000015ADsd00001976* + ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS Controller) + +pci:v00001000d00000055* + ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS + +pci:v00001000d00000055sv00001033sd00008336* + ID_MODEL_FROM_DATABASE=SAS1068 PCI-X Fusion-MPT SAS (SAS1068) + +pci:v00001000d00000056* + ID_MODEL_FROM_DATABASE=SAS1064ET PCI-Express Fusion-MPT SAS + +pci:v00001000d00000056sv00001014sd000003BB* + ID_MODEL_FROM_DATABASE=SAS1064ET PCI-Express Fusion-MPT SAS (ServeRAID BR10il SAS/SATA Controller v2) + +pci:v00001000d00000056sv00008086sd000034DC* + ID_MODEL_FROM_DATABASE=SAS1064ET PCI-Express Fusion-MPT SAS (AXX4SASMOD RAID Controller) + +pci:v00001000d00000057* + ID_MODEL_FROM_DATABASE=M1064E MegaRAID SAS + +pci:v00001000d00000057sv00008086sd0000346C* + ID_MODEL_FROM_DATABASE=M1064E MegaRAID SAS (Embedded Software RAID Technology II (ESTRII)) + +pci:v00001000d00000058* + ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS + +pci:v00001000d00000058sv00001000sd00003140* + ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SAS3081E-R 8-Port SAS/SATA Host Bus Adapter) + +pci:v00001000d00000058sv00001028sd0000021D* + ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SAS 6/iR Integrated Workstations RAID Controller) + +pci:v00001000d00000058sv00001028sd00001F0E* + ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SAS 6/iR Adapter RAID Controller) + +pci:v00001000d00000058sv00001028sd00001F0F* + ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SAS 6/iR Integrated Blades RAID Controller) + +pci:v00001000d00000058sv00001028sd00001F10* + ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SAS 6/iR Integrated RAID Controller) + +pci:v00001000d00000058sv0000103Csd00003229* + ID_MODEL_FROM_DATABASE=SAS1068E PCI-Express Fusion-MPT SAS (SC44Ge Host Bus Adapter) + +pci:v00001000d00000059* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 8208ELP/8208ELP + +pci:v00001000d0000005A* + ID_MODEL_FROM_DATABASE=SAS1066E PCI-Express Fusion-MPT SAS + +pci:v00001000d0000005B* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] + +pci:v00001000d0000005Bsv00001000sd00009265* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9265-8i) + +pci:v00001000d0000005Bsv00001000sd00009266* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9266-8i) + +pci:v00001000d0000005Bsv00001000sd00009267* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9267-8i) + +pci:v00001000d0000005Bsv00001000sd00009268* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9265CV-8i / 9270CV-8i) + +pci:v00001000d0000005Bsv00001000sd00009269* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9266-4i) + +pci:v00001000d0000005Bsv00001000sd00009270* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9270-8i) + +pci:v00001000d0000005Bsv00001000sd00009271* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9271-8i) + +pci:v00001000d0000005Bsv00001000sd00009272* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9272-8i) + +pci:v00001000d0000005Bsv00001000sd00009273* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9270CV-8i) + +pci:v00001000d0000005Bsv00001000sd00009274* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9270-4i) + +pci:v00001000d0000005Bsv00001000sd00009275* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9271-8iCC) + +pci:v00001000d0000005Bsv00001000sd00009276* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9271-4i) + +pci:v00001000d0000005Bsv00001000sd00009285* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9285-8e) + +pci:v00001000d0000005Bsv00001000sd00009288* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9285CV-8e) + +pci:v00001000d0000005Bsv00001000sd00009290* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9286-8e) + +pci:v00001000d0000005Bsv00001000sd00009291* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9286CV-8e) + +pci:v00001000d0000005Bsv00001000sd00009295* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (MegaRAID SAS 9286CV-8eCC) + +pci:v00001000d0000005Bsv00001014sd0000040B* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (ServeRAID M5110 SAS/SATA Controller) + +pci:v00001000d0000005Bsv00001014sd0000040C* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (ServeRAID M5120 SAS/SATA Controller) + +pci:v00001000d0000005Bsv00001014sd00000412* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (ServeRAID M5110e SAS/SATA Controller) + +pci:v00001000d0000005Bsv00001028sd00001F2D* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H810 Adapter) + +pci:v00001000d0000005Bsv00001028sd00001F30* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710 Embedded) + +pci:v00001000d0000005Bsv00001028sd00001F31* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710P Adapter) + +pci:v00001000d0000005Bsv00001028sd00001F33* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710P Mini (for blades)) + +pci:v00001000d0000005Bsv00001028sd00001F34* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710P Mini (for monolithics)) + +pci:v00001000d0000005Bsv00001028sd00001F35* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710 Adapter) + +pci:v00001000d0000005Bsv00001028sd00001F37* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710 Mini (for blades)) + +pci:v00001000d0000005Bsv00001028sd00001F38* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (PERC H710 Mini (for monolithics)) + +pci:v00001000d0000005Bsv000015D9sd00000690* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (LSI MegaRAID ROMB) + +pci:v00001000d0000005Bsv00008086sd00003510* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RMS25PB080 RAID Controller) + +pci:v00001000d0000005Bsv00008086sd00003511* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RMS25PB040 RAID Controller) + +pci:v00001000d0000005Bsv00008086sd00003512* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RMT3PB080 RAID Controller) + +pci:v00001000d0000005Bsv00008086sd00003513* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (Integrated RAID Module RMS25CB080) + +pci:v00001000d0000005Bsv00008086sd00003514* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RMS25CB040 RAID Controller) + +pci:v00001000d0000005Bsv00008086sd0000351C* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RMS25PB080N RAID Controller) + +pci:v00001000d0000005Bsv00008086sd0000351D* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RMS25CB080N RAID Controller) + +pci:v00001000d0000005Bsv00008086sd00009265* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RS25DB080 RAID Controller) + +pci:v00001000d0000005Bsv00008086sd00009268* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RS25AB080 RAID Controller) + +pci:v00001000d0000005Bsv00008086sd00009285* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RS25NB008 RAID Controller) + +pci:v00001000d0000005Bsv00008086sd00009288* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2208 [Thunderbolt] (RS25SB008 RAID Controller) + +pci:v00001000d0000005C* + ID_MODEL_FROM_DATABASE=SAS1064A PCI-X Fusion-MPT SAS + +pci:v00001000d0000005D* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] + +pci:v00001000d0000005Dsv00001000sd00009361* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (MegaRAID SAS 9361-8i) + +pci:v00001000d0000005Dsv00001000sd00009363* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (MegaRAID SAS 9361-4i) + +pci:v00001000d0000005Dsv00001000sd00009364* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (MegaRAID SAS 9364-8i) + +pci:v00001000d0000005Dsv00001000sd0000936A* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (MegaRAID SAS 9364-8i) + +pci:v00001000d0000005Dsv00001028sd00001F41* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H830 Adapter) + +pci:v00001000d0000005Dsv00001028sd00001F42* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730P Adapter) + +pci:v00001000d0000005Dsv00001028sd00001F43* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730 Adapter) + +pci:v00001000d0000005Dsv00001028sd00001F47* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730P Mini) + +pci:v00001000d0000005Dsv00001028sd00001F48* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730P Mini (for blades)) + +pci:v00001000d0000005Dsv00001028sd00001F49* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730 Mini) + +pci:v00001000d0000005Dsv00001028sd00001F4A* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730 Mini (for blades)) + +pci:v00001000d0000005Dsv00001028sd00001F4D* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC FD33xS) + +pci:v00001000d0000005Dsv00001028sd00001F4F* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730P Slim) + +pci:v00001000d0000005Dsv00001028sd00001F54* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC FD33xD) + +pci:v00001000d0000005Dsv00001028sd00001FD1* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (PERC H730P MX) + +pci:v00001000d0000005Dsv000017AAsd00001052* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkServer RAID 720i) + +pci:v00001000d0000005Dsv000017AAsd00001053* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkServer RAID 720ix) + +pci:v00001000d0000005Dsv00001D49sd00000600* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkSystem RAID 730-8i 1GB Cache PCIe 12Gb Adapter) + +pci:v00001000d0000005Dsv00001D49sd00000608* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkSystem RAID 730-8i 2GB Flash PCIe 12Gb Adapter) + +pci:v00001000d0000005Dsv00001D49sd00000609* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (ThinkSystem RAID 730-8i 4GB Flash PCIe 12Gb Adapter) + +pci:v00001000d0000005Dsv00008086sd0000351E* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (RMS3CC080 RAID Controller) + +pci:v00001000d0000005Dsv00008086sd0000351F* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (RMS3CC040 RAID Controller) + +pci:v00001000d0000005Dsv00008086sd00009360* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (RS3DC080 RAID Controller) + +pci:v00001000d0000005Dsv00008086sd00009362* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (RS3DC040 RAID Controller) + +pci:v00001000d0000005Dsv00008086sd00009380* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (RS3SC008 RAID Controller) + +pci:v00001000d0000005Dsv00008086sd00009381* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3108 [Invader] (RS3MC044 RAID Controller) + +pci:v00001000d0000005E* + ID_MODEL_FROM_DATABASE=SAS1066 PCI-X Fusion-MPT SAS + +pci:v00001000d0000005F* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] + +pci:v00001000d0000005Fsv00001028sd00001F44* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (PERC H330 Adapter) + +pci:v00001000d0000005Fsv00001028sd00001F4B* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (PERC H330 Mini) + +pci:v00001000d0000005Fsv00001028sd00001F4C* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (PERC H330 Mini (for blades)) + +pci:v00001000d0000005Fsv00001028sd00001F4D* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (PERC H330 Embedded (for monolithic)) + +pci:v00001000d0000005Fsv00001054sd0000306A* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (SAS 3004 iMR ROMB) + +pci:v00001000d0000005Fsv00001D49sd000004DB* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (ServeRAID M1210 SAS/SATA Controller) + +pci:v00001000d0000005Fsv00001D49sd00000504* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3008 [Fury] (ThinkSystem RAID 520-8i PCIe 12Gb Adapter) + +pci:v00001000d00000060* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 + +pci:v00001000d00000060sv00001000sd00001006* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8888ELP) + +pci:v00001000d00000060sv00001000sd0000100A* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8708ELP) + +pci:v00001000d00000060sv00001000sd0000100E* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8884E) + +pci:v00001000d00000060sv00001000sd0000100F* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8708E) + +pci:v00001000d00000060sv00001000sd00001010* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SATA 350-8ELP) + +pci:v00001000d00000060sv00001000sd00001011* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SATA 350-4ELP) + +pci:v00001000d00000060sv00001000sd00001012* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8704ELP) + +pci:v00001000d00000060sv00001000sd00001016* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS 8880EM2) + +pci:v00001000d00000060sv00001014sd00000363* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000060sv00001014sd00000364* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (SystemX MegaRAID SAS 8808E) + +pci:v00001000d00000060sv00001014sd00000365* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (SystemX MegaRAID SAS 8884E) + +pci:v00001000d00000060sv00001014sd00000379* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (SystemX MegaRAID SAS 8880EM2) + +pci:v00001000d00000060sv00001028sd00001F0A* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (PERC 6/E Adapter RAID Controller) + +pci:v00001000d00000060sv00001028sd00001F0B* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (PERC 6/i Adapter RAID Controller) + +pci:v00001000d00000060sv00001028sd00001F0C* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (PERC 6/i Integrated RAID Controller) + +pci:v00001000d00000060sv00001028sd00001F0D* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (PERC 6/i Integrated RAID Controller) + +pci:v00001000d00000060sv00001028sd00001F11* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (CERC 6/i Integrated RAID Controller) + +pci:v00001000d00000060sv00001033sd0000835A* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000060sv00001043sd0000824D* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000060sv00001170sd0000002F* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000060sv00001170sd00000036* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000060sv000015D9sd0000C080* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000060sv000017AAsd00006B7C* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000060sv000018A1sd00000003* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (LSI MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000060sv00008086sd00001006* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (RAID Controller SRCSAS28EP) + +pci:v00001000d00000060sv00008086sd0000100A* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (RAID Controller SRCSAS28EV) + +pci:v00001000d00000060sv00008086sd00001010* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (RAID Controller SRCSATA28E) + +pci:v00001000d00000060sv00008086sd000034CC* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (Integrated RAID Controller SROMBSAS28E) + +pci:v00001000d00000060sv00008086sd000034CD* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (Integrated RAID Controller SROMBSAS28E) + +pci:v00001000d00000060sv00008086sd00003505* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078 (Integrated RAID Controller SROMBSASMP2) + +pci:v00001000d00000062* + ID_MODEL_FROM_DATABASE=SAS1078 PCI-Express Fusion-MPT SAS + +pci:v00001000d00000062sv00001000sd00000062* + ID_MODEL_FROM_DATABASE=SAS1078 PCI-Express Fusion-MPT SAS + +pci:v00001000d00000064* + ID_MODEL_FROM_DATABASE=SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] + +pci:v00001000d00000064sv00001000sd00003030* + ID_MODEL_FROM_DATABASE=SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] (9200-16e 6Gb/s SAS/SATA PCIe x8 External HBA) + +pci:v00001000d00000064sv00001000sd000030C0* + ID_MODEL_FROM_DATABASE=SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] (SAS 9201-16i) + +pci:v00001000d00000064sv00001000sd000030D0* + ID_MODEL_FROM_DATABASE=SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] (9201-16e 6Gb/s SAS/SATA PCIe x8 External HBA) + +pci:v00001000d00000065* + ID_MODEL_FROM_DATABASE=SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] + +pci:v00001000d0000006E* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 + +pci:v00001000d00000070* + ID_MODEL_FROM_DATABASE=SAS2004 PCI-Express Fusion-MPT SAS-2 [Spitfire] + +pci:v00001000d00000070sv00001000sd00003010* + ID_MODEL_FROM_DATABASE=SAS2004 PCI-Express Fusion-MPT SAS-2 [Spitfire] (SAS9211-4i) + +pci:v00001000d00000070sv00001014sd0000040E* + ID_MODEL_FROM_DATABASE=SAS2004 PCI-Express Fusion-MPT SAS-2 [Spitfire] (ServeRAID H1110) + +pci:v00001000d00000071* + ID_MODEL_FROM_DATABASE=MR SAS HBA 2004 + +pci:v00001000d00000072* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] + +pci:v00001000d00000072sv00001000sd00003040* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (9210-8i) + +pci:v00001000d00000072sv00001000sd00003080* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (9200-8e [LSI SAS 6Gb/s SAS/SATA PCIe x8 External HBA]) + +pci:v00001000d00000072sv00001000sd000030B0* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (9200-8e [LSI SAS 6Gb/s SAS/SATA PCIe x8 External HBA]) + +pci:v00001000d00000072sv00001028sd00001F1C* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (6Gbps SAS HBA Adapter) + +pci:v00001000d00000072sv00001028sd00001F1D* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (PERC H200 Adapter) + +pci:v00001000d00000072sv00001028sd00001F1E* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (PERC H200 Integrated) + +pci:v00001000d00000072sv00001028sd00001F1F* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (PERC H200 Modular) + +pci:v00001000d00000072sv00001028sd00001F20* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (PERC H200 Embedded) + +pci:v00001000d00000072sv00001028sd00001F22* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (PERC H200 Internal Tape Adapter) + +pci:v00001000d00000072sv00008086sd0000350F* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (RMS2LL040 RAID Controller) + +pci:v00001000d00000072sv00008086sd00003700* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] (SSD 910 Series) + +pci:v00001000d00000073* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] + +pci:v00001000d00000073sv00001000sd00009240* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (MegaRAID SAS 9240-8i) + +pci:v00001000d00000073sv00001000sd00009241* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (MegaRAID SAS 9240-4i) + +pci:v00001000d00000073sv00001000sd000092A0* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (MegaRAID SAS 9220-8i) + +pci:v00001000d00000073sv00001014sd000003B1* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (ServeRAID M1015 SAS/SATA Controller) + +pci:v00001000d00000073sv00001014sd0000040D* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (ServeRAID M1115 SAS/SATA Controller) + +pci:v00001000d00000073sv00001028sd00001F4E* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Adapter) + +pci:v00001000d00000073sv00001028sd00001F4F* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Integrated) + +pci:v00001000d00000073sv00001028sd00001F50* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Mini Blades) + +pci:v00001000d00000073sv00001028sd00001F51* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Mini Monolithics) + +pci:v00001000d00000073sv00001028sd00001F52* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Embedded1) + +pci:v00001000d00000073sv00001028sd00001F53* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Embedded2) + +pci:v00001000d00000073sv00001028sd00001F54* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310 Reserved) + +pci:v00001000d00000073sv00001028sd00001F78* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (PERC H310) + +pci:v00001000d00000073sv00001054sd00003035* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (LSI MegaRAID SAS 9240-8i) + +pci:v00001000d00000073sv00001137sd00000072* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (2004 iMR ROMB) + +pci:v00001000d00000073sv00001137sd00000073* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (2008 ROMB) + +pci:v00001000d00000073sv00001137sd000000B0* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (UCSC RAID SAS 2008M-8i) + +pci:v00001000d00000073sv00001137sd000000B1* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (UCSC RAID SAS 2008M-8i) + +pci:v00001000d00000073sv00001137sd000000C2* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (UCS E-Series Double Wide) + +pci:v00001000d00000073sv00001137sd000000C3* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (UCS E-Series Single Wide) + +pci:v00001000d00000073sv000015D9sd00000400* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (Supermicro SMC2008-iMR) + +pci:v00001000d00000073sv00001734sd00001177* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (RAID Ctrl SAS 6G 0/1 (D2607)) + +pci:v00001000d00000073sv000017AAsd00001051* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (ThinkServer RAID 510i) + +pci:v00001000d00000073sv00008086sd0000350D* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (RMS2AF040 RAID Controller) + +pci:v00001000d00000073sv00008086sd00009240* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (RAID Controller RS2WC080) + +pci:v00001000d00000073sv00008086sd00009241* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2008 [Falcon] (RAID Controller RS2WC040) + +pci:v00001000d00000074* + ID_MODEL_FROM_DATABASE=SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] + +pci:v00001000d00000076* + ID_MODEL_FROM_DATABASE=SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] + +pci:v00001000d00000077* + ID_MODEL_FROM_DATABASE=SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] + +pci:v00001000d00000079* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] + +pci:v00001000d00000079sv00001000sd00009251* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260-4ix) + +pci:v00001000d00000079sv00001000sd00009256* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260-8ix) + +pci:v00001000d00000079sv00001000sd00009260* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260-4i) + +pci:v00001000d00000079sv00001000sd00009261* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260-8i) + +pci:v00001000d00000079sv00001000sd00009262* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9262-8i) + +pci:v00001000d00000079sv00001000sd00009263* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9261-8i) + +pci:v00001000d00000079sv00001000sd00009264* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9264-8i) + +pci:v00001000d00000079sv00001000sd00009267* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260CV-4i) + +pci:v00001000d00000079sv00001000sd00009268* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260CV-8i) + +pci:v00001000d00000079sv00001000sd00009275* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9280-8ex) + +pci:v00001000d00000079sv00001000sd00009276* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MR9260-16i) + +pci:v00001000d00000079sv00001000sd00009280* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9280-8e) + +pci:v00001000d00000079sv00001000sd00009281* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9281-8E) + +pci:v00001000d00000079sv00001000sd00009282* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9280-4i4e) + +pci:v00001000d00000079sv00001000sd00009290* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9280DE-24i4e) + +pci:v00001000d00000079sv00001014sd000003B2* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (ServeRAID M5015 SAS/SATA Controller) + +pci:v00001000d00000079sv00001014sd000003B3* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (ServeRAID M5025 SAS/SATA Controller) + +pci:v00001000d00000079sv00001028sd00001F15* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H800 Adapter) + +pci:v00001000d00000079sv00001028sd00001F16* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H700 Adapter) + +pci:v00001000d00000079sv00001028sd00001F17* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H700 Integrated) + +pci:v00001000d00000079sv00001028sd00001F18* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H700 Modular) + +pci:v00001000d00000079sv00001028sd00001F1A* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H800 Proto Adapter) + +pci:v00001000d00000079sv00001028sd00001F1B* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PERC H700 Integrated) + +pci:v00001000d00000079sv00001043sd00008480* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (PIKE-2108 16PD) + +pci:v00001000d00000079sv00001734sd00001176* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Ctrl SAS 6G 5/6 512MB (D2616)) + +pci:v00001000d00000079sv00001734sd00001177* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Ctrl SAS 6G 0/1 (D2607)) + +pci:v00001000d00000079sv00008086sd0000350B* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RMS2MH080 RAID Controller) + +pci:v00001000d00000079sv00008086sd00009256* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (MegaRAID SAS 9260DE-8i RS2BL080DE) + +pci:v00001000d00000079sv00008086sd00009260* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2BL040) + +pci:v00001000d00000079sv00008086sd00009261* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2BL080) + +pci:v00001000d00000079sv00008086sd00009264* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RT3WB080 Warm Beach (Caster Lite)) + +pci:v00001000d00000079sv00008086sd00009267* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2VB040) + +pci:v00001000d00000079sv00008086sd00009268* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2VB080) + +pci:v00001000d00000079sv00008086sd00009275* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2PI008DE) + +pci:v00001000d00000079sv00008086sd00009276* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2WG160) + +pci:v00001000d00000079sv00008086sd00009280* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2PI008) + +pci:v00001000d00000079sv00008086sd00009282* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2MB044) + +pci:v00001000d00000079sv00008086sd00009290* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 2108 [Liberator] (RAID Controller RS2SG244) + +pci:v00001000d0000007C* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078DE + +pci:v00001000d0000007Csv00001014sd00000395* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1078DE (ServeRAID-AR10is SAS/SATA Controller) + +pci:v00001000d0000007E* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD + +pci:v00001000d0000007Esv00001000sd00000504* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro NWD-BLP4-800) + +pci:v00001000d0000007Esv00001000sd00000507* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro NWD-BLP4-1600) + +pci:v00001000d0000007Esv00001000sd00000581* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro NWD-BLP4-400) + +pci:v00001000d0000007Esv00001000sd0000100D* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro NWD-BFH6-1200) + +pci:v00001000d0000007Esv00001000sd0000100E* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro NWD-BFH8-1600) + +pci:v00001000d0000007Esv00001000sd0000107E* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro NWD-BFH8-3200) + +pci:v00001000d0000007Esv00001000sd00001310* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro XP6302-8B1536) + +pci:v00001000d0000007Esv00001000sd00001311* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro XP6302-8B2048) + +pci:v00001000d0000007Esv00001000sd00001314* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro XP6302-8B4096) + +pci:v00001000d0000007Esv00001000sd0000150C* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro XP6210-4A2048) + +pci:v00001000d0000007Esv00001000sd0000150F* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro XP6210-4B2048) + +pci:v00001000d0000007Esv00001000sd0000160B* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro XP6209-4A1024) + +pci:v00001000d0000007Esv00001000sd00001613* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro XP6209-4B2048) + +pci:v00001000d0000007Esv0000108Esd0000050A* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro ELP4x200_4d_n) + +pci:v00001000d0000007Esv0000108Esd00000581* + ID_MODEL_FROM_DATABASE=SSS6200 PCI-Express Flash SSD (Nytro ELP4x100_4d_n) + +pci:v00001000d00000080* + ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 + +pci:v00001000d00000081* + ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 + +pci:v00001000d00000082* + ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 + +pci:v00001000d00000083* + ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 + +pci:v00001000d00000084* + ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 + +pci:v00001000d00000085* + ID_MODEL_FROM_DATABASE=SAS2208 PCI-Express Fusion-MPT SAS-2 + +pci:v00001000d00000086* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 + +pci:v00001000d00000086sv000015D9sd00000690* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (Onboard MegaRAID SAS2208 [Thunderbolt]) + +pci:v00001000d00000086sv000015D9sd00000691* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (Onboard SAS2308 PCI-Express Fusion-MPT SAS-2) + +pci:v00001000d00000087* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 + +pci:v00001000d00000087sv00001000sd00003020* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (9207-8i SAS2.1 HBA) + +pci:v00001000d00000087sv00001000sd00003030* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (SAS9207-4i4e) + +pci:v00001000d00000087sv00001000sd00003040* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (9207-8e SAS2.1 HBA) + +pci:v00001000d00000087sv00001000sd00003050* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (SAS9217-8i) + +pci:v00001000d00000087sv00001000sd00003060* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (SAS9217-4i4e) + +pci:v00001000d00000087sv00001014sd00000472* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (N2125 External Host Bus Adapter) + +pci:v00001000d00000087sv00001590sd00000041* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (H220i) + +pci:v00001000d00000087sv00001590sd00000042* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (H221 / 9207-8e) + +pci:v00001000d00000087sv00001590sd00000044* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (H220i) + +pci:v00001000d00000087sv00008086sd00003000* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (RS25GB008 RAID Controller) + +pci:v00001000d00000087sv00008086sd00003060* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (RS25FB044 RAID Controller) + +pci:v00001000d00000087sv00008086sd00003516* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (RMS25JB080 RAID Controller) + +pci:v00001000d00000087sv00008086sd00003517* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (RMS25JB040 RAID Controller) + +pci:v00001000d00000087sv00008086sd00003518* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (RMS25KB080 RAID Controller) + +pci:v00001000d00000087sv00008086sd00003519* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (RMS25KB040 RAID Controller) + +pci:v00001000d00000087sv00008086sd0000351A* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (RMS25LB040 RAID Controller) + +pci:v00001000d00000087sv00008086sd0000351B* + ID_MODEL_FROM_DATABASE=SAS2308 PCI-Express Fusion-MPT SAS-2 (RMS25LB080 RAID Controller) + +pci:v00001000d0000008F* + ID_MODEL_FROM_DATABASE=53c875J + +pci:v00001000d0000008Fsv00001092sd00008000* + ID_MODEL_FROM_DATABASE=53c875J (FirePort 40 SCSI Controller) + +pci:v00001000d0000008Fsv00001092sd00008760* + ID_MODEL_FROM_DATABASE=53c875J (FirePort 40 Dual SCSI Host Adapter) + +pci:v00001000d00000090* + ID_MODEL_FROM_DATABASE=SAS3108 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d00000091* + ID_MODEL_FROM_DATABASE=SAS3108 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d00000094* + ID_MODEL_FROM_DATABASE=SAS3108 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d00000095* + ID_MODEL_FROM_DATABASE=SAS3108 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d00000096* + ID_MODEL_FROM_DATABASE=SAS3004 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d00000097* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d00000097sv00001000sd00003090* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (SAS9311-8i) + +pci:v00001000d00000097sv00001000sd000030A0* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (SAS9300-8e) + +pci:v00001000d00000097sv00001000sd000030E0* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (SAS9300-8i) + +pci:v00001000d00000097sv00001000sd00003130* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (SAS 9300-16i) + +pci:v00001000d00000097sv00001028sd00001F45* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (HBA330 Adapter) + +pci:v00001000d00000097sv00001028sd00001F46* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (12Gbps HBA) + +pci:v00001000d00000097sv00001028sd00001F53* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (HBA330 Mini) + +pci:v00001000d00000097sv00001028sd00001FD2* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (HBA330 MX) + +pci:v00001000d00000097sv00001028sd00001FD3* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (HBA330 MMZ) + +pci:v00001000d00000097sv000015D9sd00000808* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (AOC-S3008L-L8e) + +pci:v00001000d00000097sv00001BD4sd0000000B* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (12G SAS3008IR) + +pci:v00001000d00000097sv00001BD4sd0000000C* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (12G SAS3008IT) + +pci:v00001000d00000097sv00001BD4sd00000011* + ID_MODEL_FROM_DATABASE=SAS3008 PCI-Express Fusion-MPT SAS-3 (Inspur 12Gb 8i-3008 IT SAS HBA) + +pci:v00001000d000000AB* + ID_MODEL_FROM_DATABASE=SAS3516 Fusion-MPT Tri-Mode RAID On Chip (ROC) + +pci:v00001000d000000ABsv00001000sd00003040* + ID_MODEL_FROM_DATABASE=SAS3516 Fusion-MPT Tri-Mode RAID On Chip (ROC) (HBA 9400-8i8e) + +pci:v00001000d000000ABsv00008086sd00003530* + ID_MODEL_FROM_DATABASE=SAS3516 Fusion-MPT Tri-Mode RAID On Chip (ROC) (Integrated RAID Module RMSP3JD160J) + +pci:v00001000d000000AC* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + +pci:v00001000d000000ACsv00001000sd00003000* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (HBA 9400-16i) + +pci:v00001000d000000ACsv00001000sd00003020* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (HBA 9400-16e) + +pci:v00001000d000000ACsv00001028sd00001FE3* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (HBA345 Adapter) + +pci:v00001000d000000ACsv00001028sd00001FE4* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (HBA345 Front) + +pci:v00001000d000000ACsv00001D49sd00000201* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 430-16i SAS/SATA 12Gb HBA) + +pci:v00001000d000000ACsv00001D49sd00000203* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 430-16e SAS/SATA 12Gb HBA) + +pci:v00001000d000000ACsv00008086sd00003000* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (RAID Controller RSP3QD160J) + +pci:v00001000d000000ACsv00008086sd00003020* + ID_MODEL_FROM_DATABASE=SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (RAID Controller RSP3GD016J) + +pci:v00001000d000000AE* + ID_MODEL_FROM_DATABASE=SAS3508 Fusion-MPT Tri-Mode RAID On Chip (ROC) + +pci:v00001000d000000AF* + ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + +pci:v00001000d000000AFsv00001000sd00003010* + ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (HBA 9400-8i) + +pci:v00001000d000000AFsv00001000sd00003030* + ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (HBA 9400-8e) + +pci:v00001000d000000AFsv00001D49sd00000200* + ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 430-8i SAS/SATA 12Gb HBA) + +pci:v00001000d000000AFsv00001D49sd00000202* + ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 430-8e SAS/SATA 12Gb HBA) + +pci:v00001000d000000AFsv00001D49sd00000204* + ID_MODEL_FROM_DATABASE=SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (ThinkSystem 430-8i SAS/SATA 12Gb Dense HBA) + +pci:v00001000d000000BE* + ID_MODEL_FROM_DATABASE=SAS3504 Fusion-MPT Tri-Mode RAID On Chip (ROC) + +pci:v00001000d000000BF* + ID_MODEL_FROM_DATABASE=SAS3404 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + +pci:v00001000d000000C0* + ID_MODEL_FROM_DATABASE=SAS3324 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d000000C1* + ID_MODEL_FROM_DATABASE=SAS3324 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d000000C2* + ID_MODEL_FROM_DATABASE=SAS3324 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d000000C3* + ID_MODEL_FROM_DATABASE=SAS3324 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d000000C4* + ID_MODEL_FROM_DATABASE=SAS3224 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d000000C5* + ID_MODEL_FROM_DATABASE=SAS3316 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d000000C6* + ID_MODEL_FROM_DATABASE=SAS3316 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d000000C7* + ID_MODEL_FROM_DATABASE=SAS3316 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d000000C8* + ID_MODEL_FROM_DATABASE=SAS3316 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d000000C9* + ID_MODEL_FROM_DATABASE=SAS3216 PCI-Express Fusion-MPT SAS-3 + +pci:v00001000d000000CE* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3316 [Intruder] + +pci:v00001000d000000CEsv00001000sd00009371* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3316 [Intruder] (MegaRAID SAS 9361-16i) + +pci:v00001000d000000CEsv00001000sd00009390* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3316 [Intruder] (MegaRAID SAS 9380-8i8e) + +pci:v00001000d000000CF* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3324 [Intruder] + +pci:v00001000d000000CFsv00001000sd00009370* + ID_MODEL_FROM_DATABASE=MegaRAID SAS-3 3324 [Intruder] (MegaRAID SAS 9361-24i) + +pci:v00001000d000000D0* + ID_MODEL_FROM_DATABASE=SAS3716 Fusion-MPT Tri-Mode RAID Controller Chip (ROC) + +pci:v00001000d000000D0sv00001000sd00003050* + ID_MODEL_FROM_DATABASE=SAS3716 Fusion-MPT Tri-Mode RAID Controller Chip (ROC) (HBA 9405W-16i) + +pci:v00001000d000000D0sv00001000sd00003070* + ID_MODEL_FROM_DATABASE=SAS3716 Fusion-MPT Tri-Mode RAID Controller Chip (ROC) (HBA 9405W-8i8e) + +pci:v00001000d000000D1* + ID_MODEL_FROM_DATABASE=SAS3616 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + +pci:v00001000d000000D1sv00001000sd00003080* + ID_MODEL_FROM_DATABASE=SAS3616 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (HBA 9405W-16e) + +pci:v00001000d000000D1sv00001000sd00003090* + ID_MODEL_FROM_DATABASE=SAS3616 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) (HBA 9405W-16i) + +pci:v00001000d000000D3* + ID_MODEL_FROM_DATABASE=MegaRAID Tri-Mode SAS3716W + +pci:v00001000d000000E0* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS39xx + +pci:v00001000d000000E1* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe SAS39xx + +pci:v00001000d000000E2* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS39xx + +pci:v00001000d000000E3* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS39xx + +pci:v00001000d000000E4* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx + +pci:v00001000d000000E4sv00001028sd0000200B* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx (HBA355i Adapter Invalid) + +pci:v00001000d000000E4sv00001028sd0000200C* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx (HBA355i Front Invalid) + +pci:v00001000d000000E4sv00001028sd0000200D* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx (HBA355e Adapter Invalid) + +pci:v00001000d000000E4sv00001028sd0000200E* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx (HBA350i MX Invalid) + +pci:v00001000d000000E5* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe SAS38xx + +pci:v00001000d000000E5sv00001028sd0000200B* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe SAS38xx (HBA355i Adapter) + +pci:v00001000d000000E5sv00001028sd0000200C* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe SAS38xx (HBA355i Front) + +pci:v00001000d000000E5sv00001028sd0000200D* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe SAS38xx (HBA355e Adapter) + +pci:v00001000d000000E5sv00001028sd0000200E* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe SAS38xx (HBA350i MX) + +pci:v00001000d000000E5sv00001D49sd00000205* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe SAS38xx (ThinkSystem 440-16i SAS/SATA PCIe Gen4 12Gb Internal HBA) + +pci:v00001000d000000E5sv00001D49sd00000206* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe SAS38xx (ThinkSystem 440-16e SAS/SATA PCIe Gen4 12Gb HBA) + +pci:v00001000d000000E6* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx + +pci:v00001000d000000E6sv00001028sd0000200B* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx (HBA355i Adapter) + +pci:v00001000d000000E6sv00001028sd0000200C* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx (HBA355i Front) + +pci:v00001000d000000E6sv00001028sd0000200D* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx (HBA355e Adapter) + +pci:v00001000d000000E6sv00001028sd0000200E* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx (HBA355i MX) + +pci:v00001000d000000E6sv00001D49sd00000205* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx (ThinkSystem 440-16i SAS/SATA PCIe Gen4 12Gb Internal HBA) + +pci:v00001000d000000E6sv00001D49sd00000206* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Secure SAS38xx (ThinkSystem 440-16e SAS/SATA PCIe Gen4 12Gb HBA) + +pci:v00001000d000000E7* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx + +pci:v00001000d000000E7sv00001028sd0000200B* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx (HBA355i Adapter Tampered) + +pci:v00001000d000000E7sv00001028sd0000200C* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx (HBA355i Front Tampered) + +pci:v00001000d000000E7sv00001028sd0000200D* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx (HBA355e Adapter Tampered) + +pci:v00001000d000000E7sv00001028sd0000200E* + ID_MODEL_FROM_DATABASE=Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx (HBA350i MX Tampered) + +pci:v00001000d000002B0* + ID_MODEL_FROM_DATABASE=Virtual Endpoint on PCIe Switch + +pci:v00001000d000002B0sv00001D49sd00000001* + ID_MODEL_FROM_DATABASE=Virtual Endpoint on PCIe Switch (ThinkSystem 1610-4P NVMe Switch Adapter) + +pci:v00001000d000002B0sv00001D49sd00000002* + ID_MODEL_FROM_DATABASE=Virtual Endpoint on PCIe Switch (ThinkSystem 810-4P NVMe Switch Adapter) + +pci:v00001000d000002B1* + ID_MODEL_FROM_DATABASE=Virtual Endpoint on PCIe Switch (9749) + +pci:v00001000d000002B1sv00001D49sd00000004* + ID_MODEL_FROM_DATABASE=Virtual Endpoint on PCIe Switch (9749) (ThinkSystem 1610-8P NVMe Switch Adapter) + +pci:v00001000d00000407* + ID_MODEL_FROM_DATABASE=MegaRAID + +pci:v00001000d00000407sv00001000sd00000530* + ID_MODEL_FROM_DATABASE=MegaRAID (530 SCSI 320-0X RAID Controller) + +pci:v00001000d00000407sv00001000sd00000531* + ID_MODEL_FROM_DATABASE=MegaRAID (531 SCSI 320-4X RAID Controller) + +pci:v00001000d00000407sv00001000sd00000532* + ID_MODEL_FROM_DATABASE=MegaRAID (532 SCSI 320-2X RAID Controller) + +pci:v00001000d00000407sv00001028sd00000531* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge Expandable RAID Controller 4/QC) + +pci:v00001000d00000407sv00001028sd00000533* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge Expandable RAID Controller 4/QC) + +pci:v00001000d00000407sv00008086sd00000530* + ID_MODEL_FROM_DATABASE=MegaRAID (Intel RAID Controller SRCZCRX) + +pci:v00001000d00000407sv00008086sd00000532* + ID_MODEL_FROM_DATABASE=MegaRAID (Intel RAID Controller SRCU42X) + +pci:v00001000d00000408* + ID_MODEL_FROM_DATABASE=MegaRAID + +pci:v00001000d00000408sv00001000sd00000001* + ID_MODEL_FROM_DATABASE=MegaRAID (SCSI 320-1E RAID Controller) + +pci:v00001000d00000408sv00001000sd00000002* + ID_MODEL_FROM_DATABASE=MegaRAID (SCSI 320-2E RAID Controller) + +pci:v00001000d00000408sv00001025sd0000004D* + ID_MODEL_FROM_DATABASE=MegaRAID (ACER ROMB-2E RAID Controller) + +pci:v00001000d00000408sv00001028sd00000001* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller PERC4e/SC) + +pci:v00001000d00000408sv00001028sd00000002* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller PERC4e/DC) + +pci:v00001000d00000408sv00001028sd00000012* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller RAC4) + +pci:v00001000d00000408sv00001028sd00000015* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller PERC5) + +pci:v00001000d00000408sv00001028sd00001F03* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller PERC5) + +pci:v00001000d00000408sv00001734sd00001065* + ID_MODEL_FROM_DATABASE=MegaRAID (FSC MegaRAID PCI Express ROMB) + +pci:v00001000d00000408sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=MegaRAID (Intel RAID Controller SRCU42E) + +pci:v00001000d00000408sv00008086sd00003449* + ID_MODEL_FROM_DATABASE=MegaRAID (Intel RAID Controller SROMBU) + +pci:v00001000d00000409* + ID_MODEL_FROM_DATABASE=MegaRAID + +pci:v00001000d00000409sv00001000sd00003004* + ID_MODEL_FROM_DATABASE=MegaRAID (SATA 300-4X RAID Controller) + +pci:v00001000d00000409sv00001000sd00003008* + ID_MODEL_FROM_DATABASE=MegaRAID (SATA 300-8X RAID Controller) + +pci:v00001000d00000409sv00008086sd00003008* + ID_MODEL_FROM_DATABASE=MegaRAID (RAID Controller SRCS28X) + +pci:v00001000d00000409sv00008086sd00003431* + ID_MODEL_FROM_DATABASE=MegaRAID (RAID Controller Alief SROMBU42E) + +pci:v00001000d00000409sv00008086sd00003499* + ID_MODEL_FROM_DATABASE=MegaRAID (RAID Controller Harwich SROMBU42E) + +pci:v00001000d00000411* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 + +pci:v00001000d00000411sv00001000sd00001001* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS 8408E) + +pci:v00001000d00000411sv00001000sd00001002* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS 8480E) + +pci:v00001000d00000411sv00001000sd00001003* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS 8344ELP) + +pci:v00001000d00000411sv00001000sd00001004* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS 8308ELP) + +pci:v00001000d00000411sv00001000sd00001008* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS 84016E) + +pci:v00001000d00000411sv00001000sd0000100C* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SATA 300-12E) + +pci:v00001000d00000411sv00001000sd0000100D* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SATA 300-16E) + +pci:v00001000d00000411sv00001000sd00002004* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SATA 300-8ELP) + +pci:v00001000d00000411sv00001000sd00002005* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SATA 300-4ELP) + +pci:v00001000d00000411sv00001033sd00008287* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000411sv00001054sd00003016* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS RoMB Server) + +pci:v00001000d00000411sv00001734sd00001081* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000411sv00001734sd000010A3* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (MegaRAID SAS PCI Express ROMB) + +pci:v00001000d00000411sv00008086sd00001001* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (RAID Controller SRCSAS18E) + +pci:v00001000d00000411sv00008086sd00001003* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (RAID Controller SRCSAS144E) + +pci:v00001000d00000411sv00008086sd00003500* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (SROMBSAS18E RAID Controller) + +pci:v00001000d00000411sv00008086sd00003501* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (SROMBSAS18E RAID Controller) + +pci:v00001000d00000411sv00008086sd00003504* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 (SROMBSAS18E RAID Controller) + +pci:v00001000d00000413* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 [Verde ZCR] + +pci:v00001000d00000413sv00001000sd00001005* + ID_MODEL_FROM_DATABASE=MegaRAID SAS 1068 [Verde ZCR] (MegaRAID SAS 8300XLP) + +pci:v00001000d00000621* + ID_MODEL_FROM_DATABASE=FC909 Fibre Channel Adapter + +pci:v00001000d00000622* + ID_MODEL_FROM_DATABASE=FC929 Fibre Channel Adapter + +pci:v00001000d00000622sv00001000sd00001020* + ID_MODEL_FROM_DATABASE=FC929 Fibre Channel Adapter (44929 O Dual Fibre Channel card) + +pci:v00001000d00000623* + ID_MODEL_FROM_DATABASE=FC929 LAN + +pci:v00001000d00000624* + ID_MODEL_FROM_DATABASE=FC919 Fibre Channel Adapter + +pci:v00001000d00000625* + ID_MODEL_FROM_DATABASE=FC919 LAN + +pci:v00001000d00000626* + ID_MODEL_FROM_DATABASE=FC929X Fibre Channel Adapter + +pci:v00001000d00000626sv00001000sd00001010* + ID_MODEL_FROM_DATABASE=FC929X Fibre Channel Adapter (7202-XP-LC Dual Fibre Channel card) + +pci:v00001000d00000627* + ID_MODEL_FROM_DATABASE=FC929X LAN + +pci:v00001000d00000628* + ID_MODEL_FROM_DATABASE=FC919X Fibre Channel Adapter + +pci:v00001000d00000629* + ID_MODEL_FROM_DATABASE=FC919X LAN + +pci:v00001000d00000640* + ID_MODEL_FROM_DATABASE=FC949X Fibre Channel Adapter + +pci:v00001000d00000642* + ID_MODEL_FROM_DATABASE=FC939X Fibre Channel Adapter + +pci:v00001000d00000646* + ID_MODEL_FROM_DATABASE=FC949ES Fibre Channel Adapter + +pci:v00001000d00000701* + ID_MODEL_FROM_DATABASE=83C885 NT50 DigitalScape Fast Ethernet + +pci:v00001000d00000702* + ID_MODEL_FROM_DATABASE=Yellowfin G-NIC gigabit ethernet + +pci:v00001000d00000702sv00001318sd00000000* + ID_MODEL_FROM_DATABASE=Yellowfin G-NIC gigabit ethernet (PEI100X) + +pci:v00001000d00000804* + ID_MODEL_FROM_DATABASE=SA2010 + +pci:v00001000d00000805* + ID_MODEL_FROM_DATABASE=SA2010ZC + +pci:v00001000d00000806* + ID_MODEL_FROM_DATABASE=SA2020 + +pci:v00001000d00000807* + ID_MODEL_FROM_DATABASE=SA2020ZC + +pci:v00001000d00000901* + ID_MODEL_FROM_DATABASE=61C102 + +pci:v00001000d00001000* + ID_MODEL_FROM_DATABASE=63C815 + +pci:v00001000d000010E0* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS39xx + +pci:v00001000d000010E0sv00001028sd00001AE0* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS39xx (PERC H755 Adapter - Invalid Device) + +pci:v00001000d000010E0sv00001028sd00001AE1* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS39xx (PERC H755 Front - Invalid Device) + +pci:v00001000d000010E0sv00001028sd00001AE2* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS39xx (PERC H755N Front - Invalid Device) + +pci:v00001000d000010E0sv00001028sd00001AE3* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS39xx (PERC H755 MX - Invalid Device) + +pci:v00001000d000010E1* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx + +pci:v00001000d000010E1sv00001028sd00001AE0* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx (PERC H755 Adapter) + +pci:v00001000d000010E1sv00001028sd00001AE1* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx (PERC H755 Front) + +pci:v00001000d000010E1sv00001028sd00001AE2* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx (PERC H755N Front) + +pci:v00001000d000010E1sv00001028sd00001AE3* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx (PERC H755 MX) + +pci:v00001000d000010E1sv00001D49sd0000060A* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx (ThinkSystem RAID 940-8i 4GB Flash PCIe Gen4 12Gb Adapter) + +pci:v00001000d000010E1sv00001D49sd0000060B* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx (ThinkSystem RAID 940-8i 8GB Flash PCIe Gen4 12Gb Adapter) + +pci:v00001000d000010E1sv00001D49sd0000060C* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx (ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Adapter) + +pci:v00001000d000010E1sv00001D49sd0000060D* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx (ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Internal Adapter) + +pci:v00001000d000010E1sv00001D49sd0000060E* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx (ThinkSystem RAID 940-32i 8GB Flash PCIe Gen4 12Gb Adapter) + +pci:v00001000d000010E1sv00001D49sd0000060F* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS39xx (ThinkSystem RAID 940-8e 4GB Flash PCIe Gen4 12Gb Adapter) + +pci:v00001000d000010E2* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx + +pci:v00001000d000010E2sv00001028sd00001AE0* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx (PERC H755 Adapter) + +pci:v00001000d000010E2sv00001028sd00001AE1* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx (PERC H755 Front) + +pci:v00001000d000010E2sv00001028sd00001AE2* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx (PERC H755N Front) + +pci:v00001000d000010E2sv00001028sd00001AE3* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx (PERC H755 MX) + +pci:v00001000d000010E2sv00001D49sd0000060A* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx (ThinkSystem RAID 940-8i 4GB Flash PCIe Gen4 12Gb Adapter) + +pci:v00001000d000010E2sv00001D49sd0000060B* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx (ThinkSystem RAID 940-8i 8GB Flash PCIe Gen4 12Gb Adapter) + +pci:v00001000d000010E2sv00001D49sd0000060C* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx (ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Adapter) + +pci:v00001000d000010E2sv00001D49sd0000060D* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx (ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Internal Adapter) + +pci:v00001000d000010E2sv00001D49sd0000060E* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx (ThinkSystem RAID 940-32i 8GB Flash PCIe Gen4 12Gb Adapter) + +pci:v00001000d000010E2sv00001D49sd0000060F* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS39xx (ThinkSystem RAID 940-8e 4GB Flash PCIe Gen4 12Gb Adapter) + +pci:v00001000d000010E3* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS39xx + +pci:v00001000d000010E3sv00001028sd00001AE0* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS39xx (PERC H755 Adapter - Tampered Device) + +pci:v00001000d000010E3sv00001028sd00001AE1* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS39xx (PERC H755 Front - Tampered Device) + +pci:v00001000d000010E3sv00001028sd00001AE2* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS39xx (PERC H755N Front - Tampered Device) + +pci:v00001000d000010E3sv00001028sd00001AE3* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS39xx (PERC H755 MX - Tampered Device) + +pci:v00001000d000010E4* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS38xx + +pci:v00001000d000010E5* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe SAS38xx + +pci:v00001000d000010E6* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Secure SAS38xx + +pci:v00001000d000010E7* + ID_MODEL_FROM_DATABASE=MegaRAID 12GSAS/PCIe Unsupported SAS38xx + +pci:v00001000d00001960* + ID_MODEL_FROM_DATABASE=MegaRAID + +pci:v00001000d00001960sv00001000sd00000518* + ID_MODEL_FROM_DATABASE=MegaRAID (518 SCSI 320-2 Controller) + +pci:v00001000d00001960sv00001000sd00000520* + ID_MODEL_FROM_DATABASE=MegaRAID (520 SCSI 320-1 Controller) + +pci:v00001000d00001960sv00001000sd00000522* + ID_MODEL_FROM_DATABASE=MegaRAID (522 i4 133 RAID Controller) + +pci:v00001000d00001960sv00001000sd00000523* + ID_MODEL_FROM_DATABASE=MegaRAID (SATA 150-6 RAID Controller) + +pci:v00001000d00001960sv00001000sd00004523* + ID_MODEL_FROM_DATABASE=MegaRAID (SATA 150-4 RAID Controller) + +pci:v00001000d00001960sv00001000sd0000A520* + ID_MODEL_FROM_DATABASE=MegaRAID (ZCR SCSI 320-0 Controller) + +pci:v00001000d00001960sv00001028sd00000518* + ID_MODEL_FROM_DATABASE=MegaRAID (518 DELL PERC 4/DC RAID Controller) + +pci:v00001000d00001960sv00001028sd00000520* + ID_MODEL_FROM_DATABASE=MegaRAID (520 DELL PERC 4/SC RAID Controller) + +pci:v00001000d00001960sv00001028sd00000531* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge Expandable RAID Controller 4/QC) + +pci:v00001000d00001960sv00001028sd00000533* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge Expandable RAID Controller 4/QC) + +pci:v00001000d00001960sv00008086sd00000520* + ID_MODEL_FROM_DATABASE=MegaRAID (RAID Controller SRCU41L) + +pci:v00001000d00001960sv00008086sd00000523* + ID_MODEL_FROM_DATABASE=MegaRAID (RAID Controller SRCS16) + +pci:v00001000d00003050* + ID_MODEL_FROM_DATABASE=SAS2008 PCI-Express Fusion-MPT SAS-2 + +pci:v00001000d00006001* + ID_MODEL_FROM_DATABASE=DX1 Multiformat Broadcast HD/SD Encoder/Decoder + +pci:v00001001* + ID_VENDOR_FROM_DATABASE=Kolter Electronic + +pci:v00001001d00000010* + ID_MODEL_FROM_DATABASE=PCI 1616 Measurement card with 32 digital I/O lines + +pci:v00001001d00000011* + ID_MODEL_FROM_DATABASE=OPTO-PCI Opto-Isolated digital I/O board + +pci:v00001001d00000012* + ID_MODEL_FROM_DATABASE=PCI-AD/DA Analogue I/O board + +pci:v00001001d00000013* + ID_MODEL_FROM_DATABASE=PCI-OPTO-RELAIS Digital I/O board with relay outputs + +pci:v00001001d00000014* + ID_MODEL_FROM_DATABASE=PCI-Counter/Timer Counter Timer board + +pci:v00001001d00000015* + ID_MODEL_FROM_DATABASE=PCI-DAC416 Analogue output board + +pci:v00001001d00000016* + ID_MODEL_FROM_DATABASE=PCI-MFB Analogue I/O board + +pci:v00001001d00000017* + ID_MODEL_FROM_DATABASE=PROTO-3 PCI Prototyping board + +pci:v00001001d00009100* + ID_MODEL_FROM_DATABASE=INI-9100/9100W SCSI Host + +pci:v00001002* + ID_VENDOR_FROM_DATABASE=Advanced Micro Devices, Inc. [AMD/ATI] + +pci:v00001002d00001304* + ID_MODEL_FROM_DATABASE=Kaveri + +pci:v00001002d00001305* + ID_MODEL_FROM_DATABASE=Kaveri + +pci:v00001002d00001306* + ID_MODEL_FROM_DATABASE=Kaveri + +pci:v00001002d00001307* + ID_MODEL_FROM_DATABASE=Kaveri + +pci:v00001002d00001308* + ID_MODEL_FROM_DATABASE=Kaveri HDMI/DP Audio Controller + +pci:v00001002d00001309* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R6/R7 Graphics] + +pci:v00001002d0000130A* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R6 Graphics] + +pci:v00001002d0000130B* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R4 Graphics] + +pci:v00001002d0000130C* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R7 Graphics] + +pci:v00001002d0000130D* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R6 Graphics] + +pci:v00001002d0000130E* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R5 Graphics] + +pci:v00001002d0000130F* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R7 Graphics] + +pci:v00001002d00001310* + ID_MODEL_FROM_DATABASE=Kaveri + +pci:v00001002d00001311* + ID_MODEL_FROM_DATABASE=Kaveri + +pci:v00001002d00001312* + ID_MODEL_FROM_DATABASE=Kaveri + +pci:v00001002d00001313* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R7 Graphics] + +pci:v00001002d00001314* + ID_MODEL_FROM_DATABASE=Wrestler HDMI Audio + +pci:v00001002d00001314sv0000174Bsd00001001* + ID_MODEL_FROM_DATABASE=Wrestler HDMI Audio (PURE Fusion Mini) + +pci:v00001002d00001315* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R5 Graphics] + +pci:v00001002d00001316* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R5 Graphics] + +pci:v00001002d00001317* + ID_MODEL_FROM_DATABASE=Kaveri + +pci:v00001002d00001318* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R5 Graphics] + +pci:v00001002d0000131B* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R4 Graphics] + +pci:v00001002d0000131C* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R7 Graphics] + +pci:v00001002d0000131D* + ID_MODEL_FROM_DATABASE=Kaveri [Radeon R6 Graphics] + +pci:v00001002d000013E9* + ID_MODEL_FROM_DATABASE=Ariel + +pci:v00001002d00001478* + ID_MODEL_FROM_DATABASE=Navi 10 XL Upstream Port of PCI Express Switch + +pci:v00001002d00001479* + ID_MODEL_FROM_DATABASE=Navi 10 XL Downstream Port of PCI Express Switch + +pci:v00001002d0000154C* + ID_MODEL_FROM_DATABASE=Kryptos + +pci:v00001002d0000154E* + ID_MODEL_FROM_DATABASE=Garfield + +pci:v00001002d00001551* + ID_MODEL_FROM_DATABASE=Arlene + +pci:v00001002d00001552* + ID_MODEL_FROM_DATABASE=Pooky + +pci:v00001002d00001561* + ID_MODEL_FROM_DATABASE=Anubis + +pci:v00001002d000015D8* + ID_MODEL_FROM_DATABASE=Picasso + +pci:v00001002d000015D8sv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=Picasso (Pavilion Laptop 15-cw1xxx) + +pci:v00001002d000015DD* + ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] + +pci:v00001002d000015DDsv0000103Csd000083C6* + ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] (Radeon Vega 8 Mobile) + +pci:v00001002d000015DDsv00001458sd0000D000* + ID_MODEL_FROM_DATABASE=Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] (Radeon RX Vega 11) + +pci:v00001002d000015DE* + ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang HDMI/DP Audio Controller + +pci:v00001002d000015DEsv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang HDMI/DP Audio Controller (Pavilion Laptop 15-cw1xxx) + +pci:v00001002d000015DF* + ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang/Renoir Cryptographic Coprocessor + +pci:v00001002d000015DFsv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=Raven/Raven2/Fenghuang/Renoir Cryptographic Coprocessor (Pavilion Laptop 15-cw1xxx) + +pci:v00001002d000015FF* + ID_MODEL_FROM_DATABASE=Fenghuang [Zhongshan Subor Z+] + +pci:v00001002d00001607* + ID_MODEL_FROM_DATABASE=Arden + +pci:v00001002d00001636* + ID_MODEL_FROM_DATABASE=Renoir + +pci:v00001002d00001714* + ID_MODEL_FROM_DATABASE=BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series] + +pci:v00001002d00001714sv0000103Csd0000168B* + ID_MODEL_FROM_DATABASE=BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series] (ProBook 4535s) + +pci:v00001002d00003150* + ID_MODEL_FROM_DATABASE=RV380/M24 [Mobility Radeon X600] + +pci:v00001002d00003150sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=RV380/M24 [Mobility Radeon X600] (nx8220) + +pci:v00001002d00003151* + ID_MODEL_FROM_DATABASE=RV380 GL [FireMV 2400] + +pci:v00001002d00003152* + ID_MODEL_FROM_DATABASE=RV370/M22 [Mobility Radeon X300] + +pci:v00001002d00003154* + ID_MODEL_FROM_DATABASE=RV380/M24 GL [Mobility FireGL V3200] + +pci:v00001002d00003155* + ID_MODEL_FROM_DATABASE=RV380 GL [FireMV 2400] + +pci:v00001002d00003171* + ID_MODEL_FROM_DATABASE=RV380 GL [FireMV 2400] (Secondary) + +pci:v00001002d00003E50* + ID_MODEL_FROM_DATABASE=RV380 [Radeon X600] + +pci:v00001002d00003E54* + ID_MODEL_FROM_DATABASE=RV380 GL [FireGL V3200] + +pci:v00001002d00003E70* + ID_MODEL_FROM_DATABASE=RV380 [Radeon X600] (Secondary) + +pci:v00001002d00004136* + ID_MODEL_FROM_DATABASE=RS100 [Mobility IGP 320M] + +pci:v00001002d00004137* + ID_MODEL_FROM_DATABASE=RS200 [Radeon IGP 340] + +pci:v00001002d00004144* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9500] + +pci:v00001002d00004146* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9700 PRO] + +pci:v00001002d00004147* + ID_MODEL_FROM_DATABASE=R300 GL [FireGL Z1] + +pci:v00001002d00004148* + ID_MODEL_FROM_DATABASE=R350 [Radeon 9800/9800 SE] + +pci:v00001002d00004150* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] + +pci:v00001002d00004150sv00001002sd00000002* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (R9600 Pro primary (Asus OEM for HP)) + +pci:v00001002d00004150sv00001002sd00000003* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (R9600 Pro secondary (Asus OEM for HP)) + +pci:v00001002d00004150sv00001002sd00004722* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (All-in-Wonder 2006 AGP Edition) + +pci:v00001002d00004150sv00001458sd00004024* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (GV-R96128D) + +pci:v00001002d00004150sv0000148Csd00002064* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (R96A-C3N) + +pci:v00001002d00004150sv0000148Csd00002066* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (R96A-C3N) + +pci:v00001002d00004150sv0000174Bsd00007C19* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Atlantis Radeon 9600 Pro) + +pci:v00001002d00004150sv0000174Bsd00007C29* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (GC-R9600PRO) + +pci:v00001002d00004150sv000017EEsd00002002* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Radeon 9600 256Mb Primary) + +pci:v00001002d00004150sv000018BCsd00000101* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (GC-R9600PRO (Primary)) + +pci:v00001002d00004151* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600 Series] + +pci:v00001002d00004151sv00001043sd0000C004* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600 Series] (A9600SE) + +pci:v00001002d00004151sv0000174Bsd00007C37* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600 Series] (Radeon 9600SE 128M DDR V/D/VO) + +pci:v00001002d00004152* + ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] + +pci:v00001002d00004152sv00001002sd00000002* + ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (Radeon 9600XT) + +pci:v00001002d00004152sv00001002sd00004772* + ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (All-in-Wonder 9600 XT) + +pci:v00001002d00004152sv00001043sd0000C002* + ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (Radeon 9600 XT TVD) + +pci:v00001002d00004152sv00001043sd0000C01A* + ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (A9600XT/TD) + +pci:v00001002d00004152sv00001462sd00009510* + ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (RX9600XT (MS-8951)) + +pci:v00001002d00004152sv0000174Bsd00007C29* + ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (Radeon 9600XT) + +pci:v00001002d00004152sv00001787sd00004002* + ID_MODEL_FROM_DATABASE=RV360 [Radeon 9600/X1050 Series] (Radeon 9600 XT) + +pci:v00001002d00004153* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550] + +pci:v00001002d00004153sv00001043sd0000010C* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550] (A9550GE/TD) + +pci:v00001002d00004153sv00001462sd0000932C* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550] (RX9550SE-TD128 (MS-8932)) + +pci:v00001002d00004154* + ID_MODEL_FROM_DATABASE=RV350 GL [FireGL T2] + +pci:v00001002d00004155* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600] + +pci:v00001002d00004157* + ID_MODEL_FROM_DATABASE=RV350 GL [FireGL T2] + +pci:v00001002d00004158* + ID_MODEL_FROM_DATABASE=68800AX [Graphics Ultra Pro PCI] + +pci:v00001002d00004164* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO] (Secondary) + +pci:v00001002d00004165* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9700 PRO] (Secondary) + +pci:v00001002d00004166* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9700 PRO] (Secondary) + +pci:v00001002d00004168* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9800 SE] (Secondary) + +pci:v00001002d00004170* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) + +pci:v00001002d00004170sv00001002sd00000003* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (R9600 Pro secondary (Asus OEM for HP)) + +pci:v00001002d00004170sv00001002sd00004723* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (All-in-Wonder 2006 AGP Edition (Secondary)) + +pci:v00001002d00004170sv00001458sd00004025* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (GV-R96128D (Secondary)) + +pci:v00001002d00004170sv0000148Csd00002067* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (R96A-C3N (Secondary)) + +pci:v00001002d00004170sv0000174Bsd00007C28* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (GC-R9600PRO (Secondary)) + +pci:v00001002d00004170sv000017EEsd00002003* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (Radeon 9600 256Mb (Secondary)) + +pci:v00001002d00004170sv000018BCsd00000100* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] (Secondary) (GC-R9600PRO (Secondary)) + +pci:v00001002d00004171* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600] (Secondary) + +pci:v00001002d00004171sv00001043sd0000C005* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600] (Secondary) (A9600SE (Secondary)) + +pci:v00001002d00004171sv0000174Bsd00007C36* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600] (Secondary) (Radeon 9600SE 128M DDR V/D/VO (secondary)) + +pci:v00001002d00004172* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) + +pci:v00001002d00004172sv00001002sd00000003* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (Radeon 9600XT (Secondary)) + +pci:v00001002d00004172sv00001002sd00004773* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (All-in-Wonder 9600 XT (Secondary)) + +pci:v00001002d00004172sv00001043sd0000C003* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (A9600XT (Secondary)) + +pci:v00001002d00004172sv00001043sd0000C01B* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (A9600XT/TD (Secondary)) + +pci:v00001002d00004172sv0000174Bsd00007C28* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (Radeon 9600XT (Secondary)) + +pci:v00001002d00004172sv00001787sd00004003* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600/X1050 Series] (Secondary) (Radeon 9600 XT (Secondary)) + +pci:v00001002d00004173* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550] (Secondary) + +pci:v00001002d00004173sv00001043sd0000010D* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550] (Secondary) (A9550GE/TD (Secondary)) + +pci:v00001002d00004242* + ID_MODEL_FROM_DATABASE=R200 [All-In-Wonder Radeon 8500 DV] + +pci:v00001002d00004242sv00001002sd000002AA* + ID_MODEL_FROM_DATABASE=R200 [All-In-Wonder Radeon 8500 DV] (Radeon 8500 AIW DV Edition) + +pci:v00001002d00004243* + ID_MODEL_FROM_DATABASE=R200 PCI Bridge [All-in-Wonder Radeon 8500DV] + +pci:v00001002d00004336* + ID_MODEL_FROM_DATABASE=RS100 [Radeon IGP 320M] + +pci:v00001002d00004336sv00001002sd00004336* + ID_MODEL_FROM_DATABASE=RS100 [Radeon IGP 320M] (Pavilion ze4300 ATI Radeon Mobility U1 (IGP 320 M)) + +pci:v00001002d00004336sv0000103Csd00000024* + ID_MODEL_FROM_DATABASE=RS100 [Radeon IGP 320M] (Pavilion ze4400 builtin Video) + +pci:v00001002d00004336sv0000161Fsd00002029* + ID_MODEL_FROM_DATABASE=RS100 [Radeon IGP 320M] (eMachines M5312 builtin Video) + +pci:v00001002d00004337* + ID_MODEL_FROM_DATABASE=RS200M [Radeon IGP 330M/340M/345M/350M] + +pci:v00001002d00004337sv00001014sd0000053A* + ID_MODEL_FROM_DATABASE=RS200M [Radeon IGP 330M/340M/345M/350M] (ThinkPad R40e) + +pci:v00001002d00004337sv0000103Csd00000850* + ID_MODEL_FROM_DATABASE=RS200M [Radeon IGP 330M/340M/345M/350M] (Radeon IGP 345M) + +pci:v00001002d00004341* + ID_MODEL_FROM_DATABASE=SB200 AC97 Audio Controller + +pci:v00001002d00004342* + ID_MODEL_FROM_DATABASE=SB200 PCI to PCI Bridge + +pci:v00001002d00004345* + ID_MODEL_FROM_DATABASE=SB200 EHCI USB Controller + +pci:v00001002d00004346* + ID_MODEL_FROM_DATABASE=Crayola 6 [XENOS Parent Die (XBOX 360)] + +pci:v00001002d00004347* + ID_MODEL_FROM_DATABASE=SB200 OHCI USB Controller #1 + +pci:v00001002d00004348* + ID_MODEL_FROM_DATABASE=SB200 OHCI USB Controller #2 + +pci:v00001002d00004349* + ID_MODEL_FROM_DATABASE=SB200 IDE Controller + +pci:v00001002d0000434C* + ID_MODEL_FROM_DATABASE=SB200 PCI to LPC Bridge + +pci:v00001002d0000434D* + ID_MODEL_FROM_DATABASE=SB200 AC97 Modem Controller + +pci:v00001002d00004353* + ID_MODEL_FROM_DATABASE=SB200 SMBus Controller + +pci:v00001002d00004354* + ID_MODEL_FROM_DATABASE=215CT [Mach64 CT PCI] + +pci:v00001002d00004358* + ID_MODEL_FROM_DATABASE=Mach64 CX [Graphics Xpression] + +pci:v00001002d00004361* + ID_MODEL_FROM_DATABASE=SB300 AC'97 Audio Controller + +pci:v00001002d00004362* + ID_MODEL_FROM_DATABASE=SB300 PCI to PCI Bridge + +pci:v00001002d00004363* + ID_MODEL_FROM_DATABASE=SB300 SMBus Controller + +pci:v00001002d00004365* + ID_MODEL_FROM_DATABASE=SB300 USB Controller (EHCI) + +pci:v00001002d00004367* + ID_MODEL_FROM_DATABASE=SB300 USB Controller (EHCI) + +pci:v00001002d00004368* + ID_MODEL_FROM_DATABASE=SB300 USB Controller (EHCI) + +pci:v00001002d00004369* + ID_MODEL_FROM_DATABASE=SB300 IDE Controller + +pci:v00001002d0000436C* + ID_MODEL_FROM_DATABASE=SB300 PCI to LPC Bridge + +pci:v00001002d0000436D* + ID_MODEL_FROM_DATABASE=SB300 AC97 Modem Controller + +pci:v00001002d0000436E* + ID_MODEL_FROM_DATABASE=SB300 Serial ATA Controller + +pci:v00001002d00004370* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller + +pci:v00001002d00004370sv00001025sd00000079* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (Aspire 5024WLMMi) + +pci:v00001002d00004370sv00001025sd00000091* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (Aspire 5032WXMi) + +pci:v00001002d00004370sv0000103Csd00002A05* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (Pavilion t3030.de Desktop PC) + +pci:v00001002d00004370sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (MX6125) + +pci:v00001002d00004370sv0000105Bsd00000C81* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (Realtek ALC 653) + +pci:v00001002d00004370sv0000107Bsd00000300* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (MX6421) + +pci:v00001002d00004370sv00001462sd00000131* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Audio Controller (MS-1013 Notebook) + +pci:v00001002d00004371* + ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-PCI Bridge + +pci:v00001002d00004371sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-PCI Bridge (MX6125) + +pci:v00001002d00004371sv00001462sd00007217* + ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-PCI Bridge (Aspire L250) + +pci:v00001002d00004372* + ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller + +pci:v00001002d00004372sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller (Aspire 5024WLMMi) + +pci:v00001002d00004372sv0000103Csd00002A20* + ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller (Pavilion t3030.de Desktop PC) + +pci:v00001002d00004372sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller (MX6125) + +pci:v00001002d00004372sv00001462sd00000131* + ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller (MS-1013 Notebook) + +pci:v00001002d00004372sv00001462sd00007217* + ID_MODEL_FROM_DATABASE=IXP SB4x0 SMBus Controller (Aspire L250) + +pci:v00001002d00004373* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller + +pci:v00001002d00004373sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller (Aspire 5024WLMMi) + +pci:v00001002d00004373sv0000103Csd00002A20* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller (Pavilion t3030.de Desktop PC) + +pci:v00001002d00004373sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller (MX6125) + +pci:v00001002d00004373sv00001462sd00007217* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB2 Host Controller (Aspire L250) + +pci:v00001002d00004374* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller + +pci:v00001002d00004374sv0000103Csd00002A20* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (Pavilion t3030.de Desktop PC) + +pci:v00001002d00004374sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (MX6125) + +pci:v00001002d00004374sv00001462sd00007217* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (Aspire L250) + +pci:v00001002d00004375* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller + +pci:v00001002d00004375sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (Aspire 5024WLMMi) + +pci:v00001002d00004375sv0000103Csd00002A20* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (Pavilion t3030.de Desktop PC) + +pci:v00001002d00004375sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (MX6125) + +pci:v00001002d00004375sv00001462sd00007217* + ID_MODEL_FROM_DATABASE=IXP SB4x0 USB Host Controller (Aspire L250) + +pci:v00001002d00004376* + ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller + +pci:v00001002d00004376sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller (Aspire 5024WLMMi) + +pci:v00001002d00004376sv0000103Csd00002A20* + ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller (Pavilion t3030.de Desktop PC) + +pci:v00001002d00004376sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller (MX6125) + +pci:v00001002d00004376sv00001462sd00000131* + ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller (MS-1013 Notebook) + +pci:v00001002d00004376sv00001462sd00007217* + ID_MODEL_FROM_DATABASE=IXP SB4x0 IDE Controller (Aspire L250) + +pci:v00001002d00004377* + ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge + +pci:v00001002d00004377sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge (Aspire 5024WLMi) + +pci:v00001002d00004377sv0000103Csd00002A20* + ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge (Pavilion t3030.de Desktop PC) + +pci:v00001002d00004377sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge (MX6125) + +pci:v00001002d00004377sv00001462sd00007217* + ID_MODEL_FROM_DATABASE=IXP SB4x0 PCI-ISA Bridge (Aspire L250) + +pci:v00001002d00004378* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Modem Controller + +pci:v00001002d00004378sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Modem Controller (Aspire 5024WLMMi) + +pci:v00001002d00004378sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Modem Controller (MX6125) + +pci:v00001002d00004378sv00001462sd00000131* + ID_MODEL_FROM_DATABASE=IXP SB400 AC'97 Modem Controller (MS-1013 Notebook) + +pci:v00001002d00004379* + ID_MODEL_FROM_DATABASE=IXP SB4x0 Serial ATA Controller + +pci:v00001002d00004379sv00001462sd00007141* + ID_MODEL_FROM_DATABASE=IXP SB4x0 Serial ATA Controller (Aspire L250) + +pci:v00001002d0000437A* + ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller + +pci:v00001002d0000437Asv00001002sd00004379* + ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller (4379 Serial ATA Controller) + +pci:v00001002d0000437Asv00001002sd0000437A* + ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller (437A Serial ATA Controller) + +pci:v00001002d0000437Asv00001462sd00007141* + ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller (Aspire L250) + +pci:v00001002d0000437Asv000014F1sd00008800* + ID_MODEL_FROM_DATABASE=IXP SB400 Serial ATA Controller (Leadtek WinFast TV2000XP Expert) + +pci:v00001002d0000437B* + ID_MODEL_FROM_DATABASE=IXP SB4x0 High Definition Audio Controller + +pci:v00001002d0000437Bsv00001002sd0000437B* + ID_MODEL_FROM_DATABASE=IXP SB4x0 High Definition Audio Controller + +pci:v00001002d0000437Bsv000010CFsd00001326* + ID_MODEL_FROM_DATABASE=IXP SB4x0 High Definition Audio Controller (Fujitsu Lifebook A3040) + +pci:v00001002d0000437Bsv00001734sd000010B8* + ID_MODEL_FROM_DATABASE=IXP SB4x0 High Definition Audio Controller (Realtek High Definition Audio) + +pci:v00001002d00004380* + ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA + +pci:v00001002d00004380sv0000103Csd00002813* + ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (DC5750 Microtower) + +pci:v00001002d00004380sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (Satellite P305D-S8995E) + +pci:v00001002d00004380sv00001458sd0000B003* + ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (GA-MA790FX-DS5 (rev. 1.0)) + +pci:v00001002d00004380sv00001458sd0000B005* + ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (Gigabyte GA-MA69G-S3H Motherboard) + +pci:v00001002d00004380sv00001462sd00007327* + ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (K9AG Neo2) + +pci:v00001002d00004380sv000017F2sd00005999* + ID_MODEL_FROM_DATABASE=SB600 Non-Raid-5 SATA (KI690-AM2 Motherboard) + +pci:v00001002d00004381* + ID_MODEL_FROM_DATABASE=SB600 SATA Controller (RAID 5 mode) + +pci:v00001002d00004382* + ID_MODEL_FROM_DATABASE=SB600 AC97 Audio + +pci:v00001002d00004383* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) + +pci:v00001002d00004383sv00001019sd00002120* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (A785GM-M) + +pci:v00001002d00004383sv0000103Csd00001611* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (Pavilion DM1Z-3000) + +pci:v00001002d00004383sv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (DC5750 Microtower) + +pci:v00001002d00004383sv00001043sd00008230* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (M3A78-EH Motherboard) + +pci:v00001002d00004383sv00001043sd0000836C* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (M4A785TD Motherboard) + +pci:v00001002d00004383sv00001043sd00008410* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (M4A89GTD PRO/USB3 Motherboard) + +pci:v00001002d00004383sv00001043sd0000841B* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (M5A88-V EVO) + +pci:v00001002d00004383sv00001043sd00008445* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (M5A78L LE) + +pci:v00001002d00004383sv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d00004383sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (Satellite P305D-S8995E) + +pci:v00001002d00004383sv00001458sd0000A022* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (GA-MA770-DS3rev2.0 Motherboard) + +pci:v00001002d00004383sv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=SBx00 Azalia (Intel HDA) (KI690-AM2 Motherboard) + +pci:v00001002d00004384* + ID_MODEL_FROM_DATABASE=SBx00 PCI to PCI Bridge + +pci:v00001002d00004385* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller + +pci:v00001002d00004385sv00001019sd00002120* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (A785GM-M) + +pci:v00001002d00004385sv0000103Csd00001611* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (Pavilion DM1Z-3000) + +pci:v00001002d00004385sv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (DC5750 Microtower) + +pci:v00001002d00004385sv00001043sd000082EF* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (M3A78-EH Motherboard) + +pci:v00001002d00004385sv00001043sd00008389* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (M4A785TD Motherboard) + +pci:v00001002d00004385sv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d00004385sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (Satellite P305D-S8995E) + +pci:v00001002d00004385sv00001458sd00004385* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (GA-MA770-DS3rev2.0 Motherboard) + +pci:v00001002d00004385sv00001462sd00007368* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (K9AG Neo2) + +pci:v00001002d00004385sv000015D9sd0000A811* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (H8DGU) + +pci:v00001002d00004385sv0000174Bsd00001001* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (PURE Fusion Mini) + +pci:v00001002d00004385sv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=SBx00 SMBus Controller (KI690-AM2 Motherboard) + +pci:v00001002d00004386* + ID_MODEL_FROM_DATABASE=SB600 USB Controller (EHCI) + +pci:v00001002d00004386sv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=SB600 USB Controller (EHCI) (DC5750 Microtower) + +pci:v00001002d00004386sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SB600 USB Controller (EHCI) (Satellite P305D-S8995E) + +pci:v00001002d00004386sv00001462sd00007368* + ID_MODEL_FROM_DATABASE=SB600 USB Controller (EHCI) (K9AG Neo2) + +pci:v00001002d00004386sv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=SB600 USB Controller (EHCI) (KI690-AM2 Motherboard) + +pci:v00001002d00004387* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI0) + +pci:v00001002d00004387sv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI0) (DC5750 Microtower) + +pci:v00001002d00004387sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI0) (Satellite P305D-S8995E) + +pci:v00001002d00004387sv00001462sd00007368* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI0) (K9AG Neo2) + +pci:v00001002d00004387sv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI0) (KI690-AM2 Motherboard) + +pci:v00001002d00004388* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI1) + +pci:v00001002d00004388sv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI1) (DC5750 Microtower) + +pci:v00001002d00004388sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI1) (Satellite P305D-S8995E) + +pci:v00001002d00004388sv00001462sd00007368* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI1) (K9AG Neo2) + +pci:v00001002d00004388sv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI1) (KI690-AM2 Motherboard) + +pci:v00001002d00004389* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI2) + +pci:v00001002d00004389sv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI2) (DC5750 Microtower) + +pci:v00001002d00004389sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI2) (Satellite P305D-S8995E) + +pci:v00001002d00004389sv00001462sd00007368* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI2) (K9AG Neo2) + +pci:v00001002d00004389sv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI2) (KI690-AM2 Motherboard) + +pci:v00001002d0000438A* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI3) + +pci:v00001002d0000438Asv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI3) (DC5750 Microtower) + +pci:v00001002d0000438Asv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI3) (Satellite P305D-S8995E) + +pci:v00001002d0000438Asv00001462sd00007368* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI3) (K9AG Neo2) + +pci:v00001002d0000438Asv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI3) (KI690-AM2 Motherboard) + +pci:v00001002d0000438B* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI4) + +pci:v00001002d0000438Bsv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI4) (DC5750 Microtower) + +pci:v00001002d0000438Bsv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI4) (Satellite P305D-S8995E) + +pci:v00001002d0000438Bsv00001462sd00007368* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI4) (K9AG Neo2) + +pci:v00001002d0000438Bsv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=SB600 USB (OHCI4) (KI690-AM2 Motherboard) + +pci:v00001002d0000438C* + ID_MODEL_FROM_DATABASE=SB600 IDE + +pci:v00001002d0000438Csv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=SB600 IDE (DC5750 Microtower) + +pci:v00001002d0000438Csv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SB600 IDE (Satellite P305D-S8995E) + +pci:v00001002d0000438Csv00001458sd00005002* + ID_MODEL_FROM_DATABASE=SB600 IDE (Gigabyte GA-MA69G-S3H Motherboard) + +pci:v00001002d0000438Csv00001462sd00007368* + ID_MODEL_FROM_DATABASE=SB600 IDE (K9AG Neo2) + +pci:v00001002d0000438Csv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=SB600 IDE (KI690-AM2 Motherboard) + +pci:v00001002d0000438D* + ID_MODEL_FROM_DATABASE=SB600 PCI to LPC Bridge + +pci:v00001002d0000438Dsv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=SB600 PCI to LPC Bridge (DC5750 Microtower) + +pci:v00001002d0000438Dsv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=SB600 PCI to LPC Bridge (Satellite P305D-S8995E) + +pci:v00001002d0000438Dsv00001462sd00007368* + ID_MODEL_FROM_DATABASE=SB600 PCI to LPC Bridge (K9AG Neo2) + +pci:v00001002d0000438Dsv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=SB600 PCI to LPC Bridge (KI690-AM2 Motherboard) + +pci:v00001002d0000438E* + ID_MODEL_FROM_DATABASE=SB600 AC97 Modem + +pci:v00001002d00004390* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] + +pci:v00001002d00004390sv00001043sd000082EF* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (M3A78-EH Motherboard) + +pci:v00001002d00004390sv00001043sd00008389* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (M4A785TD Motherboard) + +pci:v00001002d00004390sv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d00004390sv00001458sd0000B002* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (GA-MA770-DS3rev2.0 Motherboard) + +pci:v00001002d00004390sv00001849sd00004390* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] (Motherboard (one of many)) + +pci:v00001002d00004391* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] + +pci:v00001002d00004391sv0000103Csd00001609* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (ProLiant MicroServer N36L) + +pci:v00001002d00004391sv0000103Csd00001611* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (Pavilion DM1Z-3000) + +pci:v00001002d00004391sv00001043sd000082EF* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (M3A78-EH Motherboard) + +pci:v00001002d00004391sv00001043sd00008443* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (M5A88-V EVO) + +pci:v00001002d00004391sv00001043sd000084DD* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (M5A99X EVO (R1.0) SB950) + +pci:v00001002d00004391sv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d00004391sv0000174Bsd00001001* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] (PURE Fusion Mini) + +pci:v00001002d00004392* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [Non-RAID5 mode] + +pci:v00001002d00004392sv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [Non-RAID5 mode] (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d00004393* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [RAID5 mode] + +pci:v00001002d00004394* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] + +pci:v00001002d00004395* + ID_MODEL_FROM_DATABASE=SB8x0/SB9x0 SATA Controller [Storage mode] + +pci:v00001002d00004396* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller + +pci:v00001002d00004396sv00001019sd00002120* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (A785GM-M) + +pci:v00001002d00004396sv0000103Csd00001609* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (ProLiant MicroServer N36L) + +pci:v00001002d00004396sv0000103Csd00001611* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (Pavilion DM1Z-3000) + +pci:v00001002d00004396sv00001043sd000082EF* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (M3A78-EH Motherboard) + +pci:v00001002d00004396sv00001043sd00008443* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (M5A88-V EVO) + +pci:v00001002d00004396sv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d00004396sv000015D9sd0000A811* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (H8DGU) + +pci:v00001002d00004396sv0000174Bsd00001001* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB EHCI Controller (PURE Fusion Mini) + +pci:v00001002d00004397* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller + +pci:v00001002d00004397sv00001019sd00002120* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (A785GM-M) + +pci:v00001002d00004397sv0000103Csd00001609* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (ProLiant MicroServer N36L) + +pci:v00001002d00004397sv0000103Csd00001611* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (Pavilion DM1Z-3000) + +pci:v00001002d00004397sv00001043sd000082EF* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (M3A78-EH Motherboard) + +pci:v00001002d00004397sv00001043sd00008443* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (M5A88-V EVO) + +pci:v00001002d00004397sv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d00004397sv000015D9sd0000A811* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (H8DGU) + +pci:v00001002d00004397sv0000174Bsd00001001* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI0 Controller (PURE Fusion Mini) + +pci:v00001002d00004398* + ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller + +pci:v00001002d00004398sv00001019sd00002120* + ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller (A785GM-M) + +pci:v00001002d00004398sv00001043sd000082EF* + ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller (M3A78-EH Motherboard) + +pci:v00001002d00004398sv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d00004398sv000015D9sd0000A811* + ID_MODEL_FROM_DATABASE=SB7x0 USB OHCI1 Controller (H8DGU) + +pci:v00001002d00004399* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller + +pci:v00001002d00004399sv00001019sd00002120* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (A785GM-M) + +pci:v00001002d00004399sv00001043sd000082EF* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (M3A78-EH Motherboard) + +pci:v00001002d00004399sv00001043sd00008443* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (M5A88-V EVO) + +pci:v00001002d00004399sv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d00004399sv0000174Bsd00001001* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 USB OHCI2 Controller (PURE Fusion Mini) + +pci:v00001002d0000439C* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller + +pci:v00001002d0000439Csv00001002sd00004392* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller (MSI MS-7713 motherboard) + +pci:v00001002d0000439Csv00001019sd00002120* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller (A785GM-M) + +pci:v00001002d0000439Csv0000103Csd00001609* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller (ProLiant MicroServer N36L) + +pci:v00001002d0000439Csv00001043sd000082EF* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller (M3A78-EH Motherboard) + +pci:v00001002d0000439Csv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 IDE Controller (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d0000439D* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller + +pci:v00001002d0000439Dsv00001019sd00002120* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (A785GM-M) + +pci:v00001002d0000439Dsv0000103Csd00001609* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (ProLiant MicroServer N36L) + +pci:v00001002d0000439Dsv0000103Csd00001611* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (Pavilion DM1Z-3000) + +pci:v00001002d0000439Dsv00001043sd000082EF* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (M3A78-EH Motherboard) + +pci:v00001002d0000439Dsv00001043sd00008443* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (M5A88-V EVO) + +pci:v00001002d0000439Dsv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (N15235/A74MX mainboard / AMD SB700) + +pci:v00001002d0000439Dsv0000174Bsd00001001* + ID_MODEL_FROM_DATABASE=SB7x0/SB8x0/SB9x0 LPC host controller (PURE Fusion Mini) + +pci:v00001002d000043A0* + ID_MODEL_FROM_DATABASE=SB700/SB800/SB900 PCI to PCI bridge (PCIE port 0) + +pci:v00001002d000043A1* + ID_MODEL_FROM_DATABASE=SB700/SB800/SB900 PCI to PCI bridge (PCIE port 1) + +pci:v00001002d000043A2* + ID_MODEL_FROM_DATABASE=SB900 PCI to PCI bridge (PCIE port 2) + +pci:v00001002d000043A3* + ID_MODEL_FROM_DATABASE=SB900 PCI to PCI bridge (PCIE port 3) + +pci:v00001002d00004437* + ID_MODEL_FROM_DATABASE=RS250 [Mobility Radeon 7000 IGP] + +pci:v00001002d00004554* + ID_MODEL_FROM_DATABASE=210888ET [Mach64 ET] + +pci:v00001002d00004630* + ID_MODEL_FROM_DATABASE=XENOS Parent Die (XBOX 360) + +pci:v00001002d00004631* + ID_MODEL_FROM_DATABASE=XENOS Daughter Die (XBOX 360) + +pci:v00001002d00004654* + ID_MODEL_FROM_DATABASE=Mach64 VT + +pci:v00001002d00004742* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] + +pci:v00001002d00004742sv00001002sd00000040* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X) + +pci:v00001002d00004742sv00001002sd00000044* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X) + +pci:v00001002d00004742sv00001002sd00000061* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro AIW AGP 2X) + +pci:v00001002d00004742sv00001002sd00000062* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro AIW AGP 2X) + +pci:v00001002d00004742sv00001002sd00000063* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro AIW AGP 2X) + +pci:v00001002d00004742sv00001002sd00000080* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X) + +pci:v00001002d00004742sv00001002sd00000084* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X) + +pci:v00001002d00004742sv00001002sd00004742* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X) + +pci:v00001002d00004742sv00001002sd00008001* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X) + +pci:v00001002d00004742sv00001028sd00000082* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X) + +pci:v00001002d00004742sv00001028sd00004082* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Optiplex GX1 Onboard Display Adapter) + +pci:v00001002d00004742sv00001028sd00008082* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X) + +pci:v00001002d00004742sv00001028sd0000C082* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X) + +pci:v00001002d00004742sv00008086sd00004152* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Xpert 98D AGP 2X) + +pci:v00001002d00004742sv00008086sd0000464A* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 2X] (Rage Pro Turbo AGP 2X) + +pci:v00001002d00004744* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 1X] + +pci:v00001002d00004744sv00001002sd00004744* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 1X] (Rage Pro Turbo AGP) + +pci:v00001002d00004744sv00008086sd00004D55* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage PRO AGP 1X] (Rage 3D Pro AGP 1X [Intel MU440EX]) + +pci:v00001002d00004749* + ID_MODEL_FROM_DATABASE=3D Rage PRO PCI + +pci:v00001002d00004749sv00001002sd00000061* + ID_MODEL_FROM_DATABASE=3D Rage PRO PCI (Rage Pro AIW) + +pci:v00001002d00004749sv00001002sd00000062* + ID_MODEL_FROM_DATABASE=3D Rage PRO PCI (Rage Pro AIW) + +pci:v00001002d0000474D* + ID_MODEL_FROM_DATABASE=Rage XL AGP 2X + +pci:v00001002d0000474Dsv00001002sd00000004* + ID_MODEL_FROM_DATABASE=Rage XL AGP 2X (Xpert 98 RXL AGP 2X) + +pci:v00001002d0000474Dsv00001002sd00000008* + ID_MODEL_FROM_DATABASE=Rage XL AGP 2X (Xpert 98 RXL AGP 2X) + +pci:v00001002d0000474Dsv00001002sd00000080* + ID_MODEL_FROM_DATABASE=Rage XL AGP 2X + +pci:v00001002d0000474Dsv00001002sd00000084* + ID_MODEL_FROM_DATABASE=Rage XL AGP 2X (Xpert 98 AGP 2X) + +pci:v00001002d0000474Dsv00001002sd0000474D* + ID_MODEL_FROM_DATABASE=Rage XL AGP 2X (Rage XL AGP) + +pci:v00001002d0000474Dsv00001033sd0000806A* + ID_MODEL_FROM_DATABASE=Rage XL AGP 2X (Rage XL AGP) + +pci:v00001002d0000474E* + ID_MODEL_FROM_DATABASE=Rage XC AGP + +pci:v00001002d0000474Esv00001002sd0000474E* + ID_MODEL_FROM_DATABASE=Rage XC AGP + +pci:v00001002d0000474F* + ID_MODEL_FROM_DATABASE=Rage XL + +pci:v00001002d0000474Fsv00001002sd00000008* + ID_MODEL_FROM_DATABASE=Rage XL + +pci:v00001002d0000474Fsv00001002sd0000474F* + ID_MODEL_FROM_DATABASE=Rage XL + +pci:v00001002d00004750* + ID_MODEL_FROM_DATABASE=3D Rage Pro PCI + +pci:v00001002d00004750sv00001002sd00000040* + ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo) + +pci:v00001002d00004750sv00001002sd00000044* + ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo) + +pci:v00001002d00004750sv00001002sd00000080* + ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo) + +pci:v00001002d00004750sv00001002sd00000084* + ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo) + +pci:v00001002d00004750sv00001002sd00004750* + ID_MODEL_FROM_DATABASE=3D Rage Pro PCI (Rage Pro Turbo) + +pci:v00001002d00004752* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] + +pci:v00001002d00004752sv00000E11sd0000001E* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (Proliant Rage XL) + +pci:v00001002d00004752sv00001002sd00000008* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (Rage XL) + +pci:v00001002d00004752sv00001002sd00004752* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (Proliant Rage XL) + +pci:v00001002d00004752sv00001002sd00008008* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (Rage XL) + +pci:v00001002d00004752sv00001014sd00000240* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (eServer xSeries server mainboard) + +pci:v00001002d00004752sv00001028sd000000CE* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 1400) + +pci:v00001002d00004752sv00001028sd000000D1* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 2550) + +pci:v00001002d00004752sv00001028sd000000D9* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 2500) + +pci:v00001002d00004752sv00001028sd00000134* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 600SC) + +pci:v00001002d00004752sv00001028sd0000014A* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 1750) + +pci:v00001002d00004752sv00001028sd00000165* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PowerEdge 750) + +pci:v00001002d00004752sv0000103Csd000010E1* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (NetServer Rage XL) + +pci:v00001002d00004752sv0000103Csd00003208* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (ProLiant DL140 G2) + +pci:v00001002d00004752sv0000107Bsd00006400* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (6400 Server) + +pci:v00001002d00004752sv00001734sd0000007A* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (PRIMERGY RX/TX series onboard VGA) + +pci:v00001002d00004752sv00001734sd00001073* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (Primergy Econel 200 D2020 mainboard) + +pci:v00001002d00004752sv00008086sd00003411* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (SDS2 Mainboard) + +pci:v00001002d00004752sv00008086sd00003427* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (S875WP1-E mainboard) + +pci:v00001002d00004752sv00008086sd00005744* + ID_MODEL_FROM_DATABASE=Rage 3 [Rage XL PCI] (S845WD1-E mainboard) + +pci:v00001002d00004753* + ID_MODEL_FROM_DATABASE=Rage XC + +pci:v00001002d00004753sv00001002sd00004753* + ID_MODEL_FROM_DATABASE=Rage XC + +pci:v00001002d00004754* + ID_MODEL_FROM_DATABASE=Mach64 GT/GT-B [3D Rage I/II] + +pci:v00001002d00004755* + ID_MODEL_FROM_DATABASE=Mach64 GT-B [3D Rage II+ DVD] + +pci:v00001002d00004756* + ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC PCI] + +pci:v00001002d00004756sv00001002sd00004756* + ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC PCI] (Rage IIC) + +pci:v00001002d00004757* + ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] + +pci:v00001002d00004757sv00001002sd00004757* + ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (Rage IIC AGP) + +pci:v00001002d00004757sv00001028sd00000089* + ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (Rage 3D IIC) + +pci:v00001002d00004757sv00001028sd0000008E* + ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (PowerEdge 1300 onboard video) + +pci:v00001002d00004757sv00001028sd00004082* + ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (Rage 3D IIC) + +pci:v00001002d00004757sv00001028sd00008082* + ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (Rage 3D IIC) + +pci:v00001002d00004757sv00001028sd0000C082* + ID_MODEL_FROM_DATABASE=Rage 2 [3D Rage IIC AGP] (Rage 3D IIC) + +pci:v00001002d00004758* + ID_MODEL_FROM_DATABASE=Mach64 GX [WinTurbo] + +pci:v00001002d00004759* + ID_MODEL_FROM_DATABASE=Rage 3 [3D Rage IIC PCI] + +pci:v00001002d0000475A* + ID_MODEL_FROM_DATABASE=3D Rage IIC AGP + +pci:v00001002d0000475Asv00001002sd00000084* + ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D Pro AGP 2x XPERT 98) + +pci:v00001002d0000475Asv00001002sd00000087* + ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage 3D IIC) + +pci:v00001002d0000475Asv00001002sd0000475A* + ID_MODEL_FROM_DATABASE=3D Rage IIC AGP (Rage IIC AGP) + +pci:v00001002d00004845* + ID_MODEL_FROM_DATABASE=Xilleon 220 HBIU for HDTV2 + +pci:v00001002d00004846* + ID_MODEL_FROM_DATABASE=Xilleon 220 IDE for HDTV2 + +pci:v00001002d00004847* + ID_MODEL_FROM_DATABASE=Xilleon 220 USB for HDTV2 + +pci:v00001002d00004848* + ID_MODEL_FROM_DATABASE=Xilleon 220 DAIO-0 for HDTV2 + +pci:v00001002d00004849* + ID_MODEL_FROM_DATABASE=Xilleon 220 DAIO-1 for HDTV2 + +pci:v00001002d0000484A* + ID_MODEL_FROM_DATABASE=Xilleon 220 LPC for HDTV2 + +pci:v00001002d00004850* + ID_MODEL_FROM_DATABASE=Xilleon 215 HBIU for X215 + +pci:v00001002d00004851* + ID_MODEL_FROM_DATABASE=Xilleon 215 IDE for X215 + +pci:v00001002d00004852* + ID_MODEL_FROM_DATABASE=Xilleon 215 USB for X215 + +pci:v00001002d00004853* + ID_MODEL_FROM_DATABASE=Xilleon 215 DAIO-0 for X215 + +pci:v00001002d00004854* + ID_MODEL_FROM_DATABASE=Xilleon 215 DAIO-1 for X215 + +pci:v00001002d00004855* + ID_MODEL_FROM_DATABASE=Xilleon 225 HBIU for X225 + +pci:v00001002d00004856* + ID_MODEL_FROM_DATABASE=Xilleon 225 IDE for X225 + +pci:v00001002d00004857* + ID_MODEL_FROM_DATABASE=Xilleon 225 USB for X225 + +pci:v00001002d00004858* + ID_MODEL_FROM_DATABASE=Xilleon 225 DAIO-0 for X225 + +pci:v00001002d00004859* + ID_MODEL_FROM_DATABASE=Xilleon 225 DAIO-1 for X225 + +pci:v00001002d00004860* + ID_MODEL_FROM_DATABASE=Xilleon 210 HBIU for X210 + +pci:v00001002d00004861* + ID_MODEL_FROM_DATABASE=Xilleon 210 IDE for X210 + +pci:v00001002d00004862* + ID_MODEL_FROM_DATABASE=Xilleon 210 USB for X210 + +pci:v00001002d00004863* + ID_MODEL_FROM_DATABASE=Xilleon 210 DAIO-0 for X210 + +pci:v00001002d00004864* + ID_MODEL_FROM_DATABASE=Xilleon 210 DAIO-1 for X210 + +pci:v00001002d00004865* + ID_MODEL_FROM_DATABASE=Xilleon 226 HBIU for X226 + +pci:v00001002d00004866* + ID_MODEL_FROM_DATABASE=Xilleon 226 IDE for X226 + +pci:v00001002d00004867* + ID_MODEL_FROM_DATABASE=Xilleon 226 USB for X226 + +pci:v00001002d00004868* + ID_MODEL_FROM_DATABASE=Xilleon 226 DAIO-0 for X226 + +pci:v00001002d00004869* + ID_MODEL_FROM_DATABASE=Xilleon 226 DAIO-1 for X226 + +pci:v00001002d0000486A* + ID_MODEL_FROM_DATABASE=Xilleon 240S HBIU for X240S + +pci:v00001002d0000486B* + ID_MODEL_FROM_DATABASE=Xilleon 240H HBIU for X240H + +pci:v00001002d0000486C* + ID_MODEL_FROM_DATABASE=Xilleon 240S USB for X240S + +pci:v00001002d0000486D* + ID_MODEL_FROM_DATABASE=Xilleon 240H USB for X240H + +pci:v00001002d0000486E* + ID_MODEL_FROM_DATABASE=Xilleon 250 USB 1.1 for X250 + +pci:v00001002d0000486F* + ID_MODEL_FROM_DATABASE=Xilleon 260 USB 1.1 for X260 + +pci:v00001002d00004870* + ID_MODEL_FROM_DATABASE=Xilleon 250 HBIU for X250 + +pci:v00001002d00004871* + ID_MODEL_FROM_DATABASE=Xilleon 250 IDE for X250 + +pci:v00001002d00004872* + ID_MODEL_FROM_DATABASE=Xilleon 234/235 HBIU for X234/X235 + +pci:v00001002d00004873* + ID_MODEL_FROM_DATABASE=Xilleon 244/245 HBIU for X244/X245 + +pci:v00001002d00004874* + ID_MODEL_FROM_DATABASE=Xilleon 234/235 USB 1.1 for X234/X235 + +pci:v00001002d00004875* + ID_MODEL_FROM_DATABASE=Xilleon 260 HBIU for X260 + +pci:v00001002d00004876* + ID_MODEL_FROM_DATABASE=Xilleon 260 IDE for X260 + +pci:v00001002d00004877* + ID_MODEL_FROM_DATABASE=Xilleon 244/245 USB 1.1 for X244/X245 + +pci:v00001002d00004878* + ID_MODEL_FROM_DATABASE=Xilleon 270 HBIU for X270 + +pci:v00001002d0000487B* + ID_MODEL_FROM_DATABASE=Xilleon 242 HBIU for X242 + +pci:v00001002d0000487D* + ID_MODEL_FROM_DATABASE=Xilleon 242 USB 1.1 for X242 + +pci:v00001002d00004880* + ID_MODEL_FROM_DATABASE=Xilleon 254 HBIU for X254 + +pci:v00001002d00004881* + ID_MODEL_FROM_DATABASE=Xilleon 254 USB 1.1 for X254 + +pci:v00001002d00004882* + ID_MODEL_FROM_DATABASE=Xilleon 255 HBIU for X255 + +pci:v00001002d00004883* + ID_MODEL_FROM_DATABASE=Xilleon 255 USB 1.1 for X255 + +pci:v00001002d00004884* + ID_MODEL_FROM_DATABASE=Xilleon 243 HBIU for X243 + +pci:v00001002d00004885* + ID_MODEL_FROM_DATABASE=Xilleon 243 USB 1.1 for X243 + +pci:v00001002d00004886* + ID_MODEL_FROM_DATABASE=Xilleon 233 HBIU for X233 + +pci:v00001002d00004887* + ID_MODEL_FROM_DATABASE=Xilleon 233 USB 1.1 for X233 + +pci:v00001002d00004888* + ID_MODEL_FROM_DATABASE=Xilleon 143 HBIU for X143 + +pci:v00001002d00004889* + ID_MODEL_FROM_DATABASE=Xilleon 143 HBIU for X143L + +pci:v00001002d0000488A* + ID_MODEL_FROM_DATABASE=Xilleon 143 HBIU for X143S + +pci:v00001002d00004966* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] + +pci:v00001002d00004966sv000010F1sd00000002* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Tachyon G9000 PRO]) + +pci:v00001002d00004966sv0000148Csd00002039* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Radeon 9000 Pro "Evil Commando"]) + +pci:v00001002d00004966sv00001509sd00009A00* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Radeon 9000 "AT009"]) + +pci:v00001002d00004966sv00001681sd00000040* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [3D prophet 9000]) + +pci:v00001002d00004966sv0000174Bsd00007176* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (Radeon 9000 Pro) + +pci:v00001002d00004966sv0000174Bsd00007192* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Radeon 9000 "Atlantis"]) + +pci:v00001002d00004966sv000017AFsd00002005* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Excalibur Radeon 9000 Pro]) + +pci:v00001002d00004966sv000017AFsd00002006* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (RV250 If [Excalibur Radeon 9000]) + +pci:v00001002d0000496E* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000] (Secondary) + +pci:v00001002d00004A49* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 PRO/GTO AGP] + +pci:v00001002d00004A49sv0000174Bsd00002620* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 PRO/GTO AGP] (R420 [Radeon X800 GTO AGP]) + +pci:v00001002d00004A4A* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 GT AGP] + +pci:v00001002d00004A4B* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 AGP Series] + +pci:v00001002d00004A4D* + ID_MODEL_FROM_DATABASE=R420 GL [FireGL X3-256] + +pci:v00001002d00004A4E* + ID_MODEL_FROM_DATABASE=RV420/M18 [Mobility Radeon 9800] + +pci:v00001002d00004A4F* + ID_MODEL_FROM_DATABASE=R420 [Radeon X850 AGP] + +pci:v00001002d00004A50* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 XT Platinum Edition AGP] + +pci:v00001002d00004A54* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 VE AGP] + +pci:v00001002d00004A54sv00001002sd00004422* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 VE AGP] (All-In-Wonder X800 VE AGP) + +pci:v00001002d00004A69* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 PRO/GTO] (Secondary) + +pci:v00001002d00004A6A* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800] (Secondary) + +pci:v00001002d00004A6B* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 XT AGP] (Secondary) + +pci:v00001002d00004A70* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 XT Platinum Edition AGP] (Secondary) + +pci:v00001002d00004A74* + ID_MODEL_FROM_DATABASE=R420 [Radeon X800 VE] (Secondary) + +pci:v00001002d00004B49* + ID_MODEL_FROM_DATABASE=R481 [Radeon X850 XT AGP] + +pci:v00001002d00004B4B* + ID_MODEL_FROM_DATABASE=R481 [Radeon X850 PRO AGP] + +pci:v00001002d00004B4C* + ID_MODEL_FROM_DATABASE=R481 [Radeon X850 XT Platinum Edition AGP] + +pci:v00001002d00004B69* + ID_MODEL_FROM_DATABASE=R481 [Radeon X850 XT AGP] (Secondary) + +pci:v00001002d00004B6B* + ID_MODEL_FROM_DATABASE=R481 [Radeon X850 PRO AGP] (Secondary) + +pci:v00001002d00004B6C* + ID_MODEL_FROM_DATABASE=R481 [Radeon X850 XT Platinum Edition AGP] (Secondary) + +pci:v00001002d00004C42* + ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] + +pci:v00001002d00004C42sv00000E11sd0000B0E7* + ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage LT Pro (Compaq Presario 5240)) + +pci:v00001002d00004C42sv00000E11sd0000B0E8* + ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage 3D LT Pro) + +pci:v00001002d00004C42sv00000E11sd0000B10E* + ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (3D Rage LT Pro (Compaq Armada 1750)) + +pci:v00001002d00004C42sv00001002sd00000040* + ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage LT Pro AGP 2X) + +pci:v00001002d00004C42sv00001002sd00000044* + ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage LT Pro AGP 2X) + +pci:v00001002d00004C42sv00001002sd00004C42* + ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage LT Pro AGP 2X) + +pci:v00001002d00004C42sv00001002sd00008001* + ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage LT Pro AGP 2X) + +pci:v00001002d00004C42sv00001028sd00000085* + ID_MODEL_FROM_DATABASE=Mach64 LT [3D Rage LT PRO AGP] (Rage 3D LT Pro) + +pci:v00001002d00004C46* + ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 + +pci:v00001002d00004C46sv00001002sd00000155* + ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 (IBM Thinkpad A22p) + +pci:v00001002d00004C46sv00001014sd00000155* + ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 (Thinkpad A22p) + +pci:v00001002d00004C46sv00001028sd000000B1* + ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 2X/Mobility M3 (Latitude C600) + +pci:v00001002d00004C47* + ID_MODEL_FROM_DATABASE=3D Rage IIC PCI / Mobility Radeon 7500/7500C + +pci:v00001002d00004C49* + ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI + +pci:v00001002d00004C49sv00001002sd00000004* + ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI (Rage LT Pro) + +pci:v00001002d00004C49sv00001002sd00000040* + ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI (Rage LT Pro) + +pci:v00001002d00004C49sv00001002sd00000044* + ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI (Rage LT Pro) + +pci:v00001002d00004C49sv00001002sd00004C49* + ID_MODEL_FROM_DATABASE=3D Rage LT PRO PCI (Rage LT Pro) + +pci:v00001002d00004C4D* + ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series + +pci:v00001002d00004C4Dsv00000E11sd0000B111* + ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Armada M700) + +pci:v00001002d00004C4Dsv00000E11sd0000B160* + ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Armada E500) + +pci:v00001002d00004C4Dsv00001002sd00000084* + ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Xpert 98 AGP 2X (Mobility)) + +pci:v00001002d00004C4Dsv00001014sd00000154* + ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (ThinkPad A20m/A21m) + +pci:v00001002d00004C4Dsv00001028sd000000AA* + ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Latitude CPt) + +pci:v00001002d00004C4Dsv00001028sd000000BB* + ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Latitude CPx) + +pci:v00001002d00004C4Dsv00001179sd0000FF00* + ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (Satellite 1715XCDS laptop) + +pci:v00001002d00004C4Dsv000013BDsd00001019* + ID_MODEL_FROM_DATABASE=Rage Mobility AGP 2x Series (PC-AR10) + +pci:v00001002d00004C50* + ID_MODEL_FROM_DATABASE=Rage 3 LT [3D Rage LT PRO PCI] + +pci:v00001002d00004C50sv00001002sd00004C50* + ID_MODEL_FROM_DATABASE=Rage 3 LT [3D Rage LT PRO PCI] (Rage LT Pro) + +pci:v00001002d00004C52* + ID_MODEL_FROM_DATABASE=M1 [Rage Mobility-M1 PCI] + +pci:v00001002d00004C52sv00001033sd00008112* + ID_MODEL_FROM_DATABASE=M1 [Rage Mobility-M1 PCI] (Versa Note VXi) + +pci:v00001002d00004C54* + ID_MODEL_FROM_DATABASE=264LT [Mach64 LT] + +pci:v00001002d00004C57* + ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] + +pci:v00001002d00004C57sv00001014sd00000517* + ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (ThinkPad T30) + +pci:v00001002d00004C57sv00001014sd00000530* + ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (ThinkPad T4x Series) + +pci:v00001002d00004C57sv00001028sd000000E6* + ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (Radeon Mobility M7 LW (Dell Inspiron 8100)) + +pci:v00001002d00004C57sv00001028sd0000012A* + ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (Latitude C640) + +pci:v00001002d00004C57sv00001043sd00001622* + ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (Mobility Radeon M7 (L3C/S)) + +pci:v00001002d00004C57sv0000144Dsd0000C006* + ID_MODEL_FROM_DATABASE=RV200/M7 [Mobility Radeon 7500] (Radeon Mobility M7 LW in vpr Matrix 170B4) + +pci:v00001002d00004C58* + ID_MODEL_FROM_DATABASE=RV200/M7 GL [Mobility FireGL 7800] + +pci:v00001002d00004C59* + ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] + +pci:v00001002d00004C59sv00000E11sd0000B111* + ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (Evo N600c) + +pci:v00001002d00004C59sv00001014sd00000235* + ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (ThinkPad A30/A30p (2652/2653)) + +pci:v00001002d00004C59sv00001014sd00000239* + ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (ThinkPad X22/X23/X24) + +pci:v00001002d00004C59sv0000103Csd00000025* + ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (XE4500 Notebook) + +pci:v00001002d00004C59sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00001002d00004C59sv0000104Dsd00008140* + ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (PCG-Z1SP laptop) + +pci:v00001002d00004C59sv00001509sd00001930* + ID_MODEL_FROM_DATABASE=RV100/M6 [Rage/Radeon Mobility Series] (Medion MD9703) + +pci:v00001002d00004C66* + ID_MODEL_FROM_DATABASE=RV250/M9 GL [Mobility FireGL 9000/Radeon 9000] + +pci:v00001002d00004C66sv00001014sd0000054D* + ID_MODEL_FROM_DATABASE=RV250/M9 GL [Mobility FireGL 9000/Radeon 9000] (ThinkPad T41) + +pci:v00001002d00004C6E* + ID_MODEL_FROM_DATABASE=RV250/M9 [Mobility Radeon 9000] (Secondary) + +pci:v00001002d00004D46* + ID_MODEL_FROM_DATABASE=Rage Mobility 128 AGP 4X/Mobility M4 + +pci:v00001002d00004D52* + ID_MODEL_FROM_DATABASE=Theater 550 PRO PCI [ATI TV Wonder 550] + +pci:v00001002d00004D53* + ID_MODEL_FROM_DATABASE=Theater 550 PRO PCIe + +pci:v00001002d00004E44* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9700/9700 PRO] + +pci:v00001002d00004E44sv00001002sd0000515E* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9700/9700 PRO] (Radeon ES1000) + +pci:v00001002d00004E44sv00001002sd00005965* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9700/9700 PRO] (Radeon ES1000) + +pci:v00001002d00004E45* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO/9700] + +pci:v00001002d00004E45sv00001002sd00000002* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO/9700] (Radeon R300 NE [Radeon 9500 Pro]) + +pci:v00001002d00004E45sv00001681sd00000002* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO/9700] (Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro]) + +pci:v00001002d00004E46* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9600 TX] + +pci:v00001002d00004E47* + ID_MODEL_FROM_DATABASE=R300 GL [FireGL X1] + +pci:v00001002d00004E48* + ID_MODEL_FROM_DATABASE=R350 [Radeon 9800 Series] + +pci:v00001002d00004E49* + ID_MODEL_FROM_DATABASE=R350 [Radeon 9800] + +pci:v00001002d00004E4A* + ID_MODEL_FROM_DATABASE=R360 [Radeon 9800 XXL/XT] + +pci:v00001002d00004E4Asv00001002sd00004E4A* + ID_MODEL_FROM_DATABASE=R360 [Radeon 9800 XXL/XT] (R360 [Radeon 9800 XT]) + +pci:v00001002d00004E4B* + ID_MODEL_FROM_DATABASE=R350 GL [FireGL X2 AGP Pro] + +pci:v00001002d00004E50* + ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] + +pci:v00001002d00004E50sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (TravelMate 290) + +pci:v00001002d00004E50sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (Extensa 3000 series laptop: ATI RV360/M11 [Mobility Radeon 9700]) + +pci:v00001002d00004E50sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (NC8000 laptop) + +pci:v00001002d00004E50sv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (NC6000 laptop) + +pci:v00001002d00004E50sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (P35 notebook) + +pci:v00001002d00004E50sv00001462sd00000311* + ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (MSI M510A) + +pci:v00001002d00004E50sv00001734sd00001055* + ID_MODEL_FROM_DATABASE=RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] (Amilo M1420W) + +pci:v00001002d00004E51* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9550/9600/X1050 Series] + +pci:v00001002d00004E52* + ID_MODEL_FROM_DATABASE=RV350/M10 [Mobility Radeon 9500/9700 SE] + +pci:v00001002d00004E52sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=RV350/M10 [Mobility Radeon 9500/9700 SE] (P35 notebook) + +pci:v00001002d00004E54* + ID_MODEL_FROM_DATABASE=RV350/M10 GL [Mobility FireGL T2] + +pci:v00001002d00004E56* + ID_MODEL_FROM_DATABASE=RV360/M12 [Mobility Radeon 9550] + +pci:v00001002d00004E64* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9700 PRO] (Secondary) + +pci:v00001002d00004E65* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO] (Secondary) + +pci:v00001002d00004E65sv00001002sd00000003* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO] (Secondary) (Radeon R300 NE [Radeon 9500 Pro]) + +pci:v00001002d00004E65sv00001681sd00000003* + ID_MODEL_FROM_DATABASE=R300 [Radeon 9500 PRO] (Secondary) (Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro] (Secondary)) + +pci:v00001002d00004E66* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9600] (Secondary) + +pci:v00001002d00004E67* + ID_MODEL_FROM_DATABASE=R300 GL [FireGL X1] (Secondary) + +pci:v00001002d00004E68* + ID_MODEL_FROM_DATABASE=R350 [Radeon 9800 PRO] (Secondary) + +pci:v00001002d00004E69* + ID_MODEL_FROM_DATABASE=R350 [Radeon 9800] (Secondary) + +pci:v00001002d00004E6A* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9800 XT] (Secondary) + +pci:v00001002d00004E6Asv00001002sd00004E6A* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9800 XT] (Secondary) (R360 [Radeon 9800 XT] (Secondary)) + +pci:v00001002d00004E6Asv00001002sd00004E71* + ID_MODEL_FROM_DATABASE=RV350 [Radeon 9800 XT] (Secondary) (M10 NQ [Radeon Mobility 9600]) + +pci:v00001002d00004E71* + ID_MODEL_FROM_DATABASE=RV350/M10 [Mobility Radeon 9600] (Secondary) + +pci:v00001002d00004F72* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] + +pci:v00001002d00004F73* + ID_MODEL_FROM_DATABASE=RV250 [Radeon 9000 Series] (Secondary) + +pci:v00001002d00005044* + ID_MODEL_FROM_DATABASE=All-In-Wonder 128 PCI + +pci:v00001002d00005044sv00001002sd00000028* + ID_MODEL_FROM_DATABASE=All-In-Wonder 128 PCI (Rage 128 AIW) + +pci:v00001002d00005044sv00001002sd00000029* + ID_MODEL_FROM_DATABASE=All-In-Wonder 128 PCI (Rage 128 AIW) + +pci:v00001002d00005046* + ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] + +pci:v00001002d00005046sv00001002sd00000004* + ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro) + +pci:v00001002d00005046sv00001002sd00000008* + ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro/Xpert 2000 Pro) + +pci:v00001002d00005046sv00001002sd00000014* + ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro) + +pci:v00001002d00005046sv00001002sd00000018* + ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro/Xpert 2000 Pro) + +pci:v00001002d00005046sv00001002sd00000028* + ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage 128 Pro AIW AGP) + +pci:v00001002d00005046sv00001002sd0000002A* + ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage 128 Pro AIW AGP) + +pci:v00001002d00005046sv00001002sd00000048* + ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury Pro) + +pci:v00001002d00005046sv00001002sd00002000* + ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury MAXX AGP 4x (TMDS) (VGA device)) + +pci:v00001002d00005046sv00001002sd00002001* + ID_MODEL_FROM_DATABASE=Rage 4 [Rage 128 PRO AGP 4X TMDS] (Rage Fury MAXX AGP 4x (TMDS) (Extra device?!)) + +pci:v00001002d00005050* + ID_MODEL_FROM_DATABASE=Rage128 [Xpert 128 PCI] + +pci:v00001002d00005050sv00001002sd00000008* + ID_MODEL_FROM_DATABASE=Rage128 [Xpert 128 PCI] (Xpert 128) + +pci:v00001002d00005052* + ID_MODEL_FROM_DATABASE=Rage 128 PRO AGP 4X TMDS + +pci:v00001002d00005144* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] + +pci:v00001002d00005144sv00001002sd00000008* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon VE) + +pci:v00001002d00005144sv00001002sd00000009* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) + +pci:v00001002d00005144sv00001002sd0000000A* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) + +pci:v00001002d00005144sv00001002sd0000001A* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) + +pci:v00001002d00005144sv00001002sd00000029* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon AIW) + +pci:v00001002d00005144sv00001002sd00000038* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) + +pci:v00001002d00005144sv00001002sd00000039* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) + +pci:v00001002d00005144sv00001002sd0000008A* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) + +pci:v00001002d00005144sv00001002sd000000BA* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) + +pci:v00001002d00005144sv00001002sd00000139* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) + +pci:v00001002d00005144sv00001002sd0000028A* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) + +pci:v00001002d00005144sv00001002sd000002AA* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon AIW) + +pci:v00001002d00005144sv00001002sd0000053A* + ID_MODEL_FROM_DATABASE=R100 [Radeon 7200 / All-In-Wonder Radeon] (Radeon 7000/Radeon) + +pci:v00001002d00005148* + ID_MODEL_FROM_DATABASE=R200 GL [FireGL 8800] + +pci:v00001002d00005148sv00001002sd0000010A* + ID_MODEL_FROM_DATABASE=R200 GL [FireGL 8800] (FireGL 8800 64Mb) + +pci:v00001002d00005148sv00001002sd00000152* + ID_MODEL_FROM_DATABASE=R200 GL [FireGL 8800] (FireGL 8800 128Mb) + +pci:v00001002d00005148sv00001002sd00000162* + ID_MODEL_FROM_DATABASE=R200 GL [FireGL 8800] (FireGL 8700 32Mb) + +pci:v00001002d00005148sv00001002sd00000172* + ID_MODEL_FROM_DATABASE=R200 GL [FireGL 8800] (FireGL 8700 64Mb) + +pci:v00001002d0000514C* + ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] + +pci:v00001002d0000514Csv00001002sd0000003A* + ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (Radeon R200 QL [Radeon 8500 LE]) + +pci:v00001002d0000514Csv00001002sd0000013A* + ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (Radeon 8500) + +pci:v00001002d0000514Csv0000148Csd00002026* + ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (R200 QL [Radeon 8500 Evil Master II Multi Display Edition]) + +pci:v00001002d0000514Csv00001681sd00000010* + ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (Radeon 8500 [3D Prophet 8500 128Mb]) + +pci:v00001002d0000514Csv0000174Bsd00007149* + ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (Radeon 8500 LE) + +pci:v00001002d0000514Csv00001787sd00000F08* + ID_MODEL_FROM_DATABASE=R200 [Radeon 8500/8500 LE] (Radeon R200 QL [PowerMagic Radeon 8500]) + +pci:v00001002d0000514D* + ID_MODEL_FROM_DATABASE=R200 [Radeon 9100] + +pci:v00001002d00005157* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] + +pci:v00001002d00005157sv00001002sd0000013A* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (Radeon 7500) + +pci:v00001002d00005157sv00001002sd00000F2B* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (ALL-IN-WONDER VE PCI) + +pci:v00001002d00005157sv00001002sd0000103A* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (Dell Optiplex GX260) + +pci:v00001002d00005157sv00001458sd00004000* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [RADEON 7500 PRO MAYA AR]) + +pci:v00001002d00005157sv0000148Csd00002024* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [Radeon 7500LE Dual Display]) + +pci:v00001002d00005157sv0000148Csd00002025* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [Radeon 7500 Evil Master Multi Display Edition]) + +pci:v00001002d00005157sv0000148Csd00002036* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [Radeon 7500 PCI Dual Display]) + +pci:v00001002d00005157sv0000174Bsd00007146* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [Radeon 7500 LE]) + +pci:v00001002d00005157sv0000174Bsd00007147* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (Radeon 7500 LE) + +pci:v00001002d00005157sv0000174Bsd00007161* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (Radeon RV200 QW [Radeon 7500 LE]) + +pci:v00001002d00005157sv000017AFsd00000202* + ID_MODEL_FROM_DATABASE=RV200 [Radeon 7500/7500 LE] (RV200 QW [Excalibur Radeon 7500LE]) + +pci:v00001002d00005159* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] + +pci:v00001002d00005159sv00001002sd0000000A* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000/Radeon VE) + +pci:v00001002d00005159sv00001002sd0000000B* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000) + +pci:v00001002d00005159sv00001002sd00000038* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000/Radeon VE) + +pci:v00001002d00005159sv00001002sd0000003A* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000/Radeon VE) + +pci:v00001002d00005159sv00001002sd000000BA* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000/Radeon VE) + +pci:v00001002d00005159sv00001002sd0000013A* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000/Radeon VE) + +pci:v00001002d00005159sv00001002sd00000908* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (XVR-100 (supplied by Sun)) + +pci:v00001002d00005159sv00001014sd0000029A* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Remote Supervisor Adapter II (RSA2)) + +pci:v00001002d00005159sv00001014sd000002C8* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (eServer xSeries server mainboard) + +pci:v00001002d00005159sv00001028sd0000016C* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (PowerEdge 1850 Embedded Radeon 7000/VE) + +pci:v00001002d00005159sv00001028sd0000016D* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (PowerEdge 2850 Embedded Radeon 7000-M) + +pci:v00001002d00005159sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (PowerEdge 6850 Embedded Radeon 7000/VE) + +pci:v00001002d00005159sv00001028sd0000019A* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (PowerEdge SC1425) + +pci:v00001002d00005159sv0000103Csd00001292* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000) + +pci:v00001002d00005159sv00001043sd0000C00A* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (A7000/T/64M) + +pci:v00001002d00005159sv00001458sd00004002* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (RV100 QY [RADEON 7000 PRO MAYA AV Series]) + +pci:v00001002d00005159sv0000148Csd00002003* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (RV100 QY [Radeon 7000 Multi-Display Edition]) + +pci:v00001002d00005159sv0000148Csd00002023* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (RV100 QY [Radeon 7000 Evil Master Multi-Display]) + +pci:v00001002d00005159sv0000148Csd00002081* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (RV6DE) + +pci:v00001002d00005159sv0000174Bsd00000280* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon RV100 QY [Radeon 7000/VE]) + +pci:v00001002d00005159sv0000174Bsd00007112* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon VE 7000) + +pci:v00001002d00005159sv0000174Bsd00007C28* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon VE 7000 DDR) + +pci:v00001002d00005159sv00001787sd00000202* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (RV100 QY [Excalibur Radeon 7000]) + +pci:v00001002d00005159sv000017EEsd00001001* + ID_MODEL_FROM_DATABASE=RV100 [Radeon 7000 / Radeon VE] (Radeon 7000 64MB DDR + DVI) + +pci:v00001002d0000515E* + ID_MODEL_FROM_DATABASE=ES1000 + +pci:v00001002d0000515Esv00001028sd000001BB* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge 1955 Embedded ATI ES1000) + +pci:v00001002d0000515Esv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge SC440) + +pci:v00001002d0000515Esv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge 860) + +pci:v00001002d0000515Esv00001028sd000001F0* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge R900 Embedded ATI ES1000) + +pci:v00001002d0000515Esv00001028sd00000205* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge 2970 Embedded ATI ES1000) + +pci:v00001002d0000515Esv00001028sd0000020B* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge T605 Embedded ATI ES1000) + +pci:v00001002d0000515Esv00001028sd0000020F* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge R300 Embedded ATI ES1000) + +pci:v00001002d0000515Esv00001028sd00000210* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge T300 Embedded ATI ES1000) + +pci:v00001002d0000515Esv00001028sd00000221* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge R805 Embedded ATI ES1000) + +pci:v00001002d0000515Esv00001028sd00000223* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge R905 Embedded ATI ES1000) + +pci:v00001002d0000515Esv00001028sd00000225* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge T105 Embedded ATI ES1000) + +pci:v00001002d0000515Esv00001028sd0000023C* + ID_MODEL_FROM_DATABASE=ES1000 (PowerEdge R200 Embedded ATI ES1000) + +pci:v00001002d0000515Esv0000103Csd00001304* + ID_MODEL_FROM_DATABASE=ES1000 (Integrity iLO2 Advanced KVM VGA [AD307A]) + +pci:v00001002d0000515Esv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=ES1000 (X7DVL-E-O motherboard) + +pci:v00001002d0000515Esv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=ES1000 (X7DBN Motherboard) + +pci:v00001002d0000515Esv00008086sd00003476* + ID_MODEL_FROM_DATABASE=ES1000 (S5000PSLSATA Server Board) + +pci:v00001002d00005245* + ID_MODEL_FROM_DATABASE=Rage 128 GL PCI + +pci:v00001002d00005245sv00001002sd00000008* + ID_MODEL_FROM_DATABASE=Rage 128 GL PCI (Xpert 128) + +pci:v00001002d00005245sv00001002sd00000028* + ID_MODEL_FROM_DATABASE=Rage 128 GL PCI (Rage 128 AIW) + +pci:v00001002d00005245sv00001002sd00000029* + ID_MODEL_FROM_DATABASE=Rage 128 GL PCI (Rage 128 AIW) + +pci:v00001002d00005245sv00001002sd00000068* + ID_MODEL_FROM_DATABASE=Rage 128 GL PCI (Rage 128 AIW) + +pci:v00001002d00005246* + ID_MODEL_FROM_DATABASE=Rage 128 (Rage 4) series + +pci:v00001002d00005246sv00001002sd00000004* + ID_MODEL_FROM_DATABASE=Rage 128 (Rage 4) series (Magnum/Xpert 128/Xpert 99) + +pci:v00001002d00005246sv00001002sd00000008* + ID_MODEL_FROM_DATABASE=Rage 128 (Rage 4) series (Rage 128 AGP 2x) + +pci:v00001002d00005246sv00001002sd00000028* + ID_MODEL_FROM_DATABASE=Rage 128 (Rage 4) series (Rage 128 AIW AGP) + +pci:v00001002d00005246sv00001002sd00000044* + ID_MODEL_FROM_DATABASE=Rage 128 (Rage 4) series (Rage Fury/Xpert 128/Xpert 2000) + +pci:v00001002d00005246sv00001002sd00000068* + ID_MODEL_FROM_DATABASE=Rage 128 (Rage 4) series (Rage 128 AIW AGP) + +pci:v00001002d00005246sv00001002sd00000448* + ID_MODEL_FROM_DATABASE=Rage 128 (Rage 4) series (Rage Fury) + +pci:v00001002d0000524B* + ID_MODEL_FROM_DATABASE=Rage 128 VR PCI + +pci:v00001002d0000524C* + ID_MODEL_FROM_DATABASE=Rage 128 VR AGP + +pci:v00001002d0000524Csv00001002sd00000008* + ID_MODEL_FROM_DATABASE=Rage 128 VR AGP (Xpert 99/Xpert 2000) + +pci:v00001002d0000524Csv00001002sd00000088* + ID_MODEL_FROM_DATABASE=Rage 128 VR AGP (Xpert 99) + +pci:v00001002d00005346* + ID_MODEL_FROM_DATABASE=Rage 128 SF/4x AGP 2x + +pci:v00001002d00005346sv00001002sd00000048* + ID_MODEL_FROM_DATABASE=Rage 128 SF/4x AGP 2x (RAGE 128 16MB VGA TVOUT AMC PAL) + +pci:v00001002d0000534D* + ID_MODEL_FROM_DATABASE=Rage 128 4X AGP 4x + +pci:v00001002d0000534Dsv00001002sd00000008* + ID_MODEL_FROM_DATABASE=Rage 128 4X AGP 4x (Xpert 99/Xpert 2000) + +pci:v00001002d0000534Dsv00001002sd00000018* + ID_MODEL_FROM_DATABASE=Rage 128 4X AGP 4x (Xpert 2000) + +pci:v00001002d00005354* + ID_MODEL_FROM_DATABASE=Mach 64 VT + +pci:v00001002d00005354sv00001002sd00005654* + ID_MODEL_FROM_DATABASE=Mach 64 VT (Mach 64 reference) + +pci:v00001002d00005446* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x + +pci:v00001002d00005446sv00001002sd00000004* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage Fury Pro) + +pci:v00001002d00005446sv00001002sd00000008* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage Fury Pro/Xpert 2000 Pro) + +pci:v00001002d00005446sv00001002sd00000018* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage Fury Pro/Xpert 2000 Pro) + +pci:v00001002d00005446sv00001002sd00000028* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage 128 AIW Pro AGP) + +pci:v00001002d00005446sv00001002sd00000029* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage 128 AIW) + +pci:v00001002d00005446sv00001002sd0000002A* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage 128 AIW Pro AGP) + +pci:v00001002d00005446sv00001002sd0000002B* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Rage 128 AIW) + +pci:v00001002d00005446sv00001002sd00000048* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra AGP 4x (Xpert 2000 Pro) + +pci:v00001002d00005452* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra4XL VR-R AGP + +pci:v00001002d00005452sv00001002sd0000001C* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra4XL VR-R AGP (Rage 128 Pro 4XL) + +pci:v00001002d00005452sv0000103Csd00001279* + ID_MODEL_FROM_DATABASE=Rage 128 PRO Ultra4XL VR-R AGP (Rage 128 Pro 4XL) + +pci:v00001002d00005460* + ID_MODEL_FROM_DATABASE=RV370/M22 [Mobility Radeon X300] + +pci:v00001002d00005460sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=RV370/M22 [Mobility Radeon X300] (CR11/VR11 Single Board Computer) + +pci:v00001002d00005461* + ID_MODEL_FROM_DATABASE=RV370/M22 [Mobility Radeon X300] + +pci:v00001002d00005462* + ID_MODEL_FROM_DATABASE=RV380/M24C [Mobility Radeon X600 SE] + +pci:v00001002d00005464* + ID_MODEL_FROM_DATABASE=RV370/M22 GL [Mobility FireGL V3100] + +pci:v00001002d00005549* + ID_MODEL_FROM_DATABASE=R423 [Radeon X800 GTO] + +pci:v00001002d0000554A* + ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT Platinum Edition] + +pci:v00001002d0000554B* + ID_MODEL_FROM_DATABASE=R423 [Radeon X800 GT/SE] + +pci:v00001002d0000554Bsv00001002sd00000302* + ID_MODEL_FROM_DATABASE=R423 [Radeon X800 GT/SE] (Radeon X800 SE) + +pci:v00001002d0000554D* + ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] + +pci:v00001002d0000554Dsv00001002sd00000322* + ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (All-In-Wonder X800 XL) + +pci:v00001002d0000554Dsv00001458sd00002124* + ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (GV-R80L256V-B (AGP)) + +pci:v00001002d0000554E* + ID_MODEL_FROM_DATABASE=R430 [All-In-Wonder X800 GT] + +pci:v00001002d0000554F* + ID_MODEL_FROM_DATABASE=R430 [Radeon X800] + +pci:v00001002d00005550* + ID_MODEL_FROM_DATABASE=R423 GL [FireGL V7100] + +pci:v00001002d00005551* + ID_MODEL_FROM_DATABASE=R423 GL [FireGL V5100] + +pci:v00001002d00005569* + ID_MODEL_FROM_DATABASE=R423 [Radeon X800 PRO] (Secondary) + +pci:v00001002d0000556B* + ID_MODEL_FROM_DATABASE=R423 [Radeon X800 GT] (Secondary) + +pci:v00001002d0000556D* + ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (Secondary) + +pci:v00001002d0000556Dsv00001458sd00002125* + ID_MODEL_FROM_DATABASE=R430 [Radeon X800 XL] (Secondary) (GV-R80L256V-B (AGP)) + +pci:v00001002d0000556F* + ID_MODEL_FROM_DATABASE=R430 [Radeon X800] (Secondary) + +pci:v00001002d00005571* + ID_MODEL_FROM_DATABASE=R423 GL [FireGL V5100] (Secondary) + +pci:v00001002d0000564B* + ID_MODEL_FROM_DATABASE=RV410/M26 GL [Mobility FireGL V5000] + +pci:v00001002d0000564F* + ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700 XL] + +pci:v00001002d00005652* + ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700] + +pci:v00001002d00005653* + ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700] + +pci:v00001002d00005653sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700] (Aspire 5024WLMi) + +pci:v00001002d00005653sv0000103Csd00000940* + ID_MODEL_FROM_DATABASE=RV410/M26 [Mobility Radeon X700] (Compaq NW8240 Mobile Workstation) + +pci:v00001002d00005654* + ID_MODEL_FROM_DATABASE=Mach64 VT [Video Xpression] + +pci:v00001002d00005654sv00001002sd00005654* + ID_MODEL_FROM_DATABASE=Mach64 VT [Video Xpression] (Mach64VT Reference) + +pci:v00001002d00005655* + ID_MODEL_FROM_DATABASE=264VT3 [Mach64 VT3] + +pci:v00001002d00005656* + ID_MODEL_FROM_DATABASE=Mach64 VT4 [Video Xpression+] + +pci:v00001002d00005657* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X550 XTX / X700] + +pci:v00001002d00005830* + ID_MODEL_FROM_DATABASE=RS300 Host Bridge + +pci:v00001002d00005831* + ID_MODEL_FROM_DATABASE=RS300 Host Bridge + +pci:v00001002d00005832* + ID_MODEL_FROM_DATABASE=RS300 Host Bridge + +pci:v00001002d00005833* + ID_MODEL_FROM_DATABASE=RS300 Host Bridge + +pci:v00001002d00005834* + ID_MODEL_FROM_DATABASE=RS300 [Radeon 9100 IGP] + +pci:v00001002d00005835* + ID_MODEL_FROM_DATABASE=RS300M [Mobility Radeon 9100 IGP] + +pci:v00001002d00005838* + ID_MODEL_FROM_DATABASE=RS300 AGP Bridge + +pci:v00001002d00005854* + ID_MODEL_FROM_DATABASE=RS480 [Radeon Xpress 200 Series] (Secondary) + +pci:v00001002d00005874* + ID_MODEL_FROM_DATABASE=RS480 [Radeon Xpress 1150] (Secondary) + +pci:v00001002d00005940* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO] (Secondary) + +pci:v00001002d00005940sv000017AFsd00002021* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO] (Secondary) (Excalibur Radeon 9250 (Secondary)) + +pci:v00001002d00005941* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary) + +pci:v00001002d00005941sv00001458sd00004019* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary) (Radeon 9200) + +pci:v00001002d00005941sv0000174Bsd00007C12* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary) (Radeon 9200) + +pci:v00001002d00005941sv000017AFsd0000200D* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary) (Excalibur Radeon 9200) + +pci:v00001002d00005941sv000018BCsd00000050* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Secondary) (GC-R9200-C3 (Secondary)) + +pci:v00001002d00005944* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE PCI] + +pci:v00001002d00005950* + ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge + +pci:v00001002d00005950sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (Aspire 5024WLMMi) + +pci:v00001002d00005950sv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (DC5750 Microtower) + +pci:v00001002d00005950sv0000103Csd00002A20* + ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (Pavilion t3030.de Desktop PC) + +pci:v00001002d00005950sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (MX6125) + +pci:v00001002d00005950sv00001462sd00000131* + ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (MS-1013 Notebook) + +pci:v00001002d00005950sv00001462sd00007217* + ID_MODEL_FROM_DATABASE=RS480/RS482/RS485 Host Bridge (Aspire L250) + +pci:v00001002d00005951* + ID_MODEL_FROM_DATABASE=RX480/RX482 Host Bridge + +pci:v00001002d00005952* + ID_MODEL_FROM_DATABASE=RD580 Host Bridge + +pci:v00001002d00005954* + ID_MODEL_FROM_DATABASE=RS480 [Radeon Xpress 200 Series] + +pci:v00001002d00005954sv00001002sd00005954* + ID_MODEL_FROM_DATABASE=RS480 [Radeon Xpress 200 Series] (RV370 [Radeon Xpress 200G Series]) + +pci:v00001002d00005955* + ID_MODEL_FROM_DATABASE=RS480M [Mobility Radeon Xpress 200] + +pci:v00001002d00005955sv00001002sd00005955* + ID_MODEL_FROM_DATABASE=RS480M [Mobility Radeon Xpress 200] (RS480 0x5955 [Radeon XPRESS 200M 5955 (PCIE)]) + +pci:v00001002d00005955sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=RS480M [Mobility Radeon Xpress 200] (MX6125) + +pci:v00001002d00005955sv00001462sd00000131* + ID_MODEL_FROM_DATABASE=RS480M [Mobility Radeon Xpress 200] (MS-1013 Notebook) + +pci:v00001002d00005956* + ID_MODEL_FROM_DATABASE=RD790 Host Bridge + +pci:v00001002d00005957* + ID_MODEL_FROM_DATABASE=RX780/RX790 Host Bridge + +pci:v00001002d00005957sv00001849sd00005957* + ID_MODEL_FROM_DATABASE=RX780/RX790 Host Bridge (A770CrossFire Motherboard) + +pci:v00001002d00005958* + ID_MODEL_FROM_DATABASE=RD780 Host Bridge + +pci:v00001002d00005960* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO] + +pci:v00001002d00005960sv000017AFsd00002020* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 PRO] (Excalibur Radeon 9250) + +pci:v00001002d00005961* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] + +pci:v00001002d00005961sv00001002sd00002F72* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (All-in-Wonder 9200 Series) + +pci:v00001002d00005961sv00001019sd00004C30* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Radeon 9200 VIVO) + +pci:v00001002d00005961sv000012ABsd00005961* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (YUAN SMARTVGA Radeon 9200) + +pci:v00001002d00005961sv00001458sd00004018* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Radeon 9200) + +pci:v00001002d00005961sv0000174Bsd00007C13* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Radeon 9200) + +pci:v00001002d00005961sv000017AFsd0000200C* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Excalibur Radeon 9200) + +pci:v00001002d00005961sv000018BCsd00000050* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Radeon 9200 Game Buster) + +pci:v00001002d00005961sv000018BCsd00000051* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (GC-R9200-C3) + +pci:v00001002d00005961sv000018BCsd00000053* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] (Radeon 9200 Game Buster VIVO) + +pci:v00001002d00005962* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200] + +pci:v00001002d00005964* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] + +pci:v00001002d00005964sv00001002sd00005964* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE, 64-bit 128MB DDR, 200/166MHz) + +pci:v00001002d00005964sv00001043sd0000C006* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE / TD / 128M) + +pci:v00001002d00005964sv00001458sd00004018* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE) + +pci:v00001002d00005964sv00001458sd00004032* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE 128MB) + +pci:v00001002d00005964sv0000147Bsd00006191* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (R9200SE-DT) + +pci:v00001002d00005964sv0000148Csd00002073* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (CN-AG92E) + +pci:v00001002d00005964sv0000174Bsd00007C13* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE) + +pci:v00001002d00005964sv00001787sd00005964* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Excalibur 9200SE VIVO 128M) + +pci:v00001002d00005964sv000017AFsd00002012* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Radeon 9200 SE Excalibur) + +pci:v00001002d00005964sv000018BCsd00000170* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Sapphire Radeon 9200 SE 128MB Game Buster) + +pci:v00001002d00005964sv000018BCsd00000173* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]) + +pci:v00001002d00005965* + ID_MODEL_FROM_DATABASE=RV280 GL [FireMV 2200 PCI] + +pci:v00001002d00005974* + ID_MODEL_FROM_DATABASE=RS482/RS485 [Radeon Xpress 1100/1150] + +pci:v00001002d00005974sv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=RS482/RS485 [Radeon Xpress 1100/1150] (DC5750 Microtower) + +pci:v00001002d00005974sv00001462sd00007141* + ID_MODEL_FROM_DATABASE=RS482/RS485 [Radeon Xpress 1100/1150] (Aspire L250) + +pci:v00001002d00005975* + ID_MODEL_FROM_DATABASE=RS482M [Mobility Radeon Xpress 200] + +pci:v00001002d00005978* + ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (external gfx0 port A) + +pci:v00001002d00005978sv00001849sd00005957* + ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (external gfx0 port A) (A770CrossFire Motherboard) + +pci:v00001002d00005979* + ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (external gfx0 port B) + +pci:v00001002d0000597A* + ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port A) + +pci:v00001002d0000597B* + ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (PCI express gpp port B) + +pci:v00001002d0000597C* + ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port C) + +pci:v00001002d0000597D* + ID_MODEL_FROM_DATABASE=RX780/RD790 PCI to PCI bridge (PCI express gpp port D) + +pci:v00001002d0000597E* + ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port E) + +pci:v00001002d0000597Esv00001849sd00005957* + ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port E) (A770CrossFire Motherboard) + +pci:v00001002d0000597F* + ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port F) + +pci:v00001002d0000597Fsv00001849sd00005957* + ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (PCI express gpp port F) (A770CrossFire Motherboard) + +pci:v00001002d00005980* + ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (external gfx1 port A) + +pci:v00001002d00005981* + ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (external gfx1 port B) + +pci:v00001002d00005982* + ID_MODEL_FROM_DATABASE=RD790 PCI to PCI bridge (NB-SB link) + +pci:v00001002d00005A10* + ID_MODEL_FROM_DATABASE=RD890 Northbridge only dual slot (2x16) PCI-e GFX Hydra part + +pci:v00001002d00005A11* + ID_MODEL_FROM_DATABASE=RD890 Northbridge only single slot PCI-e GFX Hydra part + +pci:v00001002d00005A12* + ID_MODEL_FROM_DATABASE=RD890 Northbridge only dual slot (2x8) PCI-e GFX Hydra part + +pci:v00001002d00005A12sv000015D9sd0000A811* + ID_MODEL_FROM_DATABASE=RD890 Northbridge only dual slot (2x8) PCI-e GFX Hydra part (H8DGU) + +pci:v00001002d00005A13* + ID_MODEL_FROM_DATABASE=RD890S/SR5650 Host Bridge + +pci:v00001002d00005A14* + ID_MODEL_FROM_DATABASE=RD9x0/RX980 Host Bridge + +pci:v00001002d00005A15* + ID_MODEL_FROM_DATABASE=RD890 PCI to PCI bridge (PCI express gpp port A) + +pci:v00001002d00005A16* + ID_MODEL_FROM_DATABASE=RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GFX port 0) + +pci:v00001002d00005A17* + ID_MODEL_FROM_DATABASE=RD890/RD9x0 PCI to PCI bridge (PCI Express GFX port 1) + +pci:v00001002d00005A18* + ID_MODEL_FROM_DATABASE=RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 0) + +pci:v00001002d00005A18sv000015D9sd0000A811* + ID_MODEL_FROM_DATABASE=RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 0) (H8DGU) + +pci:v00001002d00005A19* + ID_MODEL_FROM_DATABASE=RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 1) + +pci:v00001002d00005A1A* + ID_MODEL_FROM_DATABASE=RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 2) + +pci:v00001002d00005A1B* + ID_MODEL_FROM_DATABASE=RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 3) + +pci:v00001002d00005A1C* + ID_MODEL_FROM_DATABASE=RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 4) + +pci:v00001002d00005A1D* + ID_MODEL_FROM_DATABASE=RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 5) + +pci:v00001002d00005A1E* + ID_MODEL_FROM_DATABASE=RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP2 Port 0) + +pci:v00001002d00005A1F* + ID_MODEL_FROM_DATABASE=RD890/RD990 PCI to PCI bridge (PCI Express GFX2 port 0) + +pci:v00001002d00005A1Fsv000015D9sd0000A811* + ID_MODEL_FROM_DATABASE=RD890/RD990 PCI to PCI bridge (PCI Express GFX2 port 0) (H8DGU) + +pci:v00001002d00005A20* + ID_MODEL_FROM_DATABASE=RD890/RD990 PCI to PCI bridge (PCI Express GFX2 port 1) + +pci:v00001002d00005A23* + ID_MODEL_FROM_DATABASE=RD890S/RD990 I/O Memory Management Unit (IOMMU) + +pci:v00001002d00005A31* + ID_MODEL_FROM_DATABASE=RC410 Host Bridge + +pci:v00001002d00005A33* + ID_MODEL_FROM_DATABASE=RS400 Host Bridge + +pci:v00001002d00005A34* + ID_MODEL_FROM_DATABASE=RS4xx PCI Express Port [ext gfx] + +pci:v00001002d00005A36* + ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 1 + +pci:v00001002d00005A37* + ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 2 + +pci:v00001002d00005A38* + ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 3 + +pci:v00001002d00005A39* + ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Express Port 4 + +pci:v00001002d00005A3F* + ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Bridge [int gfx] + +pci:v00001002d00005A3Fsv00001462sd00007217* + ID_MODEL_FROM_DATABASE=RC4xx/RS4xx PCI Bridge [int gfx] (Aspire L250) + +pci:v00001002d00005A41* + ID_MODEL_FROM_DATABASE=RS400 [Radeon Xpress 200] + +pci:v00001002d00005A42* + ID_MODEL_FROM_DATABASE=RS400M [Radeon Xpress 200M] + +pci:v00001002d00005A61* + ID_MODEL_FROM_DATABASE=RC410 [Radeon Xpress 200/1100] + +pci:v00001002d00005A62* + ID_MODEL_FROM_DATABASE=RC410M [Mobility Radeon Xpress 200M] + +pci:v00001002d00005B60* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] + +pci:v00001002d00005B60sv00001043sd0000002A* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (Extreme AX300SE-X) + +pci:v00001002d00005B60sv00001043sd0000032E* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (Extreme AX300/TD) + +pci:v00001002d00005B60sv00001458sd00002102* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (GV-RX30S128D (X300SE)) + +pci:v00001002d00005B60sv00001462sd00000400* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (RX300SE-TD128E (MS-8940 REV:200)) + +pci:v00001002d00005B60sv00001462sd00000402* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (RX300SE-TD128E (MS-8940)) + +pci:v00001002d00005B60sv0000174Bsd00000500* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (Radeon X300 (PCIE)) + +pci:v00001002d00005B60sv0000196Dsd00001086* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300] (X300SE HM) + +pci:v00001002d00005B62* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X600/X600 SE] + +pci:v00001002d00005B63* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300/X550/X1050 Series] + +pci:v00001002d00005B64* + ID_MODEL_FROM_DATABASE=RV370 GL [FireGL V3100] + +pci:v00001002d00005B65* + ID_MODEL_FROM_DATABASE=RV370 GL [FireMV 2200] + +pci:v00001002d00005B66* + ID_MODEL_FROM_DATABASE=RV370X + +pci:v00001002d00005B70* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300 SE] + +pci:v00001002d00005B70sv00001462sd00000403* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300 SE] (Radeon X300 SE 128MB DDR) + +pci:v00001002d00005B70sv0000174Bsd00000501* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300 SE] (Radeon X300 SE) + +pci:v00001002d00005B70sv0000196Dsd00001087* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300 SE] (Radeon X300 SE HyperMemory) + +pci:v00001002d00005B72* + ID_MODEL_FROM_DATABASE=RV380 [Radeon X300/X550/X1050 Series] (Secondary) + +pci:v00001002d00005B73* + ID_MODEL_FROM_DATABASE=RV370 [Radeon X300/X550/X1050 Series] (Secondary) + +pci:v00001002d00005B74* + ID_MODEL_FROM_DATABASE=RV370 GL [FireGL V3100] (Secondary) + +pci:v00001002d00005B75* + ID_MODEL_FROM_DATABASE=RV370 GL [FireMV 2200] (Secondary) + +pci:v00001002d00005C61* + ID_MODEL_FROM_DATABASE=RV280/M9+ [Mobility Radeon 9200 AGP] + +pci:v00001002d00005C63* + ID_MODEL_FROM_DATABASE=RV280/M9+ [Mobility Radeon 9200 AGP] + +pci:v00001002d00005C63sv00001002sd00005C63* + ID_MODEL_FROM_DATABASE=RV280/M9+ [Mobility Radeon 9200 AGP] (Apple iBook G4 2004) + +pci:v00001002d00005C63sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=RV280/M9+ [Mobility Radeon 9200 AGP] (P30 notebook) + +pci:v00001002d00005D44* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) + +pci:v00001002d00005D44sv00001458sd00004019* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE (Secondary)) + +pci:v00001002d00005D44sv00001458sd00004032* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE 128MB) + +pci:v00001002d00005D44sv0000147Bsd00006190* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (R9200SE-DT (Secondary)) + +pci:v00001002d00005D44sv0000174Bsd00007C12* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE (Secondary)) + +pci:v00001002d00005D44sv00001787sd00005965* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Excalibur 9200SE VIVO 128M (Secondary)) + +pci:v00001002d00005D44sv000017AFsd00002013* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE Excalibur (Secondary)) + +pci:v00001002d00005D44sv000018BCsd00000171* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (Radeon 9200 SE 128MB Game Buster (Secondary)) + +pci:v00001002d00005D44sv000018BCsd00000172* + ID_MODEL_FROM_DATABASE=RV280 [Radeon 9200 SE] (Secondary) (GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]) + +pci:v00001002d00005D45* + ID_MODEL_FROM_DATABASE=RV280 GL [FireMV 2200 PCI] (Secondary) + +pci:v00001002d00005D48* + ID_MODEL_FROM_DATABASE=R423/M28 [Mobility Radeon X800 XT] + +pci:v00001002d00005D49* + ID_MODEL_FROM_DATABASE=R423/M28 GL [Mobility FireGL V5100] + +pci:v00001002d00005D4A* + ID_MODEL_FROM_DATABASE=R423/M28 [Mobility Radeon X800] + +pci:v00001002d00005D4D* + ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT Platinum Edition] + +pci:v00001002d00005D4E* + ID_MODEL_FROM_DATABASE=R480 [Radeon X850 SE] + +pci:v00001002d00005D4F* + ID_MODEL_FROM_DATABASE=R480 [Radeon X800 GTO] + +pci:v00001002d00005D50* + ID_MODEL_FROM_DATABASE=R480 GL [FireGL V7200] + +pci:v00001002d00005D52* + ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT] + +pci:v00001002d00005D52sv00001002sd00000B12* + ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT] (PowerColor X850XT PCIe (Primary)) + +pci:v00001002d00005D57* + ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT] + +pci:v00001002d00005D6D* + ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT Platinum Edition] (Secondary) + +pci:v00001002d00005D6F* + ID_MODEL_FROM_DATABASE=R480 [Radeon X800 GTO] (Secondary) + +pci:v00001002d00005D72* + ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT] (Secondary) + +pci:v00001002d00005D72sv00001002sd00000B13* + ID_MODEL_FROM_DATABASE=R480 [Radeon X850 XT] (Secondary) (PowerColor X850XT PCIe (Secondary)) + +pci:v00001002d00005D77* + ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT] (Secondary) + +pci:v00001002d00005E48* + ID_MODEL_FROM_DATABASE=RV410 GL [FireGL V5000] + +pci:v00001002d00005E49* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700 Series] + +pci:v00001002d00005E4A* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700 XT] + +pci:v00001002d00005E4B* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700 PRO] + +pci:v00001002d00005E4C* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700 SE] + +pci:v00001002d00005E4D* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] + +pci:v00001002d00005E4Dsv0000148Csd00002116* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] (Bravo X700) + +pci:v00001002d00005E4F* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] + +pci:v00001002d00005E4Fsv00001569sd00001E4F* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] (Radeon X550 XT) + +pci:v00001002d00005E6B* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700 PRO] (Secondary) + +pci:v00001002d00005E6D* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] (Secondary) + +pci:v00001002d00005E6Dsv0000148Csd00002117* + ID_MODEL_FROM_DATABASE=RV410 [Radeon X700] (Secondary) (Bravo X700 (Secondary)) + +pci:v00001002d00005F57* + ID_MODEL_FROM_DATABASE=R423 [Radeon X800 XT] + +pci:v00001002d00006600* + ID_MODEL_FROM_DATABASE=Mars [Radeon HD 8670A/8670M/8750M] + +pci:v00001002d00006600sv0000103Csd00001952* + ID_MODEL_FROM_DATABASE=Mars [Radeon HD 8670A/8670M/8750M] (ProBook 455 G1) + +pci:v00001002d00006601* + ID_MODEL_FROM_DATABASE=Mars [Radeon HD 8730M] + +pci:v00001002d00006601sv0000103Csd00002100* + ID_MODEL_FROM_DATABASE=Mars [Radeon HD 8730M] (FirePro M4100) + +pci:v00001002d00006604* + ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265/M365X/M465] + +pci:v00001002d00006604sv00001025sd00000776* + ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265/M365X/M465] (Aspire V5 Radeon R7 M265) + +pci:v00001002d00006604sv0000103Csd00008006* + ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265/M365X/M465] (FirePro M4170) + +pci:v00001002d00006604sv0000103Csd0000814F* + ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265/M365X/M465] (Litho XT [Radeon R7 M365X]) + +pci:v00001002d00006604sv0000103Csd000082AA* + ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265/M365X/M465] (Litho XT [Radeon R7 M465]) + +pci:v00001002d00006604sv000017AAsd00003643* + ID_MODEL_FROM_DATABASE=Opal XT [Radeon R7 M265/M365X/M465] (Radeon R7 A360) + +pci:v00001002d00006605* + ID_MODEL_FROM_DATABASE=Opal PRO [Radeon R7 M260X] + +pci:v00001002d00006605sv0000103Csd00002259* + ID_MODEL_FROM_DATABASE=Opal PRO [Radeon R7 M260X] (FirePro M4150) + +pci:v00001002d00006606* + ID_MODEL_FROM_DATABASE=Mars XTX [Radeon HD 8790M] + +pci:v00001002d00006606sv00001028sd00000684* + ID_MODEL_FROM_DATABASE=Mars XTX [Radeon HD 8790M] (FirePro W4170M) + +pci:v00001002d00006607* + ID_MODEL_FROM_DATABASE=Mars LE [Radeon HD 8530M / R5 M240] + +pci:v00001002d00006608* + ID_MODEL_FROM_DATABASE=Oland GL [FirePro W2100] + +pci:v00001002d00006608sv000013CCsd00003D28* + ID_MODEL_FROM_DATABASE=Oland GL [FirePro W2100] (MXRT-2600) + +pci:v00001002d00006610* + ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] + +pci:v00001002d00006610sv00001019sd00000030* + ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670) + +pci:v00001002d00006610sv00001028sd00002120* + ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 250) + +pci:v00001002d00006610sv00001028sd00002322* + ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 250) + +pci:v00001002d00006610sv00001462sd00002910* + ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670) + +pci:v00001002d00006610sv00001462sd00002911* + ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670) + +pci:v00001002d00006610sv0000148Csd00007350* + ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 350) + +pci:v00001002d00006610sv00001642sd00003C81* + ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670) + +pci:v00001002d00006610sv00001642sd00003C91* + ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon HD 8670) + +pci:v00001002d00006610sv00001642sd00003F09* + ID_MODEL_FROM_DATABASE=Oland XT [Radeon HD 8670 / R7 250/350] (Radeon R7 350) + +pci:v00001002d00006611* + ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] + +pci:v00001002d00006611sv00001028sd0000210B* + ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R5 240 OEM) + +pci:v00001002d00006611sv0000174Bsd00004248* + ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R7 240 OEM) + +pci:v00001002d00006611sv0000174Bsd0000A240* + ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R7 240 OEM) + +pci:v00001002d00006611sv0000174Bsd0000D340* + ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R7 340 OEM) + +pci:v00001002d00006611sv00001B0Asd000090D3* + ID_MODEL_FROM_DATABASE=Oland [Radeon HD 8570 / R7 240/340 OEM] (Radeon R7 240 OEM) + +pci:v00001002d00006613* + ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240/340] + +pci:v00001002d00006613sv0000148Csd00007340* + ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240/340] (Radeon R7 340) + +pci:v00001002d00006613sv00001682sd00007240* + ID_MODEL_FROM_DATABASE=Oland PRO [Radeon R7 240/340] (R7 240 2048 MB) + +pci:v00001002d00006631* + ID_MODEL_FROM_DATABASE=Oland + +pci:v00001002d00006640* + ID_MODEL_FROM_DATABASE=Saturn XT [FirePro M6100] + +pci:v00001002d00006640sv0000106Bsd0000014B* + ID_MODEL_FROM_DATABASE=Saturn XT [FirePro M6100] (Tropo XT [Radeon R9 M380 Mac Edition]) + +pci:v00001002d00006641* + ID_MODEL_FROM_DATABASE=Saturn PRO [Radeon HD 8930M] + +pci:v00001002d00006646* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon R9 M280X] + +pci:v00001002d00006647* + ID_MODEL_FROM_DATABASE=Saturn PRO/XT [Radeon R9 M270X/M280X] + +pci:v00001002d00006647sv00001043sd0000223D* + ID_MODEL_FROM_DATABASE=Saturn PRO/XT [Radeon R9 M270X/M280X] (N551ZU laptop Radeon R9 M280X) + +pci:v00001002d00006649* + ID_MODEL_FROM_DATABASE=Bonaire [FirePro W5100] + +pci:v00001002d00006649sv00001002sd00000B0C* + ID_MODEL_FROM_DATABASE=Bonaire [FirePro W5100] (FirePro W4300) + +pci:v00001002d00006649sv0000103Csd00000B0C* + ID_MODEL_FROM_DATABASE=Bonaire [FirePro W5100] (Bonaire [FirePro W4300]) + +pci:v00001002d00006649sv0000103Csd0000230C* + ID_MODEL_FROM_DATABASE=Bonaire [FirePro W5100] (FirePro W5100) + +pci:v00001002d00006649sv000013CCsd00003D2A* + ID_MODEL_FROM_DATABASE=Bonaire [FirePro W5100] (MXRT-5600) + +pci:v00001002d00006650* + ID_MODEL_FROM_DATABASE=Bonaire + +pci:v00001002d00006651* + ID_MODEL_FROM_DATABASE=Bonaire + +pci:v00001002d00006658* + ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] + +pci:v00001002d00006658sv00001043sd000004D3* + ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] (AMD Radeon R7 260X) + +pci:v00001002d00006658sv0000148Csd00000907* + ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] (Radeon R7 360) + +pci:v00001002d00006658sv00001682sd00000907* + ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] (Radeon R7 360) + +pci:v00001002d00006658sv00001682sd00007360* + ID_MODEL_FROM_DATABASE=Bonaire XTX [Radeon R7 260X/360] (Radeon R7 360) + +pci:v00001002d0000665C* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] + +pci:v00001002d0000665Csv00001043sd00000452* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 DirectCU II OC) + +pci:v00001002d0000665Csv00001462sd00002930* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 OC) + +pci:v00001002d0000665Csv00001462sd00002932* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 8770) + +pci:v00001002d0000665Csv00001462sd00002934* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 260 OEM) + +pci:v00001002d0000665Csv00001462sd00002938* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 360 OEM) + +pci:v00001002d0000665Csv0000148Csd00000907* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R7 360) + +pci:v00001002d0000665Csv0000148Csd00009260* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 260 OEM) + +pci:v00001002d0000665Csv0000148Csd00009360* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R9 360 OEM) + +pci:v00001002d0000665Csv00001682sd00000907* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon R7 360) + +pci:v00001002d0000665Csv00001682sd00003310* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 Black Edition 2 GB) + +pci:v00001002d0000665Csv0000174Bsd0000E253* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 Dual-X OC) + +pci:v00001002d0000665Csv00001787sd00002329* + ID_MODEL_FROM_DATABASE=Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] (Radeon HD 7790 TurboDuo) + +pci:v00001002d0000665D* + ID_MODEL_FROM_DATABASE=Bonaire [Radeon R7 200 Series] + +pci:v00001002d0000665F* + ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] + +pci:v00001002d0000665Fsv00001028sd00000B04* + ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R9 360 OEM) + +pci:v00001002d0000665Fsv00001462sd00002938* + ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R9 360 OEM) + +pci:v00001002d0000665Fsv00001462sd00003271* + ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R9 360 OEM) + +pci:v00001002d0000665Fsv00001682sd00007360* + ID_MODEL_FROM_DATABASE=Tobago PRO [Radeon R7 360 / R9 360 OEM] (Radeon R7 360) + +pci:v00001002d00006660* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] + +pci:v00001002d00006660sv00001028sd000005EA* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon HD 8670M) + +pci:v00001002d00006660sv00001028sd000006BF* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon R5 M335) + +pci:v00001002d00006660sv0000103Csd00001970* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon HD 8670M) + +pci:v00001002d00006660sv0000103Csd000080BE* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon R5 M330) + +pci:v00001002d00006660sv0000103Csd00008136* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon R5 M330) + +pci:v00001002d00006660sv0000103Csd00008329* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon R7 M520) + +pci:v00001002d00006660sv000017AAsd00003633* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon R5 A330) + +pci:v00001002d00006660sv000017AAsd00003804* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon R5 M330) + +pci:v00001002d00006660sv000017AAsd00003809* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon R5 M330) + +pci:v00001002d00006660sv000017AAsd0000381A* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon R5 M430) + +pci:v00001002d00006660sv000017AAsd0000390C* + ID_MODEL_FROM_DATABASE=Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] (Radeon R5 M330) + +pci:v00001002d00006663* + ID_MODEL_FROM_DATABASE=Sun PRO [Radeon HD 8570A/8570M] + +pci:v00001002d00006663sv00001025sd00000846* + ID_MODEL_FROM_DATABASE=Sun PRO [Radeon HD 8570A/8570M] (Radeon HD 8570A) + +pci:v00001002d00006663sv000017AAsd00003805* + ID_MODEL_FROM_DATABASE=Sun PRO [Radeon HD 8570A/8570M] (Radeon HD 8570M) + +pci:v00001002d00006664* + ID_MODEL_FROM_DATABASE=Jet XT [Radeon R5 M240] + +pci:v00001002d00006665* + ID_MODEL_FROM_DATABASE=Jet PRO [Radeon R5 M230 / R7 M260DX / Radeon 520 Mobile] + +pci:v00001002d00006665sv000017AAsd00001309* + ID_MODEL_FROM_DATABASE=Jet PRO [Radeon R5 M230 / R7 M260DX / Radeon 520 Mobile] (Radeon R7 M260DX) + +pci:v00001002d00006665sv000017AAsd0000368F* + ID_MODEL_FROM_DATABASE=Jet PRO [Radeon R5 M230 / R7 M260DX / Radeon 520 Mobile] (Radeon R5 A230) + +pci:v00001002d00006667* + ID_MODEL_FROM_DATABASE=Jet ULT [Radeon R5 M230] + +pci:v00001002d0000666F* + ID_MODEL_FROM_DATABASE=Sun LE [Radeon HD 8550M / R5 M230] + +pci:v00001002d000066A0* + ID_MODEL_FROM_DATABASE=Vega 20 [Radeon Instinct] + +pci:v00001002d000066A1* + ID_MODEL_FROM_DATABASE=Vega 20 + +pci:v00001002d000066A2* + ID_MODEL_FROM_DATABASE=Vega 20 + +pci:v00001002d000066A3* + ID_MODEL_FROM_DATABASE=Vega 20 + +pci:v00001002d000066A7* + ID_MODEL_FROM_DATABASE=Vega 20 [Radeon Pro Vega 20] + +pci:v00001002d000066AF* + ID_MODEL_FROM_DATABASE=Vega 20 [Radeon VII] + +pci:v00001002d00006704* + ID_MODEL_FROM_DATABASE=Cayman PRO GL [FirePro V7900] + +pci:v00001002d00006707* + ID_MODEL_FROM_DATABASE=Cayman LE GL [FirePro V5900] + +pci:v00001002d00006718* + ID_MODEL_FROM_DATABASE=Cayman XT [Radeon HD 6970] + +pci:v00001002d00006719* + ID_MODEL_FROM_DATABASE=Cayman PRO [Radeon HD 6950] + +pci:v00001002d0000671C* + ID_MODEL_FROM_DATABASE=Antilles [Radeon HD 6990] + +pci:v00001002d0000671D* + ID_MODEL_FROM_DATABASE=Antilles [Radeon HD 6990] + +pci:v00001002d0000671F* + ID_MODEL_FROM_DATABASE=Cayman CE [Radeon HD 6930] + +pci:v00001002d00006720* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] + +pci:v00001002d00006720sv00001028sd0000048F* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6990M) + +pci:v00001002d00006720sv00001028sd00000490* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Alienware M17x R3 Radeon HD 6970M) + +pci:v00001002d00006720sv00001028sd000004A4* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (FirePro M8900) + +pci:v00001002d00006720sv00001028sd000004BA* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6990M) + +pci:v00001002d00006720sv00001028sd0000053F* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (FirePro M8900) + +pci:v00001002d00006720sv0000106Bsd00000B00* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6970M) + +pci:v00001002d00006720sv00001558sd00005102* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6970M) + +pci:v00001002d00006720sv00001558sd00005104* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6990M) + +pci:v00001002d00006720sv00001558sd00007201* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6990M) + +pci:v00001002d00006720sv0000174Bsd0000E188* + ID_MODEL_FROM_DATABASE=Blackcomb [Radeon HD 6970M/6990M] (Radeon HD 6970M) + +pci:v00001002d00006738* + ID_MODEL_FROM_DATABASE=Barts XT [Radeon HD 6870] + +pci:v00001002d00006738sv00001682sd00003103* + ID_MODEL_FROM_DATABASE=Barts XT [Radeon HD 6870] (Radeon HD 8670) + +pci:v00001002d00006738sv00001787sd0000201A* + ID_MODEL_FROM_DATABASE=Barts XT [Radeon HD 6870] (Barts XT [Radeon HD 6870 X2]) + +pci:v00001002d00006738sv00001787sd0000201B* + ID_MODEL_FROM_DATABASE=Barts XT [Radeon HD 6870] (Barts XT [Radeon HD 6870 X2]) + +pci:v00001002d00006739* + ID_MODEL_FROM_DATABASE=Barts PRO [Radeon HD 6850] + +pci:v00001002d00006739sv00001043sd000003B4* + ID_MODEL_FROM_DATABASE=Barts PRO [Radeon HD 6850] (EAH6850 [Radeon HD 6850]) + +pci:v00001002d0000673E* + ID_MODEL_FROM_DATABASE=Barts LE [Radeon HD 6790] + +pci:v00001002d0000673Esv0000148Csd00007720* + ID_MODEL_FROM_DATABASE=Barts LE [Radeon HD 6790] (Radeon HD 7720 OEM) + +pci:v00001002d00006740* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] + +pci:v00001002d00006740sv00001019sd0000238C* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv00001019sd0000238E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv00001019sd00002391* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv00001019sd00002392* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Precision M4600) + +pci:v00001002d00006740sv00001028sd0000053E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (FirePro M5950) + +pci:v00001002d00006740sv0000103Csd00001630* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (FirePro M5950) + +pci:v00001002d00006740sv0000103Csd00001631* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (FirePro M5950) + +pci:v00001002d00006740sv0000103Csd0000164B* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv0000103Csd0000164E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv0000103Csd00001657* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv0000103Csd00001658* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv0000103Csd0000165A* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv0000103Csd0000165B* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv0000103Csd00001688* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv0000103Csd00001689* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv0000103Csd0000168A* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv0000103Csd0000185E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 7690M XT) + +pci:v00001002d00006740sv0000103Csd00003388* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv0000103Csd00003389* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv0000103Csd00003582* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6770M) + +pci:v00001002d00006740sv0000103Csd0000366C* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv00001043sd00001D02* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv00001043sd00001D12* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv0000104Dsd00009084* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv0000104Dsd00009085* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv0000144Dsd0000B074* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv0000144Dsd0000B077* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv0000144Dsd0000B084* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv0000144Dsd0000B088* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006740sv000017AAsd00003982* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6730M/6770M/7690M XT] (Radeon HD 6730M) + +pci:v00001002d00006741* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] + +pci:v00001002d00006741sv00001019sd0000238E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001019sd0000238F* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000379* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000037B* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000037E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000382* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000384* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000385* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000386* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000387* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000388* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000442* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000451* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000489* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000048B* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000048C* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000050A* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000050B* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000050C* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000050E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000050F* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000513* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000514* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000515* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000516* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000051E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000051F* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000520* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000521* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000052A* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000555* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000556* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000055D* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000055E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000056D* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000059A* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000059B* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000059E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd0000059F* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000600* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000605* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000606* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001025sd00000619* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001028sd000004C1* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv00001028sd000004C5* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv00001028sd000004CD* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv00001028sd000004D7* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv00001028sd000004D9* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv00001028sd0000052D* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv0000103Csd00001617* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv0000103Csd00001646* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) + +pci:v00001002d00006741sv0000103Csd00001647* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv0000103Csd0000164B* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv0000103Csd0000164E* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv0000103Csd00001688* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) + +pci:v00001002d00006741sv0000103Csd00001689* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) + +pci:v00001002d00006741sv0000103Csd0000168A* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) + +pci:v00001002d00006741sv0000103Csd00001860* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 7690M) + +pci:v00001002d00006741sv0000103Csd00003385* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv0000103Csd00003560* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) + +pci:v00001002d00006741sv0000103Csd0000358D* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) + +pci:v00001002d00006741sv0000103Csd00003590* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) + +pci:v00001002d00006741sv0000103Csd00003593* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) + +pci:v00001002d00006741sv0000103Csd0000366C* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001043sd00001CD2* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001043sd00002121* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001043sd00002122* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001043sd00002123* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001043sd00002125* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 7670M) + +pci:v00001002d00006741sv00001043sd00002127* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 7670M) + +pci:v00001002d00006741sv0000104Dsd0000907B* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv0000104Dsd00009080* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv0000104Dsd00009081* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv0000106Bsd000000E2* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (MacBookPro8,2 [Core i7, 15", Late 2011]) + +pci:v00001002d00006741sv00001179sd0000FD63* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv00001179sd0000FD65* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv0000144Dsd0000C093* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv0000144Dsd0000C0AC* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv0000144Dsd0000C0B3* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6750M) + +pci:v00001002d00006741sv0000144Dsd0000C539* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv0000144Dsd0000C609* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv0000152Dsd00000914* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv000017AAsd000021E1* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6630M) + +pci:v00001002d00006741sv000017AAsd00003970* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv000017AAsd00003976* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006741sv00001854sd00000907* + ID_MODEL_FROM_DATABASE=Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] (Radeon HD 6650M) + +pci:v00001002d00006742* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] + +pci:v00001002d00006742sv00001002sd00006570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) + +pci:v00001002d00006742sv00001019sd00002393* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 6610M) + +pci:v00001002d00006742sv00001043sd00001D82* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (K53SK Laptop Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB22* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB23* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB27* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB2A* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB2C* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB30* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB31* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB32* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB38* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB39* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB3A* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB3B* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB40* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB41* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB47* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB48* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB49* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB51* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB52* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB53* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB56* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB81* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB82* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FB83* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FC56* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FCD4* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001179sd0000FCEE* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 7610M) + +pci:v00001002d00006742sv00001458sd00006570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) + +pci:v00001002d00006742sv00001462sd00006570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) + +pci:v00001002d00006742sv0000148Csd00006570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) + +pci:v00001002d00006742sv00001682sd00006570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) + +pci:v00001002d00006742sv0000174Bsd00005570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 5570]) + +pci:v00001002d00006742sv0000174Bsd00006570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) + +pci:v00001002d00006742sv0000174Bsd00007570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 7570]) + +pci:v00001002d00006742sv0000174Bsd00008510* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 8510]) + +pci:v00001002d00006742sv0000174Bsd00008570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 8570]) + +pci:v00001002d00006742sv00001787sd00006570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) + +pci:v00001002d00006742sv000017AFsd00006570* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Turks [Radeon HD 6570]) + +pci:v00001002d00006742sv00008086sd00002111* + ID_MODEL_FROM_DATABASE=Whistler LE [Radeon HD 6610M/7610M] (Radeon HD 6625M) + +pci:v00001002d00006743* + ID_MODEL_FROM_DATABASE=Whistler [Radeon E6760] + +pci:v00001002d00006749* + ID_MODEL_FROM_DATABASE=Turks GL [FirePro V4900] + +pci:v00001002d00006749sv000015C3sd00002B06* + ID_MODEL_FROM_DATABASE=Turks GL [FirePro V4900] (MED-X4900) + +pci:v00001002d0000674A* + ID_MODEL_FROM_DATABASE=Turks GL [FirePro V3900] + +pci:v00001002d0000674Asv000013CCsd00003D22* + ID_MODEL_FROM_DATABASE=Turks GL [FirePro V3900] (MXRT-2500) + +pci:v00001002d0000674Asv000015C3sd00000106* + ID_MODEL_FROM_DATABASE=Turks GL [FirePro V3900] (MED-X3900) + +pci:v00001002d00006750* + ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] + +pci:v00001002d00006750sv00001462sd00002670* + ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 6670A) + +pci:v00001002d00006750sv000017AAsd00003079* + ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 7650A) + +pci:v00001002d00006750sv000017AAsd0000307A* + ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 6650A) + +pci:v00001002d00006750sv000017AAsd00003087* + ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 7650A) + +pci:v00001002d00006750sv000017AAsd00003618* + ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 6650A) + +pci:v00001002d00006750sv000017AAsd00003623* + ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 6650A) + +pci:v00001002d00006750sv000017AAsd00003627* + ID_MODEL_FROM_DATABASE=Onega [Radeon HD 6650A/7650A] (Radeon HD 6650A) + +pci:v00001002d00006751* + ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] + +pci:v00001002d00006751sv00001028sd00000548* + ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7650A) + +pci:v00001002d00006751sv00001462sd00002671* + ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7670A) + +pci:v00001002d00006751sv00001462sd00002672* + ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7670A) + +pci:v00001002d00006751sv00001462sd00002680* + ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7650A) + +pci:v00001002d00006751sv00001462sd00002681* + ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7650A) + +pci:v00001002d00006751sv000017AAsd00003087* + ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7650A/7670A] (Radeon HD 7650A) + +pci:v00001002d00006758* + ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] + +pci:v00001002d00006758sv00001028sd00000B0E* + ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 6670) + +pci:v00001002d00006758sv0000103Csd00006882* + ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 6670) + +pci:v00001002d00006758sv00001462sd0000250A* + ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 7670) + +pci:v00001002d00006758sv0000148Csd00007670* + ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 7670) + +pci:v00001002d00006758sv00001545sd00007670* + ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 7670) + +pci:v00001002d00006758sv00001682sd00003300* + ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 7670) + +pci:v00001002d00006758sv0000174Bsd00007670* + ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 7670) + +pci:v00001002d00006758sv0000174Bsd0000E181* + ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 6670) + +pci:v00001002d00006758sv00001787sd00002309* + ID_MODEL_FROM_DATABASE=Turks XT [Radeon HD 6670/7670] (Radeon HD 6670) + +pci:v00001002d00006759* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] + +pci:v00001002d00006759sv0000103Csd00003130* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv00001043sd00000403* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv00001462sd00002500* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv00001462sd00002509* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) + +pci:v00001002d00006759sv0000148Csd00007570* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) + +pci:v00001002d00006759sv00001642sd00003A67* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv00001682sd00003280* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) + +pci:v00001002d00006759sv00001682sd00003530* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 8550) + +pci:v00001002d00006759sv0000174Bsd00007570* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) + +pci:v00001002d00006759sv0000174Bsd0000E142* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv0000174Bsd0000E181* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv00001B0Asd0000908F* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv00001B0Asd00009090* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv00001B0Asd00009091* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv00001B0Asd00009092* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv00001B0Asd0000909E* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 6570) + +pci:v00001002d00006759sv00001B0Asd000090B5* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) + +pci:v00001002d00006759sv00001B0Asd000090B6* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 6570/7570/8550] (Radeon HD 7570) + +pci:v00001002d0000675B* + ID_MODEL_FROM_DATABASE=Turks [Radeon HD 7600 Series] + +pci:v00001002d0000675D* + ID_MODEL_FROM_DATABASE=Turks PRO [Radeon HD 7570] + +pci:v00001002d0000675F* + ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] + +pci:v00001002d0000675Fsv0000148Csd00006510* + ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 6510) + +pci:v00001002d0000675Fsv0000148Csd00006530* + ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 6530) + +pci:v00001002d0000675Fsv0000148Csd00007510* + ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 7510) + +pci:v00001002d0000675Fsv00001545sd00007570* + ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 7570) + +pci:v00001002d0000675Fsv0000174Bsd00006510* + ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 6510) + +pci:v00001002d0000675Fsv0000174Bsd00007510* + ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 7510) + +pci:v00001002d0000675Fsv0000174Bsd00008510* + ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 8510) + +pci:v00001002d0000675Fsv00001787sd00002012* + ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 5570 2GB GDDR3) + +pci:v00001002d0000675Fsv00001787sd00002314* + ID_MODEL_FROM_DATABASE=Turks LE [Radeon HD 5570/6510/7510/8510] (Radeon HD 5570 1GB DDR2/GDDR3) + +pci:v00001002d00006760* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] + +pci:v00001002d00006760sv00001002sd00000124* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001002sd00000134* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001019sd0000238B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001019sd0000238E* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001019sd00002390* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001019sd00009985* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd000004C1* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd000004C3* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd000004CA* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd000004CB* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd000004CC* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Vostro 3350) + +pci:v00001002d00006760sv00001028sd000004D1* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd000004D3* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd000004D7* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd00000502* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd00000503* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd00000506* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd00000507* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd00000514* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001028sd0000051C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) + +pci:v00001002d00006760sv00001028sd0000051D* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) + +pci:v00001002d00006760sv0000103Csd0000161A* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000161B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000161E* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000161F* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001622* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) + +pci:v00001002d00006760sv0000103Csd00001623* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) + +pci:v00001002d00006760sv0000103Csd0000164A* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000164D* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001651* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001656* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd00001658* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd00001659* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd0000165B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd0000165D* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000165F* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001661* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001663* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001665* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001667* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001669* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000166B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000166C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000166E* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001670* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001672* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000167A* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000167B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000167D* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd0000167F* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd0000168C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000168F* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001694* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001696* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00001698* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000169A* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000169C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd00001855* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv0000103Csd00001859* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv0000103Csd0000185C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv0000103Csd0000185D* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv0000103Csd0000185F* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv0000103Csd00001863* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv0000103Csd0000355C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd0000355F* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd00003563* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00003565* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00003567* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00003569* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00003581* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd00003584* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd0000358C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd0000358F* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd00003592* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd00003596* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000103Csd0000366B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000103Csd00003671* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (FirePro M3900) + +pci:v00001002d00006760sv0000103Csd00003673* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd0000100A* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd0000100C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd0000101B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd0000101C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd0000102A* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv00001043sd0000102C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd0000104B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd0000105D* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd0000106B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd0000106D* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd0000107D* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd00001CB2* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd00001D22* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd00001D32* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd00002001* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd00002002* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd00002107* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd00002108* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd00002109* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd000084A0* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd000084E9* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001043sd00008515* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd00008517* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001043sd0000855A* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv0000104Dsd0000907B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000104Dsd00009081* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000104Dsd00009084* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000104Dsd00009085* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) + +pci:v00001002d00006760sv00001179sd00000003* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) + +pci:v00001002d00006760sv00001179sd00000004* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6450M) + +pci:v00001002d00006760sv00001179sd0000FB22* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB23* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB2C* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB31* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB32* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB33* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB38* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB39* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB3A* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB40* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB41* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB42* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB47* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB48* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB51* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB52* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB53* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB81* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB82* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FB83* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FC51* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001179sd0000FC52* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FC56* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FCD3* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FCD4* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FCEE* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv00001179sd0000FDEE* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv0000144Dsd0000B074* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000144Dsd0000B084* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000144Dsd0000C095* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000144Dsd0000C0B3* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6490M) + +pci:v00001002d00006760sv0000144Dsd0000C538* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000144Dsd0000C581* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000144Dsd0000C589* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000144Dsd0000C609* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv0000144Dsd0000C625* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv0000144Dsd0000C636* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv00001462sd000010AC* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv0000152Dsd00000916* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv000017AAsd000021E5* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv000017AAsd00003900* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv000017AAsd00003902* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv000017AAsd00003969* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv000017AAsd00003970* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv000017AAsd00003976* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv000017AAsd0000397B* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv000017AAsd0000397D* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv000017AAsd00005101* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7470M) + +pci:v00001002d00006760sv000017AAsd00005102* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv000017AAsd00005103* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv000017AAsd00005106* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 7450M) + +pci:v00001002d00006760sv00001854sd00000897* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001854sd00000900* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001854sd00000908* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006760sv00001854sd00002015* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M/7400M Series] (Radeon HD 6470M) + +pci:v00001002d00006761* + ID_MODEL_FROM_DATABASE=Seymour LP [Radeon HD 6430M] + +pci:v00001002d00006763* + ID_MODEL_FROM_DATABASE=Seymour [Radeon E6460] + +pci:v00001002d00006764* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M Series] + +pci:v00001002d00006765* + ID_MODEL_FROM_DATABASE=Seymour [Radeon HD 6400M Series] + +pci:v00001002d00006766* + ID_MODEL_FROM_DATABASE=Caicos + +pci:v00001002d00006767* + ID_MODEL_FROM_DATABASE=Caicos + +pci:v00001002d00006768* + ID_MODEL_FROM_DATABASE=Caicos + +pci:v00001002d00006770* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] + +pci:v00001002d00006770sv000017AAsd0000308D* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 7450A) + +pci:v00001002d00006770sv000017AAsd00003623* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 6450A) + +pci:v00001002d00006770sv000017AAsd00003627* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 6450A) + +pci:v00001002d00006770sv000017AAsd00003629* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 6450A) + +pci:v00001002d00006770sv000017AAsd0000363C* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 6450A) + +pci:v00001002d00006770sv000017AAsd00003658* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450A/7450A] (Radeon HD 7470A) + +pci:v00001002d00006771* + ID_MODEL_FROM_DATABASE=Caicos XTX [Radeon HD 8490 / R5 235X OEM] + +pci:v00001002d00006772* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 7450A] + +pci:v00001002d00006778* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] + +pci:v00001002d00006778sv00001019sd00000024* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 7470) + +pci:v00001002d00006778sv00001019sd00000027* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) + +pci:v00001002d00006778sv00001028sd00002120* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 7470) + +pci:v00001002d00006778sv00001462sd0000B491* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) + +pci:v00001002d00006778sv00001462sd0000B492* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) + +pci:v00001002d00006778sv00001462sd0000B493* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470 OEM) + +pci:v00001002d00006778sv00001462sd0000B499* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon R5 235 OEM) + +pci:v00001002d00006778sv00001642sd00003C65* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) + +pci:v00001002d00006778sv00001642sd00003C75* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) + +pci:v00001002d00006778sv0000174Bsd00008145* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 8470) + +pci:v00001002d00006778sv0000174Bsd0000D145* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon R5 235 OEM) + +pci:v00001002d00006778sv0000174Bsd0000D335* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon R5 310 OEM) + +pci:v00001002d00006778sv0000174Bsd0000E145* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon HD 7470) + +pci:v00001002d00006778sv000017AAsd00003694* + ID_MODEL_FROM_DATABASE=Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] (Radeon R5 A220) + +pci:v00001002d00006779* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] + +pci:v00001002d00006779sv00001019sd00000016* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001019sd00000017* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001019sd00000018* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001028sd00002120* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv0000103Csd00002128* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv0000103Csd00002AEE* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450A) + +pci:v00001002d00006779sv00001092sd00006450* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001462sd00002125* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001462sd00002346* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) + +pci:v00001002d00006779sv00001462sd00002490* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001462sd00002494* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001462sd00002496* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) + +pci:v00001002d00006779sv0000148Csd00007450* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) + +pci:v00001002d00006779sv0000148Csd00008450* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 8450 OEM) + +pci:v00001002d00006779sv00001545sd00007470* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7470) + +pci:v00001002d00006779sv00001642sd00003A65* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001642sd00003A66* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) + +pci:v00001002d00006779sv00001642sd00003A75* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001642sd00003A76* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) + +pci:v00001002d00006779sv00001682sd00003200* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) + +pci:v00001002d00006779sv0000174Bsd00007450* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450) + +pci:v00001002d00006779sv0000174Bsd0000E127* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv0000174Bsd0000E153* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv0000174Bsd0000E164* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450 1 GB DDR3) + +pci:v00001002d00006779sv0000174Bsd0000E180* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv0000174Bsd0000E201* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv000017AFsd00008450* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 8450 OEM) + +pci:v00001002d00006779sv00001B0Asd00009096* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001B0Asd00009097* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001B0Asd000090A8* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450A) + +pci:v00001002d00006779sv00001B0Asd000090B1* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 6450) + +pci:v00001002d00006779sv00001B0Asd000090B3* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450A) + +pci:v00001002d00006779sv00001B0Asd000090BB* + ID_MODEL_FROM_DATABASE=Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] (Radeon HD 7450A) + +pci:v00001002d0000677B* + ID_MODEL_FROM_DATABASE=Caicos PRO [Radeon HD 7450] + +pci:v00001002d00006780* + ID_MODEL_FROM_DATABASE=Tahiti XT GL [FirePro W9000] + +pci:v00001002d00006784* + ID_MODEL_FROM_DATABASE=Tahiti [FirePro Series Graphics Adapter] + +pci:v00001002d00006788* + ID_MODEL_FROM_DATABASE=Tahiti [FirePro Series Graphics Adapter] + +pci:v00001002d0000678A* + ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] + +pci:v00001002d0000678Asv00001002sd0000030C* + ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro W8000) + +pci:v00001002d0000678Asv00001002sd00000310* + ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro S9000) + +pci:v00001002d0000678Asv00001002sd00000420* + ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (Radeon Sky 700) + +pci:v00001002d0000678Asv00001002sd00000422* + ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (Radeon Sky 900) + +pci:v00001002d0000678Asv00001002sd00000710* + ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro S9050) + +pci:v00001002d0000678Asv00001002sd00000B0E* + ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro S10000 Passive) + +pci:v00001002d0000678Asv00001002sd00000B2A* + ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro S10000) + +pci:v00001002d0000678Asv00001028sd0000030C* + ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro W8000) + +pci:v00001002d0000678Asv00001028sd00000710* + ID_MODEL_FROM_DATABASE=Tahiti PRO GL [FirePro Series] (FirePro S9000) + +pci:v00001002d00006798* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] + +pci:v00001002d00006798sv00001002sd00003000* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Radeon HD 7970 GHz Edition]) + +pci:v00001002d00006798sv00001002sd00003001* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XTL [Radeon R9 280X]) + +pci:v00001002d00006798sv00001002sd00004000* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Radeon HD 8970 OEM) + +pci:v00001002d00006798sv00001043sd0000041C* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 DirectCU II) + +pci:v00001002d00006798sv00001043sd00000420* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 DirectCU II TOP) + +pci:v00001002d00006798sv00001043sd00000444* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 DirectCU II TOP) + +pci:v00001002d00006798sv00001043sd00000448* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 DirectCU II TOP) + +pci:v00001002d00006798sv00001043sd0000044A* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Matrix HD 7970]) + +pci:v00001002d00006798sv00001043sd0000044C* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Matrix HD 7970 Platinum]) + +pci:v00001002d00006798sv00001043sd00003001* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XTL [ROG Matrix R9 280X]) + +pci:v00001002d00006798sv00001043sd00003006* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XTL [Radeon R9 280X DirectCU II TOP]) + +pci:v00001002d00006798sv00001043sd00009999* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (ARES II) + +pci:v00001002d00006798sv0000106Bsd00000127* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (FirePro D700) + +pci:v00001002d00006798sv0000106Bsd00000128* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (FirePro D700) + +pci:v00001002d00006798sv00001092sd00003000* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Radeon HD 7970 GHz Edition]) + +pci:v00001002d00006798sv00001458sd00002261* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Radeon HD 7970 GHz Edition OC]) + +pci:v00001002d00006798sv00001458sd00003001* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XTL [Radeon R9 280X OC]) + +pci:v00001002d00006798sv00001462sd00002774* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 TwinFrozr III Boost Edition OC) + +pci:v00001002d00006798sv00001682sd00003001* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XTL [Radeon R9 280X]) + +pci:v00001002d00006798sv00001682sd00003211* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Double D HD 7970 Black Edition) + +pci:v00001002d00006798sv00001682sd00003213* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 Black Edition) + +pci:v00001002d00006798sv00001682sd00003214* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Double D HD 7970) + +pci:v00001002d00006798sv00001787sd0000201C* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (HD 7970 IceQ X²) + +pci:v00001002d00006798sv00001787sd00002317* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Radeon HD 7990) + +pci:v00001002d00006798sv00001787sd00003000* + ID_MODEL_FROM_DATABASE=Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (Tahiti XT2 [Radeon HD 7970 GHz Edition]) + +pci:v00001002d0000679A* + ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] + +pci:v00001002d0000679Asv00001002sd00000B01* + ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] (Radeon HD 8950 OEM) + +pci:v00001002d0000679Asv00001002sd00003000* + ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] (Tahiti PRO2 [Radeon HD 7950 Boost]) + +pci:v00001002d0000679Asv00001462sd00003000* + ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] (Radeon HD 8950 OEM) + +pci:v00001002d0000679Asv0000174Bsd0000A003* + ID_MODEL_FROM_DATABASE=Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] (Radeon R9 280) + +pci:v00001002d0000679B* + ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990/8990 OEM] + +pci:v00001002d0000679Bsv00001002sd00000B28* + ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990/8990 OEM] (Radeon HD 8990 OEM) + +pci:v00001002d0000679Bsv00001002sd00000B2A* + ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990/8990 OEM] (Radeon HD 7990) + +pci:v00001002d0000679Bsv00001462sd00008036* + ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990/8990 OEM] (Radeon HD 8990 OEM) + +pci:v00001002d0000679Bsv0000148Csd00008990* + ID_MODEL_FROM_DATABASE=Malta [Radeon HD 7990/8990 OEM] (Radeon HD 8990 OEM) + +pci:v00001002d0000679E* + ID_MODEL_FROM_DATABASE=Tahiti LE [Radeon HD 7870 XT] + +pci:v00001002d0000679Esv0000106Bsd00000125* + ID_MODEL_FROM_DATABASE=Tahiti LE [Radeon HD 7870 XT] (FirePro D500) + +pci:v00001002d0000679Esv0000106Bsd00000126* + ID_MODEL_FROM_DATABASE=Tahiti LE [Radeon HD 7870 XT] (FirePro D500) + +pci:v00001002d0000679Esv00001787sd00002328* + ID_MODEL_FROM_DATABASE=Tahiti LE [Radeon HD 7870 XT] (Radeon HD 7870 Black Edition 2 GB GDDR5 [2GBD5-2DHV3E]) + +pci:v00001002d0000679F* + ID_MODEL_FROM_DATABASE=Tahiti + +pci:v00001002d000067A0* + ID_MODEL_FROM_DATABASE=Hawaii XT GL [FirePro W9100] + +pci:v00001002d000067A0sv00001002sd00000335* + ID_MODEL_FROM_DATABASE=Hawaii XT GL [FirePro W9100] (FirePro S9150) + +pci:v00001002d000067A0sv00001002sd00000735* + ID_MODEL_FROM_DATABASE=Hawaii XT GL [FirePro W9100] (FirePro S9170) + +pci:v00001002d000067A0sv00001028sd0000031F* + ID_MODEL_FROM_DATABASE=Hawaii XT GL [FirePro W9100] (FirePro W9100) + +pci:v00001002d000067A0sv00001028sd00000335* + ID_MODEL_FROM_DATABASE=Hawaii XT GL [FirePro W9100] (FirePro S9150) + +pci:v00001002d000067A1* + ID_MODEL_FROM_DATABASE=Hawaii PRO GL [FirePro W8100] + +pci:v00001002d000067A1sv00001002sd00000335* + ID_MODEL_FROM_DATABASE=Hawaii PRO GL [FirePro W8100] (FirePro S9100) + +pci:v00001002d000067A1sv00001028sd00000335* + ID_MODEL_FROM_DATABASE=Hawaii PRO GL [FirePro W8100] (FirePro S9100) + +pci:v00001002d000067A2* + ID_MODEL_FROM_DATABASE=Hawaii GL + +pci:v00001002d000067A8* + ID_MODEL_FROM_DATABASE=Hawaii + +pci:v00001002d000067A9* + ID_MODEL_FROM_DATABASE=Hawaii + +pci:v00001002d000067AA* + ID_MODEL_FROM_DATABASE=Hawaii + +pci:v00001002d000067B0* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] + +pci:v00001002d000067B0sv00001028sd00000B00* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Grenada XT [Radeon R9 390X]) + +pci:v00001002d000067B0sv0000103Csd00006566* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Radeon R9 390X) + +pci:v00001002d000067B0sv00001043sd0000046A* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X DirectCU II) + +pci:v00001002d000067B0sv00001043sd0000046C* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X DirectCU II OC) + +pci:v00001002d000067B0sv00001043sd00000474* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Matrix R9 290X Platinum) + +pci:v00001002d000067B0sv00001043sd00000476* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (ARES III) + +pci:v00001002d000067B0sv00001043sd000004D7* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Radeon R9 390X) + +pci:v00001002d000067B0sv00001043sd000004DB* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Radeon R9 390X) + +pci:v00001002d000067B0sv00001043sd000004DF* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Radeon R9 390X) + +pci:v00001002d000067B0sv00001043sd000004E9* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Radeon R9 390X) + +pci:v00001002d000067B0sv00001458sd0000227C* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X WindForce 3X OC) + +pci:v00001002d000067B0sv00001458sd00002281* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X WindForce 3X OC) + +pci:v00001002d000067B0sv00001458sd0000228C* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X WindForce 3X) + +pci:v00001002d000067B0sv00001458sd0000228D* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X WindForce 3X OC) + +pci:v00001002d000067B0sv00001458sd00002290* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X WindForce 3X) + +pci:v00001002d000067B0sv00001458sd000022BC* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Radeon R9 390X) + +pci:v00001002d000067B0sv00001458sd000022C1* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Grenada PRO [Radeon R9 390]) + +pci:v00001002d000067B0sv00001462sd00002015* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Radeon R9 390X) + +pci:v00001002d000067B0sv00001462sd00003070* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X Lightning) + +pci:v00001002d000067B0sv00001462sd00003071* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X Lightning) + +pci:v00001002d000067B0sv00001462sd00003072* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X Lightning LE) + +pci:v00001002d000067B0sv00001462sd00003080* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X Gaming) + +pci:v00001002d000067B0sv00001462sd00003082* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X Gaming OC) + +pci:v00001002d000067B0sv0000148Csd00002347* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Devil 13 Dual Core R9 290X) + +pci:v00001002d000067B0sv0000148Csd00002357* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Grenada XT [Radeon R9 390X]) + +pci:v00001002d000067B0sv00001682sd00009290* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Double Dissipation R9 290X) + +pci:v00001002d000067B0sv00001682sd00009395* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Grenada XT [Radeon R9 390X]) + +pci:v00001002d000067B0sv0000174Bsd00000E34* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Radeon R9 390X) + +pci:v00001002d000067B0sv0000174Bsd0000E282* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Vapor-X R9 290X Tri-X OC) + +pci:v00001002d000067B0sv0000174Bsd0000E285* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X Tri-X OC) + +pci:v00001002d000067B0sv0000174Bsd0000E324* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Grenada XT2 [Radeon R9 390X]) + +pci:v00001002d000067B0sv00001787sd00002020* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (R9 290X IceQ X² Turbo) + +pci:v00001002d000067B0sv00001787sd00002357* + ID_MODEL_FROM_DATABASE=Hawaii XT / Grenada XT [Radeon R9 290X/390X] (Grenada XT [Radeon R9 390X]) + +pci:v00001002d000067B1* + ID_MODEL_FROM_DATABASE=Hawaii PRO [Radeon R9 290/390] + +pci:v00001002d000067B1sv00001043sd000004DD* + ID_MODEL_FROM_DATABASE=Hawaii PRO [Radeon R9 290/390] (STRIX R9 390) + +pci:v00001002d000067B1sv0000148Csd00002358* + ID_MODEL_FROM_DATABASE=Hawaii PRO [Radeon R9 290/390] (Radeon R9 390) + +pci:v00001002d000067B1sv0000174Bsd0000E324* + ID_MODEL_FROM_DATABASE=Hawaii PRO [Radeon R9 290/390] (Sapphire Nitro R9 390) + +pci:v00001002d000067B9* + ID_MODEL_FROM_DATABASE=Vesuvius [Radeon R9 295X2] + +pci:v00001002d000067BE* + ID_MODEL_FROM_DATABASE=Hawaii LE + +pci:v00001002d000067C0* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 7100 Mobile] + +pci:v00001002d000067C2* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro V7300X / V7350x2] + +pci:v00001002d000067C4* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 7100] + +pci:v00001002d000067C4sv00001002sd00000336* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 7100] (Radeon Pro Duo) + +pci:v00001002d000067C4sv00001002sd00001336* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 7100] (Radeon Pro Duo) + +pci:v00001002d000067C7* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro WX 5100] + +pci:v00001002d000067CA* + ID_MODEL_FROM_DATABASE=Ellesmere [Polaris10] + +pci:v00001002d000067CC* + ID_MODEL_FROM_DATABASE=Ellesmere [Polaris10] + +pci:v00001002d000067CF* + ID_MODEL_FROM_DATABASE=Ellesmere [Polaris10] + +pci:v00001002d000067D0* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon Pro V7300X / V7350x2] + +pci:v00001002d000067DF* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] + +pci:v00001002d000067DFsv00001002sd00000B37* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 480) + +pci:v00001002d000067DFsv00001028sd00001722* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 570X) + +pci:v00001002d000067DFsv00001028sd00001723* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 580X) + +pci:v00001002d000067DFsv00001043sd000004A8* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 480) + +pci:v00001002d000067DFsv00001043sd000004B0* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 470) + +pci:v00001002d000067DFsv00001043sd000004FB* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 480) + +pci:v00001002d000067DFsv00001043sd000004FD* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 480 8GB) + +pci:v00001002d000067DFsv00001043sd0000056A* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 590) + +pci:v00001002d000067DFsv0000106Bsd00000161* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon Pro 580) + +pci:v00001002d000067DFsv0000106Bsd00000162* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon Pro 575) + +pci:v00001002d000067DFsv0000106Bsd00000163* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon Pro 570) + +pci:v00001002d000067DFsv00001458sd000022F0* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 570) + +pci:v00001002d000067DFsv00001458sd000022F7* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 570 Gaming 4G) + +pci:v00001002d000067DFsv00001462sd00003411* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 470) + +pci:v00001002d000067DFsv00001462sd00003413* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 480 Gaming X 8GB) + +pci:v00001002d000067DFsv00001462sd00003416* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 570) + +pci:v00001002d000067DFsv00001462sd00003418* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 580 Armor 4G OC) + +pci:v00001002d000067DFsv00001462sd0000341E* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 570 Armor 4G OC) + +pci:v00001002d000067DFsv00001462sd00008A92* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 580) + +pci:v00001002d000067DFsv0000148Csd00002372* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 480) + +pci:v00001002d000067DFsv0000148Csd00002373* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 470) + +pci:v00001002d000067DFsv00001682sd00009470* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 470) + +pci:v00001002d000067DFsv00001682sd00009480* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 480) + +pci:v00001002d000067DFsv00001682sd00009588* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 580 XTR) + +pci:v00001002d000067DFsv00001682sd0000C570* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 570) + +pci:v00001002d000067DFsv0000174Bsd0000E347* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 470/480) + +pci:v00001002d000067DFsv0000174Bsd0000E349* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 470) + +pci:v00001002d000067DFsv00001787sd0000A470* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 470) + +pci:v00001002d000067DFsv00001787sd0000A480* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 480) + +pci:v00001002d000067DFsv00001849sd00005001* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Phantom Gaming X RX 580 OC) + +pci:v00001002d000067DFsv00001849sd00005030* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Phantom Gaming D Radeon RX580 8G OC) + +pci:v00001002d000067DFsv00001DA2sd0000E353* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 570 Pulse 4GB) + +pci:v00001002d000067DFsv00001DA2sd0000E366* + ID_MODEL_FROM_DATABASE=Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Nitro+ Radeon RX 570/580/590) + +pci:v00001002d000067E0* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4170] + +pci:v00001002d000067E0sv0000103Csd00008270* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4170] (Radeon Pro WX 4170) + +pci:v00001002d000067E0sv0000103Csd00008272* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4170] (Radeon Pro WX 4170) + +pci:v00001002d000067E1* + ID_MODEL_FROM_DATABASE=Baffin [Polaris11] + +pci:v00001002d000067E3* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4100] + +pci:v00001002d000067E8* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4130/4150] + +pci:v00001002d000067E8sv00001028sd0000075D* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4130/4150] (Radeon Pro WX 4150) + +pci:v00001002d000067E8sv00001028sd000007B0* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4130/4150] (Radeon Pro WX 4130/4150) + +pci:v00001002d000067E8sv00001028sd000007B1* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4130/4150] (Radeon Pro WX 4130) + +pci:v00001002d000067E8sv00001028sd0000175D* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4130/4150] (Radeon Pro WX 4150) + +pci:v00001002d000067E8sv00001028sd000017B0* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4130/4150] (Radeon Pro WX 4130/4150) + +pci:v00001002d000067E8sv00001028sd000017B1* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4130/4150] (Radeon Pro WX 4130) + +pci:v00001002d000067E8sv0000103Csd00008275* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4130/4150] (Radeon Pro WX 4150) + +pci:v00001002d000067E8sv0000103Csd00008277* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro WX 4130/4150] (Radeon Pro WX 4150) + +pci:v00001002d000067E9* + ID_MODEL_FROM_DATABASE=Baffin [Polaris11] + +pci:v00001002d000067EB* + ID_MODEL_FROM_DATABASE=Baffin [Radeon Pro V5300X] + +pci:v00001002d000067EF* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] + +pci:v00001002d000067EFsv00001028sd00001703* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (RX 560D OEM OC 2 GB) + +pci:v00001002d000067EFsv0000103Csd00003421* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Radeon RX 460) + +pci:v00001002d000067EFsv0000106Bsd00000160* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Radeon Pro 460) + +pci:v00001002d000067EFsv0000106Bsd00000166* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Radeon Pro 455) + +pci:v00001002d000067EFsv0000106Bsd00000167* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Radeon Pro 450) + +pci:v00001002d000067EFsv0000106Bsd00000179* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Radeon Pro 560) + +pci:v00001002d000067EFsv0000106Bsd0000017A* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Radeon Pro 555) + +pci:v00001002d000067EFsv0000106Bsd0000018F* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Radeon Pro 560X) + +pci:v00001002d000067EFsv0000106Bsd00000190* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Radeon Pro 555X) + +pci:v00001002d000067EFsv00001642sd00001727* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Polaris 21 XL [Radeon RX 560D]) + +pci:v00001002d000067EFsv00001682sd0000956D* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (Polaris 21 XL [Radeon RX 560D]) + +pci:v00001002d000067FF* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] + +pci:v00001002d000067FFsv00001002sd00000B04* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560) + +pci:v00001002d000067FFsv00001028sd00001721* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560X) + +pci:v00001002d000067FFsv00001028sd00001726* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560DX) + +pci:v00001002d000067FFsv0000103Csd00008479* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560X Mobile) + +pci:v00001002d000067FFsv00001043sd000004BC* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560) + +pci:v00001002d000067FFsv00001043sd0000052F* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560) + +pci:v00001002d000067FFsv00001458sd000022ED* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560) + +pci:v00001002d000067FFsv0000148Csd00002381* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560) + +pci:v00001002d000067FFsv00001682sd00009560* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560) + +pci:v00001002d000067FFsv00001DA2sd0000E348* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 560) + +pci:v00001002d000067FFsv00001DA2sd0000E367* + ID_MODEL_FROM_DATABASE=Baffin [Radeon RX 550 640SP / RX 560/560X] (Radeon RX 550 640SP) + +pci:v00001002d00006800* + ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M] + +pci:v00001002d00006800sv00001002sd00000124* + ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M] (Radeon HD 7970M) + +pci:v00001002d00006800sv00008086sd00002110* + ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M] (Radeon HD 7970M) + +pci:v00001002d00006800sv00008086sd00002111* + ID_MODEL_FROM_DATABASE=Wimbledon XT [Radeon HD 7970M] (Radeon HD 7970M) + +pci:v00001002d00006801* + ID_MODEL_FROM_DATABASE=Neptune XT [Radeon HD 8970M] + +pci:v00001002d00006801sv00001002sd00000124* + ID_MODEL_FROM_DATABASE=Neptune XT [Radeon HD 8970M] (Radeon HD 8970M) + +pci:v00001002d00006801sv00001462sd00001117* + ID_MODEL_FROM_DATABASE=Neptune XT [Radeon HD 8970M] (Radeon R9 M290X) + +pci:v00001002d00006801sv00008086sd00002110* + ID_MODEL_FROM_DATABASE=Neptune XT [Radeon HD 8970M] (Radeon HD 8970M) + +pci:v00001002d00006801sv00008086sd00002111* + ID_MODEL_FROM_DATABASE=Neptune XT [Radeon HD 8970M] (Radeon HD 8970M) + +pci:v00001002d00006802* + ID_MODEL_FROM_DATABASE=Wimbledon + +pci:v00001002d00006806* + ID_MODEL_FROM_DATABASE=Neptune + +pci:v00001002d00006808* + ID_MODEL_FROM_DATABASE=Pitcairn XT GL [FirePro W7000] + +pci:v00001002d00006808sv00001002sd00000310* + ID_MODEL_FROM_DATABASE=Pitcairn XT GL [FirePro W7000] (FirePro S7000) + +pci:v00001002d00006808sv00001002sd00000420* + ID_MODEL_FROM_DATABASE=Pitcairn XT GL [FirePro W7000] (Radeon Sky 500) + +pci:v00001002d00006808sv0000103Csd0000030C* + ID_MODEL_FROM_DATABASE=Pitcairn XT GL [FirePro W7000] (MED-X7000) + +pci:v00001002d00006808sv000013CCsd00003D25* + ID_MODEL_FROM_DATABASE=Pitcairn XT GL [FirePro W7000] (MXRT-7500) + +pci:v00001002d00006808sv000015C3sd0000030C* + ID_MODEL_FROM_DATABASE=Pitcairn XT GL [FirePro W7000] (MED-X7000) + +pci:v00001002d00006809* + ID_MODEL_FROM_DATABASE=Pitcairn LE GL [FirePro W5000] + +pci:v00001002d00006809sv000013CCsd00003D23* + ID_MODEL_FROM_DATABASE=Pitcairn LE GL [FirePro W5000] (MXRT-5500) + +pci:v00001002d00006809sv000013CCsd00003D24* + ID_MODEL_FROM_DATABASE=Pitcairn LE GL [FirePro W5000] (MXRT-5550) + +pci:v00001002d00006809sv000015C3sd00000B06* + ID_MODEL_FROM_DATABASE=Pitcairn LE GL [FirePro W5000] (MED-X5000) + +pci:v00001002d00006810* + ID_MODEL_FROM_DATABASE=Curacao XT / Trinidad XT [Radeon R7 370 / R9 270X/370X] + +pci:v00001002d00006810sv0000106Bsd0000012A* + ID_MODEL_FROM_DATABASE=Curacao XT / Trinidad XT [Radeon R7 370 / R9 270X/370X] (FirePro D300) + +pci:v00001002d00006810sv0000106Bsd0000012B* + ID_MODEL_FROM_DATABASE=Curacao XT / Trinidad XT [Radeon R7 370 / R9 270X/370X] (FirePro D300) + +pci:v00001002d00006810sv0000148Csd00000908* + ID_MODEL_FROM_DATABASE=Curacao XT / Trinidad XT [Radeon R7 370 / R9 270X/370X] (Radeon R9 370 OEM) + +pci:v00001002d00006810sv00001682sd00007370* + ID_MODEL_FROM_DATABASE=Curacao XT / Trinidad XT [Radeon R7 370 / R9 270X/370X] (Radeon R7 370) + +pci:v00001002d00006811* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] + +pci:v00001002d00006811sv00001028sd00000B00* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) + +pci:v00001002d00006811sv00001043sd00002016* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) + +pci:v00001002d00006811sv00001458sd00002016* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) + +pci:v00001002d00006811sv00001462sd00002016* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) + +pci:v00001002d00006811sv00001462sd00003050* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (R9 270 Gaming OC) + +pci:v00001002d00006811sv0000148Csd00002016* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) + +pci:v00001002d00006811sv00001682sd00002015* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R7 370]) + +pci:v00001002d00006811sv0000174Bsd00002015* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (NITRO Radeon R7 370) + +pci:v00001002d00006811sv0000174Bsd00002016* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) + +pci:v00001002d00006811sv00001787sd00002016* + ID_MODEL_FROM_DATABASE=Curacao PRO [Radeon R7 370 / R9 270/370 OEM] (Trinidad PRO [Radeon R9 370 OEM]) + +pci:v00001002d00006816* + ID_MODEL_FROM_DATABASE=Pitcairn + +pci:v00001002d00006817* + ID_MODEL_FROM_DATABASE=Pitcairn + +pci:v00001002d00006818* + ID_MODEL_FROM_DATABASE=Pitcairn XT [Radeon HD 7870 GHz Edition] + +pci:v00001002d00006818sv00001002sd00000B05* + ID_MODEL_FROM_DATABASE=Pitcairn XT [Radeon HD 7870 GHz Edition] (Radeon HD 8870 OEM) + +pci:v00001002d00006818sv0000174Bsd00008B04* + ID_MODEL_FROM_DATABASE=Pitcairn XT [Radeon HD 7870 GHz Edition] (Radeon HD 8860) + +pci:v00001002d00006819* + ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] + +pci:v00001002d00006819sv00001043sd0000042C* + ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon HD 7850) + +pci:v00001002d00006819sv00001682sd00007269* + ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon R9 270 1024SP) + +pci:v00001002d00006819sv00001682sd00009278* + ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon R9 270 1024SP) + +pci:v00001002d00006819sv0000174Bsd0000A008* + ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon R9 270 1024SP) + +pci:v00001002d00006819sv0000174Bsd0000E221* + ID_MODEL_FROM_DATABASE=Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] (Radeon HD 7850 2GB GDDR5 DVI-I/DVI-D/HDMI/DP) + +pci:v00001002d00006820* + ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X] + +pci:v00001002d00006820sv0000103Csd00001851* + ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X] (Radeon HD 7750M) + +pci:v00001002d00006820sv000017AAsd00003643* + ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X] (Radeon R9 A375) + +pci:v00001002d00006820sv000017AAsd00003801* + ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X] (Radeon R9 M275) + +pci:v00001002d00006820sv000017AAsd00003824* + ID_MODEL_FROM_DATABASE=Venus XTX [Radeon HD 8890M / R9 M275X/M375X] (Radeon R9 M375) + +pci:v00001002d00006821* + ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8870M / R9 M270X/M370X] + +pci:v00001002d00006821sv00001002sd0000031E* + ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8870M / R9 M270X/M370X] (FirePro SX4000) + +pci:v00001002d00006821sv00001028sd000005CC* + ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8870M / R9 M270X/M370X] (FirePro M5100) + +pci:v00001002d00006821sv00001028sd000015CC* + ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8870M / R9 M270X/M370X] (FirePro M5100) + +pci:v00001002d00006821sv0000106Bsd00000149* + ID_MODEL_FROM_DATABASE=Venus XT [Radeon HD 8870M / R9 M270X/M370X] (Radeon R9 M370X Mac Edition) + +pci:v00001002d00006822* + ID_MODEL_FROM_DATABASE=Venus PRO [Radeon E8860] + +pci:v00001002d00006823* + ID_MODEL_FROM_DATABASE=Venus PRO [Radeon HD 8850M / R9 M265X] + +pci:v00001002d00006825* + ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] + +pci:v00001002d00006825sv00001028sd0000053F* + ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] (FirePro M6000) + +pci:v00001002d00006825sv00001028sd000005CD* + ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] (FirePro M6000) + +pci:v00001002d00006825sv00001028sd000015CD* + ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] (FirePro M6000) + +pci:v00001002d00006825sv0000103Csd0000176C* + ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] (FirePro M6000) + +pci:v00001002d00006825sv00008086sd00002111* + ID_MODEL_FROM_DATABASE=Heathrow XT [Radeon HD 7870M] (Chelsea PRO) + +pci:v00001002d00006826* + ID_MODEL_FROM_DATABASE=Chelsea LP [Radeon HD 7700M Series] + +pci:v00001002d00006827* + ID_MODEL_FROM_DATABASE=Heathrow PRO [Radeon HD 7850M/8850M] + +pci:v00001002d00006828* + ID_MODEL_FROM_DATABASE=Cape Verde PRO [FirePro W600] + +pci:v00001002d00006828sv000015C3sd00002B1E* + ID_MODEL_FROM_DATABASE=Cape Verde PRO [FirePro W600] (MED-X6000) + +pci:v00001002d00006829* + ID_MODEL_FROM_DATABASE=Cape Verde + +pci:v00001002d0000682A* + ID_MODEL_FROM_DATABASE=Venus PRO + +pci:v00001002d0000682B* + ID_MODEL_FROM_DATABASE=Cape Verde PRO / Venus LE / Tropo PRO-L [Radeon HD 8830M / R7 250 / R7 M465X] + +pci:v00001002d0000682Bsv00000128sd0000079C* + ID_MODEL_FROM_DATABASE=Cape Verde PRO / Venus LE / Tropo PRO-L [Radeon HD 8830M / R7 250 / R7 M465X] (Radeon R7 465X) + +pci:v00001002d0000682Bsv00001462sd00003012* + ID_MODEL_FROM_DATABASE=Cape Verde PRO / Venus LE / Tropo PRO-L [Radeon HD 8830M / R7 250 / R7 M465X] (Radeon R7 250) + +pci:v00001002d0000682C* + ID_MODEL_FROM_DATABASE=Cape Verde GL [FirePro W4100] + +pci:v00001002d0000682D* + ID_MODEL_FROM_DATABASE=Chelsea XT GL [FirePro M4000] + +pci:v00001002d0000682F* + ID_MODEL_FROM_DATABASE=Chelsea LP [Radeon HD 7730M] + +pci:v00001002d0000682Fsv0000103Csd00001851* + ID_MODEL_FROM_DATABASE=Chelsea LP [Radeon HD 7730M] (Radeon HD 7750M) + +pci:v00001002d00006835* + ID_MODEL_FROM_DATABASE=Cape Verde PRX [Radeon R9 255 OEM] + +pci:v00001002d00006837* + ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730] + +pci:v00001002d00006837sv00001462sd00002796* + ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730] (Radeon HD 8730) + +pci:v00001002d00006837sv00001462sd00008092* + ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730] (Radeon HD 8730) + +pci:v00001002d00006837sv0000148Csd00008730* + ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730] (Radeon HD 8730) + +pci:v00001002d00006837sv00001787sd00003000* + ID_MODEL_FROM_DATABASE=Cape Verde LE [Radeon HD 7730/8730] (Radeon HD 6570) + +pci:v00001002d0000683D* + ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] + +pci:v00001002d0000683Dsv00001002sd00000030* + ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (Radeon HD 8760 OEM) + +pci:v00001002d0000683Dsv00001019sd00000030* + ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (Radeon HD 8760 OEM) + +pci:v00001002d0000683Dsv0000103Csd00006890* + ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (Radeon HD 8760 OEM) + +pci:v00001002d0000683Dsv00001043sd00008760* + ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (Radeon HD 8760 OEM) + +pci:v00001002d0000683Dsv00001462sd00002710* + ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (R7770-PMD1GD5) + +pci:v00001002d0000683Dsv0000174Bsd00008304* + ID_MODEL_FROM_DATABASE=Cape Verde XT [Radeon HD 7770/8760 / R7 250X] (Radeon HD 8760 OEM) + +pci:v00001002d0000683F* + ID_MODEL_FROM_DATABASE=Cape Verde PRO [Radeon HD 7750/8740 / R7 250E] + +pci:v00001002d0000683Fsv00001462sd00002790* + ID_MODEL_FROM_DATABASE=Cape Verde PRO [Radeon HD 7750/8740 / R7 250E] (Radeon HD 8740) + +pci:v00001002d0000683Fsv00001462sd00002791* + ID_MODEL_FROM_DATABASE=Cape Verde PRO [Radeon HD 7750/8740 / R7 250E] (Radeon HD 8740) + +pci:v00001002d0000683Fsv00001642sd00003B97* + ID_MODEL_FROM_DATABASE=Cape Verde PRO [Radeon HD 7750/8740 / R7 250E] (Radeon HD 8740) + +pci:v00001002d00006840* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] + +pci:v00001002d00006840sv00001025sd0000050E* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001025sd0000050F* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001025sd00000513* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001025sd00000514* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001025sd0000056D* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001025sd0000059A* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001025sd0000059B* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001025sd0000059E* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001025sd00000600* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001025sd00000606* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001025sd00000696* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7650M) + +pci:v00001002d00006840sv00001025sd00000697* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7650M) + +pci:v00001002d00006840sv00001025sd00000698* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7650M) + +pci:v00001002d00006840sv00001025sd00000699* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7650M) + +pci:v00001002d00006840sv00001025sd00000757* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001028sd0000056A* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001028sd0000056E* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001028sd00000598* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001028sd0000059D* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001028sd000005A3* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001028sd000005B9* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001028sd000005BB* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd00001789* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (FirePro M2000) + +pci:v00001002d00006840sv0000103Csd000017F1* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7570M) + +pci:v00001002d00006840sv0000103Csd000017F4* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7650M) + +pci:v00001002d00006840sv0000103Csd00001813* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7590M) + +pci:v00001002d00006840sv0000103Csd0000182F* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd00001830* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd00001835* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd0000183A* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd0000183C* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd0000183E* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd00001840* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd00001842* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd00001844* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd00001848* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd0000184A* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd0000184C* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd00001895* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd00001897* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd000018A5* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd000018A7* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000103Csd000018F4* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001043sd0000100A* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001043sd0000104B* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001043sd000010DC* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001043sd00002121* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001043sd00002122* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001043sd00002123* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001043sd00002125* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001043sd00002127* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB11* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB22* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB23* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB2C* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB31* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB32* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB38* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB39* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB3A* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB40* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB41* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB47* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB48* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB51* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB52* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB53* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB81* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB82* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FB83* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FC56* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FCD4* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv00001179sd0000FCEE* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000144Dsd0000C0C5* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7690M) + +pci:v00001002d00006840sv0000144Dsd0000C0CE* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv0000144Dsd0000C0DA* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv000017AAsd00003970* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv000017AAsd0000397B* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv000017AAsd00005101* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv000017AAsd00005102* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006840sv000017AAsd00005103* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7500M/7600M Series] (Radeon HD 7670M) + +pci:v00001002d00006841* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] + +pci:v00001002d00006841sv00001028sd00000561* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv00001028sd0000056C* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv00001028sd0000057F* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7570M) + +pci:v00001002d00006841sv0000103Csd000017F1* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7570M) + +pci:v00001002d00006841sv0000103Csd000017F4* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv0000103Csd00001813* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7570M) + +pci:v00001002d00006841sv0000103Csd0000183A* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv0000103Csd0000183C* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv0000103Csd0000183E* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv0000103Csd00001840* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv0000103Csd00001842* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv0000103Csd00001844* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv00001043sd0000100A* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv00001043sd0000104B* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv00001043sd000010DC* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv00001043sd00002134* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7650M) + +pci:v00001002d00006841sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7570M) + +pci:v00001002d00006841sv00001179sd00000002* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7570M) + +pci:v00001002d00006841sv00001179sd0000FB43* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) + +pci:v00001002d00006841sv00001179sd0000FB91* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) + +pci:v00001002d00006841sv00001179sd0000FB92* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) + +pci:v00001002d00006841sv00001179sd0000FB93* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) + +pci:v00001002d00006841sv00001179sd0000FBA2* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) + +pci:v00001002d00006841sv00001179sd0000FBA3* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) + +pci:v00001002d00006841sv0000144Dsd0000C0C7* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7550M/7570M/7650M] (Radeon HD 7550M) + +pci:v00001002d00006842* + ID_MODEL_FROM_DATABASE=Thames LE [Radeon HD 7000M Series] + +pci:v00001002d00006843* + ID_MODEL_FROM_DATABASE=Thames [Radeon HD 7670M] + +pci:v00001002d00006860* + ID_MODEL_FROM_DATABASE=Vega 10 [Radeon Instinct MI25] + +pci:v00001002d00006860sv00001002sd00000C35* + ID_MODEL_FROM_DATABASE=Vega 10 [Radeon Instinct MI25] (Radeon PRO V320) + +pci:v00001002d00006860sv00001002sd00006C75* + ID_MODEL_FROM_DATABASE=Vega 10 [Radeon Instinct MI25] (Radeon PRO V320) + +pci:v00001002d00006860sv0000106Bsd0000017C* + ID_MODEL_FROM_DATABASE=Vega 10 [Radeon Instinct MI25] (Radeon Pro Vega 64) + +pci:v00001002d00006861* + ID_MODEL_FROM_DATABASE=Vega 10 XT [Radeon PRO WX 9100] + +pci:v00001002d00006862* + ID_MODEL_FROM_DATABASE=Vega 10 XT [Radeon PRO SSG] + +pci:v00001002d00006863* + ID_MODEL_FROM_DATABASE=Vega 10 XTX [Radeon Vega Frontier Edition] + +pci:v00001002d00006864* + ID_MODEL_FROM_DATABASE=Vega + +pci:v00001002d00006867* + ID_MODEL_FROM_DATABASE=Vega 10 XL [Radeon Pro Vega 56] + +pci:v00001002d00006868* + ID_MODEL_FROM_DATABASE=Vega 10 [Radeon PRO WX 8100/8200] + +pci:v00001002d0000686C* + ID_MODEL_FROM_DATABASE=Vega 10 [Radeon Instinct MI25 MxGPU] + +pci:v00001002d0000687F* + ID_MODEL_FROM_DATABASE=Vega 10 XL/XT [Radeon RX Vega 56/64] + +pci:v00001002d0000687Fsv00001002sd00000B36* + ID_MODEL_FROM_DATABASE=Vega 10 XL/XT [Radeon RX Vega 56/64] (RX Vega64) + +pci:v00001002d0000687Fsv00001002sd00006B76* + ID_MODEL_FROM_DATABASE=Vega 10 XL/XT [Radeon RX Vega 56/64] (RX Vega56) + +pci:v00001002d00006880* + ID_MODEL_FROM_DATABASE=Lexington [Radeon HD 6550M] + +pci:v00001002d00006880sv0000103Csd0000163C* + ID_MODEL_FROM_DATABASE=Lexington [Radeon HD 6550M] (Pavilion dv6 Radeon HD 6550M) + +pci:v00001002d00006888* + ID_MODEL_FROM_DATABASE=Cypress XT [FirePro V8800] + +pci:v00001002d00006889* + ID_MODEL_FROM_DATABASE=Cypress PRO [FirePro V7800] + +pci:v00001002d00006889sv00001002sd00000301* + ID_MODEL_FROM_DATABASE=Cypress PRO [FirePro V7800] (FirePro V7800P) + +pci:v00001002d00006889sv000013CCsd00003D1F* + ID_MODEL_FROM_DATABASE=Cypress PRO [FirePro V7800] (MXRT-7400) + +pci:v00001002d0000688A* + ID_MODEL_FROM_DATABASE=Cypress XT [FirePro V9800] + +pci:v00001002d0000688Asv00001002sd0000030C* + ID_MODEL_FROM_DATABASE=Cypress XT [FirePro V9800] (FirePro V9800P) + +pci:v00001002d0000688C* + ID_MODEL_FROM_DATABASE=Cypress XT GL [FireStream 9370] + +pci:v00001002d0000688D* + ID_MODEL_FROM_DATABASE=Cypress PRO GL [FireStream 9350] + +pci:v00001002d00006898* + ID_MODEL_FROM_DATABASE=Cypress XT [Radeon HD 5870] + +pci:v00001002d00006898sv00001002sd00000B00* + ID_MODEL_FROM_DATABASE=Cypress XT [Radeon HD 5870] (Radeon HD 5870 Eyefinity⁶ Edition) + +pci:v00001002d00006898sv0000106Bsd000000D0* + ID_MODEL_FROM_DATABASE=Cypress XT [Radeon HD 5870] (Radeon HD 5870 Mac Edition) + +pci:v00001002d00006898sv00001462sd00008032* + ID_MODEL_FROM_DATABASE=Cypress XT [Radeon HD 5870] (Radeon HD 5870 1 GB GDDR5) + +pci:v00001002d00006898sv0000174Bsd00006870* + ID_MODEL_FROM_DATABASE=Cypress XT [Radeon HD 5870] (Radeon HD 6870 1600SP Edition) + +pci:v00001002d00006899* + ID_MODEL_FROM_DATABASE=Cypress PRO [Radeon HD 5850] + +pci:v00001002d00006899sv00001043sd00000330* + ID_MODEL_FROM_DATABASE=Cypress PRO [Radeon HD 5850] (Radeon HD 5850) + +pci:v00001002d00006899sv0000174Bsd0000237B* + ID_MODEL_FROM_DATABASE=Cypress PRO [Radeon HD 5850] (Radeon HD 5850 X2) + +pci:v00001002d00006899sv0000174Bsd00006850* + ID_MODEL_FROM_DATABASE=Cypress PRO [Radeon HD 5850] (Radeon HD 6850 1440SP Edition) + +pci:v00001002d0000689B* + ID_MODEL_FROM_DATABASE=Cypress PRO [Radeon HD 6800 Series] + +pci:v00001002d0000689C* + ID_MODEL_FROM_DATABASE=Hemlock [Radeon HD 5970] + +pci:v00001002d0000689Csv00001043sd00000352* + ID_MODEL_FROM_DATABASE=Hemlock [Radeon HD 5970] (ARES) + +pci:v00001002d0000689D* + ID_MODEL_FROM_DATABASE=Hemlock [Radeon HD 5970] + +pci:v00001002d0000689E* + ID_MODEL_FROM_DATABASE=Cypress LE [Radeon HD 5830] + +pci:v00001002d000068A0* + ID_MODEL_FROM_DATABASE=Broadway XT [Mobility Radeon HD 5870] + +pci:v00001002d000068A0sv00001028sd000012EF* + ID_MODEL_FROM_DATABASE=Broadway XT [Mobility Radeon HD 5870] (FirePro M7820) + +pci:v00001002d000068A0sv0000103Csd00001520* + ID_MODEL_FROM_DATABASE=Broadway XT [Mobility Radeon HD 5870] (FirePro M7820) + +pci:v00001002d000068A1* + ID_MODEL_FROM_DATABASE=Broadway PRO [Mobility Radeon HD 5850] + +pci:v00001002d000068A1sv0000106Bsd000000CC* + ID_MODEL_FROM_DATABASE=Broadway PRO [Mobility Radeon HD 5850] (iMac MC511 Mobility Radeon HD 5850 MXM Module) + +pci:v00001002d000068A8* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] + +pci:v00001002d000068A8sv00001025sd00000442* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd00000451* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd0000050A* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd0000050B* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd0000050C* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd0000050E* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd0000050F* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd00000513* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd00000514* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd00000515* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd00000516* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd00000525* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd00000526* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001025sd0000056D* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv00001028sd0000048F* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6870M) + +pci:v00001002d000068A8sv00001028sd00000490* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6870M) + +pci:v00001002d000068A8sv00001028sd000004B9* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6870M) + +pci:v00001002d000068A8sv00001028sd000004BA* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6870M) + +pci:v00001002d000068A8sv0000103Csd0000159B* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A8sv0000144Dsd0000C0AD* + ID_MODEL_FROM_DATABASE=Granville [Radeon HD 6850M/6870M] (Radeon HD 6850M) + +pci:v00001002d000068A9* + ID_MODEL_FROM_DATABASE=Juniper XT [FirePro V5800] + +pci:v00001002d000068A9sv000013CCsd00003D1E* + ID_MODEL_FROM_DATABASE=Juniper XT [FirePro V5800] (MXRT-5400) + +pci:v00001002d000068A9sv000013CCsd00003D20* + ID_MODEL_FROM_DATABASE=Juniper XT [FirePro V5800] (MXRT-5450) + +pci:v00001002d000068B8* + ID_MODEL_FROM_DATABASE=Juniper XT [Radeon HD 5770] + +pci:v00001002d000068B8sv0000106Bsd000000CF* + ID_MODEL_FROM_DATABASE=Juniper XT [Radeon HD 5770] (MacPro5,1 [Mac Pro 2.8GHz DDR3]) + +pci:v00001002d000068B9* + ID_MODEL_FROM_DATABASE=Juniper LE [Radeon HD 5670 640SP Edition] + +pci:v00001002d000068BA* + ID_MODEL_FROM_DATABASE=Juniper XT [Radeon HD 6770] + +pci:v00001002d000068BE* + ID_MODEL_FROM_DATABASE=Juniper PRO [Radeon HD 5750] + +pci:v00001002d000068BEsv0000148Csd00003000* + ID_MODEL_FROM_DATABASE=Juniper PRO [Radeon HD 5750] (Radeon HD 6750) + +pci:v00001002d000068BF* + ID_MODEL_FROM_DATABASE=Juniper PRO [Radeon HD 6750] + +pci:v00001002d000068BFsv0000174Bsd00006750* + ID_MODEL_FROM_DATABASE=Juniper PRO [Radeon HD 6750] (Radeon HD 6750) + +pci:v00001002d000068C0* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] + +pci:v00001002d000068C0sv00001019sd00002383* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) + +pci:v00001002d000068C0sv00001028sd000002A2* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) + +pci:v00001002d000068C0sv00001028sd000002FE* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) + +pci:v00001002d000068C0sv00001028sd00000419* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) + +pci:v00001002d000068C0sv0000103Csd0000147D* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) + +pci:v00001002d000068C0sv0000103Csd00001521* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Madison XT [FirePro M5800]) + +pci:v00001002d000068C0sv0000103Csd00001593* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 6570) + +pci:v00001002d000068C0sv0000103Csd00001596* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 6570) + +pci:v00001002d000068C0sv0000103Csd00001599* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 6570) + +pci:v00001002d000068C0sv00001043sd00001C22* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) + +pci:v00001002d000068C0sv000017AAsd00003927* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) + +pci:v00001002d000068C0sv000017AAsd00003952* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Mobility Radeon HD 5730) + +pci:v00001002d000068C0sv000017AAsd00003978* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5730 / 6570M] (Radeon HD 6570M) + +pci:v00001002d000068C1* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] + +pci:v00001002d000068C1sv00001025sd00000205* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000293* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000294* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000296* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000308* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000030A* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000311* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000312* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000031C* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000031D* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000033D* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000033E* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000033F* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000346* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000347* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Aspire 7740G) + +pci:v00001002d000068C1sv00001025sd00000348* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000356* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000357* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000358* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000359* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000035A* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000035B* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000035C* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000035D* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000035E* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000360* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000362* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000364* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000365* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000366* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000367* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000368* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000036C* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000036D* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000036E* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000036F* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000372* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000373* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000377* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000378* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000379* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000037A* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000037B* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000037E* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000037F* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000382* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000383* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000384* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000385* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000386* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000387* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000388* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000038B* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000038C* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000039A* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000411* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000412* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000418* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000419* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000420* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000421* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000425* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000042A* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000042E* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000042F* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000432* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000433* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000442* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000044C* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd0000044E* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000451* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000454* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000455* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000475* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000476* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000487* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000489* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000498* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001025sd00000517* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd0000051A* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd0000051B* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd0000051C* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd0000051D* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd00000525* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd00000526* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd0000052B* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd0000052C* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd0000053C* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd0000053D* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd0000053E* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd0000053F* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001025sd00000607* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C1sv00001028sd0000041B* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001028sd00000447* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001028sd00000448* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001028sd00000456* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001028sd00000457* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd00001436* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd00001437* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd00001440* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd00001448* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd00001449* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd0000144A* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd0000144B* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd0000147B* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd0000149C* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd0000149E* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000103Csd00001521* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Madison Pro [FirePro M5800]) + +pci:v00001002d000068C1sv00001043sd00001BC2* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000104Dsd00009071* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000104Dsd00009077* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000104Dsd00009081* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001179sd0000FD00* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001179sd0000FD12* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001179sd0000FD1A* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001179sd0000FD30* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001179sd0000FD31* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001179sd0000FD50* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001179sd0000FD52* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6530M) + +pci:v00001002d000068C1sv00001179sd0000FD63* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6530M) + +pci:v00001002d000068C1sv00001179sd0000FD65* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6530M) + +pci:v00001002d000068C1sv00001179sd0000FDD0* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv00001179sd0000FDD2* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6530M) + +pci:v00001002d000068C1sv0000144Dsd0000C07E* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv0000144Dsd0000C085* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv000014C0sd00000043* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv000014C0sd0000004D* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv000017AAsd00003928* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv000017AAsd00003951* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Mobility Radeon HD 5650) + +pci:v00001002d000068C1sv000017AAsd00003977* + ID_MODEL_FROM_DATABASE=Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] (Radeon HD 6550M) + +pci:v00001002d000068C7* + ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] + +pci:v00001002d000068C7sv00001462sd00002241* + ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570) + +pci:v00001002d000068C7sv00001462sd00002243* + ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570) + +pci:v00001002d000068C7sv00001462sd00002244* + ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] (Mobility Radeon HD 5570) + +pci:v00001002d000068C7sv00001462sd00002245* + ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] (Radeon HD 6550A) + +pci:v00001002d000068C7sv00001462sd00002246* + ID_MODEL_FROM_DATABASE=Pinewood [Mobility Radeon HD 5570/6550A] (Radeon HD 6550A) + +pci:v00001002d000068C8* + ID_MODEL_FROM_DATABASE=Redwood XT GL [FirePro V4800] + +pci:v00001002d000068C9* + ID_MODEL_FROM_DATABASE=Redwood PRO GL [FirePro V3800] + +pci:v00001002d000068C9sv000013CCsd00003D1D* + ID_MODEL_FROM_DATABASE=Redwood PRO GL [FirePro V3800] (MXRT-2400) + +pci:v00001002d000068D8* + ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] + +pci:v00001002d000068D8sv00001028sd000068E0* + ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5670) + +pci:v00001002d000068D8sv0000174Bsd00005690* + ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5690) + +pci:v00001002d000068D8sv0000174Bsd00005730* + ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5730) + +pci:v00001002d000068D8sv0000174Bsd0000E151* + ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5670) + +pci:v00001002d000068D8sv00001787sd00003000* + ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5730) + +pci:v00001002d000068D8sv000017AFsd00003010* + ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5730) + +pci:v00001002d000068D8sv000017AFsd00003011* + ID_MODEL_FROM_DATABASE=Redwood XT [Radeon HD 5670/5690/5730] (Radeon HD 5690) + +pci:v00001002d000068D9* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] + +pci:v00001002d000068D9sv0000103Csd00006870* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) + +pci:v00001002d000068D9sv0000103Csd00006872* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) + +pci:v00001002d000068D9sv00001043sd000003CE* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5550) + +pci:v00001002d000068D9sv00001462sd00002151* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) + +pci:v00001002d000068D9sv00001462sd00002240* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) + +pci:v00001002d000068D9sv0000148Csd00003000* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6510) + +pci:v00001002d000068D9sv0000148Csd00003001* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6610) + +pci:v00001002d000068D9sv00001545sd00005550* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5550) + +pci:v00001002d000068D9sv00001545sd00007570* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 7570) + +pci:v00001002d000068D9sv00001642sd00003985* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) + +pci:v00001002d000068D9sv00001642sd00003996* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) + +pci:v00001002d000068D9sv0000174Bsd00003000* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6510) + +pci:v00001002d000068D9sv0000174Bsd00006510* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6510) + +pci:v00001002d000068D9sv0000174Bsd00006610* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6610) + +pci:v00001002d000068D9sv0000174Bsd0000E142* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5570) + +pci:v00001002d000068D9sv00001787sd00003000* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6510) + +pci:v00001002d000068D9sv000017AFsd00003000* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 6510) + +pci:v00001002d000068D9sv000017AFsd00003010* + ID_MODEL_FROM_DATABASE=Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] (Radeon HD 5630) + +pci:v00001002d000068DA* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] + +pci:v00001002d000068DAsv0000148Csd00003000* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6390) + +pci:v00001002d000068DAsv0000148Csd00003001* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6490) + +pci:v00001002d000068DAsv00001545sd00007570* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 7570) + +pci:v00001002d000068DAsv0000174Bsd00003000* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6390) + +pci:v00001002d000068DAsv0000174Bsd00005570* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 5570) + +pci:v00001002d000068DAsv0000174Bsd00005630* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 5630) + +pci:v00001002d000068DAsv0000174Bsd00006490* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6490) + +pci:v00001002d000068DAsv00001787sd00003000* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 5630) + +pci:v00001002d000068DAsv000017AFsd00003000* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 6390) + +pci:v00001002d000068DAsv000017AFsd00003010* + ID_MODEL_FROM_DATABASE=Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] (Radeon HD 5630) + +pci:v00001002d000068DE* + ID_MODEL_FROM_DATABASE=Redwood + +pci:v00001002d000068E0* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] + +pci:v00001002d000068E0sv00001028sd00000404* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv00001028sd00000414* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv00001028sd00000434* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv0000103Csd00001433* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv0000103Csd00001434* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv0000103Csd00001469* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv0000103Csd0000146B* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv0000103Csd00001486* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (TouchSmart tm2-2050er discrete GPU (Mobility Radeon HD 5450)) + +pci:v00001002d000068E0sv0000103Csd00001622* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv0000103Csd00001623* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv0000103Csd0000EEEE* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv0000104Dsd00009076* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Mobility Radeon HD 5450) + +pci:v00001002d000068E0sv00001682sd0000304E* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E0sv00001682sd00006000* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E0sv000017AAsd00009E52* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (FirePro M3800) + +pci:v00001002d000068E0sv000017AAsd00009E53* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430/5450/5470] (FirePro M3800) + +pci:v00001002d000068E1* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] + +pci:v00001002d000068E1sv00001043sd0000041F* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) + +pci:v00001002d000068E1sv00001043sd00003000* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E1sv0000148Csd00003000* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E1sv0000148Csd00003001* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6230]) + +pci:v00001002d000068E1sv0000148Csd00003002* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6250]) + +pci:v00001002d000068E1sv0000148Csd00003003* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6350]) + +pci:v00001002d000068E1sv0000148Csd00007350* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) + +pci:v00001002d000068E1sv0000148Csd00008350* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 8350]) + +pci:v00001002d000068E1sv00001545sd00005450* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E1sv00001545sd00007350* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) + +pci:v00001002d000068E1sv00001682sd00003000* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E1sv00001682sd00006000* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E1sv00001682sd00007350* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) + +pci:v00001002d000068E1sv0000174Bsd00003000* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E1sv0000174Bsd00005470* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5470]) + +pci:v00001002d000068E1sv0000174Bsd00006000* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E1sv0000174Bsd00006230* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6230]) + +pci:v00001002d000068E1sv0000174Bsd00006350* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6350]) + +pci:v00001002d000068E1sv0000174Bsd00007350* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) + +pci:v00001002d000068E1sv00001787sd00003000* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E1sv000017AFsd00003000* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 5450]) + +pci:v00001002d000068E1sv000017AFsd00003001* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6230]) + +pci:v00001002d000068E1sv000017AFsd00003014* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 6350]) + +pci:v00001002d000068E1sv000017AFsd00003015* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 7350]) + +pci:v00001002d000068E1sv000017AFsd00008350* + ID_MODEL_FROM_DATABASE=Park [Mobility Radeon HD 5430] (Caicos [Radeon HD 8350 OEM]) + +pci:v00001002d000068E4* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] + +pci:v00001002d000068E4sv00001019sd00002386* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6350M) + +pci:v00001002d000068E4sv00001019sd00002387* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6350M) + +pci:v00001002d000068E4sv00001019sd0000238D* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001019sd0000238E* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001025sd00000382* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001025sd00000489* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001025sd0000048A* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001025sd0000048B* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001025sd0000048C* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001028sd000004C1* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001028sd000004CA* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001028sd000004CC* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001028sd000004CD* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001028sd000004D7* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00001411* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00001421* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00001426* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00001428* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000142A* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000142B* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000143A* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000143C* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00001445* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000162C* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000162D* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000162E* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000162F* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00001639* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000163A* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000163B* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000163C* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000163D* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000163E* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000163F* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00001641* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00001643* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00003578* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd0000357A* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00003673* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000103Csd00003675* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001043sd00001C92* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001043sd000084A1* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001043sd000084AD* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000104Dsd00009081* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001545sd00007350* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Cedar [Radeon HD 7350]) + +pci:v00001002d000068E4sv00001558sd00004510* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv00001558sd00005505* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv0000174Bsd00005450* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Cedar [Radeon HD 5450]) + +pci:v00001002d000068E4sv000017AAsd000021DD* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv000017AAsd000021E9* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv000017AAsd00003971* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M) + +pci:v00001002d000068E4sv000017AAsd00003972* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 7370M) + +pci:v00001002d000068E4sv000017AAsd0000397A* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M/7370M) + +pci:v00001002d000068E4sv000017AAsd0000397B* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 6370M/7370M) + +pci:v00001002d000068E4sv000017AAsd0000397F* + ID_MODEL_FROM_DATABASE=Robson CE [Radeon HD 6370M/7370M] (Radeon HD 7370M) + +pci:v00001002d000068E5* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] + +pci:v00001002d000068E5sv00001179sd0000FD3C* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv00001179sd0000FD50* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv00001179sd0000FD52* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv00001179sd0000FD63* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv00001179sd0000FD65* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv00001179sd0000FD73* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv00001179sd0000FD75* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv00001179sd0000FDD0* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv00001179sd0000FDD2* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv00001179sd0000FDEA* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv00001179sd0000FDF8* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Radeon HD 6330M) + +pci:v00001002d000068E5sv0000148Csd00005450* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Cedar [Radeon HD 5450]) + +pci:v00001002d000068E5sv0000148Csd00006350* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Cedar [Radeon HD 6350]) + +pci:v00001002d000068E5sv0000148Csd00007350* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Cedar [Radeon HD 7350]) + +pci:v00001002d000068E5sv0000148Csd00008350* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Cedar [Radeon HD 8350]) + +pci:v00001002d000068E5sv00001545sd00007350* + ID_MODEL_FROM_DATABASE=Robson LE [Radeon HD 6330M] (Cedar [Radeon HD 7350]) + +pci:v00001002d000068E8* + ID_MODEL_FROM_DATABASE=Cedar + +pci:v00001002d000068E9* + ID_MODEL_FROM_DATABASE=Cedar [ATI FirePro (FireGL) Graphics Adapter] + +pci:v00001002d000068F1* + ID_MODEL_FROM_DATABASE=Cedar GL [FirePro 2460] + +pci:v00001002d000068F2* + ID_MODEL_FROM_DATABASE=Cedar GL [FirePro 2270] + +pci:v00001002d000068F8* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7300 Series] + +pci:v00001002d000068F9* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] + +pci:v00001002d000068F9sv00001019sd00000001* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001019sd00000002* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001019sd00000019* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv00001025sd00000518* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001025sd00000519* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001028sd0000010E* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (XPS 8300) + +pci:v00001002d000068F9sv00001028sd00002126* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv0000103Csd00002126* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv0000103Csd00002AAC* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv0000103Csd00002AAE* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv0000103Csd00003580* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001043sd00000386* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001043sd000003C2* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (EAH5450 SILENT/DI/512MD2 (LP)) + +pci:v00001002d000068F9sv00001462sd00002130* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001462sd00002131* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001462sd00002133* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv00001462sd00002180* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001462sd00002181* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001462sd00002182* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv00001462sd00002183* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv00001462sd00002230* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001462sd00002231* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001462sd00002495* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv0000148Csd00003001* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5530/6250) + +pci:v00001002d000068F9sv0000148Csd00003002* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6290) + +pci:v00001002d000068F9sv0000148Csd00003003* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6230) + +pci:v00001002d000068F9sv0000148Csd00003004* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv0000148Csd00007350* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 7350) + +pci:v00001002d000068F9sv0000148Csd00008350* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 8350) + +pci:v00001002d000068F9sv00001545sd00007350* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 7350) + +pci:v00001002d000068F9sv00001642sd00003983* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001642sd00003984* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv00001642sd00003987* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv00001642sd00003997* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001642sd00003A05* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001642sd00003B31* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350A) + +pci:v00001002d000068F9sv00001682sd00003270* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 7350) + +pci:v00001002d000068F9sv0000174Bsd00003000* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6230) + +pci:v00001002d000068F9sv0000174Bsd00003987* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv0000174Bsd00005470* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5470) + +pci:v00001002d000068F9sv0000174Bsd00005490* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5490) + +pci:v00001002d000068F9sv0000174Bsd00005530* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5530) + +pci:v00001002d000068F9sv0000174Bsd00006230* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6230) + +pci:v00001002d000068F9sv0000174Bsd00006250* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6250) + +pci:v00001002d000068F9sv0000174Bsd00006290* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6290) + +pci:v00001002d000068F9sv0000174Bsd00006350* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068F9sv0000174Bsd00007350* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 7350) + +pci:v00001002d000068F9sv0000174Bsd00008350* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 8350) + +pci:v00001002d000068F9sv0000174Bsd0000E127* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv0000174Bsd0000E145* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv0000174Bsd0000E153* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv00001787sd00003000* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5470) + +pci:v00001002d000068F9sv00001787sd00003001* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5530) + +pci:v00001002d000068F9sv00001787sd00003002* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5490) + +pci:v00001002d000068F9sv000017AAsd00003602* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv000017AAsd00003603* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv000017AAsd0000360F* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv000017AAsd00003619* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5450) + +pci:v00001002d000068F9sv000017AFsd00003000* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6250) + +pci:v00001002d000068F9sv000017AFsd00003001* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6230) + +pci:v00001002d000068F9sv000017AFsd00003002* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6290) + +pci:v00001002d000068F9sv000017AFsd00003011* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5470) + +pci:v00001002d000068F9sv000017AFsd00003012* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5490) + +pci:v00001002d000068F9sv000017AFsd00003013* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 5470) + +pci:v00001002d000068F9sv000017AFsd00003014* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 5000/6000/7350/8350 Series] (Radeon HD 6350) + +pci:v00001002d000068FA* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] + +pci:v00001002d000068FAsv00001019sd00000019* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv00001019sd00000021* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv00001019sd00000022* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv00001019sd00000026* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 8350) + +pci:v00001002d000068FAsv0000103Csd00002ADF* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350A) + +pci:v00001002d000068FAsv0000103Csd00002AE8* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350A) + +pci:v00001002d000068FAsv00001043sd00008350* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 8350) + +pci:v00001002d000068FAsv00001462sd00002128* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv00001462sd00002184* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv00001462sd00002186* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv00001462sd00002495* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv00001462sd0000B490* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv00001642sd00003985* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv0000174Bsd00003510* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 8350) + +pci:v00001002d000068FAsv0000174Bsd00003521* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon R5 220) + +pci:v00001002d000068FAsv0000174Bsd00003522* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon R5 220) + +pci:v00001002d000068FAsv0000174Bsd00007350* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv0000174Bsd00008153* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 8350) + +pci:v00001002d000068FAsv0000174Bsd0000E127* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv0000174Bsd0000E153* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv0000174Bsd0000E180* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FAsv000017AFsd00003015* + ID_MODEL_FROM_DATABASE=Cedar [Radeon HD 7350/8350 / R5 220] (Radeon HD 7350) + +pci:v00001002d000068FE* + ID_MODEL_FROM_DATABASE=Cedar LE + +pci:v00001002d00006900* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] + +pci:v00001002d00006900sv00001025sd00001056* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M360 / R8 M365DX) + +pci:v00001002d00006900sv00001028sd00000640* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260/M265) + +pci:v00001002d00006900sv00001028sd00000643* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260/M265) + +pci:v00001002d00006900sv00001028sd0000067F* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv00001028sd00000767* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M445) + +pci:v00001002d00006900sv00001028sd00000810* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon 530) + +pci:v00001002d00006900sv00001028sd0000130A* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv0000103Csd00002263* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv0000103Csd00002269* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv0000103Csd000022C6* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv0000103Csd000022C8* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv0000103Csd00002B45* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 A360) + +pci:v00001002d00006900sv0000103Csd0000808C* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv0000103Csd00008099* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M360) + +pci:v00001002d00006900sv0000103Csd000080B5* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M360) + +pci:v00001002d00006900sv0000103Csd000080B9* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M360) + +pci:v00001002d00006900sv0000103Csd0000811C* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M340) + +pci:v00001002d00006900sv0000103Csd00008226* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M440) + +pci:v00001002d00006900sv000010CFsd00001906* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv00001170sd00009979* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M360) + +pci:v00001002d00006900sv00001179sd0000F903* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv00001179sd0000F922* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv00001179sd0000F923* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv00001179sd0000F934* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006900sv000017AAsd00003822* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M360) + +pci:v00001002d00006900sv000017AAsd00003824* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M360) + +pci:v00001002d00006900sv000017AAsd00005021* + ID_MODEL_FROM_DATABASE=Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] (Radeon R7 M260) + +pci:v00001002d00006901* + ID_MODEL_FROM_DATABASE=Topaz PRO [Radeon R5 M255] + +pci:v00001002d00006901sv0000103Csd00001318* + ID_MODEL_FROM_DATABASE=Topaz PRO [Radeon R5 M255] (Radeon R6 M255DX) + +pci:v00001002d00006907* + ID_MODEL_FROM_DATABASE=Meso XT [Radeon R5 M315] + +pci:v00001002d00006921* + ID_MODEL_FROM_DATABASE=Amethyst XT [Radeon R9 M295X] + +pci:v00001002d00006929* + ID_MODEL_FROM_DATABASE=Tonga XT GL [FirePro S7150] + +pci:v00001002d0000692B* + ID_MODEL_FROM_DATABASE=Tonga PRO GL [FirePro W7100] + +pci:v00001002d0000692Bsv000013CCsd00003D2B* + ID_MODEL_FROM_DATABASE=Tonga PRO GL [FirePro W7100] (MXRT-7600) + +pci:v00001002d0000692F* + ID_MODEL_FROM_DATABASE=Tonga XTV GL [FirePro S7150V] + +pci:v00001002d00006938* + ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X] + +pci:v00001002d00006938sv00001043sd000004F5* + ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X] (Radeon R9 380X) + +pci:v00001002d00006938sv00001043sd000004F7* + ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X] (Radeon R9 380X) + +pci:v00001002d00006938sv0000106Bsd0000013A* + ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X] (Radeon R9 M295X Mac Edition) + +pci:v00001002d00006938sv00001458sd000022C8* + ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X] (Radeon R9 380X) + +pci:v00001002d00006938sv0000148Csd00002350* + ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X] (Radeon R9 380X) + +pci:v00001002d00006938sv00001682sd00009385* + ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X] (Radeon R9 380X) + +pci:v00001002d00006938sv0000174Bsd0000E308* + ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X] (Radeon R9 380X Nitro 4G D5) + +pci:v00001002d00006938sv000017AFsd00002006* + ID_MODEL_FROM_DATABASE=Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X] (Radeon R9 380X) + +pci:v00001002d00006939* + ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380] + +pci:v00001002d00006939sv0000148Csd00009380* + ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380] (Radeon R9 380) + +pci:v00001002d00006939sv0000174Bsd0000E308* + ID_MODEL_FROM_DATABASE=Tonga PRO [Radeon R9 285/380] (Radeon R9 380 Nitro 4G D5) + +pci:v00001002d0000694C* + ID_MODEL_FROM_DATABASE=Polaris 22 XT [Radeon RX Vega M GH] + +pci:v00001002d0000694E* + ID_MODEL_FROM_DATABASE=Polaris 22 XL [Radeon RX Vega M GL] + +pci:v00001002d0000694F* + ID_MODEL_FROM_DATABASE=Polaris 22 MGL XL [Radeon Pro WX Vega M GL] + +pci:v00001002d00006980* + ID_MODEL_FROM_DATABASE=Polaris12 + +pci:v00001002d00006981* + ID_MODEL_FROM_DATABASE=Lexa XT [Radeon PRO WX 3200] + +pci:v00001002d00006985* + ID_MODEL_FROM_DATABASE=Lexa XT [Radeon PRO WX 3100] + +pci:v00001002d00006986* + ID_MODEL_FROM_DATABASE=Polaris12 + +pci:v00001002d00006987* + ID_MODEL_FROM_DATABASE=Lexa [Radeon 540X/550X/630 / RX 640 / E9171 MCM] + +pci:v00001002d00006995* + ID_MODEL_FROM_DATABASE=Lexa XT [Radeon PRO WX 2100] + +pci:v00001002d0000699F* + ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon 540/540X/550/550X / RX 540X/550/550X] + +pci:v00001002d0000699Fsv00001028sd00001720* + ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon 540/540X/550/550X / RX 540X/550/550X] (Radeon RX 550X) + +pci:v00001002d0000699Fsv0000148Csd00002380* + ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon 540/540X/550/550X / RX 540X/550/550X] (Lexa XL [Radeon RX 550]) + +pci:v00001002d0000699Fsv00001DA2sd0000E367* + ID_MODEL_FROM_DATABASE=Lexa PRO [Radeon 540/540X/550/550X / RX 540X/550/550X] (Lexa PRO [Radeon RX 550]) + +pci:v00001002d000069A0* + ID_MODEL_FROM_DATABASE=Vega 12 + +pci:v00001002d000069A1* + ID_MODEL_FROM_DATABASE=Vega 12 + +pci:v00001002d000069A2* + ID_MODEL_FROM_DATABASE=Vega 12 + +pci:v00001002d000069A3* + ID_MODEL_FROM_DATABASE=Vega 12 + +pci:v00001002d000069AF* + ID_MODEL_FROM_DATABASE=Vega 12 [Radeon Pro Vega 20] + +pci:v00001002d00006FDF* + ID_MODEL_FROM_DATABASE=Polaris 20 XL [Radeon RX 580 2048SP] + +pci:v00001002d0000700F* + ID_MODEL_FROM_DATABASE=RS100 AGP Bridge + +pci:v00001002d00007010* + ID_MODEL_FROM_DATABASE=RS200/RS250 AGP Bridge + +pci:v00001002d00007100* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 XT] + +pci:v00001002d00007101* + ID_MODEL_FROM_DATABASE=R520/M58 [Mobility Radeon X1800 XT] + +pci:v00001002d00007102* + ID_MODEL_FROM_DATABASE=R520/M58 [Mobility Radeon X1800] + +pci:v00001002d00007104* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7200] + +pci:v00001002d00007104sv000013CCsd00003D0A* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7200] (MXRT-5100) + +pci:v00001002d00007109* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 XL] + +pci:v00001002d00007109sv00001002sd00000322* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 XL] (All-in-Wonder X1800XL) + +pci:v00001002d00007109sv00001002sd00000D02* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 XL] (Radeon X1800 CrossFire Edition) + +pci:v00001002d0000710A* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 GTO] + +pci:v00001002d0000710Asv00001002sd00000B12* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 GTO] (Radeon X1800 GTO²) + +pci:v00001002d0000710B* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800 GTO] + +pci:v00001002d0000710E* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7300] + +pci:v00001002d0000710Esv000013CCsd00003D0C* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7300] (MXRT-5150) + +pci:v00001002d0000710F* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7350] + +pci:v00001002d0000710Fsv000013CCsd00003D0E* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7350] (MXRT-7100) + +pci:v00001002d00007120* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800] (Secondary) + +pci:v00001002d00007124* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7200] (Secondary) + +pci:v00001002d00007124sv000013CCsd00003D0B* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7200] (Secondary) (MXRT-5100 (Secondary)) + +pci:v00001002d00007129* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800] (Secondary) + +pci:v00001002d00007129sv00001002sd00000323* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800] (Secondary) (All-In-Wonder X1800 XL (Secondary)) + +pci:v00001002d00007129sv00001002sd00000D03* + ID_MODEL_FROM_DATABASE=R520 [Radeon X1800] (Secondary) (Radeon X1800 CrossFire Edition (Secondary)) + +pci:v00001002d0000712E* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7300] (Secondary) + +pci:v00001002d0000712Esv000013CCsd00003D0D* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7300] (Secondary) (MXRT-5150 (Secondary)) + +pci:v00001002d0000712F* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7350] (Secondary) + +pci:v00001002d0000712Fsv000013CCsd00003D0F* + ID_MODEL_FROM_DATABASE=R520 GL [FireGL V7350] (Secondary) (MXRT-7100 (Secondary)) + +pci:v00001002d00007140* + ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550/X1600 Series] + +pci:v00001002d00007142* + ID_MODEL_FROM_DATABASE=RV515 PRO [Radeon X1300/X1550 Series] + +pci:v00001002d00007142sv00001002sd00000322* + ID_MODEL_FROM_DATABASE=RV515 PRO [Radeon X1300/X1550 Series] (All-in-Wonder 2006 PCI-E Edition) + +pci:v00001002d00007142sv00001043sd00000142* + ID_MODEL_FROM_DATABASE=RV515 PRO [Radeon X1300/X1550 Series] (EAX1300PRO/TD/256M) + +pci:v00001002d00007143* + ID_MODEL_FROM_DATABASE=RV505 [Radeon X1300/X1550 Series] + +pci:v00001002d00007145* + ID_MODEL_FROM_DATABASE=RV515/M54 [Mobility Radeon X1400] + +pci:v00001002d00007145sv000017AAsd00002006* + ID_MODEL_FROM_DATABASE=RV515/M54 [Mobility Radeon X1400] (Thinkpad T60 model 2007) + +pci:v00001002d00007146* + ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550] + +pci:v00001002d00007146sv00001002sd00000322* + ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550] (All-in-Wonder 2006 PCI-E Edition) + +pci:v00001002d00007146sv00001545sd00001996* + ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550] (Radeon X1300 512MB PCI-e) + +pci:v00001002d00007147* + ID_MODEL_FROM_DATABASE=RV505 [Radeon X1550 64-bit] + +pci:v00001002d00007149* + ID_MODEL_FROM_DATABASE=RV515/M52 [Mobility Radeon X1300] + +pci:v00001002d0000714A* + ID_MODEL_FROM_DATABASE=RV515/M52 [Mobility Radeon X1300] + +pci:v00001002d00007152* + ID_MODEL_FROM_DATABASE=RV515 GL [FireGL V3300] + +pci:v00001002d00007153* + ID_MODEL_FROM_DATABASE=RV515 GL [FireGL V3350] + +pci:v00001002d0000715F* + ID_MODEL_FROM_DATABASE=RV505 CE [Radeon X1550 64-bit] + +pci:v00001002d00007162* + ID_MODEL_FROM_DATABASE=RV515 PRO [Radeon X1300/X1550 Series] (Secondary) + +pci:v00001002d00007162sv00001002sd00000323* + ID_MODEL_FROM_DATABASE=RV515 PRO [Radeon X1300/X1550 Series] (Secondary) (All-in-Wonder 2006 PCI-E Edition (Secondary)) + +pci:v00001002d00007163* + ID_MODEL_FROM_DATABASE=RV505 [Radeon X1550 Series] (Secondary) + +pci:v00001002d00007166* + ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550 Series] (Secondary) + +pci:v00001002d00007166sv00001002sd00000323* + ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550 Series] (Secondary) (All-in-Wonder 2006 PCI-E Edition (Secondary)) + +pci:v00001002d00007166sv00001545sd00001997* + ID_MODEL_FROM_DATABASE=RV515 [Radeon X1300/X1550 Series] (Secondary) (Radeon X1300 512MB PCI-e (Secondary)) + +pci:v00001002d00007167* + ID_MODEL_FROM_DATABASE=RV515 [Radeon X1550 64-bit] (Secondary) + +pci:v00001002d00007172* + ID_MODEL_FROM_DATABASE=RV515 GL [FireGL V3300] (Secondary) + +pci:v00001002d00007173* + ID_MODEL_FROM_DATABASE=RV515 GL [FireGL V3350] (Secondary) + +pci:v00001002d00007181* + ID_MODEL_FROM_DATABASE=RV516 [Radeon X1600/X1650 Series] + +pci:v00001002d00007183* + ID_MODEL_FROM_DATABASE=RV516 [Radeon X1300/X1550 Series] + +pci:v00001002d00007186* + ID_MODEL_FROM_DATABASE=RV516/M64 [Mobility Radeon X1450] + +pci:v00001002d00007187* + ID_MODEL_FROM_DATABASE=RV516 [Radeon X1300/X1550 Series] + +pci:v00001002d00007188* + ID_MODEL_FROM_DATABASE=RV516/M64-S [Mobility Radeon X2300] + +pci:v00001002d00007188sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=RV516/M64-S [Mobility Radeon X2300] (6910p) + +pci:v00001002d0000718A* + ID_MODEL_FROM_DATABASE=RV516/M64 [Mobility Radeon X2300] + +pci:v00001002d0000718B* + ID_MODEL_FROM_DATABASE=RV516/M62 [Mobility Radeon X1350] + +pci:v00001002d0000718Bsv00001071sd00008209* + ID_MODEL_FROM_DATABASE=RV516/M62 [Mobility Radeon X1350] (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00001002d0000718C* + ID_MODEL_FROM_DATABASE=RV516/M62-CSP64 [Mobility Radeon X1350] + +pci:v00001002d0000718D* + ID_MODEL_FROM_DATABASE=RV516/M64-CSP128 [Mobility Radeon X1450] + +pci:v00001002d00007193* + ID_MODEL_FROM_DATABASE=RV516 [Radeon X1550 Series] + +pci:v00001002d00007196* + ID_MODEL_FROM_DATABASE=RV516/M62-S [Mobility Radeon X1350] + +pci:v00001002d0000719B* + ID_MODEL_FROM_DATABASE=RV516 GL [FireMV 2250] + +pci:v00001002d0000719Bsv000013CCsd00003D12* + ID_MODEL_FROM_DATABASE=RV516 GL [FireMV 2250] (MXRT-1150) + +pci:v00001002d0000719Bsv000013CCsd00003D14* + ID_MODEL_FROM_DATABASE=RV516 GL [FireMV 2250] (MXRT-2150) + +pci:v00001002d0000719F* + ID_MODEL_FROM_DATABASE=RV516 [Radeon X1550 Series] + +pci:v00001002d000071A0* + ID_MODEL_FROM_DATABASE=RV516 [Radeon X1300/X1550 Series] (Secondary) + +pci:v00001002d000071A1* + ID_MODEL_FROM_DATABASE=RV516 [Radeon X1600/X1650 Series] (Secondary) + +pci:v00001002d000071A3* + ID_MODEL_FROM_DATABASE=RV516 [Radeon X1300/X1550 Series] (Secondary) + +pci:v00001002d000071A7* + ID_MODEL_FROM_DATABASE=RV516 [Radeon X1300/X1550 Series] (Secondary) + +pci:v00001002d000071BB* + ID_MODEL_FROM_DATABASE=RV516 GL [FireMV 2250] (Secondary) + +pci:v00001002d000071BBsv000013CCsd00003D13* + ID_MODEL_FROM_DATABASE=RV516 GL [FireMV 2250] (Secondary) (MXRT-1150 (Secondary)) + +pci:v00001002d000071BBsv000013CCsd00003D15* + ID_MODEL_FROM_DATABASE=RV516 GL [FireMV 2250] (Secondary) (MXRT-2150 (Secondary)) + +pci:v00001002d000071C0* + ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600 XT/X1650 GTO] + +pci:v00001002d000071C0sv00001002sd0000E160* + ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600 XT/X1650 GTO] (Radeon X1650 GTO) + +pci:v00001002d000071C0sv0000174Bsd0000E160* + ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600 XT/X1650 GTO] (Radeon X1650 GTO) + +pci:v00001002d000071C1* + ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] + +pci:v00001002d000071C1sv0000174Bsd00000880* + ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (Radeon X1700 FSC) + +pci:v00001002d000071C2* + ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600 PRO] + +pci:v00001002d000071C4* + ID_MODEL_FROM_DATABASE=RV530/M56 GL [Mobility FireGL V5200] + +pci:v00001002d000071C4sv000017AAsd00002007* + ID_MODEL_FROM_DATABASE=RV530/M56 GL [Mobility FireGL V5200] (ThinkPad T60p) + +pci:v00001002d000071C5* + ID_MODEL_FROM_DATABASE=RV530/M56-P [Mobility Radeon X1600] + +pci:v00001002d000071C5sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=RV530/M56-P [Mobility Radeon X1600] (Compaq nx9420 Notebook) + +pci:v00001002d000071C5sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=RV530/M56-P [Mobility Radeon X1600] (Compaq NW8440) + +pci:v00001002d000071C5sv00001043sd000010B2* + ID_MODEL_FROM_DATABASE=RV530/M56-P [Mobility Radeon X1600] (A6J-Q008) + +pci:v00001002d000071C5sv0000106Bsd00000080* + ID_MODEL_FROM_DATABASE=RV530/M56-P [Mobility Radeon X1600] (MacBook Pro) + +pci:v00001002d000071C6* + ID_MODEL_FROM_DATABASE=RV530LE [Radeon X1600/X1650 PRO] + +pci:v00001002d000071C7* + ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] + +pci:v00001002d000071C7sv00001787sd00003000* + ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (PowerColor X1650 PRO AGP) + +pci:v00001002d000071CE* + ID_MODEL_FROM_DATABASE=RV530 [Radeon X1300 XT/X1600 PRO] + +pci:v00001002d000071D2* + ID_MODEL_FROM_DATABASE=RV530 GL [FireGL V3400] + +pci:v00001002d000071D2sv000013CCsd00003D08* + ID_MODEL_FROM_DATABASE=RV530 GL [FireGL V3400] (MXRT-2100) + +pci:v00001002d000071D4* + ID_MODEL_FROM_DATABASE=RV530/M66 GL [Mobility FireGL V5250] + +pci:v00001002d000071D5* + ID_MODEL_FROM_DATABASE=RV530/M66-P [Mobility Radeon X1700] + +pci:v00001002d000071D6* + ID_MODEL_FROM_DATABASE=RV530/M66-XT [Mobility Radeon X1700] + +pci:v00001002d000071DE* + ID_MODEL_FROM_DATABASE=RV530/M66 [Mobility Radeon X1700/X2500] + +pci:v00001002d000071E0* + ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600] (Secondary) + +pci:v00001002d000071E0sv0000174Bsd0000E161* + ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600] (Secondary) (Radeon X1600 GTO (Secondary)) + +pci:v00001002d000071E1* + ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (Secondary) + +pci:v00001002d000071E1sv0000174Bsd00000881* + ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (Secondary) (Radeon X1700 FSC (Secondary)) + +pci:v00001002d000071E2* + ID_MODEL_FROM_DATABASE=RV530 [Radeon X1600] (Secondary) + +pci:v00001002d000071E6* + ID_MODEL_FROM_DATABASE=RV530 [Radeon X1650] (Secondary) + +pci:v00001002d000071E7* + ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (Secondary) + +pci:v00001002d000071E7sv00001787sd00003001* + ID_MODEL_FROM_DATABASE=RV535 [Radeon X1650 PRO] (Secondary) (Radeon X1650 PRO AGP) + +pci:v00001002d000071F2* + ID_MODEL_FROM_DATABASE=RV530 GL [FireGL V3400] (Secondary) + +pci:v00001002d000071F2sv000013CCsd00003D09* + ID_MODEL_FROM_DATABASE=RV530 GL [FireGL V3400] (Secondary) (MXRT-2100 (Secondary)) + +pci:v00001002d00007210* + ID_MODEL_FROM_DATABASE=RV550/M71 [Mobility Radeon HD 2300] + +pci:v00001002d00007211* + ID_MODEL_FROM_DATABASE=RV550/M71 [Mobility Radeon X2300 HD] + +pci:v00001002d00007240* + ID_MODEL_FROM_DATABASE=R580+ [Radeon X1950 XTX] + +pci:v00001002d00007240sv00001002sd00000D02* + ID_MODEL_FROM_DATABASE=R580+ [Radeon X1950 XTX] (Radeon X1950 CrossFire Edition) + +pci:v00001002d00007244* + ID_MODEL_FROM_DATABASE=R580+ [Radeon X1950 XT] + +pci:v00001002d00007248* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1950] + +pci:v00001002d00007249* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] + +pci:v00001002d00007249sv00001002sd00000412* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] (All-In-Wonder X1900) + +pci:v00001002d00007249sv00001002sd00000B12* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] (Radeon X1900 XT/XTX) + +pci:v00001002d00007249sv00001002sd00000D02* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] (Radeon X1900 CrossFire Edition) + +pci:v00001002d00007249sv00001043sd00000160* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] (Radeon X1900 XTX 512 MB GDDR3) + +pci:v00001002d0000724B* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 GT] + +pci:v00001002d0000724Bsv00001002sd00000B12* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 GT] (Radeon X1900 (Primary)) + +pci:v00001002d0000724Bsv00001002sd00000B13* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 GT] (Radeon X1900 (Secondary)) + +pci:v00001002d0000724E* + ID_MODEL_FROM_DATABASE=R580 GL [FireGL V7350] + +pci:v00001002d00007269* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 XT] (Secondary) + +pci:v00001002d0000726B* + ID_MODEL_FROM_DATABASE=R580 [Radeon X1900 GT] (Secondary) + +pci:v00001002d0000726E* + ID_MODEL_FROM_DATABASE=R580 [AMD Stream Processor] (Secondary) + +pci:v00001002d00007280* + ID_MODEL_FROM_DATABASE=RV570 [Radeon X1950 PRO] + +pci:v00001002d00007288* + ID_MODEL_FROM_DATABASE=RV570 [Radeon X1950 GT] + +pci:v00001002d00007291* + ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 XT] + +pci:v00001002d00007291sv00001462sd00000810* + ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 XT] (Radeon X1700 SE) + +pci:v00001002d00007293* + ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 GT] + +pci:v00001002d000072A0* + ID_MODEL_FROM_DATABASE=RV570 [Radeon X1950 PRO] (Secondary) + +pci:v00001002d000072A8* + ID_MODEL_FROM_DATABASE=RV570 [Radeon X1950 GT] (Secondary) + +pci:v00001002d000072B1* + ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 XT] (Secondary) + +pci:v00001002d000072B3* + ID_MODEL_FROM_DATABASE=RV560 [Radeon X1650 GT] (Secondary) + +pci:v00001002d00007300* + ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] + +pci:v00001002d00007300sv00001002sd00000B36* + ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon R9 FURY X / NANO) + +pci:v00001002d00007300sv00001002sd00001B36* + ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon Pro Duo) + +pci:v00001002d00007300sv00001043sd0000049E* + ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon R9 FURY) + +pci:v00001002d00007300sv00001043sd000004A0* + ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon R9 FURY X) + +pci:v00001002d00007300sv0000174Bsd0000E329* + ID_MODEL_FROM_DATABASE=Fiji [Radeon R9 FURY / NANO Series] (Radeon R9 FURY) + +pci:v00001002d00007310* + ID_MODEL_FROM_DATABASE=Navi 10 + +pci:v00001002d00007312* + ID_MODEL_FROM_DATABASE=Navi 10 [Radeon Pro W5700] + +pci:v00001002d0000731F* + ID_MODEL_FROM_DATABASE=Navi 10 [Radeon RX 5600 OEM/5600 XT / 5700/5700 XT] + +pci:v00001002d00007340* + ID_MODEL_FROM_DATABASE=Navi 14 [Radeon RX 5500/5500M / Pro 5500M] + +pci:v00001002d00007341* + ID_MODEL_FROM_DATABASE=Navi 14 [Radeon Pro W5500] + +pci:v00001002d00007347* + ID_MODEL_FROM_DATABASE=Navi 14 [Radeon Pro W5500M] + +pci:v00001002d0000734F* + ID_MODEL_FROM_DATABASE=Navi 14 [Radeon Pro W5300M] + +pci:v00001002d00007833* + ID_MODEL_FROM_DATABASE=RS350 Host Bridge + +pci:v00001002d00007834* + ID_MODEL_FROM_DATABASE=RS350 [Radeon 9100 PRO/XT IGP] + +pci:v00001002d00007835* + ID_MODEL_FROM_DATABASE=RS350M [Mobility Radeon 9000 IGP] + +pci:v00001002d00007838* + ID_MODEL_FROM_DATABASE=RS350 AGP Bridge + +pci:v00001002d00007910* + ID_MODEL_FROM_DATABASE=RS690 Host Bridge + +pci:v00001002d00007910sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=RS690 Host Bridge (Satellite P305D-S8995E) + +pci:v00001002d00007910sv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=RS690 Host Bridge (KI690-AM2 Motherboard) + +pci:v00001002d00007911* + ID_MODEL_FROM_DATABASE=RS690/RS740 Host Bridge + +pci:v00001002d00007911sv00001002sd00007910* + ID_MODEL_FROM_DATABASE=RS690/RS740 Host Bridge + +pci:v00001002d00007912* + ID_MODEL_FROM_DATABASE=RS690/RS740 PCI to PCI Bridge (Internal gfx) + +pci:v00001002d00007913* + ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Graphics Port 0) + +pci:v00001002d00007915* + ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Port 1) + +pci:v00001002d00007916* + ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Port 2) + +pci:v00001002d00007917* + ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Port 3) + +pci:v00001002d00007917sv00001002sd00007910* + ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Port 3) (RS690 PCI to PCI Bridge) + +pci:v00001002d00007919* + ID_MODEL_FROM_DATABASE=RS690 HDMI Audio [Radeon Xpress 1200 Series] + +pci:v00001002d00007919sv00001179sd00007919* + ID_MODEL_FROM_DATABASE=RS690 HDMI Audio [Radeon Xpress 1200 Series] (Satellite P305D-S8995E) + +pci:v00001002d00007919sv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=RS690 HDMI Audio [Radeon Xpress 1200 Series] (KI690-AM2 Motherboard) + +pci:v00001002d0000791E* + ID_MODEL_FROM_DATABASE=RS690 [Radeon X1200] + +pci:v00001002d0000791Esv00001462sd00007327* + ID_MODEL_FROM_DATABASE=RS690 [Radeon X1200] (K9AG Neo2) + +pci:v00001002d0000791Esv000017F2sd00005000* + ID_MODEL_FROM_DATABASE=RS690 [Radeon X1200] (KI690-AM2 Motherboard) + +pci:v00001002d0000791F* + ID_MODEL_FROM_DATABASE=RS690M [Radeon Xpress 1200/1250/1270] + +pci:v00001002d0000791Fsv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=RS690M [Radeon Xpress 1200/1250/1270] (Satellite P305D-S8995E) + +pci:v00001002d00007930* + ID_MODEL_FROM_DATABASE=RS600 Host Bridge + +pci:v00001002d00007932* + ID_MODEL_FROM_DATABASE=RS600 PCI to PCI Bridge (Internal gfx) + +pci:v00001002d00007933* + ID_MODEL_FROM_DATABASE=RS600 PCI to PCI Bridge (PCI Express Graphics Port 0) + +pci:v00001002d00007935* + ID_MODEL_FROM_DATABASE=RS600 PCI to PCI Bridge (PCI Express Port 1) + +pci:v00001002d00007936* + ID_MODEL_FROM_DATABASE=RS600 PCI to PCI Bridge (PCI Express Port 2) + +pci:v00001002d00007937* + ID_MODEL_FROM_DATABASE=RS690 PCI to PCI Bridge (PCI Express Port 3) + +pci:v00001002d0000793B* + ID_MODEL_FROM_DATABASE=RS600 HDMI Audio [Radeon Xpress 1250] + +pci:v00001002d0000793F* + ID_MODEL_FROM_DATABASE=RS690M [Radeon Xpress 1200/1250/1270] (Secondary) + +pci:v00001002d00007941* + ID_MODEL_FROM_DATABASE=RS600 [Radeon Xpress 1250] + +pci:v00001002d00007942* + ID_MODEL_FROM_DATABASE=RS600M [Radeon Xpress 1250] + +pci:v00001002d0000796E* + ID_MODEL_FROM_DATABASE=RS740 [Radeon 2100] + +pci:v00001002d0000796Esv0000105Bsd00000E13* + ID_MODEL_FROM_DATABASE=RS740 [Radeon 2100] (N15235/A74MX mainboard) + +pci:v00001002d00009400* + ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 PRO/XT] + +pci:v00001002d00009400sv00001002sd00002552* + ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 PRO/XT] (Radeon HD 2900 XT) + +pci:v00001002d00009400sv00001002sd00003000* + ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 PRO/XT] (Radeon HD 2900 PRO) + +pci:v00001002d00009400sv00001002sd00003142* + ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 PRO/XT] (HIS Radeon HD 2900XT 512MB GDDR3 VIVO PCIe) + +pci:v00001002d00009401* + ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 XT] + +pci:v00001002d00009403* + ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 PRO] + +pci:v00001002d00009405* + ID_MODEL_FROM_DATABASE=R600 [Radeon HD 2900 GT] + +pci:v00001002d0000940A* + ID_MODEL_FROM_DATABASE=R600 GL [FireGL V8650] + +pci:v00001002d0000940Asv000013CCsd00003D16* + ID_MODEL_FROM_DATABASE=R600 GL [FireGL V8650] (MXRT-7200) + +pci:v00001002d0000940B* + ID_MODEL_FROM_DATABASE=R600 GL [FireGL V8600] + +pci:v00001002d0000940F* + ID_MODEL_FROM_DATABASE=R600 GL [FireGL V7600] + +pci:v00001002d00009440* + ID_MODEL_FROM_DATABASE=RV770 [Radeon HD 4870] + +pci:v00001002d00009441* + ID_MODEL_FROM_DATABASE=R700 [Radeon HD 4870 X2] + +pci:v00001002d00009442* + ID_MODEL_FROM_DATABASE=RV770 [Radeon HD 4850] + +pci:v00001002d00009442sv00001002sd00000502* + ID_MODEL_FROM_DATABASE=RV770 [Radeon HD 4850] (MSI Radeon HD 4850 512MB GDDR3) + +pci:v00001002d00009442sv0000174Bsd0000E810* + ID_MODEL_FROM_DATABASE=RV770 [Radeon HD 4850] (Radeon HD 4850 512MB GDDR3) + +pci:v00001002d00009443* + ID_MODEL_FROM_DATABASE=R700 [Radeon HD 4850 X2] + +pci:v00001002d00009444* + ID_MODEL_FROM_DATABASE=RV770 GL [FirePro V8750] + +pci:v00001002d00009446* + ID_MODEL_FROM_DATABASE=RV770 GL [FirePro V7760] + +pci:v00001002d0000944A* + ID_MODEL_FROM_DATABASE=RV770/M98L [Mobility Radeon HD 4850] + +pci:v00001002d0000944B* + ID_MODEL_FROM_DATABASE=RV770/M98 [Mobility Radeon HD 4850 X2] + +pci:v00001002d0000944C* + ID_MODEL_FROM_DATABASE=RV770 LE [Radeon HD 4830] + +pci:v00001002d0000944E* + ID_MODEL_FROM_DATABASE=RV770 CE [Radeon HD 4710] + +pci:v00001002d0000944Esv0000174Bsd00003261* + ID_MODEL_FROM_DATABASE=RV770 CE [Radeon HD 4710] (Radeon HD 4810) + +pci:v00001002d00009450* + ID_MODEL_FROM_DATABASE=RV770 GL [FireStream 9270] + +pci:v00001002d00009452* + ID_MODEL_FROM_DATABASE=RV770 GL [FireStream 9250] + +pci:v00001002d00009456* + ID_MODEL_FROM_DATABASE=RV770 GL [FirePro V8700] + +pci:v00001002d0000945A* + ID_MODEL_FROM_DATABASE=RV770/M98-XT [Mobility Radeon HD 4870] + +pci:v00001002d00009460* + ID_MODEL_FROM_DATABASE=RV790 [Radeon HD 4890] + +pci:v00001002d00009462* + ID_MODEL_FROM_DATABASE=RV790 [Radeon HD 4860] + +pci:v00001002d0000946A* + ID_MODEL_FROM_DATABASE=RV770 GL [FirePro M7750] + +pci:v00001002d00009480* + ID_MODEL_FROM_DATABASE=RV730/M96 [Mobility Radeon HD 4650/5165] + +pci:v00001002d00009480sv0000103Csd00003628* + ID_MODEL_FROM_DATABASE=RV730/M96 [Mobility Radeon HD 4650/5165] (Mobility Radeon HD 4650 [dv6-1190en]) + +pci:v00001002d00009488* + ID_MODEL_FROM_DATABASE=RV730/M96-XT [Mobility Radeon HD 4670] + +pci:v00001002d00009489* + ID_MODEL_FROM_DATABASE=RV730/M96 GL [Mobility FireGL V5725] + +pci:v00001002d00009490* + ID_MODEL_FROM_DATABASE=RV730 XT [Radeon HD 4670] + +pci:v00001002d00009490sv0000174Bsd0000E880* + ID_MODEL_FROM_DATABASE=RV730 XT [Radeon HD 4670] (Radeon HD 4670 512MB GDDR3 Dual DVI-I/TVO) + +pci:v00001002d00009491* + ID_MODEL_FROM_DATABASE=RV730/M96-CSP [Radeon E4690] + +pci:v00001002d00009495* + ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] + +pci:v00001002d00009495sv00001002sd00000028* + ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] (Radeon HD 4650/4670 AGP) + +pci:v00001002d00009495sv00001092sd00000028* + ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] (Radeon HD 4670 AGP 512MB DDR2) + +pci:v00001002d00009495sv00001458sd00000028* + ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] (Radeon HD 4650 AGP) + +pci:v00001002d00009495sv00001682sd00000028* + ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] (Radeon HD 4650 AGP) + +pci:v00001002d00009495sv0000174Bsd00000028* + ID_MODEL_FROM_DATABASE=RV730 [Radeon HD 4600 AGP Series] (Radeon HD 4650 AGP DDR2) + +pci:v00001002d00009498* + ID_MODEL_FROM_DATABASE=RV730 PRO [Radeon HD 4650] + +pci:v00001002d0000949C* + ID_MODEL_FROM_DATABASE=RV730 GL [FirePro V7750] + +pci:v00001002d0000949Csv000013CCsd00003D1B* + ID_MODEL_FROM_DATABASE=RV730 GL [FirePro V7750] (MXRT-7300) + +pci:v00001002d0000949E* + ID_MODEL_FROM_DATABASE=RV730 GL [FirePro V5700] + +pci:v00001002d0000949F* + ID_MODEL_FROM_DATABASE=RV730 GL [FirePro V3750] + +pci:v00001002d000094A0* + ID_MODEL_FROM_DATABASE=RV740/M97 [Mobility Radeon HD 4830] + +pci:v00001002d000094A1* + ID_MODEL_FROM_DATABASE=RV740/M97-XT [Mobility Radeon HD 4860] + +pci:v00001002d000094A3* + ID_MODEL_FROM_DATABASE=RV740/M97 GL [FirePro M7740] + +pci:v00001002d000094B3* + ID_MODEL_FROM_DATABASE=RV740 PRO [Radeon HD 4770] + +pci:v00001002d000094B4* + ID_MODEL_FROM_DATABASE=RV740 PRO [Radeon HD 4750] + +pci:v00001002d000094C1* + ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO/XT] + +pci:v00001002d000094C1sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO/XT] (Optiplex 755) + +pci:v00001002d000094C1sv00001028sd00000D02* + ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO/XT] (Optiplex 755) + +pci:v00001002d000094C3* + ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO] + +pci:v00001002d000094C3sv00001028sd00000302* + ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO] (Radeon HD 2400 Pro) + +pci:v00001002d000094C3sv0000174Bsd0000E400* + ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO] (Radeon HD 2400 PRO) + +pci:v00001002d000094C3sv000018BCsd00003550* + ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 PRO] (Radeon HD 2400 PRO) + +pci:v00001002d000094C4* + ID_MODEL_FROM_DATABASE=RV610 LE [Radeon HD 2400 PRO AGP] + +pci:v00001002d000094C5* + ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2400 LE] + +pci:v00001002d000094C7* + ID_MODEL_FROM_DATABASE=RV610 [Radeon HD 2350] + +pci:v00001002d000094C8* + ID_MODEL_FROM_DATABASE=RV610/M74 [Mobility Radeon HD 2400 XT] + +pci:v00001002d000094C9* + ID_MODEL_FROM_DATABASE=RV610/M72-S [Mobility Radeon HD 2400] + +pci:v00001002d000094C9sv00001002sd000094C9* + ID_MODEL_FROM_DATABASE=RV610/M72-S [Mobility Radeon HD 2400] (Radeon HD2400) + +pci:v00001002d000094CB* + ID_MODEL_FROM_DATABASE=RV610 [Radeon E2400] + +pci:v00001002d000094CC* + ID_MODEL_FROM_DATABASE=RV610 LE [Radeon HD 2400 PRO PCI] + +pci:v00001002d00009500* + ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3850 X2] + +pci:v00001002d00009501* + ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3870] + +pci:v00001002d00009501sv0000174Bsd0000E620* + ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3870] (Radeon HD 3870) + +pci:v00001002d00009504* + ID_MODEL_FROM_DATABASE=RV670/M88 [Mobility Radeon HD 3850] + +pci:v00001002d00009505* + ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3690/3850] + +pci:v00001002d00009505sv0000148Csd00003000* + ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3690/3850] (Radeon HD 3850) + +pci:v00001002d00009505sv0000174Bsd00003000* + ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3690/3850] (Radeon HD 3690/3850) + +pci:v00001002d00009505sv00001787sd00003000* + ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3690/3850] (Radeon HD 3690) + +pci:v00001002d00009506* + ID_MODEL_FROM_DATABASE=RV670/M88 [Mobility Radeon HD 3850 X2] + +pci:v00001002d00009507* + ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3830] + +pci:v00001002d00009508* + ID_MODEL_FROM_DATABASE=RV670/M88-XT [Mobility Radeon HD 3870] + +pci:v00001002d00009509* + ID_MODEL_FROM_DATABASE=RV670/M88 [Mobility Radeon HD 3870 X2] + +pci:v00001002d0000950F* + ID_MODEL_FROM_DATABASE=R680 [Radeon HD 3870 X2] + +pci:v00001002d00009511* + ID_MODEL_FROM_DATABASE=RV670 GL [FireGL V7700] + +pci:v00001002d00009513* + ID_MODEL_FROM_DATABASE=RV670 [Radeon HD 3850 X2] + +pci:v00001002d00009515* + ID_MODEL_FROM_DATABASE=RV670 PRO [Radeon HD 3850 AGP] + +pci:v00001002d00009519* + ID_MODEL_FROM_DATABASE=RV670 GL [FireStream 9170] + +pci:v00001002d00009540* + ID_MODEL_FROM_DATABASE=RV710 [Radeon HD 4550] + +pci:v00001002d0000954F* + ID_MODEL_FROM_DATABASE=RV710 [Radeon HD 4350/4550] + +pci:v00001002d0000954Fsv00001462sd00001618* + ID_MODEL_FROM_DATABASE=RV710 [Radeon HD 4350/4550] (R4350 MD512H (MS-V161)) + +pci:v00001002d00009552* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] + +pci:v00001002d00009552sv00001028sd00001103* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] (M92 [Mobility Radeon HD 4330]) + +pci:v00001002d00009552sv00001458sd000021AC* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] (Radeon HD 4350) + +pci:v00001002d00009552sv00001458sd000021ED* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] (Radeon HD 4550) + +pci:v00001002d00009552sv0000148Csd00003000* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] (Radeon HD 4350 Go! Green 512MB GDDR3) + +pci:v00001002d00009552sv0000174Bsd00003000* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330/4350/4550] (Radeon HD 4350/4550 HyperMemory DDR2) + +pci:v00001002d00009553* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] + +pci:v00001002d00009553sv00001025sd0000015E* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) + +pci:v00001002d00009553sv00001025sd0000017D* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) + +pci:v00001002d00009553sv00001025sd00000205* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570 / 545v) + +pci:v00001002d00009553sv00001025sd00000206* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) + +pci:v00001002d00009553sv00001025sd00000237* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) + +pci:v00001002d00009553sv00001028sd000002BE* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570 / 545v) + +pci:v00001002d00009553sv00001028sd000002E8* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4530) + +pci:v00001002d00009553sv0000103Csd0000143C* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v) + +pci:v00001002d00009553sv0000103Csd00001446* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v) + +pci:v00001002d00009553sv0000103Csd00003624* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4530) + +pci:v00001002d00009553sv0000103Csd00003628* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4530) + +pci:v00001002d00009553sv0000103Csd00003636* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4530) + +pci:v00001002d00009553sv00001043sd00001B32* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) + +pci:v00001002d00009553sv00001043sd00001B42* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) + +pci:v00001002d00009553sv0000104Dsd00009056* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 4570) + +pci:v00001002d00009553sv00001179sd0000FF82* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Satellite L505-13T GPU (Mobility Radeon HD 5145)) + +pci:v00001002d00009553sv0000144Dsd0000C07F* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v) + +pci:v00001002d00009553sv0000144Dsd0000C571* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v) + +pci:v00001002d00009553sv00001462sd00001006* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v) + +pci:v00001002d00009553sv000017AAsd00002129* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v) + +pci:v00001002d00009553sv000017AAsd0000215B* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v) + +pci:v00001002d00009553sv000017AAsd000021BB* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4530/4570/545v] (Mobility Radeon HD 545v) + +pci:v00001002d00009555* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4350/4550] + +pci:v00001002d00009555sv0000103Csd00001411* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4350/4550] (ProBook 4720s GPU (Mobility Radeon HD 4350)) + +pci:v00001002d00009557* + ID_MODEL_FROM_DATABASE=RV711 GL [FirePro RG220] + +pci:v00001002d0000955F* + ID_MODEL_FROM_DATABASE=RV710/M92 [Mobility Radeon HD 4330] + +pci:v00001002d00009580* + ID_MODEL_FROM_DATABASE=RV630 [Radeon HD 2600 PRO] + +pci:v00001002d00009581* + ID_MODEL_FROM_DATABASE=RV630/M76 [Mobility Radeon HD 2600] + +pci:v00001002d00009583* + ID_MODEL_FROM_DATABASE=RV630/M76 [Mobility Radeon HD 2600 XT/2700] + +pci:v00001002d00009583sv0000106Bsd00000083* + ID_MODEL_FROM_DATABASE=RV630/M76 [Mobility Radeon HD 2600 XT/2700] (iMac 7,1) + +pci:v00001002d00009583sv00001734sd00001107* + ID_MODEL_FROM_DATABASE=RV630/M76 [Mobility Radeon HD 2600 XT/2700] (Mobility Radeon HD 2700) + +pci:v00001002d00009586* + ID_MODEL_FROM_DATABASE=RV630 XT [Radeon HD 2600 XT AGP] + +pci:v00001002d00009587* + ID_MODEL_FROM_DATABASE=RV630 PRO [Radeon HD 2600 PRO AGP] + +pci:v00001002d00009588* + ID_MODEL_FROM_DATABASE=RV630 XT [Radeon HD 2600 XT] + +pci:v00001002d00009588sv00001458sd0000216C* + ID_MODEL_FROM_DATABASE=RV630 XT [Radeon HD 2600 XT] (Radeon HD 2600 XT, 256MB GDDR3, 2x DVI, TV-out, PCIe (GV-RX26T256H)) + +pci:v00001002d00009589* + ID_MODEL_FROM_DATABASE=RV630 PRO [Radeon HD 2600 PRO] + +pci:v00001002d00009589sv00001787sd00003000* + ID_MODEL_FROM_DATABASE=RV630 PRO [Radeon HD 2600 PRO] (Radeon HD 3610) + +pci:v00001002d0000958A* + ID_MODEL_FROM_DATABASE=RV630 [Radeon HD 2600 X2] + +pci:v00001002d0000958B* + ID_MODEL_FROM_DATABASE=RV630/M76 [Mobility Radeon HD 2600 XT] + +pci:v00001002d0000958C* + ID_MODEL_FROM_DATABASE=RV630 GL [FireGL V5600] + +pci:v00001002d0000958Csv000013CCsd00003D18* + ID_MODEL_FROM_DATABASE=RV630 GL [FireGL V5600] (MXRT-5200) + +pci:v00001002d0000958D* + ID_MODEL_FROM_DATABASE=RV630 GL [FireGL V3600] + +pci:v00001002d00009591* + ID_MODEL_FROM_DATABASE=RV635/M86 [Mobility Radeon HD 3650] + +pci:v00001002d00009591sv00001002sd00009591* + ID_MODEL_FROM_DATABASE=RV635/M86 [Mobility Radeon HD 3650] (Mobility Radeon HD 3650) + +pci:v00001002d00009593* + ID_MODEL_FROM_DATABASE=RV635/M86 [Mobility Radeon HD 3670] + +pci:v00001002d00009595* + ID_MODEL_FROM_DATABASE=RV635/M86 GL [Mobility FireGL V5700] + +pci:v00001002d00009596* + ID_MODEL_FROM_DATABASE=RV635 PRO [Radeon HD 3650 AGP] + +pci:v00001002d00009596sv00001043sd00000028* + ID_MODEL_FROM_DATABASE=RV635 PRO [Radeon HD 3650 AGP] (EAH3650 SILENT/HTDI/512M/A) + +pci:v00001002d00009597* + ID_MODEL_FROM_DATABASE=RV635 PRO [Radeon HD 3650 AGP] + +pci:v00001002d00009598* + ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] + +pci:v00001002d00009598sv00001002sd00009598* + ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (Mobility Radeon HD 3600) + +pci:v00001002d00009598sv00001043sd000001D6* + ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (EAH3650 Silent) + +pci:v00001002d00009598sv00001043sd00003001* + ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (Radeon HD 4570) + +pci:v00001002d00009598sv0000174Bsd00003001* + ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (Radeon HD 3750) + +pci:v00001002d00009598sv0000174Bsd00004580* + ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (RV635 PRO [Radeon HD 4580]) + +pci:v00001002d00009598sv000017AFsd00003011* + ID_MODEL_FROM_DATABASE=RV635 [Radeon HD 3650/3750/4570/4580] (RV635 PRO [Radeon HD 4580]) + +pci:v00001002d00009599* + ID_MODEL_FROM_DATABASE=RV635 PRO [Radeon HD 3650 AGP] + +pci:v00001002d000095C0* + ID_MODEL_FROM_DATABASE=RV620 PRO [Radeon HD 3470] + +pci:v00001002d000095C0sv00001002sd000095C0* + ID_MODEL_FROM_DATABASE=RV620 PRO [Radeon HD 3470] (Mobility Radeon HD 3470) + +pci:v00001002d000095C2* + ID_MODEL_FROM_DATABASE=RV620/M82 [Mobility Radeon HD 3410/3430] + +pci:v00001002d000095C4* + ID_MODEL_FROM_DATABASE=RV620/M82 [Mobility Radeon HD 3450/3470] + +pci:v00001002d000095C4sv00001002sd000095C4* + ID_MODEL_FROM_DATABASE=RV620/M82 [Mobility Radeon HD 3450/3470] (Mobility Radeon HD 3400) + +pci:v00001002d000095C5* + ID_MODEL_FROM_DATABASE=RV620 LE [Radeon HD 3450] + +pci:v00001002d000095C5sv00001028sd00000342* + ID_MODEL_FROM_DATABASE=RV620 LE [Radeon HD 3450] (OptiPlex 980) + +pci:v00001002d000095C6* + ID_MODEL_FROM_DATABASE=RV620 LE [Radeon HD 3450 AGP] + +pci:v00001002d000095C9* + ID_MODEL_FROM_DATABASE=RV620 LE [Radeon HD 3450 PCI] + +pci:v00001002d000095CC* + ID_MODEL_FROM_DATABASE=RV620 GL [FirePro V3700] + +pci:v00001002d000095CD* + ID_MODEL_FROM_DATABASE=RV620 GL [FirePro 2450] + +pci:v00001002d000095CF* + ID_MODEL_FROM_DATABASE=RV620 GL [FirePro 2260] + +pci:v00001002d0000960F* + ID_MODEL_FROM_DATABASE=RS780 HDMI Audio [Radeon 3000/3100 / HD 3200/3300] + +pci:v00001002d00009610* + ID_MODEL_FROM_DATABASE=RS780 [Radeon HD 3200] + +pci:v00001002d00009610sv00001458sd0000D000* + ID_MODEL_FROM_DATABASE=RS780 [Radeon HD 3200] (GA-MA78GM-S2H Motherboard) + +pci:v00001002d00009611* + ID_MODEL_FROM_DATABASE=RS780C [Radeon 3100] + +pci:v00001002d00009612* + ID_MODEL_FROM_DATABASE=RS780M [Mobility Radeon HD 3200] + +pci:v00001002d00009613* + ID_MODEL_FROM_DATABASE=RS780MC [Mobility Radeon HD 3100] + +pci:v00001002d00009614* + ID_MODEL_FROM_DATABASE=RS780D [Radeon HD 3300] + +pci:v00001002d00009616* + ID_MODEL_FROM_DATABASE=RS780L [Radeon 3000] + +pci:v00001002d00009640* + ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6550D] + +pci:v00001002d00009641* + ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6620G] + +pci:v00001002d00009642* + ID_MODEL_FROM_DATABASE=SuperSumo [Radeon HD 6370D] + +pci:v00001002d00009643* + ID_MODEL_FROM_DATABASE=SuperSumo [Radeon HD 6380G] + +pci:v00001002d00009644* + ID_MODEL_FROM_DATABASE=SuperSumo [Radeon HD 6410D] + +pci:v00001002d00009645* + ID_MODEL_FROM_DATABASE=SuperSumo [Radeon HD 6410D] + +pci:v00001002d00009647* + ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6520G] + +pci:v00001002d00009648* + ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6480G] + +pci:v00001002d00009649* + ID_MODEL_FROM_DATABASE=SuperSumo [Radeon HD 6480G] + +pci:v00001002d0000964A* + ID_MODEL_FROM_DATABASE=Sumo [Radeon HD 6530D] + +pci:v00001002d0000964B* + ID_MODEL_FROM_DATABASE=Sumo + +pci:v00001002d0000964C* + ID_MODEL_FROM_DATABASE=Sumo + +pci:v00001002d0000964E* + ID_MODEL_FROM_DATABASE=Sumo + +pci:v00001002d0000964F* + ID_MODEL_FROM_DATABASE=Sumo + +pci:v00001002d0000970F* + ID_MODEL_FROM_DATABASE=RS880 HDMI Audio [Radeon HD 4200 Series] + +pci:v00001002d0000970Fsv00001019sd00002120* + ID_MODEL_FROM_DATABASE=RS880 HDMI Audio [Radeon HD 4200 Series] (A785GM-M) + +pci:v00001002d0000970Fsv00001043sd000083A2* + ID_MODEL_FROM_DATABASE=RS880 HDMI Audio [Radeon HD 4200 Series] (M4A785TD Motherboard) + +pci:v00001002d0000970Fsv00001043sd0000843E* + ID_MODEL_FROM_DATABASE=RS880 HDMI Audio [Radeon HD 4200 Series] (M5A88-V EVO) + +pci:v00001002d00009710* + ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4200] + +pci:v00001002d00009710sv00001019sd00002120* + ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4200] (A785GM-M) + +pci:v00001002d00009710sv00001043sd000083A2* + ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4200] (M4A785TD Motherboard) + +pci:v00001002d00009712* + ID_MODEL_FROM_DATABASE=RS880M [Mobility Radeon HD 4225/4250] + +pci:v00001002d00009712sv0000103Csd00001609* + ID_MODEL_FROM_DATABASE=RS880M [Mobility Radeon HD 4225/4250] (ProLiant MicroServer N36L) + +pci:v00001002d00009713* + ID_MODEL_FROM_DATABASE=RS880M [Mobility Radeon HD 4100] + +pci:v00001002d00009714* + ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4290] + +pci:v00001002d00009715* + ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4250] + +pci:v00001002d00009715sv00001043sd0000843E* + ID_MODEL_FROM_DATABASE=RS880 [Radeon HD 4250] (M5A88-V EVO) + +pci:v00001002d00009802* + ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6310] + +pci:v00001002d00009802sv0000174Bsd00001001* + ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6310] (PURE Fusion Mini) + +pci:v00001002d00009803* + ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6310] + +pci:v00001002d00009804* + ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6250] + +pci:v00001002d00009805* + ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6250] + +pci:v00001002d00009806* + ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6320] + +pci:v00001002d00009807* + ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 6290] + +pci:v00001002d00009808* + ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 7340] + +pci:v00001002d00009809* + ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 7310] + +pci:v00001002d0000980A* + ID_MODEL_FROM_DATABASE=Wrestler [Radeon HD 7290] + +pci:v00001002d00009830* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8400 / R3 Series] + +pci:v00001002d00009831* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8400E] + +pci:v00001002d00009832* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8330] + +pci:v00001002d00009832sv00001849sd00009832* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8330] (QC5000-ITX/PH) + +pci:v00001002d00009833* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8330E] + +pci:v00001002d00009834* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8210] + +pci:v00001002d00009835* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8310E] + +pci:v00001002d00009836* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8280 / R3 Series] + +pci:v00001002d00009837* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8280E] + +pci:v00001002d00009838* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8240 / R3 Series] + +pci:v00001002d00009839* + ID_MODEL_FROM_DATABASE=Kabini [Radeon HD 8180] + +pci:v00001002d0000983D* + ID_MODEL_FROM_DATABASE=Temash [Radeon HD 8250/8280G] + +pci:v00001002d00009840* + ID_MODEL_FROM_DATABASE=Kabini HDMI/DP Audio + +pci:v00001002d00009840sv00001849sd00009840* + ID_MODEL_FROM_DATABASE=Kabini HDMI/DP Audio (QC5000-ITX/PH) + +pci:v00001002d00009850* + ID_MODEL_FROM_DATABASE=Mullins [Radeon R3 Graphics] + +pci:v00001002d00009851* + ID_MODEL_FROM_DATABASE=Mullins [Radeon R4/R5 Graphics] + +pci:v00001002d00009851sv00001179sd0000F928* + ID_MODEL_FROM_DATABASE=Mullins [Radeon R4/R5 Graphics] (Beema [Radeon R5 Graphics]) + +pci:v00001002d00009852* + ID_MODEL_FROM_DATABASE=Mullins [Radeon R2 Graphics] + +pci:v00001002d00009853* + ID_MODEL_FROM_DATABASE=Mullins [Radeon R2 Graphics] + +pci:v00001002d00009854* + ID_MODEL_FROM_DATABASE=Mullins [Radeon R3E Graphics] + +pci:v00001002d00009855* + ID_MODEL_FROM_DATABASE=Mullins [Radeon R6 Graphics] + +pci:v00001002d00009856* + ID_MODEL_FROM_DATABASE=Mullins [Radeon R1E/R2E Graphics] + +pci:v00001002d00009857* + ID_MODEL_FROM_DATABASE=Mullins [Radeon APU XX-2200M with R2 Graphics] + +pci:v00001002d00009858* + ID_MODEL_FROM_DATABASE=Mullins + +pci:v00001002d00009859* + ID_MODEL_FROM_DATABASE=Mullins + +pci:v00001002d0000985A* + ID_MODEL_FROM_DATABASE=Mullins + +pci:v00001002d0000985B* + ID_MODEL_FROM_DATABASE=Mullins + +pci:v00001002d0000985C* + ID_MODEL_FROM_DATABASE=Mullins + +pci:v00001002d0000985D* + ID_MODEL_FROM_DATABASE=Mullins + +pci:v00001002d0000985E* + ID_MODEL_FROM_DATABASE=Mullins + +pci:v00001002d0000985F* + ID_MODEL_FROM_DATABASE=Mullins + +pci:v00001002d00009874* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] + +pci:v00001002d00009874sv00001002sd00001871* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R5 Graphics) + +pci:v00001002d00009874sv00001002sd00001E20* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R7 Graphics) + +pci:v00001002d00009874sv00001028sd000006BD* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R6 Graphics) + +pci:v00001002d00009874sv0000103Csd00002B44* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R6 Graphics) + +pci:v00001002d00009874sv0000103Csd00008221* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R5 Graphics) + +pci:v00001002d00009874sv0000103Csd00008223* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R5 Graphics) + +pci:v00001002d00009874sv0000103Csd00008238* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R7 Graphics) + +pci:v00001002d00009874sv0000103Csd00008353* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R7 Graphics) + +pci:v00001002d00009874sv00001458sd0000D000* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R7 Graphics) + +pci:v00001002d00009874sv000017AAsd00005113* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R6 Graphics) + +pci:v00001002d00009874sv000017AAsd00005116* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R6 Graphics) + +pci:v00001002d00009874sv000017AAsd00005118* + ID_MODEL_FROM_DATABASE=Wani [Radeon R5/R6/R7 Graphics] (Radeon R5 Graphics) + +pci:v00001002d00009890* + ID_MODEL_FROM_DATABASE=Amur + +pci:v00001002d000098C0* + ID_MODEL_FROM_DATABASE=Nolan + +pci:v00001002d000098E4* + ID_MODEL_FROM_DATABASE=Stoney [Radeon R2/R3/R4/R5 Graphics] + +pci:v00001002d00009900* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7660G] + +pci:v00001002d00009900sv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7660G] (Pavilion 17-e163sg Notebook PC) + +pci:v00001002d00009901* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7660D] + +pci:v00001002d00009902* + ID_MODEL_FROM_DATABASE=Trinity HDMI Audio Controller + +pci:v00001002d00009902sv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=Trinity HDMI Audio Controller (ProBook 455 G1 Notebook) + +pci:v00001002d00009902sv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=Trinity HDMI Audio Controller (Pavilion 17-e163sg Notebook PC) + +pci:v00001002d00009903* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7640G] + +pci:v00001002d00009903sv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7640G] (ProBook 455 G1 Notebook) + +pci:v00001002d00009903sv0000103Csd00001952* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7640G] (ProBook 455 G1 Notebook) + +pci:v00001002d00009904* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7560D] + +pci:v00001002d00009905* + ID_MODEL_FROM_DATABASE=Trinity GL [FirePro A300] + +pci:v00001002d00009906* + ID_MODEL_FROM_DATABASE=Trinity GL [FirePro A320] + +pci:v00001002d00009907* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7620G] + +pci:v00001002d00009908* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7600G] + +pci:v00001002d00009909* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7500G] + +pci:v00001002d0000990A* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7500G] + +pci:v00001002d0000990B* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8650G] + +pci:v00001002d0000990C* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8670D] + +pci:v00001002d0000990D* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8550G] + +pci:v00001002d0000990E* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8570D] + +pci:v00001002d0000990F* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8610G] + +pci:v00001002d00009910* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7660G] + +pci:v00001002d00009913* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7640G] + +pci:v00001002d00009917* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7620G] + +pci:v00001002d00009918* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7600G] + +pci:v00001002d00009919* + ID_MODEL_FROM_DATABASE=Trinity [Radeon HD 7500G] + +pci:v00001002d0000991E* + ID_MODEL_FROM_DATABASE=Bishop + +pci:v00001002d00009920* + ID_MODEL_FROM_DATABASE=Liverpool [Playstation 4 APU] + +pci:v00001002d00009921* + ID_MODEL_FROM_DATABASE=Liverpool HDMI/DP Audio Controller + +pci:v00001002d00009922* + ID_MODEL_FROM_DATABASE=Starshp + +pci:v00001002d00009923* + ID_MODEL_FROM_DATABASE=Starsha2 [Kingston/Clayton] + +pci:v00001002d00009924* + ID_MODEL_FROM_DATABASE=Gladius + +pci:v00001002d00009925* + ID_MODEL_FROM_DATABASE=Kingston/Clayton/Jupiter/Gladius/Montego HDMI Controller + +pci:v00001002d00009926* + ID_MODEL_FROM_DATABASE=Jupiter + +pci:v00001002d00009990* + ID_MODEL_FROM_DATABASE=Trinity 2 [Radeon HD 7520G] + +pci:v00001002d00009991* + ID_MODEL_FROM_DATABASE=Trinity 2 [Radeon HD 7540D] + +pci:v00001002d00009992* + ID_MODEL_FROM_DATABASE=Trinity 2 [Radeon HD 7420G] + +pci:v00001002d00009993* + ID_MODEL_FROM_DATABASE=Trinity 2 [Radeon HD 7480D] + +pci:v00001002d00009994* + ID_MODEL_FROM_DATABASE=Trinity 2 [Radeon HD 7400G] + +pci:v00001002d00009995* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8450G] + +pci:v00001002d00009996* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8470D] + +pci:v00001002d00009997* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8350G] + +pci:v00001002d00009998* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8370D] + +pci:v00001002d00009999* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8510G] + +pci:v00001002d0000999A* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8410G] + +pci:v00001002d0000999B* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8310G] + +pci:v00001002d0000999C* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8650D] + +pci:v00001002d0000999D* + ID_MODEL_FROM_DATABASE=Richland [Radeon HD 8550D] + +pci:v00001002d000099A0* + ID_MODEL_FROM_DATABASE=Trinity 2 [Radeon HD 7520G] + +pci:v00001002d000099A2* + ID_MODEL_FROM_DATABASE=Trinity 2 [Radeon HD 7420G] + +pci:v00001002d000099A4* + ID_MODEL_FROM_DATABASE=Trinity 2 [Radeon HD 7400G] + +pci:v00001002d0000AA00* + ID_MODEL_FROM_DATABASE=R600 HDMI Audio [Radeon HD 2900 GT/PRO/XT] + +pci:v00001002d0000AA01* + ID_MODEL_FROM_DATABASE=RV635 HDMI Audio [Radeon HD 3650/3730/3750] + +pci:v00001002d0000AA08* + ID_MODEL_FROM_DATABASE=RV630 HDMI Audio [Radeon HD 2600 PRO/XT / HD 3610] + +pci:v00001002d0000AA10* + ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350 PRO / 2400 PRO/XT / HD 3410] + +pci:v00001002d0000AA10sv0000174Bsd0000AA10* + ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350 PRO / 2400 PRO/XT / HD 3410] (Radeon HD 2400 PRO) + +pci:v00001002d0000AA10sv000018BCsd0000AA10* + ID_MODEL_FROM_DATABASE=RV610 HDMI Audio [Radeon HD 2350 PRO / 2400 PRO/XT / HD 3410] (Radeon HD 2400 PRO) + +pci:v00001002d0000AA18* + ID_MODEL_FROM_DATABASE=RV670/680 HDMI Audio [Radeon HD 3690/3800 Series] + +pci:v00001002d0000AA20* + ID_MODEL_FROM_DATABASE=RV635 HDMI Audio [Radeon HD 3650/3730/3750] + +pci:v00001002d0000AA28* + ID_MODEL_FROM_DATABASE=RV620 HDMI Audio [Radeon HD 3450/3470/3550/3570] + +pci:v00001002d0000AA30* + ID_MODEL_FROM_DATABASE=RV770 HDMI Audio [Radeon HD 4850/4870] + +pci:v00001002d0000AA30sv0000174Bsd0000AA30* + ID_MODEL_FROM_DATABASE=RV770 HDMI Audio [Radeon HD 4850/4870] (Radeon HD 4850 512MB GDDR3 PCI-E Dual Slot Fansink) + +pci:v00001002d0000AA38* + ID_MODEL_FROM_DATABASE=RV710/730 HDMI Audio [Radeon HD 4000 series] + +pci:v00001002d0000AA38sv0000103Csd00003628* + ID_MODEL_FROM_DATABASE=RV710/730 HDMI Audio [Radeon HD 4000 series] (dv6-1190en) + +pci:v00001002d0000AA50* + ID_MODEL_FROM_DATABASE=Cypress HDMI Audio [Radeon HD 5830/5850/5870 / 6850/6870 Rebrand] + +pci:v00001002d0000AA58* + ID_MODEL_FROM_DATABASE=Juniper HDMI Audio [Radeon HD 5700 Series] + +pci:v00001002d0000AA60* + ID_MODEL_FROM_DATABASE=Redwood HDMI Audio [Radeon HD 5000 Series] + +pci:v00001002d0000AA60sv00001025sd0000033D* + ID_MODEL_FROM_DATABASE=Redwood HDMI Audio [Radeon HD 5000 Series] (Mobility Radeon HD 5650) + +pci:v00001002d0000AA60sv00001025sd00000347* + ID_MODEL_FROM_DATABASE=Redwood HDMI Audio [Radeon HD 5000 Series] (Aspire 7740G) + +pci:v00001002d0000AA68* + ID_MODEL_FROM_DATABASE=Cedar HDMI Audio [Radeon HD 5400/6300/7300 Series] + +pci:v00001002d0000AA68sv00001028sd0000AA68* + ID_MODEL_FROM_DATABASE=Cedar HDMI Audio [Radeon HD 5400/6300/7300 Series] (XPS 8300) + +pci:v00001002d0000AA80* + ID_MODEL_FROM_DATABASE=Cayman/Antilles HDMI Audio [Radeon HD 6930/6950/6970/6990] + +pci:v00001002d0000AA88* + ID_MODEL_FROM_DATABASE=Barts HDMI Audio [Radeon HD 6790/6850/6870 / 7720 OEM] + +pci:v00001002d0000AA90* + ID_MODEL_FROM_DATABASE=Turks HDMI Audio [Radeon HD 6500/6600 / 6700M Series] + +pci:v00001002d0000AA90sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=Turks HDMI Audio [Radeon HD 6500/6600 / 6700M Series] (Precision M4600) + +pci:v00001002d0000AA98* + ID_MODEL_FROM_DATABASE=Caicos HDMI Audio [Radeon HD 6450 / 7450/8450/8490 OEM / R5 230/235/235X OEM] + +pci:v00001002d0000AA98sv0000174Bsd0000AA98* + ID_MODEL_FROM_DATABASE=Caicos HDMI Audio [Radeon HD 6450 / 7450/8450/8490 OEM / R5 230/235/235X OEM] (Radeon HD 6450 1GB DDR3) + +pci:v00001002d0000AAA0* + ID_MODEL_FROM_DATABASE=Tahiti HDMI Audio [Radeon HD 7870 XT / 7950/7970] + +pci:v00001002d0000AAB0* + ID_MODEL_FROM_DATABASE=Oland/Hainan/Cape Verde/Pitcairn HDMI Audio [Radeon HD 7000 Series] + +pci:v00001002d0000AAB8* + ID_MODEL_FROM_DATABASE=Tiran HDMI Audio + +pci:v00001002d0000AAC0* + ID_MODEL_FROM_DATABASE=Tobago HDMI Audio [Radeon R7 360 / R9 360 OEM] + +pci:v00001002d0000AAC8* + ID_MODEL_FROM_DATABASE=Hawaii HDMI Audio [Radeon R9 290/290X / 390/390X] + +pci:v00001002d0000AAD8* + ID_MODEL_FROM_DATABASE=Tonga HDMI Audio [Radeon R9 285/380] + +pci:v00001002d0000AAD8sv0000174Bsd0000AAD8* + ID_MODEL_FROM_DATABASE=Tonga HDMI Audio [Radeon R9 285/380] (Radeon R9 285/380 HDMI Audio) + +pci:v00001002d0000AAE0* + ID_MODEL_FROM_DATABASE=Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] + +pci:v00001002d0000AAE8* + ID_MODEL_FROM_DATABASE=Fiji HDMI/DP Audio [Radeon R9 Nano / FURY/FURY X] + +pci:v00001002d0000AAF0* + ID_MODEL_FROM_DATABASE=Ellesmere HDMI Audio [Radeon RX 470/480 / 570/580/590] + +pci:v00001002d0000AAF8* + ID_MODEL_FROM_DATABASE=Vega 10 HDMI Audio [Radeon Vega 56/64] + +pci:v00001002d0000AB00* + ID_MODEL_FROM_DATABASE=Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] + +pci:v00001002d0000AB08* + ID_MODEL_FROM_DATABASE=Polaris 22 HDMI Audio + +pci:v00001002d0000AB10* + ID_MODEL_FROM_DATABASE=Lexa HDMI Audio + +pci:v00001002d0000AB18* + ID_MODEL_FROM_DATABASE=Vega 12 HDMI Audio + +pci:v00001002d0000AB20* + ID_MODEL_FROM_DATABASE=Vega 20 HDMI Audio [Radeon VII] + +pci:v00001002d0000AB38* + ID_MODEL_FROM_DATABASE=Navi 10 HDMI Audio + +pci:v00001002d0000AC00* + ID_MODEL_FROM_DATABASE=Theater 506 World-Wide Analog Decoder + +pci:v00001002d0000AC01* + ID_MODEL_FROM_DATABASE=Theater 506 World-Wide Analog Decoder + +pci:v00001002d0000AC02* + ID_MODEL_FROM_DATABASE=TV Wonder HD 600 PCIe + +pci:v00001002d0000AC03* + ID_MODEL_FROM_DATABASE=Theater 506 PCIe + +pci:v00001002d0000AC04* + ID_MODEL_FROM_DATABASE=Theater 506 USB + +pci:v00001002d0000AC05* + ID_MODEL_FROM_DATABASE=Theater 506 USB + +pci:v00001002d0000AC06* + ID_MODEL_FROM_DATABASE=Theater 506 External USB + +pci:v00001002d0000AC07* + ID_MODEL_FROM_DATABASE=Theater 506 External USB + +pci:v00001002d0000AC08* + ID_MODEL_FROM_DATABASE=Theater 506A World-Wide Analog Decoder + Demodulator + +pci:v00001002d0000AC09* + ID_MODEL_FROM_DATABASE=Theater 506A World-Wide Analog Decoder + Demodulator + +pci:v00001002d0000AC0A* + ID_MODEL_FROM_DATABASE=Theater 506A PCIe + +pci:v00001002d0000AC0B* + ID_MODEL_FROM_DATABASE=Theater 506A PCIe + +pci:v00001002d0000AC0C* + ID_MODEL_FROM_DATABASE=Theater 506A USB + +pci:v00001002d0000AC0D* + ID_MODEL_FROM_DATABASE=Theater 506A USB + +pci:v00001002d0000AC0E* + ID_MODEL_FROM_DATABASE=Theater 506A External USB + +pci:v00001002d0000AC0F* + ID_MODEL_FROM_DATABASE=Theater 506A External USB + +pci:v00001002d0000AC12* + ID_MODEL_FROM_DATABASE=Theater HD T507 (DVB-T) TV tuner/capture device + +pci:v00001002d0000CAB0* + ID_MODEL_FROM_DATABASE=RS100 Host Bridge + +pci:v00001002d0000CAB2* + ID_MODEL_FROM_DATABASE=RS200 Host Bridge + +pci:v00001002d0000CAB3* + ID_MODEL_FROM_DATABASE=RS250 Host Bridge + +pci:v00001002d0000CBB2* + ID_MODEL_FROM_DATABASE=RS200 Host Bridge + +pci:v00001003* + ID_VENDOR_FROM_DATABASE=ULSI Systems + +pci:v00001003d00000201* + ID_MODEL_FROM_DATABASE=US201 + +pci:v00001004* + ID_VENDOR_FROM_DATABASE=VLSI Technology Inc + +pci:v00001004d00000005* + ID_MODEL_FROM_DATABASE=82C592-FC1 + +pci:v00001004d00000006* + ID_MODEL_FROM_DATABASE=82C593-FC1 + +pci:v00001004d00000007* + ID_MODEL_FROM_DATABASE=82C594-AFC2 + +pci:v00001004d00000008* + ID_MODEL_FROM_DATABASE=82C596/7 [Wildcat] + +pci:v00001004d00000009* + ID_MODEL_FROM_DATABASE=82C597-AFC2 + +pci:v00001004d0000000C* + ID_MODEL_FROM_DATABASE=82C541 [Lynx] + +pci:v00001004d0000000D* + ID_MODEL_FROM_DATABASE=82C543 [Lynx] + +pci:v00001004d00000101* + ID_MODEL_FROM_DATABASE=82C532 + +pci:v00001004d00000102* + ID_MODEL_FROM_DATABASE=82C534 [Eagle] + +pci:v00001004d00000103* + ID_MODEL_FROM_DATABASE=82C538 + +pci:v00001004d00000104* + ID_MODEL_FROM_DATABASE=82C535 + +pci:v00001004d00000105* + ID_MODEL_FROM_DATABASE=82C147 + +pci:v00001004d00000200* + ID_MODEL_FROM_DATABASE=82C975 + +pci:v00001004d00000280* + ID_MODEL_FROM_DATABASE=82C925 + +pci:v00001004d00000304* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio + +pci:v00001004d00000304sv00001004sd00000304* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio + +pci:v00001004d00000304sv0000122Dsd00001206* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio (DSP368 Audio) + +pci:v00001004d00000304sv00001483sd00005020* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio (XWave Thunder 3D Audio) + +pci:v00001004d00000305* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Gameport + +pci:v00001004d00000305sv00001004sd00000305* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Gameport + +pci:v00001004d00000305sv0000122Dsd00001207* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Gameport (DSP368 Audio Gameport) + +pci:v00001004d00000305sv00001483sd00005021* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Gameport (XWave Thunder 3D Audio Gameport) + +pci:v00001004d00000306* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Support Registers + +pci:v00001004d00000306sv00001004sd00000306* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Support Registers + +pci:v00001004d00000306sv0000122Dsd00001208* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Support Registers (DSP368 Audio Support Registers) + +pci:v00001004d00000306sv00001483sd00005022* + ID_MODEL_FROM_DATABASE=QSound ThunderBird PCI Audio Support Registers (XWave Thunder 3D Audio Support Registers) + +pci:v00001004d00000307* + ID_MODEL_FROM_DATABASE=SAA7785 ThunderBird PCI Audio + +pci:v00001004d00000307sv00001004sd00000703* + ID_MODEL_FROM_DATABASE=SAA7785 ThunderBird PCI Audio (Philips Rhythmic Edge PSC703) + +pci:v00001004d00000307sv00001004sd00000705* + ID_MODEL_FROM_DATABASE=SAA7785 ThunderBird PCI Audio (Philips Seismic Edge PSC705) + +pci:v00001004d00000307sv00001004sd00000706* + ID_MODEL_FROM_DATABASE=SAA7785 ThunderBird PCI Audio (Philips Acoustic Edge PSC706) + +pci:v00001004d00000308* + ID_MODEL_FROM_DATABASE=SAA7785 ThunderBird PCI Audio Gameport + +pci:v00001004d00000702* + ID_MODEL_FROM_DATABASE=VAS96011 [Golden Gate II] + +pci:v00001004d00000703* + ID_MODEL_FROM_DATABASE=Tollgate + +pci:v00001005* + ID_VENDOR_FROM_DATABASE=Avance Logic Inc. [ALI] + +pci:v00001005d00002064* + ID_MODEL_FROM_DATABASE=ALG2032/2064 + +pci:v00001005d00002128* + ID_MODEL_FROM_DATABASE=ALG2364A + +pci:v00001005d00002301* + ID_MODEL_FROM_DATABASE=ALG2301 + +pci:v00001005d00002302* + ID_MODEL_FROM_DATABASE=ALG2302 + +pci:v00001005d00002364* + ID_MODEL_FROM_DATABASE=ALG2364 + +pci:v00001005d00002464* + ID_MODEL_FROM_DATABASE=ALG2364A + +pci:v00001005d00002501* + ID_MODEL_FROM_DATABASE=ALG2564A/25128A + +pci:v00001006* + ID_VENDOR_FROM_DATABASE=Reply Group + +pci:v00001007* + ID_VENDOR_FROM_DATABASE=NetFrame Systems Inc + +pci:v00001008* + ID_VENDOR_FROM_DATABASE=Epson + +pci:v0000100A* + ID_VENDOR_FROM_DATABASE=Phoenix Technologies + +pci:v0000100B* + ID_VENDOR_FROM_DATABASE=National Semiconductor Corporation + +pci:v0000100Bd00000001* + ID_MODEL_FROM_DATABASE=DP83810 + +pci:v0000100Bd00000002* + ID_MODEL_FROM_DATABASE=87415/87560 IDE + +pci:v0000100Bd0000000E* + ID_MODEL_FROM_DATABASE=87560 Legacy I/O + +pci:v0000100Bd0000000F* + ID_MODEL_FROM_DATABASE=FireWire Controller + +pci:v0000100Bd00000011* + ID_MODEL_FROM_DATABASE=NS87560 National PCI System I/O + +pci:v0000100Bd00000012* + ID_MODEL_FROM_DATABASE=USB Controller + +pci:v0000100Bd00000020* + ID_MODEL_FROM_DATABASE=DP83815 (MacPhyter) Ethernet Controller + +pci:v0000100Bd00000020sv0000103Csd00000024* + ID_MODEL_FROM_DATABASE=DP83815 (MacPhyter) Ethernet Controller (Pavilion ze4400 builtin Network) + +pci:v0000100Bd00000020sv000012D9sd0000000C* + ID_MODEL_FROM_DATABASE=DP83815 (MacPhyter) Ethernet Controller (Aculab E1/T1 PMXc cPCI carrier card) + +pci:v0000100Bd00000020sv00001385sd0000F311* + ID_MODEL_FROM_DATABASE=DP83815 (MacPhyter) Ethernet Controller (FA311 / FA312 (FA311 with WoL HW)) + +pci:v0000100Bd00000020sv00001385sd0000F312* + ID_MODEL_FROM_DATABASE=DP83815 (MacPhyter) Ethernet Controller (FA312 (rev. A1) Fast Ethernet PCI Adapter) + +pci:v0000100Bd00000021* + ID_MODEL_FROM_DATABASE=PC87200 PCI to ISA Bridge + +pci:v0000100Bd00000022* + ID_MODEL_FROM_DATABASE=DP83820 10/100/1000 Ethernet Controller + +pci:v0000100Bd00000022sv00001186sd00004900* + ID_MODEL_FROM_DATABASE=DP83820 10/100/1000 Ethernet Controller (DGE-500T) + +pci:v0000100Bd00000022sv00001385sd0000621A* + ID_MODEL_FROM_DATABASE=DP83820 10/100/1000 Ethernet Controller (GA621) + +pci:v0000100Bd00000022sv00001385sd0000622A* + ID_MODEL_FROM_DATABASE=DP83820 10/100/1000 Ethernet Controller (GA622T) + +pci:v0000100Bd00000028* + ID_MODEL_FROM_DATABASE=Geode GX2 Host Bridge + +pci:v0000100Bd0000002A* + ID_MODEL_FROM_DATABASE=CS5535 South Bridge + +pci:v0000100Bd0000002B* + ID_MODEL_FROM_DATABASE=CS5535 ISA bridge + +pci:v0000100Bd0000002D* + ID_MODEL_FROM_DATABASE=CS5535 IDE + +pci:v0000100Bd0000002E* + ID_MODEL_FROM_DATABASE=CS5535 Audio + +pci:v0000100Bd0000002F* + ID_MODEL_FROM_DATABASE=CS5535 USB + +pci:v0000100Bd00000030* + ID_MODEL_FROM_DATABASE=Geode GX2 Graphics Processor + +pci:v0000100Bd00000035* + ID_MODEL_FROM_DATABASE=DP83065 [Saturn] 10/100/1000 Ethernet Controller + +pci:v0000100Bd00000500* + ID_MODEL_FROM_DATABASE=SCx200 Bridge + +pci:v0000100Bd00000501* + ID_MODEL_FROM_DATABASE=SCx200 SMI + +pci:v0000100Bd00000502* + ID_MODEL_FROM_DATABASE=SCx200, SC1100 IDE controller + +pci:v0000100Bd00000502sv0000100Bsd00000502* + ID_MODEL_FROM_DATABASE=SCx200, SC1100 IDE controller (IDE Controller) + +pci:v0000100Bd00000503* + ID_MODEL_FROM_DATABASE=SCx200, SC1100 Audio Controller + +pci:v0000100Bd00000503sv0000100Bsd00000503* + ID_MODEL_FROM_DATABASE=SCx200, SC1100 Audio Controller (XpressAudio controller) + +pci:v0000100Bd00000504* + ID_MODEL_FROM_DATABASE=SCx200 Video + +pci:v0000100Bd00000505* + ID_MODEL_FROM_DATABASE=SCx200 XBus + +pci:v0000100Bd00000510* + ID_MODEL_FROM_DATABASE=SC1100 Bridge + +pci:v0000100Bd00000510sv0000100Bsd00000500* + ID_MODEL_FROM_DATABASE=SC1100 Bridge (GPIO and LPC support bridge) + +pci:v0000100Bd00000511* + ID_MODEL_FROM_DATABASE=SC1100 SMI & ACPI + +pci:v0000100Bd00000511sv0000100Bsd00000501* + ID_MODEL_FROM_DATABASE=SC1100 SMI & ACPI (bridge) + +pci:v0000100Bd00000515* + ID_MODEL_FROM_DATABASE=SC1100 XBus + +pci:v0000100Bd00000515sv0000100Bsd00000505* + ID_MODEL_FROM_DATABASE=SC1100 XBus (SC1100 PCI to XBus bridge) + +pci:v0000100Bd0000D001* + ID_MODEL_FROM_DATABASE=87410 IDE + +pci:v0000100C* + ID_VENDOR_FROM_DATABASE=Tseng Labs Inc + +pci:v0000100Cd00003202* + ID_MODEL_FROM_DATABASE=ET4000/W32p rev A + +pci:v0000100Cd00003205* + ID_MODEL_FROM_DATABASE=ET4000/W32p rev B + +pci:v0000100Cd00003206* + ID_MODEL_FROM_DATABASE=ET4000/W32p rev C + +pci:v0000100Cd00003207* + ID_MODEL_FROM_DATABASE=ET4000/W32p rev D + +pci:v0000100Cd00003208* + ID_MODEL_FROM_DATABASE=ET6000 + +pci:v0000100Cd00004702* + ID_MODEL_FROM_DATABASE=ET6300 + +pci:v0000100D* + ID_VENDOR_FROM_DATABASE=AST Research Inc + +pci:v0000100E* + ID_VENDOR_FROM_DATABASE=Weitek + +pci:v0000100Ed00009000* + ID_MODEL_FROM_DATABASE=P9000 Viper + +pci:v0000100Ed00009001* + ID_MODEL_FROM_DATABASE=P9000 Viper + +pci:v0000100Ed00009002* + ID_MODEL_FROM_DATABASE=P9000 Viper + +pci:v0000100Ed00009100* + ID_MODEL_FROM_DATABASE=P9100 Viper Pro/SE + +pci:v00001010* + ID_VENDOR_FROM_DATABASE=Video Logic, Ltd. + +pci:v00001011* + ID_VENDOR_FROM_DATABASE=Digital Equipment Corporation + +pci:v00001011d00000001* + ID_MODEL_FROM_DATABASE=DECchip 21050 + +pci:v00001011d00000002* + ID_MODEL_FROM_DATABASE=DECchip 21040 [Tulip] + +pci:v00001011d00000004* + ID_MODEL_FROM_DATABASE=DECchip 21030 [TGA] + +pci:v00001011d00000007* + ID_MODEL_FROM_DATABASE=NVRAM [Zephyr NVRAM] + +pci:v00001011d00000008* + ID_MODEL_FROM_DATABASE=KZPSA [KZPSA] + +pci:v00001011d00000009* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] + +pci:v00001011d00000009sv00001025sd00000310* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (21140 Fast Ethernet) + +pci:v00001011d00000009sv000010B8sd00002001* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (SMC9332BDT EtherPower 10/100) + +pci:v00001011d00000009sv000010B8sd00002002* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (SMC9332BVT EtherPower T4 10/100) + +pci:v00001011d00000009sv000010B8sd00002003* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (SMC9334BDT EtherPower 10/100 (1-port)) + +pci:v00001011d00000009sv00001109sd00002400* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (ANA-6944A/TX Fast Ethernet) + +pci:v00001011d00000009sv00001112sd00002300* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (RNS2300 Fast Ethernet) + +pci:v00001011d00000009sv00001112sd00002320* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (RNS2320 Fast Ethernet) + +pci:v00001011d00000009sv00001112sd00002340* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (RNS2340 Fast Ethernet) + +pci:v00001011d00000009sv00001113sd00001207* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (EN-1207-TX Fast Ethernet) + +pci:v00001011d00000009sv00001186sd00001100* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (DFE-500TX Fast Ethernet) + +pci:v00001011d00000009sv00001186sd00001112* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (DFE-570TX Fast Ethernet) + +pci:v00001011d00000009sv00001186sd00001140* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (DFE-660 Cardbus Ethernet 10/100) + +pci:v00001011d00000009sv00001186sd00001142* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (DFE-660 Cardbus Ethernet 10/100) + +pci:v00001011d00000009sv000011F6sd00000503* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (Freedomline Fast Ethernet) + +pci:v00001011d00000009sv00001282sd00009100* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (AEF-380TXD Fast Ethernet) + +pci:v00001011d00000009sv00001385sd00001100* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (FA310TX Fast Ethernet) + +pci:v00001011d00000009sv00002646sd00000001* + ID_MODEL_FROM_DATABASE=DECchip 21140 [FasterNet] (KNE100TX Fast Ethernet) + +pci:v00001011d0000000A* + ID_MODEL_FROM_DATABASE=21230 Video Codec + +pci:v00001011d0000000D* + ID_MODEL_FROM_DATABASE=PBXGB [TGA2] + +pci:v00001011d0000000F* + ID_MODEL_FROM_DATABASE=DEFPA FDDI PCI-to-PDQ Interface Chip [PFI] + +pci:v00001011d0000000Fsv00001011sd0000DEF1* + ID_MODEL_FROM_DATABASE=DEFPA FDDI PCI-to-PDQ Interface Chip [PFI] (FDDI controller (DEFPA)) + +pci:v00001011d0000000Fsv0000103Csd0000DEF1* + ID_MODEL_FROM_DATABASE=DEFPA FDDI PCI-to-PDQ Interface Chip [PFI] (FDDI controller (3X-DEFPA)) + +pci:v00001011d00000014* + ID_MODEL_FROM_DATABASE=DECchip 21041 [Tulip Pass 3] + +pci:v00001011d00000014sv00001186sd00000100* + ID_MODEL_FROM_DATABASE=DECchip 21041 [Tulip Pass 3] (DE-530+) + +pci:v00001011d00000016* + ID_MODEL_FROM_DATABASE=DGLPB [OPPO] + +pci:v00001011d00000017* + ID_MODEL_FROM_DATABASE=PV-PCI Graphics Controller (ZLXp-L) + +pci:v00001011d00000018* + ID_MODEL_FROM_DATABASE=Memory Channel interface + +pci:v00001011d00000019* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 + +pci:v00001011d00000019sv00001011sd0000500A* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DE500A Fast Ethernet) + +pci:v00001011d00000019sv00001011sd0000500B* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DE500B Fast Ethernet) + +pci:v00001011d00000019sv00001014sd00000001* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (10/100 EtherJet Cardbus) + +pci:v00001011d00000019sv00001025sd00000315* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (ALN315 Fast Ethernet) + +pci:v00001011d00000019sv00001033sd0000800C* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (PC-9821-CS01 100BASE-TX Interface Card) + +pci:v00001011d00000019sv00001033sd0000800D* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (PC-9821NR-B06 100BASE-TX Interface Card) + +pci:v00001011d00000019sv0000103Csd0000125A* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (10/100Base-TX (PCI) [A5506B]) + +pci:v00001011d00000019sv0000108Dsd00000016* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Rapidfire 2327 10/100 Ethernet) + +pci:v00001011d00000019sv0000108Dsd00000017* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (GoCard 2250 Ethernet 10/100 Cardbus) + +pci:v00001011d00000019sv000010B8sd00002005* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (SMC8032DT Extreme Ethernet 10/100) + +pci:v00001011d00000019sv000010B8sd00008034* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (SMC8034 Extreme Ethernet 10/100) + +pci:v00001011d00000019sv000010EFsd00008169* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Fast Ethernet) + +pci:v00001011d00000019sv00001109sd00002A00* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (ANA-6911A/TX Fast Ethernet) + +pci:v00001011d00000019sv00001109sd00002B00* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (ANA-6911A/TXC Fast Ethernet) + +pci:v00001011d00000019sv00001109sd00003000* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (ANA-6922/TX Fast Ethernet) + +pci:v00001011d00000019sv00001113sd00001207* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cheetah Fast Ethernet) + +pci:v00001011d00000019sv00001113sd00002220* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Fast Ethernet) + +pci:v00001011d00000019sv0000115Dsd00000002* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Ethernet 10/100) + +pci:v00001011d00000019sv00001179sd00000203* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Fast Ethernet) + +pci:v00001011d00000019sv00001179sd00000204* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Fast Ethernet) + +pci:v00001011d00000019sv00001186sd00001100* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DFE-500TX Fast Ethernet) + +pci:v00001011d00000019sv00001186sd00001101* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DFE-500TX Fast Ethernet) + +pci:v00001011d00000019sv00001186sd00001102* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DFE-500TX Fast Ethernet) + +pci:v00001011d00000019sv00001186sd00001112* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (DFE-570TX Quad Fast Ethernet) + +pci:v00001011d00000019sv000011F0sd00004235* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (21143 [FASTLine-II UTP 10/100]) + +pci:v00001011d00000019sv00001259sd00002800* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (AT-2800Tx Fast Ethernet) + +pci:v00001011d00000019sv00001266sd00000004* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Eagle Fast EtherMAX) + +pci:v00001011d00000019sv000012AFsd00000019* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (NetFlyer Cardbus Fast Ethernet) + +pci:v00001011d00000019sv00001374sd00000001* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Ethernet Card 10/100) + +pci:v00001011d00000019sv00001374sd00000002* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Ethernet Card 10/100) + +pci:v00001011d00000019sv00001374sd00000007* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Ethernet Card 10/100) + +pci:v00001011d00000019sv00001374sd00000008* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (Cardbus Ethernet Card 10/100) + +pci:v00001011d00000019sv00001385sd00002100* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (FA510) + +pci:v00001011d00000019sv00001395sd00000001* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (10/100 Ethernet CardBus PC Card) + +pci:v00001011d00000019sv000013D1sd0000AB01* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (EtherFast 10/100 Cardbus (PCMPC200)) + +pci:v00001011d00000019sv00001498sd0000000A* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (TPMC880-10 10/100Base-T and 10Base2 PMC Ethernet Adapter) + +pci:v00001011d00000019sv00001498sd0000000B* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (TPMC880-11 Single 10/100Base-T PMC Ethernet Adapter) + +pci:v00001011d00000019sv00001498sd0000000C* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (TPMC880-12 Single 10Base2 PMC Ethernet Adapter) + +pci:v00001011d00000019sv000014CBsd00000100* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (LNDL-100N 100Base-TX Ethernet PC Card) + +pci:v00001011d00000019sv00001668sd00002000* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (FastNet Pro (PE2000)) + +pci:v00001011d00000019sv00002646sd00000001* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (KNE100TX) + +pci:v00001011d00000019sv00002646sd00000002* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (KNE-CB4TX) + +pci:v00001011d00000019sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=DECchip 21142/43 (EtherExpress PRO/100 Mobile CardBus 32) + +pci:v00001011d0000001A* + ID_MODEL_FROM_DATABASE=Farallon PN9000SX Gigabit Ethernet + +pci:v00001011d00000021* + ID_MODEL_FROM_DATABASE=DECchip 21052 + +pci:v00001011d00000022* + ID_MODEL_FROM_DATABASE=DECchip 21150 + +pci:v00001011d00000023* + ID_MODEL_FROM_DATABASE=DECchip 21150 + +pci:v00001011d00000024* + ID_MODEL_FROM_DATABASE=DECchip 21152 + +pci:v00001011d00000025* + ID_MODEL_FROM_DATABASE=DECchip 21153 + +pci:v00001011d00000026* + ID_MODEL_FROM_DATABASE=DECchip 21154 + +pci:v00001011d00000034* + ID_MODEL_FROM_DATABASE=56k Modem Cardbus + +pci:v00001011d00000034sv00001374sd00000003* + ID_MODEL_FROM_DATABASE=56k Modem Cardbus + +pci:v00001011d00000045* + ID_MODEL_FROM_DATABASE=DECchip 21553 + +pci:v00001011d00000046* + ID_MODEL_FROM_DATABASE=DECchip 21554 + +pci:v00001011d00000046sv00000E11sd00004050* + ID_MODEL_FROM_DATABASE=DECchip 21554 (Smart Array 4200 Controller) + +pci:v00001011d00000046sv00000E11sd00004051* + ID_MODEL_FROM_DATABASE=DECchip 21554 (Smart Array 4250ES Controller) + +pci:v00001011d00000046sv00000E11sd00004058* + ID_MODEL_FROM_DATABASE=DECchip 21554 (Smart Array 431 Controller) + +pci:v00001011d00000046sv0000103Csd000010C2* + ID_MODEL_FROM_DATABASE=DECchip 21554 (NetRAID-4M) + +pci:v00001011d00000046sv000012D9sd0000000A* + ID_MODEL_FROM_DATABASE=DECchip 21554 (IP Telephony card) + +pci:v00001011d00000046sv00004C53sd00001050* + ID_MODEL_FROM_DATABASE=DECchip 21554 (CT7 mainboard) + +pci:v00001011d00000046sv00004C53sd00001051* + ID_MODEL_FROM_DATABASE=DECchip 21554 (CE7 mainboard) + +pci:v00001011d00000046sv00009005sd00000364* + ID_MODEL_FROM_DATABASE=DECchip 21554 (5400S (Mustang)) + +pci:v00001011d00000046sv00009005sd00000365* + ID_MODEL_FROM_DATABASE=DECchip 21554 (5400S (Mustang)) + +pci:v00001011d00000046sv00009005sd00001364* + ID_MODEL_FROM_DATABASE=DECchip 21554 (Dell PowerEdge RAID Controller 2) + +pci:v00001011d00000046sv00009005sd00001365* + ID_MODEL_FROM_DATABASE=DECchip 21554 (Dell PowerEdge RAID Controller 2) + +pci:v00001011d00000046sv0000E4BFsd00001000* + ID_MODEL_FROM_DATABASE=DECchip 21554 (CC8-1-BLUES) + +pci:v00001011d00001065* + ID_MODEL_FROM_DATABASE=StrongARM DC21285 + +pci:v00001011d00001065sv00001069sd00000020* + ID_MODEL_FROM_DATABASE=StrongARM DC21285 (DAC960P / DAC1164P) + +pci:v00001012* + ID_VENDOR_FROM_DATABASE=Micronics Computers Inc + +pci:v00001013* + ID_VENDOR_FROM_DATABASE=Cirrus Logic + +pci:v00001013d00000038* + ID_MODEL_FROM_DATABASE=GD 7548 + +pci:v00001013d00000040* + ID_MODEL_FROM_DATABASE=GD 7555 Flat Panel GUI Accelerator + +pci:v00001013d0000004C* + ID_MODEL_FROM_DATABASE=GD 7556 Video/Graphics LCD/CRT Ctrlr + +pci:v00001013d000000A0* + ID_MODEL_FROM_DATABASE=GD 5430/40 [Alpine] + +pci:v00001013d000000A2* + ID_MODEL_FROM_DATABASE=GD 5432 [Alpine] + +pci:v00001013d000000A4* + ID_MODEL_FROM_DATABASE=GD 5434-4 [Alpine] + +pci:v00001013d000000A8* + ID_MODEL_FROM_DATABASE=GD 5434-8 [Alpine] + +pci:v00001013d000000AC* + ID_MODEL_FROM_DATABASE=GD 5436 [Alpine] + +pci:v00001013d000000B0* + ID_MODEL_FROM_DATABASE=GD 5440 + +pci:v00001013d000000B8* + ID_MODEL_FROM_DATABASE=GD 5446 + +pci:v00001013d000000B8sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=GD 5446 (QEMU Virtual Machine) + +pci:v00001013d000000BC* + ID_MODEL_FROM_DATABASE=GD 5480 + +pci:v00001013d000000BCsv00001013sd000000BC* + ID_MODEL_FROM_DATABASE=GD 5480 (CL-GD5480) + +pci:v00001013d000000D0* + ID_MODEL_FROM_DATABASE=GD 5462 + +pci:v00001013d000000D2* + ID_MODEL_FROM_DATABASE=GD 5462 [Laguna I] + +pci:v00001013d000000D4* + ID_MODEL_FROM_DATABASE=GD 5464 [Laguna] + +pci:v00001013d000000D5* + ID_MODEL_FROM_DATABASE=GD 5464 BD [Laguna] + +pci:v00001013d000000D6* + ID_MODEL_FROM_DATABASE=GD 5465 [Laguna] + +pci:v00001013d000000D6sv000013CEsd00008031* + ID_MODEL_FROM_DATABASE=GD 5465 [Laguna] (Barco Metheus 2 Megapixel, Dual Head) + +pci:v00001013d000000D6sv000013CFsd00008031* + ID_MODEL_FROM_DATABASE=GD 5465 [Laguna] (Barco Metheus 2 Megapixel, Dual Head) + +pci:v00001013d000000E8* + ID_MODEL_FROM_DATABASE=GD 5436U + +pci:v00001013d00001100* + ID_MODEL_FROM_DATABASE=CL 6729 + +pci:v00001013d00001110* + ID_MODEL_FROM_DATABASE=PD 6832 PCMCIA/CardBus Ctrlr + +pci:v00001013d00001112* + ID_MODEL_FROM_DATABASE=PD 6834 PCMCIA/CardBus Ctrlr + +pci:v00001013d00001113* + ID_MODEL_FROM_DATABASE=PD 6833 PCMCIA/CardBus Ctrlr + +pci:v00001013d00001200* + ID_MODEL_FROM_DATABASE=GD 7542 [Nordic] + +pci:v00001013d00001202* + ID_MODEL_FROM_DATABASE=GD 7543 [Viking] + +pci:v00001013d00001204* + ID_MODEL_FROM_DATABASE=GD 7541 [Nordic Light] + +pci:v00001013d00004000* + ID_MODEL_FROM_DATABASE=MD 5620 [CLM Data Fax Voice] + +pci:v00001013d00004400* + ID_MODEL_FROM_DATABASE=CD 4400 + +pci:v00001013d00006001* + ID_MODEL_FROM_DATABASE=CS 4610/11 [CrystalClear SoundFusion Audio Accelerator] + +pci:v00001013d00006001sv00001014sd00001010* + ID_MODEL_FROM_DATABASE=CS 4610/11 [CrystalClear SoundFusion Audio Accelerator] (CS4610 SoundFusion Audio Accelerator) + +pci:v00001013d00006003* + ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] + +pci:v00001013d00006003sv00001013sd00004280* + ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (Crystal SoundFusion PCI Audio Accelerator) + +pci:v00001013d00006003sv00001014sd00000153* + ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (ThinkPad 600X/A20m) + +pci:v00001013d00006003sv0000153Bsd0000112E* + ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (DMX XFire 1024) + +pci:v00001013d00006003sv0000153Bsd00001136* + ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (SiXPack 5.1+) + +pci:v00001013d00006003sv00001681sd00000050* + ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (Game Theater XP) + +pci:v00001013d00006003sv00001681sd0000A010* + ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (Gamesurround Fortissimo II) + +pci:v00001013d00006003sv00001681sd0000A011* + ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (Gamesurround Fortissimo III 7.1) + +pci:v00001013d00006003sv00005053sd00003357* + ID_MODEL_FROM_DATABASE=CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] (Santa Cruz) + +pci:v00001013d00006004* + ID_MODEL_FROM_DATABASE=CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator] + +pci:v00001013d00006005* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001013d00006005sv00001013sd00004281* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001013d00006005sv000010CFsd000010A8* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001013d00006005sv000010CFsd000010A9* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001013d00006005sv000010CFsd000010AA* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001013d00006005sv000010CFsd000010AB* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001013d00006005sv000010CFsd000010AC* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001013d00006005sv000010CFsd000010AD* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001013d00006005sv000010CFsd000010B4* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001013d00006005sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001013d00006005sv000014C0sd0000000C* + ID_MODEL_FROM_DATABASE=Crystal CS4281 PCI Audio + +pci:v00001014* + ID_VENDOR_FROM_DATABASE=IBM + +pci:v00001014d00000002* + ID_MODEL_FROM_DATABASE=PCI to MCA Bridge + +pci:v00001014d00000005* + ID_MODEL_FROM_DATABASE=Processor to I/O Controller [Alta Lite] + +pci:v00001014d00000007* + ID_MODEL_FROM_DATABASE=Processor to I/O Controller [Alta MP] + +pci:v00001014d0000000A* + ID_MODEL_FROM_DATABASE=PCI to ISA Bridge (IBM27-82376) [Fire Coral] + +pci:v00001014d00000017* + ID_MODEL_FROM_DATABASE=CPU to PCI Bridge + +pci:v00001014d00000018* + ID_MODEL_FROM_DATABASE=TR Auto LANstreamer + +pci:v00001014d0000001B* + ID_MODEL_FROM_DATABASE=GXT-150P + +pci:v00001014d0000001C* + ID_MODEL_FROM_DATABASE=Carrera + +pci:v00001014d0000001D* + ID_MODEL_FROM_DATABASE=SCSI-2 FAST PCI Adapter (82G2675) + +pci:v00001014d00000020* + ID_MODEL_FROM_DATABASE=GXT1000 Graphics Adapter + +pci:v00001014d00000022* + ID_MODEL_FROM_DATABASE=PCI to PCI Bridge (IBM27-82351) + +pci:v00001014d0000002D* + ID_MODEL_FROM_DATABASE=Processor to I/O Controller [Python] + +pci:v00001014d0000002E* + ID_MODEL_FROM_DATABASE=SCSI RAID Adapter [ServeRAID] + +pci:v00001014d0000002Esv00001014sd0000002E* + ID_MODEL_FROM_DATABASE=SCSI RAID Adapter [ServeRAID] (ServeRAID-3x) + +pci:v00001014d0000002Esv00001014sd0000022E* + ID_MODEL_FROM_DATABASE=SCSI RAID Adapter [ServeRAID] (ServeRAID-4H) + +pci:v00001014d00000031* + ID_MODEL_FROM_DATABASE=2 Port Serial Adapter + +pci:v00001014d00000031sv00001014sd00000031* + ID_MODEL_FROM_DATABASE=2 Port Serial Adapter (2721 WAN IOA - 2 Port Sync Serial Adapter) + +pci:v00001014d00000036* + ID_MODEL_FROM_DATABASE=PCI to 32-bit LocalBus Bridge [Miami] + +pci:v00001014d00000037* + ID_MODEL_FROM_DATABASE=PowerPC to PCI Bridge (IBM27-82660) + +pci:v00001014d0000003A* + ID_MODEL_FROM_DATABASE=CPU to PCI Bridge + +pci:v00001014d0000003C* + ID_MODEL_FROM_DATABASE=GXT250P/GXT255P Graphics Adapter + +pci:v00001014d0000003E* + ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller + +pci:v00001014d0000003Esv00001014sd0000003E* + ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (Token-Ring Adapter) + +pci:v00001014d0000003Esv00001014sd000000CD* + ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (Token-Ring Adapter + Wake-On-LAN) + +pci:v00001014d0000003Esv00001014sd000000CE* + ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (16/4 Token-Ring Adapter 2) + +pci:v00001014d0000003Esv00001014sd000000CF* + ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (16/4 Token-Ring Adapter Special) + +pci:v00001014d0000003Esv00001014sd000000E4* + ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (High-Speed 100/16/4 Token-Ring Adapter) + +pci:v00001014d0000003Esv00001014sd000000E5* + ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (16/4 Token-Ring Adapter 2 + Wake-On-LAN) + +pci:v00001014d0000003Esv00001014sd0000016D* + ID_MODEL_FROM_DATABASE=16/4 Token ring UTP/STP controller (iSeries 2744 Card) + +pci:v00001014d00000045* + ID_MODEL_FROM_DATABASE=SSA Adapter + +pci:v00001014d00000046* + ID_MODEL_FROM_DATABASE=MPIC interrupt controller + +pci:v00001014d00000047* + ID_MODEL_FROM_DATABASE=PCI to PCI Bridge + +pci:v00001014d00000048* + ID_MODEL_FROM_DATABASE=PCI to PCI Bridge + +pci:v00001014d00000049* + ID_MODEL_FROM_DATABASE=Warhead SCSI Controller + +pci:v00001014d0000004E* + ID_MODEL_FROM_DATABASE=ATM Controller (14104e00) + +pci:v00001014d0000004F* + ID_MODEL_FROM_DATABASE=ATM Controller (14104f00) + +pci:v00001014d00000050* + ID_MODEL_FROM_DATABASE=ATM Controller (14105000) + +pci:v00001014d00000053* + ID_MODEL_FROM_DATABASE=25 MBit ATM Controller + +pci:v00001014d00000054* + ID_MODEL_FROM_DATABASE=GXT500P/GXT550P Graphics Adapter + +pci:v00001014d00000057* + ID_MODEL_FROM_DATABASE=MPEG PCI Bridge + +pci:v00001014d00000058* + ID_MODEL_FROM_DATABASE=SSA Adapter [Advanced SerialRAID/X] + +pci:v00001014d0000005E* + ID_MODEL_FROM_DATABASE=GXT800P Graphics Adapter + +pci:v00001014d0000007C* + ID_MODEL_FROM_DATABASE=ATM Controller (14107c00) + +pci:v00001014d0000007D* + ID_MODEL_FROM_DATABASE=3780IDSP [MWave] + +pci:v00001014d0000008B* + ID_MODEL_FROM_DATABASE=EADS PCI to PCI Bridge + +pci:v00001014d0000008E* + ID_MODEL_FROM_DATABASE=GXT3000P Graphics Adapter + +pci:v00001014d00000090* + ID_MODEL_FROM_DATABASE=GXT 3000P + +pci:v00001014d00000090sv00001014sd0000008E* + ID_MODEL_FROM_DATABASE=GXT 3000P (GXT-3000P) + +pci:v00001014d00000091* + ID_MODEL_FROM_DATABASE=SSA Adapter + +pci:v00001014d00000095* + ID_MODEL_FROM_DATABASE=20H2999 PCI Docking Bridge + +pci:v00001014d00000096* + ID_MODEL_FROM_DATABASE=Chukar chipset SCSI controller + +pci:v00001014d00000096sv00001014sd00000097* + ID_MODEL_FROM_DATABASE=Chukar chipset SCSI controller (iSeries 2778 DASD IOA) + +pci:v00001014d00000096sv00001014sd00000098* + ID_MODEL_FROM_DATABASE=Chukar chipset SCSI controller (iSeries 2763 DASD IOA) + +pci:v00001014d00000096sv00001014sd00000099* + ID_MODEL_FROM_DATABASE=Chukar chipset SCSI controller (iSeries 2748 DASD IOA) + +pci:v00001014d0000009F* + ID_MODEL_FROM_DATABASE=PCI 4758 Cryptographic Accelerator + +pci:v00001014d000000A5* + ID_MODEL_FROM_DATABASE=ATM Controller (1410a500) + +pci:v00001014d000000A6* + ID_MODEL_FROM_DATABASE=ATM 155MBPS MM Controller (1410a600) + +pci:v00001014d000000B7* + ID_MODEL_FROM_DATABASE=GXT2000P Graphics Adapter + +pci:v00001014d000000B7sv00001092sd000000B8* + ID_MODEL_FROM_DATABASE=GXT2000P Graphics Adapter (FireGL1 AGP 32Mb) + +pci:v00001014d000000B8* + ID_MODEL_FROM_DATABASE=GXT2000P Graphics Adapter + +pci:v00001014d000000BE* + ID_MODEL_FROM_DATABASE=ATM 622MBPS Controller (1410be00) + +pci:v00001014d000000DC* + ID_MODEL_FROM_DATABASE=Advanced Systems Management Adapter (ASMA) + +pci:v00001014d000000FC* + ID_MODEL_FROM_DATABASE=CPC710 Dual Bridge and Memory Controller (PCI-64) + +pci:v00001014d00000105* + ID_MODEL_FROM_DATABASE=CPC710 Dual Bridge and Memory Controller (PCI-32) + +pci:v00001014d0000010F* + ID_MODEL_FROM_DATABASE=Remote Supervisor Adapter (RSA) + +pci:v00001014d00000142* + ID_MODEL_FROM_DATABASE=Yotta Video Compositor Input + +pci:v00001014d00000142sv00001014sd00000143* + ID_MODEL_FROM_DATABASE=Yotta Video Compositor Input (Yotta Input Controller (ytin)) + +pci:v00001014d00000144* + ID_MODEL_FROM_DATABASE=Yotta Video Compositor Output + +pci:v00001014d00000144sv00001014sd00000145* + ID_MODEL_FROM_DATABASE=Yotta Video Compositor Output (Yotta Output Controller (ytout)) + +pci:v00001014d00000156* + ID_MODEL_FROM_DATABASE=405GP PLB to PCI Bridge + +pci:v00001014d0000015E* + ID_MODEL_FROM_DATABASE=622Mbps ATM PCI Adapter + +pci:v00001014d00000160* + ID_MODEL_FROM_DATABASE=64bit/66MHz PCI ATM 155 MMF + +pci:v00001014d0000016E* + ID_MODEL_FROM_DATABASE=GXT4000P Graphics Adapter + +pci:v00001014d00000170* + ID_MODEL_FROM_DATABASE=GXT6000P Graphics Adapter + +pci:v00001014d00000170sv00001092sd00000172* + ID_MODEL_FROM_DATABASE=GXT6000P Graphics Adapter (Fire GL2) + +pci:v00001014d00000170sv00001092sd00000173* + ID_MODEL_FROM_DATABASE=GXT6000P Graphics Adapter (Fire GL3) + +pci:v00001014d00000170sv00001092sd00000174* + ID_MODEL_FROM_DATABASE=GXT6000P Graphics Adapter (Fire GL4) + +pci:v00001014d00000170sv00001092sd00000184* + ID_MODEL_FROM_DATABASE=GXT6000P Graphics Adapter (Fire GL4s) + +pci:v00001014d0000017D* + ID_MODEL_FROM_DATABASE=GXT300P Graphics Adapter + +pci:v00001014d00000180* + ID_MODEL_FROM_DATABASE=Snipe chipset SCSI controller + +pci:v00001014d00000180sv00001014sd00000241* + ID_MODEL_FROM_DATABASE=Snipe chipset SCSI controller (iSeries 2757 DASD IOA) + +pci:v00001014d00000180sv00001014sd00000264* + ID_MODEL_FROM_DATABASE=Snipe chipset SCSI controller (Quad Channel PCI-X U320 SCSI RAID Adapter (2780)) + +pci:v00001014d00000188* + ID_MODEL_FROM_DATABASE=EADS-X PCI-X to PCI-X Bridge + +pci:v00001014d000001A7* + ID_MODEL_FROM_DATABASE=PCI-X to PCI-X Bridge + +pci:v00001014d000001BD* + ID_MODEL_FROM_DATABASE=ServeRAID Controller + +pci:v00001014d000001BDsv00001014sd000001BD* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID 4Lx) + +pci:v00001014d000001BDsv00001014sd000001BE* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-4M) + +pci:v00001014d000001BDsv00001014sd000001BF* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-4L) + +pci:v00001014d000001BDsv00001014sd00000208* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-4Mx) + +pci:v00001014d000001BDsv00001014sd0000020E* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-4Lx) + +pci:v00001014d000001BDsv00001014sd0000022E* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-4H) + +pci:v00001014d000001BDsv00001014sd00000258* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-5i) + +pci:v00001014d000001BDsv00001014sd00000259* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID-5i) + +pci:v00001014d000001C1* + ID_MODEL_FROM_DATABASE=64bit/66MHz PCI ATM 155 UTP + +pci:v00001014d000001E6* + ID_MODEL_FROM_DATABASE=Cryptographic Accelerator + +pci:v00001014d000001EF* + ID_MODEL_FROM_DATABASE=PowerPC 440GP PCI Bridge + +pci:v00001014d000001EFsv00001734sd0000102B* + ID_MODEL_FROM_DATABASE=PowerPC 440GP PCI Bridge (PCEAS PCI-X Dual Port ESCON Adapter) + +pci:v00001014d000001EFsv00001734sd000010F8* + ID_MODEL_FROM_DATABASE=PowerPC 440GP PCI Bridge (PCEAT PCI-Express Dual Port ESCON Adapter) + +pci:v00001014d000001FF* + ID_MODEL_FROM_DATABASE=10/100 Mbps Ethernet + +pci:v00001014d00000219* + ID_MODEL_FROM_DATABASE=Multiport Serial Adapter + +pci:v00001014d00000219sv00001014sd0000021A* + ID_MODEL_FROM_DATABASE=Multiport Serial Adapter (Dual RVX) + +pci:v00001014d00000219sv00001014sd00000251* + ID_MODEL_FROM_DATABASE=Multiport Serial Adapter (Internal Modem/RVX) + +pci:v00001014d00000219sv00001014sd00000252* + ID_MODEL_FROM_DATABASE=Multiport Serial Adapter (Quad Internal Modem) + +pci:v00001014d0000021B* + ID_MODEL_FROM_DATABASE=GXT6500P Graphics Adapter + +pci:v00001014d0000021C* + ID_MODEL_FROM_DATABASE=GXT4500P Graphics Adapter + +pci:v00001014d00000233* + ID_MODEL_FROM_DATABASE=GXT135P Graphics Adapter + +pci:v00001014d0000028C* + ID_MODEL_FROM_DATABASE=Citrine chipset SCSI controller + +pci:v00001014d0000028Csv00001014sd0000028D* + ID_MODEL_FROM_DATABASE=Citrine chipset SCSI controller (Dual Channel PCI-X DDR SAS RAID Adapter (572E)) + +pci:v00001014d0000028Csv00001014sd000002BE* + ID_MODEL_FROM_DATABASE=Citrine chipset SCSI controller (Dual Channel PCI-X DDR U320 SCSI RAID Adapter (571B)) + +pci:v00001014d0000028Csv00001014sd000002C0* + ID_MODEL_FROM_DATABASE=Citrine chipset SCSI controller (Dual Channel PCI-X DDR U320 SCSI Adapter (571A)) + +pci:v00001014d0000028Csv00001014sd0000030D* + ID_MODEL_FROM_DATABASE=Citrine chipset SCSI controller (PCI-X DDR Auxiliary Cache Adapter (575B)) + +pci:v00001014d000002A1* + ID_MODEL_FROM_DATABASE=Calgary PCI-X Host Bridge + +pci:v00001014d000002BD* + ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller + +pci:v00001014d000002BDsv00001014sd000002C1* + ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller (PCI-X DDR 3Gb SAS Adapter (572A/572C)) + +pci:v00001014d000002BDsv00001014sd000002C2* + ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller (PCI-X DDR 3Gb SAS RAID Adapter (572B/571D)) + +pci:v00001014d000002BDsv00001014sd00000338* + ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller (PCI-X DDR Auxiliary Cache Adapter (575C)) + +pci:v00001014d00000302* + ID_MODEL_FROM_DATABASE=Winnipeg PCI-X Host Bridge + +pci:v00001014d00000308* + ID_MODEL_FROM_DATABASE=CalIOC2 PCI-E Root Port + +pci:v00001014d00000311* + ID_MODEL_FROM_DATABASE=FC 5740/1954 4-Port 10/100/1000 Base-TX PCI-X Adapter for POWER + +pci:v00001014d00000314* + ID_MODEL_FROM_DATABASE=ZISC 036 Neural accelerator card + +pci:v00001014d0000032D* + ID_MODEL_FROM_DATABASE=Axon - Cell Companion Chip + +pci:v00001014d0000032Dsv00001014sd000003A1* + ID_MODEL_FROM_DATABASE=Axon - Cell Companion Chip (PCIe PowerXCell 8i Cell Accelerator Board) + +pci:v00001014d00000339* + ID_MODEL_FROM_DATABASE=Obsidian-E PCI-E SCSI controller + +pci:v00001014d00000339sv00001014sd0000030A* + ID_MODEL_FROM_DATABASE=Obsidian-E PCI-E SCSI controller (PCIe 3Gb SAS RAID Adapter (574E)) + +pci:v00001014d00000339sv00001014sd0000033A* + ID_MODEL_FROM_DATABASE=Obsidian-E PCI-E SCSI controller (PCIe 3Gb SAS Adapter (57B3)) + +pci:v00001014d00000339sv00001014sd0000035C* + ID_MODEL_FROM_DATABASE=Obsidian-E PCI-E SCSI controller (PCIe x8 Internal 3Gb SAS adapter (57CC)) + +pci:v00001014d00000339sv00001014sd00000360* + ID_MODEL_FROM_DATABASE=Obsidian-E PCI-E SCSI controller (PCI-E Auxiliary Cache Adapter (57B7)) + +pci:v00001014d0000033D* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) + +pci:v00001014d0000033Dsv00001014sd0000033C* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) (PCIe2 1.8GB Cache 6Gb SAS RAID Adapter Tri-port (57B5)) + +pci:v00001014d0000033Dsv00001014sd00000353* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) (PCIe2 3.1GB Cache 6Gb SAS RAID Enclosure (57C3)) + +pci:v00001014d0000033Dsv00001014sd00000354* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) (PCIe2 6Gb SAS Adapter Dual-port (57C4)) + +pci:v00001014d0000033Dsv00001014sd00000356* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) (PCIe2 1.8GB Cache 6Gb SAS RAID & SSD Adapter (574D)) + +pci:v00001014d0000033Dsv00001014sd0000035F* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (FPGA) (PCIe2 6Gb SAS Adapter Quad-port (57B2)) + +pci:v00001014d0000034A* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) + +pci:v00001014d0000034Asv00001014sd0000033B* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe2 6Gb SAS RAID Adapter Quad-port (57B4)) + +pci:v00001014d0000034Asv00001014sd00000355* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe2 3.6GB Cache 6Gb SAS RAID Adapter Quad-port (57B1)) + +pci:v00001014d0000034Asv00001014sd00000357* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe2 6Gb SAS Adapter Quad-port (57C6)) + +pci:v00001014d0000034Asv00001014sd0000035D* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 1.8GB Cache RAID SAS Adapter Quad-port 6GB (57C8)) + +pci:v00001014d0000034Asv00001014sd0000035E* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe2 3.6GB Cache 6Gb SAS RAID Adapter Quad-port (57CE)) + +pci:v00001014d0000034Asv00001014sd000003FB* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 28GB Cache RAID SAS Enclosure 6Gb x 16 (57D5)) + +pci:v00001014d0000034Asv00001014sd000003FE* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x8 Cache SAS RAID Internal Adapter 6Gb (57D8)) + +pci:v00001014d0000034Asv00001014sd000003FF* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x8 SAS RAID Internal Adapter 6Gb (57D7)) + +pci:v00001014d0000034Asv00001014sd00000474* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x16 Cache SAS RAID Internal Adapter 6Gb (57EB)) + +pci:v00001014d0000034Asv00001014sd00000475* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x16 SAS RAID Internal Adapter 6Gb (57EC)) + +pci:v00001014d0000034Asv00001014sd00000499* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x16 Cache SAS RAID Internal Adapter 6Gb (57ED)) + +pci:v00001014d0000034Asv00001014sd0000049A* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x16 SAS RAID Internal Adapter 6Gb (57EE)) + +pci:v00001014d0000034Asv00001014sd000004C7* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCA)) + +pci:v00001014d0000034Asv00001014sd000004C8* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CD2)) + +pci:v00001014d0000034Asv00001014sd000004C9* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS Adapter (ASIC) (PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCD)) + +pci:v00001014d000003DC* + ID_MODEL_FROM_DATABASE=POWER8 Host Bridge (PHB3) + +pci:v00001014d0000044B* + ID_MODEL_FROM_DATABASE=GenWQE Accelerator Adapter + +pci:v00001014d000004AA* + ID_MODEL_FROM_DATABASE=Flash Adapter 90 (PCIe2 0.9TB) + +pci:v00001014d000004C1* + ID_MODEL_FROM_DATABASE=POWER9 Host Bridge (PHB4) + +pci:v00001014d000004DA* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS+ Adapter (ASIC) + +pci:v00001014d000004DAsv00001014sd000004FB* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS+ Adapter (ASIC) (PCIe3 x16 20GB Cache 12Gb Quad SAS RAID+ Adapter(580B)) + +pci:v00001014d000004DAsv00001014sd000004FC* + ID_MODEL_FROM_DATABASE=PCI-E IPR SAS+ Adapter (ASIC) (PCIe3 x8 12Gb Quad SAS RAID+ Adapter(580A)) + +pci:v00001014d000004ED* + ID_MODEL_FROM_DATABASE=Internal Shared Memory (ISM) virtual PCI device + +pci:v00001014d00003022* + ID_MODEL_FROM_DATABASE=QLA3022 Network Adapter + +pci:v00001014d00004022* + ID_MODEL_FROM_DATABASE=QLA3022 Network Adapter + +pci:v00001014d0000FFFF* + ID_MODEL_FROM_DATABASE=MPIC-2 interrupt controller + +pci:v00001015* + ID_VENDOR_FROM_DATABASE=LSI Logic Corp of Canada + +pci:v00001016* + ID_VENDOR_FROM_DATABASE=ICL Personal Systems + +pci:v00001017* + ID_VENDOR_FROM_DATABASE=SPEA Software AG + +pci:v00001017d00005343* + ID_MODEL_FROM_DATABASE=SPEA 3D Accelerator + +pci:v00001018* + ID_VENDOR_FROM_DATABASE=Unisys Systems + +pci:v00001019* + ID_VENDOR_FROM_DATABASE=Elitegroup Computer Systems + +pci:v0000101A* + ID_VENDOR_FROM_DATABASE=AT&T GIS (NCR) + +pci:v0000101Ad00000005* + ID_MODEL_FROM_DATABASE=100VG ethernet + +pci:v0000101Ad00000007* + ID_MODEL_FROM_DATABASE=BYNET BIC4G/2C/2G + +pci:v0000101Ad00000007sv0000101Asd00000019* + ID_MODEL_FROM_DATABASE=BYNET BIC4G/2C/2G (BYNET BIC2C) + +pci:v0000101Ad00000007sv0000101Asd0000001C* + ID_MODEL_FROM_DATABASE=BYNET BIC4G/2C/2G (BYNET BIC2G) + +pci:v0000101Ad00000007sv0000101Asd0000001F* + ID_MODEL_FROM_DATABASE=BYNET BIC4G/2C/2G (BYNET BIC4G) + +pci:v0000101Ad00000009* + ID_MODEL_FROM_DATABASE=PQS Memory Controller + +pci:v0000101Ad0000000A* + ID_MODEL_FROM_DATABASE=BYNET BPCI Adapter + +pci:v0000101Ad0000000B* + ID_MODEL_FROM_DATABASE=BYNET 4 Port BYA Switch (BYA4P) + +pci:v0000101Ad0000000C* + ID_MODEL_FROM_DATABASE=BYNET 4 Port BYA Switch (BYA4G) + +pci:v0000101Ad00000010* + ID_MODEL_FROM_DATABASE=NCR AMC Memory Controller + +pci:v0000101Ad00001DC1* + ID_MODEL_FROM_DATABASE=BYNET BIC2M/BIC4M/BYA4M + +pci:v0000101Ad00001DC1sv0000101Asd00000019* + ID_MODEL_FROM_DATABASE=BYNET BIC2M/BIC4M/BYA4M (BIC2M) + +pci:v0000101Ad00001DC1sv0000101Asd0000001F* + ID_MODEL_FROM_DATABASE=BYNET BIC2M/BIC4M/BYA4M (BIC4M) + +pci:v0000101Ad00001DC1sv0000101Asd00000ECE* + ID_MODEL_FROM_DATABASE=BYNET BIC2M/BIC4M/BYA4M (BYA4M) + +pci:v0000101Ad00001FA8* + ID_MODEL_FROM_DATABASE=BYNET Multi-port BIC Adapter (XBIC Based) + +pci:v0000101Ad00001FA8sv0000101Asd000000C3* + ID_MODEL_FROM_DATABASE=BYNET Multi-port BIC Adapter (XBIC Based) (BYNET BIC2SE) + +pci:v0000101B* + ID_VENDOR_FROM_DATABASE=Vitesse Semiconductor + +pci:v0000101Bd00000452* + ID_MODEL_FROM_DATABASE=VSC452 [SuperBMC] + +pci:v0000101C* + ID_VENDOR_FROM_DATABASE=Western Digital + +pci:v0000101Cd00000193* + ID_MODEL_FROM_DATABASE=33C193A + +pci:v0000101Cd00000196* + ID_MODEL_FROM_DATABASE=33C196A + +pci:v0000101Cd00000197* + ID_MODEL_FROM_DATABASE=33C197A + +pci:v0000101Cd00000296* + ID_MODEL_FROM_DATABASE=33C296A + +pci:v0000101Cd00003193* + ID_MODEL_FROM_DATABASE=7193 + +pci:v0000101Cd00003197* + ID_MODEL_FROM_DATABASE=7197 + +pci:v0000101Cd00003296* + ID_MODEL_FROM_DATABASE=33C296A + +pci:v0000101Cd00004296* + ID_MODEL_FROM_DATABASE=34C296 + +pci:v0000101Cd00009710* + ID_MODEL_FROM_DATABASE=Pipeline 9710 + +pci:v0000101Cd00009712* + ID_MODEL_FROM_DATABASE=Pipeline 9712 + +pci:v0000101Cd0000C24A* + ID_MODEL_FROM_DATABASE=90C + +pci:v0000101D* + ID_VENDOR_FROM_DATABASE=Maxim Integrated Products + +pci:v0000101E* + ID_VENDOR_FROM_DATABASE=American Megatrends Inc. + +pci:v0000101Ed00000009* + ID_MODEL_FROM_DATABASE=MegaRAID 428 Ultra RAID Controller (rev 03) + +pci:v0000101Ed00001960* + ID_MODEL_FROM_DATABASE=MegaRAID + +pci:v0000101Ed00001960sv0000101Esd00000471* + ID_MODEL_FROM_DATABASE=MegaRAID (471 Enterprise 1600 RAID Controller) + +pci:v0000101Ed00001960sv0000101Esd00000475* + ID_MODEL_FROM_DATABASE=MegaRAID (475 Express 500/500LC RAID Controller) + +pci:v0000101Ed00001960sv0000101Esd00000477* + ID_MODEL_FROM_DATABASE=MegaRAID (477 Elite 3100 RAID Controller) + +pci:v0000101Ed00001960sv0000101Esd00000493* + ID_MODEL_FROM_DATABASE=MegaRAID (493 Elite 1600 RAID Controller) + +pci:v0000101Ed00001960sv0000101Esd00000494* + ID_MODEL_FROM_DATABASE=MegaRAID (494 Elite 1650 RAID Controller) + +pci:v0000101Ed00001960sv0000101Esd00000503* + ID_MODEL_FROM_DATABASE=MegaRAID (503 Enterprise 1650 RAID Controller) + +pci:v0000101Ed00001960sv0000101Esd00000511* + ID_MODEL_FROM_DATABASE=MegaRAID (511 i4 IDE RAID Controller) + +pci:v0000101Ed00001960sv0000101Esd00000522* + ID_MODEL_FROM_DATABASE=MegaRAID (522 i4133 RAID Controller) + +pci:v0000101Ed00001960sv00001028sd00000471* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller 3/QC) + +pci:v0000101Ed00001960sv00001028sd00000475* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller 3/SC) + +pci:v0000101Ed00001960sv00001028sd00000493* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge RAID Controller 3/DC) + +pci:v0000101Ed00001960sv00001028sd00000511* + ID_MODEL_FROM_DATABASE=MegaRAID (PowerEdge Cost Effective RAID Controller ATA100/4Ch) + +pci:v0000101Ed00001960sv0000103Csd000060E7* + ID_MODEL_FROM_DATABASE=MegaRAID (NetRAID-1M) + +pci:v0000101Ed00001960sv0000103Csd000060E8* + ID_MODEL_FROM_DATABASE=MegaRAID (NetRaid 2M [AMI MegaRaid 493]) + +pci:v0000101Ed00009010* + ID_MODEL_FROM_DATABASE=MegaRAID 428 Ultra RAID Controller + +pci:v0000101Ed00009030* + ID_MODEL_FROM_DATABASE=EIDE Controller + +pci:v0000101Ed00009031* + ID_MODEL_FROM_DATABASE=EIDE Controller + +pci:v0000101Ed00009032* + ID_MODEL_FROM_DATABASE=EIDE & SCSI Controller + +pci:v0000101Ed00009033* + ID_MODEL_FROM_DATABASE=SCSI Controller + +pci:v0000101Ed00009040* + ID_MODEL_FROM_DATABASE=Multimedia card + +pci:v0000101Ed00009060* + ID_MODEL_FROM_DATABASE=MegaRAID 434 Ultra GT RAID Controller + +pci:v0000101Ed00009063* + ID_MODEL_FROM_DATABASE=MegaRAC + +pci:v0000101Ed00009063sv0000101Esd00000767* + ID_MODEL_FROM_DATABASE=MegaRAC (Dell Remote Assistant Card 2) + +pci:v0000101F* + ID_VENDOR_FROM_DATABASE=PictureTel + +pci:v00001020* + ID_VENDOR_FROM_DATABASE=Hitachi Computer Products + +pci:v00001021* + ID_VENDOR_FROM_DATABASE=OKI Electric Industry Co. Ltd. + +pci:v00001022* + ID_VENDOR_FROM_DATABASE=Advanced Micro Devices, Inc. [AMD] + +pci:v00001022d00001100* + ID_MODEL_FROM_DATABASE=K8 [Athlon64/Opteron] HyperTransport Technology Configuration + +pci:v00001022d00001101* + ID_MODEL_FROM_DATABASE=K8 [Athlon64/Opteron] Address Map + +pci:v00001022d00001102* + ID_MODEL_FROM_DATABASE=K8 [Athlon64/Opteron] DRAM Controller + +pci:v00001022d00001103* + ID_MODEL_FROM_DATABASE=K8 [Athlon64/Opteron] Miscellaneous Control + +pci:v00001022d00001200* + ID_MODEL_FROM_DATABASE=Family 10h Processor HyperTransport Configuration + +pci:v00001022d00001201* + ID_MODEL_FROM_DATABASE=Family 10h Processor Address Map + +pci:v00001022d00001202* + ID_MODEL_FROM_DATABASE=Family 10h Processor DRAM Controller + +pci:v00001022d00001203* + ID_MODEL_FROM_DATABASE=Family 10h Processor Miscellaneous Control + +pci:v00001022d00001204* + ID_MODEL_FROM_DATABASE=Family 10h Processor Link Control + +pci:v00001022d00001300* + ID_MODEL_FROM_DATABASE=Family 11h Processor HyperTransport Configuration + +pci:v00001022d00001301* + ID_MODEL_FROM_DATABASE=Family 11h Processor Address Map + +pci:v00001022d00001302* + ID_MODEL_FROM_DATABASE=Family 11h Processor DRAM Controller + +pci:v00001022d00001303* + ID_MODEL_FROM_DATABASE=Family 11h Processor Miscellaneous Control + +pci:v00001022d00001304* + ID_MODEL_FROM_DATABASE=Family 11h Processor Link Control + +pci:v00001022d00001305* + ID_MODEL_FROM_DATABASE=Griffin Function 5 + +pci:v00001022d00001306* + ID_MODEL_FROM_DATABASE=Griffin Function 6 + +pci:v00001022d00001307* + ID_MODEL_FROM_DATABASE=Griffin Function 7 + +pci:v00001022d00001308* + ID_MODEL_FROM_DATABASE=Kaveri Audio Controller + +pci:v00001022d00001314* + ID_MODEL_FROM_DATABASE=Wrestler/Bheem/Ontario/Krishna Audio Controller + +pci:v00001022d000013E0* + ID_MODEL_FROM_DATABASE=Ariel Root Complex + +pci:v00001022d000013E1* + ID_MODEL_FROM_DATABASE=Ariel IOMMU + +pci:v00001022d000013E2* + ID_MODEL_FROM_DATABASE=Ariel PCIe Dummy Host Bridge + +pci:v00001022d000013E3* + ID_MODEL_FROM_DATABASE=Ariel PCIe GPP Bridge + +pci:v00001022d000013E4* + ID_MODEL_FROM_DATABASE=Ariel PCIe Dummy Host Bridge + +pci:v00001022d000013E5* + ID_MODEL_FROM_DATABASE=Ariel Internal PCIe GPP Bridge 0 to Bus A + +pci:v00001022d000013E6* + ID_MODEL_FROM_DATABASE=Ariel Internal PCIe GPP Bridge 0 to Bus B + +pci:v00001022d000013E7* + ID_MODEL_FROM_DATABASE=Ariel SMBus Controller + +pci:v00001022d000013E8* + ID_MODEL_FROM_DATABASE=Ariel LPC Bridge + +pci:v00001022d000013E9* + ID_MODEL_FROM_DATABASE=Ariel Internal GPU + +pci:v00001022d000013EA* + ID_MODEL_FROM_DATABASE=Ariel HD Audio Controller + +pci:v00001022d000013EB* + ID_MODEL_FROM_DATABASE=Ariel HD Audio Coprocessor + +pci:v00001022d000013EC* + ID_MODEL_FROM_DATABASE=Ariel Cryptographic Coprocessor + +pci:v00001022d000013ED* + ID_MODEL_FROM_DATABASE=Ariel USB 3.1 Type C: Gen2 x 1port + DP Alt Mode + +pci:v00001022d000013EE* + ID_MODEL_FROM_DATABASE=Ariel USB 3.1 Type A: Gen2 x 2 ports + +pci:v00001022d000013EF* + ID_MODEL_FROM_DATABASE=Ariel ZCN/MP4 + +pci:v00001022d000013F0* + ID_MODEL_FROM_DATABASE=Ariel Device 24: Function 0 + +pci:v00001022d000013F1* + ID_MODEL_FROM_DATABASE=Ariel Device 24: Function 1 + +pci:v00001022d000013F2* + ID_MODEL_FROM_DATABASE=Ariel Device 24: Function 2 + +pci:v00001022d000013F3* + ID_MODEL_FROM_DATABASE=Ariel Device 24: Function 3 + +pci:v00001022d000013F4* + ID_MODEL_FROM_DATABASE=Ariel Device 24: Function 4 + +pci:v00001022d000013F5* + ID_MODEL_FROM_DATABASE=Ariel Device 24: Function 5 + +pci:v00001022d000013F6* + ID_MODEL_FROM_DATABASE=Ariel Device 24: Function 6 + +pci:v00001022d000013F7* + ID_MODEL_FROM_DATABASE=Ariel Device 24: Function 7 + +pci:v00001022d00001400* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 0 + +pci:v00001022d00001401* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 1 + +pci:v00001022d00001402* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 2 + +pci:v00001022d00001403* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 3 + +pci:v00001022d00001404* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 4 + +pci:v00001022d00001405* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Function 5 + +pci:v00001022d00001410* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Complex + +pci:v00001022d00001410sv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Complex (Pavilion 17-e163sg Notebook PC) + +pci:v00001022d00001412* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port + +pci:v00001022d00001412sv00001022sd00001234* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port (Trinity A-series APU) + +pci:v00001022d00001413* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port + +pci:v00001022d00001414* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port + +pci:v00001022d00001414sv00001022sd00001234* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port (Trinity A-series APU) + +pci:v00001022d00001415* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port + +pci:v00001022d00001416* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port + +pci:v00001022d00001417* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port + +pci:v00001022d00001418* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) Processor Root Port + +pci:v00001022d00001419* + ID_MODEL_FROM_DATABASE=Family 15h (Models 10h-1fh) I/O Memory Management Unit + +pci:v00001022d0000141A* + ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 0 + +pci:v00001022d0000141B* + ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 1 + +pci:v00001022d0000141C* + ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 2 + +pci:v00001022d0000141D* + ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 3 + +pci:v00001022d0000141E* + ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 4 + +pci:v00001022d0000141F* + ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Function 5 + +pci:v00001022d00001422* + ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Root Complex + +pci:v00001022d00001423* + ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) I/O Memory Management Unit + +pci:v00001022d00001424* + ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Root Port + +pci:v00001022d00001425* + ID_MODEL_FROM_DATABASE=Kaveri P2P Bridge for GFX PCIe Port [1:0] + +pci:v00001022d00001426* + ID_MODEL_FROM_DATABASE=Family 15h (Models 30h-3fh) Processor Root Port + +pci:v00001022d0000142E* + ID_MODEL_FROM_DATABASE=Liverpool Processor HT configuration + +pci:v00001022d0000142F* + ID_MODEL_FROM_DATABASE=Liverpool Processor Address Maps + +pci:v00001022d00001430* + ID_MODEL_FROM_DATABASE=Liverpool Processor DRAM configuration + +pci:v00001022d00001431* + ID_MODEL_FROM_DATABASE=Liverpool Processor Misc configuration + +pci:v00001022d00001432* + ID_MODEL_FROM_DATABASE=Liverpool Processor PM configuration + +pci:v00001022d00001433* + ID_MODEL_FROM_DATABASE=Liverpool Processor NB Performance Monitor + +pci:v00001022d00001434* + ID_MODEL_FROM_DATABASE=Liverpool Processor SPLL Configuration + +pci:v00001022d00001436* + ID_MODEL_FROM_DATABASE=Liverpool Processor Root Complex + +pci:v00001022d00001437* + ID_MODEL_FROM_DATABASE=Liverpool I/O Memory Management Unit + +pci:v00001022d00001438* + ID_MODEL_FROM_DATABASE=Liverpool UMI PCIe Dummy Host Bridge + +pci:v00001022d00001439* + ID_MODEL_FROM_DATABASE=Family 16h Processor Functions 5:1 + +pci:v00001022d0000143A* + ID_MODEL_FROM_DATABASE=Kingston/Clayton/Gladius/Montego Root Complex + +pci:v00001022d0000143B* + ID_MODEL_FROM_DATABASE=Kingston/Clayton/Gladius/Montego P2P Bridge for UMI Link + +pci:v00001022d00001440* + ID_MODEL_FROM_DATABASE=Matisse Device 24: Function 0 + +pci:v00001022d00001441* + ID_MODEL_FROM_DATABASE=Matisse Device 24: Function 1 + +pci:v00001022d00001442* + ID_MODEL_FROM_DATABASE=Matisse Device 24: Function 2 + +pci:v00001022d00001443* + ID_MODEL_FROM_DATABASE=Matisse Device 24: Function 3 + +pci:v00001022d00001444* + ID_MODEL_FROM_DATABASE=Matisse Device 24: Function 4 + +pci:v00001022d00001445* + ID_MODEL_FROM_DATABASE=Matisse Device 24: Function 5 + +pci:v00001022d00001446* + ID_MODEL_FROM_DATABASE=Matisse Device 24: Function 6 + +pci:v00001022d00001447* + ID_MODEL_FROM_DATABASE=Matisse Device 24: Function 7 + +pci:v00001022d00001448* + ID_MODEL_FROM_DATABASE=Renoir Device 24: Function 0 + +pci:v00001022d00001449* + ID_MODEL_FROM_DATABASE=Renoir Device 24: Function 1 + +pci:v00001022d0000144A* + ID_MODEL_FROM_DATABASE=Renoir Device 24: Function 2 + +pci:v00001022d0000144B* + ID_MODEL_FROM_DATABASE=Renoir Device 24: Function 3 + +pci:v00001022d0000144C* + ID_MODEL_FROM_DATABASE=Renoir Device 24: Function 4 + +pci:v00001022d0000144D* + ID_MODEL_FROM_DATABASE=Renoir Device 24: Function 5 + +pci:v00001022d0000144E* + ID_MODEL_FROM_DATABASE=Renoir Device 24: Function 6 + +pci:v00001022d0000144F* + ID_MODEL_FROM_DATABASE=Renoir Device 24: Function 7 + +pci:v00001022d00001450* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Root Complex + +pci:v00001022d00001451* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) I/O Memory Management Unit + +pci:v00001022d00001452* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-1fh) PCIe Dummy Host Bridge + +pci:v00001022d00001453* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) PCIe GPP Bridge + +pci:v00001022d00001454* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Internal PCIe GPP Bridge 0 to Bus B + +pci:v00001022d00001455* + ID_MODEL_FROM_DATABASE=Zeppelin/Renoir PCIe Dummy Function + +pci:v00001022d00001456* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Platform Security Processor + +pci:v00001022d00001457* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) HD Audio Controller + +pci:v00001022d0000145A* + ID_MODEL_FROM_DATABASE=Zeppelin/Raven/Raven2 PCIe Dummy Function + +pci:v00001022d0000145B* + ID_MODEL_FROM_DATABASE=Zeppelin Non-Transparent Bridge + +pci:v00001022d0000145C* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) USB 3.0 Host Controller + +pci:v00001022d0000145D* + ID_MODEL_FROM_DATABASE=Zeppelin Switch Upstream (PCIE SW.US) + +pci:v00001022d0000145E* + ID_MODEL_FROM_DATABASE=Zeppelin Switch Downstream (PCIE SW.DS) + +pci:v00001022d0000145F* + ID_MODEL_FROM_DATABASE=Zeppelin USB 3.0 Host controller + +pci:v00001022d00001460* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 0 + +pci:v00001022d00001461* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 1 + +pci:v00001022d00001462* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 2 + +pci:v00001022d00001463* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 3 + +pci:v00001022d00001464* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 4 + +pci:v00001022d00001465* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 5 + +pci:v00001022d00001466* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 6 + +pci:v00001022d00001467* + ID_MODEL_FROM_DATABASE=Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 7 + +pci:v00001022d00001468* + ID_MODEL_FROM_DATABASE=Zeppelin Cryptographic Coprocessor NTBCCP + +pci:v00001022d00001480* + ID_MODEL_FROM_DATABASE=Starship/Matisse Root Complex + +pci:v00001022d00001480sv00001462sd00007C37* + ID_MODEL_FROM_DATABASE=Starship/Matisse Root Complex (X570-A PRO motherboard) + +pci:v00001022d00001481* + ID_MODEL_FROM_DATABASE=Starship/Matisse IOMMU + +pci:v00001022d00001482* + ID_MODEL_FROM_DATABASE=Starship/Matisse PCIe Dummy Host Bridge + +pci:v00001022d00001483* + ID_MODEL_FROM_DATABASE=Starship/Matisse GPP Bridge + +pci:v00001022d00001484* + ID_MODEL_FROM_DATABASE=Starship/Matisse Internal PCIe GPP Bridge 0 to bus[E:B] + +pci:v00001022d00001485* + ID_MODEL_FROM_DATABASE=Starship/Matisse Reserved SPP + +pci:v00001022d00001486* + ID_MODEL_FROM_DATABASE=Starship/Matisse Cryptographic Coprocessor PSPCPP + +pci:v00001022d00001487* + ID_MODEL_FROM_DATABASE=Starship/Matisse HD Audio Controller + +pci:v00001022d00001487sv00001462sd00009C37* + ID_MODEL_FROM_DATABASE=Starship/Matisse HD Audio Controller (X570-A PRO motherboard) + +pci:v00001022d00001488* + ID_MODEL_FROM_DATABASE=Starship Reserved SSP + +pci:v00001022d00001489* + ID_MODEL_FROM_DATABASE=Starship Reserved SSP + +pci:v00001022d0000148A* + ID_MODEL_FROM_DATABASE=Starship/Matisse PCIe Dummy Function + +pci:v00001022d0000148B* + ID_MODEL_FROM_DATABASE=Starship/Matisse Non-Transparent Bridge + +pci:v00001022d0000148C* + ID_MODEL_FROM_DATABASE=Starship USB 3.0 Host Controller + +pci:v00001022d0000148D* + ID_MODEL_FROM_DATABASE=Starship/Matisse Switch Upstream (PCIE SW.US) + +pci:v00001022d0000148E* + ID_MODEL_FROM_DATABASE=Starship/Matisse Switch Downstream (PCIE SW.DS) + +pci:v00001022d0000148F* + ID_MODEL_FROM_DATABASE=Starship Reserved SSP + +pci:v00001022d00001490* + ID_MODEL_FROM_DATABASE=Starship Device 24; Function 0 + +pci:v00001022d00001491* + ID_MODEL_FROM_DATABASE=Starship Device 24; Function 1 + +pci:v00001022d00001492* + ID_MODEL_FROM_DATABASE=Starship Device 24; Function 2 + +pci:v00001022d00001493* + ID_MODEL_FROM_DATABASE=Starship Device 24; Function 3 + +pci:v00001022d00001494* + ID_MODEL_FROM_DATABASE=Starship Device 24; Function 4 + +pci:v00001022d00001495* + ID_MODEL_FROM_DATABASE=Starship Device 24; Function 5 + +pci:v00001022d00001496* + ID_MODEL_FROM_DATABASE=Starship Device 24; Function 6 + +pci:v00001022d00001497* + ID_MODEL_FROM_DATABASE=Starship Device 24; Function 7 + +pci:v00001022d00001498* + ID_MODEL_FROM_DATABASE=Starship/Matisse PTDMA + +pci:v00001022d00001499* + ID_MODEL_FROM_DATABASE=Starship/Matisse NVMe + +pci:v00001022d0000149A* + ID_MODEL_FROM_DATABASE=Starship PCIe GPP Bridge [1:0] + +pci:v00001022d0000149B* + ID_MODEL_FROM_DATABASE=Starship Reserved SSP + +pci:v00001022d0000149C* + ID_MODEL_FROM_DATABASE=Matisse USB 3.0 Host Controller + +pci:v00001022d0000149Csv00001462sd00007C37* + ID_MODEL_FROM_DATABASE=Matisse USB 3.0 Host Controller (X570-A PRO motherboard) + +pci:v00001022d00001510* + ID_MODEL_FROM_DATABASE=Family 14h Processor Root Complex + +pci:v00001022d00001510sv0000174Bsd00001001* + ID_MODEL_FROM_DATABASE=Family 14h Processor Root Complex (PURE Fusion Mini) + +pci:v00001022d00001512* + ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port + +pci:v00001022d00001513* + ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port + +pci:v00001022d00001514* + ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port + +pci:v00001022d00001515* + ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port + +pci:v00001022d00001516* + ID_MODEL_FROM_DATABASE=Family 14h Processor Root Port + +pci:v00001022d00001530* + ID_MODEL_FROM_DATABASE=Family 16h Processor Function 0 + +pci:v00001022d00001531* + ID_MODEL_FROM_DATABASE=Family 16h Processor Function 1 + +pci:v00001022d00001532* + ID_MODEL_FROM_DATABASE=Family 16h Processor Function 2 + +pci:v00001022d00001533* + ID_MODEL_FROM_DATABASE=Family 16h Processor Function 3 + +pci:v00001022d00001534* + ID_MODEL_FROM_DATABASE=Family 16h Processor Function 4 + +pci:v00001022d00001535* + ID_MODEL_FROM_DATABASE=Family 16h Processor Function 5 + +pci:v00001022d00001536* + ID_MODEL_FROM_DATABASE=Family 16h Processor Root Complex + +pci:v00001022d00001536sv00001849sd00001536* + ID_MODEL_FROM_DATABASE=Family 16h Processor Root Complex (QC5000-ITX/PH) + +pci:v00001022d00001537* + ID_MODEL_FROM_DATABASE=Kabini/Mullins PSP-Platform Security Processor + +pci:v00001022d00001538* + ID_MODEL_FROM_DATABASE=Family 16h Processor Function 0 + +pci:v00001022d00001539* + ID_MODEL_FROM_DATABASE=Kabini P2P Bridge for PCIe Ports[4:0] + +pci:v00001022d00001540* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky HT Configuration + +pci:v00001022d00001541* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Address Maps + +pci:v00001022d00001542* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky DRAM Configuration + +pci:v00001022d00001543* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Miscellaneous Configuration + +pci:v00001022d00001544* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky PM Configuration + +pci:v00001022d00001545* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky NB Performance Monitor + +pci:v00001022d00001546* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Root Complex + +pci:v00001022d00001547* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky IOMMU + +pci:v00001022d00001548* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky UMI PCIe Dummy Host Bridge + +pci:v00001022d00001549* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+ P2P Bridge for PCIe Port [3:0] + +pci:v00001022d0000154A* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Audio Processor + +pci:v00001022d0000154B* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Security Processor + +pci:v00001022d0000154D* + ID_MODEL_FROM_DATABASE=Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky/Anubis HDMI Controller + +pci:v00001022d0000154F* + ID_MODEL_FROM_DATABASE=Anubis Audio Processor + +pci:v00001022d00001550* + ID_MODEL_FROM_DATABASE=Garfield+/Arlene/Pooky/Anubis SPLL Configuration + +pci:v00001022d00001553* + ID_MODEL_FROM_DATABASE=Arlene/Pooky P2P Bridge for PCIE (3:0) + +pci:v00001022d0000155B* + ID_MODEL_FROM_DATABASE=Anubis Root Complex + +pci:v00001022d0000155C* + ID_MODEL_FROM_DATABASE=Anubis IOMMU + +pci:v00001022d0000155D* + ID_MODEL_FROM_DATABASE=Anubis UMI PCIe Dummy Bridge + +pci:v00001022d0000155E* + ID_MODEL_FROM_DATABASE=Anubis P2P Bridge for PCIe Ports [4:0] + +pci:v00001022d00001560* + ID_MODEL_FROM_DATABASE=Anubis Security Processor + +pci:v00001022d00001566* + ID_MODEL_FROM_DATABASE=Family 16h (Models 30h-3fh) Processor Root Complex + +pci:v00001022d00001567* + ID_MODEL_FROM_DATABASE=Mullins IOMMU + +pci:v00001022d0000156B* + ID_MODEL_FROM_DATABASE=Family 16h (Models 30h-3fh) Host Bridge + +pci:v00001022d00001570* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) Processor Function 0 + +pci:v00001022d00001571* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) Processor Function 1 + +pci:v00001022d00001572* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) Processor Function 2 + +pci:v00001022d00001573* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) Processor Function 3 + +pci:v00001022d00001574* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) Processor Function 4 + +pci:v00001022d00001575* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) Processor Function 5 + +pci:v00001022d00001576* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) Processor Root Complex + +pci:v00001022d00001577* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) I/O Memory Management Unit + +pci:v00001022d00001578* + ID_MODEL_FROM_DATABASE=Carrizo Platform Security Processor + +pci:v00001022d00001579* + ID_MODEL_FROM_DATABASE=Carrizo Audio Processor + +pci:v00001022d0000157A* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) Audio Controller + +pci:v00001022d0000157B* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) Host Bridge + +pci:v00001022d0000157C* + ID_MODEL_FROM_DATABASE=Family 15h (Models 60h-6fh) Processor Root Port + +pci:v00001022d0000157D* + ID_MODEL_FROM_DATABASE=Carrizo Audio Dummy Host Bridge + +pci:v00001022d0000157E* + ID_MODEL_FROM_DATABASE=Carrizo Audio Controller + +pci:v00001022d00001580* + ID_MODEL_FROM_DATABASE=Family 16h (Models 30h-3fh) Processor Function 0 + +pci:v00001022d00001581* + ID_MODEL_FROM_DATABASE=Family 16h (Models 30h-3fh) Processor Function 1 + +pci:v00001022d00001582* + ID_MODEL_FROM_DATABASE=Family 16h (Models 30h-3fh) Processor Function 2 + +pci:v00001022d00001583* + ID_MODEL_FROM_DATABASE=Family 16h (Models 30h-3fh) Processor Function 3 + +pci:v00001022d00001584* + ID_MODEL_FROM_DATABASE=Family 16h (Models 30h-3fh) Processor Function 4 + +pci:v00001022d00001585* + ID_MODEL_FROM_DATABASE=Family 16h (Models 30h-3fh) Processor Function 5 + +pci:v00001022d00001590* + ID_MODEL_FROM_DATABASE=Amur/Nolan HT Configuration + +pci:v00001022d00001591* + ID_MODEL_FROM_DATABASE=Amur/Nolan Address Maps + +pci:v00001022d00001592* + ID_MODEL_FROM_DATABASE=Amur/Nolan DRAM Configuration + +pci:v00001022d00001593* + ID_MODEL_FROM_DATABASE=Amur/Nolan Miscellaneous Configuration + +pci:v00001022d00001594* + ID_MODEL_FROM_DATABASE=Amur/Nolan PM Configuration + +pci:v00001022d00001595* + ID_MODEL_FROM_DATABASE=Amur/Nolan NB Performance Monitor + +pci:v00001022d00001596* + ID_MODEL_FROM_DATABASE=Amur/Nolan Root Complex + +pci:v00001022d00001597* + ID_MODEL_FROM_DATABASE=Amur/Nolan IOMMU + +pci:v00001022d00001598* + ID_MODEL_FROM_DATABASE=Amur/Nolan Platform Security Processor + +pci:v00001022d00001599* + ID_MODEL_FROM_DATABASE=Amur/Nolan PCIe Dummy Host Bridge + +pci:v00001022d0000159D* + ID_MODEL_FROM_DATABASE=Amur Function 6: Gasket + +pci:v00001022d000015B0* + ID_MODEL_FROM_DATABASE=Stoney HT Configuration + +pci:v00001022d000015B1* + ID_MODEL_FROM_DATABASE=Stoney Address Maps + +pci:v00001022d000015B2* + ID_MODEL_FROM_DATABASE=Stoney DRAM Configuration + +pci:v00001022d000015B3* + ID_MODEL_FROM_DATABASE=Stoney Miscellaneous Configuration + +pci:v00001022d000015B4* + ID_MODEL_FROM_DATABASE=Stoney PM Configuration + +pci:v00001022d000015B5* + ID_MODEL_FROM_DATABASE=Stoney NB Performance Monitor + +pci:v00001022d000015BC* + ID_MODEL_FROM_DATABASE=Stoney PCIe [GFX,GPP] Bridge [4:0] + +pci:v00001022d000015BE* + ID_MODEL_FROM_DATABASE=Stoney Audio Processor + +pci:v00001022d000015D0* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Root Complex + +pci:v00001022d000015D0sv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Root Complex (Pavilion Laptop 15-cw1xxx) + +pci:v00001022d000015D1* + ID_MODEL_FROM_DATABASE=Raven/Raven2 IOMMU + +pci:v00001022d000015D1sv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=Raven/Raven2 IOMMU (Pavilion Laptop 15-cw1xxx) + +pci:v00001022d000015D2* + ID_MODEL_FROM_DATABASE=Raven/Raven2 PCIe Dummy Host Bridge + +pci:v00001022d000015D3* + ID_MODEL_FROM_DATABASE=Raven/Raven2 PCIe GPP Bridge [6:0] + +pci:v00001022d000015D4* + ID_MODEL_FROM_DATABASE=FireFlight USB 3.1 + +pci:v00001022d000015D5* + ID_MODEL_FROM_DATABASE=FireFlight USB 3.1 + +pci:v00001022d000015DA* + ID_MODEL_FROM_DATABASE=Raven/Raven2 PCIe Dummy Host Bridge + +pci:v00001022d000015DB* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus A + +pci:v00001022d000015DC* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus B + +pci:v00001022d000015DE* + ID_MODEL_FROM_DATABASE=Raven/Raven2/FireFlight HD Audio Controller + +pci:v00001022d000015DF* + ID_MODEL_FROM_DATABASE=Family 17h (Models 10h-1fh) Platform Security Processor + +pci:v00001022d000015E0* + ID_MODEL_FROM_DATABASE=Raven USB 3.1 + +pci:v00001022d000015E0sv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=Raven USB 3.1 (Pavilion Laptop 15-cw1xxx) + +pci:v00001022d000015E1* + ID_MODEL_FROM_DATABASE=Raven USB 3.1 + +pci:v00001022d000015E1sv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=Raven USB 3.1 (Pavilion Laptop 15-cw1xxx) + +pci:v00001022d000015E2* + ID_MODEL_FROM_DATABASE=Raven/Raven2/FireFlight/Renoir Audio Processor + +pci:v00001022d000015E3* + ID_MODEL_FROM_DATABASE=Family 17h (Models 10h-1fh) HD Audio Controller + +pci:v00001022d000015E3sv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=Family 17h (Models 10h-1fh) HD Audio Controller (Pavilion Laptop 15-cw1xxx) + +pci:v00001022d000015E4* + ID_MODEL_FROM_DATABASE=Raven/Raven2/Renoir Sensor Fusion Hub + +pci:v00001022d000015E5* + ID_MODEL_FROM_DATABASE=Raven2 USB 3.1 + +pci:v00001022d000015E6* + ID_MODEL_FROM_DATABASE=Raven/Raven2/Renoir Non-Sensor Fusion Hub KMDF driver + +pci:v00001022d000015E6sv00001022sd000015E4* + ID_MODEL_FROM_DATABASE=Raven/Raven2/Renoir Non-Sensor Fusion Hub KMDF driver (Raven/Raven2/Renoir Sensor Fusion Hub) + +pci:v00001022d000015E8* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Device 24: Function 0 + +pci:v00001022d000015E9* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Device 24: Function 1 + +pci:v00001022d000015EA* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Device 24: Function 2 + +pci:v00001022d000015EB* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Device 24: Function 3 + +pci:v00001022d000015EC* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Device 24: Function 4 + +pci:v00001022d000015ED* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Device 24: Function 5 + +pci:v00001022d000015EE* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Device 24: Function 6 + +pci:v00001022d000015EF* + ID_MODEL_FROM_DATABASE=Raven/Raven2 Device 24: Function 7 + +pci:v00001022d000015F0* + ID_MODEL_FROM_DATABASE=FireFlight Device 24: Function 0 + +pci:v00001022d000015F1* + ID_MODEL_FROM_DATABASE=FireFlight Device 24: Function 1 + +pci:v00001022d000015F2* + ID_MODEL_FROM_DATABASE=FireFlight Device 24: Function 2 + +pci:v00001022d000015F3* + ID_MODEL_FROM_DATABASE=FireFlight Device 24: Function 3 + +pci:v00001022d000015F4* + ID_MODEL_FROM_DATABASE=FireFlight Device 24: Function 4 + +pci:v00001022d000015F5* + ID_MODEL_FROM_DATABASE=FireFlight Device 24: Function 5 + +pci:v00001022d000015F6* + ID_MODEL_FROM_DATABASE=FireFlight Device 24: Function 6 + +pci:v00001022d000015F7* + ID_MODEL_FROM_DATABASE=FireFlight Device 24: Function 7 + +pci:v00001022d000015F8* + ID_MODEL_FROM_DATABASE=FireFlight Root Complex + +pci:v00001022d000015F9* + ID_MODEL_FROM_DATABASE=FireFlight IOMMU + +pci:v00001022d000015FA* + ID_MODEL_FROM_DATABASE=FireFlight PCIe Dummy Host Bridge + +pci:v00001022d000015FB* + ID_MODEL_FROM_DATABASE=FireFlight PCIe GPP Bride 3:0 + +pci:v00001022d000015FC* + ID_MODEL_FROM_DATABASE=FireFlight PCIe Dummy Host Bridge + +pci:v00001022d000015FD* + ID_MODEL_FROM_DATABASE=FireFlight Internal PCIe GPP Bridge 0 to Bus A + +pci:v00001022d000015FE* + ID_MODEL_FROM_DATABASE=FireFlight Internal PCIe GPP Bridge 0 to Bus B + +pci:v00001022d000015FF* + ID_MODEL_FROM_DATABASE=FireFlight Bus A; Device 0: Function 0: Internal GPU + +pci:v00001022d00001600* + ID_MODEL_FROM_DATABASE=Family 15h Processor Function 0 + +pci:v00001022d00001601* + ID_MODEL_FROM_DATABASE=Family 15h Processor Function 1 + +pci:v00001022d00001602* + ID_MODEL_FROM_DATABASE=Family 15h Processor Function 2 + +pci:v00001022d00001603* + ID_MODEL_FROM_DATABASE=Family 15h Processor Function 3 + +pci:v00001022d00001604* + ID_MODEL_FROM_DATABASE=Family 15h Processor Function 4 + +pci:v00001022d00001605* + ID_MODEL_FROM_DATABASE=Family 15h Processor Function 5 + +pci:v00001022d00001606* + ID_MODEL_FROM_DATABASE=Arden Security Processor + +pci:v00001022d00001608* + ID_MODEL_FROM_DATABASE=Arden Device 18h: Function 0 + +pci:v00001022d00001609* + ID_MODEL_FROM_DATABASE=Arden Device 18h: Function 1 + +pci:v00001022d0000160A* + ID_MODEL_FROM_DATABASE=Arden Device 18h: Function 2 + +pci:v00001022d0000160B* + ID_MODEL_FROM_DATABASE=Arden Device 18h: Function 3 + +pci:v00001022d0000160C* + ID_MODEL_FROM_DATABASE=Arden Device 18h: Function 4 + +pci:v00001022d0000160D* + ID_MODEL_FROM_DATABASE=Arden Device 18h: Function 5 + +pci:v00001022d0000160E* + ID_MODEL_FROM_DATABASE=Arden Device 18h: Function 6 + +pci:v00001022d0000160F* + ID_MODEL_FROM_DATABASE=Arden Device 18h: Function 7 + +pci:v00001022d00001620* + ID_MODEL_FROM_DATABASE=Anubis HT Configuration + +pci:v00001022d00001621* + ID_MODEL_FROM_DATABASE=Anubis Address Maps + +pci:v00001022d00001622* + ID_MODEL_FROM_DATABASE=Anubis DRAM Configuration + +pci:v00001022d00001623* + ID_MODEL_FROM_DATABASE=Anubis Miscellaneous Configuration + +pci:v00001022d00001624* + ID_MODEL_FROM_DATABASE=Anubis PM Configuration + +pci:v00001022d00001625* + ID_MODEL_FROM_DATABASE=Anubis NB Performance Monitor + +pci:v00001022d00001626* + ID_MODEL_FROM_DATABASE=Arden Root Complex + +pci:v00001022d00001627* + ID_MODEL_FROM_DATABASE=Arden IOMMU + +pci:v00001022d00001628* + ID_MODEL_FROM_DATABASE=Arden PCIe Dummy Host Bridge + +pci:v00001022d00001629* + ID_MODEL_FROM_DATABASE=Arden PCIe GPP Bridge + +pci:v00001022d0000162A* + ID_MODEL_FROM_DATABASE=Arden Internal PCIe GPP Bridge 0 to bus X + +pci:v00001022d0000162B* + ID_MODEL_FROM_DATABASE=Arden PCIe Non-Transparent Bridge + +pci:v00001022d00001630* + ID_MODEL_FROM_DATABASE=Renoir Root Complex + +pci:v00001022d00001631* + ID_MODEL_FROM_DATABASE=Renoir IOMMU + +pci:v00001022d00001632* + ID_MODEL_FROM_DATABASE=Renoir PCIe Dummy Host Bridge + +pci:v00001022d00001633* + ID_MODEL_FROM_DATABASE=Renoir PCIe GPP Bridge + +pci:v00001022d00001634* + ID_MODEL_FROM_DATABASE=Renoir PCIe GPP Bridge + +pci:v00001022d00001635* + ID_MODEL_FROM_DATABASE=Renoir Internal PCIe GPP Bridge to Bus + +pci:v00001022d00001637* + ID_MODEL_FROM_DATABASE=Renoir HD Audio Controller + +pci:v00001022d00001639* + ID_MODEL_FROM_DATABASE=Renoir USB 3.1 + +pci:v00001022d00001641* + ID_MODEL_FROM_DATABASE=Renoir 10GbE Controller Port 0 (XGBE0/1) + +pci:v00001022d00001642* + ID_MODEL_FROM_DATABASE=Renoir WLAN + +pci:v00001022d00001643* + ID_MODEL_FROM_DATABASE=Renoir BT + +pci:v00001022d00001644* + ID_MODEL_FROM_DATABASE=Renoir I2S + +pci:v00001022d00001700* + ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 0 + +pci:v00001022d00001701* + ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 1 + +pci:v00001022d00001702* + ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 2 + +pci:v00001022d00001703* + ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 3 + +pci:v00001022d00001704* + ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 4 + +pci:v00001022d00001705* + ID_MODEL_FROM_DATABASE=Family 12h Processor Root Complex + +pci:v00001022d00001706* + ID_MODEL_FROM_DATABASE=Llano P2P Bridge to external GPU + +pci:v00001022d00001707* + ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port + +pci:v00001022d00001708* + ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port + +pci:v00001022d00001709* + ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port + +pci:v00001022d0000170A* + ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port + +pci:v00001022d0000170B* + ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port + +pci:v00001022d0000170C* + ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port + +pci:v00001022d0000170D* + ID_MODEL_FROM_DATABASE=Family 12h Processor Root Port + +pci:v00001022d00001716* + ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 5 + +pci:v00001022d00001718* + ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 6 + +pci:v00001022d00001719* + ID_MODEL_FROM_DATABASE=Family 12h/14h Processor Function 7 + +pci:v00001022d00002000* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] + +pci:v00001022d00002000sv00001014sd00002000* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (NetFinity 10/100 Fast Ethernet) + +pci:v00001022d00002000sv00001022sd00002000* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (PCnet - Fast 79C971) + +pci:v00001022d00002000sv0000103Csd0000104C* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) + +pci:v00001022d00002000sv0000103Csd00001064* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) + +pci:v00001022d00002000sv0000103Csd00001065* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) + +pci:v00001022d00002000sv0000103Csd0000106C* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) + +pci:v00001022d00002000sv0000103Csd0000106E* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) + +pci:v00001022d00002000sv0000103Csd000010EA* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (Ethernet with LAN remote power Adapter) + +pci:v00001022d00002000sv00001113sd00001220* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (EN1220 10/100 Fast Ethernet) + +pci:v00001022d00002000sv00001259sd00002450* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2450 10/100 Fast Ethernet) + +pci:v00001022d00002000sv00001259sd00002454* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2450v4 10Mb Ethernet Adapter) + +pci:v00001022d00002000sv00001259sd00002700* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2700TX 10/100 Fast Ethernet) + +pci:v00001022d00002000sv00001259sd00002701* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2700FX 100Mb Ethernet) + +pci:v00001022d00002000sv00001259sd00002702* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2700FTX 10/100 Mb Fiber/Copper Fast Ethernet) + +pci:v00001022d00002000sv00001259sd00002703* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2701FX) + +pci:v00001022d00002000sv00001259sd00002704* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (AT-2701FTX 10/100 Mb Fiber/Copper Fast Ethernet) + +pci:v00001022d00002000sv00004C53sd00001000* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) + +pci:v00001022d00002000sv00004C53sd00001010* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (CP5/CR6 mainboard) + +pci:v00001022d00002000sv00004C53sd00001020* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (VR6 mainboard) + +pci:v00001022d00002000sv00004C53sd00001030* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (PC5 mainboard) + +pci:v00001022d00002000sv00004C53sd00001040* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (CL7 mainboard) + +pci:v00001022d00002000sv00004C53sd00001060* + ID_MODEL_FROM_DATABASE=79c970 [PCnet32 LANCE] (PC7 mainboard) + +pci:v00001022d00002001* + ID_MODEL_FROM_DATABASE=79c978 [HomePNA] + +pci:v00001022d00002001sv00001092sd00000A78* + ID_MODEL_FROM_DATABASE=79c978 [HomePNA] (Multimedia Home Network Adapter) + +pci:v00001022d00002001sv00001668sd00000299* + ID_MODEL_FROM_DATABASE=79c978 [HomePNA] (ActionLink Home Network Adapter) + +pci:v00001022d00002003* + ID_MODEL_FROM_DATABASE=Am 1771 MBW [Alchemy] + +pci:v00001022d00002020* + ID_MODEL_FROM_DATABASE=53c974 [PCscsi] + +pci:v00001022d00002020sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=53c974 [PCscsi] (QEMU Virtual Machine) + +pci:v00001022d00002040* + ID_MODEL_FROM_DATABASE=79c974 + +pci:v00001022d00002080* + ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] Host Bridge + +pci:v00001022d00002081* + ID_MODEL_FROM_DATABASE=Geode LX Video + +pci:v00001022d00002082* + ID_MODEL_FROM_DATABASE=Geode LX AES Security Block + +pci:v00001022d0000208F* + ID_MODEL_FROM_DATABASE=CS5536 GeodeLink PCI South Bridge + +pci:v00001022d00002090* + ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] ISA + +pci:v00001022d00002091* + ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] FLASH + +pci:v00001022d00002093* + ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] Audio + +pci:v00001022d00002094* + ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] OHC + +pci:v00001022d00002095* + ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] EHC + +pci:v00001022d00002096* + ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] UDC + +pci:v00001022d00002097* + ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] UOC + +pci:v00001022d0000209A* + ID_MODEL_FROM_DATABASE=CS5536 [Geode companion] IDE + +pci:v00001022d00003000* + ID_MODEL_FROM_DATABASE=ELanSC520 Microcontroller + +pci:v00001022d000043A0* + ID_MODEL_FROM_DATABASE=Hudson PCI to PCI bridge (PCIE port 0) + +pci:v00001022d000043A1* + ID_MODEL_FROM_DATABASE=Hudson PCI to PCI bridge (PCIE port 1) + +pci:v00001022d000043A2* + ID_MODEL_FROM_DATABASE=Hudson PCI to PCI bridge (PCIE port 2) + +pci:v00001022d000043A3* + ID_MODEL_FROM_DATABASE=Hudson PCI to PCI bridge (PCIE port 3) + +pci:v00001022d000043B0* + ID_MODEL_FROM_DATABASE=X370 Series Chipset PCIe Upstream Port + +pci:v00001022d000043B0sv00001849sd000043C6* + ID_MODEL_FROM_DATABASE=X370 Series Chipset PCIe Upstream Port (Fatal1ty X370 Professional Gaming) + +pci:v00001022d000043B1* + ID_MODEL_FROM_DATABASE=X399 Series Chipset PCIe Bridge + +pci:v00001022d000043B4* + ID_MODEL_FROM_DATABASE=300 Series Chipset PCIe Port + +pci:v00001022d000043B5* + ID_MODEL_FROM_DATABASE=X370 Series Chipset SATA Controller + +pci:v00001022d000043B5sv00001849sd000043C8* + ID_MODEL_FROM_DATABASE=X370 Series Chipset SATA Controller (Fatal1ty X370 Professional Gaming) + +pci:v00001022d000043B6* + ID_MODEL_FROM_DATABASE=X399 Series Chipset SATA Controller + +pci:v00001022d000043B7* + ID_MODEL_FROM_DATABASE=300 Series Chipset SATA Controller + +pci:v00001022d000043B9* + ID_MODEL_FROM_DATABASE=X370 Series Chipset USB 3.1 xHCI Controller + +pci:v00001022d000043B9sv00001849sd000043D0* + ID_MODEL_FROM_DATABASE=X370 Series Chipset USB 3.1 xHCI Controller (Fatal1ty X370 Professional Gaming) + +pci:v00001022d000043BA* + ID_MODEL_FROM_DATABASE=X399 Series Chipset USB 3.1 xHCI Controller + +pci:v00001022d000043BB* + ID_MODEL_FROM_DATABASE=300 Series Chipset USB 3.1 xHCI Controller + +pci:v00001022d000043C6* + ID_MODEL_FROM_DATABASE=400 Series Chipset PCIe Bridge + +pci:v00001022d000043C7* + ID_MODEL_FROM_DATABASE=400 Series Chipset PCIe Port + +pci:v00001022d000043C8* + ID_MODEL_FROM_DATABASE=400 Series Chipset SATA Controller + +pci:v00001022d000043D5* + ID_MODEL_FROM_DATABASE=400 Series Chipset USB 3.1 XHCI Controller + +pci:v00001022d000057A3* + ID_MODEL_FROM_DATABASE=Matisse PCIe GPP Bridge + +pci:v00001022d000057A4* + ID_MODEL_FROM_DATABASE=Matisse PCIe GPP Bridge + +pci:v00001022d000057AD* + ID_MODEL_FROM_DATABASE=Matisse Switch Upstream + +pci:v00001022d00007006* + ID_MODEL_FROM_DATABASE=AMD-751 [Irongate] System Controller + +pci:v00001022d00007007* + ID_MODEL_FROM_DATABASE=AMD-751 [Irongate] AGP Bridge + +pci:v00001022d0000700A* + ID_MODEL_FROM_DATABASE=AMD-IGR4 AGP Host to PCI Bridge + +pci:v00001022d0000700B* + ID_MODEL_FROM_DATABASE=AMD-IGR4 PCI to PCI Bridge + +pci:v00001022d0000700C* + ID_MODEL_FROM_DATABASE=AMD-760 MP [IGD4-2P] System Controller + +pci:v00001022d0000700D* + ID_MODEL_FROM_DATABASE=AMD-760 MP [IGD4-2P] AGP Bridge + +pci:v00001022d0000700E* + ID_MODEL_FROM_DATABASE=AMD-760 [IGD4-1P] System Controller + +pci:v00001022d0000700F* + ID_MODEL_FROM_DATABASE=AMD-760 [IGD4-1P] AGP Bridge + +pci:v00001022d00007400* + ID_MODEL_FROM_DATABASE=AMD-755 [Cobra] ISA + +pci:v00001022d00007401* + ID_MODEL_FROM_DATABASE=AMD-755 [Cobra] IDE + +pci:v00001022d00007403* + ID_MODEL_FROM_DATABASE=AMD-755 [Cobra] ACPI + +pci:v00001022d00007404* + ID_MODEL_FROM_DATABASE=AMD-755 [Cobra] USB + +pci:v00001022d00007408* + ID_MODEL_FROM_DATABASE=AMD-756 [Viper] ISA + +pci:v00001022d00007409* + ID_MODEL_FROM_DATABASE=AMD-756 [Viper] IDE + +pci:v00001022d0000740B* + ID_MODEL_FROM_DATABASE=AMD-756 [Viper] ACPI + +pci:v00001022d0000740C* + ID_MODEL_FROM_DATABASE=AMD-756 [Viper] USB + +pci:v00001022d00007410* + ID_MODEL_FROM_DATABASE=AMD-766 [ViperPlus] ISA + +pci:v00001022d00007411* + ID_MODEL_FROM_DATABASE=AMD-766 [ViperPlus] IDE + +pci:v00001022d00007413* + ID_MODEL_FROM_DATABASE=AMD-766 [ViperPlus] ACPI + +pci:v00001022d00007414* + ID_MODEL_FROM_DATABASE=AMD-766 [ViperPlus] USB + +pci:v00001022d00007440* + ID_MODEL_FROM_DATABASE=AMD-768 [Opus] ISA + +pci:v00001022d00007440sv00001043sd00008044* + ID_MODEL_FROM_DATABASE=AMD-768 [Opus] ISA (A7M-D Mainboard) + +pci:v00001022d00007441* + ID_MODEL_FROM_DATABASE=AMD-768 [Opus] IDE + +pci:v00001022d00007443* + ID_MODEL_FROM_DATABASE=AMD-768 [Opus] ACPI + +pci:v00001022d00007443sv00001043sd00008044* + ID_MODEL_FROM_DATABASE=AMD-768 [Opus] ACPI (A7M-D Mainboard) + +pci:v00001022d00007445* + ID_MODEL_FROM_DATABASE=AMD-768 [Opus] Audio + +pci:v00001022d00007446* + ID_MODEL_FROM_DATABASE=AMD-768 [Opus] MC97 Modem + +pci:v00001022d00007448* + ID_MODEL_FROM_DATABASE=AMD-768 [Opus] PCI + +pci:v00001022d00007449* + ID_MODEL_FROM_DATABASE=AMD-768 [Opus] USB + +pci:v00001022d00007450* + ID_MODEL_FROM_DATABASE=AMD-8131 PCI-X Bridge + +pci:v00001022d00007451* + ID_MODEL_FROM_DATABASE=AMD-8131 PCI-X IOAPIC + +pci:v00001022d00007454* + ID_MODEL_FROM_DATABASE=AMD-8151 System Controller + +pci:v00001022d00007455* + ID_MODEL_FROM_DATABASE=AMD-8151 AGP Bridge + +pci:v00001022d00007458* + ID_MODEL_FROM_DATABASE=AMD-8132 PCI-X Bridge + +pci:v00001022d00007459* + ID_MODEL_FROM_DATABASE=AMD-8132 PCI-X IOAPIC + +pci:v00001022d00007460* + ID_MODEL_FROM_DATABASE=AMD-8111 PCI + +pci:v00001022d00007460sv0000161Fsd00003017* + ID_MODEL_FROM_DATABASE=AMD-8111 PCI (HDAMB) + +pci:v00001022d00007461* + ID_MODEL_FROM_DATABASE=AMD-8111 USB + +pci:v00001022d00007462* + ID_MODEL_FROM_DATABASE=AMD-8111 Ethernet + +pci:v00001022d00007463* + ID_MODEL_FROM_DATABASE=AMD-8111 USB EHCI + +pci:v00001022d00007464* + ID_MODEL_FROM_DATABASE=AMD-8111 USB OHCI + +pci:v00001022d00007464sv0000161Fsd00003017* + ID_MODEL_FROM_DATABASE=AMD-8111 USB OHCI (HDAMB) + +pci:v00001022d00007468* + ID_MODEL_FROM_DATABASE=AMD-8111 LPC + +pci:v00001022d00007468sv0000161Fsd00003017* + ID_MODEL_FROM_DATABASE=AMD-8111 LPC (HDAMB) + +pci:v00001022d00007469* + ID_MODEL_FROM_DATABASE=AMD-8111 IDE + +pci:v00001022d00007469sv00001022sd00002B80* + ID_MODEL_FROM_DATABASE=AMD-8111 IDE ([Quartet]) + +pci:v00001022d00007469sv0000161Fsd00003017* + ID_MODEL_FROM_DATABASE=AMD-8111 IDE (HDAMB) + +pci:v00001022d0000746A* + ID_MODEL_FROM_DATABASE=AMD-8111 SMBus 2.0 + +pci:v00001022d0000746B* + ID_MODEL_FROM_DATABASE=AMD-8111 ACPI + +pci:v00001022d0000746Bsv0000161Fsd00003017* + ID_MODEL_FROM_DATABASE=AMD-8111 ACPI (HDAMB) + +pci:v00001022d0000746D* + ID_MODEL_FROM_DATABASE=AMD-8111 AC97 Audio + +pci:v00001022d0000746Dsv0000161Fsd00003017* + ID_MODEL_FROM_DATABASE=AMD-8111 AC97 Audio (HDAMB) + +pci:v00001022d0000746E* + ID_MODEL_FROM_DATABASE=AMD-8111 MC97 Modem + +pci:v00001022d0000756B* + ID_MODEL_FROM_DATABASE=AMD-8111 ACPI + +pci:v00001022d00007800* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [IDE mode] + +pci:v00001022d00007801* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] + +pci:v00001022d00007801sv0000103Csd0000168B* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (ProBook 4535s Notebook) + +pci:v00001022d00007801sv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (ProBook 455 G1 Notebook) + +pci:v00001022d00007801sv00001849sd00007801* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (QC5000-ITX/PH) + +pci:v00001022d00007802* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode] + +pci:v00001022d00007803* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode] + +pci:v00001022d00007804* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] + +pci:v00001022d00007804sv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (Pavilion 17-e163sg Notebook PC) + +pci:v00001022d00007805* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode] + +pci:v00001022d00007806* + ID_MODEL_FROM_DATABASE=FCH SD Flash Controller + +pci:v00001022d00007807* + ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller + +pci:v00001022d00007807sv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller (ProBook 455 G1 Notebook) + +pci:v00001022d00007807sv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller (Pavilion 17-e163sg Notebook PC) + +pci:v00001022d00007807sv00001849sd00007807* + ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller (QC5000-ITX/PH) + +pci:v00001022d00007808* + ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller + +pci:v00001022d00007808sv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller (ProBook 455 G1 Notebook) + +pci:v00001022d00007808sv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller (Pavilion 17-e163sg Notebook PC) + +pci:v00001022d00007808sv00001849sd00007808* + ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller (QC5000-ITX/PH) + +pci:v00001022d00007809* + ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller + +pci:v00001022d00007809sv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=FCH USB OHCI Controller (ProBook 455 G1 Notebook) + +pci:v00001022d0000780A* + ID_MODEL_FROM_DATABASE=Kabini/Mullins SATA Raid/AHCI Mode (DotHill driver) + +pci:v00001022d0000780B* + ID_MODEL_FROM_DATABASE=FCH SMBus Controller + +pci:v00001022d0000780Bsv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=FCH SMBus Controller (ProBook 455 G1 Notebook) + +pci:v00001022d0000780Bsv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=FCH SMBus Controller (Pavilion 17-e163sg Notebook PC) + +pci:v00001022d0000780Bsv00001849sd0000780B* + ID_MODEL_FROM_DATABASE=FCH SMBus Controller (QC5000-ITX/PH) + +pci:v00001022d0000780C* + ID_MODEL_FROM_DATABASE=FCH IDE Controller + +pci:v00001022d0000780D* + ID_MODEL_FROM_DATABASE=FCH Azalia Controller + +pci:v00001022d0000780Dsv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=FCH Azalia Controller (ProBook 455 G1 Notebook) + +pci:v00001022d0000780Dsv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=FCH Azalia Controller (Pavilion 17-e163sg Notebook PC) + +pci:v00001022d0000780Dsv00001043sd00008444* + ID_MODEL_FROM_DATABASE=FCH Azalia Controller (F2A85-M Series) + +pci:v00001022d0000780Dsv00001849sd00008892* + ID_MODEL_FROM_DATABASE=FCH Azalia Controller (QC5000-ITX/PH) + +pci:v00001022d0000780E* + ID_MODEL_FROM_DATABASE=FCH LPC Bridge + +pci:v00001022d0000780Esv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=FCH LPC Bridge (ProBook 455 G1 Notebook) + +pci:v00001022d0000780Esv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=FCH LPC Bridge (Pavilion 17-e163sg Notebook PC) + +pci:v00001022d0000780Esv00001849sd0000780E* + ID_MODEL_FROM_DATABASE=FCH LPC Bridge (QC5000-ITX/PH) + +pci:v00001022d0000780F* + ID_MODEL_FROM_DATABASE=FCH PCI Bridge + +pci:v00001022d00007812* + ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller + +pci:v00001022d00007813* + ID_MODEL_FROM_DATABASE=FCH SD Flash Controller + +pci:v00001022d00007814* + ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller + +pci:v00001022d00007814sv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller (ProBook 455 G1 Notebook) + +pci:v00001022d00007814sv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller (Pavilion 17-e163sg Notebook PC) + +pci:v00001022d00007814sv00001849sd00007814* + ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller (QC5000-ITX/PH) + +pci:v00001022d00007900* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [IDE mode] + +pci:v00001022d00007901* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] + +pci:v00001022d00007901sv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (Pavilion Laptop 15-cw1xxx) + +pci:v00001022d00007901sv00001462sd00007C37* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] (X570-A PRO motherboard) + +pci:v00001022d00007902* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode] + +pci:v00001022d00007903* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [RAID mode] + +pci:v00001022d00007904* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] + +pci:v00001022d00007906* + ID_MODEL_FROM_DATABASE=FCH SD Flash Controller + +pci:v00001022d00007908* + ID_MODEL_FROM_DATABASE=FCH USB EHCI Controller + +pci:v00001022d0000790B* + ID_MODEL_FROM_DATABASE=FCH SMBus Controller + +pci:v00001022d0000790Bsv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=FCH SMBus Controller (Pavilion Laptop 15-cw1xxx) + +pci:v00001022d0000790Bsv00001462sd00007C37* + ID_MODEL_FROM_DATABASE=FCH SMBus Controller (X570-A PRO motherboard) + +pci:v00001022d0000790E* + ID_MODEL_FROM_DATABASE=FCH LPC Bridge + +pci:v00001022d0000790Esv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=FCH LPC Bridge (Pavilion Laptop 15-cw1xxx) + +pci:v00001022d0000790Esv00001462sd00007C37* + ID_MODEL_FROM_DATABASE=FCH LPC Bridge (X570-A PRO motherboard) + +pci:v00001022d0000790F* + ID_MODEL_FROM_DATABASE=FCH PCI Bridge + +pci:v00001022d00007914* + ID_MODEL_FROM_DATABASE=FCH USB XHCI Controller + +pci:v00001022d00009600* + ID_MODEL_FROM_DATABASE=RS780 Host Bridge + +pci:v00001022d00009600sv00001043sd000082EE* + ID_MODEL_FROM_DATABASE=RS780 Host Bridge (M378A-CM Motherboard) + +pci:v00001022d00009600sv00001043sd000082F1* + ID_MODEL_FROM_DATABASE=RS780 Host Bridge (M3A78-EH Motherboard) + +pci:v00001022d00009601* + ID_MODEL_FROM_DATABASE=RS880 Host Bridge + +pci:v00001022d00009601sv00001019sd00002120* + ID_MODEL_FROM_DATABASE=RS880 Host Bridge (A785GM-M) + +pci:v00001022d00009601sv0000103Csd00001609* + ID_MODEL_FROM_DATABASE=RS880 Host Bridge (ProLiant MicroServer N36L) + +pci:v00001022d00009601sv00001043sd000083A2* + ID_MODEL_FROM_DATABASE=RS880 Host Bridge (M4A785-M Mainboard) + +pci:v00001022d00009601sv00001043sd0000843E* + ID_MODEL_FROM_DATABASE=RS880 Host Bridge (M5A88-V EVO) + +pci:v00001022d00009602* + ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (int gfx) + +pci:v00001022d00009603* + ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (ext gfx port 0) + +pci:v00001022d00009603sv0000103Csd00001609* + ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (ext gfx port 0) (ProLiant MicroServer N36L) + +pci:v00001022d00009604* + ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 0) + +pci:v00001022d00009605* + ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 1) + +pci:v00001022d00009606* + ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (PCIE port 2) + +pci:v00001022d00009606sv0000103Csd00001609* + ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (PCIE port 2) (ProLiant MicroServer N36L) + +pci:v00001022d00009607* + ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 3) + +pci:v00001022d00009608* + ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 4) + +pci:v00001022d00009609* + ID_MODEL_FROM_DATABASE=RS780/RS880 PCI to PCI bridge (PCIE port 5) + +pci:v00001022d0000960A* + ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (NB-SB link) + +pci:v00001022d0000960B* + ID_MODEL_FROM_DATABASE=RS780 PCI to PCI bridge (ext gfx port 1) + +pci:v00001023* + ID_VENDOR_FROM_DATABASE=Trident Microsystems + +pci:v00001023d00000194* + ID_MODEL_FROM_DATABASE=82C194 + +pci:v00001023d00002000* + ID_MODEL_FROM_DATABASE=4DWave DX + +pci:v00001023d00002001* + ID_MODEL_FROM_DATABASE=4DWave NX + +pci:v00001023d00002001sv0000122Dsd00001400* + ID_MODEL_FROM_DATABASE=4DWave NX (Trident PCI288-Q3DII (NX)) + +pci:v00001023d00002100* + ID_MODEL_FROM_DATABASE=CyberBlade XP4m32 + +pci:v00001023d00002200* + ID_MODEL_FROM_DATABASE=XGI Volari XP5 + +pci:v00001023d00008400* + ID_MODEL_FROM_DATABASE=CyberBlade/i7 + +pci:v00001023d00008400sv00001023sd00008400* + ID_MODEL_FROM_DATABASE=CyberBlade/i7 (CyberBlade i7 AGP) + +pci:v00001023d00008420* + ID_MODEL_FROM_DATABASE=CyberBlade/i7d + +pci:v00001023d00008420sv00000E11sd0000B15A* + ID_MODEL_FROM_DATABASE=CyberBlade/i7d (CyberBlade i7 AGP) + +pci:v00001023d00008500* + ID_MODEL_FROM_DATABASE=CyberBlade/i1 + +pci:v00001023d00008520* + ID_MODEL_FROM_DATABASE=CyberBlade i1 + +pci:v00001023d00008520sv00000E11sd0000B16E* + ID_MODEL_FROM_DATABASE=CyberBlade i1 (AGP) + +pci:v00001023d00008520sv00001023sd00008520* + ID_MODEL_FROM_DATABASE=CyberBlade i1 (AGP) + +pci:v00001023d00008620* + ID_MODEL_FROM_DATABASE=CyberBlade/i1 + +pci:v00001023d00008620sv00001014sd00000502* + ID_MODEL_FROM_DATABASE=CyberBlade/i1 (ThinkPad R30/T30) + +pci:v00001023d00008620sv00001014sd00001025* + ID_MODEL_FROM_DATABASE=CyberBlade/i1 (Travelmate 352TE) + +pci:v00001023d00008820* + ID_MODEL_FROM_DATABASE=CyberBlade XPAi1 + +pci:v00001023d00009320* + ID_MODEL_FROM_DATABASE=TGUI 9320 + +pci:v00001023d00009350* + ID_MODEL_FROM_DATABASE=GUI Accelerator + +pci:v00001023d00009360* + ID_MODEL_FROM_DATABASE=Flat panel GUI Accelerator + +pci:v00001023d00009382* + ID_MODEL_FROM_DATABASE=Cyber 9382 [Reference design] + +pci:v00001023d00009383* + ID_MODEL_FROM_DATABASE=Cyber 9383 [Reference design] + +pci:v00001023d00009385* + ID_MODEL_FROM_DATABASE=Cyber 9385 [Reference design] + +pci:v00001023d00009386* + ID_MODEL_FROM_DATABASE=Cyber 9386 + +pci:v00001023d00009388* + ID_MODEL_FROM_DATABASE=Cyber 9388 + +pci:v00001023d00009397* + ID_MODEL_FROM_DATABASE=Cyber 9397 + +pci:v00001023d0000939A* + ID_MODEL_FROM_DATABASE=Cyber 9397DVD + +pci:v00001023d00009420* + ID_MODEL_FROM_DATABASE=TGUI 9420 + +pci:v00001023d00009430* + ID_MODEL_FROM_DATABASE=TGUI 9430 + +pci:v00001023d00009440* + ID_MODEL_FROM_DATABASE=TGUI 9440 + +pci:v00001023d00009460* + ID_MODEL_FROM_DATABASE=TGUI 9460 + +pci:v00001023d00009470* + ID_MODEL_FROM_DATABASE=TGUI 9470 + +pci:v00001023d00009520* + ID_MODEL_FROM_DATABASE=Cyber 9520 + +pci:v00001023d00009525* + ID_MODEL_FROM_DATABASE=Cyber 9525 + +pci:v00001023d00009540* + ID_MODEL_FROM_DATABASE=Cyber 9540 + +pci:v00001023d00009660* + ID_MODEL_FROM_DATABASE=TGUI 9660/938x/968x + +pci:v00001023d00009680* + ID_MODEL_FROM_DATABASE=TGUI 9680 + +pci:v00001023d00009682* + ID_MODEL_FROM_DATABASE=TGUI 9682 + +pci:v00001023d00009683* + ID_MODEL_FROM_DATABASE=TGUI 9683 + +pci:v00001023d00009685* + ID_MODEL_FROM_DATABASE=ProVIDIA 9685 + +pci:v00001023d00009750* + ID_MODEL_FROM_DATABASE=3DImage 9750 + +pci:v00001023d00009750sv00001014sd00009750* + ID_MODEL_FROM_DATABASE=3DImage 9750 + +pci:v00001023d00009750sv00001023sd00009750* + ID_MODEL_FROM_DATABASE=3DImage 9750 + +pci:v00001023d00009753* + ID_MODEL_FROM_DATABASE=TGUI 9753 + +pci:v00001023d00009754* + ID_MODEL_FROM_DATABASE=TGUI 9754 + +pci:v00001023d00009759* + ID_MODEL_FROM_DATABASE=TGUI 975 + +pci:v00001023d00009783* + ID_MODEL_FROM_DATABASE=TGUI 9783 + +pci:v00001023d00009785* + ID_MODEL_FROM_DATABASE=TGUI 9785 + +pci:v00001023d00009850* + ID_MODEL_FROM_DATABASE=3DImage 9850 + +pci:v00001023d00009880* + ID_MODEL_FROM_DATABASE=Blade 3D PCI/AGP + +pci:v00001023d00009880sv00001023sd00009880* + ID_MODEL_FROM_DATABASE=Blade 3D PCI/AGP (Blade 3D) + +pci:v00001023d00009910* + ID_MODEL_FROM_DATABASE=CyberBlade/XP + +pci:v00001023d00009930* + ID_MODEL_FROM_DATABASE=CyberBlade/XPm + +pci:v00001023d00009960* + ID_MODEL_FROM_DATABASE=CyberBlade XP2 + +pci:v00001024* + ID_VENDOR_FROM_DATABASE=Zenith Data Systems + +pci:v00001025* + ID_VENDOR_FROM_DATABASE=Acer Incorporated [ALI] + +pci:v00001025d00001435* + ID_MODEL_FROM_DATABASE=M1435 + +pci:v00001025d00001445* + ID_MODEL_FROM_DATABASE=M1445 + +pci:v00001025d00001449* + ID_MODEL_FROM_DATABASE=M1449 + +pci:v00001025d00001451* + ID_MODEL_FROM_DATABASE=M1451 + +pci:v00001025d00001461* + ID_MODEL_FROM_DATABASE=M1461 + +pci:v00001025d00001489* + ID_MODEL_FROM_DATABASE=M1489 + +pci:v00001025d00001511* + ID_MODEL_FROM_DATABASE=M1511 + +pci:v00001025d00001512* + ID_MODEL_FROM_DATABASE=ALI M1512 Aladdin + +pci:v00001025d00001513* + ID_MODEL_FROM_DATABASE=M1513 + +pci:v00001025d00001521* + ID_MODEL_FROM_DATABASE=ALI M1521 Aladdin III CPU Bridge + +pci:v00001025d00001521sv000010B9sd00001521* + ID_MODEL_FROM_DATABASE=ALI M1521 Aladdin III CPU Bridge + +pci:v00001025d00001523* + ID_MODEL_FROM_DATABASE=ALI M1523 ISA Bridge + +pci:v00001025d00001523sv000010B9sd00001523* + ID_MODEL_FROM_DATABASE=ALI M1523 ISA Bridge + +pci:v00001025d00001531* + ID_MODEL_FROM_DATABASE=M1531 Northbridge [Aladdin IV/IV+] + +pci:v00001025d00001533* + ID_MODEL_FROM_DATABASE=M1533 PCI-to-ISA Bridge + +pci:v00001025d00001533sv000010B9sd00001533* + ID_MODEL_FROM_DATABASE=M1533 PCI-to-ISA Bridge (ALI M1533 Aladdin IV/V ISA South Bridge) + +pci:v00001025d00001535* + ID_MODEL_FROM_DATABASE=M1535 PCI Bridge + Super I/O + FIR + +pci:v00001025d00001541* + ID_MODEL_FROM_DATABASE=M1541 Northbridge [Aladdin V] + +pci:v00001025d00001541sv000010B9sd00001541* + ID_MODEL_FROM_DATABASE=M1541 Northbridge [Aladdin V] (ALI M1541 Aladdin V/V+ AGP+PCI North Bridge) + +pci:v00001025d00001542* + ID_MODEL_FROM_DATABASE=M1542 Northbridge [Aladdin V] + +pci:v00001025d00001543* + ID_MODEL_FROM_DATABASE=M1543 PCI-to-ISA Bridge + Super I/O + FIR + +pci:v00001025d00001561* + ID_MODEL_FROM_DATABASE=M1561 Northbridge [Aladdin 7] + +pci:v00001025d00001621* + ID_MODEL_FROM_DATABASE=M1621 Northbridge [Aladdin-Pro II] + +pci:v00001025d00001631* + ID_MODEL_FROM_DATABASE=M1631 Northbridge+3D Graphics [Aladdin TNT2] + +pci:v00001025d00001641* + ID_MODEL_FROM_DATABASE=M1641 Northbridge [Aladdin-Pro IV] + +pci:v00001025d00001647* + ID_MODEL_FROM_DATABASE=M1647 [MaGiK1] PCI North Bridge + +pci:v00001025d00001671* + ID_MODEL_FROM_DATABASE=M1671 Northbridge [ALADDiN-P4] + +pci:v00001025d00001672* + ID_MODEL_FROM_DATABASE=Northbridge [CyberALADDiN-P4] + +pci:v00001025d00003141* + ID_MODEL_FROM_DATABASE=M3141 + +pci:v00001025d00003143* + ID_MODEL_FROM_DATABASE=M3143 + +pci:v00001025d00003145* + ID_MODEL_FROM_DATABASE=M3145 + +pci:v00001025d00003147* + ID_MODEL_FROM_DATABASE=M3147 + +pci:v00001025d00003149* + ID_MODEL_FROM_DATABASE=M3149 + +pci:v00001025d00003151* + ID_MODEL_FROM_DATABASE=M3151 + +pci:v00001025d00003307* + ID_MODEL_FROM_DATABASE=M3307 MPEG-I Video Controller + +pci:v00001025d00003309* + ID_MODEL_FROM_DATABASE=M3309 MPEG-II Video w/ Software Audio Decoder + +pci:v00001025d00003321* + ID_MODEL_FROM_DATABASE=M3321 MPEG-II Audio/Video Decoder + +pci:v00001025d00005212* + ID_MODEL_FROM_DATABASE=M4803 + +pci:v00001025d00005215* + ID_MODEL_FROM_DATABASE=ALI PCI EIDE Controller + +pci:v00001025d00005217* + ID_MODEL_FROM_DATABASE=M5217H + +pci:v00001025d00005219* + ID_MODEL_FROM_DATABASE=M5219 + +pci:v00001025d00005225* + ID_MODEL_FROM_DATABASE=M5225 + +pci:v00001025d00005229* + ID_MODEL_FROM_DATABASE=M5229 + +pci:v00001025d00005235* + ID_MODEL_FROM_DATABASE=M5235 + +pci:v00001025d00005237* + ID_MODEL_FROM_DATABASE=M5237 PCI USB Host Controller + +pci:v00001025d00005240* + ID_MODEL_FROM_DATABASE=EIDE Controller + +pci:v00001025d00005241* + ID_MODEL_FROM_DATABASE=PCMCIA Bridge + +pci:v00001025d00005242* + ID_MODEL_FROM_DATABASE=General Purpose Controller + +pci:v00001025d00005243* + ID_MODEL_FROM_DATABASE=PCI to PCI Bridge Controller + +pci:v00001025d00005244* + ID_MODEL_FROM_DATABASE=Floppy Disk Controller + +pci:v00001025d00005247* + ID_MODEL_FROM_DATABASE=M1541 PCI to PCI Bridge + +pci:v00001025d00005251* + ID_MODEL_FROM_DATABASE=M5251 P1394 Controller + +pci:v00001025d00005427* + ID_MODEL_FROM_DATABASE=PCI to AGP Bridge + +pci:v00001025d00005451* + ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device + +pci:v00001025d00005453* + ID_MODEL_FROM_DATABASE=M5453 PCI AC-Link Controller Modem Device + +pci:v00001025d00007101* + ID_MODEL_FROM_DATABASE=M7101 PCI PMU Power Management Controller + +pci:v00001025d00007101sv000010B9sd00007101* + ID_MODEL_FROM_DATABASE=M7101 PCI PMU Power Management Controller + +pci:v00001025d00009602* + ID_MODEL_FROM_DATABASE=AMD RS780/RS880 PCI to PCI bridge (int gfx) + +pci:v00001028* + ID_VENDOR_FROM_DATABASE=Dell + +pci:v00001028d00000001* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 2/Si + +pci:v00001028d00000001sv00001028sd00000001* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 2/Si (PowerEdge 2400) + +pci:v00001028d00000002* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di + +pci:v00001028d00000002sv00001028sd00000002* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PowerEdge 4400) + +pci:v00001028d00000002sv00001028sd000000D1* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PERC 3/DiV [Viper]) + +pci:v00001028d00000002sv00001028sd000000D9* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PERC 3/DiL [Lexus]) + +pci:v00001028d00000003* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Si + +pci:v00001028d00000003sv00001028sd00000003* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Si (PowerEdge 2450) + +pci:v00001028d00000004* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di [Iguana] + +pci:v00001028d00000004sv00001028sd00000004* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di [Iguana] (PERC 3/DiF [Iguana]) + +pci:v00001028d00000006* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di + +pci:v00001028d00000007* + ID_MODEL_FROM_DATABASE=Remote Access Card III + +pci:v00001028d00000008* + ID_MODEL_FROM_DATABASE=Remote Access Card III + +pci:v00001028d00000009* + ID_MODEL_FROM_DATABASE=Remote Access Card III: BMC/SMIC device not present + +pci:v00001028d0000000A* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di + +pci:v00001028d0000000Asv00001028sd00000106* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PERC 3/DiJ [Jaguar]) + +pci:v00001028d0000000Asv00001028sd0000011B* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PERC 3/DiD [Dagger]) + +pci:v00001028d0000000Asv00001028sd00000121* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID Controller 3/Di (PERC 3/DiB [Boxster]) + +pci:v00001028d0000000C* + ID_MODEL_FROM_DATABASE=Embedded Remote Access or ERA/O + +pci:v00001028d0000000D* + ID_MODEL_FROM_DATABASE=Embedded Remote Access: BMC/SMIC device + +pci:v00001028d0000000E* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4/Di + +pci:v00001028d0000000F* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4/Di + +pci:v00001028d0000000Fsv00001028sd0000014A* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4/Di (PowerEdge 1750) + +pci:v00001028d00000010* + ID_MODEL_FROM_DATABASE=Remote Access Card 4 + +pci:v00001028d00000011* + ID_MODEL_FROM_DATABASE=Remote Access Card 4 Daughter Card + +pci:v00001028d00000012* + ID_MODEL_FROM_DATABASE=Remote Access Card 4 Daughter Card Virtual UART + +pci:v00001028d00000013* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 + +pci:v00001028d00000013sv00001028sd0000016C* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 (PowerEdge Expandable RAID Controller 4e/Si) + +pci:v00001028d00000013sv00001028sd0000016D* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 (PowerEdge Expandable RAID Controller 4e/Di) + +pci:v00001028d00000013sv00001028sd0000016E* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 (PowerEdge Expandable RAID Controller 4e/Di) + +pci:v00001028d00000013sv00001028sd0000016F* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 (PowerEdge Expandable RAID Controller 4e/Di) + +pci:v00001028d00000013sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 4 (PowerEdge Expandable RAID Controller 4e/Di) + +pci:v00001028d00000014* + ID_MODEL_FROM_DATABASE=Remote Access Card 4 Daughter Card SMIC interface + +pci:v00001028d00000015* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 5 + +pci:v00001028d00000015sv00001028sd00001F01* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 5 (PERC 5/E Adapter RAID Controller) + +pci:v00001028d00000015sv00001028sd00001F02* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 5 (PERC 5/i Adapter RAID Controller) + +pci:v00001028d00000015sv00001028sd00001F03* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller 5 (PERC 5/i Integrated RAID Controller) + +pci:v00001028d00000016* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller S300 + +pci:v00001028d00000016sv00001028sd00001F24* + ID_MODEL_FROM_DATABASE=PowerEdge Expandable RAID controller S300 (PERC S300 Controller) + +pci:v00001028d00000073* + ID_MODEL_FROM_DATABASE=NV-RAM Adapter + +pci:v00001029* + ID_VENDOR_FROM_DATABASE=Siemens Nixdorf IS + +pci:v0000102A* + ID_VENDOR_FROM_DATABASE=LSI Logic + +pci:v0000102Ad00000000* + ID_MODEL_FROM_DATABASE=HYDRA + +pci:v0000102Ad00000010* + ID_MODEL_FROM_DATABASE=ASPEN + +pci:v0000102Ad0000001F* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W /7890/7891 SCSI Controllers + +pci:v0000102Ad0000001Fsv00009005sd0000000F* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W /7890/7891 SCSI Controllers (2940U2W SCSI Controller) + +pci:v0000102Ad0000001Fsv00009005sd00000106* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W /7890/7891 SCSI Controllers (2940U2W SCSI Controller) + +pci:v0000102Ad0000001Fsv00009005sd0000A180* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W /7890/7891 SCSI Controllers (2940U2W SCSI Controller) + +pci:v0000102Ad000000C5* + ID_MODEL_FROM_DATABASE=AIC-7899 U160/m SCSI Controller + +pci:v0000102Ad000000C5sv00001028sd000000C5* + ID_MODEL_FROM_DATABASE=AIC-7899 U160/m SCSI Controller (PowerEdge 2550/2650/4600) + +pci:v0000102Ad000000CF* + ID_MODEL_FROM_DATABASE=AIC-7899P U160/m + +pci:v0000102Ad000000CFsv00001028sd00000106* + ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (PowerEdge 4600) + +pci:v0000102Ad000000CFsv00001028sd00000121* + ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (PowerEdge 2650) + +pci:v0000102B* + ID_VENDOR_FROM_DATABASE=Matrox Electronics Systems Ltd. + +pci:v0000102Bd00000010* + ID_MODEL_FROM_DATABASE=MGA-I [Impression?] + +pci:v0000102Bd00000100* + ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] + +pci:v0000102Bd00000518* + ID_MODEL_FROM_DATABASE=MGA-II [Athena] + +pci:v0000102Bd00000519* + ID_MODEL_FROM_DATABASE=MGA 2064W [Millennium] + +pci:v0000102Bd0000051A* + ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] + +pci:v0000102Bd0000051Asv0000102Bsd00000100* + ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] (MGA-1064SG Mystique) + +pci:v0000102Bd0000051Asv0000102Bsd00001100* + ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] (MGA-1084SG Mystique) + +pci:v0000102Bd0000051Asv0000102Bsd00001200* + ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] (MGA-1084SG Mystique) + +pci:v0000102Bd0000051Asv00001100sd0000102B* + ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] (MGA-1084SG Mystique) + +pci:v0000102Bd0000051Asv0000110Asd00000018* + ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] (Scenic Pro C5 (D1025)) + +pci:v0000102Bd0000051B* + ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] + +pci:v0000102Bd0000051Bsv0000102Bsd0000051B* + ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] (MGA-2164W Millennium II) + +pci:v0000102Bd0000051Bsv0000102Bsd00001100* + ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] (MGA-2164W Millennium II) + +pci:v0000102Bd0000051Bsv0000102Bsd00001200* + ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] (MGA-2164W Millennium II) + +pci:v0000102Bd0000051Bsv0000102Bsd00002100* + ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] (MGA-2164W Millennium II) + +pci:v0000102Bd0000051E* + ID_MODEL_FROM_DATABASE=MGA 1064SG [Mystique] AGP + +pci:v0000102Bd0000051F* + ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] AGP + +pci:v0000102Bd0000051Fsv0000102Bsd00002100* + ID_MODEL_FROM_DATABASE=MGA 2164W [Millennium II] AGP (MGA-2164WA [Millennium II A]) + +pci:v0000102Bd00000520* + ID_MODEL_FROM_DATABASE=MGA G200 + +pci:v0000102Bd00000520sv0000102Bsd0000DBC2* + ID_MODEL_FROM_DATABASE=MGA G200 (G200 Multi-Monitor) + +pci:v0000102Bd00000520sv0000102Bsd0000DBC8* + ID_MODEL_FROM_DATABASE=MGA G200 (G200 Multi-Monitor) + +pci:v0000102Bd00000520sv0000102Bsd0000DBE2* + ID_MODEL_FROM_DATABASE=MGA G200 (G200 Multi-Monitor) + +pci:v0000102Bd00000520sv0000102Bsd0000DBE8* + ID_MODEL_FROM_DATABASE=MGA G200 (G200 Multi-Monitor) + +pci:v0000102Bd00000520sv0000102Bsd0000FF03* + ID_MODEL_FROM_DATABASE=MGA G200 (Millennium G200 SD) + +pci:v0000102Bd00000520sv0000102Bsd0000FF04* + ID_MODEL_FROM_DATABASE=MGA G200 (Marvel G200) + +pci:v0000102Bd00000521* + ID_MODEL_FROM_DATABASE=MGA G200 AGP + +pci:v0000102Bd00000521sv00001014sd0000FF03* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) + +pci:v0000102Bd00000521sv0000102Bsd000048E9* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Mystique G200 AGP) + +pci:v0000102Bd00000521sv0000102Bsd000048F8* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 SD AGP) + +pci:v0000102Bd00000521sv0000102Bsd00004A60* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 LE AGP) + +pci:v0000102Bd00000521sv0000102Bsd00004A64* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000C93C* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000C9B0* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000C9BC* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000CA60* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G250 LE AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000CA6C* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G250 AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000DBBC* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000DBC2* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 MMS (Dual G200)) + +pci:v0000102Bd00000521sv0000102Bsd0000DBC3* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBC8* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 MMS (Dual G200)) + +pci:v0000102Bd00000521sv0000102Bsd0000DBD2* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBD3* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBD4* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBD5* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBD8* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBD9* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBE2* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 MMS (Quad G200)) + +pci:v0000102Bd00000521sv0000102Bsd0000DBE3* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBE8* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200 MMS (Quad G200)) + +pci:v0000102Bd00000521sv0000102Bsd0000DBF2* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBF3* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBF4* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBF5* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBF8* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000DBF9* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (G200 Multi-Monitor) + +pci:v0000102Bd00000521sv0000102Bsd0000F806* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Mystique G200 Video AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000FF00* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (MGA-G200 AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000FF02* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Mystique G200 AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000FF03* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Millennium G200A AGP) + +pci:v0000102Bd00000521sv0000102Bsd0000FF04* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (Marvel G200 AGP) + +pci:v0000102Bd00000521sv0000110Asd00000032* + ID_MODEL_FROM_DATABASE=MGA G200 AGP (MGA-G200 AGP) + +pci:v0000102Bd00000522* + ID_MODEL_FROM_DATABASE=MGA G200e [Pilot] ServerEngines (SEP1) + +pci:v0000102Bd00000522sv0000103Csd000031FA* + ID_MODEL_FROM_DATABASE=MGA G200e [Pilot] ServerEngines (SEP1) (ProLiant DL140 G3) + +pci:v0000102Bd00000525* + ID_MODEL_FROM_DATABASE=MGA G400/G450 + +pci:v0000102Bd00000525sv00000E11sd0000B16F* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (MGA-G400 AGP) + +pci:v0000102Bd00000525sv0000102Bsd00000328* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 16Mb SDRAM) + +pci:v0000102Bd00000525sv0000102Bsd00000338* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 16Mb SDRAM) + +pci:v0000102Bd00000525sv0000102Bsd00000378* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 32Mb SDRAM) + +pci:v0000102Bd00000525sv0000102Bsd00000541* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Dual Head) + +pci:v0000102Bd00000525sv0000102Bsd00000542* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Dual Head LX) + +pci:v0000102Bd00000525sv0000102Bsd00000543* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Single Head LX) + +pci:v0000102Bd00000525sv0000102Bsd00000641* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32Mb SDRAM Dual Head) + +pci:v0000102Bd00000525sv0000102Bsd00000642* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32Mb SDRAM Dual Head LX) + +pci:v0000102Bd00000525sv0000102Bsd00000643* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32Mb SDRAM Single Head LX) + +pci:v0000102Bd00000525sv0000102Bsd000007C0* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Dual Head LE) + +pci:v0000102Bd00000525sv0000102Bsd000007C1* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 SDR Dual Head LE) + +pci:v0000102Bd00000525sv0000102Bsd00000D41* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Dual Head PCI) + +pci:v0000102Bd00000525sv0000102Bsd00000D42* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Dual Head LX PCI) + +pci:v0000102Bd00000525sv0000102Bsd00000D43* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32Mb Dual Head PCI) + +pci:v0000102Bd00000525sv0000102Bsd00000E00* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Marvel G450 eTV) + +pci:v0000102Bd00000525sv0000102Bsd00000E01* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Marvel G450 eTV) + +pci:v0000102Bd00000525sv0000102Bsd00000E02* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Marvel G450 eTV) + +pci:v0000102Bd00000525sv0000102Bsd00000E03* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Marvel G450 eTV) + +pci:v0000102Bd00000525sv0000102Bsd00000F80* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Low Profile) + +pci:v0000102Bd00000525sv0000102Bsd00000F81* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Low Profile) + +pci:v0000102Bd00000525sv0000102Bsd00000F82* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Low Profile DVI) + +pci:v0000102Bd00000525sv0000102Bsd00000F83* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 Low Profile DVI) + +pci:v0000102Bd00000525sv0000102Bsd000019D8* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 16Mb SGRAM) + +pci:v0000102Bd00000525sv0000102Bsd000019F8* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 32Mb SGRAM) + +pci:v0000102Bd00000525sv0000102Bsd00002159* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 Dual Head 16Mb) + +pci:v0000102Bd00000525sv0000102Bsd00002179* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 MAX/Dual Head 32Mb) + +pci:v0000102Bd00000525sv0000102Bsd0000217D* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 Dual Head Max) + +pci:v0000102Bd00000525sv0000102Bsd000023C0* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450) + +pci:v0000102Bd00000525sv0000102Bsd000023C1* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450) + +pci:v0000102Bd00000525sv0000102Bsd000023C2* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 DVI) + +pci:v0000102Bd00000525sv0000102Bsd000023C3* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 DVI) + +pci:v0000102Bd00000525sv0000102Bsd00002F58* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400) + +pci:v0000102Bd00000525sv0000102Bsd00002F78* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400) + +pci:v0000102Bd00000525sv0000102Bsd00003693* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Marvel G400 AGP) + +pci:v0000102Bd00000525sv0000102Bsd00005DD0* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (4Sight II) + +pci:v0000102Bd00000525sv0000102Bsd00005F50* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (4Sight II) + +pci:v0000102Bd00000525sv0000102Bsd00005F51* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (4Sight II) + +pci:v0000102Bd00000525sv0000102Bsd00005F52* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (4Sight II) + +pci:v0000102Bd00000525sv0000102Bsd00009010* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G400 Dual Head) + +pci:v0000102Bd00000525sv00001458sd00000400* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (GA-G400) + +pci:v0000102Bd00000525sv00001705sd00000001* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32MB SGRAM) + +pci:v0000102Bd00000525sv00001705sd00000002* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 16MB SGRAM) + +pci:v0000102Bd00000525sv00001705sd00000003* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 32MB) + +pci:v0000102Bd00000525sv00001705sd00000004* + ID_MODEL_FROM_DATABASE=MGA G400/G450 (Millennium G450 16MB) + +pci:v0000102Bd00000527* + ID_MODEL_FROM_DATABASE=Parhelia + +pci:v0000102Bd00000527sv0000102Bsd00000840* + ID_MODEL_FROM_DATABASE=Parhelia (128Mb) + +pci:v0000102Bd00000527sv0000102Bsd00000850* + ID_MODEL_FROM_DATABASE=Parhelia (256MB) + +pci:v0000102Bd00000527sv0000102Bsd00000870* + ID_MODEL_FROM_DATABASE=Parhelia (MED2mp-DVI) + +pci:v0000102Bd00000527sv0000102Bsd00000880* + ID_MODEL_FROM_DATABASE=Parhelia (P-256 Edge Overlap Controller) + +pci:v0000102Bd00000528* + ID_MODEL_FROM_DATABASE=Parhelia + +pci:v0000102Bd00000528sv0000102Bsd00001020* + ID_MODEL_FROM_DATABASE=Parhelia (128MB) + +pci:v0000102Bd00000528sv0000102Bsd00001030* + ID_MODEL_FROM_DATABASE=Parhelia (256 MB Dual DVI) + +pci:v0000102Bd00000528sv0000102Bsd00001040* + ID_MODEL_FROM_DATABASE=Parhelia (MED2mp-DVI) + +pci:v0000102Bd00000528sv0000102Bsd00001050* + ID_MODEL_FROM_DATABASE=Parhelia (Sono S20) + +pci:v0000102Bd00000528sv0000102Bsd00001060* + ID_MODEL_FROM_DATABASE=Parhelia (PJ-30L) + +pci:v0000102Bd00000528sv0000102Bsd00001070* + ID_MODEL_FROM_DATABASE=Parhelia (PJ-40L) + +pci:v0000102Bd00000528sv0000102Bsd00001421* + ID_MODEL_FROM_DATABASE=Parhelia (MED5mp) + +pci:v0000102Bd00000528sv0000102Bsd00001431* + ID_MODEL_FROM_DATABASE=Parhelia (MED3mp-DVI) + +pci:v0000102Bd00000528sv0000102Bsd00001451* + ID_MODEL_FROM_DATABASE=Parhelia (MED5mp-DVI) + +pci:v0000102Bd00000528sv0000102Bsd00001491* + ID_MODEL_FROM_DATABASE=Parhelia (MED2mp-DVI) + +pci:v0000102Bd00000528sv0000102Bsd000014B1* + ID_MODEL_FROM_DATABASE=Parhelia (MED3mp-DVI) + +pci:v0000102Bd00000528sv0000102Bsd000014C1* + ID_MODEL_FROM_DATABASE=Parhelia (MED5mp-DVI) + +pci:v0000102Bd00000528sv0000102Bsd000014E1* + ID_MODEL_FROM_DATABASE=Parhelia (PCI 256MB) + +pci:v0000102Bd00000528sv0000102Bsd000014F1* + ID_MODEL_FROM_DATABASE=Parhelia (Precision SGT) + +pci:v0000102Bd00000528sv0000102Bsd00001501* + ID_MODEL_FROM_DATABASE=Parhelia (ATC-4MP) + +pci:v0000102Bd00000528sv0000102Bsd00001511* + ID_MODEL_FROM_DATABASE=Parhelia (ATC-4MP) + +pci:v0000102Bd00000528sv0000102Bsd00001521* + ID_MODEL_FROM_DATABASE=Parhelia (TheatreVUE T30) + +pci:v0000102Bd00000528sv0000102Bsd00001531* + ID_MODEL_FROM_DATABASE=Parhelia (TheatreVUE T20) + +pci:v0000102Bd00000528sv0000102Bsd00001541* + ID_MODEL_FROM_DATABASE=Parhelia (MED2mp-DVI) + +pci:v0000102Bd00000528sv0000102Bsd00001551* + ID_MODEL_FROM_DATABASE=Parhelia (MED3mp-DVI) + +pci:v0000102Bd00000528sv0000102Bsd00001561* + ID_MODEL_FROM_DATABASE=Parhelia (MED5mp-DVI) + +pci:v0000102Bd00000528sv0000102Bsd00001571* + ID_MODEL_FROM_DATABASE=Parhelia (DL256 PCI) + +pci:v0000102Bd00000528sv0000102Bsd00001591* + ID_MODEL_FROM_DATABASE=Parhelia (Precision SDT) + +pci:v0000102Bd00000528sv0000102Bsd000015A1* + ID_MODEL_FROM_DATABASE=Parhelia (MED4mp-DVI) + +pci:v0000102Bd00000528sv0000102Bsd00002011* + ID_MODEL_FROM_DATABASE=Parhelia (HR256) + +pci:v0000102Bd00000528sv0000102Bsd00002021* + ID_MODEL_FROM_DATABASE=Parhelia (QID Pro) + +pci:v0000102Bd00000528sv0000102Bsd00002061* + ID_MODEL_FROM_DATABASE=Parhelia (PJ-40LP) + +pci:v0000102Bd00000528sv0000102Bsd00002081* + ID_MODEL_FROM_DATABASE=Parhelia (EWS Quad) + +pci:v0000102Bd00000528sv0000102Bsd00002411* + ID_MODEL_FROM_DATABASE=Parhelia (PPX-OUT8) + +pci:v0000102Bd00000528sv0000102Bsd00002421* + ID_MODEL_FROM_DATABASE=Parhelia (VPX-OUT8) + +pci:v0000102Bd00000528sv0000102Bsd00002441* + ID_MODEL_FROM_DATABASE=Parhelia (PPX-OUT4) + +pci:v0000102Bd00000528sv0000102Bsd00002451* + ID_MODEL_FROM_DATABASE=Parhelia (VPX-OUT4) + +pci:v0000102Bd00000528sv0000102Bsd00002491* + ID_MODEL_FROM_DATABASE=Parhelia (LPX-OUT4) + +pci:v0000102Bd00000530* + ID_MODEL_FROM_DATABASE=MGA G200EV + +pci:v0000102Bd00000532* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 + +pci:v0000102Bd00000532sv00001028sd00000235* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge R710 MGA G200eW WPCM450) + +pci:v0000102Bd00000532sv00001028sd00000236* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge R610 MGA G200eW WPCM450) + +pci:v0000102Bd00000532sv00001028sd00000237* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge T610 MGA G200eW WPCM450) + +pci:v0000102Bd00000532sv00001028sd00000287* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge M610 MGA G200eW WPCM450) + +pci:v0000102Bd00000532sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge R410 MGA G200eW WPCM450) + +pci:v0000102Bd00000532sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge T410 MGA G200eW WPCM450) + +pci:v0000102Bd00000532sv00001028sd0000029C* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge M710 MGA G200eW WPCM450) + +pci:v0000102Bd00000532sv00001028sd000002A4* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (PowerEdge T310 MGA G200eW WPCM450) + +pci:v0000102Bd00000532sv000015D9sd00000605* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (X8SIL) + +pci:v0000102Bd00000532sv000015D9sd00000624* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (X9SCM-F Motherboard) + +pci:v0000102Bd00000532sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (X9SRL-F) + +pci:v0000102Bd00000532sv000015D9sd0000A811* + ID_MODEL_FROM_DATABASE=MGA G200eW WPCM450 (H8DGU) + +pci:v0000102Bd00000533* + ID_MODEL_FROM_DATABASE=MGA G200EH + +pci:v0000102Bd00000533sv0000103Csd00003381* + ID_MODEL_FROM_DATABASE=MGA G200EH (iLO4) + +pci:v0000102Bd00000534* + ID_MODEL_FROM_DATABASE=G200eR2 + +pci:v0000102Bd00000534sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=G200eR2 (PowerEdge R320 server) + +pci:v0000102Bd00000536* + ID_MODEL_FROM_DATABASE=Integrated Matrox G200eW3 Graphics Controller + +pci:v0000102Bd00000538* + ID_MODEL_FROM_DATABASE=MGA G200eH3 + +pci:v0000102Bd00000538sv00001590sd000000E4* + ID_MODEL_FROM_DATABASE=MGA G200eH3 (iLO5 VGA) + +pci:v0000102Bd00000540* + ID_MODEL_FROM_DATABASE=M91XX + +pci:v0000102Bd00000540sv0000102Bsd00002080* + ID_MODEL_FROM_DATABASE=M91XX (M9140 LP PCIe x16) + +pci:v0000102Bd00000540sv0000102Bsd000020C0* + ID_MODEL_FROM_DATABASE=M91XX (Xenia) + +pci:v0000102Bd00000540sv0000102Bsd000020C1* + ID_MODEL_FROM_DATABASE=M91XX (Xenia Pro) + +pci:v0000102Bd00000540sv0000102Bsd00002100* + ID_MODEL_FROM_DATABASE=M91XX (M9120 PCIe x16) + +pci:v0000102Bd00000540sv0000102Bsd00002140* + ID_MODEL_FROM_DATABASE=M91XX (M9125 PCIe x16) + +pci:v0000102Bd00000540sv0000102Bsd00002180* + ID_MODEL_FROM_DATABASE=M91XX (M9120 Plus LP PCIe x16) + +pci:v0000102Bd00000540sv0000102Bsd000021C0* + ID_MODEL_FROM_DATABASE=M91XX (M9120 Plus LP PCIe x1) + +pci:v0000102Bd00000540sv0000102Bsd00002200* + ID_MODEL_FROM_DATABASE=M91XX (VDA1164 Output Board) + +pci:v0000102Bd00000540sv0000102Bsd00002240* + ID_MODEL_FROM_DATABASE=M91XX (M9148 LP PCIe x16) + +pci:v0000102Bd00000540sv0000102Bsd00002241* + ID_MODEL_FROM_DATABASE=M91XX (M9138 LP PCIe x16) + +pci:v0000102Bd00000540sv0000102Bsd00002280* + ID_MODEL_FROM_DATABASE=M91XX (M9188 ATX PCIe x16) + +pci:v0000102Bd00000540sv0000102Bsd000022C0* + ID_MODEL_FROM_DATABASE=M91XX (M9128 LP PCIe x16) + +pci:v0000102Bd00000550* + ID_MODEL_FROM_DATABASE=SV2 + +pci:v0000102Bd00000550sv0000102Bsd000000C0* + ID_MODEL_FROM_DATABASE=SV2 (MURA-IPX-I4EF) + +pci:v0000102Bd00000550sv0000102Bsd000000C1* + ID_MODEL_FROM_DATABASE=SV2 (MURA-IPX-I4DF) + +pci:v0000102Bd00000550sv0000102Bsd000000C3* + ID_MODEL_FROM_DATABASE=SV2 (MURA-IPX-I4DHF) + +pci:v0000102Bd00000550sv0000102Bsd000000C5* + ID_MODEL_FROM_DATABASE=SV2 (MURA-IPX-I4EHF) + +pci:v0000102Bd00000D10* + ID_MODEL_FROM_DATABASE=MGA Ultima/Impression + +pci:v0000102Bd00001000* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] + +pci:v0000102Bd00001000sv0000102Bsd0000FF01* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] (Productiva G100) + +pci:v0000102Bd00001000sv0000102Bsd0000FF05* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] (Productiva G100 Multi-Monitor) + +pci:v0000102Bd00001001* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP + +pci:v0000102Bd00001001sv0000102Bsd00001001* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 AGP) + +pci:v0000102Bd00001001sv0000102Bsd0000FF00* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 AGP) + +pci:v0000102Bd00001001sv0000102Bsd0000FF01* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 Productiva AGP) + +pci:v0000102Bd00001001sv0000102Bsd0000FF03* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (Millennium G100 AGP) + +pci:v0000102Bd00001001sv0000102Bsd0000FF04* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 AGP) + +pci:v0000102Bd00001001sv0000102Bsd0000FF05* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 Productiva AGP Multi-Monitor) + +pci:v0000102Bd00001001sv0000110Asd0000001E* + ID_MODEL_FROM_DATABASE=MGA G100 [Productiva] AGP (MGA-G100 AGP) + +pci:v0000102Bd00002007* + ID_MODEL_FROM_DATABASE=MGA Mistral + +pci:v0000102Bd00002527* + ID_MODEL_FROM_DATABASE=Millennium G550 + +pci:v0000102Bd00002527sv0000102Bsd00000F42* + ID_MODEL_FROM_DATABASE=Millennium G550 (Matrox G550 Low Profile PCI) + +pci:v0000102Bd00002527sv0000102Bsd00000F83* + ID_MODEL_FROM_DATABASE=Millennium G550 + +pci:v0000102Bd00002527sv0000102Bsd00000F84* + ID_MODEL_FROM_DATABASE=Millennium G550 (Dual Head DDR 32Mb) + +pci:v0000102Bd00002527sv0000102Bsd00001E41* + ID_MODEL_FROM_DATABASE=Millennium G550 + +pci:v0000102Bd00002527sv0000102Bsd000022C0* + ID_MODEL_FROM_DATABASE=Millennium G550 (G550 PCIe) + +pci:v0000102Bd00002527sv0000102Bsd00002300* + ID_MODEL_FROM_DATABASE=Millennium G550 (LP PCIE) + +pci:v0000102Bd00002537* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 + +pci:v0000102Bd00002537sv0000102Bsd00001820* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (Millennium P750 64MB) + +pci:v0000102Bd00002537sv0000102Bsd00001830* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (Millennium P650 64MB) + +pci:v0000102Bd00002537sv0000102Bsd00001850* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (RAD2mp) + +pci:v0000102Bd00002537sv0000102Bsd00001860* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (RAD3mp) + +pci:v0000102Bd00002537sv0000102Bsd00001880* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (Sono S10) + +pci:v0000102Bd00002537sv0000102Bsd00001C10* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (QID 128MB) + +pci:v0000102Bd00002537sv0000102Bsd00002811* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (Millennium P650 Low-profile PCI 64MB) + +pci:v0000102Bd00002537sv0000102Bsd00002821* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (Millennium P650 Low-profile PCI) + +pci:v0000102Bd00002537sv0000102Bsd00002841* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (RAD PCI) + +pci:v0000102Bd00002537sv0000102Bsd00002851* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (Spectrum PCI) + +pci:v0000102Bd00002537sv0000102Bsd00002871* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (EpicA TC2) + +pci:v0000102Bd00002537sv0000102Bsd00002C11* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (QID Low-profile PCI) + +pci:v0000102Bd00002537sv0000102Bsd00002C21* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (QID LP PCI LW) + +pci:v0000102Bd00002537sv0000102Bsd00002C31* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (QID LP PCI) + +pci:v0000102Bd00002537sv0000102Bsd00002C41* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (EpicA TC4) + +pci:v0000102Bd00002537sv0000102Bsd00003001* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (Extio F1400) + +pci:v0000102Bd00002537sv0000102Bsd00003011* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (Extio F1220) + +pci:v0000102Bd00002537sv0000102Bsd00003041* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (RG-200DL) + +pci:v0000102Bd00002537sv0000102Bsd00003051* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (RG-400SL) + +pci:v0000102Bd00002537sv0000102Bsd00003061* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (Extio F1420) + +pci:v0000102Bd00002537sv0000102Bsd00003081* + ID_MODEL_FROM_DATABASE=Millennium P650/P750 (Extio F1240) + +pci:v0000102Bd00002538* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe + +pci:v0000102Bd00002538sv0000102Bsd00000847* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (RAD PCIe) + +pci:v0000102Bd00002538sv0000102Bsd000008C7* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (128MB) + +pci:v0000102Bd00002538sv0000102Bsd00000907* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (64MB) + +pci:v0000102Bd00002538sv0000102Bsd00000947* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (Parhelia APVe) + +pci:v0000102Bd00002538sv0000102Bsd00000987* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (ATC PCIe 4MP) + +pci:v0000102Bd00002538sv0000102Bsd00001047* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (Millennium P650 LP PCIe 128MB) + +pci:v0000102Bd00002538sv0000102Bsd00001087* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (Millennium P650 LP PCIe 64MB) + +pci:v0000102Bd00002538sv0000102Bsd00001801* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (x1) + +pci:v0000102Bd00002538sv0000102Bsd00002538* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (Parhelia APVe) + +pci:v0000102Bd00002538sv0000102Bsd00003007* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (QID Low-profile PCIe) + +pci:v0000102Bd00002538sv0000102Bsd00003087* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (Aurora VX3mp) + +pci:v0000102Bd00002538sv0000102Bsd000030C7* + ID_MODEL_FROM_DATABASE=Millennium P650 PCIe (QID LP PCIe) + +pci:v0000102Bd00002539* + ID_MODEL_FROM_DATABASE=Millennium P690 + +pci:v0000102Bd00002539sv0000102Bsd00000040* + ID_MODEL_FROM_DATABASE=Millennium P690 (PCIe x16) + +pci:v0000102Bd00002539sv0000102Bsd00000042* + ID_MODEL_FROM_DATABASE=Millennium P690 (ONYX) + +pci:v0000102Bd00002539sv0000102Bsd00000043* + ID_MODEL_FROM_DATABASE=Millennium P690 (SPECTRA) + +pci:v0000102Bd00002539sv0000102Bsd00000080* + ID_MODEL_FROM_DATABASE=Millennium P690 (Plus LP PCIe x16) + +pci:v0000102Bd00002539sv0000102Bsd00000081* + ID_MODEL_FROM_DATABASE=Millennium P690 (LP PCIe x16) + +pci:v0000102Bd00002539sv0000102Bsd00000082* + ID_MODEL_FROM_DATABASE=Millennium P690 (RAD LPX PCIe x16) + +pci:v0000102Bd00002539sv0000102Bsd000000C0* + ID_MODEL_FROM_DATABASE=Millennium P690 (Plus LP PCI) + +pci:v0000102Bd00002539sv0000102Bsd000000C2* + ID_MODEL_FROM_DATABASE=Millennium P690 (LP PCI) + +pci:v0000102Bd00002539sv0000102Bsd000000C3* + ID_MODEL_FROM_DATABASE=Millennium P690 (RAD LPX PCI) + +pci:v0000102Bd00002539sv0000102Bsd00000101* + ID_MODEL_FROM_DATABASE=Millennium P690 (PCI) + +pci:v0000102Bd00002539sv0000102Bsd00000140* + ID_MODEL_FROM_DATABASE=Millennium P690 (LP PCIe x1) + +pci:v0000102Bd00002539sv0000102Bsd00000180* + ID_MODEL_FROM_DATABASE=Millennium P690 (Display Wall IP Decode 128 MB) + +pci:v0000102Bd00004164* + ID_MODEL_FROM_DATABASE=Morphis QxT frame grabber + +pci:v0000102Bd000043B4* + ID_MODEL_FROM_DATABASE=Morphis Qxt encoding engine + +pci:v0000102Bd00004510* + ID_MODEL_FROM_DATABASE=Morphis COM port + +pci:v0000102Bd00004536* + ID_MODEL_FROM_DATABASE=VIA Framegrabber + +pci:v0000102Bd00004686* + ID_MODEL_FROM_DATABASE=Concord GX (customized Intel 82541) + +pci:v0000102Bd0000475B* + ID_MODEL_FROM_DATABASE=Solios eCL/XCL-B frame grabber + +pci:v0000102Bd0000475D* + ID_MODEL_FROM_DATABASE=Vio frame grabber family + +pci:v0000102Bd0000475Dsv0000102Bsd00004B90* + ID_MODEL_FROM_DATABASE=Vio frame grabber family (Vio Duo frame grabber (single channel)) + +pci:v0000102Bd0000475Dsv0000102Bsd00004B91* + ID_MODEL_FROM_DATABASE=Vio frame grabber family (Vio Duo frame grabber) + +pci:v0000102Bd0000475Dsv0000102Bsd00004B92* + ID_MODEL_FROM_DATABASE=Vio frame grabber family (Vio Analog frame grabber) + +pci:v0000102Bd0000475Dsv0000102Bsd00004B93* + ID_MODEL_FROM_DATABASE=Vio frame grabber family (Vio SDI Frame Grabber) + +pci:v0000102Bd0000475Dsv0000102Bsd00004B94* + ID_MODEL_FROM_DATABASE=Vio frame grabber family (Vio DVI-A frame grabber) + +pci:v0000102Bd0000475F* + ID_MODEL_FROM_DATABASE=Solios (single-Full) CL frame grabber + +pci:v0000102Bd0000475Fsv0000102Bsd0000475F* + ID_MODEL_FROM_DATABASE=Solios (single-Full) CL frame grabber (Solios eCL/XCL-F frame grabber) + +pci:v0000102Bd0000475Fsv0000102Bsd00004D5F* + ID_MODEL_FROM_DATABASE=Solios (single-Full) CL frame grabber (Solios eV-CL (single-Full) frame grabber) + +pci:v0000102Bd0000475Fsv0000102Bsd00004E5F* + ID_MODEL_FROM_DATABASE=Solios (single-Full) CL frame grabber (Solios eM-CL (single-Full) frame grabber) + +pci:v0000102Bd000047A1* + ID_MODEL_FROM_DATABASE=Solios eA/XA frame grabber + +pci:v0000102Bd000047A1sv0000102Bsd00004BE0* + ID_MODEL_FROM_DATABASE=Solios eA/XA frame grabber (Solios eA/XA (single) frame grabber) + +pci:v0000102Bd000047A1sv0000102Bsd00004BE1* + ID_MODEL_FROM_DATABASE=Solios eA/XA frame grabber (Solios eA/XA (dual) frame grabber) + +pci:v0000102Bd000047A1sv0000102Bsd00004BE2* + ID_MODEL_FROM_DATABASE=Solios eA/XA frame grabber (Solios eA/XA (quad) frame grabber) + +pci:v0000102Bd000047A2* + ID_MODEL_FROM_DATABASE=Solios COM port + +pci:v0000102Bd000047C1* + ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber + +pci:v0000102Bd000047C1sv0000102Bsd00000000* + ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios frame grabber) + +pci:v0000102Bd000047C1sv0000102Bsd00004B80* + ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eCL/XCL (single-Medium) frame grabber) + +pci:v0000102Bd000047C1sv0000102Bsd00004B81* + ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eCL/XCL (dual-Base) frame grabber) + +pci:v0000102Bd000047C1sv0000102Bsd00004D80* + ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eV-CL (single-Medium) frame grabber) + +pci:v0000102Bd000047C1sv0000102Bsd00004D81* + ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eV-CL (dual-Base) frame grabber) + +pci:v0000102Bd000047C1sv0000102Bsd00004E80* + ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eM-CL (single-Medium) frame grabber) + +pci:v0000102Bd000047C1sv0000102Bsd00004E81* + ID_MODEL_FROM_DATABASE=Solios (dual-Base/single-Medium) CL frame grabber (Solios eM-CL (dual-Base) frame grabber) + +pci:v0000102Bd000047C2* + ID_MODEL_FROM_DATABASE=Solios COM port + +pci:v0000102Bd00004949* + ID_MODEL_FROM_DATABASE=Radient frame grabber family + +pci:v0000102Bd00004949sv0000102Bsd00000010* + ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCL (Single-full) frame grabber) + +pci:v0000102Bd00004949sv0000102Bsd00000011* + ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCLV (Single-full) frame grabber) + +pci:v0000102Bd00004949sv0000102Bsd00000020* + ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCL (Dual-base) frame grabber) + +pci:v0000102Bd00004949sv0000102Bsd00000030* + ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCL (Dual-full) frame grabber) + +pci:v0000102Bd00004949sv0000102Bsd00000040* + ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCL (Quad-base) frame grabber) + +pci:v0000102Bd00004949sv0000102Bsd00000050* + ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eCL (Golden) frame grabber) + +pci:v0000102Bd00004949sv0000102Bsd00001010* + ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eV-CXP (quad CXP-6) frame grabber) + +pci:v0000102Bd00004949sv0000102Bsd00001015* + ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eV-CXP (dual CXP-6) frame grabber) + +pci:v0000102Bd00004949sv0000102Bsd00001020* + ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eV-CXP (quad CXP-3) frame grabber) + +pci:v0000102Bd00004949sv0000102Bsd00001050* + ID_MODEL_FROM_DATABASE=Radient frame grabber family (Radient eV-CXP (Golden) frame grabber) + +pci:v0000102Bd00004CDC* + ID_MODEL_FROM_DATABASE=Morphis JPEG2000 accelerator + +pci:v0000102Bd00004F54* + ID_MODEL_FROM_DATABASE=Morphis (e)Quad frame grabber + +pci:v0000102Bd00004FC5* + ID_MODEL_FROM_DATABASE=Morphis (e)Dual frame grabber + +pci:v0000102Bd00005E10* + ID_MODEL_FROM_DATABASE=Morphis aux I/O + +pci:v0000102Bd00006573* + ID_MODEL_FROM_DATABASE=Shark 10/100 Multiport SwitchNIC + +pci:v0000102C* + ID_VENDOR_FROM_DATABASE=Chips and Technologies + +pci:v0000102Cd000000B8* + ID_MODEL_FROM_DATABASE=F64310 + +pci:v0000102Cd000000C0* + ID_MODEL_FROM_DATABASE=F69000 HiQVideo + +pci:v0000102Cd000000C0sv0000102Csd000000C0* + ID_MODEL_FROM_DATABASE=F69000 HiQVideo + +pci:v0000102Cd000000C0sv00004C53sd00001000* + ID_MODEL_FROM_DATABASE=F69000 HiQVideo (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) + +pci:v0000102Cd000000C0sv00004C53sd00001010* + ID_MODEL_FROM_DATABASE=F69000 HiQVideo (CP5/CR6 mainboard) + +pci:v0000102Cd000000C0sv00004C53sd00001020* + ID_MODEL_FROM_DATABASE=F69000 HiQVideo (VR6 mainboard) + +pci:v0000102Cd000000C0sv00004C53sd00001030* + ID_MODEL_FROM_DATABASE=F69000 HiQVideo (PC5 mainboard) + +pci:v0000102Cd000000C0sv00004C53sd00001050* + ID_MODEL_FROM_DATABASE=F69000 HiQVideo (CT7 mainboard) + +pci:v0000102Cd000000C0sv00004C53sd00001051* + ID_MODEL_FROM_DATABASE=F69000 HiQVideo (CE7 mainboard) + +pci:v0000102Cd000000D0* + ID_MODEL_FROM_DATABASE=F65545 + +pci:v0000102Cd000000D8* + ID_MODEL_FROM_DATABASE=F65545 + +pci:v0000102Cd000000DC* + ID_MODEL_FROM_DATABASE=F65548 + +pci:v0000102Cd000000E0* + ID_MODEL_FROM_DATABASE=F65550 + +pci:v0000102Cd000000E4* + ID_MODEL_FROM_DATABASE=F65554 + +pci:v0000102Cd000000E5* + ID_MODEL_FROM_DATABASE=F65555 HiQVPro + +pci:v0000102Cd000000E5sv00000E11sd0000B049* + ID_MODEL_FROM_DATABASE=F65555 HiQVPro (Armada 1700 Laptop Display Controller) + +pci:v0000102Cd000000E5sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=F65555 HiQVPro (Satellite Pro/Satellite) + +pci:v0000102Cd000000F0* + ID_MODEL_FROM_DATABASE=F68554 + +pci:v0000102Cd000000F4* + ID_MODEL_FROM_DATABASE=F68554 HiQVision + +pci:v0000102Cd000000F5* + ID_MODEL_FROM_DATABASE=F68555 + +pci:v0000102Cd00000C30* + ID_MODEL_FROM_DATABASE=F69030 + +pci:v0000102Cd00000C30sv00004C53sd00001000* + ID_MODEL_FROM_DATABASE=F69030 (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) + +pci:v0000102Cd00000C30sv00004C53sd00001050* + ID_MODEL_FROM_DATABASE=F69030 (CT7 mainboard) + +pci:v0000102Cd00000C30sv00004C53sd00001051* + ID_MODEL_FROM_DATABASE=F69030 (CE7 mainboard) + +pci:v0000102Cd00000C30sv00004C53sd00001080* + ID_MODEL_FROM_DATABASE=F69030 (CT8 mainboard) + +pci:v0000102D* + ID_VENDOR_FROM_DATABASE=Wyse Technology Inc. + +pci:v0000102Dd000050DC* + ID_MODEL_FROM_DATABASE=3328 Audio + +pci:v0000102E* + ID_VENDOR_FROM_DATABASE=Olivetti Advanced Technology + +pci:v0000102F* + ID_VENDOR_FROM_DATABASE=Toshiba America + +pci:v0000102Fd00000009* + ID_MODEL_FROM_DATABASE=r4x00 + +pci:v0000102Fd0000000A* + ID_MODEL_FROM_DATABASE=TX3927 MIPS RISC PCI Controller + +pci:v0000102Fd00000020* + ID_MODEL_FROM_DATABASE=ATM Meteor 155 + +pci:v0000102Fd00000020sv0000102Fsd000000F8* + ID_MODEL_FROM_DATABASE=ATM Meteor 155 + +pci:v0000102Fd00000030* + ID_MODEL_FROM_DATABASE=TC35815CF PCI 10/100 Mbit Ethernet Controller + +pci:v0000102Fd00000031* + ID_MODEL_FROM_DATABASE=TC35815CF PCI 10/100 Mbit Ethernet Controller with WOL + +pci:v0000102Fd00000032* + ID_MODEL_FROM_DATABASE=TC35815CF PCI 10/100 Mbit Ethernet Controller on TX4939 + +pci:v0000102Fd00000105* + ID_MODEL_FROM_DATABASE=TC86C001 [goku-s] IDE + +pci:v0000102Fd00000106* + ID_MODEL_FROM_DATABASE=TC86C001 [goku-s] USB 1.1 Host + +pci:v0000102Fd00000107* + ID_MODEL_FROM_DATABASE=TC86C001 [goku-s] USB Device Controller + +pci:v0000102Fd00000108* + ID_MODEL_FROM_DATABASE=TC86C001 [goku-s] I2C/SIO/GPIO Controller + +pci:v0000102Fd00000180* + ID_MODEL_FROM_DATABASE=TX4927/38 MIPS RISC PCI Controller + +pci:v0000102Fd00000181* + ID_MODEL_FROM_DATABASE=TX4925 MIPS RISC PCI Controller + +pci:v0000102Fd00000182* + ID_MODEL_FROM_DATABASE=TX4937 MIPS RISC PCI Controller + +pci:v0000102Fd000001B4* + ID_MODEL_FROM_DATABASE=Celleb platform IDE interface + +pci:v0000102Fd000001B5* + ID_MODEL_FROM_DATABASE=SCC USB 2.0 EHCI controller + +pci:v0000102Fd000001B6* + ID_MODEL_FROM_DATABASE=SCC USB 1.1 OHCI controller + +pci:v00001030* + ID_VENDOR_FROM_DATABASE=TMC Research + +pci:v00001031* + ID_VENDOR_FROM_DATABASE=Miro Computer Products AG + +pci:v00001031d00005601* + ID_MODEL_FROM_DATABASE=DC20 ASIC + +pci:v00001031d00005607* + ID_MODEL_FROM_DATABASE=Video I/O & motion JPEG compressor + +pci:v00001031d00005631* + ID_MODEL_FROM_DATABASE=Media 3D + +pci:v00001031d00006057* + ID_MODEL_FROM_DATABASE=MiroVideo DC10/DC30+ + +pci:v00001032* + ID_VENDOR_FROM_DATABASE=Compaq + +pci:v00001033* + ID_VENDOR_FROM_DATABASE=NEC Corporation + +pci:v00001033d00000000* + ID_MODEL_FROM_DATABASE=Vr4181A USB Host or Function Control Unit + +pci:v00001033d00000001* + ID_MODEL_FROM_DATABASE=PCI to 486-like bus Bridge + +pci:v00001033d00000002* + ID_MODEL_FROM_DATABASE=PCI to VL98 Bridge + +pci:v00001033d00000003* + ID_MODEL_FROM_DATABASE=ATM Controller + +pci:v00001033d00000004* + ID_MODEL_FROM_DATABASE=R4000 PCI Bridge + +pci:v00001033d00000005* + ID_MODEL_FROM_DATABASE=PCI to 486-like bus Bridge + +pci:v00001033d00000006* + ID_MODEL_FROM_DATABASE=PC-9800 Graphic Accelerator + +pci:v00001033d00000007* + ID_MODEL_FROM_DATABASE=PCI to UX-Bus Bridge + +pci:v00001033d00000008* + ID_MODEL_FROM_DATABASE=PC-9800 Graphic Accelerator + +pci:v00001033d00000009* + ID_MODEL_FROM_DATABASE=PCI to PC9800 Core-Graph Bridge + +pci:v00001033d00000016* + ID_MODEL_FROM_DATABASE=PCI to VL Bridge + +pci:v00001033d0000001A* + ID_MODEL_FROM_DATABASE=[Nile II] + +pci:v00001033d00000021* + ID_MODEL_FROM_DATABASE=Vrc4373 [Nile I] + +pci:v00001033d00000029* + ID_MODEL_FROM_DATABASE=PowerVR PCX1 + +pci:v00001033d0000002A* + ID_MODEL_FROM_DATABASE=PowerVR 3D + +pci:v00001033d0000002C* + ID_MODEL_FROM_DATABASE=Star Alpha 2 + +pci:v00001033d0000002D* + ID_MODEL_FROM_DATABASE=PCI to C-bus Bridge + +pci:v00001033d00000035* + ID_MODEL_FROM_DATABASE=OHCI USB Controller + +pci:v00001033d00000035sv00001033sd00000035* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (USB Controller) + +pci:v00001033d00000035sv0000103Csd00001293* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (USB add-in card) + +pci:v00001033d00000035sv0000103Csd00001294* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (USB 2.0 add-in card) + +pci:v00001033d00000035sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (USB) + +pci:v00001033d00000035sv00001186sd00000035* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (DUB-C2 USB 2.0 2-port 32-bit cardbus controller) + +pci:v00001033d00000035sv000012EEsd00007000* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (Root Hub) + +pci:v00001033d00000035sv000014C2sd00000105* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (PTI-205N USB 2.0 Host Controller) + +pci:v00001033d00000035sv00001799sd00000001* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (Root Hub) + +pci:v00001033d00000035sv00001931sd0000000A* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (GlobeTrotter Fusion Quad Lite (PPP data)) + +pci:v00001033d00000035sv00001931sd0000000B* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (GlobeTrotter Fusion Quad Lite (GSM data)) + +pci:v00001033d00000035sv0000807Dsd00000035* + ID_MODEL_FROM_DATABASE=OHCI USB Controller (PCI-USB2 (OHCI subsystem)) + +pci:v00001033d0000003B* + ID_MODEL_FROM_DATABASE=PCI to C-bus Bridge + +pci:v00001033d0000003E* + ID_MODEL_FROM_DATABASE=NAPCCARD Cardbus Controller + +pci:v00001033d00000046* + ID_MODEL_FROM_DATABASE=PowerVR PCX2 [midas] + +pci:v00001033d0000005A* + ID_MODEL_FROM_DATABASE=Vrc5074 [Nile 4] + +pci:v00001033d00000063* + ID_MODEL_FROM_DATABASE=uPD72862 [Firewarden] IEEE1394 OHCI 1.0 Link Controller + +pci:v00001033d00000067* + ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset + +pci:v00001033d00000067sv00001010sd00000020* + ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 AGP 32Mb) + +pci:v00001033d00000067sv00001010sd00000080* + ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 AGP 16Mb) + +pci:v00001033d00000067sv00001010sd00000088* + ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 16Mb) + +pci:v00001033d00000067sv00001010sd00000090* + ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 AGP 16Mb) + +pci:v00001033d00000067sv00001010sd00000098* + ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 16Mb) + +pci:v00001033d00000067sv00001010sd000000A0* + ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 AGP 32Mb) + +pci:v00001033d00000067sv00001010sd000000A8* + ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 32Mb) + +pci:v00001033d00000067sv00001010sd00000120* + ID_MODEL_FROM_DATABASE=PowerVR Neon 250 Chipset (PowerVR Neon 250 AGP 32Mb) + +pci:v00001033d00000072* + ID_MODEL_FROM_DATABASE=uPD72874 IEEE1394 OHCI 1.1 3-port PHY-Link Ctrlr + +pci:v00001033d00000074* + ID_MODEL_FROM_DATABASE=56k Voice Modem + +pci:v00001033d00000074sv00001033sd00008014* + ID_MODEL_FROM_DATABASE=56k Voice Modem (RCV56ACF 56k Voice Modem) + +pci:v00001033d0000009B* + ID_MODEL_FROM_DATABASE=Vrc5476 + +pci:v00001033d000000A5* + ID_MODEL_FROM_DATABASE=VRC4173 + +pci:v00001033d000000A6* + ID_MODEL_FROM_DATABASE=VRC5477 AC97 + +pci:v00001033d000000CD* + ID_MODEL_FROM_DATABASE=uPD72870 [Firewarden] IEEE1394a OHCI 1.0 Link/3-port PHY Controller + +pci:v00001033d000000CDsv000012EEsd00008011* + ID_MODEL_FROM_DATABASE=uPD72870 [Firewarden] IEEE1394a OHCI 1.0 Link/3-port PHY Controller (Root hub) + +pci:v00001033d000000CE* + ID_MODEL_FROM_DATABASE=uPD72871 [Firewarden] IEEE1394a OHCI 1.0 Link/1-port PHY Controller + +pci:v00001033d000000DF* + ID_MODEL_FROM_DATABASE=Vr4131 + +pci:v00001033d000000E0* + ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller + +pci:v00001033d000000E0sv00001186sd0000F100* + ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (DUB-C2 USB 2.0 2-port 32-bit cardbus controller) + +pci:v00001033d000000E0sv000012EEsd00007001* + ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (Root hub) + +pci:v00001033d000000E0sv000014C2sd00000205* + ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (PTI-205N USB 2.0 Host Controller) + +pci:v00001033d000000E0sv00001799sd00000002* + ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (Root Hub) + +pci:v00001033d000000E0sv0000807Dsd00001043* + ID_MODEL_FROM_DATABASE=uPD72010x USB 2.0 Controller (PCI-USB2 (EHCI subsystem)) + +pci:v00001033d000000E7* + ID_MODEL_FROM_DATABASE=uPD72873 [Firewarden] IEEE1394a OHCI 1.1 Link/2-port PHY Controller + +pci:v00001033d000000F2* + ID_MODEL_FROM_DATABASE=uPD72874 [Firewarden] IEEE1394a OHCI 1.1 Link/3-port PHY Controller + +pci:v00001033d000000F3* + ID_MODEL_FROM_DATABASE=uPD6113x Multimedia Decoder/Processor [EMMA2] + +pci:v00001033d0000010C* + ID_MODEL_FROM_DATABASE=VR7701 + +pci:v00001033d00000125* + ID_MODEL_FROM_DATABASE=uPD720400 PCI Express - PCI/PCI-X Bridge + +pci:v00001033d0000013A* + ID_MODEL_FROM_DATABASE=Dual Tuner/MPEG Encoder + +pci:v00001033d00000194* + ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller + +pci:v00001033d00000194sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (Precision M4600) + +pci:v00001033d00000194sv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (Vostro 3350) + +pci:v00001033d00000194sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (Vostro 3750) + +pci:v00001033d00000194sv00001043sd00008413* + ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (P8P67 Deluxe Motherboard) + +pci:v00001033d00000194sv0000104Dsd0000907A* + ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (Vaio VPCF1) + +pci:v00001033d00000194sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (QEMU Virtual Machine) + +pci:v00001033d00000194sv00001B96sd00000001* + ID_MODEL_FROM_DATABASE=uPD720200 USB 3.0 Host Controller (USB 3.0 PCIe Card) + +pci:v00001033d000001E7* + ID_MODEL_FROM_DATABASE=uPD72873 [Firewarden] IEEE1394a OHCI 1.1 Link/2-port PHY Controller + +pci:v00001033d000001F2* + ID_MODEL_FROM_DATABASE=uPD72874 [Firewarden] IEEE1394a OHCI 1.1 Link/3-port PHY Controller + +pci:v00001034* + ID_VENDOR_FROM_DATABASE=Framatome Connectors USA Inc. + +pci:v00001035* + ID_VENDOR_FROM_DATABASE=Comp. & Comm. Research Lab + +pci:v00001036* + ID_VENDOR_FROM_DATABASE=Future Domain Corp. + +pci:v00001036d00000000* + ID_MODEL_FROM_DATABASE=TMC-18C30 [36C70] + +pci:v00001037* + ID_VENDOR_FROM_DATABASE=Hitachi Micro Systems + +pci:v00001038* + ID_VENDOR_FROM_DATABASE=AMP, Inc + +pci:v00001039* + ID_VENDOR_FROM_DATABASE=Silicon Integrated Systems [SiS] + +pci:v00001039d00000001* + ID_MODEL_FROM_DATABASE=AGP Port (virtual PCI-to-PCI bridge) + +pci:v00001039d00000002* + ID_MODEL_FROM_DATABASE=AGP Port (virtual PCI-to-PCI bridge) + +pci:v00001039d00000003* + ID_MODEL_FROM_DATABASE=AGP Port (virtual PCI-to-PCI bridge) + +pci:v00001039d00000004* + ID_MODEL_FROM_DATABASE=PCI-to-PCI bridge + +pci:v00001039d00000004sv00001039sd00000000* + ID_MODEL_FROM_DATABASE=PCI-to-PCI bridge (PCIe x16 port) + +pci:v00001039d00000006* + ID_MODEL_FROM_DATABASE=85C501/2/3 + +pci:v00001039d00000008* + ID_MODEL_FROM_DATABASE=SiS85C503/5513 (LPC Bridge) + +pci:v00001039d00000009* + ID_MODEL_FROM_DATABASE=5595 Power Management Controller + +pci:v00001039d0000000A* + ID_MODEL_FROM_DATABASE=PCI-to-PCI bridge + +pci:v00001039d0000000Asv00001039sd00000000* + ID_MODEL_FROM_DATABASE=PCI-to-PCI bridge (PCIe x1 port) + +pci:v00001039d00000016* + ID_MODEL_FROM_DATABASE=SiS961/2/3 SMBus controller + +pci:v00001039d00000018* + ID_MODEL_FROM_DATABASE=SiS85C503/5513 (LPC Bridge) + +pci:v00001039d00000163* + ID_MODEL_FROM_DATABASE=163 802.11b/g Wireless LAN Adapter + +pci:v00001039d00000180* + ID_MODEL_FROM_DATABASE=RAID bus controller 180 SATA/PATA [SiS] + +pci:v00001039d00000181* + ID_MODEL_FROM_DATABASE=SATA + +pci:v00001039d00000182* + ID_MODEL_FROM_DATABASE=182 SATA/RAID Controller + +pci:v00001039d00000182sv00001734sd00001095* + ID_MODEL_FROM_DATABASE=182 SATA/RAID Controller (D2030-A1) + +pci:v00001039d00000186* + ID_MODEL_FROM_DATABASE=AHCI Controller (0106) + +pci:v00001039d00000190* + ID_MODEL_FROM_DATABASE=190 Ethernet Adapter + +pci:v00001039d00000191* + ID_MODEL_FROM_DATABASE=191 Gigabit Ethernet Adapter + +pci:v00001039d00000191sv00001043sd00008139* + ID_MODEL_FROM_DATABASE=191 Gigabit Ethernet Adapter (P5SD2-FM/S mainboard) + +pci:v00001039d00000200* + ID_MODEL_FROM_DATABASE=5597/5598/6326 VGA + +pci:v00001039d00000200sv00001039sd00000000* + ID_MODEL_FROM_DATABASE=5597/5598/6326 VGA (SiS5597 SVGA (Shared RAM)) + +pci:v00001039d00000204* + ID_MODEL_FROM_DATABASE=82C204 + +pci:v00001039d00000205* + ID_MODEL_FROM_DATABASE=SG86C205 + +pci:v00001039d00000300* + ID_MODEL_FROM_DATABASE=300/305 PCI/AGP VGA Display Adapter + +pci:v00001039d00000300sv0000107Dsd00002720* + ID_MODEL_FROM_DATABASE=300/305 PCI/AGP VGA Display Adapter (Leadtek WinFast VR300) + +pci:v00001039d00000310* + ID_MODEL_FROM_DATABASE=315H PCI/AGP VGA Display Adapter + +pci:v00001039d00000315* + ID_MODEL_FROM_DATABASE=315 PCI/AGP VGA Display Adapter + +pci:v00001039d00000325* + ID_MODEL_FROM_DATABASE=315PRO PCI/AGP VGA Display Adapter + +pci:v00001039d00000330* + ID_MODEL_FROM_DATABASE=330 [Xabre] PCI/AGP VGA Display Adapter + +pci:v00001039d00000406* + ID_MODEL_FROM_DATABASE=85C501/2 + +pci:v00001039d00000496* + ID_MODEL_FROM_DATABASE=85C496 + +pci:v00001039d00000530* + ID_MODEL_FROM_DATABASE=530 Host + +pci:v00001039d00000540* + ID_MODEL_FROM_DATABASE=540 Host + +pci:v00001039d00000550* + ID_MODEL_FROM_DATABASE=550 Host + +pci:v00001039d00000597* + ID_MODEL_FROM_DATABASE=5513C + +pci:v00001039d00000601* + ID_MODEL_FROM_DATABASE=85C601 + +pci:v00001039d00000620* + ID_MODEL_FROM_DATABASE=620 Host + +pci:v00001039d00000630* + ID_MODEL_FROM_DATABASE=630 Host + +pci:v00001039d00000633* + ID_MODEL_FROM_DATABASE=633 Host + +pci:v00001039d00000635* + ID_MODEL_FROM_DATABASE=635 Host + +pci:v00001039d00000645* + ID_MODEL_FROM_DATABASE=SiS645 Host & Memory & AGP Controller + +pci:v00001039d00000646* + ID_MODEL_FROM_DATABASE=SiS645DX Host & Memory & AGP Controller + +pci:v00001039d00000648* + ID_MODEL_FROM_DATABASE=645xx + +pci:v00001039d00000649* + ID_MODEL_FROM_DATABASE=SiS649 Host + +pci:v00001039d00000650* + ID_MODEL_FROM_DATABASE=650/M650 Host + +pci:v00001039d00000651* + ID_MODEL_FROM_DATABASE=651 Host + +pci:v00001039d00000655* + ID_MODEL_FROM_DATABASE=655 Host + +pci:v00001039d00000660* + ID_MODEL_FROM_DATABASE=660 Host + +pci:v00001039d00000661* + ID_MODEL_FROM_DATABASE=661FX/M661FX/M661MX Host + +pci:v00001039d00000662* + ID_MODEL_FROM_DATABASE=662 Host + +pci:v00001039d00000671* + ID_MODEL_FROM_DATABASE=671MX + +pci:v00001039d00000730* + ID_MODEL_FROM_DATABASE=730 Host + +pci:v00001039d00000733* + ID_MODEL_FROM_DATABASE=733 Host + +pci:v00001039d00000735* + ID_MODEL_FROM_DATABASE=735 Host + +pci:v00001039d00000740* + ID_MODEL_FROM_DATABASE=740 Host + +pci:v00001039d00000741* + ID_MODEL_FROM_DATABASE=741/741GX/M741 Host + +pci:v00001039d00000741sv00001849sd00000741* + ID_MODEL_FROM_DATABASE=741/741GX/M741 Host (K7S41/K7S41GX motherboard) + +pci:v00001039d00000745* + ID_MODEL_FROM_DATABASE=745 Host + +pci:v00001039d00000746* + ID_MODEL_FROM_DATABASE=746 Host + +pci:v00001039d00000755* + ID_MODEL_FROM_DATABASE=755 Host + +pci:v00001039d00000760* + ID_MODEL_FROM_DATABASE=760/M760 Host + +pci:v00001039d00000761* + ID_MODEL_FROM_DATABASE=761/M761 Host + +pci:v00001039d00000761sv00001734sd00001099* + ID_MODEL_FROM_DATABASE=761/M761 Host (D2030-A1 Motherboard) + +pci:v00001039d00000900* + ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet + +pci:v00001039d00000900sv00001019sd00000A14* + ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet (K7S5A motherboard) + +pci:v00001039d00000900sv00001039sd00000900* + ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet (SiS900 10/100 Ethernet Adapter onboard) + +pci:v00001039d00000900sv00001043sd00008035* + ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet (CUSI-FX motherboard) + +pci:v00001039d00000900sv00001043sd000080A7* + ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet (Motherboard P4S800D-X) + +pci:v00001039d00000900sv00001462sd00000900* + ID_MODEL_FROM_DATABASE=SiS900 PCI Fast Ethernet (MS-6701 motherboard) + +pci:v00001039d00000961* + ID_MODEL_FROM_DATABASE=SiS961 [MuTIOL Media IO] + +pci:v00001039d00000962* + ID_MODEL_FROM_DATABASE=SiS962 [MuTIOL Media IO] LPC Controller + +pci:v00001039d00000963* + ID_MODEL_FROM_DATABASE=SiS963 [MuTIOL Media IO] LPC Controller + +pci:v00001039d00000964* + ID_MODEL_FROM_DATABASE=SiS964 [MuTIOL Media IO] LPC Controller + +pci:v00001039d00000965* + ID_MODEL_FROM_DATABASE=SiS965 [MuTIOL Media IO] + +pci:v00001039d00000966* + ID_MODEL_FROM_DATABASE=SiS966 [MuTIOL Media IO] + +pci:v00001039d00000968* + ID_MODEL_FROM_DATABASE=SiS968 [MuTIOL Media IO] + +pci:v00001039d00001180* + ID_MODEL_FROM_DATABASE=SATA Controller / IDE mode + +pci:v00001039d00001182* + ID_MODEL_FROM_DATABASE=SATA Controller / RAID mode + +pci:v00001039d00001182sv00001039sd00000180* + ID_MODEL_FROM_DATABASE=SATA Controller / RAID mode (SiS 966 4-port SATA controller) + +pci:v00001039d00001183* + ID_MODEL_FROM_DATABASE=SATA Controller / IDE mode + +pci:v00001039d00001183sv00001039sd00000180* + ID_MODEL_FROM_DATABASE=SATA Controller / IDE mode (SiS 966 4-port SATA controller) + +pci:v00001039d00001184* + ID_MODEL_FROM_DATABASE=AHCI Controller / RAID mode + +pci:v00001039d00001185* + ID_MODEL_FROM_DATABASE=AHCI IDE Controller (0106) + +pci:v00001039d00003602* + ID_MODEL_FROM_DATABASE=83C602 + +pci:v00001039d00005107* + ID_MODEL_FROM_DATABASE=5107 + +pci:v00001039d00005300* + ID_MODEL_FROM_DATABASE=SiS540 PCI Display Adapter + +pci:v00001039d00005315* + ID_MODEL_FROM_DATABASE=550 PCI/AGP VGA Display Adapter + +pci:v00001039d00005401* + ID_MODEL_FROM_DATABASE=486 PCI Chipset + +pci:v00001039d00005511* + ID_MODEL_FROM_DATABASE=5511/5512 + +pci:v00001039d00005513* + ID_MODEL_FROM_DATABASE=5513 IDE Controller + +pci:v00001039d00005513sv00001019sd00000970* + ID_MODEL_FROM_DATABASE=5513 IDE Controller (P6STP-FL motherboard) + +pci:v00001039d00005513sv00001039sd00005513* + ID_MODEL_FROM_DATABASE=5513 IDE Controller (SiS5513 EIDE Controller (A,B step)) + +pci:v00001039d00005513sv00001043sd00008035* + ID_MODEL_FROM_DATABASE=5513 IDE Controller (CUSI-FX motherboard) + +pci:v00001039d00005513sv00001462sd00007010* + ID_MODEL_FROM_DATABASE=5513 IDE Controller (MS-6701 motherboard) + +pci:v00001039d00005513sv00001631sd00005513* + ID_MODEL_FROM_DATABASE=5513 IDE Controller (GA-8SIML Rev1.0 Motherboard) + +pci:v00001039d00005513sv00001734sd00001095* + ID_MODEL_FROM_DATABASE=5513 IDE Controller (D2030-A1 Motherboard) + +pci:v00001039d00005517* + ID_MODEL_FROM_DATABASE=5517 + +pci:v00001039d00005571* + ID_MODEL_FROM_DATABASE=5571 + +pci:v00001039d00005581* + ID_MODEL_FROM_DATABASE=5581 Pentium Chipset + +pci:v00001039d00005582* + ID_MODEL_FROM_DATABASE=5582 + +pci:v00001039d00005591* + ID_MODEL_FROM_DATABASE=5591/5592 Host + +pci:v00001039d00005596* + ID_MODEL_FROM_DATABASE=5596 Pentium Chipset + +pci:v00001039d00005597* + ID_MODEL_FROM_DATABASE=5597 [SiS5582] + +pci:v00001039d00005600* + ID_MODEL_FROM_DATABASE=5600 Host + +pci:v00001039d00006204* + ID_MODEL_FROM_DATABASE=Video decoder & MPEG interface + +pci:v00001039d00006205* + ID_MODEL_FROM_DATABASE=VGA Controller + +pci:v00001039d00006236* + ID_MODEL_FROM_DATABASE=6236 3D-AGP + +pci:v00001039d00006300* + ID_MODEL_FROM_DATABASE=630/730 PCI/AGP VGA Display Adapter + +pci:v00001039d00006300sv00001019sd00000970* + ID_MODEL_FROM_DATABASE=630/730 PCI/AGP VGA Display Adapter (P6STP-FL motherboard) + +pci:v00001039d00006300sv00001043sd00008035* + ID_MODEL_FROM_DATABASE=630/730 PCI/AGP VGA Display Adapter (CUSI-FX motherboard) + +pci:v00001039d00006300sv0000104Dsd000080E2* + ID_MODEL_FROM_DATABASE=630/730 PCI/AGP VGA Display Adapter (VAIO PCV-J200) + +pci:v00001039d00006306* + ID_MODEL_FROM_DATABASE=530/620 PCI/AGP VGA Display Adapter + +pci:v00001039d00006325* + ID_MODEL_FROM_DATABASE=65x/M650/740 PCI/AGP VGA Display Adapter + +pci:v00001039d00006325sv00001039sd00006325* + ID_MODEL_FROM_DATABASE=65x/M650/740 PCI/AGP VGA Display Adapter (SiS 651 onboard [Asus P4SC-EA]) + +pci:v00001039d00006325sv00001631sd00001004* + ID_MODEL_FROM_DATABASE=65x/M650/740 PCI/AGP VGA Display Adapter (SiS 651C onboard [Gigabyte GA-8SIML Rev1.0]) + +pci:v00001039d00006326* + ID_MODEL_FROM_DATABASE=86C326 5598/6326 + +pci:v00001039d00006326sv00001039sd00006326* + ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SiS6326 GUI Accelerator) + +pci:v00001039d00006326sv00001092sd00000A50* + ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SpeedStar A50) + +pci:v00001039d00006326sv00001092sd00000A70* + ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SpeedStar A70) + +pci:v00001039d00006326sv00001092sd00004910* + ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SpeedStar A70) + +pci:v00001039d00006326sv00001092sd00004920* + ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SpeedStar A70) + +pci:v00001039d00006326sv000010B0sd00006326* + ID_MODEL_FROM_DATABASE=86C326 5598/6326 (S6110-B (AGP)) + +pci:v00001039d00006326sv00001569sd00006326* + ID_MODEL_FROM_DATABASE=86C326 5598/6326 (SiS6326 GUI Accelerator) + +pci:v00001039d00006330* + ID_MODEL_FROM_DATABASE=661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter + +pci:v00001039d00006330sv00001039sd00006330* + ID_MODEL_FROM_DATABASE=661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter ([M]661xX/[M]741[GX]/[M]760 PCI/AGP VGA Adapter) + +pci:v00001039d00006330sv00001043sd00008113* + ID_MODEL_FROM_DATABASE=661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter (SiS Real 256E (ASUS P5S800-VM motherboard)) + +pci:v00001039d00006330sv00001458sd0000D000* + ID_MODEL_FROM_DATABASE=661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter (SiS661FX GUI 2D/3D Accelerator) + +pci:v00001039d00006330sv00001734sd00001099* + ID_MODEL_FROM_DATABASE=661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter (D2030-A1) + +pci:v00001039d00006350* + ID_MODEL_FROM_DATABASE=770/670 PCIE VGA Display Adapter + +pci:v00001039d00006351* + ID_MODEL_FROM_DATABASE=771/671 PCIE VGA Display Adapter + +pci:v00001039d00007001* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller + +pci:v00001039d00007001sv00001019sd00000A14* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (K7S5A motherboard) + +pci:v00001039d00007001sv00001039sd00007000* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (Onboard USB Controller) + +pci:v00001039d00007001sv00001462sd00005470* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (ECS K7SOM+ motherboard) + +pci:v00001039d00007001sv00001462sd00007010* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (MS-6701 motherboard) + +pci:v00001039d00007001sv00001734sd00001095* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (D2030-A1 Motherboard) + +pci:v00001039d00007002* + ID_MODEL_FROM_DATABASE=USB 2.0 Controller + +pci:v00001039d00007002sv00001462sd00005470* + ID_MODEL_FROM_DATABASE=USB 2.0 Controller (K7SOM+ 5.2C Motherboard) + +pci:v00001039d00007002sv00001462sd00007010* + ID_MODEL_FROM_DATABASE=USB 2.0 Controller (MS-6701 motherboard) + +pci:v00001039d00007002sv00001509sd00007002* + ID_MODEL_FROM_DATABASE=USB 2.0 Controller (Onboard USB Controller) + +pci:v00001039d00007002sv00001734sd00001095* + ID_MODEL_FROM_DATABASE=USB 2.0 Controller (D2030-A1) + +pci:v00001039d00007007* + ID_MODEL_FROM_DATABASE=FireWire Controller + +pci:v00001039d00007007sv00001462sd0000701D* + ID_MODEL_FROM_DATABASE=FireWire Controller (MS-6701) + +pci:v00001039d00007012* + ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller + +pci:v00001039d00007012sv00001019sd00000F05* + ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (A928 (i-Buddie)) + +pci:v00001039d00007012sv00001039sd00007012* + ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (SiS 7012 onboard [Asus P4SC-EA] AC'97 Sound Controller) + +pci:v00001039d00007012sv00001043sd0000818F* + ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (A8S-X Motherboard) + +pci:v00001039d00007012sv000013F6sd00000300* + ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (CMI9739(A) on ECS K7S series motherboard) + +pci:v00001039d00007012sv00001462sd00005850* + ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (MSI 648 Max (MS-6585)) + +pci:v00001039d00007012sv00001462sd00007010* + ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (MS-6701 motherboard) + +pci:v00001039d00007012sv000015BDsd00001001* + ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (DFI 661FX motherboard) + +pci:v00001039d00007012sv00001734sd0000109F* + ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (D2030-A1 Motherboard) + +pci:v00001039d00007012sv00001849sd00007012* + ID_MODEL_FROM_DATABASE=SiS7012 AC'97 Sound Controller (K7S41GX motherboard) + +pci:v00001039d00007013* + ID_MODEL_FROM_DATABASE=AC'97 Modem Controller + +pci:v00001039d00007016* + ID_MODEL_FROM_DATABASE=SiS7016 PCI Fast Ethernet Adapter + +pci:v00001039d00007016sv00001039sd00007016* + ID_MODEL_FROM_DATABASE=SiS7016 PCI Fast Ethernet Adapter (SiS7016 10/100 Ethernet Adapter) + +pci:v00001039d00007018* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001014sd000001B6* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001014sd000001B7* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001019sd00007018* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001025sd0000000E* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001025sd00000018* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001039sd00007018* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001043sd00001453* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001043sd0000800B* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv0000104Dsd000080E2* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator (VAIO PCV-J200) + +pci:v00001039d00007018sv00001054sd00007018* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv0000107Dsd00005330* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv0000107Dsd00005350* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001170sd00003209* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001462sd0000400A* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv000014A4sd00002089* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv000014CDsd00002194* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv000014FFsd00001100* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv0000152Dsd00008808* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001558sd00001103* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001558sd00002200* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv00001563sd00007018* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv000015C5sd00000111* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv0000270Fsd0000A171* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007018sv0000A0A0sd00000022* + ID_MODEL_FROM_DATABASE=SiS PCI Audio Accelerator + +pci:v00001039d00007019* + ID_MODEL_FROM_DATABASE=SiS7019 Audio Accelerator + +pci:v00001039d00007502* + ID_MODEL_FROM_DATABASE=Azalia Audio Controller + +pci:v00001039d00007502sv00001043sd000081A1* + ID_MODEL_FROM_DATABASE=Azalia Audio Controller (P5SD2-FM/S mainboard) + +pci:v0000103A* + ID_VENDOR_FROM_DATABASE=Seiko Epson Corporation + +pci:v0000103B* + ID_VENDOR_FROM_DATABASE=Tatung Corp. Of America + +pci:v0000103C* + ID_VENDOR_FROM_DATABASE=Hewlett-Packard Company + +pci:v0000103Cd00001005* + ID_MODEL_FROM_DATABASE=A4977A Visualize EG + +pci:v0000103Cd00001008* + ID_MODEL_FROM_DATABASE=Visualize FX + +pci:v0000103Cd00001028* + ID_MODEL_FROM_DATABASE=Tach TL Fibre Channel Host Adapter + +pci:v0000103Cd00001029* + ID_MODEL_FROM_DATABASE=Tach XL2 Fibre Channel Host Adapter + +pci:v0000103Cd00001029sv0000107Esd0000000F* + ID_MODEL_FROM_DATABASE=Tach XL2 Fibre Channel Host Adapter (Interphase 5560 Fibre Channel Adapter) + +pci:v0000103Cd00001029sv00009004sd00009210* + ID_MODEL_FROM_DATABASE=Tach XL2 Fibre Channel Host Adapter (1Gb/2Gb Family Fibre Channel Controller) + +pci:v0000103Cd00001029sv00009004sd00009211* + ID_MODEL_FROM_DATABASE=Tach XL2 Fibre Channel Host Adapter (1Gb/2Gb Family Fibre Channel Controller) + +pci:v0000103Cd0000102A* + ID_MODEL_FROM_DATABASE=Tach TS Fibre Channel Host Adapter + +pci:v0000103Cd0000102Asv0000107Esd0000000E* + ID_MODEL_FROM_DATABASE=Tach TS Fibre Channel Host Adapter (Interphase 5540/5541 Fibre Channel Adapter) + +pci:v0000103Cd0000102Asv00009004sd00009110* + ID_MODEL_FROM_DATABASE=Tach TS Fibre Channel Host Adapter (1Gb/2Gb Family Fibre Channel Controller) + +pci:v0000103Cd0000102Asv00009004sd00009111* + ID_MODEL_FROM_DATABASE=Tach TS Fibre Channel Host Adapter (1Gb/2Gb Family Fibre Channel Controller) + +pci:v0000103Cd00001030* + ID_MODEL_FROM_DATABASE=J2585A DeskDirect 10/100VG NIC + +pci:v0000103Cd00001031* + ID_MODEL_FROM_DATABASE=J2585B HP 10/100VG PCI LAN Adapter + +pci:v0000103Cd00001031sv0000103Csd00001040* + ID_MODEL_FROM_DATABASE=J2585B HP 10/100VG PCI LAN Adapter (J2973A DeskDirect 10BaseT NIC) + +pci:v0000103Cd00001031sv0000103Csd00001041* + ID_MODEL_FROM_DATABASE=J2585B HP 10/100VG PCI LAN Adapter (J2585B DeskDirect 10/100VG NIC) + +pci:v0000103Cd00001031sv0000103Csd00001042* + ID_MODEL_FROM_DATABASE=J2585B HP 10/100VG PCI LAN Adapter (J2970A DeskDirect 10BaseT/2 NIC) + +pci:v0000103Cd00001040* + ID_MODEL_FROM_DATABASE=J2973A DeskDirect 10BaseT NIC + +pci:v0000103Cd00001041* + ID_MODEL_FROM_DATABASE=J2585B DeskDirect 10/100 NIC + +pci:v0000103Cd00001042* + ID_MODEL_FROM_DATABASE=J2970A DeskDirect 10BaseT/2 NIC + +pci:v0000103Cd00001048* + ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART + +pci:v0000103Cd00001048sv0000103Csd00001049* + ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Tosca Console) + +pci:v0000103Cd00001048sv0000103Csd0000104A* + ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Tosca Secondary) + +pci:v0000103Cd00001048sv0000103Csd0000104B* + ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Maestro SP2) + +pci:v0000103Cd00001048sv0000103Csd00001223* + ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Superdome Console) + +pci:v0000103Cd00001048sv0000103Csd00001226* + ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Keystone SP2) + +pci:v0000103Cd00001048sv0000103Csd00001227* + ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Powerbar SP2) + +pci:v0000103Cd00001048sv0000103Csd00001282* + ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Everest SP2) + +pci:v0000103Cd00001048sv0000103Csd00001301* + ID_MODEL_FROM_DATABASE=Diva Serial [GSP] Multiport UART (Diva RMP3) + +pci:v0000103Cd00001054* + ID_MODEL_FROM_DATABASE=PCI Local Bus Adapter + +pci:v0000103Cd00001064* + ID_MODEL_FROM_DATABASE=79C970 PCnet Ethernet Controller + +pci:v0000103Cd0000108B* + ID_MODEL_FROM_DATABASE=Visualize FXe + +pci:v0000103Cd000010C1* + ID_MODEL_FROM_DATABASE=NetServer Smart IRQ Router + +pci:v0000103Cd000010ED* + ID_MODEL_FROM_DATABASE=TopTools Remote Control + +pci:v0000103Cd000010F0* + ID_MODEL_FROM_DATABASE=rio System Bus Adapter + +pci:v0000103Cd000010F1* + ID_MODEL_FROM_DATABASE=rio I/O Controller + +pci:v0000103Cd00001219* + ID_MODEL_FROM_DATABASE=NetServer PCI Hot-Plug Controller + +pci:v0000103Cd0000121A* + ID_MODEL_FROM_DATABASE=NetServer SMIC Controller + +pci:v0000103Cd0000121B* + ID_MODEL_FROM_DATABASE=NetServer Legacy COM Port Decoder + +pci:v0000103Cd0000121C* + ID_MODEL_FROM_DATABASE=NetServer PCI COM Port Decoder + +pci:v0000103Cd00001229* + ID_MODEL_FROM_DATABASE=zx1 System Bus Adapter + +pci:v0000103Cd0000122A* + ID_MODEL_FROM_DATABASE=zx1 I/O Controller + +pci:v0000103Cd0000122E* + ID_MODEL_FROM_DATABASE=PCI-X Local Bus Adapter + +pci:v0000103Cd0000127B* + ID_MODEL_FROM_DATABASE=sx1000 System Bus Adapter + +pci:v0000103Cd0000127C* + ID_MODEL_FROM_DATABASE=sx1000 I/O Controller + +pci:v0000103Cd0000128D* + ID_MODEL_FROM_DATABASE=Diva [GSP] Management Board + +pci:v0000103Cd00001290* + ID_MODEL_FROM_DATABASE=Auxiliary Diva Serial Port + +pci:v0000103Cd00001290sv0000103Csd00001291* + ID_MODEL_FROM_DATABASE=Auxiliary Diva Serial Port (Diva SP2) + +pci:v0000103Cd00001291* + ID_MODEL_FROM_DATABASE=Auxiliary Diva Serial Port + +pci:v0000103Cd000012B4* + ID_MODEL_FROM_DATABASE=zx1 QuickSilver AGP8x Local Bus Adapter + +pci:v0000103Cd000012EB* + ID_MODEL_FROM_DATABASE=sx2000 System Bus Adapter + +pci:v0000103Cd000012EC* + ID_MODEL_FROM_DATABASE=sx2000 I/O Controller + +pci:v0000103Cd000012EE* + ID_MODEL_FROM_DATABASE=PCI-X 2.0 Local Bus Adapter + +pci:v0000103Cd00001302* + ID_MODEL_FROM_DATABASE=RMP-3 Shared Memory Driver + +pci:v0000103Cd00001303* + ID_MODEL_FROM_DATABASE=RMP-3 (Remote Management Processor) + +pci:v0000103Cd000022F6* + ID_MODEL_FROM_DATABASE=iLO5 Virtual USB Controller + +pci:v0000103Cd000022F6sv00001590sd000000E4* + ID_MODEL_FROM_DATABASE=iLO5 Virtual USB Controller (iLO5 Standard Virtual USB Controller) + +pci:v0000103Cd00002910* + ID_MODEL_FROM_DATABASE=E2910A PCIBus Exerciser + +pci:v0000103Cd00002925* + ID_MODEL_FROM_DATABASE=E2925A 32 Bit, 33 MHzPCI Exerciser & Analyzer + +pci:v0000103Cd00003206* + ID_MODEL_FROM_DATABASE=Adaptec Embedded Serial ATA HostRAID + +pci:v0000103Cd00003220* + ID_MODEL_FROM_DATABASE=Smart Array P600 + +pci:v0000103Cd00003220sv0000103Csd00003225* + ID_MODEL_FROM_DATABASE=Smart Array P600 (3 Gb/s SAS RAID) + +pci:v0000103Cd00003230* + ID_MODEL_FROM_DATABASE=Smart Array Controller + +pci:v0000103Cd00003230sv0000103Csd00003223* + ID_MODEL_FROM_DATABASE=Smart Array Controller (Smart Array P800) + +pci:v0000103Cd00003230sv0000103Csd00003234* + ID_MODEL_FROM_DATABASE=Smart Array Controller (P400 SAS Controller) + +pci:v0000103Cd00003230sv0000103Csd00003235* + ID_MODEL_FROM_DATABASE=Smart Array Controller (P400i SAS Controller) + +pci:v0000103Cd00003230sv0000103Csd00003237* + ID_MODEL_FROM_DATABASE=Smart Array Controller (E500 SAS Controller) + +pci:v0000103Cd00003230sv0000103Csd0000323D* + ID_MODEL_FROM_DATABASE=Smart Array Controller (P700m SAS Controller) + +pci:v0000103Cd00003238* + ID_MODEL_FROM_DATABASE=Smart Array E200i (SAS Controller) + +pci:v0000103Cd00003238sv0000103Csd00003211* + ID_MODEL_FROM_DATABASE=Smart Array E200i (SAS Controller) (Smart Array E200i) + +pci:v0000103Cd00003238sv0000103Csd00003212* + ID_MODEL_FROM_DATABASE=Smart Array E200i (SAS Controller) (Smart Array E200) + +pci:v0000103Cd00003239* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers + +pci:v0000103Cd00003239sv0000103Csd000021BD* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P244br) + +pci:v0000103Cd00003239sv0000103Csd000021BE* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P741m) + +pci:v0000103Cd00003239sv0000103Csd000021BF* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (H240ar) + +pci:v0000103Cd00003239sv0000103Csd000021C0* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P440ar) + +pci:v0000103Cd00003239sv0000103Csd000021C1* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P840ar) + +pci:v0000103Cd00003239sv0000103Csd000021C2* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P440) + +pci:v0000103Cd00003239sv0000103Csd000021C3* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P441) + +pci:v0000103Cd00003239sv0000103Csd000021C4* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (Smart Array) + +pci:v0000103Cd00003239sv0000103Csd000021C5* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P841) + +pci:v0000103Cd00003239sv0000103Csd000021C6* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (H244br) + +pci:v0000103Cd00003239sv0000103Csd000021C7* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (H240) + +pci:v0000103Cd00003239sv0000103Csd000021C8* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (H241) + +pci:v0000103Cd00003239sv0000103Csd000021C9* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (Smart Array) + +pci:v0000103Cd00003239sv0000103Csd000021CA* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P246br) + +pci:v0000103Cd00003239sv0000103Csd000021CB* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P840) + +pci:v0000103Cd00003239sv0000103Csd000021CC* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (Smart Array) + +pci:v0000103Cd00003239sv0000103Csd000021CD* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (P240nr) + +pci:v0000103Cd00003239sv0000103Csd000021CE* + ID_MODEL_FROM_DATABASE=Smart Array Gen9 Controllers (H240nr) + +pci:v0000103Cd0000323A* + ID_MODEL_FROM_DATABASE=Smart Array G6 controllers + +pci:v0000103Cd0000323Asv0000103Csd00003241* + ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P212) + +pci:v0000103Cd0000323Asv0000103Csd00003243* + ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P410) + +pci:v0000103Cd0000323Asv0000103Csd00003245* + ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P410i) + +pci:v0000103Cd0000323Asv0000103Csd00003247* + ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P411) + +pci:v0000103Cd0000323Asv0000103Csd00003249* + ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P812) + +pci:v0000103Cd0000323Asv0000103Csd0000324A* + ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array 712m (Mezzanine RAID controller)) + +pci:v0000103Cd0000323Asv0000103Csd0000324B* + ID_MODEL_FROM_DATABASE=Smart Array G6 controllers (Smart Array P711m (Mezzanine RAID controller)) + +pci:v0000103Cd0000323B* + ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers + +pci:v0000103Cd0000323Bsv0000103Csd00003350* + ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers (P222) + +pci:v0000103Cd0000323Bsv0000103Csd00003351* + ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers (P420) + +pci:v0000103Cd0000323Bsv0000103Csd00003352* + ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers (P421) + +pci:v0000103Cd0000323Bsv0000103Csd00003354* + ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers (P420i) + +pci:v0000103Cd0000323Bsv0000103Csd00003355* + ID_MODEL_FROM_DATABASE=Smart Array Gen8 Controllers (P220i) + +pci:v0000103Cd0000323C* + ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers + +pci:v0000103Cd0000323Csv0000103Csd00001920* + ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P430i) + +pci:v0000103Cd0000323Csv0000103Csd00001921* + ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P830i) + +pci:v0000103Cd0000323Csv0000103Csd00001922* + ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P430) + +pci:v0000103Cd0000323Csv0000103Csd00001923* + ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P431) + +pci:v0000103Cd0000323Csv0000103Csd00001924* + ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P830) + +pci:v0000103Cd0000323Csv0000103Csd00001925* + ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (Smart Array) + +pci:v0000103Cd0000323Csv0000103Csd00001926* + ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P731m) + +pci:v0000103Cd0000323Csv0000103Csd00001928* + ID_MODEL_FROM_DATABASE=Smart Array Gen8+ Controllers (P230i) + +pci:v0000103Cd00003300* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller + +pci:v0000103Cd00003300sv0000103Csd00003304* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller (iLO2) + +pci:v0000103Cd00003300sv0000103Csd00003305* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller (iLO2) + +pci:v0000103Cd00003300sv0000103Csd00003309* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller (iLO2 GXL/iLO3 GXE) + +pci:v0000103Cd00003300sv0000103Csd0000330E* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller (iLO3) + +pci:v0000103Cd00003300sv0000103Csd00003381* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Virtual USB Controller (iLO4) + +pci:v0000103Cd00003301* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Serial Port + +pci:v0000103Cd00003301sv0000103Csd00003304* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Serial Port (iLO2) + +pci:v0000103Cd00003301sv0000103Csd00003305* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Serial Port (iLO2) + +pci:v0000103Cd00003301sv0000103Csd0000330E* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Serial Port (iLO3) + +pci:v0000103Cd00003301sv0000103Csd00003381* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Serial Port (iLO4) + +pci:v0000103Cd00003302* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard KCS Interface + +pci:v0000103Cd00003302sv0000103Csd00003304* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard KCS Interface (iLO2) + +pci:v0000103Cd00003302sv0000103Csd00003305* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard KCS Interface (iLO2) + +pci:v0000103Cd00003302sv0000103Csd0000330E* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard KCS Interface (iLO3) + +pci:v0000103Cd00003302sv0000103Csd00003381* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard KCS Interface (iLO4) + +pci:v0000103Cd00003305* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out (iLO2) Controller + +pci:v0000103Cd00003306* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Slave Instrumentation & System Support + +pci:v0000103Cd00003306sv0000103Csd0000330E* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Slave Instrumentation & System Support (iLO3) + +pci:v0000103Cd00003306sv0000103Csd00003381* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Slave Instrumentation & System Support (iLO4) + +pci:v0000103Cd00003306sv00001590sd000000E4* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Slave Instrumentation & System Support (iLO5) + +pci:v0000103Cd00003307* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Management Processor Support and Messaging + +pci:v0000103Cd00003307sv0000103Csd00003309* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Management Processor Support and Messaging (iLO 2) + +pci:v0000103Cd00003307sv0000103Csd0000330E* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Management Processor Support and Messaging (iLO3) + +pci:v0000103Cd00003307sv0000103Csd00003381* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard Management Processor Support and Messaging (iLO4) + +pci:v0000103Cd00003308* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard MS Watchdog Timer + +pci:v0000103Cd00003308sv0000103Csd0000330E* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard MS Watchdog Timer (iLO3) + +pci:v0000103Cd00003308sv0000103Csd00003381* + ID_MODEL_FROM_DATABASE=Integrated Lights-Out Standard MS Watchdog Timer (iLO4) + +pci:v0000103Cd00004030* + ID_MODEL_FROM_DATABASE=zx2 System Bus Adapter + +pci:v0000103Cd00004031* + ID_MODEL_FROM_DATABASE=zx2 I/O Controller + +pci:v0000103Cd00004037* + ID_MODEL_FROM_DATABASE=PCIe Local Bus Adapter + +pci:v0000103Cd00009602* + ID_MODEL_FROM_DATABASE=AMD RS780/RS880 PCI to PCI bridge (int gfx) + +pci:v0000103Cd00009602sv0000103Csd00001609* + ID_MODEL_FROM_DATABASE=AMD RS780/RS880 PCI to PCI bridge (int gfx) (ProLiant MicroServer N36L) + +pci:v0000103E* + ID_VENDOR_FROM_DATABASE=Solliday Engineering + +pci:v0000103F* + ID_VENDOR_FROM_DATABASE=Synopsys/Logic Modeling Group + +pci:v00001040* + ID_VENDOR_FROM_DATABASE=Accelgraphics Inc. + +pci:v00001041* + ID_VENDOR_FROM_DATABASE=Computrend + +pci:v00001042* + ID_VENDOR_FROM_DATABASE=Micron + +pci:v00001042d00001000* + ID_MODEL_FROM_DATABASE=PC Tech RZ1000 + +pci:v00001042d00001001* + ID_MODEL_FROM_DATABASE=PC Tech RZ1001 + +pci:v00001042d00003000* + ID_MODEL_FROM_DATABASE=Samurai_0 + +pci:v00001042d00003010* + ID_MODEL_FROM_DATABASE=Samurai_1 + +pci:v00001042d00003020* + ID_MODEL_FROM_DATABASE=Samurai_IDE + +pci:v00001043* + ID_VENDOR_FROM_DATABASE=ASUSTeK Computer Inc. + +pci:v00001043d00000464* + ID_MODEL_FROM_DATABASE=Radeon R9 270x GPU + +pci:v00001043d00000521* + ID_MODEL_FROM_DATABASE=RX580 [RX 580 Dual O8G] + +pci:v00001043d00000675* + ID_MODEL_FROM_DATABASE=ISDNLink P-IN100-ST-D + +pci:v00001043d00000675sv00000675sd00001704* + ID_MODEL_FROM_DATABASE=ISDNLink P-IN100-ST-D (ISDN Adapter (PCI Bus, D, C)) + +pci:v00001043d00000675sv00000675sd00001707* + ID_MODEL_FROM_DATABASE=ISDNLink P-IN100-ST-D (ISDN Adapter (PCI Bus, DV, W)) + +pci:v00001043d00000675sv000010CFsd0000105E* + ID_MODEL_FROM_DATABASE=ISDNLink P-IN100-ST-D (ISDN Adapter (PCI Bus, DV, W)) + +pci:v00001043d00009602* + ID_MODEL_FROM_DATABASE=AMD RS780/RS880 PCI to PCI bridge (int gfx) + +pci:v00001043d00009602sv00001043sd000083A2* + ID_MODEL_FROM_DATABASE=AMD RS780/RS880 PCI to PCI bridge (int gfx) (M4A785TD Motherboard) + +pci:v00001044* + ID_VENDOR_FROM_DATABASE=Adaptec (formerly DPT) + +pci:v00001044d00001012* + ID_MODEL_FROM_DATABASE=Domino RAID Engine + +pci:v00001044d0000A400* + ID_MODEL_FROM_DATABASE=SmartCache/Raid I-IV Controller + +pci:v00001044d0000A500* + ID_MODEL_FROM_DATABASE=PCI Bridge + +pci:v00001044d0000A501* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller + +pci:v00001044d0000A501sv00001044sd0000C001* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM1554U2 Ultra2 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C002* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM1654U2 Ultra2 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C003* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM1564U3 Ultra3 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C004* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM1564U3 Ultra3 Dual Channel) + +pci:v00001044d0000A501sv00001044sd0000C005* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM1554U2 Ultra2 Single Channel (NON ACPI)) + +pci:v00001044d0000A501sv00001044sd0000C00A* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2554U2 Ultra2 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C00B* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2654U2 Ultra2 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C00C* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2664U3 Ultra3 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C00D* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2664U3 Ultra3 Dual Channel) + +pci:v00001044d0000A501sv00001044sd0000C00E* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2554U2 Ultra2 Single Channel (NON ACPI)) + +pci:v00001044d0000A501sv00001044sd0000C00F* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2654U2 Ultra2 Single Channel (NON ACPI)) + +pci:v00001044d0000A501sv00001044sd0000C014* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3754U2 Ultra2 Single Channel (NON ACPI)) + +pci:v00001044d0000A501sv00001044sd0000C015* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3755U2B Ultra2 Single Channel (NON ACPI)) + +pci:v00001044d0000A501sv00001044sd0000C016* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3755F Fibre Channel (NON ACPI)) + +pci:v00001044d0000A501sv00001044sd0000C01E* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3757U2 Ultra2 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C01F* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3757U2 Ultra2 Dual Channel) + +pci:v00001044d0000A501sv00001044sd0000C020* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3767U3 Ultra3 Dual Channel) + +pci:v00001044d0000A501sv00001044sd0000C021* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM3767U3 Ultra3 Quad Channel) + +pci:v00001044d0000A501sv00001044sd0000C028* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2865U3 Ultra3 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C029* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2865U3 Ultra3 Dual Channel) + +pci:v00001044d0000A501sv00001044sd0000C02A* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (PM2865F Fibre Channel) + +pci:v00001044d0000A501sv00001044sd0000C03C* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (2000S Ultra3 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C03D* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (2000S Ultra3 Dual Channel) + +pci:v00001044d0000A501sv00001044sd0000C03E* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (2000F Fibre Channel) + +pci:v00001044d0000A501sv00001044sd0000C046* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3000S Ultra3 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C047* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3000S Ultra3 Dual Channel) + +pci:v00001044d0000A501sv00001044sd0000C048* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3000F Fibre Channel) + +pci:v00001044d0000A501sv00001044sd0000C050* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (5000S Ultra3 Single Channel) + +pci:v00001044d0000A501sv00001044sd0000C051* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (5000S Ultra3 Dual Channel) + +pci:v00001044d0000A501sv00001044sd0000C052* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (5000F Fibre Channel) + +pci:v00001044d0000A501sv00001044sd0000C05A* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (2400A UDMA Four Channel) + +pci:v00001044d0000A501sv00001044sd0000C05B* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (2400A UDMA Four Channel DAC) + +pci:v00001044d0000A501sv00001044sd0000C064* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3010S Ultra3 Dual Channel) + +pci:v00001044d0000A501sv00001044sd0000C065* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3410S Ultra160 Four Channel) + +pci:v00001044d0000A501sv00001044sd0000C066* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (3010S Fibre Channel) + +pci:v00001044d0000A511* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller + +pci:v00001044d0000A511sv00001044sd0000C032* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (ASR-2005S I2O Zero Channel) + +pci:v00001044d0000A511sv00001044sd0000C035* + ID_MODEL_FROM_DATABASE=SmartRAID V Controller (ASR-2010S I2O Zero Channel) + +pci:v00001044d0000C066* + ID_MODEL_FROM_DATABASE=3010S Ultra3 Dual Channel + +pci:v00001045* + ID_VENDOR_FROM_DATABASE=OPTi Inc. + +pci:v00001045d0000A0F8* + ID_MODEL_FROM_DATABASE=82C750 [Vendetta] USB Controller + +pci:v00001045d0000C101* + ID_MODEL_FROM_DATABASE=92C264 + +pci:v00001045d0000C178* + ID_MODEL_FROM_DATABASE=92C178 + +pci:v00001045d0000C556* + ID_MODEL_FROM_DATABASE=82X556 [Viper] + +pci:v00001045d0000C557* + ID_MODEL_FROM_DATABASE=82C557 [Viper-M] + +pci:v00001045d0000C558* + ID_MODEL_FROM_DATABASE=82C558 [Viper-M ISA+IDE] + +pci:v00001045d0000C567* + ID_MODEL_FROM_DATABASE=82C750 [Vendetta], device 0 + +pci:v00001045d0000C568* + ID_MODEL_FROM_DATABASE=82C750 [Vendetta], device 1 + +pci:v00001045d0000C569* + ID_MODEL_FROM_DATABASE=82C579 [Viper XPress+ Chipset] + +pci:v00001045d0000C621* + ID_MODEL_FROM_DATABASE=82C621 [Viper-M/N+] + +pci:v00001045d0000C700* + ID_MODEL_FROM_DATABASE=82C700 [FireStar] + +pci:v00001045d0000C701* + ID_MODEL_FROM_DATABASE=82C701 [FireStar Plus] + +pci:v00001045d0000C814* + ID_MODEL_FROM_DATABASE=82C814 [Firebridge 1] + +pci:v00001045d0000C822* + ID_MODEL_FROM_DATABASE=82C822 + +pci:v00001045d0000C824* + ID_MODEL_FROM_DATABASE=82C824 + +pci:v00001045d0000C825* + ID_MODEL_FROM_DATABASE=82C825 [Firebridge 2] + +pci:v00001045d0000C832* + ID_MODEL_FROM_DATABASE=82C832 + +pci:v00001045d0000C861* + ID_MODEL_FROM_DATABASE=82C861 OHCI USB Host + +pci:v00001045d0000C881* + ID_MODEL_FROM_DATABASE=82C881 [FireLink] 1394 OHCI Link Controller + +pci:v00001045d0000C895* + ID_MODEL_FROM_DATABASE=82C895 + +pci:v00001045d0000C935* + ID_MODEL_FROM_DATABASE=EV1935 ECTIVA MachOne PCIAudio + +pci:v00001045d0000D568* + ID_MODEL_FROM_DATABASE=82C825 [Firebridge 2] + +pci:v00001045d0000D721* + ID_MODEL_FROM_DATABASE=IDE [FireStar] + +pci:v00001046* + ID_VENDOR_FROM_DATABASE=IPC Corporation, Ltd. + +pci:v00001047* + ID_VENDOR_FROM_DATABASE=Genoa Systems Corp + +pci:v00001048* + ID_VENDOR_FROM_DATABASE=Elsa AG + +pci:v00001048d00000C60* + ID_MODEL_FROM_DATABASE=Gladiac MX + +pci:v00001048d00000D22* + ID_MODEL_FROM_DATABASE=Quadro4 900XGL [ELSA GLoria4 900XGL] + +pci:v00001048d00001000* + ID_MODEL_FROM_DATABASE=QuickStep 1000 + +pci:v00001048d00003000* + ID_MODEL_FROM_DATABASE=QuickStep 3000 + +pci:v00001048d00008901* + ID_MODEL_FROM_DATABASE=Gloria XL + +pci:v00001048d00008901sv00001048sd00000935* + ID_MODEL_FROM_DATABASE=Gloria XL (GLoria XL (Virge)) + +pci:v00001049* + ID_VENDOR_FROM_DATABASE=Fountain Technologies, Inc. + +pci:v0000104A* + ID_VENDOR_FROM_DATABASE=STMicroelectronics + +pci:v0000104Ad00000000* + ID_MODEL_FROM_DATABASE=STLS2F Host Bridge + +pci:v0000104Ad00000008* + ID_MODEL_FROM_DATABASE=STG 2000X + +pci:v0000104Ad00000009* + ID_MODEL_FROM_DATABASE=STG 1764X + +pci:v0000104Ad00000010* + ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] + +pci:v0000104Ad00000010sv0000104Asd00004018* + ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] (ST PowerVR Kyro (64MB AGP TVO)) + +pci:v0000104Ad00000010sv00001681sd00000010* + ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] (PowerVR Kyro II [3D Prophet 4500]) + +pci:v0000104Ad00000010sv00001681sd00000028* + ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] (3D Prophet 4000XT) + +pci:v0000104Ad00000010sv00001681sd0000C010* + ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] (3D Prophet 4500 TV-Out) + +pci:v0000104Ad00000010sv00001681sd0000C069* + ID_MODEL_FROM_DATABASE=STG4000 [3D Prophet Kyro Series] (3D Prophet 4000XT) + +pci:v0000104Ad00000201* + ID_MODEL_FROM_DATABASE=STPC Vega Northbridge + +pci:v0000104Ad00000209* + ID_MODEL_FROM_DATABASE=STPC Consumer/Industrial North- and Southbridge + +pci:v0000104Ad0000020A* + ID_MODEL_FROM_DATABASE=STPC Atlas/ConsumerS/Consumer IIA Northbridge + +pci:v0000104Ad0000020B* + ID_MODEL_FROM_DATABASE=STPC Consumer II ISA Bridge + +pci:v0000104Ad00000210* + ID_MODEL_FROM_DATABASE=STPC Atlas ISA Bridge + +pci:v0000104Ad0000021A* + ID_MODEL_FROM_DATABASE=STPC Consumer S Southbridge + +pci:v0000104Ad0000021B* + ID_MODEL_FROM_DATABASE=STPC Consumer IIA Southbridge + +pci:v0000104Ad00000220* + ID_MODEL_FROM_DATABASE=STPC Industrial PCI to PCCard bridge + +pci:v0000104Ad00000228* + ID_MODEL_FROM_DATABASE=STPC Atlas IDE + +pci:v0000104Ad00000229* + ID_MODEL_FROM_DATABASE=STPC Vega IDE + +pci:v0000104Ad00000230* + ID_MODEL_FROM_DATABASE=STPC Atlas/Vega OHCI USB Controller + +pci:v0000104Ad00000238* + ID_MODEL_FROM_DATABASE=STPC Vega LAN + +pci:v0000104Ad00000500* + ID_MODEL_FROM_DATABASE=ST70137 [Unicorn] ADSL DMT Transceiver + +pci:v0000104Ad00000500sv0000104Asd00000500* + ID_MODEL_FROM_DATABASE=ST70137 [Unicorn] ADSL DMT Transceiver (BeWAN ADSL PCI st) + +pci:v0000104Ad00000564* + ID_MODEL_FROM_DATABASE=STPC Client Northbridge + +pci:v0000104Ad00000981* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v0000104Ad00001746* + ID_MODEL_FROM_DATABASE=STG 1764X + +pci:v0000104Ad00002774* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v0000104Ad00003520* + ID_MODEL_FROM_DATABASE=MPEG-II decoder card + +pci:v0000104Ad000055CC* + ID_MODEL_FROM_DATABASE=STPC Client Southbridge + +pci:v0000104B* + ID_VENDOR_FROM_DATABASE=BusLogic + +pci:v0000104Bd00000140* + ID_MODEL_FROM_DATABASE=BT-946C (old) [multimaster 01] + +pci:v0000104Bd00001040* + ID_MODEL_FROM_DATABASE=BT-946C (BA80C30) [MultiMaster 10] + +pci:v0000104Bd00008130* + ID_MODEL_FROM_DATABASE=Flashpoint LT + +pci:v0000104C* + ID_VENDOR_FROM_DATABASE=Texas Instruments + +pci:v0000104Cd00000500* + ID_MODEL_FROM_DATABASE=100 MBit LAN Controller + +pci:v0000104Cd00000508* + ID_MODEL_FROM_DATABASE=TMS380C2X Compressor Interface + +pci:v0000104Cd00001000* + ID_MODEL_FROM_DATABASE=Eagle i/f AS + +pci:v0000104Cd0000104C* + ID_MODEL_FROM_DATABASE=PCI1510 PC card Cardbus Controller + +pci:v0000104Cd00003D04* + ID_MODEL_FROM_DATABASE=TVP4010 [Permedia] + +pci:v0000104Cd00003D07* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] + +pci:v0000104Cd00003D07sv00001011sd00004D10* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (Comet) + +pci:v0000104Cd00003D07sv00001040sd0000000F* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (AccelStar II) + +pci:v0000104Cd00003D07sv00001040sd00000011* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (AccelStar II) + +pci:v0000104Cd00003D07sv00001048sd00000A31* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (WINNER 2000) + +pci:v0000104Cd00003D07sv00001048sd00000A32* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) + +pci:v0000104Cd00003D07sv00001048sd00000A34* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) + +pci:v0000104Cd00003D07sv00001048sd00000A35* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) + +pci:v0000104Cd00003D07sv00001048sd00000A36* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) + +pci:v0000104Cd00003D07sv00001048sd00000A43* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) + +pci:v0000104Cd00003D07sv00001048sd00000A44* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (GLoria Synergy) + +pci:v0000104Cd00003D07sv0000107Dsd00002633* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (WinFast 3D L2300) + +pci:v0000104Cd00003D07sv00001092sd00000126* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000127* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000136* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000141* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000146* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000148* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000149* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000152* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000154* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000155* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000156* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001092sd00000157* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (FIRE GL 1000 PRO) + +pci:v0000104Cd00003D07sv00001097sd00003D01* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (Jeronimo Pro) + +pci:v0000104Cd00003D07sv00001102sd0000100F* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (Graphics Blaster Extreme) + +pci:v0000104Cd00003D07sv00003D3Dsd00000100* + ID_MODEL_FROM_DATABASE=TVP4020 [Permedia 2] (Reference Permedia 2 3D) + +pci:v0000104Cd00008000* + ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller + +pci:v0000104Cd00008000sv0000105Esd00008003* + ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (FireBoard200) + +pci:v0000104Cd00008000sv00001443sd00008003* + ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (FireBoard200) + +pci:v0000104Cd00008000sv00001443sd00008005* + ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (FireBoard400) + +pci:v0000104Cd00008000sv00001443sd00008006* + ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (FireBoard400) + +pci:v0000104Cd00008000sv0000E4BFsd00001010* + ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (CF1-1-SNARE) + +pci:v0000104Cd00008000sv0000E4BFsd00001020* + ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (CF1-2-SNARE) + +pci:v0000104Cd00008000sv0000E4BFsd00001040* + ID_MODEL_FROM_DATABASE=PCILynx/PCILynx2 IEEE 1394 Link Layer Controller (FireCompact400) + +pci:v0000104Cd00008009* + ID_MODEL_FROM_DATABASE=TSB12LV22 IEEE-1394 Controller + +pci:v0000104Cd00008009sv0000104Dsd00008032* + ID_MODEL_FROM_DATABASE=TSB12LV22 IEEE-1394 Controller (8032 OHCI i.LINK (IEEE 1394) Controller) + +pci:v0000104Cd00008009sv00001443sd00008010* + ID_MODEL_FROM_DATABASE=TSB12LV22 IEEE-1394 Controller (FireBoard400-OHCI) + +pci:v0000104Cd00008017* + ID_MODEL_FROM_DATABASE=PCI4410 FireWire Controller + +pci:v0000104Cd00008019* + ID_MODEL_FROM_DATABASE=TSB12LV23 IEEE-1394 Controller + +pci:v0000104Cd00008019sv000011BDsd0000000A* + ID_MODEL_FROM_DATABASE=TSB12LV23 IEEE-1394 Controller (Studio DV500-1394) + +pci:v0000104Cd00008019sv000011BDsd0000000E* + ID_MODEL_FROM_DATABASE=TSB12LV23 IEEE-1394 Controller (Studio DV) + +pci:v0000104Cd00008019sv00001443sd00008010* + ID_MODEL_FROM_DATABASE=TSB12LV23 IEEE-1394 Controller (FireBoard400-OHCI) + +pci:v0000104Cd00008019sv0000E4BFsd00001010* + ID_MODEL_FROM_DATABASE=TSB12LV23 IEEE-1394 Controller (CF2-1-CYMBAL) + +pci:v0000104Cd00008020* + ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) + +pci:v0000104Cd00008020sv00001028sd000000D8* + ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) (Precision 530) + +pci:v0000104Cd00008020sv0000104Dsd000080E2* + ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) (VAIO PCV-J200) + +pci:v0000104Cd00008020sv000011BDsd0000000F* + ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) (Studio DV500-1394) + +pci:v0000104Cd00008020sv000011BDsd0000001C* + ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) (Excalibur 4.1) + +pci:v0000104Cd00008020sv00001443sd00008010* + ID_MODEL_FROM_DATABASE=TSB12LV26 IEEE-1394 Controller (Link) (FireBoard400-OHCI) + +pci:v0000104Cd00008021* + ID_MODEL_FROM_DATABASE=TSB43AA22 IEEE-1394 Controller (PHY/Link Integrated) + +pci:v0000104Cd00008021sv0000104Dsd000080DF* + ID_MODEL_FROM_DATABASE=TSB43AA22 IEEE-1394 Controller (PHY/Link Integrated) (Vaio PCG-FX403) + +pci:v0000104Cd00008021sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=TSB43AA22 IEEE-1394 Controller (PHY/Link Integrated) (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v0000104Cd00008022* + ID_MODEL_FROM_DATABASE=TSB43AB22 IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] + +pci:v0000104Cd00008022sv0000104Csd00008023* + ID_MODEL_FROM_DATABASE=TSB43AB22 IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (TSB43AB22/A IEEE-1394a-2000 Controller (PHY/Link)) + +pci:v0000104Cd00008023* + ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] + +pci:v0000104Cd00008023sv00001028sd00000168* + ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (Precision Workstation 670 Mainboard) + +pci:v0000104Cd00008023sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (NC8000 laptop) + +pci:v0000104Cd00008023sv00001043sd0000808B* + ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (K8N4/A8N Series Mainboard) + +pci:v0000104Cd00008023sv00001043sd0000815B* + ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (P5W DH Deluxe Motherboard) + +pci:v0000104Cd00008023sv00001443sd00008023* + ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (FireCard400) + +pci:v0000104Cd00008023sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] (Desktop Board DP35DP) + +pci:v0000104Cd00008024* + ID_MODEL_FROM_DATABASE=TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link) + +pci:v0000104Cd00008024sv0000107Dsd00006620* + ID_MODEL_FROM_DATABASE=TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link) (Winfast DV2000 FireWire Controller) + +pci:v0000104Cd00008024sv00001443sd00008024* + ID_MODEL_FROM_DATABASE=TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link) (FireBoard Blue) + +pci:v0000104Cd00008024sv00001458sd00001000* + ID_MODEL_FROM_DATABASE=TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link) (Motherboard) + +pci:v0000104Cd00008025* + ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller + +pci:v0000104Cd00008025sv00001043sd0000813C* + ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller (P5P series mainboard) + +pci:v0000104Cd00008025sv00001443sd00008025* + ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller (FireBoard800) + +pci:v0000104Cd00008025sv00001458sd00001000* + ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller (GA-K8N Ultra-9 Mainboard) + +pci:v0000104Cd00008025sv00001546sd00008025* + ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller (FWB-PCI01) + +pci:v0000104Cd00008025sv000017FCsd00008025* + ID_MODEL_FROM_DATABASE=TSB82AA2 IEEE-1394b Link Layer Controller (GIC3800) + +pci:v0000104Cd00008026* + ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) + +pci:v0000104Cd00008026sv00001025sd00000035* + ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) (TravelMate 660) + +pci:v0000104Cd00008026sv00001025sd0000003C* + ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) (Aspire 2001WLCi (Compaq CL50 motherboard)) + +pci:v0000104Cd00008026sv0000103Csd00000025* + ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) (XE4500 Notebook) + +pci:v0000104Cd00008026sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) (NX9500) + +pci:v0000104Cd00008026sv00001043sd0000808D* + ID_MODEL_FROM_DATABASE=TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) (A7V333 mainboard.) + +pci:v0000104Cd00008027* + ID_MODEL_FROM_DATABASE=PCI4451 IEEE-1394 Controller + +pci:v0000104Cd00008027sv00001028sd000000E5* + ID_MODEL_FROM_DATABASE=PCI4451 IEEE-1394 Controller (Latitude C810) + +pci:v0000104Cd00008027sv00001028sd000000E6* + ID_MODEL_FROM_DATABASE=PCI4451 IEEE-1394 Controller ((Dell Inspiron 8100)) + +pci:v0000104Cd00008029* + ID_MODEL_FROM_DATABASE=PCI4510 IEEE-1394 Controller + +pci:v0000104Cd00008029sv00001028sd00000163* + ID_MODEL_FROM_DATABASE=PCI4510 IEEE-1394 Controller (Latitude D505) + +pci:v0000104Cd00008029sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=PCI4510 IEEE-1394 Controller (Inspiron 5160) + +pci:v0000104Cd00008029sv00001071sd00008160* + ID_MODEL_FROM_DATABASE=PCI4510 IEEE-1394 Controller (MIM2900) + +pci:v0000104Cd0000802B* + ID_MODEL_FROM_DATABASE=PCI7410,7510,7610 OHCI-Lynx Controller + +pci:v0000104Cd0000802Bsv00001028sd00000139* + ID_MODEL_FROM_DATABASE=PCI7410,7510,7610 OHCI-Lynx Controller (Latitude D400) + +pci:v0000104Cd0000802Bsv00001028sd0000014E* + ID_MODEL_FROM_DATABASE=PCI7410,7510,7610 OHCI-Lynx Controller ((Latitude D800)) + +pci:v0000104Cd0000802E* + ID_MODEL_FROM_DATABASE=PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller + +pci:v0000104Cd0000802Esv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller (Inspiron 700m/710m) + +pci:v0000104Cd00008031* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11/PCIx515 PC Card Controller + +pci:v0000104Cd00008031sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11/PCIx515 PC Card Controller (Extensa 3000 series laptop) + +pci:v0000104Cd00008031sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11/PCIx515 PC Card Controller (Aspire 5024WLMi) + +pci:v0000104Cd00008031sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11/PCIx515 PC Card Controller (Compaq nw8240/nx8220) + +pci:v0000104Cd00008031sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11/PCIx515 PC Card Controller (Compaq nc6220 Notebook PC) + +pci:v0000104Cd00008031sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11/PCIx515 PC Card Controller (NX6110/NC6120) + +pci:v0000104Cd00008031sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11/PCIx515 PC Card Controller (MX6125) + +pci:v0000104Cd00008032* + ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller + +pci:v0000104Cd00008032sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller (Extensa 3000 series laptop) + +pci:v0000104Cd00008032sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller (Aspire 5024WLMi) + +pci:v0000104Cd00008032sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller (Compaq nw8240/nx8220) + +pci:v0000104Cd00008032sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller (NX6110/NC6120) + +pci:v0000104Cd00008032sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=OHCI Compliant IEEE 1394 Host Controller (MX6125) + +pci:v0000104Cd00008033* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Flash Media Controller + +pci:v0000104Cd00008033sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Flash Media Controller (Extensa 3000 series laptop) + +pci:v0000104Cd00008033sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Flash Media Controller (Aspire 5024WLMi) + +pci:v0000104Cd00008033sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Flash Media Controller (Compaq nw8240/nx8220) + +pci:v0000104Cd00008033sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Flash Media Controller (Compaq nc6220 Notebook PC) + +pci:v0000104Cd00008033sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Flash Media Controller (NX6110/NC6120) + +pci:v0000104Cd00008033sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Flash Media Controller (MX6125) + +pci:v0000104Cd00008034* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 SD Host Controller + +pci:v0000104Cd00008034sv00001025sd00000080* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 SD Host Controller (Aspire 5024WLMi) + +pci:v0000104Cd00008034sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 SD Host Controller (Compaq nw8240/nx8220) + +pci:v0000104Cd00008034sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 SD Host Controller (Compaq nc6220 Notebook PC) + +pci:v0000104Cd00008034sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 SD Host Controller (NX6110/NC6120) + +pci:v0000104Cd00008034sv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 SD Host Controller (MX6125) + +pci:v0000104Cd00008035* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Smart Card Controller + +pci:v0000104Cd00008035sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Smart Card Controller (Compaq nw8240/nx8220) + +pci:v0000104Cd00008035sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Smart Card Controller (Compaq nc6220 Notebook PC) + +pci:v0000104Cd00008035sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=PCIxx21/PCIxx11 Smart Card Controller (NX6110/NC6120) + +pci:v0000104Cd00008036* + ID_MODEL_FROM_DATABASE=PCI6515 Cardbus Controller + +pci:v0000104Cd00008038* + ID_MODEL_FROM_DATABASE=PCI6515 SmartCard Controller + +pci:v0000104Cd00008039* + ID_MODEL_FROM_DATABASE=PCIxx12 Cardbus Controller + +pci:v0000104Cd00008039sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=PCIxx12 Cardbus Controller (Compaq nx9420 Notebook) + +pci:v0000104Cd00008039sv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=PCIxx12 Cardbus Controller (NC2400) + +pci:v0000104Cd00008039sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=PCIxx12 Cardbus Controller (Compaq nw8440) + +pci:v0000104Cd00008039sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=PCIxx12 Cardbus Controller (VAIO VGN-NR120E) + +pci:v0000104Cd0000803A* + ID_MODEL_FROM_DATABASE=PCIxx12 OHCI Compliant IEEE 1394 Host Controller + +pci:v0000104Cd0000803Asv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=PCIxx12 OHCI Compliant IEEE 1394 Host Controller (nx9420) + +pci:v0000104Cd0000803Asv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=PCIxx12 OHCI Compliant IEEE 1394 Host Controller (NC2400) + +pci:v0000104Cd0000803Asv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=PCIxx12 OHCI Compliant IEEE 1394 Host Controller (Compaq nw8440) + +pci:v0000104Cd0000803Asv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=PCIxx12 OHCI Compliant IEEE 1394 Host Controller (VAIO VGN-NR120E) + +pci:v0000104Cd0000803B* + ID_MODEL_FROM_DATABASE=PCIxx12 Flash Media Controller + +pci:v0000104Cd0000803Bsv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=PCIxx12 Flash Media Controller (nx9420) + +pci:v0000104Cd0000803Bsv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=PCIxx12 Flash Media Controller (Compaq nw8440) + +pci:v0000104Cd0000803Bsv0000104Dsd00008212* + ID_MODEL_FROM_DATABASE=PCIxx12 Flash Media Controller (VAIO VGN-N21E) + +pci:v0000104Cd0000803Bsv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=PCIxx12 Flash Media Controller (VAIO VGN-NR120E) + +pci:v0000104Cd0000803C* + ID_MODEL_FROM_DATABASE=PCIxx12 SDA Standard Compliant SD Host Controller + +pci:v0000104Cd0000803Csv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=PCIxx12 SDA Standard Compliant SD Host Controller (nx9420) + +pci:v0000104Cd0000803Csv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=PCIxx12 SDA Standard Compliant SD Host Controller (Compaq nw8440) + +pci:v0000104Cd0000803D* + ID_MODEL_FROM_DATABASE=PCIxx12 GemCore based SmartCard controller + +pci:v0000104Cd0000803Dsv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=PCIxx12 GemCore based SmartCard controller (Compaq nx9420 Notebook) + +pci:v0000104Cd0000803Dsv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=PCIxx12 GemCore based SmartCard controller (NC2400) + +pci:v0000104Cd0000803Dsv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=PCIxx12 GemCore based SmartCard controller (nc8430) + +pci:v0000104Cd0000803Dsv0000103Csd000030AA* + ID_MODEL_FROM_DATABASE=PCIxx12 GemCore based SmartCard controller (nc6310) + +pci:v0000104Cd00008101* + ID_MODEL_FROM_DATABASE=TSB43DB42 IEEE-1394a-2000 Controller (PHY/Link) + +pci:v0000104Cd00008201* + ID_MODEL_FROM_DATABASE=PCI1620 Firmware Loading Function + +pci:v0000104Cd00008204* + ID_MODEL_FROM_DATABASE=PCI7410/7510/7610 PCI Firmware Loading Function + +pci:v0000104Cd00008204sv00001028sd00000139* + ID_MODEL_FROM_DATABASE=PCI7410/7510/7610 PCI Firmware Loading Function (Latitude D400) + +pci:v0000104Cd00008204sv00001028sd0000014E* + ID_MODEL_FROM_DATABASE=PCI7410/7510/7610 PCI Firmware Loading Function (Latitude D800) + +pci:v0000104Cd00008231* + ID_MODEL_FROM_DATABASE=XIO2000(A)/XIO2200A PCI Express-to-PCI Bridge + +pci:v0000104Cd00008231sv00005678sd00001234* + ID_MODEL_FROM_DATABASE=XIO2000(A)/XIO2200A PCI Express-to-PCI Bridge (DC-1394 PCIe) + +pci:v0000104Cd00008232* + ID_MODEL_FROM_DATABASE=XIO3130 PCI Express Switch (Upstream) + +pci:v0000104Cd00008233* + ID_MODEL_FROM_DATABASE=XIO3130 PCI Express Switch (Downstream) + +pci:v0000104Cd00008235* + ID_MODEL_FROM_DATABASE=XIO2200A IEEE-1394a-2000 Controller (PHY/Link) + +pci:v0000104Cd00008235sv00005678sd00001234* + ID_MODEL_FROM_DATABASE=XIO2200A IEEE-1394a-2000 Controller (PHY/Link) (DC-1394 PCIe) + +pci:v0000104Cd0000823E* + ID_MODEL_FROM_DATABASE=XIO2213A/B/XIO2221 PCI Express to PCI Bridge [Cheetah Express] + +pci:v0000104Cd0000823F* + ID_MODEL_FROM_DATABASE=XIO2213A/B/XIO2221 IEEE-1394b OHCI Controller [Cheetah Express] + +pci:v0000104Cd0000823Fsv00001546sd0000803C* + ID_MODEL_FROM_DATABASE=XIO2213A/B/XIO2221 IEEE-1394b OHCI Controller [Cheetah Express] (FWB-PCIE1X11B) + +pci:v0000104Cd00008240* + ID_MODEL_FROM_DATABASE=XIO2001 PCI Express-to-PCI Bridge + +pci:v0000104Cd00008241* + ID_MODEL_FROM_DATABASE=TUSB73x0 SuperSpeed USB 3.0 xHCI Host Controller + +pci:v0000104Cd00008241sv00001014sd000004B2* + ID_MODEL_FROM_DATABASE=TUSB73x0 SuperSpeed USB 3.0 xHCI Host Controller (S824 (8286-42A)) + +pci:v0000104Cd00008400* + ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface + +pci:v0000104Cd00008400sv00001186sd00003B00* + ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface (DWL-650+ PC Card cardbus 22Mbs Wireless Adapter [AirPlus]) + +pci:v0000104Cd00008400sv00001186sd00003B01* + ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface (DWL-520+ 22Mbps PCI Wireless Adapter) + +pci:v0000104Cd00008400sv00001395sd00002201* + ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface (WL22-PC) + +pci:v0000104Cd00008400sv000016ABsd00008501* + ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface (WL-8305 IEEE802.11b+ Wireless LAN PCI Adapter) + +pci:v0000104Cd00008401* + ID_MODEL_FROM_DATABASE=ACX 100 22Mbps Wireless Interface + +pci:v0000104Cd00008888* + ID_MODEL_FROM_DATABASE=Multicore DSP+ARM KeyStone II SOC + +pci:v0000104Cd00009000* + ID_MODEL_FROM_DATABASE=Wireless Interface (of unknown type) + +pci:v0000104Cd00009065* + ID_MODEL_FROM_DATABASE=TMS320DM642 + +pci:v0000104Cd00009066* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface + +pci:v0000104Cd00009066sv00000308sd00003404* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (G-102 v1 802.11g Wireless Cardbus Adapter) + +pci:v0000104Cd00009066sv00000308sd00003406* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (G-162 v2 802.11g Wireless Cardbus Adapter) + +pci:v0000104Cd00009066sv0000104Csd00009066* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (WL212 Sitecom Wireless Network PCI-Card 100M (Version 1)) + +pci:v0000104Cd00009066sv0000104Csd00009067* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (TNETW1130GVF) + +pci:v0000104Cd00009066sv0000104Csd00009096* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (Trendnet TEW-412PC Wireless PCI Adapter (Version A)) + +pci:v0000104Cd00009066sv00001186sd00003B04* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (DWL-G520+ Wireless PCI Adapter) + +pci:v0000104Cd00009066sv00001186sd00003B05* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (DWL-G650+ AirPlusG+ CardBus Wireless LAN) + +pci:v0000104Cd00009066sv00001186sd00003B08* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.B1)) + +pci:v0000104Cd00009066sv00001385sd00004C00* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (WG311v2 802.11g Wireless PCI Adapter) + +pci:v0000104Cd00009066sv000013D1sd0000ABA0* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (SWLMP-54108 108Mbps Wireless mini PCI card 802.11g+) + +pci:v0000104Cd00009066sv000014EAsd0000AB07* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (GW-NS54GM Wireless Cardbus Adapter) + +pci:v0000104Cd00009066sv000016ECsd0000010D* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (USR5416 802.11g Wireless Turbo PCI Adapter) + +pci:v0000104Cd00009066sv000016ECsd0000010E* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (USR5410 802.11g Wireless Cardbus Adapter) + +pci:v0000104Cd00009066sv00001737sd00000033* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (WPC54G v2 802.11g Wireless-G Notebook Adapter) + +pci:v0000104Cd00009066sv000017CFsd00000032* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (G-162 v1 802.11g Wireless Cardbus Adapter) + +pci:v0000104Cd00009066sv000017CFsd00000033* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (Z-Com XG650 Wireless miniPCI 802.11b/g) + +pci:v0000104Cd00009066sv0000187Esd0000340B* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (G-302 v2 802.11g Wireless PCI Adapter) + +pci:v0000104Cd00009066sv0000187Esd0000340C* + ID_MODEL_FROM_DATABASE=ACX 111 54Mbps Wireless Interface (G-360 v2 802.11g Wireless PCI Adapter) + +pci:v0000104Cd0000A001* + ID_MODEL_FROM_DATABASE=TDC1570 + +pci:v0000104Cd0000A100* + ID_MODEL_FROM_DATABASE=TDC1561 + +pci:v0000104Cd0000A102* + ID_MODEL_FROM_DATABASE=TNETA1575 HyperSAR Plus w/PCI Host i/f & UTOPIA i/f + +pci:v0000104Cd0000A106* + ID_MODEL_FROM_DATABASE=TMS320C6414 TMS320C6415 TMS320C6416 + +pci:v0000104Cd0000A106sv0000175Csd00005000* + ID_MODEL_FROM_DATABASE=TMS320C6414 TMS320C6415 TMS320C6416 (ASI50xx Audio Adapter) + +pci:v0000104Cd0000A106sv0000175Csd00006400* + ID_MODEL_FROM_DATABASE=TMS320C6414 TMS320C6415 TMS320C6416 (ASI6400 Cobranet series) + +pci:v0000104Cd0000A106sv0000175Csd00008700* + ID_MODEL_FROM_DATABASE=TMS320C6414 TMS320C6415 TMS320C6416 (ASI87xx Radio Tuner card) + +pci:v0000104Cd0000AC10* + ID_MODEL_FROM_DATABASE=PCI1050 + +pci:v0000104Cd0000AC11* + ID_MODEL_FROM_DATABASE=PCI1053 + +pci:v0000104Cd0000AC12* + ID_MODEL_FROM_DATABASE=PCI1130 + +pci:v0000104Cd0000AC13* + ID_MODEL_FROM_DATABASE=PCI1031 + +pci:v0000104Cd0000AC15* + ID_MODEL_FROM_DATABASE=PCI1131 + +pci:v0000104Cd0000AC16* + ID_MODEL_FROM_DATABASE=PCI1250 + +pci:v0000104Cd0000AC16sv00001014sd00000092* + ID_MODEL_FROM_DATABASE=PCI1250 (ThinkPad 600) + +pci:v0000104Cd0000AC17* + ID_MODEL_FROM_DATABASE=PCI1220 + +pci:v0000104Cd0000AC18* + ID_MODEL_FROM_DATABASE=PCI1260 + +pci:v0000104Cd0000AC19* + ID_MODEL_FROM_DATABASE=PCI1221 + +pci:v0000104Cd0000AC1A* + ID_MODEL_FROM_DATABASE=PCI1210 + +pci:v0000104Cd0000AC1B* + ID_MODEL_FROM_DATABASE=PCI1450 + +pci:v0000104Cd0000AC1Bsv00000E11sd0000B113* + ID_MODEL_FROM_DATABASE=PCI1450 (Armada M700) + +pci:v0000104Cd0000AC1Bsv00001014sd00000130* + ID_MODEL_FROM_DATABASE=PCI1450 (ThinkPad 600X/A21m/T20/T22) + +pci:v0000104Cd0000AC1C* + ID_MODEL_FROM_DATABASE=PCI1225 + +pci:v0000104Cd0000AC1Csv00000E11sd0000B121* + ID_MODEL_FROM_DATABASE=PCI1225 (Armada E500) + +pci:v0000104Cd0000AC1Csv00001028sd00000088* + ID_MODEL_FROM_DATABASE=PCI1225 (Latitude CPi A400XT) + +pci:v0000104Cd0000AC1D* + ID_MODEL_FROM_DATABASE=PCI1251A + +pci:v0000104Cd0000AC1E* + ID_MODEL_FROM_DATABASE=PCI1211 + +pci:v0000104Cd0000AC1F* + ID_MODEL_FROM_DATABASE=PCI1251B + +pci:v0000104Cd0000AC20* + ID_MODEL_FROM_DATABASE=TI 2030 + +pci:v0000104Cd0000AC21* + ID_MODEL_FROM_DATABASE=PCI2031 + +pci:v0000104Cd0000AC22* + ID_MODEL_FROM_DATABASE=PCI2032 PCI Docking Bridge + +pci:v0000104Cd0000AC23* + ID_MODEL_FROM_DATABASE=PCI2250 PCI-to-PCI Bridge + +pci:v0000104Cd0000AC28* + ID_MODEL_FROM_DATABASE=PCI2050 PCI-to-PCI Bridge + +pci:v0000104Cd0000AC2C* + ID_MODEL_FROM_DATABASE=PCI2060 PCI-to-PCI Bridge + +pci:v0000104Cd0000AC30* + ID_MODEL_FROM_DATABASE=PCI1260 PC card Cardbus Controller + +pci:v0000104Cd0000AC40* + ID_MODEL_FROM_DATABASE=PCI4450 PC card Cardbus Controller + +pci:v0000104Cd0000AC41* + ID_MODEL_FROM_DATABASE=PCI4410 PC card Cardbus Controller + +pci:v0000104Cd0000AC42* + ID_MODEL_FROM_DATABASE=PCI4451 PC card Cardbus Controller + +pci:v0000104Cd0000AC42sv00001028sd000000E6* + ID_MODEL_FROM_DATABASE=PCI4451 PC card Cardbus Controller (PCI4451 PC card CardBus Controller (Inspiron 8100)) + +pci:v0000104Cd0000AC44* + ID_MODEL_FROM_DATABASE=PCI4510 PC card Cardbus Controller + +pci:v0000104Cd0000AC44sv00001028sd00000149* + ID_MODEL_FROM_DATABASE=PCI4510 PC card Cardbus Controller (Inspiron 5100) + +pci:v0000104Cd0000AC44sv00001028sd00000163* + ID_MODEL_FROM_DATABASE=PCI4510 PC card Cardbus Controller (Latitude D505) + +pci:v0000104Cd0000AC44sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=PCI4510 PC card Cardbus Controller (Inspiron 5160) + +pci:v0000104Cd0000AC44sv00001071sd00008160* + ID_MODEL_FROM_DATABASE=PCI4510 PC card Cardbus Controller (MIM2000) + +pci:v0000104Cd0000AC46* + ID_MODEL_FROM_DATABASE=PCI4520 PC card Cardbus Controller + +pci:v0000104Cd0000AC46sv00001014sd00000552* + ID_MODEL_FROM_DATABASE=PCI4520 PC card Cardbus Controller (ThinkPad) + +pci:v0000104Cd0000AC47* + ID_MODEL_FROM_DATABASE=PCI7510 PC card Cardbus Controller + +pci:v0000104Cd0000AC47sv00001028sd00000139* + ID_MODEL_FROM_DATABASE=PCI7510 PC card Cardbus Controller (Latitude D400) + +pci:v0000104Cd0000AC47sv00001028sd0000013F* + ID_MODEL_FROM_DATABASE=PCI7510 PC card Cardbus Controller (Precision M60) + +pci:v0000104Cd0000AC47sv00001028sd0000014E* + ID_MODEL_FROM_DATABASE=PCI7510 PC card Cardbus Controller (Latitude D800) + +pci:v0000104Cd0000AC48* + ID_MODEL_FROM_DATABASE=PCI7610 PC Card Cardbus Controller + +pci:v0000104Cd0000AC49* + ID_MODEL_FROM_DATABASE=PCI7410 PC Card Cardbus Controller + +pci:v0000104Cd0000AC4A* + ID_MODEL_FROM_DATABASE=PCI7510/7610 CardBus Bridge + +pci:v0000104Cd0000AC4Asv00001028sd00000139* + ID_MODEL_FROM_DATABASE=PCI7510/7610 CardBus Bridge (Latitude D400) + +pci:v0000104Cd0000AC4Asv00001028sd0000014E* + ID_MODEL_FROM_DATABASE=PCI7510/7610 CardBus Bridge (Latitude D800) + +pci:v0000104Cd0000AC4B* + ID_MODEL_FROM_DATABASE=PCI7610 SD/MMC controller + +pci:v0000104Cd0000AC4C* + ID_MODEL_FROM_DATABASE=PCI7610 Memory Stick controller + +pci:v0000104Cd0000AC50* + ID_MODEL_FROM_DATABASE=PCI1410 PC card Cardbus Controller + +pci:v0000104Cd0000AC51* + ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller + +pci:v0000104Cd0000AC51sv00000E11sd0000004E* + ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (Evo N600c) + +pci:v0000104Cd0000AC51sv00001014sd00000148* + ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (ThinkPad A20m) + +pci:v0000104Cd0000AC51sv00001014sd0000023B* + ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (ThinkPad T23) + +pci:v0000104Cd0000AC51sv00001028sd000000B1* + ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (Latitude C600) + +pci:v0000104Cd0000AC51sv00001028sd0000012A* + ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (Latitude C640) + +pci:v0000104Cd0000AC51sv00001033sd000080CD* + ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (Versa Note VXi) + +pci:v0000104Cd0000AC51sv000010CFsd00001095* + ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (Lifebook S-4510/C6155) + +pci:v0000104Cd0000AC51sv0000E4BFsd00001000* + ID_MODEL_FROM_DATABASE=PCI1420 PC card Cardbus Controller (CP2-2-HIPHOP) + +pci:v0000104Cd0000AC52* + ID_MODEL_FROM_DATABASE=PCI1451 PC card Cardbus Controller + +pci:v0000104Cd0000AC53* + ID_MODEL_FROM_DATABASE=PCI1421 PC card Cardbus Controller + +pci:v0000104Cd0000AC54* + ID_MODEL_FROM_DATABASE=PCI1620 PC Card Controller + +pci:v0000104Cd0000AC54sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=PCI1620 PC Card Controller (tc1100 tablet) + +pci:v0000104Cd0000AC55* + ID_MODEL_FROM_DATABASE=PCI1520 PC card Cardbus Controller + +pci:v0000104Cd0000AC55sv00001014sd00000512* + ID_MODEL_FROM_DATABASE=PCI1520 PC card Cardbus Controller (ThinkPad T30/T40) + +pci:v0000104Cd0000AC55sv0000103Csd00000025* + ID_MODEL_FROM_DATABASE=PCI1520 PC card Cardbus Controller (XE4500 Notebook) + +pci:v0000104Cd0000AC56* + ID_MODEL_FROM_DATABASE=PCI1510 PC card Cardbus Controller + +pci:v0000104Cd0000AC56sv00001014sd00000512* + ID_MODEL_FROM_DATABASE=PCI1510 PC card Cardbus Controller (ThinkPad R50e) + +pci:v0000104Cd0000AC56sv00001014sd00000528* + ID_MODEL_FROM_DATABASE=PCI1510 PC card Cardbus Controller (ThinkPad R40e) + +pci:v0000104Cd0000AC56sv000017AAsd00002012* + ID_MODEL_FROM_DATABASE=PCI1510 PC card Cardbus Controller (ThinkPad T60/R60 series) + +pci:v0000104Cd0000AC60* + ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller + +pci:v0000104Cd0000AC60sv0000175Csd00005100* + ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (ASI51xx Audio Adapter) + +pci:v0000104Cd0000AC60sv0000175Csd00006100* + ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (ASI61xx Audio Adapter) + +pci:v0000104Cd0000AC60sv0000175Csd00006200* + ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (ASI62xx Audio Adapter) + +pci:v0000104Cd0000AC60sv0000175Csd00008800* + ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (ASI88xx Audio Adapter) + +pci:v0000104Cd0000AC60sv0000186Fsd00003001* + ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (WR-G303 PCI radio receiver) + +pci:v0000104Cd0000AC60sv0000186Fsd00003005* + ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (WR-G305 PCI radio receiver) + +pci:v0000104Cd0000AC60sv0000186Fsd00003101* + ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (WR-G313 PCI radio receiver) + +pci:v0000104Cd0000AC60sv0000186Fsd00003105* + ID_MODEL_FROM_DATABASE=PCI2040 PCI to DSP Bridge Controller (WR-G315 PCI radio receiver) + +pci:v0000104Cd0000AC8D* + ID_MODEL_FROM_DATABASE=PCI 7620 + +pci:v0000104Cd0000AC8E* + ID_MODEL_FROM_DATABASE=PCI7420 CardBus Controller + +pci:v0000104Cd0000AC8Esv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=PCI7420 CardBus Controller (Inspiron 700m/710m) + +pci:v0000104Cd0000AC8F* + ID_MODEL_FROM_DATABASE=PCI7420/7620 SD/MS-Pro Controller + +pci:v0000104Cd0000AC8Fsv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=PCI7420/7620 SD/MS-Pro Controller (Inspiron 700m/710m) + +pci:v0000104Cd0000B001* + ID_MODEL_FROM_DATABASE=TMS320C6424 + +pci:v0000104Cd0000FE00* + ID_MODEL_FROM_DATABASE=FireWire Host Controller + +pci:v0000104Cd0000FE03* + ID_MODEL_FROM_DATABASE=12C01A FireWire Host Controller + +pci:v0000104D* + ID_VENDOR_FROM_DATABASE=Sony Corporation + +pci:v0000104Dd00008004* + ID_MODEL_FROM_DATABASE=DTL-H2500 [Playstation development board] + +pci:v0000104Dd00008009* + ID_MODEL_FROM_DATABASE=CXD1947Q i.LINK Controller + +pci:v0000104Dd0000800C* + ID_MODEL_FROM_DATABASE=DTL-H800 [PS1 sound development board] + +pci:v0000104Dd00008039* + ID_MODEL_FROM_DATABASE=CXD3222 i.LINK Controller + +pci:v0000104Dd00008047* + ID_MODEL_FROM_DATABASE=PS2 TOOL MRP + +pci:v0000104Dd00008056* + ID_MODEL_FROM_DATABASE=Rockwell HCF 56K modem + +pci:v0000104Dd0000808A* + ID_MODEL_FROM_DATABASE=Memory Stick Controller + +pci:v0000104Dd000080FF* + ID_MODEL_FROM_DATABASE=PS2 Performance Analyzer + +pci:v0000104Dd0000814A* + ID_MODEL_FROM_DATABASE=PS2 Performance Analyzer + +pci:v0000104Dd00008183* + ID_MODEL_FROM_DATABASE=ATHENS [PS3 prototype developer interface card] + +pci:v0000104Dd000081B0* + ID_MODEL_FROM_DATABASE=BM-1 [PSP TOOL Board Management Device] + +pci:v0000104Dd000081C3* + ID_MODEL_FROM_DATABASE=VO-4 [PSP TOOL Video Output Device] + +pci:v0000104Dd000081CE* + ID_MODEL_FROM_DATABASE=SxS Pro memory card + +pci:v0000104Dd000081FF* + ID_MODEL_FROM_DATABASE=PS3 TOOL MRP + +pci:v0000104Dd00008200* + ID_MODEL_FROM_DATABASE=PS3 TOOL RSX Tracing FPGA + +pci:v0000104Dd0000820E* + ID_MODEL_FROM_DATABASE=CXD9208GP [PS3 PS2 emulation subsystem adapter] + +pci:v0000104Dd0000905C* + ID_MODEL_FROM_DATABASE=SxS Pro memory card + +pci:v0000104Dd0000907F* + ID_MODEL_FROM_DATABASE=SxS Pro+ memory card + +pci:v0000104Dd0000908F* + ID_MODEL_FROM_DATABASE=Aeolia ACPI + +pci:v0000104Dd0000909E* + ID_MODEL_FROM_DATABASE=Aeolia Ethernet Controller (Marvell Yukon 2 Family) + +pci:v0000104Dd0000909F* + ID_MODEL_FROM_DATABASE=Aeolia SATA AHCI Controller + +pci:v0000104Dd000090A0* + ID_MODEL_FROM_DATABASE=Aeolia SD/MMC Host Controller + +pci:v0000104Dd000090A1* + ID_MODEL_FROM_DATABASE=Aeolia PCI Express Glue and Miscellaneous Devices + +pci:v0000104Dd000090A2* + ID_MODEL_FROM_DATABASE=Aeolia DMA Controller + +pci:v0000104Dd000090A3* + ID_MODEL_FROM_DATABASE=Aeolia Memory (DDR3/SPM) + +pci:v0000104Dd000090A4* + ID_MODEL_FROM_DATABASE=Aeolia USB 3.0 xHCI Host Controller + +pci:v0000104Dd000090BC* + ID_MODEL_FROM_DATABASE=SxS Pro+ memory card + +pci:v0000104Dd000090C8* + ID_MODEL_FROM_DATABASE=Belize ACPI + +pci:v0000104Dd000090C9* + ID_MODEL_FROM_DATABASE=Belize Ethernet Controller + +pci:v0000104Dd000090CA* + ID_MODEL_FROM_DATABASE=Belize SATA AHCI Controller + +pci:v0000104Dd000090CB* + ID_MODEL_FROM_DATABASE=Belize SD/MMC Host Controller + +pci:v0000104Dd000090CC* + ID_MODEL_FROM_DATABASE=Belize PCI Express Glue and Miscellaneous Devices + +pci:v0000104Dd000090CD* + ID_MODEL_FROM_DATABASE=Belize DMA Controller + +pci:v0000104Dd000090CE* + ID_MODEL_FROM_DATABASE=Belize Memory (DDR3/SPM) + +pci:v0000104Dd000090CF* + ID_MODEL_FROM_DATABASE=Belize USB 3.0 xHCI Host Controller + +pci:v0000104Dd000090D7* + ID_MODEL_FROM_DATABASE=Baikal ACPI + +pci:v0000104Dd000090D8* + ID_MODEL_FROM_DATABASE=Baikal Ethernet Controller + +pci:v0000104Dd000090D9* + ID_MODEL_FROM_DATABASE=Baikal SATA AHCI Controller + +pci:v0000104Dd000090DA* + ID_MODEL_FROM_DATABASE=Baikal SD/MMC Host Controller + +pci:v0000104Dd000090DB* + ID_MODEL_FROM_DATABASE=Baikal PCI Express Glue and Miscellaneous Devices + +pci:v0000104Dd000090DC* + ID_MODEL_FROM_DATABASE=Baikal DMA Controller + +pci:v0000104Dd000090DD* + ID_MODEL_FROM_DATABASE=Baikal Memory (DDR3/SPM) + +pci:v0000104Dd000090DE* + ID_MODEL_FROM_DATABASE=Baikal USB 3.0 xHCI Host Controller + +pci:v0000104E* + ID_VENDOR_FROM_DATABASE=Oak Technology, Inc + +pci:v0000104Ed00000017* + ID_MODEL_FROM_DATABASE=OTI-64017 + +pci:v0000104Ed00000107* + ID_MODEL_FROM_DATABASE=OTI-107 [Spitfire] + +pci:v0000104Ed00000109* + ID_MODEL_FROM_DATABASE=Video Adapter + +pci:v0000104Ed00000111* + ID_MODEL_FROM_DATABASE=OTI-64111 [Spitfire] + +pci:v0000104Ed00000217* + ID_MODEL_FROM_DATABASE=OTI-64217 + +pci:v0000104Ed00000317* + ID_MODEL_FROM_DATABASE=OTI-64317 + +pci:v0000104F* + ID_VENDOR_FROM_DATABASE=Co-time Computer Ltd + +pci:v00001050* + ID_VENDOR_FROM_DATABASE=Winbond Electronics Corp + +pci:v00001050d00000000* + ID_MODEL_FROM_DATABASE=NE2000 + +pci:v00001050d00000001* + ID_MODEL_FROM_DATABASE=W83769F + +pci:v00001050d00000033* + ID_MODEL_FROM_DATABASE=W89C33D 802.11 a/b/g BB/MAC + +pci:v00001050d00000105* + ID_MODEL_FROM_DATABASE=W82C105 + +pci:v00001050d00000840* + ID_MODEL_FROM_DATABASE=W89C840 + +pci:v00001050d00000840sv00001050sd00000001* + ID_MODEL_FROM_DATABASE=W89C840 (Ethernet Adapter) + +pci:v00001050d00000840sv00001050sd00000840* + ID_MODEL_FROM_DATABASE=W89C840 (Ethernet Adapter) + +pci:v00001050d00000940* + ID_MODEL_FROM_DATABASE=W89C940 + +pci:v00001050d00005A5A* + ID_MODEL_FROM_DATABASE=W89C940F + +pci:v00001050d00006692* + ID_MODEL_FROM_DATABASE=W6692 + +pci:v00001050d00006692sv00001043sd00001702* + ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, D, W)) + +pci:v00001050d00006692sv00001043sd00001703* + ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, DV, W)) + +pci:v00001050d00006692sv00001043sd00001707* + ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, DV, W)) + +pci:v00001050d00006692sv0000144Fsd00001702* + ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, D, W)) + +pci:v00001050d00006692sv0000144Fsd00001703* + ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, DV, W)) + +pci:v00001050d00006692sv0000144Fsd00001707* + ID_MODEL_FROM_DATABASE=W6692 (ISDN Adapter (PCI Bus, DV, W)) + +pci:v00001050d00009921* + ID_MODEL_FROM_DATABASE=W99200F MPEG-1 Video Encoder + +pci:v00001050d00009922* + ID_MODEL_FROM_DATABASE=W99200F/W9922PF MPEG-1/2 Video Encoder + +pci:v00001050d00009970* + ID_MODEL_FROM_DATABASE=W9970CF + +pci:v00001051* + ID_VENDOR_FROM_DATABASE=Anigma, Inc. + +pci:v00001052* + ID_VENDOR_FROM_DATABASE=?Young Micro Systems + +pci:v00001053* + ID_VENDOR_FROM_DATABASE=Young Micro Systems + +pci:v00001054* + ID_VENDOR_FROM_DATABASE=Hitachi, Ltd + +pci:v00001054d00003009* + ID_MODEL_FROM_DATABASE=2Gbps Fibre Channel to PCI HBA 3009 + +pci:v00001054d0000300A* + ID_MODEL_FROM_DATABASE=4Gbps Fibre Channel to PCI-X HBA 300a + +pci:v00001054d0000300B* + ID_MODEL_FROM_DATABASE=4Gbps Fibre Channel to PCI-X HBA 300b + +pci:v00001054d0000300F* + ID_MODEL_FROM_DATABASE=ColdFusion 3 Chipset Processor to I/O Controller + +pci:v00001054d00003010* + ID_MODEL_FROM_DATABASE=ColdFusion 3 Chipset Memory Controller Hub + +pci:v00001054d00003011* + ID_MODEL_FROM_DATABASE=ColdFusion 3e Chipset Processor to I/O Controller + +pci:v00001054d00003012* + ID_MODEL_FROM_DATABASE=ColdFusion 3e Chipset Memory Controller Hub + +pci:v00001054d00003017* + ID_MODEL_FROM_DATABASE=Unassigned Hitachi Shared FC Device 3017 + +pci:v00001054d0000301B* + ID_MODEL_FROM_DATABASE=Virtual VGA Device + +pci:v00001054d0000301D* + ID_MODEL_FROM_DATABASE=PCIe-to-PCIe Bridge with Virtualization IO Assist Feature + +pci:v00001054d00003020* + ID_MODEL_FROM_DATABASE=FIVE-EX based Fibre Channel to PCIe HBA + +pci:v00001054d0000302C* + ID_MODEL_FROM_DATABASE=M001 PCI Express Switch Upstream Port + +pci:v00001054d0000302D* + ID_MODEL_FROM_DATABASE=M001 PCI Express Switch Downstream Port + +pci:v00001054d00003070* + ID_MODEL_FROM_DATABASE=Hitachi FIVE-FX Fibre Channel to PCIe HBA + +pci:v00001054d00003505* + ID_MODEL_FROM_DATABASE=SH7751 PCI Controller (PCIC) + +pci:v00001054d0000350E* + ID_MODEL_FROM_DATABASE=SH7751R PCI Controller (PCIC) + +pci:v00001055* + ID_VENDOR_FROM_DATABASE=Microchip Technology / SMSC + +pci:v00001055d00009130* + ID_MODEL_FROM_DATABASE=SLC90E66 [Victory66] IDE + +pci:v00001055d00009460* + ID_MODEL_FROM_DATABASE=SLC90E66 [Victory66] ISA + +pci:v00001055d00009462* + ID_MODEL_FROM_DATABASE=SLC90E66 [Victory66] USB + +pci:v00001055d00009463* + ID_MODEL_FROM_DATABASE=SLC90E66 [Victory66] ACPI + +pci:v00001055d0000E420* + ID_MODEL_FROM_DATABASE=LAN9420/LAN9420i + +pci:v00001056* + ID_VENDOR_FROM_DATABASE=ICL + +pci:v00001057* + ID_VENDOR_FROM_DATABASE=Motorola + +pci:v00001057d00000001* + ID_MODEL_FROM_DATABASE=MPC105 [Eagle] + +pci:v00001057d00000002* + ID_MODEL_FROM_DATABASE=MPC106 [Grackle] + +pci:v00001057d00000003* + ID_MODEL_FROM_DATABASE=MPC8240 [Kahlua] + +pci:v00001057d00000004* + ID_MODEL_FROM_DATABASE=MPC107 + +pci:v00001057d00000006* + ID_MODEL_FROM_DATABASE=MPC8245 [Unity] + +pci:v00001057d00000008* + ID_MODEL_FROM_DATABASE=MPC8540 + +pci:v00001057d00000009* + ID_MODEL_FROM_DATABASE=MPC8560 + +pci:v00001057d00000012* + ID_MODEL_FROM_DATABASE=MPC8548 [PowerQUICC III] + +pci:v00001057d00000100* + ID_MODEL_FROM_DATABASE=MC145575 [HFC-PCI] + +pci:v00001057d00000431* + ID_MODEL_FROM_DATABASE=KTI829c 100VG + +pci:v00001057d00001073* + ID_MODEL_FROM_DATABASE=Nokia N770 + +pci:v00001057d00001219* + ID_MODEL_FROM_DATABASE=Nokia N800 + +pci:v00001057d00001801* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor + +pci:v00001057d00001801sv000014FBsd00000101* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Transas Radar Imitator Board [RIM]) + +pci:v00001057d00001801sv000014FBsd00000102* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Transas Radar Imitator Board [RIM-2]) + +pci:v00001057d00001801sv000014FBsd00000202* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Transas Radar Integrator Board [RIB-2]) + +pci:v00001057d00001801sv000014FBsd00000611* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (1 channel CAN bus Controller [CanPci-1]) + +pci:v00001057d00001801sv000014FBsd00000612* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (2 channels CAN bus Controller [CanPci-2]) + +pci:v00001057d00001801sv000014FBsd00000613* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (3 channels CAN bus Controller [CanPci-3]) + +pci:v00001057d00001801sv000014FBsd00000614* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (4 channels CAN bus Controller [CanPci-4]) + +pci:v00001057d00001801sv000014FBsd00000621* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (1 channel CAN bus Controller [CanPci2-1]) + +pci:v00001057d00001801sv000014FBsd00000622* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (2 channels CAN bus Controller [CanPci2-2]) + +pci:v00001057d00001801sv000014FBsd00000810* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Transas VTS Radar Integrator Board [RIB-4]) + +pci:v00001057d00001801sv0000175Csd00004200* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (ASI4215 Audio Adapter) + +pci:v00001057d00001801sv0000175Csd00004300* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (ASI43xx Audio Adapter) + +pci:v00001057d00001801sv0000175Csd00004400* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (ASI4401 Audio Adapter) + +pci:v00001057d00001801sv0000ECC0sd00000010* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Darla) + +pci:v00001057d00001801sv0000ECC0sd00000020* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Gina) + +pci:v00001057d00001801sv0000ECC0sd00000030* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Layla rev.0) + +pci:v00001057d00001801sv0000ECC0sd00000031* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Layla rev.1) + +pci:v00001057d00001801sv0000ECC0sd00000040* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Darla24 rev.0) + +pci:v00001057d00001801sv0000ECC0sd00000041* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Darla24 rev.1) + +pci:v00001057d00001801sv0000ECC0sd00000050* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Gina24 rev.0) + +pci:v00001057d00001801sv0000ECC0sd00000051* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Gina24 rev.1) + +pci:v00001057d00001801sv0000ECC0sd00000070* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Mona rev.0) + +pci:v00001057d00001801sv0000ECC0sd00000071* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Mona rev.1) + +pci:v00001057d00001801sv0000ECC0sd00000072* + ID_MODEL_FROM_DATABASE=DSP56301 Digital Signal Processor (Mona rev.2) + +pci:v00001057d000018C0* + ID_MODEL_FROM_DATABASE=MPC8265A/8266/8272 + +pci:v00001057d000018C1* + ID_MODEL_FROM_DATABASE=MPC8271/MPC8272 + +pci:v00001057d00003052* + ID_MODEL_FROM_DATABASE=SM56 Data Fax Modem + +pci:v00001057d00003410* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor + +pci:v00001057d00003410sv0000ECC0sd00000050* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Gina24 rev.0) + +pci:v00001057d00003410sv0000ECC0sd00000051* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Gina24 rev.1) + +pci:v00001057d00003410sv0000ECC0sd00000060* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Layla24) + +pci:v00001057d00003410sv0000ECC0sd00000070* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Mona rev.0) + +pci:v00001057d00003410sv0000ECC0sd00000071* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Mona rev.1) + +pci:v00001057d00003410sv0000ECC0sd00000072* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Mona rev.2) + +pci:v00001057d00003410sv0000ECC0sd00000080* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Mia rev.0) + +pci:v00001057d00003410sv0000ECC0sd00000081* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Mia rev.1) + +pci:v00001057d00003410sv0000ECC0sd00000090* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Indigo) + +pci:v00001057d00003410sv0000ECC0sd000000A0* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Indigo IO) + +pci:v00001057d00003410sv0000ECC0sd000000B0* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (Indigo DJ) + +pci:v00001057d00003410sv0000ECC0sd00000100* + ID_MODEL_FROM_DATABASE=DSP56361 Digital Signal Processor (3G) + +pci:v00001057d00004801* + ID_MODEL_FROM_DATABASE=Raven + +pci:v00001057d00004802* + ID_MODEL_FROM_DATABASE=Falcon + +pci:v00001057d00004803* + ID_MODEL_FROM_DATABASE=Hawk + +pci:v00001057d00004806* + ID_MODEL_FROM_DATABASE=CPX8216 + +pci:v00001057d00004D68* + ID_MODEL_FROM_DATABASE=20268 + +pci:v00001057d00005600* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem + +pci:v00001057d00005600sv00001057sd00000300* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) + +pci:v00001057d00005600sv00001057sd00000301* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Voice Modem) + +pci:v00001057d00005600sv00001057sd00000302* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) + +pci:v00001057d00005600sv00001057sd00005600* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Voice modem) + +pci:v00001057d00005600sv000013D2sd00000300* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) + +pci:v00001057d00005600sv000013D2sd00000301* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Voice modem) + +pci:v00001057d00005600sv000013D2sd00000302* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) + +pci:v00001057d00005600sv00001436sd00000300* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) + +pci:v00001057d00005600sv00001436sd00000301* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Voice modem) + +pci:v00001057d00005600sv00001436sd00000302* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) + +pci:v00001057d00005600sv0000144Fsd0000100C* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) + +pci:v00001057d00005600sv00001494sd00000300* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) + +pci:v00001057d00005600sv00001494sd00000301* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Voice modem) + +pci:v00001057d00005600sv000014C8sd00000300* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) + +pci:v00001057d00005600sv000014C8sd00000302* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) + +pci:v00001057d00005600sv00001668sd00000300* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Speakerphone Modem) + +pci:v00001057d00005600sv00001668sd00000302* + ID_MODEL_FROM_DATABASE=SM56 PCI Modem (SM56 PCI Fax Modem) + +pci:v00001057d00005608* + ID_MODEL_FROM_DATABASE=Wildcard X100P + +pci:v00001057d00005803* + ID_MODEL_FROM_DATABASE=MPC5200 + +pci:v00001057d00005806* + ID_MODEL_FROM_DATABASE=MCF54 Coldfire + +pci:v00001057d00005808* + ID_MODEL_FROM_DATABASE=MPC8220 + +pci:v00001057d00005809* + ID_MODEL_FROM_DATABASE=MPC5200B + +pci:v00001057d00006400* + ID_MODEL_FROM_DATABASE=MPC190 Security Processor (S1 family, encryption) + +pci:v00001057d00006405* + ID_MODEL_FROM_DATABASE=MPC184 Security Processor (S1 family) + +pci:v00001058* + ID_VENDOR_FROM_DATABASE=Electronics & Telecommunications RSH + +pci:v00001059* + ID_VENDOR_FROM_DATABASE=Kontron + +pci:v0000105A* + ID_VENDOR_FROM_DATABASE=Promise Technology, Inc. + +pci:v0000105Ad00000D30* + ID_MODEL_FROM_DATABASE=PDC20265 (FastTrak100 Lite/Ultra100) + +pci:v0000105Ad00000D30sv00001043sd00008042* + ID_MODEL_FROM_DATABASE=PDC20265 (FastTrak100 Lite/Ultra100) (AV7266-E South Bridge Promise RAID) + +pci:v0000105Ad00000D30sv0000105Asd00004D33* + ID_MODEL_FROM_DATABASE=PDC20265 (FastTrak100 Lite/Ultra100) (Ultra100) + +pci:v0000105Ad00000D38* + ID_MODEL_FROM_DATABASE=20263 + +pci:v0000105Ad00000D38sv0000105Asd00004D39* + ID_MODEL_FROM_DATABASE=20263 (Fasttrak66) + +pci:v0000105Ad00001275* + ID_MODEL_FROM_DATABASE=20275 + +pci:v0000105Ad00003318* + ID_MODEL_FROM_DATABASE=PDC20318 (SATA150 TX4) + +pci:v0000105Ad00003319* + ID_MODEL_FROM_DATABASE=PDC20319 (FastTrak S150 TX4) + +pci:v0000105Ad00003319sv0000105Asd00003319* + ID_MODEL_FROM_DATABASE=PDC20319 (FastTrak S150 TX4) (FastTrak S150 TX4 4 port SATA PCI board) + +pci:v0000105Ad00003319sv00008086sd00003427* + ID_MODEL_FROM_DATABASE=PDC20319 (FastTrak S150 TX4) (S875WP1-E mainboard) + +pci:v0000105Ad00003371* + ID_MODEL_FROM_DATABASE=PDC20371 (FastTrak S150 TX2plus) + +pci:v0000105Ad00003373* + ID_MODEL_FROM_DATABASE=PDC20378 (FastTrak 378/SATA 378) + +pci:v0000105Ad00003373sv00001043sd000080F5* + ID_MODEL_FROM_DATABASE=PDC20378 (FastTrak 378/SATA 378) (K8V Deluxe/PC-DL Deluxe motherboard) + +pci:v0000105Ad00003373sv00001462sd0000590D* + ID_MODEL_FROM_DATABASE=PDC20378 (FastTrak 378/SATA 378) (KT6 Delta-FIS2R (MS-6590)) + +pci:v0000105Ad00003373sv00001462sd0000702E* + ID_MODEL_FROM_DATABASE=PDC20378 (FastTrak 378/SATA 378) (K8T NEO FIS2R motherboard) + +pci:v0000105Ad00003375* + ID_MODEL_FROM_DATABASE=PDC20375 (SATA150 TX2plus) + +pci:v0000105Ad00003376* + ID_MODEL_FROM_DATABASE=PDC20376 (FastTrak 376) + +pci:v0000105Ad00003376sv00001043sd0000809E* + ID_MODEL_FROM_DATABASE=PDC20376 (FastTrak 376) (A7V8X motherboard) + +pci:v0000105Ad00003515* + ID_MODEL_FROM_DATABASE=PDC40719 [FastTrak TX4300/TX4310] + +pci:v0000105Ad00003519* + ID_MODEL_FROM_DATABASE=PDC40519 (FastTrak TX4200) + +pci:v0000105Ad00003570* + ID_MODEL_FROM_DATABASE=PDC20771 [FastTrak TX2300] + +pci:v0000105Ad00003571* + ID_MODEL_FROM_DATABASE=PDC20571 (FastTrak TX2200) + +pci:v0000105Ad00003574* + ID_MODEL_FROM_DATABASE=PDC20579 SATAII 150 IDE Controller + +pci:v0000105Ad00003577* + ID_MODEL_FROM_DATABASE=PDC40779 (SATA 300 779) + +pci:v0000105Ad00003D17* + ID_MODEL_FROM_DATABASE=PDC40718 (SATA 300 TX4) + +pci:v0000105Ad00003D18* + ID_MODEL_FROM_DATABASE=PDC20518/PDC40518 (SATAII 150 TX4) + +pci:v0000105Ad00003D73* + ID_MODEL_FROM_DATABASE=PDC40775 (SATA 300 TX2plus) + +pci:v0000105Ad00003D75* + ID_MODEL_FROM_DATABASE=PDC20575 (SATAII150 TX2plus) + +pci:v0000105Ad00003F20* + ID_MODEL_FROM_DATABASE=PDC42819 [FastTrak TX2650/TX4650] + +pci:v0000105Ad00004302* + ID_MODEL_FROM_DATABASE=80333 [SuperTrak EX4350] + +pci:v0000105Ad00004D30* + ID_MODEL_FROM_DATABASE=PDC20267 (FastTrak100/Ultra100) + +pci:v0000105Ad00004D30sv0000105Asd00004D33* + ID_MODEL_FROM_DATABASE=PDC20267 (FastTrak100/Ultra100) (Ultra100) + +pci:v0000105Ad00004D30sv0000105Asd00004D39* + ID_MODEL_FROM_DATABASE=PDC20267 (FastTrak100/Ultra100) (FastTrak100) + +pci:v0000105Ad00004D30sv00008086sd00005744* + ID_MODEL_FROM_DATABASE=PDC20267 (FastTrak100/Ultra100) (S845WD1-E mainboard) + +pci:v0000105Ad00004D33* + ID_MODEL_FROM_DATABASE=20246 + +pci:v0000105Ad00004D33sv0000105Asd00004D33* + ID_MODEL_FROM_DATABASE=20246 (IDE Controller) + +pci:v0000105Ad00004D38* + ID_MODEL_FROM_DATABASE=PDC20262 (FastTrak66/Ultra66) + +pci:v0000105Ad00004D38sv0000105Asd00004D30* + ID_MODEL_FROM_DATABASE=PDC20262 (FastTrak66/Ultra66) (Ultra Device on SuperTrak) + +pci:v0000105Ad00004D38sv0000105Asd00004D33* + ID_MODEL_FROM_DATABASE=PDC20262 (FastTrak66/Ultra66) (Ultra66) + +pci:v0000105Ad00004D38sv0000105Asd00004D39* + ID_MODEL_FROM_DATABASE=PDC20262 (FastTrak66/Ultra66) (FastTrak66) + +pci:v0000105Ad00004D68* + ID_MODEL_FROM_DATABASE=PDC20268 [Ultra100 TX2] + +pci:v0000105Ad00004D68sv0000105Asd00004D68* + ID_MODEL_FROM_DATABASE=PDC20268 [Ultra100 TX2] (Ultra100 TX2) + +pci:v0000105Ad00004D69* + ID_MODEL_FROM_DATABASE=20269 + +pci:v0000105Ad00004D69sv0000105Asd00004D68* + ID_MODEL_FROM_DATABASE=20269 (Ultra133TX2) + +pci:v0000105Ad00005275* + ID_MODEL_FROM_DATABASE=PDC20276 (MBFastTrak133 Lite) + +pci:v0000105Ad00005275sv00001043sd0000807E* + ID_MODEL_FROM_DATABASE=PDC20276 (MBFastTrak133 Lite) (A7V333 motherboard.) + +pci:v0000105Ad00005275sv0000105Asd00000275* + ID_MODEL_FROM_DATABASE=PDC20276 (MBFastTrak133 Lite) (SuperTrak SX6000 IDE) + +pci:v0000105Ad00005275sv0000105Asd00001275* + ID_MODEL_FROM_DATABASE=PDC20276 (MBFastTrak133 Lite) (MBFastTrak133 Lite (tm) Controller (RAID mode)) + +pci:v0000105Ad00005275sv00001458sd0000B001* + ID_MODEL_FROM_DATABASE=PDC20276 (MBFastTrak133 Lite) (MBUltra 133) + +pci:v0000105Ad00005300* + ID_MODEL_FROM_DATABASE=DC5300 + +pci:v0000105Ad00006268* + ID_MODEL_FROM_DATABASE=PDC20270 (FastTrak100 LP/TX2/TX4) + +pci:v0000105Ad00006268sv0000105Asd00004D68* + ID_MODEL_FROM_DATABASE=PDC20270 (FastTrak100 LP/TX2/TX4) (FastTrak100 TX2) + +pci:v0000105Ad00006269* + ID_MODEL_FROM_DATABASE=PDC20271 (FastTrak TX2000) + +pci:v0000105Ad00006269sv0000105Asd00006269* + ID_MODEL_FROM_DATABASE=PDC20271 (FastTrak TX2000) (FastTrak TX2/TX2000) + +pci:v0000105Ad00006300* + ID_MODEL_FROM_DATABASE=PDC81731 [FastTrak SX8300] + +pci:v0000105Ad00006621* + ID_MODEL_FROM_DATABASE=PDC20621 (FastTrak S150 SX4/FastTrak SX4000 lite) + +pci:v0000105Ad00006622* + ID_MODEL_FROM_DATABASE=PDC20621 [SATA150 SX4] 4 Channel IDE RAID Controller + +pci:v0000105Ad00006624* + ID_MODEL_FROM_DATABASE=PDC20621 [FastTrak SX4100] + +pci:v0000105Ad00006626* + ID_MODEL_FROM_DATABASE=PDC20618 (Ultra 618) + +pci:v0000105Ad00006629* + ID_MODEL_FROM_DATABASE=PDC20619 (FastTrak TX4000) + +pci:v0000105Ad00007275* + ID_MODEL_FROM_DATABASE=PDC20277 (SBFastTrak133 Lite) + +pci:v0000105Ad00008002* + ID_MODEL_FROM_DATABASE=SATAII150 SX8 + +pci:v0000105Ad00008350* + ID_MODEL_FROM_DATABASE=80333 [SuperTrak EX8350/EX16350], 80331 [SuperTrak EX8300/EX16300] + +pci:v0000105Ad00008650* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] + +pci:v0000105Ad00008650sv0000105Asd00004600* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX4650A) + +pci:v0000105Ad00008650sv0000105Asd00004601* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX4650) + +pci:v0000105Ad00008650sv0000105Asd00004610* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX4650EL) + +pci:v0000105Ad00008650sv0000105Asd00008600* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8650EL) + +pci:v0000105Ad00008650sv0000105Asd00008601* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8650A) + +pci:v0000105Ad00008650sv0000105Asd00008602* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8654) + +pci:v0000105Ad00008650sv0000105Asd00008603* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8658) + +pci:v0000105Ad00008650sv0000105Asd00008604* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8650) + +pci:v0000105Ad00008650sv0000105Asd00008610* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX8650M) + +pci:v0000105Ad00008650sv0000105Asd0000A600* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX12650) + +pci:v0000105Ad00008650sv0000105Asd0000B600* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX16650) + +pci:v0000105Ad00008650sv0000105Asd0000B601* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX16654) + +pci:v0000105Ad00008650sv0000105Asd0000B602* + ID_MODEL_FROM_DATABASE=81384 [SuperTrak EX SAS and SATA RAID Controller] (SuperTrak EX16658) + +pci:v0000105Ad00008760* + ID_MODEL_FROM_DATABASE=PM8010 [SuperTrak EX SAS and SATA 6G RAID Controller] + +pci:v0000105Ad0000C350* + ID_MODEL_FROM_DATABASE=80333 [SuperTrak EX12350] + +pci:v0000105Ad0000E350* + ID_MODEL_FROM_DATABASE=80333 [SuperTrak EX24350] + +pci:v0000105B* + ID_VENDOR_FROM_DATABASE=Foxconn International, Inc. + +pci:v0000105C* + ID_VENDOR_FROM_DATABASE=Wipro Infotech Limited + +pci:v0000105D* + ID_VENDOR_FROM_DATABASE=Number 9 Computer Company + +pci:v0000105Dd00002309* + ID_MODEL_FROM_DATABASE=Imagine 128 + +pci:v0000105Dd00002339* + ID_MODEL_FROM_DATABASE=Imagine 128-II + +pci:v0000105Dd00002339sv0000105Dsd00000000* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) + +pci:v0000105Dd00002339sv0000105Dsd00000001* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) + +pci:v0000105Dd00002339sv0000105Dsd00000002* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) + +pci:v0000105Dd00002339sv0000105Dsd00000003* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) + +pci:v0000105Dd00002339sv0000105Dsd00000004* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) + +pci:v0000105Dd00002339sv0000105Dsd00000005* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) + +pci:v0000105Dd00002339sv0000105Dsd00000006* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) + +pci:v0000105Dd00002339sv0000105Dsd00000007* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 4Mb VRAM) + +pci:v0000105Dd00002339sv0000105Dsd00000008* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2e 4Mb DRAM) + +pci:v0000105Dd00002339sv0000105Dsd00000009* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2e 4Mb DRAM) + +pci:v0000105Dd00002339sv0000105Dsd0000000A* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 8Mb VRAM) + +pci:v0000105Dd00002339sv0000105Dsd0000000B* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Imagine 128 series 2 8Mb H-VRAM) + +pci:v0000105Dd00002339sv000011A4sd0000000A* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) + +pci:v0000105Dd00002339sv000013CCsd00000000* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) + +pci:v0000105Dd00002339sv000013CCsd00000004* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) + +pci:v0000105Dd00002339sv000013CCsd00000005* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) + +pci:v0000105Dd00002339sv000013CCsd00000006* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) + +pci:v0000105Dd00002339sv000013CCsd00000008* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) + +pci:v0000105Dd00002339sv000013CCsd00000009* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) + +pci:v0000105Dd00002339sv000013CCsd0000000A* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) + +pci:v0000105Dd00002339sv000013CCsd0000000C* + ID_MODEL_FROM_DATABASE=Imagine 128-II (Barco Metheus 5 Megapixel) + +pci:v0000105Dd0000493D* + ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] + +pci:v0000105Dd0000493Dsv000011A4sd0000000A* + ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) + +pci:v0000105Dd0000493Dsv000011A4sd0000000B* + ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) + +pci:v0000105Dd0000493Dsv000013CCsd00000002* + ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 4 Megapixel, Dual Head) + +pci:v0000105Dd0000493Dsv000013CCsd00000003* + ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) + +pci:v0000105Dd0000493Dsv000013CCsd00000007* + ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) + +pci:v0000105Dd0000493Dsv000013CCsd00000008* + ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) + +pci:v0000105Dd0000493Dsv000013CCsd00000009* + ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) + +pci:v0000105Dd0000493Dsv000013CCsd0000000A* + ID_MODEL_FROM_DATABASE=Imagine 128 T2R [Ticket to Ride] (Barco Metheus 5 Megapixel, Dual Head) + +pci:v0000105Dd00005348* + ID_MODEL_FROM_DATABASE=Revolution 4 + +pci:v0000105Dd00005348sv0000105Dsd00000037* + ID_MODEL_FROM_DATABASE=Revolution 4 (Revolution IV-FP AGP (For SGI 1600SW)) + +pci:v0000105Dd00005348sv000011A4sd00000028* + ID_MODEL_FROM_DATABASE=Revolution 4 (PVS5600M) + +pci:v0000105Dd00005348sv000011A4sd00000038* + ID_MODEL_FROM_DATABASE=Revolution 4 (PVS5600D) + +pci:v0000105E* + ID_VENDOR_FROM_DATABASE=Vtech Computers Ltd + +pci:v0000105F* + ID_VENDOR_FROM_DATABASE=Infotronic America Inc + +pci:v00001060* + ID_VENDOR_FROM_DATABASE=United Microelectronics [UMC] + +pci:v00001060d00000001* + ID_MODEL_FROM_DATABASE=UM82C881 + +pci:v00001060d00000002* + ID_MODEL_FROM_DATABASE=UM82C886 + +pci:v00001060d00000101* + ID_MODEL_FROM_DATABASE=UM8673F + +pci:v00001060d00000881* + ID_MODEL_FROM_DATABASE=UM8881 + +pci:v00001060d00000886* + ID_MODEL_FROM_DATABASE=UM8886F + +pci:v00001060d00000891* + ID_MODEL_FROM_DATABASE=UM8891A + +pci:v00001060d00001001* + ID_MODEL_FROM_DATABASE=UM886A + +pci:v00001060d0000673A* + ID_MODEL_FROM_DATABASE=UM8886BF + +pci:v00001060d0000673B* + ID_MODEL_FROM_DATABASE=EIDE Master/DMA + +pci:v00001060d00008710* + ID_MODEL_FROM_DATABASE=UM8710 + +pci:v00001060d0000886A* + ID_MODEL_FROM_DATABASE=UM8886A + +pci:v00001060d00008881* + ID_MODEL_FROM_DATABASE=UM8881F + +pci:v00001060d00008886* + ID_MODEL_FROM_DATABASE=UM8886F + +pci:v00001060d0000888A* + ID_MODEL_FROM_DATABASE=UM8886A + +pci:v00001060d00008891* + ID_MODEL_FROM_DATABASE=UM8891A + +pci:v00001060d00009017* + ID_MODEL_FROM_DATABASE=UM9017F + +pci:v00001060d00009018* + ID_MODEL_FROM_DATABASE=UM9018 + +pci:v00001060d00009026* + ID_MODEL_FROM_DATABASE=UM9026 + +pci:v00001060d0000E881* + ID_MODEL_FROM_DATABASE=UM8881N + +pci:v00001060d0000E886* + ID_MODEL_FROM_DATABASE=UM8886N + +pci:v00001060d0000E88A* + ID_MODEL_FROM_DATABASE=UM8886N + +pci:v00001060d0000E891* + ID_MODEL_FROM_DATABASE=UM8891N + +pci:v00001061* + ID_VENDOR_FROM_DATABASE=I.I.T. + +pci:v00001061d00000001* + ID_MODEL_FROM_DATABASE=AGX016 + +pci:v00001061d00000002* + ID_MODEL_FROM_DATABASE=IIT3204/3501 + +pci:v00001062* + ID_VENDOR_FROM_DATABASE=Maspar Computer Corp + +pci:v00001063* + ID_VENDOR_FROM_DATABASE=Ocean Office Automation + +pci:v00001064* + ID_VENDOR_FROM_DATABASE=Alcatel + +pci:v00001064d00001102* + ID_MODEL_FROM_DATABASE=Dynamite 2840 (ADSL PCI modem) + +pci:v00001065* + ID_VENDOR_FROM_DATABASE=Texas Microsystems + +pci:v00001066* + ID_VENDOR_FROM_DATABASE=PicoPower Technology + +pci:v00001066d00000000* + ID_MODEL_FROM_DATABASE=PT80C826 + +pci:v00001066d00000001* + ID_MODEL_FROM_DATABASE=PT86C521 [Vesuvius v1] Host Bridge + +pci:v00001066d00000002* + ID_MODEL_FROM_DATABASE=PT86C523 [Vesuvius v3] PCI-ISA Bridge Master + +pci:v00001066d00000003* + ID_MODEL_FROM_DATABASE=PT86C524 [Nile] PCI-to-PCI Bridge + +pci:v00001066d00000004* + ID_MODEL_FROM_DATABASE=PT86C525 [Nile-II] PCI-to-PCI Bridge + +pci:v00001066d00000005* + ID_MODEL_FROM_DATABASE=National PC87550 System Controller + +pci:v00001066d00008002* + ID_MODEL_FROM_DATABASE=PT86C523 [Vesuvius v3] PCI-ISA Bridge Slave + +pci:v00001067* + ID_VENDOR_FROM_DATABASE=Mitsubishi Electric + +pci:v00001067d00000301* + ID_MODEL_FROM_DATABASE=AccelGraphics AccelECLIPSE + +pci:v00001067d00000304* + ID_MODEL_FROM_DATABASE=AccelGALAXY A2100 [OEM Evans & Sutherland] + +pci:v00001067d00000308* + ID_MODEL_FROM_DATABASE=Tornado 3000 [OEM Evans & Sutherland] + +pci:v00001067d00001002* + ID_MODEL_FROM_DATABASE=VG500 [VolumePro Volume Rendering Accelerator] + +pci:v00001068* + ID_VENDOR_FROM_DATABASE=Diversified Technology + +pci:v00001069* + ID_VENDOR_FROM_DATABASE=Mylex Corporation + +pci:v00001069d00000001* + ID_MODEL_FROM_DATABASE=DAC960P + +pci:v00001069d00000002* + ID_MODEL_FROM_DATABASE=DAC960PD + +pci:v00001069d00000010* + ID_MODEL_FROM_DATABASE=DAC960PG + +pci:v00001069d00000020* + ID_MODEL_FROM_DATABASE=DAC960LA + +pci:v00001069d00000050* + ID_MODEL_FROM_DATABASE=AcceleRAID 352/170/160 support Device + +pci:v00001069d00000050sv00001069sd00000050* + ID_MODEL_FROM_DATABASE=AcceleRAID 352/170/160 support Device (AcceleRAID 352 support Device) + +pci:v00001069d00000050sv00001069sd00000052* + ID_MODEL_FROM_DATABASE=AcceleRAID 352/170/160 support Device (AcceleRAID 170 support Device) + +pci:v00001069d00000050sv00001069sd00000054* + ID_MODEL_FROM_DATABASE=AcceleRAID 352/170/160 support Device (AcceleRAID 160 support Device) + +pci:v00001069d0000B166* + ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device + +pci:v00001069d0000B166sv00001014sd00000242* + ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (iSeries 2872 DASD IOA) + +pci:v00001069d0000B166sv00001014sd00000266* + ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (Dual Channel PCI-X U320 SCSI Adapter) + +pci:v00001069d0000B166sv00001014sd00000278* + ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (Dual Channel PCI-X U320 SCSI RAID Adapter) + +pci:v00001069d0000B166sv00001014sd000002D3* + ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (Dual Channel PCI-X U320 SCSI Adapter) + +pci:v00001069d0000B166sv00001014sd000002D4* + ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (Dual Channel PCI-X U320 SCSI RAID Adapter) + +pci:v00001069d0000B166sv00001069sd00000200* + ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (AcceleRAID 400, Single Channel, PCI-X, U320, SCSI RAID) + +pci:v00001069d0000B166sv00001069sd00000202* + ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (AcceleRAID Sapphire, Dual Channel, PCI-X, U320, SCSI RAID) + +pci:v00001069d0000B166sv00001069sd00000204* + ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (AcceleRAID 500, Dual Channel, Low-Profile, PCI-X, U320, SCSI RAID) + +pci:v00001069d0000B166sv00001069sd00000206* + ID_MODEL_FROM_DATABASE=AcceleRAID 600/500/400/Sapphire support Device (AcceleRAID 600, Dual Channel, PCI-X, U320, SCSI RAID) + +pci:v00001069d0000BA55* + ID_MODEL_FROM_DATABASE=eXtremeRAID 1100 support Device + +pci:v00001069d0000BA56* + ID_MODEL_FROM_DATABASE=eXtremeRAID 2000/3000 support Device + +pci:v00001069d0000BA56sv00001069sd00000030* + ID_MODEL_FROM_DATABASE=eXtremeRAID 2000/3000 support Device (eXtremeRAID 3000 support Device) + +pci:v00001069d0000BA56sv00001069sd00000040* + ID_MODEL_FROM_DATABASE=eXtremeRAID 2000/3000 support Device (eXtremeRAID 2000 support Device) + +pci:v00001069d0000BA57* + ID_MODEL_FROM_DATABASE=eXtremeRAID 4000/5000 support Device + +pci:v00001069d0000BA57sv00001069sd00000072* + ID_MODEL_FROM_DATABASE=eXtremeRAID 4000/5000 support Device (eXtremeRAID 5000 support Device) + +pci:v0000106A* + ID_VENDOR_FROM_DATABASE=Aten Research Inc + +pci:v0000106B* + ID_VENDOR_FROM_DATABASE=Apple Inc. + +pci:v0000106Bd00000001* + ID_MODEL_FROM_DATABASE=Bandit PowerPC host bridge + +pci:v0000106Bd00000002* + ID_MODEL_FROM_DATABASE=Grand Central I/O + +pci:v0000106Bd00000003* + ID_MODEL_FROM_DATABASE=Control Video + +pci:v0000106Bd00000004* + ID_MODEL_FROM_DATABASE=PlanB Video-In + +pci:v0000106Bd00000007* + ID_MODEL_FROM_DATABASE=O'Hare I/O + +pci:v0000106Bd0000000C* + ID_MODEL_FROM_DATABASE=DOS on Mac + +pci:v0000106Bd0000000E* + ID_MODEL_FROM_DATABASE=Hydra Mac I/O + +pci:v0000106Bd00000010* + ID_MODEL_FROM_DATABASE=Heathrow Mac I/O + +pci:v0000106Bd00000017* + ID_MODEL_FROM_DATABASE=Paddington Mac I/O + +pci:v0000106Bd00000018* + ID_MODEL_FROM_DATABASE=UniNorth FireWire + +pci:v0000106Bd00000019* + ID_MODEL_FROM_DATABASE=KeyLargo USB + +pci:v0000106Bd0000001E* + ID_MODEL_FROM_DATABASE=UniNorth Internal PCI + +pci:v0000106Bd0000001F* + ID_MODEL_FROM_DATABASE=UniNorth PCI + +pci:v0000106Bd00000020* + ID_MODEL_FROM_DATABASE=UniNorth AGP + +pci:v0000106Bd00000021* + ID_MODEL_FROM_DATABASE=UniNorth GMAC (Sun GEM) + +pci:v0000106Bd00000022* + ID_MODEL_FROM_DATABASE=KeyLargo Mac I/O + +pci:v0000106Bd00000024* + ID_MODEL_FROM_DATABASE=UniNorth/Pangea GMAC (Sun GEM) + +pci:v0000106Bd00000025* + ID_MODEL_FROM_DATABASE=KeyLargo/Pangea Mac I/O + +pci:v0000106Bd00000026* + ID_MODEL_FROM_DATABASE=KeyLargo/Pangea USB + +pci:v0000106Bd00000027* + ID_MODEL_FROM_DATABASE=UniNorth/Pangea AGP + +pci:v0000106Bd00000028* + ID_MODEL_FROM_DATABASE=UniNorth/Pangea PCI + +pci:v0000106Bd00000029* + ID_MODEL_FROM_DATABASE=UniNorth/Pangea Internal PCI + +pci:v0000106Bd0000002D* + ID_MODEL_FROM_DATABASE=UniNorth 1.5 AGP + +pci:v0000106Bd0000002E* + ID_MODEL_FROM_DATABASE=UniNorth 1.5 PCI + +pci:v0000106Bd0000002F* + ID_MODEL_FROM_DATABASE=UniNorth 1.5 Internal PCI + +pci:v0000106Bd00000030* + ID_MODEL_FROM_DATABASE=UniNorth/Pangea FireWire + +pci:v0000106Bd00000031* + ID_MODEL_FROM_DATABASE=UniNorth 2 FireWire + +pci:v0000106Bd00000031sv0000106Bsd00005811* + ID_MODEL_FROM_DATABASE=UniNorth 2 FireWire (iBook G4 2004) + +pci:v0000106Bd00000032* + ID_MODEL_FROM_DATABASE=UniNorth 2 GMAC (Sun GEM) + +pci:v0000106Bd00000033* + ID_MODEL_FROM_DATABASE=UniNorth 2 ATA/100 + +pci:v0000106Bd00000034* + ID_MODEL_FROM_DATABASE=UniNorth 2 AGP + +pci:v0000106Bd00000035* + ID_MODEL_FROM_DATABASE=UniNorth 2 PCI + +pci:v0000106Bd00000036* + ID_MODEL_FROM_DATABASE=UniNorth 2 Internal PCI + +pci:v0000106Bd0000003B* + ID_MODEL_FROM_DATABASE=UniNorth/Intrepid ATA/100 + +pci:v0000106Bd0000003E* + ID_MODEL_FROM_DATABASE=KeyLargo/Intrepid Mac I/O + +pci:v0000106Bd0000003F* + ID_MODEL_FROM_DATABASE=KeyLargo/Intrepid USB + +pci:v0000106Bd0000003Fsv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=KeyLargo/Intrepid USB (QEMU Virtual Machine) + +pci:v0000106Bd00000040* + ID_MODEL_FROM_DATABASE=K2 KeyLargo USB + +pci:v0000106Bd00000041* + ID_MODEL_FROM_DATABASE=K2 KeyLargo Mac/IO + +pci:v0000106Bd00000042* + ID_MODEL_FROM_DATABASE=K2 FireWire + +pci:v0000106Bd00000043* + ID_MODEL_FROM_DATABASE=K2 ATA/100 + +pci:v0000106Bd00000045* + ID_MODEL_FROM_DATABASE=K2 HT-PCI Bridge + +pci:v0000106Bd00000046* + ID_MODEL_FROM_DATABASE=K2 HT-PCI Bridge + +pci:v0000106Bd00000047* + ID_MODEL_FROM_DATABASE=K2 HT-PCI Bridge + +pci:v0000106Bd00000048* + ID_MODEL_FROM_DATABASE=K2 HT-PCI Bridge + +pci:v0000106Bd00000049* + ID_MODEL_FROM_DATABASE=K2 HT-PCI Bridge + +pci:v0000106Bd0000004A* + ID_MODEL_FROM_DATABASE=CPC945 HT Bridge + +pci:v0000106Bd0000004B* + ID_MODEL_FROM_DATABASE=U3 AGP + +pci:v0000106Bd0000004C* + ID_MODEL_FROM_DATABASE=K2 GMAC (Sun GEM) + +pci:v0000106Bd0000004F* + ID_MODEL_FROM_DATABASE=Shasta Mac I/O + +pci:v0000106Bd00000050* + ID_MODEL_FROM_DATABASE=Shasta IDE + +pci:v0000106Bd00000051* + ID_MODEL_FROM_DATABASE=Shasta (Sun GEM) + +pci:v0000106Bd00000052* + ID_MODEL_FROM_DATABASE=Shasta Firewire + +pci:v0000106Bd00000053* + ID_MODEL_FROM_DATABASE=Shasta PCI Bridge + +pci:v0000106Bd00000054* + ID_MODEL_FROM_DATABASE=Shasta PCI Bridge + +pci:v0000106Bd00000055* + ID_MODEL_FROM_DATABASE=Shasta PCI Bridge + +pci:v0000106Bd00000056* + ID_MODEL_FROM_DATABASE=U4 PCIe + +pci:v0000106Bd00000057* + ID_MODEL_FROM_DATABASE=U3 HT Bridge + +pci:v0000106Bd00000058* + ID_MODEL_FROM_DATABASE=U3L AGP Bridge + +pci:v0000106Bd00000059* + ID_MODEL_FROM_DATABASE=U3H AGP Bridge + +pci:v0000106Bd0000005B* + ID_MODEL_FROM_DATABASE=CPC945 PCIe Bridge + +pci:v0000106Bd00000066* + ID_MODEL_FROM_DATABASE=Intrepid2 AGP Bridge + +pci:v0000106Bd00000067* + ID_MODEL_FROM_DATABASE=Intrepid2 PCI Bridge + +pci:v0000106Bd00000068* + ID_MODEL_FROM_DATABASE=Intrepid2 PCI Bridge + +pci:v0000106Bd00000069* + ID_MODEL_FROM_DATABASE=Intrepid2 ATA/100 + +pci:v0000106Bd0000006A* + ID_MODEL_FROM_DATABASE=Intrepid2 Firewire + +pci:v0000106Bd0000006B* + ID_MODEL_FROM_DATABASE=Intrepid2 GMAC (Sun GEM) + +pci:v0000106Bd00000074* + ID_MODEL_FROM_DATABASE=U4 HT Bridge + +pci:v0000106Bd00001645* + ID_MODEL_FROM_DATABASE=Broadcom NetXtreme BCM5701 Gigabit Ethernet + +pci:v0000106Bd00001801* + ID_MODEL_FROM_DATABASE=T2 Bridge Controller + +pci:v0000106Bd00001802* + ID_MODEL_FROM_DATABASE=T2 Secure Enclave Processor + +pci:v0000106Bd00001803* + ID_MODEL_FROM_DATABASE=Apple Audio Device + +pci:v0000106Bd00002001* + ID_MODEL_FROM_DATABASE=S1X NVMe Controller + +pci:v0000106Bd00002002* + ID_MODEL_FROM_DATABASE=S3ELab NVMe Controller + +pci:v0000106Bd00002003* + ID_MODEL_FROM_DATABASE=S3X NVMe Controller + +pci:v0000106Bd00002005* + ID_MODEL_FROM_DATABASE=ANS2 NVMe Controller + +pci:v0000106C* + ID_VENDOR_FROM_DATABASE=Hynix Semiconductor + +pci:v0000106Cd00008139* + ID_MODEL_FROM_DATABASE=8139c 100BaseTX Ethernet Controller + +pci:v0000106Cd00008801* + ID_MODEL_FROM_DATABASE=Dual Pentium ISA/PCI Motherboard + +pci:v0000106Cd00008802* + ID_MODEL_FROM_DATABASE=PowerPC ISA/PCI Motherboard + +pci:v0000106Cd00008803* + ID_MODEL_FROM_DATABASE=Dual Window Graphics Accelerator + +pci:v0000106Cd00008804* + ID_MODEL_FROM_DATABASE=LAN Controller + +pci:v0000106Cd00008805* + ID_MODEL_FROM_DATABASE=100-BaseT LAN + +pci:v0000106D* + ID_VENDOR_FROM_DATABASE=Sequent Computer Systems + +pci:v0000106E* + ID_VENDOR_FROM_DATABASE=DFI, Inc + +pci:v0000106F* + ID_VENDOR_FROM_DATABASE=City Gate Development Ltd + +pci:v00001070* + ID_VENDOR_FROM_DATABASE=Daewoo Telecom Ltd + +pci:v00001071* + ID_VENDOR_FROM_DATABASE=Mitac + +pci:v00001071d00008160* + ID_MODEL_FROM_DATABASE=Mitac 8060B Mobile Platform + +pci:v00001072* + ID_VENDOR_FROM_DATABASE=GIT Co Ltd + +pci:v00001073* + ID_VENDOR_FROM_DATABASE=Yamaha Corporation + +pci:v00001073d00000001* + ID_MODEL_FROM_DATABASE=3D GUI Accelerator + +pci:v00001073d00000002* + ID_MODEL_FROM_DATABASE=YGV615 [RPA3 3D-Graphics Controller] + +pci:v00001073d00000003* + ID_MODEL_FROM_DATABASE=YMF-740 + +pci:v00001073d00000004* + ID_MODEL_FROM_DATABASE=YMF-724 + +pci:v00001073d00000004sv00001073sd00000004* + ID_MODEL_FROM_DATABASE=YMF-724 (YMF724-Based PCI Audio Adapter) + +pci:v00001073d00000005* + ID_MODEL_FROM_DATABASE=DS1 Audio + +pci:v00001073d00000005sv00001073sd00000005* + ID_MODEL_FROM_DATABASE=DS1 Audio (DS-XG PCI Audio CODEC) + +pci:v00001073d00000006* + ID_MODEL_FROM_DATABASE=DS1 Audio + +pci:v00001073d00000008* + ID_MODEL_FROM_DATABASE=DS1 Audio + +pci:v00001073d00000008sv00001073sd00000008* + ID_MODEL_FROM_DATABASE=DS1 Audio (DS-XG PCI Audio CODEC) + +pci:v00001073d0000000A* + ID_MODEL_FROM_DATABASE=DS1L Audio + +pci:v00001073d0000000Asv00001073sd00000004* + ID_MODEL_FROM_DATABASE=DS1L Audio (DS-XG PCI Audio CODEC) + +pci:v00001073d0000000Asv00001073sd0000000A* + ID_MODEL_FROM_DATABASE=DS1L Audio (DS-XG PCI Audio CODEC) + +pci:v00001073d0000000Asv00008086sd00004D55* + ID_MODEL_FROM_DATABASE=DS1L Audio (DS-XG PCI Audio CODEC [Intel MU440EX]) + +pci:v00001073d0000000C* + ID_MODEL_FROM_DATABASE=YMF-740C [DS-1L Audio Controller] + +pci:v00001073d0000000Csv0000107Asd0000000C* + ID_MODEL_FROM_DATABASE=YMF-740C [DS-1L Audio Controller] (DS-XG PCI Audio CODEC) + +pci:v00001073d0000000D* + ID_MODEL_FROM_DATABASE=YMF-724F [DS-1 Audio Controller] + +pci:v00001073d0000000Dsv00001073sd0000000D* + ID_MODEL_FROM_DATABASE=YMF-724F [DS-1 Audio Controller] (DS-XG PCI Audio CODEC) + +pci:v00001073d00000010* + ID_MODEL_FROM_DATABASE=YMF-744B [DS-1S Audio Controller] + +pci:v00001073d00000010sv00001073sd00000006* + ID_MODEL_FROM_DATABASE=YMF-744B [DS-1S Audio Controller] (DS-XG PCI Audio CODEC) + +pci:v00001073d00000010sv00001073sd00000010* + ID_MODEL_FROM_DATABASE=YMF-744B [DS-1S Audio Controller] (DS-XG PCI Audio CODEC) + +pci:v00001073d00000012* + ID_MODEL_FROM_DATABASE=YMF-754 [DS-1E Audio Controller] + +pci:v00001073d00000012sv00001073sd00000012* + ID_MODEL_FROM_DATABASE=YMF-754 [DS-1E Audio Controller] (DS-XG PCI Audio Codec) + +pci:v00001073d00000020* + ID_MODEL_FROM_DATABASE=DS-1 Audio + +pci:v00001073d00001000* + ID_MODEL_FROM_DATABASE=SW1000XG [XG Factory] + +pci:v00001073d00002000* + ID_MODEL_FROM_DATABASE=DS2416 Digital Mixing Card + +pci:v00001073d00002000sv00001073sd00002000* + ID_MODEL_FROM_DATABASE=DS2416 Digital Mixing Card + +pci:v00001074* + ID_VENDOR_FROM_DATABASE=NexGen Microsystems + +pci:v00001074d00004E78* + ID_MODEL_FROM_DATABASE=82c500/1 + +pci:v00001075* + ID_VENDOR_FROM_DATABASE=Advanced Integrations Research + +pci:v00001076* + ID_VENDOR_FROM_DATABASE=Chaintech Computer Co. Ltd + +pci:v00001077* + ID_VENDOR_FROM_DATABASE=QLogic Corp. + +pci:v00001077d00001016* + ID_MODEL_FROM_DATABASE=ISP10160 Single Channel Ultra3 SCSI Processor + +pci:v00001077d00001020* + ID_MODEL_FROM_DATABASE=ISP1020 Fast-wide SCSI + +pci:v00001077d00001022* + ID_MODEL_FROM_DATABASE=ISP1022 Fast-wide SCSI + +pci:v00001077d00001080* + ID_MODEL_FROM_DATABASE=ISP1080 SCSI Host Adapter + +pci:v00001077d00001216* + ID_MODEL_FROM_DATABASE=ISP12160 Dual Channel Ultra3 SCSI Processor + +pci:v00001077d00001216sv0000101Esd00008471* + ID_MODEL_FROM_DATABASE=ISP12160 Dual Channel Ultra3 SCSI Processor (QLA12160 on AMI MegaRAID) + +pci:v00001077d00001216sv0000101Esd00008493* + ID_MODEL_FROM_DATABASE=ISP12160 Dual Channel Ultra3 SCSI Processor (QLA12160 on AMI MegaRAID) + +pci:v00001077d00001240* + ID_MODEL_FROM_DATABASE=ISP1240 SCSI Host Adapter + +pci:v00001077d00001280* + ID_MODEL_FROM_DATABASE=ISP1280 SCSI Host Adapter + +pci:v00001077d00001634* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller + +pci:v00001077d00001634sv00001077sd0000E4F1* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FastLinQ QL45212H 40GbE Adapter) + +pci:v00001077d00001634sv00001077sd0000E4F2* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FastLinQ QL45211H 40GbE Adapter) + +pci:v00001077d00001634sv00001077sd0000E4F3* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FastLinQ QL45412H 40GbE Adapter) + +pci:v00001077d00001634sv00001077sd0000E4F4* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 40GbE Controller (FastLinQ QL45411H 40GbE Adapter) + +pci:v00001077d00001644* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 100GbE Controller + +pci:v00001077d00001644sv00001077sd0000E4F8* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 100GbE Controller (FastLinQ QL45611H 100GbE Adapter) + +pci:v00001077d00001654* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 50GbE Controller + +pci:v00001077d00001654sv00001077sd00000032* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 50GbE Controller (QL45212 Flex 50Gb 2-port Ethernet Adapter) + +pci:v00001077d00001654sv00001590sd00000223* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 50GbE Controller (Synergy 6810C 25/50Gb Ethernet Adapter) + +pci:v00001077d00001654sv00001590sd00000287* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 50GbE Controller (Synergy 6820C 25/50Gb CNA) + +pci:v00001077d00001656* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller + +pci:v00001077d00001656sv00001077sd00000033* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (QL45214 Flex 25Gb 4-port Ethernet Adapter) + +pci:v00001077d00001656sv00001077sd000002A7* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (QL45212-DE 25GbE Adapter) + +pci:v00001077d00001656sv00001077sd0000E4F6* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (FastLinQ QL45211H 25GbE Adapter) + +pci:v00001077d00001656sv00001077sd0000E4F7* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (FastLinQ QL45212H 25GbE Adapter) + +pci:v00001077d00001656sv00001590sd00000245* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 25GbE Controller (10/20/25GbE 2P 4820c CNA) + +pci:v00001077d0000165C* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE) + +pci:v00001077d0000165Csv00001077sd00000034* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE) (QL45262 Flex 50Gb 2-port Ethernet Adapter w/ iSCSI/FCoE) + +pci:v00001077d0000165Csv00001077sd0000E4F1* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE) (FastLinQ QL45462H 40GbE FCoE Adapter) + +pci:v00001077d0000165Csv00001077sd0000E4F2* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE) (FastLinQ QL45461H 40GbE FCoE Adapter) + +pci:v00001077d0000165Csv00001590sd00000245* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE) (10/20/25GbE 2P 4820c CNA FCoE) + +pci:v00001077d0000165E* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI) + +pci:v00001077d0000165Esv00001077sd00000034* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI) (QL45262 Flex 50Gb 2-port Ethernet Adapter w/ iSCSI/FCoE) + +pci:v00001077d0000165Esv00001077sd0000E4F1* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI) (FastLinQ QL45462H 40GbE iSCSI Adapter) + +pci:v00001077d0000165Esv00001077sd0000E4F2* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI) (FastLinQ QL45461H 40GbE iSCSI Adapter) + +pci:v00001077d0000165Esv00001590sd00000245* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI) (10/20/25GbE 2P 4820c CNA iSCSI) + +pci:v00001077d00001664* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) + +pci:v00001077d00001664sv00001077sd0000E4F1* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45462H 40GbE Adapter (SR-IOV VF)) + +pci:v00001077d00001664sv00001077sd0000E4F2* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45461H 40GbE Adapter (SR-IOV VF)) + +pci:v00001077d00001664sv00001077sd0000E4F3* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45412H 40GbE Adapter (SR-IOV VF)) + +pci:v00001077d00001664sv00001077sd0000E4F4* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45411H 40GbE Adapter (SR-IOV VF)) + +pci:v00001077d00001664sv00001077sd0000E4F6* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45211H 25GbE Adapter (SR-IOV VF)) + +pci:v00001077d00001664sv00001077sd0000E4F7* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45212H 25GbE Adapter (SR-IOV VF)) + +pci:v00001077d00001664sv00001077sd0000E4F8* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL45611H 100GbE Adapter (SR-IOV VF)) + +pci:v00001077d00001664sv00001590sd00000245* + ID_MODEL_FROM_DATABASE=FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) (10/20/25GbE 2P 4820c CNA SRIOV) + +pci:v00001077d00002020* + ID_MODEL_FROM_DATABASE=ISP2020A Fast!SCSI Basic Adapter + +pci:v00001077d00002031* + ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter + +pci:v00001077d00002031sv0000103Csd000017E7* + ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (SN1000Q 16Gb Single Port Fibre Channel Adapter) + +pci:v00001077d00002031sv0000103Csd000017E8* + ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (SN1000Q 16Gb Dual Port Fibre Channel Adapter) + +pci:v00001077d00002031sv0000103Csd00001939* + ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (QMH2672 16Gb Dual Port Fibre Channel Adapter) + +pci:v00001077d00002031sv0000103Csd00008002* + ID_MODEL_FROM_DATABASE=ISP8324-based 16Gb Fibre Channel to PCI Express Adapter (3830C 16G Fibre Channel Host Bus Adapter) + +pci:v00001077d00002071* + ID_MODEL_FROM_DATABASE=ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter + +pci:v00001077d00002071sv00001077sd00000283* + ID_MODEL_FROM_DATABASE=ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2764 Quad Port 32Gb Fibre Channel to PCIe Adapter) + +pci:v00001077d00002071sv00001077sd0000029E* + ID_MODEL_FROM_DATABASE=ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2694 Quad Port 16Gb Fibre Channel to PCIe Adapter) + +pci:v00001077d00002071sv00001077sd000002A2* + ID_MODEL_FROM_DATABASE=ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2694L Quad Port 16Gb Fibre Channel to PCIe Adapter) + +pci:v00001077d00002071sv00001077sd000002AD* + ID_MODEL_FROM_DATABASE=ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2694U Quad Port 16/32Gb Fibre Channel to PCIe Adapter) + +pci:v00001077d00002081* + ID_MODEL_FROM_DATABASE=ISP2814-based 64/32G Fibre Channel to PCIe Controller + +pci:v00001077d00002081sv00001077sd000002E1* + ID_MODEL_FROM_DATABASE=ISP2814-based 64/32G Fibre Channel to PCIe Controller (QLE2874 Quad Port 64GFC PCIe Gen4 x16 Adapter) + +pci:v00001077d00002081sv00001077sd000002E3* + ID_MODEL_FROM_DATABASE=ISP2814-based 64/32G Fibre Channel to PCIe Controller (QLE2774 Quad Port 32GFC PCIe Gen4 x16 Adapter) + +pci:v00001077d00002100* + ID_MODEL_FROM_DATABASE=QLA2100 64-bit Fibre Channel Adapter + +pci:v00001077d00002100sv00001077sd00000001* + ID_MODEL_FROM_DATABASE=QLA2100 64-bit Fibre Channel Adapter + +pci:v00001077d00002200* + ID_MODEL_FROM_DATABASE=QLA2200 64-bit Fibre Channel Adapter + +pci:v00001077d00002200sv00001077sd00000002* + ID_MODEL_FROM_DATABASE=QLA2200 64-bit Fibre Channel Adapter (QLA2200) + +pci:v00001077d00002261* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter + +pci:v00001077d00002261sv00001077sd00000299* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2740 Single Port 32Gb Fibre Channel to PCIe Adapter) + +pci:v00001077d00002261sv00001077sd0000029A* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2742 Dual Port 32Gb Fibre Channel to PCIe Adapter) + +pci:v00001077d00002261sv00001077sd0000029B* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2690 Single Port 16Gb Fibre Channel to PCIe Adapter) + +pci:v00001077d00002261sv00001077sd0000029C* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2692 Dual Port 16Gb Fibre Channel to PCIe Adapter) + +pci:v00001077d00002261sv00001077sd000002A7* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2690 Single Port 16Gb FC to PCIe Gen3 x8 Adapter) + +pci:v00001077d00002261sv00001077sd000002A8* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2692 Dual Port 16Gb FC to PCIe Gen3 x8 Adapter) + +pci:v00001077d00002261sv00001077sd000002AB* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2740 Single Port 32Gb FC to PCIe Gen3 x8 Adapter) + +pci:v00001077d00002261sv00001077sd000002AC* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (QLE2742 Dual Port 32Gb FC to PCIe Gen3 x8 Adapter) + +pci:v00001077d00002261sv00001077sd000002B8* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (2x16Gb QME2692 FC HBA) + +pci:v00001077d00002261sv00001077sd000002B9* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (2x32Gb QME2742 FC HBA) + +pci:v00001077d00002261sv00001590sd000000F9* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (StoreFabric SN1100Q 16Gb Single Port Fibre Channel Host Bus Adapter) + +pci:v00001077d00002261sv00001590sd000000FA* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (StoreFabric SN1100Q 16Gb Dual Port Fibre Channel Host Bus Adapter) + +pci:v00001077d00002261sv00001590sd00000203* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (StoreFabric SN1600Q 32Gb Single Port Fibre Channel Host Bus Adapter) + +pci:v00001077d00002261sv00001590sd00000204* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (StoreFabric SN1600Q 32Gb Dual Port Fibre Channel Host Bus Adapter) + +pci:v00001077d00002261sv00001590sd0000022D* + ID_MODEL_FROM_DATABASE=ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter (5830C 32Gb Dual Port Fibre Channel Adapter) + +pci:v00001077d00002281* + ID_MODEL_FROM_DATABASE=ISP2812-based 64/32G Fibre Channel to PCIe Controller + +pci:v00001077d00002281sv00001077sd000002E2* + ID_MODEL_FROM_DATABASE=ISP2812-based 64/32G Fibre Channel to PCIe Controller (QLE2872 Dual Port 64GFC PCIe Gen4 x8 Adapter) + +pci:v00001077d00002281sv00001077sd000002E4* + ID_MODEL_FROM_DATABASE=ISP2812-based 64/32G Fibre Channel to PCIe Controller (QLE2772 Dual Port 32GFC PCIe Gen4 x8 Adapter) + +pci:v00001077d00002281sv00001077sd000002EE* + ID_MODEL_FROM_DATABASE=ISP2812-based 64/32G Fibre Channel to PCIe Controller (QLE2870 Single Port 64GFC PCIe Gen4 x8 Adapter) + +pci:v00001077d00002281sv00001077sd000002F0* + ID_MODEL_FROM_DATABASE=ISP2812-based 64/32G Fibre Channel to PCIe Controller (QLE2770 Single Port 32GFC PCIe Gen4 x8 Adapter) + +pci:v00001077d00002281sv00001590sd000002D3* + ID_MODEL_FROM_DATABASE=ISP2812-based 64/32G Fibre Channel to PCIe Controller (SN1610Q - 1P Enhanced 32GFC Single Port Fibre Channel Host Bus Adapter) + +pci:v00001077d00002281sv00001590sd000002D4* + ID_MODEL_FROM_DATABASE=ISP2812-based 64/32G Fibre Channel to PCIe Controller (SN1610Q – 2P Enhanced 32GFC Dual Port Fibre Channel Host Bus Adapter) + +pci:v00001077d00002300* + ID_MODEL_FROM_DATABASE=QLA2300 64-bit Fibre Channel Adapter + +pci:v00001077d00002312* + ID_MODEL_FROM_DATABASE=ISP2312-based 2Gb Fibre Channel to PCI-X HBA + +pci:v00001077d00002312sv0000103Csd00000131* + ID_MODEL_FROM_DATABASE=ISP2312-based 2Gb Fibre Channel to PCI-X HBA (2Gb Fibre Channel - Single port [A7538A]) + +pci:v00001077d00002312sv0000103Csd000012BA* + ID_MODEL_FROM_DATABASE=ISP2312-based 2Gb Fibre Channel to PCI-X HBA (2Gb Fibre Channel - Dual port [A6826A]) + +pci:v00001077d00002322* + ID_MODEL_FROM_DATABASE=ISP2322-based 2Gb Fibre Channel to PCI-X HBA + +pci:v00001077d00002422* + ID_MODEL_FROM_DATABASE=ISP2422-based 4Gb Fibre Channel to PCI-X HBA + +pci:v00001077d00002422sv0000103Csd000012D7* + ID_MODEL_FROM_DATABASE=ISP2422-based 4Gb Fibre Channel to PCI-X HBA (4Gb Fibre Channel [AB379A]) + +pci:v00001077d00002422sv0000103Csd000012DD* + ID_MODEL_FROM_DATABASE=ISP2422-based 4Gb Fibre Channel to PCI-X HBA (4Gb Fibre Channel [AB429A]) + +pci:v00001077d00002432* + ID_MODEL_FROM_DATABASE=ISP2432-based 4Gb Fibre Channel to PCI Express HBA + +pci:v00001077d00002432sv0000103Csd00007040* + ID_MODEL_FROM_DATABASE=ISP2432-based 4Gb Fibre Channel to PCI Express HBA (FC1142SR 4Gb 1-port PCIe Fibre Channel Host Bus Adapter [HPAE311A]) + +pci:v00001077d00002432sv00001077sd00000137* + ID_MODEL_FROM_DATABASE=ISP2432-based 4Gb Fibre Channel to PCI Express HBA (QLE2460 4 GB PCI-X Host-Bus-Adapter) + +pci:v00001077d00002532* + ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA + +pci:v00001077d00002532sv00001014sd0000041E* + ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (FC EN0Y/EN12 PCIe2 LP 8 Gb 4-port Fibre Channel Adapter for POWER) + +pci:v00001077d00002532sv0000103Csd00003262* + ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (StorageWorks 81Q) + +pci:v00001077d00002532sv0000103Csd00003263* + ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (StorageWorks 82Q) + +pci:v00001077d00002532sv00001077sd0000015C* + ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (QLE2560 PCI Express to 8Gb FC Single Channel) + +pci:v00001077d00002532sv00001077sd0000015D* + ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (QLE2562 PCI Express to 8Gb FC Dual Channel) + +pci:v00001077d00002532sv00001077sd0000015E* + ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (QLE2564 PCI Express to 8Gb FC Quad Channel) + +pci:v00001077d00002532sv00001077sd00000167* + ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (QME2572 Dual Port FC8 HBA Mezzanine) + +pci:v00001077d00002532sv00001590sd000000FC* + ID_MODEL_FROM_DATABASE=ISP2532-based 8Gb Fibre Channel to PCI Express HBA (StoreFabric 84Q 8Gb Quad Port Fibre Channel Host Bus Adapter) + +pci:v00001077d00002971* + ID_MODEL_FROM_DATABASE=ISP2684 + +pci:v00001077d00003022* + ID_MODEL_FROM_DATABASE=ISP4022-based Ethernet NIC + +pci:v00001077d00003032* + ID_MODEL_FROM_DATABASE=ISP4032-based Ethernet IPv6 NIC + +pci:v00001077d00004010* + ID_MODEL_FROM_DATABASE=ISP4010-based iSCSI TOE HBA + +pci:v00001077d00004022* + ID_MODEL_FROM_DATABASE=ISP4022-based iSCSI TOE HBA + +pci:v00001077d00004032* + ID_MODEL_FROM_DATABASE=ISP4032-based iSCSI TOE IPv6 HBA + +pci:v00001077d00005432* + ID_MODEL_FROM_DATABASE=SP232-based 4Gb Fibre Channel to PCI Express HBA + +pci:v00001077d00006312* + ID_MODEL_FROM_DATABASE=SP202-based 2Gb Fibre Channel to PCI-X HBA + +pci:v00001077d00006322* + ID_MODEL_FROM_DATABASE=SP212-based 2Gb Fibre Channel to PCI-X HBA + +pci:v00001077d00007220* + ID_MODEL_FROM_DATABASE=IBA7220 InfiniBand HCA + +pci:v00001077d00007322* + ID_MODEL_FROM_DATABASE=IBA7322 QDR InfiniBand HCA + +pci:v00001077d00008000* + ID_MODEL_FROM_DATABASE=10GbE Converged Network Adapter (TCP/IP Networking) + +pci:v00001077d00008001* + ID_MODEL_FROM_DATABASE=10GbE Converged Network Adapter (FCoE) + +pci:v00001077d00008001sv00001014sd000003AF* + ID_MODEL_FROM_DATABASE=10GbE Converged Network Adapter (FCoE) (FC 5708/5270 10 Gb FCoE PCIe Dual Port Adapter for POWER) + +pci:v00001077d00008020* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller + +pci:v00001077d00008020sv00001028sd00001F64* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (QMD8262-k 10G DP bNDC KR) + +pci:v00001077d00008020sv0000103Csd00003346* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (CN1000Q Dual Port Converged Network Adapter) + +pci:v00001077d00008020sv0000103Csd00003733* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (NC523SFP 10Gb 2-port Server Adapter) + +pci:v00001077d00008020sv00001077sd00000203* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (8200 Series Single Port 10GbE Converged Network Adapter (TCP/IP Networking)) + +pci:v00001077d00008020sv00001077sd00000207* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (8200 Series Dual Port 10GbE Converged Network Adapter (TCP/IP Networking)) + +pci:v00001077d00008020sv00001077sd0000020B* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (3200 Series Dual Port 10Gb Intelligent Ethernet Adapter) + +pci:v00001077d00008020sv00001077sd0000020C* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (3200 Series Quad Port 1Gb Intelligent Ethernet Adapter) + +pci:v00001077d00008020sv00001077sd0000020F* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (3200 Series Single Port 10Gb Intelligent Ethernet Adapter) + +pci:v00001077d00008020sv00001077sd00000210* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (QME8242-k 10GbE Dual Port Mezzanine Card) + +pci:v00001077d00008020sv00001077sd00000233* + ID_MODEL_FROM_DATABASE=cLOM8214 1/10GbE Controller (QME8262-k 10GbE Dual Port Mezzanine Card) + +pci:v00001077d00008021* + ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (FCoE) + +pci:v00001077d00008021sv0000103Csd00003348* + ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (FCoE) (CN1000Q Dual Port Converged Network Adapter) + +pci:v00001077d00008021sv00001077sd00000211* + ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (FCoE) (QME8242-k 10GbE Dual Port Mezzanine Card, FCoE) + +pci:v00001077d00008022* + ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (iSCSI) + +pci:v00001077d00008022sv0000103Csd00003347* + ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (iSCSI) (CN1000Q Dual Port Converged Network Adapter) + +pci:v00001077d00008022sv00001077sd00000212* + ID_MODEL_FROM_DATABASE=8200 Series 10GbE Converged Network Adapter (iSCSI) (QME8242-k 10GbE Dual Port Mezzanine Card, iSCSI) + +pci:v00001077d00008030* + ID_MODEL_FROM_DATABASE=ISP8324 1/10GbE Converged Network Controller + +pci:v00001077d00008030sv00001077sd00000243* + ID_MODEL_FROM_DATABASE=ISP8324 1/10GbE Converged Network Controller (8300 Series Single Port 10GbE Converged Network Adapter (TCP/IP Networking)) + +pci:v00001077d00008030sv00001077sd00000246* + ID_MODEL_FROM_DATABASE=ISP8324 1/10GbE Converged Network Controller (8300 Series Dual Port 10GbE Converged Network Adapter (TCP/IP Networking)) + +pci:v00001077d00008031* + ID_MODEL_FROM_DATABASE=8300 Series 10GbE Converged Network Adapter (FCoE) + +pci:v00001077d00008032* + ID_MODEL_FROM_DATABASE=8300 Series 10GbE Converged Network Adapter (iSCSI) + +pci:v00001077d00008070* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller + +pci:v00001077d00008070sv00001077sd00000001* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GE 2P QL41162HxRJ-DE Adapter) + +pci:v00001077d00008070sv00001077sd00000002* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GE 2P QL41112HxCU-DE Adapter) + +pci:v00001077d00008070sv00001077sd00000004* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (4x10GE QL41164HFCU CNA) + +pci:v00001077d00008070sv00001077sd00000005* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QLogic 4x10GE QL41164HMRJ CNA) + +pci:v00001077d00008070sv00001077sd00000006* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QLogic 4x10GE QL41164HMCU CNA) + +pci:v00001077d00008070sv00001077sd00000007* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QLogic 2x1GE+2x10GE QL41264HMCU CNA) + +pci:v00001077d00008070sv00001077sd00000009* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QLogic 2x1GE+2x10GE QL41162HMRJ CNA) + +pci:v00001077d00008070sv00001077sd0000000B* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (25GE 2P QL41262HxCU-DE Adapter) + +pci:v00001077d00008070sv00001077sd0000000F* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (2x25GE QL41262HMKR CNA) + +pci:v00001077d00008070sv00001077sd00000010* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (2x25GE QL41232HMKR NIC) + +pci:v00001077d00008070sv00001077sd00000011* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FastLinQ QL41212HLCU 25GbE Adapter) + +pci:v00001077d00008070sv00001077sd00000012* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FastLinQ QL41112H 10GbE Adapter) + +pci:v00001077d00008070sv00001077sd00000019* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QL41232HOCU - Dual Port 25/10GbE SFP28 OCP Adapter) + +pci:v00001077d00008070sv00001077sd00000039* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QLogic QL41262 PCIe 25Gb 2-Port SFP28 Ethernet Adapter) + +pci:v00001077d00008070sv00001077sd00000053* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QLogic 2x25GE QL41232HQCU NIC) + +pci:v00001077d00008070sv00001077sd00000054* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (2x10GE QL41132HQRJ NIC) + +pci:v00001077d00008070sv00001077sd00000055* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (QLogic 2x10GE QL41132HQCU NIC) + +pci:v00001077d00008070sv00001077sd00000056* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (2x10GE QL41132HxRJ NIC) + +pci:v00001077d00008070sv00001077sd00000057* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (2x25GE QL41232HxCU NIC) + +pci:v00001077d00008070sv00001077sd00000068* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GbE 2p SFP+ QL41132HLCU-HC Adapter) + +pci:v00001077d00008070sv00001077sd00000069* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GbE 2p BASE-T QL41132HQRJ-HC OCP3 Adapter) + +pci:v00001077d00008070sv00001077sd00000070* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GbE 2p BASE-T QL41132HLRJ-HC Adapter) + +pci:v00001077d00008070sv00001077sd00000071* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GbE 2p SFP+ QL41132HQCU-HC OCP3 Adapter) + +pci:v00001077d00008070sv00001077sd00000072* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GbE 4p SFP+ QL41134HLCU-HC Adapter) + +pci:v00001077d00008070sv00001077sd00000073* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10/25GbE 2p SFP28 QL41232HQCU-HC OCP3 Adapter) + +pci:v00001077d00008070sv00001077sd00000074* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10/25GbE 2p SFP28 QL41232HLCU-HC Adapter) + +pci:v00001077d00008070sv00001590sd0000021A* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GbE 2P QL41162HLRJ-HP Adapter) + +pci:v00001077d00008070sv00001590sd0000021B* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10GbE 2P QL41162HLRJ-HP Adapter) + +pci:v00001077d00008070sv00001590sd0000021D* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10/25GbE 2P QL41222HLCU-HP Adapter) + +pci:v00001077d00008070sv00001590sd0000021E* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10/25GbE 2P QL41162HMRJ-HP Adapter) + +pci:v00001077d00008070sv00001590sd0000021F* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10/25GbE 2P QL41262HMCU-HP Adapter) + +pci:v00001077d00008070sv00001590sd00000220* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10/25GbE 2P QL41122HLRJ-HP Adapter) + +pci:v00001077d00008070sv00001590sd000002BD* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (10Gb 2P 524SFP+ NIC) + +pci:v00001077d00008080* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) + +pci:v00001077d00008080sv00001077sd00000001* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (10GE 2P QL41162HxRJ-DE Adapter) + +pci:v00001077d00008080sv00001077sd00000002* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (10GE 2P QL41112HxCU-DE Adapter) + +pci:v00001077d00008080sv00001077sd00000004* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (4x10GE QL41164HFCU CNA) + +pci:v00001077d00008080sv00001077sd00000005* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (QLogic 4x10GE QL41164HMRJ CNA) + +pci:v00001077d00008080sv00001077sd00000006* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (QLogic 4x10GE QL41164HMCU CNA) + +pci:v00001077d00008080sv00001077sd00000007* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (QLogic 2x1GE+2x10GE QL41264HMCU CNA) + +pci:v00001077d00008080sv00001077sd00000009* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (QLogic 2x1GE+2x10GE QL41162HMRJ CNA) + +pci:v00001077d00008080sv00001077sd0000000B* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (25GE 2P QL41262HxCU-DE Adapter) + +pci:v00001077d00008080sv00001077sd0000000C* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (QLogic 2x25GE QL41262HMCU CNA) + +pci:v00001077d00008080sv00001077sd0000000D* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (FastLinQ QL41262H 25GbE FCoE Adapter) + +pci:v00001077d00008080sv00001077sd0000000E* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (FastLinQ QL41162H 10GbE FCoE Adapter) + +pci:v00001077d00008080sv00001077sd0000000F* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (2x25GE QL41262HMKR CNA) + +pci:v00001077d00008080sv00001590sd0000021A* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (10GbE 2P QL41162HLRJ-HP Adapter) + +pci:v00001077d00008080sv00001590sd0000021B* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) (10GbE 2P QL41162HLRJ-HP Adapter) + +pci:v00001077d00008084* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) + +pci:v00001077d00008084sv00001077sd00000001* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (10GE 2P QL41162HxRJ-DE Adapter) + +pci:v00001077d00008084sv00001077sd00000002* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (10GE 2P QL41112HxCU-DE Adapter) + +pci:v00001077d00008084sv00001077sd00000003* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (4x10GE QL41164HxRJ CNA) + +pci:v00001077d00008084sv00001077sd00000004* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (4x10GE QL41164HFCU CNA) + +pci:v00001077d00008084sv00001077sd00000005* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (QLogic 4x10GE QL41164HMRJ CNA) + +pci:v00001077d00008084sv00001077sd00000006* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (QLogic 4x10GE QL41164HMCU CNA) + +pci:v00001077d00008084sv00001077sd00000007* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (QLogic 2x25GE QL41262HMCU CNA) + +pci:v00001077d00008084sv00001077sd00000009* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (QLogic 2x1GE+2x10GE QL41162HMRJ CNA) + +pci:v00001077d00008084sv00001077sd0000000B* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (25GE 2P QL41262HxCU-DE Adapter) + +pci:v00001077d00008084sv00001077sd0000000C* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (QLogic 2x25GE QL41262HMCU CNA) + +pci:v00001077d00008084sv00001077sd0000000D* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (FastLinQ QL41262H 25GbE iSCSI Adapter) + +pci:v00001077d00008084sv00001077sd0000000E* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (FastLinQ QL41162H 10GbE iSCSI Adapter) + +pci:v00001077d00008084sv00001077sd0000000F* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (2x25GE QL41262HMKR CNA) + +pci:v00001077d00008084sv00001590sd0000021A* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (10GbE 2P QL41162HLRJ-HP Adapter) + +pci:v00001077d00008084sv00001590sd0000021B* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) (10GbE 2P QL41162HLRJ-HP Adapter) + +pci:v00001077d00008090* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) + +pci:v00001077d00008090sv00001077sd00000001* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (25GE 2P QL41262HxCU-DE Adapter) + +pci:v00001077d00008090sv00001077sd00000002* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (10GE 2P QL41112HxCU-DE Adapter) + +pci:v00001077d00008090sv00001077sd00000003* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (4x10GE QL41164HxRJ CNA) + +pci:v00001077d00008090sv00001077sd00000004* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (4x10GE QL41164HFCU CNA) + +pci:v00001077d00008090sv00001077sd00000005* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (QLogic 4x10GE QL41164HMRJ CNA) + +pci:v00001077d00008090sv00001077sd00000006* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (QLogic 4x10GE QL41164HMCU CNA) + +pci:v00001077d00008090sv00001077sd00000007* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (QLogic 2x1GE+2x10GE QL41264HMCU CNA) + +pci:v00001077d00008090sv00001077sd00000009* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (QLogic 2x1GE+2x10GE QL41162HMRJ CNA) + +pci:v00001077d00008090sv00001077sd0000000B* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (25GE 2P QL41262HxCU-DE Adapter) + +pci:v00001077d00008090sv00001077sd0000000C* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (QLogic 2x25GE QL41262HMCU CNA) + +pci:v00001077d00008090sv00001077sd0000000D* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL41262H 25GbE FCoE Adapter (SR-IOV VF)) + +pci:v00001077d00008090sv00001077sd0000000E* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL41162H 10GbE iSCSI Adapter (SR-IOV VF)) + +pci:v00001077d00008090sv00001077sd0000000F* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (2x25GE QL41262HMKR CNA) + +pci:v00001077d00008090sv00001077sd00000010* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (2x25GE QL41232HMKR NIC) + +pci:v00001077d00008090sv00001077sd00000011* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL41212H 25GbE Adapter (SR-IOV VF)) + +pci:v00001077d00008090sv00001077sd00000012* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (FastLinQ QL41112H 10GbE Adapter (SR-IOV VF)) + +pci:v00001077d00008090sv00001077sd00000053* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (QLogic 2x25GE QL41232HQCU NIC) + +pci:v00001077d00008090sv00001077sd00000054* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (QLogic 2x10GE QL41132HQRJ NIC) + +pci:v00001077d00008090sv00001077sd00000055* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (QLogic 2x10GE QL41132HQCU NIC) + +pci:v00001077d00008090sv00001077sd00000056* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (2x10GE QL41132HxRJ NIC) + +pci:v00001077d00008090sv00001077sd00000057* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (2x25GE QL41232HxCU NIC) + +pci:v00001077d00008090sv00001590sd0000021A* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (10GbE 2P QL41162HLRJ-HP Adapter) + +pci:v00001077d00008090sv00001590sd0000021B* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (10GbE 2P QL41162HLRJ-HP Adapter) + +pci:v00001077d00008090sv00001590sd0000021E* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (10/25GbE 2P QL41162HMRJ-HP Adapter) + +pci:v00001077d00008090sv00001590sd0000021F* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (10/25GbE 2P QL41262HMCU-HP Adapter) + +pci:v00001077d00008090sv00001590sd000002BD* + ID_MODEL_FROM_DATABASE=FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) (10Gb 2P 524SFP+ NIC) + +pci:v00001077d00008430* + ID_MODEL_FROM_DATABASE=ISP8324 1/10GbE Converged Network Controller (NIC VF) + +pci:v00001077d00008431* + ID_MODEL_FROM_DATABASE=8300 Series 10GbE Converged Network Adapter (FCoE VF) + +pci:v00001077d00008432* + ID_MODEL_FROM_DATABASE=ISP2432M-based 10GbE Converged Network Adapter (CNA) + +pci:v00001078* + ID_VENDOR_FROM_DATABASE=Cyrix Corporation + +pci:v00001078d00000000* + ID_MODEL_FROM_DATABASE=5510 [Grappa] + +pci:v00001078d00000001* + ID_MODEL_FROM_DATABASE=PCI Master + +pci:v00001078d00000002* + ID_MODEL_FROM_DATABASE=5520 [Cognac] + +pci:v00001078d00000100* + ID_MODEL_FROM_DATABASE=5530 Legacy [Kahlua] + +pci:v00001078d00000101* + ID_MODEL_FROM_DATABASE=5530 SMI [Kahlua] + +pci:v00001078d00000102* + ID_MODEL_FROM_DATABASE=5530 IDE [Kahlua] + +pci:v00001078d00000103* + ID_MODEL_FROM_DATABASE=5530 Audio [Kahlua] + +pci:v00001078d00000104* + ID_MODEL_FROM_DATABASE=5530 Video [Kahlua] + +pci:v00001078d00000400* + ID_MODEL_FROM_DATABASE=ZFMicro PCI Bridge + +pci:v00001078d00000401* + ID_MODEL_FROM_DATABASE=ZFMicro Chipset SMI + +pci:v00001078d00000402* + ID_MODEL_FROM_DATABASE=ZFMicro Chipset IDE + +pci:v00001078d00000403* + ID_MODEL_FROM_DATABASE=ZFMicro Expansion Bus + +pci:v00001079* + ID_VENDOR_FROM_DATABASE=I-Bus + +pci:v0000107A* + ID_VENDOR_FROM_DATABASE=NetWorth + +pci:v0000107B* + ID_VENDOR_FROM_DATABASE=Gateway, Inc. + +pci:v0000107C* + ID_VENDOR_FROM_DATABASE=LG Electronics [Lucky Goldstar Co. Ltd] + +pci:v0000107D* + ID_VENDOR_FROM_DATABASE=LeadTek Research Inc. + +pci:v0000107Dd00000000* + ID_MODEL_FROM_DATABASE=P86C850 + +pci:v0000107E* + ID_VENDOR_FROM_DATABASE=Interphase Corporation + +pci:v0000107Ed00000001* + ID_MODEL_FROM_DATABASE=5515 ATM Adapter [Flipper] + +pci:v0000107Ed00000002* + ID_MODEL_FROM_DATABASE=100 VG AnyLan Controller + +pci:v0000107Ed00000004* + ID_MODEL_FROM_DATABASE=5526 Fibre Channel Host Adapter + +pci:v0000107Ed00000005* + ID_MODEL_FROM_DATABASE=x526 Fibre Channel Host Adapter + +pci:v0000107Ed00000008* + ID_MODEL_FROM_DATABASE=5525/5575 ATM Adapter (155 Mbit) [Atlantic] + +pci:v0000107Ed00009003* + ID_MODEL_FROM_DATABASE=5535-4P-BRI-ST + +pci:v0000107Ed00009007* + ID_MODEL_FROM_DATABASE=5535-4P-BRI-U + +pci:v0000107Ed00009008* + ID_MODEL_FROM_DATABASE=5535-1P-SR + +pci:v0000107Ed0000900C* + ID_MODEL_FROM_DATABASE=5535-1P-SR-ST + +pci:v0000107Ed0000900E* + ID_MODEL_FROM_DATABASE=5535-1P-SR-U + +pci:v0000107Ed00009011* + ID_MODEL_FROM_DATABASE=5535-1P-PRI + +pci:v0000107Ed00009013* + ID_MODEL_FROM_DATABASE=5535-2P-PRI + +pci:v0000107Ed00009023* + ID_MODEL_FROM_DATABASE=5536-4P-BRI-ST + +pci:v0000107Ed00009027* + ID_MODEL_FROM_DATABASE=5536-4P-BRI-U + +pci:v0000107Ed00009031* + ID_MODEL_FROM_DATABASE=5536-1P-PRI + +pci:v0000107Ed00009033* + ID_MODEL_FROM_DATABASE=5536-2P-PRI + +pci:v0000107F* + ID_VENDOR_FROM_DATABASE=Data Technology Corporation + +pci:v0000107Fd00000802* + ID_MODEL_FROM_DATABASE=SL82C105 + +pci:v00001080* + ID_VENDOR_FROM_DATABASE=Contaq Microsystems + +pci:v00001080d00000600* + ID_MODEL_FROM_DATABASE=82C599 + +pci:v00001080d0000C691* + ID_MODEL_FROM_DATABASE=Cypress CY82C691 + +pci:v00001080d0000C693* + ID_MODEL_FROM_DATABASE=82c693 + +pci:v00001081* + ID_VENDOR_FROM_DATABASE=Supermac Technology + +pci:v00001081d00000D47* + ID_MODEL_FROM_DATABASE=Radius PCI to NuBUS Bridge + +pci:v00001082* + ID_VENDOR_FROM_DATABASE=EFA Corporation of America + +pci:v00001083* + ID_VENDOR_FROM_DATABASE=Forex Computer Corporation + +pci:v00001083d00000001* + ID_MODEL_FROM_DATABASE=FR710 + +pci:v00001084* + ID_VENDOR_FROM_DATABASE=Parador + +pci:v00001086* + ID_VENDOR_FROM_DATABASE=J. Bond Computer Systems + +pci:v00001087* + ID_VENDOR_FROM_DATABASE=Cache Computer + +pci:v00001088* + ID_VENDOR_FROM_DATABASE=Microcomputer Systems (M) Son + +pci:v00001089* + ID_VENDOR_FROM_DATABASE=Data General Corporation + +pci:v0000108A* + ID_VENDOR_FROM_DATABASE=SBS Technologies + +pci:v0000108Ad00000001* + ID_MODEL_FROM_DATABASE=VME Bridge Model 617 + +pci:v0000108Ad00000010* + ID_MODEL_FROM_DATABASE=VME Bridge Model 618 + +pci:v0000108Ad00000040* + ID_MODEL_FROM_DATABASE=dataBLIZZARD + +pci:v0000108Ad00003000* + ID_MODEL_FROM_DATABASE=VME Bridge Model 2706 + +pci:v0000108C* + ID_VENDOR_FROM_DATABASE=Oakleigh Systems Inc. + +pci:v0000108D* + ID_VENDOR_FROM_DATABASE=Olicom + +pci:v0000108Dd00000001* + ID_MODEL_FROM_DATABASE=Token-Ring 16/4 PCI Adapter (3136/3137) + +pci:v0000108Dd00000002* + ID_MODEL_FROM_DATABASE=16/4 Token Ring + +pci:v0000108Dd00000004* + ID_MODEL_FROM_DATABASE=RapidFire OC-3139/3140 Token-Ring 16/4 PCI Adapter + +pci:v0000108Dd00000004sv0000108Dsd00000004* + ID_MODEL_FROM_DATABASE=RapidFire OC-3139/3140 Token-Ring 16/4 PCI Adapter (OC-3139/3140 RapidFire Token-Ring 16/4 Adapter) + +pci:v0000108Dd00000005* + ID_MODEL_FROM_DATABASE=GoCard 3250 Token-Ring 16/4 CardBus PC Card + +pci:v0000108Dd00000006* + ID_MODEL_FROM_DATABASE=OC-3530 RapidFire Token-Ring 100 + +pci:v0000108Dd00000007* + ID_MODEL_FROM_DATABASE=RapidFire 3141 Token-Ring 16/4 PCI Fiber Adapter + +pci:v0000108Dd00000007sv0000108Dsd00000007* + ID_MODEL_FROM_DATABASE=RapidFire 3141 Token-Ring 16/4 PCI Fiber Adapter (OC-3141 RapidFire Token-Ring 16/4 Adapter) + +pci:v0000108Dd00000008* + ID_MODEL_FROM_DATABASE=RapidFire 3540 HSTR 100/16/4 PCI Adapter + +pci:v0000108Dd00000008sv0000108Dsd00000008* + ID_MODEL_FROM_DATABASE=RapidFire 3540 HSTR 100/16/4 PCI Adapter (OC-3540 RapidFire HSTR 100/16/4 Adapter) + +pci:v0000108Dd00000011* + ID_MODEL_FROM_DATABASE=OC-2315 + +pci:v0000108Dd00000012* + ID_MODEL_FROM_DATABASE=OC-2325 + +pci:v0000108Dd00000013* + ID_MODEL_FROM_DATABASE=OC-2183/2185 + +pci:v0000108Dd00000014* + ID_MODEL_FROM_DATABASE=OC-2326 + +pci:v0000108Dd00000019* + ID_MODEL_FROM_DATABASE=OC-2327/2250 10/100 Ethernet Adapter + +pci:v0000108Dd00000019sv0000108Dsd00000016* + ID_MODEL_FROM_DATABASE=OC-2327/2250 10/100 Ethernet Adapter (OC-2327 Rapidfire 10/100 Ethernet Adapter) + +pci:v0000108Dd00000019sv0000108Dsd00000017* + ID_MODEL_FROM_DATABASE=OC-2327/2250 10/100 Ethernet Adapter (OC-2250 GoCard 10/100 Ethernet Adapter) + +pci:v0000108Dd00000021* + ID_MODEL_FROM_DATABASE=OC-6151/6152 [RapidFire ATM 155] + +pci:v0000108Dd00000022* + ID_MODEL_FROM_DATABASE=ATM Adapter + +pci:v0000108E* + ID_VENDOR_FROM_DATABASE=Oracle/SUN + +pci:v0000108Ed00000001* + ID_MODEL_FROM_DATABASE=EBUS + +pci:v0000108Ed00001000* + ID_MODEL_FROM_DATABASE=EBUS + +pci:v0000108Ed00001001* + ID_MODEL_FROM_DATABASE=Happy Meal 10/100 Ethernet [hme] + +pci:v0000108Ed00001100* + ID_MODEL_FROM_DATABASE=RIO EBUS + +pci:v0000108Ed00001100sv0000108Esd00001100* + ID_MODEL_FROM_DATABASE=RIO EBUS (on Blade 100 motherboard) + +pci:v0000108Ed00001101* + ID_MODEL_FROM_DATABASE=RIO 10/100 Ethernet [eri] + +pci:v0000108Ed00001101sv0000108Esd00001101* + ID_MODEL_FROM_DATABASE=RIO 10/100 Ethernet [eri] (RIO GEM on Blade 100 motherboard) + +pci:v0000108Ed00001102* + ID_MODEL_FROM_DATABASE=RIO 1394 + +pci:v0000108Ed00001102sv0000108Esd00001102* + ID_MODEL_FROM_DATABASE=RIO 1394 (on Blade 100 motherboard) + +pci:v0000108Ed00001103* + ID_MODEL_FROM_DATABASE=RIO USB + +pci:v0000108Ed00001103sv0000108Esd00001103* + ID_MODEL_FROM_DATABASE=RIO USB (on Blade 100 motherboard) + +pci:v0000108Ed00001647* + ID_MODEL_FROM_DATABASE=Broadcom 570x 10/100/1000 Ethernet [bge] + +pci:v0000108Ed00001648* + ID_MODEL_FROM_DATABASE=Broadcom 570x 10/100/1000 Ethernet [bge] + +pci:v0000108Ed000016A7* + ID_MODEL_FROM_DATABASE=Broadcom 570x 10/100/1000 Ethernet [bge] + +pci:v0000108Ed000016A8* + ID_MODEL_FROM_DATABASE=Broadcom 570x 10/100/1000 Ethernet [bge] + +pci:v0000108Ed00002BAD* + ID_MODEL_FROM_DATABASE=GEM 10/100/1000 Ethernet [ge] + +pci:v0000108Ed00005000* + ID_MODEL_FROM_DATABASE=Simba Advanced PCI Bridge + +pci:v0000108Ed00005000sv0000108Esd00005000* + ID_MODEL_FROM_DATABASE=Simba Advanced PCI Bridge (Netra AX1105-500) + +pci:v0000108Ed00005043* + ID_MODEL_FROM_DATABASE=SunPCI Co-processor + +pci:v0000108Ed00005CA0* + ID_MODEL_FROM_DATABASE=Crypto Accelerator 6000 [mca] + +pci:v0000108Ed00006300* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006301* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006302* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006303* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006310* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006311* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006312* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006313* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006320* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006323* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006330* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006331* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006332* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006333* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006340* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006343* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006350* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006353* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed00006722* + ID_MODEL_FROM_DATABASE=Intel 21554 PCI-PCI bus bridge [db21554] + +pci:v0000108Ed0000676E* + ID_MODEL_FROM_DATABASE=SunPCiIII + +pci:v0000108Ed00007063* + ID_MODEL_FROM_DATABASE=SunPCiII / SunPCiIIpro + +pci:v0000108Ed00008000* + ID_MODEL_FROM_DATABASE=Psycho PCI Bus Module + +pci:v0000108Ed00008001* + ID_MODEL_FROM_DATABASE=Schizo PCI Bus Module + +pci:v0000108Ed00008002* + ID_MODEL_FROM_DATABASE=Schizo+ PCI Bus Module + +pci:v0000108Ed000080F0* + ID_MODEL_FROM_DATABASE=PCIe switch [px] + +pci:v0000108Ed000080F8* + ID_MODEL_FROM_DATABASE=PCIe switch [px] + +pci:v0000108Ed00009010* + ID_MODEL_FROM_DATABASE=PCIe/PCI bridge switch [pxb_plx] + +pci:v0000108Ed00009020* + ID_MODEL_FROM_DATABASE=PCIe/PCI bridge switch [pxb_plx] + +pci:v0000108Ed00009102* + ID_MODEL_FROM_DATABASE=Davicom Fast Ethernet driver for Davicom DM9102A [dmfe] + +pci:v0000108Ed0000A000* + ID_MODEL_FROM_DATABASE=Psycho UPA-PCI Bus Module [pcipsy] + +pci:v0000108Ed0000A001* + ID_MODEL_FROM_DATABASE=Psycho UPA-PCI Bus Module [pcipsy] + +pci:v0000108Ed0000A001sv0000108Esd0000A001* + ID_MODEL_FROM_DATABASE=Psycho UPA-PCI Bus Module [pcipsy] (Ultra IIe on Blade 100 motherboard) + +pci:v0000108Ed0000A801* + ID_MODEL_FROM_DATABASE=Schizo Fireplane-PCI bus bridge module [pcisch] + +pci:v0000108Ed0000AAAA* + ID_MODEL_FROM_DATABASE=Multithreaded Shared 10GbE Ethernet Network Controller + +pci:v0000108Ed0000ABBA* + ID_MODEL_FROM_DATABASE=Cassini 10/100/1000 + +pci:v0000108Ed0000ABCD* + ID_MODEL_FROM_DATABASE=Multithreaded 10-Gigabit Ethernet Network Controller + +pci:v0000108Ed0000C416* + ID_MODEL_FROM_DATABASE=Sun Fire System/System Controller Interface chip [sbbc] + +pci:v0000108F* + ID_VENDOR_FROM_DATABASE=Systemsoft + +pci:v00001090* + ID_VENDOR_FROM_DATABASE=Compro Computer Services, Inc. + +pci:v00001090d00004610* + ID_MODEL_FROM_DATABASE=PCI RTOM + +pci:v00001090d00004620* + ID_MODEL_FROM_DATABASE=GPIO HSD + +pci:v00001091* + ID_VENDOR_FROM_DATABASE=Intergraph Corporation + +pci:v00001091d00000020* + ID_MODEL_FROM_DATABASE=3D graphics processor + +pci:v00001091d00000021* + ID_MODEL_FROM_DATABASE=3D graphics processor w/Texturing + +pci:v00001091d00000040* + ID_MODEL_FROM_DATABASE=3D graphics frame buffer + +pci:v00001091d00000041* + ID_MODEL_FROM_DATABASE=3D graphics frame buffer + +pci:v00001091d00000060* + ID_MODEL_FROM_DATABASE=Proprietary bus bridge + +pci:v00001091d000000E4* + ID_MODEL_FROM_DATABASE=Powerstorm 4D50T + +pci:v00001091d00000720* + ID_MODEL_FROM_DATABASE=Motion JPEG codec + +pci:v00001091d00000780* + ID_MODEL_FROM_DATABASE=Intense3D Wildcat 3410 (MSMT496) + +pci:v00001091d000007A0* + ID_MODEL_FROM_DATABASE=Sun Expert3D-Lite Graphics Accelerator + +pci:v00001091d00001091* + ID_MODEL_FROM_DATABASE=Sun Expert3D Graphics Accelerator + +pci:v00001092* + ID_VENDOR_FROM_DATABASE=Diamond Multimedia Systems + +pci:v00001092d00000028* + ID_MODEL_FROM_DATABASE=Viper V770 + +pci:v00001092d00000028sv00001092sd00004A00* + ID_MODEL_FROM_DATABASE=Viper V770 (32MB) + +pci:v00001092d000000A0* + ID_MODEL_FROM_DATABASE=Speedstar Pro SE + +pci:v00001092d000000A8* + ID_MODEL_FROM_DATABASE=Speedstar 64 + +pci:v00001092d00000550* + ID_MODEL_FROM_DATABASE=Viper V550 + +pci:v00001092d000008D4* + ID_MODEL_FROM_DATABASE=Supra 2260 Modem + +pci:v00001092d0000094C* + ID_MODEL_FROM_DATABASE=SupraExpress 56i Pro + +pci:v00001092d00001001* + ID_MODEL_FROM_DATABASE=Video Crunch It 1001 capture card + +pci:v00001092d00001092* + ID_MODEL_FROM_DATABASE=Viper V330 + +pci:v00001092d00006120* + ID_MODEL_FROM_DATABASE=Maximum DVD + +pci:v00001092d00008810* + ID_MODEL_FROM_DATABASE=Stealth SE + +pci:v00001092d00008811* + ID_MODEL_FROM_DATABASE=Stealth 64/SE + +pci:v00001092d00008880* + ID_MODEL_FROM_DATABASE=Stealth + +pci:v00001092d00008881* + ID_MODEL_FROM_DATABASE=Stealth + +pci:v00001092d000088B0* + ID_MODEL_FROM_DATABASE=Stealth 64 + +pci:v00001092d000088B1* + ID_MODEL_FROM_DATABASE=Stealth 64 + +pci:v00001092d000088C0* + ID_MODEL_FROM_DATABASE=Stealth 64 + +pci:v00001092d000088C1* + ID_MODEL_FROM_DATABASE=Stealth 64 + +pci:v00001092d000088D0* + ID_MODEL_FROM_DATABASE=Stealth 64 + +pci:v00001092d000088D1* + ID_MODEL_FROM_DATABASE=Stealth 64 + +pci:v00001092d000088F0* + ID_MODEL_FROM_DATABASE=Stealth 64 + +pci:v00001092d000088F1* + ID_MODEL_FROM_DATABASE=Stealth 64 + +pci:v00001092d00009999* + ID_MODEL_FROM_DATABASE=DMD-I0928-1 "Monster sound" sound chip + +pci:v00001093* + ID_VENDOR_FROM_DATABASE=National Instruments + +pci:v00001093d00000160* + ID_MODEL_FROM_DATABASE=PCI-DIO-96 + +pci:v00001093d00000162* + ID_MODEL_FROM_DATABASE=PCI-MIO-16XE-50 + +pci:v00001093d00000FE1* + ID_MODEL_FROM_DATABASE=PXI-8320 + +pci:v00001093d00001150* + ID_MODEL_FROM_DATABASE=PCI-6533 (PCI-DIO-32HS) + +pci:v00001093d00001170* + ID_MODEL_FROM_DATABASE=PCI-MIO-16XE-10 + +pci:v00001093d00001180* + ID_MODEL_FROM_DATABASE=PCI-MIO-16E-1 + +pci:v00001093d00001190* + ID_MODEL_FROM_DATABASE=PCI-MIO-16E-4 + +pci:v00001093d000011B0* + ID_MODEL_FROM_DATABASE=PXI-6070E + +pci:v00001093d000011C0* + ID_MODEL_FROM_DATABASE=PXI-6040E + +pci:v00001093d000011D0* + ID_MODEL_FROM_DATABASE=PXI-6030E + +pci:v00001093d00001270* + ID_MODEL_FROM_DATABASE=PCI-6032E + +pci:v00001093d00001290* + ID_MODEL_FROM_DATABASE=PCI-6704 + +pci:v00001093d000012B0* + ID_MODEL_FROM_DATABASE=PCI-6534 + +pci:v00001093d00001310* + ID_MODEL_FROM_DATABASE=PCI-6602 + +pci:v00001093d00001320* + ID_MODEL_FROM_DATABASE=PXI-6533 + +pci:v00001093d00001330* + ID_MODEL_FROM_DATABASE=PCI-6031E + +pci:v00001093d00001340* + ID_MODEL_FROM_DATABASE=PCI-6033E + +pci:v00001093d00001350* + ID_MODEL_FROM_DATABASE=PCI-6071E + +pci:v00001093d00001360* + ID_MODEL_FROM_DATABASE=PXI-6602 + +pci:v00001093d000013C0* + ID_MODEL_FROM_DATABASE=PXI-6508 + +pci:v00001093d00001490* + ID_MODEL_FROM_DATABASE=PXI-6534 + +pci:v00001093d000014E0* + ID_MODEL_FROM_DATABASE=PCI-6110 + +pci:v00001093d000014F0* + ID_MODEL_FROM_DATABASE=PCI-6111 + +pci:v00001093d00001580* + ID_MODEL_FROM_DATABASE=PXI-6031E + +pci:v00001093d000015B0* + ID_MODEL_FROM_DATABASE=PXI-6071E + +pci:v00001093d00001710* + ID_MODEL_FROM_DATABASE=PXI-6509 + +pci:v00001093d000017C0* + ID_MODEL_FROM_DATABASE=PXI-5690 + +pci:v00001093d000017D0* + ID_MODEL_FROM_DATABASE=PCI-6503 + +pci:v00001093d00001870* + ID_MODEL_FROM_DATABASE=PCI-6713 + +pci:v00001093d00001880* + ID_MODEL_FROM_DATABASE=PCI-6711 + +pci:v00001093d000018B0* + ID_MODEL_FROM_DATABASE=PCI-6052E + +pci:v00001093d000018C0* + ID_MODEL_FROM_DATABASE=PXI-6052E + +pci:v00001093d00001920* + ID_MODEL_FROM_DATABASE=PXI-6704 + +pci:v00001093d00001930* + ID_MODEL_FROM_DATABASE=PCI-6040E + +pci:v00001093d000019C0* + ID_MODEL_FROM_DATABASE=PCI-4472 + +pci:v00001093d00001AA0* + ID_MODEL_FROM_DATABASE=PXI-4110 + +pci:v00001093d00001AD0* + ID_MODEL_FROM_DATABASE=PCI-6133 + +pci:v00001093d00001AE0* + ID_MODEL_FROM_DATABASE=PXI-6133 + +pci:v00001093d00001E30* + ID_MODEL_FROM_DATABASE=PCI-6624 + +pci:v00001093d00001E40* + ID_MODEL_FROM_DATABASE=PXI-6624 + +pci:v00001093d00001E50* + ID_MODEL_FROM_DATABASE=PXI-5404 + +pci:v00001093d00002410* + ID_MODEL_FROM_DATABASE=PCI-6733 + +pci:v00001093d00002420* + ID_MODEL_FROM_DATABASE=PXI-6733 + +pci:v00001093d00002430* + ID_MODEL_FROM_DATABASE=PCI-6731 + +pci:v00001093d00002470* + ID_MODEL_FROM_DATABASE=PCI-4474 + +pci:v00001093d000024A0* + ID_MODEL_FROM_DATABASE=PCI-4065 + +pci:v00001093d000024B0* + ID_MODEL_FROM_DATABASE=PXI-4200 + +pci:v00001093d000024F0* + ID_MODEL_FROM_DATABASE=PXI-4472 + +pci:v00001093d00002510* + ID_MODEL_FROM_DATABASE=PCI-4472 + +pci:v00001093d00002520* + ID_MODEL_FROM_DATABASE=PCI-4474 + +pci:v00001093d000027A0* + ID_MODEL_FROM_DATABASE=PCI-6123 + +pci:v00001093d000027B0* + ID_MODEL_FROM_DATABASE=PXI-6123 + +pci:v00001093d00002880* + ID_MODEL_FROM_DATABASE=DAQCard-6601 + +pci:v00001093d00002890* + ID_MODEL_FROM_DATABASE=PCI-6036E + +pci:v00001093d000028A0* + ID_MODEL_FROM_DATABASE=PXI-4461 + +pci:v00001093d000028B0* + ID_MODEL_FROM_DATABASE=PCI-6013 + +pci:v00001093d000028C0* + ID_MODEL_FROM_DATABASE=PCI-6014 + +pci:v00001093d000028D0* + ID_MODEL_FROM_DATABASE=PCI-5122 + +pci:v00001093d000028E0* + ID_MODEL_FROM_DATABASE=PXI-5122 + +pci:v00001093d000029F0* + ID_MODEL_FROM_DATABASE=PXI-7334 + +pci:v00001093d00002A00* + ID_MODEL_FROM_DATABASE=PXI-7344 + +pci:v00001093d00002A60* + ID_MODEL_FROM_DATABASE=PCI-6023E + +pci:v00001093d00002A70* + ID_MODEL_FROM_DATABASE=PCI-6024E + +pci:v00001093d00002A80* + ID_MODEL_FROM_DATABASE=PCI-6025E + +pci:v00001093d00002AB0* + ID_MODEL_FROM_DATABASE=PXI-6025E + +pci:v00001093d00002B10* + ID_MODEL_FROM_DATABASE=PXI-6527 + +pci:v00001093d00002B20* + ID_MODEL_FROM_DATABASE=PCI-6527 + +pci:v00001093d00002B80* + ID_MODEL_FROM_DATABASE=PXI-6713 + +pci:v00001093d00002B90* + ID_MODEL_FROM_DATABASE=PXI-6711 + +pci:v00001093d00002C60* + ID_MODEL_FROM_DATABASE=PCI-6601 + +pci:v00001093d00002C70* + ID_MODEL_FROM_DATABASE=PXI-6601 + +pci:v00001093d00002C80* + ID_MODEL_FROM_DATABASE=PCI-6035E + +pci:v00001093d00002C90* + ID_MODEL_FROM_DATABASE=PCI-6703 + +pci:v00001093d00002CA0* + ID_MODEL_FROM_DATABASE=PCI-6034E + +pci:v00001093d00002CB0* + ID_MODEL_FROM_DATABASE=PCI-7344 + +pci:v00001093d00002CC0* + ID_MODEL_FROM_DATABASE=PXI-6608 + +pci:v00001093d00002D20* + ID_MODEL_FROM_DATABASE=PXI-5600 + +pci:v00001093d00002DB0* + ID_MODEL_FROM_DATABASE=PCI-6608 + +pci:v00001093d00002DC0* + ID_MODEL_FROM_DATABASE=PCI-4070 + +pci:v00001093d00002DD0* + ID_MODEL_FROM_DATABASE=PXI-4070 + +pci:v00001093d00002EB0* + ID_MODEL_FROM_DATABASE=PXI-4472 + +pci:v00001093d00002EC0* + ID_MODEL_FROM_DATABASE=PXI-6115 + +pci:v00001093d00002ED0* + ID_MODEL_FROM_DATABASE=PCI-6115 + +pci:v00001093d00002EE0* + ID_MODEL_FROM_DATABASE=PXI-6120 + +pci:v00001093d00002EF0* + ID_MODEL_FROM_DATABASE=PCI-6120 + +pci:v00001093d00002FD1* + ID_MODEL_FROM_DATABASE=PCI-7334 + +pci:v00001093d00002FD2* + ID_MODEL_FROM_DATABASE=PCI-7350 + +pci:v00001093d00002FD3* + ID_MODEL_FROM_DATABASE=PCI-7342 + +pci:v00001093d00002FD5* + ID_MODEL_FROM_DATABASE=PXI-7350 + +pci:v00001093d00002FD6* + ID_MODEL_FROM_DATABASE=PXI-7342 + +pci:v00001093d00007003* + ID_MODEL_FROM_DATABASE=PCI-6551 + +pci:v00001093d00007004* + ID_MODEL_FROM_DATABASE=PXI-6551 + +pci:v00001093d0000700B* + ID_MODEL_FROM_DATABASE=PXI-5421 + +pci:v00001093d0000700C* + ID_MODEL_FROM_DATABASE=PCI-5421 + +pci:v00001093d0000701A* + ID_MODEL_FROM_DATABASE=VXIpc-87xB + +pci:v00001093d0000701B* + ID_MODEL_FROM_DATABASE=VXIpc-770 + +pci:v00001093d00007023* + ID_MODEL_FROM_DATABASE=PXI-2593 + +pci:v00001093d00007027* + ID_MODEL_FROM_DATABASE=PCI-MXI-2 Universal + +pci:v00001093d0000702C* + ID_MODEL_FROM_DATABASE=PXI-7831R + +pci:v00001093d0000702D* + ID_MODEL_FROM_DATABASE=PCI-7831R + +pci:v00001093d0000702E* + ID_MODEL_FROM_DATABASE=PXI-7811R + +pci:v00001093d0000702F* + ID_MODEL_FROM_DATABASE=PCI-7811R + +pci:v00001093d00007030* + ID_MODEL_FROM_DATABASE=PCI-CAN (Series 2) + +pci:v00001093d00007031* + ID_MODEL_FROM_DATABASE=PCI-CAN/2 (Series 2) + +pci:v00001093d00007032* + ID_MODEL_FROM_DATABASE=PCI-CAN/LS (Series 2) + +pci:v00001093d00007033* + ID_MODEL_FROM_DATABASE=PCI-CAN/LS2 (Series 2) + +pci:v00001093d00007034* + ID_MODEL_FROM_DATABASE=PCI-CAN/DS (Series 2) + +pci:v00001093d00007035* + ID_MODEL_FROM_DATABASE=PXI-8460 (Series 2, 1 port) + +pci:v00001093d00007036* + ID_MODEL_FROM_DATABASE=PXI-8460 (Series 2, 2 ports) + +pci:v00001093d00007037* + ID_MODEL_FROM_DATABASE=PXI-8461 (Series 2, 1 port) + +pci:v00001093d00007038* + ID_MODEL_FROM_DATABASE=PXI-8461 (Series 2, 2 ports) + +pci:v00001093d00007039* + ID_MODEL_FROM_DATABASE=PXI-8462 (Series 2) + +pci:v00001093d0000703F* + ID_MODEL_FROM_DATABASE=PXI-2566 + +pci:v00001093d00007040* + ID_MODEL_FROM_DATABASE=PXI-2567 + +pci:v00001093d00007044* + ID_MODEL_FROM_DATABASE=MXI-4 Connection Monitor + +pci:v00001093d00007047* + ID_MODEL_FROM_DATABASE=PXI-6653 + +pci:v00001093d0000704C* + ID_MODEL_FROM_DATABASE=PXI-2530 + +pci:v00001093d0000704F* + ID_MODEL_FROM_DATABASE=PXI-4220 + +pci:v00001093d00007050* + ID_MODEL_FROM_DATABASE=PXI-4204 + +pci:v00001093d00007055* + ID_MODEL_FROM_DATABASE=PXI-7830R + +pci:v00001093d00007056* + ID_MODEL_FROM_DATABASE=PCI-7830R + +pci:v00001093d0000705A* + ID_MODEL_FROM_DATABASE=PCI-CAN/XS (Series 2) + +pci:v00001093d0000705B* + ID_MODEL_FROM_DATABASE=PCI-CAN/XS2 (Series 2) + +pci:v00001093d0000705C* + ID_MODEL_FROM_DATABASE=PXI-8464 (Series 2, 1 port) + +pci:v00001093d0000705D* + ID_MODEL_FROM_DATABASE=PXI-8464 (Series 2, 2 ports) + +pci:v00001093d0000705E* + ID_MODEL_FROM_DATABASE=cRIO-9102 + +pci:v00001093d00007060* + ID_MODEL_FROM_DATABASE=PXI-5610 + +pci:v00001093d00007064* + ID_MODEL_FROM_DATABASE=PXI-1045 Trigger Routing Module + +pci:v00001093d00007065* + ID_MODEL_FROM_DATABASE=PXI-6652 + +pci:v00001093d00007066* + ID_MODEL_FROM_DATABASE=PXI-6651 + +pci:v00001093d00007067* + ID_MODEL_FROM_DATABASE=PXI-2529 + +pci:v00001093d00007068* + ID_MODEL_FROM_DATABASE=PCI-CAN/SW (Series 2) + +pci:v00001093d00007069* + ID_MODEL_FROM_DATABASE=PCI-CAN/SW2 (Series 2) + +pci:v00001093d0000706A* + ID_MODEL_FROM_DATABASE=PXI-8463 (Series 2, 1 port) + +pci:v00001093d0000706B* + ID_MODEL_FROM_DATABASE=PXI-8463 (Series 2, 2 ports) + +pci:v00001093d00007073* + ID_MODEL_FROM_DATABASE=PCI-6723 + +pci:v00001093d00007074* + ID_MODEL_FROM_DATABASE=PXI-7833R + +pci:v00001093d00007075* + ID_MODEL_FROM_DATABASE=PXI-6552 + +pci:v00001093d00007076* + ID_MODEL_FROM_DATABASE=PCI-6552 + +pci:v00001093d0000707C* + ID_MODEL_FROM_DATABASE=PXI-1428 + +pci:v00001093d0000707E* + ID_MODEL_FROM_DATABASE=PXI-4462 + +pci:v00001093d00007080* + ID_MODEL_FROM_DATABASE=PXI-8430/2 (RS-232) Interface + +pci:v00001093d00007081* + ID_MODEL_FROM_DATABASE=PXI-8431/2 (RS-485) Interface + +pci:v00001093d00007083* + ID_MODEL_FROM_DATABASE=PCI-7833R + +pci:v00001093d00007085* + ID_MODEL_FROM_DATABASE=PCI-6509 + +pci:v00001093d00007086* + ID_MODEL_FROM_DATABASE=PXI-6528 + +pci:v00001093d00007087* + ID_MODEL_FROM_DATABASE=PCI-6515 + +pci:v00001093d00007088* + ID_MODEL_FROM_DATABASE=PCI-6514 + +pci:v00001093d0000708C* + ID_MODEL_FROM_DATABASE=PXI-2568 + +pci:v00001093d0000708D* + ID_MODEL_FROM_DATABASE=PXI-2569 + +pci:v00001093d000070A9* + ID_MODEL_FROM_DATABASE=PCI-6528 + +pci:v00001093d000070AA* + ID_MODEL_FROM_DATABASE=PCI-6229 + +pci:v00001093d000070AB* + ID_MODEL_FROM_DATABASE=PCI-6259 + +pci:v00001093d000070AC* + ID_MODEL_FROM_DATABASE=PCI-6289 + +pci:v00001093d000070AD* + ID_MODEL_FROM_DATABASE=PXI-6251 + +pci:v00001093d000070AE* + ID_MODEL_FROM_DATABASE=PXI-6220 + +pci:v00001093d000070AF* + ID_MODEL_FROM_DATABASE=PCI-6221 + +pci:v00001093d000070B0* + ID_MODEL_FROM_DATABASE=PCI-6220 + +pci:v00001093d000070B1* + ID_MODEL_FROM_DATABASE=PXI-6229 + +pci:v00001093d000070B2* + ID_MODEL_FROM_DATABASE=PXI-6259 + +pci:v00001093d000070B3* + ID_MODEL_FROM_DATABASE=PXI-6289 + +pci:v00001093d000070B4* + ID_MODEL_FROM_DATABASE=PCI-6250 + +pci:v00001093d000070B5* + ID_MODEL_FROM_DATABASE=PXI-6221 + +pci:v00001093d000070B6* + ID_MODEL_FROM_DATABASE=PCI-6280 + +pci:v00001093d000070B7* + ID_MODEL_FROM_DATABASE=PCI-6254 + +pci:v00001093d000070B8* + ID_MODEL_FROM_DATABASE=PCI-6251 + +pci:v00001093d000070B9* + ID_MODEL_FROM_DATABASE=PXI-6250 + +pci:v00001093d000070BA* + ID_MODEL_FROM_DATABASE=PXI-6254 + +pci:v00001093d000070BB* + ID_MODEL_FROM_DATABASE=PXI-6280 + +pci:v00001093d000070BC* + ID_MODEL_FROM_DATABASE=PCI-6284 + +pci:v00001093d000070BD* + ID_MODEL_FROM_DATABASE=PCI-6281 + +pci:v00001093d000070BE* + ID_MODEL_FROM_DATABASE=PXI-6284 + +pci:v00001093d000070BF* + ID_MODEL_FROM_DATABASE=PXI-6281 + +pci:v00001093d000070C0* + ID_MODEL_FROM_DATABASE=PCI-6143 + +pci:v00001093d000070C3* + ID_MODEL_FROM_DATABASE=PCI-6511 + +pci:v00001093d000070C4* + ID_MODEL_FROM_DATABASE=PXI-7330 + +pci:v00001093d000070C5* + ID_MODEL_FROM_DATABASE=PXI-7340 + +pci:v00001093d000070C6* + ID_MODEL_FROM_DATABASE=PCI-7330 + +pci:v00001093d000070C7* + ID_MODEL_FROM_DATABASE=PCI-7340 + +pci:v00001093d000070C8* + ID_MODEL_FROM_DATABASE=PCI-6513 + +pci:v00001093d000070C9* + ID_MODEL_FROM_DATABASE=PXI-6515 + +pci:v00001093d000070CA* + ID_MODEL_FROM_DATABASE=PCI-1405 + +pci:v00001093d000070CC* + ID_MODEL_FROM_DATABASE=PCI-6512 + +pci:v00001093d000070CD* + ID_MODEL_FROM_DATABASE=PXI-6514 + +pci:v00001093d000070CE* + ID_MODEL_FROM_DATABASE=PXI-1405 + +pci:v00001093d000070CF* + ID_MODEL_FROM_DATABASE=PCIe-GPIB + +pci:v00001093d000070D0* + ID_MODEL_FROM_DATABASE=PXI-2570 + +pci:v00001093d000070D1* + ID_MODEL_FROM_DATABASE=PXI-6513 + +pci:v00001093d000070D2* + ID_MODEL_FROM_DATABASE=PXI-6512 + +pci:v00001093d000070D3* + ID_MODEL_FROM_DATABASE=PXI-6511 + +pci:v00001093d000070D4* + ID_MODEL_FROM_DATABASE=PCI-6722 + +pci:v00001093d000070D6* + ID_MODEL_FROM_DATABASE=PXI-4072 + +pci:v00001093d000070D7* + ID_MODEL_FROM_DATABASE=PXI-6541 + +pci:v00001093d000070D8* + ID_MODEL_FROM_DATABASE=PXI-6542 + +pci:v00001093d000070D9* + ID_MODEL_FROM_DATABASE=PCI-6541 + +pci:v00001093d000070DA* + ID_MODEL_FROM_DATABASE=PCI-6542 + +pci:v00001093d000070DB* + ID_MODEL_FROM_DATABASE=PCI-8430/2 (RS-232) Interface + +pci:v00001093d000070DC* + ID_MODEL_FROM_DATABASE=PCI-8431/2 (RS-485) Interface + +pci:v00001093d000070DD* + ID_MODEL_FROM_DATABASE=PXI-8430/4 (RS-232) Interface + +pci:v00001093d000070DE* + ID_MODEL_FROM_DATABASE=PXI-8431/4 (RS-485) Interface + +pci:v00001093d000070DF* + ID_MODEL_FROM_DATABASE=PCI-8430/4 (RS-232) Interface + +pci:v00001093d000070E0* + ID_MODEL_FROM_DATABASE=PCI-8431/4 (RS-485) Interface + +pci:v00001093d000070E1* + ID_MODEL_FROM_DATABASE=PXI-2532 + +pci:v00001093d000070E2* + ID_MODEL_FROM_DATABASE=PXI-8430/8 (RS-232) Interface + +pci:v00001093d000070E3* + ID_MODEL_FROM_DATABASE=PXI-8431/8 (RS-485) Interface + +pci:v00001093d000070E4* + ID_MODEL_FROM_DATABASE=PCI-8430/8 (RS-232) Interface + +pci:v00001093d000070E5* + ID_MODEL_FROM_DATABASE=PCI-8431/8 (RS-485) Interface + +pci:v00001093d000070E6* + ID_MODEL_FROM_DATABASE=PXI-8430/16 (RS-232) Interface + +pci:v00001093d000070E7* + ID_MODEL_FROM_DATABASE=PCI-8430/16 (RS-232) Interface + +pci:v00001093d000070E8* + ID_MODEL_FROM_DATABASE=PXI-8432/2 (Isolated RS-232) Interface + +pci:v00001093d000070E9* + ID_MODEL_FROM_DATABASE=PXI-8433/2 (Isolated RS-485) Interface + +pci:v00001093d000070EA* + ID_MODEL_FROM_DATABASE=PCI-8432/2 (Isolated RS-232) Interface + +pci:v00001093d000070EB* + ID_MODEL_FROM_DATABASE=PCI-8433/2 (Isolated RS-485) Interface + +pci:v00001093d000070EC* + ID_MODEL_FROM_DATABASE=PXI-8432/4 (Isolated RS-232) Interface + +pci:v00001093d000070ED* + ID_MODEL_FROM_DATABASE=PXI-8433/4 (Isolated RS-485) Interface + +pci:v00001093d000070EE* + ID_MODEL_FROM_DATABASE=PCI-8432/4 (Isolated RS-232) Interface + +pci:v00001093d000070EF* + ID_MODEL_FROM_DATABASE=PCI-8433/4 (Isolated RS-485) Interface + +pci:v00001093d000070F0* + ID_MODEL_FROM_DATABASE=PXI-5922 + +pci:v00001093d000070F1* + ID_MODEL_FROM_DATABASE=PCI-5922 + +pci:v00001093d000070F2* + ID_MODEL_FROM_DATABASE=PCI-6224 + +pci:v00001093d000070F3* + ID_MODEL_FROM_DATABASE=PXI-6224 + +pci:v00001093d000070F6* + ID_MODEL_FROM_DATABASE=cRIO-9101 + +pci:v00001093d000070F7* + ID_MODEL_FROM_DATABASE=cRIO-9103 + +pci:v00001093d000070F8* + ID_MODEL_FROM_DATABASE=cRIO-9104 + +pci:v00001093d000070FF* + ID_MODEL_FROM_DATABASE=PXI-6723 + +pci:v00001093d00007100* + ID_MODEL_FROM_DATABASE=PXI-6722 + +pci:v00001093d00007104* + ID_MODEL_FROM_DATABASE=PCIx-1429 + +pci:v00001093d00007105* + ID_MODEL_FROM_DATABASE=PCIe-1429 + +pci:v00001093d0000710A* + ID_MODEL_FROM_DATABASE=PXI-4071 + +pci:v00001093d0000710D* + ID_MODEL_FROM_DATABASE=PXI-6143 + +pci:v00001093d0000710E* + ID_MODEL_FROM_DATABASE=PCIe-GPIB + +pci:v00001093d0000710F* + ID_MODEL_FROM_DATABASE=PXI-5422 + +pci:v00001093d00007110* + ID_MODEL_FROM_DATABASE=PCI-5422 + +pci:v00001093d00007111* + ID_MODEL_FROM_DATABASE=PXI-5441 + +pci:v00001093d00007119* + ID_MODEL_FROM_DATABASE=PXI-6561 + +pci:v00001093d0000711A* + ID_MODEL_FROM_DATABASE=PXI-6562 + +pci:v00001093d0000711B* + ID_MODEL_FROM_DATABASE=PCI-6561 + +pci:v00001093d0000711C* + ID_MODEL_FROM_DATABASE=PCI-6562 + +pci:v00001093d00007120* + ID_MODEL_FROM_DATABASE=PCI-7390 + +pci:v00001093d00007121* + ID_MODEL_FROM_DATABASE=PXI-5122EX + +pci:v00001093d00007122* + ID_MODEL_FROM_DATABASE=PCI-5122EX + +pci:v00001093d00007123* + ID_MODEL_FROM_DATABASE=PXIe-5653 + +pci:v00001093d00007124* + ID_MODEL_FROM_DATABASE=PCI-6510 + +pci:v00001093d00007125* + ID_MODEL_FROM_DATABASE=PCI-6516 + +pci:v00001093d00007126* + ID_MODEL_FROM_DATABASE=PCI-6517 + +pci:v00001093d00007127* + ID_MODEL_FROM_DATABASE=PCI-6518 + +pci:v00001093d00007128* + ID_MODEL_FROM_DATABASE=PCI-6519 + +pci:v00001093d00007137* + ID_MODEL_FROM_DATABASE=PXI-2575 + +pci:v00001093d0000713C* + ID_MODEL_FROM_DATABASE=PXI-2585 + +pci:v00001093d0000713D* + ID_MODEL_FROM_DATABASE=PXI-2586 + +pci:v00001093d00007142* + ID_MODEL_FROM_DATABASE=PXI-4224 + +pci:v00001093d00007144* + ID_MODEL_FROM_DATABASE=PXI-5124 + +pci:v00001093d00007145* + ID_MODEL_FROM_DATABASE=PCI-5124 + +pci:v00001093d00007146* + ID_MODEL_FROM_DATABASE=PCI-6132 + +pci:v00001093d00007147* + ID_MODEL_FROM_DATABASE=PXI-6132 + +pci:v00001093d00007148* + ID_MODEL_FROM_DATABASE=PCI-6122 + +pci:v00001093d00007149* + ID_MODEL_FROM_DATABASE=PXI-6122 + +pci:v00001093d0000714C* + ID_MODEL_FROM_DATABASE=PXI-5114 + +pci:v00001093d0000714D* + ID_MODEL_FROM_DATABASE=PCI-5114 + +pci:v00001093d00007150* + ID_MODEL_FROM_DATABASE=PXI-2564 + +pci:v00001093d00007152* + ID_MODEL_FROM_DATABASE=PCI-5640R + +pci:v00001093d00007156* + ID_MODEL_FROM_DATABASE=PXI-1044 Trigger Routing Module + +pci:v00001093d0000715D* + ID_MODEL_FROM_DATABASE=PCI-1426 + +pci:v00001093d00007167* + ID_MODEL_FROM_DATABASE=PXI-5412 + +pci:v00001093d00007168* + ID_MODEL_FROM_DATABASE=PCI-5412 + +pci:v00001093d0000716B* + ID_MODEL_FROM_DATABASE=PCI-6230 + +pci:v00001093d0000716C* + ID_MODEL_FROM_DATABASE=PCI-6225 + +pci:v00001093d0000716D* + ID_MODEL_FROM_DATABASE=PXI-6225 + +pci:v00001093d0000716F* + ID_MODEL_FROM_DATABASE=PCI-4461 + +pci:v00001093d00007170* + ID_MODEL_FROM_DATABASE=PCI-4462 + +pci:v00001093d00007171* + ID_MODEL_FROM_DATABASE=PCI-6010 + +pci:v00001093d00007174* + ID_MODEL_FROM_DATABASE=PXI-8360 + +pci:v00001093d00007177* + ID_MODEL_FROM_DATABASE=PXI-6230 + +pci:v00001093d0000717D* + ID_MODEL_FROM_DATABASE=PCIe-6251 + +pci:v00001093d0000717F* + ID_MODEL_FROM_DATABASE=PCIe-6259 + +pci:v00001093d00007187* + ID_MODEL_FROM_DATABASE=PCI-1410 + +pci:v00001093d0000718B* + ID_MODEL_FROM_DATABASE=PCI-6521 + +pci:v00001093d0000718C* + ID_MODEL_FROM_DATABASE=PXI-6521 + +pci:v00001093d00007191* + ID_MODEL_FROM_DATABASE=PCI-6154 + +pci:v00001093d00007193* + ID_MODEL_FROM_DATABASE=PXI-7813R + +pci:v00001093d00007194* + ID_MODEL_FROM_DATABASE=PCI-7813R + +pci:v00001093d00007195* + ID_MODEL_FROM_DATABASE=PCI-8254R + +pci:v00001093d00007197* + ID_MODEL_FROM_DATABASE=PXI-5402 + +pci:v00001093d00007198* + ID_MODEL_FROM_DATABASE=PCI-5402 + +pci:v00001093d0000719F* + ID_MODEL_FROM_DATABASE=PCIe-6535 + +pci:v00001093d000071A0* + ID_MODEL_FROM_DATABASE=PCIe-6536 + +pci:v00001093d000071A3* + ID_MODEL_FROM_DATABASE=PXI-5650 + +pci:v00001093d000071A4* + ID_MODEL_FROM_DATABASE=PXI-5652 + +pci:v00001093d000071A5* + ID_MODEL_FROM_DATABASE=PXI-2594 + +pci:v00001093d000071A7* + ID_MODEL_FROM_DATABASE=PXI-2595 + +pci:v00001093d000071A9* + ID_MODEL_FROM_DATABASE=PXI-2596 + +pci:v00001093d000071AA* + ID_MODEL_FROM_DATABASE=PXI-2597 + +pci:v00001093d000071AB* + ID_MODEL_FROM_DATABASE=PXI-2598 + +pci:v00001093d000071AC* + ID_MODEL_FROM_DATABASE=PXI-2599 + +pci:v00001093d000071AD* + ID_MODEL_FROM_DATABASE=PCI-GPIB+ + +pci:v00001093d000071AE* + ID_MODEL_FROM_DATABASE=PCIe-1430 + +pci:v00001093d000071B7* + ID_MODEL_FROM_DATABASE=PXI-1056 Trigger Routing Module + +pci:v00001093d000071B8* + ID_MODEL_FROM_DATABASE=PXI-1045 Trigger Routing Module + +pci:v00001093d000071B9* + ID_MODEL_FROM_DATABASE=PXI-1044 Trigger Routing Module + +pci:v00001093d000071BB* + ID_MODEL_FROM_DATABASE=PXI-2584 + +pci:v00001093d000071BC* + ID_MODEL_FROM_DATABASE=PCI-6221 (37-pin) + +pci:v00001093d000071BF* + ID_MODEL_FROM_DATABASE=PCIe-1427 + +pci:v00001093d000071C5* + ID_MODEL_FROM_DATABASE=PCI-6520 + +pci:v00001093d000071C6* + ID_MODEL_FROM_DATABASE=PXI-2576 + +pci:v00001093d000071C7* + ID_MODEL_FROM_DATABASE=cRIO-9072 + +pci:v00001093d000071DC* + ID_MODEL_FROM_DATABASE=PCI-1588 + +pci:v00001093d000071E0* + ID_MODEL_FROM_DATABASE=PCI-6255 + +pci:v00001093d000071E1* + ID_MODEL_FROM_DATABASE=PXI-6255 + +pci:v00001093d000071E2* + ID_MODEL_FROM_DATABASE=PXI-5406 + +pci:v00001093d000071E3* + ID_MODEL_FROM_DATABASE=PCI-5406 + +pci:v00001093d000071FC* + ID_MODEL_FROM_DATABASE=PXI-4022 + +pci:v00001093d00007209* + ID_MODEL_FROM_DATABASE=PCI-6233 + +pci:v00001093d0000720A* + ID_MODEL_FROM_DATABASE=PXI-6233 + +pci:v00001093d0000720B* + ID_MODEL_FROM_DATABASE=PCI-6238 + +pci:v00001093d0000720C* + ID_MODEL_FROM_DATABASE=PXI-6238 + +pci:v00001093d00007260* + ID_MODEL_FROM_DATABASE=PXI-5142 + +pci:v00001093d00007261* + ID_MODEL_FROM_DATABASE=PCI-5142 + +pci:v00001093d0000726D* + ID_MODEL_FROM_DATABASE=PXI-5651 + +pci:v00001093d00007273* + ID_MODEL_FROM_DATABASE=PXI-4461 + +pci:v00001093d00007274* + ID_MODEL_FROM_DATABASE=PXI-4462 + +pci:v00001093d00007279* + ID_MODEL_FROM_DATABASE=PCI-6232 + +pci:v00001093d0000727A* + ID_MODEL_FROM_DATABASE=PXI-6232 + +pci:v00001093d0000727B* + ID_MODEL_FROM_DATABASE=PCI-6239 + +pci:v00001093d0000727C* + ID_MODEL_FROM_DATABASE=PXI-6239 + +pci:v00001093d0000727E* + ID_MODEL_FROM_DATABASE=SMBus Controller + +pci:v00001093d0000727Esv00001093sd000075AC* + ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8388) + +pci:v00001093d0000727Esv00001093sd000075AD* + ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8389) + +pci:v00001093d0000727Esv00001093sd00007650* + ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8381) + +pci:v00001093d0000727Esv00001093sd00008360* + ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8360) + +pci:v00001093d0000727Esv00001093sd00008370* + ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8370) + +pci:v00001093d0000727Esv00001093sd00008375* + ID_MODEL_FROM_DATABASE=SMBus Controller (PXIe-8375) + +pci:v00001093d00007281* + ID_MODEL_FROM_DATABASE=PCI-6236 + +pci:v00001093d00007282* + ID_MODEL_FROM_DATABASE=PXI-6236 + +pci:v00001093d00007283* + ID_MODEL_FROM_DATABASE=PXI-2554 + +pci:v00001093d00007288* + ID_MODEL_FROM_DATABASE=PXIe-5611 + +pci:v00001093d00007293* + ID_MODEL_FROM_DATABASE=PCIe-8255R + +pci:v00001093d0000729D* + ID_MODEL_FROM_DATABASE=cRIO-9074 + +pci:v00001093d000072A4* + ID_MODEL_FROM_DATABASE=PCIe-4065 + +pci:v00001093d000072A7* + ID_MODEL_FROM_DATABASE=PCIe-6537 + +pci:v00001093d000072A8* + ID_MODEL_FROM_DATABASE=PXI-5152 + +pci:v00001093d000072A9* + ID_MODEL_FROM_DATABASE=PCI-5152 + +pci:v00001093d000072AA* + ID_MODEL_FROM_DATABASE=PXI-5105 + +pci:v00001093d000072AB* + ID_MODEL_FROM_DATABASE=PCI-5105 + +pci:v00001093d000072B8* + ID_MODEL_FROM_DATABASE=PXI-6682 + +pci:v00001093d000072D0* + ID_MODEL_FROM_DATABASE=PXI-2545 + +pci:v00001093d000072D1* + ID_MODEL_FROM_DATABASE=PXI-2546 + +pci:v00001093d000072D2* + ID_MODEL_FROM_DATABASE=PXI-2547 + +pci:v00001093d000072D3* + ID_MODEL_FROM_DATABASE=PXI-2548 + +pci:v00001093d000072D4* + ID_MODEL_FROM_DATABASE=PXI-2549 + +pci:v00001093d000072D5* + ID_MODEL_FROM_DATABASE=PXI-2555 + +pci:v00001093d000072D6* + ID_MODEL_FROM_DATABASE=PXI-2556 + +pci:v00001093d000072D7* + ID_MODEL_FROM_DATABASE=PXI-2557 + +pci:v00001093d000072D8* + ID_MODEL_FROM_DATABASE=PXI-2558 + +pci:v00001093d000072D9* + ID_MODEL_FROM_DATABASE=PXI-2559 + +pci:v00001093d000072E8* + ID_MODEL_FROM_DATABASE=PXIe-6251 + +pci:v00001093d000072E9* + ID_MODEL_FROM_DATABASE=PXIe-6259 + +pci:v00001093d000072EF* + ID_MODEL_FROM_DATABASE=PXI-4498 + +pci:v00001093d000072F0* + ID_MODEL_FROM_DATABASE=PXI-4496 + +pci:v00001093d000072FB* + ID_MODEL_FROM_DATABASE=PXIe-6672 + +pci:v00001093d0000730E* + ID_MODEL_FROM_DATABASE=PXI-4130 + +pci:v00001093d0000730F* + ID_MODEL_FROM_DATABASE=PXI-5922EX + +pci:v00001093d00007310* + ID_MODEL_FROM_DATABASE=PCI-5922EX + +pci:v00001093d0000731C* + ID_MODEL_FROM_DATABASE=PXI-2535 + +pci:v00001093d0000731D* + ID_MODEL_FROM_DATABASE=PXI-2536 + +pci:v00001093d00007322* + ID_MODEL_FROM_DATABASE=PXIe-6124 + +pci:v00001093d00007327* + ID_MODEL_FROM_DATABASE=PXI-6529 + +pci:v00001093d0000732C* + ID_MODEL_FROM_DATABASE=VXI-8360T + +pci:v00001093d00007331* + ID_MODEL_FROM_DATABASE=PXIe-5602 + +pci:v00001093d00007332* + ID_MODEL_FROM_DATABASE=PXIe-5601 + +pci:v00001093d00007333* + ID_MODEL_FROM_DATABASE=PXI-5900 + +pci:v00001093d00007335* + ID_MODEL_FROM_DATABASE=PXI-2533 + +pci:v00001093d00007336* + ID_MODEL_FROM_DATABASE=PXI-2534 + +pci:v00001093d00007342* + ID_MODEL_FROM_DATABASE=PXI-4461 + +pci:v00001093d00007349* + ID_MODEL_FROM_DATABASE=PXI-5154 + +pci:v00001093d0000734A* + ID_MODEL_FROM_DATABASE=PCI-5154 + +pci:v00001093d00007357* + ID_MODEL_FROM_DATABASE=PXI-4065 + +pci:v00001093d00007359* + ID_MODEL_FROM_DATABASE=PXI-4495 + +pci:v00001093d00007370* + ID_MODEL_FROM_DATABASE=PXI-4461 + +pci:v00001093d00007373* + ID_MODEL_FROM_DATABASE=sbRIO-9601 + +pci:v00001093d00007374* + ID_MODEL_FROM_DATABASE=IOtech-9601 + +pci:v00001093d00007375* + ID_MODEL_FROM_DATABASE=sbRIO-9602 + +pci:v00001093d00007378* + ID_MODEL_FROM_DATABASE=sbRIO-9641 + +pci:v00001093d0000737D* + ID_MODEL_FROM_DATABASE=PXI-5124EX + +pci:v00001093d00007384* + ID_MODEL_FROM_DATABASE=PXI-7851R + +pci:v00001093d00007385* + ID_MODEL_FROM_DATABASE=PXI-7852R + +pci:v00001093d00007386* + ID_MODEL_FROM_DATABASE=PCIe-7851R + +pci:v00001093d00007387* + ID_MODEL_FROM_DATABASE=PCIe-7852R + +pci:v00001093d00007390* + ID_MODEL_FROM_DATABASE=PXI-7841R + +pci:v00001093d00007391* + ID_MODEL_FROM_DATABASE=PXI-7842R + +pci:v00001093d00007392* + ID_MODEL_FROM_DATABASE=PXI-7853R + +pci:v00001093d00007393* + ID_MODEL_FROM_DATABASE=PCIe-7841R + +pci:v00001093d00007394* + ID_MODEL_FROM_DATABASE=PCIe-7842R + +pci:v00001093d00007397* + ID_MODEL_FROM_DATABASE=sbRIO-9611 + +pci:v00001093d00007398* + ID_MODEL_FROM_DATABASE=sbRIO-9612 + +pci:v00001093d00007399* + ID_MODEL_FROM_DATABASE=sbRIO-9631 + +pci:v00001093d0000739A* + ID_MODEL_FROM_DATABASE=sbRIO-9632 + +pci:v00001093d0000739B* + ID_MODEL_FROM_DATABASE=sbRIO-9642 + +pci:v00001093d000073A1* + ID_MODEL_FROM_DATABASE=PXIe-4498 + +pci:v00001093d000073A2* + ID_MODEL_FROM_DATABASE=PXIe-4496 + +pci:v00001093d000073A5* + ID_MODEL_FROM_DATABASE=PXIe-5641R + +pci:v00001093d000073A7* + ID_MODEL_FROM_DATABASE=PXI-8250 Chassis Monitor Module + +pci:v00001093d000073A8* + ID_MODEL_FROM_DATABASE=PXI-8511 CAN/LS + +pci:v00001093d000073A9* + ID_MODEL_FROM_DATABASE=PXI-8511 CAN/LS + +pci:v00001093d000073AA* + ID_MODEL_FROM_DATABASE=PXI-8512 CAN/HS + +pci:v00001093d000073AB* + ID_MODEL_FROM_DATABASE=PXI-8512 CAN/HS + +pci:v00001093d000073AC* + ID_MODEL_FROM_DATABASE=PXI-8513 CAN/XS + +pci:v00001093d000073AD* + ID_MODEL_FROM_DATABASE=PXI-8513 CAN/XS + +pci:v00001093d000073AF* + ID_MODEL_FROM_DATABASE=PXI-8516 LIN + +pci:v00001093d000073B1* + ID_MODEL_FROM_DATABASE=PXI-8517 FlexRay + +pci:v00001093d000073B2* + ID_MODEL_FROM_DATABASE=PXI-8531 CANopen + +pci:v00001093d000073B3* + ID_MODEL_FROM_DATABASE=PXI-8531 CANopen + +pci:v00001093d000073B4* + ID_MODEL_FROM_DATABASE=PXI-8532 DeviceNet + +pci:v00001093d000073B5* + ID_MODEL_FROM_DATABASE=PXI-8532 DeviceNet + +pci:v00001093d000073B6* + ID_MODEL_FROM_DATABASE=PCI-8511 CAN/LS + +pci:v00001093d000073B7* + ID_MODEL_FROM_DATABASE=PCI-8511 CAN/LS + +pci:v00001093d000073B8* + ID_MODEL_FROM_DATABASE=PCI-8512 CAN/HS + +pci:v00001093d000073B9* + ID_MODEL_FROM_DATABASE=PCI-8512 CAN/HS + +pci:v00001093d000073BA* + ID_MODEL_FROM_DATABASE=PCI-8513 CAN/XS + +pci:v00001093d000073BB* + ID_MODEL_FROM_DATABASE=PCI-8513 CAN/XS + +pci:v00001093d000073BD* + ID_MODEL_FROM_DATABASE=PCI-8516 LIN + +pci:v00001093d000073BF* + ID_MODEL_FROM_DATABASE=PCI-8517 FlexRay + +pci:v00001093d000073C0* + ID_MODEL_FROM_DATABASE=PCI-8531 CANopen + +pci:v00001093d000073C1* + ID_MODEL_FROM_DATABASE=PCI-8531 CANopen + +pci:v00001093d000073C2* + ID_MODEL_FROM_DATABASE=PCI-8532 DeviceNet + +pci:v00001093d000073C3* + ID_MODEL_FROM_DATABASE=PCI-8532 DeviceNet + +pci:v00001093d000073C5* + ID_MODEL_FROM_DATABASE=PXIe-2527 + +pci:v00001093d000073C6* + ID_MODEL_FROM_DATABASE=PXIe-2529 + +pci:v00001093d000073C8* + ID_MODEL_FROM_DATABASE=PXIe-2530 + +pci:v00001093d000073C9* + ID_MODEL_FROM_DATABASE=PXIe-2532 + +pci:v00001093d000073CA* + ID_MODEL_FROM_DATABASE=PXIe-2569 + +pci:v00001093d000073CB* + ID_MODEL_FROM_DATABASE=PXIe-2575 + +pci:v00001093d000073CC* + ID_MODEL_FROM_DATABASE=PXIe-2593 + +pci:v00001093d000073D5* + ID_MODEL_FROM_DATABASE=PXI-7951R + +pci:v00001093d000073D6* + ID_MODEL_FROM_DATABASE=PXI-7952R + +pci:v00001093d000073D7* + ID_MODEL_FROM_DATABASE=PXI-7953R + +pci:v00001093d000073E1* + ID_MODEL_FROM_DATABASE=PXI-7854R + +pci:v00001093d000073EC* + ID_MODEL_FROM_DATABASE=PXI-7954R + +pci:v00001093d000073ED* + ID_MODEL_FROM_DATABASE=cRIO-9073 + +pci:v00001093d000073F0* + ID_MODEL_FROM_DATABASE=PXI-5153 + +pci:v00001093d000073F1* + ID_MODEL_FROM_DATABASE=PCI-5153 + +pci:v00001093d000073F4* + ID_MODEL_FROM_DATABASE=PXI-2515 + +pci:v00001093d000073F6* + ID_MODEL_FROM_DATABASE=cRIO-9111 + +pci:v00001093d000073F7* + ID_MODEL_FROM_DATABASE=cRIO-9112 + +pci:v00001093d000073F8* + ID_MODEL_FROM_DATABASE=cRIO-9113 + +pci:v00001093d000073F9* + ID_MODEL_FROM_DATABASE=cRIO-9114 + +pci:v00001093d000073FA* + ID_MODEL_FROM_DATABASE=cRIO-9116 + +pci:v00001093d000073FB* + ID_MODEL_FROM_DATABASE=cRIO-9118 + +pci:v00001093d00007404* + ID_MODEL_FROM_DATABASE=PXI-4132 + +pci:v00001093d00007405* + ID_MODEL_FROM_DATABASE=PXIe-6674T + +pci:v00001093d00007406* + ID_MODEL_FROM_DATABASE=PXIe-6674 + +pci:v00001093d0000740E* + ID_MODEL_FROM_DATABASE=PCIe-8430/16 (RS-232) Interface + +pci:v00001093d0000740F* + ID_MODEL_FROM_DATABASE=PCIe-8430/8 (RS-232) Interface + +pci:v00001093d00007410* + ID_MODEL_FROM_DATABASE=PCIe-8431/16 (RS-485) Interface + +pci:v00001093d00007411* + ID_MODEL_FROM_DATABASE=PCIe-8431/8 (RS-485) Interface + +pci:v00001093d00007414* + ID_MODEL_FROM_DATABASE=PCIe-GPIB+ + +pci:v00001093d0000741C* + ID_MODEL_FROM_DATABASE=PXI-5691 + +pci:v00001093d0000741D* + ID_MODEL_FROM_DATABASE=PXI-5695 + +pci:v00001093d0000743C* + ID_MODEL_FROM_DATABASE=CSC-3059 + +pci:v00001093d00007448* + ID_MODEL_FROM_DATABASE=PXI-2510 + +pci:v00001093d00007454* + ID_MODEL_FROM_DATABASE=PXI-2512 + +pci:v00001093d00007455* + ID_MODEL_FROM_DATABASE=PXI-2514 + +pci:v00001093d00007456* + ID_MODEL_FROM_DATABASE=PXIe-2512 + +pci:v00001093d00007457* + ID_MODEL_FROM_DATABASE=PXIe-2514 + +pci:v00001093d0000745A* + ID_MODEL_FROM_DATABASE=PXI-6682H + +pci:v00001093d0000745E* + ID_MODEL_FROM_DATABASE=PXI-5153EX + +pci:v00001093d0000745F* + ID_MODEL_FROM_DATABASE=PCI-5153EX + +pci:v00001093d00007460* + ID_MODEL_FROM_DATABASE=PXI-5154EX + +pci:v00001093d00007461* + ID_MODEL_FROM_DATABASE=PCI-5154EX + +pci:v00001093d0000746D* + ID_MODEL_FROM_DATABASE=PXIe-5650 + +pci:v00001093d0000746E* + ID_MODEL_FROM_DATABASE=PXIe-5651 + +pci:v00001093d0000746F* + ID_MODEL_FROM_DATABASE=PXIe-5652 + +pci:v00001093d00007472* + ID_MODEL_FROM_DATABASE=PXI-2800 + +pci:v00001093d00007495* + ID_MODEL_FROM_DATABASE=PXIe-5603 + +pci:v00001093d00007497* + ID_MODEL_FROM_DATABASE=PXIe-5605 + +pci:v00001093d000074AE* + ID_MODEL_FROM_DATABASE=PXIe-2515 + +pci:v00001093d000074B4* + ID_MODEL_FROM_DATABASE=PXI-2531 + +pci:v00001093d000074B5* + ID_MODEL_FROM_DATABASE=PXIe-2531 + +pci:v00001093d000074C1* + ID_MODEL_FROM_DATABASE=PXIe-8430/16 (RS-232) Interface + +pci:v00001093d000074C2* + ID_MODEL_FROM_DATABASE=PXIe-8430/8 (RS-232) Interface + +pci:v00001093d000074C3* + ID_MODEL_FROM_DATABASE=PXIe-8431/16 (RS-485) Interface + +pci:v00001093d000074C4* + ID_MODEL_FROM_DATABASE=PXIe-8431/8 (RS-485) Interface + +pci:v00001093d000074D5* + ID_MODEL_FROM_DATABASE=PXIe-5630 + +pci:v00001093d000074D9* + ID_MODEL_FROM_DATABASE=PCIe-8432/2 (Isolated RS-232) Interface + +pci:v00001093d000074DA* + ID_MODEL_FROM_DATABASE=PCIe-8433/2 (Isolated RS-485) Interface + +pci:v00001093d000074DB* + ID_MODEL_FROM_DATABASE=PCIe-8432/4 (Isolated RS-232) Interface + +pci:v00001093d000074DC* + ID_MODEL_FROM_DATABASE=PCIe-8433/4 (Isolated RS-485) Interface + +pci:v00001093d000074E8* + ID_MODEL_FROM_DATABASE=NI 9148 + +pci:v00001093d00007515* + ID_MODEL_FROM_DATABASE=PCIe-8430/2 (RS-232) Interface + +pci:v00001093d00007516* + ID_MODEL_FROM_DATABASE=PCIe-8430/4 (RS-232) Interface + +pci:v00001093d00007517* + ID_MODEL_FROM_DATABASE=PCIe-8431/2 (RS-485) Interface + +pci:v00001093d00007518* + ID_MODEL_FROM_DATABASE=PCIe-8431/4 (RS-485) Interface + +pci:v00001093d0000751B* + ID_MODEL_FROM_DATABASE=cRIO-9081 + +pci:v00001093d0000751C* + ID_MODEL_FROM_DATABASE=cRIO-9082 + +pci:v00001093d00007528* + ID_MODEL_FROM_DATABASE=PXIe-4497 + +pci:v00001093d00007529* + ID_MODEL_FROM_DATABASE=PXIe-4499 + +pci:v00001093d0000752A* + ID_MODEL_FROM_DATABASE=PXIe-4492 + +pci:v00001093d00007539* + ID_MODEL_FROM_DATABASE=NI 9157 + +pci:v00001093d0000753A* + ID_MODEL_FROM_DATABASE=NI 9159 + +pci:v00001093d00007598* + ID_MODEL_FROM_DATABASE=PXI-2571 + +pci:v00001093d000075A4* + ID_MODEL_FROM_DATABASE=PXI-4131A + +pci:v00001093d000075B1* + ID_MODEL_FROM_DATABASE=PCIe-7854R + +pci:v00001093d000075BA* + ID_MODEL_FROM_DATABASE=PXI-2543 + +pci:v00001093d000075BB* + ID_MODEL_FROM_DATABASE=PXIe-2543 + +pci:v00001093d000075E5* + ID_MODEL_FROM_DATABASE=PXI-6683 + +pci:v00001093d000075E6* + ID_MODEL_FROM_DATABASE=PXI-6683H + +pci:v00001093d000075EF* + ID_MODEL_FROM_DATABASE=PXIe-5632 + +pci:v00001093d0000761C* + ID_MODEL_FROM_DATABASE=VXI-8360LT + +pci:v00001093d0000761F* + ID_MODEL_FROM_DATABASE=PXI-2540 + +pci:v00001093d00007620* + ID_MODEL_FROM_DATABASE=PXIe-2540 + +pci:v00001093d00007621* + ID_MODEL_FROM_DATABASE=PXI-2541 + +pci:v00001093d00007622* + ID_MODEL_FROM_DATABASE=PXIe-2541 + +pci:v00001093d00007626* + ID_MODEL_FROM_DATABASE=NI 9154 + +pci:v00001093d00007627* + ID_MODEL_FROM_DATABASE=NI 9155 + +pci:v00001093d00007638* + ID_MODEL_FROM_DATABASE=PXI-2720 + +pci:v00001093d00007639* + ID_MODEL_FROM_DATABASE=PXI-2722 + +pci:v00001093d0000763A* + ID_MODEL_FROM_DATABASE=PXIe-2725 + +pci:v00001093d0000763B* + ID_MODEL_FROM_DATABASE=PXIe-2727 + +pci:v00001093d0000763C* + ID_MODEL_FROM_DATABASE=PXI-4465 + +pci:v00001093d0000764B* + ID_MODEL_FROM_DATABASE=PXIe-2790 + +pci:v00001093d0000764C* + ID_MODEL_FROM_DATABASE=PXI-2520 + +pci:v00001093d0000764D* + ID_MODEL_FROM_DATABASE=PXI-2521 + +pci:v00001093d0000764E* + ID_MODEL_FROM_DATABASE=PXI-2522 + +pci:v00001093d0000764F* + ID_MODEL_FROM_DATABASE=PXI-2523 + +pci:v00001093d00007654* + ID_MODEL_FROM_DATABASE=PXI-2796 + +pci:v00001093d00007655* + ID_MODEL_FROM_DATABASE=PXI-2797 + +pci:v00001093d00007656* + ID_MODEL_FROM_DATABASE=PXI-2798 + +pci:v00001093d00007657* + ID_MODEL_FROM_DATABASE=PXI-2799 + +pci:v00001093d0000765D* + ID_MODEL_FROM_DATABASE=PXI-2542 + +pci:v00001093d0000765E* + ID_MODEL_FROM_DATABASE=PXIe-2542 + +pci:v00001093d0000765F* + ID_MODEL_FROM_DATABASE=PXI-2544 + +pci:v00001093d00007660* + ID_MODEL_FROM_DATABASE=PXIe-2544 + +pci:v00001093d0000766D* + ID_MODEL_FROM_DATABASE=PCIe-6535B + +pci:v00001093d0000766E* + ID_MODEL_FROM_DATABASE=PCIe-6536B + +pci:v00001093d0000766F* + ID_MODEL_FROM_DATABASE=PCIe-6537B + +pci:v00001093d000076A3* + ID_MODEL_FROM_DATABASE=PXIe-6535B + +pci:v00001093d000076A4* + ID_MODEL_FROM_DATABASE=PXIe-6536B + +pci:v00001093d000076A5* + ID_MODEL_FROM_DATABASE=PXIe-6537B + +pci:v00001093d0000783E* + ID_MODEL_FROM_DATABASE=PXI-8368 + +pci:v00001093d00009020* + ID_MODEL_FROM_DATABASE=PXI-2501 + +pci:v00001093d00009030* + ID_MODEL_FROM_DATABASE=PXI-2503 + +pci:v00001093d00009040* + ID_MODEL_FROM_DATABASE=PXI-2527 + +pci:v00001093d00009050* + ID_MODEL_FROM_DATABASE=PXI-2565 + +pci:v00001093d00009060* + ID_MODEL_FROM_DATABASE=PXI-2590 + +pci:v00001093d00009070* + ID_MODEL_FROM_DATABASE=PXI-2591 + +pci:v00001093d00009080* + ID_MODEL_FROM_DATABASE=PXI-2580 + +pci:v00001093d00009090* + ID_MODEL_FROM_DATABASE=PCI-4021 + +pci:v00001093d000090A0* + ID_MODEL_FROM_DATABASE=PXI-4021 + +pci:v00001093d0000A001* + ID_MODEL_FROM_DATABASE=PCI-MXI-2 + +pci:v00001093d0000B001* + ID_MODEL_FROM_DATABASE=PCI-1408 + +pci:v00001093d0000B011* + ID_MODEL_FROM_DATABASE=PXI-1408 + +pci:v00001093d0000B021* + ID_MODEL_FROM_DATABASE=PCI-1424 + +pci:v00001093d0000B022* + ID_MODEL_FROM_DATABASE=PXI-1424 + +pci:v00001093d0000B031* + ID_MODEL_FROM_DATABASE=PCI-1413 + +pci:v00001093d0000B041* + ID_MODEL_FROM_DATABASE=PCI-1407 + +pci:v00001093d0000B051* + ID_MODEL_FROM_DATABASE=PXI-1407 + +pci:v00001093d0000B061* + ID_MODEL_FROM_DATABASE=PCI-1411 + +pci:v00001093d0000B071* + ID_MODEL_FROM_DATABASE=PCI-1422 + +pci:v00001093d0000B081* + ID_MODEL_FROM_DATABASE=PXI-1422 + +pci:v00001093d0000B091* + ID_MODEL_FROM_DATABASE=PXI-1411 + +pci:v00001093d0000B0B1* + ID_MODEL_FROM_DATABASE=PCI-1409 + +pci:v00001093d0000B0C1* + ID_MODEL_FROM_DATABASE=PXI-1409 + +pci:v00001093d0000B0E1* + ID_MODEL_FROM_DATABASE=PCI-1428 + +pci:v00001093d0000C4C4* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device + +pci:v00001093d0000C4C4sv00001093sd0000728A* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5421) + +pci:v00001093d0000C4C4sv00001093sd0000728B* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5442) + +pci:v00001093d0000C4C4sv00001093sd0000728D* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5451) + +pci:v00001093d0000C4C4sv00001093sd000072A2* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5122) + +pci:v00001093d0000C4C4sv00001093sd000072DA* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5422) + +pci:v00001093d0000C4C4sv00001093sd000072F7* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6535) + +pci:v00001093d0000C4C4sv00001093sd000072F8* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6536) + +pci:v00001093d0000C4C4sv00001093sd000072F9* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6537) + +pci:v00001093d0000C4C4sv00001093sd00007326* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6509) + +pci:v00001093d0000C4C4sv00001093sd0000736C* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4140) + +pci:v00001093d0000C4C4sv00001093sd0000738B* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5622) + +pci:v00001093d0000C4C4sv00001093sd000073C4* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5450) + +pci:v00001093d0000C4C4sv00001093sd000073C7* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6545) + +pci:v00001093d0000C4C4sv00001093sd000073D4* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6544) + +pci:v00001093d0000C4C4sv00001093sd00007425* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6320) + +pci:v00001093d0000C4C4sv00001093sd00007427* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6321) + +pci:v00001093d0000C4C4sv00001093sd00007428* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6323) + +pci:v00001093d0000C4C4sv00001093sd00007429* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6323) + +pci:v00001093d0000C4C4sv00001093sd0000742A* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6341) + +pci:v00001093d0000C4C4sv00001093sd0000742B* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6341) + +pci:v00001093d0000C4C4sv00001093sd0000742C* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6343) + +pci:v00001093d0000C4C4sv00001093sd0000742D* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6343) + +pci:v00001093d0000C4C4sv00001093sd0000742F* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6351) + +pci:v00001093d0000C4C4sv00001093sd00007431* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6353) + +pci:v00001093d0000C4C4sv00001093sd00007432* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6361) + +pci:v00001093d0000C4C4sv00001093sd00007433* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6361) + +pci:v00001093d0000C4C4sv00001093sd00007434* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6363) + +pci:v00001093d0000C4C4sv00001093sd00007435* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6363) + +pci:v00001093d0000C4C4sv00001093sd00007436* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6356) + +pci:v00001093d0000C4C4sv00001093sd00007437* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6358) + +pci:v00001093d0000C4C4sv00001093sd00007438* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6366) + +pci:v00001093d0000C4C4sv00001093sd00007439* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6368) + +pci:v00001093d0000C4C4sv00001093sd00007468* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5185) + +pci:v00001093d0000C4C4sv00001093sd00007469* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5186) + +pci:v00001093d0000C4C4sv00001093sd00007492* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4300) + +pci:v00001093d0000C4C4sv00001093sd00007498* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6548) + +pci:v00001093d0000C4C4sv00001093sd00007499* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6547) + +pci:v00001093d0000C4C4sv00001093sd000074A8* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4330) + +pci:v00001093d0000C4C4sv00001093sd000074A9* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4331) + +pci:v00001093d0000C4C4sv00001093sd000074B1* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4154) + +pci:v00001093d0000C4C4sv00001093sd000074B2* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4353) + +pci:v00001093d0000C4C4sv00001093sd000074B6* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-1433) + +pci:v00001093d0000C4C4sv00001093sd000074CD* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5643R) + +pci:v00001093d0000C4C4sv00001093sd000074D0* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7961R) + +pci:v00001093d0000C4C4sv00001093sd000074DD* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6376) + +pci:v00001093d0000C4C4sv00001093sd000074DE* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6378) + +pci:v00001093d0000C4C4sv00001093sd000074E2* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7962R) + +pci:v00001093d0000C4C4sv00001093sd000074E3* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7965R) + +pci:v00001093d0000C4C4sv00001093sd000074E5* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4844) + +pci:v00001093d0000C4C4sv00001093sd000074F3* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-5140) + +pci:v00001093d0000C4C4sv00001093sd0000753C* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-1435) + +pci:v00001093d0000C4C4sv00001093sd00007548* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5622 (25MHz DDC)) + +pci:v00001093d0000C4C4sv00001093sd0000754D* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-5155) + +pci:v00001093d0000C4C4sv00001093sd00007551* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6556) + +pci:v00001093d0000C4C4sv00001093sd00007553* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-1473R) + +pci:v00001093d0000C4C4sv00001093sd00007570* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-1474R) + +pci:v00001093d0000C4C4sv00001093sd00007571* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-1475R) + +pci:v00001093d0000C4C4sv00001093sd00007572* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-1476R) + +pci:v00001093d0000C4C4sv00001093sd000075A2* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5693) + +pci:v00001093d0000C4C4sv00001093sd000075A3* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5694) + +pci:v00001093d0000C4C4sv00001093sd000075A5* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4141) + +pci:v00001093d0000C4C4sv00001093sd000075CE* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7966R) + +pci:v00001093d0000C4C4sv00001093sd000075CF* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4357) + +pci:v00001093d0000C4C4sv00001093sd000075D2* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-RevB-5643R) + +pci:v00001093d0000C4C4sv00001093sd000075D3* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5644R) + +pci:v00001093d0000C4C4sv00001093sd000075EE* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5645R) + +pci:v00001093d0000C4C4sv00001093sd00007613* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6555) + +pci:v00001093d0000C4C4sv00001093sd00007619* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5185) + +pci:v00001093d0000C4C4sv00001093sd0000761A* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5186) + +pci:v00001093d0000C4C4sv00001093sd00007629* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4142) + +pci:v00001093d0000C4C4sv00001093sd0000762A* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4143) + +pci:v00001093d0000C4C4sv00001093sd0000762B* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4138) + +pci:v00001093d0000C4C4sv00001093sd0000762C* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4144) + +pci:v00001093d0000C4C4sv00001093sd0000762D* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4145) + +pci:v00001093d0000C4C4sv00001093sd0000762E* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5606) + +pci:v00001093d0000C4C4sv00001093sd00007644* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4841) + +pci:v00001093d0000C4C4sv00001093sd0000764A* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-8237R-S) + +pci:v00001093d0000C4C4sv00001093sd00007658* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5162 (4CH)) + +pci:v00001093d0000C4C4sv00001093sd000076AB* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4322) + +pci:v00001093d0000C4C4sv00001093sd000076AD* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4112) + +pci:v00001093d0000C4C4sv00001093sd000076AE* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4113) + +pci:v00001093d0000C4C4sv00001093sd000076B5* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7971R) + +pci:v00001093d0000C4C4sv00001093sd000076B6* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7972R) + +pci:v00001093d0000C4C4sv00001093sd000076B7* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7975R) + +pci:v00001093d0000C4C4sv00001093sd000076B8* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5696) + +pci:v00001093d0000C4C4sv00001093sd000076B9* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5654) + +pci:v00001093d0000C4C4sv00001093sd000076C8* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6614) + +pci:v00001093d0000C4C4sv00001093sd000076C9* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6612) + +pci:v00001093d0000C4C4sv00001093sd000076CB* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5646R) + +pci:v00001093d0000C4C4sv00001093sd000076CC* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5162 (2CH)) + +pci:v00001093d0000C4C4sv00001093sd000076CE* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (CVS-1459) + +pci:v00001093d0000C4C4sv00001093sd000076D0* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5160 (2CH)) + +pci:v00001093d0000C4C4sv00001093sd000076D1* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5160 (4CH)) + +pci:v00001093d0000C4C4sv00001093sd000076DC* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4610) + +pci:v00001093d0000C4C4sv00001093sd000076EC* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2524) + +pci:v00001093d0000C4C4sv00001093sd000076ED* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2525) + +pci:v00001093d0000C4C4sv00001093sd000076EE* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2526) + +pci:v00001093d0000C4C4sv00001093sd000076EF* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2737) + +pci:v00001093d0000C4C4sv00001093sd000076F0* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2738) + +pci:v00001093d0000C4C4sv00001093sd000076F1* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2739) + +pci:v00001093d0000C4C4sv00001093sd000076FB* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-1473R-LX110) + +pci:v00001093d0000C4C4sv00001093sd000076FC* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5105) + +pci:v00001093d0000C4C4sv00001093sd000076FD* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5114) + +pci:v00001093d0000C4C4sv00001093sd000076FE* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5644R) + +pci:v00001093d0000C4C4sv00001093sd000076FF* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5644R) + +pci:v00001093d0000C4C4sv00001093sd00007700* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5644R) + +pci:v00001093d0000C4C4sv00001093sd00007701* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5645R) + +pci:v00001093d0000C4C4sv00001093sd00007702* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5645R) + +pci:v00001093d0000C4C4sv00001093sd00007703* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5645R) + +pci:v00001093d0000C4C4sv00001093sd0000770C* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4139) + +pci:v00001093d0000C4C4sv00001093sd00007711* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4464) + +pci:v00001093d0000C4C4sv00001093sd00007712* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4463) + +pci:v00001093d0000C4C4sv00001093sd00007716* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PCIe-6612) + +pci:v00001093d0000C4C4sv00001093sd0000771D* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (Unconfigured CA4 Switch) + +pci:v00001093d0000C4C4sv00001093sd0000771E* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4339) + +pci:v00001093d0000C4C4sv00001093sd00007735* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9033) + +pci:v00001093d0000C4C4sv00001093sd0000773E* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R) + +pci:v00001093d0000C4C4sv00001093sd0000774B* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9031) + +pci:v00001093d0000C4C4sv00001093sd0000774D* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9034) + +pci:v00001093d0000C4C4sv00001093sd00007755* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9030) + +pci:v00001093d0000C4C4sv00001093sd00007768* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2747) + +pci:v00001093d0000C4C4sv00001093sd00007769* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2748) + +pci:v00001093d0000C4C4sv00001093sd0000776A* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-2746) + +pci:v00001093d0000C4C4sv00001093sd00007777* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7976R) + +pci:v00001093d0000C4C4sv00001093sd00007782* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5646R) + +pci:v00001093d0000C4C4sv00001093sd00007783* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5646R) + +pci:v00001093d0000C4C4sv00001093sd00007784* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5646R) + +pci:v00001093d0000C4C4sv00001093sd00007790* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5170R (4CH)) + +pci:v00001093d0000C4C4sv00001093sd00007791* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5170R (8CH)) + +pci:v00001093d0000C4C4sv00001093sd00007793* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5171R (8CH)) + +pci:v00001093d0000C4C4sv00001093sd000077A5* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6345) + +pci:v00001093d0000C4C4sv00001093sd000077A6* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6355) + +pci:v00001093d0000C4C4sv00001093sd000077A7* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6365) + +pci:v00001093d0000C4C4sv00001093sd000077A8* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6375) + +pci:v00001093d0000C4C4sv00001093sd000077AA* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (CVS-1458) + +pci:v00001093d0000C4C4sv00001093sd000077AD* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (IC-3173) + +pci:v00001093d0000C4C4sv00001093sd000077B4* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7820R) + +pci:v00001093d0000C4C4sv00001093sd000077B5* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7821R) + +pci:v00001093d0000C4C4sv00001093sd000077B6* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7822R) + +pci:v00001093d0000C4C4sv00001093sd000077B9* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9038) + +pci:v00001093d0000C4C4sv00001093sd000077BA* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4136) + +pci:v00001093d0000C4C4sv00001093sd000077BB* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4137) + +pci:v00001093d0000C4C4sv00001093sd000077C0* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R) + +pci:v00001093d0000C4C4sv00001093sd000077C1* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R) + +pci:v00001093d0000C4C4sv00001093sd000077C2* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-5624R) + +pci:v00001093d0000C4C4sv00001093sd000077CA* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6738) + +pci:v00001093d0000C4C4sv00001093sd000077CB* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-6739) + +pci:v00001093d0000C4C4sv00001093sd000077DB* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9035) + +pci:v00001093d0000C4C4sv00001093sd000077DC* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9036) + +pci:v00001093d0000C4C4sv00001093sd000077DD* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (cRIO-9039) + +pci:v00001093d0000C4C4sv00001093sd00007802* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4302) + +pci:v00001093d0000C4C4sv00001093sd00007803* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4303) + +pci:v00001093d0000C4C4sv00001093sd00007805* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4305) + +pci:v00001093d0000C4C4sv00001093sd0000786F* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4163) + +pci:v00001093d0000C4C4sv00001093sd0000788E* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4304) + +pci:v00001093d0000C4C4sv00001093sd000078F8* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (NI FlexRIO Module (KU035)) + +pci:v00001093d0000C4C4sv00001093sd000078F9* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (NI FlexRIO Module (KU040)) + +pci:v00001093d0000C4C4sv00001093sd000078FA* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (NI FlexRIO Module (KU060)) + +pci:v00001093d0000C4C4sv00001093sd000078FF* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-4162) + +pci:v00001093d0000C4C4sv00001093sd00007995* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7911R) + +pci:v00001093d0000C4C4sv00001093sd00007996* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7912R) + +pci:v00001093d0000C4C4sv00001093sd00007997* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (PXIe-7915R) + +pci:v00001093d0000C4C4sv00001093sd000079D3* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (NI FlexRIO PCIe Module (KU035)) + +pci:v00001093d0000C4C4sv00001093sd000079D4* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (NI FlexRIO PCIe Module (KU040)) + +pci:v00001093d0000C4C4sv00001093sd000079D5* + ID_MODEL_FROM_DATABASE=PXIe/PCIe Device (NI FlexRIO PCIe Module (KU060)) + +pci:v00001093d0000C801* + ID_MODEL_FROM_DATABASE=PCI-GPIB + +pci:v00001093d0000C811* + ID_MODEL_FROM_DATABASE=PCI-GPIB+ + +pci:v00001093d0000C821* + ID_MODEL_FROM_DATABASE=PXI-GPIB + +pci:v00001093d0000C831* + ID_MODEL_FROM_DATABASE=PMC-GPIB + +pci:v00001093d0000C840* + ID_MODEL_FROM_DATABASE=PCI-GPIB + +pci:v00001093d0000D130* + ID_MODEL_FROM_DATABASE=PCI-232/2 Interface + +pci:v00001093d0000D140* + ID_MODEL_FROM_DATABASE=PCI-232/4 Interface + +pci:v00001093d0000D150* + ID_MODEL_FROM_DATABASE=PCI-232/8 Interface + +pci:v00001093d0000D160* + ID_MODEL_FROM_DATABASE=PCI-485/2 Interface + +pci:v00001093d0000D170* + ID_MODEL_FROM_DATABASE=PCI-485/4 Interface + +pci:v00001093d0000D190* + ID_MODEL_FROM_DATABASE=PXI-8422/2 (Isolated RS-232) Interface + +pci:v00001093d0000D1A0* + ID_MODEL_FROM_DATABASE=PXI-8422/4 (Isolated RS-232) Interface + +pci:v00001093d0000D1B0* + ID_MODEL_FROM_DATABASE=PXI-8423/2 (Isolated RS-485) Interface + +pci:v00001093d0000D1C0* + ID_MODEL_FROM_DATABASE=PXI-8423/4 (Isolated RS-485) Interface + +pci:v00001093d0000D1D0* + ID_MODEL_FROM_DATABASE=PXI-8420/2 (RS-232) Interface + +pci:v00001093d0000D1E0* + ID_MODEL_FROM_DATABASE=PXI-8420/4 (RS-232) Interface + +pci:v00001093d0000D1F0* + ID_MODEL_FROM_DATABASE=PXI-8420/8 (RS-232) Interface + +pci:v00001093d0000D1F1* + ID_MODEL_FROM_DATABASE=PXI-8420/16 (RS-232) Interface + +pci:v00001093d0000D230* + ID_MODEL_FROM_DATABASE=PXI-8421/2 (RS-485) Interface + +pci:v00001093d0000D240* + ID_MODEL_FROM_DATABASE=PXI-8421/4 (RS-485) Interface + +pci:v00001093d0000D250* + ID_MODEL_FROM_DATABASE=PCI-232/2 (Isolated) Interface + +pci:v00001093d0000D260* + ID_MODEL_FROM_DATABASE=PCI-485/2 (Isolated) Interface + +pci:v00001093d0000D270* + ID_MODEL_FROM_DATABASE=PCI-232/4 (Isolated) Interface + +pci:v00001093d0000D280* + ID_MODEL_FROM_DATABASE=PCI-485/4 (Isolated) Interface + +pci:v00001093d0000D290* + ID_MODEL_FROM_DATABASE=PCI-485/8 Interface + +pci:v00001093d0000D2A0* + ID_MODEL_FROM_DATABASE=PXI-8421/8 (RS-485) Interface + +pci:v00001093d0000D2B0* + ID_MODEL_FROM_DATABASE=PCI-232/16 Interface + +pci:v00001093d0000E111* + ID_MODEL_FROM_DATABASE=PCI-CAN + +pci:v00001093d0000E131* + ID_MODEL_FROM_DATABASE=PXI-8461 (1 port) + +pci:v00001093d0000E141* + ID_MODEL_FROM_DATABASE=PCI-CAN/LS + +pci:v00001093d0000E151* + ID_MODEL_FROM_DATABASE=PXI-8460 (1 port) + +pci:v00001093d0000E211* + ID_MODEL_FROM_DATABASE=PCI-CAN/2 + +pci:v00001093d0000E231* + ID_MODEL_FROM_DATABASE=PXI-8461 (2 ports) + +pci:v00001093d0000E241* + ID_MODEL_FROM_DATABASE=PCI-CAN/LS2 + +pci:v00001093d0000E251* + ID_MODEL_FROM_DATABASE=PXI-8460 (2 ports) + +pci:v00001093d0000E261* + ID_MODEL_FROM_DATABASE=PCI-CAN/DS + +pci:v00001093d0000E271* + ID_MODEL_FROM_DATABASE=PXI-8462 + +pci:v00001093d0000F110* + ID_MODEL_FROM_DATABASE=VMEpc-650 + +pci:v00001093d0000F120* + ID_MODEL_FROM_DATABASE=VXIpc-650 + +pci:v00001093d0000FE00* + ID_MODEL_FROM_DATABASE=VXIpc-87x + +pci:v00001093d0000FE41* + ID_MODEL_FROM_DATABASE=VXIpc-860 + +pci:v00001093d0000FE51* + ID_MODEL_FROM_DATABASE=VXIpc-74x + +pci:v00001093d0000FE61* + ID_MODEL_FROM_DATABASE=VXIpc-850 + +pci:v00001093d0000FE70* + ID_MODEL_FROM_DATABASE=VXIpc-880 + +pci:v00001094* + ID_VENDOR_FROM_DATABASE=First International Computers [FIC] + +pci:v00001095* + ID_VENDOR_FROM_DATABASE=Silicon Image, Inc. + +pci:v00001095d00000240* + ID_MODEL_FROM_DATABASE=Adaptec AAR-1210SA SATA HostRAID Controller + +pci:v00001095d00000640* + ID_MODEL_FROM_DATABASE=PCI0640 + +pci:v00001095d00000643* + ID_MODEL_FROM_DATABASE=PCI0643 + +pci:v00001095d00000646* + ID_MODEL_FROM_DATABASE=PCI0646 + +pci:v00001095d00000647* + ID_MODEL_FROM_DATABASE=PCI0647 + +pci:v00001095d00000648* + ID_MODEL_FROM_DATABASE=PCI0648 + +pci:v00001095d00000648sv00001043sd00008025* + ID_MODEL_FROM_DATABASE=PCI0648 (CUBX motherboard) + +pci:v00001095d00000649* + ID_MODEL_FROM_DATABASE=SiI 0649 Ultra ATA/100 PCI to ATA Host Controller + +pci:v00001095d00000649sv00000E11sd0000005D* + ID_MODEL_FROM_DATABASE=SiI 0649 Ultra ATA/100 PCI to ATA Host Controller (Integrated Ultra ATA-100 Dual Channel Controller) + +pci:v00001095d00000649sv00000E11sd0000007E* + ID_MODEL_FROM_DATABASE=SiI 0649 Ultra ATA/100 PCI to ATA Host Controller (Integrated Ultra ATA-100 IDE RAID Controller) + +pci:v00001095d00000649sv0000101Esd00000649* + ID_MODEL_FROM_DATABASE=SiI 0649 Ultra ATA/100 PCI to ATA Host Controller (AMI MegaRAID IDE 100 Controller) + +pci:v00001095d00000650* + ID_MODEL_FROM_DATABASE=PBC0650A + +pci:v00001095d00000670* + ID_MODEL_FROM_DATABASE=USB0670 + +pci:v00001095d00000670sv00001095sd00000670* + ID_MODEL_FROM_DATABASE=USB0670 + +pci:v00001095d00000673* + ID_MODEL_FROM_DATABASE=USB0673 + +pci:v00001095d00000680* + ID_MODEL_FROM_DATABASE=PCI0680 Ultra ATA-133 Host Controller + +pci:v00001095d00000680sv00001095sd00000680* + ID_MODEL_FROM_DATABASE=PCI0680 Ultra ATA-133 Host Controller (SiI 0680 ATA/133 Controller) + +pci:v00001095d00000680sv00001095sd00003680* + ID_MODEL_FROM_DATABASE=PCI0680 Ultra ATA-133 Host Controller (Winic W-680 (Silicon Image 680 based)) + +pci:v00001095d00003112* + ID_MODEL_FROM_DATABASE=SiI 3112 [SATALink/SATARaid] Serial ATA Controller + +pci:v00001095d00003112sv00001095sd00003112* + ID_MODEL_FROM_DATABASE=SiI 3112 [SATALink/SATARaid] Serial ATA Controller (SiI 3112 SATALink Controller) + +pci:v00001095d00003112sv00001095sd00006112* + ID_MODEL_FROM_DATABASE=SiI 3112 [SATALink/SATARaid] Serial ATA Controller (SiI 3112 SATARaid Controller) + +pci:v00001095d00003112sv00009005sd00000250* + ID_MODEL_FROM_DATABASE=SiI 3112 [SATALink/SATARaid] Serial ATA Controller (SATAConnect 1205SA Host Controller) + +pci:v00001095d00003114* + ID_MODEL_FROM_DATABASE=SiI 3114 [SATALink/SATARaid] Serial ATA Controller + +pci:v00001095d00003114sv00001043sd00008167* + ID_MODEL_FROM_DATABASE=SiI 3114 [SATALink/SATARaid] Serial ATA Controller (A8N-SLI Deluxe/Premium Mainboard) + +pci:v00001095d00003114sv00001095sd00003114* + ID_MODEL_FROM_DATABASE=SiI 3114 [SATALink/SATARaid] Serial ATA Controller (SiI 3114 SATALink Controller) + +pci:v00001095d00003114sv00001095sd00006114* + ID_MODEL_FROM_DATABASE=SiI 3114 [SATALink/SATARaid] Serial ATA Controller (SiI 3114 SATARaid Controller) + +pci:v00001095d00003124* + ID_MODEL_FROM_DATABASE=SiI 3124 PCI-X Serial ATA Controller + +pci:v00001095d00003124sv00001095sd00003124* + ID_MODEL_FROM_DATABASE=SiI 3124 PCI-X Serial ATA Controller + +pci:v00001095d00003132* + ID_MODEL_FROM_DATABASE=SiI 3132 Serial ATA Raid II Controller + +pci:v00001095d00003512* + ID_MODEL_FROM_DATABASE=SiI 3512 [SATALink/SATARaid] Serial ATA Controller + +pci:v00001095d00003512sv00001095sd00003512* + ID_MODEL_FROM_DATABASE=SiI 3512 [SATALink/SATARaid] Serial ATA Controller (SiI 3512 SATALink Controller) + +pci:v00001095d00003512sv00001095sd00006512* + ID_MODEL_FROM_DATABASE=SiI 3512 [SATALink/SATARaid] Serial ATA Controller (SiI 3512 SATARaid Controller) + +pci:v00001095d00003531* + ID_MODEL_FROM_DATABASE=SiI 3531 [SATALink/SATARaid] Serial ATA Controller + +pci:v00001095d00003531sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=SiI 3531 [SATALink/SATARaid] Serial ATA Controller (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00001096* + ID_VENDOR_FROM_DATABASE=Alacron + +pci:v00001097* + ID_VENDOR_FROM_DATABASE=Appian Technology + +pci:v00001098* + ID_VENDOR_FROM_DATABASE=Quantum Designs (H.K.) Ltd + +pci:v00001098d00000001* + ID_MODEL_FROM_DATABASE=QD-8500 + +pci:v00001098d00000002* + ID_MODEL_FROM_DATABASE=QD-8580 + +pci:v00001099* + ID_VENDOR_FROM_DATABASE=Samsung Electronics Co., Ltd + +pci:v0000109A* + ID_VENDOR_FROM_DATABASE=Packard Bell + +pci:v0000109B* + ID_VENDOR_FROM_DATABASE=Gemlight Computer Ltd. + +pci:v0000109C* + ID_VENDOR_FROM_DATABASE=Megachips Corporation + +pci:v0000109D* + ID_VENDOR_FROM_DATABASE=Zida Technologies Ltd. + +pci:v0000109E* + ID_VENDOR_FROM_DATABASE=Brooktree Corporation + +pci:v0000109Ed00000310* + ID_MODEL_FROM_DATABASE=Bt848 Video Capture + +pci:v0000109Ed0000032E* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture + +pci:v0000109Ed00000350* + ID_MODEL_FROM_DATABASE=Bt848 Video Capture + +pci:v0000109Ed00000351* + ID_MODEL_FROM_DATABASE=Bt849A Video capture + +pci:v0000109Ed00000369* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture + +pci:v0000109Ed00000369sv00001002sd00000001* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (TV-Wonder) + +pci:v0000109Ed00000369sv00001002sd00000003* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (TV-Wonder/VE) + +pci:v0000109Ed0000036C* + ID_MODEL_FROM_DATABASE=Bt879(??) Video Capture + +pci:v0000109Ed0000036Csv000013E9sd00000070* + ID_MODEL_FROM_DATABASE=Bt879(??) Video Capture (Win/TV (Video Section)) + +pci:v0000109Ed0000036E* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture + +pci:v0000109Ed0000036Esv00000000sd00000001* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Euresys Picolo PCIe) + +pci:v0000109Ed0000036Esv00000070sd000013EB* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (WinTV Series) + +pci:v0000109Ed0000036Esv00000070sd0000FF01* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Viewcast Osprey 200) + +pci:v0000109Ed0000036Esv00000071sd00000101* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (DigiTV PCI) + +pci:v0000109Ed0000036Esv0000107Dsd00006606* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (WinFast TV 2000) + +pci:v0000109Ed0000036Esv000011BDsd00000012* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (PCTV pro (TV + FM stereo receiver)) + +pci:v0000109Ed0000036Esv000011BDsd0000001C* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (PCTV Sat (DBC receiver)) + +pci:v0000109Ed0000036Esv0000127Asd00000001* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878 Mediastream Controller NTSC) + +pci:v0000109Ed0000036Esv0000127Asd00000002* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878 Mediastream Controller PAL BG) + +pci:v0000109Ed0000036Esv0000127Asd00000003* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878a Mediastream Controller PAL BG) + +pci:v0000109Ed0000036Esv0000127Asd00000048* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878/832 Mediastream Controller) + +pci:v0000109Ed0000036Esv0000144Fsd00003000* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (MagicTView CPH060 - Video) + +pci:v0000109Ed0000036Esv00001461sd00000002* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (TV98 Series (TV/No FM/Remote)) + +pci:v0000109Ed0000036Esv00001461sd00000003* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (AverMedia UltraTV PCI 350) + +pci:v0000109Ed0000036Esv00001461sd00000004* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (AVerTV WDM Video Capture) + +pci:v0000109Ed0000036Esv00001461sd00000761* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (AverTV DVB-T) + +pci:v0000109Ed0000036Esv00001461sd00000771* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (AverMedia AVerTV DVB-T 771) + +pci:v0000109Ed0000036Esv000014F1sd00000001* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878 Mediastream Controller NTSC) + +pci:v0000109Ed0000036Esv000014F1sd00000002* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878 Mediastream Controller PAL BG) + +pci:v0000109Ed0000036Esv000014F1sd00000003* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878a Mediastream Controller PAL BG) + +pci:v0000109Ed0000036Esv000014F1sd00000048* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Bt878/832 Mediastream Controller) + +pci:v0000109Ed0000036Esv00001822sd00000001* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (VisionPlus DVB card) + +pci:v0000109Ed0000036Esv00001851sd00001850* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (FlyVideo'98 - Video) + +pci:v0000109Ed0000036Esv00001851sd00001851* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (FlyVideo II) + +pci:v0000109Ed0000036Esv00001852sd00001852* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (FlyVideo'98 - Video (with FM Tuner)) + +pci:v0000109Ed0000036Esv000018ACsd0000D500* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (DViCO FusionHDTV5 Lite) + +pci:v0000109Ed0000036Esv0000270Fsd0000FC00* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Digitop DTT-1000) + +pci:v0000109Ed0000036Esv0000AA00sd00001460* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardA Input0) + +pci:v0000109Ed0000036Esv0000AA01sd00001461* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardA Input1) + +pci:v0000109Ed0000036Esv0000AA02sd00001462* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardA Input2) + +pci:v0000109Ed0000036Esv0000AA03sd00001463* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardA Input3) + +pci:v0000109Ed0000036Esv0000AA04sd00001464* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardB Input0) + +pci:v0000109Ed0000036Esv0000AA05sd00001465* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardB Input1) + +pci:v0000109Ed0000036Esv0000AA06sd00001466* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardB Input2) + +pci:v0000109Ed0000036Esv0000AA07sd00001467* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardB Input3) + +pci:v0000109Ed0000036Esv0000AA08sd00001468* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardC Input0) + +pci:v0000109Ed0000036Esv0000AA09sd00001469* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardC Input1) + +pci:v0000109Ed0000036Esv0000AA0Asd0000146A* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardC Input2) + +pci:v0000109Ed0000036Esv0000AA0Bsd0000146B* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardC Input3) + +pci:v0000109Ed0000036Esv0000AA0Csd0000146C* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardD Input0) + +pci:v0000109Ed0000036Esv0000AA0Dsd0000146D* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardD Input1) + +pci:v0000109Ed0000036Esv0000AA0Esd0000146E* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardD Input2) + +pci:v0000109Ed0000036Esv0000AA0Fsd0000146F* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (Spectra8 CardD Input3) + +pci:v0000109Ed0000036Esv0000BD11sd00001200* + ID_MODEL_FROM_DATABASE=Bt878 Video Capture (PCTV pro (TV + FM stereo receiver)) + +pci:v0000109Ed0000036F* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture + +pci:v0000109Ed0000036Fsv0000127Asd00000044* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) + +pci:v0000109Ed0000036Fsv0000127Asd00000122* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL I) + +pci:v0000109Ed0000036Fsv0000127Asd00000144* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) + +pci:v0000109Ed0000036Fsv0000127Asd00000222* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL BG) + +pci:v0000109Ed0000036Fsv0000127Asd00000244* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture NTSC) + +pci:v0000109Ed0000036Fsv0000127Asd00000322* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) + +pci:v0000109Ed0000036Fsv0000127Asd00000422* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) + +pci:v0000109Ed0000036Fsv0000127Asd00001122* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL I) + +pci:v0000109Ed0000036Fsv0000127Asd00001222* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL BG) + +pci:v0000109Ed0000036Fsv0000127Asd00001322* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) + +pci:v0000109Ed0000036Fsv0000127Asd00001522* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture PAL I) + +pci:v0000109Ed0000036Fsv0000127Asd00001622* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture PAL BG) + +pci:v0000109Ed0000036Fsv0000127Asd00001722* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture NTSC) + +pci:v0000109Ed0000036Fsv000014F1sd00000044* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) + +pci:v0000109Ed0000036Fsv000014F1sd00000122* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL I) + +pci:v0000109Ed0000036Fsv000014F1sd00000144* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) + +pci:v0000109Ed0000036Fsv000014F1sd00000222* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL BG) + +pci:v0000109Ed0000036Fsv000014F1sd00000244* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture NTSC) + +pci:v0000109Ed0000036Fsv000014F1sd00000322* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) + +pci:v0000109Ed0000036Fsv000014F1sd00000422* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) + +pci:v0000109Ed0000036Fsv000014F1sd00001122* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL I) + +pci:v0000109Ed0000036Fsv000014F1sd00001222* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (PAL BG) + +pci:v0000109Ed0000036Fsv000014F1sd00001322* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (NTSC) + +pci:v0000109Ed0000036Fsv000014F1sd00001522* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture PAL I) + +pci:v0000109Ed0000036Fsv000014F1sd00001622* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture PAL BG) + +pci:v0000109Ed0000036Fsv000014F1sd00001722* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (Bt879a Video Capture NTSC) + +pci:v0000109Ed0000036Fsv00001851sd00001850* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (FlyVideo'98 - Video) + +pci:v0000109Ed0000036Fsv00001851sd00001851* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (FlyVideo II) + +pci:v0000109Ed0000036Fsv00001852sd00001852* + ID_MODEL_FROM_DATABASE=Bt879 Video Capture (FlyVideo'98 - Video (with FM Tuner)) + +pci:v0000109Ed00000370* + ID_MODEL_FROM_DATABASE=Bt880 Video Capture + +pci:v0000109Ed00000370sv00001851sd00001850* + ID_MODEL_FROM_DATABASE=Bt880 Video Capture (FlyVideo'98) + +pci:v0000109Ed00000370sv00001851sd00001851* + ID_MODEL_FROM_DATABASE=Bt880 Video Capture (FlyVideo'98 EZ - video) + +pci:v0000109Ed00000370sv00001852sd00001852* + ID_MODEL_FROM_DATABASE=Bt880 Video Capture (FlyVideo'98 (with FM Tuner)) + +pci:v0000109Ed00000878* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture + +pci:v0000109Ed00000878sv00000000sd00000001* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Euresys Picolo PCIe) + +pci:v0000109Ed00000878sv00000070sd000013EB* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (WinTV Series) + +pci:v0000109Ed00000878sv00000070sd0000FF01* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Viewcast Osprey 200) + +pci:v0000109Ed00000878sv00000071sd00000101* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (DigiTV PCI) + +pci:v0000109Ed00000878sv00001002sd00000001* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (TV-Wonder) + +pci:v0000109Ed00000878sv00001002sd00000003* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (TV-Wonder/VE) + +pci:v0000109Ed00000878sv000011BDsd00000012* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (PCTV pro (TV + FM stereo receiver, audio section)) + +pci:v0000109Ed00000878sv000011BDsd0000001C* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (PCTV Sat (DBC receiver)) + +pci:v0000109Ed00000878sv0000127Asd00000001* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) + +pci:v0000109Ed00000878sv0000127Asd00000002* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) + +pci:v0000109Ed00000878sv0000127Asd00000003* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) + +pci:v0000109Ed00000878sv0000127Asd00000048* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) + +pci:v0000109Ed00000878sv000013E9sd00000070* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Win/TV (Audio Section)) + +pci:v0000109Ed00000878sv0000144Fsd00003000* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (MagicTView CPH060 - Audio) + +pci:v0000109Ed00000878sv00001461sd00000002* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Avermedia PCTV98 Audio Capture) + +pci:v0000109Ed00000878sv00001461sd00000003* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (UltraTV PCI 350) + +pci:v0000109Ed00000878sv00001461sd00000004* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (AVerTV WDM Audio Capture) + +pci:v0000109Ed00000878sv00001461sd00000761* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (AVerTV DVB-T) + +pci:v0000109Ed00000878sv00001461sd00000771* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (AverMedia AVerTV DVB-T 771) + +pci:v0000109Ed00000878sv000014F1sd00000001* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) + +pci:v0000109Ed00000878sv000014F1sd00000002* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) + +pci:v0000109Ed00000878sv000014F1sd00000003* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) + +pci:v0000109Ed00000878sv000014F1sd00000048* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Bt878 Video Capture (Audio Section)) + +pci:v0000109Ed00000878sv00001822sd00000001* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (VisionPlus DVB Card) + +pci:v0000109Ed00000878sv000018ACsd0000D500* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (DViCO FusionHDTV5 Lite) + +pci:v0000109Ed00000878sv0000270Fsd0000FC00* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (Digitop DTT-1000) + +pci:v0000109Ed00000878sv0000BD11sd00001200* + ID_MODEL_FROM_DATABASE=Bt878 Audio Capture (PCTV pro (TV + FM stereo receiver, audio section)) + +pci:v0000109Ed00000879* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture + +pci:v0000109Ed00000879sv0000127Asd00000044* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00000122* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00000144* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00000222* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00000244* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00000322* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00000422* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00001122* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00001222* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00001322* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00001522* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00001622* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv0000127Asd00001722* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00000044* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00000122* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00000144* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00000222* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00000244* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00000322* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00000422* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00001122* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00001222* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00001322* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00001522* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00001622* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000879sv000014F1sd00001722* + ID_MODEL_FROM_DATABASE=Bt879 Audio Capture (Bt879 Video Capture (Audio Section)) + +pci:v0000109Ed00000880* + ID_MODEL_FROM_DATABASE=Bt880 Audio Capture + +pci:v0000109Ed00002115* + ID_MODEL_FROM_DATABASE=BtV 2115 Mediastream controller + +pci:v0000109Ed00002125* + ID_MODEL_FROM_DATABASE=BtV 2125 Mediastream controller + +pci:v0000109Ed00002164* + ID_MODEL_FROM_DATABASE=BtV 2164 + +pci:v0000109Ed00002165* + ID_MODEL_FROM_DATABASE=BtV 2165 + +pci:v0000109Ed00008230* + ID_MODEL_FROM_DATABASE=Bt8230 ATM Segment/Reassembly Ctrlr (SRC) + +pci:v0000109Ed00008472* + ID_MODEL_FROM_DATABASE=Bt8472 + +pci:v0000109Ed00008474* + ID_MODEL_FROM_DATABASE=Bt8474 + +pci:v0000109F* + ID_VENDOR_FROM_DATABASE=Trigem Computer Inc. + +pci:v000010A0* + ID_VENDOR_FROM_DATABASE=Meidensha Corporation + +pci:v000010A1* + ID_VENDOR_FROM_DATABASE=Juko Electronics Ind. Co. Ltd + +pci:v000010A2* + ID_VENDOR_FROM_DATABASE=Quantum Corporation + +pci:v000010A3* + ID_VENDOR_FROM_DATABASE=Everex Systems Inc + +pci:v000010A4* + ID_VENDOR_FROM_DATABASE=Globe Manufacturing Sales + +pci:v000010A5* + ID_VENDOR_FROM_DATABASE=Smart Link Ltd. + +pci:v000010A5d00003052* + ID_MODEL_FROM_DATABASE=SmartPCI562 56K Modem + +pci:v000010A5d00005449* + ID_MODEL_FROM_DATABASE=SmartPCI561 modem + +pci:v000010A6* + ID_VENDOR_FROM_DATABASE=Informtech Industrial Ltd. + +pci:v000010A7* + ID_VENDOR_FROM_DATABASE=Benchmarq Microelectronics + +pci:v000010A8* + ID_VENDOR_FROM_DATABASE=Sierra Semiconductor + +pci:v000010A8d00000000* + ID_MODEL_FROM_DATABASE=STB Horizon 64 + +pci:v000010A9* + ID_VENDOR_FROM_DATABASE=Silicon Graphics Intl. Corp. + +pci:v000010A9d00000001* + ID_MODEL_FROM_DATABASE=Crosstalk to PCI Bridge + +pci:v000010A9d00000002* + ID_MODEL_FROM_DATABASE=Linc I/O controller + +pci:v000010A9d00000003* + ID_MODEL_FROM_DATABASE=IOC3 I/O controller + +pci:v000010A9d00000004* + ID_MODEL_FROM_DATABASE=O2 MACE + +pci:v000010A9d00000005* + ID_MODEL_FROM_DATABASE=RAD Audio + +pci:v000010A9d00000006* + ID_MODEL_FROM_DATABASE=HPCEX + +pci:v000010A9d00000007* + ID_MODEL_FROM_DATABASE=RPCEX + +pci:v000010A9d00000008* + ID_MODEL_FROM_DATABASE=DiVO VIP + +pci:v000010A9d00000009* + ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet + +pci:v000010A9d00000009sv000010A9sd00008002* + ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet + +pci:v000010A9d00000010* + ID_MODEL_FROM_DATABASE=AMP Video I/O + +pci:v000010A9d00000011* + ID_MODEL_FROM_DATABASE=GRIP + +pci:v000010A9d00000012* + ID_MODEL_FROM_DATABASE=SGH PSHAC GSN + +pci:v000010A9d00000208* + ID_MODEL_FROM_DATABASE=SSIM1 SAS Adapter + +pci:v000010A9d00001001* + ID_MODEL_FROM_DATABASE=Magic Carpet + +pci:v000010A9d00001002* + ID_MODEL_FROM_DATABASE=Lithium + +pci:v000010A9d00001003* + ID_MODEL_FROM_DATABASE=Dual JPEG 1 + +pci:v000010A9d00001004* + ID_MODEL_FROM_DATABASE=Dual JPEG 2 + +pci:v000010A9d00001005* + ID_MODEL_FROM_DATABASE=Dual JPEG 3 + +pci:v000010A9d00001006* + ID_MODEL_FROM_DATABASE=Dual JPEG 4 + +pci:v000010A9d00001007* + ID_MODEL_FROM_DATABASE=Dual JPEG 5 + +pci:v000010A9d00001008* + ID_MODEL_FROM_DATABASE=Cesium + +pci:v000010A9d0000100A* + ID_MODEL_FROM_DATABASE=IOC4 I/O controller + +pci:v000010A9d00001504* + ID_MODEL_FROM_DATABASE=SSIM1 Fibre Channel Adapter + +pci:v000010A9d00002001* + ID_MODEL_FROM_DATABASE=Fibre Channel + +pci:v000010A9d00002002* + ID_MODEL_FROM_DATABASE=ASDE + +pci:v000010A9d00004001* + ID_MODEL_FROM_DATABASE=TIO-CE PCI Express Bridge + +pci:v000010A9d00004002* + ID_MODEL_FROM_DATABASE=TIO-CE PCI Express Port + +pci:v000010A9d00008001* + ID_MODEL_FROM_DATABASE=O2 1394 + +pci:v000010A9d00008002* + ID_MODEL_FROM_DATABASE=G-net NT + +pci:v000010A9d0000802B* + ID_MODEL_FROM_DATABASE=REACT external interrupt controller + +pci:v000010AA* + ID_VENDOR_FROM_DATABASE=ACC Microelectronics + +pci:v000010AAd00000000* + ID_MODEL_FROM_DATABASE=ACCM 2188 + +pci:v000010AAd00002051* + ID_MODEL_FROM_DATABASE=2051 CPU bridge + +pci:v000010AAd00005842* + ID_MODEL_FROM_DATABASE=2051 ISA bridge + +pci:v000010AB* + ID_VENDOR_FROM_DATABASE=Digicom + +pci:v000010AC* + ID_VENDOR_FROM_DATABASE=Honeywell IAC + +pci:v000010AD* + ID_VENDOR_FROM_DATABASE=Symphony Labs + +pci:v000010ADd00000001* + ID_MODEL_FROM_DATABASE=W83769F + +pci:v000010ADd00000003* + ID_MODEL_FROM_DATABASE=SL82C103 + +pci:v000010ADd00000005* + ID_MODEL_FROM_DATABASE=SL82C105 + +pci:v000010ADd00000103* + ID_MODEL_FROM_DATABASE=SL82c103 + +pci:v000010ADd00000105* + ID_MODEL_FROM_DATABASE=SL82c105 + +pci:v000010ADd00000565* + ID_MODEL_FROM_DATABASE=W83C553F/W83C554F + +pci:v000010AE* + ID_VENDOR_FROM_DATABASE=Cornerstone Technology + +pci:v000010AF* + ID_VENDOR_FROM_DATABASE=Micro Computer Systems Inc + +pci:v000010B0* + ID_VENDOR_FROM_DATABASE=CardExpert Technology + +pci:v000010B1* + ID_VENDOR_FROM_DATABASE=Cabletron Systems Inc + +pci:v000010B2* + ID_VENDOR_FROM_DATABASE=Raytheon Company + +pci:v000010B3* + ID_VENDOR_FROM_DATABASE=Databook Inc + +pci:v000010B3d00003106* + ID_MODEL_FROM_DATABASE=DB87144 + +pci:v000010B3d0000B106* + ID_MODEL_FROM_DATABASE=DB87144 + +pci:v000010B4* + ID_VENDOR_FROM_DATABASE=STB Systems Inc + +pci:v000010B4d00001B1D* + ID_MODEL_FROM_DATABASE=Velocity 128 3D + +pci:v000010B4d00001B1Dsv000010B4sd0000237E* + ID_MODEL_FROM_DATABASE=Velocity 128 3D (Velocity 4400) + +pci:v000010B5* + ID_VENDOR_FROM_DATABASE=PLX Technology, Inc. + +pci:v000010B5d00000001* + ID_MODEL_FROM_DATABASE=i960 PCI bus interface + +pci:v000010B5d00000557* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d00000557sv000010B5sd00009030* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Digium Tormenta 2 T400P-SS7 or E400P-SS7 Quad T1 or E1 PCI card) + +pci:v000010B5d00001000* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d00001000sv000010B5sd00009030* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (ATCOM AT400P Quad T1 PCI card) + +pci:v000010B5d00001024* + ID_MODEL_FROM_DATABASE=Acromag, Inc. IndustryPack Carrier Card + +pci:v000010B5d00001042* + ID_MODEL_FROM_DATABASE=Brandywine / jxi2, Inc. - PMC-SyncClock32, IRIG A & B, Nasa 36 + +pci:v000010B5d0000106A* + ID_MODEL_FROM_DATABASE=Dual OX16C952 4 port serial adapter [Megawolf Romulus/4] + +pci:v000010B5d00001076* + ID_MODEL_FROM_DATABASE=VScom 800 8 port serial adaptor + +pci:v000010B5d00001077* + ID_MODEL_FROM_DATABASE=VScom 400 4 port serial adaptor + +pci:v000010B5d00001078* + ID_MODEL_FROM_DATABASE=VScom 210 2 port serial and 1 port parallel adaptor + +pci:v000010B5d00001103* + ID_MODEL_FROM_DATABASE=VScom 200 2 port serial adaptor + +pci:v000010B5d00001146* + ID_MODEL_FROM_DATABASE=VScom 010 1 port parallel adaptor + +pci:v000010B5d00001147* + ID_MODEL_FROM_DATABASE=VScom 020 2 port parallel adaptor + +pci:v000010B5d00002000* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d00002000sv000010B5sd00009030* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (ATCOM AE400P Quad E1 PCI card) + +pci:v000010B5d00002540* + ID_MODEL_FROM_DATABASE=IXXAT CAN-Interface PC-I 04/PCI + +pci:v000010B5d00002724* + ID_MODEL_FROM_DATABASE=Thales PCSM Security Card + +pci:v000010B5d00003376* + ID_MODEL_FROM_DATABASE=Cosateq 4 Port CAN Card + +pci:v000010B5d00004000* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d00004000sv000010B5sd00009030* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Tormenta 3 Varion V400P/ATCOM TE400P Quad E1/T1/J1 PCI card) + +pci:v000010B5d00004001* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d00004001sv000010B5sd00009030* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (ATCOM A400PE Quad E1 PCI card) + +pci:v000010B5d00004002* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d00004002sv000010B5sd00009030* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (ATCOM A400PT Quad T1 PCI card) + +pci:v000010B5d00006140* + ID_MODEL_FROM_DATABASE=PCI6140 32-bit 33MHz PCI-to-PCI Bridge + +pci:v000010B5d00006150* + ID_MODEL_FROM_DATABASE=PCI6150 32-bit 33MHz PCI-to-PCI Bridge + +pci:v000010B5d00006152* + ID_MODEL_FROM_DATABASE=PCI6152 32-bit 66MHz PCI-to-PCI Bridge + +pci:v000010B5d00006154* + ID_MODEL_FROM_DATABASE=PCI6154 64-bit 66MHz PCI-to-PCI Bridge + +pci:v000010B5d00006254* + ID_MODEL_FROM_DATABASE=PCI6254 64-bit 66MHz PCI-to-PCI Bridge + +pci:v000010B5d00006466* + ID_MODEL_FROM_DATABASE=PCI6466 64-bit 66MHz PCI-to-PCI Bridge + +pci:v000010B5d00006520* + ID_MODEL_FROM_DATABASE=PCI6520 64-bit 133MHz PCI-X-to-PCI-X Bridge + +pci:v000010B5d00006540* + ID_MODEL_FROM_DATABASE=PCI6540 64-bit 133MHz PCI-X-to-PCI-X Bridge + +pci:v000010B5d00006540sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=PCI6540 64-bit 133MHz PCI-X-to-PCI-X Bridge (CR11 Single Board Computer) + +pci:v000010B5d00006540sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=PCI6540 64-bit 133MHz PCI-X-to-PCI-X Bridge (PSL09 PrPMC) + +pci:v000010B5d00006541* + ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, primary side) + +pci:v000010B5d00006541sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, primary side) (CR11 Single Board Computer) + +pci:v000010B5d00006541sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, primary side) (PSL09 PrPMC) + +pci:v000010B5d00006542* + ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, secondary side) + +pci:v000010B5d00006542sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, secondary side) (CR11 Single Board Computer) + +pci:v000010B5d00006542sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=PCI6540/6466 PCI-PCI bridge (non-transparent mode, secondary side) (PSL09 PrPMC) + +pci:v000010B5d00008111* + ID_MODEL_FROM_DATABASE=PEX 8111 PCI Express-to-PCI Bridge + +pci:v000010B5d00008112* + ID_MODEL_FROM_DATABASE=PEX8112 x1 Lane PCI Express-to-PCI Bridge + +pci:v000010B5d00008114* + ID_MODEL_FROM_DATABASE=PEX 8114 PCI Express-to-PCI/PCI-X Bridge + +pci:v000010B5d00008311* + ID_MODEL_FROM_DATABASE=PEX8311 x1 Lane PCI Express-to-Generic Local Bus Bridge + +pci:v000010B5d00008505* + ID_MODEL_FROM_DATABASE=PEX 8505 5-lane, 5-port PCI Express Switch + +pci:v000010B5d00008508* + ID_MODEL_FROM_DATABASE=PEX 8508 8-lane, 5-port PCI Express Switch + +pci:v000010B5d00008509* + ID_MODEL_FROM_DATABASE=PEX 8509 8-lane, 8-port PCI Express Switch + +pci:v000010B5d00008512* + ID_MODEL_FROM_DATABASE=PEX 8512 12-lane, 5-port PCI Express Switch + +pci:v000010B5d00008516* + ID_MODEL_FROM_DATABASE=PEX 8516 Versatile PCI Express Switch + +pci:v000010B5d00008517* + ID_MODEL_FROM_DATABASE=PEX 8517 16-lane, 5-port PCI Express Switch + +pci:v000010B5d00008518* + ID_MODEL_FROM_DATABASE=PEX 8518 16-lane, 5-port PCI Express Switch + +pci:v000010B5d00008524* + ID_MODEL_FROM_DATABASE=PEX 8524 24-lane, 6-port PCI Express Switch + +pci:v000010B5d00008525* + ID_MODEL_FROM_DATABASE=PEX 8525 24-lane, 5-port PCI Express Switch + +pci:v000010B5d00008532* + ID_MODEL_FROM_DATABASE=PEX 8532 Versatile PCI Express Switch + +pci:v000010B5d00008533* + ID_MODEL_FROM_DATABASE=PEX 8533 32-lane, 6-port PCI Express Switch + +pci:v000010B5d00008547* + ID_MODEL_FROM_DATABASE=PEX 8547 48-lane, 3-port PCI Express Switch + +pci:v000010B5d00008548* + ID_MODEL_FROM_DATABASE=PEX 8548 48-lane, 9-port PCI Express Switch + +pci:v000010B5d00008603* + ID_MODEL_FROM_DATABASE=PEX 8603 3-lane, 3-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008604* + ID_MODEL_FROM_DATABASE=PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008605* + ID_MODEL_FROM_DATABASE=PEX 8605 PCI Express 4-port Gen2 Switch + +pci:v000010B5d00008606* + ID_MODEL_FROM_DATABASE=PEX 8606 6 Lane, 6 Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008608* + ID_MODEL_FROM_DATABASE=PEX 8608 8-lane, 8-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008609* + ID_MODEL_FROM_DATABASE=PEX 8609 8-lane, 8-Port PCI Express Gen 2 (5.0 GT/s) Switch with DMA + +pci:v000010B5d00008612* + ID_MODEL_FROM_DATABASE=PEX 8612 12-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008613* + ID_MODEL_FROM_DATABASE=PEX 8613 12-lane, 3-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008614* + ID_MODEL_FROM_DATABASE=PEX 8614 12-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008615* + ID_MODEL_FROM_DATABASE=PEX 8615 12-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch with DMA + +pci:v000010B5d00008616* + ID_MODEL_FROM_DATABASE=PEX 8616 16-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008617* + ID_MODEL_FROM_DATABASE=PEX 8617 16-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch with P2P + +pci:v000010B5d00008618* + ID_MODEL_FROM_DATABASE=PEX 8618 16-lane, 16-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008619* + ID_MODEL_FROM_DATABASE=PEX 8619 16-lane, 16-Port PCI Express Gen 2 (5.0 GT/s) Switch with DMA + +pci:v000010B5d00008624* + ID_MODEL_FROM_DATABASE=PEX 8624 24-lane, 6-Port PCI Express Gen 2 (5.0 GT/s) Switch [ExpressLane] + +pci:v000010B5d00008624sv000013A3sd00001845* + ID_MODEL_FROM_DATABASE=PEX 8624 24-lane, 6-Port PCI Express Gen 2 (5.0 GT/s) Switch [ExpressLane] (DX1845 Acceleration Card) + +pci:v000010B5d00008625* + ID_MODEL_FROM_DATABASE=PEX 8625 24-lane, 24-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008632* + ID_MODEL_FROM_DATABASE=PEX 8632 32-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008636* + ID_MODEL_FROM_DATABASE=PEX 8636 36-lane, 24-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008647* + ID_MODEL_FROM_DATABASE=PEX 8647 48-Lane, 3-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008648* + ID_MODEL_FROM_DATABASE=PEX 8648 48-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008649* + ID_MODEL_FROM_DATABASE=PEX 8649 48-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008664* + ID_MODEL_FROM_DATABASE=PEX 8664 64-lane, 16-Port PCI Express Gen 2 (5.0 GT/s) Switch + +pci:v000010B5d00008680* + ID_MODEL_FROM_DATABASE=PEX 8680 80-lane, 20-Port PCI Express Gen 2 (5.0 GT/s) Multi-Root Switch + +pci:v000010B5d00008696* + ID_MODEL_FROM_DATABASE=PEX 8696 96-lane, 24-Port PCI Express Gen 2 (5.0 GT/s) Multi-Root Switch + +pci:v000010B5d00008717* + ID_MODEL_FROM_DATABASE=PEX 8717 16-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch with DMA + +pci:v000010B5d00008718* + ID_MODEL_FROM_DATABASE=PEX 8718 16-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch + +pci:v000010B5d00008724* + ID_MODEL_FROM_DATABASE=PEX 8724 24-Lane, 6-Port PCI Express Gen 3 (8 GT/s) Switch, 19 x 19mm FCBGA + +pci:v000010B5d00008732* + ID_MODEL_FROM_DATABASE=PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch + +pci:v000010B5d00008734* + ID_MODEL_FROM_DATABASE=PEX 8734 32-lane, 8-Port PCI Express Gen 3 (8.0GT/s) Switch + +pci:v000010B5d00008747* + ID_MODEL_FROM_DATABASE=PEX 8747 48-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch + +pci:v000010B5d00008748* + ID_MODEL_FROM_DATABASE=PEX 8748 48-Lane, 12-Port PCI Express Gen 3 (8 GT/s) Switch, 27 x 27mm FCBGA + +pci:v000010B5d000087B0* + ID_MODEL_FROM_DATABASE=PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch + +pci:v000010B5d000087B0sv00001093sd00007761* + ID_MODEL_FROM_DATABASE=PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch (PXIe-8830mc) + +pci:v000010B5d00009016* + ID_MODEL_FROM_DATABASE=PLX 9016 8-port serial controller + +pci:v000010B5d00009030* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d00009030sv000010B5sd00002695* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Hilscher CIF50-PB/DPS Profibus) + +pci:v000010B5d00009030sv000010B5sd00002862* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI LV (3V/5V): Timecode Reader Board) + +pci:v000010B5d00009030sv000010B5sd00002906* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCI TS (3V/5V): Time Synchronisation Board) + +pci:v000010B5d00009030sv000010B5sd00002940* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI D (3V/5V): Timecode Reader Board) + +pci:v000010B5d00009030sv000010B5sd00002977* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (IXXAT iPC-I XC16/PCI CAN Board) + +pci:v000010B5d00009030sv000010B5sd00002978* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (SH ARC-PCIu/SH ARC-PCI104/SH ARC-PCIe SOHARD ARCNET card) + +pci:v000010B5d00009030sv000010B5sd00003025* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI L (3V/5V): Timecode Reader Board) + +pci:v000010B5d00009030sv000010B5sd00003068* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI HD (3V/5V): Timecode Reader Board) + +pci:v000010B5d00009030sv000010B5sd00003463* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI D (v2) (3V/5V): Timecode Reader Board) + +pci:v000010B5d00009030sv000010B5sd00003591* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PLURA PCL PCI L (v2) (3.3V/5V): Time Code Reader Board) + +pci:v000010B5d00009030sv000012FEsd00000111* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (CPCI-ASIO4 (ESD 4-port Serial Interface Board)) + +pci:v000010B5d00009030sv00001369sd00009C01* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (VX222v2) + +pci:v000010B5d00009030sv00001369sd00009D01* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (VX222-Mic) + +pci:v000010B5d00009030sv00001369sd00009D02* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (VX222-Mic) + +pci:v000010B5d00009030sv00001369sd00009E01* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PCX924v2) + +pci:v000010B5d00009030sv00001369sd00009F01* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PCX924-Mic) + +pci:v000010B5d00009030sv00001369sd00009F02* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PCX924-Mic) + +pci:v000010B5d00009030sv00001369sd0000A001* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (PCX22v2) + +pci:v000010B5d00009030sv00001369sd0000A701* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (LCM220v2) + +pci:v000010B5d00009030sv00001369sd0000A801* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (LCM200) + +pci:v000010B5d00009030sv00001397sd00003136* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (4xS0-ISDN PCI Adapter) + +pci:v000010B5d00009030sv00001397sd00003137* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (S2M-E1-ISDN PCI Adapter) + +pci:v000010B5d00009030sv00001518sd00000200* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (ThinkIO-C) + +pci:v000010B5d00009030sv000015EDsd00001002* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (MCCS 8-port Serial Hot Swap) + +pci:v000010B5d00009030sv000015EDsd00001003* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (MCCS 16-port Serial Hot Swap) + +pci:v000010B5d00009030sv0000E1C5sd00000001* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (TE1-PCI) + +pci:v000010B5d00009030sv0000E1C5sd00000005* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (TA1-PCI) + +pci:v000010B5d00009030sv0000E1C5sd00000006* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (TA1-PCI4) + +pci:v000010B5d00009036* + ID_MODEL_FROM_DATABASE=9036 + +pci:v000010B5d00009050* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge + +pci:v000010B5d00009050sv000010B5sd00001067* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IXXAT CAN i165) + +pci:v000010B5d00009050sv000010B5sd0000114E* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Wasco WITIO PCI168extended) + +pci:v000010B5d00009050sv000010B5sd00001169* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Wasco OPTOIO32standard 32 digital in, 32 digital out) + +pci:v000010B5d00009050sv000010B5sd00001172* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IK220 (Heidenhain)) + +pci:v000010B5d00009050sv000010B5sd00002036* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (SatPak GPS) + +pci:v000010B5d00009050sv000010B5sd00002221* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI LV: Timecode Reader Board) + +pci:v000010B5d00009050sv000010B5sd00002273* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (SH ARC-PCI SOHARD ARCNET card) + +pci:v000010B5d00009050sv000010B5sd00002431* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Alpermann+Velte PCL PCI D: Timecode Reader Board) + +pci:v000010B5d00009050sv000010B5sd00002905* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Alpermann+Velte PCI TS: Time Synchronisation Board) + +pci:v000010B5d00009050sv000010B5sd00003196* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Goramo PLX200SYN sync serial card) + +pci:v000010B5d00009050sv000010B5sd00009050* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCI-I04 PCI Passive PC/CAN Interface) + +pci:v000010B5d00009050sv00001369sd00008901* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCX11+ PCI) + +pci:v000010B5d00009050sv00001369sd00008F01* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (VX222) + +pci:v000010B5d00009050sv00001369sd00009401* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCX924) + +pci:v000010B5d00009050sv00001369sd00009501* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCX22) + +pci:v000010B5d00009050sv00001498sd00000362* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (TPMC866 8 Channel Serial Card) + +pci:v000010B5d00009050sv00001522sd00000001* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce 4 Port V.90 Data/Fax/Voice Modem) + +pci:v000010B5d00009050sv00001522sd00000002* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce 2 Port V.90 Data/Fax/Voice Modem) + +pci:v000010B5d00009050sv00001522sd00000003* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce 6 Port V.90 Data/Fax/Voice Modem) + +pci:v000010B5d00009050sv00001522sd00000004* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce 8 Port V.90 Data/Fax/Voice Modem) + +pci:v000010B5d00009050sv00001522sd00000010* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce2000 4 Port V.90 Data/Fax/Voice Modem) + +pci:v000010B5d00009050sv00001522sd00000020* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce2000 2 Port V.90 Data/Fax/Voice Modem) + +pci:v000010B5d00009050sv000015EDsd00001000* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Macrolink MCCS 8-port Serial) + +pci:v000010B5d00009050sv000015EDsd00001001* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Macrolink MCCS 16-port Serial) + +pci:v000010B5d00009050sv000015EDsd00001002* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Macrolink MCCS 8-port Serial Hot Swap) + +pci:v000010B5d00009050sv000015EDsd00001003* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (Macrolink MCCS 16-port Serial Hot Swap) + +pci:v000010B5d00009050sv00005654sd00002036* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (OpenSwitch 6 Telephony card) + +pci:v000010B5d00009050sv00005654sd00003132* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (OpenSwitch 12 Telephony card) + +pci:v000010B5d00009050sv00005654sd00005634* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (OpenLine4 Telephony Card) + +pci:v000010B5d00009050sv0000D531sd0000C002* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (PCIntelliCAN 2xSJA1000 CAN bus) + +pci:v000010B5d00009050sv0000D84Dsd00004006* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4006 1P) + +pci:v000010B5d00009050sv0000D84Dsd00004008* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4008 1P EPP/ECP) + +pci:v000010B5d00009050sv0000D84Dsd00004014* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4014 2P) + +pci:v000010B5d00009050sv0000D84Dsd00004018* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4018 3P EPP/ECP) + +pci:v000010B5d00009050sv0000D84Dsd00004025* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4025 1S(16C550) RS-232) + +pci:v000010B5d00009050sv0000D84Dsd00004027* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4027 1S(16C650) RS-232) + +pci:v000010B5d00009050sv0000D84Dsd00004028* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4028 1S(16C850) RS-232) + +pci:v000010B5d00009050sv0000D84Dsd00004036* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4036 2S(16C650) RS-232) + +pci:v000010B5d00009050sv0000D84Dsd00004037* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4037 2S(16C650) RS-232) + +pci:v000010B5d00009050sv0000D84Dsd00004038* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4038 2S(16C850) RS-232) + +pci:v000010B5d00009050sv0000D84Dsd00004052* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4052 1S(16C550) RS-422/485) + +pci:v000010B5d00009050sv0000D84Dsd00004053* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4053 2S(16C550) RS-422/485) + +pci:v000010B5d00009050sv0000D84Dsd00004055* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4055 4S(16C550) RS-232) + +pci:v000010B5d00009050sv0000D84Dsd00004058* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4055 4S(16C650) RS-232) + +pci:v000010B5d00009050sv0000D84Dsd00004065* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4065 8S(16C550) RS-232) + +pci:v000010B5d00009050sv0000D84Dsd00004068* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4068 8S(16C650) RS-232) + +pci:v000010B5d00009050sv0000D84Dsd00004078* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (EX-4078 2S(16C552) RS-232+1P) + +pci:v000010B5d00009052* + ID_MODEL_FROM_DATABASE=PCI9052 PCI <-> IOBus Bridge + +pci:v000010B5d00009054* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d00009054sv000010B5sd00002455* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Wessex Techology PHIL-PCI) + +pci:v000010B5d00009054sv000010B5sd00002696* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Innes Corp AM Radcap card) + +pci:v000010B5d00009054sv000010B5sd00002717* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Innes Corp Auricon card) + +pci:v000010B5d00009054sv000010B5sd00002844* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Innes Corp TVS Encoder card) + +pci:v000010B5d00009054sv000012C7sd00004001* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Intel Dialogic DM/V960-4T1 PCI) + +pci:v000010B5d00009054sv000012D9sd00000002* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PCI Prosody Card rev 1.5) + +pci:v000010B5d00009054sv000014B4sd0000D100* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Dektec DTA-100) + +pci:v000010B5d00009054sv000014B4sd0000D114* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (Dektec DTA-120) + +pci:v000010B5d00009054sv000016DFsd00000011* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA PrimeNet MM PCI) + +pci:v000010B5d00009054sv000016DFsd00000012* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA PrimeNet MM cPCI 8) + +pci:v000010B5d00009054sv000016DFsd00000013* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA PrimeNet MM cPCI 8 (without CAS Signaling)) + +pci:v000010B5d00009054sv000016DFsd00000014* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA PrimeNet MM cPCI 4) + +pci:v000010B5d00009054sv000016DFsd00000015* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA Daytona MM) + +pci:v000010B5d00009054sv000016DFsd00000016* + ID_MODEL_FROM_DATABASE=PCI9054 32-bit 33MHz PCI <-> IOBus Bridge (PIKA InLine MM) + +pci:v000010B5d00009056* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge + +pci:v000010B5d00009056sv000010B5sd00002979* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (CellinkBlade 11 - CPCI board VoATM AAL1) + +pci:v000010B5d00009056sv000010B5sd00003268* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (IXXAT iPC-I XC16/PCIe CAN Board) + +pci:v000010B5d00009056sv000010B5sd00003334* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Cambridge Pixel HPx Radar Input Card) + +pci:v000010B5d00009056sv000010B5sd00003352* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCIe HD: Timecode Reader Board) + +pci:v000010B5d00009056sv000010B5sd00003353* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCIe D: Timecode Reader Board) + +pci:v000010B5d00009056sv000010B5sd00003354* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCIe LV: Timecode Reader Board) + +pci:v000010B5d00009056sv000010B5sd00003355* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCIe L: Timecode Reader Board) + +pci:v000010B5d00009056sv000010B5sd00003415* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCIe TS: Time Synchronisation Board) + +pci:v000010B5d00009056sv000010B5sd00003493* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Alpermann+Velte PCL PCIe 3G: Timecode Reader Board) + +pci:v000010B5d00009056sv000010B5sd00003565* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Cambridge Pixel HPx Radar Output Card) + +pci:v000010B5d00009056sv00001369sd0000C001* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (LX6464ES) + +pci:v000010B5d00009056sv00001369sd0000C201* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (LX1616ES) + +pci:v000010B5d00009056sv000014B4sd0000D10A* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (DekTec DTA-110T) + +pci:v000010B5d00009056sv000014B4sd0000D128* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Dektec DTA-140) + +pci:v000010B5d00009056sv000014B4sd0000D140* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Dektec DTA-140) + +pci:v000010B5d00009056sv00001A0Esd0000006F* + ID_MODEL_FROM_DATABASE=PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (Dektec DTA-111) + +pci:v000010B5d00009060* + ID_MODEL_FROM_DATABASE=PCI9060 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d0000906D* + ID_MODEL_FROM_DATABASE=9060SD + +pci:v000010B5d0000906Dsv0000125Csd00000640* + ID_MODEL_FROM_DATABASE=9060SD (Aries 16000P) + +pci:v000010B5d0000906E* + ID_MODEL_FROM_DATABASE=9060ES + +pci:v000010B5d00009080* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d00009080sv0000103Csd000010EB* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge ((Agilent) E2777B 83K Series Optical Communication Interface) + +pci:v000010B5d00009080sv0000103Csd000010EC* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge ((Agilent) E6978-66442 PCI CIC) + +pci:v000010B5d00009080sv000010B5sd00001123* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (Sectra KK631 encryption board) + +pci:v000010B5d00009080sv000010B5sd00009080* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (9080 [real subsystem ID not set]) + +pci:v000010B5d00009080sv000012D9sd00000002* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (PCI Prosody Card) + +pci:v000010B5d00009080sv000012DFsd00004422* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (4422PCI ["Do-All" Telemetry Data Acquisition System]) + +pci:v000010B5d00009080sv00001369sd00009601* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (PCX822np) + +pci:v000010B5d00009080sv00001369sd0000A102* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (PCX822v2) + +pci:v000010B5d00009080sv00001369sd0000A201* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (PCX442) + +pci:v000010B5d00009080sv00001369sd0000A301* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (LCM440v2) + +pci:v000010B5d00009080sv00001369sd0000A401* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (VX822) + +pci:v000010B5d00009080sv00001369sd0000A402* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (VX822v2) + +pci:v000010B5d00009080sv00001369sd0000A901* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (LCM420) + +pci:v000010B5d00009080sv00001369sd0000AA01* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (VX820v2) + +pci:v000010B5d00009080sv00001517sd0000000B* + ID_MODEL_FROM_DATABASE=PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge (ECSG-1R3ADC-PMC Clock synthesizer) + +pci:v000010B5d00009656* + ID_MODEL_FROM_DATABASE=PCI9656 PCI <-> IOBus Bridge + +pci:v000010B5d00009656sv00001517sd0000000F* + ID_MODEL_FROM_DATABASE=PCI9656 PCI <-> IOBus Bridge (ECDR-GC314-PMC Receiver) + +pci:v000010B5d00009656sv00001885sd00000700* + ID_MODEL_FROM_DATABASE=PCI9656 PCI <-> IOBus Bridge (Tsunami FPGA PMC with Altera Stratix S40) + +pci:v000010B5d00009656sv00001885sd00000701* + ID_MODEL_FROM_DATABASE=PCI9656 PCI <-> IOBus Bridge (Tsunami FPGA PMC with Altera Stratix S30) + +pci:v000010B5d00009733* + ID_MODEL_FROM_DATABASE=PEX 9733 33-lane, 9-port PCI Express Gen 3 (8.0 GT/s) Switch + +pci:v000010B5d00009733sv00001D49sd00000001* + ID_MODEL_FROM_DATABASE=PEX 9733 33-lane, 9-port PCI Express Gen 3 (8.0 GT/s) Switch (ThinkSystem 1610-4P NVMe Switch Adapter) + +pci:v000010B5d00009733sv00001D49sd00000002* + ID_MODEL_FROM_DATABASE=PEX 9733 33-lane, 9-port PCI Express Gen 3 (8.0 GT/s) Switch (ThinkSystem 810-4P NVMe Switch Adapter) + +pci:v000010B5d00009749* + ID_MODEL_FROM_DATABASE=PEX 9749 49-lane, 13-port PCI Express Gen 3 (8.0 GT/s) Switch + +pci:v000010B5d00009749sv00001D49sd00000004* + ID_MODEL_FROM_DATABASE=PEX 9749 49-lane, 13-port PCI Express Gen 3 (8.0 GT/s) Switch (ThinkSystem 1610-8P NVMe Switch Adapter) + +pci:v000010B5d0000A100* + ID_MODEL_FROM_DATABASE=Blackmagic Design DeckLink + +pci:v000010B5d0000BB04* + ID_MODEL_FROM_DATABASE=B&B 3PCIOSD1A Isolated PCI Serial + +pci:v000010B5d0000C001* + ID_MODEL_FROM_DATABASE=CronyxOmega-PCI (8-port RS232) + +pci:v000010B5d0000D00D* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d0000D00Dsv000010B5sd00009030* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Digium Tormenta 2 T400P or E400P Quad T1 or E1 PCI card) + +pci:v000010B5d0000D33D* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d0000D33Dsv000010B5sd00009030* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Tormenta 3 Varion V401PT Quad T1/J1 PCI card) + +pci:v000010B5d0000D44D* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + +pci:v000010B5d0000D44Dsv000010B5sd000017F6* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Allo CP100P/E 1-port E1/T1/J1 PCI/PCIe card) + +pci:v000010B5d0000D44Dsv000010B5sd000017F7* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Allo CP400P/E 4-port E1/T1/J1 PCI/PCIe card) + +pci:v000010B5d0000D44Dsv000010B5sd000017F8* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Allo CP200P/E 2-port E1/T1/J1 PCI/PCIe card) + +pci:v000010B5d0000D44Dsv000010B5sd00009030* + ID_MODEL_FROM_DATABASE=PCI9030 32-bit 33MHz PCI <-> IOBus Bridge (Tormenta 3 Varion V401PE Quad E1 PCI card) + +pci:v000010B6* + ID_VENDOR_FROM_DATABASE=Madge Networks + +pci:v000010B6d00000001* + ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode + +pci:v000010B6d00000002* + ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk2 + +pci:v000010B6d00000002sv000010B6sd00000002* + ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk2 + +pci:v000010B6d00000002sv000010B6sd00000006* + ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk2 (16/4 CardBus Adapter) + +pci:v000010B6d00000003* + ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk3 + +pci:v000010B6d00000003sv00000E11sd0000B0FD* + ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk3 (Compaq NC4621 PCI, 4/16, WOL) + +pci:v000010B6d00000003sv000010B6sd00000003* + ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk3 + +pci:v000010B6d00000003sv000010B6sd00000007* + ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk3 (Presto PCI Plus Adapter) + +pci:v000010B6d00000004* + ID_MODEL_FROM_DATABASE=Smart 16/4 PCI Ringnode Mk1 + +pci:v000010B6d00000006* + ID_MODEL_FROM_DATABASE=16/4 Cardbus Adapter + +pci:v000010B6d00000006sv000010B6sd00000006* + ID_MODEL_FROM_DATABASE=16/4 Cardbus Adapter (16/4 CardBus Adapter) + +pci:v000010B6d00000007* + ID_MODEL_FROM_DATABASE=Presto PCI Adapter + +pci:v000010B6d00000007sv000010B6sd00000007* + ID_MODEL_FROM_DATABASE=Presto PCI Adapter (Presto PCI) + +pci:v000010B6d00000009* + ID_MODEL_FROM_DATABASE=Smart 100/16/4 PCI-HS Ringnode + +pci:v000010B6d00000009sv000010B6sd00000009* + ID_MODEL_FROM_DATABASE=Smart 100/16/4 PCI-HS Ringnode + +pci:v000010B6d0000000A* + ID_MODEL_FROM_DATABASE=Token Ring 100/16/4 Ringnode/Ringrunner + +pci:v000010B6d0000000Asv000010B6sd0000000A* + ID_MODEL_FROM_DATABASE=Token Ring 100/16/4 Ringnode/Ringrunner + +pci:v000010B6d0000000B* + ID_MODEL_FROM_DATABASE=16/4 CardBus Adapter Mk2 + +pci:v000010B6d0000000Bsv000010B6sd00000008* + ID_MODEL_FROM_DATABASE=16/4 CardBus Adapter Mk2 + +pci:v000010B6d0000000Bsv000010B6sd0000000B* + ID_MODEL_FROM_DATABASE=16/4 CardBus Adapter Mk2 (16/4 Cardbus Adapter Mk2) + +pci:v000010B6d0000000C* + ID_MODEL_FROM_DATABASE=RapidFire 3140V2 16/4 TR Adapter + +pci:v000010B6d0000000Csv000010B6sd0000000C* + ID_MODEL_FROM_DATABASE=RapidFire 3140V2 16/4 TR Adapter + +pci:v000010B6d00001000* + ID_MODEL_FROM_DATABASE=Collage 25/155 ATM Client Adapter + +pci:v000010B6d00001001* + ID_MODEL_FROM_DATABASE=Collage 155 ATM Server Adapter + +pci:v000010B7* + ID_VENDOR_FROM_DATABASE=3Com Corporation + +pci:v000010B7d00000001* + ID_MODEL_FROM_DATABASE=3c985 1000BaseSX (SX/TX) + +pci:v000010B7d00000001sv00009850sd00000001* + ID_MODEL_FROM_DATABASE=3c985 1000BaseSX (SX/TX) (3c985B-SX) + +pci:v000010B7d00000013* + ID_MODEL_FROM_DATABASE=AR5212 802.11abg NIC (3CRDAG675) + +pci:v000010B7d00000013sv000010B7sd00002031* + ID_MODEL_FROM_DATABASE=AR5212 802.11abg NIC (3CRDAG675) (3CRDAG675 11a/b/g Wireless PCI Adapter) + +pci:v000010B7d00000910* + ID_MODEL_FROM_DATABASE=3C910-A01 + +pci:v000010B7d00001006* + ID_MODEL_FROM_DATABASE=MINI PCI type 3B Data Fax Modem + +pci:v000010B7d00001007* + ID_MODEL_FROM_DATABASE=Mini PCI 56k Winmodem + +pci:v000010B7d00001007sv000010B7sd0000615B* + ID_MODEL_FROM_DATABASE=Mini PCI 56k Winmodem (Mini PCI 56K Modem) + +pci:v000010B7d00001007sv000010B7sd0000615C* + ID_MODEL_FROM_DATABASE=Mini PCI 56k Winmodem (Mini PCI 56K Modem) + +pci:v000010B7d00001201* + ID_MODEL_FROM_DATABASE=3c982-TXM 10/100baseTX Dual Port A [Hydra] + +pci:v000010B7d00001202* + ID_MODEL_FROM_DATABASE=3c982-TXM 10/100baseTX Dual Port B [Hydra] + +pci:v000010B7d00001700* + ID_MODEL_FROM_DATABASE=3c940 10/100/1000Base-T [Marvell] + +pci:v000010B7d00001700sv00001043sd000080EB* + ID_MODEL_FROM_DATABASE=3c940 10/100/1000Base-T [Marvell] (A7V600/P4P800/K8V motherboard) + +pci:v000010B7d00001700sv000010B7sd00000010* + ID_MODEL_FROM_DATABASE=3c940 10/100/1000Base-T [Marvell] (3C940 Gigabit LOM Ethernet Adapter) + +pci:v000010B7d00001700sv000010B7sd00000020* + ID_MODEL_FROM_DATABASE=3c940 10/100/1000Base-T [Marvell] (3C941 Gigabit LOM Ethernet Adapter) + +pci:v000010B7d00001700sv0000147Bsd00001407* + ID_MODEL_FROM_DATABASE=3c940 10/100/1000Base-T [Marvell] (KV8-MAX3 motherboard) + +pci:v000010B7d00003390* + ID_MODEL_FROM_DATABASE=3c339 TokenLink Velocity + +pci:v000010B7d00003590* + ID_MODEL_FROM_DATABASE=3c359 TokenLink Velocity XL + +pci:v000010B7d00003590sv000010B7sd00003590* + ID_MODEL_FROM_DATABASE=3c359 TokenLink Velocity XL (TokenLink Velocity XL Adapter (3C359/359B)) + +pci:v000010B7d00004500* + ID_MODEL_FROM_DATABASE=3c450 HomePNA [Tornado] + +pci:v000010B7d00005055* + ID_MODEL_FROM_DATABASE=3c555 Laptop Hurricane + +pci:v000010B7d00005057* + ID_MODEL_FROM_DATABASE=3c575 Megahertz 10/100 LAN CardBus [Boomerang] + +pci:v000010B7d00005057sv000010B7sd00005A57* + ID_MODEL_FROM_DATABASE=3c575 Megahertz 10/100 LAN CardBus [Boomerang] (3C575 Megahertz 10/100 LAN Cardbus PC Card) + +pci:v000010B7d00005157* + ID_MODEL_FROM_DATABASE=3cCFE575BT Megahertz 10/100 LAN CardBus [Cyclone] + +pci:v000010B7d00005157sv000010B7sd00005B57* + ID_MODEL_FROM_DATABASE=3cCFE575BT Megahertz 10/100 LAN CardBus [Cyclone] (3C575 Megahertz 10/100 LAN Cardbus PC Card) + +pci:v000010B7d00005257* + ID_MODEL_FROM_DATABASE=3cCFE575CT CardBus [Cyclone] + +pci:v000010B7d00005257sv000010B7sd00005C57* + ID_MODEL_FROM_DATABASE=3cCFE575CT CardBus [Cyclone] (FE575C-3Com 10/100 LAN CardBus-Fast Ethernet) + +pci:v000010B7d00005900* + ID_MODEL_FROM_DATABASE=3c590 10BaseT [Vortex] + +pci:v000010B7d00005920* + ID_MODEL_FROM_DATABASE=3c592 EISA 10mbps Demon/Vortex + +pci:v000010B7d00005950* + ID_MODEL_FROM_DATABASE=3c595 100BaseTX [Vortex] + +pci:v000010B7d00005951* + ID_MODEL_FROM_DATABASE=3c595 100BaseT4 [Vortex] + +pci:v000010B7d00005952* + ID_MODEL_FROM_DATABASE=3c595 100Base-MII [Vortex] + +pci:v000010B7d00005970* + ID_MODEL_FROM_DATABASE=3c597 EISA Fast Demon/Vortex + +pci:v000010B7d00005B57* + ID_MODEL_FROM_DATABASE=3c595 Megahertz 10/100 LAN CardBus [Boomerang] + +pci:v000010B7d00005B57sv000010B7sd00005B57* + ID_MODEL_FROM_DATABASE=3c595 Megahertz 10/100 LAN CardBus [Boomerang] (3C575 Megahertz 10/100 LAN Cardbus PC Card) + +pci:v000010B7d00006000* + ID_MODEL_FROM_DATABASE=3CRSHPW796 [OfficeConnect Wireless CardBus] + +pci:v000010B7d00006001* + ID_MODEL_FROM_DATABASE=3com 3CRWE154G72 [Office Connect Wireless LAN Adapter] + +pci:v000010B7d00006055* + ID_MODEL_FROM_DATABASE=3c556 Hurricane CardBus [Cyclone] + +pci:v000010B7d00006056* + ID_MODEL_FROM_DATABASE=3c556B CardBus [Tornado] + +pci:v000010B7d00006056sv000010B7sd00006556* + ID_MODEL_FROM_DATABASE=3c556B CardBus [Tornado] (10/100 Mini PCI Ethernet Adapter) + +pci:v000010B7d00006560* + ID_MODEL_FROM_DATABASE=3cCFE656 CardBus [Cyclone] + +pci:v000010B7d00006560sv000010B7sd0000656A* + ID_MODEL_FROM_DATABASE=3cCFE656 CardBus [Cyclone] (3CCFEM656 10/100 LAN+56K Modem CardBus) + +pci:v000010B7d00006561* + ID_MODEL_FROM_DATABASE=3cCFEM656 10/100 LAN+56K Modem CardBus + +pci:v000010B7d00006561sv000010B7sd0000656B* + ID_MODEL_FROM_DATABASE=3cCFEM656 10/100 LAN+56K Modem CardBus (3CCFEM656 10/100 LAN+56K Modem CardBus) + +pci:v000010B7d00006562* + ID_MODEL_FROM_DATABASE=3cCFEM656B 10/100 LAN+Winmodem CardBus [Cyclone] + +pci:v000010B7d00006562sv000010B7sd0000656B* + ID_MODEL_FROM_DATABASE=3cCFEM656B 10/100 LAN+Winmodem CardBus [Cyclone] (3CCFEM656B 10/100 LAN+56K Modem CardBus) + +pci:v000010B7d00006563* + ID_MODEL_FROM_DATABASE=3cCFEM656B 10/100 LAN+56K Modem CardBus + +pci:v000010B7d00006563sv000010B7sd0000656B* + ID_MODEL_FROM_DATABASE=3cCFEM656B 10/100 LAN+56K Modem CardBus (3CCFEM656 10/100 LAN+56K Modem CardBus) + +pci:v000010B7d00006564* + ID_MODEL_FROM_DATABASE=3cXFEM656C 10/100 LAN+Winmodem CardBus [Tornado] + +pci:v000010B7d00007646* + ID_MODEL_FROM_DATABASE=3cSOHO100-TX Hurricane + +pci:v000010B7d00007770* + ID_MODEL_FROM_DATABASE=3CRWE777 PCI Wireless Adapter [Airconnect] + +pci:v000010B7d00007940* + ID_MODEL_FROM_DATABASE=3c803 FDDILink UTP Controller + +pci:v000010B7d00007980* + ID_MODEL_FROM_DATABASE=3c804 FDDILink SAS Controller + +pci:v000010B7d00007990* + ID_MODEL_FROM_DATABASE=3c805 FDDILink DAS Controller + +pci:v000010B7d000080EB* + ID_MODEL_FROM_DATABASE=3c940B 10/100/1000Base-T + +pci:v000010B7d00008811* + ID_MODEL_FROM_DATABASE=Token ring + +pci:v000010B7d00009000* + ID_MODEL_FROM_DATABASE=3c900 10BaseT [Boomerang] + +pci:v000010B7d00009001* + ID_MODEL_FROM_DATABASE=3c900 10Mbps Combo [Boomerang] + +pci:v000010B7d00009004* + ID_MODEL_FROM_DATABASE=3c900B-TPO Etherlink XL [Cyclone] + +pci:v000010B7d00009004sv000010B7sd00009004* + ID_MODEL_FROM_DATABASE=3c900B-TPO Etherlink XL [Cyclone] (3C900B-TPO Etherlink XL TPO 10Mb) + +pci:v000010B7d00009005* + ID_MODEL_FROM_DATABASE=3c900B-Combo Etherlink XL [Cyclone] + +pci:v000010B7d00009005sv000010B7sd00009005* + ID_MODEL_FROM_DATABASE=3c900B-Combo Etherlink XL [Cyclone] (3C900B-Combo Etherlink XL Combo) + +pci:v000010B7d00009006* + ID_MODEL_FROM_DATABASE=3c900B-TPC Etherlink XL [Cyclone] + +pci:v000010B7d0000900A* + ID_MODEL_FROM_DATABASE=3c900B-FL 10base-FL [Cyclone] + +pci:v000010B7d00009050* + ID_MODEL_FROM_DATABASE=3c905 100BaseTX [Boomerang] + +pci:v000010B7d00009051* + ID_MODEL_FROM_DATABASE=3c905 100BaseT4 [Boomerang] + +pci:v000010B7d00009054* + ID_MODEL_FROM_DATABASE=3C905B-TX Fast Etherlink XL PCI + +pci:v000010B7d00009054sv000010B7sd00009054* + ID_MODEL_FROM_DATABASE=3C905B-TX Fast Etherlink XL PCI + +pci:v000010B7d00009055* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] + +pci:v000010B7d00009055sv00001028sd00000080* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000081* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000082* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000083* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000084* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000085* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000086* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000087* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000088* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000089* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000090* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000091* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000092* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000093* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000094* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000095* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000096* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000097* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000098* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv00001028sd00000099* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009055sv000010B7sd00009055* + ID_MODEL_FROM_DATABASE=3c905B 100BaseTX [Cyclone] (3C905B Fast Etherlink XL 10/100) + +pci:v000010B7d00009056* + ID_MODEL_FROM_DATABASE=3c905B-T4 Fast EtherLink XL [Cyclone] + +pci:v000010B7d00009058* + ID_MODEL_FROM_DATABASE=3c905B Deluxe Etherlink 10/100/BNC [Cyclone] + +pci:v000010B7d0000905A* + ID_MODEL_FROM_DATABASE=3c905B-FX Fast Etherlink XL FX 100baseFx [Cyclone] + +pci:v000010B7d00009200* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] + +pci:v000010B7d00009200sv00001028sd00000095* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (3C920 Integrated Fast Ethernet Controller) + +pci:v000010B7d00009200sv00001028sd00000097* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (3C920 Integrated Fast Ethernet Controller) + +pci:v000010B7d00009200sv00001028sd000000B4* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (OptiPlex GX110) + +pci:v000010B7d00009200sv00001028sd000000D8* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (Precision 530) + +pci:v000010B7d00009200sv00001028sd000000FE* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (Optiplex GX240) + +pci:v000010B7d00009200sv00001028sd0000012A* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (3C920 Integrated Fast Ethernet Controller [Latitude C640]) + +pci:v000010B7d00009200sv000010B7sd00001000* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (3C905CX-TX/TX-M Fast Etherlink for PC Management NIC) + +pci:v000010B7d00009200sv000010B7sd00007000* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (10/100 Mini PCI Ethernet Adapter) + +pci:v000010B7d00009200sv000010F1sd00002466* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (Tiger MPX S2466 (3C920 Integrated Fast Ethernet Controller)) + +pci:v000010B7d00009200sv0000144Dsd0000C005* + ID_MODEL_FROM_DATABASE=3c905C-TX/TX-M [Tornado] (X10 Laptop) + +pci:v000010B7d00009201* + ID_MODEL_FROM_DATABASE=3C920B-EMB Integrated Fast Ethernet Controller [Tornado] + +pci:v000010B7d00009201sv00001043sd000080AB* + ID_MODEL_FROM_DATABASE=3C920B-EMB Integrated Fast Ethernet Controller [Tornado] (A7N8X Deluxe onboard 3C920B-EMB Integrated Fast Ethernet Controller) + +pci:v000010B7d00009202* + ID_MODEL_FROM_DATABASE=3Com 3C920B-EMB-WNM Integrated Fast Ethernet Controller + +pci:v000010B7d00009210* + ID_MODEL_FROM_DATABASE=3C920B-EMB-WNM Integrated Fast Ethernet Controller + +pci:v000010B7d00009300* + ID_MODEL_FROM_DATABASE=3CSOHO100B-TX 910-A01 [tulip] + +pci:v000010B7d00009800* + ID_MODEL_FROM_DATABASE=3c980-TX Fast Etherlink XL Server Adapter [Cyclone] + +pci:v000010B7d00009800sv000010B7sd00009800* + ID_MODEL_FROM_DATABASE=3c980-TX Fast Etherlink XL Server Adapter [Cyclone] (3c980-TX Fast Etherlink XL Server Adapter) + +pci:v000010B7d00009805* + ID_MODEL_FROM_DATABASE=3c980-C 10/100baseTX NIC [Python-T] + +pci:v000010B7d00009805sv000010B7sd00001201* + ID_MODEL_FROM_DATABASE=3c980-C 10/100baseTX NIC [Python-T] (EtherLink Server 10/100 Dual Port A) + +pci:v000010B7d00009805sv000010B7sd00001202* + ID_MODEL_FROM_DATABASE=3c980-C 10/100baseTX NIC [Python-T] (EtherLink Server 10/100 Dual Port B) + +pci:v000010B7d00009805sv000010B7sd00009805* + ID_MODEL_FROM_DATABASE=3c980-C 10/100baseTX NIC [Python-T] (3c980 10/100baseTX NIC [Python-T]) + +pci:v000010B7d00009805sv000010F1sd00002462* + ID_MODEL_FROM_DATABASE=3c980-C 10/100baseTX NIC [Python-T] (Thunder K7 S2462) + +pci:v000010B7d00009900* + ID_MODEL_FROM_DATABASE=3C990-TX [Typhoon] + +pci:v000010B7d00009902* + ID_MODEL_FROM_DATABASE=3CR990-TX-95 [Typhoon 56-bit] + +pci:v000010B7d00009903* + ID_MODEL_FROM_DATABASE=3CR990-TX-97 [Typhoon 168-bit] + +pci:v000010B7d00009904* + ID_MODEL_FROM_DATABASE=3C990B-TX-M/3C990BSVR [Typhoon2] + +pci:v000010B7d00009904sv000010B7sd00001000* + ID_MODEL_FROM_DATABASE=3C990B-TX-M/3C990BSVR [Typhoon2] (3CR990B-TX-M [Typhoon2]) + +pci:v000010B7d00009904sv000010B7sd00002000* + ID_MODEL_FROM_DATABASE=3C990B-TX-M/3C990BSVR [Typhoon2] (3CR990BSVR [Typhoon2 Server]) + +pci:v000010B7d00009905* + ID_MODEL_FROM_DATABASE=3CR990-FX-95/97/95 [Typhon Fiber] + +pci:v000010B7d00009905sv000010B7sd00001101* + ID_MODEL_FROM_DATABASE=3CR990-FX-95/97/95 [Typhon Fiber] (3CR990-FX-95 [Typhoon Fiber 56-bit]) + +pci:v000010B7d00009905sv000010B7sd00001102* + ID_MODEL_FROM_DATABASE=3CR990-FX-95/97/95 [Typhon Fiber] (3CR990-FX-97 [Typhoon Fiber 168-bit]) + +pci:v000010B7d00009905sv000010B7sd00002101* + ID_MODEL_FROM_DATABASE=3CR990-FX-95/97/95 [Typhon Fiber] (3CR990-FX-95 Server [Typhoon Fiber 56-bit]) + +pci:v000010B7d00009905sv000010B7sd00002102* + ID_MODEL_FROM_DATABASE=3CR990-FX-95/97/95 [Typhon Fiber] (3CR990-FX-97 Server [Typhoon Fiber 168-bit]) + +pci:v000010B7d00009908* + ID_MODEL_FROM_DATABASE=3CR990SVR95 [Typhoon Server 56-bit] + +pci:v000010B7d00009909* + ID_MODEL_FROM_DATABASE=3CR990SVR97 [Typhoon Server 168-bit] + +pci:v000010B7d0000990A* + ID_MODEL_FROM_DATABASE=3C990SVR [Typhoon Server] + +pci:v000010B7d0000990B* + ID_MODEL_FROM_DATABASE=3C990SVR [Typhoon Server] + +pci:v000010B8* + ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp [SMC] + +pci:v000010B8d00000005* + ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter + +pci:v000010B8d00000005sv00001055sd0000E000* + ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (LANEPIC 10/100 [EVB171Q-PCI]) + +pci:v000010B8d00000005sv00001055sd0000E002* + ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (LANEPIC 10/100 [EVB171G-PCI]) + +pci:v000010B8d00000005sv000010B8sd0000A011* + ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (EtherPower II 10/100) + +pci:v000010B8d00000005sv000010B8sd0000A014* + ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (EtherPower II 10/100) + +pci:v000010B8d00000005sv000010B8sd0000A015* + ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (EtherPower II 10/100) + +pci:v000010B8d00000005sv000010B8sd0000A016* + ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (EtherPower II 10/100) + +pci:v000010B8d00000005sv000010B8sd0000A017* + ID_MODEL_FROM_DATABASE=83c170 EPIC/100 Fast Ethernet Adapter (EtherPower II 10/100) + +pci:v000010B8d00000006* + ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter + +pci:v000010B8d00000006sv00001055sd0000E100* + ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) + +pci:v000010B8d00000006sv00001055sd0000E102* + ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) + +pci:v000010B8d00000006sv00001055sd0000E300* + ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) + +pci:v000010B8d00000006sv00001055sd0000E302* + ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) + +pci:v000010B8d00000006sv000010B8sd0000A012* + ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) + +pci:v000010B8d00000006sv000013A2sd00008002* + ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) + +pci:v000010B8d00000006sv000013A2sd00008006* + ID_MODEL_FROM_DATABASE=83c175 EPIC/100 Fast Ethernet Adapter (LANEPIC Cardbus Fast Ethernet Adapter) + +pci:v000010B8d00001000* + ID_MODEL_FROM_DATABASE=FDC 37c665 + +pci:v000010B8d00001001* + ID_MODEL_FROM_DATABASE=FDC 37C922 + +pci:v000010B8d0000A011* + ID_MODEL_FROM_DATABASE=83C170QF + +pci:v000010B8d0000B106* + ID_MODEL_FROM_DATABASE=SMC34C90 + +pci:v000010B9* + ID_VENDOR_FROM_DATABASE=ULi Electronics Inc. + +pci:v000010B9d00000101* + ID_MODEL_FROM_DATABASE=CMI8338/C3DX PCI Audio Device + +pci:v000010B9d00000111* + ID_MODEL_FROM_DATABASE=C-Media CMI8738/C3DX Audio Device (OEM) + +pci:v000010B9d00000111sv000010B9sd00000111* + ID_MODEL_FROM_DATABASE=C-Media CMI8738/C3DX Audio Device (OEM) + +pci:v000010B9d00000780* + ID_MODEL_FROM_DATABASE=Multi-IO Card + +pci:v000010B9d00000782* + ID_MODEL_FROM_DATABASE=Multi-IO Card + +pci:v000010B9d00001435* + ID_MODEL_FROM_DATABASE=M1435 + +pci:v000010B9d00001445* + ID_MODEL_FROM_DATABASE=M1445 + +pci:v000010B9d00001449* + ID_MODEL_FROM_DATABASE=M1449 + +pci:v000010B9d00001451* + ID_MODEL_FROM_DATABASE=M1451 + +pci:v000010B9d00001461* + ID_MODEL_FROM_DATABASE=M1461 + +pci:v000010B9d00001489* + ID_MODEL_FROM_DATABASE=M1489 + +pci:v000010B9d00001511* + ID_MODEL_FROM_DATABASE=M1511 [Aladdin] + +pci:v000010B9d00001512* + ID_MODEL_FROM_DATABASE=M1512 [Aladdin] + +pci:v000010B9d00001513* + ID_MODEL_FROM_DATABASE=M1513 [Aladdin] + +pci:v000010B9d00001521* + ID_MODEL_FROM_DATABASE=M1521 [Aladdin III] + +pci:v000010B9d00001521sv000010B9sd00001521* + ID_MODEL_FROM_DATABASE=M1521 [Aladdin III] (ALI M1521 Aladdin III CPU Bridge) + +pci:v000010B9d00001523* + ID_MODEL_FROM_DATABASE=M1523 + +pci:v000010B9d00001523sv000010B9sd00001523* + ID_MODEL_FROM_DATABASE=M1523 (ALI M1523 ISA Bridge) + +pci:v000010B9d00001531* + ID_MODEL_FROM_DATABASE=M1531 [Aladdin IV] + +pci:v000010B9d00001533* + ID_MODEL_FROM_DATABASE=M1533/M1535/M1543 PCI to ISA Bridge [Aladdin IV/V/V+] + +pci:v000010B9d00001533sv00001014sd0000053B* + ID_MODEL_FROM_DATABASE=M1533/M1535/M1543 PCI to ISA Bridge [Aladdin IV/V/V+] (ThinkPad R40e) + +pci:v000010B9d00001533sv000010B9sd00001533* + ID_MODEL_FROM_DATABASE=M1533/M1535/M1543 PCI to ISA Bridge [Aladdin IV/V/V+] (ALi M1533 Aladdin IV/V ISA Bridge) + +pci:v000010B9d00001541* + ID_MODEL_FROM_DATABASE=M1541 + +pci:v000010B9d00001541sv000010B9sd00001541* + ID_MODEL_FROM_DATABASE=M1541 (ALI M1541 Aladdin V/V+ AGP System Controller) + +pci:v000010B9d00001543* + ID_MODEL_FROM_DATABASE=M1543 + +pci:v000010B9d00001563* + ID_MODEL_FROM_DATABASE=M1563 HyperTransport South Bridge + +pci:v000010B9d00001563sv000010B9sd00001563* + ID_MODEL_FROM_DATABASE=M1563 HyperTransport South Bridge (ASRock 939Dual-SATA2 Motherboard) + +pci:v000010B9d00001563sv00001849sd00001563* + ID_MODEL_FROM_DATABASE=M1563 HyperTransport South Bridge (ASRock 939Dual-SATA2 Motherboard) + +pci:v000010B9d00001573* + ID_MODEL_FROM_DATABASE=PCI to LPC Controller + +pci:v000010B9d00001575* + ID_MODEL_FROM_DATABASE=M1575 South Bridge + +pci:v000010B9d00001621* + ID_MODEL_FROM_DATABASE=M1621 + +pci:v000010B9d00001631* + ID_MODEL_FROM_DATABASE=ALI M1631 PCI North Bridge Aladdin Pro III + +pci:v000010B9d00001632* + ID_MODEL_FROM_DATABASE=M1632M Northbridge+Trident + +pci:v000010B9d00001641* + ID_MODEL_FROM_DATABASE=ALI M1641 PCI North Bridge Aladdin Pro IV + +pci:v000010B9d00001644* + ID_MODEL_FROM_DATABASE=M1644/M1644T Northbridge+Trident + +pci:v000010B9d00001646* + ID_MODEL_FROM_DATABASE=M1646 Northbridge+Trident + +pci:v000010B9d00001647* + ID_MODEL_FROM_DATABASE=M1647 Northbridge [MAGiK 1 / MobileMAGiK 1] + +pci:v000010B9d00001651* + ID_MODEL_FROM_DATABASE=M1651/M1651T Northbridge [Aladdin-Pro 5/5M,Aladdin-Pro 5T/5TM] + +pci:v000010B9d00001671* + ID_MODEL_FROM_DATABASE=M1671 Super P4 Northbridge [AGP4X,PCI and SDR/DDR] + +pci:v000010B9d00001672* + ID_MODEL_FROM_DATABASE=M1672 Northbridge [CyberALADDiN-P4] + +pci:v000010B9d00001681* + ID_MODEL_FROM_DATABASE=M1681 P4 Northbridge [AGP8X,HyperTransport and SDR/DDR] + +pci:v000010B9d00001687* + ID_MODEL_FROM_DATABASE=M1687 K8 Northbridge [AGP8X and HyperTransport] + +pci:v000010B9d00001689* + ID_MODEL_FROM_DATABASE=M1689 K8 Northbridge [Super K8 Single Chip] + +pci:v000010B9d00001695* + ID_MODEL_FROM_DATABASE=M1695 Host Bridge + +pci:v000010B9d00001697* + ID_MODEL_FROM_DATABASE=M1697 HTT Host Bridge + +pci:v000010B9d00003141* + ID_MODEL_FROM_DATABASE=M3141 + +pci:v000010B9d00003143* + ID_MODEL_FROM_DATABASE=M3143 + +pci:v000010B9d00003145* + ID_MODEL_FROM_DATABASE=M3145 + +pci:v000010B9d00003147* + ID_MODEL_FROM_DATABASE=M3147 + +pci:v000010B9d00003149* + ID_MODEL_FROM_DATABASE=M3149 + +pci:v000010B9d00003151* + ID_MODEL_FROM_DATABASE=M3151 + +pci:v000010B9d00003307* + ID_MODEL_FROM_DATABASE=M3307 + +pci:v000010B9d00003309* + ID_MODEL_FROM_DATABASE=M3309 + +pci:v000010B9d00003323* + ID_MODEL_FROM_DATABASE=M3325 Video/Audio Decoder + +pci:v000010B9d00005212* + ID_MODEL_FROM_DATABASE=M4803 + +pci:v000010B9d00005215* + ID_MODEL_FROM_DATABASE=MS4803 + +pci:v000010B9d00005217* + ID_MODEL_FROM_DATABASE=M5217H + +pci:v000010B9d00005219* + ID_MODEL_FROM_DATABASE=M5219 + +pci:v000010B9d00005225* + ID_MODEL_FROM_DATABASE=M5225 + +pci:v000010B9d00005228* + ID_MODEL_FROM_DATABASE=M5228 ALi ATA/RAID Controller + +pci:v000010B9d00005229* + ID_MODEL_FROM_DATABASE=M5229 IDE + +pci:v000010B9d00005229sv00001014sd0000050F* + ID_MODEL_FROM_DATABASE=M5229 IDE (ThinkPad R30) + +pci:v000010B9d00005229sv00001014sd0000053D* + ID_MODEL_FROM_DATABASE=M5229 IDE (ThinkPad R40e) + +pci:v000010B9d00005229sv0000103Csd00000024* + ID_MODEL_FROM_DATABASE=M5229 IDE (Pavilion ze4400 builtin IDE) + +pci:v000010B9d00005229sv0000103Csd00000025* + ID_MODEL_FROM_DATABASE=M5229 IDE (XE4500 Notebook) + +pci:v000010B9d00005229sv00001043sd00008053* + ID_MODEL_FROM_DATABASE=M5229 IDE (A7A266 Motherboard IDE) + +pci:v000010B9d00005229sv00001849sd00005229* + ID_MODEL_FROM_DATABASE=M5229 IDE (ASRock 939Dual-SATA2 Motherboard IDE (PATA)) + +pci:v000010B9d00005235* + ID_MODEL_FROM_DATABASE=M5225 + +pci:v000010B9d00005237* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller + +pci:v000010B9d00005237sv00001014sd00000540* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (ThinkPad R40e) + +pci:v000010B9d00005237sv0000103Csd00000024* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (Pavilion ze4400 builtin USB) + +pci:v000010B9d00005237sv0000103Csd00000025* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (XE4500 Notebook) + +pci:v000010B9d00005237sv0000104Dsd0000810F* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (VAIO PCG-U1 USB/OHCI Revision 1.0) + +pci:v000010B9d00005237sv000010B9sd00005237* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (ASRock 939Dual-SATA2 Motherboard) + +pci:v000010B9d00005237sv00001849sd00005237* + ID_MODEL_FROM_DATABASE=USB 1.1 Controller (ASRock 939Dual-SATA2 Motherboard) + +pci:v000010B9d00005239* + ID_MODEL_FROM_DATABASE=USB 2.0 Controller + +pci:v000010B9d00005239sv000010B9sd00005239* + ID_MODEL_FROM_DATABASE=USB 2.0 Controller (ASRock 939Dual-SATA2 Motherboard) + +pci:v000010B9d00005239sv00001849sd00005239* + ID_MODEL_FROM_DATABASE=USB 2.0 Controller (ASRock 939Dual-SATA2 Motherboard) + +pci:v000010B9d00005243* + ID_MODEL_FROM_DATABASE=M1541 PCI to AGP Controller + +pci:v000010B9d00005246* + ID_MODEL_FROM_DATABASE=AGP8X Controller + +pci:v000010B9d00005247* + ID_MODEL_FROM_DATABASE=PCI to AGP Controller + +pci:v000010B9d00005249* + ID_MODEL_FROM_DATABASE=M5249 HTT to PCI Bridge + +pci:v000010B9d0000524B* + ID_MODEL_FROM_DATABASE=PCI Express Root Port + +pci:v000010B9d0000524C* + ID_MODEL_FROM_DATABASE=PCI Express Root Port + +pci:v000010B9d0000524D* + ID_MODEL_FROM_DATABASE=PCI Express Root Port + +pci:v000010B9d0000524E* + ID_MODEL_FROM_DATABASE=PCI Express Root Port + +pci:v000010B9d00005251* + ID_MODEL_FROM_DATABASE=M5251 P1394 OHCI 1.0 Controller + +pci:v000010B9d00005253* + ID_MODEL_FROM_DATABASE=M5253 P1394 OHCI 1.1 Controller + +pci:v000010B9d00005261* + ID_MODEL_FROM_DATABASE=M5261 Ethernet Controller + +pci:v000010B9d00005263* + ID_MODEL_FROM_DATABASE=ULi 1689,1573 integrated ethernet. + +pci:v000010B9d00005281* + ID_MODEL_FROM_DATABASE=ALi M5281 Serial ATA / RAID Host Controller + +pci:v000010B9d00005287* + ID_MODEL_FROM_DATABASE=ULi 5287 SATA + +pci:v000010B9d00005288* + ID_MODEL_FROM_DATABASE=ULi M5288 SATA + +pci:v000010B9d00005288sv00001043sd00008056* + ID_MODEL_FROM_DATABASE=ULi M5288 SATA (A8R-MVP Mainboard) + +pci:v000010B9d00005289* + ID_MODEL_FROM_DATABASE=ULi 5289 SATA + +pci:v000010B9d00005450* + ID_MODEL_FROM_DATABASE=Lucent Technologies Soft Modem AMR + +pci:v000010B9d00005451* + ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device + +pci:v000010B9d00005451sv00001014sd00000506* + ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device (ThinkPad R30) + +pci:v000010B9d00005451sv00001014sd0000053E* + ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device (ThinkPad R40e) + +pci:v000010B9d00005451sv0000103Csd00000024* + ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device (Pavilion ze4400 builtin Audio) + +pci:v000010B9d00005451sv0000103Csd00000025* + ID_MODEL_FROM_DATABASE=M5451 PCI AC-Link Controller Audio Device (XE4500 Notebook) + +pci:v000010B9d00005453* + ID_MODEL_FROM_DATABASE=M5453 PCI AC-Link Controller Modem Device + +pci:v000010B9d00005455* + ID_MODEL_FROM_DATABASE=M5455 PCI AC-Link Controller Audio Device + +pci:v000010B9d00005455sv000010B9sd00005455* + ID_MODEL_FROM_DATABASE=M5455 PCI AC-Link Controller Audio Device (ASRock 939Dual-SATA2 Motherboard) + +pci:v000010B9d00005455sv00001849sd00000850* + ID_MODEL_FROM_DATABASE=M5455 PCI AC-Link Controller Audio Device (ASRock 939Dual-SATA2 Motherboard) + +pci:v000010B9d00005457* + ID_MODEL_FROM_DATABASE=M5457 AC'97 Modem Controller + +pci:v000010B9d00005457sv00001014sd00000535* + ID_MODEL_FROM_DATABASE=M5457 AC'97 Modem Controller (ThinkPad R40e) + +pci:v000010B9d00005457sv0000103Csd00000024* + ID_MODEL_FROM_DATABASE=M5457 AC'97 Modem Controller (Pavilion ze4400 builtin Modem Device) + +pci:v000010B9d00005457sv0000103Csd00000025* + ID_MODEL_FROM_DATABASE=M5457 AC'97 Modem Controller (XE4500 Notebook) + +pci:v000010B9d00005459* + ID_MODEL_FROM_DATABASE=SmartLink SmartPCI561 56K Modem + +pci:v000010B9d0000545A* + ID_MODEL_FROM_DATABASE=SmartLink SmartPCI563 56K Modem + +pci:v000010B9d00005461* + ID_MODEL_FROM_DATABASE=HD Audio Controller + +pci:v000010B9d00005471* + ID_MODEL_FROM_DATABASE=M5471 Memory Stick Controller + +pci:v000010B9d00005473* + ID_MODEL_FROM_DATABASE=M5473 SD-MMC Controller + +pci:v000010B9d00007101* + ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] + +pci:v000010B9d00007101sv00001014sd00000510* + ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] (ThinkPad R30) + +pci:v000010B9d00007101sv00001014sd0000053C* + ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] (ThinkPad R40e) + +pci:v000010B9d00007101sv0000103Csd00000024* + ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] (Pavilion ze4400) + +pci:v000010B9d00007101sv0000103Csd00000025* + ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] (XE4500 Notebook) + +pci:v000010B9d00007101sv00001849sd00007101* + ID_MODEL_FROM_DATABASE=M7101 Power Management Controller [PMU] (ASRock 939Dual-SATA2 Motherboard) + +pci:v000010BA* + ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Corp. + +pci:v000010BAd00000301* + ID_MODEL_FROM_DATABASE=AccelGraphics AccelECLIPSE + +pci:v000010BAd00000304* + ID_MODEL_FROM_DATABASE=AccelGALAXY A2100 [OEM Evans & Sutherland] + +pci:v000010BAd00000308* + ID_MODEL_FROM_DATABASE=Tornado 3000 [OEM Evans & Sutherland] + +pci:v000010BAd00000308sv000010DDsd00000024* + ID_MODEL_FROM_DATABASE=Tornado 3000 [OEM Evans & Sutherland] (Tornado 3000) + +pci:v000010BAd00001002* + ID_MODEL_FROM_DATABASE=VG500 [VolumePro Volume Rendering Accelerator] + +pci:v000010BB* + ID_VENDOR_FROM_DATABASE=Dapha Electronics Corporation + +pci:v000010BC* + ID_VENDOR_FROM_DATABASE=Advanced Logic Research + +pci:v000010BD* + ID_VENDOR_FROM_DATABASE=Surecom Technology + +pci:v000010BDd00000E34* + ID_MODEL_FROM_DATABASE=NE-34 + +pci:v000010BE* + ID_VENDOR_FROM_DATABASE=Tseng Labs International Co. + +pci:v000010BF* + ID_VENDOR_FROM_DATABASE=Most Inc + +pci:v000010C0* + ID_VENDOR_FROM_DATABASE=Boca Research Inc. + +pci:v000010C1* + ID_VENDOR_FROM_DATABASE=ICM Co., Ltd. + +pci:v000010C2* + ID_VENDOR_FROM_DATABASE=Auspex Systems Inc. + +pci:v000010C3* + ID_VENDOR_FROM_DATABASE=Samsung Semiconductors, Inc. + +pci:v000010C4* + ID_VENDOR_FROM_DATABASE=Award Software International Inc. + +pci:v000010C5* + ID_VENDOR_FROM_DATABASE=Xerox Corporation + +pci:v000010C6* + ID_VENDOR_FROM_DATABASE=Rambus Inc. + +pci:v000010C7* + ID_VENDOR_FROM_DATABASE=Media Vision + +pci:v000010C8* + ID_VENDOR_FROM_DATABASE=Neomagic Corporation + +pci:v000010C8d00000001* + ID_MODEL_FROM_DATABASE=NM2070 [MagicGraph 128] + +pci:v000010C8d00000002* + ID_MODEL_FROM_DATABASE=NM2090 [MagicGraph 128V] + +pci:v000010C8d00000003* + ID_MODEL_FROM_DATABASE=NM2093 [MagicGraph 128ZV] + +pci:v000010C8d00000004* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] + +pci:v000010C8d00000004sv00001014sd000000BA* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv00001025sd00001007* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv00001028sd00000074* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv00001028sd00000075* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv00001028sd0000007D* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv00001028sd0000007E* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv00001033sd0000802F* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv0000104Dsd0000801B* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv0000104Dsd0000802F* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv0000104Dsd0000830B* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv000010BAsd00000E00* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv000010C8sd00000004* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv000010CFsd00001029* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv000010F7sd00008308* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv000010F7sd00008309* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv000010F7sd0000830B* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv000010F7sd0000830D* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000004sv000010F7sd00008312* + ID_MODEL_FROM_DATABASE=NM2160 [MagicGraph 128XD] (MagicGraph 128XD) + +pci:v000010C8d00000005* + ID_MODEL_FROM_DATABASE=NM2200 [MagicGraph 256AV] + +pci:v000010C8d00000005sv00001014sd000000DD* + ID_MODEL_FROM_DATABASE=NM2200 [MagicGraph 256AV] (ThinkPad 570) + +pci:v000010C8d00000005sv00001028sd00000088* + ID_MODEL_FROM_DATABASE=NM2200 [MagicGraph 256AV] (Latitude CPi A) + +pci:v000010C8d00000006* + ID_MODEL_FROM_DATABASE=NM2360 [MagicMedia 256ZX] + +pci:v000010C8d00000006sv00001014sd00000152* + ID_MODEL_FROM_DATABASE=NM2360 [MagicMedia 256ZX] (ThinkPad 600X) + +pci:v000010C8d00000016* + ID_MODEL_FROM_DATABASE=NM2380 [MagicMedia 256XL+] + +pci:v000010C8d00000016sv000010C8sd00000016* + ID_MODEL_FROM_DATABASE=NM2380 [MagicMedia 256XL+] (MagicMedia 256XL+) + +pci:v000010C8d00000025* + ID_MODEL_FROM_DATABASE=NM2230 [MagicGraph 256AV+] + +pci:v000010C8d00000083* + ID_MODEL_FROM_DATABASE=NM2093 [MagicGraph 128ZV+] + +pci:v000010C8d00008005* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] + +pci:v000010C8d00008005sv00000E11sd0000B0D1* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Discovery) + +pci:v000010C8d00008005sv00000E11sd0000B126* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Durango) + +pci:v000010C8d00008005sv00001014sd000000DD* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (ThinkPad 390/i1720/i1721) + +pci:v000010C8d00008005sv00001025sd00001003* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on TravelMate 720) + +pci:v000010C8d00008005sv00001028sd00000088* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (Latitude CPi A) + +pci:v000010C8d00008005sv00001028sd0000008F* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Colorado Inspiron) + +pci:v000010C8d00008005sv0000103Csd00000007* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Voyager II) + +pci:v000010C8d00008005sv0000103Csd00000008* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Voyager III) + +pci:v000010C8d00008005sv0000103Csd0000000D* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on Omnibook 900) + +pci:v000010C8d00008005sv000010C8sd00008005* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device on FireAnt) + +pci:v000010C8d00008005sv0000110Asd00008005* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device) + +pci:v000010C8d00008005sv000014C0sd00000004* + ID_MODEL_FROM_DATABASE=NM2200 [MagicMedia 256AV Audio] (MagicMedia 256AV Audio Device) + +pci:v000010C8d00008006* + ID_MODEL_FROM_DATABASE=NM2360 [MagicMedia 256ZX Audio] + +pci:v000010C8d00008016* + ID_MODEL_FROM_DATABASE=NM2380 [MagicMedia 256XL+ Audio] + +pci:v000010C9* + ID_VENDOR_FROM_DATABASE=Dataexpert Corporation + +pci:v000010CA* + ID_VENDOR_FROM_DATABASE=Fujitsu Microelectr., Inc. + +pci:v000010CB* + ID_VENDOR_FROM_DATABASE=Omron Corporation + +pci:v000010CC* + ID_VENDOR_FROM_DATABASE=Mai Logic Incorporated + +pci:v000010CCd00000660* + ID_MODEL_FROM_DATABASE=Articia S Host Bridge + +pci:v000010CCd00000661* + ID_MODEL_FROM_DATABASE=Articia S PCI Bridge + +pci:v000010CD* + ID_VENDOR_FROM_DATABASE=Advanced System Products, Inc + +pci:v000010CDd00001100* + ID_MODEL_FROM_DATABASE=ASC1100 + +pci:v000010CDd00001200* + ID_MODEL_FROM_DATABASE=ASC1200 [(abp940) Fast SCSI-II] + +pci:v000010CDd00001300* + ID_MODEL_FROM_DATABASE=ASC1300 / ASC3030 [ABP940-U / ABP960-U / ABP3925] + +pci:v000010CDd00001300sv000010CDsd00001310* + ID_MODEL_FROM_DATABASE=ASC1300 / ASC3030 [ABP940-U / ABP960-U / ABP3925] (ASC1300/3030 SCSI adapter) + +pci:v000010CDd00001300sv00001195sd00001320* + ID_MODEL_FROM_DATABASE=ASC1300 / ASC3030 [ABP940-U / ABP960-U / ABP3925] (Ultra-SCSI CardBus PC Card REX CB31) + +pci:v000010CDd00002300* + ID_MODEL_FROM_DATABASE=ABP940-UW + +pci:v000010CDd00002500* + ID_MODEL_FROM_DATABASE=ABP940-U2W + +pci:v000010CDd00002700* + ID_MODEL_FROM_DATABASE=ABP3950-U3W + +pci:v000010CE* + ID_VENDOR_FROM_DATABASE=Radius + +pci:v000010CF* + ID_VENDOR_FROM_DATABASE=Fujitsu Limited. + +pci:v000010CFd000001EF* + ID_MODEL_FROM_DATABASE=PCEA4 PCI-Express Dual Port ESCON Adapter + +pci:v000010CFd00001414* + ID_MODEL_FROM_DATABASE=On-board USB 1.1 companion controller + +pci:v000010CFd00001415* + ID_MODEL_FROM_DATABASE=On-board USB 2.0 EHCI controller + +pci:v000010CFd00001422* + ID_MODEL_FROM_DATABASE=E8410 nVidia graphics adapter + +pci:v000010CFd0000142D* + ID_MODEL_FROM_DATABASE=HD audio (Realtek ALC262) + +pci:v000010CFd00001430* + ID_MODEL_FROM_DATABASE=82566MM Intel 1Gb copper LAN interface + +pci:v000010CFd00001623* + ID_MODEL_FROM_DATABASE=PCEA4 PCI-Express Dual Port ESCON Adapter + +pci:v000010CFd00002001* + ID_MODEL_FROM_DATABASE=mb86605 + +pci:v000010CFd0000200C* + ID_MODEL_FROM_DATABASE=MB86613L IEEE1394 OHCI 1.0 Controller + +pci:v000010CFd00002010* + ID_MODEL_FROM_DATABASE=MB86613S IEEE1394 OHCI 1.1 Controller + +pci:v000010CFd00002019* + ID_MODEL_FROM_DATABASE=MB86295S [CORAL P] + +pci:v000010CFd0000201E* + ID_MODEL_FROM_DATABASE=MB86296S [CORAL PA] + +pci:v000010CFd0000202B* + ID_MODEL_FROM_DATABASE=MB86297A [Carmine Graphics Controller] + +pci:v000010D1* + ID_VENDOR_FROM_DATABASE=FuturePlus Systems Corp. + +pci:v000010D2* + ID_VENDOR_FROM_DATABASE=Molex Incorporated + +pci:v000010D3* + ID_VENDOR_FROM_DATABASE=Jabil Circuit Inc + +pci:v000010D4* + ID_VENDOR_FROM_DATABASE=Hualon Microelectronics + +pci:v000010D5* + ID_VENDOR_FROM_DATABASE=Autologic Inc. + +pci:v000010D6* + ID_VENDOR_FROM_DATABASE=Cetia + +pci:v000010D7* + ID_VENDOR_FROM_DATABASE=BCM Advanced Research + +pci:v000010D8* + ID_VENDOR_FROM_DATABASE=Advanced Peripherals Labs + +pci:v000010D9* + ID_VENDOR_FROM_DATABASE=Macronix, Inc. [MXIC] + +pci:v000010D9d00000431* + ID_MODEL_FROM_DATABASE=MX98715 + +pci:v000010D9d00000512* + ID_MODEL_FROM_DATABASE=MX98713 + +pci:v000010D9d00000531* + ID_MODEL_FROM_DATABASE=MX987x5 + +pci:v000010D9d00000531sv00001186sd00001200* + ID_MODEL_FROM_DATABASE=MX987x5 (DFE-540TX ProFAST 10/100 Adapter) + +pci:v000010D9d00008625* + ID_MODEL_FROM_DATABASE=MX86250 + +pci:v000010D9d00008626* + ID_MODEL_FROM_DATABASE=Macronix MX86251 + 3Dfx Voodoo Rush + +pci:v000010D9d00008888* + ID_MODEL_FROM_DATABASE=MX86200 + +pci:v000010DA* + ID_VENDOR_FROM_DATABASE=Compaq IPG-Austin + +pci:v000010DAd00000508* + ID_MODEL_FROM_DATABASE=TC4048 Token Ring 4/16 + +pci:v000010DAd00003390* + ID_MODEL_FROM_DATABASE=Tl3c3x9 + +pci:v000010DB* + ID_VENDOR_FROM_DATABASE=Rohm LSI Systems, Inc. + +pci:v000010DC* + ID_VENDOR_FROM_DATABASE=CERN/ECP/EDU + +pci:v000010DCd00000001* + ID_MODEL_FROM_DATABASE=STAR/RD24 SCI-PCI (PMC) + +pci:v000010DCd00000002* + ID_MODEL_FROM_DATABASE=TAR/RD24 SCI-PCI (PMC) + +pci:v000010DCd00000021* + ID_MODEL_FROM_DATABASE=HIPPI destination + +pci:v000010DCd00000022* + ID_MODEL_FROM_DATABASE=HIPPI source + +pci:v000010DCd000010DC* + ID_MODEL_FROM_DATABASE=ATT2C15-3 FPGA + +pci:v000010DD* + ID_VENDOR_FROM_DATABASE=Evans & Sutherland + +pci:v000010DDd00000100* + ID_MODEL_FROM_DATABASE=Lightning 1200 + +pci:v000010DDd00000100sv000010DDsd00000023* + ID_MODEL_FROM_DATABASE=Lightning 1200 (15+16M) + +pci:v000010DE* + ID_VENDOR_FROM_DATABASE=NVIDIA Corporation + +pci:v000010DEd00000008* + ID_MODEL_FROM_DATABASE=NV1 [STG2000X-B Series] + +pci:v000010DEd00000009* + ID_MODEL_FROM_DATABASE=NV1 [NV1 Series] + +pci:v000010DEd00000018* + ID_MODEL_FROM_DATABASE=NV3 [Riva 128] + +pci:v000010DEd00000019* + ID_MODEL_FROM_DATABASE=NV3 [Riva 128ZX] + +pci:v000010DEd00000020* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] + +pci:v000010DEd00000020sv00001043sd00000200* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (V3400 TNT) + +pci:v000010DEd00000020sv00001048sd00000C18* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Erazor II SGRAM) + +pci:v000010DEd00000020sv00001048sd00000C19* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Erazor II) + +pci:v000010DEd00000020sv00001048sd00000C1B* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Erazor II) + +pci:v000010DEd00000020sv00001048sd00000C1C* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Erazor II) + +pci:v000010DEd00000020sv00001092sd00000550* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv00001092sd00000552* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv00001092sd00004804* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv00001092sd00004808* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv00001092sd00004810* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv00001092sd00004812* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv00001092sd00004815* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv00001092sd00004820* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550 with TV out) + +pci:v000010DEd00000020sv00001092sd00004822* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv00001092sd00004904* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv00001092sd00004914* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv00001092sd00008225* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Viper V550) + +pci:v000010DEd00000020sv000010B4sd0000273D* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Velocity 4400) + +pci:v000010DEd00000020sv000010B4sd0000273E* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Velocity 4400) + +pci:v000010DEd00000020sv000010B4sd00002740* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Velocity 4400) + +pci:v000010DEd00000020sv000010DEsd00000020* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Riva TNT) + +pci:v000010DEd00000020sv00001102sd00001015* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Graphics Blaster CT6710) + +pci:v000010DEd00000020sv00001102sd00001016* + ID_MODEL_FROM_DATABASE=NV4 [Riva TNT] (Graphics Blaster RIVA TNT) + +pci:v000010DEd00000028* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] + +pci:v000010DEd00000028sv00001043sd00000200* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (AGP-V3800 SGRAM) + +pci:v000010DEd00000028sv00001043sd00000201* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (AGP-V3800 SDRAM) + +pci:v000010DEd00000028sv00001043sd00000205* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (PCI-V3800) + +pci:v000010DEd00000028sv00001043sd00004000* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (AGP-V3800PRO) + +pci:v000010DEd00000028sv00001048sd00000C21* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Synergy II) + +pci:v000010DEd00000028sv00001048sd00000C28* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III) + +pci:v000010DEd00000028sv00001048sd00000C29* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III) + +pci:v000010DEd00000028sv00001048sd00000C2A* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III) + +pci:v000010DEd00000028sv00001048sd00000C2B* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III) + +pci:v000010DEd00000028sv00001048sd00000C31* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III Pro) + +pci:v000010DEd00000028sv00001048sd00000C32* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III Pro) + +pci:v000010DEd00000028sv00001048sd00000C33* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III Pro) + +pci:v000010DEd00000028sv00001048sd00000C34* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Erazor III Pro) + +pci:v000010DEd00000028sv0000107Dsd00002134* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (WinFast 3D S320 II + TV-Out) + +pci:v000010DEd00000028sv00001092sd00004804* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770) + +pci:v000010DEd00000028sv00001092sd00004A00* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770) + +pci:v000010DEd00000028sv00001092sd00004A02* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770 Ultra) + +pci:v000010DEd00000028sv00001092sd00005A00* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (RIVA TNT2/TNT2 Pro) + +pci:v000010DEd00000028sv00001092sd00005A40* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770D AGP) + +pci:v000010DEd00000028sv00001092sd00006A02* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770 Ultra) + +pci:v000010DEd00000028sv00001092sd00007A02* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Viper V770 Ultra) + +pci:v000010DEd00000028sv000010DEsd00000005* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (RIVA TNT2 Pro) + +pci:v000010DEd00000028sv000010DEsd0000000F* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Compaq NVIDIA TNT2 Pro) + +pci:v000010DEd00000028sv00001102sd00001020* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (3D Blaster RIVA TNT2) + +pci:v000010DEd00000028sv00001102sd00001026* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (3D Blaster RIVA TNT2 Digital) + +pci:v000010DEd00000028sv00001462sd00008806* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (MS-8806 AGPhantom Graphics Card) + +pci:v000010DEd00000028sv000014AFsd00005810* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 / TNT2 Pro] (Maxi Gamer Xentor) + +pci:v000010DEd00000029* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] + +pci:v000010DEd00000029sv00001043sd00000200* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (AGP-V3800 Deluxe) + +pci:v000010DEd00000029sv00001043sd00000201* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (AGP-V3800 Ultra SDRAM) + +pci:v000010DEd00000029sv00001043sd00000205* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (PCI-V3800 Ultra) + +pci:v000010DEd00000029sv00001048sd00000C2E* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (Erazor III Ultra) + +pci:v000010DEd00000029sv00001048sd00000C2F* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (Erazor III Ultra) + +pci:v000010DEd00000029sv00001048sd00000C30* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (Erazor III Ultra) + +pci:v000010DEd00000029sv00001102sd00001021* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (3D Blaster RIVA TNT2 Ultra) + +pci:v000010DEd00000029sv00001102sd00001029* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (3D Blaster RIVA TNT2 Ultra) + +pci:v000010DEd00000029sv00001102sd0000102F* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (3D Blaster RIVA TNT2 Ultra) + +pci:v000010DEd00000029sv000014AFsd00005820* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (Maxi Gamer Xentor 32) + +pci:v000010DEd00000029sv00004843sd00004F34* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Ultra] (Dynamite) + +pci:v000010DEd0000002A* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2] + +pci:v000010DEd0000002B* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2] + +pci:v000010DEd0000002C* + ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] + +pci:v000010DEd0000002Csv00001043sd00000200* + ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (AGP-V3800 Combat SDRAM) + +pci:v000010DEd0000002Csv00001043sd00000201* + ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (AGP-V3800 Combat) + +pci:v000010DEd0000002Csv00001048sd00000C20* + ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (TNT2 Vanta) + +pci:v000010DEd0000002Csv00001048sd00000C21* + ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (TNT2 Vanta) + +pci:v000010DEd0000002Csv00001048sd00000C25* + ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (TNT2 Vanta 16MB) + +pci:v000010DEd0000002Csv00001092sd00006820* + ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (Viper V730) + +pci:v000010DEd0000002Csv00001102sd00001031* + ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (CT6938 VANTA 8MB) + +pci:v000010DEd0000002Csv00001102sd00001034* + ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (CT6894 VANTA 16MB) + +pci:v000010DEd0000002Csv000014AFsd00005008* + ID_MODEL_FROM_DATABASE=NV5 [Vanta / Vanta LT] (Maxi Gamer Phoenix 2) + +pci:v000010DEd0000002D* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] + +pci:v000010DEd0000002Dsv00001043sd00000200* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (AGP-V3800M) + +pci:v000010DEd0000002Dsv00001043sd00000201* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (AGP-V3800M) + +pci:v000010DEd0000002Dsv00001048sd00000C3A* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (Erazor III LT) + +pci:v000010DEd0000002Dsv00001048sd00000C3B* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (Erazor III LT) + +pci:v000010DEd0000002Dsv0000107Dsd00002137* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (WinFast 3D S325) + +pci:v000010DEd0000002Dsv000010DEsd00000006* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (RIVA TNT2 Model 64/Model 64 Pro) + +pci:v000010DEd0000002Dsv000010DEsd0000001E* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (M64 AGP4x) + +pci:v000010DEd0000002Dsv00001102sd00001023* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (CT6892 RIVA TNT2 Value) + +pci:v000010DEd0000002Dsv00001102sd00001024* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (CT6932 RIVA TNT2 Value 32Mb) + +pci:v000010DEd0000002Dsv00001102sd0000102C* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (CT6931 RIVA TNT2 Value [Jumper]) + +pci:v000010DEd0000002Dsv00001102sd00001030* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (CT6931 RIVA TNT2 Value) + +pci:v000010DEd0000002Dsv0000110Asd0000006F* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (GM1000-16) + +pci:v000010DEd0000002Dsv0000110Asd00000081* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (GM1000-16) + +pci:v000010DEd0000002Dsv00001462sd00008808* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (MSI-8808) + +pci:v000010DEd0000002Dsv000014AFsd00005620* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (Gamer Cougar Video Edition) + +pci:v000010DEd0000002Dsv00001554sd00001041* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (Pixelview RIVA TNT2 M64) + +pci:v000010DEd0000002Dsv00001569sd0000002D* + ID_MODEL_FROM_DATABASE=NV5 [Riva TNT2 Model 64 / Model 64 Pro] (Palit Microsystems Daytona TNT2 M64) + +pci:v000010DEd00000034* + ID_MODEL_FROM_DATABASE=MCP04 SMBus + +pci:v000010DEd00000035* + ID_MODEL_FROM_DATABASE=MCP04 IDE + +pci:v000010DEd00000036* + ID_MODEL_FROM_DATABASE=MCP04 Serial ATA Controller + +pci:v000010DEd00000037* + ID_MODEL_FROM_DATABASE=MCP04 Ethernet Controller + +pci:v000010DEd00000038* + ID_MODEL_FROM_DATABASE=MCP04 Ethernet Controller + +pci:v000010DEd0000003A* + ID_MODEL_FROM_DATABASE=MCP04 AC'97 Audio Controller + +pci:v000010DEd0000003B* + ID_MODEL_FROM_DATABASE=MCP04 USB Controller + +pci:v000010DEd0000003C* + ID_MODEL_FROM_DATABASE=MCP04 USB Controller + +pci:v000010DEd0000003D* + ID_MODEL_FROM_DATABASE=MCP04 PCI Bridge + +pci:v000010DEd0000003E* + ID_MODEL_FROM_DATABASE=MCP04 Serial ATA Controller + +pci:v000010DEd00000040* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 Ultra] + +pci:v000010DEd00000041* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800] + +pci:v000010DEd00000041sv00001043sd0000817B* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800] (V9999 Gamer Edition) + +pci:v000010DEd00000041sv0000107Dsd00002992* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800] (WinFast A400) + +pci:v000010DEd00000041sv00001458sd0000310F* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800] (Geforce 6800 GV-N6812) + +pci:v000010DEd00000042* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 LE] + +pci:v000010DEd00000042sv0000107Dsd0000299B* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 LE] (WinFast A400 LE) + +pci:v000010DEd00000043* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 XE] + +pci:v000010DEd00000044* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 XT] + +pci:v000010DEd00000045* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT] + +pci:v000010DEd00000045sv00001043sd0000817D* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT] (V9999GT) + +pci:v000010DEd00000045sv00001458sd00003140* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT] (GV-N68T256D) + +pci:v000010DEd00000047* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GS] + +pci:v000010DEd00000047sv00001682sd00002109* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GS] (GeForce 6800 GS) + +pci:v000010DEd00000048* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 XT] + +pci:v000010DEd0000004E* + ID_MODEL_FROM_DATABASE=NV40GL [Quadro FX 4000] + +pci:v000010DEd00000050* + ID_MODEL_FROM_DATABASE=CK804 ISA Bridge + +pci:v000010DEd00000050sv00001043sd0000815A* + ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (K8N4/A8N Series Mainboard) + +pci:v000010DEd00000050sv000010F1sd00002865* + ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (Tomcat K8E (S2865)) + +pci:v000010DEd00000050sv00001458sd00000C11* + ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (GA-K8N Ultra-9 Mainboard) + +pci:v000010DEd00000050sv00001462sd00007100* + ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (MSI K8N Diamond) + +pci:v000010DEd00000050sv00001462sd00007125* + ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (K8N Neo4-F mainboard) + +pci:v000010DEd00000050sv0000147Bsd00001C1A* + ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (KN8-Ultra Mainboard) + +pci:v000010DEd00000050sv00001565sd00003402* + ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (NF4 AM2L Mainboard) + +pci:v000010DEd00000051* + ID_MODEL_FROM_DATABASE=CK804 ISA Bridge + +pci:v000010DEd00000051sv00001028sd00000225* + ID_MODEL_FROM_DATABASE=CK804 ISA Bridge (PowerEdge T105 ISA Bridge) + +pci:v000010DEd00000052* + ID_MODEL_FROM_DATABASE=CK804 SMBus + +pci:v000010DEd00000052sv00001028sd00000225* + ID_MODEL_FROM_DATABASE=CK804 SMBus (PowerEdge T105 SMBus) + +pci:v000010DEd00000052sv00001043sd0000815A* + ID_MODEL_FROM_DATABASE=CK804 SMBus (K8N4/A8N Series Mainboard) + +pci:v000010DEd00000052sv000010F1sd00002865* + ID_MODEL_FROM_DATABASE=CK804 SMBus (Tomcat K8E (S2865)) + +pci:v000010DEd00000052sv00001458sd00000C11* + ID_MODEL_FROM_DATABASE=CK804 SMBus (GA-K8N Ultra-9 Mainboard) + +pci:v000010DEd00000052sv00001462sd00007100* + ID_MODEL_FROM_DATABASE=CK804 SMBus (MSI K8N Diamond) + +pci:v000010DEd00000052sv00001462sd00007125* + ID_MODEL_FROM_DATABASE=CK804 SMBus (K8N Neo4-F mainboard) + +pci:v000010DEd00000052sv0000147Bsd00001C1A* + ID_MODEL_FROM_DATABASE=CK804 SMBus (KN8-Ultra Mainboard) + +pci:v000010DEd00000052sv00001565sd00003402* + ID_MODEL_FROM_DATABASE=CK804 SMBus (NF4 AM2L Mainboard) + +pci:v000010DEd00000053* + ID_MODEL_FROM_DATABASE=CK804 IDE + +pci:v000010DEd00000053sv00001043sd0000815A* + ID_MODEL_FROM_DATABASE=CK804 IDE (K8N4/A8N Series Mainboard) + +pci:v000010DEd00000053sv000010F1sd00002865* + ID_MODEL_FROM_DATABASE=CK804 IDE (Tomcat K8E (S2865)) + +pci:v000010DEd00000053sv00001458sd00005002* + ID_MODEL_FROM_DATABASE=CK804 IDE (GA-K8N Ultra-9 Mainboard) + +pci:v000010DEd00000053sv00001462sd00007100* + ID_MODEL_FROM_DATABASE=CK804 IDE (MSI K8N Diamond) + +pci:v000010DEd00000053sv00001462sd00007125* + ID_MODEL_FROM_DATABASE=CK804 IDE (K8N Neo4-F mainboard) + +pci:v000010DEd00000053sv0000147Bsd00001C1A* + ID_MODEL_FROM_DATABASE=CK804 IDE (KN8-Ultra Mainboard) + +pci:v000010DEd00000053sv00001565sd00003402* + ID_MODEL_FROM_DATABASE=CK804 IDE (NF4 AM2L Mainboard) + +pci:v000010DEd00000054* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller + +pci:v000010DEd00000054sv00001028sd00000225* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (PowerEdge T105 Serial ATA) + +pci:v000010DEd00000054sv00001043sd0000815A* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (A8N Series Mainboard) + +pci:v000010DEd00000054sv000010F1sd00002865* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (Tomcat K8E (S2865)) + +pci:v000010DEd00000054sv00001458sd0000B003* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (GA-K8N Ultra-9 Mainboard) + +pci:v000010DEd00000054sv00001462sd00007100* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (MSI K8N Diamond) + +pci:v000010DEd00000054sv00001462sd00007125* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (K8N Neo4-F mainboard) + +pci:v000010DEd00000054sv0000147Bsd00001C1A* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (KN8-Ultra Mainboard) + +pci:v000010DEd00000054sv00001565sd00005401* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (NF4 AM2L Mainboard) + +pci:v000010DEd00000055* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller + +pci:v000010DEd00000055sv00001028sd00000225* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (PowerEdge T105 Serial ATA) + +pci:v000010DEd00000055sv00001043sd0000815A* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (K8N4/A8N Series Mainboard) + +pci:v000010DEd00000055sv000010F1sd00002865* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (Tomcat K8E (S2865)) + +pci:v000010DEd00000055sv00001458sd0000B003* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (GA-K8N Ultra-9 Mainboard) + +pci:v000010DEd00000055sv00001462sd00007125* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (K8N Neo4-F mainboard) + +pci:v000010DEd00000055sv0000147Bsd00001C1A* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (KN8-Ultra Mainboard) + +pci:v000010DEd00000055sv00001565sd00005401* + ID_MODEL_FROM_DATABASE=CK804 Serial ATA Controller (NF4 AM2L Mainboard) + +pci:v000010DEd00000056* + ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller + +pci:v000010DEd00000057* + ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller + +pci:v000010DEd00000057sv00001043sd00008141* + ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (K8N4/A8N Series Mainboard) + +pci:v000010DEd00000057sv000010DEsd0000CB84* + ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (NF4 Lanparty) + +pci:v000010DEd00000057sv000010F1sd00002865* + ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (Tomcat K8E (S2865)) + +pci:v000010DEd00000057sv00001458sd0000E000* + ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (GA-K8N Ultra-9 Mainboard) + +pci:v000010DEd00000057sv00001462sd00007100* + ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (MSI K8N Diamond) + +pci:v000010DEd00000057sv00001462sd00007125* + ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (K8N Neo4-F mainboard) + +pci:v000010DEd00000057sv0000147Bsd00001C1A* + ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (KN8-Ultra Mainboard) + +pci:v000010DEd00000057sv00001565sd00002501* + ID_MODEL_FROM_DATABASE=CK804 Ethernet Controller (NF4 AM2L Mainboard) + +pci:v000010DEd00000058* + ID_MODEL_FROM_DATABASE=CK804 AC'97 Modem + +pci:v000010DEd00000059* + ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller + +pci:v000010DEd00000059sv00001043sd0000812A* + ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller (K8N4/A8N Series Mainboard) + +pci:v000010DEd00000059sv000010F1sd00002865* + ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller (Tomcat K8E (S2865)) + +pci:v000010DEd00000059sv00001462sd00007585* + ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller (K8N Neo4-F mainboard) + +pci:v000010DEd00000059sv0000147Bsd00001C1A* + ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller (KN8-Ultra Mainboard) + +pci:v000010DEd00000059sv00001565sd00008211* + ID_MODEL_FROM_DATABASE=CK804 AC'97 Audio Controller (NF4 AM2L Mainboard) + +pci:v000010DEd0000005A* + ID_MODEL_FROM_DATABASE=CK804 USB Controller + +pci:v000010DEd0000005Asv00001028sd00000225* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (PowerEdge T105 onboard USB) + +pci:v000010DEd0000005Asv00001043sd0000815A* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (K8N4/A8N Series Mainboard) + +pci:v000010DEd0000005Asv000010F1sd00002865* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (Tomcat K8E (S2865)) + +pci:v000010DEd0000005Asv00001458sd00005004* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (GA-K8N Ultra-9 Mainboard) + +pci:v000010DEd0000005Asv00001462sd00007100* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (MSI K8N Diamond) + +pci:v000010DEd0000005Asv00001462sd00007125* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (K8N Neo4-F mainboard) + +pci:v000010DEd0000005Asv0000147Bsd00001C1A* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (KN8-Ultra Mainboard) + +pci:v000010DEd0000005Asv00001565sd00003402* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (NF4 AM2L Mainboard) + +pci:v000010DEd0000005B* + ID_MODEL_FROM_DATABASE=CK804 USB Controller + +pci:v000010DEd0000005Bsv00001028sd00000225* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (PowerEdge T105 onboard USB) + +pci:v000010DEd0000005Bsv00001043sd0000815A* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (K8N4/A8N Series Mainboard) + +pci:v000010DEd0000005Bsv000010F1sd00002865* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (Tomcat K8E (S2865)) + +pci:v000010DEd0000005Bsv00001458sd00005004* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (GA-K8N Ultra-9 Mainboard) + +pci:v000010DEd0000005Bsv00001462sd00007100* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (MSI K8N Diamond) + +pci:v000010DEd0000005Bsv00001462sd00007125* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (K8N Neo4-F mainboard) + +pci:v000010DEd0000005Bsv0000147Bsd00001C1A* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (KN8-Ultra Mainboard) + +pci:v000010DEd0000005Bsv00001565sd00003402* + ID_MODEL_FROM_DATABASE=CK804 USB Controller (NF4 AM2L Mainboard) + +pci:v000010DEd0000005C* + ID_MODEL_FROM_DATABASE=CK804 PCI Bridge + +pci:v000010DEd0000005D* + ID_MODEL_FROM_DATABASE=CK804 PCIE Bridge + +pci:v000010DEd0000005E* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller + +pci:v000010DEd0000005Esv00001028sd00000225* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller (PowerEdge T105 Memory Controller) + +pci:v000010DEd0000005Esv00001043sd0000815A* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller (A8N Series Mainboard) + +pci:v000010DEd0000005Esv000010DEsd0000005E* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller (ECS Elitegroup NFORCE3-A939 motherboard.) + +pci:v000010DEd0000005Esv000010F1sd00002865* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller (Tomcat K8E (S2865)) + +pci:v000010DEd0000005Esv000010F1sd00002891* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller (Thunder K8SRE Mainboard) + +pci:v000010DEd0000005Esv00001458sd00005000* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller (GA-K8N Ultra-9 Mainboard) + +pci:v000010DEd0000005Esv00001462sd00007100* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller (K8N Diamond Mainboard) + +pci:v000010DEd0000005Esv00001462sd00007125* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller (K8N Neo4-F Mainboard) + +pci:v000010DEd0000005Esv0000147Bsd00001C1A* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller (KN8-Ultra Mainboard) + +pci:v000010DEd0000005Esv00001565sd00003402* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller (NF4 AM2L Mainboard) + +pci:v000010DEd0000005F* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller + +pci:v000010DEd00000060* + ID_MODEL_FROM_DATABASE=nForce2 ISA Bridge + +pci:v000010DEd00000060sv00001043sd000080AD* + ID_MODEL_FROM_DATABASE=nForce2 ISA Bridge (A7N8X Mainboard) + +pci:v000010DEd00000060sv0000147Bsd00001C02* + ID_MODEL_FROM_DATABASE=nForce2 ISA Bridge (NF7-S/NF7 (nVidia-nForce2) 2.X) + +pci:v000010DEd00000060sv0000A0A0sd000003BA* + ID_MODEL_FROM_DATABASE=nForce2 ISA Bridge (UK79G-1394 motherboard) + +pci:v000010DEd00000064* + ID_MODEL_FROM_DATABASE=nForce2 SMBus (MCP) + +pci:v000010DEd00000064sv0000147Bsd00001C02* + ID_MODEL_FROM_DATABASE=nForce2 SMBus (MCP) (NF7-S/NF7 (nVidia-nForce2) 2.X) + +pci:v000010DEd00000064sv0000A0A0sd000003BB* + ID_MODEL_FROM_DATABASE=nForce2 SMBus (MCP) (UK79G-1394 motherboard) + +pci:v000010DEd00000065* + ID_MODEL_FROM_DATABASE=nForce2 IDE + +pci:v000010DEd00000065sv000010DEsd00000C11* + ID_MODEL_FROM_DATABASE=nForce2 IDE (nForce 2 EIDE Controller) + +pci:v000010DEd00000065sv0000A0A0sd000003B2* + ID_MODEL_FROM_DATABASE=nForce2 IDE (UK79G-1394 motherboard) + +pci:v000010DEd00000066* + ID_MODEL_FROM_DATABASE=nForce2 Ethernet Controller + +pci:v000010DEd00000066sv00001043sd000080A7* + ID_MODEL_FROM_DATABASE=nForce2 Ethernet Controller (A7N8X Mainboard onboard nForce2 Ethernet) + +pci:v000010DEd00000066sv000010DEsd00000C11* + ID_MODEL_FROM_DATABASE=nForce2 Ethernet Controller (nForce MCP-T Networking Adapter) + +pci:v000010DEd00000066sv0000A0A0sd000003B3* + ID_MODEL_FROM_DATABASE=nForce2 Ethernet Controller (UK79G-1394 motherboard) + +pci:v000010DEd00000067* + ID_MODEL_FROM_DATABASE=nForce2 USB Controller + +pci:v000010DEd00000067sv00001043sd00000C11* + ID_MODEL_FROM_DATABASE=nForce2 USB Controller (A7N8X Mainboard) + +pci:v000010DEd00000067sv0000A0A0sd000003B4* + ID_MODEL_FROM_DATABASE=nForce2 USB Controller (UK79G-1394 motherboard) + +pci:v000010DEd00000068* + ID_MODEL_FROM_DATABASE=nForce2 USB Controller + +pci:v000010DEd00000068sv00001043sd00000C11* + ID_MODEL_FROM_DATABASE=nForce2 USB Controller (A7N8X Mainboard) + +pci:v000010DEd00000068sv0000A0A0sd000003B4* + ID_MODEL_FROM_DATABASE=nForce2 USB Controller (UK79G-1394 motherboard) + +pci:v000010DEd0000006A* + ID_MODEL_FROM_DATABASE=nForce2 AC97 Audio Controler (MCP) + +pci:v000010DEd0000006Asv00001043sd00008095* + ID_MODEL_FROM_DATABASE=nForce2 AC97 Audio Controler (MCP) (nForce2 AC97 Audio Controller (MCP)) + +pci:v000010DEd0000006Asv0000A0A0sd00000304* + ID_MODEL_FROM_DATABASE=nForce2 AC97 Audio Controler (MCP) (UK79G-1394 motherboard) + +pci:v000010DEd0000006B* + ID_MODEL_FROM_DATABASE=nForce Audio Processing Unit + +pci:v000010DEd0000006Bsv000010DEsd0000006B* + ID_MODEL_FROM_DATABASE=nForce Audio Processing Unit (nForce2 MCP Audio Processing Unit) + +pci:v000010DEd0000006Bsv0000A0A0sd00000304* + ID_MODEL_FROM_DATABASE=nForce Audio Processing Unit (UK79G-1394 motherboard) + +pci:v000010DEd0000006C* + ID_MODEL_FROM_DATABASE=nForce2 External PCI Bridge + +pci:v000010DEd0000006D* + ID_MODEL_FROM_DATABASE=nForce2 PCI Bridge + +pci:v000010DEd0000006E* + ID_MODEL_FROM_DATABASE=nForce2 FireWire (IEEE 1394) Controller + +pci:v000010DEd0000006Esv0000A0A0sd00000306* + ID_MODEL_FROM_DATABASE=nForce2 FireWire (IEEE 1394) Controller (UK79G-1394 motherboard) + +pci:v000010DEd00000080* + ID_MODEL_FROM_DATABASE=MCP2A ISA bridge + +pci:v000010DEd00000080sv0000147Bsd00001C09* + ID_MODEL_FROM_DATABASE=MCP2A ISA bridge (NV7 Motherboard) + +pci:v000010DEd00000084* + ID_MODEL_FROM_DATABASE=MCP2A SMBus + +pci:v000010DEd00000084sv0000147Bsd00001C09* + ID_MODEL_FROM_DATABASE=MCP2A SMBus (NV7 Motherboard) + +pci:v000010DEd00000085* + ID_MODEL_FROM_DATABASE=MCP2A IDE + +pci:v000010DEd00000085sv0000147Bsd00001C09* + ID_MODEL_FROM_DATABASE=MCP2A IDE (NV7 Motherboard) + +pci:v000010DEd00000086* + ID_MODEL_FROM_DATABASE=MCP2A Ethernet Controller + +pci:v000010DEd00000087* + ID_MODEL_FROM_DATABASE=MCP2A USB Controller + +pci:v000010DEd00000087sv0000147Bsd00001C09* + ID_MODEL_FROM_DATABASE=MCP2A USB Controller (NV7 Motherboard) + +pci:v000010DEd00000088* + ID_MODEL_FROM_DATABASE=MCP2A USB Controller + +pci:v000010DEd00000088sv0000147Bsd00001C09* + ID_MODEL_FROM_DATABASE=MCP2A USB Controller (NV7 Motherboard) + +pci:v000010DEd0000008A* + ID_MODEL_FROM_DATABASE=MCP2S AC'97 Audio Controller + +pci:v000010DEd0000008Asv0000147Bsd00001C09* + ID_MODEL_FROM_DATABASE=MCP2S AC'97 Audio Controller (NV7 Motherboard) + +pci:v000010DEd0000008B* + ID_MODEL_FROM_DATABASE=MCP2A PCI Bridge + +pci:v000010DEd0000008C* + ID_MODEL_FROM_DATABASE=MCP2A Ethernet Controller + +pci:v000010DEd0000008E* + ID_MODEL_FROM_DATABASE=nForce2 Serial ATA Controller + +pci:v000010DEd00000090* + ID_MODEL_FROM_DATABASE=G70 [GeForce 7800 GTX] + +pci:v000010DEd00000091* + ID_MODEL_FROM_DATABASE=G70 [GeForce 7800 GTX] + +pci:v000010DEd00000092* + ID_MODEL_FROM_DATABASE=G70 [GeForce 7800 GT] + +pci:v000010DEd00000093* + ID_MODEL_FROM_DATABASE=G70 [GeForce 7800 GS] + +pci:v000010DEd00000095* + ID_MODEL_FROM_DATABASE=G70 [GeForce 7800 SLI] + +pci:v000010DEd00000097* + ID_MODEL_FROM_DATABASE=G70 [GeForce GTS 250] + +pci:v000010DEd00000098* + ID_MODEL_FROM_DATABASE=G70M [GeForce Go 7800] + +pci:v000010DEd00000099* + ID_MODEL_FROM_DATABASE=G70M [GeForce Go 7800 GTX] + +pci:v000010DEd0000009D* + ID_MODEL_FROM_DATABASE=G70GL [Quadro FX 4500] + +pci:v000010DEd000000A0* + ID_MODEL_FROM_DATABASE=NV0A [Aladdin TNT2 IGP] + +pci:v000010DEd000000A0sv000014AFsd00005810* + ID_MODEL_FROM_DATABASE=NV0A [Aladdin TNT2 IGP] (Maxi Gamer Xentor) + +pci:v000010DEd000000C0* + ID_MODEL_FROM_DATABASE=NV41 [GeForce 6800 GS] + +pci:v000010DEd000000C1* + ID_MODEL_FROM_DATABASE=NV41 [GeForce 6800] + +pci:v000010DEd000000C2* + ID_MODEL_FROM_DATABASE=NV41 [GeForce 6800 LE] + +pci:v000010DEd000000C3* + ID_MODEL_FROM_DATABASE=NV41 [GeForce 6800 XT] + +pci:v000010DEd000000C5* + ID_MODEL_FROM_DATABASE=NV41 + +pci:v000010DEd000000C6* + ID_MODEL_FROM_DATABASE=NV41 + +pci:v000010DEd000000C7* + ID_MODEL_FROM_DATABASE=NV41 + +pci:v000010DEd000000C8* + ID_MODEL_FROM_DATABASE=NV41M [GeForce Go 6800] + +pci:v000010DEd000000C9* + ID_MODEL_FROM_DATABASE=NV41M [GeForce Go 6800 Ultra] + +pci:v000010DEd000000CC* + ID_MODEL_FROM_DATABASE=NV41GLM [Quadro FX Go1400] + +pci:v000010DEd000000CD* + ID_MODEL_FROM_DATABASE=NV42GL [Quadro FX 3450/4000 SDI] + +pci:v000010DEd000000CDsv000010DEsd0000029B* + ID_MODEL_FROM_DATABASE=NV42GL [Quadro FX 3450/4000 SDI] (Quadro FX 3450) + +pci:v000010DEd000000CE* + ID_MODEL_FROM_DATABASE=NV41GL [Quadro FX 1400] + +pci:v000010DEd000000CF* + ID_MODEL_FROM_DATABASE=NV41 + +pci:v000010DEd000000D0* + ID_MODEL_FROM_DATABASE=nForce3 LPC Bridge + +pci:v000010DEd000000D1* + ID_MODEL_FROM_DATABASE=nForce3 Host Bridge + +pci:v000010DEd000000D2* + ID_MODEL_FROM_DATABASE=nForce3 AGP Bridge + +pci:v000010DEd000000D3* + ID_MODEL_FROM_DATABASE=CK804 Memory Controller + +pci:v000010DEd000000D4* + ID_MODEL_FROM_DATABASE=nForce3 SMBus + +pci:v000010DEd000000D5* + ID_MODEL_FROM_DATABASE=nForce3 IDE + +pci:v000010DEd000000D6* + ID_MODEL_FROM_DATABASE=nForce3 Ethernet + +pci:v000010DEd000000D7* + ID_MODEL_FROM_DATABASE=nForce3 USB 1.1 + +pci:v000010DEd000000D8* + ID_MODEL_FROM_DATABASE=nForce3 USB 2.0 + +pci:v000010DEd000000D9* + ID_MODEL_FROM_DATABASE=nForce3 Audio + +pci:v000010DEd000000DA* + ID_MODEL_FROM_DATABASE=nForce3 Audio + +pci:v000010DEd000000DD* + ID_MODEL_FROM_DATABASE=nForce3 PCI Bridge + +pci:v000010DEd000000DF* + ID_MODEL_FROM_DATABASE=CK8S Ethernet Controller + +pci:v000010DEd000000DFsv00001043sd000080A7* + ID_MODEL_FROM_DATABASE=CK8S Ethernet Controller (K8N-E) + +pci:v000010DEd000000DFsv0000105Bsd00000C43* + ID_MODEL_FROM_DATABASE=CK8S Ethernet Controller (Winfast NF3250K8AA) + +pci:v000010DEd000000DFsv0000147Bsd00001C0B* + ID_MODEL_FROM_DATABASE=CK8S Ethernet Controller (NF8 Mainboard) + +pci:v000010DEd000000E0* + ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge + +pci:v000010DEd000000E0sv00001043sd0000813F* + ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge (K8N-E) + +pci:v000010DEd000000E0sv000010DEsd00000C11* + ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge (Winfast NF3250K8AA) + +pci:v000010DEd000000E0sv00001462sd00007030* + ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge (K8N Neo-FSR v2.0) + +pci:v000010DEd000000E0sv0000147Bsd00001C0B* + ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge (NF8 Mainboard) + +pci:v000010DEd000000E0sv00001849sd000000E0* + ID_MODEL_FROM_DATABASE=nForce3 250Gb LPC Bridge (Motherboard (one of many)) + +pci:v000010DEd000000E1* + ID_MODEL_FROM_DATABASE=nForce3 250Gb Host Bridge + +pci:v000010DEd000000E1sv00001043sd0000813F* + ID_MODEL_FROM_DATABASE=nForce3 250Gb Host Bridge (K8N-E) + +pci:v000010DEd000000E1sv00001462sd00007030* + ID_MODEL_FROM_DATABASE=nForce3 250Gb Host Bridge (K8N Neo-FSR v2.0) + +pci:v000010DEd000000E1sv0000147Bsd00001C0B* + ID_MODEL_FROM_DATABASE=nForce3 250Gb Host Bridge (NF8 Mainboard) + +pci:v000010DEd000000E1sv00001849sd000000E1* + ID_MODEL_FROM_DATABASE=nForce3 250Gb Host Bridge (Motherboard (one of many)) + +pci:v000010DEd000000E2* + ID_MODEL_FROM_DATABASE=nForce3 250Gb AGP Host to PCI Bridge + +pci:v000010DEd000000E3* + ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller + +pci:v000010DEd000000E3sv00001043sd0000813F* + ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller (K8N-E) + +pci:v000010DEd000000E3sv0000105Bsd00000C43* + ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller (Winfast NF3250K8AA) + +pci:v000010DEd000000E3sv0000147Bsd00001C0B* + ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller (NF8 Mainboard) + +pci:v000010DEd000000E3sv00001849sd000000E3* + ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller (Motherboard (one of many)) + +pci:v000010DEd000000E4* + ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management + +pci:v000010DEd000000E4sv00001043sd0000813F* + ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management (K8N-E) + +pci:v000010DEd000000E4sv0000105Bsd00000C43* + ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management (Winfast NF3250K8AA) + +pci:v000010DEd000000E4sv00001462sd00007030* + ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management (K8N Neo-FSR v2.0) + +pci:v000010DEd000000E4sv0000147Bsd00001C0B* + ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management (NF8 Mainboard) + +pci:v000010DEd000000E4sv00001849sd000000E4* + ID_MODEL_FROM_DATABASE=nForce 250Gb PCI System Management (Motherboard (one of many)) + +pci:v000010DEd000000E5* + ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) + +pci:v000010DEd000000E5sv00001043sd0000813F* + ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (K8N-E) + +pci:v000010DEd000000E5sv0000105Bsd00000C43* + ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (Winfast NF3250K8AA) + +pci:v000010DEd000000E5sv00001462sd00007030* + ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (K8N Neo-FSR v2.0) + +pci:v000010DEd000000E5sv0000147Bsd00001C0B* + ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (NF8 Mainboard) + +pci:v000010DEd000000E5sv00001849sd000000E5* + ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (Motherboard (one of many)) + +pci:v000010DEd000000E5sv0000F849sd000000E5* + ID_MODEL_FROM_DATABASE=CK8S Parallel ATA Controller (v2.5) (Motherboard (one of many)) + +pci:v000010DEd000000E6* + ID_MODEL_FROM_DATABASE=CK8S Ethernet Controller + +pci:v000010DEd000000E7* + ID_MODEL_FROM_DATABASE=CK8S USB Controller + +pci:v000010DEd000000E7sv00001043sd0000813F* + ID_MODEL_FROM_DATABASE=CK8S USB Controller (K8N-E) + +pci:v000010DEd000000E7sv0000105Bsd00000C43* + ID_MODEL_FROM_DATABASE=CK8S USB Controller (Winfast NF3250K8AA) + +pci:v000010DEd000000E7sv00001462sd00007030* + ID_MODEL_FROM_DATABASE=CK8S USB Controller (K8N Neo-FSR v2.0) + +pci:v000010DEd000000E7sv0000147Bsd00001C0B* + ID_MODEL_FROM_DATABASE=CK8S USB Controller (NF8 Mainboard) + +pci:v000010DEd000000E7sv00001849sd000000E7* + ID_MODEL_FROM_DATABASE=CK8S USB Controller (Motherboard (one of many)) + +pci:v000010DEd000000E8* + ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller + +pci:v000010DEd000000E8sv00001043sd0000813F* + ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller (K8N-E) + +pci:v000010DEd000000E8sv0000105Bsd00000C43* + ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller (Winfast NF3250K8AA) + +pci:v000010DEd000000E8sv00001462sd00007030* + ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller (K8N Neo-FSR v2.0) + +pci:v000010DEd000000E8sv0000147Bsd00001C0B* + ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller (NF8 Mainboard) + +pci:v000010DEd000000E8sv00001849sd000000E8* + ID_MODEL_FROM_DATABASE=nForce3 EHCI USB 2.0 Controller (Motherboard (one of many)) + +pci:v000010DEd000000EA* + ID_MODEL_FROM_DATABASE=nForce3 250Gb AC'97 Audio Controller + +pci:v000010DEd000000EAsv00001043sd0000819D* + ID_MODEL_FROM_DATABASE=nForce3 250Gb AC'97 Audio Controller (K8N-E) + +pci:v000010DEd000000EAsv0000105Bsd00000C43* + ID_MODEL_FROM_DATABASE=nForce3 250Gb AC'97 Audio Controller (Winfast NF3250K8AA) + +pci:v000010DEd000000EAsv00001462sd0000B010* + ID_MODEL_FROM_DATABASE=nForce3 250Gb AC'97 Audio Controller (K8N Neo-FSR v2.0) + +pci:v000010DEd000000EAsv0000147Bsd00001C0B* + ID_MODEL_FROM_DATABASE=nForce3 250Gb AC'97 Audio Controller (NF8 Mainboard) + +pci:v000010DEd000000ED* + ID_MODEL_FROM_DATABASE=nForce3 250Gb PCI-to-PCI Bridge + +pci:v000010DEd000000EE* + ID_MODEL_FROM_DATABASE=nForce3 Serial ATA Controller 2 + +pci:v000010DEd000000F1* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] + +pci:v000010DEd000000F1sv00001043sd000081A6* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (N6600GT TD 128M AGP) + +pci:v000010DEd000000F1sv00001043sd000081C6* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (N6600GT TD 128M AGP) + +pci:v000010DEd000000F1sv00001458sd00003150* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (GV-N66T128VP) + +pci:v000010DEd000000F1sv00001554sd00001191* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (PixelView PV-N43UA (128KD)) + +pci:v000010DEd000000F1sv00001682sd00002119* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (GeForce 6600 GT AGP) + +pci:v000010DEd000000F2* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] + +pci:v000010DEd000000F2sv00001554sd00001194* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (PixelView PV-N43AT (256KD)) + +pci:v000010DEd000000F2sv00001682sd0000211C* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (GeForce 6600 256MB DDR DUAL DVI TV) + +pci:v000010DEd000000F3* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6200] + +pci:v000010DEd000000F4* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 LE] + +pci:v000010DEd000000F5* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7800 GS] + +pci:v000010DEd000000F6* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6800 GS/XT] + +pci:v000010DEd000000F6sv00001682sd0000217E* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6800 GS/XT] (XFX GeForce 6800 XTreme 256MB DDR3 AGP) + +pci:v000010DEd000000F8* + ID_MODEL_FROM_DATABASE=NV45GL [Quadro FX 3400/4400] + +pci:v000010DEd000000F9* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT/GTO/Ultra] + +pci:v000010DEd000000F9sv000010DEsd000000F9* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT/GTO/Ultra] (NV40 [GeForce 6800 GT]) + +pci:v000010DEd000000F9sv00001682sd00002120* + ID_MODEL_FROM_DATABASE=NV40 [GeForce 6800 GT/GTO/Ultra] (GEFORCE 6800 GT PCI-E) + +pci:v000010DEd000000FA* + ID_MODEL_FROM_DATABASE=NV39 [GeForce PCX 5750] + +pci:v000010DEd000000FB* + ID_MODEL_FROM_DATABASE=NV35 [GeForce PCX 5900] + +pci:v000010DEd000000FC* + ID_MODEL_FROM_DATABASE=NV37GL [Quadro FX 330/GeForce PCX 5300] + +pci:v000010DEd000000FD* + ID_MODEL_FROM_DATABASE=NV37GL [Quadro PCI-E Series] + +pci:v000010DEd000000FE* + ID_MODEL_FROM_DATABASE=NV38GL [Quadro FX 1300] + +pci:v000010DEd000000FF* + ID_MODEL_FROM_DATABASE=NV19 [GeForce PCX 4300] + +pci:v000010DEd00000100* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] + +pci:v000010DEd00000100sv00001043sd00000200* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (AGP-V6600 SGRAM) + +pci:v000010DEd00000100sv00001043sd00000201* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (AGP-V6600 SDRAM) + +pci:v000010DEd00000100sv00001043sd00004008* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (AGP-V6600 SGRAM) + +pci:v000010DEd00000100sv00001043sd00004009* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (AGP-V6600 SDRAM) + +pci:v000010DEd00000100sv00001048sd00000C41* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (Erazor X) + +pci:v000010DEd00000100sv00001048sd00000C43* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (ERAZOR X PCI) + +pci:v000010DEd00000100sv00001048sd00000C48* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (Synergy Force) + +pci:v000010DEd00000100sv00001102sd0000102D* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (CT6941 GeForce 256) + +pci:v000010DEd00000100sv000014AFsd00005022* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 SDR] (3D Prophet SE) + +pci:v000010DEd00000101* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] + +pci:v000010DEd00000101sv00001043sd00000202* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (AGP-V6800 DDR) + +pci:v000010DEd00000101sv00001043sd0000400A* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (AGP-V6800 DDR SGRAM) + +pci:v000010DEd00000101sv00001043sd0000400B* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (AGP-V6800 DDR SDRAM) + +pci:v000010DEd00000101sv00001048sd00000C42* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (Erazor X) + +pci:v000010DEd00000101sv0000107Dsd00002822* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (WinFast GeForce 256) + +pci:v000010DEd00000101sv00001102sd0000102E* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (CT6970/CT6971) + +pci:v000010DEd00000101sv000014AFsd00005021* + ID_MODEL_FROM_DATABASE=NV10 [GeForce 256 DDR] (3D Prophet DDR-DVI) + +pci:v000010DEd00000103* + ID_MODEL_FROM_DATABASE=NV10GL [Quadro] + +pci:v000010DEd00000103sv00001048sd00000C40* + ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (GLoria II-64) + +pci:v000010DEd00000103sv00001048sd00000C44* + ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (GLoria II) + +pci:v000010DEd00000103sv00001048sd00000C45* + ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (GLoria II) + +pci:v000010DEd00000103sv00001048sd00000C4A* + ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (GLoria II-64 Pro) + +pci:v000010DEd00000103sv00001048sd00000C4B* + ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (GLoria II-64 Pro DVII) + +pci:v000010DEd00000103sv000010A9sd00009002* + ID_MODEL_FROM_DATABASE=NV10GL [Quadro] (VPro VR3) + +pci:v000010DEd00000110* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] + +pci:v000010DEd00000110sv00001043sd00004015* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (AGP-V7100 Pro) + +pci:v000010DEd00000110sv00001043sd00004021* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (V7100 Deluxe Combo) + +pci:v000010DEd00000110sv00001043sd00004031* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (V7100 Pro with TV output) + +pci:v000010DEd00000110sv00001048sd00000C60* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac MX) + +pci:v000010DEd00000110sv00001048sd00000C61* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac 511PCI) + +pci:v000010DEd00000110sv00001048sd00000C63* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac 511TV-OUT 32MB) + +pci:v000010DEd00000110sv00001048sd00000C64* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac 511TV-OUT 64MB) + +pci:v000010DEd00000110sv00001048sd00000C65* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac 511TWIN) + +pci:v000010DEd00000110sv00001048sd00000C66* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Gladiac 311) + +pci:v000010DEd00000110sv000010B0sd00000001* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (GeForce2 MX Jumbo TV) + +pci:v000010DEd00000110sv000010DEsd00000091* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Dell OEM GeForce 2 MX 400) + +pci:v000010DEd00000110sv000010DEsd000000A1* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Apple OEM GeForce2 MX) + +pci:v000010DEd00000110sv00001462sd00008523* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (MS-8852) + +pci:v000010DEd00000110sv00001462sd00008817* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (MSI GeForce2 MX400 Pro32S [MS-8817]) + +pci:v000010DEd00000110sv000014AFsd00007102* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (3D Prophet II MX) + +pci:v000010DEd00000110sv000014AFsd00007103* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (3D Prophet II MX Dual-Display) + +pci:v000010DEd00000110sv00001545sd00000023* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (Xtasy Rev. B2) + +pci:v000010DEd00000110sv00001554sd00001081* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX/MX 400] (MVGA-NVG11AM(400)) + +pci:v000010DEd00000111* + ID_MODEL_FROM_DATABASE=NV11 [GeForce2 MX200] + +pci:v000010DEd00000112* + ID_MODEL_FROM_DATABASE=NV11M [GeForce2 Go] + +pci:v000010DEd00000113* + ID_MODEL_FROM_DATABASE=NV11GL [Quadro2 MXR/EX/Go] + +pci:v000010DEd00000113sv00001028sd000000E5* + ID_MODEL_FROM_DATABASE=NV11GL [Quadro2 MXR/EX/Go] (Quadro2 Go) + +pci:v000010DEd00000140* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] + +pci:v000010DEd00000140sv00001458sd00003125* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (GV-NX66T128D) + +pci:v000010DEd00000140sv00001458sd00003126* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (GV-NX66T256DE) + +pci:v000010DEd00000140sv00001462sd00008939* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 GT] (MS-8983) + +pci:v000010DEd00000141* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] + +pci:v000010DEd00000141sv00001043sd000081B0* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (EN6600 Silencer) + +pci:v000010DEd00000141sv0000107Dsd0000593A* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (LR2A22 128MB TV OUT) + +pci:v000010DEd00000141sv0000107Dsd0000597B* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (WINFAST PX6600) + +pci:v000010DEd00000141sv00001458sd00003124* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600] (GV-NX66128DP Turbo Force Edition) + +pci:v000010DEd00000142* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 LE] + +pci:v000010DEd00000143* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6600 VE] + +pci:v000010DEd00000144* + ID_MODEL_FROM_DATABASE=NV43M [GeForce Go 6600] + +pci:v000010DEd00000145* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6610 XL] + +pci:v000010DEd00000146* + ID_MODEL_FROM_DATABASE=NV43M [GeForce Go6200 TE / 6600 TE] + +pci:v000010DEd00000147* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6700 XL] + +pci:v000010DEd00000148* + ID_MODEL_FROM_DATABASE=NV43M [GeForce Go 6600] + +pci:v000010DEd00000149* + ID_MODEL_FROM_DATABASE=NV43M [GeForce Go 6600 GT] + +pci:v000010DEd0000014A* + ID_MODEL_FROM_DATABASE=NV43 [Quadro NVS 440] + +pci:v000010DEd0000014B* + ID_MODEL_FROM_DATABASE=NV43 + +pci:v000010DEd0000014D* + ID_MODEL_FROM_DATABASE=NV43GL [Quadro FX 550] + +pci:v000010DEd0000014E* + ID_MODEL_FROM_DATABASE=NV43GL [Quadro FX 540] + +pci:v000010DEd0000014F* + ID_MODEL_FROM_DATABASE=NV43 [GeForce 6200] + +pci:v000010DEd00000150* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] + +pci:v000010DEd00000150sv00001043sd00004016* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (V7700 AGP Video Card) + +pci:v000010DEd00000150sv00001043sd0000402A* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (AGP-V7700) + +pci:v000010DEd00000150sv00001048sd00000C50* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (Gladiac) + +pci:v000010DEd00000150sv00001048sd00000C52* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (Gladiac-64) + +pci:v000010DEd00000150sv0000107Dsd00002840* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (WinFast GeForce2 GTS with TV output) + +pci:v000010DEd00000150sv0000107Dsd00002842* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (WinFast GeForce 2 Pro) + +pci:v000010DEd00000150sv000010DEsd0000002E* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (GeForce2 GTS) + +pci:v000010DEd00000150sv00001462sd0000815A* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (MS-8815) + +pci:v000010DEd00000150sv00001462sd00008831* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 GTS/Pro] (Creative GeForce2 Pro) + +pci:v000010DEd00000151* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ti] + +pci:v000010DEd00000151sv00001043sd0000405F* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ti] (V7700Ti) + +pci:v000010DEd00000151sv00001462sd00005506* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ti] (Creative 3D Blaster GeForce2 Titanium) + +pci:v000010DEd00000151sv00001462sd00008364* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ti] (MS-8836) + +pci:v000010DEd00000152* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ultra] + +pci:v000010DEd00000152sv00001048sd00000C56* + ID_MODEL_FROM_DATABASE=NV15 [GeForce2 Ultra] (GLADIAC Ultra) + +pci:v000010DEd00000153* + ID_MODEL_FROM_DATABASE=NV15GL [Quadro2 Pro] + +pci:v000010DEd00000160* + ID_MODEL_FROM_DATABASE=NV44 [GeForce 6500] + +pci:v000010DEd00000161* + ID_MODEL_FROM_DATABASE=NV44 [GeForce 6200 TurboCache] + +pci:v000010DEd00000162* + ID_MODEL_FROM_DATABASE=NV44 [GeForce 6200 SE TurboCache] + +pci:v000010DEd00000163* + ID_MODEL_FROM_DATABASE=NV44 [GeForce 6200 LE] + +pci:v000010DEd00000164* + ID_MODEL_FROM_DATABASE=NV44M [GeForce Go 6200] + +pci:v000010DEd00000165* + ID_MODEL_FROM_DATABASE=NV44 [Quadro NVS 285] + +pci:v000010DEd00000166* + ID_MODEL_FROM_DATABASE=NV44M [GeForce Go 6400] + +pci:v000010DEd00000167* + ID_MODEL_FROM_DATABASE=NV44M [GeForce Go 6200] + +pci:v000010DEd00000168* + ID_MODEL_FROM_DATABASE=NV44M [GeForce Go 6400] + +pci:v000010DEd00000169* + ID_MODEL_FROM_DATABASE=NV44 [GeForce 6250] + +pci:v000010DEd0000016A* + ID_MODEL_FROM_DATABASE=NV44 [GeForce 7100 GS] + +pci:v000010DEd0000016D* + ID_MODEL_FROM_DATABASE=NV44 + +pci:v000010DEd0000016E* + ID_MODEL_FROM_DATABASE=NV44 + +pci:v000010DEd0000016F* + ID_MODEL_FROM_DATABASE=NV44 + +pci:v000010DEd00000170* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 460] + +pci:v000010DEd00000170sv00001462sd00008630* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 460] (MS-8863) + +pci:v000010DEd00000171* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] + +pci:v000010DEd00000171sv000010B0sd00000002* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (Gainward Pro/600 TV) + +pci:v000010DEd00000171sv000010DEsd00000008* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (Apple OEM GeForce4 MX 440) + +pci:v000010DEd00000171sv00001462sd00008661* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (G4MX440-VTP) + +pci:v000010DEd00000171sv00001462sd00008730* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (MX440SES-T (MS-8873)) + +pci:v000010DEd00000171sv00001462sd00008743* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (MS-8874) + +pci:v000010DEd00000171sv00001462sd00008852* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (GeForce4 MX440 PCI) + +pci:v000010DEd00000171sv0000147Bsd00008F00* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440] (Abit Siluro GeForce4MX440) + +pci:v000010DEd00000172* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 420] + +pci:v000010DEd00000172sv00001462sd00008730* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 420] (MS-8873) + +pci:v000010DEd00000172sv00001462sd00008784* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 420] (MS-8878) + +pci:v000010DEd00000173* + ID_MODEL_FROM_DATABASE=NV17 [GeForce4 MX 440-SE] + +pci:v000010DEd00000174* + ID_MODEL_FROM_DATABASE=NV17M [GeForce4 440 Go] + +pci:v000010DEd00000175* + ID_MODEL_FROM_DATABASE=NV17M [GeForce4 420 Go] + +pci:v000010DEd00000176* + ID_MODEL_FROM_DATABASE=NV17M [GeForce4 420 Go 32M] + +pci:v000010DEd00000176sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=NV17M [GeForce4 420 Go 32M] (tc1100 tablet) + +pci:v000010DEd00000176sv0000144Dsd0000C005* + ID_MODEL_FROM_DATABASE=NV17M [GeForce4 420 Go 32M] (X10 Laptop) + +pci:v000010DEd00000176sv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=NV17M [GeForce4 420 Go 32M] (Cx9 / Vx9 mainboard) + +pci:v000010DEd00000177* + ID_MODEL_FROM_DATABASE=NV17M [GeForce4 460 Go] + +pci:v000010DEd00000178* + ID_MODEL_FROM_DATABASE=NV17GL [Quadro4 550 XGL] + +pci:v000010DEd00000179* + ID_MODEL_FROM_DATABASE=NV17M [GeForce4 440 Go 64M] + +pci:v000010DEd00000179sv000010DEsd00000179* + ID_MODEL_FROM_DATABASE=NV17M [GeForce4 440 Go 64M] (GeForce4 MX (Mac)) + +pci:v000010DEd0000017A* + ID_MODEL_FROM_DATABASE=NV17GL [Quadro NVS] + +pci:v000010DEd0000017B* + ID_MODEL_FROM_DATABASE=NV17GL [Quadro4 550 XGL] + +pci:v000010DEd0000017C* + ID_MODEL_FROM_DATABASE=NV17GL [Quadro4 500 GoGL] + +pci:v000010DEd0000017F* + ID_MODEL_FROM_DATABASE=NV17 + +pci:v000010DEd00000181* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] + +pci:v000010DEd00000181sv00001043sd00008063* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (GeForce4 MX 440 AGP 8X) + +pci:v000010DEd00000181sv00001043sd0000806F* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (V9180 Magic) + +pci:v000010DEd00000181sv00001462sd00008880* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (MS-StarForce GeForce4 MX 440 with AGP8X) + +pci:v000010DEd00000181sv00001462sd00008900* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (MS-8890 GeForce 4 MX440 AGP8X) + +pci:v000010DEd00000181sv00001462sd00009350* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (MSI GeForce4 MX T8X with AGP8X) + +pci:v000010DEd00000181sv0000147Bsd00008F0D* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (Siluro GF4 MX-8X) + +pci:v000010DEd00000181sv00001554sd00001111* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440 AGP 8x] (PixelView MVGA-NVG18A) + +pci:v000010DEd00000182* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 440SE AGP 8x] + +pci:v000010DEd00000183* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 420 AGP 8x] + +pci:v000010DEd00000184* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX] + +pci:v000010DEd00000185* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX 4000] + +pci:v000010DEd00000186* + ID_MODEL_FROM_DATABASE=NV18M [GeForce4 448 Go] + +pci:v000010DEd00000187* + ID_MODEL_FROM_DATABASE=NV18M [GeForce4 488 Go] + +pci:v000010DEd00000188* + ID_MODEL_FROM_DATABASE=NV18GL [Quadro4 580 XGL] + +pci:v000010DEd00000189* + ID_MODEL_FROM_DATABASE=NV18 [GeForce4 MX with AGP8X (Mac)] + +pci:v000010DEd0000018A* + ID_MODEL_FROM_DATABASE=NV18GL [Quadro NVS 280 SD] + +pci:v000010DEd0000018B* + ID_MODEL_FROM_DATABASE=NV18GL [Quadro4 380 XGL] + +pci:v000010DEd0000018C* + ID_MODEL_FROM_DATABASE=NV18GL [Quadro NVS 50 PCI] + +pci:v000010DEd0000018D* + ID_MODEL_FROM_DATABASE=NV18M [GeForce4 448 Go] + +pci:v000010DEd00000190* + ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 GTS / 8800 GTX] + +pci:v000010DEd00000191* + ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 GTX] + +pci:v000010DEd00000192* + ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 GTS] + +pci:v000010DEd00000193* + ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 GTS] + +pci:v000010DEd00000193sv0000107Dsd000020BD* + ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 GTS] (WinFast PX 8800 GTS TDH) + +pci:v000010DEd00000194* + ID_MODEL_FROM_DATABASE=G80 [GeForce 8800 Ultra] + +pci:v000010DEd00000197* + ID_MODEL_FROM_DATABASE=G80GL [Tesla C870] + +pci:v000010DEd0000019D* + ID_MODEL_FROM_DATABASE=G80GL [Quadro FX 5600] + +pci:v000010DEd0000019E* + ID_MODEL_FROM_DATABASE=G80GL [Quadro FX 4600] + +pci:v000010DEd000001A0* + ID_MODEL_FROM_DATABASE=nForce 220/420 NV1A [GeForce2 MX] + +pci:v000010DEd000001A4* + ID_MODEL_FROM_DATABASE=nForce CPU bridge + +pci:v000010DEd000001AB* + ID_MODEL_FROM_DATABASE=nForce 420 Memory Controller (DDR) + +pci:v000010DEd000001AC* + ID_MODEL_FROM_DATABASE=nForce 220/420 Memory Controller + +pci:v000010DEd000001AD* + ID_MODEL_FROM_DATABASE=nForce 220/420 Memory Controller + +pci:v000010DEd000001B0* + ID_MODEL_FROM_DATABASE=nForce Audio Processing Unit + +pci:v000010DEd000001B1* + ID_MODEL_FROM_DATABASE=nForce AC'97 Audio Controller + +pci:v000010DEd000001B2* + ID_MODEL_FROM_DATABASE=nForce ISA Bridge + +pci:v000010DEd000001B4* + ID_MODEL_FROM_DATABASE=nForce PCI System Management + +pci:v000010DEd000001B7* + ID_MODEL_FROM_DATABASE=nForce AGP to PCI Bridge + +pci:v000010DEd000001B8* + ID_MODEL_FROM_DATABASE=nForce PCI-to-PCI bridge + +pci:v000010DEd000001BC* + ID_MODEL_FROM_DATABASE=nForce IDE + +pci:v000010DEd000001C1* + ID_MODEL_FROM_DATABASE=nForce AC'97 Modem Controller + +pci:v000010DEd000001C2* + ID_MODEL_FROM_DATABASE=nForce USB Controller + +pci:v000010DEd000001C3* + ID_MODEL_FROM_DATABASE=nForce Ethernet Controller + +pci:v000010DEd000001D0* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7350 LE] + +pci:v000010DEd000001D1* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7300 LE] + +pci:v000010DEd000001D1sv0000107Dsd00005EFA* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7300 LE] (WinFast PX7300LE-TD128) + +pci:v000010DEd000001D1sv0000107Dsd00005EFB* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7300 LE] (WinFast PX7300LE-TD256) + +pci:v000010DEd000001D1sv00001462sd00000345* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7300 LE] (7300LE PCI Express Graphics Adapter) + +pci:v000010DEd000001D2* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7550 LE] + +pci:v000010DEd000001D3* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7200 GS / 7300 SE] + +pci:v000010DEd000001D3sv00001043sd00008203* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7200 GS / 7300 SE] (EN7300SE) + +pci:v000010DEd000001D3sv00001043sd00008250* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7200 GS / 7300 SE] (EN7200GS) + +pci:v000010DEd000001D5* + ID_MODEL_FROM_DATABASE=G72 + +pci:v000010DEd000001D6* + ID_MODEL_FROM_DATABASE=G72M [GeForce Go 7200] + +pci:v000010DEd000001D7* + ID_MODEL_FROM_DATABASE=G72M [Quadro NVS 110M/GeForce Go 7300] + +pci:v000010DEd000001D8* + ID_MODEL_FROM_DATABASE=G72M [GeForce Go 7400] + +pci:v000010DEd000001D8sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=G72M [GeForce Go 7400] (XPS M1210) + +pci:v000010DEd000001D9* + ID_MODEL_FROM_DATABASE=G72M [GeForce Go 7450] + +pci:v000010DEd000001DA* + ID_MODEL_FROM_DATABASE=G72M [Quadro NVS 110M] + +pci:v000010DEd000001DB* + ID_MODEL_FROM_DATABASE=G72M [Quadro NVS 120M] + +pci:v000010DEd000001DC* + ID_MODEL_FROM_DATABASE=G72GLM [Quadro FX 350M] + +pci:v000010DEd000001DD* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7500 LE] + +pci:v000010DEd000001DE* + ID_MODEL_FROM_DATABASE=G72GL [Quadro FX 350] + +pci:v000010DEd000001DEsv000010DEsd000001DC* + ID_MODEL_FROM_DATABASE=G72GL [Quadro FX 350] (Quadro FX Go350M) + +pci:v000010DEd000001DF* + ID_MODEL_FROM_DATABASE=G72 [GeForce 7300 GS] + +pci:v000010DEd000001E0* + ID_MODEL_FROM_DATABASE=nForce2 IGP2 + +pci:v000010DEd000001E0sv0000147Bsd00001C09* + ID_MODEL_FROM_DATABASE=nForce2 IGP2 (NV7 Motherboard) + +pci:v000010DEd000001E8* + ID_MODEL_FROM_DATABASE=nForce2 AGP + +pci:v000010DEd000001EA* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 0 + +pci:v000010DEd000001EAsv0000A0A0sd000003B9* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 0 (UK79G-1394 motherboard) + +pci:v000010DEd000001EB* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 1 + +pci:v000010DEd000001EBsv0000A0A0sd000003B9* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 1 (UK79G-1394 motherboard) + +pci:v000010DEd000001EC* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 2 + +pci:v000010DEd000001ECsv0000A0A0sd000003B9* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 2 (UK79G-1394 motherboard) + +pci:v000010DEd000001ED* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 3 + +pci:v000010DEd000001EDsv0000A0A0sd000003B9* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 3 (UK79G-1394 motherboard) + +pci:v000010DEd000001EE* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 4 + +pci:v000010DEd000001EEsv000010DEsd000001EE* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 4 (MSI Delta-L nForce2 memory controller) + +pci:v000010DEd000001EEsv0000A0A0sd000003B9* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 4 (UK79G-1394 motherboard) + +pci:v000010DEd000001EF* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 5 + +pci:v000010DEd000001EFsv0000A0A0sd000003B9* + ID_MODEL_FROM_DATABASE=nForce2 Memory Controller 5 (UK79G-1394 motherboard) + +pci:v000010DEd000001F0* + ID_MODEL_FROM_DATABASE=NV1F C17 [GeForce4 MX IGP] + +pci:v000010DEd000001F0sv0000A0A0sd000003B5* + ID_MODEL_FROM_DATABASE=NV1F C17 [GeForce4 MX IGP] (UK79G-1394 motherboard) + +pci:v000010DEd00000200* + ID_MODEL_FROM_DATABASE=NV20 [GeForce3] + +pci:v000010DEd00000200sv00001043sd0000402F* + ID_MODEL_FROM_DATABASE=NV20 [GeForce3] (AGP-V8200 DDR) + +pci:v000010DEd00000200sv00001048sd00000C70* + ID_MODEL_FROM_DATABASE=NV20 [GeForce3] (GLADIAC 920) + +pci:v000010DEd00000201* + ID_MODEL_FROM_DATABASE=NV20 [GeForce3 Ti 200] + +pci:v000010DEd00000202* + ID_MODEL_FROM_DATABASE=NV20 [GeForce3 Ti 500] + +pci:v000010DEd00000202sv00001043sd0000405B* + ID_MODEL_FROM_DATABASE=NV20 [GeForce3 Ti 500] (V8200 T5) + +pci:v000010DEd00000202sv00001545sd0000002F* + ID_MODEL_FROM_DATABASE=NV20 [GeForce3 Ti 500] (Xtasy 6964) + +pci:v000010DEd00000203* + ID_MODEL_FROM_DATABASE=NV20GL [Quadro DCC] + +pci:v000010DEd00000211* + ID_MODEL_FROM_DATABASE=NV48 [GeForce 6800] + +pci:v000010DEd00000212* + ID_MODEL_FROM_DATABASE=NV48 [GeForce 6800 LE] + +pci:v000010DEd00000215* + ID_MODEL_FROM_DATABASE=NV48 [GeForce 6800 GT] + +pci:v000010DEd00000218* + ID_MODEL_FROM_DATABASE=NV48 [GeForce 6800 XT] + +pci:v000010DEd00000221* + ID_MODEL_FROM_DATABASE=NV44A [GeForce 6200] + +pci:v000010DEd00000221sv00001043sd000081E1* + ID_MODEL_FROM_DATABASE=NV44A [GeForce 6200] (N6200/TD/256M/A) + +pci:v000010DEd00000221sv00003842sd0000A341* + ID_MODEL_FROM_DATABASE=NV44A [GeForce 6200] (256A8N341DX) + +pci:v000010DEd00000222* + ID_MODEL_FROM_DATABASE=NV44 [GeForce 6200 A-LE] + +pci:v000010DEd00000224* + ID_MODEL_FROM_DATABASE=NV44 + +pci:v000010DEd00000240* + ID_MODEL_FROM_DATABASE=C51PV [GeForce 6150] + +pci:v000010DEd00000240sv00001043sd000081CD* + ID_MODEL_FROM_DATABASE=C51PV [GeForce 6150] (A8N-VM CSM) + +pci:v000010DEd00000240sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=C51PV [GeForce 6150] (K8NGM2 series) + +pci:v000010DEd00000241* + ID_MODEL_FROM_DATABASE=C51 [GeForce 6150 LE] + +pci:v000010DEd00000242* + ID_MODEL_FROM_DATABASE=C51G [GeForce 6100] + +pci:v000010DEd00000242sv0000105Bsd00000CAD* + ID_MODEL_FROM_DATABASE=C51G [GeForce 6100] (Winfast 6100K8MB) + +pci:v000010DEd00000243* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd00000244* + ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6150] + +pci:v000010DEd00000244sv0000103Csd000030B5* + ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6150] (Presario V3242AU) + +pci:v000010DEd00000244sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6150] (Presario V6133CL) + +pci:v000010DEd00000244sv000010DEsd00000244* + ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6150] (GeForce Go 6150) + +pci:v000010DEd00000245* + ID_MODEL_FROM_DATABASE=C51 [Quadro NVS 210S/GeForce 6150LE] + +pci:v000010DEd00000246* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd00000247* + ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6100] + +pci:v000010DEd00000247sv00001043sd00001382* + ID_MODEL_FROM_DATABASE=C51 [GeForce Go 6100] (MCP51 PCI-X GeForce Go 6100) + +pci:v000010DEd00000248* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd00000249* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd0000024A* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd0000024B* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd0000024C* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd0000024D* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd0000024E* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd0000024F* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd00000250* + ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4600] + +pci:v000010DEd00000251* + ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4400] + +pci:v000010DEd00000251sv00001043sd00008023* + ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4400] (v8440 GeForce 4 Ti4400) + +pci:v000010DEd00000251sv000010DEsd00000251* + ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4400] (PNY GeForce4 Ti 4400) + +pci:v000010DEd00000251sv00001462sd00008710* + ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4400] (PNY GeForce4 Ti 4400) + +pci:v000010DEd00000252* + ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti] + +pci:v000010DEd00000253* + ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4200] + +pci:v000010DEd00000253sv0000107Dsd00002896* + ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4200] (WinFast A250 LE TD (Dual VGA/TV-out/DVI)) + +pci:v000010DEd00000253sv0000147Bsd00008F09* + ID_MODEL_FROM_DATABASE=NV25 [GeForce4 Ti 4200] (Siluro (Dual VGA/TV-out/DVI)) + +pci:v000010DEd00000258* + ID_MODEL_FROM_DATABASE=NV25GL [Quadro4 900 XGL] + +pci:v000010DEd00000259* + ID_MODEL_FROM_DATABASE=NV25GL [Quadro4 750 XGL] + +pci:v000010DEd0000025B* + ID_MODEL_FROM_DATABASE=NV25GL [Quadro4 700 XGL] + +pci:v000010DEd00000260* + ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge + +pci:v000010DEd00000260sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (Pavilion a1677c) + +pci:v000010DEd00000260sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (Presario V6133CL) + +pci:v000010DEd00000260sv00001043sd000081BC* + ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (A8N-VM CSM Mainboard) + +pci:v000010DEd00000260sv00001458sd00005001* + ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (GA-M55plus-S3G) + +pci:v000010DEd00000260sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (K8NGM2 series) + +pci:v000010DEd00000261* + ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge + +pci:v000010DEd00000261sv0000105Bsd00000CAD* + ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge (Winfast 6100K8MB) + +pci:v000010DEd00000262* + ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge + +pci:v000010DEd00000263* + ID_MODEL_FROM_DATABASE=MCP51 LPC Bridge + +pci:v000010DEd00000264* + ID_MODEL_FROM_DATABASE=MCP51 SMBus + +pci:v000010DEd00000264sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 SMBus (Pavilion a1677c) + +pci:v000010DEd00000264sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 SMBus (Presario V6133CL) + +pci:v000010DEd00000264sv00001043sd000081BC* + ID_MODEL_FROM_DATABASE=MCP51 SMBus (A8N-VM CSM Mainboard) + +pci:v000010DEd00000264sv0000105Bsd00000CAD* + ID_MODEL_FROM_DATABASE=MCP51 SMBus (Winfast 6100K8MB) + +pci:v000010DEd00000264sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=MCP51 SMBus (K8NGM2 series) + +pci:v000010DEd00000265* + ID_MODEL_FROM_DATABASE=MCP51 IDE + +pci:v000010DEd00000265sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 IDE (Pavilion a1677c) + +pci:v000010DEd00000265sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 IDE (Presario V6133CL) + +pci:v000010DEd00000265sv00001043sd000081BC* + ID_MODEL_FROM_DATABASE=MCP51 IDE (A8N-VM CSM Mainboard) + +pci:v000010DEd00000265sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=MCP51 IDE (K8NGM2 series) + +pci:v000010DEd00000265sv0000F05Bsd00000CAD* + ID_MODEL_FROM_DATABASE=MCP51 IDE (Winfast 6100K8MB) + +pci:v000010DEd00000266* + ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller + +pci:v000010DEd00000266sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (Pavilion a1677c) + +pci:v000010DEd00000266sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (Presario V6133CL) + +pci:v000010DEd00000266sv00001043sd000081BC* + ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (A8N-VM CSM Mainboard) + +pci:v000010DEd00000266sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (K8NGM2 series) + +pci:v000010DEd00000267* + ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller + +pci:v000010DEd00000267sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (Pavilion a1677c) + +pci:v000010DEd00000267sv00001043sd000081BC* + ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (A8N-VM CSM Mainboard) + +pci:v000010DEd00000267sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=MCP51 Serial ATA Controller (K8NGM2 series) + +pci:v000010DEd00000268* + ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller + +pci:v000010DEd00000269* + ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller + +pci:v000010DEd00000269sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller (Pavilion a1677c) + +pci:v000010DEd00000269sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller (Presario V6133CL) + +pci:v000010DEd00000269sv00001043sd00008141* + ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller (A8N-VM CSM Mainboard) + +pci:v000010DEd00000269sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=MCP51 Ethernet Controller (K8NGM2 series) + +pci:v000010DEd0000026A* + ID_MODEL_FROM_DATABASE=MCP51 MCI + +pci:v000010DEd0000026B* + ID_MODEL_FROM_DATABASE=MCP51 AC97 Audio Controller + +pci:v000010DEd0000026Bsv0000105Bsd00000CAD* + ID_MODEL_FROM_DATABASE=MCP51 AC97 Audio Controller (Winfast 6100K8MB) + +pci:v000010DEd0000026C* + ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio + +pci:v000010DEd0000026Csv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio (Pavilion a1677c) + +pci:v000010DEd0000026Csv0000103Csd000030B5* + ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio (Presario V3242AU) + +pci:v000010DEd0000026Csv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio (Presario V6133CL) + +pci:v000010DEd0000026Csv000010DEsd0000CB84* + ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio (ASUSTeK Computer Inc. A8N-VM CSM Mainboard) + +pci:v000010DEd0000026Csv00001462sd00007207* + ID_MODEL_FROM_DATABASE=MCP51 High Definition Audio (K8NGM2 series) + +pci:v000010DEd0000026D* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller + +pci:v000010DEd0000026Dsv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Pavilion a1677c) + +pci:v000010DEd0000026Dsv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Presario V6133CL) + +pci:v000010DEd0000026Dsv00001043sd000081BC* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller (A8N-VM CSM Mainboard) + +pci:v000010DEd0000026Dsv0000105Bsd00000CAD* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Winfast 6100K8MB) + +pci:v000010DEd0000026Dsv00001462sd00007207* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller (K8NGM2 series) + +pci:v000010DEd0000026E* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller + +pci:v000010DEd0000026Esv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Pavilion a1677c) + +pci:v000010DEd0000026Esv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Presario V6133CL) + +pci:v000010DEd0000026Esv00001043sd000081BC* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller (A8N-VM CSM Mainboard) + +pci:v000010DEd0000026Esv0000105Bsd00000CAD* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller (Winfast 6100K8MB) + +pci:v000010DEd0000026Esv00001462sd00007207* + ID_MODEL_FROM_DATABASE=MCP51 USB Controller (K8NGM2 series) + +pci:v000010DEd0000026F* + ID_MODEL_FROM_DATABASE=MCP51 PCI Bridge + +pci:v000010DEd0000026Fsv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 PCI Bridge (Presario V6133CL) + +pci:v000010DEd00000270* + ID_MODEL_FROM_DATABASE=MCP51 Host Bridge + +pci:v000010DEd00000270sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (Pavilion a1677c) + +pci:v000010DEd00000270sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (Presario V6133CL) + +pci:v000010DEd00000270sv00001043sd000081BC* + ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (A8N-VM CSM Mainboard) + +pci:v000010DEd00000270sv0000105Bsd00000CAD* + ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (Winfast 6100K8MB) + +pci:v000010DEd00000270sv00001458sd00005001* + ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (GA-M55plus-S3G) + +pci:v000010DEd00000270sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=MCP51 Host Bridge (K8NGM2 series) + +pci:v000010DEd00000271* + ID_MODEL_FROM_DATABASE=MCP51 PMU + +pci:v000010DEd00000271sv0000103Csd000030B5* + ID_MODEL_FROM_DATABASE=MCP51 PMU (Presario V3242AU) + +pci:v000010DEd00000271sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=MCP51 PMU (Presario V6133CL) + +pci:v000010DEd00000272* + ID_MODEL_FROM_DATABASE=MCP51 Memory Controller 0 + +pci:v000010DEd00000272sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=MCP51 Memory Controller 0 (Pavilion a1677c) + +pci:v000010DEd00000272sv0000105Bsd00000CAD* + ID_MODEL_FROM_DATABASE=MCP51 Memory Controller 0 (Winfast 6100K8MB) + +pci:v000010DEd0000027E* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 + +pci:v000010DEd0000027Esv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 (Pavilion a1677c) + +pci:v000010DEd0000027Esv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 (Presario V6133CL) + +pci:v000010DEd0000027Esv00001043sd000081CD* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 (A8N-VM CSM Mainboard) + +pci:v000010DEd0000027Esv00001458sd00005000* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 (GA-M55plus-S3G) + +pci:v000010DEd0000027Esv00001462sd00007207* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 2 (K8NGM2 series) + +pci:v000010DEd0000027F* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 + +pci:v000010DEd0000027Fsv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 (Pavilion a1677c) + +pci:v000010DEd0000027Fsv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 (Presario V6133CL) + +pci:v000010DEd0000027Fsv00001043sd000081CD* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 (A8N-VM CSM Mainboard) + +pci:v000010DEd0000027Fsv00001458sd00005000* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 (GA-M55plus-S3G) + +pci:v000010DEd0000027Fsv00001462sd00007207* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 3 (K8NGM2 series) + +pci:v000010DEd00000280* + ID_MODEL_FROM_DATABASE=NV28 [GeForce4 Ti 4800] + +pci:v000010DEd00000281* + ID_MODEL_FROM_DATABASE=NV28 [GeForce4 Ti 4200 AGP 8x] + +pci:v000010DEd00000282* + ID_MODEL_FROM_DATABASE=NV28 [GeForce4 Ti 4800 SE] + +pci:v000010DEd00000286* + ID_MODEL_FROM_DATABASE=NV28M [GeForce4 Ti 4200 Go AGP 8x] + +pci:v000010DEd00000288* + ID_MODEL_FROM_DATABASE=NV28GL [Quadro4 980 XGL] + +pci:v000010DEd00000289* + ID_MODEL_FROM_DATABASE=NV28GL [Quadro4 780 XGL] + +pci:v000010DEd0000028C* + ID_MODEL_FROM_DATABASE=NV28GLM [Quadro4 Go700] + +pci:v000010DEd00000290* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GTX] + +pci:v000010DEd00000291* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GT/GTO] + +pci:v000010DEd00000291sv000010DEsd0000042B* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GT/GTO] (NX7900GTO-T2D512E [7900 GTO]) + +pci:v000010DEd00000292* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GS] + +pci:v000010DEd00000293* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GX2] + +pci:v000010DEd00000294* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GX2] + +pci:v000010DEd00000295* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] + +pci:v000010DEd00000295sv00001043sd00008225* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] (GeForce 7950 GT) + +pci:v000010DEd00000295sv0000107Dsd00002A68* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] (WinFast PX7950GT TDH) + +pci:v000010DEd00000295sv00001462sd00000663* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] (NX7950GT-VT2D512EZ-HD) + +pci:v000010DEd00000297* + ID_MODEL_FROM_DATABASE=G71M [GeForce Go 7950 GTX] + +pci:v000010DEd00000298* + ID_MODEL_FROM_DATABASE=G71M [GeForce Go 7900 GS] + +pci:v000010DEd00000299* + ID_MODEL_FROM_DATABASE=G71M [GeForce Go 7900 GTX] + +pci:v000010DEd0000029A* + ID_MODEL_FROM_DATABASE=G71GLM [Quadro FX 2500M] + +pci:v000010DEd0000029B* + ID_MODEL_FROM_DATABASE=G71GLM [Quadro FX 1500M] + +pci:v000010DEd0000029C* + ID_MODEL_FROM_DATABASE=G71GL [Quadro FX 5500] + +pci:v000010DEd0000029D* + ID_MODEL_FROM_DATABASE=G71GL [Quadro FX 3500] + +pci:v000010DEd0000029Dsv00001028sd0000019B* + ID_MODEL_FROM_DATABASE=G71GL [Quadro FX 3500] (G71GLM [Quadro FX 3500M]) + +pci:v000010DEd0000029E* + ID_MODEL_FROM_DATABASE=G71GL [Quadro FX 1500] + +pci:v000010DEd0000029F* + ID_MODEL_FROM_DATABASE=G71GL [Quadro FX 4500 X2] + +pci:v000010DEd000002A0* + ID_MODEL_FROM_DATABASE=NV2A [XGPU] + +pci:v000010DEd000002A5* + ID_MODEL_FROM_DATABASE=MCPX CPU Bridge + +pci:v000010DEd000002A6* + ID_MODEL_FROM_DATABASE=MCPX Memory Controller + +pci:v000010DEd000002E0* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] + +pci:v000010DEd000002E0sv000002E0sd00002249* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] (GF 7600GT 560M 256MB DDR3 DUAL DVI TV) + +pci:v000010DEd000002E1* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] + +pci:v000010DEd000002E1sv00001682sd0000222B* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] (PV-T73K-UAL3 (256MB)) + +pci:v000010DEd000002E1sv00001682sd00002247* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] (GF 7600GS 512MB DDR2) + +pci:v000010DEd000002E2* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT] + +pci:v000010DEd000002E3* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7900 GS] + +pci:v000010DEd000002E4* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] + +pci:v000010DEd000002E4sv00001682sd00002271* + ID_MODEL_FROM_DATABASE=G71 [GeForce 7950 GT] (PV-T71A-YDF7 (512MB)) + +pci:v000010DEd000002F0* + ID_MODEL_FROM_DATABASE=C51 Host Bridge + +pci:v000010DEd000002F0sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=C51 Host Bridge (Pavilion a1677c) + +pci:v000010DEd000002F0sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 Host Bridge (Presario V6133CL) + +pci:v000010DEd000002F0sv00001043sd000081CD* + ID_MODEL_FROM_DATABASE=C51 Host Bridge (A8N-VM CSM Mainboard) + +pci:v000010DEd000002F0sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=C51 Host Bridge (K8NGM2 series) + +pci:v000010DEd000002F1* + ID_MODEL_FROM_DATABASE=C51 Host Bridge + +pci:v000010DEd000002F1sv00001458sd00005000* + ID_MODEL_FROM_DATABASE=C51 Host Bridge (GA-M55plus-S3G) + +pci:v000010DEd000002F2* + ID_MODEL_FROM_DATABASE=C51 Host Bridge + +pci:v000010DEd000002F3* + ID_MODEL_FROM_DATABASE=C51 Host Bridge + +pci:v000010DEd000002F4* + ID_MODEL_FROM_DATABASE=C51 Host Bridge + +pci:v000010DEd000002F5* + ID_MODEL_FROM_DATABASE=C51 Host Bridge + +pci:v000010DEd000002F6* + ID_MODEL_FROM_DATABASE=C51 Host Bridge + +pci:v000010DEd000002F7* + ID_MODEL_FROM_DATABASE=C51 Host Bridge + +pci:v000010DEd000002F8* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 + +pci:v000010DEd000002F8sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 (Pavilion a1677c) + +pci:v000010DEd000002F8sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 (Presario V6133CL) + +pci:v000010DEd000002F8sv00001043sd000081CD* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 (A8N-VM CSM Mainboard) + +pci:v000010DEd000002F8sv00001458sd00005000* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 (GA-M55plus-S3G) + +pci:v000010DEd000002F8sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 5 (K8NGM2 series) + +pci:v000010DEd000002F9* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 + +pci:v000010DEd000002F9sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 (Pavilion a1677c) + +pci:v000010DEd000002F9sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 (Presario V6133CL) + +pci:v000010DEd000002F9sv00001043sd000081CD* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 (A8N-VM CSM Mainboard) + +pci:v000010DEd000002F9sv00001458sd00005000* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 (GA-M55plus-S3G) + +pci:v000010DEd000002F9sv00001462sd00007207* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 4 (K8NGM2 series) + +pci:v000010DEd000002FA* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 + +pci:v000010DEd000002FAsv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 (Pavilion a1677c) + +pci:v000010DEd000002FAsv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 (Presario V6133CL) + +pci:v000010DEd000002FAsv00001043sd000081CD* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 (A8N-VM CSM Mainboard) + +pci:v000010DEd000002FAsv00001458sd00005000* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 (GA-M55plus-S3G) + +pci:v000010DEd000002FAsv00001462sd00007207* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 0 (K8NGM2 series) + +pci:v000010DEd000002FB* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd000002FC* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd000002FCsv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge (Presario V6133CL) + +pci:v000010DEd000002FD* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge + +pci:v000010DEd000002FDsv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 PCI Express Bridge (Presario V6133CL) + +pci:v000010DEd000002FE* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 + +pci:v000010DEd000002FEsv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 (Pavilion a1677c) + +pci:v000010DEd000002FEsv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 (Presario V6133CL) + +pci:v000010DEd000002FEsv00001043sd000081CD* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 (A8N-VM CSM Mainboard) + +pci:v000010DEd000002FEsv00001458sd00005000* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 (GA-M55plus-S3G) + +pci:v000010DEd000002FEsv00001462sd00007207* + ID_MODEL_FROM_DATABASE=C51 Memory Controller 1 (K8NGM2 series) + +pci:v000010DEd000002FF* + ID_MODEL_FROM_DATABASE=C51 Host Bridge + +pci:v000010DEd000002FFsv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=C51 Host Bridge (Pavilion a1677c) + +pci:v000010DEd000002FFsv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=C51 Host Bridge (Presario V6133CL) + +pci:v000010DEd000002FFsv00001043sd000081CD* + ID_MODEL_FROM_DATABASE=C51 Host Bridge (A8N-VM CSM Mainboard) + +pci:v000010DEd000002FFsv00001458sd00005000* + ID_MODEL_FROM_DATABASE=C51 Host Bridge (GA-M55plus-S3G) + +pci:v000010DEd000002FFsv00001462sd00007207* + ID_MODEL_FROM_DATABASE=C51 Host Bridge (K8NGM2 series) + +pci:v000010DEd00000300* + ID_MODEL_FROM_DATABASE=NV30 [GeForce FX] + +pci:v000010DEd00000301* + ID_MODEL_FROM_DATABASE=NV30 [GeForce FX 5800 Ultra] + +pci:v000010DEd00000302* + ID_MODEL_FROM_DATABASE=NV30 [GeForce FX 5800] + +pci:v000010DEd00000308* + ID_MODEL_FROM_DATABASE=NV30GL [Quadro FX 2000] + +pci:v000010DEd00000309* + ID_MODEL_FROM_DATABASE=NV30GL [Quadro FX 1000] + +pci:v000010DEd00000311* + ID_MODEL_FROM_DATABASE=NV31 [GeForce FX 5600 Ultra] + +pci:v000010DEd00000312* + ID_MODEL_FROM_DATABASE=NV31 [GeForce FX 5600] + +pci:v000010DEd00000314* + ID_MODEL_FROM_DATABASE=NV31 [GeForce FX 5600XT] + +pci:v000010DEd00000314sv00001043sd0000814A* + ID_MODEL_FROM_DATABASE=NV31 [GeForce FX 5600XT] (V9560XT/TD) + +pci:v000010DEd00000316* + ID_MODEL_FROM_DATABASE=NV31M + +pci:v000010DEd00000318* + ID_MODEL_FROM_DATABASE=NV31GL + +pci:v000010DEd0000031A* + ID_MODEL_FROM_DATABASE=NV31M [GeForce FX Go5600] + +pci:v000010DEd0000031B* + ID_MODEL_FROM_DATABASE=NV31M [GeForce FX Go5650] + +pci:v000010DEd0000031C* + ID_MODEL_FROM_DATABASE=NV31GLM [Quadro FX Go700] + +pci:v000010DEd00000320* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] + +pci:v000010DEd00000321* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200 Ultra] + +pci:v000010DEd00000322* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] + +pci:v000010DEd00000322sv00001043sd000002FB* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (V9250 Magic) + +pci:v000010DEd00000322sv00001043sd00008180* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (V9520-X/TD/128M) + +pci:v000010DEd00000322sv0000107Dsd00002967* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (WinFast A340T 128MB) + +pci:v000010DEd00000322sv00001462sd00009110* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (MS-8911 (FX5200-TD128)) + +pci:v000010DEd00000322sv00001462sd00009171* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (MS-8917 (FX5200-T128)) + +pci:v000010DEd00000322sv00001462sd00009360* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (MS-8936 (FX5200-T128)) + +pci:v000010DEd00000322sv00001682sd00001351* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] (GeForce FX 5200) + +pci:v000010DEd00000323* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200LE] + +pci:v000010DEd00000324* + ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200 64M] + +pci:v000010DEd00000324sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200 64M] (Inspiron 5160) + +pci:v000010DEd00000324sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200 64M] (Pavilion ZD7000 laptop) + +pci:v000010DEd00000324sv00001071sd00008160* + ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200 64M] (MIM2000) + +pci:v000010DEd00000325* + ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5250] + +pci:v000010DEd00000326* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5500] + +pci:v000010DEd00000326sv00001458sd0000310D* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5500] (GeForce FX 5500 128 MB) + +pci:v000010DEd00000326sv00001682sd00002034* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5500] (GeForce 5500 256 MB) + +pci:v000010DEd00000327* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5100] + +pci:v000010DEd00000328* + ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200 32M/64M] + +pci:v000010DEd00000329* + ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200] + +pci:v000010DEd00000329sv000010DEsd00000010* + ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5200] (Powerbook G4) + +pci:v000010DEd0000032A* + ID_MODEL_FROM_DATABASE=NV34GL [Quadro NVS 280 PCI] + +pci:v000010DEd0000032B* + ID_MODEL_FROM_DATABASE=NV34GL [Quadro FX 500/600 PCI] + +pci:v000010DEd0000032C* + ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5300 / Go5350] + +pci:v000010DEd0000032D* + ID_MODEL_FROM_DATABASE=NV34M [GeForce FX Go5100] + +pci:v000010DEd0000032E* + ID_MODEL_FROM_DATABASE=NV34 + +pci:v000010DEd0000032F* + ID_MODEL_FROM_DATABASE=NV34 [GeForce FX 5200] + +pci:v000010DEd00000330* + ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900 Ultra] + +pci:v000010DEd00000330sv00001043sd00008137* + ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900 Ultra] (V9950 Ultra / 256 MB) + +pci:v000010DEd00000331* + ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900] + +pci:v000010DEd00000331sv00001043sd00008145* + ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900] (V9950GE) + +pci:v000010DEd00000332* + ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900XT] + +pci:v000010DEd00000333* + ID_MODEL_FROM_DATABASE=NV38 [GeForce FX 5950 Ultra] + +pci:v000010DEd00000334* + ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900ZT] + +pci:v000010DEd00000334sv00001462sd00009373* + ID_MODEL_FROM_DATABASE=NV35 [GeForce FX 5900ZT] (FX5900ZT-VTD128 (MS-8937)) + +pci:v000010DEd00000338* + ID_MODEL_FROM_DATABASE=NV35GL [Quadro FX 3000] + +pci:v000010DEd0000033F* + ID_MODEL_FROM_DATABASE=NV35GL [Quadro FX 700] + +pci:v000010DEd00000341* + ID_MODEL_FROM_DATABASE=NV36 [GeForce FX 5700 Ultra] + +pci:v000010DEd00000341sv00001462sd00009380* + ID_MODEL_FROM_DATABASE=NV36 [GeForce FX 5700 Ultra] (MS-8938 (FX5700U-TD128)) + +pci:v000010DEd00000342* + ID_MODEL_FROM_DATABASE=NV36 [GeForce FX 5700] + +pci:v000010DEd00000343* + ID_MODEL_FROM_DATABASE=NV36 [GeForce FX 5700LE] + +pci:v000010DEd00000344* + ID_MODEL_FROM_DATABASE=NV36 [GeForce FX 5700VE] + +pci:v000010DEd00000347* + ID_MODEL_FROM_DATABASE=NV36M [GeForce FX Go5700] + +pci:v000010DEd00000347sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=NV36M [GeForce FX Go5700] (NX9500) + +pci:v000010DEd00000348* + ID_MODEL_FROM_DATABASE=NV36M [GeForce FX Go5700] + +pci:v000010DEd0000034C* + ID_MODEL_FROM_DATABASE=NV36 [Quadro FX Go1000] + +pci:v000010DEd0000034D* + ID_MODEL_FROM_DATABASE=NV36 + +pci:v000010DEd0000034E* + ID_MODEL_FROM_DATABASE=NV36GL [Quadro FX 1100] + +pci:v000010DEd00000360* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge + +pci:v000010DEd00000361* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge + +pci:v000010DEd00000361sv00001028sd00000221* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge (PowerEdge R805 MCP55 LPC Bridge) + +pci:v000010DEd00000362* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge + +pci:v000010DEd00000362sv0000147Bsd00001C24* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge (KN9 series mainboard) + +pci:v000010DEd00000363* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge + +pci:v000010DEd00000364* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge + +pci:v000010DEd00000364sv00001028sd00000221* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge (PowerEdge R805 MCP55 LPC Bridge) + +pci:v000010DEd00000365* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge + +pci:v000010DEd00000366* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge + +pci:v000010DEd00000367* + ID_MODEL_FROM_DATABASE=MCP55 LPC Bridge + +pci:v000010DEd00000368* + ID_MODEL_FROM_DATABASE=MCP55 SMBus Controller + +pci:v000010DEd00000368sv00001028sd0000020C* + ID_MODEL_FROM_DATABASE=MCP55 SMBus Controller (PowerEdge M605 MCP55 SMBus) + +pci:v000010DEd00000368sv00001028sd00000221* + ID_MODEL_FROM_DATABASE=MCP55 SMBus Controller (PowerEdge R805 MCP55 SMBus) + +pci:v000010DEd00000368sv0000147Bsd00001C24* + ID_MODEL_FROM_DATABASE=MCP55 SMBus Controller (KN9 series mainboard) + +pci:v000010DEd00000369* + ID_MODEL_FROM_DATABASE=MCP55 Memory Controller + +pci:v000010DEd00000369sv0000147Bsd00001C24* + ID_MODEL_FROM_DATABASE=MCP55 Memory Controller (KN9 series mainboard) + +pci:v000010DEd0000036A* + ID_MODEL_FROM_DATABASE=MCP55 Memory Controller + +pci:v000010DEd0000036B* + ID_MODEL_FROM_DATABASE=MCP55 SMU + +pci:v000010DEd0000036C* + ID_MODEL_FROM_DATABASE=MCP55 USB Controller + +pci:v000010DEd0000036Csv00001028sd0000020C* + ID_MODEL_FROM_DATABASE=MCP55 USB Controller (PowerEdge M605 MCP55 USB Controller) + +pci:v000010DEd0000036Csv00001028sd00000221* + ID_MODEL_FROM_DATABASE=MCP55 USB Controller (PowerEdge R805 MCP55 USB Controller) + +pci:v000010DEd0000036Csv0000147Bsd00001C24* + ID_MODEL_FROM_DATABASE=MCP55 USB Controller (KN9 series mainboard) + +pci:v000010DEd0000036D* + ID_MODEL_FROM_DATABASE=MCP55 USB Controller + +pci:v000010DEd0000036Dsv00001028sd0000020C* + ID_MODEL_FROM_DATABASE=MCP55 USB Controller (PowerEdge M605 MCP55 USB Controller) + +pci:v000010DEd0000036Dsv00001028sd00000221* + ID_MODEL_FROM_DATABASE=MCP55 USB Controller (PowerEdge R805 MCP55 USB Controller) + +pci:v000010DEd0000036Dsv0000147Bsd00001C24* + ID_MODEL_FROM_DATABASE=MCP55 USB Controller (KN9 series mainboard) + +pci:v000010DEd0000036E* + ID_MODEL_FROM_DATABASE=MCP55 IDE + +pci:v000010DEd0000036Esv0000147Bsd00001C24* + ID_MODEL_FROM_DATABASE=MCP55 IDE (KN9 series mainboard) + +pci:v000010DEd00000370* + ID_MODEL_FROM_DATABASE=MCP55 PCI bridge + +pci:v000010DEd00000371* + ID_MODEL_FROM_DATABASE=MCP55 High Definition Audio + +pci:v000010DEd00000371sv0000147Bsd00001C24* + ID_MODEL_FROM_DATABASE=MCP55 High Definition Audio (KN9 series mainboard) + +pci:v000010DEd00000372* + ID_MODEL_FROM_DATABASE=MCP55 Ethernet + +pci:v000010DEd00000373* + ID_MODEL_FROM_DATABASE=MCP55 Ethernet + +pci:v000010DEd00000373sv0000147Bsd00001C24* + ID_MODEL_FROM_DATABASE=MCP55 Ethernet (KN9 series mainboard) + +pci:v000010DEd00000374* + ID_MODEL_FROM_DATABASE=MCP55 PCI Express bridge + +pci:v000010DEd00000375* + ID_MODEL_FROM_DATABASE=MCP55 PCI Express bridge + +pci:v000010DEd00000376* + ID_MODEL_FROM_DATABASE=MCP55 PCI Express bridge + +pci:v000010DEd00000377* + ID_MODEL_FROM_DATABASE=MCP55 PCI Express bridge + +pci:v000010DEd00000378* + ID_MODEL_FROM_DATABASE=MCP55 PCI Express bridge + +pci:v000010DEd0000037A* + ID_MODEL_FROM_DATABASE=MCP55 Memory Controller + +pci:v000010DEd0000037E* + ID_MODEL_FROM_DATABASE=MCP55 SATA Controller + +pci:v000010DEd0000037F* + ID_MODEL_FROM_DATABASE=MCP55 SATA Controller + +pci:v000010DEd0000037Fsv00001028sd00000221* + ID_MODEL_FROM_DATABASE=MCP55 SATA Controller (PowerEdge R805 MCP55 SATA Controller) + +pci:v000010DEd0000037Fsv0000147Bsd00001C24* + ID_MODEL_FROM_DATABASE=MCP55 SATA Controller (KN9 series mainboard) + +pci:v000010DEd0000038B* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7650 GS] + +pci:v000010DEd00000390* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7650 GS] + +pci:v000010DEd00000391* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] + +pci:v000010DEd00000391sv00001458sd00003427* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] (GV-NX76T128D-RH) + +pci:v000010DEd00000391sv00001462sd00000452* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GT] (NX7600GT-VT2D256E) + +pci:v000010DEd00000392* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] + +pci:v000010DEd00000392sv00001462sd00000622* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 GS] (NX7600GS-T2D256EH) + +pci:v000010DEd00000393* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT] + +pci:v000010DEd00000393sv000010DEsd00000412* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT] (NX7300GT-TD256EH) + +pci:v000010DEd00000393sv00001462sd00000412* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT] (NX7300GT-TD256EH) + +pci:v000010DEd00000394* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7600 LE] + +pci:v000010DEd00000395* + ID_MODEL_FROM_DATABASE=G73 [GeForce 7300 GT] + +pci:v000010DEd00000396* + ID_MODEL_FROM_DATABASE=G73 + +pci:v000010DEd00000397* + ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7700] + +pci:v000010DEd00000398* + ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7600] + +pci:v000010DEd00000398sv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7600] (Aspire 9814WKMi) + +pci:v000010DEd00000399* + ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7600 GT] + +pci:v000010DEd0000039A* + ID_MODEL_FROM_DATABASE=G73M [Quadro NVS 300M] + +pci:v000010DEd0000039B* + ID_MODEL_FROM_DATABASE=G73M [GeForce Go 7900 SE] + +pci:v000010DEd0000039C* + ID_MODEL_FROM_DATABASE=G73GLM [Quadro FX 550M] + +pci:v000010DEd0000039Csv000010DEsd0000039C* + ID_MODEL_FROM_DATABASE=G73GLM [Quadro FX 550M] (Quadro FX 560M) + +pci:v000010DEd0000039D* + ID_MODEL_FROM_DATABASE=G73 + +pci:v000010DEd0000039E* + ID_MODEL_FROM_DATABASE=G73GL [Quadro FX 560] + +pci:v000010DEd0000039F* + ID_MODEL_FROM_DATABASE=G73 + +pci:v000010DEd000003A0* + ID_MODEL_FROM_DATABASE=C55 Host Bridge + +pci:v000010DEd000003A1* + ID_MODEL_FROM_DATABASE=C55 Host Bridge + +pci:v000010DEd000003A2* + ID_MODEL_FROM_DATABASE=C55 Host Bridge + +pci:v000010DEd000003A3* + ID_MODEL_FROM_DATABASE=C55 Host Bridge + +pci:v000010DEd000003A4* + ID_MODEL_FROM_DATABASE=C55 Host Bridge + +pci:v000010DEd000003A5* + ID_MODEL_FROM_DATABASE=C55 Host Bridge + +pci:v000010DEd000003A6* + ID_MODEL_FROM_DATABASE=C55 Host Bridge + +pci:v000010DEd000003A7* + ID_MODEL_FROM_DATABASE=C55 Host Bridge + +pci:v000010DEd000003A8* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003A9* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003AA* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003AB* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003AC* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003AD* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003AE* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003AF* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003B0* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003B1* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003B2* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003B3* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003B4* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003B5* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003B6* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003B7* + ID_MODEL_FROM_DATABASE=C55 PCI Express bridge + +pci:v000010DEd000003B8* + ID_MODEL_FROM_DATABASE=C55 PCI Express bridge + +pci:v000010DEd000003B9* + ID_MODEL_FROM_DATABASE=C55 PCI Express bridge + +pci:v000010DEd000003BA* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003BB* + ID_MODEL_FROM_DATABASE=C55 PCI Express bridge + +pci:v000010DEd000003BC* + ID_MODEL_FROM_DATABASE=C55 Memory Controller + +pci:v000010DEd000003D0* + ID_MODEL_FROM_DATABASE=C61 [GeForce 6150SE nForce 430] + +pci:v000010DEd000003D0sv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=C61 [GeForce 6150SE nForce 430] (Inspiron 531) + +pci:v000010DEd000003D1* + ID_MODEL_FROM_DATABASE=C61 [GeForce 6100 nForce 405] + +pci:v000010DEd000003D2* + ID_MODEL_FROM_DATABASE=C61 [GeForce 6100 nForce 400] + +pci:v000010DEd000003D5* + ID_MODEL_FROM_DATABASE=C61 [GeForce 6100 nForce 420] + +pci:v000010DEd000003D6* + ID_MODEL_FROM_DATABASE=C61 [GeForce 7025 / nForce 630a] + +pci:v000010DEd000003E0* + ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge + +pci:v000010DEd000003E0sv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge (Inspiron 531) + +pci:v000010DEd000003E0sv00001849sd000003E0* + ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge (939NF6G-VSTA Board) + +pci:v000010DEd000003E1* + ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge + +pci:v000010DEd000003E1sv00001043sd000083A4* + ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge (M4N68T series motherboard) + +pci:v000010DEd000003E2* + ID_MODEL_FROM_DATABASE=MCP61 Host Bridge + +pci:v000010DEd000003E2sv00001043sd000083A4* + ID_MODEL_FROM_DATABASE=MCP61 Host Bridge (M4N68T series motherboard) + +pci:v000010DEd000003E3* + ID_MODEL_FROM_DATABASE=MCP61 LPC Bridge + +pci:v000010DEd000003E4* + ID_MODEL_FROM_DATABASE=MCP61 High Definition Audio + +pci:v000010DEd000003E5* + ID_MODEL_FROM_DATABASE=MCP61 Ethernet + +pci:v000010DEd000003E6* + ID_MODEL_FROM_DATABASE=MCP61 Ethernet + +pci:v000010DEd000003E7* + ID_MODEL_FROM_DATABASE=MCP61 SATA Controller + +pci:v000010DEd000003E8* + ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge + +pci:v000010DEd000003E8sv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge (Inspiron 531) + +pci:v000010DEd000003E8sv00001849sd000003E8* + ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge (939NF6G-VSTA Board) + +pci:v000010DEd000003E9* + ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge + +pci:v000010DEd000003E9sv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge (Inspiron 531) + +pci:v000010DEd000003E9sv00001849sd000003E9* + ID_MODEL_FROM_DATABASE=MCP61 PCI Express bridge (939NF6G-VSTA Board) + +pci:v000010DEd000003EA* + ID_MODEL_FROM_DATABASE=MCP61 Memory Controller + +pci:v000010DEd000003EAsv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 Memory Controller (Inspiron 531) + +pci:v000010DEd000003EAsv00001849sd000003EA* + ID_MODEL_FROM_DATABASE=MCP61 Memory Controller (939NF6G-VSTA Board) + +pci:v000010DEd000003EB* + ID_MODEL_FROM_DATABASE=MCP61 SMBus + +pci:v000010DEd000003EBsv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 SMBus (Inspiron 531) + +pci:v000010DEd000003EBsv00001043sd000083A4* + ID_MODEL_FROM_DATABASE=MCP61 SMBus (M4N68T series motherboard) + +pci:v000010DEd000003EBsv00001849sd000003EB* + ID_MODEL_FROM_DATABASE=MCP61 SMBus (939NF6G-VSTA Board) + +pci:v000010DEd000003EC* + ID_MODEL_FROM_DATABASE=MCP61 IDE + +pci:v000010DEd000003ECsv00001025sd00000392* + ID_MODEL_FROM_DATABASE=MCP61 IDE (ET1350) + +pci:v000010DEd000003ECsv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 IDE (Inspiron 531) + +pci:v000010DEd000003ECsv00001043sd000083A4* + ID_MODEL_FROM_DATABASE=MCP61 IDE (M4N68T series motherboard) + +pci:v000010DEd000003ECsv00001849sd000003EC* + ID_MODEL_FROM_DATABASE=MCP61 IDE (939NF6G-VSTA Board) + +pci:v000010DEd000003EE* + ID_MODEL_FROM_DATABASE=MCP61 Ethernet + +pci:v000010DEd000003EF* + ID_MODEL_FROM_DATABASE=MCP61 Ethernet + +pci:v000010DEd000003EFsv00001025sd00008000* + ID_MODEL_FROM_DATABASE=MCP61 Ethernet (ET1350) + +pci:v000010DEd000003EFsv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 Ethernet (Inspiron 531) + +pci:v000010DEd000003EFsv00001043sd000083A4* + ID_MODEL_FROM_DATABASE=MCP61 Ethernet (M4N68T series motherboard) + +pci:v000010DEd000003EFsv00001849sd000003EF* + ID_MODEL_FROM_DATABASE=MCP61 Ethernet (939NF6G-VSTA Board) + +pci:v000010DEd000003F0* + ID_MODEL_FROM_DATABASE=MCP61 High Definition Audio + +pci:v000010DEd000003F0sv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 High Definition Audio (Inspiron 531) + +pci:v000010DEd000003F0sv00001043sd00008415* + ID_MODEL_FROM_DATABASE=MCP61 High Definition Audio (M4N68T series motherboard) + +pci:v000010DEd000003F0sv00001849sd00000888* + ID_MODEL_FROM_DATABASE=MCP61 High Definition Audio (939NF6G-VSTA Board) + +pci:v000010DEd000003F1* + ID_MODEL_FROM_DATABASE=MCP61 USB 1.1 Controller + +pci:v000010DEd000003F1sv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 USB 1.1 Controller (Inspiron 531) + +pci:v000010DEd000003F1sv00001043sd000083A4* + ID_MODEL_FROM_DATABASE=MCP61 USB 1.1 Controller (M4N68T series motherboard) + +pci:v000010DEd000003F1sv00001849sd000003F1* + ID_MODEL_FROM_DATABASE=MCP61 USB 1.1 Controller (939NF6G-VSTA Board) + +pci:v000010DEd000003F2* + ID_MODEL_FROM_DATABASE=MCP61 USB 2.0 Controller + +pci:v000010DEd000003F2sv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 USB 2.0 Controller (Inspiron 531) + +pci:v000010DEd000003F2sv00001043sd000083A4* + ID_MODEL_FROM_DATABASE=MCP61 USB 2.0 Controller (M4N68T series motherboard) + +pci:v000010DEd000003F2sv00001849sd000003F2* + ID_MODEL_FROM_DATABASE=MCP61 USB 2.0 Controller (939NF6G-VSTA Board) + +pci:v000010DEd000003F3* + ID_MODEL_FROM_DATABASE=MCP61 PCI bridge + +pci:v000010DEd000003F3sv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 PCI bridge (Inspiron 531) + +pci:v000010DEd000003F3sv00001849sd000003F3* + ID_MODEL_FROM_DATABASE=MCP61 PCI bridge (939NF6G-VSTA Board) + +pci:v000010DEd000003F4* + ID_MODEL_FROM_DATABASE=MCP61 SMU + +pci:v000010DEd000003F5* + ID_MODEL_FROM_DATABASE=MCP61 Memory Controller + +pci:v000010DEd000003F5sv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 Memory Controller (Inspiron 531) + +pci:v000010DEd000003F5sv00001043sd000083A4* + ID_MODEL_FROM_DATABASE=MCP61 Memory Controller (M4N68T series motherboard) + +pci:v000010DEd000003F5sv00001849sd000003EB* + ID_MODEL_FROM_DATABASE=MCP61 Memory Controller (939NF6G-VSTA Board) + +pci:v000010DEd000003F6* + ID_MODEL_FROM_DATABASE=MCP61 SATA Controller + +pci:v000010DEd000003F6sv00001028sd0000020E* + ID_MODEL_FROM_DATABASE=MCP61 SATA Controller (Inspiron 531) + +pci:v000010DEd000003F6sv00001043sd000083A4* + ID_MODEL_FROM_DATABASE=MCP61 SATA Controller (M4N68T series motherboard) + +pci:v000010DEd000003F6sv00001849sd000003F6* + ID_MODEL_FROM_DATABASE=MCP61 SATA Controller (939NF6G-VSTA Board) + +pci:v000010DEd000003F7* + ID_MODEL_FROM_DATABASE=MCP61 SATA Controller + +pci:v000010DEd00000400* + ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GTS] + +pci:v000010DEd00000400sv00001043sd00008241* + ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GTS] (EN8600GTS) + +pci:v000010DEd00000401* + ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GT] + +pci:v000010DEd00000402* + ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GT] + +pci:v000010DEd00000402sv00001458sd00003455* + ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GT] (GV-NX86T512H) + +pci:v000010DEd00000402sv00001462sd00000910* + ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GT] (NX8600GT-T2D256EZ) + +pci:v000010DEd00000403* + ID_MODEL_FROM_DATABASE=G84 [GeForce 8600 GS] + +pci:v000010DEd00000404* + ID_MODEL_FROM_DATABASE=G84 [GeForce 8400 GS] + +pci:v000010DEd00000404sv00001462sd00001230* + ID_MODEL_FROM_DATABASE=G84 [GeForce 8400 GS] (NX8400GS-TD256E) + +pci:v000010DEd00000405* + ID_MODEL_FROM_DATABASE=G84M [GeForce 9500M GS] + +pci:v000010DEd00000406* + ID_MODEL_FROM_DATABASE=G84 [GeForce 8300 GS] + +pci:v000010DEd00000407* + ID_MODEL_FROM_DATABASE=G84M [GeForce 8600M GT] + +pci:v000010DEd00000408* + ID_MODEL_FROM_DATABASE=G84M [GeForce 9650M GS] + +pci:v000010DEd00000409* + ID_MODEL_FROM_DATABASE=G84M [GeForce 8700M GT] + +pci:v000010DEd0000040A* + ID_MODEL_FROM_DATABASE=G84GL [Quadro FX 370] + +pci:v000010DEd0000040B* + ID_MODEL_FROM_DATABASE=G84GLM [Quadro NVS 320M] + +pci:v000010DEd0000040C* + ID_MODEL_FROM_DATABASE=G84GLM [Quadro FX 570M] + +pci:v000010DEd0000040Csv000017AAsd000020D9* + ID_MODEL_FROM_DATABASE=G84GLM [Quadro FX 570M] (ThinkPad T61p) + +pci:v000010DEd0000040D* + ID_MODEL_FROM_DATABASE=G84GLM [Quadro FX 1600M] + +pci:v000010DEd0000040E* + ID_MODEL_FROM_DATABASE=G84GL [Quadro FX 570] + +pci:v000010DEd0000040F* + ID_MODEL_FROM_DATABASE=G84GL [Quadro FX 1700] + +pci:v000010DEd00000410* + ID_MODEL_FROM_DATABASE=G92 [GeForce GT 330] + +pci:v000010DEd00000414* + ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GT] + +pci:v000010DEd00000418* + ID_MODEL_FROM_DATABASE=G92 [GeForce GT 330 OEM] + +pci:v000010DEd00000420* + ID_MODEL_FROM_DATABASE=G86 [GeForce 8400 SE] + +pci:v000010DEd00000421* + ID_MODEL_FROM_DATABASE=G86 [GeForce 8500 GT] + +pci:v000010DEd00000421sv00001462sd00000960* + ID_MODEL_FROM_DATABASE=G86 [GeForce 8500 GT] (NX8500GT-TD512EH/M2) + +pci:v000010DEd00000422* + ID_MODEL_FROM_DATABASE=G86 [GeForce 8400 GS] + +pci:v000010DEd00000423* + ID_MODEL_FROM_DATABASE=G86 [GeForce 8300 GS] + +pci:v000010DEd00000424* + ID_MODEL_FROM_DATABASE=G86 [GeForce 8400 GS] + +pci:v000010DEd00000425* + ID_MODEL_FROM_DATABASE=G86M [GeForce 8600M GS] + +pci:v000010DEd00000425sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=G86M [GeForce 8600M GS] (Aspire 5920G) + +pci:v000010DEd00000425sv00001043sd00001514* + ID_MODEL_FROM_DATABASE=G86M [GeForce 8600M GS] (F3SV) + +pci:v000010DEd00000426* + ID_MODEL_FROM_DATABASE=G86M [GeForce 8400M GT] + +pci:v000010DEd00000427* + ID_MODEL_FROM_DATABASE=G86M [GeForce 8400M GS] + +pci:v000010DEd00000427sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=G86M [GeForce 8400M GS] (Pavilion dv6700) + +pci:v000010DEd00000427sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=G86M [GeForce 8400M GS] (Pavilion dv9668eg Laptop) + +pci:v000010DEd00000428* + ID_MODEL_FROM_DATABASE=G86M [GeForce 8400M G] + +pci:v000010DEd00000429* + ID_MODEL_FROM_DATABASE=G86M [Quadro NVS 140M] + +pci:v000010DEd00000429sv000017AAsd000020D8* + ID_MODEL_FROM_DATABASE=G86M [Quadro NVS 140M] (ThinkPad T61) + +pci:v000010DEd0000042A* + ID_MODEL_FROM_DATABASE=G86M [Quadro NVS 130M] + +pci:v000010DEd0000042B* + ID_MODEL_FROM_DATABASE=G86M [Quadro NVS 135M] + +pci:v000010DEd0000042C* + ID_MODEL_FROM_DATABASE=G86 [GeForce 9400 GT] + +pci:v000010DEd0000042D* + ID_MODEL_FROM_DATABASE=G86GLM [Quadro FX 360M] + +pci:v000010DEd0000042E* + ID_MODEL_FROM_DATABASE=G86M [GeForce 9300M G] + +pci:v000010DEd0000042F* + ID_MODEL_FROM_DATABASE=G86 [Quadro NVS 290] + +pci:v000010DEd00000440* + ID_MODEL_FROM_DATABASE=MCP65 LPC Bridge + +pci:v000010DEd00000441* + ID_MODEL_FROM_DATABASE=MCP65 LPC Bridge + +pci:v000010DEd00000442* + ID_MODEL_FROM_DATABASE=MCP65 LPC Bridge + +pci:v000010DEd00000442sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=MCP65 LPC Bridge (Pavilion dv9668eg Laptop) + +pci:v000010DEd00000443* + ID_MODEL_FROM_DATABASE=MCP65 LPC Bridge + +pci:v000010DEd00000444* + ID_MODEL_FROM_DATABASE=MCP65 Memory Controller + +pci:v000010DEd00000444sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=MCP65 Memory Controller (Pavilion dv9668eg Laptop) + +pci:v000010DEd00000445* + ID_MODEL_FROM_DATABASE=MCP65 Memory Controller + +pci:v000010DEd00000446* + ID_MODEL_FROM_DATABASE=MCP65 SMBus + +pci:v000010DEd00000446sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=MCP65 SMBus (Pavilion dv9668eg Laptop) + +pci:v000010DEd00000447* + ID_MODEL_FROM_DATABASE=MCP65 SMU + +pci:v000010DEd00000447sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=MCP65 SMU (Pavilion dv9500/9600/9700 series) + +pci:v000010DEd00000448* + ID_MODEL_FROM_DATABASE=MCP65 IDE + +pci:v000010DEd00000448sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=MCP65 IDE (Pavilion dv9668eg Laptop) + +pci:v000010DEd00000449* + ID_MODEL_FROM_DATABASE=MCP65 PCI bridge + +pci:v000010DEd00000449sv000010DEsd0000CB84* + ID_MODEL_FROM_DATABASE=MCP65 PCI bridge (HP Pavilion dv9668eg Laptop) + +pci:v000010DEd0000044A* + ID_MODEL_FROM_DATABASE=MCP65 High Definition Audio + +pci:v000010DEd0000044Asv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=MCP65 High Definition Audio (Pavilion dv9668eg Laptop) + +pci:v000010DEd0000044B* + ID_MODEL_FROM_DATABASE=MCP65 High Definition Audio + +pci:v000010DEd0000044C* + ID_MODEL_FROM_DATABASE=MCP65 AHCI Controller + +pci:v000010DEd0000044D* + ID_MODEL_FROM_DATABASE=MCP65 AHCI Controller + +pci:v000010DEd0000044E* + ID_MODEL_FROM_DATABASE=MCP65 AHCI Controller + +pci:v000010DEd0000044F* + ID_MODEL_FROM_DATABASE=MCP65 AHCI Controller + +pci:v000010DEd00000450* + ID_MODEL_FROM_DATABASE=MCP65 Ethernet + +pci:v000010DEd00000450sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=MCP65 Ethernet (Pavilion dv9668eg Laptop) + +pci:v000010DEd00000451* + ID_MODEL_FROM_DATABASE=MCP65 Ethernet + +pci:v000010DEd00000452* + ID_MODEL_FROM_DATABASE=MCP65 Ethernet + +pci:v000010DEd00000453* + ID_MODEL_FROM_DATABASE=MCP65 Ethernet + +pci:v000010DEd00000454* + ID_MODEL_FROM_DATABASE=MCP65 USB 1.1 OHCI Controller + +pci:v000010DEd00000454sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=MCP65 USB 1.1 OHCI Controller (Pavilion dv9668eg Laptop) + +pci:v000010DEd00000455* + ID_MODEL_FROM_DATABASE=MCP65 USB 2.0 EHCI Controller + +pci:v000010DEd00000455sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=MCP65 USB 2.0 EHCI Controller (Pavilion dv9668eg Laptop) + +pci:v000010DEd00000456* + ID_MODEL_FROM_DATABASE=MCP65 USB Controller + +pci:v000010DEd00000457* + ID_MODEL_FROM_DATABASE=MCP65 USB Controller + +pci:v000010DEd00000458* + ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge + +pci:v000010DEd00000458sv000010DEsd00000000* + ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge + +pci:v000010DEd00000459* + ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge + +pci:v000010DEd00000459sv000010DEsd00000000* + ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge + +pci:v000010DEd0000045A* + ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge + +pci:v000010DEd0000045Asv000010DEsd00000000* + ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge + +pci:v000010DEd0000045B* + ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge + +pci:v000010DEd0000045Bsv000010DEsd00000000* + ID_MODEL_FROM_DATABASE=MCP65 PCI Express bridge + +pci:v000010DEd0000045C* + ID_MODEL_FROM_DATABASE=MCP65 SATA Controller + +pci:v000010DEd0000045D* + ID_MODEL_FROM_DATABASE=MCP65 SATA Controller + +pci:v000010DEd0000045Dsv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=MCP65 SATA Controller (Pavilion dv9668eg Laptop) + +pci:v000010DEd0000045E* + ID_MODEL_FROM_DATABASE=MCP65 SATA Controller + +pci:v000010DEd0000045F* + ID_MODEL_FROM_DATABASE=MCP65 SATA Controller + +pci:v000010DEd00000531* + ID_MODEL_FROM_DATABASE=C67 [GeForce 7150M / nForce 630M] + +pci:v000010DEd00000533* + ID_MODEL_FROM_DATABASE=C67 [GeForce 7000M / nForce 610M] + +pci:v000010DEd0000053A* + ID_MODEL_FROM_DATABASE=C68 [GeForce 7050 PV / nForce 630a] + +pci:v000010DEd0000053B* + ID_MODEL_FROM_DATABASE=C68 [GeForce 7050 PV / nForce 630a] + +pci:v000010DEd0000053Bsv00001043sd00008308* + ID_MODEL_FROM_DATABASE=C68 [GeForce 7050 PV / nForce 630a] (M2N68-AM Motherboard) + +pci:v000010DEd0000053E* + ID_MODEL_FROM_DATABASE=C68 [GeForce 7025 / nForce 630a] + +pci:v000010DEd00000541* + ID_MODEL_FROM_DATABASE=MCP67 Memory Controller + +pci:v000010DEd00000542* + ID_MODEL_FROM_DATABASE=MCP67 SMBus + +pci:v000010DEd00000542sv00001043sd00008308* + ID_MODEL_FROM_DATABASE=MCP67 SMBus (M2N68-AM Motherboard) + +pci:v000010DEd00000543* + ID_MODEL_FROM_DATABASE=MCP67 Co-processor + +pci:v000010DEd00000547* + ID_MODEL_FROM_DATABASE=MCP67 Memory Controller + +pci:v000010DEd00000547sv00001043sd00008308* + ID_MODEL_FROM_DATABASE=MCP67 Memory Controller (M2N68-AM Motherboard) + +pci:v000010DEd00000547sv00001849sd00000547* + ID_MODEL_FROM_DATABASE=MCP67 Memory Controller (ALiveNF7G-HDready) + +pci:v000010DEd00000548* + ID_MODEL_FROM_DATABASE=MCP67 ISA Bridge + +pci:v000010DEd00000548sv00001043sd00008308* + ID_MODEL_FROM_DATABASE=MCP67 ISA Bridge (M2N68-AM Motherboard) + +pci:v000010DEd0000054C* + ID_MODEL_FROM_DATABASE=MCP67 Ethernet + +pci:v000010DEd0000054Csv00001043sd00008308* + ID_MODEL_FROM_DATABASE=MCP67 Ethernet (M2N68-AM Motherboard) + +pci:v000010DEd0000054Csv00001849sd0000054C* + ID_MODEL_FROM_DATABASE=MCP67 Ethernet (ALiveNF7G-HDready, MCP67 Gigabit Ethernet) + +pci:v000010DEd0000054D* + ID_MODEL_FROM_DATABASE=MCP67 Ethernet + +pci:v000010DEd0000054E* + ID_MODEL_FROM_DATABASE=MCP67 Ethernet + +pci:v000010DEd0000054F* + ID_MODEL_FROM_DATABASE=MCP67 Ethernet + +pci:v000010DEd00000550* + ID_MODEL_FROM_DATABASE=MCP67 AHCI Controller + +pci:v000010DEd00000550sv00001043sd00008308* + ID_MODEL_FROM_DATABASE=MCP67 AHCI Controller (M2N68-AM Motherboard) + +pci:v000010DEd00000554* + ID_MODEL_FROM_DATABASE=MCP67 AHCI Controller + +pci:v000010DEd00000554sv00001043sd00008308* + ID_MODEL_FROM_DATABASE=MCP67 AHCI Controller (M2N68-AM Motherboard) + +pci:v000010DEd00000555* + ID_MODEL_FROM_DATABASE=MCP67 SATA Controller + +pci:v000010DEd00000555sv00001043sd00008308* + ID_MODEL_FROM_DATABASE=MCP67 SATA Controller (M2N68-AM Motherboard) + +pci:v000010DEd0000055C* + ID_MODEL_FROM_DATABASE=MCP67 High Definition Audio + +pci:v000010DEd0000055Csv00001043sd00008290* + ID_MODEL_FROM_DATABASE=MCP67 High Definition Audio (M2N68-AM Motherboard) + +pci:v000010DEd0000055D* + ID_MODEL_FROM_DATABASE=MCP67 High Definition Audio + +pci:v000010DEd0000055E* + ID_MODEL_FROM_DATABASE=MCP67 OHCI USB 1.1 Controller + +pci:v000010DEd0000055Esv00001043sd00008308* + ID_MODEL_FROM_DATABASE=MCP67 OHCI USB 1.1 Controller (M2N68-AM Motherboard) + +pci:v000010DEd0000055F* + ID_MODEL_FROM_DATABASE=MCP67 EHCI USB 2.0 Controller + +pci:v000010DEd0000055Fsv00001043sd00008308* + ID_MODEL_FROM_DATABASE=MCP67 EHCI USB 2.0 Controller (M2N68-AM Motherboard) + +pci:v000010DEd00000560* + ID_MODEL_FROM_DATABASE=MCP67 IDE Controller + +pci:v000010DEd00000560sv0000F043sd00008308* + ID_MODEL_FROM_DATABASE=MCP67 IDE Controller (M2N68-AM Motherboard) + +pci:v000010DEd00000561* + ID_MODEL_FROM_DATABASE=MCP67 PCI Bridge + +pci:v000010DEd00000562* + ID_MODEL_FROM_DATABASE=MCP67 PCI Express Bridge + +pci:v000010DEd00000562sv00001849sd00000562* + ID_MODEL_FROM_DATABASE=MCP67 PCI Express Bridge (ALiveNF7G-HDready) + +pci:v000010DEd00000563* + ID_MODEL_FROM_DATABASE=MCP67 PCI Express Bridge + +pci:v000010DEd00000568* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller + +pci:v000010DEd00000568sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (Pavilion p6310f) + +pci:v000010DEd00000568sv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (M3N72-D) + +pci:v000010DEd00000568sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K9N2GM-FIH) + +pci:v000010DEd00000568sv00001849sd00000568* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K10N78FullHD-hSLI R3.0 Memory Controller) + +pci:v000010DEd00000569* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge + +pci:v000010DEd00000569sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (Pavilion p6310f) + +pci:v000010DEd00000569sv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (M3N72-D) + +pci:v000010DEd00000569sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K9N2GM-FIH) + +pci:v000010DEd00000569sv00001849sd00000569* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K10N78FullHD-hSLI R3.0 PCI Express Bridge) + +pci:v000010DEd0000056A* + ID_MODEL_FROM_DATABASE=MCP73 [nForce 630i] USB 2.0 Controller (EHCI) + +pci:v000010DEd0000056Asv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 [nForce 630i] USB 2.0 Controller (EHCI) (MCP73PVT-SM) + +pci:v000010DEd0000056Asv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 [nForce 630i] USB 2.0 Controller (EHCI) (I-N73V motherboard) + +pci:v000010DEd0000056C* + ID_MODEL_FROM_DATABASE=MCP73 IDE Controller + +pci:v000010DEd0000056Csv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 IDE Controller (MCP73PVT-SM) + +pci:v000010DEd0000056Csv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 IDE Controller (I-N73V motherboard) + +pci:v000010DEd0000056Csv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=MCP73 IDE Controller (JW-IN7150-HD) + +pci:v000010DEd0000056D* + ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge + +pci:v000010DEd0000056Dsv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73PVT-SM) + +pci:v000010DEd0000056Dsv000010DEsd0000CB73* + ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73 PCI Bridge) + +pci:v000010DEd0000056E* + ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge + +pci:v000010DEd0000056Esv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73PVT-SM) + +pci:v000010DEd0000056Esv000010DEsd00000000* + ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73 PCIe x16 port) + +pci:v000010DEd0000056F* + ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge + +pci:v000010DEd0000056Fsv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73PVT-SM) + +pci:v000010DEd0000056Fsv000010DEsd00000000* + ID_MODEL_FROM_DATABASE=MCP73 PCI Express bridge (MCP73 PCIe x1 port) + +pci:v000010DEd000005B1* + ID_MODEL_FROM_DATABASE=NF200 PCIe 2.0 switch + +pci:v000010DEd000005B8* + ID_MODEL_FROM_DATABASE=NF200 PCIe 2.0 switch for GTX 295 + +pci:v000010DEd000005BE* + ID_MODEL_FROM_DATABASE=NF200 PCIe 2.0 switch for Quadro Plex S4 / Tesla S870 / Tesla S1070 / Tesla S2050 + +pci:v000010DEd000005E0* + ID_MODEL_FROM_DATABASE=GT200b [GeForce GTX 295] + +pci:v000010DEd000005E1* + ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 280] + +pci:v000010DEd000005E2* + ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 260] + +pci:v000010DEd000005E3* + ID_MODEL_FROM_DATABASE=GT200b [GeForce GTX 285] + +pci:v000010DEd000005E3sv00001682sd00002490* + ID_MODEL_FROM_DATABASE=GT200b [GeForce GTX 285] (GX-285N-ZDF) + +pci:v000010DEd000005E6* + ID_MODEL_FROM_DATABASE=GT200b [GeForce GTX 275] + +pci:v000010DEd000005E7* + ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] + +pci:v000010DEd000005E7sv000010DEsd00000595* + ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] (Tesla T10 Processor) + +pci:v000010DEd000005E7sv000010DEsd0000068F* + ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] (Tesla T10 Processor) + +pci:v000010DEd000005E7sv000010DEsd00000697* + ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] (Tesla M1060) + +pci:v000010DEd000005E7sv000010DEsd00000714* + ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] (Tesla M1060) + +pci:v000010DEd000005E7sv000010DEsd00000743* + ID_MODEL_FROM_DATABASE=GT200GL [Tesla C1060 / M1060] (Tesla M1060) + +pci:v000010DEd000005EA* + ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 260] + +pci:v000010DEd000005EB* + ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 295] + +pci:v000010DEd000005ED* + ID_MODEL_FROM_DATABASE=GT200GL [Quadro Plex 2200 D2] + +pci:v000010DEd000005F1* + ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 280] + +pci:v000010DEd000005F2* + ID_MODEL_FROM_DATABASE=GT200 [GeForce GTX 260] + +pci:v000010DEd000005F8* + ID_MODEL_FROM_DATABASE=GT200GL [Quadro Plex 2200 S4] + +pci:v000010DEd000005F9* + ID_MODEL_FROM_DATABASE=GT200GL [Quadro CX] + +pci:v000010DEd000005FD* + ID_MODEL_FROM_DATABASE=GT200GL [Quadro FX 5800] + +pci:v000010DEd000005FE* + ID_MODEL_FROM_DATABASE=GT200GL [Quadro FX 4800] + +pci:v000010DEd000005FF* + ID_MODEL_FROM_DATABASE=GT200GL [Quadro FX 3800] + +pci:v000010DEd00000600* + ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GTS 512] + +pci:v000010DEd00000601* + ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GT] + +pci:v000010DEd00000602* + ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GT] + +pci:v000010DEd00000603* + ID_MODEL_FROM_DATABASE=G92 [GeForce GT 230 OEM] + +pci:v000010DEd00000604* + ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GX2] + +pci:v000010DEd00000605* + ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GT] + +pci:v000010DEd00000606* + ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GS] + +pci:v000010DEd00000607* + ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 240] + +pci:v000010DEd00000608* + ID_MODEL_FROM_DATABASE=G92M [GeForce 9800M GTX] + +pci:v000010DEd00000609* + ID_MODEL_FROM_DATABASE=G92M [GeForce 8800M GTS] + +pci:v000010DEd00000609sv0000106Bsd000000A7* + ID_MODEL_FROM_DATABASE=G92M [GeForce 8800M GTS] (GeForce 8800 GS) + +pci:v000010DEd0000060A* + ID_MODEL_FROM_DATABASE=G92M [GeForce GTX 280M] + +pci:v000010DEd0000060B* + ID_MODEL_FROM_DATABASE=G92M [GeForce 9800M GT] + +pci:v000010DEd0000060C* + ID_MODEL_FROM_DATABASE=G92M [GeForce 8800M GTX] + +pci:v000010DEd0000060D* + ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GS] + +pci:v000010DEd0000060F* + ID_MODEL_FROM_DATABASE=G92M [GeForce GTX 285M] + +pci:v000010DEd00000610* + ID_MODEL_FROM_DATABASE=G92 [GeForce 9600 GSO] + +pci:v000010DEd00000610sv00001682sd00002385* + ID_MODEL_FROM_DATABASE=G92 [GeForce 9600 GSO] (GeForce 9600 GSO 768mb) + +pci:v000010DEd00000611* + ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GT] + +pci:v000010DEd00000611sv0000107Dsd00002AB0* + ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GT] (Winfast PX8800 GT PCI-E) + +pci:v000010DEd00000611sv00001462sd00001170* + ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GT] (NX8800GT series model V117 2xDVI+TV) + +pci:v000010DEd00000611sv000019DAsd00001040* + ID_MODEL_FROM_DATABASE=G92 [GeForce 8800 GT] (ZT-88TES2P-FSP) + +pci:v000010DEd00000612* + ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GTX / 9800 GTX+] + +pci:v000010DEd00000613* + ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GTX+] + +pci:v000010DEd00000614* + ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GT] + +pci:v000010DEd00000614sv0000107Dsd00002AB3* + ID_MODEL_FROM_DATABASE=G92 [GeForce 9800 GT] (WinFast PX9800 GT (S-Fanpipe)) + +pci:v000010DEd00000615* + ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 250] + +pci:v000010DEd00000615sv00003842sd00001150* + ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 250] (GeForce GTS 250 P/N 512-P3-1150-TR) + +pci:v000010DEd00000615sv00003842sd00001151* + ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 250] (GeForce GTS 250 P/N 512-P3-1151-TR) + +pci:v000010DEd00000615sv00003842sd00001155* + ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 250] (GeForce GTS 250 P/N 01G-P3-1155-TR) + +pci:v000010DEd00000615sv00003842sd00001156* + ID_MODEL_FROM_DATABASE=G92 [GeForce GTS 250] (GeForce GTS 250 P/N 01G-P3-1156-TR) + +pci:v000010DEd00000617* + ID_MODEL_FROM_DATABASE=G92M [GeForce 9800M GTX] + +pci:v000010DEd00000618* + ID_MODEL_FROM_DATABASE=G92M [GeForce GTX 260M] + +pci:v000010DEd00000619* + ID_MODEL_FROM_DATABASE=G92GL [Quadro FX 4700 X2] + +pci:v000010DEd0000061A* + ID_MODEL_FROM_DATABASE=G92GL [Quadro FX 3700] + +pci:v000010DEd0000061B* + ID_MODEL_FROM_DATABASE=G92GL [Quadro VX 200] + +pci:v000010DEd0000061C* + ID_MODEL_FROM_DATABASE=G92GLM [Quadro FX 3600M] + +pci:v000010DEd0000061D* + ID_MODEL_FROM_DATABASE=G92GLM [Quadro FX 2800M] + +pci:v000010DEd0000061E* + ID_MODEL_FROM_DATABASE=G92GLM [Quadro FX 3700M] + +pci:v000010DEd0000061F* + ID_MODEL_FROM_DATABASE=G92GLM [Quadro FX 3800M] + +pci:v000010DEd00000620* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9800 GT] + +pci:v000010DEd00000621* + ID_MODEL_FROM_DATABASE=G94 [GeForce GT 230] + +pci:v000010DEd00000622* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] + +pci:v000010DEd00000622sv0000107Dsd00002AC1* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] (WinFast PX9600GT 1024MB) + +pci:v000010DEd00000622sv00001458sd00003481* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] (GV-NX96T512HP) + +pci:v000010DEd00000623* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GS] + +pci:v000010DEd00000624* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT Green Edition] + +pci:v000010DEd00000625* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GSO 512] + +pci:v000010DEd00000626* + ID_MODEL_FROM_DATABASE=G94 [GeForce GT 130] + +pci:v000010DEd00000627* + ID_MODEL_FROM_DATABASE=G94 [GeForce GT 140] + +pci:v000010DEd00000628* + ID_MODEL_FROM_DATABASE=G94M [GeForce 9800M GTS] + +pci:v000010DEd0000062A* + ID_MODEL_FROM_DATABASE=G94M [GeForce 9700M GTS] + +pci:v000010DEd0000062B* + ID_MODEL_FROM_DATABASE=G94M [GeForce 9800M GS] + +pci:v000010DEd0000062C* + ID_MODEL_FROM_DATABASE=G94M [GeForce 9800M GTS] + +pci:v000010DEd0000062D* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] + +pci:v000010DEd0000062E* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] + +pci:v000010DEd0000062Esv0000106Bsd00000605* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] (GeForce GT 130) + +pci:v000010DEd0000062F* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9800 S] + +pci:v000010DEd00000630* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] + +pci:v000010DEd00000631* + ID_MODEL_FROM_DATABASE=G94M [GeForce GTS 160M] + +pci:v000010DEd00000632* + ID_MODEL_FROM_DATABASE=G94M [GeForce GTS 150M] + +pci:v000010DEd00000633* + ID_MODEL_FROM_DATABASE=G94 [GeForce GT 220] + +pci:v000010DEd00000635* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GSO] + +pci:v000010DEd00000637* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GT] + +pci:v000010DEd00000638* + ID_MODEL_FROM_DATABASE=G94GL [Quadro FX 1800] + +pci:v000010DEd0000063A* + ID_MODEL_FROM_DATABASE=G94GLM [Quadro FX 2700M] + +pci:v000010DEd0000063F* + ID_MODEL_FROM_DATABASE=G94 [GeForce 9600 GE] + +pci:v000010DEd00000640* + ID_MODEL_FROM_DATABASE=G96C [GeForce 9500 GT] + +pci:v000010DEd00000641* + ID_MODEL_FROM_DATABASE=G96C [GeForce 9400 GT] + +pci:v000010DEd00000641sv00001682sd00004009* + ID_MODEL_FROM_DATABASE=G96C [GeForce 9400 GT] (PV-T94G-ZAFG) + +pci:v000010DEd00000642* + ID_MODEL_FROM_DATABASE=G96 [D9M-10] + +pci:v000010DEd00000643* + ID_MODEL_FROM_DATABASE=G96 [GeForce 9500 GT] + +pci:v000010DEd00000644* + ID_MODEL_FROM_DATABASE=G96 [GeForce 9500 GS] + +pci:v000010DEd00000644sv0000174Bsd00009600* + ID_MODEL_FROM_DATABASE=G96 [GeForce 9500 GS] (Geforce 9500GS 512M DDR2 V/D/HDMI) + +pci:v000010DEd00000645* + ID_MODEL_FROM_DATABASE=G96C [GeForce 9500 GS] + +pci:v000010DEd00000646* + ID_MODEL_FROM_DATABASE=G96C [GeForce GT 120] + +pci:v000010DEd00000647* + ID_MODEL_FROM_DATABASE=G96CM [GeForce 9600M GT] + +pci:v000010DEd00000648* + ID_MODEL_FROM_DATABASE=G96CM [GeForce 9600M GS] + +pci:v000010DEd00000649* + ID_MODEL_FROM_DATABASE=G96CM [GeForce 9600M GT] + +pci:v000010DEd00000649sv00001043sd0000202D* + ID_MODEL_FROM_DATABASE=G96CM [GeForce 9600M GT] (GeForce GT 220M) + +pci:v000010DEd0000064A* + ID_MODEL_FROM_DATABASE=G96M [GeForce 9700M GT] + +pci:v000010DEd0000064B* + ID_MODEL_FROM_DATABASE=G96M [GeForce 9500M G] + +pci:v000010DEd0000064C* + ID_MODEL_FROM_DATABASE=G96CM [GeForce 9650M GT] + +pci:v000010DEd0000064E* + ID_MODEL_FROM_DATABASE=G96C [GeForce 9600 GSO / 9800 GT] + +pci:v000010DEd00000651* + ID_MODEL_FROM_DATABASE=G96CM [GeForce G 110M] + +pci:v000010DEd00000652* + ID_MODEL_FROM_DATABASE=G96CM [GeForce GT 130M] + +pci:v000010DEd00000652sv0000152Dsd00000850* + ID_MODEL_FROM_DATABASE=G96CM [GeForce GT 130M] (GeForce GT 240M LE) + +pci:v000010DEd00000653* + ID_MODEL_FROM_DATABASE=G96CM [GeForce GT 120M] + +pci:v000010DEd00000654* + ID_MODEL_FROM_DATABASE=G96CM [GeForce GT 220M] + +pci:v000010DEd00000654sv00001043sd000014A2* + ID_MODEL_FROM_DATABASE=G96CM [GeForce GT 220M] (GeForce GT 320M) + +pci:v000010DEd00000654sv00001043sd000014D2* + ID_MODEL_FROM_DATABASE=G96CM [GeForce GT 220M] (GeForce GT 320M) + +pci:v000010DEd00000655* + ID_MODEL_FROM_DATABASE=G96 [GeForce GT 120 Mac Edition] + +pci:v000010DEd00000656* + ID_MODEL_FROM_DATABASE=G96 [GeForce GT 120 Mac Edition] + +pci:v000010DEd00000658* + ID_MODEL_FROM_DATABASE=G96GL [Quadro FX 380] + +pci:v000010DEd00000659* + ID_MODEL_FROM_DATABASE=G96CGL [Quadro FX 580] + +pci:v000010DEd0000065A* + ID_MODEL_FROM_DATABASE=G96GLM [Quadro FX 1700M] + +pci:v000010DEd0000065B* + ID_MODEL_FROM_DATABASE=G96C [GeForce 9400 GT] + +pci:v000010DEd0000065C* + ID_MODEL_FROM_DATABASE=G96GLM [Quadro FX 770M] + +pci:v000010DEd0000065D* + ID_MODEL_FROM_DATABASE=G96 [GeForce 9500 GA / 9600 GT / GTS 250] + +pci:v000010DEd0000065F* + ID_MODEL_FROM_DATABASE=G96C [GeForce G210] + +pci:v000010DEd000006C0* + ID_MODEL_FROM_DATABASE=GF100 [GeForce GTX 480] + +pci:v000010DEd000006C4* + ID_MODEL_FROM_DATABASE=GF100 [GeForce GTX 465] + +pci:v000010DEd000006CA* + ID_MODEL_FROM_DATABASE=GF100M [GeForce GTX 480M] + +pci:v000010DEd000006CB* + ID_MODEL_FROM_DATABASE=GF100 [GeForce GTX 480] + +pci:v000010DEd000006CD* + ID_MODEL_FROM_DATABASE=GF100 [GeForce GTX 470] + +pci:v000010DEd000006D0* + ID_MODEL_FROM_DATABASE=GF100GL + +pci:v000010DEd000006D1* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla C2050 / C2070] + +pci:v000010DEd000006D1sv000010DEsd00000771* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla C2050 / C2070] (Tesla C2050) + +pci:v000010DEd000006D1sv000010DEsd00000772* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla C2050 / C2070] (Tesla C2070) + +pci:v000010DEd000006D2* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] + +pci:v000010DEd000006D2sv000010DEsd00000774* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] (Tesla M2070) + +pci:v000010DEd000006D2sv000010DEsd00000830* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] (Tesla M2070) + +pci:v000010DEd000006D2sv000010DEsd00000842* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] (Tesla M2070) + +pci:v000010DEd000006D2sv000010DEsd0000088F* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] (Tesla X2070) + +pci:v000010DEd000006D2sv000010DEsd00000908* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070] (Tesla M2070) + +pci:v000010DEd000006D8* + ID_MODEL_FROM_DATABASE=GF100GL [Quadro 6000] + +pci:v000010DEd000006D9* + ID_MODEL_FROM_DATABASE=GF100GL [Quadro 5000] + +pci:v000010DEd000006DA* + ID_MODEL_FROM_DATABASE=GF100GLM [Quadro 5000M] + +pci:v000010DEd000006DC* + ID_MODEL_FROM_DATABASE=GF100GL [Quadro 6000] + +pci:v000010DEd000006DD* + ID_MODEL_FROM_DATABASE=GF100GL [Quadro 4000] + +pci:v000010DEd000006DE* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] + +pci:v000010DEd000006DEsv000010DEsd00000773* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla S2050) + +pci:v000010DEd000006DEsv000010DEsd0000082F* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) + +pci:v000010DEd000006DEsv000010DEsd00000840* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla X2070) + +pci:v000010DEd000006DEsv000010DEsd00000842* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) + +pci:v000010DEd000006DEsv000010DEsd00000846* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) + +pci:v000010DEd000006DEsv000010DEsd00000866* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) + +pci:v000010DEd000006DEsv000010DEsd00000907* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) + +pci:v000010DEd000006DEsv000010DEsd0000091E* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla T20 Processor] (Tesla M2050) + +pci:v000010DEd000006DF* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070-Q] + +pci:v000010DEd000006DFsv000010DEsd0000084D* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070-Q] (Tesla M2070-Q) + +pci:v000010DEd000006DFsv000010DEsd0000087F* + ID_MODEL_FROM_DATABASE=GF100GL [Tesla M2070-Q] (Tesla M2070-Q) + +pci:v000010DEd000006E0* + ID_MODEL_FROM_DATABASE=G98 [GeForce 9300 GE] + +pci:v000010DEd000006E0sv0000107Dsd00005A96* + ID_MODEL_FROM_DATABASE=G98 [GeForce 9300 GE] (Geforce 9300GE) + +pci:v000010DEd000006E1* + ID_MODEL_FROM_DATABASE=G98 [GeForce 9300 GS] + +pci:v000010DEd000006E2* + ID_MODEL_FROM_DATABASE=G98 [GeForce 8400] + +pci:v000010DEd000006E3* + ID_MODEL_FROM_DATABASE=G98 [GeForce 8300 GS] + +pci:v000010DEd000006E4* + ID_MODEL_FROM_DATABASE=G98 [GeForce 8400 GS Rev. 2] + +pci:v000010DEd000006E4sv00001458sd00003475* + ID_MODEL_FROM_DATABASE=G98 [GeForce 8400 GS Rev. 2] (GV-NX84S256HE [GeForce 8400 GS]) + +pci:v000010DEd000006E5* + ID_MODEL_FROM_DATABASE=G98M [GeForce 9300M GS] + +pci:v000010DEd000006E6* + ID_MODEL_FROM_DATABASE=G98 [GeForce G 100] + +pci:v000010DEd000006E7* + ID_MODEL_FROM_DATABASE=G98 [GeForce 9300 SE] + +pci:v000010DEd000006E8* + ID_MODEL_FROM_DATABASE=G98M [GeForce 9200M GS] + +pci:v000010DEd000006E8sv0000103Csd0000360B* + ID_MODEL_FROM_DATABASE=G98M [GeForce 9200M GS] (GeForce 9200M GE) + +pci:v000010DEd000006E9* + ID_MODEL_FROM_DATABASE=G98M [GeForce 9300M GS] + +pci:v000010DEd000006E9sv00001043sd000019B2* + ID_MODEL_FROM_DATABASE=G98M [GeForce 9300M GS] (U6V laptop) + +pci:v000010DEd000006EA* + ID_MODEL_FROM_DATABASE=G98M [Quadro NVS 150M] + +pci:v000010DEd000006EB* + ID_MODEL_FROM_DATABASE=G98M [Quadro NVS 160M] + +pci:v000010DEd000006EC* + ID_MODEL_FROM_DATABASE=G98M [GeForce G 105M] + +pci:v000010DEd000006ED* + ID_MODEL_FROM_DATABASE=G98 [GeForce 9600 GT / 9800 GT] + +pci:v000010DEd000006EE* + ID_MODEL_FROM_DATABASE=G98 [GeForce 9600 GT / 9800 GT] + +pci:v000010DEd000006EF* + ID_MODEL_FROM_DATABASE=G98M [GeForce G 103M] + +pci:v000010DEd000006F1* + ID_MODEL_FROM_DATABASE=G98M [GeForce G 105M] + +pci:v000010DEd000006F8* + ID_MODEL_FROM_DATABASE=G98 [Quadro NVS 420] + +pci:v000010DEd000006F9* + ID_MODEL_FROM_DATABASE=G98GL [Quadro FX 370 LP] + +pci:v000010DEd000006FA* + ID_MODEL_FROM_DATABASE=G98 [Quadro NVS 450] + +pci:v000010DEd000006FB* + ID_MODEL_FROM_DATABASE=G98GLM [Quadro FX 370M] + +pci:v000010DEd000006FD* + ID_MODEL_FROM_DATABASE=G98 [Quadro NVS 295] + +pci:v000010DEd000006FF* + ID_MODEL_FROM_DATABASE=G98 [HICx16 + Graphics] + +pci:v000010DEd000006FFsv000010DEsd00000711* + ID_MODEL_FROM_DATABASE=G98 [HICx16 + Graphics] (HICx8 + Graphics) + +pci:v000010DEd00000751* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller + +pci:v000010DEd00000751sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (Pavilion p6310f) + +pci:v000010DEd00000751sv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (M3N72-D) + +pci:v000010DEd00000751sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K9N2GM-FIH) + +pci:v000010DEd00000751sv00001849sd00000751* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K10N78FullHD-hSLI R3.0 Memory Controller) + +pci:v000010DEd00000752* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SMBus + +pci:v000010DEd00000752sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SMBus (Pavilion p6310f) + +pci:v000010DEd00000752sv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SMBus (M3N72-D) + +pci:v000010DEd00000752sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SMBus (K9N2GM-FIH) + +pci:v000010DEd00000752sv00001849sd00000752* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SMBus (K10N78FullHD-hSLI R3.0 SMBus) + +pci:v000010DEd00000753* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Co-Processor + +pci:v000010DEd00000753sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Co-Processor (Pavilion p6310f) + +pci:v000010DEd00000753sv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Co-Processor (M3N72-D) + +pci:v000010DEd00000753sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Co-Processor (K9N2GM-FIH) + +pci:v000010DEd00000753sv00001849sd00000753* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Co-Processor (K10N78FullHD-hSLI R3.0 Co-Processor) + +pci:v000010DEd00000754* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller + +pci:v000010DEd00000754sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (Pavilion p6310f) + +pci:v000010DEd00000754sv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (M3N72-D) + +pci:v000010DEd00000754sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K9N2GM-FIH) + +pci:v000010DEd00000754sv00001849sd00000754* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] Memory Controller (K10N78FullHD-hSLI R3.0 Memory Controller) + +pci:v000010DEd00000759* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] IDE + +pci:v000010DEd00000759sv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] IDE (M3N72-D) + +pci:v000010DEd00000759sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] IDE (K9N2GM-FIH) + +pci:v000010DEd00000759sv00001849sd00000759* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] IDE (K10N78FullHD-hSLI R3.0 IDE) + +pci:v000010DEd0000075A* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge + +pci:v000010DEd0000075Asv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (Pavilion p6310f) + +pci:v000010DEd0000075Asv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (M3N72-D) + +pci:v000010DEd0000075Asv00001849sd0000075A* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (K10N78FullHD-hSLI R3.0 PCI Bridge) + +pci:v000010DEd0000075B* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge + +pci:v000010DEd0000075Bsv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (Pavilion p6310f) + +pci:v000010DEd0000075Bsv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (M3N72-D) + +pci:v000010DEd0000075Bsv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K9N2GM-FIH) + +pci:v000010DEd0000075Bsv00001849sd0000075B* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K10N78FullHD-hSLI R3.0 PCI Express Bridge) + +pci:v000010DEd0000075C* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge + +pci:v000010DEd0000075Csv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge (Pavilion p6310f) + +pci:v000010DEd0000075Csv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge (K9N2GM-FIH) + +pci:v000010DEd0000075Csv00001849sd0000075C* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge (K10N78FullHD-hSLI R3.0 LPC Bridge) + +pci:v000010DEd0000075D* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge + +pci:v000010DEd0000075Dsv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] LPC Bridge (M3N72-D) + +pci:v000010DEd00000760* + ID_MODEL_FROM_DATABASE=MCP77 Ethernet + +pci:v000010DEd00000760sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP77 Ethernet (Pavilion p6310f) + +pci:v000010DEd00000760sv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP77 Ethernet (M3N72-D) + +pci:v000010DEd00000760sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP77 Ethernet (K9N2GM-FIH) + +pci:v000010DEd00000760sv00001849sd00000760* + ID_MODEL_FROM_DATABASE=MCP77 Ethernet (K10N78FullHD-hSLI R3.0 Ethernet) + +pci:v000010DEd00000761* + ID_MODEL_FROM_DATABASE=MCP77 Ethernet + +pci:v000010DEd00000762* + ID_MODEL_FROM_DATABASE=MCP77 Ethernet + +pci:v000010DEd00000763* + ID_MODEL_FROM_DATABASE=MCP77 Ethernet + +pci:v000010DEd00000774* + ID_MODEL_FROM_DATABASE=MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio + +pci:v000010DEd00000774sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio (Pavilion p6310f) + +pci:v000010DEd00000774sv00001043sd000082FE* + ID_MODEL_FROM_DATABASE=MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio (M3N72-D) + +pci:v000010DEd00000774sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio (K9N2GM-FIH) + +pci:v000010DEd00000774sv00001849sd00003662* + ID_MODEL_FROM_DATABASE=MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio (K10N78FullHD-hSLI R3.0 High Definition Audio) + +pci:v000010DEd00000778* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge + +pci:v000010DEd00000778sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (Pavilion p6310f) + +pci:v000010DEd00000778sv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (M3N72-D) + +pci:v000010DEd00000778sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K9N2GM-FIH) + +pci:v000010DEd00000778sv00001849sd00000778* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Express Bridge (K10N78FullHD-hSLI R3.0 PCI Express Bridge) + +pci:v000010DEd0000077A* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge + +pci:v000010DEd0000077Asv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (Pavilion p6310f) + +pci:v000010DEd0000077Asv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (M3N72-D) + +pci:v000010DEd0000077Asv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (K9N2GM-FIH) + +pci:v000010DEd0000077Asv00001849sd0000077A* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] PCI Bridge (K10N78FullHD-hSLI R3.0 PCI Bridge) + +pci:v000010DEd0000077B* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller + +pci:v000010DEd0000077Bsv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (Pavilion p6310f) + +pci:v000010DEd0000077Bsv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (M3N72-D) + +pci:v000010DEd0000077Bsv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (K9N2GM-FIH) + +pci:v000010DEd0000077Bsv00001849sd0000077B* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (K10N78FullHD-hSLI R3.0 OHCI USB 1.1 Controller) + +pci:v000010DEd0000077C* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller + +pci:v000010DEd0000077Csv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (Pavilion p6310f) + +pci:v000010DEd0000077Csv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (M3N72-D) + +pci:v000010DEd0000077Csv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (K9N2GM-FIH) + +pci:v000010DEd0000077Csv00001849sd0000077C* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (K10N78FullHD-hSLI R3.0 EHCI USB 2.0 Controller) + +pci:v000010DEd0000077D* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller + +pci:v000010DEd0000077Dsv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (Pavilion p6310f) + +pci:v000010DEd0000077Dsv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (M3N72-D) + +pci:v000010DEd0000077Dsv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (K9N2GM-FIH) + +pci:v000010DEd0000077Dsv00001849sd0000077D* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] OHCI USB 1.1 Controller (K10N78FullHD-hSLI R3.0 OHCI USB 1.1 Controller) + +pci:v000010DEd0000077E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller + +pci:v000010DEd0000077Esv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (Pavilion p6310f) + +pci:v000010DEd0000077Esv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (M3N72-D) + +pci:v000010DEd0000077Esv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (K9N2GM-FIH) + +pci:v000010DEd0000077Esv00001849sd0000077E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] EHCI USB 2.0 Controller (K10N78FullHD-hSLI R3.0 EHCI USB 2.0 Controller) + +pci:v000010DEd000007C0* + ID_MODEL_FROM_DATABASE=MCP73 Host Bridge + +pci:v000010DEd000007C0sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=MCP73 Host Bridge (JW-IN7150-HD) + +pci:v000010DEd000007C1* + ID_MODEL_FROM_DATABASE=MCP73 Host Bridge + +pci:v000010DEd000007C1sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 Host Bridge (MCP73PVT-SM) + +pci:v000010DEd000007C2* + ID_MODEL_FROM_DATABASE=MCP73 Host Bridge + +pci:v000010DEd000007C3* + ID_MODEL_FROM_DATABASE=MCP73 Host Bridge + +pci:v000010DEd000007C3sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 Host Bridge (I-N73V motherboard) + +pci:v000010DEd000007C5* + ID_MODEL_FROM_DATABASE=MCP73 Host Bridge + +pci:v000010DEd000007C8* + ID_MODEL_FROM_DATABASE=MCP73 Memory Controller + +pci:v000010DEd000007C8sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (MCP73PVT-SM) + +pci:v000010DEd000007C8sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (I-N73V motherboard) + +pci:v000010DEd000007C8sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (JW-IN7150-HD) + +pci:v000010DEd000007CB* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller + +pci:v000010DEd000007CBsv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) + +pci:v000010DEd000007CBsv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) + +pci:v000010DEd000007CBsv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) + +pci:v000010DEd000007CD* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller + +pci:v000010DEd000007CDsv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) + +pci:v000010DEd000007CDsv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) + +pci:v000010DEd000007CDsv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) + +pci:v000010DEd000007CE* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller + +pci:v000010DEd000007CEsv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) + +pci:v000010DEd000007CEsv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) + +pci:v000010DEd000007CEsv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) + +pci:v000010DEd000007CF* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller + +pci:v000010DEd000007CFsv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) + +pci:v000010DEd000007CFsv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) + +pci:v000010DEd000007CFsv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) + +pci:v000010DEd000007D0* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller + +pci:v000010DEd000007D0sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) + +pci:v000010DEd000007D0sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) + +pci:v000010DEd000007D0sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) + +pci:v000010DEd000007D1* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller + +pci:v000010DEd000007D1sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) + +pci:v000010DEd000007D1sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) + +pci:v000010DEd000007D1sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) + +pci:v000010DEd000007D2* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller + +pci:v000010DEd000007D2sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) + +pci:v000010DEd000007D2sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) + +pci:v000010DEd000007D2sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) + +pci:v000010DEd000007D3* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller + +pci:v000010DEd000007D3sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) + +pci:v000010DEd000007D3sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) + +pci:v000010DEd000007D3sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) + +pci:v000010DEd000007D6* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller + +pci:v000010DEd000007D6sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (MCP73PVT-SM) + +pci:v000010DEd000007D6sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (I-N73V motherboard) + +pci:v000010DEd000007D6sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=nForce 610i/630i memory controller (JW-IN7150-HD) + +pci:v000010DEd000007D7* + ID_MODEL_FROM_DATABASE=MCP73 LPC Bridge + +pci:v000010DEd000007D7sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 LPC Bridge (MCP73PVT-SM) + +pci:v000010DEd000007D7sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 LPC Bridge (I-N73V motherboard) + +pci:v000010DEd000007D7sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=MCP73 LPC Bridge (JW-IN7150-HD) + +pci:v000010DEd000007D8* + ID_MODEL_FROM_DATABASE=MCP73 SMBus + +pci:v000010DEd000007D8sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 SMBus (MCP73PVT-SM) + +pci:v000010DEd000007D8sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 SMBus (I-N73V motherboard) + +pci:v000010DEd000007D8sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=MCP73 SMBus (JW-IN7150-HD) + +pci:v000010DEd000007D9* + ID_MODEL_FROM_DATABASE=MCP73 Memory Controller + +pci:v000010DEd000007D9sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (MCP73PVT-SM) + +pci:v000010DEd000007D9sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (I-N73V motherboard) + +pci:v000010DEd000007D9sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=MCP73 Memory Controller (JW-IN7150-HD) + +pci:v000010DEd000007DA* + ID_MODEL_FROM_DATABASE=MCP73 Co-processor + +pci:v000010DEd000007DAsv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=MCP73 Co-processor (JW-IN7150-HD) + +pci:v000010DEd000007DC* + ID_MODEL_FROM_DATABASE=MCP73 Ethernet + +pci:v000010DEd000007DCsv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 Ethernet (I-N73V motherboard) + +pci:v000010DEd000007DD* + ID_MODEL_FROM_DATABASE=MCP73 Ethernet + +pci:v000010DEd000007DE* + ID_MODEL_FROM_DATABASE=MCP73 Ethernet + +pci:v000010DEd000007DF* + ID_MODEL_FROM_DATABASE=MCP73 Ethernet + +pci:v000010DEd000007E0* + ID_MODEL_FROM_DATABASE=C73 [GeForce 7150 / nForce 630i] + +pci:v000010DEd000007E0sv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=C73 [GeForce 7150 / nForce 630i] (JW-IN7150-HD) + +pci:v000010DEd000007E1* + ID_MODEL_FROM_DATABASE=C73 [GeForce 7100 / nForce 630i] + +pci:v000010DEd000007E1sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=C73 [GeForce 7100 / nForce 630i] (MCP73PVT-SM) + +pci:v000010DEd000007E2* + ID_MODEL_FROM_DATABASE=C73 [GeForce 7050 / nForce 630i] + +pci:v000010DEd000007E3* + ID_MODEL_FROM_DATABASE=C73 [GeForce 7050 / nForce 610i] + +pci:v000010DEd000007E3sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=C73 [GeForce 7050 / nForce 610i] (I-N73V motherboard) + +pci:v000010DEd000007E5* + ID_MODEL_FROM_DATABASE=C73 [GeForce 7100 / nForce 620i] + +pci:v000010DEd000007F0* + ID_MODEL_FROM_DATABASE=MCP73 SATA Controller (IDE mode) + +pci:v000010DEd000007F0sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 SATA Controller (IDE mode) (I-N73V motherboard) + +pci:v000010DEd000007F4* + ID_MODEL_FROM_DATABASE=GeForce 7100/nForce 630i SATA + +pci:v000010DEd000007F4sv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=GeForce 7100/nForce 630i SATA (MCP73PVT-SM) + +pci:v000010DEd000007F4sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=GeForce 7100/nForce 630i SATA (I-N73V motherboard) + +pci:v000010DEd000007F8* + ID_MODEL_FROM_DATABASE=MCP73 SATA RAID Controller + +pci:v000010DEd000007F8sv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 SATA RAID Controller (I-N73V motherboard) + +pci:v000010DEd000007FC* + ID_MODEL_FROM_DATABASE=MCP73 High Definition Audio + +pci:v000010DEd000007FCsv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 High Definition Audio (MCP73PVT-SM) + +pci:v000010DEd000007FCsv000010DEsd000007FC* + ID_MODEL_FROM_DATABASE=MCP73 High Definition Audio + +pci:v000010DEd000007FCsv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 High Definition Audio (I-N73V motherboard) + +pci:v000010DEd000007FE* + ID_MODEL_FROM_DATABASE=MCP73 OHCI USB 1.1 Controller + +pci:v000010DEd000007FEsv00001019sd0000297A* + ID_MODEL_FROM_DATABASE=MCP73 OHCI USB 1.1 Controller (MCP73PVT-SM) + +pci:v000010DEd000007FEsv0000147Bsd00001C3E* + ID_MODEL_FROM_DATABASE=MCP73 OHCI USB 1.1 Controller (I-N73V motherboard) + +pci:v000010DEd000007FEsv00001AFAsd00007150* + ID_MODEL_FROM_DATABASE=MCP73 OHCI USB 1.1 Controller (JW-IN7150-HD) + +pci:v000010DEd00000840* + ID_MODEL_FROM_DATABASE=C77 [GeForce 8200M] + +pci:v000010DEd00000844* + ID_MODEL_FROM_DATABASE=C77 [GeForce 9100M G] + +pci:v000010DEd00000845* + ID_MODEL_FROM_DATABASE=C77 [GeForce 8200M G] + +pci:v000010DEd00000846* + ID_MODEL_FROM_DATABASE=C77 [GeForce 9200] + +pci:v000010DEd00000847* + ID_MODEL_FROM_DATABASE=C78 [GeForce 9100] + +pci:v000010DEd00000847sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=C78 [GeForce 9100] (Pavilion p6310f) + +pci:v000010DEd00000848* + ID_MODEL_FROM_DATABASE=C77 [GeForce 8300] + +pci:v000010DEd00000849* + ID_MODEL_FROM_DATABASE=C77 [GeForce 8200] + +pci:v000010DEd00000849sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=C77 [GeForce 8200] (K9N2GM-FIH) + +pci:v000010DEd00000849sv00001849sd00000849* + ID_MODEL_FROM_DATABASE=C77 [GeForce 8200] (K10N78FullHD-hSLI R3.0 GeForce 8200) + +pci:v000010DEd0000084A* + ID_MODEL_FROM_DATABASE=C77 [nForce 730a] + +pci:v000010DEd0000084B* + ID_MODEL_FROM_DATABASE=C77 [GeForce 8200] + +pci:v000010DEd0000084C* + ID_MODEL_FROM_DATABASE=C77 [nForce 780a/980a SLI] + +pci:v000010DEd0000084D* + ID_MODEL_FROM_DATABASE=C77 [nForce 750a SLI] + +pci:v000010DEd0000084Dsv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=C77 [nForce 750a SLI] (M3N72-D mGPU) + +pci:v000010DEd0000084F* + ID_MODEL_FROM_DATABASE=C77 [GeForce 8100 / nForce 720a] + +pci:v000010DEd00000860* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9300] + +pci:v000010DEd00000861* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400] + +pci:v000010DEd00000862* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M G] + +pci:v000010DEd00000863* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M] + +pci:v000010DEd00000863sv0000106Bsd000000AA* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M] (MacBook5,1) + +pci:v000010DEd00000864* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9300] + +pci:v000010DEd00000865* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9300 / ION] + +pci:v000010DEd00000866* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M G] + +pci:v000010DEd00000866sv0000106Bsd000000B1* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M G] (GeForce 9400M) + +pci:v000010DEd00000867* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400] + +pci:v000010DEd00000867sv0000106Bsd000000AD* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400] (iMac 9,1) + +pci:v000010DEd00000868* + ID_MODEL_FROM_DATABASE=C79 [nForce 760i SLI] + +pci:v000010DEd00000869* + ID_MODEL_FROM_DATABASE=MCP7A [GeForce 9400] + +pci:v000010DEd0000086A* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400] + +pci:v000010DEd0000086C* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9300 / nForce 730i] + +pci:v000010DEd0000086D* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9200] + +pci:v000010DEd0000086E* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9100M G] + +pci:v000010DEd0000086F* + ID_MODEL_FROM_DATABASE=MCP79 [GeForce 8200M G] + +pci:v000010DEd00000870* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M] + +pci:v000010DEd00000871* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9200] + +pci:v000010DEd00000872* + ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] + +pci:v000010DEd00000872sv00001043sd000019B4* + ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G102M) + +pci:v000010DEd00000872sv00001043sd00001AA2* + ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G102M) + +pci:v000010DEd00000872sv00001043sd00001C02* + ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G102M) + +pci:v000010DEd00000872sv00001043sd00001C42* + ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G205M) + +pci:v000010DEd00000873* + ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] + +pci:v000010DEd00000873sv00001043sd000019B4* + ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G102M) + +pci:v000010DEd00000873sv00001043sd00001C12* + ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G102M) + +pci:v000010DEd00000873sv00001043sd00001C52* + ID_MODEL_FROM_DATABASE=C79 [GeForce G102M] (GeForce G205M) + +pci:v000010DEd00000874* + ID_MODEL_FROM_DATABASE=C79 [ION] + +pci:v000010DEd00000876* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400M / ION] + +pci:v000010DEd0000087A* + ID_MODEL_FROM_DATABASE=C79 [GeForce 9400] + +pci:v000010DEd0000087D* + ID_MODEL_FROM_DATABASE=C79 [ION] + +pci:v000010DEd0000087Dsv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=C79 [ION] (IONITX-F-E) + +pci:v000010DEd0000087E* + ID_MODEL_FROM_DATABASE=C79 [ION LE] + +pci:v000010DEd0000087F* + ID_MODEL_FROM_DATABASE=C79 [ION LE] + +pci:v000010DEd000008A0* + ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M] + +pci:v000010DEd000008A2* + ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M] + +pci:v000010DEd000008A3* + ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M] + +pci:v000010DEd000008A4* + ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M] + +pci:v000010DEd000008A5* + ID_MODEL_FROM_DATABASE=MCP89 [GeForce 320M] + +pci:v000010DEd00000A20* + ID_MODEL_FROM_DATABASE=GT216 [GeForce GT 220] + +pci:v000010DEd00000A20sv00001043sd00008311* + ID_MODEL_FROM_DATABASE=GT216 [GeForce GT 220] (ENGT220/DI/1GD3(LP)/V2) + +pci:v000010DEd00000A21* + ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 330M] + +pci:v000010DEd00000A22* + ID_MODEL_FROM_DATABASE=GT216 [GeForce 315] + +pci:v000010DEd00000A23* + ID_MODEL_FROM_DATABASE=GT216 [GeForce 210] + +pci:v000010DEd00000A26* + ID_MODEL_FROM_DATABASE=GT216 [GeForce 405] + +pci:v000010DEd00000A27* + ID_MODEL_FROM_DATABASE=GT216 [GeForce 405] + +pci:v000010DEd00000A28* + ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 230M] + +pci:v000010DEd00000A29* + ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 330M] + +pci:v000010DEd00000A2A* + ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 230M] + +pci:v000010DEd00000A2B* + ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 330M] + +pci:v000010DEd00000A2C* + ID_MODEL_FROM_DATABASE=GT216M [NVS 5100M] + +pci:v000010DEd00000A2D* + ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 320M] + +pci:v000010DEd00000A30* + ID_MODEL_FROM_DATABASE=GT216 [GeForce 505] + +pci:v000010DEd00000A32* + ID_MODEL_FROM_DATABASE=GT216 [GeForce GT 415] + +pci:v000010DEd00000A34* + ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 240M] + +pci:v000010DEd00000A35* + ID_MODEL_FROM_DATABASE=GT216M [GeForce GT 325M] + +pci:v000010DEd00000A38* + ID_MODEL_FROM_DATABASE=GT216GL [Quadro 400] + +pci:v000010DEd00000A3C* + ID_MODEL_FROM_DATABASE=GT216GLM [Quadro FX 880M] + +pci:v000010DEd00000A60* + ID_MODEL_FROM_DATABASE=GT218 [GeForce G210] + +pci:v000010DEd00000A62* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 205] + +pci:v000010DEd00000A63* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 310] + +pci:v000010DEd00000A64* + ID_MODEL_FROM_DATABASE=GT218 [ION] + +pci:v000010DEd00000A65* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 210] + +pci:v000010DEd00000A65sv00001043sd00008334* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 210] (EN210 SILENT) + +pci:v000010DEd00000A65sv00001458sd000036A9* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 210] (GV-N210D3-1GI (rev. 6.0/6.1)) + +pci:v000010DEd00000A65sv00001462sd00008094* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 210] (N210 [Geforce 210] PCIe graphics adapter) + +pci:v000010DEd00000A66* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 310] + +pci:v000010DEd00000A67* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 315] + +pci:v000010DEd00000A68* + ID_MODEL_FROM_DATABASE=GT218M [GeForce G 105M] + +pci:v000010DEd00000A69* + ID_MODEL_FROM_DATABASE=GT218M [GeForce G 105M] + +pci:v000010DEd00000A6A* + ID_MODEL_FROM_DATABASE=GT218M [NVS 2100M] + +pci:v000010DEd00000A6C* + ID_MODEL_FROM_DATABASE=GT218M [NVS 3100M] + +pci:v000010DEd00000A6Csv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=GT218M [NVS 3100M] (Latitude E6510) + +pci:v000010DEd00000A6Csv000017AAsd00002142* + ID_MODEL_FROM_DATABASE=GT218M [NVS 3100M] (ThinkPad T410) + +pci:v000010DEd00000A6E* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 305M] + +pci:v000010DEd00000A6F* + ID_MODEL_FROM_DATABASE=GT218M [ION] + +pci:v000010DEd00000A70* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 310M] + +pci:v000010DEd00000A71* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 305M] + +pci:v000010DEd00000A72* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 310M] + +pci:v000010DEd00000A73* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 305M] + +pci:v000010DEd00000A74* + ID_MODEL_FROM_DATABASE=GT218M [GeForce G210M] + +pci:v000010DEd00000A74sv00001B0Asd0000903A* + ID_MODEL_FROM_DATABASE=GT218M [GeForce G210M] (GeForce G210) + +pci:v000010DEd00000A75* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 310M] + +pci:v000010DEd00000A76* + ID_MODEL_FROM_DATABASE=GT218M [ION 2] + +pci:v000010DEd00000A78* + ID_MODEL_FROM_DATABASE=GT218GL [Quadro FX 380 LP] + +pci:v000010DEd00000A7A* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] + +pci:v000010DEd00000A7Asv0000104Dsd0000907E* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FC50* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FC61* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FC71* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FC90* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FCC0* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FCD0* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FCE2* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FCF2* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FD16* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FD40* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FD50* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FD52* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FD61* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FD71* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FD92* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FD96* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FDD0* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FDD2* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001179sd0000FDFE* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv0000144Dsd0000C0A2* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv0000144Dsd0000C0B2* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv0000144Dsd0000C581* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv0000144Dsd0000C587* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv0000144Dsd0000C588* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv0000144Dsd0000C597* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv0000144Dsd0000C606* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001462sd0000AA51* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) + +pci:v000010DEd00000A7Asv00001462sd0000AA58* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) + +pci:v000010DEd00000A7Asv00001462sd0000AC71* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) + +pci:v000010DEd00000A7Asv00001462sd0000AC81* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001462sd0000AC82* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) + +pci:v000010DEd00000A7Asv00001462sd0000AE33* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) + +pci:v000010DEd00000A7Asv00001642sd00003980* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) + +pci:v000010DEd00000A7Asv000017AAsd00003950* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405M) + +pci:v000010DEd00000A7Asv000017AAsd0000397D* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405M) + +pci:v000010DEd00000A7Asv00001B0Asd00002091* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7Asv00001B0Asd000090B4* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) + +pci:v000010DEd00000A7Asv00001BFDsd00000003* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) + +pci:v000010DEd00000A7Asv00001BFDsd00008006* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 405) + +pci:v000010DEd00000A7Asv00001BFDsd00008007* + ID_MODEL_FROM_DATABASE=GT218M [GeForce 315M] (GeForce 315M) + +pci:v000010DEd00000A7B* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 505] + +pci:v000010DEd00000A7C* + ID_MODEL_FROM_DATABASE=GT218GLM [Quadro FX 380M] + +pci:v000010DEd00000A80* + ID_MODEL_FROM_DATABASE=MCP79 Host Bridge + +pci:v000010DEd00000A81* + ID_MODEL_FROM_DATABASE=MCP79 Host Bridge + +pci:v000010DEd00000A82* + ID_MODEL_FROM_DATABASE=MCP79 Host Bridge + +pci:v000010DEd00000A83* + ID_MODEL_FROM_DATABASE=MCP79 Host Bridge + +pci:v000010DEd00000A84* + ID_MODEL_FROM_DATABASE=MCP79 Host Bridge + +pci:v000010DEd00000A85* + ID_MODEL_FROM_DATABASE=MCP79 Host Bridge + +pci:v000010DEd00000A86* + ID_MODEL_FROM_DATABASE=MCP79 Host Bridge + +pci:v000010DEd00000A87* + ID_MODEL_FROM_DATABASE=MCP79 Host Bridge + +pci:v000010DEd00000A88* + ID_MODEL_FROM_DATABASE=MCP79 Memory Controller + +pci:v000010DEd00000A89* + ID_MODEL_FROM_DATABASE=MCP79 Memory Controller + +pci:v000010DEd00000A98* + ID_MODEL_FROM_DATABASE=MCP79 Memory Controller + +pci:v000010DEd00000A98sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 Memory Controller (iMac 9,1) + +pci:v000010DEd00000AA0* + ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge + +pci:v000010DEd00000AA0sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge (Apple iMac 9,1) + +pci:v000010DEd00000AA2* + ID_MODEL_FROM_DATABASE=MCP79 SMBus + +pci:v000010DEd00000AA2sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 SMBus (Apple iMac 9,1) + +pci:v000010DEd00000AA2sv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=MCP79 SMBus (IONITX-F-E) + +pci:v000010DEd00000AA3* + ID_MODEL_FROM_DATABASE=MCP79 Co-processor + +pci:v000010DEd00000AA3sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 Co-processor (Apple iMac 9,1) + +pci:v000010DEd00000AA3sv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=MCP79 Co-processor (IONITX-F-E) + +pci:v000010DEd00000AA4* + ID_MODEL_FROM_DATABASE=MCP79 Memory Controller + +pci:v000010DEd00000AA4sv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=MCP79 Memory Controller (IONITX-F-E) + +pci:v000010DEd00000AA5* + ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller + +pci:v000010DEd00000AA5sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller (Apple iMac 9,1) + +pci:v000010DEd00000AA5sv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller (IONITX-F-E) + +pci:v000010DEd00000AA6* + ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller + +pci:v000010DEd00000AA6sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller (Apple iMac 9,1) + +pci:v000010DEd00000AA6sv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller (IONITX-F-E) + +pci:v000010DEd00000AA7* + ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller + +pci:v000010DEd00000AA7sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller (Apple iMac 9,1) + +pci:v000010DEd00000AA7sv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller (IONITX-F-E) + +pci:v000010DEd00000AA8* + ID_MODEL_FROM_DATABASE=MCP79 OHCI USB 1.1 Controller + +pci:v000010DEd00000AA9* + ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller + +pci:v000010DEd00000AA9sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller (Apple iMac 9,1) + +pci:v000010DEd00000AA9sv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller (IONITX-F-E) + +pci:v000010DEd00000AAA* + ID_MODEL_FROM_DATABASE=MCP79 EHCI USB 2.0 Controller + +pci:v000010DEd00000AAB* + ID_MODEL_FROM_DATABASE=MCP79 PCI Bridge + +pci:v000010DEd00000AABsv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 PCI Bridge (Apple iMac 9,1) + +pci:v000010DEd00000AAC* + ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge + +pci:v000010DEd00000AAD* + ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge + +pci:v000010DEd00000AADsv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge (IONITX-F-E) + +pci:v000010DEd00000AAE* + ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge + +pci:v000010DEd00000AAEsv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge (Apple iMac 9,1) + +pci:v000010DEd00000AAF* + ID_MODEL_FROM_DATABASE=MCP79 LPC Bridge + +pci:v000010DEd00000AB0* + ID_MODEL_FROM_DATABASE=MCP79 Ethernet + +pci:v000010DEd00000AB0sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 Ethernet (Apple iMac 9,1) + +pci:v000010DEd00000AB0sv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=MCP79 Ethernet (IONITX-F-E) + +pci:v000010DEd00000AB1* + ID_MODEL_FROM_DATABASE=MCP79 Ethernet + +pci:v000010DEd00000AB2* + ID_MODEL_FROM_DATABASE=MCP79 Ethernet + +pci:v000010DEd00000AB3* + ID_MODEL_FROM_DATABASE=MCP79 Ethernet + +pci:v000010DEd00000AB4* + ID_MODEL_FROM_DATABASE=MCP79 SATA Controller + +pci:v000010DEd00000AB4sv000019DAsd0000A123* + ID_MODEL_FROM_DATABASE=MCP79 SATA Controller (IONITX-F-E) + +pci:v000010DEd00000AB5* + ID_MODEL_FROM_DATABASE=MCP79 SATA Controller + +pci:v000010DEd00000AB6* + ID_MODEL_FROM_DATABASE=MCP79 SATA Controller + +pci:v000010DEd00000AB7* + ID_MODEL_FROM_DATABASE=MCP79 SATA Controller + +pci:v000010DEd00000AB8* + ID_MODEL_FROM_DATABASE=MCP79 AHCI Controller + +pci:v000010DEd00000AB9* + ID_MODEL_FROM_DATABASE=MCP79 AHCI Controller + +pci:v000010DEd00000AB9sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 AHCI Controller (Apple iMac 9,1) + +pci:v000010DEd00000ABA* + ID_MODEL_FROM_DATABASE=MCP79 AHCI Controller + +pci:v000010DEd00000ABB* + ID_MODEL_FROM_DATABASE=MCP79 AHCI Controller + +pci:v000010DEd00000ABC* + ID_MODEL_FROM_DATABASE=MCP79 RAID Controller + +pci:v000010DEd00000ABD* + ID_MODEL_FROM_DATABASE=MCP79 RAID Controller + +pci:v000010DEd00000ABE* + ID_MODEL_FROM_DATABASE=MCP79 RAID Controller + +pci:v000010DEd00000ABF* + ID_MODEL_FROM_DATABASE=MCP79 RAID Controller + +pci:v000010DEd00000AC0* + ID_MODEL_FROM_DATABASE=MCP79 High Definition Audio + +pci:v000010DEd00000AC0sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 High Definition Audio (Apple iMac 9,1) + +pci:v000010DEd00000AC1* + ID_MODEL_FROM_DATABASE=MCP79 High Definition Audio + +pci:v000010DEd00000AC2* + ID_MODEL_FROM_DATABASE=MCP79 High Definition Audio + +pci:v000010DEd00000AC3* + ID_MODEL_FROM_DATABASE=MCP79 High Definition Audio + +pci:v000010DEd00000AC4* + ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge + +pci:v000010DEd00000AC4sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge (Apple iMac 9,1) + +pci:v000010DEd00000AC5* + ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge + +pci:v000010DEd00000AC6* + ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge + +pci:v000010DEd00000AC6sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge (Apple iMac 9,1) + +pci:v000010DEd00000AC7* + ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge + +pci:v000010DEd00000AC7sv000010DEsd0000CB79* + ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge (Apple iMac 9,1) + +pci:v000010DEd00000AC8* + ID_MODEL_FROM_DATABASE=MCP79 PCI Express Bridge + +pci:v000010DEd00000AD0* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SATA Controller (non-AHCI mode) + +pci:v000010DEd00000AD0sv00001462sd00007508* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SATA Controller (non-AHCI mode) (K9N2GM-FIH) + +pci:v000010DEd00000AD0sv00001849sd00000AD0* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SATA Controller (non-AHCI mode) (K10N78FullHD-hSLI R3.0 IDE) + +pci:v000010DEd00000AD4* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] AHCI Controller + +pci:v000010DEd00000AD4sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] AHCI Controller (Pavilion p6310f) + +pci:v000010DEd00000AD4sv00001043sd000082E8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] AHCI Controller (M3N72-D) + +pci:v000010DEd00000AD4sv00001849sd00000AD4* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] AHCI Controller (K10N78FullHD-hSLI R3.0 AHCI Controller) + +pci:v000010DEd00000AD8* + ID_MODEL_FROM_DATABASE=MCP78S [GeForce 8200] SATA Controller (RAID mode) + +pci:v000010DEd00000BE2* + ID_MODEL_FROM_DATABASE=GT216 HDMI Audio Controller + +pci:v000010DEd00000BE2sv00001043sd00008311* + ID_MODEL_FROM_DATABASE=GT216 HDMI Audio Controller (ENGT220/DI/1GD3(LP)/V2) + +pci:v000010DEd00000BE3* + ID_MODEL_FROM_DATABASE=High Definition Audio Controller + +pci:v000010DEd00000BE3sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=High Definition Audio Controller (Latitude E6510) + +pci:v000010DEd00000BE3sv000010DEsd0000066D* + ID_MODEL_FROM_DATABASE=High Definition Audio Controller (G98 [GeForce 8400GS]) + +pci:v000010DEd00000BE3sv00001462sd00008094* + ID_MODEL_FROM_DATABASE=High Definition Audio Controller (N210 [Geforce 210] PCIe graphics adapter) + +pci:v000010DEd00000BE4* + ID_MODEL_FROM_DATABASE=High Definition Audio Controller + +pci:v000010DEd00000BE5* + ID_MODEL_FROM_DATABASE=GF100 High Definition Audio Controller + +pci:v000010DEd00000BE9* + ID_MODEL_FROM_DATABASE=GF106 High Definition Audio Controller + +pci:v000010DEd00000BE9sv00001558sd00008687* + ID_MODEL_FROM_DATABASE=GF106 High Definition Audio Controller (CLEVO/KAPOK W860CU) + +pci:v000010DEd00000BE9sv00003842sd00001452* + ID_MODEL_FROM_DATABASE=GF106 High Definition Audio Controller (GeForce GTS 450) + +pci:v000010DEd00000BEA* + ID_MODEL_FROM_DATABASE=GF108 High Definition Audio Controller + +pci:v000010DEd00000BEAsv00003842sd00001430* + ID_MODEL_FROM_DATABASE=GF108 High Definition Audio Controller (GeForce GT 430) + +pci:v000010DEd00000BEB* + ID_MODEL_FROM_DATABASE=GF104 High Definition Audio Controller + +pci:v000010DEd00000BEBsv00001462sd00002322* + ID_MODEL_FROM_DATABASE=GF104 High Definition Audio Controller (N460GTX Cyclone 1GD5/OC) + +pci:v000010DEd00000BEE* + ID_MODEL_FROM_DATABASE=GF116 High Definition Audio Controller + +pci:v000010DEd00000BF0* + ID_MODEL_FROM_DATABASE=Tegra2 PCIe x4 Bridge + +pci:v000010DEd00000BF1* + ID_MODEL_FROM_DATABASE=Tegra2 PCIe x2 Bridge + +pci:v000010DEd00000CA0* + ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 330] + +pci:v000010DEd00000CA2* + ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 320] + +pci:v000010DEd00000CA3* + ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 240] + +pci:v000010DEd00000CA4* + ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 340] + +pci:v000010DEd00000CA5* + ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 220] + +pci:v000010DEd00000CA7* + ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 330] + +pci:v000010DEd00000CA8* + ID_MODEL_FROM_DATABASE=GT215M [GeForce GTS 260M] + +pci:v000010DEd00000CA9* + ID_MODEL_FROM_DATABASE=GT215M [GeForce GTS 250M] + +pci:v000010DEd00000CAC* + ID_MODEL_FROM_DATABASE=GT215 [GeForce GT 220/315] + +pci:v000010DEd00000CAF* + ID_MODEL_FROM_DATABASE=GT215M [GeForce GT 335M] + +pci:v000010DEd00000CB0* + ID_MODEL_FROM_DATABASE=GT215M [GeForce GTS 350M] + +pci:v000010DEd00000CB1* + ID_MODEL_FROM_DATABASE=GT215M [GeForce GTS 360M] + +pci:v000010DEd00000CBC* + ID_MODEL_FROM_DATABASE=GT215GLM [Quadro FX 1800M] + +pci:v000010DEd00000D60* + ID_MODEL_FROM_DATABASE=MCP89 HOST Bridge + +pci:v000010DEd00000D68* + ID_MODEL_FROM_DATABASE=MCP89 Memory Controller + +pci:v000010DEd00000D69* + ID_MODEL_FROM_DATABASE=MCP89 Memory Controller + +pci:v000010DEd00000D76* + ID_MODEL_FROM_DATABASE=MCP89 PCI Express Bridge + +pci:v000010DEd00000D79* + ID_MODEL_FROM_DATABASE=MCP89 SMBus + +pci:v000010DEd00000D7A* + ID_MODEL_FROM_DATABASE=MCP89 Co-Processor + +pci:v000010DEd00000D7B* + ID_MODEL_FROM_DATABASE=MCP89 Memory Controller + +pci:v000010DEd00000D7D* + ID_MODEL_FROM_DATABASE=MCP89 Ethernet + +pci:v000010DEd00000D80* + ID_MODEL_FROM_DATABASE=MCP89 LPC Bridge + +pci:v000010DEd00000D85* + ID_MODEL_FROM_DATABASE=MCP89 SATA Controller + +pci:v000010DEd00000D88* + ID_MODEL_FROM_DATABASE=MCP89 SATA Controller (AHCI mode) + +pci:v000010DEd00000D89* + ID_MODEL_FROM_DATABASE=MCP89 SATA Controller (AHCI mode) + +pci:v000010DEd00000D8D* + ID_MODEL_FROM_DATABASE=MCP89 SATA Controller (RAID mode) + +pci:v000010DEd00000D94* + ID_MODEL_FROM_DATABASE=MCP89 High Definition Audio + +pci:v000010DEd00000D9C* + ID_MODEL_FROM_DATABASE=MCP89 OHCI USB 1.1 Controller + +pci:v000010DEd00000D9D* + ID_MODEL_FROM_DATABASE=MCP89 EHCI USB 2.0 Controller + +pci:v000010DEd00000DC0* + ID_MODEL_FROM_DATABASE=GF106 [GeForce GT 440] + +pci:v000010DEd00000DC4* + ID_MODEL_FROM_DATABASE=GF106 [GeForce GTS 450] + +pci:v000010DEd00000DC5* + ID_MODEL_FROM_DATABASE=GF106 [GeForce GTS 450 OEM] + +pci:v000010DEd00000DC6* + ID_MODEL_FROM_DATABASE=GF106 [GeForce GTS 450 OEM] + +pci:v000010DEd00000DCD* + ID_MODEL_FROM_DATABASE=GF106M [GeForce GT 555M] + +pci:v000010DEd00000DCE* + ID_MODEL_FROM_DATABASE=GF106M [GeForce GT 555M] + +pci:v000010DEd00000DD1* + ID_MODEL_FROM_DATABASE=GF106M [GeForce GTX 460M] + +pci:v000010DEd00000DD1sv00001558sd00008687* + ID_MODEL_FROM_DATABASE=GF106M [GeForce GTX 460M] (CLEVO/KAPOK W860CU) + +pci:v000010DEd00000DD2* + ID_MODEL_FROM_DATABASE=GF106M [GeForce GT 445M] + +pci:v000010DEd00000DD3* + ID_MODEL_FROM_DATABASE=GF106M [GeForce GT 435M] + +pci:v000010DEd00000DD6* + ID_MODEL_FROM_DATABASE=GF106M [GeForce GT 550M] + +pci:v000010DEd00000DD8* + ID_MODEL_FROM_DATABASE=GF106GL [Quadro 2000] + +pci:v000010DEd00000DD8sv000010DEsd00000914* + ID_MODEL_FROM_DATABASE=GF106GL [Quadro 2000] (Quadro 2000D) + +pci:v000010DEd00000DDA* + ID_MODEL_FROM_DATABASE=GF106GLM [Quadro 2000M] + +pci:v000010DEd00000DE0* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 440] + +pci:v000010DEd00000DE1* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 430] + +pci:v000010DEd00000DE1sv00003842sd00001430* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 430] (GeForce GT 430) + +pci:v000010DEd00000DE2* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 420] + +pci:v000010DEd00000DE3* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 635M] + +pci:v000010DEd00000DE4* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 520] + +pci:v000010DEd00000DE5* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 530] + +pci:v000010DEd00000DE7* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 610] + +pci:v000010DEd00000DE8* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M] + +pci:v000010DEd00000DE9* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M/630M/635M/640M LE] + +pci:v000010DEd00000DE9sv00001025sd00000692* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M/630M/635M/640M LE] (GeForce GT 620M) + +pci:v000010DEd00000DE9sv00001025sd00000725* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M/630M/635M/640M LE] (GeForce GT 620M) + +pci:v000010DEd00000DE9sv00001025sd00000728* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M/630M/635M/640M LE] (GeForce GT 620M) + +pci:v000010DEd00000DE9sv00001025sd0000072B* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M/630M/635M/640M LE] (GeForce GT 620M) + +pci:v000010DEd00000DE9sv00001025sd0000072E* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M/630M/635M/640M LE] (GeForce GT 620M) + +pci:v000010DEd00000DE9sv00001025sd00000753* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M/630M/635M/640M LE] (GeForce GT 620M) + +pci:v000010DEd00000DE9sv00001025sd00000754* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M/630M/635M/640M LE] (GeForce GT 620M) + +pci:v000010DEd00000DE9sv000017AAsd00003977* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M/630M/635M/640M LE] (GeForce GT 640M LE) + +pci:v000010DEd00000DE9sv00001B0Asd00002210* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 620M/630M/635M/640M LE] (GeForce GT 635M) + +pci:v000010DEd00000DEA* + ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] + +pci:v000010DEd00000DEAsv000017AAsd0000365A* + ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] (GeForce 615) + +pci:v000010DEd00000DEAsv000017AAsd0000365B* + ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] (GeForce 615) + +pci:v000010DEd00000DEAsv000017AAsd0000365E* + ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] (GeForce 615) + +pci:v000010DEd00000DEAsv000017AAsd00003660* + ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] (GeForce 615) + +pci:v000010DEd00000DEAsv000017AAsd0000366C* + ID_MODEL_FROM_DATABASE=GF108M [GeForce 610M] (GeForce 615) + +pci:v000010DEd00000DEB* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 555M] + +pci:v000010DEd00000DEC* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 525M] + +pci:v000010DEd00000DED* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 520M] + +pci:v000010DEd00000DEE* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 415M] + +pci:v000010DEd00000DEF* + ID_MODEL_FROM_DATABASE=GF108M [NVS 5400M] + +pci:v000010DEd00000DF0* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 425M] + +pci:v000010DEd00000DF1* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 420M] + +pci:v000010DEd00000DF2* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 435M] + +pci:v000010DEd00000DF3* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 420M] + +pci:v000010DEd00000DF4* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 540M] + +pci:v000010DEd00000DF4sv0000152Dsd00000952* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 540M] (GeForce GT 630M) + +pci:v000010DEd00000DF4sv0000152Dsd00000953* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 540M] (GeForce GT 630M) + +pci:v000010DEd00000DF5* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 525M] + +pci:v000010DEd00000DF6* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 550M] + +pci:v000010DEd00000DF7* + ID_MODEL_FROM_DATABASE=GF108M [GeForce GT 520M] + +pci:v000010DEd00000DF8* + ID_MODEL_FROM_DATABASE=GF108GL [Quadro 600] + +pci:v000010DEd00000DF9* + ID_MODEL_FROM_DATABASE=GF108GLM [Quadro 500M] + +pci:v000010DEd00000DFA* + ID_MODEL_FROM_DATABASE=GF108GLM [Quadro 1000M] + +pci:v000010DEd00000DFC* + ID_MODEL_FROM_DATABASE=GF108GLM [NVS 5200M] + +pci:v000010DEd00000E08* + ID_MODEL_FROM_DATABASE=GF119 HDMI Audio Controller + +pci:v000010DEd00000E08sv00001043sd000083A0* + ID_MODEL_FROM_DATABASE=GF119 HDMI Audio Controller (ENGT520 SILENT) + +pci:v000010DEd00000E08sv000010B0sd0000104A* + ID_MODEL_FROM_DATABASE=GF119 HDMI Audio Controller (Gainward GeForce GT 610) + +pci:v000010DEd00000E09* + ID_MODEL_FROM_DATABASE=GF110 High Definition Audio Controller + +pci:v000010DEd00000E0A* + ID_MODEL_FROM_DATABASE=GK104 HDMI Audio Controller + +pci:v000010DEd00000E0B* + ID_MODEL_FROM_DATABASE=GK106 HDMI Audio Controller + +pci:v000010DEd00000E0C* + ID_MODEL_FROM_DATABASE=GF114 HDMI Audio Controller + +pci:v000010DEd00000E0F* + ID_MODEL_FROM_DATABASE=GK208 HDMI/DP Audio Controller + +pci:v000010DEd00000E12* + ID_MODEL_FROM_DATABASE=TegraK1 PCIe x4 Bridge + +pci:v000010DEd00000E13* + ID_MODEL_FROM_DATABASE=TegraK1 PCIe x1 Bridge + +pci:v000010DEd00000E1A* + ID_MODEL_FROM_DATABASE=GK110 High Definition Audio Controller + +pci:v000010DEd00000E1B* + ID_MODEL_FROM_DATABASE=GK107 HDMI Audio Controller + +pci:v000010DEd00000E1Bsv0000103Csd0000197B* + ID_MODEL_FROM_DATABASE=GK107 HDMI Audio Controller (ZBook 15) + +pci:v000010DEd00000E1Bsv00001043sd00008428* + ID_MODEL_FROM_DATABASE=GK107 HDMI Audio Controller (GTX650-DC-1GD5) + +pci:v000010DEd00000E1C* + ID_MODEL_FROM_DATABASE=Tegra3+ PCIe x4 Bridge + +pci:v000010DEd00000E1D* + ID_MODEL_FROM_DATABASE=Tegra3+ PCIe x2 Bridge + +pci:v000010DEd00000E22* + ID_MODEL_FROM_DATABASE=GF104 [GeForce GTX 460] + +pci:v000010DEd00000E22sv00001462sd00002322* + ID_MODEL_FROM_DATABASE=GF104 [GeForce GTX 460] (N460GTX Cyclone 1GD5/OC) + +pci:v000010DEd00000E23* + ID_MODEL_FROM_DATABASE=GF104 [GeForce GTX 460 SE] + +pci:v000010DEd00000E24* + ID_MODEL_FROM_DATABASE=GF104 [GeForce GTX 460 OEM] + +pci:v000010DEd00000E30* + ID_MODEL_FROM_DATABASE=GF104M [GeForce GTX 470M] + +pci:v000010DEd00000E31* + ID_MODEL_FROM_DATABASE=GF104M [GeForce GTX 485M] + +pci:v000010DEd00000E3A* + ID_MODEL_FROM_DATABASE=GF104GLM [Quadro 3000M] + +pci:v000010DEd00000E3B* + ID_MODEL_FROM_DATABASE=GF104GLM [Quadro 4000M] + +pci:v000010DEd00000F00* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 630] + +pci:v000010DEd00000F01* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 620] + +pci:v000010DEd00000F02* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 730] + +pci:v000010DEd00000F03* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 610] + +pci:v000010DEd00000F06* + ID_MODEL_FROM_DATABASE=GF108 [GeForce GT 730] + +pci:v000010DEd00000FB0* + ID_MODEL_FROM_DATABASE=GM200 High Definition Audio + +pci:v000010DEd00000FB8* + ID_MODEL_FROM_DATABASE=GP108 High Definition Audio Controller + +pci:v000010DEd00000FB9* + ID_MODEL_FROM_DATABASE=GP107GL High Definition Audio Controller + +pci:v000010DEd00000FBA* + ID_MODEL_FROM_DATABASE=GM206 High Definition Audio Controller + +pci:v000010DEd00000FBB* + ID_MODEL_FROM_DATABASE=GM204 High Definition Audio Controller + +pci:v000010DEd00000FC0* + ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 640 OEM] + +pci:v000010DEd00000FC1* + ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 640] + +pci:v000010DEd00000FC2* + ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 630 OEM] + +pci:v000010DEd00000FC5* + ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 1030] + +pci:v000010DEd00000FC6* + ID_MODEL_FROM_DATABASE=GK107 [GeForce GTX 650] + +pci:v000010DEd00000FC6sv00001043sd00008428* + ID_MODEL_FROM_DATABASE=GK107 [GeForce GTX 650] (GTX650-DC-1GD5) + +pci:v000010DEd00000FC8* + ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 740] + +pci:v000010DEd00000FC9* + ID_MODEL_FROM_DATABASE=GK107 [GeForce GT 730] + +pci:v000010DEd00000FCD* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 755M] + +pci:v000010DEd00000FCE* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M LE] + +pci:v000010DEd00000FD1* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] + +pci:v000010DEd00000FD1sv00001043sd00001597* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] (GeForce GT 650M) + +pci:v000010DEd00000FD1sv00001043sd000015A7* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] (GeForce GT 650M) + +pci:v000010DEd00000FD1sv00001043sd00002103* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] (N56VZ) + +pci:v000010DEd00000FD1sv00001043sd00002105* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] (GeForce GT 650M) + +pci:v000010DEd00000FD1sv00001043sd00002141* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M] (GeForce GT 650M) + +pci:v000010DEd00000FD2* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M] + +pci:v000010DEd00000FD2sv00001028sd0000054F* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M] (GeForce GT 640M) + +pci:v000010DEd00000FD2sv00001028sd0000055F* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M] (GeForce GT 640M) + +pci:v000010DEd00000FD2sv00001028sd00000595* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M] (GeForce GT 640M LE) + +pci:v000010DEd00000FD2sv00001028sd000005B2* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M] (GeForce GT 640M LE) + +pci:v000010DEd00000FD3* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M LE] + +pci:v000010DEd00000FD4* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GTX 660M] + +pci:v000010DEd00000FD5* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 650M Mac Edition] + +pci:v000010DEd00000FD8* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 640M Mac Edition] + +pci:v000010DEd00000FD9* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 645M] + +pci:v000010DEd00000FDB* + ID_MODEL_FROM_DATABASE=GK107M + +pci:v000010DEd00000FDF* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 740M] + +pci:v000010DEd00000FE0* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GTX 660M Mac Edition] + +pci:v000010DEd00000FE1* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 730M] + +pci:v000010DEd00000FE2* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 745M] + +pci:v000010DEd00000FE3* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 745M] + +pci:v000010DEd00000FE3sv0000103Csd00002B16* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 745M] (GeForce GT 745A) + +pci:v000010DEd00000FE3sv000017AAsd00003675* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 745M] (GeForce GT 745A) + +pci:v000010DEd00000FE4* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 750M] + +pci:v000010DEd00000FE5* + ID_MODEL_FROM_DATABASE=GK107 [GeForce K340 USM] + +pci:v000010DEd00000FE6* + ID_MODEL_FROM_DATABASE=GK107 [GRID K1 NVS USM] + +pci:v000010DEd00000FE7* + ID_MODEL_FROM_DATABASE=GK107GL [GRID K100 vGPU] + +pci:v000010DEd00000FE7sv000010DEsd0000101E* + ID_MODEL_FROM_DATABASE=GK107GL [GRID K100 vGPU] (GRID K100) + +pci:v000010DEd00000FE9* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 750M Mac Edition] + +pci:v000010DEd00000FEA* + ID_MODEL_FROM_DATABASE=GK107M [GeForce GT 755M Mac Edition] + +pci:v000010DEd00000FEC* + ID_MODEL_FROM_DATABASE=GK107M [GeForce 710A] + +pci:v000010DEd00000FED* + ID_MODEL_FROM_DATABASE=GK107M [GeForce 820M] + +pci:v000010DEd00000FEE* + ID_MODEL_FROM_DATABASE=GK107M [GeForce 810M] + +pci:v000010DEd00000FEF* + ID_MODEL_FROM_DATABASE=GK107GL [GRID K340] + +pci:v000010DEd00000FF1* + ID_MODEL_FROM_DATABASE=GK107 [NVS 1000] + +pci:v000010DEd00000FF2* + ID_MODEL_FROM_DATABASE=GK107GL [GRID K1] + +pci:v000010DEd00000FF3* + ID_MODEL_FROM_DATABASE=GK107GL [Quadro K420] + +pci:v000010DEd00000FF5* + ID_MODEL_FROM_DATABASE=GK107GL [GRID K1 Tesla USM] + +pci:v000010DEd00000FF6* + ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K1100M] + +pci:v000010DEd00000FF6sv0000103Csd0000197B* + ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K1100M] (ZBook 15) + +pci:v000010DEd00000FF7* + ID_MODEL_FROM_DATABASE=GK107GL [GRID K140Q vGPU] + +pci:v000010DEd00000FF7sv000010DEsd00001037* + ID_MODEL_FROM_DATABASE=GK107GL [GRID K140Q vGPU] (GRID K140Q) + +pci:v000010DEd00000FF8* + ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K500M] + +pci:v000010DEd00000FF9* + ID_MODEL_FROM_DATABASE=GK107GL [Quadro K2000D] + +pci:v000010DEd00000FFA* + ID_MODEL_FROM_DATABASE=GK107GL [Quadro K600] + +pci:v000010DEd00000FFB* + ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K2000M] + +pci:v000010DEd00000FFC* + ID_MODEL_FROM_DATABASE=GK107GLM [Quadro K1000M] + +pci:v000010DEd00000FFD* + ID_MODEL_FROM_DATABASE=GK107 [NVS 510] + +pci:v000010DEd00000FFE* + ID_MODEL_FROM_DATABASE=GK107GL [Quadro K2000] + +pci:v000010DEd00000FFF* + ID_MODEL_FROM_DATABASE=GK107GL [Quadro 410] + +pci:v000010DEd00001001* + ID_MODEL_FROM_DATABASE=GK110B [GeForce GTX TITAN Z] + +pci:v000010DEd00001003* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX Titan LE] + +pci:v000010DEd00001004* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780] + +pci:v000010DEd00001004sv00003842sd00000784* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780] (GK110B [GeForce GTX 780 SC w/ ACX Cooler]) + +pci:v000010DEd00001004sv00003842sd00001784* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780] (GK110B [GeForce GTX 780 Dual FTW w/ ACX Cooler]) + +pci:v000010DEd00001004sv00003842sd00001788* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780] (GK110B [GeForce GTX 780 Dual Classified w/ ACX Cooler]) + +pci:v000010DEd00001005* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] + +pci:v000010DEd00001005sv00001043sd00008451* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GTXTITAN-6GD5) + +pci:v000010DEd00001005sv000010DEsd00001035* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan) + +pci:v000010DEd00001005sv00003842sd00002790* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan) + +pci:v000010DEd00001005sv00003842sd00002791* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan SC) + +pci:v000010DEd00001005sv00003842sd00002793* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan SC Signature) + +pci:v000010DEd00001005sv00003842sd00002794* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan SC Hydro Copper) + +pci:v000010DEd00001005sv00003842sd00002795* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX TITAN] (GeForce GTX Titan SC Hydro Copper Signature) + +pci:v000010DEd00001007* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780 Rev. 2] + +pci:v000010DEd00001008* + ID_MODEL_FROM_DATABASE=GK110 [GeForce GTX 780 Ti 6GB] + +pci:v000010DEd0000100A* + ID_MODEL_FROM_DATABASE=GK110B [GeForce GTX 780 Ti] + +pci:v000010DEd0000100C* + ID_MODEL_FROM_DATABASE=GK110B [GeForce GTX TITAN Black] + +pci:v000010DEd0000101E* + ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20X] + +pci:v000010DEd0000101F* + ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20] + +pci:v000010DEd00001020* + ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20X] + +pci:v000010DEd00001021* + ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20Xm] + +pci:v000010DEd00001022* + ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20c] + +pci:v000010DEd00001023* + ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40m] + +pci:v000010DEd00001023sv000010DEsd0000097E* + ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40m] (12GB Computational Accelerator) + +pci:v000010DEd00001024* + ID_MODEL_FROM_DATABASE=GK180GL [Tesla K40c] + +pci:v000010DEd00001026* + ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20s] + +pci:v000010DEd00001027* + ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40st] + +pci:v000010DEd00001028* + ID_MODEL_FROM_DATABASE=GK110GL [Tesla K20m] + +pci:v000010DEd00001029* + ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40s] + +pci:v000010DEd0000102A* + ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40t] + +pci:v000010DEd0000102D* + ID_MODEL_FROM_DATABASE=GK210GL [Tesla K80] + +pci:v000010DEd0000102E* + ID_MODEL_FROM_DATABASE=GK110BGL [Tesla K40d] + +pci:v000010DEd0000102F* + ID_MODEL_FROM_DATABASE=GK110BGL [Tesla Stella Solo] + +pci:v000010DEd0000103A* + ID_MODEL_FROM_DATABASE=GK110GL [Quadro K6000] + +pci:v000010DEd0000103C* + ID_MODEL_FROM_DATABASE=GK110GL [Quadro K5200] + +pci:v000010DEd0000103F* + ID_MODEL_FROM_DATABASE=GK110BGL [Tesla Stella SXM] + +pci:v000010DEd00001040* + ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 520] + +pci:v000010DEd00001040sv00001043sd000083A0* + ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 520] (ENGT520 SILENT) + +pci:v000010DEd00001042* + ID_MODEL_FROM_DATABASE=GF119 [GeForce 510] + +pci:v000010DEd00001045* + ID_MODEL_FROM_DATABASE=GF119 + +pci:v000010DEd00001048* + ID_MODEL_FROM_DATABASE=GF119 [GeForce 605] + +pci:v000010DEd00001049* + ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 620 OEM] + +pci:v000010DEd0000104A* + ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 610] + +pci:v000010DEd0000104Asv000010B0sd0000104A* + ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 610] (Gainward GeForce GT 610) + +pci:v000010DEd0000104B* + ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 625 OEM] + +pci:v000010DEd0000104C* + ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 705] + +pci:v000010DEd0000104D* + ID_MODEL_FROM_DATABASE=GF119 [GeForce GT 710] + +pci:v000010DEd00001050* + ID_MODEL_FROM_DATABASE=GF119M [GeForce GT 520M] + +pci:v000010DEd00001051* + ID_MODEL_FROM_DATABASE=GF119M [GeForce GT 520MX] + +pci:v000010DEd00001052* + ID_MODEL_FROM_DATABASE=GF119M [GeForce GT 520M] + +pci:v000010DEd00001054* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 410M] + +pci:v000010DEd00001055* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 410M] + +pci:v000010DEd00001056* + ID_MODEL_FROM_DATABASE=GF119M [NVS 4200M] + +pci:v000010DEd00001057* + ID_MODEL_FROM_DATABASE=GF119M [Quadro NVS 4200M] + +pci:v000010DEd00001058* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] + +pci:v000010DEd00001058sv0000103Csd00002AED* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 610) + +pci:v000010DEd00001058sv0000103Csd00002AF1* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 610) + +pci:v000010DEd00001058sv00001043sd000010AC* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce GT 610M) + +pci:v000010DEd00001058sv00001043sd000010BC* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce GT 610M) + +pci:v000010DEd00001058sv00001043sd00001652* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce GT 610M) + +pci:v000010DEd00001058sv000017AAsd0000367A* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 610M) + +pci:v000010DEd00001058sv000017AAsd00003682* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 800A) + +pci:v000010DEd00001058sv000017AAsd00003687* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 800A) + +pci:v000010DEd00001058sv000017AAsd00003692* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 705A) + +pci:v000010DEd00001058sv000017AAsd00003695* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 800A) + +pci:v000010DEd00001058sv000017AAsd0000A117* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce 610M) + +pci:v000010DEd00001059* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] + +pci:v000010DEd0000105A* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] + +pci:v000010DEd0000105Asv00001043sd00002111* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce GT 610M) + +pci:v000010DEd0000105Asv00001043sd00002112* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 610M] (GeForce GT 610M) + +pci:v000010DEd0000105B* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] + +pci:v000010DEd0000105Bsv0000103Csd00002AFB* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] (GeForce 705A) + +pci:v000010DEd0000105Bsv000017AAsd0000309D* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] (GeForce 705A) + +pci:v000010DEd0000105Bsv000017AAsd000030B1* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] (GeForce 800A) + +pci:v000010DEd0000105Bsv000017AAsd000030F3* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] (GeForce 705A) + +pci:v000010DEd0000105Bsv000017AAsd000036A1* + ID_MODEL_FROM_DATABASE=GF119M [GeForce 705M] (GeForce 800A) + +pci:v000010DEd0000107C* + ID_MODEL_FROM_DATABASE=GF119 [NVS 315] + +pci:v000010DEd0000107D* + ID_MODEL_FROM_DATABASE=GF119 [NVS 310] + +pci:v000010DEd00001080* + ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 580] + +pci:v000010DEd00001081* + ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 570] + +pci:v000010DEd00001081sv000010DEsd0000087E* + ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 570] (Leadtek WinFast GTX 570) + +pci:v000010DEd00001082* + ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 560 Ti OEM] + +pci:v000010DEd00001084* + ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 560 OEM] + +pci:v000010DEd00001086* + ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 570 Rev. 2] + +pci:v000010DEd00001087* + ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 560 Ti 448 Cores] + +pci:v000010DEd00001088* + ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 590] + +pci:v000010DEd00001089* + ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 580 Rev. 2] + +pci:v000010DEd0000108B* + ID_MODEL_FROM_DATABASE=GF110 [GeForce GTX 580] + +pci:v000010DEd0000108E* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla C2090] + +pci:v000010DEd00001091* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2090] + +pci:v000010DEd00001091sv000010DEsd0000088E* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2090] (Tesla X2090) + +pci:v000010DEd00001091sv000010DEsd00000891* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2090] (Tesla X2090) + +pci:v000010DEd00001091sv000010DEsd00000974* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2090] (Tesla X2090) + +pci:v000010DEd00001091sv000010DEsd0000098D* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2090] (Tesla X2090) + +pci:v000010DEd00001094* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2075] + +pci:v000010DEd00001094sv000010DEsd00000888* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla M2075] (Tesla M2075) + +pci:v000010DEd00001096* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla C2050 / C2075] + +pci:v000010DEd00001096sv000010DEsd00000910* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla C2050 / C2075] (Tesla C2075) + +pci:v000010DEd00001096sv000010DEsd00000911* + ID_MODEL_FROM_DATABASE=GF110GL [Tesla C2050 / C2075] (Tesla C2050) + +pci:v000010DEd0000109A* + ID_MODEL_FROM_DATABASE=GF100GLM [Quadro 5010M] + +pci:v000010DEd0000109B* + ID_MODEL_FROM_DATABASE=GF100GL [Quadro 7000] + +pci:v000010DEd0000109Bsv000010DEsd00000918* + ID_MODEL_FROM_DATABASE=GF100GL [Quadro 7000] (Quadro 7000) + +pci:v000010DEd000010C0* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 9300 GS Rev. 2] + +pci:v000010DEd000010C3* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 8400 GS Rev. 3] + +pci:v000010DEd000010C5* + ID_MODEL_FROM_DATABASE=GT218 [GeForce 405] + +pci:v000010DEd000010D8* + ID_MODEL_FROM_DATABASE=GT218 [NVS 300] + +pci:v000010DEd000010EF* + ID_MODEL_FROM_DATABASE=GP102 HDMI Audio Controller + +pci:v000010DEd000010F0* + ID_MODEL_FROM_DATABASE=GP104 High Definition Audio Controller + +pci:v000010DEd000010F1* + ID_MODEL_FROM_DATABASE=GP106 High Definition Audio Controller + +pci:v000010DEd000010F7* + ID_MODEL_FROM_DATABASE=TU102 High Definition Audio Controller + +pci:v000010DEd000010F8* + ID_MODEL_FROM_DATABASE=TU104 HD Audio Controller + +pci:v000010DEd000010F9* + ID_MODEL_FROM_DATABASE=TU106 High Definition Audio Controller + +pci:v000010DEd000010F9sv00001043sd00008673* + ID_MODEL_FROM_DATABASE=TU106 High Definition Audio Controller (TURBO-RTX2070-8G) + +pci:v000010DEd00001140* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] + +pci:v000010DEd00001140sv00001019sd00000799* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001019sd0000999F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd00000600* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd00000606* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd0000064A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd0000064C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd0000067A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd00000680* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd00000686* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd00000689* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd0000068B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd0000068D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd0000068E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd00000691* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd00000692* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd00000694* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd00000702* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd00000719* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd00000725* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd00000728* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd0000072B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd0000072E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd00000732* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001025sd00000763* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd00000773* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd00000774* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd00000776* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd0000077A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd0000077B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd0000077C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd0000077D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd0000077E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd0000077F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd00000781* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd00000798* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd00000799* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd0000079B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd0000079C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd00000807* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd00000821* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd00000823* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd00000830* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd00000833* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd00000837* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001025sd0000083E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000841* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001025sd00000854* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000855* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000856* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000857* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000858* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000863* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000868* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000869* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 810M) + +pci:v000010DEd00001140sv00001025sd00000873* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000878* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd0000087B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd0000087C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 810M) + +pci:v000010DEd00001140sv00001025sd00000881* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd0000088A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd0000089B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd0000090F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000921* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd0000092E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 810M) + +pci:v000010DEd00001140sv00001025sd0000092F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000932* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd0000093A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd0000093C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd0000093F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000941* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000945* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000954* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001025sd00000965* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd0000054D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv00001028sd0000054E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv00001028sd00000554* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001028sd00000557* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001028sd00000562* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) + +pci:v000010DEd00001140sv00001028sd00000565* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv00001028sd00000568* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv00001028sd00000590* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv00001028sd00000592* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) + +pci:v000010DEd00001140sv00001028sd00000594* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) + +pci:v000010DEd00001140sv00001028sd00000595* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) + +pci:v000010DEd00001140sv00001028sd000005A2* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) + +pci:v000010DEd00001140sv00001028sd000005B1* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) + +pci:v000010DEd00001140sv00001028sd000005B3* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 625M) + +pci:v000010DEd00001140sv00001028sd000005DA* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv00001028sd000005DE* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001028sd000005E0* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001028sd000005E8* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv00001028sd000005F4* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001028sd0000060F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001028sd0000064E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd00000652* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd00000653* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd00000655* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd0000065E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd00000662* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd0000068D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd000006AD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd000006AE* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd000006AF* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd000006B0* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd000006C0* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001028sd000006C1* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd000018EF* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv0000103Csd000018F9* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv0000103Csd000018FB* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv0000103Csd000018FD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv0000103Csd000018FF* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv0000103Csd0000218A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd000021BB* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd000021BC* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd0000220E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd00002210* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd00002212* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd00002214* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd00002218* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd0000225B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd0000225D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd0000226D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd0000226F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd000022D2* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd000022D9* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd00002335* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd00002337* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000103Csd00002AEF* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720A) + +pci:v000010DEd00001140sv0000103Csd00002AF9* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710A) + +pci:v000010DEd00001140sv00001043sd000010DD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) + +pci:v000010DEd00001140sv00001043sd000010ED* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) + +pci:v000010DEd00001140sv00001043sd000011FD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd0000124D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd0000126D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd0000131D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd000013FD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd000014C7* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd00001507* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001043sd000015AD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd000015ED* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000160D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000163D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000166D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd000016CD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd000016DD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000170D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000176D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000178D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000179D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd000017DD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd00002132* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001043sd00002136* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) + +pci:v000010DEd00001140sv00001043sd000021BA* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd000021FA* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd0000220A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd0000221A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd0000223A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 710M) + +pci:v000010DEd00001140sv00001043sd0000224A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 710M) + +pci:v000010DEd00001140sv00001043sd0000227A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000228A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000232A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000233A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000235A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000236A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000238A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd00008595* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd000085EA* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd000085EB* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd000085EC* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd000085EE* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001043sd000085F3* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000860E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000861A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000861B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd00008628* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd00008643* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd0000864C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd00008652* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd00008660* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001043sd00008661* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000105Bsd00000DAC* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv0000105Bsd00000DAD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv0000105Bsd00000EF3* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001072sd0000152D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000010CFsd000017F5* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001179sd0000FA01* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA02* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA03* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA05* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA11* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA13* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA18* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA19* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA21* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA23* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA2A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA32* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA33* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA36* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA38* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA42* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA43* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA45* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA47* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA49* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA58* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA59* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA88* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001179sd0000FA89* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv0000144Dsd0000B092* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv0000144Dsd0000C0D5* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv0000144Dsd0000C0D7* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv0000144Dsd0000C0E2* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) + +pci:v000010DEd00001140sv0000144Dsd0000C0E3* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) + +pci:v000010DEd00001140sv0000144Dsd0000C0E4* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) + +pci:v000010DEd00001140sv0000144Dsd0000C10D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M on NP300E5C series laptop) + +pci:v000010DEd00001140sv0000144Dsd0000C709* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv0000144Dsd0000C711* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv0000144Dsd0000C736* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv0000144Dsd0000C737* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv0000144Dsd0000C745* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000144Dsd0000C750* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001462sd000010B8* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 710M) + +pci:v000010DEd00001140sv00001462sd000010E9* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001462sd00001116* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001462sd0000AA33* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 720M) + +pci:v000010DEd00001140sv00001462sd0000AAA2* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001462sd0000AAA3* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001462sd0000ACB2* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001462sd0000ACC1* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001462sd0000AE61* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 720M) + +pci:v000010DEd00001140sv00001462sd0000AE65* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001462sd0000AE6A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001462sd0000AE71* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000014C0sd00000083* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000152Dsd00000926* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 620M) + +pci:v000010DEd00001140sv0000152Dsd00000982* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv0000152Dsd00000983* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv0000152Dsd00001005* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 820M) + +pci:v000010DEd00001140sv0000152Dsd00001012* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv0000152Dsd00001019* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000152Dsd00001030* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 630M) + +pci:v000010DEd00001140sv0000152Dsd00001055* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv0000152Dsd00001067* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv0000152Dsd00001072* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv0000152Dsd00001086* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv0000152Dsd00001092* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00002200* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (NVS 5200M) + +pci:v000010DEd00001140sv000017AAsd00002213* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00002220* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd0000309C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720A) + +pci:v000010DEd00001140sv000017AAsd000030B4* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd000030B7* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 720A) + +pci:v000010DEd00001140sv000017AAsd000030E4* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd0000361B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd0000361C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd0000361D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd00003656* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv000017AAsd0000365A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 705M) + +pci:v000010DEd00001140sv000017AAsd0000365E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 800M) + +pci:v000010DEd00001140sv000017AAsd00003661* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd0000366C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 800M) + +pci:v000010DEd00001140sv000017AAsd00003685* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 800M) + +pci:v000010DEd00001140sv000017AAsd00003686* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 800M) + +pci:v000010DEd00001140sv000017AAsd00003687* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 705A) + +pci:v000010DEd00001140sv000017AAsd00003696* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd0000369B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd0000369C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd0000369D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd0000369E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd000036A9* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd000036AF* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd000036B0* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd000036B6* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820A) + +pci:v000010DEd00001140sv000017AAsd00003800* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00003801* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00003802* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00003803* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00003804* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00003806* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00003808* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd0000380D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd0000380E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd0000380F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00003811* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00003812* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00003813* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00003816* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00003818* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd0000381A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd0000381C* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00003901* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 610M / GT 620M) + +pci:v000010DEd00001140sv000017AAsd00003902* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv000017AAsd00003903* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 610M/710M) + +pci:v000010DEd00001140sv000017AAsd00003904* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M/625M) + +pci:v000010DEd00001140sv000017AAsd00003905* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00003907* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00003910* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 720M) + +pci:v000010DEd00001140sv000017AAsd00003912* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 720M) + +pci:v000010DEd00001140sv000017AAsd00003913* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00003915* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00003977* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00003983* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 610M) + +pci:v000010DEd00001140sv000017AAsd00005001* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 610M) + +pci:v000010DEd00001140sv000017AAsd00005003* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00005005* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 705M) + +pci:v000010DEd00001140sv000017AAsd0000500D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv000017AAsd00005014* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv000017AAsd00005017* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv000017AAsd00005019* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv000017AAsd0000501A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv000017AAsd0000501F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00005025* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv000017AAsd00005027* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv000017AAsd0000502A* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv000017AAsd0000502B* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd0000502D* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv000017AAsd0000502E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd0000502F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv000017AAsd00005030* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 705M) + +pci:v000010DEd00001140sv000017AAsd00005031* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 705M) + +pci:v000010DEd00001140sv000017AAsd00005032* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00005033* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd0000503E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv000017AAsd0000503F* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv000017AAsd00005040* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001854sd00000177* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001854sd00000180* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 710M) + +pci:v000010DEd00001140sv00001854sd00000190* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001854sd00000192* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001854sd00000224* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001B0Asd000001C0* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001B0Asd000020DD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001B0Asd000020DF* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 620M) + +pci:v000010DEd00001140sv00001B0Asd0000210E* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001B0Asd00002202* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001B0Asd000090D7* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001B0Asd000090DD* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001B50sd00005530* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001B6Csd00005531* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce GT 720M) + +pci:v000010DEd00001140sv00001BABsd00000106* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 820M) + +pci:v000010DEd00001140sv00001D05sd00001013* + ID_MODEL_FROM_DATABASE=GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] (GeForce 810M) + +pci:v000010DEd00001180* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 680] + +pci:v000010DEd00001180sv00001043sd000083F1* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 680] (GTX680-DC2-2GD5) + +pci:v000010DEd00001180sv00003842sd00003682* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 680] (GeForce GTX 680 Mac Edition) + +pci:v000010DEd00001182* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 Ti] + +pci:v000010DEd00001183* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 660 Ti] + +pci:v000010DEd00001184* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 770] + +pci:v000010DEd00001185* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 660 OEM] + +pci:v000010DEd00001185sv000010DEsd0000106F* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 660 OEM] (GK104 [GeForce GTX 760 OEM]) + +pci:v000010DEd00001187* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760] + +pci:v000010DEd00001188* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 690] + +pci:v000010DEd00001189* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 670] + +pci:v000010DEd00001189sv000010DEsd00001074* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 670] (GK104 [GeForce GTX 760 Ti OEM]) + +pci:v000010DEd0000118A* + ID_MODEL_FROM_DATABASE=GK104GL [GRID K520] + +pci:v000010DEd0000118B* + ID_MODEL_FROM_DATABASE=GK104GL [GRID K2 GeForce USM] + +pci:v000010DEd0000118C* + ID_MODEL_FROM_DATABASE=GK104 [GRID K2 NVS USM] + +pci:v000010DEd0000118D* + ID_MODEL_FROM_DATABASE=GK104GL [GRID K200 vGPU] + +pci:v000010DEd0000118Dsv000010DEsd0000101D* + ID_MODEL_FROM_DATABASE=GK104GL [GRID K200 vGPU] (GRID K200) + +pci:v000010DEd0000118E* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 OEM] + +pci:v000010DEd0000118F* + ID_MODEL_FROM_DATABASE=GK104GL [Tesla K10] + +pci:v000010DEd00001191* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 Rev. 2] + +pci:v000010DEd00001193* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 760 Ti OEM] + +pci:v000010DEd00001194* + ID_MODEL_FROM_DATABASE=GK104GL [Tesla K8] + +pci:v000010DEd00001195* + ID_MODEL_FROM_DATABASE=GK104 [GeForce GTX 660 Rev. 2] + +pci:v000010DEd00001198* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 880M] + +pci:v000010DEd00001199* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 870M] + +pci:v000010DEd0000119A* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 860M] + +pci:v000010DEd0000119D* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 775M Mac Edition] + +pci:v000010DEd0000119E* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 780M Mac Edition] + +pci:v000010DEd0000119F* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 780M] + +pci:v000010DEd000011A0* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 680M] + +pci:v000010DEd000011A1* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 670MX] + +pci:v000010DEd000011A2* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 675MX Mac Edition] + +pci:v000010DEd000011A3* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 680MX] + +pci:v000010DEd000011A3sv0000106Bsd0000010D* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 680MX] (iMac 13,2) + +pci:v000010DEd000011A7* + ID_MODEL_FROM_DATABASE=GK104M [GeForce GTX 675MX] + +pci:v000010DEd000011AF* + ID_MODEL_FROM_DATABASE=GK104GLM [GRID IceCube] + +pci:v000010DEd000011B0* + ID_MODEL_FROM_DATABASE=GK104GL [GRID K240Q / K260Q vGPU] + +pci:v000010DEd000011B0sv000010DEsd0000101A* + ID_MODEL_FROM_DATABASE=GK104GL [GRID K240Q / K260Q vGPU] (GRID K240Q) + +pci:v000010DEd000011B0sv000010DEsd0000101B* + ID_MODEL_FROM_DATABASE=GK104GL [GRID K240Q / K260Q vGPU] (GRID K260Q) + +pci:v000010DEd000011B1* + ID_MODEL_FROM_DATABASE=GK104GL [GRID K2 Tesla USM] + +pci:v000010DEd000011B4* + ID_MODEL_FROM_DATABASE=GK104GL [Quadro K4200] + +pci:v000010DEd000011B6* + ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K3100M] + +pci:v000010DEd000011B7* + ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K4100M] + +pci:v000010DEd000011B8* + ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K5100M] + +pci:v000010DEd000011B9* + ID_MODEL_FROM_DATABASE=GK104GLM + +pci:v000010DEd000011BA* + ID_MODEL_FROM_DATABASE=GK104GL [Quadro K5000] + +pci:v000010DEd000011BB* + ID_MODEL_FROM_DATABASE=GK104GL [Quadro 4100] + +pci:v000010DEd000011BC* + ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K5000M] + +pci:v000010DEd000011BD* + ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K4000M] + +pci:v000010DEd000011BE* + ID_MODEL_FROM_DATABASE=GK104GLM [Quadro K3000M] + +pci:v000010DEd000011BF* + ID_MODEL_FROM_DATABASE=GK104GL [GRID K2] + +pci:v000010DEd000011C0* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 660] + +pci:v000010DEd000011C2* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] + +pci:v000010DEd000011C2sv00001043sd0000845B* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost DirectCU II OC) + +pci:v000010DEd000011C2sv00001462sd00002874* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost TwinFrozr II OC) + +pci:v000010DEd000011C2sv00001569sd000011C2* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost OC) + +pci:v000010DEd000011C2sv000019DAsd00001281* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost OC) + +pci:v000010DEd000011C2sv00003842sd00003657* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost) + +pci:v000010DEd000011C2sv00003842sd00003658* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti Boost] (GeForce GTX 650 Ti Boost Superclocked) + +pci:v000010DEd000011C3* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti OEM] + +pci:v000010DEd000011C3sv000010DEsd00001030* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti OEM] (GeForce GTX 650 Ti OEM) + +pci:v000010DEd000011C4* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 645 OEM] + +pci:v000010DEd000011C5* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GT 740] + +pci:v000010DEd000011C6* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 Ti] + +pci:v000010DEd000011C7* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 750 Ti] + +pci:v000010DEd000011C8* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GTX 650 OEM] + +pci:v000010DEd000011CB* + ID_MODEL_FROM_DATABASE=GK106 [GeForce GT 740] + +pci:v000010DEd000011E0* + ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 770M] + +pci:v000010DEd000011E1* + ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 765M] + +pci:v000010DEd000011E2* + ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 765M] + +pci:v000010DEd000011E3* + ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 760M] + +pci:v000010DEd000011E3sv000017AAsd00003683* + ID_MODEL_FROM_DATABASE=GK106M [GeForce GTX 760M] (GeForce GTX 760A) + +pci:v000010DEd000011E7* + ID_MODEL_FROM_DATABASE=GK106M + +pci:v000010DEd000011FA* + ID_MODEL_FROM_DATABASE=GK106GL [Quadro K4000] + +pci:v000010DEd000011FC* + ID_MODEL_FROM_DATABASE=GK106GLM [Quadro K2100M] + +pci:v000010DEd00001200* + ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 560 Ti] + +pci:v000010DEd00001201* + ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 560] + +pci:v000010DEd00001202* + ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 560 Ti OEM] + +pci:v000010DEd00001203* + ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 460 SE v2] + +pci:v000010DEd00001205* + ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 460 v2] + +pci:v000010DEd00001206* + ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 555] + +pci:v000010DEd00001207* + ID_MODEL_FROM_DATABASE=GF114 [GeForce GT 645 OEM] + +pci:v000010DEd00001208* + ID_MODEL_FROM_DATABASE=GF114 [GeForce GTX 560 SE] + +pci:v000010DEd00001210* + ID_MODEL_FROM_DATABASE=GF114M [GeForce GTX 570M] + +pci:v000010DEd00001211* + ID_MODEL_FROM_DATABASE=GF114M [GeForce GTX 580M] + +pci:v000010DEd00001212* + ID_MODEL_FROM_DATABASE=GF114M [GeForce GTX 675M] + +pci:v000010DEd00001213* + ID_MODEL_FROM_DATABASE=GF114M [GeForce GTX 670M] + +pci:v000010DEd00001241* + ID_MODEL_FROM_DATABASE=GF116 [GeForce GT 545 OEM] + +pci:v000010DEd00001243* + ID_MODEL_FROM_DATABASE=GF116 [GeForce GT 545] + +pci:v000010DEd00001244* + ID_MODEL_FROM_DATABASE=GF116 [GeForce GTX 550 Ti] + +pci:v000010DEd00001245* + ID_MODEL_FROM_DATABASE=GF116 [GeForce GTS 450 Rev. 2] + +pci:v000010DEd00001246* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 550M] + +pci:v000010DEd00001247* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] + +pci:v000010DEd00001247sv00001043sd00001752* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001247sv00001043sd00002050* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001247sv00001043sd00002051* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001247sv00001043sd0000212A* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) + +pci:v000010DEd00001247sv00001043sd0000212B* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) + +pci:v000010DEd00001247sv00001043sd0000212C* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) + +pci:v000010DEd00001247sv0000152Dsd00000930* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) + +pci:v000010DEd00001248* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] + +pci:v000010DEd00001248sv0000152Dsd00000930* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) + +pci:v000010DEd00001248sv000017C0sd000010E7* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001248sv000017C0sd000010E8* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001248sv000017C0sd000010EA* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001248sv00001854sd00000890* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001248sv00001854sd00000891* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001248sv00001854sd00001795* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001248sv00001854sd00001796* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001248sv00001854sd00003005* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd00001249* + ID_MODEL_FROM_DATABASE=GF116 [GeForce GTS 450 Rev. 3] + +pci:v000010DEd0000124B* + ID_MODEL_FROM_DATABASE=GF116 [GeForce GT 640 OEM] + +pci:v000010DEd0000124D* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] + +pci:v000010DEd0000124Dsv00001028sd00000491* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd0000124Dsv00001028sd00000570* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd0000124Dsv00001028sd00000571* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd0000124Dsv00001462sd0000108D* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 555M) + +pci:v000010DEd0000124Dsv00001462sd000010CC* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 555M/635M] (GeForce GT 635M) + +pci:v000010DEd00001251* + ID_MODEL_FROM_DATABASE=GF116M [GeForce GT 560M] + +pci:v000010DEd00001280* + ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 635] + +pci:v000010DEd00001281* + ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 710] + +pci:v000010DEd00001282* + ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 640 Rev. 2] + +pci:v000010DEd00001284* + ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 630 Rev. 2] + +pci:v000010DEd00001286* + ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 720] + +pci:v000010DEd00001287* + ID_MODEL_FROM_DATABASE=GK208B [GeForce GT 730] + +pci:v000010DEd00001288* + ID_MODEL_FROM_DATABASE=GK208B [GeForce GT 720] + +pci:v000010DEd00001289* + ID_MODEL_FROM_DATABASE=GK208 [GeForce GT 710] + +pci:v000010DEd0000128B* + ID_MODEL_FROM_DATABASE=GK208B [GeForce GT 710] + +pci:v000010DEd0000128Bsv00001043sd000085F7* + ID_MODEL_FROM_DATABASE=GK208B [GeForce GT 710] (GT710-SL-1GD5) + +pci:v000010DEd00001290* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] + +pci:v000010DEd00001290sv0000103Csd00002AFA* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] (GeForce GT 730A) + +pci:v000010DEd00001290sv0000103Csd00002B04* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] (GeForce GT 730A) + +pci:v000010DEd00001290sv00001043sd000013AD* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] (GeForce GT 730M) + +pci:v000010DEd00001290sv00001043sd000013CD* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] (GeForce GT 730M) + +pci:v000010DEd00001291* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 735M] + +pci:v000010DEd00001292* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M] + +pci:v000010DEd00001292sv000017AAsd00003675* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M] (GeForce GT 740A) + +pci:v000010DEd00001292sv000017AAsd0000367C* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M] (GeForce GT 740A) + +pci:v000010DEd00001292sv000017AAsd00003684* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M] (GeForce GT 740A) + +pci:v000010DEd00001293* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 730M] + +pci:v000010DEd00001294* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 740M] + +pci:v000010DEd00001295* + ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] + +pci:v000010DEd00001295sv0000103Csd00002B0D* + ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 710A) + +pci:v000010DEd00001295sv0000103Csd00002B0F* + ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 710A) + +pci:v000010DEd00001295sv0000103Csd00002B11* + ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 710A) + +pci:v000010DEd00001295sv0000103Csd00002B20* + ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 810A) + +pci:v000010DEd00001295sv0000103Csd00002B21* + ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 810A) + +pci:v000010DEd00001295sv0000103Csd00002B22* + ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 810A) + +pci:v000010DEd00001295sv000017AAsd0000367A* + ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 805A) + +pci:v000010DEd00001295sv000017AAsd0000367C* + ID_MODEL_FROM_DATABASE=GK208M [GeForce 710M] (GeForce 710A) + +pci:v000010DEd00001296* + ID_MODEL_FROM_DATABASE=GK208M [GeForce 825M] + +pci:v000010DEd00001298* + ID_MODEL_FROM_DATABASE=GK208M [GeForce GT 720M] + +pci:v000010DEd00001299* + ID_MODEL_FROM_DATABASE=GK208BM [GeForce 920M] + +pci:v000010DEd00001299sv000017AAsd000030BB* + ID_MODEL_FROM_DATABASE=GK208BM [GeForce 920M] (GeForce 920A) + +pci:v000010DEd00001299sv000017AAsd000030DF* + ID_MODEL_FROM_DATABASE=GK208BM [GeForce 920M] (GeForce 920A) + +pci:v000010DEd00001299sv000017AAsd000036A7* + ID_MODEL_FROM_DATABASE=GK208BM [GeForce 920M] (GeForce 920A) + +pci:v000010DEd00001299sv000017AAsd000036AF* + ID_MODEL_FROM_DATABASE=GK208BM [GeForce 920M] (GeForce 920M) + +pci:v000010DEd0000129A* + ID_MODEL_FROM_DATABASE=GK208BM [GeForce 910M] + +pci:v000010DEd000012A0* + ID_MODEL_FROM_DATABASE=GK208 + +pci:v000010DEd000012B9* + ID_MODEL_FROM_DATABASE=GK208GLM [Quadro K610M] + +pci:v000010DEd000012BA* + ID_MODEL_FROM_DATABASE=GK208GLM [Quadro K510M] + +pci:v000010DEd00001340* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 830M] + +pci:v000010DEd00001340sv0000103Csd00002B2B* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 830M] (GeForce 830A) + +pci:v000010DEd00001341* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 840M] + +pci:v000010DEd00001341sv000017AAsd00003697* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 840M] (GeForce 840A) + +pci:v000010DEd00001341sv000017AAsd00003699* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 840M] (GeForce 840A) + +pci:v000010DEd00001341sv000017AAsd0000369C* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 840M] (GeForce 840A) + +pci:v000010DEd00001344* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 845M] + +pci:v000010DEd00001346* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 930M] + +pci:v000010DEd00001347* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 940M] + +pci:v000010DEd00001348* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 945M / 945A] + +pci:v000010DEd00001349* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 930M] + +pci:v000010DEd0000134B* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 940MX] + +pci:v000010DEd0000134D* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 940MX] + +pci:v000010DEd0000134Dsv000017AAsd00002248* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 940MX] (ThinkPad T570) + +pci:v000010DEd0000134E* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 930MX] + +pci:v000010DEd0000134F* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 920MX] + +pci:v000010DEd0000137A* + ID_MODEL_FROM_DATABASE=GM108GLM [Quadro K620M / Quadro M500M] + +pci:v000010DEd0000137Asv000017AAsd0000505A* + ID_MODEL_FROM_DATABASE=GM108GLM [Quadro K620M / Quadro M500M] (Quadro M500M) + +pci:v000010DEd0000137B* + ID_MODEL_FROM_DATABASE=GM108GLM [Quadro M520 Mobile] + +pci:v000010DEd0000137D* + ID_MODEL_FROM_DATABASE=GM108M [GeForce 940A] + +pci:v000010DEd00001380* + ID_MODEL_FROM_DATABASE=GM107 [GeForce GTX 750 Ti] + +pci:v000010DEd00001381* + ID_MODEL_FROM_DATABASE=GM107 [GeForce GTX 750] + +pci:v000010DEd00001382* + ID_MODEL_FROM_DATABASE=GM107 [GeForce GTX 745] + +pci:v000010DEd00001389* + ID_MODEL_FROM_DATABASE=GM107GL [GRID M30] + +pci:v000010DEd00001390* + ID_MODEL_FROM_DATABASE=GM107M [GeForce 845M] + +pci:v000010DEd00001391* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 850M] + +pci:v000010DEd00001391sv000017AAsd00003697* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 850M] (GeForce GTX 850A) + +pci:v000010DEd00001391sv000017AAsd0000A125* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 850M] (GeForce GTX 850A) + +pci:v000010DEd00001392* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 860M] + +pci:v000010DEd00001393* + ID_MODEL_FROM_DATABASE=GM107M [GeForce 840M] + +pci:v000010DEd00001398* + ID_MODEL_FROM_DATABASE=GM107M [GeForce 845M] + +pci:v000010DEd00001399* + ID_MODEL_FROM_DATABASE=GM107M [GeForce 945M] + +pci:v000010DEd0000139A* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] + +pci:v000010DEd0000139Asv000017AAsd0000362C* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) + +pci:v000010DEd0000139Asv000017AAsd0000362F* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) + +pci:v000010DEd0000139Asv000017AAsd0000363F* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) + +pci:v000010DEd0000139Asv000017AAsd00003640* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) + +pci:v000010DEd0000139Asv000017AAsd00003647* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) + +pci:v000010DEd0000139Asv000017AAsd000036B9* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 950M] (GeForce GTX 950A) + +pci:v000010DEd0000139B* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 960M] + +pci:v000010DEd0000139Bsv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 960M] (XPS 15 9550) + +pci:v000010DEd0000139Bsv0000103Csd00002B4C* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 960M] (GeForce GTX 960A) + +pci:v000010DEd0000139C* + ID_MODEL_FROM_DATABASE=GM107M [GeForce 940M] + +pci:v000010DEd0000139D* + ID_MODEL_FROM_DATABASE=GM107M [GeForce GTX 750 Ti] + +pci:v000010DEd000013B0* + ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M2000M] + +pci:v000010DEd000013B1* + ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M1000M] + +pci:v000010DEd000013B2* + ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M600M] + +pci:v000010DEd000013B3* + ID_MODEL_FROM_DATABASE=GM107GLM [Quadro K2200M] + +pci:v000010DEd000013B4* + ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M620 Mobile] + +pci:v000010DEd000013B6* + ID_MODEL_FROM_DATABASE=GM107GLM [Quadro M1200 Mobile] + +pci:v000010DEd000013B9* + ID_MODEL_FROM_DATABASE=GM107GL [NVS 810] + +pci:v000010DEd000013BA* + ID_MODEL_FROM_DATABASE=GM107GL [Quadro K2200] + +pci:v000010DEd000013BB* + ID_MODEL_FROM_DATABASE=GM107GL [Quadro K620] + +pci:v000010DEd000013BC* + ID_MODEL_FROM_DATABASE=GM107GL [Quadro K1200] + +pci:v000010DEd000013BD* + ID_MODEL_FROM_DATABASE=GM107GL [Tesla M10] + +pci:v000010DEd000013BDsv000010DEsd0000110A* + ID_MODEL_FROM_DATABASE=GM107GL [Tesla M10] (GRID M40) + +pci:v000010DEd000013BDsv000010DEsd00001160* + ID_MODEL_FROM_DATABASE=GM107GL [Tesla M10] (Tesla M10) + +pci:v000010DEd000013BDsv000010DEsd000011D2* + ID_MODEL_FROM_DATABASE=GM107GL [Tesla M10] (GRID M10-8Q) + +pci:v000010DEd000013C0* + ID_MODEL_FROM_DATABASE=GM204 [GeForce GTX 980] + +pci:v000010DEd000013C0sv00001043sd00008504* + ID_MODEL_FROM_DATABASE=GM204 [GeForce GTX 980] (GTX980-4GD5) + +pci:v000010DEd000013C1* + ID_MODEL_FROM_DATABASE=GM204 + +pci:v000010DEd000013C2* + ID_MODEL_FROM_DATABASE=GM204 [GeForce GTX 970] + +pci:v000010DEd000013C3* + ID_MODEL_FROM_DATABASE=GM204 + +pci:v000010DEd000013D7* + ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980M] + +pci:v000010DEd000013D8* + ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 970M] + +pci:v000010DEd000013D9* + ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 965M] + +pci:v000010DEd000013DA* + ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980 Mobile] + +pci:v000010DEd000013E7* + ID_MODEL_FROM_DATABASE=GM204GL [GeForce GTX 980 Engineering Sample] + +pci:v000010DEd000013F0* + ID_MODEL_FROM_DATABASE=GM204GL [Quadro M5000] + +pci:v000010DEd000013F1* + ID_MODEL_FROM_DATABASE=GM204GL [Quadro M4000] + +pci:v000010DEd000013F2* + ID_MODEL_FROM_DATABASE=GM204GL [Tesla M60] + +pci:v000010DEd000013F2sv000010DEsd0000114D* + ID_MODEL_FROM_DATABASE=GM204GL [Tesla M60] (GRID M60-1Q) + +pci:v000010DEd000013F2sv000010DEsd0000114E* + ID_MODEL_FROM_DATABASE=GM204GL [Tesla M60] (GRID M60-2Q) + +pci:v000010DEd000013F2sv000010DEsd00001150* + ID_MODEL_FROM_DATABASE=GM204GL [Tesla M60] (GRID M60-8Q) + +pci:v000010DEd000013F2sv000010DEsd000011B0* + ID_MODEL_FROM_DATABASE=GM204GL [Tesla M60] (GRID M60-4A) + +pci:v000010DEd000013F3* + ID_MODEL_FROM_DATABASE=GM204GL [Tesla M6] + +pci:v000010DEd000013F3sv000010DEsd00001184* + ID_MODEL_FROM_DATABASE=GM204GL [Tesla M6] (GRID M6-8Q) + +pci:v000010DEd000013F8* + ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M5000M / M5000 SE] + +pci:v000010DEd000013F9* + ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M4000M] + +pci:v000010DEd000013FA* + ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M3000M] + +pci:v000010DEd000013FAsv000010DEsd000011C9* + ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M3000M] (Quadro M3000 SE) + +pci:v000010DEd000013FB* + ID_MODEL_FROM_DATABASE=GM204GLM [Quadro M5500] + +pci:v000010DEd00001401* + ID_MODEL_FROM_DATABASE=GM206 [GeForce GTX 960] + +pci:v000010DEd00001402* + ID_MODEL_FROM_DATABASE=GM206 [GeForce GTX 950] + +pci:v000010DEd00001406* + ID_MODEL_FROM_DATABASE=GM206 [GeForce GTX 960 OEM] + +pci:v000010DEd00001407* + ID_MODEL_FROM_DATABASE=GM206 [GeForce GTX 750 v2] + +pci:v000010DEd00001427* + ID_MODEL_FROM_DATABASE=GM206M [GeForce GTX 965M] + +pci:v000010DEd00001430* + ID_MODEL_FROM_DATABASE=GM206GL [Quadro M2000] + +pci:v000010DEd00001431* + ID_MODEL_FROM_DATABASE=GM206GL [Tesla M4] + +pci:v000010DEd00001436* + ID_MODEL_FROM_DATABASE=GM206GLM [Quadro M2200 Mobile] + +pci:v000010DEd000015F0* + ID_MODEL_FROM_DATABASE=GP100GL [Quadro GP100] + +pci:v000010DEd000015F1* + ID_MODEL_FROM_DATABASE=GP100GL + +pci:v000010DEd000015F7* + ID_MODEL_FROM_DATABASE=GP100GL [Tesla P100 PCIe 12GB] + +pci:v000010DEd000015F8* + ID_MODEL_FROM_DATABASE=GP100GL [Tesla P100 PCIe 16GB] + +pci:v000010DEd000015F9* + ID_MODEL_FROM_DATABASE=GP100GL [Tesla P100 SXM2 16GB] + +pci:v000010DEd00001617* + ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980M] + +pci:v000010DEd00001618* + ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 970M] + +pci:v000010DEd00001619* + ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 965M] + +pci:v000010DEd0000161A* + ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 980 Mobile] + +pci:v000010DEd00001667* + ID_MODEL_FROM_DATABASE=GM204M [GeForce GTX 965M] + +pci:v000010DEd00001725* + ID_MODEL_FROM_DATABASE=GP100 + +pci:v000010DEd0000172E* + ID_MODEL_FROM_DATABASE=GP100 + +pci:v000010DEd0000172F* + ID_MODEL_FROM_DATABASE=GP100 + +pci:v000010DEd0000174D* + ID_MODEL_FROM_DATABASE=GM108M [GeForce MX130] + +pci:v000010DEd0000174E* + ID_MODEL_FROM_DATABASE=GM108M [GeForce MX110] + +pci:v000010DEd00001789* + ID_MODEL_FROM_DATABASE=GM107GL [GRID M3-3020] + +pci:v000010DEd0000179C* + ID_MODEL_FROM_DATABASE=GM107 [GeForce 940MX] + +pci:v000010DEd000017C2* + ID_MODEL_FROM_DATABASE=GM200 [GeForce GTX TITAN X] + +pci:v000010DEd000017C8* + ID_MODEL_FROM_DATABASE=GM200 [GeForce GTX 980 Ti] + +pci:v000010DEd000017F0* + ID_MODEL_FROM_DATABASE=GM200GL [Quadro M6000] + +pci:v000010DEd000017F0sv000010DEsd00001141* + ID_MODEL_FROM_DATABASE=GM200GL [Quadro M6000] (VCA 6000) + +pci:v000010DEd000017F1* + ID_MODEL_FROM_DATABASE=GM200GL [Quadro M6000 24GB] + +pci:v000010DEd000017FD* + ID_MODEL_FROM_DATABASE=GM200GL [Tesla M40] + +pci:v000010DEd00001AD6* + ID_MODEL_FROM_DATABASE=TU102 USB 3.1 Host Controller + +pci:v000010DEd00001AD7* + ID_MODEL_FROM_DATABASE=TU102 USB Type-C UCSI Controller + +pci:v000010DEd00001AD8* + ID_MODEL_FROM_DATABASE=TU104 USB 3.1 Host Controller + +pci:v000010DEd00001AD9* + ID_MODEL_FROM_DATABASE=TU104 USB Type-C UCSI Controller + +pci:v000010DEd00001ADA* + ID_MODEL_FROM_DATABASE=TU106 USB 3.1 Host Controller + +pci:v000010DEd00001ADAsv00001043sd00008673* + ID_MODEL_FROM_DATABASE=TU106 USB 3.1 Host Controller (TURBO-RTX2070-8G) + +pci:v000010DEd00001ADB* + ID_MODEL_FROM_DATABASE=TU106 USB Type-C UCSI Controller + +pci:v000010DEd00001ADBsv00001043sd00008673* + ID_MODEL_FROM_DATABASE=TU106 USB Type-C UCSI Controller (TURBO-RTX2070-8G) + +pci:v000010DEd00001AEB* + ID_MODEL_FROM_DATABASE=TU116 High Definition Audio Controller + +pci:v000010DEd00001AED* + ID_MODEL_FROM_DATABASE=TU116 [GeForce GTX 1650 SUPER] + +pci:v000010DEd00001B00* + ID_MODEL_FROM_DATABASE=GP102 [TITAN X] + +pci:v000010DEd00001B01* + ID_MODEL_FROM_DATABASE=GP102 [GeForce GTX 1080 Ti 10GB] + +pci:v000010DEd00001B02* + ID_MODEL_FROM_DATABASE=GP102 [TITAN Xp] + +pci:v000010DEd00001B04* + ID_MODEL_FROM_DATABASE=GP102 + +pci:v000010DEd00001B06* + ID_MODEL_FROM_DATABASE=GP102 [GeForce GTX 1080 Ti] + +pci:v000010DEd00001B07* + ID_MODEL_FROM_DATABASE=GP102 [P102-100] + +pci:v000010DEd00001B30* + ID_MODEL_FROM_DATABASE=GP102GL [Quadro P6000] + +pci:v000010DEd00001B38* + ID_MODEL_FROM_DATABASE=GP102GL [Tesla P40] + +pci:v000010DEd00001B70* + ID_MODEL_FROM_DATABASE=GP102GL + +pci:v000010DEd00001B78* + ID_MODEL_FROM_DATABASE=GP102GL + +pci:v000010DEd00001B80* + ID_MODEL_FROM_DATABASE=GP104 [GeForce GTX 1080] + +pci:v000010DEd00001B81* + ID_MODEL_FROM_DATABASE=GP104 [GeForce GTX 1070] + +pci:v000010DEd00001B82* + ID_MODEL_FROM_DATABASE=GP104 [GeForce GTX 1070 Ti] + +pci:v000010DEd00001B83* + ID_MODEL_FROM_DATABASE=GP104 [GeForce GTX 1060 6GB] + +pci:v000010DEd00001B84* + ID_MODEL_FROM_DATABASE=GP104 [GeForce GTX 1060 3GB] + +pci:v000010DEd00001B87* + ID_MODEL_FROM_DATABASE=GP104 [P104-100] + +pci:v000010DEd00001BA0* + ID_MODEL_FROM_DATABASE=GP104M [GeForce GTX 1080 Mobile] + +pci:v000010DEd00001BA1* + ID_MODEL_FROM_DATABASE=GP104M [GeForce GTX 1070 Mobile] + +pci:v000010DEd00001BA1sv00001458sd00001651* + ID_MODEL_FROM_DATABASE=GP104M [GeForce GTX 1070 Mobile] (GeForce GTX 1070 Max-Q) + +pci:v000010DEd00001BA1sv00001462sd000011E8* + ID_MODEL_FROM_DATABASE=GP104M [GeForce GTX 1070 Mobile] (GeForce GTX 1070 Max-Q) + +pci:v000010DEd00001BA1sv00001462sd000011E9* + ID_MODEL_FROM_DATABASE=GP104M [GeForce GTX 1070 Mobile] (GeForce GTX 1070 Max-Q) + +pci:v000010DEd00001BA1sv00001558sd00009501* + ID_MODEL_FROM_DATABASE=GP104M [GeForce GTX 1070 Mobile] (GeForce GTX 1070 Max-Q) + +pci:v000010DEd00001BA2* + ID_MODEL_FROM_DATABASE=GP104M [GeForce GTX 1070 Mobile] + +pci:v000010DEd00001BA9* + ID_MODEL_FROM_DATABASE=GP104M + +pci:v000010DEd00001BAA* + ID_MODEL_FROM_DATABASE=GP104M + +pci:v000010DEd00001BAD* + ID_MODEL_FROM_DATABASE=GP104 [GeForce GTX 1070 Engineering Sample] + +pci:v000010DEd00001BB0* + ID_MODEL_FROM_DATABASE=GP104GL [Quadro P5000] + +pci:v000010DEd00001BB1* + ID_MODEL_FROM_DATABASE=GP104GL [Quadro P4000] + +pci:v000010DEd00001BB3* + ID_MODEL_FROM_DATABASE=GP104GL [Tesla P4] + +pci:v000010DEd00001BB4* + ID_MODEL_FROM_DATABASE=GP104GL [Tesla P6] + +pci:v000010DEd00001BB5* + ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P5200 Mobile] + +pci:v000010DEd00001BB5sv0000103Csd0000842F* + ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P5200 Mobile] (P5200 [Zbook 17 G5 mobile workstation]) + +pci:v000010DEd00001BB6* + ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P5000 Mobile] + +pci:v000010DEd00001BB7* + ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P4000 Mobile] + +pci:v000010DEd00001BB7sv00001462sd000011E9* + ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P4000 Mobile] (Quadro P4000 Max-Q) + +pci:v000010DEd00001BB8* + ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P3000 Mobile] + +pci:v000010DEd00001BB9* + ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P4200 Mobile] + +pci:v000010DEd00001BB9sv0000103Csd0000842F* + ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P4200 Mobile] (P4200 [Zbook 17 G5 mobile workstation]) + +pci:v000010DEd00001BBB* + ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P3200 Mobile] + +pci:v000010DEd00001BBBsv0000103Csd0000842F* + ID_MODEL_FROM_DATABASE=GP104GLM [Quadro P3200 Mobile] (P3200 [Zbook 17 G5 moble workstation]) + +pci:v000010DEd00001BC7* + ID_MODEL_FROM_DATABASE=GP104 [P104-101] + +pci:v000010DEd00001BE0* + ID_MODEL_FROM_DATABASE=GP104BM [GeForce GTX 1080 Mobile] + +pci:v000010DEd00001BE0sv00001028sd000007C0* + ID_MODEL_FROM_DATABASE=GP104BM [GeForce GTX 1080 Mobile] (GeForce GTX 1080 Max-Q) + +pci:v000010DEd00001BE0sv00001458sd0000355B* + ID_MODEL_FROM_DATABASE=GP104BM [GeForce GTX 1080 Mobile] (GeForce GTX 1080 Max-Q) + +pci:v000010DEd00001BE1* + ID_MODEL_FROM_DATABASE=GP104BM [GeForce GTX 1070 Mobile] + +pci:v000010DEd00001C00* + ID_MODEL_FROM_DATABASE=GP106 + +pci:v000010DEd00001C01* + ID_MODEL_FROM_DATABASE=GP106 + +pci:v000010DEd00001C02* + ID_MODEL_FROM_DATABASE=GP106 [GeForce GTX 1060 3GB] + +pci:v000010DEd00001C03* + ID_MODEL_FROM_DATABASE=GP106 [GeForce GTX 1060 6GB] + +pci:v000010DEd00001C04* + ID_MODEL_FROM_DATABASE=GP106 [GeForce GTX 1060 5GB] + +pci:v000010DEd00001C06* + ID_MODEL_FROM_DATABASE=GP106 [GeForce GTX 1060 6GB Rev. 2] + +pci:v000010DEd00001C07* + ID_MODEL_FROM_DATABASE=GP106 [P106-100] + +pci:v000010DEd00001C09* + ID_MODEL_FROM_DATABASE=GP106 [P106-090] + +pci:v000010DEd00001C20* + ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1060 Mobile] + +pci:v000010DEd00001C20sv000017AAsd000039B9* + ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1060 Mobile] (GeForce GTX 1060 Max-Q 3GB) + +pci:v000010DEd00001C21* + ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1050 Ti Mobile] + +pci:v000010DEd00001C22* + ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1050 Mobile] + +pci:v000010DEd00001C23* + ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1060 Mobile Rev. 2] + +pci:v000010DEd00001C23sv00001414sd00000020* + ID_MODEL_FROM_DATABASE=GP106M [GeForce GTX 1060 Mobile Rev. 2] (GTX 1060 Mobile) + +pci:v000010DEd00001C2D* + ID_MODEL_FROM_DATABASE=GP106M + +pci:v000010DEd00001C30* + ID_MODEL_FROM_DATABASE=GP106GL [Quadro P2000] + +pci:v000010DEd00001C31* + ID_MODEL_FROM_DATABASE=GP106GL [Quadro P2200] + +pci:v000010DEd00001C35* + ID_MODEL_FROM_DATABASE=GP106 + +pci:v000010DEd00001C60* + ID_MODEL_FROM_DATABASE=GP106BM [GeForce GTX 1060 Mobile 6GB] + +pci:v000010DEd00001C60sv0000103Csd00008390* + ID_MODEL_FROM_DATABASE=GP106BM [GeForce GTX 1060 Mobile 6GB] (GeForce GTX 1060 Max-Q 6GB) + +pci:v000010DEd00001C61* + ID_MODEL_FROM_DATABASE=GP106BM [GeForce GTX 1050 Ti Mobile] + +pci:v000010DEd00001C62* + ID_MODEL_FROM_DATABASE=GP106BM [GeForce GTX 1050 Mobile] + +pci:v000010DEd00001C70* + ID_MODEL_FROM_DATABASE=GP106GL + +pci:v000010DEd00001C81* + ID_MODEL_FROM_DATABASE=GP107 [GeForce GTX 1050] + +pci:v000010DEd00001C82* + ID_MODEL_FROM_DATABASE=GP107 [GeForce GTX 1050 Ti] + +pci:v000010DEd00001C82sv00001043sd00008613* + ID_MODEL_FROM_DATABASE=GP107 [GeForce GTX 1050 Ti] (PH-GTX1050TI-4G) + +pci:v000010DEd00001C82sv00001458sd00003763* + ID_MODEL_FROM_DATABASE=GP107 [GeForce GTX 1050 Ti] (GV-N105TOC-4GD) + +pci:v000010DEd00001C83* + ID_MODEL_FROM_DATABASE=GP107 [GeForce GTX 1050 3GB] + +pci:v000010DEd00001C8C* + ID_MODEL_FROM_DATABASE=GP107M [GeForce GTX 1050 Ti Mobile] + +pci:v000010DEd00001C8D* + ID_MODEL_FROM_DATABASE=GP107M [GeForce GTX 1050 Mobile] + +pci:v000010DEd00001C8E* + ID_MODEL_FROM_DATABASE=GP107M + +pci:v000010DEd00001C8F* + ID_MODEL_FROM_DATABASE=GP107M [GeForce GTX 1050 Ti Max-Q] + +pci:v000010DEd00001C90* + ID_MODEL_FROM_DATABASE=GP107M [GeForce MX150] + +pci:v000010DEd00001C91* + ID_MODEL_FROM_DATABASE=GP107M [GeForce GTX 1050 3 GB Max-Q] + +pci:v000010DEd00001C92* + ID_MODEL_FROM_DATABASE=GP107M [GeForce GTX 1050 Mobile] + +pci:v000010DEd00001C94* + ID_MODEL_FROM_DATABASE=GP107M [GeForce MX350] + +pci:v000010DEd00001CA7* + ID_MODEL_FROM_DATABASE=GP107GL + +pci:v000010DEd00001CA8* + ID_MODEL_FROM_DATABASE=GP107GL + +pci:v000010DEd00001CAA* + ID_MODEL_FROM_DATABASE=GP107GL + +pci:v000010DEd00001CB1* + ID_MODEL_FROM_DATABASE=GP107GL [Quadro P1000] + +pci:v000010DEd00001CB2* + ID_MODEL_FROM_DATABASE=GP107GL [Quadro P600] + +pci:v000010DEd00001CB3* + ID_MODEL_FROM_DATABASE=GP107GL [Quadro P400] + +pci:v000010DEd00001CB6* + ID_MODEL_FROM_DATABASE=GP107GL [Quadro P620] + +pci:v000010DEd00001CBA* + ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P2000 Mobile] + +pci:v000010DEd00001CBAsv0000103Csd0000842C* + ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P2000 Mobile] (P2000 [Zbook 15 G5 mobile workstation]) + +pci:v000010DEd00001CBAsv0000103Csd0000842F* + ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P2000 Mobile] (P2000 [Zbook 17 G5 mobile workstation]) + +pci:v000010DEd00001CBB* + ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P1000 Mobile] + +pci:v000010DEd00001CBBsv0000103Csd00008429* + ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P1000 Mobile] (P1000 [Zbook Studio G5 mobile workstation]) + +pci:v000010DEd00001CBBsv0000103Csd0000842C* + ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P1000 Mobile] (P1000 [Zbook 15 G5 mobile workstation]) + +pci:v000010DEd00001CBBsv0000103Csd0000842F* + ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P1000 Mobile] (P1000 [Zbook 17 G5 mobile workstation]) + +pci:v000010DEd00001CBBsv0000103Csd00008451* + ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P1000 Mobile] (P1000 [Zbook Studio x360 G5 mobile workstation]) + +pci:v000010DEd00001CBC* + ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P600 Mobile] + +pci:v000010DEd00001CBD* + ID_MODEL_FROM_DATABASE=GP107GLM [Quadro P620] + +pci:v000010DEd00001CCC* + ID_MODEL_FROM_DATABASE=GP107BM [GeForce GTX 1050 Ti Mobile] + +pci:v000010DEd00001CCD* + ID_MODEL_FROM_DATABASE=GP107BM [GeForce GTX 1050 Mobile] + +pci:v000010DEd00001D01* + ID_MODEL_FROM_DATABASE=GP108 [GeForce GT 1030] + +pci:v000010DEd00001D10* + ID_MODEL_FROM_DATABASE=GP108M [GeForce MX150] + +pci:v000010DEd00001D10sv000017AAsd0000225E* + ID_MODEL_FROM_DATABASE=GP108M [GeForce MX150] (ThinkPad T480) + +pci:v000010DEd00001D11* + ID_MODEL_FROM_DATABASE=GP108M [GeForce MX230] + +pci:v000010DEd00001D12* + ID_MODEL_FROM_DATABASE=GP108M [GeForce MX150] + +pci:v000010DEd00001D12sv00001D72sd00001701* + ID_MODEL_FROM_DATABASE=GP108M [GeForce MX150] (Mi Notebook Pro [GeForce MX150]) + +pci:v000010DEd00001D13* + ID_MODEL_FROM_DATABASE=GP108M [GeForce MX250] + +pci:v000010DEd00001D16* + ID_MODEL_FROM_DATABASE=GP108M [GeForce MX330] + +pci:v000010DEd00001D33* + ID_MODEL_FROM_DATABASE=GP108GLM [Quadro P500 Mobile] + +pci:v000010DEd00001D34* + ID_MODEL_FROM_DATABASE=GP108GLM [Quadro P520] + +pci:v000010DEd00001D52* + ID_MODEL_FROM_DATABASE=GP108BM [GeForce MX250] + +pci:v000010DEd00001D81* + ID_MODEL_FROM_DATABASE=GV100 [TITAN V] + +pci:v000010DEd00001DB1* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 SXM2 16GB] + +pci:v000010DEd00001DB2* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 DGXS 16GB] + +pci:v000010DEd00001DB3* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 FHHL 16GB] + +pci:v000010DEd00001DB4* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 PCIe 16GB] + +pci:v000010DEd00001DB5* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 SXM2 32GB] + +pci:v000010DEd00001DB6* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 PCIe 32GB] + +pci:v000010DEd00001DB7* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 DGXS 32GB] + +pci:v000010DEd00001DB8* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 SXM3 32GB] + +pci:v000010DEd00001DB8sv000010DEsd0000131D* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 SXM3 32GB] (Tesla V100-SXM3-32GB-H) + +pci:v000010DEd00001DBA* + ID_MODEL_FROM_DATABASE=GV100GL [Quadro GV100] + +pci:v000010DEd00001DBAsv000010DEsd000012EB* + ID_MODEL_FROM_DATABASE=GV100GL [Quadro GV100] (TITAN V CEO Edition) + +pci:v000010DEd00001DF5* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100 SXM2 16GB] + +pci:v000010DEd00001DF6* + ID_MODEL_FROM_DATABASE=GV100GL [Tesla V100S PCIe 32GB] + +pci:v000010DEd00001E02* + ID_MODEL_FROM_DATABASE=TU102 [TITAN RTX] + +pci:v000010DEd00001E04* + ID_MODEL_FROM_DATABASE=TU102 [GeForce RTX 2080 Ti] + +pci:v000010DEd00001E07* + ID_MODEL_FROM_DATABASE=TU102 [GeForce RTX 2080 Ti Rev. A] + +pci:v000010DEd00001E07sv00001462sd00003715* + ID_MODEL_FROM_DATABASE=TU102 [GeForce RTX 2080 Ti Rev. A] (RTX 2080 Ti GAMING X TRIO) + +pci:v000010DEd00001E2D* + ID_MODEL_FROM_DATABASE=TU102B + +pci:v000010DEd00001E2E* + ID_MODEL_FROM_DATABASE=TU102B + +pci:v000010DEd00001E30* + ID_MODEL_FROM_DATABASE=TU102GL [Quadro RTX 6000/8000] + +pci:v000010DEd00001E30sv000010DEsd0000129E* + ID_MODEL_FROM_DATABASE=TU102GL [Quadro RTX 6000/8000] (Quadro RTX 8000) + +pci:v000010DEd00001E30sv000010DEsd000012BA* + ID_MODEL_FROM_DATABASE=TU102GL [Quadro RTX 6000/8000] (Quadro RTX 6000) + +pci:v000010DEd00001E38* + ID_MODEL_FROM_DATABASE=TU102GL + +pci:v000010DEd00001E3C* + ID_MODEL_FROM_DATABASE=TU102GL + +pci:v000010DEd00001E3D* + ID_MODEL_FROM_DATABASE=TU102GL + +pci:v000010DEd00001E3E* + ID_MODEL_FROM_DATABASE=TU102GL + +pci:v000010DEd00001E78* + ID_MODEL_FROM_DATABASE=TU102GL [Quadro RTX 6000/8000] + +pci:v000010DEd00001E78sv000010DEsd000013D8* + ID_MODEL_FROM_DATABASE=TU102GL [Quadro RTX 6000/8000] (Quadro RTX 8000) + +pci:v000010DEd00001E78sv000010DEsd000013D9* + ID_MODEL_FROM_DATABASE=TU102GL [Quadro RTX 6000/8000] (Quadro RTX 6000) + +pci:v000010DEd00001E81* + ID_MODEL_FROM_DATABASE=TU104 [GeForce RTX 2080 SUPER] + +pci:v000010DEd00001E82* + ID_MODEL_FROM_DATABASE=TU104 [GeForce RTX 2080] + +pci:v000010DEd00001E84* + ID_MODEL_FROM_DATABASE=TU104 [GeForce RTX 2070 SUPER] + +pci:v000010DEd00001E87* + ID_MODEL_FROM_DATABASE=TU104 [GeForce RTX 2080 Rev. A] + +pci:v000010DEd00001E89* + ID_MODEL_FROM_DATABASE=TU104 [GeForce RTX 2060] + +pci:v000010DEd00001E90* + ID_MODEL_FROM_DATABASE=TU104M [GeForce RTX 2080 Mobile] + +pci:v000010DEd00001EAB* + ID_MODEL_FROM_DATABASE=TU104M + +pci:v000010DEd00001EAE* + ID_MODEL_FROM_DATABASE=TU104M + +pci:v000010DEd00001EB0* + ID_MODEL_FROM_DATABASE=TU104GL [Quadro RTX 5000] + +pci:v000010DEd00001EB1* + ID_MODEL_FROM_DATABASE=TU104GL [Quadro RTX 4000] + +pci:v000010DEd00001EB5* + ID_MODEL_FROM_DATABASE=TU104GLM [Quadro RTX 5000 Mobile / Max-Q] + +pci:v000010DEd00001EB6* + ID_MODEL_FROM_DATABASE=TU104GLM [Quadro RTX 4000 Mobile / Max-Q] + +pci:v000010DEd00001EB8* + ID_MODEL_FROM_DATABASE=TU104GL [Tesla T4] + +pci:v000010DEd00001EB9* + ID_MODEL_FROM_DATABASE=TU104GL + +pci:v000010DEd00001EBE* + ID_MODEL_FROM_DATABASE=TU104GL + +pci:v000010DEd00001EC2* + ID_MODEL_FROM_DATABASE=TU104 [GeForce RTX 2070 SUPER] + +pci:v000010DEd00001EC7* + ID_MODEL_FROM_DATABASE=TU104 [GeForce RTX 2070 SUPER] + +pci:v000010DEd00001ED0* + ID_MODEL_FROM_DATABASE=TU104BM [GeForce RTX 2080 Mobile] + +pci:v000010DEd00001F02* + ID_MODEL_FROM_DATABASE=TU106 [GeForce RTX 2070] + +pci:v000010DEd00001F02sv00001043sd00008673* + ID_MODEL_FROM_DATABASE=TU106 [GeForce RTX 2070] (TURBO RTX 2070) + +pci:v000010DEd00001F04* + ID_MODEL_FROM_DATABASE=TU106 + +pci:v000010DEd00001F06* + ID_MODEL_FROM_DATABASE=TU106 [GeForce RTX 2060 SUPER] + +pci:v000010DEd00001F07* + ID_MODEL_FROM_DATABASE=TU106 [GeForce RTX 2070 Rev. A] + +pci:v000010DEd00001F08* + ID_MODEL_FROM_DATABASE=TU106 [GeForce RTX 2060 Rev. A] + +pci:v000010DEd00001F10* + ID_MODEL_FROM_DATABASE=TU106M [GeForce RTX 2070 Mobile] + +pci:v000010DEd00001F11* + ID_MODEL_FROM_DATABASE=TU106M [GeForce RTX 2060 Mobile] + +pci:v000010DEd00001F2E* + ID_MODEL_FROM_DATABASE=TU106M + +pci:v000010DEd00001F36* + ID_MODEL_FROM_DATABASE=TU106GLM [Quadro RTX 3000 Mobile / Max-Q] + +pci:v000010DEd00001F42* + ID_MODEL_FROM_DATABASE=TU106 [GeForce RTX 2060 SUPER] + +pci:v000010DEd00001F47* + ID_MODEL_FROM_DATABASE=TU106 [GeForce RTX 2060 SUPER] + +pci:v000010DEd00001F50* + ID_MODEL_FROM_DATABASE=TU106BM [GeForce RTX 2070 Mobile] + +pci:v000010DEd00001F51* + ID_MODEL_FROM_DATABASE=TU106BM [GeForce RTX 2060 Mobile] + +pci:v000010DEd00001F81* + ID_MODEL_FROM_DATABASE=TU117 + +pci:v000010DEd00001F82* + ID_MODEL_FROM_DATABASE=TU117 [GeForce GTX 1650] + +pci:v000010DEd00001F91* + ID_MODEL_FROM_DATABASE=TU117M [GeForce GTX 1650 Mobile / Max-Q] + +pci:v000010DEd00001F92* + ID_MODEL_FROM_DATABASE=TU117M [GeForce GTX 1650 Mobile] + +pci:v000010DEd00001F96* + ID_MODEL_FROM_DATABASE=TU117M [GeForce GTX 1650 Mobile / Max-Q] + +pci:v000010DEd00001FAE* + ID_MODEL_FROM_DATABASE=TU117GL + +pci:v000010DEd00001FB8* + ID_MODEL_FROM_DATABASE=TU117GLM [Quadro T2000 Mobile / Max-Q] + +pci:v000010DEd00001FB9* + ID_MODEL_FROM_DATABASE=TU117GLM [Quadro T1000 Mobile] + +pci:v000010DEd00001FBF* + ID_MODEL_FROM_DATABASE=TU117GL + +pci:v000010DEd00002182* + ID_MODEL_FROM_DATABASE=TU116 [GeForce GTX 1660 Ti] + +pci:v000010DEd00002183* + ID_MODEL_FROM_DATABASE=TU116 + +pci:v000010DEd00002184* + ID_MODEL_FROM_DATABASE=TU116 [GeForce GTX 1660] + +pci:v000010DEd00002187* + ID_MODEL_FROM_DATABASE=TU116 [GeForce GTX 1650 SUPER] + +pci:v000010DEd00002191* + ID_MODEL_FROM_DATABASE=TU116M [GeForce GTX 1660 Ti Mobile] + +pci:v000010DEd000021AE* + ID_MODEL_FROM_DATABASE=TU116GL + +pci:v000010DEd000021BF* + ID_MODEL_FROM_DATABASE=TU116GL + +pci:v000010DEd000021C4* + ID_MODEL_FROM_DATABASE=TU116 [GeForce GTX 1660 SUPER] + +pci:v000010DEd000021D1* + ID_MODEL_FROM_DATABASE=TU116BM [GeForce GTX 1660 Ti Mobile] + +pci:v000010DF* + ID_VENDOR_FROM_DATABASE=Emulex Corporation + +pci:v000010DFd00000720* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) + +pci:v000010DFd00000720sv0000103Csd00001934* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (FlexFabric 20Gb 2-port 650M Adapter) + +pci:v000010DFd00000720sv0000103Csd00001935* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (FlexFabric 20Gb 2-port 650FLB Adapter) + +pci:v000010DFd00000720sv0000103Csd000021D4* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (StoreFabric CN1200E 10Gb Converged Network Adapter) + +pci:v000010DFd00000720sv0000103Csd0000220A* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (FlexFabric 10Gb 2-port 556FLR-SFP+ Adapter) + +pci:v000010DFd00000720sv0000103Csd0000803F* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (Ethernet 10Gb 2-port 557SFP+ Adapter) + +pci:v000010DFd00000720sv0000103Csd00008144* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (FlexFabric 10GB 2-port 556FLR-T Adapter) + +pci:v000010DFd00000720sv000017AAsd00001056* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (ThinkServer OCm14102-UX-L AnyFabric) + +pci:v000010DFd00000720sv000017AAsd00001057* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (ThinkServer OCm14104-UX-L AnyFabric) + +pci:v000010DFd00000720sv000017AAsd00001059* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (ThinkServer OCm14104-UT-L AnyFabric) + +pci:v000010DFd00000720sv000017AAsd00004014* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk) (ThinkServer OCm14102-NX-L AnyFabric) + +pci:v000010DFd00000722* + ID_MODEL_FROM_DATABASE=OneConnect iSCSI Initiator (Skyhawk) + +pci:v000010DFd00000723* + ID_MODEL_FROM_DATABASE=OneConnect iSCSI Initiator + Target (Skyhawk) + +pci:v000010DFd00000724* + ID_MODEL_FROM_DATABASE=OneConnect FCoE Initiator (Skyhawk) + +pci:v000010DFd00000728* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Skyhawk-VF) + +pci:v000010DFd0000072A* + ID_MODEL_FROM_DATABASE=OneConnect iSCSI Initiator (Skyhawk-VF) + +pci:v000010DFd0000072B* + ID_MODEL_FROM_DATABASE=OneConnect iSCSI Initiator + Target (Skyhawk-VF) + +pci:v000010DFd0000072C* + ID_MODEL_FROM_DATABASE=OneConnect FCoE Initiator (Skyhawk-VF) + +pci:v000010DFd00001AE5* + ID_MODEL_FROM_DATABASE=LP6000 Fibre Channel Host Adapter + +pci:v000010DFd0000E100* + ID_MODEL_FROM_DATABASE=Proteus-X: LightPulse IOV Fibre Channel Host Adapter + +pci:v000010DFd0000E131* + ID_MODEL_FROM_DATABASE=LightPulse 8Gb/s PCIe Shared I/O Fibre Channel Adapter + +pci:v000010DFd0000E180* + ID_MODEL_FROM_DATABASE=Proteus-X: LightPulse IOV Fibre Channel Host Adapter + +pci:v000010DFd0000E200* + ID_MODEL_FROM_DATABASE=LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter + +pci:v000010DFd0000E200sv00001014sd000003F1* + ID_MODEL_FROM_DATABASE=LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter (PCIe2 2-Port 16Gb Fibre Channel Adapter for POWER (FC EL5B; CCIN 577F)) + +pci:v000010DFd0000E200sv00001014sd000004E3* + ID_MODEL_FROM_DATABASE=LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter (PCIe3 4-Port 10GbE SR Adapter for POWER (FC EN15/EN16; CCIN 2CE3)) + +pci:v000010DFd0000E200sv00001014sd000004E4* + ID_MODEL_FROM_DATABASE=LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter (PCIe3 4-Port 10GbE SFP+ Adapter for POWER (FC EN18; CCIN 2CE4)) + +pci:v000010DFd0000E200sv000010DFsd0000E280* + ID_MODEL_FROM_DATABASE=LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter (LPe16002B-M6 2-Port 16Gb Fibre Channel Adapter) + +pci:v000010DFd0000E200sv000010DFsd0000E281* + ID_MODEL_FROM_DATABASE=LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter (LPe16000B-M6 1-Port 16Gb Fibre Channel Adapter) + +pci:v000010DFd0000E200sv000010DFsd0000E282* + ID_MODEL_FROM_DATABASE=LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter (Flex System FC5054 4-port 16Gb FC Adapter) + +pci:v000010DFd0000E208* + ID_MODEL_FROM_DATABASE=LightPulse 16Gb Fibre Channel Host Adapter (Lancer-VF) + +pci:v000010DFd0000E220* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Lancer) + +pci:v000010DFd0000E220sv000017AAsd00001054* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Lancer) (ThinkServer LPm16002B-M6-L AnyFabric) + +pci:v000010DFd0000E220sv000017AAsd00001055* + ID_MODEL_FROM_DATABASE=OneConnect NIC (Lancer) (ThinkServer LPm16004B-M8-L AnyFabric) + +pci:v000010DFd0000E240* + ID_MODEL_FROM_DATABASE=OneConnect iSCSI Initiator (Lancer) + +pci:v000010DFd0000E260* + ID_MODEL_FROM_DATABASE=OneConnect FCoE Initiator (Lancer) + +pci:v000010DFd0000E268* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Converged Network Adapter (Lancer-VF) + +pci:v000010DFd0000E300* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter + +pci:v000010DFd0000E300sv00001014sd00000614* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (PCIe3 4-Port 16Gb Fibre Channel Adapter for POWER (FC EN1C/EN1D; CCIN 578E)) + +pci:v000010DFd0000E300sv00001014sd00000615* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (PCIe3 2-Port 32Gb Fibre Channel Adapter for POWER (FC EN1A/EN1B; CCIN 578F)) + +pci:v000010DFd0000E300sv000010DFsd0000E300* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe32002-M2 2-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E301* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe32000-M2 1-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E310* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe31002-M6 2-Port 16Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E311* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe31000-M6 1-Port 16Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E312* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe31004-M6 4-Port 16Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E320* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe32002-M2-D 2-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E321* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe32000-M2-D 1-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E322* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe31002-M6-D 2-Port 16Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E323* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe31000-M6-D 1-Port 16Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E324* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPm32002-D 2-Port 32Gb Fibre Channel Mezz Card) + +pci:v000010DFd0000E300sv000010DFsd0000E325* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPm31002-D 2-Port 16Gb Fibre Channel Mezz Card) + +pci:v000010DFd0000E300sv000010DFsd0000E330* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe32002-M2-L 2-Port 32Gb PCIe Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E331* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe32000-M2-L 1-Port 32Gb PCIe Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E332* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe31002-M6-L 2-Port 16Gb PCIe Fibre Channel Adapter) + +pci:v000010DFd0000E300sv000010DFsd0000E333* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (LPe31000-M6-L 1-Port 16Gb PCIe Fibre Channel Adapter) + +pci:v000010DFd0000E300sv00001590sd00000201* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (StoreFabric SN1600E 1-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv00001590sd00000202* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (StoreFabric SN1600E 2-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv00001590sd00000213* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (StoreFabric SN1200E 1-Port 16Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv00001590sd00000214* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (StoreFabric SN1200E 2-Port 16Gb Fibre Channel Adapter) + +pci:v000010DFd0000E300sv00001590sd0000022E* + ID_MODEL_FROM_DATABASE=LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter (Synergy 5330C 2-Port 32Gb Fibre Channel Mezz Card) + +pci:v000010DFd0000F011* + ID_MODEL_FROM_DATABASE=Saturn: LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F015* + ID_MODEL_FROM_DATABASE=Saturn: LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F085* + ID_MODEL_FROM_DATABASE=LP850 Fibre Channel Host Adapter + +pci:v000010DFd0000F095* + ID_MODEL_FROM_DATABASE=LP952 Fibre Channel Host Adapter + +pci:v000010DFd0000F098* + ID_MODEL_FROM_DATABASE=LP982 Fibre Channel Host Adapter + +pci:v000010DFd0000F0A1* + ID_MODEL_FROM_DATABASE=Thor LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F0A5* + ID_MODEL_FROM_DATABASE=Thor LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F0B5* + ID_MODEL_FROM_DATABASE=Viper LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F0D1* + ID_MODEL_FROM_DATABASE=Helios LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F0D5* + ID_MODEL_FROM_DATABASE=Helios LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F0E1* + ID_MODEL_FROM_DATABASE=Zephyr LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F0E5* + ID_MODEL_FROM_DATABASE=Zephyr LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F0F5* + ID_MODEL_FROM_DATABASE=Neptune LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F100* + ID_MODEL_FROM_DATABASE=LPe12000 Series 8Gb Fibre Channel Adapter + +pci:v000010DFd0000F100sv00001014sd0000038A* + ID_MODEL_FROM_DATABASE=LPe12000 Series 8Gb Fibre Channel Adapter (8Gb PCI Express Dual Port FC Adapter for POWER) + +pci:v000010DFd0000F100sv0000103Csd00003282* + ID_MODEL_FROM_DATABASE=LPe12000 Series 8Gb Fibre Channel Adapter (8Gb Dual-port PCI-e FC HBA) + +pci:v000010DFd0000F100sv000010DFsd0000F140* + ID_MODEL_FROM_DATABASE=LPe12000 Series 8Gb Fibre Channel Adapter (LPe12000-M8-L 1-Port 8Gb PCIe Fibre Channel Adapter) + +pci:v000010DFd0000F100sv000010DFsd0000F141* + ID_MODEL_FROM_DATABASE=LPe12000 Series 8Gb Fibre Channel Adapter (LPe12002-M8-L 2-Port 8Gb PCIe Fibre Channel Adapter) + +pci:v000010DFd0000F111* + ID_MODEL_FROM_DATABASE=Saturn-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F112* + ID_MODEL_FROM_DATABASE=Saturn-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000F180* + ID_MODEL_FROM_DATABASE=LPSe12002 EmulexSecure Fibre Channel Adapter + +pci:v000010DFd0000F400* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter + +pci:v000010DFd0000F400sv000010DFsd0000F401* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (LPe35000-M2 1-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000F400sv000010DFsd0000F402* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (LPe35002-M2 2-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000F400sv000010DFsd0000F403* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (LPe36000-M64 1-Port 64Gb Fibre Channel Adapter) + +pci:v000010DFd0000F400sv000010DFsd0000F404* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (LPe36002-M64 2-Port 64Gb Fibre Channel Adapter) + +pci:v000010DFd0000F400sv000010DFsd0000F405* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (LPe35004-M2 4-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000F400sv000010DFsd0000F406* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (LPe35004-X6 4-Port Fibre Channel Adapter) + +pci:v000010DFd0000F400sv000010DFsd0000F410* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (LPe35002-M2-D 2-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000F400sv000010DFsd0000F411* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (LPe35000-M2-D 1-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000F400sv000010DFsd0000F418* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (LPe35000-M2-L 1-Port 32Gb PCIe Fibre Channel Adapter) + +pci:v000010DFd0000F400sv000010DFsd0000F419* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (LPe35002-M2-L 2-Port 32Gb PCIe Fibre Channel Adapter) + +pci:v000010DFd0000F400sv00001590sd000002D5* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (StoreFabric SN1610E 1-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000F400sv00001590sd000002D6* + ID_MODEL_FROM_DATABASE=LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter (StoreFabric SN1610E 2-Port 32Gb Fibre Channel Adapter) + +pci:v000010DFd0000F700* + ID_MODEL_FROM_DATABASE=LP7000 Fibre Channel Host Adapter + +pci:v000010DFd0000F701* + ID_MODEL_FROM_DATABASE=LP7000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) + +pci:v000010DFd0000F800* + ID_MODEL_FROM_DATABASE=LP8000 Fibre Channel Host Adapter + +pci:v000010DFd0000F801* + ID_MODEL_FROM_DATABASE=LP8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) + +pci:v000010DFd0000F900* + ID_MODEL_FROM_DATABASE=LP9000 Fibre Channel Host Adapter + +pci:v000010DFd0000F901* + ID_MODEL_FROM_DATABASE=LP9000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) + +pci:v000010DFd0000F980* + ID_MODEL_FROM_DATABASE=LP9802 Fibre Channel Host Adapter + +pci:v000010DFd0000F981* + ID_MODEL_FROM_DATABASE=LP9802 Fibre Channel Host Adapter Alternate ID + +pci:v000010DFd0000F982* + ID_MODEL_FROM_DATABASE=LP9802 Fibre Channel Host Adapter Alternate ID + +pci:v000010DFd0000FA00* + ID_MODEL_FROM_DATABASE=Thor-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FB00* + ID_MODEL_FROM_DATABASE=Viper LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FC00* + ID_MODEL_FROM_DATABASE=Thor-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FC00sv000010DFsd0000FC00* + ID_MODEL_FROM_DATABASE=Thor-X LightPulse Fibre Channel Host Adapter (LP10000 LightPulse Fibre Channel Host Adapter) + +pci:v000010DFd0000FC10* + ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FC20* + ID_MODEL_FROM_DATABASE=Zephyr-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FC40* + ID_MODEL_FROM_DATABASE=Saturn-X: LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FC50* + ID_MODEL_FROM_DATABASE=Proteus-X: LightPulse IOV Fibre Channel Host Adapter + +pci:v000010DFd0000FD00* + ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FD00sv000010DFsd0000FD02* + ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter (LightPulse LP11002 Dual-port 4Gigabit PCI Fibre Channel Adapter) + +pci:v000010DFd0000FD11* + ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FD12* + ID_MODEL_FROM_DATABASE=Helios-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FE00* + ID_MODEL_FROM_DATABASE=Zephyr-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FE05* + ID_MODEL_FROM_DATABASE=Zephyr-X: LightPulse FCoE Adapter + +pci:v000010DFd0000FE11* + ID_MODEL_FROM_DATABASE=Zephyr-X LightPulse Fibre Channel Host Adapter + +pci:v000010DFd0000FE12* + ID_MODEL_FROM_DATABASE=Zephyr-X LightPulse FCoE Adapter + +pci:v000010DFd0000FF00* + ID_MODEL_FROM_DATABASE=Neptune LightPulse Fibre Channel Host Adapter + +pci:v000010E0* + ID_VENDOR_FROM_DATABASE=Integrated Micro Solutions Inc. + +pci:v000010E0d00005026* + ID_MODEL_FROM_DATABASE=IMS5026/27/28 + +pci:v000010E0d00005027* + ID_MODEL_FROM_DATABASE=IMS5027 + +pci:v000010E0d00005028* + ID_MODEL_FROM_DATABASE=IMS5028 + +pci:v000010E0d00008849* + ID_MODEL_FROM_DATABASE=IMS8849 + +pci:v000010E0d00008853* + ID_MODEL_FROM_DATABASE=IMS8853 + +pci:v000010E0d00009128* + ID_MODEL_FROM_DATABASE=IMS9128 [Twin turbo 128] + +pci:v000010E1* + ID_VENDOR_FROM_DATABASE=Tekram Technology Co.,Ltd. + +pci:v000010E1d00000391* + ID_MODEL_FROM_DATABASE=TRM-S1040 + +pci:v000010E1d00000391sv000010E1sd00000391* + ID_MODEL_FROM_DATABASE=TRM-S1040 (DC-315U SCSI-3 Host Adapter) + +pci:v000010E1d0000690C* + ID_MODEL_FROM_DATABASE=DC-690c + +pci:v000010E1d0000DC29* + ID_MODEL_FROM_DATABASE=DC-290 + +pci:v000010E2* + ID_VENDOR_FROM_DATABASE=Aptix Corporation + +pci:v000010E3* + ID_VENDOR_FROM_DATABASE=Tundra Semiconductor Corp. + +pci:v000010E3d00000000* + ID_MODEL_FROM_DATABASE=CA91C042 [Universe] + +pci:v000010E3d00000108* + ID_MODEL_FROM_DATABASE=Tsi108 Host Bridge for Single PowerPC + +pci:v000010E3d00000148* + ID_MODEL_FROM_DATABASE=Tsi148 [Tempe] + +pci:v000010E3d00000148sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=Tsi148 [Tempe] (VR11 Single Board Computer) + +pci:v000010E3d00000860* + ID_MODEL_FROM_DATABASE=CA91C860 [QSpan] + +pci:v000010E3d00000862* + ID_MODEL_FROM_DATABASE=CA91C862A [QSpan-II] + +pci:v000010E3d00008111* + ID_MODEL_FROM_DATABASE=Tsi381 PCIe to PCI Bridge + +pci:v000010E3d00008260* + ID_MODEL_FROM_DATABASE=CA91L8200B [Dual PCI PowerSpan II] + +pci:v000010E3d00008261* + ID_MODEL_FROM_DATABASE=CA91L8260B [Single PCI PowerSpan II] + +pci:v000010E3d0000A108* + ID_MODEL_FROM_DATABASE=Tsi109 Host Bridge for Dual PowerPC + +pci:v000010E4* + ID_VENDOR_FROM_DATABASE=Tandem Computers + +pci:v000010E4d00008029* + ID_MODEL_FROM_DATABASE=Realtek 8029 Network Card + +pci:v000010E5* + ID_VENDOR_FROM_DATABASE=Micro Industries Corporation + +pci:v000010E6* + ID_VENDOR_FROM_DATABASE=Gainbery Computer Products Inc. + +pci:v000010E7* + ID_VENDOR_FROM_DATABASE=Vadem + +pci:v000010E8* + ID_VENDOR_FROM_DATABASE=Applied Micro Circuits Corp. + +pci:v000010E8d00001072* + ID_MODEL_FROM_DATABASE=INES GPIB-PCI (AMCC5920 based) + +pci:v000010E8d00002011* + ID_MODEL_FROM_DATABASE=Q-Motion Video Capture/Edit board + +pci:v000010E8d00004750* + ID_MODEL_FROM_DATABASE=S5930 [Matchmaker] + +pci:v000010E8d00005920* + ID_MODEL_FROM_DATABASE=S5920 + +pci:v000010E8d00008043* + ID_MODEL_FROM_DATABASE=LANai4.x [Myrinet LANai interface chip] + +pci:v000010E8d00008062* + ID_MODEL_FROM_DATABASE=S5933_PARASTATION + +pci:v000010E8d0000807D* + ID_MODEL_FROM_DATABASE=S5933 [Matchmaker] + +pci:v000010E8d00008088* + ID_MODEL_FROM_DATABASE=Kongsberg Spacetec Format Synchronizer + +pci:v000010E8d00008089* + ID_MODEL_FROM_DATABASE=Kongsberg Spacetec Serial Output Board + +pci:v000010E8d0000809C* + ID_MODEL_FROM_DATABASE=S5933_HEPC3 + +pci:v000010E8d000080B9* + ID_MODEL_FROM_DATABASE=Harmonix Hi-Card P8 (4x active ISDN BRI) + +pci:v000010E8d000080D7* + ID_MODEL_FROM_DATABASE=PCI-9112 + +pci:v000010E8d000080D8* + ID_MODEL_FROM_DATABASE=PCI-7200 + +pci:v000010E8d000080D9* + ID_MODEL_FROM_DATABASE=PCI-9118 + +pci:v000010E8d000080DA* + ID_MODEL_FROM_DATABASE=PCI-9812 + +pci:v000010E8d000080FC* + ID_MODEL_FROM_DATABASE=APCI1500 Signal processing controller (16 dig. inputs + 16 dig. outputs) + +pci:v000010E8d0000811A* + ID_MODEL_FROM_DATABASE=PCI-IEEE1355-DS-DE Interface + +pci:v000010E8d0000814C* + ID_MODEL_FROM_DATABASE=Fastcom ESCC-PCI (Commtech, Inc.) + +pci:v000010E8d00008170* + ID_MODEL_FROM_DATABASE=S5933 [Matchmaker] (Chipset Development Tool) + +pci:v000010E8d000081E6* + ID_MODEL_FROM_DATABASE=Multimedia video controller + +pci:v000010E8d0000828D* + ID_MODEL_FROM_DATABASE=APCI3001 Signal processing controller (up to 16 analog inputs) + +pci:v000010E8d00008291* + ID_MODEL_FROM_DATABASE=Fastcom 232/8-PCI (Commtech, Inc.) + +pci:v000010E8d000082C4* + ID_MODEL_FROM_DATABASE=Fastcom 422/4-PCI (Commtech, Inc.) + +pci:v000010E8d000082C5* + ID_MODEL_FROM_DATABASE=Fastcom 422/2-PCI (Commtech, Inc.) + +pci:v000010E8d000082C6* + ID_MODEL_FROM_DATABASE=Fastcom IG422/1-PCI (Commtech, Inc.) + +pci:v000010E8d000082C7* + ID_MODEL_FROM_DATABASE=Fastcom IG232/2-PCI (Commtech, Inc.) + +pci:v000010E8d000082CA* + ID_MODEL_FROM_DATABASE=Fastcom 232/4-PCI (Commtech, Inc.) + +pci:v000010E8d000082DB* + ID_MODEL_FROM_DATABASE=AJA HDNTV HD SDI Framestore + +pci:v000010E8d000082E2* + ID_MODEL_FROM_DATABASE=Fastcom DIO24H-PCI (Commtech, Inc.) + +pci:v000010E8d00008406* + ID_MODEL_FROM_DATABASE=PCIcanx/PCIcan CAN interface [Kvaser AB] + +pci:v000010E8d00008407* + ID_MODEL_FROM_DATABASE=PCIcan II CAN interface (A1021, PCB-07, PCB-08) [Kvaser AB] + +pci:v000010E8d00008851* + ID_MODEL_FROM_DATABASE=S5933 on Innes Corp FM Radio Capture card + +pci:v000010E8d0000E004* + ID_MODEL_FROM_DATABASE=X-Gene PCIe bridge + +pci:v000010E9* + ID_VENDOR_FROM_DATABASE=Alps Electric Co., Ltd. + +pci:v000010EA* + ID_VENDOR_FROM_DATABASE=Integraphics + +pci:v000010EAd00001680* + ID_MODEL_FROM_DATABASE=IGA-1680 + +pci:v000010EAd00001682* + ID_MODEL_FROM_DATABASE=IGA-1682 + +pci:v000010EAd00001683* + ID_MODEL_FROM_DATABASE=IGA-1683 + +pci:v000010EAd00002000* + ID_MODEL_FROM_DATABASE=CyberPro 2000 + +pci:v000010EAd00002010* + ID_MODEL_FROM_DATABASE=CyberPro 2000A + +pci:v000010EAd00005000* + ID_MODEL_FROM_DATABASE=CyberPro 5000 + +pci:v000010EAd00005050* + ID_MODEL_FROM_DATABASE=CyberPro 5050 + +pci:v000010EAd00005202* + ID_MODEL_FROM_DATABASE=CyberPro 5202 + +pci:v000010EAd00005252* + ID_MODEL_FROM_DATABASE=CyberPro5252 + +pci:v000010EB* + ID_VENDOR_FROM_DATABASE=Artists Graphics + +pci:v000010EBd00000101* + ID_MODEL_FROM_DATABASE=3GA + +pci:v000010EBd00008111* + ID_MODEL_FROM_DATABASE=Twist3 Frame Grabber + +pci:v000010EC* + ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Co., Ltd. + +pci:v000010ECd00000139* + ID_MODEL_FROM_DATABASE=RTL-8139/8139C/8139C+ Ethernet Controller + +pci:v000010ECd00005208* + ID_MODEL_FROM_DATABASE=RTS5208 PCI Express Card Reader + +pci:v000010ECd00005209* + ID_MODEL_FROM_DATABASE=RTS5209 PCI Express Card Reader + +pci:v000010ECd00005227* + ID_MODEL_FROM_DATABASE=RTS5227 PCI Express Card Reader + +pci:v000010ECd00005227sv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=RTS5227 PCI Express Card Reader (ThinkPad T440p) + +pci:v000010ECd00005227sv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=RTS5227 PCI Express Card Reader (ThinkPad X240) + +pci:v000010ECd00005229* + ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader + +pci:v000010ECd00005229sv00001025sd00000813* + ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader (Aspire R7-571) + +pci:v000010ECd00005229sv0000103Csd0000194E* + ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader (ProBook 455 G1 Notebook) + +pci:v000010ECd00005229sv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader (Pavilion 17-e163sg Notebook PC) + +pci:v000010ECd00005229sv000017AAsd00003832* + ID_MODEL_FROM_DATABASE=RTS5229 PCI Express Card Reader (Yoga 520) + +pci:v000010ECd0000522A* + ID_MODEL_FROM_DATABASE=RTS522A PCI Express Card Reader + +pci:v000010ECd0000522Asv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=RTS522A PCI Express Card Reader (EliteBook 840 G3) + +pci:v000010ECd00005249* + ID_MODEL_FROM_DATABASE=RTS5249 PCI Express Card Reader + +pci:v000010ECd00005249sv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=RTS5249 PCI Express Card Reader (ZBook 15) + +pci:v000010ECd0000524A* + ID_MODEL_FROM_DATABASE=RTS524A PCI Express Card Reader + +pci:v000010ECd00005250* + ID_MODEL_FROM_DATABASE=RTS5250 PCI Express Card Reader + +pci:v000010ECd0000525A* + ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader + +pci:v000010ECd0000525Asv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader (Latitude E7470) + +pci:v000010ECd0000525Asv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader (XPS 15 9550) + +pci:v000010ECd0000525Asv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=RTS525A PCI Express Card Reader (ThinkPad X1 Carbon 5th Gen) + +pci:v000010ECd00005260* + ID_MODEL_FROM_DATABASE=RTS5260 PCI Express Card Reader + +pci:v000010ECd00005286* + ID_MODEL_FROM_DATABASE=RTS5286 PCI Express Card Reader + +pci:v000010ECd00005287* + ID_MODEL_FROM_DATABASE=RTL8411B PCI Express Card Reader + +pci:v000010ECd00005288* + ID_MODEL_FROM_DATABASE=RTS5288 PCI Express Card Reader + +pci:v000010ECd00005289* + ID_MODEL_FROM_DATABASE=RTL8411 PCI Express Card Reader + +pci:v000010ECd00005289sv00001043sd00001457* + ID_MODEL_FROM_DATABASE=RTL8411 PCI Express Card Reader (K55A Laptop) + +pci:v000010ECd00008029* + ID_MODEL_FROM_DATABASE=RTL-8029(AS) + +pci:v000010ECd00008029sv000010B8sd00002011* + ID_MODEL_FROM_DATABASE=RTL-8029(AS) (EZ-Card (SMC1208)) + +pci:v000010ECd00008029sv000010ECsd00008029* + ID_MODEL_FROM_DATABASE=RTL-8029(AS) + +pci:v000010ECd00008029sv00001113sd00001208* + ID_MODEL_FROM_DATABASE=RTL-8029(AS) (EN1208) + +pci:v000010ECd00008029sv00001186sd00000300* + ID_MODEL_FROM_DATABASE=RTL-8029(AS) (DE-528) + +pci:v000010ECd00008029sv00001259sd00002400* + ID_MODEL_FROM_DATABASE=RTL-8029(AS) (AT-2400) + +pci:v000010ECd00008029sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=RTL-8029(AS) (QEMU Virtual Machine) + +pci:v000010ECd00008125* + ID_MODEL_FROM_DATABASE=RTL8125 2.5GbE Controller + +pci:v000010ECd00008129* + ID_MODEL_FROM_DATABASE=RTL-8129 + +pci:v000010ECd00008129sv000010ECsd00008129* + ID_MODEL_FROM_DATABASE=RTL-8129 (RT8129 Fast Ethernet Adapter) + +pci:v000010ECd00008129sv000011ECsd00008129* + ID_MODEL_FROM_DATABASE=RTL-8129 (RTL8111/8168 PCIe Gigabit Ethernet (misconfigured)) + +pci:v000010ECd00008136* + ID_MODEL_FROM_DATABASE=RTL810xE PCI Express Fast Ethernet controller + +pci:v000010ECd00008136sv0000103Csd00001985* + ID_MODEL_FROM_DATABASE=RTL810xE PCI Express Fast Ethernet controller (RTL8106E on Pavilion 17-e163sg Notebook PC) + +pci:v000010ECd00008136sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=RTL810xE PCI Express Fast Ethernet controller (Compaq 500B Microtower) + +pci:v000010ECd00008136sv0000103Csd00002AB1* + ID_MODEL_FROM_DATABASE=RTL810xE PCI Express Fast Ethernet controller (Pavilion p6774) + +pci:v000010ECd00008136sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=RTL810xE PCI Express Fast Ethernet controller (Pavilion dv6700) + +pci:v000010ECd00008136sv00001179sd0000FF64* + ID_MODEL_FROM_DATABASE=RTL810xE PCI Express Fast Ethernet controller (RTL8102E PCI-E Fast Ethernet NIC) + +pci:v000010ECd00008136sv000017C0sd00001053* + ID_MODEL_FROM_DATABASE=RTL810xE PCI Express Fast Ethernet controller (RTL8101e Medion WIM 2210 Notebook PC [MD96850]) + +pci:v000010ECd00008137* + ID_MODEL_FROM_DATABASE=RTL8104E PCIe Fast Ethernet Controller + +pci:v000010ECd00008138* + ID_MODEL_FROM_DATABASE=RT8139 (B/C) Cardbus Fast Ethernet Adapter + +pci:v000010ECd00008138sv000010ECsd00008138* + ID_MODEL_FROM_DATABASE=RT8139 (B/C) Cardbus Fast Ethernet Adapter (RT8139 (B/C) Fast Ethernet Adapter) + +pci:v000010ECd00008139* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter + +pci:v000010ECd00008139sv00000357sd0000000A* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (TTP-Monitoring Card V2.0) + +pci:v000010ECd00008139sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (TravelMate 290) + +pci:v000010ECd00008139sv00001025sd00008920* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (ALN-325) + +pci:v000010ECd00008139sv00001025sd00008921* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (ALN-325) + +pci:v000010ECd00008139sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (NX9500) + +pci:v000010ECd00008139sv0000103Csd00002A20* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Pavilion t3030.de Desktop PC) + +pci:v000010ECd00008139sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Presario C700) + +pci:v000010ECd00008139sv00001043sd00001045* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (L8400B, L3C/S, X58LE notebook) + +pci:v000010ECd00008139sv00001043sd00008109* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (P5P800-MX Mainboard) + +pci:v000010ECd00008139sv00001071sd00008160* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (MIM2000) + +pci:v000010ECd00008139sv000010BDsd00000320* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (EP-320X-R) + +pci:v000010ECd00008139sv000010ECsd00008139* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter + +pci:v000010ECd00008139sv000010F7sd00008338* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Panasonic CF-Y5 laptop) + +pci:v000010ECd00008139sv00001113sd0000EC01* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (LevelOne FNC-0107TX/FNC-0109TX) + +pci:v000010ECd00008139sv00001186sd00001104* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (DFE-520TX Fast Ethernet PCI Adapter (rev. D1)) + +pci:v000010ECd00008139sv00001186sd00001300* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (DFE-538TX) + +pci:v000010ECd00008139sv00001186sd00001320* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (SN5200) + +pci:v000010ECd00008139sv00001186sd00008139* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (DRN-32TX) + +pci:v000010ECd00008139sv000011F6sd00008139* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (FN22-3(A) LinxPRO Ethernet Adapter) + +pci:v000010ECd00008139sv00001259sd00002500* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (AT-2500TX) + +pci:v000010ECd00008139sv00001259sd00002503* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (AT-2500TX/ACPI) + +pci:v000010ECd00008139sv00001385sd0000F31D* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (FA311 v2) + +pci:v000010ECd00008139sv00001395sd00002100* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (AMB2100) + +pci:v000010ECd00008139sv00001429sd0000D010* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (ND010/ND012) + +pci:v000010ECd00008139sv00001432sd00009130* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (EN-9130TX) + +pci:v000010ECd00008139sv00001436sd00008139* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (RT8139) + +pci:v000010ECd00008139sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (P30/P35 notebook) + +pci:v000010ECd00008139sv00001458sd0000E000* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (GA-7VM400M/7VT600 Motherboard) + +pci:v000010ECd00008139sv00001462sd00000131* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (MS-1013 Notebook) + +pci:v000010ECd00008139sv00001462sd0000217C* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Aspire L250) + +pci:v000010ECd00008139sv00001462sd0000788C* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (865PE Neo2-V Mainboard) + +pci:v000010ECd00008139sv0000146Csd00001439* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (FE-1439TX) + +pci:v000010ECd00008139sv00001489sd00006001* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (GF100TXRII) + +pci:v000010ECd00008139sv00001489sd00006002* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (GF100TXRA) + +pci:v000010ECd00008139sv0000149Csd0000139A* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (LFE-8139ATX) + +pci:v000010ECd00008139sv0000149Csd00008139* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (LFE-8139TX) + +pci:v000010ECd00008139sv000014CBsd00000200* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (LNR-100 Family 10/100 Base-TX Ethernet) + +pci:v000010ECd00008139sv00001565sd00002300* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (P4TSV Onboard LAN (RTL8100B)) + +pci:v000010ECd00008139sv00001631sd00007003* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Onboard RTL8111 on GA-8SIML Rev1.0 Mainboard) + +pci:v000010ECd00008139sv00001695sd00009001* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (Onboard RTL8101L 10/100 MBit) + +pci:v000010ECd00008139sv000016ECsd000000FF* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (USR997900A) + +pci:v000010ECd00008139sv00001799sd00005000* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (F5D5000 PCI Card/Desktop Network PCI Card) + +pci:v000010ECd00008139sv00001799sd00005010* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (F5D5010 CardBus Notebook Network Card) + +pci:v000010ECd00008139sv0000187Esd00003303* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (FN312) + +pci:v000010ECd00008139sv00001904sd00008139* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (RTL8139D Fast Ethernet Adapter) + +pci:v000010ECd00008139sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (QEMU Virtual Machine) + +pci:v000010ECd00008139sv00002646sd00000001* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (KNE120TX) + +pci:v000010ECd00008139sv00008E2Esd00007000* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (KF-230TX) + +pci:v000010ECd00008139sv00008E2Esd00007100* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (KF-230TX/2) + +pci:v000010ECd00008139sv0000A0A0sd00000007* + ID_MODEL_FROM_DATABASE=RTL-8100/8101L/8139 PCI Fast Ethernet Adapter (ALN-325C) + +pci:v000010ECd00008167* + ID_MODEL_FROM_DATABASE=RTL-8110SC/8169SC Gigabit Ethernet + +pci:v000010ECd00008167sv0000105Bsd00000E10* + ID_MODEL_FROM_DATABASE=RTL-8110SC/8169SC Gigabit Ethernet (RTL-8110SC-GR on a N15235/A74MX mainboard) + +pci:v000010ECd00008167sv00001458sd0000E000* + ID_MODEL_FROM_DATABASE=RTL-8110SC/8169SC Gigabit Ethernet (GA-MA69G-S3H Motherboard) + +pci:v000010ECd00008167sv00001462sd0000235C* + ID_MODEL_FROM_DATABASE=RTL-8110SC/8169SC Gigabit Ethernet (P965 Neo MS-7235 mainboard) + +pci:v000010ECd00008167sv00001462sd0000236C* + ID_MODEL_FROM_DATABASE=RTL-8110SC/8169SC Gigabit Ethernet (945P Neo3-F motherboard) + +pci:v000010ECd00008168* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller + +pci:v000010ECd00008168sv00001019sd00008168* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (RTL8111/8168 PCI Express Gigabit Ethernet controller) + +pci:v000010ECd00008168sv00001028sd00000283* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Vostro 220) + +pci:v000010ECd00008168sv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Vostro 3350) + +pci:v000010ECd00008168sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Vostro 3750) + +pci:v000010ECd00008168sv00001028sd000006F2* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Latitude 3470) + +pci:v000010ECd00008168sv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Latitude 3570) + +pci:v000010ECd00008168sv0000103Csd00001611* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Pavilion DM1Z-3000) + +pci:v000010ECd00008168sv0000103Csd00001950* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (ProBook 450/455) + +pci:v000010ECd00008168sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Asus IPIBL-LB Motherboard) + +pci:v000010ECd00008168sv0000103Csd00008615* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Pavilion Laptop 15-cw1xxx) + +pci:v000010ECd00008168sv00001043sd000011F5* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Notebook motherboard (one of many models)) + +pci:v000010ECd00008168sv00001043sd000016D5* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (U6V/U31J laptop) + +pci:v000010ECd00008168sv00001043sd000081AA* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (P5B) + +pci:v000010ECd00008168sv00001043sd000082C6* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (M3A78 Series Motherboard) + +pci:v000010ECd00008168sv00001043sd000083A3* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (M4A785/P7P55 Motherboard) + +pci:v000010ECd00008168sv00001043sd00008432* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (P8P67 and other motherboards) + +pci:v000010ECd00008168sv00001043sd00008505* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (P8 series motherboard) + +pci:v000010ECd00008168sv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (D270S/D250S Motherboard) + +pci:v000010ECd00008168sv000010ECsd00008168* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (RTL8111/8168 PCI Express Gigabit Ethernet controller) + +pci:v000010ECd00008168sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (RTL8168 on a NP300E5C series laptop) + +pci:v000010ECd00008168sv00001458sd0000E000* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Onboard Ethernet) + +pci:v000010ECd00008168sv00001462sd0000238C* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Onboard RTL8111b on MSI P965 Platinum Mainboard) + +pci:v000010ECd00008168sv00001462sd0000345C* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (RTL8111B on MS-7345 Motherboard) + +pci:v000010ECd00008168sv00001462sd0000368C* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (K9AG Neo2) + +pci:v000010ECd00008168sv00001462sd00004180* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Wind PC MS-7418) + +pci:v000010ECd00008168sv00001462sd00007522* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (X58 Pro-E) + +pci:v000010ECd00008168sv00001462sd00007C37* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (X570-A PRO motherboard) + +pci:v000010ECd00008168sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (CC11/CL11) + +pci:v000010ECd00008168sv00001849sd00008168* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Motherboard (one of many)) + +pci:v000010ECd00008168sv00007470sd00003468* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (TG-3468 Gigabit PCI Express Network Adapter) + +pci:v000010ECd00008168sv00008086sd00002055* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (NUC Kit DN2820FYKH) + +pci:v000010ECd00008168sv00008086sd0000D615* + ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Desktop Board D510MO/D525MW) + +pci:v000010ECd00008169* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller + +pci:v000010ECd00008169sv00001025sd00000079* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (Aspire 5024WLMi) + +pci:v000010ECd00008169sv000010BDsd00003202* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (EP-320G-TX1 32-bit PCI Gigabit Ethernet Adapter) + +pci:v000010ECd00008169sv000010ECsd00008169* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (RTL8169/8110 Family PCI Gigabit Ethernet NIC) + +pci:v000010ECd00008169sv00001259sd0000C107* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (CG-LAPCIGT) + +pci:v000010ECd00008169sv00001371sd0000434E* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (ProG-2000L) + +pci:v000010ECd00008169sv00001385sd0000311A* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (GA311) + +pci:v000010ECd00008169sv00001385sd00005200* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (GA511 Gigabit PC Card) + +pci:v000010ECd00008169sv00001458sd0000E000* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (GA-8I915ME-G Mainboard) + +pci:v000010ECd00008169sv00001462sd0000030C* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (K8N Neo-FSR v2.0 mainboard) + +pci:v000010ECd00008169sv00001462sd0000065C* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (Hetis 865GV-E (MS-7065)) + +pci:v000010ECd00008169sv00001462sd0000702C* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (K8T NEO 2 motherboard) + +pci:v000010ECd00008169sv00001462sd00007094* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (K8T Neo2-F V2.0) + +pci:v000010ECd00008169sv000016ECsd0000011F* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (USR997903) + +pci:v000010ECd00008169sv00001734sd00001091* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (D2030-A1) + +pci:v000010ECd00008169sv0000A0A0sd00000449* + ID_MODEL_FROM_DATABASE=RTL8169 PCI Gigabit Ethernet Controller (AK86-L motherboard) + +pci:v000010ECd00008171* + ID_MODEL_FROM_DATABASE=RTL8191SEvA Wireless LAN Controller + +pci:v000010ECd00008172* + ID_MODEL_FROM_DATABASE=RTL8191SEvB Wireless LAN Controller + +pci:v000010ECd00008173* + ID_MODEL_FROM_DATABASE=RTL8192SE Wireless LAN Controller + +pci:v000010ECd00008174* + ID_MODEL_FROM_DATABASE=RTL8192SE Wireless LAN Controller + +pci:v000010ECd00008176* + ID_MODEL_FROM_DATABASE=RTL8188CE 802.11b/g/n WiFi Adapter + +pci:v000010ECd00008176sv00001043sd000084B5* + ID_MODEL_FROM_DATABASE=RTL8188CE 802.11b/g/n WiFi Adapter (PCE-N10) + +pci:v000010ECd00008176sv00001A3Bsd00001139* + ID_MODEL_FROM_DATABASE=RTL8188CE 802.11b/g/n WiFi Adapter (AW-NE139H Half-size Mini PCIe Card) + +pci:v000010ECd00008177* + ID_MODEL_FROM_DATABASE=RTL8191CE PCIe Wireless Network Adapter + +pci:v000010ECd00008178* + ID_MODEL_FROM_DATABASE=RTL8192CE PCIe Wireless Network Adapter + +pci:v000010ECd00008179* + ID_MODEL_FROM_DATABASE=RTL8188EE Wireless Network Adapter + +pci:v000010ECd00008179sv0000103Csd0000197D* + ID_MODEL_FROM_DATABASE=RTL8188EE Wireless Network Adapter (RTL8188EE mini-PCIe card) + +pci:v000010ECd00008180* + ID_MODEL_FROM_DATABASE=RTL8180L 802.11b MAC + +pci:v000010ECd00008180sv00001385sd00004700* + ID_MODEL_FROM_DATABASE=RTL8180L 802.11b MAC (MA521 802.11b Wireless PC Card) + +pci:v000010ECd00008180sv00001737sd00000019* + ID_MODEL_FROM_DATABASE=RTL8180L 802.11b MAC (WPC11v4 802.11b Wireless-B Notebook Adapter) + +pci:v000010ECd00008185* + ID_MODEL_FROM_DATABASE=RTL-8185 IEEE 802.11a/b/g Wireless LAN Controller + +pci:v000010ECd0000818B* + ID_MODEL_FROM_DATABASE=RTL8192EE PCIe Wireless Network Adapter + +pci:v000010ECd00008190* + ID_MODEL_FROM_DATABASE=RTL8190 802.11n PCI Wireless Network Adapter + +pci:v000010ECd00008191* + ID_MODEL_FROM_DATABASE=RTL8192CE PCIe Wireless Network Adapter + +pci:v000010ECd00008192* + ID_MODEL_FROM_DATABASE=RTL8192E/RTL8192SE Wireless LAN Controller + +pci:v000010ECd00008193* + ID_MODEL_FROM_DATABASE=RTL8192DE Wireless LAN Controller + +pci:v000010ECd00008196* + ID_MODEL_FROM_DATABASE=RTL8196 Integrated PCI-e Bridge + +pci:v000010ECd00008197* + ID_MODEL_FROM_DATABASE=SmartLAN56 56K Modem + +pci:v000010ECd00008199* + ID_MODEL_FROM_DATABASE=RTL8187SE Wireless LAN Controller + +pci:v000010ECd00008199sv00001462sd00006894* + ID_MODEL_FROM_DATABASE=RTL8187SE Wireless LAN Controller (MN54G2 / MS-6894 Wireless Mini PCIe Card) + +pci:v000010ECd00008723* + ID_MODEL_FROM_DATABASE=RTL8723AE PCIe Wireless Network Adapter + +pci:v000010ECd00008812* + ID_MODEL_FROM_DATABASE=RTL8812AE 802.11ac PCIe Wireless Network Adapter + +pci:v000010ECd00008813* + ID_MODEL_FROM_DATABASE=RTL8813AE 802.11ac PCIe Wireless Network Adapter + +pci:v000010ECd00008821* + ID_MODEL_FROM_DATABASE=RTL8821AE 802.11ac PCIe Wireless Network Adapter + +pci:v000010ECd0000B723* + ID_MODEL_FROM_DATABASE=RTL8723BE PCIe Wireless Network Adapter + +pci:v000010ECd0000B723sv000010ECsd00008739* + ID_MODEL_FROM_DATABASE=RTL8723BE PCIe Wireless Network Adapter (Dell Wireless 1801) + +pci:v000010ECd0000B822* + ID_MODEL_FROM_DATABASE=RTL8822BE 802.11a/b/g/n/ac WiFi adapter + +pci:v000010ECd0000B822sv0000103Csd0000831B* + ID_MODEL_FROM_DATABASE=RTL8822BE 802.11a/b/g/n/ac WiFi adapter (Realtek RTL8822BE 802.11ac 2 × 2 Wi-Fi + Bluetooth 4.2 Combo Adapter (MU-MIMO supported)) + +pci:v000010ECd0000C821* + ID_MODEL_FROM_DATABASE=RTL8821CE 802.11ac PCIe Wireless Network Adapter + +pci:v000010ECd0000C822* + ID_MODEL_FROM_DATABASE=RTL8822CE 802.11ac PCIe Wireless Network Adapter + +pci:v000010ECd0000D723* + ID_MODEL_FROM_DATABASE=RTL8723DE 802.11b/g/n PCIe Adapter + +pci:v000010ED* + ID_VENDOR_FROM_DATABASE=Ascii Corporation + +pci:v000010EDd00007310* + ID_MODEL_FROM_DATABASE=V7310 + +pci:v000010EE* + ID_VENDOR_FROM_DATABASE=Xilinx Corporation + +pci:v000010EEd00000001* + ID_MODEL_FROM_DATABASE=EUROCOM for PCI (ECOMP) + +pci:v000010EEd00000002* + ID_MODEL_FROM_DATABASE=Octal E1/T1 for PCI ETP Card + +pci:v000010EEd00000007* + ID_MODEL_FROM_DATABASE=Default PCIe endpoint ID + +pci:v000010EEd00000205* + ID_MODEL_FROM_DATABASE=Wildcard TE205P + +pci:v000010EEd00000210* + ID_MODEL_FROM_DATABASE=Wildcard TE210P + +pci:v000010EEd00000300* + ID_MODEL_FROM_DATABASE=Spartan 3 Designs (Xilinx IP) + +pci:v000010EEd00000314* + ID_MODEL_FROM_DATABASE=Wildcard TE405P/TE410P (1st Gen) + +pci:v000010EEd00000405* + ID_MODEL_FROM_DATABASE=Wildcard TE405P (2nd Gen) + +pci:v000010EEd00000410* + ID_MODEL_FROM_DATABASE=Wildcard TE410P (2nd Gen) + +pci:v000010EEd00000600* + ID_MODEL_FROM_DATABASE=Xilinx 6 Designs (Xilinx IP) + +pci:v000010EEd00003FC0* + ID_MODEL_FROM_DATABASE=RME Digi96 + +pci:v000010EEd00003FC1* + ID_MODEL_FROM_DATABASE=RME Digi96/8 + +pci:v000010EEd00003FC2* + ID_MODEL_FROM_DATABASE=RME Digi96/8 Pro + +pci:v000010EEd00003FC3* + ID_MODEL_FROM_DATABASE=RME Digi96/8 Pad + +pci:v000010EEd00003FC4* + ID_MODEL_FROM_DATABASE=RME Digi9652 (Hammerfall) + +pci:v000010EEd00003FC5* + ID_MODEL_FROM_DATABASE=RME Hammerfall DSP + +pci:v000010EEd00003FC6* + ID_MODEL_FROM_DATABASE=RME Hammerfall DSP MADI + +pci:v000010EEd00007038* + ID_MODEL_FROM_DATABASE=FPGA Card XC7VX690T + +pci:v000010EEd00007038sv000017AAsd0000402F* + ID_MODEL_FROM_DATABASE=FPGA Card XC7VX690T (FPGA XC7VX690T-3FFG1157E) + +pci:v000010EEd00008380* + ID_MODEL_FROM_DATABASE=Ellips ProfiXpress Profibus Master + +pci:v000010EEd00008381* + ID_MODEL_FROM_DATABASE=Ellips Santos Frame Grabber + +pci:v000010EEd0000D154* + ID_MODEL_FROM_DATABASE=Copley Controls CAN card (PCI-CAN-02) + +pci:v000010EEd0000EBF0* + ID_MODEL_FROM_DATABASE=SED Systems Modulator/Demodulator + +pci:v000010EEd0000EBF1* + ID_MODEL_FROM_DATABASE=SED Systems Audio Interface Card + +pci:v000010EEd0000EBF2* + ID_MODEL_FROM_DATABASE=SED Systems Common PCI Interface + +pci:v000010EEd0000EBF3* + ID_MODEL_FROM_DATABASE=SED Systems PCIe-AXI Bridge + +pci:v000010EF* + ID_VENDOR_FROM_DATABASE=Racore Computer Products, Inc. + +pci:v000010EFd00008154* + ID_MODEL_FROM_DATABASE=M815x Token Ring Adapter + +pci:v000010F0* + ID_VENDOR_FROM_DATABASE=Peritek Corporation + +pci:v000010F1* + ID_VENDOR_FROM_DATABASE=Tyan Computer + +pci:v000010F1d00002865* + ID_MODEL_FROM_DATABASE=Tyan Thunder K8E S2865 + +pci:v000010F1d00005300* + ID_MODEL_FROM_DATABASE=Tyan S5380 Mainboard + +pci:v000010F2* + ID_VENDOR_FROM_DATABASE=Achme Computer, Inc. + +pci:v000010F3* + ID_VENDOR_FROM_DATABASE=Alaris, Inc. + +pci:v000010F4* + ID_VENDOR_FROM_DATABASE=S-MOS Systems, Inc. + +pci:v000010F5* + ID_VENDOR_FROM_DATABASE=NKK Corporation + +pci:v000010F5d0000A001* + ID_MODEL_FROM_DATABASE=NDR4000 [NR4600 Bridge] + +pci:v000010F6* + ID_VENDOR_FROM_DATABASE=Creative Electronic Systems SA + +pci:v000010F7* + ID_VENDOR_FROM_DATABASE=Matsushita Electric Industrial Co., Ltd. + +pci:v000010F8* + ID_VENDOR_FROM_DATABASE=Altos India Ltd + +pci:v000010F9* + ID_VENDOR_FROM_DATABASE=PC Direct + +pci:v000010FA* + ID_VENDOR_FROM_DATABASE=Truevision + +pci:v000010FAd0000000C* + ID_MODEL_FROM_DATABASE=TARGA 1000 + +pci:v000010FB* + ID_VENDOR_FROM_DATABASE=Thesys Gesellschaft fuer Mikroelektronik mbH + +pci:v000010FBd0000186F* + ID_MODEL_FROM_DATABASE=TH 6255 + +pci:v000010FC* + ID_VENDOR_FROM_DATABASE=I-O Data Device, Inc. + +pci:v000010FCd00000003* + ID_MODEL_FROM_DATABASE=Cardbus IDE Controller + +pci:v000010FCd00000005* + ID_MODEL_FROM_DATABASE=Cardbus SCSI CBSC II + +pci:v000010FD* + ID_VENDOR_FROM_DATABASE=Soyo Computer, Inc + +pci:v000010FE* + ID_VENDOR_FROM_DATABASE=Fast Multimedia AG + +pci:v000010FF* + ID_VENDOR_FROM_DATABASE=NCube + +pci:v00001100* + ID_VENDOR_FROM_DATABASE=Jazz Multimedia + +pci:v00001101* + ID_VENDOR_FROM_DATABASE=Initio Corporation + +pci:v00001101d00000002* + ID_MODEL_FROM_DATABASE=INI-920 Ultra SCSI Adapter + +pci:v00001101d00001060* + ID_MODEL_FROM_DATABASE=INI-A100U2W + +pci:v00001101d00001622* + ID_MODEL_FROM_DATABASE=INI-1623 PCI SATA-II Controller + +pci:v00001101d00009100* + ID_MODEL_FROM_DATABASE=INI-9100/9100W + +pci:v00001101d00009400* + ID_MODEL_FROM_DATABASE=INI-940 Fast Wide SCSI Adapter + +pci:v00001101d00009401* + ID_MODEL_FROM_DATABASE=INI-935 Fast Wide SCSI Adapter + +pci:v00001101d00009500* + ID_MODEL_FROM_DATABASE=INI-950 SCSI Adapter + +pci:v00001101d00009502* + ID_MODEL_FROM_DATABASE=INI-950P Ultra Wide SCSI Adapter + +pci:v00001102* + ID_VENDOR_FROM_DATABASE=Creative Labs + +pci:v00001102d00000002* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] + +pci:v00001102d00000002sv0000100Asd00001102* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB Live! 5.1 Digital OEM SB0220 EMU10K1-JFF) + +pci:v00001102d00000002sv00001102sd00000020* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4670/4850 SBLive! Value) + +pci:v00001102d00000002sv00001102sd00000021* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4620 SBLive!) + +pci:v00001102d00000002sv00001102sd0000002F* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (M002/M003 Integrated SBLive!) + +pci:v00001102d00000002sv00001102sd0000100A* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0220/0229 SBLive! 5.1 Digital OEM) + +pci:v00001102d00000002sv00001102sd00004001* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (E-mu APS) + +pci:v00001102d00000002sv00001102sd00008022* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4780 SBLive! Value) + +pci:v00001102d00000002sv00001102sd00008023* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4790 SoundBlaster PCI512) + +pci:v00001102d00000002sv00001102sd00008024* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4760 SBLive!) + +pci:v00001102d00000002sv00001102sd00008025* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT1140/SB0040 Integrated SBLive!) + +pci:v00001102d00000002sv00001102sd00008026* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4830 SBLive! Value) + +pci:v00001102d00000002sv00001102sd00008027* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4832 SBLive! Value) + +pci:v00001102d00000002sv00001102sd00008028* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4870 SBLive! Value) + +pci:v00001102d00000002sv00001102sd00008029* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4872 SBLive! Value) + +pci:v00001102d00000002sv00001102sd0000802A* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4890 SoundBlaster PCI256) + +pci:v00001102d00000002sv00001102sd0000802B* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4891 SoundBlaster PCI256) + +pci:v00001102d00000002sv00001102sd00008031* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4831 SBLive! Value) + +pci:v00001102d00000002sv00001102sd00008032* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4871 SBLive! Value) + +pci:v00001102d00000002sv00001102sd00008033* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4893 SoundBlaster PCI256) + +pci:v00001102d00000002sv00001102sd00008035* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT0060 SBLive!) + +pci:v00001102d00000002sv00001102sd00008040* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4760 SBLive!) + +pci:v00001102d00000002sv00001102sd00008050* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4750 SoundBlaster PCI512) + +pci:v00001102d00000002sv00001102sd00008051* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT4850 SBLive! Value) + +pci:v00001102d00000002sv00001102sd00008061* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB060 SBLive! Player 5.1) + +pci:v00001102d00000002sv00001102sd00008062* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0100 SBLive! 5.1) + +pci:v00001102d00000002sv00001102sd00008063* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (DXW Integrated SBLive! 5.1) + +pci:v00001102d00000002sv00001102sd00008064* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0100/SB0102 SBLive! 5.1) + +pci:v00001102d00000002sv00001102sd00008065* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0220/0222 SBLive! 5.1 Digital) + +pci:v00001102d00000002sv00001102sd00008066* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0228 SBLive! 5.1 Digital) + +pci:v00001102d00000002sv00001102sd00008067* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0220 SBLive! 5.1) + +pci:v00001102d00000002sv00001102sd00008068* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (CT0061 SBLive!) + +pci:v00001102d00000002sv00001102sd00008069* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0101 SBLive! 5.1 Value) + +pci:v00001102d00000002sv00001102sd0000806A* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0103 SBLive! 5.1) + +pci:v00001102d00000002sv00001102sd0000806B* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0105 SBLive! 5.1) + +pci:v00001102d00000002sv00001102sd0000806C* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0221 SBLive! 5.1) + +pci:v00001102d00000002sv00001102sd00008071* + ID_MODEL_FROM_DATABASE=EMU10k1 [Sound Blaster Live! Series] (SB0150 SoundBlaster PCI512) + +pci:v00001102d00000003* + ID_MODEL_FROM_DATABASE=SB AWE64(D) + +pci:v00001102d00000004* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] + +pci:v00001102d00000004sv00001102sd00000040* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0090 Audigy Player) + +pci:v00001102d00000004sv00001102sd00000041* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (CT4820 SBLive!2) + +pci:v00001102d00000004sv00001102sd00000042* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (CT0070 Audigy) + +pci:v00001102d00000004sv00001102sd00000043* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (CT0072 Audigy) + +pci:v00001102d00000004sv00001102sd00000051* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0090 Audigy Player/Platinum (EX)) + +pci:v00001102d00000004sv00001102sd00000052* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0162 Audigy ES) + +pci:v00001102d00000004sv00001102sd00000053* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (CT0090/SB0092 Audigy Player/OEM) + +pci:v00001102d00000004sv00001102sd00000054* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0161 Audigy ES) + +pci:v00001102d00000004sv00001102sd00000055* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0192 Audigy) + +pci:v00001102d00000004sv00001102sd00000056* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0191 Audigy) + +pci:v00001102d00000004sv00001102sd00000057* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0091 Audigy) + +pci:v00001102d00000004sv00001102sd00000058* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0095 Audigy Player/OEM) + +pci:v00001102d00000004sv00001102sd00000059* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0230 Audigy) + +pci:v00001102d00000004sv00001102sd0000005A* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0231 Audigy) + +pci:v00001102d00000004sv00001102sd0000005B* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0232 Audigy) + +pci:v00001102d00000004sv00001102sd0000005C* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0238 Audigy) + +pci:v00001102d00000004sv00001102sd00001002* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0240 Audigy 2 Platinum 6.1) + +pci:v00001102d00000004sv00001102sd00001003* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0350 Audigy 2 / SB0243 Audigy 2 OEM) + +pci:v00001102d00000004sv00001102sd00001004* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0242 Audigy 2) + +pci:v00001102d00000004sv00001102sd00001005* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0280 Audigy 2 Platinum Ex) + +pci:v00001102d00000004sv00001102sd00001006* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0245 Audigy 2 OEM) + +pci:v00001102d00000004sv00001102sd00001007* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0240/SB0244 Audigy 2 Platinum) + +pci:v00001102d00000004sv00001102sd00001008* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0320 Audigy 2) + +pci:v00001102d00000004sv00001102sd00001009* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0249 Audigy 2 OEM) + +pci:v00001102d00000004sv00001102sd0000100A* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0246 Audigy 2) + +pci:v00001102d00000004sv00001102sd00002001* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0360 Audigy 2 ZS Platinum Pro) + +pci:v00001102d00000004sv00001102sd00002002* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0350 Audigy 2 ZS) + +pci:v00001102d00000004sv00001102sd00002003* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0352 Audigy 2 ZS) + +pci:v00001102d00000004sv00001102sd00002004* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0355 Audigy 2 ZS) + +pci:v00001102d00000004sv00001102sd00002005* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0359 Audigy 2 ZS) + +pci:v00001102d00000004sv00001102sd00002006* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB035x Audigy 2 OEM) + +pci:v00001102d00000004sv00001102sd00002007* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (SB0380 Audigy 4 Pro) + +pci:v00001102d00000004sv00001102sd00004001* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (E-MU 1010 [MAEM8810]) + +pci:v00001102d00000004sv00001102sd00004002* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (E-MU 0404) + +pci:v00001102d00000004sv00001102sd00004003* + ID_MODEL_FROM_DATABASE=EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] (E-MU 1010) + +pci:v00001102d00000005* + ID_MODEL_FROM_DATABASE=EMU20k1 [Sound Blaster X-Fi Series] + +pci:v00001102d00000005sv00001102sd00000021* + ID_MODEL_FROM_DATABASE=EMU20k1 [Sound Blaster X-Fi Series] (X-Fi Platinum) + +pci:v00001102d00000005sv00001102sd0000002C* + ID_MODEL_FROM_DATABASE=EMU20k1 [Sound Blaster X-Fi Series] (X-Fi XtremeGamer FATAL1TY PRO) + +pci:v00001102d00000005sv00001102sd00001003* + ID_MODEL_FROM_DATABASE=EMU20k1 [Sound Blaster X-Fi Series] (X-Fi XtremeMusic) + +pci:v00001102d00000006* + ID_MODEL_FROM_DATABASE=EMU10k1X [SB Live! Value/OEM Series] + +pci:v00001102d00000007* + ID_MODEL_FROM_DATABASE=CA0106/CA0111 [SB Live!/Audigy/X-Fi Series] + +pci:v00001102d00000007sv00001102sd00000007* + ID_MODEL_FROM_DATABASE=CA0106/CA0111 [SB Live!/Audigy/X-Fi Series] (SBLive! 24bit) + +pci:v00001102d00000007sv00001102sd00001001* + ID_MODEL_FROM_DATABASE=CA0106/CA0111 [SB Live!/Audigy/X-Fi Series] (SB0310 Audigy LS) + +pci:v00001102d00000007sv00001102sd00001002* + ID_MODEL_FROM_DATABASE=CA0106/CA0111 [SB Live!/Audigy/X-Fi Series] (SB0312 Audigy LS) + +pci:v00001102d00000007sv00001102sd00001006* + ID_MODEL_FROM_DATABASE=CA0106/CA0111 [SB Live!/Audigy/X-Fi Series] (SB0410 SBLive! 24-bit) + +pci:v00001102d00000007sv00001102sd0000100A* + ID_MODEL_FROM_DATABASE=CA0106/CA0111 [SB Live!/Audigy/X-Fi Series] (SB0570 [SB Audigy SE]) + +pci:v00001102d00000007sv00001102sd00001012* + ID_MODEL_FROM_DATABASE=CA0106/CA0111 [SB Live!/Audigy/X-Fi Series] (SB0790 X-Fi XA) + +pci:v00001102d00000007sv00001102sd00001013* + ID_MODEL_FROM_DATABASE=CA0106/CA0111 [SB Live!/Audigy/X-Fi Series] (Soundblaster X-Fi Xtreme Audio) + +pci:v00001102d00000007sv00001462sd00001009* + ID_MODEL_FROM_DATABASE=CA0106/CA0111 [SB Live!/Audigy/X-Fi Series] (K8N Diamond) + +pci:v00001102d00000008* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] + +pci:v00001102d00000008sv00001102sd00000008* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (EMU0404 Digital Audio System) + +pci:v00001102d00000008sv00001102sd00001001* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (SB0400 Audigy 2 Value) + +pci:v00001102d00000008sv00001102sd00001021* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (SB0610 Audigy 4 Value) + +pci:v00001102d00000008sv00001102sd00001022* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (SBxxx Audigy 2/4 Value) + +pci:v00001102d00000008sv00001102sd00001023* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (SB0612 Audigy 2 LS) + +pci:v00001102d00000008sv00001102sd00001024* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (SB1550 Audigy 5/Rx) + +pci:v00001102d00000008sv00001102sd00001101* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (SBxxxx Audigy 2 SA) + +pci:v00001102d00000008sv00001102sd00002001* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (SB0530 Audigy 2 ZS Notebook) + +pci:v00001102d00000008sv00001102sd00002021* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (SBxxxx Audigy 4 Notebook) + +pci:v00001102d00000008sv00001102sd00004002* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (E-MU 0404) + +pci:v00001102d00000008sv00001102sd00004003* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (E-MU 1010) + +pci:v00001102d00000008sv00001102sd00004004* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (EMU1010 Digital Audio System [MAEM8960]) + +pci:v00001102d00000008sv00001102sd00004005* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (E-MU 0404 [MAEM8984]) + +pci:v00001102d00000008sv00001102sd00004007* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (E-MU 1010 [MAEM8982]) + +pci:v00001102d00000008sv00001102sd00004201* + ID_MODEL_FROM_DATABASE=CA0108/CA10300 [Sound Blaster Audigy Series] (E-MU 0202 [MAEM8950]) + +pci:v00001102d00000009* + ID_MODEL_FROM_DATABASE=CA0110 [Sound Blaster X-Fi Xtreme Audio] + +pci:v00001102d00000009sv00001102sd00000010* + ID_MODEL_FROM_DATABASE=CA0110 [Sound Blaster X-Fi Xtreme Audio] (MB0820 Integrated) + +pci:v00001102d00000009sv00001102sd00000018* + ID_MODEL_FROM_DATABASE=CA0110 [Sound Blaster X-Fi Xtreme Audio] (SB1040 PCI Express) + +pci:v00001102d0000000B* + ID_MODEL_FROM_DATABASE=EMU20k2 [Sound Blaster X-Fi Titanium Series] + +pci:v00001102d0000000Bsv00001102sd00000041* + ID_MODEL_FROM_DATABASE=EMU20k2 [Sound Blaster X-Fi Titanium Series] (SB0880 [SoundBlaster X-Fi Titanium PCI-e]) + +pci:v00001102d0000000Bsv00001102sd00000062* + ID_MODEL_FROM_DATABASE=EMU20k2 [Sound Blaster X-Fi Titanium Series] (SB1270 [SoundBlaster X-Fi Titanium HD]) + +pci:v00001102d00000012* + ID_MODEL_FROM_DATABASE=Sound Core3D [Sound Blaster Recon3D / Z-Series] + +pci:v00001102d00000012sv00001102sd00000010* + ID_MODEL_FROM_DATABASE=Sound Core3D [Sound Blaster Recon3D / Z-Series] (SB1570 SB Audigy Fx) + +pci:v00001102d00004001* + ID_MODEL_FROM_DATABASE=SB Audigy FireWire Port + +pci:v00001102d00004001sv00001102sd00000010* + ID_MODEL_FROM_DATABASE=SB Audigy FireWire Port + +pci:v00001102d00007002* + ID_MODEL_FROM_DATABASE=SB Live! Game Port + +pci:v00001102d00007002sv00001102sd00000020* + ID_MODEL_FROM_DATABASE=SB Live! Game Port (Gameport Joystick) + +pci:v00001102d00007003* + ID_MODEL_FROM_DATABASE=SB Audigy Game Port + +pci:v00001102d00007003sv00001102sd00000040* + ID_MODEL_FROM_DATABASE=SB Audigy Game Port + +pci:v00001102d00007003sv00001102sd00000060* + ID_MODEL_FROM_DATABASE=SB Audigy Game Port (SB Audigy2 MIDI/Game Port) + +pci:v00001102d00007004* + ID_MODEL_FROM_DATABASE=[SB Live! Value] Input device controller + +pci:v00001102d00007005* + ID_MODEL_FROM_DATABASE=SB Audigy LS Game Port + +pci:v00001102d00007005sv00001102sd00001001* + ID_MODEL_FROM_DATABASE=SB Audigy LS Game Port (SB0310 Audigy LS MIDI/Game port) + +pci:v00001102d00007005sv00001102sd00001002* + ID_MODEL_FROM_DATABASE=SB Audigy LS Game Port (SB0312 Audigy LS MIDI/Game port) + +pci:v00001102d00007006* + ID_MODEL_FROM_DATABASE=[SB X-Fi Xtreme Audio] CA0110-IBG PCIe to PCI Bridge + +pci:v00001102d00008938* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 + +pci:v00001102d00008938sv00001033sd000080E5* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (SlimTower-Jim (NEC)) + +pci:v00001102d00008938sv00001071sd00007150* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Mitac 7150) + +pci:v00001102d00008938sv0000110Asd00005938* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Siemens Scenic Mobile 510PIII) + +pci:v00001102d00008938sv000013BDsd0000100C* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Ceres-C (Sharp, Intel BX)) + +pci:v00001102d00008938sv000013BDsd0000100D* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Sharp, Intel Banister) + +pci:v00001102d00008938sv000013BDsd0000100E* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (TwinHead P09S/P09S3 (Sharp)) + +pci:v00001102d00008938sv000013BDsd0000F6F1* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Marlin (Sharp)) + +pci:v00001102d00008938sv000014FFsd00000E70* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (P88TE (TWINHEAD INTERNATIONAL Corp)) + +pci:v00001102d00008938sv000014FFsd0000C401* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (Notebook 9100/9200/2000 (TWINHEAD INTERNATIONAL Corp)) + +pci:v00001102d00008938sv0000156Dsd0000B400* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G400 - Geo (AlphaTop (Taiwan))) + +pci:v00001102d00008938sv0000156Dsd0000B550* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G560 (AlphaTop (Taiwan))) + +pci:v00001102d00008938sv0000156Dsd0000B560* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G560 (AlphaTop (Taiwan))) + +pci:v00001102d00008938sv0000156Dsd0000B700* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G700/U700 (AlphaTop (Taiwan))) + +pci:v00001102d00008938sv0000156Dsd0000B795* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G795 (AlphaTop (Taiwan))) + +pci:v00001102d00008938sv0000156Dsd0000B797* + ID_MODEL_FROM_DATABASE=Ectiva EV1938 (G797 (AlphaTop (Taiwan))) + +pci:v00001103* + ID_VENDOR_FROM_DATABASE=HighPoint Technologies, Inc. + +pci:v00001103d00000003* + ID_MODEL_FROM_DATABASE=HPT343/345/346/363 + +pci:v00001103d00000004* + ID_MODEL_FROM_DATABASE=HPT366/368/370/370A/372/372N + +pci:v00001103d00000004sv00001103sd00000001* + ID_MODEL_FROM_DATABASE=HPT366/368/370/370A/372/372N (HPT370A) + +pci:v00001103d00000004sv00001103sd00000004* + ID_MODEL_FROM_DATABASE=HPT366/368/370/370A/372/372N (HPT366 UDMA66 (r1) / HPT368 UDMA66 (r2) / HPT370 UDMA100 (r3) / HPT370 UDMA100 RAID (r4)) + +pci:v00001103d00000004sv00001103sd00000005* + ID_MODEL_FROM_DATABASE=HPT366/368/370/370A/372/372N (HPT370 UDMA100) + +pci:v00001103d00000004sv00001103sd00000006* + ID_MODEL_FROM_DATABASE=HPT366/368/370/370A/372/372N (HPT302/302N) + +pci:v00001103d00000005* + ID_MODEL_FROM_DATABASE=HPT372A/372N + +pci:v00001103d00000006* + ID_MODEL_FROM_DATABASE=HPT302/302N + +pci:v00001103d00000007* + ID_MODEL_FROM_DATABASE=HPT371/371N + +pci:v00001103d00000008* + ID_MODEL_FROM_DATABASE=HPT374 + +pci:v00001103d00000009* + ID_MODEL_FROM_DATABASE=HPT372N + +pci:v00001103d00000620* + ID_MODEL_FROM_DATABASE=RocketRAID 620 2 Port SATA-III Controller + +pci:v00001103d00000622* + ID_MODEL_FROM_DATABASE=RocketRAID 622 2 Port SATA-III Controller + +pci:v00001103d00000640* + ID_MODEL_FROM_DATABASE=RocketRAID 640 4 Port SATA-III Controller + +pci:v00001103d00000641* + ID_MODEL_FROM_DATABASE=RocketRAID 640L 4 Port SATA-III Controller + +pci:v00001103d00000642* + ID_MODEL_FROM_DATABASE=RocketRAID 642L SATA-III Controller (2 eSATA ports + 2 internal SATA ports) + +pci:v00001103d00000644* + ID_MODEL_FROM_DATABASE=RocketRAID 644 4 Port SATA-III Controller (eSATA) + +pci:v00001103d00000645* + ID_MODEL_FROM_DATABASE=RocketRAID 644L 4 Port SATA-III Controller (eSATA) + +pci:v00001103d00000646* + ID_MODEL_FROM_DATABASE=RocketRAID 644LS SATA-III Controller (4 eSATA devices connected by 1 SAS cable) + +pci:v00001103d00001720* + ID_MODEL_FROM_DATABASE=RocketRAID 1720 (2x SATA II RAID Controller) + +pci:v00001103d00001740* + ID_MODEL_FROM_DATABASE=RocketRAID 1740 + +pci:v00001103d00001742* + ID_MODEL_FROM_DATABASE=RocketRAID 1742 + +pci:v00001103d00002210* + ID_MODEL_FROM_DATABASE=RocketRAID 2210 SATA-II Controller + +pci:v00001103d00002210sv000011ABsd000011AB* + ID_MODEL_FROM_DATABASE=RocketRAID 2210 SATA-II Controller (88SX6042) + +pci:v00001103d00002300* + ID_MODEL_FROM_DATABASE=RocketRAID 230x 4 Port SATA-II Controller + +pci:v00001103d00002310* + ID_MODEL_FROM_DATABASE=RocketRAID 2310 4 Port SATA-II Controller + +pci:v00001103d00002320* + ID_MODEL_FROM_DATABASE=RocketRAID 2320 SATA-II Controller + +pci:v00001103d00002322* + ID_MODEL_FROM_DATABASE=RocketRAID 2322 SATA-II Controller + +pci:v00001103d00002340* + ID_MODEL_FROM_DATABASE=RocketRAID 2340 16 Port SATA-II Controller + +pci:v00001103d00002640* + ID_MODEL_FROM_DATABASE=RocketRAID 2640 SAS/SATA Controller + +pci:v00001103d00002722* + ID_MODEL_FROM_DATABASE=RocketRAID 2722 + +pci:v00001103d00002740* + ID_MODEL_FROM_DATABASE=RocketRAID 2740 + +pci:v00001103d00002744* + ID_MODEL_FROM_DATABASE=RocketRaid 2744 + +pci:v00001103d00002782* + ID_MODEL_FROM_DATABASE=RocketRAID 2782 + +pci:v00001103d00003120* + ID_MODEL_FROM_DATABASE=RocketRAID 3120 + +pci:v00001103d00003220* + ID_MODEL_FROM_DATABASE=RocketRAID 3220 + +pci:v00001103d00003320* + ID_MODEL_FROM_DATABASE=RocketRAID 3320 + +pci:v00001103d00004310* + ID_MODEL_FROM_DATABASE=RocketRaid 4310 + +pci:v00001104* + ID_VENDOR_FROM_DATABASE=RasterOps Corp. + +pci:v00001105* + ID_VENDOR_FROM_DATABASE=Sigma Designs, Inc. + +pci:v00001105d00001105* + ID_MODEL_FROM_DATABASE=REALmagic Xcard MPEG 1/2/3/4 DVD Decoder + +pci:v00001105d00008300* + ID_MODEL_FROM_DATABASE=REALmagic Hollywood Plus DVD Decoder + +pci:v00001105d00008400* + ID_MODEL_FROM_DATABASE=EM840x REALmagic DVD/MPEG-2 Audio/Video Decoder + +pci:v00001105d00008401* + ID_MODEL_FROM_DATABASE=EM8401 REALmagic DVD/MPEG-2 A/V Decoder + +pci:v00001105d00008470* + ID_MODEL_FROM_DATABASE=EM8470 REALmagic DVD/MPEG-4 A/V Decoder + +pci:v00001105d00008471* + ID_MODEL_FROM_DATABASE=EM8471 REALmagic DVD/MPEG-4 A/V Decoder + +pci:v00001105d00008475* + ID_MODEL_FROM_DATABASE=EM8475 REALmagic DVD/MPEG-4 A/V Decoder + +pci:v00001105d00008475sv00001105sd00000001* + ID_MODEL_FROM_DATABASE=EM8475 REALmagic DVD/MPEG-4 A/V Decoder (REALmagic X-Card) + +pci:v00001105d00008476* + ID_MODEL_FROM_DATABASE=EM8476 REALmagic DVD/MPEG-4 A/V Decoder + +pci:v00001105d00008476sv0000127Dsd00000000* + ID_MODEL_FROM_DATABASE=EM8476 REALmagic DVD/MPEG-4 A/V Decoder (CineView II) + +pci:v00001105d00008485* + ID_MODEL_FROM_DATABASE=EM8485 REALmagic DVD/MPEG-4 A/V Decoder + +pci:v00001105d00008486* + ID_MODEL_FROM_DATABASE=EM8486 REALmagic DVD/MPEG-4 A/V Decoder + +pci:v00001105d0000C621* + ID_MODEL_FROM_DATABASE=EM8621L Digital Media Processor + +pci:v00001105d0000C622* + ID_MODEL_FROM_DATABASE=EM8622L MPEG-4.10 (H.264) and SMPTE 421M (VC-1) A/V Decoder + +pci:v00001106* + ID_VENDOR_FROM_DATABASE=VIA Technologies, Inc. + +pci:v00001106d00000102* + ID_MODEL_FROM_DATABASE=Embedded VIA Ethernet Controller + +pci:v00001106d00000130* + ID_MODEL_FROM_DATABASE=VT6305 1394.A Controller + +pci:v00001106d00000198* + ID_MODEL_FROM_DATABASE=P4X600 Host Bridge + +pci:v00001106d00000204* + ID_MODEL_FROM_DATABASE=K8M800 Host Bridge + +pci:v00001106d00000208* + ID_MODEL_FROM_DATABASE=PT890 Host Bridge + +pci:v00001106d00000238* + ID_MODEL_FROM_DATABASE=K8T890 Host Bridge + +pci:v00001106d00000258* + ID_MODEL_FROM_DATABASE=PT880 Host Bridge + +pci:v00001106d00000259* + ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 Host Bridge + +pci:v00001106d00000269* + ID_MODEL_FROM_DATABASE=KT880 Host Bridge + +pci:v00001106d00000282* + ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge + +pci:v00001106d00000282sv00001043sd000080A3* + ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge (A8V Deluxe) + +pci:v00001106d00000290* + ID_MODEL_FROM_DATABASE=K8M890 Host Bridge + +pci:v00001106d00000293* + ID_MODEL_FROM_DATABASE=PM896 Host Bridge + +pci:v00001106d00000296* + ID_MODEL_FROM_DATABASE=P4M800 Host Bridge + +pci:v00001106d00000305* + ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] + +pci:v00001106d00000305sv00001019sd00000987* + ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] (K7VZA Mainboard) + +pci:v00001106d00000305sv00001043sd00008033* + ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] (A7V Mainboard) + +pci:v00001106d00000305sv00001043sd0000803E* + ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] (A7V-E Mainboard) + +pci:v00001106d00000305sv00001043sd00008042* + ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] (A7V133/A7V133-C Mainboard) + +pci:v00001106d00000305sv0000147Bsd0000A401* + ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] (KT7/KT7-RAID/KT7A/KT7A-RAID Mainboard) + +pci:v00001106d00000308* + ID_MODEL_FROM_DATABASE=PT880 Ultra/PT894 Host Bridge + +pci:v00001106d00000308sv00001043sd00008199* + ID_MODEL_FROM_DATABASE=PT880 Ultra/PT894 Host Bridge (P4V800D-X Mainboard) + +pci:v00001106d00000308sv00001849sd00000308* + ID_MODEL_FROM_DATABASE=PT880 Ultra/PT894 Host Bridge (Motherboard) + +pci:v00001106d00000314* + ID_MODEL_FROM_DATABASE=CN700/VN800/P4M800CE/Pro Host Bridge + +pci:v00001106d00000324* + ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge + +pci:v00001106d00000327* + ID_MODEL_FROM_DATABASE=P4M890 Host Bridge + +pci:v00001106d00000336* + ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge + +pci:v00001106d00000340* + ID_MODEL_FROM_DATABASE=PT900 Host Bridge + +pci:v00001106d00000351* + ID_MODEL_FROM_DATABASE=K8T890CF Host Bridge + +pci:v00001106d00000353* + ID_MODEL_FROM_DATABASE=VX800 Host Bridge + +pci:v00001106d00000364* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge + +pci:v00001106d00000364sv00001043sd000081CE* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge (P5VD2-VM mothervoard) + +pci:v00001106d00000391* + ID_MODEL_FROM_DATABASE=VT8371 [KX133] + +pci:v00001106d00000409* + ID_MODEL_FROM_DATABASE=VX855/VX875 Host Bridge: Host Control + +pci:v00001106d00000410* + ID_MODEL_FROM_DATABASE=VX900 Host Bridge: Host Control + +pci:v00001106d00000415* + ID_MODEL_FROM_DATABASE=VT6415 PATA IDE Host Controller + +pci:v00001106d00000415sv00001043sd0000838F* + ID_MODEL_FROM_DATABASE=VT6415 PATA IDE Host Controller (Motherboard) + +pci:v00001106d00000501* + ID_MODEL_FROM_DATABASE=VT8501 [Apollo MVP4] + +pci:v00001106d00000505* + ID_MODEL_FROM_DATABASE=VT82C505 + +pci:v00001106d00000561* + ID_MODEL_FROM_DATABASE=VT82C576MV + +pci:v00001106d00000571* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE + +pci:v00001106d00000571sv00001019sd00000985* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (P6VXA Motherboard) + +pci:v00001106d00000571sv00001019sd00000A81* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (L7VTA v1.0 Motherboard (KT400-8235)) + +pci:v00001106d00000571sv00001043sd00008052* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (VT8233A Bus Master ATA100/66/33 IDE) + +pci:v00001106d00000571sv00001043sd0000808C* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (A7V8X / A7V333 motherboard) + +pci:v00001106d00000571sv00001043sd000080A1* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (A7V8X-X motherboard rev. 1.01) + +pci:v00001106d00000571sv00001043sd000080ED* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (A7V600/K8V-X/A8V Deluxe motherboard) + +pci:v00001106d00000571sv00001106sd00000571* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (VT82C586/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE) + +pci:v00001106d00000571sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (Magnia Z310) + +pci:v00001106d00000571sv00001297sd0000F641* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (FX41 motherboard) + +pci:v00001106d00000571sv00001458sd00005002* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (GA-7VAX Mainboard) + +pci:v00001106d00000571sv00001462sd00005901* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (KT6 Delta-FIS2R (MS-6590)) + +pci:v00001106d00000571sv00001462sd00007020* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (K8T NEO 2 motherboard) + +pci:v00001106d00000571sv00001462sd00007094* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (K8T Neo2-F V2.0) + +pci:v00001106d00000571sv00001462sd00007120* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (KT4AV motherboard) + +pci:v00001106d00000571sv00001462sd00007181* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (K8MM3-V mainboard) + +pci:v00001106d00000571sv0000147Bsd00001407* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (KV8-MAX3 motherboard) + +pci:v00001106d00000571sv00001849sd00000571* + ID_MODEL_FROM_DATABASE=VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE (K7VT series Motherboards) + +pci:v00001106d00000576* + ID_MODEL_FROM_DATABASE=VT82C576 3V [Apollo Master] + +pci:v00001106d00000581* + ID_MODEL_FROM_DATABASE=CX700/VX700 RAID Controller + +pci:v00001106d00000581sv00001106sd00000581* + ID_MODEL_FROM_DATABASE=CX700/VX700 RAID Controller (Wrong IDE ID) + +pci:v00001106d00000585* + ID_MODEL_FROM_DATABASE=VT82C585VP [Apollo VP1/VPX] + +pci:v00001106d00000586* + ID_MODEL_FROM_DATABASE=VT82C586/A/B PCI-to-ISA [Apollo VP] + +pci:v00001106d00000586sv00001106sd00000000* + ID_MODEL_FROM_DATABASE=VT82C586/A/B PCI-to-ISA [Apollo VP] (MVP3 ISA Bridge) + +pci:v00001106d00000591* + ID_MODEL_FROM_DATABASE=VT8237A SATA 2-Port Controller + +pci:v00001106d00000595* + ID_MODEL_FROM_DATABASE=VT82C595 [Apollo VP2] + +pci:v00001106d00000596* + ID_MODEL_FROM_DATABASE=VT82C596 ISA [Mobile South] + +pci:v00001106d00000596sv00001106sd00000000* + ID_MODEL_FROM_DATABASE=VT82C596 ISA [Mobile South] (VT82C596/A/B PCI to ISA Bridge) + +pci:v00001106d00000596sv00001458sd00000596* + ID_MODEL_FROM_DATABASE=VT82C596 ISA [Mobile South] (VT82C596/A/B PCI to ISA Bridge) + +pci:v00001106d00000597* + ID_MODEL_FROM_DATABASE=VT82C597 [Apollo VP3] + +pci:v00001106d00000598* + ID_MODEL_FROM_DATABASE=VT82C598 [Apollo MVP3] + +pci:v00001106d00000601* + ID_MODEL_FROM_DATABASE=VT8601 [Apollo ProMedia] + +pci:v00001106d00000605* + ID_MODEL_FROM_DATABASE=VT8605 [ProSavage PM133] + +pci:v00001106d00000605sv0000103Csd00001254* + ID_MODEL_FROM_DATABASE=VT8605 [ProSavage PM133] (D9840-60001 [Brio BA410 Motherboard]) + +pci:v00001106d00000605sv00001043sd0000802C* + ID_MODEL_FROM_DATABASE=VT8605 [ProSavage PM133] (CUV4X mainboard) + +pci:v00001106d00000680* + ID_MODEL_FROM_DATABASE=VT82C680 [Apollo P6] + +pci:v00001106d00000686* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] + +pci:v00001106d00000686sv00001019sd00000985* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (P6VXA Motherboard) + +pci:v00001106d00000686sv0000103Csd00001256* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (D9840-60001 [Brio BA410 Motherboard]) + +pci:v00001106d00000686sv00001043sd0000802C* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (CUV4X mainboard) + +pci:v00001106d00000686sv00001043sd00008033* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (A7V Mainboard) + +pci:v00001106d00000686sv00001043sd0000803E* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (A7V-E Mainboard) + +pci:v00001106d00000686sv00001043sd00008040* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (A7M266 Mainboard) + +pci:v00001106d00000686sv00001043sd00008042* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (A7V133/A7V133-C Mainboard) + +pci:v00001106d00000686sv00001106sd00000000* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (VT82C686/A PCI to ISA Bridge) + +pci:v00001106d00000686sv00001106sd00000686* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (VT82C686/A PCI to ISA Bridge) + +pci:v00001106d00000686sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (Magnia Z310) + +pci:v00001106d00000686sv0000147Bsd0000A702* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super South] (KG7-Lite Mainboard) + +pci:v00001106d00000691* + ID_MODEL_FROM_DATABASE=VT82C693A/694x [Apollo PRO133x] + +pci:v00001106d00000691sv00001019sd00000985* + ID_MODEL_FROM_DATABASE=VT82C693A/694x [Apollo PRO133x] (P6VXA Motherboard) + +pci:v00001106d00000691sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=VT82C693A/694x [Apollo PRO133x] (Magnia Z310) + +pci:v00001106d00000691sv00001458sd00000691* + ID_MODEL_FROM_DATABASE=VT82C693A/694x [Apollo PRO133x] (VT82C691 Apollo Pro System Controller) + +pci:v00001106d00000693* + ID_MODEL_FROM_DATABASE=VT82C693 [Apollo Pro Plus] + +pci:v00001106d00000698* + ID_MODEL_FROM_DATABASE=VT82C693A [Apollo Pro133 AGP] + +pci:v00001106d00000709* + ID_MODEL_FROM_DATABASE=VX11 Standard Host Bridge + +pci:v00001106d0000070A* + ID_MODEL_FROM_DATABASE=VX11 PCI Express Root Port + +pci:v00001106d0000070B* + ID_MODEL_FROM_DATABASE=VX11 PCI Express Root Port + +pci:v00001106d0000070C* + ID_MODEL_FROM_DATABASE=VX11 PCI Express Root Port + +pci:v00001106d0000070D* + ID_MODEL_FROM_DATABASE=VX11 PCI Express Root Port + +pci:v00001106d0000070E* + ID_MODEL_FROM_DATABASE=VX11 PCI Express Root Port + +pci:v00001106d00000926* + ID_MODEL_FROM_DATABASE=VT82C926 [Amazon] + +pci:v00001106d00001000* + ID_MODEL_FROM_DATABASE=VT82C570MV + +pci:v00001106d00001106* + ID_MODEL_FROM_DATABASE=VT82C570MV + +pci:v00001106d00001122* + ID_MODEL_FROM_DATABASE=VX800/VX820 Chrome 9 HC3 Integrated Graphics + +pci:v00001106d00001204* + ID_MODEL_FROM_DATABASE=K8M800 Host Bridge + +pci:v00001106d00001208* + ID_MODEL_FROM_DATABASE=PT890 Host Bridge + +pci:v00001106d00001238* + ID_MODEL_FROM_DATABASE=K8T890 Host Bridge + +pci:v00001106d00001258* + ID_MODEL_FROM_DATABASE=PT880 Host Bridge + +pci:v00001106d00001259* + ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 Host Bridge + +pci:v00001106d00001269* + ID_MODEL_FROM_DATABASE=KT880 Host Bridge + +pci:v00001106d00001282* + ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge + +pci:v00001106d00001290* + ID_MODEL_FROM_DATABASE=K8M890 Host Bridge + +pci:v00001106d00001293* + ID_MODEL_FROM_DATABASE=PM896 Host Bridge + +pci:v00001106d00001296* + ID_MODEL_FROM_DATABASE=P4M800 Host Bridge + +pci:v00001106d00001308* + ID_MODEL_FROM_DATABASE=PT894 Host Bridge + +pci:v00001106d00001314* + ID_MODEL_FROM_DATABASE=CN700/VN800/P4M800CE/Pro Host Bridge + +pci:v00001106d00001324* + ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge + +pci:v00001106d00001327* + ID_MODEL_FROM_DATABASE=P4M890 Host Bridge + +pci:v00001106d00001336* + ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge + +pci:v00001106d00001340* + ID_MODEL_FROM_DATABASE=PT900 Host Bridge + +pci:v00001106d00001351* + ID_MODEL_FROM_DATABASE=VT3351 Host Bridge + +pci:v00001106d00001353* + ID_MODEL_FROM_DATABASE=VX800/VX820 Error Reporting + +pci:v00001106d00001364* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge + +pci:v00001106d00001409* + ID_MODEL_FROM_DATABASE=VX855/VX875 Error Reporting + +pci:v00001106d00001410* + ID_MODEL_FROM_DATABASE=VX900 Error Reporting + +pci:v00001106d00001571* + ID_MODEL_FROM_DATABASE=VT82C576M/VT82C586 + +pci:v00001106d00001595* + ID_MODEL_FROM_DATABASE=VT82C595/97 [Apollo VP2/97] + +pci:v00001106d00001732* + ID_MODEL_FROM_DATABASE=VT1732 [Envy24 II] PCI Multi-Channel Audio Controller + +pci:v00001106d00002106* + ID_MODEL_FROM_DATABASE=VIA Rhine Family Fast Ethernet Adapter (VT6105) + +pci:v00001106d00002204* + ID_MODEL_FROM_DATABASE=K8M800 Host Bridge + +pci:v00001106d00002208* + ID_MODEL_FROM_DATABASE=PT890 Host Bridge + +pci:v00001106d00002238* + ID_MODEL_FROM_DATABASE=K8T890 Host Bridge + +pci:v00001106d00002258* + ID_MODEL_FROM_DATABASE=PT880 Host Bridge + +pci:v00001106d00002259* + ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 CPU Host Bridge + +pci:v00001106d00002269* + ID_MODEL_FROM_DATABASE=KT880 Host Bridge + +pci:v00001106d00002282* + ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge + +pci:v00001106d00002290* + ID_MODEL_FROM_DATABASE=K8M890 Host Bridge + +pci:v00001106d00002293* + ID_MODEL_FROM_DATABASE=PM896 Host Bridge + +pci:v00001106d00002296* + ID_MODEL_FROM_DATABASE=P4M800 Host Bridge + +pci:v00001106d00002308* + ID_MODEL_FROM_DATABASE=PT894 Host Bridge + +pci:v00001106d00002314* + ID_MODEL_FROM_DATABASE=CN700/VN800/P4M800CE/Pro Host Bridge + +pci:v00001106d00002324* + ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge + +pci:v00001106d00002327* + ID_MODEL_FROM_DATABASE=P4M890 Host Bridge + +pci:v00001106d00002336* + ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge + +pci:v00001106d00002340* + ID_MODEL_FROM_DATABASE=PT900 Host Bridge + +pci:v00001106d00002351* + ID_MODEL_FROM_DATABASE=VT3351 Host Bridge + +pci:v00001106d00002353* + ID_MODEL_FROM_DATABASE=VX800/VX820 Host Bus Control + +pci:v00001106d00002364* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge + +pci:v00001106d00002409* + ID_MODEL_FROM_DATABASE=VX855/VX875 Host Bus Control + +pci:v00001106d00002410* + ID_MODEL_FROM_DATABASE=VX900 CPU Bus Controller + +pci:v00001106d0000287A* + ID_MODEL_FROM_DATABASE=VT8251 PCI to PCI Bridge + +pci:v00001106d0000287B* + ID_MODEL_FROM_DATABASE=VT8251 Host Bridge + +pci:v00001106d0000287C* + ID_MODEL_FROM_DATABASE=VT8251 PCIE Root Port + +pci:v00001106d0000287D* + ID_MODEL_FROM_DATABASE=VT8251 PCIE Root Port + +pci:v00001106d0000287E* + ID_MODEL_FROM_DATABASE=VT8237/8251 Ultra VLINK Controller + +pci:v00001106d00003022* + ID_MODEL_FROM_DATABASE=CLE266 + +pci:v00001106d00003038* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller + +pci:v00001106d00003038sv00000925sd00001234* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (onboard UHCI USB 1.1 Controller) + +pci:v00001106d00003038sv00001019sd00000985* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (P6VXA Motherboard) + +pci:v00001106d00003038sv00001019sd00000A81* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (L7VTA v1.0 Motherboard (KT400-8235)) + +pci:v00001106d00003038sv00001043sd00008080* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (A7V333 motherboard) + +pci:v00001106d00003038sv00001043sd0000808C* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (VT6202 USB2.0 4 port controller) + +pci:v00001106d00003038sv00001043sd000080A1* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (A7V8X-X motherboard) + +pci:v00001106d00003038sv00001043sd000080ED* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (A7V600/K8V-X/A8V Deluxe motherboard) + +pci:v00001106d00003038sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (Magnia Z310) + +pci:v00001106d00003038sv00001458sd00005004* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (GA-7VAX Mainboard) + +pci:v00001106d00003038sv00001462sd00005901* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (KT6 Delta-FIS2R (MS-6590)) + +pci:v00001106d00003038sv00001462sd00007020* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (K8T NEO 2 motherboard) + +pci:v00001106d00003038sv00001462sd00007094* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (K8T Neo2-F V2.0) + +pci:v00001106d00003038sv00001462sd00007120* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (KT4AV motherboard) + +pci:v00001106d00003038sv00001462sd00007181* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (K8MM3-V mainboard) + +pci:v00001106d00003038sv0000147Bsd00001407* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (KV8-MAX3 motherboard) + +pci:v00001106d00003038sv0000182Dsd0000201D* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (CN-029 USB2.0 4 port PCI Card) + +pci:v00001106d00003038sv00001849sd00003038* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (K7VT series Motherboards) + +pci:v00001106d00003038sv000019DAsd0000A179* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (ZBOX nano VD01) + +pci:v00001106d00003038sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=VT82xx/62xx UHCI USB 1.1 Controller (QEMU Virtual Machine) + +pci:v00001106d00003040* + ID_MODEL_FROM_DATABASE=VT82C586B ACPI + +pci:v00001106d00003043* + ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] + +pci:v00001106d00003043sv000010BDsd00000000* + ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] (VT86C100A Fast Ethernet Adapter) + +pci:v00001106d00003043sv00001106sd00000100* + ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] (VT86C100A Fast Ethernet Adapter) + +pci:v00001106d00003043sv00001186sd00001400* + ID_MODEL_FROM_DATABASE=VT86C100A [Rhine] (DFE-530TX PCI Fast Ethernet Adapter (rev. A)) + +pci:v00001106d00003044* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller + +pci:v00001106d00003044sv00000010sd00000001* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (IEEE 1394 4port DCST 1394-3+1B) + +pci:v00001106d00003044sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (TravelMate 290) + +pci:v00001106d00003044sv0000103Csd00002A20* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (Pavilion t3030.de Desktop PC) + +pci:v00001106d00003044sv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (Media Center PC m7590n) + +pci:v00001106d00003044sv00001043sd0000808A* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (A8V/A8N/P4P800/P5SD2 series motherboard) + +pci:v00001106d00003044sv00001043sd000081FE* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (Motherboard) + +pci:v00001106d00003044sv00001458sd00001000* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (GA-7VT600-1394 Motherboard) + +pci:v00001106d00003044sv00001462sd0000207D* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (K8NGM2 series motherboard) + +pci:v00001106d00003044sv00001462sd0000217D* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (Aspire L250) + +pci:v00001106d00003044sv00001462sd0000590D* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (KT6 Delta-FIS2R (MS-6590)) + +pci:v00001106d00003044sv00001462sd0000702D* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (K8T NEO 2 motherboard) + +pci:v00001106d00003044sv00001462sd0000971D* + ID_MODEL_FROM_DATABASE=VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller (MS-6917) + +pci:v00001106d00003050* + ID_MODEL_FROM_DATABASE=VT82C596 Power Management + +pci:v00001106d00003051* + ID_MODEL_FROM_DATABASE=VT82C596 Power Management + +pci:v00001106d00003053* + ID_MODEL_FROM_DATABASE=VT6105M [Rhine-III] + +pci:v00001106d00003053sv00001186sd00001404* + ID_MODEL_FROM_DATABASE=VT6105M [Rhine-III] (DFE-530TX PCI Fast Ethernet Adapter (rev. D)) + +pci:v00001106d00003057* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] + +pci:v00001106d00003057sv00001019sd00000985* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (P6VXA Motherboard) + +pci:v00001106d00003057sv00001019sd00000987* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (K7VZA Motherboard) + +pci:v00001106d00003057sv00001043sd00008033* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (A7V Mainboard) + +pci:v00001106d00003057sv00001043sd0000803E* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (A7V-E Mainboard) + +pci:v00001106d00003057sv00001043sd00008040* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (A7M266 Mainboard) + +pci:v00001106d00003057sv00001043sd00008042* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (A7V133/A7V133-C Mainboard) + +pci:v00001106d00003057sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=VT82C686 [Apollo Super ACPI] (Magnia Z310) + +pci:v00001106d00003058* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller + +pci:v00001106d00003058sv00000E11sd00000097* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (SoundMax Digital Integrated Audio) + +pci:v00001106d00003058sv00000E11sd0000B194* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (Soundmax integrated digital audio) + +pci:v00001106d00003058sv00001019sd00000985* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (P6VXA Motherboard) + +pci:v00001106d00003058sv00001019sd00000987* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (K7VZA Motherboard) + +pci:v00001106d00003058sv0000103Csd00001251* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (D9840-60001 [Brio BA410 Motherboard]) + +pci:v00001106d00003058sv00001043sd00001106* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (A7V133/A7V133-C Mainboard) + +pci:v00001106d00003058sv00001106sd00004511* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (Onboard Audio on EP7KXA) + +pci:v00001106d00003058sv00001106sd0000AA03* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (VT1612A AC'97 Audio Controller) + +pci:v00001106d00003058sv000011D4sd00005348* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (AD1881A audio) + +pci:v00001106d00003058sv00001458sd00007600* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (Onboard Audio) + +pci:v00001106d00003058sv00001462sd00003091* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (MS-6309 Onboard Audio) + +pci:v00001106d00003058sv00001462sd00003092* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (MS-6309 v2.x Mainboard (VIA VT1611A codec)) + +pci:v00001106d00003058sv00001462sd00003300* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (MS-6330 Onboard Audio) + +pci:v00001106d00003058sv00001462sd00003400* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (MS-6340 (VT8363) motherboard) + +pci:v00001106d00003058sv000015DDsd00007609* + ID_MODEL_FROM_DATABASE=VT82C686 AC97 Audio Controller (Onboard Audio) + +pci:v00001106d00003059* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller + +pci:v00001106d00003059sv00001019sd00000A81* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (L7VTA v1.0 Motherboard (KT400-8235)) + +pci:v00001106d00003059sv00001019sd00001841* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (M811 (VT8367/VT8235/VT6103) [KT333] motherboard) + +pci:v00001106d00003059sv00001019sd00001877* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (K8M800-M2 (V2.0) onboard audio) + +pci:v00001106d00003059sv00001043sd00008095* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (A7V8X Motherboard (Realtek ALC650 codec)) + +pci:v00001106d00003059sv00001043sd000080A1* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (A7V8X-X Motherboard) + +pci:v00001106d00003059sv00001043sd000080B0* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (A7V600/K8V-X/K8V Deluxe motherboard (ADI AD1980 codec [SoundMAX])) + +pci:v00001106d00003059sv00001043sd000080F3* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (SK8V motherboard) + +pci:v00001106d00003059sv00001043sd0000810D* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (P5VD1-X (AD1888 codec [SoundMax])) + +pci:v00001106d00003059sv00001043sd0000812A* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (A8V Deluxe motherboard (Realtek ALC850 codec)) + +pci:v00001106d00003059sv000010ECsd00008168* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (High Definition Audio) + +pci:v00001106d00003059sv00001106sd00003059* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (L7VMM2 Motherboard) + +pci:v00001106d00003059sv00001106sd00004161* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (K7VT2 motherboard) + +pci:v00001106d00003059sv00001106sd00004170* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (PCPartner P4M800-8237R Motherboard) + +pci:v00001106d00003059sv00001106sd00004552* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (Soyo KT-600 Dragon Plus (Realtek ALC 650)) + +pci:v00001106d00003059sv00001297sd0000C160* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (FX41 motherboard (Realtek ALC650 codec)) + +pci:v00001106d00003059sv00001413sd0000147B* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (KV8 Pro motherboard onboard audio) + +pci:v00001106d00003059sv00001458sd0000A002* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (GA-7VAX Onboard Audio (Realtek ALC650)) + +pci:v00001106d00003059sv00001462sd00000080* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (K8T NEO 2 motherboard) + +pci:v00001106d00003059sv00001462sd00003800* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (KT266 onboard audio) + +pci:v00001106d00003059sv00001462sd00005901* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (KT6 Delta-FIS2R (MS-6590)) + +pci:v00001106d00003059sv00001462sd00007181* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (K8MM3-V mainboard) + +pci:v00001106d00003059sv0000147Bsd00001407* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (KV8-MAX3 motherboard) + +pci:v00001106d00003059sv00001695sd0000300C* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (Realtek ALC655 audio on EP-8KRA series mainboard) + +pci:v00001106d00003059sv00001849sd00000850* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (ASRock 775Dual-880 Pro onboard audio (Realtek ALC850)) + +pci:v00001106d00003059sv00001849sd00009739* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (P4VT8 Mainboard (C-Media CMI9739A codec)) + +pci:v00001106d00003059sv00001849sd00009761* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (K7VT series Motherboards) + +pci:v00001106d00003059sv00004005sd00004710* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (MSI K7T266 Pro2-RU (MSI-6380 v2) onboard audio (Realtek/ALC 200/200P)) + +pci:v00001106d00003059sv0000A0A0sd000001B6* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (AK77-8XN onboard audio) + +pci:v00001106d00003059sv0000A0A0sd00000342* + ID_MODEL_FROM_DATABASE=VT8233/A/8235/8237 AC97 Audio Controller (AK86-L motherboard) + +pci:v00001106d00003065* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] + +pci:v00001106d00003065sv00001043sd000080A1* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (A7V8X-X Motherboard) + +pci:v00001106d00003065sv00001043sd000080ED* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (A7V600-X Motherboard) + +pci:v00001106d00003065sv00001106sd00000102* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (VT6102/6103 [Rhine II] Ethernet Controller) + +pci:v00001106d00003065sv00001186sd00001400* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX PCI Fast Ethernet Adapter (rev. A)) + +pci:v00001106d00003065sv00001186sd00001401* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX PCI Fast Ethernet Adapter (rev. B)) + +pci:v00001106d00003065sv00001186sd00001402* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (DFE-530TX PCI Fast Ethernet Adapter (rev. B)) + +pci:v00001106d00003065sv000013B9sd00001421* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (LD-10/100AL PCI Fast Ethernet Adapter (rev.B)) + +pci:v00001106d00003065sv00001462sd00007061* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (MS-7061) + +pci:v00001106d00003065sv00001462sd00007181* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (K8MM3-V mainboard) + +pci:v00001106d00003065sv0000147Bsd00001C09* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (NV7 Motherboard) + +pci:v00001106d00003065sv00001695sd00003005* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (VT6103) + +pci:v00001106d00003065sv00001849sd00003065* + ID_MODEL_FROM_DATABASE=VT6102/VT6103 [Rhine-II] (K7VT series Motherboards) + +pci:v00001106d00003068* + ID_MODEL_FROM_DATABASE=AC'97 Modem Controller + +pci:v00001106d00003068sv00001462sd0000309E* + ID_MODEL_FROM_DATABASE=AC'97 Modem Controller (MS-6309 Saturn Motherboard) + +pci:v00001106d00003074* + ID_MODEL_FROM_DATABASE=VT8233 PCI to ISA Bridge + +pci:v00001106d00003074sv00001043sd00008052* + ID_MODEL_FROM_DATABASE=VT8233 PCI to ISA Bridge (VT8233A) + +pci:v00001106d00003091* + ID_MODEL_FROM_DATABASE=VT8633 [Apollo Pro266] + +pci:v00001106d00003099* + ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333] + +pci:v00001106d00003099sv00001019sd00001841* + ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333] (M811 (VT8367/VT8235/VT6103) [KT333] motherboard) + +pci:v00001106d00003099sv00001043sd00008064* + ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333] (A7V266-E Mainboard) + +pci:v00001106d00003099sv00001043sd0000807F* + ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333] (A7V333 Mainboard) + +pci:v00001106d00003099sv00001849sd00003099* + ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333] (K7VT2 motherboard) + +pci:v00001106d00003101* + ID_MODEL_FROM_DATABASE=VT8653 Host Bridge + +pci:v00001106d00003102* + ID_MODEL_FROM_DATABASE=VT8662 Host Bridge + +pci:v00001106d00003103* + ID_MODEL_FROM_DATABASE=VT8615 Host Bridge + +pci:v00001106d00003104* + ID_MODEL_FROM_DATABASE=USB 2.0 + +pci:v00001106d00003104sv00000925sd00001234* + ID_MODEL_FROM_DATABASE=USB 2.0 (onboard EHCI USB 2.0 Controller) + +pci:v00001106d00003104sv00001019sd00000A81* + ID_MODEL_FROM_DATABASE=USB 2.0 (L7VTA v1.0 Motherboard (KT400-8235)) + +pci:v00001106d00003104sv00001043sd0000808C* + ID_MODEL_FROM_DATABASE=USB 2.0 (A7V8X motherboard) + +pci:v00001106d00003104sv00001043sd000080A1* + ID_MODEL_FROM_DATABASE=USB 2.0 (A7V8X-X motherboard rev 1.01) + +pci:v00001106d00003104sv00001043sd000080ED* + ID_MODEL_FROM_DATABASE=USB 2.0 (A7V600/K8V-X/A8V Deluxe motherboard) + +pci:v00001106d00003104sv00001106sd00003104* + ID_MODEL_FROM_DATABASE=USB 2.0 (Controller) + +pci:v00001106d00003104sv00001297sd0000F641* + ID_MODEL_FROM_DATABASE=USB 2.0 (FX41 motherboard) + +pci:v00001106d00003104sv00001458sd00005004* + ID_MODEL_FROM_DATABASE=USB 2.0 (GA-7VAX Mainboard) + +pci:v00001106d00003104sv00001462sd00005901* + ID_MODEL_FROM_DATABASE=USB 2.0 (KT6 Delta-FIS2R (MS-6590)) + +pci:v00001106d00003104sv00001462sd00007020* + ID_MODEL_FROM_DATABASE=USB 2.0 (K8T NEO 2 motherboard) + +pci:v00001106d00003104sv00001462sd00007094* + ID_MODEL_FROM_DATABASE=USB 2.0 (K8T Neo2-F V2.0) + +pci:v00001106d00003104sv00001462sd00007120* + ID_MODEL_FROM_DATABASE=USB 2.0 (KT4AV motherboard) + +pci:v00001106d00003104sv00001462sd00007181* + ID_MODEL_FROM_DATABASE=USB 2.0 (K8MM3-V mainboard) + +pci:v00001106d00003104sv0000147Bsd00001407* + ID_MODEL_FROM_DATABASE=USB 2.0 (KV8-MAX3 motherboard) + +pci:v00001106d00003104sv0000182Dsd0000201D* + ID_MODEL_FROM_DATABASE=USB 2.0 (CN-029 USB 2.0 4 port PCI Card) + +pci:v00001106d00003104sv00001849sd00003104* + ID_MODEL_FROM_DATABASE=USB 2.0 (K7VT series Motherboards) + +pci:v00001106d00003104sv000019DAsd0000A179* + ID_MODEL_FROM_DATABASE=USB 2.0 (ZBOX nano VD01) + +pci:v00001106d00003106* + ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] + +pci:v00001106d00003106sv00001106sd00000105* + ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (VT6106S [Rhine-III]) + +pci:v00001106d00003106sv00001186sd00001403* + ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-530TX PCI Fast Ethernet Adapter (rev. C)) + +pci:v00001106d00003106sv00001186sd00001405* + ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-520TX Fast Ethernet PCI Adapter) + +pci:v00001106d00003106sv00001186sd00001406* + ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-530TX+ rev F2) + +pci:v00001106d00003106sv00001186sd00001407* + ID_MODEL_FROM_DATABASE=VT6105/VT6106S [Rhine-III] (DFE-538TX) + +pci:v00001106d00003108* + ID_MODEL_FROM_DATABASE=K8M800/K8N800/K8N800A [S3 UniChrome Pro] + +pci:v00001106d00003109* + ID_MODEL_FROM_DATABASE=VT8233C PCI to ISA Bridge + +pci:v00001106d00003112* + ID_MODEL_FROM_DATABASE=VT8361 [KLE133] Host Bridge + +pci:v00001106d00003113* + ID_MODEL_FROM_DATABASE=VPX/VPX2 PCI to PCI Bridge Controller + +pci:v00001106d00003116* + ID_MODEL_FROM_DATABASE=VT8375 [KM266/KL266] Host Bridge + +pci:v00001106d00003116sv00001297sd0000F641* + ID_MODEL_FROM_DATABASE=VT8375 [KM266/KL266] Host Bridge (FX41 motherboard) + +pci:v00001106d00003118* + ID_MODEL_FROM_DATABASE=CN400/PM800/PM880/PN800/PN880 [S3 UniChrome Pro] + +pci:v00001106d00003119* + ID_MODEL_FROM_DATABASE=VT6120/VT6121/VT6122 Gigabit Ethernet Adapter + +pci:v00001106d00003122* + ID_MODEL_FROM_DATABASE=VT8623 [Apollo CLE266] integrated CastleRock graphics + +pci:v00001106d00003123* + ID_MODEL_FROM_DATABASE=VT8623 [Apollo CLE266] + +pci:v00001106d00003128* + ID_MODEL_FROM_DATABASE=VT8753 [P4X266 AGP] + +pci:v00001106d00003133* + ID_MODEL_FROM_DATABASE=VT3133 Host Bridge + +pci:v00001106d00003142* + ID_MODEL_FROM_DATABASE=VT6651 WiFi Adapter, 802.11b + +pci:v00001106d00003147* + ID_MODEL_FROM_DATABASE=VT8233A ISA Bridge + +pci:v00001106d00003147sv00001043sd0000808C* + ID_MODEL_FROM_DATABASE=VT8233A ISA Bridge (A7V333 motherboard) + +pci:v00001106d00003148* + ID_MODEL_FROM_DATABASE=P4M266 Host Bridge + +pci:v00001106d00003149* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller + +pci:v00001106d00003149sv00001043sd000080ED* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (A7V600/K8V Deluxe/K8V-X/A8V Deluxe motherboard) + +pci:v00001106d00003149sv00001458sd0000B003* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (GA-7VM400AM(F) Motherboard) + +pci:v00001106d00003149sv00001462sd00005901* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (KT6 Delta-FIS2R (MS-6590)) + +pci:v00001106d00003149sv00001462sd00007020* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (K8T Neo 2 Motherboard) + +pci:v00001106d00003149sv00001462sd00007094* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (K8T Neo2-F V2.0) + +pci:v00001106d00003149sv00001462sd00007181* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (K8MM3-V mainboard) + +pci:v00001106d00003149sv0000147Bsd00001407* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (KV8-MAX3 motherboard) + +pci:v00001106d00003149sv0000147Bsd00001408* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (KV7) + +pci:v00001106d00003149sv00001849sd00003149* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (K7VT6 motherboard) + +pci:v00001106d00003149sv0000A0A0sd000004AD* + ID_MODEL_FROM_DATABASE=VIA VT6420 SATA RAID Controller (AK86-L motherboard) + +pci:v00001106d00003156* + ID_MODEL_FROM_DATABASE=P/KN266 Host Bridge + +pci:v00001106d00003157* + ID_MODEL_FROM_DATABASE=CX700/VX700 [S3 UniChrome Pro] + +pci:v00001106d00003164* + ID_MODEL_FROM_DATABASE=VT6410 ATA133 RAID controller + +pci:v00001106d00003164sv00001043sd000080F4* + ID_MODEL_FROM_DATABASE=VT6410 ATA133 RAID controller (P4P800 Mainboard Deluxe ATX) + +pci:v00001106d00003164sv00001462sd00007028* + ID_MODEL_FROM_DATABASE=VT6410 ATA133 RAID controller (915P/G Neo2) + +pci:v00001106d00003168* + ID_MODEL_FROM_DATABASE=P4X333/P4X400/PT800 AGP Bridge + +pci:v00001106d00003168sv00001849sd00003168* + ID_MODEL_FROM_DATABASE=P4X333/P4X400/PT800 AGP Bridge (P4VT8 Mainboard) + +pci:v00001106d00003177* + ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge + +pci:v00001106d00003177sv00001019sd00000A81* + ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (L7VTA v1.0 Motherboard (KT400-8235)) + +pci:v00001106d00003177sv00001019sd00001841* + ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (M811 (VT8367/VT8235/VT6103) [KT333] motherboard) + +pci:v00001106d00003177sv00001043sd0000808C* + ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (A7V8X motherboard) + +pci:v00001106d00003177sv00001043sd000080A1* + ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (A7V8X-X motherboard) + +pci:v00001106d00003177sv00001106sd00000000* + ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (KT4AV motherboard) + +pci:v00001106d00003177sv00001297sd0000F641* + ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (FX41 motherboard) + +pci:v00001106d00003177sv00001458sd00005001* + ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (GA-7VAX Mainboard) + +pci:v00001106d00003177sv00001849sd00003177* + ID_MODEL_FROM_DATABASE=VT8235 ISA Bridge (K7VT series Motherboards) + +pci:v00001106d00003178* + ID_MODEL_FROM_DATABASE=ProSavageDDR P4N333 Host Bridge + +pci:v00001106d00003188* + ID_MODEL_FROM_DATABASE=VT8385 [K8T800 AGP] Host Bridge + +pci:v00001106d00003188sv00001043sd000080A3* + ID_MODEL_FROM_DATABASE=VT8385 [K8T800 AGP] Host Bridge (K8V Deluxe/K8V-X motherboard) + +pci:v00001106d00003188sv0000147Bsd00001407* + ID_MODEL_FROM_DATABASE=VT8385 [K8T800 AGP] Host Bridge (KV8-MAX3 motherboard) + +pci:v00001106d00003189* + ID_MODEL_FROM_DATABASE=VT8377 [KT400/KT600 AGP] Host Bridge + +pci:v00001106d00003189sv00001043sd0000807F* + ID_MODEL_FROM_DATABASE=VT8377 [KT400/KT600 AGP] Host Bridge (A7V8X motherboard) + +pci:v00001106d00003189sv00001106sd00000000* + ID_MODEL_FROM_DATABASE=VT8377 [KT400/KT600 AGP] Host Bridge (KT4AV motherboard (KT400A)) + +pci:v00001106d00003189sv00001458sd00005000* + ID_MODEL_FROM_DATABASE=VT8377 [KT400/KT600 AGP] Host Bridge (GA-7VAX Mainboard) + +pci:v00001106d00003189sv00001849sd00003189* + ID_MODEL_FROM_DATABASE=VT8377 [KT400/KT600 AGP] Host Bridge (K7VT series Motherboards) + +pci:v00001106d000031B0* + ID_MODEL_FROM_DATABASE=VX11 Standard Host Bridge + +pci:v00001106d000031B1* + ID_MODEL_FROM_DATABASE=VX11 Standard Host Bridge + +pci:v00001106d000031B2* + ID_MODEL_FROM_DATABASE=VX11 DRAM Controller + +pci:v00001106d000031B3* + ID_MODEL_FROM_DATABASE=VX11 Power Management Controller + +pci:v00001106d000031B4* + ID_MODEL_FROM_DATABASE=VX11 I/O APIC + +pci:v00001106d000031B5* + ID_MODEL_FROM_DATABASE=VX11 Scratch Device + +pci:v00001106d000031B7* + ID_MODEL_FROM_DATABASE=VX11 Standard Host Bridge + +pci:v00001106d000031B8* + ID_MODEL_FROM_DATABASE=VX11 PCI to PCI Bridge + +pci:v00001106d00003204* + ID_MODEL_FROM_DATABASE=K8M800 Host Bridge + +pci:v00001106d00003205* + ID_MODEL_FROM_DATABASE=VT8378 [KM400/A] Chipset Host Bridge + +pci:v00001106d00003205sv00001458sd00005000* + ID_MODEL_FROM_DATABASE=VT8378 [KM400/A] Chipset Host Bridge (GA-7VM400M Motherboard) + +pci:v00001106d00003208* + ID_MODEL_FROM_DATABASE=PT890 Host Bridge + +pci:v00001106d00003213* + ID_MODEL_FROM_DATABASE=VPX/VPX2 PCI to PCI Bridge Controller + +pci:v00001106d00003218* + ID_MODEL_FROM_DATABASE=K8T800M Host Bridge + +pci:v00001106d00003227* + ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] + +pci:v00001106d00003227sv00001043sd000080ED* + ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] (A7V600/K8V-X/A8V Deluxe motherboard) + +pci:v00001106d00003227sv00001106sd00003227* + ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] (DFI KT600-AL / Soltek SL-B9D-FGR Motherboard) + +pci:v00001106d00003227sv00001458sd00005001* + ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] (GA-7VT600 Motherboard) + +pci:v00001106d00003227sv0000147Bsd00001407* + ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] (KV8-MAX3 motherboard) + +pci:v00001106d00003227sv00001849sd00003227* + ID_MODEL_FROM_DATABASE=VT8237 ISA bridge [KT600/K8T800/K8T890 South] (K7VT4 motherboard) + +pci:v00001106d00003230* + ID_MODEL_FROM_DATABASE=K8M890CE/K8N890CE [Chrome 9] + +pci:v00001106d00003238* + ID_MODEL_FROM_DATABASE=K8T890 Host Bridge + +pci:v00001106d00003249* + ID_MODEL_FROM_DATABASE=VT6421 IDE/SATA Controller + +pci:v00001106d00003249sv00001106sd00003249* + ID_MODEL_FROM_DATABASE=VT6421 IDE/SATA Controller + +pci:v00001106d0000324A* + ID_MODEL_FROM_DATABASE=CX700/VX700 PCI to PCI Bridge + +pci:v00001106d0000324B* + ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge + +pci:v00001106d0000324E* + ID_MODEL_FROM_DATABASE=CX700/VX700 Internal Module Bus + +pci:v00001106d00003253* + ID_MODEL_FROM_DATABASE=VT6655 WiFi Adapter, 802.11a/b/g + +pci:v00001106d00003258* + ID_MODEL_FROM_DATABASE=PT880 Host Bridge + +pci:v00001106d00003259* + ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 Host Bridge + +pci:v00001106d00003260* + ID_MODEL_FROM_DATABASE=VIA Chrome9 HC IGP + +pci:v00001106d00003269* + ID_MODEL_FROM_DATABASE=KT880 Host Bridge + +pci:v00001106d00003282* + ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge + +pci:v00001106d00003287* + ID_MODEL_FROM_DATABASE=VT8251 PCI to ISA Bridge + +pci:v00001106d00003288* + ID_MODEL_FROM_DATABASE=VT8237A/VT8251 HDA Controller + +pci:v00001106d00003288sv000019DAsd0000A179* + ID_MODEL_FROM_DATABASE=VT8237A/VT8251 HDA Controller (ZBOX VD01) + +pci:v00001106d00003290* + ID_MODEL_FROM_DATABASE=K8M890 Host Bridge + +pci:v00001106d00003296* + ID_MODEL_FROM_DATABASE=P4M800 Host Bridge + +pci:v00001106d00003324* + ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge + +pci:v00001106d00003327* + ID_MODEL_FROM_DATABASE=P4M890 Host Bridge + +pci:v00001106d00003336* + ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge + +pci:v00001106d00003337* + ID_MODEL_FROM_DATABASE=VT8237A PCI to ISA Bridge + +pci:v00001106d00003340* + ID_MODEL_FROM_DATABASE=PT900 Host Bridge + +pci:v00001106d00003343* + ID_MODEL_FROM_DATABASE=P4M890 [S3 UniChrome Pro] + +pci:v00001106d00003344* + ID_MODEL_FROM_DATABASE=CN700/P4M800 Pro/P4M800 CE/VN800 Graphics [S3 UniChrome Pro] + +pci:v00001106d00003349* + ID_MODEL_FROM_DATABASE=VT8251 AHCI/SATA 4-Port Controller + +pci:v00001106d00003351* + ID_MODEL_FROM_DATABASE=VT3351 Host Bridge + +pci:v00001106d00003353* + ID_MODEL_FROM_DATABASE=VX800 PCI to PCI Bridge + +pci:v00001106d00003364* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge + +pci:v00001106d00003371* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 [Chrome 9 HC] + +pci:v00001106d00003372* + ID_MODEL_FROM_DATABASE=VT8237S PCI to ISA Bridge + +pci:v00001106d0000337A* + ID_MODEL_FROM_DATABASE=VT8237A PCI to PCI Bridge + +pci:v00001106d0000337B* + ID_MODEL_FROM_DATABASE=VT8237A Host Bridge + +pci:v00001106d00003403* + ID_MODEL_FROM_DATABASE=VT6315 Series Firewire Controller + +pci:v00001106d00003403sv00001043sd00008374* + ID_MODEL_FROM_DATABASE=VT6315 Series Firewire Controller (M5A88-V EVO) + +pci:v00001106d00003403sv00001043sd00008384* + ID_MODEL_FROM_DATABASE=VT6315 Series Firewire Controller (P8P67 Deluxe Motherboard) + +pci:v00001106d00003409* + ID_MODEL_FROM_DATABASE=VX855/VX875 DRAM Bus Control + +pci:v00001106d00003410* + ID_MODEL_FROM_DATABASE=VX900 DRAM Bus Control + +pci:v00001106d00003410sv000019DAsd0000A179* + ID_MODEL_FROM_DATABASE=VX900 DRAM Bus Control (ZBOX nano VD01) + +pci:v00001106d00003432* + ID_MODEL_FROM_DATABASE=VL80x xHCI USB 3.0 Controller + +pci:v00001106d00003456* + ID_MODEL_FROM_DATABASE=VX11 Standard Host Bridge + +pci:v00001106d0000345B* + ID_MODEL_FROM_DATABASE=VX11 Miscellaneous Bus + +pci:v00001106d00003483* + ID_MODEL_FROM_DATABASE=VL805 USB 3.0 Host Controller + +pci:v00001106d00003A01* + ID_MODEL_FROM_DATABASE=VX11 Graphics [Chrome 645/640] + +pci:v00001106d00004149* + ID_MODEL_FROM_DATABASE=VIA VT6420 (ATA133) Controller + +pci:v00001106d00004204* + ID_MODEL_FROM_DATABASE=K8M800 Host Bridge + +pci:v00001106d00004208* + ID_MODEL_FROM_DATABASE=PT890 Host Bridge + +pci:v00001106d00004238* + ID_MODEL_FROM_DATABASE=K8T890 Host Bridge + +pci:v00001106d00004258* + ID_MODEL_FROM_DATABASE=PT880 Host Bridge + +pci:v00001106d00004259* + ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 Host Bridge + +pci:v00001106d00004269* + ID_MODEL_FROM_DATABASE=KT880 Host Bridge + +pci:v00001106d00004282* + ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge + +pci:v00001106d00004290* + ID_MODEL_FROM_DATABASE=K8M890 Host Bridge + +pci:v00001106d00004293* + ID_MODEL_FROM_DATABASE=PM896 Host Bridge + +pci:v00001106d00004296* + ID_MODEL_FROM_DATABASE=P4M800 Host Bridge + +pci:v00001106d00004308* + ID_MODEL_FROM_DATABASE=PT894 Host Bridge + +pci:v00001106d00004314* + ID_MODEL_FROM_DATABASE=CN700/VN800/P4M800CE/Pro Host Bridge + +pci:v00001106d00004324* + ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge + +pci:v00001106d00004327* + ID_MODEL_FROM_DATABASE=P4M890 Host Bridge + +pci:v00001106d00004336* + ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge + +pci:v00001106d00004340* + ID_MODEL_FROM_DATABASE=PT900 Host Bridge + +pci:v00001106d00004351* + ID_MODEL_FROM_DATABASE=VT3351 Host Bridge + +pci:v00001106d00004353* + ID_MODEL_FROM_DATABASE=VX800/VX820 Power Management Control + +pci:v00001106d00004364* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge + +pci:v00001106d00004409* + ID_MODEL_FROM_DATABASE=VX855/VX875 Power Management Control + +pci:v00001106d00004410* + ID_MODEL_FROM_DATABASE=VX900 Power Management and Chip Testing Control + +pci:v00001106d00004410sv000019DAsd0000A179* + ID_MODEL_FROM_DATABASE=VX900 Power Management and Chip Testing Control (ZBOX nano VD01) + +pci:v00001106d00005030* + ID_MODEL_FROM_DATABASE=VT82C596 ACPI [Apollo PRO] + +pci:v00001106d00005122* + ID_MODEL_FROM_DATABASE=VX855/VX875 Chrome 9 HCM Integrated Graphics + +pci:v00001106d00005208* + ID_MODEL_FROM_DATABASE=PT890 I/O APIC Interrupt Controller + +pci:v00001106d00005238* + ID_MODEL_FROM_DATABASE=K8T890 I/O APIC Interrupt Controller + +pci:v00001106d00005287* + ID_MODEL_FROM_DATABASE=VT8251 Serial ATA Controller + +pci:v00001106d00005290* + ID_MODEL_FROM_DATABASE=K8M890 I/O APIC Interrupt Controller + +pci:v00001106d00005308* + ID_MODEL_FROM_DATABASE=PT894 I/O APIC Interrupt Controller + +pci:v00001106d00005324* + ID_MODEL_FROM_DATABASE=VX800 Serial ATA and EIDE Controller + +pci:v00001106d00005327* + ID_MODEL_FROM_DATABASE=P4M890 I/O APIC Interrupt Controller + +pci:v00001106d00005336* + ID_MODEL_FROM_DATABASE=K8M890CE I/O APIC Interrupt Controller + +pci:v00001106d00005340* + ID_MODEL_FROM_DATABASE=PT900 I/O APIC Interrupt Controller + +pci:v00001106d00005351* + ID_MODEL_FROM_DATABASE=VT3351 I/O APIC Interrupt Controller + +pci:v00001106d00005353* + ID_MODEL_FROM_DATABASE=VX800/VX820 APIC and Central Traffic Control + +pci:v00001106d00005364* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 I/O APIC Interrupt Controller + +pci:v00001106d00005372* + ID_MODEL_FROM_DATABASE=VT8237/8251 Serial ATA Controller + +pci:v00001106d00005409* + ID_MODEL_FROM_DATABASE=VX855/VX875 APIC and Central Traffic Control + +pci:v00001106d00005410* + ID_MODEL_FROM_DATABASE=VX900 APIC and Central Traffic Control + +pci:v00001106d00006100* + ID_MODEL_FROM_DATABASE=VT85C100A [Rhine II] + +pci:v00001106d00006287* + ID_MODEL_FROM_DATABASE=SATA RAID Controller + +pci:v00001106d00006290* + ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge + +pci:v00001106d00006327* + ID_MODEL_FROM_DATABASE=P4M890 Security Device + +pci:v00001106d00006353* + ID_MODEL_FROM_DATABASE=VX800/VX820 Scratch Registers + +pci:v00001106d00006364* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Security Device + +pci:v00001106d00006409* + ID_MODEL_FROM_DATABASE=VX855/VX875 Scratch Registers + +pci:v00001106d00006410* + ID_MODEL_FROM_DATABASE=VX900 Scratch Registers + +pci:v00001106d00006410sv000019DAsd0000A179* + ID_MODEL_FROM_DATABASE=VX900 Scratch Registers (ZBOX nano VD01) + +pci:v00001106d00007122* + ID_MODEL_FROM_DATABASE=VX900 Graphics [Chrome9 HD] + +pci:v00001106d00007204* + ID_MODEL_FROM_DATABASE=K8M800 Host Bridge + +pci:v00001106d00007205* + ID_MODEL_FROM_DATABASE=KM400/KN400/P4M800 [S3 UniChrome] + +pci:v00001106d00007205sv00001458sd0000D000* + ID_MODEL_FROM_DATABASE=KM400/KN400/P4M800 [S3 UniChrome] (Gigabyte GA-7VM400(A)M(F) Motherboard) + +pci:v00001106d00007205sv00001462sd00007061* + ID_MODEL_FROM_DATABASE=KM400/KN400/P4M800 [S3 UniChrome] (MS-7061) + +pci:v00001106d00007208* + ID_MODEL_FROM_DATABASE=PT890 Host Bridge + +pci:v00001106d00007238* + ID_MODEL_FROM_DATABASE=K8T890 Host Bridge + +pci:v00001106d00007258* + ID_MODEL_FROM_DATABASE=PT880 Host Bridge + +pci:v00001106d00007259* + ID_MODEL_FROM_DATABASE=CN333/CN400/PM880 Host Bridge + +pci:v00001106d00007269* + ID_MODEL_FROM_DATABASE=KT880 Host Bridge + +pci:v00001106d00007282* + ID_MODEL_FROM_DATABASE=K8T800Pro Host Bridge + +pci:v00001106d00007290* + ID_MODEL_FROM_DATABASE=K8M890 Host Bridge + +pci:v00001106d00007293* + ID_MODEL_FROM_DATABASE=PM896 Host Bridge + +pci:v00001106d00007296* + ID_MODEL_FROM_DATABASE=P4M800 Host Bridge + +pci:v00001106d00007308* + ID_MODEL_FROM_DATABASE=PT894 Host Bridge + +pci:v00001106d00007314* + ID_MODEL_FROM_DATABASE=CN700/VN800/P4M800CE/Pro Host Bridge + +pci:v00001106d00007324* + ID_MODEL_FROM_DATABASE=CX700/VX700 Host Bridge + +pci:v00001106d00007327* + ID_MODEL_FROM_DATABASE=P4M890 Host Bridge + +pci:v00001106d00007336* + ID_MODEL_FROM_DATABASE=K8M890CE Host Bridge + +pci:v00001106d00007340* + ID_MODEL_FROM_DATABASE=PT900 Host Bridge + +pci:v00001106d00007351* + ID_MODEL_FROM_DATABASE=VT3351 Host Bridge + +pci:v00001106d00007353* + ID_MODEL_FROM_DATABASE=VX800/VX820 North-South Module Interface Control + +pci:v00001106d00007364* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 Host Bridge + +pci:v00001106d00007409* + ID_MODEL_FROM_DATABASE=VX855/VX875 North-South Module Interface Control + +pci:v00001106d00007410* + ID_MODEL_FROM_DATABASE=VX900 North-South Module Interface Control + +pci:v00001106d00007410sv000019DAsd0000A179* + ID_MODEL_FROM_DATABASE=VX900 North-South Module Interface Control (ZBOX nano VD01) + +pci:v00001106d00008231* + ID_MODEL_FROM_DATABASE=VT8231 [PCI-to-ISA Bridge] + +pci:v00001106d00008235* + ID_MODEL_FROM_DATABASE=VT8235 ACPI + +pci:v00001106d00008305* + ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133 AGP] + +pci:v00001106d00008324* + ID_MODEL_FROM_DATABASE=CX700/VX700 PCI to ISA Bridge + +pci:v00001106d00008353* + ID_MODEL_FROM_DATABASE=VX800/VX820 Bus Control and Power Management + +pci:v00001106d00008391* + ID_MODEL_FROM_DATABASE=VT8371 [KX133 AGP] + +pci:v00001106d00008400* + ID_MODEL_FROM_DATABASE=MVP4 + +pci:v00001106d00008409* + ID_MODEL_FROM_DATABASE=VX855/VX875 Bus Control and Power Management + +pci:v00001106d00008410* + ID_MODEL_FROM_DATABASE=VX900 Bus Control and Power Management + +pci:v00001106d00008410sv000019DAsd0000A179* + ID_MODEL_FROM_DATABASE=VX900 Bus Control and Power Management (ZBOX VD01) + +pci:v00001106d00008500* + ID_MODEL_FROM_DATABASE=KLE133/PLE133/PLE133T + +pci:v00001106d00008501* + ID_MODEL_FROM_DATABASE=VT8501 [Apollo MVP4 AGP] + +pci:v00001106d00008596* + ID_MODEL_FROM_DATABASE=VT82C596 [Apollo PRO AGP] + +pci:v00001106d00008597* + ID_MODEL_FROM_DATABASE=VT82C597 [Apollo VP3 AGP] + +pci:v00001106d00008598* + ID_MODEL_FROM_DATABASE=VT82C598/694x [Apollo MVP3/Pro133x AGP] + +pci:v00001106d00008598sv00001019sd00000985* + ID_MODEL_FROM_DATABASE=VT82C598/694x [Apollo MVP3/Pro133x AGP] (P6VXA Motherboard) + +pci:v00001106d00008601* + ID_MODEL_FROM_DATABASE=VT8601 [Apollo ProMedia AGP] + +pci:v00001106d00008605* + ID_MODEL_FROM_DATABASE=VT8605 [PM133 AGP] + +pci:v00001106d00008691* + ID_MODEL_FROM_DATABASE=VT82C691 [Apollo Pro] + +pci:v00001106d00008693* + ID_MODEL_FROM_DATABASE=VT82C693 [Apollo Pro Plus] PCI Bridge + +pci:v00001106d00008A25* + ID_MODEL_FROM_DATABASE=PL133/PL133T [S3 ProSavage] + +pci:v00001106d00008A26* + ID_MODEL_FROM_DATABASE=KL133/KL133A/KM133/KM133A [S3 ProSavage] + +pci:v00001106d00008D01* + ID_MODEL_FROM_DATABASE=PN133/PN133T [S3 Twister] + +pci:v00001106d00008D04* + ID_MODEL_FROM_DATABASE=KM266/P4M266/P4M266A/P4N266 [S3 ProSavageDDR] + +pci:v00001106d00009001* + ID_MODEL_FROM_DATABASE=VX900 Serial ATA Controller + +pci:v00001106d00009082* + ID_MODEL_FROM_DATABASE=Standard AHCI 1.0 SATA Controller + +pci:v00001106d00009140* + ID_MODEL_FROM_DATABASE=HDMI Audio Device + +pci:v00001106d00009201* + ID_MODEL_FROM_DATABASE=USB3.0 Controller + +pci:v00001106d00009530* + ID_MODEL_FROM_DATABASE=Secure Digital Memory Card Controller + +pci:v00001106d000095D0* + ID_MODEL_FROM_DATABASE=SDIO Host Controller + +pci:v00001106d0000A208* + ID_MODEL_FROM_DATABASE=PT890 PCI to PCI Bridge Controller + +pci:v00001106d0000A238* + ID_MODEL_FROM_DATABASE=K8T890 PCI to PCI Bridge Controller + +pci:v00001106d0000A327* + ID_MODEL_FROM_DATABASE=P4M890 PCI to PCI Bridge Controller + +pci:v00001106d0000A353* + ID_MODEL_FROM_DATABASE=VX8xx South-North Module Interface Control + +pci:v00001106d0000A364* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 PCI to PCI Bridge Controller + +pci:v00001106d0000A409* + ID_MODEL_FROM_DATABASE=VX855/VX875 USB Device Controller + +pci:v00001106d0000A410* + ID_MODEL_FROM_DATABASE=VX900 PCI Express Root Port 0 + +pci:v00001106d0000B091* + ID_MODEL_FROM_DATABASE=VT8633 [Apollo Pro266 AGP] + +pci:v00001106d0000B099* + ID_MODEL_FROM_DATABASE=VT8366/A/7 [Apollo KT266/A/333 AGP] + +pci:v00001106d0000B101* + ID_MODEL_FROM_DATABASE=VT8653 AGP Bridge + +pci:v00001106d0000B102* + ID_MODEL_FROM_DATABASE=VT8362 AGP Bridge + +pci:v00001106d0000B103* + ID_MODEL_FROM_DATABASE=VT8615 AGP Bridge + +pci:v00001106d0000B112* + ID_MODEL_FROM_DATABASE=VT8361 [KLE133] AGP Bridge + +pci:v00001106d0000B113* + ID_MODEL_FROM_DATABASE=VPX/VPX2 I/O APIC Interrupt Controller + +pci:v00001106d0000B115* + ID_MODEL_FROM_DATABASE=VT8363/8365 [KT133/KM133] PCI Bridge + +pci:v00001106d0000B168* + ID_MODEL_FROM_DATABASE=VT8235 PCI Bridge + +pci:v00001106d0000B188* + ID_MODEL_FROM_DATABASE=VT8237/8251 PCI bridge [K8M890/K8T800/K8T890 South] + +pci:v00001106d0000B188sv0000147Bsd00001407* + ID_MODEL_FROM_DATABASE=VT8237/8251 PCI bridge [K8M890/K8T800/K8T890 South] (KV8-MAX3 motherboard) + +pci:v00001106d0000B198* + ID_MODEL_FROM_DATABASE=VT8237/VX700 PCI Bridge + +pci:v00001106d0000B213* + ID_MODEL_FROM_DATABASE=VPX/VPX2 I/O APIC Interrupt Controller + +pci:v00001106d0000B353* + ID_MODEL_FROM_DATABASE=VX855/VX875/VX900 PCI to PCI Bridge + +pci:v00001106d0000B410* + ID_MODEL_FROM_DATABASE=VX900 PCI Express Root Port 1 + +pci:v00001106d0000B999* + ID_MODEL_FROM_DATABASE=[K8T890 North / VT8237 South] PCI Bridge + +pci:v00001106d0000C208* + ID_MODEL_FROM_DATABASE=PT890 PCI to PCI Bridge Controller + +pci:v00001106d0000C238* + ID_MODEL_FROM_DATABASE=K8T890 PCI to PCI Bridge Controller + +pci:v00001106d0000C327* + ID_MODEL_FROM_DATABASE=P4M890 PCI to PCI Bridge Controller + +pci:v00001106d0000C340* + ID_MODEL_FROM_DATABASE=PT900 PCI to PCI Bridge Controller + +pci:v00001106d0000C353* + ID_MODEL_FROM_DATABASE=VX800/VX820 PCI Express Root Port + +pci:v00001106d0000C364* + ID_MODEL_FROM_DATABASE=CN896/VN896/P4M900 PCI to PCI Bridge Controller + +pci:v00001106d0000C409* + ID_MODEL_FROM_DATABASE=VX855/VX875 EIDE Controller + +pci:v00001106d0000C410* + ID_MODEL_FROM_DATABASE=VX900 PCI Express Root Port 2 + +pci:v00001106d0000D104* + ID_MODEL_FROM_DATABASE=VT8237R USB UDCI Controller + +pci:v00001106d0000D208* + ID_MODEL_FROM_DATABASE=PT890 PCI to PCI Bridge Controller + +pci:v00001106d0000D213* + ID_MODEL_FROM_DATABASE=VPX/VPX2 PCI to PCI Bridge Controller + +pci:v00001106d0000D238* + ID_MODEL_FROM_DATABASE=K8T890 PCI to PCI Bridge Controller + +pci:v00001106d0000D340* + ID_MODEL_FROM_DATABASE=PT900 PCI to PCI Bridge Controller + +pci:v00001106d0000D410* + ID_MODEL_FROM_DATABASE=VX900 PCI Express Root Port 3 + +pci:v00001106d0000E208* + ID_MODEL_FROM_DATABASE=PT890 PCI to PCI Bridge Controller + +pci:v00001106d0000E238* + ID_MODEL_FROM_DATABASE=K8T890 PCI to PCI Bridge Controller + +pci:v00001106d0000E340* + ID_MODEL_FROM_DATABASE=PT900 PCI to PCI Bridge Controller + +pci:v00001106d0000E353* + ID_MODEL_FROM_DATABASE=VX800/VX820 PCI Express Root Port + +pci:v00001106d0000E410* + ID_MODEL_FROM_DATABASE=VX900 PCI Express Physical Layer Electrical Sub-block + +pci:v00001106d0000F208* + ID_MODEL_FROM_DATABASE=PT890 PCI to PCI Bridge Controller + +pci:v00001106d0000F238* + ID_MODEL_FROM_DATABASE=K8T890 PCI to PCI Bridge Controller + +pci:v00001106d0000F340* + ID_MODEL_FROM_DATABASE=PT900 PCI to PCI Bridge Controller + +pci:v00001106d0000F353* + ID_MODEL_FROM_DATABASE=VX800/VX820 PCI Express Root Port + +pci:v00001107* + ID_VENDOR_FROM_DATABASE=Stratus Computers + +pci:v00001107d00000576* + ID_MODEL_FROM_DATABASE=VIA VT82C570MV [Apollo] (Wrong vendor ID!) + +pci:v00001108* + ID_VENDOR_FROM_DATABASE=Proteon, Inc. + +pci:v00001108d00000100* + ID_MODEL_FROM_DATABASE=p1690plus_AA + +pci:v00001108d00000101* + ID_MODEL_FROM_DATABASE=p1690plus_AB + +pci:v00001108d00000105* + ID_MODEL_FROM_DATABASE=P1690Plus + +pci:v00001108d00000108* + ID_MODEL_FROM_DATABASE=P1690Plus + +pci:v00001108d00000138* + ID_MODEL_FROM_DATABASE=P1690Plus + +pci:v00001108d00000139* + ID_MODEL_FROM_DATABASE=P1690Plus + +pci:v00001108d0000013C* + ID_MODEL_FROM_DATABASE=P1690Plus + +pci:v00001108d0000013D* + ID_MODEL_FROM_DATABASE=P1690Plus + +pci:v00001109* + ID_VENDOR_FROM_DATABASE=Cogent Data Technologies, Inc. + +pci:v00001109d00001400* + ID_MODEL_FROM_DATABASE=EM110TX [EX110TX] + +pci:v0000110A* + ID_VENDOR_FROM_DATABASE=Siemens AG + +pci:v0000110Ad00000002* + ID_MODEL_FROM_DATABASE=Pirahna 2-port + +pci:v0000110Ad00000005* + ID_MODEL_FROM_DATABASE=Tulip controller, power management, switch extender + +pci:v0000110Ad00000006* + ID_MODEL_FROM_DATABASE=FSC PINC (I/O-APIC) + +pci:v0000110Ad00000015* + ID_MODEL_FROM_DATABASE=FSC Multiprocessor Interrupt Controller + +pci:v0000110Ad0000001D* + ID_MODEL_FROM_DATABASE=FSC Copernicus Management Controller + +pci:v0000110Ad0000007B* + ID_MODEL_FROM_DATABASE=FSC Remote Service Controller, mailbox device + +pci:v0000110Ad0000007C* + ID_MODEL_FROM_DATABASE=FSC Remote Service Controller, shared memory device + +pci:v0000110Ad0000007D* + ID_MODEL_FROM_DATABASE=FSC Remote Service Controller, SMIC device + +pci:v0000110Ad00002101* + ID_MODEL_FROM_DATABASE=HST SAPHIR V Primary PCI (ISDN/PMx) + +pci:v0000110Ad00002102* + ID_MODEL_FROM_DATABASE=DSCC4 PEB/PEF 20534 DMA Supported Serial Communication Controller with 4 Channels + +pci:v0000110Ad00002104* + ID_MODEL_FROM_DATABASE=Eicon Diva 2.02 compatible passive ISDN card + +pci:v0000110Ad00003141* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5611 / 5621 + +pci:v0000110Ad00003142* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5613 / 5614 + +pci:v0000110Ad00003143* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 1613 + +pci:v0000110Ad00004021* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5512 (Profibus and MPI Cardbus Adapter) + +pci:v0000110Ad00004029* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5613 A2 + +pci:v0000110Ad00004029sv0000110Asd00004029* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5613 A2 + +pci:v0000110Ad00004029sv0000110Asd0000C029* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5613 A2 (SIMATIC NET CP 5614 A2) + +pci:v0000110Ad00004035* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 1613 A2 + +pci:v0000110Ad00004036* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 1616 + +pci:v0000110Ad00004038* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 1604 + +pci:v0000110Ad00004069* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5623 + +pci:v0000110Ad00004069sv0000110Asd00004069* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5623 + +pci:v0000110Ad00004069sv0000110Asd0000C069* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5623 (SIMATIC NET CP 5624) + +pci:v0000110Ad0000407C* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5612 + +pci:v0000110Ad0000407D* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5613 A3 + +pci:v0000110Ad0000407E* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5622 + +pci:v0000110Ad00004083* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5614 A3 + +pci:v0000110Ad00004084* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 1626 + +pci:v0000110Ad00004942* + ID_MODEL_FROM_DATABASE=FPGA I-Bus Tracer for MBD + +pci:v0000110Ad00006120* + ID_MODEL_FROM_DATABASE=SZB6120 + +pci:v0000110B* + ID_VENDOR_FROM_DATABASE=Chromatic Research Inc. + +pci:v0000110Bd00000001* + ID_MODEL_FROM_DATABASE=Mpact Media Processor + +pci:v0000110Bd00000004* + ID_MODEL_FROM_DATABASE=Mpact 2 + +pci:v0000110C* + ID_VENDOR_FROM_DATABASE=Mini-Max Technology, Inc. + +pci:v0000110D* + ID_VENDOR_FROM_DATABASE=Znyx Advanced Systems + +pci:v0000110E* + ID_VENDOR_FROM_DATABASE=CPU Technology + +pci:v0000110F* + ID_VENDOR_FROM_DATABASE=Ross Technology + +pci:v00001110* + ID_VENDOR_FROM_DATABASE=Powerhouse Systems + +pci:v00001110d00006037* + ID_MODEL_FROM_DATABASE=Firepower Powerized SMP I/O ASIC + +pci:v00001110d00006073* + ID_MODEL_FROM_DATABASE=Firepower Powerized SMP I/O ASIC + +pci:v00001111* + ID_VENDOR_FROM_DATABASE=Santa Cruz Operation + +pci:v00001112* + ID_VENDOR_FROM_DATABASE=Osicom Technologies Inc + +pci:v00001112d00002200* + ID_MODEL_FROM_DATABASE=FDDI Adapter + +pci:v00001112d00002300* + ID_MODEL_FROM_DATABASE=Fast Ethernet Adapter + +pci:v00001112d00002340* + ID_MODEL_FROM_DATABASE=4 Port Fast Ethernet Adapter + +pci:v00001112d00002400* + ID_MODEL_FROM_DATABASE=ATM Adapter + +pci:v00001113* + ID_VENDOR_FROM_DATABASE=Accton Technology Corporation + +pci:v00001113d00001211* + ID_MODEL_FROM_DATABASE=SMC2-1211TX + +pci:v00001113d00001211sv0000103Csd00001207* + ID_MODEL_FROM_DATABASE=SMC2-1211TX (EN-1207D Fast Ethernet Adapter) + +pci:v00001113d00001211sv00001113sd00001211* + ID_MODEL_FROM_DATABASE=SMC2-1211TX (EN-1207D Fast Ethernet Adapter) + +pci:v00001113d00001216* + ID_MODEL_FROM_DATABASE=EN-1216 Ethernet Adapter + +pci:v00001113d00001216sv00001113sd00001216* + ID_MODEL_FROM_DATABASE=EN-1216 Ethernet Adapter (EN1207F series PCI Fast Ethernet Adapter) + +pci:v00001113d00001216sv00001113sd00002220* + ID_MODEL_FROM_DATABASE=EN-1216 Ethernet Adapter (EN2220A Cardbus Fast Ethernet Adapter) + +pci:v00001113d00001216sv00001113sd00002242* + ID_MODEL_FROM_DATABASE=EN-1216 Ethernet Adapter (EN2242 10/100 Ethernet Mini-PCI Card) + +pci:v00001113d00001216sv0000111Asd00001020* + ID_MODEL_FROM_DATABASE=EN-1216 Ethernet Adapter (SpeedStream 1020 PCI 10/100 Ethernet Adaptor [EN-1207F-TX ?]) + +pci:v00001113d00001217* + ID_MODEL_FROM_DATABASE=EN-1217 Ethernet Adapter + +pci:v00001113d00005105* + ID_MODEL_FROM_DATABASE=10Mbps Network card + +pci:v00001113d00009211* + ID_MODEL_FROM_DATABASE=EN-1207D Fast Ethernet Adapter + +pci:v00001113d00009211sv00001113sd00009211* + ID_MODEL_FROM_DATABASE=EN-1207D Fast Ethernet Adapter + +pci:v00001113d00009511* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible Fast Ethernet + +pci:v00001113d0000D301* + ID_MODEL_FROM_DATABASE=CPWNA100 (Philips wireless PCMCIA) + +pci:v00001113d0000EC02* + ID_MODEL_FROM_DATABASE=SMC 1244TX v3 + +pci:v00001113d0000EE23* + ID_MODEL_FROM_DATABASE=SMCWPCIT-G 108Mbps Wireless PCI adapter + +pci:v00001114* + ID_VENDOR_FROM_DATABASE=Atmel Corporation + +pci:v00001114d00000506* + ID_MODEL_FROM_DATABASE=at76c506 802.11b Wireless Network Adaptor + +pci:v00001115* + ID_VENDOR_FROM_DATABASE=3D Labs + +pci:v00001116* + ID_VENDOR_FROM_DATABASE=Data Translation + +pci:v00001116d00000022* + ID_MODEL_FROM_DATABASE=DT3001 + +pci:v00001116d00000023* + ID_MODEL_FROM_DATABASE=DT3002 + +pci:v00001116d00000024* + ID_MODEL_FROM_DATABASE=DT3003 + +pci:v00001116d00000025* + ID_MODEL_FROM_DATABASE=DT3004 + +pci:v00001116d00000026* + ID_MODEL_FROM_DATABASE=DT3005 + +pci:v00001116d00000027* + ID_MODEL_FROM_DATABASE=DT3001-PGL + +pci:v00001116d00000028* + ID_MODEL_FROM_DATABASE=DT3003-PGL + +pci:v00001116d00000051* + ID_MODEL_FROM_DATABASE=DT322 + +pci:v00001116d00000060* + ID_MODEL_FROM_DATABASE=DT340 + +pci:v00001116d00000069* + ID_MODEL_FROM_DATABASE=DT332 + +pci:v00001116d000080C2* + ID_MODEL_FROM_DATABASE=DT3162 + +pci:v00001117* + ID_VENDOR_FROM_DATABASE=Datacube, Inc + +pci:v00001117d00009500* + ID_MODEL_FROM_DATABASE=Max-1C SVGA card + +pci:v00001117d00009501* + ID_MODEL_FROM_DATABASE=Max-1C image processing + +pci:v00001118* + ID_VENDOR_FROM_DATABASE=Berg Electronics + +pci:v00001119* + ID_VENDOR_FROM_DATABASE=ICP Vortex Computersysteme GmbH + +pci:v00001119d00000000* + ID_MODEL_FROM_DATABASE=GDT 6000/6020/6050 + +pci:v00001119d00000001* + ID_MODEL_FROM_DATABASE=GDT 6000B/6010 + +pci:v00001119d00000002* + ID_MODEL_FROM_DATABASE=GDT 6110/6510 + +pci:v00001119d00000003* + ID_MODEL_FROM_DATABASE=GDT 6120/6520 + +pci:v00001119d00000004* + ID_MODEL_FROM_DATABASE=GDT 6530 + +pci:v00001119d00000005* + ID_MODEL_FROM_DATABASE=GDT 6550 + +pci:v00001119d00000006* + ID_MODEL_FROM_DATABASE=GDT 6117/6517 + +pci:v00001119d00000007* + ID_MODEL_FROM_DATABASE=GDT 6127/6527 + +pci:v00001119d00000008* + ID_MODEL_FROM_DATABASE=GDT 6537 + +pci:v00001119d00000009* + ID_MODEL_FROM_DATABASE=GDT 6557/6557-ECC + +pci:v00001119d0000000A* + ID_MODEL_FROM_DATABASE=GDT 6115/6515 + +pci:v00001119d0000000B* + ID_MODEL_FROM_DATABASE=GDT 6125/6525 + +pci:v00001119d0000000C* + ID_MODEL_FROM_DATABASE=GDT 6535 + +pci:v00001119d0000000D* + ID_MODEL_FROM_DATABASE=GDT 6555/6555-ECC + +pci:v00001119d00000100* + ID_MODEL_FROM_DATABASE=GDT 6117RP/6517RP + +pci:v00001119d00000101* + ID_MODEL_FROM_DATABASE=GDT 6127RP/6527RP + +pci:v00001119d00000102* + ID_MODEL_FROM_DATABASE=GDT 6537RP + +pci:v00001119d00000103* + ID_MODEL_FROM_DATABASE=GDT 6557RP + +pci:v00001119d00000104* + ID_MODEL_FROM_DATABASE=GDT 6111RP/6511RP + +pci:v00001119d00000105* + ID_MODEL_FROM_DATABASE=GDT 6121RP/6521RP + +pci:v00001119d00000110* + ID_MODEL_FROM_DATABASE=GDT 6117RD/6517RD + +pci:v00001119d00000111* + ID_MODEL_FROM_DATABASE=GDT 6127RD/6527RD + +pci:v00001119d00000112* + ID_MODEL_FROM_DATABASE=GDT 6537RD + +pci:v00001119d00000113* + ID_MODEL_FROM_DATABASE=GDT 6557RD + +pci:v00001119d00000114* + ID_MODEL_FROM_DATABASE=GDT 6111RD/6511RD + +pci:v00001119d00000115* + ID_MODEL_FROM_DATABASE=GDT 6121RD/6521RD + +pci:v00001119d00000118* + ID_MODEL_FROM_DATABASE=GDT 6118RD/6518RD/6618RD + +pci:v00001119d00000119* + ID_MODEL_FROM_DATABASE=GDT 6128RD/6528RD/6628RD + +pci:v00001119d0000011A* + ID_MODEL_FROM_DATABASE=GDT 6538RD/6638RD + +pci:v00001119d0000011B* + ID_MODEL_FROM_DATABASE=GDT 6558RD/6658RD + +pci:v00001119d00000120* + ID_MODEL_FROM_DATABASE=GDT 6117RP2/6517RP2 + +pci:v00001119d00000121* + ID_MODEL_FROM_DATABASE=GDT 6127RP2/6527RP2 + +pci:v00001119d00000122* + ID_MODEL_FROM_DATABASE=GDT 6537RP2 + +pci:v00001119d00000123* + ID_MODEL_FROM_DATABASE=GDT 6557RP2 + +pci:v00001119d00000124* + ID_MODEL_FROM_DATABASE=GDT 6111RP2/6511RP2 + +pci:v00001119d00000125* + ID_MODEL_FROM_DATABASE=GDT 6121RP2/6521RP2 + +pci:v00001119d00000136* + ID_MODEL_FROM_DATABASE=GDT 6113RS/6513RS + +pci:v00001119d00000137* + ID_MODEL_FROM_DATABASE=GDT 6123RS/6523RS + +pci:v00001119d00000138* + ID_MODEL_FROM_DATABASE=GDT 6118RS/6518RS/6618RS + +pci:v00001119d00000139* + ID_MODEL_FROM_DATABASE=GDT 6128RS/6528RS/6628RS + +pci:v00001119d0000013A* + ID_MODEL_FROM_DATABASE=GDT 6538RS/6638RS + +pci:v00001119d0000013B* + ID_MODEL_FROM_DATABASE=GDT 6558RS/6658RS + +pci:v00001119d0000013C* + ID_MODEL_FROM_DATABASE=GDT 6533RS/6633RS + +pci:v00001119d0000013D* + ID_MODEL_FROM_DATABASE=GDT 6543RS/6643RS + +pci:v00001119d0000013E* + ID_MODEL_FROM_DATABASE=GDT 6553RS/6653RS + +pci:v00001119d0000013F* + ID_MODEL_FROM_DATABASE=GDT 6563RS/6663RS + +pci:v00001119d00000166* + ID_MODEL_FROM_DATABASE=GDT 7113RN/7513RN/7613RN + +pci:v00001119d00000167* + ID_MODEL_FROM_DATABASE=GDT 7123RN/7523RN/7623RN + +pci:v00001119d00000168* + ID_MODEL_FROM_DATABASE=GDT 7118RN/7518RN/7518RN + +pci:v00001119d00000169* + ID_MODEL_FROM_DATABASE=GDT 7128RN/7528RN/7628RN + +pci:v00001119d0000016A* + ID_MODEL_FROM_DATABASE=GDT 7538RN/7638RN + +pci:v00001119d0000016B* + ID_MODEL_FROM_DATABASE=GDT 7558RN/7658RN + +pci:v00001119d0000016C* + ID_MODEL_FROM_DATABASE=GDT 7533RN/7633RN + +pci:v00001119d0000016D* + ID_MODEL_FROM_DATABASE=GDT 7543RN/7643RN + +pci:v00001119d0000016E* + ID_MODEL_FROM_DATABASE=GDT 7553RN/7653RN + +pci:v00001119d0000016F* + ID_MODEL_FROM_DATABASE=GDT 7563RN/7663RN + +pci:v00001119d000001D6* + ID_MODEL_FROM_DATABASE=GDT 4x13RZ + +pci:v00001119d000001D7* + ID_MODEL_FROM_DATABASE=GDT 4x23RZ + +pci:v00001119d000001F6* + ID_MODEL_FROM_DATABASE=GDT 8x13RZ + +pci:v00001119d000001F7* + ID_MODEL_FROM_DATABASE=GDT 8x23RZ + +pci:v00001119d000001FC* + ID_MODEL_FROM_DATABASE=GDT 8x33RZ + +pci:v00001119d000001FD* + ID_MODEL_FROM_DATABASE=GDT 8x43RZ + +pci:v00001119d000001FE* + ID_MODEL_FROM_DATABASE=GDT 8x53RZ + +pci:v00001119d000001FF* + ID_MODEL_FROM_DATABASE=GDT 8x63RZ + +pci:v00001119d00000210* + ID_MODEL_FROM_DATABASE=GDT 6519RD/6619RD + +pci:v00001119d00000211* + ID_MODEL_FROM_DATABASE=GDT 6529RD/6629RD + +pci:v00001119d00000260* + ID_MODEL_FROM_DATABASE=GDT 7519RN/7619RN + +pci:v00001119d00000261* + ID_MODEL_FROM_DATABASE=GDT 7529RN/7629RN + +pci:v00001119d000002FF* + ID_MODEL_FROM_DATABASE=GDT MAXRP + +pci:v00001119d00000300* + ID_MODEL_FROM_DATABASE=GDT NEWRX + +pci:v00001119d00000301* + ID_MODEL_FROM_DATABASE=GDT NEWRX2 + +pci:v0000111A* + ID_VENDOR_FROM_DATABASE=Efficient Networks, Inc + +pci:v0000111Ad00000000* + ID_MODEL_FROM_DATABASE=155P-MF1 (FPGA) + +pci:v0000111Ad00000002* + ID_MODEL_FROM_DATABASE=155P-MF1 (ASIC) + +pci:v0000111Ad00000003* + ID_MODEL_FROM_DATABASE=ENI-25P ATM + +pci:v0000111Ad00000003sv0000111Asd00000000* + ID_MODEL_FROM_DATABASE=ENI-25P ATM (ENI-25p Miniport ATM Adapter) + +pci:v0000111Ad00000005* + ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) + +pci:v0000111Ad00000005sv0000111Asd00000001* + ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3010 ATM) + +pci:v0000111Ad00000005sv0000111Asd00000009* + ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3060 ADSL (VPI=0)) + +pci:v0000111Ad00000005sv0000111Asd00000101* + ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3010 ATM) + +pci:v0000111Ad00000005sv0000111Asd00000109* + ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3060CO ADSL (VPI=0)) + +pci:v0000111Ad00000005sv0000111Asd00000809* + ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3060 ADSL (VPI=0 or 8)) + +pci:v0000111Ad00000005sv0000111Asd00000909* + ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3060CO ADSL (VPI=0 or 8)) + +pci:v0000111Ad00000005sv0000111Asd00000A09* + ID_MODEL_FROM_DATABASE=SpeedStream (LANAI) (ENI-3060 ADSL (VPI=<0..15>)) + +pci:v0000111Ad00000007* + ID_MODEL_FROM_DATABASE=SpeedStream ADSL + +pci:v0000111Ad00000007sv0000111Asd00001001* + ID_MODEL_FROM_DATABASE=SpeedStream ADSL (ENI-3061 ADSL [ASIC]) + +pci:v0000111Ad00001020* + ID_MODEL_FROM_DATABASE=SpeedStream PCI 10/100 Network Card + +pci:v0000111Ad00001203* + ID_MODEL_FROM_DATABASE=SpeedStream 1023 Wireless PCI Adapter + +pci:v0000111B* + ID_VENDOR_FROM_DATABASE=Teledyne Electronic Systems + +pci:v0000111C* + ID_VENDOR_FROM_DATABASE=Tricord Systems Inc. + +pci:v0000111Cd00000001* + ID_MODEL_FROM_DATABASE=Powerbis Bridge + +pci:v0000111D* + ID_VENDOR_FROM_DATABASE=Microsemi / PMC / IDT + +pci:v0000111Dd00000001* + ID_MODEL_FROM_DATABASE=IDT77201/77211 155Mbps ATM SAR Controller [NICStAR] + +pci:v0000111Dd00000003* + ID_MODEL_FROM_DATABASE=IDT77222/77252 155Mbps ATM MICRO ABR SAR Controller + +pci:v0000111Dd00000004* + ID_MODEL_FROM_DATABASE=IDT77V252 155Mbps ATM MICRO ABR SAR Controller + +pci:v0000111Dd00000005* + ID_MODEL_FROM_DATABASE=IDT77V222 155Mbps ATM MICRO ABR SAR Controller + +pci:v0000111Dd00008018* + ID_MODEL_FROM_DATABASE=PES12N3A 12-lane 3-Port PCI Express Switch + +pci:v0000111Dd0000801C* + ID_MODEL_FROM_DATABASE=PES24N3A PCI Express Switch + +pci:v0000111Dd00008028* + ID_MODEL_FROM_DATABASE=PES4T4 PCI Express Switch + +pci:v0000111Dd0000802B* + ID_MODEL_FROM_DATABASE=PES8T5A PCI Express Switch + +pci:v0000111Dd0000802C* + ID_MODEL_FROM_DATABASE=PES16T4 PCI Express Switch + +pci:v0000111Dd0000802D* + ID_MODEL_FROM_DATABASE=PES16T7 PCI Express Switch + +pci:v0000111Dd0000802E* + ID_MODEL_FROM_DATABASE=PES24T6 PCI Express Switch + +pci:v0000111Dd0000802F* + ID_MODEL_FROM_DATABASE=PES32T8 PCI Express Switch + +pci:v0000111Dd00008032* + ID_MODEL_FROM_DATABASE=PES48T12 PCI Express Switch + +pci:v0000111Dd00008034* + ID_MODEL_FROM_DATABASE=PES16/22/34H16 PCI Express Switch + +pci:v0000111Dd00008035* + ID_MODEL_FROM_DATABASE=PES32H8 PCI Express Switch + +pci:v0000111Dd00008036* + ID_MODEL_FROM_DATABASE=PES48H12 PCI Express Switch + +pci:v0000111Dd00008037* + ID_MODEL_FROM_DATABASE=PES64H16 PCI Express Switch + +pci:v0000111Dd00008039* + ID_MODEL_FROM_DATABASE=PES3T3 PCI Express Switch + +pci:v0000111Dd0000803A* + ID_MODEL_FROM_DATABASE=PES4T4 PCI Express Switch + +pci:v0000111Dd0000803C* + ID_MODEL_FROM_DATABASE=PES5T5 PCI Express Switch + +pci:v0000111Dd0000803D* + ID_MODEL_FROM_DATABASE=PES6T5 PCI Express Switch + +pci:v0000111Dd00008048* + ID_MODEL_FROM_DATABASE=PES8NT2 PCI Express Switch + +pci:v0000111Dd00008049* + ID_MODEL_FROM_DATABASE=PES8NT2 PCI Express Switch + +pci:v0000111Dd0000804A* + ID_MODEL_FROM_DATABASE=PES8NT2 PCI Express Internal NTB + +pci:v0000111Dd0000804B* + ID_MODEL_FROM_DATABASE=PES8NT2 PCI Express External NTB + +pci:v0000111Dd0000804C* + ID_MODEL_FROM_DATABASE=PES16NT2 PCI Express Switch + +pci:v0000111Dd0000804D* + ID_MODEL_FROM_DATABASE=PES16NT2 PCI Express Switch + +pci:v0000111Dd0000804E* + ID_MODEL_FROM_DATABASE=PES16NT2 PCI Express Internal NTB + +pci:v0000111Dd0000804F* + ID_MODEL_FROM_DATABASE=PES16NT2 PCI Express External NTB + +pci:v0000111Dd00008058* + ID_MODEL_FROM_DATABASE=PES12NT3 PCI Express Switch + +pci:v0000111Dd00008059* + ID_MODEL_FROM_DATABASE=PES12NT3 PCI Express Switch + +pci:v0000111Dd0000805A* + ID_MODEL_FROM_DATABASE=PES12NT3 PCI Express Internal NTB + +pci:v0000111Dd0000805B* + ID_MODEL_FROM_DATABASE=PES12NT3 PCI Express External NTB + +pci:v0000111Dd0000805C* + ID_MODEL_FROM_DATABASE=PES24NT3 PCI Express Switch + +pci:v0000111Dd0000805D* + ID_MODEL_FROM_DATABASE=PES24NT3 PCI Express Switch + +pci:v0000111Dd0000805E* + ID_MODEL_FROM_DATABASE=PES24NT3 PCI Express Internal NTB + +pci:v0000111Dd0000805F* + ID_MODEL_FROM_DATABASE=PES24NT3 PCI Express External NTB + +pci:v0000111Dd00008060* + ID_MODEL_FROM_DATABASE=PES16T4G2 PCI Express Gen2 Switch + +pci:v0000111Dd00008061* + ID_MODEL_FROM_DATABASE=PES12T3G2 PCI Express Gen2 Switch + +pci:v0000111Dd00008068* + ID_MODEL_FROM_DATABASE=PES6T6G2 PCI Express Gen2 Switch + +pci:v0000111Dd0000806A* + ID_MODEL_FROM_DATABASE=PES24T3G2 PCI Express Gen2 Switch + +pci:v0000111Dd0000806Asv000014C1sd0000000C* + ID_MODEL_FROM_DATABASE=PES24T3G2 PCI Express Gen2 Switch (10G-PCIE2-8B2) + +pci:v0000111Dd0000806C* + ID_MODEL_FROM_DATABASE=PES16T4A/4T4G2 PCI Express Gen2 Switch + +pci:v0000111Dd0000806E* + ID_MODEL_FROM_DATABASE=PES24T6G2 PCI Express Gen2 Switch + +pci:v0000111Dd0000806F* + ID_MODEL_FROM_DATABASE=HIO524G2 PCI Express Gen2 Switch + +pci:v0000111Dd00008077* + ID_MODEL_FROM_DATABASE=89HPES64H16G2 64-Lane 16-Port PCIe Gen2 System Interconnect Switch + +pci:v0000111Dd00008088* + ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch + +pci:v0000111Dd00008088sv00001093sd0000752F* + ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8383mc Device) + +pci:v0000111Dd00008088sv00001093sd00007543* + ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8383mc System Host) + +pci:v0000111Dd00008088sv00001093sd0000755C* + ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8364) + +pci:v0000111Dd00008088sv00001093sd0000755D* + ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8374) + +pci:v0000111Dd00008088sv00001093sd000075FF* + ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8383mc DMA) + +pci:v0000111Dd00008088sv00001093sd00007600* + ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8383mc DMA) + +pci:v0000111Dd00008088sv00001093sd00007602* + ID_MODEL_FROM_DATABASE=PES32NT8BG2 PCI Express Switch (PXIe-8384) + +pci:v0000111Dd0000808A* + ID_MODEL_FROM_DATABASE=89HPES32NT24BG2 PCI Express Switch + +pci:v0000111Dd0000808C* + ID_MODEL_FROM_DATABASE=89HPES32NT24AG2 PCI Express Switch + +pci:v0000111Dd0000808E* + ID_MODEL_FROM_DATABASE=PES24NT24G2 PCI Express Switch + +pci:v0000111Dd0000808F* + ID_MODEL_FROM_DATABASE=89HPES32NT8AG2 32-Lane 8-Port PCIe Gen2 System Interconnect Switch with Non-Transparent Bridging + +pci:v0000111Dd00008090* + ID_MODEL_FROM_DATABASE=89HPES16NT16G2 16-Lane 16-Port PCIe Gen2 System Interconnect Switch + +pci:v0000111Dd00008092* + ID_MODEL_FROM_DATABASE=89HPES12NT12G2 12-Lane 12-Port PCIe Gen2 System Interconnect Switch + +pci:v0000111Dd000080CF* + ID_MODEL_FROM_DATABASE=F32P08xG3 [PCIe boot mode] + +pci:v0000111Dd000080D2* + ID_MODEL_FROM_DATABASE=F32P08xG3 NVMe controller + +pci:v0000111E* + ID_VENDOR_FROM_DATABASE=Eldec + +pci:v0000111F* + ID_VENDOR_FROM_DATABASE=Precision Digital Images + +pci:v0000111Fd00004A47* + ID_MODEL_FROM_DATABASE=Precision MX Video engine interface + +pci:v0000111Fd00005243* + ID_MODEL_FROM_DATABASE=Frame capture bus interface + +pci:v00001120* + ID_VENDOR_FROM_DATABASE=Dell EMC + +pci:v00001120d00002306* + ID_MODEL_FROM_DATABASE=Unity Fibre Channel Controller + +pci:v00001120d00002501* + ID_MODEL_FROM_DATABASE=Unity Ethernet Controller + +pci:v00001120d00002505* + ID_MODEL_FROM_DATABASE=Unity Fibre Channel Controller + +pci:v00001121* + ID_VENDOR_FROM_DATABASE=Zilog + +pci:v00001122* + ID_VENDOR_FROM_DATABASE=Multi-tech Systems, Inc. + +pci:v00001123* + ID_VENDOR_FROM_DATABASE=Excellent Design, Inc. + +pci:v00001124* + ID_VENDOR_FROM_DATABASE=Leutron Vision AG + +pci:v00001124d00002581* + ID_MODEL_FROM_DATABASE=Picport Monochrome + +pci:v00001125* + ID_VENDOR_FROM_DATABASE=Eurocore + +pci:v00001126* + ID_VENDOR_FROM_DATABASE=Vigra + +pci:v00001127* + ID_VENDOR_FROM_DATABASE=FORE Systems Inc + +pci:v00001127d00000200* + ID_MODEL_FROM_DATABASE=ForeRunner PCA-200 ATM + +pci:v00001127d00000210* + ID_MODEL_FROM_DATABASE=PCA-200PC + +pci:v00001127d00000250* + ID_MODEL_FROM_DATABASE=ATM + +pci:v00001127d00000300* + ID_MODEL_FROM_DATABASE=ForeRunner PCA-200EPC ATM + +pci:v00001127d00000310* + ID_MODEL_FROM_DATABASE=ATM + +pci:v00001127d00000400* + ID_MODEL_FROM_DATABASE=ForeRunnerHE ATM Adapter + +pci:v00001127d00000400sv00001127sd00000400* + ID_MODEL_FROM_DATABASE=ForeRunnerHE ATM Adapter (ForeRunnerHE ATM) + +pci:v00001129* + ID_VENDOR_FROM_DATABASE=Firmworks + +pci:v0000112A* + ID_VENDOR_FROM_DATABASE=Hermes Electronics Company, Ltd. + +pci:v0000112B* + ID_VENDOR_FROM_DATABASE=Heidelberger Druckmaschinen AGHeidelberger Druckmaschinen AG + +pci:v0000112C* + ID_VENDOR_FROM_DATABASE=Zenith Data Systems + +pci:v0000112D* + ID_VENDOR_FROM_DATABASE=Ravicad + +pci:v0000112E* + ID_VENDOR_FROM_DATABASE=Infomedia Microelectronics Inc. + +pci:v0000112F* + ID_VENDOR_FROM_DATABASE=Dalsa Inc. + +pci:v0000112Fd00000000* + ID_MODEL_FROM_DATABASE=MVC IC-PCI + +pci:v0000112Fd00000001* + ID_MODEL_FROM_DATABASE=MVC IM-PCI Video frame grabber/processor + +pci:v0000112Fd00000004* + ID_MODEL_FROM_DATABASE=PCDig Digital Image Capture + +pci:v0000112Fd00000008* + ID_MODEL_FROM_DATABASE=PC-CamLink PCI framegrabber + +pci:v00001130* + ID_VENDOR_FROM_DATABASE=Computervision + +pci:v00001131* + ID_VENDOR_FROM_DATABASE=Philips Semiconductors + +pci:v00001131d00001561* + ID_MODEL_FROM_DATABASE=USB 1.1 Host Controller + +pci:v00001131d00001561sv00001775sd0000C200* + ID_MODEL_FROM_DATABASE=USB 1.1 Host Controller (C2K onboard USB 1.1 host controller) + +pci:v00001131d00001562* + ID_MODEL_FROM_DATABASE=USB 2.0 Host Controller + +pci:v00001131d00001562sv00001775sd0000C200* + ID_MODEL_FROM_DATABASE=USB 2.0 Host Controller (C2K onboard USB 2.0 host controller) + +pci:v00001131d00003400* + ID_MODEL_FROM_DATABASE=SmartPCI56(UCB1500) 56K Modem + +pci:v00001131d00005400* + ID_MODEL_FROM_DATABASE=TriMedia TM1000/1100 + +pci:v00001131d00005400sv000012CAsd00000000* + ID_MODEL_FROM_DATABASE=TriMedia TM1000/1100 (BlueICE) + +pci:v00001131d00005402* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 + +pci:v00001131d00005402sv00001244sd00000F00* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (Fritz!Card DSL) + +pci:v00001131d00005402sv000015EBsd00001300* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1300) + +pci:v00001131d00005402sv000015EBsd00001302* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1302) + +pci:v00001131d00005402sv000015EBsd00001304* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1304) + +pci:v00001131d00005402sv000015EBsd00001305* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1305) + +pci:v00001131d00005402sv000015EBsd00001306* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (PMCDT1306) + +pci:v00001131d00005402sv000015EBsd00001308* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1308) + +pci:v00001131d00005402sv000015EBsd00001331* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1301 with SAA7121) + +pci:v00001131d00005402sv000015EBsd00001337* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (DT1301 with SAA7127) + +pci:v00001131d00005402sv000015EBsd00002D3D* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (X3D) + +pci:v00001131d00005402sv000015EBsd00007022* + ID_MODEL_FROM_DATABASE=TriMedia TM1300 (PTM1300) + +pci:v00001131d00005405* + ID_MODEL_FROM_DATABASE=TriMedia TM1500 + +pci:v00001131d00005405sv00001136sd00000005* + ID_MODEL_FROM_DATABASE=TriMedia TM1500 (LCP-1500) + +pci:v00001131d00005406* + ID_MODEL_FROM_DATABASE=TriMedia TM1700 + +pci:v00001131d0000540B* + ID_MODEL_FROM_DATABASE=PNX1005 Media Processor + +pci:v00001131d0000540Bsv00001131sd00000020* + ID_MODEL_FROM_DATABASE=PNX1005 Media Processor (PNXLite PCI Demo Board) + +pci:v00001131d00007130* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder + +pci:v00001131d00007130sv00000000sd00004016* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 401) + +pci:v00001131d00007130sv00000000sd00004051* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 405 FM) + +pci:v00001131d00007130sv00000000sd00005051* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 505 RDS) + +pci:v00001131d00007130sv00000000sd0000505B* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 505 RDS) + +pci:v00001131d00007130sv0000102Bsd000048D0* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Matrox CronosPlus) + +pci:v00001131d00007130sv00001048sd0000226B* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (ELSA EX-VISION 300TV) + +pci:v00001131d00007130sv0000107Dsd00006655* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (WinFast DTV1000S) + +pci:v00001131d00007130sv00001131sd00000000* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (SAA7130-based TV tuner card) + +pci:v00001131d00007130sv00001131sd00002001* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (10MOONS PCI TV CAPTURE CARD) + +pci:v00001131d00007130sv00001131sd00002005* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Techcom (India) TV Tuner Card (SSD-TV-670)) + +pci:v00001131d00007130sv00001458sd00009006* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (GT-PS700 DVB-S tuner) + +pci:v00001131d00007130sv00001461sd0000050C* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Nagase Sangyo TransGear 3000TV) + +pci:v00001131d00007130sv00001461sd000010FF* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (AVerMedia DVD EZMaker) + +pci:v00001131d00007130sv00001461sd00002108* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (AverMedia AverTV/305) + +pci:v00001131d00007130sv00001461sd00002115* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (AverMedia AverTV Studio 305) + +pci:v00001131d00007130sv0000153Bsd00001152* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Terratec Cinergy 200 TV) + +pci:v00001131d00007130sv0000185Bsd0000C100* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Compro VideoMate TV PVR/FM) + +pci:v00001131d00007130sv0000185Bsd0000C901* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Videomate DVB-T200) + +pci:v00001131d00007130sv00005168sd00000138* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (LifeView FlyVIDEO2000) + +pci:v00001131d00007130sv00005ACEsd00005010* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 501) + +pci:v00001131d00007130sv00005ACEsd00005050* + ID_MODEL_FROM_DATABASE=SAA7130 Video Broadcast Decoder (Behold TV 505 FM) + +pci:v00001131d00007133* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder + +pci:v00001131d00007133sv00000000sd00004091* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Beholder BeholdTV 409 FM) + +pci:v00001131d00007133sv00000000sd00005071* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 507 RDS) + +pci:v00001131d00007133sv00000000sd0000507B* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 507 RDS) + +pci:v00001131d00007133sv00000000sd00005201* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV Columbus) + +pci:v00001131d00007133sv00000070sd00006701* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (WinTV HVR-1110) + +pci:v00001131d00007133sv00001019sd00004CB5* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM)) + +pci:v00001131d00007133sv00001043sd00000210* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (FlyTV mini Asus Digimatrix) + +pci:v00001131d00007133sv00001043sd00004843* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (TV-FM 7133) + +pci:v00001131d00007133sv00001043sd00004845* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (TV-FM 7135) + +pci:v00001131d00007133sv00001043sd00004862* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (P7131 Dual) + +pci:v00001131d00007133sv00001043sd00004876* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (My Cinema-P7131 Hybrid) + +pci:v00001131d00007133sv00001131sd00000000* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (SAA713x-based TV tuner card) + +pci:v00001131d00007133sv00001131sd00002001* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Proteus Pro [philips reference design]) + +pci:v00001131d00007133sv00001131sd00002018* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Tiger reference design) + +pci:v00001131d00007133sv00001131sd00004EE9* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (MonsterTV Mobile) + +pci:v00001131d00007133sv00001131sd00007133* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Pinnacle PCTV 301i) + +pci:v00001131d00007133sv000011BDsd0000002B* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (PCTV Stereo) + +pci:v00001131d00007133sv000011BDsd0000002E* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (PCTV 110i (saa7133)) + +pci:v00001131d00007133sv000012ABsd00000800* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (PURPLE TV) + +pci:v00001131d00007133sv000013C2sd00002804* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Technotrend Budget T-3000 Hybrid) + +pci:v00001131d00007133sv00001421sd00000335* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Instant TV DVB-T Cardbus) + +pci:v00001131d00007133sv00001421sd00001370* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Instant TV (saa7135)) + +pci:v00001131d00007133sv00001435sd00007330* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (VFG7330) + +pci:v00001131d00007133sv00001435sd00007350* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (VFG7350) + +pci:v00001131d00007133sv00001458sd00009001* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GC-PTV-TAF Hybrid TV card) + +pci:v00001131d00007133sv00001458sd00009002* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GT-PTV-TAF-RH DVB-T/Analog TV/FM tuner) + +pci:v00001131d00007133sv00001458sd00009003* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GT-PTV-AF-RH Analog TV/FM tuner) + +pci:v00001131d00007133sv00001458sd00009004* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GT-P8000 DVB-T/Analog TV/FM tuner) + +pci:v00001131d00007133sv00001458sd00009005* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GT-P6000 Analog TV/FM tuner) + +pci:v00001131d00007133sv00001458sd00009008* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (GT-P5100 Analog TV tuner) + +pci:v00001131d00007133sv00001461sd00001044* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (AVerTVHD MCE A180) + +pci:v00001131d00007133sv00001461sd00004836* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (M10D Hybrid DVBT) + +pci:v00001131d00007133sv00001461sd0000861E* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (M105 PAL/SECAM/NTSC/FM Tuner) + +pci:v00001131d00007133sv00001461sd0000A14B* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (AVerTV Studio 509) + +pci:v00001131d00007133sv00001461sd0000A836* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (M115 DVB-T, PAL/SECAM/NTSC Tuner) + +pci:v00001131d00007133sv00001461sd0000F01D* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (DVB-T Super 007) + +pci:v00001131d00007133sv00001461sd0000F31F* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Avermedia AVerTV GO 007 FM) + +pci:v00001131d00007133sv00001461sd0000F936* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Hybrid+FM PCI (rev A16D)) + +pci:v00001131d00007133sv00001462sd00006231* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (TV@nywhere Plus) + +pci:v00001131d00007133sv00001489sd00000214* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyTV Platinum FM) + +pci:v00001131d00007133sv000014C0sd00001212* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyTV Platinum Mini2) + +pci:v00001131d00007133sv0000153Bsd00001160* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Cinergy 250 PCI TV) + +pci:v00001131d00007133sv0000153Bsd00001162* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Terratec Cinergy 400 mobile) + +pci:v00001131d00007133sv000017DEsd00007256* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (PlusTV All In One PI610 card) + +pci:v00001131d00007133sv000017DEsd00007350* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (ATSC 110 Digital / Analog HDTV Tuner) + +pci:v00001131d00007133sv000017DEsd00007352* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (ATSC 115 Digital / Analog HDTV Tuner) + +pci:v00001131d00007133sv0000185Bsd0000C100* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (VideoMate TV) + +pci:v00001131d00007133sv0000185Bsd0000C900* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (VideoMate T750) + +pci:v00001131d00007133sv00005168sd00000306* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB-T DUO) + +pci:v00001131d00007133sv00005168sd00000319* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB Trio) + +pci:v00001131d00007133sv00005168sd00000502* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB-T Duo CardBus) + +pci:v00001131d00007133sv00005168sd00000520* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB Trio CardBus) + +pci:v00001131d00007133sv00005168sd00001502* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyTV CardBus) + +pci:v00001131d00007133sv00005168sd00002502* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB-T CardBus) + +pci:v00001131d00007133sv00005168sd00002520* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB-S Duo CardBus) + +pci:v00001131d00007133sv00005168sd00003502* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB-T Hybrid CardBus) + +pci:v00001131d00007133sv00005168sd00003520* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (LifeView FlyDVB Trio N CardBus) + +pci:v00001131d00007133sv00005ACEsd00005030* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 503 FM) + +pci:v00001131d00007133sv00005ACEsd00005090* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 509 FM) + +pci:v00001131d00007133sv00005ACEsd00006090* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 609 FM) + +pci:v00001131d00007133sv00005ACEsd00006091* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 609 FM) + +pci:v00001131d00007133sv00005ACEsd00006092* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 609 RDS) + +pci:v00001131d00007133sv00005ACEsd00006093* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV 609 RDS) + +pci:v00001131d00007133sv00005ACEsd00006190* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV M6) + +pci:v00001131d00007133sv00005ACEsd00006191* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV M63) + +pci:v00001131d00007133sv00005ACEsd00006193* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV M6 Extra) + +pci:v00001131d00007133sv00005ACEsd00006290* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV H6) + +pci:v00001131d00007133sv00005ACEsd00007090* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV A7) + +pci:v00001131d00007133sv00005ACEsd00007150* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV H75) + +pci:v00001131d00007133sv00005ACEsd00007151* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV H75) + +pci:v00001131d00007133sv00005ACEsd00007190* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV H7) + +pci:v00001131d00007133sv00005ACEsd00007191* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV H7) + +pci:v00001131d00007133sv00005ACEsd00007290* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV T7) + +pci:v00001131d00007133sv00005ACEsd00007591* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV X7) + +pci:v00001131d00007133sv00005ACEsd00007595* + ID_MODEL_FROM_DATABASE=SAA7131/SAA7133/SAA7135 Video Broadcast Decoder (Behold TV X7) + +pci:v00001131d00007134* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder + +pci:v00001131d00007134sv00000000sd00004036* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 403) + +pci:v00001131d00007134sv00000000sd00004037* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 403 FM) + +pci:v00001131d00007134sv00000000sd00004071* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 407 FM) + +pci:v00001131d00007134sv00001019sd00004CB4* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM)) + +pci:v00001131d00007134sv00001043sd00000210* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Digimatrix TV) + +pci:v00001131d00007134sv00001043sd00004840* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (TV-FM 7134) + +pci:v00001131d00007134sv00001043sd00004842* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (TV-FM 7134) + +pci:v00001131d00007134sv00001131sd00000000* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (SAA713x-based TV tuner card) + +pci:v00001131d00007134sv00001131sd00002004* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (EUROPA V3 reference design) + +pci:v00001131d00007134sv00001131sd00004E85* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (SKNet Monster TV) + +pci:v00001131d00007134sv00001131sd00006752* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (EMPRESS) + +pci:v00001131d00007134sv000011BDsd0000002B* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (PCTV Stereo) + +pci:v00001131d00007134sv000011BDsd0000002D* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (PCTV 300i DVB-T + PAL) + +pci:v00001131d00007134sv00001461sd00002C00* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (AverTV Hybrid+FM PCI) + +pci:v00001131d00007134sv00001461sd00009715* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (AVerTV Studio 307) + +pci:v00001131d00007134sv00001461sd0000A70A* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Avermedia AVerTV 307) + +pci:v00001131d00007134sv00001461sd0000A70B* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (AverMedia M156 / Medion 2819) + +pci:v00001131d00007134sv00001461sd0000D6EE* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Cardbus TV/Radio (E500)) + +pci:v00001131d00007134sv00001471sd0000B7E9* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (AVerTV Cardbus plus) + +pci:v00001131d00007134sv0000153Bsd00001142* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Terratec Cinergy 400 TV) + +pci:v00001131d00007134sv0000153Bsd00001143* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Terratec Cinergy 600 TV) + +pci:v00001131d00007134sv0000153Bsd00001158* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Terratec Cinergy 600 TV MK3) + +pci:v00001131d00007134sv00001540sd00009524* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (ProVideo PV952) + +pci:v00001131d00007134sv000016BEsd00000003* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Medion 7134) + +pci:v00001131d00007134sv0000185Bsd0000C200* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Compro VideoMate Gold+ Pal) + +pci:v00001131d00007134sv0000185Bsd0000C900* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Videomate DVB-T300) + +pci:v00001131d00007134sv00001894sd0000A006* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (KNC One TV-Station DVR) + +pci:v00001131d00007134sv00001894sd0000FE01* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (KNC One TV-Station RDS / Typhoon TV Tuner RDS) + +pci:v00001131d00007134sv00005168sd00000138* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (FLY TV PRIME 34FM) + +pci:v00001131d00007134sv00005168sd00000300* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (FlyDVB-S) + +pci:v00001131d00007134sv00005ACEsd00005070* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 507 FM) + +pci:v00001131d00007134sv00005ACEsd00006070* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 607 FM) + +pci:v00001131d00007134sv00005ACEsd00006071* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 607 FM) + +pci:v00001131d00007134sv00005ACEsd00006072* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 607 RDS) + +pci:v00001131d00007134sv00005ACEsd00006073* + ID_MODEL_FROM_DATABASE=SAA7134/SAA7135HL Video Broadcast Decoder (Behold TV 607 RDS) + +pci:v00001131d00007145* + ID_MODEL_FROM_DATABASE=SAA7145 + +pci:v00001131d00007146* + ID_MODEL_FROM_DATABASE=SAA7146 + +pci:v00001131d00007146sv0000110Asd00000000* + ID_MODEL_FROM_DATABASE=SAA7146 (Fujitsu/Siemens DVB-C card rev1.5) + +pci:v00001131d00007146sv0000110Asd0000FFFF* + ID_MODEL_FROM_DATABASE=SAA7146 (Fujitsu/Siemens DVB-C card rev1.5) + +pci:v00001131d00007146sv00001124sd00002581* + ID_MODEL_FROM_DATABASE=SAA7146 (Leutron Vision PicPort) + +pci:v00001131d00007146sv00001131sd00004F56* + ID_MODEL_FROM_DATABASE=SAA7146 (KNC1 DVB-S Budget) + +pci:v00001131d00007146sv00001131sd00004F60* + ID_MODEL_FROM_DATABASE=SAA7146 (Fujitsu-Siemens Activy DVB-S Budget Rev AL) + +pci:v00001131d00007146sv00001131sd00004F61* + ID_MODEL_FROM_DATABASE=SAA7146 (Activy DVB-S Budget Rev GR) + +pci:v00001131d00007146sv00001131sd00005F61* + ID_MODEL_FROM_DATABASE=SAA7146 (Activy DVB-T Budget) + +pci:v00001131d00007146sv0000114Bsd00002003* + ID_MODEL_FROM_DATABASE=SAA7146 (DVRaptor Video Edit/Capture Card) + +pci:v00001131d00007146sv00001159sd00000040* + ID_MODEL_FROM_DATABASE=SAA7146 (MuTech M-Vision 500 (MV-500 rev. E)) + +pci:v00001131d00007146sv00001159sd00000050* + ID_MODEL_FROM_DATABASE=SAA7146 (MuTech M-Vision 500 (MV-500 rev. F)) + +pci:v00001131d00007146sv000011BDsd00000006* + ID_MODEL_FROM_DATABASE=SAA7146 (DV500 Overlay) + +pci:v00001131d00007146sv000011BDsd0000000A* + ID_MODEL_FROM_DATABASE=SAA7146 (DV500 Overlay) + +pci:v00001131d00007146sv000011BDsd0000000F* + ID_MODEL_FROM_DATABASE=SAA7146 (DV500 Overlay) + +pci:v00001131d00007146sv000013C2sd00000000* + ID_MODEL_FROM_DATABASE=SAA7146 (Siemens/Technotrend/Hauppauge DVB card rev1.3 or rev1.5) + +pci:v00001131d00007146sv000013C2sd00000001* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev1.3 or rev1.6) + +pci:v00001131d00007146sv000013C2sd00000002* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev2.1) + +pci:v00001131d00007146sv000013C2sd00000003* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev2.1) + +pci:v00001131d00007146sv000013C2sd00000004* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev2.1) + +pci:v00001131d00007146sv000013C2sd00000006* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev1.3 or rev1.6) + +pci:v00001131d00007146sv000013C2sd00000008* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB-T) + +pci:v00001131d00007146sv000013C2sd0000000A* + ID_MODEL_FROM_DATABASE=SAA7146 (Octal/Technotrend DVB-C for iTV) + +pci:v00001131d00007146sv000013C2sd0000000E* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev2.3) + +pci:v00001131d00007146sv000013C2sd00001003* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-S DVB card) + +pci:v00001131d00007146sv000013C2sd00001004* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-C DVB card) + +pci:v00001131d00007146sv000013C2sd00001005* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-T DVB card) + +pci:v00001131d00007146sv000013C2sd0000100C* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-CI DVB card) + +pci:v00001131d00007146sv000013C2sd0000100F* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-CI DVB card) + +pci:v00001131d00007146sv000013C2sd00001010* + ID_MODEL_FROM_DATABASE=SAA7146 (DVB C-1500) + +pci:v00001131d00007146sv000013C2sd00001011* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend-Budget/Hauppauge WinTV-NOVA-T DVB card) + +pci:v00001131d00007146sv000013C2sd00001012* + ID_MODEL_FROM_DATABASE=SAA7146 (DVB T-1500) + +pci:v00001131d00007146sv000013C2sd00001013* + ID_MODEL_FROM_DATABASE=SAA7146 (SATELCO Multimedia DVB) + +pci:v00001131d00007146sv000013C2sd00001016* + ID_MODEL_FROM_DATABASE=SAA7146 (WinTV-NOVA-SE DVB card) + +pci:v00001131d00007146sv000013C2sd00001018* + ID_MODEL_FROM_DATABASE=SAA7146 (DVB S-1401) + +pci:v00001131d00007146sv000013C2sd00001019* + ID_MODEL_FROM_DATABASE=SAA7146 (S2-3200) + +pci:v00001131d00007146sv000013C2sd00001102* + ID_MODEL_FROM_DATABASE=SAA7146 (Technotrend/Hauppauge DVB card rev2.1) + +pci:v00001131d00007146sv0000153Bsd00001155* + ID_MODEL_FROM_DATABASE=SAA7146 (Cinergy 1200 DVB-S) + +pci:v00001131d00007146sv0000153Bsd00001156* + ID_MODEL_FROM_DATABASE=SAA7146 (Cinergy 1200 DVB-C) + +pci:v00001131d00007146sv0000153Bsd00001157* + ID_MODEL_FROM_DATABASE=SAA7146 (Cinergy 1200 DVB-T) + +pci:v00001131d00007146sv0000153Bsd00001176* + ID_MODEL_FROM_DATABASE=SAA7146 (Cinergy 1200 DVB-C (MK3)) + +pci:v00001131d00007146sv00001894sd00000020* + ID_MODEL_FROM_DATABASE=SAA7146 (KNC One DVB-C V1.0) + +pci:v00001131d00007146sv00001894sd00000023* + ID_MODEL_FROM_DATABASE=SAA7146 (TVStation DVB-C plus) + +pci:v00001131d00007146sv00001894sd00000054* + ID_MODEL_FROM_DATABASE=SAA7146 (TV-Station DVB-S) + +pci:v00001131d00007160* + ID_MODEL_FROM_DATABASE=SAA7160 + +pci:v00001131d00007160sv00001458sd00009009* + ID_MODEL_FROM_DATABASE=SAA7160 (E8000 DVB-T/Analog TV/FM tuner) + +pci:v00001131d00007160sv00001461sd00001455* + ID_MODEL_FROM_DATABASE=SAA7160 (AVerTV Hybrid Speedy PCI-E (H788)) + +pci:v00001131d00007162* + ID_MODEL_FROM_DATABASE=SAA7162 + +pci:v00001131d00007162sv000011BDsd00000101* + ID_MODEL_FROM_DATABASE=SAA7162 (Pinnacle PCTV 7010iX TV Card) + +pci:v00001131d00007164* + ID_MODEL_FROM_DATABASE=SAA7164 + +pci:v00001131d00007164sv00000070sd00008800* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) + +pci:v00001131d00007164sv00000070sd00008810* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) + +pci:v00001131d00007164sv00000070sd00008851* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) + +pci:v00001131d00007164sv00000070sd00008853* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) + +pci:v00001131d00007164sv00000070sd00008880* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) + +pci:v00001131d00007164sv00000070sd00008891* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) + +pci:v00001131d00007164sv00000070sd000088A0* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) + +pci:v00001131d00007164sv00000070sd000088A1* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2250) + +pci:v00001131d00007164sv00000070sd00008900* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) + +pci:v00001131d00007164sv00000070sd00008901* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) + +pci:v00001131d00007164sv00000070sd00008940* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200 (submodel 89619)) + +pci:v00001131d00007164sv00000070sd00008951* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) + +pci:v00001131d00007164sv00000070sd00008953* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) + +pci:v00001131d00007164sv00000070sd00008980* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) + +pci:v00001131d00007164sv00000070sd00008991* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) + +pci:v00001131d00007164sv00000070sd00008993* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) + +pci:v00001131d00007164sv00000070sd000089A0* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) + +pci:v00001131d00007164sv00000070sd000089A1* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2200) + +pci:v00001131d00007164sv00000070sd0000F120* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2205) + +pci:v00001131d00007164sv00000070sd0000F123* + ID_MODEL_FROM_DATABASE=SAA7164 (WinTV HVR-2215) + +pci:v00001131d00007231* + ID_MODEL_FROM_DATABASE=SAA7231 + +pci:v00001131d00007231sv00005ACEsd00008000* + ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV H8) + +pci:v00001131d00007231sv00005ACEsd00008001* + ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV H8) + +pci:v00001131d00007231sv00005ACEsd00008050* + ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV H85) + +pci:v00001131d00007231sv00005ACEsd00008051* + ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV H85) + +pci:v00001131d00007231sv00005ACEsd00008100* + ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV A8) + +pci:v00001131d00007231sv00005ACEsd00008101* + ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV A8) + +pci:v00001131d00007231sv00005ACEsd00008150* + ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV A85) + +pci:v00001131d00007231sv00005ACEsd00008151* + ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV A85) + +pci:v00001131d00007231sv00005ACEsd00008201* + ID_MODEL_FROM_DATABASE=SAA7231 (Behold TV T8) + +pci:v00001131d00009730* + ID_MODEL_FROM_DATABASE=SAA9730 Integrated Multimedia and Peripheral Controller + +pci:v00001131d00009730sv00001131sd00000000* + ID_MODEL_FROM_DATABASE=SAA9730 Integrated Multimedia and Peripheral Controller (Integrated Multimedia and Peripheral Controller) + +pci:v00001132* + ID_VENDOR_FROM_DATABASE=Mitel Corp. + +pci:v00001133* + ID_VENDOR_FROM_DATABASE=Dialogic Corporation + +pci:v00001133d00007701* + ID_MODEL_FROM_DATABASE=Eiconcard C90 + +pci:v00001133d00007711* + ID_MODEL_FROM_DATABASE=Eiconcard C91 + +pci:v00001133d00007901* + ID_MODEL_FROM_DATABASE=EiconCard S90 + +pci:v00001133d00007902* + ID_MODEL_FROM_DATABASE=EiconCard S90 + +pci:v00001133d00007911* + ID_MODEL_FROM_DATABASE=EiconCard S91 + +pci:v00001133d00007912* + ID_MODEL_FROM_DATABASE=EiconCard S91 + +pci:v00001133d00007921* + ID_MODEL_FROM_DATABASE=Eiconcard S92 + +pci:v00001133d00007941* + ID_MODEL_FROM_DATABASE=EiconCard S94 + +pci:v00001133d00007942* + ID_MODEL_FROM_DATABASE=EiconCard S94 + +pci:v00001133d00007943* + ID_MODEL_FROM_DATABASE=EiconCard S94 + +pci:v00001133d00007944* + ID_MODEL_FROM_DATABASE=EiconCard S94 + +pci:v00001133d00007945* + ID_MODEL_FROM_DATABASE=Eiconcard S94 + +pci:v00001133d00007948* + ID_MODEL_FROM_DATABASE=Eiconcard S94 64bit/66MHz + +pci:v00001133d00009711* + ID_MODEL_FROM_DATABASE=Eiconcard S91 V2 + +pci:v00001133d00009911* + ID_MODEL_FROM_DATABASE=Eiconcard S91 V2 + +pci:v00001133d00009941* + ID_MODEL_FROM_DATABASE=Eiconcard S94 V2 + +pci:v00001133d00009A41* + ID_MODEL_FROM_DATABASE=Eiconcard S94 PCIe + +pci:v00001133d0000B921* + ID_MODEL_FROM_DATABASE=EiconCard P92 + +pci:v00001133d0000B922* + ID_MODEL_FROM_DATABASE=EiconCard P92 + +pci:v00001133d0000B923* + ID_MODEL_FROM_DATABASE=EiconCard P92 + +pci:v00001133d0000E001* + ID_MODEL_FROM_DATABASE=Diva Pro 2.0 S/T + +pci:v00001133d0000E002* + ID_MODEL_FROM_DATABASE=Diva 2.0 S/T PCI + +pci:v00001133d0000E003* + ID_MODEL_FROM_DATABASE=Diva Pro 2.0 U + +pci:v00001133d0000E004* + ID_MODEL_FROM_DATABASE=Diva 2.0 U PCI + +pci:v00001133d0000E005* + ID_MODEL_FROM_DATABASE=Diva 2.01 S/T PCI + +pci:v00001133d0000E006* + ID_MODEL_FROM_DATABASE=Diva CT S/T PCI + +pci:v00001133d0000E007* + ID_MODEL_FROM_DATABASE=Diva CT U PCI + +pci:v00001133d0000E008* + ID_MODEL_FROM_DATABASE=Diva CT Lite S/T PCI + +pci:v00001133d0000E009* + ID_MODEL_FROM_DATABASE=Diva CT Lite U PCI + +pci:v00001133d0000E00A* + ID_MODEL_FROM_DATABASE=Diva ISDN+V.90 PCI + +pci:v00001133d0000E00B* + ID_MODEL_FROM_DATABASE=Diva ISDN PCI 2.02 + +pci:v00001133d0000E00C* + ID_MODEL_FROM_DATABASE=Diva 2.02 PCI U + +pci:v00001133d0000E00D* + ID_MODEL_FROM_DATABASE=Diva Pro 3.0 PCI + +pci:v00001133d0000E00E* + ID_MODEL_FROM_DATABASE=Diva ISDN+CT S/T PCI Rev 2 + +pci:v00001133d0000E010* + ID_MODEL_FROM_DATABASE=Diva Server BRI-2M PCI + +pci:v00001133d0000E010sv0000110Asd00000021* + ID_MODEL_FROM_DATABASE=Diva Server BRI-2M PCI (Fujitsu Siemens ISDN S0) + +pci:v00001133d0000E011* + ID_MODEL_FROM_DATABASE=Diva Server BRI S/T Rev 2 + +pci:v00001133d0000E012* + ID_MODEL_FROM_DATABASE=Diva Server 4BRI-8M PCI + +pci:v00001133d0000E013* + ID_MODEL_FROM_DATABASE=4BRI + +pci:v00001133d0000E013sv00001133sd00001300* + ID_MODEL_FROM_DATABASE=4BRI (Diva V-4BRI-8 PCI v2) + +pci:v00001133d0000E013sv00001133sd0000E013* + ID_MODEL_FROM_DATABASE=4BRI (Diva 4BRI-8 PCI v2) + +pci:v00001133d0000E014* + ID_MODEL_FROM_DATABASE=Diva Server PRI-30M PCI + +pci:v00001133d0000E015* + ID_MODEL_FROM_DATABASE=Diva PRI PCI v2 + +pci:v00001133d0000E016* + ID_MODEL_FROM_DATABASE=Diva Server Voice 4BRI PCI + +pci:v00001133d0000E017* + ID_MODEL_FROM_DATABASE=Diva Server Voice 4BRI Rev 2 + +pci:v00001133d0000E017sv00001133sd0000E017* + ID_MODEL_FROM_DATABASE=Diva Server Voice 4BRI Rev 2 (Diva Server Voice 4BRI-8M 2.0 PCI) + +pci:v00001133d0000E018* + ID_MODEL_FROM_DATABASE=BRI + +pci:v00001133d0000E018sv00001133sd00001800* + ID_MODEL_FROM_DATABASE=BRI (Diva V-BRI-2 PCI v2) + +pci:v00001133d0000E018sv00001133sd0000E018* + ID_MODEL_FROM_DATABASE=BRI (Diva BRI-2 PCI v2) + +pci:v00001133d0000E019* + ID_MODEL_FROM_DATABASE=Diva Server Voice PRI Rev 2 + +pci:v00001133d0000E019sv00001133sd0000E019* + ID_MODEL_FROM_DATABASE=Diva Server Voice PRI Rev 2 (Diva Server Voice PRI 2.0 PCI) + +pci:v00001133d0000E01A* + ID_MODEL_FROM_DATABASE=Diva BRI-2FX PCI v2 + +pci:v00001133d0000E01B* + ID_MODEL_FROM_DATABASE=Diva Server Voice BRI-2M 2.0 PCI + +pci:v00001133d0000E01Bsv00001133sd0000E01B* + ID_MODEL_FROM_DATABASE=Diva Server Voice BRI-2M 2.0 PCI + +pci:v00001133d0000E01C* + ID_MODEL_FROM_DATABASE=PRI + +pci:v00001133d0000E01Csv00001133sd00001C01* + ID_MODEL_FROM_DATABASE=PRI (Diva PRI/E1/T1-8 PCI v3) + +pci:v00001133d0000E01Csv00001133sd00001C02* + ID_MODEL_FROM_DATABASE=PRI (Diva PRI/T1-24 PCI(e) v3) + +pci:v00001133d0000E01Csv00001133sd00001C03* + ID_MODEL_FROM_DATABASE=PRI (Diva PRI/E1-30 PCI(e) v3) + +pci:v00001133d0000E01Csv00001133sd00001C04* + ID_MODEL_FROM_DATABASE=PRI (Diva PRI/E1/T1-CTI PCI(e) v3) + +pci:v00001133d0000E01Csv00001133sd00001C05* + ID_MODEL_FROM_DATABASE=PRI (Diva V-PRI/T1-24 PCI(e) v3) + +pci:v00001133d0000E01Csv00001133sd00001C06* + ID_MODEL_FROM_DATABASE=PRI (Diva V-PRI/E1-30 PCI(e) v3) + +pci:v00001133d0000E01Csv00001133sd00001C07* + ID_MODEL_FROM_DATABASE=PRI (Diva Server PRI/E1/T1-8 Cornet NQ) + +pci:v00001133d0000E01Csv00001133sd00001C08* + ID_MODEL_FROM_DATABASE=PRI (Diva Server PRI/T1-24 Cornet NQ) + +pci:v00001133d0000E01Csv00001133sd00001C09* + ID_MODEL_FROM_DATABASE=PRI (Diva Server PRI/E1-30 Cornet NQ) + +pci:v00001133d0000E01Csv00001133sd00001C0A* + ID_MODEL_FROM_DATABASE=PRI (Diva Server PRI/E1/T1 Cornet NQ) + +pci:v00001133d0000E01Csv00001133sd00001C0B* + ID_MODEL_FROM_DATABASE=PRI (Diva Server V-PRI/T1-24 Cornet NQ) + +pci:v00001133d0000E01Csv00001133sd00001C0C* + ID_MODEL_FROM_DATABASE=PRI (Diva Server V-PRI/E1-30 Cornet NQ) + +pci:v00001133d0000E01E* + ID_MODEL_FROM_DATABASE=2PRI + +pci:v00001133d0000E01Esv00001133sd00001E01* + ID_MODEL_FROM_DATABASE=2PRI (Diva 2PRI/E1/T1-60 PCI v1) + +pci:v00001133d0000E01Esv00001133sd0000E01E* + ID_MODEL_FROM_DATABASE=2PRI (Diva V-2PRI/E1/T1-60 PCI v1) + +pci:v00001133d0000E020* + ID_MODEL_FROM_DATABASE=4PRI + +pci:v00001133d0000E020sv00001133sd00002001* + ID_MODEL_FROM_DATABASE=4PRI (Diva 4PRI/E1/T1-120 PCI v1) + +pci:v00001133d0000E020sv00001133sd0000E020* + ID_MODEL_FROM_DATABASE=4PRI (Diva V-4PRI/E1/T1-120 PCI v1) + +pci:v00001133d0000E022* + ID_MODEL_FROM_DATABASE=Analog-2 + +pci:v00001133d0000E022sv00001133sd00002200* + ID_MODEL_FROM_DATABASE=Analog-2 (Diva V-Analog-2 PCI v1) + +pci:v00001133d0000E022sv00001133sd0000E022* + ID_MODEL_FROM_DATABASE=Analog-2 (Diva Analog-2 PCI v1) + +pci:v00001133d0000E024* + ID_MODEL_FROM_DATABASE=Analog-4 + +pci:v00001133d0000E024sv00001133sd00002400* + ID_MODEL_FROM_DATABASE=Analog-4 (Diva V-Analog-4 PCI v1) + +pci:v00001133d0000E024sv00001133sd0000E024* + ID_MODEL_FROM_DATABASE=Analog-4 (Diva Analog-4 PCI v1) + +pci:v00001133d0000E028* + ID_MODEL_FROM_DATABASE=Analog-8 + +pci:v00001133d0000E028sv00001133sd00002800* + ID_MODEL_FROM_DATABASE=Analog-8 (Diva V-Analog-8 PCI v1) + +pci:v00001133d0000E028sv00001133sd0000E028* + ID_MODEL_FROM_DATABASE=Analog-8 (Diva Analog-8 PCI v1) + +pci:v00001133d0000E02A* + ID_MODEL_FROM_DATABASE=Diva IPM-300 PCI v1 + +pci:v00001133d0000E02C* + ID_MODEL_FROM_DATABASE=Diva IPM-600 PCI v1 + +pci:v00001133d0000E02E* + ID_MODEL_FROM_DATABASE=4BRI + +pci:v00001133d0000E02Esv00001133sd00002E01* + ID_MODEL_FROM_DATABASE=4BRI (Diva V-4BRI-8 PCIe v2) + +pci:v00001133d0000E02Esv00001133sd0000E02E* + ID_MODEL_FROM_DATABASE=4BRI (Diva 4BRI-8 PCIe v2) + +pci:v00001133d0000E032* + ID_MODEL_FROM_DATABASE=BRI + +pci:v00001133d0000E032sv00001133sd00003201* + ID_MODEL_FROM_DATABASE=BRI (Diva V-BRI-2 PCIe v2) + +pci:v00001133d0000E032sv00001133sd0000E032* + ID_MODEL_FROM_DATABASE=BRI (Diva BRI-2 PCIe v2) + +pci:v00001133d0000E034* + ID_MODEL_FROM_DATABASE=Diva BRI-CTI PCI v2 + +pci:v00001134* + ID_VENDOR_FROM_DATABASE=Mercury Computer Systems + +pci:v00001134d00000001* + ID_MODEL_FROM_DATABASE=Raceway Bridge + +pci:v00001134d00000002* + ID_MODEL_FROM_DATABASE=Dual PCI to RapidIO Bridge + +pci:v00001134d0000000B* + ID_MODEL_FROM_DATABASE=POET Serial RapidIO Bridge + +pci:v00001134d0000000D* + ID_MODEL_FROM_DATABASE=POET PSDMS Device + +pci:v00001135* + ID_VENDOR_FROM_DATABASE=Fuji Xerox Co Ltd + +pci:v00001135d00000001* + ID_MODEL_FROM_DATABASE=Printer controller + +pci:v00001136* + ID_VENDOR_FROM_DATABASE=Momentum Data Systems + +pci:v00001136d00000002* + ID_MODEL_FROM_DATABASE=PCI-JTAG + +pci:v00001137* + ID_VENDOR_FROM_DATABASE=Cisco Systems Inc + +pci:v00001137d00000023* + ID_MODEL_FROM_DATABASE=VIC 81 PCIe Upstream Port + +pci:v00001137d00000040* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port + +pci:v00001137d00000040sv00001137sd0000004F* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1280 Dual 40Gb Mezzanine) + +pci:v00001137d00000040sv00001137sd00000084* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1240 Dual 40Gb MLOM) + +pci:v00001137d00000040sv00001137sd00000085* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1225 Dual 10Gb SFP+ PCIe) + +pci:v00001137d00000040sv00001137sd000000CD* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1285 Dual 40Gb QSFP+ PCIe) + +pci:v00001137d00000040sv00001137sd000000CE* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1225T Dual 10GBaseT PCIe) + +pci:v00001137d00000040sv00001137sd0000012A* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC M4308 Dual 40Gb) + +pci:v00001137d00000040sv00001137sd0000012C* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1340 Dual 40Gb MLOM) + +pci:v00001137d00000040sv00001137sd0000012E* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1227 Dual 10Gb SFP+ PCIe) + +pci:v00001137d00000040sv00001137sd00000137* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1380 Dual 40Gb Mezzanine) + +pci:v00001137d00000040sv00001137sd0000014D* + ID_MODEL_FROM_DATABASE=VIC PCIe Upstream Port (VIC 1385 Dual 40Gb PCIe) + +pci:v00001137d00000041* + ID_MODEL_FROM_DATABASE=VIC PCIe Downstream Port + +pci:v00001137d00000042* + ID_MODEL_FROM_DATABASE=VIC Management Controller + +pci:v00001137d00000042sv00001137sd00000047* + ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC P81E PCIe Management Controller) + +pci:v00001137d00000042sv00001137sd00000085* + ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1225 PCIe Management Controller) + +pci:v00001137d00000042sv00001137sd000000CD* + ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1285 PCIe Management Controller) + +pci:v00001137d00000042sv00001137sd000000CE* + ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1225T PCIe Management Controller) + +pci:v00001137d00000042sv00001137sd0000012E* + ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1227 PCIe Management Controller) + +pci:v00001137d00000042sv00001137sd0000014D* + ID_MODEL_FROM_DATABASE=VIC Management Controller (VIC 1385 PCIe Management Controller) + +pci:v00001137d00000043* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC + +pci:v00001137d00000043sv00001137sd00000047* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC P81E PCIe Ethernet NIC) + +pci:v00001137d00000043sv00001137sd00000048* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC M81KR Mezzanine Ethernet NIC) + +pci:v00001137d00000043sv00001137sd0000004F* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1280 Mezzanine Ethernet NIC) + +pci:v00001137d00000043sv00001137sd00000084* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1240 MLOM Ethernet NIC) + +pci:v00001137d00000043sv00001137sd00000085* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1225 PCIe Ethernet NIC) + +pci:v00001137d00000043sv00001137sd000000CD* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1285 PCIe Ethernet NIC) + +pci:v00001137d00000043sv00001137sd000000CE* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1225T PCIe Ethernet NIC) + +pci:v00001137d00000043sv00001137sd0000012A* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC M4308 Ethernet NIC) + +pci:v00001137d00000043sv00001137sd0000012C* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1340 MLOM Ethernet NIC) + +pci:v00001137d00000043sv00001137sd0000012E* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1227 PCIe Ethernet NIC) + +pci:v00001137d00000043sv00001137sd00000137* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1380 Mezzanine Ethernet NIC) + +pci:v00001137d00000043sv00001137sd0000014D* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1385 PCIe Ethernet NIC) + +pci:v00001137d00000043sv00001137sd0000015D* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1387 MLOM Ethernet NIC) + +pci:v00001137d00000043sv00001137sd00000215* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1440 Mezzanine Ethernet NIC) + +pci:v00001137d00000043sv00001137sd00000216* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1480 MLOM Ethernet NIC) + +pci:v00001137d00000043sv00001137sd00000217* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1455 PCIe Ethernet NIC) + +pci:v00001137d00000043sv00001137sd00000218* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1457 MLOM Ethernet NIC) + +pci:v00001137d00000043sv00001137sd00000219* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1485 PCIe Ethernet NIC) + +pci:v00001137d00000043sv00001137sd0000021A* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1487 MLOM Ethernet NIC) + +pci:v00001137d00000043sv00001137sd0000024A* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1495 PCIe Ethernet NIC) + +pci:v00001137d00000043sv00001137sd0000024B* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC (VIC 1497 MLOM Ethernet NIC) + +pci:v00001137d00000044* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic + +pci:v00001137d00000044sv00001137sd00000047* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC P81E PCIe Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd00000048* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC M81KR Mezzanine Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd0000004F* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1280 Mezzanine Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd00000084* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1240 MLOM Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd00000085* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1225 PCIe Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd000000CD* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1285 PCIe Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd000000CE* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1225T PCIe Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd0000012A* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC M4308 Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd0000012C* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1340 MLOM Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd0000012E* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1227 PCIe Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd00000137* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1380 Mezzanine Ethernet NIC Dynamic) + +pci:v00001137d00000044sv00001137sd0000014D* + ID_MODEL_FROM_DATABASE=VIC Ethernet NIC Dynamic (VIC 1385 PCIe Ethernet NIC Dynamic) + +pci:v00001137d00000045* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA + +pci:v00001137d00000045sv00001137sd00000047* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC P81E PCIe FCoE HBA) + +pci:v00001137d00000045sv00001137sd00000048* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC M81KR Mezzanine FCoE HBA) + +pci:v00001137d00000045sv00001137sd0000004F* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1280 Mezzanine FCoE HBA) + +pci:v00001137d00000045sv00001137sd00000084* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1240 MLOM FCoE HBA) + +pci:v00001137d00000045sv00001137sd00000085* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1225 PCIe FCoE HBA) + +pci:v00001137d00000045sv00001137sd000000CD* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1285 PCIe FCoE HBA) + +pci:v00001137d00000045sv00001137sd000000CE* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1225T PCIe FCoE HBA) + +pci:v00001137d00000045sv00001137sd0000012A* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC M4308 FCoE HBA) + +pci:v00001137d00000045sv00001137sd0000012C* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1340 MLOM FCoE HBA) + +pci:v00001137d00000045sv00001137sd0000012E* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1227 PCIe FCoE HBA) + +pci:v00001137d00000045sv00001137sd00000137* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1380 Mezzanine FCoE HBA) + +pci:v00001137d00000045sv00001137sd0000014D* + ID_MODEL_FROM_DATABASE=VIC FCoE HBA (VIC 1385 PCIe FCoE HBA) + +pci:v00001137d00000046* + ID_MODEL_FROM_DATABASE=VIC SCSI Controller + +pci:v00001137d00000046sv00001137sd0000012A* + ID_MODEL_FROM_DATABASE=VIC SCSI Controller (VIC M4308 SCSI Controller) + +pci:v00001137d0000004E* + ID_MODEL_FROM_DATABASE=VIC 82 PCIe Upstream Port + +pci:v00001137d00000071* + ID_MODEL_FROM_DATABASE=VIC SR-IOV VF + +pci:v00001137d0000007A* + ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port + +pci:v00001137d0000007Asv00001137sd0000012A* + ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port (VIC M4308 Dual 40Gb) + +pci:v00001137d0000007Asv00001137sd0000012C* + ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port (VIC 1340 Dual 40Gb MLOM) + +pci:v00001137d0000007Asv00001137sd00000137* + ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port (VIC 1380 Dual 40Gb Mezzanine) + +pci:v00001137d0000007Asv00001137sd0000014D* + ID_MODEL_FROM_DATABASE=VIC 1300 PCIe Upstream Port (VIC 1385 Dual 40Gb PCIe) + +pci:v00001137d000000CF* + ID_MODEL_FROM_DATABASE=VIC Userspace NIC + +pci:v00001137d000000CFsv00001137sd0000004F* + ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1280 Mezzanine Userspace NIC) + +pci:v00001137d000000CFsv00001137sd00000084* + ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1240 MLOM Userspace NIC) + +pci:v00001137d000000CFsv00001137sd00000085* + ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1225 PCIe Userspace NIC) + +pci:v00001137d000000CFsv00001137sd000000CD* + ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1285 PCIe Userspace NIC) + +pci:v00001137d000000CFsv00001137sd000000CE* + ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1225T PCIe Userspace NIC) + +pci:v00001137d000000CFsv00001137sd0000012A* + ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC M4308 Userspace NIC) + +pci:v00001137d000000CFsv00001137sd0000012C* + ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1340 MLOM Userspace NIC) + +pci:v00001137d000000CFsv00001137sd0000012E* + ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1227 PCIe Userspace NIC) + +pci:v00001137d000000CFsv00001137sd00000137* + ID_MODEL_FROM_DATABASE=VIC Userspace NIC (VIC 1380 Mezzanine Userspace NIC) + +pci:v00001137d0000023E* + ID_MODEL_FROM_DATABASE=1GigE I350 LOM + +pci:v00001138* + ID_VENDOR_FROM_DATABASE=Ziatech Corporation + +pci:v00001138d00008905* + ID_MODEL_FROM_DATABASE=8905 [STD 32 Bridge] + +pci:v00001139* + ID_VENDOR_FROM_DATABASE=Dynamic Pictures, Inc + +pci:v00001139d00000001* + ID_MODEL_FROM_DATABASE=VGA Compatible 3D Graphics + +pci:v0000113A* + ID_VENDOR_FROM_DATABASE=FWB Inc + +pci:v0000113B* + ID_VENDOR_FROM_DATABASE=Network Computing Devices + +pci:v0000113C* + ID_VENDOR_FROM_DATABASE=Cyclone Microsystems, Inc. + +pci:v0000113Cd00000000* + ID_MODEL_FROM_DATABASE=PCI-9060 i960 Bridge + +pci:v0000113Cd00000001* + ID_MODEL_FROM_DATABASE=PCI-SDK [PCI i960 Evaluation Platform] + +pci:v0000113Cd00000911* + ID_MODEL_FROM_DATABASE=PCI-911 [i960Jx-based Intelligent I/O Controller] + +pci:v0000113Cd00000912* + ID_MODEL_FROM_DATABASE=PCI-912 [i960CF-based Intelligent I/O Controller] + +pci:v0000113Cd00000913* + ID_MODEL_FROM_DATABASE=PCI-913 + +pci:v0000113Cd00000914* + ID_MODEL_FROM_DATABASE=PCI-914 [I/O Controller w/ secondary PCI bus] + +pci:v0000113D* + ID_VENDOR_FROM_DATABASE=Leading Edge Products Inc + +pci:v0000113E* + ID_VENDOR_FROM_DATABASE=Sanyo Electric Co - Computer Engineering Dept + +pci:v0000113F* + ID_VENDOR_FROM_DATABASE=Equinox Systems, Inc. + +pci:v0000113Fd00000808* + ID_MODEL_FROM_DATABASE=SST-64P Adapter + +pci:v0000113Fd00001010* + ID_MODEL_FROM_DATABASE=SST-128P Adapter + +pci:v0000113Fd000080C0* + ID_MODEL_FROM_DATABASE=SST-16P DB Adapter + +pci:v0000113Fd000080C4* + ID_MODEL_FROM_DATABASE=SST-16P RJ Adapter + +pci:v0000113Fd000080C8* + ID_MODEL_FROM_DATABASE=SST-16P Adapter + +pci:v0000113Fd00008888* + ID_MODEL_FROM_DATABASE=SST-4P Adapter + +pci:v0000113Fd00009090* + ID_MODEL_FROM_DATABASE=SST-8P Adapter + +pci:v00001140* + ID_VENDOR_FROM_DATABASE=Intervoice Inc + +pci:v00001141* + ID_VENDOR_FROM_DATABASE=Crest Microsystem Inc + +pci:v00001142* + ID_VENDOR_FROM_DATABASE=Alliance Semiconductor Corporation + +pci:v00001142d00003210* + ID_MODEL_FROM_DATABASE=AP6410 + +pci:v00001142d00006422* + ID_MODEL_FROM_DATABASE=ProVideo 6422 + +pci:v00001142d00006424* + ID_MODEL_FROM_DATABASE=ProVideo 6424 + +pci:v00001142d00006425* + ID_MODEL_FROM_DATABASE=ProMotion AT25 + +pci:v00001142d0000643D* + ID_MODEL_FROM_DATABASE=ProMotion AT3D + +pci:v00001143* + ID_VENDOR_FROM_DATABASE=NetPower, Inc + +pci:v00001144* + ID_VENDOR_FROM_DATABASE=Cincinnati Milacron + +pci:v00001144d00000001* + ID_MODEL_FROM_DATABASE=Noservo controller + +pci:v00001145* + ID_VENDOR_FROM_DATABASE=Workbit Corporation + +pci:v00001145d00008007* + ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Workbit + +pci:v00001145d0000F007* + ID_MODEL_FROM_DATABASE=NinjaSCSI-32 KME + +pci:v00001145d0000F010* + ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Workbit + +pci:v00001145d0000F012* + ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Logitec + +pci:v00001145d0000F013* + ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Logitec + +pci:v00001145d0000F015* + ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Melco + +pci:v00001145d0000F020* + ID_MODEL_FROM_DATABASE=NinjaSCSI-32 Sony PCGA-DVD51 + +pci:v00001145d0000F021* + ID_MODEL_FROM_DATABASE=NinjaPATA-32 Delkin Cardbus UDMA + +pci:v00001145d0000F024* + ID_MODEL_FROM_DATABASE=NinjaPATA-32 Delkin Cardbus UDMA + +pci:v00001145d0000F103* + ID_MODEL_FROM_DATABASE=NinjaPATA-32 Delkin Cardbus UDMA + +pci:v00001146* + ID_VENDOR_FROM_DATABASE=Force Computers + +pci:v00001147* + ID_VENDOR_FROM_DATABASE=Interface Corp + +pci:v00001148* + ID_VENDOR_FROM_DATABASE=SysKonnect + +pci:v00001148d00004000* + ID_MODEL_FROM_DATABASE=FDDI Adapter + +pci:v00001148d00004000sv00000E11sd0000B03B* + ID_MODEL_FROM_DATABASE=FDDI Adapter (Netelligent 100 FDDI DAS Fibre SC) + +pci:v00001148d00004000sv00000E11sd0000B03C* + ID_MODEL_FROM_DATABASE=FDDI Adapter (Netelligent 100 FDDI SAS Fibre SC) + +pci:v00001148d00004000sv00000E11sd0000B03D* + ID_MODEL_FROM_DATABASE=FDDI Adapter (Netelligent 100 FDDI DAS UTP) + +pci:v00001148d00004000sv00000E11sd0000B03E* + ID_MODEL_FROM_DATABASE=FDDI Adapter (Netelligent 100 FDDI SAS UTP) + +pci:v00001148d00004000sv00000E11sd0000B03F* + ID_MODEL_FROM_DATABASE=FDDI Adapter (Netelligent 100 FDDI SAS Fibre MIC) + +pci:v00001148d00004000sv00001148sd00005521* + ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5521 (SK-NET FDDI-UP)) + +pci:v00001148d00004000sv00001148sd00005522* + ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5522 (SK-NET FDDI-UP DAS)) + +pci:v00001148d00004000sv00001148sd00005541* + ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5541 (SK-NET FDDI-FP)) + +pci:v00001148d00004000sv00001148sd00005543* + ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5543 (SK-NET FDDI-LP)) + +pci:v00001148d00004000sv00001148sd00005544* + ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5544 (SK-NET FDDI-LP DAS)) + +pci:v00001148d00004000sv00001148sd00005821* + ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5821 (SK-NET FDDI-UP64)) + +pci:v00001148d00004000sv00001148sd00005822* + ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5822 (SK-NET FDDI-UP64 DAS)) + +pci:v00001148d00004000sv00001148sd00005841* + ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5841 (SK-NET FDDI-FP64)) + +pci:v00001148d00004000sv00001148sd00005843* + ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5843 (SK-NET FDDI-LP64)) + +pci:v00001148d00004000sv00001148sd00005844* + ID_MODEL_FROM_DATABASE=FDDI Adapter (FDDI SK-5844 (SK-NET FDDI-LP64 DAS)) + +pci:v00001148d00004200* + ID_MODEL_FROM_DATABASE=Token Ring adapter + +pci:v00001148d00004300* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) + +pci:v00001148d00004300sv00001148sd00009821* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)) + +pci:v00001148d00004300sv00001148sd00009822* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)) + +pci:v00001148d00004300sv00001148sd00009841* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)) + +pci:v00001148d00004300sv00001148sd00009842* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)) + +pci:v00001148d00004300sv00001148sd00009843* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)) + +pci:v00001148d00004300sv00001148sd00009844* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)) + +pci:v00001148d00004300sv00001148sd00009861* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)) + +pci:v00001148d00004300sv00001148sd00009862* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)) + +pci:v00001148d00004300sv00001148sd00009871* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)) + +pci:v00001148d00004300sv00001148sd00009872* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) + +pci:v00001148d00004300sv00001259sd00002970* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970SX Gigabit Ethernet Adapter) + +pci:v00001148d00004300sv00001259sd00002971* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970LX Gigabit Ethernet Adapter) + +pci:v00001148d00004300sv00001259sd00002972* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970TX Gigabit Ethernet Adapter) + +pci:v00001148d00004300sv00001259sd00002973* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2971SX Gigabit Ethernet Adapter) + +pci:v00001148d00004300sv00001259sd00002974* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2971T Gigabit Ethernet Adapter) + +pci:v00001148d00004300sv00001259sd00002975* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970SX/2SC Gigabit Ethernet Adapter) + +pci:v00001148d00004300sv00001259sd00002976* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970LX/2SC Gigabit Ethernet Adapter) + +pci:v00001148d00004300sv00001259sd00002977* + ID_MODEL_FROM_DATABASE=SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) (AT-2970TX/2TX Gigabit Ethernet Adapter) + +pci:v00001148d00004320* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] + +pci:v00001148d00004320sv00001148sd00000121* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (Marvell RDK-8001 Adapter) + +pci:v00001148d00004320sv00001148sd00000221* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (Marvell RDK-8002 Adapter) + +pci:v00001148d00004320sv00001148sd00000321* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (Marvell RDK-8003 Adapter) + +pci:v00001148d00004320sv00001148sd00000421* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (Marvell RDK-8004 Adapter) + +pci:v00001148d00004320sv00001148sd00000621* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (Marvell RDK-8006 Adapter) + +pci:v00001148d00004320sv00001148sd00000721* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (Marvell RDK-8007 Adapter) + +pci:v00001148d00004320sv00001148sd00000821* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (Marvell RDK-8008 Adapter) + +pci:v00001148d00004320sv00001148sd00000921* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (Marvell RDK-8009 Adapter) + +pci:v00001148d00004320sv00001148sd00001121* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (Marvell RDK-8011 Adapter) + +pci:v00001148d00004320sv00001148sd00001221* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (Marvell RDK-8012 Adapter) + +pci:v00001148d00004320sv00001148sd00003221* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (SK-9521 V2.0 10/100/1000Base-T Adapter) + +pci:v00001148d00004320sv00001148sd00005021* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter) + +pci:v00001148d00004320sv00001148sd00005041* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter) + +pci:v00001148d00004320sv00001148sd00005043* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter) + +pci:v00001148d00004320sv00001148sd00005051* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter) + +pci:v00001148d00004320sv00001148sd00005061* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter) + +pci:v00001148d00004320sv00001148sd00005071* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter) + +pci:v00001148d00004320sv00001148sd00009521* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (SK-9521 10/100/1000Base-T Adapter) + +pci:v00001148d00004320sv00001259sd00002916* + ID_MODEL_FROM_DATABASE=SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] (AT-2916T) + +pci:v00001148d00004400* + ID_MODEL_FROM_DATABASE=SK-9Dxx Gigabit Ethernet Adapter + +pci:v00001148d00004500* + ID_MODEL_FROM_DATABASE=SK-9Mxx Gigabit Ethernet Adapter + +pci:v00001148d00009000* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] + +pci:v00001148d00009000sv00001148sd00002100* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (SK-9S21 10/100/1000Base-T Server Adapter, PCI-X, Copper RJ-45) + +pci:v00001148d00009000sv00001148sd00002200* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (SK-9S22 10/100/1000Base-T Dual Port Server Adapter, PCI-X, 2 Copper RJ-45) + +pci:v00001148d00009000sv00001148sd00002210* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (SK-9P22 10/100/1000 Base-T Dual Port PMC card) + +pci:v00001148d00009000sv00001148sd00002220* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (TPMC-GBE-CO) + +pci:v00001148d00009000sv00001148sd00008100* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (SK-9S81 1000Base-SX Server Adapter,PCI-X, Fiber SX/LC) + +pci:v00001148d00009000sv00001148sd00008200* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (SK-9S82 1000Base-SX Dual Port Server Adapter, PCI-X, 2 Fiber SX/LC) + +pci:v00001148d00009000sv00001148sd00008210* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (SK-9P82 1000 Base-SX Dual Port PMC card) + +pci:v00001148d00009000sv00001148sd00008220* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (TPMC-GBE-FI) + +pci:v00001148d00009000sv00001148sd00009100* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (SK-9S91 1000Base-LX Server Adapter,PCI-X, Fiber LX/LC) + +pci:v00001148d00009000sv00001148sd00009200* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (SK-9S92 1000Base-LX Dual Port Server Adapter, PCI-X, 2 Fiber LX/LC) + +pci:v00001148d00009000sv00001259sd00002973* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (AT-2971SX v2 Gigabit Adapter) + +pci:v00001148d00009000sv00001259sd00002974* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (AT-2971T v2 Gigabit Adapter) + +pci:v00001148d00009000sv00001259sd00002978* + ID_MODEL_FROM_DATABASE=SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] (AT-2971LX Gigabit Adapter) + +pci:v00001148d00009843* + ID_MODEL_FROM_DATABASE=[Fujitsu] Gigabit Ethernet + +pci:v00001148d00009E00* + ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 + +pci:v00001148d00009E00sv00001148sd00002100* + ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E21 Server Adapter) + +pci:v00001148d00009E00sv00001148sd000021D0* + ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E21D 10/100/1000Base-T Adapter) + +pci:v00001148d00009E00sv00001148sd00002200* + ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E22 Server Adapter) + +pci:v00001148d00009E00sv00001148sd00008100* + ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E81 Server Adapter) + +pci:v00001148d00009E00sv00001148sd00008200* + ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E82 Server Adapter) + +pci:v00001148d00009E00sv00001148sd00009100* + ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E91 Server Adapter) + +pci:v00001148d00009E00sv00001148sd00009200* + ID_MODEL_FROM_DATABASE=SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 (SK-9E92 Server Adapter) + +pci:v00001148d00009E01* + ID_MODEL_FROM_DATABASE=SK-9E21M 10/100/1000Base-T Adapter + +pci:v00001149* + ID_VENDOR_FROM_DATABASE=Win System Corporation + +pci:v0000114A* + ID_VENDOR_FROM_DATABASE=VMIC + +pci:v0000114Ad00005565* + ID_MODEL_FROM_DATABASE=GE-IP PCI5565,PMC5565 Reflective Memory Node + +pci:v0000114Ad00005579* + ID_MODEL_FROM_DATABASE=VMIPCI-5579 (Reflective Memory Card) + +pci:v0000114Ad00005587* + ID_MODEL_FROM_DATABASE=VMIPCI-5587 (Reflective Memory Card) + +pci:v0000114Ad00006504* + ID_MODEL_FROM_DATABASE=VMIC PCI 7755 FPGA + +pci:v0000114Ad00007587* + ID_MODEL_FROM_DATABASE=VMIVME-7587 + +pci:v0000114B* + ID_VENDOR_FROM_DATABASE=Canopus Co., Ltd + +pci:v0000114C* + ID_VENDOR_FROM_DATABASE=Annabooks + +pci:v0000114D* + ID_VENDOR_FROM_DATABASE=IC Corporation + +pci:v0000114E* + ID_VENDOR_FROM_DATABASE=Nikon Systems Inc + +pci:v0000114F* + ID_VENDOR_FROM_DATABASE=Digi International + +pci:v0000114Fd00000002* + ID_MODEL_FROM_DATABASE=AccelePort EPC + +pci:v0000114Fd00000003* + ID_MODEL_FROM_DATABASE=RightSwitch SE-6 + +pci:v0000114Fd00000004* + ID_MODEL_FROM_DATABASE=AccelePort Xem + +pci:v0000114Fd00000005* + ID_MODEL_FROM_DATABASE=AccelePort Xr + +pci:v0000114Fd00000006* + ID_MODEL_FROM_DATABASE=AccelePort Xr,C/X + +pci:v0000114Fd00000009* + ID_MODEL_FROM_DATABASE=AccelePort Xr/J + +pci:v0000114Fd0000000A* + ID_MODEL_FROM_DATABASE=AccelePort EPC/J + +pci:v0000114Fd0000000C* + ID_MODEL_FROM_DATABASE=DataFirePRIme T1 (1-port) + +pci:v0000114Fd0000000D* + ID_MODEL_FROM_DATABASE=SyncPort 2-Port (x.25/FR) + +pci:v0000114Fd00000011* + ID_MODEL_FROM_DATABASE=AccelePort 8r EIA-232 (IBM) + +pci:v0000114Fd00000012* + ID_MODEL_FROM_DATABASE=AccelePort 8r EIA-422 + +pci:v0000114Fd00000013* + ID_MODEL_FROM_DATABASE=AccelePort Xr + +pci:v0000114Fd00000014* + ID_MODEL_FROM_DATABASE=AccelePort 8r EIA-422 + +pci:v0000114Fd00000015* + ID_MODEL_FROM_DATABASE=AccelePort Xem + +pci:v0000114Fd00000016* + ID_MODEL_FROM_DATABASE=AccelePort EPC/X + +pci:v0000114Fd00000017* + ID_MODEL_FROM_DATABASE=AccelePort C/X + +pci:v0000114Fd0000001A* + ID_MODEL_FROM_DATABASE=DataFirePRIme E1 (1-port) + +pci:v0000114Fd0000001B* + ID_MODEL_FROM_DATABASE=AccelePort C/X (IBM) + +pci:v0000114Fd0000001C* + ID_MODEL_FROM_DATABASE=AccelePort Xr (SAIP) + +pci:v0000114Fd0000001D* + ID_MODEL_FROM_DATABASE=DataFire RAS T1/E1/PRI + +pci:v0000114Fd0000001Dsv0000114Fsd00000050* + ID_MODEL_FROM_DATABASE=DataFire RAS T1/E1/PRI (DataFire RAS E1 Adapter) + +pci:v0000114Fd0000001Dsv0000114Fsd00000051* + ID_MODEL_FROM_DATABASE=DataFire RAS T1/E1/PRI (DataFire RAS Dual E1 Adapter) + +pci:v0000114Fd0000001Dsv0000114Fsd00000052* + ID_MODEL_FROM_DATABASE=DataFire RAS T1/E1/PRI (DataFire RAS T1 Adapter) + +pci:v0000114Fd0000001Dsv0000114Fsd00000053* + ID_MODEL_FROM_DATABASE=DataFire RAS T1/E1/PRI (DataFire RAS Dual T1 Adapter) + +pci:v0000114Fd00000023* + ID_MODEL_FROM_DATABASE=AccelePort RAS + +pci:v0000114Fd00000024* + ID_MODEL_FROM_DATABASE=DataFire RAS B4 ST/U + +pci:v0000114Fd00000024sv0000114Fsd00000030* + ID_MODEL_FROM_DATABASE=DataFire RAS B4 ST/U (DataFire RAS BRI U Adapter) + +pci:v0000114Fd00000024sv0000114Fsd00000031* + ID_MODEL_FROM_DATABASE=DataFire RAS B4 ST/U (DataFire RAS BRI S/T Adapter) + +pci:v0000114Fd00000026* + ID_MODEL_FROM_DATABASE=AccelePort 4r 920 + +pci:v0000114Fd00000027* + ID_MODEL_FROM_DATABASE=AccelePort Xr 920 + +pci:v0000114Fd00000028* + ID_MODEL_FROM_DATABASE=ClassicBoard 4 + +pci:v0000114Fd00000029* + ID_MODEL_FROM_DATABASE=ClassicBoard 8 + +pci:v0000114Fd00000034* + ID_MODEL_FROM_DATABASE=AccelePort 2r 920 + +pci:v0000114Fd00000035* + ID_MODEL_FROM_DATABASE=DataFire DSP T1/E1/PRI cPCI + +pci:v0000114Fd00000040* + ID_MODEL_FROM_DATABASE=AccelePort Xp + +pci:v0000114Fd00000040sv0000114Fsd00000042* + ID_MODEL_FROM_DATABASE=AccelePort Xp (AccelePort 2p PCI) + +pci:v0000114Fd00000040sv0000114Fsd00000043* + ID_MODEL_FROM_DATABASE=AccelePort Xp (AccelePort 4p PCI) + +pci:v0000114Fd00000040sv0000114Fsd00000044* + ID_MODEL_FROM_DATABASE=AccelePort Xp (AccelePort 8p PCI) + +pci:v0000114Fd00000040sv0000114Fsd00000045* + ID_MODEL_FROM_DATABASE=AccelePort Xp (AccelePort 16p PCI) + +pci:v0000114Fd00000040sv0000114Fsd0000004E* + ID_MODEL_FROM_DATABASE=AccelePort Xp (AccelePort 32p PCI) + +pci:v0000114Fd00000042* + ID_MODEL_FROM_DATABASE=AccelePort 2p + +pci:v0000114Fd00000043* + ID_MODEL_FROM_DATABASE=AccelePort 4p + +pci:v0000114Fd00000044* + ID_MODEL_FROM_DATABASE=AccelePort 8p + +pci:v0000114Fd00000045* + ID_MODEL_FROM_DATABASE=AccelePort 16p + +pci:v0000114Fd0000004E* + ID_MODEL_FROM_DATABASE=AccelePort 32p + +pci:v0000114Fd00000070* + ID_MODEL_FROM_DATABASE=Datafire Micro V IOM2 (Europe) + +pci:v0000114Fd00000071* + ID_MODEL_FROM_DATABASE=Datafire Micro V (Europe) + +pci:v0000114Fd00000072* + ID_MODEL_FROM_DATABASE=Datafire Micro V IOM2 (North America) + +pci:v0000114Fd00000073* + ID_MODEL_FROM_DATABASE=Datafire Micro V (North America) + +pci:v0000114Fd000000B0* + ID_MODEL_FROM_DATABASE=Digi Neo 4 + +pci:v0000114Fd000000B1* + ID_MODEL_FROM_DATABASE=Digi Neo 8 + +pci:v0000114Fd000000C8* + ID_MODEL_FROM_DATABASE=Digi Neo 2 DB9 + +pci:v0000114Fd000000C9* + ID_MODEL_FROM_DATABASE=Digi Neo 2 DB9 PRI + +pci:v0000114Fd000000CA* + ID_MODEL_FROM_DATABASE=Digi Neo 2 RJ45 + +pci:v0000114Fd000000CB* + ID_MODEL_FROM_DATABASE=Digi Neo 2 RJ45 PRI + +pci:v0000114Fd000000CC* + ID_MODEL_FROM_DATABASE=Digi Neo 1 422 + +pci:v0000114Fd000000CD* + ID_MODEL_FROM_DATABASE=Digi Neo 1 422 485 + +pci:v0000114Fd000000CE* + ID_MODEL_FROM_DATABASE=Digi Neo 2 422 485 + +pci:v0000114Fd000000D0* + ID_MODEL_FROM_DATABASE=ClassicBoard 4 422 + +pci:v0000114Fd000000D1* + ID_MODEL_FROM_DATABASE=ClassicBoard 8 422 + +pci:v0000114Fd000000F1* + ID_MODEL_FROM_DATABASE=Digi Neo PCI-E 4 port + +pci:v0000114Fd000000F4* + ID_MODEL_FROM_DATABASE=Digi Neo 4 (IBM version) + +pci:v0000114Fd00006001* + ID_MODEL_FROM_DATABASE=Avanstar + +pci:v00001150* + ID_VENDOR_FROM_DATABASE=Thinking Machines Corp + +pci:v00001151* + ID_VENDOR_FROM_DATABASE=JAE Electronics Inc. + +pci:v00001152* + ID_VENDOR_FROM_DATABASE=Megatek + +pci:v00001153* + ID_VENDOR_FROM_DATABASE=Land Win Electronic Corp + +pci:v00001154* + ID_VENDOR_FROM_DATABASE=Melco Inc + +pci:v00001155* + ID_VENDOR_FROM_DATABASE=Pine Technology Ltd + +pci:v00001156* + ID_VENDOR_FROM_DATABASE=Periscope Engineering + +pci:v00001157* + ID_VENDOR_FROM_DATABASE=Avsys Corporation + +pci:v00001158* + ID_VENDOR_FROM_DATABASE=Voarx R & D Inc + +pci:v00001158d00003011* + ID_MODEL_FROM_DATABASE=Tokenet/vg 1001/10m anylan + +pci:v00001158d00009050* + ID_MODEL_FROM_DATABASE=Lanfleet/Truevalue + +pci:v00001158d00009051* + ID_MODEL_FROM_DATABASE=Lanfleet/Truevalue + +pci:v00001159* + ID_VENDOR_FROM_DATABASE=MuTech Corporation + +pci:v00001159d00000001* + ID_MODEL_FROM_DATABASE=MV-1000 + +pci:v00001159d00000002* + ID_MODEL_FROM_DATABASE=MV-1500 + +pci:v0000115A* + ID_VENDOR_FROM_DATABASE=Harlequin Ltd + +pci:v0000115B* + ID_VENDOR_FROM_DATABASE=Parallax Graphics + +pci:v0000115C* + ID_VENDOR_FROM_DATABASE=Photron Ltd. + +pci:v0000115D* + ID_VENDOR_FROM_DATABASE=Xircom + +pci:v0000115Dd00000003* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd00000003sv00001014sd00000181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) + +pci:v0000115Dd00000003sv00001014sd00001181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) + +pci:v0000115Dd00000003sv00001014sd00008181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) + +pci:v0000115Dd00000003sv00001014sd00009181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) + +pci:v0000115Dd00000003sv0000115Dsd00000181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd00000003sv0000115Dsd00000182* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (RealPort2 CardBus Ethernet 10/100 (R2BE-100)) + +pci:v0000115Dd00000003sv0000115Dsd00001181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd00000003sv00001179sd00000181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd00000003sv00008086sd00008181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (EtherExpress PRO/100 Mobile CardBus 32 Adapter) + +pci:v0000115Dd00000003sv00008086sd00009181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (EtherExpress PRO/100 Mobile CardBus 32 Adapter) + +pci:v0000115Dd00000005* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd00000005sv00001014sd00000182* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) + +pci:v0000115Dd00000005sv00001014sd00001182* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) + +pci:v0000115Dd00000005sv0000115Dsd00000182* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd00000005sv0000115Dsd00001182* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd00000007* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd00000007sv00001014sd00000182* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) + +pci:v0000115Dd00000007sv00001014sd00001182* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) + +pci:v0000115Dd00000007sv0000115Dsd00000182* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd00000007sv0000115Dsd00001182* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd0000000B* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd0000000Bsv00001014sd00000183* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) + +pci:v0000115Dd0000000Bsv0000115Dsd00000183* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd0000000C* + ID_MODEL_FROM_DATABASE=Mini-PCI V.90 56k Modem + +pci:v0000115Dd0000000F* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd0000000Fsv00001014sd00000183* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 (10/100 EtherJet Cardbus Adapter) + +pci:v0000115Dd0000000Fsv0000115Dsd00000183* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet 10/100 + +pci:v0000115Dd000000D4* + ID_MODEL_FROM_DATABASE=Mini-PCI K56Flex Modem + +pci:v0000115Dd00000101* + ID_MODEL_FROM_DATABASE=Cardbus 56k modem + +pci:v0000115Dd00000101sv0000115Dsd00001081* + ID_MODEL_FROM_DATABASE=Cardbus 56k modem (Cardbus 56k Modem) + +pci:v0000115Dd00000103* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet + 56k Modem + +pci:v0000115Dd00000103sv00001014sd00009181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet + 56k Modem (Cardbus 56k Modem) + +pci:v0000115Dd00000103sv00001115sd00001181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet + 56k Modem (Cardbus Ethernet 100 + 56k Modem) + +pci:v0000115Dd00000103sv0000115Dsd00001181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet + 56k Modem (CBEM56G-100 Ethernet + 56k Modem) + +pci:v0000115Dd00000103sv00008086sd00009181* + ID_MODEL_FROM_DATABASE=Cardbus Ethernet + 56k Modem (PRO/100 LAN + Modem56 CardBus) + +pci:v0000115E* + ID_VENDOR_FROM_DATABASE=Peer Protocols Inc + +pci:v0000115F* + ID_VENDOR_FROM_DATABASE=Maxtor Corporation + +pci:v00001160* + ID_VENDOR_FROM_DATABASE=Megasoft Inc + +pci:v00001161* + ID_VENDOR_FROM_DATABASE=PFU Limited + +pci:v00001162* + ID_VENDOR_FROM_DATABASE=OA Laboratory Co Ltd + +pci:v00001163* + ID_VENDOR_FROM_DATABASE=Rendition + +pci:v00001163d00000001* + ID_MODEL_FROM_DATABASE=Verite 1000 + +pci:v00001163d00002000* + ID_MODEL_FROM_DATABASE=Verite V2000/V2100/V2200 + +pci:v00001163d00002000sv00001092sd00002000* + ID_MODEL_FROM_DATABASE=Verite V2000/V2100/V2200 (Stealth II S220) + +pci:v00001164* + ID_VENDOR_FROM_DATABASE=Advanced Peripherals Technologies + +pci:v00001165* + ID_VENDOR_FROM_DATABASE=Imagraph Corporation + +pci:v00001165d00000001* + ID_MODEL_FROM_DATABASE=Motion TPEG Recorder/Player with audio + +pci:v00001166* + ID_VENDOR_FROM_DATABASE=Broadcom + +pci:v00001166d00000000* + ID_MODEL_FROM_DATABASE=CMIC-LE + +pci:v00001166d00000005* + ID_MODEL_FROM_DATABASE=CNB20-LE Host Bridge + +pci:v00001166d00000006* + ID_MODEL_FROM_DATABASE=CNB20HE Host Bridge + +pci:v00001166d00000007* + ID_MODEL_FROM_DATABASE=CNB20-LE Host Bridge + +pci:v00001166d00000008* + ID_MODEL_FROM_DATABASE=CNB20HE Host Bridge + +pci:v00001166d00000009* + ID_MODEL_FROM_DATABASE=CNB20LE Host Bridge + +pci:v00001166d00000010* + ID_MODEL_FROM_DATABASE=CIOB30 + +pci:v00001166d00000011* + ID_MODEL_FROM_DATABASE=CMIC-HE + +pci:v00001166d00000012* + ID_MODEL_FROM_DATABASE=CMIC-WS Host Bridge (GC-LE chipset) + +pci:v00001166d00000013* + ID_MODEL_FROM_DATABASE=CNB20-HE Host Bridge + +pci:v00001166d00000014* + ID_MODEL_FROM_DATABASE=CMIC-LE Host Bridge (GC-LE chipset) + +pci:v00001166d00000015* + ID_MODEL_FROM_DATABASE=CMIC-GC Host Bridge + +pci:v00001166d00000016* + ID_MODEL_FROM_DATABASE=CMIC-GC Host Bridge + +pci:v00001166d00000017* + ID_MODEL_FROM_DATABASE=GCNB-LE Host Bridge + +pci:v00001166d00000031* + ID_MODEL_FROM_DATABASE=HT1100 HPX0 HT Host Bridge + +pci:v00001166d00000036* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] PCI/PCI-X Bridge + +pci:v00001166d00000101* + ID_MODEL_FROM_DATABASE=CIOB-X2 PCI-X I/O Bridge + +pci:v00001166d00000103* + ID_MODEL_FROM_DATABASE=EPB PCI-Express to PCI-X Bridge + +pci:v00001166d00000104* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] PCI/PCI-X Bridge + +pci:v00001166d00000110* + ID_MODEL_FROM_DATABASE=CIOB-E I/O Bridge with Gigabit Ethernet + +pci:v00001166d00000130* + ID_MODEL_FROM_DATABASE=BCM5780 [HT2000] PCI-X bridge + +pci:v00001166d00000132* + ID_MODEL_FROM_DATABASE=BCM5780 [HT2000] PCI-Express Bridge + +pci:v00001166d00000132sv00001166sd00000132* + ID_MODEL_FROM_DATABASE=BCM5780 [HT2000] PCI-Express Bridge (HT2000 PCI-Express bridge) + +pci:v00001166d00000140* + ID_MODEL_FROM_DATABASE=HT2100 PCI-Express Bridge + +pci:v00001166d00000141* + ID_MODEL_FROM_DATABASE=HT2100 PCI-Express Bridge + +pci:v00001166d00000142* + ID_MODEL_FROM_DATABASE=HT2100 PCI-Express Bridge + +pci:v00001166d00000144* + ID_MODEL_FROM_DATABASE=HT2100 PCI-Express Bridge + +pci:v00001166d00000200* + ID_MODEL_FROM_DATABASE=OSB4 South Bridge + +pci:v00001166d00000201* + ID_MODEL_FROM_DATABASE=CSB5 South Bridge + +pci:v00001166d00000201sv00004C53sd00001080* + ID_MODEL_FROM_DATABASE=CSB5 South Bridge (CT8 mainboard) + +pci:v00001166d00000203* + ID_MODEL_FROM_DATABASE=CSB6 South Bridge + +pci:v00001166d00000203sv00001734sd00001012* + ID_MODEL_FROM_DATABASE=CSB6 South Bridge (PRIMERGY RX/TX series) + +pci:v00001166d00000205* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] Legacy South Bridge + +pci:v00001166d00000211* + ID_MODEL_FROM_DATABASE=OSB4 IDE Controller + +pci:v00001166d00000212* + ID_MODEL_FROM_DATABASE=CSB5 IDE Controller + +pci:v00001166d00000212sv00001028sd0000014A* + ID_MODEL_FROM_DATABASE=CSB5 IDE Controller (PowerEdge 1750) + +pci:v00001166d00000212sv00001028sd0000810B* + ID_MODEL_FROM_DATABASE=CSB5 IDE Controller (PowerEdge 1650/2550) + +pci:v00001166d00000212sv00004C53sd00001080* + ID_MODEL_FROM_DATABASE=CSB5 IDE Controller (CT8 mainboard) + +pci:v00001166d00000213* + ID_MODEL_FROM_DATABASE=CSB6 RAID/IDE Controller + +pci:v00001166d00000213sv00001028sd00004134* + ID_MODEL_FROM_DATABASE=CSB6 RAID/IDE Controller (PowerEdge 600SC) + +pci:v00001166d00000213sv00001028sd0000C134* + ID_MODEL_FROM_DATABASE=CSB6 RAID/IDE Controller (Poweredge SC600) + +pci:v00001166d00000213sv00001734sd00001012* + ID_MODEL_FROM_DATABASE=CSB6 RAID/IDE Controller (PRIMERGY RX/TX series onboard IDE) + +pci:v00001166d00000214* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] IDE + +pci:v00001166d00000214sv00001028sd00000205* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] IDE (PowerEdge 2970 HT1000 IDE) + +pci:v00001166d00000217* + ID_MODEL_FROM_DATABASE=CSB6 IDE Controller + +pci:v00001166d00000217sv00001028sd00004134* + ID_MODEL_FROM_DATABASE=CSB6 IDE Controller (Poweredge SC600) + +pci:v00001166d0000021B* + ID_MODEL_FROM_DATABASE=HT1100 HD Audio + +pci:v00001166d00000220* + ID_MODEL_FROM_DATABASE=OSB4/CSB5 OHCI USB Controller + +pci:v00001166d00000220sv00004C53sd00001080* + ID_MODEL_FROM_DATABASE=OSB4/CSB5 OHCI USB Controller (CT8 mainboard) + +pci:v00001166d00000221* + ID_MODEL_FROM_DATABASE=CSB6 OHCI USB Controller + +pci:v00001166d00000221sv00001734sd00001012* + ID_MODEL_FROM_DATABASE=CSB6 OHCI USB Controller (PRIMERGY RX/TX series onboard OHCI) + +pci:v00001166d00000223* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] USB + +pci:v00001166d00000223sv00001028sd00000205* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] USB (PowerEdge 2970 HT1000 USB Controller) + +pci:v00001166d00000223sv00001028sd0000020B* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] USB (PowerEdge T605 HT1000 USB Controller) + +pci:v00001166d00000225* + ID_MODEL_FROM_DATABASE=CSB5 LPC bridge + +pci:v00001166d00000227* + ID_MODEL_FROM_DATABASE=GCLE-2 Host Bridge + +pci:v00001166d00000227sv00001734sd00001012* + ID_MODEL_FROM_DATABASE=GCLE-2 Host Bridge (PRIMERGY RX/TX series) + +pci:v00001166d00000230* + ID_MODEL_FROM_DATABASE=CSB5 LPC bridge + +pci:v00001166d00000230sv00004C53sd00001080* + ID_MODEL_FROM_DATABASE=CSB5 LPC bridge (CT8 mainboard) + +pci:v00001166d00000234* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] LPC + +pci:v00001166d00000234sv00001028sd00000205* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] LPC (PowerEdge 2970 HT1000 LPC) + +pci:v00001166d00000234sv00001028sd0000020B* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] LPC (PowerEdge T605 HT1000 LPC) + +pci:v00001166d00000235* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] XIOAPIC0-2 + +pci:v00001166d00000238* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] WDTimer + +pci:v00001166d00000240* + ID_MODEL_FROM_DATABASE=K2 SATA + +pci:v00001166d00000241* + ID_MODEL_FROM_DATABASE=RAIDCore RC4000 + +pci:v00001166d00000242* + ID_MODEL_FROM_DATABASE=RAIDCore BC4000 + +pci:v00001166d0000024A* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] SATA (Native SATA Mode) + +pci:v00001166d0000024Asv00001028sd0000020B* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] SATA (Native SATA Mode) (PowerEdge T605 onboard SATA Controller) + +pci:v00001166d0000024B* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] SATA (PATA/IDE Mode) + +pci:v00001166d0000024Bsv00001028sd00000205* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] SATA (PATA/IDE Mode) (PowerEdge 2970 HT1000 SATA controller) + +pci:v00001166d00000406* + ID_MODEL_FROM_DATABASE=HT1100 PCI-X Bridge + +pci:v00001166d00000408* + ID_MODEL_FROM_DATABASE=HT1100 Legacy Device + +pci:v00001166d0000040A* + ID_MODEL_FROM_DATABASE=HT1100 ISA-LPC Bridge + +pci:v00001166d0000040Asv00001028sd00000223* + ID_MODEL_FROM_DATABASE=HT1100 ISA-LPC Bridge (PowerEdge R905 HT1100 ISA-LPC Bridge) + +pci:v00001166d00000410* + ID_MODEL_FROM_DATABASE=HT1100 SATA Controller (Native SATA Mode) + +pci:v00001166d00000411* + ID_MODEL_FROM_DATABASE=HT1100 SATA Controller (PATA / IDE Mode) + +pci:v00001166d00000412* + ID_MODEL_FROM_DATABASE=HT1100 USB OHCI Controller + +pci:v00001166d00000414* + ID_MODEL_FROM_DATABASE=HT1100 USB EHCI Controller + +pci:v00001166d00000416* + ID_MODEL_FROM_DATABASE=HT1100 USB EHCI Controller (with Debug Port) + +pci:v00001166d00000420* + ID_MODEL_FROM_DATABASE=HT1100 PCI-Express Bridge + +pci:v00001166d00000421* + ID_MODEL_FROM_DATABASE=HT1100 SAS/SATA Controller + +pci:v00001166d00000422* + ID_MODEL_FROM_DATABASE=HT1100 PCI-Express Bridge + +pci:v00001167* + ID_VENDOR_FROM_DATABASE=Mutoh Industries Inc + +pci:v00001168* + ID_VENDOR_FROM_DATABASE=Thine Electronics Inc + +pci:v00001169* + ID_VENDOR_FROM_DATABASE=Centre for Development of Advanced Computing + +pci:v0000116A* + ID_VENDOR_FROM_DATABASE=Luminex Software, Inc. + +pci:v0000116Ad00006100* + ID_MODEL_FROM_DATABASE=Bus/Tag Channel + +pci:v0000116Ad00006800* + ID_MODEL_FROM_DATABASE=Escon Channel + +pci:v0000116Ad00007100* + ID_MODEL_FROM_DATABASE=Bus/Tag Channel + +pci:v0000116Ad00007800* + ID_MODEL_FROM_DATABASE=Escon Channel + +pci:v0000116B* + ID_VENDOR_FROM_DATABASE=Connectware Inc + +pci:v0000116C* + ID_VENDOR_FROM_DATABASE=Intelligent Resources Integrated Systems + +pci:v0000116D* + ID_VENDOR_FROM_DATABASE=Martin-Marietta + +pci:v0000116E* + ID_VENDOR_FROM_DATABASE=Electronics for Imaging + +pci:v0000116F* + ID_VENDOR_FROM_DATABASE=Workstation Technology + +pci:v00001170* + ID_VENDOR_FROM_DATABASE=Inventec Corporation + +pci:v00001171* + ID_VENDOR_FROM_DATABASE=Loughborough Sound Images Plc + +pci:v00001172* + ID_VENDOR_FROM_DATABASE=Altera Corporation + +pci:v00001172d000000A7* + ID_MODEL_FROM_DATABASE=Stratix V + +pci:v00001172d00000530* + ID_MODEL_FROM_DATABASE=Stratix IV + +pci:v00001173* + ID_VENDOR_FROM_DATABASE=Adobe Systems, Inc + +pci:v00001174* + ID_VENDOR_FROM_DATABASE=Bridgeport Machines + +pci:v00001175* + ID_VENDOR_FROM_DATABASE=Mitron Computer Inc. + +pci:v00001176* + ID_VENDOR_FROM_DATABASE=SBE Incorporated + +pci:v00001177* + ID_VENDOR_FROM_DATABASE=Silicon Engineering + +pci:v00001178* + ID_VENDOR_FROM_DATABASE=Alfa, Inc. + +pci:v00001178d0000AFA1* + ID_MODEL_FROM_DATABASE=Fast Ethernet Adapter + +pci:v00001179* + ID_VENDOR_FROM_DATABASE=Toshiba Corporation + +pci:v00001179d00000102* + ID_MODEL_FROM_DATABASE=Extended IDE Controller + +pci:v00001179d00000103* + ID_MODEL_FROM_DATABASE=EX-IDE Type-B + +pci:v00001179d0000010F* + ID_MODEL_FROM_DATABASE=NVMe Controller + +pci:v00001179d00000110* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx5 + +pci:v00001179d00000110sv00001028sd00001FFB* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx5 (Express Flash NVMe 960G (RI) U.2 (CD5)) + +pci:v00001179d00000110sv00001028sd00001FFC* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx5 (Express Flash NVMe 1.92T (RI) U.2 (CD5)) + +pci:v00001179d00000110sv00001028sd00001FFD* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx5 (Express Flash NVMe 3.84T (RI) U.2 (CD5)) + +pci:v00001179d00000110sv00001028sd00001FFE* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx5 (Express Flash NVMe 7.68T (RI) U.2 (CD5)) + +pci:v00001179d00000110sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx5 (KIOXIA CM5-R series SSD) + +pci:v00001179d00000110sv00001179sd00000021* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx5 (KIOXIA CD5 series SSD) + +pci:v00001179d00000110sv00001D49sd00004039* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx5 (Thinksystem U.2 CM5 NVMe SSD) + +pci:v00001179d00000110sv00001D49sd0000403A* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller Cx5 (Thinksystem AIC CM5 NVMe SSD) + +pci:v00001179d00000113* + ID_MODEL_FROM_DATABASE=BG3 NVMe SSD Controller + +pci:v00001179d00000115* + ID_MODEL_FROM_DATABASE=XG4 NVMe SSD Controller + +pci:v00001179d00000404* + ID_MODEL_FROM_DATABASE=DVD Decoder card + +pci:v00001179d00000406* + ID_MODEL_FROM_DATABASE=Tecra Video Capture device + +pci:v00001179d00000407* + ID_MODEL_FROM_DATABASE=DVD Decoder card (Version 2) + +pci:v00001179d00000601* + ID_MODEL_FROM_DATABASE=CPU to PCI bridge + +pci:v00001179d00000601sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=CPU to PCI bridge (Satellite Pro) + +pci:v00001179d00000602* + ID_MODEL_FROM_DATABASE=PCI to ISA bridge + +pci:v00001179d00000603* + ID_MODEL_FROM_DATABASE=ToPIC95 PCI to CardBus Bridge for Notebooks + +pci:v00001179d00000604* + ID_MODEL_FROM_DATABASE=PCI-Docking Host bridge + +pci:v00001179d0000060A* + ID_MODEL_FROM_DATABASE=ToPIC95 + +pci:v00001179d0000060Asv00001179sd00000001* + ID_MODEL_FROM_DATABASE=ToPIC95 (Satellite Pro) + +pci:v00001179d0000060F* + ID_MODEL_FROM_DATABASE=ToPIC97 + +pci:v00001179d0000060Fsv00001179sd00000001* + ID_MODEL_FROM_DATABASE=ToPIC97 (Satellite 4010) + +pci:v00001179d00000617* + ID_MODEL_FROM_DATABASE=ToPIC100 PCI to Cardbus Bridge with ZV Support + +pci:v00001179d00000618* + ID_MODEL_FROM_DATABASE=CPU to PCI and PCI to ISA bridge + +pci:v00001179d00000701* + ID_MODEL_FROM_DATABASE=FIR Port Type-O + +pci:v00001179d00000803* + ID_MODEL_FROM_DATABASE=TC6371AF SD Host Controller + +pci:v00001179d00000804* + ID_MODEL_FROM_DATABASE=TC6371AF SmartMedia Controller + +pci:v00001179d00000805* + ID_MODEL_FROM_DATABASE=SD TypA Controller + +pci:v00001179d00000D01* + ID_MODEL_FROM_DATABASE=FIR Port Type-DO + +pci:v00001179d00000D01sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=FIR Port Type-DO + +pci:v0000117A* + ID_VENDOR_FROM_DATABASE=A-Trend Technology + +pci:v0000117B* + ID_VENDOR_FROM_DATABASE=L G Electronics, Inc. + +pci:v0000117C* + ID_VENDOR_FROM_DATABASE=ATTO Technology, Inc. + +pci:v0000117Cd0000002C* + ID_MODEL_FROM_DATABASE=ExpressSAS R380 + +pci:v0000117Cd0000002D* + ID_MODEL_FROM_DATABASE=ExpressSAS R348 + +pci:v0000117Cd00000030* + ID_MODEL_FROM_DATABASE=Ultra320 SCSI Host Adapter + +pci:v0000117Cd00000030sv0000117Csd00008013* + ID_MODEL_FROM_DATABASE=Ultra320 SCSI Host Adapter (ExpressPCI UL4D) + +pci:v0000117Cd00000030sv0000117Csd00008014* + ID_MODEL_FROM_DATABASE=Ultra320 SCSI Host Adapter (ExpressPCI UL4S) + +pci:v0000117Cd00000030sv0000117Csd00008027* + ID_MODEL_FROM_DATABASE=Ultra320 SCSI Host Adapter (ExpressPCI UL5D) + +pci:v0000117Cd00000030sv0000117Csd0000802F* + ID_MODEL_FROM_DATABASE=Ultra320 SCSI Host Adapter (ExpressPCI UL5D Low Profile) + +pci:v0000117Cd00000033* + ID_MODEL_FROM_DATABASE=SAS Adapter + +pci:v0000117Cd00000041* + ID_MODEL_FROM_DATABASE=ExpressSAS R30F + +pci:v0000117Cd00000042* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA + +pci:v0000117Cd00000042sv0000117Csd00000042* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS H680) + +pci:v0000117Cd00000042sv0000117Csd00000043* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS H608) + +pci:v0000117Cd00000042sv0000117Csd00000044* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS H60F) + +pci:v0000117Cd00000042sv0000117Csd00000045* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS H6F0) + +pci:v0000117Cd00000042sv0000117Csd00000046* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS H644) + +pci:v0000117Cd00000042sv0000117Csd0000004F* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS M608) + +pci:v0000117Cd00000042sv0000117Csd00000057* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS M680) + +pci:v0000117Cd00000042sv0000117Csd00000058* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS M644) + +pci:v0000117Cd00000042sv0000117Csd00000059* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS W608) + +pci:v0000117Cd00000042sv0000117Csd0000005A* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS W680) + +pci:v0000117Cd00000042sv0000117Csd0000005B* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb/s SAS/SATA HBA (ExpressSAS W644) + +pci:v0000117Cd00000049* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb SAS/SATA RAID Adapter + +pci:v0000117Cd00000049sv0000117Csd00000049* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb SAS/SATA RAID Adapter (ExpressSAS R680) + +pci:v0000117Cd00000049sv0000117Csd0000004A* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb SAS/SATA RAID Adapter (ExpressSAS R608) + +pci:v0000117Cd00000049sv0000117Csd0000004B* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb SAS/SATA RAID Adapter (ExpressSAS R60F) + +pci:v0000117Cd00000049sv0000117Csd0000004C* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb SAS/SATA RAID Adapter (ExpressSAS R6F0) + +pci:v0000117Cd00000049sv0000117Csd0000004D* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb SAS/SATA RAID Adapter (ExpressSAS R644) + +pci:v0000117Cd00000049sv0000117Csd0000004E* + ID_MODEL_FROM_DATABASE=ExpressSAS 6Gb SAS/SATA RAID Adapter (ExpressSAS R648) + +pci:v0000117Cd00000064* + ID_MODEL_FROM_DATABASE=Celerity FC 16Gb/s Gen 5 Fibre Channel HBA + +pci:v0000117Cd00000064sv0000117Csd00000063* + ID_MODEL_FROM_DATABASE=Celerity FC 16Gb/s Gen 5 Fibre Channel HBA (Celerity FC-161E) + +pci:v0000117Cd00000064sv0000117Csd00000064* + ID_MODEL_FROM_DATABASE=Celerity FC 16Gb/s Gen 5 Fibre Channel HBA (Celerity FC-162E) + +pci:v0000117Cd00000064sv0000117Csd00000065* + ID_MODEL_FROM_DATABASE=Celerity FC 16Gb/s Gen 5 Fibre Channel HBA (Celerity FC-164E) + +pci:v0000117Cd00000094* + ID_MODEL_FROM_DATABASE=Celerity FC 16/32Gb/s Gen 6 Fibre Channel HBA + +pci:v0000117Cd00000094sv0000117Csd00000094* + ID_MODEL_FROM_DATABASE=Celerity FC 16/32Gb/s Gen 6 Fibre Channel HBA (Celerity FC-162P) + +pci:v0000117Cd00000094sv0000117Csd000000A0* + ID_MODEL_FROM_DATABASE=Celerity FC 16/32Gb/s Gen 6 Fibre Channel HBA (Celerity FC-161P) + +pci:v0000117Cd00000094sv0000117Csd000000A1* + ID_MODEL_FROM_DATABASE=Celerity FC 16/32Gb/s Gen 6 Fibre Channel HBA (Celerity FC-164P) + +pci:v0000117Cd00000094sv0000117Csd000000A2* + ID_MODEL_FROM_DATABASE=Celerity FC 16/32Gb/s Gen 6 Fibre Channel HBA (Celerity FC-321E) + +pci:v0000117Cd00000094sv0000117Csd000000A3* + ID_MODEL_FROM_DATABASE=Celerity FC 16/32Gb/s Gen 6 Fibre Channel HBA (Celerity FC-322E) + +pci:v0000117Cd00000094sv0000117Csd000000AC* + ID_MODEL_FROM_DATABASE=Celerity FC 16/32Gb/s Gen 6 Fibre Channel HBA (Celerity FC-324E) + +pci:v0000117Cd00008013* + ID_MODEL_FROM_DATABASE=ExpressPCI UL4D + +pci:v0000117Cd00008014* + ID_MODEL_FROM_DATABASE=ExpressPCI UL4S + +pci:v0000117Cd00008027* + ID_MODEL_FROM_DATABASE=ExpressPCI UL5D + +pci:v0000117Cd00008070* + ID_MODEL_FROM_DATABASE=ExpressSAS 12Gb/s SAS/SATA HBA + +pci:v0000117Cd00008070sv0000117Csd00000070* + ID_MODEL_FROM_DATABASE=ExpressSAS 12Gb/s SAS/SATA HBA (ExpressSAS H1280) + +pci:v0000117Cd00008070sv0000117Csd00000071* + ID_MODEL_FROM_DATABASE=ExpressSAS 12Gb/s SAS/SATA HBA (ExpressSAS H1208) + +pci:v0000117Cd00008070sv0000117Csd00000080* + ID_MODEL_FROM_DATABASE=ExpressSAS 12Gb/s SAS/SATA HBA (ExpressSAS H1244) + +pci:v0000117Cd00008072* + ID_MODEL_FROM_DATABASE=ExpressSAS 12Gb/s SAS/SATA HBA + +pci:v0000117Cd00008072sv0000117Csd00000072* + ID_MODEL_FROM_DATABASE=ExpressSAS 12Gb/s SAS/SATA HBA (ExpressSAS H12F0) + +pci:v0000117Cd00008072sv0000117Csd00000073* + ID_MODEL_FROM_DATABASE=ExpressSAS 12Gb/s SAS/SATA HBA (ExpressSAS H120F) + +pci:v0000117Cd00008072sv0000117Csd00000082* + ID_MODEL_FROM_DATABASE=ExpressSAS 12Gb/s SAS/SATA HBA (ExpressSAS H1288) + +pci:v0000117D* + ID_VENDOR_FROM_DATABASE=Becton & Dickinson + +pci:v0000117E* + ID_VENDOR_FROM_DATABASE=T/R Systems + +pci:v0000117F* + ID_VENDOR_FROM_DATABASE=Integrated Circuit Systems + +pci:v00001180* + ID_VENDOR_FROM_DATABASE=Ricoh Co Ltd + +pci:v00001180d00000465* + ID_MODEL_FROM_DATABASE=RL5c465 + +pci:v00001180d00000466* + ID_MODEL_FROM_DATABASE=RL5c466 + +pci:v00001180d00000475* + ID_MODEL_FROM_DATABASE=RL5c475 + +pci:v00001180d00000475sv0000144Dsd0000C006* + ID_MODEL_FROM_DATABASE=RL5c475 (vpr Matrix 170B4 CardBus bridge) + +pci:v00001180d00000476* + ID_MODEL_FROM_DATABASE=RL5c476 II + +pci:v00001180d00000476sv00001014sd00000185* + ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad A/T/X Series) + +pci:v00001180d00000476sv00001014sd00000555* + ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad X41) + +pci:v00001180d00000476sv00001014sd0000056C* + ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad Z60t) + +pci:v00001180d00000476sv00001028sd0000014F* + ID_MODEL_FROM_DATABASE=RL5c476 II (Latitude X300 laptop) + +pci:v00001180d00000476sv00001028sd00000188* + ID_MODEL_FROM_DATABASE=RL5c476 II (Inspiron 6000 laptop) + +pci:v00001180d00000476sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=RL5c476 II (Compaq 6710b) + +pci:v00001180d00000476sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=RL5c476 II (Compaq 6910p) + +pci:v00001180d00000476sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=RL5c476 II (X58LE) + +pci:v00001180d00000476sv00001043sd00001237* + ID_MODEL_FROM_DATABASE=RL5c476 II (A6J-Q008) + +pci:v00001180d00000476sv00001043sd00001967* + ID_MODEL_FROM_DATABASE=RL5c476 II (V6800V) + +pci:v00001180d00000476sv00001043sd00001987* + ID_MODEL_FROM_DATABASE=RL5c476 II (A4K and Z81K notebooks, possibly others ( mid-2005 machines )) + +pci:v00001180d00000476sv0000104Dsd000080DF* + ID_MODEL_FROM_DATABASE=RL5c476 II (Vaio PCG-FX403) + +pci:v00001180d00000476sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=RL5c476 II (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00001180d00000476sv0000104Dsd0000814E* + ID_MODEL_FROM_DATABASE=RL5c476 II (VAIO GRZ390Z) + +pci:v00001180d00000476sv000010F7sd00008338* + ID_MODEL_FROM_DATABASE=RL5c476 II (Panasonic CF-Y5 laptop) + +pci:v00001180d00000476sv0000144Dsd0000C005* + ID_MODEL_FROM_DATABASE=RL5c476 II (X10 Laptop) + +pci:v00001180d00000476sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=RL5c476 II (P30/P35 notebook) + +pci:v00001180d00000476sv000014EFsd00000220* + ID_MODEL_FROM_DATABASE=RL5c476 II (PCD-RP-220S) + +pci:v00001180d00000476sv000017AAsd0000201C* + ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad X60/X60s) + +pci:v00001180d00000476sv000017AAsd000020C4* + ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad T61/R61) + +pci:v00001180d00000476sv000017AAsd000020C6* + ID_MODEL_FROM_DATABASE=RL5c476 II (ThinkPad R61/T400) + +pci:v00001180d00000477* + ID_MODEL_FROM_DATABASE=RL5c477 + +pci:v00001180d00000478* + ID_MODEL_FROM_DATABASE=RL5c478 + +pci:v00001180d00000478sv00001014sd00000184* + ID_MODEL_FROM_DATABASE=RL5c478 (ThinkPad A30p) + +pci:v00001180d00000511* + ID_MODEL_FROM_DATABASE=R5C511 + +pci:v00001180d00000522* + ID_MODEL_FROM_DATABASE=R5C522 IEEE 1394 Controller + +pci:v00001180d00000522sv00001014sd000001CF* + ID_MODEL_FROM_DATABASE=R5C522 IEEE 1394 Controller (ThinkPad A30p) + +pci:v00001180d00000522sv00001043sd00001967* + ID_MODEL_FROM_DATABASE=R5C522 IEEE 1394 Controller (V6800V) + +pci:v00001180d00000551* + ID_MODEL_FROM_DATABASE=R5C551 IEEE 1394 Controller + +pci:v00001180d00000551sv0000144Dsd0000C006* + ID_MODEL_FROM_DATABASE=R5C551 IEEE 1394 Controller (vpr Matrix 170B4) + +pci:v00001180d00000552* + ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller + +pci:v00001180d00000552sv00001014sd00000511* + ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (ThinkPad A/T/X Series) + +pci:v00001180d00000552sv00001028sd0000014F* + ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (Latitude X300 laptop) + +pci:v00001180d00000552sv00001028sd00000188* + ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (Inspiron 6000 laptop) + +pci:v00001180d00000552sv00001043sd00001237* + ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (A6J-Q008) + +pci:v00001180d00000552sv00001043sd00001757* + ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (M2400N laptop) + +pci:v00001180d00000552sv0000144Dsd0000C005* + ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (X10 Laptop) + +pci:v00001180d00000552sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (P30/P35 notebook) + +pci:v00001180d00000552sv000017AAsd0000201E* + ID_MODEL_FROM_DATABASE=R5C552 IEEE 1394 Controller (ThinkPad X60/X60s) + +pci:v00001180d00000554* + ID_MODEL_FROM_DATABASE=R5C554 + +pci:v00001180d00000575* + ID_MODEL_FROM_DATABASE=R5C575 SD Bus Host Adapter + +pci:v00001180d00000576* + ID_MODEL_FROM_DATABASE=R5C576 SD Bus Host Adapter + +pci:v00001180d00000592* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter + +pci:v00001180d00000592sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Aspire 5920G) + +pci:v00001180d00000592sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (XPS M1210) + +pci:v00001180d00000592sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Inspiron 1420) + +pci:v00001180d00000592sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Inspiron 1525) + +pci:v00001180d00000592sv0000103Csd00001521* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (HP EliteBook 8540w) + +pci:v00001180d00000592sv0000103Csd000030B5* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Presario V3242AU) + +pci:v00001180d00000592sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Presario V6133CL) + +pci:v00001180d00000592sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Pavilion dv6700) + +pci:v00001180d00000592sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (Pavilion dv95xx/96xx/97xx/98xx series) + +pci:v00001180d00000592sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (X58LE) + +pci:v00001180d00000592sv00001043sd00001237* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (A6J-Q008) + +pci:v00001180d00000592sv00001043sd00001967* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (V6800V) + +pci:v00001180d00000592sv0000104Dsd00009035* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (VAIO VGN-FW11ZRU) + +pci:v00001180d00000592sv0000144Dsd0000C018* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (X20 IV) + +pci:v00001180d00000592sv000017AAsd000020CA* + ID_MODEL_FROM_DATABASE=R5C592 Memory Stick Bus Host Adapter (ThinkPad T61/T400) + +pci:v00001180d00000811* + ID_MODEL_FROM_DATABASE=R5C811 + +pci:v00001180d00000822* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter + +pci:v00001180d00000822sv00001014sd00000556* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ThinkPad X40 / X41 / X60s / Z60t) + +pci:v00001180d00000822sv00001014sd00000598* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ThinkPad Z60m) + +pci:v00001180d00000822sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Aspire 5920G) + +pci:v00001180d00000822sv00001028sd00000188* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Inspiron 6000 laptop) + +pci:v00001180d00000822sv00001028sd000001A2* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Inspiron 9200) + +pci:v00001180d00000822sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (XPS M1210) + +pci:v00001180d00000822sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Inspiron 1420) + +pci:v00001180d00000822sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Inspiron 1525) + +pci:v00001180d00000822sv0000103Csd000003B5* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Presario V3242AU) + +pci:v00001180d00000822sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Presario V6133CL) + +pci:v00001180d00000822sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Compaq 6910p) + +pci:v00001180d00000822sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Pavilion dv6700) + +pci:v00001180d00000822sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Pavilion dv9668eg Laptop) + +pci:v00001180d00000822sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (X58LE) + +pci:v00001180d00000822sv00001043sd00001237* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (A6J-Q008) + +pci:v00001180d00000822sv00001043sd00001967* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (V6800V) + +pci:v00001180d00000822sv000010F7sd00008338* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (Panasonic CF-Y5 laptop) + +pci:v00001180d00000822sv0000144Dsd0000C018* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (X20 IV) + +pci:v00001180d00000822sv000017AAsd0000201D* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ThinkPad X60/X60s) + +pci:v00001180d00000822sv000017AAsd000020C7* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ThinkPad T61) + +pci:v00001180d00000822sv000017AAsd000020C8* + ID_MODEL_FROM_DATABASE=R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter (ThinkPad T400/W500) + +pci:v00001180d00000832* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller + +pci:v00001180d00000832sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Aspire 5920G) + +pci:v00001180d00000832sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (XPS M1210) + +pci:v00001180d00000832sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Inspiron 1420) + +pci:v00001180d00000832sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Inspiron 1525) + +pci:v00001180d00000832sv00001028sd0000024D* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Latitude E4300) + +pci:v00001180d00000832sv0000103Csd000030B5* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Presario V3242AU) + +pci:v00001180d00000832sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Presario V6133CL) + +pci:v00001180d00000832sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Compaq 6910p) + +pci:v00001180d00000832sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Pavilion dv6700) + +pci:v00001180d00000832sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (Pavilion dv9668eg Laptop) + +pci:v00001180d00000832sv000017AAsd000020C5* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (ThinkPad R61) + +pci:v00001180d00000832sv000017AAsd000020C7* + ID_MODEL_FROM_DATABASE=R5C832 IEEE 1394 Controller (ThinkPad R61) + +pci:v00001180d00000841* + ID_MODEL_FROM_DATABASE=R5C841 CardBus/SD/SDIO/MMC/MS/MSPro/xD/IEEE1394 + +pci:v00001180d00000843* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller + +pci:v00001180d00000843sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Aspire 5920G) + +pci:v00001180d00000843sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (XPS M1210) + +pci:v00001180d00000843sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Inspiron 1420) + +pci:v00001180d00000843sv00001028sd000001F5* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Inspiron 1501) + +pci:v00001180d00000843sv00001028sd0000024F* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Latitude e6500) + +pci:v00001180d00000843sv0000103Csd000003B5* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Presario V3242AU) + +pci:v00001180d00000843sv0000103Csd00001521* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (HP EliteBook 8540w) + +pci:v00001180d00000843sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Presario V6133CL) + +pci:v00001180d00000843sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Pavilion dv9500/9600/9700 series) + +pci:v00001180d00000843sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (X58LE) + +pci:v00001180d00000843sv00001183sd00000843* + ID_MODEL_FROM_DATABASE=R5C843 MMC Host Controller (Alienware Aurora m9700) + +pci:v00001180d00000852* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller + +pci:v00001180d00000852sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Aspire 5920G) + +pci:v00001180d00000852sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Inspiron 1420) + +pci:v00001180d00000852sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Inspiron 1525) + +pci:v00001180d00000852sv0000103Csd000030B5* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Presario V3242AU) + +pci:v00001180d00000852sv0000103Csd000030B7* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Presario V6133CL) + +pci:v00001180d00000852sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Pavilion dv6700) + +pci:v00001180d00000852sv0000103Csd000030CF* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Pavilion dv9668eg Laptop) + +pci:v00001180d00000852sv00001043sd00001967* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (V6800V) + +pci:v00001180d00000852sv00001180sd00000852* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (Pavilion 2410us) + +pci:v00001180d00000852sv00001324sd000010CF* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (P7120) + +pci:v00001180d00000852sv000017AAsd000020CB* + ID_MODEL_FROM_DATABASE=xD-Picture Card Controller (ThinkPad T400) + +pci:v00001180d0000E230* + ID_MODEL_FROM_DATABASE=R5U2xx (R5U230 / R5U231 / R5U241) [Memory Stick Host Controller] + +pci:v00001180d0000E476* + ID_MODEL_FROM_DATABASE=CardBus bridge + +pci:v00001180d0000E476sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=CardBus bridge (Latitude E6410) + +pci:v00001180d0000E476sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=CardBus bridge (Latitude E6510) + +pci:v00001180d0000E822* + ID_MODEL_FROM_DATABASE=MMC/SD Host Controller + +pci:v00001180d0000E822sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=MMC/SD Host Controller (Latitude E6410) + +pci:v00001180d0000E822sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=MMC/SD Host Controller (Latitude E6510) + +pci:v00001180d0000E822sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=MMC/SD Host Controller (ThinkPad T520) + +pci:v00001180d0000E823* + ID_MODEL_FROM_DATABASE=PCIe SDXC/MMC Host Controller + +pci:v00001180d0000E823sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=PCIe SDXC/MMC Host Controller (ThinkPad T520) + +pci:v00001180d0000E832* + ID_MODEL_FROM_DATABASE=R5C832 PCIe IEEE 1394 Controller + +pci:v00001180d0000E832sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=R5C832 PCIe IEEE 1394 Controller (Latitude E6410) + +pci:v00001180d0000E832sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=R5C832 PCIe IEEE 1394 Controller (Latitude E6510) + +pci:v00001180d0000E832sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=R5C832 PCIe IEEE 1394 Controller (ThinkPad T520) + +pci:v00001180d0000E852* + ID_MODEL_FROM_DATABASE=PCIe xD-Picture Card Controller + +pci:v00001181* + ID_VENDOR_FROM_DATABASE=Telmatics International + +pci:v00001183* + ID_VENDOR_FROM_DATABASE=Fujikura Ltd + +pci:v00001184* + ID_VENDOR_FROM_DATABASE=Forks Inc + +pci:v00001185* + ID_VENDOR_FROM_DATABASE=Dataworld International Ltd + +pci:v00001186* + ID_VENDOR_FROM_DATABASE=D-Link System Inc + +pci:v00001186d00001002* + ID_MODEL_FROM_DATABASE=DL10050 Sundance Ethernet + +pci:v00001186d00001002sv00001186sd00001002* + ID_MODEL_FROM_DATABASE=DL10050 Sundance Ethernet (DFE-550TX/FX) + +pci:v00001186d00001002sv00001186sd00001012* + ID_MODEL_FROM_DATABASE=DL10050 Sundance Ethernet (DFE-580TX) + +pci:v00001186d00001025* + ID_MODEL_FROM_DATABASE=AirPlus Xtreme G DWL-G650 Adapter + +pci:v00001186d00001026* + ID_MODEL_FROM_DATABASE=AirXpert DWL-AG650 Wireless Cardbus Adapter + +pci:v00001186d00001043* + ID_MODEL_FROM_DATABASE=AirXpert DWL-AG650 Wireless Cardbus Adapter + +pci:v00001186d00001300* + ID_MODEL_FROM_DATABASE=RTL8139 Ethernet + +pci:v00001186d00001300sv00001186sd00001300* + ID_MODEL_FROM_DATABASE=RTL8139 Ethernet (DFE-538TX 10/100 Ethernet Adapter) + +pci:v00001186d00001300sv00001186sd00001301* + ID_MODEL_FROM_DATABASE=RTL8139 Ethernet (DFE-530TX+ 10/100 Ethernet Adapter) + +pci:v00001186d00001300sv00001186sd00001303* + ID_MODEL_FROM_DATABASE=RTL8139 Ethernet (DFE-528TX 10/100 Fast Ethernet PCI Adapter) + +pci:v00001186d00001340* + ID_MODEL_FROM_DATABASE=DFE-690TXD CardBus PC Card + +pci:v00001186d00001540* + ID_MODEL_FROM_DATABASE=DFE-680TX + +pci:v00001186d00001541* + ID_MODEL_FROM_DATABASE=DFE-680TXD CardBus PC Card + +pci:v00001186d00001561* + ID_MODEL_FROM_DATABASE=DRP-32TXD Cardbus PC Card + +pci:v00001186d00003300* + ID_MODEL_FROM_DATABASE=DWL-510 / DWL-610 802.11b [Realtek RTL8180L] + +pci:v00001186d00003300sv00001186sd00003300* + ID_MODEL_FROM_DATABASE=DWL-510 / DWL-610 802.11b [Realtek RTL8180L] (DWL-610 Wireless Cardbus Adapter) + +pci:v00001186d00003300sv00001186sd00003301* + ID_MODEL_FROM_DATABASE=DWL-510 / DWL-610 802.11b [Realtek RTL8180L] (DWL-510 Wireless PCI Adapter) + +pci:v00001186d00003A10* + ID_MODEL_FROM_DATABASE=AirXpert DWL-AG650 Wireless Cardbus Adapter(rev.B) + +pci:v00001186d00003A11* + ID_MODEL_FROM_DATABASE=AirXpert DWL-AG520 Wireless PCI Adapter(rev.B) + +pci:v00001186d00004000* + ID_MODEL_FROM_DATABASE=DL2000-based Gigabit Ethernet + +pci:v00001186d00004001* + ID_MODEL_FROM_DATABASE=DGE-550SX PCI-X Gigabit Ethernet Adapter + +pci:v00001186d00004200* + ID_MODEL_FROM_DATABASE=DFE-520TX Fast Ethernet PCI Adapter + +pci:v00001186d00004200sv00001186sd00001103* + ID_MODEL_FROM_DATABASE=DFE-520TX Fast Ethernet PCI Adapter ((rev. C1)) + +pci:v00001186d00004300* + ID_MODEL_FROM_DATABASE=DGE-528T Gigabit Ethernet Adapter + +pci:v00001186d00004300sv00001186sd00004300* + ID_MODEL_FROM_DATABASE=DGE-528T Gigabit Ethernet Adapter (DGE-528T PCI Gigabit Ethernet Adapter) + +pci:v00001186d00004300sv00001186sd00004B10* + ID_MODEL_FROM_DATABASE=DGE-528T Gigabit Ethernet Adapter (DGE-560T PCI Express (x1) Gigabit Ethernet Adapter) + +pci:v00001186d00004302* + ID_MODEL_FROM_DATABASE=DGE-530T Gigabit Ethernet Adapter (rev.C1) [Realtek RTL8169] + +pci:v00001186d00004B00* + ID_MODEL_FROM_DATABASE=DGE-560T PCI Express Gigabit Ethernet Adapter + +pci:v00001186d00004B01* + ID_MODEL_FROM_DATABASE=DGE-530T Gigabit Ethernet Adapter (rev 11) + +pci:v00001186d00004B02* + ID_MODEL_FROM_DATABASE=DGE-560SX PCI Express Gigabit Ethernet Adapter + +pci:v00001186d00004B03* + ID_MODEL_FROM_DATABASE=DGE-550T Gigabit Ethernet Adapter V.B1 + +pci:v00001186d00004C00* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter + +pci:v00001186d00004C00sv00001186sd00004C00* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter (DGE-530T Gigabit Ethernet Adapter) + +pci:v00001186d00008400* + ID_MODEL_FROM_DATABASE=D-Link DWL-650+ CardBus PC Card + +pci:v00001187* + ID_VENDOR_FROM_DATABASE=Advanced Technology Laboratories, Inc. + +pci:v00001188* + ID_VENDOR_FROM_DATABASE=Shima Seiki Manufacturing Ltd. + +pci:v00001189* + ID_VENDOR_FROM_DATABASE=Matsushita Electronics Co Ltd + +pci:v0000118A* + ID_VENDOR_FROM_DATABASE=Hilevel Technology + +pci:v0000118B* + ID_VENDOR_FROM_DATABASE=Hypertec Pty Limited + +pci:v0000118C* + ID_VENDOR_FROM_DATABASE=Corollary, Inc + +pci:v0000118Cd00000014* + ID_MODEL_FROM_DATABASE=PCIB [C-bus II to PCI bus host bridge chip] + +pci:v0000118Cd00001117* + ID_MODEL_FROM_DATABASE=Intel 8-way XEON Profusion Chipset [Cache Coherency Filter] + +pci:v0000118D* + ID_VENDOR_FROM_DATABASE=BitFlow Inc + +pci:v0000118Dd00000001* + ID_MODEL_FROM_DATABASE=Raptor-PCI framegrabber + +pci:v0000118Dd00000012* + ID_MODEL_FROM_DATABASE=Model 12 Road Runner Frame Grabber + +pci:v0000118Dd00000014* + ID_MODEL_FROM_DATABASE=Model 14 Road Runner Frame Grabber + +pci:v0000118Dd00000024* + ID_MODEL_FROM_DATABASE=Model 24 Road Runner Frame Grabber + +pci:v0000118Dd00000044* + ID_MODEL_FROM_DATABASE=Model 44 Road Runner Frame Grabber + +pci:v0000118Dd00000112* + ID_MODEL_FROM_DATABASE=Model 12 Road Runner Frame Grabber + +pci:v0000118Dd00000114* + ID_MODEL_FROM_DATABASE=Model 14 Road Runner Frame Grabber + +pci:v0000118Dd00000124* + ID_MODEL_FROM_DATABASE=Model 24 Road Runner Frame Grabber + +pci:v0000118Dd00000144* + ID_MODEL_FROM_DATABASE=Model 44 Road Runner Frame Grabber + +pci:v0000118Dd00000212* + ID_MODEL_FROM_DATABASE=Model 12 Road Runner Frame Grabber + +pci:v0000118Dd00000214* + ID_MODEL_FROM_DATABASE=Model 14 Road Runner Frame Grabber + +pci:v0000118Dd00000224* + ID_MODEL_FROM_DATABASE=Model 24 Road Runner Frame Grabber + +pci:v0000118Dd00000244* + ID_MODEL_FROM_DATABASE=Model 44 Road Runner Frame Grabber + +pci:v0000118Dd00000312* + ID_MODEL_FROM_DATABASE=Model 12 Road Runner Frame Grabber + +pci:v0000118Dd00000314* + ID_MODEL_FROM_DATABASE=Model 14 Road Runner Frame Grabber + +pci:v0000118Dd00000324* + ID_MODEL_FROM_DATABASE=Model 24 Road Runner Frame Grabber + +pci:v0000118Dd00000344* + ID_MODEL_FROM_DATABASE=Model 44 Road Runner Frame Grabber + +pci:v0000118E* + ID_VENDOR_FROM_DATABASE=Hermstedt GmbH + +pci:v0000118F* + ID_VENDOR_FROM_DATABASE=Green Logic + +pci:v00001190* + ID_VENDOR_FROM_DATABASE=Tripace + +pci:v00001190d0000C731* + ID_MODEL_FROM_DATABASE=TP-910/920/940 PCI Ultra(Wide) SCSI Adapter + +pci:v00001191* + ID_VENDOR_FROM_DATABASE=Artop Electronic Corp + +pci:v00001191d00000003* + ID_MODEL_FROM_DATABASE=SCSI Cache Host Adapter + +pci:v00001191d00000004* + ID_MODEL_FROM_DATABASE=ATP8400 + +pci:v00001191d00000005* + ID_MODEL_FROM_DATABASE=ATP850UF + +pci:v00001191d00000006* + ID_MODEL_FROM_DATABASE=ATP860 NO-BIOS + +pci:v00001191d00000007* + ID_MODEL_FROM_DATABASE=ATP860 + +pci:v00001191d00000008* + ID_MODEL_FROM_DATABASE=ATP865 NO-ROM + +pci:v00001191d00000009* + ID_MODEL_FROM_DATABASE=ATP865 + +pci:v00001191d0000000A* + ID_MODEL_FROM_DATABASE=ATP867-A + +pci:v00001191d0000000B* + ID_MODEL_FROM_DATABASE=ATP867-B + +pci:v00001191d0000000D* + ID_MODEL_FROM_DATABASE=ATP8620 + +pci:v00001191d0000000E* + ID_MODEL_FROM_DATABASE=ATP8620 + +pci:v00001191d00008002* + ID_MODEL_FROM_DATABASE=AEC6710 SCSI-2 Host Adapter + +pci:v00001191d00008010* + ID_MODEL_FROM_DATABASE=AEC6712UW SCSI + +pci:v00001191d00008020* + ID_MODEL_FROM_DATABASE=AEC6712U SCSI + +pci:v00001191d00008030* + ID_MODEL_FROM_DATABASE=AEC6712S SCSI + +pci:v00001191d00008040* + ID_MODEL_FROM_DATABASE=AEC6712D SCSI + +pci:v00001191d00008050* + ID_MODEL_FROM_DATABASE=AEC6712SUW SCSI + +pci:v00001191d00008060* + ID_MODEL_FROM_DATABASE=AEC6712 SCSI + +pci:v00001191d00008080* + ID_MODEL_FROM_DATABASE=AEC67160 SCSI + +pci:v00001191d00008081* + ID_MODEL_FROM_DATABASE=AEC67160S SCSI + +pci:v00001191d0000808A* + ID_MODEL_FROM_DATABASE=AEC67162 2-ch. LVD SCSI + +pci:v00001192* + ID_VENDOR_FROM_DATABASE=Densan Company Ltd + +pci:v00001193* + ID_VENDOR_FROM_DATABASE=Zeitnet Inc. + +pci:v00001193d00000001* + ID_MODEL_FROM_DATABASE=1221 + +pci:v00001193d00000002* + ID_MODEL_FROM_DATABASE=1225 + +pci:v00001194* + ID_VENDOR_FROM_DATABASE=Toucan Technology + +pci:v00001195* + ID_VENDOR_FROM_DATABASE=Ratoc System Inc + +pci:v00001196* + ID_VENDOR_FROM_DATABASE=Hytec Electronics Ltd + +pci:v00001197* + ID_VENDOR_FROM_DATABASE=Gage Applied Sciences, Inc. + +pci:v00001197d0000010C* + ID_MODEL_FROM_DATABASE=CompuScope 82G 8bit 2GS/s Analog Input Card + +pci:v00001198* + ID_VENDOR_FROM_DATABASE=Lambda Systems Inc + +pci:v00001199* + ID_VENDOR_FROM_DATABASE=Attachmate Corporation + +pci:v00001199d00000101* + ID_MODEL_FROM_DATABASE=Advanced ISCA/PCI Adapter + +pci:v0000119A* + ID_VENDOR_FROM_DATABASE=Mind Share, Inc. + +pci:v0000119B* + ID_VENDOR_FROM_DATABASE=Omega Micro Inc. + +pci:v0000119Bd00001221* + ID_MODEL_FROM_DATABASE=82C092G + +pci:v0000119C* + ID_VENDOR_FROM_DATABASE=Information Technology Inst. + +pci:v0000119D* + ID_VENDOR_FROM_DATABASE=Bug, Inc. Sapporo Japan + +pci:v0000119E* + ID_VENDOR_FROM_DATABASE=Fujitsu Microelectronics Ltd. + +pci:v0000119Ed00000001* + ID_MODEL_FROM_DATABASE=FireStream 155 + +pci:v0000119Ed00000003* + ID_MODEL_FROM_DATABASE=FireStream 50 + +pci:v0000119F* + ID_VENDOR_FROM_DATABASE=Bull HN Information Systems + +pci:v0000119Fd00001081* + ID_MODEL_FROM_DATABASE=BXI Host Channel Adapter + +pci:v0000119Fd00001101* + ID_MODEL_FROM_DATABASE=BXI Host Channel Adapter v1.2 + +pci:v0000119Fd00001121* + ID_MODEL_FROM_DATABASE=BXI Host Channel Adapter v1.3 + +pci:v000011A0* + ID_VENDOR_FROM_DATABASE=Convex Computer Corporation + +pci:v000011A1* + ID_VENDOR_FROM_DATABASE=Hamamatsu Photonics K.K. + +pci:v000011A2* + ID_VENDOR_FROM_DATABASE=Sierra Research and Technology + +pci:v000011A3* + ID_VENDOR_FROM_DATABASE=Deuretzbacher GmbH & Co. Eng. KG + +pci:v000011A4* + ID_VENDOR_FROM_DATABASE=Barco Graphics NV + +pci:v000011A5* + ID_VENDOR_FROM_DATABASE=Microunity Systems Eng. Inc + +pci:v000011A6* + ID_VENDOR_FROM_DATABASE=Pure Data Ltd. + +pci:v000011A7* + ID_VENDOR_FROM_DATABASE=Power Computing Corp. + +pci:v000011A8* + ID_VENDOR_FROM_DATABASE=Systech Corp. + +pci:v000011A9* + ID_VENDOR_FROM_DATABASE=InnoSys Inc. + +pci:v000011A9d00004240* + ID_MODEL_FROM_DATABASE=AMCC S933Q Intelligent Serial Card + +pci:v000011AA* + ID_VENDOR_FROM_DATABASE=Actel + +pci:v000011AB* + ID_VENDOR_FROM_DATABASE=Marvell Technology Group Ltd. + +pci:v000011ABd00000146* + ID_MODEL_FROM_DATABASE=GT-64010/64010A System Controller + +pci:v000011ABd00000F53* + ID_MODEL_FROM_DATABASE=88E6318 Link Street network controller + +pci:v000011ABd000011AB* + ID_MODEL_FROM_DATABASE=MV88SE614x SATA II PCI-E controller + +pci:v000011ABd0000138F* + ID_MODEL_FROM_DATABASE=W8300 802.11 Adapter (rev 07) + +pci:v000011ABd00001FA6* + ID_MODEL_FROM_DATABASE=Marvell W8300 802.11 Adapter + +pci:v000011ABd00001FA6sv00001186sd00003B08* + ID_MODEL_FROM_DATABASE=Marvell W8300 802.11 Adapter (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.A1)) + +pci:v000011ABd00001FA7* + ID_MODEL_FROM_DATABASE=88W8310 and 88W8000G [Libertas] 802.11g client chipset + +pci:v000011ABd00001FAA* + ID_MODEL_FROM_DATABASE=88w8335 [Libertas] 802.11b/g Wireless + +pci:v000011ABd00001FAAsv00001385sd00004E00* + ID_MODEL_FROM_DATABASE=88w8335 [Libertas] 802.11b/g Wireless (WG511v2 54 Mbps Wireless PC Card) + +pci:v000011ABd00001FAAsv00001385sd00006B00* + ID_MODEL_FROM_DATABASE=88w8335 [Libertas] 802.11b/g Wireless (WG311v3 802.11g Wireless PCI Adapter) + +pci:v000011ABd00001FAAsv00001737sd00000040* + ID_MODEL_FROM_DATABASE=88w8335 [Libertas] 802.11b/g Wireless (WPC54G v5 802.11g Wireless-G Notebook Adapter) + +pci:v000011ABd00002211* + ID_MODEL_FROM_DATABASE=88SB2211 PCI Express to PCI Bridge + +pci:v000011ABd00002A01* + ID_MODEL_FROM_DATABASE=88W8335 [Libertas] 802.11b/g Wireless + +pci:v000011ABd00002A02* + ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless + +pci:v000011ABd00002A02sv000007D1sd00003B02* + ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless (DIR-615 rev. A1 Mini PCI Wireless Module) + +pci:v000011ABd00002A02sv00001385sd00007C00* + ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless (WN511T RangeMax Next 300 Mbps Wireless PC Card) + +pci:v000011ABd00002A02sv00001385sd00007C01* + ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless (WN511T RangeMax Next 300 Mbps Wireless Notebook Adapter) + +pci:v000011ABd00002A02sv00001385sd00007E00* + ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless (WN311T RangeMax Next 300 Mbps Wireless PCI Adapter) + +pci:v000011ABd00002A02sv00001799sd0000801B* + ID_MODEL_FROM_DATABASE=88W8361 [TopDog] 802.11n Wireless (F5D8011 v2 802.11n N1 Wireless Notebook Card) + +pci:v000011ABd00002A08* + ID_MODEL_FROM_DATABASE=88W8362e [TopDog] 802.11a/b/g/n Wireless + +pci:v000011ABd00002A0A* + ID_MODEL_FROM_DATABASE=88W8363 [TopDog] 802.11n Wireless + +pci:v000011ABd00002A0C* + ID_MODEL_FROM_DATABASE=88W8363 [TopDog] 802.11n Wireless + +pci:v000011ABd00002A24* + ID_MODEL_FROM_DATABASE=88W8363 [TopDog] 802.11n Wireless + +pci:v000011ABd00002A2B* + ID_MODEL_FROM_DATABASE=88W8687 [TopDog] 802.11b/g Wireless + +pci:v000011ABd00002A30* + ID_MODEL_FROM_DATABASE=88W8687 [TopDog] 802.11b/g Wireless + +pci:v000011ABd00002A40* + ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless + +pci:v000011ABd00002A41* + ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless + +pci:v000011ABd00002A42* + ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless + +pci:v000011ABd00002A43* + ID_MODEL_FROM_DATABASE=88W8366 [TopDog] 802.11n Wireless + +pci:v000011ABd00002A55* + ID_MODEL_FROM_DATABASE=88W8864 [Avastar] 802.11ac Wireless + +pci:v000011ABd00002B36* + ID_MODEL_FROM_DATABASE=88W8764 [Avastar] 802.11n Wireless + +pci:v000011ABd00002B38* + ID_MODEL_FROM_DATABASE=88W8897 [AVASTAR] 802.11ac Wireless + +pci:v000011ABd00002B40* + ID_MODEL_FROM_DATABASE=88W8964 [Avastar] 802.11ac Wireless + +pci:v000011ABd00004101* + ID_MODEL_FROM_DATABASE=OLPC Cafe Controller Secure Digital Controller + +pci:v000011ABd00004320* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller + +pci:v000011ABd00004320sv00001019sd00000F38* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (ECS)) + +pci:v000011ABd00004320sv00001019sd00008001* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (ECS)) + +pci:v000011ABd00004320sv00001043sd0000173C* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Asus)) + +pci:v000011ABd00004320sv00001043sd0000811A* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Asus)) + +pci:v000011ABd00004320sv0000105Bsd00000C19* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Foxconn)) + +pci:v000011ABd00004320sv000010B8sd0000B452* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (EZ Card 1000 (SMC9452TXV.2)) + +pci:v000011ABd00004320sv000011ABsd00000121* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell RDK-8001) + +pci:v000011ABd00004320sv000011ABsd00000321* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell RDK-8003) + +pci:v000011ABd00004320sv000011ABsd00001021* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell RDK-8010) + +pci:v000011ABd00004320sv000011ABsd00004320* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell Yukon Gigabit Ethernet 10/100/1000Baset-T Constroller (Asus)) + +pci:v000011ABd00004320sv000011ABsd00005021* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (64 bit)) + +pci:v000011ABd00004320sv000011ABsd00009521* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (32 bit)) + +pci:v000011ABd00004320sv00001458sd0000E000* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Gigabyte)) + +pci:v000011ABd00004320sv0000147Bsd00001406* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Abit)) + +pci:v000011ABd00004320sv000015D4sd00000047* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Iwill)) + +pci:v000011ABd00004320sv00001695sd00009025* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Epox)) + +pci:v000011ABd00004320sv000017F2sd00001C03* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Albatron)) + +pci:v000011ABd00004320sv0000270Fsd00002803* + ID_MODEL_FROM_DATABASE=88E8001 Gigabit Ethernet Controller (Marvell 88E8001 Gigabit Ethernet Controller (Chaintech)) + +pci:v000011ABd00004340* + ID_MODEL_FROM_DATABASE=88E8021 PCI-X IPMI Gigabit Ethernet Controller + +pci:v000011ABd00004341* + ID_MODEL_FROM_DATABASE=88E8022 PCI-X IPMI Gigabit Ethernet Controller + +pci:v000011ABd00004342* + ID_MODEL_FROM_DATABASE=88E8061 PCI-E IPMI Gigabit Ethernet Controller + +pci:v000011ABd00004343* + ID_MODEL_FROM_DATABASE=88E8062 PCI-E IPMI Gigabit Ethernet Controller + +pci:v000011ABd00004344* + ID_MODEL_FROM_DATABASE=88E8021 PCI-X IPMI Gigabit Ethernet Controller + +pci:v000011ABd00004345* + ID_MODEL_FROM_DATABASE=88E8022 PCI-X IPMI Gigabit Ethernet Controller + +pci:v000011ABd00004346* + ID_MODEL_FROM_DATABASE=88E8061 PCI-E IPMI Gigabit Ethernet Controller + +pci:v000011ABd00004347* + ID_MODEL_FROM_DATABASE=88E8062 PCI-E IPMI Gigabit Ethernet Controller + +pci:v000011ABd00004347sv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=88E8062 PCI-E IPMI Gigabit Ethernet Controller (Telum ASLP10 PrAMC Gigabit Ethernet) + +pci:v000011ABd00004350* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller + +pci:v000011ABd00004350sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (Toshiba)) + +pci:v000011ABd00004350sv000011ABsd00003521* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell RDK-8035) + +pci:v000011ABd00004350sv00001854sd0000000D* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd0000000E* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd0000000F* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd00000011* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd00000012* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd00000016* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd00000017* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd00000018* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd00000019* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd0000001C* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd0000001E* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004350sv00001854sd00000020* + ID_MODEL_FROM_DATABASE=88E8035 PCI-E Fast Ethernet Controller (Marvell 88E8035 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller + +pci:v000011ABd00004351sv0000107Bsd00004009* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Wistron)) + +pci:v000011ABd00004351sv000010F7sd00008338* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Panasonic)) + +pci:v000011ABd00004351sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Toshiba)) + +pci:v000011ABd00004351sv00001179sd0000FF00* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Compal)) + +pci:v000011ABd00004351sv00001179sd0000FF10* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Inventec)) + +pci:v000011ABd00004351sv000011ABsd00003621* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell RDK-8036) + +pci:v000011ABd00004351sv000013D1sd0000AC12* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Abocom EFE3K - 10/100 Ethernet Expresscard) + +pci:v000011ABd00004351sv0000161Fsd0000203D* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (Arima)) + +pci:v000011ABd00004351sv00001854sd0000000D* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd0000000E* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd0000000F* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd00000011* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd00000012* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd00000016* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd00000017* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd00000018* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd00000019* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd0000001C* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd0000001E* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004351sv00001854sd00000020* + ID_MODEL_FROM_DATABASE=88E8036 PCI-E Fast Ethernet Controller (Marvell 88E8036 Fast Ethernet Controller (LGE)) + +pci:v000011ABd00004352* + ID_MODEL_FROM_DATABASE=88E8038 PCI-E Fast Ethernet Controller + +pci:v000011ABd00004353* + ID_MODEL_FROM_DATABASE=88E8039 PCI-E Fast Ethernet Controller + +pci:v000011ABd00004353sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=88E8039 PCI-E Fast Ethernet Controller (VAIO VGN-NR120E) + +pci:v000011ABd00004354* + ID_MODEL_FROM_DATABASE=88E8040 PCI-E Fast Ethernet Controller + +pci:v000011ABd00004354sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=88E8040 PCI-E Fast Ethernet Controller (Inspiron 1525) + +pci:v000011ABd00004354sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=88E8040 PCI-E Fast Ethernet Controller (R730 Laptop) + +pci:v000011ABd00004354sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=88E8040 PCI-E Fast Ethernet Controller (Notebook N150P) + +pci:v000011ABd00004355* + ID_MODEL_FROM_DATABASE=88E8040T PCI-E Fast Ethernet Controller + +pci:v000011ABd00004355sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=88E8040T PCI-E Fast Ethernet Controller (Satellite P305D-S8995E) + +pci:v000011ABd00004356* + ID_MODEL_FROM_DATABASE=88EC033 PCI-E Fast Ethernet Controller + +pci:v000011ABd00004357* + ID_MODEL_FROM_DATABASE=88E8042 PCI-E Fast Ethernet Controller + +pci:v000011ABd0000435A* + ID_MODEL_FROM_DATABASE=88E8048 PCI-E Fast Ethernet Controller + +pci:v000011ABd00004360* + ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller + +pci:v000011ABd00004360sv00001043sd00008134* + ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (Asus)) + +pci:v000011ABd00004360sv0000107Bsd00004009* + ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (Wistron)) + +pci:v000011ABd00004360sv000011ABsd00005221* + ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell RDK-8052) + +pci:v000011ABd00004360sv00001458sd0000E000* + ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)) + +pci:v000011ABd00004360sv00001462sd0000052C* + ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (MSI)) + +pci:v000011ABd00004360sv00001849sd00008052* + ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (ASRock)) + +pci:v000011ABd00004360sv0000A0A0sd00000509* + ID_MODEL_FROM_DATABASE=88E8052 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8052 Gigabit Ethernet Controller (Aopen)) + +pci:v000011ABd00004361* + ID_MODEL_FROM_DATABASE=88E8050 PCI-E ASF Gigabit Ethernet Controller + +pci:v000011ABd00004361sv0000107Bsd00003015* + ID_MODEL_FROM_DATABASE=88E8050 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8050 Gigabit Ethernet Controller (Gateway)) + +pci:v000011ABd00004361sv000011ABsd00005021* + ID_MODEL_FROM_DATABASE=88E8050 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8050 Gigabit Ethernet Controller (Intel)) + +pci:v000011ABd00004361sv00008086sd00003063* + ID_MODEL_FROM_DATABASE=88E8050 PCI-E ASF Gigabit Ethernet Controller (D925XCVLK mainboard) + +pci:v000011ABd00004361sv00008086sd00003439* + ID_MODEL_FROM_DATABASE=88E8050 PCI-E ASF Gigabit Ethernet Controller (Marvell 88E8050 Gigabit Ethernet Controller (Intel)) + +pci:v000011ABd00004362* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller + +pci:v000011ABd00004362sv0000103Csd00002A0D* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Asus)) + +pci:v000011ABd00004362sv00001043sd00008142* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet controller PCIe (Asus)) + +pci:v000011ABd00004362sv0000109Fsd00003197* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Trigem)) + +pci:v000011ABd00004362sv000010F7sd00008338* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Panasonic)) + +pci:v000011ABd00004362sv000010FDsd0000A430* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (SOYO)) + +pci:v000011ABd00004362sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Toshiba)) + +pci:v000011ABd00004362sv00001179sd0000FF00* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Compal)) + +pci:v000011ABd00004362sv00001179sd0000FF10* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Inventec)) + +pci:v000011ABd00004362sv000011ABsd00005321* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell RDK-8053) + +pci:v000011ABd00004362sv00001297sd0000C240* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)) + +pci:v000011ABd00004362sv00001297sd0000C241* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)) + +pci:v000011ABd00004362sv00001297sd0000C242* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)) + +pci:v000011ABd00004362sv00001297sd0000C243* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)) + +pci:v000011ABd00004362sv00001297sd0000C244* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)) + +pci:v000011ABd00004362sv000013D1sd0000AC11* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (EGE5K - Giga Ethernet Expresscard) + +pci:v000011ABd00004362sv00001458sd0000E000* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)) + +pci:v000011ABd00004362sv00001462sd0000058C* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (MSI)) + +pci:v000011ABd00004362sv000014C0sd00000012* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Compal)) + +pci:v000011ABd00004362sv00001558sd000004A0* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Clevo)) + +pci:v000011ABd00004362sv000015BDsd00001003* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (DFI)) + +pci:v000011ABd00004362sv0000161Fsd0000203C* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Arima)) + +pci:v000011ABd00004362sv0000161Fsd0000203D* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Arima)) + +pci:v000011ABd00004362sv00001695sd00009029* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Epox)) + +pci:v000011ABd00004362sv000017F2sd00002C08* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Albatron)) + +pci:v000011ABd00004362sv000017FFsd00000585* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Quanta)) + +pci:v000011ABd00004362sv00001849sd00008053* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (ASRock)) + +pci:v000011ABd00004362sv00001854sd0000000B* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd0000000C* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd00000010* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd00000013* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd00000014* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd00000015* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd0000001A* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd0000001B* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd0000001D* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd0000001F* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd00000021* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv00001854sd00000022* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (LGE)) + +pci:v000011ABd00004362sv0000270Fsd00002801* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Chaintech)) + +pci:v000011ABd00004362sv0000A0A0sd00000506* + ID_MODEL_FROM_DATABASE=88E8053 PCI-E Gigabit Ethernet Controller (Marvell 88E8053 Gigabit Ethernet Controller (Aopen)) + +pci:v000011ABd00004363* + ID_MODEL_FROM_DATABASE=88E8055 PCI-E Gigabit Ethernet Controller + +pci:v000011ABd00004364* + ID_MODEL_FROM_DATABASE=88E8056 PCI-E Gigabit Ethernet Controller + +pci:v000011ABd00004364sv00001043sd000081F8* + ID_MODEL_FROM_DATABASE=88E8056 PCI-E Gigabit Ethernet Controller (Motherboard) + +pci:v000011ABd00004364sv000011BAsd000000BA* + ID_MODEL_FROM_DATABASE=88E8056 PCI-E Gigabit Ethernet Controller (8056 Gigabit Ethernet Controller) + +pci:v000011ABd00004365* + ID_MODEL_FROM_DATABASE=88E8070 based Ethernet Controller + +pci:v000011ABd00004366* + ID_MODEL_FROM_DATABASE=88EC036 PCI-E Gigabit Ethernet Controller + +pci:v000011ABd00004367* + ID_MODEL_FROM_DATABASE=88EC032 Ethernet Controller + +pci:v000011ABd00004368* + ID_MODEL_FROM_DATABASE=88EC034 Ethernet Controller + +pci:v000011ABd00004369* + ID_MODEL_FROM_DATABASE=88EC042 Ethernet Controller + +pci:v000011ABd0000436A* + ID_MODEL_FROM_DATABASE=88E8058 PCI-E Gigabit Ethernet Controller + +pci:v000011ABd0000436Asv000011ABsd000000BA* + ID_MODEL_FROM_DATABASE=88E8058 PCI-E Gigabit Ethernet Controller (Imac 8,1 Wired Ethernet Adapter) + +pci:v000011ABd0000436B* + ID_MODEL_FROM_DATABASE=88E8071 PCI-E Gigabit Ethernet Controller + +pci:v000011ABd0000436C* + ID_MODEL_FROM_DATABASE=88E8072 PCI-E Gigabit Ethernet Controller + +pci:v000011ABd0000436D* + ID_MODEL_FROM_DATABASE=88E8055 PCI-E Gigabit Ethernet Controller + +pci:v000011ABd00004370* + ID_MODEL_FROM_DATABASE=88E8075 PCI-E Gigabit Ethernet Controller + +pci:v000011ABd00004380* + ID_MODEL_FROM_DATABASE=88E8057 PCI-E Gigabit Ethernet Controller + +pci:v000011ABd00004381* + ID_MODEL_FROM_DATABASE=Yukon Optima 88E8059 [PCIe Gigabit Ethernet Controller with AVB] + +pci:v000011ABd00004381sv00001259sd00002803* + ID_MODEL_FROM_DATABASE=Yukon Optima 88E8059 [PCIe Gigabit Ethernet Controller with AVB] (AT-2814FX) + +pci:v000011ABd00004381sv00001259sd00002804* + ID_MODEL_FROM_DATABASE=Yukon Optima 88E8059 [PCIe Gigabit Ethernet Controller with AVB] (AT-2874xx) + +pci:v000011ABd00004611* + ID_MODEL_FROM_DATABASE=GT-64115 System Controller + +pci:v000011ABd00004620* + ID_MODEL_FROM_DATABASE=GT-64120/64120A/64121A System Controller + +pci:v000011ABd00004801* + ID_MODEL_FROM_DATABASE=GT-48001 + +pci:v000011ABd00005005* + ID_MODEL_FROM_DATABASE=Belkin F5D5005 Gigabit Desktop Network PCI Card + +pci:v000011ABd00005040* + ID_MODEL_FROM_DATABASE=MV88SX5040 4-port SATA I PCI-X Controller + +pci:v000011ABd00005041* + ID_MODEL_FROM_DATABASE=MV88SX5041 4-port SATA I PCI-X Controller + +pci:v000011ABd00005080* + ID_MODEL_FROM_DATABASE=MV88SX5080 8-port SATA I PCI-X Controller + +pci:v000011ABd00005081* + ID_MODEL_FROM_DATABASE=MV88SX5081 8-port SATA I PCI-X Controller + +pci:v000011ABd00005181* + ID_MODEL_FROM_DATABASE=88f5181 [Orion-1] ARM SoC + +pci:v000011ABd00005182* + ID_MODEL_FROM_DATABASE=88f5182 [Orion-NAS] ARM SoC + +pci:v000011ABd00005281* + ID_MODEL_FROM_DATABASE=88f5281 [Orion-2] ARM SoC + +pci:v000011ABd00006041* + ID_MODEL_FROM_DATABASE=MV88SX6041 4-port SATA II PCI-X Controller + +pci:v000011ABd00006042* + ID_MODEL_FROM_DATABASE=88SX6042 PCI-X 4-Port SATA-II + +pci:v000011ABd00006081* + ID_MODEL_FROM_DATABASE=MV88SX6081 8-port SATA II PCI-X Controller + +pci:v000011ABd00006101* + ID_MODEL_FROM_DATABASE=88SE6101/6102 single-port PATA133 interface + +pci:v000011ABd00006101sv00001043sd000082E0* + ID_MODEL_FROM_DATABASE=88SE6101/6102 single-port PATA133 interface (P5K PRO Motherboard) + +pci:v000011ABd00006121* + ID_MODEL_FROM_DATABASE=88SE6111/6121 SATA II / PATA Controller + +pci:v000011ABd00006121sv000011ABsd00006121* + ID_MODEL_FROM_DATABASE=88SE6111/6121 SATA II / PATA Controller (88SE6111/6121 1/2 port SATA II + 1 port PATA Controller) + +pci:v000011ABd00006141* + ID_MODEL_FROM_DATABASE=88SE614x SATA II PCI-E controller + +pci:v000011ABd00006145* + ID_MODEL_FROM_DATABASE=88SE6145 SATA II PCI-E controller + +pci:v000011ABd00006180* + ID_MODEL_FROM_DATABASE=88F6180 [Kirkwood] ARM SoC + +pci:v000011ABd00006192* + ID_MODEL_FROM_DATABASE=88F6190/6192 [Kirkwood] ARM SoC + +pci:v000011ABd00006281* + ID_MODEL_FROM_DATABASE=88F6281 [Kirkwood] ARM SoC + +pci:v000011ABd00006381* + ID_MODEL_FROM_DATABASE=MV78xx0 [Discovery Innovation] ARM SoC + +pci:v000011ABd00006440* + ID_MODEL_FROM_DATABASE=88SE6440 SAS/SATA PCIe controller + +pci:v000011ABd00006450* + ID_MODEL_FROM_DATABASE=64560 System Controller + +pci:v000011ABd00006460* + ID_MODEL_FROM_DATABASE=MV64360/64361/64362 System Controller + +pci:v000011ABd00006480* + ID_MODEL_FROM_DATABASE=MV64460/64461/64462 System Controller + +pci:v000011ABd00006480sv00001775sd0000C200* + ID_MODEL_FROM_DATABASE=MV64460/64461/64462 System Controller (C2K CompactPCI single board computer) + +pci:v000011ABd00006485* + ID_MODEL_FROM_DATABASE=MV64460/64461/64462 System Controller, Revision B + +pci:v000011ABd00007042* + ID_MODEL_FROM_DATABASE=88SX7042 PCI-e 4-port SATA-II + +pci:v000011ABd00007042sv000016B8sd0000434B* + ID_MODEL_FROM_DATABASE=88SX7042 PCI-e 4-port SATA-II (Tempo SATA E4P) + +pci:v000011ABd00007810* + ID_MODEL_FROM_DATABASE=MV78100 [Discovery Innovation] ARM SoC + +pci:v000011ABd00007820* + ID_MODEL_FROM_DATABASE=MV78200 [Discovery Innovation] ARM SoC + +pci:v000011ABd00007823* + ID_MODEL_FROM_DATABASE=MV78230 [Armada XP] ARM SoC + +pci:v000011ABd00007846* + ID_MODEL_FROM_DATABASE=88F6820 [Armada 385] ARM SoC + +pci:v000011ABd0000D40F* + ID_MODEL_FROM_DATABASE=Bobcat3 Ethernet Switch + +pci:v000011ABd0000F003* + ID_MODEL_FROM_DATABASE=GT-64010 Primary Image Piranha Image Generator + +pci:v000011AC* + ID_VENDOR_FROM_DATABASE=Canon Information Systems Research Aust. + +pci:v000011AD* + ID_VENDOR_FROM_DATABASE=Lite-On Communications Inc + +pci:v000011ADd00000002* + ID_MODEL_FROM_DATABASE=LNE100TX + +pci:v000011ADd00000002sv000011ADsd00000002* + ID_MODEL_FROM_DATABASE=LNE100TX + +pci:v000011ADd00000002sv000011ADsd00000003* + ID_MODEL_FROM_DATABASE=LNE100TX + +pci:v000011ADd00000002sv000011ADsd0000F003* + ID_MODEL_FROM_DATABASE=LNE100TX + +pci:v000011ADd00000002sv000011ADsd0000FFFF* + ID_MODEL_FROM_DATABASE=LNE100TX + +pci:v000011ADd00000002sv00001385sd0000F004* + ID_MODEL_FROM_DATABASE=LNE100TX (FA310TX) + +pci:v000011ADd00000002sv00002646sd0000F002* + ID_MODEL_FROM_DATABASE=LNE100TX (KNE110TX EtheRx Fast Ethernet) + +pci:v000011ADd0000C115* + ID_MODEL_FROM_DATABASE=LNE100TX [Linksys EtherFast 10/100] + +pci:v000011ADd0000C115sv000011ADsd0000C001* + ID_MODEL_FROM_DATABASE=LNE100TX [Linksys EtherFast 10/100] (LNE100TX [ver 2.0]) + +pci:v000011ADd0000C115sv00002646sd0000000B* + ID_MODEL_FROM_DATABASE=LNE100TX [Linksys EtherFast 10/100] (KNE111TX) + +pci:v000011AE* + ID_VENDOR_FROM_DATABASE=Aztech System Ltd + +pci:v000011AF* + ID_VENDOR_FROM_DATABASE=Avid Technology Inc. + +pci:v000011AFd00000001* + ID_MODEL_FROM_DATABASE=Cinema + +pci:v000011AFd0000EE40* + ID_MODEL_FROM_DATABASE=Digidesign Audiomedia III + +pci:v000011B0* + ID_VENDOR_FROM_DATABASE=V3 Semiconductor Inc. + +pci:v000011B0d00000002* + ID_MODEL_FROM_DATABASE=V300PSC + +pci:v000011B0d00000292* + ID_MODEL_FROM_DATABASE=V292PBC [Am29030/40 Bridge] + +pci:v000011B0d00000960* + ID_MODEL_FROM_DATABASE=V96xPBC + +pci:v000011B0d0000880A* + ID_MODEL_FROM_DATABASE=Deltacast Delta-HD-22 + +pci:v000011B0d0000C960* + ID_MODEL_FROM_DATABASE=V96DPC + +pci:v000011B1* + ID_VENDOR_FROM_DATABASE=Apricot Computers + +pci:v000011B2* + ID_VENDOR_FROM_DATABASE=Eastman Kodak + +pci:v000011B3* + ID_VENDOR_FROM_DATABASE=Barr Systems Inc. + +pci:v000011B4* + ID_VENDOR_FROM_DATABASE=Leitch Technology International + +pci:v000011B5* + ID_VENDOR_FROM_DATABASE=Radstone Technology Plc + +pci:v000011B6* + ID_VENDOR_FROM_DATABASE=United Video Corp + +pci:v000011B7* + ID_VENDOR_FROM_DATABASE=Motorola + +pci:v000011B8* + ID_VENDOR_FROM_DATABASE=XPoint Technologies, Inc + +pci:v000011B8d00000001* + ID_MODEL_FROM_DATABASE=Quad PeerMaster + +pci:v000011B9* + ID_VENDOR_FROM_DATABASE=Pathlight Technology Inc. + +pci:v000011B9d0000C0ED* + ID_MODEL_FROM_DATABASE=SSA Controller + +pci:v000011BA* + ID_VENDOR_FROM_DATABASE=Videotron Corp + +pci:v000011BB* + ID_VENDOR_FROM_DATABASE=Pyramid Technology + +pci:v000011BC* + ID_VENDOR_FROM_DATABASE=Network Peripherals Inc + +pci:v000011BCd00000001* + ID_MODEL_FROM_DATABASE=NP-PCI + +pci:v000011BD* + ID_VENDOR_FROM_DATABASE=Pinnacle Systems Inc. + +pci:v000011BDd0000002E* + ID_MODEL_FROM_DATABASE=PCTV 40i + +pci:v000011BDd00000040* + ID_MODEL_FROM_DATABASE=Royal TS Function 1 + +pci:v000011BDd00000040sv000011BDsd00000044* + ID_MODEL_FROM_DATABASE=Royal TS Function 1 (PCTV 2000i Dual DVB-T Pro PCI Tuner 1) + +pci:v000011BDd00000040sv000011BDsd00000045* + ID_MODEL_FROM_DATABASE=Royal TS Function 1 (PCTV Dual Sat Pro PCI 4000i Tuner 1) + +pci:v000011BDd00000041* + ID_MODEL_FROM_DATABASE=RoyalTS Function 2 + +pci:v000011BDd00000041sv000011BDsd00000044* + ID_MODEL_FROM_DATABASE=RoyalTS Function 2 (PCTV 2000i Dual DVB-T Pro PCI Tuner 2) + +pci:v000011BDd00000041sv000011BDsd00000045* + ID_MODEL_FROM_DATABASE=RoyalTS Function 2 (PCTV Dual Sat Pro PCI 4000i Tuner 2) + +pci:v000011BDd00000042* + ID_MODEL_FROM_DATABASE=Royal TS Function 3 + +pci:v000011BDd00000042sv000011BDsd00000044* + ID_MODEL_FROM_DATABASE=Royal TS Function 3 (PCTV 2000i Dual DVB-T Pro PCI Common) + +pci:v000011BDd00000042sv000011BDsd00000045* + ID_MODEL_FROM_DATABASE=Royal TS Function 3 (PCTV Dual Sat Pro PCI 4000i Common) + +pci:v000011BDd00000051* + ID_MODEL_FROM_DATABASE=PCTV HD 800i + +pci:v000011BDd0000BEDE* + ID_MODEL_FROM_DATABASE=AV/DV Studio Capture Card + +pci:v000011BE* + ID_VENDOR_FROM_DATABASE=International Microcircuits Inc + +pci:v000011BF* + ID_VENDOR_FROM_DATABASE=Astrodesign, Inc. + +pci:v000011C0* + ID_VENDOR_FROM_DATABASE=Hewlett Packard + +pci:v000011C1* + ID_VENDOR_FROM_DATABASE=LSI Corporation + +pci:v000011C1d00000440* + ID_MODEL_FROM_DATABASE=56k WinModem + +pci:v000011C1d00000440sv00001033sd00008015* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000440sv00001033sd00008047* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000440sv00001033sd0000804F* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000440sv000010CFsd0000102C* + ID_MODEL_FROM_DATABASE=56k WinModem (LB LT Modem V.90 56k) + +pci:v000011C1d00000440sv000010CFsd0000104A* + ID_MODEL_FROM_DATABASE=56k WinModem (BIBLO LT Modem 56k) + +pci:v000011C1d00000440sv000010CFsd0000105F* + ID_MODEL_FROM_DATABASE=56k WinModem (LB2 LT Modem V.90 56k) + +pci:v000011C1d00000440sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=56k WinModem (Internal V.90 Modem) + +pci:v000011C1d00000440sv000011C1sd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000440sv0000122Dsd00004101* + ID_MODEL_FROM_DATABASE=56k WinModem (MDP7800-U Modem) + +pci:v000011C1d00000440sv0000122Dsd00004102* + ID_MODEL_FROM_DATABASE=56k WinModem (MDP7800SP-U Modem) + +pci:v000011C1d00000440sv000013E0sd00000040* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000440sv000013E0sd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000440sv000013E0sd00000441* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000440sv000013E0sd00000450* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000440sv000013E0sd0000F100* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000440sv000013E0sd0000F101* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000440sv0000144Dsd00002101* + ID_MODEL_FROM_DATABASE=56k WinModem (LT56PV Modem) + +pci:v000011C1d00000440sv0000149Fsd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000441* + ID_MODEL_FROM_DATABASE=56k WinModem + +pci:v000011C1d00000441sv00001033sd0000804D* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv00001033sd00008065* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv00001092sd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (Supra 56i) + +pci:v000011C1d00000441sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=56k WinModem (Internal V.90 Modem) + +pci:v000011C1d00000441sv000011C1sd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv000011C1sd00000441* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv0000122Dsd00004100* + ID_MODEL_FROM_DATABASE=56k WinModem (MDP7800-U Modem) + +pci:v000011C1d00000441sv000013E0sd00000040* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv000013E0sd00000100* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv000013E0sd00000410* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv000013E0sd00000420* + ID_MODEL_FROM_DATABASE=56k WinModem (TelePath Internet 56k WinModem) + +pci:v000011C1d00000441sv000013E0sd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv000013E0sd00000443* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv000013E0sd0000F102* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv00001416sd00009804* + ID_MODEL_FROM_DATABASE=56k WinModem (CommWave 56k Modem) + +pci:v000011C1d00000441sv0000141Dsd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000441sv0000144Fsd00000441* + ID_MODEL_FROM_DATABASE=56k WinModem (Lucent 56k V.90 DF Modem) + +pci:v000011C1d00000441sv0000144Fsd00000449* + ID_MODEL_FROM_DATABASE=56k WinModem (Lucent 56k V.90 DF Modem) + +pci:v000011C1d00000441sv0000144Fsd0000110D* + ID_MODEL_FROM_DATABASE=56k WinModem (Lucent Win Modem) + +pci:v000011C1d00000441sv00001468sd00000441* + ID_MODEL_FROM_DATABASE=56k WinModem (Presario 56k V.90 DF Modem) + +pci:v000011C1d00000441sv00001668sd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (Lucent Win Modem) + +pci:v000011C1d00000442* + ID_MODEL_FROM_DATABASE=56k WinModem + +pci:v000011C1d00000442sv000011C1sd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d00000442sv000011C1sd00000442* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d00000442sv000013E0sd00000412* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d00000442sv000013E0sd00000442* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d00000442sv000013FCsd00002471* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d00000442sv0000144Dsd00002104* + ID_MODEL_FROM_DATABASE=56k WinModem (LT56PT Modem) + +pci:v000011C1d00000442sv0000144Fsd00001104* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d00000442sv0000149Fsd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d00000442sv00001668sd00000440* + ID_MODEL_FROM_DATABASE=56k WinModem (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d00000443* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000444* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000445* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000445sv00008086sd00002203* + ID_MODEL_FROM_DATABASE=LT WinModem (PRO/100+ MiniPCI (probably an Ambit U98.003.C.00 combo card)) + +pci:v000011C1d00000445sv00008086sd00002204* + ID_MODEL_FROM_DATABASE=LT WinModem (PRO/100+ MiniPCI on Armada E500) + +pci:v000011C1d00000446* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000447* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000448* + ID_MODEL_FROM_DATABASE=WinModem 56k + +pci:v000011C1d00000448sv00001014sd00000131* + ID_MODEL_FROM_DATABASE=WinModem 56k (Lucent Win Modem) + +pci:v000011C1d00000448sv00001033sd00008066* + ID_MODEL_FROM_DATABASE=WinModem 56k (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000448sv000013E0sd00000030* + ID_MODEL_FROM_DATABASE=WinModem 56k (56k Voice Modem) + +pci:v000011C1d00000448sv000013E0sd00000040* + ID_MODEL_FROM_DATABASE=WinModem 56k (LT WinModem 56k Data+Fax+Voice+Dsvd) + +pci:v000011C1d00000448sv00001668sd00002400* + ID_MODEL_FROM_DATABASE=WinModem 56k (LT WinModem 56k (MiniPCI Ethernet+Modem)) + +pci:v000011C1d00000449* + ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k + +pci:v000011C1d00000449sv00000E11sd0000B14D* + ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (56k V.90 Modem) + +pci:v000011C1d00000449sv00001014sd0000018C* + ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (ThinkPad 600X) + +pci:v000011C1d00000449sv000013E0sd00000020* + ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (LT WinModem 56k Data+Fax) + +pci:v000011C1d00000449sv000013E0sd00000041* + ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (TelePath Internet 56k WinModem) + +pci:v000011C1d00000449sv00001436sd00000440* + ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (Lucent Win Modem) + +pci:v000011C1d00000449sv0000144Fsd00000449* + ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (Lucent 56k V.90 DFi Modem) + +pci:v000011C1d00000449sv00001468sd00000410* + ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (IBM ThinkPad T23) + +pci:v000011C1d00000449sv00001468sd00000440* + ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (Lucent Win Modem) + +pci:v000011C1d00000449sv00001468sd00000449* + ID_MODEL_FROM_DATABASE=L56xM+S [Mars-2] WinModem 56k (Presario 56k V.90 DFi Modem) + +pci:v000011C1d0000044A* + ID_MODEL_FROM_DATABASE=F-1156IV WinModem (V90, 56KFlex) + +pci:v000011C1d0000044Asv000010CFsd00001072* + ID_MODEL_FROM_DATABASE=F-1156IV WinModem (V90, 56KFlex) (LB Global LT Modem) + +pci:v000011C1d0000044Asv000013E0sd00000012* + ID_MODEL_FROM_DATABASE=F-1156IV WinModem (V90, 56KFlex) (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d0000044Asv000013E0sd00000042* + ID_MODEL_FROM_DATABASE=F-1156IV WinModem (V90, 56KFlex) (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d0000044Asv0000144Fsd00001005* + ID_MODEL_FROM_DATABASE=F-1156IV WinModem (V90, 56KFlex) (LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd) + +pci:v000011C1d0000044B* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d0000044C* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d0000044D* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d0000044E* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d0000044F* + ID_MODEL_FROM_DATABASE=V90 WildWire Modem + +pci:v000011C1d00000450* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000450sv00001033sd000080A8* + ID_MODEL_FROM_DATABASE=LT WinModem (Versa Note Vxi) + +pci:v000011C1d00000450sv0000144Fsd00004005* + ID_MODEL_FROM_DATABASE=LT WinModem (Magnia SG20) + +pci:v000011C1d00000450sv00001468sd00000450* + ID_MODEL_FROM_DATABASE=LT WinModem (Evo N600c) + +pci:v000011C1d00000451* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000452* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000453* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000454* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000455* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000456* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000457* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000458* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000459* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d0000045A* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d0000045C* + ID_MODEL_FROM_DATABASE=LT WinModem + +pci:v000011C1d00000461* + ID_MODEL_FROM_DATABASE=V90 WildWire Modem + +pci:v000011C1d00000462* + ID_MODEL_FROM_DATABASE=V90 WildWire Modem + +pci:v000011C1d00000480* + ID_MODEL_FROM_DATABASE=Venus Modem (V90, 56KFlex) + +pci:v000011C1d0000048C* + ID_MODEL_FROM_DATABASE=V.92 56K WinModem + +pci:v000011C1d0000048F* + ID_MODEL_FROM_DATABASE=V.92 56k WinModem + +pci:v000011C1d00000620* + ID_MODEL_FROM_DATABASE=Lucent V.92 Data/Fax Modem + +pci:v000011C1d00002600* + ID_MODEL_FROM_DATABASE=StarPro26XX family (SP2601, SP2603, SP2612) DSP + +pci:v000011C1d00005400* + ID_MODEL_FROM_DATABASE=OR3TP12 FPSC + +pci:v000011C1d00005656* + ID_MODEL_FROM_DATABASE=Venus Modem + +pci:v000011C1d00005801* + ID_MODEL_FROM_DATABASE=USB + +pci:v000011C1d00005802* + ID_MODEL_FROM_DATABASE=USS-312 USB Controller + +pci:v000011C1d00005803* + ID_MODEL_FROM_DATABASE=USS-344S USB Controller + +pci:v000011C1d00005811* + ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller + +pci:v000011C1d00005811sv0000103Csd00002A34* + ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (Pavilion a1677c) + +pci:v000011C1d00005811sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (Asus IPIBL-LB Motherboard) + +pci:v000011C1d00005811sv0000103Csd00002A9E* + ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (Pavilion p6310f) + +pci:v000011C1d00005811sv00001043sd00008294* + ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (LSI FW322/323 IEEE 1394a FireWire Controller) + +pci:v000011C1d00005811sv000011BDsd0000000E* + ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (LSI FW323) + +pci:v000011C1d00005811sv00008086sd0000524C* + ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (D865PERL mainboard) + +pci:v000011C1d00005811sv00009005sd00000033* + ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (Adaptec AFW-2100 (HP) 2102900-R) + +pci:v000011C1d00005811sv0000DEADsd00000800* + ID_MODEL_FROM_DATABASE=FW322/323 [TrueFire] 1394a Controller (FireWire Host Bus Adapter) + +pci:v000011C1d00005901* + ID_MODEL_FROM_DATABASE=FW643 [TrueFire] PCIe 1394b Controller + +pci:v000011C1d00005901sv000011C1sd00005900* + ID_MODEL_FROM_DATABASE=FW643 [TrueFire] PCIe 1394b Controller + +pci:v000011C1d00005901sv00001443sd00000643* + ID_MODEL_FROM_DATABASE=FW643 [TrueFire] PCIe 1394b Controller (FireBoard800-e V.2) + +pci:v000011C1d00005901sv00001546sd00000643* + ID_MODEL_FROM_DATABASE=FW643 [TrueFire] PCIe 1394b Controller (FWB-PCIE1X2x) + +pci:v000011C1d00005903* + ID_MODEL_FROM_DATABASE=FW533 [TrueFire] PCIe 1394a Controller + +pci:v000011C1d00008110* + ID_MODEL_FROM_DATABASE=T8110 H.100/H.110 TDM switch + +pci:v000011C1d00008110sv000012D9sd0000000C* + ID_MODEL_FROM_DATABASE=T8110 H.100/H.110 TDM switch (E1/T1 PMXc cPCI carrier card) + +pci:v000011C1d0000AB10* + ID_MODEL_FROM_DATABASE=WL60010 Wireless LAN MAC + +pci:v000011C1d0000AB11* + ID_MODEL_FROM_DATABASE=WL60040 Multimode Wireles LAN MAC + +pci:v000011C1d0000AB11sv000011C1sd0000AB12* + ID_MODEL_FROM_DATABASE=WL60040 Multimode Wireles LAN MAC (WaveLAN 11abg Cardbus card (Model 1102)) + +pci:v000011C1d0000AB11sv000011C1sd0000AB13* + ID_MODEL_FROM_DATABASE=WL60040 Multimode Wireles LAN MAC (WaveLAN 11abg MiniPCI card (Model 0512)) + +pci:v000011C1d0000AB11sv000011C1sd0000AB15* + ID_MODEL_FROM_DATABASE=WL60040 Multimode Wireles LAN MAC (WaveLAN 11abg Cardbus card (Model 1106)) + +pci:v000011C1d0000AB11sv000011C1sd0000AB16* + ID_MODEL_FROM_DATABASE=WL60040 Multimode Wireles LAN MAC (WaveLAN 11abg MiniPCI card (Model 0516)) + +pci:v000011C1d0000AB20* + ID_MODEL_FROM_DATABASE=ORiNOCO PCI Adapter + +pci:v000011C1d0000AB21* + ID_MODEL_FROM_DATABASE=Agere Wireless PCI Adapter + +pci:v000011C1d0000AB30* + ID_MODEL_FROM_DATABASE=Hermes2 Mini-PCI WaveLAN a/b/g + +pci:v000011C1d0000AB30sv000014CDsd00002012* + ID_MODEL_FROM_DATABASE=Hermes2 Mini-PCI WaveLAN a/b/g + +pci:v000011C1d0000ED00* + ID_MODEL_FROM_DATABASE=ET-131x PCI-E Ethernet Controller + +pci:v000011C1d0000ED01* + ID_MODEL_FROM_DATABASE=ET-131x PCI-E Ethernet Controller + +pci:v000011C2* + ID_VENDOR_FROM_DATABASE=Sand Microelectronics + +pci:v000011C3* + ID_VENDOR_FROM_DATABASE=NEC Corporation + +pci:v000011C4* + ID_VENDOR_FROM_DATABASE=Document Technologies, Inc + +pci:v000011C5* + ID_VENDOR_FROM_DATABASE=Shiva Corporation + +pci:v000011C6* + ID_VENDOR_FROM_DATABASE=Dainippon Screen Mfg. Co. Ltd + +pci:v000011C7* + ID_VENDOR_FROM_DATABASE=D.C.M. Data Systems + +pci:v000011C8* + ID_VENDOR_FROM_DATABASE=Dolphin Interconnect Solutions AS + +pci:v000011C8d00000658* + ID_MODEL_FROM_DATABASE=PSB32 SCI-Adapter D31x + +pci:v000011C8d0000D665* + ID_MODEL_FROM_DATABASE=PSB64 SCI-Adapter D32x + +pci:v000011C8d0000D667* + ID_MODEL_FROM_DATABASE=PSB66 SCI-Adapter D33x + +pci:v000011C9* + ID_VENDOR_FROM_DATABASE=Magma + +pci:v000011C9d00000010* + ID_MODEL_FROM_DATABASE=16-line serial port w/- DMA + +pci:v000011C9d00000011* + ID_MODEL_FROM_DATABASE=4-line serial port w/- DMA + +pci:v000011CA* + ID_VENDOR_FROM_DATABASE=LSI Systems, Inc + +pci:v000011CB* + ID_VENDOR_FROM_DATABASE=Specialix Research Ltd. + +pci:v000011CBd00002000* + ID_MODEL_FROM_DATABASE=PCI_9050 + +pci:v000011CBd00002000sv000011CBsd00000200* + ID_MODEL_FROM_DATABASE=PCI_9050 (SX) + +pci:v000011CBd00002000sv000011CBsd0000B008* + ID_MODEL_FROM_DATABASE=PCI_9050 (I/O8+) + +pci:v000011CBd00004000* + ID_MODEL_FROM_DATABASE=SUPI_1 + +pci:v000011CBd00008000* + ID_MODEL_FROM_DATABASE=T225 + +pci:v000011CC* + ID_VENDOR_FROM_DATABASE=Michels & Kleberhoff Computer GmbH + +pci:v000011CD* + ID_VENDOR_FROM_DATABASE=HAL Computer Systems, Inc. + +pci:v000011CE* + ID_VENDOR_FROM_DATABASE=Netaccess + +pci:v000011CF* + ID_VENDOR_FROM_DATABASE=Pioneer Electronic Corporation + +pci:v000011D0* + ID_VENDOR_FROM_DATABASE=Lockheed Martin Federal Systems-Manassas + +pci:v000011D1* + ID_VENDOR_FROM_DATABASE=Auravision + +pci:v000011D1d000001F7* + ID_MODEL_FROM_DATABASE=VxP524 + +pci:v000011D1d000001F9* + ID_MODEL_FROM_DATABASE=VxP951 + +pci:v000011D2* + ID_VENDOR_FROM_DATABASE=Intercom Inc. + +pci:v000011D3* + ID_VENDOR_FROM_DATABASE=Trancell Systems Inc + +pci:v000011D4* + ID_VENDOR_FROM_DATABASE=Analog Devices + +pci:v000011D4d00001535* + ID_MODEL_FROM_DATABASE=Blackfin BF535 processor + +pci:v000011D4d00001805* + ID_MODEL_FROM_DATABASE=SM56 PCI modem + +pci:v000011D5* + ID_VENDOR_FROM_DATABASE=Ikon Corporation + +pci:v000011D5d00000115* + ID_MODEL_FROM_DATABASE=10115 + +pci:v000011D5d00000117* + ID_MODEL_FROM_DATABASE=10117 + +pci:v000011D6* + ID_VENDOR_FROM_DATABASE=Tekelec Telecom + +pci:v000011D7* + ID_VENDOR_FROM_DATABASE=Trenton Technology, Inc. + +pci:v000011D8* + ID_VENDOR_FROM_DATABASE=Image Technologies Development + +pci:v000011D9* + ID_VENDOR_FROM_DATABASE=TEC Corporation + +pci:v000011DA* + ID_VENDOR_FROM_DATABASE=Novell + +pci:v000011DB* + ID_VENDOR_FROM_DATABASE=Sega Enterprises Ltd + +pci:v000011DC* + ID_VENDOR_FROM_DATABASE=Questra Corporation + +pci:v000011DD* + ID_VENDOR_FROM_DATABASE=Crosfield Electronics Limited + +pci:v000011DE* + ID_VENDOR_FROM_DATABASE=Zoran Corporation + +pci:v000011DEd00006017* + ID_MODEL_FROM_DATABASE=miroVIDEO DC30 + +pci:v000011DEd00006057* + ID_MODEL_FROM_DATABASE=ZR36057PQC Video cutting chipset + +pci:v000011DEd00006057sv00001031sd00007EFE* + ID_MODEL_FROM_DATABASE=ZR36057PQC Video cutting chipset (DC10 Plus) + +pci:v000011DEd00006057sv00001031sd0000FC00* + ID_MODEL_FROM_DATABASE=ZR36057PQC Video cutting chipset (MiroVIDEO DC50, Motion JPEG Capture/CODEC Board) + +pci:v000011DEd00006057sv000012F8sd00008A02* + ID_MODEL_FROM_DATABASE=ZR36057PQC Video cutting chipset (Tekram Video Kit) + +pci:v000011DEd00006057sv000013CAsd00004231* + ID_MODEL_FROM_DATABASE=ZR36057PQC Video cutting chipset (JPEG/TV Card) + +pci:v000011DEd00006120* + ID_MODEL_FROM_DATABASE=ZR36120 + +pci:v000011DEd00006120sv00001328sd0000F001* + ID_MODEL_FROM_DATABASE=ZR36120 (Cinemaster C DVD Decoder) + +pci:v000011DEd00006120sv000013C2sd00000000* + ID_MODEL_FROM_DATABASE=ZR36120 (MediaFocus Satellite TV Card) + +pci:v000011DEd00006120sv00001DE1sd00009FFF* + ID_MODEL_FROM_DATABASE=ZR36120 (Video Kit C210) + +pci:v000011DF* + ID_VENDOR_FROM_DATABASE=New Wave PDG + +pci:v000011E0* + ID_VENDOR_FROM_DATABASE=Cray Communications A/S + +pci:v000011E1* + ID_VENDOR_FROM_DATABASE=GEC Plessey Semi Inc. + +pci:v000011E2* + ID_VENDOR_FROM_DATABASE=Samsung Information Systems America + +pci:v000011E3* + ID_VENDOR_FROM_DATABASE=Quicklogic Corporation + +pci:v000011E3d00000001* + ID_MODEL_FROM_DATABASE=COM-ON-AIR Dosch&Amand DECT + +pci:v000011E3d00000560* + ID_MODEL_FROM_DATABASE=QL5064 Companion Design Demo Board + +pci:v000011E3d00005030* + ID_MODEL_FROM_DATABASE=PC Watchdog + +pci:v000011E3d00008417* + ID_MODEL_FROM_DATABASE=QL5064 [QuickPCI] PCI v2.2 bridge for SMT417 Dual TMS320C6416T PMC Module + +pci:v000011E4* + ID_VENDOR_FROM_DATABASE=Second Wave Inc + +pci:v000011E5* + ID_VENDOR_FROM_DATABASE=IIX Consulting + +pci:v000011E6* + ID_VENDOR_FROM_DATABASE=Mitsui-Zosen System Research + +pci:v000011E7* + ID_VENDOR_FROM_DATABASE=Toshiba America, Elec. Company + +pci:v000011E8* + ID_VENDOR_FROM_DATABASE=Digital Processing Systems Inc. + +pci:v000011E9* + ID_VENDOR_FROM_DATABASE=Highwater Designs Ltd. + +pci:v000011EA* + ID_VENDOR_FROM_DATABASE=Elsag Bailey + +pci:v000011EB* + ID_VENDOR_FROM_DATABASE=Formation Inc. + +pci:v000011EC* + ID_VENDOR_FROM_DATABASE=Coreco Inc + +pci:v000011ECd0000000D* + ID_MODEL_FROM_DATABASE=Oculus-F/64P + +pci:v000011ECd00001800* + ID_MODEL_FROM_DATABASE=Cobra/C6 + +pci:v000011ED* + ID_VENDOR_FROM_DATABASE=Mediamatics + +pci:v000011EE* + ID_VENDOR_FROM_DATABASE=Dome Imaging Systems Inc + +pci:v000011EF* + ID_VENDOR_FROM_DATABASE=Nicolet Technologies B.V. + +pci:v000011F0* + ID_VENDOR_FROM_DATABASE=Compu-Shack + +pci:v000011F0d00004231* + ID_MODEL_FROM_DATABASE=FDDI + +pci:v000011F0d00004232* + ID_MODEL_FROM_DATABASE=FASTline UTP Quattro + +pci:v000011F0d00004233* + ID_MODEL_FROM_DATABASE=FASTline FO + +pci:v000011F0d00004234* + ID_MODEL_FROM_DATABASE=FASTline UTP + +pci:v000011F0d00004235* + ID_MODEL_FROM_DATABASE=FASTline-II UTP + +pci:v000011F0d00004236* + ID_MODEL_FROM_DATABASE=FASTline-II FO + +pci:v000011F0d00004731* + ID_MODEL_FROM_DATABASE=GIGAline + +pci:v000011F1* + ID_VENDOR_FROM_DATABASE=Symbios Logic Inc + +pci:v000011F2* + ID_VENDOR_FROM_DATABASE=Picture Tel Japan K.K. + +pci:v000011F3* + ID_VENDOR_FROM_DATABASE=Keithley Metrabyte + +pci:v000011F3d00000011* + ID_MODEL_FROM_DATABASE=KPCI-PIO24 + +pci:v000011F4* + ID_VENDOR_FROM_DATABASE=Kinetic Systems Corporation + +pci:v000011F4d00002915* + ID_MODEL_FROM_DATABASE=CAMAC controller + +pci:v000011F5* + ID_VENDOR_FROM_DATABASE=Computing Devices International + +pci:v000011F6* + ID_VENDOR_FROM_DATABASE=Compex + +pci:v000011F6d00000112* + ID_MODEL_FROM_DATABASE=ENet100VG4 + +pci:v000011F6d00000113* + ID_MODEL_FROM_DATABASE=FreedomLine 100 + +pci:v000011F6d00001401* + ID_MODEL_FROM_DATABASE=ReadyLink 2000 + +pci:v000011F6d00002011* + ID_MODEL_FROM_DATABASE=RL100-ATX 10/100 + +pci:v000011F6d00002011sv000011F6sd00002011* + ID_MODEL_FROM_DATABASE=RL100-ATX 10/100 (RL100-ATX) + +pci:v000011F6d00002201* + ID_MODEL_FROM_DATABASE=ReadyLink 100TX (Winbond W89C840) + +pci:v000011F6d00002201sv000011F6sd00002011* + ID_MODEL_FROM_DATABASE=ReadyLink 100TX (Winbond W89C840) (ReadyLink 100TX) + +pci:v000011F6d00009881* + ID_MODEL_FROM_DATABASE=RL100TX Fast Ethernet + +pci:v000011F7* + ID_VENDOR_FROM_DATABASE=Scientific Atlanta + +pci:v000011F8* + ID_VENDOR_FROM_DATABASE=PMC-Sierra Inc. + +pci:v000011F8d00005220* + ID_MODEL_FROM_DATABASE=BR522x [PMC-Sierra maxRAID SAS Controller] + +pci:v000011F8d00007364* + ID_MODEL_FROM_DATABASE=PM7364 [FREEDM - 32 Frame Engine & Datalink Mgr] + +pci:v000011F8d00007375* + ID_MODEL_FROM_DATABASE=PM7375 [LASAR-155 ATM SAR] + +pci:v000011F8d00007384* + ID_MODEL_FROM_DATABASE=PM7384 [FREEDM - 84P672 Frm Engine & Datalink Mgr] + +pci:v000011F8d00008000* + ID_MODEL_FROM_DATABASE=PM8000 [SPC - SAS Protocol Controller] + +pci:v000011F8d00008009* + ID_MODEL_FROM_DATABASE=PM8009 SPCve 8x6G + +pci:v000011F8d00008018* + ID_MODEL_FROM_DATABASE=PM8018 Adaptec SAS Adaptor ASA-70165H PCIe Gen3 x8 6 Gbps 16-lane 4x SFF-8644 + +pci:v000011F8d00008032* + ID_MODEL_FROM_DATABASE=PM8032 Tachyon QE8 + +pci:v000011F8d00008032sv0000117Csd0000003A* + ID_MODEL_FROM_DATABASE=PM8032 Tachyon QE8 (Celerity FC-81EN Fibre Channel Adapter) + +pci:v000011F8d00008032sv0000117Csd0000003B* + ID_MODEL_FROM_DATABASE=PM8032 Tachyon QE8 (Celerity FC-82EN Fibre Channel Adapter) + +pci:v000011F8d00008032sv0000117Csd0000003C* + ID_MODEL_FROM_DATABASE=PM8032 Tachyon QE8 (Celerity FC-84EN Fibre Channel Adapter) + +pci:v000011F8d00008032sv0000117Csd0000403B* + ID_MODEL_FROM_DATABASE=PM8032 Tachyon QE8 (ThunderLink FC 1082 Fibre Channel Adapter) + +pci:v000011F8d00008053* + ID_MODEL_FROM_DATABASE=PM8053 SXP 12G 24-port SAS/SATA expander + +pci:v000011F8d00008054* + ID_MODEL_FROM_DATABASE=PM8054 SXP 12G 36-port SAS/SATA expander + +pci:v000011F8d00008055* + ID_MODEL_FROM_DATABASE=PM8055 SXP 12G 48-port SAS/SATA expander + +pci:v000011F8d00008056* + ID_MODEL_FROM_DATABASE=PM8056 SXP 12G 68-port SAS/SATA expander + +pci:v000011F8d00008060* + ID_MODEL_FROM_DATABASE=PM8060 SRCv 12G eight-port SAS/SATA RoC + +pci:v000011F8d00008063* + ID_MODEL_FROM_DATABASE=PM8063 SRCv 12G 16-port SAS/SATA RoC + +pci:v000011F8d00008070* + ID_MODEL_FROM_DATABASE=PM8070 Tachyon SPCv 12G eight-port SAS/SATA controller + +pci:v000011F8d00008071* + ID_MODEL_FROM_DATABASE=PM8071 Tachyon SPCve 12G eight-port SAS/SATA controller + +pci:v000011F8d00008072* + ID_MODEL_FROM_DATABASE=PM8072 Tachyon SPCv 12G 16-port SAS/SATA controller + +pci:v000011F8d00008073* + ID_MODEL_FROM_DATABASE=PM8073 Tachyon SPCve 12G 16-port SAS/SATA controller + +pci:v000011F8d00008531* + ID_MODEL_FROM_DATABASE=PM8531 PFX 24xG3 Fanout PCIe Switches + +pci:v000011F8d00008546* + ID_MODEL_FROM_DATABASE=PM8546 B-FEIP PSX 96xG3 PCIe Storage Switch + +pci:v000011F9* + ID_VENDOR_FROM_DATABASE=I-Cube Inc + +pci:v000011FA* + ID_VENDOR_FROM_DATABASE=Kasan Electronics Company, Ltd. + +pci:v000011FB* + ID_VENDOR_FROM_DATABASE=Datel Inc + +pci:v000011FC* + ID_VENDOR_FROM_DATABASE=Silicon Magic + +pci:v000011FD* + ID_VENDOR_FROM_DATABASE=High Street Consultants + +pci:v000011FE* + ID_VENDOR_FROM_DATABASE=Pepperl+Fuchs Comtrol, Inc. + +pci:v000011FEd00000001* + ID_MODEL_FROM_DATABASE=RocketPort PCI 32-port w/external I/F + +pci:v000011FEd00000002* + ID_MODEL_FROM_DATABASE=RocketPort PCI 8-port w/external I/F + +pci:v000011FEd00000003* + ID_MODEL_FROM_DATABASE=RocketPort PCI 16-port w/external I/F + +pci:v000011FEd00000004* + ID_MODEL_FROM_DATABASE=RocketPort PCI 4-port w/Quad Cable + +pci:v000011FEd00000005* + ID_MODEL_FROM_DATABASE=RocketPort PCI 8-port w/Octa Cable + +pci:v000011FEd00000006* + ID_MODEL_FROM_DATABASE=RocketPort PCI 8-port w/RJ11 connectors + +pci:v000011FEd00000007* + ID_MODEL_FROM_DATABASE=RocketPort PCI 4-port w/RJ45 connectors + +pci:v000011FEd00000008* + ID_MODEL_FROM_DATABASE=RocketPort PCI 8-port w/DB78 SNI connector (Siemens) + +pci:v000011FEd00000009* + ID_MODEL_FROM_DATABASE=RocketPort PCI 16-port w/DB78 SNI connector (Siemens) + +pci:v000011FEd0000000A* + ID_MODEL_FROM_DATABASE=RocketPort PCI Plus 4-port w/Quad Cable + +pci:v000011FEd0000000B* + ID_MODEL_FROM_DATABASE=RocketPort PCI Plus 8-port w/Octa Cable + +pci:v000011FEd0000000C* + ID_MODEL_FROM_DATABASE=RocketModem II 6-port + +pci:v000011FEd0000000D* + ID_MODEL_FROM_DATABASE=RocketModem 4-port + +pci:v000011FEd0000000E* + ID_MODEL_FROM_DATABASE=RocketPort PCI Plus 2-port RS-232 w/DB9 connectors + +pci:v000011FEd0000000F* + ID_MODEL_FROM_DATABASE=RocketPort PCI Plus 2-port SMPTE w/DB9 connectors + +pci:v000011FEd00000040* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 8-port w/Octa Cable RJ45 + +pci:v000011FEd00000041* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 32-port w/external I/F + +pci:v000011FEd00000042* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 8-port w/external I/F + +pci:v000011FEd00000043* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 16-port w/external I/F + +pci:v000011FEd00000044* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 4-port w/Quad Cable DB + +pci:v000011FEd00000045* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 8-port w/Octa Cable DB + +pci:v000011FEd00000046* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 4-port w/external I/F + +pci:v000011FEd00000047* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 4J (4-port) w/RJ45 connectors + +pci:v000011FEd00000048* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 4J (4-port) w/RJ45 connectors + +pci:v000011FEd0000004A* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY Plus 4-port + +pci:v000011FEd0000004B* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY Plus 8-port + +pci:v000011FEd0000004C* + ID_MODEL_FROM_DATABASE=RocketModem INFINITY III 8-port + +pci:v000011FEd0000004D* + ID_MODEL_FROM_DATABASE=RocketModem INFINITY III 4-port + +pci:v000011FEd0000004E* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY Plus 2-port + +pci:v000011FEd0000004F* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 2-port SMPTE w/DB9 connectors + +pci:v000011FEd00000050* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY Plus 4-port RJ45 + +pci:v000011FEd00000051* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY Plus 8-port RJ11 + +pci:v000011FEd00000052* + ID_MODEL_FROM_DATABASE=RocketPort INFINITY 8-port SMPTE w/DB9 Connectors + +pci:v000011FEd00000060* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS 8-port w/Octa Cable + +pci:v000011FEd00000061* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS 32-port w/external I/F + +pci:v000011FEd00000062* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS 8-Port w/external I/F + +pci:v000011FEd00000063* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS 16-port w/external I/F + +pci:v000011FEd00000064* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS 4-port w/Quad Cable + +pci:v000011FEd00000065* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS 8-port w/Octa Cable + +pci:v000011FEd00000066* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS 4-port w/external I/F + +pci:v000011FEd00000067* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS 4J (4-port) w/RJ45 connectors + +pci:v000011FEd00000068* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS 8J (8-port) w/RJ11 connectors + +pci:v000011FEd0000006F* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS SMPTE 2-port + +pci:v000011FEd00000072* + ID_MODEL_FROM_DATABASE=RocketPort EXPRESS SMPTE 8-port w/external I/F + +pci:v000011FEd00000801* + ID_MODEL_FROM_DATABASE=RocketPort uPCI 32-port w/external I/F + +pci:v000011FEd00000802* + ID_MODEL_FROM_DATABASE=RocketPort uPCI 8-port w/external I/F + +pci:v000011FEd00000803* + ID_MODEL_FROM_DATABASE=RocketPort uPCI 16-port w/external I/F + +pci:v000011FEd00000805* + ID_MODEL_FROM_DATABASE=RocketPort uPCI 8-port w/Octa Cable + +pci:v000011FEd0000080B* + ID_MODEL_FROM_DATABASE=RocketPort Plus uPCI 8-port w/Octa Cable + +pci:v000011FEd0000080C* + ID_MODEL_FROM_DATABASE=RocketModem III 8-port + +pci:v000011FEd0000080D* + ID_MODEL_FROM_DATABASE=RocketModem III 4-port + +pci:v000011FEd0000080E* + ID_MODEL_FROM_DATABASE=RocketPort uPCI 2-port RS232 w/DB9 connectors + +pci:v000011FEd0000080F* + ID_MODEL_FROM_DATABASE=RocketPort uPCI SMPTE 2-port + +pci:v000011FEd00000810* + ID_MODEL_FROM_DATABASE=RocketPort Plus uPCI 4J (4-port) w/RJ45 connectors + +pci:v000011FEd00000811* + ID_MODEL_FROM_DATABASE=RocketPort Plus uPCI 8J (8-port) w/RJ11 connectors + +pci:v000011FEd00000812* + ID_MODEL_FROM_DATABASE=RocketPort Plus uPCI 422 8-port + +pci:v000011FEd00000813* + ID_MODEL_FROM_DATABASE=RocketModem IV uPCI 8-port + +pci:v000011FEd00000814* + ID_MODEL_FROM_DATABASE=RocketModem IV uPCI 4-port + +pci:v000011FEd00000903* + ID_MODEL_FROM_DATABASE=RocketPort Compact PCI 16 port w/external I/F + +pci:v000011FEd00008015* + ID_MODEL_FROM_DATABASE=RocketPort 550 4-port + +pci:v000011FEd00008805* + ID_MODEL_FROM_DATABASE=RocketPort uPCI 4-port w/Quad Cable + +pci:v000011FEd0000880B* + ID_MODEL_FROM_DATABASE=RocketPort Plus uPCI 4-port w/Quad Cable + +pci:v000011FEd00008812* + ID_MODEL_FROM_DATABASE=RocketPort Plus uPCI 4-port RS422 w/Quad Cable + +pci:v000011FF* + ID_VENDOR_FROM_DATABASE=Scion Corporation + +pci:v000011FFd00000003* + ID_MODEL_FROM_DATABASE=AG-5 + +pci:v00001200* + ID_VENDOR_FROM_DATABASE=CSS Corporation + +pci:v00001201* + ID_VENDOR_FROM_DATABASE=Vista Controls Corp + +pci:v00001202* + ID_VENDOR_FROM_DATABASE=Network General Corp. + +pci:v00001202d00004300* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter + +pci:v00001202d00004300sv00001202sd00009841* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter (SK-9841 LX) + +pci:v00001202d00004300sv00001202sd00009842* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter (SK-9841 LX dual link) + +pci:v00001202d00004300sv00001202sd00009843* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter (SK-9843 SX) + +pci:v00001202d00004300sv00001202sd00009844* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter (SK-9843 SX dual link) + +pci:v00001203* + ID_VENDOR_FROM_DATABASE=Bayer Corporation, Agfa Division + +pci:v00001204* + ID_VENDOR_FROM_DATABASE=Lattice Semiconductor Corporation + +pci:v00001204d00001965* + ID_MODEL_FROM_DATABASE=SB6501 802.11ad Wireless Network Adapter + +pci:v00001205* + ID_VENDOR_FROM_DATABASE=Array Corporation + +pci:v00001206* + ID_VENDOR_FROM_DATABASE=Amdahl Corporation + +pci:v00001208* + ID_VENDOR_FROM_DATABASE=Parsytec GmbH + +pci:v00001208d00004853* + ID_MODEL_FROM_DATABASE=HS-Link Device + +pci:v00001209* + ID_VENDOR_FROM_DATABASE=SCI Systems Inc + +pci:v0000120A* + ID_VENDOR_FROM_DATABASE=Synaptel + +pci:v0000120B* + ID_VENDOR_FROM_DATABASE=Adaptive Solutions + +pci:v0000120C* + ID_VENDOR_FROM_DATABASE=Technical Corp. + +pci:v0000120D* + ID_VENDOR_FROM_DATABASE=Compression Labs, Inc. + +pci:v0000120E* + ID_VENDOR_FROM_DATABASE=Cyclades Corporation + +pci:v0000120Ed00000100* + ID_MODEL_FROM_DATABASE=Cyclom-Y below first megabyte + +pci:v0000120Ed00000101* + ID_MODEL_FROM_DATABASE=Cyclom-Y above first megabyte + +pci:v0000120Ed00000102* + ID_MODEL_FROM_DATABASE=Cyclom-4Y below first megabyte + +pci:v0000120Ed00000103* + ID_MODEL_FROM_DATABASE=Cyclom-4Y above first megabyte + +pci:v0000120Ed00000104* + ID_MODEL_FROM_DATABASE=Cyclom-8Y below first megabyte + +pci:v0000120Ed00000105* + ID_MODEL_FROM_DATABASE=Cyclom-8Y above first megabyte + +pci:v0000120Ed00000200* + ID_MODEL_FROM_DATABASE=Cyclades-Z below first megabyte + +pci:v0000120Ed00000201* + ID_MODEL_FROM_DATABASE=Cyclades-Z above first megabyte + +pci:v0000120Ed00000300* + ID_MODEL_FROM_DATABASE=PC300/RSV or /X21 (2 ports) + +pci:v0000120Ed00000301* + ID_MODEL_FROM_DATABASE=PC300/RSV or /X21 (1 port) + +pci:v0000120Ed00000310* + ID_MODEL_FROM_DATABASE=PC300/TE (2 ports) + +pci:v0000120Ed00000311* + ID_MODEL_FROM_DATABASE=PC300/TE (1 port) + +pci:v0000120Ed00000320* + ID_MODEL_FROM_DATABASE=PC300/TE-M (2 ports) + +pci:v0000120Ed00000321* + ID_MODEL_FROM_DATABASE=PC300/TE-M (1 port) + +pci:v0000120Ed00000400* + ID_MODEL_FROM_DATABASE=PC400 + +pci:v0000120F* + ID_VENDOR_FROM_DATABASE=Essential Communications + +pci:v0000120Fd00000001* + ID_MODEL_FROM_DATABASE=Roadrunner serial HIPPI + +pci:v00001210* + ID_VENDOR_FROM_DATABASE=Hyperparallel Technologies + +pci:v00001211* + ID_VENDOR_FROM_DATABASE=Braintech Inc + +pci:v00001213* + ID_VENDOR_FROM_DATABASE=Applied Intelligent Systems, Inc. + +pci:v00001214* + ID_VENDOR_FROM_DATABASE=Performance Technologies, Inc. + +pci:v00001215* + ID_VENDOR_FROM_DATABASE=Interware Co., Ltd + +pci:v00001216* + ID_VENDOR_FROM_DATABASE=Purup Prepress A/S + +pci:v00001217* + ID_VENDOR_FROM_DATABASE=O2 Micro, Inc. + +pci:v00001217d000000F7* + ID_MODEL_FROM_DATABASE=Firewire (IEEE 1394) + +pci:v00001217d000000F7sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=Firewire (IEEE 1394) (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00001217d000000F7sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=Firewire (IEEE 1394) (Satellite P305D-S8995E) + +pci:v00001217d000010F7* + ID_MODEL_FROM_DATABASE=1394 OHCI Compliant Host Controller + +pci:v00001217d000011F7* + ID_MODEL_FROM_DATABASE=OZ600 1394a-2000 Controller + +pci:v00001217d000011F7sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=OZ600 1394a-2000 Controller (Precision M4600) + +pci:v00001217d000013F7* + ID_MODEL_FROM_DATABASE=1394 OHCI Compliant Host Controller + +pci:v00001217d00006729* + ID_MODEL_FROM_DATABASE=OZ6729 + +pci:v00001217d0000673A* + ID_MODEL_FROM_DATABASE=OZ6730 + +pci:v00001217d00006832* + ID_MODEL_FROM_DATABASE=OZ6832/6833 CardBus Controller + +pci:v00001217d00006836* + ID_MODEL_FROM_DATABASE=OZ6836/6860 CardBus Controller + +pci:v00001217d00006872* + ID_MODEL_FROM_DATABASE=OZ6812 CardBus Controller + +pci:v00001217d00006925* + ID_MODEL_FROM_DATABASE=OZ6922 CardBus Controller + +pci:v00001217d00006933* + ID_MODEL_FROM_DATABASE=OZ6933/711E1 CardBus/SmartCardBus Controller + +pci:v00001217d00006933sv00001025sd00001016* + ID_MODEL_FROM_DATABASE=OZ6933/711E1 CardBus/SmartCardBus Controller (Travelmate 612 TX) + +pci:v00001217d00006972* + ID_MODEL_FROM_DATABASE=OZ601/6912/711E0 CardBus/SmartCardBus Controller + +pci:v00001217d00006972sv00001014sd0000020C* + ID_MODEL_FROM_DATABASE=OZ601/6912/711E0 CardBus/SmartCardBus Controller (ThinkPad R30) + +pci:v00001217d00006972sv00001028sd00000152* + ID_MODEL_FROM_DATABASE=OZ601/6912/711E0 CardBus/SmartCardBus Controller (Latitude D500) + +pci:v00001217d00006972sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=OZ601/6912/711E0 CardBus/SmartCardBus Controller (Magnia Z310) + +pci:v00001217d00007110* + ID_MODEL_FROM_DATABASE=OZ711Mx 4-in-1 MemoryCardBus Accelerator + +pci:v00001217d00007110sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=OZ711Mx 4-in-1 MemoryCardBus Accelerator (NC8000 laptop) + +pci:v00001217d00007110sv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=OZ711Mx 4-in-1 MemoryCardBus Accelerator (NC6000 laptop) + +pci:v00001217d00007110sv00001734sd0000106C* + ID_MODEL_FROM_DATABASE=OZ711Mx 4-in-1 MemoryCardBus Accelerator (Amilo A1645) + +pci:v00001217d00007112* + ID_MODEL_FROM_DATABASE=OZ711EC1/M1 SmartCardBus/MemoryCardBus Controller + +pci:v00001217d00007113* + ID_MODEL_FROM_DATABASE=OZ711EC1 SmartCardBus Controller + +pci:v00001217d00007113sv00001025sd00000035* + ID_MODEL_FROM_DATABASE=OZ711EC1 SmartCardBus Controller (TravelMate 660) + +pci:v00001217d00007114* + ID_MODEL_FROM_DATABASE=OZ711M1/MC1 4-in-1 MemoryCardBus Controller + +pci:v00001217d00007120* + ID_MODEL_FROM_DATABASE=Integrated MMC/SD Controller + +pci:v00001217d00007120sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=Integrated MMC/SD Controller (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00001217d00007120sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=Integrated MMC/SD Controller (Satellite P305D-S8995E) + +pci:v00001217d00007130* + ID_MODEL_FROM_DATABASE=Integrated MS/xD Controller + +pci:v00001217d00007130sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=Integrated MS/xD Controller (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00001217d00007130sv00001179sd0000FF50* + ID_MODEL_FROM_DATABASE=Integrated MS/xD Controller (Satellite P305D-S8995E) + +pci:v00001217d00007134* + ID_MODEL_FROM_DATABASE=OZ711MP1/MS1 MemoryCardBus Controller + +pci:v00001217d00007135* + ID_MODEL_FROM_DATABASE=Cardbus bridge + +pci:v00001217d00007136* + ID_MODEL_FROM_DATABASE=OZ711SP1 Memory CardBus Controller + +pci:v00001217d000071E2* + ID_MODEL_FROM_DATABASE=OZ711E2 SmartCardBus Controller + +pci:v00001217d00007212* + ID_MODEL_FROM_DATABASE=OZ711M2 4-in-1 MemoryCardBus Controller + +pci:v00001217d00007213* + ID_MODEL_FROM_DATABASE=OZ6933E CardBus Controller + +pci:v00001217d00007223* + ID_MODEL_FROM_DATABASE=OZ711M3/MC3 4-in-1 MemoryCardBus Controller + +pci:v00001217d00007223sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=OZ711M3/MC3 4-in-1 MemoryCardBus Controller (NC8000 laptop) + +pci:v00001217d00007223sv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=OZ711M3/MC3 4-in-1 MemoryCardBus Controller (NC6000 laptop) + +pci:v00001217d00007223sv000010CFsd000011C4* + ID_MODEL_FROM_DATABASE=OZ711M3/MC3 4-in-1 MemoryCardBus Controller (Lifebook P5020D Laptop) + +pci:v00001217d00007233* + ID_MODEL_FROM_DATABASE=OZ711MP3/MS3 4-in-1 MemoryCardBus Controller + +pci:v00001217d00008120* + ID_MODEL_FROM_DATABASE=Integrated MMC/SD Controller + +pci:v00001217d00008130* + ID_MODEL_FROM_DATABASE=Integrated MS/MSPRO/xD Controller + +pci:v00001217d00008220* + ID_MODEL_FROM_DATABASE=OZ600FJ1/OZ900FJ1 SD/MMC Card Reader Controller + +pci:v00001217d00008221* + ID_MODEL_FROM_DATABASE=OZ600FJ0/OZ900FJ0/OZ600FJS SD/MMC Card Reader Controller + +pci:v00001217d00008320* + ID_MODEL_FROM_DATABASE=OZ600RJ1/OZ900RJ1 SD/MMC Card Reader Controller + +pci:v00001217d00008320sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=OZ600RJ1/OZ900RJ1 SD/MMC Card Reader Controller (Precision M4600) + +pci:v00001217d00008321* + ID_MODEL_FROM_DATABASE=OZ600RJ0/OZ900RJ0/OZ600RJS SD/MMC Card Reader Controller + +pci:v00001217d00008330* + ID_MODEL_FROM_DATABASE=OZ600 MS/xD Controller + +pci:v00001217d00008330sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=OZ600 MS/xD Controller (Precision M4600) + +pci:v00001217d00008331* + ID_MODEL_FROM_DATABASE=O2 Flash Memory Card + +pci:v00001217d00008520* + ID_MODEL_FROM_DATABASE=SD/MMC Card Reader Controller + +pci:v00001217d00008621* + ID_MODEL_FROM_DATABASE=SD/MMC Card Reader Controller + +pci:v00001218* + ID_VENDOR_FROM_DATABASE=Hybricon Corp. + +pci:v00001219* + ID_VENDOR_FROM_DATABASE=First Virtual Corporation + +pci:v0000121A* + ID_VENDOR_FROM_DATABASE=3Dfx Interactive, Inc. + +pci:v0000121Ad00000001* + ID_MODEL_FROM_DATABASE=Voodoo + +pci:v0000121Ad00000002* + ID_MODEL_FROM_DATABASE=Voodoo 2 + +pci:v0000121Ad00000003* + ID_MODEL_FROM_DATABASE=Voodoo Banshee + +pci:v0000121Ad00000003sv00001092sd00000003* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion) + +pci:v0000121Ad00000003sv00001092sd00004000* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion) + +pci:v0000121Ad00000003sv00001092sd00004002* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion) + +pci:v0000121Ad00000003sv00001092sd00004801* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion AGP) + +pci:v0000121Ad00000003sv00001092sd00004803* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion AGP) + +pci:v0000121Ad00000003sv00001092sd00008030* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion) + +pci:v0000121Ad00000003sv00001092sd00008035* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Monster Fusion AGP) + +pci:v0000121Ad00000003sv000010B0sd00000001* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Dragon 4000) + +pci:v0000121Ad00000003sv00001102sd00001017* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (3D Blaster Banshee PCI (CT6760)) + +pci:v0000121Ad00000003sv00001102sd00001018* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (3D Blaster Banshee VE) + +pci:v0000121Ad00000003sv0000121Asd00000001* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (AGP) + +pci:v0000121Ad00000003sv0000121Asd00000003* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (AGP SGRAM) + +pci:v0000121Ad00000003sv0000121Asd00000004* + ID_MODEL_FROM_DATABASE=Voodoo Banshee + +pci:v0000121Ad00000003sv0000139Csd00000016* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Raven) + +pci:v0000121Ad00000003sv0000139Csd00000017* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Raven) + +pci:v0000121Ad00000003sv000014AFsd00000002* + ID_MODEL_FROM_DATABASE=Voodoo Banshee (Maxi Gamer Phoenix) + +pci:v0000121Ad00000004* + ID_MODEL_FROM_DATABASE=Voodoo Banshee [Velocity 100] + +pci:v0000121Ad00000005* + ID_MODEL_FROM_DATABASE=Voodoo 3 + +pci:v0000121Ad00000005sv0000121Asd00000004* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd00000030* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd00000031* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd00000034* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd00000036* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 2000 PCI) + +pci:v0000121Ad00000005sv0000121Asd00000037* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd00000038* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd0000003A* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd00000044* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3) + +pci:v0000121Ad00000005sv0000121Asd0000004B* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Velocity 100) + +pci:v0000121Ad00000005sv0000121Asd0000004C* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Velocity 200) + +pci:v0000121Ad00000005sv0000121Asd0000004D* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd0000004E* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd00000051* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd00000052* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 AGP) + +pci:v0000121Ad00000005sv0000121Asd00000057* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 3000 PCI) + +pci:v0000121Ad00000005sv0000121Asd00000060* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 3500 TV (NTSC)) + +pci:v0000121Ad00000005sv0000121Asd00000061* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 3500 TV (PAL)) + +pci:v0000121Ad00000005sv0000121Asd00000062* + ID_MODEL_FROM_DATABASE=Voodoo 3 (Voodoo3 3500 TV (SECAM)) + +pci:v0000121Ad00000009* + ID_MODEL_FROM_DATABASE=Voodoo 4 / Voodoo 5 + +pci:v0000121Ad00000009sv0000121Asd00000003* + ID_MODEL_FROM_DATABASE=Voodoo 4 / Voodoo 5 (Voodoo5 PCI 5500) + +pci:v0000121Ad00000009sv0000121Asd00000009* + ID_MODEL_FROM_DATABASE=Voodoo 4 / Voodoo 5 (Voodoo5 AGP 5500/6000) + +pci:v0000121Ad00000057* + ID_MODEL_FROM_DATABASE=Voodoo 3/3000 [Avenger] + +pci:v0000121B* + ID_VENDOR_FROM_DATABASE=Advanced Telecommunications Modules + +pci:v0000121C* + ID_VENDOR_FROM_DATABASE=Nippon Texaco., Ltd + +pci:v0000121D* + ID_VENDOR_FROM_DATABASE=LiPPERT ADLINK Technology GmbH + +pci:v0000121E* + ID_VENDOR_FROM_DATABASE=CSPI + +pci:v0000121Ed00000201* + ID_MODEL_FROM_DATABASE=Myrinet 2000 Scalable Cluster Interconnect + +pci:v0000121F* + ID_VENDOR_FROM_DATABASE=Arcus Technology, Inc. + +pci:v00001220* + ID_VENDOR_FROM_DATABASE=Ariel Corporation + +pci:v00001220d00001220* + ID_MODEL_FROM_DATABASE=AMCC 5933 TMS320C80 DSP/Imaging board + +pci:v00001221* + ID_VENDOR_FROM_DATABASE=Contec Co., Ltd + +pci:v00001221d00009172* + ID_MODEL_FROM_DATABASE=PO-64L(PCI)H [Isolated Digital Output Board for PCI] + +pci:v00001221d000091A2* + ID_MODEL_FROM_DATABASE=PO-32L(PCI)H [Isolated Digital Output Board for PCI] + +pci:v00001221d000091C3* + ID_MODEL_FROM_DATABASE=DA16-16(LPCI)L [Un-insulated highly precise analog output board for Low Profile PCI] + +pci:v00001221d0000B152* + ID_MODEL_FROM_DATABASE=DIO-96D2-LPCI + +pci:v00001221d0000C103* + ID_MODEL_FROM_DATABASE=ADA16-32/2(PCI)F [High-Speed Analog I/O Board for PCI] + +pci:v00001222* + ID_VENDOR_FROM_DATABASE=Ancor Communications, Inc. + +pci:v00001223* + ID_VENDOR_FROM_DATABASE=Artesyn Communication Products + +pci:v00001223d00000003* + ID_MODEL_FROM_DATABASE=PM/Link + +pci:v00001223d00000004* + ID_MODEL_FROM_DATABASE=PM/T1 + +pci:v00001223d00000005* + ID_MODEL_FROM_DATABASE=PM/E1 + +pci:v00001223d00000008* + ID_MODEL_FROM_DATABASE=PM/SLS + +pci:v00001223d00000009* + ID_MODEL_FROM_DATABASE=BajaSpan Resource Target + +pci:v00001223d0000000A* + ID_MODEL_FROM_DATABASE=BajaSpan Section 0 + +pci:v00001223d0000000B* + ID_MODEL_FROM_DATABASE=BajaSpan Section 1 + +pci:v00001223d0000000C* + ID_MODEL_FROM_DATABASE=BajaSpan Section 2 + +pci:v00001223d0000000D* + ID_MODEL_FROM_DATABASE=BajaSpan Section 3 + +pci:v00001223d0000000E* + ID_MODEL_FROM_DATABASE=PM/PPC + +pci:v00001224* + ID_VENDOR_FROM_DATABASE=Interactive Images + +pci:v00001225* + ID_VENDOR_FROM_DATABASE=Power I/O, Inc. + +pci:v00001227* + ID_VENDOR_FROM_DATABASE=EIZO Rugged Solutions + +pci:v00001227d00000006* + ID_MODEL_FROM_DATABASE=Raptor GFX 8P + +pci:v00001227d00000023* + ID_MODEL_FROM_DATABASE=Raptor GFX [1100T] + +pci:v00001227d00000045* + ID_MODEL_FROM_DATABASE=Raptor 4000-L [Linux version] + +pci:v00001227d0000004A* + ID_MODEL_FROM_DATABASE=Raptor 4000-LR-L [Linux version] + +pci:v00001228* + ID_VENDOR_FROM_DATABASE=Norsk Elektro Optikk A/S + +pci:v00001229* + ID_VENDOR_FROM_DATABASE=Data Kinesis Inc. + +pci:v0000122A* + ID_VENDOR_FROM_DATABASE=Integrated Telecom + +pci:v0000122B* + ID_VENDOR_FROM_DATABASE=LG Industrial Systems Co., Ltd + +pci:v0000122C* + ID_VENDOR_FROM_DATABASE=Sican GmbH + +pci:v0000122D* + ID_VENDOR_FROM_DATABASE=Aztech System Ltd + +pci:v0000122Dd00001206* + ID_MODEL_FROM_DATABASE=368DSP + +pci:v0000122Dd00001400* + ID_MODEL_FROM_DATABASE=Trident PCI288-Q3DII (NX) + +pci:v0000122Dd000050DC* + ID_MODEL_FROM_DATABASE=3328 Audio + +pci:v0000122Dd000050DCsv0000122Dsd00000001* + ID_MODEL_FROM_DATABASE=3328 Audio + +pci:v0000122Dd000080DA* + ID_MODEL_FROM_DATABASE=3328 Audio + +pci:v0000122Dd000080DAsv0000122Dsd00000001* + ID_MODEL_FROM_DATABASE=3328 Audio + +pci:v0000122E* + ID_VENDOR_FROM_DATABASE=Xyratex + +pci:v0000122Ed00007722* + ID_MODEL_FROM_DATABASE=Napatech XL1 + +pci:v0000122Ed00007724* + ID_MODEL_FROM_DATABASE=Napatech XL2/XA + +pci:v0000122Ed00007729* + ID_MODEL_FROM_DATABASE=Napatech XD + +pci:v0000122F* + ID_VENDOR_FROM_DATABASE=Andrew Corporation + +pci:v00001230* + ID_VENDOR_FROM_DATABASE=Fishcamp Engineering + +pci:v00001231* + ID_VENDOR_FROM_DATABASE=Woodward McCoach, Inc. + +pci:v00001231d000004E1* + ID_MODEL_FROM_DATABASE=Desktop PCI Telephony 4 + +pci:v00001231d000005E1* + ID_MODEL_FROM_DATABASE=Desktop PCI Telephony 5/6 + +pci:v00001231d00000D00* + ID_MODEL_FROM_DATABASE=LightParser + +pci:v00001231d00000D02* + ID_MODEL_FROM_DATABASE=LightParser 2 + +pci:v00001231d00000D13* + ID_MODEL_FROM_DATABASE=Desktop PCI L1/L3 Telephony + +pci:v00001232* + ID_VENDOR_FROM_DATABASE=GPT Limited + +pci:v00001233* + ID_VENDOR_FROM_DATABASE=Bus-Tech, Inc. + +pci:v00001235* + ID_VENDOR_FROM_DATABASE=SMART Modular Technologies + +pci:v00001236* + ID_VENDOR_FROM_DATABASE=Sigma Designs Corporation + +pci:v00001236d00000000* + ID_MODEL_FROM_DATABASE=RealMagic64/GX + +pci:v00001236d00006401* + ID_MODEL_FROM_DATABASE=REALmagic 64/GX (SD 6425) + +pci:v00001237* + ID_VENDOR_FROM_DATABASE=Alta Technology Corporation + +pci:v00001238* + ID_VENDOR_FROM_DATABASE=Adtran + +pci:v00001239* + ID_VENDOR_FROM_DATABASE=3DO Company + +pci:v0000123A* + ID_VENDOR_FROM_DATABASE=Visicom Laboratories, Inc. + +pci:v0000123B* + ID_VENDOR_FROM_DATABASE=Seeq Technology, Inc. + +pci:v0000123C* + ID_VENDOR_FROM_DATABASE=Century Systems, Inc. + +pci:v0000123D* + ID_VENDOR_FROM_DATABASE=Engineering Design Team, Inc. + +pci:v0000123Dd00000000* + ID_MODEL_FROM_DATABASE=EasyConnect 8/32 + +pci:v0000123Dd00000002* + ID_MODEL_FROM_DATABASE=EasyConnect 8/64 + +pci:v0000123Dd00000003* + ID_MODEL_FROM_DATABASE=EasyIO + +pci:v0000123E* + ID_VENDOR_FROM_DATABASE=Simutech, Inc. + +pci:v0000123F* + ID_VENDOR_FROM_DATABASE=LSI Logic + +pci:v0000123Fd000000E4* + ID_MODEL_FROM_DATABASE=MPEG + +pci:v0000123Fd00008120* + ID_MODEL_FROM_DATABASE=DVxplore Codec + +pci:v0000123Fd00008120sv000010DEsd000001E1* + ID_MODEL_FROM_DATABASE=DVxplore Codec (NVTV PAL) + +pci:v0000123Fd00008120sv000010DEsd000001E2* + ID_MODEL_FROM_DATABASE=DVxplore Codec (NVTV NTSC) + +pci:v0000123Fd00008120sv000010DEsd000001E3* + ID_MODEL_FROM_DATABASE=DVxplore Codec (NVTV PAL) + +pci:v0000123Fd00008120sv000010DEsd00000248* + ID_MODEL_FROM_DATABASE=DVxplore Codec (NVTV NTSC) + +pci:v0000123Fd00008120sv000010DEsd00000249* + ID_MODEL_FROM_DATABASE=DVxplore Codec (NVTV PAL) + +pci:v0000123Fd00008120sv000011BDsd00000006* + ID_MODEL_FROM_DATABASE=DVxplore Codec (DV500 E4) + +pci:v0000123Fd00008120sv000011BDsd0000000A* + ID_MODEL_FROM_DATABASE=DVxplore Codec (DV500 E4) + +pci:v0000123Fd00008120sv000011BDsd0000000F* + ID_MODEL_FROM_DATABASE=DVxplore Codec (DV500 E4) + +pci:v0000123Fd00008120sv00001809sd00000016* + ID_MODEL_FROM_DATABASE=DVxplore Codec (Emuzed MAUI-III PCI PVR FM TV) + +pci:v0000123Fd00008888* + ID_MODEL_FROM_DATABASE=Cinemaster C 3.0 DVD Decoder + +pci:v0000123Fd00008888sv00001002sd00000001* + ID_MODEL_FROM_DATABASE=Cinemaster C 3.0 DVD Decoder + +pci:v0000123Fd00008888sv00001002sd00000002* + ID_MODEL_FROM_DATABASE=Cinemaster C 3.0 DVD Decoder + +pci:v0000123Fd00008888sv00001328sd00000001* + ID_MODEL_FROM_DATABASE=Cinemaster C 3.0 DVD Decoder + +pci:v00001240* + ID_VENDOR_FROM_DATABASE=Marathon Technologies Corp. + +pci:v00001241* + ID_VENDOR_FROM_DATABASE=DSC Communications + +pci:v00001242* + ID_VENDOR_FROM_DATABASE=JNI Corporation + +pci:v00001242d00001560* + ID_MODEL_FROM_DATABASE=JNIC-1560 PCI-X Fibre Channel Controller + +pci:v00001242d00001560sv00001242sd00006562* + ID_MODEL_FROM_DATABASE=JNIC-1560 PCI-X Fibre Channel Controller (FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter) + +pci:v00001242d00001560sv00001242sd0000656A* + ID_MODEL_FROM_DATABASE=JNIC-1560 PCI-X Fibre Channel Controller (FCX-6562 PCI-X Fibre Channel Adapter) + +pci:v00001242d00004643* + ID_MODEL_FROM_DATABASE=FCI-1063 Fibre Channel Adapter + +pci:v00001242d00006562* + ID_MODEL_FROM_DATABASE=FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter + +pci:v00001242d0000656A* + ID_MODEL_FROM_DATABASE=FCX-6562 PCI-X Fibre Channel Adapter + +pci:v00001243* + ID_VENDOR_FROM_DATABASE=Delphax + +pci:v00001244* + ID_VENDOR_FROM_DATABASE=AVM GmbH + +pci:v00001244d00000700* + ID_MODEL_FROM_DATABASE=B1 ISDN + +pci:v00001244d00000800* + ID_MODEL_FROM_DATABASE=C4 ISDN + +pci:v00001244d00000A00* + ID_MODEL_FROM_DATABASE=A1 ISDN [Fritz] + +pci:v00001244d00000A00sv00001244sd00000A00* + ID_MODEL_FROM_DATABASE=A1 ISDN [Fritz] (FRITZ!Card ISDN Controller) + +pci:v00001244d00000E00* + ID_MODEL_FROM_DATABASE=Fritz!Card PCI v2.0 ISDN + +pci:v00001244d00000E80* + ID_MODEL_FROM_DATABASE=Fritz!Card PCI v2.1 ISDN + +pci:v00001244d00000E80sv00001244sd00000E00* + ID_MODEL_FROM_DATABASE=Fritz!Card PCI v2.1 ISDN (PSB 3100F (AVM KAFKA) [Fritz!Card PCI v2.1]) + +pci:v00001244d00001100* + ID_MODEL_FROM_DATABASE=C2 ISDN + +pci:v00001244d00001200* + ID_MODEL_FROM_DATABASE=T1 ISDN + +pci:v00001244d00002700* + ID_MODEL_FROM_DATABASE=Fritz!Card DSL SL + +pci:v00001244d00002900* + ID_MODEL_FROM_DATABASE=Fritz!Card DSL v2.0 + +pci:v00001245* + ID_VENDOR_FROM_DATABASE=A.P.D., S.A. + +pci:v00001246* + ID_VENDOR_FROM_DATABASE=Dipix Technologies, Inc. + +pci:v00001247* + ID_VENDOR_FROM_DATABASE=Xylon Research, Inc. + +pci:v00001248* + ID_VENDOR_FROM_DATABASE=Central Data Corporation + +pci:v00001249* + ID_VENDOR_FROM_DATABASE=Samsung Electronics Co., Ltd. + +pci:v0000124A* + ID_VENDOR_FROM_DATABASE=AEG Electrocom GmbH + +pci:v0000124B* + ID_VENDOR_FROM_DATABASE=SBS/Greenspring Modular I/O + +pci:v0000124Bd00000040* + ID_MODEL_FROM_DATABASE=PCI-40A or cPCI-200 Quad IndustryPack carrier + +pci:v0000124Bd00000040sv0000124Bsd00009080* + ID_MODEL_FROM_DATABASE=PCI-40A or cPCI-200 Quad IndustryPack carrier (PCI9080 Bridge) + +pci:v0000124C* + ID_VENDOR_FROM_DATABASE=Solitron Technologies, Inc. + +pci:v0000124D* + ID_VENDOR_FROM_DATABASE=Stallion Technologies, Inc. + +pci:v0000124Dd00000000* + ID_MODEL_FROM_DATABASE=EasyConnection 8/32 + +pci:v0000124Dd00000002* + ID_MODEL_FROM_DATABASE=EasyConnection 8/64 + +pci:v0000124Dd00000003* + ID_MODEL_FROM_DATABASE=EasyIO + +pci:v0000124Dd00000004* + ID_MODEL_FROM_DATABASE=EasyConnection/RA + +pci:v0000124E* + ID_VENDOR_FROM_DATABASE=Cylink + +pci:v0000124F* + ID_VENDOR_FROM_DATABASE=Infortrend Technology, Inc. + +pci:v0000124Fd00000041* + ID_MODEL_FROM_DATABASE=IFT-2000 Series RAID Controller + +pci:v00001250* + ID_VENDOR_FROM_DATABASE=Hitachi Microcomputer System Ltd + +pci:v00001251* + ID_VENDOR_FROM_DATABASE=VLSI Solutions Oy + +pci:v00001253* + ID_VENDOR_FROM_DATABASE=Guzik Technical Enterprises + +pci:v00001254* + ID_VENDOR_FROM_DATABASE=Linear Systems Ltd. + +pci:v00001254d00000065* + ID_MODEL_FROM_DATABASE=DVB Master FD + +pci:v00001254d0000007C* + ID_MODEL_FROM_DATABASE=DVB Master Quad/o + +pci:v00001255* + ID_VENDOR_FROM_DATABASE=Optibase Ltd + +pci:v00001255d00001110* + ID_MODEL_FROM_DATABASE=MPEG Forge + +pci:v00001255d00001210* + ID_MODEL_FROM_DATABASE=MPEG Fusion + +pci:v00001255d00002110* + ID_MODEL_FROM_DATABASE=VideoPlex + +pci:v00001255d00002120* + ID_MODEL_FROM_DATABASE=VideoPlex CC + +pci:v00001255d00002130* + ID_MODEL_FROM_DATABASE=VideoQuest + +pci:v00001256* + ID_VENDOR_FROM_DATABASE=Perceptive Solutions, Inc. + +pci:v00001256d00004201* + ID_MODEL_FROM_DATABASE=PCI-2220I + +pci:v00001256d00004401* + ID_MODEL_FROM_DATABASE=PCI-2240I + +pci:v00001256d00005201* + ID_MODEL_FROM_DATABASE=PCI-2000 + +pci:v00001257* + ID_VENDOR_FROM_DATABASE=Vertex Networks, Inc. + +pci:v00001258* + ID_VENDOR_FROM_DATABASE=Gilbarco, Inc. + +pci:v00001259* + ID_VENDOR_FROM_DATABASE=Allied Telesis + +pci:v00001259d00002560* + ID_MODEL_FROM_DATABASE=AT-2560 Fast Ethernet Adapter (i82557B) + +pci:v00001259d00002801* + ID_MODEL_FROM_DATABASE=AT-2801FX (RTL-8139) + +pci:v00001259d0000A117* + ID_MODEL_FROM_DATABASE=RTL81xx Fast Ethernet + +pci:v00001259d0000A11E* + ID_MODEL_FROM_DATABASE=RTL81xx Fast Ethernet + +pci:v00001259d0000A120* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v0000125A* + ID_VENDOR_FROM_DATABASE=ABB Power Systems + +pci:v0000125B* + ID_VENDOR_FROM_DATABASE=Asix Electronics Corporation + +pci:v0000125Bd00001400* + ID_MODEL_FROM_DATABASE=AX88141 Fast Ethernet Controller + +pci:v0000125Bd00001400sv00001186sd00001100* + ID_MODEL_FROM_DATABASE=AX88141 Fast Ethernet Controller (AX8814X Based PCI Fast Ethernet Adapter) + +pci:v0000125C* + ID_VENDOR_FROM_DATABASE=Aurora Technologies, Inc. + +pci:v0000125Cd00000101* + ID_MODEL_FROM_DATABASE=Saturn 4520P + +pci:v0000125Cd00000640* + ID_MODEL_FROM_DATABASE=Aries 16000P + +pci:v0000125D* + ID_VENDOR_FROM_DATABASE=ESS Technology + +pci:v0000125Dd00000000* + ID_MODEL_FROM_DATABASE=ES336H Fax Modem (Early Model) + +pci:v0000125Dd00001948* + ID_MODEL_FROM_DATABASE=ES1948 Maestro-1 + +pci:v0000125Dd00001968* + ID_MODEL_FROM_DATABASE=ES1968 Maestro 2 + +pci:v0000125Dd00001968sv00001028sd00000085* + ID_MODEL_FROM_DATABASE=ES1968 Maestro 2 (ES1968 Maestro-2 PCI) + +pci:v0000125Dd00001968sv00001033sd00008051* + ID_MODEL_FROM_DATABASE=ES1968 Maestro 2 (ES1968 Maestro-2 Audiodrive) + +pci:v0000125Dd00001969* + ID_MODEL_FROM_DATABASE=ES1938/ES1946/ES1969 Solo-1 Audiodrive + +pci:v0000125Dd00001969sv00001014sd00000166* + ID_MODEL_FROM_DATABASE=ES1938/ES1946/ES1969 Solo-1 Audiodrive (ES1969 SOLO-1 AudioDrive on IBM Aptiva Mainboard) + +pci:v0000125Dd00001969sv0000125Dsd00008888* + ID_MODEL_FROM_DATABASE=ES1938/ES1946/ES1969 Solo-1 Audiodrive (Solo-1 Audio Adapter) + +pci:v0000125Dd00001969sv0000125Dsd00008898* + ID_MODEL_FROM_DATABASE=ES1938/ES1946/ES1969 Solo-1 Audiodrive (ES1938S TTSOLO1-SL [TerraTec 128i PCI]) + +pci:v0000125Dd00001969sv0000153Bsd0000111B* + ID_MODEL_FROM_DATABASE=ES1938/ES1946/ES1969 Solo-1 Audiodrive (Terratec 128i PCI) + +pci:v0000125Dd00001978* + ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E + +pci:v0000125Dd00001978sv00000E11sd0000B112* + ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E (Armada M700/E500) + +pci:v0000125Dd00001978sv00001033sd0000803C* + ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E (ES1978 Maestro-2E Audiodrive) + +pci:v0000125Dd00001978sv00001033sd00008058* + ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E (ES1978 Maestro-2E Audiodrive) + +pci:v0000125Dd00001978sv00001092sd00004000* + ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E (Monster Sound MX400) + +pci:v0000125Dd00001978sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=ES1978 Maestro 2E (ES1978 Maestro-2E Audiodrive) + +pci:v0000125Dd00001988* + ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 + +pci:v0000125Dd00001988sv00000E11sd00000098* + ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (Evo N600c) + +pci:v0000125Dd00001988sv00001092sd00004100* + ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (Sonic Impact S100) + +pci:v0000125Dd00001988sv0000125Dsd00000431* + ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (Allegro AudioDrive) + +pci:v0000125Dd00001988sv0000125Dsd00001988* + ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (ESS Allegro-1 Audiodrive) + +pci:v0000125Dd00001988sv0000125Dsd00001998* + ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (Allegro AudioDrive) + +pci:v0000125Dd00001988sv0000125Dsd00001999* + ID_MODEL_FROM_DATABASE=ES1988 Allegro-1 (Allegro-1 AudioDrive) + +pci:v0000125Dd00001989* + ID_MODEL_FROM_DATABASE=ESS Modem + +pci:v0000125Dd00001989sv0000125Dsd00001989* + ID_MODEL_FROM_DATABASE=ESS Modem + +pci:v0000125Dd00001998* + ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Audio Accelerator + +pci:v0000125Dd00001998sv00001028sd000000B1* + ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Audio Accelerator (Latitude C600) + +pci:v0000125Dd00001998sv00001028sd000000E5* + ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Audio Accelerator (Latitude C810) + +pci:v0000125Dd00001998sv00001028sd000000E6* + ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Audio Accelerator (ES1983S Maestro-3i (Dell Inspiron 8100)) + +pci:v0000125Dd00001999* + ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Modem Accelerator + +pci:v0000125Dd0000199A* + ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Audio Accelerator + +pci:v0000125Dd0000199B* + ID_MODEL_FROM_DATABASE=ES1983S Maestro-3i PCI Modem Accelerator + +pci:v0000125Dd00002808* + ID_MODEL_FROM_DATABASE=ES336H Fax Modem (Later Model) + +pci:v0000125Dd00002838* + ID_MODEL_FROM_DATABASE=ES2838/2839 SuperLink Modem + +pci:v0000125Dd00002898* + ID_MODEL_FROM_DATABASE=ES2898 Modem + +pci:v0000125Dd00002898sv0000125Dsd00000424* + ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56-PI Data Fax Modem) + +pci:v0000125Dd00002898sv0000125Dsd00000425* + ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56T-PI Data Fax Modem) + +pci:v0000125Dd00002898sv0000125Dsd00000426* + ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56V-PI Data Fax Modem) + +pci:v0000125Dd00002898sv0000125Dsd00000427* + ID_MODEL_FROM_DATABASE=ES2898 Modem (VW-PI Data Fax Modem) + +pci:v0000125Dd00002898sv0000125Dsd00000428* + ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56ST-PI Data Fax Modem) + +pci:v0000125Dd00002898sv0000125Dsd00000429* + ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56SV-PI Data Fax Modem) + +pci:v0000125Dd00002898sv0000147Asd0000C001* + ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56-PI Data Fax Modem) + +pci:v0000125Dd00002898sv0000148Dsd00001030* + ID_MODEL_FROM_DATABASE=ES2898 Modem (HCF WV-PI56 [ESS ES56-PI Data Fax Modem]) + +pci:v0000125Dd00002898sv000014FEsd00000428* + ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56-PI Data Fax Modem) + +pci:v0000125Dd00002898sv000014FEsd00000429* + ID_MODEL_FROM_DATABASE=ES2898 Modem (ES56-PI Data Fax Modem) + +pci:v0000125E* + ID_VENDOR_FROM_DATABASE=Specialvideo Engineering SRL + +pci:v0000125F* + ID_VENDOR_FROM_DATABASE=Concurrent Technologies, Inc. + +pci:v0000125Fd00002071* + ID_MODEL_FROM_DATABASE=CC PMC/232 + +pci:v0000125Fd00002084* + ID_MODEL_FROM_DATABASE=CC PMC/23P + +pci:v0000125Fd00002091* + ID_MODEL_FROM_DATABASE=CC PMC/422 + +pci:v00001260* + ID_VENDOR_FROM_DATABASE=Intersil Corporation + +pci:v00001260d00003872* + ID_MODEL_FROM_DATABASE=ISL3872 [Prism 3] + +pci:v00001260d00003872sv00001468sd00000202* + ID_MODEL_FROM_DATABASE=ISL3872 [Prism 3] (LAN-Express IEEE 802.11b Wireless LAN) + +pci:v00001260d00003873* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] + +pci:v00001260d00003873sv000010CFsd00001169* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (MBH7WM01-8734 802.11b Wireless Mini PCI Card [ISL3874]) + +pci:v00001260d00003873sv00001186sd00003501* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (DWL-520 Wireless PCI Adapter (rev A or B) [ISL3874]) + +pci:v00001260d00003873sv00001186sd00003700* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (DWL-520 Wireless PCI Adapter (rev E1) [ISL3872]) + +pci:v00001260d00003873sv00001385sd00004105* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (MA311 802.11b wireless adapter [ISL3874]) + +pci:v00001260d00003873sv00001668sd00000414* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (HWP01170-01 802.11b PCI Wireless Adapter) + +pci:v00001260d00003873sv000016A5sd00001601* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (AIR.mate PC-400 PCI Wireless LAN Adapter) + +pci:v00001260d00003873sv00001737sd00003874* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (WMP11 v1 802.11b Wireless-B PCI Adapter [ISL3874]) + +pci:v00001260d00003873sv00004033sd00007033* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (PCW200 802.11b Wireless PCI Adapter [ISL3874]) + +pci:v00001260d00003873sv00008086sd00002510* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (M3AWEB Wireless 802.11b MiniPCI Adapter) + +pci:v00001260d00003873sv00008086sd00002513* + ID_MODEL_FROM_DATABASE=ISL3874 [Prism 2.5]/ISL3872 [Prism 3] (Wireless 802.11b MiniPCI Adapter) + +pci:v00001260d00003877* + ID_MODEL_FROM_DATABASE=ISL3877 [Prism Indigo] + +pci:v00001260d00003886* + ID_MODEL_FROM_DATABASE=ISL3886 [Prism Javelin/Prism Xbow] + +pci:v00001260d00003886sv000017CFsd00000037* + ID_MODEL_FROM_DATABASE=ISL3886 [Prism Javelin/Prism Xbow] (XG-901 and clones Wireless Adapter) + +pci:v00001260d00003890* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] + +pci:v00001260d00003890sv000010B8sd00002802* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (SMC2802W V1 Wireless PCI Adapter [ISL3890]) + +pci:v00001260d00003890sv000010B8sd00002835* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (SMC2835W Wireless Cardbus Adapter) + +pci:v00001260d00003890sv000010B8sd0000A835* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (SMC2835W V2 Wireless Cardbus Adapter) + +pci:v00001260d00003890sv00001113sd00004203* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (WN4201B) + +pci:v00001260d00003890sv00001113sd00008201* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (T-Com T-Sinus 154pcicard Wireless PCI Adapter) + +pci:v00001260d00003890sv00001113sd0000B301* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (T-Sinus 154card Cardbus) + +pci:v00001260d00003890sv00001113sd0000EE03* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (SMC2802W V2 Wireless PCI Adapter [ISL3886]) + +pci:v00001260d00003890sv00001113sd0000EE08* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (SMC2835W V3 EU Wireless Cardbus Adapter) + +pci:v00001260d00003890sv00001186sd00003202* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (DWL-G650 A1 Wireless Adapter) + +pci:v00001260d00003890sv00001259sd0000C104* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (CG-WLCB54GT Wireless Adapter) + +pci:v00001260d00003890sv00001260sd00000000* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (WG511 v1 54 Mbps Wireless PC Card) + +pci:v00001260d00003890sv00001385sd00004800* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (WG511 v2/v3 54 Mbps Wireless PC Card) + +pci:v00001260d00003890sv000016A5sd00001605* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (ALLNET ALL0271 Wireless PCI Adapter) + +pci:v00001260d00003890sv000017CFsd00000014* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (XG-600 and clones Wireless Adapter) + +pci:v00001260d00003890sv000017CFsd00000020* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (XG-900 and clones Wireless Adapter) + +pci:v00001260d00003890sv0000187Esd00003403* + ID_MODEL_FROM_DATABASE=ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] (G-110 802.11g Wireless Cardbus Adapter) + +pci:v00001260d00008130* + ID_MODEL_FROM_DATABASE=HMP8130 NTSC/PAL Video Decoder + +pci:v00001260d00008131* + ID_MODEL_FROM_DATABASE=HMP8131 NTSC/PAL Video Decoder + +pci:v00001260d0000FFFF* + ID_MODEL_FROM_DATABASE=ISL3886IK + +pci:v00001260d0000FFFFsv00001260sd00000000* + ID_MODEL_FROM_DATABASE=ISL3886IK (Senao 3054MP+ (J) mini-PCI WLAN 802.11g adapter) + +pci:v00001261* + ID_VENDOR_FROM_DATABASE=Matsushita-Kotobuki Electronics Industries, Ltd. + +pci:v00001262* + ID_VENDOR_FROM_DATABASE=ES Computer Company, Ltd. + +pci:v00001263* + ID_VENDOR_FROM_DATABASE=Sonic Solutions + +pci:v00001264* + ID_VENDOR_FROM_DATABASE=Aval Nagasaki Corporation + +pci:v00001265* + ID_VENDOR_FROM_DATABASE=Casio Computer Co., Ltd. + +pci:v00001266* + ID_VENDOR_FROM_DATABASE=Microdyne Corporation + +pci:v00001266d00000001* + ID_MODEL_FROM_DATABASE=NE10/100 Adapter (i82557B) + +pci:v00001266d00001910* + ID_MODEL_FROM_DATABASE=NE2000Plus (RT8029) Ethernet Adapter + +pci:v00001266d00001910sv00001266sd00001910* + ID_MODEL_FROM_DATABASE=NE2000Plus (RT8029) Ethernet Adapter (NE2000Plus Ethernet Adapter) + +pci:v00001267* + ID_VENDOR_FROM_DATABASE=S. A. Telecommunications + +pci:v00001267d00005352* + ID_MODEL_FROM_DATABASE=PCR2101 + +pci:v00001267d00005A4B* + ID_MODEL_FROM_DATABASE=Telsat Turbo + +pci:v00001268* + ID_VENDOR_FROM_DATABASE=Tektronix + +pci:v00001269* + ID_VENDOR_FROM_DATABASE=Thomson-CSF/TTM + +pci:v0000126A* + ID_VENDOR_FROM_DATABASE=Lexmark International, Inc. + +pci:v0000126B* + ID_VENDOR_FROM_DATABASE=Adax, Inc. + +pci:v0000126C* + ID_VENDOR_FROM_DATABASE=Northern Telecom + +pci:v0000126Cd00001211* + ID_MODEL_FROM_DATABASE=10/100BaseTX [RTL81xx] + +pci:v0000126Cd0000126C* + ID_MODEL_FROM_DATABASE=802.11b Wireless Ethernet Adapter + +pci:v0000126D* + ID_VENDOR_FROM_DATABASE=Splash Technology, Inc. + +pci:v0000126E* + ID_VENDOR_FROM_DATABASE=Sumitomo Metal Industries, Ltd. + +pci:v0000126F* + ID_VENDOR_FROM_DATABASE=Silicon Motion, Inc. + +pci:v0000126Fd00000501* + ID_MODEL_FROM_DATABASE=SM501 VoyagerGX Rev. AA + +pci:v0000126Fd00000510* + ID_MODEL_FROM_DATABASE=SM501 VoyagerGX Rev. B + +pci:v0000126Fd00000710* + ID_MODEL_FROM_DATABASE=SM710 LynxEM + +pci:v0000126Fd00000712* + ID_MODEL_FROM_DATABASE=SM712 LynxEM+ + +pci:v0000126Fd00000718* + ID_MODEL_FROM_DATABASE=SM718 LynxSE+ + +pci:v0000126Fd00000720* + ID_MODEL_FROM_DATABASE=SM720 Lynx3DM + +pci:v0000126Fd00000730* + ID_MODEL_FROM_DATABASE=SM731 Cougar3DR + +pci:v0000126Fd00000750* + ID_MODEL_FROM_DATABASE=SM750 + +pci:v0000126Fd00000810* + ID_MODEL_FROM_DATABASE=SM810 LynxE + +pci:v0000126Fd00000811* + ID_MODEL_FROM_DATABASE=SM811 LynxE + +pci:v0000126Fd00000820* + ID_MODEL_FROM_DATABASE=SM820 Lynx3D + +pci:v0000126Fd00000910* + ID_MODEL_FROM_DATABASE=SM910 + +pci:v00001270* + ID_VENDOR_FROM_DATABASE=Olympus Optical Co., Ltd. + +pci:v00001271* + ID_VENDOR_FROM_DATABASE=GW Instruments + +pci:v00001272* + ID_VENDOR_FROM_DATABASE=Telematics International + +pci:v00001273* + ID_VENDOR_FROM_DATABASE=Hughes Network Systems + +pci:v00001273d00000002* + ID_MODEL_FROM_DATABASE=DirecPC + +pci:v00001274* + ID_VENDOR_FROM_DATABASE=Ensoniq + +pci:v00001274d00001171* + ID_MODEL_FROM_DATABASE=ES1373 / Creative Labs CT5803 [AudioPCI] + +pci:v00001274d00001371* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 + +pci:v00001274d00001371sv00000E11sd00000024* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (AudioPCI on Motherboard Compaq Deskpro) + +pci:v00001274d00001371sv00000E11sd0000B1A7* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI) + +pci:v00001274d00001371sv00001033sd000080AC* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI) + +pci:v00001274d00001371sv00001042sd00001854* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (Tazer) + +pci:v00001274d00001371sv0000107Bsd00008054* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (Tabor2) + +pci:v00001274d00001371sv00001274sd00001371* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (Audio PCI 64V/128/5200 / Creative CT4810/CT5803/CT5806 [Sound Blaster PCI]) + +pci:v00001274d00001371sv00001274sd00008001* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (CT4751 board) + +pci:v00001274d00001371sv00001462sd00006470* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6147 1.1A) + +pci:v00001274d00001371sv00001462sd00006560* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6156 1.10) + +pci:v00001274d00001371sv00001462sd00006630* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6163BX 1.0A) + +pci:v00001274d00001371sv00001462sd00006631* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6163VIA 1.0A) + +pci:v00001274d00001371sv00001462sd00006632* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6163BX 2.0A) + +pci:v00001274d00001371sv00001462sd00006633* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6163VIA 2.0A) + +pci:v00001274d00001371sv00001462sd00006820* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6182 1.00) + +pci:v00001274d00001371sv00001462sd00006822* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6182 1.00A) + +pci:v00001274d00001371sv00001462sd00006830* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6183 1.00) + +pci:v00001274d00001371sv00001462sd00006880* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6188 1.00) + +pci:v00001274d00001371sv00001462sd00006900* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6190 1.00) + +pci:v00001274d00001371sv00001462sd00006910* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6191) + +pci:v00001274d00001371sv00001462sd00006930* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6193) + +pci:v00001274d00001371sv00001462sd00006990* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6199BX 2.0A) + +pci:v00001274d00001371sv00001462sd00006991* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MS-6199VIA 2.0A) + +pci:v00001274d00001371sv000014A4sd00002077* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard KR639) + +pci:v00001274d00001371sv000014A4sd00002105* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MR800) + +pci:v00001274d00001371sv000014A4sd00002107* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard MR801) + +pci:v00001274d00001371sv000014A4sd00002172* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard DR739) + +pci:v00001274d00001371sv00001509sd00009902* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard KW11) + +pci:v00001274d00001371sv00001509sd00009903* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard KW31) + +pci:v00001274d00001371sv00001509sd00009904* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard KA11) + +pci:v00001274d00001371sv00001509sd00009905* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard KC13) + +pci:v00001274d00001371sv0000152Dsd00008801* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard CP810E) + +pci:v00001274d00001371sv0000152Dsd00008802* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard CP810) + +pci:v00001274d00001371sv0000152Dsd00008803* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard P3810E) + +pci:v00001274d00001371sv0000152Dsd00008804* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard P3810-S) + +pci:v00001274d00001371sv0000152Dsd00008805* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard P3820-S) + +pci:v00001274d00001371sv0000270Fsd00002001* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard 6CTR) + +pci:v00001274d00001371sv0000270Fsd00002200* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard 6WTX) + +pci:v00001274d00001371sv0000270Fsd00003000* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard 6WSV) + +pci:v00001274d00001371sv0000270Fsd00003100* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard 6WIV2) + +pci:v00001274d00001371sv0000270Fsd00003102* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard 6WIV) + +pci:v00001274d00001371sv0000270Fsd00007060* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard 6ASA2) + +pci:v00001274d00001371sv00008086sd00004249* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard BI440ZX) + +pci:v00001274d00001371sv00008086sd0000424C* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard BL440ZX) + +pci:v00001274d00001371sv00008086sd0000425A* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard BZ440ZX) + +pci:v00001274d00001371sv00008086sd00004341* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard Cayman) + +pci:v00001274d00001371sv00008086sd00004343* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard Cape Cod) + +pci:v00001274d00001371sv00008086sd00004541* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (D815EEA Motherboard) + +pci:v00001274d00001371sv00008086sd00004649* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard Fire Island) + +pci:v00001274d00001371sv00008086sd0000464A* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard FJ440ZX) + +pci:v00001274d00001371sv00008086sd00004D4F* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard Montreal) + +pci:v00001274d00001371sv00008086sd00004F43* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard OC440LX) + +pci:v00001274d00001371sv00008086sd00005243* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard RC440BX) + +pci:v00001274d00001371sv00008086sd00005352* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard SunRiver) + +pci:v00001274d00001371sv00008086sd00005643* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard Vancouver) + +pci:v00001274d00001371sv00008086sd00005753* + ID_MODEL_FROM_DATABASE=ES1371/ES1373 / Creative Labs CT2518 (ES1371, ES1373 AudioPCI On Motherboard WS440BX) + +pci:v00001274d00005000* + ID_MODEL_FROM_DATABASE=ES1370 [AudioPCI] + +pci:v00001274d00005880* + ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 + +pci:v00001274d00005880sv00001274sd00002000* + ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (Creative CT4810 [Sound Blaster AudioPCI 128]) + +pci:v00001274d00005880sv00001274sd00002003* + ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (Creative SoundBlaster AudioPCI 128) + +pci:v00001274d00005880sv00001274sd00005880* + ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (Creative CT4750 [Sound Blaster PCI 128]) + +pci:v00001274d00005880sv00001274sd00008001* + ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (Sound Blaster 16PCI 4.1ch) + +pci:v00001274d00005880sv00001458sd0000A000* + ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (5880 AudioPCI On Motherboard 6OXET) + +pci:v00001274d00005880sv00001462sd00006880* + ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (5880 AudioPCI On Motherboard MS-6188 1.00) + +pci:v00001274d00005880sv0000270Fsd00002001* + ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (5880 AudioPCI On Motherboard 6CTR) + +pci:v00001274d00005880sv0000270Fsd00002200* + ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (5880 AudioPCI On Motherboard 6WTX) + +pci:v00001274d00005880sv0000270Fsd00007040* + ID_MODEL_FROM_DATABASE=5880B / Creative Labs CT5880 (5880 AudioPCI On Motherboard 6ATA4) + +pci:v00001274d00008001* + ID_MODEL_FROM_DATABASE=CT5880 [AudioPCI] + +pci:v00001274d00008002* + ID_MODEL_FROM_DATABASE=5880A [AudioPCI] + +pci:v00001275* + ID_VENDOR_FROM_DATABASE=Network Appliance Corporation + +pci:v00001276* + ID_VENDOR_FROM_DATABASE=Switched Network Technologies, Inc. + +pci:v00001277* + ID_VENDOR_FROM_DATABASE=Comstream + +pci:v00001278* + ID_VENDOR_FROM_DATABASE=Transtech Parallel Systems Ltd. + +pci:v00001278d00000701* + ID_MODEL_FROM_DATABASE=TPE3/TM3 PowerPC Node + +pci:v00001278d00000710* + ID_MODEL_FROM_DATABASE=TPE5 PowerPC PCI board + +pci:v00001278d00001100* + ID_MODEL_FROM_DATABASE=PMC-FPGA02 + +pci:v00001278d00001101* + ID_MODEL_FROM_DATABASE=TS-C43 card with 4 ADSP-TS101 processors + +pci:v00001279* + ID_VENDOR_FROM_DATABASE=Transmeta Corporation + +pci:v00001279d00000060* + ID_MODEL_FROM_DATABASE=TM8000 Northbridge + +pci:v00001279d00000061* + ID_MODEL_FROM_DATABASE=TM8000 AGP bridge + +pci:v00001279d00000295* + ID_MODEL_FROM_DATABASE=Northbridge + +pci:v00001279d00000395* + ID_MODEL_FROM_DATABASE=LongRun Northbridge + +pci:v00001279d00000396* + ID_MODEL_FROM_DATABASE=SDRAM controller + +pci:v00001279d00000397* + ID_MODEL_FROM_DATABASE=BIOS scratchpad + +pci:v0000127A* + ID_VENDOR_FROM_DATABASE=Rockwell International + +pci:v0000127Ad00001002* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem + +pci:v0000127Ad00001002sv00001092sd0000094C* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (SupraExpress 56i PRO [Diamond SUP2380]) + +pci:v0000127Ad00001002sv0000122Dsd00004002* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (HPG / MDP3858-U) + +pci:v0000127Ad00001002sv0000122Dsd00004005* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-E) + +pci:v0000127Ad00001002sv0000122Dsd00004007* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-A/-NZ) + +pci:v0000127Ad00001002sv0000122Dsd00004012* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-SA) + +pci:v0000127Ad00001002sv0000122Dsd00004017* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-W) + +pci:v0000127Ad00001002sv0000122Dsd00004018* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-W) + +pci:v0000127Ad00001002sv0000127Asd00001002* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Rockwell 56K D/F HCF Modem) + +pci:v0000127Ad00001003* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem + +pci:v0000127Ad00001003sv00000E11sd0000B0BC* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (229-DF Zephyr) + +pci:v0000127Ad00001003sv00000E11sd0000B114* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (229-DF Cheetah) + +pci:v0000127Ad00001003sv00001033sd0000802B* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (229-DF) + +pci:v0000127Ad00001003sv000013DFsd00001003* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (PCI56RX Modem) + +pci:v0000127Ad00001003sv000013E0sd00000117* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v0000127Ad00001003sv000013E0sd00000147* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM F-1156IV+/R3 Spain V.90 Modem) + +pci:v0000127Ad00001003sv000013E0sd00000197* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v0000127Ad00001003sv000013E0sd000001C7* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM F-1156IV+/R3 WW V.90 Modem) + +pci:v0000127Ad00001003sv000013E0sd000001F7* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v0000127Ad00001003sv00001436sd00001003* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v0000127Ad00001003sv00001436sd00001103* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM 5614PM3G V.90 Modem) + +pci:v0000127Ad00001003sv00001436sd00001602* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Compaq 229-DF Ducati) + +pci:v0000127Ad00001004* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem + +pci:v0000127Ad00001004sv00001048sd00001500* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem (MicroLink 56k Modem) + +pci:v0000127Ad00001004sv000010CFsd00001059* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem (Fujitsu 229-DFRT) + +pci:v0000127Ad00001005* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + +pci:v0000127Ad00001005sv00001005sd0000127A* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (AOpen FM56-P) + +pci:v0000127Ad00001005sv00001033sd00008029* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (229-DFSV) + +pci:v0000127Ad00001005sv00001033sd00008054* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Modem) + +pci:v0000127Ad00001005sv000010CFsd0000103C* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu) + +pci:v0000127Ad00001005sv000010CFsd00001055* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu 229-DFSV) + +pci:v0000127Ad00001005sv000010CFsd00001056* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu 229-DFSV) + +pci:v0000127Ad00001005sv0000122Dsd00004003* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-U) + +pci:v0000127Ad00001005sv0000122Dsd00004006* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Packard Bell MDP3858V-E) + +pci:v0000127Ad00001005sv0000122Dsd00004008* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-A/SP-NZ) + +pci:v0000127Ad00001005sv0000122Dsd00004009* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-E) + +pci:v0000127Ad00001005sv0000122Dsd00004010* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858V-U) + +pci:v0000127Ad00001005sv0000122Dsd00004011* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-SA) + +pci:v0000127Ad00001005sv0000122Dsd00004013* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858V-A/V-NZ) + +pci:v0000127Ad00001005sv0000122Dsd00004015* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-W) + +pci:v0000127Ad00001005sv0000122Dsd00004016* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858V-W) + +pci:v0000127Ad00001005sv0000122Dsd00004019* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858V-SA) + +pci:v0000127Ad00001005sv000013DFsd00001005* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (PCI56RVP Modem) + +pci:v0000127Ad00001005sv000013E0sd00000187* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM) + +pci:v0000127Ad00001005sv000013E0sd000001A7* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM) + +pci:v0000127Ad00001005sv000013E0sd000001B7* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM DF-1156IV+/R3 Spain V.90 Modem) + +pci:v0000127Ad00001005sv000013E0sd000001D7* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM DF-1156IV+/R3 WW V.90 Modem) + +pci:v0000127Ad00001005sv00001436sd00001005* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM) + +pci:v0000127Ad00001005sv00001436sd00001105* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM) + +pci:v0000127Ad00001005sv00001437sd00001105* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (IBM 5614PS3G V.90 Modem) + +pci:v0000127Ad00001022* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v0000127Ad00001022sv00001436sd00001303* + ID_MODEL_FROM_DATABASE=HCF 56k Modem (M3-5614PM3G V.90 Modem) + +pci:v0000127Ad00001023* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem + +pci:v0000127Ad00001023sv0000122Dsd00004020* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Packard Bell MDP3858-WE) + +pci:v0000127Ad00001023sv0000122Dsd00004023* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (MDP3858-UE) + +pci:v0000127Ad00001023sv000013E0sd00000247* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM F-1156IV+/R6 Spain V.90 Modem) + +pci:v0000127Ad00001023sv000013E0sd00000297* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v0000127Ad00001023sv000013E0sd000002C7* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM F-1156IV+/R6 WW V.90 Modem) + +pci:v0000127Ad00001023sv00001436sd00001203* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v0000127Ad00001023sv00001436sd00001303* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v0000127Ad00001024* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem + +pci:v0000127Ad00001025* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + +pci:v0000127Ad00001025sv000010CFsd0000106A* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu 235-DFSV) + +pci:v0000127Ad00001025sv0000122Dsd00004021* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Packard Bell MDP3858V-WE) + +pci:v0000127Ad00001025sv0000122Dsd00004022* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-WE) + +pci:v0000127Ad00001025sv0000122Dsd00004024* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858V-UE) + +pci:v0000127Ad00001025sv0000122Dsd00004025* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (MDP3858SP-UE) + +pci:v0000127Ad00001026* + ID_MODEL_FROM_DATABASE=HCF 56k PCI Speakerphone Modem + +pci:v0000127Ad00001032* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v0000127Ad00001033* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v0000127Ad00001034* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v0000127Ad00001035* + ID_MODEL_FROM_DATABASE=HCF 56k PCI Speakerphone Modem + +pci:v0000127Ad00001036* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v0000127Ad00001085* + ID_MODEL_FROM_DATABASE=HCF 56k Volcano PCI Modem + +pci:v0000127Ad00002004* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + +pci:v0000127Ad00002005* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem + +pci:v0000127Ad00002005sv0000104Dsd00008044* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (229-DFSV) + +pci:v0000127Ad00002005sv0000104Dsd00008045* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (229-DFSV) + +pci:v0000127Ad00002005sv0000104Dsd00008055* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (PBE/Aztech 235W-DFSV) + +pci:v0000127Ad00002005sv0000104Dsd00008056* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (235-DFSV) + +pci:v0000127Ad00002005sv0000104Dsd0000805A* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Modem) + +pci:v0000127Ad00002005sv0000104Dsd0000805F* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Modem) + +pci:v0000127Ad00002005sv0000104Dsd00008074* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Modem) + +pci:v0000127Ad00002013* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem + +pci:v0000127Ad00002013sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Modem) + +pci:v0000127Ad00002013sv00001179sd0000FF00* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Modem) + +pci:v0000127Ad00002014* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem + +pci:v0000127Ad00002014sv000010CFsd00001057* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (Fujitsu Citicorp III) + +pci:v0000127Ad00002014sv0000122Dsd00004050* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (MSP3880-U) + +pci:v0000127Ad00002014sv0000122Dsd00004055* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (MSP3880-W) + +pci:v0000127Ad00002015* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + +pci:v0000127Ad00002015sv000010CFsd00001063* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu) + +pci:v0000127Ad00002015sv000010CFsd00001064* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu) + +pci:v0000127Ad00002015sv00001468sd00002015* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu) + +pci:v0000127Ad00002016* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem + +pci:v0000127Ad00002016sv0000122Dsd00004051* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (MSP3880V-W) + +pci:v0000127Ad00002016sv0000122Dsd00004052* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (MSP3880SP-W) + +pci:v0000127Ad00002016sv0000122Dsd00004054* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (MSP3880V-U) + +pci:v0000127Ad00002016sv0000122Dsd00004056* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (MSP3880SP-U) + +pci:v0000127Ad00002016sv0000122Dsd00004057* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (MSP3880SP-A) + +pci:v0000127Ad00004311* + ID_MODEL_FROM_DATABASE=Riptide HSF 56k PCI Modem + +pci:v0000127Ad00004311sv0000127Asd00004311* + ID_MODEL_FROM_DATABASE=Riptide HSF 56k PCI Modem (Ring Modular? Riptide HSF RT HP Dom) + +pci:v0000127Ad00004311sv000013E0sd00000210* + ID_MODEL_FROM_DATABASE=Riptide HSF 56k PCI Modem (HP-GVC) + +pci:v0000127Ad00004320* + ID_MODEL_FROM_DATABASE=Riptide PCI Audio Controller + +pci:v0000127Ad00004320sv00001235sd00004320* + ID_MODEL_FROM_DATABASE=Riptide PCI Audio Controller + +pci:v0000127Ad00004321* + ID_MODEL_FROM_DATABASE=Riptide HCF 56k PCI Modem + +pci:v0000127Ad00004321sv00001235sd00004321* + ID_MODEL_FROM_DATABASE=Riptide HCF 56k PCI Modem (Hewlett Packard DF) + +pci:v0000127Ad00004321sv00001235sd00004324* + ID_MODEL_FROM_DATABASE=Riptide HCF 56k PCI Modem (Hewlett Packard DF) + +pci:v0000127Ad00004321sv000013E0sd00000210* + ID_MODEL_FROM_DATABASE=Riptide HCF 56k PCI Modem (Hewlett Packard DF) + +pci:v0000127Ad00004321sv0000144Dsd00002321* + ID_MODEL_FROM_DATABASE=Riptide HCF 56k PCI Modem (Riptide) + +pci:v0000127Ad00004322* + ID_MODEL_FROM_DATABASE=Riptide PCI Game Controller + +pci:v0000127Ad00004322sv00001235sd00004322* + ID_MODEL_FROM_DATABASE=Riptide PCI Game Controller + +pci:v0000127Ad00008234* + ID_MODEL_FROM_DATABASE=RapidFire 616X ATM155 Adapter + +pci:v0000127Ad00008234sv0000108Dsd00000022* + ID_MODEL_FROM_DATABASE=RapidFire 616X ATM155 Adapter + +pci:v0000127Ad00008234sv0000108Dsd00000027* + ID_MODEL_FROM_DATABASE=RapidFire 616X ATM155 Adapter + +pci:v0000127B* + ID_VENDOR_FROM_DATABASE=Pixera Corporation + +pci:v0000127C* + ID_VENDOR_FROM_DATABASE=Crosspoint Solutions, Inc. + +pci:v0000127D* + ID_VENDOR_FROM_DATABASE=Vela Research + +pci:v0000127E* + ID_VENDOR_FROM_DATABASE=Winnov, L.P. + +pci:v0000127Ed00000010* + ID_MODEL_FROM_DATABASE=Videum 1000 Plus + +pci:v0000127F* + ID_VENDOR_FROM_DATABASE=Fujifilm + +pci:v00001280* + ID_VENDOR_FROM_DATABASE=Photoscript Group Ltd. + +pci:v00001281* + ID_VENDOR_FROM_DATABASE=Yokogawa Electric Corporation + +pci:v00001282* + ID_VENDOR_FROM_DATABASE=Davicom Semiconductor, Inc. + +pci:v00001282d00006585* + ID_MODEL_FROM_DATABASE=DM562P V90 Modem + +pci:v00001282d00009009* + ID_MODEL_FROM_DATABASE=Ethernet 100/10 MBit + +pci:v00001282d00009100* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v00001282d00009102* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v00001282d00009102sv00000291sd00008212* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet (DM9102A (DM9102AE, SM9102AF) Ethernet 100/10 MBit) + +pci:v00001282d00009132* + ID_MODEL_FROM_DATABASE=Ethernet 100/10 MBit + +pci:v00001283* + ID_VENDOR_FROM_DATABASE=Integrated Technology Express, Inc. + +pci:v00001283d0000673A* + ID_MODEL_FROM_DATABASE=IT8330G + +pci:v00001283d00008152* + ID_MODEL_FROM_DATABASE=IT8152F/G Advanced RISC-to-PCI Companion Chip + +pci:v00001283d00008211* + ID_MODEL_FROM_DATABASE=ITE 8211F Single Channel UDMA 133 + +pci:v00001283d00008211sv00001043sd00008138* + ID_MODEL_FROM_DATABASE=ITE 8211F Single Channel UDMA 133 (P5GD1-VW Mainboard) + +pci:v00001283d00008212* + ID_MODEL_FROM_DATABASE=IT8212 Dual channel ATA RAID controller + +pci:v00001283d00008212sv00001283sd00000001* + ID_MODEL_FROM_DATABASE=IT8212 Dual channel ATA RAID controller (IT/ITE8212 Dual channel ATA RAID controller) + +pci:v00001283d00008213* + ID_MODEL_FROM_DATABASE=IT8213 IDE Controller + +pci:v00001283d00008213sv00001458sd0000B000* + ID_MODEL_FROM_DATABASE=IT8213 IDE Controller (GA-EG45M-DS2H Mainboard) + +pci:v00001283d00008330* + ID_MODEL_FROM_DATABASE=IT8330G + +pci:v00001283d00008872* + ID_MODEL_FROM_DATABASE=IT887xF PCI to ISA I/O chip with SMB, GPIO, Serial or Parallel Port + +pci:v00001283d00008888* + ID_MODEL_FROM_DATABASE=IT8888F/G PCI to ISA Bridge with SMB [Golden Gate] + +pci:v00001283d00008889* + ID_MODEL_FROM_DATABASE=IT8889F PCI to ISA Bridge + +pci:v00001283d00008892* + ID_MODEL_FROM_DATABASE=IT8892E PCIe to PCI Bridge + +pci:v00001283d00008893* + ID_MODEL_FROM_DATABASE=IT8893E PCIe to PCI Bridge + +pci:v00001283d0000E886* + ID_MODEL_FROM_DATABASE=IT8330G + +pci:v00001284* + ID_VENDOR_FROM_DATABASE=Sahara Networks, Inc. + +pci:v00001285* + ID_VENDOR_FROM_DATABASE=Platform Technologies, Inc. + +pci:v00001285d00000100* + ID_MODEL_FROM_DATABASE=AGOGO sound chip (aka ESS Maestro 1) + +pci:v00001286* + ID_VENDOR_FROM_DATABASE=Mazet GmbH + +pci:v00001287* + ID_VENDOR_FROM_DATABASE=M-Pact, Inc. + +pci:v00001287d0000001E* + ID_MODEL_FROM_DATABASE=LS220D DVD Decoder + +pci:v00001287d0000001F* + ID_MODEL_FROM_DATABASE=LS220C DVD Decoder + +pci:v00001288* + ID_VENDOR_FROM_DATABASE=Timestep Corporation + +pci:v00001289* + ID_VENDOR_FROM_DATABASE=AVC Technology, Inc. + +pci:v0000128A* + ID_VENDOR_FROM_DATABASE=Asante Technologies, Inc. + +pci:v0000128B* + ID_VENDOR_FROM_DATABASE=Transwitch Corporation + +pci:v0000128C* + ID_VENDOR_FROM_DATABASE=Retix Corporation + +pci:v0000128D* + ID_VENDOR_FROM_DATABASE=G2 Networks, Inc. + +pci:v0000128Dd00000021* + ID_MODEL_FROM_DATABASE=ATM155 Adapter + +pci:v0000128E* + ID_VENDOR_FROM_DATABASE=Hoontech Corporation/Samho Multi Tech Ltd. + +pci:v0000128Ed00000008* + ID_MODEL_FROM_DATABASE=ST128 WSS/SB + +pci:v0000128Ed00000009* + ID_MODEL_FROM_DATABASE=ST128 SAM9407 + +pci:v0000128Ed0000000A* + ID_MODEL_FROM_DATABASE=ST128 Game Port + +pci:v0000128Ed0000000B* + ID_MODEL_FROM_DATABASE=ST128 MPU Port + +pci:v0000128Ed0000000C* + ID_MODEL_FROM_DATABASE=ST128 Ctrl Port + +pci:v0000128F* + ID_VENDOR_FROM_DATABASE=Tateno Dennou, Inc. + +pci:v00001290* + ID_VENDOR_FROM_DATABASE=Sord Computer Corporation + +pci:v00001291* + ID_VENDOR_FROM_DATABASE=NCS Computer Italia + +pci:v00001292* + ID_VENDOR_FROM_DATABASE=Tritech Microelectronics Inc + +pci:v00001292d0000FC02* + ID_MODEL_FROM_DATABASE=Pyramid3D TR25202 + +pci:v00001293* + ID_VENDOR_FROM_DATABASE=Media Reality Technology + +pci:v00001294* + ID_VENDOR_FROM_DATABASE=Rhetorex, Inc. + +pci:v00001295* + ID_VENDOR_FROM_DATABASE=Imagenation Corporation + +pci:v00001295d00000800* + ID_MODEL_FROM_DATABASE=PXR800 + +pci:v00001295d00001000* + ID_MODEL_FROM_DATABASE=PXD1000 + +pci:v00001296* + ID_VENDOR_FROM_DATABASE=Kofax Image Products + +pci:v00001297* + ID_VENDOR_FROM_DATABASE=Holco Enterprise Co, Ltd/Shuttle Computer + +pci:v00001298* + ID_VENDOR_FROM_DATABASE=Spellcaster Telecommunications Inc. + +pci:v00001299* + ID_VENDOR_FROM_DATABASE=Knowledge Technology Lab. + +pci:v0000129A* + ID_VENDOR_FROM_DATABASE=VMetro, inc. + +pci:v0000129Ad00000615* + ID_MODEL_FROM_DATABASE=PBT-615 PCI-X Bus Analyzer + +pci:v0000129Ad00001100* + ID_MODEL_FROM_DATABASE=PMC-FPGA05 + +pci:v0000129Ad00001106* + ID_MODEL_FROM_DATABASE=XMC-FPGA05F, PCI interface + +pci:v0000129Ad00001107* + ID_MODEL_FROM_DATABASE=XMC-FPGA05F, PCIe interface + +pci:v0000129Ad00001108* + ID_MODEL_FROM_DATABASE=XMC-FPGA05D, PCI interface + +pci:v0000129Ad00001109* + ID_MODEL_FROM_DATABASE=XMC-FPGA05D, PCIe interface + +pci:v0000129B* + ID_VENDOR_FROM_DATABASE=Image Access + +pci:v0000129C* + ID_VENDOR_FROM_DATABASE=Jaycor + +pci:v0000129D* + ID_VENDOR_FROM_DATABASE=Compcore Multimedia, Inc. + +pci:v0000129E* + ID_VENDOR_FROM_DATABASE=Victor Company of Japan, Ltd. + +pci:v0000129F* + ID_VENDOR_FROM_DATABASE=OEC Medical Systems, Inc. + +pci:v000012A0* + ID_VENDOR_FROM_DATABASE=Allen-Bradley Company + +pci:v000012A1* + ID_VENDOR_FROM_DATABASE=Simpact Associates, Inc. + +pci:v000012A2* + ID_VENDOR_FROM_DATABASE=Newgen Systems Corporation + +pci:v000012A3* + ID_VENDOR_FROM_DATABASE=Lucent Technologies + +pci:v000012A3d00008105* + ID_MODEL_FROM_DATABASE=T8105 H100 Digital Switch + +pci:v000012A4* + ID_VENDOR_FROM_DATABASE=NTT Electronics Corporation + +pci:v000012A5* + ID_VENDOR_FROM_DATABASE=Vision Dynamics Ltd. + +pci:v000012A6* + ID_VENDOR_FROM_DATABASE=Scalable Networks, Inc. + +pci:v000012A7* + ID_VENDOR_FROM_DATABASE=AMO GmbH + +pci:v000012A8* + ID_VENDOR_FROM_DATABASE=News Datacom + +pci:v000012A9* + ID_VENDOR_FROM_DATABASE=Xiotech Corporation + +pci:v000012AA* + ID_VENDOR_FROM_DATABASE=SDL Communications, Inc. + +pci:v000012AB* + ID_VENDOR_FROM_DATABASE=YUAN High-Tech Development Co., Ltd. + +pci:v000012ABd00000000* + ID_MODEL_FROM_DATABASE=MPG160/Kuroutoshikou ITVC15-STVLP + +pci:v000012ABd00000002* + ID_MODEL_FROM_DATABASE=AU8830 [Vortex2] Based Sound Card With A3D Support + +pci:v000012ABd00000003* + ID_MODEL_FROM_DATABASE=T507 (DVB-T) TV tuner/capture device + +pci:v000012ABd00002300* + ID_MODEL_FROM_DATABASE=Club-3D Zap TV2100 + +pci:v000012ABd00003000* + ID_MODEL_FROM_DATABASE=MPG-200C PCI DVD Decoder Card + +pci:v000012ABd00004789* + ID_MODEL_FROM_DATABASE=MPC788 MiniPCI Hybrid TV Tuner + +pci:v000012ABd0000FFF3* + ID_MODEL_FROM_DATABASE=MPG600/Kuroutoshikou ITVC16-STVLP + +pci:v000012ABd0000FFFF* + ID_MODEL_FROM_DATABASE=MPG600/Kuroutoshikou ITVC16-STVLP + +pci:v000012AC* + ID_VENDOR_FROM_DATABASE=Measurex Corporation + +pci:v000012AD* + ID_VENDOR_FROM_DATABASE=Multidata GmbH + +pci:v000012AE* + ID_VENDOR_FROM_DATABASE=Alteon Networks Inc. + +pci:v000012AEd00000001* + ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet + +pci:v000012AEd00000001sv00001014sd00000104* + ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet (Gigabit Ethernet-SX PCI Adapter) + +pci:v000012AEd00000001sv000012AEsd00000001* + ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet (Gigabit Ethernet-SX (Universal)) + +pci:v000012AEd00000002* + ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet (Copper) + +pci:v000012AEd00000002sv000010A9sd00008002* + ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet (Copper) (Acenic Gigabit Ethernet) + +pci:v000012AEd00000002sv000012AEsd00000002* + ID_MODEL_FROM_DATABASE=AceNIC Gigabit Ethernet (Copper) (Gigabit Ethernet-T (3C986-T)) + +pci:v000012AEd000000FA* + ID_MODEL_FROM_DATABASE=Farallon PN9100-T Gigabit Ethernet + +pci:v000012AF* + ID_VENDOR_FROM_DATABASE=TDK USA Corp + +pci:v000012B0* + ID_VENDOR_FROM_DATABASE=Jorge Scientific Corp + +pci:v000012B1* + ID_VENDOR_FROM_DATABASE=GammaLink + +pci:v000012B2* + ID_VENDOR_FROM_DATABASE=General Signal Networks + +pci:v000012B3* + ID_VENDOR_FROM_DATABASE=Inter-Face Co Ltd + +pci:v000012B4* + ID_VENDOR_FROM_DATABASE=FutureTel Inc + +pci:v000012B5* + ID_VENDOR_FROM_DATABASE=Granite Systems Inc. + +pci:v000012B6* + ID_VENDOR_FROM_DATABASE=Natural Microsystems + +pci:v000012B7* + ID_VENDOR_FROM_DATABASE=Cognex Corporation + +pci:v000012B8* + ID_VENDOR_FROM_DATABASE=Korg + +pci:v000012B9* + ID_VENDOR_FROM_DATABASE=3Com Corp, Modem Division + +pci:v000012B9d00001006* + ID_MODEL_FROM_DATABASE=WinModem + +pci:v000012B9d00001006sv000012B9sd0000005C* + ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Model 3472)) + +pci:v000012B9d00001006sv000012B9sd0000005E* + ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal WinModem (Models 662975)) + +pci:v000012B9d00001006sv000012B9sd00000062* + ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Model 662978)) + +pci:v000012B9d00001006sv000012B9sd00000068* + ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Model 5690)) + +pci:v000012B9d00001006sv000012B9sd0000007A* + ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Model 662974)) + +pci:v000012B9d00001006sv000012B9sd0000007F* + ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal WinModem (Models 5698, 5699)) + +pci:v000012B9d00001006sv000012B9sd00000080* + ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal WinModem (Models 2975, 3528)) + +pci:v000012B9d00001006sv000012B9sd00000081* + ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Models 2974, 3529)) + +pci:v000012B9d00001006sv000012B9sd00000091* + ID_MODEL_FROM_DATABASE=WinModem (USR 56k Internal Voice WinModem (Model 2978)) + +pci:v000012B9d00001007* + ID_MODEL_FROM_DATABASE=USR 56k Internal WinModem + +pci:v000012B9d00001007sv000012B9sd000000A3* + ID_MODEL_FROM_DATABASE=USR 56k Internal WinModem ((Model 3595)) + +pci:v000012B9d00001007sv000012B9sd000000C4* + ID_MODEL_FROM_DATABASE=USR 56k Internal WinModem (U.S. Robotics V.92 Voice Faxmodem (2884A/B/C)) + +pci:v000012B9d00001008* + ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 + +pci:v000012B9d00001008sv000012B9sd000000A2* + ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56k Internal FAX Modem (Model 2977)) + +pci:v000012B9d00001008sv000012B9sd000000AA* + ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56k Internal Voice Modem (Model 2976)) + +pci:v000012B9d00001008sv000012B9sd000000AB* + ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56k Internal Voice Modem (Model 5609)) + +pci:v000012B9d00001008sv000012B9sd000000AC* + ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56k Internal Voice Modem (Model 3298)) + +pci:v000012B9d00001008sv000012B9sd000000AD* + ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56k Internal FAX Modem (Model 5610)) + +pci:v000012B9d00001008sv000012B9sd000000D3* + ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56K Internal V92 FAX Modem (Model 5610)) + +pci:v000012B9d00001008sv000012B9sd0000BABA* + ID_MODEL_FROM_DATABASE=56K FaxModem Model 5610 (USR 56K Internal Voice Modem 3CP3298-DEL (Model 5601) [Hawk]) + +pci:v000012BA* + ID_VENDOR_FROM_DATABASE=BittWare, Inc. + +pci:v000012BB* + ID_VENDOR_FROM_DATABASE=Nippon Unisoft Corporation + +pci:v000012BC* + ID_VENDOR_FROM_DATABASE=Array Microsystems + +pci:v000012BD* + ID_VENDOR_FROM_DATABASE=Computerm Corp. + +pci:v000012BE* + ID_VENDOR_FROM_DATABASE=Anchor Chips Inc. + +pci:v000012BEd00003041* + ID_MODEL_FROM_DATABASE=AN3041Q CO-MEM + +pci:v000012BEd00003042* + ID_MODEL_FROM_DATABASE=AN3042Q CO-MEM Lite + +pci:v000012BEd00003042sv000012BEsd00003042* + ID_MODEL_FROM_DATABASE=AN3042Q CO-MEM Lite (Anchor Chips Lite Evaluation Board) + +pci:v000012BF* + ID_VENDOR_FROM_DATABASE=Fujifilm Microdevices + +pci:v000012C0* + ID_VENDOR_FROM_DATABASE=Infimed + +pci:v000012C1* + ID_VENDOR_FROM_DATABASE=GMM Research Corp + +pci:v000012C2* + ID_VENDOR_FROM_DATABASE=Mentec Limited + +pci:v000012C3* + ID_VENDOR_FROM_DATABASE=Holtek Microelectronics Inc + +pci:v000012C3d00000058* + ID_MODEL_FROM_DATABASE=PCI NE2K Ethernet + +pci:v000012C3d00005598* + ID_MODEL_FROM_DATABASE=PCI NE2K Ethernet + +pci:v000012C4* + ID_VENDOR_FROM_DATABASE=Connect Tech Inc + +pci:v000012C4d00000001* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 8 (RS232/CL/RJ11) + +pci:v000012C4d00000002* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 4 (RS232) + +pci:v000012C4d00000003* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2 (RS232) + +pci:v000012C4d00000004* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 8 (UNIV, RS485) + +pci:v000012C4d00000005* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 4+4/6+2 (UNIV, RS232/485) + +pci:v000012C4d00000006* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 4 (OPTO, RS485) + +pci:v000012C4d00000007* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2+2 (RS232/485) + +pci:v000012C4d00000008* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2 (OPTO, Tx, RS485) + +pci:v000012C4d00000009* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2+6 (RS232/485) + +pci:v000012C4d0000000A* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 8 (Tx, RS485) + +pci:v000012C4d0000000B* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 4 (Tx, RS485) + +pci:v000012C4d0000000C* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2 (20 MHz, RS485) + +pci:v000012C4d0000000D* + ID_MODEL_FROM_DATABASE=Blue HEAT/PCI 2 PTM + +pci:v000012C4d00000100* + ID_MODEL_FROM_DATABASE=NT960/PCI + +pci:v000012C4d00000201* + ID_MODEL_FROM_DATABASE=cPCI Titan - 2 Port + +pci:v000012C4d00000202* + ID_MODEL_FROM_DATABASE=cPCI Titan - 4 Port + +pci:v000012C4d00000300* + ID_MODEL_FROM_DATABASE=CTI PCI UART 2 (RS232) + +pci:v000012C4d00000301* + ID_MODEL_FROM_DATABASE=CTI PCI UART 4 (RS232) + +pci:v000012C4d00000302* + ID_MODEL_FROM_DATABASE=CTI PCI UART 8 (RS232) + +pci:v000012C4d00000310* + ID_MODEL_FROM_DATABASE=CTI PCI UART 1+1 (RS232/485) + +pci:v000012C4d00000311* + ID_MODEL_FROM_DATABASE=CTI PCI UART 2+2 (RS232/485) + +pci:v000012C4d00000312* + ID_MODEL_FROM_DATABASE=CTI PCI UART 4+4 (RS232/485) + +pci:v000012C4d00000320* + ID_MODEL_FROM_DATABASE=CTI PCI UART 2 + +pci:v000012C4d00000321* + ID_MODEL_FROM_DATABASE=CTI PCI UART 4 + +pci:v000012C4d00000322* + ID_MODEL_FROM_DATABASE=CTI PCI UART 8 + +pci:v000012C4d00000330* + ID_MODEL_FROM_DATABASE=CTI PCI UART 2 (RS485) + +pci:v000012C4d00000331* + ID_MODEL_FROM_DATABASE=CTI PCI UART 4 (RS485) + +pci:v000012C4d00000332* + ID_MODEL_FROM_DATABASE=CTI PCI UART 8 (RS485) + +pci:v000012C5* + ID_VENDOR_FROM_DATABASE=Picture Elements Incorporated + +pci:v000012C5d0000007E* + ID_MODEL_FROM_DATABASE=Imaging/Scanning Subsystem Engine + +pci:v000012C5d0000007F* + ID_MODEL_FROM_DATABASE=Imaging/Scanning Subsystem Engine + +pci:v000012C5d00000081* + ID_MODEL_FROM_DATABASE=PCIVST [Grayscale Thresholding Engine] + +pci:v000012C5d00000085* + ID_MODEL_FROM_DATABASE=Video Simulator/Sender + +pci:v000012C5d00000086* + ID_MODEL_FROM_DATABASE=THR2 Multi-scale Thresholder + +pci:v000012C6* + ID_VENDOR_FROM_DATABASE=Mitani Corporation + +pci:v000012C7* + ID_VENDOR_FROM_DATABASE=Dialogic Corp + +pci:v000012C7d00000546* + ID_MODEL_FROM_DATABASE=Springware D/120JCT-LS + +pci:v000012C7d00000647* + ID_MODEL_FROM_DATABASE=Springware D/240JCT-T1 + +pci:v000012C7d00000676* + ID_MODEL_FROM_DATABASE=Springware D/41JCT-LS + +pci:v000012C7d00000685* + ID_MODEL_FROM_DATABASE=Springware D/480JCT-2T1 + +pci:v000012C8* + ID_VENDOR_FROM_DATABASE=G Force Co, Ltd + +pci:v000012C9* + ID_VENDOR_FROM_DATABASE=Gigi Operations + +pci:v000012CA* + ID_VENDOR_FROM_DATABASE=Integrated Computing Engines + +pci:v000012CB* + ID_VENDOR_FROM_DATABASE=Antex Electronics Corporation + +pci:v000012CBd00000027* + ID_MODEL_FROM_DATABASE=SC4 (StudioCard) + +pci:v000012CBd0000002E* + ID_MODEL_FROM_DATABASE=StudioCard 2000 + +pci:v000012CC* + ID_VENDOR_FROM_DATABASE=Pluto Technologies International + +pci:v000012CD* + ID_VENDOR_FROM_DATABASE=Aims Lab + +pci:v000012CE* + ID_VENDOR_FROM_DATABASE=Netspeed Inc. + +pci:v000012CF* + ID_VENDOR_FROM_DATABASE=Prophet Systems, Inc. + +pci:v000012D0* + ID_VENDOR_FROM_DATABASE=GDE Systems, Inc. + +pci:v000012D1* + ID_VENDOR_FROM_DATABASE=PSITech + +pci:v000012D2* + ID_VENDOR_FROM_DATABASE=NVidia / SGS Thomson (Joint Venture) + +pci:v000012D2d00000008* + ID_MODEL_FROM_DATABASE=NV1 + +pci:v000012D2d00000009* + ID_MODEL_FROM_DATABASE=DAC64 + +pci:v000012D2d00000018* + ID_MODEL_FROM_DATABASE=Riva128 + +pci:v000012D2d00000018sv00001048sd00000C10* + ID_MODEL_FROM_DATABASE=Riva128 (VICTORY Erazor) + +pci:v000012D2d00000018sv0000107Bsd00008030* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) + +pci:v000012D2d00000018sv00001092sd00000350* + ID_MODEL_FROM_DATABASE=Riva128 (Viper V330) + +pci:v000012D2d00000018sv00001092sd00001092* + ID_MODEL_FROM_DATABASE=Riva128 (Viper V330) + +pci:v000012D2d00000018sv000010B4sd00001B1B* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) + +pci:v000012D2d00000018sv000010B4sd00001B1D* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) + +pci:v000012D2d00000018sv000010B4sd00001B1E* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128, PAL TV-Out) + +pci:v000012D2d00000018sv000010B4sd00001B20* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 Sapphire) + +pci:v000012D2d00000018sv000010B4sd00001B21* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) + +pci:v000012D2d00000018sv000010B4sd00001B22* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 AGP, NTSC TV-Out) + +pci:v000012D2d00000018sv000010B4sd00001B23* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 AGP, PAL TV-Out) + +pci:v000012D2d00000018sv000010B4sd00001B27* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 DVD) + +pci:v000012D2d00000018sv000010B4sd00001B88* + ID_MODEL_FROM_DATABASE=Riva128 (MVP Pro 128) + +pci:v000012D2d00000018sv000010B4sd0000222A* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 AGP) + +pci:v000012D2d00000018sv000010B4sd00002230* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) + +pci:v000012D2d00000018sv000010B4sd00002232* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128) + +pci:v000012D2d00000018sv000010B4sd00002235* + ID_MODEL_FROM_DATABASE=Riva128 (STB Velocity 128 AGP) + +pci:v000012D2d00000018sv00002A15sd000054A3* + ID_MODEL_FROM_DATABASE=Riva128 (3DVision-SAGP / 3DexPlorer 3000) + +pci:v000012D2d00000019* + ID_MODEL_FROM_DATABASE=Riva128ZX + +pci:v000012D2d00000020* + ID_MODEL_FROM_DATABASE=TNT + +pci:v000012D2d00000028* + ID_MODEL_FROM_DATABASE=TNT2 + +pci:v000012D2d00000029* + ID_MODEL_FROM_DATABASE=UTNT2 + +pci:v000012D2d0000002C* + ID_MODEL_FROM_DATABASE=VTNT2 + +pci:v000012D2d000000A0* + ID_MODEL_FROM_DATABASE=ITNT2 + +pci:v000012D3* + ID_VENDOR_FROM_DATABASE=Vingmed Sound A/S + +pci:v000012D4* + ID_VENDOR_FROM_DATABASE=Ulticom (Formerly DGM&S) + +pci:v000012D4d00000200* + ID_MODEL_FROM_DATABASE=T1 Card + +pci:v000012D5* + ID_VENDOR_FROM_DATABASE=Equator Technologies Inc + +pci:v000012D5d00000003* + ID_MODEL_FROM_DATABASE=BSP16 + +pci:v000012D5d00001000* + ID_MODEL_FROM_DATABASE=BSP15 + +pci:v000012D6* + ID_VENDOR_FROM_DATABASE=Analogic Corp + +pci:v000012D7* + ID_VENDOR_FROM_DATABASE=Biotronic SRL + +pci:v000012D8* + ID_VENDOR_FROM_DATABASE=Pericom Semiconductor + +pci:v000012D8d000001A7* + ID_MODEL_FROM_DATABASE=7C21P100 2-port PCI-X to PCI-X Bridge + +pci:v000012D8d00002304* + ID_MODEL_FROM_DATABASE=PI7C9X2G304 EL/SL PCIe2 3-Port/4-Lane Packet Switch + +pci:v000012D8d00002404* + ID_MODEL_FROM_DATABASE=PI7C9X2G404 EL/SL PCIe2 4-Port/4-Lane Packet Switch + +pci:v000012D8d00002608* + ID_MODEL_FROM_DATABASE=PI7C9X2G608GP PCIe2 6-Port/8-Lane Packet Switch + +pci:v000012D8d0000400A* + ID_MODEL_FROM_DATABASE=PI7C9X442SL PCI Express Bridge Port + +pci:v000012D8d0000400E* + ID_MODEL_FROM_DATABASE=PI7C9X442SL USB OHCI Controller + +pci:v000012D8d0000400F* + ID_MODEL_FROM_DATABASE=PI7C9X442SL USB EHCI Controller + +pci:v000012D8d000071E2* + ID_MODEL_FROM_DATABASE=PI7C7300A/PI7C7300D PCI-to-PCI Bridge + +pci:v000012D8d000071E3* + ID_MODEL_FROM_DATABASE=PI7C7300A/PI7C7300D PCI-to-PCI Bridge (Secondary Bus 2) + +pci:v000012D8d00008140* + ID_MODEL_FROM_DATABASE=PI7C8140A PCI-to-PCI Bridge + +pci:v000012D8d00008148* + ID_MODEL_FROM_DATABASE=PI7C8148A/PI7C8148B PCI-to-PCI Bridge + +pci:v000012D8d00008150* + ID_MODEL_FROM_DATABASE=PCI to PCI Bridge + +pci:v000012D8d00008152* + ID_MODEL_FROM_DATABASE=PI7C8152A/PI7C8152B/PI7C8152BI PCI-to-PCI Bridge + +pci:v000012D8d00008154* + ID_MODEL_FROM_DATABASE=PI7C8154A/PI7C8154B/PI7C8154BI PCI-to-PCI Bridge + +pci:v000012D8d0000E110* + ID_MODEL_FROM_DATABASE=PI7C9X110 PCI Express to PCI bridge + +pci:v000012D8d0000E110sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=PI7C9X110 PCI Express to PCI bridge (CC11/CL11 CompactPCI Bridge) + +pci:v000012D8d0000E111* + ID_MODEL_FROM_DATABASE=PI7C9X111SL PCIe-to-PCI Reversible Bridge + +pci:v000012D8d0000E130* + ID_MODEL_FROM_DATABASE=PCI Express to PCI-XPI7C9X130 PCI-X Bridge + +pci:v000012D9* + ID_VENDOR_FROM_DATABASE=Aculab PLC + +pci:v000012D9d00000002* + ID_MODEL_FROM_DATABASE=PCI Prosody + +pci:v000012D9d00000004* + ID_MODEL_FROM_DATABASE=cPCI Prosody + +pci:v000012D9d00000005* + ID_MODEL_FROM_DATABASE=Aculab E1/T1 PCI card + +pci:v000012D9d00001078* + ID_MODEL_FROM_DATABASE=Prosody X class e1000 device + +pci:v000012D9d00001078sv000012D9sd0000000D* + ID_MODEL_FROM_DATABASE=Prosody X class e1000 device (Prosody X PCI) + +pci:v000012D9d00001078sv000012D9sd0000000E* + ID_MODEL_FROM_DATABASE=Prosody X class e1000 device (Prosody X cPCI) + +pci:v000012DA* + ID_VENDOR_FROM_DATABASE=True Time Inc. + +pci:v000012DB* + ID_VENDOR_FROM_DATABASE=Annapolis Micro Systems, Inc + +pci:v000012DC* + ID_VENDOR_FROM_DATABASE=Symicron Computer Communication Ltd. + +pci:v000012DD* + ID_VENDOR_FROM_DATABASE=Management Graphics + +pci:v000012DE* + ID_VENDOR_FROM_DATABASE=Rainbow Technologies + +pci:v000012DEd00000200* + ID_MODEL_FROM_DATABASE=CryptoSwift CS200 + +pci:v000012DF* + ID_VENDOR_FROM_DATABASE=SBS Technologies Inc + +pci:v000012E0* + ID_VENDOR_FROM_DATABASE=Chase Research + +pci:v000012E0d00000010* + ID_MODEL_FROM_DATABASE=ST16C654 Quad UART + +pci:v000012E0d00000020* + ID_MODEL_FROM_DATABASE=ST16C654 Quad UART + +pci:v000012E0d00000030* + ID_MODEL_FROM_DATABASE=ST16C654 Quad UART + +pci:v000012E1* + ID_VENDOR_FROM_DATABASE=Nintendo Co, Ltd + +pci:v000012E2* + ID_VENDOR_FROM_DATABASE=Datum Inc. Bancomm-Timing Division + +pci:v000012E3* + ID_VENDOR_FROM_DATABASE=Imation Corp - Medical Imaging Systems + +pci:v000012E4* + ID_VENDOR_FROM_DATABASE=Brooktrout Technology Inc + +pci:v000012E5* + ID_VENDOR_FROM_DATABASE=Apex Semiconductor Inc + +pci:v000012E6* + ID_VENDOR_FROM_DATABASE=Cirel Systems + +pci:v000012E7* + ID_VENDOR_FROM_DATABASE=Sunsgroup Corporation + +pci:v000012E8* + ID_VENDOR_FROM_DATABASE=Crisc Corp + +pci:v000012E9* + ID_VENDOR_FROM_DATABASE=GE Spacenet + +pci:v000012EA* + ID_VENDOR_FROM_DATABASE=Zuken + +pci:v000012EB* + ID_VENDOR_FROM_DATABASE=Aureal Semiconductor + +pci:v000012EBd00000001* + ID_MODEL_FROM_DATABASE=Vortex 1 + +pci:v000012EBd00000001sv0000104Dsd00008036* + ID_MODEL_FROM_DATABASE=Vortex 1 (AU8820 Vortex Digital Audio Processor) + +pci:v000012EBd00000001sv00001092sd00002000* + ID_MODEL_FROM_DATABASE=Vortex 1 (Sonic Impact A3D) + +pci:v000012EBd00000001sv00001092sd00002100* + ID_MODEL_FROM_DATABASE=Vortex 1 (Sonic Impact A3D) + +pci:v000012EBd00000001sv00001092sd00002110* + ID_MODEL_FROM_DATABASE=Vortex 1 (Sonic Impact A3D) + +pci:v000012EBd00000001sv00001092sd00002200* + ID_MODEL_FROM_DATABASE=Vortex 1 (Sonic Impact A3D) + +pci:v000012EBd00000001sv0000122Dsd00001002* + ID_MODEL_FROM_DATABASE=Vortex 1 (AU8820 Vortex Digital Audio Processor) + +pci:v000012EBd00000001sv000012EBsd00000001* + ID_MODEL_FROM_DATABASE=Vortex 1 (AU8820 Vortex Digital Audio Processor) + +pci:v000012EBd00000001sv00005053sd00003355* + ID_MODEL_FROM_DATABASE=Vortex 1 (Montego) + +pci:v000012EBd00000001sv000050B2sd00001111* + ID_MODEL_FROM_DATABASE=Vortex 1 (XLerate) + +pci:v000012EBd00000002* + ID_MODEL_FROM_DATABASE=Vortex 2 + +pci:v000012EBd00000002sv0000104Dsd00008049* + ID_MODEL_FROM_DATABASE=Vortex 2 (AU8830 Vortex 3D Digital Audio Processor) + +pci:v000012EBd00000002sv0000104Dsd0000807B* + ID_MODEL_FROM_DATABASE=Vortex 2 (AU8830 Vortex 3D Digital Audio Processor) + +pci:v000012EBd00000002sv00001092sd00003000* + ID_MODEL_FROM_DATABASE=Vortex 2 (Monster Sound II) + +pci:v000012EBd00000002sv00001092sd00003001* + ID_MODEL_FROM_DATABASE=Vortex 2 (Monster Sound II) + +pci:v000012EBd00000002sv00001092sd00003002* + ID_MODEL_FROM_DATABASE=Vortex 2 (Monster Sound II) + +pci:v000012EBd00000002sv00001092sd00003003* + ID_MODEL_FROM_DATABASE=Vortex 2 (Monster Sound II) + +pci:v000012EBd00000002sv00001092sd00003004* + ID_MODEL_FROM_DATABASE=Vortex 2 (Monster Sound II) + +pci:v000012EBd00000002sv000012EBsd00000002* + ID_MODEL_FROM_DATABASE=Vortex 2 (AU8830 Vortex 3D Digital Audio Processor) + +pci:v000012EBd00000002sv000012EBsd00000088* + ID_MODEL_FROM_DATABASE=Vortex 2 (AU8830 Vortex 3D Digital Audio Processor) + +pci:v000012EBd00000002sv0000144Dsd00003510* + ID_MODEL_FROM_DATABASE=Vortex 2 (AU8830 Vortex 3D Digital Audio Processor) + +pci:v000012EBd00000002sv00005053sd00003356* + ID_MODEL_FROM_DATABASE=Vortex 2 (Montego II) + +pci:v000012EBd00000003* + ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor + +pci:v000012EBd00000003sv0000104Dsd00008049* + ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor + +pci:v000012EBd00000003sv0000104Dsd00008077* + ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor + +pci:v000012EBd00000003sv0000109Fsd00001000* + ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor + +pci:v000012EBd00000003sv000012EBsd00000003* + ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor + +pci:v000012EBd00000003sv00001462sd00006780* + ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor + +pci:v000012EBd00000003sv000014A4sd00002073* + ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor + +pci:v000012EBd00000003sv000014A4sd00002091* + ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor + +pci:v000012EBd00000003sv000014A4sd00002104* + ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor + +pci:v000012EBd00000003sv000014A4sd00002106* + ID_MODEL_FROM_DATABASE=AU8810 Vortex Digital Audio Processor + +pci:v000012EBd00008803* + ID_MODEL_FROM_DATABASE=Vortex 56k Software Modem + +pci:v000012EBd00008803sv000012EBsd00008803* + ID_MODEL_FROM_DATABASE=Vortex 56k Software Modem + +pci:v000012EC* + ID_VENDOR_FROM_DATABASE=3A International, Inc. + +pci:v000012ED* + ID_VENDOR_FROM_DATABASE=Optivision Inc. + +pci:v000012EE* + ID_VENDOR_FROM_DATABASE=Orange Micro + +pci:v000012EF* + ID_VENDOR_FROM_DATABASE=Vienna Systems + +pci:v000012F0* + ID_VENDOR_FROM_DATABASE=Pentek + +pci:v000012F1* + ID_VENDOR_FROM_DATABASE=Sorenson Vision Inc + +pci:v000012F2* + ID_VENDOR_FROM_DATABASE=Gammagraphx, Inc. + +pci:v000012F3* + ID_VENDOR_FROM_DATABASE=Radstone Technology + +pci:v000012F4* + ID_VENDOR_FROM_DATABASE=Megatel + +pci:v000012F5* + ID_VENDOR_FROM_DATABASE=Forks + +pci:v000012F6* + ID_VENDOR_FROM_DATABASE=Dawson France + +pci:v000012F7* + ID_VENDOR_FROM_DATABASE=Cognex + +pci:v000012F8* + ID_VENDOR_FROM_DATABASE=Electronic Design GmbH + +pci:v000012F8d00000002* + ID_MODEL_FROM_DATABASE=VideoMaker + +pci:v000012F9* + ID_VENDOR_FROM_DATABASE=Four Fold Ltd + +pci:v000012FB* + ID_VENDOR_FROM_DATABASE=Spectrum Signal Processing + +pci:v000012FBd00000001* + ID_MODEL_FROM_DATABASE=PMC-MAI + +pci:v000012FBd000000F5* + ID_MODEL_FROM_DATABASE=F5 Dakar + +pci:v000012FBd000002AD* + ID_MODEL_FROM_DATABASE=PMC-2MAI + +pci:v000012FBd00002ADC* + ID_MODEL_FROM_DATABASE=ePMC-2ADC + +pci:v000012FBd00003100* + ID_MODEL_FROM_DATABASE=PRO-3100 + +pci:v000012FBd00003500* + ID_MODEL_FROM_DATABASE=PRO-3500 + +pci:v000012FBd00004D4F* + ID_MODEL_FROM_DATABASE=Modena + +pci:v000012FBd00008120* + ID_MODEL_FROM_DATABASE=ePMC-8120 + +pci:v000012FBd0000DA62* + ID_MODEL_FROM_DATABASE=Daytona C6201 PCI (Hurricane) + +pci:v000012FBd0000DB62* + ID_MODEL_FROM_DATABASE=Ingliston XBIF + +pci:v000012FBd0000DC62* + ID_MODEL_FROM_DATABASE=Ingliston PLX9054 + +pci:v000012FBd0000DD62* + ID_MODEL_FROM_DATABASE=Ingliston JTAG/ISP + +pci:v000012FBd0000EDDC* + ID_MODEL_FROM_DATABASE=ePMC-MSDDC + +pci:v000012FBd0000FA01* + ID_MODEL_FROM_DATABASE=ePMC-FPGA + +pci:v000012FC* + ID_VENDOR_FROM_DATABASE=Capital Equipment Corp + +pci:v000012FD* + ID_VENDOR_FROM_DATABASE=I2S + +pci:v000012FE* + ID_VENDOR_FROM_DATABASE=ESD Electronic System Design GmbH + +pci:v000012FF* + ID_VENDOR_FROM_DATABASE=Lexicon + +pci:v00001300* + ID_VENDOR_FROM_DATABASE=Harman International Industries Inc + +pci:v00001302* + ID_VENDOR_FROM_DATABASE=Computer Sciences Corp + +pci:v00001303* + ID_VENDOR_FROM_DATABASE=Innovative Integration + +pci:v00001303d00000030* + ID_MODEL_FROM_DATABASE=X3-SDF 4-channel XMC acquisition board + +pci:v00001304* + ID_VENDOR_FROM_DATABASE=Juniper Networks + +pci:v00001305* + ID_VENDOR_FROM_DATABASE=Netphone, Inc + +pci:v00001306* + ID_VENDOR_FROM_DATABASE=Duet Technologies + +pci:v00001307* + ID_VENDOR_FROM_DATABASE=Measurement Computing + +pci:v00001307d00000001* + ID_MODEL_FROM_DATABASE=PCI-DAS1602/16 + +pci:v00001307d0000000B* + ID_MODEL_FROM_DATABASE=PCI-DIO48H + +pci:v00001307d0000000C* + ID_MODEL_FROM_DATABASE=PCI-PDISO8 + +pci:v00001307d0000000D* + ID_MODEL_FROM_DATABASE=PCI-PDISO16 + +pci:v00001307d0000000F* + ID_MODEL_FROM_DATABASE=PCI-DAS1200 + +pci:v00001307d00000010* + ID_MODEL_FROM_DATABASE=PCI-DAS1602/12 + +pci:v00001307d00000014* + ID_MODEL_FROM_DATABASE=PCI-DIO24H + +pci:v00001307d00000015* + ID_MODEL_FROM_DATABASE=PCI-DIO24H/CTR3 + +pci:v00001307d00000016* + ID_MODEL_FROM_DATABASE=PCI-DIO48H/CTR15 + +pci:v00001307d00000017* + ID_MODEL_FROM_DATABASE=PCI-DIO96H + +pci:v00001307d00000018* + ID_MODEL_FROM_DATABASE=PCI-CTR05 + +pci:v00001307d00000019* + ID_MODEL_FROM_DATABASE=PCI-DAS1200/JR + +pci:v00001307d0000001A* + ID_MODEL_FROM_DATABASE=PCI-DAS1001 + +pci:v00001307d0000001B* + ID_MODEL_FROM_DATABASE=PCI-DAS1002 + +pci:v00001307d0000001C* + ID_MODEL_FROM_DATABASE=PCI-DAS1602JR/16 + +pci:v00001307d0000001D* + ID_MODEL_FROM_DATABASE=PCI-DAS6402/16 + +pci:v00001307d0000001E* + ID_MODEL_FROM_DATABASE=PCI-DAS6402/12 + +pci:v00001307d0000001F* + ID_MODEL_FROM_DATABASE=PCI-DAS16/M1 + +pci:v00001307d00000020* + ID_MODEL_FROM_DATABASE=PCI-DDA02/12 + +pci:v00001307d00000021* + ID_MODEL_FROM_DATABASE=PCI-DDA04/12 + +pci:v00001307d00000022* + ID_MODEL_FROM_DATABASE=PCI-DDA08/12 + +pci:v00001307d00000023* + ID_MODEL_FROM_DATABASE=PCI-DDA02/16 + +pci:v00001307d00000024* + ID_MODEL_FROM_DATABASE=PCI-DDA04/16 + +pci:v00001307d00000025* + ID_MODEL_FROM_DATABASE=PCI-DDA08/16 + +pci:v00001307d00000026* + ID_MODEL_FROM_DATABASE=PCI-DAC04/12-HS + +pci:v00001307d00000027* + ID_MODEL_FROM_DATABASE=PCI-DAC04/16-HS + +pci:v00001307d00000028* + ID_MODEL_FROM_DATABASE=PCI-DIO24 + +pci:v00001307d00000029* + ID_MODEL_FROM_DATABASE=PCI-DAS08 + +pci:v00001307d0000002C* + ID_MODEL_FROM_DATABASE=PCI-INT32 + +pci:v00001307d00000033* + ID_MODEL_FROM_DATABASE=PCI-DUAL-AC5 + +pci:v00001307d00000034* + ID_MODEL_FROM_DATABASE=PCI-DAS-TC + +pci:v00001307d00000035* + ID_MODEL_FROM_DATABASE=PCI-DAS64/M1/16 + +pci:v00001307d00000036* + ID_MODEL_FROM_DATABASE=PCI-DAS64/M2/16 + +pci:v00001307d00000037* + ID_MODEL_FROM_DATABASE=PCI-DAS64/M3/16 + +pci:v00001307d0000004C* + ID_MODEL_FROM_DATABASE=PCI-DAS1000 + +pci:v00001307d0000004D* + ID_MODEL_FROM_DATABASE=PCI-QUAD04 + +pci:v00001307d00000052* + ID_MODEL_FROM_DATABASE=PCI-DAS4020/12 + +pci:v00001307d00000053* + ID_MODEL_FROM_DATABASE=PCIM-DDA06/16 + +pci:v00001307d00000054* + ID_MODEL_FROM_DATABASE=PCI-DIO96 + +pci:v00001307d0000005D* + ID_MODEL_FROM_DATABASE=PCI-DAS6023 + +pci:v00001307d0000005E* + ID_MODEL_FROM_DATABASE=PCI-DAS6025 + +pci:v00001307d0000005F* + ID_MODEL_FROM_DATABASE=PCI-DAS6030 + +pci:v00001307d00000060* + ID_MODEL_FROM_DATABASE=PCI-DAS6031 + +pci:v00001307d00000061* + ID_MODEL_FROM_DATABASE=PCI-DAS6032 + +pci:v00001307d00000062* + ID_MODEL_FROM_DATABASE=PCI-DAS6033 + +pci:v00001307d00000063* + ID_MODEL_FROM_DATABASE=PCI-DAS6034 + +pci:v00001307d00000064* + ID_MODEL_FROM_DATABASE=PCI-DAS6035 + +pci:v00001307d00000065* + ID_MODEL_FROM_DATABASE=PCI-DAS6040 + +pci:v00001307d00000066* + ID_MODEL_FROM_DATABASE=PCI-DAS6052 + +pci:v00001307d00000067* + ID_MODEL_FROM_DATABASE=PCI-DAS6070 + +pci:v00001307d00000068* + ID_MODEL_FROM_DATABASE=PCI-DAS6071 + +pci:v00001307d0000006F* + ID_MODEL_FROM_DATABASE=PCI-DAS6036 + +pci:v00001307d00000070* + ID_MODEL_FROM_DATABASE=PCI-DAC6702 + +pci:v00001307d00000078* + ID_MODEL_FROM_DATABASE=PCI-DAS6013 + +pci:v00001307d00000079* + ID_MODEL_FROM_DATABASE=PCI-DAS6014 + +pci:v00001307d00000115* + ID_MODEL_FROM_DATABASE=PCIe-DAS1602/16 + +pci:v00001308* + ID_VENDOR_FROM_DATABASE=Jato Technologies Inc. + +pci:v00001308d00000001* + ID_MODEL_FROM_DATABASE=NetCelerator Adapter + +pci:v00001308d00000001sv00001308sd00000001* + ID_MODEL_FROM_DATABASE=NetCelerator Adapter + +pci:v00001309* + ID_VENDOR_FROM_DATABASE=AB Semiconductor Ltd + +pci:v0000130A* + ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Microcomputer + +pci:v0000130B* + ID_VENDOR_FROM_DATABASE=Colorgraphic Communications Corp + +pci:v0000130C* + ID_VENDOR_FROM_DATABASE=Ambex Technologies, Inc + +pci:v0000130D* + ID_VENDOR_FROM_DATABASE=Accelerix Inc + +pci:v0000130E* + ID_VENDOR_FROM_DATABASE=Yamatake-Honeywell Co. Ltd + +pci:v0000130F* + ID_VENDOR_FROM_DATABASE=Advanet Inc + +pci:v00001310* + ID_VENDOR_FROM_DATABASE=Gespac + +pci:v00001311* + ID_VENDOR_FROM_DATABASE=Videoserver, Inc + +pci:v00001312* + ID_VENDOR_FROM_DATABASE=Acuity Imaging, Inc + +pci:v00001313* + ID_VENDOR_FROM_DATABASE=Yaskawa Electric Co. + +pci:v00001315* + ID_VENDOR_FROM_DATABASE=Wavesat + +pci:v00001316* + ID_VENDOR_FROM_DATABASE=Teradyne Inc + +pci:v00001317* + ID_VENDOR_FROM_DATABASE=ADMtek + +pci:v00001317d00000981* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v00001317d00000985* + ID_MODEL_FROM_DATABASE=NC100 Network Everywhere Fast Ethernet 10/100 + +pci:v00001317d00000985sv00001734sd0000100C* + ID_MODEL_FROM_DATABASE=NC100 Network Everywhere Fast Ethernet 10/100 (Scenic N300 ADMtek AN983 10/100 Mbps PCI Adapter) + +pci:v00001317d00001985* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v00001317d00001985sv00001385sd0000511A* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet (FA511) + +pci:v00001317d00001985sv00001395sd00002103* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet (CB100-EZ (4-LED version)) + +pci:v00001317d00002850* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 + +pci:v00001317d00005120* + ID_MODEL_FROM_DATABASE=ADM5120 OpenGate System-on-Chip + +pci:v00001317d00008201* + ID_MODEL_FROM_DATABASE=ADM8211 802.11b Wireless Interface + +pci:v00001317d00008201sv000010B8sd00002635* + ID_MODEL_FROM_DATABASE=ADM8211 802.11b Wireless Interface (SMC2635W v1 802.11b Wireless Cardbus Adapter) + +pci:v00001317d00008201sv00001317sd00008201* + ID_MODEL_FROM_DATABASE=ADM8211 802.11b Wireless Interface (SMC2635W v2 802.11b Wireless Cardbus Adapter) + +pci:v00001317d00008211* + ID_MODEL_FROM_DATABASE=ADM8211 802.11b Wireless Interface + +pci:v00001317d00009511* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v00001318* + ID_VENDOR_FROM_DATABASE=Packet Engines Inc. + +pci:v00001318d00000911* + ID_MODEL_FROM_DATABASE=GNIC-II PCI Gigabit Ethernet [Hamachi] + +pci:v00001319* + ID_VENDOR_FROM_DATABASE=Fortemedia, Inc + +pci:v00001319d00000801* + ID_MODEL_FROM_DATABASE=Xwave QS3000A [FM801] + +pci:v00001319d00000801sv00001319sd00001319* + ID_MODEL_FROM_DATABASE=Xwave QS3000A [FM801] (FM801 PCI Audio) + +pci:v00001319d00000802* + ID_MODEL_FROM_DATABASE=Xwave QS3000A [FM801 game port] + +pci:v00001319d00000802sv00001319sd00001319* + ID_MODEL_FROM_DATABASE=Xwave QS3000A [FM801 game port] (FM801 PCI Joystick) + +pci:v00001319d00001000* + ID_MODEL_FROM_DATABASE=FM801 PCI Audio + +pci:v00001319d00001001* + ID_MODEL_FROM_DATABASE=FM801 PCI Joystick + +pci:v0000131A* + ID_VENDOR_FROM_DATABASE=Finisar Corp. + +pci:v0000131C* + ID_VENDOR_FROM_DATABASE=Nippon Electro-Sensory Devices Corp + +pci:v0000131D* + ID_VENDOR_FROM_DATABASE=Sysmic, Inc. + +pci:v0000131E* + ID_VENDOR_FROM_DATABASE=Xinex Networks Inc + +pci:v0000131F* + ID_VENDOR_FROM_DATABASE=Siig Inc + +pci:v0000131Fd00001000* + ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16550 + +pci:v0000131Fd00001001* + ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16650 + +pci:v0000131Fd00001002* + ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16850 + +pci:v0000131Fd00001010* + ID_MODEL_FROM_DATABASE=Duet 1S(16550)+1P + +pci:v0000131Fd00001011* + ID_MODEL_FROM_DATABASE=Duet 1S(16650)+1P + +pci:v0000131Fd00001012* + ID_MODEL_FROM_DATABASE=Duet 1S(16850)+1P + +pci:v0000131Fd00001020* + ID_MODEL_FROM_DATABASE=CyberParallel (1-port) + +pci:v0000131Fd00001021* + ID_MODEL_FROM_DATABASE=CyberParallel (2-port) + +pci:v0000131Fd00001030* + ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16550 + +pci:v0000131Fd00001031* + ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16650 + +pci:v0000131Fd00001032* + ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16850 + +pci:v0000131Fd00001034* + ID_MODEL_FROM_DATABASE=Trio 2S(16550)+1P + +pci:v0000131Fd00001035* + ID_MODEL_FROM_DATABASE=Trio 2S(16650)+1P + +pci:v0000131Fd00001036* + ID_MODEL_FROM_DATABASE=Trio 2S(16850)+1P + +pci:v0000131Fd00001050* + ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16550 + +pci:v0000131Fd00001051* + ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16650 + +pci:v0000131Fd00001052* + ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16850 + +pci:v0000131Fd00002000* + ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16550 + +pci:v0000131Fd00002001* + ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16650 + +pci:v0000131Fd00002002* + ID_MODEL_FROM_DATABASE=CyberSerial (1-port) 16850 + +pci:v0000131Fd00002010* + ID_MODEL_FROM_DATABASE=Duet 1S(16550)+1P + +pci:v0000131Fd00002011* + ID_MODEL_FROM_DATABASE=Duet 1S(16650)+1P + +pci:v0000131Fd00002012* + ID_MODEL_FROM_DATABASE=Duet 1S(16850)+1P + +pci:v0000131Fd00002020* + ID_MODEL_FROM_DATABASE=CyberParallel (1-port) + +pci:v0000131Fd00002021* + ID_MODEL_FROM_DATABASE=CyberParallel (2-port) + +pci:v0000131Fd00002030* + ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16550 + +pci:v0000131Fd00002030sv0000131Fsd00002030* + ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16550 (PCI Serial Card) + +pci:v0000131Fd00002031* + ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16650 + +pci:v0000131Fd00002032* + ID_MODEL_FROM_DATABASE=CyberSerial (2-port) 16850 + +pci:v0000131Fd00002040* + ID_MODEL_FROM_DATABASE=Trio 1S(16550)+2P + +pci:v0000131Fd00002041* + ID_MODEL_FROM_DATABASE=Trio 1S(16650)+2P + +pci:v0000131Fd00002042* + ID_MODEL_FROM_DATABASE=Trio 1S(16850)+2P + +pci:v0000131Fd00002050* + ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16550 + +pci:v0000131Fd00002051* + ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16650 + +pci:v0000131Fd00002052* + ID_MODEL_FROM_DATABASE=CyberSerial (4-port) 16850 + +pci:v0000131Fd00002060* + ID_MODEL_FROM_DATABASE=Trio 2S(16550)+1P + +pci:v0000131Fd00002061* + ID_MODEL_FROM_DATABASE=Trio 2S(16650)+1P + +pci:v0000131Fd00002062* + ID_MODEL_FROM_DATABASE=Trio 2S(16850)+1P + +pci:v0000131Fd00002081* + ID_MODEL_FROM_DATABASE=CyberSerial (8-port) ST16654 + +pci:v00001320* + ID_VENDOR_FROM_DATABASE=Crypto AG + +pci:v00001321* + ID_VENDOR_FROM_DATABASE=Arcobel Graphics BV + +pci:v00001322* + ID_VENDOR_FROM_DATABASE=MTT Co., Ltd + +pci:v00001323* + ID_VENDOR_FROM_DATABASE=Dome Inc + +pci:v00001324* + ID_VENDOR_FROM_DATABASE=Sphere Communications + +pci:v00001325* + ID_VENDOR_FROM_DATABASE=Salix Technologies, Inc + +pci:v00001326* + ID_VENDOR_FROM_DATABASE=Seachange international + +pci:v00001327* + ID_VENDOR_FROM_DATABASE=Voss scientific + +pci:v00001328* + ID_VENDOR_FROM_DATABASE=quadrant international + +pci:v00001329* + ID_VENDOR_FROM_DATABASE=Productivity Enhancement + +pci:v0000132A* + ID_VENDOR_FROM_DATABASE=Microcom Inc. + +pci:v0000132B* + ID_VENDOR_FROM_DATABASE=Broadband Technologies + +pci:v0000132C* + ID_VENDOR_FROM_DATABASE=Micrel Inc + +pci:v0000132D* + ID_VENDOR_FROM_DATABASE=Integrated Silicon Solution, Inc. + +pci:v00001330* + ID_VENDOR_FROM_DATABASE=MMC Networks + +pci:v00001331* + ID_VENDOR_FROM_DATABASE=RadiSys Corporation + +pci:v00001331d00000030* + ID_MODEL_FROM_DATABASE=ENP-2611 + +pci:v00001331d00008200* + ID_MODEL_FROM_DATABASE=82600 Host Bridge + +pci:v00001331d00008201* + ID_MODEL_FROM_DATABASE=82600 IDE + +pci:v00001331d00008202* + ID_MODEL_FROM_DATABASE=82600 USB + +pci:v00001331d00008210* + ID_MODEL_FROM_DATABASE=82600 PCI Bridge + +pci:v00001332* + ID_VENDOR_FROM_DATABASE=Micro Memory + +pci:v00001332d00005415* + ID_MODEL_FROM_DATABASE=MM-5415CN PCI Memory Module with Battery Backup + +pci:v00001332d00005425* + ID_MODEL_FROM_DATABASE=MM-5425CN PCI 64/66 Memory Module with Battery Backup + +pci:v00001332d00006140* + ID_MODEL_FROM_DATABASE=MM-6140D + +pci:v00001334* + ID_VENDOR_FROM_DATABASE=Redcreek Communications, Inc + +pci:v00001335* + ID_VENDOR_FROM_DATABASE=Videomail, Inc + +pci:v00001337* + ID_VENDOR_FROM_DATABASE=Third Planet Publishing + +pci:v00001338* + ID_VENDOR_FROM_DATABASE=BT Electronics + +pci:v0000133A* + ID_VENDOR_FROM_DATABASE=Vtel Corp + +pci:v0000133B* + ID_VENDOR_FROM_DATABASE=Softcom Microsystems + +pci:v0000133C* + ID_VENDOR_FROM_DATABASE=Holontech Corp + +pci:v0000133D* + ID_VENDOR_FROM_DATABASE=SS Technologies + +pci:v0000133E* + ID_VENDOR_FROM_DATABASE=Virtual Computer Corp + +pci:v0000133F* + ID_VENDOR_FROM_DATABASE=SCM Microsystems + +pci:v00001340* + ID_VENDOR_FROM_DATABASE=Atalla Corp + +pci:v00001341* + ID_VENDOR_FROM_DATABASE=Kyoto Microcomputer Co + +pci:v00001342* + ID_VENDOR_FROM_DATABASE=Promax Systems Inc + +pci:v00001343* + ID_VENDOR_FROM_DATABASE=Phylon Communications Inc + +pci:v00001344* + ID_VENDOR_FROM_DATABASE=Micron Technology Inc + +pci:v00001344d00005150* + ID_MODEL_FROM_DATABASE=RealSSD P320h + +pci:v00001344d00005151* + ID_MODEL_FROM_DATABASE=RealSSD P320m + +pci:v00001344d00005152* + ID_MODEL_FROM_DATABASE=RealSSD P320s + +pci:v00001344d00005153* + ID_MODEL_FROM_DATABASE=RealSSD P325m + +pci:v00001344d00005160* + ID_MODEL_FROM_DATABASE=RealSSD P420h + +pci:v00001344d00005161* + ID_MODEL_FROM_DATABASE=RealSSD P420m + +pci:v00001344d00005163* + ID_MODEL_FROM_DATABASE=RealSSD P425m + +pci:v00001344d00005180* + ID_MODEL_FROM_DATABASE=9100 PRO NVMe SSD + +pci:v00001344d00005181* + ID_MODEL_FROM_DATABASE=9100 MAX NVMe SSD + +pci:v00001344d00005190* + ID_MODEL_FROM_DATABASE=9200 ECO NVMe SSD + +pci:v00001344d00005191* + ID_MODEL_FROM_DATABASE=9200 PRO NVMe SSD + +pci:v00001344d00005192* + ID_MODEL_FROM_DATABASE=9200 MAX NVMe SSD + +pci:v00001345* + ID_VENDOR_FROM_DATABASE=Arescom Inc + +pci:v00001347* + ID_VENDOR_FROM_DATABASE=Odetics + +pci:v00001349* + ID_VENDOR_FROM_DATABASE=Sumitomo Electric Industries, Ltd. + +pci:v0000134A* + ID_VENDOR_FROM_DATABASE=DTC Technology Corp. + +pci:v0000134Ad00000001* + ID_MODEL_FROM_DATABASE=Domex 536 + +pci:v0000134Ad00000002* + ID_MODEL_FROM_DATABASE=Domex DMX3194UP SCSI Adapter + +pci:v0000134B* + ID_VENDOR_FROM_DATABASE=ARK Research Corp. + +pci:v0000134C* + ID_VENDOR_FROM_DATABASE=Chori Joho System Co. Ltd + +pci:v0000134D* + ID_VENDOR_FROM_DATABASE=PCTel Inc + +pci:v0000134Dd00002189* + ID_MODEL_FROM_DATABASE=HSP56 MicroModem + +pci:v0000134Dd00002486* + ID_MODEL_FROM_DATABASE=2304WT V.92 MDC Modem + +pci:v0000134Dd00007890* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 + +pci:v0000134Dd00007890sv0000134Dsd00000001* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 (PCT789 adapter) + +pci:v0000134Dd00007891* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 + +pci:v0000134Dd00007891sv0000134Dsd00000001* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 + +pci:v0000134Dd00007892* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 + +pci:v0000134Dd00007893* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 + +pci:v0000134Dd00007894* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 + +pci:v0000134Dd00007895* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 + +pci:v0000134Dd00007896* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 + +pci:v0000134Dd00007897* + ID_MODEL_FROM_DATABASE=HSP MicroModem 56 + +pci:v0000134E* + ID_VENDOR_FROM_DATABASE=CSTI + +pci:v0000134F* + ID_VENDOR_FROM_DATABASE=Algo System Co Ltd + +pci:v00001350* + ID_VENDOR_FROM_DATABASE=Systec Co. Ltd + +pci:v00001351* + ID_VENDOR_FROM_DATABASE=Sonix Inc + +pci:v00001353* + ID_VENDOR_FROM_DATABASE=Vierling Communication SAS + +pci:v00001353d00000002* + ID_MODEL_FROM_DATABASE=Proserver + +pci:v00001353d00000003* + ID_MODEL_FROM_DATABASE=PCI-FUT + +pci:v00001353d00000004* + ID_MODEL_FROM_DATABASE=PCI-S0 + +pci:v00001353d00000005* + ID_MODEL_FROM_DATABASE=PCI-FUT-S0 + +pci:v00001354* + ID_VENDOR_FROM_DATABASE=Dwave System Inc + +pci:v00001355* + ID_VENDOR_FROM_DATABASE=Kratos Analytical Ltd + +pci:v00001356* + ID_VENDOR_FROM_DATABASE=The Logical Co + +pci:v00001359* + ID_VENDOR_FROM_DATABASE=Prisa Networks + +pci:v0000135A* + ID_VENDOR_FROM_DATABASE=Brain Boxes + +pci:v0000135Ad00000A61* + ID_MODEL_FROM_DATABASE=UC-324 [VELOCITY RS422/485] + +pci:v0000135B* + ID_VENDOR_FROM_DATABASE=Giganet Inc + +pci:v0000135C* + ID_VENDOR_FROM_DATABASE=Quatech Inc + +pci:v0000135Cd00000010* + ID_MODEL_FROM_DATABASE=QSC-100 + +pci:v0000135Cd00000020* + ID_MODEL_FROM_DATABASE=DSC-100 + +pci:v0000135Cd00000030* + ID_MODEL_FROM_DATABASE=DSC-200/300 + +pci:v0000135Cd00000040* + ID_MODEL_FROM_DATABASE=QSC-200/300 + +pci:v0000135Cd00000050* + ID_MODEL_FROM_DATABASE=ESC-100D + +pci:v0000135Cd00000060* + ID_MODEL_FROM_DATABASE=ESC-100M + +pci:v0000135Cd000000F0* + ID_MODEL_FROM_DATABASE=MPAC-100 Synchronous Serial Card (Zilog 85230) + +pci:v0000135Cd00000170* + ID_MODEL_FROM_DATABASE=QSCLP-100 + +pci:v0000135Cd00000180* + ID_MODEL_FROM_DATABASE=DSCLP-100 + +pci:v0000135Cd00000190* + ID_MODEL_FROM_DATABASE=SSCLP-100 + +pci:v0000135Cd000001A0* + ID_MODEL_FROM_DATABASE=QSCLP-200/300 + +pci:v0000135Cd000001B0* + ID_MODEL_FROM_DATABASE=DSCLP-200/300 + +pci:v0000135Cd000001C0* + ID_MODEL_FROM_DATABASE=SSCLP-200/300 + +pci:v0000135Cd00000258* + ID_MODEL_FROM_DATABASE=DSPSX-200/300 + +pci:v0000135D* + ID_VENDOR_FROM_DATABASE=ABB Network Partner AB + +pci:v0000135E* + ID_VENDOR_FROM_DATABASE=Sealevel Systems Inc + +pci:v0000135Ed00005101* + ID_MODEL_FROM_DATABASE=Route 56.PCI - Multi-Protocol Serial Interface (Zilog Z16C32) + +pci:v0000135Ed00007101* + ID_MODEL_FROM_DATABASE=Single Port RS-232/422/485/530 + +pci:v0000135Ed00007201* + ID_MODEL_FROM_DATABASE=Dual Port RS-232/422/485 Interface + +pci:v0000135Ed00007202* + ID_MODEL_FROM_DATABASE=Dual Port RS-232 Interface + +pci:v0000135Ed00007401* + ID_MODEL_FROM_DATABASE=Four Port RS-232 Interface + +pci:v0000135Ed00007402* + ID_MODEL_FROM_DATABASE=Four Port RS-422/485 Interface + +pci:v0000135Ed00007801* + ID_MODEL_FROM_DATABASE=Eight Port RS-232 Interface + +pci:v0000135Ed00007804* + ID_MODEL_FROM_DATABASE=Eight Port RS-232/422/485 Interface + +pci:v0000135Ed00008001* + ID_MODEL_FROM_DATABASE=8001 Digital I/O Adapter + +pci:v0000135F* + ID_VENDOR_FROM_DATABASE=I-Data International A-S + +pci:v00001360* + ID_VENDOR_FROM_DATABASE=Meinberg Funkuhren + +pci:v00001360d00000101* + ID_MODEL_FROM_DATABASE=PCI32 DCF77 Radio Clock + +pci:v00001360d00000102* + ID_MODEL_FROM_DATABASE=PCI509 DCF77 Radio Clock + +pci:v00001360d00000103* + ID_MODEL_FROM_DATABASE=PCI510 DCF77 Radio Clock + +pci:v00001360d00000104* + ID_MODEL_FROM_DATABASE=PCI511 DCF77 Radio Clock + +pci:v00001360d00000105* + ID_MODEL_FROM_DATABASE=PEX511 DCF77 Radio Clock (PCI Express) + +pci:v00001360d00000106* + ID_MODEL_FROM_DATABASE=PZF180PEX High Precision DCF77 Radio Clock (PCI Express) + +pci:v00001360d00000201* + ID_MODEL_FROM_DATABASE=GPS167PCI GPS Receiver + +pci:v00001360d00000202* + ID_MODEL_FROM_DATABASE=GPS168PCI GPS Receiver + +pci:v00001360d00000203* + ID_MODEL_FROM_DATABASE=GPS169PCI GPS Receiver + +pci:v00001360d00000204* + ID_MODEL_FROM_DATABASE=GPS170PCI GPS Receiver + +pci:v00001360d00000205* + ID_MODEL_FROM_DATABASE=GPS170PEX GPS Receiver (PCI Express) + +pci:v00001360d00000206* + ID_MODEL_FROM_DATABASE=GPS180PEX GPS Receiver (PCI Express) + +pci:v00001360d00000207* + ID_MODEL_FROM_DATABASE=GLN180PEX GPS/GLONASS receiver (PCI Express) + +pci:v00001360d00000208* + ID_MODEL_FROM_DATABASE=GPS180AMC GPS Receiver (PCI Express / MicroTCA / AdvancedMC) + +pci:v00001360d00000209* + ID_MODEL_FROM_DATABASE=GNS181PEX GPS/Galileo/GLONASS/BEIDOU receiver (PCI Express) + +pci:v00001360d00000301* + ID_MODEL_FROM_DATABASE=TCR510PCI IRIG Timecode Reader + +pci:v00001360d00000302* + ID_MODEL_FROM_DATABASE=TCR167PCI IRIG Timecode Reader + +pci:v00001360d00000303* + ID_MODEL_FROM_DATABASE=TCR511PCI IRIG Timecode Reader + +pci:v00001360d00000304* + ID_MODEL_FROM_DATABASE=TCR511PEX IRIG Timecode Reader (PCI Express) + +pci:v00001360d00000305* + ID_MODEL_FROM_DATABASE=TCR170PEX IRIG Timecode Reader (PCI Express) + +pci:v00001360d00000306* + ID_MODEL_FROM_DATABASE=TCR180PEX IRIG Timecode Reader (PCI Express) + +pci:v00001360d00000501* + ID_MODEL_FROM_DATABASE=PTP270PEX PTP/IEEE1588 slave card (PCI Express) + +pci:v00001360d00000601* + ID_MODEL_FROM_DATABASE=FRC511PEX Free Running Clock (PCI Express) + +pci:v00001361* + ID_VENDOR_FROM_DATABASE=Soliton Systems K.K. + +pci:v00001362* + ID_VENDOR_FROM_DATABASE=Fujifacom Corporation + +pci:v00001363* + ID_VENDOR_FROM_DATABASE=Phoenix Technology Ltd + +pci:v00001364* + ID_VENDOR_FROM_DATABASE=ATM Communications Inc + +pci:v00001365* + ID_VENDOR_FROM_DATABASE=Hypercope GmbH + +pci:v00001366* + ID_VENDOR_FROM_DATABASE=Teijin Seiki Co. Ltd + +pci:v00001367* + ID_VENDOR_FROM_DATABASE=Hitachi Zosen Corporation + +pci:v00001368* + ID_VENDOR_FROM_DATABASE=Skyware Corporation + +pci:v00001369* + ID_VENDOR_FROM_DATABASE=Digigram + +pci:v0000136A* + ID_VENDOR_FROM_DATABASE=High Soft Tech + +pci:v0000136Ad00000004* + ID_MODEL_FROM_DATABASE=HST Saphir VII mini PCI + +pci:v0000136Ad00000007* + ID_MODEL_FROM_DATABASE=HST Saphir III E MultiLink 4 + +pci:v0000136Ad00000008* + ID_MODEL_FROM_DATABASE=HST Saphir III E MultiLink 8 + +pci:v0000136Ad0000000A* + ID_MODEL_FROM_DATABASE=HST Saphir III E MultiLink 2 + +pci:v0000136B* + ID_VENDOR_FROM_DATABASE=Kawasaki Steel Corporation + +pci:v0000136Bd0000FF01* + ID_MODEL_FROM_DATABASE=KL5A72002 Motion JPEG + +pci:v0000136C* + ID_VENDOR_FROM_DATABASE=Adtek System Science Co Ltd + +pci:v0000136D* + ID_VENDOR_FROM_DATABASE=Gigalabs Inc + +pci:v0000136F* + ID_VENDOR_FROM_DATABASE=Applied Magic Inc + +pci:v00001370* + ID_VENDOR_FROM_DATABASE=ATL Products + +pci:v00001371* + ID_VENDOR_FROM_DATABASE=CNet Technology Inc + +pci:v00001371d0000434E* + ID_MODEL_FROM_DATABASE=GigaCard Network Adapter + +pci:v00001371d0000434Esv00001371sd0000434E* + ID_MODEL_FROM_DATABASE=GigaCard Network Adapter (N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)) + +pci:v00001373* + ID_VENDOR_FROM_DATABASE=Silicon Vision Inc + +pci:v00001374* + ID_VENDOR_FROM_DATABASE=Silicom Ltd. + +pci:v00001374d00000024* + ID_MODEL_FROM_DATABASE=Silicom Dual port Giga Ethernet BGE Bypass Server Adapter + +pci:v00001374d00000025* + ID_MODEL_FROM_DATABASE=Silicom Quad port Giga Ethernet BGE Bypass Server Adapter + +pci:v00001374d00000026* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber Giga Ethernet 546 Bypass Server Adapter + +pci:v00001374d00000027* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber LX Giga Ethernet 546 Bypass Server Adapter + +pci:v00001374d00000029* + ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Giga Ethernet 546GB Bypass Server Adapter + +pci:v00001374d0000002A* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber Giga Ethernet 546 TAP/Bypass Server Adapter + +pci:v00001374d0000002B* + ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Fast Ethernet 546 TAP/Bypass Server Adapter (PXE2TBI) + +pci:v00001374d0000002C* + ID_MODEL_FROM_DATABASE=Silicom Quad port Copper Giga Ethernet 546GB Bypass Server Adapter (PXG4BPI) + +pci:v00001374d0000002D* + ID_MODEL_FROM_DATABASE=Silicom Quad port Fiber-SX Giga Ethernet 546GB Bypass Server Adapter (PXG4BPFI) + +pci:v00001374d0000002E* + ID_MODEL_FROM_DATABASE=Silicom Quad port Fiber-LX Giga Ethernet 546GB Bypass Server Adapter (PXG4BPFI-LX) + +pci:v00001374d0000002F* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber-SX Giga Ethernet 546GB Low profile Bypass Server Adapter (PXG2BPFIL) + +pci:v00001374d00000030* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber-LX Giga Ethernet 546GB Low profile Bypass Server Adapter + +pci:v00001374d00000031* + ID_MODEL_FROM_DATABASE=Silicom Quad port Copper Giga Ethernet PCI-E Bypass Server Adapter + +pci:v00001374d00000032* + ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Fast Ethernet 546 TAP/Bypass Server Adapter + +pci:v00001374d00000034* + ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Giga Ethernet PCI-E BGE Bypass Server Adapter + +pci:v00001374d00000035* + ID_MODEL_FROM_DATABASE=Silicom Quad port Copper Giga Ethernet PCI-E BGE Bypass Server Adapter + +pci:v00001374d00000036* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber Giga Ethernet PCI-E BGE Bypass Server Adapter + +pci:v00001374d00000037* + ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Ethernet PCI-E Intel based Bypass Server Adapter + +pci:v00001374d00000038* + ID_MODEL_FROM_DATABASE=Silicom Quad port Copper Ethernet PCI-E Intel based Bypass Server Adapter + +pci:v00001374d00000039* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber-SX Ethernet PCI-E Intel based Bypass Server Adapter + +pci:v00001374d0000003A* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber-LX Ethernet PCI-E Intel based Bypass Server Adapter + +pci:v00001374d0000003B* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber Ethernet PMC Intel based Bypass Server Adapter (PMCX2BPFI) + +pci:v00001374d0000003C* + ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Ethernet PCI-X BGE based Bypass Server Adapter (PXG2BPRB) + +pci:v00001374d0000003D* + ID_MODEL_FROM_DATABASE=2-port Copper GBE Bypass with Caviume 1010 PCI-X + +pci:v00001374d0000003E* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber Giga Ethernet PCI-E 571 TAP/Bypass Server Adapter (PEG2TBFI) + +pci:v00001374d0000003F* + ID_MODEL_FROM_DATABASE=Silicom Dual port Copper Giga Ethernet PCI-X 546 TAP/Bypass Server Adapter (PXG2TBI) + +pci:v00001374d00000040* + ID_MODEL_FROM_DATABASE=Silicom Quad port Fiber-SX Giga Ethernet 571 Bypass Server Adapter (PEG4BPFI) + +pci:v00001374d00000042* + ID_MODEL_FROM_DATABASE=4-port Copper GBE PMC-X Bypass + +pci:v00001374d00000043* + ID_MODEL_FROM_DATABASE=Silicom Quad port Fiber-SX Giga Ethernet 546 Bypass Server Adapter (PXG4BPFID) + +pci:v00001374d00000045* + ID_MODEL_FROM_DATABASE=Silicom 6 port Copper Giga Ethernet 546 Bypass Server Adapter (PXG6BPI) + +pci:v00001374d00000046* + ID_MODEL_FROM_DATABASE=4-port bypass PCI-E w disconnect low profile + +pci:v00001374d00000047* + ID_MODEL_FROM_DATABASE=Silicom Dual port Fiber-SX Giga Ethernet 571 Bypass Disconnect Server Adapter (PEG2BPFID) + +pci:v00001374d0000004A* + ID_MODEL_FROM_DATABASE=Silicom Quad port Fiber-LX Giga Ethernet 571 Bypass Server Adapter (PEG4BPFI-LX) + +pci:v00001374d0000004D* + ID_MODEL_FROM_DATABASE=Dual port Copper Giga Ethernet PCI-E Bypass Server Adapter + +pci:v00001374d00000401* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet ExpressModule Bypass Server Adapter + +pci:v00001374d00000420* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet ExpressModule Bypass Server Adapter + +pci:v00001374d00000460* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Express Module Bypass Server Adapter + +pci:v00001374d00000461* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet ExpressModule Bypass Server Adapter + +pci:v00001374d00000462* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet ExpressModule Bypass Server Adapter + +pci:v00001374d00000470* + ID_MODEL_FROM_DATABASE=Octal-port Copper Gigabit Ethernet Express Module Bypass Server Adapter + +pci:v00001374d00000482* + ID_MODEL_FROM_DATABASE=Dual-port Fiber (SR) 10 Gigabit Ethernet ExpressModule Bypass Server Adapter + +pci:v00001374d00000483* + ID_MODEL_FROM_DATABASE=Dual-port Fiber (LR) 10 Gigabit Ethernet ExpressModule Bypass Server Adapter + +pci:v00001375* + ID_VENDOR_FROM_DATABASE=Argosystems Inc + +pci:v00001376* + ID_VENDOR_FROM_DATABASE=LMC + +pci:v00001377* + ID_VENDOR_FROM_DATABASE=Electronic Equipment Production & Distribution GmbH + +pci:v00001378* + ID_VENDOR_FROM_DATABASE=Telemann Co. Ltd + +pci:v00001379* + ID_VENDOR_FROM_DATABASE=Asahi Kasei Microsystems Co Ltd + +pci:v0000137A* + ID_VENDOR_FROM_DATABASE=Mark of the Unicorn Inc + +pci:v0000137Ad00000001* + ID_MODEL_FROM_DATABASE=PCI-324 Audiowire Interface + +pci:v0000137B* + ID_VENDOR_FROM_DATABASE=PPT Vision + +pci:v0000137C* + ID_VENDOR_FROM_DATABASE=Iwatsu Electric Co Ltd + +pci:v0000137D* + ID_VENDOR_FROM_DATABASE=Dynachip Corporation + +pci:v0000137E* + ID_VENDOR_FROM_DATABASE=Patriot Scientific Corporation + +pci:v0000137F* + ID_VENDOR_FROM_DATABASE=Japan Satellite Systems Inc + +pci:v00001380* + ID_VENDOR_FROM_DATABASE=Sanritz Automation Co Ltd + +pci:v00001381* + ID_VENDOR_FROM_DATABASE=Brains Co. Ltd + +pci:v00001382* + ID_VENDOR_FROM_DATABASE=Marian - Electronic & Software + +pci:v00001382d00000001* + ID_MODEL_FROM_DATABASE=ARC88 audio recording card + +pci:v00001382d00002008* + ID_MODEL_FROM_DATABASE=Prodif 96 Pro sound system + +pci:v00001382d00002048* + ID_MODEL_FROM_DATABASE=Prodif Plus sound system + +pci:v00001382d00002088* + ID_MODEL_FROM_DATABASE=Marc 8 Midi sound system + +pci:v00001382d000020C8* + ID_MODEL_FROM_DATABASE=Marc A sound system + +pci:v00001382d00004008* + ID_MODEL_FROM_DATABASE=Marc 2 sound system + +pci:v00001382d00004010* + ID_MODEL_FROM_DATABASE=Marc 2 Pro sound system + +pci:v00001382d00004048* + ID_MODEL_FROM_DATABASE=Marc 4 MIDI sound system + +pci:v00001382d00004088* + ID_MODEL_FROM_DATABASE=Marc 4 Digi sound system + +pci:v00001382d00004248* + ID_MODEL_FROM_DATABASE=Marc X sound system + +pci:v00001382d00004424* + ID_MODEL_FROM_DATABASE=TRACE D4 Sound System + +pci:v00001383* + ID_VENDOR_FROM_DATABASE=Controlnet Inc + +pci:v00001384* + ID_VENDOR_FROM_DATABASE=Reality Simulation Systems Inc + +pci:v00001385* + ID_VENDOR_FROM_DATABASE=Netgear + +pci:v00001385d0000006B* + ID_MODEL_FROM_DATABASE=WA301 802.11b Wireless PCI Adapter + +pci:v00001385d00004100* + ID_MODEL_FROM_DATABASE=MA301 802.11b Wireless PCI Adapter + +pci:v00001385d00004601* + ID_MODEL_FROM_DATABASE=WAG511 802.11a/b/g Dual Band Wireless PC Card + +pci:v00001385d0000620A* + ID_MODEL_FROM_DATABASE=GA620 Gigabit Ethernet + +pci:v00001385d0000630A* + ID_MODEL_FROM_DATABASE=GA630 Gigabit Ethernet + +pci:v00001386* + ID_VENDOR_FROM_DATABASE=Video Domain Technologies + +pci:v00001387* + ID_VENDOR_FROM_DATABASE=Systran Corp + +pci:v00001388* + ID_VENDOR_FROM_DATABASE=Hitachi Information Technology Co Ltd + +pci:v00001389* + ID_VENDOR_FROM_DATABASE=Applicom International + +pci:v00001389d00000001* + ID_MODEL_FROM_DATABASE=PCI1500PFB [Intelligent fieldbus adaptor] + +pci:v0000138A* + ID_VENDOR_FROM_DATABASE=Fusion Micromedia Corp + +pci:v0000138Ad0000003D* + ID_MODEL_FROM_DATABASE=VFS491 Validity Sensor + +pci:v0000138B* + ID_VENDOR_FROM_DATABASE=Tokimec Inc + +pci:v0000138C* + ID_VENDOR_FROM_DATABASE=Silicon Reality + +pci:v0000138D* + ID_VENDOR_FROM_DATABASE=Future Techno Designs pte Ltd + +pci:v0000138E* + ID_VENDOR_FROM_DATABASE=Basler GmbH + +pci:v0000138F* + ID_VENDOR_FROM_DATABASE=Patapsco Designs Inc + +pci:v00001390* + ID_VENDOR_FROM_DATABASE=Concept Development Inc + +pci:v00001391* + ID_VENDOR_FROM_DATABASE=Development Concepts Inc + +pci:v00001392* + ID_VENDOR_FROM_DATABASE=Medialight Inc + +pci:v00001393* + ID_VENDOR_FROM_DATABASE=Moxa Technologies Co Ltd + +pci:v00001393d00000001* + ID_MODEL_FROM_DATABASE=UC7000 Serial + +pci:v00001393d00001020* + ID_MODEL_FROM_DATABASE=CP-102 (2-port RS-232 PCI) + +pci:v00001393d00001021* + ID_MODEL_FROM_DATABASE=CP-102UL (2-port RS-232 Universal PCI) + +pci:v00001393d00001022* + ID_MODEL_FROM_DATABASE=CP-102U (2-port RS-232 Universal PCI) + +pci:v00001393d00001023* + ID_MODEL_FROM_DATABASE=CP-102UF + +pci:v00001393d00001024* + ID_MODEL_FROM_DATABASE=CP-102E (2-port RS-232 Smart PCI Express Serial Board) + +pci:v00001393d00001025* + ID_MODEL_FROM_DATABASE=CP-102EL (2-port RS-232 Smart PCI Express Serial Board) + +pci:v00001393d00001040* + ID_MODEL_FROM_DATABASE=Smartio C104H/PCI + +pci:v00001393d00001041* + ID_MODEL_FROM_DATABASE=CP104U (4-port RS-232 Universal PCI) + +pci:v00001393d00001042* + ID_MODEL_FROM_DATABASE=CP104JU (4-port RS-232 Universal PCI) + +pci:v00001393d00001043* + ID_MODEL_FROM_DATABASE=CP104EL (4-port RS-232 Smart PCI Express) + +pci:v00001393d00001044* + ID_MODEL_FROM_DATABASE=POS104UL (4-port RS-232 Universal PCI) + +pci:v00001393d00001045* + ID_MODEL_FROM_DATABASE=CP-104EL-A (4-port RS-232 PCI Express Serial Board) + +pci:v00001393d00001080* + ID_MODEL_FROM_DATABASE=CB108 (8-port RS-232 PC/104-plus Module) + +pci:v00001393d00001140* + ID_MODEL_FROM_DATABASE=CT-114 series + +pci:v00001393d00001141* + ID_MODEL_FROM_DATABASE=Industrio CP-114 + +pci:v00001393d00001142* + ID_MODEL_FROM_DATABASE=CB114 (4-port RS-232/422/485 PC/104-plus Module) + +pci:v00001393d00001143* + ID_MODEL_FROM_DATABASE=CP-114UL (4-port RS-232/422/485 Smart Universal PCI Serial Board) + +pci:v00001393d00001144* + ID_MODEL_FROM_DATABASE=CP-114EL (4-port RS-232/422/485 Smart PCI Express Serial Board) + +pci:v00001393d00001180* + ID_MODEL_FROM_DATABASE=CP118U (8-port RS-232/422/485 Smart Universal PCI) + +pci:v00001393d00001181* + ID_MODEL_FROM_DATABASE=CP118EL (8-port RS-232/422/485 Smart PCI Express) + +pci:v00001393d00001182* + ID_MODEL_FROM_DATABASE=CP-118EL-A (8-port RS-232/422/485 PCI Express Serial Board) + +pci:v00001393d00001320* + ID_MODEL_FROM_DATABASE=CP132 (2-port RS-422/485 PCI) + +pci:v00001393d00001321* + ID_MODEL_FROM_DATABASE=CP132U (2-Port RS-422/485 Universal PCI) + +pci:v00001393d00001322* + ID_MODEL_FROM_DATABASE=CP-132EL (2-port RS-422/485 Smart PCI Express Serial Board) + +pci:v00001393d00001340* + ID_MODEL_FROM_DATABASE=CP134U (4-Port RS-422/485 Universal PCI) + +pci:v00001393d00001341* + ID_MODEL_FROM_DATABASE=CB134I (4-port RS-422/485 PC/104-plus Module) + +pci:v00001393d00001380* + ID_MODEL_FROM_DATABASE=CP138U (8-port RS-232/422/485 Smart Universal PCI) + +pci:v00001393d00001680* + ID_MODEL_FROM_DATABASE=Smartio C168H/PCI + +pci:v00001393d00001681* + ID_MODEL_FROM_DATABASE=CP-168U V2 Smart Serial Board (8-port RS-232) + +pci:v00001393d00001682* + ID_MODEL_FROM_DATABASE=CP-168EL (8-port RS-232 Smart PCI Express) + +pci:v00001393d00001683* + ID_MODEL_FROM_DATABASE=CP-168EL-A (8-port RS-232 PCI Express Serial Board) + +pci:v00001393d00002040* + ID_MODEL_FROM_DATABASE=Intellio CP-204J + +pci:v00001393d00002180* + ID_MODEL_FROM_DATABASE=Intellio C218 Turbo PCI + +pci:v00001393d00003200* + ID_MODEL_FROM_DATABASE=Intellio C320 Turbo PCI + +pci:v00001394* + ID_VENDOR_FROM_DATABASE=Level One Communications + +pci:v00001394d00000001* + ID_MODEL_FROM_DATABASE=LXT1001 Gigabit Ethernet + +pci:v00001394d00000001sv00001186sd00004800* + ID_MODEL_FROM_DATABASE=LXT1001 Gigabit Ethernet (DGE-500SX) + +pci:v00001394d00000001sv00001394sd00000001* + ID_MODEL_FROM_DATABASE=LXT1001 Gigabit Ethernet (NetCelerator Adapter) + +pci:v00001395* + ID_VENDOR_FROM_DATABASE=Ambicom Inc + +pci:v00001396* + ID_VENDOR_FROM_DATABASE=Cipher Systems Inc + +pci:v00001397* + ID_VENDOR_FROM_DATABASE=Cologne Chip Designs GmbH + +pci:v00001397d000008B4* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] + +pci:v00001397d000008B4sv00001397sd000008B4* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Cologne Chip HFC-4S Eval. Board]) + +pci:v00001397d000008B4sv00001397sd0000B51A* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Allo.com BRI card]) + +pci:v00001397d000008B4sv00001397sd0000B520* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [IOB4ST]) + +pci:v00001397d000008B4sv00001397sd0000B540* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Swyx SX2 QuadBri]) + +pci:v00001397d000008B4sv00001397sd0000B550* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Junghanns.NET quadBRI]) + +pci:v00001397d000008B4sv00001397sd0000B556* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Junghanns.NET duoBRI]) + +pci:v00001397d000008B4sv00001397sd0000B559* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Junghanns.NET duoBRI miniPCI]) + +pci:v00001397d000008B4sv00001397sd0000B560* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN4S0]) + +pci:v00001397d000008B4sv00001397sd0000B566* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN2S0]) + +pci:v00001397d000008B4sv00001397sd0000B567* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN1S0 miniPCI]) + +pci:v00001397d000008B4sv00001397sd0000B568* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN4S0 miniPCI]) + +pci:v00001397d000008B4sv00001397sd0000B569* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN2S0 miniPCI]) + +pci:v00001397d000008B4sv00001397sd0000B620* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S) + +pci:v00001397d000008B4sv00001397sd0000B752* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [Junghanns.NET quadBRI PCIe]) + +pci:v00001397d000008B4sv00001397sd0000B761* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN2S0 PCIe]) + +pci:v00001397d000008B4sv00001397sd0000B762* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [BeroNet BN4S0 PCIe]) + +pci:v00001397d000008B4sv00001397sd0000E884* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [OpenVox B200P]) + +pci:v00001397d000008B4sv00001397sd0000E888* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-4S] (HFC-4S [OpenVox B200P / B400P]) + +pci:v00001397d000016B8* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] + +pci:v00001397d000016B8sv00001397sd000016B8* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [Cologne Chip HFC-8S Eval. Board]) + +pci:v00001397d000016B8sv00001397sd0000B521* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [IOB4ST Recording]) + +pci:v00001397d000016B8sv00001397sd0000B522* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [IOB8ST]) + +pci:v00001397d000016B8sv00001397sd0000B552* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [Junghanns.NET octoBRI]) + +pci:v00001397d000016B8sv00001397sd0000B55B* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [Junghanns.NET octoBRI]) + +pci:v00001397d000016B8sv00001397sd0000B562* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [BeroNet BN8S0]) + +pci:v00001397d000016B8sv00001397sd0000B56B* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [BeroNet BN8S0+]) + +pci:v00001397d000016B8sv00001397sd0000B622* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S) + +pci:v00001397d000016B8sv00001397sd0000E998* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-8S] (HFC-8S [OpenVox B800P]) + +pci:v00001397d00002BD0* + ID_MODEL_FROM_DATABASE=ISDN network controller [HFC-PCI] + +pci:v00001397d00002BD0sv00000675sd00001704* + ID_MODEL_FROM_DATABASE=ISDN network controller [HFC-PCI] (ISDN Adapter (PCI Bus, D, C)) + +pci:v00001397d00002BD0sv00000675sd00001708* + ID_MODEL_FROM_DATABASE=ISDN network controller [HFC-PCI] (ISDN Adapter (PCI Bus, D, C, ACPI)) + +pci:v00001397d00002BD0sv00001397sd00002BD0* + ID_MODEL_FROM_DATABASE=ISDN network controller [HFC-PCI] (ISDN Board) + +pci:v00001397d00002BD0sv0000E4BFsd00001000* + ID_MODEL_FROM_DATABASE=ISDN network controller [HFC-PCI] (CI1-1-Harp) + +pci:v00001397d000030B1* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] + +pci:v00001397d000030B1sv00001397sd000030B1* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Cologne Chip HFC-E1 Eval. Board]) + +pci:v00001397d000030B1sv00001397sd0000B523* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [IOB1E1]) + +pci:v00001397d000030B1sv00001397sd0000B543* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Swyx SX2 SinglePRI V2]) + +pci:v00001397d000030B1sv00001397sd0000B544* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Swyx SX2 DualPRI V2]) + +pci:v00001397d000030B1sv00001397sd0000B553* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Junghanns.NET singleE1]) + +pci:v00001397d000030B1sv00001397sd0000B554* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Junghanns.NET doubleE1]) + +pci:v00001397d000030B1sv00001397sd0000B555* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Junghanns.NET doubleE1 2.0]) + +pci:v00001397d000030B1sv00001397sd0000B55A* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [Junghanns.NET singleE1 miniPCI]) + +pci:v00001397d000030B1sv00001397sd0000B563* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [beroNet BN1E1]) + +pci:v00001397d000030B1sv00001397sd0000B564* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [beroNet BN2E1]) + +pci:v00001397d000030B1sv00001397sd0000B565* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [beroNet BN2E1+]) + +pci:v00001397d000030B1sv00001397sd0000B56A* + ID_MODEL_FROM_DATABASE=ISDN network Controller [HFC-E1] (HFC-E1 [beroNet BN1E1 miniPCI]) + +pci:v00001397d0000B700* + ID_MODEL_FROM_DATABASE=ISDN network controller PrimuX S0 [HFC-PCI] + +pci:v00001397d0000F001* + ID_MODEL_FROM_DATABASE=GSM Network Controller [HFC-4GSM] + +pci:v00001398* + ID_VENDOR_FROM_DATABASE=Clarion co. Ltd + +pci:v00001399* + ID_VENDOR_FROM_DATABASE=Rios systems Co Ltd + +pci:v0000139A* + ID_VENDOR_FROM_DATABASE=Alacritech Inc + +pci:v0000139Ad00000001* + ID_MODEL_FROM_DATABASE=Quad Port 10/100 Server Accelerator + +pci:v0000139Ad00000003* + ID_MODEL_FROM_DATABASE=Single Port 10/100 Server Accelerator + +pci:v0000139Ad00000005* + ID_MODEL_FROM_DATABASE=Single Port Gigabit Server Accelerator + +pci:v0000139B* + ID_VENDOR_FROM_DATABASE=Mediasonic Multimedia Systems Ltd + +pci:v0000139C* + ID_VENDOR_FROM_DATABASE=Quantum 3d Inc + +pci:v0000139D* + ID_VENDOR_FROM_DATABASE=EPL limited + +pci:v0000139E* + ID_VENDOR_FROM_DATABASE=Media4 + +pci:v0000139F* + ID_VENDOR_FROM_DATABASE=Aethra s.r.l. + +pci:v000013A0* + ID_VENDOR_FROM_DATABASE=Crystal Group Inc + +pci:v000013A1* + ID_VENDOR_FROM_DATABASE=Kawasaki Heavy Industries Ltd + +pci:v000013A2* + ID_VENDOR_FROM_DATABASE=Ositech Communications Inc + +pci:v000013A3* + ID_VENDOR_FROM_DATABASE=Hifn Inc. + +pci:v000013A3d00000005* + ID_MODEL_FROM_DATABASE=7751 Security Processor + +pci:v000013A3d00000006* + ID_MODEL_FROM_DATABASE=6500 Public Key Processor + +pci:v000013A3d00000007* + ID_MODEL_FROM_DATABASE=7811 Security Processor + +pci:v000013A3d00000012* + ID_MODEL_FROM_DATABASE=7951 Security Processor + +pci:v000013A3d00000014* + ID_MODEL_FROM_DATABASE=78XX Security Processor + +pci:v000013A3d00000016* + ID_MODEL_FROM_DATABASE=8065 Security Processor + +pci:v000013A3d00000017* + ID_MODEL_FROM_DATABASE=8165 Security Processor + +pci:v000013A3d00000018* + ID_MODEL_FROM_DATABASE=8154 Security Processor + +pci:v000013A3d0000001D* + ID_MODEL_FROM_DATABASE=7956 Security Processor + +pci:v000013A3d0000001F* + ID_MODEL_FROM_DATABASE=7855 Security Processor + +pci:v000013A3d00000020* + ID_MODEL_FROM_DATABASE=7955 Security Processor + +pci:v000013A3d00000026* + ID_MODEL_FROM_DATABASE=8155 Security Processor + +pci:v000013A3d0000002E* + ID_MODEL_FROM_DATABASE=9630 Compression Processor + +pci:v000013A3d0000002F* + ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor + +pci:v000013A3d0000002Fsv000013A3sd00001600* + ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1600 Acceleration Card) + +pci:v000013A3d0000002Fsv000013A3sd00001605* + ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1605 Acceleration Card) + +pci:v000013A3d0000002Fsv000013A3sd00001610* + ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1610 Acceleration Card) + +pci:v000013A3d0000002Fsv000013A3sd00001615* + ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1615 Acceleration Card) + +pci:v000013A3d0000002Fsv000013A3sd00001620* + ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1620 Acceleration Card) + +pci:v000013A3d0000002Fsv000013A3sd00001625* + ID_MODEL_FROM_DATABASE=9725 Compression and Security Processor (DR1625 Acceleration Card) + +pci:v000013A3d00000033* + ID_MODEL_FROM_DATABASE=8201 Acceleration Processor + +pci:v000013A3d00000033sv000013A3sd00000036* + ID_MODEL_FROM_DATABASE=8201 Acceleration Processor (DX1710 Acceleration Card) + +pci:v000013A3d00000034* + ID_MODEL_FROM_DATABASE=8202 Acceleration Processor + +pci:v000013A3d00000034sv000013A3sd00000036* + ID_MODEL_FROM_DATABASE=8202 Acceleration Processor (DX1720 Acceleration Card) + +pci:v000013A3d00000035* + ID_MODEL_FROM_DATABASE=8203 Acceleration Processor + +pci:v000013A3d00000035sv000013A3sd00000036* + ID_MODEL_FROM_DATABASE=8203 Acceleration Processor (DX1730 Acceleration Card) + +pci:v000013A3d00000037* + ID_MODEL_FROM_DATABASE=8204 Acceleration Processor + +pci:v000013A3d00000037sv000013A3sd00000036* + ID_MODEL_FROM_DATABASE=8204 Acceleration Processor (DX1740 Acceleration Card) + +pci:v000013A4* + ID_VENDOR_FROM_DATABASE=Rascom Inc + +pci:v000013A5* + ID_VENDOR_FROM_DATABASE=Audio Digital Imaging Inc + +pci:v000013A6* + ID_VENDOR_FROM_DATABASE=Videonics Inc + +pci:v000013A7* + ID_VENDOR_FROM_DATABASE=Teles AG + +pci:v000013A8* + ID_VENDOR_FROM_DATABASE=Exar Corp. + +pci:v000013A8d00000152* + ID_MODEL_FROM_DATABASE=XR17C/D152 Dual PCI UART + +pci:v000013A8d00000154* + ID_MODEL_FROM_DATABASE=XR17C154 Quad UART + +pci:v000013A8d00000158* + ID_MODEL_FROM_DATABASE=XR17C158 Octal UART + +pci:v000013A8d00000252* + ID_MODEL_FROM_DATABASE=XR17V252 Dual UART PCI controller + +pci:v000013A8d00000254* + ID_MODEL_FROM_DATABASE=XR17V254 Quad UART PCI controller + +pci:v000013A8d00000258* + ID_MODEL_FROM_DATABASE=XR17V258 Octal UART PCI controller + +pci:v000013A8d00000352* + ID_MODEL_FROM_DATABASE=XR17V3521 Dual PCIe UART + +pci:v000013A9* + ID_VENDOR_FROM_DATABASE=Siemens Medical Systems, Ultrasound Group + +pci:v000013AA* + ID_VENDOR_FROM_DATABASE=Broadband Networks Inc + +pci:v000013AB* + ID_VENDOR_FROM_DATABASE=Arcom Control Systems Ltd + +pci:v000013AC* + ID_VENDOR_FROM_DATABASE=Motion Media Technology Ltd + +pci:v000013AD* + ID_VENDOR_FROM_DATABASE=Nexus Inc + +pci:v000013AE* + ID_VENDOR_FROM_DATABASE=ALD Technology Ltd + +pci:v000013AF* + ID_VENDOR_FROM_DATABASE=T.Sqware + +pci:v000013B0* + ID_VENDOR_FROM_DATABASE=Maxspeed Corp + +pci:v000013B1* + ID_VENDOR_FROM_DATABASE=Tamura corporation + +pci:v000013B2* + ID_VENDOR_FROM_DATABASE=Techno Chips Co. Ltd + +pci:v000013B3* + ID_VENDOR_FROM_DATABASE=Lanart Corporation + +pci:v000013B4* + ID_VENDOR_FROM_DATABASE=Wellbean Co Inc + +pci:v000013B5* + ID_VENDOR_FROM_DATABASE=ARM + +pci:v000013B6* + ID_VENDOR_FROM_DATABASE=Dlog GmbH + +pci:v000013B7* + ID_VENDOR_FROM_DATABASE=Logic Devices Inc + +pci:v000013B8* + ID_VENDOR_FROM_DATABASE=Nokia Telecommunications oy + +pci:v000013B9* + ID_VENDOR_FROM_DATABASE=Elecom Co Ltd + +pci:v000013BA* + ID_VENDOR_FROM_DATABASE=Oxford Instruments + +pci:v000013BB* + ID_VENDOR_FROM_DATABASE=Sanyo Technosound Co Ltd + +pci:v000013BC* + ID_VENDOR_FROM_DATABASE=Bitran Corporation + +pci:v000013BD* + ID_VENDOR_FROM_DATABASE=Sharp corporation + +pci:v000013BE* + ID_VENDOR_FROM_DATABASE=Miroku Jyoho Service Co. Ltd + +pci:v000013BF* + ID_VENDOR_FROM_DATABASE=Sharewave Inc + +pci:v000013C0* + ID_VENDOR_FROM_DATABASE=Microgate Corporation + +pci:v000013C0d00000010* + ID_MODEL_FROM_DATABASE=SyncLink Adapter v1 + +pci:v000013C0d00000020* + ID_MODEL_FROM_DATABASE=SyncLink SCC Adapter + +pci:v000013C0d00000030* + ID_MODEL_FROM_DATABASE=SyncLink Multiport Adapter + +pci:v000013C0d00000070* + ID_MODEL_FROM_DATABASE=SyncLink GT Adapter + +pci:v000013C0d00000080* + ID_MODEL_FROM_DATABASE=SyncLink GT4 Adapter + +pci:v000013C0d000000A0* + ID_MODEL_FROM_DATABASE=SyncLink GT2 Adapter + +pci:v000013C0d00000210* + ID_MODEL_FROM_DATABASE=SyncLink Adapter v2 + +pci:v000013C1* + ID_VENDOR_FROM_DATABASE=3ware Inc + +pci:v000013C1d00001000* + ID_MODEL_FROM_DATABASE=5xxx/6xxx-series PATA-RAID + +pci:v000013C1d00001001* + ID_MODEL_FROM_DATABASE=7xxx/8xxx-series PATA/SATA-RAID + +pci:v000013C1d00001001sv000013C1sd00001001* + ID_MODEL_FROM_DATABASE=7xxx/8xxx-series PATA/SATA-RAID + +pci:v000013C1d00001002* + ID_MODEL_FROM_DATABASE=9xxx-series SATA-RAID + +pci:v000013C1d00001003* + ID_MODEL_FROM_DATABASE=9550SX SATA-II RAID PCI-X + +pci:v000013C1d00001004* + ID_MODEL_FROM_DATABASE=9650SE SATA-II RAID PCIe + +pci:v000013C1d00001005* + ID_MODEL_FROM_DATABASE=9690SA SAS/SATA-II RAID PCIe + +pci:v000013C1d00001010* + ID_MODEL_FROM_DATABASE=9750 SAS2/SATA-II RAID PCIe + +pci:v000013C2* + ID_VENDOR_FROM_DATABASE=Technotrend Systemtechnik GmbH + +pci:v000013C2d0000000E* + ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge DVB card rev2.3 + +pci:v000013C2d00001019* + ID_MODEL_FROM_DATABASE=TTechnoTrend-budget DVB S2-3200 + +pci:v000013C3* + ID_VENDOR_FROM_DATABASE=Janz Computer AG + +pci:v000013C4* + ID_VENDOR_FROM_DATABASE=Phase Metrics + +pci:v000013C5* + ID_VENDOR_FROM_DATABASE=Alphi Technology Corp + +pci:v000013C6* + ID_VENDOR_FROM_DATABASE=Condor Engineering Inc + +pci:v000013C6d00000520* + ID_MODEL_FROM_DATABASE=CEI-520 A429 Card + +pci:v000013C6d00000620* + ID_MODEL_FROM_DATABASE=CEI-620 A429 Card + +pci:v000013C6d00000820* + ID_MODEL_FROM_DATABASE=CEI-820 A429 Card + +pci:v000013C6d00000830* + ID_MODEL_FROM_DATABASE=CEI-830 A429 Card + +pci:v000013C6d00001004* + ID_MODEL_FROM_DATABASE=P-SER Multi-channel PMC to RS-485/422/232 adapter + +pci:v000013C7* + ID_VENDOR_FROM_DATABASE=Blue Chip Technology Ltd + +pci:v000013C7d00000ADC* + ID_MODEL_FROM_DATABASE=PCI-ADC + +pci:v000013C7d00000B10* + ID_MODEL_FROM_DATABASE=PCI-PIO + +pci:v000013C7d00000D10* + ID_MODEL_FROM_DATABASE=PCI-DIO + +pci:v000013C7d0000524C* + ID_MODEL_FROM_DATABASE=PCI-RLY + +pci:v000013C7d00005744* + ID_MODEL_FROM_DATABASE=PCI-WDT + +pci:v000013C8* + ID_VENDOR_FROM_DATABASE=Apptech Inc + +pci:v000013C9* + ID_VENDOR_FROM_DATABASE=Eaton Corporation + +pci:v000013CA* + ID_VENDOR_FROM_DATABASE=Iomega Corporation + +pci:v000013CB* + ID_VENDOR_FROM_DATABASE=Yano Electric Co Ltd + +pci:v000013CC* + ID_VENDOR_FROM_DATABASE=Metheus Corporation + +pci:v000013CD* + ID_VENDOR_FROM_DATABASE=Compatible Systems Corporation + +pci:v000013CE* + ID_VENDOR_FROM_DATABASE=Cocom A/S + +pci:v000013CF* + ID_VENDOR_FROM_DATABASE=Studio Audio & Video Ltd + +pci:v000013D0* + ID_VENDOR_FROM_DATABASE=Techsan Electronics Co Ltd + +pci:v000013D0d00002103* + ID_MODEL_FROM_DATABASE=B2C2 FlexCopII DVB chip / Technisat SkyStar2 DVB card + +pci:v000013D0d00002104* + ID_MODEL_FROM_DATABASE=B2C2 FlexCopIII DVB chip / Technisat SkyStar2 DVB card (rev 01) + +pci:v000013D0d00002200* + ID_MODEL_FROM_DATABASE=B2C2 FlexCopIII DVB chip / Technisat SkyStar2 DVB card + +pci:v000013D1* + ID_VENDOR_FROM_DATABASE=Abocom Systems Inc + +pci:v000013D1d0000AB02* + ID_MODEL_FROM_DATABASE=ADMtek Centaur-C rev 17 [D-Link DFE-680TX] CardBus Fast Ethernet Adapter + +pci:v000013D1d0000AB03* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v000013D1d0000AB06* + ID_MODEL_FROM_DATABASE=RTL8139 [FE2000VX] CardBus Fast Ethernet Attached Port Adapter + +pci:v000013D1d0000AB08* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v000013D2* + ID_VENDOR_FROM_DATABASE=Shark Multimedia Inc + +pci:v000013D4* + ID_VENDOR_FROM_DATABASE=Graphics Microsystems Inc + +pci:v000013D5* + ID_VENDOR_FROM_DATABASE=Media 100 Inc + +pci:v000013D6* + ID_VENDOR_FROM_DATABASE=K.I. Technology Co Ltd + +pci:v000013D7* + ID_VENDOR_FROM_DATABASE=Toshiba Engineering Corporation + +pci:v000013D8* + ID_VENDOR_FROM_DATABASE=Phobos corporation + +pci:v000013D9* + ID_VENDOR_FROM_DATABASE=Apex PC Solutions Inc + +pci:v000013DA* + ID_VENDOR_FROM_DATABASE=Intresource Systems pte Ltd + +pci:v000013DB* + ID_VENDOR_FROM_DATABASE=Janich & Klass Computertechnik GmbH + +pci:v000013DC* + ID_VENDOR_FROM_DATABASE=Netboost Corporation + +pci:v000013DD* + ID_VENDOR_FROM_DATABASE=Multimedia Bundle Inc + +pci:v000013DE* + ID_VENDOR_FROM_DATABASE=ABB Robotics Products AB + +pci:v000013DF* + ID_VENDOR_FROM_DATABASE=E-Tech Inc + +pci:v000013DFd00000001* + ID_MODEL_FROM_DATABASE=PCI56RVP Modem + +pci:v000013DFd00000001sv000013DFsd00000001* + ID_MODEL_FROM_DATABASE=PCI56RVP Modem + +pci:v000013E0* + ID_VENDOR_FROM_DATABASE=GVC Corporation + +pci:v000013E1* + ID_VENDOR_FROM_DATABASE=Silicom Multimedia Systems Inc + +pci:v000013E2* + ID_VENDOR_FROM_DATABASE=Dynamics Research Corporation + +pci:v000013E3* + ID_VENDOR_FROM_DATABASE=Nest Inc + +pci:v000013E4* + ID_VENDOR_FROM_DATABASE=Calculex Inc + +pci:v000013E5* + ID_VENDOR_FROM_DATABASE=Telesoft Design Ltd + +pci:v000013E6* + ID_VENDOR_FROM_DATABASE=Argosy research Inc + +pci:v000013E7* + ID_VENDOR_FROM_DATABASE=NAC Incorporated + +pci:v000013E8* + ID_VENDOR_FROM_DATABASE=Chip Express Corporation + +pci:v000013E9* + ID_VENDOR_FROM_DATABASE=Intraserver Technology Inc + +pci:v000013EA* + ID_VENDOR_FROM_DATABASE=Dallas Semiconductor + +pci:v000013EB* + ID_VENDOR_FROM_DATABASE=Hauppauge Computer Works Inc + +pci:v000013EC* + ID_VENDOR_FROM_DATABASE=Zydacron Inc + +pci:v000013ECd0000000A* + ID_MODEL_FROM_DATABASE=NPC-RC01 Remote control receiver + +pci:v000013ED* + ID_VENDOR_FROM_DATABASE=Raytheion E-Systems + +pci:v000013EE* + ID_VENDOR_FROM_DATABASE=Hayes Microcomputer Products Inc + +pci:v000013EF* + ID_VENDOR_FROM_DATABASE=Coppercom Inc + +pci:v000013F0* + ID_VENDOR_FROM_DATABASE=Sundance Technology Inc / IC Plus Corp + +pci:v000013F0d00000200* + ID_MODEL_FROM_DATABASE=IC Plus IP100A Integrated 10/100 Ethernet MAC + PHY + +pci:v000013F0d00000200sv00001043sd00008213* + ID_MODEL_FROM_DATABASE=IC Plus IP100A Integrated 10/100 Ethernet MAC + PHY (NX1001) + +pci:v000013F0d00000201* + ID_MODEL_FROM_DATABASE=ST201 Sundance Ethernet + +pci:v000013F0d00001021* + ID_MODEL_FROM_DATABASE=TC902x Gigabit Ethernet + +pci:v000013F0d00001023* + ID_MODEL_FROM_DATABASE=IP1000 Family Gigabit Ethernet + +pci:v000013F0d00001023sv00001043sd00008180* + ID_MODEL_FROM_DATABASE=IP1000 Family Gigabit Ethernet (NX1101) + +pci:v000013F1* + ID_VENDOR_FROM_DATABASE=Oce' - Technologies B.V. + +pci:v000013F2* + ID_VENDOR_FROM_DATABASE=Ford Microelectronics Inc + +pci:v000013F3* + ID_VENDOR_FROM_DATABASE=Mcdata Corporation + +pci:v000013F4* + ID_VENDOR_FROM_DATABASE=Troika Networks, Inc. + +pci:v000013F4d00001401* + ID_MODEL_FROM_DATABASE=Zentai Fibre Channel Adapter + +pci:v000013F5* + ID_VENDOR_FROM_DATABASE=Kansai Electric Co. Ltd + +pci:v000013F6* + ID_VENDOR_FROM_DATABASE=C-Media Electronics Inc + +pci:v000013F6d00000011* + ID_MODEL_FROM_DATABASE=CMI8738 + +pci:v000013F6d00000100* + ID_MODEL_FROM_DATABASE=CM8338A + +pci:v000013F6d00000100sv000013F6sd0000FFFF* + ID_MODEL_FROM_DATABASE=CM8338A (CMI8338/C3DX PCI Audio Device) + +pci:v000013F6d00000101* + ID_MODEL_FROM_DATABASE=CM8338B + +pci:v000013F6d00000101sv000013F6sd00000101* + ID_MODEL_FROM_DATABASE=CM8338B (CMI8338-031 PCI Audio Device) + +pci:v000013F6d00000111* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio + +pci:v000013F6d00000111sv00001019sd00000970* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (P6STP-FL motherboard) + +pci:v000013F6d00000111sv00001043sd00008035* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (CUSI-FX motherboard) + +pci:v000013F6d00000111sv00001043sd00008077* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (CMI8738 6-channel audio controller) + +pci:v000013F6d00000111sv00001043sd000080E2* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (CMI8738 6ch-MX) + +pci:v000013F6d00000111sv000013F6sd00000111* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (CMI8738/C3DX PCI Audio Device) + +pci:v000013F6d00000111sv000013F6sd00009761* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Theatron Agrippa) + +pci:v000013F6d00000111sv0000153Bsd00001144* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Aureon 5.1) + +pci:v000013F6d00000111sv0000153Bsd00001170* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Aureon 7.1) + +pci:v000013F6d00000111sv00001681sd0000A000* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Gamesurround MUSE XL) + +pci:v000013F6d00000111sv000017ABsd00000604* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (PSC604 Dynamic Edge) + +pci:v000013F6d00000111sv000017ABsd00000605* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (PSC605 Sonic Edge) + +pci:v000013F6d00000111sv000017ABsd00007777* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (PSC605 Sonic Edge) + +pci:v000013F6d00000111sv0000270Fsd00001103* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (CT-7NJS Ultra motherboard) + +pci:v000013F6d00000111sv0000270Fsd0000F462* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (7NJL1 motherboard) + +pci:v000013F6d00000111sv0000584Dsd00003731* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Digital X-Mystique) + +pci:v000013F6d00000111sv0000584Dsd00003741* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (X-Plosion 7.1) + +pci:v000013F6d00000111sv0000584Dsd00003751* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (X-Raider 7.1) + +pci:v000013F6d00000111sv0000584Dsd00003761* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (X-Mystique 7.1 LP) + +pci:v000013F6d00000111sv0000584Dsd00003771* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (X-Mystique 7.1 LP Value) + +pci:v000013F6d00000111sv00007284sd00008384* + ID_MODEL_FROM_DATABASE=CMI8738/CMI8768 PCI Audio (Striker 7.1) + +pci:v000013F6d00000211* + ID_MODEL_FROM_DATABASE=CM8738 + +pci:v000013F6d00005011* + ID_MODEL_FROM_DATABASE=CM8888 [Oxygen Express] + +pci:v000013F6d00005011sv000013F6sd00005011* + ID_MODEL_FROM_DATABASE=CM8888 [Oxygen Express] (HDA Controller) + +pci:v000013F6d00008788* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] + +pci:v000013F6d00008788sv00001043sd00008269* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 200 (Xonar D2)) + +pci:v000013F6d00008788sv00001043sd00008275* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar DX)) + +pci:v000013F6d00008788sv00001043sd000082B7* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 200 (Xonar D2X)) + +pci:v000013F6d00008788sv00001043sd00008314* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 200 (Xonar HDAV1.3)) + +pci:v000013F6d00008788sv00001043sd00008327* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar DX)) + +pci:v000013F6d00008788sv00001043sd0000834F* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar D1)) + +pci:v000013F6d00008788sv00001043sd0000835C* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar Essence STX)) + +pci:v000013F6d00008788sv00001043sd0000835D* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar ST)) + +pci:v000013F6d00008788sv00001043sd0000835E* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 200 (Xonar HDAV1.3 Slim)) + +pci:v000013F6d00008788sv00001043sd0000838E* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 66 (Xonar DS)) + +pci:v000013F6d00008788sv00001043sd00008428* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar Xense)) + +pci:v000013F6d00008788sv00001043sd00008467* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CMI8786 (Xonar DG)) + +pci:v000013F6d00008788sv00001043sd00008521* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CMI8786 (Xonar DGX)) + +pci:v000013F6d00008788sv00001043sd00008522* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Xonar DSX) + +pci:v000013F6d00008788sv00001043sd000085F4* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Virtuoso 100 (Xonar Essence STX II)) + +pci:v000013F6d00008788sv000013F6sd00008782* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (PCI 2.0 HD Audio) + +pci:v000013F6d00008788sv000013F6sd0000FFFF* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CMI8787-HG2PCI) + +pci:v000013F6d00008788sv000014C3sd00001710* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (HiFier Fantasia) + +pci:v000013F6d00008788sv000014C3sd00001711* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (HiFier Serenade) + +pci:v000013F6d00008788sv000014C3sd00001713* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (HiFier Serenade III) + +pci:v000013F6d00008788sv00001A58sd00000910* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (Barracuda AC-1) + +pci:v000013F6d00008788sv0000415Asd00005431* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (X-Meridian 7.1) + +pci:v000013F6d00008788sv00005431sd0000017A* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (X-Meridian 7.1 2G) + +pci:v000013F6d00008788sv0000584Dsd00003781* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (HDA X-Purity 7.1 Platinum) + +pci:v000013F6d00008788sv00007284sd00009761* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CLARO) + +pci:v000013F6d00008788sv00007284sd00009781* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CLARO halo) + +pci:v000013F6d00008788sv00007284sd00009783* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (eCLARO) + +pci:v000013F6d00008788sv00007284sd00009787* + ID_MODEL_FROM_DATABASE=CMI8788 [Oxygen HD Audio] (CLARO II) + +pci:v000013F7* + ID_VENDOR_FROM_DATABASE=Wildfire Communications + +pci:v000013F8* + ID_VENDOR_FROM_DATABASE=Ad Lib Multimedia Inc + +pci:v000013F9* + ID_VENDOR_FROM_DATABASE=NTT Advanced Technology Corp. + +pci:v000013FA* + ID_VENDOR_FROM_DATABASE=Pentland Systems Ltd + +pci:v000013FB* + ID_VENDOR_FROM_DATABASE=Aydin Corp + +pci:v000013FC* + ID_VENDOR_FROM_DATABASE=Computer Peripherals International + +pci:v000013FD* + ID_VENDOR_FROM_DATABASE=Micro Science Inc + +pci:v000013FE* + ID_VENDOR_FROM_DATABASE=Advantech Co. Ltd + +pci:v000013FEd00001240* + ID_MODEL_FROM_DATABASE=PCI-1240 4-channel stepper motor controller card + +pci:v000013FEd00001600* + ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 0) + +pci:v000013FEd00001600sv00001601sd00000002* + ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 0) (PCI-1601 2-port unisolated RS-422/485) + +pci:v000013FEd00001600sv00001602sd00000002* + ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 0) (PCI-1602 2-port isolated RS-422/485) + +pci:v000013FEd00001600sv00001612sd00000004* + ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 0) (PCI-1612 4-port RS-232/422/485) + +pci:v000013FEd00001603* + ID_MODEL_FROM_DATABASE=PCI-1603 2-port isolated RS-232/current loop + +pci:v000013FEd00001604* + ID_MODEL_FROM_DATABASE=PCI-1604 2-port RS-232 + +pci:v000013FEd00001680* + ID_MODEL_FROM_DATABASE=PCI-1680 Rev.A1 2-port CAN-bus with isolation protection + +pci:v000013FEd000016FF* + ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 1: RX/TX steering CPLD) + +pci:v000013FEd000016FFsv00001601sd00000000* + ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 1: RX/TX steering CPLD) (PCI-1601 2-port unisolated RS-422/485 PCI communications card) + +pci:v000013FEd000016FFsv00001602sd00000000* + ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 1: RX/TX steering CPLD) (PCI-1602 2-port isolated RS-422/485) + +pci:v000013FEd000016FFsv00001612sd00000000* + ID_MODEL_FROM_DATABASE=PCI-16xx series PCI multiport serial board (function 1: RX/TX steering CPLD) (PCI-1612 4-port RS-232/422/485) + +pci:v000013FEd00001711* + ID_MODEL_FROM_DATABASE=PCI-1711 16-channel data acquisition card 12-bit, 100kS/s + +pci:v000013FEd00001713* + ID_MODEL_FROM_DATABASE=PCI-1713 32-channel isolated analog input card + +pci:v000013FEd00001733* + ID_MODEL_FROM_DATABASE=PCI-1733 32-channel isolated digital input card + +pci:v000013FEd00001734* + ID_MODEL_FROM_DATABASE=PCI-1734 32-channel isolated digital output card + +pci:v000013FEd00001752* + ID_MODEL_FROM_DATABASE=PCI-1752 64-channel Isolated Digital Output Card + +pci:v000013FEd00001754* + ID_MODEL_FROM_DATABASE=PCI-1754 64-channel Isolated Digital Input Card + +pci:v000013FEd00001756* + ID_MODEL_FROM_DATABASE=PCI-1756 64-ch Isolated Digital I/O PCI Card + +pci:v000013FEd0000A004* + ID_MODEL_FROM_DATABASE=PCI-1612 4-port RS-232/422/485 + +pci:v000013FEd0000C302* + ID_MODEL_FROM_DATABASE=MIOe-3680 2-Port CAN-Bus MIOe Module with Isolation Protection + +pci:v000013FF* + ID_VENDOR_FROM_DATABASE=Silicon Spice Inc + +pci:v00001400* + ID_VENDOR_FROM_DATABASE=Artx Inc + +pci:v00001400d00001401* + ID_MODEL_FROM_DATABASE=9432 TX + +pci:v00001401* + ID_VENDOR_FROM_DATABASE=CR-Systems A/S + +pci:v00001402* + ID_VENDOR_FROM_DATABASE=Meilhaus Electronic GmbH + +pci:v00001402d00000630* + ID_MODEL_FROM_DATABASE=ME-630 + +pci:v00001402d00000940* + ID_MODEL_FROM_DATABASE=ME-94 + +pci:v00001402d00000950* + ID_MODEL_FROM_DATABASE=ME-95 + +pci:v00001402d00000960* + ID_MODEL_FROM_DATABASE=ME-96 + +pci:v00001402d00001000* + ID_MODEL_FROM_DATABASE=ME-1000 + +pci:v00001402d0000100A* + ID_MODEL_FROM_DATABASE=ME-1000 + +pci:v00001402d0000100B* + ID_MODEL_FROM_DATABASE=ME-1000 + +pci:v00001402d00001400* + ID_MODEL_FROM_DATABASE=ME-1400 + +pci:v00001402d0000140A* + ID_MODEL_FROM_DATABASE=ME-1400A + +pci:v00001402d0000140B* + ID_MODEL_FROM_DATABASE=ME-1400B + +pci:v00001402d0000140C* + ID_MODEL_FROM_DATABASE=ME-1400C + +pci:v00001402d0000140D* + ID_MODEL_FROM_DATABASE=ME-1400D + +pci:v00001402d0000140E* + ID_MODEL_FROM_DATABASE=ME-1400E + +pci:v00001402d000014EA* + ID_MODEL_FROM_DATABASE=ME-1400EA + +pci:v00001402d000014EB* + ID_MODEL_FROM_DATABASE=ME-1400EB + +pci:v00001402d00001604* + ID_MODEL_FROM_DATABASE=ME-1600/4U + +pci:v00001402d00001608* + ID_MODEL_FROM_DATABASE=ME-1600/8U + +pci:v00001402d0000160C* + ID_MODEL_FROM_DATABASE=ME-1600/12U + +pci:v00001402d0000160F* + ID_MODEL_FROM_DATABASE=ME-1600/16U + +pci:v00001402d0000168F* + ID_MODEL_FROM_DATABASE=ME-1600/16U8I + +pci:v00001402d00004610* + ID_MODEL_FROM_DATABASE=ME-4610 + +pci:v00001402d00004650* + ID_MODEL_FROM_DATABASE=ME-4650 + +pci:v00001402d00004660* + ID_MODEL_FROM_DATABASE=ME-4660 + +pci:v00001402d00004661* + ID_MODEL_FROM_DATABASE=ME-4660I + +pci:v00001402d00004662* + ID_MODEL_FROM_DATABASE=ME-4660 + +pci:v00001402d00004663* + ID_MODEL_FROM_DATABASE=ME-4660I + +pci:v00001402d00004670* + ID_MODEL_FROM_DATABASE=ME-4670 + +pci:v00001402d00004671* + ID_MODEL_FROM_DATABASE=ME-4670I + +pci:v00001402d00004672* + ID_MODEL_FROM_DATABASE=ME-4670S + +pci:v00001402d00004673* + ID_MODEL_FROM_DATABASE=ME-4670IS + +pci:v00001402d00004680* + ID_MODEL_FROM_DATABASE=ME-4680 + +pci:v00001402d00004681* + ID_MODEL_FROM_DATABASE=ME-4680I + +pci:v00001402d00004682* + ID_MODEL_FROM_DATABASE=ME-4680S + +pci:v00001402d00004683* + ID_MODEL_FROM_DATABASE=ME-4680IS + +pci:v00001402d00006004* + ID_MODEL_FROM_DATABASE=ME-6000/4 + +pci:v00001402d00006008* + ID_MODEL_FROM_DATABASE=ME-6000/8 + +pci:v00001402d0000600F* + ID_MODEL_FROM_DATABASE=ME-6000/16 + +pci:v00001402d00006014* + ID_MODEL_FROM_DATABASE=ME-6000I/4 + +pci:v00001402d00006018* + ID_MODEL_FROM_DATABASE=ME-6000I/8 + +pci:v00001402d0000601F* + ID_MODEL_FROM_DATABASE=ME-6000I/16 + +pci:v00001402d00006034* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/4 + +pci:v00001402d00006038* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/8 + +pci:v00001402d0000603F* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/16 + +pci:v00001402d00006044* + ID_MODEL_FROM_DATABASE=ME-6000/4/DIO + +pci:v00001402d00006048* + ID_MODEL_FROM_DATABASE=ME-6000/8/DIO + +pci:v00001402d0000604F* + ID_MODEL_FROM_DATABASE=ME-6000/16/DIO + +pci:v00001402d00006054* + ID_MODEL_FROM_DATABASE=ME-6000I/4/DIO + +pci:v00001402d00006058* + ID_MODEL_FROM_DATABASE=ME-6000I/8/DIO + +pci:v00001402d0000605F* + ID_MODEL_FROM_DATABASE=ME-6000I/16/DIO + +pci:v00001402d00006074* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/4/DIO + +pci:v00001402d00006078* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/8/DIO + +pci:v00001402d0000607F* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/16/DIO + +pci:v00001402d00006104* + ID_MODEL_FROM_DATABASE=ME-6100/4 + +pci:v00001402d00006108* + ID_MODEL_FROM_DATABASE=ME-6100/8 + +pci:v00001402d0000610F* + ID_MODEL_FROM_DATABASE=ME-6100/16 + +pci:v00001402d00006114* + ID_MODEL_FROM_DATABASE=ME-6100I/4 + +pci:v00001402d00006118* + ID_MODEL_FROM_DATABASE=ME-6100I/8 + +pci:v00001402d0000611F* + ID_MODEL_FROM_DATABASE=ME-6100I/16 + +pci:v00001402d00006134* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/4 + +pci:v00001402d00006138* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/8 + +pci:v00001402d0000613F* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/16 + +pci:v00001402d00006144* + ID_MODEL_FROM_DATABASE=ME-6100/4/DIO + +pci:v00001402d00006148* + ID_MODEL_FROM_DATABASE=ME-6100/8/DIO + +pci:v00001402d0000614F* + ID_MODEL_FROM_DATABASE=ME-6100/16/DIO + +pci:v00001402d00006154* + ID_MODEL_FROM_DATABASE=ME-6100I/4/DIO + +pci:v00001402d00006158* + ID_MODEL_FROM_DATABASE=ME-6100I/8/DIO + +pci:v00001402d0000615F* + ID_MODEL_FROM_DATABASE=ME-6100I/16/DIO + +pci:v00001402d00006174* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/4/DIO + +pci:v00001402d00006178* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/8/DIO + +pci:v00001402d0000617F* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/16/DIO + +pci:v00001402d00006259* + ID_MODEL_FROM_DATABASE=ME-6200I/9/DIO + +pci:v00001402d00006359* + ID_MODEL_FROM_DATABASE=ME-6300I/9/DIO + +pci:v00001402d0000810A* + ID_MODEL_FROM_DATABASE=ME-8100A + +pci:v00001402d0000810B* + ID_MODEL_FROM_DATABASE=ME-8100B + +pci:v00001402d0000820A* + ID_MODEL_FROM_DATABASE=ME-8200A + +pci:v00001402d0000820B* + ID_MODEL_FROM_DATABASE=ME-8200B + +pci:v00001403* + ID_VENDOR_FROM_DATABASE=Ascor Inc + +pci:v00001404* + ID_VENDOR_FROM_DATABASE=Fundamental Software Inc + +pci:v00001405* + ID_VENDOR_FROM_DATABASE=Excalibur Systems Inc + +pci:v00001406* + ID_VENDOR_FROM_DATABASE=Oce' Printing Systems GmbH + +pci:v00001407* + ID_VENDOR_FROM_DATABASE=Lava Computer mfg Inc + +pci:v00001407d00000100* + ID_MODEL_FROM_DATABASE=Lava Dual Serial + +pci:v00001407d00000101* + ID_MODEL_FROM_DATABASE=Lava Quatro A + +pci:v00001407d00000102* + ID_MODEL_FROM_DATABASE=Lava Quatro B + +pci:v00001407d00000110* + ID_MODEL_FROM_DATABASE=Lava DSerial-PCI Port A + +pci:v00001407d00000111* + ID_MODEL_FROM_DATABASE=Lava DSerial-PCI Port B + +pci:v00001407d00000120* + ID_MODEL_FROM_DATABASE=Quattro-PCI A + +pci:v00001407d00000121* + ID_MODEL_FROM_DATABASE=Quattro-PCI B + +pci:v00001407d00000180* + ID_MODEL_FROM_DATABASE=Lava Octo A + +pci:v00001407d00000181* + ID_MODEL_FROM_DATABASE=Lava Octo B + +pci:v00001407d00000200* + ID_MODEL_FROM_DATABASE=Lava Port Plus + +pci:v00001407d00000201* + ID_MODEL_FROM_DATABASE=Lava Quad A + +pci:v00001407d00000202* + ID_MODEL_FROM_DATABASE=Lava Quad B + +pci:v00001407d00000220* + ID_MODEL_FROM_DATABASE=Lava Quattro PCI Ports A/B + +pci:v00001407d00000221* + ID_MODEL_FROM_DATABASE=Lava Quattro PCI Ports C/D + +pci:v00001407d00000400* + ID_MODEL_FROM_DATABASE=Lava 8255-PIO-PCI + +pci:v00001407d00000500* + ID_MODEL_FROM_DATABASE=Lava Single Serial + +pci:v00001407d00000520* + ID_MODEL_FROM_DATABASE=Lava RS422-SS-PCI + +pci:v00001407d00000600* + ID_MODEL_FROM_DATABASE=Lava Port 650 + +pci:v00001407d00008000* + ID_MODEL_FROM_DATABASE=Lava Parallel + +pci:v00001407d00008001* + ID_MODEL_FROM_DATABASE=Dual parallel port controller A + +pci:v00001407d00008002* + ID_MODEL_FROM_DATABASE=Lava Dual Parallel port A + +pci:v00001407d00008003* + ID_MODEL_FROM_DATABASE=Lava Dual Parallel port B + +pci:v00001407d00008800* + ID_MODEL_FROM_DATABASE=BOCA Research IOPPAR + +pci:v00001408* + ID_VENDOR_FROM_DATABASE=Aloka Co. Ltd + +pci:v00001409* + ID_VENDOR_FROM_DATABASE=Timedia Technology Co Ltd + +pci:v00001409d00007168* + ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) + +pci:v00001409d00007168sv00001409sd00000002* + ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4036A3V (2x RS232 port)) + +pci:v00001409d00007168sv00001409sd00004027* + ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4027A (1x RS232 port)) + +pci:v00001409d00007168sv00001409sd00004037* + ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4037A(L) [SUNIX SUN1889] (2x RS232 port)) + +pci:v00001409d00007168sv00001409sd00004056* + ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4056A (4x RS232)) + +pci:v00001409d00007168sv00001409sd00005027* + ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4027D) + +pci:v00001409d00007168sv00001409sd00005037* + ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4037D (2x RS232 port)) + +pci:v00001409d00007168sv00001409sd00005066* + ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4066R (8x RS232)) + +pci:v00001409d00007168sv00001409sd00006056* + ID_MODEL_FROM_DATABASE=PCI2S550 (Dual 16550 UART) (SER4056D (4x RS232 port)) + +pci:v00001409d00007268* + ID_MODEL_FROM_DATABASE=SUN1888 (Dual IEEE1284 parallel port) + +pci:v00001409d00007268sv00001409sd00000103* + ID_MODEL_FROM_DATABASE=SUN1888 (Dual IEEE1284 parallel port) (PAR4008A) + +pci:v00001409d00007268sv00001409sd00000104* + ID_MODEL_FROM_DATABASE=SUN1888 (Dual IEEE1284 parallel port) (PAR4018A) + +pci:v0000140A* + ID_VENDOR_FROM_DATABASE=DSP Research Inc + +pci:v0000140B* + ID_VENDOR_FROM_DATABASE=Abaco Systems, Inc. + +pci:v0000140C* + ID_VENDOR_FROM_DATABASE=Elmic Systems Inc + +pci:v0000140D* + ID_VENDOR_FROM_DATABASE=Matsushita Electric Works Ltd + +pci:v0000140E* + ID_VENDOR_FROM_DATABASE=Goepel Electronic GmbH + +pci:v0000140F* + ID_VENDOR_FROM_DATABASE=Salient Systems Corp + +pci:v00001410* + ID_VENDOR_FROM_DATABASE=Midas lab Inc + +pci:v00001411* + ID_VENDOR_FROM_DATABASE=Ikos Systems Inc + +pci:v00001412* + ID_VENDOR_FROM_DATABASE=VIA Technologies Inc. + +pci:v00001412d00001712* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller + +pci:v00001412d00001712sv00001412sd00001712* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (Hoontech ST Audio DSP 24) + +pci:v00001412d00001712sv00001412sd0000D630* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 1010) + +pci:v00001412d00001712sv00001412sd0000D631* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta DiO) + +pci:v00001412d00001712sv00001412sd0000D632* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 66) + +pci:v00001412d00001712sv00001412sd0000D633* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 44) + +pci:v00001412d00001712sv00001412sd0000D634* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta Audiophile 2496) + +pci:v00001412d00001712sv00001412sd0000D635* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta TDIF) + +pci:v00001412d00001712sv00001412sd0000D637* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta RBUS) + +pci:v00001412d00001712sv00001412sd0000D638* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 410) + +pci:v00001412d00001712sv00001412sd0000D63B* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (M-Audio Delta 1010LT) + +pci:v00001412d00001712sv00001412sd0000D63C* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (Digigram VX442) + +pci:v00001412d00001712sv00001416sd00001712* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (Hoontech ST Audio DSP 24 Media 7.1) + +pci:v00001412d00001712sv0000153Bsd00001115* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (EWS88 MT) + +pci:v00001412d00001712sv0000153Bsd00001125* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (EWS88 MT (Master)) + +pci:v00001412d00001712sv0000153Bsd0000112B* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (EWS88 D) + +pci:v00001412d00001712sv0000153Bsd0000112C* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (EWS88 D (Master)) + +pci:v00001412d00001712sv0000153Bsd00001130* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (EWX 24/96) + +pci:v00001412d00001712sv0000153Bsd00001138* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (DMX 6fire 24/96) + +pci:v00001412d00001712sv0000153Bsd00001151* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (PHASE88) + +pci:v00001412d00001712sv000016CEsd00001040* + ID_MODEL_FROM_DATABASE=ICE1712 [Envy24] PCI Multi-Channel I/O Controller (Edirol DA-2496) + +pci:v00001412d00001724* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller + +pci:v00001412d00001724sv000010B0sd00000200* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Hollywood@Home 7.1) + +pci:v00001412d00001724sv00001412sd00001724* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Albatron PX865PE 7.1) + +pci:v00001412d00001724sv00001412sd00003630* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (M-Audio Revolution 7.1) + +pci:v00001412d00001724sv00001412sd00003631* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (M-Audio Revolution 5.1) + +pci:v00001412d00001724sv00001412sd00003632* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (M-Audio Audiophile 192) + +pci:v00001412d00001724sv0000153Bsd00001145* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Aureon 7.1 Space) + +pci:v00001412d00001724sv0000153Bsd00001147* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Aureon 5.1 Sky) + +pci:v00001412d00001724sv0000153Bsd00001150* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (PHASE 22) + +pci:v00001412d00001724sv0000153Bsd00001153* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (Aureon 7.1 Universe) + +pci:v00001412d00001724sv000017ABsd00001906* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (PSC 724 [Ultimate Edge]) + +pci:v00001412d00001724sv0000270Fsd0000F641* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (ZNF3-150) + +pci:v00001412d00001724sv0000270Fsd0000F645* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (ZNF3-250) + +pci:v00001412d00001724sv00003130sd00004154* + ID_MODEL_FROM_DATABASE=VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller (MAYA 44 MKII) + +pci:v00001413* + ID_VENDOR_FROM_DATABASE=Addonics + +pci:v00001414* + ID_VENDOR_FROM_DATABASE=Microsoft Corporation + +pci:v00001414d00000001* + ID_MODEL_FROM_DATABASE=MN-120 (ADMtek Centaur-C based) + +pci:v00001414d00000002* + ID_MODEL_FROM_DATABASE=MN-130 (ADMtek Centaur-P based) + +pci:v00001414d00005353* + ID_MODEL_FROM_DATABASE=Hyper-V virtual VGA + +pci:v00001414d00005801* + ID_MODEL_FROM_DATABASE=XMA Decoder (Xenon) + +pci:v00001414d00005802* + ID_MODEL_FROM_DATABASE=SATA Controller - CdRom (Xenon) + +pci:v00001414d00005803* + ID_MODEL_FROM_DATABASE=SATA Controller - Disk (Xenon) + +pci:v00001414d00005804* + ID_MODEL_FROM_DATABASE=OHCI Controller 0 (Xenon) + +pci:v00001414d00005805* + ID_MODEL_FROM_DATABASE=EHCI Controller 0 (Xenon) + +pci:v00001414d00005806* + ID_MODEL_FROM_DATABASE=OHCI Controller 1 (Xenon) + +pci:v00001414d00005807* + ID_MODEL_FROM_DATABASE=EHCI Controller 1 (Xenon) + +pci:v00001414d0000580A* + ID_MODEL_FROM_DATABASE=Fast Ethernet Adapter (Xenon) + +pci:v00001414d0000580B* + ID_MODEL_FROM_DATABASE=Secure Flash Controller (Xenon) + +pci:v00001414d0000580D* + ID_MODEL_FROM_DATABASE=System Management Controller (Xenon) + +pci:v00001414d00005811* + ID_MODEL_FROM_DATABASE=Xenos GPU (Xenon) + +pci:v00001415* + ID_VENDOR_FROM_DATABASE=Oxford Semiconductor Ltd + +pci:v00001415d00008401* + ID_MODEL_FROM_DATABASE=OX9162 Mode 1 (8-bit bus) + +pci:v00001415d00008403* + ID_MODEL_FROM_DATABASE=OX9162 Mode 0 (parallel port) + +pci:v00001415d00009500* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Disabled) + +pci:v00001415d00009501* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) + +pci:v00001415d00009501sv000012C4sd00000201* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (Titan/cPCI (2 port)) + +pci:v00001415d00009501sv000012C4sd00000202* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (Titan/cPCI (4 port)) + +pci:v00001415d00009501sv000012C4sd00000203* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (Titan/cPCI (8 port)) + +pci:v00001415d00009501sv000012C4sd00000210* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (Titan/104-Plus (8 port, p1-4)) + +pci:v00001415d00009501sv0000131Fsd00002050* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (CyberPro (4-port)) + +pci:v00001415d00009501sv0000131Fsd00002051* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (CyberSerial 4S Plus) + +pci:v00001415d00009501sv000015EDsd00002000* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (MCCR Serial p0-3 of 8) + +pci:v00001415d00009501sv000015EDsd00002001* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 0 (Uart) (MCCR Serial p0-3 of 16) + +pci:v00001415d00009505* + ID_MODEL_FROM_DATABASE=OXuPCI952 (Dual 16C950 UART) + +pci:v00001415d0000950A* + ID_MODEL_FROM_DATABASE=EXSYS EX-41092 Dual 16950 Serial adapter + +pci:v00001415d0000950B* + ID_MODEL_FROM_DATABASE=OXCB950 Cardbus 16950 UART + +pci:v00001415d00009510* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (Disabled) + +pci:v00001415d00009510sv000012C4sd00000200* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (Disabled) (Titan/cPCI (Unused)) + +pci:v00001415d00009511* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (8bit bus) + +pci:v00001415d00009511sv000012C4sd00000211* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (8bit bus) (Titan/104-Plus (8 port, p5-8)) + +pci:v00001415d00009511sv000015EDsd00002000* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (8bit bus) (MCCR Serial p4-7 of 8) + +pci:v00001415d00009511sv000015EDsd00002001* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (8bit bus) (MCCR Serial p4-15 of 16) + +pci:v00001415d00009512* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (32bit bus) + +pci:v00001415d00009513* + ID_MODEL_FROM_DATABASE=OX16PCI954 (Quad 16950 UART) function 1 (parallel port) + +pci:v00001415d00009521* + ID_MODEL_FROM_DATABASE=OX16PCI952 (Dual 16950 UART) + +pci:v00001415d00009523* + ID_MODEL_FROM_DATABASE=OX16PCI952 Integrated Parallel Port + +pci:v00001415d0000C158* + ID_MODEL_FROM_DATABASE=OXPCIe952 Dual 16C950 UART + +pci:v00001415d0000C158sv0000E4BFsd0000C504* + ID_MODEL_FROM_DATABASE=OXPCIe952 Dual 16C950 UART (CP4-SCAT Wireless Technologies Carrier Board) + +pci:v00001415d0000C158sv0000E4BFsd0000D551* + ID_MODEL_FROM_DATABASE=OXPCIe952 Dual 16C950 UART (DU1-MUSTANG Dual-Port RS-485 Interface) + +pci:v00001415d0000C308* + ID_MODEL_FROM_DATABASE=EX-44016 16-port serial + +pci:v00001416* + ID_VENDOR_FROM_DATABASE=Multiwave Innovation pte Ltd + +pci:v00001417* + ID_VENDOR_FROM_DATABASE=Convergenet Technologies Inc + +pci:v00001418* + ID_VENDOR_FROM_DATABASE=Kyushu electronics systems Inc + +pci:v00001419* + ID_VENDOR_FROM_DATABASE=Excel Switching Corp + +pci:v0000141A* + ID_VENDOR_FROM_DATABASE=Apache Micro Peripherals Inc + +pci:v0000141B* + ID_VENDOR_FROM_DATABASE=Zoom Telephonics Inc + +pci:v0000141D* + ID_VENDOR_FROM_DATABASE=Digitan Systems Inc + +pci:v0000141E* + ID_VENDOR_FROM_DATABASE=Fanuc Ltd + +pci:v0000141F* + ID_VENDOR_FROM_DATABASE=Visiontech Ltd + +pci:v00001420* + ID_VENDOR_FROM_DATABASE=Psion Dacom plc + +pci:v00001420d00008002* + ID_MODEL_FROM_DATABASE=Gold Card NetGlobal 56k+10/100Mb CardBus (Ethernet part) + +pci:v00001420d00008003* + ID_MODEL_FROM_DATABASE=Gold Card NetGlobal 56k+10/100Mb CardBus (Modem part) + +pci:v00001421* + ID_VENDOR_FROM_DATABASE=Ads Technologies Inc + +pci:v00001422* + ID_VENDOR_FROM_DATABASE=Ygrec Systems Co Ltd + +pci:v00001423* + ID_VENDOR_FROM_DATABASE=Custom Technology Corp. + +pci:v00001424* + ID_VENDOR_FROM_DATABASE=Videoserver Connections + +pci:v00001425* + ID_VENDOR_FROM_DATABASE=Chelsio Communications Inc + +pci:v00001425d0000000B* + ID_MODEL_FROM_DATABASE=T210 Protocol Engine + +pci:v00001425d0000000C* + ID_MODEL_FROM_DATABASE=T204 Protocol Engine + +pci:v00001425d00000022* + ID_MODEL_FROM_DATABASE=10GbE Ethernet Adapter + +pci:v00001425d00000030* + ID_MODEL_FROM_DATABASE=T310 10GbE Single Port Adapter + +pci:v00001425d00000030sv0000103Csd0000705E* + ID_MODEL_FROM_DATABASE=T310 10GbE Single Port Adapter (PCIe 10GBase-SR [AD386A]) + +pci:v00001425d00000031* + ID_MODEL_FROM_DATABASE=T320 10GbE Dual Port Adapter + +pci:v00001425d00000032* + ID_MODEL_FROM_DATABASE=T302 1GbE Dual Port Adapter + +pci:v00001425d00000033* + ID_MODEL_FROM_DATABASE=T304 1GbE Quad Port Adapter + +pci:v00001425d00000034* + ID_MODEL_FROM_DATABASE=B320 10GbE Dual Port Adapter + +pci:v00001425d00000035* + ID_MODEL_FROM_DATABASE=S310-CR 10GbE Single Port Adapter + +pci:v00001425d00000036* + ID_MODEL_FROM_DATABASE=S320-LP-CR 10GbE Dual Port Adapter + +pci:v00001425d00000037* + ID_MODEL_FROM_DATABASE=N320-G2-CR 10GbE Dual Port Adapter + +pci:v00001425d00004001* + ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller + +pci:v00001425d00004002* + ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Ethernet Controller + +pci:v00001425d00004003* + ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Ethernet Controller + +pci:v00001425d00004004* + ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Ethernet Controller + +pci:v00001425d00004005* + ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Ethernet Controller + +pci:v00001425d00004006* + ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Ethernet Controller + +pci:v00001425d00004007* + ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Ethernet Controller + +pci:v00001425d00004008* + ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Ethernet Controller + +pci:v00001425d00004009* + ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Ethernet Controller + +pci:v00001425d0000400A* + ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Ethernet Controller + +pci:v00001425d0000400B* + ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Ethernet Controller + +pci:v00001425d0000400C* + ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Ethernet Controller + +pci:v00001425d0000400D* + ID_MODEL_FROM_DATABASE=T480 Unified Wire Ethernet Controller + +pci:v00001425d0000400E* + ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d0000400F* + ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Ethernet Controller + +pci:v00001425d00004080* + ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Ethernet Controller + +pci:v00001425d00004081* + ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Ethernet Controller + +pci:v00001425d00004082* + ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Ethernet Controller + +pci:v00001425d00004083* + ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Ethernet Controller + +pci:v00001425d00004084* + ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Ethernet Controller + +pci:v00001425d00004085* + ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Ethernet Controller + +pci:v00001425d00004086* + ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Ethernet Controller + +pci:v00001425d00004087* + ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller + +pci:v00001425d00004088* + ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller + +pci:v00001425d00004401* + ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller + +pci:v00001425d00004402* + ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Ethernet Controller + +pci:v00001425d00004403* + ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Ethernet Controller + +pci:v00001425d00004404* + ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Ethernet Controller + +pci:v00001425d00004405* + ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Ethernet Controller + +pci:v00001425d00004406* + ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Ethernet Controller + +pci:v00001425d00004407* + ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Ethernet Controller + +pci:v00001425d00004408* + ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Ethernet Controller + +pci:v00001425d00004409* + ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Ethernet Controller + +pci:v00001425d0000440A* + ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Ethernet Controller + +pci:v00001425d0000440B* + ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Ethernet Controller + +pci:v00001425d0000440C* + ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Ethernet Controller + +pci:v00001425d0000440D* + ID_MODEL_FROM_DATABASE=T480 Unified Wire Ethernet Controller + +pci:v00001425d0000440E* + ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d0000440F* + ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Ethernet Controller + +pci:v00001425d00004480* + ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Ethernet Controller + +pci:v00001425d00004481* + ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Ethernet Controller + +pci:v00001425d00004482* + ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Ethernet Controller + +pci:v00001425d00004483* + ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Ethernet Controller + +pci:v00001425d00004484* + ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Ethernet Controller + +pci:v00001425d00004485* + ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Ethernet Controller + +pci:v00001425d00004486* + ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Ethernet Controller + +pci:v00001425d00004487* + ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller + +pci:v00001425d00004488* + ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller + +pci:v00001425d00004501* + ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Storage Controller + +pci:v00001425d00004502* + ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Storage Controller + +pci:v00001425d00004503* + ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Storage Controller + +pci:v00001425d00004504* + ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Storage Controller + +pci:v00001425d00004505* + ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Storage Controller + +pci:v00001425d00004506* + ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Storage Controller + +pci:v00001425d00004507* + ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Storage Controller + +pci:v00001425d00004508* + ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Storage Controller + +pci:v00001425d00004509* + ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Storage Controller + +pci:v00001425d0000450A* + ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Storage Controller + +pci:v00001425d0000450B* + ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Storage Controller + +pci:v00001425d0000450C* + ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Storage Controller + +pci:v00001425d0000450D* + ID_MODEL_FROM_DATABASE=T480 Unified Wire Storage Controller + +pci:v00001425d0000450E* + ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Storage Controller + +pci:v00001425d0000450F* + ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Storage Controller + +pci:v00001425d00004580* + ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Storage Controller + +pci:v00001425d00004581* + ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Storage Controller + +pci:v00001425d00004582* + ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Storage Controller + +pci:v00001425d00004583* + ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Storage Controller + +pci:v00001425d00004584* + ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Storage Controller + +pci:v00001425d00004585* + ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Storage Controller + +pci:v00001425d00004586* + ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Storage Controller + +pci:v00001425d00004587* + ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Storage Controller + +pci:v00001425d00004588* + ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Storage Controller + +pci:v00001425d00004601* + ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Storage Controller + +pci:v00001425d00004602* + ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Storage Controller + +pci:v00001425d00004603* + ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Storage Controller + +pci:v00001425d00004604* + ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Storage Controller + +pci:v00001425d00004605* + ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Storage Controller + +pci:v00001425d00004606* + ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Storage Controller + +pci:v00001425d00004607* + ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Storage Controller + +pci:v00001425d00004608* + ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Storage Controller + +pci:v00001425d00004609* + ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Storage Controller + +pci:v00001425d0000460A* + ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Storage Controller + +pci:v00001425d0000460B* + ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Storage Controller + +pci:v00001425d0000460C* + ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Storage Controller + +pci:v00001425d0000460D* + ID_MODEL_FROM_DATABASE=T480 Unified Wire Storage Controller + +pci:v00001425d0000460E* + ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Storage Controller + +pci:v00001425d0000460F* + ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Storage Controller + +pci:v00001425d00004680* + ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Storage Controller + +pci:v00001425d00004681* + ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Storage Controller + +pci:v00001425d00004682* + ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Storage Controller + +pci:v00001425d00004683* + ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Storage Controller + +pci:v00001425d00004684* + ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Storage Controller + +pci:v00001425d00004685* + ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Storage Controller + +pci:v00001425d00004686* + ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Storage Controller + +pci:v00001425d00004687* + ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Storage Controller + +pci:v00001425d00004688* + ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Storage Controller + +pci:v00001425d00004701* + ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller + +pci:v00001425d00004702* + ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Ethernet Controller + +pci:v00001425d00004703* + ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Ethernet Controller + +pci:v00001425d00004704* + ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Ethernet Controller + +pci:v00001425d00004705* + ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Ethernet Controller + +pci:v00001425d00004706* + ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Ethernet Controller + +pci:v00001425d00004707* + ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Ethernet Controller + +pci:v00001425d00004708* + ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Ethernet Controller + +pci:v00001425d00004709* + ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Ethernet Controller + +pci:v00001425d0000470A* + ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Ethernet Controller + +pci:v00001425d0000470B* + ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Ethernet Controller + +pci:v00001425d0000470C* + ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Ethernet Controller + +pci:v00001425d0000470D* + ID_MODEL_FROM_DATABASE=T480 Unified Wire Ethernet Controller + +pci:v00001425d0000470E* + ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d0000470F* + ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Ethernet Controller + +pci:v00001425d00004780* + ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Ethernet Controller + +pci:v00001425d00004781* + ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Ethernet Controller + +pci:v00001425d00004782* + ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Ethernet Controller + +pci:v00001425d00004783* + ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Ethernet Controller + +pci:v00001425d00004784* + ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Ethernet Controller + +pci:v00001425d00004785* + ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Ethernet Controller + +pci:v00001425d00004786* + ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Ethernet Controller + +pci:v00001425d00004787* + ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller + +pci:v00001425d00004788* + ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller + +pci:v00001425d00004801* + ID_MODEL_FROM_DATABASE=T420-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004802* + ID_MODEL_FROM_DATABASE=T422-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004803* + ID_MODEL_FROM_DATABASE=T440-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004804* + ID_MODEL_FROM_DATABASE=T420-BCH Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004805* + ID_MODEL_FROM_DATABASE=T440-BCH Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004806* + ID_MODEL_FROM_DATABASE=T440-CH Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004807* + ID_MODEL_FROM_DATABASE=T420-SO Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004808* + ID_MODEL_FROM_DATABASE=T420-CX Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004809* + ID_MODEL_FROM_DATABASE=T420-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000480A* + ID_MODEL_FROM_DATABASE=T404-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000480B* + ID_MODEL_FROM_DATABASE=B420-SR Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000480C* + ID_MODEL_FROM_DATABASE=B404-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000480D* + ID_MODEL_FROM_DATABASE=T480 Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000480E* + ID_MODEL_FROM_DATABASE=T440-LP-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000480F* + ID_MODEL_FROM_DATABASE=T440 [Amsterdam] Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004880* + ID_MODEL_FROM_DATABASE=T480-4080 T480 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004881* + ID_MODEL_FROM_DATABASE=T440F-4081 T440-FCoE Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004882* + ID_MODEL_FROM_DATABASE=T420-4082 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004883* + ID_MODEL_FROM_DATABASE=T420X-4083 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004884* + ID_MODEL_FROM_DATABASE=T440-4084 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004885* + ID_MODEL_FROM_DATABASE=T420-4085 SFP+ Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004886* + ID_MODEL_FROM_DATABASE=T440-4086 10Gbase-T Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004887* + ID_MODEL_FROM_DATABASE=T440T-4087 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00004888* + ID_MODEL_FROM_DATABASE=T440-4088 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005001* + ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller + +pci:v00001425d00005001sv0000193Dsd00001001* + ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller (510F-B) + +pci:v00001425d00005002* + ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Ethernet Controller + +pci:v00001425d00005003* + ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Ethernet Controller + +pci:v00001425d00005004* + ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Ethernet Controller + +pci:v00001425d00005005* + ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Ethernet Controller + +pci:v00001425d00005006* + ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Ethernet Controller + +pci:v00001425d00005007* + ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Ethernet Controller + +pci:v00001425d00005008* + ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Ethernet Controller + +pci:v00001425d00005009* + ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Ethernet Controller + +pci:v00001425d0000500A* + ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Ethernet Controller + +pci:v00001425d0000500B* + ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Ethernet Controller + +pci:v00001425d0000500C* + ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Ethernet Controller + +pci:v00001425d0000500D* + ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller + +pci:v00001425d0000500E* + ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d0000500F* + ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Ethernet Controller + +pci:v00001425d00005010* + ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d00005011* + ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Ethernet Controller + +pci:v00001425d00005012* + ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Ethernet Controller + +pci:v00001425d00005013* + ID_MODEL_FROM_DATABASE=T580-CHR Unified Wire Ethernet Controller + +pci:v00001425d00005014* + ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00005015* + ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller + +pci:v00001425d00005016* + ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00005017* + ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00005018* + ID_MODEL_FROM_DATABASE=T540-BT Unified Wire Ethernet Controller + +pci:v00001425d00005019* + ID_MODEL_FROM_DATABASE=T540-LP-BT Unified Wire Ethernet Controller + +pci:v00001425d0000501A* + ID_MODEL_FROM_DATABASE=T540-SO-BT Unified Wire Ethernet Controller + +pci:v00001425d0000501B* + ID_MODEL_FROM_DATABASE=T540-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00005080* + ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller + +pci:v00001425d00005081* + ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller + +pci:v00001425d00005082* + ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Ethernet Controller + +pci:v00001425d00005083* + ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Ethernet Controller + +pci:v00001425d00005084* + ID_MODEL_FROM_DATABASE=T540-5084 Unified Wire Ethernet Controller + +pci:v00001425d00005085* + ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Ethernet Controller + +pci:v00001425d00005086* + ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Ethernet Controller + +pci:v00001425d00005087* + ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Ethernet Controller + +pci:v00001425d00005088* + ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Ethernet Controller + +pci:v00001425d00005089* + ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Ethernet Controller + +pci:v00001425d00005090* + ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller + +pci:v00001425d00005091* + ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller + +pci:v00001425d00005092* + ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller + +pci:v00001425d00005093* + ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Ethernet Controller + +pci:v00001425d00005094* + ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Ethernet Controller + +pci:v00001425d00005095* + ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Ethernet Controller + +pci:v00001425d00005096* + ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Ethernet Controller + +pci:v00001425d00005097* + ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller + +pci:v00001425d00005098* + ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Ethernet Controller + +pci:v00001425d00005099* + ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Ethernet Controller + +pci:v00001425d0000509A* + ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Ethernet Controller + +pci:v00001425d0000509B* + ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Ethernet Controller + +pci:v00001425d0000509C* + ID_MODEL_FROM_DATABASE=T520-509C Unified Wire Ethernet Controller + +pci:v00001425d0000509D* + ID_MODEL_FROM_DATABASE=T540-509D Unified Wire Ethernet Controller + +pci:v00001425d0000509E* + ID_MODEL_FROM_DATABASE=T520-509E Unified Wire Ethernet Controller + +pci:v00001425d0000509F* + ID_MODEL_FROM_DATABASE=T540-509F Unified Wire Ethernet Controller + +pci:v00001425d000050A0* + ID_MODEL_FROM_DATABASE=T540-50A0 Unified Wire Ethernet Controller + +pci:v00001425d000050A1* + ID_MODEL_FROM_DATABASE=T540-50A1 Unified Wire Ethernet Controller + +pci:v00001425d000050A2* + ID_MODEL_FROM_DATABASE=T580-50A2 Unified Wire Ethernet Controller + +pci:v00001425d000050A3* + ID_MODEL_FROM_DATABASE=T580-50A3 Unified Wire Ethernet Controller + +pci:v00001425d000050A4* + ID_MODEL_FROM_DATABASE=T540-50A4 Unified Wire Ethernet Controller + +pci:v00001425d000050A5* + ID_MODEL_FROM_DATABASE=T522-50A5 Unified Wire Ethernet Controller + +pci:v00001425d000050A6* + ID_MODEL_FROM_DATABASE=T522-50A6 Unified Wire Ethernet Controller + +pci:v00001425d000050A7* + ID_MODEL_FROM_DATABASE=T580-50A7 Unified Wire Ethernet Controller + +pci:v00001425d000050A8* + ID_MODEL_FROM_DATABASE=T580-50A8 Unified Wire Ethernet Controller + +pci:v00001425d000050A9* + ID_MODEL_FROM_DATABASE=T580-50A9 Unified Wire Ethernet Controller + +pci:v00001425d000050AA* + ID_MODEL_FROM_DATABASE=T580-50AA Unified Wire Ethernet Controller + +pci:v00001425d000050AB* + ID_MODEL_FROM_DATABASE=T520-50AB Unified Wire Ethernet Controller + +pci:v00001425d000050AC* + ID_MODEL_FROM_DATABASE=T540-50AC Unified Wire Ethernet Controller + +pci:v00001425d000050AD* + ID_MODEL_FROM_DATABASE=T520-50AD Unified Wire Ethernet Controller + +pci:v00001425d000050AE* + ID_MODEL_FROM_DATABASE=T540-50AE Unified Wire Ethernet Controller + +pci:v00001425d000050AF* + ID_MODEL_FROM_DATABASE=T580-50AF Unified Wire Ethernet Controller + +pci:v00001425d000050B0* + ID_MODEL_FROM_DATABASE=T520-50B0 Unified Wire Ethernet Controller + +pci:v00001425d00005401* + ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller + +pci:v00001425d00005402* + ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Ethernet Controller + +pci:v00001425d00005403* + ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Ethernet Controller + +pci:v00001425d00005404* + ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Ethernet Controller + +pci:v00001425d00005405* + ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Ethernet Controller + +pci:v00001425d00005406* + ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Ethernet Controller + +pci:v00001425d00005407* + ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Ethernet Controller + +pci:v00001425d00005408* + ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Ethernet Controller + +pci:v00001425d00005409* + ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Ethernet Controller + +pci:v00001425d0000540A* + ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Ethernet Controller + +pci:v00001425d0000540B* + ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Ethernet Controller + +pci:v00001425d0000540C* + ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Ethernet Controller + +pci:v00001425d0000540D* + ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller + +pci:v00001425d0000540E* + ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d0000540F* + ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Ethernet Controller + +pci:v00001425d00005410* + ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d00005411* + ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Ethernet Controller + +pci:v00001425d00005412* + ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Ethernet Controller + +pci:v00001425d00005413* + ID_MODEL_FROM_DATABASE=T580-CHR Unified Wire Ethernet Controller + +pci:v00001425d00005414* + ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00005415* + ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller + +pci:v00001425d00005416* + ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00005417* + ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00005418* + ID_MODEL_FROM_DATABASE=T540-BT Unified Wire Ethernet Controller + +pci:v00001425d00005419* + ID_MODEL_FROM_DATABASE=T540-LP-BT Unified Wire Ethernet Controller + +pci:v00001425d0000541A* + ID_MODEL_FROM_DATABASE=T540-SO-BT Unified Wire Ethernet Controller + +pci:v00001425d0000541B* + ID_MODEL_FROM_DATABASE=T540-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00005480* + ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller + +pci:v00001425d00005481* + ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller + +pci:v00001425d00005482* + ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Ethernet Controller + +pci:v00001425d00005483* + ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Ethernet Controller + +pci:v00001425d00005484* + ID_MODEL_FROM_DATABASE=T540-5084 Unified Wire Ethernet Controller + +pci:v00001425d00005485* + ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Ethernet Controller + +pci:v00001425d00005486* + ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Ethernet Controller + +pci:v00001425d00005487* + ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Ethernet Controller + +pci:v00001425d00005488* + ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Ethernet Controller + +pci:v00001425d00005489* + ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Ethernet Controller + +pci:v00001425d00005490* + ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller + +pci:v00001425d00005491* + ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller + +pci:v00001425d00005492* + ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller + +pci:v00001425d00005493* + ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Ethernet Controller + +pci:v00001425d00005494* + ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Ethernet Controller + +pci:v00001425d00005495* + ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Ethernet Controller + +pci:v00001425d00005496* + ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Ethernet Controller + +pci:v00001425d00005497* + ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller + +pci:v00001425d00005498* + ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Ethernet Controller + +pci:v00001425d00005499* + ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Ethernet Controller + +pci:v00001425d0000549A* + ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Ethernet Controller + +pci:v00001425d0000549B* + ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Ethernet Controller + +pci:v00001425d0000549C* + ID_MODEL_FROM_DATABASE=T520-509C Unified Wire Ethernet Controller + +pci:v00001425d0000549D* + ID_MODEL_FROM_DATABASE=T540-509D Unified Wire Ethernet Controller + +pci:v00001425d0000549E* + ID_MODEL_FROM_DATABASE=T520-509E Unified Wire Ethernet Controller + +pci:v00001425d0000549F* + ID_MODEL_FROM_DATABASE=T540-509F Unified Wire Ethernet Controller + +pci:v00001425d000054A0* + ID_MODEL_FROM_DATABASE=T540-50A0 Unified Wire Ethernet Controller + +pci:v00001425d000054A1* + ID_MODEL_FROM_DATABASE=T540-50A1 Unified Wire Ethernet Controller + +pci:v00001425d000054A2* + ID_MODEL_FROM_DATABASE=T580-50A2 Unified Wire Ethernet Controller + +pci:v00001425d000054A3* + ID_MODEL_FROM_DATABASE=T580-50A3 Unified Wire Ethernet Controller + +pci:v00001425d000054A4* + ID_MODEL_FROM_DATABASE=T540-50A4 Unified Wire Ethernet Controller + +pci:v00001425d000054A5* + ID_MODEL_FROM_DATABASE=T522-50A5 Unified Wire Ethernet Controller + +pci:v00001425d000054A6* + ID_MODEL_FROM_DATABASE=T522-50A6 Unified Wire Ethernet Controller + +pci:v00001425d000054A7* + ID_MODEL_FROM_DATABASE=T580-50A7 Unified Wire Ethernet Controller + +pci:v00001425d000054A8* + ID_MODEL_FROM_DATABASE=T580-50A8 Unified Wire Ethernet Controller + +pci:v00001425d000054A9* + ID_MODEL_FROM_DATABASE=T580-50A9 Unified Wire Ethernet Controller + +pci:v00001425d000054AA* + ID_MODEL_FROM_DATABASE=T580-50AA Unified Wire Ethernet Controller + +pci:v00001425d000054AB* + ID_MODEL_FROM_DATABASE=T520-50AB Unified Wire Ethernet Controller + +pci:v00001425d000054AC* + ID_MODEL_FROM_DATABASE=T540-50AC Unified Wire Ethernet Controller + +pci:v00001425d000054AD* + ID_MODEL_FROM_DATABASE=T520-50AD Unified Wire Ethernet Controller + +pci:v00001425d000054AE* + ID_MODEL_FROM_DATABASE=T540-50AE Unified Wire Ethernet Controller + +pci:v00001425d000054AF* + ID_MODEL_FROM_DATABASE=T580-50AF Unified Wire Ethernet Controller + +pci:v00001425d000054B0* + ID_MODEL_FROM_DATABASE=T520-50B0 Unified Wire Ethernet Controller + +pci:v00001425d00005501* + ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller + +pci:v00001425d00005502* + ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Storage Controller + +pci:v00001425d00005503* + ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Storage Controller + +pci:v00001425d00005504* + ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Storage Controller + +pci:v00001425d00005505* + ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Storage Controller + +pci:v00001425d00005506* + ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Storage Controller + +pci:v00001425d00005507* + ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Storage Controller + +pci:v00001425d00005508* + ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Storage Controller + +pci:v00001425d00005509* + ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Storage Controller + +pci:v00001425d0000550A* + ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Storage Controller + +pci:v00001425d0000550B* + ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Storage Controller + +pci:v00001425d0000550C* + ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Storage Controller + +pci:v00001425d0000550D* + ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Storage Controller + +pci:v00001425d0000550E* + ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Storage Controller + +pci:v00001425d0000550F* + ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Storage Controller + +pci:v00001425d00005510* + ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Storage Controller + +pci:v00001425d00005511* + ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Storage Controller + +pci:v00001425d00005512* + ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Storage Controller + +pci:v00001425d00005513* + ID_MODEL_FROM_DATABASE=T580-CHR Unified Wire Storage Controller + +pci:v00001425d00005514* + ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Storage Controller + +pci:v00001425d00005515* + ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Storage Controller + +pci:v00001425d00005516* + ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00005517* + ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00005518* + ID_MODEL_FROM_DATABASE=T540-BT Unified Wire Storage Controller + +pci:v00001425d00005519* + ID_MODEL_FROM_DATABASE=T540-LP-BT Unified Wire Storage Controller + +pci:v00001425d0000551A* + ID_MODEL_FROM_DATABASE=T540-SO-BT Unified Wire Storage Controller + +pci:v00001425d0000551B* + ID_MODEL_FROM_DATABASE=T540-SO-CR Unified Wire Storage Controller + +pci:v00001425d00005580* + ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Storage Controller + +pci:v00001425d00005581* + ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Storage Controller + +pci:v00001425d00005582* + ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Storage Controller + +pci:v00001425d00005583* + ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Storage Controller + +pci:v00001425d00005584* + ID_MODEL_FROM_DATABASE=T540-5084 Unified Wire Storage Controller + +pci:v00001425d00005585* + ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Storage Controller + +pci:v00001425d00005586* + ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Storage Controller + +pci:v00001425d00005587* + ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Storage Controller + +pci:v00001425d00005588* + ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Storage Controller + +pci:v00001425d00005589* + ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Storage Controller + +pci:v00001425d00005590* + ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Storage Controller + +pci:v00001425d00005591* + ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Storage Controller + +pci:v00001425d00005592* + ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Storage Controller + +pci:v00001425d00005593* + ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Storage Controller + +pci:v00001425d00005594* + ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Storage Controller + +pci:v00001425d00005595* + ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Storage Controller + +pci:v00001425d00005596* + ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Storage Controller + +pci:v00001425d00005597* + ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Storage Controller + +pci:v00001425d00005598* + ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Storage Controller + +pci:v00001425d00005599* + ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Storage Controller + +pci:v00001425d0000559A* + ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Storage Controller + +pci:v00001425d0000559B* + ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Storage Controller + +pci:v00001425d0000559C* + ID_MODEL_FROM_DATABASE=T520-509C Unified Wire Storage Controller + +pci:v00001425d0000559D* + ID_MODEL_FROM_DATABASE=T540-509D Unified Wire Storage Controller + +pci:v00001425d0000559E* + ID_MODEL_FROM_DATABASE=T520-509E Unified Wire Storage Controller + +pci:v00001425d0000559F* + ID_MODEL_FROM_DATABASE=T540-509F Unified Wire Storage Controller + +pci:v00001425d000055A0* + ID_MODEL_FROM_DATABASE=T540-50A0 Unified Wire Storage Controller + +pci:v00001425d000055A1* + ID_MODEL_FROM_DATABASE=T540-50A1 Unified Wire Storage Controller + +pci:v00001425d000055A2* + ID_MODEL_FROM_DATABASE=T580-50A2 Unified Wire Storage Controller + +pci:v00001425d000055A3* + ID_MODEL_FROM_DATABASE=T580-50A3 Unified Wire Storage Controller + +pci:v00001425d000055A4* + ID_MODEL_FROM_DATABASE=T540-50A4 Unified Wire Storage Controller + +pci:v00001425d000055A5* + ID_MODEL_FROM_DATABASE=T522-50A5 Unified Wire Storage Controller + +pci:v00001425d000055A6* + ID_MODEL_FROM_DATABASE=T522-50A6 Unified Wire Storage Controller + +pci:v00001425d000055A7* + ID_MODEL_FROM_DATABASE=T580-50A7 Unified Wire Storage Controller + +pci:v00001425d000055A8* + ID_MODEL_FROM_DATABASE=T580-50A8 Unified Wire Storage Controller + +pci:v00001425d000055A9* + ID_MODEL_FROM_DATABASE=T580-50A9 Unified Wire Storage Controller + +pci:v00001425d000055AA* + ID_MODEL_FROM_DATABASE=T580-50AA Unified Wire Storage Controller + +pci:v00001425d000055AB* + ID_MODEL_FROM_DATABASE=T520-50AB Unified Wire Storage Controller + +pci:v00001425d000055AC* + ID_MODEL_FROM_DATABASE=T540-50AC Unified Wire Storage Controller + +pci:v00001425d000055AD* + ID_MODEL_FROM_DATABASE=T520-50AD Unified Wire Storage Controller + +pci:v00001425d000055AE* + ID_MODEL_FROM_DATABASE=T540-50AE Unified Wire Storage Controller + +pci:v00001425d000055AF* + ID_MODEL_FROM_DATABASE=T580-50AF Unified Wire Storage Controller + +pci:v00001425d000055B0* + ID_MODEL_FROM_DATABASE=T520-50B0 Unified Wire Storage Controller + +pci:v00001425d00005601* + ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Storage Controller + +pci:v00001425d00005602* + ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Storage Controller + +pci:v00001425d00005603* + ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Storage Controller + +pci:v00001425d00005604* + ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Storage Controller + +pci:v00001425d00005605* + ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Storage Controller + +pci:v00001425d00005606* + ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Storage Controller + +pci:v00001425d00005607* + ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Storage Controller + +pci:v00001425d00005608* + ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Storage Controller + +pci:v00001425d00005609* + ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Storage Controller + +pci:v00001425d0000560A* + ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Storage Controller + +pci:v00001425d0000560B* + ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Storage Controller + +pci:v00001425d0000560C* + ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Storage Controller + +pci:v00001425d0000560D* + ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Storage Controller + +pci:v00001425d0000560E* + ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Storage Controller + +pci:v00001425d0000560F* + ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Storage Controller + +pci:v00001425d00005610* + ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Storage Controller + +pci:v00001425d00005611* + ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Storage Controller + +pci:v00001425d00005612* + ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Storage Controller + +pci:v00001425d00005613* + ID_MODEL_FROM_DATABASE=T580-CHR Unified Wire Storage Controller + +pci:v00001425d00005614* + ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Storage Controller + +pci:v00001425d00005615* + ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Storage Controller + +pci:v00001425d00005616* + ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00005617* + ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00005618* + ID_MODEL_FROM_DATABASE=T540-BT Unified Wire Storage Controller + +pci:v00001425d00005619* + ID_MODEL_FROM_DATABASE=T540-LP-BT Unified Wire Storage Controller + +pci:v00001425d0000561A* + ID_MODEL_FROM_DATABASE=T540-SO-BT Unified Wire Storage Controller + +pci:v00001425d0000561B* + ID_MODEL_FROM_DATABASE=T540-SO-CR Unified Wire Storage Controller + +pci:v00001425d00005680* + ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Storage Controller + +pci:v00001425d00005681* + ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Storage Controller + +pci:v00001425d00005682* + ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Storage Controller + +pci:v00001425d00005683* + ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Storage Controller + +pci:v00001425d00005684* + ID_MODEL_FROM_DATABASE=T540-5084 Unified Wire Storage Controller + +pci:v00001425d00005685* + ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Storage Controller + +pci:v00001425d00005686* + ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Storage Controller + +pci:v00001425d00005687* + ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Storage Controller + +pci:v00001425d00005688* + ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Storage Controller + +pci:v00001425d00005689* + ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Storage Controller + +pci:v00001425d00005690* + ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Storage Controller + +pci:v00001425d00005691* + ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Storage Controller + +pci:v00001425d00005692* + ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Storage Controller + +pci:v00001425d00005693* + ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Storage Controller + +pci:v00001425d00005694* + ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Storage Controller + +pci:v00001425d00005695* + ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Storage Controller + +pci:v00001425d00005696* + ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Storage Controller + +pci:v00001425d00005697* + ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Storage Controller + +pci:v00001425d00005698* + ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Storage Controller + +pci:v00001425d00005699* + ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Storage Controller + +pci:v00001425d0000569A* + ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Storage Controller + +pci:v00001425d0000569B* + ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Storage Controller + +pci:v00001425d0000569C* + ID_MODEL_FROM_DATABASE=T520-509C Unified Wire Storage Controller + +pci:v00001425d0000569D* + ID_MODEL_FROM_DATABASE=T540-509D Unified Wire Storage Controller + +pci:v00001425d0000569E* + ID_MODEL_FROM_DATABASE=T520-509E Unified Wire Storage Controller + +pci:v00001425d0000569F* + ID_MODEL_FROM_DATABASE=T540-509F Unified Wire Storage Controller + +pci:v00001425d000056A0* + ID_MODEL_FROM_DATABASE=T540-50A0 Unified Wire Storage Controller + +pci:v00001425d000056A1* + ID_MODEL_FROM_DATABASE=T540-50A1 Unified Wire Storage Controller + +pci:v00001425d000056A2* + ID_MODEL_FROM_DATABASE=T580-50A2 Unified Wire Storage Controller + +pci:v00001425d000056A3* + ID_MODEL_FROM_DATABASE=T580-50A3 Unified Wire Storage Controller + +pci:v00001425d000056A4* + ID_MODEL_FROM_DATABASE=T540-50A4 Unified Wire Storage Controller + +pci:v00001425d000056A5* + ID_MODEL_FROM_DATABASE=T522-50A5 Unified Wire Storage Controller + +pci:v00001425d000056A6* + ID_MODEL_FROM_DATABASE=T522-50A6 Unified Wire Storage Controller + +pci:v00001425d000056A7* + ID_MODEL_FROM_DATABASE=T580-50A7 Unified Wire Storage Controller + +pci:v00001425d000056A8* + ID_MODEL_FROM_DATABASE=T580-50A8 Unified Wire Storage Controller + +pci:v00001425d000056A9* + ID_MODEL_FROM_DATABASE=T580-50A9 Unified Wire Storage Controller + +pci:v00001425d000056AA* + ID_MODEL_FROM_DATABASE=T580-50AA Unified Wire Storage Controller + +pci:v00001425d000056AB* + ID_MODEL_FROM_DATABASE=T520-50AB Unified Wire Storage Controller + +pci:v00001425d000056AC* + ID_MODEL_FROM_DATABASE=T540-50AC Unified Wire Storage Controller + +pci:v00001425d000056AD* + ID_MODEL_FROM_DATABASE=T520-50AD Unified Wire Storage Controller + +pci:v00001425d000056AE* + ID_MODEL_FROM_DATABASE=T540-50AE Unified Wire Storage Controller + +pci:v00001425d000056AF* + ID_MODEL_FROM_DATABASE=T580-50AF Unified Wire Storage Controller + +pci:v00001425d000056B0* + ID_MODEL_FROM_DATABASE=T520-50B0 Unified Wire Storage Controller + +pci:v00001425d00005701* + ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller + +pci:v00001425d00005702* + ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Ethernet Controller + +pci:v00001425d00005703* + ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Ethernet Controller + +pci:v00001425d00005704* + ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Ethernet Controller + +pci:v00001425d00005705* + ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Ethernet Controller + +pci:v00001425d00005706* + ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Ethernet Controller + +pci:v00001425d00005707* + ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Ethernet Controller + +pci:v00001425d00005708* + ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Ethernet Controller + +pci:v00001425d00005709* + ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Ethernet Controller + +pci:v00001425d0000570A* + ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Ethernet Controller + +pci:v00001425d0000570B* + ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Ethernet Controller + +pci:v00001425d0000570C* + ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Ethernet Controller + +pci:v00001425d0000570D* + ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller + +pci:v00001425d0000570E* + ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d0000570F* + ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Ethernet Controller + +pci:v00001425d00005710* + ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d00005711* + ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Ethernet Controller + +pci:v00001425d00005712* + ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Ethernet Controller + +pci:v00001425d00005713* + ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller + +pci:v00001425d00005714* + ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00005715* + ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller + +pci:v00001425d00005780* + ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller + +pci:v00001425d00005781* + ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller + +pci:v00001425d00005782* + ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Ethernet Controller + +pci:v00001425d00005783* + ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Ethernet Controller + +pci:v00001425d00005784* + ID_MODEL_FROM_DATABASE=T580-5084 Unified Wire Ethernet Controller + +pci:v00001425d00005785* + ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Ethernet Controller + +pci:v00001425d00005786* + ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Ethernet Controller + +pci:v00001425d00005787* + ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Ethernet Controller + +pci:v00001425d00005788* + ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Ethernet Controller + +pci:v00001425d00005789* + ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Ethernet Controller + +pci:v00001425d00005790* + ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller + +pci:v00001425d00005791* + ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller + +pci:v00001425d00005792* + ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller + +pci:v00001425d00005793* + ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Ethernet Controller + +pci:v00001425d00005794* + ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Ethernet Controller + +pci:v00001425d00005795* + ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Ethernet Controller + +pci:v00001425d00005796* + ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Ethernet Controller + +pci:v00001425d00005797* + ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller + +pci:v00001425d00005801* + ID_MODEL_FROM_DATABASE=T520-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005802* + ID_MODEL_FROM_DATABASE=T522-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005803* + ID_MODEL_FROM_DATABASE=T540-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005804* + ID_MODEL_FROM_DATABASE=T520-BCH Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005805* + ID_MODEL_FROM_DATABASE=T540-BCH Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005806* + ID_MODEL_FROM_DATABASE=T540-CH Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005807* + ID_MODEL_FROM_DATABASE=T520-SO Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005808* + ID_MODEL_FROM_DATABASE=T520-CX Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005809* + ID_MODEL_FROM_DATABASE=T520-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000580A* + ID_MODEL_FROM_DATABASE=T504-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000580B* + ID_MODEL_FROM_DATABASE=B520-SR Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000580C* + ID_MODEL_FROM_DATABASE=B504-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000580D* + ID_MODEL_FROM_DATABASE=T580-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000580E* + ID_MODEL_FROM_DATABASE=T540-LP-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000580F* + ID_MODEL_FROM_DATABASE=T540 [Amsterdam] Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005810* + ID_MODEL_FROM_DATABASE=T580-LP-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005811* + ID_MODEL_FROM_DATABASE=T520-LL-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005812* + ID_MODEL_FROM_DATABASE=T560-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005813* + ID_MODEL_FROM_DATABASE=T580-CHR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005814* + ID_MODEL_FROM_DATABASE=T580-SO-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005815* + ID_MODEL_FROM_DATABASE=T502-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005816* + ID_MODEL_FROM_DATABASE=T580-OCP-SO Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005817* + ID_MODEL_FROM_DATABASE=T520-OCP-SO Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005818* + ID_MODEL_FROM_DATABASE=T540-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005819* + ID_MODEL_FROM_DATABASE=T540-LP-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000581A* + ID_MODEL_FROM_DATABASE=T540-SO-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000581B* + ID_MODEL_FROM_DATABASE=T540-SO-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005880* + ID_MODEL_FROM_DATABASE=T540-5080 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005881* + ID_MODEL_FROM_DATABASE=T540-5081 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005882* + ID_MODEL_FROM_DATABASE=T504-5082 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005883* + ID_MODEL_FROM_DATABASE=T540-5083 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005884* + ID_MODEL_FROM_DATABASE=T540-5084 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005885* + ID_MODEL_FROM_DATABASE=T580-5085 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005886* + ID_MODEL_FROM_DATABASE=T580-5086 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005887* + ID_MODEL_FROM_DATABASE=T580-5087 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005888* + ID_MODEL_FROM_DATABASE=T570-5088 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005889* + ID_MODEL_FROM_DATABASE=T520-5089 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005890* + ID_MODEL_FROM_DATABASE=T540-5090 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005891* + ID_MODEL_FROM_DATABASE=T522-5091 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005892* + ID_MODEL_FROM_DATABASE=T520-5092 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005893* + ID_MODEL_FROM_DATABASE=T580-5093 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005894* + ID_MODEL_FROM_DATABASE=T540-5094 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005895* + ID_MODEL_FROM_DATABASE=T540-5095 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005896* + ID_MODEL_FROM_DATABASE=T580-5096 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005897* + ID_MODEL_FROM_DATABASE=T520-5097 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005898* + ID_MODEL_FROM_DATABASE=T580-5098 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00005899* + ID_MODEL_FROM_DATABASE=T580-5099 Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000589A* + ID_MODEL_FROM_DATABASE=T520-509A Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000589B* + ID_MODEL_FROM_DATABASE=T540-509B Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000589C* + ID_MODEL_FROM_DATABASE=T520-509C Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000589D* + ID_MODEL_FROM_DATABASE=T540-509D Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000589E* + ID_MODEL_FROM_DATABASE=T520-509E Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000589F* + ID_MODEL_FROM_DATABASE=T540-509F Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058A0* + ID_MODEL_FROM_DATABASE=T540-50A0 Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058A1* + ID_MODEL_FROM_DATABASE=T540-50A1 Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058A2* + ID_MODEL_FROM_DATABASE=T580-50A2 Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058A3* + ID_MODEL_FROM_DATABASE=T580-50A3 Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058A4* + ID_MODEL_FROM_DATABASE=T540-50A4 Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058A5* + ID_MODEL_FROM_DATABASE=T522-50A5 Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058A6* + ID_MODEL_FROM_DATABASE=T522-50A6 Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058A7* + ID_MODEL_FROM_DATABASE=T580-50A7 Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058A8* + ID_MODEL_FROM_DATABASE=T580-50A8 Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058A9* + ID_MODEL_FROM_DATABASE=T580-50A9 Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058AA* + ID_MODEL_FROM_DATABASE=T580-50AA Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058AB* + ID_MODEL_FROM_DATABASE=T520-50AB Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058AC* + ID_MODEL_FROM_DATABASE=T540-50AC Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058AD* + ID_MODEL_FROM_DATABASE=T520-50AD Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058AE* + ID_MODEL_FROM_DATABASE=T540-50AE Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058AF* + ID_MODEL_FROM_DATABASE=T580-50AF Unified Wire Ethernet Controller [VF] + +pci:v00001425d000058B0* + ID_MODEL_FROM_DATABASE=T520-50B0 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006001* + ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller + +pci:v00001425d00006002* + ID_MODEL_FROM_DATABASE=T6225-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006003* + ID_MODEL_FROM_DATABASE=T6425-CR Unified Wire Ethernet Controller + +pci:v00001425d00006004* + ID_MODEL_FROM_DATABASE=T6425-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006005* + ID_MODEL_FROM_DATABASE=T6225-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006006* + ID_MODEL_FROM_DATABASE=T62100-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006007* + ID_MODEL_FROM_DATABASE=T62100-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d00006008* + ID_MODEL_FROM_DATABASE=T62100-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006009* + ID_MODEL_FROM_DATABASE=T6210-BT Unified Wire Ethernet Controller + +pci:v00001425d0000600D* + ID_MODEL_FROM_DATABASE=T62100-CR Unified Wire Ethernet Controller + +pci:v00001425d00006011* + ID_MODEL_FROM_DATABASE=T6225-LL-CR Unified Wire Ethernet Controller + +pci:v00001425d00006014* + ID_MODEL_FROM_DATABASE=T61100-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006015* + ID_MODEL_FROM_DATABASE=T6201-BT Unified Wire Ethernet Controller + +pci:v00001425d00006080* + ID_MODEL_FROM_DATABASE=T6225-6080 Unified Wire Ethernet Controller + +pci:v00001425d00006081* + ID_MODEL_FROM_DATABASE=T62100-6081 Unified Wire Ethernet Controller + +pci:v00001425d00006082* + ID_MODEL_FROM_DATABASE=T6225-6082 Unified Wire Ethernet Controller + +pci:v00001425d00006083* + ID_MODEL_FROM_DATABASE=T62100-6083 Unified Wire Ethernet Controller + +pci:v00001425d00006084* + ID_MODEL_FROM_DATABASE=T64100-6084 Unified Wire Ethernet Controller + +pci:v00001425d00006085* + ID_MODEL_FROM_DATABASE=T6240-6085 Unified Wire Ethernet Controller + +pci:v00001425d00006086* + ID_MODEL_FROM_DATABASE=T6225-6086 Unified Wire Ethernet Controller + +pci:v00001425d00006087* + ID_MODEL_FROM_DATABASE=T6225-6087 Unified Wire Ethernet Controller + +pci:v00001425d00006088* + ID_MODEL_FROM_DATABASE=T62100-6088 Unified Wire Ethernet Controller + +pci:v00001425d00006089* + ID_MODEL_FROM_DATABASE=T62100-6089 Unified Wire Ethernet Controller + +pci:v00001425d0000608A* + ID_MODEL_FROM_DATABASE=T62100-608a Unified Wire Ethernet Controller + +pci:v00001425d00006401* + ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller + +pci:v00001425d00006402* + ID_MODEL_FROM_DATABASE=T6225-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006403* + ID_MODEL_FROM_DATABASE=T6425-CR Unified Wire Ethernet Controller + +pci:v00001425d00006404* + ID_MODEL_FROM_DATABASE=T6425-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006405* + ID_MODEL_FROM_DATABASE=T6225-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006406* + ID_MODEL_FROM_DATABASE=T62100-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006407* + ID_MODEL_FROM_DATABASE=T62100-LP-CR Unified Wire Ethernet Controller + +pci:v00001425d00006408* + ID_MODEL_FROM_DATABASE=T62100-SO-CR Unified Wire Ethernet Controller + +pci:v00001425d00006409* + ID_MODEL_FROM_DATABASE=T6210-BT Unified Wire Ethernet Controller + +pci:v00001425d0000640D* + ID_MODEL_FROM_DATABASE=T62100-CR Unified Wire Ethernet Controller + +pci:v00001425d00006411* + ID_MODEL_FROM_DATABASE=T6225-LL-CR Unified Wire Ethernet Controller + +pci:v00001425d00006414* + ID_MODEL_FROM_DATABASE=T61100-OCP-SO Unified Wire Ethernet Controller + +pci:v00001425d00006415* + ID_MODEL_FROM_DATABASE=T6201-BT Unified Wire Ethernet Controller + +pci:v00001425d00006480* + ID_MODEL_FROM_DATABASE=T6225-6080 Unified Wire Ethernet Controller + +pci:v00001425d00006481* + ID_MODEL_FROM_DATABASE=T62100-6081 Unified Wire Ethernet Controller + +pci:v00001425d00006482* + ID_MODEL_FROM_DATABASE=T6225-6082 Unified Wire Ethernet Controller + +pci:v00001425d00006483* + ID_MODEL_FROM_DATABASE=T62100-6083 Unified Wire Ethernet Controller + +pci:v00001425d00006484* + ID_MODEL_FROM_DATABASE=T64100-6084 Unified Wire Ethernet Controller + +pci:v00001425d00006485* + ID_MODEL_FROM_DATABASE=T6240-6085 Unified Wire Ethernet Controller + +pci:v00001425d00006486* + ID_MODEL_FROM_DATABASE=T6225-6086 Unified Wire Ethernet Controller + +pci:v00001425d00006487* + ID_MODEL_FROM_DATABASE=T6225-6087 Unified Wire Ethernet Controller + +pci:v00001425d00006488* + ID_MODEL_FROM_DATABASE=T62100-6088 Unified Wire Ethernet Controller + +pci:v00001425d00006489* + ID_MODEL_FROM_DATABASE=T62100-6089 Unified Wire Ethernet Controller + +pci:v00001425d0000648A* + ID_MODEL_FROM_DATABASE=T62100-608a Unified Wire Ethernet Controller + +pci:v00001425d00006501* + ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Storage Controller + +pci:v00001425d00006502* + ID_MODEL_FROM_DATABASE=T6225-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006503* + ID_MODEL_FROM_DATABASE=T6425-CR Unified Wire Storage Controller + +pci:v00001425d00006504* + ID_MODEL_FROM_DATABASE=T6425-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006505* + ID_MODEL_FROM_DATABASE=T6225-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006506* + ID_MODEL_FROM_DATABASE=T62100-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006507* + ID_MODEL_FROM_DATABASE=T62100-LP-CR Unified Wire Storage Controller + +pci:v00001425d00006508* + ID_MODEL_FROM_DATABASE=T62100-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006509* + ID_MODEL_FROM_DATABASE=T6210-BT Unified Wire Storage Controller + +pci:v00001425d0000650D* + ID_MODEL_FROM_DATABASE=T62100-CR Unified Wire Storage Controller + +pci:v00001425d00006511* + ID_MODEL_FROM_DATABASE=T6225-LL-CR Unified Wire Storage Controller + +pci:v00001425d00006514* + ID_MODEL_FROM_DATABASE=T61100-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006515* + ID_MODEL_FROM_DATABASE=T6201-BT Unified Wire Storage Controller + +pci:v00001425d00006580* + ID_MODEL_FROM_DATABASE=T6225-6080 Unified Wire Storage Controller + +pci:v00001425d00006581* + ID_MODEL_FROM_DATABASE=T62100-6081 Unified Wire Storage Controller + +pci:v00001425d00006582* + ID_MODEL_FROM_DATABASE=T6225-6082 Unified Wire Storage Controller + +pci:v00001425d00006583* + ID_MODEL_FROM_DATABASE=T62100-6083 Unified Wire Storage Controller + +pci:v00001425d00006584* + ID_MODEL_FROM_DATABASE=T64100-6084 Unified Wire Storage Controller + +pci:v00001425d00006585* + ID_MODEL_FROM_DATABASE=T6240-6085 Unified Wire Storage Controller + +pci:v00001425d00006586* + ID_MODEL_FROM_DATABASE=T6225-6086 Unified Wire Storage Controller + +pci:v00001425d00006587* + ID_MODEL_FROM_DATABASE=T6225-6087 Unified Wire Storage Controller + +pci:v00001425d00006588* + ID_MODEL_FROM_DATABASE=T62100-6088 Unified Wire Storage Controller + +pci:v00001425d00006589* + ID_MODEL_FROM_DATABASE=T62100-6089 Unified Wire Storage Controller + +pci:v00001425d0000658A* + ID_MODEL_FROM_DATABASE=T62100-608a Unified Wire Storage Controller + +pci:v00001425d00006601* + ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Storage Controller + +pci:v00001425d00006602* + ID_MODEL_FROM_DATABASE=T6225-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006603* + ID_MODEL_FROM_DATABASE=T6425-CR Unified Wire Storage Controller + +pci:v00001425d00006604* + ID_MODEL_FROM_DATABASE=T6425-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006605* + ID_MODEL_FROM_DATABASE=T6225-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006606* + ID_MODEL_FROM_DATABASE=T62100-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006607* + ID_MODEL_FROM_DATABASE=T62100-LP-CR Unified Wire Storage Controller + +pci:v00001425d00006608* + ID_MODEL_FROM_DATABASE=T62100-SO-CR Unified Wire Storage Controller + +pci:v00001425d00006609* + ID_MODEL_FROM_DATABASE=T6210-BT Unified Wire Storage Controller + +pci:v00001425d0000660D* + ID_MODEL_FROM_DATABASE=T62100-CR Unified Wire Storage Controller + +pci:v00001425d00006611* + ID_MODEL_FROM_DATABASE=T6225-LL-CR Unified Wire Storage Controller + +pci:v00001425d00006614* + ID_MODEL_FROM_DATABASE=T61100-OCP-SO Unified Wire Storage Controller + +pci:v00001425d00006615* + ID_MODEL_FROM_DATABASE=T6201-BT Unified Wire Storage Controller + +pci:v00001425d00006680* + ID_MODEL_FROM_DATABASE=T6225-6080 Unified Wire Storage Controller + +pci:v00001425d00006681* + ID_MODEL_FROM_DATABASE=T62100-6081 Unified Wire Storage Controller + +pci:v00001425d00006682* + ID_MODEL_FROM_DATABASE=T6225-6082 Unified Wire Storage Controller + +pci:v00001425d00006683* + ID_MODEL_FROM_DATABASE=T62100-6083 Unified Wire Storage Controller + +pci:v00001425d00006684* + ID_MODEL_FROM_DATABASE=T64100-6084 Unified Wire Storage Controller + +pci:v00001425d00006685* + ID_MODEL_FROM_DATABASE=T6240-6085 Unified Wire Storage Controller + +pci:v00001425d00006686* + ID_MODEL_FROM_DATABASE=T6225-6086 Unified Wire Storage Controller + +pci:v00001425d00006687* + ID_MODEL_FROM_DATABASE=T6225-6087 Unified Wire Storage Controller + +pci:v00001425d00006688* + ID_MODEL_FROM_DATABASE=T62100-6088 Unified Wire Storage Controller + +pci:v00001425d00006689* + ID_MODEL_FROM_DATABASE=T62100-6089 Unified Wire Storage Controller + +pci:v00001425d0000668A* + ID_MODEL_FROM_DATABASE=T62100-608a Unified Wire Storage Controller + +pci:v00001425d00006801* + ID_MODEL_FROM_DATABASE=T6225-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006802* + ID_MODEL_FROM_DATABASE=T6225-SO-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006803* + ID_MODEL_FROM_DATABASE=T6425-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006804* + ID_MODEL_FROM_DATABASE=T6425-SO-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006805* + ID_MODEL_FROM_DATABASE=T6225-OCP-SO Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006806* + ID_MODEL_FROM_DATABASE=T62100-OCP-SO Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006807* + ID_MODEL_FROM_DATABASE=T62100-LP-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006808* + ID_MODEL_FROM_DATABASE=T62100-SO-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006809* + ID_MODEL_FROM_DATABASE=T6210-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000680D* + ID_MODEL_FROM_DATABASE=T62100-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006811* + ID_MODEL_FROM_DATABASE=T6225-LL-CR Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006814* + ID_MODEL_FROM_DATABASE=T61100-OCP-SO Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006815* + ID_MODEL_FROM_DATABASE=T6201-BT Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006880* + ID_MODEL_FROM_DATABASE=T6225-6080 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006881* + ID_MODEL_FROM_DATABASE=T62100-6081 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006882* + ID_MODEL_FROM_DATABASE=T6225-6082 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006883* + ID_MODEL_FROM_DATABASE=T62100-6083 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006884* + ID_MODEL_FROM_DATABASE=T64100-6084 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006885* + ID_MODEL_FROM_DATABASE=T6240-6085 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006886* + ID_MODEL_FROM_DATABASE=T6225-6086 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006887* + ID_MODEL_FROM_DATABASE=T6225-6087 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006888* + ID_MODEL_FROM_DATABASE=T62100-6088 Unified Wire Ethernet Controller [VF] + +pci:v00001425d00006889* + ID_MODEL_FROM_DATABASE=T62100-6089 Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000688A* + ID_MODEL_FROM_DATABASE=T62100-608a Unified Wire Ethernet Controller [VF] + +pci:v00001425d0000A000* + ID_MODEL_FROM_DATABASE=PE10K Unified Wire Ethernet Controller + +pci:v00001426* + ID_VENDOR_FROM_DATABASE=Storage Technology Corp. + +pci:v00001427* + ID_VENDOR_FROM_DATABASE=Better On-Line Solutions + +pci:v00001428* + ID_VENDOR_FROM_DATABASE=Edec Co Ltd + +pci:v00001429* + ID_VENDOR_FROM_DATABASE=Unex Technology Corp. + +pci:v0000142A* + ID_VENDOR_FROM_DATABASE=Kingmax Technology Inc + +pci:v0000142B* + ID_VENDOR_FROM_DATABASE=Radiolan + +pci:v0000142C* + ID_VENDOR_FROM_DATABASE=Minton Optic Industry Co Ltd + +pci:v0000142D* + ID_VENDOR_FROM_DATABASE=Pix stream Inc + +pci:v0000142E* + ID_VENDOR_FROM_DATABASE=Vitec Multimedia + +pci:v0000142Ed00004020* + ID_MODEL_FROM_DATABASE=VM2-2 [Video Maker 2] MPEG1/2 Encoder + +pci:v0000142Ed00004337* + ID_MODEL_FROM_DATABASE=VM2-2-C7 [Video Maker 2 rev. C7] MPEG1/2 Encoder + +pci:v0000142F* + ID_VENDOR_FROM_DATABASE=Radicom Research Inc + +pci:v00001430* + ID_VENDOR_FROM_DATABASE=ITT Aerospace/Communications Division + +pci:v00001431* + ID_VENDOR_FROM_DATABASE=Gilat Satellite Networks + +pci:v00001432* + ID_VENDOR_FROM_DATABASE=Edimax Computer Co. + +pci:v00001432d00009130* + ID_MODEL_FROM_DATABASE=RTL81xx Fast Ethernet + +pci:v00001433* + ID_VENDOR_FROM_DATABASE=Eltec Elektronik GmbH + +pci:v00001435* + ID_VENDOR_FROM_DATABASE=RTD Embedded Technologies, Inc. + +pci:v00001435d00004520* + ID_MODEL_FROM_DATABASE=PCI4520 + +pci:v00001435d00006020* + ID_MODEL_FROM_DATABASE=SPM6020 + +pci:v00001435d00006030* + ID_MODEL_FROM_DATABASE=SPM6030 + +pci:v00001435d00006420* + ID_MODEL_FROM_DATABASE=SPM186420 + +pci:v00001435d00006430* + ID_MODEL_FROM_DATABASE=SPM176430 + +pci:v00001435d00006431* + ID_MODEL_FROM_DATABASE=SPM176431 + +pci:v00001435d00007520* + ID_MODEL_FROM_DATABASE=DM7520 + +pci:v00001435d00007540* + ID_MODEL_FROM_DATABASE=SDM7540 + +pci:v00001435d00007820* + ID_MODEL_FROM_DATABASE=DM7820 + +pci:v00001436* + ID_VENDOR_FROM_DATABASE=CIS Technology Inc + +pci:v00001437* + ID_VENDOR_FROM_DATABASE=Nissin Inc Co + +pci:v00001438* + ID_VENDOR_FROM_DATABASE=Atmel-dream + +pci:v00001439* + ID_VENDOR_FROM_DATABASE=Outsource Engineering & Mfg. Inc + +pci:v0000143A* + ID_VENDOR_FROM_DATABASE=Stargate Solutions Inc + +pci:v0000143B* + ID_VENDOR_FROM_DATABASE=Canon Research Center, America + +pci:v0000143C* + ID_VENDOR_FROM_DATABASE=Amlogic Inc + +pci:v0000143D* + ID_VENDOR_FROM_DATABASE=Tamarack Microelectronics Inc + +pci:v0000143E* + ID_VENDOR_FROM_DATABASE=Jones Futurex Inc + +pci:v0000143F* + ID_VENDOR_FROM_DATABASE=Lightwell Co Ltd - Zax Division + +pci:v00001440* + ID_VENDOR_FROM_DATABASE=ALGOL Corp. + +pci:v00001441* + ID_VENDOR_FROM_DATABASE=AGIE Ltd + +pci:v00001442* + ID_VENDOR_FROM_DATABASE=Phoenix Contact GmbH & Co. + +pci:v00001443* + ID_VENDOR_FROM_DATABASE=Unibrain S.A. + +pci:v00001444* + ID_VENDOR_FROM_DATABASE=TRW + +pci:v00001445* + ID_VENDOR_FROM_DATABASE=Logical DO Ltd + +pci:v00001446* + ID_VENDOR_FROM_DATABASE=Graphin Co Ltd + +pci:v00001447* + ID_VENDOR_FROM_DATABASE=AIM GmBH + +pci:v00001448* + ID_VENDOR_FROM_DATABASE=Alesis Studio Electronics + +pci:v00001449* + ID_VENDOR_FROM_DATABASE=TUT Systems Inc + +pci:v0000144A* + ID_VENDOR_FROM_DATABASE=Adlink Technology + +pci:v0000144Ad00006208* + ID_MODEL_FROM_DATABASE=PCI-6208V + +pci:v0000144Ad00007250* + ID_MODEL_FROM_DATABASE=PCI-7250 + +pci:v0000144Ad00007296* + ID_MODEL_FROM_DATABASE=PCI-7296 + +pci:v0000144Ad00007432* + ID_MODEL_FROM_DATABASE=PCI-7432 + +pci:v0000144Ad00007433* + ID_MODEL_FROM_DATABASE=PCI-7433 + +pci:v0000144Ad00007434* + ID_MODEL_FROM_DATABASE=PCI-7434 + +pci:v0000144Ad00007841* + ID_MODEL_FROM_DATABASE=PCI-7841 + +pci:v0000144Ad00008133* + ID_MODEL_FROM_DATABASE=PCI-8133 + +pci:v0000144Ad00008164* + ID_MODEL_FROM_DATABASE=PCI-8164 + +pci:v0000144Ad00008554* + ID_MODEL_FROM_DATABASE=PCI-8554 + +pci:v0000144Ad00009111* + ID_MODEL_FROM_DATABASE=PCI-9111 + +pci:v0000144Ad00009113* + ID_MODEL_FROM_DATABASE=PCI-9113 + +pci:v0000144Ad00009114* + ID_MODEL_FROM_DATABASE=PCI-9114 + +pci:v0000144Ad0000A001* + ID_MODEL_FROM_DATABASE=ADi-BSEC + +pci:v0000144B* + ID_VENDOR_FROM_DATABASE=Verint Systems Inc. + +pci:v0000144C* + ID_VENDOR_FROM_DATABASE=Catalina Research Inc + +pci:v0000144D* + ID_VENDOR_FROM_DATABASE=Samsung Electronics Co Ltd + +pci:v0000144Dd00001600* + ID_MODEL_FROM_DATABASE=Apple PCIe SSD + +pci:v0000144Dd0000A800* + ID_MODEL_FROM_DATABASE=XP941 PCIe SSD + +pci:v0000144Dd0000A802* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM951/PM951 + +pci:v0000144Dd0000A804* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM961/PM961 + +pci:v0000144Dd0000A808* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM981/PM981/PM983 + +pci:v0000144Dd0000A808sv00001D49sd0000403B* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller SM981/PM981/PM983 (Thinksystem U.2 PM983 NVMe SSD) + +pci:v0000144Dd0000A820* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X + +pci:v0000144Dd0000A820sv00001028sd00001F95* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe XS1715 SSD 400GB) + +pci:v0000144Dd0000A820sv00001028sd00001F96* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe XS1715 SSD 800GB) + +pci:v0000144Dd0000A820sv00001028sd00001F97* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe XS1715 SSD 1600GB) + +pci:v0000144Dd0000A820sv00001028sd00001FA4* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 3.2TB SFF) + +pci:v0000144Dd0000A820sv00001028sd00001FA6* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 3.2TB AIC) + +pci:v0000144Dd0000A820sv00001028sd00001FBA* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 800GB SFF) + +pci:v0000144Dd0000A820sv00001028sd00001FBB* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 1.6TB SFF) + +pci:v0000144Dd0000A820sv00001028sd00001FBC* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 171X (Express Flash NVMe SM1715 1.6TB AIC) + +pci:v0000144Dd0000A821* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X + +pci:v0000144Dd0000A821sv00001028sd00001FB7* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 3.2TB SFF) + +pci:v0000144Dd0000A821sv00001028sd00001FB8* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 3.2TB AIC) + +pci:v0000144Dd0000A821sv00001028sd00001FB9* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 6.4TB AIC) + +pci:v0000144Dd0000A821sv00001028sd00001FC1* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 800GB SFF) + +pci:v0000144Dd0000A821sv00001028sd00001FC2* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 1.6TB SFF) + +pci:v0000144Dd0000A821sv00001028sd00001FC4* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172X (Express Flash NVMe PM1725 1.6TB AIC) + +pci:v0000144Dd0000A822* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb + +pci:v0000144Dd0000A822sv00001014sd00000621* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (PCIe3 1.6TB NVMe Flash Adapter II x8) + +pci:v0000144Dd0000A822sv00001014sd00000622* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (PCIe3 3.2TB NVMe Flash Adapter II x8) + +pci:v0000144Dd0000A822sv00001014sd00000629* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (PCIe3 6.4TB NVMe Flash Adapter II x8) + +pci:v0000144Dd0000A822sv00001014sd0000064A* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (PCIe3 1.6TB NVMe Flash Adapter III x8) + +pci:v0000144Dd0000A822sv00001014sd0000064B* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (PCIe3 3.2TB NVMe Flash Adapter III x8) + +pci:v0000144Dd0000A822sv00001014sd0000064C* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (PCIe3 6.4TB NVMe Flash Adapter III x8) + +pci:v0000144Dd0000A822sv00001028sd00001FD9* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 800GB SFF) + +pci:v0000144Dd0000A822sv00001028sd00001FDA* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 1.6TB SFF) + +pci:v0000144Dd0000A822sv00001028sd00001FDB* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 3.2TB SFF) + +pci:v0000144Dd0000A822sv00001028sd00001FDC* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 6.4TB SFF) + +pci:v0000144Dd0000A822sv00001028sd00001FDD* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 1.6TB AIC) + +pci:v0000144Dd0000A822sv00001028sd00001FDE* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 3.2TB AIC) + +pci:v0000144Dd0000A822sv00001028sd00001FDF* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725a 6.4TB AIC) + +pci:v0000144Dd0000A822sv00001028sd00001FF3* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 1.6TB SFF) + +pci:v0000144Dd0000A822sv00001028sd00001FF4* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 3.2TB SFF) + +pci:v0000144Dd0000A822sv00001028sd00001FF5* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 6.4TB SFF) + +pci:v0000144Dd0000A822sv00001028sd00001FF6* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 12.8TB SFF) + +pci:v0000144Dd0000A822sv00001028sd00001FF7* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 1.6TB AIC) + +pci:v0000144Dd0000A822sv00001028sd00001FF8* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 3.2TB AIC) + +pci:v0000144Dd0000A822sv00001028sd00001FF9* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 6.4TB AIC) + +pci:v0000144Dd0000A822sv00001028sd00001FFA* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller 172Xa/172Xb (Express Flash PM1725b 12.8TB AIC) + +pci:v0000144E* + ID_VENDOR_FROM_DATABASE=OLITEC + +pci:v0000144F* + ID_VENDOR_FROM_DATABASE=Askey Computer Corp. + +pci:v00001450* + ID_VENDOR_FROM_DATABASE=Octave Communications Ind. + +pci:v00001451* + ID_VENDOR_FROM_DATABASE=SP3D Chip Design GmBH + +pci:v00001453* + ID_VENDOR_FROM_DATABASE=MYCOM Inc + +pci:v00001454* + ID_VENDOR_FROM_DATABASE=Altiga Networks + +pci:v00001455* + ID_VENDOR_FROM_DATABASE=Logic Plus Plus Inc + +pci:v00001456* + ID_VENDOR_FROM_DATABASE=Advanced Hardware Architectures + +pci:v00001457* + ID_VENDOR_FROM_DATABASE=Nuera Communications Inc + +pci:v00001458* + ID_VENDOR_FROM_DATABASE=Gigabyte Technology Co., Ltd + +pci:v00001459* + ID_VENDOR_FROM_DATABASE=DOOIN Electronics + +pci:v0000145A* + ID_VENDOR_FROM_DATABASE=Escalate Networks Inc + +pci:v0000145B* + ID_VENDOR_FROM_DATABASE=PRAIM SRL + +pci:v0000145C* + ID_VENDOR_FROM_DATABASE=Cryptek + +pci:v0000145D* + ID_VENDOR_FROM_DATABASE=Gallant Computer Inc + +pci:v0000145E* + ID_VENDOR_FROM_DATABASE=Aashima Technology B.V. + +pci:v0000145F* + ID_VENDOR_FROM_DATABASE=Baldor Electric Company + +pci:v0000145Fd00000001* + ID_MODEL_FROM_DATABASE=NextMove PCI + +pci:v00001460* + ID_VENDOR_FROM_DATABASE=DYNARC INC + +pci:v00001461* + ID_VENDOR_FROM_DATABASE=Avermedia Technologies Inc + +pci:v00001461d0000A3CE* + ID_MODEL_FROM_DATABASE=M179 + +pci:v00001461d0000A3CF* + ID_MODEL_FROM_DATABASE=M179 + +pci:v00001461d0000A836* + ID_MODEL_FROM_DATABASE=M115 DVB-T, PAL/SECAM/NTSC Tuner + +pci:v00001461d0000E836* + ID_MODEL_FROM_DATABASE=M115S Hybrid Analog/DVB PAL/SECAM/NTSC Tuner + +pci:v00001461d0000F436* + ID_MODEL_FROM_DATABASE=AVerTV Hybrid+FM + +pci:v00001462* + ID_VENDOR_FROM_DATABASE=Micro-Star International Co., Ltd. [MSI] + +pci:v00001462d0000AAF0* + ID_MODEL_FROM_DATABASE=Radeon RX 580 Gaming X 8G + +pci:v00001463* + ID_VENDOR_FROM_DATABASE=Fast Corporation + +pci:v00001464* + ID_VENDOR_FROM_DATABASE=Interactive Circuits & Systems Ltd + +pci:v00001465* + ID_VENDOR_FROM_DATABASE=GN NETTEST Telecom DIV. + +pci:v00001466* + ID_VENDOR_FROM_DATABASE=Designpro Inc. + +pci:v00001467* + ID_VENDOR_FROM_DATABASE=DIGICOM SPA + +pci:v00001468* + ID_VENDOR_FROM_DATABASE=AMBIT Microsystem Corp. + +pci:v00001469* + ID_VENDOR_FROM_DATABASE=Cleveland Motion Controls + +pci:v0000146A* + ID_VENDOR_FROM_DATABASE=Aeroflex + +pci:v0000146Ad00003010* + ID_MODEL_FROM_DATABASE=3010 RF Synthesizer + +pci:v0000146Ad00003A11* + ID_MODEL_FROM_DATABASE=3011A PXI RF Synthesizer + +pci:v0000146B* + ID_VENDOR_FROM_DATABASE=Parascan Technologies Ltd + +pci:v0000146C* + ID_VENDOR_FROM_DATABASE=Ruby Tech Corp. + +pci:v0000146Cd00001430* + ID_MODEL_FROM_DATABASE=FE-1430TX Fast Ethernet PCI Adapter + +pci:v0000146D* + ID_VENDOR_FROM_DATABASE=Tachyon, INC. + +pci:v0000146E* + ID_VENDOR_FROM_DATABASE=Williams Electronics Games, Inc. + +pci:v0000146F* + ID_VENDOR_FROM_DATABASE=Multi Dimensional Consulting Inc + +pci:v00001470* + ID_VENDOR_FROM_DATABASE=Bay Networks + +pci:v00001471* + ID_VENDOR_FROM_DATABASE=Integrated Telecom Express Inc + +pci:v00001472* + ID_VENDOR_FROM_DATABASE=DAIKIN Industries, Ltd + +pci:v00001473* + ID_VENDOR_FROM_DATABASE=ZAPEX Technologies Inc + +pci:v00001474* + ID_VENDOR_FROM_DATABASE=Doug Carson & Associates + +pci:v00001475* + ID_VENDOR_FROM_DATABASE=PICAZO Communications + +pci:v00001476* + ID_VENDOR_FROM_DATABASE=MORTARA Instrument Inc + +pci:v00001477* + ID_VENDOR_FROM_DATABASE=Net Insight + +pci:v00001478* + ID_VENDOR_FROM_DATABASE=DIATREND Corporation + +pci:v00001479* + ID_VENDOR_FROM_DATABASE=TORAY Industries Inc + +pci:v0000147A* + ID_VENDOR_FROM_DATABASE=FORMOSA Industrial Computing + +pci:v0000147B* + ID_VENDOR_FROM_DATABASE=ABIT Computer Corp. + +pci:v0000147Bd00001084* + ID_MODEL_FROM_DATABASE=IP35 [Dark Raider] + +pci:v0000147C* + ID_VENDOR_FROM_DATABASE=AWARE, Inc. + +pci:v0000147D* + ID_VENDOR_FROM_DATABASE=Interworks Computer Products + +pci:v0000147E* + ID_VENDOR_FROM_DATABASE=Matsushita Graphic Communication Systems, Inc. + +pci:v0000147F* + ID_VENDOR_FROM_DATABASE=NIHON UNISYS, Ltd. + +pci:v00001480* + ID_VENDOR_FROM_DATABASE=SCII Telecom + +pci:v00001481* + ID_VENDOR_FROM_DATABASE=BIOPAC Systems Inc + +pci:v00001482* + ID_VENDOR_FROM_DATABASE=ISYTEC - Integrierte Systemtechnik GmBH + +pci:v00001482d00000001* + ID_MODEL_FROM_DATABASE=PCI-16 Host Interface for ITC-16 + +pci:v00001483* + ID_VENDOR_FROM_DATABASE=LABWAY Corporation + +pci:v00001484* + ID_VENDOR_FROM_DATABASE=Logic Corporation + +pci:v00001485* + ID_VENDOR_FROM_DATABASE=ERMA - Electronic GmBH + +pci:v00001486* + ID_VENDOR_FROM_DATABASE=L3 Communications Telemetry & Instrumentation + +pci:v00001487* + ID_VENDOR_FROM_DATABASE=MARQUETTE Medical Systems + +pci:v00001489* + ID_VENDOR_FROM_DATABASE=KYE Systems Corporation + +pci:v0000148A* + ID_VENDOR_FROM_DATABASE=OPTO + +pci:v0000148B* + ID_VENDOR_FROM_DATABASE=INNOMEDIALOGIC Inc. + +pci:v0000148C* + ID_VENDOR_FROM_DATABASE=Tul Corporation / PowerColor + +pci:v0000148D* + ID_VENDOR_FROM_DATABASE=DIGICOM Systems, Inc. + +pci:v0000148Dd00001003* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem + +pci:v0000148E* + ID_VENDOR_FROM_DATABASE=OSI Plus Corporation + +pci:v0000148F* + ID_VENDOR_FROM_DATABASE=Plant Equipment, Inc. + +pci:v00001490* + ID_VENDOR_FROM_DATABASE=Stone Microsystems PTY Ltd. + +pci:v00001491* + ID_VENDOR_FROM_DATABASE=ZEAL Corporation + +pci:v00001492* + ID_VENDOR_FROM_DATABASE=Time Logic Corporation + +pci:v00001493* + ID_VENDOR_FROM_DATABASE=MAKER Communications + +pci:v00001494* + ID_VENDOR_FROM_DATABASE=WINTOP Technology, Inc. + +pci:v00001495* + ID_VENDOR_FROM_DATABASE=TOKAI Communications Industry Co. Ltd + +pci:v00001496* + ID_VENDOR_FROM_DATABASE=JOYTECH Computer Co., Ltd. + +pci:v00001497* + ID_VENDOR_FROM_DATABASE=SMA Regelsysteme GmBH + +pci:v00001497d00001497* + ID_MODEL_FROM_DATABASE=SMA Technologie AG + +pci:v00001498* + ID_VENDOR_FROM_DATABASE=TEWS Technologies GmbH + +pci:v00001498d00000330* + ID_MODEL_FROM_DATABASE=TPMC816 2 Channel CAN bus controller. + +pci:v00001498d0000035D* + ID_MODEL_FROM_DATABASE=TPMC861 4-Channel Isolated Serial Interface RS422/RS485 + +pci:v00001498d00000385* + ID_MODEL_FROM_DATABASE=TPMC901 Extended CAN bus with 2/4/6 CAN controller + +pci:v00001498d000021CC* + ID_MODEL_FROM_DATABASE=TCP460 CompactPCI 16 Channel Serial Interface RS232/RS422 + +pci:v00001498d000021CD* + ID_MODEL_FROM_DATABASE=TCP461 CompactPCI 8 Channel Serial Interface RS232/RS422 + +pci:v00001498d00003064* + ID_MODEL_FROM_DATABASE=TPCI100 (2 Slot IndustryPack PCI Carrier) + +pci:v00001498d000030C8* + ID_MODEL_FROM_DATABASE=TPCI200 4 Slot IndustryPack PCI Carrier + +pci:v00001498d000070C8* + ID_MODEL_FROM_DATABASE=TPCE200 4 Slot IndustryPack PCIe Carrier + +pci:v00001498d00009177* + ID_MODEL_FROM_DATABASE=TXMC375 8 channel RS232/RS422/RS485 programmable serial interface + +pci:v00001499* + ID_VENDOR_FROM_DATABASE=EMTEC CO., Ltd + +pci:v0000149A* + ID_VENDOR_FROM_DATABASE=ANDOR Technology Ltd + +pci:v0000149B* + ID_VENDOR_FROM_DATABASE=SEIKO Instruments Inc + +pci:v0000149C* + ID_VENDOR_FROM_DATABASE=OVISLINK Corp. + +pci:v0000149D* + ID_VENDOR_FROM_DATABASE=NEWTEK Inc + +pci:v0000149Dd00000001* + ID_MODEL_FROM_DATABASE=Video Toaster for PC + +pci:v0000149E* + ID_VENDOR_FROM_DATABASE=Mapletree Networks Inc. + +pci:v0000149F* + ID_VENDOR_FROM_DATABASE=LECTRON Co Ltd + +pci:v000014A0* + ID_VENDOR_FROM_DATABASE=SOFTING GmBH + +pci:v000014A1* + ID_VENDOR_FROM_DATABASE=Systembase Co Ltd + +pci:v000014A2* + ID_VENDOR_FROM_DATABASE=Millennium Engineering Inc + +pci:v000014A3* + ID_VENDOR_FROM_DATABASE=Maverick Networks + +pci:v000014A4* + ID_VENDOR_FROM_DATABASE=Lite-On Technology Corporation + +pci:v000014A4d000022F1* + ID_MODEL_FROM_DATABASE=M8Pe Series NVMe SSD + +pci:v000014A4d00004318* + ID_MODEL_FROM_DATABASE=Broadcom BCM4318 [AirForce One 54g] 802.11g WLAN Controller + +pci:v000014A5* + ID_VENDOR_FROM_DATABASE=XIONICS Document Technologies Inc + +pci:v000014A6* + ID_VENDOR_FROM_DATABASE=INOVA Computers GmBH & Co KG + +pci:v000014A7* + ID_VENDOR_FROM_DATABASE=MYTHOS Systems Inc + +pci:v000014A8* + ID_VENDOR_FROM_DATABASE=FEATRON Technologies Corporation + +pci:v000014A9* + ID_VENDOR_FROM_DATABASE=HIVERTEC Inc + +pci:v000014AA* + ID_VENDOR_FROM_DATABASE=Advanced MOS Technology Inc + +pci:v000014AB* + ID_VENDOR_FROM_DATABASE=Mentor Graphics Corp. + +pci:v000014AC* + ID_VENDOR_FROM_DATABASE=Novaweb Technologies Inc + +pci:v000014AD* + ID_VENDOR_FROM_DATABASE=Time Space Radio AB + +pci:v000014AE* + ID_VENDOR_FROM_DATABASE=CTI, Inc + +pci:v000014AF* + ID_VENDOR_FROM_DATABASE=Guillemot Corporation + +pci:v000014AFd00007102* + ID_MODEL_FROM_DATABASE=3D Prophet II MX + +pci:v000014B0* + ID_VENDOR_FROM_DATABASE=BST Communication Technology Ltd + +pci:v000014B1* + ID_VENDOR_FROM_DATABASE=Nextcom K.K. + +pci:v000014B2* + ID_VENDOR_FROM_DATABASE=ENNOVATE Networks Inc + +pci:v000014B3* + ID_VENDOR_FROM_DATABASE=XPEED Inc + +pci:v000014B3d00000000* + ID_MODEL_FROM_DATABASE=DSL NIC + +pci:v000014B4* + ID_VENDOR_FROM_DATABASE=PHILIPS Business Electronics B.V. + +pci:v000014B5* + ID_VENDOR_FROM_DATABASE=Creamware GmBH + +pci:v000014B5d00000200* + ID_MODEL_FROM_DATABASE=Scope + +pci:v000014B5d00000300* + ID_MODEL_FROM_DATABASE=Pulsar + +pci:v000014B5d00000400* + ID_MODEL_FROM_DATABASE=PulsarSRB + +pci:v000014B5d00000600* + ID_MODEL_FROM_DATABASE=Pulsar2 + +pci:v000014B5d00000800* + ID_MODEL_FROM_DATABASE=DSP-Board + +pci:v000014B5d00000900* + ID_MODEL_FROM_DATABASE=DSP-Board + +pci:v000014B5d00000A00* + ID_MODEL_FROM_DATABASE=DSP-Board + +pci:v000014B5d00000B00* + ID_MODEL_FROM_DATABASE=DSP-Board + +pci:v000014B6* + ID_VENDOR_FROM_DATABASE=Quantum Data Corp. + +pci:v000014B7* + ID_VENDOR_FROM_DATABASE=PROXIM Inc + +pci:v000014B7d00000001* + ID_MODEL_FROM_DATABASE=Symphony 4110 + +pci:v000014B8* + ID_VENDOR_FROM_DATABASE=Techsoft Technology Co Ltd + +pci:v000014B9* + ID_VENDOR_FROM_DATABASE=Cisco Aironet Wireless Communications + +pci:v000014B9d00000001* + ID_MODEL_FROM_DATABASE=PC4800 + +pci:v000014B9d00000340* + ID_MODEL_FROM_DATABASE=PC4800 + +pci:v000014B9d00000350* + ID_MODEL_FROM_DATABASE=350 series 802.11b Wireless LAN Adapter + +pci:v000014B9d00004500* + ID_MODEL_FROM_DATABASE=PC4500 + +pci:v000014B9d00004800* + ID_MODEL_FROM_DATABASE=Cisco Aironet 340 802.11b Wireless LAN Adapter/Aironet PC4800 + +pci:v000014B9d0000A504* + ID_MODEL_FROM_DATABASE=Cisco Aironet Wireless 802.11b + +pci:v000014B9d0000A505* + ID_MODEL_FROM_DATABASE=Cisco Aironet CB20a 802.11a Wireless LAN Adapter + +pci:v000014B9d0000A506* + ID_MODEL_FROM_DATABASE=Cisco Aironet Mini PCI b/g + +pci:v000014BA* + ID_VENDOR_FROM_DATABASE=INTERNIX Inc. + +pci:v000014BAd00000600* + ID_MODEL_FROM_DATABASE=ARC-PCI/22 + +pci:v000014BB* + ID_VENDOR_FROM_DATABASE=SEMTECH Corporation + +pci:v000014BC* + ID_VENDOR_FROM_DATABASE=Globespan Semiconductor Inc. + +pci:v000014BCd0000D002* + ID_MODEL_FROM_DATABASE=Pulsar [PCI ADSL Card] + +pci:v000014BCd0000D00F* + ID_MODEL_FROM_DATABASE=Pulsar [PCI ADSL Card] + +pci:v000014BD* + ID_VENDOR_FROM_DATABASE=CARDIO Control N.V. + +pci:v000014BE* + ID_VENDOR_FROM_DATABASE=L3 Communications + +pci:v000014BF* + ID_VENDOR_FROM_DATABASE=SPIDER Communications Inc. + +pci:v000014C0* + ID_VENDOR_FROM_DATABASE=COMPAL Electronics Inc + +pci:v000014C0d00001201* + ID_MODEL_FROM_DATABASE=X550 10Gb 2P RJ45 OCP Mezz + +pci:v000014C1* + ID_VENDOR_FROM_DATABASE=MYRICOM Inc. + +pci:v000014C1d00000008* + ID_MODEL_FROM_DATABASE=Myri-10G Dual-Protocol NIC + +pci:v000014C1d00000008sv000014C1sd00000008* + ID_MODEL_FROM_DATABASE=Myri-10G Dual-Protocol NIC (10G-PCIE-8A) + +pci:v000014C1d00000008sv000014C1sd00000009* + ID_MODEL_FROM_DATABASE=Myri-10G Dual-Protocol NIC (10G-PCIE-8A (MSI-X firmware)) + +pci:v000014C1d00000008sv000014C1sd0000000A* + ID_MODEL_FROM_DATABASE=Myri-10G Dual-Protocol NIC (10G-PCIE-8B) + +pci:v000014C1d00008043* + ID_MODEL_FROM_DATABASE=Myrinet 2000 Scalable Cluster Interconnect + +pci:v000014C1d00008043sv0000103Csd00001240* + ID_MODEL_FROM_DATABASE=Myrinet 2000 Scalable Cluster Interconnect (Myrinet M2L-PCI64/2-3.0 LANai 7.4 (HP OEM)) + +pci:v000014C2* + ID_VENDOR_FROM_DATABASE=DTK Computer + +pci:v000014C3* + ID_VENDOR_FROM_DATABASE=MEDIATEK Corp. + +pci:v000014C3d00007630* + ID_MODEL_FROM_DATABASE=MT7630e 802.11bgn Wireless Network Adapter + +pci:v000014C3d00007662* + ID_MODEL_FROM_DATABASE=MT7662E 802.11ac PCI Express Wireless Network Adapter + +pci:v000014C4* + ID_VENDOR_FROM_DATABASE=IWASAKI Information Systems Co Ltd + +pci:v000014C5* + ID_VENDOR_FROM_DATABASE=Automation Products AB + +pci:v000014C6* + ID_VENDOR_FROM_DATABASE=Data Race Inc + +pci:v000014C7* + ID_VENDOR_FROM_DATABASE=Modular Technology Holdings Ltd + +pci:v000014C8* + ID_VENDOR_FROM_DATABASE=Turbocomm Tech. Inc. + +pci:v000014C9* + ID_VENDOR_FROM_DATABASE=ODIN Telesystems Inc + +pci:v000014CA* + ID_VENDOR_FROM_DATABASE=PE Logic Corp. + +pci:v000014CB* + ID_VENDOR_FROM_DATABASE=Billionton Systems Inc + +pci:v000014CC* + ID_VENDOR_FROM_DATABASE=NAKAYO Telecommunications Inc + +pci:v000014CD* + ID_VENDOR_FROM_DATABASE=Universal Global Scientific Industrial Co.,Ltd + +pci:v000014CDd00000001* + ID_MODEL_FROM_DATABASE=USI-1514-1GbaseT [OCP1] + +pci:v000014CDd00000002* + ID_MODEL_FROM_DATABASE=USI-4227-SFP [OCP2] + +pci:v000014CDd00000003* + ID_MODEL_FROM_DATABASE=USI-X557-10GbaseT [OCP3] + +pci:v000014CE* + ID_VENDOR_FROM_DATABASE=Whistle Communications + +pci:v000014CF* + ID_VENDOR_FROM_DATABASE=TEK Microsystems Inc. + +pci:v000014D0* + ID_VENDOR_FROM_DATABASE=Ericsson Axe R & D + +pci:v000014D1* + ID_VENDOR_FROM_DATABASE=Computer Hi-Tech Co Ltd + +pci:v000014D2* + ID_VENDOR_FROM_DATABASE=Titan Electronics Inc + +pci:v000014D2d00008001* + ID_MODEL_FROM_DATABASE=VScom 010L 1 port parallel adaptor + +pci:v000014D2d00008002* + ID_MODEL_FROM_DATABASE=VScom 020L 2 port parallel adaptor + +pci:v000014D2d00008010* + ID_MODEL_FROM_DATABASE=VScom 100L 1 port serial adaptor + +pci:v000014D2d00008011* + ID_MODEL_FROM_DATABASE=VScom 110L 1 port serial and 1 port parallel adaptor + +pci:v000014D2d00008020* + ID_MODEL_FROM_DATABASE=VScom 200L 1 or 2 port serial adaptor + +pci:v000014D2d00008021* + ID_MODEL_FROM_DATABASE=VScom 210L 2 port serial and 1 port parallel adaptor + +pci:v000014D2d00008028* + ID_MODEL_FROM_DATABASE=VScom 200I/200I-SI 2-port serial adapter + +pci:v000014D2d00008040* + ID_MODEL_FROM_DATABASE=VScom 400L 4 port serial adaptor + +pci:v000014D2d00008043* + ID_MODEL_FROM_DATABASE=VScom 430L 4-port serial and 3-port parallel adapter + +pci:v000014D2d00008048* + ID_MODEL_FROM_DATABASE=VScom 400I 4-port serial adapter + +pci:v000014D2d00008080* + ID_MODEL_FROM_DATABASE=VScom 800L 8 port serial adaptor + +pci:v000014D2d00008088* + ID_MODEL_FROM_DATABASE=VScom 800I 8-port serial adapter + +pci:v000014D2d0000A000* + ID_MODEL_FROM_DATABASE=VScom 010H 1 port parallel adaptor + +pci:v000014D2d0000A001* + ID_MODEL_FROM_DATABASE=VScom 100H 1 port serial adaptor + +pci:v000014D2d0000A003* + ID_MODEL_FROM_DATABASE=VScom 400H 4 port serial adaptor + +pci:v000014D2d0000A004* + ID_MODEL_FROM_DATABASE=VScom 400HF1 4 port serial adaptor + +pci:v000014D2d0000A005* + ID_MODEL_FROM_DATABASE=VScom 200H 2 port serial adaptor + +pci:v000014D2d0000A007* + ID_MODEL_FROM_DATABASE=VScom PCI800EH (PCIe) 8-port serial adapter Port 1-4 + +pci:v000014D2d0000A008* + ID_MODEL_FROM_DATABASE=VScom PCI800EH (PCIe) 8-port serial adapter Port 5-8 + +pci:v000014D2d0000A009* + ID_MODEL_FROM_DATABASE=VScom PCI400EH (PCIe) 4-port serial adapter + +pci:v000014D2d0000E001* + ID_MODEL_FROM_DATABASE=VScom 010HV2 1 port parallel adaptor + +pci:v000014D2d0000E010* + ID_MODEL_FROM_DATABASE=VScom 100HV2 1 port serial adaptor + +pci:v000014D2d0000E020* + ID_MODEL_FROM_DATABASE=VScom 200HV2 2 port serial adaptor + +pci:v000014D3* + ID_VENDOR_FROM_DATABASE=CIRTECH (UK) Ltd + +pci:v000014D3d00000002* + ID_MODEL_FROM_DATABASE=DTL-T14000 Rev. 1 [PS2 TOOL CD/DVD Emulator] + +pci:v000014D3d00000003* + ID_MODEL_FROM_DATABASE=DTL-T14000 Rev. 2 [PS2 TOOL CD/DVD Emulator] + +pci:v000014D3d00000004* + ID_MODEL_FROM_DATABASE=DTL-T14000 Rev. 3 [PS2 TOOL CD/DVD Emulator] + +pci:v000014D4* + ID_VENDOR_FROM_DATABASE=Panacom Technology Corp + +pci:v000014D5* + ID_VENDOR_FROM_DATABASE=Nitsuko Corporation + +pci:v000014D6* + ID_VENDOR_FROM_DATABASE=Accusys Inc + +pci:v000014D6d00006101* + ID_MODEL_FROM_DATABASE=ACS-61xxx, PCIe to SAS/SATA RAID HBA + +pci:v000014D6d00006201* + ID_MODEL_FROM_DATABASE=ACS-62xxx, External PCIe to SAS/SATA RAID controller + +pci:v000014D7* + ID_VENDOR_FROM_DATABASE=Hirakawa Hewtech Corp + +pci:v000014D8* + ID_VENDOR_FROM_DATABASE=HOPF Elektronik GmBH + +pci:v000014D9* + ID_VENDOR_FROM_DATABASE=Alliance Semiconductor Corporation + +pci:v000014D9d00000010* + ID_MODEL_FROM_DATABASE=AP1011/SP1011 HyperTransport-PCI Bridge [Sturgeon] + +pci:v000014D9d00009000* + ID_MODEL_FROM_DATABASE=AS90L10204/10208 HyperTransport to PCI-X Bridge + +pci:v000014DA* + ID_VENDOR_FROM_DATABASE=National Aerospace Laboratories + +pci:v000014DB* + ID_VENDOR_FROM_DATABASE=AFAVLAB Technology Inc + +pci:v000014DBd00002120* + ID_MODEL_FROM_DATABASE=TK9902 + +pci:v000014DBd00002182* + ID_MODEL_FROM_DATABASE=AFAVLAB Technology Inc. 8-port serial card + +pci:v000014DC* + ID_VENDOR_FROM_DATABASE=Amplicon Liveline Ltd + +pci:v000014DCd00000000* + ID_MODEL_FROM_DATABASE=PCI230 + +pci:v000014DCd00000001* + ID_MODEL_FROM_DATABASE=PCI242 + +pci:v000014DCd00000002* + ID_MODEL_FROM_DATABASE=PCI244 + +pci:v000014DCd00000003* + ID_MODEL_FROM_DATABASE=PCI247 + +pci:v000014DCd00000004* + ID_MODEL_FROM_DATABASE=PCI248 + +pci:v000014DCd00000005* + ID_MODEL_FROM_DATABASE=PCI249 + +pci:v000014DCd00000006* + ID_MODEL_FROM_DATABASE=PCI260 + +pci:v000014DCd00000007* + ID_MODEL_FROM_DATABASE=PCI224 + +pci:v000014DCd00000008* + ID_MODEL_FROM_DATABASE=PCI234 + +pci:v000014DCd00000009* + ID_MODEL_FROM_DATABASE=PCI236 + +pci:v000014DCd0000000A* + ID_MODEL_FROM_DATABASE=PCI272 + +pci:v000014DCd0000000B* + ID_MODEL_FROM_DATABASE=PCI215 + +pci:v000014DD* + ID_VENDOR_FROM_DATABASE=Boulder Design Labs Inc + +pci:v000014DE* + ID_VENDOR_FROM_DATABASE=Applied Integration Corporation + +pci:v000014DF* + ID_VENDOR_FROM_DATABASE=ASIC Communications Corp + +pci:v000014E1* + ID_VENDOR_FROM_DATABASE=INVERTEX + +pci:v000014E2* + ID_VENDOR_FROM_DATABASE=INFOLIBRIA + +pci:v000014E3* + ID_VENDOR_FROM_DATABASE=AMTELCO + +pci:v000014E4* + ID_VENDOR_FROM_DATABASE=Broadcom Inc. and subsidiaries + +pci:v000014E4d00000576* + ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n + +pci:v000014E4d00000800* + ID_MODEL_FROM_DATABASE=Sentry5 Chipcommon I/O Controller + +pci:v000014E4d00000804* + ID_MODEL_FROM_DATABASE=Sentry5 PCI Bridge + +pci:v000014E4d00000805* + ID_MODEL_FROM_DATABASE=Sentry5 MIPS32 CPU + +pci:v000014E4d00000806* + ID_MODEL_FROM_DATABASE=Sentry5 Ethernet Controller + +pci:v000014E4d0000080B* + ID_MODEL_FROM_DATABASE=Sentry5 Crypto Accelerator + +pci:v000014E4d0000080F* + ID_MODEL_FROM_DATABASE=Sentry5 DDR/SDR RAM Controller + +pci:v000014E4d00000811* + ID_MODEL_FROM_DATABASE=Sentry5 External Interface Core + +pci:v000014E4d00000816* + ID_MODEL_FROM_DATABASE=BCM3302 Sentry5 MIPS32 CPU + +pci:v000014E4d00001570* + ID_MODEL_FROM_DATABASE=720p FaceTime HD Camera + +pci:v000014E4d00001600* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express + +pci:v000014E4d00001600sv00001028sd000001C1* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express (Precision 490) + +pci:v000014E4d00001600sv00001028sd000001C2* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express (Latitude D620) + +pci:v000014E4d00001600sv0000103Csd00003015* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express (PCIe LAN on Motherboard) + +pci:v000014E4d00001600sv0000107Bsd00005048* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express (E4500 Onboard) + +pci:v000014E4d00001600sv00001259sd00002705* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5752 Gigabit Ethernet PCI Express (AT-2711FX) + +pci:v000014E4d00001601* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5752M Gigabit Ethernet PCI Express + +pci:v000014E4d00001604* + ID_MODEL_FROM_DATABASE=BCM5745X NetXtreme-E Ethernet Partition + +pci:v000014E4d00001605* + ID_MODEL_FROM_DATABASE=BCM5745X NetXtreme-E RDMA Partition + +pci:v000014E4d00001606* + ID_MODEL_FROM_DATABASE=BCM5745X NetXtreme-E RDMA Virtual Function + +pci:v000014E4d00001609* + ID_MODEL_FROM_DATABASE=BCM5745X NetXtreme-E Ethernet Virtual Function + +pci:v000014E4d00001612* + ID_MODEL_FROM_DATABASE=BCM70012 Video Decoder [Crystal HD] + +pci:v000014E4d00001614* + ID_MODEL_FROM_DATABASE=BCM57454 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet + +pci:v000014E4d00001615* + ID_MODEL_FROM_DATABASE=BCM70015 Video Decoder [Crystal HD] + +pci:v000014E4d00001639* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet + +pci:v000014E4d00001639sv00001028sd00000235* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (PowerEdge R710 BCM5709 Gigabit Ethernet) + +pci:v000014E4d00001639sv00001028sd00000236* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (PowerEdge R610 BCM5709 Gigabit Ethernet) + +pci:v000014E4d00001639sv00001028sd00000237* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (PowerEdge T610 BCM5709 Gigabit Ethernet) + +pci:v000014E4d00001639sv0000103Csd00007055* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (NC382i Integrated Multi-port PCI Express Gigabit Server Adapter) + +pci:v000014E4d00001639sv0000103Csd00007059* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (NC382T PCIe Dual Port Multifunction Gigabit Server Adapter) + +pci:v000014E4d00001639sv000010A9sd00008027* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709 Gigabit Ethernet (Quad port Gigabit Ethernet Controller) + +pci:v000014E4d0000163A* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet + +pci:v000014E4d0000163Asv00001028sd0000027B* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet (PowerEdge M805 Broadcom NetXtreme II BCM5709S) + +pci:v000014E4d0000163Asv00001028sd0000029C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet (PowerEdge M710 BCM5709S Gigabit Ethernet) + +pci:v000014E4d0000163Asv0000103Csd0000171D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet (NC382m Dual Port 1GbE Multifunction BL-c Adapter) + +pci:v000014E4d0000163Asv0000103Csd00007056* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet (NC382i Integrated Quad Port PCI Express Gigabit Server Adapter) + +pci:v000014E4d0000163Asv00001259sd00002984* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5709S Gigabit Ethernet (AT-2973SX) + +pci:v000014E4d0000163B* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716 Gigabit Ethernet + +pci:v000014E4d0000163Bsv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716 Gigabit Ethernet (PowerEdge R410 BCM5716 Gigabit Ethernet) + +pci:v000014E4d0000163Bsv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716 Gigabit Ethernet (PowerEdge T410 BCM5716 Gigabit Ethernet) + +pci:v000014E4d0000163Bsv00001028sd000002F1* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716 Gigabit Ethernet (PowerEdge R510 BCM5716 Gigabit Ethernet) + +pci:v000014E4d0000163C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5716S Gigabit Ethernet + +pci:v000014E4d0000163D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57811 10-Gigabit Ethernet + +pci:v000014E4d0000163Dsv00001043sd0000858A* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57811 10-Gigabit Ethernet (PEB-10G/57811-1S) + +pci:v000014E4d0000163E* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57811 10 Gigabit Ethernet Multi Function + +pci:v000014E4d0000163F* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57811 10-Gigabit Ethernet Virtual Function + +pci:v000014E4d00001641* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57787 Gigabit Ethernet PCIe + +pci:v000014E4d00001642* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57764 Gigabit Ethernet PCIe + +pci:v000014E4d00001643* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5725 Gigabit Ethernet PCIe + +pci:v000014E4d00001644* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet + +pci:v000014E4d00001644sv00001014sd00000277* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (Broadcom Vigil B5700 1000Base-T) + +pci:v000014E4d00001644sv00001028sd000000D1* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (Broadcom BCM5700) + +pci:v000014E4d00001644sv00001028sd00000106* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (Broadcom BCM5700) + +pci:v000014E4d00001644sv00001028sd00000109* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (Broadcom BCM5700 1000Base-T) + +pci:v000014E4d00001644sv00001028sd0000010A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (Broadcom BCM5700 1000BaseTX) + +pci:v000014E4d00001644sv000010B7sd00001000* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C996-T 1000Base-T) + +pci:v000014E4d00001644sv000010B7sd00001001* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C996B-T 1000Base-T) + +pci:v000014E4d00001644sv000010B7sd00001002* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C996C-T 1000Base-T) + +pci:v000014E4d00001644sv000010B7sd00001003* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C997-T 1000Base-T Dual Port) + +pci:v000014E4d00001644sv000010B7sd00001004* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C996-SX 1000Base-SX) + +pci:v000014E4d00001644sv000010B7sd00001005* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C997-SX 1000Base-SX Dual Port) + +pci:v000014E4d00001644sv000010B7sd00001008* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (3C942 Gigabit LOM (31X31)) + +pci:v000014E4d00001644sv000014E4sd00000002* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (NetXtreme 1000Base-SX) + +pci:v000014E4d00001644sv000014E4sd00000003* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (NetXtreme 1000Base-SX) + +pci:v000014E4d00001644sv000014E4sd00000004* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (NetXtreme 1000Base-T) + +pci:v000014E4d00001644sv000014E4sd00001028* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (NetXtreme 1000BaseTX) + +pci:v000014E4d00001644sv000014E4sd00001644* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5700 Gigabit Ethernet (BCM5700 1000Base-T) + +pci:v000014E4d00001645* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet + +pci:v000014E4d00001645sv00000E11sd0000007C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T)) + +pci:v000014E4d00001645sv00000E11sd0000007D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC6770 Gigabit Server Adapter (PCI-X, 1000-SX)) + +pci:v000014E4d00001645sv00000E11sd00000085* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC7780 Gigabit Server Adapter (embedded, WOL)) + +pci:v000014E4d00001645sv00000E11sd00000099* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC7780 Gigabit Server Adapter (embedded, WOL)) + +pci:v000014E4d00001645sv00000E11sd0000009A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T)) + +pci:v000014E4d00001645sv00000E11sd000000C1* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (NC6770 Gigabit Server Adapter (PCI-X, 1000-SX)) + +pci:v000014E4d00001645sv00001028sd00000121* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (Broadcom BCM5701 1000Base-T) + +pci:v000014E4d00001645sv0000103Csd0000128A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T (HP, OEM 3COM)) + +pci:v000014E4d00001645sv0000103Csd0000128B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (1000Base-SX (PCI) [A7073A]) + +pci:v000014E4d00001645sv0000103Csd000012A4* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (Core Lan 1000Base-T) + +pci:v000014E4d00001645sv0000103Csd000012C1* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (IOX Core Lan 1000Base-T [A7109AX]) + +pci:v000014E4d00001645sv0000103Csd00001300* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (Core LAN/SCSI Combo [A6794A]) + +pci:v000014E4d00001645sv000010A9sd00008010* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (IO9/IO10 Gigabit Ethernet (Copper)) + +pci:v000014E4d00001645sv000010A9sd00008011* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (Gigabit Ethernet (Copper)) + +pci:v000014E4d00001645sv000010A9sd00008012* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (Gigabit Ethernet (Fiber)) + +pci:v000014E4d00001645sv000010B7sd00001004* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (3C996-SX 1000Base-SX) + +pci:v000014E4d00001645sv000010B7sd00001006* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (3C996B-T 1000Base-T) + +pci:v000014E4d00001645sv000010B7sd00001007* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (3C1000-T 1000Base-T) + +pci:v000014E4d00001645sv000010B7sd00001008* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (3C940-BR01 1000Base-T) + +pci:v000014E4d00001645sv000014E4sd00000001* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T) + +pci:v000014E4d00001645sv000014E4sd00000005* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T) + +pci:v000014E4d00001645sv000014E4sd00000006* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T) + +pci:v000014E4d00001645sv000014E4sd00000007* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-SX) + +pci:v000014E4d00001645sv000014E4sd00000008* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T) + +pci:v000014E4d00001645sv000014E4sd00001645* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet + +pci:v000014E4d00001645sv000014E4sd00008008* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5701 Gigabit Ethernet (BCM5701 1000Base-T) + +pci:v000014E4d00001646* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702 Gigabit Ethernet + +pci:v000014E4d00001646sv00000E11sd000000BB* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702 Gigabit Ethernet (NC7760 1000BaseTX) + +pci:v000014E4d00001646sv00001028sd00000126* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702 Gigabit Ethernet (Broadcom BCM5702 1000BaseTX) + +pci:v000014E4d00001646sv000014E4sd00008009* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702 Gigabit Ethernet (BCM5702 1000BaseTX) + +pci:v000014E4d00001647* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet + +pci:v000014E4d00001647sv00000E11sd00000099* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NC7780 1000BaseTX) + +pci:v000014E4d00001647sv00000E11sd0000009A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NC7770 1000BaseTX) + +pci:v000014E4d00001647sv000010A9sd00008010* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (IO9 Gigabit Ethernet (Copper)) + +pci:v000014E4d00001647sv000014E4sd00000009* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (BCM5703 1000BaseTX) + +pci:v000014E4d00001647sv000014E4sd0000000A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (BCM5703 1000BaseSX) + +pci:v000014E4d00001647sv000014E4sd0000000B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (BCM5703 1000BaseTX) + +pci:v000014E4d00001647sv000014E4sd00008009* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (BCM5703 1000BaseTX) + +pci:v000014E4d00001647sv000014E4sd0000800A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (BCM5703 1000BaseTX) + +pci:v000014E4d00001648* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet + +pci:v000014E4d00001648sv00000E11sd000000CF* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (NC7772 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) + +pci:v000014E4d00001648sv00000E11sd000000D0* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (NC7782 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) + +pci:v000014E4d00001648sv00000E11sd000000D1* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (NC7783 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) + +pci:v000014E4d00001648sv00001028sd0000014A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (PowerEdge 1750) + +pci:v000014E4d00001648sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (PowerEdge 6850 Broadcom NetXtreme BCM5704) + +pci:v000014E4d00001648sv0000103Csd0000310F* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (NC7782 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) + +pci:v000014E4d00001648sv000010A9sd00008013* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (Dual Port Gigabit Ethernet (PCI-X,Copper)) + +pci:v000014E4d00001648sv000010A9sd00008018* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (Dual Port Gigabit Ethernet (A330)) + +pci:v000014E4d00001648sv000010A9sd0000801A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (Dual Port Gigabit Ethernet (IA-blade)) + +pci:v000014E4d00001648sv000010A9sd0000801B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (Quad Port Gigabit Ethernet (PCI-E,Copper)) + +pci:v000014E4d00001648sv000010B7sd00002000* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (3C998-T Dual Port 10/100/1000 PCI-X) + +pci:v000014E4d00001648sv000010B7sd00003000* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (3C999-T Quad Port 10/100/1000 PCI-X) + +pci:v000014E4d00001648sv00001166sd00001648* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (NetXtreme CIOB-E 1000Base-T) + +pci:v000014E4d00001648sv00001734sd0000100B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704 Gigabit Ethernet (PRIMERGY RX/TX series onboard LAN) + +pci:v000014E4d00001649* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S_2 Gigabit Ethernet + +pci:v000014E4d0000164A* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706 Gigabit Ethernet + +pci:v000014E4d0000164Asv0000103Csd00001709* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706 Gigabit Ethernet (NC371i Integrated PCI-X Multifunction Gigabit Server Adapter) + +pci:v000014E4d0000164Asv0000103Csd00003070* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706 Gigabit Ethernet (NC380T PCI Express Dual Port Multifunction Gigabit Server Adapter) + +pci:v000014E4d0000164Asv0000103Csd00003101* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706 Gigabit Ethernet (NC370T MultifuNCtion Gigabit Server Adapter) + +pci:v000014E4d0000164Asv0000103Csd00003106* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706 Gigabit Ethernet (NC370i Multifunction Gigabit Server Adapter) + +pci:v000014E4d0000164C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet + +pci:v000014E4d0000164Csv00001028sd000001F0* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge R900 Broadcom NetXtreme II BCM5708) + +pci:v000014E4d0000164Csv00001028sd00000205* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge 2970 Broadcom NetXtreme II BCM5708) + +pci:v000014E4d0000164Csv00001028sd0000020B* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge T605 Broadcom NetXtreme II BCM5708) + +pci:v000014E4d0000164Csv00001028sd00000221* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge R805 Broadcom NetXtreme II BCM5708) + +pci:v000014E4d0000164Csv00001028sd00000223* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge R905 Broadcom NetXtreme II BCM5708) + +pci:v000014E4d0000164Csv00001028sd00001F12* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (PowerEdge R805/R905 Broadcom NetXtreme II BCM5708) + +pci:v000014E4d0000164Csv0000103Csd00007037* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (NC373T PCI Express Multifunction Gigabit Server Adapter) + +pci:v000014E4d0000164Csv0000103Csd00007038* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (NC373i Integrated Multifunction Gigabit Server Adapter) + +pci:v000014E4d0000164Csv0000103Csd00007045* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708 Gigabit Ethernet (NC374m PCI Express Dual Port Multifunction Gigabit Server Adapter) + +pci:v000014E4d0000164D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702FE Gigabit Ethernet + +pci:v000014E4d0000164E* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57710 10-Gigabit PCIe [Everest] + +pci:v000014E4d0000164Esv0000103Csd0000171C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57710 10-Gigabit PCIe [Everest] (NC532m Dual Port 10GbE Multifunction BL-C Adapter) + +pci:v000014E4d0000164Esv0000103Csd00007058* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57710 10-Gigabit PCIe [Everest] (NC532i Dual Port 10GbE Multifunction BL-C Adapter) + +pci:v000014E4d0000164F* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57711 10-Gigabit PCIe + +pci:v000014E4d00001650* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57711E 10-Gigabit PCIe + +pci:v000014E4d00001650sv0000103Csd0000171C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57711E 10-Gigabit PCIe (NC532m Dual Port 10GbE Multifunction BL-C Adapter) + +pci:v000014E4d00001650sv0000103Csd00007058* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57711E 10-Gigabit PCIe (NC532i Dual Port 10GbE Multifunction BL-C Adapter) + +pci:v000014E4d00001653* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705 Gigabit Ethernet + +pci:v000014E4d00001653sv00000E11sd000000E3* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705 Gigabit Ethernet (NC7761 Gigabit Server Adapter) + +pci:v000014E4d00001653sv00001734sd00001073* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705 Gigabit Ethernet (Primergy Econel 200 D2020 mainboard) + +pci:v000014E4d00001654* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705_2 Gigabit Ethernet + +pci:v000014E4d00001654sv00000E11sd000000E3* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705_2 Gigabit Ethernet (NC7761 Gigabit Server Adapter) + +pci:v000014E4d00001654sv0000103Csd00003100* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705_2 Gigabit Ethernet (NC1020 ProLiant Gigabit Server Adapter 32 PCI) + +pci:v000014E4d00001654sv0000103Csd00003226* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705_2 Gigabit Ethernet (NC150T 4-port Gigabit Combo Switch & Adapter) + +pci:v000014E4d00001655* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5717 Gigabit Ethernet PCIe + +pci:v000014E4d00001656* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5718 Gigabit Ethernet PCIe + +pci:v000014E4d00001657* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe + +pci:v000014E4d00001657sv00001014sd00000420* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe (FC 5260/5899 4-port 1 GbE Adapter for Power) + +pci:v000014E4d00001657sv0000103Csd0000169D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe (Ethernet 1Gb 4-port 331FLR Adapter) + +pci:v000014E4d00001657sv0000103Csd000022BE* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe (Ethernet 1Gb 4-port 331i Adapter) + +pci:v000014E4d00001657sv0000103Csd00003383* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe (Ethernet 1Gb 4-port 331T Adapter) + +pci:v000014E4d00001657sv000014E4sd00001904* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5719 Gigabit Ethernet PCIe (4-port 1Gb Ethernet Adapter) + +pci:v000014E4d00001659* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express + +pci:v000014E4d00001659sv00001014sd000002C6* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (eServer xSeries server mainboard) + +pci:v000014E4d00001659sv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (PowerEdge 860) + +pci:v000014E4d00001659sv00001028sd0000023C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (PowerEdge R200 Broadcom NetXtreme BCM5721) + +pci:v000014E4d00001659sv0000103Csd0000170B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (NC320m PCI Express Dual Port Gigabit Server Adapter) + +pci:v000014E4d00001659sv0000103Csd00007031* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (NC320T PCIe Gigabit Server Adapter) + +pci:v000014E4d00001659sv0000103Csd00007032* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (NC320i PCIe Gigabit Server Adapter) + +pci:v000014E4d00001659sv00001734sd00001061* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5721 Gigabit Ethernet PCI Express (PRIMERGY RX/TX S2 series onboard LAN) + +pci:v000014E4d0000165A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express + +pci:v000014E4d0000165Asv00001014sd00000378* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (System x3350 (Machine type 4192)) + +pci:v000014E4d0000165Asv00001028sd0000020F* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (PowerEdge R300 Broadcom NetXtreme 5722) + +pci:v000014E4d0000165Asv00001028sd00000210* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (PowerEdge T300 Broadcom NetXtreme 5722) + +pci:v000014E4d0000165Asv00001028sd00000225* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (PowerEdge T105 Broadcom NetXtreme 5722) + +pci:v000014E4d0000165Asv0000103Csd00007051* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (NC105i PCIe Gigabit Server Adapter) + +pci:v000014E4d0000165Asv0000103Csd00007052* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5722 Gigabit Ethernet PCI Express (NC105T PCIe Gigabit Server Adapter) + +pci:v000014E4d0000165B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5723 Gigabit Ethernet PCIe + +pci:v000014E4d0000165Bsv0000103Csd0000705D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5723 Gigabit Ethernet PCIe (NC107i Integrated PCI Express Gigabit Server Adapter) + +pci:v000014E4d0000165C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5724 Gigabit Ethernet PCIe + +pci:v000014E4d0000165D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M Gigabit Ethernet + +pci:v000014E4d0000165Dsv00001028sd0000865D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M Gigabit Ethernet (Latitude D400) + +pci:v000014E4d0000165Dsv000014E4sd0000165D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M Gigabit Ethernet (Dell Latitude D600) + +pci:v000014E4d0000165E* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M_2 Gigabit Ethernet + +pci:v000014E4d0000165Esv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M_2 Gigabit Ethernet (NC8000 laptop) + +pci:v000014E4d0000165Esv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M_2 Gigabit Ethernet (NC6000 laptop) + +pci:v000014E4d0000165Esv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M_2 Gigabit Ethernet (NX6110/NC6120) + +pci:v000014E4d0000165Esv000010CFsd00001279* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5705M_2 Gigabit Ethernet (LifeBook E8010D) + +pci:v000014E4d0000165F* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 2-port Gigabit Ethernet PCIe + +pci:v000014E4d0000165Fsv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 2-port Gigabit Ethernet PCIe (PowerEdge R320 server) + +pci:v000014E4d0000165Fsv00001028sd000008FD* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 2-port Gigabit Ethernet PCIe (PowerEdge R6515/R7515 LOM) + +pci:v000014E4d0000165Fsv00001028sd000008FF* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 2-port Gigabit Ethernet PCIe (PowerEdge Rx5xx LOM Board) + +pci:v000014E4d0000165Fsv00001028sd00000900* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 2-port Gigabit Ethernet PCIe (PowerEdge C6525 LOM) + +pci:v000014E4d0000165Fsv0000103Csd00001786* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 2-port Gigabit Ethernet PCIe (NC332T Adapter) + +pci:v000014E4d0000165Fsv0000103Csd0000193D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 2-port Gigabit Ethernet PCIe (NC332i Adapter) + +pci:v000014E4d0000165Fsv0000103Csd00002133* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 2-port Gigabit Ethernet PCIe (NC332i Adapter) + +pci:v000014E4d0000165Fsv0000103Csd000022E8* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 2-port Gigabit Ethernet PCIe (NC332i Adapter) + +pci:v000014E4d0000165Fsv0000103Csd000022EB* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5720 2-port Gigabit Ethernet PCIe (NC332i Adapter) + +pci:v000014E4d00001662* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57712 10 Gigabit Ethernet + +pci:v000014E4d00001663* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function + +pci:v000014E4d00001665* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5717 Gigabit Ethernet PCIe + +pci:v000014E4d00001668* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5714 Gigabit Ethernet + +pci:v000014E4d00001668sv0000103Csd00007039* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5714 Gigabit Ethernet (NC324i PCIe Dual Port Gigabit Server Adapter) + +pci:v000014E4d00001669* + ID_MODEL_FROM_DATABASE=NetXtreme 5714S Gigabit Ethernet + +pci:v000014E4d0000166A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5780 Gigabit Ethernet + +pci:v000014E4d0000166Asv0000103Csd00007035* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5780 Gigabit Ethernet (NC325i Integrated Dual port PCIe Express Gigabit Server Adapter) + +pci:v000014E4d0000166B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5780S Gigabit Ethernet + +pci:v000014E4d0000166E* + ID_MODEL_FROM_DATABASE=570x 10/100 Integrated Controller + +pci:v000014E4d0000166F* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57712 10 Gigabit Ethernet Virtual Function + +pci:v000014E4d00001672* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5754M Gigabit Ethernet PCI Express + +pci:v000014E4d00001673* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5755M Gigabit Ethernet PCI Express + +pci:v000014E4d00001674* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5756ME Gigabit Ethernet PCI Express + +pci:v000014E4d00001677* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express + +pci:v000014E4d00001677sv00001028sd00000176* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Dimension XPS Gen 4) + +pci:v000014E4d00001677sv00001028sd00000177* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Dimension 8400) + +pci:v000014E4d00001677sv00001028sd00000179* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Optiplex GX280) + +pci:v000014E4d00001677sv00001028sd00000182* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Latitude D610) + +pci:v000014E4d00001677sv00001028sd00000187* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Precision M70) + +pci:v000014E4d00001677sv00001028sd000001A3* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Latitude X1) + +pci:v000014E4d00001677sv00001028sd000001A8* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Precision 380) + +pci:v000014E4d00001677sv00001028sd000001AD* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (OptiPlex GX620) + +pci:v000014E4d00001677sv0000103Csd00003006* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (DC7100 SFF(DX878AV)) + +pci:v000014E4d00001677sv00001462sd0000028C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (915P/G Neo2) + +pci:v000014E4d00001677sv00001734sd0000105D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751 Gigabit Ethernet PCI Express (Scenic W620) + +pci:v000014E4d00001678* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5715 Gigabit Ethernet + +pci:v000014E4d00001678sv0000103Csd0000703E* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5715 Gigabit Ethernet (NC326i PCIe Dual Port Gigabit Server Adapter) + +pci:v000014E4d00001679* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5715S Gigabit Ethernet + +pci:v000014E4d00001679sv0000103Csd00001707* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5715S Gigabit Ethernet (NC326m PCIe Dual Port Adapter) + +pci:v000014E4d00001679sv0000103Csd0000170C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5715S Gigabit Ethernet (NC325m PCIe Quad Port Adapter) + +pci:v000014E4d00001679sv0000103Csd0000703C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5715S Gigabit Ethernet (NC326i PCIe Dual Port Gigabit Server Adapter) + +pci:v000014E4d0000167A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express + +pci:v000014E4d0000167Asv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express (OptiPlex 745) + +pci:v000014E4d0000167Asv00001028sd000001DE* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express (Precision 390) + +pci:v000014E4d0000167Asv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express (PowerEdge SC440) + +pci:v000014E4d0000167Asv00001028sd00000214* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express (Precision T3400) + +pci:v000014E4d0000167Asv00001028sd0000021E* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5754 Gigabit Ethernet PCI Express (Precision T5400) + +pci:v000014E4d0000167B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5755 Gigabit Ethernet PCI Express + +pci:v000014E4d0000167Bsv0000103Csd0000280A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5755 Gigabit Ethernet PCI Express (DC5750 Microtower) + +pci:v000014E4d0000167D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express + +pci:v000014E4d0000167Dsv00001014sd00000577* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express (ThinkPad X41 / Z60t) + +pci:v000014E4d0000167Dsv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express (nx8220) + +pci:v000014E4d0000167Dsv0000103Csd00000940* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express (Compaq nw8240 Mobile Workstation) + +pci:v000014E4d0000167Dsv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express (Compaq nc6220 Notebook PC) + +pci:v000014E4d0000167Dsv000017AAsd00002081* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751M Gigabit Ethernet PCI Express (ThinkPad R60e) + +pci:v000014E4d0000167E* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5751F Fast Ethernet PCI Express + +pci:v000014E4d0000167F* + ID_MODEL_FROM_DATABASE=NetLink BCM5787F Fast Ethernet PCI Express + +pci:v000014E4d00001680* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5761e Gigabit Ethernet PCIe + +pci:v000014E4d00001681* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5761 Gigabit Ethernet PCIe + +pci:v000014E4d00001682* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57762 Gigabit Ethernet PCIe + +pci:v000014E4d00001682sv0000106Bsd000000F6* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57762 Gigabit Ethernet PCIe (Thunderbolt to Gigabit Ethernet Adapter) + +pci:v000014E4d00001683* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57767 Gigabit Ethernet PCIe + +pci:v000014E4d00001684* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5764M Gigabit Ethernet PCIe + +pci:v000014E4d00001685* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57500S Gigabit Ethernet + +pci:v000014E4d00001686* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57766 Gigabit Ethernet PCIe + +pci:v000014E4d00001687* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5762 Gigabit Ethernet PCIe + +pci:v000014E4d00001688* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5761 10/100/1000BASE-T Ethernet + +pci:v000014E4d00001688sv00001259sd00002708* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5761 10/100/1000BASE-T Ethernet (AT-2712 FX) + +pci:v000014E4d0000168A* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet + +pci:v000014E4d0000168Asv00001028sd00001F5C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet (BCM57800 10-Gigabit Ethernet) + +pci:v000014E4d0000168Asv00001028sd00001F5D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet (BCM57800 10-Gigabit Ethernet) + +pci:v000014E4d0000168Asv00001028sd00001F67* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet (BCM57800 1-Gigabit Ethernet) + +pci:v000014E4d0000168Asv00001028sd00001F68* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet (BCM57800 1-Gigabit Ethernet) + +pci:v000014E4d0000168D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet + +pci:v000014E4d0000168E* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet + +pci:v000014E4d0000168Esv00001014sd00000492* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (PCIe2 2-port 10 GbE BaseT RJ45 Adapter (FC EN0W; CCIN 2CC4)) + +pci:v000014E4d0000168Esv0000103Csd00001798* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Flex-10 10Gb 2-port 530FLB Adapter [Meru]) + +pci:v000014E4d0000168Esv0000103Csd000017A5* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Flex-10 10Gb 2-port 530M Adapter) + +pci:v000014E4d0000168Esv0000103Csd000018D3* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Ethernet 10Gb 2-port 530T Adapter) + +pci:v000014E4d0000168Esv0000103Csd00001930* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (FlexFabric 10Gb 2-port 534FLR-SFP+ Adapter) + +pci:v000014E4d0000168Esv0000103Csd00001931* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (StoreFabric CN1100R Dual Port Converged Network Adapter) + +pci:v000014E4d0000168Esv0000103Csd00001932* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (FlexFabric 10Gb 2-port 534FLB Adapter) + +pci:v000014E4d0000168Esv0000103Csd00001933* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (FlexFabric 10Gb 2-port 534M Adapter) + +pci:v000014E4d0000168Esv0000103Csd0000193A* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (FlexFabric 10Gb 2-port 533FLR-T Adapter) + +pci:v000014E4d0000168Esv0000103Csd00003382* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Ethernet 10Gb 2-port 530FLR-SFP+ Adapter) + +pci:v000014E4d0000168Esv0000103Csd0000339D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (Ethernet 10Gb 2-port 530SFP+ Adapter) + +pci:v000014E4d0000168Esv0000193Dsd00001003* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (530F-B) + +pci:v000014E4d0000168Esv0000193Dsd00001006* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet (530F-L) + +pci:v000014E4d00001690* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57760 Gigabit Ethernet PCIe + +pci:v000014E4d00001691* + ID_MODEL_FROM_DATABASE=NetLink BCM57788 Gigabit Ethernet PCIe + +pci:v000014E4d00001691sv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=NetLink BCM57788 Gigabit Ethernet PCIe (XPS 8300) + +pci:v000014E4d00001692* + ID_MODEL_FROM_DATABASE=NetLink BCM57780 Gigabit Ethernet PCIe + +pci:v000014E4d00001692sv00001025sd0000033D* + ID_MODEL_FROM_DATABASE=NetLink BCM57780 Gigabit Ethernet PCIe (Aspire 7740G) + +pci:v000014E4d00001693* + ID_MODEL_FROM_DATABASE=NetLink BCM5787M Gigabit Ethernet PCI Express + +pci:v000014E4d00001693sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=NetLink BCM5787M Gigabit Ethernet PCI Express (Aspire 5920G) + +pci:v000014E4d00001693sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=NetLink BCM5787M Gigabit Ethernet PCI Express (6710b) + +pci:v000014E4d00001693sv000017AAsd000020D5* + ID_MODEL_FROM_DATABASE=NetLink BCM5787M Gigabit Ethernet PCI Express (ThinkPad R61) + +pci:v000014E4d00001694* + ID_MODEL_FROM_DATABASE=NetLink BCM57790 Gigabit Ethernet PCIe + +pci:v000014E4d00001696* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5782 Gigabit Ethernet + +pci:v000014E4d00001696sv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5782 Gigabit Ethernet (d530 CMT (DG746A)) + +pci:v000014E4d00001696sv000014E4sd0000000D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5782 Gigabit Ethernet (NetXtreme BCM5782 1000Base-T) + +pci:v000014E4d00001698* + ID_MODEL_FROM_DATABASE=NetLink BCM5784M Gigabit Ethernet PCIe + +pci:v000014E4d00001699* + ID_MODEL_FROM_DATABASE=NetLink BCM5785 Gigabit Ethernet + +pci:v000014E4d0000169A* + ID_MODEL_FROM_DATABASE=NetLink BCM5786 Gigabit Ethernet PCI Express + +pci:v000014E4d0000169B* + ID_MODEL_FROM_DATABASE=NetLink BCM5787 Gigabit Ethernet PCI Express + +pci:v000014E4d0000169C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5788 Gigabit Ethernet + +pci:v000014E4d0000169Csv0000103Csd0000308B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5788 Gigabit Ethernet (MX6125) + +pci:v000014E4d0000169Csv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5788 Gigabit Ethernet (NC2400) + +pci:v000014E4d0000169Csv0000144Dsd0000C018* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5788 Gigabit Ethernet (X20) + +pci:v000014E4d0000169Csv00001462sd0000590C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5788 Gigabit Ethernet (KT6 Delta-FIS2R (MS-6590)) + +pci:v000014E4d0000169D* + ID_MODEL_FROM_DATABASE=NetLink BCM5789 Gigabit Ethernet PCI Express + +pci:v000014E4d000016A0* + ID_MODEL_FROM_DATABASE=NetLink BCM5785 Fast Ethernet + +pci:v000014E4d000016A1* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10 Gigabit Ethernet + +pci:v000014E4d000016A1sv00001043sd0000866E* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10 Gigabit Ethernet (PEB-10G/57840-2T 10GBase-T Network Adapter) + +pci:v000014E4d000016A2* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet + +pci:v000014E4d000016A2sv0000103Csd00001916* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet (FlexFabric 20Gb 2-port 630FLB Adapter) + +pci:v000014E4d000016A2sv0000103Csd00001917* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet (FlexFabric 20Gb 2-port 630M Adapter) + +pci:v000014E4d000016A2sv0000103Csd00002231* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet (3820C 10/20Gb Converged Network Adapter) + +pci:v000014E4d000016A2sv0000103Csd000022FA* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II 10/20-Gigabit Ethernet (FlexFabric 10Gb 2-port 536FLB Adapter) + +pci:v000014E4d000016A3* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57786 Gigabit Ethernet PCIe + +pci:v000014E4d000016A4* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II Ethernet Multi Function + +pci:v000014E4d000016A4sv0000103Csd00001916* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II Ethernet Multi Function (NPAR 20Gb 2-port 630FLB Adapter) + +pci:v000014E4d000016A4sv0000103Csd00001917* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II Ethernet Multi Function (NPAR 20Gb 2-port 630M Adapter) + +pci:v000014E4d000016A4sv0000103Csd00002231* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II Ethernet Multi Function (3820C 10/20Gb Converged Network Adapter (NPAR 1.5)) + +pci:v000014E4d000016A4sv0000103Csd000022FA* + ID_MODEL_FROM_DATABASE=BCM57840 NetXtreme II Ethernet Multi Function (FlexFabric 10Gb 2-port 536FLB Adapter (NPAR 1.5)) + +pci:v000014E4d000016A5* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function + +pci:v000014E4d000016A5sv00001028sd00001F5C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function (NetXtreme II BCM57800 10-Gigabit Ethernet Multi Function) + +pci:v000014E4d000016A5sv00001028sd00001F5D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function (NetXtreme II BCM57800 10-Gigabit Ethernet Multi Function) + +pci:v000014E4d000016A5sv00001028sd00001F67* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function (NetXtreme II BCM57800 1-Gigabit Ethernet Multi Function) + +pci:v000014E4d000016A5sv00001028sd00001F68* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function (NetXtreme II BCM57800 1-Gigabit Ethernet Multi Function) + +pci:v000014E4d000016A6* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702X Gigabit Ethernet + +pci:v000014E4d000016A6sv00000E11sd000000BB* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702X Gigabit Ethernet (NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T)) + +pci:v000014E4d000016A6sv00001028sd00000126* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702X Gigabit Ethernet (BCM5702 1000Base-T) + +pci:v000014E4d000016A6sv000014E4sd0000000C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702X Gigabit Ethernet (BCM5702 1000Base-T) + +pci:v000014E4d000016A6sv000014E4sd00008009* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702X Gigabit Ethernet (BCM5702 1000Base-T) + +pci:v000014E4d000016A7* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet + +pci:v000014E4d000016A7sv00000E11sd000000CA* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) + +pci:v000014E4d000016A7sv00000E11sd000000CB* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) + +pci:v000014E4d000016A7sv00001014sd0000026F* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (eServer xSeries server mainboard) + +pci:v000014E4d000016A7sv000014E4sd00000009* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NetXtreme BCM5703 1000Base-T) + +pci:v000014E4d000016A7sv000014E4sd0000000A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NetXtreme BCM5703 1000Base-SX) + +pci:v000014E4d000016A7sv000014E4sd0000000B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NetXtreme BCM5703 1000Base-T) + +pci:v000014E4d000016A7sv000014E4sd0000800A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703X Gigabit Ethernet (NetXtreme BCM5703 1000Base-T) + +pci:v000014E4d000016A8* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S Gigabit Ethernet + +pci:v000014E4d000016A8sv0000103Csd0000132B* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S Gigabit Ethernet (PCI-X 1000Mbps Dual-port Built-in) + +pci:v000014E4d000016A8sv000010A9sd00008014* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S Gigabit Ethernet (Dual Port Gigabit Ethernet (PCI-X,Fiber)) + +pci:v000014E4d000016A8sv000010A9sd0000801C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S Gigabit Ethernet (Quad Port Gigabit Ethernet (PCI-E,Fiber)) + +pci:v000014E4d000016A8sv000010B7sd00002001* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5704S Gigabit Ethernet (3C998-SX Dual Port 1000-SX PCI-X) + +pci:v000014E4d000016A9* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function + +pci:v000014E4d000016A9sv00001028sd00001F5C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function (NetXtreme II BCM57800 10-Gigabit Ethernet Virtual Function) + +pci:v000014E4d000016A9sv00001028sd00001F5D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function (NetXtreme II BCM57800 10-Gigabit Ethernet Virtual Function) + +pci:v000014E4d000016A9sv00001028sd00001F67* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function (NetXtreme II BCM57800 1-Gigabit Ethernet Virtual Function) + +pci:v000014E4d000016A9sv00001028sd00001F68* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function (NetXtreme II BCM57800 1-Gigabit Ethernet Virtual Function) + +pci:v000014E4d000016AA* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706S Gigabit Ethernet + +pci:v000014E4d000016AAsv0000103Csd00003102* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706S Gigabit Ethernet (NC370F MultifuNCtion Gigabit Server Adapter) + +pci:v000014E4d000016AAsv0000103Csd0000310C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5706S Gigabit Ethernet (NC370i Multifunction Gigabit Server Adapter) + +pci:v000014E4d000016AB* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Multi Function + +pci:v000014E4d000016AC* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet + +pci:v000014E4d000016ACsv00001014sd00000304* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet + +pci:v000014E4d000016ACsv00001028sd000001BB* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (PowerEdge 1955 Broadcom NetXtreme II BCM5708S) + +pci:v000014E4d000016ACsv00001028sd0000020C* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (PowerEdge M605 Broadcom NetXtreme II BCM5708S) + +pci:v000014E4d000016ACsv0000103Csd00001706* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (NC373m Multifunction Gigabit Server Adapter) + +pci:v000014E4d000016ACsv0000103Csd00007038* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (NC373i PCI Express Multifunction Gigabit Server Adapter) + +pci:v000014E4d000016ACsv0000103Csd0000703B* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (NC373i Integrated Multifunction Gigabit Server Adapter) + +pci:v000014E4d000016ACsv0000103Csd0000703D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM5708S Gigabit Ethernet (NC373F PCI Express Multifunction Gigabit Server Adapter) + +pci:v000014E4d000016AD* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function + +pci:v000014E4d000016ADsv0000103Csd00001916* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function (FlexFabric 20Gb 2-port 630FLB Adapter) + +pci:v000014E4d000016ADsv0000103Csd00001917* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function (FlexFabric 20Gb 2-port 630M Adapter) + +pci:v000014E4d000016ADsv0000103Csd00002231* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function (3820C 10/20Gb Converged Network Adapter (SR-IOV VF)) + +pci:v000014E4d000016ADsv0000103Csd000022FA* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function (FlexFabric 10Gb 2-port 536FLB Adapter (SR-IOV VF)) + +pci:v000014E4d000016AE* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function + +pci:v000014E4d000016AEsv0000103Csd00001798* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 530FLB Adapter) + +pci:v000014E4d000016AEsv0000103Csd000017A5* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 530M Adapter) + +pci:v000014E4d000016AEsv0000103Csd000018D3* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 530T Adapter) + +pci:v000014E4d000016AEsv0000103Csd00001930* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 534FLR-SFP+ Adapter) + +pci:v000014E4d000016AEsv0000103Csd00001931* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR CN1100R Dual Port Converged Network Adapter) + +pci:v000014E4d000016AEsv0000103Csd00001932* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 534FLB Adapter) + +pci:v000014E4d000016AEsv0000103Csd00001933* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 534M Adapter) + +pci:v000014E4d000016AEsv0000103Csd0000193A* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 533FLR-T Adapter) + +pci:v000014E4d000016AEsv0000103Csd00003382* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 530FLR-SFP+ Adapter) + +pci:v000014E4d000016AEsv0000103Csd0000339D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function (NPAR 10Gb 2-port 530SFP+ Adapter) + +pci:v000014E4d000016AF* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function + +pci:v000014E4d000016AFsv0000103Csd00001798* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (Flex-10 10Gb 2-port 530FLB Adapter) + +pci:v000014E4d000016AFsv0000103Csd000017A5* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (Flex-10 10Gb 2-port 530M Adapter) + +pci:v000014E4d000016AFsv0000103Csd000018D3* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (Ethernet 10Gb 2-port 530T Adapter) + +pci:v000014E4d000016AFsv0000103Csd00001930* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (FlexFabric 10Gb 2-port 534FLR-SFP+ Adapter) + +pci:v000014E4d000016AFsv0000103Csd00001931* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (StoreFabric CN1100R Dual Port Converged Network Adapter) + +pci:v000014E4d000016AFsv0000103Csd00001932* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (FlexFabric 10Gb 2-port 534FLB Adapter) + +pci:v000014E4d000016AFsv0000103Csd00001933* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (FlexFabric 10Gb 2-port 534M Adapter) + +pci:v000014E4d000016AFsv0000103Csd0000193A* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (FlexFabric 10Gb 2-port 533FLR-T Adapter) + +pci:v000014E4d000016AFsv0000103Csd00003382* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (Ethernet 10Gb 2-port 530FLR-SFP+ Adapter) + +pci:v000014E4d000016AFsv0000103Csd0000339D* + ID_MODEL_FROM_DATABASE=NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function (Ethernet 10Gb 2-port 530SFP+ Adapter) + +pci:v000014E4d000016B0* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57761 Gigabit Ethernet PCIe + +pci:v000014E4d000016B1* + ID_MODEL_FROM_DATABASE=NetLink BCM57781 Gigabit Ethernet PCIe + +pci:v000014E4d000016B1sv00001849sd000096B1* + ID_MODEL_FROM_DATABASE=NetLink BCM57781 Gigabit Ethernet PCIe (Z77 Extreme4 motherboard) + +pci:v000014E4d000016B2* + ID_MODEL_FROM_DATABASE=NetLink BCM57791 Gigabit Ethernet PCIe + +pci:v000014E4d000016B3* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57786 Gigabit Ethernet PCIe + +pci:v000014E4d000016B4* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57765 Gigabit Ethernet PCIe + +pci:v000014E4d000016B5* + ID_MODEL_FROM_DATABASE=NetLink BCM57785 Gigabit Ethernet PCIe + +pci:v000014E4d000016B6* + ID_MODEL_FROM_DATABASE=NetLink BCM57795 Gigabit Ethernet PCIe + +pci:v000014E4d000016B7* + ID_MODEL_FROM_DATABASE=NetXtreme BCM57782 Gigabit Ethernet PCIe + +pci:v000014E4d000016BC* + ID_MODEL_FROM_DATABASE=BCM57765/57785 SDXC/MMC Card Reader + +pci:v000014E4d000016BE* + ID_MODEL_FROM_DATABASE=BCM57765/57785 MS Card Reader + +pci:v000014E4d000016BF* + ID_MODEL_FROM_DATABASE=BCM57765/57785 xD-Picture Card Reader + +pci:v000014E4d000016C1* + ID_MODEL_FROM_DATABASE=NetXtreme-E RDMA Virtual Function + +pci:v000014E4d000016C6* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702A3 Gigabit Ethernet + +pci:v000014E4d000016C6sv000010B7sd00001100* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702A3 Gigabit Ethernet (3C1000B-T 10/100/1000 PCI) + +pci:v000014E4d000016C6sv000014E4sd0000000C* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702A3 Gigabit Ethernet (BCM5702 1000Base-T) + +pci:v000014E4d000016C6sv000014E4sd00008009* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5702A3 Gigabit Ethernet (BCM5702 1000Base-T) + +pci:v000014E4d000016C7* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet + +pci:v000014E4d000016C7sv00000E11sd000000CA* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) + +pci:v000014E4d000016C7sv00000E11sd000000CB* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T)) + +pci:v000014E4d000016C7sv0000103Csd000012C3* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (Combo FC/GigE-SX [A9782A]) + +pci:v000014E4d000016C7sv0000103Csd000012CA* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (Combo FC/GigE-T [A9784A]) + +pci:v000014E4d000016C7sv0000103Csd00001321* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (Core I/O LAN/SCSI Combo [AB314A]) + +pci:v000014E4d000016C7sv000014E4sd00000009* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NetXtreme BCM5703 1000Base-T) + +pci:v000014E4d000016C7sv000014E4sd0000000A* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5703 Gigabit Ethernet (NetXtreme BCM5703 1000Base-SX) + +pci:v000014E4d000016C8* + ID_MODEL_FROM_DATABASE=BCM57301 NetXtreme-C 10Gb Ethernet Controller + +pci:v000014E4d000016C9* + ID_MODEL_FROM_DATABASE=BCM57302 NetXtreme-C 10Gb/25Gb Ethernet Controller + +pci:v000014E4d000016CA* + ID_MODEL_FROM_DATABASE=BCM57304 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet Controller + +pci:v000014E4d000016CB* + ID_MODEL_FROM_DATABASE=NetXtreme-C Ethernet Virtual Function + +pci:v000014E4d000016CC* + ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016CE* + ID_MODEL_FROM_DATABASE=BCM57311 NetXtreme-C 10Gb RDMA Ethernet Controller + +pci:v000014E4d000016CF* + ID_MODEL_FROM_DATABASE=BCM57312 NetXtreme-C 10Gb/25Gb RDMA Ethernet Controller + +pci:v000014E4d000016D0* + ID_MODEL_FROM_DATABASE=BCM57402 NetXtreme-E 10Gb Ethernet Controller + +pci:v000014E4d000016D1* + ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E 10Gb/25Gb Ethernet Controller + +pci:v000014E4d000016D2* + ID_MODEL_FROM_DATABASE=BCM57406 NetXtreme-E 10GBASE-T Ethernet Controller + +pci:v000014E4d000016D3* + ID_MODEL_FROM_DATABASE=NetXtreme-E Ethernet Virtual Function + +pci:v000014E4d000016D4* + ID_MODEL_FROM_DATABASE=BCM57402 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016D5* + ID_MODEL_FROM_DATABASE=BCM57407 NetXtreme-E 10GBase-T Ethernet Controller + +pci:v000014E4d000016D6* + ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller + +pci:v000014E4d000016D6sv000014E4sd00004120* + ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller (NetXtreme E-Series Advanced Dual-port 10Gb SFP+ Ethernet Network Daughter Card) + +pci:v000014E4d000016D6sv0000152Dsd00008B20* + ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller + +pci:v000014E4d000016D6sv0000152Dsd00008B22* + ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller (BCM57412 NetXtreme-E 25Gb RDMA Ethernet Controller) + +pci:v000014E4d000016D7* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller + +pci:v000014E4d000016D7sv000014E4sd00001202* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (BCM957412M4122C OCP 1x25G Type1 wRoCE) + +pci:v000014E4d000016D7sv000014E4sd00001402* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (BCM957414A4142CC 10Gb/25Gb Ethernet PCIe) + +pci:v000014E4d000016D7sv000014E4sd00001404* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (BCM957414M4142C OCP 2x25G Type1 wRoCE) + +pci:v000014E4d000016D7sv000014E4sd00004140* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (NetXtreme E-Series Advanced Dual-port 25Gb SFP28 Network Daughter Card) + +pci:v000014E4d000016D7sv00001590sd0000020E* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (Ethernet 25Gb 2-port 631SFP28 Adapter) + +pci:v000014E4d000016D7sv00001590sd00000211* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (Ethernet 25Gb 2-port 631FLR-SFP28 Adapter) + +pci:v000014E4d000016D8* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller + +pci:v000014E4d000016D8sv00001028sd00001FEB* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller (NetXtreme-E 10Gb SFP+ Adapter) + +pci:v000014E4d000016D8sv000014E4sd00004163* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller (BCM957416M4163C OCP 2x10GBT Type1 wRoCE) + +pci:v000014E4d000016D8sv00001590sd0000020C* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller (Ethernet 10Gb 2-port 535T Adapter) + +pci:v000014E4d000016D8sv00001590sd00000212* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller (Ethernet 10Gb 2-port 535FLR-T Adapter) + +pci:v000014E4d000016D9* + ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E 10GBASE-T RDMA Ethernet Controller + +pci:v000014E4d000016D9sv0000108Esd00004866* + ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E 10GBASE-T RDMA Ethernet Controller (Dual Port 10GBase-T Ethernet Controller) + +pci:v000014E4d000016DC* + ID_MODEL_FROM_DATABASE=NetXtreme-E Ethernet Virtual Function + +pci:v000014E4d000016DD* + ID_MODEL_FROM_DATABASE=NetLink BCM5781 Gigabit Ethernet PCI Express + +pci:v000014E4d000016DE* + ID_MODEL_FROM_DATABASE=BCM57412 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016DF* + ID_MODEL_FROM_DATABASE=BCM57314 NetXtreme-C 10Gb/25Gb/40Gb/50Gb RDMA Ethernet Controller + +pci:v000014E4d000016E1* + ID_MODEL_FROM_DATABASE=NetXtreme-C Ethernet Virtual Function + +pci:v000014E4d000016E2* + ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller + +pci:v000014E4d000016E2sv0000108Esd00004866* + ID_MODEL_FROM_DATABASE=BCM57417 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller (Dual Port 10Gb/25Gb SFP28 Ethernet Controller) + +pci:v000014E4d000016E3* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E 10Gb RDMA Ethernet Controller + +pci:v000014E4d000016E5* + ID_MODEL_FROM_DATABASE=NetXtreme-C RDMA Virtual Function + +pci:v000014E4d000016E7* + ID_MODEL_FROM_DATABASE=BCM57404 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016E8* + ID_MODEL_FROM_DATABASE=BCM57406 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016E9* + ID_MODEL_FROM_DATABASE=BCM57407 NetXtreme-E 25Gb Ethernet Controller + +pci:v000014E4d000016EC* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016ED* + ID_MODEL_FROM_DATABASE=BCM57414 NetXtreme-E RDMA Partition + +pci:v000014E4d000016EE* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E Ethernet Partition + +pci:v000014E4d000016EF* + ID_MODEL_FROM_DATABASE=BCM57416 NetXtreme-E RDMA Partition + +pci:v000014E4d000016F1* + ID_MODEL_FROM_DATABASE=BCM57452 NetXtreme-E 10Gb/25Gb/40Gb/50Gb Ethernet + +pci:v000014E4d000016F3* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5727 Gigabit Ethernet PCIe + +pci:v000014E4d000016F7* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5753 Gigabit Ethernet PCI Express + +pci:v000014E4d000016FD* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5753M Gigabit Ethernet PCI Express + +pci:v000014E4d000016FDsv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5753M Gigabit Ethernet PCI Express (Compaq nx9420 Notebook) + +pci:v000014E4d000016FDsv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5753M Gigabit Ethernet PCI Express (Compaq nw8440) + +pci:v000014E4d000016FE* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5753F Fast Ethernet PCI Express + +pci:v000014E4d0000170C* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX + +pci:v000014E4d0000170Csv00001028sd00000188* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron 6000 laptop) + +pci:v000014E4d0000170Csv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron 700m/710m) + +pci:v000014E4d0000170Csv00001028sd00000196* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron 5160) + +pci:v000014E4d0000170Csv00001028sd000001AF* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron 6400) + +pci:v000014E4d0000170Csv00001028sd000001CD* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron 9400 Laptop) + +pci:v000014E4d0000170Csv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (XPS M1210) + +pci:v000014E4d0000170Csv00001028sd000001D8* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (Inspiron E1405) + +pci:v000014E4d0000170Csv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (NX6110/NC6120) + +pci:v000014E4d0000170Csv0000103Csd000030A2* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (NX7300 laptop) + +pci:v000014E4d0000170Csv000014E4sd0000170C* + ID_MODEL_FROM_DATABASE=BCM4401-B0 100Base-TX (HP Compaq 6720t Mobile Thin Client) + +pci:v000014E4d0000170D* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5901 100Base-TX + +pci:v000014E4d0000170Dsv00001014sd00000545* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5901 100Base-TX (ThinkPad R40e) + +pci:v000014E4d0000170E* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5901 100Base-TX + +pci:v000014E4d00001712* + ID_MODEL_FROM_DATABASE=NetLink BCM5906 Fast Ethernet PCI Express + +pci:v000014E4d00001713* + ID_MODEL_FROM_DATABASE=NetLink BCM5906M Fast Ethernet PCI Express + +pci:v000014E4d00001713sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=NetLink BCM5906M Fast Ethernet PCI Express (Inspiron 1420) + +pci:v000014E4d00001713sv00001028sd00000209* + ID_MODEL_FROM_DATABASE=NetLink BCM5906M Fast Ethernet PCI Express (XPS M1330) + +pci:v000014E4d00001713sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=NetLink BCM5906M Fast Ethernet PCI Express (Compaq 6710b) + +pci:v000014E4d00001713sv000017AAsd00003A23* + ID_MODEL_FROM_DATABASE=NetLink BCM5906M Fast Ethernet PCI Express (IdeaPad S10e) + +pci:v000014E4d00001750* + ID_MODEL_FROM_DATABASE=BCM57508 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet + +pci:v000014E4d00001751* + ID_MODEL_FROM_DATABASE=BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet + +pci:v000014E4d00001752* + ID_MODEL_FROM_DATABASE=BCM57502 NetXtreme-E 10Gb/25Gb/40Gb/50Gb Ethernet + +pci:v000014E4d00001806* + ID_MODEL_FROM_DATABASE=BCM5750X NetXtreme-E Ethernet Virtual Function + +pci:v000014E4d00001807* + ID_MODEL_FROM_DATABASE=BCM5750X NetXtreme-E RDMA Virtual Function + +pci:v000014E4d00003352* + ID_MODEL_FROM_DATABASE=BCM3352 + +pci:v000014E4d00003360* + ID_MODEL_FROM_DATABASE=BCM3360 + +pci:v000014E4d00004210* + ID_MODEL_FROM_DATABASE=BCM4210 iLine10 HomePNA 2.0 + +pci:v000014E4d00004211* + ID_MODEL_FROM_DATABASE=BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem + +pci:v000014E4d00004212* + ID_MODEL_FROM_DATABASE=BCM4212 v.90 56k modem + +pci:v000014E4d00004220* + ID_MODEL_FROM_DATABASE=802-11b/g Wireless PCI controller, packaged as a Linksys WPC54G ver 1.2 PCMCIA card + +pci:v000014E4d00004222* + ID_MODEL_FROM_DATABASE=NetXtreme BCM5753M Gigabit Ethernet PCI Express + +pci:v000014E4d00004301* + ID_MODEL_FROM_DATABASE=BCM4301 802.11b Wireless LAN Controller + +pci:v000014E4d00004301sv00001028sd00000407* + ID_MODEL_FROM_DATABASE=BCM4301 802.11b Wireless LAN Controller (TrueMobile 1180 Onboard WLAN) + +pci:v000014E4d00004301sv00001043sd00000120* + ID_MODEL_FROM_DATABASE=BCM4301 802.11b Wireless LAN Controller (WL-103b Wireless LAN PC Card) + +pci:v000014E4d00004301sv000016A5sd00001602* + ID_MODEL_FROM_DATABASE=BCM4301 802.11b Wireless LAN Controller (B-300 802.11b Wireless CardBus Adapter) + +pci:v000014E4d00004301sv00001737sd00004301* + ID_MODEL_FROM_DATABASE=BCM4301 802.11b Wireless LAN Controller (WMP11 v2.7 802.11b Wireless-B PCI Adapter) + +pci:v000014E4d00004305* + ID_MODEL_FROM_DATABASE=BCM4307 V.90 56k Modem + +pci:v000014E4d00004306* + ID_MODEL_FROM_DATABASE=BCM4306 802.11bg Wireless LAN controller + +pci:v000014E4d00004307* + ID_MODEL_FROM_DATABASE=BCM4306 802.11bg Wireless LAN Controller + +pci:v000014E4d00004310* + ID_MODEL_FROM_DATABASE=BCM4310 Chipcommon I/OController + +pci:v000014E4d00004311* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN + +pci:v000014E4d00004311sv00001028sd00000007* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (Wireless 1390 WLAN Mini-Card) + +pci:v000014E4d00004311sv00001028sd00000008* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (Wireless 1390 WLAN ExpressCard) + +pci:v000014E4d00004311sv0000103Csd00001363* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) + +pci:v000014E4d00004311sv0000103Csd00001364* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) + +pci:v000014E4d00004311sv0000103Csd00001365* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) + +pci:v000014E4d00004311sv0000103Csd00001374* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) + +pci:v000014E4d00004311sv0000103Csd00001375* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) + +pci:v000014E4d00004311sv0000103Csd00001376* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) + +pci:v000014E4d00004311sv0000103Csd00001377* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4311 802.11b/g Wireless LAN Controller) + +pci:v000014E4d00004311sv0000103Csd0000137F* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4322 802.11a/b/g/n Wireless LAN Controller) + +pci:v000014E4d00004311sv0000103Csd00001380* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM4322 802.11a/b/g/n Wireless LAN Controller) + +pci:v000014E4d00004311sv000014E4sd00004311* + ID_MODEL_FROM_DATABASE=BCM4311 802.11b/g WLAN (BCM94311MCG) + +pci:v000014E4d00004312* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g + +pci:v000014E4d00004312sv00001028sd00000007* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Wireless 1490 Dual Band WLAN Mini-Card) + +pci:v000014E4d00004312sv00001028sd00000008* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Wireless 1490 Dual Band WLAN ExpressCard) + +pci:v000014E4d00004312sv0000103Csd0000135A* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004312sv0000103Csd0000135F* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004312sv0000103Csd00001360* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004312sv0000103Csd00001361* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004312sv0000103Csd00001362* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004312sv0000103Csd00001370* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004312sv0000103Csd00001371* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004312sv0000103Csd00001372* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004312sv0000103Csd00001373* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004312sv0000103Csd000030B5* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Presario V3242AU) + +pci:v000014E4d00004312sv0000106Bsd00000089* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (AirPort Extreme) + +pci:v000014E4d00004312sv00001371sd0000103C* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a/b/g (Broadcom 802.11 Multiband-netwerkadapter(6715s)) + +pci:v000014E4d00004313* + ID_MODEL_FROM_DATABASE=BCM4311 802.11a + +pci:v000014E4d00004315* + ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY + +pci:v000014E4d00004315sv00001028sd0000000B* + ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (Wireless 1395 WLAN Mini-Card) + +pci:v000014E4d00004315sv00001028sd0000000C* + ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (Wireless 1397 WLAN Mini-Card) + +pci:v000014E4d00004315sv0000103Csd0000137C* + ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (BCM4312 802.11b/g Wireless LAN Controller) + +pci:v000014E4d00004315sv0000103Csd0000137D* + ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (BCM4312 802.11b/g Wireless LAN Controller) + +pci:v000014E4d00004315sv0000103Csd00001507* + ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (U98Z049.00 Wireless Mini PCIe Card) + +pci:v000014E4d00004315sv0000105Bsd0000E003* + ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (T77H030.00 Wireless Mini PCIe Card) + +pci:v000014E4d00004315sv0000105Bsd0000E01B* + ID_MODEL_FROM_DATABASE=BCM4312 802.11b/g LP-PHY (T77H106.00 Wireless Half-size Mini PCIe Card) + +pci:v000014E4d00004318* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller + +pci:v000014E4d00004318sv00001028sd00000005* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Wireless 1370 WLAN Mini-PCI Card) + +pci:v000014E4d00004318sv00001028sd00000006* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Wireless 1370 WLAN PC Card) + +pci:v000014E4d00004318sv0000103Csd00001355* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Broadcom 802.11b/g WLAN) + +pci:v000014E4d00004318sv0000103Csd00001356* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Broadcom 802.11b/g WLAN) + +pci:v000014E4d00004318sv0000103Csd00001357* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Broadcom 802.11b/g WLAN) + +pci:v000014E4d00004318sv00001043sd0000100F* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (WL-138G v2 / WL-138gE / WL-100gE) + +pci:v000014E4d00004318sv00001043sd0000120F* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (A6U notebook embedded card) + +pci:v000014E4d00004318sv00001154sd00000355* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Buffalo WLI2-PCI-G54S High Speed Mode Wireless Adapter) + +pci:v000014E4d00004318sv00001468sd00000311* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Aspire 3022WLMi, 5024WLMi, 5020) + +pci:v000014E4d00004318sv00001468sd00000312* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (TravelMate 2410) + +pci:v000014E4d00004318sv000014E4sd00000449* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (Gateway 7510GX) + +pci:v000014E4d00004318sv000016ECsd00000119* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (U.S.Robotics Wireless MAXg PC Card) + +pci:v000014E4d00004318sv00001737sd00000042* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (WMP54GS v1.1 802.11g Wireless-G PCI Adapter with SpeedBooster) + +pci:v000014E4d00004318sv00001737sd00000048* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (WPC54G v3 802.11g Wireless-G Notebook Adapter) + +pci:v000014E4d00004318sv00001737sd00000049* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (WPC54GS v2 802.11g Wireless-G Notebook Adapter with SpeedBooster) + +pci:v000014E4d00004318sv00001799sd00007000* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (F5D7000 v4000 Wireless G Desktop Card) + +pci:v000014E4d00004318sv00001799sd00007001* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (F5D7001 v2000 Wireless G Plus Desktop Card) + +pci:v000014E4d00004318sv00001799sd00007010* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (F5D7010 v4000 Wireless G Notebook Card) + +pci:v000014E4d00004318sv00001799sd00007011* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller (F5D7011 v2000 High-Speed Mode Wireless G Notebook Card) + +pci:v000014E4d00004319* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver + +pci:v000014E4d00004319sv00001028sd00000005* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver (Wireless 1470 Dual Band WLAN Mini-PCI Card) + +pci:v000014E4d00004319sv00001028sd00000006* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver (Wireless 1470 Dual Band WLAN PC Card) + +pci:v000014E4d00004319sv0000103Csd00001358* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004319sv0000103Csd00001359* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004319sv0000103Csd0000135A* + ID_MODEL_FROM_DATABASE=BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004320* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller + +pci:v000014E4d00004320sv00001028sd00000001* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (TrueMobile 1300 WLAN Mini-PCI Card) + +pci:v000014E4d00004320sv00001028sd00000002* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (TrueMobile 1300 WLAN PC Card) + +pci:v000014E4d00004320sv00001028sd00000003* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Wireless 1350 WLAN Mini-PCI Card) + +pci:v000014E4d00004320sv00001028sd00000004* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Wireless 1350 WLAN PC Card) + +pci:v000014E4d00004320sv0000103Csd000012F4* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Broadcom 802.11b/g WLAN) + +pci:v000014E4d00004320sv0000103Csd000012F8* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Broadcom 802.11b/g WLAN) + +pci:v000014E4d00004320sv0000103Csd000012FA* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Broadcom 802.11b/g WLAN) + +pci:v000014E4d00004320sv0000103Csd000012FB* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Broadcom 802.11b/g WLAN) + +pci:v000014E4d00004320sv00001043sd0000100F* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WL-100G) + +pci:v000014E4d00004320sv00001057sd00007025* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WN825G) + +pci:v000014E4d00004320sv0000106Bsd0000004E* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (AirPort Extreme) + +pci:v000014E4d00004320sv00001154sd00000330* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Buffalo WLI2-PCI-G54S High Speed Mode Wireless Desktop Adapter) + +pci:v000014E4d00004320sv0000144Fsd00007050* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (eMachines M6805 802.11g Built-in Wireless) + +pci:v000014E4d00004320sv0000144Fsd00007051* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (Sonnet Aria Extreme PCI) + +pci:v000014E4d00004320sv00001737sd00000013* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WMP54G v1 802.11g PCI Adapter) + +pci:v000014E4d00004320sv00001737sd00000014* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WMP54G v2 802.11g PCI Adapter) + +pci:v000014E4d00004320sv00001737sd00000015* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WMP54GS v1.0 802.11g Wireless-G PCI Adapter with SpeedBooster) + +pci:v000014E4d00004320sv00001737sd00004320* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (WPC54G v1 / WPC54GS v1 802.11g Wireless-G Notebook Adapter) + +pci:v000014E4d00004320sv00001799sd00007000* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (F5D7000 v1000 Wireless G Desktop Card) + +pci:v000014E4d00004320sv00001799sd00007001* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (F5D7001 v1000 Wireless G Plus Desktop Card) + +pci:v000014E4d00004320sv00001799sd00007010* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (F5D7010 v1000 Wireless G Notebook Card) + +pci:v000014E4d00004320sv00001799sd00007011* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (F5D7011 v1000 High-Speed Mode Wireless G Notebook Card) + +pci:v000014E4d00004320sv0000185Fsd00001220* + ID_MODEL_FROM_DATABASE=BCM4306 802.11b/g Wireless LAN Controller (TravelMate 290E WLAN Mini-PCI Card) + +pci:v000014E4d00004321* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a Wireless Network Controller + +pci:v000014E4d00004322* + ID_MODEL_FROM_DATABASE=BCM4322 802.11bgn Wireless Network Controller + +pci:v000014E4d00004324* + ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller + +pci:v000014E4d00004324sv00001028sd00000001* + ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (Truemobile 1400) + +pci:v000014E4d00004324sv00001028sd00000002* + ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (TrueMobile 1400 Dual Band WLAN PC Card) + +pci:v000014E4d00004324sv00001028sd00000003* + ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (Truemobile 1450 MiniPCI) + +pci:v000014E4d00004324sv00001028sd00000004* + ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (Wireless 1450 Dual Band WLAN PC Card) + +pci:v000014E4d00004324sv0000103Csd000012F9* + ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004324sv0000103Csd000012FC* + ID_MODEL_FROM_DATABASE=BCM4309 802.11abg Wireless Network Controller (Broadcom 802.11a/b/g WLAN) + +pci:v000014E4d00004325* + ID_MODEL_FROM_DATABASE=BCM4306 802.11bg Wireless Network Controller + +pci:v000014E4d00004325sv00001414sd00000003* + ID_MODEL_FROM_DATABASE=BCM4306 802.11bg Wireless Network Controller (Wireless Notebook Adapter MN-720) + +pci:v000014E4d00004325sv00001414sd00000004* + ID_MODEL_FROM_DATABASE=BCM4306 802.11bg Wireless Network Controller (Wireless PCI Adapter MN-730) + +pci:v000014E4d00004326* + ID_MODEL_FROM_DATABASE=BCM4307 Chipcommon I/O Controller? + +pci:v000014E4d00004328* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n + +pci:v000014E4d00004328sv00001028sd00000009* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless 1500 Draft 802.11n WLAN Mini-Card) + +pci:v000014E4d00004328sv00001028sd0000000A* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless 1500 Draft 802.11n WLAN Mini-card) + +pci:v000014E4d00004328sv0000103Csd00001366* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless LAN Controller) + +pci:v000014E4d00004328sv0000103Csd00001367* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless LAN Controller) + +pci:v000014E4d00004328sv0000103Csd00001368* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless LAN Controller) + +pci:v000014E4d00004328sv0000103Csd00001369* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (Wireless LAN Controller) + +pci:v000014E4d00004328sv0000106Bsd00000087* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004328sv0000106Bsd00000088* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004328sv0000106Bsd0000008B* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004328sv0000106Bsd0000008C* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004328sv0000106Bsd00000090* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004328sv000014E4sd00004328* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (BCM4328 802.11a/b/g/n) + +pci:v000014E4d00004328sv00001737sd00000066* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (WPC600N v1 802.11a/b/g/n Wireless-N CardBus Adapter) + +pci:v000014E4d00004328sv00001737sd00000068* + ID_MODEL_FROM_DATABASE=BCM4321 802.11a/b/g/n (WEC600N v1 802.11a/b/g/n Wireless-N ExpressCard) + +pci:v000014E4d00004329* + ID_MODEL_FROM_DATABASE=BCM4321 802.11b/g/n + +pci:v000014E4d00004329sv00001385sd00007B00* + ID_MODEL_FROM_DATABASE=BCM4321 802.11b/g/n (WN511B RangeMax NEXT Wireless Notebook Adapter) + +pci:v000014E4d00004329sv00001385sd00007D00* + ID_MODEL_FROM_DATABASE=BCM4321 802.11b/g/n (WN311B RangeMax Next 270 Mbps Wireless PCI Adapter) + +pci:v000014E4d00004329sv00001737sd00000058* + ID_MODEL_FROM_DATABASE=BCM4321 802.11b/g/n (WPC300N v1 Wireless-N Notebook Adapter) + +pci:v000014E4d0000432A* + ID_MODEL_FROM_DATABASE=BCM4321 802.11an Wireless Network Controller + +pci:v000014E4d0000432B* + ID_MODEL_FROM_DATABASE=BCM4322 802.11a/b/g/n Wireless LAN Controller + +pci:v000014E4d0000432Bsv00001028sd0000000D* + ID_MODEL_FROM_DATABASE=BCM4322 802.11a/b/g/n Wireless LAN Controller (Wireless 1510 Wireless-N WLAN Mini-Card) + +pci:v000014E4d0000432Bsv0000106Bsd0000008D* + ID_MODEL_FROM_DATABASE=BCM4322 802.11a/b/g/n Wireless LAN Controller (AirPort Extreme) + +pci:v000014E4d0000432Bsv0000106Bsd0000008E* + ID_MODEL_FROM_DATABASE=BCM4322 802.11a/b/g/n Wireless LAN Controller (AirPort Extreme) + +pci:v000014E4d0000432C* + ID_MODEL_FROM_DATABASE=BCM4322 802.11b/g/n + +pci:v000014E4d0000432Csv00001799sd0000D311* + ID_MODEL_FROM_DATABASE=BCM4322 802.11b/g/n (Dynex DX-NNBX 802.11n WLAN Cardbus Card) + +pci:v000014E4d0000432D* + ID_MODEL_FROM_DATABASE=BCM4322 802.11an Wireless Network Controller + +pci:v000014E4d00004331* + ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n + +pci:v000014E4d00004331sv0000106Bsd000000D6* + ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004331sv0000106Bsd000000E4* + ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004331sv0000106Bsd000000EF* + ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004331sv0000106Bsd000000F4* + ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004331sv0000106Bsd000000F5* + ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004331sv0000106Bsd0000010E* + ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004331sv0000106Bsd0000010F* + ID_MODEL_FROM_DATABASE=BCM4331 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004333* + ID_MODEL_FROM_DATABASE=Serial (EDGE/GPRS modem part of Option GT Combo Edge) + +pci:v000014E4d00004344* + ID_MODEL_FROM_DATABASE=EDGE/GPRS data and 802.11b/g combo cardbus [GC89] + +pci:v000014E4d00004350* + ID_MODEL_FROM_DATABASE=BCM43222 Wireless Network Adapter + +pci:v000014E4d00004351* + ID_MODEL_FROM_DATABASE=BCM43222 802.11abgn Wireless Network Adapter + +pci:v000014E4d00004353* + ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n + +pci:v000014E4d00004353sv00001028sd0000000E* + ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (Wireless 1520 Half-size Mini PCIe Card) + +pci:v000014E4d00004353sv0000103Csd00001509* + ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (WMIB-275N Half-size Mini PCIe Card) + +pci:v000014E4d00004353sv0000106Bsd00000093* + ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004353sv0000106Bsd000000D1* + ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004353sv0000106Bsd000000E9* + ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (AirPort Extreme) + +pci:v000014E4d00004353sv000014E4sd000004D8* + ID_MODEL_FROM_DATABASE=BCM43224 802.11a/b/g/n (Pegatron UPWL6024) + +pci:v000014E4d00004357* + ID_MODEL_FROM_DATABASE=BCM43225 802.11b/g/n + +pci:v000014E4d00004357sv0000105Bsd0000E021* + ID_MODEL_FROM_DATABASE=BCM43225 802.11b/g/n (T77H103.00 Wireless Half-size Mini PCIe Card) + +pci:v000014E4d00004358* + ID_MODEL_FROM_DATABASE=BCM43227 802.11b/g/n + +pci:v000014E4d00004359* + ID_MODEL_FROM_DATABASE=BCM43228 802.11a/b/g/n + +pci:v000014E4d00004359sv00001028sd00000011* + ID_MODEL_FROM_DATABASE=BCM43228 802.11a/b/g/n (Wireless 1530 Half-size Mini PCIe Card) + +pci:v000014E4d00004359sv0000103Csd0000182C* + ID_MODEL_FROM_DATABASE=BCM43228 802.11a/b/g/n (BCM943228HM4L 802.11a/b/g/n 2x2 Wi-Fi Adapter) + +pci:v000014E4d00004360* + ID_MODEL_FROM_DATABASE=BCM4360 802.11ac Wireless Network Adapter + +pci:v000014E4d00004365* + ID_MODEL_FROM_DATABASE=BCM43142 802.11b/g/n + +pci:v000014E4d00004365sv00001028sd00000016* + ID_MODEL_FROM_DATABASE=BCM43142 802.11b/g/n (Wireless 1704 802.11n + BT 4.0) + +pci:v000014E4d000043A0* + ID_MODEL_FROM_DATABASE=BCM4360 802.11ac Wireless Network Adapter + +pci:v000014E4d000043A1* + ID_MODEL_FROM_DATABASE=BCM4360 802.11ac Wireless Network Adapter + +pci:v000014E4d000043A2* + ID_MODEL_FROM_DATABASE=BCM4360 802.11ac Wireless Network Adapter + +pci:v000014E4d000043A3* + ID_MODEL_FROM_DATABASE=BCM4350 802.11ac Wireless Network Adapter + +pci:v000014E4d000043A9* + ID_MODEL_FROM_DATABASE=BCM43217 802.11b/g/n + +pci:v000014E4d000043AA* + ID_MODEL_FROM_DATABASE=BCM43131 802.11b/g/n + +pci:v000014E4d000043AE* + ID_MODEL_FROM_DATABASE=BCM43162 802.11ac Wireless Network Adapter + +pci:v000014E4d000043B1* + ID_MODEL_FROM_DATABASE=BCM4352 802.11ac Wireless Network Adapter + +pci:v000014E4d000043BA* + ID_MODEL_FROM_DATABASE=BCM43602 802.11ac Wireless LAN SoC + +pci:v000014E4d000043BB* + ID_MODEL_FROM_DATABASE=BCM43602 802.11ac Wireless LAN SoC + +pci:v000014E4d000043BC* + ID_MODEL_FROM_DATABASE=BCM43602 802.11ac Wireless LAN SoC + +pci:v000014E4d000043D3* + ID_MODEL_FROM_DATABASE=BCM43567 802.11ac Wireless Network Adapter + +pci:v000014E4d000043D9* + ID_MODEL_FROM_DATABASE=BCM43570 802.11ac Wireless Network Adapter + +pci:v000014E4d000043DC* + ID_MODEL_FROM_DATABASE=BCM4355 802.11ac Wireless LAN SoC + +pci:v000014E4d000043DF* + ID_MODEL_FROM_DATABASE=BCM4354 802.11ac Wireless LAN SoC + +pci:v000014E4d000043E9* + ID_MODEL_FROM_DATABASE=BCM4358 802.11ac Wireless LAN SoC + +pci:v000014E4d000043EC* + ID_MODEL_FROM_DATABASE=BCM4356 802.11ac Wireless Network Adapter + +pci:v000014E4d00004401* + ID_MODEL_FROM_DATABASE=BCM4401 100Base-T + +pci:v000014E4d00004401sv00001025sd00000035* + ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (TravelMate 660) + +pci:v000014E4d00004401sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (Extensa 3000 series laptop) + +pci:v000014E4d00004401sv00001028sd00008127* + ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (Dimension 2400) + +pci:v000014E4d00004401sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (tc1100 tablet) + +pci:v000014E4d00004401sv00001043sd000080A8* + ID_MODEL_FROM_DATABASE=BCM4401 100Base-T (A7V8X motherboard) + +pci:v000014E4d00004402* + ID_MODEL_FROM_DATABASE=BCM4402 Integrated 10/100BaseT + +pci:v000014E4d00004403* + ID_MODEL_FROM_DATABASE=BCM4402 V.90 56k Modem + +pci:v000014E4d00004410* + ID_MODEL_FROM_DATABASE=BCM4413 iLine32 HomePNA 2.0 + +pci:v000014E4d00004411* + ID_MODEL_FROM_DATABASE=BCM4413 V.90 56k modem + +pci:v000014E4d00004412* + ID_MODEL_FROM_DATABASE=BCM4412 10/100BaseT + +pci:v000014E4d00004430* + ID_MODEL_FROM_DATABASE=BCM44xx CardBus iLine32 HomePNA 2.0 + +pci:v000014E4d00004432* + ID_MODEL_FROM_DATABASE=BCM4432 CardBus 10/100BaseT + +pci:v000014E4d00004464* + ID_MODEL_FROM_DATABASE=BCM4364 802.11ac Wireless Network Adapter + +pci:v000014E4d00004488* + ID_MODEL_FROM_DATABASE=BCM4377b Wireless Network Adapter + +pci:v000014E4d00004610* + ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 PCI to SB Bridge + +pci:v000014E4d00004611* + ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 iLine32 HomePNA 1.0 + +pci:v000014E4d00004612* + ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 V.90 56k Modem + +pci:v000014E4d00004613* + ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 Ethernet Controller + +pci:v000014E4d00004614* + ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 External Interface + +pci:v000014E4d00004615* + ID_MODEL_FROM_DATABASE=BCM4610 Sentry5 USB Controller + +pci:v000014E4d00004704* + ID_MODEL_FROM_DATABASE=BCM4704 PCI to SB Bridge + +pci:v000014E4d00004705* + ID_MODEL_FROM_DATABASE=BCM4704 Sentry5 802.11b Wireless LAN Controller + +pci:v000014E4d00004706* + ID_MODEL_FROM_DATABASE=BCM4704 Sentry5 Ethernet Controller + +pci:v000014E4d00004707* + ID_MODEL_FROM_DATABASE=BCM4704 Sentry5 USB Controller + +pci:v000014E4d00004708* + ID_MODEL_FROM_DATABASE=BCM4704 Crypto Accelerator + +pci:v000014E4d00004710* + ID_MODEL_FROM_DATABASE=BCM4710 Sentry5 PCI to SB Bridge + +pci:v000014E4d00004711* + ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 iLine32 HomePNA 2.0 + +pci:v000014E4d00004712* + ID_MODEL_FROM_DATABASE=BCM47xx V.92 56k modem + +pci:v000014E4d00004713* + ID_MODEL_FROM_DATABASE=Sentry5 Ethernet Controller + +pci:v000014E4d00004714* + ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 External Interface + +pci:v000014E4d00004715* + ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 USB / Ethernet Controller + +pci:v000014E4d00004716* + ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 USB Host Controller + +pci:v000014E4d00004717* + ID_MODEL_FROM_DATABASE=BCM47xx Sentry5 USB Device Controller + +pci:v000014E4d00004718* + ID_MODEL_FROM_DATABASE=Sentry5 Crypto Accelerator + +pci:v000014E4d00004719* + ID_MODEL_FROM_DATABASE=BCM47xx/53xx RoboSwitch Core + +pci:v000014E4d00004720* + ID_MODEL_FROM_DATABASE=BCM4712 MIPS CPU + +pci:v000014E4d00004727* + ID_MODEL_FROM_DATABASE=BCM4313 802.11bgn Wireless Network Adapter + +pci:v000014E4d00004727sv00001028sd00000010* + ID_MODEL_FROM_DATABASE=BCM4313 802.11bgn Wireless Network Adapter (Inspiron M5010 / XPS 8300) + +pci:v000014E4d00005365* + ID_MODEL_FROM_DATABASE=BCM5365P Sentry5 Host Bridge + +pci:v000014E4d00005600* + ID_MODEL_FROM_DATABASE=BCM5600 StrataSwitch 24+2 Ethernet Switch Controller + +pci:v000014E4d00005605* + ID_MODEL_FROM_DATABASE=BCM5605 StrataSwitch 24+2 Ethernet Switch Controller + +pci:v000014E4d00005615* + ID_MODEL_FROM_DATABASE=BCM5615 StrataSwitch 24+2 Ethernet Switch Controller + +pci:v000014E4d00005625* + ID_MODEL_FROM_DATABASE=BCM5625 StrataSwitch 24+2 Ethernet Switch Controller + +pci:v000014E4d00005645* + ID_MODEL_FROM_DATABASE=BCM5645 StrataSwitch 24+2 Ethernet Switch Controller + +pci:v000014E4d00005670* + ID_MODEL_FROM_DATABASE=BCM5670 8-Port 10GE Ethernet Switch Fabric + +pci:v000014E4d00005680* + ID_MODEL_FROM_DATABASE=BCM5680 G-Switch 8 Port Gigabit Ethernet Switch Controller + +pci:v000014E4d00005690* + ID_MODEL_FROM_DATABASE=BCM5690 12-port Multi-Layer Gigabit Ethernet Switch + +pci:v000014E4d00005691* + ID_MODEL_FROM_DATABASE=BCM5691 GE/10GE 8+2 Gigabit Ethernet Switch Controller + +pci:v000014E4d00005692* + ID_MODEL_FROM_DATABASE=BCM5692 12-port Multi-Layer Gigabit Ethernet Switch + +pci:v000014E4d00005695* + ID_MODEL_FROM_DATABASE=BCM5695 12-port + HiGig Multi-Layer Gigabit Ethernet Switch + +pci:v000014E4d00005698* + ID_MODEL_FROM_DATABASE=BCM5698 12-port Multi-Layer Gigabit Ethernet Switch + +pci:v000014E4d00005820* + ID_MODEL_FROM_DATABASE=BCM5820 Crypto Accelerator + +pci:v000014E4d00005821* + ID_MODEL_FROM_DATABASE=BCM5821 Crypto Accelerator + +pci:v000014E4d00005822* + ID_MODEL_FROM_DATABASE=BCM5822 Crypto Accelerator + +pci:v000014E4d00005823* + ID_MODEL_FROM_DATABASE=BCM5823 Crypto Accelerator + +pci:v000014E4d00005824* + ID_MODEL_FROM_DATABASE=BCM5824 Crypto Accelerator + +pci:v000014E4d00005840* + ID_MODEL_FROM_DATABASE=BCM5840 Crypto Accelerator + +pci:v000014E4d00005841* + ID_MODEL_FROM_DATABASE=BCM5841 Crypto Accelerator + +pci:v000014E4d00005850* + ID_MODEL_FROM_DATABASE=BCM5850 Crypto Accelerator + +pci:v000014E4d00005E87* + ID_MODEL_FROM_DATABASE=Valkyrie offload engine + +pci:v000014E4d00005E88* + ID_MODEL_FROM_DATABASE=Viper Offload Engine + +pci:v000014E4d00008602* + ID_MODEL_FROM_DATABASE=BCM7400/BCM7405 Serial ATA Controller + +pci:v000014E4d00009026* + ID_MODEL_FROM_DATABASE=CN99xx [ThunderX2] Integrated USB 3.0 xHCI Host Controller + +pci:v000014E4d00009027* + ID_MODEL_FROM_DATABASE=CN99xx [ThunderX2] Integrated AHCI/SATA 3 Host Controller + +pci:v000014E4d0000A8D8* + ID_MODEL_FROM_DATABASE=BCM43224/5 Wireless Network Adapter + +pci:v000014E4d0000AA52* + ID_MODEL_FROM_DATABASE=BCM43602 802.11ac Wireless LAN SoC + +pci:v000014E4d0000B302* + ID_MODEL_FROM_DATABASE=BCM56302 StrataXGS 24x1GE 2x10GE Switch Controller + +pci:v000014E4d0000B334* + ID_MODEL_FROM_DATABASE=BCM56334 StrataXGS 24x1GE 4x10GE Switch Controller + +pci:v000014E4d0000B370* + ID_MODEL_FROM_DATABASE=BCM56370 Switch ASIC + +pci:v000014E4d0000B371* + ID_MODEL_FROM_DATABASE=BCM56371 Switch ASIC + +pci:v000014E4d0000B372* + ID_MODEL_FROM_DATABASE=BCM56372 Switch ASIC + +pci:v000014E4d0000B375* + ID_MODEL_FROM_DATABASE=BCM56375 Switch ASIC + +pci:v000014E4d0000B376* + ID_MODEL_FROM_DATABASE=BCM56376 Switch ASIC + +pci:v000014E4d0000B377* + ID_MODEL_FROM_DATABASE=BCM56377 Switch ASIC + +pci:v000014E4d0000B379* + ID_MODEL_FROM_DATABASE=Broadcom BCM56379 Switch ASIC + +pci:v000014E4d0000B470* + ID_MODEL_FROM_DATABASE=BCM56470 SWITCH ASIC + +pci:v000014E4d0000B471* + ID_MODEL_FROM_DATABASE=BCM56471 SWITCH ASIC + +pci:v000014E4d0000B472* + ID_MODEL_FROM_DATABASE=BCM56472 SWITCH ASIC + +pci:v000014E4d0000B800* + ID_MODEL_FROM_DATABASE=BCM56800 StrataXGS 10GE Switch Controller + +pci:v000014E4d0000B842* + ID_MODEL_FROM_DATABASE=BCM56842 Trident 10GE Switch Controller + +pci:v000014E4d0000B850* + ID_MODEL_FROM_DATABASE=Broadcom BCM56850 Switch ASIC + +pci:v000014E4d0000B880* + ID_MODEL_FROM_DATABASE=BCM56880 Switch ASIC + +pci:v000014E4d0000B960* + ID_MODEL_FROM_DATABASE=Broadcom BCM56960 Switch ASIC + +pci:v000014E4d0000B990* + ID_MODEL_FROM_DATABASE=BCM56990 Switch ASIC + +pci:v000014E4d0000D802* + ID_MODEL_FROM_DATABASE=BCM58802 Stingray 50Gb Ethernet SoC + +pci:v000014E4d0000D802sv000014E4sd00008021* + ID_MODEL_FROM_DATABASE=BCM58802 Stingray 50Gb Ethernet SoC (Stingray Dual-Port 25Gb Ethernet PCIe SmartNIC w16GB DRAM (Part No BCM958802A8046C)) + +pci:v000014E4d0000D802sv000014E4sd00008023* + ID_MODEL_FROM_DATABASE=BCM58802 Stingray 50Gb Ethernet SoC (PS410T-H04 NetXtreme-S 4x10G 10GBaseT PCIe SmartNIC) + +pci:v000014E4d0000D802sv000014E4sd00008024* + ID_MODEL_FROM_DATABASE=BCM58802 Stingray 50Gb Ethernet SoC (Stingray Dual-Port 25Gb Ethernet PCIe SmartNIC w4GB DRAM (Part No BCM958802A8044C)) + +pci:v000014E4d0000D802sv000014E4sd00008028* + ID_MODEL_FROM_DATABASE=BCM58802 Stingray 50Gb Ethernet SoC (Stingray Dual-Port 25Gb Ethernet PCIe SmartNIC w8GB DRAM (Part No BCM958802A8048C)) + +pci:v000014E4d0000D802sv00001BB0sd00000021* + ID_MODEL_FROM_DATABASE=BCM58802 Stingray 50Gb Ethernet SoC (HPE SimpliVity Accelerator) + +pci:v000014E4d0000D804* + ID_MODEL_FROM_DATABASE=BCM58804 Stingray 100Gb Ethernet SoC + +pci:v000014E5* + ID_VENDOR_FROM_DATABASE=Pixelfusion Ltd + +pci:v000014E6* + ID_VENDOR_FROM_DATABASE=SHINING Technology Inc + +pci:v000014E7* + ID_VENDOR_FROM_DATABASE=3CX + +pci:v000014E8* + ID_VENDOR_FROM_DATABASE=RAYCER Inc + +pci:v000014E9* + ID_VENDOR_FROM_DATABASE=GARNETS System CO Ltd + +pci:v000014EA* + ID_VENDOR_FROM_DATABASE=Planex Communications, Inc + +pci:v000014EAd0000AB06* + ID_MODEL_FROM_DATABASE=FNW-3603-TX CardBus Fast Ethernet + +pci:v000014EAd0000AB07* + ID_MODEL_FROM_DATABASE=RTL81xx RealTek Ethernet + +pci:v000014EAd0000AB08* + ID_MODEL_FROM_DATABASE=FNW-3602-TX CardBus Fast Ethernet + +pci:v000014EB* + ID_VENDOR_FROM_DATABASE=SEIKO EPSON Corp + +pci:v000014EC* + ID_VENDOR_FROM_DATABASE=Agilent Technologies + +pci:v000014ECd00000000* + ID_MODEL_FROM_DATABASE=Aciris Digitizer (malformed ID) + +pci:v000014ED* + ID_VENDOR_FROM_DATABASE=DATAKINETICS Ltd + +pci:v000014EE* + ID_VENDOR_FROM_DATABASE=MASPRO KENKOH Corp + +pci:v000014EF* + ID_VENDOR_FROM_DATABASE=CARRY Computer ENG. CO Ltd + +pci:v000014F0* + ID_VENDOR_FROM_DATABASE=CANON RESEACH CENTRE FRANCE + +pci:v000014F1* + ID_VENDOR_FROM_DATABASE=Conexant Systems, Inc. + +pci:v000014F1d00001002* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001003* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001004* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001005* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001006* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001022* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001023* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001024* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001025* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001026* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001032* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001033* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem + +pci:v000014F1d00001033sv00001033sd00008077* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (NEC) + +pci:v000014F1d00001033sv0000122Dsd00004027* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Dell Zeus - MDP3880-W(B) Data Fax Modem) + +pci:v000014F1d00001033sv0000122Dsd00004030* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Dell Mercury - MDP3880-U(B) Data Fax Modem) + +pci:v000014F1d00001033sv0000122Dsd00004034* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Dell Thor - MDP3880-W(U) Data Fax Modem) + +pci:v000014F1d00001033sv000013E0sd0000020D* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Dell Copper) + +pci:v000014F1d00001033sv000013E0sd0000020E* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Dell Silver) + +pci:v000014F1d00001033sv000013E0sd00000261* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v000014F1d00001033sv000013E0sd00000290* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Compaq Goldwing) + +pci:v000014F1d00001033sv000013E0sd000002A0* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v000014F1d00001033sv000013E0sd000002B0* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v000014F1d00001033sv000013E0sd000002C0* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Compaq Scooter) + +pci:v000014F1d00001033sv000013E0sd000002D0* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v000014F1d00001033sv0000144Fsd00001500* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P85-DF (1)) + +pci:v000014F1d00001033sv0000144Fsd00001501* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P85-DF (2)) + +pci:v000014F1d00001033sv0000144Fsd0000150A* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P85-DF (3)) + +pci:v000014F1d00001033sv0000144Fsd0000150B* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P85-DF Low Profile (1)) + +pci:v000014F1d00001033sv0000144Fsd00001510* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P85-DF Low Profile (2)) + +pci:v000014F1d00001034* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem + +pci:v000014F1d00001035* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + +pci:v000014F1d00001035sv000010CFsd00001098* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Fujitsu P85-DFSV) + +pci:v000014F1d00001036* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem + +pci:v000014F1d00001036sv0000104Dsd00008067* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (HCF 56k Modem) + +pci:v000014F1d00001036sv0000122Dsd00004029* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (MDP3880SP-W) + +pci:v000014F1d00001036sv0000122Dsd00004031* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (MDP3880SP-U) + +pci:v000014F1d00001036sv000013E0sd00000209* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Dell Titanium) + +pci:v000014F1d00001036sv000013E0sd0000020A* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Dell Graphite) + +pci:v000014F1d00001036sv000013E0sd00000260* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Gateway Red Owl) + +pci:v000014F1d00001036sv000013E0sd00000270* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Gateway White Horse) + +pci:v000014F1d00001052* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Worldwide) + +pci:v000014F1d00001053* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (Worldwide) + +pci:v000014F1d00001054* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem (Worldwide) + +pci:v000014F1d00001055* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Worldwide) + +pci:v000014F1d00001056* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide) + +pci:v000014F1d00001056sv0000122Dsd00004035* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide) (MDP3900V-W) + +pci:v000014F1d00001057* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide) + +pci:v000014F1d00001059* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem (Worldwide) + +pci:v000014F1d00001063* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem + +pci:v000014F1d00001064* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem + +pci:v000014F1d00001065* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + +pci:v000014F1d00001066* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem + +pci:v000014F1d00001066sv0000122Dsd00004033* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Dell Athena - MDP3900V-U) + +pci:v000014F1d00001085* + ID_MODEL_FROM_DATABASE=HCF V90 56k Data/Fax/Voice/Spkp PCI Modem + +pci:v000014F1d000010B6* + ID_MODEL_FROM_DATABASE=CX06834-11 HCF V.92 56k Data/Fax/Voice/Spkp Modem + +pci:v000014F1d00001433* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem + +pci:v000014F1d00001434* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem + +pci:v000014F1d00001435* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + +pci:v000014F1d00001436* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem + +pci:v000014F1d00001453* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem + +pci:v000014F1d00001453sv000013E0sd00000240* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v000014F1d00001453sv000013E0sd00000250* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM) + +pci:v000014F1d00001453sv0000144Fsd00001502* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P95-DF (1)) + +pci:v000014F1d00001453sv0000144Fsd00001503* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax Modem (IBM P95-DF (2)) + +pci:v000014F1d00001454* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice Modem + +pci:v000014F1d00001455* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + +pci:v000014F1d00001456* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem + +pci:v000014F1d00001456sv0000122Dsd00004035* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Dell Europa - MDP3900V-W) + +pci:v000014F1d00001456sv0000122Dsd00004302* + ID_MODEL_FROM_DATABASE=HCF 56k Data/Fax/Voice/Spkp Modem (Dell MP3930V-W(C) MiniPCI) + +pci:v000014F1d00001610* + ID_MODEL_FROM_DATABASE=ADSL AccessRunner PCI Arbitration Device + +pci:v000014F1d00001611* + ID_MODEL_FROM_DATABASE=AccessRunner PCI ADSL Interface Device + +pci:v000014F1d00001620* + ID_MODEL_FROM_DATABASE=AccessRunner V2 PCI ADSL Arbitration Device + +pci:v000014F1d00001621* + ID_MODEL_FROM_DATABASE=AccessRunner V2 PCI ADSL Interface Device + +pci:v000014F1d00001622* + ID_MODEL_FROM_DATABASE=AccessRunner V2 PCI ADSL Yukon WAN Adapter + +pci:v000014F1d00001803* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001803sv00000E11sd00000023* + ID_MODEL_FROM_DATABASE=HCF 56k Modem (623-LAN Grizzly) + +pci:v000014F1d00001803sv00000E11sd00000043* + ID_MODEL_FROM_DATABASE=HCF 56k Modem (623-LAN Yogi) + +pci:v000014F1d00001811* + ID_MODEL_FROM_DATABASE=MiniPCI Network Adapter + +pci:v000014F1d00001815* + ID_MODEL_FROM_DATABASE=HCF 56k Modem + +pci:v000014F1d00001815sv00000E11sd00000022* + ID_MODEL_FROM_DATABASE=HCF 56k Modem (Grizzly) + +pci:v000014F1d00001815sv00000E11sd00000042* + ID_MODEL_FROM_DATABASE=HCF 56k Modem (Yogi) + +pci:v000014F1d00001830* + ID_MODEL_FROM_DATABASE=CX861xx Integrated Host Bridge + +pci:v000014F1d00002003* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem + +pci:v000014F1d00002004* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem + +pci:v000014F1d00002005* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + +pci:v000014F1d00002006* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem + +pci:v000014F1d00002013* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem + +pci:v000014F1d00002013sv00000E11sd0000B195* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Bear) + +pci:v000014F1d00002013sv00000E11sd0000B196* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Seminole 1) + +pci:v000014F1d00002013sv00000E11sd0000B1BE* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Seminole 2) + +pci:v000014F1d00002013sv00001025sd00008013* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Acer) + +pci:v000014F1d00002013sv00001033sd0000809D* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (NEC) + +pci:v000014F1d00002013sv00001033sd000080BC* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (NEC) + +pci:v000014F1d00002013sv0000155Dsd00006793* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (HP) + +pci:v000014F1d00002013sv0000155Dsd00008850* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (E Machines) + +pci:v000014F1d00002014* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem + +pci:v000014F1d00002015* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + +pci:v000014F1d00002016* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem + +pci:v000014F1d00002043* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (WorldW SmartDAA) + +pci:v000014F1d00002044* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (WorldW SmartDAA) + +pci:v000014F1d00002045* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (WorldW SmartDAA) + +pci:v000014F1d00002045sv000014F1sd00002045* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (WorldW SmartDAA) (Generic SoftK56) + +pci:v000014F1d00002046* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (WorldW SmartDAA) + +pci:v000014F1d00002063* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (SmartDAA) + +pci:v000014F1d00002064* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (SmartDAA) + +pci:v000014F1d00002065* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (SmartDAA) + +pci:v000014F1d00002066* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (SmartDAA) + +pci:v000014F1d00002093* + ID_MODEL_FROM_DATABASE=HSF 56k Modem + +pci:v000014F1d00002093sv0000155Dsd00002F07* + ID_MODEL_FROM_DATABASE=HSF 56k Modem (Legend) + +pci:v000014F1d00002143* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Cell Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002144* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Cell Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002145* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002146* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002163* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Cell Modem (Mob SmartDAA) + +pci:v000014F1d00002164* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Cell Modem (Mob SmartDAA) + +pci:v000014F1d00002165* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob SmartDAA) + +pci:v000014F1d00002166* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mob SmartDAA) + +pci:v000014F1d00002343* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax CardBus Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002344* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice CardBus Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002345* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002346* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002363* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax CardBus Modem (Mob SmartDAA) + +pci:v000014F1d00002364* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice CardBus Modem (Mob SmartDAA) + +pci:v000014F1d00002365* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob SmartDAA) + +pci:v000014F1d00002366* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mob SmartDAA) + +pci:v000014F1d00002443* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002443sv0000104Dsd00008075* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Mob WorldW SmartDAA) (Modem) + +pci:v000014F1d00002443sv0000104Dsd00008083* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Mob WorldW SmartDAA) (Modem) + +pci:v000014F1d00002443sv0000104Dsd00008097* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Mob WorldW SmartDAA) (Modem) + +pci:v000014F1d00002444* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002445* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002446* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (Mob WorldW SmartDAA) + +pci:v000014F1d00002463* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Mob SmartDAA) + +pci:v000014F1d00002464* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice Modem (Mob SmartDAA) + +pci:v000014F1d00002465* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob SmartDAA) + +pci:v000014F1d00002466* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax/Voice/Spkp Modem (Mob SmartDAA) + +pci:v000014F1d00002702* + ID_MODEL_FROM_DATABASE=HSFi modem RD01-D270 + +pci:v000014F1d00002702sv00001028sd00008D88* + ID_MODEL_FROM_DATABASE=HSFi modem RD01-D270 (SmartHSFi V92 56K PCI Modem) + +pci:v000014F1d00002F00* + ID_MODEL_FROM_DATABASE=HSF 56k HSFi Modem + +pci:v000014F1d00002F00sv000013E0sd00008D84* + ID_MODEL_FROM_DATABASE=HSF 56k HSFi Modem (IBM HSFi V.90) + +pci:v000014F1d00002F00sv000013E0sd00008D85* + ID_MODEL_FROM_DATABASE=HSF 56k HSFi Modem (Compaq Stinger) + +pci:v000014F1d00002F00sv000014F1sd00002004* + ID_MODEL_FROM_DATABASE=HSF 56k HSFi Modem (Dynalink 56PMi) + +pci:v000014F1d00002F02* + ID_MODEL_FROM_DATABASE=HSF 56k HSFi Data/Fax + +pci:v000014F1d00002F11* + ID_MODEL_FROM_DATABASE=HSF 56k HSFi Modem + +pci:v000014F1d00002F20* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem + +pci:v000014F1d00002F20sv000014F1sd0000200C* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Soft Data Fax Modem with SmartCP) + +pci:v000014F1d00002F20sv000014F1sd0000200F* + ID_MODEL_FROM_DATABASE=HSF 56k Data/Fax Modem (Dimension 3000) + +pci:v000014F1d00002F30* + ID_MODEL_FROM_DATABASE=SoftV92 SpeakerPhone SoftRing Modem with SmartSP + +pci:v000014F1d00002F30sv000014F1sd00002014* + ID_MODEL_FROM_DATABASE=SoftV92 SpeakerPhone SoftRing Modem with SmartSP (Devolo MikroLink 56K Modem PCI) + +pci:v000014F1d00002F50* + ID_MODEL_FROM_DATABASE=Conexant SoftK56 Data/Fax Modem + +pci:v000014F1d00005B7A* + ID_MODEL_FROM_DATABASE=CX23418 Single-Chip MPEG-2 Encoder with Integrated Analog Video/Broadcast Audio Decoder + +pci:v000014F1d00005B7Asv00000070sd00007444* + ID_MODEL_FROM_DATABASE=CX23418 Single-Chip MPEG-2 Encoder with Integrated Analog Video/Broadcast Audio Decoder (WinTV HVR-1600) + +pci:v000014F1d00005B7Asv0000107Dsd00006F34* + ID_MODEL_FROM_DATABASE=CX23418 Single-Chip MPEG-2 Encoder with Integrated Analog Video/Broadcast Audio Decoder (WinFast DVR3100 H) + +pci:v000014F1d00005B7Asv00005854sd00003343* + ID_MODEL_FROM_DATABASE=CX23418 Single-Chip MPEG-2 Encoder with Integrated Analog Video/Broadcast Audio Decoder (GoTView PCI DVD3 Hybrid) + +pci:v000014F1d00008200* + ID_MODEL_FROM_DATABASE=CX25850 + +pci:v000014F1d00008234* + ID_MODEL_FROM_DATABASE=RS8234 ATM SAR Controller [ServiceSAR Plus] + +pci:v000014F1d00008800* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder + +pci:v000014F1d00008800sv00000070sd00002801* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Hauppauge WinTV 28xxx (Roslyn) models) + +pci:v000014F1d00008800sv00000070sd00003400* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV 34604) + +pci:v000014F1d00008800sv00000070sd00003401* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Hauppauge WinTV 34xxx models) + +pci:v000014F1d00008800sv00000070sd00006902* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV HVR-4000-HD) + +pci:v000014F1d00008800sv00000070sd00007801* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV HVR-1800 MCE) + +pci:v000014F1d00008800sv00000070sd00009001* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Nova-T DVB-T) + +pci:v000014F1d00008800sv00000070sd00009200* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Nova-SE2 DVB-S) + +pci:v000014F1d00008800sv00000070sd00009202* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Nova-S-Plus DVB-S) + +pci:v000014F1d00008800sv00000070sd00009402* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV-HVR1100 DVB-T/Hybrid) + +pci:v000014F1d00008800sv00000070sd00009600* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV 88x Video) + +pci:v000014F1d00008800sv00000070sd00009802* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinTV-HVR1100 DVB-T/Hybrid (Low Profile)) + +pci:v000014F1d00008800sv00001002sd000000F8* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (ATI TV Wonder Pro) + +pci:v000014F1d00008800sv00001002sd000000F9* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (ATI TV Wonder) + +pci:v000014F1d00008800sv00001002sd0000A101* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (HDTV Wonder) + +pci:v000014F1d00008800sv00001043sd00004823* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (PVR-416) + +pci:v000014F1d00008800sv0000107Dsd00006611* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Winfast TV 2000XP Expert) + +pci:v000014F1d00008800sv0000107Dsd00006613* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Leadtek Winfast 2000XP Expert) + +pci:v000014F1d00008800sv0000107Dsd00006620* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Leadtek Winfast DV2000) + +pci:v000014F1d00008800sv0000107Dsd0000663C* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Leadtek PVR 2000) + +pci:v000014F1d00008800sv0000107Dsd0000665F* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (WinFast DTV1000-T) + +pci:v000014F1d00008800sv000010FCsd0000D003* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (IODATA GV-VCP3/PCI) + +pci:v000014F1d00008800sv000010FCsd0000D035* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (IODATA GV/BCTV7E) + +pci:v000014F1d00008800sv00001421sd00000334* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Instant TV DVB-T PCI) + +pci:v000014F1d00008800sv00001461sd0000000A* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (AVerTV 303 (M126)) + +pci:v000014F1d00008800sv00001461sd0000000B* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (AverTV Studio 303 (M126)) + +pci:v000014F1d00008800sv00001461sd00008011* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (UltraTV Media Center PCI 550) + +pci:v000014F1d00008800sv00001462sd00008606* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (MSI TV-@nywhere Master) + +pci:v000014F1d00008800sv000014C7sd00000107* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (GDI Black Gold) + +pci:v000014F1d00008800sv000014F1sd00000187* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Conexant DVB-T reference design) + +pci:v000014F1d00008800sv000014F1sd00000342* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Digital-Logic MICROSPACE Entertainment Center (MEC)) + +pci:v000014F1d00008800sv0000153Bsd00001166* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Cinergy 1400 DVB-T) + +pci:v000014F1d00008800sv00001540sd00002580* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Provideo PV259) + +pci:v000014F1d00008800sv00001554sd00004811* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (PixelView) + +pci:v000014F1d00008800sv00001554sd00004813* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (Club 3D ZAP1000 MCE Edition) + +pci:v000014F1d00008800sv000017DEsd000008A1* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (KWorld/VStream XPert DVB-T with cx22702) + +pci:v000014F1d00008800sv000017DEsd000008A6* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (KWorld/VStream XPert DVB-T) + +pci:v000014F1d00008800sv000017DEsd000008B2* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (KWorld DVB-S 100) + +pci:v000014F1d00008800sv000017DEsd0000A8A6* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (digitalnow DNTV Live! DVB-T) + +pci:v000014F1d00008800sv00001822sd00000025* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (digitalnow DNTV Live! DVB-T Pro) + +pci:v000014F1d00008800sv0000185Bsd0000E000* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (VideoMate X500) + +pci:v000014F1d00008800sv000018ACsd0000D500* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV 5 Gold) + +pci:v000014F1d00008800sv000018ACsd0000D810* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV 3 Gold-Q) + +pci:v000014F1d00008800sv000018ACsd0000D820* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV 3 Gold-T) + +pci:v000014F1d00008800sv000018ACsd0000DB00* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV DVB-T1) + +pci:v000014F1d00008800sv000018ACsd0000DB11* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV DVB-T Plus) + +pci:v000014F1d00008800sv000018ACsd0000DB50* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (FusionHDTV DVB-T Dual Digital) + +pci:v000014F1d00008800sv00005654sd00002388* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (GoTView PCI Hybrid TV Tuner Card) + +pci:v000014F1d00008800sv00007063sd00003000* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (pcHDTV HD3000 HDTV) + +pci:v000014F1d00008800sv00007063sd00005500* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder (pcHDTV HD-5500) + +pci:v000014F1d00008801* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] + +pci:v000014F1d00008801sv00000070sd00002801* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (Hauppauge WinTV 28xxx (Roslyn) models) + +pci:v000014F1d00008801sv0000185Bsd0000E000* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (VideoMate X500) + +pci:v000014F1d00008801sv00005654sd00002388* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (GoTView PCI Hybrid Audio AVStream Device) + +pci:v000014F1d00008801sv00007063sd00005500* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (pcHDTV HD-5500) + +pci:v000014F1d00008802* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] + +pci:v000014F1d00008802sv00000070sd00002801* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (Hauppauge WinTV 28xxx (Roslyn) models) + +pci:v000014F1d00008802sv00000070sd00006902* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (WinTV HVR-4000-HD) + +pci:v000014F1d00008802sv00000070sd00009002* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (Nova-T DVB-T Model 909) + +pci:v000014F1d00008802sv00000070sd00009402* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (WinTV-HVR1100 DVB-T/Hybrid) + +pci:v000014F1d00008802sv00000070sd00009600* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (WinTV 88x MPEG Encoder) + +pci:v000014F1d00008802sv00001043sd00004823* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (PVR-416) + +pci:v000014F1d00008802sv0000107Dsd0000663C* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (Leadtek PVR 2000) + +pci:v000014F1d00008802sv0000107Dsd0000665F* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (WinFast DTV1000-T) + +pci:v000014F1d00008802sv000014F1sd00000187* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (Conexant DVB-T reference design) + +pci:v000014F1d00008802sv000017DEsd000008A1* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (XPert DVB-T PCI BDA DVBT 23880 Transport Stream Capture) + +pci:v000014F1d00008802sv000017DEsd000008A6* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (KWorld/VStream XPert DVB-T) + +pci:v000014F1d00008802sv000018ACsd0000D500* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (DViCO FusionHDTV5 Gold) + +pci:v000014F1d00008802sv000018ACsd0000D810* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (DViCO FusionHDTV3 Gold-Q) + +pci:v000014F1d00008802sv000018ACsd0000D820* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (DViCO FusionHDTV3 Gold-T) + +pci:v000014F1d00008802sv000018ACsd0000DB00* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (DVICO FusionHDTV DVB-T1) + +pci:v000014F1d00008802sv000018ACsd0000DB10* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (DVICO FusionHDTV DVB-T Plus) + +pci:v000014F1d00008802sv00005654sd00002388* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (GoTView PCI Hybrid TS Capture Device) + +pci:v000014F1d00008802sv00007063sd00003000* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (pcHDTV HD3000 HDTV) + +pci:v000014F1d00008802sv00007063sd00005500* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] (pcHDTV HD-5500) + +pci:v000014F1d00008804* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] + +pci:v000014F1d00008804sv00000070sd00006902* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] (WinTV HVR-4000-HD) + +pci:v000014F1d00008804sv00000070sd00009002* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] (Nova-T DVB-T Model 909) + +pci:v000014F1d00008804sv00000070sd00009402* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] (WinTV-HVR1100 DVB-T/Hybrid) + +pci:v000014F1d00008804sv00007063sd00005500* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] (pcHDTV HD-5500) + +pci:v000014F1d00008811* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] + +pci:v000014F1d00008811sv00000070sd00003400* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (WinTV 34604) + +pci:v000014F1d00008811sv00000070sd00003401* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (Hauppauge WinTV 34xxx models) + +pci:v000014F1d00008811sv00000070sd00006902* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (WinTV HVR-4000-HD) + +pci:v000014F1d00008811sv00000070sd00009402* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (WinTV-HVR1100 DVB-T/Hybrid) + +pci:v000014F1d00008811sv00000070sd00009600* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (WinTV 88x Audio) + +pci:v000014F1d00008811sv00001462sd00008606* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (MSI TV-@nywhere Master) + +pci:v000014F1d00008811sv000018ACsd0000D500* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (DViCO FusionHDTV5 Gold) + +pci:v000014F1d00008811sv000018ACsd0000D810* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (DViCO FusionHDTV3 Gold-Q) + +pci:v000014F1d00008811sv000018ACsd0000D820* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (DViCO FusionHDTV3 Gold-T) + +pci:v000014F1d00008811sv000018ACsd0000DB00* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (DVICO FusionHDTV DVB-T1) + +pci:v000014F1d00008811sv00005654sd00002388* + ID_MODEL_FROM_DATABASE=CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] (GoTView PCI Hybrid Audio Capture Device) + +pci:v000014F1d00008852* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder + +pci:v000014F1d00008852sv00000070sd00008010* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (WinTV HVR-1400 ExpressCard) + +pci:v000014F1d00008852sv00000070sd0000F038* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (WinTV HVR-5525) + +pci:v000014F1d00008852sv0000107Dsd00006F22* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (WinFast PxTV1200) + +pci:v000014F1d00008852sv000012ABsd0000D585* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (PE988J Hybrid ATSC/QAM PCI-E AVS Video Capture (SoftEncoder)) + +pci:v000014F1d00008852sv000013C2sd00003013* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (TT-budget CT2-4500 CI) + +pci:v000014F1d00008852sv00001461sd0000C039* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (AVerTV Hybrid Express (A577)) + +pci:v000014F1d00008852sv0000153Bsd0000117E* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (Cinergy T PCIe Dual) + +pci:v000014F1d00008852sv000018ACsd0000DB78* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (FusionHDTV DVB-T Dual Express) + +pci:v000014F1d00008852sv00004254sd00000950* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (S950) + +pci:v000014F1d00008852sv00004254sd00000952* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (S952) + +pci:v000014F1d00008852sv00004254sd00000982* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (T982) + +pci:v000014F1d00008852sv00004254sd00009580* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (T9580) + +pci:v000014F1d00008852sv00004254sd0000980C* + ID_MODEL_FROM_DATABASE=CX23885 PCI Video and Audio Decoder (T980C) + +pci:v000014F1d00008880* + ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb + +pci:v000014F1d00008880sv00000070sd00002259* + ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb (WinTV HVR-1250) + +pci:v000014F1d00008880sv00000070sd00006A18* + ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb (WinTV-quadHD) + +pci:v000014F1d00008880sv00000070sd0000C108* + ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb (WinTV-HVR-4400-HD model 1278) + +pci:v000014F1d00008880sv00001461sd00003100* + ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb (CE310B SD PCIe Video Capture Card) + +pci:v000014F1d00008880sv00005654sd00002389* + ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb (GoTView X5 DVD Hybrid PCI-E) + +pci:v000014F1d00008880sv00005654sd00002390* + ID_MODEL_FROM_DATABASE=CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb (GoTView X5 3D HYBRID PCI-E) + +pci:v000014F2* + ID_VENDOR_FROM_DATABASE=MOBILITY Electronics + +pci:v000014F2d00000120* + ID_MODEL_FROM_DATABASE=EV1000 bridge + +pci:v000014F2d00000121* + ID_MODEL_FROM_DATABASE=EV1000 Parallel port + +pci:v000014F2d00000122* + ID_MODEL_FROM_DATABASE=EV1000 Serial port + +pci:v000014F2d00000123* + ID_MODEL_FROM_DATABASE=EV1000 Keyboard controller + +pci:v000014F2d00000124* + ID_MODEL_FROM_DATABASE=EV1000 Mouse controller + +pci:v000014F3* + ID_VENDOR_FROM_DATABASE=BroadLogic + +pci:v000014F3d00002030* + ID_MODEL_FROM_DATABASE=2030 DVB-S Satellite Receiver + +pci:v000014F3d00002035* + ID_MODEL_FROM_DATABASE=2035 DVB-S Satellite Receiver + +pci:v000014F3d00002050* + ID_MODEL_FROM_DATABASE=2050 DVB-T Terrestrial (Cable) Receiver + +pci:v000014F3d00002060* + ID_MODEL_FROM_DATABASE=2060 ATSC Terrestrial (Cable) Receiver + +pci:v000014F4* + ID_VENDOR_FROM_DATABASE=TOKYO Electronic Industry CO Ltd + +pci:v000014F5* + ID_VENDOR_FROM_DATABASE=SOPAC Ltd + +pci:v000014F6* + ID_VENDOR_FROM_DATABASE=COYOTE Technologies LLC + +pci:v000014F7* + ID_VENDOR_FROM_DATABASE=WOLF Technology Inc + +pci:v000014F8* + ID_VENDOR_FROM_DATABASE=AUDIOCODES Inc + +pci:v000014F8d00002077* + ID_MODEL_FROM_DATABASE=TP-240 dual span E1 VoIP PCI card + +pci:v000014F9* + ID_VENDOR_FROM_DATABASE=AG COMMUNICATIONS + +pci:v000014FA* + ID_VENDOR_FROM_DATABASE=WANDEL & GOLTERMANN + +pci:v000014FB* + ID_VENDOR_FROM_DATABASE=TRANSAS MARINE (UK) Ltd + +pci:v000014FC* + ID_VENDOR_FROM_DATABASE=Quadrics Ltd + +pci:v000014FCd00000000* + ID_MODEL_FROM_DATABASE=QsNet Elan3 Network Adapter + +pci:v000014FCd00000001* + ID_MODEL_FROM_DATABASE=QsNetII Elan4 Network Adapter + +pci:v000014FCd00000002* + ID_MODEL_FROM_DATABASE=QsNetIII Elan5 Network Adapter + +pci:v000014FD* + ID_VENDOR_FROM_DATABASE=JAPAN Computer Industry Inc + +pci:v000014FE* + ID_VENDOR_FROM_DATABASE=ARCHTEK TELECOM Corp + +pci:v000014FF* + ID_VENDOR_FROM_DATABASE=TWINHEAD INTERNATIONAL Corp + +pci:v00001500* + ID_VENDOR_FROM_DATABASE=DELTA Electronics, Inc + +pci:v00001500d00001360* + ID_MODEL_FROM_DATABASE=RTL81xx RealTek Ethernet + +pci:v00001501* + ID_VENDOR_FROM_DATABASE=BANKSOFT CANADA Ltd + +pci:v00001502* + ID_VENDOR_FROM_DATABASE=MITSUBISHI ELECTRIC LOGISTICS SUPPORT Co Ltd + +pci:v00001503* + ID_VENDOR_FROM_DATABASE=KAWASAKI LSI USA Inc + +pci:v00001504* + ID_VENDOR_FROM_DATABASE=KAISER Electronics + +pci:v00001505* + ID_VENDOR_FROM_DATABASE=ITA INGENIEURBURO FUR TESTAUFGABEN GmbH + +pci:v00001506* + ID_VENDOR_FROM_DATABASE=CHAMELEON Systems Inc + +pci:v00001507* + ID_VENDOR_FROM_DATABASE=Motorola ?? / HTEC + +pci:v00001507d00000001* + ID_MODEL_FROM_DATABASE=MPC105 [Eagle] + +pci:v00001507d00000002* + ID_MODEL_FROM_DATABASE=MPC106 [Grackle] + +pci:v00001507d00000003* + ID_MODEL_FROM_DATABASE=MPC8240 [Kahlua] + +pci:v00001507d00000100* + ID_MODEL_FROM_DATABASE=MC145575 [HFC-PCI] + +pci:v00001507d00000431* + ID_MODEL_FROM_DATABASE=KTI829c 100VG + +pci:v00001507d00004801* + ID_MODEL_FROM_DATABASE=Raven + +pci:v00001507d00004802* + ID_MODEL_FROM_DATABASE=Falcon + +pci:v00001507d00004803* + ID_MODEL_FROM_DATABASE=Hawk + +pci:v00001507d00004806* + ID_MODEL_FROM_DATABASE=CPX8216 + +pci:v00001508* + ID_VENDOR_FROM_DATABASE=HONDA CONNECTORS/MHOTRONICS Inc + +pci:v00001509* + ID_VENDOR_FROM_DATABASE=FIRST INTERNATIONAL Computer Inc + +pci:v0000150A* + ID_VENDOR_FROM_DATABASE=FORVUS RESEARCH Inc + +pci:v0000150B* + ID_VENDOR_FROM_DATABASE=YAMASHITA Systems Corp + +pci:v0000150C* + ID_VENDOR_FROM_DATABASE=KYOPAL CO Ltd + +pci:v0000150D* + ID_VENDOR_FROM_DATABASE=WARPSPPED Inc + +pci:v0000150E* + ID_VENDOR_FROM_DATABASE=C-PORT Corp + +pci:v0000150F* + ID_VENDOR_FROM_DATABASE=INTEC GmbH + +pci:v00001510* + ID_VENDOR_FROM_DATABASE=BEHAVIOR TECH Computer Corp + +pci:v00001511* + ID_VENDOR_FROM_DATABASE=CENTILLIUM Technology Corp + +pci:v00001512* + ID_VENDOR_FROM_DATABASE=ROSUN Technologies Inc + +pci:v00001513* + ID_VENDOR_FROM_DATABASE=Raychem + +pci:v00001514* + ID_VENDOR_FROM_DATABASE=TFL LAN Inc + +pci:v00001515* + ID_VENDOR_FROM_DATABASE=Advent design + +pci:v00001516* + ID_VENDOR_FROM_DATABASE=MYSON Technology Inc + +pci:v00001516d00000800* + ID_MODEL_FROM_DATABASE=MTD-8xx 100/10M Ethernet PCI Adapter + +pci:v00001516d00000803* + ID_MODEL_FROM_DATABASE=SURECOM EP-320X-S 100/10M Ethernet PCI Adapter + +pci:v00001516d00000803sv00001320sd000010BD* + ID_MODEL_FROM_DATABASE=SURECOM EP-320X-S 100/10M Ethernet PCI Adapter + +pci:v00001516d00000891* + ID_MODEL_FROM_DATABASE=MTD-8xx 100/10M Ethernet PCI Adapter + +pci:v00001517* + ID_VENDOR_FROM_DATABASE=ECHOTEK Corp + +pci:v00001518* + ID_VENDOR_FROM_DATABASE=Kontron + +pci:v00001519* + ID_VENDOR_FROM_DATABASE=TELEFON AKTIEBOLAGET LM Ericsson + +pci:v0000151A* + ID_VENDOR_FROM_DATABASE=Globetek + +pci:v0000151Ad00001002* + ID_MODEL_FROM_DATABASE=PCI-1002 + +pci:v0000151Ad00001004* + ID_MODEL_FROM_DATABASE=PCI-1004 + +pci:v0000151Ad00001008* + ID_MODEL_FROM_DATABASE=PCI-1008 + +pci:v0000151B* + ID_VENDOR_FROM_DATABASE=COMBOX Ltd + +pci:v0000151C* + ID_VENDOR_FROM_DATABASE=DIGITAL AUDIO LABS Inc + +pci:v0000151Cd00000003* + ID_MODEL_FROM_DATABASE=Prodif T 2496 + +pci:v0000151Cd00004000* + ID_MODEL_FROM_DATABASE=Prodif 88 + +pci:v0000151D* + ID_VENDOR_FROM_DATABASE=Fujitsu Computer Products Of America + +pci:v0000151E* + ID_VENDOR_FROM_DATABASE=MATRIX Corp + +pci:v0000151F* + ID_VENDOR_FROM_DATABASE=TOPIC SEMICONDUCTOR Corp + +pci:v0000151Fd00000000* + ID_MODEL_FROM_DATABASE=TP560 Data/Fax/Voice 56k modem + +pci:v00001520* + ID_VENDOR_FROM_DATABASE=CHAPLET System Inc + +pci:v00001521* + ID_VENDOR_FROM_DATABASE=BELL Corp + +pci:v00001522* + ID_VENDOR_FROM_DATABASE=MainPine Ltd + +pci:v00001522d00000100* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge + +pci:v00001522d00000100sv00001522sd00000200* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceDUO 2 Port V.92/V.44 Data/Fax/Voice Modem) + +pci:v00001522d00000100sv00001522sd00000300* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceQUATRO 4 Port V.92/V.44 Data/Fax/Voice Modem) + +pci:v00001522d00000100sv00001522sd00000400* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceDUO+ 2 Port V.92/V.44 Data/Fax/Voice Modem) + +pci:v00001522d00000100sv00001522sd00000500* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceQUATRO+ 4 Port V.92/V.44 Data/Fax/Voice Modem) + +pci:v00001522d00000100sv00001522sd00000600* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce+ 2 Port V.90 Data/Fax/Voice Modem) + +pci:v00001522d00000100sv00001522sd00000700* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForce+ 4 Port V.90 Data/Fax/Voice Modem) + +pci:v00001522d00000100sv00001522sd00000800* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceOCTO+ 8 Port V.92/V.44 Data/Fax/Voice Modem) + +pci:v00001522d00000100sv00001522sd00000C00* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceDUO+ 2 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem) + +pci:v00001522d00000100sv00001522sd00000D00* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceQUATRO+ 4 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem) + +pci:v00001522d00000100sv00001522sd00001D00* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceOCTO+ 8 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem) + +pci:v00001522d00000100sv00001522sd00002000* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceD1 1 Port V.90 Data Modem) + +pci:v00001522d00000100sv00001522sd00002100* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceF1 1 Port V.34 Super-G3 Fax Modem) + +pci:v00001522d00000100sv00001522sd00002200* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceD2 2 Port V.90 Data Modem) + +pci:v00001522d00000100sv00001522sd00002300* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceF2 2 Port V.34 Super-G3 Fax Modem) + +pci:v00001522d00000100sv00001522sd00002400* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceD4 4 Port V.90 Data Modem) + +pci:v00001522d00000100sv00001522sd00002500* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceF4 4 Port V.34 Super-G3 Fax Modem) + +pci:v00001522d00000100sv00001522sd00002600* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceD8 8 Port V.90 Data Modem) + +pci:v00001522d00000100sv00001522sd00002700* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (RockForceF8 8 Port V.34 Super-G3 Fax Modem) + +pci:v00001522d00000100sv00001522sd00003000* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express D1 - 1 Port V.92 Data Modem) + +pci:v00001522d00000100sv00001522sd00003100* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express F1 - 1 Port V.34 Super-G3 Fax Modem) + +pci:v00001522d00000100sv00001522sd00003200* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express D2 - 2 Port V.92 Data Modem) + +pci:v00001522d00000100sv00001522sd00003300* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express F2 - 2 Port V.34 Super-G3 Fax Modem) + +pci:v00001522d00000100sv00001522sd00003400* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express D4 - 4 Port V.92 Data Modem) + +pci:v00001522d00000100sv00001522sd00003500* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express F4 - 4 Port V.34 Super-G3 Fax Modem) + +pci:v00001522d00000100sv00001522sd00003C00* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express D8 - 8 Port V.92 Data Modem) + +pci:v00001522d00000100sv00001522sd00003D00* + ID_MODEL_FROM_DATABASE=PCI <-> IOBus Bridge (IQ Express F8 - 8 Port V.34 Super-G3 Fax Modem) + +pci:v00001522d00004000* + ID_MODEL_FROM_DATABASE=PCI Express UART + +pci:v00001522d00004000sv00001522sd00004001* + ID_MODEL_FROM_DATABASE=PCI Express UART (IQ Express 1-port V.34 Super-G3 Fax) + +pci:v00001522d00004000sv00001522sd00004002* + ID_MODEL_FROM_DATABASE=PCI Express UART (IQ Express 2-port V.34 Super-G3 Fax) + +pci:v00001522d00004000sv00001522sd00004004* + ID_MODEL_FROM_DATABASE=PCI Express UART (IQ Express 4-port V.34 Super-G3 Fax) + +pci:v00001522d00004000sv00001522sd00004008* + ID_MODEL_FROM_DATABASE=PCI Express UART (IQ Express 8-port V.34 Super-G3 Fax) + +pci:v00001522d00004000sv00001522sd00004100* + ID_MODEL_FROM_DATABASE=PCI Express UART (IQ Express SideBand) + +pci:v00001523* + ID_VENDOR_FROM_DATABASE=MUSIC Semiconductors + +pci:v00001524* + ID_VENDOR_FROM_DATABASE=ENE Technology Inc + +pci:v00001524d00000510* + ID_MODEL_FROM_DATABASE=CB710 Memory Card Reader Controller + +pci:v00001524d00000510sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=CB710 Memory Card Reader Controller (NX9500) + +pci:v00001524d00000520* + ID_MODEL_FROM_DATABASE=FLASH memory: ENE Technology Inc: + +pci:v00001524d00000530* + ID_MODEL_FROM_DATABASE=ENE PCI Memory Stick Card Reader Controller + +pci:v00001524d00000550* + ID_MODEL_FROM_DATABASE=ENE PCI Secure Digital Card Reader Controller + +pci:v00001524d00000551* + ID_MODEL_FROM_DATABASE=SD/MMC Card Reader Controller + +pci:v00001524d00000610* + ID_MODEL_FROM_DATABASE=PCI Smart Card Reader Controller + +pci:v00001524d00000720* + ID_MODEL_FROM_DATABASE=Memory Stick Card Reader Controller + +pci:v00001524d00000730* + ID_MODEL_FROM_DATABASE=ENE PCI Memory Stick Card Reader Controller + +pci:v00001524d00000750* + ID_MODEL_FROM_DATABASE=ENE PCI SmartMedia / xD Card Reader Controller + +pci:v00001524d00000751* + ID_MODEL_FROM_DATABASE=ENE PCI Secure Digital / MMC Card Reader Controller + +pci:v00001524d00001211* + ID_MODEL_FROM_DATABASE=CB1211 Cardbus Controller + +pci:v00001524d00001225* + ID_MODEL_FROM_DATABASE=CB1225 Cardbus Controller + +pci:v00001524d00001410* + ID_MODEL_FROM_DATABASE=CB1410 Cardbus Controller + +pci:v00001524d00001410sv00001025sd0000003C* + ID_MODEL_FROM_DATABASE=CB1410 Cardbus Controller (CL50 motherboard) + +pci:v00001524d00001410sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=CB1410 Cardbus Controller (TravelMate 290) + +pci:v00001524d00001410sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=CB1410 Cardbus Controller (530 Laptop) + +pci:v00001524d00001411* + ID_MODEL_FROM_DATABASE=CB-710/2/4 Cardbus Controller + +pci:v00001524d00001411sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=CB-710/2/4 Cardbus Controller (NX9500) + +pci:v00001524d00001412* + ID_MODEL_FROM_DATABASE=CB-712/4 Cardbus Controller + +pci:v00001524d00001420* + ID_MODEL_FROM_DATABASE=CB1420 Cardbus Controller + +pci:v00001524d00001421* + ID_MODEL_FROM_DATABASE=CB-720/2/4 Cardbus Controller + +pci:v00001524d00001422* + ID_MODEL_FROM_DATABASE=CB-722/4 Cardbus Controller + +pci:v00001525* + ID_VENDOR_FROM_DATABASE=IMPACT Technologies + +pci:v00001526* + ID_VENDOR_FROM_DATABASE=ISS, Inc + +pci:v00001527* + ID_VENDOR_FROM_DATABASE=SOLECTRON + +pci:v00001528* + ID_VENDOR_FROM_DATABASE=ACKSYS + +pci:v00001529* + ID_VENDOR_FROM_DATABASE=AMERICAN MICROSystems Inc + +pci:v0000152A* + ID_VENDOR_FROM_DATABASE=QUICKTURN DESIGN Systems + +pci:v0000152B* + ID_VENDOR_FROM_DATABASE=FLYTECH Technology CO Ltd + +pci:v0000152C* + ID_VENDOR_FROM_DATABASE=MACRAIGOR Systems LLC + +pci:v0000152D* + ID_VENDOR_FROM_DATABASE=QUANTA Computer Inc + +pci:v0000152E* + ID_VENDOR_FROM_DATABASE=MELEC Inc + +pci:v0000152F* + ID_VENDOR_FROM_DATABASE=PHILIPS - CRYPTO + +pci:v00001530* + ID_VENDOR_FROM_DATABASE=ACQIS Technology Inc + +pci:v00001531* + ID_VENDOR_FROM_DATABASE=CHRYON Corp + +pci:v00001532* + ID_VENDOR_FROM_DATABASE=ECHELON Corp + +pci:v00001532d00000020* + ID_MODEL_FROM_DATABASE=LonWorks PCLTA-20 PCI LonTalk Adapter + +pci:v00001533* + ID_VENDOR_FROM_DATABASE=BALTIMORE + +pci:v00001534* + ID_VENDOR_FROM_DATABASE=ROAD Corp + +pci:v00001535* + ID_VENDOR_FROM_DATABASE=EVERGREEN Technologies Inc + +pci:v00001536* + ID_VENDOR_FROM_DATABASE=ACTIS Computer + +pci:v00001537* + ID_VENDOR_FROM_DATABASE=DATALEX COMMUNCATIONS + +pci:v00001538* + ID_VENDOR_FROM_DATABASE=ARALION Inc + +pci:v00001538d00000303* + ID_MODEL_FROM_DATABASE=ARS106S Ultra ATA 133/100/66 Host Controller + +pci:v00001539* + ID_VENDOR_FROM_DATABASE=ATELIER INFORMATIQUES et ELECTRONIQUE ETUDES S.A. + +pci:v0000153A* + ID_VENDOR_FROM_DATABASE=ONO SOKKI + +pci:v0000153B* + ID_VENDOR_FROM_DATABASE=TERRATEC Electronic GmbH + +pci:v0000153Bd00001144* + ID_MODEL_FROM_DATABASE=Aureon 5.1 + +pci:v0000153Bd00001147* + ID_MODEL_FROM_DATABASE=Aureon 5.1 Sky + +pci:v0000153Bd00001158* + ID_MODEL_FROM_DATABASE=Philips Semiconductors SAA7134 (rev 01) [Terratec Cinergy 600 TV] + +pci:v0000153C* + ID_VENDOR_FROM_DATABASE=ANTAL Electronic + +pci:v0000153D* + ID_VENDOR_FROM_DATABASE=FILANET Corp + +pci:v0000153E* + ID_VENDOR_FROM_DATABASE=TECHWELL Inc + +pci:v0000153F* + ID_VENDOR_FROM_DATABASE=MIPS Technologies, Inc. + +pci:v0000153Fd00000001* + ID_MODEL_FROM_DATABASE=SOC-it 101 System Controller + +pci:v00001540* + ID_VENDOR_FROM_DATABASE=PROVIDEO MULTIMEDIA Co Ltd + +pci:v00001541* + ID_VENDOR_FROM_DATABASE=MACHONE Communications + +pci:v00001542* + ID_VENDOR_FROM_DATABASE=Concurrent Real-Time + +pci:v00001542d00009260* + ID_MODEL_FROM_DATABASE=RCIM-II Real-Time Clock & Interrupt Module + +pci:v00001542d00009271* + ID_MODEL_FROM_DATABASE=RCIM-III Real-Time Clock & Interrupt Module (PCIe) + +pci:v00001542d00009272* + ID_MODEL_FROM_DATABASE=Pulse Width Modulator Card + +pci:v00001542d00009277* + ID_MODEL_FROM_DATABASE=5 Volt Delta Sigma Converter Card + +pci:v00001542d00009278* + ID_MODEL_FROM_DATABASE=10 Volt Delta Sigma Converter Card + +pci:v00001542d00009287* + ID_MODEL_FROM_DATABASE=Analog Output Card + +pci:v00001542d00009290* + ID_MODEL_FROM_DATABASE=FPGA Card + +pci:v00001542d00009300* + ID_MODEL_FROM_DATABASE=Universal Exhaust Gas Oxygen Sensor Simulator + +pci:v00001542d00009310* + ID_MODEL_FROM_DATABASE=Digital Programmable Resistor + +pci:v00001542d00009350* + ID_MODEL_FROM_DATABASE=Analog Input Card + +pci:v00001543* + ID_VENDOR_FROM_DATABASE=SILICON Laboratories + +pci:v00001543d00003052* + ID_MODEL_FROM_DATABASE=Intel 537 [Winmodem] + +pci:v00001543d00004C22* + ID_MODEL_FROM_DATABASE=Si3036 MC'97 DAA + +pci:v00001544* + ID_VENDOR_FROM_DATABASE=DCM DATA Systems + +pci:v00001545* + ID_VENDOR_FROM_DATABASE=VISIONTEK + +pci:v00001546* + ID_VENDOR_FROM_DATABASE=IOI Technology Corp + +pci:v00001547* + ID_VENDOR_FROM_DATABASE=MITUTOYO Corp + +pci:v00001548* + ID_VENDOR_FROM_DATABASE=JET PROPULSION Laboratory + +pci:v00001549* + ID_VENDOR_FROM_DATABASE=INTERCONNECT Systems Solutions + +pci:v0000154A* + ID_VENDOR_FROM_DATABASE=MAX Technologies Inc + +pci:v0000154B* + ID_VENDOR_FROM_DATABASE=COMPUTEX Co Ltd + +pci:v0000154C* + ID_VENDOR_FROM_DATABASE=VISUAL Technology Inc + +pci:v0000154D* + ID_VENDOR_FROM_DATABASE=PAN INTERNATIONAL Industrial Corp + +pci:v0000154E* + ID_VENDOR_FROM_DATABASE=SERVOTEST Ltd + +pci:v0000154F* + ID_VENDOR_FROM_DATABASE=STRATABEAM Technology + +pci:v00001550* + ID_VENDOR_FROM_DATABASE=OPEN NETWORK Co Ltd + +pci:v00001551* + ID_VENDOR_FROM_DATABASE=SMART Electronic DEVELOPMENT GmBH + +pci:v00001552* + ID_VENDOR_FROM_DATABASE=RACAL AIRTECH Ltd + +pci:v00001553* + ID_VENDOR_FROM_DATABASE=CHICONY Electronics Co Ltd + +pci:v00001554* + ID_VENDOR_FROM_DATABASE=PROLINK Microsystems Corp + +pci:v00001555* + ID_VENDOR_FROM_DATABASE=GESYTEC GmBH + +pci:v00001556* + ID_VENDOR_FROM_DATABASE=PLDA + +pci:v00001556d00001100* + ID_MODEL_FROM_DATABASE=PCI Express Core Reference Design + +pci:v00001556d0000110F* + ID_MODEL_FROM_DATABASE=PCI Express Core Reference Design Virtual Function + +pci:v00001556d00001110* + ID_MODEL_FROM_DATABASE=XpressRich Reference Design + +pci:v00001556d00001113* + ID_MODEL_FROM_DATABASE=XpressSwitch + +pci:v00001556d0000BE00* + ID_MODEL_FROM_DATABASE=PCI Express Bridge + +pci:v00001557* + ID_VENDOR_FROM_DATABASE=MEDIASTAR Co Ltd + +pci:v00001558* + ID_VENDOR_FROM_DATABASE=CLEVO/KAPOK Computer + +pci:v00001559* + ID_VENDOR_FROM_DATABASE=SI LOGIC Ltd + +pci:v0000155A* + ID_VENDOR_FROM_DATABASE=INNOMEDIA Inc + +pci:v0000155B* + ID_VENDOR_FROM_DATABASE=PROTAC INTERNATIONAL Corp + +pci:v0000155C* + ID_VENDOR_FROM_DATABASE=Cemax-Icon Inc + +pci:v0000155D* + ID_VENDOR_FROM_DATABASE=Mac System Co Ltd + +pci:v0000155E* + ID_VENDOR_FROM_DATABASE=LP Elektronik GmbH + +pci:v0000155F* + ID_VENDOR_FROM_DATABASE=Perle Systems Ltd + +pci:v00001560* + ID_VENDOR_FROM_DATABASE=Terayon Communications Systems + +pci:v00001561* + ID_VENDOR_FROM_DATABASE=Viewgraphics Inc + +pci:v00001562* + ID_VENDOR_FROM_DATABASE=Symbol Technologies + +pci:v00001563* + ID_VENDOR_FROM_DATABASE=A-Trend Technology Co Ltd + +pci:v00001564* + ID_VENDOR_FROM_DATABASE=Yamakatsu Electronics Industry Co Ltd + +pci:v00001565* + ID_VENDOR_FROM_DATABASE=Biostar Microtech Int'l Corp + +pci:v00001566* + ID_VENDOR_FROM_DATABASE=Ardent Technologies Inc + +pci:v00001567* + ID_VENDOR_FROM_DATABASE=Jungsoft + +pci:v00001568* + ID_VENDOR_FROM_DATABASE=DDK Electronics Inc + +pci:v00001569* + ID_VENDOR_FROM_DATABASE=Palit Microsystems Inc. + +pci:v0000156A* + ID_VENDOR_FROM_DATABASE=Avtec Systems + +pci:v0000156B* + ID_VENDOR_FROM_DATABASE=2wire Inc + +pci:v0000156C* + ID_VENDOR_FROM_DATABASE=Vidac Electronics GmbH + +pci:v0000156D* + ID_VENDOR_FROM_DATABASE=Alpha-Top Corp + +pci:v0000156E* + ID_VENDOR_FROM_DATABASE=Alfa Inc + +pci:v0000156F* + ID_VENDOR_FROM_DATABASE=M-Systems Flash Disk Pioneers Ltd + +pci:v00001570* + ID_VENDOR_FROM_DATABASE=Lecroy Corp + +pci:v00001571* + ID_VENDOR_FROM_DATABASE=Contemporary Controls + +pci:v00001571d0000A001* + ID_MODEL_FROM_DATABASE=CCSI PCI20-485 ARCnet + +pci:v00001571d0000A002* + ID_MODEL_FROM_DATABASE=CCSI PCI20-485D ARCnet + +pci:v00001571d0000A003* + ID_MODEL_FROM_DATABASE=CCSI PCI20-485X ARCnet + +pci:v00001571d0000A004* + ID_MODEL_FROM_DATABASE=CCSI PCI20-CXB ARCnet + +pci:v00001571d0000A005* + ID_MODEL_FROM_DATABASE=CCSI PCI20-CXS ARCnet + +pci:v00001571d0000A006* + ID_MODEL_FROM_DATABASE=CCSI PCI20-FOG-SMA ARCnet + +pci:v00001571d0000A007* + ID_MODEL_FROM_DATABASE=CCSI PCI20-FOG-ST ARCnet + +pci:v00001571d0000A008* + ID_MODEL_FROM_DATABASE=CCSI PCI20-TB5 ARCnet + +pci:v00001571d0000A009* + ID_MODEL_FROM_DATABASE=CCSI PCI20-5-485 5Mbit ARCnet + +pci:v00001571d0000A00A* + ID_MODEL_FROM_DATABASE=CCSI PCI20-5-485D 5Mbit ARCnet + +pci:v00001571d0000A00B* + ID_MODEL_FROM_DATABASE=CCSI PCI20-5-485X 5Mbit ARCnet + +pci:v00001571d0000A00C* + ID_MODEL_FROM_DATABASE=CCSI PCI20-5-FOG-ST 5Mbit ARCnet + +pci:v00001571d0000A00D* + ID_MODEL_FROM_DATABASE=CCSI PCI20-5-FOG-SMA 5Mbit ARCnet + +pci:v00001571d0000A201* + ID_MODEL_FROM_DATABASE=CCSI PCI22-485 10Mbit ARCnet + +pci:v00001571d0000A202* + ID_MODEL_FROM_DATABASE=CCSI PCI22-485D 10Mbit ARCnet + +pci:v00001571d0000A203* + ID_MODEL_FROM_DATABASE=CCSI PCI22-485X 10Mbit ARCnet + +pci:v00001571d0000A204* + ID_MODEL_FROM_DATABASE=CCSI PCI22-CHB 10Mbit ARCnet + +pci:v00001571d0000A205* + ID_MODEL_FROM_DATABASE=CCSI PCI22-FOG_ST 10Mbit ARCnet + +pci:v00001571d0000A206* + ID_MODEL_FROM_DATABASE=CCSI PCI22-THB 10Mbit ARCnet + +pci:v00001572* + ID_VENDOR_FROM_DATABASE=Otis Elevator Company + +pci:v00001573* + ID_VENDOR_FROM_DATABASE=Lattice - Vantis + +pci:v00001574* + ID_VENDOR_FROM_DATABASE=Fairchild Semiconductor + +pci:v00001575* + ID_VENDOR_FROM_DATABASE=Voltaire Advanced Data Security Ltd + +pci:v00001576* + ID_VENDOR_FROM_DATABASE=Viewcast COM + +pci:v00001578* + ID_VENDOR_FROM_DATABASE=HITT + +pci:v00001578d00004D34* + ID_MODEL_FROM_DATABASE=VPMK4 [Video Processor Mk IV] + +pci:v00001578d00005615* + ID_MODEL_FROM_DATABASE=VPMK3 [Video Processor Mk III] + +pci:v00001579* + ID_VENDOR_FROM_DATABASE=Dual Technology Corp + +pci:v0000157A* + ID_VENDOR_FROM_DATABASE=Japan Elecronics Ind Inc + +pci:v0000157B* + ID_VENDOR_FROM_DATABASE=Star Multimedia Corp + +pci:v0000157C* + ID_VENDOR_FROM_DATABASE=Eurosoft (UK) + +pci:v0000157Cd00008001* + ID_MODEL_FROM_DATABASE=Fix2000 PCI Y2K Compliance Card + +pci:v0000157D* + ID_VENDOR_FROM_DATABASE=Gemflex Networks + +pci:v0000157E* + ID_VENDOR_FROM_DATABASE=Transition Networks + +pci:v0000157F* + ID_VENDOR_FROM_DATABASE=PX Instruments Technology Ltd + +pci:v00001580* + ID_VENDOR_FROM_DATABASE=Primex Aerospace Co + +pci:v00001581* + ID_VENDOR_FROM_DATABASE=SEH Computertechnik GmbH + +pci:v00001582* + ID_VENDOR_FROM_DATABASE=Cytec Corp + +pci:v00001583* + ID_VENDOR_FROM_DATABASE=Inet Technologies Inc + +pci:v00001584* + ID_VENDOR_FROM_DATABASE=Uniwill Computer Corp + +pci:v00001585* + ID_VENDOR_FROM_DATABASE=Logitron + +pci:v00001586* + ID_VENDOR_FROM_DATABASE=Lancast Inc + +pci:v00001587* + ID_VENDOR_FROM_DATABASE=Konica Corp + +pci:v00001588* + ID_VENDOR_FROM_DATABASE=Solidum Systems Corp + +pci:v00001589* + ID_VENDOR_FROM_DATABASE=Atlantek Microsystems Pty Ltd + +pci:v00001589d00000008* + ID_MODEL_FROM_DATABASE=Leutron Vision PicPortExpress CL + +pci:v00001589d00000009* + ID_MODEL_FROM_DATABASE=Leutron Vision PicPortExpress CL Stereo + +pci:v0000158A* + ID_VENDOR_FROM_DATABASE=Digalog Systems Inc + +pci:v0000158B* + ID_VENDOR_FROM_DATABASE=Allied Data Technologies + +pci:v0000158C* + ID_VENDOR_FROM_DATABASE=Hitachi Semiconductor & Devices Sales Co Ltd + +pci:v0000158D* + ID_VENDOR_FROM_DATABASE=Point Multimedia Systems + +pci:v0000158E* + ID_VENDOR_FROM_DATABASE=Lara Technology Inc + +pci:v0000158F* + ID_VENDOR_FROM_DATABASE=Ditect Coop + +pci:v00001590* + ID_VENDOR_FROM_DATABASE=Hewlett Packard Enterprise + +pci:v00001590d00000001* + ID_MODEL_FROM_DATABASE=Eagle Cluster Manager + +pci:v00001590d00000002* + ID_MODEL_FROM_DATABASE=Osprey Cluster Manager + +pci:v00001590d00000003* + ID_MODEL_FROM_DATABASE=Harrier Cluster Manager + +pci:v00001590d0000A01D* + ID_MODEL_FROM_DATABASE=FC044X Fibre Channel HBA + +pci:v00001591* + ID_VENDOR_FROM_DATABASE=ARN + +pci:v00001592* + ID_VENDOR_FROM_DATABASE=Syba Tech Ltd + +pci:v00001592d00000781* + ID_MODEL_FROM_DATABASE=Multi-IO Card + +pci:v00001592d00000782* + ID_MODEL_FROM_DATABASE=Parallel Port Card 2xEPP + +pci:v00001592d00000783* + ID_MODEL_FROM_DATABASE=Multi-IO Card + +pci:v00001592d00000785* + ID_MODEL_FROM_DATABASE=Multi-IO Card + +pci:v00001592d00000786* + ID_MODEL_FROM_DATABASE=Multi-IO Card + +pci:v00001592d00000787* + ID_MODEL_FROM_DATABASE=Multi-IO Card + +pci:v00001592d00000788* + ID_MODEL_FROM_DATABASE=Multi-IO Card + +pci:v00001592d0000078A* + ID_MODEL_FROM_DATABASE=Multi-IO Card + +pci:v00001593* + ID_VENDOR_FROM_DATABASE=Bops Inc + +pci:v00001594* + ID_VENDOR_FROM_DATABASE=Netgame Ltd + +pci:v00001595* + ID_VENDOR_FROM_DATABASE=Diva Systems Corp + +pci:v00001596* + ID_VENDOR_FROM_DATABASE=Folsom Research Inc + +pci:v00001597* + ID_VENDOR_FROM_DATABASE=Memec Design Services + +pci:v00001598* + ID_VENDOR_FROM_DATABASE=Granite Microsystems + +pci:v00001599* + ID_VENDOR_FROM_DATABASE=Delta Electronics Inc + +pci:v0000159A* + ID_VENDOR_FROM_DATABASE=General Instrument + +pci:v0000159B* + ID_VENDOR_FROM_DATABASE=Faraday Technology Corp + +pci:v0000159Bd00004321* + ID_MODEL_FROM_DATABASE=StorLink SL3516 (Gemini) Host Bridge + +pci:v0000159C* + ID_VENDOR_FROM_DATABASE=Stratus Computer Systems + +pci:v0000159D* + ID_VENDOR_FROM_DATABASE=Ningbo Harrison Electronics Co Ltd + +pci:v0000159E* + ID_VENDOR_FROM_DATABASE=A-Max Technology Co Ltd + +pci:v0000159F* + ID_VENDOR_FROM_DATABASE=Galea Network Security + +pci:v000015A0* + ID_VENDOR_FROM_DATABASE=Compumaster SRL + +pci:v000015A1* + ID_VENDOR_FROM_DATABASE=Geocast Network Systems + +pci:v000015A2* + ID_VENDOR_FROM_DATABASE=Catalyst Enterprises Inc + +pci:v000015A2d00000001* + ID_MODEL_FROM_DATABASE=TA700 PCI Bus Analyzer/Exerciser + +pci:v000015A3* + ID_VENDOR_FROM_DATABASE=Italtel + +pci:v000015A4* + ID_VENDOR_FROM_DATABASE=X-Net OY + +pci:v000015A5* + ID_VENDOR_FROM_DATABASE=Toyota Macs Inc + +pci:v000015A6* + ID_VENDOR_FROM_DATABASE=Sunlight Ultrasound Technologies Ltd + +pci:v000015A7* + ID_VENDOR_FROM_DATABASE=SSE Telecom Inc + +pci:v000015A8* + ID_VENDOR_FROM_DATABASE=Shanghai Communications Technologies Center + +pci:v000015AA* + ID_VENDOR_FROM_DATABASE=Moreton Bay + +pci:v000015AB* + ID_VENDOR_FROM_DATABASE=Bluesteel Networks Inc + +pci:v000015AC* + ID_VENDOR_FROM_DATABASE=North Atlantic Instruments + +pci:v000015ACd00006893* + ID_MODEL_FROM_DATABASE=3U OpenVPX Multi-function I/O Board [Model 68C3] + +pci:v000015AD* + ID_VENDOR_FROM_DATABASE=VMware + +pci:v000015ADd00000405* + ID_MODEL_FROM_DATABASE=SVGA II Adapter + +pci:v000015ADd00000710* + ID_MODEL_FROM_DATABASE=SVGA Adapter + +pci:v000015ADd00000720* + ID_MODEL_FROM_DATABASE=VMXNET Ethernet Controller + +pci:v000015ADd00000740* + ID_MODEL_FROM_DATABASE=Virtual Machine Communication Interface + +pci:v000015ADd00000770* + ID_MODEL_FROM_DATABASE=USB2 EHCI Controller + +pci:v000015ADd00000774* + ID_MODEL_FROM_DATABASE=USB1.1 UHCI Controller + +pci:v000015ADd00000778* + ID_MODEL_FROM_DATABASE=USB3 xHCI 0.96 Controller + +pci:v000015ADd00000779* + ID_MODEL_FROM_DATABASE=USB3 xHCI 1.0 Controller + +pci:v000015ADd00000790* + ID_MODEL_FROM_DATABASE=PCI bridge + +pci:v000015ADd000007A0* + ID_MODEL_FROM_DATABASE=PCI Express Root Port + +pci:v000015ADd000007B0* + ID_MODEL_FROM_DATABASE=VMXNET3 Ethernet Controller + +pci:v000015ADd000007C0* + ID_MODEL_FROM_DATABASE=PVSCSI SCSI Controller + +pci:v000015ADd000007E0* + ID_MODEL_FROM_DATABASE=SATA AHCI controller + +pci:v000015ADd00000801* + ID_MODEL_FROM_DATABASE=Virtual Machine Interface + +pci:v000015ADd00000801sv000015ADsd00000800* + ID_MODEL_FROM_DATABASE=Virtual Machine Interface (Hypervisor ROM Interface) + +pci:v000015ADd00000820* + ID_MODEL_FROM_DATABASE=Paravirtual RDMA controller + +pci:v000015ADd00001977* + ID_MODEL_FROM_DATABASE=HD Audio Controller + +pci:v000015AE* + ID_VENDOR_FROM_DATABASE=Amersham Pharmacia Biotech + +pci:v000015B0* + ID_VENDOR_FROM_DATABASE=Zoltrix International Ltd + +pci:v000015B1* + ID_VENDOR_FROM_DATABASE=Source Technology Inc + +pci:v000015B2* + ID_VENDOR_FROM_DATABASE=Mosaid Technologies Inc + +pci:v000015B3* + ID_VENDOR_FROM_DATABASE=Mellanox Technologies + +pci:v000015B3d00000191* + ID_MODEL_FROM_DATABASE=MT25408 [ConnectX IB Flash Recovery] + +pci:v000015B3d000001F6* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3 Flash Recovery] + +pci:v000015B3d000001F8* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro Flash Recovery] + +pci:v000015B3d000001FF* + ID_MODEL_FROM_DATABASE=MT27600 Family [Connect-IB Flash Recovery] + +pci:v000015B3d00000209* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4 Flash Recovery] + +pci:v000015B3d0000020B* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx Flash Recovery] + +pci:v000015B3d0000020D* + ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Flash Recovery] + +pci:v000015B3d0000020F* + ID_MODEL_FROM_DATABASE=MT28908A0 Family [ConnectX-6 Flash Recovery] + +pci:v000015B3d00000210* + ID_MODEL_FROM_DATABASE=MT28908A0 Family [ConnectX-6 Secure Flash Recovery] + +pci:v000015B3d00000211* + ID_MODEL_FROM_DATABASE=MT416842 Family [BlueField SoC Flash Recovery] + +pci:v000015B3d00000212* + ID_MODEL_FROM_DATABASE=MT2892 Family [ConnectX-6 Dx Flash Recovery] + +pci:v000015B3d00000213* + ID_MODEL_FROM_DATABASE=MT2892 Family [ConnectX-6 Dx Secure Flash Recovery] + +pci:v000015B3d00000214* + ID_MODEL_FROM_DATABASE=MT42822 Family [BlueField-2 SoC Flash Recovery] + +pci:v000015B3d00000215* + ID_MODEL_FROM_DATABASE=MT42822 Family [BlueField-2 Secure Flash Recovery] + +pci:v000015B3d00000216* + ID_MODEL_FROM_DATABASE=MT2894 Family [ConnectX-6 Lx Flash Recovery] + +pci:v000015B3d00000217* + ID_MODEL_FROM_DATABASE=MT2894 Family [ConnectX-6 Lx Secure Flash Recovery] + +pci:v000015B3d0000024E* + ID_MODEL_FROM_DATABASE=MT53100 [Spectrum-2, Flash recovery mode] + +pci:v000015B3d0000024F* + ID_MODEL_FROM_DATABASE=MT53100 [Spectrum-2, Secure Flash recovery mode] + +pci:v000015B3d00000250* + ID_MODEL_FROM_DATABASE=Spectrum-3, Flash recovery mode + +pci:v000015B3d00000251* + ID_MODEL_FROM_DATABASE=Spectrum-3, Secure Flash recovery mode + +pci:v000015B3d00000252* + ID_MODEL_FROM_DATABASE=Amos chiplet + +pci:v000015B3d00000254* + ID_MODEL_FROM_DATABASE=Spectrum-4, Flash recovery mode + +pci:v000015B3d00000255* + ID_MODEL_FROM_DATABASE=Spectrum-4, Secure Flash recovery mode + +pci:v000015B3d00000256* + ID_MODEL_FROM_DATABASE=Ofek chiplet + +pci:v000015B3d00000257* + ID_MODEL_FROM_DATABASE=Quantum-2 in Flash Recovery Mode + +pci:v000015B3d00000262* + ID_MODEL_FROM_DATABASE=MT27710 [ConnectX-4 Lx Programmable] EN + +pci:v000015B3d00000263* + ID_MODEL_FROM_DATABASE=MT27710 [ConnectX-4 Lx Programmable Virtual Function] EN + +pci:v000015B3d00000264* + ID_MODEL_FROM_DATABASE=Innova-2 Flex Burn image + +pci:v000015B3d00000281* + ID_MODEL_FROM_DATABASE=NPS-600 Flash Recovery + +pci:v000015B3d00000538* + ID_MODEL_FROM_DATABASE=MT2910 Family [ConnectX-7 Flash Recovery] + +pci:v000015B3d00000539* + ID_MODEL_FROM_DATABASE=MT2910 Family [ConnectX-7 Secure Flash Recovery] + +pci:v000015B3d00001002* + ID_MODEL_FROM_DATABASE=MT25400 Family [ConnectX-2 Virtual Function] + +pci:v000015B3d00001003* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] + +pci:v000015B3d00001003sv00001014sd000004B5* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (PCIe3 40GbE RoCE Converged Host Bus Adapter for Power) + +pci:v000015B3d00001003sv0000103Csd00001777* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (InfiniBand FDR/EN 10/40Gb Dual Port 544FLR-QSFP Adapter (Rev Cx)) + +pci:v000015B3d00001003sv0000103Csd000017C9* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (Infiniband QDR/Ethernet 10Gb 2-port 544i Adapter) + +pci:v000015B3d00001003sv0000103Csd000018CE* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (InfiniBand QDR/EN 10Gb Dual Port 544M Adapter) + +pci:v000015B3d00001003sv0000103Csd000018CF* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (InfiniBand FDR/EN 10/40Gb Dual Port 544M Adapter) + +pci:v000015B3d00001003sv0000103Csd000018D6* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (InfiniBand FDR/EN 10/40Gb Dual Port 544QSFP Adapter) + +pci:v000015B3d00001003sv000015B3sd00000025* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 IB QDR Dual Port Mezzanine Card) + +pci:v000015B3d00001003sv000015B3sd00000026* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 IB FDR Dual Port Mezzanine Card) + +pci:v000015B3d00001003sv000015B3sd00000028* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI Dual QSFP+ Port QDR Infiniband 40Gb/s or 10Gb Ethernet) + +pci:v000015B3d00001003sv000015B3sd00000059* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI IB FDR/40 GbE Single Port QSFP+ Mezzanine Card) + +pci:v000015B3d00001003sv000015B3sd00000064* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 EN 10/40 GbE Single Port QSFP+ Adapter (MCX313A-BCBT)) + +pci:v000015B3d00001003sv000015B3sd00000065* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI IB FDR/40 GbE Dual Port QSFP+ Adapter) + +pci:v000015B3d00001003sv000015B3sd00000066* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 IB FDR10 Dual Port Mezzanine Card) + +pci:v000015B3d00001003sv000015B3sd00000067* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI IB FDR/40 GbE Single Port QSFP+ Adapter) + +pci:v000015B3d00001003sv000015B3sd00000071* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 VPI IB FDR/40 GbE Dual Port QSFP+ Mezzanine Card) + +pci:v000015B3d00001003sv000015B3sd00000078* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 10 GbE Dual Port KR Mezzanine Card) + +pci:v000015B3d00001003sv000015B3sd00000079* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 40 GbE Dual Port QSFP+ Adapter) + +pci:v000015B3d00001003sv000015B3sd00000080* + ID_MODEL_FROM_DATABASE=MT27500 Family [ConnectX-3] (ConnectX-3 10 GbE Dual Port SFP+ Adapter) + +pci:v000015B3d00001004* + ID_MODEL_FROM_DATABASE=MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function] + +pci:v000015B3d00001005* + ID_MODEL_FROM_DATABASE=MT27510 Family + +pci:v000015B3d00001006* + ID_MODEL_FROM_DATABASE=MT27511 Family + +pci:v000015B3d00001007* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] + +pci:v000015B3d00001007sv00001014sd000004EB* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (2-Port 10GbE NIC and RoCE SR PCIe3) + +pci:v000015B3d00001007sv0000103Csd000022F3* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (InfiniBand FDR/Ethernet 10Gb/40Gb 2-port 544+QSFP Adapter) + +pci:v000015B3d00001007sv0000103Csd000022F4* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (InfiniBand FDR/Ethernet 10Gb/40Gb 2-port 544+FLR-QSFP Adapter) + +pci:v000015B3d00001007sv0000103Csd0000801F* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (Ethernet 10G 2-port 546SFP+ Adapter) + +pci:v000015B3d00001007sv0000117Csd00000090* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (FastFrame NQ41) + +pci:v000015B3d00001007sv0000117Csd00000091* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (FastFrame NQ42) + +pci:v000015B3d00001007sv0000117Csd00000092* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (FastFrame NQ11) + +pci:v000015B3d00001007sv0000117Csd00000093* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (FastFrame NQ12) + +pci:v000015B3d00001007sv000015B3sd00000006* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (Mellanox Technologies ConnectX-3 Pro Stand-up dual-port 40GbE MCX314A-BCCT) + +pci:v000015B3d00001007sv000015B3sd00000078* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (ConnectX-3 Pro 10 GbE Dual Port KR Mezzanine Card) + +pci:v000015B3d00001007sv000015B3sd00000079* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (ConnectX-3 Pro 40 GbE Dual Port QSFP+ Adapter) + +pci:v000015B3d00001007sv000015B3sd00000080* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (ConnectX-3 Pro 10 GbE Dual Port SFP+ Adapter) + +pci:v000015B3d00001007sv0000193Dsd00001002* + ID_MODEL_FROM_DATABASE=MT27520 Family [ConnectX-3 Pro] (520F-B) + +pci:v000015B3d00001009* + ID_MODEL_FROM_DATABASE=MT27530 Family + +pci:v000015B3d0000100A* + ID_MODEL_FROM_DATABASE=MT27531 Family + +pci:v000015B3d0000100B* + ID_MODEL_FROM_DATABASE=MT27540 Family + +pci:v000015B3d0000100C* + ID_MODEL_FROM_DATABASE=MT27541 Family + +pci:v000015B3d0000100D* + ID_MODEL_FROM_DATABASE=MT27550 Family + +pci:v000015B3d0000100E* + ID_MODEL_FROM_DATABASE=MT27551 Family + +pci:v000015B3d0000100F* + ID_MODEL_FROM_DATABASE=MT27560 Family + +pci:v000015B3d00001010* + ID_MODEL_FROM_DATABASE=MT27561 Family + +pci:v000015B3d00001011* + ID_MODEL_FROM_DATABASE=MT27600 [Connect-IB] + +pci:v000015B3d00001012* + ID_MODEL_FROM_DATABASE=MT27600 Family [Connect-IB Virtual Function] + +pci:v000015B3d00001013* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] + +pci:v000015B3d00001013sv00001014sd000004F7* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (PCIe3 2-port 100 GbE (NIC and RoCE) QSFP28 Adapter for Power) + +pci:v000015B3d00001013sv000015B3sd00000003* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (Mellanox Technologies ConnectX-4 Stand-up single-port 40GbE MCX413A-BCAT) + +pci:v000015B3d00001013sv000015B3sd00000005* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (Mellanox Technologies ConnectX-4 Stand-up single-port 40GbE MCX415A-BCAT) + +pci:v000015B3d00001013sv000015B3sd00000006* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (MCX416A-BCAT, ConnectX-4 EN, 40/56GbE 2P, PCIe3.0 x16) + +pci:v000015B3d00001013sv000015B3sd00000007* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (ConnectX-4 EN network interface card, 40/56GbE dual-port QSFP28, PCIe3.0 x16, tall bracket) + +pci:v000015B3d00001013sv000015B3sd00000008* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (ConnectX-4 Stand-up dual-port 100GbE MCX416A-CCAT) + +pci:v000015B3d00001013sv000015B3sd00000033* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (ConnectX-4 VPI IB EDR/100 GbE Single Port QSFP28 Adapter) + +pci:v000015B3d00001013sv000015B3sd00000034* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (ConnectX-4 VPI IB EDR/100 GbE Dual Port QSFP28 Adapter) + +pci:v000015B3d00001013sv000015B3sd00000050* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4] (ConnectX-4 100 GbE Dual Port QSFP28 Adapter) + +pci:v000015B3d00001014* + ID_MODEL_FROM_DATABASE=MT27700 Family [ConnectX-4 Virtual Function] + +pci:v000015B3d00001015* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] + +pci:v000015B3d00001015sv000015B3sd00000001* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (ConnectX-4 Lx EN network interface card, 25GbE single-port SFP28, PCIe3.0 x8, tall bracket, ROHS R6) + +pci:v000015B3d00001015sv000015B3sd00000003* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (Stand-up ConnectX-4 Lx EN, 25GbE dual-port SFP28, PCIe3.0 x8, MCX4121A-ACAT) + +pci:v000015B3d00001015sv000015B3sd00000004* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (ConnectX-4 Lx Stand-up dual-port 10GbE MCX4121A-XCAT) + +pci:v000015B3d00001015sv000015B3sd00000005* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (Mellanox Technologies ConnectX-4 Lx Stand-up single-port 40GbE MCX4131A-BCAT) + +pci:v000015B3d00001015sv000015B3sd00000020* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (MCX4411A-ACQN, ConnectX-4 Lx EN OCP, 1x25Gb) + +pci:v000015B3d00001015sv000015B3sd00000021* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (MCX4421A-ACQN ConnectX-4 Lx EN OCP,2x25G) + +pci:v000015B3d00001015sv000015B3sd00000025* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (ConnectX-4 Lx 25 GbE Dual Port SFP28 rNDC) + +pci:v000015B3d00001015sv0000193Dsd0000100A* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx] (620F-B) + +pci:v000015B3d00001016* + ID_MODEL_FROM_DATABASE=MT27710 Family [ConnectX-4 Lx Virtual Function] + +pci:v000015B3d00001017* + ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5] + +pci:v000015B3d00001017sv000015B3sd00000006* + ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5] (ConnectX®-5 EN network interface card, 100GbE single-port QSFP28, PCIe3.0 x16, tall bracket; MCX515A-CCAT) + +pci:v000015B3d00001017sv000015B3sd00000020* + ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5] (ConnectX®-5 EN network interface card, 10/25GbE dual-port SFP28, PCIe3.0 x8, tall bracket ; MCX512A-ACAT) + +pci:v000015B3d00001017sv000015B3sd00000068* + ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5] (ConnectX®-5 EN network interface card for OCP2.0, Type 1, with host management, 25GbE dual-port SFP28, PCIe3.0 x8, no bracket Halogen free ; MCX542B-ACAN) + +pci:v000015B3d00001018* + ID_MODEL_FROM_DATABASE=MT27800 Family [ConnectX-5 Virtual Function] + +pci:v000015B3d00001019* + ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Ex] + +pci:v000015B3d00001019sv000015B3sd00000008* + ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Ex] (ConnectX-5 Ex EN network interface card, 100GbE dual-port QSFP28, PCIe4.0 x16, tall bracket; MCX516A-CDAT) + +pci:v000015B3d0000101A* + ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 Ex Virtual Function] + +pci:v000015B3d0000101B* + ID_MODEL_FROM_DATABASE=MT28908 Family [ConnectX-6] + +pci:v000015B3d0000101C* + ID_MODEL_FROM_DATABASE=MT28908 Family [ConnectX-6 Virtual Function] + +pci:v000015B3d0000101D* + ID_MODEL_FROM_DATABASE=MT2892 Family [ConnectX-6 Dx] + +pci:v000015B3d0000101E* + ID_MODEL_FROM_DATABASE=ConnectX Family mlx5Gen Virtual Function + +pci:v000015B3d0000101F* + ID_MODEL_FROM_DATABASE=MT2894 Family [ConnectX-6 Lx] + +pci:v000015B3d00001020* + ID_MODEL_FROM_DATABASE=MT28860 + +pci:v000015B3d00001021* + ID_MODEL_FROM_DATABASE=MT2910 Family [ConnectX-7] + +pci:v000015B3d00001974* + ID_MODEL_FROM_DATABASE=MT28800 Family [ConnectX-5 PCIe Bridge] + +pci:v000015B3d00001975* + ID_MODEL_FROM_DATABASE=MT416842 Family [BlueField SoC PCIe Bridge] + +pci:v000015B3d00001976* + ID_MODEL_FROM_DATABASE=MT28908 Family [ConnectX-6 PCIe Bridge] + +pci:v000015B3d00001977* + ID_MODEL_FROM_DATABASE=MT2892 Family [ConnectX-6 Dx PCIe Bridge] + +pci:v000015B3d00001978* + ID_MODEL_FROM_DATABASE=MT42822 Family [BlueField-2 SoC PCIe Bridge] + +pci:v000015B3d00004117* + ID_MODEL_FROM_DATABASE=MT27712A0-FDCF-AE + +pci:v000015B3d00004117sv00001BD4sd00000039* + ID_MODEL_FROM_DATABASE=MT27712A0-FDCF-AE (SN10XMP2P25) + +pci:v000015B3d00004117sv00001BD4sd0000004D* + ID_MODEL_FROM_DATABASE=MT27712A0-FDCF-AE (SN10XMP2P25,YZPC-01191-101) + +pci:v000015B3d00005274* + ID_MODEL_FROM_DATABASE=MT21108 InfiniBridge + +pci:v000015B3d00005A44* + ID_MODEL_FROM_DATABASE=MT23108 InfiniHost + +pci:v000015B3d00005A45* + ID_MODEL_FROM_DATABASE=MT23108 [Infinihost HCA Flash Recovery] + +pci:v000015B3d00005A46* + ID_MODEL_FROM_DATABASE=MT23108 PCI Bridge + +pci:v000015B3d00005E8C* + ID_MODEL_FROM_DATABASE=MT24204 [InfiniHost III Lx HCA] + +pci:v000015B3d00005E8D* + ID_MODEL_FROM_DATABASE=MT25204 [InfiniHost III Lx HCA Flash Recovery] + +pci:v000015B3d00006001* + ID_MODEL_FROM_DATABASE=NVMe SNAP Controller + +pci:v000015B3d00006274* + ID_MODEL_FROM_DATABASE=MT25204 [InfiniHost III Lx HCA] + +pci:v000015B3d00006278* + ID_MODEL_FROM_DATABASE=MT25208 InfiniHost III Ex (Tavor compatibility mode) + +pci:v000015B3d00006279* + ID_MODEL_FROM_DATABASE=MT25208 [InfiniHost III Ex HCA Flash Recovery] + +pci:v000015B3d00006282* + ID_MODEL_FROM_DATABASE=MT25208 [InfiniHost III Ex] + +pci:v000015B3d00006340* + ID_MODEL_FROM_DATABASE=MT25408A0-FCC-SI ConnectX, Dual Port 10Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 2.5GT/s Interface + +pci:v000015B3d0000634A* + ID_MODEL_FROM_DATABASE=MT25408A0-FCC-DI ConnectX, Dual Port 20Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 2.5GT/s Interface + +pci:v000015B3d0000634Asv00001014sd00001014* + ID_MODEL_FROM_DATABASE=MT25408A0-FCC-DI ConnectX, Dual Port 20Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 2.5GT/s Interface (4X InfiniBand DDR Expansion Card (CFFh) for IBM BladeCenter) + +pci:v000015B3d00006368* + ID_MODEL_FROM_DATABASE=MT25448 [ConnectX EN 10GigE, PCIe 2.0 2.5GT/s] + +pci:v000015B3d00006372* + ID_MODEL_FROM_DATABASE=MT25458 ConnectX EN 10GBASE-T PCIe 2.5 GT/s + +pci:v000015B3d00006732* + ID_MODEL_FROM_DATABASE=MT25408A0-FCC-GI ConnectX, Dual Port 20Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface + +pci:v000015B3d0000673C* + ID_MODEL_FROM_DATABASE=MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface + +pci:v000015B3d0000673Csv00001014sd00000415* + ID_MODEL_FROM_DATABASE=MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface (PCIe2 2-port 4X InfiniBand QDR Adapter for Power) + +pci:v000015B3d0000673Csv00001014sd00000487* + ID_MODEL_FROM_DATABASE=MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface (GX++ 1-port 4X IB QDR Adapter for Power 795) + +pci:v000015B3d0000673Csv0000103Csd00001782* + ID_MODEL_FROM_DATABASE=MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface (4X QDR InfiniBand Mezzanine HCA for c-Class BladeSystem) + +pci:v000015B3d0000673Csv000015B3sd00000021* + ID_MODEL_FROM_DATABASE=MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface (HP InfiniBand 4X QDR CX-2 PCI-e G2 Dual Port HCA) + +pci:v000015B3d00006746* + ID_MODEL_FROM_DATABASE=MT26438 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virtualization+] + +pci:v000015B3d00006746sv0000103Csd00001781* + ID_MODEL_FROM_DATABASE=MT26438 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virtualization+] (NC543i 1-port 4x QDR IB/Flex-10 10Gb Adapter) + +pci:v000015B3d00006746sv0000103Csd00003349* + ID_MODEL_FROM_DATABASE=MT26438 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virtualization+] (NC543i 2-port 4xQDR IB/10Gb Adapter) + +pci:v000015B3d00006750* + ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] + +pci:v000015B3d00006750sv00001014sd00000416* + ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (PCIe2 2-Port 10GbE RoCE SFP+ Adapter) + +pci:v000015B3d00006750sv00001014sd00000461* + ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (PCIe2 2-Port 10GbE RoCE SR Adapter) + +pci:v000015B3d00006750sv000015B3sd00000018* + ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (HP 10 GbE PCI-e G2 Dual-Port NIC (rev C1)) + +pci:v000015B3d00006750sv000015B3sd00006572* + ID_MODEL_FROM_DATABASE=MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] (IBM Flex System EN4132 2-port 10Gb RoCE Adapter) + +pci:v000015B3d0000675A* + ID_MODEL_FROM_DATABASE=MT26458 ConnectX EN 10GBASE-T PCIe Gen2 5.0 GT/s + +pci:v000015B3d00006764* + ID_MODEL_FROM_DATABASE=MT26468 [ConnectX EN 10GigE, PCIe 2.0 5GT/s Virtualization+] + +pci:v000015B3d00006764sv0000103Csd00003313* + ID_MODEL_FROM_DATABASE=MT26468 [ConnectX EN 10GigE, PCIe 2.0 5GT/s Virtualization+] (NC542m Dual Port Flex-10 10GbE BLc Adapter) + +pci:v000015B3d0000676E* + ID_MODEL_FROM_DATABASE=MT26478 [ConnectX EN 40GigE, PCIe 2.0 5GT/s] + +pci:v000015B3d00006778* + ID_MODEL_FROM_DATABASE=MT26488 [ConnectX VPI PCIe 2.0 5GT/s - IB DDR / 10GigE Virtualization+] + +pci:v000015B3d00007101* + ID_MODEL_FROM_DATABASE=NPS-400 configuration and management interface + +pci:v000015B3d00007102* + ID_MODEL_FROM_DATABASE=NPS-400 network interface PF + +pci:v000015B3d00007103* + ID_MODEL_FROM_DATABASE=NPS-400 network interface VF + +pci:v000015B3d00007121* + ID_MODEL_FROM_DATABASE=NPS-600 configuration and management interface + +pci:v000015B3d00007122* + ID_MODEL_FROM_DATABASE=NPS-600 network interface PF + +pci:v000015B3d00007123* + ID_MODEL_FROM_DATABASE=NPS-600 network interface VF + +pci:v000015B3d00008200* + ID_MODEL_FROM_DATABASE=Innova-2 Flex Shell Logic + +pci:v000015B3d0000A2D0* + ID_MODEL_FROM_DATABASE=MT416842 BlueField SoC Crypto enabled + +pci:v000015B3d0000A2D1* + ID_MODEL_FROM_DATABASE=MT416842 BlueField SoC Crypto disabled + +pci:v000015B3d0000A2D2* + ID_MODEL_FROM_DATABASE=MT416842 BlueField integrated ConnectX-5 network controller + +pci:v000015B3d0000A2D3* + ID_MODEL_FROM_DATABASE=MT416842 BlueField multicore SoC family VF + +pci:v000015B3d0000A2D4* + ID_MODEL_FROM_DATABASE=MT42822 BlueField-2 SoC Crypto enabled + +pci:v000015B3d0000A2D5* + ID_MODEL_FROM_DATABASE=MT42822 BlueField-2 SoC Crypto disabled + +pci:v000015B3d0000A2D6* + ID_MODEL_FROM_DATABASE=MT42822 BlueField-2 integrated ConnectX-6 Dx network controller + +pci:v000015B3d0000C2D2* + ID_MODEL_FROM_DATABASE=MT416842 BlueField SoC management interfac + +pci:v000015B3d0000C2D3* + ID_MODEL_FROM_DATABASE=MT42822 BlueField-2 SoC Management Interface + +pci:v000015B3d0000C738* + ID_MODEL_FROM_DATABASE=MT51136 + +pci:v000015B3d0000C739* + ID_MODEL_FROM_DATABASE=MT51136 GW + +pci:v000015B3d0000C838* + ID_MODEL_FROM_DATABASE=MT52236 + +pci:v000015B3d0000C839* + ID_MODEL_FROM_DATABASE=MT52236 router + +pci:v000015B3d0000CAF1* + ID_MODEL_FROM_DATABASE=ConnectX-4 CAPI Function + +pci:v000015B3d0000CB84* + ID_MODEL_FROM_DATABASE=MT52100 + +pci:v000015B3d0000CF08* + ID_MODEL_FROM_DATABASE=Switch-IB2 + +pci:v000015B3d0000CF6C* + ID_MODEL_FROM_DATABASE=MT53100 [Spectrum-2] + +pci:v000015B3d0000CF70* + ID_MODEL_FROM_DATABASE=Spectrum-3 + +pci:v000015B3d0000CF80* + ID_MODEL_FROM_DATABASE=Spectrum-4 + +pci:v000015B3d0000D2F0* + ID_MODEL_FROM_DATABASE=Quantum HDR (200Gbps) switch + +pci:v000015B3d0000D2F2* + ID_MODEL_FROM_DATABASE=Quantum-2 NDR (400Gbps) switch + +pci:v000015B4* + ID_VENDOR_FROM_DATABASE=CCI/TRIAD + +pci:v000015B5* + ID_VENDOR_FROM_DATABASE=Cimetrics Inc + +pci:v000015B6* + ID_VENDOR_FROM_DATABASE=Texas Memory Systems Inc + +pci:v000015B6d00000001* + ID_MODEL_FROM_DATABASE=XP15 DSP Accelerator + +pci:v000015B6d00000002* + ID_MODEL_FROM_DATABASE=XP30 DSP Accelerator + +pci:v000015B6d00000003* + ID_MODEL_FROM_DATABASE=XP00 Data Acquisition Device + +pci:v000015B6d00000004* + ID_MODEL_FROM_DATABASE=XP35 DSP Accelerator + +pci:v000015B6d00000007* + ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-T0] + +pci:v000015B6d00000008* + ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-T1] + +pci:v000015B6d00000009* + ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-E0] + +pci:v000015B6d0000000A* + ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-E1] + +pci:v000015B6d0000000E* + ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-0] + +pci:v000015B6d0000000F* + ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-1] + +pci:v000015B6d00000010* + ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-P0] + +pci:v000015B6d00000011* + ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-P1] + +pci:v000015B6d00000012* + ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-P2] + +pci:v000015B6d00000013* + ID_MODEL_FROM_DATABASE=XP100 DSP Accelerator [XP100-P3] + +pci:v000015B6d00000014* + ID_MODEL_FROM_DATABASE=RamSan Flash SSD + +pci:v000015B6d00000015* + ID_MODEL_FROM_DATABASE=ZBox + +pci:v000015B7* + ID_VENDOR_FROM_DATABASE=Sandisk Corp + +pci:v000015B7d00002001* + ID_MODEL_FROM_DATABASE=Skyhawk Series NVME SSD + +pci:v000015B7d00005001* + ID_MODEL_FROM_DATABASE=WD Black NVMe SSD + +pci:v000015B7d00005002* + ID_MODEL_FROM_DATABASE=WD Black 2018/PC SN720 NVMe SSD + +pci:v000015B7d00005003* + ID_MODEL_FROM_DATABASE=WD Black 2018/PC SN520 NVMe SSD + +pci:v000015B8* + ID_VENDOR_FROM_DATABASE=ADDI-DATA GmbH + +pci:v000015B8d00001001* + ID_MODEL_FROM_DATABASE=APCI1516 SP controller (16 digi outputs) + +pci:v000015B8d00001003* + ID_MODEL_FROM_DATABASE=APCI1032 SP controller (32 digi inputs w/ opto coupler) + +pci:v000015B8d00001004* + ID_MODEL_FROM_DATABASE=APCI2032 SP controller (32 digi outputs) + +pci:v000015B8d00001005* + ID_MODEL_FROM_DATABASE=APCI2200 SP controller (8/16 digi outputs (relay)) + +pci:v000015B8d00001006* + ID_MODEL_FROM_DATABASE=APCI1564 SP controller (32 digi ins, 32 digi outs) + +pci:v000015B8d0000100A* + ID_MODEL_FROM_DATABASE=APCI1696 SP controller (96 TTL I/Os) + +pci:v000015B8d00003001* + ID_MODEL_FROM_DATABASE=APCI3501 SP controller (analog output board) + +pci:v000015B8d0000300F* + ID_MODEL_FROM_DATABASE=APCI3600 Noise and vibration measurement board + +pci:v000015B8d00007001* + ID_MODEL_FROM_DATABASE=APCI7420 2-port Serial Controller + +pci:v000015B8d00007002* + ID_MODEL_FROM_DATABASE=APCI7300 Serial Controller + +pci:v000015B9* + ID_VENDOR_FROM_DATABASE=Maestro Digital Communications + +pci:v000015BA* + ID_VENDOR_FROM_DATABASE=Impacct Technology Corp + +pci:v000015BB* + ID_VENDOR_FROM_DATABASE=Portwell Inc + +pci:v000015BC* + ID_VENDOR_FROM_DATABASE=Agilent Technologies + +pci:v000015BCd00000100* + ID_MODEL_FROM_DATABASE=HPFC-5600 Tachyon DX2+ FC + +pci:v000015BCd00000103* + ID_MODEL_FROM_DATABASE=QX4 PCI Express quad 4-gigabit Fibre Channel controller + +pci:v000015BCd00000105* + ID_MODEL_FROM_DATABASE=Celerity FC-44XS/FC-42XS/FC-41XS/FC-44ES/FC-42ES/FC-41ES + +pci:v000015BCd00000105sv0000117Csd00000022* + ID_MODEL_FROM_DATABASE=Celerity FC-44XS/FC-42XS/FC-41XS/FC-44ES/FC-42ES/FC-41ES (Celerity FC-42XS Fibre Channel Adapter) + +pci:v000015BCd00000105sv0000117Csd00000025* + ID_MODEL_FROM_DATABASE=Celerity FC-44XS/FC-42XS/FC-41XS/FC-44ES/FC-42ES/FC-41ES (Celerity FC-44ES Fibre Channel Adapter) + +pci:v000015BCd00000105sv0000117Csd00000026* + ID_MODEL_FROM_DATABASE=Celerity FC-44XS/FC-42XS/FC-41XS/FC-44ES/FC-42ES/FC-41ES (Celerity FC-42ES Fibre Channel Adapter) + +pci:v000015BCd00001100* + ID_MODEL_FROM_DATABASE=E8001-66442 PCI Express CIC + +pci:v000015BCd00002922* + ID_MODEL_FROM_DATABASE=64 Bit, 133MHz PCI-X Exerciser & Protocol Checker + +pci:v000015BCd00002928* + ID_MODEL_FROM_DATABASE=64 Bit, 66MHz PCI Exerciser & Analyzer + +pci:v000015BCd00002929* + ID_MODEL_FROM_DATABASE=64 Bit, 133MHz PCI-X Analyzer & Exerciser + +pci:v000015BD* + ID_VENDOR_FROM_DATABASE=DFI Inc + +pci:v000015BE* + ID_VENDOR_FROM_DATABASE=Sola Electronics + +pci:v000015BF* + ID_VENDOR_FROM_DATABASE=High Tech Computer Corp (HTC) + +pci:v000015C0* + ID_VENDOR_FROM_DATABASE=BVM Ltd + +pci:v000015C1* + ID_VENDOR_FROM_DATABASE=Quantel + +pci:v000015C2* + ID_VENDOR_FROM_DATABASE=Newer Technology Inc + +pci:v000015C3* + ID_VENDOR_FROM_DATABASE=Taiwan Mycomp Co Ltd + +pci:v000015C4* + ID_VENDOR_FROM_DATABASE=EVSX Inc + +pci:v000015C5* + ID_VENDOR_FROM_DATABASE=Procomp Informatics Ltd + +pci:v000015C5d00008010* + ID_MODEL_FROM_DATABASE=1394b - 1394 Firewire 3-Port Host Adapter Card + +pci:v000015C6* + ID_VENDOR_FROM_DATABASE=Technical University of Budapest + +pci:v000015C7* + ID_VENDOR_FROM_DATABASE=Tateyama System Laboratory Co Ltd + +pci:v000015C7d00000349* + ID_MODEL_FROM_DATABASE=Tateyama C-PCI PLC/NC card Rev.01A + +pci:v000015C8* + ID_VENDOR_FROM_DATABASE=Penta Media Co Ltd + +pci:v000015C9* + ID_VENDOR_FROM_DATABASE=Serome Technology Inc + +pci:v000015CA* + ID_VENDOR_FROM_DATABASE=Bitboys OY + +pci:v000015CB* + ID_VENDOR_FROM_DATABASE=AG Electronics Ltd + +pci:v000015CC* + ID_VENDOR_FROM_DATABASE=Hotrail Inc + +pci:v000015CD* + ID_VENDOR_FROM_DATABASE=Dreamtech Co Ltd + +pci:v000015CE* + ID_VENDOR_FROM_DATABASE=Genrad Inc + +pci:v000015CF* + ID_VENDOR_FROM_DATABASE=Hilscher GmbH + +pci:v000015CFd00000000* + ID_MODEL_FROM_DATABASE=CIFX 50E-DP(M/S) + +pci:v000015D1* + ID_VENDOR_FROM_DATABASE=Infineon Technologies AG + +pci:v000015D2* + ID_VENDOR_FROM_DATABASE=FIC (First International Computer Inc) + +pci:v000015D3* + ID_VENDOR_FROM_DATABASE=NDS Technologies Israel Ltd + +pci:v000015D4* + ID_VENDOR_FROM_DATABASE=Iwill Corp + +pci:v000015D5* + ID_VENDOR_FROM_DATABASE=Tatung Co + +pci:v000015D6* + ID_VENDOR_FROM_DATABASE=Entridia Corp + +pci:v000015D7* + ID_VENDOR_FROM_DATABASE=Rockwell-Collins Inc + +pci:v000015D8* + ID_VENDOR_FROM_DATABASE=Cybernetics Technology Co Ltd + +pci:v000015D9* + ID_VENDOR_FROM_DATABASE=Super Micro Computer Inc + +pci:v000015DA* + ID_VENDOR_FROM_DATABASE=Cyberfirm Inc + +pci:v000015DB* + ID_VENDOR_FROM_DATABASE=Applied Computing Systems Inc + +pci:v000015DC* + ID_VENDOR_FROM_DATABASE=Litronic Inc + +pci:v000015DCd00000001* + ID_MODEL_FROM_DATABASE=Argus 300 PCI Cryptography Module + +pci:v000015DD* + ID_VENDOR_FROM_DATABASE=Sigmatel Inc + +pci:v000015DE* + ID_VENDOR_FROM_DATABASE=Malleable Technologies Inc + +pci:v000015DF* + ID_VENDOR_FROM_DATABASE=Infinilink Corp + +pci:v000015E0* + ID_VENDOR_FROM_DATABASE=Cacheflow Inc + +pci:v000015E1* + ID_VENDOR_FROM_DATABASE=Voice Technologies Group Inc + +pci:v000015E2* + ID_VENDOR_FROM_DATABASE=Quicknet Technologies Inc + +pci:v000015E2d00000500* + ID_MODEL_FROM_DATABASE=PhoneJack-PCI + +pci:v000015E3* + ID_VENDOR_FROM_DATABASE=Networth Technologies Inc + +pci:v000015E4* + ID_VENDOR_FROM_DATABASE=VSN Systemen BV + +pci:v000015E5* + ID_VENDOR_FROM_DATABASE=Valley technologies Inc + +pci:v000015E6* + ID_VENDOR_FROM_DATABASE=Agere Inc + +pci:v000015E7* + ID_VENDOR_FROM_DATABASE=Get Engineering Corp + +pci:v000015E8* + ID_VENDOR_FROM_DATABASE=National Datacomm Corp + +pci:v000015E8d00000130* + ID_MODEL_FROM_DATABASE=Wireless PCI Card + +pci:v000015E8d00000131* + ID_MODEL_FROM_DATABASE=NCP130A2 Wireless NIC + +pci:v000015E9* + ID_VENDOR_FROM_DATABASE=Pacific Digital Corp + +pci:v000015E9d00001841* + ID_MODEL_FROM_DATABASE=ADMA-100 DiscStaQ ATA Controller + +pci:v000015EA* + ID_VENDOR_FROM_DATABASE=Tokyo Denshi Sekei K.K. + +pci:v000015EB* + ID_VENDOR_FROM_DATABASE=DResearch Digital Media Systems GmbH + +pci:v000015EC* + ID_VENDOR_FROM_DATABASE=Beckhoff GmbH + +pci:v000015ECd00003101* + ID_MODEL_FROM_DATABASE=FC3101 Profibus DP 1 Channel PCI + +pci:v000015ECd00005102* + ID_MODEL_FROM_DATABASE=FC5102 + +pci:v000015ED* + ID_VENDOR_FROM_DATABASE=Macrolink Inc + +pci:v000015EE* + ID_VENDOR_FROM_DATABASE=In Win Development Inc + +pci:v000015EF* + ID_VENDOR_FROM_DATABASE=Intelligent Paradigm Inc + +pci:v000015F0* + ID_VENDOR_FROM_DATABASE=B-Tree Systems Inc + +pci:v000015F1* + ID_VENDOR_FROM_DATABASE=Times N Systems Inc + +pci:v000015F2* + ID_VENDOR_FROM_DATABASE=Diagnostic Instruments Inc + +pci:v000015F3* + ID_VENDOR_FROM_DATABASE=Digitmedia Corp + +pci:v000015F4* + ID_VENDOR_FROM_DATABASE=Valuesoft + +pci:v000015F5* + ID_VENDOR_FROM_DATABASE=Power Micro Research + +pci:v000015F6* + ID_VENDOR_FROM_DATABASE=Extreme Packet Device Inc + +pci:v000015F7* + ID_VENDOR_FROM_DATABASE=Banctec + +pci:v000015F8* + ID_VENDOR_FROM_DATABASE=Koga Electronics Co + +pci:v000015F9* + ID_VENDOR_FROM_DATABASE=Zenith Electronics Corp + +pci:v000015FA* + ID_VENDOR_FROM_DATABASE=J.P. Axzam Corp + +pci:v000015FB* + ID_VENDOR_FROM_DATABASE=Zilog Inc + +pci:v000015FC* + ID_VENDOR_FROM_DATABASE=Techsan Electronics Co Ltd + +pci:v000015FD* + ID_VENDOR_FROM_DATABASE=N-CUBED.NET + +pci:v000015FE* + ID_VENDOR_FROM_DATABASE=Kinpo Electronics Inc + +pci:v000015FF* + ID_VENDOR_FROM_DATABASE=Fastpoint Technologies Inc + +pci:v00001600* + ID_VENDOR_FROM_DATABASE=Northrop Grumman - Canada Ltd + +pci:v00001601* + ID_VENDOR_FROM_DATABASE=Tenta Technology + +pci:v00001602* + ID_VENDOR_FROM_DATABASE=Prosys-tec Inc + +pci:v00001603* + ID_VENDOR_FROM_DATABASE=Nokia Wireless Communications + +pci:v00001604* + ID_VENDOR_FROM_DATABASE=Central System Research Co Ltd + +pci:v00001605* + ID_VENDOR_FROM_DATABASE=Pairgain Technologies + +pci:v00001606* + ID_VENDOR_FROM_DATABASE=Europop AG + +pci:v00001607* + ID_VENDOR_FROM_DATABASE=Lava Semiconductor Manufacturing Inc + +pci:v00001608* + ID_VENDOR_FROM_DATABASE=Automated Wagering International + +pci:v00001609* + ID_VENDOR_FROM_DATABASE=Scimetric Instruments Inc + +pci:v00001612* + ID_VENDOR_FROM_DATABASE=Telesynergy Research Inc. + +pci:v00001618* + ID_VENDOR_FROM_DATABASE=Stone Ridge Technology + +pci:v00001618d00000001* + ID_MODEL_FROM_DATABASE=RDX 11 + +pci:v00001618d00000002* + ID_MODEL_FROM_DATABASE=HFT-01 + +pci:v00001618d00000400* + ID_MODEL_FROM_DATABASE=FarSync T2P (2 port X.21/V.35/V.24) + +pci:v00001618d00000440* + ID_MODEL_FROM_DATABASE=FarSync T4P (4 port X.21/V.35/V.24) + +pci:v00001618d00000610* + ID_MODEL_FROM_DATABASE=FarSync T1U (1 port X.21/V.35/V.24) + +pci:v00001618d00000620* + ID_MODEL_FROM_DATABASE=FarSync T2U (2 port X.21/V.35/V.24) + +pci:v00001618d00000640* + ID_MODEL_FROM_DATABASE=FarSync T4U (4 port X.21/V.35/V.24) + +pci:v00001618d00001610* + ID_MODEL_FROM_DATABASE=FarSync TE1 (T1,E1) + +pci:v00001618d00002610* + ID_MODEL_FROM_DATABASE=FarSync DSL-S1 (SHDSL) + +pci:v00001618d00003640* + ID_MODEL_FROM_DATABASE=FarSync T4E (4-port X.21/V.35/V.24) + +pci:v00001618d00004620* + ID_MODEL_FROM_DATABASE=FarSync T2Ue PCI Express (2-port X.21/V.35/V.24) + +pci:v00001618d00004640* + ID_MODEL_FROM_DATABASE=FarSync T4Ue PCI Express (4-port X.21/V.35/V.24) + +pci:v00001619* + ID_VENDOR_FROM_DATABASE=FarSite Communications Ltd + +pci:v00001619d00000400* + ID_MODEL_FROM_DATABASE=FarSync T2P (2 port X.21/V.35/V.24) + +pci:v00001619d00000440* + ID_MODEL_FROM_DATABASE=FarSync T4P (4 port X.21/V.35/V.24) + +pci:v00001619d00000610* + ID_MODEL_FROM_DATABASE=FarSync T1U (1 port X.21/V.35/V.24) + +pci:v00001619d00000620* + ID_MODEL_FROM_DATABASE=FarSync T2U (2 port X.21/V.35/V.24) + +pci:v00001619d00000640* + ID_MODEL_FROM_DATABASE=FarSync T4U (4 port X.21/V.35/V.24) + +pci:v00001619d00001610* + ID_MODEL_FROM_DATABASE=FarSync TE1 (T1,E1) + +pci:v00001619d00001612* + ID_MODEL_FROM_DATABASE=FarSync TE1 PCI Express (T1,E1) + +pci:v00001619d00002610* + ID_MODEL_FROM_DATABASE=FarSync DSL-S1 (SHDSL) + +pci:v00001619d00003640* + ID_MODEL_FROM_DATABASE=FarSync T4E (4-port X.21/V.35/V.24) + +pci:v00001619d00004620* + ID_MODEL_FROM_DATABASE=FarSync T2Ue PCI Express (2-port X.21/V.35/V.24) + +pci:v00001619d00004640* + ID_MODEL_FROM_DATABASE=FarSync T4Ue PCI Express (4-port X.21/V.35/V.24) + +pci:v00001619d00005621* + ID_MODEL_FROM_DATABASE=FarSync T2Ee PCI Express (2 port X.21/V.35/V.24) + +pci:v00001619d00005641* + ID_MODEL_FROM_DATABASE=FarSync T4Ee PCI Express (4 port X.21/V.35/V.24) + +pci:v00001619d00006620* + ID_MODEL_FROM_DATABASE=FarSync T2U-PMC PCI Express (2 port X.21/V.35/V.24) + +pci:v0000161F* + ID_VENDOR_FROM_DATABASE=Rioworks + +pci:v00001621* + ID_VENDOR_FROM_DATABASE=Lynx Studio Technology, Inc. + +pci:v00001621d00000020* + ID_MODEL_FROM_DATABASE=LynxTWO-A + +pci:v00001621d00000021* + ID_MODEL_FROM_DATABASE=LynxTWO-B + +pci:v00001621d00000022* + ID_MODEL_FROM_DATABASE=LynxTWO-C + +pci:v00001621d00000023* + ID_MODEL_FROM_DATABASE=Lynx L22 + +pci:v00001621d00000024* + ID_MODEL_FROM_DATABASE=Lynx AES16 + +pci:v00001621d00000025* + ID_MODEL_FROM_DATABASE=Lynx AES16-SRC + +pci:v00001621d00000028* + ID_MODEL_FROM_DATABASE=Lynx AES16e + +pci:v00001626* + ID_VENDOR_FROM_DATABASE=TDK Semiconductor Corp. + +pci:v00001626d00008410* + ID_MODEL_FROM_DATABASE=RTL81xx Fast Ethernet + +pci:v00001629* + ID_VENDOR_FROM_DATABASE=Kongsberg Spacetec AS + +pci:v00001629d00001003* + ID_MODEL_FROM_DATABASE=Format synchronizer v3.0 + +pci:v00001629d00001006* + ID_MODEL_FROM_DATABASE=Format synchronizer, model 10500 + +pci:v00001629d00001007* + ID_MODEL_FROM_DATABASE=Format synchronizer, model 21000 + +pci:v00001629d00002002* + ID_MODEL_FROM_DATABASE=Fast Universal Data Output + +pci:v00001629d00003100* + ID_MODEL_FROM_DATABASE=IO31000 Frame Synchronizer and I/O + +pci:v00001629d00003200* + ID_MODEL_FROM_DATABASE=IO32000 Frame Synchronizer and I/O + +pci:v00001629d00004002* + ID_MODEL_FROM_DATABASE=High Rate Demodulator + +pci:v00001629d00005001* + ID_MODEL_FROM_DATABASE=High Rate FEC + +pci:v00001629d00006001* + ID_MODEL_FROM_DATABASE=High Rate Demodulator and FEC + +pci:v00001631* + ID_VENDOR_FROM_DATABASE=Packard Bell B.V. + +pci:v00001638* + ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp [SMC] + +pci:v00001638d00001100* + ID_MODEL_FROM_DATABASE=SMC2602W EZConnect / Addtron AWA-100 / Eumitcom PCI WL11000 + +pci:v0000163C* + ID_VENDOR_FROM_DATABASE=Smart Link Ltd. + +pci:v0000163Cd00003052* + ID_MODEL_FROM_DATABASE=SmartLink SmartPCI562 56K Modem + +pci:v0000163Cd00005449* + ID_MODEL_FROM_DATABASE=SmartPCI561 Modem + +pci:v00001641* + ID_VENDOR_FROM_DATABASE=MKNet Corp. + +pci:v00001642* + ID_VENDOR_FROM_DATABASE=Bitland(ShenZhen) Information Technology Co., Ltd. + +pci:v00001657* + ID_VENDOR_FROM_DATABASE=Cavium QLogic + +pci:v00001657d00000013* + ID_MODEL_FROM_DATABASE=425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA + +pci:v00001657d00000013sv0000103Csd00001742* + ID_MODEL_FROM_DATABASE=425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA (82B 8Gbps dual port FC HBA) + +pci:v00001657d00000013sv0000103Csd00001744* + ID_MODEL_FROM_DATABASE=425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA (42B 4Gbps dual port FC HBA) + +pci:v00001657d00000013sv00001657sd00000014* + ID_MODEL_FROM_DATABASE=425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA (425/825 4Gbps/8Gbps PCIe dual port FC HBA) + +pci:v00001657d00000014* + ID_MODEL_FROM_DATABASE=1010/1020/1007/1741 10Gbps CNA + +pci:v00001657d00000014sv00001657sd00000014* + ID_MODEL_FROM_DATABASE=1010/1020/1007/1741 10Gbps CNA (- FCOE) + +pci:v00001657d00000014sv00001657sd00000015* + ID_MODEL_FROM_DATABASE=1010/1020/1007/1741 10Gbps CNA (- LL) + +pci:v00001657d00000017* + ID_MODEL_FROM_DATABASE=415/815/41B/81B 4Gbps/8Gbps PCIe single port FC HBA + +pci:v00001657d00000017sv0000103Csd00001741* + ID_MODEL_FROM_DATABASE=415/815/41B/81B 4Gbps/8Gbps PCIe single port FC HBA (41B 4Gbps single port FC HBA) + +pci:v00001657d00000017sv0000103Csd00001743* + ID_MODEL_FROM_DATABASE=415/815/41B/81B 4Gbps/8Gbps PCIe single port FC HBA (81B 8Gbps single port FC HBA) + +pci:v00001657d00000017sv00001657sd00000014* + ID_MODEL_FROM_DATABASE=415/815/41B/81B 4Gbps/8Gbps PCIe single port FC HBA (415/815 4Gbps/8Gbps single port PCIe FC HBA) + +pci:v00001657d00000021* + ID_MODEL_FROM_DATABASE=804 8Gbps FC HBA for HP Bladesystem c-class + +pci:v00001657d00000022* + ID_MODEL_FROM_DATABASE=BR-1860 Fabric Adapter + +pci:v00001657d00000022sv00001657sd00000022* + ID_MODEL_FROM_DATABASE=BR-1860 Fabric Adapter (10Gbps CNA - FCOE) + +pci:v00001657d00000022sv00001657sd00000023* + ID_MODEL_FROM_DATABASE=BR-1860 Fabric Adapter (10Gbps CNA - LL) + +pci:v00001657d00000022sv00001657sd00000024* + ID_MODEL_FROM_DATABASE=BR-1860 Fabric Adapter (16Gbps FC HBA) + +pci:v00001657d00000023* + ID_MODEL_FROM_DATABASE=1867/1869 16Gbps FC HBA + +pci:v00001657d00000646* + ID_MODEL_FROM_DATABASE=400 4Gbps PCIe FC HBA + +pci:v0000165A* + ID_VENDOR_FROM_DATABASE=Epix Inc + +pci:v0000165Ad0000C100* + ID_MODEL_FROM_DATABASE=PIXCI(R) CL1 Camera Link Video Capture Board [custom QL5232] + +pci:v0000165Ad0000D200* + ID_MODEL_FROM_DATABASE=PIXCI(R) D2X Digital Video Capture Board [custom QL5232] + +pci:v0000165Ad0000D300* + ID_MODEL_FROM_DATABASE=PIXCI(R) D3X Digital Video Capture Board [custom QL5232] + +pci:v0000165Ad0000EB01* + ID_MODEL_FROM_DATABASE=PIXCI(R) EB1 PCI Camera Link Video Capture Board + +pci:v0000165C* + ID_VENDOR_FROM_DATABASE=Gidel Ltd. + +pci:v0000165Cd00005361* + ID_MODEL_FROM_DATABASE=PROCStarII60-1 + +pci:v0000165Cd00005362* + ID_MODEL_FROM_DATABASE=PROCStarII60-2 + +pci:v0000165Cd00005364* + ID_MODEL_FROM_DATABASE=PROCStarII60-4 + +pci:v0000165Cd00005435* + ID_MODEL_FROM_DATABASE=ProcSparkII + +pci:v0000165Cd00005661* + ID_MODEL_FROM_DATABASE=ProcE60 + +pci:v0000165Cd000056E1* + ID_MODEL_FROM_DATABASE=ProcE180 + +pci:v0000165Cd00005911* + ID_MODEL_FROM_DATABASE=ProcStarIII110-1 + +pci:v0000165Cd00005912* + ID_MODEL_FROM_DATABASE=ProcStarIII110-2 + +pci:v0000165Cd00005913* + ID_MODEL_FROM_DATABASE=ProcStarIII110-3 + +pci:v0000165Cd00005914* + ID_MODEL_FROM_DATABASE=ProcStarIII110-4 + +pci:v0000165Cd00005921* + ID_MODEL_FROM_DATABASE=ProcStarIII150-1 + +pci:v0000165Cd00005922* + ID_MODEL_FROM_DATABASE=ProcStarIII150-2 + +pci:v0000165Cd00005923* + ID_MODEL_FROM_DATABASE=ProcStarIII150-3 + +pci:v0000165Cd00005924* + ID_MODEL_FROM_DATABASE=ProcStarIII150-4 + +pci:v0000165Cd00005931* + ID_MODEL_FROM_DATABASE=ProcStarIII260-1 + +pci:v0000165Cd00005932* + ID_MODEL_FROM_DATABASE=ProcStarIII260-2 + +pci:v0000165Cd00005933* + ID_MODEL_FROM_DATABASE=ProcStarIII260-3 + +pci:v0000165Cd00005934* + ID_MODEL_FROM_DATABASE=ProcStarIII260-4 + +pci:v0000165Cd00005941* + ID_MODEL_FROM_DATABASE=ProcStarIII340-1 + +pci:v0000165Cd00005942* + ID_MODEL_FROM_DATABASE=ProcStarIII340-2 + +pci:v0000165Cd00005943* + ID_MODEL_FROM_DATABASE=ProcStarIII340-3 + +pci:v0000165Cd00005944* + ID_MODEL_FROM_DATABASE=ProcStarIII340-4 + +pci:v0000165Cd00005A01* + ID_MODEL_FROM_DATABASE=ProceIII80 + +pci:v0000165Cd00005A11* + ID_MODEL_FROM_DATABASE=ProceIII110 + +pci:v0000165Cd00005A21* + ID_MODEL_FROM_DATABASE=ProceIII150 + +pci:v0000165Cd00005A31* + ID_MODEL_FROM_DATABASE=ProceIII260 + +pci:v0000165Cd00005A41* + ID_MODEL_FROM_DATABASE=ProceIII340 + +pci:v0000165Cd00005B51* + ID_MODEL_FROM_DATABASE=ProceIV360 + +pci:v0000165Cd00005B61* + ID_MODEL_FROM_DATABASE=ProceIV530 + +pci:v0000165Cd00005B71* + ID_MODEL_FROM_DATABASE=ProceIV820 + +pci:v0000165Cd00005C01* + ID_MODEL_FROM_DATABASE=ProcStarIV80-1 + +pci:v0000165Cd00005C02* + ID_MODEL_FROM_DATABASE=ProcStarIV80-2 + +pci:v0000165Cd00005C03* + ID_MODEL_FROM_DATABASE=ProcStarIV80-3 + +pci:v0000165Cd00005C04* + ID_MODEL_FROM_DATABASE=ProcStarIV80-4 + +pci:v0000165Cd00005C11* + ID_MODEL_FROM_DATABASE=ProcStarIV110-1 + +pci:v0000165Cd00005C12* + ID_MODEL_FROM_DATABASE=ProcStarIV110-2 + +pci:v0000165Cd00005C13* + ID_MODEL_FROM_DATABASE=ProcStarIV110-3 + +pci:v0000165Cd00005C14* + ID_MODEL_FROM_DATABASE=ProcStarIV110-4 + +pci:v0000165Cd00005C51* + ID_MODEL_FROM_DATABASE=ProcStarIV360-1 + +pci:v0000165Cd00005C52* + ID_MODEL_FROM_DATABASE=ProcStarIV360-2 + +pci:v0000165Cd00005C53* + ID_MODEL_FROM_DATABASE=ProcStarIV360-3 + +pci:v0000165Cd00005C54* + ID_MODEL_FROM_DATABASE=ProcStarIV360-4 + +pci:v0000165Cd00005C61* + ID_MODEL_FROM_DATABASE=ProcStarIV530-1 + +pci:v0000165Cd00005C62* + ID_MODEL_FROM_DATABASE=ProcStarIV530-2 + +pci:v0000165Cd00005C63* + ID_MODEL_FROM_DATABASE=ProcStarIV530-3 + +pci:v0000165Cd00005C64* + ID_MODEL_FROM_DATABASE=ProcStarIV530-4 + +pci:v0000165Cd00005C71* + ID_MODEL_FROM_DATABASE=ProcStarIV820-1 + +pci:v0000165Cd00005C72* + ID_MODEL_FROM_DATABASE=ProcStarIV820-2 + +pci:v0000165Cd00005C73* + ID_MODEL_FROM_DATABASE=ProcStarIV820-3 + +pci:v0000165Cd00005C74* + ID_MODEL_FROM_DATABASE=ProcStarIV820-4 + +pci:v0000165Cd00005D01* + ID_MODEL_FROM_DATABASE=Proc10480 + +pci:v0000165Cd00005D11* + ID_MODEL_FROM_DATABASE=Proc104110 + +pci:v0000165Cd00005F01* + ID_MODEL_FROM_DATABASE=ProceV_A3 + +pci:v0000165Cd00005F11* + ID_MODEL_FROM_DATABASE=ProceV_A7 + +pci:v0000165Cd00005F21* + ID_MODEL_FROM_DATABASE=ProceV_AB + +pci:v0000165Cd00005F31* + ID_MODEL_FROM_DATABASE=ProceV_D5 + +pci:v0000165Cd00005F41* + ID_MODEL_FROM_DATABASE=ProceV_D8 + +pci:v0000165Cd00006732* + ID_MODEL_FROM_DATABASE=Proc6M + +pci:v0000165Cd00006832* + ID_MODEL_FROM_DATABASE=Proc12M + +pci:v0000165Cd00007101* + ID_MODEL_FROM_DATABASE=Proc10a_27 + +pci:v0000165Cd00007111* + ID_MODEL_FROM_DATABASE=Proc10a_48 + +pci:v0000165Cd00007121* + ID_MODEL_FROM_DATABASE=Proc10a_66 + +pci:v0000165Cd00007141* + ID_MODEL_FROM_DATABASE=Proc10a_115 + +pci:v0000165Cd00007181* + ID_MODEL_FROM_DATABASE=Proc10a_27S + +pci:v0000165Cd00007191* + ID_MODEL_FROM_DATABASE=Proc10a_48S + +pci:v0000165Cd000071A1* + ID_MODEL_FROM_DATABASE=Proc10a_66S + +pci:v0000165Cd000071B1* + ID_MODEL_FROM_DATABASE=Proc10A + +pci:v0000165Cd000072B1* + ID_MODEL_FROM_DATABASE=HawkEye + +pci:v0000165Cd000073B1* + ID_MODEL_FROM_DATABASE=Proc10s + +pci:v0000165D* + ID_VENDOR_FROM_DATABASE=Hsing Tech. Enterprise Co., Ltd. + +pci:v0000165F* + ID_VENDOR_FROM_DATABASE=Linux Media Labs, LLC + +pci:v0000165Fd00001020* + ID_MODEL_FROM_DATABASE=LMLM4 MPEG-4 encoder + +pci:v00001661* + ID_VENDOR_FROM_DATABASE=Worldspace Corp. + +pci:v00001668* + ID_VENDOR_FROM_DATABASE=Actiontec Electronics Inc + +pci:v00001668d00000100* + ID_MODEL_FROM_DATABASE=Mini-PCI bridge + +pci:v0000166D* + ID_VENDOR_FROM_DATABASE=Broadcom Corporation + +pci:v0000166Dd00000001* + ID_MODEL_FROM_DATABASE=SiByte BCM1125/1125H/1250 System-on-a-Chip PCI + +pci:v0000166Dd00000002* + ID_MODEL_FROM_DATABASE=SiByte BCM1125H/1250 System-on-a-Chip HyperTransport + +pci:v0000166Dd00000012* + ID_MODEL_FROM_DATABASE=SiByte BCM1280/BCM1480 System-on-a-Chip PCI-X + +pci:v0000166Dd00000014* + ID_MODEL_FROM_DATABASE=Sibyte BCM1280/BCM1480 System-on-a-Chip HyperTransport + +pci:v00001677* + ID_VENDOR_FROM_DATABASE=Bernecker + Rainer + +pci:v00001677d0000104E* + ID_MODEL_FROM_DATABASE=5LS172.6 B&R Dual CAN Interface Card + +pci:v00001677d000012D7* + ID_MODEL_FROM_DATABASE=5LS172.61 B&R Dual CAN Interface Card + +pci:v00001677d000020AD* + ID_MODEL_FROM_DATABASE=5ACPCI.MFIO-K01 Profibus DP / K-Feldbus / COM + +pci:v00001678* + ID_VENDOR_FROM_DATABASE=NetEffect + +pci:v00001678d00000100* + ID_MODEL_FROM_DATABASE=NE020 10Gb Accelerated Ethernet Adapter (iWARP RNIC) + +pci:v00001679* + ID_VENDOR_FROM_DATABASE=Tokyo Electron Device Ltd. + +pci:v00001679d00003000* + ID_MODEL_FROM_DATABASE=SD Standard host controller [Ellen] + +pci:v0000167B* + ID_VENDOR_FROM_DATABASE=ZyDAS Technology Corp. + +pci:v0000167Bd00002102* + ID_MODEL_FROM_DATABASE=ZyDAS ZD1202 + +pci:v0000167Bd00002102sv0000187Esd00003406* + ID_MODEL_FROM_DATABASE=ZyDAS ZD1202 (ZyAIR B-122 CardBus 11Mbs Wireless LAN Card) + +pci:v0000167Bd00002102sv0000187Esd00003407* + ID_MODEL_FROM_DATABASE=ZyDAS ZD1202 (ZyAIR B-320 802.11b Wireless PCI Adapter) + +pci:v0000167Bd00002116* + ID_MODEL_FROM_DATABASE=ZD1212B Wireless Adapter + +pci:v0000167D* + ID_VENDOR_FROM_DATABASE=Samsung Electro-Mechanics Co., Ltd. + +pci:v0000167Dd0000A000* + ID_MODEL_FROM_DATABASE=MagicLAN SWL-2210P 802.11b [Intersil ISL3874] + +pci:v0000167E* + ID_VENDOR_FROM_DATABASE=ONNTO Corp. + +pci:v00001681* + ID_VENDOR_FROM_DATABASE=Hercules + +pci:v00001682* + ID_VENDOR_FROM_DATABASE=XFX Pine Group Inc. + +pci:v00001682d0000C580* + ID_MODEL_FROM_DATABASE=Radeon RX 580 + +pci:v00001688* + ID_VENDOR_FROM_DATABASE=CastleNet Technology Inc. + +pci:v00001688d00001170* + ID_MODEL_FROM_DATABASE=WLAN 802.11b card + +pci:v0000168C* + ID_VENDOR_FROM_DATABASE=Qualcomm Atheros + +pci:v0000168Cd00000007* + ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] + +pci:v0000168Cd00000007sv00001737sd00000007* + ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] (WPC54A Wireless PC Card) + +pci:v0000168Cd00000007sv00001B47sd00000100* + ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] (Harmony 8450CN Wireless CardBus Module) + +pci:v0000168Cd00000007sv00001B47sd00000110* + ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] (Skyline 4030 / Harmony 8450 802.11a Wireless CardBus Adapter) + +pci:v0000168Cd00000007sv00008086sd00002501* + ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] (PRO/Wireless 5000 LAN PCI Adapter Module) + +pci:v0000168Cd00000011* + ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001A 802.11a] + +pci:v0000168Cd00000012* + ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] + +pci:v0000168Cd00000012sv00001186sd00003A03* + ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (AirPro DWL-A650 Wireless Cardbus Adapter (rev.B)) + +pci:v0000168Cd00000012sv00001186sd00003A04* + ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (AirPro DWL-AB650 Multimode Wireless Cardbus Adapter) + +pci:v0000168Cd00000012sv00001186sd00003A05* + ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (AirPro DWL-AB520 Multimode Wireless PCI Adapter) + +pci:v0000168Cd00000012sv0000126Csd00008031* + ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (2201 Mobile Adapter) + +pci:v0000168Cd00000012sv00001385sd00004400* + ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (WAB501 802.11ab Wireless CardBus Card) + +pci:v0000168Cd00000012sv00001B47sd0000AA00* + ID_MODEL_FROM_DATABASE=AR5211 Wireless Network Adapter [AR5001X 802.11ab] (8460 802.11ab Wireless CardBus Adapter) + +pci:v0000168Cd00000013* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter + +pci:v0000168Cd00000013sv00000308sd00003402* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AG-100 802.11ag Wireless Cardbus Adapter) + +pci:v0000168Cd00000013sv00000308sd00003405* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (G-102 v2 802.11g Wireless Cardbus Adapter) + +pci:v0000168Cd00000013sv00000308sd00003408* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (G-170S 802.11g Wireless CardBus Adapter) + +pci:v0000168Cd00000013sv00000E11sd000000E5* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (NC6000/NC8000 laptop) + +pci:v0000168Cd00000013sv000010B7sd00006002* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (3CRWE154A72 802.11abg Cardbus Adapter) + +pci:v0000168Cd00000013sv00001113sd0000D301* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Philips CPWNA100 Wireless CardBus adapter) + +pci:v0000168Cd00000013sv00001113sd0000EE23* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (SMCWPCIT-G 108Mbps Wireless PCI adapter) + +pci:v0000168Cd00000013sv00001154sd0000033B* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Buffalo WLI-CB-AMG54) + +pci:v0000168Cd00000013sv00001154sd0000034E* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Buffalo WLI-CB-AG108HP 802.11abg Cardbus Adapter) + +pci:v0000168Cd00000013sv00001186sd00003202* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (DWL-G650 (Rev B3,B5) Wireless cardbus adapter) + +pci:v0000168Cd00000013sv00001186sd00003203* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirPlus DWL-G520 Wireless PCI Adapter (rev. A)) + +pci:v0000168Cd00000013sv00001186sd00003A07* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirXpert DWL-AG650 Wireless Cardbus Adapter) + +pci:v0000168Cd00000013sv00001186sd00003A08* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirXpert DWL-AG520 Wireless PCI Adapter) + +pci:v0000168Cd00000013sv00001186sd00003A12* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (D-Link AirPlus DWL-G650 Wireless Cardbus Adapter(rev.C)) + +pci:v0000168Cd00000013sv00001186sd00003A13* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirPlus DWL-G520 Wireless PCI Adapter (rev. B)) + +pci:v0000168Cd00000013sv00001186sd00003A14* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirPremier AG DWL-AG530 Wireless PCI Adapter (rev.A)) + +pci:v0000168Cd00000013sv00001186sd00003A17* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (D-Link AirPremier DWL-G680 Wireless Cardbus Adapter) + +pci:v0000168Cd00000013sv00001186sd00003A18* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (D-Link AirPremier DWL-G550 Wireless PCI Adapter) + +pci:v0000168Cd00000013sv00001186sd00003A1A* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WNA-2330 802.11bg Wireless CardBus Adapter) + +pci:v0000168Cd00000013sv00001186sd00003A63* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (D-Link AirPremier DWL-AG660 Wireless Cardbus Adapter) + +pci:v0000168Cd00000013sv00001186sd00003A93* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Conceptronic C54I Wireless 801.11g PCI card) + +pci:v0000168Cd00000013sv00001186sd00003A94* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Conceptronic C54C 802.11g Wireless Cardbus Adapter) + +pci:v0000168Cd00000013sv00001186sd00003AB0* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Allnet ALL0281 Wireless PCI Card) + +pci:v0000168Cd00000013sv00001385sd00004600* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WAG511 802.11a/b/g Dual Band Wireless PC Card) + +pci:v0000168Cd00000013sv00001385sd00004610* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WAG511 802.11a/b/g Dual Band Wireless PC Card) + +pci:v0000168Cd00000013sv00001385sd00004900* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG311v1 802.11g Wireless PCI Adapter) + +pci:v0000168Cd00000013sv00001385sd00004A00* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WAG311 802.11a/g Wireless PCI Adapter) + +pci:v0000168Cd00000013sv00001385sd00004B00* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG511T 108 Mbps Wireless PC Card (rev.A/B)) + +pci:v0000168Cd00000013sv00001385sd00004D00* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG311T 108 Mbps Wireless PCI Adapter (rev.A2)) + +pci:v0000168Cd00000013sv00001385sd00004F00* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG511U Double 108 Mbps Wireless PC Card) + +pci:v0000168Cd00000013sv00001385sd00005A00* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG311T (rev.A3 v1h3/v1h4) 108 Mbps Wireless PCI Adapter [AR2412]) + +pci:v0000168Cd00000013sv00001385sd00005B00* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WG511T 108 Mbps Wireless PC Card (rev.C)) + +pci:v0000168Cd00000013sv00001385sd00005D00* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WPN511 RangeMax Wireless PC Card) + +pci:v0000168Cd00000013sv00001458sd0000E911* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (GN-WIAG02) + +pci:v0000168Cd00000013sv00001468sd00000403* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (U10H014 802.11g Cardbus Adapter) + +pci:v0000168Cd00000013sv00001468sd00000408* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (ThinkPad 11b/g Wireless LAN Mini PCI Adapter) + +pci:v0000168Cd00000013sv000014B7sd00000A10* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (8480-WD 802.11abg Cardbus Adapter) + +pci:v0000168Cd00000013sv000014B7sd00000A60* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (8482-WD ORiNOCO 11a/b/g Wireless PCI Adapter) + +pci:v0000168Cd00000013sv000014B7sd0000AA30* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (8800-FC 802.11bg Cardbus Adapter) + +pci:v0000168Cd00000013sv000014B7sd0000AA40* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (8470-WD 802.11bg Cardbus Adapter) + +pci:v0000168Cd00000013sv000014B9sd0000CB21* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (CB21 802.11a/b/g Cardbus Adapter) + +pci:v0000168Cd00000013sv00001668sd00001026* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (IBM HighRate 11 a/b/g Wireless CardBus Adapter) + +pci:v0000168Cd00000013sv0000168Csd00000013* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (AirPlus XtremeG DWL-G650 Wireless PCMCIA Adapter) + +pci:v0000168Cd00000013sv0000168Csd00001025* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (DWL-G650B2 Wireless CardBus Adapter) + +pci:v0000168Cd00000013sv0000168Csd00001027* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Engenius NL-3054CB ARIES b/g CardBus Adapter) + +pci:v0000168Cd00000013sv0000168Csd00001042* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Ubiquiti Networks SuperRange a/b/g Cardbus Adapter) + +pci:v0000168Cd00000013sv0000168Csd00001051* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (EZ Connect g 802.11g 108Mbps Wireless PCI Adapter) + +pci:v0000168Cd00000013sv0000168Csd00002026* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Netgate 5354MP ARIES a(108Mb turbo)/b/g MiniPCI Adapter) + +pci:v0000168Cd00000013sv0000168Csd00002027* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (D-Link AirPlus DWL-G520 Wireless PCI Adapter (rev. A)) + +pci:v0000168Cd00000013sv0000168Csd00002041* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Engenius 5354MP Plus ARIES2 b/g MiniPCI Adapter) + +pci:v0000168Cd00000013sv0000168Csd00002042* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Engenius 5354MP Plus ARIES2 a/b/g MiniPCI Adapter) + +pci:v0000168Cd00000013sv0000168Csd00002051* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (TRENDnet TEW-443PI Wireless PCI Adapter) + +pci:v0000168Cd00000013sv000016A5sd0000160A* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (BWP712 802.11bg Wireless CardBus Adapter) + +pci:v0000168Cd00000013sv000016ABsd00007302* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Trust Speedshare Turbo Pro Wireless PCI Adapter) + +pci:v0000168Cd00000013sv00001737sd00000017* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WPC55AG) + +pci:v0000168Cd00000013sv00001737sd00000026* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WMP55AG v1.1) + +pci:v0000168Cd00000013sv00001737sd00000035* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WPC55AG v1.2 802.11abg Cardbus Adapter) + +pci:v0000168Cd00000013sv00001737sd00000036* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (WMP55AG v1.2 802.11abg PCI Adapter) + +pci:v0000168Cd00000013sv00001799sd00003000* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (F6D3000 Dual-Band Wireless A+G Desktop Card) + +pci:v0000168Cd00000013sv00001799sd00003010* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (F6D3010 Dual-Band Wireless A+G Notebook Card) + +pci:v0000168Cd00000013sv000017CFsd00000042* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Z-COMAX Highpower XG-622H (400mw) 802.11b/g mini-PCI Adapter) + +pci:v0000168Cd00000013sv0000185Fsd00001012* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (CM9 Wireless a/b/g MiniPCI Adapter) + +pci:v0000168Cd00000013sv0000185Fsd00002012* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (Wistron NeWeb WLAN a+b+g model CB9) + +pci:v0000168Cd00000013sv0000A727sd00006801* + ID_MODEL_FROM_DATABASE=AR5212/5213/2414 Wireless Network Adapter (3CRXJK10075 OfficeConnect Wireless 108Mbps 11g XJACK PC Card) + +pci:v0000168Cd0000001A* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] + +pci:v0000168Cd0000001Asv00001052sd0000168C* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (Sweex Wireless Lan PC Card 54Mbps) + +pci:v0000168Cd0000001Asv00001113sd0000EE20* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (SMC Wireless CardBus Adapter 802.11g (SMCWCB-G EU)) + +pci:v0000168Cd0000001Asv00001113sd0000EE24* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (SMC Wireless PCI Card WPCI-G) + +pci:v0000168Cd0000001Asv00001186sd00003A15* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.D1)) + +pci:v0000168Cd0000001Asv00001186sd00003A16* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (AirPlus G DWL-G510 Wireless PCI Adapter(rev.B)) + +pci:v0000168Cd0000001Asv00001186sd00003A1C* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (WNA-1330 Notebook Adapter) + +pci:v0000168Cd0000001Asv00001186sd00003A1D* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (WDA-1320 Desktop Adapter) + +pci:v0000168Cd0000001Asv00001186sd00003A23* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (AirPlus G DWL-G520+A Wireless PCI Adapter) + +pci:v0000168Cd0000001Asv00001186sd00003A24* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (AirPlus G DWL-G650+A Wireless Cardbus Adapter) + +pci:v0000168Cd0000001Asv00001186sd00003B08* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.C1)) + +pci:v0000168Cd0000001Asv0000168Csd0000001A* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (Belkin FD7000) + +pci:v0000168Cd0000001Asv0000168Csd00001052* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (TP-Link TL-WN510G Wireless CardBus Adapter) + +pci:v0000168Cd0000001Asv0000168Csd00002052* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (Compex Wireless 802.11 b/g MiniPCI Adapter, Rev A1 [WLM54G]) + +pci:v0000168Cd0000001Asv000016ECsd00000122* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (Wireless PCI Adapter Model 5418) + +pci:v0000168Cd0000001Asv00001737sd00000053* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (WPC54G v7 802.11g Wireless-G Notebook Adapter) + +pci:v0000168Cd0000001Asv00001799sd0000700C* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (F5D7000 v5000 Wireless G Desktop Card) + +pci:v0000168Cd0000001Asv00001799sd0000701D* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (F5D7010 v5000 Wireless G Notebook Card) + +pci:v0000168Cd0000001Asv000017F9sd00000008* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (DX-WGNBC 802.11bg Wireless CardBus Adapter) + +pci:v0000168Cd0000001Asv000017F9sd00000018* + ID_MODEL_FROM_DATABASE=AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] (DX-WGDTC 802.11bg Wireless PCI Adapter) + +pci:v0000168Cd0000001B* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] + +pci:v0000168Cd0000001Bsv00000777sd00001107* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (UB5 802.11a Wireless Mini PCI Adapter) + +pci:v0000168Cd0000001Bsv00000777sd00003002* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (XR2 802.11g Wireless Mini PCI Adapter) + +pci:v0000168Cd0000001Bsv00000777sd00003005* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (XR5 802.11a Wireless Mini PCI Adapter) + +pci:v0000168Cd0000001Bsv00000777sd00003009* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (XR9 900MHz Wireless Mini PCI Adapter) + +pci:v0000168Cd0000001Bsv00001154sd0000034E* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (WLI-CB-AG108HP 802.11abg Wireless CardBus Adapter) + +pci:v0000168Cd0000001Bsv00001186sd00003A19* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (D-Link AirPremier AG DWL-AG660 Wireless Cardbus Adapter) + +pci:v0000168Cd0000001Bsv00001186sd00003A22* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (AirPremier AG DWL-AG530 Wireless PCI Adapter (rev.B)) + +pci:v0000168Cd0000001Bsv000011ADsd00005001* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (WN5301A 802.11bg Wireless PCI Adapter) + +pci:v0000168Cd0000001Bsv00001458sd0000E901* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (GN-WI01HT Wireless a/b/g MiniPCI Adapter) + +pci:v0000168Cd0000001Bsv0000168Csd0000001B* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (Wireless LAN PCI LiteOn) + +pci:v0000168Cd0000001Bsv0000168Csd00001062* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (IPN-W100CB 802.11abg Wireless CardBus Adapter) + +pci:v0000168Cd0000001Bsv0000168Csd00002062* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (EnGenius EMP-8602 (400mw) or Compex WLM54AG (SuperAG)) + +pci:v0000168Cd0000001Bsv0000168Csd00002063* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (EnGenius EMP-8602 (400mw) or Compex WLM54AG) + +pci:v0000168Cd0000001Bsv000017F9sd0000000B* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (WL-711A 802.11abg Wireless CardBus Adapter) + +pci:v0000168Cd0000001Bsv000017F9sd0000000C* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (WPIA-112AG 802.11abg Wireless PCI Adapter) + +pci:v0000168Cd0000001Bsv000017F9sd0000000D* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (PC-686X 802.11abg Wireless Mini PCI Adapter) + +pci:v0000168Cd0000001Bsv0000185Fsd00001600* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (DCMA-82 High Power WLAN 802.11a/b/g mini-PCI Module (Super A/G, eXtended Range, 400mW)) + +pci:v0000168Cd0000001Bsv00001948sd00003ABA* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (RBTBJ-AW 802.11abg Wireless Cardbus Adapter) + +pci:v0000168Cd0000001Bsv0000A727sd00006804* + ID_MODEL_FROM_DATABASE=AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] (Wireless 11a/b/g PC Card with XJACK(r) Antenna) + +pci:v0000168Cd0000001C* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) + +pci:v0000168Cd0000001Csv00000777sd00003006* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (SRX 802.11abg Wireless ExpressCard Adapter) + +pci:v0000168Cd0000001Csv0000103Csd0000137A* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5BXB63 (Foxconn) 802.11bg Mini PCIe NIC) + +pci:v0000168Cd0000001Csv0000106Bsd00000086* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AirPort Extreme) + +pci:v0000168Cd0000001Csv0000144Fsd00007106* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (WLL3140 (Toshiba PA3501U-1MPC) 802.11bg Wireless Mini PCIe Card) + +pci:v0000168Cd0000001Csv0000144Fsd00007128* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (WLL3141 (Toshiba PA3613U-1MPC) 802.11bg Wireless Mini PCIe Card) + +pci:v0000168Cd0000001Csv00001468sd00000428* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5BXB63 802.11bg NIC) + +pci:v0000168Cd0000001Csv00001468sd0000042A* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5007EG 802.11bg NIC) + +pci:v0000168Cd0000001Csv0000147Bsd00001033* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AirPace Wi-Fi) + +pci:v0000168Cd0000001Csv0000168Csd0000001C* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR242x 802.11abg NIC (PCI Express)) + +pci:v0000168Cd0000001Csv0000168Csd00003061* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5006EGS 802.11bg NIC (2.4GHz, PCI Express)) + +pci:v0000168Cd0000001Csv0000168Csd00003062* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5006EXS 802.11abg NIC (2.4/5.0GHz, PCI Express)) + +pci:v0000168Cd0000001Csv0000168Csd00003063* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5006EX 802.11abg NIC (2.4/5.0GHz, PCI Express)) + +pci:v0000168Cd0000001Csv0000168Csd00003065* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR5006EG 802.11bg NIC (2.4GHz, PCI Express)) + +pci:v0000168Cd0000001Csv0000168Csd00003067* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AR242x 802.11abg Wireless PCI Express Adapter (rev 01)) + +pci:v0000168Cd0000001Csv00001A3Bsd00001026* + ID_MODEL_FROM_DATABASE=AR242x / AR542x Wireless Network Adapter (PCI-Express) (AW-GE780 802.11bg Wireless Mini PCIe Card) + +pci:v0000168Cd0000001D* + ID_MODEL_FROM_DATABASE=AR2417 Wireless Network Adapter [AR5007G 802.11bg] + +pci:v0000168Cd0000001Dsv00001799sd0000720B* + ID_MODEL_FROM_DATABASE=AR2417 Wireless Network Adapter [AR5007G 802.11bg] (F5D7000 v8000 Wireless G Desktop Card) + +pci:v0000168Cd0000001Dsv00001799sd0000721B* + ID_MODEL_FROM_DATABASE=AR2417 Wireless Network Adapter [AR5007G 802.11bg] (F5D7010 v8000 Wireless G Notebook Card) + +pci:v0000168Cd00000020* + ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC + +pci:v0000168Cd00000020sv00000308sd00003407* + ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC (M-102 802.11g Wireless Cardbus Adapter) + +pci:v0000168Cd00000020sv00001186sd00003A67* + ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC (DWL-G650M Super G MIMO Wireless Notebook Adapter) + +pci:v0000168Cd00000020sv00001186sd00003A68* + ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC (DWL-G520M Wireless 108G MIMO Desktop Adapter) + +pci:v0000168Cd00000020sv0000187Esd0000340E* + ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC (M-302 802.11g Wireless PCI Adapter) + +pci:v0000168Cd00000020sv00001976sd00002003* + ID_MODEL_FROM_DATABASE=AR5513 802.11abg Wireless NIC (TEW-601PC 802.11g Wireless CardBus Adapter) + +pci:v0000168Cd00000023* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] + +pci:v0000168Cd00000023sv00000308sd0000340B* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (NWD-170N 802.11bgn Wireless CardBus Adapter) + +pci:v0000168Cd00000023sv00001154sd00000365* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (Buffalo WLP-CB-AG300 802.11abgn Cardbus Adapter) + +pci:v0000168Cd00000023sv00001154sd00000367* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (WLI-CB-AG301N 802.11abgn Wireless CardBus Adapter) + +pci:v0000168Cd00000023sv00001186sd00003A6A* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (DWA-642 802.11n RangeBooster N CardBus Adapter) + +pci:v0000168Cd00000023sv00001186sd00003A6B* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (DWA-547 802.11n RangeBooster N 650 DeskTop Adapter) + +pci:v0000168Cd00000023sv00001186sd00003A6D* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (DWA-552 802.11n Xtreme N Desktop Adapter (rev A1)) + +pci:v0000168Cd00000023sv00001186sd00003A76* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (DWA-645 802.11n RangeBooster N 650 Notebook Adapter (rev A1)) + +pci:v0000168Cd00000023sv00001737sd00000059* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (WPC300N v2 Wireless-N Notebook Adapter) + +pci:v0000168Cd00000023sv00001737sd00000069* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (WPC100 v1 802.11n RangePlus Wireless Notebook Adapter) + +pci:v0000168Cd00000023sv00001737sd00000072* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (WMP110 v1 802.11n RangePlus Wireless PCI Adapter) + +pci:v0000168Cd00000023sv00001799sd00008011* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (F5D8011 v1 802.11n N1 Wireless Notebook Card) + +pci:v0000168Cd00000023sv0000187Esd00003411* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (NWD-370N 802.11n Wireless PCI Adapter) + +pci:v0000168Cd00000023sv00001976sd00002008* + ID_MODEL_FROM_DATABASE=AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] (TEW-621PC 802.11bgn Wireless CardBus Adapter) + +pci:v0000168Cd00000024* + ID_MODEL_FROM_DATABASE=AR5418 Wireless Network Adapter [AR5008E 802.11(a)bgn] (PCI-Express) + +pci:v0000168Cd00000024sv0000106Bsd00000087* + ID_MODEL_FROM_DATABASE=AR5418 Wireless Network Adapter [AR5008E 802.11(a)bgn] (PCI-Express) (AirPort Extreme) + +pci:v0000168Cd00000024sv00001186sd00003A70* + ID_MODEL_FROM_DATABASE=AR5418 Wireless Network Adapter [AR5008E 802.11(a)bgn] (PCI-Express) (DWA-556 Xtreme N PCI Express Desktop Adapter) + +pci:v0000168Cd00000027* + ID_MODEL_FROM_DATABASE=AR9160 Wireless Network Adapter [AR9001 802.11(a)bgn] + +pci:v0000168Cd00000027sv00000777sd00004082* + ID_MODEL_FROM_DATABASE=AR9160 Wireless Network Adapter [AR9001 802.11(a)bgn] (SR71-A 802.11abgn Wireless Mini PCI Adapter) + +pci:v0000168Cd00000029* + ID_MODEL_FROM_DATABASE=AR922X Wireless Network Adapter + +pci:v0000168Cd00000029sv00000777sd00004005* + ID_MODEL_FROM_DATABASE=AR922X Wireless Network Adapter (SR71-15 802.11an Mini PCI Adapter) + +pci:v0000168Cd00000029sv00001186sd00003A7A* + ID_MODEL_FROM_DATABASE=AR922X Wireless Network Adapter (DWA-552 802.11n Xtreme N Desktop Adapter (rev A2)) + +pci:v0000168Cd00000029sv00001186sd00003A7D* + ID_MODEL_FROM_DATABASE=AR922X Wireless Network Adapter (DWA-552 802.11n Xtreme N Desktop Adapter (rev A3)) + +pci:v0000168Cd00000029sv0000168Csd00000029* + ID_MODEL_FROM_DATABASE=AR922X Wireless Network Adapter + +pci:v0000168Cd00000029sv0000168Csd00002096* + ID_MODEL_FROM_DATABASE=AR922X Wireless Network Adapter (Compex WLM200NX / Wistron DNMA-92) + +pci:v0000168Cd0000002A* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) + +pci:v0000168Cd0000002Asv00000777sd00004F05* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (SR71-X 802.11abgn Wireless ExpressCard Adapter [AR9280]) + +pci:v0000168Cd0000002Asv0000103Csd00003041* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AR5BHB92-H 802.11abgn Wireless Half-size Mini PCIe Card [AR9280]) + +pci:v0000168Cd0000002Asv0000103Csd00003042* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AzureWave AW-NE773 802.11abgn Wireless Half-size Mini PCIe Card [AR9280]) + +pci:v0000168Cd0000002Asv0000105Bsd0000E006* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (T77H053.00 802.11bgn Wireless Mini PCIe Card [AR9281]) + +pci:v0000168Cd0000002Asv0000105Bsd0000E01F* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (T77H047.31 802.11bgn Wireless Half-size Mini PCIe Card [AR9283]) + +pci:v0000168Cd0000002Asv0000106Bsd0000008F* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AirPort Extreme) + +pci:v0000168Cd0000002Asv000011ADsd00006600* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (WN6600A 802.11bgn Wireless Mini PCIe Card [AR9281]) + +pci:v0000168Cd0000002Asv0000144Fsd00007141* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (WLL6080 802.11bgn Wireless Mini PCIe Card [AR9281]) + +pci:v0000168Cd0000002Asv0000168Csd00000203* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (DW1525 802.11abgn WLAN PCIe Card [AR9280]) + +pci:v0000168Cd0000002Asv00001A32sd00000303* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (EM303 802.11bgn Wireless Mini PCIe Card [AR9281]) + +pci:v0000168Cd0000002Asv00001A32sd00000306* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (EM306 802.11bgn Wireless Half-size Mini PCIe Card [AR9283]) + +pci:v0000168Cd0000002Asv00001A3Bsd00001067* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AW-NE771 802.11bgn Wireless Mini PCIe Card [AR9281]) + +pci:v0000168Cd0000002Asv00001A3Bsd00001071* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AW-NE772 802.11abgn Wireless Mini PCIe Card [AR9280]) + +pci:v0000168Cd0000002Asv00001A3Bsd00001081* + ID_MODEL_FROM_DATABASE=AR928X Wireless Network Adapter (PCI-Express) (AW-NE773 802.11abgn Wireless Half-size Mini PCIe Card [AR9280]) + +pci:v0000168Cd0000002B* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) + +pci:v0000168Cd0000002Bsv00001028sd00000204* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (Wireless 1502 802.11bgn Half-size Mini PCIe Card) + +pci:v0000168Cd0000002Bsv00001028sd00000205* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (Wireless 1702 802.11bgn Half-size Mini PCIe Card [AR9002WB-1NGCD]) + +pci:v0000168Cd0000002Bsv0000103Csd0000303F* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (U98Z062.10 802.11bgn Wireless Half-size Mini PCIe Card) + +pci:v0000168Cd0000002Bsv0000103Csd00003040* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (U98Z062.12 802.11bgn Wireless Half-size Mini PCIe Card) + +pci:v0000168Cd0000002Bsv0000105Bsd0000E017* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (T77H126.00 802.11bgn Wireless Half-size Mini PCIe Card) + +pci:v0000168Cd0000002Bsv0000105Bsd0000E023* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (T77H121.04 802.11bgn Wireless Half-size Mini PCIe Card) + +pci:v0000168Cd0000002Bsv0000105Bsd0000E025* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (T77H121.05 802.11bgn Wireless Half-size Mini PCIe Card) + +pci:v0000168Cd0000002Bsv00001113sd0000E811* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (WN7811A (Toshiba PA3722U-1MPC) 802.11bgn Wireless Half-size Mini PCIe Card) + +pci:v0000168Cd0000002Bsv0000185Fsd000030AF* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (DNXA-95 802.11bgn Wireless Half-size Mini PCIe Card) + +pci:v0000168Cd0000002Bsv00001931sd00000023* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (Option GTM67x PCIe WiFi Adapter) + +pci:v0000168Cd0000002Bsv00001A3Bsd00001089* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (AW-NE785 / AW-NE785H 802.11bgn Wireless Full or Half-size Mini PCIe Card) + +pci:v0000168Cd0000002Bsv00001A3Bsd00002C37* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (AW-NB037H 802.11bgn Wireless Half-size Mini PCIe Card [AR9002WB-1NGCD]) + +pci:v0000168Cd0000002Bsv00001B9Asd00000401* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (XW204E 802.11bgn Wireless Half-size Mini PCIe Card) + +pci:v0000168Cd0000002Bsv00001B9Asd00000C03* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) (WB214E 802.11bgn Wireless Half-size Mini PCIe Card [AR9002WB-1NGCD]) + +pci:v0000168Cd0000002C* + ID_MODEL_FROM_DATABASE=AR2427 802.11bg Wireless Network Adapter (PCI-Express) + +pci:v0000168Cd0000002D* + ID_MODEL_FROM_DATABASE=AR9227 Wireless Network Adapter + +pci:v0000168Cd0000002E* + ID_MODEL_FROM_DATABASE=AR9287 Wireless Network Adapter (PCI-Express) + +pci:v0000168Cd0000002Esv0000105Bsd0000E034* + ID_MODEL_FROM_DATABASE=AR9287 Wireless Network Adapter (PCI-Express) (T77H167.00) + +pci:v0000168Cd00000030* + ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter + +pci:v0000168Cd00000030sv0000103Csd00001627* + ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter (AR9380/HB112 802.11abgn 3×3 Wi-Fi Adapter) + +pci:v0000168Cd00000030sv0000106Bsd0000009A* + ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter (AirPort Extreme) + +pci:v0000168Cd00000030sv00001186sd00003A7E* + ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter (DWA-566 Wireless N 300 Dual Band PCIe Desktop Adapter) + +pci:v0000168Cd00000030sv00001A56sd00002000* + ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter (Killer Wireless-N 1102 Half-size Mini PCIe Card [AR9382]) + +pci:v0000168Cd00000030sv00001A56sd00002001* + ID_MODEL_FROM_DATABASE=AR93xx Wireless Network Adapter (Killer Wireless-N 1103 Half-size Mini PCIe Card [AR9380]) + +pci:v0000168Cd00000032* + ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter + +pci:v0000168Cd00000032sv00001028sd00000208* + ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (Wireless 1506 WLAN Half Mini-Card) + +pci:v0000168Cd00000032sv0000103Csd00001838* + ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AR9485/HB125 802.11bgn 1×1 Wi-Fi Adapter) + +pci:v0000168Cd00000032sv0000105Bsd0000E044* + ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (Unex DHXA-225) + +pci:v0000168Cd00000032sv0000144Dsd0000410E* + ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AR9485WB-EG 802.11b/g/n mini-PCIe card on a series 3 laptop) + +pci:v0000168Cd00000032sv00001A3Bsd00001186* + ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AW-NE186H) + +pci:v0000168Cd00000033* + ID_MODEL_FROM_DATABASE=AR958x 802.11abgn Wireless Network Adapter + +pci:v0000168Cd00000033sv0000168Csd0000A120* + ID_MODEL_FROM_DATABASE=AR958x 802.11abgn Wireless Network Adapter (AR9582 802.11a/n WLAN Mini-PCIe Adapter) + +pci:v0000168Cd00000034* + ID_MODEL_FROM_DATABASE=AR9462 Wireless Network Adapter + +pci:v0000168Cd00000034sv00001028sd0000020B* + ID_MODEL_FROM_DATABASE=AR9462 Wireless Network Adapter (Wireless 1601 802.11abgn Adapter) + +pci:v0000168Cd00000034sv00001028sd00000300* + ID_MODEL_FROM_DATABASE=AR9462 Wireless Network Adapter (Wireless 1802 802.11abgn Adapter) + +pci:v0000168Cd00000034sv00001A56sd00002003* + ID_MODEL_FROM_DATABASE=AR9462 Wireless Network Adapter (Killer Wireless-N 1202 Half-size Mini PCIe Card) + +pci:v0000168Cd00000036* + ID_MODEL_FROM_DATABASE=QCA9565 / AR9565 Wireless Network Adapter + +pci:v0000168Cd00000037* + ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter + +pci:v0000168Cd00000037sv00001A3Bsd00002100* + ID_MODEL_FROM_DATABASE=AR9485 Wireless Network Adapter (AW-NB100H 802.11n Wireless Mini PCIe Card) + +pci:v0000168Cd0000003C* + ID_MODEL_FROM_DATABASE=QCA986x/988x 802.11ac Wireless Network Adapter + +pci:v0000168Cd0000003E* + ID_MODEL_FROM_DATABASE=QCA6174 802.11ac Wireless Network Adapter + +pci:v0000168Cd0000003Esv00001A56sd0000143A* + ID_MODEL_FROM_DATABASE=QCA6174 802.11ac Wireless Network Adapter (Killer 1435 Wireless-AC) + +pci:v0000168Cd0000003Esv00001A56sd00001525* + ID_MODEL_FROM_DATABASE=QCA6174 802.11ac Wireless Network Adapter (Killer N1525 Wireless-AC) + +pci:v0000168Cd00000040* + ID_MODEL_FROM_DATABASE=QCA9980/9990 802.11ac Wireless Network Adapter + +pci:v0000168Cd00000041* + ID_MODEL_FROM_DATABASE=QCA6164 802.11ac Wireless Network Adapter + +pci:v0000168Cd00000042* + ID_MODEL_FROM_DATABASE=QCA9377 802.11ac Wireless Network Adapter + +pci:v0000168Cd00000046* + ID_MODEL_FROM_DATABASE=QCA9984 802.11ac Wave 2 Wireless Network Adapter + +pci:v0000168Cd00000050* + ID_MODEL_FROM_DATABASE=QCA9887 802.11ac Wireless Network Adapter + +pci:v0000168Cd00000207* + ID_MODEL_FROM_DATABASE=AR5210 Wireless Network Adapter [AR5000 802.11a] + +pci:v0000168Cd00001014* + ID_MODEL_FROM_DATABASE=AR5212 802.11abg NIC + +pci:v0000168Cd00001014sv00001014sd0000058A* + ID_MODEL_FROM_DATABASE=AR5212 802.11abg NIC (ThinkPad 11a/b/g Wireless LAN Mini Express Adapter (AR5BXB6)) + +pci:v0000168Cd00009013* + ID_MODEL_FROM_DATABASE=AR5002X Wireless Network Adapter + +pci:v0000168Cd0000FF19* + ID_MODEL_FROM_DATABASE=AR5006X Wireless Network Adapter + +pci:v0000168Cd0000FF1B* + ID_MODEL_FROM_DATABASE=AR2425 Wireless Network Adapter [AR5007EG 802.11bg] + +pci:v0000168Cd0000FF1C* + ID_MODEL_FROM_DATABASE=AR5008 Wireless Network Adapter + +pci:v0000168Cd0000FF1D* + ID_MODEL_FROM_DATABASE=AR922x Wireless Network Adapter + +pci:v0000168Cd0000FF1Dsv0000168Csd0000EE1C* + ID_MODEL_FROM_DATABASE=AR922x Wireless Network Adapter (AR9220-AC1A [AVM Fritz!Box FON WLAN 7270 v3]) + +pci:v00001695* + ID_VENDOR_FROM_DATABASE=EPoX Computer Co., Ltd. + +pci:v0000169C* + ID_VENDOR_FROM_DATABASE=Netcell Corporation + +pci:v0000169Cd00000044* + ID_MODEL_FROM_DATABASE=Revolution Storage Processing Card + +pci:v0000169D* + ID_VENDOR_FROM_DATABASE=Club-3D VB (Wrong ID) + +pci:v000016A5* + ID_VENDOR_FROM_DATABASE=Tekram Technology Co.,Ltd. + +pci:v000016AB* + ID_VENDOR_FROM_DATABASE=Global Sun Technology Inc + +pci:v000016ABd00001100* + ID_MODEL_FROM_DATABASE=GL24110P + +pci:v000016ABd00001101* + ID_MODEL_FROM_DATABASE=PLX9052 PCMCIA-to-PCI Wireless LAN + +pci:v000016ABd00001102* + ID_MODEL_FROM_DATABASE=PCMCIA-to-PCI Wireless Network Bridge + +pci:v000016ABd00008501* + ID_MODEL_FROM_DATABASE=WL-8305 Wireless LAN PCI Adapter + +pci:v000016AE* + ID_VENDOR_FROM_DATABASE=SafeNet Inc + +pci:v000016AEd00000001* + ID_MODEL_FROM_DATABASE=SafeXcel 1140 + +pci:v000016AEd0000000A* + ID_MODEL_FROM_DATABASE=SafeXcel 1841 + +pci:v000016AEd00001141* + ID_MODEL_FROM_DATABASE=SafeXcel 1141 + +pci:v000016AEd00001141sv00000001sd00000001* + ID_MODEL_FROM_DATABASE=SafeXcel 1141 (v. 1.1) + +pci:v000016AEd00001841* + ID_MODEL_FROM_DATABASE=SafeXcel 1842 + +pci:v000016AF* + ID_VENDOR_FROM_DATABASE=SparkLAN Communications, Inc. + +pci:v000016B4* + ID_VENDOR_FROM_DATABASE=Aspex Semiconductor Ltd + +pci:v000016B8* + ID_VENDOR_FROM_DATABASE=Sonnet Technologies, Inc. + +pci:v000016BE* + ID_VENDOR_FROM_DATABASE=Creatix Polymedia GmbH + +pci:v000016C3* + ID_VENDOR_FROM_DATABASE=Synopsys, Inc. + +pci:v000016C3d0000ABCD* + ID_MODEL_FROM_DATABASE=DWC_usb3 / PCIe bridge + +pci:v000016C3d0000ABCE* + ID_MODEL_FROM_DATABASE=DWC_usb3 + +pci:v000016C3d0000ABCF* + ID_MODEL_FROM_DATABASE=DWC_usb31 + +pci:v000016C3d0000EDDA* + ID_MODEL_FROM_DATABASE=EPMockUp + +pci:v000016C6* + ID_VENDOR_FROM_DATABASE=Micrel-Kendin + +pci:v000016C6d00008695* + ID_MODEL_FROM_DATABASE=Centaur KS8695 ARM processor + +pci:v000016C6d00008842* + ID_MODEL_FROM_DATABASE=KSZ8842-PMQL 2-Port Ethernet Switch + +pci:v000016C8* + ID_VENDOR_FROM_DATABASE=Octasic Inc. + +pci:v000016C9* + ID_VENDOR_FROM_DATABASE=EONIC B.V. The Netherlands + +pci:v000016CA* + ID_VENDOR_FROM_DATABASE=CENATEK Inc + +pci:v000016CAd00000001* + ID_MODEL_FROM_DATABASE=Rocket Drive DL + +pci:v000016CD* + ID_VENDOR_FROM_DATABASE=Advantech Co. Ltd + +pci:v000016CDd00000101* + ID_MODEL_FROM_DATABASE=DirectPCI SRAM for DPX-11x series + +pci:v000016CDd00000102* + ID_MODEL_FROM_DATABASE=DirectPCI SRAM for DPX-S/C/E-series + +pci:v000016CDd00000103* + ID_MODEL_FROM_DATABASE=DirectPCI ROM for DPX-11x series + +pci:v000016CDd00000104* + ID_MODEL_FROM_DATABASE=DirectPCI ROM for DPX-S/C/E-series + +pci:v000016CDd00000105* + ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-114/DPX-115 + +pci:v000016CDd00000106* + ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-116 + +pci:v000016CDd00000107* + ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-116U + +pci:v000016CDd00000108* + ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-117 + +pci:v000016CDd00000109* + ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-112 + +pci:v000016CDd0000010A* + ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-C/E-series + +pci:v000016CDd0000010B* + ID_MODEL_FROM_DATABASE=DirectPCI I/O for DPX-S series + +pci:v000016CE* + ID_VENDOR_FROM_DATABASE=Roland Corp. + +pci:v000016D5* + ID_VENDOR_FROM_DATABASE=Acromag, Inc. + +pci:v000016D5d00000504* + ID_MODEL_FROM_DATABASE=PMC-DX504 Reconfigurable FPGA with LVDS I/O + +pci:v000016D5d00000520* + ID_MODEL_FROM_DATABASE=PMC520 Serial Communication, 232 Octal + +pci:v000016D5d00000521* + ID_MODEL_FROM_DATABASE=PMC521 Serial Communication, 422/485 Octal + +pci:v000016D5d00001020* + ID_MODEL_FROM_DATABASE=PMC-AX1020 Reconfigurable FPGA with A/D & D/A + +pci:v000016D5d00001065* + ID_MODEL_FROM_DATABASE=PMC-AX1065 Reconfigurable FPGA with A/D & D/A + +pci:v000016D5d00002004* + ID_MODEL_FROM_DATABASE=PMC-DX2004 Reconfigurable FPGA with LVDS I/O + +pci:v000016D5d00002020* + ID_MODEL_FROM_DATABASE=PMC-AX2020 Reconfigurable FPGA with A/D & D/A + +pci:v000016D5d00002065* + ID_MODEL_FROM_DATABASE=PMC-AX2065 Reconfigurable FPGA with A/D & D/A + +pci:v000016D5d00003020* + ID_MODEL_FROM_DATABASE=PMC-AX3020 Reconfigurable FPGA with A/D & D/A + +pci:v000016D5d00003065* + ID_MODEL_FROM_DATABASE=PMC-AX3065 Reconfigurable FPGA with A/D & D/A + +pci:v000016D5d00004243* + ID_MODEL_FROM_DATABASE=PMC424, APC424, AcPC424 Digital I/O and Counter Timer Module + +pci:v000016D5d00004248* + ID_MODEL_FROM_DATABASE=PMC464, APC464, AcPC464 Digital I/O and Counter Timer Module + +pci:v000016D5d0000424B* + ID_MODEL_FROM_DATABASE=PMC-DX2002 Reconfigurable FPGA with Differential I/O + +pci:v000016D5d00004253* + ID_MODEL_FROM_DATABASE=PMC-DX503 Reconfigurable FPGA with TTL and Differential I/O + +pci:v000016D5d00004312* + ID_MODEL_FROM_DATABASE=PMC-CX1002 Reconfigurable Conduction-Cooled FPGA Virtex-II with Differential I/O + +pci:v000016D5d00004313* + ID_MODEL_FROM_DATABASE=PMC-CX1003 Reconfigurable Conduction-Cooled FPGA Virtex-II with CMOS and Differential I/O + +pci:v000016D5d00004322* + ID_MODEL_FROM_DATABASE=PMC-CX2002 Reconfigurable Conduction-Cooled FPGA Virtex-II with Differential I/O + +pci:v000016D5d00004323* + ID_MODEL_FROM_DATABASE=PMC-CX2003 Reconfigurable Conduction-Cooled FPGA Virtex-II with CMOS and Differential I/O + +pci:v000016D5d00004350* + ID_MODEL_FROM_DATABASE=PMC-DX501 Reconfigurable Digital I/O Module + +pci:v000016D5d00004353* + ID_MODEL_FROM_DATABASE=PMC-DX2003 Reconfigurable FPGA with TTL and Differential I/O + +pci:v000016D5d00004357* + ID_MODEL_FROM_DATABASE=PMC-DX502 Reconfigurable Differential I/O Module + +pci:v000016D5d00004457* + ID_MODEL_FROM_DATABASE=PMC730, APC730, AcPC730 Multifunction Module + +pci:v000016D5d00004471* + ID_MODEL_FROM_DATABASE=XMC730 Multi-function I/O module with front I/O + +pci:v000016D5d00004473* + ID_MODEL_FROM_DATABASE=XMC730CC Multi-function I/O module with rear I/O Conduction-cooled + +pci:v000016D5d0000464D* + ID_MODEL_FROM_DATABASE=PMC408 32-Channel Digital Input/Output Module + +pci:v000016D5d00004850* + ID_MODEL_FROM_DATABASE=PMC220-16 12-Bit Analog Output Module + +pci:v000016D5d00004A42* + ID_MODEL_FROM_DATABASE=PMC483, APC483, AcPC483 Counter Timer Module + +pci:v000016D5d00004A50* + ID_MODEL_FROM_DATABASE=PMC484, APC484, AcPC484 Counter Timer Module + +pci:v000016D5d00004A56* + ID_MODEL_FROM_DATABASE=PMC230 16-Bit Analog Output Module + +pci:v000016D5d00004B47* + ID_MODEL_FROM_DATABASE=PMC330, APC330, AcPC330 Analog Input Module, 16-bit A/D + +pci:v000016D5d00004C40* + ID_MODEL_FROM_DATABASE=PMC-LX40 Reconfigurable Virtex-4 FPGA with plug-in I/O + +pci:v000016D5d00004C60* + ID_MODEL_FROM_DATABASE=PMC-LX60 Reconfigurable Virtex-4 FPGA with plug-in I/O + +pci:v000016D5d00004D4D* + ID_MODEL_FROM_DATABASE=PMC341, APC341, AcPC341 Analog Input Module, Simultaneous Sample & Hold + +pci:v000016D5d00004D4E* + ID_MODEL_FROM_DATABASE=PMC482, APC482, AcPC482 Counter Timer Board + +pci:v000016D5d0000524D* + ID_MODEL_FROM_DATABASE=PMC-DX2001 Reconfigurable FPGA with TTL I/O + +pci:v000016D5d00005335* + ID_MODEL_FROM_DATABASE=PMC-SX35 Reconfigurable Virtex-4 FPGA with plug-in I/O + +pci:v000016D5d00005456* + ID_MODEL_FROM_DATABASE=PMC470 48-Channel Digital Input/Output Module + +pci:v000016D5d00005601* + ID_MODEL_FROM_DATABASE=PMC-VLX85 Reconfigurable Virtex-5 FPGA with plug-in I/O + +pci:v000016D5d00005602* + ID_MODEL_FROM_DATABASE=PMC-VLX110 Reconfigurable Virtex-5 FPGA with plug-in I/O + +pci:v000016D5d00005603* + ID_MODEL_FROM_DATABASE=PMC-VSX95 Reconfigurable Virtex-5 FPGA with plug-in I/O + +pci:v000016D5d00005604* + ID_MODEL_FROM_DATABASE=PMC-VLX155 Reconfigurable Virtex-5 FPGA with plug-in I/O + +pci:v000016D5d00005605* + ID_MODEL_FROM_DATABASE=PMC-VFX70 Reconfigurable Virtex-5 FPGA with plug-in I/O + +pci:v000016D5d00005606* + ID_MODEL_FROM_DATABASE=PMC-VLX155-1M Reconfigurable Virtex-5 FPGA with plug-in I/O + +pci:v000016D5d00005701* + ID_MODEL_FROM_DATABASE=PMC-SLX150: Reconfigurable Spartan-6 FPGA with plug-in I/O + +pci:v000016D5d00005702* + ID_MODEL_FROM_DATABASE=PMC-SLX150-1M: Reconfigurable Spartan-6 FPGA with plug-in I/O + +pci:v000016D5d00005801* + ID_MODEL_FROM_DATABASE=XMC-VLX85 Reconfigurable Virtex-5 FPGA with plug-in I/O + +pci:v000016D5d00005802* + ID_MODEL_FROM_DATABASE=XMC-VLX110 Reconfigurable Virtex-5 FPGA with plug-in I/O + +pci:v000016D5d00005803* + ID_MODEL_FROM_DATABASE=XMC-VSX95 Reconfigurable Virtex-5 FPGA with plug-in I/O + +pci:v000016D5d00005804* + ID_MODEL_FROM_DATABASE=XMC-VLX155 Reconfigurable Virtex-5 FPGA with plug-in I/O + +pci:v000016D5d00005807* + ID_MODEL_FROM_DATABASE=XMC-SLX150: Reconfigurable Spartan-6 FPGA with plug-in I/O + +pci:v000016D5d00005808* + ID_MODEL_FROM_DATABASE=XMC-SLX150-1M: Reconfigurable Spartan-6 FPGA with plug-in I/O + +pci:v000016D5d00005901* + ID_MODEL_FROM_DATABASE=APCe8650 PCI Express IndustryPack Carrier Card + +pci:v000016D5d00006301* + ID_MODEL_FROM_DATABASE=XMC Module with user-configurable Virtex-6 FPGA, 240k logic cells, SFP front I/O + +pci:v000016D5d00006302* + ID_MODEL_FROM_DATABASE=XMC Module with user-configurable Virtex-6 FPGA, 365k logic cells, SFP front I/O + +pci:v000016D5d00006303* + ID_MODEL_FROM_DATABASE=XMC Module with user-configurable Virtex-6 FPGA, 240k logic cells, no front I/O + +pci:v000016D5d00006304* + ID_MODEL_FROM_DATABASE=XMC Module with user-configurable Virtex-6 FPGA, 365k logic cells, no front I/O + +pci:v000016D5d00007000* + ID_MODEL_FROM_DATABASE=XMC-7K325F: User-configurable Kintex-7 FPGA, 325k logic cells plus SFP front I/O + +pci:v000016D5d00007001* + ID_MODEL_FROM_DATABASE=XMC-7K410F: User-configurable Kintex-7 FPGA, 410k logic cells plus SFP front I/O + +pci:v000016D5d00007002* + ID_MODEL_FROM_DATABASE=XMC-7K325AX: User-Configurable Kintex-7 FPGA, 325k logic cells with AXM Plug-In I/O + +pci:v000016D5d00007003* + ID_MODEL_FROM_DATABASE=XMC-7K410AX: User-Configurable Kintex-7 FPGA, 410k logic cells with AXM Plug-In I/O + +pci:v000016D5d00007004* + ID_MODEL_FROM_DATABASE=XMC-7K325CC: User-Configurable Kintex-7 FPGA, 325k logic cells, conduction-cooled + +pci:v000016D5d00007005* + ID_MODEL_FROM_DATABASE=XMC-7K410CC: User-Configurable Kintex-7 FPGA, 410k logic cells, conduction-cooled + +pci:v000016D5d00007006* + ID_MODEL_FROM_DATABASE=XMC-7A200: User-Configurable Artix-7 FPGA, 200k logic cells with Plug-In I/O + +pci:v000016D5d00007007* + ID_MODEL_FROM_DATABASE=XMC-7A200CC: User-Configurable Conduction-Cooled Artix-7 FPGA, with 200k logic cells + +pci:v000016D5d00007011* + ID_MODEL_FROM_DATABASE=AP440-1: 32-Channel Isolated Digital Input Module + +pci:v000016D5d00007012* + ID_MODEL_FROM_DATABASE=AP440-2: 32-Channel Isolated Digital Input Module + +pci:v000016D5d00007013* + ID_MODEL_FROM_DATABASE=AP440-3: 32-Channel Isolated Digital Input Module + +pci:v000016D5d00007014* + ID_MODEL_FROM_DATABASE=AP445: 32-Channel Isolated Digital Output Module + +pci:v000016D5d00007015* + ID_MODEL_FROM_DATABASE=AP471 48-Channel TTL Level Digital Input/Output Module + +pci:v000016D5d00007016* + ID_MODEL_FROM_DATABASE=AP470 48-Channel TTL Level Digital Input/Output Module + +pci:v000016D5d00007017* + ID_MODEL_FROM_DATABASE=AP323 16-bit, 20 or 40 Channel Analog Input Module + +pci:v000016D5d00007018* + ID_MODEL_FROM_DATABASE=AP408: 32-Channel Digital I/O Module + +pci:v000016D5d00007019* + ID_MODEL_FROM_DATABASE=AP341 14-bit, 16-Channel Simultaneous Conversion Analog Input Module + +pci:v000016D5d0000701A* + ID_MODEL_FROM_DATABASE=AP220-16 12-Bit, 16-Channel Analog Output Module + +pci:v000016D5d0000701B* + ID_MODEL_FROM_DATABASE=AP231-16 16-Bit, 16-Channel Analog Output Module + +pci:v000016D5d0000701C* + ID_MODEL_FROM_DATABASE=AP225 12-Bit, 16-Channel Analog Output Module with Waveform Memory + +pci:v000016D5d0000701D* + ID_MODEL_FROM_DATABASE=AP235 16-Bit, 16-Channel Analog Output Module with Waveform Memory + +pci:v000016D5d00007021* + ID_MODEL_FROM_DATABASE=APA7-201 Reconfigurable Artix-7 FPGA module 48 TTL channels + +pci:v000016D5d00007022* + ID_MODEL_FROM_DATABASE=APA7-202 Reconfigurable Artix-7 FPGA module 24 RS485 channels + +pci:v000016D5d00007023* + ID_MODEL_FROM_DATABASE=APA7-203 Reconfigurable Artix-7 FPGA module 24 TTL & 12 RS485 channels + +pci:v000016D5d00007024* + ID_MODEL_FROM_DATABASE=APA7-204 Reconfigurable Artix-7 FPGA module 24 LVDS channels + +pci:v000016D5d00007027* + ID_MODEL_FROM_DATABASE=AP418 16-Channel High Voltage Digital Input/Output Module + +pci:v000016D5d00007029* + ID_MODEL_FROM_DATABASE=AP342 14-bit, 12-Channel Isolated Simultaneous Conversion Analog Input Module + +pci:v000016D5d0000702A* + ID_MODEL_FROM_DATABASE=AP226 12-Bit, 8-Channel Isolated Analog Output Module + +pci:v000016D5d0000702B* + ID_MODEL_FROM_DATABASE=AP236 16-Bit, 8-Channel Isolated Analog Output Module + +pci:v000016D5d00007031* + ID_MODEL_FROM_DATABASE=AP441-1: 32-Channel Isolated Digital Input Module + +pci:v000016D5d00007032* + ID_MODEL_FROM_DATABASE=AP441-2: 32-Channel Isolated Digital Input Module + +pci:v000016D5d00007033* + ID_MODEL_FROM_DATABASE=AP441-3: 32-Channel Isolated Digital Input Module + +pci:v000016D5d00007042* + ID_MODEL_FROM_DATABASE=AP482 Counter Timer Module with TTL Level Input/Output + +pci:v000016D5d00007043* + ID_MODEL_FROM_DATABASE=AP483 Counter Timer Module with TTL Level and RS422 Input/Output + +pci:v000016D5d00007044* + ID_MODEL_FROM_DATABASE=AP484 Counter Timer Module with RS422 Input/Output + +pci:v000016D5d00007051* + ID_MODEL_FROM_DATABASE=APA7-501 Reconfigurable Artix-7 52,160 Cell FPGA module 48 TTL channels + +pci:v000016D5d00007052* + ID_MODEL_FROM_DATABASE=APA7-502 Reconfigurable Artix-7 52,160 Cell FPGA module 24 RS485 channels + +pci:v000016D5d00007053* + ID_MODEL_FROM_DATABASE=APA7-503 Reconfigurable Artix-7 52,160 Cell FPGA module 24 TTL & 12 RS485 channels + +pci:v000016D5d00007054* + ID_MODEL_FROM_DATABASE=APA7-504 Reconfigurable Artix-7 52,160 Cell FPGA module 24 LVDS channels + +pci:v000016DA* + ID_VENDOR_FROM_DATABASE=Advantech Co., Ltd. + +pci:v000016DAd00000011* + ID_MODEL_FROM_DATABASE=INES GPIB-PCI + +pci:v000016DF* + ID_VENDOR_FROM_DATABASE=PIKA Technologies Inc. + +pci:v000016E2* + ID_VENDOR_FROM_DATABASE=Geotest-MTS + +pci:v000016E3* + ID_VENDOR_FROM_DATABASE=European Space Agency + +pci:v000016E3d00001E0F* + ID_MODEL_FROM_DATABASE=LEON2FT Processor + +pci:v000016E5* + ID_VENDOR_FROM_DATABASE=Intellon Corp. + +pci:v000016E5d00006000* + ID_MODEL_FROM_DATABASE=INT6000 Ethernet-to-Powerline Bridge [HomePlug AV] + +pci:v000016E5d00006300* + ID_MODEL_FROM_DATABASE=INT6300 Ethernet-to-Powerline Bridge [HomePlug AV] + +pci:v000016EC* + ID_VENDOR_FROM_DATABASE=U.S. Robotics + +pci:v000016ECd000000ED* + ID_MODEL_FROM_DATABASE=USR997900 + +pci:v000016ECd00000116* + ID_MODEL_FROM_DATABASE=USR997902 10/100/1000 Mbps PCI Network Card + +pci:v000016ECd00002F00* + ID_MODEL_FROM_DATABASE=USR5660A (USR265660A, USR5660A-BP) 56K PCI Faxmodem + +pci:v000016ECd00003685* + ID_MODEL_FROM_DATABASE=Wireless Access PCI Adapter Model 022415 + +pci:v000016ECd00004320* + ID_MODEL_FROM_DATABASE=USR997904 10/100/1000 64-bit NIC (Marvell Yukon) + +pci:v000016ECd0000AB06* + ID_MODEL_FROM_DATABASE=USR997901A 10/100 Cardbus NIC + +pci:v000016ED* + ID_VENDOR_FROM_DATABASE=Sycron N. V. + +pci:v000016EDd00001001* + ID_MODEL_FROM_DATABASE=UMIO communication card + +pci:v000016F2* + ID_VENDOR_FROM_DATABASE=ETAS GmbH + +pci:v000016F2d00000200* + ID_MODEL_FROM_DATABASE=I/O board + +pci:v000016F2d00000200sv000016F2sd00000010* + ID_MODEL_FROM_DATABASE=I/O board (ES53xx I/O board) + +pci:v000016F3* + ID_VENDOR_FROM_DATABASE=Jetway Information Co., Ltd. + +pci:v000016F4* + ID_VENDOR_FROM_DATABASE=Vweb Corp + +pci:v000016F4d00008000* + ID_MODEL_FROM_DATABASE=VW2010 + +pci:v000016F6* + ID_VENDOR_FROM_DATABASE=VideoTele.com, Inc. + +pci:v00001702* + ID_VENDOR_FROM_DATABASE=Internet Machines Corporation (IMC) + +pci:v00001705* + ID_VENDOR_FROM_DATABASE=Digital First, Inc. + +pci:v0000170B* + ID_VENDOR_FROM_DATABASE=NetOctave + +pci:v0000170Bd00000100* + ID_MODEL_FROM_DATABASE=NSP2000-SSL crypto accelerator + +pci:v0000170C* + ID_VENDOR_FROM_DATABASE=YottaYotta Inc. + +pci:v00001719* + ID_VENDOR_FROM_DATABASE=EZChip Technologies + +pci:v00001719d00001000* + ID_MODEL_FROM_DATABASE=NPA Access Network Processor Family + +pci:v00001725* + ID_VENDOR_FROM_DATABASE=Vitesse Semiconductor + +pci:v00001725d00007174* + ID_MODEL_FROM_DATABASE=VSC7174 PCI/PCI-X Serial ATA Host Bus Controller + +pci:v0000172A* + ID_VENDOR_FROM_DATABASE=Accelerated Encryption + +pci:v0000172Ad000013C8* + ID_MODEL_FROM_DATABASE=AEP SureWare Runner 1000V3 + +pci:v00001734* + ID_VENDOR_FROM_DATABASE=Fujitsu Technology Solutions + +pci:v00001735* + ID_VENDOR_FROM_DATABASE=Aten International Co. Ltd. + +pci:v00001737* + ID_VENDOR_FROM_DATABASE=Linksys + +pci:v00001737d00000029* + ID_MODEL_FROM_DATABASE=WPG54G ver. 4 PCI Card + +pci:v00001737d00001032* + ID_MODEL_FROM_DATABASE=Gigabit Network Adapter + +pci:v00001737d00001032sv00001737sd00000015* + ID_MODEL_FROM_DATABASE=Gigabit Network Adapter (EG1032 v2 Instant Gigabit Network Adapter) + +pci:v00001737d00001032sv00001737sd00000024* + ID_MODEL_FROM_DATABASE=Gigabit Network Adapter (EG1032 v3 Instant Gigabit Network Adapter) + +pci:v00001737d00001064* + ID_MODEL_FROM_DATABASE=Gigabit Network Adapter + +pci:v00001737d00001064sv00001737sd00000016* + ID_MODEL_FROM_DATABASE=Gigabit Network Adapter (EG1064 v2 Instant Gigabit Network Adapter) + +pci:v00001737d0000AB08* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v00001737d0000AB09* + ID_MODEL_FROM_DATABASE=21x4x DEC-Tulip compatible 10/100 Ethernet + +pci:v0000173B* + ID_VENDOR_FROM_DATABASE=Altima (nee Broadcom) + +pci:v0000173Bd000003E8* + ID_MODEL_FROM_DATABASE=AC1000 Gigabit Ethernet + +pci:v0000173Bd000003E9* + ID_MODEL_FROM_DATABASE=AC1001 Gigabit Ethernet + +pci:v0000173Bd000003EA* + ID_MODEL_FROM_DATABASE=AC9100 Gigabit Ethernet + +pci:v0000173Bd000003EAsv0000173Bsd00000001* + ID_MODEL_FROM_DATABASE=AC9100 Gigabit Ethernet (AC1002) + +pci:v0000173Bd000003EB* + ID_MODEL_FROM_DATABASE=AC1003 Gigabit Ethernet + +pci:v00001743* + ID_VENDOR_FROM_DATABASE=Peppercon AG + +pci:v00001743d00008139* + ID_MODEL_FROM_DATABASE=ROL/F-100 Fast Ethernet Adapter with ROL + +pci:v00001745* + ID_VENDOR_FROM_DATABASE=ViXS Systems, Inc. + +pci:v00001745d00002020* + ID_MODEL_FROM_DATABASE=XCode II Series + +pci:v00001745d00002100* + ID_MODEL_FROM_DATABASE=XCode 2100 Series + +pci:v00001749* + ID_VENDOR_FROM_DATABASE=RLX Technologies + +pci:v0000174B* + ID_VENDOR_FROM_DATABASE=PC Partner Limited / Sapphire Technology + +pci:v0000174D* + ID_VENDOR_FROM_DATABASE=WellX Telecom SA + +pci:v0000175C* + ID_VENDOR_FROM_DATABASE=AudioScience Inc + +pci:v0000175E* + ID_VENDOR_FROM_DATABASE=Sanera Systems, Inc. + +pci:v00001760* + ID_VENDOR_FROM_DATABASE=TEDIA spol. s r. o. + +pci:v00001760d00000101* + ID_MODEL_FROM_DATABASE=PCD-7004 Digital Bi-Directional Ports PCI Card + +pci:v00001760d00000102* + ID_MODEL_FROM_DATABASE=PCD-7104 Digital Input & Output PCI Card + +pci:v00001760d00000121* + ID_MODEL_FROM_DATABASE=PCT-7303A PC card with IRC counters + +pci:v00001760d00000122* + ID_MODEL_FROM_DATABASE=PCT-7408A PC card with counters and timers + +pci:v00001760d00000123* + ID_MODEL_FROM_DATABASE=PCT-7424 PCI card with standard counters + +pci:v00001760d00000214* + ID_MODEL_FROM_DATABASE=PCT-7424C (F0) PC card with standard counters + +pci:v00001760d00000215* + ID_MODEL_FROM_DATABASE=PCT-7424C (F1) PC card with standard counters + +pci:v00001760d00000216* + ID_MODEL_FROM_DATABASE=PCT-7424E (F0) PC card with standard counters + +pci:v00001760d00000217* + ID_MODEL_FROM_DATABASE=PCT-7424E (F1) PC card with standard counters + +pci:v00001760d00000303* + ID_MODEL_FROM_DATABASE=PCD-7006C Digital Input & Output PCI Card + +pci:v00001760d0000FF00* + ID_MODEL_FROM_DATABASE=CTU CAN FD PCIe Card + +pci:v00001761* + ID_VENDOR_FROM_DATABASE=Pickering Interfaces Ltd + +pci:v00001771* + ID_VENDOR_FROM_DATABASE=InnoVISION Multimedia Ltd. + +pci:v00001775* + ID_VENDOR_FROM_DATABASE=General Electric + +pci:v0000177D* + ID_VENDOR_FROM_DATABASE=Cavium, Inc. + +pci:v0000177Dd00000001* + ID_MODEL_FROM_DATABASE=Nitrox XL N1 + +pci:v0000177Dd00000003* + ID_MODEL_FROM_DATABASE=Nitrox XL N1 Lite + +pci:v0000177Dd00000004* + ID_MODEL_FROM_DATABASE=Octeon (and older) FIPS + +pci:v0000177Dd00000005* + ID_MODEL_FROM_DATABASE=Octeon CN38XX Network Processor Pass 3.x + +pci:v0000177Dd00000006* + ID_MODEL_FROM_DATABASE=RoHS + +pci:v0000177Dd00000010* + ID_MODEL_FROM_DATABASE=Nitrox XL NPX + +pci:v0000177Dd00000020* + ID_MODEL_FROM_DATABASE=Octeon CN31XX Network Processor + +pci:v0000177Dd00000030* + ID_MODEL_FROM_DATABASE=Octeon CN30XX Network Processor + +pci:v0000177Dd00000040* + ID_MODEL_FROM_DATABASE=Octeon CN58XX Network Processor + +pci:v0000177Dd00000050* + ID_MODEL_FROM_DATABASE=Octeon CN57XX Network Processor (CN54XX/CN55XX/CN56XX) + +pci:v0000177Dd00000070* + ID_MODEL_FROM_DATABASE=Octeon CN50XX Network Processor + +pci:v0000177Dd00000080* + ID_MODEL_FROM_DATABASE=Octeon CN52XX Network Processor + +pci:v0000177Dd00000090* + ID_MODEL_FROM_DATABASE=Octeon II CN63XX Network Processor + +pci:v0000177Dd00000091* + ID_MODEL_FROM_DATABASE=Octeon II CN68XX Network Processor + +pci:v0000177Dd00000092* + ID_MODEL_FROM_DATABASE=Octeon II CN65XX Network Processor + +pci:v0000177Dd00000093* + ID_MODEL_FROM_DATABASE=Octeon II CN61XX Network Processor + +pci:v0000177Dd00000094* + ID_MODEL_FROM_DATABASE=Octeon Fusion CNF71XX Cell processor + +pci:v0000177Dd00000095* + ID_MODEL_FROM_DATABASE=Octeon III CN78XX Network Processor + +pci:v0000177Dd00000096* + ID_MODEL_FROM_DATABASE=Octeon III CN70XX Network Processor + +pci:v0000177Dd00009700* + ID_MODEL_FROM_DATABASE=Octeon III CN73XX Network Processor + +pci:v0000177Dd00009702* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] Intelligent Adapter + +pci:v0000177Dd00009702sv0000177Dsd00000003* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] Intelligent Adapter (CN2350 [LiquidIO II] 2-port 10GbE Intelligent adapter) + +pci:v0000177Dd00009702sv0000177Dsd00000004* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] Intelligent Adapter (CN2350 [LiquidIO II] 2-port 10GbE Intelligent adapter) + +pci:v0000177Dd00009702sv0000177Dsd00000005* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] Intelligent Adapter (CN2360 [LiquidIO II] 2-port 10GbE Intelligent adapter) + +pci:v0000177Dd00009702sv0000177Dsd00000006* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] Intelligent Adapter (CN2360 [LiquidIO II] 2-port 25GbE Intelligent adapter) + +pci:v0000177Dd00009702sv0000177Dsd00000007* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] Intelligent Adapter (CN2350 [LiquidIO II] 2-port 25GbE Intelligent adapter) + +pci:v0000177Dd00009702sv0000177Dsd00000008* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] Intelligent Adapter (CN2350 [LiquidIO II] 2-port 10GbE SFP+ Intelligent adapter) + +pci:v0000177Dd00009702sv0000177Dsd00000009* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] Intelligent Adapter (CN2360 [LiquidIO II] 2-port 10GbE SFP+ Intelligent adapter) + +pci:v0000177Dd00009702sv0000177Dsd0000000A* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] Intelligent Adapter (CN2350 [LiquidIO II] 2-port 10GBASE-T Intelligent adapter) + +pci:v0000177Dd00009702sv0000177Dsd0000000B* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] Intelligent Adapter (CN2360 [LiquidIO II] 2-port 10GBASE-T Intelligent adapter) + +pci:v0000177Dd00009703* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] NVMe Controller + +pci:v0000177Dd00009712* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] SRIOV Virtual Function + +pci:v0000177Dd00009712sv0000177Dsd00000003* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] SRIOV Virtual Function (CN2350 [LiquidIO II] 2-port 10GbE SRIOV Virtual Function) + +pci:v0000177Dd00009712sv0000177Dsd00000004* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] SRIOV Virtual Function (CN2350 [LiquidIO II] 2-port 10GbE SRIOV Virtual Function) + +pci:v0000177Dd00009712sv0000177Dsd00000005* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] SRIOV Virtual Function (CN2360 [LiquidIO II] 2-port 10GbE SRIOV Virtual Function) + +pci:v0000177Dd00009712sv0000177Dsd00000006* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] SRIOV Virtual Function (CN2360 [LiquidIO II] 2-port 25GbE SRIOV Virtual Function) + +pci:v0000177Dd00009712sv0000177Dsd00000007* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] SRIOV Virtual Function (CN2350 [LiquidIO II] 2-port 25GbE SRIOV Virtual Function) + +pci:v0000177Dd00009713* + ID_MODEL_FROM_DATABASE=CN23XX [LiquidIO II] NVMe SRIOV Virtual Function + +pci:v0000177Dd00009800* + ID_MODEL_FROM_DATABASE=Octeon Fusion CNF75XX Processor + +pci:v0000177Dd0000A001* + ID_MODEL_FROM_DATABASE=ThunderX MRML(Master RML Bridge to RSL devices) + +pci:v0000177Dd0000A002* + ID_MODEL_FROM_DATABASE=THUNDERX PCC Bridge + +pci:v0000177Dd0000A002sv0000177Dsd0000A102* + ID_MODEL_FROM_DATABASE=THUNDERX PCC Bridge (CN88XX PCC Bridge) + +pci:v0000177Dd0000A008* + ID_MODEL_FROM_DATABASE=THUNDERX SMMU + +pci:v0000177Dd0000A008sv0000177Dsd0000A108* + ID_MODEL_FROM_DATABASE=THUNDERX SMMU (CN88XX SMMU) + +pci:v0000177Dd0000A009* + ID_MODEL_FROM_DATABASE=THUNDERX Generic Interrupt Controller + +pci:v0000177Dd0000A00A* + ID_MODEL_FROM_DATABASE=THUNDERX GPIO Controller + +pci:v0000177Dd0000A00B* + ID_MODEL_FROM_DATABASE=THUNDERX MPI / SPI Controller + +pci:v0000177Dd0000A00C* + ID_MODEL_FROM_DATABASE=THUNDERX MIO-PTP Controller + +pci:v0000177Dd0000A00D* + ID_MODEL_FROM_DATABASE=THUNDERX MIX Network Controller + +pci:v0000177Dd0000A00E* + ID_MODEL_FROM_DATABASE=THUNDERX Reset Controller + +pci:v0000177Dd0000A00F* + ID_MODEL_FROM_DATABASE=THUNDERX UART Controller + +pci:v0000177Dd0000A010* + ID_MODEL_FROM_DATABASE=THUNDERX eMMC/SD Controller + +pci:v0000177Dd0000A011* + ID_MODEL_FROM_DATABASE=THUNDERX MIO-BOOT Controller + +pci:v0000177Dd0000A012* + ID_MODEL_FROM_DATABASE=THUNDERX TWSI / I2C Controller + +pci:v0000177Dd0000A013* + ID_MODEL_FROM_DATABASE=THUNDERX CCPI (Multi-node connect) + +pci:v0000177Dd0000A014* + ID_MODEL_FROM_DATABASE=THUNDERX Voltage Regulator Module + +pci:v0000177Dd0000A015* + ID_MODEL_FROM_DATABASE=THUNDERX PCIe Switch Logic Interface + +pci:v0000177Dd0000A016* + ID_MODEL_FROM_DATABASE=THUNDERX Key Memory + +pci:v0000177Dd0000A017* + ID_MODEL_FROM_DATABASE=THUNDERX GTI (Global System Timers) + +pci:v0000177Dd0000A018* + ID_MODEL_FROM_DATABASE=THUNDERX Random Number Generator + +pci:v0000177Dd0000A019* + ID_MODEL_FROM_DATABASE=THUNDERX DFA + +pci:v0000177Dd0000A01A* + ID_MODEL_FROM_DATABASE=THUNDERX Zip Coprocessor + +pci:v0000177Dd0000A01B* + ID_MODEL_FROM_DATABASE=THUNDERX xHCI USB Controller + +pci:v0000177Dd0000A01C* + ID_MODEL_FROM_DATABASE=THUNDERX AHCI SATA Controller + +pci:v0000177Dd0000A01Csv0000177Dsd0000A11C* + ID_MODEL_FROM_DATABASE=THUNDERX AHCI SATA Controller (CN88XX AHCI SATA Controller) + +pci:v0000177Dd0000A01D* + ID_MODEL_FROM_DATABASE=THUNDERX RAID Coprocessor + +pci:v0000177Dd0000A01E* + ID_MODEL_FROM_DATABASE=THUNDERX Network Interface Controller + +pci:v0000177Dd0000A01F* + ID_MODEL_FROM_DATABASE=THUNDERX Traffic Network Switch + +pci:v0000177Dd0000A020* + ID_MODEL_FROM_DATABASE=THUNDERX PEM (PCI Express Interface) + +pci:v0000177Dd0000A021* + ID_MODEL_FROM_DATABASE=THUNDERX L2C (Level-2 Cache Controller) + +pci:v0000177Dd0000A022* + ID_MODEL_FROM_DATABASE=THUNDERX LMC (DRAM Controller) + +pci:v0000177Dd0000A023* + ID_MODEL_FROM_DATABASE=THUNDERX OCLA (On-Chip Logic Analyzer) + +pci:v0000177Dd0000A024* + ID_MODEL_FROM_DATABASE=THUNDERX OSM + +pci:v0000177Dd0000A025* + ID_MODEL_FROM_DATABASE=THUNDERX GSER (General Serializer/Deserializer) + +pci:v0000177Dd0000A026* + ID_MODEL_FROM_DATABASE=THUNDERX BGX (Common Ethernet Interface) + +pci:v0000177Dd0000A027* + ID_MODEL_FROM_DATABASE=THUNDERX IOBN + +pci:v0000177Dd0000A029* + ID_MODEL_FROM_DATABASE=THUNDERX NCSI (Network Controller Sideband Interface) + +pci:v0000177Dd0000A02A* + ID_MODEL_FROM_DATABASE=ThunderX SGPIO (Serial GPIO controller for SATA disk lights) + +pci:v0000177Dd0000A02B* + ID_MODEL_FROM_DATABASE=THUNDERX SMI / MDIO Controller + +pci:v0000177Dd0000A02C* + ID_MODEL_FROM_DATABASE=THUNDERX DAP (Debug Access Port) + +pci:v0000177Dd0000A02D* + ID_MODEL_FROM_DATABASE=THUNDERX PCIERC (PCIe Root Complex) + +pci:v0000177Dd0000A02E* + ID_MODEL_FROM_DATABASE=ThunderX L2C-TAD (Level 2 cache tag and data) + +pci:v0000177Dd0000A02F* + ID_MODEL_FROM_DATABASE=THUNDERX L2C-CBC + +pci:v0000177Dd0000A030* + ID_MODEL_FROM_DATABASE=THUNDERX L2C-MCI + +pci:v0000177Dd0000A031* + ID_MODEL_FROM_DATABASE=THUNDERX MIO-FUS (Fuse Access Controller) + +pci:v0000177Dd0000A032* + ID_MODEL_FROM_DATABASE=THUNDERX FUSF (Fuse Controller) + +pci:v0000177Dd0000A033* + ID_MODEL_FROM_DATABASE=THUNDERX Random Number Generator virtual function + +pci:v0000177Dd0000A034* + ID_MODEL_FROM_DATABASE=THUNDERX Network Interface Controller virtual function + +pci:v0000177Dd0000A035* + ID_MODEL_FROM_DATABASE=THUNDERX Parallel Bus + +pci:v0000177Dd0000A036* + ID_MODEL_FROM_DATABASE=ThunderX RAD (RAID acceleration engine) virtual function + +pci:v0000177Dd0000A037* + ID_MODEL_FROM_DATABASE=THUNDERX ZIP virtual function + +pci:v0000177Dd0000A040* + ID_MODEL_FROM_DATABASE=THUNDERX CPT Cryptographic Accelerator + +pci:v0000177Dd0000A100* + ID_MODEL_FROM_DATABASE=THUNDERX CN88XX 48 core SoC + +pci:v0000177Dd0000A200* + ID_MODEL_FROM_DATABASE=OCTEON TX CN81XX/CN80XX + +pci:v0000177Dd0000A300* + ID_MODEL_FROM_DATABASE=OCTEON TX CN83XX + +pci:v0000177Dd0000AF00* + ID_MODEL_FROM_DATABASE=CN99xx [ThunderX2] Integrated PCI Host bridge + +pci:v0000177Dd0000AF84* + ID_MODEL_FROM_DATABASE=CN99xx [ThunderX2] Integrated PCI Express RP Bridge + +pci:v00001787* + ID_VENDOR_FROM_DATABASE=Hightech Information System Ltd. + +pci:v00001789* + ID_VENDOR_FROM_DATABASE=Ennyah Technologies Corp. + +pci:v00001796* + ID_VENDOR_FROM_DATABASE=Research Centre Juelich + +pci:v00001796d00000001* + ID_MODEL_FROM_DATABASE=SIS1100 [Gigabit link] + +pci:v00001796d00000002* + ID_MODEL_FROM_DATABASE=HOTlink + +pci:v00001796d00000003* + ID_MODEL_FROM_DATABASE=Counter Timer + +pci:v00001796d00000004* + ID_MODEL_FROM_DATABASE=CAMAC Controller + +pci:v00001796d00000005* + ID_MODEL_FROM_DATABASE=PROFIBUS + +pci:v00001796d00000006* + ID_MODEL_FROM_DATABASE=AMCC HOTlink + +pci:v00001796d00000007* + ID_MODEL_FROM_DATABASE=LVD Cable Bus + +pci:v00001796d00000008* + ID_MODEL_FROM_DATABASE=100MHz, 64bit Sequence Generator based on VirtexII + +pci:v00001796d00000009* + ID_MODEL_FROM_DATABASE=double 14bit-ADC + +pci:v00001796d0000000A* + ID_MODEL_FROM_DATABASE=SIS1100 with N110 TDC + +pci:v00001796d0000000B* + ID_MODEL_FROM_DATABASE=double 14bit-ADC with memory + +pci:v00001796d0000000D* + ID_MODEL_FROM_DATABASE=Synchronisation Slave + +pci:v00001796d0000000E* + ID_MODEL_FROM_DATABASE=SIS1100-eCMC + +pci:v00001796d0000000F* + ID_MODEL_FROM_DATABASE=TDC (GPX) + +pci:v00001796d00000010* + ID_MODEL_FROM_DATABASE=PCIe Counter Timer + +pci:v00001796d00000011* + ID_MODEL_FROM_DATABASE=SIS1100-e single link + +pci:v00001796d00000012* + ID_MODEL_FROM_DATABASE=SIS1100-e quad link + +pci:v00001796d00000013* + ID_MODEL_FROM_DATABASE=4x2.5GHz SFP to 4 lane PCIe bridge + +pci:v00001796d00000014* + ID_MODEL_FROM_DATABASE=SIS1100 with GPX piggy back + +pci:v00001796d00000015* + ID_MODEL_FROM_DATABASE=SIS8100 [Gigabit link, MicroTCA] + +pci:v00001796d00000016* + ID_MODEL_FROM_DATABASE=SIS1100e with 4 lanes + +pci:v00001796d00000017* + ID_MODEL_FROM_DATABASE=Quad 14bit, 50MHz ADC with 2.5GHz SFP + +pci:v00001796d00000018* + ID_MODEL_FROM_DATABASE=SIS8300 4-lane PCI Express, Micro TCA for Physics ADC + +pci:v00001796d00000019* + ID_MODEL_FROM_DATABASE=SIS SIS8300-Lx MTCA.4 Digitizer + +pci:v00001796d0000001A* + ID_MODEL_FROM_DATABASE=100MHz, 64bit Sequence Generator based on VirtexII + +pci:v00001796d0000001C* + ID_MODEL_FROM_DATABASE=Quad 16bit, 150MHz ADC with 2.5GHz SFP + +pci:v00001796d00000030* + ID_MODEL_FROM_DATABASE=100MHz, 64bit Sequence Generator based on Spartan6 + +pci:v00001796d00000031* + ID_MODEL_FROM_DATABASE=200MHz 64bit Sequence Generator based on Spartan7 + +pci:v00001797* + ID_VENDOR_FROM_DATABASE=Intersil Techwell + +pci:v00001797d00005864* + ID_MODEL_FROM_DATABASE=TW5864 multimedia video controller + +pci:v00001797d00006801* + ID_MODEL_FROM_DATABASE=TW6802 multimedia video card + +pci:v00001797d00006802* + ID_MODEL_FROM_DATABASE=TW6802 multimedia other device + +pci:v00001797d00006810* + ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller + +pci:v00001797d00006811* + ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller + +pci:v00001797d00006812* + ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller + +pci:v00001797d00006813* + ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller + +pci:v00001797d00006814* + ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller + +pci:v00001797d00006815* + ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller + +pci:v00001797d00006816* + ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller + +pci:v00001797d00006817* + ID_MODEL_FROM_DATABASE=TW6816 multimedia video controller + +pci:v00001797d00006864* + ID_MODEL_FROM_DATABASE=TW6864 multimedia video controller + +pci:v00001799* + ID_VENDOR_FROM_DATABASE=Belkin + +pci:v00001799d00006001* + ID_MODEL_FROM_DATABASE=F5D6001 Wireless PCI Card [Realtek RTL8180] + +pci:v00001799d00006020* + ID_MODEL_FROM_DATABASE=F5D6020 v3000 Wireless PCMCIA Card [Realtek RTL8180] + +pci:v00001799d00006060* + ID_MODEL_FROM_DATABASE=F5D6060 Wireless PDA Card + +pci:v00001799d0000700F* + ID_MODEL_FROM_DATABASE=F5D7000 v7000 Wireless G Desktop Card [Realtek RTL8185] + +pci:v00001799d0000701F* + ID_MODEL_FROM_DATABASE=F5D7010 v7000 Wireless G Notebook Card [Realtek RTL8185] + +pci:v0000179A* + ID_VENDOR_FROM_DATABASE=id Quantique + +pci:v0000179Ad00000001* + ID_MODEL_FROM_DATABASE=Quantis PCI 16Mbps + +pci:v0000179C* + ID_VENDOR_FROM_DATABASE=Data Patterns + +pci:v0000179Cd00000557* + ID_MODEL_FROM_DATABASE=DP-PCI-557 [PCI 1553B] + +pci:v0000179Cd00000566* + ID_MODEL_FROM_DATABASE=DP-PCI-566 [Intelligent PCI 1553B] + +pci:v0000179Cd00001152* + ID_MODEL_FROM_DATABASE=DP-cPCI-1152 (8-channel Isolated ADC Module) + +pci:v0000179Cd00005031* + ID_MODEL_FROM_DATABASE=DP-CPCI-5031-Synchro Module + +pci:v0000179Cd00005112* + ID_MODEL_FROM_DATABASE=DP-cPCI-5112 [MM-Carrier] + +pci:v0000179Cd00005121* + ID_MODEL_FROM_DATABASE=DP-CPCI-5121-IP Carrier + +pci:v0000179Cd00005211* + ID_MODEL_FROM_DATABASE=DP-CPCI-5211-IP Carrier + +pci:v0000179Cd00005679* + ID_MODEL_FROM_DATABASE=AGE Display Module + +pci:v000017A0* + ID_VENDOR_FROM_DATABASE=Genesys Logic, Inc + +pci:v000017A0d00007163* + ID_MODEL_FROM_DATABASE=GL9701 PCIe to PCI Bridge + +pci:v000017A0d00008083* + ID_MODEL_FROM_DATABASE=GL880 USB 1.1 UHCI controller + +pci:v000017A0d00008084* + ID_MODEL_FROM_DATABASE=GL880 USB 2.0 EHCI controller + +pci:v000017A0d00009750* + ID_MODEL_FROM_DATABASE=GL9750 SD Host Controller + +pci:v000017AA* + ID_VENDOR_FROM_DATABASE=Lenovo + +pci:v000017AAd0000402B* + ID_MODEL_FROM_DATABASE=Intel 82599ES 10Gb 2-port Server Adapter X520-2 + +pci:v000017AB* + ID_VENDOR_FROM_DATABASE=Phillips Components + +pci:v000017AF* + ID_VENDOR_FROM_DATABASE=Hightech Information System Ltd. + +pci:v000017B3* + ID_VENDOR_FROM_DATABASE=Hawking Technologies + +pci:v000017B3d0000AB08* + ID_MODEL_FROM_DATABASE=PN672TX 10/100 Ethernet + +pci:v000017B4* + ID_VENDOR_FROM_DATABASE=Indra Networks, Inc. + +pci:v000017B4d00000011* + ID_MODEL_FROM_DATABASE=WebEnhance 100 GZIP Compression Card + +pci:v000017B4d00000012* + ID_MODEL_FROM_DATABASE=WebEnhance 200 GZIP Compression Card + +pci:v000017B4d00000015* + ID_MODEL_FROM_DATABASE=WebEnhance 300 GZIP Compression Card + +pci:v000017B4d00000016* + ID_MODEL_FROM_DATABASE=StorCompress 300 GZIP Compression Card + +pci:v000017B4d00000017* + ID_MODEL_FROM_DATABASE=StorSecure 300 GZIP Compression and AES Encryption Card + +pci:v000017C0* + ID_VENDOR_FROM_DATABASE=Wistron Corp. + +pci:v000017C2* + ID_VENDOR_FROM_DATABASE=Newisys, Inc. + +pci:v000017CB* + ID_VENDOR_FROM_DATABASE=Qualcomm + +pci:v000017CBd00000001* + ID_MODEL_FROM_DATABASE=AGN100 802.11 a/b/g True MIMO Wireless Card + +pci:v000017CBd00000001sv00001385sd00005C00* + ID_MODEL_FROM_DATABASE=AGN100 802.11 a/b/g True MIMO Wireless Card (WGM511 Pre-N 802.11g Wireless CardBus Adapter) + +pci:v000017CBd00000001sv00001737sd00000045* + ID_MODEL_FROM_DATABASE=AGN100 802.11 a/b/g True MIMO Wireless Card (WMP54GX v1 802.11g Wireless-G PCI Adapter with SRX) + +pci:v000017CBd00000002* + ID_MODEL_FROM_DATABASE=AGN300 802.11 a/b/g True MIMO Wireless Card + +pci:v000017CBd00000002sv00001385sd00006D00* + ID_MODEL_FROM_DATABASE=AGN300 802.11 a/b/g True MIMO Wireless Card (WPNT511 RangeMax 240 Mbps Wireless CardBus Adapter) + +pci:v000017CBd00000002sv00001737sd00000054* + ID_MODEL_FROM_DATABASE=AGN300 802.11 a/b/g True MIMO Wireless Card (WPC54GX4 v1 802.11g Wireless-G Notebook Adapter with SRX400) + +pci:v000017CBd00000400* + ID_MODEL_FROM_DATABASE=Datacenter Technologies QDF2432 PCI Express Root Port + +pci:v000017CBd00000401* + ID_MODEL_FROM_DATABASE=Datacenter Technologies QDF2400 PCI Express Root Port + +pci:v000017CC* + ID_VENDOR_FROM_DATABASE=NetChip Technology, Inc + +pci:v000017CCd00002280* + ID_MODEL_FROM_DATABASE=USB 2.0 + +pci:v000017CD* + ID_VENDOR_FROM_DATABASE=Cadence Design Systems, Inc. + +pci:v000017CF* + ID_VENDOR_FROM_DATABASE=Z-Com, Inc. + +pci:v000017D3* + ID_VENDOR_FROM_DATABASE=Areca Technology Corp. + +pci:v000017D3d00001110* + ID_MODEL_FROM_DATABASE=ARC-1110 4-Port PCI-X to SATA RAID Controller + +pci:v000017D3d00001120* + ID_MODEL_FROM_DATABASE=ARC-1120 8-Port PCI-X to SATA RAID Controller + +pci:v000017D3d00001130* + ID_MODEL_FROM_DATABASE=ARC-1130 12-Port PCI-X to SATA RAID Controller + +pci:v000017D3d00001160* + ID_MODEL_FROM_DATABASE=ARC-1160 16-Port PCI-X to SATA RAID Controller + +pci:v000017D3d00001170* + ID_MODEL_FROM_DATABASE=ARC-1170 24-Port PCI-X to SATA RAID Controller + +pci:v000017D3d00001201* + ID_MODEL_FROM_DATABASE=ARC-1200 2-Port PCI-Express to SATA II RAID Controller + +pci:v000017D3d00001203* + ID_MODEL_FROM_DATABASE=ARC-1203 2/4/8 Port PCIe 2.0 to SATA 6Gb RAID Controller + +pci:v000017D3d00001210* + ID_MODEL_FROM_DATABASE=ARC-1210 4-Port PCI-Express to SATA RAID Controller + +pci:v000017D3d00001214* + ID_MODEL_FROM_DATABASE=ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller + +pci:v000017D3d00001214sv000017D3sd00001214* + ID_MODEL_FROM_DATABASE=ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller (ARC-1214 4-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller) + +pci:v000017D3d00001214sv000017D3sd00001224* + ID_MODEL_FROM_DATABASE=ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller (ARC-1224 8-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller) + +pci:v000017D3d00001214sv000017D3sd00001264* + ID_MODEL_FROM_DATABASE=ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller (ARC-1264 12/16 Port PCIe 2.0 to SATA 6Gb RAID Controller) + +pci:v000017D3d00001214sv000017D3sd00001284* + ID_MODEL_FROM_DATABASE=ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller (ARC-1284 24 Port PCIe 2.0 to SATA 6Gb RAID Controller) + +pci:v000017D3d00001220* + ID_MODEL_FROM_DATABASE=ARC-1220 8-Port PCI-Express to SATA RAID Controller + +pci:v000017D3d00001222* + ID_MODEL_FROM_DATABASE=ARC-1222 8-Port PCI-Express to SAS/SATA II RAID Controller + +pci:v000017D3d00001230* + ID_MODEL_FROM_DATABASE=ARC-1230 12-Port PCI-Express to SATA RAID Controller + +pci:v000017D3d00001260* + ID_MODEL_FROM_DATABASE=ARC-1260 16-Port PCI-Express to SATA RAID Controller + +pci:v000017D3d00001280* + ID_MODEL_FROM_DATABASE=ARC-1280/1280ML 24-Port PCI-Express to SATA II RAID Controller + +pci:v000017D3d00001280sv000017D3sd00001221* + ID_MODEL_FROM_DATABASE=ARC-1280/1280ML 24-Port PCI-Express to SATA II RAID Controller (ARC-1221 8-Port PCI-Express to SATA RAID Controller) + +pci:v000017D3d00001300* + ID_MODEL_FROM_DATABASE=ARC-1300ix-16 16-Port PCI-Express to SAS Non-RAID Host Adapter + +pci:v000017D3d00001320* + ID_MODEL_FROM_DATABASE=ARC-1320 8/16 Port PCIe 2.0 to SAS/SATA 6Gb Non-RAID Host Adapter + +pci:v000017D3d00001330* + ID_MODEL_FROM_DATABASE=ARC-1330 16 Port PCIe 3.0 to SAS/SATA 12Gb Non-RAID Host Adapter + +pci:v000017D3d00001680* + ID_MODEL_FROM_DATABASE=ARC-1680 series PCIe to SAS/SATA 3Gb RAID Controller + +pci:v000017D3d00001680sv000017D3sd00001212* + ID_MODEL_FROM_DATABASE=ARC-1680 series PCIe to SAS/SATA 3Gb RAID Controller (ARC-1212 4-Port PCIe to SAS/SATA II RAID Controller) + +pci:v000017D3d00001680sv000017D3sd00001222* + ID_MODEL_FROM_DATABASE=ARC-1680 series PCIe to SAS/SATA 3Gb RAID Controller (ARC-1222 8-Port PCIe to SAS/SATA 3Gb RAID Controller) + +pci:v000017D3d00001680sv000017D3sd00001680* + ID_MODEL_FROM_DATABASE=ARC-1680 series PCIe to SAS/SATA 3Gb RAID Controller (ARC-1680 8/12/16/24 Port PCIe to SAS/SATA 3Gb RAID Controller) + +pci:v000017D3d00001880* + ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller + +pci:v000017D3d00001880sv000017D3sd00001213* + ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1213 4-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller) + +pci:v000017D3d00001880sv000017D3sd00001215* + ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1215 4-Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller) + +pci:v000017D3d00001880sv000017D3sd00001216* + ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1216 4-Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller) + +pci:v000017D3d00001880sv000017D3sd00001223* + ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1223 8-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller) + +pci:v000017D3d00001880sv000017D3sd00001225* + ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1225 8-Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller) + +pci:v000017D3d00001880sv000017D3sd00001226* + ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1226 8-Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller) + +pci:v000017D3d00001880sv000017D3sd00001880* + ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1880 8/12/16/24 Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller) + +pci:v000017D3d00001880sv000017D3sd00001882* + ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1882 8/12/16/24 Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller) + +pci:v000017D3d00001880sv000017D3sd00001883* + ID_MODEL_FROM_DATABASE=ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller (ARC-1883 8/12/16/24 Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller) + +pci:v000017D3d00001884* + ID_MODEL_FROM_DATABASE=ARC-1884 series PCIe 3.0 to SAS/SATA 12/6Gb RAID Controller + +pci:v000017D3d0000188A* + ID_MODEL_FROM_DATABASE=ARC-1886 series PCIe 4.0 to NVMe/SAS/SATA 16/12/6Gb RAID Controller + +pci:v000017D5* + ID_VENDOR_FROM_DATABASE=Exar Corp. + +pci:v000017D5d00005731* + ID_MODEL_FROM_DATABASE=Xframe 10-Gigabit Ethernet PCI-X + +pci:v000017D5d00005732* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 + +pci:v000017D5d00005831* + ID_MODEL_FROM_DATABASE=Xframe 10-Gigabit Ethernet PCI-X + +pci:v000017D5d00005831sv0000103Csd000012D5* + ID_MODEL_FROM_DATABASE=Xframe 10-Gigabit Ethernet PCI-X (PCI-X 133MHz 10GbE SR Fiber) + +pci:v000017D5d00005831sv000010A9sd00008020* + ID_MODEL_FROM_DATABASE=Xframe 10-Gigabit Ethernet PCI-X (Single Port 10-Gigabit Ethernet (PCI-X, Fiber)) + +pci:v000017D5d00005831sv000010A9sd00008024* + ID_MODEL_FROM_DATABASE=Xframe 10-Gigabit Ethernet PCI-X (Single Port 10-Gigabit Ethernet (PCI-X, Fiber)) + +pci:v000017D5d00005832* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 + +pci:v000017D5d00005832sv0000103Csd00001337* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (PCI-X 266MHz 10GigE SR [AD385A]) + +pci:v000017D5d00005832sv000010A9sd00008021* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Single Port 10-Gigabit Ethernet II (PCI-X, Fiber)) + +pci:v000017D5d00005832sv000017D5sd00006020* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II SR) + +pci:v000017D5d00005832sv000017D5sd00006021* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II SR, Low Profile) + +pci:v000017D5d00005832sv000017D5sd00006022* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe E SR) + +pci:v000017D5d00005832sv000017D5sd00006420* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II LR) + +pci:v000017D5d00005832sv000017D5sd00006421* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II LR, Low Profile) + +pci:v000017D5d00005832sv000017D5sd00006422* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe E LR) + +pci:v000017D5d00005832sv000017D5sd00006C20* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II CX4) + +pci:v000017D5d00005832sv000017D5sd00006C21* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe II CX4, Low Profile) + +pci:v000017D5d00005832sv000017D5sd00006C22* + ID_MODEL_FROM_DATABASE=Xframe II 10-Gigabit Ethernet PCI-X 2.0 (Xframe E CX4) + +pci:v000017D5d00005833* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe + +pci:v000017D5d00005833sv000017D5sd00006030* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3110 Single Port SR) + +pci:v000017D5d00005833sv000017D5sd00006031* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3120 Dual Port SR) + +pci:v000017D5d00005833sv000017D5sd00006430* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3110 Single Port LR) + +pci:v000017D5d00005833sv000017D5sd00006431* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3120 Dual Port LR) + +pci:v000017D5d00005833sv000017D5sd00007030* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3110 Single Port LRM) + +pci:v000017D5d00005833sv000017D5sd00007031* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3120 Dual Port LRM) + +pci:v000017D5d00005833sv000017D5sd00007430* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3110 Single Port 10GBase-T) + +pci:v000017D5d00005833sv000017D5sd00007431* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3120 Dual Port 10GBase-T) + +pci:v000017D5d00005833sv000017D5sd00007830* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3110 Single Port 10GBase-CR) + +pci:v000017D5d00005833sv000017D5sd00007831* + ID_MODEL_FROM_DATABASE=X3100 Series 10 Gigabit Ethernet PCIe (X3120 Dual Port 10GBase-CR) + +pci:v000017DB* + ID_VENDOR_FROM_DATABASE=Cray Inc + +pci:v000017DBd00000101* + ID_MODEL_FROM_DATABASE=XT Series [Seastar] 3D Toroidal Router + +pci:v000017DE* + ID_VENDOR_FROM_DATABASE=KWorld Computer Co. Ltd. + +pci:v000017DF* + ID_VENDOR_FROM_DATABASE=Dini Group + +pci:v000017DFd00001864* + ID_MODEL_FROM_DATABASE=Virtex4 PCI Board w/ QL5064 Bridge [DN7000K10PCI/DN8000K10PCI/DN8000K10PSX/NOTUS] + +pci:v000017DFd00001865* + ID_MODEL_FROM_DATABASE=Virtex4 ASIC Emulator [DN8000K10PCIe] + +pci:v000017DFd00001866* + ID_MODEL_FROM_DATABASE=Virtex4 ASIC Emulator Cable Connection [DN8000K10PCI] + +pci:v000017DFd00001867* + ID_MODEL_FROM_DATABASE=Virtex4 ASIC Emulator Cable Connection [DN8000K10PCIe] + +pci:v000017DFd00001868* + ID_MODEL_FROM_DATABASE=Virtex4 ASIC Emulator [DN8000K10PCIe-8] + +pci:v000017DFd00001900* + ID_MODEL_FROM_DATABASE=Virtex5 PCIe ASIC Emulator [DN9000K10PCIe8T/DN9002K10PCIe8T/DN9200K10PCIe8T/DN7006K10PCIe8T/DN7406K10PCIe8T] + +pci:v000017DFd00001901* + ID_MODEL_FROM_DATABASE=Virtex5 PCIe ASIC Emulator Large BARs [DN9000K10PCIe8T/DN9002K10PCIe8T/DN9200K10PCIe8T/DN7006K10PCIe8T/DN7406K10PCIe8T] + +pci:v000017DFd00001902* + ID_MODEL_FROM_DATABASE=Virtex5 PCIe ASIC Emulator Low Power [Interceptor] + +pci:v000017DFd00001903* + ID_MODEL_FROM_DATABASE=Spartan6 PCIe FPGA Accelerator Board [DNBFCS12PCIe] + +pci:v000017DFd00001904* + ID_MODEL_FROM_DATABASE=Virtex6 PCIe ASIC Emulation Board [DNDUALV6_PCIe4] + +pci:v000017DFd00001905* + ID_MODEL_FROM_DATABASE=Virtex6 PCIe ASIC Emulation Board [DNV6F6PCIe] + +pci:v000017DFd00001906* + ID_MODEL_FROM_DATABASE=Virtex6 PCIe ASIC Emulation Board [DN2076K10] + +pci:v000017DFd00001907* + ID_MODEL_FROM_DATABASE=Virtex6 PCIe ASIC Emulation Board [DNV6F2PCIe] + +pci:v000017DFd00001908* + ID_MODEL_FROM_DATABASE=Virtex6 PCIe ASIC Emulation Board Large BARs[DNV6F2PCIe] + +pci:v000017DFd00001909* + ID_MODEL_FROM_DATABASE=Kintex7 PCIe FPGA Accelerator Board [DNK7F5PCIe] + +pci:v000017DFd0000190A* + ID_MODEL_FROM_DATABASE=Virtex7 PCIe ASIC Emulation Board [DNV7F1A] + +pci:v000017DFd0000190B* + ID_MODEL_FROM_DATABASE=Stratix5 PCIe ASIC Emulation Board [DNS5GXF2] + +pci:v000017DFd0000190C* + ID_MODEL_FROM_DATABASE=Virtex7 PCIe ASIC Emulation Board [DNV7F2A] + +pci:v000017DFd0000190D* + ID_MODEL_FROM_DATABASE=Virtex7 PCIe ASIC Emulation Board [DNV7F4A] + +pci:v000017DFd0000190E* + ID_MODEL_FROM_DATABASE=Virtex7 PCIe ASIC Emulation Board [DNV7F2B] + +pci:v000017DFd0000190F* + ID_MODEL_FROM_DATABASE=KintexUS PCIe MainRef Design [DNPCIE_40G_KU_LL] + +pci:v000017DFd00001910* + ID_MODEL_FROM_DATABASE=VirtexUS ASIC Emulation Board [DNVUF4A] + +pci:v000017DFd00001911* + ID_MODEL_FROM_DATABASE=VirtexUS PCIe ASIC Emulation Board [DNVU_F2PCIe] + +pci:v000017DFd00001912* + ID_MODEL_FROM_DATABASE=KintexUS PCIe MainRef Design [DNPCIe_40G_KU_LL_QSFP] + +pci:v000017DFd00001913* + ID_MODEL_FROM_DATABASE=VirtexUS ASIC Emulation Board [DNVUF1A] + +pci:v000017DFd00001914* + ID_MODEL_FROM_DATABASE=VirtexUS ASIC Emulation Board [DNVUF2A] + +pci:v000017DFd00001915* + ID_MODEL_FROM_DATABASE=Arria10 PCIe MainRef Design [DNPCIe_80G_A10_LL] + +pci:v000017DFd00001916* + ID_MODEL_FROM_DATABASE=VirtexUS PCIe Accelerator Board [DNVUF2_HPC_PCIe] + +pci:v000017DFd00001917* + ID_MODEL_FROM_DATABASE=UltrascalePlus PCIe Accelerator Board [DNPCIe_400G_VU_LL] + +pci:v000017DFd00001918* + ID_MODEL_FROM_DATABASE=VirtexUS+ ASIC Emulation Board [DNVUPF4A] + +pci:v000017DFd00001919* + ID_MODEL_FROM_DATABASE=UltrascalePlus PCIe Accelerator Board [DNPCIe_400G_VUP_HBM_LL] + +pci:v000017DFd00001A00* + ID_MODEL_FROM_DATABASE=Virtex6 PCIe DMA Netlist Design + +pci:v000017DFd00001A01* + ID_MODEL_FROM_DATABASE=Virtex6 PCIe Darklite Design [DNPCIe_HXT_10G_LL] + +pci:v000017DFd00001A02* + ID_MODEL_FROM_DATABASE=Virtex7 PCIe DMA Netlist Design + +pci:v000017DFd00001A03* + ID_MODEL_FROM_DATABASE=Kintex7 PCIe Darklite Design [DNPCIe_K7_10G_LL] + +pci:v000017DFd00001A05* + ID_MODEL_FROM_DATABASE=Stratix5 PCIe Darklite Design [DNS5GX_F2] + +pci:v000017DFd00001A06* + ID_MODEL_FROM_DATABASE=VirtexUS PCIe DMA Netlist Design + +pci:v000017DFd00001A07* + ID_MODEL_FROM_DATABASE=KintexUS PCIe Darklite Design [DNPCIe_40G_KU_LL] + +pci:v000017DFd00001A08* + ID_MODEL_FROM_DATABASE=KintexUS PCIe Darklite Design [DNPCIe_40G_KU_LL_QSFP] + +pci:v000017DFd00001A09* + ID_MODEL_FROM_DATABASE=Arria10 PCIe Darklite Design [DNPCIe_80G_A10_LL] + +pci:v000017DFd00001A0A* + ID_MODEL_FROM_DATABASE=VirtexUS PCIe Darklite Design [DNVUF2_HPC_PCIe] + +pci:v000017DFd00001A0B* + ID_MODEL_FROM_DATABASE=UltrascalePlus PCIe Darklite Design [DNPCIe_400G_VU_LL] + +pci:v000017DFd00001A0C* + ID_MODEL_FROM_DATABASE=KintexUS PCIe DRAM Packet Capture Design [DNPCIe_40G_KU_LL] + +pci:v000017DFd00001A0D* + ID_MODEL_FROM_DATABASE=KintexUS PCIe DRAM Packet Capture Design [DNPCIe_40G_KU_LL_2QSFP] + +pci:v000017DFd00001A0E* + ID_MODEL_FROM_DATABASE=UltrascalePlus PCIe Darklite Design [DNPCIe_400G_VUP_HBM_LL] + +pci:v000017E4* + ID_VENDOR_FROM_DATABASE=Sectra AB + +pci:v000017E4d00000001* + ID_MODEL_FROM_DATABASE=KK671 Cardbus encryption board + +pci:v000017E4d00000002* + ID_MODEL_FROM_DATABASE=KK672 Cardbus encryption board + +pci:v000017E6* + ID_VENDOR_FROM_DATABASE=MaxLinear + +pci:v000017E6d00000010* + ID_MODEL_FROM_DATABASE=EN2010 [c.Link] MoCA Network Controller (Coax, PCI interface) + +pci:v000017E6d00000011* + ID_MODEL_FROM_DATABASE=EN2010 [c.Link] MoCA Network Controller (Coax, MPEG interface) + +pci:v000017E6d00000021* + ID_MODEL_FROM_DATABASE=EN2210 [c.Link] MoCA Network Controller (Coax) + +pci:v000017E6d00000025* + ID_MODEL_FROM_DATABASE=EN2510 [c.Link] MoCA Network Controller (Coax, PCIe interface) + +pci:v000017E6d00000027* + ID_MODEL_FROM_DATABASE=EN2710 [c.Link] MoCA 2.0 Network Controller (Coax, PCIe interface) + +pci:v000017E6d00003700* + ID_MODEL_FROM_DATABASE=MoCA 2.0 Network Controller (Coax, PCIe interface) + +pci:v000017E6d00003710* + ID_MODEL_FROM_DATABASE=MoCA 2.5 Network Controller (Coax, PCIe interface) + +pci:v000017EE* + ID_VENDOR_FROM_DATABASE=Connect Components Ltd + +pci:v000017F2* + ID_VENDOR_FROM_DATABASE=Albatron Corp. + +pci:v000017F3* + ID_VENDOR_FROM_DATABASE=RDC Semiconductor, Inc. + +pci:v000017F3d00001010* + ID_MODEL_FROM_DATABASE=R1010 IDE Controller + +pci:v000017F3d00001011* + ID_MODEL_FROM_DATABASE=R1011 IDE Controller + +pci:v000017F3d00001012* + ID_MODEL_FROM_DATABASE=R1012 IDE Controller + +pci:v000017F3d00001031* + ID_MODEL_FROM_DATABASE=PCI/PCI-X to PCI-E Bridge + +pci:v000017F3d00002012* + ID_MODEL_FROM_DATABASE=M2012/R3308 VGA-compatible graphics adapter + +pci:v000017F3d00006020* + ID_MODEL_FROM_DATABASE=R6020 North Bridge + +pci:v000017F3d00006021* + ID_MODEL_FROM_DATABASE=R6021 Host Bridge + +pci:v000017F3d00006030* + ID_MODEL_FROM_DATABASE=R6030 ISA Bridge + +pci:v000017F3d00006031* + ID_MODEL_FROM_DATABASE=R6031 ISA Bridge + +pci:v000017F3d00006040* + ID_MODEL_FROM_DATABASE=R6040 MAC Controller + +pci:v000017F3d00006060* + ID_MODEL_FROM_DATABASE=R6060 USB 1.1 Controller + +pci:v000017F3d00006061* + ID_MODEL_FROM_DATABASE=R6061 USB 2.0 Controller + +pci:v000017F7* + ID_VENDOR_FROM_DATABASE=Topdek Semiconductor Inc. + +pci:v000017F9* + ID_VENDOR_FROM_DATABASE=Gemtek Technology Co., Ltd + +pci:v000017FC* + ID_VENDOR_FROM_DATABASE=IOGEAR, Inc. + +pci:v000017FE* + ID_VENDOR_FROM_DATABASE=InProComm Inc. + +pci:v000017FEd00002120* + ID_MODEL_FROM_DATABASE=IPN 2120 802.11b + +pci:v000017FEd00002120sv00001737sd00000020* + ID_MODEL_FROM_DATABASE=IPN 2120 802.11b (WMP11 v4 802.11b Wireless-B PCI Adapter) + +pci:v000017FEd00002220* + ID_MODEL_FROM_DATABASE=IPN 2220 802.11g + +pci:v000017FEd00002220sv00001468sd00000305* + ID_MODEL_FROM_DATABASE=IPN 2220 802.11g (T60N871 802.11g Mini PCI Wireless Adapter) + +pci:v000017FEd00002220sv00001737sd00000029* + ID_MODEL_FROM_DATABASE=IPN 2220 802.11g (WPC54G v4 802.11g Wireless-G Notebook Adapter) + +pci:v000017FF* + ID_VENDOR_FROM_DATABASE=Benq Corporation + +pci:v00001800* + ID_VENDOR_FROM_DATABASE=Qualcore Logic Inc. + +pci:v00001800d00001100* + ID_MODEL_FROM_DATABASE=Nanospeed Trading Gateway + +pci:v00001803* + ID_VENDOR_FROM_DATABASE=ProdaSafe GmbH + +pci:v00001804* + ID_VENDOR_FROM_DATABASE=Ralink corp. (wrong ID) + +pci:v00001804d00003060* + ID_MODEL_FROM_DATABASE=RT3060 Wireless 802.11n 1T/1R + +pci:v00001805* + ID_VENDOR_FROM_DATABASE=Euresys S.A. + +pci:v00001809* + ID_VENDOR_FROM_DATABASE=Lumanate, Inc. + +pci:v0000180C* + ID_VENDOR_FROM_DATABASE=IEI Integration Corp + +pci:v00001813* + ID_VENDOR_FROM_DATABASE=Ambient Technologies Inc + +pci:v00001813d00004000* + ID_MODEL_FROM_DATABASE=HaM controllerless modem + +pci:v00001813d00004000sv000016BEsd00000001* + ID_MODEL_FROM_DATABASE=HaM controllerless modem (V9x HAM Data Fax Modem) + +pci:v00001813d00004100* + ID_MODEL_FROM_DATABASE=HaM plus Data Fax Modem + +pci:v00001813d00004100sv000016BEsd00000002* + ID_MODEL_FROM_DATABASE=HaM plus Data Fax Modem (V9x HAM 1394) + +pci:v00001814* + ID_VENDOR_FROM_DATABASE=Ralink corp. + +pci:v00001814d00000101* + ID_MODEL_FROM_DATABASE=Wireless PCI Adapter RT2400 / RT2460 + +pci:v00001814d00000101sv00001043sd00000127* + ID_MODEL_FROM_DATABASE=Wireless PCI Adapter RT2400 / RT2460 (WiFi-b add-on Card) + +pci:v00001814d00000101sv00001371sd00000010* + ID_MODEL_FROM_DATABASE=Wireless PCI Adapter RT2400 / RT2460 (Minitar MNW2BPCI Wireless PCI Card) + +pci:v00001814d00000101sv00001462sd00006828* + ID_MODEL_FROM_DATABASE=Wireless PCI Adapter RT2400 / RT2460 (PC11B2 (MS-6828) Wireless 11b PCI Card) + +pci:v00001814d00000200* + ID_MODEL_FROM_DATABASE=RT2500 802.11g PCI [PC54G2] + +pci:v00001814d00000201* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg + +pci:v00001814d00000201sv00001043sd0000130F* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (WL-130g) + +pci:v00001814d00000201sv00001186sd00003C00* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (DWL-G650X Wireless 11g CardBus Adapter) + +pci:v00001814d00000201sv00001371sd0000001E* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (CWC-854 Wireless-G CardBus Adapter) + +pci:v00001814d00000201sv00001371sd0000001F* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (CWM-854 Wireless-G Mini PCI Adapter) + +pci:v00001814d00000201sv00001371sd00000020* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (CWP-854 Wireless-G PCI Adapter) + +pci:v00001814d00000201sv00001458sd0000E381* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (GN-WMKG 802.11b/g Wireless CardBus Adapter) + +pci:v00001814d00000201sv00001458sd0000E931* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (GN-WIKG 802.11b/g mini-PCI Adapter) + +pci:v00001814d00000201sv00001462sd00006833* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (Unknown 802.11g mini-PCI Adapter) + +pci:v00001814d00000201sv00001462sd00006835* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (Wireless 11G CardBus CB54G2) + +pci:v00001814d00000201sv00001737sd00000032* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (WMP54G v4.0 PCI Adapter) + +pci:v00001814d00000201sv00001799sd0000700A* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (F5D7000 v2000/v3000 Wireless G Desktop Card) + +pci:v00001814d00000201sv00001799sd0000701A* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (F5D7010 v2000/v3000 Wireless G Notebook Card) + +pci:v00001814d00000201sv00001814sd00002560* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg + +pci:v00001814d00000201sv0000182Dsd00009073* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (WL-115 Wireless Network PCI Adapter) + +pci:v00001814d00000201sv0000185Fsd000022A0* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (CN-WF513 Wireless Cardbus Adapter) + +pci:v00001814d00000201sv000018EBsd00005312* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (WL531P IEEE 802.11g PCI Card-EU) + +pci:v00001814d00000201sv00001948sd00003C00* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (C54RC v1 Wireless 11g CardBus Adapter) + +pci:v00001814d00000201sv00001948sd00003C01* + ID_MODEL_FROM_DATABASE=RT2500 Wireless 802.11bg (C54Ri v1 Wireless 11g PCI Adapter) + +pci:v00001814d00000300* + ID_MODEL_FROM_DATABASE=Wireless Adapter Canyon CN-WF511 + +pci:v00001814d00000301* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI + +pci:v00001814d00000301sv00001186sd00003C08* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.E1)) + +pci:v00001814d00000301sv00001186sd00003C09* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (DWL-G510 Rev C) + +pci:v00001814d00000301sv000013D1sd0000ABE3* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (miniPCI Pluscom 802.11 a/b/g) + +pci:v00001814d00000301sv00001458sd0000E933* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (GN-WI01GS) + +pci:v00001814d00000301sv00001458sd0000E934* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (GN-WP01GS) + +pci:v00001814d00000301sv00001462sd0000B833* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (MP54G5 (MS-6833B)) + +pci:v00001814d00000301sv00001737sd00000055* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (WMP54G v4.1) + +pci:v00001814d00000301sv00001799sd0000700E* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (F5D7000 v6000 Wireless G Desktop Card) + +pci:v00001814d00000301sv00001799sd0000701E* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (F5D7010 v6000 Wireless G Notebook Card) + +pci:v00001814d00000301sv000017F9sd00000012* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (AWLC3026T 802.11g Wireless CardBus Adapter) + +pci:v00001814d00000301sv00001814sd00002561* + ID_MODEL_FROM_DATABASE=RT2561/RT61 802.11g PCI (EW-7108PCg/EW-7128g) + +pci:v00001814d00000302* + ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g + +pci:v00001814d00000302sv00001186sd00003A71* + ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (DWA-510 Wireless G Desktop Adapter) + +pci:v00001814d00000302sv00001186sd00003C08* + ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.E2)) + +pci:v00001814d00000302sv00001186sd00003C09* + ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (AirPlus G DWL-G510 Wireless Network Adapter (Rev.C)) + +pci:v00001814d00000302sv00001462sd0000B834* + ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (PC54G3 Wireless 11g PCI Card) + +pci:v00001814d00000302sv00001948sd00003C23* + ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (C54RC v2 Wireless 11g CardBus Adapter) + +pci:v00001814d00000302sv00001948sd00003C24* + ID_MODEL_FROM_DATABASE=RT2561/RT61 rev B 802.11g (C54Ri v2 Wireless 11g PCI Adapter) + +pci:v00001814d00000401* + ID_MODEL_FROM_DATABASE=RT2600 802.11 MIMO + +pci:v00001814d00000401sv00001737sd00000052* + ID_MODEL_FROM_DATABASE=RT2600 802.11 MIMO (WPC54GR v1 802.11g Wireless-G Notebook Adapter with RangeBooster) + +pci:v00001814d00000401sv000017F9sd00000011* + ID_MODEL_FROM_DATABASE=RT2600 802.11 MIMO (WPCR-137G 802.11bg Wireless CardBus Adapter) + +pci:v00001814d00000401sv000017F9sd00000016* + ID_MODEL_FROM_DATABASE=RT2600 802.11 MIMO (WPIR-119GH 802.11bg Wireless Desktop Adapter) + +pci:v00001814d00000601* + ID_MODEL_FROM_DATABASE=RT2800 802.11n PCI + +pci:v00001814d00000601sv00001799sd0000801C* + ID_MODEL_FROM_DATABASE=RT2800 802.11n PCI (F5D8011 v3 802.11n N1 Wireless Notebook Card) + +pci:v00001814d00000601sv0000187Esd00003412* + ID_MODEL_FROM_DATABASE=RT2800 802.11n PCI (NWD-310N 802.11n Wireless PCI Adapter) + +pci:v00001814d00000681* + ID_MODEL_FROM_DATABASE=RT2890 Wireless 802.11n PCIe + +pci:v00001814d00000681sv00001458sd0000E939* + ID_MODEL_FROM_DATABASE=RT2890 Wireless 802.11n PCIe (GN-WS30N-RH 802.11bgn Mini PCIe Card) + +pci:v00001814d00000701* + ID_MODEL_FROM_DATABASE=RT2760 Wireless 802.11n 1T/2R + +pci:v00001814d00000701sv00001737sd00000074* + ID_MODEL_FROM_DATABASE=RT2760 Wireless 802.11n 1T/2R (WMP110 v2 802.11n RangePlus Wireless PCI Adapter) + +pci:v00001814d00000781* + ID_MODEL_FROM_DATABASE=RT2790 Wireless 802.11n 1T/2R PCIe + +pci:v00001814d00000781sv00001814sd00002790* + ID_MODEL_FROM_DATABASE=RT2790 Wireless 802.11n 1T/2R PCIe + +pci:v00001814d00003060* + ID_MODEL_FROM_DATABASE=RT3060 Wireless 802.11n 1T/1R + +pci:v00001814d00003060sv00001186sd00003C04* + ID_MODEL_FROM_DATABASE=RT3060 Wireless 802.11n 1T/1R (DWA-525 Wireless N 150 Desktop Adapter (rev.A1)) + +pci:v00001814d00003062* + ID_MODEL_FROM_DATABASE=RT3062 Wireless 802.11n 2T/2R + +pci:v00001814d00003090* + ID_MODEL_FROM_DATABASE=RT3090 Wireless 802.11n 1T/1R PCIe + +pci:v00001814d00003090sv000013BDsd00001057* + ID_MODEL_FROM_DATABASE=RT3090 Wireless 802.11n 1T/1R PCIe (GN-WS32L-RH Half-size Mini PCIe Card) + +pci:v00001814d00003091* + ID_MODEL_FROM_DATABASE=RT3091 Wireless 802.11n 1T/2R PCIe + +pci:v00001814d00003092* + ID_MODEL_FROM_DATABASE=RT3092 Wireless 802.11n 2T/2R PCIe + +pci:v00001814d00003290* + ID_MODEL_FROM_DATABASE=RT3290 Wireless 802.11n 1T/1R PCIe + +pci:v00001814d00003290sv0000103Csd000018EC* + ID_MODEL_FROM_DATABASE=RT3290 Wireless 802.11n 1T/1R PCIe (Ralink RT3290LE 802.11bgn 1x1 Wi-Fi and Bluetooth 4.0 Combo Adapter) + +pci:v00001814d00003298* + ID_MODEL_FROM_DATABASE=RT3290 Bluetooth + +pci:v00001814d00003298sv0000103Csd000018EC* + ID_MODEL_FROM_DATABASE=RT3290 Bluetooth (Ralink RT3290LE 802.11bgn 1x1 Wi-Fi and Bluetooth 4.0 Combo Adapter) + +pci:v00001814d00003592* + ID_MODEL_FROM_DATABASE=RT3592 Wireless 802.11abgn 2T/2R PCIe + +pci:v00001814d0000359F* + ID_MODEL_FROM_DATABASE=RT3592 PCIe Wireless Network Adapter + +pci:v00001814d00005360* + ID_MODEL_FROM_DATABASE=RT5360 Wireless 802.11n 1T/1R + +pci:v00001814d00005360sv00001186sd00003C05* + ID_MODEL_FROM_DATABASE=RT5360 Wireless 802.11n 1T/1R (DWA-525 Wireless N 150 Desktop Adapter (rev.A2)) + +pci:v00001814d00005360sv000020F4sd0000703A* + ID_MODEL_FROM_DATABASE=RT5360 Wireless 802.11n 1T/1R (TEW-703PI N150 Wireless PCI Adapter) + +pci:v00001814d00005362* + ID_MODEL_FROM_DATABASE=RT5362 PCI 802.11n Wireless Network Adapter + +pci:v00001814d00005390* + ID_MODEL_FROM_DATABASE=RT5390 Wireless 802.11n 1T/1R PCIe + +pci:v00001814d00005390sv0000103Csd00001636* + ID_MODEL_FROM_DATABASE=RT5390 Wireless 802.11n 1T/1R PCIe (U98Z077.00 Half-size Mini PCIe Card) + +pci:v00001814d00005392* + ID_MODEL_FROM_DATABASE=RT5392 PCIe Wireless Network Adapter + +pci:v00001814d0000539B* + ID_MODEL_FROM_DATABASE=RT5390R 802.11bgn PCIe Wireless Network Adapter + +pci:v00001814d0000539F* + ID_MODEL_FROM_DATABASE=RT5390 [802.11 b/g/n 1T1R G-band PCI Express Single Chip] + +pci:v00001814d0000539Fsv0000103Csd00001637* + ID_MODEL_FROM_DATABASE=RT5390 [802.11 b/g/n 1T1R G-band PCI Express Single Chip] (Pavilion DM1Z-3000 PCIe wireless card) + +pci:v00001814d00005592* + ID_MODEL_FROM_DATABASE=RT5592 PCIe Wireless Network Adapter + +pci:v00001814d0000E932* + ID_MODEL_FROM_DATABASE=RT2560F 802.11 b/g PCI + +pci:v00001815* + ID_VENDOR_FROM_DATABASE=Devolo AG + +pci:v00001820* + ID_VENDOR_FROM_DATABASE=InfiniCon Systems Inc. + +pci:v00001822* + ID_VENDOR_FROM_DATABASE=Twinhan Technology Co. Ltd + +pci:v00001822d00004E35* + ID_MODEL_FROM_DATABASE=Mantis DTV PCI Bridge Controller [Ver 1.0] + +pci:v0000182D* + ID_VENDOR_FROM_DATABASE=SiteCom Europe BV + +pci:v0000182Dd00003069* + ID_MODEL_FROM_DATABASE=ISDN PCI DC-105V2 + +pci:v0000182Dd00009790* + ID_MODEL_FROM_DATABASE=WL-121 Wireless Network Adapter 100g+ [Ver.3] + +pci:v0000182E* + ID_VENDOR_FROM_DATABASE=Raza Microelectronics, Inc. + +pci:v0000182Ed00000008* + ID_MODEL_FROM_DATABASE=XLR516 Processor + +pci:v0000182F* + ID_VENDOR_FROM_DATABASE=Broadcom + +pci:v0000182Fd0000000B* + ID_MODEL_FROM_DATABASE=BCM5785 [HT1000] SATA (RAID Mode) + +pci:v00001830* + ID_VENDOR_FROM_DATABASE=Credence Systems Corporation + +pci:v00001830d00008000* + ID_MODEL_FROM_DATABASE=CPIn + +pci:v00001830d00008001* + ID_MODEL_FROM_DATABASE=CPId + +pci:v00001830d00008002* + ID_MODEL_FROM_DATABASE=CPIx + +pci:v00001830d00008003* + ID_MODEL_FROM_DATABASE=CPIq + +pci:v0000183B* + ID_VENDOR_FROM_DATABASE=MikroM GmbH + +pci:v0000183Bd000008A7* + ID_MODEL_FROM_DATABASE=MVC100 DVI + +pci:v0000183Bd000008A8* + ID_MODEL_FROM_DATABASE=MVC101 SDI + +pci:v0000183Bd000008A9* + ID_MODEL_FROM_DATABASE=MVC102 DVI+Audio + +pci:v0000183Bd000008B0* + ID_MODEL_FROM_DATABASE=MVC200-DC + +pci:v00001846* + ID_VENDOR_FROM_DATABASE=Alcatel-Lucent + +pci:v00001849* + ID_VENDOR_FROM_DATABASE=ASRock Incorporation + +pci:v0000184A* + ID_VENDOR_FROM_DATABASE=Thales Computers + +pci:v0000184Ad00001100* + ID_MODEL_FROM_DATABASE=MAX II cPLD + +pci:v00001850* + ID_VENDOR_FROM_DATABASE=Advantest Corporation + +pci:v00001850d00000048* + ID_MODEL_FROM_DATABASE=EK220-66401 Computer Interface Card + +pci:v00001851* + ID_VENDOR_FROM_DATABASE=Microtune, Inc. + +pci:v00001852* + ID_VENDOR_FROM_DATABASE=Anritsu Corp. + +pci:v00001853* + ID_VENDOR_FROM_DATABASE=SMSC Automotive Infotainment System Group + +pci:v00001854* + ID_VENDOR_FROM_DATABASE=LG Electronics, Inc. + +pci:v0000185B* + ID_VENDOR_FROM_DATABASE=Compro Technology, Inc. + +pci:v0000185Bd00001489* + ID_MODEL_FROM_DATABASE=VideoMate Vista T100 + +pci:v0000185F* + ID_VENDOR_FROM_DATABASE=Wistron NeWeb Corp. + +pci:v00001864* + ID_VENDOR_FROM_DATABASE=SilverBack + +pci:v00001864d00002110* + ID_MODEL_FROM_DATABASE=ISNAP 2110 + +pci:v00001867* + ID_VENDOR_FROM_DATABASE=Topspin Communications + +pci:v00001867d00005A44* + ID_MODEL_FROM_DATABASE=MT23108 InfiniHost HCA + +pci:v00001867d00005A45* + ID_MODEL_FROM_DATABASE=MT23108 InfiniHost HCA flash recovery + +pci:v00001867d00005A46* + ID_MODEL_FROM_DATABASE=MT23108 InfiniHost HCA bridge + +pci:v00001867d00006278* + ID_MODEL_FROM_DATABASE=MT25208 InfiniHost III Ex (Tavor compatibility mode) + +pci:v00001867d00006282* + ID_MODEL_FROM_DATABASE=MT25208 InfiniHost III Ex + +pci:v0000186C* + ID_VENDOR_FROM_DATABASE=Humusoft, s.r.o. + +pci:v0000186Cd00000612* + ID_MODEL_FROM_DATABASE=AD612 Data Acquisition Device + +pci:v0000186Cd00000614* + ID_MODEL_FROM_DATABASE=MF614 Multifunction I/O Card + +pci:v0000186Cd00000622* + ID_MODEL_FROM_DATABASE=AD622 Data Acquisition Device + +pci:v0000186Cd00000624* + ID_MODEL_FROM_DATABASE=MF624 Multifunction I/O PCI Card + +pci:v0000186Cd00000625* + ID_MODEL_FROM_DATABASE=MF625 3-phase Motor Driver + +pci:v0000186Cd00000634* + ID_MODEL_FROM_DATABASE=MF634 Multifunction I/O PCIe Card + +pci:v0000186Cd00000644* + ID_MODEL_FROM_DATABASE=MF644 Multifunction I/O Thb Card + +pci:v0000186F* + ID_VENDOR_FROM_DATABASE=WiNRADiO Communications + +pci:v00001876* + ID_VENDOR_FROM_DATABASE=L-3 Communications + +pci:v00001876d0000A101* + ID_MODEL_FROM_DATABASE=VigraWATCH PCI + +pci:v00001876d0000A102* + ID_MODEL_FROM_DATABASE=VigraWATCH PMC + +pci:v00001876d0000A103* + ID_MODEL_FROM_DATABASE=Vigra I/O + +pci:v0000187E* + ID_VENDOR_FROM_DATABASE=ZyXEL Communications Corporation + +pci:v0000187Ed00003403* + ID_MODEL_FROM_DATABASE=ZyAir G-110 802.11g + +pci:v0000187Ed0000340E* + ID_MODEL_FROM_DATABASE=M-302 802.11g XtremeMIMO + +pci:v00001885* + ID_VENDOR_FROM_DATABASE=Avvida Systems Inc. + +pci:v00001888* + ID_VENDOR_FROM_DATABASE=Varisys Ltd + +pci:v00001888d00000301* + ID_MODEL_FROM_DATABASE=VMFX1 FPGA PMC module + +pci:v00001888d00000601* + ID_MODEL_FROM_DATABASE=VSM2 dual PMC carrier + +pci:v00001888d00000710* + ID_MODEL_FROM_DATABASE=VS14x series PowerPC PCI board + +pci:v00001888d00000720* + ID_MODEL_FROM_DATABASE=VS24x series PowerPC PCI board + +pci:v0000188A* + ID_VENDOR_FROM_DATABASE=Ample Communications, Inc + +pci:v00001890* + ID_VENDOR_FROM_DATABASE=Egenera, Inc. + +pci:v00001894* + ID_VENDOR_FROM_DATABASE=KNC One + +pci:v00001896* + ID_VENDOR_FROM_DATABASE=B&B Electronics Manufacturing Company, Inc. + +pci:v00001896d00004202* + ID_MODEL_FROM_DATABASE=MIport 3PCIU2 2-port Serial + +pci:v00001896d00004204* + ID_MODEL_FROM_DATABASE=MIport 3PCIU4 4-port Serial + +pci:v00001896d00004208* + ID_MODEL_FROM_DATABASE=MIport 3PCIU8 8-port Serial + +pci:v00001896d00004211* + ID_MODEL_FROM_DATABASE=MIport 3PCIOU1 1-port Isolated Serial + +pci:v00001896d00004212* + ID_MODEL_FROM_DATABASE=MIport 3PCIOU2 2-port Isolated Serial + +pci:v00001896d00004214* + ID_MODEL_FROM_DATABASE=MIport 3PCIOU4 4-port Isolated Serial + +pci:v00001896d0000BB10* + ID_MODEL_FROM_DATABASE=3PCI2 2-Port Serial + +pci:v00001896d0000BB11* + ID_MODEL_FROM_DATABASE=3PCIO1 1-Port Isolated Serial + +pci:v00001897* + ID_VENDOR_FROM_DATABASE=AMtek + +pci:v000018A1* + ID_VENDOR_FROM_DATABASE=Astute Networks Inc. + +pci:v000018A2* + ID_VENDOR_FROM_DATABASE=Stretch Inc. + +pci:v000018A2d00000002* + ID_MODEL_FROM_DATABASE=VRC6016 16-Channel PCIe DVR Card + +pci:v000018A3* + ID_VENDOR_FROM_DATABASE=AT&T + +pci:v000018AC* + ID_VENDOR_FROM_DATABASE=DViCO Corporation + +pci:v000018ACd0000D500* + ID_MODEL_FROM_DATABASE=FusionHDTV 5 + +pci:v000018ACd0000D800* + ID_MODEL_FROM_DATABASE=FusionHDTV 3 Gold + +pci:v000018ACd0000D810* + ID_MODEL_FROM_DATABASE=FusionHDTV 3 Gold-Q + +pci:v000018ACd0000D820* + ID_MODEL_FROM_DATABASE=FusionHDTV 3 Gold-T + +pci:v000018ACd0000DB30* + ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T Pro + +pci:v000018ACd0000DB40* + ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T Hybrid + +pci:v000018ACd0000DB78* + ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T Dual Express + +pci:v000018B8* + ID_VENDOR_FROM_DATABASE=Ammasso + +pci:v000018B8d0000B001* + ID_MODEL_FROM_DATABASE=AMSO 1100 iWARP/RDMA Gigabit Ethernet Coprocessor + +pci:v000018BC* + ID_VENDOR_FROM_DATABASE=GeCube Technologies, Inc. + +pci:v000018C3* + ID_VENDOR_FROM_DATABASE=Micronas Semiconductor Holding AG + +pci:v000018C3d00000720* + ID_MODEL_FROM_DATABASE=nGene PCI-Express Multimedia Controller + +pci:v000018C3d00000720sv00001461sd0000032E* + ID_MODEL_FROM_DATABASE=nGene PCI-Express Multimedia Controller (Hybrid M779 PCI-E) + +pci:v000018C8* + ID_VENDOR_FROM_DATABASE=Cray Inc + +pci:v000018C9* + ID_VENDOR_FROM_DATABASE=ARVOO Engineering BV + +pci:v000018CA* + ID_VENDOR_FROM_DATABASE=XGI Technology Inc. (eXtreme Graphics Innovation) + +pci:v000018CAd00000020* + ID_MODEL_FROM_DATABASE=Z7/Z9 (XG20 core) + +pci:v000018CAd00000021* + ID_MODEL_FROM_DATABASE=Z9s/Z9m (XG21 core) + +pci:v000018CAd00000027* + ID_MODEL_FROM_DATABASE=Z11/Z11M + +pci:v000018CAd00000040* + ID_MODEL_FROM_DATABASE=Volari V3XT/V5/V8 + +pci:v000018CAd00000047* + ID_MODEL_FROM_DATABASE=Volari 8300 (chip: XP10, codename: XG47) + +pci:v000018D2* + ID_VENDOR_FROM_DATABASE=Sitecom Europe BV (Wrong ID) + +pci:v000018D2d00003069* + ID_MODEL_FROM_DATABASE=DC-105v2 ISDN controller + +pci:v000018D4* + ID_VENDOR_FROM_DATABASE=Celestica + +pci:v000018D8* + ID_VENDOR_FROM_DATABASE=Dialogue Technology Corp. + +pci:v000018DD* + ID_VENDOR_FROM_DATABASE=Artimi Inc + +pci:v000018DDd00004C6F* + ID_MODEL_FROM_DATABASE=Artimi RTMI-100 UWB adapter + +pci:v000018DF* + ID_VENDOR_FROM_DATABASE=LeWiz Communications + +pci:v000018E6* + ID_VENDOR_FROM_DATABASE=MPL AG + +pci:v000018E6d00000001* + ID_MODEL_FROM_DATABASE=OSCI [Octal Serial Communication Interface] + +pci:v000018EB* + ID_VENDOR_FROM_DATABASE=Advance Multimedia Internet Technology, Inc. + +pci:v000018EC* + ID_VENDOR_FROM_DATABASE=Cesnet, z.s.p.o. + +pci:v000018ECd00006D05* + ID_MODEL_FROM_DATABASE=ML555 + +pci:v000018ECd00006D05sv000018ECsd00000100* + ID_MODEL_FROM_DATABASE=ML555 (NIC (ethernet interfaces)) + +pci:v000018ECd00006D05sv000018ECsd00000200* + ID_MODEL_FROM_DATABASE=ML555 (NIC (szedata2) 4x1G) + +pci:v000018ECd00006D05sv000018ECsd00000201* + ID_MODEL_FROM_DATABASE=ML555 (NIC (szedata2) 2x10G) + +pci:v000018ECd00006D05sv000018ECsd00000300* + ID_MODEL_FROM_DATABASE=ML555 (NIFIC (szedata2) 4x1G) + +pci:v000018ECd00006D05sv000018ECsd00000302* + ID_MODEL_FROM_DATABASE=ML555 (NIFIC (szedata2) 2x10G) + +pci:v000018ECd00006D05sv000018ECsd00004200* + ID_MODEL_FROM_DATABASE=ML555 (Flexible FlowMon (szedata2) 1x10G) + +pci:v000018ECd00006D05sv000018ECsd0000FF00* + ID_MODEL_FROM_DATABASE=ML555 (Testing design) + +pci:v000018ECd00006D05sv000018ECsd0000FF01* + ID_MODEL_FROM_DATABASE=ML555 (Boot design) + +pci:v000018ECd0000C006* + ID_MODEL_FROM_DATABASE=COMBO6 + +pci:v000018ECd0000C006sv000018ECsd0000D001* + ID_MODEL_FROM_DATABASE=COMBO6 (COMBO-4MTX) + +pci:v000018ECd0000C006sv000018ECsd0000D002* + ID_MODEL_FROM_DATABASE=COMBO6 (COMBO-4SFP) + +pci:v000018ECd0000C006sv000018ECsd0000D003* + ID_MODEL_FROM_DATABASE=COMBO6 (COMBO-4SFPRO) + +pci:v000018ECd0000C006sv000018ECsd0000D004* + ID_MODEL_FROM_DATABASE=COMBO6 (COMBO-2XFP) + +pci:v000018ECd0000C032* + ID_MODEL_FROM_DATABASE=COMBO-LXT110 + +pci:v000018ECd0000C032sv000018ECsd00000100* + ID_MODEL_FROM_DATABASE=COMBO-LXT110 (NIC (ethernet interfaces)) + +pci:v000018ECd0000C032sv000018ECsd00000200* + ID_MODEL_FROM_DATABASE=COMBO-LXT110 (NIC (szedata2) 4x1G) + +pci:v000018ECd0000C032sv000018ECsd00000201* + ID_MODEL_FROM_DATABASE=COMBO-LXT110 (NIC (szedata2) 2x10G) + +pci:v000018ECd0000C032sv000018ECsd00000300* + ID_MODEL_FROM_DATABASE=COMBO-LXT110 (NIFIC (szedata2) 4x1G) + +pci:v000018ECd0000C032sv000018ECsd00000302* + ID_MODEL_FROM_DATABASE=COMBO-LXT110 (NIFIC (szedata2) 2x10G) + +pci:v000018ECd0000C032sv000018ECsd00004200* + ID_MODEL_FROM_DATABASE=COMBO-LXT110 (Flexible FlowMon (szedata2) 1x10G) + +pci:v000018ECd0000C032sv000018ECsd0000FF00* + ID_MODEL_FROM_DATABASE=COMBO-LXT110 (Testing design) + +pci:v000018ECd0000C032sv000018ECsd0000FF01* + ID_MODEL_FROM_DATABASE=COMBO-LXT110 (Boot design) + +pci:v000018ECd0000C045* + ID_MODEL_FROM_DATABASE=COMBO6E + +pci:v000018ECd0000C050* + ID_MODEL_FROM_DATABASE=COMBO-PTM + +pci:v000018ECd0000C058* + ID_MODEL_FROM_DATABASE=COMBO6X + +pci:v000018ECd0000C058sv000018ECsd0000D001* + ID_MODEL_FROM_DATABASE=COMBO6X (COMBO-4MTX) + +pci:v000018ECd0000C058sv000018ECsd0000D002* + ID_MODEL_FROM_DATABASE=COMBO6X (COMBO-4SFP) + +pci:v000018ECd0000C058sv000018ECsd0000D003* + ID_MODEL_FROM_DATABASE=COMBO6X (COMBO-4SFPRO) + +pci:v000018ECd0000C058sv000018ECsd0000D004* + ID_MODEL_FROM_DATABASE=COMBO6X (COMBO-2XFP) + +pci:v000018ECd0000C132* + ID_MODEL_FROM_DATABASE=COMBO-LXT155 + +pci:v000018ECd0000C132sv000018ECsd00000100* + ID_MODEL_FROM_DATABASE=COMBO-LXT155 (NIC (ethernet interfaces)) + +pci:v000018ECd0000C132sv000018ECsd00000200* + ID_MODEL_FROM_DATABASE=COMBO-LXT155 (NIC (szedata2) 4x1G) + +pci:v000018ECd0000C132sv000018ECsd00000201* + ID_MODEL_FROM_DATABASE=COMBO-LXT155 (NIC (szedata2) 2x10G) + +pci:v000018ECd0000C132sv000018ECsd00000300* + ID_MODEL_FROM_DATABASE=COMBO-LXT155 (NIFIC (szedata2) 4x1G) + +pci:v000018ECd0000C132sv000018ECsd00000302* + ID_MODEL_FROM_DATABASE=COMBO-LXT155 (NIFIC (szedata2) 2x10G) + +pci:v000018ECd0000C132sv000018ECsd00004200* + ID_MODEL_FROM_DATABASE=COMBO-LXT155 (Flexible FlowMon (szedata2) 1x10G) + +pci:v000018ECd0000C132sv000018ECsd0000FF00* + ID_MODEL_FROM_DATABASE=COMBO-LXT155 (Testing design) + +pci:v000018ECd0000C132sv000018ECsd0000FF01* + ID_MODEL_FROM_DATABASE=COMBO-LXT155 (Boot design) + +pci:v000018ECd0000C232* + ID_MODEL_FROM_DATABASE=COMBO-FXT100 + +pci:v000018ECd0000C232sv000018ECsd00000100* + ID_MODEL_FROM_DATABASE=COMBO-FXT100 (NIC (ethernet interfaces)) + +pci:v000018ECd0000C232sv000018ECsd00000200* + ID_MODEL_FROM_DATABASE=COMBO-FXT100 (NIC (szedata2) 4x1G) + +pci:v000018ECd0000C232sv000018ECsd00000201* + ID_MODEL_FROM_DATABASE=COMBO-FXT100 (NIC (szedata2) 2x10G) + +pci:v000018ECd0000C232sv000018ECsd00000300* + ID_MODEL_FROM_DATABASE=COMBO-FXT100 (NIFIC (szedata2) 4x1G) + +pci:v000018ECd0000C232sv000018ECsd00000302* + ID_MODEL_FROM_DATABASE=COMBO-FXT100 (NIFIC (szedata2) 2x10G) + +pci:v000018ECd0000C232sv000018ECsd00004200* + ID_MODEL_FROM_DATABASE=COMBO-FXT100 (Flexible FlowMon (szedata2) 1x10G) + +pci:v000018ECd0000C232sv000018ECsd0000FF00* + ID_MODEL_FROM_DATABASE=COMBO-FXT100 (Testing design) + +pci:v000018ECd0000C232sv000018ECsd0000FF01* + ID_MODEL_FROM_DATABASE=COMBO-FXT100 (Boot design) + +pci:v000018EE* + ID_VENDOR_FROM_DATABASE=Chenming Mold Ind. Corp. + +pci:v000018F1* + ID_VENDOR_FROM_DATABASE=Spectrum GmbH + +pci:v000018F4* + ID_VENDOR_FROM_DATABASE=Napatech A/S + +pci:v000018F4d00000031* + ID_MODEL_FROM_DATABASE=NT20X Network Adapter + +pci:v000018F4d00000051* + ID_MODEL_FROM_DATABASE=NT20X Capture Card + +pci:v000018F4d00000061* + ID_MODEL_FROM_DATABASE=NT20E Capture Card + +pci:v000018F4d00000064* + ID_MODEL_FROM_DATABASE=NT20E Inline Card + +pci:v000018F4d00000071* + ID_MODEL_FROM_DATABASE=NT4E Capture Card + +pci:v000018F4d00000074* + ID_MODEL_FROM_DATABASE=NT4E Inline Card + +pci:v000018F4d00000081* + ID_MODEL_FROM_DATABASE=NT4E 4-port Expansion Card + +pci:v000018F4d00000091* + ID_MODEL_FROM_DATABASE=NT20X Capture Card [New Rev] + +pci:v000018F4d000000A1* + ID_MODEL_FROM_DATABASE=NT4E-STD Capture Card + +pci:v000018F4d000000A4* + ID_MODEL_FROM_DATABASE=NT4E-STD Inline Card + +pci:v000018F4d000000B1* + ID_MODEL_FROM_DATABASE=NTBPE Optical Bypass Adapter + +pci:v000018F4d000000C5* + ID_MODEL_FROM_DATABASE=NT20E2 Network Adapter 2x10Gb + +pci:v000018F4d000000D5* + ID_MODEL_FROM_DATABASE=NT40E2-4 Network Adapter 4x10Gb + +pci:v000018F4d000000E5* + ID_MODEL_FROM_DATABASE=NT40E2-1 Network Adapter 1x40Gb + +pci:v000018F4d000000F5* + ID_MODEL_FROM_DATABASE=NT4E2-4T-BP Network Adapter 4x1Gb with Electrical Bypass + +pci:v000018F4d00000105* + ID_MODEL_FROM_DATABASE=NT4E2-4-PTP Network Adapter 4x1Gb + +pci:v000018F4d00000115* + ID_MODEL_FROM_DATABASE=NT20E2-PTP Network Adapter 2x10Gb + +pci:v000018F4d00000125* + ID_MODEL_FROM_DATABASE=NT4E2-4-PTP Network Adapter 4x1Gb + +pci:v000018F4d00000135* + ID_MODEL_FROM_DATABASE=NT20E2-PTP Network Adapter 2x10Gb + +pci:v000018F4d00000145* + ID_MODEL_FROM_DATABASE=NT40E3-4-PTP Network Adapter 4x10Gb + +pci:v000018F4d00000155* + ID_MODEL_FROM_DATABASE=NT100E3-1-PTP Network Adapter 1x100Gb + +pci:v000018F4d00000165* + ID_MODEL_FROM_DATABASE=NT80E3-2-PTP Network Adapter 2x40Gb + +pci:v000018F4d00000175* + ID_MODEL_FROM_DATABASE=NT20E3-2-PTP Network Adapter 2x10Gb + +pci:v000018F4d00000185* + ID_MODEL_FROM_DATABASE=NT40A01 Network Adapter + +pci:v000018F4d000001A5* + ID_MODEL_FROM_DATABASE=NT200A01 Network Adapter + +pci:v000018F4d000001C5* + ID_MODEL_FROM_DATABASE=NT200A02 Network Adapter + +pci:v000018F6* + ID_VENDOR_FROM_DATABASE=NextIO + +pci:v000018F6d00001000* + ID_MODEL_FROM_DATABASE=[Nexsis] Switch Virtual P2P PCIe Bridge + +pci:v000018F6d00001001* + ID_MODEL_FROM_DATABASE=[Texsis] Switch Virtual P2P PCIe Bridge + +pci:v000018F6d00001050* + ID_MODEL_FROM_DATABASE=[Nexsis] Switch Virtual P2P PCI Bridge + +pci:v000018F6d00001051* + ID_MODEL_FROM_DATABASE=[Texsis] Switch Virtual P2P PCI Bridge + +pci:v000018F6d00002000* + ID_MODEL_FROM_DATABASE=[Nexsis] Switch Integrated Mgmt. Endpoint + +pci:v000018F6d00002001* + ID_MODEL_FROM_DATABASE=[Texsis] Switch Integrated Mgmt. Endpoint + +pci:v000018F7* + ID_VENDOR_FROM_DATABASE=Commtech, Inc. + +pci:v000018F7d00000001* + ID_MODEL_FROM_DATABASE=ESCC-PCI-335 Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000002* + ID_MODEL_FROM_DATABASE=422/4-PCI-335 Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000003* + ID_MODEL_FROM_DATABASE=232/4-1M-PCI Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000004* + ID_MODEL_FROM_DATABASE=422/2-PCI-335 Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000005* + ID_MODEL_FROM_DATABASE=IGESCC-PCI-ISO/1 Serial PCI Adapter [Fastcom] + +pci:v000018F7d0000000A* + ID_MODEL_FROM_DATABASE=232/4-PCI-335 Serial PCI Adapter [Fastcom] + +pci:v000018F7d0000000B* + ID_MODEL_FROM_DATABASE=232/8-PCI-335 Serial PCI Adapter [Fastcom] + +pci:v000018F7d0000000F* + ID_MODEL_FROM_DATABASE=FSCC Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000010* + ID_MODEL_FROM_DATABASE=GSCC Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000011* + ID_MODEL_FROM_DATABASE=QSSB Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000014* + ID_MODEL_FROM_DATABASE=SuperFSCC Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000015* + ID_MODEL_FROM_DATABASE=SuperFSCC-104-LVDS Serial PC/104+ Adapter [Fastcom] + +pci:v000018F7d00000016* + ID_MODEL_FROM_DATABASE=FSCC-232 RS-232 Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000017* + ID_MODEL_FROM_DATABASE=SuperFSCC-104 Serial PC/104+ Adapter [Fastcom] + +pci:v000018F7d00000018* + ID_MODEL_FROM_DATABASE=SuperFSCC/4 Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000019* + ID_MODEL_FROM_DATABASE=SuperFSCC Serial PCI Adapter [Fastcom] + +pci:v000018F7d0000001A* + ID_MODEL_FROM_DATABASE=SuperFSCC-LVDS Serial PCI Adapter [Fastcom] + +pci:v000018F7d0000001B* + ID_MODEL_FROM_DATABASE=FSCC/4 Serial PCI Adapter [Fastcom] + +pci:v000018F7d0000001C* + ID_MODEL_FROM_DATABASE=SuperFSCC/4-LVDS Serial PCI Adapter [Fastcom] + +pci:v000018F7d0000001D* + ID_MODEL_FROM_DATABASE=FSCC Serial PCI Adapter [Fastcom] + +pci:v000018F7d0000001E* + ID_MODEL_FROM_DATABASE=SuperFSCC/4 Serial PCIe Adapter [Fastcom] + +pci:v000018F7d0000001F* + ID_MODEL_FROM_DATABASE=SuperFSCC/4 Serial cPCI Adapter [Fastcom] + +pci:v000018F7d00000020* + ID_MODEL_FROM_DATABASE=422/4-PCIe Serial PCIe Adapter [Fastcom] + +pci:v000018F7d00000021* + ID_MODEL_FROM_DATABASE=422/8-PCIe Serial PCIe Adapter [Fastcom] + +pci:v000018F7d00000022* + ID_MODEL_FROM_DATABASE=SuperFSCC/4-LVDS Serial PCIe Adapter [Fastcom] + +pci:v000018F7d00000023* + ID_MODEL_FROM_DATABASE=SuperFSCC/4 Serial cPCI Adapter [Fastcom] + +pci:v000018F7d00000025* + ID_MODEL_FROM_DATABASE=SuperFSCC/4-LVDS Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000026* + ID_MODEL_FROM_DATABASE=SuperFSCC-LVDS Serial PCI Adapter [Fastcom] + +pci:v000018F7d00000027* + ID_MODEL_FROM_DATABASE=FSCC/4 Serial PCIe Adapter [Fastcom] + +pci:v000018FB* + ID_VENDOR_FROM_DATABASE=Resilience Corporation + +pci:v00001904* + ID_VENDOR_FROM_DATABASE=Hangzhou Silan Microelectronics Co., Ltd. + +pci:v00001904d00002031* + ID_MODEL_FROM_DATABASE=SC92031 PCI Fast Ethernet Adapter + +pci:v00001904d00008139* + ID_MODEL_FROM_DATABASE=RTL8139D [Realtek] PCI 10/100BaseTX ethernet adaptor + +pci:v00001905* + ID_VENDOR_FROM_DATABASE=Micronas USA, Inc. + +pci:v00001912* + ID_VENDOR_FROM_DATABASE=Renesas Technology Corp. + +pci:v00001912d00000002* + ID_MODEL_FROM_DATABASE=SH7780 PCI Controller (PCIC) + +pci:v00001912d00000011* + ID_MODEL_FROM_DATABASE=SH7757 PCIe End-Point [PBI] + +pci:v00001912d00000012* + ID_MODEL_FROM_DATABASE=SH7757 PCIe-PCI Bridge [PPB] + +pci:v00001912d00000013* + ID_MODEL_FROM_DATABASE=SH7757 PCIe Switch [PS] + +pci:v00001912d00000014* + ID_MODEL_FROM_DATABASE=uPD720201 USB 3.0 Host Controller + +pci:v00001912d00000015* + ID_MODEL_FROM_DATABASE=uPD720202 USB 3.0 Host Controller + +pci:v00001912d0000001A* + ID_MODEL_FROM_DATABASE=SH7758 PCIe-PCI Bridge [PPB] + +pci:v00001912d0000001B* + ID_MODEL_FROM_DATABASE=SH7758 PCIe End-Point [PBI] + +pci:v00001912d0000001D* + ID_MODEL_FROM_DATABASE=SH7758 PCIe Switch [PS] + +pci:v00001919* + ID_VENDOR_FROM_DATABASE=Soltek Computer Inc. + +pci:v00001923* + ID_VENDOR_FROM_DATABASE=Sangoma Technologies Corp. + +pci:v00001923d00000040* + ID_MODEL_FROM_DATABASE=A200/Remora FXO/FXS Analog AFT card + +pci:v00001923d00000100* + ID_MODEL_FROM_DATABASE=A104d QUAD T1/E1 AFT card + +pci:v00001923d00000300* + ID_MODEL_FROM_DATABASE=A101 single-port T1/E1 + +pci:v00001923d00000400* + ID_MODEL_FROM_DATABASE=A104u Quad T1/E1 AFT + +pci:v00001924* + ID_VENDOR_FROM_DATABASE=Solarflare Communications + +pci:v00001924d00000703* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] + +pci:v00001924d00000703sv000010B8sd00000102* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SMC10GPCIe-10BT (A2) [TigerCard]) + +pci:v00001924d00000703sv000010B8sd00000103* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SMC10GPCIe-10BT (A3) [TigerCard]) + +pci:v00001924d00000703sv000010B8sd00000201* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SMC10GPCIe-XFP (A1) [TigerCard]) + +pci:v00001924d00000703sv00001924sd00000101* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4001-A1) + +pci:v00001924d00000703sv00001924sd00000102* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4001-A2) + +pci:v00001924d00000703sv00001924sd00000103* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4001-A3) + +pci:v00001924d00000703sv00001924sd00000201* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4002-A1) + +pci:v00001924d00000703sv00001924sd00000301* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4003-A1) + +pci:v00001924d00000703sv00001924sd00000302* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4003-A2) + +pci:v00001924d00000703sv00001924sd00000303* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4003-A3) + +pci:v00001924d00000703sv00001924sd00000304* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4003-A4) + +pci:v00001924d00000703sv00001924sd00000500* + ID_MODEL_FROM_DATABASE=SFC4000 rev A net [Solarstorm] (SFE4005-A0) + +pci:v00001924d00000710* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] + +pci:v00001924d00000710sv000010B8sd00000103* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SMC10GPCIe-10BT (A3) [TigerCard]) + +pci:v00001924d00000710sv000010B8sd00000201* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SMC10GPCIe-XFP (A1) [TigerCard]) + +pci:v00001924d00000710sv00001924sd00000102* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4001-A2) + +pci:v00001924d00000710sv00001924sd00000103* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4001-A3) + +pci:v00001924d00000710sv00001924sd00000201* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4002-A1) + +pci:v00001924d00000710sv00001924sd00000302* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4003-A2) + +pci:v00001924d00000710sv00001924sd00000303* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4003-A3) + +pci:v00001924d00000710sv00001924sd00000304* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4003-A4) + +pci:v00001924d00000710sv00001924sd00000500* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFE4005-A0) + +pci:v00001924d00000710sv00001924sd00005102* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4111T-A2) + +pci:v00001924d00000710sv00001924sd00005103* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4111T-R3) + +pci:v00001924d00000710sv00001924sd00005104* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4111T-R4) + +pci:v00001924d00000710sv00001924sd00005105* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4111T-R5) + +pci:v00001924d00000710sv00001924sd00005201* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4112F-R1) + +pci:v00001924d00000710sv00001924sd00005202* + ID_MODEL_FROM_DATABASE=SFC4000 rev B [Solarstorm] (SFN4112F-R2) + +pci:v00001924d00000803* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller + +pci:v00001924d00000803sv00001014sd00000478* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (2-port 10GbE Low-Latency (R7)) + +pci:v00001924d00000803sv00001014sd00000479* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (2-port 10GbE OpenOnload (R7)) + +pci:v00001924d00000803sv00001014sd000004A7* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (Solarflare 10Gb Low-latency Dual-port HBA (R7)) + +pci:v00001924d00000803sv00001014sd000004A8* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (Solarflare 10Gb Dual-port HBA (R7)) + +pci:v00001924d00000803sv0000103Csd00002132* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (Ethernet 10Gb 2-port 570FLR-SFP+ Adapter (R1)) + +pci:v00001924d00000803sv0000103Csd00002136* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (Ethernet 10Gb 2-port 570SFP+ Adapter (R7)) + +pci:v00001924d00000803sv00001924sd00001201* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFA6902F-R1 SFP+ AOE Adapter) + +pci:v00001924d00000803sv00001924sd00006200* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5122F-R0 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00006201* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5122F-R1 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00006202* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5122F-R2 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00006204* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5122F-R4 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00006205* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5122F-R5 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00006206* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5122F-R6 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00006207* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5122F-R7 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00006210* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5322F-R0 SFP+ Precision Time Synchronization Server Adapter) + +pci:v00001924d00000803sv00001924sd00006211* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5322F-R1 SFP+ Precision Time Synchronization Server Adapter) + +pci:v00001924d00000803sv00001924sd00006217* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5322F-R7 SFP+ Precision Time Synchronization Server Adapter) + +pci:v00001924d00000803sv00001924sd00006227* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN6122F-R7 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00006237* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN6322F-R7 SFP+ Precision Time Synchronization Server Adapter) + +pci:v00001924d00000803sv00001924sd00006501* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5802K-R1 Mezzanine Adapter) + +pci:v00001924d00000803sv00001924sd00006511* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5814H-R1 Mezzanine Adapter) + +pci:v00001924d00000803sv00001924sd00006521* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5812H-R1 Mezzanine Adapter) + +pci:v00001924d00000803sv00001924sd00006562* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN6832F-R2 SFP+ Mezzanine Adapter) + +pci:v00001924d00000803sv00001924sd00006A05* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5112F-R5 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00006A06* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5112F-R6 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00007206* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5162F-R6 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00007207* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5162F-R7 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00007A06* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5152F-R6 SFP+ Server Adapter) + +pci:v00001924d00000803sv00001924sd00007A07* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (SFN5152F-R7 SFP+ Server Adapter) + +pci:v00001924d00000813* + ID_MODEL_FROM_DATABASE=SFL9021 10GBASE-T Ethernet Controller + +pci:v00001924d00000813sv00001924sd00006100* + ID_MODEL_FROM_DATABASE=SFL9021 10GBASE-T Ethernet Controller (SFN5121T-R0 10GBASE-T Server Adapter) + +pci:v00001924d00000813sv00001924sd00006102* + ID_MODEL_FROM_DATABASE=SFL9021 10GBASE-T Ethernet Controller (SFN5121T-R2 10GBASE-T Server Adapter) + +pci:v00001924d00000813sv00001924sd00006103* + ID_MODEL_FROM_DATABASE=SFL9021 10GBASE-T Ethernet Controller (SFN5121T-R3 10GBASE-T Server Adapter) + +pci:v00001924d00000813sv00001924sd00006104* + ID_MODEL_FROM_DATABASE=SFL9021 10GBASE-T Ethernet Controller (SFN5121T-R4 10GBASE-T Server Adapter) + +pci:v00001924d00000813sv00001924sd00006902* + ID_MODEL_FROM_DATABASE=SFL9021 10GBASE-T Ethernet Controller (SFN5111T-R2 10GBASE-T Server Adapter) + +pci:v00001924d00000813sv00001924sd00006904* + ID_MODEL_FROM_DATABASE=SFL9021 10GBASE-T Ethernet Controller (SFN5111T-R4 10GBASE-T Server Adapter) + +pci:v00001924d00000813sv00001924sd00007104* + ID_MODEL_FROM_DATABASE=SFL9021 10GBASE-T Ethernet Controller (SFN5161T-R4 10GBASE-T Server Adapter) + +pci:v00001924d00000813sv00001924sd00007904* + ID_MODEL_FROM_DATABASE=SFL9021 10GBASE-T Ethernet Controller (SFN5151T-R4 10GBASE-T Server Adapter) + +pci:v00001924d00000903* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller + +pci:v00001924d00000903sv00001014sd000004CC* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFN7122F-R2 2x10GbE SFP+ Flareon Ultra) + +pci:v00001924d00000903sv00001924sd00008002* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFN7122F-R1 SFP+ Server Adapter) + +pci:v00001924d00000903sv00001924sd00008003* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFN7x41Q-R1 Flareon Ultra 7000 Series 10/40G Adapter) + +pci:v00001924d00000903sv00001924sd00008006* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFN7022F-R1 SFP+ Server Adapter) + +pci:v00001924d00000903sv00001924sd00008007* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFN7322F-R2 Precision Time SFP+ Server Adapter) + +pci:v00001924d00000903sv00001924sd00008009* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFN7x22F-R2 Flareon Ultra 7000 Series 10G Adapter) + +pci:v00001924d00000903sv00001924sd0000800A* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFN7x02F-R2 Flareon 7000 Series 10G Adapter) + +pci:v00001924d00000903sv00001924sd0000800C* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFN7x22F-R3 Flareon Ultra 7000 Series 10G Adapter) + +pci:v00001924d00000903sv00001924sd0000800D* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFN7x02F-R3 Flareon 7000 Series 10G Adapter) + +pci:v00001924d00000903sv00001924sd00008010* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFA7942Q-R1 QSFP+ AOE Adapter) + +pci:v00001924d00000903sv00001924sd00008015* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (SFA7942Q-A5-0-R1 QSFP+ AOE Adapter) + +pci:v00001924d00000923* + ID_MODEL_FROM_DATABASE=SFC9140 10/40G Ethernet Controller + +pci:v00001924d00000923sv00001924sd0000800B* + ID_MODEL_FROM_DATABASE=SFC9140 10/40G Ethernet Controller (SFN7x42Q-R1 Flareon Ultra 7000 Series 10/40G Adapter) + +pci:v00001924d00000923sv00001924sd0000800E* + ID_MODEL_FROM_DATABASE=SFC9140 10/40G Ethernet Controller (SFN7x42Q-R2 Flareon Ultra 7000 Series 10/40G Adapter) + +pci:v00001924d00000923sv00001924sd0000800F* + ID_MODEL_FROM_DATABASE=SFC9140 10/40G Ethernet Controller (SFN7xx4F-R1 Flareon Ultra 7000 Series 10G Adapter) + +pci:v00001924d00000A03* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller + +pci:v00001924d00000A03sv00001924sd00008011* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8022-R1 8000 Series 10G Adapter) + +pci:v00001924d00000A03sv00001924sd00008012* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8522-R1 8000 Series 10G Adapter) + +pci:v00001924d00000A03sv00001924sd00008013* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8042-R1 8000 Series 10/40G Adapter) + +pci:v00001924d00000A03sv00001924sd00008014* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8542-R1 8000 Series 10/40G Adapter) + +pci:v00001924d00000A03sv00001924sd00008016* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8022-R2 8000 Series 10G Adapter) + +pci:v00001924d00000A03sv00001924sd00008017* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8522-R2 8000 Series 10G Adapter) + +pci:v00001924d00000A03sv00001924sd00008018* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8042-R2 8000 Series 10/40G Adapter) + +pci:v00001924d00000A03sv00001924sd00008019* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8542-R2 8000 Series 10/40G Adapter) + +pci:v00001924d00000A03sv00001924sd0000801A* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8722-R1 8000 Series OCP 10G Adapter) + +pci:v00001924d00000A03sv00001924sd0000801B* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8522-R3 8000 Series 10G Adapter) + +pci:v00001924d00000A03sv00001924sd0000801C* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8042-R3 8000 Series 10/40G Adapter) + +pci:v00001924d00000A03sv00001924sd00008021* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (SFN8041-R1 8000 Series 10/40G Adapter) + +pci:v00001924d00000B03* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller + +pci:v00001924d00000B03sv00001924sd0000801D* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (x2522-R1 2000 Series 10/25G Adapter) + +pci:v00001924d00000B03sv00001924sd0000801E* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (x2542-R1 2000 Series 40/100G Adapter) + +pci:v00001924d00000B03sv00001924sd00008022* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (XtremeScale X2522 10G Network Adapter) + +pci:v00001924d00000B03sv00001924sd00008024* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (XtremeScale X2562 OCP 3.0 Dual Port SFP28) + +pci:v00001924d00000B03sv00001924sd00008027* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (XtremeScale X2541 PCIe Single Port QSFP28) + +pci:v00001924d00000B03sv00001924sd00008028* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (XtremeScale X2522-25G Network Adapter) + +pci:v00001924d00000B03sv00001924sd0000802A* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (XtremeScale X2542 PCIe Dual Port QSFP28) + +pci:v00001924d00000B03sv00001924sd0000802B* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (XtremeScale X2552 OCP 2.0 Dual Port SFP28) + +pci:v00001924d00000B03sv00001924sd0000802C* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (XtremeScale X2522-25G PCIe Dual Port SFP28) + +pci:v00001924d00000B03sv00001924sd0000802D* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (XtremeScale X2562 OCP 3.0 Dual Port SFP28) + +pci:v00001924d00001803* + ID_MODEL_FROM_DATABASE=SFC9020 10G Ethernet Controller (Virtual Function) + +pci:v00001924d00001813* + ID_MODEL_FROM_DATABASE=SFL9021 10GBASE-T Ethernet Controller (Virtual Function) + +pci:v00001924d00001903* + ID_MODEL_FROM_DATABASE=SFC9120 10G Ethernet Controller (Virtual Function) + +pci:v00001924d00001923* + ID_MODEL_FROM_DATABASE=SFC9140 10/40G Ethernet Controller (Virtual Function) + +pci:v00001924d00001A03* + ID_MODEL_FROM_DATABASE=SFC9220 10/40G Ethernet Controller (Virtual Function) + +pci:v00001924d00001B03* + ID_MODEL_FROM_DATABASE=XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (Virtual Function) + +pci:v00001924d00006703* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] + +pci:v00001924d00006703sv000010B8sd00000102* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SMC10GPCIe-10BT (A2) [TigerCard]) + +pci:v00001924d00006703sv000010B8sd00000103* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SMC10GPCIe-10BT (A3) [TigerCard]) + +pci:v00001924d00006703sv000010B8sd00000201* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SMC10GPCIe-XFP (A1) [TigerCard]) + +pci:v00001924d00006703sv00001924sd00000101* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4001-A1) + +pci:v00001924d00006703sv00001924sd00000102* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4001-A2) + +pci:v00001924d00006703sv00001924sd00000103* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4001-A3) + +pci:v00001924d00006703sv00001924sd00000201* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4002-A1) + +pci:v00001924d00006703sv00001924sd00000301* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4003-A1) + +pci:v00001924d00006703sv00001924sd00000302* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4003-A2) + +pci:v00001924d00006703sv00001924sd00000303* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4003-A3) + +pci:v00001924d00006703sv00001924sd00000304* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4003-A4) + +pci:v00001924d00006703sv00001924sd00000500* + ID_MODEL_FROM_DATABASE=SFC4000 rev A iSCSI/Onload [Solarstorm] (SFE4005-A0) + +pci:v00001924d0000C101* + ID_MODEL_FROM_DATABASE=EF1-21022T [EtherFabric] + +pci:v0000192A* + ID_VENDOR_FROM_DATABASE=BiTMICRO Networks Inc. + +pci:v0000192Ad00000008* + ID_MODEL_FROM_DATABASE=RAMPART + +pci:v0000192E* + ID_VENDOR_FROM_DATABASE=TransDimension + +pci:v00001931* + ID_VENDOR_FROM_DATABASE=Option N.V. + +pci:v00001931d0000000C* + ID_MODEL_FROM_DATABASE=Qualcomm MSM6275 UMTS chip + +pci:v00001932* + ID_VENDOR_FROM_DATABASE=DiBcom + +pci:v0000193C* + ID_VENDOR_FROM_DATABASE=MAXIM Integrated Products + +pci:v0000193D* + ID_VENDOR_FROM_DATABASE=Hangzhou H3C Technologies Co., Ltd. + +pci:v0000193F* + ID_VENDOR_FROM_DATABASE=AHA Products Group + +pci:v0000193Fd00000001* + ID_MODEL_FROM_DATABASE=AHA36x-PCIX + +pci:v0000193Fd00000360* + ID_MODEL_FROM_DATABASE=AHA360-PCIe + +pci:v0000193Fd00000363* + ID_MODEL_FROM_DATABASE=AHA363-PCIe + +pci:v0000193Fd00000364* + ID_MODEL_FROM_DATABASE=AHA364-PCIe + +pci:v0000193Fd00000367* + ID_MODEL_FROM_DATABASE=AHA367-PCIe + +pci:v0000193Fd00000370* + ID_MODEL_FROM_DATABASE=AHA370-PCIe + +pci:v0000193Fd00000604* + ID_MODEL_FROM_DATABASE=AHA604 + +pci:v0000193Fd00000605* + ID_MODEL_FROM_DATABASE=AHA605 + +pci:v0000193Fd00003641* + ID_MODEL_FROM_DATABASE=AHA3641 + +pci:v0000193Fd00003642* + ID_MODEL_FROM_DATABASE=AHA3642 + +pci:v0000193Fd00006101* + ID_MODEL_FROM_DATABASE=AHA6101 + +pci:v0000193Fd00006102* + ID_MODEL_FROM_DATABASE=AHA6102 + +pci:v00001942* + ID_VENDOR_FROM_DATABASE=ClearSpeed Technology plc + +pci:v00001942d0000E511* + ID_MODEL_FROM_DATABASE=Advance X620 accelerator card + +pci:v00001942d0000E521* + ID_MODEL_FROM_DATABASE=Advance e620 accelerator card + +pci:v00001947* + ID_VENDOR_FROM_DATABASE=C-guys, Inc. + +pci:v00001947d00004743* + ID_MODEL_FROM_DATABASE=CG200 Dual SD/SDIO Host controller device + +pci:v00001948* + ID_VENDOR_FROM_DATABASE=Alpha Networks Inc. + +pci:v0000194A* + ID_VENDOR_FROM_DATABASE=DapTechnology B.V. + +pci:v0000194Ad00001111* + ID_MODEL_FROM_DATABASE=FireSpy3850 + +pci:v0000194Ad00001112* + ID_MODEL_FROM_DATABASE=FireSpy450b + +pci:v0000194Ad00001113* + ID_MODEL_FROM_DATABASE=FireSpy450bT + +pci:v0000194Ad00001114* + ID_MODEL_FROM_DATABASE=FireSpy850 + +pci:v0000194Ad00001115* + ID_MODEL_FROM_DATABASE=FireSpy850bT + +pci:v0000194Ad00001200* + ID_MODEL_FROM_DATABASE=FireTrac 3460bT + +pci:v0000194Ad00001201* + ID_MODEL_FROM_DATABASE=FireTrac 3460bT (fallback firmware) + +pci:v0000194Ad00001202* + ID_MODEL_FROM_DATABASE=FireTrac 3460bT + +pci:v0000194Ad00001203* + ID_MODEL_FROM_DATABASE=FireTrac 3460bT (fallback firmware) + +pci:v00001954* + ID_VENDOR_FROM_DATABASE=One Stop Systems, Inc. + +pci:v00001957* + ID_VENDOR_FROM_DATABASE=Freescale Semiconductor Inc + +pci:v00001957d00000012* + ID_MODEL_FROM_DATABASE=MPC8548E + +pci:v00001957d00000013* + ID_MODEL_FROM_DATABASE=MPC8548 + +pci:v00001957d00000014* + ID_MODEL_FROM_DATABASE=MPC8543E + +pci:v00001957d00000015* + ID_MODEL_FROM_DATABASE=MPC8543 + +pci:v00001957d00000018* + ID_MODEL_FROM_DATABASE=MPC8547E + +pci:v00001957d00000019* + ID_MODEL_FROM_DATABASE=MPC8545E + +pci:v00001957d0000001A* + ID_MODEL_FROM_DATABASE=MPC8545 + +pci:v00001957d00000020* + ID_MODEL_FROM_DATABASE=MPC8568E + +pci:v00001957d00000021* + ID_MODEL_FROM_DATABASE=MPC8568 + +pci:v00001957d00000022* + ID_MODEL_FROM_DATABASE=MPC8567E + +pci:v00001957d00000023* + ID_MODEL_FROM_DATABASE=MPC8567 + +pci:v00001957d00000030* + ID_MODEL_FROM_DATABASE=MPC8533E + +pci:v00001957d00000031* + ID_MODEL_FROM_DATABASE=MPC8533 + +pci:v00001957d00000032* + ID_MODEL_FROM_DATABASE=MPC8544E + +pci:v00001957d00000033* + ID_MODEL_FROM_DATABASE=MPC8544 + +pci:v00001957d00000040* + ID_MODEL_FROM_DATABASE=MPC8572E + +pci:v00001957d00000041* + ID_MODEL_FROM_DATABASE=MPC8572 + +pci:v00001957d00000050* + ID_MODEL_FROM_DATABASE=MPC8536E + +pci:v00001957d00000051* + ID_MODEL_FROM_DATABASE=MPC8536 + +pci:v00001957d00000052* + ID_MODEL_FROM_DATABASE=MPC8535E + +pci:v00001957d00000053* + ID_MODEL_FROM_DATABASE=MPC8535 + +pci:v00001957d00000060* + ID_MODEL_FROM_DATABASE=MPC8569 + +pci:v00001957d00000061* + ID_MODEL_FROM_DATABASE=MPC8569E + +pci:v00001957d00000070* + ID_MODEL_FROM_DATABASE=P2020E + +pci:v00001957d00000071* + ID_MODEL_FROM_DATABASE=P2020 + +pci:v00001957d00000078* + ID_MODEL_FROM_DATABASE=P2010E + +pci:v00001957d00000079* + ID_MODEL_FROM_DATABASE=P2010 + +pci:v00001957d00000080* + ID_MODEL_FROM_DATABASE=MPC8349E + +pci:v00001957d00000081* + ID_MODEL_FROM_DATABASE=MPC8349 + +pci:v00001957d00000082* + ID_MODEL_FROM_DATABASE=MPC8347E TBGA + +pci:v00001957d00000083* + ID_MODEL_FROM_DATABASE=MPC8347 TBGA + +pci:v00001957d00000084* + ID_MODEL_FROM_DATABASE=MPC8347E PBGA + +pci:v00001957d00000084sv0000110Asd00004074* + ID_MODEL_FROM_DATABASE=MPC8347E PBGA (SIMATIC NET CP 1628) + +pci:v00001957d00000085* + ID_MODEL_FROM_DATABASE=MPC8347 PBGA + +pci:v00001957d00000085sv0000110Asd00004046* + ID_MODEL_FROM_DATABASE=MPC8347 PBGA (SIMATIC NET CP 1623) + +pci:v00001957d00000086* + ID_MODEL_FROM_DATABASE=MPC8343E + +pci:v00001957d00000087* + ID_MODEL_FROM_DATABASE=MPC8343 + +pci:v00001957d000000B4* + ID_MODEL_FROM_DATABASE=MPC8315E + +pci:v00001957d000000B6* + ID_MODEL_FROM_DATABASE=MPC8314E + +pci:v00001957d000000B6sv00001A56sd00001101* + ID_MODEL_FROM_DATABASE=MPC8314E (Killer Xeno Pro Gigabit Ethernet Controller) + +pci:v00001957d000000C2* + ID_MODEL_FROM_DATABASE=MPC8379E + +pci:v00001957d000000C3* + ID_MODEL_FROM_DATABASE=MPC8379 + +pci:v00001957d000000C4* + ID_MODEL_FROM_DATABASE=MPC8378E + +pci:v00001957d000000C5* + ID_MODEL_FROM_DATABASE=MPC8378 + +pci:v00001957d000000C6* + ID_MODEL_FROM_DATABASE=MPC8377E + +pci:v00001957d000000C7* + ID_MODEL_FROM_DATABASE=MPC8377 + +pci:v00001957d00000100* + ID_MODEL_FROM_DATABASE=P1020E + +pci:v00001957d00000101* + ID_MODEL_FROM_DATABASE=P1020 + +pci:v00001957d00000102* + ID_MODEL_FROM_DATABASE=P1021E + +pci:v00001957d00000103* + ID_MODEL_FROM_DATABASE=P1021 + +pci:v00001957d00000108* + ID_MODEL_FROM_DATABASE=P1011E + +pci:v00001957d00000109* + ID_MODEL_FROM_DATABASE=P1011 + +pci:v00001957d0000010A* + ID_MODEL_FROM_DATABASE=P1012E + +pci:v00001957d0000010B* + ID_MODEL_FROM_DATABASE=P1012 + +pci:v00001957d00000110* + ID_MODEL_FROM_DATABASE=P1022E + +pci:v00001957d00000111* + ID_MODEL_FROM_DATABASE=P1022 + +pci:v00001957d00000111sv00001C7Fsd00005200* + ID_MODEL_FROM_DATABASE=P1022 (EB5200) + +pci:v00001957d00000118* + ID_MODEL_FROM_DATABASE=P1013E + +pci:v00001957d00000119* + ID_MODEL_FROM_DATABASE=P1013 + +pci:v00001957d00000128* + ID_MODEL_FROM_DATABASE=P1010 + +pci:v00001957d00000400* + ID_MODEL_FROM_DATABASE=P4080E + +pci:v00001957d00000401* + ID_MODEL_FROM_DATABASE=P4080 + +pci:v00001957d00000408* + ID_MODEL_FROM_DATABASE=P4040E + +pci:v00001957d00000409* + ID_MODEL_FROM_DATABASE=P4040 + +pci:v00001957d0000041F* + ID_MODEL_FROM_DATABASE=P3041 + +pci:v00001957d00000440* + ID_MODEL_FROM_DATABASE=T4240 with security + +pci:v00001957d00000441* + ID_MODEL_FROM_DATABASE=T4240 without security + +pci:v00001957d00000446* + ID_MODEL_FROM_DATABASE=T4160 with security + +pci:v00001957d00000447* + ID_MODEL_FROM_DATABASE=T4160 without security + +pci:v00001957d00000830* + ID_MODEL_FROM_DATABASE=T2080 with security + +pci:v00001957d00000831* + ID_MODEL_FROM_DATABASE=T2080 without security + +pci:v00001957d00000838* + ID_MODEL_FROM_DATABASE=T2081 with security + +pci:v00001957d00000839* + ID_MODEL_FROM_DATABASE=T2081 without security + +pci:v00001957d0000580C* + ID_MODEL_FROM_DATABASE=MPC5121e + +pci:v00001957d00007010* + ID_MODEL_FROM_DATABASE=MPC8641 PCI Host Bridge + +pci:v00001957d00007011* + ID_MODEL_FROM_DATABASE=MPC8641D PCI Host Bridge + +pci:v00001957d00007018* + ID_MODEL_FROM_DATABASE=MPC8610 + +pci:v00001957d0000C006* + ID_MODEL_FROM_DATABASE=MPC8308 + +pci:v00001957d0000C006sv00001A56sd00001201* + ID_MODEL_FROM_DATABASE=MPC8308 (Killer E2100 Gigabit Ethernet Controller) + +pci:v00001957d0000FC02* + ID_MODEL_FROM_DATABASE=RedStone + +pci:v00001957d0000FC03* + ID_MODEL_FROM_DATABASE=CFI + +pci:v00001958* + ID_VENDOR_FROM_DATABASE=Faster Technology, LLC. + +pci:v00001959* + ID_VENDOR_FROM_DATABASE=PA Semi, Inc + +pci:v00001959d0000A000* + ID_MODEL_FROM_DATABASE=PA6T Core + +pci:v00001959d0000A001* + ID_MODEL_FROM_DATABASE=PWRficient Host Bridge + +pci:v00001959d0000A002* + ID_MODEL_FROM_DATABASE=PWRficient PCI-Express Port + +pci:v00001959d0000A003* + ID_MODEL_FROM_DATABASE=PWRficient SMBus Controller + +pci:v00001959d0000A004* + ID_MODEL_FROM_DATABASE=PWRficient 16550 UART + +pci:v00001959d0000A005* + ID_MODEL_FROM_DATABASE=PWRficient Gigabit Ethernet + +pci:v00001959d0000A006* + ID_MODEL_FROM_DATABASE=PWRficient 10-Gigabit Ethernet + +pci:v00001959d0000A007* + ID_MODEL_FROM_DATABASE=PWRficient DMA Controller + +pci:v00001959d0000A008* + ID_MODEL_FROM_DATABASE=PWRficient LPC/Localbus Interface + +pci:v00001959d0000A009* + ID_MODEL_FROM_DATABASE=PWRficient L2 Cache + +pci:v00001959d0000A00A* + ID_MODEL_FROM_DATABASE=PWRficient DDR2 Memory Controller + +pci:v00001959d0000A00B* + ID_MODEL_FROM_DATABASE=PWRficient SERDES + +pci:v00001959d0000A00C* + ID_MODEL_FROM_DATABASE=PWRficient System/Debug Controller + +pci:v00001959d0000A00D* + ID_MODEL_FROM_DATABASE=PWRficient PCI-Express Internal Endpoint + +pci:v00001966* + ID_VENDOR_FROM_DATABASE=Orad Hi-Tec Systems + +pci:v00001966d00001975* + ID_MODEL_FROM_DATABASE=DVG64 family + +pci:v00001966d00001977* + ID_MODEL_FROM_DATABASE=DVG128 family + +pci:v00001969* + ID_VENDOR_FROM_DATABASE=Qualcomm Atheros + +pci:v00001969d00001026* + ID_MODEL_FROM_DATABASE=AR8121/AR8113/AR8114 Gigabit or Fast Ethernet + +pci:v00001969d00001026sv00001043sd00008304* + ID_MODEL_FROM_DATABASE=AR8121/AR8113/AR8114 Gigabit or Fast Ethernet (P5KPL-CM Motherboard) + +pci:v00001969d00001048* + ID_MODEL_FROM_DATABASE=Attansic L1 Gigabit Ethernet + +pci:v00001969d00001048sv00001043sd00008226* + ID_MODEL_FROM_DATABASE=Attansic L1 Gigabit Ethernet (P5B-MX/WiFi-AP, P5KPL-VM Motherboard) + +pci:v00001969d00001062* + ID_MODEL_FROM_DATABASE=AR8132 Fast Ethernet + +pci:v00001969d00001063* + ID_MODEL_FROM_DATABASE=AR8131 Gigabit Ethernet + +pci:v00001969d00001063sv00001458sd0000E000* + ID_MODEL_FROM_DATABASE=AR8131 Gigabit Ethernet (GA-G31M-ES2L Motherboard) + +pci:v00001969d00001063sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=AR8131 Gigabit Ethernet (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00001969d00001066* + ID_MODEL_FROM_DATABASE=Attansic L2c Gigabit Ethernet + +pci:v00001969d00001067* + ID_MODEL_FROM_DATABASE=Attansic L1c Gigabit Ethernet + +pci:v00001969d00001073* + ID_MODEL_FROM_DATABASE=AR8151 v1.0 Gigabit Ethernet + +pci:v00001969d00001083* + ID_MODEL_FROM_DATABASE=AR8151 v2.0 Gigabit Ethernet + +pci:v00001969d00001090* + ID_MODEL_FROM_DATABASE=AR8162 Fast Ethernet + +pci:v00001969d00001090sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=AR8162 Fast Ethernet (VivoBook X202E, X202EV) + +pci:v00001969d00001091* + ID_MODEL_FROM_DATABASE=AR8161 Gigabit Ethernet + +pci:v00001969d00001091sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=AR8161 Gigabit Ethernet (N56VZ) + +pci:v00001969d000010A0* + ID_MODEL_FROM_DATABASE=QCA8172 Fast Ethernet + +pci:v00001969d000010A1* + ID_MODEL_FROM_DATABASE=QCA8171 Gigabit Ethernet + +pci:v00001969d00002048* + ID_MODEL_FROM_DATABASE=Attansic L2 Fast Ethernet + +pci:v00001969d00002060* + ID_MODEL_FROM_DATABASE=AR8152 v1.1 Fast Ethernet + +pci:v00001969d00002062* + ID_MODEL_FROM_DATABASE=AR8152 v2.0 Fast Ethernet + +pci:v00001969d00002062sv00001043sd00008468* + ID_MODEL_FROM_DATABASE=AR8152 v2.0 Fast Ethernet (Eee PC 1015PX) + +pci:v00001969d0000E091* + ID_MODEL_FROM_DATABASE=Killer E220x Gigabit Ethernet Controller + +pci:v00001969d0000E0A1* + ID_MODEL_FROM_DATABASE=Killer E2400 Gigabit Ethernet Controller + +pci:v00001969d0000E0B1* + ID_MODEL_FROM_DATABASE=Killer E2500 Gigabit Ethernet Controller + +pci:v0000196A* + ID_VENDOR_FROM_DATABASE=Sensory Networks Inc. + +pci:v0000196Ad00000101* + ID_MODEL_FROM_DATABASE=NodalCore C-1000 Content Classification Accelerator + +pci:v0000196Ad00000102* + ID_MODEL_FROM_DATABASE=NodalCore C-2000 Content Classification Accelerator + +pci:v0000196Ad00000105* + ID_MODEL_FROM_DATABASE=NodalCore C-3000 Content Classification Accelerator + +pci:v0000196D* + ID_VENDOR_FROM_DATABASE=Club-3D BV + +pci:v0000196E* + ID_VENDOR_FROM_DATABASE=PNY + +pci:v00001971* + ID_VENDOR_FROM_DATABASE=AGEIA Technologies, Inc. + +pci:v00001971d00001011* + ID_MODEL_FROM_DATABASE=Physics Processing Unit [PhysX] + +pci:v00001971d00001011sv00001043sd00000001* + ID_MODEL_FROM_DATABASE=Physics Processing Unit [PhysX] (PhysX P1) + +pci:v00001974* + ID_VENDOR_FROM_DATABASE=Star Electronics GmbH & Co. KG + +pci:v00001974d00000009* + ID_MODEL_FROM_DATABASE=FlexCard PMC-II + +pci:v00001974d00000011* + ID_MODEL_FROM_DATABASE=FlexCard PMC-II Ethernet + +pci:v00001976* + ID_VENDOR_FROM_DATABASE=TRENDnet + +pci:v00001977* + ID_VENDOR_FROM_DATABASE=Parsec + +pci:v0000197B* + ID_VENDOR_FROM_DATABASE=JMicron Technology Corp. + +pci:v0000197Bd00000250* + ID_MODEL_FROM_DATABASE=JMC250 PCI Express Gigabit Ethernet Controller + +pci:v0000197Bd00000260* + ID_MODEL_FROM_DATABASE=JMC260 PCI Express Fast Ethernet Controller + +pci:v0000197Bd00000368* + ID_MODEL_FROM_DATABASE=JMB368 IDE controller + +pci:v0000197Bd00002360* + ID_MODEL_FROM_DATABASE=JMB360 AHCI Controller + +pci:v0000197Bd00002361* + ID_MODEL_FROM_DATABASE=JMB361 AHCI/IDE + +pci:v0000197Bd00002361sv00001462sd00007235* + ID_MODEL_FROM_DATABASE=JMB361 AHCI/IDE (P965 Neo MS-7235 mainboard) + +pci:v0000197Bd00002362* + ID_MODEL_FROM_DATABASE=JMB362 SATA Controller + +pci:v0000197Bd00002362sv00001043sd00008460* + ID_MODEL_FROM_DATABASE=JMB362 SATA Controller (P8P67 Deluxe Motherboard) + +pci:v0000197Bd00002363* + ID_MODEL_FROM_DATABASE=JMB363 SATA/IDE Controller + +pci:v0000197Bd00002363sv00001043sd000081E4* + ID_MODEL_FROM_DATABASE=JMB363 SATA/IDE Controller (P5B [JMB363]) + +pci:v0000197Bd00002363sv00001458sd0000B000* + ID_MODEL_FROM_DATABASE=JMB363 SATA/IDE Controller (Motherboard) + +pci:v0000197Bd00002363sv00001849sd00002363* + ID_MODEL_FROM_DATABASE=JMB363 SATA/IDE Controller (Motherboard (one of many)) + +pci:v0000197Bd00002364* + ID_MODEL_FROM_DATABASE=JMB364 AHCI Controller + +pci:v0000197Bd00002365* + ID_MODEL_FROM_DATABASE=JMB365 AHCI/IDE + +pci:v0000197Bd00002366* + ID_MODEL_FROM_DATABASE=JMB366 AHCI/IDE + +pci:v0000197Bd00002368* + ID_MODEL_FROM_DATABASE=JMB368 IDE controller + +pci:v0000197Bd00002369* + ID_MODEL_FROM_DATABASE=JMB369 Serial ATA Controller + +pci:v0000197Bd00002380* + ID_MODEL_FROM_DATABASE=IEEE 1394 Host Controller + +pci:v0000197Bd00002381* + ID_MODEL_FROM_DATABASE=Standard SD Host Controller + +pci:v0000197Bd00002382* + ID_MODEL_FROM_DATABASE=SD/MMC Host Controller + +pci:v0000197Bd00002383* + ID_MODEL_FROM_DATABASE=MS Host Controller + +pci:v0000197Bd00002384* + ID_MODEL_FROM_DATABASE=xD Host Controller + +pci:v0000197Bd00002386* + ID_MODEL_FROM_DATABASE=Standard SD Host Controller + +pci:v0000197Bd00002387* + ID_MODEL_FROM_DATABASE=SD/MMC Host Controller + +pci:v0000197Bd00002388* + ID_MODEL_FROM_DATABASE=MS Host Controller + +pci:v0000197Bd00002389* + ID_MODEL_FROM_DATABASE=xD Host Controller + +pci:v0000197Bd00002391* + ID_MODEL_FROM_DATABASE=Standard SD Host Controller + +pci:v0000197Bd00002392* + ID_MODEL_FROM_DATABASE=SD/MMC Host Controller + +pci:v0000197Bd00002393* + ID_MODEL_FROM_DATABASE=MS Host Controller + +pci:v0000197Bd00002394* + ID_MODEL_FROM_DATABASE=xD Host Controller + +pci:v00001982* + ID_VENDOR_FROM_DATABASE=Distant Early Warning Communications Inc + +pci:v00001982d00001600* + ID_MODEL_FROM_DATABASE=OX16C954 HOST-A + +pci:v00001982d000016FF* + ID_MODEL_FROM_DATABASE=OX16C954 HOST-B + +pci:v00001987* + ID_VENDOR_FROM_DATABASE=Phison Electronics Corporation + +pci:v00001987d00005007* + ID_MODEL_FROM_DATABASE=E7 NVMe Controller + +pci:v00001987d00005012* + ID_MODEL_FROM_DATABASE=E12 NVMe Controller + +pci:v00001987d00005016* + ID_MODEL_FROM_DATABASE=E16 PCIe4 NVMe Controller + +pci:v00001989* + ID_VENDOR_FROM_DATABASE=Montilio Inc. + +pci:v00001989d00000001* + ID_MODEL_FROM_DATABASE=RapidFile Bridge + +pci:v00001989d00008001* + ID_MODEL_FROM_DATABASE=RapidFile + +pci:v0000198A* + ID_VENDOR_FROM_DATABASE=Nallatech Ltd. + +pci:v00001993* + ID_VENDOR_FROM_DATABASE=Innominate Security Technologies AG + +pci:v00001999* + ID_VENDOR_FROM_DATABASE=A-Logics + +pci:v00001999d0000A900* + ID_MODEL_FROM_DATABASE=AM-7209 Video Processor + +pci:v0000199A* + ID_VENDOR_FROM_DATABASE=Pulse-LINK, Inc. + +pci:v0000199D* + ID_VENDOR_FROM_DATABASE=Xsigo Systems + +pci:v0000199Dd00008209* + ID_MODEL_FROM_DATABASE=Virtual NIC Device + +pci:v0000199Dd0000890A* + ID_MODEL_FROM_DATABASE=Virtual HBA Device + +pci:v0000199F* + ID_VENDOR_FROM_DATABASE=Auvitek + +pci:v0000199Fd00008501* + ID_MODEL_FROM_DATABASE=AU85X1 PCI REV1.1 + +pci:v0000199Fd00008521* + ID_MODEL_FROM_DATABASE=AU8521 TV card + +pci:v000019A2* + ID_VENDOR_FROM_DATABASE=Emulex Corporation + +pci:v000019A2d00000120* + ID_MODEL_FROM_DATABASE=x1 PCIe Gen2 Bridge[Pilot4] + +pci:v000019A2d00000200* + ID_MODEL_FROM_DATABASE=BladeEngine 10Gb PCI-E iSCSI adapter + +pci:v000019A2d00000201* + ID_MODEL_FROM_DATABASE=BladeEngine 10Gb PCIe Network Adapter + +pci:v000019A2d00000211* + ID_MODEL_FROM_DATABASE=BladeEngine2 10Gb Gen2 PCIe Network Adapter + +pci:v000019A2d00000212* + ID_MODEL_FROM_DATABASE=BladeEngine2 10Gb Gen2 PCIe iSCSI Adapter + +pci:v000019A2d00000221* + ID_MODEL_FROM_DATABASE=BladeEngine3 10Gb Gen2 PCIe Network Adapter + +pci:v000019A2d00000222* + ID_MODEL_FROM_DATABASE=BladeEngine3 10Gb Gen2 PCIe iSCSI Adapter + +pci:v000019A2d00000700* + ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE + +pci:v000019A2d00000700sv0000103Csd00001747* + ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE (NC550SFP DualPort 10GbE Server Adapter) + +pci:v000019A2d00000700sv0000103Csd00001749* + ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE (NC550SFP Dual Port Server Adapter) + +pci:v000019A2d00000700sv0000103Csd0000174A* + ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE (NC551m Dual Port FlexFabric 10Gb Adapter) + +pci:v000019A2d00000700sv0000103Csd0000174B* + ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE (StorageWorks NC550 DualPort Converged Network Adapter) + +pci:v000019A2d00000700sv0000103Csd00003314* + ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE (NC551i Dual Port FlexFabric 10Gb Adapter) + +pci:v000019A2d00000702* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb iSCSI Initiator + +pci:v000019A2d00000704* + ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE CNA + +pci:v000019A2d00000704sv000010DFsd0000E602* + ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE CNA (OneConnect OCe10100 10Gb CNA) + +pci:v000019A2d00000704sv000010DFsd0000E630* + ID_MODEL_FROM_DATABASE=OneConnect OCe10100/OCe10102 Series 10 GbE CNA (OneConnect OCe10102-FM-E / OCe10102-FX-E for EMC VNX Symmetrix) + +pci:v000019A2d00000710* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) + +pci:v000019A2d00000710sv00001014sd000003D0* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (PCIe2 2-port 10GbE SR Adapter for POWER) + +pci:v000019A2d00000710sv00001014sd000003D1* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (PCIe2 2-port 10GbE SFP+ Copper Adapter for POWER) + +pci:v000019A2d00000710sv00001014sd00000409* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (Integrated Multifunction Card with Dual 10GbE SR Optical + Dual 1GbE for Power 750/760) + +pci:v000019A2d00000710sv00001014sd0000040A* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (Integrated Multifunction Card with Dual 10GbE SR Copper + Dual 1GbE for Power 750/760) + +pci:v000019A2d00000710sv0000103Csd00003315* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC553i 10Gb 2-port FlexFabric Converged Network Adapter) + +pci:v000019A2d00000710sv0000103Csd00003340* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC552SFP 2-port 10Gb Server Adapter) + +pci:v000019A2d00000710sv0000103Csd00003341* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC552m 10Gb 2-port FlexFabric Converged Network Adapter) + +pci:v000019A2d00000710sv0000103Csd00003345* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC553m 10Gb 2-port FlexFabric Converged Network Adapter) + +pci:v000019A2d00000710sv0000103Csd0000337B* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (NC554FLB 10Gb 2-port FlexFabric Converged Network Adapter) + +pci:v000019A2d00000710sv000010DFsd0000E733* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb NIC (be3) (Flex System EN4054 4-port 10Gb Ethernet Mezzanine Adapter) + +pci:v000019A2d00000712* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb iSCSI Initiator (be3) + +pci:v000019A2d00000714* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Initiator (be3) + +pci:v000019A2d00000714sv0000103Csd00003315* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Initiator (be3) (NC553i 10Gb 2-port FlexFabric Converged Network Adapter) + +pci:v000019A2d00000714sv0000103Csd0000337B* + ID_MODEL_FROM_DATABASE=OneConnect 10Gb FCoE Initiator (be3) (NC554FLB 10Gb 2-port FlexFabric Converged Network Adapter) + +pci:v000019A2d00000800* + ID_MODEL_FROM_DATABASE=ServerView iRMC HTI + +pci:v000019A8* + ID_VENDOR_FROM_DATABASE=DAQDATA GmbH + +pci:v000019AC* + ID_VENDOR_FROM_DATABASE=Kasten Chase Applied Research + +pci:v000019ACd00000001* + ID_MODEL_FROM_DATABASE=ACA2400 Crypto Accelerator + +pci:v000019AE* + ID_VENDOR_FROM_DATABASE=Progeny Systems Corporation + +pci:v000019AEd00000520* + ID_MODEL_FROM_DATABASE=4135 HFT Interface Controller + +pci:v000019AEd00000521* + ID_MODEL_FROM_DATABASE=Decimator + +pci:v000019BA* + ID_VENDOR_FROM_DATABASE=ZyXEL Communications Corp. + +pci:v000019BAd00002330* + ID_MODEL_FROM_DATABASE=ZyWALL Turbo Card + +pci:v000019C1* + ID_VENDOR_FROM_DATABASE=Exegy Inc. + +pci:v000019D1* + ID_VENDOR_FROM_DATABASE=Motorola Expedience + +pci:v000019D4* + ID_VENDOR_FROM_DATABASE=Quixant Limited + +pci:v000019DA* + ID_VENDOR_FROM_DATABASE=ZOTAC International (MCO) Ltd. + +pci:v000019DE* + ID_VENDOR_FROM_DATABASE=Pico Computing + +pci:v000019E2* + ID_VENDOR_FROM_DATABASE=Vector Informatik GmbH + +pci:v000019E3* + ID_VENDOR_FROM_DATABASE=DDRdrive LLC + +pci:v000019E3d00005801* + ID_MODEL_FROM_DATABASE=DDRdrive X1 + +pci:v000019E3d00005808* + ID_MODEL_FROM_DATABASE=DDRdrive X8 + +pci:v000019E3d0000DD52* + ID_MODEL_FROM_DATABASE=DDRdrive X1-30 + +pci:v000019E5* + ID_VENDOR_FROM_DATABASE=Huawei Technologies Co., Ltd. + +pci:v000019E5d00000123* + ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD + +pci:v000019E5d00000123sv000019E5sd00003022* + ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600P V3 800GB 2.5" U.2) + +pci:v000019E5d00000123sv000019E5sd00003023* + ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600P V3 1200GB 2.5" U.2) + +pci:v000019E5d00000123sv000019E5sd00003024* + ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600P V3 1600GB 2.5" U.2) + +pci:v000019E5d00000123sv000019E5sd00003025* + ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600P V3 2000GB 2.5" U.2) + +pci:v000019E5d00000123sv000019E5sd00003026* + ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600P V3 3200GB 2.5" U.2) + +pci:v000019E5d00000123sv000019E5sd00003033* + ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600C V3 1200GB HHHL AIC) + +pci:v000019E5d00000123sv000019E5sd00003034* + ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600C V3 1600GB HHHL AIC) + +pci:v000019E5d00000123sv000019E5sd00003036* + ID_MODEL_FROM_DATABASE=ES3000 V3 NVMe PCIe SSD (NVMe SSD ES3600C V3 3200GB HHHL AIC) + +pci:v000019E5d00000200* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*100GE) + +pci:v000019E5d00000200sv000019E5sd0000D139* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*100GE) (Hi1822 SP572 (2*100GE)) + +pci:v000019E5d00000202* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*32G FC) + +pci:v000019E5d00000202sv000019E5sd0000D302* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*32G FC) (Hi1822 SP521 (2*32G FC)) + +pci:v000019E5d00000202sv000019E5sd0000D304* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*32G FC) (Hi1822 SP526 (2*32G FC)) + +pci:v000019E5d00000203* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*16G FC) + +pci:v000019E5d00000203sv000019E5sd0000D301* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*16G FC) (Hi1822 SP520 (2*16G FC)) + +pci:v000019E5d00000203sv000019E5sd0000D305* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*16G FC) (Hi1822 SP525 (2*16G FC)) + +pci:v000019E5d00000205* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*100GE) + +pci:v000019E5d00000205sv000019E5sd0000DF27* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*100GE) (Hi1822 MZ731 MEZZ (2*100GE)) + +pci:v000019E5d00000206* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*25GE) + +pci:v000019E5d00000206sv000019E5sd0000D138* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*25GE) (Hi1822 SP582 (2*25GE)) + +pci:v000019E5d00000210* + ID_MODEL_FROM_DATABASE=Hi1822 Family (4*25GE) + +pci:v000019E5d00000210sv000019E5sd0000DF2E* + ID_MODEL_FROM_DATABASE=Hi1822 Family (4*25GE) (Hi1822 MZ532 MEZZ (4*25GE)) + +pci:v000019E5d00000211* + ID_MODEL_FROM_DATABASE=Hi1822 Family (4*25GE) + +pci:v000019E5d00000211sv000019E5sd0000D12F* + ID_MODEL_FROM_DATABASE=Hi1822 Family (4*25GE) (Hi1822 SP571 (4*25GE)) + +pci:v000019E5d00000211sv000019E5sd0000D137* + ID_MODEL_FROM_DATABASE=Hi1822 Family (4*25GE) (Hi1822 SP581 (4*25GE)) + +pci:v000019E5d00000212* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*8G FC) + +pci:v000019E5d00000212sv000019E5sd0000D303* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*8G FC) (Hi1822 SP522 (2*8G FC)) + +pci:v000019E5d00000212sv000019E5sd0000D306* + ID_MODEL_FROM_DATABASE=Hi1822 Family (2*8G FC) (Hi1822 SP523 (2*8G FC)) + +pci:v000019E5d00001710* + ID_MODEL_FROM_DATABASE=iBMA Virtual Network Adapter + +pci:v000019E5d00001711* + ID_MODEL_FROM_DATABASE=Hi1710 [iBMC Intelligent Management system chip w/VGA support] + +pci:v000019E5d00001822* + ID_MODEL_FROM_DATABASE=Hi1822 Family (4*25GE) + +pci:v000019E5d00001822sv000019E5sd0000D129* + ID_MODEL_FROM_DATABASE=Hi1822 Family (4*25GE) (Hi1822 SP570 (4*25GE)) + +pci:v000019E5d00001822sv000019E5sd0000D136* + ID_MODEL_FROM_DATABASE=Hi1822 Family (4*25GE) (Hi1822 SP580 (4*25GE)) + +pci:v000019E5d0000371E* + ID_MODEL_FROM_DATABASE=Hi1822 Family Virtual Bridge + +pci:v000019E5d0000375E* + ID_MODEL_FROM_DATABASE=Hi1822 Family Virtual Function + +pci:v000019E5d0000379E* + ID_MODEL_FROM_DATABASE=Hi1822 Family Virtual Function + +pci:v000019E5d0000A120* + ID_MODEL_FROM_DATABASE=HiSilicon PCIe Root Port with Gen4 + +pci:v000019E5d0000A121* + ID_MODEL_FROM_DATABASE=HiSilicon PCI-PCI Bridge + +pci:v000019E5d0000A122* + ID_MODEL_FROM_DATABASE=HiSilicon Embedded DMA Engine + +pci:v000019E5d0000A124* + ID_MODEL_FROM_DATABASE=HiSilicon Internal SDI Function Engine + +pci:v000019E5d0000A125* + ID_MODEL_FROM_DATABASE=HiSilicon SDI Network Controller + +pci:v000019E5d0000A126* + ID_MODEL_FROM_DATABASE=HiSilicon SDI NVMe Storage Controller + +pci:v000019E5d0000A127* + ID_MODEL_FROM_DATABASE=HiSilicon SDI Accelerator + +pci:v000019E5d0000A12A* + ID_MODEL_FROM_DATABASE=HiSilicon Add-on PCI-PCI Bridge + +pci:v000019E5d0000A220* + ID_MODEL_FROM_DATABASE=HNS GE Network Controller + +pci:v000019E5d0000A221* + ID_MODEL_FROM_DATABASE=HNS GE/10GE/25GE Network Controller + +pci:v000019E5d0000A222* + ID_MODEL_FROM_DATABASE=HNS GE/10GE/25GE RDMA Network Controller + +pci:v000019E5d0000A224* + ID_MODEL_FROM_DATABASE=HNS GE/10GE/25GE/50GE RDMA Network Controller + +pci:v000019E5d0000A226* + ID_MODEL_FROM_DATABASE=HNS GE/10GE/25GE/50GE/100GE RDMA Network Controller + +pci:v000019E5d0000A22A* + ID_MODEL_FROM_DATABASE=HiSilicon Network For SDI + +pci:v000019E5d0000A22E* + ID_MODEL_FROM_DATABASE=HNS Network Controller (Virtual Function) + +pci:v000019E5d0000A22F* + ID_MODEL_FROM_DATABASE=HNS RDMA Network Controller (Virtual Function) + +pci:v000019E5d0000A230* + ID_MODEL_FROM_DATABASE=HiSilicon SAS 3.0 HBA + +pci:v000019E5d0000A235* + ID_MODEL_FROM_DATABASE=HiSilicon AHCI HBA + +pci:v000019E5d0000A238* + ID_MODEL_FROM_DATABASE=HiSilicon USB 3.0 Host Controller + +pci:v000019E5d0000A239* + ID_MODEL_FROM_DATABASE=HiSilicon USB 2.0 2-port Host Controller + +pci:v000019E5d0000A23A* + ID_MODEL_FROM_DATABASE=HiSilicon USB 2.0 Host Controller + +pci:v000019E5d0000A23B* + ID_MODEL_FROM_DATABASE=HiSilicon USB 1.1 Host Controller + +pci:v000019E5d0000A250* + ID_MODEL_FROM_DATABASE=HiSilicon ZIP Engine + +pci:v000019E5d0000A251* + ID_MODEL_FROM_DATABASE=HiSilicon ZIP Engine(Virtual Function) + +pci:v000019E5d0000A255* + ID_MODEL_FROM_DATABASE=HiSilicon SEC Engine + +pci:v000019E5d0000A256* + ID_MODEL_FROM_DATABASE=HiSilicon SEC Engine(Virtual Function) + +pci:v000019E5d0000A258* + ID_MODEL_FROM_DATABASE=HiSilicon HPRE Engine + +pci:v000019E5d0000A259* + ID_MODEL_FROM_DATABASE=HiSilicon HPRE Engine(Virtual Function) + +pci:v000019E5d0000A25A* + ID_MODEL_FROM_DATABASE=HiSilicon RDE Engine + +pci:v000019E5d0000A25B* + ID_MODEL_FROM_DATABASE=HiSilicon RDE Engine(Virtual Function) + +pci:v000019E7* + ID_VENDOR_FROM_DATABASE=NET (Network Equipment Technologies) + +pci:v000019E7d00001001* + ID_MODEL_FROM_DATABASE=STIX DSP Card + +pci:v000019E7d00001002* + ID_MODEL_FROM_DATABASE=STIX - 1 Port T1/E1 Card + +pci:v000019E7d00001003* + ID_MODEL_FROM_DATABASE=STIX - 2 Port T1/E1 Card + +pci:v000019E7d00001004* + ID_MODEL_FROM_DATABASE=STIX - 4 Port T1/E1 Card + +pci:v000019E7d00001005* + ID_MODEL_FROM_DATABASE=STIX - 4 Port FXS Card + +pci:v000019EE* + ID_VENDOR_FROM_DATABASE=Netronome Systems, Inc. + +pci:v000019F1* + ID_VENDOR_FROM_DATABASE=BFG Tech + +pci:v000019FF* + ID_VENDOR_FROM_DATABASE=Eclipse Electronic Systems, Inc. + +pci:v00001A03* + ID_VENDOR_FROM_DATABASE=ASPEED Technology, Inc. + +pci:v00001A03d00001150* + ID_MODEL_FROM_DATABASE=AST1150 PCI-to-PCI Bridge + +pci:v00001A03d00002000* + ID_MODEL_FROM_DATABASE=ASPEED Graphics Family + +pci:v00001A03d00002000sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=ASPEED Graphics Family (X10SRL-F) + +pci:v00001A05* + ID_VENDOR_FROM_DATABASE=deltaww + +pci:v00001A07* + ID_VENDOR_FROM_DATABASE=Kvaser AB + +pci:v00001A07d00000006* + ID_MODEL_FROM_DATABASE=CAN interface PC104+ HS/HS + +pci:v00001A07d00000007* + ID_MODEL_FROM_DATABASE=CAN interface PCIcanx II HS or HS/HS + +pci:v00001A07d00000008* + ID_MODEL_FROM_DATABASE=CAN interface PCIEcan HS or HS/HS + +pci:v00001A07d00000009* + ID_MODEL_FROM_DATABASE=CAN interface PCI104 HS/HS + +pci:v00001A08* + ID_VENDOR_FROM_DATABASE=Sierra semiconductor + +pci:v00001A08d00000000* + ID_MODEL_FROM_DATABASE=SC15064 + +pci:v00001A0E* + ID_VENDOR_FROM_DATABASE=DekTec Digital Video B.V. + +pci:v00001A0Ed0000083F* + ID_MODEL_FROM_DATABASE=DTA-2111 VHF/UHF Modulator + +pci:v00001A17* + ID_VENDOR_FROM_DATABASE=Force10 Networks, Inc. + +pci:v00001A17d00008002* + ID_MODEL_FROM_DATABASE=PB-10GE-2P 10GbE Security Card + +pci:v00001A1D* + ID_VENDOR_FROM_DATABASE=GFaI e.V. + +pci:v00001A1Dd00001A17* + ID_MODEL_FROM_DATABASE=Meta Networks MTP-1G IDPS NIC + +pci:v00001A1E* + ID_VENDOR_FROM_DATABASE=3Leaf Systems, Inc. + +pci:v00001A22* + ID_VENDOR_FROM_DATABASE=Ambric Inc. + +pci:v00001A29* + ID_VENDOR_FROM_DATABASE=Fortinet, Inc. + +pci:v00001A29d00004338* + ID_MODEL_FROM_DATABASE=CP8 Content Processor ASIC + +pci:v00001A29d00004E36* + ID_MODEL_FROM_DATABASE=NP6 Network Processor + +pci:v00001A29d00004E37* + ID_MODEL_FROM_DATABASE=NP7 Network Processor + +pci:v00001A2B* + ID_VENDOR_FROM_DATABASE=Ascom AG + +pci:v00001A2Bd00000000* + ID_MODEL_FROM_DATABASE=GESP v1.2 + +pci:v00001A2Bd00000001* + ID_MODEL_FROM_DATABASE=GESP v1.3 + +pci:v00001A2Bd00000002* + ID_MODEL_FROM_DATABASE=ECOMP v1.3 + +pci:v00001A2Bd00000005* + ID_MODEL_FROM_DATABASE=ETP v1.4 + +pci:v00001A2Bd0000000A* + ID_MODEL_FROM_DATABASE=ETP-104 v1.1 + +pci:v00001A2Bd0000000E* + ID_MODEL_FROM_DATABASE=DSLP-104 v1.1 + +pci:v00001A30* + ID_VENDOR_FROM_DATABASE=Lantiq + +pci:v00001A30d00000680* + ID_MODEL_FROM_DATABASE=MtW8171 [Hyperion II] + +pci:v00001A30d00000700* + ID_MODEL_FROM_DATABASE=Wave300 PSB8224 [Hyperion III] + +pci:v00001A30d00000710* + ID_MODEL_FROM_DATABASE=Wave300 PSB8231 [Hyperion III] + +pci:v00001A32* + ID_VENDOR_FROM_DATABASE=Quanta Microsystems, Inc + +pci:v00001A3B* + ID_VENDOR_FROM_DATABASE=AzureWave + +pci:v00001A3Bd00001112* + ID_MODEL_FROM_DATABASE=AR9285 Wireless Network Adapter (PCI-Express) + +pci:v00001A41* + ID_VENDOR_FROM_DATABASE=Tilera Corp. + +pci:v00001A41d00000001* + ID_MODEL_FROM_DATABASE=TILE64 processor + +pci:v00001A41d00000002* + ID_MODEL_FROM_DATABASE=TILEPro processor + +pci:v00001A41d00000200* + ID_MODEL_FROM_DATABASE=TILE-Gx processor + +pci:v00001A41d00000201* + ID_MODEL_FROM_DATABASE=TILE-Gx Processor Virtual Function + +pci:v00001A41d00002000* + ID_MODEL_FROM_DATABASE=TILE-Gx PCI Express Root Port + +pci:v00001A4A* + ID_VENDOR_FROM_DATABASE=SLAC National Accelerator Lab TID-AIR + +pci:v00001A4Ad00001000* + ID_MODEL_FROM_DATABASE=MCOR Power Supply Controller + +pci:v00001A4Ad00001010* + ID_MODEL_FROM_DATABASE=AMC EVR - Stockholm Timing Board + +pci:v00001A4Ad00001020* + ID_MODEL_FROM_DATABASE=Cluster On Board (COB) Ethernet Switch + +pci:v00001A4Ad00002000* + ID_MODEL_FROM_DATABASE=PGPCard - 4 Lane + +pci:v00001A4Ad00002001* + ID_MODEL_FROM_DATABASE=PGPCard - 8 Lane Plus EVR + +pci:v00001A4Ad00002010* + ID_MODEL_FROM_DATABASE=PCI-Express EVR + +pci:v00001A4Ad00002020* + ID_MODEL_FROM_DATABASE=PGP-GEN3 PCIe + +pci:v00001A4Ad00002030* + ID_MODEL_FROM_DATABASE=AXI Stream DAQ PCIe card + +pci:v00001A51* + ID_VENDOR_FROM_DATABASE=Hectronic AB + +pci:v00001A55* + ID_VENDOR_FROM_DATABASE=Rohde & Schwarz DVS GmbH + +pci:v00001A55d00000010* + ID_MODEL_FROM_DATABASE=SDStationOEM + +pci:v00001A55d00000011* + ID_MODEL_FROM_DATABASE=SDStationOEM II + +pci:v00001A55d00000020* + ID_MODEL_FROM_DATABASE=Centaurus + +pci:v00001A55d00000021* + ID_MODEL_FROM_DATABASE=Centaurus II + +pci:v00001A55d00000022* + ID_MODEL_FROM_DATABASE=Centaurus II LT + +pci:v00001A55d00000030* + ID_MODEL_FROM_DATABASE=CLIPSTER-VPU 1.x (Hugo) + +pci:v00001A55d00000040* + ID_MODEL_FROM_DATABASE=Hydra Cinema (JPEG) + +pci:v00001A55d00000050* + ID_MODEL_FROM_DATABASE=CLIPSTER-VPU 2.x (DigiLab) + +pci:v00001A55d00000060* + ID_MODEL_FROM_DATABASE=CLIPSTER-DCI 2.x (HydraX) + +pci:v00001A55d00000061* + ID_MODEL_FROM_DATABASE=Atomix + +pci:v00001A55d00000062* + ID_MODEL_FROM_DATABASE=Atomix LT + +pci:v00001A55d00000063* + ID_MODEL_FROM_DATABASE=Atomix HDMI + +pci:v00001A55d00000064* + ID_MODEL_FROM_DATABASE=Atomix STAN + +pci:v00001A55d00000065* + ID_MODEL_FROM_DATABASE=Atomix HDMI STAN + +pci:v00001A55d00000070* + ID_MODEL_FROM_DATABASE=RED Rocket + +pci:v00001A55d00000090* + ID_MODEL_FROM_DATABASE=CinePlay + +pci:v00001A56* + ID_VENDOR_FROM_DATABASE=Bigfoot Networks, Inc. + +pci:v00001A57* + ID_VENDOR_FROM_DATABASE=Highly Reliable Systems + +pci:v00001A58* + ID_VENDOR_FROM_DATABASE=Razer USA Ltd. + +pci:v00001A5D* + ID_VENDOR_FROM_DATABASE=Celoxica + +pci:v00001A5E* + ID_VENDOR_FROM_DATABASE=Aprius Inc. + +pci:v00001A5F* + ID_VENDOR_FROM_DATABASE=System TALKS Inc. + +pci:v00001A68* + ID_VENDOR_FROM_DATABASE=VirtenSys Limited + +pci:v00001A71* + ID_VENDOR_FROM_DATABASE=XenSource, Inc. + +pci:v00001A73* + ID_VENDOR_FROM_DATABASE=Violin Memory, Inc + +pci:v00001A73d00000001* + ID_MODEL_FROM_DATABASE=Mozart [Memory Appliance 1010] + +pci:v00001A76* + ID_VENDOR_FROM_DATABASE=Wavesat + +pci:v00001A77* + ID_VENDOR_FROM_DATABASE=Lightfleet Corporation + +pci:v00001A78* + ID_VENDOR_FROM_DATABASE=Virident Systems Inc. + +pci:v00001A78d00000031* + ID_MODEL_FROM_DATABASE=FlashMAX Drive + +pci:v00001A78d00000031sv00001A78sd00000034* + ID_MODEL_FROM_DATABASE=FlashMAX Drive (FlashMAX PCIe SSD [rev 3]) + +pci:v00001A78d00000031sv00001A78sd00000037* + ID_MODEL_FROM_DATABASE=FlashMAX Drive (FlashMAX PCIe SSD [rev 3D]) + +pci:v00001A78d00000031sv00001A78sd00000038* + ID_MODEL_FROM_DATABASE=FlashMAX Drive (FlashMAX PCIe SSD [rev 4]) + +pci:v00001A78d00000031sv00001A78sd00000039* + ID_MODEL_FROM_DATABASE=FlashMAX Drive (FlashMAX PCIe SSD [rev 4D]) + +pci:v00001A78d00000040* + ID_MODEL_FROM_DATABASE=FlashMAX II + +pci:v00001A78d00000041* + ID_MODEL_FROM_DATABASE=FlashMAX II + +pci:v00001A78d00000042* + ID_MODEL_FROM_DATABASE=FlashMAX II + +pci:v00001A78d00000050* + ID_MODEL_FROM_DATABASE=FlashMAX III + +pci:v00001A84* + ID_VENDOR_FROM_DATABASE=Commex Technologies + +pci:v00001A84d00000001* + ID_MODEL_FROM_DATABASE=Vulcan SP HT6210 10-Gigabit Ethernet (rev 02) + +pci:v00001A88* + ID_VENDOR_FROM_DATABASE=MEN Mikro Elektronik + +pci:v00001A88d00004D45* + ID_MODEL_FROM_DATABASE=Multifunction IP core + +pci:v00001A8A* + ID_VENDOR_FROM_DATABASE=StarBridge, Inc. + +pci:v00001A8C* + ID_VENDOR_FROM_DATABASE=Verigy Pte. Ltd. + +pci:v00001A8Cd00001100* + ID_MODEL_FROM_DATABASE=E8001-66443 PCI Express CIC + +pci:v00001A8E* + ID_VENDOR_FROM_DATABASE=DRS Technologies + +pci:v00001A8Ed00002090* + ID_MODEL_FROM_DATABASE=Model 2090 PCI Express + +pci:v00001AA8* + ID_VENDOR_FROM_DATABASE=Ciprico, Inc. + +pci:v00001AA8d00000009* + ID_MODEL_FROM_DATABASE=RAIDCore Controller + +pci:v00001AA8d0000000A* + ID_MODEL_FROM_DATABASE=RAIDCore Controller + +pci:v00001AAE* + ID_VENDOR_FROM_DATABASE=Global Velocity, Inc. + +pci:v00001AB4* + ID_VENDOR_FROM_DATABASE=Distributed Management Task Force, Inc. (DMTF) + +pci:v00001AB6* + ID_VENDOR_FROM_DATABASE=CalDigit, Inc. + +pci:v00001AB6d00006201* + ID_MODEL_FROM_DATABASE=RAID Card + +pci:v00001AB8* + ID_VENDOR_FROM_DATABASE=Parallels, Inc. + +pci:v00001AB8d00004000* + ID_MODEL_FROM_DATABASE=Virtual Machine Communication Interface + +pci:v00001AB8d00004005* + ID_MODEL_FROM_DATABASE=Accelerated Virtual Video Adapter + +pci:v00001AB8d00004006* + ID_MODEL_FROM_DATABASE=Memory Ballooning Controller + +pci:v00001AB9* + ID_VENDOR_FROM_DATABASE=Espia Srl + +pci:v00001AC8* + ID_VENDOR_FROM_DATABASE=Aeroflex Gaisler + +pci:v00001ACC* + ID_VENDOR_FROM_DATABASE=Point of View BV + +pci:v00001AD7* + ID_VENDOR_FROM_DATABASE=Spectracom Corporation + +pci:v00001AD7d00008000* + ID_MODEL_FROM_DATABASE=TSync-PCIe Time Code Processor + +pci:v00001AD7d00009100* + ID_MODEL_FROM_DATABASE=TPRO-PCI-66U Timecode Reader/Generator + +pci:v00001ADE* + ID_VENDOR_FROM_DATABASE=Spin Master Ltd. + +pci:v00001ADEd00001501* + ID_MODEL_FROM_DATABASE=Swipetech barcode scanner + +pci:v00001ADEd00003038* + ID_MODEL_FROM_DATABASE=PCIe Video Bridge + +pci:v00001ADEd00003038sv000013C2sd00003016* + ID_MODEL_FROM_DATABASE=PCIe Video Bridge (TT-budget S2-4200 Twin) + +pci:v00001ADEd00003038sv00004254sd00000552* + ID_MODEL_FROM_DATABASE=PCIe Video Bridge (S952 v3) + +pci:v00001AE0* + ID_VENDOR_FROM_DATABASE=Google, Inc. + +pci:v00001AE0d00000042* + ID_MODEL_FROM_DATABASE=Compute Engine Virtual Ethernet [gVNIC] + +pci:v00001AE3* + ID_VENDOR_FROM_DATABASE=SANBlaze Technology, Inc. + +pci:v00001AE7* + ID_VENDOR_FROM_DATABASE=First Wise Media GmbH + +pci:v00001AE7d00000520* + ID_MODEL_FROM_DATABASE=HFC-S PCI A [X-TENSIONS XC-520] + +pci:v00001AE8* + ID_VENDOR_FROM_DATABASE=Silicon Software GmbH + +pci:v00001AE8d00000A40* + ID_MODEL_FROM_DATABASE=microEnable IV-BASE x1 + +pci:v00001AE8d00000A41* + ID_MODEL_FROM_DATABASE=microEnable IV-FULL x1 + +pci:v00001AE8d00000A44* + ID_MODEL_FROM_DATABASE=microEnable IV-FULL x4 + +pci:v00001AE8d00000E44* + ID_MODEL_FROM_DATABASE=microEnable IV-GigE x4 + +pci:v00001AE9* + ID_VENDOR_FROM_DATABASE=Wilocity Ltd. + +pci:v00001AE9d00000101* + ID_MODEL_FROM_DATABASE=Wil6200 PCI Express Upstream Port + +pci:v00001AE9d00000200* + ID_MODEL_FROM_DATABASE=Wil6200 PCI Express Port + +pci:v00001AE9d00000201* + ID_MODEL_FROM_DATABASE=Wil6200 Wireless PCI Express Port + +pci:v00001AE9d00000301* + ID_MODEL_FROM_DATABASE=Wil6200 802.11ad Wireless Network Adapter + +pci:v00001AE9d00000302* + ID_MODEL_FROM_DATABASE=Wil6200 802.11ad Wireless Network Adapter + +pci:v00001AE9d00000310* + ID_MODEL_FROM_DATABASE=Wil6200 802.11ad Wireless Network Adapter + +pci:v00001AEA* + ID_VENDOR_FROM_DATABASE=Alcor Micro + +pci:v00001AEAd00006601* + ID_MODEL_FROM_DATABASE=AU6601 PCI-E Flash card reader controller + +pci:v00001AEAd00006621* + ID_MODEL_FROM_DATABASE=AU6621 PCI-E Flash card reader controller + +pci:v00001AEAd00006625* + ID_MODEL_FROM_DATABASE=AU6625 PCI-E Flash card reader controller + +pci:v00001AEC* + ID_VENDOR_FROM_DATABASE=Wolfson Microelectronics + +pci:v00001AED* + ID_VENDOR_FROM_DATABASE=SanDisk + +pci:v00001AEDd00001003* + ID_MODEL_FROM_DATABASE=ioDimm3 (v1.2) + +pci:v00001AEDd00001005* + ID_MODEL_FROM_DATABASE=ioDimm3 + +pci:v00001AEDd00001005sv00001014sd000003C3* + ID_MODEL_FROM_DATABASE=ioDimm3 (High IOPS SSD PCIe Adapter) + +pci:v00001AEDd00001005sv0000103Csd0000176F* + ID_MODEL_FROM_DATABASE=ioDimm3 (1.28TB MLC PCIe ioDrive Duo) + +pci:v00001AEDd00001005sv0000103Csd00001770* + ID_MODEL_FROM_DATABASE=ioDimm3 (5.2TB MLC PCIe ioDrive Octal) + +pci:v00001AEDd00001005sv0000103Csd0000178B* + ID_MODEL_FROM_DATABASE=ioDimm3 (160GB SLC PCIe ioDrive) + +pci:v00001AEDd00001005sv0000103Csd0000178C* + ID_MODEL_FROM_DATABASE=ioDimm3 (320GB MLC PCIe ioDrive) + +pci:v00001AEDd00001005sv0000103Csd0000178D* + ID_MODEL_FROM_DATABASE=ioDimm3 (320GB SLC PCIe ioDrive Duo) + +pci:v00001AEDd00001005sv0000103Csd0000178E* + ID_MODEL_FROM_DATABASE=ioDimm3 (640GB MLC PCIe ioDrive Duo) + +pci:v00001AEDd00001006* + ID_MODEL_FROM_DATABASE=ioXtreme + +pci:v00001AEDd00001007* + ID_MODEL_FROM_DATABASE=ioXtreme Pro + +pci:v00001AEDd00001008* + ID_MODEL_FROM_DATABASE=ioXtreme-2 + +pci:v00001AEDd00002001* + ID_MODEL_FROM_DATABASE=ioDrive2 + +pci:v00001AEDd00003001* + ID_MODEL_FROM_DATABASE=ioMemory FHHL + +pci:v00001AEDd00003002* + ID_MODEL_FROM_DATABASE=ioMemory HHHL + +pci:v00001AEDd00003003* + ID_MODEL_FROM_DATABASE=ioMemory Mezzanine + +pci:v00001AEE* + ID_VENDOR_FROM_DATABASE=Caustic Graphics Inc. + +pci:v00001AF4* + ID_VENDOR_FROM_DATABASE=Red Hat, Inc. + +pci:v00001AF4d00001000* + ID_MODEL_FROM_DATABASE=Virtio network device + +pci:v00001AF4d00001001* + ID_MODEL_FROM_DATABASE=Virtio block device + +pci:v00001AF4d00001002* + ID_MODEL_FROM_DATABASE=Virtio memory balloon + +pci:v00001AF4d00001003* + ID_MODEL_FROM_DATABASE=Virtio console + +pci:v00001AF4d00001004* + ID_MODEL_FROM_DATABASE=Virtio SCSI + +pci:v00001AF4d00001005* + ID_MODEL_FROM_DATABASE=Virtio RNG + +pci:v00001AF4d00001009* + ID_MODEL_FROM_DATABASE=Virtio filesystem + +pci:v00001AF4d00001041* + ID_MODEL_FROM_DATABASE=Virtio network device + +pci:v00001AF4d00001042* + ID_MODEL_FROM_DATABASE=Virtio block device + +pci:v00001AF4d00001043* + ID_MODEL_FROM_DATABASE=Virtio console + +pci:v00001AF4d00001044* + ID_MODEL_FROM_DATABASE=Virtio RNG + +pci:v00001AF4d00001045* + ID_MODEL_FROM_DATABASE=Virtio memory balloon + +pci:v00001AF4d00001048* + ID_MODEL_FROM_DATABASE=Virtio SCSI + +pci:v00001AF4d00001049* + ID_MODEL_FROM_DATABASE=Virtio filesystem + +pci:v00001AF4d00001050* + ID_MODEL_FROM_DATABASE=Virtio GPU + +pci:v00001AF4d00001052* + ID_MODEL_FROM_DATABASE=Virtio input + +pci:v00001AF4d00001110* + ID_MODEL_FROM_DATABASE=Inter-VM shared memory + +pci:v00001AF4d00001110sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=Inter-VM shared memory (QEMU Virtual Machine) + +pci:v00001AF5* + ID_VENDOR_FROM_DATABASE=Netezza Corp. + +pci:v00001AFA* + ID_VENDOR_FROM_DATABASE=J & W Electronics Co., Ltd. + +pci:v00001B03* + ID_VENDOR_FROM_DATABASE=Magnum Semiconductor, Inc, + +pci:v00001B03d00006100* + ID_MODEL_FROM_DATABASE=DXT/DXTPro Multiformat Broadcast HD/SD Encoder/Decoder/Transcoder + +pci:v00001B03d00007000* + ID_MODEL_FROM_DATABASE=D7 Multiformat Broadcast HD/SD Encoder/Decoder/Transcoder + +pci:v00001B08* + ID_VENDOR_FROM_DATABASE=MSC Technologies GmbH + +pci:v00001B0A* + ID_VENDOR_FROM_DATABASE=Pegatron + +pci:v00001B13* + ID_VENDOR_FROM_DATABASE=Jaton Corp + +pci:v00001B1A* + ID_VENDOR_FROM_DATABASE=K&F Computing Research Co. + +pci:v00001B1Ad00000E70* + ID_MODEL_FROM_DATABASE=GRAPE + +pci:v00001B21* + ID_VENDOR_FROM_DATABASE=ASMedia Technology Inc. + +pci:v00001B21d00000611* + ID_MODEL_FROM_DATABASE=ASM1061 SATA IDE Controller + +pci:v00001B21d00000612* + ID_MODEL_FROM_DATABASE=ASM1062 Serial ATA Controller + +pci:v00001B21d00000612sv00001849sd00000612* + ID_MODEL_FROM_DATABASE=ASM1062 Serial ATA Controller (Motherboard) + +pci:v00001B21d00001042* + ID_MODEL_FROM_DATABASE=ASM1042 SuperSpeed USB Host Controller + +pci:v00001B21d00001042sv00001043sd00008488* + ID_MODEL_FROM_DATABASE=ASM1042 SuperSpeed USB Host Controller (P8B WS Motherboard) + +pci:v00001B21d00001042sv00001849sd00001042* + ID_MODEL_FROM_DATABASE=ASM1042 SuperSpeed USB Host Controller (Motherboard) + +pci:v00001B21d00001080* + ID_MODEL_FROM_DATABASE=ASM1083/1085 PCIe to PCI Bridge + +pci:v00001B21d00001080sv00001849sd00001080* + ID_MODEL_FROM_DATABASE=ASM1083/1085 PCIe to PCI Bridge (Motherboard) + +pci:v00001B21d00001142* + ID_MODEL_FROM_DATABASE=ASM1042A USB 3.0 Host Controller + +pci:v00001B21d00001184* + ID_MODEL_FROM_DATABASE=ASM1184e PCIe Switch Port + +pci:v00001B21d00001184sv00001849sd00001184* + ID_MODEL_FROM_DATABASE=ASM1184e PCIe Switch Port (ASM1184e PCIe Switch) + +pci:v00001B21d00001242* + ID_MODEL_FROM_DATABASE=ASM1142 USB 3.1 Host Controller + +pci:v00001B21d00001343* + ID_MODEL_FROM_DATABASE=ASM1143 USB 3.1 Host Controller + +pci:v00001B21d00002142* + ID_MODEL_FROM_DATABASE=ASM2142 USB 3.1 Host Controller + +pci:v00001B26* + ID_VENDOR_FROM_DATABASE=Netcope Technologies, a.s. + +pci:v00001B26d0000C132* + ID_MODEL_FROM_DATABASE=COMBO-LXT155 + +pci:v00001B26d0000C1C0* + ID_MODEL_FROM_DATABASE=NFB-100G1-e0 + +pci:v00001B26d0000C1C1* + ID_MODEL_FROM_DATABASE=NFB-100G1-e1 + +pci:v00001B26d0000C250* + ID_MODEL_FROM_DATABASE=NFB-200G2-master + +pci:v00001B26d0000C251* + ID_MODEL_FROM_DATABASE=NFB-200G2-slave + +pci:v00001B26d0000C2C0* + ID_MODEL_FROM_DATABASE=NFB-100G2-e0 + +pci:v00001B26d0000C2C1* + ID_MODEL_FROM_DATABASE=NFB-100G2-e1 + +pci:v00001B26d0000CB20* + ID_MODEL_FROM_DATABASE=COMBO-20G + +pci:v00001B26d0000CB40* + ID_MODEL_FROM_DATABASE=COMBO-40G + +pci:v00001B26d0000CB80* + ID_MODEL_FROM_DATABASE=NFB-40G2 + +pci:v00001B2C* + ID_VENDOR_FROM_DATABASE=Opal-RT Technologies Inc. + +pci:v00001B36* + ID_VENDOR_FROM_DATABASE=Red Hat, Inc. + +pci:v00001B36d00000001* + ID_MODEL_FROM_DATABASE=QEMU PCI-PCI bridge + +pci:v00001B36d00000002* + ID_MODEL_FROM_DATABASE=QEMU PCI 16550A Adapter + +pci:v00001B36d00000002sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=QEMU PCI 16550A Adapter (QEMU Virtual Machine) + +pci:v00001B36d00000003* + ID_MODEL_FROM_DATABASE=QEMU PCI Dual-port 16550A Adapter + +pci:v00001B36d00000003sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=QEMU PCI Dual-port 16550A Adapter (QEMU Virtual Machine) + +pci:v00001B36d00000004* + ID_MODEL_FROM_DATABASE=QEMU PCI Quad-port 16550A Adapter + +pci:v00001B36d00000004sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=QEMU PCI Quad-port 16550A Adapter (QEMU Virtual Machine) + +pci:v00001B36d00000005* + ID_MODEL_FROM_DATABASE=QEMU PCI Test Device + +pci:v00001B36d00000005sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=QEMU PCI Test Device (QEMU Virtual Machine) + +pci:v00001B36d00000006* + ID_MODEL_FROM_DATABASE=PCI Rocker Ethernet switch device + +pci:v00001B36d00000007* + ID_MODEL_FROM_DATABASE=PCI SD Card Host Controller Interface + +pci:v00001B36d00000008* + ID_MODEL_FROM_DATABASE=QEMU PCIe Host bridge + +pci:v00001B36d00000009* + ID_MODEL_FROM_DATABASE=QEMU PCI Expander bridge + +pci:v00001B36d0000000A* + ID_MODEL_FROM_DATABASE=PCI-PCI bridge (multiseat) + +pci:v00001B36d0000000B* + ID_MODEL_FROM_DATABASE=QEMU PCIe Expander bridge + +pci:v00001B36d0000000C* + ID_MODEL_FROM_DATABASE=QEMU PCIe Root port + +pci:v00001B36d0000000D* + ID_MODEL_FROM_DATABASE=QEMU XHCI Host Controller + +pci:v00001B36d00000100* + ID_MODEL_FROM_DATABASE=QXL paravirtual graphic card + +pci:v00001B36d00000100sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=QXL paravirtual graphic card (QEMU Virtual Machine) + +pci:v00001B37* + ID_VENDOR_FROM_DATABASE=Signal Processing Devices Sweden AB + +pci:v00001B37d00000001* + ID_MODEL_FROM_DATABASE=ADQ214 + +pci:v00001B37d00000003* + ID_MODEL_FROM_DATABASE=ADQ114 + +pci:v00001B37d00000005* + ID_MODEL_FROM_DATABASE=ADQ112 + +pci:v00001B37d0000000E* + ID_MODEL_FROM_DATABASE=ADQ108 + +pci:v00001B37d0000000F* + ID_MODEL_FROM_DATABASE=ADQDSP + +pci:v00001B37d00000014* + ID_MODEL_FROM_DATABASE=ADQ412 + +pci:v00001B37d00000015* + ID_MODEL_FROM_DATABASE=ADQ212 + +pci:v00001B37d0000001B* + ID_MODEL_FROM_DATABASE=SDR14 + +pci:v00001B37d0000001C* + ID_MODEL_FROM_DATABASE=ADQ1600 + +pci:v00001B37d0000001E* + ID_MODEL_FROM_DATABASE=ADQ208 + +pci:v00001B37d0000001F* + ID_MODEL_FROM_DATABASE=DSU + +pci:v00001B37d00000020* + ID_MODEL_FROM_DATABASE=ADQ14 + +pci:v00001B37d00000023* + ID_MODEL_FROM_DATABASE=ADQ7 + +pci:v00001B37d00000026* + ID_MODEL_FROM_DATABASE=ADQ8 + +pci:v00001B37d00002014* + ID_MODEL_FROM_DATABASE=TX320 + +pci:v00001B37d00002019* + ID_MODEL_FROM_DATABASE=S6000 + +pci:v00001B39* + ID_VENDOR_FROM_DATABASE=sTec, Inc. + +pci:v00001B39d00000001* + ID_MODEL_FROM_DATABASE=S1120 PCIe Accelerator SSD + +pci:v00001B3A* + ID_VENDOR_FROM_DATABASE=Westar Display Technologies + +pci:v00001B3Ad00007589* + ID_MODEL_FROM_DATABASE=HRED J2000 - JPEG 2000 Video Codec Device + +pci:v00001B3E* + ID_VENDOR_FROM_DATABASE=Teradata Corp. + +pci:v00001B3Ed00001FA8* + ID_MODEL_FROM_DATABASE=BYNET BIC2SE/X + +pci:v00001B3Ed00001FA8sv00001B3Esd000000A3* + ID_MODEL_FROM_DATABASE=BYNET BIC2SE/X (BYNET BIC2SX) + +pci:v00001B3Ed00001FA8sv00001B3Esd000000C3* + ID_MODEL_FROM_DATABASE=BYNET BIC2SE/X (BYNET BIC2SE) + +pci:v00001B40* + ID_VENDOR_FROM_DATABASE=Schooner Information Technology, Inc. + +pci:v00001B47* + ID_VENDOR_FROM_DATABASE=Numascale AS + +pci:v00001B47d00000601* + ID_MODEL_FROM_DATABASE=NumaChip N601 + +pci:v00001B47d00000602* + ID_MODEL_FROM_DATABASE=NumaChip N602 + +pci:v00001B4B* + ID_VENDOR_FROM_DATABASE=Marvell Technology Group Ltd. + +pci:v00001B4Bd00000640* + ID_MODEL_FROM_DATABASE=88SE9128 SATA III 6Gb/s RAID Controller + +pci:v00001B4Bd00009120* + ID_MODEL_FROM_DATABASE=88SE9120 SATA 6Gb/s Controller + +pci:v00001B4Bd00009123* + ID_MODEL_FROM_DATABASE=88SE9123 PCIe SATA 6.0 Gb/s controller + +pci:v00001B4Bd00009123sv0000DC93sd0000600E* + ID_MODEL_FROM_DATABASE=88SE9123 PCIe SATA 6.0 Gb/s controller (DC-6xxe series SATA 6G controller) + +pci:v00001B4Bd00009125* + ID_MODEL_FROM_DATABASE=88SE9125 PCIe SATA 6.0 Gb/s controller + +pci:v00001B4Bd00009128* + ID_MODEL_FROM_DATABASE=88SE9128 PCIe SATA 6 Gb/s RAID controller + +pci:v00001B4Bd00009130* + ID_MODEL_FROM_DATABASE=88SE9128 PCIe SATA 6 Gb/s RAID controller with HyperDuo + +pci:v00001B4Bd00009130sv00001043sd00008438* + ID_MODEL_FROM_DATABASE=88SE9128 PCIe SATA 6 Gb/s RAID controller with HyperDuo (P8P67 Deluxe Motherboard) + +pci:v00001B4Bd00009172* + ID_MODEL_FROM_DATABASE=88SE9172 SATA 6Gb/s Controller + +pci:v00001B4Bd00009178* + ID_MODEL_FROM_DATABASE=88SE9170 PCIe SATA 6Gb/s Controller + +pci:v00001B4Bd0000917A* + ID_MODEL_FROM_DATABASE=88SE9172 SATA III 6Gb/s RAID Controller + +pci:v00001B4Bd00009183* + ID_MODEL_FROM_DATABASE=88SS9183 PCIe SSD Controller + +pci:v00001B4Bd00009192* + ID_MODEL_FROM_DATABASE=88SE9172 SATA III 6Gb/s RAID Controller + +pci:v00001B4Bd000091A0* + ID_MODEL_FROM_DATABASE=88SE912x SATA 6Gb/s Controller [IDE mode] + +pci:v00001B4Bd000091A4* + ID_MODEL_FROM_DATABASE=88SE912x IDE Controller + +pci:v00001B4Bd00009220* + ID_MODEL_FROM_DATABASE=88SE9220 PCIe 2.0 x2 2-port SATA 6 Gb/s RAID Controller + +pci:v00001B4Bd00009230* + ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller + +pci:v00001B4Bd00009230sv00001028sd00001FD6* + ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (BOSS-S1 Adapter) + +pci:v00001B4Bd00009230sv00001028sd00001FDF* + ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (BOSS-S1 Modular) + +pci:v00001B4Bd00009230sv00001028sd00001FE2* + ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (BOSS-S1 Adapter) + +pci:v00001B4Bd00009230sv00001028sd00002010* + ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (BOSS-S2 Adapter) + +pci:v00001B4Bd00009230sv00001D49sd00000300* + ID_MODEL_FROM_DATABASE=88SE9230 PCIe SATA 6Gb/s Controller (ThinkSystem M.2 with Mirroring Enablement Kit) + +pci:v00001B4Bd00009235* + ID_MODEL_FROM_DATABASE=88SE9235 PCIe 2.0 x2 4-port SATA 6 Gb/s Controller + +pci:v00001B4Bd00009445* + ID_MODEL_FROM_DATABASE=88SE9445 PCIe 2.0 x4 4-Port SAS/SATA 6 Gbps RAID Controller + +pci:v00001B4Bd00009480* + ID_MODEL_FROM_DATABASE=88SE9480 SAS/SATA 6Gb/s RAID controller + +pci:v00001B4Bd00009485* + ID_MODEL_FROM_DATABASE=88SE9485 SAS/SATA 6Gb/s controller + +pci:v00001B55* + ID_VENDOR_FROM_DATABASE=NetUP Inc. + +pci:v00001B55d000018F6* + ID_MODEL_FROM_DATABASE=Dual DVB Universal CI card + +pci:v00001B55d000018F7* + ID_MODEL_FROM_DATABASE=Dual DVB Universal CI card rev 1.4 + +pci:v00001B55d00002A2C* + ID_MODEL_FROM_DATABASE=Dual DVB-S2-CI card + +pci:v00001B55d0000E2E4* + ID_MODEL_FROM_DATABASE=Dual DVB-T/C-CI RF card + +pci:v00001B55d0000E5F4* + ID_MODEL_FROM_DATABASE=MPEG2 and H264 Encoder-Transcoder + +pci:v00001B55d0000F1C4* + ID_MODEL_FROM_DATABASE=Dual ASI-RX/TX-CI card + +pci:v00001B66* + ID_VENDOR_FROM_DATABASE=DELTACAST + +pci:v00001B66d00000007* + ID_MODEL_FROM_DATABASE=DELTA-3G-elp-d + +pci:v00001B6F* + ID_VENDOR_FROM_DATABASE=Etron Technology, Inc. + +pci:v00001B6Fd00007023* + ID_MODEL_FROM_DATABASE=EJ168 USB 3.0 Host Controller + +pci:v00001B6Fd00007052* + ID_MODEL_FROM_DATABASE=EJ188/EJ198 USB 3.0 Host Controller + +pci:v00001B6Fd00007052sv00001849sd00007052* + ID_MODEL_FROM_DATABASE=EJ188/EJ198 USB 3.0 Host Controller (QC5000-ITX/PH) + +pci:v00001B73* + ID_VENDOR_FROM_DATABASE=Fresco Logic + +pci:v00001B73d00001000* + ID_MODEL_FROM_DATABASE=FL1000G USB 3.0 Host Controller + +pci:v00001B73d00001000sv00001D5Csd00001000* + ID_MODEL_FROM_DATABASE=FL1000G USB 3.0 Host Controller (Anker USB 3.0 Express Card) + +pci:v00001B73d00001009* + ID_MODEL_FROM_DATABASE=FL1009 USB 3.0 Host Controller + +pci:v00001B73d00001100* + ID_MODEL_FROM_DATABASE=FL1100 USB 3.0 Host Controller + +pci:v00001B73d00001100sv000016B8sd00006E31* + ID_MODEL_FROM_DATABASE=FL1100 USB 3.0 Host Controller (Allegro Pro USB 3.0 PCIe) + +pci:v00001B74* + ID_VENDOR_FROM_DATABASE=OpenVox Communication Co. Ltd. + +pci:v00001B74d00000115* + ID_MODEL_FROM_DATABASE=D115P/D115E Single-port E1/T1 card + +pci:v00001B74d0000D130* + ID_MODEL_FROM_DATABASE=D130P/D130E Single-port E1/T1 card (3rd GEN) + +pci:v00001B74d0000D210* + ID_MODEL_FROM_DATABASE=D210P/D210E Dual-port E1/T1 card(2nd generation) + +pci:v00001B74d0000D230* + ID_MODEL_FROM_DATABASE=D230 Dual-port E1/T1 card (2nd generation) + +pci:v00001B74d0000D410* + ID_MODEL_FROM_DATABASE=D410/430 Quad-port E1/T1 card + +pci:v00001B74d0000D430* + ID_MODEL_FROM_DATABASE=D410/430 Quad-port E1/T1 card + +pci:v00001B79* + ID_VENDOR_FROM_DATABASE=Absolute Analysis + +pci:v00001B85* + ID_VENDOR_FROM_DATABASE=OCZ Technology Group, Inc. + +pci:v00001B85d00001041* + ID_MODEL_FROM_DATABASE=RevoDrive 3 X2 PCI-Express SSD 240 GB (Marvell Controller) + +pci:v00001B85d00006018* + ID_MODEL_FROM_DATABASE=RD400/400A SSD + +pci:v00001B85d00008788* + ID_MODEL_FROM_DATABASE=RevoDrive Hybrid + +pci:v00001B94* + ID_VENDOR_FROM_DATABASE=Signatec / Dynamic Signals Corp + +pci:v00001B94d0000E400* + ID_MODEL_FROM_DATABASE=PX14400 Dual Xilinx Virtex5 based Digitizer + +pci:v00001B96* + ID_VENDOR_FROM_DATABASE=Western Digital + +pci:v00001B9A* + ID_VENDOR_FROM_DATABASE=XAVi Technologies Corp. + +pci:v00001BAA* + ID_VENDOR_FROM_DATABASE=QNAP Systems, Inc. + +pci:v00001BAD* + ID_VENDOR_FROM_DATABASE=ReFLEX CES + +pci:v00001BADd0000C001* + ID_MODEL_FROM_DATABASE=XpressGXA10-LP1150 + +pci:v00001BADd0000C002* + ID_MODEL_FROM_DATABASE=XpressGXA10-LP1151 + +pci:v00001BB0* + ID_VENDOR_FROM_DATABASE=SimpliVity Corporation + +pci:v00001BB0d00000002* + ID_MODEL_FROM_DATABASE=OmniCube Accelerator OA-3000 + +pci:v00001BB0d00000010* + ID_MODEL_FROM_DATABASE=OmniCube Accelerator OA-3000-2 + +pci:v00001BB1* + ID_VENDOR_FROM_DATABASE=Seagate Technology PLC + +pci:v00001BB1d0000005D* + ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage + +pci:v00001BB1d0000005Dsv00001BB1sd00006501* + ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A1536 1.5TB) + +pci:v00001BB1d0000005Dsv00001BB1sd00006502* + ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A2048) + +pci:v00001BB1d0000005Dsv00001BB1sd00006503* + ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A4096) + +pci:v00001BB1d0000005Dsv00001BB1sd00006511* + ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XH6550-2GB DRAM) + +pci:v00001BB1d0000005Dsv00001BB1sd00006512* + ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XH6550-8GB DRAM) + +pci:v00001BB1d0000005Dsv00001BB1sd00006521* + ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A1536 1.5TB) + +pci:v00001BB1d0000005Dsv00001BB1sd00006522* + ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A2048) + +pci:v00001BB1d0000005Dsv00001BB1sd00006523* + ID_MODEL_FROM_DATABASE=Nytro PCIe Flash Storage (Nytro XP6500-8A4096) + +pci:v00001BB1d00000100* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage + +pci:v00001BB1d00000100sv00001BB1sd00000101* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro XF1440) + +pci:v00001BB1d00000100sv00001BB1sd00000103* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5000) + +pci:v00001BB1d00000100sv00001BB1sd00000105* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5020) + +pci:v00001BB1d00000100sv00001BB1sd00000106* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5020 TCG) + +pci:v00001BB1d00000100sv00001BB1sd00000107* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5320) + +pci:v00001BB1d00000100sv00001BB1sd00000108* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5320 TCG) + +pci:v00001BB1d00000100sv00001BB1sd00000121* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro XM1440) + +pci:v00001BB1d00000100sv00001BB1sd00000123* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5000) + +pci:v00001BB1d00000100sv00001BB1sd00000125* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5020) + +pci:v00001BB1d00000100sv00001BB1sd00000126* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5020) + +pci:v00001BB1d00000100sv00001BB1sd00000127* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5320 M.2) + +pci:v00001BB1d00000100sv00001BB1sd00000128* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5320 M.2 TCG) + +pci:v00001BB1d00000100sv00001BB1sd00000131* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5320 M.2) + +pci:v00001BB1d00000100sv00001BB1sd00000132* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5320 M.2 TCG) + +pci:v00001BB1d00000100sv00001BB1sd00000141* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5320 E1.S) + +pci:v00001BB1d00000100sv00001BB1sd00000142* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5320 E1.S TCG) + +pci:v00001BB1d00000100sv00001BB1sd00000151* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5520) + +pci:v00001BB1d00000100sv00001BB1sd00000152* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro 5520 TCG) + +pci:v00001BB1d00000100sv00001BB1sd000001A1* + ID_MODEL_FROM_DATABASE=Nytro Flash Storage (Nytro XP7102) + +pci:v00001BB3* + ID_VENDOR_FROM_DATABASE=Bluecherry + +pci:v00001BB3d00004304* + ID_MODEL_FROM_DATABASE=BC-04120A MPEG4 4 port video encoder / decoder + +pci:v00001BB3d00004309* + ID_MODEL_FROM_DATABASE=BC-08240A MPEG4 4 port video encoder / decoder + +pci:v00001BB3d00004310* + ID_MODEL_FROM_DATABASE=BC-16480A MPEG4 16 port video encoder / decoder + +pci:v00001BB3d00004E04* + ID_MODEL_FROM_DATABASE=BC-04120A 4 port MPEG4 video encoder / decoder + +pci:v00001BB3d00004E09* + ID_MODEL_FROM_DATABASE=BC-08240A 8 port MPEG4 video encoder / decoder + +pci:v00001BB3d00004E10* + ID_MODEL_FROM_DATABASE=BC-16480A 16 port MPEG4 video encoder / decoder + +pci:v00001BB3d00005304* + ID_MODEL_FROM_DATABASE=BC-H04120A 4 port H.264 video and audio encoder / decoder + +pci:v00001BB3d00005308* + ID_MODEL_FROM_DATABASE=BC-H08240A 8 port H.264 video and audio encoder / decoder + +pci:v00001BB3d00005310* + ID_MODEL_FROM_DATABASE=BC-H16480A 16 port H.264 video and audio encoder / decoder + +pci:v00001BB5* + ID_VENDOR_FROM_DATABASE=Quantenna Communications, Inc. + +pci:v00001BBF* + ID_VENDOR_FROM_DATABASE=Maxeler Technologies Ltd. + +pci:v00001BBFd00000003* + ID_MODEL_FROM_DATABASE=MAX3 + +pci:v00001BBFd00000004* + ID_MODEL_FROM_DATABASE=MAX4 + +pci:v00001BCF* + ID_VENDOR_FROM_DATABASE=NEC Corporation + +pci:v00001BCFd0000001C* + ID_MODEL_FROM_DATABASE=Vector Engine 1.0 + +pci:v00001BD0* + ID_VENDOR_FROM_DATABASE=Astronics Corporation + +pci:v00001BD0d00001001* + ID_MODEL_FROM_DATABASE=Mx5 PMC/XMC Databus Interface Card + +pci:v00001BD0d00001002* + ID_MODEL_FROM_DATABASE=PM1553-5 (PC/104+ MIL-STD-1553 Interface Card) + +pci:v00001BD0d00001004* + ID_MODEL_FROM_DATABASE=AB3000 Series Rugged Computer + +pci:v00001BD0d00001005* + ID_MODEL_FROM_DATABASE=PE1000 (Multi-Protocol PCIe/104 Interface Card) + +pci:v00001BD0d00001101* + ID_MODEL_FROM_DATABASE=OmniBus II PCIe Multi-Protocol Interface Card + +pci:v00001BD0d00001102* + ID_MODEL_FROM_DATABASE=OmniBusBox II Multi-Protocol Interface Core + +pci:v00001BD0d00001103* + ID_MODEL_FROM_DATABASE=OmniBus II cPCIe/PXIe Multi-Protocol Interface Card + +pci:v00001BD4* + ID_VENDOR_FROM_DATABASE=Inspur Electronic Information Industry Co., Ltd. + +pci:v00001BEE* + ID_VENDOR_FROM_DATABASE=IXXAT Automation GmbH + +pci:v00001BEEd00000003* + ID_MODEL_FROM_DATABASE=CAN-IB200/PCIe + +pci:v00001BEF* + ID_VENDOR_FROM_DATABASE=Lantiq + +pci:v00001BEFd00000011* + ID_MODEL_FROM_DATABASE=MIPS SoC PCI Express Port + +pci:v00001BF4* + ID_VENDOR_FROM_DATABASE=VTI Instruments Corporation + +pci:v00001BF4d00000001* + ID_MODEL_FROM_DATABASE=SentinelEX + +pci:v00001BF4d00007011* + ID_MODEL_FROM_DATABASE=RX0xxx + +pci:v00001BFD* + ID_VENDOR_FROM_DATABASE=EeeTOP + +pci:v00001C09* + ID_VENDOR_FROM_DATABASE=CSP, Inc. + +pci:v00001C09d00004254* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8D-2S + +pci:v00001C09d00004255* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8D-Q + +pci:v00001C09d00004256* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8D-2S + +pci:v00001C09d00004258* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-2S Network Adapter + +pci:v00001C09d00004260* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-4S Network Adapter + +pci:v00001C09d00004261* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-4S Network Adapter + +pci:v00001C09d00004262* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-4S Network Adapter + +pci:v00001C09d00004263* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-4S Network Adapter + +pci:v00001C09d00004264* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-2S Network Adapter + +pci:v00001C09d00004265* + ID_MODEL_FROM_DATABASE=10G-PCIE3-8E-2S Network Adapter + +pci:v00001C09d00005000* + ID_MODEL_FROM_DATABASE=25G-PCIE3-8A-2S Security Intelligent Adapter + +pci:v00001C09d00005001* + ID_MODEL_FROM_DATABASE=25G-PCIE3-8B-2S Security Intelligent Adapter + +pci:v00001C1C* + ID_VENDOR_FROM_DATABASE=Symphony + +pci:v00001C1Cd00000001* + ID_MODEL_FROM_DATABASE=82C101 + +pci:v00001C1F* + ID_VENDOR_FROM_DATABASE=SoftLab-NSK + +pci:v00001C28* + ID_VENDOR_FROM_DATABASE=Lite-On IT Corp. / Plextor + +pci:v00001C28d00000122* + ID_MODEL_FROM_DATABASE=M6e PCI Express SSD [Marvell 88SS9183] + +pci:v00001C2C* + ID_VENDOR_FROM_DATABASE=Silicom Denmark + +pci:v00001C2Cd0000000A* + ID_MODEL_FROM_DATABASE=Capture + +pci:v00001C2Cd0000000F* + ID_MODEL_FROM_DATABASE=SmartNIC + +pci:v00001C2Cd000000A0* + ID_MODEL_FROM_DATABASE=FBC4G Capture 4x1Gb [Herculaneum] + +pci:v00001C2Cd000000A1* + ID_MODEL_FROM_DATABASE=FBC4XG Capture 4x10Gb [Ancona] + +pci:v00001C2Cd000000A2* + ID_MODEL_FROM_DATABASE=FBC8XG Capture 8x10Gb [Livorno] + +pci:v00001C2Cd000000A3* + ID_MODEL_FROM_DATABASE=FBC2XG Capture 2x10Gb [Genoa] + +pci:v00001C2Cd000000A4* + ID_MODEL_FROM_DATABASE=FBC4XGG3 Capture 4x10Gb [Livigno] + +pci:v00001C2Cd000000A5* + ID_MODEL_FROM_DATABASE=FBC2XLG Capture 2x40Gb [Livorno] + +pci:v00001C2Cd000000A6* + ID_MODEL_FROM_DATABASE=FBC1CG Capture 1x100Gb + +pci:v00001C2Cd000000A9* + ID_MODEL_FROM_DATABASE=FBC2XGHH Capture 2x10Gb [Latina] + +pci:v00001C2Cd000000AD* + ID_MODEL_FROM_DATABASE=FBC2CGG3HL Capture 2x100Gb [Padua] + +pci:v00001C2Cd000000AF* + ID_MODEL_FROM_DATABASE=Capture slave device + +pci:v00001C2Cd000000E0* + ID_MODEL_FROM_DATABASE=PacketMover 2x100Gb [Savona] + +pci:v00001C2Cd000000E1* + ID_MODEL_FROM_DATABASE=PacketMover 2x100Gb [Tivoli] + +pci:v00001C2Cd000000E3* + ID_MODEL_FROM_DATABASE=PacketMover 2x10Gb [Tivoli] + +pci:v00001C2Cd000000E5* + ID_MODEL_FROM_DATABASE=PacketMover 2x10Gb [Corfu] + +pci:v00001C2Cd0000A000* + ID_MODEL_FROM_DATABASE=FBC2CGG3 Capture 2x40Gb [Mango_02] + +pci:v00001C2Cd0000A001* + ID_MODEL_FROM_DATABASE=FBC2CGG3 Capture 2x100Gb [Mango_02] + +pci:v00001C2Cd0000A003* + ID_MODEL_FROM_DATABASE=FBC2CGG3 Capture 16x10Gb [Mango] + +pci:v00001C2Cd0000A007* + ID_MODEL_FROM_DATABASE=FBC2CGG3 Capture 2x40Gb [Mango] + +pci:v00001C2Cd0000A008* + ID_MODEL_FROM_DATABASE=FBC2CGG3 Capture 2x25Gb [Mango] + +pci:v00001C2Cd0000A009* + ID_MODEL_FROM_DATABASE=FBC2CGG3 Capture 16x10Gb [Mango] + +pci:v00001C2Cd0000A00A* + ID_MODEL_FROM_DATABASE=FBC2CGG3 Capture 8x10Gb [Mango] + +pci:v00001C2Cd0000A00E* + ID_MODEL_FROM_DATABASE=FB2CG Capture 2x100Gb [Savona] + +pci:v00001C2Cd0000A00F* + ID_MODEL_FROM_DATABASE=FB2CG Capture 2x40Gb [Savona] + +pci:v00001C2Cd0000A011* + ID_MODEL_FROM_DATABASE=FB2CG Capture 2x25Gb [Savona] + +pci:v00001C2Cd0000A012* + ID_MODEL_FROM_DATABASE=FB2CG Capture 8x10Gb [Savona] + +pci:v00001C32* + ID_VENDOR_FROM_DATABASE=Highland Technology, Inc. + +pci:v00001C33* + ID_VENDOR_FROM_DATABASE=Daktronics, Inc + +pci:v00001C36* + ID_VENDOR_FROM_DATABASE=Annapurna Labs Ltd. + +pci:v00001C36d00000001* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter + +pci:v00001C36d00000002* + ID_MODEL_FROM_DATABASE=SFP+ 10G Ethernet Adapter + +pci:v00001C3B* + ID_VENDOR_FROM_DATABASE=Accensus, LLC + +pci:v00001C3Bd00000200* + ID_MODEL_FROM_DATABASE=Telas2 + +pci:v00001C3Bd00000300* + ID_MODEL_FROM_DATABASE=Telas 2.V + +pci:v00001C44* + ID_VENDOR_FROM_DATABASE=Enmotus Inc + +pci:v00001C44d00008000* + ID_MODEL_FROM_DATABASE=8000 Storage IO Controller + +pci:v00001C58* + ID_VENDOR_FROM_DATABASE=HGST, Inc. + +pci:v00001C58d00000003* + ID_MODEL_FROM_DATABASE=Ultrastar SN100 Series NVMe SSD + +pci:v00001C58d00000003sv00001014sd000004F5* + ID_MODEL_FROM_DATABASE=Ultrastar SN100 Series NVMe SSD (PCIe3 1.6TB NVMe Flash Adapter) + +pci:v00001C58d00000003sv00001014sd000004F6* + ID_MODEL_FROM_DATABASE=Ultrastar SN100 Series NVMe SSD (PCIe3 3.2TB NVMe Flash Adapter) + +pci:v00001C58d00000003sv00001C58sd00000003* + ID_MODEL_FROM_DATABASE=Ultrastar SN100 Series NVMe SSD (Ultrastar SN100/SN150 NVMe SSD) + +pci:v00001C58d00000023* + ID_MODEL_FROM_DATABASE=Ultrastar SN200 Series NVMe SSD + +pci:v00001C58d00000023sv00001C58sd00008823* + ID_MODEL_FROM_DATABASE=Ultrastar SN200 Series NVMe SSD (Ultrastar Memory (ME200)) + +pci:v00001C5C* + ID_VENDOR_FROM_DATABASE=SK hynix + +pci:v00001C5Cd00001283* + ID_MODEL_FROM_DATABASE=PC300 NVMe Solid State Drive 256GB + +pci:v00001C5Cd00001284* + ID_MODEL_FROM_DATABASE=PC300 NVMe Solid State Drive 512GB + +pci:v00001C5Cd00001285* + ID_MODEL_FROM_DATABASE=PC300 NVMe Solid State Drive 1TB + +pci:v00001C5Cd00001504* + ID_MODEL_FROM_DATABASE=SC300 512GB M.2 2280 SATA Solid State Drive + +pci:v00001C5F* + ID_VENDOR_FROM_DATABASE=Beijing Memblaze Technology Co. Ltd. + +pci:v00001C5Fd0000000D* + ID_MODEL_FROM_DATABASE=PBlaze5 520/526 AIC + +pci:v00001C5Fd0000003D* + ID_MODEL_FROM_DATABASE=PBlaze5 920/926 AIC + +pci:v00001C5Fd0000010D* + ID_MODEL_FROM_DATABASE=PBlaze5 520/526 U.2 + +pci:v00001C5Fd0000013D* + ID_MODEL_FROM_DATABASE=PBlaze5 920/926 U.2 + +pci:v00001C5Fd00000540* + ID_MODEL_FROM_DATABASE=PBlaze4 NVMe SSD + +pci:v00001C5Fd00000550* + ID_MODEL_FROM_DATABASE=PBlaze5 700/900 + +pci:v00001C5Fd00000555* + ID_MODEL_FROM_DATABASE=PBlaze5 510/516 + +pci:v00001C5Fd00000557* + ID_MODEL_FROM_DATABASE=PBlaze5 910/916 + +pci:v00001C63* + ID_VENDOR_FROM_DATABASE=Science and Research Centre of Computer Technology (JSC "NICEVT") + +pci:v00001C63d00000008* + ID_MODEL_FROM_DATABASE=K1927BB1Ya [EC8430] Angara Interconnection Network Adapter + +pci:v00001C7E* + ID_VENDOR_FROM_DATABASE=TTTech Computertechnik AG + +pci:v00001C7Ed00000200* + ID_MODEL_FROM_DATABASE=zFAS Debug Port + +pci:v00001C7F* + ID_VENDOR_FROM_DATABASE=Elektrobit Austria GmbH + +pci:v00001C7Fd00005100* + ID_MODEL_FROM_DATABASE=EB5100 + +pci:v00001C8A* + ID_VENDOR_FROM_DATABASE=TSF5 Corporation + +pci:v00001C8Ad00000001* + ID_MODEL_FROM_DATABASE=Hunter PCI Express + +pci:v00001C8C* + ID_VENDOR_FROM_DATABASE=Mobiveil, Inc. + +pci:v00001CB0* + ID_VENDOR_FROM_DATABASE=Shannon Systems + +pci:v00001CB0d0000D000* + ID_MODEL_FROM_DATABASE=Venice NVMe SSD + +pci:v00001CB0d0000D000sv00001CB0sd00002F10* + ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-E Series U.2 SSD) + +pci:v00001CB0d0000D000sv00001CB0sd00002F11* + ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice Series U.2 SSD) + +pci:v00001CB0d0000D000sv00001CB0sd00002F12* + ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-X Series U.2 SSD) + +pci:v00001CB0d0000D000sv00001CB0sd0000AF10* + ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-E Series AIC SSD) + +pci:v00001CB0d0000D000sv00001CB0sd0000AF11* + ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice Series AIC SSD) + +pci:v00001CB0d0000D000sv00001CB0sd0000AF12* + ID_MODEL_FROM_DATABASE=Venice NVMe SSD (Venice-X Series AIC SSD) + +pci:v00001CB1* + ID_VENDOR_FROM_DATABASE=Collion UG & Co.KG + +pci:v00001CB5* + ID_VENDOR_FROM_DATABASE=Focusrite Audio Engineering Ltd + +pci:v00001CB5d00000002* + ID_MODEL_FROM_DATABASE=Clarett + +pci:v00001CB8* + ID_VENDOR_FROM_DATABASE=Dawning Information Industry Co., Ltd. + +pci:v00001CC1* + ID_VENDOR_FROM_DATABASE=ADATA Technology Co., Ltd. + +pci:v00001CC1d00008201* + ID_MODEL_FROM_DATABASE=XPG SX8200 Pro PCIe Gen3x4 M.2 2280 Solid State Drive + +pci:v00001CC4* + ID_VENDOR_FROM_DATABASE=Union Memory (Shenzhen) + +pci:v00001CC4d000017AB* + ID_MODEL_FROM_DATABASE=NVMe 256G SSD device + +pci:v00001CC5* + ID_VENDOR_FROM_DATABASE=Embedded Intelligence, Inc. + +pci:v00001CC5d00000100* + ID_MODEL_FROM_DATABASE=CAN-PCIe-02 + +pci:v00001CC7* + ID_VENDOR_FROM_DATABASE=Radian Memory Systems Inc. + +pci:v00001CC7d00000200* + ID_MODEL_FROM_DATABASE=RMS-200 + +pci:v00001CC7d00000250* + ID_MODEL_FROM_DATABASE=RMS-250 + +pci:v00001CCF* + ID_VENDOR_FROM_DATABASE=Zoom Corporation + +pci:v00001CCFd00000001* + ID_MODEL_FROM_DATABASE=TAC-2 Thunderbolt Audio Converter + +pci:v00001CD2* + ID_VENDOR_FROM_DATABASE=SesKion GmbH + +pci:v00001CD2d00000301* + ID_MODEL_FROM_DATABASE=Simulyzer-RT CompactPCI Serial DIO-1 card + +pci:v00001CD2d00000302* + ID_MODEL_FROM_DATABASE=Simulyzer-RT CompactPCI Serial PSI5-ECU-1 card + +pci:v00001CD2d00000303* + ID_MODEL_FROM_DATABASE=Simulyzer-RT CompactPCI Serial PSI5-SIM-1 card + +pci:v00001CD2d00000304* + ID_MODEL_FROM_DATABASE=Simulyzer-RT CompactPCI Serial PWR-ANA-1 card + +pci:v00001CD2d00000305* + ID_MODEL_FROM_DATABASE=Simulyzer-RT CompactPCI Serial CAN-1 card + +pci:v00001CD2d00000306* + ID_MODEL_FROM_DATABASE=Simulyzer-RT CompactPCI Serial CAN-2 card (CAN-FD) + +pci:v00001CD7* + ID_VENDOR_FROM_DATABASE=Nanjing Magewell Electronics Co., Ltd. + +pci:v00001CD7d00000010* + ID_MODEL_FROM_DATABASE=Pro Capture Endpoint + +pci:v00001CD7d00000014* + ID_MODEL_FROM_DATABASE=PRO CAPTURE AIO 4K PLUS + +pci:v00001CD7d00000017* + ID_MODEL_FROM_DATABASE=PRO CAPTURE AIO 4K + +pci:v00001CDD* + ID_VENDOR_FROM_DATABASE=secunet Security Networks AG + +pci:v00001CE4* + ID_VENDOR_FROM_DATABASE=Exablaze + +pci:v00001CE4d00000001* + ID_MODEL_FROM_DATABASE=ExaNIC X4 + +pci:v00001CE4d00000002* + ID_MODEL_FROM_DATABASE=ExaNIC X2 + +pci:v00001CE4d00000003* + ID_MODEL_FROM_DATABASE=ExaNIC X10 + +pci:v00001CE4d00000004* + ID_MODEL_FROM_DATABASE=ExaNIC X10-GM + +pci:v00001CE4d00000005* + ID_MODEL_FROM_DATABASE=ExaNIC X40 + +pci:v00001CE4d00000006* + ID_MODEL_FROM_DATABASE=ExaNIC X10-HPT + +pci:v00001CE4d00000007* + ID_MODEL_FROM_DATABASE=ExaNIC X40 + +pci:v00001CE4d00000008* + ID_MODEL_FROM_DATABASE=ExaNIC V5P + +pci:v00001CE4d00000009* + ID_MODEL_FROM_DATABASE=ExaNIC X25 + +pci:v00001CE4d0000000A* + ID_MODEL_FROM_DATABASE=ExaNIC X100 + +pci:v00001CE4d0000000B* + ID_MODEL_FROM_DATABASE=ExaNIC V9P + +pci:v00001CE4d00000100* + ID_MODEL_FROM_DATABASE=ExaDISK FX1 + +pci:v00001CF0* + ID_VENDOR_FROM_DATABASE=Akitio + +pci:v00001CF7* + ID_VENDOR_FROM_DATABASE=Subspace Dynamics + +pci:v00001D00* + ID_VENDOR_FROM_DATABASE=Pure Storage + +pci:v00001D05* + ID_VENDOR_FROM_DATABASE=Tongfang Hongkong Limited + +pci:v00001D0F* + ID_VENDOR_FROM_DATABASE=Amazon.com, Inc. + +pci:v00001D0Fd0000CD01* + ID_MODEL_FROM_DATABASE=NVMe SSD Controller + +pci:v00001D0Fd0000EC20* + ID_MODEL_FROM_DATABASE=Elastic Network Adapter (ENA) + +pci:v00001D0Fd0000EFA0* + ID_MODEL_FROM_DATABASE=Elastic Fabric Adapter (EFA) + +pci:v00001D17* + ID_VENDOR_FROM_DATABASE=Zhaoxin + +pci:v00001D17d0000070F* + ID_MODEL_FROM_DATABASE=ZX-100 PCI Express Root Port + +pci:v00001D17d00000710* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-200 PCI Express Root Port + +pci:v00001D17d00000711* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-200 PCI Express Root Port + +pci:v00001D17d00000712* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-200 PCI Express Root Port + +pci:v00001D17d00000713* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-200 PCI Express Root Port + +pci:v00001D17d00000714* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-200 PCI Express Root Port + +pci:v00001D17d00000715* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-200 PCI Express Root Port + +pci:v00001D17d00000716* + ID_MODEL_FROM_DATABASE=ZX-D PCI Express Root Port + +pci:v00001D17d00000717* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E PCI Express Root Port + +pci:v00001D17d00000718* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E PCI Express Root Port + +pci:v00001D17d00000719* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E PCI Express Root Port + +pci:v00001D17d0000071A* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E PCI Express Root Port + +pci:v00001D17d0000071B* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E PCI Express Root Port + +pci:v00001D17d0000071C* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E PCI Express Root Port + +pci:v00001D17d0000071D* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E PCI Express Root Port + +pci:v00001D17d0000071E* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E PCI Express Root Port + +pci:v00001D17d0000071F* + ID_MODEL_FROM_DATABASE=ZX-200 Upstream Port of PCI Express Switch + +pci:v00001D17d00000720* + ID_MODEL_FROM_DATABASE=ZX-200 PCIE RC6 controller + +pci:v00001D17d00000721* + ID_MODEL_FROM_DATABASE=ZX-200 Downstream Port of PCI Express Switch + +pci:v00001D17d00000722* + ID_MODEL_FROM_DATABASE=ZX-200 PCIE P2C bridge + +pci:v00001D17d00001000* + ID_MODEL_FROM_DATABASE=ZX-D Standard Host Bridge + +pci:v00001D17d00001001* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E Miscellaneous Bus + +pci:v00001D17d00001003* + ID_MODEL_FROM_DATABASE=ZX-E Standard Host Bridge + +pci:v00001D17d00003001* + ID_MODEL_FROM_DATABASE=ZX-100 Standard Host Bridge + +pci:v00001D17d0000300A* + ID_MODEL_FROM_DATABASE=ZX-100 Miscellaneous Bus + +pci:v00001D17d00003038* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-200/ZX-E Standard Universal PCI to USB Host Controller + +pci:v00001D17d00003104* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-200/ZX-E Standard Enhanced PCI to USB Host Controller + +pci:v00001D17d000031B0* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D Standard Host Bridge + +pci:v00001D17d000031B1* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D Standard Host Bridge + +pci:v00001D17d000031B2* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D DRAM Controller + +pci:v00001D17d000031B3* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D Power Management Controller + +pci:v00001D17d000031B4* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D I/O APIC + +pci:v00001D17d000031B5* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D Scratch Device + +pci:v00001D17d000031B7* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D/ZX-E Standard Host Bridge + +pci:v00001D17d000031B8* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D PCI to PCI Bridge + +pci:v00001D17d00003288* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D/ZX-E High Definition Audio Controller + +pci:v00001D17d0000345B* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D/ZX-E Miscellaneous Bus + +pci:v00001D17d00003A02* + ID_MODEL_FROM_DATABASE=ZX-100 C-320 GPU + +pci:v00001D17d00003A03* + ID_MODEL_FROM_DATABASE=ZX-D C-860 GPU + +pci:v00001D17d00003A04* + ID_MODEL_FROM_DATABASE=ZX-E C-960 GPU + +pci:v00001D17d00009002* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-200 EIDE Controller + +pci:v00001D17d00009003* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-E EIDE Controller + +pci:v00001D17d00009045* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D/ZX-E RAID Accelerator 0 + +pci:v00001D17d00009046* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E RAID Accelerator 1 + +pci:v00001D17d00009083* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-200/ZX-E StorX AHCI Controller + +pci:v00001D17d00009084* + ID_MODEL_FROM_DATABASE=ZX-100 StorX AHCI Controller + +pci:v00001D17d00009100* + ID_MODEL_FROM_DATABASE=ZX-200 Cross bus + +pci:v00001D17d00009101* + ID_MODEL_FROM_DATABASE=ZX-200 Traffic Controller + +pci:v00001D17d00009141* + ID_MODEL_FROM_DATABASE=ZX-100 High Definition Audio Controller + +pci:v00001D17d00009142* + ID_MODEL_FROM_DATABASE=ZX-D High Definition Audio Controller + +pci:v00001D17d00009144* + ID_MODEL_FROM_DATABASE=ZX-E High Definition Audio Controller + +pci:v00001D17d00009180* + ID_MODEL_FROM_DATABASE=ZX-200 Networking Gigabit Ethernet Adapter + +pci:v00001D17d00009202* + ID_MODEL_FROM_DATABASE=ZX-100 USB eXtensible Host Controller + +pci:v00001D17d00009203* + ID_MODEL_FROM_DATABASE=ZX-200 USB eXtensible Host Controller + +pci:v00001D17d00009204* + ID_MODEL_FROM_DATABASE=ZX-E USB eXtensible Host Controller + +pci:v00001D17d00009286* + ID_MODEL_FROM_DATABASE=ZX-D eMMC Host Controller + +pci:v00001D17d00009300* + ID_MODEL_FROM_DATABASE=ZX-D/ZX-E eSPI Host Controller + +pci:v00001D17d000095D0* + ID_MODEL_FROM_DATABASE=ZX-100 Universal SD Host Controller + +pci:v00001D17d0000F410* + ID_MODEL_FROM_DATABASE=ZX-100/ZX-D/ZX-E PCI Com Port + +pci:v00001D18* + ID_VENDOR_FROM_DATABASE=RME + +pci:v00001D18d00000001* + ID_MODEL_FROM_DATABASE=Fireface UFX+ + +pci:v00001D1D* + ID_VENDOR_FROM_DATABASE=CNEX Labs + +pci:v00001D1Dd00001F1F* + ID_MODEL_FROM_DATABASE=QEMU NVM Express LightNVM Controller + +pci:v00001D1Dd00002807* + ID_MODEL_FROM_DATABASE=8800 series NVMe SSD + +pci:v00001D21* + ID_VENDOR_FROM_DATABASE=Allo + +pci:v00001D22* + ID_VENDOR_FROM_DATABASE=Baidu Technology + +pci:v00001D22d00001380* + ID_MODEL_FROM_DATABASE=Cloud Storage Device + +pci:v00001D26* + ID_VENDOR_FROM_DATABASE=Kalray Inc. + +pci:v00001D26d00000040* + ID_MODEL_FROM_DATABASE=Turbocard2 Accelerator + +pci:v00001D26d00000080* + ID_MODEL_FROM_DATABASE=Open Network Interface Card 80G + +pci:v00001D26d000000C0* + ID_MODEL_FROM_DATABASE=Turbocard3 Accelerator + +pci:v00001D26d00000140* + ID_MODEL_FROM_DATABASE=Open Network Interface Card 40G + +pci:v00001D26d0000E004* + ID_MODEL_FROM_DATABASE=AB01/EMB01 Development Board + +pci:v00001D37* + ID_VENDOR_FROM_DATABASE=NovaSparks + +pci:v00001D37d00000013* + ID_MODEL_FROM_DATABASE=PM3 + +pci:v00001D37d00000014* + ID_MODEL_FROM_DATABASE=PM4 + +pci:v00001D37d00000015* + ID_MODEL_FROM_DATABASE=PM4edge + +pci:v00001D37d00000016* + ID_MODEL_FROM_DATABASE=PM4edge User Device + +pci:v00001D40* + ID_VENDOR_FROM_DATABASE=Techman Electronics (Changshu) Co., Ltd. + +pci:v00001D44* + ID_VENDOR_FROM_DATABASE=DPT + +pci:v00001D44d0000A400* + ID_MODEL_FROM_DATABASE=PM2x24/PM3224 + +pci:v00001D49* + ID_VENDOR_FROM_DATABASE=Lenovo + +pci:v00001D4C* + ID_VENDOR_FROM_DATABASE=Diamanti, Inc. + +pci:v00001D5C* + ID_VENDOR_FROM_DATABASE=Fantasia Trading LLC + +pci:v00001D61* + ID_VENDOR_FROM_DATABASE=Technobox, Inc. + +pci:v00001D62* + ID_VENDOR_FROM_DATABASE=Nebbiolo Technologies + +pci:v00001D65* + ID_VENDOR_FROM_DATABASE=Imagine Communications Corp. + +pci:v00001D65d000004DE* + ID_MODEL_FROM_DATABASE=Taurus/McKinley + +pci:v00001D6A* + ID_VENDOR_FROM_DATABASE=Aquantia Corp. + +pci:v00001D6Ad00000001* + ID_MODEL_FROM_DATABASE=AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + +pci:v00001D6Ad000007B1* + ID_MODEL_FROM_DATABASE=AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + +pci:v00001D6Ad000008B1* + ID_MODEL_FROM_DATABASE=AQC108 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + +pci:v00001D6Ad000011B1* + ID_MODEL_FROM_DATABASE=AQC111 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + +pci:v00001D6Ad000012B1* + ID_MODEL_FROM_DATABASE=AQC112 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + +pci:v00001D6Ad000087B1* + ID_MODEL_FROM_DATABASE=AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + +pci:v00001D6Ad0000D107* + ID_MODEL_FROM_DATABASE=AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + +pci:v00001D6Ad0000D107sv00001043sd00008741* + ID_MODEL_FROM_DATABASE=AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] (XG-C100C) + +pci:v00001D6Ad0000D108* + ID_MODEL_FROM_DATABASE=AQC108 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + +pci:v00001D6C* + ID_VENDOR_FROM_DATABASE=Atomic Rules LLC + +pci:v00001D6Cd00001001* + ID_MODEL_FROM_DATABASE=A5PL-E1 + +pci:v00001D6Cd00001002* + ID_MODEL_FROM_DATABASE=A5PL-E7 + +pci:v00001D6Cd00001003* + ID_MODEL_FROM_DATABASE=S5PEDS-AB + +pci:v00001D6Cd00001004* + ID_MODEL_FROM_DATABASE=KC705-K325 + +pci:v00001D6Cd00001005* + ID_MODEL_FROM_DATABASE=ZC706-Z045 + +pci:v00001D6Cd00001006* + ID_MODEL_FROM_DATABASE=KCU105-KU040 + +pci:v00001D6Cd00001007* + ID_MODEL_FROM_DATABASE=XUSP3S-VU095 [Jasper] + +pci:v00001D6Cd00001008* + ID_MODEL_FROM_DATABASE=XUSPL4-VU065 [Mustang UltraScale] + +pci:v00001D6Cd00001009* + ID_MODEL_FROM_DATABASE=XUSPL4-VU3P [Mustang UltraScale+] + +pci:v00001D6Cd0000100A* + ID_MODEL_FROM_DATABASE=A10PL4-A10GX115 + +pci:v00001D6Cd0000100B* + ID_MODEL_FROM_DATABASE=K35-2SFP + +pci:v00001D6Cd0000100C* + ID_MODEL_FROM_DATABASE=K35-4SFP + +pci:v00001D6Cd0000100D* + ID_MODEL_FROM_DATABASE=AR-ARKA-FX0 [Arkville 32B DPDK Data Mover] + +pci:v00001D6Cd0000100Dsv00001D6Csd00002001* + ID_MODEL_FROM_DATABASE=AR-ARKA-FX0 [Arkville 32B DPDK Data Mover] (DPDK-Aware Virtual Function [Arkville VF]) + +pci:v00001D6Cd0000100E* + ID_MODEL_FROM_DATABASE=AR-ARKA-FX1 [Arkville 64B DPDK Data Mover] + +pci:v00001D6Cd0000100Esv00001D6Csd00002001* + ID_MODEL_FROM_DATABASE=AR-ARKA-FX1 [Arkville 64B DPDK Data Mover] (DPDK-Aware Virtual Function [Arkville VF]) + +pci:v00001D6Cd0000100F* + ID_MODEL_FROM_DATABASE=AR-ARKA-FX1 [Arkville 64B DPDK Data Mover for Versal] + +pci:v00001D6Cd00001010* + ID_MODEL_FROM_DATABASE=AR-ARKA-FX1 [Arkville 64B DPDK Data Mover for Agilex] + +pci:v00001D6Cd00001011* + ID_MODEL_FROM_DATABASE=AR-MAN-U50 [Manitou Class Accelerator for U50] + +pci:v00001D6Cd00001012* + ID_MODEL_FROM_DATABASE=AR-MAN-U200 [Manitou Class Accelerator for U200] + +pci:v00001D6Cd00001013* + ID_MODEL_FROM_DATABASE=AR-MAN-U250 [Manitou Class Accelerator for U250] + +pci:v00001D6Cd00001014* + ID_MODEL_FROM_DATABASE=AR-MAN-U280 [Manitou Class Accelerator for U280] + +pci:v00001D6Cd00004200* + ID_MODEL_FROM_DATABASE=A5PL-E1-10GETI [10 GbE Ethernet Traffic Instrument] + +pci:v00001D72* + ID_VENDOR_FROM_DATABASE=Xiaomi + +pci:v00001D78* + ID_VENDOR_FROM_DATABASE=DERA + +pci:v00001D7C* + ID_VENDOR_FROM_DATABASE=Aerotech, Inc. + +pci:v00001D82* + ID_VENDOR_FROM_DATABASE=NETINT Technologies Inc. + +pci:v00001D82d00000101* + ID_MODEL_FROM_DATABASE=Codensity D400 SSD + +pci:v00001D82d00000102* + ID_MODEL_FROM_DATABASE=Codensity D408 PCIe Gen4 NVMe SSD + +pci:v00001D82d00000202* + ID_MODEL_FROM_DATABASE=Codensity T408 Video Encoding-Decoding Accelerator + +pci:v00001D87* + ID_VENDOR_FROM_DATABASE=Fuzhou Rockchip Electronics Co., Ltd + +pci:v00001D87d00000100* + ID_MODEL_FROM_DATABASE=RK3399 PCI Express Root Port + +pci:v00001D87d00001808* + ID_MODEL_FROM_DATABASE=RK1808 Neural Network Processor Card + +pci:v00001D8F* + ID_VENDOR_FROM_DATABASE=Enyx + +pci:v00001D93* + ID_VENDOR_FROM_DATABASE=YADRO (KNS Group) + +pci:v00001D94* + ID_VENDOR_FROM_DATABASE=Chengdu Haiguang IC Design Co., Ltd. + +pci:v00001D94d00001450* + ID_MODEL_FROM_DATABASE=Root Complex + +pci:v00001D94d00001451* + ID_MODEL_FROM_DATABASE=I/O Memory Management Unit + +pci:v00001D94d00001452* + ID_MODEL_FROM_DATABASE=PCIe Dummy Host Bridge + +pci:v00001D94d00001453* + ID_MODEL_FROM_DATABASE=PCIE GPP Bridge + +pci:v00001D94d00001454* + ID_MODEL_FROM_DATABASE=Internal PCIe GPP Bridge 0 to Bus B + +pci:v00001D94d00001455* + ID_MODEL_FROM_DATABASE=PCIe Dummy Function + +pci:v00001D94d00001456* + ID_MODEL_FROM_DATABASE=PSPCCP Command DMA Processor + +pci:v00001D94d00001458* + ID_MODEL_FROM_DATABASE=10 Gb Ethernet Controller Port 0/Port1 + +pci:v00001D94d00001459* + ID_MODEL_FROM_DATABASE=10 Gb Ethernet Controller Port 2/Port3 + +pci:v00001D94d0000145A* + ID_MODEL_FROM_DATABASE=PCIe Dummy Function + +pci:v00001D94d0000145B* + ID_MODEL_FROM_DATABASE=PCIE Non-Transparent Bridge + +pci:v00001D94d0000145C* + ID_MODEL_FROM_DATABASE=USB3 XHCI + +pci:v00001D94d0000145D* + ID_MODEL_FROM_DATABASE=Switch upstream in PCIe + +pci:v00001D94d0000145E* + ID_MODEL_FROM_DATABASE=Switch downstream in PCIe + +pci:v00001D94d0000145F* + ID_MODEL_FROM_DATABASE=USB 3.0 Host controller + +pci:v00001D94d00001460* + ID_MODEL_FROM_DATABASE=Data Fabric: Device 18h; Function 0 + +pci:v00001D94d00001461* + ID_MODEL_FROM_DATABASE=Data Fabric: Device 18h; Function 1 + +pci:v00001D94d00001462* + ID_MODEL_FROM_DATABASE=Data Fabric: Device 18h; Function 2 + +pci:v00001D94d00001463* + ID_MODEL_FROM_DATABASE=Data Fabric: Device 18h; Function 3 + +pci:v00001D94d00001464* + ID_MODEL_FROM_DATABASE=Data Fabric: Device 18h; Function 4 + +pci:v00001D94d00001465* + ID_MODEL_FROM_DATABASE=Data Fabric: Device 18h; Function 5 + +pci:v00001D94d00001466* + ID_MODEL_FROM_DATABASE=Data Fabric: Device 18h; Function 6 + +pci:v00001D94d00001467* + ID_MODEL_FROM_DATABASE=Data Fabric: Device 18h; Function 7 + +pci:v00001D94d00001468* + ID_MODEL_FROM_DATABASE=NTBCCP + +pci:v00001D94d00007901* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] + +pci:v00001D94d00007904* + ID_MODEL_FROM_DATABASE=FCH SATA Controller [AHCI mode] + +pci:v00001D94d00007906* + ID_MODEL_FROM_DATABASE=FCH SD Flash Controller + +pci:v00001D94d0000790B* + ID_MODEL_FROM_DATABASE=FCH SMBus Controller + +pci:v00001D94d0000790E* + ID_MODEL_FROM_DATABASE=FCH LPC Bridge + +pci:v00001D95* + ID_VENDOR_FROM_DATABASE=Graphcore Ltd + +pci:v00001D95d00000001* + ID_MODEL_FROM_DATABASE=Colossus GC2 [C2] + +pci:v00001D95d00000002* + ID_MODEL_FROM_DATABASE=Colossus GC1 [S1] + +pci:v00001D9B* + ID_VENDOR_FROM_DATABASE=Facebook, Inc. + +pci:v00001D9Bd00000010* + ID_MODEL_FROM_DATABASE=Networking DOM Engine + +pci:v00001D9Bd00000011* + ID_MODEL_FROM_DATABASE=IO Bridge + +pci:v00001DA1* + ID_VENDOR_FROM_DATABASE=Teko Telecom S.r.l. + +pci:v00001DA2* + ID_VENDOR_FROM_DATABASE=Sapphire Technology Limited + +pci:v00001DA3* + ID_VENDOR_FROM_DATABASE=Habana Labs Ltd. + +pci:v00001DA3d00000001* + ID_MODEL_FROM_DATABASE=HL-1000 AI Inference Accelerator [Goya] + +pci:v00001DA3d00001000* + ID_MODEL_FROM_DATABASE=HL-2000 AI Training Accelerator [Gaudi] + +pci:v00001DBB* + ID_VENDOR_FROM_DATABASE=NGD Systems, Inc. + +pci:v00001DBF* + ID_VENDOR_FROM_DATABASE=Guizhou Huaxintong Semiconductor Technology Co., Ltd + +pci:v00001DBFd00000401* + ID_MODEL_FROM_DATABASE=StarDragon4800 PCI Express Root Port + +pci:v00001DC5* + ID_VENDOR_FROM_DATABASE=FADU Inc. + +pci:v00001DD8* + ID_VENDOR_FROM_DATABASE=Pensando Systems Inc + +pci:v00001DD8d00001000* + ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port + +pci:v00001DD8d00001000sv00001DD8sd00004000* + ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (Naples 100Gb 2-port QSFP28 x16 8GB) + +pci:v00001DD8d00001000sv00001DD8sd00004001* + ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (Naples 100Gb 2-port QSFP28 x16 4GB) + +pci:v00001DD8d00001000sv00001DD8sd00004002* + ID_MODEL_FROM_DATABASE=DSC Capri Upstream Port (Naples 25Gb 2-port SFP28 x8 4GB) + +pci:v00001DD8d00001001* + ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port + +pci:v00001DD8d00001001sv00001DD8sd00004000* + ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (Naples 100Gb 2-port QSFP28 x16 8GB) + +pci:v00001DD8d00001001sv00001DD8sd00004001* + ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (Naples 100Gb 2-port QSFP28 x16 4GB) + +pci:v00001DD8d00001001sv00001DD8sd00004002* + ID_MODEL_FROM_DATABASE=DSC Virtual Downstream Port (Naples 25Gb 2-port SFP28 x8 4GB) + +pci:v00001DD8d00001002* + ID_MODEL_FROM_DATABASE=DSC Ethernet Controller + +pci:v00001DD8d00001002sv00001DD8sd00004000* + ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (Naples 100Gb 2-port QSFP28 x16 8GB) + +pci:v00001DD8d00001002sv00001DD8sd00004001* + ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (Naples 100Gb 2-port QSFP28 x16 4GB) + +pci:v00001DD8d00001002sv00001DD8sd00004002* + ID_MODEL_FROM_DATABASE=DSC Ethernet Controller (Naples 25Gb 2-port SFP28 x8 4GB) + +pci:v00001DD8d00001003* + ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF + +pci:v00001DD8d00001003sv00001DD8sd00004000* + ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (Naples 100Gb 2-port QSFP28 x16 8GB) + +pci:v00001DD8d00001003sv00001DD8sd00004001* + ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (Naples 100Gb 2-port QSFP28 x16 4GB) + +pci:v00001DD8d00001003sv00001DD8sd00004002* + ID_MODEL_FROM_DATABASE=DSC Ethernet Controller VF (Naples 25Gb 2-port SFP28 x8 4GB) + +pci:v00001DD8d00001004* + ID_MODEL_FROM_DATABASE=DSC Management Controller + +pci:v00001DD8d00001004sv00001DD8sd00004000* + ID_MODEL_FROM_DATABASE=DSC Management Controller (Naples 100Gb 2-port QSFP28 x16 8GB) + +pci:v00001DD8d00001004sv00001DD8sd00004001* + ID_MODEL_FROM_DATABASE=DSC Management Controller (Naples 100Gb 2-port QSFP28 x16 4GB) + +pci:v00001DD8d00001004sv00001DD8sd00004002* + ID_MODEL_FROM_DATABASE=DSC Management Controller (Naples 25Gb 2-port SFP28 x8 4GB) + +pci:v00001DD8d00001007* + ID_MODEL_FROM_DATABASE=DSC Storage Accelerator + +pci:v00001DD8d00001007sv00001DD8sd00004000* + ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (Naples 100Gb 2-port QSFP28 x16 8GB) + +pci:v00001DD8d00001007sv00001DD8sd00004001* + ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (Naples 100Gb 2-port QSFP28 x16 4GB) + +pci:v00001DD8d00001007sv00001DD8sd00004002* + ID_MODEL_FROM_DATABASE=DSC Storage Accelerator (Naples 25Gb 2-port SFP28 x8 4GB) + +pci:v00001DE0* + ID_VENDOR_FROM_DATABASE=Groq + +pci:v00001DE0d00000000* + ID_MODEL_FROM_DATABASE=Q100 Tensor Streaming Processor + +pci:v00001DE1* + ID_VENDOR_FROM_DATABASE=Tekram Technology Co.,Ltd. + +pci:v00001DE1d00000391* + ID_MODEL_FROM_DATABASE=TRM-S1040 [DC-315 / DC-395 series] + +pci:v00001DE1d00002020* + ID_MODEL_FROM_DATABASE=DC-390 + +pci:v00001DE1d0000690C* + ID_MODEL_FROM_DATABASE=690c + +pci:v00001DE1d0000DC29* + ID_MODEL_FROM_DATABASE=DC290 + +pci:v00001DE5* + ID_VENDOR_FROM_DATABASE=Eideticom, Inc + +pci:v00001DE5d00001000* + ID_MODEL_FROM_DATABASE=IO Memory Controller + +pci:v00001DE5d00002000* + ID_MODEL_FROM_DATABASE=NoLoad Hardware Development Kit + +pci:v00001DEF* + ID_VENDOR_FROM_DATABASE=Ampere Computing, LLC + +pci:v00001DEFd0000E005* + ID_MODEL_FROM_DATABASE=eMAG PCI Express Root Port 0 + +pci:v00001DEFd0000E006* + ID_MODEL_FROM_DATABASE=eMAG PCI Express Root Port 1 + +pci:v00001DEFd0000E007* + ID_MODEL_FROM_DATABASE=eMAG PCI Express Root Port 2 + +pci:v00001DEFd0000E008* + ID_MODEL_FROM_DATABASE=eMAG PCI Express Root Port 3 + +pci:v00001DEFd0000E009* + ID_MODEL_FROM_DATABASE=eMAG PCI Express Root Port 4 + +pci:v00001DEFd0000E00A* + ID_MODEL_FROM_DATABASE=eMAG PCI Express Root Port 5 + +pci:v00001DEFd0000E00B* + ID_MODEL_FROM_DATABASE=eMAG PCI Express Root Port 6 + +pci:v00001DEFd0000E00C* + ID_MODEL_FROM_DATABASE=eMAG PCI Express Root Port 7 + +pci:v00001DF3* + ID_VENDOR_FROM_DATABASE=Ethernity Networks + +pci:v00001DF3d00000201* + ID_MODEL_FROM_DATABASE=ACE-NIC40 Programmable Network Accelerator + +pci:v00001DF3d00000201sv00001DF3sd00000001* + ID_MODEL_FROM_DATABASE=ACE-NIC40 Programmable Network Accelerator (ENA1040) + +pci:v00001DF3d00000201sv00001DF3sd00000002* + ID_MODEL_FROM_DATABASE=ACE-NIC40 Programmable Network Accelerator (ENA1044) + +pci:v00001DF3d00000201sv00001DF3sd00000003* + ID_MODEL_FROM_DATABASE=ACE-NIC40 Programmable Network Accelerator (ENA1044S) + +pci:v00001DF3d00000202* + ID_MODEL_FROM_DATABASE=ACE-NIC50 Programmable Network Accelerator + +pci:v00001DF3d00000202sv00001DF3sd00000001* + ID_MODEL_FROM_DATABASE=ACE-NIC50 Programmable Network Accelerator (ENA2050F) + +pci:v00001DF3d00000202sv00001DF3sd00000002* + ID_MODEL_FROM_DATABASE=ACE-NIC50 Programmable Network Accelerator (ENA2050FS) + +pci:v00001DF3d00000203* + ID_MODEL_FROM_DATABASE=ACE-NIC100 Programmable Network Accelerator + +pci:v00001DF3d00000203sv00001DF3sd00000000* + ID_MODEL_FROM_DATABASE=ACE-NIC100 Programmable Network Accelerator (Maintenance Mode) + +pci:v00001DF3d00000203sv00001DF3sd00000001* + ID_MODEL_FROM_DATABASE=ACE-NIC100 Programmable Network Accelerator (ENA2080F) + +pci:v00001DF3d00000203sv00001DF3sd00000002* + ID_MODEL_FROM_DATABASE=ACE-NIC100 Programmable Network Accelerator (ENA2080FS) + +pci:v00001DF3d00000203sv00001DF3sd00000003* + ID_MODEL_FROM_DATABASE=ACE-NIC100 Programmable Network Accelerator (ENA2100F) + +pci:v00001DF3d00000203sv00001DF3sd00000004* + ID_MODEL_FROM_DATABASE=ACE-NIC100 Programmable Network Accelerator (ENA2040F) + +pci:v00001DF3d00000204* + ID_MODEL_FROM_DATABASE=ACE-NIC-NID Programmable Network Accelerator + +pci:v00001DF3d00000204sv00001DF3sd00000001* + ID_MODEL_FROM_DATABASE=ACE-NIC-NID Programmable Network Accelerator (ENA1020Z) + +pci:v00001DF3d00000204sv00001DF3sd00000002* + ID_MODEL_FROM_DATABASE=ACE-NIC-NID Programmable Network Accelerator (ENA1020ZS) + +pci:v00001DF7* + ID_VENDOR_FROM_DATABASE=opencpi.org + +pci:v00001DF7d00000001* + ID_MODEL_FROM_DATABASE=ml605 + +pci:v00001DF7d00000002* + ID_MODEL_FROM_DATABASE=alst4 + +pci:v00001DF7d00000003* + ID_MODEL_FROM_DATABASE=alst4x + +pci:v00001DFC* + ID_VENDOR_FROM_DATABASE=JSC NT-COM + +pci:v00001DFCd00001181* + ID_MODEL_FROM_DATABASE=TDM 8 Port E1/T1/J1 Adapter + +pci:v00001E17* + ID_VENDOR_FROM_DATABASE=Arnold & Richter Cine Technik GmbH & Co. Betriebs KG + +pci:v00001E24* + ID_VENDOR_FROM_DATABASE=Squirrels Research Labs + +pci:v00001E24d00000101* + ID_MODEL_FROM_DATABASE=Acorn CLE-101 + +pci:v00001E24d00000215* + ID_MODEL_FROM_DATABASE=Acorn CLE-215 + +pci:v00001E24d0000021F* + ID_MODEL_FROM_DATABASE=Acorn CLE-215+ + +pci:v00001E24d00001525* + ID_MODEL_FROM_DATABASE=Xilinx BCU-1525 + +pci:v00001E24d00001533* + ID_MODEL_FROM_DATABASE=ForestKitten 33 + +pci:v00001E24d00001633* + ID_MODEL_FROM_DATABASE=JCM33 + +pci:v00001E24d00001635* + ID_MODEL_FROM_DATABASE=JCM35 + +pci:v00001E26* + ID_VENDOR_FROM_DATABASE=Fujitsu Client Computing Limited + +pci:v00001E38* + ID_VENDOR_FROM_DATABASE=Blaize, Inc + +pci:v00001E3D* + ID_VENDOR_FROM_DATABASE=Burlywood, Inc + +pci:v00001E49* + ID_VENDOR_FROM_DATABASE=Yangtze Memory Technologies Co.,Ltd + +pci:v00001E4C* + ID_VENDOR_FROM_DATABASE=GSI Technology + +pci:v00001E4Cd00000010* + ID_MODEL_FROM_DATABASE=Gemini [ Lida ] + +pci:v00001E4Cd00000010sv00001E4Csd00000120* + ID_MODEL_FROM_DATABASE=Gemini [ Lida ] (SE120) + +pci:v00001E57* + ID_VENDOR_FROM_DATABASE=Beijing Panyi Technology Co., Ltd + +pci:v00001E57d00000100* + ID_MODEL_FROM_DATABASE=The device has already been deleted. + +pci:v00001E57d00000100sv00000000sd00000100* + ID_MODEL_FROM_DATABASE=The device has already been deleted. (PY8800 64GB Accelerator) + +pci:v00001E6B* + ID_VENDOR_FROM_DATABASE=Axiado Corp. + +pci:v00001E89* + ID_VENDOR_FROM_DATABASE=ID Quantique SA + +pci:v00001E89d00000002* + ID_MODEL_FROM_DATABASE=Quantis-PCIe-40M + +pci:v00001E89d00000003* + ID_MODEL_FROM_DATABASE=Quantis-PCIe-240M + +pci:v00001FC0* + ID_VENDOR_FROM_DATABASE=Ascom (Finland) Oy + +pci:v00001FC0d00000300* + ID_MODEL_FROM_DATABASE=E2200 Dual E1/Rawpipe Card + +pci:v00001FC0d00000301* + ID_MODEL_FROM_DATABASE=C5400 SHDSL/E1 Card + +pci:v00001FC1* + ID_VENDOR_FROM_DATABASE=QLogic, Corp. + +pci:v00001FC1d0000000D* + ID_MODEL_FROM_DATABASE=IBA6110 InfiniBand HCA + +pci:v00001FC1d00000010* + ID_MODEL_FROM_DATABASE=IBA6120 InfiniBand HCA + +pci:v00001FC9* + ID_VENDOR_FROM_DATABASE=Tehuti Networks Ltd. + +pci:v00001FC9d00003009* + ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC + +pci:v00001FC9d00003010* + ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC + +pci:v00001FC9d00003010sv00000000sd00003002* + ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC (10-Giga TOE Single Port XFP SmartNIC) + +pci:v00001FC9d00003010sv00000000sd00003004* + ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC (10-Giga TOE Single Port SFP+ SmartNIC) + +pci:v00001FC9d00003010sv00000000sd00003008* + ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC (10-Giga TOE Single Port CX4 SmartNIC) + +pci:v00001FC9d00003014* + ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC 2-Port + +pci:v00001FC9d00003014sv00000000sd00003003* + ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC 2-Port (10-Giga TOE Dual Port XFP Low Profile SmartNIC) + +pci:v00001FC9d00003014sv00000000sd00003005* + ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC 2-Port (10-Giga TOE Dual Port SFP+ Low Profile SmartNIC) + +pci:v00001FC9d00003014sv00000000sd00003014* + ID_MODEL_FROM_DATABASE=10-Giga TOE SmartNIC 2-Port (10-Giga TOE Dual Port CX4 Low Profile SmartNIC) + +pci:v00001FC9d00003110* + ID_MODEL_FROM_DATABASE=10-Giga TOE Single Port SmartNIC + +pci:v00001FC9d00003110sv00000000sd00003004* + ID_MODEL_FROM_DATABASE=10-Giga TOE Single Port SmartNIC (10-Giga TOE Single Port SFP+ SmartNIC) + +pci:v00001FC9d00003114* + ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC + +pci:v00001FC9d00003114sv00000000sd00003005* + ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port SFP+ Low Profile SmartNIC) + +pci:v00001FC9d00003114sv00000000sd00003011* + ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port SFP+/CX4 Low Profile SmartNIC) + +pci:v00001FC9d00003114sv00000000sd00003012* + ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port CX4/SFP+ Low Profile SmartNIC) + +pci:v00001FC9d00003114sv00000000sd00003014* + ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port CX4 Low Profile SmartNIC) + +pci:v00001FC9d00003310* + ID_MODEL_FROM_DATABASE=10-Giga TOE SFP+ Single Port SmartNIC + +pci:v00001FC9d00003310sv00000000sd00003004* + ID_MODEL_FROM_DATABASE=10-Giga TOE SFP+ Single Port SmartNIC (10-Giga TOE Single Port SFP+ SmartNIC) + +pci:v00001FC9d00003314* + ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC + +pci:v00001FC9d00003314sv00000000sd00003005* + ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port SFP+ Low Profile SmartNIC) + +pci:v00001FC9d00003314sv00000000sd00003011* + ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port SFP+/CX4 Low Profile SmartNIC) + +pci:v00001FC9d00003314sv00000000sd00003012* + ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port CX4/SFP+ Low Profile SmartNIC) + +pci:v00001FC9d00003314sv00000000sd00003014* + ID_MODEL_FROM_DATABASE=10-Giga TOE Dual Port Low Profile SmartNIC (10-Giga TOE Dual Port CX4 Low Profile SmartNIC) + +pci:v00001FC9d00004010* + ID_MODEL_FROM_DATABASE=TN4010 Clean SROM + +pci:v00001FC9d00004020* + ID_MODEL_FROM_DATABASE=TN9030 10GbE CX4 Ethernet Adapter + +pci:v00001FC9d00004020sv0000180Csd00002040* + ID_MODEL_FROM_DATABASE=TN9030 10GbE CX4 Ethernet Adapter (Mustang-200 10GbE Ethernet Adapter) + +pci:v00001FC9d00004022* + ID_MODEL_FROM_DATABASE=TN9310 10GbE SFP+ Ethernet Adapter + +pci:v00001FC9d00004022sv00001043sd00008709* + ID_MODEL_FROM_DATABASE=TN9310 10GbE SFP+ Ethernet Adapter (XG-C100F 10GbE SFP+ Ethernet Adapter) + +pci:v00001FC9d00004022sv00001186sd00004D00* + ID_MODEL_FROM_DATABASE=TN9310 10GbE SFP+ Ethernet Adapter (DXE-810S 10GbE SFP+ Ethernet Adapter) + +pci:v00001FC9d00004022sv00001432sd00008103* + ID_MODEL_FROM_DATABASE=TN9310 10GbE SFP+ Ethernet Adapter (10 Gigabit Ethernet SFP+ PCI Express Adapter) + +pci:v00001FC9d00004022sv00001FC9sd00003015* + ID_MODEL_FROM_DATABASE=TN9310 10GbE SFP+ Ethernet Adapter (Ethernet Adapter) + +pci:v00001FC9d00004024* + ID_MODEL_FROM_DATABASE=TN9210 10GBase-T Ethernet Adapter + +pci:v00001FC9d00004025* + ID_MODEL_FROM_DATABASE=TN9510 10GBase-T/NBASE-T Ethernet Adapter + +pci:v00001FC9d00004025sv0000105Asd00007203* + ID_MODEL_FROM_DATABASE=TN9510 10GBase-T/NBASE-T Ethernet Adapter (SANLink3 NBase-T1) + +pci:v00001FC9d00004025sv00001186sd00002900* + ID_MODEL_FROM_DATABASE=TN9510 10GBase-T/NBASE-T Ethernet Adapter (DXE-810T 10GBase-T Ethernet Adapter) + +pci:v00001FC9d00004025sv00001432sd00008102* + ID_MODEL_FROM_DATABASE=TN9510 10GBase-T/NBASE-T Ethernet Adapter (10 Gigabit Ethernet PCI Express Adapter) + +pci:v00001FC9d00004025sv00001FC9sd00003015* + ID_MODEL_FROM_DATABASE=TN9510 10GBase-T/NBASE-T Ethernet Adapter (Ethernet Adapter) + +pci:v00001FC9d00004026* + ID_MODEL_FROM_DATABASE=TN9610 10GbE SFP+ Ethernet Adapter + +pci:v00001FC9d00004026sv00004C52sd00001000* + ID_MODEL_FROM_DATABASE=TN9610 10GbE SFP+ Ethernet Adapter (LREC6860AF 10 Gigabit Ethernet Adapter) + +pci:v00001FC9d00004027* + ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter + +pci:v00001FC9d00004027sv00001154sd00000368* + ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (LGY-PCIE-MG) + +pci:v00001FC9d00004027sv00001432sd00008104* + ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (10 Gigabit Ethernet PCI Express Adapter) + +pci:v00001FC9d00004027sv00001546sd00004027* + ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (GE10-PCIE4XG202P 10Gbase-T/NBASE-T Ethernet Adapter) + +pci:v00001FC9d00004027sv00001BAAsd00003310* + ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (PCIe Expansion Card) + +pci:v00001FC9d00004027sv00001FC9sd00003015* + ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (Ethernet Adapter) + +pci:v00001FC9d00004027sv00004C52sd00001001* + ID_MODEL_FROM_DATABASE=TN9710P 10GBase-T/NBASE-T Ethernet Adapter (LREC6860BT 10 Gigabit Ethernet Adapter) + +pci:v00001FC9d00004527* + ID_MODEL_FROM_DATABASE=TN9710Q 5GBase-T/NBASE-T Ethernet Adapter + +pci:v00001FCC* + ID_VENDOR_FROM_DATABASE=StreamLabs + +pci:v00001FCCd0000F416* + ID_MODEL_FROM_DATABASE=MS416 + +pci:v00001FCCd0000FB01* + ID_MODEL_FROM_DATABASE=MH4LM + +pci:v00001FCE* + ID_VENDOR_FROM_DATABASE=Cognio Inc. + +pci:v00001FCEd00000001* + ID_MODEL_FROM_DATABASE=Spectrum Analyzer PC Card (SAgE) + +pci:v00001FD4* + ID_VENDOR_FROM_DATABASE=SUNIX Co., Ltd. + +pci:v00001FD4d00000001* + ID_MODEL_FROM_DATABASE=Matrix multiport serial adapter + +pci:v00001FD4d00001999* + ID_MODEL_FROM_DATABASE=Multiport serial controller + +pci:v00002000* + ID_VENDOR_FROM_DATABASE=Smart Link Ltd. + +pci:v00002000d00002800* + ID_MODEL_FROM_DATABASE=SmartPCI2800 V.92 PCI Soft DFT + +pci:v00002001* + ID_VENDOR_FROM_DATABASE=Temporal Research Ltd + +pci:v00002003* + ID_VENDOR_FROM_DATABASE=Smart Link Ltd. + +pci:v00002003d00008800* + ID_MODEL_FROM_DATABASE=LM-I56N + +pci:v00002004* + ID_VENDOR_FROM_DATABASE=Smart Link Ltd. + +pci:v00002048* + ID_VENDOR_FROM_DATABASE=Beijing SpaceControl Technology Co.Ltd + +pci:v000020F4* + ID_VENDOR_FROM_DATABASE=TRENDnet + +pci:v00002116* + ID_VENDOR_FROM_DATABASE=ZyDAS Technology Corp. + +pci:v000021C3* + ID_VENDOR_FROM_DATABASE=21st Century Computer Corp. + +pci:v000022B8* + ID_VENDOR_FROM_DATABASE=Flex-Logix Technologies + +pci:v000022B8d000022A0* + ID_MODEL_FROM_DATABASE=Flex Logix InferX X1 Inference Accelerator + +pci:v000022DB* + ID_VENDOR_FROM_DATABASE=Missing Link Electronics, Inc. + +pci:v00002304* + ID_VENDOR_FROM_DATABASE=Colorgraphic Communications Corp. + +pci:v00002348* + ID_VENDOR_FROM_DATABASE=Racore + +pci:v00002348d00002010* + ID_MODEL_FROM_DATABASE=8142 100VG/AnyLAN + +pci:v00002646* + ID_VENDOR_FROM_DATABASE=Kingston Technology Company, Inc. + +pci:v0000270B* + ID_VENDOR_FROM_DATABASE=Xantel Corporation + +pci:v0000270F* + ID_VENDOR_FROM_DATABASE=Chaintech Computer Co. Ltd + +pci:v00002711* + ID_VENDOR_FROM_DATABASE=AVID Technology Inc. + +pci:v00002955* + ID_VENDOR_FROM_DATABASE=Connectix Virtual PC + +pci:v00002955d00006E61* + ID_MODEL_FROM_DATABASE=OHCI USB 1.1 controller + +pci:v00002A15* + ID_VENDOR_FROM_DATABASE=3D Vision(???) + +pci:v00002BD8* + ID_VENDOR_FROM_DATABASE=ROPEX Industrie-Elektronik GmbH + +pci:v00003000* + ID_VENDOR_FROM_DATABASE=Hansol Electronics Inc. + +pci:v00003112* + ID_VENDOR_FROM_DATABASE=Satelco Ingenieria S.A. + +pci:v00003130* + ID_VENDOR_FROM_DATABASE=AUDIOTRAK + +pci:v00003142* + ID_VENDOR_FROM_DATABASE=Post Impression Systems. + +pci:v000031AB* + ID_VENDOR_FROM_DATABASE=Zonet + +pci:v000031ABd00001FAA* + ID_MODEL_FROM_DATABASE=ZEW1602 802.11b/g Wireless Adapter + +pci:v00003388* + ID_VENDOR_FROM_DATABASE=Hint Corp + +pci:v00003388d00000013* + ID_MODEL_FROM_DATABASE=HiNT HC4 PCI to ISDN bridge, Multimedia audio controller + +pci:v00003388d00000014* + ID_MODEL_FROM_DATABASE=HiNT HC4 PCI to ISDN bridge, Network controller + +pci:v00003388d00000020* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (transparent mode) + +pci:v00003388d00000021* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) + +pci:v00003388d00000021sv00001775sd0000C200* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (C2K CompactPCI interface bridge) + +pci:v00003388d00000021sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (CE9) + +pci:v00003388d00000021sv00004C53sd00001050* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (CT7 mainboard) + +pci:v00003388d00000021sv00004C53sd00001080* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (CT8 mainboard) + +pci:v00003388d00000021sv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (Cx9 mainboard) + +pci:v00003388d00000021sv00004C53sd000010A0* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (CA3/CR3 mainboard) + +pci:v00003388d00000021sv00004C53sd00003010* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (PPCI mezzanine (32-bit PMC)) + +pci:v00003388d00000021sv00004C53sd00003011* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (PPCI mezzanine (64-bit PMC)) + +pci:v00003388d00000021sv00004C53sd00004000* + ID_MODEL_FROM_DATABASE=HB6 Universal PCI-PCI bridge (non-transparent mode) (PMCCARR1 carrier board) + +pci:v00003388d00000022* + ID_MODEL_FROM_DATABASE=HiNT HB4 PCI-PCI Bridge (PCI6150) + +pci:v00003388d00000026* + ID_MODEL_FROM_DATABASE=HB2 PCI-PCI Bridge + +pci:v00003388d00001014* + ID_MODEL_FROM_DATABASE=AudioTrak Maya + +pci:v00003388d00001018* + ID_MODEL_FROM_DATABASE=Audiotrak INCA88 + +pci:v00003388d00001019* + ID_MODEL_FROM_DATABASE=Miditrak 2120 + +pci:v00003388d0000101A* + ID_MODEL_FROM_DATABASE=E.Band [AudioTrak Inca88] + +pci:v00003388d0000101B* + ID_MODEL_FROM_DATABASE=E.Band [AudioTrak Inca88] + +pci:v00003388d00008011* + ID_MODEL_FROM_DATABASE=VXPro II Chipset + +pci:v00003388d00008011sv00003388sd00008011* + ID_MODEL_FROM_DATABASE=VXPro II Chipset (CPU to PCI Bridge) + +pci:v00003388d00008012* + ID_MODEL_FROM_DATABASE=VXPro II Chipset + +pci:v00003388d00008012sv00003388sd00008012* + ID_MODEL_FROM_DATABASE=VXPro II Chipset (PCI to ISA Bridge) + +pci:v00003388d00008013* + ID_MODEL_FROM_DATABASE=VXPro II IDE + +pci:v00003388d00008013sv00003388sd00008013* + ID_MODEL_FROM_DATABASE=VXPro II IDE (VXPro II Chipset EIDE Controller) + +pci:v00003388d0000A103* + ID_MODEL_FROM_DATABASE=Blackmagic Design DeckLink HD Pro + +pci:v00003411* + ID_VENDOR_FROM_DATABASE=Quantum Designs (H.K.) Inc + +pci:v00003442* + ID_VENDOR_FROM_DATABASE=Bihl+Wiedemann GmbH + +pci:v00003442d00001783* + ID_MODEL_FROM_DATABASE=AS-i 3.0 cPCI Master + +pci:v00003442d00001922* + ID_MODEL_FROM_DATABASE=AS-i 3.0 PCI Master + +pci:v00003475* + ID_VENDOR_FROM_DATABASE=Arastra Inc. + +pci:v00003513* + ID_VENDOR_FROM_DATABASE=ARCOM Control Systems Ltd + +pci:v000037D9* + ID_VENDOR_FROM_DATABASE=ITD Firm ltd. + +pci:v000037D9d00001138* + ID_MODEL_FROM_DATABASE=SCHD-PH-8 Phase detector + +pci:v000037D9d00001140* + ID_MODEL_FROM_DATABASE=VR-12-PCI + +pci:v000037D9d00001141* + ID_MODEL_FROM_DATABASE=PCI-485(422) + +pci:v000037D9d00001142* + ID_MODEL_FROM_DATABASE=PCI-CAN2 + +pci:v00003842* + ID_VENDOR_FROM_DATABASE=eVga.com. Corp. + +pci:v000038EF* + ID_VENDOR_FROM_DATABASE=4Links + +pci:v00003D3D* + ID_VENDOR_FROM_DATABASE=3DLabs + +pci:v00003D3Dd00000001* + ID_MODEL_FROM_DATABASE=GLINT 300SX + +pci:v00003D3Dd00000002* + ID_MODEL_FROM_DATABASE=GLINT 500TX + +pci:v00003D3Dd00000002sv00000000sd00000000* + ID_MODEL_FROM_DATABASE=GLINT 500TX (GLoria L) + +pci:v00003D3Dd00000003* + ID_MODEL_FROM_DATABASE=GLINT Delta + +pci:v00003D3Dd00000003sv00000000sd00000000* + ID_MODEL_FROM_DATABASE=GLINT Delta (GLoria XL) + +pci:v00003D3Dd00000004* + ID_MODEL_FROM_DATABASE=Permedia + +pci:v00003D3Dd00000005* + ID_MODEL_FROM_DATABASE=Permedia + +pci:v00003D3Dd00000006* + ID_MODEL_FROM_DATABASE=GLINT MX + +pci:v00003D3Dd00000006sv00000000sd00000000* + ID_MODEL_FROM_DATABASE=GLINT MX (GLoria XL) + +pci:v00003D3Dd00000006sv00001048sd00000A42* + ID_MODEL_FROM_DATABASE=GLINT MX (GLoria XXL) + +pci:v00003D3Dd00000007* + ID_MODEL_FROM_DATABASE=3D Extreme + +pci:v00003D3Dd00000008* + ID_MODEL_FROM_DATABASE=GLINT Gamma G1 + +pci:v00003D3Dd00000008sv00001048sd00000A42* + ID_MODEL_FROM_DATABASE=GLINT Gamma G1 (GLoria XXL) + +pci:v00003D3Dd00000009* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D + +pci:v00003D3Dd00000009sv00001040sd00000011* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (AccelStar II) + +pci:v00003D3Dd00000009sv00001048sd00000A42* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (GLoria XXL) + +pci:v00003D3Dd00000009sv000013E9sd00001000* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (6221L-4U) + +pci:v00003D3Dd00000009sv00003D3Dsd00000100* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (AccelStar II 3D Accelerator) + +pci:v00003D3Dd00000009sv00003D3Dsd00000111* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Permedia 3:16) + +pci:v00003D3Dd00000009sv00003D3Dsd00000114* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Santa Ana) + +pci:v00003D3Dd00000009sv00003D3Dsd00000116* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Oxygen GVX1) + +pci:v00003D3Dd00000009sv00003D3Dsd00000119* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Scirocco) + +pci:v00003D3Dd00000009sv00003D3Dsd00000120* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Santa Ana PCL) + +pci:v00003D3Dd00000009sv00003D3Dsd00000125* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Oxygen VX1) + +pci:v00003D3Dd00000009sv00003D3Dsd00000127* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D (Permedia3 Create!) + +pci:v00003D3Dd0000000A* + ID_MODEL_FROM_DATABASE=GLINT R3 + +pci:v00003D3Dd0000000Asv00003D3Dsd00000121* + ID_MODEL_FROM_DATABASE=GLINT R3 (Oxygen VX1) + +pci:v00003D3Dd0000000C* + ID_MODEL_FROM_DATABASE=GLINT R3 [Oxygen VX1] + +pci:v00003D3Dd0000000Csv00003D3Dsd00000144* + ID_MODEL_FROM_DATABASE=GLINT R3 [Oxygen VX1] (Oxygen VX1-4X AGP [Permedia 4]) + +pci:v00003D3Dd0000000D* + ID_MODEL_FROM_DATABASE=GLint R4 rev A + +pci:v00003D3Dd0000000E* + ID_MODEL_FROM_DATABASE=GLINT Gamma G2 + +pci:v00003D3Dd00000011* + ID_MODEL_FROM_DATABASE=GLint R4 rev B + +pci:v00003D3Dd00000012* + ID_MODEL_FROM_DATABASE=GLint R5 rev A + +pci:v00003D3Dd00000013* + ID_MODEL_FROM_DATABASE=GLint R5 rev B + +pci:v00003D3Dd00000020* + ID_MODEL_FROM_DATABASE=VP10 visual processor + +pci:v00003D3Dd00000022* + ID_MODEL_FROM_DATABASE=VP10 visual processor + +pci:v00003D3Dd00000024* + ID_MODEL_FROM_DATABASE=VP9 visual processor + +pci:v00003D3Dd0000002C* + ID_MODEL_FROM_DATABASE=Wildcat Realizm 100/200 + +pci:v00003D3Dd00000030* + ID_MODEL_FROM_DATABASE=Wildcat Realizm 800 + +pci:v00003D3Dd00000032* + ID_MODEL_FROM_DATABASE=Wildcat Realizm 500 + +pci:v00003D3Dd00000100* + ID_MODEL_FROM_DATABASE=Permedia II 2D+3D + +pci:v00003D3Dd000007A1* + ID_MODEL_FROM_DATABASE=Wildcat III 6210 + +pci:v00003D3Dd000007A2* + ID_MODEL_FROM_DATABASE=Sun XVR-500 Graphics Accelerator + +pci:v00003D3Dd000007A3* + ID_MODEL_FROM_DATABASE=Wildcat IV 7210 + +pci:v00003D3Dd00001004* + ID_MODEL_FROM_DATABASE=Permedia + +pci:v00003D3Dd00003D04* + ID_MODEL_FROM_DATABASE=Permedia + +pci:v00003D3Dd0000FFFF* + ID_MODEL_FROM_DATABASE=Glint VGA + +pci:v00004005* + ID_VENDOR_FROM_DATABASE=Avance Logic Inc. + +pci:v00004005d00000300* + ID_MODEL_FROM_DATABASE=ALS300 PCI Audio Device + +pci:v00004005d00000308* + ID_MODEL_FROM_DATABASE=ALS300+ PCI Audio Device + +pci:v00004005d00000309* + ID_MODEL_FROM_DATABASE=PCI Input Controller + +pci:v00004005d00001064* + ID_MODEL_FROM_DATABASE=ALG-2064 + +pci:v00004005d00002064* + ID_MODEL_FROM_DATABASE=ALG-2064i + +pci:v00004005d00002128* + ID_MODEL_FROM_DATABASE=ALG-2364A GUI Accelerator + +pci:v00004005d00002301* + ID_MODEL_FROM_DATABASE=ALG-2301 + +pci:v00004005d00002302* + ID_MODEL_FROM_DATABASE=ALG-2302 + +pci:v00004005d00002303* + ID_MODEL_FROM_DATABASE=AVG-2302 GUI Accelerator + +pci:v00004005d00002364* + ID_MODEL_FROM_DATABASE=ALG-2364A + +pci:v00004005d00002464* + ID_MODEL_FROM_DATABASE=ALG-2464 + +pci:v00004005d00002501* + ID_MODEL_FROM_DATABASE=ALG-2564A/25128A + +pci:v00004005d00004000* + ID_MODEL_FROM_DATABASE=ALS4000 Audio Chipset + +pci:v00004005d00004000sv00004005sd00004000* + ID_MODEL_FROM_DATABASE=ALS4000 Audio Chipset + +pci:v00004005d00004710* + ID_MODEL_FROM_DATABASE=ALC200/200P + +pci:v00004033* + ID_VENDOR_FROM_DATABASE=Addtron Technology Co, Inc. + +pci:v00004033d00001360* + ID_MODEL_FROM_DATABASE=RTL8139 Ethernet + +pci:v00004040* + ID_VENDOR_FROM_DATABASE=NetXen Incorporated + +pci:v00004040d00000001* + ID_MODEL_FROM_DATABASE=NXB-10GXSR 10-Gigabit Ethernet PCIe Adapter with SR-XFP optical interface + +pci:v00004040d00000001sv0000103Csd00007047* + ID_MODEL_FROM_DATABASE=NXB-10GXSR 10-Gigabit Ethernet PCIe Adapter with SR-XFP optical interface (NC510F PCIe 10-Gigabit Server Adapter) + +pci:v00004040d00000002* + ID_MODEL_FROM_DATABASE=NXB-10GCX4 10-Gigabit Ethernet PCIe Adapter with CX4 copper interface + +pci:v00004040d00000002sv0000103Csd00007048* + ID_MODEL_FROM_DATABASE=NXB-10GCX4 10-Gigabit Ethernet PCIe Adapter with CX4 copper interface (NC510c PCIe 10-Gigabit Server Adapter) + +pci:v00004040d00000003* + ID_MODEL_FROM_DATABASE=NXB-4GCU Quad Gigabit Ethernet PCIe Adapter with 1000-BASE-T interface + +pci:v00004040d00000004* + ID_MODEL_FROM_DATABASE=BladeCenter-H 10-Gigabit Ethernet High Speed Daughter Card + +pci:v00004040d00000005* + ID_MODEL_FROM_DATABASE=NetXen Dual Port 10GbE Multifunction Adapter for c-Class + +pci:v00004040d00000005sv0000103Csd0000170E* + ID_MODEL_FROM_DATABASE=NetXen Dual Port 10GbE Multifunction Adapter for c-Class (NC512m Dual Port 10GbE Multifunction BL-C Adapter) + +pci:v00004040d00000024* + ID_MODEL_FROM_DATABASE=XG Mgmt + +pci:v00004040d00000025* + ID_MODEL_FROM_DATABASE=XG Mgmt + +pci:v00004040d00000100* + ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter + +pci:v00004040d00000100sv0000103Csd0000171B* + ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NC522m Dual Port 10GbE Multifunction BL-c Adapter) + +pci:v00004040d00000100sv0000103Csd00001740* + ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NC375T PCI Express Quad Port Gigabit Server Adapter) + +pci:v00004040d00000100sv0000103Csd00003251* + ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NC375i 1G w/NC524SFP 10G Module) + +pci:v00004040d00000100sv0000103Csd0000705A* + ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NC375i Integrated Quad Port Multifunction Gigabit Server Adapter) + +pci:v00004040d00000100sv0000103Csd0000705B* + ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NC522SFP Dual Port 10GbE Server Adapter) + +pci:v00004040d00000100sv0000152Dsd0000896B* + ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (TG20 Dual Port 10GbE Server/Storage Adapter) + +pci:v00004040d00000100sv00004040sd00000124* + ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (NX3031 Quad Port Gigabit Server Adapter) + +pci:v00004040d00000100sv00004040sd00000126* + ID_MODEL_FROM_DATABASE=NX3031 Multifunction 1/10-Gigabit Server Adapter (Dual Port SFP+ 10GbE Server Adapter) + +pci:v00004143* + ID_VENDOR_FROM_DATABASE=Digital Equipment Corp + +pci:v00004144* + ID_VENDOR_FROM_DATABASE=Alpha Data + +pci:v00004144d00000044* + ID_MODEL_FROM_DATABASE=ADM-XRCIIPro + +pci:v00004150* + ID_VENDOR_FROM_DATABASE=ONA Electroerosion + +pci:v00004150d00000001* + ID_MODEL_FROM_DATABASE=PCI32TLITE FILSTRUP1 PCI to VME Bridge Controller + +pci:v00004150d00000006* + ID_MODEL_FROM_DATABASE=PCI32TLITE UART 16550 Opencores + +pci:v00004150d00000007* + ID_MODEL_FROM_DATABASE=PCI32TLITE CAN Controller Opencores + +pci:v0000415A* + ID_VENDOR_FROM_DATABASE=Auzentech, Inc. + +pci:v0000416C* + ID_VENDOR_FROM_DATABASE=Aladdin Knowledge Systems + +pci:v0000416Cd00000100* + ID_MODEL_FROM_DATABASE=AladdinCARD + +pci:v0000416Cd00000200* + ID_MODEL_FROM_DATABASE=CPC + +pci:v00004254* + ID_VENDOR_FROM_DATABASE=DVBSky + +pci:v00004321* + ID_VENDOR_FROM_DATABASE=Tata Power Strategic Electronics Division + +pci:v00004348* + ID_VENDOR_FROM_DATABASE=WCH.CN + +pci:v00004348d00002273* + ID_MODEL_FROM_DATABASE=CH351 PCI Dual Serial Port Controller + +pci:v00004348d00003253* + ID_MODEL_FROM_DATABASE=CH352 PCI Dual Serial Port Controller + +pci:v00004348d00003453* + ID_MODEL_FROM_DATABASE=CH353 PCI Quad Serial Port Controller + +pci:v00004348d00005053* + ID_MODEL_FROM_DATABASE=CH352 PCI Serial and Parallel Port Controller + +pci:v00004348d00007053* + ID_MODEL_FROM_DATABASE=CH353 PCI Dual Serial and Parallel Ports Controller + +pci:v00004348d00007073* + ID_MODEL_FROM_DATABASE=CH356 PCI Quad Serial and Parallel Ports Controller + +pci:v00004348d00007173* + ID_MODEL_FROM_DATABASE=CH355 PCI Quad Serial Port Controller + +pci:v0000434E* + ID_VENDOR_FROM_DATABASE=CAST Navigation LLC + +pci:v00004444* + ID_VENDOR_FROM_DATABASE=Internext Compression Inc + +pci:v00004444d00000016* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder + +pci:v00004444d00000016sv00000070sd00000003* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 250) + +pci:v00004444d00000016sv00000070sd00000009* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) + +pci:v00004444d00000016sv00000070sd00000801* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) + +pci:v00004444d00000016sv00000070sd00000807* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) + +pci:v00004444d00000016sv00000070sd00004001* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 250) + +pci:v00004444d00000016sv00000070sd00004009* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 250) + +pci:v00004444d00000016sv00000070sd00004801* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 250) + +pci:v00004444d00000016sv00000070sd00004803* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 250) + +pci:v00004444d00000016sv00000070sd00008003* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) + +pci:v00004444d00000016sv00000070sd00008801* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) + +pci:v00004444d00000016sv00000070sd0000C801* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) + +pci:v00004444d00000016sv00000070sd0000E807* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 500 (1st unit)) + +pci:v00004444d00000016sv00000070sd0000E817* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 500 (2nd unit)) + +pci:v00004444d00000016sv00000070sd0000FF92* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WiNTV PVR-550) + +pci:v00004444d00000016sv00000270sd00000801* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (WinTV PVR 150) + +pci:v00004444d00000016sv0000104Dsd0000013D* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (ENX-26 TV Encoder) + +pci:v00004444d00000016sv000010FCsd0000D038* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (GV-MVP/RX2W (1st unit)) + +pci:v00004444d00000016sv000010FCsd0000D039* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (GV-MVP/RX2W (2nd unit)) + +pci:v00004444d00000016sv000012ABsd0000FFF3* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (MPG600) + +pci:v00004444d00000016sv000012ABsd0000FFFF* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (MPG600) + +pci:v00004444d00000016sv00001461sd0000C00A* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM, Philips FQ1216MK3 tuner)) + +pci:v00004444d00000016sv00001461sd0000C00B* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM+FM, Philips FM1216MK3 tuner)) + +pci:v00004444d00000016sv00001461sd0000C00C* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC, JAPAN version, Philips FI1286MK2 tuner)) + +pci:v00004444d00000016sv00001461sd0000C010* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC, Philips FI1236MK3 tuner)) + +pci:v00004444d00000016sv00001461sd0000C011* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC+FM, Philips FM1236MK3 tuner)) + +pci:v00004444d00000016sv00001461sd0000C018* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC, Philips FQ1236MK5 tuner)) + +pci:v00004444d00000016sv00001461sd0000C019* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (UltraTV 1500 MCE, a.k.a. M113 PCI Analog TV (NTSC+FM, Philips FQ1236MK5 tuner)) + +pci:v00004444d00000016sv00001461sd0000C01A* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM, Philips FQ1216MK5 tuner)) + +pci:v00004444d00000016sv00001461sd0000C01B* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM+FM, Philips FM1216MK5 tuner)) + +pci:v00004444d00000016sv00001461sd0000C030* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC-J, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C031* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC-J+FM, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C032* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C033* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (PAL/SECAM+FM, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C034* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C035* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M113 PCI Analog TV (NTSC+FM, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C03F* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (C115 PCI video capture card (no tuner)) + +pci:v00004444d00000016sv00001461sd0000C136* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M104 mini-PCI Analog TV) + +pci:v00004444d00000016sv00001461sd0000C20A* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (PAL/SECAM, Philips FQ1216MK3 tuner)) + +pci:v00004444d00000016sv00001461sd0000C218* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC, Philips FQ1236MK5 tuner)) + +pci:v00004444d00000016sv00001461sd0000C219* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC+FM, Philips FQ1236MK5 tuner)) + +pci:v00004444d00000016sv00001461sd0000C21A* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (PAL/SECAM, Philips FQ1216MK5 tuner)) + +pci:v00004444d00000016sv00001461sd0000C21B* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (PAL/SECAM+FM, Philips FM1216MK5 tuner)) + +pci:v00004444d00000016sv00001461sd0000C230* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC-J, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C231* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC-J+FM, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C232* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (PAL/SECAM, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C233* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (PAL/SECAM+FM, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C234* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C235* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M755 AVerTV Video Capture (NTSC+FM, Partsnic tuner)) + +pci:v00004444d00000016sv00001461sd0000C337* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (E106 AVerMedia AVerTV Video Capture) + +pci:v00004444d00000016sv00001461sd0000C439* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M116 AVerMedia AVerTV MCE 116 Plus (NTSC/PAL/SECAM+FM+REMOTE, Xceive 2028 tuner)) + +pci:v00004444d00000016sv00001461sd0000C5FF* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (C755 AVerTV Video Capture card (no tuner)) + +pci:v00004444d00000016sv00001461sd0000C6FF* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (C115 PCI video capture card (no tuner)) + +pci:v00004444d00000016sv00001461sd0000C739* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (M785 AVerMedia PCI Analog TV (NTSC/PAL/SECAM+FM, Xceive 2028 tuner)) + +pci:v00004444d00000016sv00009005sd00000092* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (VideOh! AVC-2010) + +pci:v00004444d00000016sv00009005sd00000093* + ID_MODEL_FROM_DATABASE=iTVC16 (CX23416) Video Decoder (VideOh! AVC-2410) + +pci:v00004444d00000803* + ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder + +pci:v00004444d00000803sv00000070sd00004000* + ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (WinTV PVR-350) + +pci:v00004444d00000803sv00000070sd00004001* + ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (WinTV PVR-250) + +pci:v00004444d00000803sv00000070sd00004800* + ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (WinTV PVR-350 (V1)) + +pci:v00004444d00000803sv000012ABsd00000000* + ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (MPG160) + +pci:v00004444d00000803sv00001461sd0000A3CE* + ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (M179) + +pci:v00004444d00000803sv00001461sd0000A3CF* + ID_MODEL_FROM_DATABASE=iTVC15 (CX23415) Video Decoder (M179) + +pci:v00004468* + ID_VENDOR_FROM_DATABASE=Bridgeport machines + +pci:v00004594* + ID_VENDOR_FROM_DATABASE=Cogetec Informatique Inc + +pci:v000045FB* + ID_VENDOR_FROM_DATABASE=Baldor Electric Company + +pci:v00004624* + ID_VENDOR_FROM_DATABASE=Budker Institute of Nuclear Physics + +pci:v00004624d0000ADC1* + ID_MODEL_FROM_DATABASE=ADC200ME High speed ADC + +pci:v00004624d0000DE01* + ID_MODEL_FROM_DATABASE=DL200ME High resolution delay line PCI based card + +pci:v00004624d0000DE02* + ID_MODEL_FROM_DATABASE=DL200ME Middle resolution delay line PCI based card + +pci:v00004651* + ID_VENDOR_FROM_DATABASE=TXIC + +pci:v00004680* + ID_VENDOR_FROM_DATABASE=Umax Computer Corp + +pci:v00004843* + ID_VENDOR_FROM_DATABASE=Hercules Computer Technology Inc + +pci:v00004916* + ID_VENDOR_FROM_DATABASE=RedCreek Communications Inc + +pci:v00004916d00001960* + ID_MODEL_FROM_DATABASE=RedCreek PCI adapter + +pci:v00004943* + ID_VENDOR_FROM_DATABASE=Growth Networks + +pci:v0000494F* + ID_VENDOR_FROM_DATABASE=ACCES I/O Products, Inc. + +pci:v0000494Fd00000508* + ID_MODEL_FROM_DATABASE=PCI-IDO-16A FET Output Card + +pci:v0000494Fd00000518* + ID_MODEL_FROM_DATABASE=PCI-IDO-32A FET Output Card + +pci:v0000494Fd00000520* + ID_MODEL_FROM_DATABASE=PCI-IDO-48 FET Output Card + +pci:v0000494Fd00000521* + ID_MODEL_FROM_DATABASE=PCI-IDO-48A FET Output Card + +pci:v0000494Fd00000703* + ID_MODEL_FROM_DATABASE=PCIe-RO-4 Electromechanical Relay Output Card + +pci:v0000494Fd000007D0* + ID_MODEL_FROM_DATABASE=PCIe-IDO-24 FET Output Card + +pci:v0000494Fd00000920* + ID_MODEL_FROM_DATABASE=PCI-IDI-48 Isolated Digital Input Card + +pci:v0000494Fd00000BD0* + ID_MODEL_FROM_DATABASE=PCIe-IDI-24 Isolated Digital Input Card + +pci:v0000494Fd00000C50* + ID_MODEL_FROM_DATABASE=PCI-DIO-24H 1x 8255 Digital Input / Output Card + +pci:v0000494Fd00000C51* + ID_MODEL_FROM_DATABASE=PCI-DIO-24D 1x 8255 Digital Input / Output Card + +pci:v0000494Fd00000C52* + ID_MODEL_FROM_DATABASE=PCIe-DIO-24 1x 8255 Digital Input / Output Card + +pci:v0000494Fd00000C53* + ID_MODEL_FROM_DATABASE=PCIe-DIO-24H 8255 Digital Input / Output Card + +pci:v0000494Fd00000C57* + ID_MODEL_FROM_DATABASE=mPCIe-DIO-24 8255 Digital Input / Output Card + +pci:v0000494Fd00000C60* + ID_MODEL_FROM_DATABASE=PCI-DIO-48H 8255 Digital Input / Output Card + +pci:v0000494Fd00000C61* + ID_MODEL_FROM_DATABASE=PCIe-DIO-48 8255 Digital Input / Output Card + +pci:v0000494Fd00000C62* + ID_MODEL_FROM_DATABASE=P104-DIO-48 8255 Digital Input / Output Card + +pci:v0000494Fd00000C68* + ID_MODEL_FROM_DATABASE=PCI-DIO-72 8255 Digital Input / Output Card + +pci:v0000494Fd00000C69* + ID_MODEL_FROM_DATABASE=P104-DIO-96 8255 Digital Input / Output Card + +pci:v0000494Fd00000C70* + ID_MODEL_FROM_DATABASE=PCI-DIO-96 8255 Digital Input / Output Card + +pci:v0000494Fd00000C78* + ID_MODEL_FROM_DATABASE=PCI-DIO-120 8255 Digital Input / Output Card + +pci:v0000494Fd00000DC8* + ID_MODEL_FROM_DATABASE=PCI-IDIO-16 Isolated Digital Input / FET Output Card + +pci:v0000494Fd00000E50* + ID_MODEL_FROM_DATABASE=PCI-DIO-24S 8255 Digital Input / Output Card + +pci:v0000494Fd00000E51* + ID_MODEL_FROM_DATABASE=PCI-DIO-24H(C) 8255 Digital Input / Output Card + +pci:v0000494Fd00000E52* + ID_MODEL_FROM_DATABASE=PCI-DIO-24D(C) 8255 Digital Input / Output Card + +pci:v0000494Fd00000E53* + ID_MODEL_FROM_DATABASE=PCIe-DIO-24S 8255 Digital Input / Output Card + +pci:v0000494Fd00000E54* + ID_MODEL_FROM_DATABASE=PCIe-DIO-24HS 8255 Digital Input / Output Card + +pci:v0000494Fd00000E55* + ID_MODEL_FROM_DATABASE=PCIe-DIO-24DC 8255 Digital Input / Output Card + +pci:v0000494Fd00000E56* + ID_MODEL_FROM_DATABASE=PCIe-DIO-24DCS 8255 Digital Input / Output Card + +pci:v0000494Fd00000E57* + ID_MODEL_FROM_DATABASE=mPCIe-DIO-24S 8255 Digital Input / Output Card + +pci:v0000494Fd00000E60* + ID_MODEL_FROM_DATABASE=PCI-DIO-48S 2x 8255 Digital Input / Output Card + +pci:v0000494Fd00000E61* + ID_MODEL_FROM_DATABASE=PCIe-DIO-48S 2x 8255 Digital Input / Output Card + +pci:v0000494Fd00000E62* + ID_MODEL_FROM_DATABASE=P104-DIO-48S 2x 8255 Digital Input / Output Card + +pci:v0000494Fd00000F00* + ID_MODEL_FROM_DATABASE=PCI-IIRO-8 Isolated Digital / Relay Output Card + +pci:v0000494Fd00000F01* + ID_MODEL_FROM_DATABASE=LPCI-IIRO-8 Isolated Digital / Relay Output Card + +pci:v0000494Fd00000F02* + ID_MODEL_FROM_DATABASE=PCIe-IIRO-8 Isolated Digital / Relay Output Card + +pci:v0000494Fd00000F08* + ID_MODEL_FROM_DATABASE=PCI-IIRO-16 Isolated Digital / Relay Output Card + +pci:v0000494Fd00000F09* + ID_MODEL_FROM_DATABASE=PCIe-IIRO-16 Isolated Digital / Relay Output Card + +pci:v0000494Fd00000FC0* + ID_MODEL_FROM_DATABASE=PCIe-IDIO-12 Isolated Digital Input / FET Output Card + +pci:v0000494Fd00000FC1* + ID_MODEL_FROM_DATABASE=PCIe-IDI-12 Isolated Digital Input Card + +pci:v0000494Fd00000FC2* + ID_MODEL_FROM_DATABASE=PCIe-IDO-12 FET Output Card + +pci:v0000494Fd00000FD0* + ID_MODEL_FROM_DATABASE=PCIe-IDIO-24 Isolated Digital Input / FET Output Card + +pci:v0000494Fd00001050* + ID_MODEL_FROM_DATABASE=PCI-422/485-2 2x RS422/RS484 Card + +pci:v0000494Fd00001051* + ID_MODEL_FROM_DATABASE=PCIe-COM-2SRJ 2x RS422/RS484 Card w/RJ45 Connectors + +pci:v0000494Fd00001052* + ID_MODEL_FROM_DATABASE=104I-COM-2S 2x RS422/RS484 PCI/104 Board + +pci:v0000494Fd00001053* + ID_MODEL_FROM_DATABASE=mPCIe-COM-2S 2x RS422/RS484 PCI Express Mini Card + +pci:v0000494Fd00001058* + ID_MODEL_FROM_DATABASE=PCI-COM422/4 4x RS422 Card + +pci:v0000494Fd00001059* + ID_MODEL_FROM_DATABASE=PCI-COM485/4 4x RS485 Card + +pci:v0000494Fd0000105A* + ID_MODEL_FROM_DATABASE=PCIe-COM422-4 4x RS422 Card + +pci:v0000494Fd0000105B* + ID_MODEL_FROM_DATABASE=PCIe-COM485-4 4x RS485 Card + +pci:v0000494Fd0000105C* + ID_MODEL_FROM_DATABASE=PCIe-COM-4SRJ 4x RS422/RS485 Card w/RJ45 Connectors + +pci:v0000494Fd0000105D* + ID_MODEL_FROM_DATABASE=104I-COM-4S 4x RS422/RS484 PCI/104 Board + +pci:v0000494Fd0000105E* + ID_MODEL_FROM_DATABASE=mPCIe-COM-4S 4x RS422/RS484 PCI Express Mini Card + +pci:v0000494Fd00001068* + ID_MODEL_FROM_DATABASE=PCI-COM422/8 8x RS422 Card + +pci:v0000494Fd00001069* + ID_MODEL_FROM_DATABASE=PCI-COM485/8 8x RS485 Card + +pci:v0000494Fd0000106A* + ID_MODEL_FROM_DATABASE=PCIe-COM422-8 8x RS422 Card + +pci:v0000494Fd0000106B* + ID_MODEL_FROM_DATABASE=PCIe-COM485-8 8x RS485 Card + +pci:v0000494Fd0000106C* + ID_MODEL_FROM_DATABASE=104I-COM-8S 8x RS422/RS485 PCI/104 Board + +pci:v0000494Fd00001088* + ID_MODEL_FROM_DATABASE=PCI-COM232/1 1x RS232 Card + +pci:v0000494Fd00001090* + ID_MODEL_FROM_DATABASE=PCI-COM232/2 2x RS232 Card + +pci:v0000494Fd00001091* + ID_MODEL_FROM_DATABASE=PCIe-COM232-2RJ 2x RS232 Card w/RJ45 Connectors + +pci:v0000494Fd00001093* + ID_MODEL_FROM_DATABASE=mPCIe-COM232-2 2x RS232 PCI Express Mini Card + +pci:v0000494Fd00001098* + ID_MODEL_FROM_DATABASE=PCIe-COM232-4 4x RS232 Card + +pci:v0000494Fd00001099* + ID_MODEL_FROM_DATABASE=PCIe-COM232-4RJ 4x RS232 Card w/RJ45 Connectors + +pci:v0000494Fd0000109B* + ID_MODEL_FROM_DATABASE=mPCIe-COM232-4 4x RS232 PCI Express Mini Card + +pci:v0000494Fd000010A8* + ID_MODEL_FROM_DATABASE=P104-COM232-8 8x RS232 PC-104+ Board + +pci:v0000494Fd000010A9* + ID_MODEL_FROM_DATABASE=PCIe-COM232-8 8x RS232 Card + +pci:v0000494Fd000010C9* + ID_MODEL_FROM_DATABASE=PCI-COM-1S 1x RS422/RS485 Card + +pci:v0000494Fd000010D0* + ID_MODEL_FROM_DATABASE=PCI-COM2S 2x RS422/RS485 Card + +pci:v0000494Fd000010D1* + ID_MODEL_FROM_DATABASE=PCIe-COM-2SMRJ 2x RS232/RS422/RS485 Card w/RJ45 Connectors + +pci:v0000494Fd000010D2* + ID_MODEL_FROM_DATABASE=104I-COM-2SM 2x RS232/RS422/RS485 PCI/104 Board + +pci:v0000494Fd000010D3* + ID_MODEL_FROM_DATABASE=mPCIe-COM-2SM 2x RS232/RS422/RS485 PCI Express Mini Card + +pci:v0000494Fd000010D8* + ID_MODEL_FROM_DATABASE=PCI-COM-4SM 4x RS232/RS422/RS485 Card + +pci:v0000494Fd000010D9* + ID_MODEL_FROM_DATABASE=PCIe-COM-4SM 4x RS232/RS422/RS485 Card + +pci:v0000494Fd000010DA* + ID_MODEL_FROM_DATABASE=PCIe-COM-4SMRJ 4x RS232/RS422/RS485 Card w/RJ45 Connectors + +pci:v0000494Fd000010DB* + ID_MODEL_FROM_DATABASE=104I-COM-4SM 4x RS232/RS422/RS485 PCI/104 Board + +pci:v0000494Fd000010DC* + ID_MODEL_FROM_DATABASE=mPCIe-COM-4SM 4x RS232/RS422/RS485 PCI Express Mini Card + +pci:v0000494Fd000010E8* + ID_MODEL_FROM_DATABASE=PCI-COM-8SM 8x RS232/RS422/RS485 Card + +pci:v0000494Fd000010E9* + ID_MODEL_FROM_DATABASE=PCIe-COM-8SM 8x RS232/RS422/RS485 Card + +pci:v0000494Fd000010EA* + ID_MODEL_FROM_DATABASE=104I-COM-8SM 8x RS232/RS422/RS485 PCI-104 Board + +pci:v0000494Fd00001108* + ID_MODEL_FROM_DATABASE=mPCIe-ICM485-1 1x Isolated RS485 PCI Express Mini Card + +pci:v0000494Fd00001110* + ID_MODEL_FROM_DATABASE=mPCIe-ICM422-2 2x Isolated RS422 PCI Express Mini Card + +pci:v0000494Fd00001111* + ID_MODEL_FROM_DATABASE=mPCIe-ICM485-2 2x Isolated RS485 PCI Express Mini Card + +pci:v0000494Fd00001118* + ID_MODEL_FROM_DATABASE=mPCIe-ICM422-4 4x Isolated RS422 PCI Express Mini Card + +pci:v0000494Fd00001119* + ID_MODEL_FROM_DATABASE=mPCIe-ICM485-4 4x Isolated RS485 PCI Express Mini Card + +pci:v0000494Fd00001148* + ID_MODEL_FROM_DATABASE=PCI-ICM-1S 1x Isolated RS422/RS485 Card + +pci:v0000494Fd00001150* + ID_MODEL_FROM_DATABASE=PCI-ICM-2S 2x Isolated RS422/RS485 Card + +pci:v0000494Fd00001152* + ID_MODEL_FROM_DATABASE=PCIe-ICM-2S 2x Isolated RS422/RS485 Card + +pci:v0000494Fd00001158* + ID_MODEL_FROM_DATABASE=PCI-ICM422/4 4x Isolated RS422 Card + +pci:v0000494Fd00001159* + ID_MODEL_FROM_DATABASE=PCI-ICM485/4 4x Isolated RS485 Card + +pci:v0000494Fd0000115A* + ID_MODEL_FROM_DATABASE=PCIe-ICM-4S 4x Isolated RS422/RS485 Card + +pci:v0000494Fd00001190* + ID_MODEL_FROM_DATABASE=PCIe-ICM232-2 2x Isolated RS232 Card + +pci:v0000494Fd00001191* + ID_MODEL_FROM_DATABASE=mPCIe-ICM232-2 2x Isolated RS232 PCI Express Mini Card + +pci:v0000494Fd00001198* + ID_MODEL_FROM_DATABASE=PCIe-ICM232-4 4x Isolated RS232 Card + +pci:v0000494Fd00001199* + ID_MODEL_FROM_DATABASE=mPCIe-ICM232-4 4x Isolated RS422 PCI Express Mini Card + +pci:v0000494Fd000011D0* + ID_MODEL_FROM_DATABASE=PCIe-ICM-2SM 2x Isolated RS232/RS422/RS485 Card + +pci:v0000494Fd000011D8* + ID_MODEL_FROM_DATABASE=PCIe-ICM-4SM 4x Isolated RS232/RS422/RS485 Card + +pci:v0000494Fd00001250* + ID_MODEL_FROM_DATABASE=PCI-WDG-2S Watchdog and 2x Serial Card + +pci:v0000494Fd000012D0* + ID_MODEL_FROM_DATABASE=PCI-WDG-IMPAC + +pci:v0000494Fd00002230* + ID_MODEL_FROM_DATABASE=PCI-QUAD-8 8x Quadrature Input Card + +pci:v0000494Fd00002231* + ID_MODEL_FROM_DATABASE=PCI-QUAD-4 4x Quadrature Input Card + +pci:v0000494Fd000022C0* + ID_MODEL_FROM_DATABASE=PCI-WDG-CSM Watchdog Card + +pci:v0000494Fd000025C0* + ID_MODEL_FROM_DATABASE=P104-WDG-E Watchdog PC/104+ Board + +pci:v0000494Fd00002C50* + ID_MODEL_FROM_DATABASE=PCI-DIO-96CT 96x Digital Input / Output Card + +pci:v0000494Fd00002C58* + ID_MODEL_FROM_DATABASE=PCI-DIO-96C3 96x Digital Input / Output Card w/3x 8254 Counter Card + +pci:v0000494Fd00002EE0* + ID_MODEL_FROM_DATABASE=PCIe-DIO24S-CTR12 24x Digital Input / Output Card w/4x 8254 Counter Card + +pci:v0000494Fd00002FC0* + ID_MODEL_FROM_DATABASE=P104-WDG-CSM Watchdog PC/104+ Board + +pci:v0000494Fd00002FC1* + ID_MODEL_FROM_DATABASE=P104-WDG-CSMA Advanced Watchdog PC/104+ Board + +pci:v0000494Fd00005ED0* + ID_MODEL_FROM_DATABASE=PCI-DAC + +pci:v0000494Fd00006C90* + ID_MODEL_FROM_DATABASE=PCI-DA12-2 2x 12-bit Analog Output Card + +pci:v0000494Fd00006C98* + ID_MODEL_FROM_DATABASE=PCI-DA12-4 4x 12-bit Analog Output Card + +pci:v0000494Fd00006CA0* + ID_MODEL_FROM_DATABASE=PCI-DA12-6 6x 12-bit Analog Output Card + +pci:v0000494Fd00006CA8* + ID_MODEL_FROM_DATABASE=PCI-DA12-8 8x 12-bit Analog Output Card + +pci:v0000494Fd00006CA9* + ID_MODEL_FROM_DATABASE=PCI-DA12-8V + +pci:v0000494Fd00006CB0* + ID_MODEL_FROM_DATABASE=PCI-DA12-16 16x 12-bit Analog Output Card + +pci:v0000494Fd00006CB1* + ID_MODEL_FROM_DATABASE=PCI-DA12-16V + +pci:v0000494Fd00008EF0* + ID_MODEL_FROM_DATABASE=P104-FAS16-16 + +pci:v0000494Fd0000ACA8* + ID_MODEL_FROM_DATABASE=PCI-AI12-16 12-bit 100kHz Analog Input Card + +pci:v0000494Fd0000ACA9* + ID_MODEL_FROM_DATABASE=PCI-AI12-16A 12-bit 100kHz Analog Input w/FIFO Card + +pci:v0000494Fd0000ECA8* + ID_MODEL_FROM_DATABASE=PCI-AIO12-16 12-bit 100kHz Analog Input w/2x Analog Output and FIFO Card + +pci:v0000494Fd0000ECAA* + ID_MODEL_FROM_DATABASE=PCI-A12-16A 12-bit 100kHz Analog Input w/2x Analog Output and FIFO Card + +pci:v0000494Fd0000ECE8* + ID_MODEL_FROM_DATABASE=LPCI-A16-16A 16-bit 500kHz Analog Input low-profile Card + +pci:v0000494Fd0000ECE9* + ID_MODEL_FROM_DATABASE=LPCI-AIO16A 16-bit 500kHz Analog Input low-profile Card + +pci:v00004978* + ID_VENDOR_FROM_DATABASE=Axil Computer Inc + +pci:v00004A14* + ID_VENDOR_FROM_DATABASE=NetVin + +pci:v00004A14d00005000* + ID_MODEL_FROM_DATABASE=NV5000SC + +pci:v00004A14d00005000sv00004A14sd00005000* + ID_MODEL_FROM_DATABASE=NV5000SC (RT8029-Based Ethernet Adapter) + +pci:v00004B10* + ID_VENDOR_FROM_DATABASE=Buslogic Inc. + +pci:v00004C48* + ID_VENDOR_FROM_DATABASE=LUNG HWA Electronics + +pci:v00004C52* + ID_VENDOR_FROM_DATABASE=LR-Link + +pci:v00004C53* + ID_VENDOR_FROM_DATABASE=SBS Technologies + +pci:v00004C53d00000000* + ID_MODEL_FROM_DATABASE=PLUSTEST device + +pci:v00004C53d00000000sv00004C53sd00003000* + ID_MODEL_FROM_DATABASE=PLUSTEST device (PLUSTEST card (PC104+)) + +pci:v00004C53d00000000sv00004C53sd00003001* + ID_MODEL_FROM_DATABASE=PLUSTEST device (PLUSTEST card (PMC)) + +pci:v00004C53d00000001* + ID_MODEL_FROM_DATABASE=PLUSTEST-MM device + +pci:v00004C53d00000001sv00004C53sd00003002* + ID_MODEL_FROM_DATABASE=PLUSTEST-MM device (PLUSTEST-MM card (PMC)) + +pci:v00004CA1* + ID_VENDOR_FROM_DATABASE=Seanix Technology Inc + +pci:v00004D51* + ID_VENDOR_FROM_DATABASE=MediaQ Inc. + +pci:v00004D51d00000200* + ID_MODEL_FROM_DATABASE=MQ-200 + +pci:v00004D54* + ID_VENDOR_FROM_DATABASE=Microtechnica Co Ltd + +pci:v00004D56* + ID_VENDOR_FROM_DATABASE=MATRIX VISION GmbH + +pci:v00004D56d00000000* + ID_MODEL_FROM_DATABASE=[mvHYPERION-CLe/CLb] CameraLink PCI Express x1 Frame Grabber + +pci:v00004D56d00000001* + ID_MODEL_FROM_DATABASE=[mvHYPERION-CLf/CLm] CameraLink PCI Express x4 Frame Grabber + +pci:v00004D56d00000010* + ID_MODEL_FROM_DATABASE=[mvHYPERION-16R16/-32R16] 16 Video Channel PCI Express x4 Frame Grabber + +pci:v00004D56d00000020* + ID_MODEL_FROM_DATABASE=[mvHYPERION-HD-SDI] HD-SDI PCI Express x4 Frame Grabber + +pci:v00004D56d00000030* + ID_MODEL_FROM_DATABASE=[mvHYPERION-HD-SDI-Merger] HD-SDI PCI Express x4 Frame Grabber + +pci:v00004DDC* + ID_VENDOR_FROM_DATABASE=ILC Data Device Corp + +pci:v00004DDCd00000100* + ID_MODEL_FROM_DATABASE=DD-42924I5-300 (ARINC 429 Data Bus) + +pci:v00004DDCd00000300* + ID_MODEL_FROM_DATABASE=SB-3620 Motion Feedback Device + +pci:v00004DDCd00000340* + ID_MODEL_FROM_DATABASE=SB-3623 Motion Feedback Device + +pci:v00004DDCd00000400* + ID_MODEL_FROM_DATABASE=SB-3622 Motion Feedback Device + +pci:v00004DDCd00000500* + ID_MODEL_FROM_DATABASE=SB-3621 Motion Feedback Device + +pci:v00004DDCd00000510* + ID_MODEL_FROM_DATABASE=SB-3624 Motion Feedback Device + +pci:v00004DDCd00000801* + ID_MODEL_FROM_DATABASE=BU-65570I1 MIL-STD-1553 Test and Simulation + +pci:v00004DDCd00000802* + ID_MODEL_FROM_DATABASE=BU-65570I2 MIL-STD-1553 Test and Simulation + +pci:v00004DDCd00000811* + ID_MODEL_FROM_DATABASE=BU-65572I1 MIL-STD-1553 Test and Simulation + +pci:v00004DDCd00000812* + ID_MODEL_FROM_DATABASE=BU-65572I2 MIL-STD-1553 Test and Simulation + +pci:v00004DDCd00000881* + ID_MODEL_FROM_DATABASE=BU-65570T1 MIL-STD-1553 Test and Simulation + +pci:v00004DDCd00000882* + ID_MODEL_FROM_DATABASE=BU-65570T2 MIL-STD-1553 Test and Simulation + +pci:v00004DDCd00000891* + ID_MODEL_FROM_DATABASE=BU-65572T1 MIL-STD-1553 Test and Simulation + +pci:v00004DDCd00000892* + ID_MODEL_FROM_DATABASE=BU-65572T2 MIL-STD-1553 Test and Simulation + +pci:v00004DDCd00000901* + ID_MODEL_FROM_DATABASE=BU-65565C1 MIL-STD-1553 Data Bus + +pci:v00004DDCd00000902* + ID_MODEL_FROM_DATABASE=BU-65565C2 MIL-STD-1553 Data Bus + +pci:v00004DDCd00000903* + ID_MODEL_FROM_DATABASE=BU-65565C3 MIL-STD-1553 Data Bus + +pci:v00004DDCd00000904* + ID_MODEL_FROM_DATABASE=BU-65565C4 MIL-STD-1553 Data Bus + +pci:v00004DDCd00000B01* + ID_MODEL_FROM_DATABASE=BU-65569I1 MIL-STD-1553 Data Bus + +pci:v00004DDCd00000B02* + ID_MODEL_FROM_DATABASE=BU-65569I2 MIL-STD-1553 Data Bus + +pci:v00004DDCd00000B03* + ID_MODEL_FROM_DATABASE=BU-65569I3 MIL-STD-1553 Data Bus + +pci:v00004DDCd00000B04* + ID_MODEL_FROM_DATABASE=BU-65569I4 MIL-STD-1553 Data Bus + +pci:v00004DDCd00000D01* + ID_MODEL_FROM_DATABASE=SB-3641 Motion Feedback Device + +pci:v00004DDCd00000D10* + ID_MODEL_FROM_DATABASE=SB-365x Motion Feedback Device + +pci:v00004DDCd00002F00* + ID_MODEL_FROM_DATABASE=SB-3642 Motion Feedback Device + +pci:v00004DDCd00003000* + ID_MODEL_FROM_DATABASE=SB-3644 Motion Feedback Device + +pci:v00005045* + ID_VENDOR_FROM_DATABASE=University of Toronto + +pci:v00005045d00004243* + ID_MODEL_FROM_DATABASE=BLASTbus PCI Interface Card v1 + +pci:v00005046* + ID_VENDOR_FROM_DATABASE=GemTek Technology Corporation + +pci:v00005046d00001001* + ID_MODEL_FROM_DATABASE=PCI Radio + +pci:v00005053* + ID_VENDOR_FROM_DATABASE=Voyetra Technologies + +pci:v00005053d00002010* + ID_MODEL_FROM_DATABASE=Daytona Audio Adapter + +pci:v000050B2* + ID_VENDOR_FROM_DATABASE=TerraTec Electronic GmbH + +pci:v00005136* + ID_VENDOR_FROM_DATABASE=S S Technologies + +pci:v00005143* + ID_VENDOR_FROM_DATABASE=Qualcomm Inc + +pci:v00005145* + ID_VENDOR_FROM_DATABASE=Ensoniq (Old) + +pci:v00005145d00003031* + ID_MODEL_FROM_DATABASE=Concert AudioPCI + +pci:v00005168* + ID_VENDOR_FROM_DATABASE=Animation Technologies Inc. + +pci:v00005168d00000300* + ID_MODEL_FROM_DATABASE=FlyDVB-S + +pci:v00005168d00000301* + ID_MODEL_FROM_DATABASE=FlyDVB-T + +pci:v00005301* + ID_VENDOR_FROM_DATABASE=Alliance Semiconductor Corp. + +pci:v00005301d00000001* + ID_MODEL_FROM_DATABASE=ProMotion aT3D + +pci:v00005333* + ID_VENDOR_FROM_DATABASE=S3 Graphics Ltd. + +pci:v00005333d00000551* + ID_MODEL_FROM_DATABASE=Plato/PX (system) + +pci:v00005333d00005631* + ID_MODEL_FROM_DATABASE=86c325 [ViRGE] + +pci:v00005333d00008800* + ID_MODEL_FROM_DATABASE=86c866 [Vision 866] + +pci:v00005333d00008801* + ID_MODEL_FROM_DATABASE=86c964 [Vision 964] + +pci:v00005333d00008810* + ID_MODEL_FROM_DATABASE=86c764_0 [Trio 32 vers 0] + +pci:v00005333d00008811* + ID_MODEL_FROM_DATABASE=86c764/765 [Trio32/64/64V+] + +pci:v00005333d00008812* + ID_MODEL_FROM_DATABASE=86cM65 [Aurora64V+] + +pci:v00005333d00008813* + ID_MODEL_FROM_DATABASE=86c764_3 [Trio 32/64 vers 3] + +pci:v00005333d00008814* + ID_MODEL_FROM_DATABASE=86c767 [Trio 64UV+] + +pci:v00005333d00008815* + ID_MODEL_FROM_DATABASE=86cM65 [Aurora 128] + +pci:v00005333d0000883D* + ID_MODEL_FROM_DATABASE=86c988 [ViRGE/VX] + +pci:v00005333d00008870* + ID_MODEL_FROM_DATABASE=FireGL + +pci:v00005333d00008880* + ID_MODEL_FROM_DATABASE=86c868 [Vision 868 VRAM] vers 0 + +pci:v00005333d00008881* + ID_MODEL_FROM_DATABASE=86c868 [Vision 868 VRAM] vers 1 + +pci:v00005333d00008882* + ID_MODEL_FROM_DATABASE=86c868 [Vision 868 VRAM] vers 2 + +pci:v00005333d00008883* + ID_MODEL_FROM_DATABASE=86c868 [Vision 868 VRAM] vers 3 + +pci:v00005333d000088B0* + ID_MODEL_FROM_DATABASE=86c928 [Vision 928 VRAM] vers 0 + +pci:v00005333d000088B1* + ID_MODEL_FROM_DATABASE=86c928 [Vision 928 VRAM] vers 1 + +pci:v00005333d000088B2* + ID_MODEL_FROM_DATABASE=86c928 [Vision 928 VRAM] vers 2 + +pci:v00005333d000088B3* + ID_MODEL_FROM_DATABASE=86c928 [Vision 928 VRAM] vers 3 + +pci:v00005333d000088C0* + ID_MODEL_FROM_DATABASE=86c864 [Vision 864 DRAM] vers 0 + +pci:v00005333d000088C1* + ID_MODEL_FROM_DATABASE=86c864 [Vision 864 DRAM] vers 1 + +pci:v00005333d000088C2* + ID_MODEL_FROM_DATABASE=86c864 [Vision 864-P DRAM] vers 2 + +pci:v00005333d000088C3* + ID_MODEL_FROM_DATABASE=86c864 [Vision 864-P DRAM] vers 3 + +pci:v00005333d000088D0* + ID_MODEL_FROM_DATABASE=86c964 [Vision 964 VRAM] vers 0 + +pci:v00005333d000088D1* + ID_MODEL_FROM_DATABASE=86c964 [Vision 964 VRAM] vers 1 + +pci:v00005333d000088D2* + ID_MODEL_FROM_DATABASE=86c964 [Vision 964-P VRAM] vers 2 + +pci:v00005333d000088D3* + ID_MODEL_FROM_DATABASE=86c964 [Vision 964-P VRAM] vers 3 + +pci:v00005333d000088F0* + ID_MODEL_FROM_DATABASE=86c968 [Vision 968 VRAM] rev 0 + +pci:v00005333d000088F1* + ID_MODEL_FROM_DATABASE=86c968 [Vision 968 VRAM] rev 1 + +pci:v00005333d000088F2* + ID_MODEL_FROM_DATABASE=86c968 [Vision 968 VRAM] rev 2 + +pci:v00005333d000088F3* + ID_MODEL_FROM_DATABASE=86c968 [Vision 968 VRAM] rev 3 + +pci:v00005333d00008900* + ID_MODEL_FROM_DATABASE=86c755 [Trio 64V2/DX] + +pci:v00005333d00008900sv00005333sd00008900* + ID_MODEL_FROM_DATABASE=86c755 [Trio 64V2/DX] (86C775 Trio64V2/DX) + +pci:v00005333d00008901* + ID_MODEL_FROM_DATABASE=86c775/86c785 [Trio 64V2/DX or /GX] + +pci:v00005333d00008901sv00005333sd00008901* + ID_MODEL_FROM_DATABASE=86c775/86c785 [Trio 64V2/DX or /GX] (86C775 Trio64V2/DX, 86C785 Trio64V2/GX) + +pci:v00005333d00008902* + ID_MODEL_FROM_DATABASE=Plato/PX + +pci:v00005333d00008903* + ID_MODEL_FROM_DATABASE=Trio 3D business multimedia + +pci:v00005333d00008904* + ID_MODEL_FROM_DATABASE=86c365, 86c366 [Trio 3D] + +pci:v00005333d00008904sv00001014sd000000DB* + ID_MODEL_FROM_DATABASE=86c365, 86c366 [Trio 3D] (Integrated Trio3D) + +pci:v00005333d00008904sv00004843sd0000314A* + ID_MODEL_FROM_DATABASE=86c365, 86c366 [Trio 3D] (Terminator 128/3D GLH) + +pci:v00005333d00008904sv00005333sd00008904* + ID_MODEL_FROM_DATABASE=86c365, 86c366 [Trio 3D] (86C365 Trio3D AGP) + +pci:v00005333d00008905* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d00008906* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d00008907* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d00008908* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d00008909* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d0000890A* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d0000890B* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d0000890C* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d0000890D* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d0000890E* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d0000890F* + ID_MODEL_FROM_DATABASE=Trio 64V+ family + +pci:v00005333d00008A01* + ID_MODEL_FROM_DATABASE=86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] + +pci:v00005333d00008A01sv00000E11sd0000B032* + ID_MODEL_FROM_DATABASE=86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] (ViRGE/GX) + +pci:v00005333d00008A01sv000010B4sd00001617* + ID_MODEL_FROM_DATABASE=86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] (Nitro 3D) + +pci:v00005333d00008A01sv000010B4sd00001717* + ID_MODEL_FROM_DATABASE=86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] (Nitro 3D) + +pci:v00005333d00008A01sv00005333sd00008A01* + ID_MODEL_FROM_DATABASE=86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] (ViRGE/DX) + +pci:v00005333d00008A10* + ID_MODEL_FROM_DATABASE=ViRGE/GX2 + +pci:v00005333d00008A10sv00001092sd00008A10* + ID_MODEL_FROM_DATABASE=ViRGE/GX2 (Stealth 3D 4000) + +pci:v00005333d00008A13* + ID_MODEL_FROM_DATABASE=86c360 [Trio 3D/1X], 86c362, 86c368 [Trio 3D/2X] + +pci:v00005333d00008A13sv00005333sd00008A13* + ID_MODEL_FROM_DATABASE=86c360 [Trio 3D/1X], 86c362, 86c368 [Trio 3D/2X] (Trio3D/2X) + +pci:v00005333d00008A20* + ID_MODEL_FROM_DATABASE=86c794 [Savage 3D] + +pci:v00005333d00008A20sv00005333sd00008A20* + ID_MODEL_FROM_DATABASE=86c794 [Savage 3D] (86C391 Savage3D) + +pci:v00005333d00008A21* + ID_MODEL_FROM_DATABASE=86c390 [Savage 3D/MV] + +pci:v00005333d00008A21sv00005333sd00008A21* + ID_MODEL_FROM_DATABASE=86c390 [Savage 3D/MV] (86C390 Savage3D/MV) + +pci:v00005333d00008A22* + ID_MODEL_FROM_DATABASE=Savage 4 + +pci:v00005333d00008A22sv00001033sd00008068* + ID_MODEL_FROM_DATABASE=Savage 4 + +pci:v00005333d00008A22sv00001033sd00008069* + ID_MODEL_FROM_DATABASE=Savage 4 + +pci:v00005333d00008A22sv00001033sd00008110* + ID_MODEL_FROM_DATABASE=Savage 4 (LT) + +pci:v00005333d00008A22sv0000105Dsd00000018* + ID_MODEL_FROM_DATABASE=Savage 4 (SR9 8Mb SDRAM) + +pci:v00005333d00008A22sv0000105Dsd0000002A* + ID_MODEL_FROM_DATABASE=Savage 4 (SR9 Pro 16Mb SDRAM) + +pci:v00005333d00008A22sv0000105Dsd0000003A* + ID_MODEL_FROM_DATABASE=Savage 4 (SR9 Pro 32Mb SDRAM) + +pci:v00005333d00008A22sv0000105Dsd0000092F* + ID_MODEL_FROM_DATABASE=Savage 4 (SR9 Pro+ 16Mb SGRAM) + +pci:v00005333d00008A22sv00001092sd00004207* + ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) + +pci:v00005333d00008A22sv00001092sd00004800* + ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) + +pci:v00005333d00008A22sv00001092sd00004807* + ID_MODEL_FROM_DATABASE=Savage 4 (SpeedStar A90) + +pci:v00005333d00008A22sv00001092sd00004808* + ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) + +pci:v00005333d00008A22sv00001092sd00004809* + ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) + +pci:v00005333d00008A22sv00001092sd0000480E* + ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) + +pci:v00005333d00008A22sv00001092sd00004904* + ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S520) + +pci:v00005333d00008A22sv00001092sd00004905* + ID_MODEL_FROM_DATABASE=Savage 4 (SpeedStar A200) + +pci:v00005333d00008A22sv00001092sd00004A09* + ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) + +pci:v00005333d00008A22sv00001092sd00004A0B* + ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540 Xtreme) + +pci:v00005333d00008A22sv00001092sd00004A0F* + ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) + +pci:v00005333d00008A22sv00001092sd00004E01* + ID_MODEL_FROM_DATABASE=Savage 4 (Stealth III S540) + +pci:v00005333d00008A22sv00001102sd0000101D* + ID_MODEL_FROM_DATABASE=Savage 4 (3d Blaster Savage 4) + +pci:v00005333d00008A22sv00001102sd0000101E* + ID_MODEL_FROM_DATABASE=Savage 4 (3d Blaster Savage 4) + +pci:v00005333d00008A22sv00005333sd00008100* + ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SDRAM 100) + +pci:v00005333d00008A22sv00005333sd00008110* + ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SDRAM 110) + +pci:v00005333d00008A22sv00005333sd00008125* + ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SDRAM 125) + +pci:v00005333d00008A22sv00005333sd00008143* + ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SDRAM 143) + +pci:v00005333d00008A22sv00005333sd00008A22* + ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4) + +pci:v00005333d00008A22sv00005333sd00008A2E* + ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 32bit) + +pci:v00005333d00008A22sv00005333sd00009125* + ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SGRAM 125) + +pci:v00005333d00008A22sv00005333sd00009143* + ID_MODEL_FROM_DATABASE=Savage 4 (86C394-397 Savage4 SGRAM 143) + +pci:v00005333d00008A23* + ID_MODEL_FROM_DATABASE=Savage 4 + +pci:v00005333d00008A25* + ID_MODEL_FROM_DATABASE=ProSavage PM133 + +pci:v00005333d00008A25sv00000303sd00000303* + ID_MODEL_FROM_DATABASE=ProSavage PM133 (D9840-60001 [Brio BA410 Motherboard]) + +pci:v00005333d00008A26* + ID_MODEL_FROM_DATABASE=ProSavage KM133 + +pci:v00005333d00008C00* + ID_MODEL_FROM_DATABASE=ViRGE/M3 + +pci:v00005333d00008C01* + ID_MODEL_FROM_DATABASE=ViRGE/MX + +pci:v00005333d00008C01sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=ViRGE/MX + +pci:v00005333d00008C02* + ID_MODEL_FROM_DATABASE=ViRGE/MX+ + +pci:v00005333d00008C03* + ID_MODEL_FROM_DATABASE=ViRGE/MX+MV + +pci:v00005333d00008C10* + ID_MODEL_FROM_DATABASE=86C270-294 [SavageMX-MV] + +pci:v00005333d00008C11* + ID_MODEL_FROM_DATABASE=82C270-294 [SavageMX] + +pci:v00005333d00008C12* + ID_MODEL_FROM_DATABASE=86C270-294 [SavageIX-MV] + +pci:v00005333d00008C12sv00001014sd0000017F* + ID_MODEL_FROM_DATABASE=86C270-294 [SavageIX-MV] (ThinkPad T20/T22) + +pci:v00005333d00008C12sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=86C270-294 [SavageIX-MV] (86C584 SuperSavage/IXC Toshiba) + +pci:v00005333d00008C13* + ID_MODEL_FROM_DATABASE=86C270-294 [SavageIX] + +pci:v00005333d00008C13sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=86C270-294 [SavageIX] (Magnia Z310) + +pci:v00005333d00008C22* + ID_MODEL_FROM_DATABASE=SuperSavage MX/128 + +pci:v00005333d00008C24* + ID_MODEL_FROM_DATABASE=SuperSavage MX/64 + +pci:v00005333d00008C26* + ID_MODEL_FROM_DATABASE=SuperSavage MX/64C + +pci:v00005333d00008C2A* + ID_MODEL_FROM_DATABASE=SuperSavage IX/128 SDR + +pci:v00005333d00008C2B* + ID_MODEL_FROM_DATABASE=SuperSavage IX/128 DDR + +pci:v00005333d00008C2C* + ID_MODEL_FROM_DATABASE=SuperSavage IX/64 SDR + +pci:v00005333d00008C2D* + ID_MODEL_FROM_DATABASE=SuperSavage IX/64 DDR + +pci:v00005333d00008C2E* + ID_MODEL_FROM_DATABASE=SuperSavage IX/C SDR + +pci:v00005333d00008C2Esv00001014sd000001FC* + ID_MODEL_FROM_DATABASE=SuperSavage IX/C SDR (ThinkPad T23) + +pci:v00005333d00008C2F* + ID_MODEL_FROM_DATABASE=SuperSavage IX/C DDR + +pci:v00005333d00008D01* + ID_MODEL_FROM_DATABASE=86C380 [ProSavageDDR K4M266] + +pci:v00005333d00008D02* + ID_MODEL_FROM_DATABASE=VT8636A [ProSavage KN133] AGP4X VGA Controller (TwisterK) + +pci:v00005333d00008D03* + ID_MODEL_FROM_DATABASE=VT8751 [ProSavageDDR P4M266] + +pci:v00005333d00008D04* + ID_MODEL_FROM_DATABASE=VT8375 [ProSavage8 KM266/KL266] + +pci:v00005333d00008E00* + ID_MODEL_FROM_DATABASE=DeltaChrome + +pci:v00005333d00008E26* + ID_MODEL_FROM_DATABASE=ProSavage + +pci:v00005333d00008E40* + ID_MODEL_FROM_DATABASE=2300E Graphics Processor + +pci:v00005333d00008E48* + ID_MODEL_FROM_DATABASE=Matrix [Chrome S25 / S27] + +pci:v00005333d00008E48sv00005333sd00000130* + ID_MODEL_FROM_DATABASE=Matrix [Chrome S25 / S27] (Chrome S27 256M DDR2) + +pci:v00005333d00009043* + ID_MODEL_FROM_DATABASE=Chrome 430 GT + +pci:v00005333d00009045* + ID_MODEL_FROM_DATABASE=Chrome 430 ULP / 435 ULP / 440 GTX + +pci:v00005333d00009060* + ID_MODEL_FROM_DATABASE=Chrome 530 GT + +pci:v00005333d00009102* + ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] + +pci:v00005333d00009102sv00001092sd00005932* + ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) + +pci:v00005333d00009102sv00001092sd00005934* + ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) + +pci:v00005333d00009102sv00001092sd00005952* + ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) + +pci:v00005333d00009102sv00001092sd00005954* + ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) + +pci:v00005333d00009102sv00001092sd00005A35* + ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) + +pci:v00005333d00009102sv00001092sd00005A37* + ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) + +pci:v00005333d00009102sv00001092sd00005A55* + ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) + +pci:v00005333d00009102sv00001092sd00005A57* + ID_MODEL_FROM_DATABASE=86C410 [Savage 2000] (Viper II Z200) + +pci:v00005333d0000CA00* + ID_MODEL_FROM_DATABASE=SonicVibes + +pci:v00005431* + ID_VENDOR_FROM_DATABASE=AuzenTech, Inc. + +pci:v0000544C* + ID_VENDOR_FROM_DATABASE=Teralogic Inc + +pci:v0000544Cd00000350* + ID_MODEL_FROM_DATABASE=TL880-based HDTV/ATSC tuner + +pci:v0000544D* + ID_VENDOR_FROM_DATABASE=TBS Technologies + +pci:v0000544Dd00006178* + ID_MODEL_FROM_DATABASE=DVB Tuner PCIe Card + +pci:v0000544Dd00006178sv0000544Dsd00006904* + ID_MODEL_FROM_DATABASE=DVB Tuner PCIe Card (TBS6904 DVB-S2 Quad Tuner PCIe Card) + +pci:v0000544Dd00006178sv0000544Dsd00006905* + ID_MODEL_FROM_DATABASE=DVB Tuner PCIe Card (TBS6905 DVB-S2 Quad Tuner PCIe Card) + +pci:v0000544Dd00006178sv00006205sd00000001* + ID_MODEL_FROM_DATABASE=DVB Tuner PCIe Card (TBS6205 DVB-T2/T/C Quad TV Tuner PCIe Card) + +pci:v0000544Dd00006178sv00006209sd00000001* + ID_MODEL_FROM_DATABASE=DVB Tuner PCIe Card (TBS6209 DVB-T2/C2/T/C/ISDB-T OctaTV Tuner) + +pci:v00005452* + ID_VENDOR_FROM_DATABASE=SCANLAB AG + +pci:v00005452d00003443* + ID_MODEL_FROM_DATABASE=RTC4 + +pci:v00005455* + ID_VENDOR_FROM_DATABASE=Technische Universitaet Berlin + +pci:v00005455d00004458* + ID_MODEL_FROM_DATABASE=S5933 + +pci:v00005456* + ID_VENDOR_FROM_DATABASE=GoTView + +pci:v00005519* + ID_VENDOR_FROM_DATABASE=Cnet Technologies, Inc. + +pci:v00005544* + ID_VENDOR_FROM_DATABASE=Dunord Technologies + +pci:v00005544d00000001* + ID_MODEL_FROM_DATABASE=I-30xx Scanner Interface + +pci:v00005555* + ID_VENDOR_FROM_DATABASE=Genroco, Inc + +pci:v00005555d00000003* + ID_MODEL_FROM_DATABASE=TURBOstor HFP-832 [HiPPI NIC] + +pci:v00005555d00003B00* + ID_MODEL_FROM_DATABASE=Epiphan DVI2PCIe video capture card + +pci:v00005646* + ID_VENDOR_FROM_DATABASE=Vector Fabrics BV + +pci:v00005654* + ID_VENDOR_FROM_DATABASE=VoiceTronix Pty Ltd + +pci:v00005678* + ID_VENDOR_FROM_DATABASE=Dawicontrol Computersysteme GmbH + +pci:v00005700* + ID_VENDOR_FROM_DATABASE=Netpower + +pci:v00005845* + ID_VENDOR_FROM_DATABASE=X-ES, Inc. + +pci:v0000584D* + ID_VENDOR_FROM_DATABASE=AuzenTech Co., Ltd. + +pci:v00005851* + ID_VENDOR_FROM_DATABASE=Exacq Technologies + +pci:v00005851d00008008* + ID_MODEL_FROM_DATABASE=tDVR8008 8-port video capture card + +pci:v00005851d00008016* + ID_MODEL_FROM_DATABASE=tDVR8016 16-chan video capture card + +pci:v00005851d00008032* + ID_MODEL_FROM_DATABASE=tDVR8032 32-chan video capture card + +pci:v00005853* + ID_VENDOR_FROM_DATABASE=XenSource, Inc. + +pci:v00005853d00000001* + ID_MODEL_FROM_DATABASE=Xen Platform Device + +pci:v00005853d0000C000* + ID_MODEL_FROM_DATABASE=Citrix XenServer PCI Device for Windows Update + +pci:v00005853d0000C110* + ID_MODEL_FROM_DATABASE=Virtualized HID + +pci:v00005853d0000C147* + ID_MODEL_FROM_DATABASE=Virtualized Graphics Device + +pci:v00005853d0000C200* + ID_MODEL_FROM_DATABASE=XCP-ng Project PCI Device for Windows Update + +pci:v00005854* + ID_VENDOR_FROM_DATABASE=GoTView + +pci:v00005ACE* + ID_VENDOR_FROM_DATABASE=Beholder International Ltd. + +pci:v00006205* + ID_VENDOR_FROM_DATABASE=TBS Technologies (wrong ID) + +pci:v00006209* + ID_VENDOR_FROM_DATABASE=TBS Technologies (wrong ID) + +pci:v0000631C* + ID_VENDOR_FROM_DATABASE=SmartInfra Ltd + +pci:v0000631Cd00001652* + ID_MODEL_FROM_DATABASE=PXI-1652 Signal Generator + +pci:v0000631Cd00002504* + ID_MODEL_FROM_DATABASE=PXI-2504 Signal Interrogator + +pci:v00006356* + ID_VENDOR_FROM_DATABASE=UltraStor + +pci:v00006374* + ID_VENDOR_FROM_DATABASE=c't Magazin fuer Computertechnik + +pci:v00006374d00006773* + ID_MODEL_FROM_DATABASE=GPPCI + +pci:v00006409* + ID_VENDOR_FROM_DATABASE=Logitec Corp. + +pci:v00006549* + ID_VENDOR_FROM_DATABASE=Teradici Corp. + +pci:v00006549d00001200* + ID_MODEL_FROM_DATABASE=TERA1200 PC-over-IP Host + +pci:v00006666* + ID_VENDOR_FROM_DATABASE=Decision Computer International Co. + +pci:v00006666d00000001* + ID_MODEL_FROM_DATABASE=PCCOM4 + +pci:v00006666d00000002* + ID_MODEL_FROM_DATABASE=PCCOM8 + +pci:v00006666d00000004* + ID_MODEL_FROM_DATABASE=PCCOM2 + +pci:v00006666d00000101* + ID_MODEL_FROM_DATABASE=PCI 8255/8254 I/O Card + +pci:v00006666d00000200* + ID_MODEL_FROM_DATABASE=12-bit AD/DA Card + +pci:v00006666d00000201* + ID_MODEL_FROM_DATABASE=14-bit AD/DA Card + +pci:v00006666d00001011* + ID_MODEL_FROM_DATABASE=Industrial Card + +pci:v00006666d00001021* + ID_MODEL_FROM_DATABASE=8 photo couple 8 relay Card + +pci:v00006666d00001022* + ID_MODEL_FROM_DATABASE=4 photo couple 4 relay Card + +pci:v00006666d00001025* + ID_MODEL_FROM_DATABASE=16 photo couple 16 relay Card + +pci:v00006666d00004000* + ID_MODEL_FROM_DATABASE=WatchDog Card + +pci:v00006688* + ID_VENDOR_FROM_DATABASE=Zycoo Co., Ltd + +pci:v00006688d00001200* + ID_MODEL_FROM_DATABASE=CooVox TDM Analog Module + +pci:v00006688d00001400* + ID_MODEL_FROM_DATABASE=CooVOX TDM GSM Module + +pci:v00006688d00001600* + ID_MODEL_FROM_DATABASE=CooVOX TDM E1/T1 Module + +pci:v00006688d00001800* + ID_MODEL_FROM_DATABASE=CooVOX TDM BRI Module + +pci:v00006900* + ID_VENDOR_FROM_DATABASE=Red Hat, Inc. + +pci:v00007063* + ID_VENDOR_FROM_DATABASE=pcHDTV + +pci:v00007063d00002000* + ID_MODEL_FROM_DATABASE=HD-2000 + +pci:v00007063d00003000* + ID_MODEL_FROM_DATABASE=HD-3000 + +pci:v00007063d00005500* + ID_MODEL_FROM_DATABASE=HD5500 HDTV + +pci:v00007284* + ID_VENDOR_FROM_DATABASE=HT OMEGA Inc. + +pci:v00007357* + ID_VENDOR_FROM_DATABASE=IOxOS Technologies SA + +pci:v00007357d00007910* + ID_MODEL_FROM_DATABASE=7910 [Althea] + +pci:v00007401* + ID_VENDOR_FROM_DATABASE=EndRun Technologies + +pci:v00007401d0000E100* + ID_MODEL_FROM_DATABASE=PTP3100 PCIe PTP Slave Clock + +pci:v00007470* + ID_VENDOR_FROM_DATABASE=TP-LINK Technologies Co., Ltd. + +pci:v00007604* + ID_VENDOR_FROM_DATABASE=O.N. Electronic Co Ltd. + +pci:v00007BDE* + ID_VENDOR_FROM_DATABASE=MIDAC Corporation + +pci:v00007FED* + ID_VENDOR_FROM_DATABASE=PowerTV + +pci:v00008008* + ID_VENDOR_FROM_DATABASE=Quancom Electronic GmbH + +pci:v00008008d00000010* + ID_MODEL_FROM_DATABASE=WDOG1 [PCI-Watchdog 1] + +pci:v00008008d00000011* + ID_MODEL_FROM_DATABASE=PWDOG2 [PCI-Watchdog 2] + +pci:v00008008d00000015* + ID_MODEL_FROM_DATABASE=Clock77/PCI & Clock77/PCIe (DCF-77 receiver) + +pci:v0000807D* + ID_VENDOR_FROM_DATABASE=Asustek Computer, Inc. + +pci:v00008086* + ID_VENDOR_FROM_DATABASE=Intel Corporation + +pci:v00008086d00000007* + ID_MODEL_FROM_DATABASE=82379AB + +pci:v00008086d00000008* + ID_MODEL_FROM_DATABASE=Extended Express System Support Controller + +pci:v00008086d00000039* + ID_MODEL_FROM_DATABASE=21145 Fast Ethernet + +pci:v00008086d00000040* + ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller + +pci:v00008086d00000041* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express x16 Root Port + +pci:v00008086d00000042* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller + +pci:v00008086d00000043* + ID_MODEL_FROM_DATABASE=Core Processor Secondary PCI Express Root Port + +pci:v00008086d00000044* + ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller + +pci:v00008086d00000044sv00001025sd00000347* + ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (Aspire 7740G) + +pci:v00008086d00000044sv00001025sd00000487* + ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (TravelMate 5742) + +pci:v00008086d00000044sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (Latitude E6410) + +pci:v00008086d00000044sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (R730 Laptop) + +pci:v00008086d00000044sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00000044sv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller (PC1-GROOVE) + +pci:v00008086d00000045* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express x16 Root Port + +pci:v00008086d00000045sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express x16 Root Port (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00000046* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller + +pci:v00008086d00000046sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller (Latitude E6410) + +pci:v00008086d00000046sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller (R730 Laptop) + +pci:v00008086d00000046sv000017C0sd000010D9* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00000046sv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller (PC1-GROOVE) + +pci:v00008086d00000047* + ID_MODEL_FROM_DATABASE=Core Processor Secondary PCI Express Root Port + +pci:v00008086d00000048* + ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller + +pci:v00008086d00000049* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express x16 Root Port + +pci:v00008086d0000004A* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Graphics Controller + +pci:v00008086d0000004B* + ID_MODEL_FROM_DATABASE=Core Processor Secondary PCI Express Root Port + +pci:v00008086d00000050* + ID_MODEL_FROM_DATABASE=Core Processor Thermal Management Controller + +pci:v00008086d00000069* + ID_MODEL_FROM_DATABASE=Core Processor DRAM Controller + +pci:v00008086d00000082* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] + +pci:v00008086d00000082sv00008086sd00001301* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 AGN) + +pci:v00008086d00000082sv00008086sd00001306* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 ABG) + +pci:v00008086d00000082sv00008086sd00001307* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 BG) + +pci:v00008086d00000082sv00008086sd00001321* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 AGN) + +pci:v00008086d00000082sv00008086sd00001326* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 ABG) + +pci:v00008086d00000083* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] + +pci:v00008086d00000083sv00008086sd00001205* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) + +pci:v00008086d00000083sv00008086sd00001206* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) + +pci:v00008086d00000083sv00008086sd00001225* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) + +pci:v00008086d00000083sv00008086sd00001226* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) + +pci:v00008086d00000083sv00008086sd00001305* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) + +pci:v00008086d00000083sv00008086sd00001306* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) + +pci:v00008086d00000083sv00008086sd00001325* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) + +pci:v00008086d00000083sv00008086sd00001326* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) + +pci:v00008086d00000084* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] + +pci:v00008086d00000084sv00008086sd00001215* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) + +pci:v00008086d00000084sv00008086sd00001216* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) + +pci:v00008086d00000084sv00008086sd00001315* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BGN) + +pci:v00008086d00000084sv00008086sd00001316* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1000 [Condor Peak] (Centrino Wireless-N 1000 BG) + +pci:v00008086d00000085* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] + +pci:v00008086d00000085sv00008086sd00001311* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 (802.11a/b/g/n)) + +pci:v00008086d00000085sv00008086sd00001316* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6205 [Taylor Peak] (Centrino Advanced-N 6205 ABG) + +pci:v00008086d00000087* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] + +pci:v00008086d00000087sv00008086sd00001301* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 AGN) + +pci:v00008086d00000087sv00008086sd00001306* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 ABG) + +pci:v00008086d00000087sv00008086sd00001321* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 AGN) + +pci:v00008086d00000087sv00008086sd00001326* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 ABG) + +pci:v00008086d00000089* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] + +pci:v00008086d00000089sv00008086sd00001311* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 AGN) + +pci:v00008086d00000089sv00008086sd00001316* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] (Centrino Advanced-N + WiMAX 6250 2x2 ABG) + +pci:v00008086d0000008A* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] + +pci:v00008086d0000008Asv00008086sd00005305* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BGN) + +pci:v00008086d0000008Asv00008086sd00005307* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BG) + +pci:v00008086d0000008Asv00008086sd00005325* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BGN) + +pci:v00008086d0000008Asv00008086sd00005327* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BG) + +pci:v00008086d0000008B* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] + +pci:v00008086d0000008Bsv00008086sd00005315* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BGN) + +pci:v00008086d0000008Bsv00008086sd00005317* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 1030 [Rainbow Peak] (Centrino Wireless-N 1030 BG) + +pci:v00008086d00000090* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] + +pci:v00008086d00000090sv00008086sd00005211* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 AGN) + +pci:v00008086d00000090sv00008086sd00005215* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 BGN) + +pci:v00008086d00000090sv00008086sd00005216* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 ABG) + +pci:v00008086d00000091* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] + +pci:v00008086d00000091sv00008086sd00005201* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 AGN) + +pci:v00008086d00000091sv00008086sd00005205* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 BGN) + +pci:v00008086d00000091sv00008086sd00005206* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 ABG) + +pci:v00008086d00000091sv00008086sd00005207* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 BG) + +pci:v00008086d00000091sv00008086sd00005221* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 AGN) + +pci:v00008086d00000091sv00008086sd00005225* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 BGN) + +pci:v00008086d00000091sv00008086sd00005226* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6230 [Rainbow Peak] (Centrino Advanced-N 6230 ABG) + +pci:v00008086d00000100* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller + +pci:v00008086d00000100sv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (XPS 8300) + +pci:v00008086d00000100sv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (P8P67/P8H67 Series Motherboard) + +pci:v00008086d00000101* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port + +pci:v00008086d00000101sv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (Vostro 3350) + +pci:v00008086d00000101sv0000106Bsd000000DC* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00000101sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (NP300E5C series laptop) + +pci:v00008086d00000102* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller + +pci:v00008086d00000102sv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (XPS 8300) + +pci:v00008086d00000102sv00001043sd00000102* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (P8H67 Series Motherboard) + +pci:v00008086d00000104* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller + +pci:v00008086d00000104sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (Precision M4600) + +pci:v00008086d00000104sv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (Vostro 3350) + +pci:v00008086d00000104sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (Vostro 3750) + +pci:v00008086d00000104sv0000106Bsd000000DC* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00000104sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (NP300E5C series laptop) + +pci:v00008086d00000104sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family DRAM Controller (ThinkPad T520) + +pci:v00008086d00000105* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port + +pci:v00008086d00000105sv0000106Bsd000000DC* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port (MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00000106* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller + +pci:v00008086d00000108* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 Processor Family DRAM Controller + +pci:v00008086d00000109* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port + +pci:v00008086d0000010A* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 Processor Family Integrated Graphics Controller + +pci:v00008086d0000010B* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family Integrated Graphics Controller + +pci:v00008086d0000010C* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family DRAM Controller + +pci:v00008086d0000010D* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port + +pci:v00008086d0000010E* + ID_MODEL_FROM_DATABASE=Xeon E3-1200/2nd Generation Core Processor Family Integrated Graphics Controller + +pci:v00008086d00000112* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller + +pci:v00008086d00000116* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller + +pci:v00008086d00000116sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (Vostro 3750) + +pci:v00008086d00000116sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (integrated HD 3000 graphics controller on NP300E5C series laptop) + +pci:v00008086d00000122* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller + +pci:v00008086d00000126* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller + +pci:v00008086d00000126sv00001028sd000004CC* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (Vostro 3350) + +pci:v00008086d00000126sv000017AAsd000021CE* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (ThinkPad T420) + +pci:v00008086d00000126sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=2nd Generation Core Processor Family Integrated Graphics Controller (ThinkPad T520) + +pci:v00008086d00000150* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller + +pci:v00008086d00000150sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller (P8 series motherboard) + +pci:v00008086d00000150sv00001458sd0000D000* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller (Ivy Bridge GT1 [HD Graphics]) + +pci:v00008086d00000150sv000015D9sd00000624* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller (X9SCM-F Motherboard) + +pci:v00008086d00000150sv00001849sd00000150* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller (Motherboard) + +pci:v00008086d00000151* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port + +pci:v00008086d00000151sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (N56VZ) + +pci:v00008086d00000151sv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (P8 series motherboard) + +pci:v00008086d00000151sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (P8H77-I Motherboard) + +pci:v00008086d00000151sv00008086sd00002010* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (Server Board S1200BTS) + +pci:v00008086d00000152* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller + +pci:v00008086d00000152sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (P8H77-I Motherboard) + +pci:v00008086d00000153* + ID_MODEL_FROM_DATABASE=3rd Gen Core Processor Thermal Subsystem + +pci:v00008086d00000153sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=3rd Gen Core Processor Thermal Subsystem (Zenbook Prime UX31A) + +pci:v00008086d00000154* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller + +pci:v00008086d00000154sv00001025sd00000806* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (Aspire E1-470G) + +pci:v00008086d00000154sv00001025sd00000813* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (Aspire R7-571) + +pci:v00008086d00000154sv0000103Csd000017F6* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (ProBook 4540s) + +pci:v00008086d00000154sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (VivoBook X202EV) + +pci:v00008086d00000154sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (N56VZ) + +pci:v00008086d00000154sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (Zenbook Prime UX31A) + +pci:v00008086d00000154sv000010CFsd000016BF* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor DRAM Controller (LIFEBOOK E752) + +pci:v00008086d00000155* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port + +pci:v00008086d00000155sv00008086sd00002010* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (Server Board S1200BTS) + +pci:v00008086d00000156* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller + +pci:v00008086d00000156sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller (VivoBook X202EV) + +pci:v00008086d00000158* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/Ivy Bridge DRAM Controller + +pci:v00008086d00000158sv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/Ivy Bridge DRAM Controller (P8 series motherboard) + +pci:v00008086d00000158sv00008086sd00002010* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/Ivy Bridge DRAM Controller (Server Board S1200BT Family) + +pci:v00008086d00000159* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port + +pci:v00008086d0000015A* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/Ivy Bridge Graphics Controller + +pci:v00008086d0000015C* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller + +pci:v00008086d0000015D* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port + +pci:v00008086d0000015Dsv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port (P8 series motherboard) + +pci:v00008086d0000015E* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller + +pci:v00008086d00000162* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller + +pci:v00008086d00000162sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (P8 series motherboard) + +pci:v00008086d00000162sv00001849sd00000162* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (Motherboard) + +pci:v00008086d00000166* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller + +pci:v00008086d00000166sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller (Zenbook Prime UX31A) + +pci:v00008086d00000166sv00001043sd00002103* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller (N56VZ) + +pci:v00008086d00000166sv000010CFsd000016C1* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller (LIFEBOOK E752) + +pci:v00008086d0000016A* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller + +pci:v00008086d0000016Asv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller (P8B WS Motherboard) + +pci:v00008086d00000172* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller + +pci:v00008086d00000176* + ID_MODEL_FROM_DATABASE=3rd Gen Core processor Graphics Controller + +pci:v00008086d000002A4* + ID_MODEL_FROM_DATABASE=Comet Lake SPI (flash) Controller + +pci:v00008086d000002A6* + ID_MODEL_FROM_DATABASE=Comet Lake North Peak + +pci:v00008086d000002D3* + ID_MODEL_FROM_DATABASE=Comet Lake SATA AHCI Controller + +pci:v00008086d000002E0* + ID_MODEL_FROM_DATABASE=Comet Lake Management Engine Interface + +pci:v00008086d000002E8* + ID_MODEL_FROM_DATABASE=Serial IO I2C Host Controller + +pci:v00008086d000002F0* + ID_MODEL_FROM_DATABASE=Wireless-AC 9462 + +pci:v00008086d000002F9* + ID_MODEL_FROM_DATABASE=Comet Lake Thermal Subsytem + +pci:v00008086d000002FC* + ID_MODEL_FROM_DATABASE=Comet Lake Integrated Sensor Solution + +pci:v00008086d00000309* + ID_MODEL_FROM_DATABASE=80303 I/O Processor PCI-to-PCI Bridge + +pci:v00008086d0000030D* + ID_MODEL_FROM_DATABASE=80312 I/O Companion Chip PCI-to-PCI Bridge + +pci:v00008086d00000326* + ID_MODEL_FROM_DATABASE=6700/6702PXH I/OxAPIC Interrupt Controller A + +pci:v00008086d00000326sv0000103Csd00003208* + ID_MODEL_FROM_DATABASE=6700/6702PXH I/OxAPIC Interrupt Controller A (ProLiant DL140 G2) + +pci:v00008086d00000326sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6700/6702PXH I/OxAPIC Interrupt Controller A (CR11/VR11 Single Board Computer) + +pci:v00008086d00000327* + ID_MODEL_FROM_DATABASE=6700PXH I/OxAPIC Interrupt Controller B + +pci:v00008086d00000327sv0000103Csd00003208* + ID_MODEL_FROM_DATABASE=6700PXH I/OxAPIC Interrupt Controller B (ProLiant DL140 G2) + +pci:v00008086d00000327sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6700PXH I/OxAPIC Interrupt Controller B (CR11/VR11 Single Board Computer) + +pci:v00008086d00000329* + ID_MODEL_FROM_DATABASE=6700PXH PCI Express-to-PCI Bridge A + +pci:v00008086d0000032A* + ID_MODEL_FROM_DATABASE=6700PXH PCI Express-to-PCI Bridge B + +pci:v00008086d0000032C* + ID_MODEL_FROM_DATABASE=6702PXH PCI Express-to-PCI Bridge A + +pci:v00008086d00000330* + ID_MODEL_FROM_DATABASE=80332 [Dobson] I/O processor (A-Segment Bridge) + +pci:v00008086d00000331* + ID_MODEL_FROM_DATABASE=80332 [Dobson] I/O processor (A-Segment IOAPIC) + +pci:v00008086d00000332* + ID_MODEL_FROM_DATABASE=80332 [Dobson] I/O processor (B-Segment Bridge) + +pci:v00008086d00000333* + ID_MODEL_FROM_DATABASE=80332 [Dobson] I/O processor (B-Segment IOAPIC) + +pci:v00008086d00000334* + ID_MODEL_FROM_DATABASE=80332 [Dobson] I/O processor (ATU) + +pci:v00008086d00000335* + ID_MODEL_FROM_DATABASE=80331 [Lindsay] I/O processor (PCI-X Bridge) + +pci:v00008086d00000336* + ID_MODEL_FROM_DATABASE=80331 [Lindsay] I/O processor (ATU) + +pci:v00008086d00000340* + ID_MODEL_FROM_DATABASE=41210 [Lanai] Serial to Parallel PCI Bridge (A-Segment Bridge) + +pci:v00008086d00000341* + ID_MODEL_FROM_DATABASE=41210 [Lanai] Serial to Parallel PCI Bridge (B-Segment Bridge) + +pci:v00008086d00000370* + ID_MODEL_FROM_DATABASE=80333 Segment-A PCIe Express to PCI-X bridge + +pci:v00008086d00000371* + ID_MODEL_FROM_DATABASE=80333 A-Bus IOAPIC + +pci:v00008086d00000372* + ID_MODEL_FROM_DATABASE=80333 Segment-B PCIe Express to PCI-X bridge + +pci:v00008086d00000373* + ID_MODEL_FROM_DATABASE=80333 B-Bus IOAPIC + +pci:v00008086d00000374* + ID_MODEL_FROM_DATABASE=80333 Address Translation Unit + +pci:v00008086d00000402* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller + +pci:v00008086d00000406* + ID_MODEL_FROM_DATABASE=Haswell Integrated Graphics Controller + +pci:v00008086d0000040A* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3 Processor Integrated Graphics Controller + +pci:v00008086d00000412* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller + +pci:v00008086d00000412sv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller (ThinkCentre M83) + +pci:v00008086d00000416* + ID_MODEL_FROM_DATABASE=4th Gen Core Processor Integrated Graphics Controller + +pci:v00008086d00000416sv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=4th Gen Core Processor Integrated Graphics Controller (ThinkPad T440p) + +pci:v00008086d0000041A* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3 Processor Integrated Graphics Controller + +pci:v00008086d0000041E* + ID_MODEL_FROM_DATABASE=4th Generation Core Processor Family Integrated Graphics Controller + +pci:v00008086d00000434* + ID_MODEL_FROM_DATABASE=DH89XXCC Series QAT + +pci:v00008086d00000435* + ID_MODEL_FROM_DATABASE=DH895XCC Series QAT + +pci:v00008086d00000436* + ID_MODEL_FROM_DATABASE=DH8900CC Null Device + +pci:v00008086d00000438* + ID_MODEL_FROM_DATABASE=DH8900CC Series Gigabit Network Connection + +pci:v00008086d0000043A* + ID_MODEL_FROM_DATABASE=DH8900CC Series Gigabit Fiber Network Connection + +pci:v00008086d0000043C* + ID_MODEL_FROM_DATABASE=DH8900CC Series Gigabit Backplane Network Connection + +pci:v00008086d00000440* + ID_MODEL_FROM_DATABASE=DH8900CC Series Gigabit SFP Network Connection + +pci:v00008086d00000442* + ID_MODEL_FROM_DATABASE=DH89XXCC Series QAT Virtual Function + +pci:v00008086d00000443* + ID_MODEL_FROM_DATABASE=DH895XCC Series QAT Virtual Function + +pci:v00008086d00000482* + ID_MODEL_FROM_DATABASE=82375EB/SB PCI to EISA Bridge + +pci:v00008086d00000483* + ID_MODEL_FROM_DATABASE=82424TX/ZX [Saturn] CPU to PCI bridge + +pci:v00008086d00000484* + ID_MODEL_FROM_DATABASE=82378ZB/IB, 82379AB (SIO, SIO.A) PCI to ISA Bridge + +pci:v00008086d00000486* + ID_MODEL_FROM_DATABASE=82425EX/ZX [Aries] PCIset with ISA bridge + +pci:v00008086d000004A3* + ID_MODEL_FROM_DATABASE=82434LX/NX [Mercury/Neptune] Processor to PCI bridge + +pci:v00008086d000004D0* + ID_MODEL_FROM_DATABASE=82437FX [Triton FX] + +pci:v00008086d00000500* + ID_MODEL_FROM_DATABASE=E8870 Processor bus control + +pci:v00008086d00000501* + ID_MODEL_FROM_DATABASE=E8870 Memory controller + +pci:v00008086d00000502* + ID_MODEL_FROM_DATABASE=E8870 Scalability Port 0 + +pci:v00008086d00000503* + ID_MODEL_FROM_DATABASE=E8870 Scalability Port 1 + +pci:v00008086d00000510* + ID_MODEL_FROM_DATABASE=E8870IO Hub Interface Port 0 registers (8-bit compatibility port) + +pci:v00008086d00000511* + ID_MODEL_FROM_DATABASE=E8870IO Hub Interface Port 1 registers + +pci:v00008086d00000512* + ID_MODEL_FROM_DATABASE=E8870IO Hub Interface Port 2 registers + +pci:v00008086d00000513* + ID_MODEL_FROM_DATABASE=E8870IO Hub Interface Port 3 registers + +pci:v00008086d00000514* + ID_MODEL_FROM_DATABASE=E8870IO Hub Interface Port 4 registers + +pci:v00008086d00000515* + ID_MODEL_FROM_DATABASE=E8870IO General SIOH registers + +pci:v00008086d00000516* + ID_MODEL_FROM_DATABASE=E8870IO RAS registers + +pci:v00008086d00000530* + ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 0 registers + +pci:v00008086d00000531* + ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 1 registers + +pci:v00008086d00000532* + ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 2 registers + +pci:v00008086d00000533* + ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 3 registers + +pci:v00008086d00000534* + ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 4 registers + +pci:v00008086d00000535* + ID_MODEL_FROM_DATABASE=E8870SP Scalability Port 5 registers + +pci:v00008086d00000536* + ID_MODEL_FROM_DATABASE=E8870SP Interleave registers 0 and 1 + +pci:v00008086d00000537* + ID_MODEL_FROM_DATABASE=E8870SP Interleave registers 2 and 3 + +pci:v00008086d00000600* + ID_MODEL_FROM_DATABASE=RAID Controller + +pci:v00008086d00000600sv00008086sd00000136* + ID_MODEL_FROM_DATABASE=RAID Controller (SRCU31L) + +pci:v00008086d00000600sv00008086sd000001AF* + ID_MODEL_FROM_DATABASE=RAID Controller (SRCZCR) + +pci:v00008086d00000600sv00008086sd000001C1* + ID_MODEL_FROM_DATABASE=RAID Controller (ICP Vortex GDT8546RZ) + +pci:v00008086d00000600sv00008086sd000001F7* + ID_MODEL_FROM_DATABASE=RAID Controller (SCRU32) + +pci:v00008086d0000061F* + ID_MODEL_FROM_DATABASE=80303 I/O Processor + +pci:v00008086d00000700* + ID_MODEL_FROM_DATABASE=CE Media Processor A/V Bridge + +pci:v00008086d00000701* + ID_MODEL_FROM_DATABASE=CE Media Processor NAND Flash Controller + +pci:v00008086d00000703* + ID_MODEL_FROM_DATABASE=CE Media Processor Media Control Unit 1 + +pci:v00008086d00000704* + ID_MODEL_FROM_DATABASE=CE Media Processor Video Capture Interface + +pci:v00008086d00000707* + ID_MODEL_FROM_DATABASE=CE Media Processor SPI Slave + +pci:v00008086d00000708* + ID_MODEL_FROM_DATABASE=CE Media Processor 4100 + +pci:v00008086d00000800* + ID_MODEL_FROM_DATABASE=Moorestown SPI Ctrl 0 + +pci:v00008086d00000801* + ID_MODEL_FROM_DATABASE=Moorestown SPI Ctrl 1 + +pci:v00008086d00000802* + ID_MODEL_FROM_DATABASE=Moorestown I2C 0 + +pci:v00008086d00000803* + ID_MODEL_FROM_DATABASE=Moorestown I2C 1 + +pci:v00008086d00000804* + ID_MODEL_FROM_DATABASE=Moorestown I2C 2 + +pci:v00008086d00000805* + ID_MODEL_FROM_DATABASE=Moorestown Keyboard Ctrl + +pci:v00008086d00000806* + ID_MODEL_FROM_DATABASE=Moorestown USB Ctrl + +pci:v00008086d00000807* + ID_MODEL_FROM_DATABASE=Moorestown SD Host Ctrl 0 + +pci:v00008086d00000808* + ID_MODEL_FROM_DATABASE=Moorestown SD Host Ctrl 1 + +pci:v00008086d00000809* + ID_MODEL_FROM_DATABASE=Moorestown NAND Ctrl + +pci:v00008086d0000080A* + ID_MODEL_FROM_DATABASE=Moorestown Audio Ctrl + +pci:v00008086d0000080B* + ID_MODEL_FROM_DATABASE=Moorestown ISP + +pci:v00008086d0000080C* + ID_MODEL_FROM_DATABASE=Moorestown Security Controller + +pci:v00008086d0000080D* + ID_MODEL_FROM_DATABASE=Moorestown External Displays + +pci:v00008086d0000080E* + ID_MODEL_FROM_DATABASE=Moorestown SCU IPC + +pci:v00008086d0000080F* + ID_MODEL_FROM_DATABASE=Moorestown GPIO Controller + +pci:v00008086d00000810* + ID_MODEL_FROM_DATABASE=Moorestown Power Management Unit + +pci:v00008086d00000811* + ID_MODEL_FROM_DATABASE=Moorestown OTG Ctrl + +pci:v00008086d00000812* + ID_MODEL_FROM_DATABASE=Moorestown SPI Ctrl 2 + +pci:v00008086d00000813* + ID_MODEL_FROM_DATABASE=Moorestown SC DMA + +pci:v00008086d00000814* + ID_MODEL_FROM_DATABASE=Moorestown LPE DMA + +pci:v00008086d00000815* + ID_MODEL_FROM_DATABASE=Moorestown SSP0 + +pci:v00008086d00000817* + ID_MODEL_FROM_DATABASE=Medfield Serial IO I2C Controller #3 + +pci:v00008086d00000818* + ID_MODEL_FROM_DATABASE=Medfield Serial IO I2C Controller #4 + +pci:v00008086d00000819* + ID_MODEL_FROM_DATABASE=Medfield Serial IO I2C Controller #5 + +pci:v00008086d0000081A* + ID_MODEL_FROM_DATABASE=Medfield GPIO Controller [Core] + +pci:v00008086d0000081B* + ID_MODEL_FROM_DATABASE=Medfield Serial IO HSUART Controller #1 + +pci:v00008086d0000081C* + ID_MODEL_FROM_DATABASE=Medfield Serial IO HSUART Controller #2 + +pci:v00008086d0000081D* + ID_MODEL_FROM_DATABASE=Medfield Serial IO HSUART Controller #3 + +pci:v00008086d0000081E* + ID_MODEL_FROM_DATABASE=Medfield Serial IO HSUART DMA Controller + +pci:v00008086d0000081F* + ID_MODEL_FROM_DATABASE=Medfield GPIO Controller [AON] + +pci:v00008086d00000820* + ID_MODEL_FROM_DATABASE=Medfield SD Host Controller + +pci:v00008086d00000821* + ID_MODEL_FROM_DATABASE=Medfield SDIO Controller #1 + +pci:v00008086d00000822* + ID_MODEL_FROM_DATABASE=Medfield SDIO Controller #2 + +pci:v00008086d00000823* + ID_MODEL_FROM_DATABASE=Medfield eMMC Controller #0 + +pci:v00008086d00000824* + ID_MODEL_FROM_DATABASE=Medfield eMMC Controller #1 + +pci:v00008086d00000827* + ID_MODEL_FROM_DATABASE=Medfield Serial IO DMA Controller + +pci:v00008086d00000828* + ID_MODEL_FROM_DATABASE=Medfield Power Management Unit + +pci:v00008086d00000829* + ID_MODEL_FROM_DATABASE=Medfield USB Device Controller (OTG) + +pci:v00008086d0000082A* + ID_MODEL_FROM_DATABASE=Medfield SCU IPC + +pci:v00008086d0000082C* + ID_MODEL_FROM_DATABASE=Medfield Serial IO I2C Controller #0 + +pci:v00008086d0000082D* + ID_MODEL_FROM_DATABASE=Medfield Serial IO I2C Controller #1 + +pci:v00008086d0000082E* + ID_MODEL_FROM_DATABASE=Medfield Serial IO I2C Controller #2 + +pci:v00008086d00000885* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 + +pci:v00008086d00000885sv00008086sd00001305* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BGN) + +pci:v00008086d00000885sv00008086sd00001307* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BG) + +pci:v00008086d00000885sv00008086sd00001325* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BGN) + +pci:v00008086d00000885sv00008086sd00001327* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BG) + +pci:v00008086d00000886* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 + +pci:v00008086d00000886sv00008086sd00001315* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BGN) + +pci:v00008086d00000886sv00008086sd00001317* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N + WiMAX 6150 (BG) + +pci:v00008086d00000887* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2230 + +pci:v00008086d00000887sv00008086sd00004062* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2230 (BGN) + +pci:v00008086d00000887sv00008086sd00004462* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2230 (BGN) + +pci:v00008086d00000888* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2230 + +pci:v00008086d00000888sv00008086sd00004262* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2230 (BGN) + +pci:v00008086d0000088E* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6235 + +pci:v00008086d0000088Esv00008086sd00004060* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6235 (AGN) + +pci:v00008086d0000088Esv00008086sd00004460* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6235 (AGN) + +pci:v00008086d0000088F* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6235 + +pci:v00008086d0000088Fsv00008086sd00004260* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6235 (AGN) + +pci:v00008086d00000890* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 + +pci:v00008086d00000890sv00008086sd00004022* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 (BGN) + +pci:v00008086d00000890sv00008086sd00004422* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 (BGN) + +pci:v00008086d00000890sv00008086sd00004822* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 (BGN) + +pci:v00008086d00000891* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 + +pci:v00008086d00000891sv00008086sd00004222* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 2200 (BGN) + +pci:v00008086d00000892* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 135 + +pci:v00008086d00000892sv00008086sd00000062* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 135 (BGN) + +pci:v00008086d00000892sv00008086sd00000462* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 135 (BGN) + +pci:v00008086d00000893* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 135 + +pci:v00008086d00000893sv00008086sd00000262* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 135 (BGN) + +pci:v00008086d00000894* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 + +pci:v00008086d00000894sv00008086sd00000022* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 (BGN) + +pci:v00008086d00000894sv00008086sd00000422* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 (BGN) + +pci:v00008086d00000894sv00008086sd00000822* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 (BGN) + +pci:v00008086d00000895* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 + +pci:v00008086d00000895sv00008086sd00000222* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 105 (BGN) + +pci:v00008086d00000896* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 + +pci:v00008086d00000896sv00008086sd00005005* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BGN) + +pci:v00008086d00000896sv00008086sd00005007* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BG) + +pci:v00008086d00000896sv00008086sd00005025* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BGN) + +pci:v00008086d00000896sv00008086sd00005027* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BG) + +pci:v00008086d00000897* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 + +pci:v00008086d00000897sv00008086sd00005015* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BGN) + +pci:v00008086d00000897sv00008086sd00005017* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 130 (BG) + +pci:v00008086d000008A7* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 SDIO / eMMC Controller + +pci:v00008086d000008AE* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 + +pci:v00008086d000008AEsv00008086sd00001005* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BGN) + +pci:v00008086d000008AEsv00008086sd00001007* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BG) + +pci:v00008086d000008AEsv00008086sd00001025* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BGN) + +pci:v00008086d000008AEsv00008086sd00001027* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BG) + +pci:v00008086d000008AF* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 + +pci:v00008086d000008AFsv00008086sd00001015* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BGN) + +pci:v00008086d000008AFsv00008086sd00001017* + ID_MODEL_FROM_DATABASE=Centrino Wireless-N 100 (BG) + +pci:v00008086d000008B1* + ID_MODEL_FROM_DATABASE=Wireless 7260 + +pci:v00008086d000008B1sv00008086sd00004020* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000402A* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd00004060* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd00004062* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000406A* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd00004070* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004072* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004160* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd00004162* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd00004170* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004420* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd00004460* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd00004462* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000446A* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd00004470* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004472* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004560* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd00004570* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd0000486E* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004870* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004A6C* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004A6E* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004A70* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004C60* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00004C70* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00005070* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00005072* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00005170* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd00005770* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd0000C020* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C02A* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C060* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C062* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C06A* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C070* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd0000C072* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd0000C160* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C162* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C170* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd0000C360* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C420* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C460* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C462* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C470* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd0000C472* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd0000C560* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C570* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd0000C760* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B1sv00008086sd0000C770* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd0000CC60* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B1sv00008086sd0000CC70* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B2* + ID_MODEL_FROM_DATABASE=Wireless 7260 + +pci:v00008086d000008B2sv00008086sd00004220* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B2sv00008086sd00004260* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B2sv00008086sd00004262* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) + +pci:v00008086d000008B2sv00008086sd0000426A* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B2sv00008086sd00004270* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) + +pci:v00008086d000008B2sv00008086sd00004272* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B2sv00008086sd00004360* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B2sv00008086sd00004370* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B2sv00008086sd0000C220* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B2sv00008086sd0000C260* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B2sv00008086sd0000C262* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Wireless-N 7260) + +pci:v00008086d000008B2sv00008086sd0000C26A* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) + +pci:v00008086d000008B2sv00008086sd0000C270* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B2sv00008086sd0000C272* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B2sv00008086sd0000C370* + ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-AC 7260) + +pci:v00008086d000008B3* + ID_MODEL_FROM_DATABASE=Wireless 3160 + +pci:v00008086d000008B3sv00008086sd00000060* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-N 3160) + +pci:v00008086d000008B3sv00008086sd00000062* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Wireless-N 3160) + +pci:v00008086d000008B3sv00008086sd00000070* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B3sv00008086sd00000072* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B3sv00008086sd00000170* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B3sv00008086sd00000172* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B3sv00008086sd00000260* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-N 3160) + +pci:v00008086d000008B3sv00008086sd00000470* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B3sv00008086sd00000472* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B3sv00008086sd00001070* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B3sv00008086sd00001170* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B3sv00008086sd00008060* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless N-3160) + +pci:v00008086d000008B3sv00008086sd00008062* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Wireless N-3160) + +pci:v00008086d000008B3sv00008086sd00008070* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) + +pci:v00008086d000008B3sv00008086sd00008072* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) + +pci:v00008086d000008B3sv00008086sd00008170* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) + +pci:v00008086d000008B3sv00008086sd00008172* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) + +pci:v00008086d000008B3sv00008086sd00008470* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) + +pci:v00008086d000008B3sv00008086sd00008570* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) + +pci:v00008086d000008B4* + ID_MODEL_FROM_DATABASE=Wireless 3160 + +pci:v00008086d000008B4sv00008086sd00000270* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B4sv00008086sd00000272* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B4sv00008086sd00000370* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless-AC 3160) + +pci:v00008086d000008B4sv00008086sd00008260* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) + +pci:v00008086d000008B4sv00008086sd00008270* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) + +pci:v00008086d000008B4sv00008086sd00008272* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) + +pci:v00008086d000008B4sv00008086sd00008370* + ID_MODEL_FROM_DATABASE=Wireless 3160 (Dual Band Wireless AC 3160) + +pci:v00008086d000008CF* + ID_MODEL_FROM_DATABASE=Atom Processor Z2760 Integrated Graphics Controller + +pci:v00008086d00000934* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 I2C Controller and GPIO Controller + +pci:v00008086d00000935* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 SPI Controller + +pci:v00008086d00000936* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 HS-UART + +pci:v00008086d00000937* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 10/100 Ethernet MAC + +pci:v00008086d00000939* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 USB EHCI Host Controller / USB 2.0 Device + +pci:v00008086d0000093A* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 USB OHCI Host Controller + +pci:v00008086d00000953* + ID_MODEL_FROM_DATABASE=PCIe Data Center SSD + +pci:v00008086d00000953sv00008086sd00003702* + ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3700 SSD) + +pci:v00008086d00000953sv00008086sd00003703* + ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3700 SSD [2.5" SFF]) + +pci:v00008086d00000953sv00008086sd00003704* + ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3500 SSD [Add-in Card]) + +pci:v00008086d00000953sv00008086sd00003705* + ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3500 SSD [2.5" SFF]) + +pci:v00008086d00000953sv00008086sd00003709* + ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3600 SSD [Add-in Card]) + +pci:v00008086d00000953sv00008086sd0000370A* + ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (DC P3600 SSD [2.5" SFF]) + +pci:v00008086d00000953sv00008086sd0000370D* + ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (SSD 750 Series [Add-in Card]) + +pci:v00008086d00000953sv00008086sd0000370E* + ID_MODEL_FROM_DATABASE=PCIe Data Center SSD (SSD 750 Series [2.5" SFF]) + +pci:v00008086d00000958* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 Host Bridge + +pci:v00008086d0000095A* + ID_MODEL_FROM_DATABASE=Wireless 7265 + +pci:v00008086d0000095Asv00008086sd00001010* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005000* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) + +pci:v00008086d0000095Asv00008086sd00005002* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Wireless-N 7265) + +pci:v00008086d0000095Asv00008086sd0000500A* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) + +pci:v00008086d0000095Asv00008086sd00005010* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005012* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005020* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) + +pci:v00008086d0000095Asv00008086sd0000502A* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) + +pci:v00008086d0000095Asv00008086sd00005090* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005100* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005102* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Wireless-N 7265) + +pci:v00008086d0000095Asv00008086sd0000510A* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005110* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005112* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005190* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005400* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005410* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005412* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005420* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) + +pci:v00008086d0000095Asv00008086sd00005490* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005510* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00005590* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00009000* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd0000900A* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00009010* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00009012* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00009110* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00009112* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00009210* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00009310* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00009400* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00009410* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Asv00008086sd00009510* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095B* + ID_MODEL_FROM_DATABASE=Wireless 7265 + +pci:v00008086d0000095Bsv00008086sd00005200* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) + +pci:v00008086d0000095Bsv00008086sd00005202* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Wireless-N 7265) + +pci:v00008086d0000095Bsv00008086sd0000520A* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-N 7265) + +pci:v00008086d0000095Bsv00008086sd00005210* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Bsv00008086sd00005212* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Bsv00008086sd00005290* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Bsv00008086sd00005302* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Wireless-N 7265) + +pci:v00008086d0000095Bsv00008086sd00005310* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095Bsv00008086sd00009200* + ID_MODEL_FROM_DATABASE=Wireless 7265 (Dual Band Wireless-AC 7265) + +pci:v00008086d0000095E* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 Legacy Bridge + +pci:v00008086d00000960* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor/Bridge + +pci:v00008086d00000962* + ID_MODEL_FROM_DATABASE=80960RM (i960RM) Bridge + +pci:v00008086d00000964* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor/Bridge + +pci:v00008086d00000A03* + ID_MODEL_FROM_DATABASE=Haswell-ULT Thermal Subsystem + +pci:v00008086d00000A04* + ID_MODEL_FROM_DATABASE=Haswell-ULT DRAM Controller + +pci:v00008086d00000A04sv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=Haswell-ULT DRAM Controller (ThinkPad X240) + +pci:v00008086d00000A06* + ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller + +pci:v00008086d00000A0C* + ID_MODEL_FROM_DATABASE=Haswell-ULT HD Audio Controller + +pci:v00008086d00000A0Csv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=Haswell-ULT HD Audio Controller (ThinkPad X240) + +pci:v00008086d00000A16* + ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller + +pci:v00008086d00000A16sv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller (ThinkPad X240) + +pci:v00008086d00000A22* + ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller + +pci:v00008086d00000A26* + ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller + +pci:v00008086d00000A2A* + ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller + +pci:v00008086d00000A2E* + ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller + +pci:v00008086d00000A53* + ID_MODEL_FROM_DATABASE=DC P3520 SSD + +pci:v00008086d00000A54* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] + +pci:v00008086d00000A54sv00001028sd00001FE1* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 1TB 2.5" U.2 (P4500)) + +pci:v00008086d00000A54sv00001028sd00001FE2* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 2TB 2.5" U.2 (P4500)) + +pci:v00008086d00000A54sv00001028sd00001FE3* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 4TB 2.5" U.2 (P4500)) + +pci:v00008086d00000A54sv00001028sd00001FE4* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 4TB HHHL AIC (P4500)) + +pci:v00008086d00000A54sv00001028sd00001FEE* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 1.6TB 2.5" U.2 (P4610)) + +pci:v00008086d00000A54sv00001028sd00001FEF* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 3.2TB 2.5" U.2 (P4610)) + +pci:v00008086d00000A54sv00001028sd00001FF0* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 6.4TB 2.5" U.2 (P4610)) + +pci:v00008086d00000A54sv00001028sd00001FFF* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 8.0TB 2.5" U.2 (P4510)) + +pci:v00008086d00000A54sv00001028sd00002003* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 1.0 TB 2.5" U.2 (P4510)) + +pci:v00008086d00000A54sv00001028sd00002004* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 2.0TB 2.5" U.2 (P4510)) + +pci:v00008086d00000A54sv00001028sd00002005* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 4.0TB 2.5" U.2 (P4510)) + +pci:v00008086d00000A54sv0000108Esd00004870* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe PCIe 3.0 SSD 6.4TB AIC (P4608)) + +pci:v00008086d00000A54sv0000108Esd00004871* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe PCIe 3.0 SSD 6.4TB 2.5-inch (P4600)) + +pci:v00008086d00000A54sv0000108Esd00004879* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe PCIe 3.0 SSD v2 6.4TB AIC (P4618)) + +pci:v00008086d00000A54sv0000108Esd0000487A* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe PCIe 3.0 SSD v2 6.4TB 2.5-inch (P4610)) + +pci:v00008086d00000A54sv00001137sd00000227* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 1.6TB 2.5" U.2 (P4600)) + +pci:v00008086d00000A54sv00001137sd00000228* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4600)) + +pci:v00008086d00000A54sv00001137sd00000229* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 3.2TB 2.5" U.2 (P4600)) + +pci:v00008086d00000A54sv00001137sd0000022B* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4500)) + +pci:v00008086d00000A54sv00001137sd0000022C* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4500)) + +pci:v00008086d00000A54sv00001137sd0000022D* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 4.0TB 2.5" U.2 (P4500)) + +pci:v00008086d00000A54sv00001137sd00000231* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 0.5TB 2.5" U.2 (P4501)) + +pci:v00008086d00000A54sv00001137sd00000232* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4501)) + +pci:v00008086d00000A54sv00001137sd00000233* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4501)) + +pci:v00008086d00000A54sv00001137sd00000258* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 1.6TB 2.5" U.2 (P4610)) + +pci:v00008086d00000A54sv00001137sd0000025A* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 3.2TB 2.5" U.2 (P4610)) + +pci:v00008086d00000A54sv00001137sd0000025B* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4510)) + +pci:v00008086d00000A54sv00001137sd0000025C* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4510)) + +pci:v00008086d00000A54sv00001137sd0000025D* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 4.0TB 2.5" U.2 (P4510)) + +pci:v00008086d00000A54sv00001137sd0000025E* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 8.0TB 2.5" U.2 (P4510)) + +pci:v00008086d00000A54sv00001590sd0000025D* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4500)) + +pci:v00008086d00000A54sv00001590sd0000025E* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4500)) + +pci:v00008086d00000A54sv00001590sd0000025F* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 4.0TB 2.5" U.2 (P4500)) + +pci:v00008086d00000A54sv00001590sd00000262* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 1.6TB 2.5" U.2 (P4600)) + +pci:v00008086d00000A54sv00001590sd00000264* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 3.2TB 2.5" U.2 (P4600)) + +pci:v00008086d00000A54sv00001590sd00000265* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 6.4TB 2.5" U.2 (P4600)) + +pci:v00008086d00000A54sv00001590sd0000026C* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] 4.0TB AIC (P4500)) + +pci:v00008086d00000A54sv00001D49sd00004702* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Thinksystem Intel P4500 NVMe U.2) + +pci:v00008086d00000A54sv00001D49sd00004704* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Thinksystem Intel P4500 NVMe AIC) + +pci:v00008086d00000A54sv00001D49sd00004712* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Thinksystem Intel P4600 NVMe U.2) + +pci:v00008086d00000A54sv00001D49sd00004714* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Thinksystem Intel P4600 NVMe AIC) + +pci:v00008086d00000A54sv00001D49sd00004802* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Thinksystem U.2 P4510 NVMe SSD) + +pci:v00008086d00000A54sv00001D49sd00004812* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Thinksystem U.2 P4610 NVMe SSD) + +pci:v00008086d00000A54sv00008086sd00004308* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (Intel SSD D5-P4320 and D5-P4326) + +pci:v00008086d00000A54sv00008086sd00004702* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] SE 2.5" U.2 (P4500)) + +pci:v00008086d00000A54sv00008086sd00004704* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] SE AIC (P4500)) + +pci:v00008086d00000A54sv00008086sd00004712* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] ME 2.5" U.2 (P4600)) + +pci:v00008086d00000A54sv00008086sd00004714* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] ME AIC (P4600)) + +pci:v00008086d00000A54sv00008086sd00004802* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] SE 2.5" U.2 (P4510)) + +pci:v00008086d00000A54sv00008086sd00004804* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] SE AIC (P4510)) + +pci:v00008086d00000A54sv00008086sd00004805* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] SE M.2 (P4511)) + +pci:v00008086d00000A54sv00008086sd00004812* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] ME 2.5" U.2 (P4610)) + +pci:v00008086d00000A54sv00008086sd00004814* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [3DNAND, Beta Rock Controller] (NVMe Datacenter SSD [3DNAND] ME AIC (P4610)) + +pci:v00008086d00000A55* + ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] + +pci:v00008086d00000A55sv00001028sd00001FE5* + ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 1.6TB 2.5" U.2 (P4600)) + +pci:v00008086d00000A55sv00001028sd00001FE6* + ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 2TB 2.5" U.2 (P4600)) + +pci:v00008086d00000A55sv00001028sd00001FE7* + ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 3.2TB 2.5" U.2 (P4600)) + +pci:v00008086d00000A55sv00001028sd00001FE8* + ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 2.0TB HHHL AIC (P4600)) + +pci:v00008086d00000A55sv00001028sd00001FE9* + ID_MODEL_FROM_DATABASE=NVMe DC SSD [3DNAND, Beta Rock Controller] (Express Flash NVMe 4.0TB HHHL AIC (P4600)) + +pci:v00008086d00000BE0* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BE1* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BE1sv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller (D270S/D250S Motherboard) + +pci:v00008086d00000BE2* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BE3* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BE4* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BE5* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BE6* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BE7* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BE8* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BE9* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BEA* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BEB* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BEC* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BED* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BEE* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BEF* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx Integrated Graphics Controller + +pci:v00008086d00000BF0* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller + +pci:v00008086d00000BF1* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller + +pci:v00008086d00000BF2* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller + +pci:v00008086d00000BF3* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller + +pci:v00008086d00000BF4* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller + +pci:v00008086d00000BF5* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller + +pci:v00008086d00000BF5sv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller (D270S/D250S Motherboard) + +pci:v00008086d00000BF6* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller + +pci:v00008086d00000BF7* + ID_MODEL_FROM_DATABASE=Atom Processor D2xxx/N2xxx DRAM Controller + +pci:v00008086d00000C00* + ID_MODEL_FROM_DATABASE=4th Gen Core Processor DRAM Controller + +pci:v00008086d00000C00sv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=4th Gen Core Processor DRAM Controller (ThinkCentre M83) + +pci:v00008086d00000C01* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor PCI Express x16 Controller + +pci:v00008086d00000C04* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller + +pci:v00008086d00000C04sv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller (ZBook 15) + +pci:v00008086d00000C04sv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller (ThinkPad T440p) + +pci:v00008086d00000C05* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor PCI Express x8 Controller + +pci:v00008086d00000C08* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3 Processor DRAM Controller + +pci:v00008086d00000C09* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor PCI Express x4 Controller + +pci:v00008086d00000C0C* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller + +pci:v00008086d00000C0Csv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller (ThinkPad T440p) + +pci:v00008086d00000C0Csv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller (ThinkCentre M83) + +pci:v00008086d00000C46* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 PCI Express Root Port 1 + +pci:v00008086d00000C47* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 PCI Express Root Port 2 + +pci:v00008086d00000C48* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 PCI Express Root Port 3 + +pci:v00008086d00000C49* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 PCI Express Root Port 4 + +pci:v00008086d00000C4E* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 NTB Primary + +pci:v00008086d00000C50* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device + +pci:v00008086d00000C51* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device + +pci:v00008086d00000C52* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device + +pci:v00008086d00000C53* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device + +pci:v00008086d00000C54* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C55* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 DFX 1 + +pci:v00008086d00000C56* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 DFX 2 + +pci:v00008086d00000C59* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus 2.0 Controller 0 + +pci:v00008086d00000C5A* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus 2.0 Controller 1 + +pci:v00008086d00000C5B* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus Controller 2 + +pci:v00008086d00000C5C* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus Controller 3 + +pci:v00008086d00000C5D* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus Controller 4 + +pci:v00008086d00000C5E* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 SMBus Controller 5 + +pci:v00008086d00000C5F* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 UART + +pci:v00008086d00000C60* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Integrated Legacy Bus + +pci:v00008086d00000C70* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C71* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C72* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C73* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C74* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C75* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C76* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C77* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C78* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C79* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C7A* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C7B* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C7C* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C7D* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C7E* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000C7F* + ID_MODEL_FROM_DATABASE=Atom Processor S1200 Internal + +pci:v00008086d00000CF8* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + +pci:v00008086d00000CF8sv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + +pci:v00008086d00000CF8sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + +pci:v00008086d00000D00* + ID_MODEL_FROM_DATABASE=Crystal Well DRAM Controller + +pci:v00008086d00000D01* + ID_MODEL_FROM_DATABASE=Crystal Well PCI Express x16 Controller + +pci:v00008086d00000D04* + ID_MODEL_FROM_DATABASE=Crystal Well DRAM Controller + +pci:v00008086d00000D05* + ID_MODEL_FROM_DATABASE=Crystal Well PCI Express x8 Controller + +pci:v00008086d00000D09* + ID_MODEL_FROM_DATABASE=Crystal Well PCI Express x4 Controller + +pci:v00008086d00000D0C* + ID_MODEL_FROM_DATABASE=Crystal Well HD Audio Controller + +pci:v00008086d00000D16* + ID_MODEL_FROM_DATABASE=Crystal Well Integrated Graphics Controller + +pci:v00008086d00000D26* + ID_MODEL_FROM_DATABASE=Crystal Well Integrated Graphics Controller + +pci:v00008086d00000D36* + ID_MODEL_FROM_DATABASE=Crystal Well Integrated Graphics Controller + +pci:v00008086d00000D4C* + ID_MODEL_FROM_DATABASE=Ethernet Connection (11) I219-LM + +pci:v00008086d00000D4D* + ID_MODEL_FROM_DATABASE=Ethernet Connection (11) I219-V + +pci:v00008086d00000D4E* + ID_MODEL_FROM_DATABASE=Ethernet Connection (10) I219-LM + +pci:v00008086d00000D4F* + ID_MODEL_FROM_DATABASE=Ethernet Connection (10) I219-V + +pci:v00008086d00000D53* + ID_MODEL_FROM_DATABASE=Ethernet Connection (12) I219-LM + +pci:v00008086d00000D55* + ID_MODEL_FROM_DATABASE=Ethernet Connection (12) I219-V + +pci:v00008086d00000D58* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + +pci:v00008086d00000D58sv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + +pci:v00008086d00000D58sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + +pci:v00008086d00000E00* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DMI2 + +pci:v00008086d00000E00sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DMI2 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E00sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DMI2 (X9SRL-F) + +pci:v00008086d00000E01* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port in DMI2 Mode + +pci:v00008086d00000E02* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 1a + +pci:v00008086d00000E02sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 1a (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E03* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 1b + +pci:v00008086d00000E04* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2a + +pci:v00008086d00000E05* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2b + +pci:v00008086d00000E06* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2c + +pci:v00008086d00000E07* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2d + +pci:v00008086d00000E08* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3a + +pci:v00008086d00000E08sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3a (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E09* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3b + +pci:v00008086d00000E0A* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3c + +pci:v00008086d00000E0B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3d + +pci:v00008086d00000E10* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers + +pci:v00008086d00000E13* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers + +pci:v00008086d00000E17* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers + +pci:v00008086d00000E18* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers + +pci:v00008086d00000E1C* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers + +pci:v00008086d00000E1D* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe + +pci:v00008086d00000E1E* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 UBOX Registers + +pci:v00008086d00000E1F* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 UBOX Registers + +pci:v00008086d00000E20* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 0 + +pci:v00008086d00000E20sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 0 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E20sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 0 (X9SRL-F) + +pci:v00008086d00000E21* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 1 + +pci:v00008086d00000E21sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 1 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E21sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 1 (X9SRL-F) + +pci:v00008086d00000E22* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 2 + +pci:v00008086d00000E22sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 2 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E22sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 2 (X9SRL-F) + +pci:v00008086d00000E23* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 3 + +pci:v00008086d00000E23sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 3 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E23sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 3 (X9SRL-F) + +pci:v00008086d00000E24* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 4 + +pci:v00008086d00000E24sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 4 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E24sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 4 (X9SRL-F) + +pci:v00008086d00000E25* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 5 + +pci:v00008086d00000E25sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 5 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E25sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 5 (X9SRL-F) + +pci:v00008086d00000E26* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 6 + +pci:v00008086d00000E26sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 6 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E26sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 6 (X9SRL-F) + +pci:v00008086d00000E27* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 7 + +pci:v00008086d00000E27sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 7 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E27sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 7 (X9SRL-F) + +pci:v00008086d00000E28* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 VTd/Memory Map/Misc + +pci:v00008086d00000E28sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 VTd/Memory Map/Misc (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E28sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 VTd/Memory Map/Misc (X9SRL-F) + +pci:v00008086d00000E29* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Memory Hotplug + +pci:v00008086d00000E2A* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO RAS + +pci:v00008086d00000E2Asv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO RAS (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E2Asv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IIO RAS (X9SRL-F) + +pci:v00008086d00000E2C* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IOAPIC + +pci:v00008086d00000E2Csv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 IOAPIC (X9SRL-F) + +pci:v00008086d00000E2E* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 CBDMA + +pci:v00008086d00000E2F* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 CBDMA + +pci:v00008086d00000E30* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 0 + +pci:v00008086d00000E30sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 0 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E32* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 0 + +pci:v00008086d00000E33* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 1 + +pci:v00008086d00000E34* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe + +pci:v00008086d00000E34sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E36* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring + +pci:v00008086d00000E36sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E37* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring + +pci:v00008086d00000E38* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 1 + +pci:v00008086d00000E3A* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 2 + +pci:v00008086d00000E3E* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring + +pci:v00008086d00000E3F* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring + +pci:v00008086d00000E40* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 2 + +pci:v00008086d00000E41* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers + +pci:v00008086d00000E43* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 2 + +pci:v00008086d00000E44* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 2 + +pci:v00008086d00000E45* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register + +pci:v00008086d00000E47* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register + +pci:v00008086d00000E60* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 1 + +pci:v00008086d00000E68* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Target Address/Thermal Registers + +pci:v00008086d00000E6A* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers + +pci:v00008086d00000E6B* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers + +pci:v00008086d00000E6C* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers + +pci:v00008086d00000E6D* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers + +pci:v00008086d00000E71* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 RAS Registers + +pci:v00008086d00000E74* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe + +pci:v00008086d00000E75* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe + +pci:v00008086d00000E77* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers + +pci:v00008086d00000E79* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 RAS Registers + +pci:v00008086d00000E7D* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 UBOX Registers + +pci:v00008086d00000E7F* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers + +pci:v00008086d00000E80* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 0 + +pci:v00008086d00000E81* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers + +pci:v00008086d00000E81sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000E83* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 0 + +pci:v00008086d00000E84* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 0 + +pci:v00008086d00000E85* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register + +pci:v00008086d00000E87* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Registers + +pci:v00008086d00000E90* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 1 + +pci:v00008086d00000E93* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 1 + +pci:v00008086d00000E94* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 1 + +pci:v00008086d00000E95* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register + +pci:v00008086d00000EA0* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 0 + +pci:v00008086d00000EA0sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 0 (Xeon E5 v2 on PowerEdge R320 server) + +pci:v00008086d00000EA8* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Target Address/Thermal Registers + +pci:v00008086d00000EAA* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers + +pci:v00008086d00000EAB* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers + +pci:v00008086d00000EAC* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers + +pci:v00008086d00000EAD* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers + +pci:v00008086d00000EAE* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers + +pci:v00008086d00000EAF* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers + +pci:v00008086d00000EB0* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 0 + +pci:v00008086d00000EB1* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 1 + +pci:v00008086d00000EB2* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 0 + +pci:v00008086d00000EB3* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 1 + +pci:v00008086d00000EB4* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 2 + +pci:v00008086d00000EB5* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 3 + +pci:v00008086d00000EB6* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 2 + +pci:v00008086d00000EB7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 3 + +pci:v00008086d00000EBC* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers + +pci:v00008086d00000EBE* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers + +pci:v00008086d00000EBF* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers + +pci:v00008086d00000EC0* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 0 + +pci:v00008086d00000EC1* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 1 + +pci:v00008086d00000EC2* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 2 + +pci:v00008086d00000EC3* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 3 + +pci:v00008086d00000EC4* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 4 + +pci:v00008086d00000EC8* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 System Address Decoder + +pci:v00008086d00000EC9* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Broadcast Registers + +pci:v00008086d00000ECA* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Broadcast Registers + +pci:v00008086d00000ED8* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000ED9* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000EDC* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000EDD* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000EDE* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000EDF* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000EE0* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EE1* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EE2* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EE3* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EE4* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EE5* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EE6* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EE7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EE8* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EE9* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EEA* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EEB* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EEC* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EED* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EEE* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + +pci:v00008086d00000EF0* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 0 + +pci:v00008086d00000EF1* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 1 + +pci:v00008086d00000EF2* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 0 + +pci:v00008086d00000EF3* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 1 + +pci:v00008086d00000EF4* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 2 + +pci:v00008086d00000EF5* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 3 + +pci:v00008086d00000EF6* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 2 + +pci:v00008086d00000EF7* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 3 + +pci:v00008086d00000EF8* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000EF9* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000EFA* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000EFB* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000EFC* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000EFD* + ID_MODEL_FROM_DATABASE=Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + +pci:v00008086d00000F00* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series SoC Transaction Register + +pci:v00008086d00000F04* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series High Definition Audio Controller + +pci:v00008086d00000F06* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 DMA Controller + +pci:v00008086d00000F08* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 PWM Controller + +pci:v00008086d00000F09* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 PWM Controller + +pci:v00008086d00000F0A* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 HSUART Controller #1 + +pci:v00008086d00000F0C* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 HSUART Controller #2 + +pci:v00008086d00000F0E* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO1 SPI Controller + +pci:v00008086d00000F12* + ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series SMBus Controller + +pci:v00008086d00000F14* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series SDIO Controller + +pci:v00008086d00000F15* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series SDIO Controller + +pci:v00008086d00000F16* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series SDIO Controller + +pci:v00008086d00000F18* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series Trusted Execution Engine + +pci:v00008086d00000F1C* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series Power Control Unit + +pci:v00008086d00000F20* + ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series SATA IDE Controller + +pci:v00008086d00000F21* + ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series SATA IDE Controller + +pci:v00008086d00000F22* + ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series SATA AHCI Controller + +pci:v00008086d00000F23* + ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series SATA AHCI Controller + +pci:v00008086d00000F28* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPE Audio Controller + +pci:v00008086d00000F31* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series Graphics & Display + +pci:v00008086d00000F34* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series USB EHCI + +pci:v00008086d00000F35* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx, Celeron N2000 Series USB xHCI + +pci:v00008086d00000F35sv00001025sd00000936* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx, Celeron N2000 Series USB xHCI (Aspire ES1) + +pci:v00008086d00000F37* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series OTG USB Device + +pci:v00008086d00000F38* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series Camera ISP + +pci:v00008086d00000F40* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 DMA Controller + +pci:v00008086d00000F41* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #1 + +pci:v00008086d00000F42* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #2 + +pci:v00008086d00000F43* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #3 + +pci:v00008086d00000F44* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #4 + +pci:v00008086d00000F45* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #5 + +pci:v00008086d00000F46* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #6 + +pci:v00008086d00000F47* + ID_MODEL_FROM_DATABASE=Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #7 + +pci:v00008086d00000F48* + ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series PCI Express Root Port 1 + +pci:v00008086d00000F4A* + ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series PCI Express Root Port 2 + +pci:v00008086d00000F4C* + ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series PCI Express Root Port 3 + +pci:v00008086d00000F4E* + ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series PCI Express Root Port 4 + +pci:v00008086d00000F50* + ID_MODEL_FROM_DATABASE=Atom Processor E3800 Series eMMC 4.5 Controller + +pci:v00008086d00001000* + ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) + +pci:v00008086d00001000sv00000E11sd0000B0DF* + ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) (NC6132 Gigabit Ethernet Adapter (1000-SX)) + +pci:v00008086d00001000sv00000E11sd0000B0E0* + ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) (NC6133 Gigabit Ethernet Adapter (1000-LX)) + +pci:v00008086d00001000sv00000E11sd0000B123* + ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) (NC6134 Gigabit Ethernet Adapter (1000-LX)) + +pci:v00008086d00001000sv00001014sd00000119* + ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) (Netfinity Gigabit Ethernet SX Adapter) + +pci:v00008086d00001000sv00008086sd00001000* + ID_MODEL_FROM_DATABASE=82542 Gigabit Ethernet Controller (Fiber) (PRO/1000 Gigabit Server Adapter) + +pci:v00008086d00001001* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Fiber) + +pci:v00008086d00001001sv00000E11sd0000004A* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Fiber) (NC6136 Gigabit Server Adapter) + +pci:v00008086d00001001sv00001014sd000001EA* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Fiber) (Netfinity Gigabit Ethernet SX Adapter) + +pci:v00008086d00001001sv00008086sd00001002* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Fiber) (PRO/1000 F Server Adapter) + +pci:v00008086d00001001sv00008086sd00001003* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Fiber) (PRO/1000 F Server Adapter) + +pci:v00008086d00001002* + ID_MODEL_FROM_DATABASE=Pro 100 LAN+Modem 56 Cardbus II + +pci:v00008086d00001002sv00008086sd0000200E* + ID_MODEL_FROM_DATABASE=Pro 100 LAN+Modem 56 Cardbus II + +pci:v00008086d00001002sv00008086sd00002013* + ID_MODEL_FROM_DATABASE=Pro 100 LAN+Modem 56 Cardbus II (Pro 100 SR Mobile Combo Adapter) + +pci:v00008086d00001002sv00008086sd00002017* + ID_MODEL_FROM_DATABASE=Pro 100 LAN+Modem 56 Cardbus II (Pro 100 S Combo Mobile Adapter) + +pci:v00008086d00001004* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) + +pci:v00008086d00001004sv00000E11sd00000049* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) (NC7132 Gigabit Upgrade Module) + +pci:v00008086d00001004sv00000E11sd0000B1A4* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) (NC7131 Gigabit Server Adapter) + +pci:v00008086d00001004sv00001014sd000010F2* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) (Gigabit Ethernet Server Adapter) + +pci:v00008086d00001004sv00008086sd00001004* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) (PRO/1000 T Server Adapter) + +pci:v00008086d00001004sv00008086sd00002004* + ID_MODEL_FROM_DATABASE=82543GC Gigabit Ethernet Controller (Copper) (PRO/1000 T Server Adapter) + +pci:v00008086d00001008* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) + +pci:v00008086d00001008sv00001014sd00000269* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (iSeries 1000/100/10 Ethernet Adapter) + +pci:v00008086d00001008sv00001028sd0000011B* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PowerEdge 1650/2550) + +pci:v00008086d00001008sv00001028sd0000011C* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PRO/1000 XT Network Connection) + +pci:v00008086d00001008sv00008086sd00001107* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PRO/1000 XT Server Adapter) + +pci:v00008086d00001008sv00008086sd00002107* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PRO/1000 XT Server Adapter) + +pci:v00008086d00001008sv00008086sd00002110* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PRO/1000 XT Desktop Adapter) + +pci:v00008086d00001008sv00008086sd00003108* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Copper) (PRO/1000 XT Network Connection) + +pci:v00008086d00001009* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Fiber) + +pci:v00008086d00001009sv00001014sd00000268* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Fiber) (iSeries Gigabit Ethernet Adapter) + +pci:v00008086d00001009sv00008086sd00001109* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Fiber) (PRO/1000 XF Server Adapter) + +pci:v00008086d00001009sv00008086sd00002109* + ID_MODEL_FROM_DATABASE=82544EI Gigabit Ethernet Controller (Fiber) (PRO/1000 XF Server Adapter) + +pci:v00008086d0000100A* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller + +pci:v00008086d0000100C* + ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (Copper) + +pci:v00008086d0000100Csv00008086sd00001112* + ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (Copper) (PRO/1000 T Desktop Adapter) + +pci:v00008086d0000100Csv00008086sd00002112* + ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (Copper) (PRO/1000 T Desktop Adapter) + +pci:v00008086d0000100D* + ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (LOM) + +pci:v00008086d0000100Dsv00001028sd00000123* + ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (LOM) (PRO/1000 XT Network Connection) + +pci:v00008086d0000100Dsv00001079sd0000891F* + ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (LOM) (82544GC Based Network Connection) + +pci:v00008086d0000100Dsv00004C53sd00001080* + ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (LOM) (CT8 mainboard) + +pci:v00008086d0000100Dsv00008086sd0000110D* + ID_MODEL_FROM_DATABASE=82544GC Gigabit Ethernet Controller (LOM) (82544GC Based Network Connection) + +pci:v00008086d0000100E* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller + +pci:v00008086d0000100Esv00001014sd00000265* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d0000100Esv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d0000100Esv00001014sd0000026A* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d0000100Esv00001028sd0000002E* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (Optiplex GX260) + +pci:v00008086d0000100Esv00001028sd00000134* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PowerEdge 600SC) + +pci:v00008086d0000100Esv00001028sd00000151* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (Optiplex GX270) + +pci:v00008086d0000100Esv0000107Bsd00008920* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter) + +pci:v00008086d0000100Esv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (QEMU Virtual Machine) + +pci:v00008086d0000100Esv00008086sd0000001E* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter) + +pci:v00008086d0000100Esv00008086sd0000002E* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter) + +pci:v00008086d0000100Esv00008086sd00001376* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 GT Desktop Adapter) + +pci:v00008086d0000100Esv00008086sd00001476* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (PRO/1000 GT Desktop Adapter) + +pci:v00008086d0000100F* + ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) + +pci:v00008086d0000100Fsv00001014sd00000269* + ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) (iSeries 1000/100/10 Ethernet Adapter) + +pci:v00008086d0000100Fsv00001014sd0000028E* + ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Network Connection) + +pci:v00008086d0000100Fsv000015ADsd00000750* + ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Single Port Adapter) + +pci:v00008086d0000100Fsv00008086sd00001000* + ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Network Connection) + +pci:v00008086d0000100Fsv00008086sd00001001* + ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Copper) (PRO/1000 MT Server Adapter) + +pci:v00008086d00001010* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) + +pci:v00008086d00001010sv00000E11sd000000DB* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (NC7170 Gigabit Server Adapter) + +pci:v00008086d00001010sv00001014sd0000027C* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (PRO/1000 MT Dual Port Network Adapter) + +pci:v00008086d00001010sv000015ADsd00000760* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (PRO/1000 MT Dual Port Adapter) + +pci:v00008086d00001010sv000018FBsd00007872* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (RESlink-X) + +pci:v00008086d00001010sv00001FC1sd00000026* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (Niagara 2260 Bypass Card) + +pci:v00008086d00001010sv00004C53sd00001080* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (CT8 mainboard) + +pci:v00008086d00001010sv00004C53sd000010A0* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (CA3/CR3 mainboard) + +pci:v00008086d00001010sv00008086sd00001011* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (PRO/1000 MT Dual Port Server Adapter) + +pci:v00008086d00001010sv00008086sd00001012* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (PRO/1000 MT Dual Port Server Adapter) + +pci:v00008086d00001010sv00008086sd0000101A* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (PRO/1000 MT Dual Port Network Connection) + +pci:v00008086d00001010sv00008086sd00003424* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Copper) (SE7501HG2 Mainboard) + +pci:v00008086d00001011* + ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Fiber) + +pci:v00008086d00001011sv00001014sd00000268* + ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Fiber) (iSeries Gigabit Ethernet Adapter) + +pci:v00008086d00001011sv00008086sd00001002* + ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Fiber) (PRO/1000 MF Server Adapter) + +pci:v00008086d00001011sv00008086sd00001003* + ID_MODEL_FROM_DATABASE=82545EM Gigabit Ethernet Controller (Fiber) (PRO/1000 MF Server Adapter (LX)) + +pci:v00008086d00001012* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Fiber) + +pci:v00008086d00001012sv00000E11sd000000DC* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Fiber) (NC6170 Gigabit Server Adapter) + +pci:v00008086d00001012sv00008086sd00001012* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (Fiber) (PRO/1000 MF Dual Port Server Adapter) + +pci:v00008086d00001013* + ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller + +pci:v00008086d00001013sv00008086sd00000013* + ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d00001013sv00008086sd00001013* + ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d00001013sv00008086sd00001113* + ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter) + +pci:v00008086d00001014* + ID_MODEL_FROM_DATABASE=82541ER Gigabit Ethernet Controller + +pci:v00008086d00001014sv00008086sd00000014* + ID_MODEL_FROM_DATABASE=82541ER Gigabit Ethernet Controller (PRO/1000 MT Desktop Connection) + +pci:v00008086d00001014sv00008086sd00001014* + ID_MODEL_FROM_DATABASE=82541ER Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d00001015* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (LOM) + +pci:v00008086d00001015sv00008086sd00001015* + ID_MODEL_FROM_DATABASE=82540EM Gigabit Ethernet Controller (LOM) (PRO/1000 MT Mobile Connection) + +pci:v00008086d00001016* + ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) + +pci:v00008086d00001016sv00001014sd0000052C* + ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (PRO/1000 MT Mobile Connection) + +pci:v00008086d00001016sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (PRO/1000 MT Mobile Connection) + +pci:v00008086d00001016sv00008086sd00001016* + ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (PRO/1000 MT Mobile Connection) + +pci:v00008086d00001017* + ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller + +pci:v00008086d00001017sv00008086sd00001017* + ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (PR0/1000 MT Desktop Connection) + +pci:v00008086d00001018* + ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller + +pci:v00008086d00001018sv00008086sd00001018* + ID_MODEL_FROM_DATABASE=82541EI Gigabit Ethernet Controller (PRO/1000 MT Mobile Connection) + +pci:v00008086d00001019* + ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller + +pci:v00008086d00001019sv00001458sd00001019* + ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (GA-8IPE1000 Pro2 motherboard (865PE)) + +pci:v00008086d00001019sv00001458sd0000E000* + ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (Intel Gigabit Ethernet (Kenai II)) + +pci:v00008086d00001019sv00008086sd00001019* + ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (PRO/1000 CT Desktop Connection) + +pci:v00008086d00001019sv00008086sd0000301F* + ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (D865PERL mainboard) + +pci:v00008086d00001019sv00008086sd00003025* + ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (D875PBZ motherboard) + +pci:v00008086d00001019sv00008086sd0000302C* + ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (D865GBF Mainboard) + +pci:v00008086d00001019sv00008086sd00003427* + ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (S875WP1-E mainboard) + +pci:v00008086d0000101A* + ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (Mobile) + +pci:v00008086d0000101Asv00008086sd0000101A* + ID_MODEL_FROM_DATABASE=82547EI Gigabit Ethernet Controller (Mobile) (PRO/1000 CT Mobile Connection) + +pci:v00008086d0000101D* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller + +pci:v00008086d0000101Dsv00008086sd00001000* + ID_MODEL_FROM_DATABASE=82546EB Gigabit Ethernet Controller (PRO/1000 MT Quad Port Server Adapter) + +pci:v00008086d0000101E* + ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) + +pci:v00008086d0000101Esv00001014sd00000549* + ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (Thinkpad) + +pci:v00008086d0000101Esv00001179sd00000001* + ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (PRO/1000 MT Mobile Connection) + +pci:v00008086d0000101Esv00008086sd0000101E* + ID_MODEL_FROM_DATABASE=82540EP Gigabit Ethernet Controller (Mobile) (PRO/1000 MT Mobile Connection) + +pci:v00008086d00001026* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller + +pci:v00008086d00001026sv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (Precision Workstation 670 Mainboard) + +pci:v00008086d00001026sv00001028sd00000169* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (Precision 470) + +pci:v00008086d00001026sv00008086sd00001000* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MT Server Connection) + +pci:v00008086d00001026sv00008086sd00001001* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MT Server Adapter) + +pci:v00008086d00001026sv00008086sd00001002* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MT Server Adapter) + +pci:v00008086d00001026sv00008086sd00001003* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 GT Server Adapter) + +pci:v00008086d00001026sv00008086sd00001026* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MT Server Connection) + +pci:v00008086d00001027* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller + +pci:v00008086d00001027sv0000103Csd00003103* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (NC310F PCI-X Gigabit Server Adapter) + +pci:v00008086d00001027sv00008086sd00001001* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MF Server Adapter(LX)) + +pci:v00008086d00001027sv00008086sd00001002* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MF Server Adapter(LX)) + +pci:v00008086d00001027sv00008086sd00001003* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MF Server Adapter(LX)) + +pci:v00008086d00001027sv00008086sd00001027* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MF Server Adapter) + +pci:v00008086d00001028* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller + +pci:v00008086d00001028sv00008086sd00001028* + ID_MODEL_FROM_DATABASE=82545GM Gigabit Ethernet Controller (PRO/1000 MB Server Connection) + +pci:v00008086d00001029* + ID_MODEL_FROM_DATABASE=82559 Ethernet Controller + +pci:v00008086d00001030* + ID_MODEL_FROM_DATABASE=82559 InBusiness 10/100 + +pci:v00008086d00001031* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller + +pci:v00008086d00001031sv00001014sd00000209* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (ThinkPad A/T/X Series) + +pci:v00008086d00001031sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (Vaio PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00008086d00001031sv0000104Dsd0000813C* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (Vaio PCG-GRV616G) + +pci:v00008086d00001031sv0000107Bsd00005350* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00001031sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00001031sv0000144Dsd0000C000* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00001031sv0000144Dsd0000C001* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00001031sv0000144Dsd0000C003* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00001031sv0000144Dsd0000C006* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller (vpr Matrix 170B4) + +pci:v00008086d00001032* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VE Ethernet Controller + +pci:v00008086d00001033* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VM (LOM) Ethernet Controller + +pci:v00008086d00001034* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VM Ethernet Controller + +pci:v00008086d00001035* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3)/82562EH (LOM) Ethernet Controller + +pci:v00008086d00001036* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) 82562EH Ethernet Controller + +pci:v00008086d00001037* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) Chipset Ethernet Controller + +pci:v00008086d00001038* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VM (KM) Ethernet Controller + +pci:v00008086d00001038sv00000E11sd00000098* + ID_MODEL_FROM_DATABASE=82801CAM (ICH3) PRO/100 VM (KM) Ethernet Controller (Evo N600c) + +pci:v00008086d00001039* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (LOM) Ethernet Controller + +pci:v00008086d00001039sv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (LOM) Ethernet Controller (NetVista A30p) + +pci:v00008086d00001039sv0000114Asd00000582* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (LOM) Ethernet Controller (PC8 onboard ethernet ETH1) + +pci:v00008086d0000103A* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (CNR) Ethernet Controller + +pci:v00008086d0000103B* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VM (LOM) Ethernet Controller + +pci:v00008086d0000103C* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VM (CNR) Ethernet Controller + +pci:v00008086d0000103D* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (MOB) Ethernet Controller + +pci:v00008086d0000103Dsv00001014sd00000522* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (MOB) Ethernet Controller (ThinkPad R40) + +pci:v00008086d0000103Dsv00001028sd00002002* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (MOB) Ethernet Controller (Latitude D500) + +pci:v00008086d0000103Dsv00008086sd0000103D* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VE (MOB) Ethernet Controller (82562EZ 10/100 Ethernet Controller) + +pci:v00008086d0000103E* + ID_MODEL_FROM_DATABASE=82801DB PRO/100 VM (MOB) Ethernet Controller + +pci:v00008086d00001040* + ID_MODEL_FROM_DATABASE=536EP Data Fax Modem + +pci:v00008086d00001040sv000016BEsd00001040* + ID_MODEL_FROM_DATABASE=536EP Data Fax Modem (V.9X DSP Data Fax Modem) + +pci:v00008086d00001043* + ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter + +pci:v00008086d00001043sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter (tc1100 tablet) + +pci:v00008086d00001043sv00008086sd00002522* + ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter (Samsung X10/P30 integrated WLAN) + +pci:v00008086d00001043sv00008086sd00002527* + ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter (MIM2000/Centrino) + +pci:v00008086d00001043sv00008086sd00002561* + ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter (Dell Latitude D800) + +pci:v00008086d00001043sv00008086sd00002581* + ID_MODEL_FROM_DATABASE=PRO/Wireless LAN 2100 3B Mini PCI Adapter (Toshiba Satellite M10) + +pci:v00008086d00001048* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller + +pci:v00008086d00001048sv00008086sd0000A01F* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE LR Server Adapter) + +pci:v00008086d00001048sv00008086sd0000A11F* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE LR Server Adapter) + +pci:v00008086d00001049* + ID_MODEL_FROM_DATABASE=82566MM Gigabit Network Connection + +pci:v00008086d00001049sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82566MM Gigabit Network Connection (Compaq 6910p) + +pci:v00008086d00001049sv000017AAsd000020B9* + ID_MODEL_FROM_DATABASE=82566MM Gigabit Network Connection (ThinkPad T61/R61) + +pci:v00008086d0000104A* + ID_MODEL_FROM_DATABASE=82566DM Gigabit Network Connection + +pci:v00008086d0000104B* + ID_MODEL_FROM_DATABASE=82566DC Gigabit Network Connection + +pci:v00008086d0000104C* + ID_MODEL_FROM_DATABASE=82562V 10/100 Network Connection + +pci:v00008086d0000104D* + ID_MODEL_FROM_DATABASE=82566MC Gigabit Network Connection + +pci:v00008086d0000104E* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10 Gigabit SFP+ + +pci:v00008086d0000104F* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10 Gigabit backplane + +pci:v00008086d00001050* + ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller + +pci:v00008086d00001050sv00001014sd00000287* + ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (ThinkCentre S50) + +pci:v00008086d00001050sv00001028sd0000019D* + ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (Dimension 3000) + +pci:v00008086d00001050sv00001462sd0000728C* + ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (865PE Neo2 (MS-6728)) + +pci:v00008086d00001050sv00001462sd0000758C* + ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (MS-6758 (875P Neo)) + +pci:v00008086d00001050sv00008086sd00003020* + ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (D865PERL mainboard) + +pci:v00008086d00001050sv00008086sd0000302F* + ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (Desktop Board D865GBF) + +pci:v00008086d00001050sv00008086sd00003427* + ID_MODEL_FROM_DATABASE=82562EZ 10/100 Ethernet Controller (S875WP1-E mainboard) + +pci:v00008086d00001051* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) integrated LAN Controller + +pci:v00008086d00001052* + ID_MODEL_FROM_DATABASE=PRO/100 VM Network Connection + +pci:v00008086d00001053* + ID_MODEL_FROM_DATABASE=PRO/100 VM Network Connection + +pci:v00008086d00001054* + ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection + +pci:v00008086d00001055* + ID_MODEL_FROM_DATABASE=PRO/100 VM Network Connection + +pci:v00008086d00001056* + ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection + +pci:v00008086d00001057* + ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection + +pci:v00008086d00001059* + ID_MODEL_FROM_DATABASE=82551QM Ethernet Controller + +pci:v00008086d0000105B* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) + +pci:v00008086d0000105E* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) + +pci:v00008086d0000105Esv0000103Csd00007044* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (NC360T PCI Express Dual Port Gigabit Server Adapter) + +pci:v00008086d0000105Esv0000103Csd0000704E* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (Dual Port 1000Base-T (PCIe) [AD337A]) + +pci:v00008086d0000105Esv00001775sd00001100* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (CR11/VR11 Single Board Computer) + +pci:v00008086d0000105Esv00001775sd00006003* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (Telum GE-QT) + +pci:v00008086d0000105Esv000018DFsd00001214* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (2x 1GbE, PCIe x1, dual Intel 82571EB chips) + +pci:v00008086d0000105Esv00008086sd0000005E* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (PRO/1000 PT Dual Port Server Connection) + +pci:v00008086d0000105Esv00008086sd0000105E* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (PRO/1000 PT Dual Port Network Connection) + +pci:v00008086d0000105Esv00008086sd000010D5* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (82571PT Gigabit PT Quad Port Server ExpressModule) + +pci:v00008086d0000105Esv00008086sd0000115E* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (PRO/1000 PT Dual Port Server Adapter) + +pci:v00008086d0000105Esv00008086sd0000125E* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (PRO/1000 PT Dual Port Server Adapter) + +pci:v00008086d0000105Esv00008086sd0000135E* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) (PRO/1000 PT Dual Port Server Adapter) + +pci:v00008086d0000105F* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller + +pci:v00008086d0000105Fsv0000103Csd0000704F* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Dual Port 1000Base-SX (PCIe) [AD338A]) + +pci:v00008086d0000105Fsv00008086sd0000005A* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PF Dual Port Server Adapter) + +pci:v00008086d0000105Fsv00008086sd0000115F* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PF Dual Port Server Adapter) + +pci:v00008086d0000105Fsv00008086sd0000125F* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PF Dual Port Server Adapter) + +pci:v00008086d0000105Fsv00008086sd0000135F* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PF Dual Port Server Adapter) + +pci:v00008086d00001060* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller + +pci:v00008086d00001060sv00008086sd00000060* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PB Dual Port Server Connection) + +pci:v00008086d00001060sv00008086sd00001060* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PB Dual Port Server Connection) + +pci:v00008086d00001064* + ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller + +pci:v00008086d00001064sv00001043sd000080F8* + ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller (P5GD1-VW Mainboard) + +pci:v00008086d00001065* + ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE Ethernet Controller + +pci:v00008086d00001066* + ID_MODEL_FROM_DATABASE=82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller + +pci:v00008086d00001067* + ID_MODEL_FROM_DATABASE=82562 EM/EX/GX - PRO/100 VM Ethernet Controller + +pci:v00008086d00001068* + ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller Mobile + +pci:v00008086d00001068sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller Mobile (530 Laptop) + +pci:v00008086d00001069* + ID_MODEL_FROM_DATABASE=82562EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller Mobile + +pci:v00008086d0000106A* + ID_MODEL_FROM_DATABASE=82562G - PRO/100 VE (LOM) Ethernet Controller + +pci:v00008086d0000106B* + ID_MODEL_FROM_DATABASE=82562G - PRO/100 VE Ethernet Controller Mobile + +pci:v00008086d00001075* + ID_MODEL_FROM_DATABASE=82547GI Gigabit Ethernet Controller + +pci:v00008086d00001075sv00001028sd00000165* + ID_MODEL_FROM_DATABASE=82547GI Gigabit Ethernet Controller (PowerEdge 750) + +pci:v00008086d00001075sv00008086sd00000075* + ID_MODEL_FROM_DATABASE=82547GI Gigabit Ethernet Controller (PRO/1000 CT Network Connection) + +pci:v00008086d00001075sv00008086sd00001075* + ID_MODEL_FROM_DATABASE=82547GI Gigabit Ethernet Controller (PRO/1000 CT Network Connection) + +pci:v00008086d00001076* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller + +pci:v00008086d00001076sv00001028sd00000165* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d00001076sv00001028sd0000016D* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d00001076sv00001028sd0000019A* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d00001076sv00001028sd0000106D* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d00001076sv00008086sd00000076* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d00001076sv00008086sd00001076* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Connection) + +pci:v00008086d00001076sv00008086sd00001176* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Desktop Adapter) + +pci:v00008086d00001076sv00008086sd00001276* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Network Adapter) + +pci:v00008086d00001077* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller + +pci:v00008086d00001077sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Mobile Connection) + +pci:v00008086d00001077sv00008086sd00000077* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Mobile Connection) + +pci:v00008086d00001077sv00008086sd00001077* + ID_MODEL_FROM_DATABASE=82541GI Gigabit Ethernet Controller (PRO/1000 MT Mobile Connection) + +pci:v00008086d00001078* + ID_MODEL_FROM_DATABASE=82541ER Gigabit Ethernet Controller + +pci:v00008086d00001078sv00008086sd00001078* + ID_MODEL_FROM_DATABASE=82541ER Gigabit Ethernet Controller (82541ER-based Network Connection) + +pci:v00008086d00001079* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller + +pci:v00008086d00001079sv0000103Csd000012A6* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Dual Port 1000Base-T [A9900A]) + +pci:v00008086d00001079sv0000103Csd000012CF* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Core Dual Port 1000Base-T [AB352A]) + +pci:v00008086d00001079sv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (V5D Single Board Computer Gigabit Ethernet) + +pci:v00008086d00001079sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (CE9) + +pci:v00008086d00001079sv00001FC1sd00000027* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Niagara 2261 Failover NIC) + +pci:v00008086d00001079sv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Cx9 / Vx9 mainboard) + +pci:v00008086d00001079sv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (CL9 mainboard) + +pci:v00008086d00001079sv00008086sd00000079* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MT Dual Port Network Connection) + +pci:v00008086d00001079sv00008086sd00001079* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MT Dual Port Network Connection) + +pci:v00008086d00001079sv00008086sd00001179* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MT Dual Port Server Adapter) + +pci:v00008086d00001079sv00008086sd0000117A* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MT Dual Port Server Adapter) + +pci:v00008086d0000107A* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller + +pci:v00008086d0000107Asv0000103Csd000012A8* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Dual Port 1000base-SX [A9899A]) + +pci:v00008086d0000107Asv00008086sd0000107A* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MF Dual Port Server Adapter) + +pci:v00008086d0000107Asv00008086sd0000127A* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MF Dual Port Server Adapter) + +pci:v00008086d0000107B* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller + +pci:v00008086d0000107Bsv00008086sd0000007B* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MB Dual Port Server Connection) + +pci:v00008086d0000107Bsv00008086sd0000107B* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 MB Dual Port Server Connection) + +pci:v00008086d0000107C* + ID_MODEL_FROM_DATABASE=82541PI Gigabit Ethernet Controller + +pci:v00008086d0000107Csv00008086sd00001376* + ID_MODEL_FROM_DATABASE=82541PI Gigabit Ethernet Controller (PRO/1000 GT Desktop Adapter) + +pci:v00008086d0000107Csv00008086sd00001476* + ID_MODEL_FROM_DATABASE=82541PI Gigabit Ethernet Controller (PRO/1000 GT Desktop Adapter) + +pci:v00008086d0000107D* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) + +pci:v00008086d0000107Dsv00008086sd00001082* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (PRO/1000 PT Server Adapter) + +pci:v00008086d0000107Dsv00008086sd00001084* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (PRO/1000 PT Server Adapter) + +pci:v00008086d0000107Dsv00008086sd00001092* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (PRO/1000 PT Server Adapter) + +pci:v00008086d0000107E* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Fiber) + +pci:v00008086d0000107Esv00008086sd00001084* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Fiber) (PRO/1000 PF Server Adapter) + +pci:v00008086d0000107Esv00008086sd00001085* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Fiber) (PRO/1000 PF Server Adapter) + +pci:v00008086d0000107Esv00008086sd00001094* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Fiber) (PRO/1000 PF Server Adapter) + +pci:v00008086d0000107F* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller + +pci:v00008086d00001080* + ID_MODEL_FROM_DATABASE=FA82537EP 56K V.92 Data/Fax Modem PCI + +pci:v00008086d00001081* + ID_MODEL_FROM_DATABASE=631xESB/632xESB LAN Controller Copper + +pci:v00008086d00001082* + ID_MODEL_FROM_DATABASE=631xESB/632xESB LAN Controller fiber + +pci:v00008086d00001083* + ID_MODEL_FROM_DATABASE=631xESB/632xESB LAN Controller SERDES + +pci:v00008086d00001084* + ID_MODEL_FROM_DATABASE=631xESB/632xESB IDE Redirection + +pci:v00008086d00001085* + ID_MODEL_FROM_DATABASE=631xESB/632xESB Serial Port Redirection + +pci:v00008086d00001086* + ID_MODEL_FROM_DATABASE=631xESB/632xESB IPMI/KCS0 + +pci:v00008086d00001087* + ID_MODEL_FROM_DATABASE=631xESB/632xESB UHCI Redirection + +pci:v00008086d00001089* + ID_MODEL_FROM_DATABASE=631xESB/632xESB BT + +pci:v00008086d0000108A* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller + +pci:v00008086d0000108Asv00008086sd0000108A* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 P Dual Port Server Adapter) + +pci:v00008086d0000108Asv00008086sd0000118A* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (PRO/1000 P Dual Port Server Adapter) + +pci:v00008086d0000108B* + ID_MODEL_FROM_DATABASE=82573V Gigabit Ethernet Controller (Copper) + +pci:v00008086d0000108Bsv00001462sd0000176C* + ID_MODEL_FROM_DATABASE=82573V Gigabit Ethernet Controller (Copper) (on board on MSI 945P - NEO (MS-7176)) + +pci:v00008086d0000108C* + ID_MODEL_FROM_DATABASE=82573E Gigabit Ethernet Controller (Copper) + +pci:v00008086d0000108E* + ID_MODEL_FROM_DATABASE=82573E KCS (Active Management) + +pci:v00008086d0000108F* + ID_MODEL_FROM_DATABASE=Active Management Technology - SOL + +pci:v00008086d00001091* + ID_MODEL_FROM_DATABASE=PRO/100 VM Network Connection + +pci:v00008086d00001092* + ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection + +pci:v00008086d00001092sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d00001093* + ID_MODEL_FROM_DATABASE=PRO/100 VM Network Connection + +pci:v00008086d00001094* + ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection + +pci:v00008086d00001095* + ID_MODEL_FROM_DATABASE=PRO/100 VE Network Connection + +pci:v00008086d00001096* + ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Copper) + +pci:v00008086d00001096sv000015D9sd00001096* + ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Copper) (Motherboard) + +pci:v00008086d00001096sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Copper) (X7DVL-E-O motherboard) + +pci:v00008086d00001096sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Copper) (S5000PSLSATA Server Board) + +pci:v00008086d00001097* + ID_MODEL_FROM_DATABASE=631xESB/632xESB DPT LAN Controller (Fiber) + +pci:v00008086d00001098* + ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Serdes) + +pci:v00008086d00001099* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) + +pci:v00008086d00001099sv00008086sd00001099* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) (PRO/1000 GT Quad Port Server Adapter) + +pci:v00008086d0000109A* + ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller + +pci:v00008086d0000109Asv00001179sd0000FF10* + ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (PRO/1000 PL) + +pci:v00008086d0000109Asv000017AAsd00002001* + ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (ThinkPad T60) + +pci:v00008086d0000109Asv000017AAsd0000207E* + ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (ThinkPad X60/X60s) + +pci:v00008086d0000109Asv00008086sd0000109A* + ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (PRO/1000 PL Network Connection) + +pci:v00008086d0000109Asv00008086sd0000309C* + ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (Desktop Board D945GTP) + +pci:v00008086d0000109Asv00008086sd000030A5* + ID_MODEL_FROM_DATABASE=82573L Gigabit Ethernet Controller (Desktop Board D975XBX) + +pci:v00008086d0000109B* + ID_MODEL_FROM_DATABASE=82546GB PRO/1000 GF Quad Port Server Adapter + +pci:v00008086d0000109E* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller + +pci:v00008086d0000109Esv00008086sd0000A01F* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE CX4 Server Adapter) + +pci:v00008086d0000109Esv00008086sd0000A11F* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE CX4 Server Adapter) + +pci:v00008086d000010A0* + ID_MODEL_FROM_DATABASE=82571EB PRO/1000 AT Quad Port Bypass Adapter + +pci:v00008086d000010A1* + ID_MODEL_FROM_DATABASE=82571EB PRO/1000 AF Quad Port Bypass Adapter + +pci:v00008086d000010A4* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller + +pci:v00008086d000010A4sv00008086sd000010A4* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Quad Port Server Adapter) + +pci:v00008086d000010A4sv00008086sd000011A4* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (PRO/1000 PT Quad Port Server Adapter) + +pci:v00008086d000010A5* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Fiber) + +pci:v00008086d000010A5sv00008086sd000010A5* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Fiber) (PRO/1000 PF Quad Port Server Adapter) + +pci:v00008086d000010A5sv00008086sd000010A6* + ID_MODEL_FROM_DATABASE=82571EB Gigabit Ethernet Controller (Fiber) (PRO/1000 PF Quad Port Server Adapter) + +pci:v00008086d000010A6* + ID_MODEL_FROM_DATABASE=82599EB 10-Gigabit Dummy Function + +pci:v00008086d000010A7* + ID_MODEL_FROM_DATABASE=82575EB Gigabit Network Connection + +pci:v00008086d000010A7sv00008086sd000010A8* + ID_MODEL_FROM_DATABASE=82575EB Gigabit Network Connection (82575EB Gigabit Riser Card) + +pci:v00008086d000010A9* + ID_MODEL_FROM_DATABASE=82575EB Gigabit Backplane Connection + +pci:v00008086d000010B0* + ID_MODEL_FROM_DATABASE=82573L PRO/1000 PL Network Connection + +pci:v00008086d000010B2* + ID_MODEL_FROM_DATABASE=82573V PRO/1000 PM Network Connection + +pci:v00008086d000010B3* + ID_MODEL_FROM_DATABASE=82573E PRO/1000 PM Network Connection + +pci:v00008086d000010B4* + ID_MODEL_FROM_DATABASE=82573L PRO/1000 PL Network Connection + +pci:v00008086d000010B5* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) + +pci:v00008086d000010B5sv0000103Csd00003109* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) (NC340T PCI-X Quad-port Gigabit Server Adapter) + +pci:v00008086d000010B5sv00008086sd00001099* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) (PRO/1000 GT Quad Port Server Adapter) + +pci:v00008086d000010B5sv00008086sd00001199* + ID_MODEL_FROM_DATABASE=82546GB Gigabit Ethernet Controller (Copper) (PRO/1000 GT Quad Port Server Adapter) + +pci:v00008086d000010B6* + ID_MODEL_FROM_DATABASE=82598 10GbE PCI-Express Ethernet Controller + +pci:v00008086d000010B9* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) + +pci:v00008086d000010B9sv0000103Csd0000704A* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (110T PCIe Gigabit Server Adapter) + +pci:v00008086d000010B9sv00008086sd00001083* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (PRO/1000 PT Desktop Adapter) + +pci:v00008086d000010B9sv00008086sd00001093* + ID_MODEL_FROM_DATABASE=82572EI Gigabit Ethernet Controller (Copper) (PRO/1000 PT Desktop Adapter) + +pci:v00008086d000010BA* + ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Copper) + +pci:v00008086d000010BB* + ID_MODEL_FROM_DATABASE=80003ES2LAN Gigabit Ethernet Controller (Serdes) + +pci:v00008086d000010BC* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) + +pci:v00008086d000010BCsv00001014sd00000368* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) (4-Port 10/100/1000 Base-TX PCI Express Adapter for POWER) + +pci:v00008086d000010BCsv0000103Csd0000704B* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) (NC364T PCI Express Quad Port Gigabit Server Adapter) + +pci:v00008086d000010BCsv0000108Esd000011BC* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) (Quad Port Adapter) + +pci:v00008086d000010BCsv00008086sd000010BC* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) (PRO/1000 PT Quad Port LP Server Adapter) + +pci:v00008086d000010BCsv00008086sd000011BC* + ID_MODEL_FROM_DATABASE=82571EB/82571GB Gigabit Ethernet Controller (Copper) (PRO/1000 PT Quad Port LP Server Adapter (Kirkwood Low Profile)) + +pci:v00008086d000010BD* + ID_MODEL_FROM_DATABASE=82566DM-2 Gigabit Network Connection + +pci:v00008086d000010BDsv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82566DM-2 Gigabit Network Connection (OptiPlex 755) + +pci:v00008086d000010BF* + ID_MODEL_FROM_DATABASE=82567LF Gigabit Network Connection + +pci:v00008086d000010C0* + ID_MODEL_FROM_DATABASE=82562V-2 10/100 Network Connection + +pci:v00008086d000010C0sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82562V-2 10/100 Network Connection (Inspiron 530) + +pci:v00008086d000010C2* + ID_MODEL_FROM_DATABASE=82562G-2 10/100 Network Connection + +pci:v00008086d000010C3* + ID_MODEL_FROM_DATABASE=82562GT-2 10/100 Network Connection + +pci:v00008086d000010C4* + ID_MODEL_FROM_DATABASE=82562GT 10/100 Network Connection + +pci:v00008086d000010C5* + ID_MODEL_FROM_DATABASE=82562G 10/100 Network Connection + +pci:v00008086d000010C6* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection + +pci:v00008086d000010C6sv00008086sd0000A05F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection (10-Gigabit XF SR Dual Port Server Adapter) + +pci:v00008086d000010C6sv00008086sd0000A15F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection (10-Gigabit XF SR Dual Port Server Adapter) + +pci:v00008086d000010C7* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection + +pci:v00008086d000010C7sv00001014sd0000037F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF SR Server Adapter) + +pci:v00008086d000010C7sv00001014sd00000380* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF LR Server Adapter) + +pci:v00008086d000010C7sv00008086sd0000A05F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF SR Server Adapter) + +pci:v00008086d000010C7sv00008086sd0000A15F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF SR Server Adapter) + +pci:v00008086d000010C7sv00008086sd0000A16F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF SR Server Adapter) + +pci:v00008086d000010C8* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT Network Connection + +pci:v00008086d000010C8sv00008086sd0000A10C* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT Network Connection (10-Gigabit AT Server Adapter) + +pci:v00008086d000010C8sv00008086sd0000A11C* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT Network Connection (10-Gigabit AT Server Adapter) + +pci:v00008086d000010C8sv00008086sd0000A12C* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT Network Connection (10-Gigabit AT Server Adapter) + +pci:v00008086d000010C9* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection + +pci:v00008086d000010C9sv0000103Csd000031EF* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (NC362i Integrated Dual port Gigabit Server Adapter) + +pci:v00008086d000010C9sv0000103Csd0000323F* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (NC362i Integrated Dual port Gigabit Server Adapter) + +pci:v00008086d000010C9sv000010A9sd00008028* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (UV-BaseIO dual-port GbE) + +pci:v00008086d000010C9sv000013A3sd00000037* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (DS4100 Secure Multi-Gigabit Server Adapter with Compression) + +pci:v00008086d000010C9sv000015D9sd0000A811* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (H8DGU) + +pci:v00008086d000010C9sv00008086sd0000A01C* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET Dual Port Server Adapter) + +pci:v00008086d000010C9sv00008086sd0000A03C* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET Dual Port Server Adapter) + +pci:v00008086d000010C9sv00008086sd0000A04C* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET Dual Port Server Adapter) + +pci:v00008086d000010CA* + ID_MODEL_FROM_DATABASE=82576 Virtual Function + +pci:v00008086d000010CB* + ID_MODEL_FROM_DATABASE=82567V Gigabit Network Connection + +pci:v00008086d000010CC* + ID_MODEL_FROM_DATABASE=82567LM-2 Gigabit Network Connection + +pci:v00008086d000010CD* + ID_MODEL_FROM_DATABASE=82567LF-2 Gigabit Network Connection + +pci:v00008086d000010CE* + ID_MODEL_FROM_DATABASE=82567V-2 Gigabit Network Connection + +pci:v00008086d000010D3* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection + +pci:v00008086d000010D3sv0000103Csd00001785* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (NC112i 1-port Ethernet Server Adapter) + +pci:v00008086d000010D3sv0000103Csd00003250* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (NC112T PCI Express single Port Gigabit Server Adapter) + +pci:v00008086d000010D3sv00001043sd00008369* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Motherboard) + +pci:v00008086d000010D3sv00001093sd000076E9* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (PCIe-8233 Ethernet Adapter) + +pci:v00008086d000010D3sv000010A9sd00008029* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Prism XL Single Port Gigabit Ethernet) + +pci:v00008086d000010D3sv000015D9sd00000605* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (X8SIL) + +pci:v00008086d000010D3sv000015D9sd0000060A* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (X7SPA-H/X7SPA-HF Motherboard) + +pci:v00008086d000010D3sv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (C7SIM-Q Motherboard) + +pci:v00008086d000010D3sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Gigabit CT2 Desktop Adapter) + +pci:v00008086d000010D3sv00008086sd00003578* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Server Board S1200BTLR) + +pci:v00008086d000010D3sv00008086sd0000357A* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Server Board S1200BTS) + +pci:v00008086d000010D3sv00008086sd0000A01F* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (Gigabit CT Desktop Adapter) + +pci:v00008086d000010D3sv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (PC1-GROOVE) + +pci:v00008086d000010D3sv0000E4BFsd000050C2* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection (PC2-LIMBO) + +pci:v00008086d000010D4* + ID_MODEL_FROM_DATABASE=Matrox Concord GE (customized Intel 82574) + +pci:v00008086d000010D5* + ID_MODEL_FROM_DATABASE=82571PT Gigabit PT Quad Port Server ExpressModule + +pci:v00008086d000010D6* + ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection + +pci:v00008086d000010D6sv00008086sd000010D6* + ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection (Gigabit VT Quad Port Server Adapter) + +pci:v00008086d000010D6sv00008086sd0000145A* + ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection (Gigabit VT Quad Port Server Adapter) + +pci:v00008086d000010D6sv00008086sd0000147A* + ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection (Gigabit VT Quad Port Server Adapter) + +pci:v00008086d000010D8* + ID_MODEL_FROM_DATABASE=82599EB 10 Gigabit Unprogrammed + +pci:v00008086d000010D9* + ID_MODEL_FROM_DATABASE=82571EB Dual Port Gigabit Mezzanine Adapter + +pci:v00008086d000010D9sv0000103Csd00001716* + ID_MODEL_FROM_DATABASE=82571EB Dual Port Gigabit Mezzanine Adapter (NC360m Dual Port 1GbE BL-c Adapter) + +pci:v00008086d000010DA* + ID_MODEL_FROM_DATABASE=82571EB Quad Port Gigabit Mezzanine Adapter + +pci:v00008086d000010DAsv0000103Csd00001717* + ID_MODEL_FROM_DATABASE=82571EB Quad Port Gigabit Mezzanine Adapter (NC364m Quad Port 1GbE BL-c Adapter) + +pci:v00008086d000010DB* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit Dual Port Network Connection + +pci:v00008086d000010DD* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT CX4 Network Connection + +pci:v00008086d000010DE* + ID_MODEL_FROM_DATABASE=82567LM-3 Gigabit Network Connection + +pci:v00008086d000010DF* + ID_MODEL_FROM_DATABASE=82567LF-3 Gigabit Network Connection + +pci:v00008086d000010E1* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection + +pci:v00008086d000010E1sv00008086sd0000A15F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection (10-Gigabit SR Dual Port Express Module) + +pci:v00008086d000010E2* + ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection + +pci:v00008086d000010E2sv00008086sd000010E2* + ID_MODEL_FROM_DATABASE=82575GB Gigabit Network Connection (Gigabit VT Quad Port Server Adapter) + +pci:v00008086d000010E5* + ID_MODEL_FROM_DATABASE=82567LM-4 Gigabit Network Connection + +pci:v00008086d000010E6* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection + +pci:v00008086d000010E6sv00008086sd0000A01F* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit EF Dual Port Server Adapter) + +pci:v00008086d000010E6sv00008086sd0000A02F* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit EF Dual Port Server Adapter) + +pci:v00008086d000010E7* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection + +pci:v00008086d000010E7sv0000103Csd000031FF* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (NC362i Integrated Dual Port BL-c Gigabit Server Adapter) + +pci:v00008086d000010E8* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection + +pci:v00008086d000010E8sv00008086sd0000A02B* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET Quad Port Server Adapter) + +pci:v00008086d000010E8sv00008086sd0000A02C* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET Quad Port Server Adapter) + +pci:v00008086d000010EA* + ID_MODEL_FROM_DATABASE=82577LM Gigabit Network Connection + +pci:v00008086d000010EAsv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=82577LM Gigabit Network Connection (Latitude E6410) + +pci:v00008086d000010EAsv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=82577LM Gigabit Network Connection (Latitude E6510) + +pci:v00008086d000010EAsv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=82577LM Gigabit Network Connection (PC1-GROOVE) + +pci:v00008086d000010EB* + ID_MODEL_FROM_DATABASE=82577LC Gigabit Network Connection + +pci:v00008086d000010EC* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT CX4 Network Connection + +pci:v00008086d000010ECsv00008086sd0000A01F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT CX4 Network Connection (10-Gigabit CX4 Dual Port Server Adapter) + +pci:v00008086d000010ECsv00008086sd0000A11F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT CX4 Network Connection (10-Gigabit CX4 Dual Port Server Adapter) + +pci:v00008086d000010ED* + ID_MODEL_FROM_DATABASE=82599 Ethernet Controller Virtual Function + +pci:v00008086d000010EF* + ID_MODEL_FROM_DATABASE=82578DM Gigabit Network Connection + +pci:v00008086d000010EFsv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=82578DM Gigabit Network Connection (OptiPlex 980) + +pci:v00008086d000010EFsv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=82578DM Gigabit Network Connection (C7SIM-Q Motherboard) + +pci:v00008086d000010F0* + ID_MODEL_FROM_DATABASE=82578DC Gigabit Network Connection + +pci:v00008086d000010F1* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection + +pci:v00008086d000010F1sv00008086sd0000A20F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection (10-Gigabit AF DA Dual Port Server Adapter) + +pci:v00008086d000010F1sv00008086sd0000A21F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Dual Port Network Connection (10-Gigabit AF DA Dual Port Server Adapter) + +pci:v00008086d000010F4* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection + +pci:v00008086d000010F4sv00008086sd0000106F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF LR Server Adapter) + +pci:v00008086d000010F4sv00008086sd0000A06F* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AF Network Connection (10-Gigabit XF LR Server Adapter) + +pci:v00008086d000010F5* + ID_MODEL_FROM_DATABASE=82567LM Gigabit Network Connection + +pci:v00008086d000010F5sv000017AAsd000020EE* + ID_MODEL_FROM_DATABASE=82567LM Gigabit Network Connection (ThinkPad T400) + +pci:v00008086d000010F6* + ID_MODEL_FROM_DATABASE=82574L Gigabit Network Connection + +pci:v00008086d000010F7* + ID_MODEL_FROM_DATABASE=10 Gigabit BR KX4 Dual Port Network Connection + +pci:v00008086d000010F7sv0000108Esd00007B12* + ID_MODEL_FROM_DATABASE=10 Gigabit BR KX4 Dual Port Network Connection (Sun Dual 10GbE PCIe 2.0 FEM) + +pci:v00008086d000010F7sv00008086sd0000000D* + ID_MODEL_FROM_DATABASE=10 Gigabit BR KX4 Dual Port Network Connection (Ethernet Mezzanine Adapter X520-KX4-2) + +pci:v00008086d000010F8* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection + +pci:v00008086d000010F8sv00001028sd00001F63* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (10GbE 2P X520k bNDC) + +pci:v00008086d000010F8sv0000103Csd000017D2* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (Ethernet 10Gb 2-port 560M Adapter) + +pci:v00008086d000010F8sv0000103Csd000018D0* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (Ethernet 10Gb 2-port 560FLB Adapter) + +pci:v00008086d000010F8sv00001059sd00000111* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (T4007 10GbE interface) + +pci:v00008086d000010F8sv00001059sd00000130* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (T4009 10GbE interface) + +pci:v00008086d000010F8sv00008086sd0000000C* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection (Ethernet X520 10GbE Dual Port KX4-KR Mezz) + +pci:v00008086d000010F9* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Network Connection + +pci:v00008086d000010FB* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection + +pci:v00008086d000010FBsv00001028sd00001F72* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10G 4P X520/I350 rNDC) + +pci:v00008086d000010FBsv0000103Csd000017D0* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 2-port 560FLR-SFP+ Adapter) + +pci:v00008086d000010FBsv0000103Csd000017D2* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 2-port 560M Adapter) + +pci:v00008086d000010FBsv0000103Csd000017D3* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 2-port 560SFP+ Adapter) + +pci:v00008086d000010FBsv0000103Csd0000211B* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 1-port P560FLR-SFP+ Adapter) + +pci:v00008086d000010FBsv0000103Csd00002147* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 1-port 561i Adapter) + +pci:v00008086d000010FBsv0000103Csd00002159* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet 10Gb 2-port 562i Adapter) + +pci:v00008086d000010FBsv0000108Esd00007B11* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) + +pci:v00008086d000010FBsv00001170sd0000004C* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (82599 DP 10G Mezzanine Adapter) + +pci:v00008086d000010FBsv000015D9sd00000611* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (AOC-STGN-I2S [REV 1.01]) + +pci:v00008086d000010FBsv00001734sd000011A9* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (10 Gigabit Dual Port Network Connection) + +pci:v00008086d000010FBsv000017AAsd00001071* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (ThinkServer X520-2 AnyFabric) + +pci:v00008086d000010FBsv000017AAsd00004007* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection + +pci:v00008086d000010FBsv000017AAsd0000402B* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (82599ES 10Gb 2-port Server Adapter X520-DA2) + +pci:v00008086d000010FBsv000017AAsd0000402F* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (FPGA Card XC7VX690T-3FFG1157E) + +pci:v00008086d000010FBsv000018D4sd00000C09* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (82599ES 10Gb 2-port SFP+ OCP Mezz Card MOP81-I-10GS2) + +pci:v00008086d000010FBsv0000193Dsd00001004* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (560F-B) + +pci:v00008086d000010FBsv00001BD4sd0000001B* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (10G SFP+ DP ER102Fi4 Rack Adapter) + +pci:v00008086d000010FBsv00001BD4sd0000002F* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (10G SFP+ DP EP102Fi4A Adapter) + +pci:v00008086d000010FBsv00001BD4sd00000032* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (10G SFP+ DP EP102Fi4 Adapter) + +pci:v00008086d000010FBsv00008086sd00000002* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-DA2) + +pci:v00008086d000010FBsv00008086sd00000003* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) + +pci:v00008086d000010FBsv00008086sd00000006* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-1) + +pci:v00008086d000010FBsv00008086sd00000008* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet OCP Server Adapter X520-2) + +pci:v00008086d000010FBsv00008086sd0000000A* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-1) + +pci:v00008086d000010FBsv00008086sd0000000C* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) + +pci:v00008086d000010FBsv00008086sd000010A6* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (82599ES 10Gb 2 port Server Adapter X520-DA2) + +pci:v00008086d000010FBsv00008086sd00007A11* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) + +pci:v00008086d000010FBsv00008086sd00007A12* + ID_MODEL_FROM_DATABASE=82599ES 10-Gigabit SFI/SFP+ Network Connection (Ethernet Server Adapter X520-2) + +pci:v00008086d000010FC* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Network Connection + +pci:v00008086d000010FE* + ID_MODEL_FROM_DATABASE=82552 10/100 Network Connection + +pci:v00008086d00001107* + ID_MODEL_FROM_DATABASE=PRO/1000 MF Server Adapter (LX) + +pci:v00008086d00001130* + ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub + +pci:v00008086d00001130sv00001025sd00001016* + ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (Travelmate 612 TX) + +pci:v00008086d00001130sv00001043sd00008027* + ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (TUSL2-C Mainboard) + +pci:v00008086d00001130sv0000104Dsd000080DF* + ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (Vaio PCG-FX403) + +pci:v00008086d00001130sv00008086sd00004532* + ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (Desktop Board D815EEA2/D815EFV) + +pci:v00008086d00001130sv00008086sd00004557* + ID_MODEL_FROM_DATABASE=82815 815 Chipset Host Bridge and Memory Controller Hub (D815EGEW Mainboard) + +pci:v00008086d00001131* + ID_MODEL_FROM_DATABASE=82815 815 Chipset AGP Bridge + +pci:v00008086d00001132* + ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) + +pci:v00008086d00001132sv00001025sd00001016* + ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (Travelmate 612 TX) + +pci:v00008086d00001132sv0000103Csd00002001* + ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (e-pc 40) + +pci:v00008086d00001132sv0000104Dsd000080DF* + ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (Vaio PCG-FX403) + +pci:v00008086d00001132sv00008086sd00004532* + ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (Desktop Board D815EEA2/D815EFV) + +pci:v00008086d00001132sv00008086sd00004541* + ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (D815EEA Motherboard) + +pci:v00008086d00001132sv00008086sd00004557* + ID_MODEL_FROM_DATABASE=82815 Chipset Graphics Controller (CGC) (D815EGEW Mainboard) + +pci:v00008086d00001161* + ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Advanced Programmable Interrupt Controller + +pci:v00008086d00001161sv00008086sd00001161* + ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Advanced Programmable Interrupt Controller (82806AA PCI64 Hub APIC) + +pci:v00008086d00001162* + ID_MODEL_FROM_DATABASE=Xscale 80200 Big Endian Companion Chip + +pci:v00008086d00001190* + ID_MODEL_FROM_DATABASE=Merrifield SD/SDIO/eMMC Controller + +pci:v00008086d00001191* + ID_MODEL_FROM_DATABASE=Merrifield Serial IO HSUART Controller + +pci:v00008086d00001192* + ID_MODEL_FROM_DATABASE=Merrifield Serial IO HSUART DMA Controller + +pci:v00008086d00001194* + ID_MODEL_FROM_DATABASE=Merrifield Serial IO SPI Controller + +pci:v00008086d00001195* + ID_MODEL_FROM_DATABASE=Merrifield Serial IO I2C Controller + +pci:v00008086d00001196* + ID_MODEL_FROM_DATABASE=Merrifield Serial IO I2C Controller + +pci:v00008086d00001199* + ID_MODEL_FROM_DATABASE=Merrifield GPIO Controller + +pci:v00008086d0000119E* + ID_MODEL_FROM_DATABASE=Merrifield USB Device Controller (OTG) + +pci:v00008086d000011A0* + ID_MODEL_FROM_DATABASE=Merrifield SCU IPC + +pci:v00008086d000011A1* + ID_MODEL_FROM_DATABASE=Merrifield Power Management Unit + +pci:v00008086d000011A2* + ID_MODEL_FROM_DATABASE=Merrifield Serial IO DMA Controller + +pci:v00008086d000011A5* + ID_MODEL_FROM_DATABASE=Merrifield Serial IO PWM Controller + +pci:v00008086d000011C3* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 PCIe Root Port 0 + +pci:v00008086d000011C4* + ID_MODEL_FROM_DATABASE=Quark SoC X1000 PCIe Root Port 1 + +pci:v00008086d00001200* + ID_MODEL_FROM_DATABASE=IXP1200 Network Processor + +pci:v00008086d00001200sv0000172Asd00000000* + ID_MODEL_FROM_DATABASE=IXP1200 Network Processor (AEP SSL Accelerator) + +pci:v00008086d00001209* + ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller + +pci:v00008086d00001209sv0000140Bsd00000610* + ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller (PMC610 quad Ethernet board) + +pci:v00008086d00001209sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller (QEMU Virtual Machine) + +pci:v00008086d00001209sv00004C53sd00001050* + ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller (CT7 mainboard) + +pci:v00008086d00001209sv00004C53sd00001051* + ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller (CE7 mainboard) + +pci:v00008086d00001209sv00004C53sd00001070* + ID_MODEL_FROM_DATABASE=8255xER/82551IT Fast Ethernet Controller (PC6 mainboard) + +pci:v00008086d00001221* + ID_MODEL_FROM_DATABASE=82092AA PCI to PCMCIA Bridge + +pci:v00008086d00001222* + ID_MODEL_FROM_DATABASE=82092AA IDE Controller + +pci:v00008086d00001223* + ID_MODEL_FROM_DATABASE=SAA7116 + +pci:v00008086d00001225* + ID_MODEL_FROM_DATABASE=82452KX/GX [Orion] + +pci:v00008086d00001226* + ID_MODEL_FROM_DATABASE=82596 PRO/10 PCI + +pci:v00008086d00001227* + ID_MODEL_FROM_DATABASE=82865 EtherExpress PRO/100A + +pci:v00008086d00001228* + ID_MODEL_FROM_DATABASE=82556 EtherExpress PRO/100 Smart + +pci:v00008086d00001229* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 + +pci:v00008086d00001229sv00000E11sd00003001* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) + +pci:v00008086d00001229sv00000E11sd00003002* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) + +pci:v00008086d00001229sv00000E11sd00003003* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) + +pci:v00008086d00001229sv00000E11sd00003004* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) + +pci:v00008086d00001229sv00000E11sd00003005* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) + +pci:v00008086d00001229sv00000E11sd00003006* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) + +pci:v00008086d00001229sv00000E11sd00003007* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN*) + +pci:v00008086d00001229sv00000E11sd0000B01E* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3120 Fast Ethernet NIC) + +pci:v00008086d00001229sv00000E11sd0000B01F* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3122 Fast Ethernet NIC (dual port)) + +pci:v00008086d00001229sv00000E11sd0000B02F* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC1120 Ethernet NIC) + +pci:v00008086d00001229sv00000E11sd0000B04A* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (Netelligent 10/100TX NIC with Wake on LAN) + +pci:v00008086d00001229sv00000E11sd0000B0C6* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3161 Fast Ethernet NIC (embedded, WOL)) + +pci:v00008086d00001229sv00000E11sd0000B0C7* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3160 Fast Ethernet NIC (embedded)) + +pci:v00008086d00001229sv00000E11sd0000B0D7* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3121 Fast Ethernet NIC (WOL)) + +pci:v00008086d00001229sv00000E11sd0000B0DD* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3131 Fast Ethernet NIC (dual port)) + +pci:v00008086d00001229sv00000E11sd0000B0DE* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3132 Fast Ethernet Module (dual port)) + +pci:v00008086d00001229sv00000E11sd0000B0E1* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3133 Fast Ethernet Module (100-FX)) + +pci:v00008086d00001229sv00000E11sd0000B134* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3163 Fast Ethernet NIC (embedded, WOL)) + +pci:v00008086d00001229sv00000E11sd0000B13C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3162 Fast Ethernet NIC (embedded)) + +pci:v00008086d00001229sv00000E11sd0000B144* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3123 Fast Ethernet NIC (WOL)) + +pci:v00008086d00001229sv00000E11sd0000B163* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3134 Fast Ethernet NIC (dual port)) + +pci:v00008086d00001229sv00000E11sd0000B164* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC3135 Fast Ethernet Upgrade Module (dual port)) + +pci:v00008086d00001229sv00000E11sd0000B1A4* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NC7131 Gigabit Server Adapter) + +pci:v00008086d00001229sv00001014sd0000005C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82558B Ethernet Pro 10/100) + +pci:v00008086d00001229sv00001014sd000001BC* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LAN On Motherboard) + +pci:v00008086d00001229sv00001014sd000001F1* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Ethernet Server Adapter) + +pci:v00008086d00001229sv00001014sd000001F2* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Ethernet Server Adapter) + +pci:v00008086d00001229sv00001014sd00000207* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (Ethernet Pro/100 S) + +pci:v00008086d00001229sv00001014sd00000232* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Dual Port Server Adapter) + +pci:v00008086d00001229sv00001014sd0000023A* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (ThinkPad R30) + +pci:v00008086d00001229sv00001014sd0000105C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (Netfinity 10/100) + +pci:v00008086d00001229sv00001014sd00002205* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (ThinkPad A22p) + +pci:v00008086d00001229sv00001014sd0000305C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 EtherJet Management Adapter) + +pci:v00008086d00001229sv00001014sd0000405C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 EtherJet Adapter with Alert on LAN) + +pci:v00008086d00001229sv00001014sd0000505C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 EtherJet Secure Management Adapter) + +pci:v00008086d00001229sv00001014sd0000605C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 EtherJet Secure Management Adapter) + +pci:v00008086d00001229sv00001014sd0000705C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Netfinity 10/100 Ethernet Security Adapter) + +pci:v00008086d00001229sv00001014sd0000805C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Netfinity 10/100 Ethernet Security Adapter) + +pci:v00008086d00001229sv00001028sd0000009B* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Ethernet Server Adapter) + +pci:v00008086d00001229sv00001028sd000000CE* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (10/100 Ethernet Server Adapter) + +pci:v00008086d00001229sv00001033sd00008000* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PC-9821X-B06) + +pci:v00008086d00001229sv00001033sd00008016* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PK-UG-X006) + +pci:v00008086d00001229sv00001033sd0000801F* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PK-UG-X006) + +pci:v00008086d00001229sv00001033sd00008026* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PK-UG-X006) + +pci:v00008086d00001229sv00001033sd00008063* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559-based Fast Ethernet Adapter) + +pci:v00008086d00001229sv00001033sd00008064* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559-based Fast Ethernet Adapter) + +pci:v00008086d00001229sv0000103Csd000010C0* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) + +pci:v00008086d00001229sv0000103Csd000010C3* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) + +pci:v00008086d00001229sv0000103Csd000010CA* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) + +pci:v00008086d00001229sv0000103Csd000010CB* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) + +pci:v00008086d00001229sv0000103Csd000010E3* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) + +pci:v00008086d00001229sv0000103Csd000010E4* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) + +pci:v00008086d00001229sv0000103Csd00001200* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NetServer 10/100TX) + +pci:v00008086d00001229sv0000108Esd000010CF* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100(B)) + +pci:v00008086d00001229sv000010C3sd00001100* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (SmartEther100 SC1100) + +pci:v00008086d00001229sv000010CFsd00001115* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (8255x-based Ethernet Adapter (10/100)) + +pci:v00008086d00001229sv000010CFsd00001143* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (8255x-based Ethernet Adapter (10/100)) + +pci:v00008086d00001229sv0000110Asd0000008B* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82551QM Fast Ethernet Multifuction PCI/CardBus Controller) + +pci:v00008086d00001229sv0000114Asd00000582* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PC8 onboard ethernet ETH2) + +pci:v00008086d00001229sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (8255x-based Ethernet Adapter (10/100)) + +pci:v00008086d00001229sv00001179sd00000002* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PCI FastEther LAN on Docker) + +pci:v00008086d00001229sv00001179sd00000003* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (8255x-based Fast Ethernet) + +pci:v00008086d00001229sv00001259sd00002560* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (AT-2560 100) + +pci:v00008086d00001229sv00001259sd00002561* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (AT-2560 100 FX Ethernet Adapter) + +pci:v00008086d00001229sv00001266sd00000001* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (NE10/100 Adapter) + +pci:v00008086d00001229sv000013E9sd00001000* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (6221L-4U) + +pci:v00008086d00001229sv0000144Dsd00002501* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (SEM-2000 MiniPCI LAN Adapter) + +pci:v00008086d00001229sv0000144Dsd00002502* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (SEM-2100IL MiniPCI LAN Adapter) + +pci:v00008086d00001229sv00001668sd00001100* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100B (TX) (MiniPCI Ethernet+Modem)) + +pci:v00008086d00001229sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (CR11/VR11 Single Board Computer) + +pci:v00008086d00001229sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (CE9) + +pci:v00008086d00001229sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (QEMU Virtual Machine) + +pci:v00008086d00001229sv00004C53sd00001080* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (CT8 mainboard) + +pci:v00008086d00001229sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (PSL09 PrPMC) + +pci:v00008086d00001229sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100B (TX)) + +pci:v00008086d00001229sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100B (T4)) + +pci:v00008086d00001229sv00008086sd00000003* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/10+) + +pci:v00008086d00001229sv00008086sd00000004* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 WfM) + +pci:v00008086d00001229sv00008086sd00000005* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82557 10/100) + +pci:v00008086d00001229sv00008086sd00000006* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82557 10/100 with Wake on LAN) + +pci:v00008086d00001229sv00008086sd00000007* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82558 10/100 Adapter) + +pci:v00008086d00001229sv00008086sd00000008* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82558 10/100 with Wake on LAN) + +pci:v00008086d00001229sv00008086sd00000009* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82558B PRO/100+ PCI (TP)) + +pci:v00008086d00001229sv00008086sd0000000A* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Management Adapter) + +pci:v00008086d00001229sv00008086sd0000000B* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+) + +pci:v00008086d00001229sv00008086sd0000000C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Management Adapter) + +pci:v00008086d00001229sv00008086sd0000000D* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Alert On LAN II* Adapter) + +pci:v00008086d00001229sv00008086sd0000000E* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Management Adapter with Alert On LAN*) + +pci:v00008086d00001229sv00008086sd0000000F* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Desktop Adapter) + +pci:v00008086d00001229sv00008086sd00000010* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Management Adapter) + +pci:v00008086d00001229sv00008086sd00000011* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Management Adapter) + +pci:v00008086d00001229sv00008086sd00000012* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Advanced Management Adapter (D)) + +pci:v00008086d00001229sv00008086sd00000013* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Advanced Management Adapter (E)) + +pci:v00008086d00001229sv00008086sd00000030* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Management Adapter with Alert On LAN* GC) + +pci:v00008086d00001229sv00008086sd00000031* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Desktop Adapter) + +pci:v00008086d00001229sv00008086sd00000040* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Desktop Adapter) + +pci:v00008086d00001229sv00008086sd00000041* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Desktop Adapter) + +pci:v00008086d00001229sv00008086sd00000042* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Desktop Adapter) + +pci:v00008086d00001229sv00008086sd00000050* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Desktop Adapter) + +pci:v00008086d00001229sv00008086sd00001009* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Server Adapter) + +pci:v00008086d00001229sv00008086sd0000100C* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Server Adapter (PILA8470B)) + +pci:v00008086d00001229sv00008086sd00001012* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Server Adapter (D)) + +pci:v00008086d00001229sv00008086sd00001013* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Server Adapter (E)) + +pci:v00008086d00001229sv00008086sd00001015* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Dual Port Server Adapter) + +pci:v00008086d00001229sv00008086sd00001017* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Dual Port Server Adapter) + +pci:v00008086d00001229sv00008086sd00001030* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Management Adapter with Alert On LAN* G Server) + +pci:v00008086d00001229sv00008086sd00001040* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Server Adapter) + +pci:v00008086d00001229sv00008086sd00001041* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Server Adapter) + +pci:v00008086d00001229sv00008086sd00001042* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Server Adapter) + +pci:v00008086d00001229sv00008086sd00001050* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Server Adapter) + +pci:v00008086d00001229sv00008086sd00001051* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Server Adapter) + +pci:v00008086d00001229sv00008086sd00001052* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Server Adapter) + +pci:v00008086d00001229sv00008086sd000010F0* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ Dual Port Adapter) + +pci:v00008086d00001229sv00008086sd00001229* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82557/8/9 [Ethernet Pro 100]) + +pci:v00008086d00001229sv00008086sd00002009* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Mobile Adapter) + +pci:v00008086d00001229sv00008086sd0000200D* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Cardbus) + +pci:v00008086d00001229sv00008086sd0000200E* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 LAN+V90 Cardbus Modem) + +pci:v00008086d00001229sv00008086sd0000200F* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SR Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002010* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Mobile Combo Adapter) + +pci:v00008086d00001229sv00008086sd00002013* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SR Mobile Combo Adapter) + +pci:v00008086d00001229sv00008086sd00002016* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002017* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Combo Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002018* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SR Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002019* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SR Combo Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002101* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 P Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002102* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002103* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002104* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002105* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002106* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 P Mobile Adapter) + +pci:v00008086d00001229sv00008086sd00002107* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Network Connection) + +pci:v00008086d00001229sv00008086sd00002108* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Network Connection) + +pci:v00008086d00001229sv00008086sd00002200* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 P Mobile Combo Adapter) + +pci:v00008086d00001229sv00008086sd00002201* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 P Mobile Combo Adapter) + +pci:v00008086d00001229sv00008086sd00002202* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Combo Adapter) + +pci:v00008086d00001229sv00008086sd00002203* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd00002204* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd00002205* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Combo Adapter) + +pci:v00008086d00001229sv00008086sd00002206* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Combo Adapter) + +pci:v00008086d00001229sv00008086sd00002207* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 SP Mobile Combo Adapter) + +pci:v00008086d00001229sv00008086sd00002208* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 P Mobile Combo Adapter) + +pci:v00008086d00001229sv00008086sd00002402* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd00002407* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd00002408* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd00002409* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd0000240F* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd00002410* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd00002411* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd00002412* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd00002413* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100+ MiniPCI) + +pci:v00008086d00001229sv00008086sd00003000* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LAN on Motherboard) + +pci:v00008086d00001229sv00008086sd00003001* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Basic Alert on LAN*) + +pci:v00008086d00001229sv00008086sd00003002* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (82559 Fast Ethernet LOM with Alert on LAN II*) + +pci:v00008086d00001229sv00008086sd00003006* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Network Connection) + +pci:v00008086d00001229sv00008086sd00003007* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Network Connection) + +pci:v00008086d00001229sv00008086sd00003008* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Network Connection) + +pci:v00008086d00001229sv00008086sd00003010* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Network Connection) + +pci:v00008086d00001229sv00008086sd00003011* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 S Network Connection) + +pci:v00008086d00001229sv00008086sd00003012* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (EtherExpress PRO/100 Network Connection) + +pci:v00008086d00001229sv00008086sd0000301A* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (S845WD1-E mainboard) + +pci:v00008086d00001229sv00008086sd00003411* + ID_MODEL_FROM_DATABASE=82557/8/9/0/1 Ethernet Pro 100 (SDS2 Mainboard) + +pci:v00008086d0000122D* + ID_MODEL_FROM_DATABASE=430FX - 82437FX TSC [Triton I] + +pci:v00008086d0000122E* + ID_MODEL_FROM_DATABASE=82371FB PIIX ISA [Triton I] + +pci:v00008086d00001230* + ID_MODEL_FROM_DATABASE=82371FB PIIX IDE [Triton I] + +pci:v00008086d00001231* + ID_MODEL_FROM_DATABASE=DSVD Modem + +pci:v00008086d00001234* + ID_MODEL_FROM_DATABASE=430MX - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX) + +pci:v00008086d00001235* + ID_MODEL_FROM_DATABASE=430MX - 82437MX Mob. System Ctrlr (MTSC) & 82438MX Data Path (MTDP) + +pci:v00008086d00001237* + ID_MODEL_FROM_DATABASE=440FX - 82441FX PMC [Natoma] + +pci:v00008086d00001237sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=440FX - 82441FX PMC [Natoma] (Qemu virtual machine) + +pci:v00008086d00001239* + ID_MODEL_FROM_DATABASE=82371FB PIIX IDE Interface + +pci:v00008086d0000123B* + ID_MODEL_FROM_DATABASE=82380PB PCI to PCI Docking Bridge + +pci:v00008086d0000123C* + ID_MODEL_FROM_DATABASE=82380AB (MISA) Mobile PCI-to-ISA Bridge + +pci:v00008086d0000123D* + ID_MODEL_FROM_DATABASE=683053 Programmable Interrupt Device + +pci:v00008086d0000123E* + ID_MODEL_FROM_DATABASE=82466GX (IHPC) Integrated Hot-Plug Controller (hidden mode) + +pci:v00008086d0000123F* + ID_MODEL_FROM_DATABASE=82466GX Integrated Hot-Plug Controller (IHPC) + +pci:v00008086d00001240* + ID_MODEL_FROM_DATABASE=82752 (752) AGP Graphics Accelerator + +pci:v00008086d0000124B* + ID_MODEL_FROM_DATABASE=82380FB (MPCI2) Mobile Docking Controller + +pci:v00008086d00001250* + ID_MODEL_FROM_DATABASE=430HX - 82439HX TXC [Triton II] + +pci:v00008086d00001360* + ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub PCI Bridge + +pci:v00008086d00001361* + ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Controller (HRes) + +pci:v00008086d00001361sv00008086sd00001361* + ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Controller (HRes) + +pci:v00008086d00001361sv00008086sd00008000* + ID_MODEL_FROM_DATABASE=82806AA PCI64 Hub Controller (HRes) + +pci:v00008086d00001460* + ID_MODEL_FROM_DATABASE=82870P2 P64H2 Hub PCI Bridge + +pci:v00008086d00001461* + ID_MODEL_FROM_DATABASE=82870P2 P64H2 I/OxAPIC + +pci:v00008086d00001461sv000015D9sd00003480* + ID_MODEL_FROM_DATABASE=82870P2 P64H2 I/OxAPIC (P4DP6) + +pci:v00008086d00001461sv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=82870P2 P64H2 I/OxAPIC (Cx9/Vx9 mainboard) + +pci:v00008086d00001462* + ID_MODEL_FROM_DATABASE=82870P2 P64H2 Hot Plug Controller + +pci:v00008086d00001501* + ID_MODEL_FROM_DATABASE=82567V-3 Gigabit Network Connection + +pci:v00008086d00001502* + ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Lewisville) + +pci:v00008086d00001502sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Lewisville) (Precision M4600) + +pci:v00008086d00001502sv000017AAsd000021CE* + ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Lewisville) (ThinkPad T520) + +pci:v00008086d00001502sv00008086sd00003578* + ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Lewisville) (Server Board S1200BTLR) + +pci:v00008086d00001502sv00008086sd0000357A* + ID_MODEL_FROM_DATABASE=82579LM Gigabit Network Connection (Lewisville) (Server Board S1200BTS) + +pci:v00008086d00001503* + ID_MODEL_FROM_DATABASE=82579V Gigabit Network Connection + +pci:v00008086d00001503sv00001043sd0000849C* + ID_MODEL_FROM_DATABASE=82579V Gigabit Network Connection (P8P67 Deluxe Motherboard) + +pci:v00008086d00001503sv000010CFsd0000161C* + ID_MODEL_FROM_DATABASE=82579V Gigabit Network Connection (LIFEBOOK E752) + +pci:v00008086d00001507* + ID_MODEL_FROM_DATABASE=Ethernet Express Module X520-P2 + +pci:v00008086d00001508* + ID_MODEL_FROM_DATABASE=82598EB Gigabit BX Network Connection + +pci:v00008086d00001509* + ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection + +pci:v00008086d0000150A* + ID_MODEL_FROM_DATABASE=82576NS Gigabit Network Connection + +pci:v00008086d0000150B* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT2 Server Adapter + +pci:v00008086d0000150Bsv00008086sd0000A10C* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT2 Server Adapter + +pci:v00008086d0000150Bsv00008086sd0000A11C* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT2 Server Adapter + +pci:v00008086d0000150Bsv00008086sd0000A12C* + ID_MODEL_FROM_DATABASE=82598EB 10-Gigabit AT2 Server Adapter + +pci:v00008086d0000150C* + ID_MODEL_FROM_DATABASE=82583V Gigabit Network Connection + +pci:v00008086d0000150D* + ID_MODEL_FROM_DATABASE=82576 Gigabit Backplane Connection + +pci:v00008086d0000150Dsv00008086sd0000A10C* + ID_MODEL_FROM_DATABASE=82576 Gigabit Backplane Connection (Gigabit ET Quad Port Mezzanine Card) + +pci:v00008086d0000150E* + ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection + +pci:v00008086d0000150Esv0000103Csd00001780* + ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection (NC365T 4-port Ethernet Server Adapter) + +pci:v00008086d0000150Esv00008086sd000012A1* + ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection (Ethernet Server Adapter I340-T4) + +pci:v00008086d0000150Esv00008086sd000012A2* + ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection (Ethernet Server Adapter I340-T4) + +pci:v00008086d0000150F* + ID_MODEL_FROM_DATABASE=82580 Gigabit Fiber Network Connection + +pci:v00008086d00001510* + ID_MODEL_FROM_DATABASE=82580 Gigabit Backplane Connection + +pci:v00008086d00001511* + ID_MODEL_FROM_DATABASE=82580 Gigabit SFP Connection + +pci:v00008086d00001513* + ID_MODEL_FROM_DATABASE=CV82524 Thunderbolt Controller [Light Ridge 4C 2010] + +pci:v00008086d00001514* + ID_MODEL_FROM_DATABASE=Ethernet X520 10GbE Dual Port KX4 Mezz + +pci:v00008086d00001514sv00008086sd0000000B* + ID_MODEL_FROM_DATABASE=Ethernet X520 10GbE Dual Port KX4 Mezz + +pci:v00008086d00001515* + ID_MODEL_FROM_DATABASE=X540 Ethernet Controller Virtual Function + +pci:v00008086d00001516* + ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection + +pci:v00008086d00001516sv00008086sd000012B1* + ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection (Ethernet Server Adapter I340-T2) + +pci:v00008086d00001516sv00008086sd000012B2* + ID_MODEL_FROM_DATABASE=82580 Gigabit Network Connection (Ethernet Server Adapter I340-T2) + +pci:v00008086d00001517* + ID_MODEL_FROM_DATABASE=82599ES 10 Gigabit Network Connection + +pci:v00008086d00001517sv00001137sd0000006A* + ID_MODEL_FROM_DATABASE=82599ES 10 Gigabit Network Connection (UCS CNA M61KR-I Intel Converged Network Adapter) + +pci:v00008086d00001518* + ID_MODEL_FROM_DATABASE=82576NS SerDes Gigabit Network Connection + +pci:v00008086d0000151A* + ID_MODEL_FROM_DATABASE=DSL2310 Thunderbolt Controller [Eagle Ridge 2C 2011] + +pci:v00008086d0000151B* + ID_MODEL_FROM_DATABASE=CVL2510 Thunderbolt Controller [Light Peak 2C 2010] + +pci:v00008086d0000151C* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit TN Network Connection + +pci:v00008086d0000151Csv0000108Esd00007B13* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit TN Network Connection (Dual 10GBASE-T LP) + +pci:v00008086d00001520* + ID_MODEL_FROM_DATABASE=I350 Ethernet Controller Virtual Function + +pci:v00008086d00001521* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection + +pci:v00008086d00001521sv00001028sd00000602* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 2P I350-t LOM) + +pci:v00008086d00001521sv00001028sd00000693* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 2P I350-t LOM) + +pci:v00008086d00001521sv00001028sd000006E2* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 2P I350-t LOM) + +pci:v00008086d00001521sv00001028sd00000757* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit I350-t LOM) + +pci:v00008086d00001521sv00001028sd0000075A* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit I350-t LOM) + +pci:v00008086d00001521sv00001028sd00001F60* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P I350-t rNDC) + +pci:v00008086d00001521sv00001028sd00001F62* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P X540/I350 rNDC) + +pci:v00008086d00001521sv00001028sd00001FA8* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 10G 4P X550/I350 rNDC) + +pci:v00008086d00001521sv00001028sd00001FA9* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 10G 4P X550 rNDC) + +pci:v00008086d00001521sv00001028sd00001FAA* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P X550/I350 rNDC) + +pci:v00008086d00001521sv00001028sd0000FF9A* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Gigabit 4P X710/I350 rNDC) + +pci:v00008086d00001521sv0000103Csd000017D1* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 4-port 366FLR Adapter) + +pci:v00008086d00001521sv0000103Csd00002003* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 2-port 367i Adapter) + +pci:v00008086d00001521sv0000103Csd00002226* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 1-port 364i Adapter) + +pci:v00008086d00001521sv0000103Csd0000337F* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 2-port 361i Adapter) + +pci:v00008086d00001521sv0000103Csd00003380* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 4-port 366i Adapter) + +pci:v00008086d00001521sv0000103Csd0000339E* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 2-port 361T Adapter) + +pci:v00008086d00001521sv0000103Csd00008157* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1Gb 4-port 366T Adapter) + +pci:v00008086d00001521sv0000108Esd00007B16* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Quad Port GbE PCIe 2.0 ExpressModule, UTP) + +pci:v00008086d00001521sv0000108Esd00007B18* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Quad Port GbE PCIe 2.0 Low Profile Adapter, UTP) + +pci:v00008086d00001521sv00001093sd00007648* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (PCIe-8237R Ethernet Adapter) + +pci:v00008086d00001521sv00001093sd00007649* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (PCIe-8236 Ethernet Adapter) + +pci:v00008086d00001521sv00001093sd000076B1* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (PCIe-8237R-S Ethernet Adapter) + +pci:v00008086d00001521sv00001093sd0000775B* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (PCIe-8237 Ethernet Adapter) + +pci:v00008086d00001521sv000010A9sd0000802A* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (UV2-BaseIO dual-port GbE) + +pci:v00008086d00001521sv00001137sd0000023E* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (1GigE I350 LOM) + +pci:v00008086d00001521sv000015D9sd00000652* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Dual Port i350 GbE MicroLP [AOC-CGP-i2]) + +pci:v00008086d00001521sv000017AAsd00001074* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (ThinkServer I350-T4 AnyFabric) + +pci:v00008086d00001521sv000017AAsd00004005* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection + +pci:v00008086d00001521sv000018D4sd00000C07* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (I350 1Gb 2-port RJ45 OCP Mezz Card MOP41-I-1GT2) + +pci:v00008086d00001521sv0000193Dsd00001005* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (360T-B) + +pci:v00008086d00001521sv0000193Dsd00001007* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (360T-L) + +pci:v00008086d00001521sv00001BD4sd0000001D* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (1G base-T QP EP014Ti1 Adapter) + +pci:v00008086d00001521sv00001BD4sd00000035* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (1G base-T QP EP014Ti1 Adapter) + +pci:v00008086d00001521sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T4) + +pci:v00008086d00001521sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T2) + +pci:v00008086d00001521sv00008086sd00000003* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Network Adapter I350-T4 for OCP NIC 3.0) + +pci:v00008086d00001521sv00008086sd000000A1* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T4) + +pci:v00008086d00001521sv00008086sd000000A2* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T2) + +pci:v00008086d00001521sv00008086sd000000A3* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Network Adapter I350-T4 for OCP NIC 3.0) + +pci:v00008086d00001521sv00008086sd000000AA* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Network Adapter I350-T4 for OCP NIC 3.0) + +pci:v00008086d00001521sv00008086sd00005001* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T4) + +pci:v00008086d00001521sv00008086sd00005002* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet Server Adapter I350-T2) + +pci:v00008086d00001521sv00008086sd00005003* + ID_MODEL_FROM_DATABASE=I350 Gigabit Network Connection (Ethernet 1G 4P I350-t OCP) + +pci:v00008086d00001522* + ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection + +pci:v00008086d00001522sv0000108Esd00007B17* + ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Quad Port GbE PCIe 2.0 ExpressModule, MMF) + +pci:v00008086d00001522sv0000108Esd00007B19* + ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Dual Port GbE PCIe 2.0 Low Profile Adapter, MMF) + +pci:v00008086d00001522sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-T2) + +pci:v00008086d00001522sv00008086sd00000003* + ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-F4) + +pci:v00008086d00001522sv00008086sd00000004* + ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-F2) + +pci:v00008086d00001522sv00008086sd00000005* + ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-F1) + +pci:v00008086d00001522sv00008086sd000000A2* + ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-T2) + +pci:v00008086d00001522sv00008086sd000000A3* + ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-F4) + +pci:v00008086d00001522sv00008086sd000000A4* + ID_MODEL_FROM_DATABASE=I350 Gigabit Fiber Network Connection (Ethernet Server Adapter I350-F2) + +pci:v00008086d00001523* + ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection + +pci:v00008086d00001523sv00001028sd00000060* + ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Gigabit 2P I350 LOM) + +pci:v00008086d00001523sv00001028sd00001F9B* + ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Gigabit 4P I350-t bNDC) + +pci:v00008086d00001523sv0000103Csd00001784* + ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Ethernet 1Gb 2-port 361FLB Adapter) + +pci:v00008086d00001523sv0000103Csd000018D1* + ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Ethernet 1Gb 2-port 361FLB Adapter) + +pci:v00008086d00001523sv0000103Csd00001989* + ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Ethernet 1Gb 2-port 363i Adapter) + +pci:v00008086d00001523sv0000103Csd0000339F* + ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (Ethernet 1Gb 4-port 366M Adapter) + +pci:v00008086d00001523sv00008086sd00001F52* + ID_MODEL_FROM_DATABASE=I350 Gigabit Backplane Connection (1GbE 4P I350 Mezz) + +pci:v00008086d00001524* + ID_MODEL_FROM_DATABASE=I350 Gigabit Connection + +pci:v00008086d00001525* + ID_MODEL_FROM_DATABASE=82567V-4 Gigabit Network Connection + +pci:v00008086d00001526* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection + +pci:v00008086d00001526sv00008086sd0000A05C* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET2 Quad Port Server Adapter) + +pci:v00008086d00001526sv00008086sd0000A06C* + ID_MODEL_FROM_DATABASE=82576 Gigabit Network Connection (Gigabit ET2 Quad Port Server Adapter) + +pci:v00008086d00001527* + ID_MODEL_FROM_DATABASE=82580 Gigabit Fiber Network Connection + +pci:v00008086d00001527sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=82580 Gigabit Fiber Network Connection (Ethernet Server Adapter I340-F4) + +pci:v00008086d00001527sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=82580 Gigabit Fiber Network Connection (Ethernet Server Adapter I340-F4) + +pci:v00008086d00001528* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 + +pci:v00008086d00001528sv00001028sd00001F61* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10G 4P X540/I350 rNDC) + +pci:v00008086d00001528sv0000103Csd0000192D* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (561FLR-T 2-port 10Gb Ethernet Adapter) + +pci:v00008086d00001528sv0000103Csd00002004* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10Gb 2-port 561i Adapter) + +pci:v00008086d00001528sv0000103Csd0000211A* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10Gb 2-port 561T Adapter) + +pci:v00008086d00001528sv0000108Esd00004853* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 + +pci:v00008086d00001528sv0000108Esd00007B14* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Sun Dual Port 10 GbE PCIe 2.0 ExpressModule, Base-T) + +pci:v00008086d00001528sv0000108Esd00007B15* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Sun Dual Port 10 GbE PCIe 2.0 Low Profile Adapter, Base-T) + +pci:v00008086d00001528sv00001137sd000000BF* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T2) + +pci:v00008086d00001528sv00001170sd00000052* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 + +pci:v00008086d00001528sv000017AAsd00001073* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (ThinkServer X540-T2 AnyFabric) + +pci:v00008086d00001528sv000017AAsd00004006* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 + +pci:v00008086d00001528sv00001BD4sd0000001A* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (10G base-T DP ER102Ti3 Rack Adapter) + +pci:v00008086d00001528sv00001BD4sd00000033* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (10G base-T DP EP102Ti3 Adapter) + +pci:v00008086d00001528sv00001BD4sd00000034* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (10G base-T DP EP102Ti3A Adapter) + +pci:v00008086d00001528sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T2) + +pci:v00008086d00001528sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T1) + +pci:v00008086d00001528sv00008086sd0000001A* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T2) + +pci:v00008086d00001528sv00008086sd000000A2* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet Converged Network Adapter X540-T1) + +pci:v00008086d00001528sv00008086sd00001F61* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10G 4P X540/I350 rNDC) + +pci:v00008086d00001528sv00008086sd00005003* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10G 2P X540-t Adapter) + +pci:v00008086d00001528sv00008086sd00005004* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10-Gigabit X540-AT2 (Ethernet 10G 2P X540-t Adapter) + +pci:v00008086d00001529* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Network Connection with FCoE + +pci:v00008086d0000152A* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Dual Port Backplane Connection with FCoE + +pci:v00008086d0000152E* + ID_MODEL_FROM_DATABASE=82599 Virtual Function + +pci:v00008086d0000152F* + ID_MODEL_FROM_DATABASE=I350 Virtual Function + +pci:v00008086d00001530* + ID_MODEL_FROM_DATABASE=X540 Virtual Function + +pci:v00008086d00001531* + ID_MODEL_FROM_DATABASE=I210 Gigabit Unprogrammed + +pci:v00008086d00001533* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection + +pci:v00008086d00001533sv0000103Csd00000003* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (Ethernet I210-T1 GbE NIC) + +pci:v00008086d00001533sv00001059sd00000180* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (RD10019 1GbE interface) + +pci:v00008086d00001533sv00001093sd00007706* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (Compact Vision System Ethernet Adapter) + +pci:v00008086d00001533sv000010A9sd0000802C* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (UV300 BaseIO single-port GbE) + +pci:v00008086d00001533sv000010A9sd0000802D* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (UV3000 BaseIO GbE Network) + +pci:v00008086d00001533sv000017AAsd00001100* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (ThinkServer Ethernet Server Adapter) + +pci:v00008086d00001533sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (Ethernet Server Adapter I210-T1) + +pci:v00008086d00001533sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection (Ethernet Server Adapter I210-T1) + +pci:v00008086d00001536* + ID_MODEL_FROM_DATABASE=I210 Gigabit Fiber Network Connection + +pci:v00008086d00001537* + ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection + +pci:v00008086d00001537sv00001059sd00000110* + ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (T4005 1GbE interface) + +pci:v00008086d00001537sv00001059sd00000111* + ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (T4007 1GbE interface) + +pci:v00008086d00001537sv00001059sd00000120* + ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (T4008 1GbE interface) + +pci:v00008086d00001537sv00001059sd00000130* + ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (T4009 1GbE interface) + +pci:v00008086d00001537sv00001059sd00000140* + ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (T2035 1GbE interface) + +pci:v00008086d00001537sv00001059sd00000150* + ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (RD-01068 1GbE interface) + +pci:v00008086d00001537sv00001059sd00000170* + ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection (RD-01213 10GbE interface) + +pci:v00008086d00001538* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection + +pci:v00008086d00001539* + ID_MODEL_FROM_DATABASE=I211 Gigabit Network Connection + +pci:v00008086d0000153A* + ID_MODEL_FROM_DATABASE=Ethernet Connection I217-LM + +pci:v00008086d0000153Asv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=Ethernet Connection I217-LM (ZBook 15) + +pci:v00008086d0000153Asv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=Ethernet Connection I217-LM (ThinkPad T440p) + +pci:v00008086d0000153Asv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=Ethernet Connection I217-LM (ThinkCentre M83) + +pci:v00008086d0000153B* + ID_MODEL_FROM_DATABASE=Ethernet Connection I217-V + +pci:v00008086d00001547* + ID_MODEL_FROM_DATABASE=DSL3510 Thunderbolt Controller [Cactus Ridge 4C 2012] + +pci:v00008086d00001548* + ID_MODEL_FROM_DATABASE=DSL3310 Thunderbolt Controller [Cactus Ridge 2C 2012] + +pci:v00008086d00001549* + ID_MODEL_FROM_DATABASE=DSL2210 Thunderbolt Controller [Port Ridge 1C 2011] + +pci:v00008086d0000154A* + ID_MODEL_FROM_DATABASE=Ethernet Server Adapter X520-4 + +pci:v00008086d0000154Asv00008086sd0000011A* + ID_MODEL_FROM_DATABASE=Ethernet Server Adapter X520-4 (Ethernet Converged Network Adapter X520-4) + +pci:v00008086d0000154Asv00008086sd0000011B* + ID_MODEL_FROM_DATABASE=Ethernet Server Adapter X520-4 (Ethernet Converged Network Adapter X520-4) + +pci:v00008086d0000154Asv00008086sd0000011C* + ID_MODEL_FROM_DATABASE=Ethernet Server Adapter X520-4 (Ethernet Converged Network Adapter X520-4) + +pci:v00008086d0000154C* + ID_MODEL_FROM_DATABASE=Ethernet Virtual Function 700 Series + +pci:v00008086d0000154D* + ID_MODEL_FROM_DATABASE=Ethernet 10G 2P X520 Adapter + +pci:v00008086d0000154Dsv00008086sd00007B11* + ID_MODEL_FROM_DATABASE=Ethernet 10G 2P X520 Adapter (10GbE 2P X520 Adapter) + +pci:v00008086d00001557* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection + +pci:v00008086d00001557sv000017AAsd00004008* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection (82599EN 10 Gigabit Network Connection) + +pci:v00008086d00001557sv00001BD4sd0000001C* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection (10G SFP+ SP ER101Fi4 Rack Adapter) + +pci:v00008086d00001557sv00001BD4sd00000030* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection (10G SFP+ SP EP101Fi4A Adapter) + +pci:v00008086d00001557sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=82599 10 Gigabit Network Connection (Ethernet OCP Server Adapter X520-1) + +pci:v00008086d00001558* + ID_MODEL_FROM_DATABASE=Ethernet Converged Network Adapter X520-Q1 + +pci:v00008086d00001558sv00008086sd0000011A* + ID_MODEL_FROM_DATABASE=Ethernet Converged Network Adapter X520-Q1 + +pci:v00008086d00001558sv00008086sd0000011B* + ID_MODEL_FROM_DATABASE=Ethernet Converged Network Adapter X520-Q1 + +pci:v00008086d00001559* + ID_MODEL_FROM_DATABASE=Ethernet Connection I218-V + +pci:v00008086d0000155A* + ID_MODEL_FROM_DATABASE=Ethernet Connection I218-LM + +pci:v00008086d0000155Asv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=Ethernet Connection I218-LM (ThinkPad X240) + +pci:v00008086d0000155C* + ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter + +pci:v00008086d0000155Csv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter (X540-T2) + +pci:v00008086d0000155D* + ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter + +pci:v00008086d0000155Dsv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter (X520-SR2) + +pci:v00008086d0000155Dsv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Server Bypass Adapter (X520-LR2) + +pci:v00008086d00001560* + ID_MODEL_FROM_DATABASE=Ethernet Controller X540 + +pci:v00008086d00001563* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T + +pci:v00008086d00001563sv00001028sd00001FA8* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10G 4P X550/I350 rNDC) + +pci:v00008086d00001563sv00001028sd00001FA9* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10G 4P X550 rNDC) + +pci:v00008086d00001563sv00001137sd000002B2* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (X550-TX 10 Gig LOM) + +pci:v00008086d00001563sv00001137sd000002B3* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (X550-TX 10 Gig LOM) + +pci:v00008086d00001563sv00001170sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Intel Ethernet Controller X550-T2 OCP card) + +pci:v00008086d00001563sv000014C0sd00001201* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (X550 10Gb 2P RJ45 OCP Mezz) + +pci:v00008086d00001563sv00001590sd000000D1* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10Gb 2-port 562T Adapter) + +pci:v00008086d00001563sv00001590sd000000D2* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10Gb 2-port 562FLR-T Adapter) + +pci:v00008086d00001563sv000016B8sd00007217* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Twin10G Thunderbolt 3 Edition) + +pci:v00008086d00001563sv000018D4sd00000C08* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (X550 10Gb 2-port RJ45 OCP Mezz Card MOP81-I-10GT2) + +pci:v00008086d00001563sv0000193Dsd00001008* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (560T-B) + +pci:v00008086d00001563sv0000193Dsd00001009* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (560T-L) + +pci:v00008086d00001563sv0000193Dsd00001011* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (UN-NIC-ETH563T-sL-2P) + +pci:v00008086d00001563sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T2) + +pci:v00008086d00001563sv00008086sd0000001A* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T2) + +pci:v00008086d00001563sv00008086sd0000001B* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Server Adapter X550-T2 for OCP) + +pci:v00008086d00001563sv00008086sd0000001D* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet 10G 2P X550-t Adapter) + +pci:v00008086d00001563sv00008086sd00000022* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T2) + +pci:v00008086d00001564* + ID_MODEL_FROM_DATABASE=X550 Virtual Function + +pci:v00008086d00001565* + ID_MODEL_FROM_DATABASE=X550 Virtual Function + +pci:v00008086d00001566* + ID_MODEL_FROM_DATABASE=DSL4410 Thunderbolt NHI [Redwood Ridge 2C 2013] + +pci:v00008086d00001567* + ID_MODEL_FROM_DATABASE=DSL4410 Thunderbolt Bridge [Redwood Ridge 2C 2013] + +pci:v00008086d00001568* + ID_MODEL_FROM_DATABASE=DSL4510 Thunderbolt NHI [Redwood Ridge 4C 2013] + +pci:v00008086d00001569* + ID_MODEL_FROM_DATABASE=DSL4510 Thunderbolt Bridge [Redwood Ridge 4C 2013] + +pci:v00008086d0000156A* + ID_MODEL_FROM_DATABASE=DSL5320 Thunderbolt 2 NHI [Falcon Ridge 2C 2013] + +pci:v00008086d0000156B* + ID_MODEL_FROM_DATABASE=DSL5320 Thunderbolt 2 Bridge [Falcon Ridge 2C 2013] + +pci:v00008086d0000156C* + ID_MODEL_FROM_DATABASE=DSL5520 Thunderbolt 2 NHI [Falcon Ridge 4C 2013] + +pci:v00008086d0000156D* + ID_MODEL_FROM_DATABASE=DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013] + +pci:v00008086d0000156F* + ID_MODEL_FROM_DATABASE=Ethernet Connection I219-LM + +pci:v00008086d0000156Fsv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Ethernet Connection I219-LM (Latitude E7470) + +pci:v00008086d0000156Fsv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Ethernet Connection I219-LM (EliteBook 840 G3) + +pci:v00008086d00001570* + ID_MODEL_FROM_DATABASE=Ethernet Connection I219-V + +pci:v00008086d00001571* + ID_MODEL_FROM_DATABASE=Ethernet Virtual Function 700 Series + +pci:v00008086d00001572* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ + +pci:v00008086d00001572sv00001028sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G X710 rNDC) + +pci:v00008086d00001572sv00001028sd00001F99* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G 4P X710/I350 rNDC) + +pci:v00008086d00001572sv00001028sd00001F9C* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G 4P X710 SFP+ rNDC) + +pci:v00008086d00001572sv0000103Csd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10Gb 562SFP+ Adapter) + +pci:v00008086d00001572sv0000103Csd000022FC* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10Gb 2-port 562FLR-SFP+ Adapter) + +pci:v00008086d00001572sv0000103Csd000022FD* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10Gb 2-port 562SFP+ Adapter) + +pci:v00008086d00001572sv00001137sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged NIC X710-DA) + +pci:v00008086d00001572sv00001137sd0000013B* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged NIC X710-DA4) + +pci:v00008086d00001572sv00001137sd0000020A* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged NIC X710-DA2) + +pci:v00008086d00001572sv00001590sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ + +pci:v00008086d00001572sv00001590sd00000225* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10GbE 4P 563SFP+ Adapter) + +pci:v00008086d00001572sv00001590sd0000022F* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10Gb 2-port 564i Communication Board) + +pci:v00008086d00001572sv000017AAsd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (ThinkServer X710 AnyFabric for 10GbE SFP+) + +pci:v00008086d00001572sv000017AAsd00004001* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (ThinkServer X710-4 AnyFabric for 10GbE SFP+) + +pci:v00008086d00001572sv000017AAsd00004002* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (ThinkServer X710-2 AnyFabric for 10GbE SFP+) + +pci:v00008086d00001572sv000019E5sd0000D11C* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 2-port X710 10Gb SFP+ Adapter SP330) + +pci:v00008086d00001572sv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710) + +pci:v00008086d00001572sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710-4) + +pci:v00008086d00001572sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710-4) + +pci:v00008086d00001572sv00008086sd00000004* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710-4) + +pci:v00008086d00001572sv00008086sd00000005* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G 4P X710 Adapter) + +pci:v00008086d00001572sv00008086sd00000006* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G 2P X710 Adapter) + +pci:v00008086d00001572sv00008086sd00000007* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710-2) + +pci:v00008086d00001572sv00008086sd00000008* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710-2) + +pci:v00008086d00001572sv00008086sd00000009* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ + +pci:v00008086d00001572sv00008086sd0000000A* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ + +pci:v00008086d00001572sv00008086sd0000000B* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Server Adapter X710-DA2 for OCP) + +pci:v00008086d00001572sv00008086sd0000000D* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ + +pci:v00008086d00001572sv00008086sd0000000E* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Server Adapter OCP X710-2) + +pci:v00008086d00001572sv00008086sd0000000F* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Server Adapter OCP X710-2) + +pci:v00008086d00001572sv00008086sd00000010* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Converged Network Adapter X710) + +pci:v00008086d00001572sv00008086sd00000011* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Network Adapter X710-2 for OCP NIC 3.0) + +pci:v00008086d00001572sv00008086sd00000012* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Network Adapter X710-4 for OCP NIC 3.0) + +pci:v00008086d00001572sv00008086sd00000013* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G 2P X710 OCP) + +pci:v00008086d00001572sv00008086sd00000014* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet 10G 4P X710 OCP) + +pci:v00008086d00001572sv00008086sd00000015* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Server Adapter X710-DA2 for OCP) + +pci:v00008086d00001572sv00008086sd000000A1* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Network Adapter X710-2 for OCP NIC 3.0) + +pci:v00008086d00001572sv00008086sd000000A2* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ (Ethernet Network Adapter X710-4 for OCP NIC 3.0) + +pci:v00008086d00001572sv00008086sd00004005* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ + +pci:v00008086d00001572sv00008086sd00004006* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ + +pci:v00008086d00001572sv00008086sd00004007* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE SFP+ + +pci:v00008086d00001574* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 Emulation + +pci:v00008086d00001575* + ID_MODEL_FROM_DATABASE=DSL6340 Thunderbolt 3 NHI [Alpine Ridge 2C 2015] + +pci:v00008086d00001576* + ID_MODEL_FROM_DATABASE=DSL6340 Thunderbolt 3 Bridge [Alpine Ridge 2C 2015] + +pci:v00008086d00001577* + ID_MODEL_FROM_DATABASE=DSL6540 Thunderbolt 3 NHI [Alpine Ridge 4C 2015] + +pci:v00008086d00001578* + ID_MODEL_FROM_DATABASE=DSL6540 Thunderbolt 3 Bridge [Alpine Ridge 4C 2015] + +pci:v00008086d0000157B* + ID_MODEL_FROM_DATABASE=I210 Gigabit Network Connection + +pci:v00008086d0000157C* + ID_MODEL_FROM_DATABASE=I210 Gigabit Backplane Connection + +pci:v00008086d0000157D* + ID_MODEL_FROM_DATABASE=DSL5110 Thunderbolt 2 NHI (Low Power) [Win Ridge 2C 2014] + +pci:v00008086d0000157E* + ID_MODEL_FROM_DATABASE=DSL5110 Thunderbolt 2 Bridge (Low Power) [Win Ridge 2C 2014] + +pci:v00008086d00001580* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE backplane + +pci:v00008086d00001581* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane + +pci:v00008086d00001581sv00001028sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 10G X710-k bNDC) + +pci:v00008086d00001581sv00001028sd00001F98* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 10G 4P X710-k bNDC) + +pci:v00008086d00001581sv00001028sd00001F9E* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 10G 2P X710-k bNDC) + +pci:v00008086d00001581sv00001059sd00000150* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (RD-01068 10GbE-KR interface) + +pci:v00008086d00001581sv00001059sd00000170* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (RD-01213 10GbE interface) + +pci:v00008086d00001581sv00001590sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 2-port 563i Adapter) + +pci:v00008086d00001581sv00001590sd000000F8* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet 2-port 563i Adapter) + +pci:v00008086d00001581sv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE backplane (Ethernet Converged Network Adapter XL710-Q2) + +pci:v00008086d00001583* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ + +pci:v00008086d00001583sv00001028sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet 40G 2P XL710 QSFP+ rNDC) + +pci:v00008086d00001583sv00001028sd00001F9F* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet 40G 2P XL710 QSFP+ rNDC) + +pci:v00008086d00001583sv0000108Esd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (10 Gb/40 Gb Ethernet Adapter) + +pci:v00008086d00001583sv0000108Esd00007B1B* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (10 Gb/40 Gb Ethernet Adapter) + +pci:v00008086d00001583sv0000108Esd00007B1D* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (10Gb/40Gb Ethernet Adapter) + +pci:v00008086d00001583sv00001137sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged NIC XL710-QDA2) + +pci:v00008086d00001583sv00001137sd0000013C* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged NIC XL710-QDA2) + +pci:v00008086d00001583sv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q2) + +pci:v00008086d00001583sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q2) + +pci:v00008086d00001583sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q2) + +pci:v00008086d00001583sv00008086sd00000003* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet I/O Module XL710-Q2) + +pci:v00008086d00001583sv00008086sd00000004* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Server Adapter XL710-Q2OCP) + +pci:v00008086d00001583sv00008086sd00000006* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q2) + +pci:v00008086d00001584* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ + +pci:v00008086d00001584sv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q1) + +pci:v00008086d00001584sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q1) + +pci:v00008086d00001584sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Converged Network Adapter XL710-Q1) + +pci:v00008086d00001584sv00008086sd00000003* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet I/O Module XL710-Q1) + +pci:v00008086d00001584sv00008086sd00000004* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 40GbE QSFP+ (Ethernet Server Adapter XL710-Q1OCP) + +pci:v00008086d00001585* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GbE QSFP+ + +pci:v00008086d00001586* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T + +pci:v00008086d00001586sv0000108Esd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T + +pci:v00008086d00001586sv0000108Esd00004857* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T + +pci:v00008086d00001587* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane + +pci:v00008086d00001587sv0000103Csd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (Ethernet 10/20Gb 2-port 660FLB Adapter) + +pci:v00008086d00001587sv0000103Csd000022FE* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (Ethernet 10/20Gb 2-port 660FLB Adapter) + +pci:v00008086d00001588* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane + +pci:v00008086d00001588sv0000103Csd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (Ethernet 10/20Gb 2-port 660M Adapter) + +pci:v00008086d00001588sv0000103Csd000022FF* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (Ethernet 10/20Gb 2-port 660M Adapter) + +pci:v00008086d00001588sv00001137sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (Ethernet Network Adapter XXV710) + +pci:v00008086d00001588sv00001137sd000002B4* + ID_MODEL_FROM_DATABASE=Ethernet Controller XL710 for 20GbE backplane (Ethernet Network Adapter XXV710 OCP 2.0) + +pci:v00008086d00001589* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T + +pci:v00008086d00001589sv0000108Esd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Quad Port 10GBase-T Adapter) + +pci:v00008086d00001589sv0000108Esd00007B1C* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Quad Port 10GBase-T Adapter) + +pci:v00008086d00001589sv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T) + +pci:v00008086d00001589sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T4) + +pci:v00008086d00001589sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T4) + +pci:v00008086d00001589sv00008086sd00000003* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T) + +pci:v00008086d00001589sv00008086sd000000A0* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T4) + +pci:v00008086d00001589sv00008086sd00001003* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710/X557-AT 10GBASE-T (Ethernet Converged Network Adapter X710-T) + +pci:v00008086d0000158A* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE backplane + +pci:v00008086d0000158Asv00001590sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE backplane (10/25Gb Ethernet Adapter) + +pci:v00008086d0000158Asv00001590sd00000286* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE backplane (Synergy 4610C 10/25Gb Ethernet Adapter) + +pci:v00008086d0000158Asv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE backplane + +pci:v00008086d0000158Asv00008086sd0000000A* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE backplane (Ethernet 25G 2P XXV710 Mezz) + +pci:v00008086d0000158B* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 + +pci:v00008086d0000158Bsv00001137sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710) + +pci:v00008086d0000158Bsv00001137sd00000225* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710) + +pci:v00008086d0000158Bsv00001137sd000002B4* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710 OCP 2.0) + +pci:v00008086d0000158Bsv00001374sd00000230* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Single Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G1I71)) + +pci:v00008086d0000158Bsv00001374sd00000231* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Single Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G1I71EU)) + +pci:v00008086d0000158Bsv00001374sd00000234* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Dual Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G2I71)) + +pci:v00008086d0000158Bsv00001374sd00000235* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Dual Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G2I71EU)) + +pci:v00008086d0000158Bsv00001374sd00000238* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Quad Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G4I71L)) + +pci:v00008086d0000158Bsv00001374sd00000239* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Quad Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G4I71LEU)) + +pci:v00008086d0000158Bsv00001374sd0000023A* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Quad Port 25 Gigabit Ethernet PCI Express Server Adapter (PE31625G4I71L)) + +pci:v00008086d0000158Bsv00001374sd0000023B* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Quad Port 25 Gigabit Ethernet PCI Express Server Adapter (PE31625G4I71LEU)) + +pci:v00008086d0000158Bsv00001590sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-2) + +pci:v00008086d0000158Bsv00001590sd00000253* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet 10/25/Gb 2-port 661SFP28 Adapter) + +pci:v00008086d0000158Bsv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710) + +pci:v00008086d0000158Bsv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-2) + +pci:v00008086d0000158Bsv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-2) + +pci:v00008086d0000158Bsv00008086sd00000003* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-1) + +pci:v00008086d0000158Bsv00008086sd00000004* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-1) + +pci:v00008086d0000158Bsv00008086sd00000005* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter OCP XXV710-2) + +pci:v00008086d0000158Bsv00008086sd00000006* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter OCP XXV710-2) + +pci:v00008086d0000158Bsv00008086sd00000007* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter OCP XXV710-1) + +pci:v00008086d0000158Bsv00008086sd00000008* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter OCP XXV710-1) + +pci:v00008086d0000158Bsv00008086sd00000009* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet 25G 2P XXV710 Adapter) + +pci:v00008086d0000158Bsv00008086sd0000000A* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet 25G 2P XXV710 OCP) + +pci:v00008086d0000158Bsv00008086sd00004001* + ID_MODEL_FROM_DATABASE=Ethernet Controller XXV710 for 25GbE SFP28 (Ethernet Network Adapter XXV710-2) + +pci:v00008086d00001591* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for backplane + +pci:v00008086d00001592* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP + +pci:v00008086d00001592sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet Network Adapter E810-C-Q2) + +pci:v00008086d00001592sv00008086sd00000004* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet Network Adapter E810-C-Q2) + +pci:v00008086d00001592sv00008086sd00000005* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet Network Adapter E810-C-Q1 for OCP3.0) + +pci:v00008086d00001592sv00008086sd00000006* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet Network Adapter E810-C-Q2 for OCP3.0) + +pci:v00008086d00001592sv00008086sd00000009* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for QSFP (Ethernet Network Adapter E810-C-Q1) + +pci:v00008086d00001593* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for SFP + +pci:v00008086d00001593sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for SFP (Ethernet Network Adapter E810-L-2) + +pci:v00008086d00001593sv00008086sd00000005* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for SFP (Ethernet Network Adapter E810-XXV-4) + +pci:v00008086d00001593sv00008086sd00000006* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for SFP (Ethernet Network Adapter E810-XXV-4) + +pci:v00008086d00001593sv00008086sd00000007* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for SFP (Ethernet Network Adapter E810-XXV-4) + +pci:v00008086d00001593sv00008086sd00000008* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for SFP (Ethernet Network Adapter E810-XXV-2) + +pci:v00008086d00001593sv00008086sd00000009* + ID_MODEL_FROM_DATABASE=Ethernet Controller E810-C for SFP (Ethernet Network Adapter E810-XXV-2 for OCP 2.0) + +pci:v00008086d000015A0* + ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I218-LM + +pci:v00008086d000015A1* + ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I218-V + +pci:v00008086d000015A2* + ID_MODEL_FROM_DATABASE=Ethernet Connection (3) I218-LM + +pci:v00008086d000015A3* + ID_MODEL_FROM_DATABASE=Ethernet Connection (3) I218-V + +pci:v00008086d000015A4* + ID_MODEL_FROM_DATABASE=Ethernet Switch FM10000 Host Interface + +pci:v00008086d000015A5* + ID_MODEL_FROM_DATABASE=Ethernet Switch FM10000 Host Virtual Interface + +pci:v00008086d000015A8* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552 Virtual Function + +pci:v00008086d000015A9* + ID_MODEL_FROM_DATABASE=X552 Virtual Function + +pci:v00008086d000015AA* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane + +pci:v00008086d000015AAsv00001059sd00000120* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane (T4008 10GbE interface) + +pci:v00008086d000015AB* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane + +pci:v00008086d000015ABsv00001059sd00000150* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane (RD-01068 10GbE interface) + +pci:v00008086d000015ABsv00001059sd00000170* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE Backplane (RD-01213 10GbE interface) + +pci:v00008086d000015AC* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE SFP+ + +pci:v00008086d000015ACsv00001059sd00000160* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552 10 GbE SFP+ (RD-01167 10GbE interface) + +pci:v00008086d000015AD* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552/X557-AT 10GBASE-T + +pci:v00008086d000015AE* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552 1000BASE-T + +pci:v00008086d000015B0* + ID_MODEL_FROM_DATABASE=Ethernet Connection X552 Backplane + +pci:v00008086d000015B4* + ID_MODEL_FROM_DATABASE=X553 Virtual Function + +pci:v00008086d000015B5* + ID_MODEL_FROM_DATABASE=DSL6340 USB 3.1 Controller [Alpine Ridge] + +pci:v00008086d000015B6* + ID_MODEL_FROM_DATABASE=DSL6540 USB 3.1 Controller [Alpine Ridge] + +pci:v00008086d000015B7* + ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I219-LM + +pci:v00008086d000015B8* + ID_MODEL_FROM_DATABASE=Ethernet Connection (2) I219-V + +pci:v00008086d000015B9* + ID_MODEL_FROM_DATABASE=Ethernet Connection (3) I219-LM + +pci:v00008086d000015BB* + ID_MODEL_FROM_DATABASE=Ethernet Connection (7) I219-LM + +pci:v00008086d000015BC* + ID_MODEL_FROM_DATABASE=Ethernet Connection (7) I219-V + +pci:v00008086d000015BD* + ID_MODEL_FROM_DATABASE=Ethernet Connection (6) I219-LM + +pci:v00008086d000015BE* + ID_MODEL_FROM_DATABASE=Ethernet Connection (6) I219-V + +pci:v00008086d000015BF* + ID_MODEL_FROM_DATABASE=JHL6240 Thunderbolt 3 NHI (Low Power) [Alpine Ridge LP 2016] + +pci:v00008086d000015C0* + ID_MODEL_FROM_DATABASE=JHL6240 Thunderbolt 3 Bridge (Low Power) [Alpine Ridge LP 2016] + +pci:v00008086d000015C1* + ID_MODEL_FROM_DATABASE=JHL6240 Thunderbolt 3 USB 3.1 Controller (Low Power) [Alpine Ridge LP 2016] + +pci:v00008086d000015C2* + ID_MODEL_FROM_DATABASE=Ethernet Connection X553 Backplane + +pci:v00008086d000015C3* + ID_MODEL_FROM_DATABASE=Ethernet Connection X553 Backplane + +pci:v00008086d000015C4* + ID_MODEL_FROM_DATABASE=Ethernet Connection X553 10 GbE SFP+ + +pci:v00008086d000015C5* + ID_MODEL_FROM_DATABASE=X553 Virtual Function + +pci:v00008086d000015C6* + ID_MODEL_FROM_DATABASE=Ethernet Connection X553 1GbE + +pci:v00008086d000015C7* + ID_MODEL_FROM_DATABASE=Ethernet Connection X553 1GbE + +pci:v00008086d000015C8* + ID_MODEL_FROM_DATABASE=Ethernet Connection X553/X557-AT 10GBASE-T + +pci:v00008086d000015CE* + ID_MODEL_FROM_DATABASE=Ethernet Connection X553 10 GbE SFP+ + +pci:v00008086d000015D0* + ID_MODEL_FROM_DATABASE=Ethernet SDI Adapter + +pci:v00008086d000015D0sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet SDI Adapter (FM10420-100GbE-QDA2) + +pci:v00008086d000015D0sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet SDI Adapter (FM10840-MTP2) + +pci:v00008086d000015D1* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T + +pci:v00008086d000015D1sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T1) + +pci:v00008086d000015D1sv00008086sd0000001B* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Server Adapter X550-T1 for OCP) + +pci:v00008086d000015D1sv00008086sd00000021* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T1) + +pci:v00008086d000015D1sv00008086sd000000A2* + ID_MODEL_FROM_DATABASE=Ethernet Controller 10G X550T (Ethernet Converged Network Adapter X550-T1) + +pci:v00008086d000015D2* + ID_MODEL_FROM_DATABASE=JHL6540 Thunderbolt 3 NHI (C step) [Alpine Ridge 4C 2016] + +pci:v00008086d000015D3* + ID_MODEL_FROM_DATABASE=JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] + +pci:v00008086d000015D4* + ID_MODEL_FROM_DATABASE=JHL6540 Thunderbolt 3 USB Controller (C step) [Alpine Ridge 4C 2016] + +pci:v00008086d000015D5* + ID_MODEL_FROM_DATABASE=Ethernet SDI Adapter FM10420-25GbE-DA2 + +pci:v00008086d000015D5sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet SDI Adapter FM10420-25GbE-DA2 (Intel(R) Ethernet SDI Adapter FM10420-25GbE-DA2) + +pci:v00008086d000015D6* + ID_MODEL_FROM_DATABASE=Ethernet Connection (5) I219-V + +pci:v00008086d000015D7* + ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-LM + +pci:v00008086d000015D8* + ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-V + +pci:v00008086d000015D8sv000017AAsd00002247* + ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-V (ThinkPad T570) + +pci:v00008086d000015D8sv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-V (ThinkPad X1 Carbon 5th Gen) + +pci:v00008086d000015D8sv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Ethernet Connection (4) I219-V (ThinkPad T480) + +pci:v00008086d000015D9* + ID_MODEL_FROM_DATABASE=JHL6340 Thunderbolt 3 NHI (C step) [Alpine Ridge 2C 2016] + +pci:v00008086d000015DA* + ID_MODEL_FROM_DATABASE=JHL6340 Thunderbolt 3 Bridge (C step) [Alpine Ridge 2C 2016] + +pci:v00008086d000015DB* + ID_MODEL_FROM_DATABASE=JHL6340 Thunderbolt 3 USB 3.1 Controller (C step) [Alpine Ridge 2C 2016] + +pci:v00008086d000015DF* + ID_MODEL_FROM_DATABASE=Ethernet Connection (8) I219-LM + +pci:v00008086d000015E0* + ID_MODEL_FROM_DATABASE=Ethernet Connection (8) I219-V + +pci:v00008086d000015E1* + ID_MODEL_FROM_DATABASE=Ethernet Connection (9) I219-LM + +pci:v00008086d000015E2* + ID_MODEL_FROM_DATABASE=Ethernet Connection (9) I219-V + +pci:v00008086d000015E3* + ID_MODEL_FROM_DATABASE=Ethernet Connection (5) I219-LM + +pci:v00008086d000015E4* + ID_MODEL_FROM_DATABASE=Ethernet Connection X553 1GbE + +pci:v00008086d000015E5* + ID_MODEL_FROM_DATABASE=Ethernet Connection X553 1GbE + +pci:v00008086d000015E7* + ID_MODEL_FROM_DATABASE=JHL7540 Thunderbolt 3 Bridge [Titan Ridge 2C 2018] + +pci:v00008086d000015E8* + ID_MODEL_FROM_DATABASE=JHL7540 Thunderbolt 3 NHI [Titan Ridge 2C 2018] + +pci:v00008086d000015E9* + ID_MODEL_FROM_DATABASE=JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 2C 2018] + +pci:v00008086d000015EA* + ID_MODEL_FROM_DATABASE=JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] + +pci:v00008086d000015EB* + ID_MODEL_FROM_DATABASE=JHL7540 Thunderbolt 3 NHI [Titan Ridge 4C 2018] + +pci:v00008086d000015EC* + ID_MODEL_FROM_DATABASE=JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 4C 2018] + +pci:v00008086d000015EF* + ID_MODEL_FROM_DATABASE=JHL7540 Thunderbolt 3 Bridge [Titan Ridge DD 2018] + +pci:v00008086d000015F0* + ID_MODEL_FROM_DATABASE=JHL7540 Thunderbolt 3 USB Controller [Titan Ridge DD 2018] + +pci:v00008086d000015F4* + ID_MODEL_FROM_DATABASE=Ethernet Connection (15) I219-LM + +pci:v00008086d000015F5* + ID_MODEL_FROM_DATABASE=Ethernet Connection (15) I219-V + +pci:v00008086d000015F6* + ID_MODEL_FROM_DATABASE=I210 Gigabit Ethernet Connection + +pci:v00008086d000015F9* + ID_MODEL_FROM_DATABASE=Ethernet Connection (14) I219-LM + +pci:v00008086d000015FA* + ID_MODEL_FROM_DATABASE=Ethernet Connection (14) I219-V + +pci:v00008086d000015FB* + ID_MODEL_FROM_DATABASE=Ethernet Connection (13) I219-LM + +pci:v00008086d000015FC* + ID_MODEL_FROM_DATABASE=Ethernet Connection (13) I219-V + +pci:v00008086d000015FF* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T + +pci:v00008086d000015FFsv00001137sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (X710TLG GbE RJ45 PCIe NIC) + +pci:v00008086d000015FFsv00001137sd000002C1* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (X710T2LG 2x10 GbE RJ45 PCIe NIC) + +pci:v00008086d000015FFsv00001137sd000002C2* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (X710T4LG 4x10 GbE RJ45 PCIe NIC) + +pci:v00008086d000015FFsv00008086sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-TL) + +pci:v00008086d000015FFsv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T4L) + +pci:v00008086d000015FFsv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T4L) + +pci:v00008086d000015FFsv00008086sd00000003* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T2L) + +pci:v00008086d000015FFsv00008086sd00000004* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T2L) + +pci:v00008086d000015FFsv00008086sd00000005* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet 10G 2P X710-T2L-t Adapter) + +pci:v00008086d000015FFsv00008086sd00000006* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet 10G 4P X710-T4L-t Adapter) + +pci:v00008086d000015FFsv00008086sd00000007* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet 10G 2P X710-T2L-t OCP) + +pci:v00008086d000015FFsv00008086sd00000008* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet 10G 4P X710-T4L-t OCP) + +pci:v00008086d000015FFsv00008086sd00000009* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T4L for OCP 3.0) + +pci:v00008086d000015FFsv00008086sd0000000A* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T4L for OCP 3.0) + +pci:v00008086d000015FFsv00008086sd0000000B* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T2L for OCP 3.0) + +pci:v00008086d000015FFsv00008086sd0000000C* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T2L for OCP 3.0) + +pci:v00008086d000015FFsv00008086sd0000000F* + ID_MODEL_FROM_DATABASE=Ethernet Controller X710 for 10GBASE-T (Ethernet Network Adapter X710-T2L for OCP 3.0) + +pci:v00008086d00001600* + ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge -OPI + +pci:v00008086d00001601* + ID_MODEL_FROM_DATABASE=Broadwell-U PCI Express x16 Controller + +pci:v00008086d00001602* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d00001603* + ID_MODEL_FROM_DATABASE=Broadwell-U Processor Thermal Subsystem + +pci:v00008086d00001604* + ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge -OPI + +pci:v00008086d00001605* + ID_MODEL_FROM_DATABASE=Broadwell-U PCI Express x8 Controller + +pci:v00008086d00001606* + ID_MODEL_FROM_DATABASE=HD Graphics + +pci:v00008086d00001607* + ID_MODEL_FROM_DATABASE=Broadwell-U CHAPS Device + +pci:v00008086d00001608* + ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge -OPI + +pci:v00008086d00001609* + ID_MODEL_FROM_DATABASE=Broadwell-U x4 PCIe + +pci:v00008086d0000160A* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000160B* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000160C* + ID_MODEL_FROM_DATABASE=Broadwell-U Audio Controller + +pci:v00008086d0000160D* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000160E* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000160F* + ID_MODEL_FROM_DATABASE=Broadwell-U SoftSKU + +pci:v00008086d00001610* + ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge - DMI + +pci:v00008086d00001612* + ID_MODEL_FROM_DATABASE=HD Graphics 5600 + +pci:v00008086d00001614* + ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge - DMI + +pci:v00008086d00001616* + ID_MODEL_FROM_DATABASE=HD Graphics 5500 + +pci:v00008086d00001616sv0000103Csd00002216* + ID_MODEL_FROM_DATABASE=HD Graphics 5500 (ZBook 15u G2 Mobile Workstation) + +pci:v00008086d00001618* + ID_MODEL_FROM_DATABASE=Broadwell-U Host Bridge - DMI + +pci:v00008086d0000161A* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000161B* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000161D* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000161E* + ID_MODEL_FROM_DATABASE=HD Graphics 5300 + +pci:v00008086d00001622* + ID_MODEL_FROM_DATABASE=Iris Pro Graphics 6200 + +pci:v00008086d00001626* + ID_MODEL_FROM_DATABASE=HD Graphics 6000 + +pci:v00008086d0000162A* + ID_MODEL_FROM_DATABASE=Iris Pro Graphics P6300 + +pci:v00008086d0000162B* + ID_MODEL_FROM_DATABASE=Iris Graphics 6100 + +pci:v00008086d0000162D* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000162E* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d00001632* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d00001636* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000163A* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000163B* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000163D* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d0000163E* + ID_MODEL_FROM_DATABASE=Broadwell-U Integrated Graphics + +pci:v00008086d00001889* + ID_MODEL_FROM_DATABASE=Ethernet Adaptive Virtual Function + +pci:v00008086d000018A0* + ID_MODEL_FROM_DATABASE=C4xxx Series QAT + +pci:v00008086d000018A1* + ID_MODEL_FROM_DATABASE=C4XXX Series QAT Virtual Function + +pci:v00008086d00001900* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00001901* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x16) + +pci:v00008086d00001902* + ID_MODEL_FROM_DATABASE=HD Graphics 510 + +pci:v00008086d00001903* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem + +pci:v00008086d00001903sv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem (Latitude E7470) + +pci:v00008086d00001903sv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem (XPS 15 9550) + +pci:v00008086d00001903sv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem (ThinkPad T480) + +pci:v00008086d00001904* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00001904sv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (Latitude E7470) + +pci:v00008086d00001904sv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (Latitude 3570) + +pci:v00008086d00001904sv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (EliteBook 840 G3) + +pci:v00008086d00001904sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (B51-80 Laptop) + +pci:v00008086d00001905* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x8) + +pci:v00008086d00001906* + ID_MODEL_FROM_DATABASE=HD Graphics 510 + +pci:v00008086d00001906sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=HD Graphics 510 (B51-80 Laptop) + +pci:v00008086d00001908* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00001909* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x4) + +pci:v00008086d0000190C* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d0000190F* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00001910* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00001910sv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers (XPS 15 9550) + +pci:v00008086d00001911* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model + +pci:v00008086d00001911sv000017AAsd00002247* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model (ThinkPad T570) + +pci:v00008086d00001911sv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model (ThinkPad X1 Carbon 5th Gen) + +pci:v00008086d00001911sv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model (ThinkPad T480) + +pci:v00008086d00001912* + ID_MODEL_FROM_DATABASE=HD Graphics 530 + +pci:v00008086d00001916* + ID_MODEL_FROM_DATABASE=Skylake GT2 [HD Graphics 520] + +pci:v00008086d00001916sv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Skylake GT2 [HD Graphics 520] (Latitude E7470) + +pci:v00008086d00001916sv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Skylake GT2 [HD Graphics 520] (Latitude 3570) + +pci:v00008086d00001916sv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Skylake GT2 [HD Graphics 520] (EliteBook 840 G3) + +pci:v00008086d00001918* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00001919* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Imaging Unit + +pci:v00008086d0000191B* + ID_MODEL_FROM_DATABASE=HD Graphics 530 + +pci:v00008086d0000191Bsv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=HD Graphics 530 (XPS 15 9550) + +pci:v00008086d0000191D* + ID_MODEL_FROM_DATABASE=HD Graphics P530 + +pci:v00008086d0000191E* + ID_MODEL_FROM_DATABASE=HD Graphics 515 + +pci:v00008086d0000191F* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00001921* + ID_MODEL_FROM_DATABASE=HD Graphics 520 + +pci:v00008086d00001926* + ID_MODEL_FROM_DATABASE=Iris Graphics 540 + +pci:v00008086d00001927* + ID_MODEL_FROM_DATABASE=Iris Graphics 550 + +pci:v00008086d0000192B* + ID_MODEL_FROM_DATABASE=Iris Graphics 555 + +pci:v00008086d0000192D* + ID_MODEL_FROM_DATABASE=Iris Graphics P555 + +pci:v00008086d00001932* + ID_MODEL_FROM_DATABASE=Iris Pro Graphics 580 + +pci:v00008086d0000193A* + ID_MODEL_FROM_DATABASE=Iris Pro Graphics P580 + +pci:v00008086d0000193B* + ID_MODEL_FROM_DATABASE=Iris Pro Graphics 580 + +pci:v00008086d0000193D* + ID_MODEL_FROM_DATABASE=Iris Pro Graphics P580 + +pci:v00008086d00001960* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor + +pci:v00008086d00001960sv0000101Esd00000431* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 431 RAID Controller) + +pci:v00008086d00001960sv0000101Esd00000438* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 438 Ultra2 LVD RAID Controller) + +pci:v00008086d00001960sv0000101Esd00000466* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 466 Express Plus RAID Controller) + +pci:v00008086d00001960sv0000101Esd00000467* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 467 Enterprise 1500 RAID Controller) + +pci:v00008086d00001960sv0000101Esd00000490* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 490 Express 300 RAID Controller) + +pci:v00008086d00001960sv0000101Esd00000762* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 762 Express RAID Controller) + +pci:v00008086d00001960sv0000101Esd000009A0* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (PowerEdge Expandable RAID Controller 2/SC) + +pci:v00008086d00001960sv00001028sd00000467* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (PowerEdge Expandable RAID Controller 2/DC) + +pci:v00008086d00001960sv00001028sd00001111* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (PowerEdge Expandable RAID Controller 2/SC) + +pci:v00008086d00001960sv0000103Csd000003A2* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID) + +pci:v00008086d00001960sv0000103Csd000010C6* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 438, NetRAID-3Si) + +pci:v00008086d00001960sv0000103Csd000010C7* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID T5, Integrated NetRAID) + +pci:v00008086d00001960sv0000103Csd000010CC* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID, Integrated NetRAID) + +pci:v00008086d00001960sv0000103Csd000010CD* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (NetRAID-1Si) + +pci:v00008086d00001960sv0000105Asd00000000* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (SuperTrak) + +pci:v00008086d00001960sv0000105Asd00002168* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (SuperTrak Pro) + +pci:v00008086d00001960sv0000105Asd00005168* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (SuperTrak66/100) + +pci:v00008086d00001960sv00001111sd00001111* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID 466, PowerEdge Expandable RAID Controller 2/SC) + +pci:v00008086d00001960sv00001111sd00001112* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (PowerEdge Expandable RAID Controller 2/SC) + +pci:v00008086d00001960sv0000113Csd000003A2* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (MegaRAID) + +pci:v00008086d00001960sv0000E4BFsd00001010* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (CG1-RADIO) + +pci:v00008086d00001960sv0000E4BFsd00001020* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (CU2-QUARTET) + +pci:v00008086d00001960sv0000E4BFsd00001040* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (CU1-CHORUS) + +pci:v00008086d00001960sv0000E4BFsd00003100* + ID_MODEL_FROM_DATABASE=80960RP (i960RP) Microprocessor (CX1-BAND) + +pci:v00008086d00001962* + ID_MODEL_FROM_DATABASE=80960RM (i960RM) Microprocessor + +pci:v00008086d00001962sv0000105Asd00000000* + ID_MODEL_FROM_DATABASE=80960RM (i960RM) Microprocessor (SuperTrak SX6000 I2O CPU) + +pci:v00008086d00001964* + ID_MODEL_FROM_DATABASE=80960RN (i960RN) Microprocessor + +pci:v00008086d00001980* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series System Agent + +pci:v00008086d000019A1* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series Error Registers + +pci:v00008086d000019A2* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series Root Complex Event Collector + +pci:v00008086d000019A3* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series Integrated QAT Root Port + +pci:v00008086d000019A4* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series PCI Express Root Port #0 + +pci:v00008086d000019A5* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series PCI Express Root Port #1 + +pci:v00008086d000019A6* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series PCI Express Root Port #2 + +pci:v00008086d000019A7* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series PCI Express Root Port #3 + +pci:v00008086d000019A8* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series PCI Express Root Port #4 + +pci:v00008086d000019A9* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series PCI Express Root Port #5 + +pci:v00008086d000019AA* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series PCI Express Root Port #6 + +pci:v00008086d000019AB* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series PCI Express Root Port #7 + +pci:v00008086d000019AC* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SMBus Contoller - Host + +pci:v00008086d000019B0* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0 + +pci:v00008086d000019B1* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0 + +pci:v00008086d000019B2* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0 + +pci:v00008086d000019B3* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0 + +pci:v00008086d000019B4* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0 + +pci:v00008086d000019B5* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0 + +pci:v00008086d000019B6* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0 + +pci:v00008086d000019B7* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0 + +pci:v00008086d000019BE* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0 + +pci:v00008086d000019BF* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 0 + +pci:v00008086d000019C0* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1 + +pci:v00008086d000019C1* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1 + +pci:v00008086d000019C2* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1 + +pci:v00008086d000019C3* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1 + +pci:v00008086d000019C4* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1 + +pci:v00008086d000019C5* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1 + +pci:v00008086d000019C6* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1 + +pci:v00008086d000019C7* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1 + +pci:v00008086d000019CE* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1 + +pci:v00008086d000019CF* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SATA Controller 1 + +pci:v00008086d000019D0* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series USB 3.0 xHCI Controller + +pci:v00008086d000019D1* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series Integrated LAN Root Port #0 + +pci:v00008086d000019D2* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series Integrated LAN Root Port #1 + +pci:v00008086d000019D3* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series ME HECI 1 + +pci:v00008086d000019D4* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series ME HECI 2 + +pci:v00008086d000019D5* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series ME KT Controller + +pci:v00008086d000019D6* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series ME HECI 3 + +pci:v00008086d000019D8* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series HSUART Controller + +pci:v00008086d000019DC* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series LPC or eSPI + +pci:v00008086d000019DD* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series Primary to Side Band (P2SB) Bridge + +pci:v00008086d000019DE* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series Power Management Controller + +pci:v00008086d000019DF* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SMBus controller + +pci:v00008086d000019E0* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series SPI Controller + +pci:v00008086d000019E2* + ID_MODEL_FROM_DATABASE=Atom Processor C3000 Series QuickAssist Technology + +pci:v00008086d00001A1C* + ID_MODEL_FROM_DATABASE=Ethernet Connection (17) I219-LM + +pci:v00008086d00001A1D* + ID_MODEL_FROM_DATABASE=Ethernet Connection (17) I219-V + +pci:v00008086d00001A1E* + ID_MODEL_FROM_DATABASE=Ethernet Connection (16) I219-LM + +pci:v00008086d00001A1F* + ID_MODEL_FROM_DATABASE=Ethernet Connection (16) I219-V + +pci:v00008086d00001A21* + ID_MODEL_FROM_DATABASE=82840 840 [Carmel] Chipset Host Bridge (Hub A) + +pci:v00008086d00001A23* + ID_MODEL_FROM_DATABASE=82840 840 [Carmel] Chipset AGP Bridge + +pci:v00008086d00001A24* + ID_MODEL_FROM_DATABASE=82840 840 [Carmel] Chipset PCI Bridge (Hub B) + +pci:v00008086d00001A30* + ID_MODEL_FROM_DATABASE=82845 845 [Brookdale] Chipset Host Bridge + +pci:v00008086d00001A30sv00001028sd0000010E* + ID_MODEL_FROM_DATABASE=82845 845 [Brookdale] Chipset Host Bridge (Optiplex GX240) + +pci:v00008086d00001A30sv0000147Bsd00000505* + ID_MODEL_FROM_DATABASE=82845 845 [Brookdale] Chipset Host Bridge (BL7 motherboard) + +pci:v00008086d00001A30sv000015D9sd00003280* + ID_MODEL_FROM_DATABASE=82845 845 [Brookdale] Chipset Host Bridge (Supermicro P4SBE Mainboard) + +pci:v00008086d00001A31* + ID_MODEL_FROM_DATABASE=82845 845 [Brookdale] Chipset AGP Bridge + +pci:v00008086d00001A38* + ID_MODEL_FROM_DATABASE=5000 Series Chipset DMA Engine + +pci:v00008086d00001A38sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset DMA Engine (X7DVL-E-O motherboard) + +pci:v00008086d00001A38sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=5000 Series Chipset DMA Engine (S5000PSLSATA Server Board) + +pci:v00008086d00001A48* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller + +pci:v00008086d00001A48sv00008086sd0000A01F* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE SR Server Adapter) + +pci:v00008086d00001A48sv00008086sd0000A11F* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE SR Server Adapter) + +pci:v00008086d00001B48* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller + +pci:v00008086d00001B48sv00008086sd0000A01F* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE LR Server Adapter) + +pci:v00008086d00001B48sv00008086sd0000A11F* + ID_MODEL_FROM_DATABASE=82597EX 10GbE Ethernet Controller (PRO/10GbE LR Server Adapter) + +pci:v00008086d00001C00* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family Desktop SATA Controller (IDE mode, ports 0-3) + +pci:v00008086d00001C01* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family Mobile SATA Controller (IDE mode, ports 0-3) + +pci:v00008086d00001C02* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller + +pci:v00008086d00001C02sv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller (XPS 8300) + +pci:v00008086d00001C02sv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller (P8 series motherboard) + +pci:v00008086d00001C02sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller (Server Board S1200BT Family) + +pci:v00008086d00001C03* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller + +pci:v00008086d00001C03sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller (Precision M4600) + +pci:v00008086d00001C03sv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller (Vostro 3350) + +pci:v00008086d00001C03sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller (Vostro 3750) + +pci:v00008086d00001C03sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller (ThinkPad T520) + +pci:v00008086d00001C03sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller (Apple MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00001C04* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Desktop SATA RAID Controller + +pci:v00008086d00001C04sv0000103Csd00003118* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Desktop SATA RAID Controller (Smart Array B110i SATA RAID Controller) + +pci:v00008086d00001C05* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Mobile SATA RAID Controller + +pci:v00008086d00001C06* + ID_MODEL_FROM_DATABASE=Z68 Express Chipset SATA RAID Controller + +pci:v00008086d00001C08* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family Desktop SATA Controller (IDE mode, ports 4-5) + +pci:v00008086d00001C09* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family Mobile SATA Controller (IDE mode, ports 4-5) + +pci:v00008086d00001C10* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 + +pci:v00008086d00001C10sv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (XPS 8300) + +pci:v00008086d00001C10sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (Vostro 3750) + +pci:v00008086d00001C10sv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (P8 series motherboard) + +pci:v00008086d00001C10sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (ThinkPad T520) + +pci:v00008086d00001C10sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 1 (Server Board S1200BTS / Apple MacBook Pro 8,1/8,2) + +pci:v00008086d00001C12* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 2 + +pci:v00008086d00001C12sv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 2 (XPS 8300) + +pci:v00008086d00001C12sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 2 (ThinkPad T520) + +pci:v00008086d00001C12sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 2 (Apple MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00001C14* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 3 + +pci:v00008086d00001C14sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 3 (Vostro 3750) + +pci:v00008086d00001C14sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 3 (Apple MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00001C16* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 4 + +pci:v00008086d00001C16sv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 4 (XPS 8300) + +pci:v00008086d00001C16sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 4 (ThinkPad T520) + +pci:v00008086d00001C18* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5 + +pci:v00008086d00001C18sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5 (Vostro 3750) + +pci:v00008086d00001C18sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5 (ThinkPad T520) + +pci:v00008086d00001C18sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 5 (Server Board S1200BTS) + +pci:v00008086d00001C1A* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 6 + +pci:v00008086d00001C1Asv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 6 (Vostro 3750) + +pci:v00008086d00001C1Asv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 6 (P8 series motherboard) + +pci:v00008086d00001C1C* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 7 + +pci:v00008086d00001C1E* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 8 + +pci:v00008086d00001C1Esv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family PCI Express Root Port 8 (P8 series motherboard) + +pci:v00008086d00001C20* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller + +pci:v00008086d00001C20sv00001028sd00000490* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Alienware M17x R3) + +pci:v00008086d00001C20sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Precision M4600) + +pci:v00008086d00001C20sv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (XPS 8300) + +pci:v00008086d00001C20sv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Vostro 3350) + +pci:v00008086d00001C20sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Vostro 3750) + +pci:v00008086d00001C20sv00001043sd00008418* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (P8P67 Deluxe Motherboard) + +pci:v00008086d00001C20sv00001043sd0000841B* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (P8H67 Series Motherboard) + +pci:v00008086d00001C20sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (ThinkPad T520) + +pci:v00008086d00001C20sv00008086sd00002008* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (DQ67SW board) + +pci:v00008086d00001C20sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family High Definition Audio Controller (Apple MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00001C22* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller + +pci:v00008086d00001C22sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (Precision M4600) + +pci:v00008086d00001C22sv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (XPS 8300) + +pci:v00008086d00001C22sv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (Vostro 3350) + +pci:v00008086d00001C22sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (Vostro 3750) + +pci:v00008086d00001C22sv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (P8 series motherboard) + +pci:v00008086d00001C22sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (ThinkPad T520) + +pci:v00008086d00001C22sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family SMBus Controller (Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2) + +pci:v00008086d00001C24* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family Thermal Management Controller + +pci:v00008086d00001C25* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family DMI to PCI Bridge + +pci:v00008086d00001C26* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 + +pci:v00008086d00001C26sv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (Precision M4600) + +pci:v00008086d00001C26sv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (XPS 8300) + +pci:v00008086d00001C26sv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (Vostro 3350) + +pci:v00008086d00001C26sv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (Vostro 3750) + +pci:v00008086d00001C26sv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (P8 series motherboard) + +pci:v00008086d00001C26sv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (ThinkPad T520) + +pci:v00008086d00001C26sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 (Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2) + +pci:v00008086d00001C27* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Universal Host Controller #1 + +pci:v00008086d00001C27sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Universal Host Controller #1 (Apple MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00001C2C* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Universal Host Controller #5 + +pci:v00008086d00001C2Csv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Universal Host Controller #5 (Apple MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00001C2D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 + +pci:v00008086d00001C2Dsv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (Precision M4600) + +pci:v00008086d00001C2Dsv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (XPS 8300) + +pci:v00008086d00001C2Dsv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (Vostro 3350) + +pci:v00008086d00001C2Dsv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (Vostro 3750) + +pci:v00008086d00001C2Dsv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (P8 series motherboard) + +pci:v00008086d00001C2Dsv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (ThinkPad T520) + +pci:v00008086d00001C2Dsv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 (Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2) + +pci:v00008086d00001C33* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LAN Controller + +pci:v00008086d00001C35* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family VECI Controller + +pci:v00008086d00001C3A* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 + +pci:v00008086d00001C3Asv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (Precision M4600) + +pci:v00008086d00001C3Asv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (XPS 8300) + +pci:v00008086d00001C3Asv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (Vostro 3350) + +pci:v00008086d00001C3Asv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (Vostro 3750) + +pci:v00008086d00001C3Asv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (P8 series motherboard) + +pci:v00008086d00001C3Asv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (ThinkPad T520) + +pci:v00008086d00001C3Asv00008086sd00007270* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #1 (Apple MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00001C3B* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family MEI Controller #2 + +pci:v00008086d00001C3C* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family IDE-r Controller + +pci:v00008086d00001C3D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family KT Controller + +pci:v00008086d00001C40* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C41* + ID_MODEL_FROM_DATABASE=Mobile SFF 6 Series Chipset Family LPC Controller + +pci:v00008086d00001C42* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C43* + ID_MODEL_FROM_DATABASE=Mobile 6 Series Chipset Family LPC Controller + +pci:v00008086d00001C44* + ID_MODEL_FROM_DATABASE=Z68 Express Chipset LPC Controller + +pci:v00008086d00001C45* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C46* + ID_MODEL_FROM_DATABASE=P67 Express Chipset LPC Controller + +pci:v00008086d00001C46sv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=P67 Express Chipset LPC Controller (P8P67 Deluxe Motherboard) + +pci:v00008086d00001C47* + ID_MODEL_FROM_DATABASE=UM67 Express Chipset LPC Controller + +pci:v00008086d00001C48* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C49* + ID_MODEL_FROM_DATABASE=HM65 Express Chipset LPC Controller + +pci:v00008086d00001C49sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=HM65 Express Chipset LPC Controller (Apple MacBookPro8,2 [Core i7, 15", 2011]) + +pci:v00008086d00001C4A* + ID_MODEL_FROM_DATABASE=H67 Express Chipset LPC Controller + +pci:v00008086d00001C4Asv00001028sd000004AA* + ID_MODEL_FROM_DATABASE=H67 Express Chipset LPC Controller (XPS 8300) + +pci:v00008086d00001C4Asv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=H67 Express Chipset LPC Controller (P8H67 Series Motherboard) + +pci:v00008086d00001C4B* + ID_MODEL_FROM_DATABASE=HM67 Express Chipset LPC Controller + +pci:v00008086d00001C4Bsv00001028sd000004B2* + ID_MODEL_FROM_DATABASE=HM67 Express Chipset LPC Controller (Vostro 3350) + +pci:v00008086d00001C4Bsv00001028sd000004DA* + ID_MODEL_FROM_DATABASE=HM67 Express Chipset LPC Controller (Vostro 3750) + +pci:v00008086d00001C4C* + ID_MODEL_FROM_DATABASE=Q65 Express Chipset LPC Controller + +pci:v00008086d00001C4D* + ID_MODEL_FROM_DATABASE=QS67 Express Chipset LPC Controller + +pci:v00008086d00001C4E* + ID_MODEL_FROM_DATABASE=Q67 Express Chipset LPC Controller + +pci:v00008086d00001C4F* + ID_MODEL_FROM_DATABASE=QM67 Express Chipset LPC Controller + +pci:v00008086d00001C4Fsv00001028sd000004A3* + ID_MODEL_FROM_DATABASE=QM67 Express Chipset LPC Controller (Precision M4600) + +pci:v00008086d00001C4Fsv000017AAsd000021CF* + ID_MODEL_FROM_DATABASE=QM67 Express Chipset LPC Controller (ThinkPad T520) + +pci:v00008086d00001C50* + ID_MODEL_FROM_DATABASE=B65 Express Chipset LPC Controller + +pci:v00008086d00001C51* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C52* + ID_MODEL_FROM_DATABASE=C202 Chipset LPC Controller + +pci:v00008086d00001C52sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=C202 Chipset LPC Controller (Server Board S1200BTS) + +pci:v00008086d00001C53* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C54* + ID_MODEL_FROM_DATABASE=C204 Chipset LPC Controller + +pci:v00008086d00001C55* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C56* + ID_MODEL_FROM_DATABASE=C206 Chipset LPC Controller + +pci:v00008086d00001C56sv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=C206 Chipset LPC Controller (P8B WS Motherboard) + +pci:v00008086d00001C57* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C58* + ID_MODEL_FROM_DATABASE=Upgraded B65 Express Chipset LPC Controller + +pci:v00008086d00001C59* + ID_MODEL_FROM_DATABASE=Upgraded HM67 Express Chipset LPC Controller + +pci:v00008086d00001C5A* + ID_MODEL_FROM_DATABASE=Upgraded Q67 Express Chipset LPC Controller + +pci:v00008086d00001C5B* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C5C* + ID_MODEL_FROM_DATABASE=H61 Express Chipset LPC Controller + +pci:v00008086d00001C5D* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C5E* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001C5F* + ID_MODEL_FROM_DATABASE=6 Series/C200 Series Chipset Family LPC Controller + +pci:v00008086d00001D00* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA IDE Controller + +pci:v00008086d00001D02* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset 6-Port SATA AHCI Controller + +pci:v00008086d00001D02sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset 6-Port SATA AHCI Controller (C602J on PowerEdge R320 server) + +pci:v00008086d00001D04* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller + +pci:v00008086d00001D06* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA Premium RAID Controller + +pci:v00008086d00001D08* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset 2-Port SATA IDE Controller + +pci:v00008086d00001D10* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 1 + +pci:v00008086d00001D10sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 1 (C602J on PowerEdge R320 server) + +pci:v00008086d00001D11* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 1 + +pci:v00008086d00001D12* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 2 + +pci:v00008086d00001D13* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 2 + +pci:v00008086d00001D14* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 3 + +pci:v00008086d00001D15* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 3 + +pci:v00008086d00001D16* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 4 + +pci:v00008086d00001D17* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 4 + +pci:v00008086d00001D18* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 5 + +pci:v00008086d00001D18sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 5 (C602J on PowerEdge R320 server) + +pci:v00008086d00001D19* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 5 + +pci:v00008086d00001D1A* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 6 + +pci:v00008086d00001D1B* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 6 + +pci:v00008086d00001D1C* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 7 + +pci:v00008086d00001D1D* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 7 + +pci:v00008086d00001D1E* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 8 + +pci:v00008086d00001D1Esv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 8 (C602J on PowerEdge R320 server) + +pci:v00008086d00001D1F* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Root Port 8 + +pci:v00008086d00001D20* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset High Definition Audio Controller + +pci:v00008086d00001D22* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SMBus Host Controller + +pci:v00008086d00001D22sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SMBus Host Controller (X9SRL-F) + +pci:v00008086d00001D24* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Thermal Management Controller + +pci:v00008086d00001D24sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Thermal Management Controller (X9SRL-F) + +pci:v00008086d00001D25* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset DMI to PCI Bridge + +pci:v00008086d00001D26* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset USB2 Enhanced Host Controller #1 + +pci:v00008086d00001D26sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset USB2 Enhanced Host Controller #1 (C602J on PowerEdge R320 server) + +pci:v00008086d00001D26sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset USB2 Enhanced Host Controller #1 (X9SRL-F) + +pci:v00008086d00001D2D* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset USB2 Enhanced Host Controller #2 + +pci:v00008086d00001D2Dsv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset USB2 Enhanced Host Controller #2 (C602J on PowerEdge R320 server) + +pci:v00008086d00001D2Dsv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset USB2 Enhanced Host Controller #2 (X9SRL-F) + +pci:v00008086d00001D33* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset LAN Controller + +pci:v00008086d00001D35* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset VECI Controller + +pci:v00008086d00001D3A* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset MEI Controller #1 + +pci:v00008086d00001D3Asv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset MEI Controller #1 (C602J on PowerEdge R320 server) + +pci:v00008086d00001D3Asv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset MEI Controller #1 (X9SRL-F) + +pci:v00008086d00001D3B* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset MEI Controller #2 + +pci:v00008086d00001D3Bsv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset MEI Controller #2 (C602J on PowerEdge R320 server) + +pci:v00008086d00001D3Bsv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset MEI Controller #2 (X9SRL-F) + +pci:v00008086d00001D3C* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset IDE-r Controller + +pci:v00008086d00001D3D* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset KT Controller + +pci:v00008086d00001D3E* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Virtual Root Port + +pci:v00008086d00001D3Esv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset PCI Express Virtual Root Port (C602J on PowerEdge R320 server) + +pci:v00008086d00001D3F* + ID_MODEL_FROM_DATABASE=C608/C606/X79 series chipset PCI Express Virtual Switch Port + +pci:v00008086d00001D40* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset LPC Controller + +pci:v00008086d00001D41* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset LPC Controller + +pci:v00008086d00001D41sv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset LPC Controller (C602J on PowerEdge R320 server) + +pci:v00008086d00001D41sv000015D9sd0000066B* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset LPC Controller (X9SRL-F) + +pci:v00008086d00001D50* + ID_MODEL_FROM_DATABASE=C608 chipset Dual 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D54* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D55* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D58* + ID_MODEL_FROM_DATABASE=C606 chipset Dual 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D59* + ID_MODEL_FROM_DATABASE=C604/X79 series chipset 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D5A* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA Storage Control Unit + +pci:v00008086d00001D5B* + ID_MODEL_FROM_DATABASE=C602 chipset 4-Port SATA Storage Control Unit + +pci:v00008086d00001D5C* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D5D* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D5E* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA Storage Control Unit + +pci:v00008086d00001D5F* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA Storage Control Unit + +pci:v00008086d00001D60* + ID_MODEL_FROM_DATABASE=C608 chipset Dual 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D64* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D65* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D68* + ID_MODEL_FROM_DATABASE=C606 chipset Dual 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D69* + ID_MODEL_FROM_DATABASE=C604/X79 series chipset 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D6A* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA Storage Control Unit + +pci:v00008086d00001D6B* + ID_MODEL_FROM_DATABASE=C602 chipset 4-Port SATA Storage Control Unit + +pci:v00008086d00001D6Bsv00000497sd00001028* + ID_MODEL_FROM_DATABASE=C602 chipset 4-Port SATA Storage Control Unit (Dell Precision T3600) + +pci:v00008086d00001D6C* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D6D* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit + +pci:v00008086d00001D6E* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Dual 4-Port SATA Storage Control Unit + +pci:v00008086d00001D6F* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset 4-Port SATA Storage Control Unit + +pci:v00008086d00001D70* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SMBus Controller 0 + +pci:v00008086d00001D71* + ID_MODEL_FROM_DATABASE=C608/C606/X79 series chipset SMBus Controller 1 + +pci:v00008086d00001D72* + ID_MODEL_FROM_DATABASE=C608 chipset SMBus Controller 2 + +pci:v00008086d00001D74* + ID_MODEL_FROM_DATABASE=C608/C606/X79 series chipset PCI Express Upstream Port + +pci:v00008086d00001D76* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset Multi-Function Glue + +pci:v00008086d00001E00* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 4-port SATA Controller [IDE mode] + +pci:v00008086d00001E01* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 4-port SATA Controller [IDE mode] + +pci:v00008086d00001E01sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 4-port SATA Controller [IDE mode] (NP300E5C series laptop) + +pci:v00008086d00001E02* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 6-port SATA Controller [AHCI mode] + +pci:v00008086d00001E02sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 6-port SATA Controller [AHCI mode] (P8 series motherboard) + +pci:v00008086d00001E02sv00001849sd00001E02* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 6-port SATA Controller [AHCI mode] (Motherboard) + +pci:v00008086d00001E03* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] + +pci:v00008086d00001E03sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (VivoBook X202EV) + +pci:v00008086d00001E03sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (N56VZ) + +pci:v00008086d00001E03sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (Zenbook Prime UX31A) + +pci:v00008086d00001E03sv000010CFsd000016E2* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (LIFEBOOK E752) + +pci:v00008086d00001E03sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 6-port SATA Controller [AHCI mode] (NP300E5C series laptop) + +pci:v00008086d00001E04* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SATA Controller [RAID mode] + +pci:v00008086d00001E05* + ID_MODEL_FROM_DATABASE=7 Series Chipset SATA Controller [RAID mode] + +pci:v00008086d00001E06* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SATA Controller [RAID mode] + +pci:v00008086d00001E07* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family SATA Controller [RAID mode] + +pci:v00008086d00001E08* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family 2-port SATA Controller [IDE mode] + +pci:v00008086d00001E09* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 2-port SATA Controller [IDE mode] + +pci:v00008086d00001E09sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family 2-port SATA Controller [IDE mode] (NP300E5C series laptop) + +pci:v00008086d00001E0E* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family SATA Controller [RAID mode] + +pci:v00008086d00001E10* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 + +pci:v00008086d00001E10sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (VivoBook X202EV) + +pci:v00008086d00001E10sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (N56VZ) + +pci:v00008086d00001E10sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (Zenbook Prime UX31A) + +pci:v00008086d00001E10sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (P8H77-I Motherboard) + +pci:v00008086d00001E10sv000010CFsd000016E9* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (LIFEBOOK E752) + +pci:v00008086d00001E10sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (NP300E5C series laptop) + +pci:v00008086d00001E10sv00001849sd00001E10* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 1 (Motherboard) + +pci:v00008086d00001E12* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 + +pci:v00008086d00001E12sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 (VivoBook X202EV) + +pci:v00008086d00001E12sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 (N56VZ) + +pci:v00008086d00001E12sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 2 (Zenbook Prime UX31A) + +pci:v00008086d00001E14* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 3 + +pci:v00008086d00001E14sv000010CFsd000016E9* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 3 (LIFEBOOK E752) + +pci:v00008086d00001E16* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 4 + +pci:v00008086d00001E16sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 4 (VivoBook X202EV) + +pci:v00008086d00001E16sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 4 (N56VZ) + +pci:v00008086d00001E16sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 4 (NP300E5C series laptop) + +pci:v00008086d00001E16sv00001849sd00001618* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family PCI Express Root Port 4 (Z77 Extreme4 motherboard) + +pci:v00008086d00001E18* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 5 + +pci:v00008086d00001E18sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 5 (P8H77-I Motherboard) + +pci:v00008086d00001E18sv00001849sd00001E18* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 5 (Motherboard) + +pci:v00008086d00001E1A* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 6 + +pci:v00008086d00001E1Asv00001849sd00001E1A* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 6 (Motherboard) + +pci:v00008086d00001E1C* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 7 + +pci:v00008086d00001E1E* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 8 + +pci:v00008086d00001E1Esv000010CFsd000016E9* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 8 (LIFEBOOK E752) + +pci:v00008086d00001E1Esv00001849sd00001E1E* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family PCI Express Root Port 8 (Motherboard) + +pci:v00008086d00001E20* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller + +pci:v00008086d00001E20sv00001028sd0000054B* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (XPS One 2710) + +pci:v00008086d00001E20sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (VivoBook X202EV) + +pci:v00008086d00001E20sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (N56VZ) + +pci:v00008086d00001E20sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (Zenbook Prime UX31A) + +pci:v00008086d00001E20sv00001043sd00008415* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (P8H77-I Motherboard) + +pci:v00008086d00001E20sv00001043sd00008445* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (P8Z77-V LX Motherboard) + +pci:v00008086d00001E20sv000010CFsd00001757* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (LIFEBOOK E752) + +pci:v00008086d00001E20sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (NP300E5C series laptop) + +pci:v00008086d00001E20sv00001849sd00001898* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family High Definition Audio Controller (Z77 Extreme4 motherboard) + +pci:v00008086d00001E22* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller + +pci:v00008086d00001E22sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (VivoBook X202EV) + +pci:v00008086d00001E22sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (N56VZ) + +pci:v00008086d00001E22sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (Zenbook Prime UX31A) + +pci:v00008086d00001E22sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (P8 series motherboard) + +pci:v00008086d00001E22sv000010CFsd000016E6* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (LIFEBOOK E752) + +pci:v00008086d00001E22sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (NP300E5C series laptop) + +pci:v00008086d00001E22sv00001849sd00001E22* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family SMBus Controller (Motherboard) + +pci:v00008086d00001E24* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family Thermal Management Controller + +pci:v00008086d00001E24sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family Thermal Management Controller (Zenbook Prime UX31A) + +pci:v00008086d00001E25* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family DMI to PCI Bridge + +pci:v00008086d00001E26* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 + +pci:v00008086d00001E26sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (VivoBook X202EV) + +pci:v00008086d00001E26sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (N56VZ) + +pci:v00008086d00001E26sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (Zenbook Prime UX31A) + +pci:v00008086d00001E26sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (P8 series motherboard) + +pci:v00008086d00001E26sv000010CFsd000016E8* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (LIFEBOOK E752) + +pci:v00008086d00001E26sv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (NP300E5C series laptop) + +pci:v00008086d00001E26sv00001849sd00001E26* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #1 (Motherboard) + +pci:v00008086d00001E2D* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 + +pci:v00008086d00001E2Dsv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (VivoBook X202EV) + +pci:v00008086d00001E2Dsv00001043sd00001477* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (N56VZ) + +pci:v00008086d00001E2Dsv00001043sd00001517* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (Zenbook Prime UX31A) + +pci:v00008086d00001E2Dsv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (P8 series motherboard) + +pci:v00008086d00001E2Dsv000010CFsd000016E8* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (LIFEBOOK E752) + +pci:v00008086d00001E2Dsv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (NP300E5C series laptop) + +pci:v00008086d00001E2Dsv00001849sd00001E2D* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family USB Enhanced Host Controller #2 (Motherboard) + +pci:v00008086d00001E31* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller + +pci:v00008086d00001E31sv0000103Csd0000179B* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (Elitebook 8470p) + +pci:v00008086d00001E31sv0000103Csd000017AB* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (ProBook 6570b) + +pci:v00008086d00001E31sv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (VivoBook X202EV) + +pci:v00008086d00001E31sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (N56VZ) + +pci:v00008086d00001E31sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (Zenbook Prime UX31A) + +pci:v00008086d00001E31sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (P8 series motherboard) + +pci:v00008086d00001E31sv000010CFsd000016EE* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (LIFEBOOK E752) + +pci:v00008086d00001E31sv000017AAsd000021F3* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (ThinkPad T430) + +pci:v00008086d00001E31sv00001849sd00001E31* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family USB xHCI Host Controller (Motherboard) + +pci:v00008086d00001E33* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family LAN Controller + +pci:v00008086d00001E3A* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 + +pci:v00008086d00001E3Asv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (VivoBook X202EV) + +pci:v00008086d00001E3Asv00001043sd00001477* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (N56VZ) + +pci:v00008086d00001E3Asv00001043sd00001517* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (Zenbook Prime UX31A) + +pci:v00008086d00001E3Asv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (P8 series motherboard) + +pci:v00008086d00001E3Asv000010CFsd000016EA* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (LIFEBOOK E752) + +pci:v00008086d00001E3Asv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (NP300E5C series laptop) + +pci:v00008086d00001E3Asv00001849sd00001E3A* + ID_MODEL_FROM_DATABASE=7 Series/C216 Chipset Family MEI Controller #1 (Motherboard) + +pci:v00008086d00001E3B* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family MEI Controller #2 + +pci:v00008086d00001E3C* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family IDE-r Controller + +pci:v00008086d00001E3D* + ID_MODEL_FROM_DATABASE=7 Series/C210 Series Chipset Family KT Controller + +pci:v00008086d00001E41* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E42* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E43* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E44* + ID_MODEL_FROM_DATABASE=Z77 Express Chipset LPC Controller + +pci:v00008086d00001E44sv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=Z77 Express Chipset LPC Controller (P8 series motherboard) + +pci:v00008086d00001E44sv00001849sd00001E44* + ID_MODEL_FROM_DATABASE=Z77 Express Chipset LPC Controller (Motherboard) + +pci:v00008086d00001E45* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E46* + ID_MODEL_FROM_DATABASE=Z75 Express Chipset LPC Controller + +pci:v00008086d00001E47* + ID_MODEL_FROM_DATABASE=Q77 Express Chipset LPC Controller + +pci:v00008086d00001E48* + ID_MODEL_FROM_DATABASE=Q75 Express Chipset LPC Controller + +pci:v00008086d00001E49* + ID_MODEL_FROM_DATABASE=B75 Express Chipset LPC Controller + +pci:v00008086d00001E4A* + ID_MODEL_FROM_DATABASE=H77 Express Chipset LPC Controller + +pci:v00008086d00001E4Asv00001043sd000084CA* + ID_MODEL_FROM_DATABASE=H77 Express Chipset LPC Controller (P8H77-I Motherboard) + +pci:v00008086d00001E4B* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E4C* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E4D* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E4E* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E4F* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E50* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E51* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E52* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E53* + ID_MODEL_FROM_DATABASE=C216 Series Chipset LPC Controller + +pci:v00008086d00001E54* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E55* + ID_MODEL_FROM_DATABASE=QM77 Express Chipset LPC Controller + +pci:v00008086d00001E56* + ID_MODEL_FROM_DATABASE=QS77 Express Chipset LPC Controller + +pci:v00008086d00001E57* + ID_MODEL_FROM_DATABASE=HM77 Express Chipset LPC Controller + +pci:v00008086d00001E58* + ID_MODEL_FROM_DATABASE=UM77 Express Chipset LPC Controller + +pci:v00008086d00001E59* + ID_MODEL_FROM_DATABASE=HM76 Express Chipset LPC Controller + +pci:v00008086d00001E59sv00001043sd00001477* + ID_MODEL_FROM_DATABASE=HM76 Express Chipset LPC Controller (N56VZ) + +pci:v00008086d00001E59sv00001043sd00001517* + ID_MODEL_FROM_DATABASE=HM76 Express Chipset LPC Controller (Zenbook Prime UX31A) + +pci:v00008086d00001E59sv000010CFsd000016E0* + ID_MODEL_FROM_DATABASE=HM76 Express Chipset LPC Controller (LIFEBOOK E752) + +pci:v00008086d00001E5A* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E5B* + ID_MODEL_FROM_DATABASE=UM77 Express Chipset LPC Controller + +pci:v00008086d00001E5C* + ID_MODEL_FROM_DATABASE=7 Series Chipset Family LPC Controller + +pci:v00008086d00001E5D* + ID_MODEL_FROM_DATABASE=HM75 Express Chipset LPC Controller + +pci:v00008086d00001E5Dsv0000144Dsd0000C652* + ID_MODEL_FROM_DATABASE=HM75 Express Chipset LPC Controller (NP300E5C series laptop) + +pci:v00008086d00001E5E* + ID_MODEL_FROM_DATABASE=HM70 Express Chipset LPC Controller + +pci:v00008086d00001E5Esv00001043sd0000108D* + ID_MODEL_FROM_DATABASE=HM70 Express Chipset LPC Controller (VivoBook X202EV) + +pci:v00008086d00001E5F* + ID_MODEL_FROM_DATABASE=NM70 Express Chipset LPC Controller + +pci:v00008086d00001F00* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F01* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F02* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F03* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F04* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F05* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F06* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F07* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F08* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F09* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F0A* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F0B* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F0C* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F0D* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F0E* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F0F* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SoC Transaction Router + +pci:v00008086d00001F10* + ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 1 + +pci:v00008086d00001F11* + ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 2 + +pci:v00008086d00001F12* + ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 3 + +pci:v00008086d00001F13* + ID_MODEL_FROM_DATABASE=Atom processor C2000 PCIe Root Port 4 + +pci:v00008086d00001F14* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAS + +pci:v00008086d00001F15* + ID_MODEL_FROM_DATABASE=Atom processor C2000 SMBus 2.0 + +pci:v00008086d00001F16* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RCEC + +pci:v00008086d00001F18* + ID_MODEL_FROM_DATABASE=Atom processor C2000 QAT + +pci:v00008086d00001F19* + ID_MODEL_FROM_DATABASE=Atom processor C2000 QAT + +pci:v00008086d00001F20* + ID_MODEL_FROM_DATABASE=Atom processor C2000 4-Port IDE SATA2 Controller + +pci:v00008086d00001F21* + ID_MODEL_FROM_DATABASE=Atom processor C2000 4-Port IDE SATA2 Controller + +pci:v00008086d00001F22* + ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA2 Controller + +pci:v00008086d00001F23* + ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA2 Controller + +pci:v00008086d00001F24* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller + +pci:v00008086d00001F25* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller + +pci:v00008086d00001F26* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller + +pci:v00008086d00001F27* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller + +pci:v00008086d00001F2C* + ID_MODEL_FROM_DATABASE=Atom processor C2000 USB Enhanced Host Controller + +pci:v00008086d00001F2E* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller + +pci:v00008086d00001F2F* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA2 Controller + +pci:v00008086d00001F30* + ID_MODEL_FROM_DATABASE=Atom processor C2000 2-Port IDE SATA3 Controller + +pci:v00008086d00001F31* + ID_MODEL_FROM_DATABASE=Atom processor C2000 2-Port IDE SATA3 Controller + +pci:v00008086d00001F32* + ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA3 Controller + +pci:v00008086d00001F33* + ID_MODEL_FROM_DATABASE=Atom processor C2000 AHCI SATA3 Controller + +pci:v00008086d00001F34* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller + +pci:v00008086d00001F35* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller + +pci:v00008086d00001F36* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller + +pci:v00008086d00001F37* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller + +pci:v00008086d00001F38* + ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU + +pci:v00008086d00001F39* + ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU + +pci:v00008086d00001F3A* + ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU + +pci:v00008086d00001F3B* + ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU + +pci:v00008086d00001F3C* + ID_MODEL_FROM_DATABASE=Atom processor C2000 PCU SMBus + +pci:v00008086d00001F3D* + ID_MODEL_FROM_DATABASE=Atom Processor C2000 PECI SMBus + +pci:v00008086d00001F3E* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller + +pci:v00008086d00001F3F* + ID_MODEL_FROM_DATABASE=Atom processor C2000 RAID SATA3 Controller + +pci:v00008086d00001F40* + ID_MODEL_FROM_DATABASE=Ethernet Connection I354 1.0 GbE Backplane + +pci:v00008086d00001F40sv00001028sd000005F1* + ID_MODEL_FROM_DATABASE=Ethernet Connection I354 1.0 GbE Backplane + +pci:v00008086d00001F41* + ID_MODEL_FROM_DATABASE=Ethernet Connection I354 + +pci:v00008086d00001F42* + ID_MODEL_FROM_DATABASE=Atom processor C2000 GbE + +pci:v00008086d00001F44* + ID_MODEL_FROM_DATABASE=Atom processor C2000 GbE Virtual Function + +pci:v00008086d00001F45* + ID_MODEL_FROM_DATABASE=Ethernet Connection I354 2.5 GbE Backplane + +pci:v00008086d00002014* + ID_MODEL_FROM_DATABASE=Sky Lake-E Ubox Registers + +pci:v00008086d00002015* + ID_MODEL_FROM_DATABASE=Sky Lake-E Ubox Registers + +pci:v00008086d00002016* + ID_MODEL_FROM_DATABASE=Sky Lake-E Ubox Registers + +pci:v00008086d00002018* + ID_MODEL_FROM_DATABASE=Sky Lake-E M2PCI Registers + +pci:v00008086d0000201A* + ID_MODEL_FROM_DATABASE=Sky Lake-E Non-Transparent Bridge Registers + +pci:v00008086d0000201C* + ID_MODEL_FROM_DATABASE=Sky Lake-E Non-Transparent Bridge Registers + +pci:v00008086d0000201D* + ID_MODEL_FROM_DATABASE=Volume Management Device NVMe RAID Controller + +pci:v00008086d00002020* + ID_MODEL_FROM_DATABASE=Sky Lake-E DMI3 Registers + +pci:v00008086d00002020sv000015D9sd0000095D* + ID_MODEL_FROM_DATABASE=Sky Lake-E DMI3 Registers (X11SPM-TF) + +pci:v00008086d00002021* + ID_MODEL_FROM_DATABASE=Sky Lake-E CBDMA Registers + +pci:v00008086d00002024* + ID_MODEL_FROM_DATABASE=Sky Lake-E MM/Vt-d Configuration Registers + +pci:v00008086d00002025* + ID_MODEL_FROM_DATABASE=Sky Lake-E RAS + +pci:v00008086d00002026* + ID_MODEL_FROM_DATABASE=Sky Lake-E IOAPIC + +pci:v00008086d00002030* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port A + +pci:v00008086d00002031* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port B + +pci:v00008086d00002032* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port C + +pci:v00008086d00002033* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCI Express Root Port D + +pci:v00008086d00002034* + ID_MODEL_FROM_DATABASE=Sky Lake-E VT-d + +pci:v00008086d00002035* + ID_MODEL_FROM_DATABASE=Sky Lake-E RAS Configuration Registers + +pci:v00008086d00002036* + ID_MODEL_FROM_DATABASE=Sky Lake-E IOxAPIC Configuration Registers + +pci:v00008086d00002040* + ID_MODEL_FROM_DATABASE=Sky Lake-E Integrated Memory Controller + +pci:v00008086d00002041* + ID_MODEL_FROM_DATABASE=Sky Lake-E Integrated Memory Controller + +pci:v00008086d00002042* + ID_MODEL_FROM_DATABASE=Sky Lake-E Integrated Memory Controller + +pci:v00008086d00002043* + ID_MODEL_FROM_DATABASE=Sky Lake-E Integrated Memory Controller + +pci:v00008086d00002044* + ID_MODEL_FROM_DATABASE=Sky Lake-E Integrated Memory Controller + +pci:v00008086d00002045* + ID_MODEL_FROM_DATABASE=Sky Lake-E LM Channel 1 + +pci:v00008086d00002046* + ID_MODEL_FROM_DATABASE=Sky Lake-E LMS Channel 1 + +pci:v00008086d00002047* + ID_MODEL_FROM_DATABASE=Sky Lake-E LMDP Channel 1 + +pci:v00008086d00002048* + ID_MODEL_FROM_DATABASE=Sky Lake-E DECS Channel 2 + +pci:v00008086d00002049* + ID_MODEL_FROM_DATABASE=Sky Lake-E LM Channel 2 + +pci:v00008086d0000204A* + ID_MODEL_FROM_DATABASE=Sky Lake-E LMS Channel 2 + +pci:v00008086d0000204B* + ID_MODEL_FROM_DATABASE=Sky Lake-E LMDP Channel 2 + +pci:v00008086d0000204C* + ID_MODEL_FROM_DATABASE=Sky Lake-E M3KTI Registers + +pci:v00008086d0000204D* + ID_MODEL_FROM_DATABASE=Sky Lake-E M3KTI Registers + +pci:v00008086d0000204E* + ID_MODEL_FROM_DATABASE=Sky Lake-E M3KTI Registers + +pci:v00008086d00002054* + ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers + +pci:v00008086d00002055* + ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers + +pci:v00008086d00002056* + ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers + +pci:v00008086d00002057* + ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers + +pci:v00008086d00002058* + ID_MODEL_FROM_DATABASE=Sky Lake-E KTI 0 + +pci:v00008086d00002059* + ID_MODEL_FROM_DATABASE=Sky Lake-E UPI Registers + +pci:v00008086d00002066* + ID_MODEL_FROM_DATABASE=Sky Lake-E Integrated Memory Controller + +pci:v00008086d00002068* + ID_MODEL_FROM_DATABASE=Sky Lake-E DDRIO Registers + +pci:v00008086d00002069* + ID_MODEL_FROM_DATABASE=Sky Lake-E DDRIO Registers + +pci:v00008086d0000206A* + ID_MODEL_FROM_DATABASE=Sky Lake-E IOxAPIC Configuration Registers + +pci:v00008086d0000206E* + ID_MODEL_FROM_DATABASE=Sky Lake-E DDRIO Registers + +pci:v00008086d0000206F* + ID_MODEL_FROM_DATABASE=Sky Lake-E DDRIO Registers + +pci:v00008086d00002078* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers + +pci:v00008086d0000207A* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers + +pci:v00008086d00002080* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers + +pci:v00008086d00002081* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers + +pci:v00008086d00002082* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers + +pci:v00008086d00002083* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers + +pci:v00008086d00002084* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers + +pci:v00008086d00002085* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers + +pci:v00008086d00002086* + ID_MODEL_FROM_DATABASE=Sky Lake-E PCU Registers + +pci:v00008086d00002088* + ID_MODEL_FROM_DATABASE=Sky Lake-E DDRIO Registers + +pci:v00008086d0000208D* + ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers + +pci:v00008086d0000208E* + ID_MODEL_FROM_DATABASE=Sky Lake-E CHA Registers + +pci:v00008086d00002241* + ID_MODEL_FROM_DATABASE=Larrabee + +pci:v00008086d00002250* + ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor 5100 series + +pci:v00008086d0000225C* + ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor SE10/7120 series + +pci:v00008086d0000225D* + ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor 3120 series + +pci:v00008086d0000225E* + ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor 31S1 + +pci:v00008086d00002262* + ID_MODEL_FROM_DATABASE=Xeon Phi coprocessor 7220 + +pci:v00008086d00002280* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SoC Transaction Register + +pci:v00008086d00002284* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series High Definition Audio Controller + +pci:v00008086d00002286* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO1 DMA Controller + +pci:v00008086d0000228A* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO1 HSUART Controller #1 + +pci:v00008086d0000228C* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO1 HSUART Controller #2 + +pci:v00008086d00002292* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx SMBus Controller + +pci:v00008086d00002294* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series MMC Controller + +pci:v00008086d00002295* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SDIO Controller + +pci:v00008086d00002296* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SD Controller + +pci:v00008086d00002298* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Trusted Execution Engine + +pci:v00008086d0000229C* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCU + +pci:v00008086d000022A3* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SATA Controller + +pci:v00008086d000022A4* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SATA AHCI Controller + +pci:v00008086d000022A8* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Low Power Engine Audio + +pci:v00008086d000022B0* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Integrated Graphics Controller + +pci:v00008086d000022B1* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Integrated Graphics Controller + +pci:v00008086d000022B5* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series USB xHCI Controller + +pci:v00008086d000022B8* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Imaging Unit + +pci:v00008086d000022C0* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 DMA Controller + +pci:v00008086d000022C1* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #1 + +pci:v00008086d000022C2* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #2 + +pci:v00008086d000022C3* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #3 + +pci:v00008086d000022C4* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #4 + +pci:v00008086d000022C5* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #5 + +pci:v00008086d000022C6* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #6 + +pci:v00008086d000022C7* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #7 + +pci:v00008086d000022C8* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCI Express Port #1 + +pci:v00008086d000022CA* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCI Express Port #2 + +pci:v00008086d000022CC* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCI Express Port #3 + +pci:v00008086d000022CE* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCI Express Port #4 + +pci:v00008086d000022DC* + ID_MODEL_FROM_DATABASE=Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Power Management Controller + +pci:v00008086d00002310* + ID_MODEL_FROM_DATABASE=DH89xxCC LPC Controller + +pci:v00008086d00002323* + ID_MODEL_FROM_DATABASE=DH89xxCC 4 Port SATA AHCI Controller + +pci:v00008086d00002330* + ID_MODEL_FROM_DATABASE=DH89xxCC SMBus Controller + +pci:v00008086d00002331* + ID_MODEL_FROM_DATABASE=DH89xxCC Chap Counter + +pci:v00008086d00002332* + ID_MODEL_FROM_DATABASE=DH89xxCC Thermal Subsystem + +pci:v00008086d00002334* + ID_MODEL_FROM_DATABASE=DH89xxCC USB2 Enhanced Host Controller #1 + +pci:v00008086d00002335* + ID_MODEL_FROM_DATABASE=DH89xxCC USB2 Enhanced Host Controller #1 + +pci:v00008086d00002342* + ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #1 + +pci:v00008086d00002343* + ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #1 + +pci:v00008086d00002344* + ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #2 + +pci:v00008086d00002345* + ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #2 + +pci:v00008086d00002346* + ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #3 + +pci:v00008086d00002347* + ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #3 + +pci:v00008086d00002348* + ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #4 + +pci:v00008086d00002349* + ID_MODEL_FROM_DATABASE=DH89xxCC PCI Express Root Port #4 + +pci:v00008086d00002360* + ID_MODEL_FROM_DATABASE=DH89xxCC Watchdog Timer + +pci:v00008086d00002364* + ID_MODEL_FROM_DATABASE=DH89xxCC MEI 0 + +pci:v00008086d00002365* + ID_MODEL_FROM_DATABASE=DH89xxCC MEI 1 + +pci:v00008086d00002390* + ID_MODEL_FROM_DATABASE=DH895XCC Series LPC Controller + +pci:v00008086d000023A1* + ID_MODEL_FROM_DATABASE=DH895XCC Series 2-Port SATA Controller [IDE Mode] + +pci:v00008086d000023A3* + ID_MODEL_FROM_DATABASE=DH895XCC Series 4-Port SATA Controller [AHCI Mode] + +pci:v00008086d000023A6* + ID_MODEL_FROM_DATABASE=DH895XCC Series 2-Port SATA Controller [IDE Mode] + +pci:v00008086d000023B0* + ID_MODEL_FROM_DATABASE=DH895XCC Series SMBus Controller + +pci:v00008086d000023B1* + ID_MODEL_FROM_DATABASE=DH895XCC Series CHAP Counter + +pci:v00008086d000023B2* + ID_MODEL_FROM_DATABASE=DH895XCC Series Thermal Management Controller + +pci:v00008086d000023B4* + ID_MODEL_FROM_DATABASE=DH895XCC Series USB2 Enhanced Host Controller #1 + +pci:v00008086d000023B5* + ID_MODEL_FROM_DATABASE=DH895XCC Series USB2 Enhanced Host Controller #1 + +pci:v00008086d000023C2* + ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #1 + +pci:v00008086d000023C3* + ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #1 + +pci:v00008086d000023C4* + ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #2 + +pci:v00008086d000023C5* + ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #2 + +pci:v00008086d000023C6* + ID_MODEL_FROM_DATABASE=CDH895XCC Series PCI Express Root Port #3 + +pci:v00008086d000023C7* + ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #3 + +pci:v00008086d000023C8* + ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #4 + +pci:v00008086d000023C9* + ID_MODEL_FROM_DATABASE=DH895XCC Series PCI Express Root Port #4 + +pci:v00008086d000023E0* + ID_MODEL_FROM_DATABASE=DH895XCC Series Watchdog Timer + +pci:v00008086d000023E4* + ID_MODEL_FROM_DATABASE=DH895XCC Series MEI Controller #1 + +pci:v00008086d000023E5* + ID_MODEL_FROM_DATABASE=DH895XCC Series MEI Controller #2 + +pci:v00008086d00002410* + ID_MODEL_FROM_DATABASE=82801AA ISA Bridge (LPC) + +pci:v00008086d00002411* + ID_MODEL_FROM_DATABASE=82801AA IDE Controller + +pci:v00008086d00002412* + ID_MODEL_FROM_DATABASE=82801AA USB Controller + +pci:v00008086d00002413* + ID_MODEL_FROM_DATABASE=82801AA SMBus Controller + +pci:v00008086d00002415* + ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller + +pci:v00008086d00002415sv00001028sd00000095* + ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (Precision Workstation 220 Integrated Digital Audio) + +pci:v00008086d00002415sv00001028sd000000B4* + ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (OptiPlex GX110) + +pci:v00008086d00002415sv0000110Asd00000051* + ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (Activy 2xx) + +pci:v00008086d00002415sv000011D4sd00000040* + ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (SoundMAX Integrated Digital Audio) + +pci:v00008086d00002415sv000011D4sd00000048* + ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (SoundMAX Integrated Digital Audio) + +pci:v00008086d00002415sv000011D4sd00005340* + ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (SoundMAX Integrated Digital Audio) + +pci:v00008086d00002415sv00001734sd00001025* + ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (Activy 3xx) + +pci:v00008086d00002415sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801AA AC'97 Audio Controller (QEMU Virtual Machine) + +pci:v00008086d00002416* + ID_MODEL_FROM_DATABASE=82801AA AC'97 Modem Controller + +pci:v00008086d00002418* + ID_MODEL_FROM_DATABASE=82801AA PCI Bridge + +pci:v00008086d00002420* + ID_MODEL_FROM_DATABASE=82801AB ISA Bridge (LPC) + +pci:v00008086d00002421* + ID_MODEL_FROM_DATABASE=82801AB IDE Controller + +pci:v00008086d00002422* + ID_MODEL_FROM_DATABASE=82801AB USB Controller + +pci:v00008086d00002423* + ID_MODEL_FROM_DATABASE=82801AB SMBus Controller + +pci:v00008086d00002425* + ID_MODEL_FROM_DATABASE=82801AB AC'97 Audio Controller + +pci:v00008086d00002425sv000011D4sd00000040* + ID_MODEL_FROM_DATABASE=82801AB AC'97 Audio Controller (SoundMAX Integrated Digital Audio) + +pci:v00008086d00002425sv000011D4sd00000048* + ID_MODEL_FROM_DATABASE=82801AB AC'97 Audio Controller (SoundMAX Integrated Digital Audio) + +pci:v00008086d00002426* + ID_MODEL_FROM_DATABASE=82801AB AC'97 Modem Controller + +pci:v00008086d00002428* + ID_MODEL_FROM_DATABASE=82801AB PCI Bridge + +pci:v00008086d00002440* + ID_MODEL_FROM_DATABASE=82801BA ISA Bridge (LPC) + +pci:v00008086d00002440sv00008086sd00005744* + ID_MODEL_FROM_DATABASE=82801BA ISA Bridge (LPC) (S845WD1-E) + +pci:v00008086d00002442* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 + +pci:v00008086d00002442sv00001014sd000001C6* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Netvista A40/A40p) + +pci:v00008086d00002442sv00001025sd00001016* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Travelmate 612 TX) + +pci:v00008086d00002442sv00001028sd000000C7* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Dimension 8100) + +pci:v00008086d00002442sv00001028sd000000D8* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Precision 530) + +pci:v00008086d00002442sv00001028sd0000010E* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Optiplex GX240) + +pci:v00008086d00002442sv0000103Csd0000126F* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (e-pc 40) + +pci:v00008086d00002442sv00001043sd00008027* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (TUSL2-C Mainboard) + +pci:v00008086d00002442sv0000104Dsd000080DF* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Vaio PCG-FX403) + +pci:v00008086d00002442sv0000147Bsd00000505* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (BL7 motherboard) + +pci:v00008086d00002442sv0000147Bsd00000507* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (TH7II-RAID) + +pci:v00008086d00002442sv00008086sd00004532* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (Desktop Board D815EEA2/D815EFV) + +pci:v00008086d00002442sv00008086sd00004557* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (D815EGEW Mainboard) + +pci:v00008086d00002442sv00008086sd00005744* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #1 (S845WD1-E mainboard) + +pci:v00008086d00002443* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller + +pci:v00008086d00002443sv00001014sd000001C6* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Netvista A40/A40p) + +pci:v00008086d00002443sv00001025sd00001016* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Travelmate 612 TX) + +pci:v00008086d00002443sv00001028sd000000C7* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Dimension 8100) + +pci:v00008086d00002443sv00001028sd000000D8* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Precision 530) + +pci:v00008086d00002443sv00001028sd0000010E* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Optiplex GX240) + +pci:v00008086d00002443sv0000103Csd0000126F* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (e-pc 40) + +pci:v00008086d00002443sv00001043sd00008027* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (TUSL2-C Mainboard) + +pci:v00008086d00002443sv0000104Dsd000080DF* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Vaio PCG-FX403) + +pci:v00008086d00002443sv0000147Bsd00000505* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (BL7 motherboard) + +pci:v00008086d00002443sv0000147Bsd00000507* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (TH7II-RAID) + +pci:v00008086d00002443sv000015D9sd00003280* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Supermicro P4SBE Mainboard) + +pci:v00008086d00002443sv00008086sd00004532* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (Desktop Board D815EEA2/D815EFV) + +pci:v00008086d00002443sv00008086sd00004557* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (D815EGEW Mainboard) + +pci:v00008086d00002443sv00008086sd00005744* + ID_MODEL_FROM_DATABASE=82801BA/BAM SMBus Controller (S845WD1-E mainboard) + +pci:v00008086d00002444* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 + +pci:v00008086d00002444sv00001025sd00001016* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Travelmate 612 TX) + +pci:v00008086d00002444sv00001028sd000000C7* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Dimension 8100) + +pci:v00008086d00002444sv00001028sd000000D8* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Precision 530) + +pci:v00008086d00002444sv00001028sd0000010E* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Optiplex GX240) + +pci:v00008086d00002444sv0000103Csd0000126F* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (e-pc 40) + +pci:v00008086d00002444sv00001043sd00008027* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (TUSL2-C Mainboard) + +pci:v00008086d00002444sv0000104Dsd000080DF* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Vaio PCG-FX403) + +pci:v00008086d00002444sv0000147Bsd00000505* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (BL7 motherboard) + +pci:v00008086d00002444sv0000147Bsd00000507* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (TH7II-RAID) + +pci:v00008086d00002444sv00008086sd00004532* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (Desktop Board D815EEA2/D815EFV) + +pci:v00008086d00002444sv00008086sd00005744* + ID_MODEL_FROM_DATABASE=82801BA/BAM UHCI USB 1.1 Controller #2 (S845WD1-E mainboard) + +pci:v00008086d00002445* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller + +pci:v00008086d00002445sv00000E11sd0000000B* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Compaq Deskpro EN Audio) + +pci:v00008086d00002445sv00000E11sd00000088* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Evo D500) + +pci:v00008086d00002445sv00001014sd000001C6* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Netvista A40/A40p) + +pci:v00008086d00002445sv00001025sd00001016* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Travelmate 612 TX) + +pci:v00008086d00002445sv00001028sd000000D8* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Precision 530) + +pci:v00008086d00002445sv0000103Csd0000126F* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (e-pc 40) + +pci:v00008086d00002445sv0000104Dsd000080DF* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Vaio PCG-FX403) + +pci:v00008086d00002445sv00001462sd00003370* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (STAC9721 AC) + +pci:v00008086d00002445sv0000147Bsd00000505* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (BL7 motherboard) + +pci:v00008086d00002445sv0000147Bsd00000507* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (TH7II-RAID) + +pci:v00008086d00002445sv00008086sd00004557* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (D815EGEW Mainboard) + +pci:v00008086d00002445sv00008086sd00004656* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Audio Controller (Desktop Board D815EFV) + +pci:v00008086d00002446* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Modem Controller + +pci:v00008086d00002446sv00001025sd00001016* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Modem Controller (Travelmate 612 TX) + +pci:v00008086d00002446sv0000104Dsd000080DF* + ID_MODEL_FROM_DATABASE=82801BA/BAM AC'97 Modem Controller (Vaio PCG-FX403) + +pci:v00008086d00002448* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge + +pci:v00008086d00002448sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Latitude E6410) + +pci:v00008086d00002448sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Latitude E6510) + +pci:v00008086d00002448sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Compaq nw8240 Mobile Workstation) + +pci:v00008086d00002448sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Compaq nc6220 Notebook PC) + +pci:v00008086d00002448sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (NX6110/NC6120) + +pci:v00008086d00002448sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Compaq nx9420 Notebook) + +pci:v00008086d00002448sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Compaq nw8440) + +pci:v00008086d00002448sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Compaq 6910p) + +pci:v00008086d00002448sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (X58LE) + +pci:v00008086d00002448sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (VAIO VGN-NR120E) + +pci:v00008086d00002448sv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (D270S/D250S Motherboard) + +pci:v00008086d00002448sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d00002448sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (P30 notebook) + +pci:v00008086d00002448sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (R730 Laptop) + +pci:v00008086d00002448sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Notebook N150P) + +pci:v00008086d00002448sv00001458sd00005000* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (GA-D525TUD) + +pci:v00008086d00002448sv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Amilo M1420) + +pci:v00008086d00002448sv000017AAsd00002013* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (ThinkPad R60e) + +pci:v00008086d00002448sv000017AAsd000020AE* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (ThinkPad T61/R61) + +pci:v00008086d00002448sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00002448sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002448sv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (Desktop Board D425KT) + +pci:v00008086d00002448sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801 Mobile PCI Bridge (CCG-RUMBA) + +pci:v00008086d00002449* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller + +pci:v00008086d00002449sv00000E11sd00000012* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VM) + +pci:v00008086d00002449sv00000E11sd00000091* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd000001CE* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd000001DC* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd000001EB* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd000001EC* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd00000202* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd00000205* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd00000217* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd00000234* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd0000023D* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd00000244* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd00000245* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001014sd00000265* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (PRO/100 VE Desktop Connection) + +pci:v00008086d00002449sv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (PRO/100 VE Desktop Connection) + +pci:v00008086d00002449sv00001014sd0000026A* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (PRO/100 VE Desktop Connection) + +pci:v00008086d00002449sv0000109Fsd0000315D* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv0000109Fsd00003181* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00001179sd0000FF01* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (PRO/100 VE Network Connection) + +pci:v00008086d00002449sv00001186sd00007801* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv0000144Dsd00002602* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (HomePNA 1M CNR) + +pci:v00008086d00002449sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (QEMU Virtual Machine) + +pci:v00008086d00002449sv00008086sd00003010* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00008086sd00003011* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VM) + +pci:v00008086d00002449sv00008086sd00003012* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (82562EH based Phoneline) + +pci:v00008086d00002449sv00008086sd00003013* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VE) + +pci:v00008086d00002449sv00008086sd00003014* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 VM) + +pci:v00008086d00002449sv00008086sd00003015* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (82562EH based Phoneline) + +pci:v00008086d00002449sv00008086sd00003016* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 P Mobile Combo) + +pci:v00008086d00002449sv00008086sd00003017* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100 P Mobile) + +pci:v00008086d00002449sv00008086sd00003018* + ID_MODEL_FROM_DATABASE=82801BA/BAM/CA/CAM Ethernet Controller (EtherExpress PRO/100) + +pci:v00008086d0000244A* + ID_MODEL_FROM_DATABASE=82801BAM IDE U100 Controller + +pci:v00008086d0000244Asv00001025sd00001016* + ID_MODEL_FROM_DATABASE=82801BAM IDE U100 Controller (Travelmate 612TX) + +pci:v00008086d0000244Asv0000104Dsd000080DF* + ID_MODEL_FROM_DATABASE=82801BAM IDE U100 Controller (Vaio PCG-FX403) + +pci:v00008086d0000244B* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller + +pci:v00008086d0000244Bsv00001014sd000001C6* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Netvista A40/A40p) + +pci:v00008086d0000244Bsv00001028sd000000C7* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Dimension 8100) + +pci:v00008086d0000244Bsv00001028sd000000D8* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Precision 530) + +pci:v00008086d0000244Bsv00001028sd0000010E* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Optiplex GX240) + +pci:v00008086d0000244Bsv0000103Csd0000126F* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (e-pc 40) + +pci:v00008086d0000244Bsv00001043sd00008027* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (TUSL2-C Mainboard) + +pci:v00008086d0000244Bsv0000147Bsd00000505* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (BL7 motherboard) + +pci:v00008086d0000244Bsv0000147Bsd00000507* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (TH7II-RAID) + +pci:v00008086d0000244Bsv000015D9sd00003280* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Supermicro P4SBE Mainboard) + +pci:v00008086d0000244Bsv00008086sd00004532* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (Desktop Board D815EEA2/D815EFV) + +pci:v00008086d0000244Bsv00008086sd00004557* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (D815EGEW Mainboard) + +pci:v00008086d0000244Bsv00008086sd00005744* + ID_MODEL_FROM_DATABASE=82801BA IDE U100 Controller (S845WD1-E mainboard) + +pci:v00008086d0000244C* + ID_MODEL_FROM_DATABASE=82801BAM ISA Bridge (LPC) + +pci:v00008086d0000244E* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge + +pci:v00008086d0000244Esv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (NetVista A30p) + +pci:v00008086d0000244Esv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Inspiron 530) + +pci:v00008086d0000244Esv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Optiplex 755) + +pci:v00008086d0000244Esv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (OptiPlex 980) + +pci:v00008086d0000244Esv00001028sd000004F7* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (PowerEdge R320 server) + +pci:v00008086d0000244Esv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Pavilion A1512X) + +pci:v00008086d0000244Esv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Asus IPIBL-LB Motherboard) + +pci:v00008086d0000244Esv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (ProLiant DL140 G3) + +pci:v00008086d0000244Esv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (ProLiant ML150 G6 Server) + +pci:v00008086d0000244Esv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (P5K PRO Motherboard) + +pci:v00008086d0000244Esv00001043sd0000844D* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (P8 series motherboard) + +pci:v00008086d0000244Esv00001043sd00008534* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (ASUS B85-PLUS) + +pci:v00008086d0000244Esv00001458sd00005000* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Motherboard) + +pci:v00008086d0000244Esv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d0000244Esv00001462sd00007418* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Wind PC MS-7418) + +pci:v00008086d0000244Esv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (C7SIM-Q Motherboard) + +pci:v00008086d0000244Esv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (X7DBN Motherboard) + +pci:v00008086d0000244Esv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (CC11/CL11) + +pci:v00008086d0000244Esv00008086sd00007270* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge (Server Board S1200BTS) + +pci:v00008086d00002450* + ID_MODEL_FROM_DATABASE=82801E ISA Bridge (LPC) + +pci:v00008086d00002452* + ID_MODEL_FROM_DATABASE=82801E USB Controller + +pci:v00008086d00002453* + ID_MODEL_FROM_DATABASE=82801E SMBus Controller + +pci:v00008086d00002459* + ID_MODEL_FROM_DATABASE=82801E Ethernet Controller 0 + +pci:v00008086d0000245B* + ID_MODEL_FROM_DATABASE=82801E IDE U100 Controller + +pci:v00008086d0000245D* + ID_MODEL_FROM_DATABASE=82801E Ethernet Controller 1 + +pci:v00008086d0000245E* + ID_MODEL_FROM_DATABASE=82801E PCI Bridge + +pci:v00008086d00002480* + ID_MODEL_FROM_DATABASE=82801CA LPC Interface Controller + +pci:v00008086d00002482* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 + +pci:v00008086d00002482sv00000E11sd00000030* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (Evo N600c) + +pci:v00008086d00002482sv00001014sd00000220* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (ThinkPad A/T/X Series) + +pci:v00008086d00002482sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00008086d00002482sv000015D9sd00003480* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (P4DP6) + +pci:v00008086d00002482sv00008086sd00001958* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (vpr Matrix 170B4) + +pci:v00008086d00002482sv00008086sd00003424* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (SE7501HG2 Mainboard) + +pci:v00008086d00002482sv00008086sd00004541* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #1 (Latitude C640) + +pci:v00008086d00002483* + ID_MODEL_FROM_DATABASE=82801CA/CAM SMBus Controller + +pci:v00008086d00002483sv00001014sd00000220* + ID_MODEL_FROM_DATABASE=82801CA/CAM SMBus Controller (ThinkPad A/T/X Series) + +pci:v00008086d00002483sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=82801CA/CAM SMBus Controller (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00008086d00002483sv000015D9sd00003480* + ID_MODEL_FROM_DATABASE=82801CA/CAM SMBus Controller (P4DP6) + +pci:v00008086d00002483sv00008086sd00001958* + ID_MODEL_FROM_DATABASE=82801CA/CAM SMBus Controller (vpr Matrix 170B4) + +pci:v00008086d00002484* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 + +pci:v00008086d00002484sv00000E11sd00000030* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 (Evo N600c) + +pci:v00008086d00002484sv00001014sd00000220* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 (ThinkPad A/T/X Series) + +pci:v00008086d00002484sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00008086d00002484sv000015D9sd00003480* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 (P4DP6) + +pci:v00008086d00002484sv00008086sd00001958* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #2 (vpr Matrix 170B4) + +pci:v00008086d00002485* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller + +pci:v00008086d00002485sv00001013sd00005959* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (Crystal WMD Audio Codec) + +pci:v00008086d00002485sv00001014sd00000222* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (ThinkPad A30/A30p/T23) + +pci:v00008086d00002485sv00001014sd00000508* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (ThinkPad T30) + +pci:v00008086d00002485sv00001014sd0000051C* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (ThinkPad A/T/X Series) + +pci:v00008086d00002485sv00001043sd00001583* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (L3C (SPDIF)) + +pci:v00008086d00002485sv00001043sd00001623* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (L2B (no SPDIF)) + +pci:v00008086d00002485sv00001043sd00001643* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (L3F) + +pci:v00008086d00002485sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00008086d00002485sv0000144Dsd0000C006* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Audio Controller (vpr Matrix 170B4) + +pci:v00008086d00002486* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller + +pci:v00008086d00002486sv00001014sd00000223* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (ThinkPad A/T/X Series) + +pci:v00008086d00002486sv00001014sd00000503* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (ThinkPad R31) + +pci:v00008086d00002486sv00001014sd0000051A* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (ThinkPad A/T/X Series) + +pci:v00008086d00002486sv0000101Fsd00001025* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (620 Series) + +pci:v00008086d00002486sv00001043sd00001496* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (PCtel HSP56 MR) + +pci:v00008086d00002486sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00008086d00002486sv0000134Dsd00004C21* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (Dell Inspiron 2100 internal modem) + +pci:v00008086d00002486sv0000144Dsd00002115* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (vpr Matrix 170B4 internal modem) + +pci:v00008086d00002486sv000014F1sd00005421* + ID_MODEL_FROM_DATABASE=82801CA/CAM AC'97 Modem Controller (MD56ORD V.92 MDC Modem) + +pci:v00008086d00002487* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 + +pci:v00008086d00002487sv00000E11sd00000030* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 (Evo N600c) + +pci:v00008086d00002487sv00001014sd00000220* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 (ThinkPad A/T/X Series) + +pci:v00008086d00002487sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00008086d00002487sv000015D9sd00003480* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 (P4DP6) + +pci:v00008086d00002487sv00008086sd00001958* + ID_MODEL_FROM_DATABASE=82801CA/CAM USB Controller #3 (vpr Matrix 170B4) + +pci:v00008086d0000248A* + ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller + +pci:v00008086d0000248Asv00000E11sd00000030* + ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller (Evo N600c) + +pci:v00008086d0000248Asv00001014sd00000220* + ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller (ThinkPad A/T/X Series) + +pci:v00008086d0000248Asv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00008086d0000248Asv00008086sd00001958* + ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller (vpr Matrix 170B4) + +pci:v00008086d0000248Asv00008086sd00004541* + ID_MODEL_FROM_DATABASE=82801CAM IDE U100 Controller (Latitude C640) + +pci:v00008086d0000248B* + ID_MODEL_FROM_DATABASE=82801CA Ultra ATA Storage Controller + +pci:v00008086d0000248Bsv000015D9sd00003480* + ID_MODEL_FROM_DATABASE=82801CA Ultra ATA Storage Controller (P4DP6) + +pci:v00008086d0000248C* + ID_MODEL_FROM_DATABASE=82801CAM ISA Bridge (LPC) + +pci:v00008086d000024C0* + ID_MODEL_FROM_DATABASE=82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge + +pci:v00008086d000024C0sv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge (NetVista A30p) + +pci:v00008086d000024C0sv00001462sd00005800* + ID_MODEL_FROM_DATABASE=82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge (845PE Max (MS-6580)) + +pci:v00008086d000024C1* + ID_MODEL_FROM_DATABASE=82801DBL (ICH4-L) IDE Controller + +pci:v00008086d000024C2* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 + +pci:v00008086d000024C2sv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (NetVista A30p) + +pci:v00008086d000024C2sv00001014sd0000052D* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (ThinkPad) + +pci:v00008086d000024C2sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (TravelMate 290) + +pci:v00008086d000024C2sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) + +pci:v00008086d000024C2sv00001028sd00000126* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Optiplex GX260) + +pci:v00008086d000024C2sv00001028sd00000160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Dimension 2400) + +pci:v00008086d000024C2sv00001028sd00000163* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Latitude D505) + +pci:v00008086d000024C2sv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Inspiron 700m/710m) + +pci:v00008086d000024C2sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Inspiron 5160) + +pci:v00008086d000024C2sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (NC8000 laptop) + +pci:v00008086d000024C2sv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (NC6000 laptop) + +pci:v00008086d000024C2sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (tc1100 tablet) + +pci:v00008086d000024C2sv00001043sd00008089* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (P4B533) + +pci:v00008086d000024C2sv00001071sd00008160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (MIM2000) + +pci:v00008086d000024C2sv0000114Asd00000582* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (PC8 onboard USB 1.x) + +pci:v00008086d000024C2sv0000144Dsd0000C005* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (X10 Laptop) + +pci:v00008086d000024C2sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (P30/P35 notebook) + +pci:v00008086d000024C2sv00001462sd00005800* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (845PE Max (MS-6580)) + +pci:v00008086d000024C2sv00001509sd00002990* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Averatec 5110H laptop) + +pci:v00008086d000024C2sv00001734sd00001004* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (D1451 Mainboard (SCENIC N300, i845GV)) + +pci:v00008086d000024C2sv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Amilo M1420) + +pci:v00008086d000024C2sv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Cx9 / Vx9 mainboard) + +pci:v00008086d000024C2sv00008086sd000024C2* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Latitude X300) + +pci:v00008086d000024C2sv00008086sd00004541* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (Latitude D400/D500) + +pci:v00008086d000024C2sv0000E4BFsd00000CC9* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (CC9-SAMBA) + +pci:v00008086d000024C2sv0000E4BFsd00000CD2* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 (CD2-BEBOP) + +pci:v00008086d000024C3* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller + +pci:v00008086d000024C3sv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (NetVista A30p) + +pci:v00008086d000024C3sv00001014sd0000052D* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (ThinkPad) + +pci:v00008086d000024C3sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (TravelMate 290) + +pci:v00008086d000024C3sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) + +pci:v00008086d000024C3sv00001028sd00000126* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Optiplex GX260) + +pci:v00008086d000024C3sv00001028sd0000014F* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Latitude X300) + +pci:v00008086d000024C3sv00001028sd00000160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Dimension 2400) + +pci:v00008086d000024C3sv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Inspiron 700m/710m) + +pci:v00008086d000024C3sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (NC8000 laptop) + +pci:v00008086d000024C3sv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (NC6000 laptop) + +pci:v00008086d000024C3sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (tc1100 tablet) + +pci:v00008086d000024C3sv00001071sd00008160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (MIM2000) + +pci:v00008086d000024C3sv0000114Asd00000582* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (PC8 onboard SMbus) + +pci:v00008086d000024C3sv0000144Dsd0000C005* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (X10 Laptop) + +pci:v00008086d000024C3sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (P30/P35 notebook) + +pci:v00008086d000024C3sv00001458sd000024C2* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (GA-8PE667 Ultra) + +pci:v00008086d000024C3sv00001462sd00005800* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (845PE Max (MS-6580)) + +pci:v00008086d000024C3sv00001734sd00001004* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (D1451 Mainboard (SCENIC N300, i845GV)) + +pci:v00008086d000024C3sv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Amilo M1420) + +pci:v00008086d000024C3sv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (Cx9 / Vx9 mainboard) + +pci:v00008086d000024C3sv0000E4BFsd00000CC9* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (CC9-SAMBA) + +pci:v00008086d000024C3sv0000E4BFsd00000CD2* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller (CD2-BEBOP) + +pci:v00008086d000024C4* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 + +pci:v00008086d000024C4sv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (NetVista A30p) + +pci:v00008086d000024C4sv00001014sd0000052D* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (ThinkPad) + +pci:v00008086d000024C4sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (TravelMate 290) + +pci:v00008086d000024C4sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) + +pci:v00008086d000024C4sv00001028sd00000126* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Optiplex GX260) + +pci:v00008086d000024C4sv00001028sd00000160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Dimension 2400) + +pci:v00008086d000024C4sv00001028sd00000163* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Latitude D505) + +pci:v00008086d000024C4sv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Inspiron 700m/710m) + +pci:v00008086d000024C4sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Inspiron 5160) + +pci:v00008086d000024C4sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (NC8000 laptop) + +pci:v00008086d000024C4sv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (NC6000 laptop) + +pci:v00008086d000024C4sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (tc1100 tablet) + +pci:v00008086d000024C4sv00001043sd00008089* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (P4B533) + +pci:v00008086d000024C4sv00001071sd00008160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (MIM2000) + +pci:v00008086d000024C4sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (P30/P35 notebook) + +pci:v00008086d000024C4sv00001462sd00005800* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (845PE Max (MS-6580)) + +pci:v00008086d000024C4sv00001509sd00002990* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Averatec 5110H) + +pci:v00008086d000024C4sv00001734sd00001004* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (D1451 Mainboard (SCENIC N300, i845GV)) + +pci:v00008086d000024C4sv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Cx9 / Vx9 mainboard) + +pci:v00008086d000024C4sv00008086sd000024C2* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Latitude X300) + +pci:v00008086d000024C4sv00008086sd00004541* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (Latitude D400/D500) + +pci:v00008086d000024C4sv0000E4BFsd00000CC9* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (CC9-SAMBA) + +pci:v00008086d000024C4sv0000E4BFsd00000CD2* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 (CD2-BEBOP) + +pci:v00008086d000024C5* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller + +pci:v00008086d000024C5sv00000E11sd000000B8* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Analog Devices Inc. codec [SoundMAX]) + +pci:v00008086d000024C5sv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (NetVista A30p) + +pci:v00008086d000024C5sv00001014sd00000537* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (ThinkPad T4x Series) + +pci:v00008086d000024C5sv00001014sd0000055F* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Thinkpad R50e model 1634) + +pci:v00008086d000024C5sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (TravelMate 290) + +pci:v00008086d000024C5sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) + +pci:v00008086d000024C5sv00001028sd00000139* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Latitude D400) + +pci:v00008086d000024C5sv00001028sd0000014F* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Latitude X300) + +pci:v00008086d000024C5sv00001028sd00000152* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Latitude D500) + +pci:v00008086d000024C5sv00001028sd00000160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Dimension 2400) + +pci:v00008086d000024C5sv00001028sd00000163* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Latitude D505) + +pci:v00008086d000024C5sv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Inspiron 700m/710m [SigmaTel STAC9750,51]) + +pci:v00008086d000024C5sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Inspiron 5160) + +pci:v00008086d000024C5sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (NC8000 laptop) + +pci:v00008086d000024C5sv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (NC6000 laptop) + +pci:v00008086d000024C5sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (tc1100 tablet) + +pci:v00008086d000024C5sv00001043sd00001713* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (M2400N/M6800N laptop) + +pci:v00008086d000024C5sv00001043sd000080B0* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (P4B533) + +pci:v00008086d000024C5sv00001071sd00008160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (MIM2000) + +pci:v00008086d000024C5sv00001179sd00000201* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Toshiba Tecra M1) + +pci:v00008086d000024C5sv0000144Dsd0000C005* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (X10 Laptop) + +pci:v00008086d000024C5sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (P30/P35 notebook) + +pci:v00008086d000024C5sv00001458sd0000A002* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (GA-8PE667 Ultra) + +pci:v00008086d000024C5sv00001462sd00005800* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (845PE Max (MS-6580)) + +pci:v00008086d000024C5sv00001734sd00001005* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (D1451 (SCENIC N300, i845GV) Sigmatel STAC9750T) + +pci:v00008086d000024C5sv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller (Amilo M1420) + +pci:v00008086d000024C6* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller + +pci:v00008086d000024C6sv00001014sd00000524* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (ThinkPad T4x Series) + +pci:v00008086d000024C6sv00001014sd00000525* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (ThinkPad) + +pci:v00008086d000024C6sv00001014sd00000559* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (ThinkPad R50e) + +pci:v00008086d000024C6sv00001025sd0000003C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (Aspire 2001WLCi (Compal CL50 motherboard) implementation) + +pci:v00008086d000024C6sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (TravelMate 290) + +pci:v00008086d000024C6sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) + +pci:v00008086d000024C6sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (Inspiron 5160) + +pci:v00008086d000024C6sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (NC8000 laptop) + +pci:v00008086d000024C6sv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (NC6000 laptop) + +pci:v00008086d000024C6sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (tc1100 tablet) + +pci:v00008086d000024C6sv00001043sd00001716* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (M2400N laptop) + +pci:v00008086d000024C6sv00001043sd00001826* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (M6800N) + +pci:v00008086d000024C6sv00001071sd00008160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (MIM2000) + +pci:v00008086d000024C6sv0000134Dsd00004C21* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (Latitude D500) + +pci:v00008086d000024C6sv0000144Dsd00002115* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (X10 Laptop) + +pci:v00008086d000024C6sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (P30/P35 notebook) + +pci:v00008086d000024C6sv000014F1sd00005422* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller (D480 MDC V.9x Modem) + +pci:v00008086d000024C7* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 + +pci:v00008086d000024C7sv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (NetVista A30p) + +pci:v00008086d000024C7sv00001014sd0000052D* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (ThinkPad) + +pci:v00008086d000024C7sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (TravelMate 290) + +pci:v00008086d000024C7sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) + +pci:v00008086d000024C7sv00001028sd00000126* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Optiplex GX260) + +pci:v00008086d000024C7sv00001028sd00000160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Dimension 2400) + +pci:v00008086d000024C7sv00001028sd00000163* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Latitude D505) + +pci:v00008086d000024C7sv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Inspiron 700m/710m) + +pci:v00008086d000024C7sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Inspiron 5160) + +pci:v00008086d000024C7sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (NC8000 laptop) + +pci:v00008086d000024C7sv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (NC6000 laptop) + +pci:v00008086d000024C7sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (tc1100 tablet) + +pci:v00008086d000024C7sv00001043sd00008089* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (P4B533) + +pci:v00008086d000024C7sv00001071sd00008160* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (MIM2000) + +pci:v00008086d000024C7sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (P30/P35 notebook) + +pci:v00008086d000024C7sv00001462sd00005800* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (845PE Max (MS-6580)) + +pci:v00008086d000024C7sv00001509sd00002990* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Averatec 5110H) + +pci:v00008086d000024C7sv00001734sd00001004* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (D1451 Mainboard (SCENIC N300, i845GV)) + +pci:v00008086d000024C7sv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Cx9 / Vx9 mainboard) + +pci:v00008086d000024C7sv00008086sd000024C2* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Latitude X300) + +pci:v00008086d000024C7sv00008086sd00004541* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (Latitude D400/D500) + +pci:v00008086d000024C7sv0000E4BFsd00000CC9* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (CC9-SAMBA) + +pci:v00008086d000024C7sv0000E4BFsd00000CD2* + ID_MODEL_FROM_DATABASE=82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 (CD2-BEBOP) + +pci:v00008086d000024CA* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller + +pci:v00008086d000024CAsv00001014sd0000052D* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (ThinkPad) + +pci:v00008086d000024CAsv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (TravelMate 290) + +pci:v00008086d000024CAsv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) + +pci:v00008086d000024CAsv00001028sd0000014F* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Latitude X300) + +pci:v00008086d000024CAsv00001028sd00000163* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Latitude D505) + +pci:v00008086d000024CAsv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Inspiron 700m/710m) + +pci:v00008086d000024CAsv00001028sd00000196* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Inspiron 5160) + +pci:v00008086d000024CAsv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (NC8000 laptop) + +pci:v00008086d000024CAsv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (NC6000 laptop) + +pci:v00008086d000024CAsv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (tc1100 tablet) + +pci:v00008086d000024CAsv00001071sd00008160* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (MIM2000) + +pci:v00008086d000024CAsv0000144Dsd0000C005* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (X10 Laptop) + +pci:v00008086d000024CAsv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (P30/P35 notebook) + +pci:v00008086d000024CAsv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Amilo M1420) + +pci:v00008086d000024CAsv00008086sd00004541* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) IDE Controller (Latitude D400/D500) + +pci:v00008086d000024CB* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller + +pci:v00008086d000024CBsv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (NetVista A30p) + +pci:v00008086d000024CBsv00001028sd00000126* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (Optiplex GX260) + +pci:v00008086d000024CBsv00001028sd00000160* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (Dimension 2400) + +pci:v00008086d000024CBsv00001043sd00008089* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (P4B533) + +pci:v00008086d000024CBsv0000114Asd00000582* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (PC8 onboard IDE) + +pci:v00008086d000024CBsv00001458sd000024C2* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (GA-8PE667 Ultra) + +pci:v00008086d000024CBsv00001462sd00005800* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (845PE Max (MS-6580)) + +pci:v00008086d000024CBsv00001734sd00001004* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (D1451 Mainboard (SCENIC N300, i845GV)) + +pci:v00008086d000024CBsv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (Cx9 / Vx9 mainboard) + +pci:v00008086d000024CBsv0000E4BFsd00000CC9* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (CC9-SAMBA) + +pci:v00008086d000024CBsv0000E4BFsd00000CD2* + ID_MODEL_FROM_DATABASE=82801DB (ICH4) IDE Controller (CD2-BEBOP) + +pci:v00008086d000024CC* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) LPC Interface Bridge + +pci:v00008086d000024CCsv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) LPC Interface Bridge (P30 notebook) + +pci:v00008086d000024CCsv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82801DBM (ICH4-M) LPC Interface Bridge (Amilo M1420) + +pci:v00008086d000024CD* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller + +pci:v00008086d000024CDsv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (NetVista A30p) + +pci:v00008086d000024CDsv00001014sd0000052E* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (ThinkPad) + +pci:v00008086d000024CDsv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (TravelMate 290) + +pci:v00008086d000024CDsv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)) + +pci:v00008086d000024CDsv00001028sd0000011D* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude D600) + +pci:v00008086d000024CDsv00001028sd00000126* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Optiplex GX260) + +pci:v00008086d000024CDsv00001028sd00000139* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude D400) + +pci:v00008086d000024CDsv00001028sd00000152* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude D500) + +pci:v00008086d000024CDsv00001028sd00000160* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Dimension 2400) + +pci:v00008086d000024CDsv00001028sd00000163* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude D505) + +pci:v00008086d000024CDsv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Inspiron 700m/710m) + +pci:v00008086d000024CDsv00001028sd00000196* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Inspiron 5160) + +pci:v00008086d000024CDsv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (NC8000 laptop) + +pci:v00008086d000024CDsv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (NC6000 laptop) + +pci:v00008086d000024CDsv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (tc1100 tablet) + +pci:v00008086d000024CDsv00001043sd00008089* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (P4B533) + +pci:v00008086d000024CDsv00001071sd00008160* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (MIM2000) + +pci:v00008086d000024CDsv0000114Asd00000582* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (PC8 onboard USB 2.0) + +pci:v00008086d000024CDsv00001179sd0000FF00* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Satellite 2430) + +pci:v00008086d000024CDsv0000144Dsd0000C005* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (X10 Laptop) + +pci:v00008086d000024CDsv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (P30/P35 notebook) + +pci:v00008086d000024CDsv00001462sd00003981* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (845PE Max (MS-6580)) + +pci:v00008086d000024CDsv00001509sd00001968* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Averatec 5110H) + +pci:v00008086d000024CDsv00001734sd00001004* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (D1451 Mainboard (SCENIC N300, i845GV)) + +pci:v00008086d000024CDsv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Amilo M1420) + +pci:v00008086d000024CDsv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (QEMU Virtual Machine) + +pci:v00008086d000024CDsv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Cx9 / Vx9 mainboard) + +pci:v00008086d000024CDsv00008086sd000024C2* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (Latitude X300) + +pci:v00008086d000024CDsv0000E4BFsd00000CC9* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (CC9-SAMBA) + +pci:v00008086d000024CDsv0000E4BFsd00000CD2* + ID_MODEL_FROM_DATABASE=82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (CD2-BEBOP) + +pci:v00008086d000024D0* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) LPC Interface Bridge + +pci:v00008086d000024D1* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller + +pci:v00008086d000024D1sv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (Precision Workstation 670 Mainboard) + +pci:v00008086d000024D1sv00001028sd00000169* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (Precision 470) + +pci:v00008086d000024D1sv00001028sd0000019A* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (PowerEdge SC1425) + +pci:v00008086d000024D1sv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (d530 CMT (DG746A)) + +pci:v00008086d000024D1sv0000103Csd00003208* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (ProLiant DL140 G2) + +pci:v00008086d000024D1sv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (P4P800 series motherboard) + +pci:v00008086d000024D1sv00001458sd000024D1* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (GA-8IPE1000 Pro2 motherboard (865PE)) + +pci:v00008086d000024D1sv00001462sd00007280* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (865PE Neo2 (MS-6728)) + +pci:v00008086d000024D1sv00001462sd00007650* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (Hetis 865GV-E (MS-7065)) + +pci:v00008086d000024D1sv00001565sd00005200* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (P4TSV Motherboard (865G)) + +pci:v00008086d000024D1sv000015D9sd00004580* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (P4SCE Mainboard) + +pci:v00008086d000024D1sv00008086sd00003427* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (S875WP1-E mainboard) + +pci:v00008086d000024D1sv00008086sd00004246* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (Desktop Board D865GBF) + +pci:v00008086d000024D1sv00008086sd00004C43* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (Desktop Board D865GLC) + +pci:v00008086d000024D1sv00008086sd0000524C* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) SATA Controller (D865PERL mainboard) + +pci:v00008086d000024D2* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 + +pci:v00008086d000024D2sv00001014sd00000287* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (ThinkCentre S50) + +pci:v00008086d000024D2sv00001014sd000002DD* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (eServer xSeries server mainboard) + +pci:v00008086d000024D2sv00001014sd000002ED* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (eServer xSeries server mainboard) + +pci:v00008086d000024D2sv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (Precision Workstation 670 Mainboard) + +pci:v00008086d000024D2sv00001028sd00000169* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (Precision 470) + +pci:v00008086d000024D2sv00001028sd0000016C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PowerEdge 1850 onboard UHCI) + +pci:v00008086d000024D2sv00001028sd0000016D* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PowerEdge 2850 onboard UHCI) + +pci:v00008086d000024D2sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PowerEdge 6850 onboard UHCI) + +pci:v00008086d000024D2sv00001028sd00000183* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PowerEdge 1800) + +pci:v00008086d000024D2sv00001028sd0000019A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PowerEdge SC1425) + +pci:v00008086d000024D2sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (NX9500) + +pci:v00008086d000024D2sv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (d530 CMT (DG746A)) + +pci:v00008086d000024D2sv0000103Csd00003208* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (ProLiant DL140 G2) + +pci:v00008086d000024D2sv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (P4P800/P5P800 series motherboard) + +pci:v00008086d000024D2sv00001458sd000024D2* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (GA-8IPE1000/8KNXP motherboard) + +pci:v00008086d000024D2sv00001462sd00007280* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (865PE Neo2 (MS-6728)) + +pci:v00008086d000024D2sv00001565sd00003101* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (P4TSV Motherboard (865G)) + +pci:v00008086d000024D2sv000015D9sd00004580* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (P4SCE Mainboard) + +pci:v00008086d000024D2sv00001734sd0000101C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (PRIMERGY RX/TX series onboard UHCI) + +pci:v00008086d000024D2sv00008086sd00003427* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (S875WP1-E mainboard) + +pci:v00008086d000024D2sv00008086sd00004246* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (Desktop Board D865GBF) + +pci:v00008086d000024D2sv00008086sd00004C43* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (Desktop Board D865GLC) + +pci:v00008086d000024D2sv00008086sd0000524C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 (D865PERL mainboard) + +pci:v00008086d000024D3* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller + +pci:v00008086d000024D3sv00001014sd00000287* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (ThinkCentre S50) + +pci:v00008086d000024D3sv00001014sd000002DD* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (eServer xSeries server mainboard) + +pci:v00008086d000024D3sv00001014sd000002ED* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (eServer xSeries server mainboard) + +pci:v00008086d000024D3sv00001028sd00000156* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Precision 360) + +pci:v00008086d000024D3sv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Precision Workstation 670 Mainboard) + +pci:v00008086d000024D3sv00001028sd00000169* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Precision 470) + +pci:v00008086d000024D3sv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (d330 uT) + +pci:v00008086d000024D3sv0000103Csd00003208* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (ProLiant DL140 G2) + +pci:v00008086d000024D3sv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (P4P800/P5P800 series motherboard) + +pci:v00008086d000024D3sv00001458sd000024D2* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (GA-8IPE1000 Pro2 motherboard (865PE)) + +pci:v00008086d000024D3sv00001462sd00007280* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (865PE Neo2 (MS-6728)) + +pci:v00008086d000024D3sv00001462sd00007650* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Hetis 865GV-E (MS-7065)) + +pci:v00008086d000024D3sv00001565sd00003101* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (P4TSV Motherboard (865G)) + +pci:v00008086d000024D3sv000015D9sd00004580* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (P4SCE Mainboard) + +pci:v00008086d000024D3sv00001734sd0000101C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (PRIMERGY RX/TX S2 series SMBus) + +pci:v00008086d000024D3sv00008086sd00003427* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (S875WP1-E mainboard) + +pci:v00008086d000024D3sv00008086sd00004246* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Desktop Board D865GBF) + +pci:v00008086d000024D3sv00008086sd00004C43* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (Desktop Board D865GLC) + +pci:v00008086d000024D3sv00008086sd0000524C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) SMBus Controller (D865PERL mainboard) + +pci:v00008086d000024D4* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 + +pci:v00008086d000024D4sv00001014sd00000287* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (ThinkCentre S50) + +pci:v00008086d000024D4sv00001014sd000002DD* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (eServer xSeries server mainboard) + +pci:v00008086d000024D4sv00001014sd000002ED* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (eServer xSeries server mainboard) + +pci:v00008086d000024D4sv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (Precision Workstation 670 Mainboard) + +pci:v00008086d000024D4sv00001028sd00000169* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (Precision 470) + +pci:v00008086d000024D4sv00001028sd0000016C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PowerEdge 1850 onboard UHCI) + +pci:v00008086d000024D4sv00001028sd0000016D* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PowerEdge 2850 onboard UHCI) + +pci:v00008086d000024D4sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PowerEdge 6850 onboard UHCI) + +pci:v00008086d000024D4sv00001028sd00000183* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PowerEdge 1800) + +pci:v00008086d000024D4sv00001028sd0000019A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PowerEdge SC1425) + +pci:v00008086d000024D4sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (NX9500) + +pci:v00008086d000024D4sv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (d530 CMT (DG746A)) + +pci:v00008086d000024D4sv0000103Csd00003208* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (ProLiant DL140 G2) + +pci:v00008086d000024D4sv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (P4P800/P5P800 series motherboard) + +pci:v00008086d000024D4sv00001458sd000024D2* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (GA-8IPE1000 Pro2 motherboard (865PE)) + +pci:v00008086d000024D4sv00001462sd00007280* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (865PE Neo2 (MS-6728)) + +pci:v00008086d000024D4sv00001462sd00007650* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (Hetis 865GV-E (MS-7065)) + +pci:v00008086d000024D4sv00001565sd00003101* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (P4TSV Motherboard (865G)) + +pci:v00008086d000024D4sv000015D9sd00004580* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (P4SCE Mainboard) + +pci:v00008086d000024D4sv00001734sd0000101C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (PRIMERGY RX/TX S2 series onboard UHCI) + +pci:v00008086d000024D4sv00008086sd00003427* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (S875WP1-E mainboard) + +pci:v00008086d000024D4sv00008086sd00004246* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (Desktop Board D865GBF) + +pci:v00008086d000024D4sv00008086sd00004C43* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (Desktop Board D865GLC) + +pci:v00008086d000024D4sv00008086sd0000524C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 (D865PERL mainboard) + +pci:v00008086d000024D5* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller + +pci:v00008086d000024D5sv0000100Asd0000147B* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (Abit IS7-E motherboard) + +pci:v00008086d000024D5sv00001014sd00000287* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (ThinkCentre S50) + +pci:v00008086d000024D5sv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (Precision Workstation 670 Mainboard) + +pci:v00008086d000024D5sv00001028sd00000169* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (Precision 470) + +pci:v00008086d000024D5sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (NX9500) + +pci:v00008086d000024D5sv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (d330 uT) + +pci:v00008086d000024D5sv00001043sd000080F3* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (P4P800 series motherboard) + +pci:v00008086d000024D5sv00001043sd0000810F* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (P5P800-MX Mainboard) + +pci:v00008086d000024D5sv00001458sd0000A002* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (GA-8IPE1000/8KNXP motherboard) + +pci:v00008086d000024D5sv00001462sd00000080* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (865PE Neo2-V (MS-6788) Mainboard) + +pci:v00008086d000024D5sv00001462sd00007280* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (865PE Neo2 (MS-6728)) + +pci:v00008086d000024D5sv00001462sd00007650* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (Hetis 865GV-E (MS-7065)) + +pci:v00008086d000024D5sv00008086sd0000A000* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (D865PERL mainboard) + +pci:v00008086d000024D5sv00008086sd0000E000* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (D865PERL mainboard) + +pci:v00008086d000024D5sv00008086sd0000E001* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (Desktop Board D865GBF) + +pci:v00008086d000024D5sv00008086sd0000E002* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller (SoundMax Integrated Digital Audio) + +pci:v00008086d000024D6* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller + +pci:v00008086d000024D6sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller (NX9500) + +pci:v00008086d000024D7* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 + +pci:v00008086d000024D7sv00001014sd00000287* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (ThinkCentre S50) + +pci:v00008086d000024D7sv00001014sd000002ED* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (xSeries server mainboard) + +pci:v00008086d000024D7sv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (Precision Workstation 670 Mainboard) + +pci:v00008086d000024D7sv00001028sd00000169* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (Precision 470) + +pci:v00008086d000024D7sv00001028sd0000016C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (PowerEdge 1850 onboard UHCI) + +pci:v00008086d000024D7sv00001028sd0000016D* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (PowerEdge 2850 onboard UHCI) + +pci:v00008086d000024D7sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (PowerEdge 6850 onboard UHCI) + +pci:v00008086d000024D7sv00001028sd00000183* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (PowerEdge 1800) + +pci:v00008086d000024D7sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (NX9500) + +pci:v00008086d000024D7sv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (d530 CMT (DG746A)) + +pci:v00008086d000024D7sv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (P4P800/P5P800 series motherboard) + +pci:v00008086d000024D7sv00001458sd000024D2* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (GA-8IPE1000 Pro2 motherboard (865PE)) + +pci:v00008086d000024D7sv00001462sd00007280* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (865PE Neo2 (MS-6728)) + +pci:v00008086d000024D7sv00001462sd00007650* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (Hetis 865GV-E (MS-7065)) + +pci:v00008086d000024D7sv00001565sd00003101* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (P4TSV Motherboard (865G)) + +pci:v00008086d000024D7sv000015D9sd00004580* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (P4SCE Mainboard) + +pci:v00008086d000024D7sv00001734sd0000101C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (PRIMERGY RX/TX S2 series onboard UHCI) + +pci:v00008086d000024D7sv00008086sd00003427* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (S875WP1-E mainboard) + +pci:v00008086d000024D7sv00008086sd00004246* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (Desktop Board D865GBF) + +pci:v00008086d000024D7sv00008086sd00004C43* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (Desktop Board D865GLC) + +pci:v00008086d000024D7sv00008086sd0000524C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 (D865PERL mainboard) + +pci:v00008086d000024DB* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller + +pci:v00008086d000024DBsv00001014sd00000287* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (ThinkCentre S50) + +pci:v00008086d000024DBsv00001014sd000002DD* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (eServer xSeries server mainboard) + +pci:v00008086d000024DBsv00001014sd000002ED* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (eServer xSeries server mainboard) + +pci:v00008086d000024DBsv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (Precision Workstation 670 Mainboard) + +pci:v00008086d000024DBsv00001028sd00000169* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (Precision 470) + +pci:v00008086d000024DBsv00001028sd0000016C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (PowerEdge 1850 IDE Controller) + +pci:v00008086d000024DBsv00001028sd0000016D* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (PowerEdge 2850 IDE Controller) + +pci:v00008086d000024DBsv00001028sd00000170* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (PowerEdge 6850 IDE Controller) + +pci:v00008086d000024DBsv00001028sd0000019A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (PowerEdge SC1425) + +pci:v00008086d000024DBsv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (NX9500) + +pci:v00008086d000024DBsv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (d530 CMT (DG746A)) + +pci:v00008086d000024DBsv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (P4P800/P5P800 series motherboard) + +pci:v00008086d000024DBsv00001458sd000024D2* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (GA-8IPE1000 Pro2 motherboard (865PE)) + +pci:v00008086d000024DBsv00001462sd00007280* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (865PE Neo2 (MS-6728)) + +pci:v00008086d000024DBsv00001462sd00007580* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (MSI 875P) + +pci:v00008086d000024DBsv00001462sd00007650* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (Hetis 865GV-E (MS-7065)) + +pci:v00008086d000024DBsv00001565sd00003101* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (P4TSV Motherboard (865G)) + +pci:v00008086d000024DBsv000015D9sd00004580* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (P4SCE Mainboard) + +pci:v00008086d000024DBsv00001734sd0000101C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (PRIMERGY RX/TX S2 series onboard IDE) + +pci:v00008086d000024DBsv00008086sd000024DB* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (P4C800 Mainboard) + +pci:v00008086d000024DBsv00008086sd00003427* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (S875WP1-E mainboard) + +pci:v00008086d000024DBsv00008086sd00004246* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (Desktop Board D865GBF) + +pci:v00008086d000024DBsv00008086sd00004C43* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (Desktop Board D865GLC) + +pci:v00008086d000024DBsv00008086sd0000524C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) IDE Controller (D865PERL mainboard) + +pci:v00008086d000024DC* + ID_MODEL_FROM_DATABASE=82801EB (ICH5) LPC Interface Bridge + +pci:v00008086d000024DD* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller + +pci:v00008086d000024DDsv00001014sd00000287* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (ThinkCentre S50) + +pci:v00008086d000024DDsv00001014sd000002DD* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (eServer xSeries server mainboard) + +pci:v00008086d000024DDsv00001014sd000002ED* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (eServer xSeries server mainboard) + +pci:v00008086d000024DDsv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (Precision Workstation 670 Mainboard) + +pci:v00008086d000024DDsv00001028sd00000169* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (Precision 470) + +pci:v00008086d000024DDsv00001028sd0000016C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (PowerEdge 1850 onboard EHCI) + +pci:v00008086d000024DDsv00001028sd0000016D* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (PowerEdge 2850 onboard EHCI) + +pci:v00008086d000024DDsv00001028sd00000170* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (PowerEdge 6850 onboard EHCI) + +pci:v00008086d000024DDsv00001028sd00000183* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (PowerEdge 1800) + +pci:v00008086d000024DDsv00001028sd0000019A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (PowerEdge SC1425) + +pci:v00008086d000024DDsv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (NX9500) + +pci:v00008086d000024DDsv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (d530 CMT (DG746A)) + +pci:v00008086d000024DDsv0000103Csd00003208* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (ProLiant DL140 G2) + +pci:v00008086d000024DDsv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (P4P800/P5P800 series motherboard) + +pci:v00008086d000024DDsv00001458sd00005006* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (GA-8IPE1000 Pro2 motherboard (865PE)) + +pci:v00008086d000024DDsv00001462sd00007280* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (865PE Neo2 (MS-6728)) + +pci:v00008086d000024DDsv00001462sd00007650* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (Hetis 865GV-E (MS-7065)) + +pci:v00008086d000024DDsv00008086sd00003427* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (S875WP1-E mainboard) + +pci:v00008086d000024DDsv00008086sd00004246* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (Desktop Board D865GBF) + +pci:v00008086d000024DDsv00008086sd00004C43* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (Desktop Board D865GLC) + +pci:v00008086d000024DDsv00008086sd0000524C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller (D865PERL mainboard) + +pci:v00008086d000024DE* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 + +pci:v00008086d000024DEsv00001014sd00000287* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (ThinkCentre S50) + +pci:v00008086d000024DEsv00001014sd000002ED* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (xSeries server mainboard) + +pci:v00008086d000024DEsv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (Precision Workstation 670 Mainboard) + +pci:v00008086d000024DEsv00001028sd00000169* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (Precision 470) + +pci:v00008086d000024DEsv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (P4P800/P5P800 series motherboard) + +pci:v00008086d000024DEsv00001458sd000024D2* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (GA-8IPE1000 Pro2 motherboard (865PE)) + +pci:v00008086d000024DEsv00001462sd00007280* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (865PE Neo2 (MS-6728)) + +pci:v00008086d000024DEsv00001462sd00007650* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (Hetis 865GV-E (MS-7065)) + +pci:v00008086d000024DEsv00001565sd00003101* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (P4TSV Motherboard (865G)) + +pci:v00008086d000024DEsv000015D9sd00004580* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (P4SCE Mainboard) + +pci:v00008086d000024DEsv00001734sd0000101C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (PRIMERGY RX/TX S2 series onboard UHCI) + +pci:v00008086d000024DEsv00008086sd00003427* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (S875WP1-E mainboard) + +pci:v00008086d000024DEsv00008086sd00004246* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (Desktop Board D865GBF) + +pci:v00008086d000024DEsv00008086sd00004C43* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (Desktop Board D865GLC) + +pci:v00008086d000024DEsv00008086sd0000524C* + ID_MODEL_FROM_DATABASE=82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 (D865PERL mainboard) + +pci:v00008086d000024DF* + ID_MODEL_FROM_DATABASE=82801ER (ICH5R) SATA Controller + +pci:v00008086d000024DFsv00001028sd00000168* + ID_MODEL_FROM_DATABASE=82801ER (ICH5R) SATA Controller (Precision Workstation 670 Mainboard) + +pci:v00008086d000024F0* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] + +pci:v00008086d000024F0sv000010A9sd0000802E* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-path HFI 100 Series, 1-port A-board) + +pci:v00008086d000024F0sv000010A9sd0000802F* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-path HFI 100 Series, 2-port A-board) + +pci:v00008086d000024F0sv000010A9sd00008030* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-path HFI 100 Series, 1-port B-board) + +pci:v00008086d000024F0sv000010A9sd00008031* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-path HFI 100 Series, 2-port B-board) + +pci:v00008086d000024F0sv00001590sd000000E7* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (100Gb 1-port OP101 QSFP28 x8 PCIe Gen3 with Intel Omni-Path Adapter) + +pci:v00008086d000024F0sv00001590sd000000E8* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (100Gb 1-port OP101 QSFP28 x16 PCIe Gen3 with Intel Omni-Path Adapter) + +pci:v00008086d000024F0sv00001590sd0000021C* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Apollo 100Gb 1-port Intel Omni-Path Architecture 860z Mezzanine FIO Adapter) + +pci:v00008086d000024F0sv000015D9sd00000934* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, SIOM Module) + +pci:v00008086d000024F0sv000015D9sd0000099B* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-path HFI Mezz AOC, 1 Port, PCIe x16.) + +pci:v00008086d000024F0sv00001CB8sd00000001* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, TC4600 QSFP28) + +pci:v00008086d000024F0sv00001CB8sd00000002* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, TC6600 Fixed Port) + +pci:v00008086d000024F0sv00001CB8sd00000003* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 2 Port, 2 PCIe x16, Earth Simulation QSFP28) + +pci:v00008086d000024F0sv00001CB8sd00000004* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, TC4600E QSFP28) + +pci:v00008086d000024F0sv00008086sd00002628* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16) + +pci:v00008086d000024F0sv00008086sd00002629* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x8) + +pci:v00008086d000024F0sv00008086sd0000262A* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 2 Ports, Split PCIe x16) + +pci:v00008086d000024F0sv00008086sd0000262D* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [discrete] (Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, IO Module AHWKPTP100HF) + +pci:v00008086d000024F1* + ID_MODEL_FROM_DATABASE=Omni-Path HFI Silicon 100 Series [integrated] + +pci:v00008086d000024F3* + ID_MODEL_FROM_DATABASE=Wireless 8260 + +pci:v00008086d000024F3sv00008086sd00000010* + ID_MODEL_FROM_DATABASE=Wireless 8260 (Dual Band Wireless-AC 8260) + +pci:v00008086d000024F3sv00008086sd00001010* + ID_MODEL_FROM_DATABASE=Wireless 8260 (Dual Band Wireless-AC 8260) + +pci:v00008086d000024F4* + ID_MODEL_FROM_DATABASE=Wireless 8260 + +pci:v00008086d000024F4sv00008086sd00000030* + ID_MODEL_FROM_DATABASE=Wireless 8260 (Dual Band Wireless-AC 8260) + +pci:v00008086d000024FB* + ID_MODEL_FROM_DATABASE=Dual Band Wireless-AC 3168NGW [Stone Peak] + +pci:v00008086d000024FD* + ID_MODEL_FROM_DATABASE=Wireless 8265 / 8275 + +pci:v00008086d000024FDsv00008086sd00000010* + ID_MODEL_FROM_DATABASE=Wireless 8265 / 8275 (Dual Band Wireless-AC 8265) + +pci:v00008086d000024FDsv00008086sd00000150* + ID_MODEL_FROM_DATABASE=Wireless 8265 / 8275 (Dual Band Wireless-AC 8265) + +pci:v00008086d000024FDsv00008086sd00001010* + ID_MODEL_FROM_DATABASE=Wireless 8265 / 8275 (Dual Band Wireless-AC 8265) + +pci:v00008086d000024FDsv00008086sd00001130* + ID_MODEL_FROM_DATABASE=Wireless 8265 / 8275 (Dual Band Wireless-AC 8265) + +pci:v00008086d00002500* + ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH) + +pci:v00008086d00002500sv00001028sd00000095* + ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH) (Precision Workstation 220 Chipset) + +pci:v00008086d00002500sv00001043sd0000801C* + ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH) (P3C-2000 system chipset) + +pci:v00008086d00002501* + ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH) + +pci:v00008086d00002501sv00001043sd0000801C* + ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge (MCH) (P3C-2000 system chipset) + +pci:v00008086d0000250B* + ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset Host Bridge + +pci:v00008086d0000250F* + ID_MODEL_FROM_DATABASE=82820 820 (Camino) Chipset AGP Bridge + +pci:v00008086d00002520* + ID_MODEL_FROM_DATABASE=82805AA MTH Memory Translator Hub + +pci:v00008086d00002521* + ID_MODEL_FROM_DATABASE=82804AA MRH-S Memory Repeater Hub for SDRAM + +pci:v00008086d00002526* + ID_MODEL_FROM_DATABASE=Wireless-AC 9260 + +pci:v00008086d00002530* + ID_MODEL_FROM_DATABASE=82850 850 (Tehama) Chipset Host Bridge (MCH) + +pci:v00008086d00002530sv00001028sd000000C7* + ID_MODEL_FROM_DATABASE=82850 850 (Tehama) Chipset Host Bridge (MCH) (Dimension 8100) + +pci:v00008086d00002530sv0000147Bsd00000507* + ID_MODEL_FROM_DATABASE=82850 850 (Tehama) Chipset Host Bridge (MCH) (TH7II-RAID) + +pci:v00008086d00002531* + ID_MODEL_FROM_DATABASE=82860 860 (Wombat) Chipset Host Bridge (MCH) + +pci:v00008086d00002531sv00001028sd000000D8* + ID_MODEL_FROM_DATABASE=82860 860 (Wombat) Chipset Host Bridge (MCH) (Precision 530) + +pci:v00008086d00002532* + ID_MODEL_FROM_DATABASE=82850 850 (Tehama) Chipset AGP Bridge + +pci:v00008086d00002533* + ID_MODEL_FROM_DATABASE=82860 860 (Wombat) Chipset AGP Bridge + +pci:v00008086d00002534* + ID_MODEL_FROM_DATABASE=82860 860 (Wombat) Chipset PCI Bridge + +pci:v00008086d00002540* + ID_MODEL_FROM_DATABASE=E7500 Memory Controller Hub + +pci:v00008086d00002540sv000015D9sd00003480* + ID_MODEL_FROM_DATABASE=E7500 Memory Controller Hub (P4DP6) + +pci:v00008086d00002541* + ID_MODEL_FROM_DATABASE=E7500/E7501 Host RASUM Controller + +pci:v00008086d00002541sv000015D9sd00003480* + ID_MODEL_FROM_DATABASE=E7500/E7501 Host RASUM Controller (P4DP6) + +pci:v00008086d00002541sv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=E7500/E7501 Host RASUM Controller (Cx9 / Vx9 mainboard) + +pci:v00008086d00002541sv00008086sd00003424* + ID_MODEL_FROM_DATABASE=E7500/E7501 Host RASUM Controller (SE7501HG2 Mainboard) + +pci:v00008086d00002543* + ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface B PCI-to-PCI Bridge + +pci:v00008086d00002544* + ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface B RASUM Controller + +pci:v00008086d00002544sv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface B RASUM Controller (Cx9 / Vx9 mainboard) + +pci:v00008086d00002545* + ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface C PCI-to-PCI Bridge + +pci:v00008086d00002546* + ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface C RASUM Controller + +pci:v00008086d00002547* + ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface D PCI-to-PCI Bridge + +pci:v00008086d00002548* + ID_MODEL_FROM_DATABASE=E7500/E7501 Hub Interface D RASUM Controller + +pci:v00008086d0000254C* + ID_MODEL_FROM_DATABASE=E7501 Memory Controller Hub + +pci:v00008086d0000254Csv00004C53sd00001090* + ID_MODEL_FROM_DATABASE=E7501 Memory Controller Hub (Cx9 / Vx9 mainboard) + +pci:v00008086d0000254Csv00008086sd00003424* + ID_MODEL_FROM_DATABASE=E7501 Memory Controller Hub (SE7501HG2 Mainboard) + +pci:v00008086d00002550* + ID_MODEL_FROM_DATABASE=E7505 Memory Controller Hub + +pci:v00008086d00002551* + ID_MODEL_FROM_DATABASE=E7505/E7205 Series RAS Controller + +pci:v00008086d00002552* + ID_MODEL_FROM_DATABASE=E7505/E7205 PCI-to-AGP Bridge + +pci:v00008086d00002553* + ID_MODEL_FROM_DATABASE=E7505 Hub Interface B PCI-to-PCI Bridge + +pci:v00008086d00002554* + ID_MODEL_FROM_DATABASE=E7505 Hub Interface B PCI-to-PCI Bridge RAS Controller + +pci:v00008086d0000255D* + ID_MODEL_FROM_DATABASE=E7205 Memory Controller Hub + +pci:v00008086d00002560* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface + +pci:v00008086d00002560sv00001028sd00000126* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface (Optiplex GX260) + +pci:v00008086d00002560sv00001458sd00002560* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface (GA-8PE667 Ultra) + +pci:v00008086d00002560sv00001462sd00005800* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface (845PE Max (MS-6580)) + +pci:v00008086d00002561* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE/PE Host-to-AGP Bridge + +pci:v00008086d00002562* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device + +pci:v00008086d00002562sv00000E11sd000000B9* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (Evo D510 SFF) + +pci:v00008086d00002562sv00001014sd00000267* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (NetVista A30p) + +pci:v00008086d00002562sv00001028sd00000160* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (Dimension 2400) + +pci:v00008086d00002562sv00001734sd00001003* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (D1521 Mainboard (Fujitsu-Siemens)) + +pci:v00008086d00002562sv00001734sd00001004* + ID_MODEL_FROM_DATABASE=82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device (D1451 Mainboard (SCENIC N300, i845GV)) + +pci:v00008086d00002570* + ID_MODEL_FROM_DATABASE=82865G/PE/P DRAM Controller/Host-Hub Interface + +pci:v00008086d00002570sv0000103Csd0000006A* + ID_MODEL_FROM_DATABASE=82865G/PE/P DRAM Controller/Host-Hub Interface (NX9500) + +pci:v00008086d00002570sv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=82865G/PE/P DRAM Controller/Host-Hub Interface (d330 uT) + +pci:v00008086d00002570sv00001043sd000080F2* + ID_MODEL_FROM_DATABASE=82865G/PE/P DRAM Controller/Host-Hub Interface (P4P800/P5P800 series motherboard) + +pci:v00008086d00002570sv00001458sd00002570* + ID_MODEL_FROM_DATABASE=82865G/PE/P DRAM Controller/Host-Hub Interface (GA-8IPE1000 Pro2 motherboard (865PE)) + +pci:v00008086d00002571* + ID_MODEL_FROM_DATABASE=82865G/PE/P AGP Bridge + +pci:v00008086d00002572* + ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller + +pci:v00008086d00002572sv00001014sd00000287* + ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (ThinkCentre S50) + +pci:v00008086d00002572sv00001028sd0000019D* + ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (Dimension 3000) + +pci:v00008086d00002572sv0000103Csd000012BC* + ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (D530 sff(dc578av)) + +pci:v00008086d00002572sv00001043sd000080A5* + ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (P5P800-MX Mainboard) + +pci:v00008086d00002572sv00001462sd00007650* + ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (Hetis 865GV-E (MS-7065)) + +pci:v00008086d00002572sv00001734sd0000101B* + ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (Fujitsu-Siemens Scenic E300 i865GV) + +pci:v00008086d00002572sv00008086sd00004246* + ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (Desktop Board D865GBF) + +pci:v00008086d00002572sv00008086sd00004C43* + ID_MODEL_FROM_DATABASE=82865G Integrated Graphics Controller (Desktop Board D865GLC) + +pci:v00008086d00002573* + ID_MODEL_FROM_DATABASE=82865G/PE/P PCI to CSA Bridge + +pci:v00008086d00002576* + ID_MODEL_FROM_DATABASE=82865G/PE/P Processor to I/O Memory Interface + +pci:v00008086d00002578* + ID_MODEL_FROM_DATABASE=82875P/E7210 Memory Controller Hub + +pci:v00008086d00002578sv00001458sd00002578* + ID_MODEL_FROM_DATABASE=82875P/E7210 Memory Controller Hub (GA-8KNXP motherboard (875P)) + +pci:v00008086d00002578sv00001462sd00007580* + ID_MODEL_FROM_DATABASE=82875P/E7210 Memory Controller Hub (MS-6758 (875P Neo)) + +pci:v00008086d00002578sv000015D9sd00004580* + ID_MODEL_FROM_DATABASE=82875P/E7210 Memory Controller Hub (P4SCE Motherboard) + +pci:v00008086d00002579* + ID_MODEL_FROM_DATABASE=82875P Processor to AGP Controller + +pci:v00008086d0000257B* + ID_MODEL_FROM_DATABASE=82875P/E7210 Processor to PCI to CSA Bridge + +pci:v00008086d0000257E* + ID_MODEL_FROM_DATABASE=82875P/E7210 Processor to I/O Memory Interface + +pci:v00008086d00002580* + ID_MODEL_FROM_DATABASE=82915G/P/GV/GL/PL/910GL Memory Controller Hub + +pci:v00008086d00002580sv00001458sd00002580* + ID_MODEL_FROM_DATABASE=82915G/P/GV/GL/PL/910GL Memory Controller Hub (GA-8I915ME-G Mainboard) + +pci:v00008086d00002580sv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82915G/P/GV/GL/PL/910GL Memory Controller Hub (915P/G Neo2) + +pci:v00008086d00002580sv00001734sd0000105B* + ID_MODEL_FROM_DATABASE=82915G/P/GV/GL/PL/910GL Memory Controller Hub (Scenic W620) + +pci:v00008086d00002581* + ID_MODEL_FROM_DATABASE=82915G/P/GV/GL/PL/910GL PCI Express Root Port + +pci:v00008086d00002582* + ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller + +pci:v00008086d00002582sv00001028sd00001079* + ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (Optiplex GX280) + +pci:v00008086d00002582sv0000103Csd00003006* + ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (DC7100 SFF(DX878AV)) + +pci:v00008086d00002582sv00001043sd00002582* + ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (P5GD1-VW Mainboard) + +pci:v00008086d00002582sv00001458sd00002582* + ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (GA-8I915ME-G Mainboard) + +pci:v00008086d00002582sv00001734sd0000105B* + ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (Scenic W620) + +pci:v00008086d00002582sv00001849sd00002582* + ID_MODEL_FROM_DATABASE=82915G/GV/910GL Integrated Graphics Controller (ASRock P4Dual-915GL) + +pci:v00008086d00002584* + ID_MODEL_FROM_DATABASE=82925X/XE Memory Controller Hub + +pci:v00008086d00002584sv00001028sd00000177* + ID_MODEL_FROM_DATABASE=82925X/XE Memory Controller Hub (Dimension 8400) + +pci:v00008086d00002585* + ID_MODEL_FROM_DATABASE=82925X/XE PCI Express Root Port + +pci:v00008086d00002588* + ID_MODEL_FROM_DATABASE=E7220/E7221 Memory Controller Hub + +pci:v00008086d00002589* + ID_MODEL_FROM_DATABASE=E7220/E7221 PCI Express Root Port + +pci:v00008086d0000258A* + ID_MODEL_FROM_DATABASE=E7221 Integrated Graphics Controller + +pci:v00008086d00002590* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller + +pci:v00008086d00002590sv00001014sd00000575* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (ThinkPad X41 / Z60t) + +pci:v00008086d00002590sv00001028sd00000182* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Latitude C610) + +pci:v00008086d00002590sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Compaq nw8240/nx8220) + +pci:v00008086d00002590sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Compaq nc6220 Notebook PC) + +pci:v00008086d00002590sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (NX6110/NC6120) + +pci:v00008086d00002590sv0000104Dsd000081B7* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Vaio VGN-S3XP) + +pci:v00008086d00002590sv0000A304sd000081B7* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (Vaio VGN-S3XP) + +pci:v00008086d00002590sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (CCD-CALYPSO) + +pci:v00008086d00002590sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (CD3-JIVE) + +pci:v00008086d00002590sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller (XB1) + +pci:v00008086d00002591* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM Express PCI Express Root Port + +pci:v00008086d00002591sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=Mobile 915GM/PM Express PCI Express Root Port (Compaq nw8240 Mobile Workstation) + +pci:v00008086d00002592* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller + +pci:v00008086d00002592sv00001014sd00000582* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (ThinkPad X41) + +pci:v00008086d00002592sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (NX6110/NC6120) + +pci:v00008086d00002592sv0000103Csd0000308A* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (NC6220) + +pci:v00008086d00002592sv00001043sd00001881* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (GMA 900 915GM Integrated Graphics) + +pci:v00008086d00002592sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (CCD-CALYPSO) + +pci:v00008086d00002592sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (CD3-JIVE) + +pci:v00008086d00002592sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (XB1) + +pci:v00008086d000025A1* + ID_MODEL_FROM_DATABASE=6300ESB LPC Interface Controller + +pci:v00008086d000025A2* + ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller + +pci:v00008086d000025A2sv00001734sd00001073* + ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (Primergy Econel 200 D2020 mainboard) + +pci:v00008086d000025A2sv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (V5D Single Board Computer IDE) + +pci:v00008086d000025A2sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (CR11/VR11 Single Board Computer) + +pci:v00008086d000025A2sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (CE9) + +pci:v00008086d000025A2sv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (CL9 mainboard) + +pci:v00008086d000025A2sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=6300ESB PATA Storage Controller (PSL09 PrPMC) + +pci:v00008086d000025A3* + ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller + +pci:v00008086d000025A3sv00001734sd00001073* + ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (Primergy Econel 200 D2020 mainboard) + +pci:v00008086d000025A3sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (CR11/VR11 Single Board Computer) + +pci:v00008086d000025A3sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (CE9) + +pci:v00008086d000025A3sv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (CL9 mainboard) + +pci:v00008086d000025A3sv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (Telum ASLP10 Processor AMC) + +pci:v00008086d000025A3sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=6300ESB SATA Storage Controller (PSL09 PrPMC) + +pci:v00008086d000025A4* + ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller + +pci:v00008086d000025A4sv00001734sd00001073* + ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (Primergy Econel 200 D2020 mainboard) + +pci:v00008086d000025A4sv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (V5D Single Board Computer) + +pci:v00008086d000025A4sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (CR11/VR11 Single Board Computer) + +pci:v00008086d000025A4sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (CE9) + +pci:v00008086d000025A4sv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (CL9 mainboard) + +pci:v00008086d000025A4sv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (Telum ASLP10 Processor AMC) + +pci:v00008086d000025A4sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=6300ESB SMBus Controller (PSL09 PrPMC) + +pci:v00008086d000025A6* + ID_MODEL_FROM_DATABASE=6300ESB AC'97 Audio Controller + +pci:v00008086d000025A6sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB AC'97 Audio Controller (CR11/VR11 Single Board Computer) + +pci:v00008086d000025A6sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=6300ESB AC'97 Audio Controller (CE9) + +pci:v00008086d000025A6sv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=6300ESB AC'97 Audio Controller (CL9 mainboard) + +pci:v00008086d000025A7* + ID_MODEL_FROM_DATABASE=6300ESB AC'97 Modem Controller + +pci:v00008086d000025A9* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller + +pci:v00008086d000025A9sv00001734sd00001073* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (Primergy Econel 200 D2020 mainboard) + +pci:v00008086d000025A9sv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (V5D Single Board Computer USB) + +pci:v00008086d000025A9sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CR11/VR11 Single Board Computer) + +pci:v00008086d000025A9sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CE9) + +pci:v00008086d000025A9sv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CL9 mainboard) + +pci:v00008086d000025A9sv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (Telum ASLP10 Processor AMC) + +pci:v00008086d000025A9sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (PSL09 PrPMC) + +pci:v00008086d000025AA* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller + +pci:v00008086d000025AAsv00001734sd00001073* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (Primergy Econel 200 D2020 mainboard) + +pci:v00008086d000025AAsv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CR11/VR11 Single Board Computer) + +pci:v00008086d000025AAsv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CE9) + +pci:v00008086d000025AAsv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (CL9 mainboard) + +pci:v00008086d000025AAsv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (Telum ASLP10 Processor AMC) + +pci:v00008086d000025AAsv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=6300ESB USB Universal Host Controller (PSL09 PrPMC) + +pci:v00008086d000025AB* + ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer + +pci:v00008086d000025ABsv00001734sd00001073* + ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (Primergy Econel 200 D2020 mainboard) + +pci:v00008086d000025ABsv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (V5D Single Board Computer) + +pci:v00008086d000025ABsv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (CR11/VR11 Single Board Computer) + +pci:v00008086d000025ABsv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (CE9) + +pci:v00008086d000025ABsv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (QEMU Virtual Machine) + +pci:v00008086d000025ABsv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (CL9 mainboard) + +pci:v00008086d000025ABsv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (Telum ASLP10 Processor AMC) + +pci:v00008086d000025ABsv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=6300ESB Watchdog Timer (PSL09 PrPMC) + +pci:v00008086d000025AC* + ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller + +pci:v00008086d000025ACsv00001734sd00001073* + ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (Primergy Econel 200 D2020 mainboard) + +pci:v00008086d000025ACsv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (V5D Single Board Computer) + +pci:v00008086d000025ACsv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (CR11/VR11 Single Board Computer) + +pci:v00008086d000025ACsv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (CE9) + +pci:v00008086d000025ACsv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (CL9 mainboard) + +pci:v00008086d000025ACsv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (Telum ASLP10 Processor AMC) + +pci:v00008086d000025ACsv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=6300ESB I/O Advanced Programmable Interrupt Controller (PSL09 PrPMC) + +pci:v00008086d000025AD* + ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller + +pci:v00008086d000025ADsv00001734sd00001073* + ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (Primergy Econel 200 D2020 mainboard) + +pci:v00008086d000025ADsv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (V5D Single Board Computer USB 2.0) + +pci:v00008086d000025ADsv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (CR11/VR11 Single Board Computer) + +pci:v00008086d000025ADsv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (CE9) + +pci:v00008086d000025ADsv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (CL9 mainboard) + +pci:v00008086d000025ADsv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (Telum ASLP10 Processor AMC) + +pci:v00008086d000025ADsv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=6300ESB USB2 Enhanced Host Controller (PSL09 PrPMC) + +pci:v00008086d000025AE* + ID_MODEL_FROM_DATABASE=6300ESB 64-bit PCI-X Bridge + +pci:v00008086d000025B0* + ID_MODEL_FROM_DATABASE=6300ESB SATA RAID Controller + +pci:v00008086d000025B0sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=6300ESB SATA RAID Controller (CR11/VR11 Single Board Computer) + +pci:v00008086d000025B0sv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=6300ESB SATA RAID Controller (Telum ASLP10 Processor AMC) + +pci:v00008086d000025B0sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=6300ESB SATA RAID Controller (PSL09 PrPMC) + +pci:v00008086d000025C0* + ID_MODEL_FROM_DATABASE=5000X Chipset Memory Controller Hub + +pci:v00008086d000025D0* + ID_MODEL_FROM_DATABASE=5000Z Chipset Memory Controller Hub + +pci:v00008086d000025D4* + ID_MODEL_FROM_DATABASE=5000V Chipset Memory Controller Hub + +pci:v00008086d000025D4sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=5000V Chipset Memory Controller Hub (X7DVL-E-O motherboard) + +pci:v00008086d000025D8* + ID_MODEL_FROM_DATABASE=5000P Chipset Memory Controller Hub + +pci:v00008086d000025D8sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=5000P Chipset Memory Controller Hub (X7DBN Motherboard) + +pci:v00008086d000025D8sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=5000P Chipset Memory Controller Hub (S5000PSLSATA Server Board) + +pci:v00008086d000025E2* + ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 2 + +pci:v00008086d000025E3* + ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 3 + +pci:v00008086d000025E4* + ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 4 + +pci:v00008086d000025E5* + ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 5 + +pci:v00008086d000025E6* + ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 6 + +pci:v00008086d000025E7* + ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x4 Port 7 + +pci:v00008086d000025F0* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers + +pci:v00008086d000025F0sv00001028sd000001BB* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers (PowerEdge 1955 FSB Registers) + +pci:v00008086d000025F0sv0000103Csd000031FD* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers (ProLiant DL140 G3) + +pci:v00008086d000025F0sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers (X7DVL-E-O motherboard) + +pci:v00008086d000025F0sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers (X7DBN Motherboard) + +pci:v00008086d000025F0sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FSB Registers (S5000PSLSATA Server Board) + +pci:v00008086d000025F1* + ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers + +pci:v00008086d000025F1sv0000103Csd000031FD* + ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (ProLiant DL140 G3) + +pci:v00008086d000025F1sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (X7DVL-E-O motherboard) + +pci:v00008086d000025F1sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (X7DBN Motherboard) + +pci:v00008086d000025F1sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (S5000PSLSATA Server Board) + +pci:v00008086d000025F3* + ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers + +pci:v00008086d000025F3sv0000103Csd000031FD* + ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (ProLiant DL140 G3) + +pci:v00008086d000025F3sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (X7DVL-E-O motherboard) + +pci:v00008086d000025F3sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (X7DBN Motherboard) + +pci:v00008086d000025F3sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=5000 Series Chipset Reserved Registers (S5000PSLSATA Server Board) + +pci:v00008086d000025F5* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers + +pci:v00008086d000025F5sv0000103Csd000031FD* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (ProLiant DL140 G3) + +pci:v00008086d000025F5sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (X7DVL-E-O motherboard) + +pci:v00008086d000025F5sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (X7DBN Motherboard) + +pci:v00008086d000025F5sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (S5000PSLSATA Server Board) + +pci:v00008086d000025F6* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers + +pci:v00008086d000025F6sv0000103Csd000031FD* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (ProLiant DL140 G3) + +pci:v00008086d000025F6sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (X7DVL-E-O motherboard) + +pci:v00008086d000025F6sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (X7DBN Motherboard) + +pci:v00008086d000025F6sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=5000 Series Chipset FBD Registers (S5000PSLSATA Server Board) + +pci:v00008086d000025F7* + ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x8 Port 2-3 + +pci:v00008086d000025F8* + ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x8 Port 4-5 + +pci:v00008086d000025F9* + ID_MODEL_FROM_DATABASE=5000 Series Chipset PCI Express x8 Port 6-7 + +pci:v00008086d000025FA* + ID_MODEL_FROM_DATABASE=5000X Chipset PCI Express x16 Port 4-7 + +pci:v00008086d00002600* + ID_MODEL_FROM_DATABASE=E8500/E8501 Hub Interface 1.5 + +pci:v00008086d00002600sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=E8500/E8501 Hub Interface 1.5 (PowerEdge 6850 Hub Interface) + +pci:v00008086d00002601* + ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port D + +pci:v00008086d00002602* + ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port C0 + +pci:v00008086d00002603* + ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port C1 + +pci:v00008086d00002604* + ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port B0 + +pci:v00008086d00002605* + ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port B1 + +pci:v00008086d00002606* + ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port A0 + +pci:v00008086d00002607* + ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x4 Port A1 + +pci:v00008086d00002608* + ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x8 Port C + +pci:v00008086d00002609* + ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x8 Port B + +pci:v00008086d0000260A* + ID_MODEL_FROM_DATABASE=E8500/E8501 PCI Express x8 Port A + +pci:v00008086d0000260C* + ID_MODEL_FROM_DATABASE=E8500/E8501 IMI Registers + +pci:v00008086d00002610* + ID_MODEL_FROM_DATABASE=E8500/E8501 FSB Registers + +pci:v00008086d00002611* + ID_MODEL_FROM_DATABASE=E8500/E8501 Address Mapping Registers + +pci:v00008086d00002612* + ID_MODEL_FROM_DATABASE=E8500/E8501 RAS Registers + +pci:v00008086d00002613* + ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers + +pci:v00008086d00002614* + ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers + +pci:v00008086d00002615* + ID_MODEL_FROM_DATABASE=E8500/E8501 Miscellaneous Registers + +pci:v00008086d00002617* + ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers + +pci:v00008086d00002618* + ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers + +pci:v00008086d00002619* + ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers + +pci:v00008086d0000261A* + ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers + +pci:v00008086d0000261B* + ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers + +pci:v00008086d0000261C* + ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers + +pci:v00008086d0000261D* + ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers + +pci:v00008086d0000261E* + ID_MODEL_FROM_DATABASE=E8500/E8501 Reserved Registers + +pci:v00008086d00002620* + ID_MODEL_FROM_DATABASE=E8500/E8501 eXternal Memory Bridge + +pci:v00008086d00002620sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=E8500/E8501 eXternal Memory Bridge (PowerEdge 6850 Memory Bridge) + +pci:v00008086d00002621* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Miscellaneous Registers + +pci:v00008086d00002621sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Miscellaneous Registers (PowerEdge 6850 XMB Registers) + +pci:v00008086d00002622* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Memory Interleaving Registers + +pci:v00008086d00002622sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Memory Interleaving Registers (PowerEdge 6850 Memory Interleaving Registers) + +pci:v00008086d00002623* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB DDR Initialization and Calibration + +pci:v00008086d00002623sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB DDR Initialization and Calibration (PowerEdge 6850 DDR Initialization and Calibration) + +pci:v00008086d00002624* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers + +pci:v00008086d00002624sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers (PowerEdge 6850 Reserved Registers) + +pci:v00008086d00002625* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers + +pci:v00008086d00002625sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers (PowerEdge 6850 Reserved Registers) + +pci:v00008086d00002626* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers + +pci:v00008086d00002626sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers (PowerEdge 6850 Reserved Registers) + +pci:v00008086d00002627* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers + +pci:v00008086d00002627sv00001028sd00000170* + ID_MODEL_FROM_DATABASE=E8500/E8501 XMB Reserved Registers (PowerEdge 6850 Reserved Registers) + +pci:v00008086d00002640* + ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge + +pci:v00008086d00002640sv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (915P/G Neo2) + +pci:v00008086d00002640sv00001734sd0000105C* + ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (Scenic W620) + +pci:v00008086d00002640sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (CCD-CALYPSO) + +pci:v00008086d00002640sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (CD3-JIVE) + +pci:v00008086d00002640sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FR (ICH6/ICH6R) LPC Interface Bridge (XB1) + +pci:v00008086d00002641* + ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) LPC Interface Bridge + +pci:v00008086d00002641sv00001014sd00000568* + ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) LPC Interface Bridge (ThinkPad X41) + +pci:v00008086d00002641sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) LPC Interface Bridge (Compaq nw8240/nx8220) + +pci:v00008086d00002641sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) LPC Interface Bridge (Compaq nc6220 Notebook PC) + +pci:v00008086d00002641sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) LPC Interface Bridge (NX6110/NC6120) + +pci:v00008086d00002642* + ID_MODEL_FROM_DATABASE=82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge + +pci:v00008086d00002651* + ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller + +pci:v00008086d00002651sv00001028sd00000179* + ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (Optiplex GX280) + +pci:v00008086d00002651sv00001043sd00002601* + ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (P5GD1-VW Mainboard) + +pci:v00008086d00002651sv00001734sd0000105C* + ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (Scenic W620) + +pci:v00008086d00002651sv00008086sd00004147* + ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (D915GAG Motherboard) + +pci:v00008086d00002651sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (CCD-CALYPSO) + +pci:v00008086d00002651sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (CD3-JIVE) + +pci:v00008086d00002651sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FW (ICH6/ICH6W) SATA Controller (XB1) + +pci:v00008086d00002652* + ID_MODEL_FROM_DATABASE=82801FR/FRW (ICH6R/ICH6RW) SATA Controller + +pci:v00008086d00002652sv00001028sd00000177* + ID_MODEL_FROM_DATABASE=82801FR/FRW (ICH6R/ICH6RW) SATA Controller (Dimension 8400) + +pci:v00008086d00002652sv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82801FR/FRW (ICH6R/ICH6RW) SATA Controller (915P/G Neo2) + +pci:v00008086d00002653* + ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) SATA Controller + +pci:v00008086d00002653sv00001014sd0000056A* + ID_MODEL_FROM_DATABASE=82801FBM (ICH6M) SATA Controller (ThinkPad X41) + +pci:v00008086d00002658* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 + +pci:v00008086d00002658sv00001014sd00000565* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (ThinkPad X41) + +pci:v00008086d00002658sv00001028sd00000177* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (Dimension 8400) + +pci:v00008086d00002658sv00001028sd00000179* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (Optiplex GX280) + +pci:v00008086d00002658sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (Compaq nw8240/nx8220) + +pci:v00008086d00002658sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (Compaq nc6220 Notebook PC) + +pci:v00008086d00002658sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (NX6110/NC6120) + +pci:v00008086d00002658sv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (P5GD1-VW Mainboard) + +pci:v00008086d00002658sv00001458sd00002558* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (GA-8I915ME-G Mainboard) + +pci:v00008086d00002658sv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (915P/G Neo2) + +pci:v00008086d00002658sv00001734sd0000105C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (Scenic W620) + +pci:v00008086d00002658sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (CCD-CALYPSO) + +pci:v00008086d00002658sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (CD3-JIVE) + +pci:v00008086d00002658sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 (XB1) + +pci:v00008086d00002659* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 + +pci:v00008086d00002659sv00001014sd00000565* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (ThinkPad X41) + +pci:v00008086d00002659sv00001028sd00000177* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (Dimension 8400) + +pci:v00008086d00002659sv00001028sd00000179* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (Optiplex GX280) + +pci:v00008086d00002659sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (Compaq nw8240/nx8220) + +pci:v00008086d00002659sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (Compaq nc6220 Notebook PC) + +pci:v00008086d00002659sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (NX6110/NC6120) + +pci:v00008086d00002659sv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (P5GD1-VW Mainboard) + +pci:v00008086d00002659sv00001458sd00002659* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (GA-8I915ME-G Mainboard) + +pci:v00008086d00002659sv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (915P/G Neo2) + +pci:v00008086d00002659sv00001734sd0000105C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (Scenic W620) + +pci:v00008086d00002659sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (CCD-CALYPSO) + +pci:v00008086d00002659sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (CD3-JIVE) + +pci:v00008086d00002659sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 (XB1) + +pci:v00008086d0000265A* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 + +pci:v00008086d0000265Asv00001014sd00000565* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (ThinkPad X41) + +pci:v00008086d0000265Asv00001028sd00000177* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (Dimension 8400) + +pci:v00008086d0000265Asv00001028sd00000179* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (Optiplex GX280) + +pci:v00008086d0000265Asv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (Compaq nw8240/nx8220) + +pci:v00008086d0000265Asv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (Compaq nc6220 Notebook PC) + +pci:v00008086d0000265Asv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (NX6110/NC6120) + +pci:v00008086d0000265Asv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (P5GD1-VW Mainboard) + +pci:v00008086d0000265Asv00001458sd0000265A* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (GA-8I915ME-G Mainboard) + +pci:v00008086d0000265Asv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (915P/G Neo2) + +pci:v00008086d0000265Asv00001734sd0000105C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (Scenic W620) + +pci:v00008086d0000265Asv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (CCD-CALYPSO) + +pci:v00008086d0000265Asv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (CD3-JIVE) + +pci:v00008086d0000265Asv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 (XB1) + +pci:v00008086d0000265B* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 + +pci:v00008086d0000265Bsv00001014sd00000565* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (ThinkPad X41) + +pci:v00008086d0000265Bsv00001028sd00000177* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (Dimension 8400) + +pci:v00008086d0000265Bsv00001028sd00000179* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (Optiplex GX280) + +pci:v00008086d0000265Bsv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (NX6110/NC6120) + +pci:v00008086d0000265Bsv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (P5GD1-VW Mainboard) + +pci:v00008086d0000265Bsv00001458sd0000265A* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (GA-8I915ME-G Mainboard) + +pci:v00008086d0000265Bsv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (915P/G Neo2) + +pci:v00008086d0000265Bsv00001734sd0000105C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (Scenic W620) + +pci:v00008086d0000265Bsv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (CCD-CALYPSO) + +pci:v00008086d0000265Bsv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (CD3-JIVE) + +pci:v00008086d0000265Bsv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 (XB1) + +pci:v00008086d0000265C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller + +pci:v00008086d0000265Csv00001014sd00000566* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (ThinkPad X41) + +pci:v00008086d0000265Csv00001028sd00000177* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Dimension 8400) + +pci:v00008086d0000265Csv00001028sd00000179* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Optiplex GX280) + +pci:v00008086d0000265Csv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Compaq nw8240/nx8220) + +pci:v00008086d0000265Csv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Compaq nc6220 Notebook PC) + +pci:v00008086d0000265Csv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (NX6110/NC6120) + +pci:v00008086d0000265Csv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (P5GD1-VW Mainboard) + +pci:v00008086d0000265Csv00001458sd00005006* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (GA-8I915ME-G Mainboard) + +pci:v00008086d0000265Csv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (915P/G Neo2) + +pci:v00008086d0000265Csv00001734sd0000105C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Scenic W620) + +pci:v00008086d0000265Csv00008086sd0000265C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (Dimension 3100) + +pci:v00008086d0000265Csv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (CCD-CALYPSO) + +pci:v00008086d0000265Csv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (CD3-JIVE) + +pci:v00008086d0000265Csv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller (XB1) + +pci:v00008086d00002660* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 + +pci:v00008086d00002660sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (Compaq nw8240 Mobile Workstation) + +pci:v00008086d00002660sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (Compaq nc6220 Notebook PC) + +pci:v00008086d00002660sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (NX6110/NC6120) + +pci:v00008086d00002660sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (CCD-CALYPSO) + +pci:v00008086d00002660sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (CD3-JIVE) + +pci:v00008086d00002660sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 (XB1) + +pci:v00008086d00002662* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 + +pci:v00008086d00002662sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (Compaq nw8240 Mobile Workstation) + +pci:v00008086d00002662sv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (Compaq nc6220 Notebook PC) + +pci:v00008086d00002662sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (CCD-CALYPSO) + +pci:v00008086d00002662sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (CD3-JIVE) + +pci:v00008086d00002662sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 (XB1) + +pci:v00008086d00002664* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 + +pci:v00008086d00002664sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 (CCD-CALYPSO) + +pci:v00008086d00002664sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 (CD3-JIVE) + +pci:v00008086d00002664sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 (XB1) + +pci:v00008086d00002666* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 + +pci:v00008086d00002666sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 (CCD-CALYPSO) + +pci:v00008086d00002666sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 (CD3-JIVE) + +pci:v00008086d00002666sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 (XB1) + +pci:v00008086d00002668* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller + +pci:v00008086d00002668sv00001014sd000005B7* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (ThinkPad Z60t) + +pci:v00008086d00002668sv0000103Csd00002A09* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (PufferM-UL8E) + +pci:v00008086d00002668sv00001043sd00001173* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (A6VC) + +pci:v00008086d00002668sv00001043sd0000814E* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (P5GD1-VW Mainboard) + +pci:v00008086d00002668sv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (915P/G Neo2) + +pci:v00008086d00002668sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller (QEMU Virtual Machine) + +pci:v00008086d0000266A* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller + +pci:v00008086d0000266Asv00001014sd0000056B* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (ThinkPad X41) + +pci:v00008086d0000266Asv00001028sd00000177* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (Dimension 8400) + +pci:v00008086d0000266Asv00001028sd00000179* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (Optiplex GX280) + +pci:v00008086d0000266Asv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (P5GD1-VW Mainboard) + +pci:v00008086d0000266Asv00001458sd0000266A* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (GA-8I915ME-G Mainboard) + +pci:v00008086d0000266Asv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (915P/G Neo2) + +pci:v00008086d0000266Asv00001734sd0000105C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (Scenic W620) + +pci:v00008086d0000266Asv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (CCD-CALYPSO) + +pci:v00008086d0000266Asv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (CD3-JIVE) + +pci:v00008086d0000266Asv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller (XB1) + +pci:v00008086d0000266C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller + +pci:v00008086d0000266D* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller + +pci:v00008086d0000266Dsv00001025sd0000006A* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller (Conexant AC'97 CoDec (in Acer TravelMate 2410 serie laptop)) + +pci:v00008086d0000266Dsv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller (Compaq nw8240/nx8220) + +pci:v00008086d0000266Dsv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller (NX6110/NC6120) + +pci:v00008086d0000266E* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller + +pci:v00008086d0000266Esv00001014sd00000581* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (ThinkPad X41 (Analog Devices AD1981B codec)) + +pci:v00008086d0000266Esv00001025sd0000006A* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Realtek ALC 655 codec (in Acer TravelMate 2410 serie laptop)) + +pci:v00008086d0000266Esv00001028sd00000177* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Dimension 8400) + +pci:v00008086d0000266Esv00001028sd00000179* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Optiplex GX280) + +pci:v00008086d0000266Esv00001028sd00000182* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Latitude D610 Laptop) + +pci:v00008086d0000266Esv00001028sd00000187* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Precision M70 Laptop) + +pci:v00008086d0000266Esv00001028sd00000188* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Inspiron 6000 laptop) + +pci:v00008086d0000266Esv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Compaq nw8240/nx8220) + +pci:v00008086d0000266Esv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Compaq NC6220) + +pci:v00008086d0000266Esv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (NX6110/NC6120) + +pci:v00008086d0000266Esv0000103Csd00003006* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (DC7100 SFF(DX878AV)) + +pci:v00008086d0000266Esv00001458sd0000A002* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (GA-8I915ME-G Mainboard) + +pci:v00008086d0000266Esv0000152Dsd00000745* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Packard Bell A8550 Laptop) + +pci:v00008086d0000266Esv00001734sd0000105A* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller (Scenic W620) + +pci:v00008086d0000266F* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller + +pci:v00008086d0000266Fsv00001028sd00000177* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (Dimension 8400) + +pci:v00008086d0000266Fsv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (Compaq nw8240/nx8220) + +pci:v00008086d0000266Fsv0000103Csd00000944* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (Compaq nc6220 Notebook PC) + +pci:v00008086d0000266Fsv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (NX6110/NC6120) + +pci:v00008086d0000266Fsv00001043sd000080A6* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (P5GD1-VW Mainboard) + +pci:v00008086d0000266Fsv00001458sd0000266F* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (GA-8I915ME-G Mainboard) + +pci:v00008086d0000266Fsv00001462sd00007028* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (915P/G Neo2) + +pci:v00008086d0000266Fsv00001734sd0000105C* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (Scenic W620) + +pci:v00008086d0000266Fsv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (CCD-CALYPSO) + +pci:v00008086d0000266Fsv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (CD3-JIVE) + +pci:v00008086d0000266Fsv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller (XB1) + +pci:v00008086d00002670* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset LPC Interface Controller + +pci:v00008086d00002670sv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset LPC Interface Controller (ProLiant DL140 G3) + +pci:v00008086d00002670sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset LPC Interface Controller (X7DVL-E-O motherboard) + +pci:v00008086d00002670sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset LPC Interface Controller (X7DBN Motherboard) + +pci:v00008086d00002670sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset LPC Interface Controller (S5000PSLSATA Server Board) + +pci:v00008086d00002680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SATA IDE Controller + +pci:v00008086d00002681* + ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA AHCI Controller + +pci:v00008086d00002681sv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA AHCI Controller (ProLiant DL140 G3) + +pci:v00008086d00002681sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA AHCI Controller (X7DVL-E-O motherboard) + +pci:v00008086d00002681sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA AHCI Controller (X7DBN Motherboard) + +pci:v00008086d00002681sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA AHCI Controller (S5000PSLSATA Server Board) + +pci:v00008086d00002682* + ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA RAID Controller + +pci:v00008086d00002682sv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA RAID Controller (Adaptec Serial ATA HostRAID) + +pci:v00008086d00002683* + ID_MODEL_FROM_DATABASE=631xESB/632xESB SATA RAID Controller + +pci:v00008086d00002688* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 + +pci:v00008086d00002688sv00001028sd000001BB* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (PowerEdge 1955 onboard USB) + +pci:v00008086d00002688sv00001028sd000001F0* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (PowerEdge R900 onboard USB) + +pci:v00008086d00002688sv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (ProLiant DL140 G3) + +pci:v00008086d00002688sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (X7DVL-E-O motherboard) + +pci:v00008086d00002688sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (X7DBN Motherboard) + +pci:v00008086d00002688sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #1 (S5000PSLSATA Server Board) + +pci:v00008086d00002689* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 + +pci:v00008086d00002689sv00001028sd000001BB* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (PowerEdge 1955 onboard USB) + +pci:v00008086d00002689sv00001028sd000001F0* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (PowerEdge R900 onboard USB) + +pci:v00008086d00002689sv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (ProLiant DL140 G3) + +pci:v00008086d00002689sv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (X7DVL-E-O motherboard) + +pci:v00008086d00002689sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (X7DBN Motherboard) + +pci:v00008086d00002689sv00008086sd00003476* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #2 (S5000PSLSATA Server Board) + +pci:v00008086d0000268A* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 + +pci:v00008086d0000268Asv00001028sd000001F0* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 (PowerEdge R900 onboard USB) + +pci:v00008086d0000268Asv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 (ProLiant DL140 G3) + +pci:v00008086d0000268Asv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 (X7DVL-E-O motherboard) + +pci:v00008086d0000268Asv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 (X7DBN Motherboard) + +pci:v00008086d0000268Asv00008086sd00003476* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #3 (S5000PSLSATA Server Board) + +pci:v00008086d0000268B* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #4 + +pci:v00008086d0000268Bsv00001028sd000001F0* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #4 (PowerEdge R900 onboard USB) + +pci:v00008086d0000268Bsv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #4 (X7DVL-E-O motherboard) + +pci:v00008086d0000268Bsv00008086sd00003476* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset UHCI USB Controller #4 (S5000PSLSATA Server Board) + +pci:v00008086d0000268C* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller + +pci:v00008086d0000268Csv00001028sd000001BB* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (PowerEdge 1955 onboard USB) + +pci:v00008086d0000268Csv00001028sd000001F0* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (PowerEdge R900 onboard USB) + +pci:v00008086d0000268Csv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (ProLiant DL140 G3) + +pci:v00008086d0000268Csv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (X7DVL-E-O motherboard) + +pci:v00008086d0000268Csv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (X7DBN Motherboard) + +pci:v00008086d0000268Csv00008086sd00003476* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset EHCI USB2 Controller (S5000PSLSATA Server Board) + +pci:v00008086d00002690* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 1 + +pci:v00008086d00002690sv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 1 (ProLiant DL140 G3) + +pci:v00008086d00002690sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 1 (X7DBN Motherboard) + +pci:v00008086d00002692* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 2 + +pci:v00008086d00002692sv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 2 (ProLiant DL140 G3) + +pci:v00008086d00002694* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 3 + +pci:v00008086d00002696* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset PCI Express Root Port 4 + +pci:v00008086d00002698* + ID_MODEL_FROM_DATABASE=631xESB/632xESB AC '97 Audio Controller + +pci:v00008086d00002699* + ID_MODEL_FROM_DATABASE=631xESB/632xESB AC '97 Modem Controller + +pci:v00008086d0000269A* + ID_MODEL_FROM_DATABASE=631xESB/632xESB High Definition Audio Controller + +pci:v00008086d0000269B* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SMBus Controller + +pci:v00008086d0000269Bsv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SMBus Controller (ProLiant DL140 G3) + +pci:v00008086d0000269Bsv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SMBus Controller (X7DVL-E-O motherboard) + +pci:v00008086d0000269Bsv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SMBus Controller (X7DBN Motherboard) + +pci:v00008086d0000269Bsv00008086sd00003476* + ID_MODEL_FROM_DATABASE=631xESB/632xESB/3100 Chipset SMBus Controller (S5000PSLSATA Server Board) + +pci:v00008086d0000269E* + ID_MODEL_FROM_DATABASE=631xESB/632xESB IDE Controller + +pci:v00008086d0000269Esv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=631xESB/632xESB IDE Controller (ProLiant DL140 G3) + +pci:v00008086d0000269Esv000015D9sd00008680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB IDE Controller (X7DVL-E-O motherboard) + +pci:v00008086d0000269Esv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=631xESB/632xESB IDE Controller (X7DBN Motherboard) + +pci:v00008086d00002700* + ID_MODEL_FROM_DATABASE=Optane SSD 900P Series + +pci:v00008086d00002700sv00008086sd00003900* + ID_MODEL_FROM_DATABASE=Optane SSD 900P Series (900P Series [Add-in Card]) + +pci:v00008086d00002700sv00008086sd00003901* + ID_MODEL_FROM_DATABASE=Optane SSD 900P Series (900P Series [2.5" SFF]) + +pci:v00008086d00002701* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] + +pci:v00008086d00002701sv00001028sd00002000* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (Express Flash NVMe [Optane] 375GB 2.5" U.2 (P4800X)) + +pci:v00008086d00002701sv00001028sd00002001* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (Express Flash NVMe [Optane] 750GB 2.5" U.2 (P4800X)) + +pci:v00008086d00002701sv00001028sd00002002* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (Express Flash NVMe [Optane] 750GB AIC (P4800X)) + +pci:v00008086d00002701sv00001028sd0000200A* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (Express Flash NVMe [Optane] 375GB AIC (P4800X)) + +pci:v00008086d00002701sv00008086sd00003904* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (x4 AIC (P4800X)) + +pci:v00008086d00002701sv00008086sd00003905* + ID_MODEL_FROM_DATABASE=NVMe Datacenter SSD [Optane] (15mm 2.5" U.2 (P4800X)) + +pci:v00008086d00002723* + ID_MODEL_FROM_DATABASE=Wi-Fi 6 AX200 + +pci:v00008086d00002723sv00008086sd00002723* + ID_MODEL_FROM_DATABASE=Wi-Fi 6 AX200 (Wireless AX200) + +pci:v00008086d00002770* + ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub + +pci:v00008086d00002770sv00001028sd000001AD* + ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (OptiPlex GX620) + +pci:v00008086d00002770sv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (Pavilion A1512X) + +pci:v00008086d00002770sv00001043sd0000817A* + ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (P5LD2-VM Mainboard) + +pci:v00008086d00002770sv0000107Bsd00005048* + ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (E4500) + +pci:v00008086d00002770sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (Wind PC MS-7418) + +pci:v00008086d00002770sv00001849sd00002770* + ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (ConRoe1333-D667) + +pci:v00008086d00002770sv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL Memory Controller Hub (DeskTop Board D945GTP) + +pci:v00008086d00002771* + ID_MODEL_FROM_DATABASE=82945G/GZ/P/PL PCI Express Root Port + +pci:v00008086d00002772* + ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller + +pci:v00008086d00002772sv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller (Pavilion A1512X) + +pci:v00008086d00002772sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller (Wind PC MS-7418) + +pci:v00008086d00002772sv00001849sd00002772* + ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller (ConRoe1333-D667) + +pci:v00008086d00002772sv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller (DeskTop Board D945GTP) + +pci:v00008086d00002772sv00008086sd0000D605* + ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller (Desktop Board D945GCCR) + +pci:v00008086d00002774* + ID_MODEL_FROM_DATABASE=82955X Memory Controller Hub + +pci:v00008086d00002775* + ID_MODEL_FROM_DATABASE=82955X PCI Express Root Port + +pci:v00008086d00002776* + ID_MODEL_FROM_DATABASE=82945G/GZ Integrated Graphics Controller + +pci:v00008086d00002778* + ID_MODEL_FROM_DATABASE=E7230/3000/3010 Memory Controller Hub + +pci:v00008086d00002778sv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=E7230/3000/3010 Memory Controller Hub (PowerEdge SC440) + +pci:v00008086d00002778sv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=E7230/3000/3010 Memory Controller Hub (PowerEdge 860) + +pci:v00008086d00002779* + ID_MODEL_FROM_DATABASE=E7230/3000/3010 PCI Express Root Port + +pci:v00008086d0000277A* + ID_MODEL_FROM_DATABASE=82975X/3010 PCI Express Root Port + +pci:v00008086d0000277C* + ID_MODEL_FROM_DATABASE=82975X Memory Controller Hub + +pci:v00008086d0000277Csv00001043sd00008178* + ID_MODEL_FROM_DATABASE=82975X Memory Controller Hub (P5WDG2 WS Professional motherboard) + +pci:v00008086d0000277D* + ID_MODEL_FROM_DATABASE=82975X PCI Express Root Port + +pci:v00008086d00002782* + ID_MODEL_FROM_DATABASE=82915G Integrated Graphics Controller + +pci:v00008086d00002782sv00001043sd00002582* + ID_MODEL_FROM_DATABASE=82915G Integrated Graphics Controller (P5GD1-VW Mainboard) + +pci:v00008086d00002782sv00001734sd0000105B* + ID_MODEL_FROM_DATABASE=82915G Integrated Graphics Controller (Scenic W620) + +pci:v00008086d00002792* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller + +pci:v00008086d00002792sv00001014sd00000582* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (ThinkPad X41) + +pci:v00008086d00002792sv0000103Csd0000099C* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (NX6110/NC6120) + +pci:v00008086d00002792sv0000103Csd0000308A* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (Compaq nc6220 Notebook PC) + +pci:v00008086d00002792sv00001043sd00001881* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (GMA 900 915GM Integrated Graphics) + +pci:v00008086d00002792sv0000E4BFsd00000CCD* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (CCD-CALYPSO) + +pci:v00008086d00002792sv0000E4BFsd00000CD3* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (CD3-JIVE) + +pci:v00008086d00002792sv0000E4BFsd000058B1* + ID_MODEL_FROM_DATABASE=Mobile 915GM/GMS/910GML Express Graphics Controller (XB1) + +pci:v00008086d000027A0* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub + +pci:v00008086d000027A0sv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (9814 WKMI) + +pci:v00008086d000027A0sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (XPS M1210) + +pci:v00008086d000027A0sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (Compaq nx9420 Notebook) + +pci:v00008086d000027A0sv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (NC2400) + +pci:v00008086d000027A0sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (Compaq nw8440) + +pci:v00008086d000027A0sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (530 Laptop) + +pci:v00008086d000027A0sv00001043sd00001237* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (A6J-Q008) + +pci:v00008086d000027A0sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027A0sv000017AAsd00002015* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (ThinkPad T60) + +pci:v00008086d000027A0sv000017AAsd00002017* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027A1* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express PCI Express Root Port + +pci:v00008086d000027A1sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express PCI Express Root Port (Compaq nx9420 Notebook) + +pci:v00008086d000027A1sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express PCI Express Root Port (Compaq nw8440) + +pci:v00008086d000027A1sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=Mobile 945GM/PM/GMS, 943/940GML and 945GT Express PCI Express Root Port (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027A2* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller + +pci:v00008086d000027A2sv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (NC2400) + +pci:v00008086d000027A2sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (530 Laptop) + +pci:v00008086d000027A2sv000017AAsd0000201A* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027A2sv00009902sd00001584* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (CCE MPL-D10H120F) + +pci:v00008086d000027A6* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller + +pci:v00008086d000027A6sv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (NC2400) + +pci:v00008086d000027A6sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (530 Laptop) + +pci:v00008086d000027A6sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (CC11/CL11 integrated graphics (secondary)) + +pci:v00008086d000027A6sv000017AAsd0000201A* + ID_MODEL_FROM_DATABASE=Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027AC* + ID_MODEL_FROM_DATABASE=Mobile 945GSE Express Memory Controller Hub + +pci:v00008086d000027ACsv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=Mobile 945GSE Express Memory Controller Hub (CC11/CL11) + +pci:v00008086d000027AD* + ID_MODEL_FROM_DATABASE=Mobile 945GSE Express PCI Express Root Port + +pci:v00008086d000027AE* + ID_MODEL_FROM_DATABASE=Mobile 945GSE Express Integrated Graphics Controller + +pci:v00008086d000027AEsv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=Mobile 945GSE Express Integrated Graphics Controller (CC11/CL11 integrated graphics (primary)) + +pci:v00008086d000027B0* + ID_MODEL_FROM_DATABASE=82801GH (ICH7DH) LPC Interface Bridge + +pci:v00008086d000027B0sv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=82801GH (ICH7DH) LPC Interface Bridge (Pavilion A1512X) + +pci:v00008086d000027B0sv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=82801GH (ICH7DH) LPC Interface Bridge (DeskTop Board D945GTP) + +pci:v00008086d000027B8* + ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge + +pci:v00008086d000027B8sv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (PowerEdge 860) + +pci:v00008086d000027B8sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (Compaq 500B Microtower) + +pci:v00008086d000027B8sv00001043sd00008179* + ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (P5B-MX/WiFi-AP, P5KPL-VM Motherboard) + +pci:v00008086d000027B8sv0000107Bsd00005048* + ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (E4500) + +pci:v00008086d000027B8sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (Wind PC MS-7418) + +pci:v00008086d000027B8sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (CC11/CL11) + +pci:v00008086d000027B8sv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=82801GB/GR (ICH7 Family) LPC Interface Bridge (DeskTop Board D945GTP) + +pci:v00008086d000027B9* + ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge + +pci:v00008086d000027B9sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (XPS M1210) + +pci:v00008086d000027B9sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (Compaq nx9420 Notebook) + +pci:v00008086d000027B9sv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (NC2400) + +pci:v00008086d000027B9sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (Compaq nw8440) + +pci:v00008086d000027B9sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (530 Laptop) + +pci:v00008086d000027B9sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027B9sv000010F7sd00008338* + ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (Panasonic CF-Y5 laptop) + +pci:v00008086d000027B9sv000017AAsd00002009* + ID_MODEL_FROM_DATABASE=82801GBM (ICH7-M) LPC Interface Bridge (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027BC* + ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller + +pci:v00008086d000027BCsv00001043sd000083AD* + ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (Eee PC 1015PX) + +pci:v00008086d000027BCsv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (D270S/D250S Motherboard) + +pci:v00008086d000027BCsv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (Notebook N150P) + +pci:v00008086d000027BCsv00001458sd00005001* + ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (GA-D525TUD) + +pci:v00008086d000027BCsv00008086sd00004F4D* + ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (DeskTop Board D510MO) + +pci:v00008086d000027BCsv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=NM10 Family LPC Controller (Desktop Board D425KT) + +pci:v00008086d000027BD* + ID_MODEL_FROM_DATABASE=82801GHM (ICH7-M DH) LPC Interface Bridge + +pci:v00008086d000027BDsv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=82801GHM (ICH7-M DH) LPC Interface Bridge (9814 WKMI) + +pci:v00008086d000027C0* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] + +pci:v00008086d000027C0sv00001028sd000001AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (OptiPlex GX620) + +pci:v00008086d000027C0sv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (PowerEdge SC440) + +pci:v00008086d000027C0sv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (PowerEdge 860) + +pci:v00008086d000027C0sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (Compaq 500B Microtower) + +pci:v00008086d000027C0sv00001043sd00008179* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (P5B-MX/WiFi-AP, P5KPL-VM Motherboard) + +pci:v00008086d000027C0sv0000107Bsd00005048* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (E4500) + +pci:v00008086d000027C0sv00001462sd00002310* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (MSI Hetis 945) + +pci:v00008086d000027C0sv00001462sd00007236* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (945P Neo3-F Rev. 2.2 motherboard) + +pci:v00008086d000027C0sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (Wind PC MS-7418) + +pci:v00008086d000027C0sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (CC11/CL11) + +pci:v00008086d000027C0sv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (Desktop Board D425KT) + +pci:v00008086d000027C0sv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [IDE mode] (DeskTop Board D945GTP) + +pci:v00008086d000027C1* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] + +pci:v00008086d000027C1sv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (PowerEdge SC440) + +pci:v00008086d000027C1sv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (Pavilion A1512X) + +pci:v00008086d000027C1sv00001043sd000083AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (Eee PC 1015PX) + +pci:v00008086d000027C1sv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (D270S/D250S Motherboard) + +pci:v00008086d000027C1sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (Notebook N150P) + +pci:v00008086d000027C1sv00001458sd0000B005* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (GA-D525TUD) + +pci:v00008086d000027C1sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (CC11/CL11) + +pci:v00008086d000027C1sv00008086sd00004F4D* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (DeskTop Board D510MO) + +pci:v00008086d000027C1sv00008086sd00005842* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SATA Controller [AHCI mode] (DeskTop Board D975XBX) + +pci:v00008086d000027C3* + ID_MODEL_FROM_DATABASE=82801GR/GDH (ICH7R/ICH7DH) SATA Controller [RAID mode] + +pci:v00008086d000027C3sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=82801GR/GDH (ICH7R/ICH7DH) SATA Controller [RAID mode] (CC11/CL11) + +pci:v00008086d000027C3sv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=82801GR/GDH (ICH7R/ICH7DH) SATA Controller [RAID mode] (DeskTop Board D945GTP) + +pci:v00008086d000027C4* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] + +pci:v00008086d000027C4sv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] (9814 WKMI) + +pci:v00008086d000027C4sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] (XPS M1210) + +pci:v00008086d000027C4sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027C4sv000017AAsd0000200E* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] (ThinkPad T60) + +pci:v00008086d000027C5* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] + +pci:v00008086d000027C5sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] (Compaq nx9420 Notebook) + +pci:v00008086d000027C5sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] (Compaq nw8440) + +pci:v00008086d000027C5sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] (530 Laptop) + +pci:v00008086d000027C5sv000017AAsd0000200D* + ID_MODEL_FROM_DATABASE=82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027C6* + ID_MODEL_FROM_DATABASE=82801GHM (ICH7-M DH) SATA Controller [RAID mode] + +pci:v00008086d000027C8* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 + +pci:v00008086d000027C8sv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (9814 WKMI) + +pci:v00008086d000027C8sv00001028sd000001AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (OptiPlex GX620) + +pci:v00008086d000027C8sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (XPS M1210) + +pci:v00008086d000027C8sv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (PowerEdge SC440) + +pci:v00008086d000027C8sv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (PowerEdge 860) + +pci:v00008086d000027C8sv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Pavilion A1512X) + +pci:v00008086d000027C8sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Compaq 500B Microtower) + +pci:v00008086d000027C8sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Compaq nx9420 Notebook) + +pci:v00008086d000027C8sv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (NC2400) + +pci:v00008086d000027C8sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Compaq nw8440) + +pci:v00008086d000027C8sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (530 Laptop) + +pci:v00008086d000027C8sv00001043sd00001237* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (A6J-Q008) + +pci:v00008086d000027C8sv00001043sd00008179* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (P5B-MX/WiFi-AP, P5KPL-VM, P5LD2-VM Mainboard) + +pci:v00008086d000027C8sv00001043sd000083AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Eee PC 1015PX) + +pci:v00008086d000027C8sv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (D270S/D250S Motherboard) + +pci:v00008086d000027C8sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027C8sv0000107Bsd00005048* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (E4500) + +pci:v00008086d000027C8sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Notebook N150P) + +pci:v00008086d000027C8sv00001458sd00005004* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (GA-D525TUD) + +pci:v00008086d000027C8sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Wind PC MS-7418) + +pci:v00008086d000027C8sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (CC11/CL11) + +pci:v00008086d000027C8sv000017AAsd0000200A* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027C8sv00008086sd00004F4D* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (DeskTop Board D510MO) + +pci:v00008086d000027C8sv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (Desktop Board D425KT) + +pci:v00008086d000027C8sv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #1 (DeskTop Board D945GTP) + +pci:v00008086d000027C9* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 + +pci:v00008086d000027C9sv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (9814 WKMI) + +pci:v00008086d000027C9sv00001028sd000001AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (OptiPlex GX620) + +pci:v00008086d000027C9sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (XPS M1210) + +pci:v00008086d000027C9sv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (PowerEdge SC440) + +pci:v00008086d000027C9sv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (PowerEdge 860) + +pci:v00008086d000027C9sv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Pavilion A1512X) + +pci:v00008086d000027C9sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Compaq 500B Microtower) + +pci:v00008086d000027C9sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Compaq nx9420 Notebook) + +pci:v00008086d000027C9sv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (NC2400) + +pci:v00008086d000027C9sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Compaq nw8440) + +pci:v00008086d000027C9sv00001043sd00001237* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (A6J-Q008) + +pci:v00008086d000027C9sv00001043sd00008179* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (P5B-MX/WiFi-AP, P5KPL-VM, P5LD2-VM Mainboard) + +pci:v00008086d000027C9sv00001043sd000083AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Eee PC 1015PX) + +pci:v00008086d000027C9sv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (D270S/D250S Motherboard) + +pci:v00008086d000027C9sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027C9sv0000107Bsd00005048* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (E4500) + +pci:v00008086d000027C9sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Notebook N150P) + +pci:v00008086d000027C9sv00001458sd00005004* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (GA-D525TUD) + +pci:v00008086d000027C9sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Wind PC MS-7418) + +pci:v00008086d000027C9sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (CC11/CL11) + +pci:v00008086d000027C9sv000017AAsd0000200A* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027C9sv00008086sd00004F4D* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (DeskTop Board D510MO) + +pci:v00008086d000027C9sv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (Desktop Board D425KT) + +pci:v00008086d000027C9sv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #2 (DeskTop Board D945GTP) + +pci:v00008086d000027CA* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 + +pci:v00008086d000027CAsv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (9814 WKMI) + +pci:v00008086d000027CAsv00001028sd000001AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (OptiPlex GX620) + +pci:v00008086d000027CAsv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (XPS M1210) + +pci:v00008086d000027CAsv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (PowerEdge SC440) + +pci:v00008086d000027CAsv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (PowerEdge 860) + +pci:v00008086d000027CAsv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Pavilion A1512X) + +pci:v00008086d000027CAsv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Compaq 500B Microtower) + +pci:v00008086d000027CAsv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Compaq nx9420 Notebook) + +pci:v00008086d000027CAsv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (NC2400) + +pci:v00008086d000027CAsv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Compaq nw8440) + +pci:v00008086d000027CAsv00001043sd00001237* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (A6J-Q008) + +pci:v00008086d000027CAsv00001043sd00008179* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (P5B-MX/WiFi-AP, P5KPL-VM, P5LD2-VM Mainboard) + +pci:v00008086d000027CAsv00001043sd000083AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Eee PC 1015PX) + +pci:v00008086d000027CAsv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (D270S/D250S Motherboard) + +pci:v00008086d000027CAsv00001071sd00008209* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027CAsv0000107Bsd00005048* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (E4500) + +pci:v00008086d000027CAsv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Notebook N150P) + +pci:v00008086d000027CAsv00001458sd00005004* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (GA-D525TUD) + +pci:v00008086d000027CAsv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (Wind PC MS-7418) + +pci:v00008086d000027CAsv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (CC11/CL11) + +pci:v00008086d000027CAsv000017AAsd0000200A* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027CAsv00008086sd00004F4D* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (DeskTop Board D510MO) + +pci:v00008086d000027CAsv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #3 (DeskTop Board D945GTP) + +pci:v00008086d000027CB* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 + +pci:v00008086d000027CBsv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (9814 WKMI) + +pci:v00008086d000027CBsv00001028sd000001AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (OptiPlex GX620) + +pci:v00008086d000027CBsv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (XPS M1210) + +pci:v00008086d000027CBsv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (PowerEdge SC440) + +pci:v00008086d000027CBsv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Pavilion A1512X) + +pci:v00008086d000027CBsv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Compaq 500B Microtower) + +pci:v00008086d000027CBsv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Compaq nx9420 Notebook) + +pci:v00008086d000027CBsv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (NC2400) + +pci:v00008086d000027CBsv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Compaq nw8440) + +pci:v00008086d000027CBsv00001043sd00001237* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (A6J-Q008) + +pci:v00008086d000027CBsv00001043sd00008179* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (P5B-MX/WiFi-AP, P5KPL-VM, P5LD2-VM Mainboard) + +pci:v00008086d000027CBsv00001043sd000083AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Eee PC 1015PX) + +pci:v00008086d000027CBsv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (D270S/D250S Motherboard) + +pci:v00008086d000027CBsv00001071sd00008209* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027CBsv0000107Bsd00005048* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (E4500) + +pci:v00008086d000027CBsv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Notebook N150P) + +pci:v00008086d000027CBsv00001458sd00005004* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (GA-D525TUD) + +pci:v00008086d000027CBsv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (Wind PC MS-7418) + +pci:v00008086d000027CBsv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (CC11/CL11) + +pci:v00008086d000027CBsv000017AAsd0000200A* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027CBsv00008086sd00004F4D* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (DeskTop Board D510MO) + +pci:v00008086d000027CBsv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB UHCI Controller #4 (DeskTop Board D945GTP) + +pci:v00008086d000027CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller + +pci:v00008086d000027CCsv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (9814 WKMI) + +pci:v00008086d000027CCsv00001028sd000001AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (OptiPlex GX620) + +pci:v00008086d000027CCsv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (XPS M1210) + +pci:v00008086d000027CCsv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (PowerEdge SC440) + +pci:v00008086d000027CCsv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (PowerEdge 860) + +pci:v00008086d000027CCsv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Pavilion A1512X) + +pci:v00008086d000027CCsv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Compaq 500B Microtower) + +pci:v00008086d000027CCsv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Compaq nx9420 Notebook) + +pci:v00008086d000027CCsv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (NC2400) + +pci:v00008086d000027CCsv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Compaq nw8440) + +pci:v00008086d000027CCsv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (530 Laptop) + +pci:v00008086d000027CCsv00001043sd00001237* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (A6J-Q008) + +pci:v00008086d000027CCsv00001043sd00008179* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (P5B-MX/WiFi-AP, P5KPL-VM, P5LD2-VM Mainboard) + +pci:v00008086d000027CCsv00001043sd000083AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Eee PC 1015PX) + +pci:v00008086d000027CCsv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (D270S/D250S Motherboard) + +pci:v00008086d000027CCsv00001071sd00008209* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027CCsv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Notebook N150P) + +pci:v00008086d000027CCsv00001458sd00005006* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (GA-D525TUD) + +pci:v00008086d000027CCsv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Wind PC MS-7418) + +pci:v00008086d000027CCsv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (CC11/CL11) + +pci:v00008086d000027CCsv000017AAsd0000200B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027CCsv00008086sd00004F4D* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (DeskTop Board D510MO) + +pci:v00008086d000027CCsv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (Desktop Board D425KT) + +pci:v00008086d000027CCsv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family USB2 EHCI Controller (DeskTop Board D945GTP) + +pci:v00008086d000027D0* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 + +pci:v00008086d000027D0sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Compaq nx9420 Notebook) + +pci:v00008086d000027D0sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Compaq nw8440) + +pci:v00008086d000027D0sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027D0sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Notebook N150P) + +pci:v00008086d000027D0sv00001458sd00005001* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (GA-D525TUD) + +pci:v00008086d000027D0sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Wind PC MS-7418) + +pci:v00008086d000027D0sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (CC11/CL11) + +pci:v00008086d000027D0sv000017AAsd00002011* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (ThinkPad R60e) + +pci:v00008086d000027D0sv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 1 (Desktop Board D425KT) + +pci:v00008086d000027D2* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 + +pci:v00008086d000027D2sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Compaq nx9420 Notebook) + +pci:v00008086d000027D2sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Compaq nw8440) + +pci:v00008086d000027D2sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027D2sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Notebook N150P) + +pci:v00008086d000027D2sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Wind PC MS-7418) + +pci:v00008086d000027D2sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (CC11/CL11) + +pci:v00008086d000027D2sv000017AAsd00002011* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (ThinkPad R60e) + +pci:v00008086d000027D2sv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 2 (Desktop Board D425KT) + +pci:v00008086d000027D4* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 + +pci:v00008086d000027D4sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027D4sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (Notebook N150P) + +pci:v00008086d000027D4sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (Wind PC MS-7418) + +pci:v00008086d000027D4sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (CC11/CL11) + +pci:v00008086d000027D4sv000017AAsd00002011* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (ThinkPad R60e) + +pci:v00008086d000027D4sv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 3 (Desktop Board D425KT) + +pci:v00008086d000027D6* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 + +pci:v00008086d000027D6sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Compaq nw8440) + +pci:v00008086d000027D6sv00001071sd00008209* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027D6sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Notebook N150P) + +pci:v00008086d000027D6sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Wind PC MS-7418) + +pci:v00008086d000027D6sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (CC11/CL11) + +pci:v00008086d000027D6sv000017AAsd00002011* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (ThinkPad R60e) + +pci:v00008086d000027D6sv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family PCI Express Port 4 (Desktop Board D425KT) + +pci:v00008086d000027D8* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller + +pci:v00008086d000027D8sv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (9814 WKMI) + +pci:v00008086d000027D8sv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (XPS M1210) + +pci:v00008086d000027D8sv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Pavilion A1512X) + +pci:v00008086d000027D8sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Compaq 500B Microtower) + +pci:v00008086d000027D8sv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Compaq nx9420 Notebook) + +pci:v00008086d000027D8sv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (NC2400) + +pci:v00008086d000027D8sv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Compaq nw8440) + +pci:v00008086d000027D8sv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (530 Laptop) + +pci:v00008086d000027D8sv00001043sd00001123* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (A6J-Q008) + +pci:v00008086d000027D8sv00001043sd000013C4* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (G2P) + +pci:v00008086d000027D8sv00001043sd0000817F* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (P5LD2-VM Mainboard (Realtek ALC 882 codec)) + +pci:v00008086d000027D8sv00001043sd00008249* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (P5B-MX/WiFi-AP) + +pci:v00008086d000027D8sv00001043sd00008290* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (P5KPL-VM Motherboard) + +pci:v00008086d000027D8sv00001043sd000082EA* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (P5KPL-CM Motherboard) + +pci:v00008086d000027D8sv00001043sd00008437* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Eee PC 1015PX) + +pci:v00008086d000027D8sv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (D270S/D250S Motherboard) + +pci:v00008086d000027D8sv00001071sd00008207* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027D8sv0000107Bsd00005048* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (E4500) + +pci:v00008086d000027D8sv000010F7sd00008338* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Panasonic CF-Y5 laptop) + +pci:v00008086d000027D8sv00001179sd0000FF10* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Toshiba Satellite A100-796 audio (Realtek ALC861)) + +pci:v00008086d000027D8sv00001179sd0000FF31* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (AC97 Data Fax SoftModem with SmartCP) + +pci:v00008086d000027D8sv00001447sd00001043* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Asus A8JP (Analog Devices AD1986A)) + +pci:v00008086d000027D8sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Notebook N150P) + +pci:v00008086d000027D8sv00001458sd0000A002* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (GA-D525TUD (Realtek ALC887)) + +pci:v00008086d000027D8sv00001458sd0000A102* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (GA-8I945PG-RH Mainboard) + +pci:v00008086d000027D8sv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Wind PC MS-7418) + +pci:v00008086d000027D8sv0000152Dsd00000753* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Softmodem) + +pci:v00008086d000027D8sv00001734sd000010AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (Conexant softmodem SmartCP) + +pci:v00008086d000027D8sv000017AAsd00002010* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027D8sv000017AAsd00003802* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (3000 C200 audio [Realtek ALC861VD]) + +pci:v00008086d000027D8sv00008086sd00001112* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (DeskTop Board D945GTP) + +pci:v00008086d000027D8sv00008086sd000027D8* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (DeskTop Board D945GTP) + +pci:v00008086d000027D8sv00008086sd0000D618* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (DeskTop Board D510MO) + +pci:v00008086d000027D8sv00008384sd00007680* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family High Definition Audio Controller (STAC9221 HD Audio Codec) + +pci:v00008086d000027DA* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller + +pci:v00008086d000027DAsv00001025sd0000006C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (9814 WKMI) + +pci:v00008086d000027DAsv00001028sd000001AD* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (OptiPlex GX620) + +pci:v00008086d000027DAsv00001028sd000001D7* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (XPS M1210) + +pci:v00008086d000027DAsv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (PowerEdge SC440) + +pci:v00008086d000027DAsv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (PowerEdge 860) + +pci:v00008086d000027DAsv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Pavilion A1512X) + +pci:v00008086d000027DAsv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Compaq 500B Microtower) + +pci:v00008086d000027DAsv00001043sd00008179* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (P5B-MX/WiFi-AP, P5KPL-VM Motherboard) + +pci:v00008086d000027DAsv0000105Bsd00000D7C* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (D270S/D250S Motherboard) + +pci:v00008086d000027DAsv00001071sd00008209* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Medion MIM 2240 Notebook PC [MD98100]) + +pci:v00008086d000027DAsv000010F7sd00008338* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Panasonic CF-Y5 laptop) + +pci:v00008086d000027DAsv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Notebook N150P) + +pci:v00008086d000027DAsv00001458sd00005001* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (GA-8I945PG-RH/GA-D525TUD Mainboard) + +pci:v00008086d000027DAsv00001462sd00007418* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Wind PC MS-7418) + +pci:v00008086d000027DAsv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (CC11/CL11) + +pci:v00008086d000027DAsv000017AAsd0000200F* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027DAsv00008086sd00004F4D* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (DeskTop Board D510MO) + +pci:v00008086d000027DAsv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (Desktop Board D425KT) + +pci:v00008086d000027DAsv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (DeskTop Board D945GTP) + +pci:v00008086d000027DAsv00008086sd00005842* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family SMBus Controller (DeskTop Board D975XBX) + +pci:v00008086d000027DC* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family LAN Controller + +pci:v00008086d000027DCsv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family LAN Controller (Pavilion A1512X) + +pci:v00008086d000027DCsv00008086sd0000308D* + ID_MODEL_FROM_DATABASE=NM10/ICH7 Family LAN Controller (DeskTop Board D945GTP) + +pci:v00008086d000027DD* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) AC'97 Modem Controller + +pci:v00008086d000027DE* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) AC'97 Audio Controller + +pci:v00008086d000027DEsv00001028sd000001AD* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) AC'97 Audio Controller (OptiPlex GX620) + +pci:v00008086d000027DEsv00001462sd00007267* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) AC'97 Audio Controller (Realtek ALC883 Audio Controller) + +pci:v00008086d000027DEsv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) AC'97 Audio Controller (CC11 integrated audio (AD1981BL codec)) + +pci:v00008086d000027DF* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller + +pci:v00008086d000027DFsv00001028sd000001DF* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (PowerEdge SC440) + +pci:v00008086d000027DFsv00001028sd000001E6* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (PowerEdge 860) + +pci:v00008086d000027DFsv0000103Csd00002A3B* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Pavilion A1512X) + +pci:v00008086d000027DFsv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Compaq 500B Microtower) + +pci:v00008086d000027DFsv0000103Csd0000309F* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Compaq nx9420 Notebook) + +pci:v00008086d000027DFsv0000103Csd000030A1* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (NC2400) + +pci:v00008086d000027DFsv0000103Csd000030A3* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Compaq nw8440) + +pci:v00008086d000027DFsv0000103Csd000030D5* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (530 Laptop) + +pci:v00008086d000027DFsv00001043sd00001237* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (A6J-Q008) + +pci:v00008086d000027DFsv00001043sd00008179* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (P5B-MX/WiFi-AP, P5KPL-VM Motherboard) + +pci:v00008086d000027DFsv0000107Bsd00005048* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (E4500) + +pci:v00008086d000027DFsv000010F7sd00008338* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Panasonic CF-Y5 laptop) + +pci:v00008086d000027DFsv00001462sd00007418* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (Wind PC MS-7418) + +pci:v00008086d000027DFsv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (CC11/CL11) + +pci:v00008086d000027DFsv000017AAsd0000200C* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (ThinkPad R60/T60/X60 series) + +pci:v00008086d000027DFsv00008086sd0000544E* + ID_MODEL_FROM_DATABASE=82801G (ICH7 Family) IDE Controller (DeskTop Board D945GTP) + +pci:v00008086d000027E0* + ID_MODEL_FROM_DATABASE=82801GR/GH/GHM (ICH7 Family) PCI Express Port 5 + +pci:v00008086d000027E0sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=82801GR/GH/GHM (ICH7 Family) PCI Express Port 5 (CC11/CL11) + +pci:v00008086d000027E2* + ID_MODEL_FROM_DATABASE=82801GR/GH/GHM (ICH7 Family) PCI Express Port 6 + +pci:v00008086d000027E2sv00001775sd000011CC* + ID_MODEL_FROM_DATABASE=82801GR/GH/GHM (ICH7 Family) PCI Express Port 6 (CC11/CL11) + +pci:v00008086d0000280B* + ID_MODEL_FROM_DATABASE=Intel(R) Display Audio + +pci:v00008086d00002810* + ID_MODEL_FROM_DATABASE=82801HB/HR (ICH8/R) LPC Interface Controller + +pci:v00008086d00002810sv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801HB/HR (ICH8/R) LPC Interface Controller (P5B) + +pci:v00008086d00002811* + ID_MODEL_FROM_DATABASE=82801HEM (ICH8M-E) LPC Interface Controller + +pci:v00008086d00002811sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801HEM (ICH8M-E) LPC Interface Controller (Compaq 6910p) + +pci:v00008086d00002811sv000017AAsd000020B6* + ID_MODEL_FROM_DATABASE=82801HEM (ICH8M-E) LPC Interface Controller (ThinkPad T61/R61) + +pci:v00008086d00002811sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801HEM (ICH8M-E) LPC Interface Controller (CCG-RUMBA) + +pci:v00008086d00002812* + ID_MODEL_FROM_DATABASE=82801HH (ICH8DH) LPC Interface Controller + +pci:v00008086d00002814* + ID_MODEL_FROM_DATABASE=82801HO (ICH8DO) LPC Interface Controller + +pci:v00008086d00002815* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller + +pci:v00008086d00002815sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Aspire 5920G) + +pci:v00008086d00002815sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Inspiron 1420) + +pci:v00008086d00002815sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Inspiron 1525) + +pci:v00008086d00002815sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Compaq 6710b) + +pci:v00008086d00002815sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Pavilion dv6700) + +pci:v00008086d00002815sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Presario C700) + +pci:v00008086d00002815sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (X58LE) + +pci:v00008086d00002815sv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Vaio VGN-FZ260E) + +pci:v00008086d00002815sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (VAIO VGN-NR120E) + +pci:v00008086d00002815sv000017AAsd000020A5* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (ThinkPad R61) + +pci:v00008086d00002815sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801HM (ICH8M) LPC Interface Controller (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002820* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) 4 port SATA Controller [IDE mode] + +pci:v00008086d00002820sv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) 4 port SATA Controller [IDE mode] (OptiPlex 745) + +pci:v00008086d00002820sv00001462sd00007235* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) 4 port SATA Controller [IDE mode] (P965 Neo MS-7235 mainboard) + +pci:v00008086d00002821* + ID_MODEL_FROM_DATABASE=82801HR/HO/HH (ICH8R/DO/DH) 6 port SATA Controller [AHCI mode] + +pci:v00008086d00002822* + ID_MODEL_FROM_DATABASE=SATA Controller [RAID mode] + +pci:v00008086d00002822sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=SATA Controller [RAID mode] (Inspiron 530) + +pci:v00008086d00002822sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=SATA Controller [RAID mode] (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002822sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=SATA Controller [RAID mode] (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002822sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=SATA Controller [RAID mode] (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d00002823* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] + +pci:v00008086d00002824* + ID_MODEL_FROM_DATABASE=82801HB (ICH8) 4 port SATA Controller [AHCI mode] + +pci:v00008086d00002824sv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801HB (ICH8) 4 port SATA Controller [AHCI mode] (P5B) + +pci:v00008086d00002825* + ID_MODEL_FROM_DATABASE=82801HR/HO/HH (ICH8R/DO/DH) 2 port SATA Controller [IDE mode] + +pci:v00008086d00002825sv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801HR/HO/HH (ICH8R/DO/DH) 2 port SATA Controller [IDE mode] (OptiPlex 745) + +pci:v00008086d00002825sv00001462sd00007235* + ID_MODEL_FROM_DATABASE=82801HR/HO/HH (ICH8R/DO/DH) 2 port SATA Controller [IDE mode] (P965 Neo MS-7235 mainboard) + +pci:v00008086d00002826* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller + +pci:v00008086d00002826sv00001D49sd00000100* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (Intel RSTe SATA Software RAID) + +pci:v00008086d00002826sv00001D49sd00000101* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (Intel RSTe SATA Software RAID) + +pci:v00008086d00002826sv00001D49sd00000102* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (Intel RSTe SATA Software RAID) + +pci:v00008086d00002826sv00001D49sd00000103* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (Intel RSTe SATA Software RAID) + +pci:v00008086d00002826sv00001D49sd00000104* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (Intel RSTe SATA Software RAID) + +pci:v00008086d00002826sv00001D49sd00000105* + ID_MODEL_FROM_DATABASE=C600/X79 series chipset SATA RAID Controller (Intel RSTe SATA Software RAID) + +pci:v00008086d00002827* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] + +pci:v00008086d00002828* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] + +pci:v00008086d00002828sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] (Inspiron 1420) + +pci:v00008086d00002828sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] (Compaq 6710b) + +pci:v00008086d00002828sv000017AAsd000020A8* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] (ThinkPad R61) + +pci:v00008086d00002828sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] (CCG-RUMBA) + +pci:v00008086d00002829* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] + +pci:v00008086d00002829sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Aspire 5920G) + +pci:v00008086d00002829sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Inspiron 1525) + +pci:v00008086d00002829sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Compaq 6710b) + +pci:v00008086d00002829sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Compaq 6910p) + +pci:v00008086d00002829sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Pavilion dv6700) + +pci:v00008086d00002829sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Presario C700) + +pci:v00008086d00002829sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (X58LE) + +pci:v00008086d00002829sv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Vaio VGN-FZ260E) + +pci:v00008086d00002829sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (VAIO VGN-NR120E) + +pci:v00008086d00002829sv000017AAsd000020A7* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (ThinkPad T61/R61) + +pci:v00008086d00002829sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002829sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (CCG-RUMBA) + +pci:v00008086d0000282A* + ID_MODEL_FROM_DATABASE=82801 Mobile SATA Controller [RAID mode] + +pci:v00008086d0000282Asv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=82801 Mobile SATA Controller [RAID mode] (Latitude E6510) + +pci:v00008086d0000282Asv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=82801 Mobile SATA Controller [RAID mode] (PC1-GROOVE) + +pci:v00008086d00002830* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 + +pci:v00008086d00002830sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Aspire 5920G) + +pci:v00008086d00002830sv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (OptiPlex 745) + +pci:v00008086d00002830sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Inspiron 1420) + +pci:v00008086d00002830sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Inspiron 1525) + +pci:v00008086d00002830sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Compaq 6710b) + +pci:v00008086d00002830sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Compaq 6910p) + +pci:v00008086d00002830sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Pavilion dv6700) + +pci:v00008086d00002830sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Presario C700) + +pci:v00008086d00002830sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (X58LE) + +pci:v00008086d00002830sv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (P5B) + +pci:v00008086d00002830sv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Vaio VGN-FZ260E) + +pci:v00008086d00002830sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (VAIO VGN-NR120E) + +pci:v00008086d00002830sv00001462sd00007235* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (P965 Neo MS-7235 mainboard) + +pci:v00008086d00002830sv000017AAsd000020AA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (ThinkPad T61/R61) + +pci:v00008086d00002830sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002830sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #1 (CCG-RUMBA) + +pci:v00008086d00002831* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 + +pci:v00008086d00002831sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Aspire 5920G) + +pci:v00008086d00002831sv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (OptiPlex 745) + +pci:v00008086d00002831sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Inspiron 1420) + +pci:v00008086d00002831sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Inspiron 1525) + +pci:v00008086d00002831sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Compaq 6710b) + +pci:v00008086d00002831sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Compaq 6910p) + +pci:v00008086d00002831sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Pavilion dv6700) + +pci:v00008086d00002831sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Presario C700) + +pci:v00008086d00002831sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (X58LE) + +pci:v00008086d00002831sv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (P5B) + +pci:v00008086d00002831sv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Vaio VGN-FZ260E) + +pci:v00008086d00002831sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (VAIO VGN-NR120E) + +pci:v00008086d00002831sv00001462sd00007235* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (P965 Neo MS-7235 mainboard) + +pci:v00008086d00002831sv000017AAsd000020AA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (ThinkPad T61/R61) + +pci:v00008086d00002831sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002831sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #2 (CCG-RUMBA) + +pci:v00008086d00002832* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 + +pci:v00008086d00002832sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Aspire 5920G) + +pci:v00008086d00002832sv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (OptiPlex 745) + +pci:v00008086d00002832sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Inspiron 1420) + +pci:v00008086d00002832sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Inspiron 1525) + +pci:v00008086d00002832sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Compaq 6710b) + +pci:v00008086d00002832sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Compaq 6910p) + +pci:v00008086d00002832sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Pavilion dv6700) + +pci:v00008086d00002832sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Presario C700) + +pci:v00008086d00002832sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (X58LE) + +pci:v00008086d00002832sv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (P5B) + +pci:v00008086d00002832sv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Vaio VGN-FZ260E) + +pci:v00008086d00002832sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (VAIO VGN-NR120E) + +pci:v00008086d00002832sv000017AAsd000020AA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (ThinkPad T61/R61) + +pci:v00008086d00002832sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002832sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #3 (CCG-RUMBA) + +pci:v00008086d00002833* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 + +pci:v00008086d00002833sv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (P5B) + +pci:v00008086d00002834* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 + +pci:v00008086d00002834sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Aspire 5920G) + +pci:v00008086d00002834sv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (OptiPlex 745) + +pci:v00008086d00002834sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Inspiron 1420) + +pci:v00008086d00002834sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Inspiron 1525) + +pci:v00008086d00002834sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Compaq 6710b) + +pci:v00008086d00002834sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Compaq 6910p) + +pci:v00008086d00002834sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Pavilion dv6700) + +pci:v00008086d00002834sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (X58LE) + +pci:v00008086d00002834sv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (P5B) + +pci:v00008086d00002834sv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Vaio VGN-FZ260E) + +pci:v00008086d00002834sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (VAIO VGN-NR120E) + +pci:v00008086d00002834sv00001462sd00007235* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (P965 Neo MS-7235 mainboard) + +pci:v00008086d00002834sv000017AAsd000020AA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (ThinkPad T61/R61) + +pci:v00008086d00002834sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002834sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #4 (CCG-RUMBA) + +pci:v00008086d00002835* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 + +pci:v00008086d00002835sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Aspire 5920G) + +pci:v00008086d00002835sv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (OptiPlex 745) + +pci:v00008086d00002835sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Inspiron 1420) + +pci:v00008086d00002835sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Inspiron 1525) + +pci:v00008086d00002835sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Compaq 6710b) + +pci:v00008086d00002835sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Compaq 6910p) + +pci:v00008086d00002835sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Pavilion dv6700) + +pci:v00008086d00002835sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (X58LE) + +pci:v00008086d00002835sv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (P5B) + +pci:v00008086d00002835sv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Vaio VGN-FZ260E) + +pci:v00008086d00002835sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (VAIO VGN-NR120E) + +pci:v00008086d00002835sv000017AAsd000020AA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Thinkpad T61/R61) + +pci:v00008086d00002835sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002835sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB UHCI Controller #5 (CCG-RUMBA) + +pci:v00008086d00002836* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 + +pci:v00008086d00002836sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Aspire 5920G) + +pci:v00008086d00002836sv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (OptiPlex 745) + +pci:v00008086d00002836sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Inspiron 1420) + +pci:v00008086d00002836sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Inspiron 1525) + +pci:v00008086d00002836sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Compaq 6710b) + +pci:v00008086d00002836sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Compaq 6910p) + +pci:v00008086d00002836sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Pavilion dv6700) + +pci:v00008086d00002836sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Presario C700) + +pci:v00008086d00002836sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (X58LE) + +pci:v00008086d00002836sv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (P5B) + +pci:v00008086d00002836sv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Vaio VGN-FZ260E) + +pci:v00008086d00002836sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (VAIO VGN-NR120E) + +pci:v00008086d00002836sv00001462sd00007235* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (P965 Neo MS-7235 mainboard) + +pci:v00008086d00002836sv000017AAsd000020AB* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (ThinkPad T61/R61) + +pci:v00008086d00002836sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002836sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #1 (CCG-RUMBA) + +pci:v00008086d0000283A* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 + +pci:v00008086d0000283Asv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Aspire 5920G) + +pci:v00008086d0000283Asv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (OptiPlex 745) + +pci:v00008086d0000283Asv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Inspiron 1420) + +pci:v00008086d0000283Asv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Inspiron 1525) + +pci:v00008086d0000283Asv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Compaq 6710b) + +pci:v00008086d0000283Asv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Compaq 6910p) + +pci:v00008086d0000283Asv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Pavilion dv6700) + +pci:v00008086d0000283Asv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (X58LE) + +pci:v00008086d0000283Asv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (P5B) + +pci:v00008086d0000283Asv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Vaio VGN-FZ260E) + +pci:v00008086d0000283Asv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (VAIO VGN-NR120E) + +pci:v00008086d0000283Asv000017AAsd000020AB* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (ThinkPad T61/R61) + +pci:v00008086d0000283Asv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d0000283Asv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) USB2 EHCI Controller #2 (CCG-RUMBA) + +pci:v00008086d0000283E* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller + +pci:v00008086d0000283Esv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Aspire 5920G) + +pci:v00008086d0000283Esv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (OptiPlex 745) + +pci:v00008086d0000283Esv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Inspiron 1420) + +pci:v00008086d0000283Esv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Inspiron 1525) + +pci:v00008086d0000283Esv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Presario C700) + +pci:v00008086d0000283Esv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (X58LE) + +pci:v00008086d0000283Esv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (P5B) + +pci:v00008086d0000283Esv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Vaio VGN-FZ260E) + +pci:v00008086d0000283Esv0000104Dsd00009008* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Vaio VGN-SZ79SN_C) + +pci:v00008086d0000283Esv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (VAIO VGN-NR120E) + +pci:v00008086d0000283Esv00001462sd00007235* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (P965 Neo MS-7235 mainboard) + +pci:v00008086d0000283Esv000017AAsd000020A9* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (ThinkPad T61/R61) + +pci:v00008086d0000283Esv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d0000283Esv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) SMBus Controller (CCG-RUMBA) + +pci:v00008086d0000283F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 + +pci:v00008086d0000283Fsv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (OptiPlex 745) + +pci:v00008086d0000283Fsv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (Compaq 6910p) + +pci:v00008086d0000283Fsv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (X58LE) + +pci:v00008086d0000283Fsv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (VAIO VGN-NR120E) + +pci:v00008086d0000283Fsv000017AAsd000020AD* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (ThinkPad T61/R61) + +pci:v00008086d0000283Fsv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 1 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002841* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 + +pci:v00008086d00002841sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 (Compaq 6910p) + +pci:v00008086d00002841sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 (X58LE) + +pci:v00008086d00002841sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 (VAIO VGN-NR120E) + +pci:v00008086d00002841sv000017AAsd000020AD* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 (ThinkPad T61/R61) + +pci:v00008086d00002841sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 2 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002843* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 3 + +pci:v00008086d00002843sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 3 (X58LE) + +pci:v00008086d00002843sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 3 (VAIO VGN-NR120E) + +pci:v00008086d00002843sv000017AAsd000020AD* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 3 (ThinkPad T61/R61) + +pci:v00008086d00002843sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 3 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002845* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 4 + +pci:v00008086d00002845sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 4 (X58LE) + +pci:v00008086d00002845sv000017AAsd000020AD* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 4 (ThinkPad T61/R61) + +pci:v00008086d00002845sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 4 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002847* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5 + +pci:v00008086d00002847sv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5 (OptiPlex 745) + +pci:v00008086d00002847sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5 (Compaq 6910p) + +pci:v00008086d00002847sv000017AAsd000020AD* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5 (ThinkPad T61/R61) + +pci:v00008086d00002847sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 5 (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002849* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) PCI Express Port 6 + +pci:v00008086d0000284B* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller + +pci:v00008086d0000284Bsv00001025sd0000011F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Realtek ALC268 audio codec) + +pci:v00008086d0000284Bsv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Aspire 5920G) + +pci:v00008086d0000284Bsv00001025sd00000145* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Realtek ALC889 (Aspire 8920G w. Dolby Theater)) + +pci:v00008086d0000284Bsv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (OptiPlex 745) + +pci:v00008086d0000284Bsv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Inspiron 1420) + +pci:v00008086d0000284Bsv00001028sd000001F9* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Latitude D630) + +pci:v00008086d0000284Bsv00001028sd000001FF* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Precision M4300) + +pci:v00008086d0000284Bsv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Inspiron 1525) + +pci:v00008086d0000284Bsv00001028sd00000256* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Studio 1735) + +pci:v00008086d0000284Bsv0000103Csd00002802* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Compaq dc7700p) + +pci:v00008086d0000284Bsv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Compaq 6710b) + +pci:v00008086d0000284Bsv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Compaq 6910p) + +pci:v00008086d0000284Bsv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Pavilion dv6700) + +pci:v00008086d0000284Bsv00001043sd00001339* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (M51S series) + +pci:v00008086d0000284Bsv00001043sd000017F3* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (X58LE) + +pci:v00008086d0000284Bsv00001043sd000081EC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (P5B) + +pci:v00008086d0000284Bsv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Vaio VGN-FZ260E) + +pci:v00008086d0000284Bsv0000104Dsd00009008* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Vaio VGN-SZ79SN_C) + +pci:v00008086d0000284Bsv0000104Dsd00009016* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Sony VAIO VGN-AR51M) + +pci:v00008086d0000284Bsv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (VAIO VGN-NR120E) + +pci:v00008086d0000284Bsv000014F1sd00005051* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Presario C700) + +pci:v00008086d0000284Bsv000017AAsd000020AC* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (ThinkPad T61/R61) + +pci:v00008086d0000284Bsv000017C0sd00004088* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d0000284Bsv00008384sd00007616* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (Dell Vostro 1400) + +pci:v00008086d0000284Bsv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) HD Audio Controller (CCG-RUMBA) + +pci:v00008086d0000284F* + ID_MODEL_FROM_DATABASE=82801H (ICH8 Family) Thermal Reporting Device + +pci:v00008086d00002850* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller + +pci:v00008086d00002850sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Aspire 5920G) + +pci:v00008086d00002850sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Inspiron 1420) + +pci:v00008086d00002850sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Inspiron 1525) + +pci:v00008086d00002850sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Compaq 6710b) + +pci:v00008086d00002850sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Compaq 6910p) + +pci:v00008086d00002850sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Pavilion dv6700) + +pci:v00008086d00002850sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Presario C700) + +pci:v00008086d00002850sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (X58LE) + +pci:v00008086d00002850sv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Vaio VGN-FZ260E) + +pci:v00008086d00002850sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (VAIO VGN-NR120E) + +pci:v00008086d00002850sv000017AAsd000020A6* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (ThinkPad T61/R61) + +pci:v00008086d00002850sv000017C0sd00004083* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002850sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=82801HM/HEM (ICH8M/ICH8M-E) IDE Controller (CCG-RUMBA) + +pci:v00008086d000028C0* + ID_MODEL_FROM_DATABASE=Volume Management Device NVMe RAID Controller + +pci:v00008086d00002912* + ID_MODEL_FROM_DATABASE=82801IH (ICH9DH) LPC Interface Controller + +pci:v00008086d00002914* + ID_MODEL_FROM_DATABASE=82801IO (ICH9DO) LPC Interface Controller + +pci:v00008086d00002914sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801IO (ICH9DO) LPC Interface Controller (Optiplex 755) + +pci:v00008086d00002916* + ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller + +pci:v00008086d00002916sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller (Inspiron 530) + +pci:v00008086d00002916sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002916sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller (P5K PRO Motherboard) + +pci:v00008086d00002916sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller (MS-7345 Motherboard) + +pci:v00008086d00002916sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801IR (ICH9R) LPC Interface Controller (Desktop Board DP35DP) + +pci:v00008086d00002917* + ID_MODEL_FROM_DATABASE=ICH9M-E LPC Interface Controller + +pci:v00008086d00002917sv000017AAsd000020F5* + ID_MODEL_FROM_DATABASE=ICH9M-E LPC Interface Controller (ThinkPad T400) + +pci:v00008086d00002917sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=ICH9M-E LPC Interface Controller (CCM-BOOGIE) + +pci:v00008086d00002918* + ID_MODEL_FROM_DATABASE=82801IB (ICH9) LPC Interface Controller + +pci:v00008086d00002918sv00001028sd00000236* + ID_MODEL_FROM_DATABASE=82801IB (ICH9) LPC Interface Controller (PowerEdge R610 82801IB (ICH9) LPC Interface Controller) + +pci:v00008086d00002918sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801IB (ICH9) LPC Interface Controller (G33/P35 Neo) + +pci:v00008086d00002918sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801IB (ICH9) LPC Interface Controller (QEMU Virtual Machine) + +pci:v00008086d00002919* + ID_MODEL_FROM_DATABASE=ICH9M LPC Interface Controller + +pci:v00008086d00002920* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] + +pci:v00008086d00002920sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (Inspiron 530) + +pci:v00008086d00002920sv00001028sd0000020F* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (PowerEdge R300 onboard SATA Controller) + +pci:v00008086d00002920sv00001028sd00000210* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (PowerEdge T300 onboard SATA Controller) + +pci:v00008086d00002920sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (Optiplex 755) + +pci:v00008086d00002920sv00001028sd0000023C* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (PowerEdge R200 onboard SATA Controller) + +pci:v00008086d00002920sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002920sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] (MS-7345 Motherboard: Intel 82801IR [ICH9R]) + +pci:v00008086d00002921* + ID_MODEL_FROM_DATABASE=82801IB (ICH9) 2 port SATA Controller [IDE mode] + +pci:v00008086d00002921sv00001028sd00000235* + ID_MODEL_FROM_DATABASE=82801IB (ICH9) 2 port SATA Controller [IDE mode] (PowerEdge R710 SATA IDE Controller) + +pci:v00008086d00002921sv00001028sd00000236* + ID_MODEL_FROM_DATABASE=82801IB (ICH9) 2 port SATA Controller [IDE mode] (PowerEdge R610 SATA IDE Controller) + +pci:v00008086d00002921sv00001028sd00000237* + ID_MODEL_FROM_DATABASE=82801IB (ICH9) 2 port SATA Controller [IDE mode] (PowerEdge T610 SATA IDE Controller) + +pci:v00008086d00002921sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801IB (ICH9) 2 port SATA Controller [IDE mode] (G33/P35 Neo) + +pci:v00008086d00002922* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] + +pci:v00008086d00002922sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002922sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (MS-7345 Motherboard: Intel 82801IR [ICH9R]) + +pci:v00008086d00002922sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (QEMU Virtual Machine) + +pci:v00008086d00002922sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] (Desktop Board DP35DP) + +pci:v00008086d00002923* + ID_MODEL_FROM_DATABASE=82801IB (ICH9) 4 port SATA Controller [AHCI mode] + +pci:v00008086d00002925* + ID_MODEL_FROM_DATABASE=82801IR/IO (ICH9R/DO) SATA Controller [RAID mode] + +pci:v00008086d00002925sv00001734sd000010E0* + ID_MODEL_FROM_DATABASE=82801IR/IO (ICH9R/DO) SATA Controller [RAID mode] (System Board D2542) + +pci:v00008086d00002925sv00008086sd00002925* + ID_MODEL_FROM_DATABASE=82801IR/IO (ICH9R/DO) SATA Controller [RAID mode] (System Board D2542) + +pci:v00008086d00002926* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] + +pci:v00008086d00002926sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (Inspiron 530) + +pci:v00008086d00002926sv00001028sd0000020F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (PowerEdge R300 onboard SATA Controller) + +pci:v00008086d00002926sv00001028sd00000210* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (PowerEdge T300 onboard SATA Controller) + +pci:v00008086d00002926sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (Optiplex 755) + +pci:v00008086d00002926sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002926sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (MS-7345 Motherboard: Intel 82801IR [ICH9R]) + +pci:v00008086d00002926sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) 2 port SATA Controller [IDE mode] (G33/P35 Neo) + +pci:v00008086d00002928* + ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 2 port SATA Controller [IDE mode] + +pci:v00008086d00002929* + ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 4 port SATA Controller [AHCI mode] + +pci:v00008086d00002929sv0000103Csd00003628* + ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 4 port SATA Controller [AHCI mode] (dv6-1190en) + +pci:v00008086d00002929sv000017AAsd000020F8* + ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 4 port SATA Controller [AHCI mode] (ThinkPad T400) + +pci:v00008086d00002929sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 4 port SATA Controller [AHCI mode] (CCM-BOOGIE) + +pci:v00008086d0000292C* + ID_MODEL_FROM_DATABASE=82801IEM (ICH9M-E) SATA Controller [RAID mode] + +pci:v00008086d0000292D* + ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 2 port SATA Controller [IDE mode] + +pci:v00008086d0000292Dsv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801IBM/IEM (ICH9M/ICH9M-E) 2 port SATA Controller [IDE mode] (CCM-BOOGIE) + +pci:v00008086d00002930* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller + +pci:v00008086d00002930sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (Inspiron 530) + +pci:v00008086d00002930sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (Optiplex 755) + +pci:v00008086d00002930sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002930sv0000103Csd00003628* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (dv6-1190en) + +pci:v00008086d00002930sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002930sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d00002930sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (G33/P35 Neo) + +pci:v00008086d00002930sv000017AAsd000020F9* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (ThinkPad T400) + +pci:v00008086d00002930sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (QEMU Virtual Machine) + +pci:v00008086d00002930sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (Desktop Board DP35DP) + +pci:v00008086d00002930sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) SMBus Controller (CCM-BOOGIE) + +pci:v00008086d00002932* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) Thermal Subsystem + +pci:v00008086d00002932sv0000103Csd00003628* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) Thermal Subsystem (dv6-1190en) + +pci:v00008086d00002934* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 + +pci:v00008086d00002934sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (Inspiron 530) + +pci:v00008086d00002934sv00001028sd0000020F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge R300 onboard UHCI) + +pci:v00008086d00002934sv00001028sd00000210* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge T300 onboard UHCI) + +pci:v00008086d00002934sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (Optiplex 755) + +pci:v00008086d00002934sv00001028sd00000235* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge R710 USB UHCI Controller) + +pci:v00008086d00002934sv00001028sd00000236* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge R610 USB UHCI Controller) + +pci:v00008086d00002934sv00001028sd00000237* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge T610 USB UHCI Controller) + +pci:v00008086d00002934sv00001028sd0000023C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge R200 onboard UHCI) + +pci:v00008086d00002934sv00001028sd00000287* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge M610 onboard UHCI) + +pci:v00008086d00002934sv00001028sd0000029C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (PowerEdge M710 USB UHCI Controller) + +pci:v00008086d00002934sv00001028sd00002011* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (Optiplex 755) + +pci:v00008086d00002934sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002934sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002934sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d00002934sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (G33/P35 Neo) + +pci:v00008086d00002934sv000017AAsd000020F0* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (ThinkPad T400) + +pci:v00008086d00002934sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (QEMU Virtual Machine) + +pci:v00008086d00002934sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (Desktop Board DP35DP) + +pci:v00008086d00002934sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #1 (CCM-BOOGIE) + +pci:v00008086d00002935* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 + +pci:v00008086d00002935sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (Inspiron 530) + +pci:v00008086d00002935sv00001028sd0000020F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge R300 onboard UHCI) + +pci:v00008086d00002935sv00001028sd00000210* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge T300 onboard UHCI) + +pci:v00008086d00002935sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (Optiplex 755) + +pci:v00008086d00002935sv00001028sd00000235* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge R710 USB UHCI Controller) + +pci:v00008086d00002935sv00001028sd00000236* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge R610 USB UHCI Controller) + +pci:v00008086d00002935sv00001028sd00000237* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge T610 USB UHCI Controller) + +pci:v00008086d00002935sv00001028sd0000023C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge R200 onboard UHCI) + +pci:v00008086d00002935sv00001028sd00000287* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge M610 onboard UHCI) + +pci:v00008086d00002935sv00001028sd0000029C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (PowerEdge M710 USB UHCI Controller) + +pci:v00008086d00002935sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002935sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002935sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d00002935sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (G33/P35 Neo) + +pci:v00008086d00002935sv000017AAsd000020F0* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (ThinkPad T400) + +pci:v00008086d00002935sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (QEMU Virtual Machine) + +pci:v00008086d00002935sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (Desktop Board DP35DP) + +pci:v00008086d00002935sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #2 (CCM-BOOGIE) + +pci:v00008086d00002936* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 + +pci:v00008086d00002936sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (Inspiron 530) + +pci:v00008086d00002936sv00001028sd0000020F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge R300 onboard UHCI) + +pci:v00008086d00002936sv00001028sd00000210* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge T300 onboard UHCI) + +pci:v00008086d00002936sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (Optiplex 755) + +pci:v00008086d00002936sv00001028sd00000237* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge T610 USB UHCI Controller) + +pci:v00008086d00002936sv00001028sd0000023C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge R200 onboard UHCI) + +pci:v00008086d00002936sv00001028sd00000287* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge M610 onboard UHCI) + +pci:v00008086d00002936sv00001028sd0000029C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (PowerEdge M710 USB UHCI Controller) + +pci:v00008086d00002936sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002936sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002936sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d00002936sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (G33/P35 Neo) + +pci:v00008086d00002936sv000017AAsd000020F0* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (ThinkPad T400) + +pci:v00008086d00002936sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (QEMU Virtual Machine) + +pci:v00008086d00002936sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (Desktop Board DP35DP) + +pci:v00008086d00002936sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #3 (CCM-BOOGIE) + +pci:v00008086d00002937* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 + +pci:v00008086d00002937sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Inspiron 530) + +pci:v00008086d00002937sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Optiplex 755) + +pci:v00008086d00002937sv00001028sd00000235* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (PowerEdge R710 USB UHCI Controller) + +pci:v00008086d00002937sv00001028sd00000236* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (PowerEdge R610 USB UHCI Controller) + +pci:v00008086d00002937sv00001028sd00000237* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (PowerEdge T610 USB UHCI Controller) + +pci:v00008086d00002937sv00001028sd00000287* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (PowerEdge M610 onboard UHCI) + +pci:v00008086d00002937sv00001028sd0000029C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (PowerEdge M710 USB UHCI Controller) + +pci:v00008086d00002937sv00001028sd00002011* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Optiplex 755) + +pci:v00008086d00002937sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002937sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002937sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d00002937sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (G33/P35 Neo) + +pci:v00008086d00002937sv000017AAsd000020F0* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (ThinkPad T400) + +pci:v00008086d00002937sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (QEMU Virtual Machine) + +pci:v00008086d00002937sv00008086sd00002937* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Optiplex 755) + +pci:v00008086d00002937sv00008086sd00002942* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (828011 (ICH9 Family ) USB UHCI Controller) + +pci:v00008086d00002937sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (Desktop Board DP35DP) + +pci:v00008086d00002937sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #4 (CCM-BOOGIE) + +pci:v00008086d00002938* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 + +pci:v00008086d00002938sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (Inspiron 530) + +pci:v00008086d00002938sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (Optiplex 755) + +pci:v00008086d00002938sv00001028sd00000235* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (PowerEdge R710 USB UHCI Controller) + +pci:v00008086d00002938sv00001028sd00000236* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (PowerEdge R610 USB UHCI Controller) + +pci:v00008086d00002938sv00001028sd00000237* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (PowerEdge T610 USB UHCI Controller) + +pci:v00008086d00002938sv00001028sd00000287* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (PowerEdge M610 onboard UHCI) + +pci:v00008086d00002938sv00001028sd0000029C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (PowerEdge M710 USB UHCI Controller) + +pci:v00008086d00002938sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002938sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002938sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d00002938sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (G33/P35 Neo) + +pci:v00008086d00002938sv000017AAsd000020F0* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (ThinkPad T400) + +pci:v00008086d00002938sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (QEMU Virtual Machine) + +pci:v00008086d00002938sv00008086sd00002938* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (Optiplex 755) + +pci:v00008086d00002938sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (Desktop Board DP35DP) + +pci:v00008086d00002938sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #5 (CCM-BOOGIE) + +pci:v00008086d00002939* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 + +pci:v00008086d00002939sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (Inspiron 530) + +pci:v00008086d00002939sv00001028sd00000210* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (PowerEdge T300 onboard UHCI) + +pci:v00008086d00002939sv00001028sd00000237* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (PowerEdge T610 USB UHCI Controller) + +pci:v00008086d00002939sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002939sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002939sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d00002939sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (G33/P35 Neo) + +pci:v00008086d00002939sv000017AAsd000020F0* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (ThinkPad T400) + +pci:v00008086d00002939sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (QEMU Virtual Machine) + +pci:v00008086d00002939sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (Desktop Board DP35DP) + +pci:v00008086d00002939sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB UHCI Controller #6 (CCM-BOOGIE) + +pci:v00008086d0000293A* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 + +pci:v00008086d0000293Asv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (Inspiron 530) + +pci:v00008086d0000293Asv00001028sd0000020F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge R300 onboard EHCI) + +pci:v00008086d0000293Asv00001028sd00000210* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge T300 onboard EHCI) + +pci:v00008086d0000293Asv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (Optiplex 755) + +pci:v00008086d0000293Asv00001028sd00000235* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge R710 USB EHCI Controller) + +pci:v00008086d0000293Asv00001028sd00000236* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge R610 USB EHCI Controller) + +pci:v00008086d0000293Asv00001028sd00000237* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge T610 USB EHCI Controller) + +pci:v00008086d0000293Asv00001028sd0000023C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge R200 onboard EHCI) + +pci:v00008086d0000293Asv00001028sd00000287* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge M610 onboard EHCI) + +pci:v00008086d0000293Asv00001028sd0000029C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (PowerEdge M710 USB EHCI Controller) + +pci:v00008086d0000293Asv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (Asus IPIBL-LB Motherboard) + +pci:v00008086d0000293Asv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d0000293Asv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d0000293Asv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (G33/P35 Neo) + +pci:v00008086d0000293Asv000017AAsd000020F1* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (ThinkPad T400) + +pci:v00008086d0000293Asv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (QEMU Virtual Machine) + +pci:v00008086d0000293Asv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (Desktop Board DP35DP) + +pci:v00008086d0000293Asv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #1 (CCM-BOOGIE) + +pci:v00008086d0000293C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 + +pci:v00008086d0000293Csv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (Inspiron 530) + +pci:v00008086d0000293Csv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (Optiplex 755) + +pci:v00008086d0000293Csv00001028sd00000235* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (PowerEdge R710 USB EHCI Controller) + +pci:v00008086d0000293Csv00001028sd00000236* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (PowerEdge R610 USB EHCI Controller) + +pci:v00008086d0000293Csv00001028sd00000237* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (PowerEdge T610 USB EHCI Controller) + +pci:v00008086d0000293Csv00001028sd00000287* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (PowerEdge M610 onboard EHCI) + +pci:v00008086d0000293Csv00001028sd0000029C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (PowerEdge M710 USB EHCI Controller) + +pci:v00008086d0000293Csv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (Asus IPIBL-LB Motherboard) + +pci:v00008086d0000293Csv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d0000293Csv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d0000293Csv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (G33/P35 Neo) + +pci:v00008086d0000293Csv000017AAsd000020F1* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (ThinkPad T400) + +pci:v00008086d0000293Csv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (QEMU Virtual Machine) + +pci:v00008086d0000293Csv00008086sd0000293C* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (Optiplex 755) + +pci:v00008086d0000293Csv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (Desktop Board DP35DP) + +pci:v00008086d0000293Csv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) USB2 EHCI Controller #2 (CCM-BOOGIE) + +pci:v00008086d0000293E* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller + +pci:v00008086d0000293Esv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (Inspiron 530) + +pci:v00008086d0000293Esv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (Optiplex 755) + +pci:v00008086d0000293Esv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (Asus IPIBL-LB Motherboard) + +pci:v00008086d0000293Esv0000103Csd00003628* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (dv6-1190en) + +pci:v00008086d0000293Esv00001043sd0000829F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d0000293Esv00001462sd0000735A* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d0000293Esv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (G33/P35 Neo) + +pci:v00008086d0000293Esv000017AAsd000020F2* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (ThinkPad T400) + +pci:v00008086d0000293Esv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (QEMU Virtual Machine) + +pci:v00008086d0000293Esv00008086sd0000293E* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (Optiplex 755) + +pci:v00008086d0000293Esv00008086sd00002940* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (Optiplex 755) + +pci:v00008086d0000293Esv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) HD Audio Controller (CCM-BOOGIE) + +pci:v00008086d00002940* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 + +pci:v00008086d00002940sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (Inspiron 530) + +pci:v00008086d00002940sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (Optiplex 755) + +pci:v00008086d00002940sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002940sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002940sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d00002940sv00008086sd00002940* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 1 (Optiplex 755) + +pci:v00008086d00002942* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 2 + +pci:v00008086d00002942sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 2 (Inspiron 530) + +pci:v00008086d00002944* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 3 + +pci:v00008086d00002944sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 3 (Inspiron 530) + +pci:v00008086d00002944sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 3 (Asus IPIBL-LB Motherboard) + +pci:v00008086d00002946* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 4 + +pci:v00008086d00002946sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 4 (Inspiron 530) + +pci:v00008086d00002948* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 5 + +pci:v00008086d00002948sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 5 (Inspiron 530) + +pci:v00008086d00002948sv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 5 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d00002948sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 5 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d0000294A* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 6 + +pci:v00008086d0000294Asv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 6 (Inspiron 530) + +pci:v00008086d0000294Asv00001043sd00008277* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 6 (P5K PRO Motherboard: 82801IR [ICH9R]) + +pci:v00008086d0000294Asv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82801I (ICH9 Family) PCI Express Port 6 (MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R]) + +pci:v00008086d0000294C* + ID_MODEL_FROM_DATABASE=82566DC-2 Gigabit Network Connection + +pci:v00008086d0000294Csv000017AAsd0000302E* + ID_MODEL_FROM_DATABASE=82566DC-2 Gigabit Network Connection (82566DM-2 Gigabit Network Connection) + +pci:v00008086d00002970* + ID_MODEL_FROM_DATABASE=82946GZ/PL/GL Memory Controller Hub + +pci:v00008086d00002970sv00001043sd0000823B* + ID_MODEL_FROM_DATABASE=82946GZ/PL/GL Memory Controller Hub (P5B-MX/WiFi-AP) + +pci:v00008086d00002971* + ID_MODEL_FROM_DATABASE=82946GZ/PL/GL PCI Express Root Port + +pci:v00008086d00002972* + ID_MODEL_FROM_DATABASE=82946GZ/GL Integrated Graphics Controller + +pci:v00008086d00002972sv00001043sd0000823B* + ID_MODEL_FROM_DATABASE=82946GZ/GL Integrated Graphics Controller (P5B-MX/WiFi-AP) + +pci:v00008086d00002973* + ID_MODEL_FROM_DATABASE=82946GZ/GL Integrated Graphics Controller + +pci:v00008086d00002974* + ID_MODEL_FROM_DATABASE=82946GZ/GL HECI Controller + +pci:v00008086d00002975* + ID_MODEL_FROM_DATABASE=82946GZ/GL HECI Controller + +pci:v00008086d00002976* + ID_MODEL_FROM_DATABASE=82946GZ/GL PT IDER Controller + +pci:v00008086d00002977* + ID_MODEL_FROM_DATABASE=82946GZ/GL KT Controller + +pci:v00008086d00002980* + ID_MODEL_FROM_DATABASE=82G35 Express DRAM Controller + +pci:v00008086d00002981* + ID_MODEL_FROM_DATABASE=82G35 Express PCI Express Root Port + +pci:v00008086d00002982* + ID_MODEL_FROM_DATABASE=82G35 Express Integrated Graphics Controller + +pci:v00008086d00002983* + ID_MODEL_FROM_DATABASE=82G35 Express Integrated Graphics Controller + +pci:v00008086d00002984* + ID_MODEL_FROM_DATABASE=82G35 Express HECI Controller + +pci:v00008086d00002990* + ID_MODEL_FROM_DATABASE=82Q963/Q965 Memory Controller Hub + +pci:v00008086d00002990sv00001028sd000001DA* + ID_MODEL_FROM_DATABASE=82Q963/Q965 Memory Controller Hub (OptiPlex 745) + +pci:v00008086d00002991* + ID_MODEL_FROM_DATABASE=82Q963/Q965 PCI Express Root Port + +pci:v00008086d00002992* + ID_MODEL_FROM_DATABASE=82Q963/Q965 Integrated Graphics Controller + +pci:v00008086d00002993* + ID_MODEL_FROM_DATABASE=82Q963/Q965 Integrated Graphics Controller + +pci:v00008086d00002994* + ID_MODEL_FROM_DATABASE=82Q963/Q965 HECI Controller + +pci:v00008086d00002995* + ID_MODEL_FROM_DATABASE=82Q963/Q965 HECI Controller + +pci:v00008086d00002996* + ID_MODEL_FROM_DATABASE=82Q963/Q965 PT IDER Controller + +pci:v00008086d00002997* + ID_MODEL_FROM_DATABASE=82Q963/Q965 KT Controller + +pci:v00008086d000029A0* + ID_MODEL_FROM_DATABASE=82P965/G965 Memory Controller Hub + +pci:v00008086d000029A0sv00001043sd000081EA* + ID_MODEL_FROM_DATABASE=82P965/G965 Memory Controller Hub (P5B) + +pci:v00008086d000029A0sv00001462sd00007276* + ID_MODEL_FROM_DATABASE=82P965/G965 Memory Controller Hub (MS-7276 [G965MDH]) + +pci:v00008086d000029A1* + ID_MODEL_FROM_DATABASE=82P965/G965 PCI Express Root Port + +pci:v00008086d000029A2* + ID_MODEL_FROM_DATABASE=82G965 Integrated Graphics Controller + +pci:v00008086d000029A2sv00001462sd00007276* + ID_MODEL_FROM_DATABASE=82G965 Integrated Graphics Controller (MS-7276 [G965MDH]) + +pci:v00008086d000029A3* + ID_MODEL_FROM_DATABASE=82G965 Integrated Graphics Controller + +pci:v00008086d000029A4* + ID_MODEL_FROM_DATABASE=82P965/G965 HECI Controller + +pci:v00008086d000029A5* + ID_MODEL_FROM_DATABASE=82P965/G965 HECI Controller + +pci:v00008086d000029A6* + ID_MODEL_FROM_DATABASE=82P965/G965 PT IDER Controller + +pci:v00008086d000029A7* + ID_MODEL_FROM_DATABASE=82P965/G965 KT Controller + +pci:v00008086d000029B0* + ID_MODEL_FROM_DATABASE=82Q35 Express DRAM Controller + +pci:v00008086d000029B0sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82Q35 Express DRAM Controller (OptiPlex 755) + +pci:v00008086d000029B1* + ID_MODEL_FROM_DATABASE=82Q35 Express PCI Express Root Port + +pci:v00008086d000029B1sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82Q35 Express PCI Express Root Port (OptiPlex 755) + +pci:v00008086d000029B2* + ID_MODEL_FROM_DATABASE=82Q35 Express Integrated Graphics Controller + +pci:v00008086d000029B2sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82Q35 Express Integrated Graphics Controller (OptiPlex 755) + +pci:v00008086d000029B3* + ID_MODEL_FROM_DATABASE=82Q35 Express Integrated Graphics Controller + +pci:v00008086d000029B3sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82Q35 Express Integrated Graphics Controller (OptiPlex 755) + +pci:v00008086d000029B4* + ID_MODEL_FROM_DATABASE=82Q35 Express MEI Controller + +pci:v00008086d000029B4sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82Q35 Express MEI Controller (OptiPlex 755) + +pci:v00008086d000029B5* + ID_MODEL_FROM_DATABASE=82Q35 Express MEI Controller + +pci:v00008086d000029B6* + ID_MODEL_FROM_DATABASE=82Q35 Express PT IDER Controller + +pci:v00008086d000029B6sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82Q35 Express PT IDER Controller (OptiPlex 755) + +pci:v00008086d000029B7* + ID_MODEL_FROM_DATABASE=82Q35 Express Serial KT Controller + +pci:v00008086d000029B7sv00001028sd00000211* + ID_MODEL_FROM_DATABASE=82Q35 Express Serial KT Controller (OptiPlex 755) + +pci:v00008086d000029C0* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller + +pci:v00008086d000029C0sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (Inspiron 530) + +pci:v00008086d000029C0sv0000103Csd00002A6F* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (Asus IPIBL-LB Motherboard) + +pci:v00008086d000029C0sv00001043sd00008276* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (P5K PRO Motherboard: Intel 82P35 Northbridge) + +pci:v00008086d000029C0sv00001043sd000082B0* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (P5KPL-VM Motherboard) + +pci:v00008086d000029C0sv00001462sd00007345* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (MS-7345 Motherboard: Intel 82G33/P35 Northbridge) + +pci:v00008086d000029C0sv00001462sd00007360* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (G33/P35 Neo) + +pci:v00008086d000029C0sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (QEMU Virtual Machine) + +pci:v00008086d000029C0sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express DRAM Controller (Desktop Board DP35DP) + +pci:v00008086d000029C1* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express PCI Express Root Port + +pci:v00008086d000029C1sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express PCI Express Root Port (Inspiron 530) + +pci:v00008086d000029C1sv00001043sd00008276* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express PCI Express Root Port (P5K PRO Motherboard: Intel 82P35 Northbridge) + +pci:v00008086d000029C2* + ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller + +pci:v00008086d000029C2sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller (Inspiron 530) + +pci:v00008086d000029C2sv00001043sd000082B0* + ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller (P5KPL-VM Motherboard) + +pci:v00008086d000029C3* + ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller + +pci:v00008086d000029C3sv00001028sd0000020D* + ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller (Inspiron 530) + +pci:v00008086d000029C3sv00001043sd000082B0* + ID_MODEL_FROM_DATABASE=82G33/G31 Express Integrated Graphics Controller (P5KPL-VM Motherboard) + +pci:v00008086d000029C4* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express MEI Controller + +pci:v00008086d000029C4sv00008086sd00005044* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express MEI Controller (Desktop Board DP35DP) + +pci:v00008086d000029C5* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express MEI Controller + +pci:v00008086d000029C6* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express PT IDER Controller + +pci:v00008086d000029C7* + ID_MODEL_FROM_DATABASE=82G33/G31/P35/P31 Express Serial KT Controller + +pci:v00008086d000029CF* + ID_MODEL_FROM_DATABASE=Virtual HECI Controller + +pci:v00008086d000029D0* + ID_MODEL_FROM_DATABASE=82Q33 Express DRAM Controller + +pci:v00008086d000029D1* + ID_MODEL_FROM_DATABASE=82Q33 Express PCI Express Root Port + +pci:v00008086d000029D2* + ID_MODEL_FROM_DATABASE=82Q33 Express Integrated Graphics Controller + +pci:v00008086d000029D3* + ID_MODEL_FROM_DATABASE=82Q33 Express Integrated Graphics Controller + +pci:v00008086d000029D4* + ID_MODEL_FROM_DATABASE=82Q33 Express MEI Controller + +pci:v00008086d000029D5* + ID_MODEL_FROM_DATABASE=82Q33 Express MEI Controller + +pci:v00008086d000029D6* + ID_MODEL_FROM_DATABASE=82Q33 Express PT IDER Controller + +pci:v00008086d000029D7* + ID_MODEL_FROM_DATABASE=82Q33 Express Serial KT Controller + +pci:v00008086d000029E0* + ID_MODEL_FROM_DATABASE=82X38/X48 Express DRAM Controller + +pci:v00008086d000029E1* + ID_MODEL_FROM_DATABASE=82X38/X48 Express Host-Primary PCI Express Bridge + +pci:v00008086d000029E4* + ID_MODEL_FROM_DATABASE=82X38/X48 Express MEI Controller + +pci:v00008086d000029E5* + ID_MODEL_FROM_DATABASE=82X38/X48 Express MEI Controller + +pci:v00008086d000029E6* + ID_MODEL_FROM_DATABASE=82X38/X48 Express PT IDER Controller + +pci:v00008086d000029E7* + ID_MODEL_FROM_DATABASE=82X38/X48 Express Serial KT Controller + +pci:v00008086d000029E9* + ID_MODEL_FROM_DATABASE=82X38/X48 Express Host-Secondary PCI Express Bridge + +pci:v00008086d000029F0* + ID_MODEL_FROM_DATABASE=3200/3210 Chipset DRAM Controller + +pci:v00008086d000029F1* + ID_MODEL_FROM_DATABASE=3200/3210 Chipset Host-Primary PCI Express Bridge + +pci:v00008086d000029F4* + ID_MODEL_FROM_DATABASE=3200/3210 Chipset MEI Controller + +pci:v00008086d000029F5* + ID_MODEL_FROM_DATABASE=3200/3210 Chipset MEI Controller + +pci:v00008086d000029F6* + ID_MODEL_FROM_DATABASE=3200/3210 Chipset PT IDER Controller + +pci:v00008086d000029F7* + ID_MODEL_FROM_DATABASE=3200/3210 Chipset Serial KT Controller + +pci:v00008086d000029F9* + ID_MODEL_FROM_DATABASE=3210 Chipset Host-Secondary PCI Express Bridge + +pci:v00008086d00002A00* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub + +pci:v00008086d00002A00sv00001025sd00000121* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Aspire 5920G) + +pci:v00008086d00002A00sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Inspiron 1420) + +pci:v00008086d00002A00sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Inspiron 1525) + +pci:v00008086d00002A00sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Compaq 6710b) + +pci:v00008086d00002A00sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Compaq 6910p) + +pci:v00008086d00002A00sv0000103Csd000030CC* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Pavilion dv6700) + +pci:v00008086d00002A00sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Presario C700) + +pci:v00008086d00002A00sv00001043sd00001017* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (X58LE) + +pci:v00008086d00002A00sv0000104Dsd00009005* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Vaio VGN-FZ260E) + +pci:v00008086d00002A00sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (VAIO VGN-NR120E) + +pci:v00008086d00002A00sv000017AAsd000020B1* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (ThinkPad T61) + +pci:v00008086d00002A00sv000017AAsd000020B3* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (ThinkPad T61/R61) + +pci:v00008086d00002A00sv000017C0sd00004082* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002A00sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 Memory Controller Hub (CCG-RUMBA) + +pci:v00008086d00002A01* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965/GL960 PCI Express Root Port + +pci:v00008086d00002A02* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) + +pci:v00008086d00002A02sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Inspiron 1420) + +pci:v00008086d00002A02sv00001028sd000001F9* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Latitude D630) + +pci:v00008086d00002A02sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Inspiron 1525) + +pci:v00008086d00002A02sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Compaq 6710b) + +pci:v00008086d00002A02sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (Presario C700) + +pci:v00008086d00002A02sv00001043sd000014E2* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (X58LE) + +pci:v00008086d00002A02sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (VAIO VGN-NR120E) + +pci:v00008086d00002A02sv000017AAsd000020B5* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (GM965 [X3100] on ThinkPad T61/R61) + +pci:v00008086d00002A02sv000017C0sd00004082* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (GM965 on Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002A02sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (primary) (CCG-RUMBA) + +pci:v00008086d00002A03* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) + +pci:v00008086d00002A03sv00001028sd000001F3* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (Inspiron 1420) + +pci:v00008086d00002A03sv00001028sd0000022F* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (Inspiron 1525) + +pci:v00008086d00002A03sv0000103Csd000030C0* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (Compaq 6710b) + +pci:v00008086d00002A03sv0000103Csd000030D9* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (Presario C700) + +pci:v00008086d00002A03sv00001043sd000014E2* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (X58LE) + +pci:v00008086d00002A03sv0000104Dsd0000902D* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (VAIO VGN-NR120E) + +pci:v00008086d00002A03sv000017AAsd000020B5* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (GM965 [X3100] on ThinkPad T61/R61) + +pci:v00008086d00002A03sv000017C0sd00004082* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (GM965 on Medion WIM 2210 Notebook PC [MD96850]) + +pci:v00008086d00002A03sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=Mobile GM965/GL960 Integrated Graphics Controller (secondary) (CCG-RUMBA) + +pci:v00008086d00002A04* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 MEI Controller + +pci:v00008086d00002A04sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 MEI Controller (Compaq 6910p) + +pci:v00008086d00002A05* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 MEI Controller + +pci:v00008086d00002A06* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 PT IDER Controller + +pci:v00008086d00002A06sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 PT IDER Controller (Compaq 6910p) + +pci:v00008086d00002A07* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 KT Controller + +pci:v00008086d00002A07sv0000103Csd000030C1* + ID_MODEL_FROM_DATABASE=Mobile PM965/GM965 KT Controller (Compaq 6910p) + +pci:v00008086d00002A10* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Memory Controller Hub + +pci:v00008086d00002A10sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Memory Controller Hub (CCG-RUMBA) + +pci:v00008086d00002A11* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 PCI Express Root Port + +pci:v00008086d00002A12* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Integrated Graphics Controller + +pci:v00008086d00002A12sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Integrated Graphics Controller (CCG-RUMBA) + +pci:v00008086d00002A13* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Integrated Graphics Controller + +pci:v00008086d00002A13sv0000E4BFsd0000CC47* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 Integrated Graphics Controller (CCG-RUMBA) + +pci:v00008086d00002A14* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 MEI Controller + +pci:v00008086d00002A15* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 MEI Controller + +pci:v00008086d00002A16* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 PT IDER Controller + +pci:v00008086d00002A17* + ID_MODEL_FROM_DATABASE=Mobile GME965/GLE960 KT Controller + +pci:v00008086d00002A40* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Memory Controller Hub + +pci:v00008086d00002A40sv000017AAsd000020E0* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Memory Controller Hub (ThinkPad T400) + +pci:v00008086d00002A40sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Memory Controller Hub (CCM-BOOGIE) + +pci:v00008086d00002A41* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset PCI Express Graphics Port + +pci:v00008086d00002A41sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset PCI Express Graphics Port (CCM-BOOGIE) + +pci:v00008086d00002A42* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002A42sv000017AAsd00002112* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller (ThinkPad T400) + +pci:v00008086d00002A42sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller (CCM-BOOGIE) + +pci:v00008086d00002A43* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002A43sv000017AAsd00002112* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller (ThinkPad T400) + +pci:v00008086d00002A43sv0000E4BFsd0000CC4D* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset Integrated Graphics Controller (CCM-BOOGIE) + +pci:v00008086d00002A44* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset MEI Controller + +pci:v00008086d00002A44sv000017AAsd000020E6* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset MEI Controller (ThinkPad T400) + +pci:v00008086d00002A45* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset MEI Controller + +pci:v00008086d00002A46* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset PT IDER Controller + +pci:v00008086d00002A47* + ID_MODEL_FROM_DATABASE=Mobile 4 Series Chipset AMT SOL Redirection + +pci:v00008086d00002A50* + ID_MODEL_FROM_DATABASE=Cantiga MEI Controller + +pci:v00008086d00002A51* + ID_MODEL_FROM_DATABASE=Cantiga MEI Controller + +pci:v00008086d00002A52* + ID_MODEL_FROM_DATABASE=Cantiga PT IDER Controller + +pci:v00008086d00002A53* + ID_MODEL_FROM_DATABASE=Cantiga AMT SOL Redirection + +pci:v00008086d00002B00* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family System Configuration Controller 1 + +pci:v00008086d00002B02* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family System Configuration Controller 2 + +pci:v00008086d00002B04* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Power Controller + +pci:v00008086d00002B08* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Caching Agent 0 + +pci:v00008086d00002B0C* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Caching Agent 1 + +pci:v00008086d00002B10* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Home Agent 0 + +pci:v00008086d00002B13* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 0c + +pci:v00008086d00002B14* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 0a + +pci:v00008086d00002B16* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 0b + +pci:v00008086d00002B18* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Home Agent 1 + +pci:v00008086d00002B1B* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 1c + +pci:v00008086d00002B1C* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 1a + +pci:v00008086d00002B1E* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Memory Controller 1b + +pci:v00008086d00002B20* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 0 + +pci:v00008086d00002B22* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family System Configuration Controller 3 + +pci:v00008086d00002B24* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 1 + +pci:v00008086d00002B28* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 2 + +pci:v00008086d00002B2A* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family System Configuration Controller 4 + +pci:v00008086d00002B2C* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 3 + +pci:v00008086d00002B30* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 4 + +pci:v00008086d00002B34* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 5 + +pci:v00008086d00002B38* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 6 + +pci:v00008086d00002B3C* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 7 + +pci:v00008086d00002B40* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Router Port 0-1 + +pci:v00008086d00002B42* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Router Port 2-3 + +pci:v00008086d00002B44* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Router Port 4-5 + +pci:v00008086d00002B46* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Router Port 6-7 + +pci:v00008086d00002B48* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Test and Debug 0 + +pci:v00008086d00002B4C* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Test and Debug 1 + +pci:v00008086d00002B50* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 0: REUT control/status + +pci:v00008086d00002B52* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 0: Misc. control/status + +pci:v00008086d00002B54* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 1: REUT control/status + +pci:v00008086d00002B56* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 1: Misc. control/status + +pci:v00008086d00002B58* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 2: REUT control/status + +pci:v00008086d00002B5A* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 2: Misc. control/status + +pci:v00008086d00002B5C* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 3: REUT control/status + +pci:v00008086d00002B5E* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family QPI Physical Port 3: Misc. control/status + +pci:v00008086d00002B60* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family SMI Physical Port 0: REUT control/status + +pci:v00008086d00002B62* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family SMI Physical Port 0: Misc control/status + +pci:v00008086d00002B64* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family SMI Physical Port 1: REUT control/status + +pci:v00008086d00002B66* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family SMI Physical Port 1: Misc control/status + +pci:v00008086d00002B68* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 8 + +pci:v00008086d00002B6C* + ID_MODEL_FROM_DATABASE=Xeon Processor E7 Product Family Last Level Cache Coherence Engine 9 + +pci:v00008086d00002C01* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QuickPath Architecture System Address Decoder + +pci:v00008086d00002C10* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QPI Link 0 + +pci:v00008086d00002C11* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QPI Physical 0 + +pci:v00008086d00002C14* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QPI Link 1 + +pci:v00008086d00002C15* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QPI Physical 1 + +pci:v00008086d00002C18* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller + +pci:v00008086d00002C19* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Target Address Decoder + +pci:v00008086d00002C1A* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller RAS Registers + +pci:v00008086d00002C1C* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Test Registers + +pci:v00008086d00002C20* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Control Registers + +pci:v00008086d00002C21* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Address Registers + +pci:v00008086d00002C22* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Rank Registers + +pci:v00008086d00002C23* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Thermal Control Registers + +pci:v00008086d00002C28* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Control Registers + +pci:v00008086d00002C29* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Address Registers + +pci:v00008086d00002C2A* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Rank Registers + +pci:v00008086d00002C2B* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Thermal Control Registers + +pci:v00008086d00002C30* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Control Registers + +pci:v00008086d00002C31* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Address Registers + +pci:v00008086d00002C32* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Rank Registers + +pci:v00008086d00002C33* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Thermal Control Registers + +pci:v00008086d00002C40* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QuickPath Architecture Generic Non-Core Registers + +pci:v00008086d00002C41* + ID_MODEL_FROM_DATABASE=Xeon 5500/Core i7 QuickPath Architecture Generic Non-Core Registers + +pci:v00008086d00002C50* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers + +pci:v00008086d00002C51* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers + +pci:v00008086d00002C52* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers + +pci:v00008086d00002C53* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers + +pci:v00008086d00002C54* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers + +pci:v00008086d00002C55* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers + +pci:v00008086d00002C56* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers + +pci:v00008086d00002C57* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-Core Registers + +pci:v00008086d00002C58* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers + +pci:v00008086d00002C59* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers + +pci:v00008086d00002C5A* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers + +pci:v00008086d00002C5B* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers + +pci:v00008086d00002C5C* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers + +pci:v00008086d00002C5D* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers + +pci:v00008086d00002C5E* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers + +pci:v00008086d00002C5F* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Generic Non-core Registers + +pci:v00008086d00002C61* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-core Registers + +pci:v00008086d00002C62* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture Generic Non-core Registers + +pci:v00008086d00002C70* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series QuickPath Architecture Generic Non-core Registers + +pci:v00008086d00002C81* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture System Address Decoder + +pci:v00008086d00002C90* + ID_MODEL_FROM_DATABASE=Core Processor QPI Link 0 + +pci:v00008086d00002C91* + ID_MODEL_FROM_DATABASE=Core Processor QPI Physical 0 + +pci:v00008086d00002C98* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller + +pci:v00008086d00002C99* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Target Address Decoder + +pci:v00008086d00002C9A* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Test Registers + +pci:v00008086d00002C9C* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Test Registers + +pci:v00008086d00002CA0* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 0 Control Registers + +pci:v00008086d00002CA1* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 0 Address Registers + +pci:v00008086d00002CA2* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 0 Rank Registers + +pci:v00008086d00002CA3* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 0 Thermal Control Registers + +pci:v00008086d00002CA8* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 1 Control Registers + +pci:v00008086d00002CA9* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 1 Address Registers + +pci:v00008086d00002CAA* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 1 Rank Registers + +pci:v00008086d00002CAB* + ID_MODEL_FROM_DATABASE=Core Processor Integrated Memory Controller Channel 1 Thermal Control Registers + +pci:v00008086d00002CC1* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI System Address Decoder + +pci:v00008086d00002CD0* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Link 0 + +pci:v00008086d00002CD1* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Physical 0 + +pci:v00008086d00002CD4* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Link 1 + +pci:v00008086d00002CD5* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Physical 1 + +pci:v00008086d00002CD8* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Registers + +pci:v00008086d00002CD9* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Target Address Decoder + +pci:v00008086d00002CDA* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller RAS Registers + +pci:v00008086d00002CDC* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Test Registers + +pci:v00008086d00002CE0* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 0 Control + +pci:v00008086d00002CE1* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 0 Address + +pci:v00008086d00002CE2* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 0 Rank + +pci:v00008086d00002CE3* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 0 Thermal Control + +pci:v00008086d00002CE8* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 1 Control + +pci:v00008086d00002CE9* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 1 Address + +pci:v00008086d00002CEA* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 1 Rank + +pci:v00008086d00002CEB* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 1 Thermal Control + +pci:v00008086d00002CF0* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 2 Control + +pci:v00008086d00002CF1* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 2 Address + +pci:v00008086d00002CF2* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 2 Rank + +pci:v00008086d00002CF3* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Integrated Memory Controller Channel 2 Thermal Control + +pci:v00008086d00002D01* + ID_MODEL_FROM_DATABASE=Core Processor QuickPath Architecture System Address Decoder + +pci:v00008086d00002D10* + ID_MODEL_FROM_DATABASE=Core Processor QPI Link 0 + +pci:v00008086d00002D11* + ID_MODEL_FROM_DATABASE=1st Generation Core i3/5/7 Processor QPI Physical 0 + +pci:v00008086d00002D12* + ID_MODEL_FROM_DATABASE=1st Generation Core i3/5/7 Processor Reserved + +pci:v00008086d00002D13* + ID_MODEL_FROM_DATABASE=1st Generation Core i3/5/7 Processor Reserved + +pci:v00008086d00002D81* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series QuickPath Architecture System Address Decoder + +pci:v00008086d00002D90* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series QPI Link 0 + +pci:v00008086d00002D91* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series QPI Physical 0 + +pci:v00008086d00002D92* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Mirror Port Link 0 + +pci:v00008086d00002D93* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Mirror Port Link 1 + +pci:v00008086d00002D94* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series QPI Link 1 + +pci:v00008086d00002D95* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series QPI Physical 1 + +pci:v00008086d00002D98* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Registers + +pci:v00008086d00002D99* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Target Address Decoder + +pci:v00008086d00002D9A* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller RAS Registers + +pci:v00008086d00002D9C* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Test Registers + +pci:v00008086d00002DA0* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 0 Control + +pci:v00008086d00002DA1* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 0 Address + +pci:v00008086d00002DA2* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 0 Rank + +pci:v00008086d00002DA3* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 0 Thermal Control + +pci:v00008086d00002DA8* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 1 Control + +pci:v00008086d00002DA9* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 1 Address + +pci:v00008086d00002DAA* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 1 Rank + +pci:v00008086d00002DAB* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 1 Thermal Control + +pci:v00008086d00002DB0* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 2 Control + +pci:v00008086d00002DB1* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 2 Address + +pci:v00008086d00002DB2* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 2 Rank + +pci:v00008086d00002DB3* + ID_MODEL_FROM_DATABASE=Xeon 5600 Series Integrated Memory Controller Channel 2 Thermal Control + +pci:v00008086d00002E00* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller + +pci:v00008086d00002E01* + ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port + +pci:v00008086d00002E02* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E03* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E04* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E05* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E06* + ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller + +pci:v00008086d00002E07* + ID_MODEL_FROM_DATABASE=4 Series Chipset Serial KT Controller + +pci:v00008086d00002E10* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller + +pci:v00008086d00002E11* + ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port + +pci:v00008086d00002E12* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E12sv000017AAsd00003048* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller (ThinkCentre M6258) + +pci:v00008086d00002E13* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E14* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E15* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E16* + ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller + +pci:v00008086d00002E17* + ID_MODEL_FROM_DATABASE=4 Series Chipset Serial KT Controller + +pci:v00008086d00002E20* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller + +pci:v00008086d00002E20sv00001028sd00000283* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (Vostro 220) + +pci:v00008086d00002E20sv00001043sd000082D3* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (P5Q Deluxe Motherboard) + +pci:v00008086d00002E20sv00001458sd00005000* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) + +pci:v00008086d00002E21* + ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port + +pci:v00008086d00002E21sv00001043sd000082D3* + ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port (P5Q Deluxe Motherboard) + +pci:v00008086d00002E21sv00001458sd00005000* + ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port (GA-EP45-DS5 Motherboard) + +pci:v00008086d00002E22* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E22sv00001458sd0000D000* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller (GA-EG45M-DS2H Mainboard) + +pci:v00008086d00002E23* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E23sv00001458sd0000D000* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller (GA-EG45M-DS2H Mainboard) + +pci:v00008086d00002E24* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E25* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E26* + ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller + +pci:v00008086d00002E27* + ID_MODEL_FROM_DATABASE=4 Series Chipset Serial KT Controller + +pci:v00008086d00002E29* + ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port + +pci:v00008086d00002E30* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller + +pci:v00008086d00002E30sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller (Compaq 500B Microtower) + +pci:v00008086d00002E31* + ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port + +pci:v00008086d00002E32* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E32sv0000103Csd00002A8C* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller (Compaq 500B Microtower) + +pci:v00008086d00002E33* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E34* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E35* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E36* + ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller + +pci:v00008086d00002E37* + ID_MODEL_FROM_DATABASE=4 Series Chipset Serial KT Controller + +pci:v00008086d00002E40* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller + +pci:v00008086d00002E41* + ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port + +pci:v00008086d00002E42* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E43* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E44* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E45* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E46* + ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller + +pci:v00008086d00002E47* + ID_MODEL_FROM_DATABASE=4 Series Chipset Serial KT Controller + +pci:v00008086d00002E50* + ID_MODEL_FROM_DATABASE=CE Media Processor CE3100 + +pci:v00008086d00002E52* + ID_MODEL_FROM_DATABASE=CE Media Processor Clock and Reset Controller + +pci:v00008086d00002E58* + ID_MODEL_FROM_DATABASE=CE Media Processor Interrupt Controller + +pci:v00008086d00002E5A* + ID_MODEL_FROM_DATABASE=CE Media Processor CE3100 A/V Bridge + +pci:v00008086d00002E5B* + ID_MODEL_FROM_DATABASE=Graphics Media Accelerator 500 Graphics + +pci:v00008086d00002E5C* + ID_MODEL_FROM_DATABASE=CE Media Processor Video Decoder + +pci:v00008086d00002E5D* + ID_MODEL_FROM_DATABASE=CE Media Processor Transport Stream Interface + +pci:v00008086d00002E5E* + ID_MODEL_FROM_DATABASE=CE Media Processor Transport Stream Processor 0 + +pci:v00008086d00002E5F* + ID_MODEL_FROM_DATABASE=CE Media Processor Audio DSP + +pci:v00008086d00002E60* + ID_MODEL_FROM_DATABASE=CE Media Processor Audio Interfaces + +pci:v00008086d00002E61* + ID_MODEL_FROM_DATABASE=CE Media Processor Video Display Controller + +pci:v00008086d00002E62* + ID_MODEL_FROM_DATABASE=CE Media Processor Video Processing Unit + +pci:v00008086d00002E63* + ID_MODEL_FROM_DATABASE=CE Media Processor HDMI Tx Interface + +pci:v00008086d00002E65* + ID_MODEL_FROM_DATABASE=CE Media Processor Expansion Bus Interface + +pci:v00008086d00002E66* + ID_MODEL_FROM_DATABASE=CE Media Processor UART + +pci:v00008086d00002E67* + ID_MODEL_FROM_DATABASE=CE Media Processor General Purpose I/Os + +pci:v00008086d00002E68* + ID_MODEL_FROM_DATABASE=CE Media Processor I2C Interface + +pci:v00008086d00002E69* + ID_MODEL_FROM_DATABASE=CE Media Processor Smart Card Interface + +pci:v00008086d00002E6A* + ID_MODEL_FROM_DATABASE=CE Media Processor SPI Master Interface + +pci:v00008086d00002E6E* + ID_MODEL_FROM_DATABASE=CE Media Processor Gigabit Ethernet Controller + +pci:v00008086d00002E6F* + ID_MODEL_FROM_DATABASE=CE Media Processor Media Timing Unit + +pci:v00008086d00002E70* + ID_MODEL_FROM_DATABASE=CE Media Processor USB + +pci:v00008086d00002E71* + ID_MODEL_FROM_DATABASE=CE Media Processor SATA + +pci:v00008086d00002E73* + ID_MODEL_FROM_DATABASE=CE Media Processor CE3100 PCI Express + +pci:v00008086d00002E90* + ID_MODEL_FROM_DATABASE=4 Series Chipset DRAM Controller + +pci:v00008086d00002E91* + ID_MODEL_FROM_DATABASE=4 Series Chipset PCI Express Root Port + +pci:v00008086d00002E92* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E93* + ID_MODEL_FROM_DATABASE=4 Series Chipset Integrated Graphics Controller + +pci:v00008086d00002E94* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E95* + ID_MODEL_FROM_DATABASE=4 Series Chipset HECI Controller + +pci:v00008086d00002E96* + ID_MODEL_FROM_DATABASE=4 Series Chipset PT IDER Controller + +pci:v00008086d00002F00* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMI2 + +pci:v00008086d00002F01* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 0 + +pci:v00008086d00002F02* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 1 + +pci:v00008086d00002F03* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 1 + +pci:v00008086d00002F04* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 + +pci:v00008086d00002F05* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 + +pci:v00008086d00002F06* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 + +pci:v00008086d00002F07* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 + +pci:v00008086d00002F08* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 + +pci:v00008086d00002F09* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 + +pci:v00008086d00002F0A* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 + +pci:v00008086d00002F0B* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 + +pci:v00008086d00002F0D* + ID_MODEL_FROM_DATABASE=Haswell Xeon Non-Transparent Bridge (Back-to-back) + +pci:v00008086d00002F0E* + ID_MODEL_FROM_DATABASE=Haswell Xeon Non-Transparent Bridge (Primary Side) + +pci:v00008086d00002F0F* + ID_MODEL_FROM_DATABASE=Haswell Xeon Non-Transparent Bridge (Secondary Side) + +pci:v00008086d00002F10* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F11* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F12* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F13* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F14* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F15* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F16* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F17* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F18* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F19* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F1A* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F1B* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F1C* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + +pci:v00008086d00002F1D* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCIe Ring Interface + +pci:v00008086d00002F1E* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Scratchpad & Semaphore Registers + +pci:v00008086d00002F1F* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Scratchpad & Semaphore Registers + +pci:v00008086d00002F20* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 0 + +pci:v00008086d00002F21* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 1 + +pci:v00008086d00002F22* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 2 + +pci:v00008086d00002F23* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 3 + +pci:v00008086d00002F24* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 4 + +pci:v00008086d00002F25* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 5 + +pci:v00008086d00002F26* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 6 + +pci:v00008086d00002F27* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 7 + +pci:v00008086d00002F28* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Address Map, VTd_Misc, System Management + +pci:v00008086d00002F29* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Hot Plug + +pci:v00008086d00002F2A* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 RAS, Control Status and Global Errors + +pci:v00008086d00002F2C* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 I/O APIC + +pci:v00008086d00002F2E* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 RAID 5/6 + +pci:v00008086d00002F2F* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 RAID 5/6 + +pci:v00008086d00002F30* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 0 + +pci:v00008086d00002F32* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 + +pci:v00008086d00002F33* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 + +pci:v00008086d00002F34* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 PCIe Ring Interface + +pci:v00008086d00002F36* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 0 & 1 Monitoring + +pci:v00008086d00002F37* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 0 & 1 Monitoring + +pci:v00008086d00002F38* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 1 + +pci:v00008086d00002F39* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 I/O Performance Monitoring + +pci:v00008086d00002F3A* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 + +pci:v00008086d00002F3E* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 2 Monitoring + +pci:v00008086d00002F3F* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 2 Monitoring + +pci:v00008086d00002F40* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 + +pci:v00008086d00002F41* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 2 Monitoring + +pci:v00008086d00002F43* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 + +pci:v00008086d00002F45* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 Debug + +pci:v00008086d00002F46* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 Debug + +pci:v00008086d00002F47* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 Debug + +pci:v00008086d00002F60* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 1 + +pci:v00008086d00002F68* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Target Address, Thermal & RAS Registers + +pci:v00008086d00002F6A* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder + +pci:v00008086d00002F6B* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder + +pci:v00008086d00002F6C* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder + +pci:v00008086d00002F6D* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder + +pci:v00008086d00002F6E* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Channel 2/3 Broadcast + +pci:v00008086d00002F6F* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Global Broadcast + +pci:v00008086d00002F70* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 0 Debug + +pci:v00008086d00002F71* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Target Address, Thermal & RAS Registers + +pci:v00008086d00002F76* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 E3 QPI Link Debug + +pci:v00008086d00002F78* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 1 Debug + +pci:v00008086d00002F79* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Target Address, Thermal & RAS Registers + +pci:v00008086d00002F7D* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Scratchpad & Semaphore Registers + +pci:v00008086d00002F7E* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 E3 QPI Link Debug + +pci:v00008086d00002F80* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 + +pci:v00008086d00002F81* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 0 & 1 Monitoring + +pci:v00008086d00002F83* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 + +pci:v00008086d00002F85* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 Debug + +pci:v00008086d00002F86* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 Debug + +pci:v00008086d00002F87* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 Debug + +pci:v00008086d00002F88* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 VCU + +pci:v00008086d00002F8A* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 VCU + +pci:v00008086d00002F90* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 + +pci:v00008086d00002F93* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 + +pci:v00008086d00002F95* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 Debug + +pci:v00008086d00002F96* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 Debug + +pci:v00008086d00002F98* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + +pci:v00008086d00002F99* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + +pci:v00008086d00002F9A* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + +pci:v00008086d00002F9C* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + +pci:v00008086d00002FA0* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 0 + +pci:v00008086d00002FA8* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Target Address, Thermal & RAS Registers + +pci:v00008086d00002FAA* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder + +pci:v00008086d00002FAB* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder + +pci:v00008086d00002FAC* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder + +pci:v00008086d00002FAD* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder + +pci:v00008086d00002FAE* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Channel 0/1 Broadcast + +pci:v00008086d00002FAF* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Global Broadcast + +pci:v00008086d00002FB0* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 0 Thermal Control + +pci:v00008086d00002FB1* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 1 Thermal Control + +pci:v00008086d00002FB2* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 0 ERROR Registers + +pci:v00008086d00002FB3* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 1 ERROR Registers + +pci:v00008086d00002FB4* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 2 Thermal Control + +pci:v00008086d00002FB5* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 3 Thermal Control + +pci:v00008086d00002FB6* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 2 ERROR Registers + +pci:v00008086d00002FB7* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 3 ERROR Registers + +pci:v00008086d00002FB8* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 + +pci:v00008086d00002FB9* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 + +pci:v00008086d00002FBA* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 + +pci:v00008086d00002FBB* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 + +pci:v00008086d00002FBC* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 + +pci:v00008086d00002FBD* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 + +pci:v00008086d00002FBE* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 + +pci:v00008086d00002FBF* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 + +pci:v00008086d00002FC0* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + +pci:v00008086d00002FC1* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + +pci:v00008086d00002FC2* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + +pci:v00008086d00002FC3* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + +pci:v00008086d00002FC4* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + +pci:v00008086d00002FC5* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + +pci:v00008086d00002FD0* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 0 Thermal Control + +pci:v00008086d00002FD1* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 1 Thermal Control + +pci:v00008086d00002FD2* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 0 ERROR Registers + +pci:v00008086d00002FD3* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 1 ERROR Registers + +pci:v00008086d00002FD4* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 2 Thermal Control + +pci:v00008086d00002FD5* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 3 Thermal Control + +pci:v00008086d00002FD6* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 2 ERROR Registers + +pci:v00008086d00002FD7* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 3 ERROR Registers + +pci:v00008086d00002FE0* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FE1* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FE2* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FE3* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FE4* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FE5* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FE6* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FE7* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FE8* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FE9* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FEA* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FEB* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FEC* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FED* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FEE* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FEF* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FF0* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FF1* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FF2* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FF3* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FF4* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FF5* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FF6* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FF7* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + +pci:v00008086d00002FF8* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent + +pci:v00008086d00002FF9* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent + +pci:v00008086d00002FFA* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent + +pci:v00008086d00002FFB* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent + +pci:v00008086d00002FFC* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers + +pci:v00008086d00002FFD* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers + +pci:v00008086d00002FFE* + ID_MODEL_FROM_DATABASE=Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers + +pci:v00008086d00003165* + ID_MODEL_FROM_DATABASE=Wireless 3165 + +pci:v00008086d00003165sv00008086sd00004010* + ID_MODEL_FROM_DATABASE=Wireless 3165 (Dual Band Wireless AC 3165) + +pci:v00008086d00003165sv00008086sd00004210* + ID_MODEL_FROM_DATABASE=Wireless 3165 (Dual Band Wireless AC 3165) + +pci:v00008086d00003166* + ID_MODEL_FROM_DATABASE=Dual Band Wireless-AC 3165 Plus Bluetooth + +pci:v00008086d00003184* + ID_MODEL_FROM_DATABASE=UHD Graphics 605 + +pci:v00008086d00003185* + ID_MODEL_FROM_DATABASE=UHD Graphics 605 + +pci:v00008086d0000318C* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Dynamic Platform and Thermal Framework Processor Participant + +pci:v00008086d0000318E* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor NorthPeak + +pci:v00008086d00003192* + ID_MODEL_FROM_DATABASE=Gemini Lake P2SB + +pci:v00008086d00003197* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor PCI-default ISA-bridge + +pci:v00008086d0000319A* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Trusted Execution Engine Interface + +pci:v00008086d000031A2* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Integrated Sensor Solution + +pci:v00008086d000031AC* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO I2C Host Controller + +pci:v00008086d000031AE* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO I2C Host Controller + +pci:v00008086d000031BC* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO UART Host Controller + +pci:v00008086d000031BE* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO UART Host Controller + +pci:v00008086d000031C0* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO UART Host Controller + +pci:v00008086d000031C2* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO SPI Host Controller + +pci:v00008086d000031C4* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO SPI Host Controller + +pci:v00008086d000031C6* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO SPI Host Controller + +pci:v00008086d000031CC* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor SDA Standard Compliant SD Host Controller + +pci:v00008086d000031D4* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Gaussian Mixture Model + +pci:v00008086d000031D6* + ID_MODEL_FROM_DATABASE=Gemini Lake PCI Express Root Port + +pci:v00008086d000031D7* + ID_MODEL_FROM_DATABASE=Gemini Lake PCI Express Root Port + +pci:v00008086d000031D8* + ID_MODEL_FROM_DATABASE=Gemini Lake PCI Express Root Port + +pci:v00008086d000031D9* + ID_MODEL_FROM_DATABASE=Gemini Lake PCI Express Root Port + +pci:v00008086d000031DA* + ID_MODEL_FROM_DATABASE=Gemini Lake PCI Express Root Port + +pci:v00008086d000031DB* + ID_MODEL_FROM_DATABASE=Gemini Lake PCI Express Root Port + +pci:v00008086d000031EE* + ID_MODEL_FROM_DATABASE=Celeron/Pentium Silver Processor Serial IO UART Host Controller + +pci:v00008086d000031F0* + ID_MODEL_FROM_DATABASE=Gemini Lake Host Bridge + +pci:v00008086d00003200* + ID_MODEL_FROM_DATABASE=GD31244 PCI-X SATA HBA + +pci:v00008086d00003200sv00001775sd0000C200* + ID_MODEL_FROM_DATABASE=GD31244 PCI-X SATA HBA (C2K onboard SATA host bus adapter) + +pci:v00008086d00003310* + ID_MODEL_FROM_DATABASE=IOP348 I/O Processor + +pci:v00008086d00003310sv00001054sd00003030* + ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (HRA380 Hitachi RAID Adapter to PCIe) + +pci:v00008086d00003310sv00001054sd00003034* + ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (HRA381 Hitachi RAID Adapter to PCIe) + +pci:v00008086d00003313* + ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (SL8e) in IOC Mode SAS/SATA + +pci:v00008086d0000331B* + ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (SL8x) in IOC Mode SAS/SATA + +pci:v00008086d00003331* + ID_MODEL_FROM_DATABASE=IOC340 I/O Controller (VV8e) SAS/SATA + +pci:v00008086d00003339* + ID_MODEL_FROM_DATABASE=IOC340 I/O Controller (VV8x) SAS/SATA + +pci:v00008086d00003340* + ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller + +pci:v00008086d00003340sv00001014sd00000529* + ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (Thinkpad T40 series) + +pci:v00008086d00003340sv00001025sd0000005A* + ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (TravelMate 290) + +pci:v00008086d00003340sv0000103Csd0000088C* + ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (NC8000 laptop) + +pci:v00008086d00003340sv0000103Csd00000890* + ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (NC6000 laptop) + +pci:v00008086d00003340sv0000103Csd000008B0* + ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (tc1100 tablet) + +pci:v00008086d00003340sv0000144Dsd0000C005* + ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (X10 Laptop) + +pci:v00008086d00003340sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82855PM Processor to I/O Controller (P30/P35 notebook) + +pci:v00008086d00003341* + ID_MODEL_FROM_DATABASE=82855PM Processor to AGP Controller + +pci:v00008086d00003341sv0000144Dsd0000C00C* + ID_MODEL_FROM_DATABASE=82855PM Processor to AGP Controller (P30 notebook) + +pci:v00008086d00003363* + ID_MODEL_FROM_DATABASE=IOC340 I/O Controller in IOC Mode SAS/SATA + +pci:v00008086d00003382* + ID_MODEL_FROM_DATABASE=81342 [Chevelon] I/O Processor (ATUe) + +pci:v00008086d000033C3* + ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (SL8De) in IOC Mode SAS/SATA + +pci:v00008086d000033CB* + ID_MODEL_FROM_DATABASE=IOP348 I/O Processor (SL8Dx) in IOC Mode SAS/SATA + +pci:v00008086d00003400* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port + +pci:v00008086d00003401* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port + +pci:v00008086d00003402* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port + +pci:v00008086d00003403* + ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port + +pci:v00008086d00003403sv00001028sd00000236* + ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port (PowerEdge R610 I/O Hub to ESI Port) + +pci:v00008086d00003403sv00001028sd00000287* + ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port (PowerEdge M610 I/O Hub to ESI Port) + +pci:v00008086d00003403sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port (PowerEdge R410 I/O Hub to ESI Port) + +pci:v00008086d00003403sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port (PowerEdge T410 I/O Hub to ESI Port) + +pci:v00008086d00003403sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=5500 I/O Hub to ESI Port (ProLiant ML150 G6 Server) + +pci:v00008086d00003404* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port + +pci:v00008086d00003405* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port + +pci:v00008086d00003406* + ID_MODEL_FROM_DATABASE=5520 I/O Hub to ESI Port + +pci:v00008086d00003406sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=5520 I/O Hub to ESI Port (ProLiant G6 series) + +pci:v00008086d00003407* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub to ESI Port + +pci:v00008086d00003408* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 1 + +pci:v00008086d00003408sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 1 (ProLiant G6 series) + +pci:v00008086d00003409* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 2 + +pci:v00008086d0000340A* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 3 + +pci:v00008086d0000340Asv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 3 (ProLiant ML150 G6 Server) + +pci:v00008086d0000340B* + ID_MODEL_FROM_DATABASE=5520/X58 I/O Hub PCI Express Root Port 4 + +pci:v00008086d0000340C* + ID_MODEL_FROM_DATABASE=5520/X58 I/O Hub PCI Express Root Port 5 + +pci:v00008086d0000340D* + ID_MODEL_FROM_DATABASE=5520/X58 I/O Hub PCI Express Root Port 6 + +pci:v00008086d0000340E* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 7 + +pci:v00008086d0000340Esv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 7 (ProLiant ML150 G6 Server) + +pci:v00008086d0000340F* + ID_MODEL_FROM_DATABASE=5520/5500/X58 I/O Hub PCI Express Root Port 8 + +pci:v00008086d00003410* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub PCI Express Root Port 9 + +pci:v00008086d00003411* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub PCI Express Root Port 10 + +pci:v00008086d00003418* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 Physical Layer Port 0 + +pci:v00008086d00003419* + ID_MODEL_FROM_DATABASE=7500/5520/5500 Physical Layer Port 1 + +pci:v00008086d00003420* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 + +pci:v00008086d00003421* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 + +pci:v00008086d00003422* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers + +pci:v00008086d00003422sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers (ProLiant G6 series) + +pci:v00008086d00003423* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub Control Status and RAS Registers + +pci:v00008086d00003423sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub Control Status and RAS Registers (ProLiant G6 series) + +pci:v00008086d00003425* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 Physical and Link Layer Registers Port 0 + +pci:v00008086d00003426* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 Routing and Protocol Layer Registers Port 0 + +pci:v00008086d00003427* + ID_MODEL_FROM_DATABASE=7500/5520/5500 Physical and Link Layer Registers Port 1 + +pci:v00008086d00003428* + ID_MODEL_FROM_DATABASE=7500/5520/5500 Routing & Protocol Layer Register Port 1 + +pci:v00008086d00003429* + ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device + +pci:v00008086d0000342A* + ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device + +pci:v00008086d0000342B* + ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device + +pci:v00008086d0000342C* + ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device + +pci:v00008086d0000342D* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub I/OxAPIC Interrupt Controller + +pci:v00008086d0000342E* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub System Management Registers + +pci:v00008086d0000342Esv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub System Management Registers (ProLiant G6 series) + +pci:v00008086d0000342F* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 Trusted Execution Technology Registers + +pci:v00008086d00003430* + ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device + +pci:v00008086d00003431* + ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device + +pci:v00008086d00003432* + ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device + +pci:v00008086d00003433* + ID_MODEL_FROM_DATABASE=5520/5500/X58 Chipset QuickData Technology Device + +pci:v00008086d00003438* + ID_MODEL_FROM_DATABASE=7500/5520/5500/X58 I/O Hub Throttle Registers + +pci:v00008086d00003482* + ID_MODEL_FROM_DATABASE=Ice Lake-LP LPC Controller + +pci:v00008086d000034A3* + ID_MODEL_FROM_DATABASE=Ice Lake-LP SMBus Controller + +pci:v00008086d000034A4* + ID_MODEL_FROM_DATABASE=Ice Lake-LP SPI Controller + +pci:v00008086d000034A8* + ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO UART Controller #0 + +pci:v00008086d000034A9* + ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO UART Controller #1 + +pci:v00008086d000034AA* + ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO SPI Controller #0 + +pci:v00008086d000034AB* + ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO SPI Controller #1 + +pci:v00008086d000034B0* + ID_MODEL_FROM_DATABASE=Ice Lake-LP PCI Express Root Port #9 + +pci:v00008086d000034BC* + ID_MODEL_FROM_DATABASE=Ice Lake-LP PCI Express Root Port #5 + +pci:v00008086d000034C5* + ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO I2c Controller #4 + +pci:v00008086d000034C6* + ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO I2c Controller #5 + +pci:v00008086d000034C8* + ID_MODEL_FROM_DATABASE=Smart Sound Technology Audio Controller + +pci:v00008086d000034D3* + ID_MODEL_FROM_DATABASE=Ice Lake-LP SATA Controller [AHCI mode] + +pci:v00008086d000034E0* + ID_MODEL_FROM_DATABASE=Management Engine Interface + +pci:v00008086d000034E8* + ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO I2C Controller #0 + +pci:v00008086d000034E9* + ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO I2C Controller #1 + +pci:v00008086d000034EA* + ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO I2C Controller #2 + +pci:v00008086d000034EB* + ID_MODEL_FROM_DATABASE=Ice Lake-LP Serial IO I2C Controller #3 + +pci:v00008086d000034ED* + ID_MODEL_FROM_DATABASE=Ice Lake-LP USB 3.1 xHCI Host Controller + +pci:v00008086d000034F0* + ID_MODEL_FROM_DATABASE=Killer Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW) + +pci:v00008086d000034F8* + ID_MODEL_FROM_DATABASE=Ice Lake-LP SD Controller + +pci:v00008086d00003500* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Upstream Port + +pci:v00008086d00003500sv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Upstream Port (ProLiant DL140 G3) + +pci:v00008086d00003500sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Upstream Port (X7DBN Motherboard) + +pci:v00008086d00003501* + ID_MODEL_FROM_DATABASE=6310ESB PCI Express Upstream Port + +pci:v00008086d00003504* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB I/OxAPIC Interrupt Controller + +pci:v00008086d00003505* + ID_MODEL_FROM_DATABASE=6310ESB I/OxAPIC Interrupt Controller + +pci:v00008086d0000350C* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express to PCI-X Bridge + +pci:v00008086d0000350Csv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express to PCI-X Bridge (ProLiant DL140 G3) + +pci:v00008086d0000350Csv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express to PCI-X Bridge (X7DBN Motherboard) + +pci:v00008086d0000350D* + ID_MODEL_FROM_DATABASE=6310ESB PCI Express to PCI-X Bridge + +pci:v00008086d00003510* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E1 + +pci:v00008086d00003510sv0000103Csd000031FE* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E1 (ProLiant DL140 G3) + +pci:v00008086d00003510sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E1 (X7DBN Motherboard) + +pci:v00008086d00003511* + ID_MODEL_FROM_DATABASE=6310ESB PCI Express Downstream Port E1 + +pci:v00008086d00003514* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E2 + +pci:v00008086d00003515* + ID_MODEL_FROM_DATABASE=6310ESB PCI Express Downstream Port E2 + +pci:v00008086d00003518* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E3 + +pci:v00008086d00003518sv000015D9sd00009680* + ID_MODEL_FROM_DATABASE=6311ESB/6321ESB PCI Express Downstream Port E3 (X7DBN Motherboard) + +pci:v00008086d00003519* + ID_MODEL_FROM_DATABASE=6310ESB PCI Express Downstream Port E3 + +pci:v00008086d00003575* + ID_MODEL_FROM_DATABASE=82830M/MG/MP Host Bridge + +pci:v00008086d00003575sv00000E11sd00000030* + ID_MODEL_FROM_DATABASE=82830M/MG/MP Host Bridge (Evo N600c) + +pci:v00008086d00003575sv00001014sd0000021D* + ID_MODEL_FROM_DATABASE=82830M/MG/MP Host Bridge (ThinkPad A/T/X Series) + +pci:v00008086d00003575sv0000104Dsd000080E7* + ID_MODEL_FROM_DATABASE=82830M/MG/MP Host Bridge (VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP) + +pci:v00008086d00003576* + ID_MODEL_FROM_DATABASE=82830M/MP AGP Bridge + +pci:v00008086d00003577* + ID_MODEL_FROM_DATABASE=82830M/MG Integrated Graphics Controller + +pci:v00008086d00003577sv00001014sd00000513* + ID_MODEL_FROM_DATABASE=82830M/MG Integrated Graphics Controller (ThinkPad A/T/X Series) + +pci:v00008086d00003578* + ID_MODEL_FROM_DATABASE=82830M/MG/MP Host Bridge + +pci:v00008086d00003580* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller + +pci:v00008086d00003580sv00001014sd0000055C* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (ThinkPad R50e) + +pci:v00008086d00003580sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Extensa 3000 series laptop) + +pci:v00008086d00003580sv00001028sd00000139* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D400) + +pci:v00008086d00003580sv00001028sd0000014F* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude X300) + +pci:v00008086d00003580sv00001028sd00000152* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D500) + +pci:v00008086d00003580sv00001028sd00000163* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D505) + +pci:v00008086d00003580sv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 700m/710m) + +pci:v00008086d00003580sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 5160) + +pci:v00008086d00003580sv0000114Asd00000582* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PC8) + +pci:v00008086d00003580sv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Amilo M1420) + +pci:v00008086d00003580sv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (V5D Single Board Computer) + +pci:v00008086d00003580sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CE9) + +pci:v00008086d00003580sv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CL9 mainboard) + +pci:v00008086d00003580sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PSL09 PrPMC) + +pci:v00008086d00003580sv0000E4BFsd00000CC9* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CC9-SAMBA) + +pci:v00008086d00003580sv0000E4BFsd00000CD2* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CD2-BEBOP) + +pci:v00008086d00003581* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to AGP Controller + +pci:v00008086d00003581sv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to AGP Controller (Amilo M1420) + +pci:v00008086d00003582* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device + +pci:v00008086d00003582sv00001014sd00000562* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (ThinkPad R50e) + +pci:v00008086d00003582sv00001028sd00000139* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (Latitude D400) + +pci:v00008086d00003582sv00001028sd0000014F* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (Latitude X300) + +pci:v00008086d00003582sv00001028sd00000152* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (Latitude D500) + +pci:v00008086d00003582sv00001028sd00000163* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (Latitude D505) + +pci:v00008086d00003582sv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (Inspiron 700m/710m) + +pci:v00008086d00003582sv0000114Asd00000582* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (PC8 integrated graphics) + +pci:v00008086d00003582sv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (V5D Single Board Computer VGA) + +pci:v00008086d00003582sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (CE9) + +pci:v00008086d00003582sv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (CL9 mainboard) + +pci:v00008086d00003582sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (PSL09 PrPMC) + +pci:v00008086d00003582sv0000E4BFsd00000CC9* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (CC9-SAMBA) + +pci:v00008086d00003582sv0000E4BFsd00000CD2* + ID_MODEL_FROM_DATABASE=82852/855GM Integrated Graphics Device (CD2-BEBOP) + +pci:v00008086d00003584* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller + +pci:v00008086d00003584sv00001014sd0000055D* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (ThinkPad R50e) + +pci:v00008086d00003584sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Extensa 3000 series laptop) + +pci:v00008086d00003584sv00001028sd00000139* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D400) + +pci:v00008086d00003584sv00001028sd0000014F* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude X300) + +pci:v00008086d00003584sv00001028sd00000152* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D500) + +pci:v00008086d00003584sv00001028sd00000163* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D505) + +pci:v00008086d00003584sv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 700m/710m) + +pci:v00008086d00003584sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 5160) + +pci:v00008086d00003584sv0000114Asd00000582* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PC8) + +pci:v00008086d00003584sv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Amilo M1420) + +pci:v00008086d00003584sv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (V5D Single Board Computer) + +pci:v00008086d00003584sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CE9) + +pci:v00008086d00003584sv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CL9 mainboard) + +pci:v00008086d00003584sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PSL09 PrPMC) + +pci:v00008086d00003585* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller + +pci:v00008086d00003585sv00001014sd0000055E* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (ThinkPad R50e) + +pci:v00008086d00003585sv00001025sd00000064* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Extensa 3000 series laptop) + +pci:v00008086d00003585sv00001028sd00000139* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D400) + +pci:v00008086d00003585sv00001028sd0000014F* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude X300) + +pci:v00008086d00003585sv00001028sd00000152* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D500) + +pci:v00008086d00003585sv00001028sd00000163* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Latitude D505) + +pci:v00008086d00003585sv00001028sd0000018D* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 700m/710m) + +pci:v00008086d00003585sv00001028sd00000196* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Inspiron 5160) + +pci:v00008086d00003585sv0000114Asd00000582* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PC8) + +pci:v00008086d00003585sv00001734sd00001055* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (Amilo M1420) + +pci:v00008086d00003585sv00001775sd000010D0* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (V5D Single Board Computer) + +pci:v00008086d00003585sv00001775sd0000CE90* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CE9) + +pci:v00008086d00003585sv00004C53sd000010B0* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (CL9 mainboard) + +pci:v00008086d00003585sv00004C53sd000010E0* + ID_MODEL_FROM_DATABASE=82852/82855 GM/GME/PM/GMV Processor to I/O Controller (PSL09 PrPMC) + +pci:v00008086d0000358C* + ID_MODEL_FROM_DATABASE=82854 GMCH + +pci:v00008086d0000358E* + ID_MODEL_FROM_DATABASE=82854 GMCH Integrated Graphics Device + +pci:v00008086d00003590* + ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub + +pci:v00008086d00003590sv00001014sd000002DD* + ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (eServer xSeries server mainboard) + +pci:v00008086d00003590sv00001028sd0000016C* + ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (PowerEdge 1850 Memory Controller Hub) + +pci:v00008086d00003590sv00001028sd0000016D* + ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (PowerEdge 2850 Memory Controller Hub) + +pci:v00008086d00003590sv00001028sd0000019A* + ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (PowerEdge SC1425) + +pci:v00008086d00003590sv00001734sd0000103E* + ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (PRIMERGY RX/TX S2 series) + +pci:v00008086d00003590sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (CR11/VR11 Single Board Computer) + +pci:v00008086d00003590sv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=E7520 Memory Controller Hub (Telum ASLP10 Processor AMC) + +pci:v00008086d00003591* + ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers + +pci:v00008086d00003591sv00001014sd000002DD* + ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers (eServer xSeries server mainboard) + +pci:v00008086d00003591sv00001028sd00000168* + ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers (Precision Workstation 670 Mainboard) + +pci:v00008086d00003591sv00001028sd00000169* + ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers (Precision 470) + +pci:v00008086d00003591sv0000103Csd00003208* + ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers (ProLiant DL140 G2) + +pci:v00008086d00003591sv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=E7525/E7520 Error Reporting Registers (Telum ASLP10 Processor AMC) + +pci:v00008086d00003592* + ID_MODEL_FROM_DATABASE=E7320 Memory Controller Hub + +pci:v00008086d00003592sv00001734sd00001073* + ID_MODEL_FROM_DATABASE=E7320 Memory Controller Hub (Primergy Econel 200 D2020 mainboard) + +pci:v00008086d00003593* + ID_MODEL_FROM_DATABASE=E7320 Error Reporting Registers + +pci:v00008086d00003593sv00001734sd00001073* + ID_MODEL_FROM_DATABASE=E7320 Error Reporting Registers (Primergy Econel 200 D2020 mainboard) + +pci:v00008086d00003594* + ID_MODEL_FROM_DATABASE=E7520 DMA Controller + +pci:v00008086d00003594sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=E7520 DMA Controller (CR11/VR11 Single Board Computer) + +pci:v00008086d00003594sv00004C53sd000010D0* + ID_MODEL_FROM_DATABASE=E7520 DMA Controller (Telum ASLP10 Processor AMC) + +pci:v00008086d00003595* + ID_MODEL_FROM_DATABASE=E7525/E7520/E7320 PCI Express Port A + +pci:v00008086d00003595sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=E7525/E7520/E7320 PCI Express Port A (CR11/VR11 Single Board Computer) + +pci:v00008086d00003596* + ID_MODEL_FROM_DATABASE=E7525/E7520/E7320 PCI Express Port A1 + +pci:v00008086d00003597* + ID_MODEL_FROM_DATABASE=E7525/E7520 PCI Express Port B + +pci:v00008086d00003597sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=E7525/E7520 PCI Express Port B (CR11/VR11 Single Board Computer) + +pci:v00008086d00003598* + ID_MODEL_FROM_DATABASE=E7520 PCI Express Port B1 + +pci:v00008086d00003598sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=E7520 PCI Express Port B1 (CR11/VR11 Single Board Computer) + +pci:v00008086d00003599* + ID_MODEL_FROM_DATABASE=E7520 PCI Express Port C + +pci:v00008086d00003599sv00001775sd00001100* + ID_MODEL_FROM_DATABASE=E7520 PCI Express Port C (CR11/VR11 Single Board Computer) + +pci:v00008086d0000359A* + ID_MODEL_FROM_DATABASE=E7520 PCI Express Port C1 + +pci:v00008086d0000359B* + ID_MODEL_FROM_DATABASE=E7525/E7520/E7320 Extended Configuration Registers + +pci:v00008086d0000359Bsv00001014sd000002DD* + ID_MODEL_FROM_DATABASE=E7525/E7520/E7320 Extended Configuration Registers (eServer xSeries server mainboard) + +pci:v00008086d0000359E* + ID_MODEL_FROM_DATABASE=E7525 Memory Controller Hub + +pci:v00008086d0000359Esv00001028sd00000168* + ID_MODEL_FROM_DATABASE=E7525 Memory Controller Hub (Precision Workstation 670 Mainboard) + +pci:v00008086d0000359Esv00001028sd00000169* + ID_MODEL_FROM_DATABASE=E7525 Memory Controller Hub (Precision 470) + +pci:v00008086d000035B0* + ID_MODEL_FROM_DATABASE=3100 Chipset Memory I/O Controller Hub + +pci:v00008086d000035B1* + ID_MODEL_FROM_DATABASE=3100 DRAM Controller Error Reporting Registers + +pci:v00008086d000035B5* + ID_MODEL_FROM_DATABASE=3100 Chipset Enhanced DMA Controller + +pci:v00008086d000035B6* + ID_MODEL_FROM_DATABASE=3100 Chipset PCI Express Port A + +pci:v00008086d000035B7* + ID_MODEL_FROM_DATABASE=3100 Chipset PCI Express Port A1 + +pci:v00008086d000035C8* + ID_MODEL_FROM_DATABASE=3100 Extended Configuration Test Overflow Registers + +pci:v00008086d00003600* + ID_MODEL_FROM_DATABASE=7300 Chipset Memory Controller Hub + +pci:v00008086d00003604* + ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 1 + +pci:v00008086d00003605* + ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 2 + +pci:v00008086d00003606* + ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 3 + +pci:v00008086d00003607* + ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 4 + +pci:v00008086d00003608* + ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 5 + +pci:v00008086d00003609* + ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 6 + +pci:v00008086d0000360A* + ID_MODEL_FROM_DATABASE=7300 Chipset PCI Express Port 7 + +pci:v00008086d0000360B* + ID_MODEL_FROM_DATABASE=7300 Chipset QuickData Technology Device + +pci:v00008086d0000360C* + ID_MODEL_FROM_DATABASE=7300 Chipset FSB Registers + +pci:v00008086d0000360Csv00001028sd000001F0* + ID_MODEL_FROM_DATABASE=7300 Chipset FSB Registers (PowerEdge R900 7300 Chipset FSB Registers) + +pci:v00008086d0000360D* + ID_MODEL_FROM_DATABASE=7300 Chipset Snoop Filter Registers + +pci:v00008086d0000360E* + ID_MODEL_FROM_DATABASE=7300 Chipset Debug and Miscellaneous Registers + +pci:v00008086d0000360F* + ID_MODEL_FROM_DATABASE=7300 Chipset FBD Branch 0 Registers + +pci:v00008086d00003610* + ID_MODEL_FROM_DATABASE=7300 Chipset FBD Branch 1 Registers + +pci:v00008086d00003700* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d00003701* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d00003702* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d00003703* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d00003704* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d00003705* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d00003706* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d00003707* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d00003708* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d00003709* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d0000370A* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d0000370B* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d0000370C* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d0000370D* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d0000370E* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d0000370F* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 DMI + +pci:v00008086d00003710* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA + +pci:v00008086d00003711* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA + +pci:v00008086d00003712* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA + +pci:v00008086d00003713* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA + +pci:v00008086d00003714* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA + +pci:v00008086d00003715* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA + +pci:v00008086d00003716* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA + +pci:v00008086d00003717* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA + +pci:v00008086d00003718* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA + +pci:v00008086d00003719* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 CB3 DMA + +pci:v00008086d0000371A* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Link + +pci:v00008086d0000371B* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Routing and Protocol + +pci:v00008086d0000371D* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 QPI Routing and Protocol + +pci:v00008086d00003720* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 PCI Express Root Port 0 + +pci:v00008086d00003721* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 PCI Express Root Port 1 + +pci:v00008086d00003722* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 PCI Express Root Port 2 + +pci:v00008086d00003723* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 PCI Express Root Port 3 + +pci:v00008086d00003724* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 PCI Express Root Port 4 + +pci:v00008086d00003725* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 NTB Primary + +pci:v00008086d00003726* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 NTB Primary + +pci:v00008086d00003727* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 NTB Secondary + +pci:v00008086d00003728* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Core + +pci:v00008086d00003729* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Core + +pci:v00008086d0000372A* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Core + +pci:v00008086d0000372B* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Core + +pci:v00008086d0000372C* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 Reserved + +pci:v00008086d0000373F* + ID_MODEL_FROM_DATABASE=Xeon C5500/C3500 IOxAPIC + +pci:v00008086d000037C8* + ID_MODEL_FROM_DATABASE=C62x Chipset QuickAssist Technology + +pci:v00008086d000037CC* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 + +pci:v00008086d000037CD* + ID_MODEL_FROM_DATABASE=Ethernet Virtual Function 700 Series + +pci:v00008086d000037CE* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE backplane + +pci:v00008086d000037CEsv00001590sd00000215* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE backplane (Ethernet 10Gb 2-port 568i Adapter) + +pci:v00008086d000037CEsv000017AAsd00004023* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE backplane (Intel Ethernet Connection X722 for 10GbE backplane) + +pci:v00008086d000037CEsv000017AAsd00004025* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE backplane + +pci:v00008086d000037CF* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE QSFP+ + +pci:v00008086d000037D0* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ + +pci:v00008086d000037D0sv000017AAsd00004020* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ (Intel Ethernet Connection X722 for 10G SFP+) + +pci:v00008086d000037D0sv000017AAsd00004021* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ (Intel Ethernet Connection X722 for 10G SFP+) + +pci:v00008086d000037D0sv000017AAsd00004022* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ + +pci:v00008086d000037D0sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ (Ethernet Network Adapter X722-2) + +pci:v00008086d000037D0sv00008086sd00000002* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ (Ethernet Network Adapter X722-2) + +pci:v00008086d000037D0sv00008086sd00000003* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ (Ethernet Network Adapter X722-4) + +pci:v00008086d000037D0sv00008086sd00000004* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ (Ethernet Network Adapter X722-4) + +pci:v00008086d000037D1* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE + +pci:v00008086d000037D1sv000014CDsd00000010* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE (88E1514 Ethernet OCP 2x1G RJ45 Phy Card [USI-1514-1GbaseT]) + +pci:v00008086d000037D1sv00001590sd00000216* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE (Ethernet 1Gb 2-port 368i Adapter) + +pci:v00008086d000037D1sv00001590sd00000217* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE (Ethernet 1Gb 2-port 368FLR-MMT Adapter) + +pci:v00008086d000037D1sv00001590sd00000247* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE (Ethernet 1Gb 4-port 369i Adapter) + +pci:v00008086d000037D1sv000017AAsd00004020* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE + +pci:v00008086d000037D1sv000017AAsd00004021* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE + +pci:v00008086d000037D1sv000017AAsd00004022* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE + +pci:v00008086d000037D1sv000017AAsd00004024* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 1GbE + +pci:v00008086d000037D2* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T + +pci:v00008086d000037D2sv00001059sd00000180* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T (RD10019 10GbE interface) + +pci:v00008086d000037D2sv00001170sd000037D2* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T + +pci:v00008086d000037D2sv000014CDsd00000030* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T (Ethernet OCP 2x10G RJ45 Phy Card [USI-X557-10GbaseT]) + +pci:v00008086d000037D2sv00001590sd00000218* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T (Ethernet 10Gb 2-port 568FLR-MMT Adapter) + +pci:v00008086d000037D2sv000017AAsd00004020* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T + +pci:v00008086d000037D2sv000017AAsd00004021* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T + +pci:v00008086d000037D2sv000017AAsd00004022* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T + +pci:v00008086d000037D2sv000017AAsd00004024* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T + +pci:v00008086d000037D2sv000017AAsd00004025* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GBASE-T + +pci:v00008086d000037D3* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ + +pci:v00008086d000037D3sv00001590sd00000219* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ (Ethernet 10Gb 2-port 568FLR-MMSFP+ Adapter) + +pci:v00008086d000037D3sv000017AAsd00004020* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ + +pci:v00008086d000037D3sv000017AAsd00004021* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ + +pci:v00008086d000037D3sv000017AAsd00004025* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE SFP+ + +pci:v00008086d000037D4* + ID_MODEL_FROM_DATABASE=Ethernet Connection X722 for 10GbE QSFP+ + +pci:v00008086d000037D9* + ID_MODEL_FROM_DATABASE=X722 Hyper-V Virtual Function + +pci:v00008086d00003A00* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) 4-port SATA IDE Controller + +pci:v00008086d00003A02* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) SATA AHCI Controller + +pci:v00008086d00003A05* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) SATA RAID Controller + +pci:v00008086d00003A06* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) 2-port SATA IDE Controller + +pci:v00008086d00003A14* + ID_MODEL_FROM_DATABASE=82801JDO (ICH10DO) LPC Interface Controller + +pci:v00008086d00003A16* + ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller + +pci:v00008086d00003A16sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller (PowerEdge R410 LPC Interface Controller) + +pci:v00008086d00003A16sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller (PowerEdge T410 LPC Interface Controller) + +pci:v00008086d00003A16sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller (ProLiant G6 series) + +pci:v00008086d00003A16sv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller (P5Q Deluxe Motherboard) + +pci:v00008086d00003A16sv00001458sd00005001* + ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) LPC Interface Controller (GA-EP45-DS5 Motherboard) + +pci:v00008086d00003A18* + ID_MODEL_FROM_DATABASE=82801JIB (ICH10) LPC Interface Controller + +pci:v00008086d00003A1A* + ID_MODEL_FROM_DATABASE=82801JD (ICH10D) LPC Interface Controller + +pci:v00008086d00003A20* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 4 port SATA IDE Controller #1 + +pci:v00008086d00003A20sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 4 port SATA IDE Controller #1 (PowerEdge R410 SATA IDE Controller) + +pci:v00008086d00003A20sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 4 port SATA IDE Controller #1 (PowerEdge T410 SATA IDE Controller) + +pci:v00008086d00003A22* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SATA AHCI Controller + +pci:v00008086d00003A22sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SATA AHCI Controller (ProLiant G6 series) + +pci:v00008086d00003A22sv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SATA AHCI Controller (P5Q Deluxe Motherboard) + +pci:v00008086d00003A22sv00001458sd0000B005* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SATA AHCI Controller (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) + +pci:v00008086d00003A25* + ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) SATA RAID Controller + +pci:v00008086d00003A25sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) SATA RAID Controller (PERC S100 Controller (PE R410)) + +pci:v00008086d00003A25sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) SATA RAID Controller (PERC S100 Controller (PE T410)) + +pci:v00008086d00003A25sv00001028sd000002F1* + ID_MODEL_FROM_DATABASE=82801JIR (ICH10R) SATA RAID Controller (PERC S100 Controller (PE R510)) + +pci:v00008086d00003A26* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 2 port SATA IDE Controller #2 + +pci:v00008086d00003A26sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 2 port SATA IDE Controller #2 (PowerEdge R410 SATA IDE Controller) + +pci:v00008086d00003A26sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) 2 port SATA IDE Controller #2 (PowerEdge T410 SATA IDE Controller) + +pci:v00008086d00003A30* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SMBus Controller + +pci:v00008086d00003A30sv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SMBus Controller (P5Q Deluxe Motherboard) + +pci:v00008086d00003A30sv00001458sd00005001* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) SMBus Controller (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) + +pci:v00008086d00003A32* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) Thermal Subsystem + +pci:v00008086d00003A34* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 + +pci:v00008086d00003A34sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 (PowerEdge R410 USB UHCI Controller) + +pci:v00008086d00003A34sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 (PowerEdge T410 USB UHCI Controller) + +pci:v00008086d00003A34sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 (ProLiant G6 series) + +pci:v00008086d00003A34sv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 (P5Q Deluxe Motherboard) + +pci:v00008086d00003A34sv00001458sd00005004* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #1 (GA-EP45-DS5 Motherboard) + +pci:v00008086d00003A35* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 + +pci:v00008086d00003A35sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 (PowerEdge R410 USB UHCI Controller) + +pci:v00008086d00003A35sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 (PowerEdge T410 USB UHCI Controller) + +pci:v00008086d00003A35sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 (ProLiant G6 series) + +pci:v00008086d00003A35sv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 (P5Q Deluxe Motherboard) + +pci:v00008086d00003A35sv00001458sd00005004* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #2 (GA-EP45-DS5 Motherboard) + +pci:v00008086d00003A36* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 + +pci:v00008086d00003A36sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 (PowerEdge R410 USB UHCI Controller) + +pci:v00008086d00003A36sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 (PowerEdge T410 USB UHCI Controller) + +pci:v00008086d00003A36sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 (ProLiant G6 series) + +pci:v00008086d00003A36sv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 (P5Q Deluxe Motherboard) + +pci:v00008086d00003A36sv00001458sd00005004* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #3 (GA-EP45-DS5 Motherboard) + +pci:v00008086d00003A37* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 + +pci:v00008086d00003A37sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 (PowerEdge R410 USB UHCI Controller) + +pci:v00008086d00003A37sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 (PowerEdge T410 USB UHCI Controller) + +pci:v00008086d00003A37sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 (ProLiant G6 series) + +pci:v00008086d00003A37sv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 (P5Q Deluxe Motherboard) + +pci:v00008086d00003A37sv00001458sd00005004* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #4 (Motherboard) + +pci:v00008086d00003A38* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 + +pci:v00008086d00003A38sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 (PowerEdge R410 USB UHCI Controller) + +pci:v00008086d00003A38sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 (PowerEdge T410 USB UHCI Controller) + +pci:v00008086d00003A38sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 (ProLiant ML150 G6 Server) + +pci:v00008086d00003A38sv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 (P5Q Deluxe Motherboard) + +pci:v00008086d00003A38sv00001458sd00005004* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #5 (Motherboard) + +pci:v00008086d00003A39* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 + +pci:v00008086d00003A39sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 (PowerEdge R410 USB UHCI Controller) + +pci:v00008086d00003A39sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 (PowerEdge T410 USB UHCI Controller) + +pci:v00008086d00003A39sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 (ProLiant ML150 G6 Server) + +pci:v00008086d00003A39sv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 (P5Q Deluxe Motherboard) + +pci:v00008086d00003A39sv00001458sd00005004* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB UHCI Controller #6 (Motherboard) + +pci:v00008086d00003A3A* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 + +pci:v00008086d00003A3Asv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 (PowerEdge R410 USB EHCI Controller) + +pci:v00008086d00003A3Asv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 (PowerEdge T410 USB EHCI Controller) + +pci:v00008086d00003A3Asv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 (ProLiant G6 series) + +pci:v00008086d00003A3Asv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 (P5Q Deluxe Motherboard) + +pci:v00008086d00003A3Asv00001458sd00005006* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #1 (GA-EP45-DS5 Motherboard) + +pci:v00008086d00003A3C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 + +pci:v00008086d00003A3Csv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 (PowerEdge R410 USB EHCI Controller) + +pci:v00008086d00003A3Csv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 (PowerEdge T410 USB EHCI Controller) + +pci:v00008086d00003A3Csv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 (ProLiant G6 series) + +pci:v00008086d00003A3Csv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 (P5Q Deluxe Motherboard) + +pci:v00008086d00003A3Csv00001458sd00005006* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) USB2 EHCI Controller #2 (Motherboard) + +pci:v00008086d00003A3E* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) HD Audio Controller + +pci:v00008086d00003A3Esv00001043sd00008311* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) HD Audio Controller (P5Q Deluxe Motherboard) + +pci:v00008086d00003A3Esv00001458sd0000A002* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) HD Audio Controller (GA-EP45-UD3R Motherboard) + +pci:v00008086d00003A3Esv00001458sd0000A102* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) HD Audio Controller (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) + +pci:v00008086d00003A40* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 + +pci:v00008086d00003A40sv00001028sd0000028C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (PowerEdge R410 PCI Express Port 1) + +pci:v00008086d00003A40sv00001028sd0000028D* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (PowerEdge T410 PCI Express Port 1) + +pci:v00008086d00003A40sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (ProLiant ML150 G6 Server) + +pci:v00008086d00003A40sv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (P5Q Deluxe Motherboard) + +pci:v00008086d00003A40sv00001043sd000082EA* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (P6T DeLuxe Motherboard) + +pci:v00008086d00003A40sv00001458sd00005001* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 1 (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) + +pci:v00008086d00003A42* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Port 2 + +pci:v00008086d00003A44* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 3 + +pci:v00008086d00003A44sv00001043sd000082EA* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 3 (P6T DeLuxe Motherboard) + +pci:v00008086d00003A46* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 4 + +pci:v00008086d00003A46sv00001043sd000082EA* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 4 (P6T DeLuxe Motherboard) + +pci:v00008086d00003A46sv00001458sd00005001* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 4 (GA-EP45-DS5 Motherboard) + +pci:v00008086d00003A48* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 5 + +pci:v00008086d00003A48sv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 5 (ProLiant ML150 G6 Server) + +pci:v00008086d00003A48sv00001043sd000082EA* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 5 (P6T Deluxe Motherboard) + +pci:v00008086d00003A48sv00001458sd00005001* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 5 (GA-EP45-DS5 Motherboard) + +pci:v00008086d00003A4A* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 6 + +pci:v00008086d00003A4Asv0000103Csd0000330B* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 6 (ProLiant ML150 G6 Server) + +pci:v00008086d00003A4Asv00001043sd000082D4* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 6 (P5Q Deluxe Motherboard) + +pci:v00008086d00003A4Asv00001043sd000082EA* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 6 (P6T DeLuxe Motherboard) + +pci:v00008086d00003A4Asv00001458sd00005001* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) PCI Express Root Port 6 (GA-EP45-DS5/GA-EG45M-DS2H Motherboard) + +pci:v00008086d00003A4C* + ID_MODEL_FROM_DATABASE=82801JI (ICH10 Family) Gigabit Ethernet Controller + +pci:v00008086d00003A51* + ID_MODEL_FROM_DATABASE=82801JDO (ICH10DO) VECI Controller + +pci:v00008086d00003A55* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) Virtual SATA Controller + +pci:v00008086d00003A60* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) SMBus Controller + +pci:v00008086d00003A62* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) Thermal Subsystem + +pci:v00008086d00003A64* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #1 + +pci:v00008086d00003A65* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #2 + +pci:v00008086d00003A66* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #3 + +pci:v00008086d00003A67* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #4 + +pci:v00008086d00003A68* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #5 + +pci:v00008086d00003A69* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB UHCI Controller #6 + +pci:v00008086d00003A6A* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB2 EHCI Controller #1 + +pci:v00008086d00003A6C* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) USB2 EHCI Controller #2 + +pci:v00008086d00003A6E* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) HD Audio Controller + +pci:v00008086d00003A70* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 1 + +pci:v00008086d00003A72* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 2 + +pci:v00008086d00003A74* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 3 + +pci:v00008086d00003A76* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 4 + +pci:v00008086d00003A78* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 5 + +pci:v00008086d00003A7A* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) PCI Express Port 6 + +pci:v00008086d00003A7C* + ID_MODEL_FROM_DATABASE=82801JD/DO (ICH10 Family) Gigabit Ethernet Controller + +pci:v00008086d00003B00* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B01* + ID_MODEL_FROM_DATABASE=Mobile 5 Series Chipset LPC Interface Controller + +pci:v00008086d00003B02* + ID_MODEL_FROM_DATABASE=P55 Chipset LPC Interface Controller + +pci:v00008086d00003B03* + ID_MODEL_FROM_DATABASE=PM55 Chipset LPC Interface Controller + +pci:v00008086d00003B04* + ID_MODEL_FROM_DATABASE=5 Series Chipset LPC Interface Controller + +pci:v00008086d00003B05* + ID_MODEL_FROM_DATABASE=Mobile 5 Series Chipset LPC Interface Controller + +pci:v00008086d00003B06* + ID_MODEL_FROM_DATABASE=H55 Chipset LPC Interface Controller + +pci:v00008086d00003B07* + ID_MODEL_FROM_DATABASE=QM57 Chipset LPC Interface Controller + +pci:v00008086d00003B07sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=QM57 Chipset LPC Interface Controller (Latitude E6410) + +pci:v00008086d00003B07sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=QM57 Chipset LPC Interface Controller (Latitude E6510) + +pci:v00008086d00003B07sv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=QM57 Chipset LPC Interface Controller (PC1-GROOVE) + +pci:v00008086d00003B08* + ID_MODEL_FROM_DATABASE=H57 Chipset LPC Interface Controller + +pci:v00008086d00003B09* + ID_MODEL_FROM_DATABASE=HM55 Chipset LPC Interface Controller + +pci:v00008086d00003B09sv00001025sd00000347* + ID_MODEL_FROM_DATABASE=HM55 Chipset LPC Interface Controller (Aspire 7740G) + +pci:v00008086d00003B09sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=HM55 Chipset LPC Interface Controller (R730 Laptop) + +pci:v00008086d00003B09sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=HM55 Chipset LPC Interface Controller (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B0A* + ID_MODEL_FROM_DATABASE=Q57 Chipset LPC Interface Controller + +pci:v00008086d00003B0Asv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=Q57 Chipset LPC Interface Controller (OptiPlex 980) + +pci:v00008086d00003B0Asv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=Q57 Chipset LPC Interface Controller (C7SIM-Q Motherboard) + +pci:v00008086d00003B0B* + ID_MODEL_FROM_DATABASE=HM57 Chipset LPC Interface Controller + +pci:v00008086d00003B0C* + ID_MODEL_FROM_DATABASE=5 Series Chipset LPC Interface Controller + +pci:v00008086d00003B0D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B0E* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B0F* + ID_MODEL_FROM_DATABASE=QS57 Chipset LPC Interface Controller + +pci:v00008086d00003B10* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B11* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B12* + ID_MODEL_FROM_DATABASE=3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B13* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B14* + ID_MODEL_FROM_DATABASE=3420 Chipset LPC Interface Controller + +pci:v00008086d00003B14sv000015D9sd00000605* + ID_MODEL_FROM_DATABASE=3420 Chipset LPC Interface Controller (X8SIL) + +pci:v00008086d00003B15* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B16* + ID_MODEL_FROM_DATABASE=3450 Chipset LPC Interface Controller + +pci:v00008086d00003B17* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B18* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B19* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B1A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B1B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B1C* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B1D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B1E* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B1F* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LPC Interface Controller + +pci:v00008086d00003B20* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller + +pci:v00008086d00003B21* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller + +pci:v00008086d00003B22* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller + +pci:v00008086d00003B22sv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (OptiPlex 980) + +pci:v00008086d00003B22sv000015D9sd00000605* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (X8SIL) + +pci:v00008086d00003B22sv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (C7SIM-Q Motherboard) + +pci:v00008086d00003B23* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA AHCI Controller + +pci:v00008086d00003B25* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SATA RAID Controller + +pci:v00008086d00003B25sv0000103Csd00003118* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SATA RAID Controller (Smart Array B110i SATA RAID Controller) + +pci:v00008086d00003B26* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller + +pci:v00008086d00003B28* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller + +pci:v00008086d00003B28sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller (R730 Laptop) + +pci:v00008086d00003B28sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B29* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA AHCI Controller + +pci:v00008086d00003B29sv00001025sd00000347* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA AHCI Controller (Aspire 7740G) + +pci:v00008086d00003B29sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA AHCI Controller (R730 Laptop) + +pci:v00008086d00003B29sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA AHCI Controller (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B2C* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SATA RAID Controller + +pci:v00008086d00003B2D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller + +pci:v00008086d00003B2Dsv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller (R730 Laptop) + +pci:v00008086d00003B2Dsv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B2Dsv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 2 port SATA IDE Controller (PC1-GROOVE) + +pci:v00008086d00003B2E* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller + +pci:v00008086d00003B2Esv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 4 port SATA IDE Controller (PC1-GROOVE) + +pci:v00008086d00003B2F* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller + +pci:v00008086d00003B2Fsv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (Latitude E6410) + +pci:v00008086d00003B2Fsv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (Latitude E6510) + +pci:v00008086d00003B2Fsv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset 6 port SATA AHCI Controller (PC1-GROOVE) + +pci:v00008086d00003B30* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller + +pci:v00008086d00003B30sv00001025sd00000347* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (Aspire 7740G) + +pci:v00008086d00003B30sv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (OptiPlex 980) + +pci:v00008086d00003B30sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (Latitude E6410) + +pci:v00008086d00003B30sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (Latitude E6510) + +pci:v00008086d00003B30sv00001043sd00003838* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (P7P55-M Motherboard) + +pci:v00008086d00003B30sv00001043sd00008383* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (P7P55-M Motherboard) + +pci:v00008086d00003B30sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (R730 Laptop) + +pci:v00008086d00003B30sv000015D9sd00000605* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (X8SIL) + +pci:v00008086d00003B30sv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (C7SIM-Q Motherboard) + +pci:v00008086d00003B30sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B30sv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset SMBus Controller (PC1-GROOVE) + +pci:v00008086d00003B32* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset Thermal Subsystem + +pci:v00008086d00003B32sv00001025sd00000347* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset Thermal Subsystem (Aspire 7740G) + +pci:v00008086d00003B32sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset Thermal Subsystem (Latitude E6410) + +pci:v00008086d00003B32sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset Thermal Subsystem (R730 Laptop) + +pci:v00008086d00003B32sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset Thermal Subsystem (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B34* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller + +pci:v00008086d00003B34sv00001025sd00000347* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Aspire 7740G) + +pci:v00008086d00003B34sv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (OptiPlex 980) + +pci:v00008086d00003B34sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Latitude E6410) + +pci:v00008086d00003B34sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Latitude E6510) + +pci:v00008086d00003B34sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (R730 Laptop) + +pci:v00008086d00003B34sv000015D9sd00000605* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (X8SIL) + +pci:v00008086d00003B34sv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (C7SIM-Q Motherboard) + +pci:v00008086d00003B34sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B34sv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (PC1-GROOVE) + +pci:v00008086d00003B36* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller + +pci:v00008086d00003B37* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller + +pci:v00008086d00003B38* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller + +pci:v00008086d00003B39* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller + +pci:v00008086d00003B3A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller + +pci:v00008086d00003B3B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller + +pci:v00008086d00003B3C* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller + +pci:v00008086d00003B3Csv00001025sd00000347* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Aspire 7740G) + +pci:v00008086d00003B3Csv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (OptiPlex 980) + +pci:v00008086d00003B3Csv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Latitude E6410) + +pci:v00008086d00003B3Csv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Latitude E6510) + +pci:v00008086d00003B3Csv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (R730 Laptop) + +pci:v00008086d00003B3Csv000015D9sd00000605* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (X8SIL) + +pci:v00008086d00003B3Csv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (C7SIM-Q Motherboard) + +pci:v00008086d00003B3Csv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B3Csv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller (PC1-GROOVE) + +pci:v00008086d00003B3E* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller + +pci:v00008086d00003B3F* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller + +pci:v00008086d00003B40* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB Universal Host Controller + +pci:v00008086d00003B41* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset LAN Controller + +pci:v00008086d00003B42* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 + +pci:v00008086d00003B42sv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (OptiPlex 980) + +pci:v00008086d00003B42sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (Latitude E6410) + +pci:v00008086d00003B42sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (Latitude E6510) + +pci:v00008086d00003B42sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (R730 Laptop) + +pci:v00008086d00003B42sv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (C7SIM-Q Motherboard) + +pci:v00008086d00003B42sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 1 (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B44* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 2 + +pci:v00008086d00003B44sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 2 (Latitude E6410) + +pci:v00008086d00003B44sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 2 (Latitude E6510) + +pci:v00008086d00003B44sv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 2 (C7SIM-Q Motherboard) + +pci:v00008086d00003B44sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 2 (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B46* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 3 + +pci:v00008086d00003B46sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 3 (Latitude E6410) + +pci:v00008086d00003B46sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 3 (Latitude E6510) + +pci:v00008086d00003B46sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 3 (R730 Laptop) + +pci:v00008086d00003B46sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 3 (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B48* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 4 + +pci:v00008086d00003B48sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 4 (Latitude E6410) + +pci:v00008086d00003B48sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 4 (Latitude E6510) + +pci:v00008086d00003B48sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 4 (R730 Laptop) + +pci:v00008086d00003B4A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 5 + +pci:v00008086d00003B4Asv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 5 (OptiPlex 980) + +pci:v00008086d00003B4Asv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 5 (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B4C* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 6 + +pci:v00008086d00003B4E* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 7 + +pci:v00008086d00003B50* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PCI Express Root Port 8 + +pci:v00008086d00003B53* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset VECI Controller + +pci:v00008086d00003B56* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio + +pci:v00008086d00003B56sv00001025sd00000347* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (Aspire 7740G) + +pci:v00008086d00003B56sv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (OptiPlex 980) + +pci:v00008086d00003B56sv00001028sd0000040A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (Latitude E6410) + +pci:v00008086d00003B56sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (Latitude E6510) + +pci:v00008086d00003B56sv00001043sd00001373* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (G73-series gaming laptop) + +pci:v00008086d00003B56sv0000144Dsd0000C06A* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (R730 Laptop) + +pci:v00008086d00003B56sv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (C7SIM-Q Motherboard) + +pci:v00008086d00003B56sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B56sv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio (PC1-GROOVE) + +pci:v00008086d00003B57* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset High Definition Audio + +pci:v00008086d00003B64* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller + +pci:v00008086d00003B64sv00001025sd00000347* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller (Aspire 7740G) + +pci:v00008086d00003B64sv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller (C7SIM-Q Motherboard) + +pci:v00008086d00003B64sv000017C0sd000010D2* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller (Medion Akoya E7214 Notebook PC [MD98410]) + +pci:v00008086d00003B64sv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller (PC1-GROOVE) + +pci:v00008086d00003B65* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset HECI Controller + +pci:v00008086d00003B66* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset PT IDER Controller + +pci:v00008086d00003B67* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset KT Controller + +pci:v00008086d00003B67sv0000E4BFsd000050C1* + ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset KT Controller (PC1-GROOVE) + +pci:v00008086d00003C00* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMI2 + +pci:v00008086d00003C01* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMI2 in PCI Express Mode + +pci:v00008086d00003C02* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 1a + +pci:v00008086d00003C03* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 1b + +pci:v00008086d00003C04* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 2a + +pci:v00008086d00003C05* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 2b + +pci:v00008086d00003C06* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 2c + +pci:v00008086d00003C07* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 2d + +pci:v00008086d00003C08* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 3a in PCI Express Mode + +pci:v00008086d00003C09* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 3b + +pci:v00008086d00003C0A* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 3c + +pci:v00008086d00003C0B* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO PCI Express Root Port 3d + +pci:v00008086d00003C0D* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Non-Transparent Bridge + +pci:v00008086d00003C0E* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Non-Transparent Bridge + +pci:v00008086d00003C0F* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Non-Transparent Bridge + +pci:v00008086d00003C20* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 0 + +pci:v00008086d00003C21* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 1 + +pci:v00008086d00003C22* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 2 + +pci:v00008086d00003C23* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 3 + +pci:v00008086d00003C24* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 4 + +pci:v00008086d00003C25* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 5 + +pci:v00008086d00003C26* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 6 + +pci:v00008086d00003C27* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA Channel 7 + +pci:v00008086d00003C28* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Address Map, VTd_Misc, System Management + +pci:v00008086d00003C2A* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Control Status and Global Errors + +pci:v00008086d00003C2C* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 I/O APIC + +pci:v00008086d00003C2E* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA + +pci:v00008086d00003C2F* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DMA + +pci:v00008086d00003C40* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 IIO Switch and IRP Performance Monitor + +pci:v00008086d00003C43* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Ring to PCI Express Performance Monitor + +pci:v00008086d00003C44* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Ring to QuickPath Interconnect Link 0 Performance Monitor + +pci:v00008086d00003C45* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Ring to QuickPath Interconnect Link 1 Performance Monitor + +pci:v00008086d00003C46* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Processor Home Agent Performance Monitoring + +pci:v00008086d00003C71* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller RAS Registers + +pci:v00008086d00003C80* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link 0 + +pci:v00008086d00003C83* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link Reut 0 + +pci:v00008086d00003C84* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link Reut 0 + +pci:v00008086d00003C90* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link 1 + +pci:v00008086d00003C93* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link Reut 1 + +pci:v00008086d00003C94* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QPI Link Reut 1 + +pci:v00008086d00003CA0* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Processor Home Agent + +pci:v00008086d00003CA8* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Registers + +pci:v00008086d00003CAA* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 0 + +pci:v00008086d00003CAB* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 1 + +pci:v00008086d00003CAC* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 2 + +pci:v00008086d00003CAD* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 3 + +pci:v00008086d00003CAE* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 4 + +pci:v00008086d00003CB0* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 0 + +pci:v00008086d00003CB1* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 1 + +pci:v00008086d00003CB2* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 0 + +pci:v00008086d00003CB3* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 1 + +pci:v00008086d00003CB4* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 2 + +pci:v00008086d00003CB5* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 3 + +pci:v00008086d00003CB6* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 2 + +pci:v00008086d00003CB7* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 3 + +pci:v00008086d00003CB8* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 DDRIO + +pci:v00008086d00003CC0* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Power Control Unit 0 + +pci:v00008086d00003CC1* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Power Control Unit 1 + +pci:v00008086d00003CC2* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Power Control Unit 2 + +pci:v00008086d00003CD0* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Power Control Unit 3 + +pci:v00008086d00003CE0* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Interrupt Control Registers + +pci:v00008086d00003CE3* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Semaphore and Scratchpad Configuration Registers + +pci:v00008086d00003CE4* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 R2PCIe + +pci:v00008086d00003CE6* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 QuickPath Interconnect Agent Ring Registers + +pci:v00008086d00003CE8* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 0 + +pci:v00008086d00003CE9* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 5 + +pci:v00008086d00003CEA* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 1 + +pci:v00008086d00003CEB* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 6 + +pci:v00008086d00003CEC* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 3 + +pci:v00008086d00003CED* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 7 + +pci:v00008086d00003CEE* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 4 + +pci:v00008086d00003CEF* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Unicast Register 8 + +pci:v00008086d00003CF4* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller System Address Decoder 0 + +pci:v00008086d00003CF5* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 Integrated Memory Controller System Address Decoder 1 + +pci:v00008086d00003CF6* + ID_MODEL_FROM_DATABASE=Xeon E5/Core i7 System Address Decoder + +pci:v00008086d00003E10* + ID_MODEL_FROM_DATABASE=8th Gen Core 4-core Processor Host Bridge/DRAM Registers [Coffee Lake H] + +pci:v00008086d00003E18* + ID_MODEL_FROM_DATABASE=8th Gen Core 4-core Workstation Processor Host Bridge/DRAM Registers [Coffee Lake S] + +pci:v00008086d00003E1F* + ID_MODEL_FROM_DATABASE=8th Gen Core 4-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S] + +pci:v00008086d00003E1Fsv00001458sd00005000* + ID_MODEL_FROM_DATABASE=8th Gen Core 4-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S] (Z370 AORUS Gaming K3-CF) + +pci:v00008086d00003E30* + ID_MODEL_FROM_DATABASE=8th Gen Core 8-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S] + +pci:v00008086d00003E33* + ID_MODEL_FROM_DATABASE=8th/9th Gen Core Processor Host Bridge/DRAM Registers [Coffee Lake] + +pci:v00008086d00003E34* + ID_MODEL_FROM_DATABASE=Coffee Lake HOST and DRAM Controller + +pci:v00008086d00003E81* + ID_MODEL_FROM_DATABASE=8th Gen Core Processor PCIe Controller (x16) + +pci:v00008086d00003E85* + ID_MODEL_FROM_DATABASE=8th Gen Core Processor PCIe Controller (x8) + +pci:v00008086d00003E89* + ID_MODEL_FROM_DATABASE=8th Gen Core Processor PCIe Controller (x4) + +pci:v00008086d00003E91* + ID_MODEL_FROM_DATABASE=8th Gen Core Processor Gaussian Mixture Model + +pci:v00008086d00003E92* + ID_MODEL_FROM_DATABASE=UHD Graphics 630 (Desktop) + +pci:v00008086d00003E93* + ID_MODEL_FROM_DATABASE=UHD Graphics 610 + +pci:v00008086d00003E96* + ID_MODEL_FROM_DATABASE=HD Graphics P630 + +pci:v00008086d00003E98* + ID_MODEL_FROM_DATABASE=UHD Graphics 630 (Desktop 9 Series) + +pci:v00008086d00003E9B* + ID_MODEL_FROM_DATABASE=UHD Graphics 630 (Mobile) + +pci:v00008086d00003EA0* + ID_MODEL_FROM_DATABASE=UHD Graphics 620 (Whiskey Lake) + +pci:v00008086d00003EA0sv00001028sd0000089E* + ID_MODEL_FROM_DATABASE=UHD Graphics 620 (Whiskey Lake) (Inspiron 5482) + +pci:v00008086d00003EA5* + ID_MODEL_FROM_DATABASE=Iris Plus Graphics 655 + +pci:v00008086d00003EC2* + ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00003EC2sv00001043sd00008694* + ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers (PRIME H310M-D) + +pci:v00008086d00003EC4* + ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00003EC6* + ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00003ECA* + ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00003ED0* + ID_MODEL_FROM_DATABASE=8th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00004000* + ID_MODEL_FROM_DATABASE=5400 Chipset Memory Controller Hub + +pci:v00008086d00004001* + ID_MODEL_FROM_DATABASE=5400 Chipset Memory Controller Hub + +pci:v00008086d00004003* + ID_MODEL_FROM_DATABASE=5400 Chipset Memory Controller Hub + +pci:v00008086d00004021* + ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 1 + +pci:v00008086d00004022* + ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 2 + +pci:v00008086d00004023* + ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 3 + +pci:v00008086d00004024* + ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 4 + +pci:v00008086d00004025* + ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 5 + +pci:v00008086d00004026* + ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 6 + +pci:v00008086d00004027* + ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 7 + +pci:v00008086d00004028* + ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 8 + +pci:v00008086d00004029* + ID_MODEL_FROM_DATABASE=5400 Chipset PCI Express Port 9 + +pci:v00008086d0000402D* + ID_MODEL_FROM_DATABASE=5400 Chipset IBIST Registers + +pci:v00008086d0000402E* + ID_MODEL_FROM_DATABASE=5400 Chipset IBIST Registers + +pci:v00008086d0000402F* + ID_MODEL_FROM_DATABASE=5400 Chipset QuickData Technology Device + +pci:v00008086d00004030* + ID_MODEL_FROM_DATABASE=5400 Chipset FSB Registers + +pci:v00008086d00004031* + ID_MODEL_FROM_DATABASE=5400 Chipset CE/SF Registers + +pci:v00008086d00004032* + ID_MODEL_FROM_DATABASE=5400 Chipset IOxAPIC + +pci:v00008086d00004035* + ID_MODEL_FROM_DATABASE=5400 Chipset FBD Registers + +pci:v00008086d00004036* + ID_MODEL_FROM_DATABASE=5400 Chipset FBD Registers + +pci:v00008086d00004100* + ID_MODEL_FROM_DATABASE=Moorestown Graphics and Video + +pci:v00008086d00004108* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller + +pci:v00008086d00004109* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller + +pci:v00008086d0000410A* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller + +pci:v00008086d0000410B* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller + +pci:v00008086d0000410C* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller + +pci:v00008086d0000410D* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller + +pci:v00008086d0000410E* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller + +pci:v00008086d0000410F* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller + +pci:v00008086d00004114* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Host Bridge #1 + +pci:v00008086d00004115* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Host Bridge #2 + +pci:v00008086d00004116* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Host Bridge #3 + +pci:v00008086d00004117* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Host Bridge #4 + +pci:v00008086d00004220* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection + +pci:v00008086d00004220sv0000103Csd00000934* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (Compaq nw8240/nx8220) + +pci:v00008086d00004220sv0000103Csd000012F6* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (nc6120/nc6220/nw8240/nx8220) + +pci:v00008086d00004220sv00008086sd00002701* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (WM3B2200BG Mini-PCI Card) + +pci:v00008086d00004220sv00008086sd00002712* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (IBM ThinkPad R50e) + +pci:v00008086d00004220sv00008086sd00002721* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (Dell B130 laptop integrated WLAN) + +pci:v00008086d00004220sv00008086sd00002722* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (Dell Latitude D600) + +pci:v00008086d00004220sv00008086sd00002731* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2200BG [Calexico2] Network Connection (Samsung P35 integrated WLAN) + +pci:v00008086d00004222* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection + +pci:v00008086d00004222sv0000103Csd0000135C* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection + +pci:v00008086d00004222sv00008086sd00001000* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945ABG Network Connection) + +pci:v00008086d00004222sv00008086sd00001001* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (WM3945ABG MOW2) + +pci:v00008086d00004222sv00008086sd00001005* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945BG Network Connection) + +pci:v00008086d00004222sv00008086sd00001034* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945BG Network Connection) + +pci:v00008086d00004222sv00008086sd00001044* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945BG Network Connection) + +pci:v00008086d00004222sv00008086sd00001C00* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945ABG Network Connection) + +pci:v00008086d00004223* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection + +pci:v00008086d00004223sv00001000sd00008086* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (mPCI 3B Americas/Europe ZZA) + +pci:v00008086d00004223sv00001001sd00008086* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (mPCI 3B Europe ZZE) + +pci:v00008086d00004223sv00001002sd00008086* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (mPCI 3B Japan ZZJ) + +pci:v00008086d00004223sv00001003sd00008086* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (mPCI 3B High-Band ZZH) + +pci:v00008086d00004223sv0000103Csd00001351* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection (Compaq nc6220) + +pci:v00008086d00004224* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2915ABG [Calexico2] Network Connection + +pci:v00008086d00004227* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection + +pci:v00008086d00004227sv00008086sd00001010* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (ThinkPad R60e) + +pci:v00008086d00004227sv00008086sd00001011* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (ThinkPad T60/R60e/X60s/R61) + +pci:v00008086d00004227sv00008086sd00001014* + ID_MODEL_FROM_DATABASE=PRO/Wireless 3945ABG [Golan] Network Connection (PRO/Wireless 3945BG Network Connection) + +pci:v00008086d00004229* + ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection + +pci:v00008086d00004229sv00008086sd00001100* + ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection (Vaio VGN-SZ79SN_C) + +pci:v00008086d00004229sv00008086sd00001101* + ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection (PRO/Wireless 4965 AG or AGN) + +pci:v00008086d0000422B* + ID_MODEL_FROM_DATABASE=Centrino Ultimate-N 6300 + +pci:v00008086d0000422Bsv00008086sd00001101* + ID_MODEL_FROM_DATABASE=Centrino Ultimate-N 6300 (3x3 AGN) + +pci:v00008086d0000422Bsv00008086sd00001121* + ID_MODEL_FROM_DATABASE=Centrino Ultimate-N 6300 (3x3 AGN) + +pci:v00008086d0000422C* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 + +pci:v00008086d0000422Csv00008086sd00001301* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 AGN) + +pci:v00008086d0000422Csv00008086sd00001306* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 ABG) + +pci:v00008086d0000422Csv00008086sd00001307* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 BG) + +pci:v00008086d0000422Csv00008086sd00001321* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 AGN) + +pci:v00008086d0000422Csv00008086sd00001326* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 ABG) + +pci:v00008086d00004230* + ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection + +pci:v00008086d00004230sv00008086sd00001110* + ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection (Lenovo ThinkPad T51) + +pci:v00008086d00004230sv00008086sd00001111* + ID_MODEL_FROM_DATABASE=PRO/Wireless 4965 AG or AGN [Kedron] Network Connection (Lenovo ThinkPad T61) + +pci:v00008086d00004232* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 + +pci:v00008086d00004232sv00008086sd00001201* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) + +pci:v00008086d00004232sv00008086sd00001204* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) + +pci:v00008086d00004232sv00008086sd00001205* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (BGN) + +pci:v00008086d00004232sv00008086sd00001206* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (ABG) + +pci:v00008086d00004232sv00008086sd00001221* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) + +pci:v00008086d00004232sv00008086sd00001224* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) + +pci:v00008086d00004232sv00008086sd00001225* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (BGN) + +pci:v00008086d00004232sv00008086sd00001226* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (ABG) + +pci:v00008086d00004232sv00008086sd00001301* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) + +pci:v00008086d00004232sv00008086sd00001304* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) + +pci:v00008086d00004232sv00008086sd00001305* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (BGN) + +pci:v00008086d00004232sv00008086sd00001306* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (ABG) + +pci:v00008086d00004232sv00008086sd00001321* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) + +pci:v00008086d00004232sv00008086sd00001324* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (AGN) + +pci:v00008086d00004232sv00008086sd00001325* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (BGN) + +pci:v00008086d00004232sv00008086sd00001326* + ID_MODEL_FROM_DATABASE=WiFi Link 5100 (ABG) + +pci:v00008086d00004235* + ID_MODEL_FROM_DATABASE=Ultimate N WiFi Link 5300 + +pci:v00008086d00004236* + ID_MODEL_FROM_DATABASE=Ultimate N WiFi Link 5300 + +pci:v00008086d00004237* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection + +pci:v00008086d00004237sv00008086sd00001211* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 AGN) + +pci:v00008086d00004237sv00008086sd00001214* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 AGN) + +pci:v00008086d00004237sv00008086sd00001215* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 BGN) + +pci:v00008086d00004237sv00008086sd00001216* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 ABG) + +pci:v00008086d00004237sv00008086sd00001311* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 AGN) + +pci:v00008086d00004237sv00008086sd00001314* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 AGN) + +pci:v00008086d00004237sv00008086sd00001315* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 BGN) + +pci:v00008086d00004237sv00008086sd00001316* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5100 AGN [Shiloh] Network Connection (WiFi Link 5100 ABG) + +pci:v00008086d00004238* + ID_MODEL_FROM_DATABASE=Centrino Ultimate-N 6300 + +pci:v00008086d00004238sv00008086sd00001111* + ID_MODEL_FROM_DATABASE=Centrino Ultimate-N 6300 (3x3 AGN) + +pci:v00008086d00004239* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 + +pci:v00008086d00004239sv00008086sd00001311* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 AGN) + +pci:v00008086d00004239sv00008086sd00001316* + ID_MODEL_FROM_DATABASE=Centrino Advanced-N 6200 (2x2 ABG) + +pci:v00008086d0000423A* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5350 AGN [Echo Peak] Network Connection + +pci:v00008086d0000423B* + ID_MODEL_FROM_DATABASE=PRO/Wireless 5350 AGN [Echo Peak] Network Connection + +pci:v00008086d0000423C* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 + +pci:v00008086d0000423Csv00008086sd00001201* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) + +pci:v00008086d0000423Csv00008086sd00001206* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (ABG) + +pci:v00008086d0000423Csv00008086sd00001221* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) + +pci:v00008086d0000423Csv00008086sd00001301* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) + +pci:v00008086d0000423Csv00008086sd00001306* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (ABG) + +pci:v00008086d0000423Csv00008086sd00001321* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) + +pci:v00008086d0000423D* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 + +pci:v00008086d0000423Dsv00008086sd00001211* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) + +pci:v00008086d0000423Dsv00008086sd00001216* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (ABG) + +pci:v00008086d0000423Dsv00008086sd00001311* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (AGN) + +pci:v00008086d0000423Dsv00008086sd00001316* + ID_MODEL_FROM_DATABASE=WiMAX/WiFi Link 5150 (ABG) + +pci:v00008086d0000444E* + ID_MODEL_FROM_DATABASE=Turbo Memory Controller + +pci:v00008086d0000467F* + ID_MODEL_FROM_DATABASE=Volume Management Device NVMe RAID Controller + +pci:v00008086d00004C3D* + ID_MODEL_FROM_DATABASE=Volume Management Device NVMe RAID Controller + +pci:v00008086d00005001* + ID_MODEL_FROM_DATABASE=LE80578 + +pci:v00008086d00005002* + ID_MODEL_FROM_DATABASE=LE80578 Graphics Processor Unit + +pci:v00008086d00005009* + ID_MODEL_FROM_DATABASE=LE80578 Video Display Controller + +pci:v00008086d0000500D* + ID_MODEL_FROM_DATABASE=LE80578 Expansion Bus + +pci:v00008086d0000500E* + ID_MODEL_FROM_DATABASE=LE80578 UART Controller + +pci:v00008086d0000500F* + ID_MODEL_FROM_DATABASE=LE80578 General Purpose IO + +pci:v00008086d00005010* + ID_MODEL_FROM_DATABASE=LE80578 I2C Controller + +pci:v00008086d00005012* + ID_MODEL_FROM_DATABASE=LE80578 Serial Peripheral Interface Bus + +pci:v00008086d00005020* + ID_MODEL_FROM_DATABASE=EP80579 Memory Controller Hub + +pci:v00008086d00005021* + ID_MODEL_FROM_DATABASE=EP80579 DRAM Error Reporting Registers + +pci:v00008086d00005023* + ID_MODEL_FROM_DATABASE=EP80579 EDMA Controller + +pci:v00008086d00005024* + ID_MODEL_FROM_DATABASE=EP80579 PCI Express Port PEA0 + +pci:v00008086d00005025* + ID_MODEL_FROM_DATABASE=EP80579 PCI Express Port PEA1 + +pci:v00008086d00005028* + ID_MODEL_FROM_DATABASE=EP80579 S-ATA IDE + +pci:v00008086d00005029* + ID_MODEL_FROM_DATABASE=EP80579 S-ATA AHCI + +pci:v00008086d0000502A* + ID_MODEL_FROM_DATABASE=EP80579 S-ATA Reserved + +pci:v00008086d0000502B* + ID_MODEL_FROM_DATABASE=EP80579 S-ATA Reserved + +pci:v00008086d0000502C* + ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor ASU + +pci:v00008086d0000502D* + ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor with QuickAssist ASU + +pci:v00008086d0000502E* + ID_MODEL_FROM_DATABASE=EP80579 Reserved + +pci:v00008086d0000502F* + ID_MODEL_FROM_DATABASE=EP80579 Reserved + +pci:v00008086d00005030* + ID_MODEL_FROM_DATABASE=EP80579 Reserved + +pci:v00008086d00005031* + ID_MODEL_FROM_DATABASE=EP80579 LPC Bus + +pci:v00008086d00005032* + ID_MODEL_FROM_DATABASE=EP80579 SMBus Controller + +pci:v00008086d00005033* + ID_MODEL_FROM_DATABASE=EP80579 USB 1.1 Controller + +pci:v00008086d00005035* + ID_MODEL_FROM_DATABASE=EP80579 USB 2.0 Controller + +pci:v00008086d00005037* + ID_MODEL_FROM_DATABASE=EP80579 PCI-PCI Bridge (transparent mode) + +pci:v00008086d00005039* + ID_MODEL_FROM_DATABASE=EP80579 Controller Area Network (CAN) interface #1 + +pci:v00008086d0000503A* + ID_MODEL_FROM_DATABASE=EP80579 Controller Area Network (CAN) interface #2 + +pci:v00008086d0000503B* + ID_MODEL_FROM_DATABASE=EP80579 Synchronous Serial Port (SPP) + +pci:v00008086d0000503C* + ID_MODEL_FROM_DATABASE=EP80579 IEEE 1588 Hardware Assist + +pci:v00008086d0000503D* + ID_MODEL_FROM_DATABASE=EP80579 Local Expansion Bus + +pci:v00008086d0000503E* + ID_MODEL_FROM_DATABASE=EP80579 Global Control Unit (GCU) + +pci:v00008086d0000503F* + ID_MODEL_FROM_DATABASE=EP80579 Reserved + +pci:v00008086d00005040* + ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor Gigabit Ethernet MAC + +pci:v00008086d00005041* + ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC + +pci:v00008086d00005042* + ID_MODEL_FROM_DATABASE=EP80579 Reserved + +pci:v00008086d00005043* + ID_MODEL_FROM_DATABASE=EP80579 Reserved + +pci:v00008086d00005044* + ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor Gigabit Ethernet MAC + +pci:v00008086d00005045* + ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC + +pci:v00008086d00005046* + ID_MODEL_FROM_DATABASE=EP80579 Reserved + +pci:v00008086d00005047* + ID_MODEL_FROM_DATABASE=EP80579 Reserved + +pci:v00008086d00005048* + ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor Gigabit Ethernet MAC + +pci:v00008086d00005049* + ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC + +pci:v00008086d0000504A* + ID_MODEL_FROM_DATABASE=EP80579 Reserved + +pci:v00008086d0000504B* + ID_MODEL_FROM_DATABASE=EP80579 Reserved + +pci:v00008086d0000504C* + ID_MODEL_FROM_DATABASE=EP80579 Integrated Processor with QuickAssist TDM + +pci:v00008086d00005200* + ID_MODEL_FROM_DATABASE=EtherExpress PRO/100 Intelligent Server PCI Bridge + +pci:v00008086d00005201* + ID_MODEL_FROM_DATABASE=EtherExpress PRO/100 Intelligent Server Fast Ethernet Controller + +pci:v00008086d00005201sv00008086sd00000001* + ID_MODEL_FROM_DATABASE=EtherExpress PRO/100 Intelligent Server Fast Ethernet Controller (EtherExpress PRO/100 Server Ethernet Adapter) + +pci:v00008086d0000530D* + ID_MODEL_FROM_DATABASE=80310 (IOP) IO Processor + +pci:v00008086d00005845* + ID_MODEL_FROM_DATABASE=QEMU NVM Express Controller + +pci:v00008086d00005845sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=QEMU NVM Express Controller (QEMU Virtual Machine) + +pci:v00008086d00005900* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00005901* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor PCIe Controller (x16) + +pci:v00008086d00005902* + ID_MODEL_FROM_DATABASE=HD Graphics 610 + +pci:v00008086d00005904* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00005904sv000017AAsd00002247* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers (ThinkPad T570) + +pci:v00008086d00005904sv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers (ThinkPad X1 Carbon 5th Gen) + +pci:v00008086d00005905* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor PCIe Controller (x8) + +pci:v00008086d00005909* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor PCIe Controller (x4) + +pci:v00008086d0000590C* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d0000590F* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d0000590Fsv00001462sd00007A68* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers (B250 KRAIT GAMING (MS-7A68)) + +pci:v00008086d00005910* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00005911* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Gaussian Mixture Model + +pci:v00008086d00005912* + ID_MODEL_FROM_DATABASE=HD Graphics 630 + +pci:v00008086d00005914* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00005914sv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers (ThinkPad T480) + +pci:v00008086d00005916* + ID_MODEL_FROM_DATABASE=HD Graphics 620 + +pci:v00008086d00005916sv000017AAsd00002248* + ID_MODEL_FROM_DATABASE=HD Graphics 620 (ThinkPad T570) + +pci:v00008086d00005916sv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=HD Graphics 620 (ThinkPad X1 Carbon 5th Gen) + +pci:v00008086d00005917* + ID_MODEL_FROM_DATABASE=UHD Graphics 620 + +pci:v00008086d00005917sv000017AAsd0000225E* + ID_MODEL_FROM_DATABASE=UHD Graphics 620 (ThinkPad T480) + +pci:v00008086d00005918* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d0000591B* + ID_MODEL_FROM_DATABASE=HD Graphics 630 + +pci:v00008086d0000591C* + ID_MODEL_FROM_DATABASE=UHD Graphics 615 + +pci:v00008086d0000591D* + ID_MODEL_FROM_DATABASE=HD Graphics P630 + +pci:v00008086d0000591E* + ID_MODEL_FROM_DATABASE=HD Graphics 615 + +pci:v00008086d0000591F* + ID_MODEL_FROM_DATABASE=Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + +pci:v00008086d00005923* + ID_MODEL_FROM_DATABASE=HD Graphics 635 + +pci:v00008086d00005926* + ID_MODEL_FROM_DATABASE=Iris Plus Graphics 640 + +pci:v00008086d00005927* + ID_MODEL_FROM_DATABASE=Iris Plus Graphics 650 + +pci:v00008086d00005A84* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Integrated Graphics Controller + +pci:v00008086d00005A85* + ID_MODEL_FROM_DATABASE=HD Graphics 500 + +pci:v00008086d00005A88* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Imaging Unit + +pci:v00008086d00005A98* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Audio Cluster + +pci:v00008086d00005A9A* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Trusted Execution Engine + +pci:v00008086d00005AA2* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Integrated Sensor Hub + +pci:v00008086d00005AA8* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series USB xHCI + +pci:v00008086d00005AAC* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #1 + +pci:v00008086d00005AAE* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #2 + +pci:v00008086d00005AB0* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #3 + +pci:v00008086d00005AB2* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #4 + +pci:v00008086d00005AB4* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #5 + +pci:v00008086d00005AB6* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #6 + +pci:v00008086d00005AB8* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #7 + +pci:v00008086d00005ABA* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #8 + +pci:v00008086d00005ABC* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller #1 + +pci:v00008086d00005ABE* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller #2 + +pci:v00008086d00005AC0* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller #3 + +pci:v00008086d00005AC2* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series SPI Controller #1 + +pci:v00008086d00005AC4* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series SPI Controller #2 + +pci:v00008086d00005AC6* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series SPI Controller #3 + +pci:v00008086d00005AC8* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series PWM Pin Controller + +pci:v00008086d00005ACA* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series SDXC/MMC Host Controller + +pci:v00008086d00005ACC* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series eMMC Controller + +pci:v00008086d00005AD0* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series SDIO Controller + +pci:v00008086d00005AD4* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series SMBus Controller + +pci:v00008086d00005AD6* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port B #1 + +pci:v00008086d00005AD7* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port B #2 + +pci:v00008086d00005AD8* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port A #1 + +pci:v00008086d00005AD9* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port A #2 + +pci:v00008086d00005ADA* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port A #3 + +pci:v00008086d00005ADB* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port A #4 + +pci:v00008086d00005AE3* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series SATA AHCI Controller + +pci:v00008086d00005AE8* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Low Pin Count Interface + +pci:v00008086d00005AEE* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller #4 + +pci:v00008086d00005AF0* + ID_MODEL_FROM_DATABASE=Celeron N3350/Pentium N4200/Atom E3900 Series Host Bridge + +pci:v00008086d000065C0* + ID_MODEL_FROM_DATABASE=5100 Chipset Memory Controller Hub + +pci:v00008086d000065E2* + ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 2 + +pci:v00008086d000065E3* + ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 3 + +pci:v00008086d000065E4* + ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 4 + +pci:v00008086d000065E5* + ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 5 + +pci:v00008086d000065E6* + ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 6 + +pci:v00008086d000065E7* + ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x4 Port 7 + +pci:v00008086d000065F0* + ID_MODEL_FROM_DATABASE=5100 Chipset FSB Registers + +pci:v00008086d000065F0sv00001028sd0000020F* + ID_MODEL_FROM_DATABASE=5100 Chipset FSB Registers (PowerEdge R300) + +pci:v00008086d000065F0sv00001028sd00000210* + ID_MODEL_FROM_DATABASE=5100 Chipset FSB Registers (PowerEdge T300) + +pci:v00008086d000065F1* + ID_MODEL_FROM_DATABASE=5100 Chipset Reserved Registers + +pci:v00008086d000065F1sv00001028sd00000210* + ID_MODEL_FROM_DATABASE=5100 Chipset Reserved Registers (PowerEdge T300) + +pci:v00008086d000065F3* + ID_MODEL_FROM_DATABASE=5100 Chipset Reserved Registers + +pci:v00008086d000065F5* + ID_MODEL_FROM_DATABASE=5100 Chipset DDR Channel 0 Registers + +pci:v00008086d000065F6* + ID_MODEL_FROM_DATABASE=5100 Chipset DDR Channel 1 Registers + +pci:v00008086d000065F7* + ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x8 Port 2-3 + +pci:v00008086d000065F8* + ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x8 Port 4-5 + +pci:v00008086d000065F9* + ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x8 Port 6-7 + +pci:v00008086d000065FA* + ID_MODEL_FROM_DATABASE=5100 Chipset PCI Express x16 Port 4-7 + +pci:v00008086d000065FF* + ID_MODEL_FROM_DATABASE=5100 Chipset DMA Engine + +pci:v00008086d00006F00* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + +pci:v00008086d00006F00sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 (X10SRL-F) + +pci:v00008086d00006F01* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 0 + +pci:v00008086d00006F02* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 1 + +pci:v00008086d00006F03* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 1 + +pci:v00008086d00006F04* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 + +pci:v00008086d00006F05* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 + +pci:v00008086d00006F06* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 + +pci:v00008086d00006F07* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 + +pci:v00008086d00006F08* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 + +pci:v00008086d00006F09* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 + +pci:v00008086d00006F0A* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 + +pci:v00008086d00006F0B* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 + +pci:v00008086d00006F10* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F11* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F12* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F13* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F14* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F15* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F16* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F17* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F18* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F19* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F1A* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F1B* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F1C* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + +pci:v00008086d00006F1D* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R2PCIe Agent + +pci:v00008086d00006F1E* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox + +pci:v00008086d00006F1F* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox + +pci:v00008086d00006F20* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 0 + +pci:v00008086d00006F20sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 0 (X10SRL-F) + +pci:v00008086d00006F21* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 1 + +pci:v00008086d00006F21sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 1 (X10SRL-F) + +pci:v00008086d00006F22* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 2 + +pci:v00008086d00006F22sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 2 (X10SRL-F) + +pci:v00008086d00006F23* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 3 + +pci:v00008086d00006F23sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 3 (X10SRL-F) + +pci:v00008086d00006F24* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 4 + +pci:v00008086d00006F24sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 4 (X10SRL-F) + +pci:v00008086d00006F25* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 5 + +pci:v00008086d00006F25sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 5 (X10SRL-F) + +pci:v00008086d00006F26* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 6 + +pci:v00008086d00006F26sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 6 (X10SRL-F) + +pci:v00008086d00006F27* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 7 + +pci:v00008086d00006F27sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 7 (X10SRL-F) + +pci:v00008086d00006F28* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Map/VTd_Misc/System Management + +pci:v00008086d00006F28sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Map/VTd_Misc/System Management (X10SRL-F) + +pci:v00008086d00006F29* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Hot Plug + +pci:v00008086d00006F29sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Hot Plug (X10SRL-F) + +pci:v00008086d00006F2A* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO RAS/Control Status/Global Errors + +pci:v00008086d00006F2Asv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO RAS/Control Status/Global Errors (X10SRL-F) + +pci:v00008086d00006F2C* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC + +pci:v00008086d00006F2Csv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (X10SRL-F) + +pci:v00008086d00006F30* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0 + +pci:v00008086d00006F32* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 + +pci:v00008086d00006F33* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 + +pci:v00008086d00006F34* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R2PCIe Agent + +pci:v00008086d00006F36* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1 + +pci:v00008086d00006F37* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1 + +pci:v00008086d00006F38* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 + +pci:v00008086d00006F39* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IO Performance Monitoring + +pci:v00008086d00006F3A* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 + +pci:v00008086d00006F3E* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2 + +pci:v00008086d00006F3F* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2 + +pci:v00008086d00006F40* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 + +pci:v00008086d00006F41* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2 + +pci:v00008086d00006F43* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 + +pci:v00008086d00006F45* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug + +pci:v00008086d00006F46* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug + +pci:v00008086d00006F47* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug + +pci:v00008086d00006F50* + ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickData Technology Register DMA Channel 0 + +pci:v00008086d00006F51* + ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickData Technology Register DMA Channel 1 + +pci:v00008086d00006F52* + ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickData Technology Register DMA Channel 2 + +pci:v00008086d00006F53* + ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickData Technology Register DMA Channel 3 + +pci:v00008086d00006F54* + ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickAssist Technology + +pci:v00008086d00006F55* + ID_MODEL_FROM_DATABASE=Xeon Processor D Family QuickAssist Technology Virtual Fuction + +pci:v00008086d00006F60* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 + +pci:v00008086d00006F68* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS + +pci:v00008086d00006F6A* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder + +pci:v00008086d00006F6B* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder + +pci:v00008086d00006F6C* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder + +pci:v00008086d00006F6D* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder + +pci:v00008086d00006F6E* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Broadcast + +pci:v00008086d00006F6F* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Global Broadcast + +pci:v00008086d00006F70* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0 Debug + +pci:v00008086d00006F71* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Target Address/Thermal/RAS + +pci:v00008086d00006F76* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link Debug + +pci:v00008086d00006F78* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 Debug + +pci:v00008086d00006F79* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS + +pci:v00008086d00006F7D* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox + +pci:v00008086d00006F7E* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link Debug + +pci:v00008086d00006F80* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 + +pci:v00008086d00006F81* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1 + +pci:v00008086d00006F83* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 + +pci:v00008086d00006F85* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug + +pci:v00008086d00006F86* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug + +pci:v00008086d00006F87* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug + +pci:v00008086d00006F88* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006F8A* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006F90* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 + +pci:v00008086d00006F93* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 + +pci:v00008086d00006F95* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 Debug + +pci:v00008086d00006F96* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 Debug + +pci:v00008086d00006F98* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006F99* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006F9A* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006F9C* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FA0* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0 + +pci:v00008086d00006FA8* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Target Address/Thermal/RAS + +pci:v00008086d00006FAA* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder + +pci:v00008086d00006FAB* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder + +pci:v00008086d00006FAC* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder + +pci:v00008086d00006FAD* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder + +pci:v00008086d00006FAE* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Broadcast + +pci:v00008086d00006FAF* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Global Broadcast + +pci:v00008086d00006FB0* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 0 Thermal Control + +pci:v00008086d00006FB1* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 1 Thermal Control + +pci:v00008086d00006FB2* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 0 Error + +pci:v00008086d00006FB3* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 1 Error + +pci:v00008086d00006FB4* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 2 Thermal Control + +pci:v00008086d00006FB5* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 3 Thermal Control + +pci:v00008086d00006FB6* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 2 Error + +pci:v00008086d00006FB7* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 3 Error + +pci:v00008086d00006FB8* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface + +pci:v00008086d00006FB9* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface + +pci:v00008086d00006FBA* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface + +pci:v00008086d00006FBB* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface + +pci:v00008086d00006FBC* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface + +pci:v00008086d00006FBD* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface + +pci:v00008086d00006FBE* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface + +pci:v00008086d00006FBF* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface + +pci:v00008086d00006FC0* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FC1* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FC2* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FC3* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FC4* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FC5* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FC6* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FC7* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FC8* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FC9* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FCA* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FCB* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FCC* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FCD* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FCE* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FCF* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + +pci:v00008086d00006FD0* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 0 Thermal Control + +pci:v00008086d00006FD1* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 1 Thermal Control + +pci:v00008086d00006FD2* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 0 Error + +pci:v00008086d00006FD3* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 1 Error + +pci:v00008086d00006FD4* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 2 Thermal Control + +pci:v00008086d00006FD5* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 3 Thermal Control + +pci:v00008086d00006FD6* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 2 Error + +pci:v00008086d00006FD7* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 3 Error + +pci:v00008086d00006FE0* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FE1* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FE2* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FE3* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FE4* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FE5* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FE6* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FE7* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FE8* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FE9* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FEA* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FEB* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FEC* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FED* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FEE* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FEF* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FF0* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FF1* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FF8* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FF9* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FFA* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FFB* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FFC* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FFD* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00006FFE* + ID_MODEL_FROM_DATABASE=Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + +pci:v00008086d00007000* + ID_MODEL_FROM_DATABASE=82371SB PIIX3 ISA [Natoma/Triton II] + +pci:v00008086d00007000sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82371SB PIIX3 ISA [Natoma/Triton II] (Qemu virtual machine) + +pci:v00008086d00007010* + ID_MODEL_FROM_DATABASE=82371SB PIIX3 IDE [Natoma/Triton II] + +pci:v00008086d00007010sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82371SB PIIX3 IDE [Natoma/Triton II] (Qemu virtual machine) + +pci:v00008086d00007020* + ID_MODEL_FROM_DATABASE=82371SB PIIX3 USB [Natoma/Triton II] + +pci:v00008086d00007020sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82371SB PIIX3 USB [Natoma/Triton II] (QEMU Virtual Machine) + +pci:v00008086d00007030* + ID_MODEL_FROM_DATABASE=430VX - 82437VX TVX [Triton VX] + +pci:v00008086d00007050* + ID_MODEL_FROM_DATABASE=Intercast Video Capture Card + +pci:v00008086d00007051* + ID_MODEL_FROM_DATABASE=PB 642365-003 (Business Video Conferencing Card) + +pci:v00008086d00007100* + ID_MODEL_FROM_DATABASE=430TX - 82439TX MTXC + +pci:v00008086d00007110* + ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 ISA + +pci:v00008086d00007110sv000015ADsd00001976* + ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 ISA (Virtual Machine Chipset) + +pci:v00008086d00007111* + ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 IDE + +pci:v00008086d00007111sv000015ADsd00001976* + ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 IDE (Virtual Machine Chipset) + +pci:v00008086d00007112* + ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 USB + +pci:v00008086d00007112sv000015ADsd00001976* + ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 USB (Virtual Machine Chipset) + +pci:v00008086d00007112sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 USB (QEMU Virtual Machine) + +pci:v00008086d00007113* + ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 ACPI + +pci:v00008086d00007113sv000015ADsd00001976* + ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 ACPI (Virtual Machine Chipset) + +pci:v00008086d00007113sv00001AF4sd00001100* + ID_MODEL_FROM_DATABASE=82371AB/EB/MB PIIX4 ACPI (Qemu virtual machine) + +pci:v00008086d00007120* + ID_MODEL_FROM_DATABASE=82810 GMCH (Graphics Memory Controller Hub) + +pci:v00008086d00007120sv00004C53sd00001040* + ID_MODEL_FROM_DATABASE=82810 GMCH (Graphics Memory Controller Hub) (CL7 mainboard) + +pci:v00008086d00007120sv00004C53sd00001060* + ID_MODEL_FROM_DATABASE=82810 GMCH (Graphics Memory Controller Hub) (PC7 mainboard) + +pci:v00008086d00007121* + ID_MODEL_FROM_DATABASE=82810 (CGC) Chipset Graphics Controller + +pci:v00008086d00007121sv00004C53sd00001040* + ID_MODEL_FROM_DATABASE=82810 (CGC) Chipset Graphics Controller (CL7 mainboard) + +pci:v00008086d00007121sv00004C53sd00001060* + ID_MODEL_FROM_DATABASE=82810 (CGC) Chipset Graphics Controller (PC7 mainboard) + +pci:v00008086d00007121sv00008086sd00004341* + ID_MODEL_FROM_DATABASE=82810 (CGC) Chipset Graphics Controller (Cayman (CA810) Mainboard) + +pci:v00008086d00007122* + ID_MODEL_FROM_DATABASE=82810 DC-100 (GMCH) Graphics Memory Controller Hub + +pci:v00008086d00007123* + ID_MODEL_FROM_DATABASE=82810 DC-100 (CGC) Chipset Graphics Controller + +pci:v00008086d00007124* + ID_MODEL_FROM_DATABASE=82810E DC-133 (GMCH) Graphics Memory Controller Hub + +pci:v00008086d00007124sv00001028sd000000B4* + ID_MODEL_FROM_DATABASE=82810E DC-133 (GMCH) Graphics Memory Controller Hub (OptiPlex GX110) + +pci:v00008086d00007125* + ID_MODEL_FROM_DATABASE=82810E DC-133 (CGC) Chipset Graphics Controller + +pci:v00008086d00007125sv00001028sd000000B4* + ID_MODEL_FROM_DATABASE=82810E DC-133 (CGC) Chipset Graphics Controller (OptiPlex GX110) + +pci:v00008086d00007126* + ID_MODEL_FROM_DATABASE=82810 DC-133 System and Graphics Controller + +pci:v00008086d00007128* + ID_MODEL_FROM_DATABASE=82810-M DC-100 System and Graphics Controller + +pci:v00008086d0000712A* + ID_MODEL_FROM_DATABASE=82810-M DC-133 System and Graphics Controller + +pci:v00008086d00007180* + ID_MODEL_FROM_DATABASE=440LX/EX - 82443LX/EX Host bridge + +pci:v00008086d00007181* + ID_MODEL_FROM_DATABASE=440LX/EX - 82443LX/EX AGP bridge + +pci:v00008086d00007190* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge + +pci:v00008086d00007190sv00000E11sd00000500* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (Armada 1750 Laptop System Chipset) + +pci:v00008086d00007190sv00000E11sd0000B110* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (Armada M700/E500) + +pci:v00008086d00007190sv00001028sd0000008E* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (PowerEdge 1300 mainboard) + +pci:v00008086d00007190sv00001043sd0000803B* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (CUBX-L/E Mainboard) + +pci:v00008086d00007190sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (Toshiba Tecra 8100 Laptop System Chipset) + +pci:v00008086d00007190sv000015ADsd00001976* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (Virtual Machine Chipset) + +pci:v00008086d00007190sv00004C53sd00001050* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (CT7 mainboard) + +pci:v00008086d00007190sv00004C53sd00001051* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (CE7 mainboard) + +pci:v00008086d00007191* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX AGP bridge + +pci:v00008086d00007191sv00001028sd0000008E* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX AGP bridge (PowerEdge 1300 mainboard) + +pci:v00008086d00007192* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) + +pci:v00008086d00007192sv00000E11sd00000460* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (Armada 1700 Laptop System Chipset) + +pci:v00008086d00007192sv00001179sd00000001* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (Satellite 4010) + +pci:v00008086d00007192sv00004C53sd00001000* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) + +pci:v00008086d00007192sv00008086sd00007190* + ID_MODEL_FROM_DATABASE=440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (Dell PowerEdge 350) + +pci:v00008086d00007194* + ID_MODEL_FROM_DATABASE=82440MX Host Bridge + +pci:v00008086d00007194sv00001033sd00000000* + ID_MODEL_FROM_DATABASE=82440MX Host Bridge (Versa Note Vxi) + +pci:v00008086d00007194sv00004C53sd000010A0* + ID_MODEL_FROM_DATABASE=82440MX Host Bridge (CA3/CR3 mainboard) + +pci:v00008086d00007195* + ID_MODEL_FROM_DATABASE=82440MX AC'97 Audio Controller + +pci:v00008086d00007195sv00001033sd000080CC* + ID_MODEL_FROM_DATABASE=82440MX AC'97 Audio Controller (Versa Note VXi) + +pci:v00008086d00007195sv000010CFsd00001099* + ID_MODEL_FROM_DATABASE=82440MX AC'97 Audio Controller (QSound_SigmaTel Stac97 PCI Audio) + +pci:v00008086d00007195sv000011D4sd00000040* + ID_MODEL_FROM_DATABASE=82440MX AC'97 Audio Controller (SoundMAX Integrated Digital Audio) + +pci:v00008086d00007195sv000011D4sd00000048* + ID_MODEL_FROM_DATABASE=82440MX AC'97 Audio Controller (SoundMAX Integrated Digital Audio) + +pci:v00008086d00007196* + ID_MODEL_FROM_DATABASE=82440MX AC'97 Modem Controller + +pci:v00008086d00007198* + ID_MODEL_FROM_DATABASE=82440MX ISA Bridge + +pci:v00008086d00007199* + ID_MODEL_FROM_DATABASE=82440MX EIDE Controller + +pci:v00008086d0000719A* + ID_MODEL_FROM_DATABASE=82440MX USB Universal Host Controller + +pci:v00008086d0000719B* + ID_MODEL_FROM_DATABASE=82440MX Power Management Controller + +pci:v00008086d000071A0* + ID_MODEL_FROM_DATABASE=440GX - 82443GX Host bridge + +pci:v00008086d000071A0sv00004C53sd00001050* + ID_MODEL_FROM_DATABASE=440GX - 82443GX Host bridge (CT7 mainboard) + +pci:v00008086d000071A0sv00004C53sd00001051* + ID_MODEL_FROM_DATABASE=440GX - 82443GX Host bridge (CE7 mainboard) + +pci:v00008086d000071A1* + ID_MODEL_FROM_DATABASE=440GX - 82443GX AGP bridge + +pci:v00008086d000071A2* + ID_MODEL_FROM_DATABASE=440GX - 82443GX Host bridge (AGP disabled) + +pci:v00008086d000071A2sv00004C53sd00001000* + ID_MODEL_FROM_DATABASE=440GX - 82443GX Host bridge (AGP disabled) (CC7/CR7/CP7/VC7/VP7/VR7 mainboard) + +pci:v00008086d00007360* + ID_MODEL_FROM_DATABASE=XMM7360 LTE Advanced Modem + +pci:v00008086d00007600* + ID_MODEL_FROM_DATABASE=82372FB PIIX5 ISA + +pci:v00008086d00007601* + ID_MODEL_FROM_DATABASE=82372FB PIIX5 IDE + +pci:v00008086d00007602* + ID_MODEL_FROM_DATABASE=82372FB PIIX5 USB + +pci:v00008086d00007603* + ID_MODEL_FROM_DATABASE=82372FB PIIX5 SMBus + +pci:v00008086d00007800* + ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator + +pci:v00008086d00007800sv0000003Dsd00000008* + ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Starfighter AGP) + +pci:v00008086d00007800sv0000003Dsd0000000B* + ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Starfighter AGP) + +pci:v00008086d00007800sv00001092sd00000100* + ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Stealth II G460) + +pci:v00008086d00007800sv000010B4sd0000201A* + ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Lightspeed 740) + +pci:v00008086d00007800sv000010B4sd0000202F* + ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Lightspeed 740) + +pci:v00008086d00007800sv00008086sd00000000* + ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Terminator 2x/i) + +pci:v00008086d00007800sv00008086sd00000100* + ID_MODEL_FROM_DATABASE=82740 (i740) AGP Graphics Accelerator (Intel740 Graphics Accelerator) + +pci:v00008086d00008002* + ID_MODEL_FROM_DATABASE=Trusted Execution Technology Registers + +pci:v00008086d00008003* + ID_MODEL_FROM_DATABASE=Trusted Execution Technology Registers + +pci:v00008086d00008100* + ID_MODEL_FROM_DATABASE=US15W/US15X SCH [Poulsbo] Host Bridge + +pci:v00008086d00008101* + ID_MODEL_FROM_DATABASE=US15L/UL11L SCH [Poulsbo] Host Bridge + +pci:v00008086d00008108* + ID_MODEL_FROM_DATABASE=US15W/US15X SCH [Poulsbo] Graphics Controller + +pci:v00008086d00008109* + ID_MODEL_FROM_DATABASE=US15L/UL11L SCH [Poulsbo] Graphics Controller + +pci:v00008086d00008110* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] PCI Express Port 1 + +pci:v00008086d00008112* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] PCI Express Port 2 + +pci:v00008086d00008114* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] USB UHCI Controller #1 + +pci:v00008086d00008115* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] USB UHCI Controller #2 + +pci:v00008086d00008116* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] USB UHCI Controller #3 + +pci:v00008086d00008117* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] USB EHCI Controller + +pci:v00008086d00008118* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] USB Client Controller + +pci:v00008086d00008119* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] LPC Bridge + +pci:v00008086d0000811A* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] IDE Controller + +pci:v00008086d0000811B* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] HD Audio Controller + +pci:v00008086d0000811C* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] SDIO/MMC Controller #1 + +pci:v00008086d0000811D* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] SDIO/MMC Controller #2 + +pci:v00008086d0000811E* + ID_MODEL_FROM_DATABASE=US15W/US15X/US15L/UL11L SCH [Poulsbo] SDIO/MMC Controller #3 + +pci:v00008086d00008180* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Express Port 3 + +pci:v00008086d00008181* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Express Port 4 + +pci:v00008086d00008182* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx Integrated Graphics Controller + +pci:v00008086d00008183* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx Configuration Unit + +pci:v00008086d00008184* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Express Port 1 + +pci:v00008086d00008185* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx PCI Express Port 2 + +pci:v00008086d00008186* + ID_MODEL_FROM_DATABASE=Atom Processor E6xx LPC Bridge + +pci:v00008086d000084C4* + ID_MODEL_FROM_DATABASE=450KX/GX [Orion] - 82454KX/GX PCI bridge + +pci:v00008086d000084C5* + ID_MODEL_FROM_DATABASE=450KX/GX [Orion] - 82453KX/GX Memory controller + +pci:v00008086d000084CA* + ID_MODEL_FROM_DATABASE=450NX - 82451NX Memory & I/O Controller + +pci:v00008086d000084CB* + ID_MODEL_FROM_DATABASE=450NX - 82454NX/84460GX PCI Expander Bridge + +pci:v00008086d000084E0* + ID_MODEL_FROM_DATABASE=460GX - 84460GX System Address Controller (SAC) + +pci:v00008086d000084E1* + ID_MODEL_FROM_DATABASE=460GX - 84460GX System Data Controller (SDC) + +pci:v00008086d000084E2* + ID_MODEL_FROM_DATABASE=460GX - 84460GX AGP Bridge (GXB function 2) + +pci:v00008086d000084E3* + ID_MODEL_FROM_DATABASE=460GX - 84460GX Memory Address Controller (MAC) + +pci:v00008086d000084E4* + ID_MODEL_FROM_DATABASE=460GX - 84460GX Memory Data Controller (MDC) + +pci:v00008086d000084E6* + ID_MODEL_FROM_DATABASE=460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB) + +pci:v00008086d000084EA* + ID_MODEL_FROM_DATABASE=460GX - 84460GX AGP Bridge (GXB function 1) + +pci:v00008086d00008500* + ID_MODEL_FROM_DATABASE=IXP4XX Network Processor (IXP420/421/422/425/IXC1100) + +pci:v00008086d00008500sv00001993sd00000DED* + ID_MODEL_FROM_DATABASE=IXP4XX Network Processor (IXP420/421/422/425/IXC1100) (mGuard-PCI AV#2) + +pci:v00008086d00008500sv00001993sd00000DEE* + ID_MODEL_FROM_DATABASE=IXP4XX Network Processor (IXP420/421/422/425/IXC1100) (mGuard-PCI AV#1) + +pci:v00008086d00008500sv00001993sd00000DEF* + ID_MODEL_FROM_DATABASE=IXP4XX Network Processor (IXP420/421/422/425/IXC1100) (mGuard-PCI AV#0) + +pci:v00008086d000087C0* + ID_MODEL_FROM_DATABASE=UHD Graphics 617 + +pci:v00008086d00008800* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T PCI Express Port + +pci:v00008086d00008801* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T Packet Hub + +pci:v00008086d00008802* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T Gigabit Ethernet Controller + +pci:v00008086d00008803* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T General Purpose IO Controller + +pci:v00008086d00008804* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #4 + +pci:v00008086d00008805* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #5 + +pci:v00008086d00008806* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #6 + +pci:v00008086d00008807* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB2 EHCI Controller #2 + +pci:v00008086d00008808* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB Client Controller + +pci:v00008086d00008809* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T SDIO Controller #1 + +pci:v00008086d0000880A* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T SDIO Controller #2 + +pci:v00008086d0000880B* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T SATA AHCI Controller + +pci:v00008086d0000880C* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #1 + +pci:v00008086d0000880D* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #2 + +pci:v00008086d0000880E* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB OHCI Controller #3 + +pci:v00008086d0000880F* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T USB2 EHCI Controller #1 + +pci:v00008086d00008810* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T DMA Controller #1 + +pci:v00008086d00008811* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T UART Controller 0 + +pci:v00008086d00008812* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T UART Controller 1 + +pci:v00008086d00008813* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T UART Controller 2 + +pci:v00008086d00008814* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T UART Controller 3 + +pci:v00008086d00008815* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T DMA Controller #2 + +pci:v00008086d00008816* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T Serial Peripheral Interface Bus + +pci:v00008086d00008817* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T I2C Controller + +pci:v00008086d00008818* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T Controller Area Network (CAN) Controller + +pci:v00008086d00008819* + ID_MODEL_FROM_DATABASE=Platform Controller Hub EG20T IEEE 1588 Hardware Assist + +pci:v00008086d00008A0D* + ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 NHI #1 + +pci:v00008086d00008A13* + ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 USB Controller + +pci:v00008086d00008A17* + ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 NHI #0 + +pci:v00008086d00008A1D* + ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 PCI Express Root Port #0 + +pci:v00008086d00008A1F* + ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 PCI Express Root Port #1 + +pci:v00008086d00008A21* + ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 PCI Express Root Port #2 + +pci:v00008086d00008A23* + ID_MODEL_FROM_DATABASE=Ice Lake Thunderbolt 3 PCI Express Root Port #3 + +pci:v00008086d00008A52* + ID_MODEL_FROM_DATABASE=Iris Plus Graphics G7 + +pci:v00008086d00008C00* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 4-port SATA Controller 1 [IDE mode] + +pci:v00008086d00008C01* + ID_MODEL_FROM_DATABASE=8 Series Chipset Family 4-port SATA Controller 1 [IDE mode] - Mobile + +pci:v00008086d00008C02* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] + +pci:v00008086d00008C02sv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (ThinkCentre M83) + +pci:v00008086d00008C03* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] + +pci:v00008086d00008C03sv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (ZBook 15) + +pci:v00008086d00008C03sv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (ThinkPad T440p) + +pci:v00008086d00008C04* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + +pci:v00008086d00008C05* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + +pci:v00008086d00008C06* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + +pci:v00008086d00008C07* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + +pci:v00008086d00008C08* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 2-port SATA Controller 2 [IDE mode] + +pci:v00008086d00008C09* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family 2-port SATA Controller 2 [IDE mode] + +pci:v00008086d00008C0E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + +pci:v00008086d00008C0F* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + +pci:v00008086d00008C10* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1 + +pci:v00008086d00008C10sv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1 (ThinkPad T440p) + +pci:v00008086d00008C11* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #1 + +pci:v00008086d00008C12* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2 + +pci:v00008086d00008C12sv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2 (ThinkPad T440p) + +pci:v00008086d00008C13* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #2 + +pci:v00008086d00008C14* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #3 + +pci:v00008086d00008C15* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #3 + +pci:v00008086d00008C16* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #4 + +pci:v00008086d00008C17* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #4 + +pci:v00008086d00008C18* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #5 + +pci:v00008086d00008C19* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #5 + +pci:v00008086d00008C1A* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #6 + +pci:v00008086d00008C1B* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #6 + +pci:v00008086d00008C1C* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #7 + +pci:v00008086d00008C1D* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #7 + +pci:v00008086d00008C1E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #8 + +pci:v00008086d00008C1F* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family PCI Express Root Port #8 + +pci:v00008086d00008C20* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller + +pci:v00008086d00008C20sv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller (ZBook 15) + +pci:v00008086d00008C20sv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller (ThinkPad T440p) + +pci:v00008086d00008C20sv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller (ThinkCentre M83) + +pci:v00008086d00008C21* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset High Definition Audio Controller + +pci:v00008086d00008C22* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller + +pci:v00008086d00008C22sv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (ZBook 15) + +pci:v00008086d00008C22sv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (ThinkPad T440p) + +pci:v00008086d00008C22sv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family SMBus Controller (ThinkCentre M83) + +pci:v00008086d00008C23* + ID_MODEL_FROM_DATABASE=8 Series Chipset Family CHAP Counters + +pci:v00008086d00008C24* + ID_MODEL_FROM_DATABASE=8 Series Chipset Family Thermal Management Controller + +pci:v00008086d00008C26* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 + +pci:v00008086d00008C26sv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ZBook 15) + +pci:v00008086d00008C26sv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ThinkPad T440p) + +pci:v00008086d00008C26sv000017AAsd00002210* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ThinkPad T540p) + +pci:v00008086d00008C26sv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ThinkCentre M83) + +pci:v00008086d00008C26sv00002210sd000017AA* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #1 (ThinkPad T540p) + +pci:v00008086d00008C2D* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 + +pci:v00008086d00008C2Dsv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (ZBook 15) + +pci:v00008086d00008C2Dsv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (ThinkPad T440p) + +pci:v00008086d00008C2Dsv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB EHCI #2 (ThinkCentre M83) + +pci:v00008086d00008C31* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI + +pci:v00008086d00008C31sv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (ZBook 15) + +pci:v00008086d00008C31sv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (ThinkPad T440p) + +pci:v00008086d00008C31sv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI (ThinkCentre M83) + +pci:v00008086d00008C33* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LAN Controller + +pci:v00008086d00008C34* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family NAND Controller + +pci:v00008086d00008C3A* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 + +pci:v00008086d00008C3Asv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (ZBook 15) + +pci:v00008086d00008C3Asv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (ThinkPad T440p) + +pci:v00008086d00008C3Asv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #1 (ThinkCentre M83) + +pci:v00008086d00008C3B* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family MEI Controller #2 + +pci:v00008086d00008C3C* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family IDE-r Controller + +pci:v00008086d00008C3D* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family KT Controller + +pci:v00008086d00008C40* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C41* + ID_MODEL_FROM_DATABASE=8 Series Chipset Family Mobile Super SKU LPC Controller + +pci:v00008086d00008C42* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family Desktop Super SKU LPC Controller + +pci:v00008086d00008C43* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C44* + ID_MODEL_FROM_DATABASE=Z87 Express LPC Controller + +pci:v00008086d00008C45* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C46* + ID_MODEL_FROM_DATABASE=Z85 Express LPC Controller + +pci:v00008086d00008C47* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C48* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C49* + ID_MODEL_FROM_DATABASE=HM86 Express LPC Controller + +pci:v00008086d00008C4A* + ID_MODEL_FROM_DATABASE=H87 Express LPC Controller + +pci:v00008086d00008C4B* + ID_MODEL_FROM_DATABASE=HM87 Express LPC Controller + +pci:v00008086d00008C4C* + ID_MODEL_FROM_DATABASE=Q85 Express LPC Controller + +pci:v00008086d00008C4Csv000017AAsd0000309F* + ID_MODEL_FROM_DATABASE=Q85 Express LPC Controller (ThinkCentre M83) + +pci:v00008086d00008C4D* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C4E* + ID_MODEL_FROM_DATABASE=Q87 Express LPC Controller + +pci:v00008086d00008C4F* + ID_MODEL_FROM_DATABASE=QM87 Express LPC Controller + +pci:v00008086d00008C4Fsv0000103Csd00001909* + ID_MODEL_FROM_DATABASE=QM87 Express LPC Controller (ZBook 15) + +pci:v00008086d00008C4Fsv000017AAsd0000220E* + ID_MODEL_FROM_DATABASE=QM87 Express LPC Controller (ThinkPad T440p) + +pci:v00008086d00008C50* + ID_MODEL_FROM_DATABASE=B85 Express LPC Controller + +pci:v00008086d00008C51* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C52* + ID_MODEL_FROM_DATABASE=C222 Series Chipset Family Server Essential SKU LPC Controller + +pci:v00008086d00008C53* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C54* + ID_MODEL_FROM_DATABASE=C224 Series Chipset Family Server Standard SKU LPC Controller + +pci:v00008086d00008C55* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C56* + ID_MODEL_FROM_DATABASE=C226 Series Chipset Family Server Advanced SKU LPC Controller + +pci:v00008086d00008C57* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C58* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family WS SKU LPC Controller + +pci:v00008086d00008C59* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C5A* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C5B* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C5C* + ID_MODEL_FROM_DATABASE=H81 Express LPC Controller + +pci:v00008086d00008C5D* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C5E* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C5F* + ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family LPC Controller + +pci:v00008086d00008C80* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [IDE Mode] + +pci:v00008086d00008C81* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [IDE Mode] + +pci:v00008086d00008C82* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [AHCI Mode] + +pci:v00008086d00008C83* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [AHCI Mode] + +pci:v00008086d00008C84* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] + +pci:v00008086d00008C85* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] + +pci:v00008086d00008C86* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] + +pci:v00008086d00008C87* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] + +pci:v00008086d00008C88* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [IDE Mode] + +pci:v00008086d00008C89* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [IDE Mode] + +pci:v00008086d00008C8E* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] + +pci:v00008086d00008C8F* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SATA Controller [RAID Mode] + +pci:v00008086d00008C90* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 1 + +pci:v00008086d00008C92* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 2 + +pci:v00008086d00008C94* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 3 + +pci:v00008086d00008C96* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 4 + +pci:v00008086d00008C98* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 5 + +pci:v00008086d00008C9A* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 6 + +pci:v00008086d00008C9C* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 7 + +pci:v00008086d00008C9E* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family PCI Express Root Port 8 + +pci:v00008086d00008CA0* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family HD Audio Controller + +pci:v00008086d00008CA2* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family SMBus Controller + +pci:v00008086d00008CA4* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family Thermal Controller + +pci:v00008086d00008CA6* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family USB EHCI Controller #1 + +pci:v00008086d00008CAD* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family USB EHCI Controller #2 + +pci:v00008086d00008CB1* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family USB xHCI Controller + +pci:v00008086d00008CB3* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family LAN Controller + +pci:v00008086d00008CBA* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family ME Interface #1 + +pci:v00008086d00008CBB* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family ME Interface #2 + +pci:v00008086d00008CBC* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family IDE-R Controller + +pci:v00008086d00008CBD* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family KT Controller + +pci:v00008086d00008CC1* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family LPC Controller + +pci:v00008086d00008CC2* + ID_MODEL_FROM_DATABASE=9 Series Chipset Family LPC Controller + +pci:v00008086d00008CC3* + ID_MODEL_FROM_DATABASE=HM97 Chipset LPC Controller + +pci:v00008086d00008CC4* + ID_MODEL_FROM_DATABASE=Z97 Chipset LPC Controller + +pci:v00008086d00008CC5* + ID_MODEL_FROM_DATABASE=QM97 Chipset LPC Controller + +pci:v00008086d00008CC6* + ID_MODEL_FROM_DATABASE=H97 Chipset LPC Controller + +pci:v00008086d00008D00* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset 4-port SATA Controller [IDE mode] + +pci:v00008086d00008D02* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset 6-Port SATA Controller [AHCI mode] + +pci:v00008086d00008D04* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset SATA Controller [RAID mode] + +pci:v00008086d00008D06* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset SATA Controller [RAID mode] + +pci:v00008086d00008D06sv000017AAsd00001031* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset SATA Controller [RAID mode] (ThinkServer RAID 110i) + +pci:v00008086d00008D08* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset 2-port SATA Controller [IDE mode] + +pci:v00008086d00008D0E* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset SATA Controller [RAID mode] + +pci:v00008086d00008D10* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #1 + +pci:v00008086d00008D11* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #1 + +pci:v00008086d00008D12* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #2 + +pci:v00008086d00008D13* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #2 + +pci:v00008086d00008D14* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #3 + +pci:v00008086d00008D15* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #3 + +pci:v00008086d00008D16* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #4 + +pci:v00008086d00008D17* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #4 + +pci:v00008086d00008D18* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #5 + +pci:v00008086d00008D19* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #5 + +pci:v00008086d00008D1A* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #6 + +pci:v00008086d00008D1B* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #6 + +pci:v00008086d00008D1C* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #7 + +pci:v00008086d00008D1D* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #7 + +pci:v00008086d00008D1E* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #8 + +pci:v00008086d00008D1F* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset PCI Express Root Port #8 + +pci:v00008086d00008D20* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset HD Audio Controller + +pci:v00008086d00008D21* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset HD Audio Controller + +pci:v00008086d00008D22* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset SMBus Controller + +pci:v00008086d00008D22sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset SMBus Controller (X10SRL-F) + +pci:v00008086d00008D24* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset Thermal Subsystem + +pci:v00008086d00008D26* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset USB Enhanced Host Controller #1 + +pci:v00008086d00008D26sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset USB Enhanced Host Controller #1 (X10SRL-F) + +pci:v00008086d00008D2D* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset USB Enhanced Host Controller #2 + +pci:v00008086d00008D2Dsv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset USB Enhanced Host Controller #2 (X10SRL-F) + +pci:v00008086d00008D31* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset USB xHCI Host Controller + +pci:v00008086d00008D31sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset USB xHCI Host Controller (X10SRL-F) + +pci:v00008086d00008D33* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LAN Controller + +pci:v00008086d00008D34* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset NAND Controller + +pci:v00008086d00008D3A* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset MEI Controller #1 + +pci:v00008086d00008D3Asv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset MEI Controller #1 (X10SRL-F) + +pci:v00008086d00008D3B* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset MEI Controller #2 + +pci:v00008086d00008D3Bsv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset MEI Controller #2 (X10SRL-F) + +pci:v00008086d00008D3C* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset IDE-r Controller + +pci:v00008086d00008D3D* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset KT Controller + +pci:v00008086d00008D40* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D41* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D42* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D43* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D44* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D44sv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller (X10SRL-F) + +pci:v00008086d00008D45* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D46* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D47* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D48* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D49* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D4A* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D4B* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D4C* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D4D* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D4E* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D4F* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset LPC Controller + +pci:v00008086d00008D60* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [IDE mode] + +pci:v00008086d00008D62* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [AHCI mode] + +pci:v00008086d00008D64* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] + +pci:v00008086d00008D66* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] + +pci:v00008086d00008D68* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [IDE mode] + +pci:v00008086d00008D6E* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset sSATA Controller [RAID mode] + +pci:v00008086d00008D7C* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset SPSR + +pci:v00008086d00008D7Csv000015D9sd00000832* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset SPSR (X10SRL-F) + +pci:v00008086d00008D7D* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset MS SMBus 0 + +pci:v00008086d00008D7E* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset MS SMBus 1 + +pci:v00008086d00008D7F* + ID_MODEL_FROM_DATABASE=C610/X99 series chipset MS SMBus 2 + +pci:v00008086d00009000* + ID_MODEL_FROM_DATABASE=IXP2000 Family Network Processor + +pci:v00008086d00009001* + ID_MODEL_FROM_DATABASE=IXP2400 Network Processor + +pci:v00008086d00009002* + ID_MODEL_FROM_DATABASE=IXP2300 Network Processor + +pci:v00008086d00009004* + ID_MODEL_FROM_DATABASE=IXP2800 Network Processor + +pci:v00008086d00009621* + ID_MODEL_FROM_DATABASE=Integrated RAID + +pci:v00008086d00009622* + ID_MODEL_FROM_DATABASE=Integrated RAID + +pci:v00008086d00009641* + ID_MODEL_FROM_DATABASE=Integrated RAID + +pci:v00008086d000096A1* + ID_MODEL_FROM_DATABASE=Integrated RAID + +pci:v00008086d00009A0B* + ID_MODEL_FROM_DATABASE=Volume Management Device NVMe RAID Controller + +pci:v00008086d00009B41* + ID_MODEL_FROM_DATABASE=UHD Graphics + +pci:v00008086d00009C00* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [IDE mode] + +pci:v00008086d00009C01* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [IDE mode] + +pci:v00008086d00009C02* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [AHCI mode] + +pci:v00008086d00009C03* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [AHCI mode] + +pci:v00008086d00009C03sv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [AHCI mode] (ThinkPad X240) + +pci:v00008086d00009C04* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] + +pci:v00008086d00009C05* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] + +pci:v00008086d00009C06* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] + +pci:v00008086d00009C07* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] + +pci:v00008086d00009C08* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 2 [IDE mode] + +pci:v00008086d00009C09* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 2 [IDE mode] + +pci:v00008086d00009C0A* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller [Reserved] + +pci:v00008086d00009C0B* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller [Reserved] + +pci:v00008086d00009C0C* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller [Reserved] + +pci:v00008086d00009C0D* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller [Reserved] + +pci:v00008086d00009C0E* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] + +pci:v00008086d00009C0F* + ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [RAID mode] + +pci:v00008086d00009C10* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 1 + +pci:v00008086d00009C11* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 1 + +pci:v00008086d00009C12* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 2 + +pci:v00008086d00009C13* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 2 + +pci:v00008086d00009C14* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 3 + +pci:v00008086d00009C15* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 3 + +pci:v00008086d00009C16* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 4 + +pci:v00008086d00009C17* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 4 + +pci:v00008086d00009C18* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 5 + +pci:v00008086d00009C19* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 5 + +pci:v00008086d00009C1A* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 6 + +pci:v00008086d00009C1B* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 6 + +pci:v00008086d00009C1C* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 7 + +pci:v00008086d00009C1D* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 7 + +pci:v00008086d00009C1E* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 8 + +pci:v00008086d00009C1F* + ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 8 + +pci:v00008086d00009C20* + ID_MODEL_FROM_DATABASE=8 Series HD Audio Controller + +pci:v00008086d00009C20sv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=8 Series HD Audio Controller (ThinkPad X240) + +pci:v00008086d00009C21* + ID_MODEL_FROM_DATABASE=8 Series HD Audio Controller + +pci:v00008086d00009C22* + ID_MODEL_FROM_DATABASE=8 Series SMBus Controller + +pci:v00008086d00009C22sv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=8 Series SMBus Controller (ThinkPad X240) + +pci:v00008086d00009C23* + ID_MODEL_FROM_DATABASE=8 Series CHAP Counters + +pci:v00008086d00009C24* + ID_MODEL_FROM_DATABASE=8 Series Thermal + +pci:v00008086d00009C26* + ID_MODEL_FROM_DATABASE=8 Series USB EHCI #1 + +pci:v00008086d00009C26sv000017AAsd0000220C* + ID_MODEL_FROM_DATABASE=8 Series USB EHCI #1 (T440s) + +pci:v00008086d00009C26sv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=8 Series USB EHCI #1 (ThinkPad X240) + +pci:v00008086d00009C2D* + ID_MODEL_FROM_DATABASE=8 Series USB EHCI #2 + +pci:v00008086d00009C31* + ID_MODEL_FROM_DATABASE=8 Series USB xHCI HC + +pci:v00008086d00009C31sv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=8 Series USB xHCI HC (ThinkPad X240) + +pci:v00008086d00009C31sv00008086sd00007270* + ID_MODEL_FROM_DATABASE=8 Series USB xHCI HC (Apple MacBookAir6,2 / MacBookPro11,1) + +pci:v00008086d00009C35* + ID_MODEL_FROM_DATABASE=8 Series SDIO Controller + +pci:v00008086d00009C36* + ID_MODEL_FROM_DATABASE=8 Series Audio DSP Controller + +pci:v00008086d00009C3A* + ID_MODEL_FROM_DATABASE=8 Series HECI #0 + +pci:v00008086d00009C3Asv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=8 Series HECI #0 (ThinkPad X240) + +pci:v00008086d00009C3B* + ID_MODEL_FROM_DATABASE=8 Series HECI #1 + +pci:v00008086d00009C3C* + ID_MODEL_FROM_DATABASE=8 Series HECI IDER + +pci:v00008086d00009C3D* + ID_MODEL_FROM_DATABASE=8 Series HECI KT + +pci:v00008086d00009C40* + ID_MODEL_FROM_DATABASE=8 Series LPC Controller + +pci:v00008086d00009C41* + ID_MODEL_FROM_DATABASE=8 Series LPC Controller + +pci:v00008086d00009C42* + ID_MODEL_FROM_DATABASE=8 Series LPC Controller + +pci:v00008086d00009C43* + ID_MODEL_FROM_DATABASE=8 Series LPC Controller + +pci:v00008086d00009C43sv000017AAsd00002214* + ID_MODEL_FROM_DATABASE=8 Series LPC Controller (ThinkPad X240) + +pci:v00008086d00009C44* + ID_MODEL_FROM_DATABASE=8 Series LPC Controller + +pci:v00008086d00009C45* + ID_MODEL_FROM_DATABASE=8 Series LPC Controller + +pci:v00008086d00009C46* + ID_MODEL_FROM_DATABASE=8 Series LPC Controller + +pci:v00008086d00009C47* + ID_MODEL_FROM_DATABASE=8 Series LPC Controller + +pci:v00008086d00009C60* + ID_MODEL_FROM_DATABASE=8 Series Low Power Sub-System DMA + +pci:v00008086d00009C61* + ID_MODEL_FROM_DATABASE=8 Series I2C Controller #0 + +pci:v00008086d00009C62* + ID_MODEL_FROM_DATABASE=8 Series I2C Controller #1 + +pci:v00008086d00009C63* + ID_MODEL_FROM_DATABASE=8 Series UART Controller #0 + +pci:v00008086d00009C64* + ID_MODEL_FROM_DATABASE=8 Series UART Controller #1 + +pci:v00008086d00009C65* + ID_MODEL_FROM_DATABASE=8 Series SPI Controller #0 + +pci:v00008086d00009C66* + ID_MODEL_FROM_DATABASE=8 Series SPI Controller #1 + +pci:v00008086d00009C83* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP SATA Controller [AHCI Mode] + +pci:v00008086d00009C85* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP SATA Controller [RAID Mode] + +pci:v00008086d00009C87* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP SATA Controller [RAID Mode] + +pci:v00008086d00009C8F* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP SATA Controller [RAID Mode] + +pci:v00008086d00009C90* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #1 + +pci:v00008086d00009C92* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #2 + +pci:v00008086d00009C94* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #3 + +pci:v00008086d00009C96* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #4 + +pci:v00008086d00009C98* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #5 + +pci:v00008086d00009C9A* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP PCI Express Root Port #6 + +pci:v00008086d00009CA0* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP High Definition Audio Controller + +pci:v00008086d00009CA2* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP SMBus Controller + +pci:v00008086d00009CA4* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP Thermal Management Controller + +pci:v00008086d00009CA6* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP USB EHCI Controller + +pci:v00008086d00009CB1* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP USB xHCI Controller + +pci:v00008086d00009CB5* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP Secure Digital IO Controller + +pci:v00008086d00009CB6* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP Smart Sound Technology Controller + +pci:v00008086d00009CBA* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP MEI Controller #1 + +pci:v00008086d00009CBB* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP MEI Controller #2 + +pci:v00008086d00009CBC* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP IDE-r Controller + +pci:v00008086d00009CBD* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP KT Controller + +pci:v00008086d00009CC1* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller + +pci:v00008086d00009CC2* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller + +pci:v00008086d00009CC3* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller + +pci:v00008086d00009CC5* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller + +pci:v00008086d00009CC6* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller + +pci:v00008086d00009CC7* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller + +pci:v00008086d00009CC9* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP LPC Controller + +pci:v00008086d00009CE0* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO DMA Controller + +pci:v00008086d00009CE1* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO I2C Controller #0 + +pci:v00008086d00009CE2* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO I2C Controller #1 + +pci:v00008086d00009CE3* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO UART Controller #0 + +pci:v00008086d00009CE4* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO UART Controller #1 + +pci:v00008086d00009CE5* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO GSPI Controller #0 + +pci:v00008086d00009CE6* + ID_MODEL_FROM_DATABASE=Wildcat Point-LP Serial IO GSPI Controller #1 + +pci:v00008086d00009D03* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] + +pci:v00008086d00009D03sv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (Latitude E7470) + +pci:v00008086d00009D03sv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (Latitude 3570) + +pci:v00008086d00009D03sv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (EliteBook 840 G3) + +pci:v00008086d00009D03sv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (ThinkPad T480) + +pci:v00008086d00009D03sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SATA Controller [AHCI mode] (B51-80 Laptop) + +pci:v00008086d00009D10* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #1 + +pci:v00008086d00009D11* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #2 + +pci:v00008086d00009D12* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #3 + +pci:v00008086d00009D13* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #4 + +pci:v00008086d00009D14* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #5 + +pci:v00008086d00009D14sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #5 (B51-80 Laptop) + +pci:v00008086d00009D15* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #6 + +pci:v00008086d00009D15sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #6 (B51-80 Laptop) + +pci:v00008086d00009D16* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #7 + +pci:v00008086d00009D17* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #8 + +pci:v00008086d00009D18* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #9 + +pci:v00008086d00009D18sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #9 (B51-80 Laptop) + +pci:v00008086d00009D19* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #10 + +pci:v00008086d00009D1A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PCI Express Root Port #11 + +pci:v00008086d00009D21* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC + +pci:v00008086d00009D21sv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (Latitude E7470) + +pci:v00008086d00009D21sv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (Latitude 3570) + +pci:v00008086d00009D21sv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (EliteBook 840 G3) + +pci:v00008086d00009D21sv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (ThinkPad X1 Carbon 5th Gen) + +pci:v00008086d00009D21sv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (ThinkPad T480) + +pci:v00008086d00009D21sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP PMC (B51-80 Laptop) + +pci:v00008086d00009D23* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus + +pci:v00008086d00009D23sv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (Latitude E7470) + +pci:v00008086d00009D23sv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (Latitude 3570) + +pci:v00008086d00009D23sv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (EliteBook 840 G3) + +pci:v00008086d00009D23sv000017AAsd00002247* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (ThinkPad T570) + +pci:v00008086d00009D23sv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (ThinkPad X1 Carbon 5th Gen) + +pci:v00008086d00009D23sv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (ThinkPad T480) + +pci:v00008086d00009D23sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP SMBus (B51-80 Laptop) + +pci:v00008086d00009D27* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO UART Controller #0 + +pci:v00008086d00009D28* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO UART Controller #1 + +pci:v00008086d00009D29* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO SPI Controller #0 + +pci:v00008086d00009D2A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO SPI Controller #1 + +pci:v00008086d00009D2D* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Secure Digital IO Controller + +pci:v00008086d00009D2F* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller + +pci:v00008086d00009D2Fsv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (Latitude E7470) + +pci:v00008086d00009D2Fsv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (Latitude 3570) + +pci:v00008086d00009D2Fsv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (EliteBook 840 G3) + +pci:v00008086d00009D2Fsv000017AAsd00002247* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (ThinkPad T570) + +pci:v00008086d00009D2Fsv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (ThinkPad T480) + +pci:v00008086d00009D2Fsv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP USB 3.0 xHCI Controller (B51-80 Laptop) + +pci:v00008086d00009D31* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem + +pci:v00008086d00009D31sv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (Latitude E7470) + +pci:v00008086d00009D31sv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (Latitude 3570) + +pci:v00008086d00009D31sv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (EliteBook 840 G3) + +pci:v00008086d00009D31sv000017AAsd00002247* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (ThinkPad T570) + +pci:v00008086d00009D31sv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (ThinkPad X1 Carbon 5th Gen) + +pci:v00008086d00009D31sv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (ThinkPad T480) + +pci:v00008086d00009D31sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Thermal subsystem (B51-80 Laptop) + +pci:v00008086d00009D35* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Integrated Sensor Hub + +pci:v00008086d00009D3A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 + +pci:v00008086d00009D3Asv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (Latitude E7470) + +pci:v00008086d00009D3Asv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (Latitude 3570) + +pci:v00008086d00009D3Asv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (EliteBook 840 G3) + +pci:v00008086d00009D3Asv000017AAsd00002247* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (ThinkPad T570) + +pci:v00008086d00009D3Asv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (ThinkPad X1 Carbon 5th Gen) + +pci:v00008086d00009D3Asv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (ThinkPad T480) + +pci:v00008086d00009D3Asv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP CSME HECI #1 (B51-80 Laptop) + +pci:v00008086d00009D3D* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Active Management Technology - SOL + +pci:v00008086d00009D3Dsv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Active Management Technology - SOL (EliteBook 840 G3) + +pci:v00008086d00009D43* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller + +pci:v00008086d00009D43sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (B51-80 Laptop) + +pci:v00008086d00009D48* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller + +pci:v00008086d00009D48sv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (Latitude E7470) + +pci:v00008086d00009D48sv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (Latitude 3570) + +pci:v00008086d00009D48sv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (EliteBook 840 G3) + +pci:v00008086d00009D4E* + ID_MODEL_FROM_DATABASE=Sunrise Point LPC Controller/eSPI Controller + +pci:v00008086d00009D4Esv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Sunrise Point LPC Controller/eSPI Controller (ThinkPad T480) + +pci:v00008086d00009D50* + ID_MODEL_FROM_DATABASE=Sunrise Point LPC Controller + +pci:v00008086d00009D56* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller + +pci:v00008086d00009D58* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller + +pci:v00008086d00009D58sv000017AAsd00002247* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (ThinkPad T570) + +pci:v00008086d00009D58sv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP LPC Controller (ThinkPad X1 Carbon 5th Gen) + +pci:v00008086d00009D60* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 + +pci:v00008086d00009D60sv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 (Latitude 3570) + +pci:v00008086d00009D60sv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 (EliteBook 840 G3) + +pci:v00008086d00009D60sv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 (ThinkPad T480) + +pci:v00008086d00009D60sv00008086sd00009D60* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #0 (100 Series PCH/Sunrise Point PCH I2C0 [Skylake/Kaby Lake LPSS I2C]) + +pci:v00008086d00009D61* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #1 + +pci:v00008086d00009D62* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #2 + +pci:v00008086d00009D63* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #3 + +pci:v00008086d00009D64* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #4 + +pci:v00008086d00009D65* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO I2C Controller #5 + +pci:v00008086d00009D66* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP Serial IO UART Controller #2 + +pci:v00008086d00009D70* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio + +pci:v00008086d00009D70sv00001028sd000006DC* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (Latitude E7470) + +pci:v00008086d00009D70sv00001028sd000006F3* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (Latitude 3570) + +pci:v00008086d00009D70sv0000103Csd00008079* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (EliteBook 840 G3) + +pci:v00008086d00009D70sv000017AAsd0000382A* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (B51-80 Laptop) + +pci:v00008086d00009D71* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio + +pci:v00008086d00009D71sv000017AAsd0000224F* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (ThinkPad X1 Carbon 5th Gen) + +pci:v00008086d00009D71sv000017AAsd0000225D* + ID_MODEL_FROM_DATABASE=Sunrise Point-LP HD Audio (ThinkPad T480) + +pci:v00008086d00009D84* + ID_MODEL_FROM_DATABASE=Cannon Point-LP LPC Controller + +pci:v00008086d00009D84sv00001028sd0000089E* + ID_MODEL_FROM_DATABASE=Cannon Point-LP LPC Controller (Inspiron 5482) + +pci:v00008086d00009DA3* + ID_MODEL_FROM_DATABASE=Cannon Point-LP SMBus Controller + +pci:v00008086d00009DA4* + ID_MODEL_FROM_DATABASE=Cannon Point-LP SPI Controller + +pci:v00008086d00009DB0* + ID_MODEL_FROM_DATABASE=Cannon Point-LP PCI Express Root Port #9 + +pci:v00008086d00009DB1* + ID_MODEL_FROM_DATABASE=Cannon Point-LP PCI Express Root Port #10 + +pci:v00008086d00009DB2* + ID_MODEL_FROM_DATABASE=Cannon Point-LP PCI Express Root Port #1 + +pci:v00008086d00009DB4* + ID_MODEL_FROM_DATABASE=Cannon Point-LP PCI Express Root Port #13 + +pci:v00008086d00009DB4sv00001028sd0000089E* + ID_MODEL_FROM_DATABASE=Cannon Point-LP PCI Express Root Port #13 (Inspiron 5482) + +pci:v00008086d00009DB6* + ID_MODEL_FROM_DATABASE=Cannon Point-LP PCI Express Root Port #15 + +pci:v00008086d00009DB8* + ID_MODEL_FROM_DATABASE=Cannon Point-LP PCI Express Root Port #1 + +pci:v00008086d00009DBC* + ID_MODEL_FROM_DATABASE=Cannon Point-LP PCI Express Root Port #5 + +pci:v00008086d00009DBE* + ID_MODEL_FROM_DATABASE=Cannon Point-LP PCI Express Root Port #7 + +pci:v00008086d00009DBF* + ID_MODEL_FROM_DATABASE=Cannon Point PCI Express Root Port #8 + +pci:v00008086d00009DC5* + ID_MODEL_FROM_DATABASE=Cannon Point-LP Serial IO I2C Host Controller + +pci:v00008086d00009DC8* + ID_MODEL_FROM_DATABASE=Cannon Point-LP High Definition Audio Controller + +pci:v00008086d00009DC8sv00001028sd0000089E* + ID_MODEL_FROM_DATABASE=Cannon Point-LP High Definition Audio Controller (Inspiron 5482) + +pci:v00008086d00009DD3* + ID_MODEL_FROM_DATABASE=Cannon Point-LP SATA Controller [AHCI Mode] + +pci:v00008086d00009DE0* + ID_MODEL_FROM_DATABASE=Cannon Point-LP MEI Controller #1 + +pci:v00008086d00009DE3* + ID_MODEL_FROM_DATABASE=Cannon Point-LP Keyboard and Text (KT) Redirection + +pci:v00008086d00009DE8* + ID_MODEL_FROM_DATABASE=Cannon Point-LP Serial IO I2C Controller #0 + +pci:v00008086d00009DE8sv00001028sd0000089E* + ID_MODEL_FROM_DATABASE=Cannon Point-LP Serial IO I2C Controller #0 (Inspiron 5482) + +pci:v00008086d00009DE9* + ID_MODEL_FROM_DATABASE=Cannon Point-LP Serial IO I2C Controller #1 + +pci:v00008086d00009DE9sv00001028sd0000089E* + ID_MODEL_FROM_DATABASE=Cannon Point-LP Serial IO I2C Controller #1 (Inspiron 5482) + +pci:v00008086d00009DED* + ID_MODEL_FROM_DATABASE=Cannon Point-LP USB 3.1 xHCI Controller + +pci:v00008086d00009DEF* + ID_MODEL_FROM_DATABASE=Cannon Point-LP Shared SRAM + +pci:v00008086d00009DF0* + ID_MODEL_FROM_DATABASE=Cannon Point-LP CNVi [Wireless-AC] + +pci:v00008086d00009DF5* + ID_MODEL_FROM_DATABASE=BayHubTech Integrated SD controller + +pci:v00008086d00009DF9* + ID_MODEL_FROM_DATABASE=Cannon Point-LP Thermal Controller + +pci:v00008086d00009DFC* + ID_MODEL_FROM_DATABASE=Cannon Point-LP Integrated Sensor Hub + +pci:v00008086d0000A000* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge + +pci:v00008086d0000A000sv00001458sd00005000* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge (GA-D525TUD) + +pci:v00008086d0000A000sv00008086sd00004F4D* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge (DeskTop Board D510MO) + +pci:v00008086d0000A000sv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge (Desktop Board D425KT) + +pci:v00008086d0000A001* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller + +pci:v00008086d0000A001sv00001458sd0000D000* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (GA-D525TUD) + +pci:v00008086d0000A001sv00008086sd00004F4D* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (DeskTop Board D510MO) + +pci:v00008086d0000A001sv00008086sd0000544B* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (Desktop Board D425KT) + +pci:v00008086d0000A002* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller + +pci:v00008086d0000A003* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx CHAPS counter + +pci:v00008086d0000A010* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge + +pci:v00008086d0000A010sv00001043sd000083AC* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge (Eee PC 1015PX) + +pci:v00008086d0000A010sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge (Notebook N150P) + +pci:v00008086d0000A011* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller + +pci:v00008086d0000A011sv00001043sd000083AC* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (Eee PC 1015PX) + +pci:v00008086d0000A011sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (Notebook N150P) + +pci:v00008086d0000A012* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller + +pci:v00008086d0000A012sv00001043sd000083AC* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (Eee PC 1015PX) + +pci:v00008086d0000A012sv0000144Dsd0000C072* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller (Notebook N150P) + +pci:v00008086d0000A013* + ID_MODEL_FROM_DATABASE=Atom Processor D4xx/D5xx/N4xx/N5xx CHAPS counter + +pci:v00008086d0000A102* + ID_MODEL_FROM_DATABASE=Q170/Q150/B150/H170/H110/Z170/CM236 Chipset SATA Controller [AHCI Mode] + +pci:v00008086d0000A103* + ID_MODEL_FROM_DATABASE=HM170/QM170 Chipset SATA Controller [AHCI Mode] + +pci:v00008086d0000A103sv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=HM170/QM170 Chipset SATA Controller [AHCI Mode] (XPS 15 9550) + +pci:v00008086d0000A105* + ID_MODEL_FROM_DATABASE=Sunrise Point-H SATA Controller [RAID mode] + +pci:v00008086d0000A106* + ID_MODEL_FROM_DATABASE=Q170/H170/Z170/CM236 Chipset SATA Controller [RAID Mode] + +pci:v00008086d0000A107* + ID_MODEL_FROM_DATABASE=HM170/QM170 Chipset SATA Controller [RAID Mode] + +pci:v00008086d0000A10F* + ID_MODEL_FROM_DATABASE=Sunrise Point-H SATA Controller [RAID mode] + +pci:v00008086d0000A110* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #1 + +pci:v00008086d0000A111* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #2 + +pci:v00008086d0000A112* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #3 + +pci:v00008086d0000A113* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #4 + +pci:v00008086d0000A114* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #5 + +pci:v00008086d0000A115* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #6 + +pci:v00008086d0000A116* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #7 + +pci:v00008086d0000A117* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #8 + +pci:v00008086d0000A118* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #9 + +pci:v00008086d0000A119* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #10 + +pci:v00008086d0000A11A* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #11 + +pci:v00008086d0000A11B* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #12 + +pci:v00008086d0000A11C* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #13 + +pci:v00008086d0000A11D* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #14 + +pci:v00008086d0000A11E* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #15 + +pci:v00008086d0000A11F* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #16 + +pci:v00008086d0000A120* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family P2SB + +pci:v00008086d0000A121* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Power Management Controller + +pci:v00008086d0000A121sv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Power Management Controller (XPS 15 9550) + +pci:v00008086d0000A122* + ID_MODEL_FROM_DATABASE=Sunrise Point-H cAVS + +pci:v00008086d0000A123* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family SMBus + +pci:v00008086d0000A123sv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family SMBus (XPS 15 9550) + +pci:v00008086d0000A124* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family SPI Controller + +pci:v00008086d0000A125* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Gigabit Ethernet Controller + +pci:v00008086d0000A126* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Trace Hub + +pci:v00008086d0000A127* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO UART #0 + +pci:v00008086d0000A128* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO UART #1 + +pci:v00008086d0000A129* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO GSPI #0 + +pci:v00008086d0000A12A* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO GSPI #1 + +pci:v00008086d0000A12F* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family USB 3.0 xHCI Controller + +pci:v00008086d0000A12Fsv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family USB 3.0 xHCI Controller (XPS 15 9550) + +pci:v00008086d0000A130* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family USB Device Controller (OTG) + +pci:v00008086d0000A131* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Thermal Subsystem + +pci:v00008086d0000A131sv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Thermal Subsystem (XPS 15 9550) + +pci:v00008086d0000A133* + ID_MODEL_FROM_DATABASE=Sunrise Point-H Northpeak ACPI Function + +pci:v00008086d0000A135* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Integrated Sensor Hub + +pci:v00008086d0000A13A* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family MEI Controller #1 + +pci:v00008086d0000A13Asv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family MEI Controller #1 (XPS 15 9550) + +pci:v00008086d0000A13B* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family MEI Controller #2 + +pci:v00008086d0000A13C* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family IDE Redirection + +pci:v00008086d0000A13D* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family KT Redirection + +pci:v00008086d0000A13E* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family MEI Controller #3 + +pci:v00008086d0000A140* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A141* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A142* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A143* + ID_MODEL_FROM_DATABASE=H110 Chipset LPC/eSPI Controller + +pci:v00008086d0000A144* + ID_MODEL_FROM_DATABASE=H170 Chipset LPC/eSPI Controller + +pci:v00008086d0000A145* + ID_MODEL_FROM_DATABASE=Z170 Chipset LPC/eSPI Controller + +pci:v00008086d0000A146* + ID_MODEL_FROM_DATABASE=Q170 Chipset LPC/eSPI Controller + +pci:v00008086d0000A147* + ID_MODEL_FROM_DATABASE=Q150 Chipset LPC/eSPI Controller + +pci:v00008086d0000A148* + ID_MODEL_FROM_DATABASE=B150 Chipset LPC/eSPI Controller + +pci:v00008086d0000A149* + ID_MODEL_FROM_DATABASE=C236 Chipset LPC/eSPI Controller + +pci:v00008086d0000A14A* + ID_MODEL_FROM_DATABASE=C232 Chipset LPC/eSPI Controller + +pci:v00008086d0000A14B* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A14C* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A14D* + ID_MODEL_FROM_DATABASE=QM170 Chipset LPC/eSPI Controller + +pci:v00008086d0000A14E* + ID_MODEL_FROM_DATABASE=HM170 Chipset LPC/eSPI Controller + +pci:v00008086d0000A14Esv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=HM170 Chipset LPC/eSPI Controller (XPS 15 9550) + +pci:v00008086d0000A14F* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A150* + ID_MODEL_FROM_DATABASE=CM236 Chipset LPC/eSPI Controller + +pci:v00008086d0000A151* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A152* + ID_MODEL_FROM_DATABASE=HM175 Chipset LPC/eSPI Controller + +pci:v00008086d0000A153* + ID_MODEL_FROM_DATABASE=QM175 Chipset LPC/eSPI Controller + +pci:v00008086d0000A154* + ID_MODEL_FROM_DATABASE=CM238 Chipset LPC/eSPI Controller + +pci:v00008086d0000A155* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A156* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A157* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A158* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A159* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A15A* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A15B* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A15C* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A15D* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A15E* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A15F* + ID_MODEL_FROM_DATABASE=Sunrise Point-H LPC Controller + +pci:v00008086d0000A160* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO I2C Controller #0 + +pci:v00008086d0000A160sv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO I2C Controller #0 (XPS 15 9550) + +pci:v00008086d0000A161* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO I2C Controller #1 + +pci:v00008086d0000A161sv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO I2C Controller #1 (XPS 15 9550) + +pci:v00008086d0000A162* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO I2C Controller #2 + +pci:v00008086d0000A163* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO I2C Controller #3 + +pci:v00008086d0000A166* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family Serial IO UART Controller #2 + +pci:v00008086d0000A167* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #17 + +pci:v00008086d0000A168* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #18 + +pci:v00008086d0000A169* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #19 + +pci:v00008086d0000A16A* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family PCI Express Root Port #20 + +pci:v00008086d0000A170* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family HD Audio Controller + +pci:v00008086d0000A170sv00001028sd000006E4* + ID_MODEL_FROM_DATABASE=100 Series/C230 Series Chipset Family HD Audio Controller (XPS 15 9550) + +pci:v00008086d0000A171* + ID_MODEL_FROM_DATABASE=CM238 HD Audio Controller + +pci:v00008086d0000A182* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family SATA Controller [AHCI mode] + +pci:v00008086d0000A186* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family SATA Controller [RAID mode] + +pci:v00008086d0000A190* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #1 + +pci:v00008086d0000A191* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #2 + +pci:v00008086d0000A192* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #3 + +pci:v00008086d0000A193* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #4 + +pci:v00008086d0000A194* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #5 + +pci:v00008086d0000A195* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #6 + +pci:v00008086d0000A196* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #7 + +pci:v00008086d0000A197* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #8 + +pci:v00008086d0000A198* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #9 + +pci:v00008086d0000A199* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #10 + +pci:v00008086d0000A19A* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #11 + +pci:v00008086d0000A19B* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #12 + +pci:v00008086d0000A19C* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #13 + +pci:v00008086d0000A19D* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #14 + +pci:v00008086d0000A19E* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #15 + +pci:v00008086d0000A19F* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #16 + +pci:v00008086d0000A1A0* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family P2SB + +pci:v00008086d0000A1A1* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family Power Management Controller + +pci:v00008086d0000A1A1sv000015D9sd0000095D* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family Power Management Controller (X11SPM-TF) + +pci:v00008086d0000A1A2* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family cAVS + +pci:v00008086d0000A1A3* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family SMBus + +pci:v00008086d0000A1A3sv000015D9sd0000095D* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family SMBus (X11SPM-TF) + +pci:v00008086d0000A1A4* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family SPI Controller + +pci:v00008086d0000A1A4sv000015D9sd0000095D* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family SPI Controller (X11SPM-TF) + +pci:v00008086d0000A1A6* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family Trace Hub + +pci:v00008086d0000A1AF* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family USB 3.0 xHCI Controller + +pci:v00008086d0000A1AFsv000015D9sd0000095D* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family USB 3.0 xHCI Controller (X11SPM-TF) + +pci:v00008086d0000A1B1* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family Thermal Subsystem + +pci:v00008086d0000A1B1sv000015D9sd0000095D* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family Thermal Subsystem (X11SPM-TF) + +pci:v00008086d0000A1BA* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family MEI Controller #1 + +pci:v00008086d0000A1BAsv000015D9sd0000095D* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family MEI Controller #1 (X11SPM-TF) + +pci:v00008086d0000A1BB* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family MEI Controller #2 + +pci:v00008086d0000A1BBsv000015D9sd0000095D* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family MEI Controller #2 (X11SPM-TF) + +pci:v00008086d0000A1BC* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family IDE Redirection + +pci:v00008086d0000A1BD* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family KT Redirection + +pci:v00008086d0000A1BE* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family MEI Controller #3 + +pci:v00008086d0000A1BEsv000015D9sd0000095D* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family MEI Controller #3 (X11SPM-TF) + +pci:v00008086d0000A1C1* + ID_MODEL_FROM_DATABASE=C621 Series Chipset LPC/eSPI Controller + +pci:v00008086d0000A1C2* + ID_MODEL_FROM_DATABASE=C622 Series Chipset LPC/eSPI Controller + +pci:v00008086d0000A1C2sv000015D9sd0000095D* + ID_MODEL_FROM_DATABASE=C622 Series Chipset LPC/eSPI Controller (X11SPM-TF) + +pci:v00008086d0000A1C3* + ID_MODEL_FROM_DATABASE=C624 Series Chipset LPC/eSPI Controller + +pci:v00008086d0000A1C4* + ID_MODEL_FROM_DATABASE=C625 Series Chipset LPC/eSPI Controller + +pci:v00008086d0000A1C5* + ID_MODEL_FROM_DATABASE=C626 Series Chipset LPC/eSPI Controller + +pci:v00008086d0000A1C6* + ID_MODEL_FROM_DATABASE=C627 Series Chipset LPC/eSPI Controller + +pci:v00008086d0000A1C7* + ID_MODEL_FROM_DATABASE=C628 Series Chipset LPC/eSPI Controller + +pci:v00008086d0000A1D2* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family SSATA Controller [AHCI mode] + +pci:v00008086d0000A1D6* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family SSATA Controller [RAID mode] + +pci:v00008086d0000A1E7* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #17 + +pci:v00008086d0000A1E8* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #18 + +pci:v00008086d0000A1E9* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #19 + +pci:v00008086d0000A1EA* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family PCI Express Root Port #20 + +pci:v00008086d0000A1EC* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family MROM 0 + +pci:v00008086d0000A1ED* + ID_MODEL_FROM_DATABASE=C620 Series Chipset Family MROM 1 + +pci:v00008086d0000A1F8* + ID_MODEL_FROM_DATABASE=Lewisburg IE: HECI #1 + +pci:v00008086d0000A1F9* + ID_MODEL_FROM_DATABASE=Lewisburg IE: HECI #2 + +pci:v00008086d0000A1FA* + ID_MODEL_FROM_DATABASE=Lewisburg IE: IDE-r + +pci:v00008086d0000A1FB* + ID_MODEL_FROM_DATABASE=Lewisburg IE: KT Controller + +pci:v00008086d0000A1FC* + ID_MODEL_FROM_DATABASE=Lewisburg IE: HECI #3 + +pci:v00008086d0000A202* + ID_MODEL_FROM_DATABASE=Lewisburg SATA Controller [AHCI mode] + +pci:v00008086d0000A206* + ID_MODEL_FROM_DATABASE=Lewisburg SATA Controller [RAID mode] + +pci:v00008086d0000A223* + ID_MODEL_FROM_DATABASE=Lewisburg SMBus + +pci:v00008086d0000A224* + ID_MODEL_FROM_DATABASE=Lewisburg SPI Controller + +pci:v00008086d0000A242* + ID_MODEL_FROM_DATABASE=Lewisburg LPC or eSPI Controller + +pci:v00008086d0000A243* + ID_MODEL_FROM_DATABASE=Lewisburg LPC or eSPI Controller + +pci:v00008086d0000A252* + ID_MODEL_FROM_DATABASE=Lewisburg SSATA Controller [AHCI mode] + +pci:v00008086d0000A256* + ID_MODEL_FROM_DATABASE=Lewisburg SSATA Controller [RAID mode] + +pci:v00008086d0000A282* + ID_MODEL_FROM_DATABASE=200 Series PCH SATA controller [AHCI mode] + +pci:v00008086d0000A286* + ID_MODEL_FROM_DATABASE=200 Series PCH SATA controller [RAID mode] + +pci:v00008086d0000A290* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #1 + +pci:v00008086d0000A291* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #2 + +pci:v00008086d0000A292* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #3 + +pci:v00008086d0000A293* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #4 + +pci:v00008086d0000A294* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #5 + +pci:v00008086d0000A295* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #6 + +pci:v00008086d0000A296* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #7 + +pci:v00008086d0000A297* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #8 + +pci:v00008086d0000A298* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #9 + +pci:v00008086d0000A299* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #10 + +pci:v00008086d0000A29A* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #11 + +pci:v00008086d0000A29B* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #12 + +pci:v00008086d0000A29C* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #13 + +pci:v00008086d0000A29D* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #14 + +pci:v00008086d0000A29E* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #15 + +pci:v00008086d0000A29F* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #16 + +pci:v00008086d0000A2A0* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family P2SB + +pci:v00008086d0000A2A1* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family Power Management Controller + +pci:v00008086d0000A2A3* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family SMBus Controller + +pci:v00008086d0000A2A4* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family SPI Controller + +pci:v00008086d0000A2A5* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family Gigabit Ethernet Controller + +pci:v00008086d0000A2A6* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family Trace Hub + +pci:v00008086d0000A2A7* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family Serial IO UART Controller #0 + +pci:v00008086d0000A2A8* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family Serial IO UART Controller #1 + +pci:v00008086d0000A2A9* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family Serial IO SPI Controller #0 + +pci:v00008086d0000A2AA* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family Serial IO SPI Controller #1 + +pci:v00008086d0000A2AF* + ID_MODEL_FROM_DATABASE=200 Series/Z370 Chipset Family USB 3.0 xHCI Controller + +pci:v00008086d0000A2B1* + ID_MODEL_FROM_DATABASE=200 Series PCH Thermal Subsystem + +pci:v00008086d0000A2BA* + ID_MODEL_FROM_DATABASE=200 Series PCH CSME HECI #1 + +pci:v00008086d0000A2BB* + ID_MODEL_FROM_DATABASE=200 Series PCH CSME HECI #2 + +pci:v00008086d0000A2C4* + ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller (H270) + +pci:v00008086d0000A2C5* + ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller (Z270) + +pci:v00008086d0000A2C6* + ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller (Q270) + +pci:v00008086d0000A2C7* + ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller (Q250) + +pci:v00008086d0000A2C8* + ID_MODEL_FROM_DATABASE=200 Series PCH LPC Controller (B250) + +pci:v00008086d0000A2C9* + ID_MODEL_FROM_DATABASE=Z370 Chipset LPC/eSPI Controller + +pci:v00008086d0000A2D2* + ID_MODEL_FROM_DATABASE=X299 Chipset LPC/eSPI Controller + +pci:v00008086d0000A2D3* + ID_MODEL_FROM_DATABASE=C422 Chipset LPC/eSPI Controller + +pci:v00008086d0000A2E0* + ID_MODEL_FROM_DATABASE=200 Series PCH Serial IO I2C Controller #0 + +pci:v00008086d0000A2E1* + ID_MODEL_FROM_DATABASE=200 Series PCH Serial IO I2C Controller #1 + +pci:v00008086d0000A2E2* + ID_MODEL_FROM_DATABASE=200 Series PCH Serial IO I2C Controller #2 + +pci:v00008086d0000A2E3* + ID_MODEL_FROM_DATABASE=200 Series PCH Serial IO I2C Controller #3 + +pci:v00008086d0000A2E6* + ID_MODEL_FROM_DATABASE=200 Series PCH Serial IO UART Controller #2 + +pci:v00008086d0000A2E7* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #17 + +pci:v00008086d0000A2E8* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #18 + +pci:v00008086d0000A2E9* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #19 + +pci:v00008086d0000A2EA* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #20 + +pci:v00008086d0000A2EB* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #21 + +pci:v00008086d0000A2EC* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #22 + +pci:v00008086d0000A2ED* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #23 + +pci:v00008086d0000A2EE* + ID_MODEL_FROM_DATABASE=200 Series PCH PCI Express Root Port #24 + +pci:v00008086d0000A2F0* + ID_MODEL_FROM_DATABASE=200 Series PCH HD Audio + +pci:v00008086d0000A304* + ID_MODEL_FROM_DATABASE=H370 Chipset LPC/eSPI Controller + +pci:v00008086d0000A305* + ID_MODEL_FROM_DATABASE=Z390 Chipset LPC/eSPI Controller + +pci:v00008086d0000A306* + ID_MODEL_FROM_DATABASE=Q370 Chipset LPC/eSPI Controller + +pci:v00008086d0000A309* + ID_MODEL_FROM_DATABASE=Cannon Point-LP LPC Controller + +pci:v00008086d0000A30C* + ID_MODEL_FROM_DATABASE=QM370 Chipset LPC/eSPI Controller + +pci:v00008086d0000A323* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH SMBus Controller + +pci:v00008086d0000A324* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH SPI Controller + +pci:v00008086d0000A328* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH Serial IO UART Host Controller + +pci:v00008086d0000A32C* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #21 + +pci:v00008086d0000A32D* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #22 + +pci:v00008086d0000A32E* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #23 + +pci:v00008086d0000A32F* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #24 + +pci:v00008086d0000A330* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #9 + +pci:v00008086d0000A331* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #10 + +pci:v00008086d0000A332* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #11 + +pci:v00008086d0000A333* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #12 + +pci:v00008086d0000A334* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #13 + +pci:v00008086d0000A335* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #14 + +pci:v00008086d0000A336* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #15 + +pci:v00008086d0000A337* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #16 + +pci:v00008086d0000A338* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #1 + +pci:v00008086d0000A339* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #2 + +pci:v00008086d0000A33A* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #3 + +pci:v00008086d0000A33B* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #4 + +pci:v00008086d0000A33C* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #5 + +pci:v00008086d0000A33D* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #6 + +pci:v00008086d0000A33E* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #7 + +pci:v00008086d0000A33F* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #8 + +pci:v00008086d0000A340* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #17 + +pci:v00008086d0000A341* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #18 + +pci:v00008086d0000A342* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #19 + +pci:v00008086d0000A343* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH PCI Express Root Port #20 + +pci:v00008086d0000A348* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH cAVS + +pci:v00008086d0000A352* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH SATA AHCI Controller + +pci:v00008086d0000A353* + ID_MODEL_FROM_DATABASE=Cannon Lake Mobile PCH SATA AHCI Controller + +pci:v00008086d0000A360* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH HECI Controller + +pci:v00008086d0000A363* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH Active Management Technology - SOL + +pci:v00008086d0000A364* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH HECI Controller #2 + +pci:v00008086d0000A368* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH Serial IO I2C Controller #0 + +pci:v00008086d0000A369* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH Serial IO I2C Controller #1 + +pci:v00008086d0000A36A* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH Serial IO I2C Controller #2 + +pci:v00008086d0000A36B* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH Serial IO I2C Controller #3 + +pci:v00008086d0000A36D* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH USB 3.1 xHCI Host Controller + +pci:v00008086d0000A36F* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH Shared SRAM + +pci:v00008086d0000A370* + ID_MODEL_FROM_DATABASE=Wireless-AC 9560 [Jefferson Peak] + +pci:v00008086d0000A379* + ID_MODEL_FROM_DATABASE=Cannon Lake PCH Thermal Controller + +pci:v00008086d0000A620* + ID_MODEL_FROM_DATABASE=6400/6402 Advanced Memory Buffer (AMB) + +pci:v00008086d0000ABC0* + ID_MODEL_FROM_DATABASE=Omni-Path Fabric Switch Silicon 100 Series + +pci:v00008086d0000B152* + ID_MODEL_FROM_DATABASE=21152 PCI-to-PCI Bridge + +pci:v00008086d0000B152sv00008086sd0000B152* + ID_MODEL_FROM_DATABASE=21152 PCI-to-PCI Bridge + +pci:v00008086d0000B154* + ID_MODEL_FROM_DATABASE=21154 PCI-to-PCI Bridge + +pci:v00008086d0000B555* + ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge + +pci:v00008086d0000B555sv000012C7sd00005005* + ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (SS7HD PCI Adaptor Card) + +pci:v00008086d0000B555sv000012C7sd00005006* + ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (SS7HDC cPCI Adaptor Card) + +pci:v00008086d0000B555sv000012D9sd0000000A* + ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (PCI VoIP Gateway) + +pci:v00008086d0000B555sv00004C53sd00001050* + ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (CT7 mainboard) + +pci:v00008086d0000B555sv00004C53sd00001051* + ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (CE7 mainboard) + +pci:v00008086d0000B555sv0000E4BFsd00001000* + ID_MODEL_FROM_DATABASE=21555 Non transparent PCI-to-PCI Bridge (CC8-1-BLUES) + +pci:v00008086d0000D130* + ID_MODEL_FROM_DATABASE=Core Processor DMI + +pci:v00008086d0000D130sv000015D9sd00000605* + ID_MODEL_FROM_DATABASE=Core Processor DMI (X8SIL) + +pci:v00008086d0000D131* + ID_MODEL_FROM_DATABASE=Core Processor DMI + +pci:v00008086d0000D131sv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=Core Processor DMI (OptiPlex 980) + +pci:v00008086d0000D131sv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=Core Processor DMI (C7SIM-Q Motherboard) + +pci:v00008086d0000D132* + ID_MODEL_FROM_DATABASE=Core Processor DMI + +pci:v00008086d0000D132sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=Core Processor DMI (Latitude E6510) + +pci:v00008086d0000D133* + ID_MODEL_FROM_DATABASE=Core Processor DMI + +pci:v00008086d0000D134* + ID_MODEL_FROM_DATABASE=Core Processor DMI + +pci:v00008086d0000D135* + ID_MODEL_FROM_DATABASE=Core Processor DMI + +pci:v00008086d0000D136* + ID_MODEL_FROM_DATABASE=Core Processor DMI + +pci:v00008086d0000D137* + ID_MODEL_FROM_DATABASE=Core Processor DMI + +pci:v00008086d0000D138* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 1 + +pci:v00008086d0000D138sv00001028sd000002DA* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 1 (OptiPlex 980) + +pci:v00008086d0000D138sv00001028sd0000040B* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 1 (Latitude E6510) + +pci:v00008086d0000D138sv000015D9sd0000060D* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 1 (C7SIM-Q Motherboard) + +pci:v00008086d0000D139* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 2 + +pci:v00008086d0000D13A* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 3 + +pci:v00008086d0000D13B* + ID_MODEL_FROM_DATABASE=Core Processor PCI Express Root Port 4 + +pci:v00008086d0000D150* + ID_MODEL_FROM_DATABASE=Core Processor QPI Link + +pci:v00008086d0000D151* + ID_MODEL_FROM_DATABASE=Core Processor QPI Routing and Protocol Registers + +pci:v00008086d0000D155* + ID_MODEL_FROM_DATABASE=Core Processor System Management Registers + +pci:v00008086d0000D156* + ID_MODEL_FROM_DATABASE=Core Processor Semaphore and Scratchpad Registers + +pci:v00008086d0000D157* + ID_MODEL_FROM_DATABASE=Core Processor System Control and Status Registers + +pci:v00008086d0000D158* + ID_MODEL_FROM_DATABASE=Core Processor Miscellaneous Registers + +pci:v00008086d0000F1A5* + ID_MODEL_FROM_DATABASE=SSD 600P Series + +pci:v00008086d0000F1A6* + ID_MODEL_FROM_DATABASE=SSD Pro 7600p/760p/E 6100p Series + +pci:v00008086d0000F1A8* + ID_MODEL_FROM_DATABASE=SSD 660P Series + +pci:v00008088* + ID_VENDOR_FROM_DATABASE=Beijing Wangxun Technology Co., Ltd. + +pci:v00008088d00000101* + ID_MODEL_FROM_DATABASE=WX1860A2 Gigabit Ethernet Controller + +pci:v00008088d00000101sv00008088sd00000201* + ID_MODEL_FROM_DATABASE=WX1860A2 Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200T) + +pci:v00008088d00000102* + ID_MODEL_FROM_DATABASE=WX1860A2S Gigabit Ethernet Controller + +pci:v00008088d00000102sv00008088sd00000210* + ID_MODEL_FROM_DATABASE=WX1860A2S Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200T-S) + +pci:v00008088d00000103* + ID_MODEL_FROM_DATABASE=WX1860A4 Gigabit Ethernet Controller + +pci:v00008088d00000103sv00008088sd00000401* + ID_MODEL_FROM_DATABASE=WX1860A4 Gigabit Ethernet Controller (Qual-Port Ethernet Network Adaptor SF400T) + +pci:v00008088d00000103sv00008088sd00000440* + ID_MODEL_FROM_DATABASE=WX1860A4 Gigabit Ethernet Controller (Qual-Port Ethernet Network Adaptor SF400-OCP) + +pci:v00008088d00000104* + ID_MODEL_FROM_DATABASE=WX1860A4S Gigabit Ethernet Controller + +pci:v00008088d00000104sv00008088sd00000410* + ID_MODEL_FROM_DATABASE=WX1860A4S Gigabit Ethernet Controller (Qual-Port Ethernet Network Adaptor SF400T-S) + +pci:v00008088d00000105* + ID_MODEL_FROM_DATABASE=WX1860AL2 Gigabit Ethernet Controller + +pci:v00008088d00000105sv00008088sd00000202* + ID_MODEL_FROM_DATABASE=WX1860AL2 Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200HT) + +pci:v00008088d00000106* + ID_MODEL_FROM_DATABASE=WX1860AL2S Gigabit Ethernet Controller + +pci:v00008088d00000106sv00008088sd00000220* + ID_MODEL_FROM_DATABASE=WX1860AL2S Gigabit Ethernet Controller (Dual-Port Ethernet Network Adaptor SF200HT-S) + +pci:v00008088d00000107* + ID_MODEL_FROM_DATABASE=WX1860AL4 Gigabit Ethernet Controller + +pci:v00008088d00000107sv00008088sd00000402* + ID_MODEL_FROM_DATABASE=WX1860AL4 Gigabit Ethernet Controller (Qual-Port Ethernet Network Adaptor SF400HT) + +pci:v00008088d00000108* + ID_MODEL_FROM_DATABASE=WX1860AL4S Gigabit Ethernet Controller + +pci:v00008088d00000108sv00008088sd00000420* + ID_MODEL_FROM_DATABASE=WX1860AL4S Gigabit Ethernet Controller (Qual-Port Ethernet Network Adaptor SF400HT-S) + +pci:v00008088d00001001* + ID_MODEL_FROM_DATABASE=Ethernet Controller RP1000 for 10GbE SFP+ + +pci:v00008088d00001001sv00008088sd00000000* + ID_MODEL_FROM_DATABASE=Ethernet Controller RP1000 for 10GbE SFP+ (Ethernet Network Adaptor RP1000 for 10GbE SFP+) + +pci:v00008088d00002001* + ID_MODEL_FROM_DATABASE=Ethernet Controller RP2000 for 10GbE SFP+ + +pci:v00008088d00002001sv00008088sd00002000* + ID_MODEL_FROM_DATABASE=Ethernet Controller RP2000 for 10GbE SFP+ (Ethernet Network Adaptor RP2000 for 10GbE SFP+) + +pci:v000080EE* + ID_VENDOR_FROM_DATABASE=InnoTek Systemberatung GmbH + +pci:v000080EEd0000BEEF* + ID_MODEL_FROM_DATABASE=VirtualBox Graphics Adapter + +pci:v000080EEd0000CAFE* + ID_MODEL_FROM_DATABASE=VirtualBox Guest Service + +pci:v00008322* + ID_VENDOR_FROM_DATABASE=Sodick America Corp. + +pci:v00008384* + ID_VENDOR_FROM_DATABASE=SigmaTel + +pci:v00008401* + ID_VENDOR_FROM_DATABASE=TRENDware International Inc. + +pci:v00008686* + ID_VENDOR_FROM_DATABASE=ScaleMP + +pci:v00008686d00001010* + ID_MODEL_FROM_DATABASE=vSMP Foundation controller [vSMP CTL] + +pci:v00008686d00001011* + ID_MODEL_FROM_DATABASE=vSMP Foundation MEX/FLX controller [vSMP CTL] + +pci:v00008800* + ID_VENDOR_FROM_DATABASE=Trigem Computer Inc. + +pci:v00008800d00002008* + ID_MODEL_FROM_DATABASE=Video assistant component + +pci:v00008866* + ID_VENDOR_FROM_DATABASE=T-Square Design Inc. + +pci:v00008888* + ID_VENDOR_FROM_DATABASE=Silicon Magic + +pci:v00008912* + ID_VENDOR_FROM_DATABASE=TRX + +pci:v00008C4A* + ID_VENDOR_FROM_DATABASE=Winbond + +pci:v00008C4Ad00001980* + ID_MODEL_FROM_DATABASE=W89C940 misprogrammed [ne2k] + +pci:v00008E0E* + ID_VENDOR_FROM_DATABASE=Computone Corporation + +pci:v00008E2E* + ID_VENDOR_FROM_DATABASE=KTI + +pci:v00008E2Ed00003000* + ID_MODEL_FROM_DATABASE=ET32P2 + +pci:v00009004* + ID_VENDOR_FROM_DATABASE=Adaptec + +pci:v00009004d00000078* + ID_MODEL_FROM_DATABASE=AHA-2940U_CN + +pci:v00009004d00001078* + ID_MODEL_FROM_DATABASE=AIC-7810 + +pci:v00009004d00001160* + ID_MODEL_FROM_DATABASE=AIC-1160 [Family Fibre Channel Adapter] + +pci:v00009004d00002178* + ID_MODEL_FROM_DATABASE=AIC-7821 + +pci:v00009004d00003860* + ID_MODEL_FROM_DATABASE=AHA-2930CU + +pci:v00009004d00003B78* + ID_MODEL_FROM_DATABASE=AHA-4844W/4844UW + +pci:v00009004d00005075* + ID_MODEL_FROM_DATABASE=AIC-755x + +pci:v00009004d00005078* + ID_MODEL_FROM_DATABASE=AIC-7850T/7856T [AVA-2902/4/6 / AHA-2910] + +pci:v00009004d00005078sv00009004sd00007850* + ID_MODEL_FROM_DATABASE=AIC-7850T/7856T [AVA-2902/4/6 / AHA-2910] (AIC-7850T/7856T [AVA-290x / AHA-2910]) + +pci:v00009004d00005175* + ID_MODEL_FROM_DATABASE=AIC-755x + +pci:v00009004d00005178* + ID_MODEL_FROM_DATABASE=AIC-7851 + +pci:v00009004d00005275* + ID_MODEL_FROM_DATABASE=AIC-755x + +pci:v00009004d00005278* + ID_MODEL_FROM_DATABASE=AIC-7852 + +pci:v00009004d00005375* + ID_MODEL_FROM_DATABASE=AIC-755x + +pci:v00009004d00005378* + ID_MODEL_FROM_DATABASE=AIC-7850 + +pci:v00009004d00005475* + ID_MODEL_FROM_DATABASE=AIC-755x + +pci:v00009004d00005478* + ID_MODEL_FROM_DATABASE=AIC-7850 + +pci:v00009004d00005575* + ID_MODEL_FROM_DATABASE=AVA-2930 + +pci:v00009004d00005578* + ID_MODEL_FROM_DATABASE=AIC-7855 + +pci:v00009004d00005647* + ID_MODEL_FROM_DATABASE=ANA-7711 TCP Offload Engine + +pci:v00009004d00005647sv00009004sd00007710* + ID_MODEL_FROM_DATABASE=ANA-7711 TCP Offload Engine (ANA-7711F TCP Offload Engine - Optical) + +pci:v00009004d00005647sv00009004sd00007711* + ID_MODEL_FROM_DATABASE=ANA-7711 TCP Offload Engine (ANA-7711LP TCP Offload Engine - Copper) + +pci:v00009004d00005675* + ID_MODEL_FROM_DATABASE=AIC-755x + +pci:v00009004d00005678* + ID_MODEL_FROM_DATABASE=AIC-7856 + +pci:v00009004d00005775* + ID_MODEL_FROM_DATABASE=AIC-755x + +pci:v00009004d00005778* + ID_MODEL_FROM_DATABASE=AIC-7850 + +pci:v00009004d00005800* + ID_MODEL_FROM_DATABASE=AIC-5800 + +pci:v00009004d00005900* + ID_MODEL_FROM_DATABASE=ANA-5910/5930/5940 ATM155 & 25 LAN Adapter + +pci:v00009004d00005905* + ID_MODEL_FROM_DATABASE=ANA-5910A/5930A/5940A ATM Adapter + +pci:v00009004d00006038* + ID_MODEL_FROM_DATABASE=AIC-3860 + +pci:v00009004d00006075* + ID_MODEL_FROM_DATABASE=AIC-1480 / APA-1480 + +pci:v00009004d00006075sv00009004sd00007560* + ID_MODEL_FROM_DATABASE=AIC-1480 / APA-1480 (Cardbus) + +pci:v00009004d00006078* + ID_MODEL_FROM_DATABASE=AIC-7860 + +pci:v00009004d00006178* + ID_MODEL_FROM_DATABASE=AIC-7861 + +pci:v00009004d00006178sv00009004sd00007861* + ID_MODEL_FROM_DATABASE=AIC-7861 (AHA-2940AU Single) + +pci:v00009004d00006278* + ID_MODEL_FROM_DATABASE=AIC-7860 + +pci:v00009004d00006378* + ID_MODEL_FROM_DATABASE=AIC-7860 + +pci:v00009004d00006478* + ID_MODEL_FROM_DATABASE=AIC-786x + +pci:v00009004d00006578* + ID_MODEL_FROM_DATABASE=AIC-786x + +pci:v00009004d00006678* + ID_MODEL_FROM_DATABASE=AIC-786x + +pci:v00009004d00006778* + ID_MODEL_FROM_DATABASE=AIC-786x + +pci:v00009004d00006915* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A + +pci:v00009004d00006915sv00009004sd00000008* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 10/100) + +pci:v00009004d00006915sv00009004sd00000009* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 10/100) + +pci:v00009004d00006915sv00009004sd00000010* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62022 2-port 10/100) + +pci:v00009004d00006915sv00009004sd00000018* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62044 4-port 10/100) + +pci:v00009004d00006915sv00009004sd00000019* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62044 4-port 10/100) + +pci:v00009004d00006915sv00009004sd00000020* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62022 2-port 10/100) + +pci:v00009004d00006915sv00009004sd00000028* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 10/100) + +pci:v00009004d00006915sv00009004sd00008008* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 64 bit 10/100) + +pci:v00009004d00006915sv00009004sd00008009* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 64 bit 10/100) + +pci:v00009004d00006915sv00009004sd00008010* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62022 2-port 64 bit 10/100) + +pci:v00009004d00006915sv00009004sd00008018* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62044 4-port 64 bit 10/100) + +pci:v00009004d00006915sv00009004sd00008019* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62044 4-port 64 bit 10/100) + +pci:v00009004d00006915sv00009004sd00008020* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA62022 2-port 64 bit 10/100) + +pci:v00009004d00006915sv00009004sd00008028* + ID_MODEL_FROM_DATABASE=ANA620xx/ANA69011A (ANA69011A/TX 64 bit 10/100) + +pci:v00009004d00007078* + ID_MODEL_FROM_DATABASE=AHA-294x / AIC-7870 + +pci:v00009004d00007178* + ID_MODEL_FROM_DATABASE=AIC-7870P/7871 [AHA-2940/W/S76] + +pci:v00009004d00007278* + ID_MODEL_FROM_DATABASE=AHA-3940/3940W / AIC-7872 + +pci:v00009004d00007378* + ID_MODEL_FROM_DATABASE=AHA-3985 / AIC-7873 + +pci:v00009004d00007478* + ID_MODEL_FROM_DATABASE=AHA-2944/2944W / AIC-7874 + +pci:v00009004d00007578* + ID_MODEL_FROM_DATABASE=AHA-3944/3944W / AIC-7875 + +pci:v00009004d00007678* + ID_MODEL_FROM_DATABASE=AHA-4944W/UW / AIC-7876 + +pci:v00009004d00007710* + ID_MODEL_FROM_DATABASE=ANA-7711F Network Accelerator Card (NAC) - Optical + +pci:v00009004d00007711* + ID_MODEL_FROM_DATABASE=ANA-7711C Network Accelerator Card (NAC) - Copper + +pci:v00009004d00007778* + ID_MODEL_FROM_DATABASE=AIC-787x + +pci:v00009004d00007810* + ID_MODEL_FROM_DATABASE=AIC-7810 + +pci:v00009004d00007815* + ID_MODEL_FROM_DATABASE=AIC-7815 RAID+Memory Controller IC + +pci:v00009004d00007815sv00009004sd00007815* + ID_MODEL_FROM_DATABASE=AIC-7815 RAID+Memory Controller IC (ARO-1130U2 RAID Controller) + +pci:v00009004d00007815sv00009004sd00007840* + ID_MODEL_FROM_DATABASE=AIC-7815 RAID+Memory Controller IC + +pci:v00009004d00007850* + ID_MODEL_FROM_DATABASE=AIC-7850 + +pci:v00009004d00007855* + ID_MODEL_FROM_DATABASE=AHA-2930 + +pci:v00009004d00007860* + ID_MODEL_FROM_DATABASE=AIC-7860 + +pci:v00009004d00007870* + ID_MODEL_FROM_DATABASE=AIC-7870 + +pci:v00009004d00007871* + ID_MODEL_FROM_DATABASE=AHA-2940 + +pci:v00009004d00007872* + ID_MODEL_FROM_DATABASE=AHA-3940 + +pci:v00009004d00007873* + ID_MODEL_FROM_DATABASE=AHA-3980 + +pci:v00009004d00007874* + ID_MODEL_FROM_DATABASE=AHA-2944 + +pci:v00009004d00007880* + ID_MODEL_FROM_DATABASE=AIC-7880P + +pci:v00009004d00007890* + ID_MODEL_FROM_DATABASE=AIC-7890 + +pci:v00009004d00007891* + ID_MODEL_FROM_DATABASE=AIC-789x + +pci:v00009004d00007892* + ID_MODEL_FROM_DATABASE=AIC-789x + +pci:v00009004d00007893* + ID_MODEL_FROM_DATABASE=AIC-789x + +pci:v00009004d00007894* + ID_MODEL_FROM_DATABASE=AIC-789x + +pci:v00009004d00007895* + ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 + +pci:v00009004d00007895sv00009004sd00007890* + ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B) + +pci:v00009004d00007895sv00009004sd00007891* + ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-2940U/2940UW Dual) + +pci:v00009004d00007895sv00009004sd00007892* + ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-3940AU/AUW/AUWD/UWD) + +pci:v00009004d00007895sv00009004sd00007894* + ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-3944AUWD) + +pci:v00009004d00007895sv00009004sd00007895* + ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B) + +pci:v00009004d00007895sv00009004sd00007896* + ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B) + +pci:v00009004d00007895sv00009004sd00007897* + ID_MODEL_FROM_DATABASE=AHA-2940U/UW / AHA-39xx / AIC-7895 (AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B) + +pci:v00009004d00007896* + ID_MODEL_FROM_DATABASE=AIC-789x + +pci:v00009004d00007897* + ID_MODEL_FROM_DATABASE=AIC-789x + +pci:v00009004d00008078* + ID_MODEL_FROM_DATABASE=AIC-7880U + +pci:v00009004d00008078sv00009004sd00007880* + ID_MODEL_FROM_DATABASE=AIC-7880U (AIC-7880P Ultra/Ultra Wide SCSI Chipset) + +pci:v00009004d00008178* + ID_MODEL_FROM_DATABASE=AIC-7870P/7881U [AHA-2940U/UW/D/S76] + +pci:v00009004d00008178sv00009004sd00007881* + ID_MODEL_FROM_DATABASE=AIC-7870P/7881U [AHA-2940U/UW/D/S76] (AHA-2940UW SCSI Host Adapter) + +pci:v00009004d00008278* + ID_MODEL_FROM_DATABASE=AHA-3940U/UW/UWD / AIC-7882U + +pci:v00009004d00008378* + ID_MODEL_FROM_DATABASE=AHA-3940U/UW / AIC-7883U + +pci:v00009004d00008478* + ID_MODEL_FROM_DATABASE=AHA-2944UW / AIC-7884U + +pci:v00009004d00008578* + ID_MODEL_FROM_DATABASE=AHA-3944U/UWD / AIC-7885 + +pci:v00009004d00008678* + ID_MODEL_FROM_DATABASE=AHA-4944UW / AIC-7886 + +pci:v00009004d00008778* + ID_MODEL_FROM_DATABASE=AHA-2940UW Pro / AIC-788x + +pci:v00009004d00008778sv00009004sd00007887* + ID_MODEL_FROM_DATABASE=AHA-2940UW Pro / AIC-788x (2940UW Pro Ultra-Wide SCSI Controller) + +pci:v00009004d00008878* + ID_MODEL_FROM_DATABASE=AHA-2930UW / AIC-7888 + +pci:v00009004d00008878sv00009004sd00007888* + ID_MODEL_FROM_DATABASE=AHA-2930UW / AIC-7888 (AHA-2930UW SCSI Controller) + +pci:v00009004d00008B78* + ID_MODEL_FROM_DATABASE=ABA-1030 + +pci:v00009004d0000EC78* + ID_MODEL_FROM_DATABASE=AHA-4944W/UW + +pci:v00009005* + ID_VENDOR_FROM_DATABASE=Adaptec + +pci:v00009005d00000010* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W + +pci:v00009005d00000010sv00009005sd00002180* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W (AHA-2940U2 SCSI Controller) + +pci:v00009005d00000010sv00009005sd00008100* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W (AHA-2940U2B SCSI Controller) + +pci:v00009005d00000010sv00009005sd0000A100* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W (AHA-2940U2B SCSI Controller) + +pci:v00009005d00000010sv00009005sd0000A180* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W (AIC-3860Q [AHA-2940U2W/GE] SCSI Controller) + +pci:v00009005d00000010sv00009005sd0000E100* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W (AHA-2950U2B SCSI Controller) + +pci:v00009005d00000011* + ID_MODEL_FROM_DATABASE=AHA-2930U2 + +pci:v00009005d00000013* + ID_MODEL_FROM_DATABASE=78902 + +pci:v00009005d00000013sv00009005sd00000003* + ID_MODEL_FROM_DATABASE=78902 (AAA-131U2 Array1000 1 Channel RAID Controller) + +pci:v00009005d00000013sv00009005sd0000000F* + ID_MODEL_FROM_DATABASE=78902 (AIC7890_ARO) + +pci:v00009005d0000001F* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W / 7890/7891 + +pci:v00009005d0000001Fsv00009005sd0000000F* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W / 7890/7891 (2940U2W SCSI Controller) + +pci:v00009005d0000001Fsv00009005sd0000A180* + ID_MODEL_FROM_DATABASE=AHA-2940U2/U2W / 7890/7891 (2940U2W SCSI Controller) + +pci:v00009005d00000020* + ID_MODEL_FROM_DATABASE=AIC-7890 + +pci:v00009005d0000002F* + ID_MODEL_FROM_DATABASE=AIC-7890 + +pci:v00009005d00000030* + ID_MODEL_FROM_DATABASE=AIC-7890 + +pci:v00009005d0000003F* + ID_MODEL_FROM_DATABASE=AIC-7890 + +pci:v00009005d00000050* + ID_MODEL_FROM_DATABASE=AHA-3940U2x/395U2x + +pci:v00009005d00000050sv00009005sd0000F500* + ID_MODEL_FROM_DATABASE=AHA-3940U2x/395U2x (AHA-3950U2B) + +pci:v00009005d00000050sv00009005sd0000FFFF* + ID_MODEL_FROM_DATABASE=AHA-3940U2x/395U2x (AHA-3950U2B) + +pci:v00009005d00000051* + ID_MODEL_FROM_DATABASE=AHA-3950U2D + +pci:v00009005d00000051sv00009005sd0000B500* + ID_MODEL_FROM_DATABASE=AHA-3950U2D + +pci:v00009005d00000053* + ID_MODEL_FROM_DATABASE=AIC-7896 SCSI Controller + +pci:v00009005d00000053sv00009005sd0000FFFF* + ID_MODEL_FROM_DATABASE=AIC-7896 SCSI Controller (mainboard implementation) + +pci:v00009005d0000005F* + ID_MODEL_FROM_DATABASE=AIC-7896U2/7897U2 + +pci:v00009005d00000080* + ID_MODEL_FROM_DATABASE=AIC-7892A U160/m + +pci:v00009005d00000080sv00000E11sd0000E2A0* + ID_MODEL_FROM_DATABASE=AIC-7892A U160/m (Compaq 64-Bit/66MHz Wide Ultra3 SCSI Adapter) + +pci:v00009005d00000080sv00009005sd00006220* + ID_MODEL_FROM_DATABASE=AIC-7892A U160/m (AHA-29160C) + +pci:v00009005d00000080sv00009005sd000062A0* + ID_MODEL_FROM_DATABASE=AIC-7892A U160/m (29160N Ultra160 SCSI Controller) + +pci:v00009005d00000080sv00009005sd0000E220* + ID_MODEL_FROM_DATABASE=AIC-7892A U160/m (29160LP Low Profile Ultra160 SCSI Controller) + +pci:v00009005d00000080sv00009005sd0000E2A0* + ID_MODEL_FROM_DATABASE=AIC-7892A U160/m (29160 Ultra160 SCSI Controller) + +pci:v00009005d00000081* + ID_MODEL_FROM_DATABASE=AIC-7892B U160/m + +pci:v00009005d00000081sv00009005sd000062A1* + ID_MODEL_FROM_DATABASE=AIC-7892B U160/m (19160 Ultra160 SCSI Controller) + +pci:v00009005d00000083* + ID_MODEL_FROM_DATABASE=AIC-7892D U160/m + +pci:v00009005d0000008F* + ID_MODEL_FROM_DATABASE=AIC-7892P U160/m + +pci:v00009005d0000008Fsv00001179sd00000001* + ID_MODEL_FROM_DATABASE=AIC-7892P U160/m (Magnia Z310) + +pci:v00009005d0000008Fsv000015D9sd00009005* + ID_MODEL_FROM_DATABASE=AIC-7892P U160/m (Onboard SCSI Host Adapter) + +pci:v00009005d00000092* + ID_MODEL_FROM_DATABASE=AVC-2010 [VideoH!] + +pci:v00009005d00000093* + ID_MODEL_FROM_DATABASE=AVC-2410 [VideoH!] + +pci:v00009005d000000C0* + ID_MODEL_FROM_DATABASE=AHA-3960D / AIC-7899A U160/m + +pci:v00009005d000000C0sv00000E11sd0000F620* + ID_MODEL_FROM_DATABASE=AHA-3960D / AIC-7899A U160/m (Compaq 64-Bit/66MHz Dual Channel Wide Ultra3 SCSI Adapter) + +pci:v00009005d000000C0sv00009005sd0000F620* + ID_MODEL_FROM_DATABASE=AHA-3960D / AIC-7899A U160/m (AHA-3960D U160/m) + +pci:v00009005d000000C1* + ID_MODEL_FROM_DATABASE=AIC-7899B U160/m + +pci:v00009005d000000C3* + ID_MODEL_FROM_DATABASE=AIC-7899D U160/m + +pci:v00009005d000000C5* + ID_MODEL_FROM_DATABASE=RAID subsystem HBA + +pci:v00009005d000000C5sv00001028sd000000C5* + ID_MODEL_FROM_DATABASE=RAID subsystem HBA (PowerEdge 2400,2500,2550,4400) + +pci:v00009005d000000CF* + ID_MODEL_FROM_DATABASE=AIC-7899P U160/m + +pci:v00009005d000000CFsv00001028sd000000CE* + ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (PowerEdge 1400) + +pci:v00009005d000000CFsv00001028sd000000D1* + ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (PowerEdge 2550) + +pci:v00009005d000000CFsv00001028sd000000D9* + ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (PowerEdge 2500) + +pci:v00009005d000000CFsv000010F1sd00002462* + ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (Thunder K7 S2462) + +pci:v00009005d000000CFsv000015D9sd00009005* + ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (Onboard SCSI Host Adapter) + +pci:v00009005d000000CFsv00008086sd00003411* + ID_MODEL_FROM_DATABASE=AIC-7899P U160/m (SDS2 Mainboard) + +pci:v00009005d00000241* + ID_MODEL_FROM_DATABASE=Serial ATA II RAID 1420SA + +pci:v00009005d00000242* + ID_MODEL_FROM_DATABASE=Serial ATA II RAID 1220SA + +pci:v00009005d00000243* + ID_MODEL_FROM_DATABASE=Serial ATA II RAID 1430SA + +pci:v00009005d00000244* + ID_MODEL_FROM_DATABASE=eSATA II RAID 1225SA + +pci:v00009005d00000250* + ID_MODEL_FROM_DATABASE=ServeRAID Controller + +pci:v00009005d00000250sv00001014sd00000279* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID 6M) + +pci:v00009005d00000250sv00001014sd0000028C* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID 6i/6i+) + +pci:v00009005d00000250sv00001014sd0000028E* + ID_MODEL_FROM_DATABASE=ServeRAID Controller (ServeRAID 7k) + +pci:v00009005d00000279* + ID_MODEL_FROM_DATABASE=ServeRAID 6M + +pci:v00009005d00000283* + ID_MODEL_FROM_DATABASE=AAC-RAID + +pci:v00009005d00000283sv00009005sd00000283* + ID_MODEL_FROM_DATABASE=AAC-RAID (Catapult) + +pci:v00009005d00000284* + ID_MODEL_FROM_DATABASE=AAC-RAID + +pci:v00009005d00000284sv00009005sd00000284* + ID_MODEL_FROM_DATABASE=AAC-RAID (Tomcat) + +pci:v00009005d00000285* + ID_MODEL_FROM_DATABASE=AAC-RAID + +pci:v00009005d00000285sv00000E11sd00000295* + ID_MODEL_FROM_DATABASE=AAC-RAID (SATA 6Ch (Bearcat)) + +pci:v00009005d00000285sv00001014sd000002F2* + ID_MODEL_FROM_DATABASE=AAC-RAID (ServeRAID 8i) + +pci:v00009005d00000285sv00001028sd00000287* + ID_MODEL_FROM_DATABASE=AAC-RAID (PowerEdge Expandable RAID Controller 320/DC) + +pci:v00009005d00000285sv00001028sd00000291* + ID_MODEL_FROM_DATABASE=AAC-RAID (CERC SATA RAID 2 PCI SATA 6ch (DellCorsair)) + +pci:v00009005d00000285sv0000103Csd00003227* + ID_MODEL_FROM_DATABASE=AAC-RAID (AAR-2610SA) + +pci:v00009005d00000285sv0000108Esd00000286* + ID_MODEL_FROM_DATABASE=AAC-RAID (Sun StorageTek SAS RAID HBA, Internal) + +pci:v00009005d00000285sv0000108Esd00000287* + ID_MODEL_FROM_DATABASE=AAC-RAID (STK RAID EXT) + +pci:v00009005d00000285sv0000108Esd00007AAC* + ID_MODEL_FROM_DATABASE=AAC-RAID (STK RAID REM) + +pci:v00009005d00000285sv0000108Esd00007AAE* + ID_MODEL_FROM_DATABASE=AAC-RAID (STK RAID EX) + +pci:v00009005d00000285sv000015D9sd000002B5* + ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S4i) + +pci:v00009005d00000285sv000015D9sd000002B6* + ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S8i) + +pci:v00009005d00000285sv000015D9sd000002C9* + ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S4iR) + +pci:v00009005d00000285sv000015D9sd000002CA* + ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S8iR) + +pci:v00009005d00000285sv000015D9sd000002D2* + ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S8i-LP) + +pci:v00009005d00000285sv000015D9sd000002D3* + ID_MODEL_FROM_DATABASE=AAC-RAID (SMC AOC-USAS-S8iR-LP) + +pci:v00009005d00000285sv000017AAsd00000286* + ID_MODEL_FROM_DATABASE=AAC-RAID (Legend S220 (Legend Crusader)) + +pci:v00009005d00000285sv000017AAsd00000287* + ID_MODEL_FROM_DATABASE=AAC-RAID (Legend S230 (Legend Vulcan)) + +pci:v00009005d00000285sv00009005sd00000285* + ID_MODEL_FROM_DATABASE=AAC-RAID (2200S (Vulcan)) + +pci:v00009005d00000285sv00009005sd00000286* + ID_MODEL_FROM_DATABASE=AAC-RAID (2120S (Crusader)) + +pci:v00009005d00000285sv00009005sd00000287* + ID_MODEL_FROM_DATABASE=AAC-RAID (2200S (Vulcan-2m)) + +pci:v00009005d00000285sv00009005sd00000288* + ID_MODEL_FROM_DATABASE=AAC-RAID (3230S (Harrier)) + +pci:v00009005d00000285sv00009005sd00000289* + ID_MODEL_FROM_DATABASE=AAC-RAID (3240S (Tornado)) + +pci:v00009005d00000285sv00009005sd0000028A* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2020ZCR) + +pci:v00009005d00000285sv00009005sd0000028B* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2025ZCR (Terminator)) + +pci:v00009005d00000285sv00009005sd0000028E* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2020SA (Skyhawk)) + +pci:v00009005d00000285sv00009005sd0000028F* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2025SA) + +pci:v00009005d00000285sv00009005sd00000290* + ID_MODEL_FROM_DATABASE=AAC-RAID (AAR-2410SA PCI SATA 4ch (Jaguar II)) + +pci:v00009005d00000285sv00009005sd00000292* + ID_MODEL_FROM_DATABASE=AAC-RAID (AAR-2810SA PCI SATA 8ch (Corsair-8)) + +pci:v00009005d00000285sv00009005sd00000293* + ID_MODEL_FROM_DATABASE=AAC-RAID (AAR-21610SA PCI SATA 16ch (Corsair-16)) + +pci:v00009005d00000285sv00009005sd00000294* + ID_MODEL_FROM_DATABASE=AAC-RAID (ESD SO-DIMM PCI-X SATA ZCR (Prowler)) + +pci:v00009005d00000285sv00009005sd00000296* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2240S) + +pci:v00009005d00000285sv00009005sd00000297* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-4005SAS) + +pci:v00009005d00000285sv00009005sd00000298* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-4000) + +pci:v00009005d00000285sv00009005sd00000299* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-4800SAS) + +pci:v00009005d00000285sv00009005sd0000029A* + ID_MODEL_FROM_DATABASE=AAC-RAID (4805SAS) + +pci:v00009005d00000285sv00009005sd000002A4* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP9085LI) + +pci:v00009005d00000285sv00009005sd000002A5* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5085BR) + +pci:v00009005d00000285sv00009005sd000002B5* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR5800) + +pci:v00009005d00000285sv00009005sd000002B6* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR5805) + +pci:v00009005d00000285sv00009005sd000002B7* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR5808) + +pci:v00009005d00000285sv00009005sd000002B8* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP5445SL) + +pci:v00009005d00000285sv00009005sd000002B9* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP5085SL) + +pci:v00009005d00000285sv00009005sd000002BA* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP5805SL) + +pci:v00009005d00000285sv00009005sd000002BB* + ID_MODEL_FROM_DATABASE=AAC-RAID (3405) + +pci:v00009005d00000285sv00009005sd000002BC* + ID_MODEL_FROM_DATABASE=AAC-RAID (3805) + +pci:v00009005d00000285sv00009005sd000002BD* + ID_MODEL_FROM_DATABASE=AAC-RAID (31205) + +pci:v00009005d00000285sv00009005sd000002BE* + ID_MODEL_FROM_DATABASE=AAC-RAID (31605) + +pci:v00009005d00000285sv00009005sd000002BF* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5045BL) + +pci:v00009005d00000285sv00009005sd000002C0* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5085BL) + +pci:v00009005d00000285sv00009005sd000002C1* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5125BR) + +pci:v00009005d00000285sv00009005sd000002C2* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5165BR) + +pci:v00009005d00000285sv00009005sd000002C3* + ID_MODEL_FROM_DATABASE=AAC-RAID (51205) + +pci:v00009005d00000285sv00009005sd000002C4* + ID_MODEL_FROM_DATABASE=AAC-RAID (51605) + +pci:v00009005d00000285sv00009005sd000002C5* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5125SL) + +pci:v00009005d00000285sv00009005sd000002C6* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP ICP5165SL) + +pci:v00009005d00000285sv00009005sd000002C7* + ID_MODEL_FROM_DATABASE=AAC-RAID (3085) + +pci:v00009005d00000285sv00009005sd000002C8* + ID_MODEL_FROM_DATABASE=AAC-RAID (ICP5805BL) + +pci:v00009005d00000285sv00009005sd000002CE* + ID_MODEL_FROM_DATABASE=AAC-RAID (51245) + +pci:v00009005d00000285sv00009005sd000002CF* + ID_MODEL_FROM_DATABASE=AAC-RAID (51645) + +pci:v00009005d00000285sv00009005sd000002D0* + ID_MODEL_FROM_DATABASE=AAC-RAID (52445) + +pci:v00009005d00000285sv00009005sd000002D1* + ID_MODEL_FROM_DATABASE=AAC-RAID (5405) + +pci:v00009005d00000285sv00009005sd000002D4* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2045) + +pci:v00009005d00000285sv00009005sd000002D5* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2405) + +pci:v00009005d00000285sv00009005sd000002D6* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2445) + +pci:v00009005d00000285sv00009005sd000002D7* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2805) + +pci:v00009005d00000285sv00009005sd000002D8* + ID_MODEL_FROM_DATABASE=AAC-RAID (5405G) + +pci:v00009005d00000285sv00009005sd000002D9* + ID_MODEL_FROM_DATABASE=AAC-RAID (5445G) + +pci:v00009005d00000285sv00009005sd000002DA* + ID_MODEL_FROM_DATABASE=AAC-RAID (5805G) + +pci:v00009005d00000285sv00009005sd000002DB* + ID_MODEL_FROM_DATABASE=AAC-RAID (5085G) + +pci:v00009005d00000285sv00009005sd000002DC* + ID_MODEL_FROM_DATABASE=AAC-RAID (51245G) + +pci:v00009005d00000285sv00009005sd000002DD* + ID_MODEL_FROM_DATABASE=AAC-RAID (51645G) + +pci:v00009005d00000285sv00009005sd000002DE* + ID_MODEL_FROM_DATABASE=AAC-RAID (52445G) + +pci:v00009005d00000285sv00009005sd000002DF* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2045G) + +pci:v00009005d00000285sv00009005sd000002E0* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2405G) + +pci:v00009005d00000285sv00009005sd000002E1* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2445G) + +pci:v00009005d00000285sv00009005sd000002E2* + ID_MODEL_FROM_DATABASE=AAC-RAID (ASR-2805G) + +pci:v00009005d00000286* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) + +pci:v00009005d00000286sv00001014sd0000034D* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (8s) + +pci:v00009005d00000286sv00001014sd00009540* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ServeRAID 8k/8k-l4) + +pci:v00009005d00000286sv00001014sd00009580* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ServeRAID 8k/8k-l8) + +pci:v00009005d00000286sv00009005sd0000028C* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ASR-2230S + ASR-2230SLP PCI-X (Lancer)) + +pci:v00009005d00000286sv00009005sd0000028D* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ASR-2130S) + +pci:v00009005d00000286sv00009005sd0000029B* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ASR-2820SA) + +pci:v00009005d00000286sv00009005sd0000029C* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ASR-2620SA) + +pci:v00009005d00000286sv00009005sd0000029D* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ASR-2420SA) + +pci:v00009005d00000286sv00009005sd0000029E* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP9024R0) + +pci:v00009005d00000286sv00009005sd0000029F* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP9014R0) + +pci:v00009005d00000286sv00009005sd000002A0* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP9047MA) + +pci:v00009005d00000286sv00009005sd000002A1* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP9087MA) + +pci:v00009005d00000286sv00009005sd000002A2* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (3800) + +pci:v00009005d00000286sv00009005sd000002A3* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP5445AU) + +pci:v00009005d00000286sv00009005sd000002A4* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP9085LI) + +pci:v00009005d00000286sv00009005sd000002A5* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP5085BR) + +pci:v00009005d00000286sv00009005sd000002A6* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP9067MA) + +pci:v00009005d00000286sv00009005sd000002A7* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (3805) + +pci:v00009005d00000286sv00009005sd000002A8* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (3400) + +pci:v00009005d00000286sv00009005sd000002A9* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP5085AU) + +pci:v00009005d00000286sv00009005sd000002AA* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP5045AU) + +pci:v00009005d00000286sv00009005sd000002AC* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (1800) + +pci:v00009005d00000286sv00009005sd000002B3* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (2400) + +pci:v00009005d00000286sv00009005sd000002B4* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (ICP ICP5045AL) + +pci:v00009005d00000286sv00009005sd00000800* + ID_MODEL_FROM_DATABASE=AAC-RAID (Rocket) (Callisto) + +pci:v00009005d0000028B* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 + +pci:v00009005d0000028Bsv00009005sd00000200* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 Entry Level - ASR-6405E - 4 internal 6G SAS ports) + +pci:v00009005d0000028Bsv00009005sd00000201* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 Entry Level - ASR-6805E - 8 internal 6G SAS ports) + +pci:v00009005d0000028Bsv00009005sd00000300* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-6405 - 4 internal 6G SAS ports) + +pci:v00009005d0000028Bsv00009005sd00000301* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-6805 - 8 internal 6G SAS ports) + +pci:v00009005d0000028Bsv00009005sd00000302* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-6445 - 4 internal and 4 external 6G SAS ports) + +pci:v00009005d0000028Bsv00009005sd00000310* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 Connectors on Top - ASR-6405T - 4 internal 6G SAS ports) + +pci:v00009005d0000028Bsv00009005sd00000311* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 Connectors on Top - ASR-6805T - 8 internal 6G SAS) + +pci:v00009005d0000028Bsv00009005sd00000400* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-61205 - 12 internal 6G SAS ports) + +pci:v00009005d0000028Bsv00009005sd00000401* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-61605 - 16 internal 6G SAS ports) + +pci:v00009005d0000028Bsv00009005sd00000403* + ID_MODEL_FROM_DATABASE=Series 6 - 6G SAS/PCIe 2 (Series 6 - ASR-62405 - 24 internal 6G SAS ports) + +pci:v00009005d0000028C* + ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 + +pci:v00009005d0000028Csv00009005sd00000500* + ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 - ASR-7805 - 8 internal 6G SAS Port/PCIe 3.0) + +pci:v00009005d0000028Csv00009005sd00000501* + ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 - ASR-71605 - 16 internal 6G SAS Port/PCIe 3.0) + +pci:v00009005d0000028Csv00009005sd00000502* + ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 - ASR-71685 - 16 internal 8 external 6G SAS Port/PCIe 3.0) + +pci:v00009005d0000028Csv00009005sd00000503* + ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 - ASR-72405 - 24 internal 0 external 6G SAS Port/PCIe 3.0) + +pci:v00009005d0000028Csv00009005sd00000504* + ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 - ASR-7885 - 8 internal 8 external 6G SAS Port/PCIe 3.0) + +pci:v00009005d0000028Csv00009005sd00000505* + ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 Entry Level - ASR-71685E - 16 internal 8 external 6G SAS Port/PCIe 3.0) + +pci:v00009005d0000028Csv00009005sd00000506* + ID_MODEL_FROM_DATABASE=Series 7 6G SAS/PCIe 3 (Series 7 Entry Level - ASR-72405E - 24 internal 0 external 6G SAS Port/PCIe 3.0) + +pci:v00009005d0000028D* + ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 + +pci:v00009005d0000028Dsv00009005sd00000550* + ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-82405 - 24 internal 0 external 12G SAS Port/PCIe 3.0) + +pci:v00009005d0000028Dsv00009005sd00000551* + ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-81605 - 16 internal 0 external 12G SAS Port/PCIe 3.0) + +pci:v00009005d0000028Dsv00009005sd00000552* + ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-8805 - 8 internal 0 external 12G SAS Port/PCIe 3.0) + +pci:v00009005d0000028Dsv00009005sd00000553* + ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-8085 - 0 internal 8 external 12G SAS Port/PCIe 3.0) + +pci:v00009005d0000028Dsv00009005sd00000554* + ID_MODEL_FROM_DATABASE=Series 8 12G SAS/PCIe 3 (Series 8 - ASR-8885 - 8 internal 8 external 12G SAS Port/PCIe 3.0) + +pci:v00009005d0000028F* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 + +pci:v00009005d0000028Fsv0000103Csd00000600* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408i-p SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00000601* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408e-p SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00000602* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408i-a SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00000603* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408i-c SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00000650* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208i-p SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00000651* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208e-p SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00000652* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208i-c SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00000654* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array E208i-a SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00000655* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P408e-m SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00000700* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P204i-c SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00000701* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P204i-b SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00001100* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P816i-a SR Gen10) + +pci:v00009005d0000028Fsv0000103Csd00001101* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (Smart Array P416ie-m SR G10) + +pci:v00009005d0000028Fsv0000105Bsd00001211* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 8238-16i) + +pci:v00009005d0000028Fsv0000105Bsd00001321* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 8242-24i) + +pci:v00009005d0000028Fsv000013FEsd00008312* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SKY-9200 MIC-8312BridgeB) + +pci:v00009005d0000028Fsv0000152Dsd00008A22* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (QS-8204-8i) + +pci:v00009005d0000028Fsv0000152Dsd00008A23* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (QS-8238-16i) + +pci:v00009005d0000028Fsv0000152Dsd00008A24* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (QS-8236-16i) + +pci:v00009005d0000028Fsv0000152Dsd00008A36* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (QS-8240-24i) + +pci:v00009005d0000028Fsv0000152Dsd00008A37* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (QS-8242-24i) + +pci:v00009005d0000028Fsv0000193Dsd00008460* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA H460-M1) + +pci:v00009005d0000028Fsv0000193Dsd00008461* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA H460-B1) + +pci:v00009005d0000028Fsv0000193Dsd0000C460* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID P460-M2) + +pci:v00009005d0000028Fsv0000193Dsd0000C461* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID P460-B2) + +pci:v00009005d0000028Fsv0000193Dsd0000F460* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID P460-M4) + +pci:v00009005d0000028Fsv0000193Dsd0000F461* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID P460-B4) + +pci:v00009005d0000028Fsv000019E5sd0000D227* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartROC-HD SR465C-M 4G) + +pci:v00009005d0000028Fsv000019E5sd0000D228* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartROC SR455C-M 2G) + +pci:v00009005d0000028Fsv000019E5sd0000D229* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartIOC SR155-M) + +pci:v00009005d0000028Fsv000019E5sd0000D22A* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartIOC-HD SR765-M) + +pci:v00009005d0000028Fsv000019E5sd0000D22B* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartROC-e SR455C-ME 4G) + +pci:v00009005d0000028Fsv000019E5sd0000D22C* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartROC SR455C-M 4G) + +pci:v00009005d0000028Fsv00001BD4sd00000045* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SMART-HBA 8242-24i) + +pci:v00009005d0000028Fsv00001BD4sd00000046* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID 8236-16i) + +pci:v00009005d0000028Fsv00001BD4sd00000047* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID 8240-24i) + +pci:v00009005d0000028Fsv00001BD4sd00000048* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SMART-HBA 8238-16i) + +pci:v00009005d0000028Fsv00001BD4sd0000004A* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (PM8222-SHBA) + +pci:v00009005d0000028Fsv00001BD4sd0000004B* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID PM8204-2GB) + +pci:v00009005d0000028Fsv00001BD4sd0000004C* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (RAID PM8204-4GB) + +pci:v00009005d0000028Fsv00001BD4sd0000004F* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (PM8222-HBA) + +pci:v00009005d0000028Fsv00009005sd00000608* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3162-8i /e) + +pci:v00009005d0000028Fsv00009005sd00000800* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-8i) + +pci:v00009005d0000028Fsv00009005sd00000801* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3152-8i) + +pci:v00009005d0000028Fsv00009005sd00000802* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3151-4i) + +pci:v00009005d0000028Fsv00009005sd00000803* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3101-4i) + +pci:v00009005d0000028Fsv00009005sd00000804* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-8e) + +pci:v00009005d0000028Fsv00009005sd00000805* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3102-8i) + +pci:v00009005d0000028Fsv00009005sd00000806* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3100) + +pci:v00009005d0000028Fsv00009005sd00000807* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3162-8i) + +pci:v00009005d0000028Fsv00009005sd00000900* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-8i) + +pci:v00009005d0000028Fsv00009005sd00000901* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-4i) + +pci:v00009005d0000028Fsv00009005sd00000902* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-8i) + +pci:v00009005d0000028Fsv00009005sd00000903* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-4i) + +pci:v00009005d0000028Fsv00009005sd00000904* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-8e) + +pci:v00009005d0000028Fsv00009005sd00000905* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-8e) + +pci:v00009005d0000028Fsv00009005sd00000906* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-4i4e) + +pci:v00009005d0000028Fsv00009005sd00000907* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100) + +pci:v00009005d0000028Fsv00009005sd00000908* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100) + +pci:v00009005d0000028Fsv00009005sd0000090A* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100A-8i) + +pci:v00009005d0000028Fsv00009005sd00001200* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-24i) + +pci:v00009005d0000028Fsv00009005sd00001201* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-8i16e) + +pci:v00009005d0000028Fsv00009005sd00001202* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-8i8e) + +pci:v00009005d0000028Fsv00009005sd00001280* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-16i) + +pci:v00009005d0000028Fsv00009005sd00001281* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-16e) + +pci:v00009005d0000028Fsv00009005sd00001300* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-8i8e) + +pci:v00009005d0000028Fsv00009005sd00001301* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (HBA 1100-24i) + +pci:v00009005d0000028Fsv00009005sd00001302* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-8i8e) + +pci:v00009005d0000028Fsv00009005sd00001303* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartHBA 2100-24i) + +pci:v00009005d0000028Fsv00009005sd00001380* + ID_MODEL_FROM_DATABASE=Smart Storage PQI 12G SAS/PCIe 3 (SmartRAID 3154-16i) + +pci:v00009005d00000410* + ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA RAID) + +pci:v00009005d00000410sv00009005sd00000410* + ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA RAID) (ASC-48300(Spirit RAID)) + +pci:v00009005d00000410sv00009005sd00000411* + ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA RAID) (ASC-58300 (Oakmont RAID)) + +pci:v00009005d00000412* + ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA non-RAID) + +pci:v00009005d00000412sv00009005sd00000412* + ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA non-RAID) (ASC-48300 (Spirit non-RAID)) + +pci:v00009005d00000412sv00009005sd00000413* + ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor HBA non-RAID) (ASC-58300 (Oakmont non-RAID)) + +pci:v00009005d00000415* + ID_MODEL_FROM_DATABASE=ASC-58300 SAS (Razor-External HBA RAID) + +pci:v00009005d00000416* + ID_MODEL_FROM_DATABASE=ASC-58300 SAS (Razor-External HBA non-RAID) + +pci:v00009005d0000041E* + ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor ASIC non-RAID) + +pci:v00009005d0000041F* + ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor ASIC RAID) + +pci:v00009005d0000041Fsv00009005sd0000041F* + ID_MODEL_FROM_DATABASE=AIC-9410W SAS (Razor ASIC RAID) + +pci:v00009005d0000042F* + ID_MODEL_FROM_DATABASE=VSC7250/7251 SAS (Aurora ASIC non-RAID) + +pci:v00009005d00000430* + ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite HBA RAID) + +pci:v00009005d00000430sv00009005sd00000430* + ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite HBA RAID) (ASC-44300 (Spirit-Lite RAID)) + +pci:v00009005d00000432* + ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite HBA non-RAID) + +pci:v00009005d00000432sv00009005sd00000432* + ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite HBA non-RAID) (ASC-44300 (Spirit-Lite non-RAID)) + +pci:v00009005d0000043E* + ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite ASIC non-RAID) + +pci:v00009005d0000043F* + ID_MODEL_FROM_DATABASE=AIC-9405W SAS (Razor-Lite ASIC RAID) + +pci:v00009005d00000450* + ID_MODEL_FROM_DATABASE=ASC-1405 Unified Serial HBA + +pci:v00009005d00000500* + ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller + +pci:v00009005d00000500sv00001014sd000002C1* + ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller (PCI-X DDR 3Gb SAS Adapter (572A/572C)) + +pci:v00009005d00000500sv00001014sd000002C2* + ID_MODEL_FROM_DATABASE=Obsidian chipset SCSI controller (PCI-X DDR 3Gb SAS RAID Adapter (572B/572D)) + +pci:v00009005d00000503* + ID_MODEL_FROM_DATABASE=Scamp chipset SCSI controller + +pci:v00009005d00000503sv00001014sd000002BF* + ID_MODEL_FROM_DATABASE=Scamp chipset SCSI controller (Quad Channel PCI-X DDR U320 SCSI RAID Adapter (571E)) + +pci:v00009005d00000503sv00001014sd000002C3* + ID_MODEL_FROM_DATABASE=Scamp chipset SCSI controller (PCI-X DDR 3Gb SAS RAID Adapter (572F)) + +pci:v00009005d00000503sv00001014sd000002D5* + ID_MODEL_FROM_DATABASE=Scamp chipset SCSI controller (Quad Channel PCI-X DDR U320 SCSI RAID Adapter (571F)) + +pci:v00009005d00000910* + ID_MODEL_FROM_DATABASE=AUA-3100B + +pci:v00009005d0000091E* + ID_MODEL_FROM_DATABASE=AUA-3100B + +pci:v00009005d00008000* + ID_MODEL_FROM_DATABASE=ASC-29320A U320 + +pci:v00009005d0000800F* + ID_MODEL_FROM_DATABASE=AIC-7901 U320 + +pci:v00009005d00008010* + ID_MODEL_FROM_DATABASE=ASC-39320 U320 + +pci:v00009005d00008011* + ID_MODEL_FROM_DATABASE=ASC-39320D + +pci:v00009005d00008011sv00000E11sd000000AC* + ID_MODEL_FROM_DATABASE=ASC-39320D (U320) + +pci:v00009005d00008011sv00009005sd00000041* + ID_MODEL_FROM_DATABASE=ASC-39320D (U320) + +pci:v00009005d00008012* + ID_MODEL_FROM_DATABASE=ASC-29320 U320 + +pci:v00009005d00008013* + ID_MODEL_FROM_DATABASE=ASC-29320B U320 + +pci:v00009005d00008014* + ID_MODEL_FROM_DATABASE=ASC-29320LP U320 + +pci:v00009005d00008015* + ID_MODEL_FROM_DATABASE=ASC-39320B U320 + +pci:v00009005d00008016* + ID_MODEL_FROM_DATABASE=ASC-39320A U320 + +pci:v00009005d00008017* + ID_MODEL_FROM_DATABASE=ASC-29320ALP U320 + +pci:v00009005d00008017sv00009005sd00000044* + ID_MODEL_FROM_DATABASE=ASC-29320ALP U320 (ASC-29320ALP PCIx U320) + +pci:v00009005d00008017sv00009005sd00000045* + ID_MODEL_FROM_DATABASE=ASC-29320ALP U320 (ASC-29320LPE PCIe U320) + +pci:v00009005d0000801C* + ID_MODEL_FROM_DATABASE=ASC-39320D U320 + +pci:v00009005d0000801D* + ID_MODEL_FROM_DATABASE=AIC-7902B U320 + +pci:v00009005d0000801Dsv00001014sd000002CC* + ID_MODEL_FROM_DATABASE=AIC-7902B U320 (ServeRAID 7e) + +pci:v00009005d0000801E* + ID_MODEL_FROM_DATABASE=AIC-7901A U320 + +pci:v00009005d0000801F* + ID_MODEL_FROM_DATABASE=AIC-7902 U320 + +pci:v00009005d0000801Fsv00001734sd00001011* + ID_MODEL_FROM_DATABASE=AIC-7902 U320 (PRIMERGY RX300 onboard SCSI) + +pci:v00009005d00008080* + ID_MODEL_FROM_DATABASE=ASC-29320A U320 w/HostRAID + +pci:v00009005d00008081* + ID_MODEL_FROM_DATABASE=PMC-Sierra PM8001 SAS HBA [Series 6H] + +pci:v00009005d00008088* + ID_MODEL_FROM_DATABASE=PMC-Sierra PM8018 SAS HBA [Series 7H] + +pci:v00009005d00008089* + ID_MODEL_FROM_DATABASE=PMC-Sierra PM8019 SAS encryption HBA [Series 7He] + +pci:v00009005d0000808F* + ID_MODEL_FROM_DATABASE=AIC-7901 U320 w/HostRAID + +pci:v00009005d0000808Fsv00001028sd00000168* + ID_MODEL_FROM_DATABASE=AIC-7901 U320 w/HostRAID (Precision Workstation 670 Mainboard) + +pci:v00009005d00008090* + ID_MODEL_FROM_DATABASE=ASC-39320 U320 w/HostRAID + +pci:v00009005d00008091* + ID_MODEL_FROM_DATABASE=ASC-39320D U320 w/HostRAID + +pci:v00009005d00008092* + ID_MODEL_FROM_DATABASE=ASC-29320 U320 w/HostRAID + +pci:v00009005d00008093* + ID_MODEL_FROM_DATABASE=ASC-29320B U320 w/HostRAID + +pci:v00009005d00008094* + ID_MODEL_FROM_DATABASE=ASC-29320LP U320 w/HostRAID + +pci:v00009005d00008095* + ID_MODEL_FROM_DATABASE=ASC-39320(B) U320 w/HostRAID + +pci:v00009005d00008096* + ID_MODEL_FROM_DATABASE=ASC-39320A U320 w/HostRAID + +pci:v00009005d00008097* + ID_MODEL_FROM_DATABASE=ASC-29320ALP U320 w/HostRAID + +pci:v00009005d0000809C* + ID_MODEL_FROM_DATABASE=ASC-39320D(B) U320 w/HostRAID + +pci:v00009005d0000809D* + ID_MODEL_FROM_DATABASE=AIC-7902(B) U320 w/HostRAID + +pci:v00009005d0000809Dsv00001014sd000002CC* + ID_MODEL_FROM_DATABASE=AIC-7902(B) U320 w/HostRAID (ServeRAID 7e) + +pci:v00009005d0000809E* + ID_MODEL_FROM_DATABASE=AIC-7901A U320 w/HostRAID + +pci:v00009005d0000809F* + ID_MODEL_FROM_DATABASE=AIC-7902 U320 w/HostRAID + +pci:v0000907F* + ID_VENDOR_FROM_DATABASE=Atronics + +pci:v0000907Fd00002015* + ID_MODEL_FROM_DATABASE=IDE-2015PL + +pci:v0000919A* + ID_VENDOR_FROM_DATABASE=Gigapixel Corp + +pci:v00009412* + ID_VENDOR_FROM_DATABASE=Holtek + +pci:v00009412d00006565* + ID_MODEL_FROM_DATABASE=6565 + +pci:v00009413* + ID_VENDOR_FROM_DATABASE=Softlogic Co., Ltd. + +pci:v00009413d00006010* + ID_MODEL_FROM_DATABASE=SOLO6010 MPEG-4 Video encoder/decoder + +pci:v00009413d00006110* + ID_MODEL_FROM_DATABASE=SOLO6110 H.264 Video encoder/decoder + +pci:v00009618* + ID_VENDOR_FROM_DATABASE=JusonTech Corporation + +pci:v00009618d00000001* + ID_MODEL_FROM_DATABASE=JusonTech Gigabit Ethernet Controller + +pci:v00009699* + ID_VENDOR_FROM_DATABASE=Omni Media Technology Inc + +pci:v00009699d00006565* + ID_MODEL_FROM_DATABASE=6565 + +pci:v00009710* + ID_VENDOR_FROM_DATABASE=MosChip Semiconductor Technology Ltd. + +pci:v00009710d00009250* + ID_MODEL_FROM_DATABASE=PCI-to-PCI bridge [MCS9250] + +pci:v00009710d00009805* + ID_MODEL_FROM_DATABASE=PCI 1 port parallel adapter + +pci:v00009710d00009815* + ID_MODEL_FROM_DATABASE=PCI 9815 Multi-I/O Controller + +pci:v00009710d00009815sv00001000sd00000020* + ID_MODEL_FROM_DATABASE=PCI 9815 Multi-I/O Controller (2P0S (2 port parallel adaptor)) + +pci:v00009710d00009820* + ID_MODEL_FROM_DATABASE=PCI 9820 Multi-I/O Controller + +pci:v00009710d00009835* + ID_MODEL_FROM_DATABASE=PCI 9835 Multi-I/O Controller + +pci:v00009710d00009835sv00001000sd00000002* + ID_MODEL_FROM_DATABASE=PCI 9835 Multi-I/O Controller (2S (16C550 UART)) + +pci:v00009710d00009835sv00001000sd00000012* + ID_MODEL_FROM_DATABASE=PCI 9835 Multi-I/O Controller (1P2S) + +pci:v00009710d00009845* + ID_MODEL_FROM_DATABASE=PCI 9845 Multi-I/O Controller + +pci:v00009710d00009845sv00001000sd00000004* + ID_MODEL_FROM_DATABASE=PCI 9845 Multi-I/O Controller (0P4S (4 port 16550A serial card)) + +pci:v00009710d00009845sv00001000sd00000006* + ID_MODEL_FROM_DATABASE=PCI 9845 Multi-I/O Controller (0P6S (6 port 16550a serial card)) + +pci:v00009710d00009845sv00001000sd00000014* + ID_MODEL_FROM_DATABASE=PCI 9845 Multi-I/O Controller (1P4S (1 Parallel / 4 16550A Serial Port Adapter)) + +pci:v00009710d00009855* + ID_MODEL_FROM_DATABASE=PCI 9855 Multi-I/O Controller + +pci:v00009710d00009855sv00001000sd00000014* + ID_MODEL_FROM_DATABASE=PCI 9855 Multi-I/O Controller (1P4S) + +pci:v00009710d00009855sv00001000sd00000022* + ID_MODEL_FROM_DATABASE=PCI 9855 Multi-I/O Controller (2P2S (2 Parallel / 2 16550A Serial Port Adapter)) + +pci:v00009710d00009865* + ID_MODEL_FROM_DATABASE=PCI 9865 Multi-I/O Controller + +pci:v00009710d00009900* + ID_MODEL_FROM_DATABASE=MCS9900 Multi-I/O Controller + +pci:v00009710d00009901* + ID_MODEL_FROM_DATABASE=PCIe 9901 Multi-I/O Controller + +pci:v00009710d00009904* + ID_MODEL_FROM_DATABASE=4-Port PCIe Serial Adapter + +pci:v00009710d00009912* + ID_MODEL_FROM_DATABASE=PCIe 9912 Multi-I/O Controller + +pci:v00009710d00009922* + ID_MODEL_FROM_DATABASE=MCS9922 PCIe Multi-I/O Controller + +pci:v00009710d00009990* + ID_MODEL_FROM_DATABASE=MCS9990 PCIe to 4‐Port USB 2.0 Host Controller + +pci:v00009850* + ID_VENDOR_FROM_DATABASE=3Com (wrong ID) + +pci:v00009902* + ID_VENDOR_FROM_DATABASE=Stargen Inc. + +pci:v00009902d00000001* + ID_MODEL_FROM_DATABASE=SG2010 PCI over Starfabric Bridge + +pci:v00009902d00000002* + ID_MODEL_FROM_DATABASE=SG2010 PCI to Starfabric Gateway + +pci:v00009902d00000003* + ID_MODEL_FROM_DATABASE=SG1010 Starfabric Switch and PCI Bridge + +pci:v0000A0A0* + ID_VENDOR_FROM_DATABASE=AOPEN Inc. + +pci:v0000A0F1* + ID_VENDOR_FROM_DATABASE=UNISYS Corporation + +pci:v0000A200* + ID_VENDOR_FROM_DATABASE=NEC Corporation + +pci:v0000A259* + ID_VENDOR_FROM_DATABASE=Hewlett Packard + +pci:v0000A25B* + ID_VENDOR_FROM_DATABASE=Hewlett Packard GmbH PL24-MKT + +pci:v0000A304* + ID_VENDOR_FROM_DATABASE=Sony + +pci:v0000A727* + ID_VENDOR_FROM_DATABASE=3Com Corporation + +pci:v0000A727d00000013* + ID_MODEL_FROM_DATABASE=3CRPAG175 Wireless PC Card + +pci:v0000A727d00006803* + ID_MODEL_FROM_DATABASE=3CRDAG675B Wireless 11a/b/g Adapter + +pci:v0000AA00* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA01* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA02* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA03* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA04* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA05* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA06* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA07* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA08* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA09* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA0A* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA0B* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA0C* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA0D* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA0E* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA0F* + ID_VENDOR_FROM_DATABASE=iTuner + +pci:v0000AA42* + ID_VENDOR_FROM_DATABASE=Scitex Digital Video + +pci:v0000AA55* + ID_VENDOR_FROM_DATABASE=Ncomputing X300 PCI-Engine + +pci:v0000AAAA* + ID_VENDOR_FROM_DATABASE=Adnaco Technology Inc. + +pci:v0000AAAAd00000001* + ID_MODEL_FROM_DATABASE=H1 PCIe over fiber optic host controller + +pci:v0000AAAAd00000002* + ID_MODEL_FROM_DATABASE=R1BP1 PCIe over fiber optic expansion chassis + +pci:v0000ABCD* + ID_VENDOR_FROM_DATABASE=Vadatech Inc. + +pci:v0000AC1E* + ID_VENDOR_FROM_DATABASE=Digital Receiver Technology Inc + +pci:v0000AC3D* + ID_VENDOR_FROM_DATABASE=Actuality Systems + +pci:v0000AD00* + ID_VENDOR_FROM_DATABASE=Alta Data Technologies LLC + +pci:v0000AECB* + ID_VENDOR_FROM_DATABASE=Adrienne Electronics Corporation + +pci:v0000AECBd00006250* + ID_MODEL_FROM_DATABASE=VITC/LTC Timecode Reader card [PCI-VLTC/RDR] + +pci:v0000AFFE* + ID_VENDOR_FROM_DATABASE=Sirrix AG security technologies + +pci:v0000AFFEd000001E1* + ID_MODEL_FROM_DATABASE=PCI1E1 1-port ISDN E1 interface + +pci:v0000AFFEd000002E1* + ID_MODEL_FROM_DATABASE=PCI2E1 2-port ISDN E1 interface + +pci:v0000AFFEd0000450E* + ID_MODEL_FROM_DATABASE=PCI4S0EC 4-port ISDN S0 interface + +pci:v0000AFFEd0000DEAD* + ID_MODEL_FROM_DATABASE=Sirrix.PCI4S0 4-port ISDN S0 interface + +pci:v0000B100* + ID_VENDOR_FROM_DATABASE=OpenVox Communication Co. Ltd. + +pci:v0000B10B* + ID_VENDOR_FROM_DATABASE=Uakron PCI Project + +pci:v0000B1B3* + ID_VENDOR_FROM_DATABASE=Shiva Europe Limited + +pci:v0000B1D9* + ID_VENDOR_FROM_DATABASE=ATCOM Technology co., LTD. + +pci:v0000BD11* + ID_VENDOR_FROM_DATABASE=Pinnacle Systems, Inc. (Wrong ID) + +pci:v0000BDBD* + ID_VENDOR_FROM_DATABASE=Blackmagic Design + +pci:v0000BDBDd0000A106* + ID_MODEL_FROM_DATABASE=Multibridge Extreme + +pci:v0000BDBDd0000A117* + ID_MODEL_FROM_DATABASE=Intensity Pro + +pci:v0000BDBDd0000A11A* + ID_MODEL_FROM_DATABASE=DeckLink HD Extreme 2 + +pci:v0000BDBDd0000A11B* + ID_MODEL_FROM_DATABASE=DeckLink SDI/Duo/Quad + +pci:v0000BDBDd0000A11C* + ID_MODEL_FROM_DATABASE=DeckLink HD Extreme 3 + +pci:v0000BDBDd0000A11D* + ID_MODEL_FROM_DATABASE=DeckLink Studio + +pci:v0000BDBDd0000A11E* + ID_MODEL_FROM_DATABASE=DeckLink Optical Fibre + +pci:v0000BDBDd0000A120* + ID_MODEL_FROM_DATABASE=Decklink Studio 2 + +pci:v0000BDBDd0000A121* + ID_MODEL_FROM_DATABASE=DeckLink HD Extreme 3D/3D+ + +pci:v0000BDBDd0000A124* + ID_MODEL_FROM_DATABASE=Intensity Extreme + +pci:v0000BDBDd0000A126* + ID_MODEL_FROM_DATABASE=Intensity Shuttle + +pci:v0000BDBDd0000A127* + ID_MODEL_FROM_DATABASE=UltraStudio Express + +pci:v0000BDBDd0000A129* + ID_MODEL_FROM_DATABASE=UltraStudio Mini Recorder + +pci:v0000BDBDd0000A12A* + ID_MODEL_FROM_DATABASE=UltraStudio Mini Monitor + +pci:v0000BDBDd0000A12D* + ID_MODEL_FROM_DATABASE=UltraStudio 4K + +pci:v0000BDBDd0000A12E* + ID_MODEL_FROM_DATABASE=DeckLink 4K Extreme + +pci:v0000BDBDd0000A12F* + ID_MODEL_FROM_DATABASE=DeckLink Mini Monitor + +pci:v0000BDBDd0000A130* + ID_MODEL_FROM_DATABASE=DeckLink Mini Recorder + +pci:v0000BDBDd0000A132* + ID_MODEL_FROM_DATABASE=UltraStudio 4K + +pci:v0000BDBDd0000A136* + ID_MODEL_FROM_DATABASE=DeckLink 4K Extreme 12G + +pci:v0000BDBDd0000A137* + ID_MODEL_FROM_DATABASE=DeckLink Studio 4K + +pci:v0000BDBDd0000A138* + ID_MODEL_FROM_DATABASE=Decklink SDI 4K + +pci:v0000BDBDd0000A139* + ID_MODEL_FROM_DATABASE=Intensity Pro 4K + +pci:v0000BDBDd0000A13B* + ID_MODEL_FROM_DATABASE=DeckLink Micro Recorder + +pci:v0000BDBDd0000A13D* + ID_MODEL_FROM_DATABASE=DeckLink 4K Pro + +pci:v0000BDBDd0000A13E* + ID_MODEL_FROM_DATABASE=UltraStudio 4K Extreme + +pci:v0000BDBDd0000A13F* + ID_MODEL_FROM_DATABASE=DeckLink Quad 2 + +pci:v0000BDBDd0000A140* + ID_MODEL_FROM_DATABASE=DeckLink Duo 2 + +pci:v0000BDBDd0000A141* + ID_MODEL_FROM_DATABASE=UltraStudio 4K Extreme 3 + +pci:v0000BDBDd0000A142* + ID_MODEL_FROM_DATABASE=UltraStudio HD Mini + +pci:v0000BDBDd0000A143* + ID_MODEL_FROM_DATABASE=DeckLink Mini Recorder 4K + +pci:v0000BDBDd0000A144* + ID_MODEL_FROM_DATABASE=DeckLink Mini Monitor 4K + +pci:v0000BDBDd0000A148* + ID_MODEL_FROM_DATABASE=DeckLink SDI Micro + +pci:v0000BDBDd0000A14B* + ID_MODEL_FROM_DATABASE=DeckLink 8K Pro + +pci:v0000BDBDd0000A14E* + ID_MODEL_FROM_DATABASE=DeckLink Quad HDMI Recorder + +pci:v0000BDBDd0000A1FF* + ID_MODEL_FROM_DATABASE=eGPU RX580 + +pci:v0000C001* + ID_VENDOR_FROM_DATABASE=TSI Telsys + +pci:v0000C0A9* + ID_VENDOR_FROM_DATABASE=Micron/Crucial Technology + +pci:v0000C0A9d00002263* + ID_MODEL_FROM_DATABASE=P1 NVMe PCIe SSD + +pci:v0000C0DE* + ID_VENDOR_FROM_DATABASE=Motorola + +pci:v0000C0FE* + ID_VENDOR_FROM_DATABASE=Motion Engineering, Inc. + +pci:v0000CA3B* + ID_VENDOR_FROM_DATABASE=Cambrionix Ltd. + +pci:v0000CA50* + ID_VENDOR_FROM_DATABASE=Varian Australia Pty Ltd + +pci:v0000CACE* + ID_VENDOR_FROM_DATABASE=CACE Technologies, Inc. + +pci:v0000CACEd00000001* + ID_MODEL_FROM_DATABASE=TurboCap Port A + +pci:v0000CACEd00000002* + ID_MODEL_FROM_DATABASE=TurboCap Port B + +pci:v0000CACEd00000023* + ID_MODEL_FROM_DATABASE=AirPcap N + +pci:v0000CAED* + ID_VENDOR_FROM_DATABASE=Canny Edge + +pci:v0000CAFE* + ID_VENDOR_FROM_DATABASE=Chrysalis-ITS + +pci:v0000CAFEd00000003* + ID_MODEL_FROM_DATABASE=Luna K3 Hardware Security Module + +pci:v0000CAFEd00000006* + ID_MODEL_FROM_DATABASE=Luna PCI-e 3000 Hardware Security Module + +pci:v0000CAFEd00000007* + ID_MODEL_FROM_DATABASE=Luna K6 Hardware Security Module + +pci:v0000CAFEd00000008* + ID_MODEL_FROM_DATABASE=Luna K7 Hardware Security Module + +pci:v0000CC53* + ID_VENDOR_FROM_DATABASE=ScaleFlux Inc. + +pci:v0000CCCC* + ID_VENDOR_FROM_DATABASE=Catapult Communications + +pci:v0000CCEC* + ID_VENDOR_FROM_DATABASE=Curtiss-Wright Controls Embedded Computing + +pci:v0000CDDD* + ID_VENDOR_FROM_DATABASE=Tyzx, Inc. + +pci:v0000CDDDd00000101* + ID_MODEL_FROM_DATABASE=DeepSea 1 High Speed Stereo Vision Frame Grabber + +pci:v0000CDDDd00000200* + ID_MODEL_FROM_DATABASE=DeepSea 2 High Speed Stereo Vision Frame Grabber + +pci:v0000CEBA* + ID_VENDOR_FROM_DATABASE=KEBA AG + +pci:v0000D161* + ID_VENDOR_FROM_DATABASE=Digium, Inc. + +pci:v0000D161d00000120* + ID_MODEL_FROM_DATABASE=Wildcard TE120P single-span T1/E1/J1 card + +pci:v0000D161d00000205* + ID_MODEL_FROM_DATABASE=Wildcard TE205P/TE207P dual-span T1/E1/J1 card 5.0V + +pci:v0000D161d00000210* + ID_MODEL_FROM_DATABASE=Wildcard TE210P/TE212P dual-span T1/E1/J1 card 3.3V + +pci:v0000D161d00000220* + ID_MODEL_FROM_DATABASE=Wildcard TE220 dual-span T1/E1/J1 card 3.3V (PCI-Express) + +pci:v0000D161d00000405* + ID_MODEL_FROM_DATABASE=Wildcard TE405P/TE407P quad-span T1/E1/J1 card 5.0V + +pci:v0000D161d00000410* + ID_MODEL_FROM_DATABASE=Wildcard TE410P/TE412P quad-span T1/E1/J1 card 3.3V + +pci:v0000D161d00000420* + ID_MODEL_FROM_DATABASE=Wildcard TE420P quad-span T1/E1/J1 card 3.3V (PCI-Express) + +pci:v0000D161d00000800* + ID_MODEL_FROM_DATABASE=Wildcard TDM800P 8-port analog card + +pci:v0000D161d00001205* + ID_MODEL_FROM_DATABASE=Wildcard TE205P/TE207P dual-span T1/E1/J1 card 5.0V (u1) + +pci:v0000D161d00001220* + ID_MODEL_FROM_DATABASE=Wildcard TE220 dual-span T1/E1/J1 card 3.3V (PCI-Express) (5th gen) + +pci:v0000D161d00001405* + ID_MODEL_FROM_DATABASE=Wildcard TE405P/TE407P quad-span T1/E1/J1 card 5.0V (u1) + +pci:v0000D161d00001410* + ID_MODEL_FROM_DATABASE=Wildcard TE410P quad-span T1/E1/J1 card 3.3V (5th Gen) + +pci:v0000D161d00001420* + ID_MODEL_FROM_DATABASE=Wildcard TE420 quad-span T1/E1/J1 card 3.3V (PCI-Express) (5th gen) + +pci:v0000D161d00001820* + ID_MODEL_FROM_DATABASE=Wildcard TE820 octal-span T1/E1/J1 card 3.3V (PCI-Express) + +pci:v0000D161d00002400* + ID_MODEL_FROM_DATABASE=Wildcard TDM2400P 24-port analog card + +pci:v0000D161d00003400* + ID_MODEL_FROM_DATABASE=Wildcard TC400P transcoder base card + +pci:v0000D161d00008000* + ID_MODEL_FROM_DATABASE=Wildcard TE121 single-span T1/E1/J1 card (PCI-Express) + +pci:v0000D161d00008001* + ID_MODEL_FROM_DATABASE=Wildcard TE122 single-span T1/E1/J1 card + +pci:v0000D161d00008002* + ID_MODEL_FROM_DATABASE=Wildcard AEX800 8-port analog card (PCI-Express) + +pci:v0000D161d00008003* + ID_MODEL_FROM_DATABASE=Wildcard AEX2400 24-port analog card (PCI-Express) + +pci:v0000D161d00008004* + ID_MODEL_FROM_DATABASE=Wildcard TCE400P transcoder base card + +pci:v0000D161d00008005* + ID_MODEL_FROM_DATABASE=Wildcard TDM410 4-port analog card + +pci:v0000D161d00008006* + ID_MODEL_FROM_DATABASE=Wildcard AEX410 4-port analog card (PCI-Express) + +pci:v0000D161d00008007* + ID_MODEL_FROM_DATABASE=Hx8 Series 8-port Base Card + +pci:v0000D161d00008008* + ID_MODEL_FROM_DATABASE=Hx8 Series 8-port Base Card (PCI-Express) + +pci:v0000D161d0000800A* + ID_MODEL_FROM_DATABASE=Wildcard TE133 single-span T1/E1/J1 card (PCI Express) + +pci:v0000D161d0000800B* + ID_MODEL_FROM_DATABASE=Wildcard TE134 single-span T1/E1/J1 card + +pci:v0000D161d0000800C* + ID_MODEL_FROM_DATABASE=Wildcard A8A 8-port analog card + +pci:v0000D161d0000800D* + ID_MODEL_FROM_DATABASE=Wildcard A8B 8-port analog card (PCI-Express) + +pci:v0000D161d0000800E* + ID_MODEL_FROM_DATABASE=Wildcard TE235/TE435 quad-span T1/E1/J1 card (PCI-Express) + +pci:v0000D161d0000800F* + ID_MODEL_FROM_DATABASE=Wildcard A4A 4-port analog card + +pci:v0000D161d00008010* + ID_MODEL_FROM_DATABASE=Wildcard A4B 4-port analog card (PCI-Express) + +pci:v0000D161d00008013* + ID_MODEL_FROM_DATABASE=Wildcard TE236/TE436 quad-span T1/E1/J1 card + +pci:v0000D161d0000B410* + ID_MODEL_FROM_DATABASE=Wildcard B410 quad-BRI card + +pci:v0000D209* + ID_VENDOR_FROM_DATABASE=Ultimarc + +pci:v0000D209d00001500* + ID_MODEL_FROM_DATABASE=PAC Drive + +pci:v0000D209d000015A2* + ID_MODEL_FROM_DATABASE=SpinTrak + +pci:v0000D209d00001601* + ID_MODEL_FROM_DATABASE=AimTrak + +pci:v0000D4D4* + ID_VENDOR_FROM_DATABASE=Dy4 Systems Inc + +pci:v0000D4D4d00000601* + ID_MODEL_FROM_DATABASE=PCI Mezzanine Card + +pci:v0000D531* + ID_VENDOR_FROM_DATABASE=I+ME ACTIA GmbH + +pci:v0000D84D* + ID_VENDOR_FROM_DATABASE=Exsys + +pci:v0000DADA* + ID_VENDOR_FROM_DATABASE=Datapath Limited + +pci:v0000DADAd00000133* + ID_MODEL_FROM_DATABASE=VisionRGB-X2 + +pci:v0000DADAd00000139* + ID_MODEL_FROM_DATABASE=VisionRGB-E1 + +pci:v0000DADAd00000144* + ID_MODEL_FROM_DATABASE=VisionSD8 + +pci:v0000DADAd00000150* + ID_MODEL_FROM_DATABASE=VisionRGB-E2 + +pci:v0000DADAd00000151* + ID_MODEL_FROM_DATABASE=VisionSD4+1 + +pci:v0000DADAd00000159* + ID_MODEL_FROM_DATABASE=VisionAV + +pci:v0000DADAd00000161* + ID_MODEL_FROM_DATABASE=DGC161 + +pci:v0000DADAd00000165* + ID_MODEL_FROM_DATABASE=DGC165 + +pci:v0000DADAd00000167* + ID_MODEL_FROM_DATABASE=DGC167 + +pci:v0000DADAd00000168* + ID_MODEL_FROM_DATABASE=DGC168 + +pci:v0000DADAd00001139* + ID_MODEL_FROM_DATABASE=VisionRGB-E1S + +pci:v0000DADAd00001150* + ID_MODEL_FROM_DATABASE=VisionRGB-E2S + +pci:v0000DADAd00001151* + ID_MODEL_FROM_DATABASE=VisionSD4+1S + +pci:v0000DADAd00001153* + ID_MODEL_FROM_DATABASE=VisionDVI-DL + +pci:v0000DADAd00001154* + ID_MODEL_FROM_DATABASE=VisionSDI2 + +pci:v0000DB10* + ID_VENDOR_FROM_DATABASE=Diablo Technologies + +pci:v0000DC93* + ID_VENDOR_FROM_DATABASE=Dawicontrol GmbH + +pci:v0000DCBA* + ID_VENDOR_FROM_DATABASE=Dynamic Engineering + +pci:v0000DCBAd00000046* + ID_MODEL_FROM_DATABASE=PCIe Altera Cyclone IV + +pci:v0000DCBAd00000047* + ID_MODEL_FROM_DATABASE=VPX-RCB + +pci:v0000DCBAd00000048* + ID_MODEL_FROM_DATABASE=PMC-Biserial-III-BAE9 + +pci:v0000DCBAd0000004E* + ID_MODEL_FROM_DATABASE=PC104p-Biserial-III-NVY5 + +pci:v0000DCBAd0000004F* + ID_MODEL_FROM_DATABASE=PC104p-Biserial-III-NVY6 + +pci:v0000DCBAd00000052* + ID_MODEL_FROM_DATABASE=PCIeBiSerialDb37 BA22 LVDS IO + +pci:v0000DCBAd00000066* + ID_MODEL_FROM_DATABASE=PMC-OctalUART-232 + +pci:v0000DD01* + ID_VENDOR_FROM_DATABASE=Digital Devices GmbH + +pci:v0000DD01d00000003* + ID_MODEL_FROM_DATABASE=Octopus DVB Adapter + +pci:v0000DD01d00000003sv0000DD01sd00000001* + ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Octopus DVB adapter) + +pci:v0000DD01d00000003sv0000DD01sd00000002* + ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Octopus LE DVB adapter) + +pci:v0000DD01d00000003sv0000DD01sd00000003* + ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Octopus OEM) + +pci:v0000DD01d00000003sv0000DD01sd00000004* + ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Octopus V3 DVB adapter) + +pci:v0000DD01d00000003sv0000DD01sd00000010* + ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Octopus Mini) + +pci:v0000DD01d00000003sv0000DD01sd00000020* + ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Cine S2 V6 DVB adapter) + +pci:v0000DD01d00000003sv0000DD01sd00000021* + ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Cine S2 V6.5 DVB adapter) + +pci:v0000DD01d00000003sv0000DD01sd00000030* + ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Cine CT V6.1 DVB adapter) + +pci:v0000DD01d00000003sv0000DD01sd0000DB03* + ID_MODEL_FROM_DATABASE=Octopus DVB Adapter (Mystique SaTiX-S2 V3 DVB adapter) + +pci:v0000DD01d00000006* + ID_MODEL_FROM_DATABASE=Cine V7 + +pci:v0000DD01d00000007* + ID_MODEL_FROM_DATABASE=Max + +pci:v0000DD01d00000007sv0000DD01sd00000023* + ID_MODEL_FROM_DATABASE=Max (S8 4/8) + +pci:v0000DD01d00000011* + ID_MODEL_FROM_DATABASE=Octopus CI DVB Adapter + +pci:v0000DD01d00000011sv0000DD01sd00000040* + ID_MODEL_FROM_DATABASE=Octopus CI DVB Adapter (Octopus CI) + +pci:v0000DD01d00000011sv0000DD01sd00000041* + ID_MODEL_FROM_DATABASE=Octopus CI DVB Adapter (Octopus CI Single) + +pci:v0000DD01d00000201* + ID_MODEL_FROM_DATABASE=Resi DVB-C Modulator + +pci:v0000DD01d00000201sv0000DD01sd00000001* + ID_MODEL_FROM_DATABASE=Resi DVB-C Modulator + +pci:v0000DEAD* + ID_VENDOR_FROM_DATABASE=Indigita Corporation + +pci:v0000DEAF* + ID_VENDOR_FROM_DATABASE=Middle Digital Inc. + +pci:v0000DEAFd00009050* + ID_MODEL_FROM_DATABASE=PC Weasel Virtual VGA + +pci:v0000DEAFd00009051* + ID_MODEL_FROM_DATABASE=PC Weasel Serial Port + +pci:v0000DEAFd00009052* + ID_MODEL_FROM_DATABASE=PC Weasel Watchdog Timer + +pci:v0000DEDA* + ID_VENDOR_FROM_DATABASE=XIMEA + +pci:v0000DEDAd00004001* + ID_MODEL_FROM_DATABASE=CB or MX camera + +pci:v0000DEDAd00004021* + ID_MODEL_FROM_DATABASE=MT camera + +pci:v0000E000* + ID_VENDOR_FROM_DATABASE=Winbond + +pci:v0000E000d0000E000* + ID_MODEL_FROM_DATABASE=W89C940 + +pci:v0000E159* + ID_VENDOR_FROM_DATABASE=Tiger Jet Network Inc. + +pci:v0000E159d00000001* + ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface + +pci:v0000E159d00000001sv00000059sd00000001* + ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (128k ISDN-S/T Adapter) + +pci:v0000E159d00000001sv00000059sd00000003* + ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (128k ISDN-U Adapter) + +pci:v0000E159d00000001sv000000A7sd00000001* + ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (TELES.S0/PCI 2.x ISDN Adapter) + +pci:v0000E159d00000001sv00008086sd00000003* + ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (Digium X100P/X101P analogue PSTN FXO interface) + +pci:v0000E159d00000001sv0000B100sd00000003* + ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (OpenVox A400P 4-port analog card) + +pci:v0000E159d00000001sv0000B1D9sd00000003* + ID_MODEL_FROM_DATABASE=Tiger3XX Modem/ISDN interface (AX400P 4-port analog card) + +pci:v0000E159d00000002* + ID_MODEL_FROM_DATABASE=Tiger100APC ISDN chipset + +pci:v0000E1C5* + ID_VENDOR_FROM_DATABASE=Elcus + +pci:v0000E4BF* + ID_VENDOR_FROM_DATABASE=EKF Elektronik GmbH + +pci:v0000E4BFd00000CCD* + ID_MODEL_FROM_DATABASE=CCD-CALYPSO + +pci:v0000E4BFd00000CD1* + ID_MODEL_FROM_DATABASE=CD1-OPERA + +pci:v0000E4BFd00000CD2* + ID_MODEL_FROM_DATABASE=CD2-BEBOP + +pci:v0000E4BFd00000CD3* + ID_MODEL_FROM_DATABASE=CD3-JIVE + +pci:v0000E4BFd000050C1* + ID_MODEL_FROM_DATABASE=PC1-GROOVE + +pci:v0000E4BFd000050C2* + ID_MODEL_FROM_DATABASE=PC2-LIMBO + +pci:v0000E4BFd000053C1* + ID_MODEL_FROM_DATABASE=SC1-ALLEGRO + +pci:v0000E4BFd0000CC47* + ID_MODEL_FROM_DATABASE=CCG-RUMBA + +pci:v0000E4BFd0000CC4D* + ID_MODEL_FROM_DATABASE=CCM-BOOGIE + +pci:v0000E4E4* + ID_VENDOR_FROM_DATABASE=Xorcom + +pci:v0000E55E* + ID_VENDOR_FROM_DATABASE=Essence Technology, Inc. + +pci:v0000EA01* + ID_VENDOR_FROM_DATABASE=Eagle Technology + +pci:v0000EA01d0000000A* + ID_MODEL_FROM_DATABASE=PCI-773 Temperature Card + +pci:v0000EA01d00000032* + ID_MODEL_FROM_DATABASE=PCI-730 & PC104P-30 Card + +pci:v0000EA01d0000003E* + ID_MODEL_FROM_DATABASE=PCI-762 Opto-Isolator Card + +pci:v0000EA01d00000041* + ID_MODEL_FROM_DATABASE=PCI-763 Reed Relay Card + +pci:v0000EA01d00000043* + ID_MODEL_FROM_DATABASE=PCI-769 Opto-Isolator Reed Relay Combo Card + +pci:v0000EA01d00000046* + ID_MODEL_FROM_DATABASE=PCI-766 Analog Output Card + +pci:v0000EA01d00000052* + ID_MODEL_FROM_DATABASE=PCI-703 Analog I/O Card + +pci:v0000EA01d00000800* + ID_MODEL_FROM_DATABASE=PCI-800 Digital I/O Card + +pci:v0000EA60* + ID_VENDOR_FROM_DATABASE=RME + +pci:v0000EA60d00009896* + ID_MODEL_FROM_DATABASE=Digi32 + +pci:v0000EA60d00009897* + ID_MODEL_FROM_DATABASE=Digi32 Pro + +pci:v0000EA60d00009898* + ID_MODEL_FROM_DATABASE=Digi32/8 + +pci:v0000EABB* + ID_VENDOR_FROM_DATABASE=Aashima Technology B.V. + +pci:v0000EACE* + ID_VENDOR_FROM_DATABASE=Endace Measurement Systems, Ltd + +pci:v0000EACEd00003100* + ID_MODEL_FROM_DATABASE=DAG 3.10 OC-3/OC-12 + +pci:v0000EACEd00003200* + ID_MODEL_FROM_DATABASE=DAG 3.2x OC-3/OC-12 + +pci:v0000EACEd0000320E* + ID_MODEL_FROM_DATABASE=DAG 3.2E Fast Ethernet + +pci:v0000EACEd0000340E* + ID_MODEL_FROM_DATABASE=DAG 3.4E Fast Ethernet + +pci:v0000EACEd0000341E* + ID_MODEL_FROM_DATABASE=DAG 3.41E Fast Ethernet + +pci:v0000EACEd00003500* + ID_MODEL_FROM_DATABASE=DAG 3.5 OC-3/OC-12 + +pci:v0000EACEd0000351C* + ID_MODEL_FROM_DATABASE=DAG 3.5ECM Fast Ethernet + +pci:v0000EACEd0000360D* + ID_MODEL_FROM_DATABASE=DAG 3.6D DS3 + +pci:v0000EACEd0000360E* + ID_MODEL_FROM_DATABASE=DAG 3.6E Fast Ethernet + +pci:v0000EACEd0000368E* + ID_MODEL_FROM_DATABASE=DAG 3.6E Gig Ethernet + +pci:v0000EACEd00003707* + ID_MODEL_FROM_DATABASE=DAG 3.7T T1/E1/J1 + +pci:v0000EACEd0000370D* + ID_MODEL_FROM_DATABASE=DAG 3.7D DS3/E3 + +pci:v0000EACEd0000378E* + ID_MODEL_FROM_DATABASE=DAG 3.7G Gig Ethernet + +pci:v0000EACEd00003800* + ID_MODEL_FROM_DATABASE=DAG 3.8S OC-3/OC-12 + +pci:v0000EACEd00004100* + ID_MODEL_FROM_DATABASE=DAG 4.10 OC-48 + +pci:v0000EACEd00004110* + ID_MODEL_FROM_DATABASE=DAG 4.11 OC-48 + +pci:v0000EACEd00004220* + ID_MODEL_FROM_DATABASE=DAG 4.2 OC-48 + +pci:v0000EACEd0000422E* + ID_MODEL_FROM_DATABASE=DAG 4.2GE Gig Ethernet + +pci:v0000EACEd00004230* + ID_MODEL_FROM_DATABASE=DAG 4.2S OC-48 + +pci:v0000EACEd0000423E* + ID_MODEL_FROM_DATABASE=DAG 4.2GE Gig Ethernet + +pci:v0000EACEd00004300* + ID_MODEL_FROM_DATABASE=DAG 4.3S OC-48 + +pci:v0000EACEd0000430E* + ID_MODEL_FROM_DATABASE=DAG 4.3GE Gig Ethernet + +pci:v0000EACEd0000452E* + ID_MODEL_FROM_DATABASE=DAG 4.5G2 Gig Ethernet + +pci:v0000EACEd0000454E* + ID_MODEL_FROM_DATABASE=DAG 4.5G4 Gig Ethernet + +pci:v0000EACEd000045B8* + ID_MODEL_FROM_DATABASE=DAG 4.5Z8 Gig Ethernet + +pci:v0000EACEd000045BE* + ID_MODEL_FROM_DATABASE=DAG 4.5Z2 Gig Ethernet + +pci:v0000EACEd0000520E* + ID_MODEL_FROM_DATABASE=DAG 5.2X 10G Ethernet + +pci:v0000EACEd0000521A* + ID_MODEL_FROM_DATABASE=DAG 5.2SXA 10G Ethernet/OC-192 + +pci:v0000EACEd00005400* + ID_MODEL_FROM_DATABASE=DAG 5.4S-12 OC-3/OC-12 + +pci:v0000EACEd00005401* + ID_MODEL_FROM_DATABASE=DAG 5.4SG-48 Gig Ethernet/OC-3/OC-12/OC-48 + +pci:v0000EACEd0000540A* + ID_MODEL_FROM_DATABASE=DAG 5.4GA Gig Ethernet + +pci:v0000EACEd0000541A* + ID_MODEL_FROM_DATABASE=DAG 5.4SA-12 OC-3/OC-12 + +pci:v0000EACEd0000542A* + ID_MODEL_FROM_DATABASE=DAG 5.4SGA-48 Gig Ethernet/OC-3/OC-12/OC-48 + +pci:v0000EACEd00006000* + ID_MODEL_FROM_DATABASE=DAG 6.0SE 10G Ethernet/OC-192 + +pci:v0000EACEd00006100* + ID_MODEL_FROM_DATABASE=DAG 6.1SE 10G Ethernet/OC-192 + +pci:v0000EACEd00006200* + ID_MODEL_FROM_DATABASE=DAG 6.2SE 10G Ethernet/OC-192 + +pci:v0000EACEd00007100* + ID_MODEL_FROM_DATABASE=DAG 7.1S OC-3/OC-12 + +pci:v0000EACEd00007400* + ID_MODEL_FROM_DATABASE=DAG 7.4S OC-3/OC-12 + +pci:v0000EACEd00007401* + ID_MODEL_FROM_DATABASE=DAG 7.4S48 OC-48 + +pci:v0000EACEd0000752E* + ID_MODEL_FROM_DATABASE=DAG 7.5G2 Gig Ethernet + +pci:v0000EACEd0000754E* + ID_MODEL_FROM_DATABASE=DAG 7.5G4 Gig Ethernet + +pci:v0000EACEd00008100* + ID_MODEL_FROM_DATABASE=DAG 8.1X 10G Ethernet + +pci:v0000EACEd00008101* + ID_MODEL_FROM_DATABASE=DAG 8.1SX 10G Ethernet/OC-192 + +pci:v0000EACEd00008102* + ID_MODEL_FROM_DATABASE=DAG 8.1X 10G Ethernet + +pci:v0000EACEd0000820E* + ID_MODEL_FROM_DATABASE=DAG 8.2X 10G Ethernet + +pci:v0000EACEd0000820F* + ID_MODEL_FROM_DATABASE=DAG 8.2X 10G Ethernet (2nd bus) + +pci:v0000EACEd00008400* + ID_MODEL_FROM_DATABASE=DAG 8.4I Infiniband x4 SDR + +pci:v0000EACEd00008500* + ID_MODEL_FROM_DATABASE=DAG 8.5I Infiniband x4 DDR + +pci:v0000EACEd00009200* + ID_MODEL_FROM_DATABASE=DAG 9.2SX2 10G Ethernet + +pci:v0000EACEd0000920E* + ID_MODEL_FROM_DATABASE=DAG 9.2X2 10G Ethernet + +pci:v0000EACEd00009540* + ID_MODEL_FROM_DATABASE=DAG 9.5G4 Gig Ethernet + +pci:v0000EACEd0000954F* + ID_MODEL_FROM_DATABASE=DAG 9.5G4F Gig Ethernet + +pci:v0000EACEd0000A120* + ID_MODEL_FROM_DATABASE=DAG 10X2-P 10G Ethernet + +pci:v0000EACEd0000A12E* + ID_MODEL_FROM_DATABASE=DAG 10X2-S 10G Ethernet + +pci:v0000EACEd0000A140* + ID_MODEL_FROM_DATABASE=DAG 10X4-P 10/40G Ethernet + +pci:v0000EACEd0000A14E* + ID_MODEL_FROM_DATABASE=DAG 10X4-S 10/40G Ethernet + +pci:v0000EACEd0000EACE* + ID_MODEL_FROM_DATABASE=vDAG virtual device + +pci:v0000EC80* + ID_VENDOR_FROM_DATABASE=Belkin Corporation + +pci:v0000EC80d0000EC00* + ID_MODEL_FROM_DATABASE=F5D6000 + +pci:v0000ECC0* + ID_VENDOR_FROM_DATABASE=Echo Digital Audio Corporation + +pci:v0000EDD8* + ID_VENDOR_FROM_DATABASE=ARK Logic Inc + +pci:v0000EDD8d0000A091* + ID_MODEL_FROM_DATABASE=1000PV [Stingray] + +pci:v0000EDD8d0000A099* + ID_MODEL_FROM_DATABASE=2000PV [Stingray] + +pci:v0000EDD8d0000A0A1* + ID_MODEL_FROM_DATABASE=2000MT + +pci:v0000EDD8d0000A0A9* + ID_MODEL_FROM_DATABASE=2000MI + +pci:v0000F043* + ID_VENDOR_FROM_DATABASE=ASUSTeK Computer Inc. (Wrong ID) + +pci:v0000F05B* + ID_VENDOR_FROM_DATABASE=Foxconn International, Inc. (Wrong ID) + +pci:v0000F15E* + ID_VENDOR_FROM_DATABASE=SiFive, Inc. + +pci:v0000F1D0* + ID_VENDOR_FROM_DATABASE=AJA Video + +pci:v0000F1D0d0000C0FE* + ID_MODEL_FROM_DATABASE=Xena HS/HD-R + +pci:v0000F1D0d0000C0FF* + ID_MODEL_FROM_DATABASE=Kona/Xena 2 + +pci:v0000F1D0d0000CAFE* + ID_MODEL_FROM_DATABASE=Kona SD + +pci:v0000F1D0d0000CFEE* + ID_MODEL_FROM_DATABASE=Xena LS/SD-22-DA/SD-DA + +pci:v0000F1D0d0000DAFE* + ID_MODEL_FROM_DATABASE=Corvid 1 + +pci:v0000F1D0d0000DAFF* + ID_MODEL_FROM_DATABASE=KONA LHi + +pci:v0000F1D0d0000DB00* + ID_MODEL_FROM_DATABASE=IoExpress + +pci:v0000F1D0d0000DB01* + ID_MODEL_FROM_DATABASE=Corvid22 + +pci:v0000F1D0d0000DB02* + ID_MODEL_FROM_DATABASE=Kona 3G + +pci:v0000F1D0d0000DB03* + ID_MODEL_FROM_DATABASE=Corvid 3G + +pci:v0000F1D0d0000DB04* + ID_MODEL_FROM_DATABASE=Kona 3G QUAD + +pci:v0000F1D0d0000DB05* + ID_MODEL_FROM_DATABASE=Kona LHe+ + +pci:v0000F1D0d0000DB06* + ID_MODEL_FROM_DATABASE=IoXT + +pci:v0000F1D0d0000DB07* + ID_MODEL_FROM_DATABASE=Kona 3G P2P + +pci:v0000F1D0d0000DB08* + ID_MODEL_FROM_DATABASE=Kona 3G QUAD P2P + +pci:v0000F1D0d0000DB09* + ID_MODEL_FROM_DATABASE=Corvid 24 + +pci:v0000F1D0d0000DB11* + ID_MODEL_FROM_DATABASE=T-Tap + +pci:v0000F1D0d0000DCAF* + ID_MODEL_FROM_DATABASE=Kona HD + +pci:v0000F1D0d0000DFEE* + ID_MODEL_FROM_DATABASE=Xena HD-DA + +pci:v0000F1D0d0000EB07* + ID_MODEL_FROM_DATABASE=Io4K + +pci:v0000F1D0d0000EB0A* + ID_MODEL_FROM_DATABASE=Io4K UFC + +pci:v0000F1D0d0000EB0B* + ID_MODEL_FROM_DATABASE=Kona 4 + +pci:v0000F1D0d0000EB0C* + ID_MODEL_FROM_DATABASE=Kona 4 UFC + +pci:v0000F1D0d0000EB0D* + ID_MODEL_FROM_DATABASE=Corvid 88 + +pci:v0000F1D0d0000EB0E* + ID_MODEL_FROM_DATABASE=Corvid 44 + +pci:v0000F1D0d0000EB16* + ID_MODEL_FROM_DATABASE=Corvid HEVC + +pci:v0000F1D0d0000EB16sv000010CFsd00001049* + ID_MODEL_FROM_DATABASE=Corvid HEVC (M31) + +pci:v0000F1D0d0000EB18* + ID_MODEL_FROM_DATABASE=Corvid HB-R + +pci:v0000F1D0d0000EB1A* + ID_MODEL_FROM_DATABASE=Kona IP 1SFP + +pci:v0000F1D0d0000EB1C* + ID_MODEL_FROM_DATABASE=Kona IP 2SFP + +pci:v0000F1D0d0000EB1D* + ID_MODEL_FROM_DATABASE=Io4KPlus + +pci:v0000F1D0d0000EB1E* + ID_MODEL_FROM_DATABASE=IoIP + +pci:v0000F1D0d0000EB1F* + ID_MODEL_FROM_DATABASE=Kona 5 + +pci:v0000F1D0d0000EB23* + ID_MODEL_FROM_DATABASE=Kona 1 + +pci:v0000F1D0d0000EB24* + ID_MODEL_FROM_DATABASE=Kona HDMI + +pci:v0000F1D0d0000EB25* + ID_MODEL_FROM_DATABASE=Corvid 44 12g + +pci:v0000F1D0d0000EFAC* + ID_MODEL_FROM_DATABASE=Xena SD-MM/SD-22-MM + +pci:v0000F1D0d0000FACD* + ID_MODEL_FROM_DATABASE=Xena HD-MM + +pci:v0000F5F5* + ID_VENDOR_FROM_DATABASE=F5 Networks, Inc. + +pci:v0000F849* + ID_VENDOR_FROM_DATABASE=ASRock Incorporation (Wrong ID) + +pci:v0000FA57* + ID_VENDOR_FROM_DATABASE=Interagon AS + +pci:v0000FA57d00000001* + ID_MODEL_FROM_DATABASE=PMC [Pattern Matching Chip] + +pci:v0000FAB7* + ID_VENDOR_FROM_DATABASE=Fabric7 Systems, Inc. + +pci:v0000FEBD* + ID_VENDOR_FROM_DATABASE=Ultraview Corp. + +pci:v0000FEDA* + ID_VENDOR_FROM_DATABASE=Broadcom Inc + +pci:v0000FEDAd0000A0FA* + ID_MODEL_FROM_DATABASE=BCM4210 iLine10 HomePNA 2.0 + +pci:v0000FEDAd0000A10E* + ID_MODEL_FROM_DATABASE=BCM4230 iLine10 HomePNA 2.0 + +pci:v0000FEDE* + ID_VENDOR_FROM_DATABASE=Fedetec Inc. + +pci:v0000FEDEd00000003* + ID_MODEL_FROM_DATABASE=TABIC PCI v3 + +pci:v0000FFFD* + ID_VENDOR_FROM_DATABASE=XenSource, Inc. + +pci:v0000FFFDd00000101* + ID_MODEL_FROM_DATABASE=PCI Event Channel Controller + +pci:v0000FFFE* + ID_VENDOR_FROM_DATABASE=VMWare Inc (temporary ID) + +pci:v0000FFFEd00000710* + ID_MODEL_FROM_DATABASE=Virtual SVGA + +pci:v0000FFFF* + ID_VENDOR_FROM_DATABASE=Illegal Vendor ID diff --git a/hwdb.d/20-sdio-classes.hwdb b/hwdb.d/20-sdio-classes.hwdb new file mode 100644 index 00000000..3bf56bbf --- /dev/null +++ b/hwdb.d/20-sdio-classes.hwdb @@ -0,0 +1,33 @@ +# This file is part of systemd. +# +# Data imported from: hwdb.d/sdio.ids + +sdio:c00v*d* + ID_SDIO_CLASS_FROM_DATABASE=Non-standard SDIO interface + +sdio:c01v*d* + ID_SDIO_CLASS_FROM_DATABASE=UART standard interface + +sdio:c02v*d* + ID_SDIO_CLASS_FROM_DATABASE=Bluetooth Type-A standard interface + +sdio:c03v*d* + ID_SDIO_CLASS_FROM_DATABASE=Bluetooth Type-B standard interface + +sdio:c04v*d* + ID_SDIO_CLASS_FROM_DATABASE=GPS standard interface + +sdio:c05v*d* + ID_SDIO_CLASS_FROM_DATABASE=Camera standard interface + +sdio:c06v*d* + ID_SDIO_CLASS_FROM_DATABASE=PHS standard interface + +sdio:c07v*d* + ID_SDIO_CLASS_FROM_DATABASE=WLAN interface + +sdio:c08v*d* + ID_SDIO_CLASS_FROM_DATABASE=Embedded SDIO-ATA standard interface + +sdio:c09v*d* + ID_SDIO_CLASS_FROM_DATABASE=Bluetooth AMP standard interface diff --git a/hwdb.d/20-sdio-vendor-model.hwdb b/hwdb.d/20-sdio-vendor-model.hwdb new file mode 100644 index 00000000..8d3e7243 --- /dev/null +++ b/hwdb.d/20-sdio-vendor-model.hwdb @@ -0,0 +1,210 @@ +# This file is part of systemd. +# +# Data imported from: hwdb.d/sdio.ids + +sdio:c*v0020* + ID_VENDOR_FROM_DATABASE=ST-Ericsson + +sdio:c*v0020d2280* + ID_MODEL_FROM_DATABASE=CW1200 + +sdio:c*v0089* + ID_VENDOR_FROM_DATABASE=Intel Corp. + +sdio:c*v0092* + ID_VENDOR_FROM_DATABASE=C-guys, Inc. + +sdio:c*v0092d0001* + ID_MODEL_FROM_DATABASE=SD-Link11b WiFi Card (TI ACX100) + +sdio:c*v0092d0004* + ID_MODEL_FROM_DATABASE=EW-CG1102GC + +sdio:c*v0092d0005* + ID_MODEL_FROM_DATABASE=SD FM Radio 2 + +sdio:c*v0092d5544* + ID_MODEL_FROM_DATABASE=SD FM Radio + +sdio:c*v0097* + ID_VENDOR_FROM_DATABASE=Texas Instruments, Inc. + +sdio:c*v0097d4076* + ID_MODEL_FROM_DATABASE=WL1271 + +sdio:c*v0098* + ID_VENDOR_FROM_DATABASE=Toshiba Corp. + +sdio:c*v0098d0001* + ID_MODEL_FROM_DATABASE=SD BT Card 1 + +sdio:c*v0098d0002* + ID_MODEL_FROM_DATABASE=SD BT Card 2 + +sdio:c*v0098d0003* + ID_MODEL_FROM_DATABASE=SD BT Card 3 + +sdio:c*v0104* + ID_VENDOR_FROM_DATABASE=Socket Communications, Inc. + +sdio:c*v0104d005E* + ID_MODEL_FROM_DATABASE=SD Scanner + +sdio:c*v0104d00C5* + ID_MODEL_FROM_DATABASE=Bluetooth SDIO Card + +sdio:c*v0271* + ID_VENDOR_FROM_DATABASE=Atheros Communications, Inc. + +sdio:c*v0271d0108* + ID_MODEL_FROM_DATABASE=AR6001 + +sdio:c*v0271d0109* + ID_MODEL_FROM_DATABASE=AR6001 + +sdio:c*v0271d010A* + ID_MODEL_FROM_DATABASE=AR6001 + +sdio:c*v0271d010B* + ID_MODEL_FROM_DATABASE=AR6001 + +sdio:c*v0296* + ID_VENDOR_FROM_DATABASE=GCT Semiconductor, Inc. + +sdio:c*v0296d5347* + ID_MODEL_FROM_DATABASE=GDM72xx WiMAX + +sdio:c*v02D0* + ID_VENDOR_FROM_DATABASE=Broadcom Corp. + +sdio:c*v02D0d044B* + ID_MODEL_FROM_DATABASE=Nintendo Wii WLAN daughter card + +sdio:c*v02D0d4324* + ID_MODEL_FROM_DATABASE=BCM43241 WLAN card + +sdio:c*v02D0d4329* + ID_MODEL_FROM_DATABASE=BCM4329 WLAN card + +sdio:c*v02D0d4330* + ID_MODEL_FROM_DATABASE=BCM4330 WLAN card + +sdio:c*v02D0d4334* + ID_MODEL_FROM_DATABASE=BCM4334 WLAN card + +sdio:c*v02D0d4335* + ID_MODEL_FROM_DATABASE=BCM4335/BCM4339 WLAN card + +sdio:c*v02D0d4354* + ID_MODEL_FROM_DATABASE=BCM4354 WLAN card + +sdio:c*v02D0dA887* + ID_MODEL_FROM_DATABASE=BCM43143 WLAN card + +sdio:c*v02D0dA94C* + ID_MODEL_FROM_DATABASE=BCM43340 WLAN card + +sdio:c*v02D0dA94D* + ID_MODEL_FROM_DATABASE=BCM43341 WLAN card + +sdio:c*v02D0dA962* + ID_MODEL_FROM_DATABASE=BCM43362 WLAN card + +sdio:c*v02D0dA9A6* + ID_MODEL_FROM_DATABASE=BCM43438 combo WLAN and Bluetooth Low Energy (BLE) # As in RPi3B + +sdio:c*v02DB* + ID_VENDOR_FROM_DATABASE=SyChip Inc. + +sdio:c*v02DBd0002* + ID_MODEL_FROM_DATABASE=Pegasus WLAN SDIO Card (6060SD) + +sdio:c*v02DF* + ID_VENDOR_FROM_DATABASE=Marvell Technology Group Ltd. + +sdio:c*v02DFd9103* + ID_MODEL_FROM_DATABASE=Libertas + +sdio:c*v02DFd9104* + ID_MODEL_FROM_DATABASE=SD8688 WLAN + +sdio:c*v02DFd9105* + ID_MODEL_FROM_DATABASE=SD8688 BT + +sdio:c*v02DFd9116* + ID_MODEL_FROM_DATABASE=SD8786 WLAN + +sdio:c*v02DFd9119* + ID_MODEL_FROM_DATABASE=SD8787 WLAN + +sdio:c*v02DFd911A* + ID_MODEL_FROM_DATABASE=SD8787 BT + +sdio:c*v02DFd911B* + ID_MODEL_FROM_DATABASE=SD8787 BT AMP + +sdio:c*v02DFd9129* + ID_MODEL_FROM_DATABASE=SD8797 WLAN + +sdio:c*v02DFd912A* + ID_MODEL_FROM_DATABASE=SD8797 BT + +sdio:c*v02DFd912D* + ID_MODEL_FROM_DATABASE=SD8897 WLAN + +sdio:c*v02DFd912E* + ID_MODEL_FROM_DATABASE=SD8897 BT + +sdio:c*v02FE* + ID_VENDOR_FROM_DATABASE=Spectec Computer Co., Ltd + +sdio:c*v02FEd2128* + ID_MODEL_FROM_DATABASE=SDIO WLAN Card (SDW820) + +sdio:c*v032A* + ID_VENDOR_FROM_DATABASE=Cambridge Silicon Radio + +sdio:c*v032Ad0001* + ID_MODEL_FROM_DATABASE=UniFi 1 + +sdio:c*v032Ad0002* + ID_MODEL_FROM_DATABASE=UniFi 2 + +sdio:c*v032Ad0007* + ID_MODEL_FROM_DATABASE=UniFi 3 + +sdio:c*v032Ad0008* + ID_MODEL_FROM_DATABASE=UniFi 4 + +sdio:c*v037A* + ID_VENDOR_FROM_DATABASE=MediaTek Inc. + +sdio:c*v037Ad5911* + ID_MODEL_FROM_DATABASE=Spectec WLAN-11b/g + +sdio:c*v039A* + ID_VENDOR_FROM_DATABASE=Siano Mobile Silicon + +sdio:c*v0501* + ID_VENDOR_FROM_DATABASE=Globalsat Technology Co. + +sdio:c*v0501dF501* + ID_MODEL_FROM_DATABASE=SD-501 GPS Card + +sdio:c*v104C* + ID_VENDOR_FROM_DATABASE=Texas Instruments, Inc. + +sdio:c*v104Cd9066* + ID_MODEL_FROM_DATABASE=WL1251 + +sdio:c*v1180* + ID_VENDOR_FROM_DATABASE=Ricoh Co., Ltd + +sdio:c*v1180dE823* + ID_MODEL_FROM_DATABASE=MMC card reader + +sdio:c*v13D1* + ID_VENDOR_FROM_DATABASE=AboCom Systems, Inc. + +sdio:c*v13D1dAC02* + ID_MODEL_FROM_DATABASE=SDW11G diff --git a/hwdb.d/20-usb-classes.hwdb b/hwdb.d/20-usb-classes.hwdb new file mode 100644 index 00000000..418d39bb --- /dev/null +++ b/hwdb.d/20-usb-classes.hwdb @@ -0,0 +1,342 @@ +# This file is part of systemd. +# +# Data imported from: http://www.linux-usb.org/usb.ids + +usb:v*p*d*dc01* + ID_USB_CLASS_FROM_DATABASE=Audio + +usb:v*p*d*dc01dsc01* + ID_USB_SUBCLASS_FROM_DATABASE=Control Device + +usb:v*p*d*dc01dsc02* + ID_USB_SUBCLASS_FROM_DATABASE=Streaming + +usb:v*p*d*dc01dsc03* + ID_USB_SUBCLASS_FROM_DATABASE=MIDI Streaming + +usb:v*p*d*dc02* + ID_USB_CLASS_FROM_DATABASE=Communications + +usb:v*p*d*dc02dsc01* + ID_USB_SUBCLASS_FROM_DATABASE=Direct Line + +usb:v*p*d*dc02dsc02* + ID_USB_SUBCLASS_FROM_DATABASE=Abstract (modem) + +usb:v*p*d*dc02dsc02dp01* + ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (v.25ter) + +usb:v*p*d*dc02dsc02dp02* + ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (PCCA101) + +usb:v*p*d*dc02dsc02dp03* + ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (PCCA101 + wakeup) + +usb:v*p*d*dc02dsc02dp04* + ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (GSM) + +usb:v*p*d*dc02dsc02dp05* + ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (3G) + +usb:v*p*d*dc02dsc02dp06* + ID_USB_PROTOCOL_FROM_DATABASE=AT-commands (CDMA) + +usb:v*p*d*dc02dsc02dpFE* + ID_USB_PROTOCOL_FROM_DATABASE=Defined by command set descriptor + +usb:v*p*d*dc02dsc02dpFF* + ID_USB_PROTOCOL_FROM_DATABASE=Vendor Specific (MSFT RNDIS?) + +usb:v*p*d*dc02dsc03* + ID_USB_SUBCLASS_FROM_DATABASE=Telephone + +usb:v*p*d*dc02dsc04* + ID_USB_SUBCLASS_FROM_DATABASE=Multi-Channel + +usb:v*p*d*dc02dsc05* + ID_USB_SUBCLASS_FROM_DATABASE=CAPI Control + +usb:v*p*d*dc02dsc06* + ID_USB_SUBCLASS_FROM_DATABASE=Ethernet Networking + +usb:v*p*d*dc02dsc07* + ID_USB_SUBCLASS_FROM_DATABASE=ATM Networking + +usb:v*p*d*dc02dsc08* + ID_USB_SUBCLASS_FROM_DATABASE=Wireless Handset Control + +usb:v*p*d*dc02dsc09* + ID_USB_SUBCLASS_FROM_DATABASE=Device Management + +usb:v*p*d*dc02dsc0A* + ID_USB_SUBCLASS_FROM_DATABASE=Mobile Direct Line + +usb:v*p*d*dc02dsc0B* + ID_USB_SUBCLASS_FROM_DATABASE=OBEX + +usb:v*p*d*dc02dsc0C* + ID_USB_SUBCLASS_FROM_DATABASE=Ethernet Emulation + +usb:v*p*d*dc02dsc0Cdp07* + ID_USB_PROTOCOL_FROM_DATABASE=Ethernet Emulation (EEM) + +usb:v*p*d*dc03* + ID_USB_CLASS_FROM_DATABASE=Human Interface Device + +usb:v*p*d*dc03dsc00dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Keyboard + +usb:v*p*d*dc03dsc00dp02* + ID_USB_PROTOCOL_FROM_DATABASE=Mouse + +usb:v*p*d*dc03dsc01* + ID_USB_SUBCLASS_FROM_DATABASE=Boot Interface Subclass + +usb:v*p*d*dc03dsc01dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Keyboard + +usb:v*p*d*dc03dsc01dp02* + ID_USB_PROTOCOL_FROM_DATABASE=Mouse + +usb:v*p*d*dc05* + ID_USB_CLASS_FROM_DATABASE=Physical Interface Device + +usb:v*p*d*dc06* + ID_USB_CLASS_FROM_DATABASE=Imaging + +usb:v*p*d*dc06dsc01* + ID_USB_SUBCLASS_FROM_DATABASE=Still Image Capture + +usb:v*p*d*dc06dsc01dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Picture Transfer Protocol (PIMA 15470) + +usb:v*p*d*dc07* + ID_USB_CLASS_FROM_DATABASE=Printer + +usb:v*p*d*dc07dsc01* + ID_USB_SUBCLASS_FROM_DATABASE=Printer + +usb:v*p*d*dc07dsc01dp00* + ID_USB_PROTOCOL_FROM_DATABASE=Reserved/Undefined + +usb:v*p*d*dc07dsc01dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Unidirectional + +usb:v*p*d*dc07dsc01dp02* + ID_USB_PROTOCOL_FROM_DATABASE=Bidirectional + +usb:v*p*d*dc07dsc01dp03* + ID_USB_PROTOCOL_FROM_DATABASE=IEEE 1284.4 compatible bidirectional + +usb:v*p*d*dc07dsc01dpFF* + ID_USB_PROTOCOL_FROM_DATABASE=Vendor Specific + +usb:v*p*d*dc08* + ID_USB_CLASS_FROM_DATABASE=Mass Storage + +usb:v*p*d*dc08dsc01* + ID_USB_SUBCLASS_FROM_DATABASE=RBC (typically Flash) + +usb:v*p*d*dc08dsc01dp00* + ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk/Interrupt + +usb:v*p*d*dc08dsc01dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk + +usb:v*p*d*dc08dsc01dp50* + ID_USB_PROTOCOL_FROM_DATABASE=Bulk-Only + +usb:v*p*d*dc08dsc02* + ID_USB_SUBCLASS_FROM_DATABASE=SFF-8020i, MMC-2 (ATAPI) + +usb:v*p*d*dc08dsc03* + ID_USB_SUBCLASS_FROM_DATABASE=QIC-157 + +usb:v*p*d*dc08dsc04* + ID_USB_SUBCLASS_FROM_DATABASE=Floppy (UFI) + +usb:v*p*d*dc08dsc04dp00* + ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk/Interrupt + +usb:v*p*d*dc08dsc04dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk + +usb:v*p*d*dc08dsc04dp50* + ID_USB_PROTOCOL_FROM_DATABASE=Bulk-Only + +usb:v*p*d*dc08dsc05* + ID_USB_SUBCLASS_FROM_DATABASE=SFF-8070i + +usb:v*p*d*dc08dsc06* + ID_USB_SUBCLASS_FROM_DATABASE=SCSI + +usb:v*p*d*dc08dsc06dp00* + ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk/Interrupt + +usb:v*p*d*dc08dsc06dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Control/Bulk + +usb:v*p*d*dc08dsc06dp50* + ID_USB_PROTOCOL_FROM_DATABASE=Bulk-Only + +usb:v*p*d*dc09* + ID_USB_CLASS_FROM_DATABASE=Hub + +usb:v*p*d*dc09dsc00dp00* + ID_USB_PROTOCOL_FROM_DATABASE=Full speed (or root) hub + +usb:v*p*d*dc09dsc00dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Single TT + +usb:v*p*d*dc09dsc00dp02* + ID_USB_PROTOCOL_FROM_DATABASE=TT per port + +usb:v*p*d*dc0A* + ID_USB_CLASS_FROM_DATABASE=CDC Data + +usb:v*p*d*dc0Adsc00dp30* + ID_USB_PROTOCOL_FROM_DATABASE=I.430 ISDN BRI + +usb:v*p*d*dc0Adsc00dp31* + ID_USB_PROTOCOL_FROM_DATABASE=HDLC + +usb:v*p*d*dc0Adsc00dp32* + ID_USB_PROTOCOL_FROM_DATABASE=Transparent + +usb:v*p*d*dc0Adsc00dp50* + ID_USB_PROTOCOL_FROM_DATABASE=Q.921M + +usb:v*p*d*dc0Adsc00dp51* + ID_USB_PROTOCOL_FROM_DATABASE=Q.921 + +usb:v*p*d*dc0Adsc00dp52* + ID_USB_PROTOCOL_FROM_DATABASE=Q.921TM + +usb:v*p*d*dc0Adsc00dp90* + ID_USB_PROTOCOL_FROM_DATABASE=V.42bis + +usb:v*p*d*dc0Adsc00dp91* + ID_USB_PROTOCOL_FROM_DATABASE=Q.932 EuroISDN + +usb:v*p*d*dc0Adsc00dp92* + ID_USB_PROTOCOL_FROM_DATABASE=V.120 V.24 rate ISDN + +usb:v*p*d*dc0Adsc00dp93* + ID_USB_PROTOCOL_FROM_DATABASE=CAPI 2.0 + +usb:v*p*d*dc0Adsc00dpFD* + ID_USB_PROTOCOL_FROM_DATABASE=Host Based Driver + +usb:v*p*d*dc0Adsc00dpFE* + ID_USB_PROTOCOL_FROM_DATABASE=CDC PUF + +usb:v*p*d*dc0Adsc00dpFF* + ID_USB_PROTOCOL_FROM_DATABASE=Vendor specific + +usb:v*p*d*dc0B* + ID_USB_CLASS_FROM_DATABASE=Chip/SmartCard + +usb:v*p*d*dc0D* + ID_USB_CLASS_FROM_DATABASE=Content Security + +usb:v*p*d*dc0E* + ID_USB_CLASS_FROM_DATABASE=Video + +usb:v*p*d*dc0Edsc01* + ID_USB_SUBCLASS_FROM_DATABASE=Video Control + +usb:v*p*d*dc0Edsc02* + ID_USB_SUBCLASS_FROM_DATABASE=Video Streaming + +usb:v*p*d*dc0Edsc03* + ID_USB_SUBCLASS_FROM_DATABASE=Video Interface Collection + +usb:v*p*d*dc58* + ID_USB_CLASS_FROM_DATABASE=Xbox + +usb:v*p*d*dc58dsc42* + ID_USB_SUBCLASS_FROM_DATABASE=Controller + +usb:v*p*d*dcDC* + ID_USB_CLASS_FROM_DATABASE=Diagnostic + +usb:v*p*d*dcDCdsc01* + ID_USB_SUBCLASS_FROM_DATABASE=Reprogrammable Diagnostics + +usb:v*p*d*dcDCdsc01dp01* + ID_USB_PROTOCOL_FROM_DATABASE=USB2 Compliance + +usb:v*p*d*dcE0* + ID_USB_CLASS_FROM_DATABASE=Wireless + +usb:v*p*d*dcE0dsc01* + ID_USB_SUBCLASS_FROM_DATABASE=Radio Frequency + +usb:v*p*d*dcE0dsc01dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Bluetooth + +usb:v*p*d*dcE0dsc01dp02* + ID_USB_PROTOCOL_FROM_DATABASE=Ultra WideBand Radio Control + +usb:v*p*d*dcE0dsc01dp03* + ID_USB_PROTOCOL_FROM_DATABASE=RNDIS + +usb:v*p*d*dcE0dsc02* + ID_USB_SUBCLASS_FROM_DATABASE=Wireless USB Wire Adapter + +usb:v*p*d*dcE0dsc02dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Host Wire Adapter Control/Data Streaming + +usb:v*p*d*dcE0dsc02dp02* + ID_USB_PROTOCOL_FROM_DATABASE=Device Wire Adapter Control/Data Streaming + +usb:v*p*d*dcE0dsc02dp03* + ID_USB_PROTOCOL_FROM_DATABASE=Device Wire Adapter Isochronous Streaming + +usb:v*p*d*dcEF* + ID_USB_CLASS_FROM_DATABASE=Miscellaneous Device + +usb:v*p*d*dcEFdsc01dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Microsoft ActiveSync + +usb:v*p*d*dcEFdsc01dp02* + ID_USB_PROTOCOL_FROM_DATABASE=Palm Sync + +usb:v*p*d*dcEFdsc02dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Interface Association + +usb:v*p*d*dcEFdsc02dp02* + ID_USB_PROTOCOL_FROM_DATABASE=Wire Adapter Multifunction Peripheral + +usb:v*p*d*dcEFdsc03dp01* + ID_USB_PROTOCOL_FROM_DATABASE=Cable Based Association + +usb:v*p*d*dcEFdsc05* + ID_USB_SUBCLASS_FROM_DATABASE=USB3 Vision + +usb:v*p*d*dcFE* + ID_USB_CLASS_FROM_DATABASE=Application Specific Interface + +usb:v*p*d*dcFEdsc01* + ID_USB_SUBCLASS_FROM_DATABASE=Device Firmware Update + +usb:v*p*d*dcFEdsc02* + ID_USB_SUBCLASS_FROM_DATABASE=IRDA Bridge + +usb:v*p*d*dcFEdsc03* + ID_USB_SUBCLASS_FROM_DATABASE=Test and Measurement + +usb:v*p*d*dcFEdsc03dp01* + ID_USB_PROTOCOL_FROM_DATABASE=TMC + +usb:v*p*d*dcFEdsc03dp02* + ID_USB_PROTOCOL_FROM_DATABASE=USB488 + +usb:v*p*d*dcFF* + ID_USB_CLASS_FROM_DATABASE=Vendor Specific Class + +usb:v*p*d*dcFFdscFF* + ID_USB_SUBCLASS_FROM_DATABASE=Vendor Specific Subclass + +usb:v*p*d*dcFFdscFFdpFF* + ID_USB_PROTOCOL_FROM_DATABASE=Vendor Specific Protocol diff --git a/hwdb.d/20-usb-vendor-model.hwdb b/hwdb.d/20-usb-vendor-model.hwdb new file mode 100644 index 00000000..96bb4722 --- /dev/null +++ b/hwdb.d/20-usb-vendor-model.hwdb @@ -0,0 +1,60309 @@ +# This file is part of systemd. +# +# Data imported from: http://www.linux-usb.org/usb.ids + +usb:v0001* + ID_VENDOR_FROM_DATABASE=Fry's Electronics + +usb:v0001p7778* + ID_MODEL_FROM_DATABASE=Counterfeit flash drive [Kingston] + +usb:v0002* + ID_VENDOR_FROM_DATABASE=Ingram + +usb:v0003* + ID_VENDOR_FROM_DATABASE=Club Mac + +usb:v0004* + ID_VENDOR_FROM_DATABASE=Nebraska Furniture Mart + +usb:v0011* + ID_VENDOR_FROM_DATABASE=Unknown + +usb:v0011p7788* + ID_MODEL_FROM_DATABASE=counterfeit flash drive + +usb:v0053* + ID_VENDOR_FROM_DATABASE=Planex + +usb:v0053p5301* + ID_MODEL_FROM_DATABASE=GW-US54ZGL 802.11bg + +usb:v0078* + ID_VENDOR_FROM_DATABASE=Microntek + +usb:v0078p0006* + ID_MODEL_FROM_DATABASE=Joystick + +usb:v0079* + ID_VENDOR_FROM_DATABASE=DragonRise Inc. + +usb:v0079p0006* + ID_MODEL_FROM_DATABASE=PC TWIN SHOCK Gamepad + +usb:v0079p0011* + ID_MODEL_FROM_DATABASE=Gamepad + +usb:v0079p1800* + ID_MODEL_FROM_DATABASE=Mayflash Wii U Pro Game Controller Adapter [DirectInput] + +usb:v0079p181B* + ID_MODEL_FROM_DATABASE=Venom Arcade Joystick + +usb:v0079p1843* + ID_MODEL_FROM_DATABASE=Mayflash GameCube Controller Adapter + +usb:v0079p1844* + ID_MODEL_FROM_DATABASE=Mayflash GameCube Controller + +usb:v0080* + ID_VENDOR_FROM_DATABASE=Assmann Electronic GmbH + +usb:v0080pA001* + ID_MODEL_FROM_DATABASE=Digitus DA-71114 SATA + +usb:v0085* + ID_VENDOR_FROM_DATABASE=Boeye Technology Co., Ltd. + +usb:v0085p0600* + ID_MODEL_FROM_DATABASE=eBook Reader + +usb:v0105* + ID_VENDOR_FROM_DATABASE=Trust International B.V. + +usb:v0105p145F* + ID_MODEL_FROM_DATABASE=NW-3100 802.11b/g 54Mbps Wireless Network Adapter [zd1211] + +usb:v0127* + ID_VENDOR_FROM_DATABASE=IBP + +usb:v0127p0002* + ID_MODEL_FROM_DATABASE=HDM Interface + +usb:v0127p0127* + ID_MODEL_FROM_DATABASE=ibp + +usb:v0145* + ID_VENDOR_FROM_DATABASE=Unknown + +usb:v0145p0112* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v017C* + ID_VENDOR_FROM_DATABASE=MLK + +usb:v017Cp145F* + ID_MODEL_FROM_DATABASE=Trust Deskset + +usb:v0200* + ID_VENDOR_FROM_DATABASE=TP-Link + +usb:v0200p0201* + ID_MODEL_FROM_DATABASE=MA180 UMTS Modem + +usb:v0204* + ID_VENDOR_FROM_DATABASE=Chipsbank Microelectronics Co., Ltd + +usb:v0204p6025* + ID_MODEL_FROM_DATABASE=CBM2080 / CBM2090 Flash drive controller + +usb:v0204p6026* + ID_MODEL_FROM_DATABASE=CBM1180 Flash drive controller + +usb:v0218* + ID_VENDOR_FROM_DATABASE=Hangzhou Worlde + +usb:v0218p0301* + ID_MODEL_FROM_DATABASE=MIDI Port + +usb:v02AD* + ID_VENDOR_FROM_DATABASE=HUMAX Co., Ltd. + +usb:v02ADp138C* + ID_MODEL_FROM_DATABASE=PVR Mass Storage + +usb:v0303* + ID_VENDOR_FROM_DATABASE=Mini Automation Controller + +usb:v0324* + ID_VENDOR_FROM_DATABASE=OCZ Technology Inc + +usb:v0324pBC06* + ID_MODEL_FROM_DATABASE=OCZ ATV USB 2.0 Flash Drive + +usb:v0324pBC08* + ID_MODEL_FROM_DATABASE=OCZ Rally2/ATV USB 2.0 Flash Drive + +usb:v0325* + ID_VENDOR_FROM_DATABASE=OCZ Technology Inc + +usb:v0325pAC02* + ID_MODEL_FROM_DATABASE=ATV Turbo / Rally2 Dual Channel USB 2.0 Flash Drive + +usb:v0386* + ID_VENDOR_FROM_DATABASE=LTS + +usb:v0386p0001* + ID_MODEL_FROM_DATABASE=PSX for USB Converter + +usb:v03D9* + ID_VENDOR_FROM_DATABASE=Shenzhen Sinote Tech-Electron Co., Ltd + +usb:v03D9p0499* + ID_MODEL_FROM_DATABASE=SE340D PC Remote Control + +usb:v03DA* + ID_VENDOR_FROM_DATABASE=Bernd Walter Computer Technology + +usb:v03DAp0002* + ID_MODEL_FROM_DATABASE=HD44780 LCD interface + +usb:v03E7* + ID_VENDOR_FROM_DATABASE=Intel + +usb:v03E7p2150* + ID_MODEL_FROM_DATABASE=Myriad VPU [Movidius Neural Compute Stick] + +usb:v03E7p2485* + ID_MODEL_FROM_DATABASE=Movidius MyriadX + +usb:v03E7pF63B* + ID_MODEL_FROM_DATABASE=Myriad VPU [Movidius Neural Compute Stick] + +usb:v03E8* + ID_VENDOR_FROM_DATABASE=EndPoints, Inc. + +usb:v03E8p0004* + ID_MODEL_FROM_DATABASE=SE401 Webcam + +usb:v03E8p0008* + ID_MODEL_FROM_DATABASE=101 Ethernet [klsi] + +usb:v03E8p0015* + ID_MODEL_FROM_DATABASE=ATAPI Enclosure + +usb:v03E8p2123* + ID_MODEL_FROM_DATABASE=SiPix StyleCam Deluxe + +usb:v03E8p8004* + ID_MODEL_FROM_DATABASE=Aox 99001 + +usb:v03E9* + ID_VENDOR_FROM_DATABASE=Thesys Microelectronics + +usb:v03EA* + ID_VENDOR_FROM_DATABASE=Data Broadcasting Corp. + +usb:v03EB* + ID_VENDOR_FROM_DATABASE=Atmel Corp. + +usb:v03EBp0902* + ID_MODEL_FROM_DATABASE=4-Port Hub + +usb:v03EBp2002* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v03EBp2015* + ID_MODEL_FROM_DATABASE=at90usbkey sample firmware (HID keyboard) + +usb:v03EBp2018* + ID_MODEL_FROM_DATABASE=at90usbkey sample firmware (CDC ACM) + +usb:v03EBp2019* + ID_MODEL_FROM_DATABASE=stk525 sample firmware (microphone) + +usb:v03EBp201C* + ID_MODEL_FROM_DATABASE=at90usbkey sample firmware (HID mouse) + +usb:v03EBp201D* + ID_MODEL_FROM_DATABASE=at90usbkey sample firmware (HID generic) + +usb:v03EBp2022* + ID_MODEL_FROM_DATABASE=at90usbkey sample firmware (composite device) + +usb:v03EBp2040* + ID_MODEL_FROM_DATABASE=LUFA Test PID + +usb:v03EBp2041* + ID_MODEL_FROM_DATABASE=LUFA Mouse Demo Application + +usb:v03EBp2042* + ID_MODEL_FROM_DATABASE=LUFA Keyboard Demo Application + +usb:v03EBp2043* + ID_MODEL_FROM_DATABASE=LUFA Joystick Demo Application + +usb:v03EBp2044* + ID_MODEL_FROM_DATABASE=LUFA CDC Demo Application + +usb:v03EBp2045* + ID_MODEL_FROM_DATABASE=LUFA Mass Storage Demo Application + +usb:v03EBp2046* + ID_MODEL_FROM_DATABASE=LUFA Audio Output Demo Application + +usb:v03EBp2047* + ID_MODEL_FROM_DATABASE=LUFA Audio Input Demo Application + +usb:v03EBp2048* + ID_MODEL_FROM_DATABASE=LUFA MIDI Demo Application + +usb:v03EBp2049* + ID_MODEL_FROM_DATABASE=Stripe Snoop Magnetic Stripe Reader + +usb:v03EBp204A* + ID_MODEL_FROM_DATABASE=LUFA CDC Class Bootloader + +usb:v03EBp204B* + ID_MODEL_FROM_DATABASE=LUFA USB to Serial Adapter Project + +usb:v03EBp204C* + ID_MODEL_FROM_DATABASE=LUFA RNDIS Demo Application + +usb:v03EBp204D* + ID_MODEL_FROM_DATABASE=LUFA Combined Mouse and Keyboard Demo Application + +usb:v03EBp204E* + ID_MODEL_FROM_DATABASE=LUFA Dual CDC Demo Application + +usb:v03EBp204F* + ID_MODEL_FROM_DATABASE=LUFA Generic HID Demo Application + +usb:v03EBp2060* + ID_MODEL_FROM_DATABASE=Benito Programmer Project + +usb:v03EBp2061* + ID_MODEL_FROM_DATABASE=LUFA Combined Mass Storage and Keyboard Demo Application + +usb:v03EBp2062* + ID_MODEL_FROM_DATABASE=LUFA Combined CDC and Mouse Demo Application + +usb:v03EBp2063* + ID_MODEL_FROM_DATABASE=LUFA Datalogger Device + +usb:v03EBp2064* + ID_MODEL_FROM_DATABASE=Interfaceless Control-Only LUFA Devices + +usb:v03EBp2065* + ID_MODEL_FROM_DATABASE=LUFA Test and Measurement Demo Application + +usb:v03EBp2066* + ID_MODEL_FROM_DATABASE=LUFA Multiple Report HID Demo + +usb:v03EBp2068* + ID_MODEL_FROM_DATABASE=LUFA Virtual Serial/Mass Storage Demo + +usb:v03EBp2069* + ID_MODEL_FROM_DATABASE=LUFA Webserver Project + +usb:v03EBp2103* + ID_MODEL_FROM_DATABASE=JTAG ICE mkII + +usb:v03EBp2104* + ID_MODEL_FROM_DATABASE=AVR ISP mkII + +usb:v03EBp2105* + ID_MODEL_FROM_DATABASE=AVRONE! + +usb:v03EBp2106* + ID_MODEL_FROM_DATABASE=STK600 development board + +usb:v03EBp2107* + ID_MODEL_FROM_DATABASE=AVR Dragon + +usb:v03EBp2109* + ID_MODEL_FROM_DATABASE=STK541 ZigBee Development Board + +usb:v03EBp210A* + ID_MODEL_FROM_DATABASE=AT86RF230 [RZUSBSTICK] transceiver + +usb:v03EBp210D* + ID_MODEL_FROM_DATABASE=XPLAIN evaluation kit (CDC ACM) + +usb:v03EBp2110* + ID_MODEL_FROM_DATABASE=AVR JTAGICE3 Debugger and Programmer + +usb:v03EBp2111* + ID_MODEL_FROM_DATABASE=Xplained Pro board debugger and programmer + +usb:v03EBp2122* + ID_MODEL_FROM_DATABASE=XMEGA-A1 Explained evaluation kit + +usb:v03EBp2140* + ID_MODEL_FROM_DATABASE=AVR JTAGICE3 (v3.x) Debugger and Programmer + +usb:v03EBp2141* + ID_MODEL_FROM_DATABASE=ICE debugger + +usb:v03EBp2145* + ID_MODEL_FROM_DATABASE=ATMEGA328P-XMINI (CDC ACM) + +usb:v03EBp2310* + ID_MODEL_FROM_DATABASE=EVK11xx evaluation board + +usb:v03EBp2404* + ID_MODEL_FROM_DATABASE=The Micro + +usb:v03EBp2FE4* + ID_MODEL_FROM_DATABASE=ATxmega32A4U DFU bootloader + +usb:v03EBp2FE6* + ID_MODEL_FROM_DATABASE=Cactus V6 (DFU) + +usb:v03EBp2FEA* + ID_MODEL_FROM_DATABASE=Cactus RF60 (DFU) + +usb:v03EBp2FEE* + ID_MODEL_FROM_DATABASE=atmega8u2 DFU bootloader + +usb:v03EBp2FEF* + ID_MODEL_FROM_DATABASE=atmega16u2 DFU bootloader + +usb:v03EBp2FF0* + ID_MODEL_FROM_DATABASE=atmega32u2 DFU bootloader + +usb:v03EBp2FF1* + ID_MODEL_FROM_DATABASE=at32uc3a3 DFU bootloader + +usb:v03EBp2FF3* + ID_MODEL_FROM_DATABASE=atmega16u4 DFU bootloader + +usb:v03EBp2FF4* + ID_MODEL_FROM_DATABASE=atmega32u4 DFU bootloader + +usb:v03EBp2FF6* + ID_MODEL_FROM_DATABASE=at32uc3b0/1 DFU bootloader + +usb:v03EBp2FF7* + ID_MODEL_FROM_DATABASE=at90usb82 DFU bootloader + +usb:v03EBp2FF8* + ID_MODEL_FROM_DATABASE=at32uc3a0/1 DFU bootloader + +usb:v03EBp2FF9* + ID_MODEL_FROM_DATABASE=at90usb646/647 DFU bootloader + +usb:v03EBp2FFA* + ID_MODEL_FROM_DATABASE=at90usb162 DFU bootloader + +usb:v03EBp2FFB* + ID_MODEL_FROM_DATABASE=at90usb AVR DFU bootloader + +usb:v03EBp2FFD* + ID_MODEL_FROM_DATABASE=at89c5130/c5131 DFU bootloader + +usb:v03EBp2FFF* + ID_MODEL_FROM_DATABASE=at89c5132/c51snd1c DFU bootloader + +usb:v03EBp3301* + ID_MODEL_FROM_DATABASE=at43301 4-Port Hub + +usb:v03EBp3312* + ID_MODEL_FROM_DATABASE=4-Port Hub + +usb:v03EBp4102* + ID_MODEL_FROM_DATABASE=AirVast W-Buddie WN210 + +usb:v03EBp5601* + ID_MODEL_FROM_DATABASE=at76c510 Prism-II 802.11b Access Point + +usb:v03EBp5603* + ID_MODEL_FROM_DATABASE=Cisco 7920 WiFi IP Phone + +usb:v03EBp6119* + ID_MODEL_FROM_DATABASE=AT91SAM CDC Demo Application + +usb:v03EBp6124* + ID_MODEL_FROM_DATABASE=at91sam SAMBA bootloader + +usb:v03EBp6127* + ID_MODEL_FROM_DATABASE=AT91SAM HID Keyboard Demo Application + +usb:v03EBp6129* + ID_MODEL_FROM_DATABASE=AT91SAM Mass Storage Demo Application + +usb:v03EBp6200* + ID_MODEL_FROM_DATABASE=AT91SAM HID Mouse Demo Application + +usb:v03EBp7603* + ID_MODEL_FROM_DATABASE=D-Link DWL-120 802.11b Wireless Adapter [Atmel at76c503a] + +usb:v03EBp7604* + ID_MODEL_FROM_DATABASE=at76c503a 802.11b Adapter + +usb:v03EBp7605* + ID_MODEL_FROM_DATABASE=at76c503a 802.11b Adapter + +usb:v03EBp7606* + ID_MODEL_FROM_DATABASE=at76c505 802.11b Adapter + +usb:v03EBp7611* + ID_MODEL_FROM_DATABASE=at76c510 rfmd2948 802.11b Access Point + +usb:v03EBp7613* + ID_MODEL_FROM_DATABASE=WL-1130 USB + +usb:v03EBp7614* + ID_MODEL_FROM_DATABASE=AT76c505a Wireless Adapter + +usb:v03EBp7615* + ID_MODEL_FROM_DATABASE=AT76C505AMX Wireless Adapter + +usb:v03EBp7617* + ID_MODEL_FROM_DATABASE=AT76C505AS Wireless Adapter + +usb:v03EBp7800* + ID_MODEL_FROM_DATABASE=Mini Album + +usb:v03EBp800C* + ID_MODEL_FROM_DATABASE=Airspy HF+ + +usb:v03EBpFF02* + ID_MODEL_FROM_DATABASE=WootingTwo + +usb:v03EBpFF07* + ID_MODEL_FROM_DATABASE=Tux Droid fish dongle + +usb:v03EC* + ID_VENDOR_FROM_DATABASE=Iwatsu America, Inc. + +usb:v03ED* + ID_VENDOR_FROM_DATABASE=Mitel Corp. + +usb:v03EE* + ID_VENDOR_FROM_DATABASE=Mitsumi + +usb:v03EEp0000* + ID_MODEL_FROM_DATABASE=CD-R/RW Drive + +usb:v03EEp2501* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v03EEp2502* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v03EEp5609* + ID_MODEL_FROM_DATABASE=Japanese Keyboard + +usb:v03EEp641F* + ID_MODEL_FROM_DATABASE=WIF-0402C Bluetooth Adapter + +usb:v03EEp6438* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v03EEp6440* + ID_MODEL_FROM_DATABASE=WML-C52APR Bluetooth Adapter + +usb:v03EEp6901* + ID_MODEL_FROM_DATABASE=SmartDisk FDD + +usb:v03EEp6902* + ID_MODEL_FROM_DATABASE=Floppy Disk Drive + +usb:v03EEp7500* + ID_MODEL_FROM_DATABASE=CD-R/RW + +usb:v03EEpFFFF* + ID_MODEL_FROM_DATABASE=Dongle with BlueCore in DFU mode + +usb:v03F0* + ID_VENDOR_FROM_DATABASE=HP, Inc + +usb:v03F0p0004* + ID_MODEL_FROM_DATABASE=DeskJet 895c + +usb:v03F0p0011* + ID_MODEL_FROM_DATABASE=OfficeJet G55 + +usb:v03F0p0012* + ID_MODEL_FROM_DATABASE=DeskJet 1125C Printer Port + +usb:v03F0p0024* + ID_MODEL_FROM_DATABASE=KU-0316 Keyboard + +usb:v03F0p002A* + ID_MODEL_FROM_DATABASE=LaserJet P1102 + +usb:v03F0p0053* + ID_MODEL_FROM_DATABASE=DeskJet 2620 All-in-One Printer + +usb:v03F0p0101* + ID_MODEL_FROM_DATABASE=ScanJet 4100c + +usb:v03F0p0102* + ID_MODEL_FROM_DATABASE=PhotoSmart S20 + +usb:v03F0p0104* + ID_MODEL_FROM_DATABASE=DeskJet 880c/970c + +usb:v03F0p0105* + ID_MODEL_FROM_DATABASE=ScanJet 4200c + +usb:v03F0p0107* + ID_MODEL_FROM_DATABASE=CD-Writer Plus + +usb:v03F0p010C* + ID_MODEL_FROM_DATABASE=Multimedia Keyboard Hub + +usb:v03F0p0111* + ID_MODEL_FROM_DATABASE=G55xi Printer/Scanner/Copier + +usb:v03F0p0117* + ID_MODEL_FROM_DATABASE=LaserJet 3200 + +usb:v03F0p011C* + ID_MODEL_FROM_DATABASE=hn210w 802.11b Adapter + +usb:v03F0p011D* + ID_MODEL_FROM_DATABASE=Bluetooth 1.2 Interface [Broadcom BCM2035] + +usb:v03F0p0121* + ID_MODEL_FROM_DATABASE=HP 39g+ [F2224A], 39gs [F2223A], 40gs [F2225A], 48gII [F2226A], 49g+ [F2228A], 50g [F2229A, NW240AA] + +usb:v03F0p0122* + ID_MODEL_FROM_DATABASE=HID Internet Keyboard + +usb:v03F0p0125* + ID_MODEL_FROM_DATABASE=DAT72 Tape + +usb:v03F0p0139* + ID_MODEL_FROM_DATABASE=Barcode Scanner 4430 + +usb:v03F0p0201* + ID_MODEL_FROM_DATABASE=ScanJet 6200c + +usb:v03F0p0202* + ID_MODEL_FROM_DATABASE=PhotoSmart S20 + +usb:v03F0p0204* + ID_MODEL_FROM_DATABASE=DeskJet 815c + +usb:v03F0p0205* + ID_MODEL_FROM_DATABASE=ScanJet 3300c + +usb:v03F0p0207* + ID_MODEL_FROM_DATABASE=CD-Writer Plus 8200e + +usb:v03F0p020C* + ID_MODEL_FROM_DATABASE=Multimedia Keyboard + +usb:v03F0p0211* + ID_MODEL_FROM_DATABASE=OfficeJet G85 + +usb:v03F0p0212* + ID_MODEL_FROM_DATABASE=DeskJet 1220C + +usb:v03F0p0217* + ID_MODEL_FROM_DATABASE=LaserJet 2200 + +usb:v03F0p0218* + ID_MODEL_FROM_DATABASE=APOLLO P2500/2600 + +usb:v03F0p0221* + ID_MODEL_FROM_DATABASE=StreamSmart 400 [F2235AA] + +usb:v03F0p0223* + ID_MODEL_FROM_DATABASE=Digital Drive Flash Reader + +usb:v03F0p022A* + ID_MODEL_FROM_DATABASE=Laserjet CP1525nw + +usb:v03F0p0241* + ID_MODEL_FROM_DATABASE=Link-5 micro dongle + +usb:v03F0p0304* + ID_MODEL_FROM_DATABASE=DeskJet 810c/812c + +usb:v03F0p0305* + ID_MODEL_FROM_DATABASE=ScanJet 4300c + +usb:v03F0p0307* + ID_MODEL_FROM_DATABASE=CD-Writer+ CD-4e + +usb:v03F0p0311* + ID_MODEL_FROM_DATABASE=OfficeJet G85xi + +usb:v03F0p0312* + ID_MODEL_FROM_DATABASE=Color Inkjet CP1700 + +usb:v03F0p0314* + ID_MODEL_FROM_DATABASE=designjet 30/130 series + +usb:v03F0p0317* + ID_MODEL_FROM_DATABASE=LaserJet 1200 + +usb:v03F0p0324* + ID_MODEL_FROM_DATABASE=SK-2885 keyboard + +usb:v03F0p034A* + ID_MODEL_FROM_DATABASE=Elite Keyboard + +usb:v03F0p0401* + ID_MODEL_FROM_DATABASE=ScanJet 5200c + +usb:v03F0p0404* + ID_MODEL_FROM_DATABASE=DeskJet 830c/832c + +usb:v03F0p0405* + ID_MODEL_FROM_DATABASE=ScanJet 3400cse + +usb:v03F0p0411* + ID_MODEL_FROM_DATABASE=OfficeJet G95 + +usb:v03F0p0412* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p0417* + ID_MODEL_FROM_DATABASE=LaserJet 1200 series + +usb:v03F0p0423* + ID_MODEL_FROM_DATABASE=HS-COMBO Cardreader + +usb:v03F0p042A* + ID_MODEL_FROM_DATABASE=LaserJet M1132 MFP + +usb:v03F0p0441* + ID_MODEL_FROM_DATABASE=Prime [NW280AA, G8X92AA] + +usb:v03F0p0504* + ID_MODEL_FROM_DATABASE=DeskJet 885c + +usb:v03F0p0505* + ID_MODEL_FROM_DATABASE=ScanJet 2100c + +usb:v03F0p0507* + ID_MODEL_FROM_DATABASE=DVD+RW + +usb:v03F0p050C* + ID_MODEL_FROM_DATABASE=5219 Wireless Keyboard + +usb:v03F0p0511* + ID_MODEL_FROM_DATABASE=OfficeJet K60 + +usb:v03F0p0512* + ID_MODEL_FROM_DATABASE=DeckJet 450 + +usb:v03F0p0517* + ID_MODEL_FROM_DATABASE=LaserJet 1000 + +usb:v03F0p051D* + ID_MODEL_FROM_DATABASE=Bluetooth Interface + +usb:v03F0p052A* + ID_MODEL_FROM_DATABASE=LaserJet M1212nf MFP + +usb:v03F0p0601* + ID_MODEL_FROM_DATABASE=ScanJet 6300c + +usb:v03F0p0604* + ID_MODEL_FROM_DATABASE=DeskJet 840c + +usb:v03F0p0605* + ID_MODEL_FROM_DATABASE=ScanJet 2200c + +usb:v03F0p0610* + ID_MODEL_FROM_DATABASE=Z24i Monitor Hub + +usb:v03F0p0611* + ID_MODEL_FROM_DATABASE=OfficeJet K60xi + +usb:v03F0p0612* + ID_MODEL_FROM_DATABASE=business inkjet 3000 + +usb:v03F0p0624* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v03F0p0641* + ID_MODEL_FROM_DATABASE=X1200 Optical Mouse + +usb:v03F0p0701* + ID_MODEL_FROM_DATABASE=ScanJet 5300c/5370c + +usb:v03F0p0704* + ID_MODEL_FROM_DATABASE=DeskJet 825c + +usb:v03F0p0705* + ID_MODEL_FROM_DATABASE=ScanJet 4400c + +usb:v03F0p070C* + ID_MODEL_FROM_DATABASE=Personal Media Drive + +usb:v03F0p0711* + ID_MODEL_FROM_DATABASE=OfficeJet K80 + +usb:v03F0p0712* + ID_MODEL_FROM_DATABASE=DeskJet 1180c + +usb:v03F0p0714* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p0741* + ID_MODEL_FROM_DATABASE=Prime Wireless Kit [FOK65AA] + +usb:v03F0p0801* + ID_MODEL_FROM_DATABASE=ScanJet 7400c + +usb:v03F0p0804* + ID_MODEL_FROM_DATABASE=DeskJet 816c + +usb:v03F0p0805* + ID_MODEL_FROM_DATABASE=HP4470C + +usb:v03F0p0811* + ID_MODEL_FROM_DATABASE=OfficeJet K80xi + +usb:v03F0p0817* + ID_MODEL_FROM_DATABASE=LaserJet 3300 + +usb:v03F0p0901* + ID_MODEL_FROM_DATABASE=ScanJet 2300c + +usb:v03F0p0904* + ID_MODEL_FROM_DATABASE=DeskJet 845c + +usb:v03F0p0912* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p0917* + ID_MODEL_FROM_DATABASE=LaserJet 3330 + +usb:v03F0p0924* + ID_MODEL_FROM_DATABASE=Modular Smartcard Keyboard + +usb:v03F0p0941* + ID_MODEL_FROM_DATABASE=X500 Optical Mouse + +usb:v03F0p094A* + ID_MODEL_FROM_DATABASE=Optical Mouse [672662-001] + +usb:v03F0p0A01* + ID_MODEL_FROM_DATABASE=ScanJet 2400c + +usb:v03F0p0A17* + ID_MODEL_FROM_DATABASE=color LaserJet 3700 + +usb:v03F0p0B01* + ID_MODEL_FROM_DATABASE=ScanJet 82x0C + +usb:v03F0p0B0C* + ID_MODEL_FROM_DATABASE=Wireless Keyboard and Optical Mouse receiver + +usb:v03F0p0B17* + ID_MODEL_FROM_DATABASE=LaserJet 2300d + +usb:v03F0p0C17* + ID_MODEL_FROM_DATABASE=LaserJet 1010 + +usb:v03F0p0C24* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v03F0p0D12* + ID_MODEL_FROM_DATABASE=OfficeJet 9100 series + +usb:v03F0p0D17* + ID_MODEL_FROM_DATABASE=LaserJet 1012 + +usb:v03F0p0D4A* + ID_MODEL_FROM_DATABASE=SK-2025 Keyboard + +usb:v03F0p0E17* + ID_MODEL_FROM_DATABASE=LaserJet 1015 + +usb:v03F0p0F0C* + ID_MODEL_FROM_DATABASE=Wireless Keyboard and Optical Mouse receiver + +usb:v03F0p0F11* + ID_MODEL_FROM_DATABASE=OfficeJet V40 + +usb:v03F0p0F12* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p0F17* + ID_MODEL_FROM_DATABASE=LaserJet 1150 + +usb:v03F0p0F2A* + ID_MODEL_FROM_DATABASE=LaserJet 400 color M451dn + +usb:v03F0p1001* + ID_MODEL_FROM_DATABASE=Photo Scanner 1000 + +usb:v03F0p1002* + ID_MODEL_FROM_DATABASE=PhotoSmart 140 series + +usb:v03F0p1004* + ID_MODEL_FROM_DATABASE=DeskJet 970c/970cse + +usb:v03F0p1005* + ID_MODEL_FROM_DATABASE=ScanJet 5400c + +usb:v03F0p1011* + ID_MODEL_FROM_DATABASE=OfficeJet V40xi + +usb:v03F0p1016* + ID_MODEL_FROM_DATABASE=Jornada 548 / iPAQ HW6515 Pocket PC + +usb:v03F0p1017* + ID_MODEL_FROM_DATABASE=LaserJet 1300 + +usb:v03F0p1024* + ID_MODEL_FROM_DATABASE=Smart Card Keyboard + +usb:v03F0p1027* + ID_MODEL_FROM_DATABASE=Virtual keyboard and mouse + +usb:v03F0p102A* + ID_MODEL_FROM_DATABASE=LaserJet Professional P 1102w + +usb:v03F0p1102* + ID_MODEL_FROM_DATABASE=PhotoSmart 240 series + +usb:v03F0p1104* + ID_MODEL_FROM_DATABASE=DeskJet 959c + +usb:v03F0p1105* + ID_MODEL_FROM_DATABASE=ScanJet 5470c/5490c + +usb:v03F0p1111* + ID_MODEL_FROM_DATABASE=OfficeJet v60 + +usb:v03F0p1116* + ID_MODEL_FROM_DATABASE=Jornada 568 Pocket PC + +usb:v03F0p1117* + ID_MODEL_FROM_DATABASE=LaserJet 1300n + +usb:v03F0p1151* + ID_MODEL_FROM_DATABASE=PSC-750xi Printer/Scanner/Copier + +usb:v03F0p1198* + ID_MODEL_FROM_DATABASE=HID-compliant mouse + +usb:v03F0p1202* + ID_MODEL_FROM_DATABASE=PhotoSmart 320 series + +usb:v03F0p1204* + ID_MODEL_FROM_DATABASE=DeskJet 930c + +usb:v03F0p1205* + ID_MODEL_FROM_DATABASE=ScanJet 4500C/5550C + +usb:v03F0p1211* + ID_MODEL_FROM_DATABASE=OfficeJet v60xi + +usb:v03F0p1217* + ID_MODEL_FROM_DATABASE=LaserJet 2300L + +usb:v03F0p1227* + ID_MODEL_FROM_DATABASE=Virtual CD-ROM + +usb:v03F0p1302* + ID_MODEL_FROM_DATABASE=PhotoSmart 370 series + +usb:v03F0p1305* + ID_MODEL_FROM_DATABASE=ScanJet 4570c + +usb:v03F0p1311* + ID_MODEL_FROM_DATABASE=OfficeJet V30 + +usb:v03F0p1312* + ID_MODEL_FROM_DATABASE=DeskJet 460 + +usb:v03F0p1317* + ID_MODEL_FROM_DATABASE=LaserJet 1005 + +usb:v03F0p1327* + ID_MODEL_FROM_DATABASE=iLO Virtual Hub + +usb:v03F0p134A* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v03F0p1405* + ID_MODEL_FROM_DATABASE=ScanJet 3670 + +usb:v03F0p1411* + ID_MODEL_FROM_DATABASE=PSC 750 + +usb:v03F0p1424* + ID_MODEL_FROM_DATABASE=f2105 Monitor Hub + +usb:v03F0p1502* + ID_MODEL_FROM_DATABASE=PhotoSmart 420 series + +usb:v03F0p1504* + ID_MODEL_FROM_DATABASE=DeskJet 920c + +usb:v03F0p150C* + ID_MODEL_FROM_DATABASE=Mood Lighting (Microchip Technology Inc.) + +usb:v03F0p1511* + ID_MODEL_FROM_DATABASE=PSC 750xi + +usb:v03F0p1512* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p1517* + ID_MODEL_FROM_DATABASE=color LaserJet 3500 + +usb:v03F0p1524* + ID_MODEL_FROM_DATABASE=Smart Card Keyboard - KR + +usb:v03F0p1539* + ID_MODEL_FROM_DATABASE=Mini Magnetic Stripe Reader + +usb:v03F0p1541* + ID_MODEL_FROM_DATABASE=Prime [G8X92AA] + +usb:v03F0p154A* + ID_MODEL_FROM_DATABASE=Laser Mouse + +usb:v03F0p1602* + ID_MODEL_FROM_DATABASE=PhotoSmart 330 series + +usb:v03F0p1604* + ID_MODEL_FROM_DATABASE=DeskJet 940c + +usb:v03F0p1605* + ID_MODEL_FROM_DATABASE=ScanJet 5530C PhotoSmart + +usb:v03F0p1611* + ID_MODEL_FROM_DATABASE=psc 780 + +usb:v03F0p1617* + ID_MODEL_FROM_DATABASE=LaserJet 3015 + +usb:v03F0p161D* + ID_MODEL_FROM_DATABASE=Wireless Rechargeable Optical Mouse (HID) + +usb:v03F0p1624* + ID_MODEL_FROM_DATABASE=Smart Card Keyboard - JP + +usb:v03F0p1702* + ID_MODEL_FROM_DATABASE=PhotoSmart 380 series + +usb:v03F0p1704* + ID_MODEL_FROM_DATABASE=DeskJet 948C + +usb:v03F0p1705* + ID_MODEL_FROM_DATABASE=ScanJet 5590 + +usb:v03F0p1711* + ID_MODEL_FROM_DATABASE=psc 780xi + +usb:v03F0p1712* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p1717* + ID_MODEL_FROM_DATABASE=LaserJet 3020 + +usb:v03F0p171D* + ID_MODEL_FROM_DATABASE=Bluetooth 2.0 Interface [Broadcom BCM2045] + +usb:v03F0p1801* + ID_MODEL_FROM_DATABASE=Inkjet P-2000U + +usb:v03F0p1802* + ID_MODEL_FROM_DATABASE=PhotoSmart 470 series + +usb:v03F0p1804* + ID_MODEL_FROM_DATABASE=DeskJet 916C + +usb:v03F0p1805* + ID_MODEL_FROM_DATABASE=ScanJet 7650 + +usb:v03F0p1811* + ID_MODEL_FROM_DATABASE=PSC 720 + +usb:v03F0p1812* + ID_MODEL_FROM_DATABASE=OfficeJet Pro K550 + +usb:v03F0p1817* + ID_MODEL_FROM_DATABASE=LaserJet 3030 + +usb:v03F0p181D* + ID_MODEL_FROM_DATABASE=Bluetooth 2.0 Interface + +usb:v03F0p1902* + ID_MODEL_FROM_DATABASE=PhotoSmart A430 series + +usb:v03F0p1904* + ID_MODEL_FROM_DATABASE=DeskJet 3820 + +usb:v03F0p1911* + ID_MODEL_FROM_DATABASE=OfficeJet V45 + +usb:v03F0p1917* + ID_MODEL_FROM_DATABASE=LaserJet 3380 + +usb:v03F0p1A02* + ID_MODEL_FROM_DATABASE=PhotoSmart A510 series + +usb:v03F0p1A11* + ID_MODEL_FROM_DATABASE=OfficeJet 5100 series + +usb:v03F0p1A17* + ID_MODEL_FROM_DATABASE=color LaserJet 4650 + +usb:v03F0p1B02* + ID_MODEL_FROM_DATABASE=PhotoSmart A610 series + +usb:v03F0p1B04* + ID_MODEL_FROM_DATABASE=DeskJet 3810 + +usb:v03F0p1B05* + ID_MODEL_FROM_DATABASE=ScanJet 4850C/4890C + +usb:v03F0p1B07* + ID_MODEL_FROM_DATABASE=Premium Starter Webcam + +usb:v03F0p1C02* + ID_MODEL_FROM_DATABASE=PhotoSmart A710 series + +usb:v03F0p1C17* + ID_MODEL_FROM_DATABASE=Color LaserJet 2550l + +usb:v03F0p1D02* + ID_MODEL_FROM_DATABASE=PhotoSmart A310 series + +usb:v03F0p1D17* + ID_MODEL_FROM_DATABASE=LaserJet 1320 + +usb:v03F0p1D24* + ID_MODEL_FROM_DATABASE=Barcode scanner + +usb:v03F0p1E02* + ID_MODEL_FROM_DATABASE=PhotoSmart A320 Printer series + +usb:v03F0p1E11* + ID_MODEL_FROM_DATABASE=PSC-950 + +usb:v03F0p1E17* + ID_MODEL_FROM_DATABASE=LaserJet 1160 series + +usb:v03F0p1F02* + ID_MODEL_FROM_DATABASE=PhotoSmart A440 Printer series + +usb:v03F0p1F11* + ID_MODEL_FROM_DATABASE=PSC 920 + +usb:v03F0p1F12* + ID_MODEL_FROM_DATABASE=OfficeJet Pro K5300 + +usb:v03F0p1F17* + ID_MODEL_FROM_DATABASE=color LaserJet 5550 + +usb:v03F0p1F1D* + ID_MODEL_FROM_DATABASE=un2400 Gobi Wireless Modem + +usb:v03F0p2001* + ID_MODEL_FROM_DATABASE=Floppy + +usb:v03F0p2002* + ID_MODEL_FROM_DATABASE=Hub + +usb:v03F0p2004* + ID_MODEL_FROM_DATABASE=DeskJet 640c + +usb:v03F0p2005* + ID_MODEL_FROM_DATABASE=ScanJet 3570c + +usb:v03F0p2012* + ID_MODEL_FROM_DATABASE=OfficeJet Pro K5400 + +usb:v03F0p201D* + ID_MODEL_FROM_DATABASE=un2400 Gobi Wireless Modem (QDL mode) + +usb:v03F0p2039* + ID_MODEL_FROM_DATABASE=Cashdrawer + +usb:v03F0p2102* + ID_MODEL_FROM_DATABASE=PhotoSmart 7345 + +usb:v03F0p2104* + ID_MODEL_FROM_DATABASE=DeskJet 630c + +usb:v03F0p2112* + ID_MODEL_FROM_DATABASE=OfficeJet Pro L7500 + +usb:v03F0p211D* + ID_MODEL_FROM_DATABASE=Sierra MC5725 [ev2210] + +usb:v03F0p2202* + ID_MODEL_FROM_DATABASE=PhotoSmart 7600 series + +usb:v03F0p2205* + ID_MODEL_FROM_DATABASE=ScanJet 3500c + +usb:v03F0p2212* + ID_MODEL_FROM_DATABASE=OfficeJet Pro L7600 + +usb:v03F0p2217* + ID_MODEL_FROM_DATABASE=color LaserJet 9500 MFP + +usb:v03F0p222A* + ID_MODEL_FROM_DATABASE=LaserJet Pro MFP M125nw + +usb:v03F0p2302* + ID_MODEL_FROM_DATABASE=PhotoSmart 7600 series + +usb:v03F0p2304* + ID_MODEL_FROM_DATABASE=DeskJet 656c + +usb:v03F0p2305* + ID_MODEL_FROM_DATABASE=ScanJet 3970c + +usb:v03F0p2311* + ID_MODEL_FROM_DATABASE=OfficeJet d series + +usb:v03F0p2312* + ID_MODEL_FROM_DATABASE=OfficeJet Pro L7700 + +usb:v03F0p2317* + ID_MODEL_FROM_DATABASE=LaserJet 4350 + +usb:v03F0p231D* + ID_MODEL_FROM_DATABASE=Broadcom 2070 Bluetooth Combo + +usb:v03F0p2402* + ID_MODEL_FROM_DATABASE=PhotoSmart 7700 series + +usb:v03F0p2404* + ID_MODEL_FROM_DATABASE=Deskjet F2280 series + +usb:v03F0p2405* + ID_MODEL_FROM_DATABASE=ScanJet 4070 PhotoSmart + +usb:v03F0p2417* + ID_MODEL_FROM_DATABASE=LaserJet 4250 + +usb:v03F0p241D* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem (QDL mode) + +usb:v03F0p2424* + ID_MODEL_FROM_DATABASE=LP1965 19" Monitor Hub + +usb:v03F0p2502* + ID_MODEL_FROM_DATABASE=PhotoSmart 7700 series + +usb:v03F0p2504* + ID_MODEL_FROM_DATABASE=DeskJet F4200 series + +usb:v03F0p2505* + ID_MODEL_FROM_DATABASE=ScanJet 3770 + +usb:v03F0p2512* + ID_MODEL_FROM_DATABASE=OfficeJet Pro L7300 / Compaq LA2405 series monitor + +usb:v03F0p2514* + ID_MODEL_FROM_DATABASE=4-port hub + +usb:v03F0p2517* + ID_MODEL_FROM_DATABASE=LaserJet 2410 + +usb:v03F0p251D* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v03F0p2524* + ID_MODEL_FROM_DATABASE=LP3065 30" Monitor Hub + +usb:v03F0p2602* + ID_MODEL_FROM_DATABASE=PhotoSmart A520 series + +usb:v03F0p2605* + ID_MODEL_FROM_DATABASE=ScanJet 3800c + +usb:v03F0p2611* + ID_MODEL_FROM_DATABASE=OfficeJet 7100 series + +usb:v03F0p2617* + ID_MODEL_FROM_DATABASE=Color LaserJet 2820 series + +usb:v03F0p2624* + ID_MODEL_FROM_DATABASE=Pole Display (HP522 2 x 20 Line Display) + +usb:v03F0p2702* + ID_MODEL_FROM_DATABASE=PhotoSmart A620 series + +usb:v03F0p2704* + ID_MODEL_FROM_DATABASE=DeskJet 915 + +usb:v03F0p2717* + ID_MODEL_FROM_DATABASE=Color LaserJet 2830 + +usb:v03F0p2724* + ID_MODEL_FROM_DATABASE=Magnetic Stripe Reader IDRA-334133-HP + +usb:v03F0p2805* + ID_MODEL_FROM_DATABASE=Scanjet G2710 + +usb:v03F0p2811* + ID_MODEL_FROM_DATABASE=PSC-2100 + +usb:v03F0p2817* + ID_MODEL_FROM_DATABASE=Color LaserJet 2840 + +usb:v03F0p2902* + ID_MODEL_FROM_DATABASE=PhotoSmart A820 series + +usb:v03F0p2911* + ID_MODEL_FROM_DATABASE=PSC 2200 + +usb:v03F0p2917* + ID_MODEL_FROM_DATABASE=LaserJet 2420 + +usb:v03F0p2A11* + ID_MODEL_FROM_DATABASE=PSC 2150 series + +usb:v03F0p2A17* + ID_MODEL_FROM_DATABASE=LaserJet 2430 + +usb:v03F0p2A1D* + ID_MODEL_FROM_DATABASE=Integrated Module with Bluetooth 2.1 Wireless technology + +usb:v03F0p2B11* + ID_MODEL_FROM_DATABASE=PSC 2170 series + +usb:v03F0p2B17* + ID_MODEL_FROM_DATABASE=LaserJet 1020 + +usb:v03F0p2B4A* + ID_MODEL_FROM_DATABASE=Business Slim Keyboard + +usb:v03F0p2C12* + ID_MODEL_FROM_DATABASE=Officejet J4680 + +usb:v03F0p2C17* + ID_MODEL_FROM_DATABASE=LaserJet 1022 + +usb:v03F0p2C24* + ID_MODEL_FROM_DATABASE=Logitech M-UAL-96 Mouse + +usb:v03F0p2D05* + ID_MODEL_FROM_DATABASE=Scanjet 7000 + +usb:v03F0p2D11* + ID_MODEL_FROM_DATABASE=OfficeJet 6110 + +usb:v03F0p2D17* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p2E11* + ID_MODEL_FROM_DATABASE=PSC 1000 + +usb:v03F0p2E17* + ID_MODEL_FROM_DATABASE=LaserJet 2600n + +usb:v03F0p2E24* + ID_MODEL_FROM_DATABASE=LP2275w Monitor Hub + +usb:v03F0p2F11* + ID_MODEL_FROM_DATABASE=PSC 1200 + +usb:v03F0p2F17* + ID_MODEL_FROM_DATABASE=Color LaserJet 2605dn + +usb:v03F0p2F24* + ID_MODEL_FROM_DATABASE=LP2475w Monitor Hub + +usb:v03F0p3002* + ID_MODEL_FROM_DATABASE=PhotoSmart P1000 + +usb:v03F0p3004* + ID_MODEL_FROM_DATABASE=DeskJet 980c + +usb:v03F0p3005* + ID_MODEL_FROM_DATABASE=ScanJet 4670v + +usb:v03F0p3011* + ID_MODEL_FROM_DATABASE=PSC 1100 series + +usb:v03F0p3017* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p304A* + ID_MODEL_FROM_DATABASE=Slim Keyboard + +usb:v03F0p3102* + ID_MODEL_FROM_DATABASE=PhotoSmart P1100 Printer w/ Card Reader + +usb:v03F0p3104* + ID_MODEL_FROM_DATABASE=DeskJet 960c + +usb:v03F0p3111* + ID_MODEL_FROM_DATABASE=OfficeJet 4100 series + +usb:v03F0p3117* + ID_MODEL_FROM_DATABASE=EWS 2605dtn + +usb:v03F0p311D* + ID_MODEL_FROM_DATABASE=Atheros AR9285 Malbec Bluetooth Adapter + +usb:v03F0p3202* + ID_MODEL_FROM_DATABASE=PhotoSmart 1215 + +usb:v03F0p3207* + ID_MODEL_FROM_DATABASE=4 GB flash drive + +usb:v03F0p3211* + ID_MODEL_FROM_DATABASE=OfficeJet 4105 series + +usb:v03F0p3217* + ID_MODEL_FROM_DATABASE=LaserJet 3050 + +usb:v03F0p3302* + ID_MODEL_FROM_DATABASE=PhotoSmart 1218 + +usb:v03F0p3304* + ID_MODEL_FROM_DATABASE=DeskJet 990c + +usb:v03F0p3307* + ID_MODEL_FROM_DATABASE=v125w Stick + +usb:v03F0p3312* + ID_MODEL_FROM_DATABASE=OfficeJet J6410 + +usb:v03F0p3317* + ID_MODEL_FROM_DATABASE=LaserJet 3052 + +usb:v03F0p3402* + ID_MODEL_FROM_DATABASE=PhotoSmart 1115 + +usb:v03F0p3404* + ID_MODEL_FROM_DATABASE=DeskJet 6122 + +usb:v03F0p3417* + ID_MODEL_FROM_DATABASE=LaserJet 3055 + +usb:v03F0p3502* + ID_MODEL_FROM_DATABASE=PhotoSmart 230 + +usb:v03F0p3504* + ID_MODEL_FROM_DATABASE=DeskJet 6127c + +usb:v03F0p3511* + ID_MODEL_FROM_DATABASE=PSC 2300 + +usb:v03F0p3517* + ID_MODEL_FROM_DATABASE=LaserJet 3390 + +usb:v03F0p3602* + ID_MODEL_FROM_DATABASE=PhotoSmart 1315 + +usb:v03F0p3611* + ID_MODEL_FROM_DATABASE=PSC 2410 PhotoSmart + +usb:v03F0p3612* + ID_MODEL_FROM_DATABASE=Officejet Pro 8000 A809 + +usb:v03F0p3617* + ID_MODEL_FROM_DATABASE=Color LaserJet 2605 + +usb:v03F0p3711* + ID_MODEL_FROM_DATABASE=PSC 2500 + +usb:v03F0p3717* + ID_MODEL_FROM_DATABASE=EWS UPD + +usb:v03F0p3724* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v03F0p3802* + ID_MODEL_FROM_DATABASE=PhotoSmart 100 + +usb:v03F0p3807* + ID_MODEL_FROM_DATABASE=c485w Flash Drive + +usb:v03F0p3817* + ID_MODEL_FROM_DATABASE=LaserJet P2015 series + +usb:v03F0p3902* + ID_MODEL_FROM_DATABASE=PhotoSmart 130 + +usb:v03F0p3912* + ID_MODEL_FROM_DATABASE=Officejet Pro 8500 + +usb:v03F0p3917* + ID_MODEL_FROM_DATABASE=LaserJet P2014 + +usb:v03F0p3A02* + ID_MODEL_FROM_DATABASE=PhotoSmart 7150 + +usb:v03F0p3A11* + ID_MODEL_FROM_DATABASE=OfficeJet 5500 series + +usb:v03F0p3A17* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p3A1D* + ID_MODEL_FROM_DATABASE=hs2340 HSPA+ mobile broadband + +usb:v03F0p3B02* + ID_MODEL_FROM_DATABASE=PhotoSmart 7150~ + +usb:v03F0p3B05* + ID_MODEL_FROM_DATABASE=Scanjet N8460 + +usb:v03F0p3B11* + ID_MODEL_FROM_DATABASE=PSC 1300 series + +usb:v03F0p3B17* + ID_MODEL_FROM_DATABASE=LaserJet M1005 MFP + +usb:v03F0p3B2A* + ID_MODEL_FROM_DATABASE=Color LaserJet MFP M277dw + +usb:v03F0p3C02* + ID_MODEL_FROM_DATABASE=PhotoSmart 7350 + +usb:v03F0p3C05* + ID_MODEL_FROM_DATABASE=Scanjet Professional 1000 Mobile Scanner + +usb:v03F0p3C11* + ID_MODEL_FROM_DATABASE=PSC 1358 + +usb:v03F0p3C17* + ID_MODEL_FROM_DATABASE=EWS UPD + +usb:v03F0p3D02* + ID_MODEL_FROM_DATABASE=PhotoSmart 7350~ + +usb:v03F0p3D11* + ID_MODEL_FROM_DATABASE=OfficeJet 4215 + +usb:v03F0p3D17* + ID_MODEL_FROM_DATABASE=LaserJet P1005 + +usb:v03F0p3E02* + ID_MODEL_FROM_DATABASE=PhotoSmart 7550 + +usb:v03F0p3E17* + ID_MODEL_FROM_DATABASE=LaserJet P1006 + +usb:v03F0p3F02* + ID_MODEL_FROM_DATABASE=PhotoSmart 7550~ + +usb:v03F0p3F11* + ID_MODEL_FROM_DATABASE=PSC-1315/PSC-1317 + +usb:v03F0p4002* + ID_MODEL_FROM_DATABASE=PhotoSmart 635/715/720/735/935/E337 (storage) + +usb:v03F0p4004* + ID_MODEL_FROM_DATABASE=CP1160 + +usb:v03F0p4102* + ID_MODEL_FROM_DATABASE=PhotoSmart 618 + +usb:v03F0p4105* + ID_MODEL_FROM_DATABASE=ScanJet 4370 + +usb:v03F0p4111* + ID_MODEL_FROM_DATABASE=OfficeJet 7200 series + +usb:v03F0p4117* + ID_MODEL_FROM_DATABASE=LaserJet 1018 + +usb:v03F0p4202* + ID_MODEL_FROM_DATABASE=PhotoSmart 812 + +usb:v03F0p4205* + ID_MODEL_FROM_DATABASE=ScanJet G3010 + +usb:v03F0p4211* + ID_MODEL_FROM_DATABASE=OfficeJet 7300 series + +usb:v03F0p4217* + ID_MODEL_FROM_DATABASE=EWS CM1015 + +usb:v03F0p4302* + ID_MODEL_FROM_DATABASE=PhotoSmart 850 (ptp) + +usb:v03F0p4305* + ID_MODEL_FROM_DATABASE=ScanJet G3110 + +usb:v03F0p4311* + ID_MODEL_FROM_DATABASE=OfficeJet 7400 series + +usb:v03F0p4317* + ID_MODEL_FROM_DATABASE=Color LaserJet CM1017 + +usb:v03F0p4402* + ID_MODEL_FROM_DATABASE=PhotoSmart 935 (ptp) + +usb:v03F0p4417* + ID_MODEL_FROM_DATABASE=EWS UPD + +usb:v03F0p4502* + ID_MODEL_FROM_DATABASE=PhotoSmart 945 (PTP mode) + +usb:v03F0p4505* + ID_MODEL_FROM_DATABASE=ScanJet G4010 + +usb:v03F0p4507* + ID_MODEL_FROM_DATABASE=External HDD + +usb:v03F0p4511* + ID_MODEL_FROM_DATABASE=PhotoSmart 2600 + +usb:v03F0p4512* + ID_MODEL_FROM_DATABASE=E709n [Officejet 6500 Wireless] + +usb:v03F0p4517* + ID_MODEL_FROM_DATABASE=EWS UPD + +usb:v03F0p4605* + ID_MODEL_FROM_DATABASE=ScanJet G4050 + +usb:v03F0p4611* + ID_MODEL_FROM_DATABASE=PhotoSmart 2700 + +usb:v03F0p4717* + ID_MODEL_FROM_DATABASE=Color LaserJet CP1215 + +usb:v03F0p4811* + ID_MODEL_FROM_DATABASE=PSC 1600 + +usb:v03F0p4911* + ID_MODEL_FROM_DATABASE=PSC 2350 + +usb:v03F0p4B11* + ID_MODEL_FROM_DATABASE=OfficeJet 6200 + +usb:v03F0p4C11* + ID_MODEL_FROM_DATABASE=PSC 1500 series + +usb:v03F0p4C17* + ID_MODEL_FROM_DATABASE=EWS UPD + +usb:v03F0p4D11* + ID_MODEL_FROM_DATABASE=PSC 1400 + +usb:v03F0p4D17* + ID_MODEL_FROM_DATABASE=EWS UPD + +usb:v03F0p4E11* + ID_MODEL_FROM_DATABASE=PhotoSmart 2570 series + +usb:v03F0p4F11* + ID_MODEL_FROM_DATABASE=OfficeJet 5600 (USBHUB) + +usb:v03F0p4F17* + ID_MODEL_FROM_DATABASE=Color LaserJet CM1312 MFP + +usb:v03F0p5004* + ID_MODEL_FROM_DATABASE=DeskJet 995c + +usb:v03F0p5011* + ID_MODEL_FROM_DATABASE=PhotoSmart 3100 series + +usb:v03F0p5017* + ID_MODEL_FROM_DATABASE=EWS UPD + +usb:v03F0p5111* + ID_MODEL_FROM_DATABASE=PhotoSmart 3200 series + +usb:v03F0p5211* + ID_MODEL_FROM_DATABASE=PhotoSmart 3300 series + +usb:v03F0p5307* + ID_MODEL_FROM_DATABASE=v165w Stick + +usb:v03F0p5311* + ID_MODEL_FROM_DATABASE=OfficeJet 6300 + +usb:v03F0p5312* + ID_MODEL_FROM_DATABASE=Officejet Pro 8500A + +usb:v03F0p5317* + ID_MODEL_FROM_DATABASE=Color LaserJet CP2025 series + +usb:v03F0p5411* + ID_MODEL_FROM_DATABASE=OfficeJet 4300 + +usb:v03F0p5511* + ID_MODEL_FROM_DATABASE=DeskJet F300 series + +usb:v03F0p5611* + ID_MODEL_FROM_DATABASE=PhotoSmart C3180 + +usb:v03F0p5617* + ID_MODEL_FROM_DATABASE=LaserJet M1120 MFP + +usb:v03F0p5711* + ID_MODEL_FROM_DATABASE=PhotoSmart C4100 series + +usb:v03F0p5717* + ID_MODEL_FROM_DATABASE=LaserJet M1120n MFP + +usb:v03F0p5811* + ID_MODEL_FROM_DATABASE=PhotoSmart C5100 series + +usb:v03F0p5817* + ID_MODEL_FROM_DATABASE=LaserJet M1319f MFP + +usb:v03F0p581D* + ID_MODEL_FROM_DATABASE=lt4112 Gobi 4G Module Network Device + +usb:v03F0p5911* + ID_MODEL_FROM_DATABASE=PhotoSmart C6180 + +usb:v03F0p5912* + ID_MODEL_FROM_DATABASE=Officejet Pro 8600 + +usb:v03F0p5A11* + ID_MODEL_FROM_DATABASE=PhotoSmart C7100 series + +usb:v03F0p5B11* + ID_MODEL_FROM_DATABASE=OfficeJet J2100 series + +usb:v03F0p5B12* + ID_MODEL_FROM_DATABASE=Officejet Pro 8100 + +usb:v03F0p5C11* + ID_MODEL_FROM_DATABASE=PhotoSmart C4200 Printer series + +usb:v03F0p5C12* + ID_MODEL_FROM_DATABASE=OfficeJet 6700 + +usb:v03F0p5C17* + ID_MODEL_FROM_DATABASE=LaserJet P2055 series + +usb:v03F0p5D11* + ID_MODEL_FROM_DATABASE=PhotoSmart C5200 series + +usb:v03F0p5E11* + ID_MODEL_FROM_DATABASE=PhotoSmart D7400 series + +usb:v03F0p6004* + ID_MODEL_FROM_DATABASE=DeskJet 5550 + +usb:v03F0p6102* + ID_MODEL_FROM_DATABASE=Hewlett Packard Digital Camera + +usb:v03F0p6104* + ID_MODEL_FROM_DATABASE=DeskJet 5650c + +usb:v03F0p6117* + ID_MODEL_FROM_DATABASE=color LaserJet 3550 + +usb:v03F0p6202* + ID_MODEL_FROM_DATABASE=PhotoSmart 215 + +usb:v03F0p6204* + ID_MODEL_FROM_DATABASE=DeskJet 5150c + +usb:v03F0p6217* + ID_MODEL_FROM_DATABASE=Color LaserJet 4700 + +usb:v03F0p6302* + ID_MODEL_FROM_DATABASE=PhotoSmart 318/612 + +usb:v03F0p6317* + ID_MODEL_FROM_DATABASE=Color LaserJet 4730mfp + +usb:v03F0p6402* + ID_MODEL_FROM_DATABASE=PhotoSmart 715 (ptp) + +usb:v03F0p6411* + ID_MODEL_FROM_DATABASE=PhotoSmart C8100 series + +usb:v03F0p6417* + ID_MODEL_FROM_DATABASE=LaserJet 5200 + +usb:v03F0p6502* + ID_MODEL_FROM_DATABASE=PhotoSmart 120 (ptp) + +usb:v03F0p6511* + ID_MODEL_FROM_DATABASE=PhotoSmart C7200 series + +usb:v03F0p6602* + ID_MODEL_FROM_DATABASE=PhotoSmart 320 + +usb:v03F0p6611* + ID_MODEL_FROM_DATABASE=PhotoSmart C4380 series + +usb:v03F0p6617* + ID_MODEL_FROM_DATABASE=LaserJet 5200L + +usb:v03F0p6702* + ID_MODEL_FROM_DATABASE=PhotoSmart 720 (ptp) + +usb:v03F0p6717* + ID_MODEL_FROM_DATABASE=Color LaserJet 3000 + +usb:v03F0p6802* + ID_MODEL_FROM_DATABASE=PhotoSmart 620 (ptp) + +usb:v03F0p6811* + ID_MODEL_FROM_DATABASE=PhotoSmart D5300 series + +usb:v03F0p6817* + ID_MODEL_FROM_DATABASE=Color LaserJet 3800 + +usb:v03F0p6911* + ID_MODEL_FROM_DATABASE=PhotoSmart D7200 series + +usb:v03F0p6917* + ID_MODEL_FROM_DATABASE=Color LaserJet 3600 + +usb:v03F0p6A02* + ID_MODEL_FROM_DATABASE=PhotoSmart 735 (ptp) + +usb:v03F0p6A11* + ID_MODEL_FROM_DATABASE=PhotoSmart C6200 series + +usb:v03F0p6A17* + ID_MODEL_FROM_DATABASE=LaserJet 4240 + +usb:v03F0p6B02* + ID_MODEL_FROM_DATABASE=PhotoSmart R707 (PTP mode) + +usb:v03F0p6B11* + ID_MODEL_FROM_DATABASE=Photosmart C4500 series + +usb:v03F0p6C11* + ID_MODEL_FROM_DATABASE=Photosmart C4480 + +usb:v03F0p6C17* + ID_MODEL_FROM_DATABASE=Color LaserJet 4610 + +usb:v03F0p6F17* + ID_MODEL_FROM_DATABASE=Color LaserJet CP6015 series + +usb:v03F0p7004* + ID_MODEL_FROM_DATABASE=DeskJet 3320c + +usb:v03F0p7102* + ID_MODEL_FROM_DATABASE=PhotoSmart 635 (PTP mode) + +usb:v03F0p7104* + ID_MODEL_FROM_DATABASE=DeskJet 3420c + +usb:v03F0p7117* + ID_MODEL_FROM_DATABASE=CM8060 Color MFP with Edgeline Technology + +usb:v03F0p7202* + ID_MODEL_FROM_DATABASE=PhotoSmart 43x (ptp) + +usb:v03F0p7204* + ID_MODEL_FROM_DATABASE=DeskJet 36xx + +usb:v03F0p7217* + ID_MODEL_FROM_DATABASE=LaserJet M5035 MFP + +usb:v03F0p7302* + ID_MODEL_FROM_DATABASE=PhotoSmart M307 (PTP mode) + +usb:v03F0p7304* + ID_MODEL_FROM_DATABASE=DeskJet 35xx + +usb:v03F0p7311* + ID_MODEL_FROM_DATABASE=Photosmart Premium C309 + +usb:v03F0p7317* + ID_MODEL_FROM_DATABASE=LaserJet P3005 + +usb:v03F0p7404* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p7417* + ID_MODEL_FROM_DATABASE=LaserJet M4345 MFP + +usb:v03F0p7504* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p7517* + ID_MODEL_FROM_DATABASE=LaserJet M3035 MFP + +usb:v03F0p7604* + ID_MODEL_FROM_DATABASE=DeskJet 3940 + +usb:v03F0p7611* + ID_MODEL_FROM_DATABASE=DeskJet F2492 All-in-One + +usb:v03F0p7617* + ID_MODEL_FROM_DATABASE=LaserJet P3004 + +usb:v03F0p7702* + ID_MODEL_FROM_DATABASE=PhotoSmart R817 (PTP mode) + +usb:v03F0p7704* + ID_MODEL_FROM_DATABASE=DeskJet D4100 + +usb:v03F0p7717* + ID_MODEL_FROM_DATABASE=CM8050 Color MFP with Edgeline Technology + +usb:v03F0p7804* + ID_MODEL_FROM_DATABASE=DeskJet D1360 + +usb:v03F0p7817* + ID_MODEL_FROM_DATABASE=Color LaserJet CP3505 + +usb:v03F0p7917* + ID_MODEL_FROM_DATABASE=LaserJet M5025 MFP + +usb:v03F0p7A02* + ID_MODEL_FROM_DATABASE=PhotoSmart M415 (PTP mode) + +usb:v03F0p7A04* + ID_MODEL_FROM_DATABASE=DeskJet D2460 + +usb:v03F0p7A17* + ID_MODEL_FROM_DATABASE=LaserJet M3027 MFP + +usb:v03F0p7B02* + ID_MODEL_FROM_DATABASE=PhotoSmart M23 (PTP mode) + +usb:v03F0p7B17* + ID_MODEL_FROM_DATABASE=Color LaserJet CP4005 + +usb:v03F0p7C17* + ID_MODEL_FROM_DATABASE=Color LaserJet CM6040 series + +usb:v03F0p7D04* + ID_MODEL_FROM_DATABASE=DeskJet F2100 Printer series + +usb:v03F0p7D17* + ID_MODEL_FROM_DATABASE=Color LaserJet CM4730 MFP + +usb:v03F0p7E04* + ID_MODEL_FROM_DATABASE=DeskJet F4100 Printer series + +usb:v03F0p8017* + ID_MODEL_FROM_DATABASE=LaserJet P4515 + +usb:v03F0p8104* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p8117* + ID_MODEL_FROM_DATABASE=LaserJet P4015 + +usb:v03F0p811C* + ID_MODEL_FROM_DATABASE=Ethernet HN210E + +usb:v03F0p8204* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v03F0p8207* + ID_MODEL_FROM_DATABASE=FHA-3510 2.4GHz Wireless Optical Mobile Mouse + +usb:v03F0p8217* + ID_MODEL_FROM_DATABASE=LaserJet P4014 + +usb:v03F0p8317* + ID_MODEL_FROM_DATABASE=LaserJet M9050 MFP + +usb:v03F0p8404* + ID_MODEL_FROM_DATABASE=DeskJet 6800 series + +usb:v03F0p8417* + ID_MODEL_FROM_DATABASE=LaserJet M9040 MFP + +usb:v03F0p8504* + ID_MODEL_FROM_DATABASE=DeskJet 6600 series + +usb:v03F0p8604* + ID_MODEL_FROM_DATABASE=DeskJet 5440 + +usb:v03F0p8607* + ID_MODEL_FROM_DATABASE=Optical Mobile Mouse + +usb:v03F0p8704* + ID_MODEL_FROM_DATABASE=DeskJet 5940 + +usb:v03F0p8711* + ID_MODEL_FROM_DATABASE=Deskjet 2050 J510 + +usb:v03F0p8804* + ID_MODEL_FROM_DATABASE=DeskJet 6980 series + +usb:v03F0p8904* + ID_MODEL_FROM_DATABASE=DeskJet 6940 series + +usb:v03F0p8911* + ID_MODEL_FROM_DATABASE=Deskjet 1050 J410 + +usb:v03F0p8C07* + ID_MODEL_FROM_DATABASE=Digital Stereo Headset + +usb:v03F0p8C11* + ID_MODEL_FROM_DATABASE=Deskjet F4500 series + +usb:v03F0p9002* + ID_MODEL_FROM_DATABASE=PhotoSmart M437 + +usb:v03F0p9102* + ID_MODEL_FROM_DATABASE=PhotoSmart M537 + +usb:v03F0p9207* + ID_MODEL_FROM_DATABASE=HD-4110 Webcam + +usb:v03F0p9302* + ID_MODEL_FROM_DATABASE=PhotoSmart R930 series + +usb:v03F0p9402* + ID_MODEL_FROM_DATABASE=PhotoSmart R837 + +usb:v03F0p942A* + ID_MODEL_FROM_DATABASE=LaserJet Pro M12a + +usb:v03F0p9502* + ID_MODEL_FROM_DATABASE=PhotoSmart R840 series + +usb:v03F0p952A* + ID_MODEL_FROM_DATABASE=LaserJet Pro M12w + +usb:v03F0p9602* + ID_MODEL_FROM_DATABASE=PhotoSmart M730 series + +usb:v03F0p9702* + ID_MODEL_FROM_DATABASE=PhotoSmart R740 series + +usb:v03F0p9802* + ID_MODEL_FROM_DATABASE=PhotoSmart Mz60 series + +usb:v03F0p9902* + ID_MODEL_FROM_DATABASE=PhotoSmart M630 series + +usb:v03F0p9A02* + ID_MODEL_FROM_DATABASE=PhotoSmart E330 series + +usb:v03F0p9B02* + ID_MODEL_FROM_DATABASE=PhotoSmart M540 series + +usb:v03F0p9B07* + ID_MODEL_FROM_DATABASE=Portable Drive + +usb:v03F0p9C02* + ID_MODEL_FROM_DATABASE=PhotoSmart M440 series + +usb:v03F0pA004* + ID_MODEL_FROM_DATABASE=DeskJet 5850c + +usb:v03F0pA011* + ID_MODEL_FROM_DATABASE=Deskjet 3050A + +usb:v03F0pA407* + ID_MODEL_FROM_DATABASE=Wireless Optical Comfort Mouse + +usb:v03F0pB002* + ID_MODEL_FROM_DATABASE=PhotoSmart 7200 series + +usb:v03F0pB102* + ID_MODEL_FROM_DATABASE=PhotoSmart 7200 series + +usb:v03F0pB107* + ID_MODEL_FROM_DATABASE=v255w/c310w Flash Drive + +usb:v03F0pB116* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v03F0pB202* + ID_MODEL_FROM_DATABASE=PhotoSmart 7600 series + +usb:v03F0pB302* + ID_MODEL_FROM_DATABASE=PhotoSmart 7600 series + +usb:v03F0pB402* + ID_MODEL_FROM_DATABASE=PhotoSmart 7700 series + +usb:v03F0pB502* + ID_MODEL_FROM_DATABASE=PhotoSmart 7700 series + +usb:v03F0pB602* + ID_MODEL_FROM_DATABASE=PhotoSmart 7900 series + +usb:v03F0pB702* + ID_MODEL_FROM_DATABASE=PhotoSmart 7900 series + +usb:v03F0pB802* + ID_MODEL_FROM_DATABASE=PhotoSmart 7400 series + +usb:v03F0pB902* + ID_MODEL_FROM_DATABASE=PhotoSmart 7800 series + +usb:v03F0pBA02* + ID_MODEL_FROM_DATABASE=PhotoSmart 8100 series + +usb:v03F0pBB02* + ID_MODEL_FROM_DATABASE=PhotoSmart 8400 series + +usb:v03F0pBC02* + ID_MODEL_FROM_DATABASE=PhotoSmart 8700 series + +usb:v03F0pBD02* + ID_MODEL_FROM_DATABASE=PhotoSmart Pro B9100 series + +usb:v03F0pBEF4* + ID_MODEL_FROM_DATABASE=NEC Picty760 + +usb:v03F0pC002* + ID_MODEL_FROM_DATABASE=PhotoSmart 7800 series + +usb:v03F0pC102* + ID_MODEL_FROM_DATABASE=PhotoSmart 8000 series + +usb:v03F0pC111* + ID_MODEL_FROM_DATABASE=Deskjet 1510 + +usb:v03F0pC202* + ID_MODEL_FROM_DATABASE=PhotoSmart 8200 series + +usb:v03F0pC302* + ID_MODEL_FROM_DATABASE=DeskJet D2300 + +usb:v03F0pC402* + ID_MODEL_FROM_DATABASE=PhotoSmart D5100 series + +usb:v03F0pC502* + ID_MODEL_FROM_DATABASE=PhotoSmart D6100 series + +usb:v03F0pC602* + ID_MODEL_FROM_DATABASE=PhotoSmart D7100 series + +usb:v03F0pC702* + ID_MODEL_FROM_DATABASE=PhotoSmart D7300 series + +usb:v03F0pC802* + ID_MODEL_FROM_DATABASE=PhotoSmart D5060 Printer + +usb:v03F0pD104* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v03F0pD507* + ID_MODEL_FROM_DATABASE=39gII [NW249AA] + +usb:v03F0pEFBE* + ID_MODEL_FROM_DATABASE=NEC Picty900 + +usb:v03F0pF0BE* + ID_MODEL_FROM_DATABASE=NEC Picty920 + +usb:v03F0pF1BE* + ID_MODEL_FROM_DATABASE=NEC Picty800 + +usb:v03F1* + ID_VENDOR_FROM_DATABASE=Genoa Technology + +usb:v03F2* + ID_VENDOR_FROM_DATABASE=Oak Technology, Inc. + +usb:v03F3* + ID_VENDOR_FROM_DATABASE=Adaptec, Inc. + +usb:v03F3p0020* + ID_MODEL_FROM_DATABASE=AWN-8020 WLAN [Intersil PRISM 2.5] + +usb:v03F3p0080* + ID_MODEL_FROM_DATABASE=AVC-1100 Audio Capture + +usb:v03F3p0083* + ID_MODEL_FROM_DATABASE=AVC-2200 Device + +usb:v03F3p0087* + ID_MODEL_FROM_DATABASE=AVC-2210 Loader + +usb:v03F3p0088* + ID_MODEL_FROM_DATABASE=AVC-2210 Device + +usb:v03F3p008B* + ID_MODEL_FROM_DATABASE=AVC-2310 Loader + +usb:v03F3p008C* + ID_MODEL_FROM_DATABASE=AVC-2310 Device + +usb:v03F3p0094* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v03F3p009B* + ID_MODEL_FROM_DATABASE=AVC-1410 GameBridge TV NTSC + +usb:v03F3p2000* + ID_MODEL_FROM_DATABASE=USBXchange + +usb:v03F3p2001* + ID_MODEL_FROM_DATABASE=USBXchange Adapter + +usb:v03F3p2002* + ID_MODEL_FROM_DATABASE=USB2-Xchange + +usb:v03F3p2003* + ID_MODEL_FROM_DATABASE=USB2-Xchange Adapter + +usb:v03F3p4000* + ID_MODEL_FROM_DATABASE=4-port hub + +usb:v03F3pADCC* + ID_MODEL_FROM_DATABASE=Composite Device Support + +usb:v03F4* + ID_VENDOR_FROM_DATABASE=Diebold, Inc. + +usb:v03F5* + ID_VENDOR_FROM_DATABASE=Siemens Electromechanical + +usb:v03F8* + ID_VENDOR_FROM_DATABASE=Epson Imaging Technology Center + +usb:v03F9* + ID_VENDOR_FROM_DATABASE=KeyTronic Corp. + +usb:v03F9p0100* + ID_MODEL_FROM_DATABASE=KT-2001 Keyboard + +usb:v03F9p0101* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v03F9p0102* + ID_MODEL_FROM_DATABASE=Keyboard Mouse + +usb:v03FB* + ID_VENDOR_FROM_DATABASE=OPTi, Inc. + +usb:v03FC* + ID_VENDOR_FROM_DATABASE=Elitegroup Computer Systems + +usb:v03FD* + ID_VENDOR_FROM_DATABASE=Xilinx, Inc. + +usb:v03FDp0008* + ID_MODEL_FROM_DATABASE=Platform Cable USB II + +usb:v03FDp0050* + ID_MODEL_FROM_DATABASE=dfu downloader + +usb:v03FE* + ID_VENDOR_FROM_DATABASE=Farallon Comunications + +usb:v0400* + ID_VENDOR_FROM_DATABASE=National Semiconductor Corp. + +usb:v0400p05DC* + ID_MODEL_FROM_DATABASE=Rigol Technologies DS1000USB Oscilloscope + +usb:v0400p0807* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v0400p080A* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0400p09C4* + ID_MODEL_FROM_DATABASE=Rigol Technologies DG1022 Arbitrary Waveform Generator + +usb:v0400p1000* + ID_MODEL_FROM_DATABASE=Mustek BearPaw 1200 Scanner + +usb:v0400p1001* + ID_MODEL_FROM_DATABASE=Mustek BearPaw 2400 Scanner + +usb:v0400p1237* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0400pA000* + ID_MODEL_FROM_DATABASE=Smart Display Reference Device + +usb:v0400pC359* + ID_MODEL_FROM_DATABASE=Logitech Harmony + +usb:v0400pC35B* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v0400pC55D* + ID_MODEL_FROM_DATABASE=Rigol Technologies DS5000USB Oscilloscope + +usb:v0401* + ID_VENDOR_FROM_DATABASE=National Registry, Inc. + +usb:v0402* + ID_VENDOR_FROM_DATABASE=ALi Corp. + +usb:v0402p5462* + ID_MODEL_FROM_DATABASE=M5462 IDE Controller + +usb:v0402p5602* + ID_MODEL_FROM_DATABASE=M5602 Video Camera Controller + +usb:v0402p5603* + ID_MODEL_FROM_DATABASE=M5603 Video Camera Controller + +usb:v0402p5606* + ID_MODEL_FROM_DATABASE=M5606 Video Camera Controller [UVC] + +usb:v0402p5621* + ID_MODEL_FROM_DATABASE=M5621 High-Speed IDE Controller + +usb:v0402p5623* + ID_MODEL_FROM_DATABASE=M5623 Scanner Controller + +usb:v0402p5627* + ID_MODEL_FROM_DATABASE=Welland ME-740PS USB2 3.5" Power Saving Enclosure + +usb:v0402p5632* + ID_MODEL_FROM_DATABASE=M5632 Host-to-Host Link + +usb:v0402p5635* + ID_MODEL_FROM_DATABASE=M5635 Flash Card Reader + +usb:v0402p5636* + ID_MODEL_FROM_DATABASE=USB 2.0 Storage Device + +usb:v0402p5637* + ID_MODEL_FROM_DATABASE=M5637 IDE Controller + +usb:v0402p5642* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v0402p5661* + ID_MODEL_FROM_DATABASE=M5661 MP3 player + +usb:v0402p5667* + ID_MODEL_FROM_DATABASE=M5667 MP3 player + +usb:v0402p9665* + ID_MODEL_FROM_DATABASE=Gateway Webcam + +usb:v0403* + ID_VENDOR_FROM_DATABASE=Future Technology Devices International, Ltd + +usb:v0403p0000* + ID_MODEL_FROM_DATABASE=H4SMK 7 Port Hub / Bricked Counterfeit FT232 Serial (UART) IC + +usb:v0403p0232* + ID_MODEL_FROM_DATABASE=Serial Converter + +usb:v0403p1060* + ID_MODEL_FROM_DATABASE=JTAG adapter + +usb:v0403p1234* + ID_MODEL_FROM_DATABASE=IronLogic RFID Adapter [Z-2 USB] + +usb:v0403p1235* + ID_MODEL_FROM_DATABASE=Iron Logic Z-397 RS-485/422 converter + +usb:v0403p6001* + ID_MODEL_FROM_DATABASE=FT232 Serial (UART) IC + +usb:v0403p6002* + ID_MODEL_FROM_DATABASE=Lumel PD12 + +usb:v0403p6007* + ID_MODEL_FROM_DATABASE=Serial Converter + +usb:v0403p6008* + ID_MODEL_FROM_DATABASE=Serial Converter + +usb:v0403p6009* + ID_MODEL_FROM_DATABASE=Serial Converter + +usb:v0403p6010* + ID_MODEL_FROM_DATABASE=FT2232C/D/H Dual UART/FIFO IC + +usb:v0403p6011* + ID_MODEL_FROM_DATABASE=FT4232H Quad HS USB-UART/FIFO IC + +usb:v0403p6014* + ID_MODEL_FROM_DATABASE=FT232H Single HS USB-UART/FIFO IC + +usb:v0403p6015* + ID_MODEL_FROM_DATABASE=Bridge(I2C/SPI/UART/FIFO) + +usb:v0403p6F70* + ID_MODEL_FROM_DATABASE=HB-RF-USB + +usb:v0403p8028* + ID_MODEL_FROM_DATABASE=Dev board JTAG (FT232H based) + +usb:v0403p8040* + ID_MODEL_FROM_DATABASE=4 Port Hub + +usb:v0403p8070* + ID_MODEL_FROM_DATABASE=7 Port Hub + +usb:v0403p8140* + ID_MODEL_FROM_DATABASE=Vehicle Explorer Interface + +usb:v0403p8210* + ID_MODEL_FROM_DATABASE=MGTimer - MGCC (Vic) Timing System + +usb:v0403p8348* + ID_MODEL_FROM_DATABASE=FT232BM [SIENNA Serial Interface] + +usb:v0403p8370* + ID_MODEL_FROM_DATABASE=7 Port Hub + +usb:v0403p8371* + ID_MODEL_FROM_DATABASE=PS/2 Keyboard And Mouse + +usb:v0403p8372* + ID_MODEL_FROM_DATABASE=FT8U100AX Serial Port + +usb:v0403p87D0* + ID_MODEL_FROM_DATABASE=Cressi Dive Computer Interface + +usb:v0403p8A28* + ID_MODEL_FROM_DATABASE=Rainforest Automation ZigBee Controller + +usb:v0403p8A98* + ID_MODEL_FROM_DATABASE=TIAO Multi-Protocol Adapter + +usb:v0403p8B28* + ID_MODEL_FROM_DATABASE=Alpermann+Velte TCI70 + +usb:v0403p8B29* + ID_MODEL_FROM_DATABASE=Alpermann+Velte TC60 CLS + +usb:v0403p8B2A* + ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium Q1 + +usb:v0403p8B2B* + ID_MODEL_FROM_DATABASE=Alpermann+Velte TCD + +usb:v0403p8B2C* + ID_MODEL_FROM_DATABASE=Alpermann+Velte TCC70 + +usb:v0403p9090* + ID_MODEL_FROM_DATABASE=SNAP Stick 200 + +usb:v0403p9132* + ID_MODEL_FROM_DATABASE=LCD and Temperature Interface + +usb:v0403p9133* + ID_MODEL_FROM_DATABASE=CallerID + +usb:v0403p9135* + ID_MODEL_FROM_DATABASE=Rotary Pub alarm + +usb:v0403p9136* + ID_MODEL_FROM_DATABASE=Pulsecounter + +usb:v0403p9E90* + ID_MODEL_FROM_DATABASE=Marvell OpenRD Base/Client + +usb:v0403p9F80* + ID_MODEL_FROM_DATABASE=Ewert Energy Systems CANdapter + +usb:v0403pA6D0* + ID_MODEL_FROM_DATABASE=Texas Instruments XDS100v2 JTAG / BeagleBone A3 + +usb:v0403pA951* + ID_MODEL_FROM_DATABASE=HCP HIT GSM/GPRS modem [Cinterion MC55i] + +usb:v0403pA9A0* + ID_MODEL_FROM_DATABASE=FT2232D - Dual UART/FIFO IC - FTDI + +usb:v0403pABB8* + ID_MODEL_FROM_DATABASE=Lego Mindstorms NXTCam + +usb:v0403pB0C0* + ID_MODEL_FROM_DATABASE=microSensys RFID device + +usb:v0403pB0C1* + ID_MODEL_FROM_DATABASE=microSensys RFID device + +usb:v0403pB0C2* + ID_MODEL_FROM_DATABASE=iID contactless RFID device + +usb:v0403pB0C3* + ID_MODEL_FROM_DATABASE=iID contactless RFID device + +usb:v0403pB0C4* + ID_MODEL_FROM_DATABASE=RFID device + +usb:v0403pB0C5* + ID_MODEL_FROM_DATABASE=RFID device + +usb:v0403pB810* + ID_MODEL_FROM_DATABASE=US Interface Navigator (CAT and 2nd PTT lines) + +usb:v0403pB811* + ID_MODEL_FROM_DATABASE=US Interface Navigator (WKEY and FSK lines) + +usb:v0403pB812* + ID_MODEL_FROM_DATABASE=US Interface Navigator (RS232 and CONFIG lines) + +usb:v0403pB9B0* + ID_MODEL_FROM_DATABASE=Fujitsu SK-16FX-100PMC V1.1 + +usb:v0403pBAF8* + ID_MODEL_FROM_DATABASE=Amontec JTAGkey + +usb:v0403pBCD8* + ID_MODEL_FROM_DATABASE=Stellaris Development Board + +usb:v0403pBCD9* + ID_MODEL_FROM_DATABASE=Stellaris Evaluation Board + +usb:v0403pBCDA* + ID_MODEL_FROM_DATABASE=Stellaris ICDI Board + +usb:v0403pBD90* + ID_MODEL_FROM_DATABASE=PICAXE Download Cable [AXE027] + +usb:v0403pBDC8* + ID_MODEL_FROM_DATABASE=Egnite GmbH - JTAG/RS-232 adapter + +usb:v0403pBFD8* + ID_MODEL_FROM_DATABASE=OpenDCC + +usb:v0403pBFD9* + ID_MODEL_FROM_DATABASE=OpenDCC (Sniffer) + +usb:v0403pBFDA* + ID_MODEL_FROM_DATABASE=OpenDCC (Throttle) + +usb:v0403pBFDB* + ID_MODEL_FROM_DATABASE=OpenDCC (Gateway) + +usb:v0403pBFDC* + ID_MODEL_FROM_DATABASE=OpenDCC (GBM) + +usb:v0403pC580* + ID_MODEL_FROM_DATABASE=HID UNIKEY dongle [F-Response] + +usb:v0403pC630* + ID_MODEL_FROM_DATABASE=lcd2usb interface + +usb:v0403pC631* + ID_MODEL_FROM_DATABASE=i2c-tiny-usb interface + +usb:v0403pC632* + ID_MODEL_FROM_DATABASE=xu1541 c64 floppy drive interface + +usb:v0403pC633* + ID_MODEL_FROM_DATABASE=TinyCrypt dongle + +usb:v0403pC634* + ID_MODEL_FROM_DATABASE=glcd2usb interface + +usb:v0403pC7D0* + ID_MODEL_FROM_DATABASE=RR-CirKits LocoBuffer-USB + +usb:v0403pC8B8* + ID_MODEL_FROM_DATABASE=Alpermann+Velte MTD TCU + +usb:v0403pC8B9* + ID_MODEL_FROM_DATABASE=Alpermann+Velte MTD TCU 1HE + +usb:v0403pC8BA* + ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium H1 + +usb:v0403pC8BB* + ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium H3 + +usb:v0403pC8BC* + ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium S1 + +usb:v0403pC8BD* + ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium T1 + +usb:v0403pC8BE* + ID_MODEL_FROM_DATABASE=Alpermann+Velte Rubidium D1 + +usb:v0403pC8BF* + ID_MODEL_FROM_DATABASE=Alpermann+Velte TC60 RLV + +usb:v0403pCC48* + ID_MODEL_FROM_DATABASE=Tactrix OpenPort 1.3 Mitsubishi + +usb:v0403pCC49* + ID_MODEL_FROM_DATABASE=Tactrix OpenPort 1.3 Subaru + +usb:v0403pCC4A* + ID_MODEL_FROM_DATABASE=Tactrix OpenPort 1.3 Universal + +usb:v0403pCFF8* + ID_MODEL_FROM_DATABASE=Amontec JTAGkey + +usb:v0403pD010* + ID_MODEL_FROM_DATABASE=SCS PTC-IIusb + +usb:v0403pD011* + ID_MODEL_FROM_DATABASE=SCS Position-Tracker/TNC + +usb:v0403pD012* + ID_MODEL_FROM_DATABASE=SCS DRAGON 1 + +usb:v0403pD013* + ID_MODEL_FROM_DATABASE=SCS DRAGON 1 + +usb:v0403pD388* + ID_MODEL_FROM_DATABASE=Xsens converter + +usb:v0403pD389* + ID_MODEL_FROM_DATABASE=Xsens Wireless Receiver + +usb:v0403pD38A* + ID_MODEL_FROM_DATABASE=Xsens serial converter + +usb:v0403pD38B* + ID_MODEL_FROM_DATABASE=Xsens serial converter + +usb:v0403pD38C* + ID_MODEL_FROM_DATABASE=Xsens Wireless Receiver + +usb:v0403pD38D* + ID_MODEL_FROM_DATABASE=Xsens Awinda Station + +usb:v0403pD38E* + ID_MODEL_FROM_DATABASE=Xsens serial converter + +usb:v0403pD38F* + ID_MODEL_FROM_DATABASE=Xsens serial converter + +usb:v0403pD491* + ID_MODEL_FROM_DATABASE=Zolix Omni 1509 monochromator + +usb:v0403pD578* + ID_MODEL_FROM_DATABASE=Accesio USB-COM-4SM + +usb:v0403pD6F8* + ID_MODEL_FROM_DATABASE=UNI Black BOX + +usb:v0403pD738* + ID_MODEL_FROM_DATABASE=Propox JTAGcable II + +usb:v0403pD739* + ID_MODEL_FROM_DATABASE=Propox ISPcable III + +usb:v0403pD9A9* + ID_MODEL_FROM_DATABASE=Actisense USG-1 NMEA Serial Gateway + +usb:v0403pD9AA* + ID_MODEL_FROM_DATABASE=Actisense NGT-1 NMEA2000 PC Interface + +usb:v0403pD9AB* + ID_MODEL_FROM_DATABASE=Actisense NGT-1 NMEA2000 Gateway + +usb:v0403pDAF4* + ID_MODEL_FROM_DATABASE=Qundis Serial Infrared Head + +usb:v0403pE0D0* + ID_MODEL_FROM_DATABASE=Total Phase Aardvark I2C/SPI Host Adapter + +usb:v0403pE521* + ID_MODEL_FROM_DATABASE=EVER Sinline XL Series UPS + +usb:v0403pE6C8* + ID_MODEL_FROM_DATABASE=PYRAMID Computer GmbH LCD + +usb:v0403pE700* + ID_MODEL_FROM_DATABASE=Elster Unicom III Optical Probe + +usb:v0403pE729* + ID_MODEL_FROM_DATABASE=Segway Robotic Mobility Platforms 200 + +usb:v0403pE888* + ID_MODEL_FROM_DATABASE=Expert ISDN Control USB + +usb:v0403pE889* + ID_MODEL_FROM_DATABASE=USB-RS232 OptoBridge + +usb:v0403pE88A* + ID_MODEL_FROM_DATABASE=Expert mouseCLOCK USB II + +usb:v0403pE88B* + ID_MODEL_FROM_DATABASE=Precision Clock MSF USB + +usb:v0403pE88C* + ID_MODEL_FROM_DATABASE=Expert mouseCLOCK USB II HBG + +usb:v0403pE8D8* + ID_MODEL_FROM_DATABASE=Aaronia AG Spectran Spectrum Analyzer + +usb:v0403pE8DC* + ID_MODEL_FROM_DATABASE=Aaronia AG UBBV Preamplifier + +usb:v0403pEA90* + ID_MODEL_FROM_DATABASE=Eclo 1-Wire Adapter + +usb:v0403pECD9* + ID_MODEL_FROM_DATABASE=miControl miCan-Stick + +usb:v0403pED71* + ID_MODEL_FROM_DATABASE=HAMEG HO870 Serial Port + +usb:v0403pED72* + ID_MODEL_FROM_DATABASE=HAMEG HO720 Serial Port + +usb:v0403pED73* + ID_MODEL_FROM_DATABASE=HAMEG HO730 Serial Port + +usb:v0403pED74* + ID_MODEL_FROM_DATABASE=HAMEG HO820 Serial Port + +usb:v0403pEF10* + ID_MODEL_FROM_DATABASE=FT1245BL + +usb:v0403pF070* + ID_MODEL_FROM_DATABASE=Serial Converter 422/485 [Vardaan VEUSB422R3] + +usb:v0403pF0C8* + ID_MODEL_FROM_DATABASE=SPROG Decoder Programmer + +usb:v0403pF0C9* + ID_MODEL_FROM_DATABASE=SPROG-DCC CAN-USB + +usb:v0403pF0E9* + ID_MODEL_FROM_DATABASE=Tagsys L-P101 + +usb:v0403pF0EE* + ID_MODEL_FROM_DATABASE=Tagsys Medio P200x + +usb:v0403pF1A0* + ID_MODEL_FROM_DATABASE=Asix PRESTO Programmer + +usb:v0403pF208* + ID_MODEL_FROM_DATABASE=Papenmeier Braille-Display + +usb:v0403pF3C0* + ID_MODEL_FROM_DATABASE=4N-GALAXY Serial Converter + +usb:v0403pF458* + ID_MODEL_FROM_DATABASE=ABACUS ELECTRICS Optical Probe + +usb:v0403pF608* + ID_MODEL_FROM_DATABASE=CTI USB-485-Mini + +usb:v0403pF60B* + ID_MODEL_FROM_DATABASE=CTI USB-Nano-485 + +usb:v0403pF680* + ID_MODEL_FROM_DATABASE=Suunto Sports Instrument + +usb:v0403pF758* + ID_MODEL_FROM_DATABASE=GW Instek GDS-8x0 Oscilloscope + +usb:v0403pF7C0* + ID_MODEL_FROM_DATABASE=ZeitControl Cardsystems TagTracer MIFARE + +usb:v0403pF850* + ID_MODEL_FROM_DATABASE=USB-UIRT (Universal Infrared Receiver+Transmitter) + +usb:v0403pF918* + ID_MODEL_FROM_DATABASE=Ant8 Logic Probe + +usb:v0403pFA00* + ID_MODEL_FROM_DATABASE=Matrix Orbital USB Serial + +usb:v0403pFA01* + ID_MODEL_FROM_DATABASE=Matrix Orbital MX2 or MX3 + +usb:v0403pFA02* + ID_MODEL_FROM_DATABASE=Matrix Orbital MX4 or MX5 + +usb:v0403pFA03* + ID_MODEL_FROM_DATABASE=Matrix Orbital VK/LK202 Family + +usb:v0403pFA04* + ID_MODEL_FROM_DATABASE=Matrix Orbital VK/LK204 Family + +usb:v0403pFA20* + ID_MODEL_FROM_DATABASE=Ross-Tech HEX-USB + +usb:v0403pFC08* + ID_MODEL_FROM_DATABASE=Crystalfontz CFA-632 USB LCD + +usb:v0403pFC09* + ID_MODEL_FROM_DATABASE=Crystalfontz CFA-634 USB LCD + +usb:v0403pFC0B* + ID_MODEL_FROM_DATABASE=Crystalfontz CFA-633 USB LCD + +usb:v0403pFC0C* + ID_MODEL_FROM_DATABASE=Crystalfontz CFA-631 USB LCD + +usb:v0403pFC0D* + ID_MODEL_FROM_DATABASE=Crystalfontz CFA-635 USB LCD + +usb:v0403pFC82* + ID_MODEL_FROM_DATABASE=SEMC DSS-20/DSS-25 SyncStation + +usb:v0403pFD48* + ID_MODEL_FROM_DATABASE=ShipModul MiniPlex-4xUSB NMEA Multiplexer + +usb:v0403pFD49* + ID_MODEL_FROM_DATABASE=ShipModul MiniPlex-4xUSB-AIS NMEA Multiplexer + +usb:v0403pFD4B* + ID_MODEL_FROM_DATABASE=ShipModul MiniPlex NMEA Multiplexer + +usb:v0403pFF08* + ID_MODEL_FROM_DATABASE=ToolHouse LoopBack Adapter + +usb:v0403pFF18* + ID_MODEL_FROM_DATABASE=ScienceScope Logbook ML + +usb:v0403pFF19* + ID_MODEL_FROM_DATABASE=Logbook Bus + +usb:v0403pFF1A* + ID_MODEL_FROM_DATABASE=Logbook Bus + +usb:v0403pFF1B* + ID_MODEL_FROM_DATABASE=Logbook Bus + +usb:v0403pFF1C* + ID_MODEL_FROM_DATABASE=ScienceScope Logbook LS + +usb:v0403pFF1D* + ID_MODEL_FROM_DATABASE=ScienceScope Logbook HS + +usb:v0403pFF1E* + ID_MODEL_FROM_DATABASE=Logbook Bus + +usb:v0403pFF1F* + ID_MODEL_FROM_DATABASE=Logbook Bus + +usb:v0404* + ID_VENDOR_FROM_DATABASE=NCR Corp. + +usb:v0404p0202* + ID_MODEL_FROM_DATABASE=78XX Scanner + +usb:v0404p0203* + ID_MODEL_FROM_DATABASE=78XX Scanner - Embedded System + +usb:v0404p0310* + ID_MODEL_FROM_DATABASE=K590 Printer, Self-Service + +usb:v0404p0311* + ID_MODEL_FROM_DATABASE=7167 Printer, Receipt/Slip + +usb:v0404p0312* + ID_MODEL_FROM_DATABASE=7197 Printer Receipt + +usb:v0404p0320* + ID_MODEL_FROM_DATABASE=5932-USB Keyboard + +usb:v0404p0321* + ID_MODEL_FROM_DATABASE=5953-USB Dynakey + +usb:v0404p0322* + ID_MODEL_FROM_DATABASE=5932-USB Enhanced Keyboard + +usb:v0404p0323* + ID_MODEL_FROM_DATABASE=5932-USB Enhanced Keyboard, Flash-Recovery/Download + +usb:v0404p0324* + ID_MODEL_FROM_DATABASE=5953-USB Enhanced Dynakey + +usb:v0404p0325* + ID_MODEL_FROM_DATABASE=5953-USB Enhanced Dynakey Flash-Recovery/Download + +usb:v0404p0328* + ID_MODEL_FROM_DATABASE=K016: USB-MSR ISO 3-track MSR: POS Standard (See HID pages) + +usb:v0404p0329* + ID_MODEL_FROM_DATABASE=K018: USB-MSR JIS 2-Track MSR: POS Standard + +usb:v0404p032A* + ID_MODEL_FROM_DATABASE=K016: USB-MSR ISO 3-Track MSR: HID Keyboard Mode + +usb:v0404p032B* + ID_MODEL_FROM_DATABASE=K016/K018: USB-MSR Flash-Recovery/Download + +usb:v0405* + ID_VENDOR_FROM_DATABASE=Synopsys, Inc. + +usb:v0406* + ID_VENDOR_FROM_DATABASE=Fujitsu-ICL Computers + +usb:v0407* + ID_VENDOR_FROM_DATABASE=Fujitsu Personal Systems, Inc. + +usb:v0408* + ID_VENDOR_FROM_DATABASE=Quanta Computer, Inc. + +usb:v0408p0103* + ID_MODEL_FROM_DATABASE=FV TouchCam N1 (Audio) + +usb:v0408p030C* + ID_MODEL_FROM_DATABASE=HP Webcam + +usb:v0408p03B2* + ID_MODEL_FROM_DATABASE=HP Webcam + +usb:v0408p03F4* + ID_MODEL_FROM_DATABASE=HP Webcam + +usb:v0408p1030* + ID_MODEL_FROM_DATABASE=FV TouchCam N1 (Video) + +usb:v0408p3000* + ID_MODEL_FROM_DATABASE=Optical dual-touch panel + +usb:v0408p3001* + ID_MODEL_FROM_DATABASE=Optical Touch Screen + +usb:v0408pA060* + ID_MODEL_FROM_DATABASE=HD Webcam + +usb:v0409* + ID_VENDOR_FROM_DATABASE=NEC Corp. + +usb:v0409p0011* + ID_MODEL_FROM_DATABASE=PC98 Series Layout Keyboard Mouse + +usb:v0409p0012* + ID_MODEL_FROM_DATABASE=ATerm IT75DSU ISDN TA + +usb:v0409p0014* + ID_MODEL_FROM_DATABASE=Japanese Keyboard + +usb:v0409p0019* + ID_MODEL_FROM_DATABASE=109 Japanese Keyboard with Bus-Powered Hub + +usb:v0409p001A* + ID_MODEL_FROM_DATABASE=PC98 Series Layout Keyboard with Bus-Powered Hub + +usb:v0409p0025* + ID_MODEL_FROM_DATABASE=Mini Keyboard with Bus-Powered Hub + +usb:v0409p0027* + ID_MODEL_FROM_DATABASE=MultiSync Monitor + +usb:v0409p002C* + ID_MODEL_FROM_DATABASE=Clik!-USB Drive + +usb:v0409p0034* + ID_MODEL_FROM_DATABASE=109 Japanese Keyboard with One-touch start buttons + +usb:v0409p003F* + ID_MODEL_FROM_DATABASE=Wireless Keyboard with One-touch start buttons + +usb:v0409p0040* + ID_MODEL_FROM_DATABASE=Floppy + +usb:v0409p004E* + ID_MODEL_FROM_DATABASE=SuperScript 1400 Series + +usb:v0409p004F* + ID_MODEL_FROM_DATABASE=Wireless Keyboard with One-touch start buttons + +usb:v0409p0050* + ID_MODEL_FROM_DATABASE=7-port hub + +usb:v0409p0058* + ID_MODEL_FROM_DATABASE=HighSpeed Hub + +usb:v0409p0059* + ID_MODEL_FROM_DATABASE=HighSpeed Hub + +usb:v0409p005A* + ID_MODEL_FROM_DATABASE=HighSpeed Hub + +usb:v0409p006A* + ID_MODEL_FROM_DATABASE=Conceptronic USB Harddisk Box + +usb:v0409p007D* + ID_MODEL_FROM_DATABASE=MINICUBE2 + +usb:v0409p007E* + ID_MODEL_FROM_DATABASE=PG-FP5 Flash Memory Programmer + +usb:v0409p0081* + ID_MODEL_FROM_DATABASE=SuperScript 1400 Series + +usb:v0409p0082* + ID_MODEL_FROM_DATABASE=SuperScript 1400 Series + +usb:v0409p0094* + ID_MODEL_FROM_DATABASE=Japanese Keyboard with One-touch start buttons + +usb:v0409p0095* + ID_MODEL_FROM_DATABASE=Japanese Keyboard + +usb:v0409p00A9* + ID_MODEL_FROM_DATABASE=AtermIT21L 128K Support Standard + +usb:v0409p00AA* + ID_MODEL_FROM_DATABASE=AtermITX72 128K Support Standard + +usb:v0409p00AB* + ID_MODEL_FROM_DATABASE=AtermITX62 128K Support Standard + +usb:v0409p00AC* + ID_MODEL_FROM_DATABASE=AtermIT42 128K Support Standard + +usb:v0409p00AE* + ID_MODEL_FROM_DATABASE=INSMATEV70G-MAX Standard + +usb:v0409p00AF* + ID_MODEL_FROM_DATABASE=AtermITX70 128K Support Standard + +usb:v0409p00B0* + ID_MODEL_FROM_DATABASE=AtermITX80 128K Support Standard + +usb:v0409p00B2* + ID_MODEL_FROM_DATABASE=AtermITX80D 128K Support Standard + +usb:v0409p00C0* + ID_MODEL_FROM_DATABASE=Wireless Remocon + +usb:v0409p00F7* + ID_MODEL_FROM_DATABASE=Smart Display PK-SD10 + +usb:v0409p011D* + ID_MODEL_FROM_DATABASE=e228 Mobile Phone + +usb:v0409p0203* + ID_MODEL_FROM_DATABASE=HID Audio Controls + +usb:v0409p021D* + ID_MODEL_FROM_DATABASE=Aterm WL54SU2 802.11g Wireless Adapter [Atheros AR5523] + +usb:v0409p0248* + ID_MODEL_FROM_DATABASE=Aterm PA-WL54GU + +usb:v0409p0249* + ID_MODEL_FROM_DATABASE=Aterm WL300NU-G + +usb:v0409p02B4* + ID_MODEL_FROM_DATABASE=Aterm WL300NU-AG + +usb:v0409p02B6* + ID_MODEL_FROM_DATABASE=Aterm WL300NU-GS 802.11n Wireless Adapter + +usb:v0409p02BC* + ID_MODEL_FROM_DATABASE=Computer Monitor + +usb:v0409p0300* + ID_MODEL_FROM_DATABASE=LifeTouch Note + +usb:v0409p0301* + ID_MODEL_FROM_DATABASE=LifeTouch Note (debug mode) + +usb:v0409p55AA* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0409p55AB* + ID_MODEL_FROM_DATABASE=Hub [iMac/iTouch kbd] + +usb:v0409p8010* + ID_MODEL_FROM_DATABASE=Intellibase Hub + +usb:v0409p8011* + ID_MODEL_FROM_DATABASE=Intellibase Hub + +usb:v0409pEFBE* + ID_MODEL_FROM_DATABASE=P!cty 900 [HP DJ] + +usb:v0409pF0BE* + ID_MODEL_FROM_DATABASE=P!cty 920 [HP DJ 812c] + +usb:v040A* + ID_VENDOR_FROM_DATABASE=Kodak Co. + +usb:v040Ap0001* + ID_MODEL_FROM_DATABASE=DVC-323 + +usb:v040Ap0002* + ID_MODEL_FROM_DATABASE=DVC-325 + +usb:v040Ap0100* + ID_MODEL_FROM_DATABASE=DC-220 + +usb:v040Ap0110* + ID_MODEL_FROM_DATABASE=DC-260 + +usb:v040Ap0111* + ID_MODEL_FROM_DATABASE=DC-265 + +usb:v040Ap0112* + ID_MODEL_FROM_DATABASE=DC-290 + +usb:v040Ap0120* + ID_MODEL_FROM_DATABASE=DC-240 + +usb:v040Ap0121* + ID_MODEL_FROM_DATABASE=DC-240 (PTP firmware) + +usb:v040Ap0130* + ID_MODEL_FROM_DATABASE=DC-280 + +usb:v040Ap0131* + ID_MODEL_FROM_DATABASE=DC-5000 + +usb:v040Ap0132* + ID_MODEL_FROM_DATABASE=DC-3400 + +usb:v040Ap0140* + ID_MODEL_FROM_DATABASE=DC-4800 + +usb:v040Ap0160* + ID_MODEL_FROM_DATABASE=DC4800 + +usb:v040Ap0170* + ID_MODEL_FROM_DATABASE=DX3900 + +usb:v040Ap0200* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0300* + ID_MODEL_FROM_DATABASE=EZ-200 + +usb:v040Ap0400* + ID_MODEL_FROM_DATABASE=MC3 + +usb:v040Ap0402* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0403* + ID_MODEL_FROM_DATABASE=Z7590 + +usb:v040Ap0500* + ID_MODEL_FROM_DATABASE=DX3500 + +usb:v040Ap0510* + ID_MODEL_FROM_DATABASE=DX3600 + +usb:v040Ap0525* + ID_MODEL_FROM_DATABASE=DX3215 + +usb:v040Ap0530* + ID_MODEL_FROM_DATABASE=DX3700 + +usb:v040Ap0535* + ID_MODEL_FROM_DATABASE=EasyShare CX4230 Camera + +usb:v040Ap0540* + ID_MODEL_FROM_DATABASE=LS420 + +usb:v040Ap0550* + ID_MODEL_FROM_DATABASE=DX4900 + +usb:v040Ap0555* + ID_MODEL_FROM_DATABASE=DX4330 + +usb:v040Ap0560* + ID_MODEL_FROM_DATABASE=CX4200 + +usb:v040Ap0565* + ID_MODEL_FROM_DATABASE=CX4210 + +usb:v040Ap0566* + ID_MODEL_FROM_DATABASE=CX4300 + +usb:v040Ap0567* + ID_MODEL_FROM_DATABASE=LS753 + +usb:v040Ap0568* + ID_MODEL_FROM_DATABASE=LS443 + +usb:v040Ap0569* + ID_MODEL_FROM_DATABASE=LS663 + +usb:v040Ap0570* + ID_MODEL_FROM_DATABASE=DX6340 + +usb:v040Ap0571* + ID_MODEL_FROM_DATABASE=CX6330 + +usb:v040Ap0572* + ID_MODEL_FROM_DATABASE=DX6440 + +usb:v040Ap0573* + ID_MODEL_FROM_DATABASE=CX6230 + +usb:v040Ap0574* + ID_MODEL_FROM_DATABASE=CX6200 + +usb:v040Ap0575* + ID_MODEL_FROM_DATABASE=DX6490 + +usb:v040Ap0576* + ID_MODEL_FROM_DATABASE=DX4530 + +usb:v040Ap0577* + ID_MODEL_FROM_DATABASE=DX7630 + +usb:v040Ap0578* + ID_MODEL_FROM_DATABASE=CX7300/CX7310 + +usb:v040Ap0579* + ID_MODEL_FROM_DATABASE=CX7220 + +usb:v040Ap057A* + ID_MODEL_FROM_DATABASE=CX7330 + +usb:v040Ap057B* + ID_MODEL_FROM_DATABASE=CX7430 + +usb:v040Ap057C* + ID_MODEL_FROM_DATABASE=CX7530 + +usb:v040Ap057D* + ID_MODEL_FROM_DATABASE=DX7440 + +usb:v040Ap057E* + ID_MODEL_FROM_DATABASE=C300 + +usb:v040Ap057F* + ID_MODEL_FROM_DATABASE=DX7590 + +usb:v040Ap0580* + ID_MODEL_FROM_DATABASE=Z730 + +usb:v040Ap0581* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0582* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0583* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0584* + ID_MODEL_FROM_DATABASE=CX6445 + +usb:v040Ap0585* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0586* + ID_MODEL_FROM_DATABASE=CX7525 + +usb:v040Ap0587* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0588* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0589* + ID_MODEL_FROM_DATABASE=EasyShare C360 + +usb:v040Ap058A* + ID_MODEL_FROM_DATABASE=C310 + +usb:v040Ap058B* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap058C* + ID_MODEL_FROM_DATABASE=C330 + +usb:v040Ap058D* + ID_MODEL_FROM_DATABASE=C340 + +usb:v040Ap058E* + ID_MODEL_FROM_DATABASE=V530 + +usb:v040Ap058F* + ID_MODEL_FROM_DATABASE=V550 + +usb:v040Ap0590* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0591* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0592* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0593* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0594* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0595* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0596* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0597* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap0598* + ID_MODEL_FROM_DATABASE=EASYSHARE M1033 digital camera + +usb:v040Ap0599* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap059A* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap059B* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap059C* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap059D* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap059E* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap059F* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05A0* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05A1* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05A2* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05A3* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05A4* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05A5* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05A6* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05A7* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05A8* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05A9* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05AA* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05AB* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05AC* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05AD* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05AE* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05AF* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05B0* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05B1* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05B2* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05B3* + ID_MODEL_FROM_DATABASE=EasyShare Z710 Camera + +usb:v040Ap05B4* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05B5* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05B6* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05B7* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05B8* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05B9* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05BA* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05BB* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05BC* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05BD* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05BE* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05BF* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05C0* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05C1* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05C2* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05C3* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05C4* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05C5* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v040Ap05C8* + ID_MODEL_FROM_DATABASE=EASYSHARE Z1485 IS Digital Camera + +usb:v040Ap05D3* + ID_MODEL_FROM_DATABASE=EasyShare M320 Camera + +usb:v040Ap05D4* + ID_MODEL_FROM_DATABASE=EasyShare C180 Digital Camera + +usb:v040Ap1001* + ID_MODEL_FROM_DATABASE=EasyShare SV811 Digital Picture Frame + +usb:v040Ap4000* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v040Ap4021* + ID_MODEL_FROM_DATABASE=Photo Printer 6800 + +usb:v040Ap4022* + ID_MODEL_FROM_DATABASE=1400 Digital Photo Printer + +usb:v040Ap402B* + ID_MODEL_FROM_DATABASE=Photo Printer 6850 + +usb:v040Ap402E* + ID_MODEL_FROM_DATABASE=605 Photo Printer + +usb:v040Ap4034* + ID_MODEL_FROM_DATABASE=805 Photo Printer + +usb:v040Ap4035* + ID_MODEL_FROM_DATABASE=7000 Photo Printer + +usb:v040Ap4037* + ID_MODEL_FROM_DATABASE=7010 Photo Printer + +usb:v040Ap4038* + ID_MODEL_FROM_DATABASE=7015 Photo Printer + +usb:v040Ap404D* + ID_MODEL_FROM_DATABASE=8810 Photo Printer + +usb:v040Ap404F* + ID_MODEL_FROM_DATABASE=305 Photo Printer + +usb:v040Ap4056* + ID_MODEL_FROM_DATABASE=ESP 7200 Series AiO + +usb:v040Ap4109* + ID_MODEL_FROM_DATABASE=EasyShare Printer Dock Series 3 + +usb:v040Ap410D* + ID_MODEL_FROM_DATABASE=EasyShare G600 Printer Dock + +usb:v040Ap5010* + ID_MODEL_FROM_DATABASE=Wireless Adapter + +usb:v040Ap5012* + ID_MODEL_FROM_DATABASE=DBT-220 Bluetooth Adapter + +usb:v040Ap6001* + ID_MODEL_FROM_DATABASE=i30 + +usb:v040Ap6002* + ID_MODEL_FROM_DATABASE=i40 + +usb:v040Ap6003* + ID_MODEL_FROM_DATABASE=i50 + +usb:v040Ap6004* + ID_MODEL_FROM_DATABASE=i60 + +usb:v040Ap6005* + ID_MODEL_FROM_DATABASE=i80 + +usb:v040Ap6029* + ID_MODEL_FROM_DATABASE=i900 + +usb:v040Ap602A* + ID_MODEL_FROM_DATABASE=i900 + +usb:v040B* + ID_VENDOR_FROM_DATABASE=Weltrend Semiconductor + +usb:v040Bp0A68* + ID_MODEL_FROM_DATABASE=Func MS-3 gaming mouse [WT6573F MCU] + +usb:v040Bp2367* + ID_MODEL_FROM_DATABASE=Human Interface Device [HP CalcPad 200 Calculator and Numeric Keypad] + +usb:v040Bp6510* + ID_MODEL_FROM_DATABASE=Weltrend Bar Code Reader + +usb:v040Bp6520* + ID_MODEL_FROM_DATABASE=Xploder Xbox Memory Unit (8MB) + +usb:v040Bp6533* + ID_MODEL_FROM_DATABASE=Speed-Link Competition Pro + +usb:v040Bp6543* + ID_MODEL_FROM_DATABASE=Manhattan Magnetic Card Strip Reader + +usb:v040C* + ID_VENDOR_FROM_DATABASE=VTech Computers, Ltd + +usb:v040D* + ID_VENDOR_FROM_DATABASE=VIA Technologies, Inc. + +usb:v040Dp3184* + ID_MODEL_FROM_DATABASE=VNT VT6656 USB-802.11 Wireless LAN Adapter + +usb:v040Dp340F* + ID_MODEL_FROM_DATABASE=Audinst HUD-mx2 + +usb:v040Dp6205* + ID_MODEL_FROM_DATABASE=USB 2.0 Card Reader + +usb:v040E* + ID_VENDOR_FROM_DATABASE=MCCI + +usb:v040F* + ID_VENDOR_FROM_DATABASE=Echo Speech Corp. + +usb:v0411* + ID_VENDOR_FROM_DATABASE=BUFFALO INC. (formerly MelCo., Inc.) + +usb:v0411p0001* + ID_MODEL_FROM_DATABASE=LUA-TX Ethernet [pegasus] + +usb:v0411p0005* + ID_MODEL_FROM_DATABASE=LUA-TX Ethernet + +usb:v0411p0006* + ID_MODEL_FROM_DATABASE=WLI-USB-L11 Wireless LAN Adapter + +usb:v0411p0009* + ID_MODEL_FROM_DATABASE=LUA2-TX Ethernet + +usb:v0411p000B* + ID_MODEL_FROM_DATABASE=WLI-USB-L11G-WR Wireless LAN Adapter + +usb:v0411p000D* + ID_MODEL_FROM_DATABASE=WLI-USB-L11G Wireless LAN Adapter + +usb:v0411p0012* + ID_MODEL_FROM_DATABASE=LUA-KTX Ethernet + +usb:v0411p0013* + ID_MODEL_FROM_DATABASE=USB2-IDE Adapter + +usb:v0411p0016* + ID_MODEL_FROM_DATABASE=WLI-USB-S11 802.11b Adapter + +usb:v0411p0018* + ID_MODEL_FROM_DATABASE=USB2-IDE Adapter + +usb:v0411p001C* + ID_MODEL_FROM_DATABASE=USB-IDE Bridge: DUB-PxxG + +usb:v0411p0027* + ID_MODEL_FROM_DATABASE=WLI-USB-KS11G 802.11b Adapter + +usb:v0411p002A* + ID_MODEL_FROM_DATABASE=SMSC USB97C202 "HD-HB300V2-EU" + +usb:v0411p003D* + ID_MODEL_FROM_DATABASE=LUA-U2-KTX Ethernet + +usb:v0411p0044* + ID_MODEL_FROM_DATABASE=WLI-USB-KB11 Wireless LAN Adapter + +usb:v0411p004B* + ID_MODEL_FROM_DATABASE=WLI-USB-G54 802.11g Adapter [Broadcom 4320 USB] + +usb:v0411p004D* + ID_MODEL_FROM_DATABASE=WLI-USB-B11 Wireless LAN Adapter + +usb:v0411p0050* + ID_MODEL_FROM_DATABASE=WLI2-USB2-G54 Wireless LAN Adapter + +usb:v0411p005E* + ID_MODEL_FROM_DATABASE=WLI-U2-KG54-YB WLAN + +usb:v0411p0065* + ID_MODEL_FROM_DATABASE=Python2 WDM Encoder + +usb:v0411p0066* + ID_MODEL_FROM_DATABASE=WLI-U2-KG54 WLAN + +usb:v0411p0067* + ID_MODEL_FROM_DATABASE=WLI-U2-KG54-AI WLAN + +usb:v0411p006E* + ID_MODEL_FROM_DATABASE=LUA-U2-GT 10/100/1000 Ethernet Adapter + +usb:v0411p0089* + ID_MODEL_FROM_DATABASE=RUF-C/U2 Flash Drive + +usb:v0411p008B* + ID_MODEL_FROM_DATABASE=Nintendo Wi-Fi + +usb:v0411p0091* + ID_MODEL_FROM_DATABASE=WLI-U2-KAMG54 Wireless LAN Adapter + +usb:v0411p0092* + ID_MODEL_FROM_DATABASE=WLI-U2-KAMG54 Bootloader + +usb:v0411p0097* + ID_MODEL_FROM_DATABASE=WLI-U2-KG54-BB + +usb:v0411p00A9* + ID_MODEL_FROM_DATABASE=WLI-U2-AMG54HP Wireless LAN Adapter + +usb:v0411p00AA* + ID_MODEL_FROM_DATABASE=WLI-U2-AMG54HP Bootloader + +usb:v0411p00B3* + ID_MODEL_FROM_DATABASE=PC-OP-RS1 RemoteStation + +usb:v0411p00BC* + ID_MODEL_FROM_DATABASE=WLI-U2-KG125S 802.11g Adapter [Broadcom 4320 USB] + +usb:v0411p00CA* + ID_MODEL_FROM_DATABASE=802.11n Network Adapter + +usb:v0411p00CB* + ID_MODEL_FROM_DATABASE=WLI-U2-G300N 802.11n Adapter + +usb:v0411p00D8* + ID_MODEL_FROM_DATABASE=WLI-U2-SG54HP + +usb:v0411p00D9* + ID_MODEL_FROM_DATABASE=WLI-U2-G54HP + +usb:v0411p00DA* + ID_MODEL_FROM_DATABASE=WLI-U2-KG54L 802.11bg [ZyDAS ZD1211B] + +usb:v0411p00DB* + ID_MODEL_FROM_DATABASE=External Hard Drive HD-PF32OU2 [Buffalo Ministation] + +usb:v0411p00E8* + ID_MODEL_FROM_DATABASE=WLI-UC-G300N Wireless LAN Adapter [Ralink RT2870] + +usb:v0411p00F9* + ID_MODEL_FROM_DATABASE=Portable DVD Writer (DVSM-PL58U2) + +usb:v0411p0105* + ID_MODEL_FROM_DATABASE=External Hard Drive HD-CEU2 [Drive Station] + +usb:v0411p012C* + ID_MODEL_FROM_DATABASE=SATA Bridge + +usb:v0411p012E* + ID_MODEL_FROM_DATABASE=WLI-UC-AG300N Wireless LAN Adapter + +usb:v0411p0148* + ID_MODEL_FROM_DATABASE=WLI-UC-G300HP Wireless LAN Adapter + +usb:v0411p0150* + ID_MODEL_FROM_DATABASE=WLP-UC-AG300 Wireless LAN Adapter + +usb:v0411p0157* + ID_MODEL_FROM_DATABASE=External Hard Drive HD-PEU2 + +usb:v0411p0158* + ID_MODEL_FROM_DATABASE=WLI-UC-GNHP Wireless LAN Adapter + +usb:v0411p015D* + ID_MODEL_FROM_DATABASE=WLI-UC-GN Wireless LAN Adapter [Ralink RT3070] + +usb:v0411p016F* + ID_MODEL_FROM_DATABASE=WLI-UC-G301N Wireless LAN Adapter [Ralink RT3072] + +usb:v0411p017F* + ID_MODEL_FROM_DATABASE=Sony UWA-BR100 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] + +usb:v0411p019E* + ID_MODEL_FROM_DATABASE=WLI-UC-GNP Wireless LAN Adapter + +usb:v0411p01A1* + ID_MODEL_FROM_DATABASE=MiniStation Metro + +usb:v0411p01A2* + ID_MODEL_FROM_DATABASE=WLI-UC-GNM Wireless LAN Adapter [Ralink RT8070] + +usb:v0411p01BA* + ID_MODEL_FROM_DATABASE=SATA Bridge + +usb:v0411p01DC* + ID_MODEL_FROM_DATABASE=Ultra-Slim Portable DVD Writer (DVSM-PC58U2V) + +usb:v0411p01DE* + ID_MODEL_FROM_DATABASE=External Hard Drive HD-PCTU3 [Buffalo MiniStation] + +usb:v0411p01EA* + ID_MODEL_FROM_DATABASE=SATA Bridge + +usb:v0411p01EE* + ID_MODEL_FROM_DATABASE=WLI-UC-GNM2 Wireless LAN Adapter [Ralink RT3070] + +usb:v0411p01F1* + ID_MODEL_FROM_DATABASE=SATA Adapter [HD-LBU3] + +usb:v0411p01FD* + ID_MODEL_FROM_DATABASE=WLI-UC-G450 Wireless LAN Adapter + +usb:v0411p027E* + ID_MODEL_FROM_DATABASE=HD-LCU3 + +usb:v0412* + ID_VENDOR_FROM_DATABASE=Award Software International + +usb:v0413* + ID_VENDOR_FROM_DATABASE=Leadtek Research, Inc. + +usb:v0413p1310* + ID_MODEL_FROM_DATABASE=WinFast TV - NTSC + FM + +usb:v0413p1311* + ID_MODEL_FROM_DATABASE=WinFast TV - NTSC + MTS + FM + +usb:v0413p1312* + ID_MODEL_FROM_DATABASE=WinFast TV - PAL BG + FM + +usb:v0413p1313* + ID_MODEL_FROM_DATABASE=WinFast TV - PAL BG+TXT + FM + +usb:v0413p1314* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL I + +usb:v0413p1315* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL I+TXT + +usb:v0413p1316* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL DK + +usb:v0413p1317* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL DK+TXT + +usb:v0413p1318* + ID_MODEL_FROM_DATABASE=WinFast TV - PAL I/DK + FM + +usb:v0413p1319* + ID_MODEL_FROM_DATABASE=WinFast TV - PAL N + FM + +usb:v0413p131A* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM LL + +usb:v0413p131B* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM LL+TXT + +usb:v0413p131C* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM DK + +usb:v0413p131D* + ID_MODEL_FROM_DATABASE=WinFast TV - SECAM DK + TXT + FM + +usb:v0413p131E* + ID_MODEL_FROM_DATABASE=WinFast TV - NTSC Japan + FM + +usb:v0413p1320* + ID_MODEL_FROM_DATABASE=WinFast TV - NTSC + +usb:v0413p1321* + ID_MODEL_FROM_DATABASE=WinFast TV - NTSC + MTS + +usb:v0413p1322* + ID_MODEL_FROM_DATABASE=WinFast TV - PAL BG + +usb:v0413p1323* + ID_MODEL_FROM_DATABASE=WinFast TV - PAL BG+TXT + +usb:v0413p1324* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL I + +usb:v0413p1325* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL I+TXT + +usb:v0413p1326* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL DK + +usb:v0413p1327* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP PAL DK+TXT + +usb:v0413p1328* + ID_MODEL_FROM_DATABASE=WinFast TV - PAL I/DK + +usb:v0413p1329* + ID_MODEL_FROM_DATABASE=WinFast TV - PAL N + +usb:v0413p132A* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM LL + +usb:v0413p132B* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM LL+TXT + +usb:v0413p132C* + ID_MODEL_FROM_DATABASE=WinFast TV Audio - PHP SECAM DK + +usb:v0413p132D* + ID_MODEL_FROM_DATABASE=WinFast TV - SECAM DK + TXT + +usb:v0413p132E* + ID_MODEL_FROM_DATABASE=WinFast TV - NTSC Japan + +usb:v0413p6023* + ID_MODEL_FROM_DATABASE=EMP Audio Device + +usb:v0413p6024* + ID_MODEL_FROM_DATABASE=WinFast PalmTop/Novo TV Video + +usb:v0413p6025* + ID_MODEL_FROM_DATABASE=WinFast DTV Dongle (cold state) + +usb:v0413p6026* + ID_MODEL_FROM_DATABASE=WinFast DTV Dongle (warm state) + +usb:v0413p6029* + ID_MODEL_FROM_DATABASE=WinFast DTV Dongle Gold + +usb:v0413p6125* + ID_MODEL_FROM_DATABASE=WinFast DTV Dongle + +usb:v0413p6126* + ID_MODEL_FROM_DATABASE=WinFast DTV Dongle BDA Driver + +usb:v0413p6A03* + ID_MODEL_FROM_DATABASE=RTL2832 [WinFast DTV Dongle Mini] + +usb:v0413p6F00* + ID_MODEL_FROM_DATABASE=WinFast DTV Dongle (STK7700P based) + +usb:v0414* + ID_VENDOR_FROM_DATABASE=Giga-Byte Technology Co., Ltd + +usb:v0416* + ID_VENDOR_FROM_DATABASE=Winbond Electronics Corp. + +usb:v0416p0035* + ID_MODEL_FROM_DATABASE=W89C35 802.11bg WLAN Adapter + +usb:v0416p0101* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0416p0961* + ID_MODEL_FROM_DATABASE=AVL Flash Card Reader + +usb:v0416p3810* + ID_MODEL_FROM_DATABASE=Smart Card Controller + +usb:v0416p3811* + ID_MODEL_FROM_DATABASE=Generic Controller - Single interface + +usb:v0416p3812* + ID_MODEL_FROM_DATABASE=Smart Card Controller_2Interface + +usb:v0416p3813* + ID_MODEL_FROM_DATABASE=Panel Display + +usb:v0416p5011* + ID_MODEL_FROM_DATABASE=Virtual Com Port + +usb:v0416p5518* + ID_MODEL_FROM_DATABASE=4-Port Hub + +usb:v0416p551A* + ID_MODEL_FROM_DATABASE=PC Sync Keypad + +usb:v0416p551B* + ID_MODEL_FROM_DATABASE=PC Async Keypad + +usb:v0416p551C* + ID_MODEL_FROM_DATABASE=Sync Tenkey + +usb:v0416p551D* + ID_MODEL_FROM_DATABASE=Async Tenkey + +usb:v0416p551E* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0416p551F* + ID_MODEL_FROM_DATABASE=Keyboard w/ Sys and Media + +usb:v0416p5521* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0416p6481* + ID_MODEL_FROM_DATABASE=16-bit Scanner + +usb:v0416p7721* + ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer + +usb:v0416p7722* + ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer + +usb:v0416p7723* + ID_MODEL_FROM_DATABASE=SD Card Reader + +usb:v0416pC141* + ID_MODEL_FROM_DATABASE=Barcode Scanner + +usb:v0417* + ID_VENDOR_FROM_DATABASE=Symbios Logic + +usb:v0418* + ID_VENDOR_FROM_DATABASE=AST Research + +usb:v0419* + ID_VENDOR_FROM_DATABASE=Samsung Info. Systems America, Inc. + +usb:v0419p0001* + ID_MODEL_FROM_DATABASE=IrDA Remote Controller / Creative Cordless Mouse + +usb:v0419p0600* + ID_MODEL_FROM_DATABASE=Desktop Wireless 6000 + +usb:v0419p2694* + ID_MODEL_FROM_DATABASE=Laila + +usb:v0419p3001* + ID_MODEL_FROM_DATABASE=Xerox P1202 Laser Printer + +usb:v0419p3003* + ID_MODEL_FROM_DATABASE=Olivetti PG L12L + +usb:v0419p3201* + ID_MODEL_FROM_DATABASE=Docuprint P8ex + +usb:v0419p3404* + ID_MODEL_FROM_DATABASE=SCX-5x12 series + +usb:v0419p3406* + ID_MODEL_FROM_DATABASE=MFP 830 series + +usb:v0419p3407* + ID_MODEL_FROM_DATABASE=ML-912 + +usb:v0419p3601* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v0419p3602* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v0419p4602* + ID_MODEL_FROM_DATABASE=Remote NDIS Network Device + +usb:v0419p8001* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0419p8002* + ID_MODEL_FROM_DATABASE=SyncMaster HID Monitor Control + +usb:v0419pAA03* + ID_MODEL_FROM_DATABASE=SDAS-3 MP3 Player + +usb:v041A* + ID_VENDOR_FROM_DATABASE=Phoenix Technologies, Ltd + +usb:v041B* + ID_VENDOR_FROM_DATABASE=d'TV + +usb:v041D* + ID_VENDOR_FROM_DATABASE=S3, Inc. + +usb:v041E* + ID_VENDOR_FROM_DATABASE=Creative Technology, Ltd + +usb:v041Ep0414* + ID_MODEL_FROM_DATABASE=HS-720 Headset + +usb:v041Ep1002* + ID_MODEL_FROM_DATABASE=Nomad II + +usb:v041Ep1003* + ID_MODEL_FROM_DATABASE=Blaster GamePad Cobra + +usb:v041Ep1050* + ID_MODEL_FROM_DATABASE=GamePad Cobra + +usb:v041Ep1053* + ID_MODEL_FROM_DATABASE=Mouse Gamer HD7600L + +usb:v041Ep200C* + ID_MODEL_FROM_DATABASE=MuVo V100 + +usb:v041Ep2020* + ID_MODEL_FROM_DATABASE=Zen X-Fi 2 + +usb:v041Ep2029* + ID_MODEL_FROM_DATABASE=ZiiO + +usb:v041Ep2801* + ID_MODEL_FROM_DATABASE=Prodikeys PC-MIDI multifunction keyboard + +usb:v041Ep3000* + ID_MODEL_FROM_DATABASE=SoundBlaster Extigy + +usb:v041Ep3002* + ID_MODEL_FROM_DATABASE=SB External Composite Device + +usb:v041Ep3010* + ID_MODEL_FROM_DATABASE=SoundBlaster MP3+ + +usb:v041Ep3014* + ID_MODEL_FROM_DATABASE=SB External Composite Device + +usb:v041Ep3015* + ID_MODEL_FROM_DATABASE=Sound Blaster Digital Music LX + +usb:v041Ep3020* + ID_MODEL_FROM_DATABASE=SoundBlaster Audigy 2 NX + +usb:v041Ep3030* + ID_MODEL_FROM_DATABASE=SB External Composite Device + +usb:v041Ep3040* + ID_MODEL_FROM_DATABASE=SoundBlaster Live! 24-bit External SB0490 + +usb:v041Ep3060* + ID_MODEL_FROM_DATABASE=Sound Blaster Audigy 2 ZS External + +usb:v041Ep3061* + ID_MODEL_FROM_DATABASE=SoundBlaster Audigy 2 ZS Video Editor + +usb:v041Ep3090* + ID_MODEL_FROM_DATABASE=Sound Blaster Digital Music SX + +usb:v041Ep30D0* + ID_MODEL_FROM_DATABASE=Xmod + +usb:v041Ep30D3* + ID_MODEL_FROM_DATABASE=Sound Blaster Play! + +usb:v041Ep3100* + ID_MODEL_FROM_DATABASE=IR Receiver (SB0540) + +usb:v041Ep3121* + ID_MODEL_FROM_DATABASE=WoW tap chat + +usb:v041Ep3220* + ID_MODEL_FROM_DATABASE=Sound Blaster Tactic(3D) Sigma sound card + +usb:v041Ep3232* + ID_MODEL_FROM_DATABASE=Sound Blaster Premium HD [SBX] + +usb:v041Ep3237* + ID_MODEL_FROM_DATABASE=SB X-Fi Surround 5.1 Pro + +usb:v041Ep3F00* + ID_MODEL_FROM_DATABASE=E-Mu Xboard 25 MIDI Controller + +usb:v041Ep3F02* + ID_MODEL_FROM_DATABASE=E-Mu 0202 + +usb:v041Ep3F04* + ID_MODEL_FROM_DATABASE=E-Mu 0404 + +usb:v041Ep3F07* + ID_MODEL_FROM_DATABASE=E-Mu Xmidi 1x1 + +usb:v041Ep3F0E* + ID_MODEL_FROM_DATABASE=Xmidi 1x1 Tab + +usb:v041Ep4003* + ID_MODEL_FROM_DATABASE=VideoBlaster Webcam Go Plus [W9967CF] + +usb:v041Ep4004* + ID_MODEL_FROM_DATABASE=Nomad II MG + +usb:v041Ep4005* + ID_MODEL_FROM_DATABASE=Webcam Blaster Go ES + +usb:v041Ep4007* + ID_MODEL_FROM_DATABASE=Go Mini + +usb:v041Ep400A* + ID_MODEL_FROM_DATABASE=PC-Cam 300 + +usb:v041Ep400B* + ID_MODEL_FROM_DATABASE=PC-Cam 600 + +usb:v041Ep400C* + ID_MODEL_FROM_DATABASE=Webcam 5 [pwc] + +usb:v041Ep400D* + ID_MODEL_FROM_DATABASE=Webcam PD1001 + +usb:v041Ep400F* + ID_MODEL_FROM_DATABASE=PC-CAM 550 (Composite) + +usb:v041Ep4011* + ID_MODEL_FROM_DATABASE=Webcam PRO eX + +usb:v041Ep4012* + ID_MODEL_FROM_DATABASE=PC-CAM350 + +usb:v041Ep4013* + ID_MODEL_FROM_DATABASE=PC-Cam 750 + +usb:v041Ep4015* + ID_MODEL_FROM_DATABASE=CardCam Value + +usb:v041Ep4016* + ID_MODEL_FROM_DATABASE=CardCam + +usb:v041Ep4017* + ID_MODEL_FROM_DATABASE=Webcam Mobile [PD1090] + +usb:v041Ep4018* + ID_MODEL_FROM_DATABASE=Webcam Vista [PD1100] + +usb:v041Ep4019* + ID_MODEL_FROM_DATABASE=Audio Device + +usb:v041Ep401A* + ID_MODEL_FROM_DATABASE=Webcam Vista [PD1100] + +usb:v041Ep401C* + ID_MODEL_FROM_DATABASE=Webcam NX [PD1110] + +usb:v041Ep401D* + ID_MODEL_FROM_DATABASE=Webcam NX Ultra + +usb:v041Ep401E* + ID_MODEL_FROM_DATABASE=Webcam NX Pro + +usb:v041Ep401F* + ID_MODEL_FROM_DATABASE=Webcam Notebook [PD1171] + +usb:v041Ep4020* + ID_MODEL_FROM_DATABASE=Webcam NX + +usb:v041Ep4021* + ID_MODEL_FROM_DATABASE=Webcam NX Ultra + +usb:v041Ep4022* + ID_MODEL_FROM_DATABASE=Webcam NX Pro + +usb:v041Ep4028* + ID_MODEL_FROM_DATABASE=Vista Plus cam [VF0090] + +usb:v041Ep4029* + ID_MODEL_FROM_DATABASE=Webcam Live! + +usb:v041Ep402F* + ID_MODEL_FROM_DATABASE=DC-CAM 3000Z + +usb:v041Ep4034* + ID_MODEL_FROM_DATABASE=Webcam Instant + +usb:v041Ep4035* + ID_MODEL_FROM_DATABASE=Webcam Instant + +usb:v041Ep4036* + ID_MODEL_FROM_DATABASE=Webcam Live!/Live! Pro + +usb:v041Ep4037* + ID_MODEL_FROM_DATABASE=Webcam Live! + +usb:v041Ep4038* + ID_MODEL_FROM_DATABASE=ORITE CCD Webcam [PC370R] + +usb:v041Ep4039* + ID_MODEL_FROM_DATABASE=Webcam Live! Effects + +usb:v041Ep403A* + ID_MODEL_FROM_DATABASE=Webcam NX Pro 2 + +usb:v041Ep403B* + ID_MODEL_FROM_DATABASE=Creative Webcam Vista [VF0010] + +usb:v041Ep403C* + ID_MODEL_FROM_DATABASE=Webcam Live! Ultra + +usb:v041Ep403D* + ID_MODEL_FROM_DATABASE=Webcam Notebook Ultra + +usb:v041Ep403E* + ID_MODEL_FROM_DATABASE=Webcam Vista Plus + +usb:v041Ep4041* + ID_MODEL_FROM_DATABASE=Webcam Live! Motion + +usb:v041Ep4043* + ID_MODEL_FROM_DATABASE=Vibra Plus Webcam + +usb:v041Ep4045* + ID_MODEL_FROM_DATABASE=Live! Cam Voice + +usb:v041Ep4049* + ID_MODEL_FROM_DATABASE=Live! Cam Voice + +usb:v041Ep4051* + ID_MODEL_FROM_DATABASE=Live! Cam Notebook Pro [VF0250] + +usb:v041Ep4052* + ID_MODEL_FROM_DATABASE=Live! Cam Vista IM + +usb:v041Ep4053* + ID_MODEL_FROM_DATABASE=Live! Cam Video IM + +usb:v041Ep4054* + ID_MODEL_FROM_DATABASE=Live! Cam Video IM + +usb:v041Ep4055* + ID_MODEL_FROM_DATABASE=Live! Cam Video IM Pro + +usb:v041Ep4056* + ID_MODEL_FROM_DATABASE=Live! Cam Video IM Pro + +usb:v041Ep4057* + ID_MODEL_FROM_DATABASE=Live! Cam Optia + +usb:v041Ep4058* + ID_MODEL_FROM_DATABASE=Live! Cam Optia AF + +usb:v041Ep405F* + ID_MODEL_FROM_DATABASE=WebCam Vista (VF0330) + +usb:v041Ep4061* + ID_MODEL_FROM_DATABASE=Live! Cam Notebook Pro [VF0400] + +usb:v041Ep4063* + ID_MODEL_FROM_DATABASE=Live! Cam Video IM Pro + +usb:v041Ep4068* + ID_MODEL_FROM_DATABASE=Live! Cam Notebook [VF0470] + +usb:v041Ep406C* + ID_MODEL_FROM_DATABASE=Live! Cam Sync [VF0520] + +usb:v041Ep4083* + ID_MODEL_FROM_DATABASE=Live! Cam Socialize [VF0640] + +usb:v041Ep4087* + ID_MODEL_FROM_DATABASE=Live! Cam Socialize HD 1080 [VF0680] + +usb:v041Ep4088* + ID_MODEL_FROM_DATABASE=Live! Cam Chat HD [VF0700] + +usb:v041Ep4095* + ID_MODEL_FROM_DATABASE=Live! Cam Sync HD [VF0770] + +usb:v041Ep4097* + ID_MODEL_FROM_DATABASE=Live! Cam Chat HD [VF0700] + +usb:v041Ep4100* + ID_MODEL_FROM_DATABASE=Nomad Jukebox 2 + +usb:v041Ep4101* + ID_MODEL_FROM_DATABASE=Nomad Jukebox 3 + +usb:v041Ep4102* + ID_MODEL_FROM_DATABASE=NOMAD MuVo^2 + +usb:v041Ep4106* + ID_MODEL_FROM_DATABASE=Nomad MuVo + +usb:v041Ep4107* + ID_MODEL_FROM_DATABASE=NOMAD MuVo + +usb:v041Ep4108* + ID_MODEL_FROM_DATABASE=Nomad Jukebox Zen + +usb:v041Ep4109* + ID_MODEL_FROM_DATABASE=Nomad Jukebox Zen NX + +usb:v041Ep410B* + ID_MODEL_FROM_DATABASE=Nomad Jukebox Zen USB 2.0 + +usb:v041Ep410C* + ID_MODEL_FROM_DATABASE=Nomad MuVo NX + +usb:v041Ep410F* + ID_MODEL_FROM_DATABASE=NOMAD MuVo^2 (Flash) + +usb:v041Ep4110* + ID_MODEL_FROM_DATABASE=Nomad Jukebox Zen Xtra + +usb:v041Ep4111* + ID_MODEL_FROM_DATABASE=Dell Digital Jukebox + +usb:v041Ep4116* + ID_MODEL_FROM_DATABASE=MuVo^2 + +usb:v041Ep4117* + ID_MODEL_FROM_DATABASE=Nomad MuVo TX + +usb:v041Ep411B* + ID_MODEL_FROM_DATABASE=Zen Touch + +usb:v041Ep411C* + ID_MODEL_FROM_DATABASE=Nomad MuVo USB 2.0 + +usb:v041Ep411D* + ID_MODEL_FROM_DATABASE=Zen + +usb:v041Ep411E* + ID_MODEL_FROM_DATABASE=Zen Micro + +usb:v041Ep4120* + ID_MODEL_FROM_DATABASE=Nomad MuVo TX FM + +usb:v041Ep4123* + ID_MODEL_FROM_DATABASE=Zen Portable Media Center + +usb:v041Ep4124* + ID_MODEL_FROM_DATABASE=MuVo^2 FM (uHDD) + +usb:v041Ep4126* + ID_MODEL_FROM_DATABASE=Dell DJ (2nd gen) + +usb:v041Ep4127* + ID_MODEL_FROM_DATABASE=Dell DJ + +usb:v041Ep4128* + ID_MODEL_FROM_DATABASE=NOMAD Jukebox Zen Xtra (mtp) + +usb:v041Ep412B* + ID_MODEL_FROM_DATABASE=MuVo N200 with FM radio + +usb:v041Ep412F* + ID_MODEL_FROM_DATABASE=Dell Digital Jukebox 2.Gen + +usb:v041Ep4130* + ID_MODEL_FROM_DATABASE=Zen Micro (mtp) + +usb:v041Ep4131* + ID_MODEL_FROM_DATABASE=DAP-HD0014 [Zen Touch] (MTP) + +usb:v041Ep4133* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v041Ep4134* + ID_MODEL_FROM_DATABASE=Zen Neeon + +usb:v041Ep4136* + ID_MODEL_FROM_DATABASE=Zen Sleek + +usb:v041Ep4137* + ID_MODEL_FROM_DATABASE=Zen Sleek (mtp) + +usb:v041Ep4139* + ID_MODEL_FROM_DATABASE=Zen Nano Plus + +usb:v041Ep413C* + ID_MODEL_FROM_DATABASE=Zen MicroPhoto + +usb:v041Ep4150* + ID_MODEL_FROM_DATABASE=Zen V (MTP) + +usb:v041Ep4151* + ID_MODEL_FROM_DATABASE=Zen Vision:M (mtp) + +usb:v041Ep4152* + ID_MODEL_FROM_DATABASE=Zen V Plus + +usb:v041Ep4153* + ID_MODEL_FROM_DATABASE=Zen Vision W + +usb:v041Ep4154* + ID_MODEL_FROM_DATABASE=Zen Stone + +usb:v041Ep4155* + ID_MODEL_FROM_DATABASE=Zen Stone plus + +usb:v041Ep4157* + ID_MODEL_FROM_DATABASE=Zen (MTP) + +usb:v041Ep500F* + ID_MODEL_FROM_DATABASE=Broadband Blaster 8012U-V + +usb:v041Ep5015* + ID_MODEL_FROM_DATABASE=TECOM Bluetooth Device + +usb:v041EpFFFF* + ID_MODEL_FROM_DATABASE=Webcam Live! Ultra + +usb:v041F* + ID_VENDOR_FROM_DATABASE=LCS Telegraphics + +usb:v0420* + ID_VENDOR_FROM_DATABASE=Chips and Technologies + +usb:v0420p1307* + ID_MODEL_FROM_DATABASE=Celly SIM Card Reader + +usb:v0421* + ID_VENDOR_FROM_DATABASE=Nokia Mobile Phones + +usb:v0421p0001* + ID_MODEL_FROM_DATABASE=E61i (PC Suite mode) + +usb:v0421p0018* + ID_MODEL_FROM_DATABASE=6288 GSM Smartphone + +usb:v0421p0019* + ID_MODEL_FROM_DATABASE=6288 GSM Smartphone (imaging mode) + +usb:v0421p001A* + ID_MODEL_FROM_DATABASE=6288 GSM Smartphone (file transfer mode) + +usb:v0421p0024* + ID_MODEL_FROM_DATABASE=5610 XpressMusic (Storage mode) + +usb:v0421p0025* + ID_MODEL_FROM_DATABASE=5610 XpressMusic (PC Suite mode) + +usb:v0421p0028* + ID_MODEL_FROM_DATABASE=5610 XpressMusic (Imaging mode) + +usb:v0421p002D* + ID_MODEL_FROM_DATABASE=6120 Phone (Mass storage mode) + +usb:v0421p002E* + ID_MODEL_FROM_DATABASE=6120 Phone (Media-Player mode) + +usb:v0421p002F* + ID_MODEL_FROM_DATABASE=6120 Phone (PC-Suite mode) + +usb:v0421p0042* + ID_MODEL_FROM_DATABASE=E51 (PC Suite mode) + +usb:v0421p0064* + ID_MODEL_FROM_DATABASE=3109c GSM Phone + +usb:v0421p006B* + ID_MODEL_FROM_DATABASE=5310 Xpress Music (PC Suite mode) + +usb:v0421p006C* + ID_MODEL_FROM_DATABASE=5310 Xpress music (Storage mode) + +usb:v0421p006D* + ID_MODEL_FROM_DATABASE=N95 (Storage mode) + +usb:v0421p006E* + ID_MODEL_FROM_DATABASE=N95 (Multimedia mode) + +usb:v0421p006F* + ID_MODEL_FROM_DATABASE=N95 (Printing mode) + +usb:v0421p0070* + ID_MODEL_FROM_DATABASE=N95 (PC Suite mode) + +usb:v0421p0096* + ID_MODEL_FROM_DATABASE=N810 Internet Tablet + +usb:v0421p00AA* + ID_MODEL_FROM_DATABASE=E71 (Mass storage mode) + +usb:v0421p00AB* + ID_MODEL_FROM_DATABASE=E71 (PC Suite mode) + +usb:v0421p00E4* + ID_MODEL_FROM_DATABASE=E71 (Media transfer mode) + +usb:v0421p0103* + ID_MODEL_FROM_DATABASE=ADL Flashing Engine AVALON Parent + +usb:v0421p0104* + ID_MODEL_FROM_DATABASE=ADL Re-Flashing Engine Parent + +usb:v0421p0105* + ID_MODEL_FROM_DATABASE=Nokia Firmware Upgrade Mode + +usb:v0421p0106* + ID_MODEL_FROM_DATABASE=ROM Parent + +usb:v0421p010D* + ID_MODEL_FROM_DATABASE=E75 (Storage Mode) + +usb:v0421p010E* + ID_MODEL_FROM_DATABASE=E75 (PC Suite mode) + +usb:v0421p010F* + ID_MODEL_FROM_DATABASE=E75 (Media transfer mode) + +usb:v0421p0110* + ID_MODEL_FROM_DATABASE=E75 (Imaging Mode) + +usb:v0421p0154* + ID_MODEL_FROM_DATABASE=5800 XpressMusic (PC Suite mode) + +usb:v0421p0155* + ID_MODEL_FROM_DATABASE=5800 XpressMusic (Multimedia mode) + +usb:v0421p0156* + ID_MODEL_FROM_DATABASE=5800 XpressMusic (Storage mode) + +usb:v0421p0157* + ID_MODEL_FROM_DATABASE=5800 XpressMusic (Imaging mode) + +usb:v0421p0199* + ID_MODEL_FROM_DATABASE=6700 Classic (msc) + +usb:v0421p019A* + ID_MODEL_FROM_DATABASE=6700 Classic (PC Suite) + +usb:v0421p019B* + ID_MODEL_FROM_DATABASE=6700 Classic (mtp) + +usb:v0421p01B0* + ID_MODEL_FROM_DATABASE=6303 classic Phone (PC Suite mode) + +usb:v0421p01B1* + ID_MODEL_FROM_DATABASE=6303 classic Phone (Mass storage mode) + +usb:v0421p01B2* + ID_MODEL_FROM_DATABASE=6303 classic Phone (Printing and media mode) + +usb:v0421p01C7* + ID_MODEL_FROM_DATABASE=N900 (Storage Mode) + +usb:v0421p01C8* + ID_MODEL_FROM_DATABASE=N900 (PC-Suite Mode) + +usb:v0421p0228* + ID_MODEL_FROM_DATABASE=5530 XpressMusic + +usb:v0421p023A* + ID_MODEL_FROM_DATABASE=6730 Classic + +usb:v0421p026A* + ID_MODEL_FROM_DATABASE=N97 (mass storage) + +usb:v0421p026B* + ID_MODEL_FROM_DATABASE=N97 (Multimedia) + +usb:v0421p026C* + ID_MODEL_FROM_DATABASE=N97 (PC Suite) + +usb:v0421p026D* + ID_MODEL_FROM_DATABASE=N97 (Pictures) + +usb:v0421p0295* + ID_MODEL_FROM_DATABASE=660i/6600i Slide Phone (Mass Storage) + +usb:v0421p0297* + ID_MODEL_FROM_DATABASE=660i/6600i Slide Phone (Still Image) + +usb:v0421p02E1* + ID_MODEL_FROM_DATABASE=5230 (Storage mode) + +usb:v0421p02E2* + ID_MODEL_FROM_DATABASE=5230 (Multimedia mode) + +usb:v0421p02E3* + ID_MODEL_FROM_DATABASE=5230 (PC-Suite mode) + +usb:v0421p02E4* + ID_MODEL_FROM_DATABASE=5230 (Imaging mode) + +usb:v0421p0360* + ID_MODEL_FROM_DATABASE=C1-01 Ovi Suite Mode + +usb:v0421p0396* + ID_MODEL_FROM_DATABASE=C7-00 (Modem mode) + +usb:v0421p03A4* + ID_MODEL_FROM_DATABASE=C5 (Storage mode) + +usb:v0421p03C0* + ID_MODEL_FROM_DATABASE=C7-00 (Mass storage mode) + +usb:v0421p03C1* + ID_MODEL_FROM_DATABASE=C7-00 (Media transfer mode) + +usb:v0421p03C2* + ID_MODEL_FROM_DATABASE=Sim + +usb:v0421p03CD* + ID_MODEL_FROM_DATABASE=C7-00 (Nokia Suite mode) + +usb:v0421p03D1* + ID_MODEL_FROM_DATABASE=N950 + +usb:v0421p0400* + ID_MODEL_FROM_DATABASE=7600 Phone Parent + +usb:v0421p0401* + ID_MODEL_FROM_DATABASE=6650 GSM Phone + +usb:v0421p0402* + ID_MODEL_FROM_DATABASE=6255 Phone Parent + +usb:v0421p0404* + ID_MODEL_FROM_DATABASE=5510 + +usb:v0421p0405* + ID_MODEL_FROM_DATABASE=9500 GSM Communicator + +usb:v0421p0407* + ID_MODEL_FROM_DATABASE=Music Player HDR-1(tm) + +usb:v0421p040B* + ID_MODEL_FROM_DATABASE=N-Gage GSM Phone + +usb:v0421p040D* + ID_MODEL_FROM_DATABASE=6620 Phone Parent + +usb:v0421p040E* + ID_MODEL_FROM_DATABASE=6651 Phone Parent + +usb:v0421p040F* + ID_MODEL_FROM_DATABASE=6230 GSM Phone + +usb:v0421p0410* + ID_MODEL_FROM_DATABASE=6630 Imaging Smartphone + +usb:v0421p0411* + ID_MODEL_FROM_DATABASE=7610 Phone Parent + +usb:v0421p0413* + ID_MODEL_FROM_DATABASE=6260 Phone Parent + +usb:v0421p0414* + ID_MODEL_FROM_DATABASE=7370 + +usb:v0421p0415* + ID_MODEL_FROM_DATABASE=9300 GSM Smartphone + +usb:v0421p0416* + ID_MODEL_FROM_DATABASE=6170 Phone Parent + +usb:v0421p0417* + ID_MODEL_FROM_DATABASE=7270 Phone Parent + +usb:v0421p0418* + ID_MODEL_FROM_DATABASE=E70 (PC Suite mode) + +usb:v0421p0419* + ID_MODEL_FROM_DATABASE=E60 (PC Suite mode) + +usb:v0421p041A* + ID_MODEL_FROM_DATABASE=9500 GSM Communicator (RNDIS) + +usb:v0421p041B* + ID_MODEL_FROM_DATABASE=9300 GSM Smartphone (RNDIS) + +usb:v0421p041C* + ID_MODEL_FROM_DATABASE=7710 Phone Parent + +usb:v0421p041D* + ID_MODEL_FROM_DATABASE=6670 Phone Parent + +usb:v0421p041E* + ID_MODEL_FROM_DATABASE=6680 + +usb:v0421p041F* + ID_MODEL_FROM_DATABASE=6235 Phone Parent + +usb:v0421p0421* + ID_MODEL_FROM_DATABASE=3230 Phone Parent + +usb:v0421p0422* + ID_MODEL_FROM_DATABASE=6681 Phone Parent + +usb:v0421p0423* + ID_MODEL_FROM_DATABASE=6682 Phone Parent + +usb:v0421p0428* + ID_MODEL_FROM_DATABASE=6230i Modem + +usb:v0421p0429* + ID_MODEL_FROM_DATABASE=6230i MultiMedia Card + +usb:v0421p0431* + ID_MODEL_FROM_DATABASE=770 Internet Tablet + +usb:v0421p0432* + ID_MODEL_FROM_DATABASE=N90 Phone Parent + +usb:v0421p0435* + ID_MODEL_FROM_DATABASE=E70 (IP Passthrough/RNDIS mode) + +usb:v0421p0436* + ID_MODEL_FROM_DATABASE=E60 (IP Passthrough/RNDIS mode) + +usb:v0421p0437* + ID_MODEL_FROM_DATABASE=6265 Phone Parent + +usb:v0421p043A* + ID_MODEL_FROM_DATABASE=N70 USB Phone Parent + +usb:v0421p043B* + ID_MODEL_FROM_DATABASE=3155 Phone Parent + +usb:v0421p043C* + ID_MODEL_FROM_DATABASE=6155 Phone Parent + +usb:v0421p043D* + ID_MODEL_FROM_DATABASE=6270 Phone Parent + +usb:v0421p0443* + ID_MODEL_FROM_DATABASE=N70 Phone Parent + +usb:v0421p0444* + ID_MODEL_FROM_DATABASE=N91 + +usb:v0421p044C* + ID_MODEL_FROM_DATABASE=NM850iG Phone Parent + +usb:v0421p044D* + ID_MODEL_FROM_DATABASE=E61 (PC Suite mode) + +usb:v0421p044E* + ID_MODEL_FROM_DATABASE=E61 (Data Exchange mode) + +usb:v0421p044F* + ID_MODEL_FROM_DATABASE=E61 (IP Passthrough/RNDIS mode) + +usb:v0421p0453* + ID_MODEL_FROM_DATABASE=9300 Phone Parent + +usb:v0421p0456* + ID_MODEL_FROM_DATABASE=6111 Phone Parent + +usb:v0421p0457* + ID_MODEL_FROM_DATABASE=6111 Phone (Printing mode) + +usb:v0421p045A* + ID_MODEL_FROM_DATABASE=6280 Phone Parent + +usb:v0421p045D* + ID_MODEL_FROM_DATABASE=6282 Phone Parent + +usb:v0421p046E* + ID_MODEL_FROM_DATABASE=6110 Navigator + +usb:v0421p0471* + ID_MODEL_FROM_DATABASE=6110 Navigator + +usb:v0421p0485* + ID_MODEL_FROM_DATABASE=MTP Device + +usb:v0421p04B9* + ID_MODEL_FROM_DATABASE=5300 + +usb:v0421p04BC* + ID_MODEL_FROM_DATABASE=5200 (Nokia mode) + +usb:v0421p04BD* + ID_MODEL_FROM_DATABASE=5200 (Storage mode) + +usb:v0421p04BE* + ID_MODEL_FROM_DATABASE=5200 (MTP mode) + +usb:v0421p04C3* + ID_MODEL_FROM_DATABASE=N800 Internet Tablet + +usb:v0421p04CE* + ID_MODEL_FROM_DATABASE=E90 Communicator (PC Suite mode) + +usb:v0421p04CF* + ID_MODEL_FROM_DATABASE=E90 Communicator (Storage mode) + +usb:v0421p04F0* + ID_MODEL_FROM_DATABASE=Nokia N95 (PC Suite mode) + +usb:v0421p04F9* + ID_MODEL_FROM_DATABASE=6300 (PC Suite mode) + +usb:v0421p0508* + ID_MODEL_FROM_DATABASE=E65 (PC Suite mode) + +usb:v0421p0509* + ID_MODEL_FROM_DATABASE=E65 (Storage mode) + +usb:v0421p0518* + ID_MODEL_FROM_DATABASE=N9 Phone + +usb:v0421p054D* + ID_MODEL_FROM_DATABASE=C2-01 + +usb:v0421p0600* + ID_MODEL_FROM_DATABASE=Digital Pen SU-1B + +usb:v0421p0610* + ID_MODEL_FROM_DATABASE=CS-15 (Internet Stick 3G modem) + +usb:v0421p0661* + ID_MODEL_FROM_DATABASE=Lumia 620/920 + +usb:v0421p0662* + ID_MODEL_FROM_DATABASE=301 Dual SIM (Mass Storage) + +usb:v0421p0663* + ID_MODEL_FROM_DATABASE=301 Dual SIM + +usb:v0421p069A* + ID_MODEL_FROM_DATABASE=130 [RM-1035] (Charging only) + +usb:v0421p06FC* + ID_MODEL_FROM_DATABASE=Lumia 640 Phone + +usb:v0421p0720* + ID_MODEL_FROM_DATABASE=X (RM-980) + +usb:v0421p0800* + ID_MODEL_FROM_DATABASE=Connectivity Cable DKU-5 + +usb:v0421p0801* + ID_MODEL_FROM_DATABASE=Data Cable DKU-6 + +usb:v0421p0802* + ID_MODEL_FROM_DATABASE=CA-42 Phone Parent + +usb:v0422* + ID_VENDOR_FROM_DATABASE=ADI Systems, Inc. + +usb:v0423* + ID_VENDOR_FROM_DATABASE=Computer Access Technology Corp. + +usb:v0423p000A* + ID_MODEL_FROM_DATABASE=NetMate Ethernet + +usb:v0423p000C* + ID_MODEL_FROM_DATABASE=NetMate2 Ethernet + +usb:v0423p000D* + ID_MODEL_FROM_DATABASE=USB Chief Analyzer + +usb:v0423p0100* + ID_MODEL_FROM_DATABASE=Generic Universal Protocol Analyzer + +usb:v0423p0101* + ID_MODEL_FROM_DATABASE=UPA USBTracer + +usb:v0423p0200* + ID_MODEL_FROM_DATABASE=Generic 10K Universal Protocol Analyzer + +usb:v0423p020A* + ID_MODEL_FROM_DATABASE=PETracer ML + +usb:v0423p0300* + ID_MODEL_FROM_DATABASE=Generic Universal Protocol Analyzer + +usb:v0423p0301* + ID_MODEL_FROM_DATABASE=2500H Tracer Trainer + +usb:v0423p030A* + ID_MODEL_FROM_DATABASE=PETracer x1 + +usb:v0423p1237* + ID_MODEL_FROM_DATABASE=Andromeda Hub + +usb:v0424* + ID_VENDOR_FROM_DATABASE=Microchip Technology, Inc. (formerly SMSC) + +usb:v0424p0001* + ID_MODEL_FROM_DATABASE=Integrated Hub + +usb:v0424p0140* + ID_MODEL_FROM_DATABASE=LPC47M14x hub + +usb:v0424p0ACD* + ID_MODEL_FROM_DATABASE=Sitecom Internal Multi Memory reader/writer MD-005 + +usb:v0424p0FDC* + ID_MODEL_FROM_DATABASE=Floppy + +usb:v0424p10CD* + ID_MODEL_FROM_DATABASE=Sitecom Internal Multi Memory reader/writer MD-005 + +usb:v0424p2020* + ID_MODEL_FROM_DATABASE=USB Hub + +usb:v0424p20CD* + ID_MODEL_FROM_DATABASE=Sitecom Internal Multi Memory reader/writer MD-005 + +usb:v0424p20FC* + ID_MODEL_FROM_DATABASE=6-in-1 Card Reader + +usb:v0424p2134* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0424p2228* + ID_MODEL_FROM_DATABASE=9-in-2 Card Reader + +usb:v0424p223A* + ID_MODEL_FROM_DATABASE=8-in-1 Card Reader + +usb:v0424p2503* + ID_MODEL_FROM_DATABASE=USB 2.0 Hub + +usb:v0424p2507* + ID_MODEL_FROM_DATABASE=hub + +usb:v0424p2512* + ID_MODEL_FROM_DATABASE=USB 2.0 Hub + +usb:v0424p2513* + ID_MODEL_FROM_DATABASE=2.0 Hub + +usb:v0424p2514* + ID_MODEL_FROM_DATABASE=USB 2.0 Hub + +usb:v0424p2517* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0424p2524* + ID_MODEL_FROM_DATABASE=USB MultiSwitch Hub + +usb:v0424p2602* + ID_MODEL_FROM_DATABASE=USB 2.0 Hub + +usb:v0424p2640* + ID_MODEL_FROM_DATABASE=USB 2.0 Hub + +usb:v0424p2660* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0424p2744* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0424p274D* + ID_MODEL_FROM_DATABASE=HTC Hub Controller + +usb:v0424p2807* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0424p3FCC* + ID_MODEL_FROM_DATABASE=RME MADIface + +usb:v0424p4041* + ID_MODEL_FROM_DATABASE=Hub and media card controller + +usb:v0424p4060* + ID_MODEL_FROM_DATABASE=Ultra Fast Media Reader + +usb:v0424p4064* + ID_MODEL_FROM_DATABASE=Ultra Fast Media Reader + +usb:v0424p4712* + ID_MODEL_FROM_DATABASE=USB4712 high-speed hub + +usb:v0424p4713* + ID_MODEL_FROM_DATABASE=USB4715 high-speed hub (2 ports disabled) + +usb:v0424p4714* + ID_MODEL_FROM_DATABASE=USB4715 high-speed hub (1 port disabled) + +usb:v0424p4715* + ID_MODEL_FROM_DATABASE=USB4715 high-speed hub + +usb:v0424p4910* + ID_MODEL_FROM_DATABASE=USB491x hub integrated functions (primary) + +usb:v0424p4912* + ID_MODEL_FROM_DATABASE=USB4912 high-speed hub (1 port disabled) + +usb:v0424p4914* + ID_MODEL_FROM_DATABASE=USB4914 high-speed hub + +usb:v0424p4916* + ID_MODEL_FROM_DATABASE=USB4916 high-speed hub + +usb:v0424p4920* + ID_MODEL_FROM_DATABASE=USB491x hub integrated functions (secondary) + +usb:v0424p4925* + ID_MODEL_FROM_DATABASE=USB4925 high-speed hub (primary upstream) + +usb:v0424p4927* + ID_MODEL_FROM_DATABASE=USB4927 high-speed hub (primary upstream) + +usb:v0424p4931* + ID_MODEL_FROM_DATABASE=USB4925/4927 high-speed hub (secondary upstream) + +usb:v0424p4940* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated WinUSB + +usb:v0424p4942* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated I2S audio port + +usb:v0424p4943* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated I2S audio + HID port + +usb:v0424p4944* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated serial port + +usb:v0424p4946* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated serial + I2S audio port + +usb:v0424p4947* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated serial + I2S audio + HID port + +usb:v0424p494A* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated WinUSB + I2S audio port + +usb:v0424p494B* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated WinUSB + I2S audio + HID port + +usb:v0424p494C* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated WinUSB + serial port + +usb:v0424p494E* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated WinUSB + serial + I2S audio port + +usb:v0424p494F* + ID_MODEL_FROM_DATABASE=USB47xx/49xx hub integrated WinUSB + serial + I2S audio + HID port + +usb:v0424p5434* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0424p5534* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0424p5744* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0424p5807* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0424p7500* + ID_MODEL_FROM_DATABASE=LAN7500 Ethernet 10/100/1000 Adapter + +usb:v0424p9500* + ID_MODEL_FROM_DATABASE=LAN9500/LAN9500i + +usb:v0424p9512* + ID_MODEL_FROM_DATABASE=SMC9512/9514 USB Hub + +usb:v0424p9514* + ID_MODEL_FROM_DATABASE=SMC9514 Hub + +usb:v0424p9904* + ID_MODEL_FROM_DATABASE=LAN9512/LAN9514 Ethernet 10/100 Adapter (SAL10) + +usb:v0424p9E00* + ID_MODEL_FROM_DATABASE=LAN9500A/LAN9500Ai + +usb:v0424pA700* + ID_MODEL_FROM_DATABASE=2 Port Hub + +usb:v0424pEC00* + ID_MODEL_FROM_DATABASE=SMSC9512/9514 Fast Ethernet Adapter + +usb:v0425* + ID_VENDOR_FROM_DATABASE=Motorola Semiconductors HK, Ltd + +usb:v0425p0101* + ID_MODEL_FROM_DATABASE=G-Tech Wireless Mouse & Keyboard + +usb:v0425pF102* + ID_MODEL_FROM_DATABASE=G-Tech U+P Wireless Mouse + +usb:v0426* + ID_VENDOR_FROM_DATABASE=Integrated Device Technology, Inc. + +usb:v0426p0426* + ID_MODEL_FROM_DATABASE=WDM Driver + +usb:v0427* + ID_VENDOR_FROM_DATABASE=Motorola Electronics Taiwan, Ltd + +usb:v0428* + ID_VENDOR_FROM_DATABASE=Advanced Gravis Computer Tech, Ltd + +usb:v0428p4001* + ID_MODEL_FROM_DATABASE=GamePad Pro + +usb:v0429* + ID_VENDOR_FROM_DATABASE=Cirrus Logic + +usb:v042A* + ID_VENDOR_FROM_DATABASE=Ericsson Austrian, AG + +usb:v042B* + ID_VENDOR_FROM_DATABASE=Intel Corp. + +usb:v042Bp9316* + ID_MODEL_FROM_DATABASE=8x931Hx Customer Hub + +usb:v042C* + ID_VENDOR_FROM_DATABASE=Innovative Semiconductors, Inc. + +usb:v042D* + ID_VENDOR_FROM_DATABASE=Micronics + +usb:v042E* + ID_VENDOR_FROM_DATABASE=Acer, Inc. + +usb:v042Ep0380* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v042F* + ID_VENDOR_FROM_DATABASE=Molex, Inc. + +usb:v0430* + ID_VENDOR_FROM_DATABASE=Sun Microsystems, Inc. + +usb:v0430p0002* + ID_MODEL_FROM_DATABASE=109 Keyboard + +usb:v0430p0005* + ID_MODEL_FROM_DATABASE=Type 6 Keyboard + +usb:v0430p000A* + ID_MODEL_FROM_DATABASE=109 Japanese Keyboard + +usb:v0430p000B* + ID_MODEL_FROM_DATABASE=109 Japanese Keyboard + +usb:v0430p0082* + ID_MODEL_FROM_DATABASE=109 Japanese Keyboard + +usb:v0430p0083* + ID_MODEL_FROM_DATABASE=109 Japanese Keyboard + +usb:v0430p00A2* + ID_MODEL_FROM_DATABASE=Type 7 Keyboard + +usb:v0430p0100* + ID_MODEL_FROM_DATABASE=3-button Mouse + +usb:v0430p0502* + ID_MODEL_FROM_DATABASE=Panasonic CF-19 HID Touch Panel + +usb:v0430p100E* + ID_MODEL_FROM_DATABASE=24.1" LCD Monitor v4 / FID-638 Mouse + +usb:v0430p36BA* + ID_MODEL_FROM_DATABASE=Bus Powered Hub + +usb:v0430pA101* + ID_MODEL_FROM_DATABASE=remote key/mouse for P3 chip + +usb:v0430pA102* + ID_MODEL_FROM_DATABASE=remote key/mouse/storage for P3 chip + +usb:v0430pA103* + ID_MODEL_FROM_DATABASE=remote storage for P3 chip + +usb:v0430pA111* + ID_MODEL_FROM_DATABASE=remote keyboard for P4 chip + +usb:v0430pA112* + ID_MODEL_FROM_DATABASE=remote mouse for P4 chip + +usb:v0430pA113* + ID_MODEL_FROM_DATABASE=remote storage for P4 chip + +usb:v0430pA4A2* + ID_MODEL_FROM_DATABASE=Ethernet (RNDIS and CDC ethernet) + +usb:v0430pCDAB* + ID_MODEL_FROM_DATABASE=Raritan KVM dongle + +usb:v0431* + ID_VENDOR_FROM_DATABASE=Itac Systems, Inc. + +usb:v0431p0100* + ID_MODEL_FROM_DATABASE=Mouse-Trak 3-button Track Ball + +usb:v0432* + ID_VENDOR_FROM_DATABASE=Unisys Corp. + +usb:v0432p0031* + ID_MODEL_FROM_DATABASE=Document Processor + +usb:v0433* + ID_VENDOR_FROM_DATABASE=Alps Electric, Inc. + +usb:v0433p1101* + ID_MODEL_FROM_DATABASE=IBM Game Controller + +usb:v0433pABAB* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0434* + ID_VENDOR_FROM_DATABASE=Samsung Info. Systems America, Inc. + +usb:v0435* + ID_VENDOR_FROM_DATABASE=Hyundai Electronics America + +usb:v0436* + ID_VENDOR_FROM_DATABASE=Taugagreining HF + +usb:v0436p0005* + ID_MODEL_FROM_DATABASE=CameraMate (DPCM_USB) + +usb:v0437* + ID_VENDOR_FROM_DATABASE=Framatome Connectors USA + +usb:v0438* + ID_VENDOR_FROM_DATABASE=Advanced Micro Devices, Inc. + +usb:v0438p7900* + ID_MODEL_FROM_DATABASE=Root Hub + +usb:v0439* + ID_VENDOR_FROM_DATABASE=Voice Technologies Group + +usb:v043D* + ID_VENDOR_FROM_DATABASE=Lexmark International, Inc. + +usb:v043Dp0001* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0002* + ID_MODEL_FROM_DATABASE=Optra E310 Printer + +usb:v043Dp0003* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0004* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0005* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0006* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0007* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0008* + ID_MODEL_FROM_DATABASE=Inkjet Color Printer + +usb:v043Dp0009* + ID_MODEL_FROM_DATABASE=Optra S2450 Printer + +usb:v043Dp000A* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp000B* + ID_MODEL_FROM_DATABASE=Inkjet Color Printer + +usb:v043Dp000C* + ID_MODEL_FROM_DATABASE=Optra E312 Printer + +usb:v043Dp000D* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp000E* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp000F* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0010* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0011* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0012* + ID_MODEL_FROM_DATABASE=Inkjet Color Printer + +usb:v043Dp0013* + ID_MODEL_FROM_DATABASE=Inkjet Color Printer + +usb:v043Dp0014* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0015* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0016* + ID_MODEL_FROM_DATABASE=Z12 Color Jetprinter + +usb:v043Dp0017* + ID_MODEL_FROM_DATABASE=Z32 printer + +usb:v043Dp0018* + ID_MODEL_FROM_DATABASE=Z52 Printer + +usb:v043Dp0019* + ID_MODEL_FROM_DATABASE=Forms Printer + +usb:v043Dp001A* + ID_MODEL_FROM_DATABASE=Z65 Printer + +usb:v043Dp001B* + ID_MODEL_FROM_DATABASE=InkJet Photo Printer + +usb:v043Dp001C* + ID_MODEL_FROM_DATABASE=Kodak Personal Picture Maker 200 Printer + +usb:v043Dp001D* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp001E* + ID_MODEL_FROM_DATABASE=InkJet Photo Printer + +usb:v043Dp001F* + ID_MODEL_FROM_DATABASE=Kodak Personal Picture Maker 200 Card Reader + +usb:v043Dp0020* + ID_MODEL_FROM_DATABASE=Z51 Printer + +usb:v043Dp0021* + ID_MODEL_FROM_DATABASE=Z33 Printer + +usb:v043Dp0022* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0023* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0024* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0025* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0026* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0027* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0028* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0029* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp002A* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp002B* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp002C* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp002D* + ID_MODEL_FROM_DATABASE=X70/X73 Scan/Print/Copy + +usb:v043Dp002E* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp002F* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0030* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0031* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0032* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0033* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0034* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0035* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0036* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0037* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0038* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0039* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp003A* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp003B* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp003C* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp003D* + ID_MODEL_FROM_DATABASE=X83 Scan/Print/Copy + +usb:v043Dp003E* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp003F* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0040* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0041* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0042* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0043* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0044* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0045* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0046* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0047* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0048* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp0049* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp004A* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp004B* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp004C* + ID_MODEL_FROM_DATABASE=Scan Print Copy + +usb:v043Dp004D* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp004E* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp004F* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0050* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0051* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0052* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp0053* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0054* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0057* + ID_MODEL_FROM_DATABASE=Z35 Printer + +usb:v043Dp0058* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v043Dp005A* + ID_MODEL_FROM_DATABASE=X63 + +usb:v043Dp005C* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0060* + ID_MODEL_FROM_DATABASE=X74/X75 Scanner + +usb:v043Dp0061* + ID_MODEL_FROM_DATABASE=X74 Hub + +usb:v043Dp0065* + ID_MODEL_FROM_DATABASE=X5130 + +usb:v043Dp0069* + ID_MODEL_FROM_DATABASE=X74/X75 Printer + +usb:v043Dp006D* + ID_MODEL_FROM_DATABASE=X125 + +usb:v043Dp006E* + ID_MODEL_FROM_DATABASE=C510 + +usb:v043Dp0072* + ID_MODEL_FROM_DATABASE=X6170 Printer + +usb:v043Dp0073* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0078* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp0079* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp007A* + ID_MODEL_FROM_DATABASE=Generic Hub + +usb:v043Dp007B* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp007C* + ID_MODEL_FROM_DATABASE=X1110/X1130/X1140/X1150/X1170/X1180/X1185 + +usb:v043Dp007D* + ID_MODEL_FROM_DATABASE=Photo 3150 + +usb:v043Dp008A* + ID_MODEL_FROM_DATABASE=4200 series + +usb:v043Dp008B* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp008C* + ID_MODEL_FROM_DATABASE=to CF/SM/SD/MS Card Reader + +usb:v043Dp008E* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp008F* + ID_MODEL_FROM_DATABASE=X422 + +usb:v043Dp0091* + ID_MODEL_FROM_DATABASE=Laser Printer E232 + +usb:v043Dp0093* + ID_MODEL_FROM_DATABASE=X5250 + +usb:v043Dp0095* + ID_MODEL_FROM_DATABASE=E220 Printer + +usb:v043Dp0096* + ID_MODEL_FROM_DATABASE=2200 series + +usb:v043Dp0097* + ID_MODEL_FROM_DATABASE=P6250 + +usb:v043Dp0098* + ID_MODEL_FROM_DATABASE=7100 series + +usb:v043Dp009E* + ID_MODEL_FROM_DATABASE=P910 series Human Interface Device + +usb:v043Dp009F* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp00A9* + ID_MODEL_FROM_DATABASE=IBM Infoprint 1410 MFP + +usb:v043Dp00AB* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp00B2* + ID_MODEL_FROM_DATABASE=3300 series + +usb:v043Dp00B8* + ID_MODEL_FROM_DATABASE=7300 series + +usb:v043Dp00B9* + ID_MODEL_FROM_DATABASE=8300 series + +usb:v043Dp00BA* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp00BB* + ID_MODEL_FROM_DATABASE=2300 series + +usb:v043Dp00BD* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v043Dp00BE* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v043Dp00BF* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v043Dp00C0* + ID_MODEL_FROM_DATABASE=6300 series + +usb:v043Dp00C1* + ID_MODEL_FROM_DATABASE=4300 series + +usb:v043Dp00C7* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v043Dp00C8* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v043Dp00C9* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v043Dp00CB* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v043Dp00CC* + ID_MODEL_FROM_DATABASE=E120(n) + +usb:v043Dp00D0* + ID_MODEL_FROM_DATABASE=9300 series + +usb:v043Dp00D3* + ID_MODEL_FROM_DATABASE=X340 Scanner + +usb:v043Dp00D4* + ID_MODEL_FROM_DATABASE=X342n Scanner + +usb:v043Dp00D5* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v043Dp00D6* + ID_MODEL_FROM_DATABASE=X340 Scanner + +usb:v043Dp00E8* + ID_MODEL_FROM_DATABASE=X642e + +usb:v043Dp00E9* + ID_MODEL_FROM_DATABASE=2400 series + +usb:v043Dp00F6* + ID_MODEL_FROM_DATABASE=3400 series + +usb:v043Dp00F7* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp00FF* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v043Dp010B* + ID_MODEL_FROM_DATABASE=2500 series + +usb:v043Dp010D* + ID_MODEL_FROM_DATABASE=3500-4500 series + +usb:v043Dp010F* + ID_MODEL_FROM_DATABASE=6500 series + +usb:v043Dp0142* + ID_MODEL_FROM_DATABASE=X3650 (Printer, Scanner, Copier) + +usb:v043Dp01FA* + ID_MODEL_FROM_DATABASE=S310 series + +usb:v043Dp4303* + ID_MODEL_FROM_DATABASE=Xerox WorkCentre Pro 412 + +usb:v043E* + ID_VENDOR_FROM_DATABASE=LG Electronics USA, Inc. + +usb:v043Ep3001* + ID_MODEL_FROM_DATABASE=AN-WF100 802.11abgn Wireless Adapter [Broadcom BCM4323] + +usb:v043Ep3004* + ID_MODEL_FROM_DATABASE=TWFM-B003D 802.11abgn Wireless Module [Broadcom BCM43236B] + +usb:v043Ep3101* + ID_MODEL_FROM_DATABASE=AN-WF500 802.11abgn + BT Wireless Adapter [Broadcom BCM43242] + +usb:v043Ep42BD* + ID_MODEL_FROM_DATABASE=Flatron 795FT Plus Monitor + +usb:v043Ep4A4D* + ID_MODEL_FROM_DATABASE=Flatron 915FT Plus Monitor + +usb:v043Ep7001* + ID_MODEL_FROM_DATABASE=MF-PD100 Soul Digital MP3 Player + +usb:v043Ep7013* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v043Ep70D7* + ID_MODEL_FROM_DATABASE=Mouse Scanner LSM-150 [LG Smart Scan Mouse] + +usb:v043Ep70F5* + ID_MODEL_FROM_DATABASE=External HDD + +usb:v043Ep8484* + ID_MODEL_FROM_DATABASE=LPC-U30 Webcam II + +usb:v043Ep8585* + ID_MODEL_FROM_DATABASE=LPC-UC35 Webcam + +usb:v043Ep8888* + ID_MODEL_FROM_DATABASE=Electronics VCS Camera II(LPC-U20) + +usb:v043Ep9800* + ID_MODEL_FROM_DATABASE=Remote Control Receiver_iMON + +usb:v043Ep9803* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v043Ep9804* + ID_MODEL_FROM_DATABASE=DMB Receiver Control + +usb:v043Ep9C01* + ID_MODEL_FROM_DATABASE=LGE Sync + +usb:v043F* + ID_VENDOR_FROM_DATABASE=RadiSys Corp. + +usb:v0440* + ID_VENDOR_FROM_DATABASE=Eizo Nanao Corp. + +usb:v0441* + ID_VENDOR_FROM_DATABASE=Winbond Systems Lab. + +usb:v0441p1456* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0442* + ID_VENDOR_FROM_DATABASE=Ericsson, Inc. + +usb:v0442pABBA* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0443* + ID_VENDOR_FROM_DATABASE=Gateway, Inc. + +usb:v0443p000E* + ID_MODEL_FROM_DATABASE=Multimedia Keyboard + +usb:v0443p002E* + ID_MODEL_FROM_DATABASE=Millennium Keyboard + +usb:v0445* + ID_VENDOR_FROM_DATABASE=Lucent Technologies, Inc. + +usb:v0446* + ID_VENDOR_FROM_DATABASE=NMB Technologies Corp. + +usb:v0446p6781* + ID_MODEL_FROM_DATABASE=Keyboard with PS/2 Mouse Port + +usb:v0446p6782* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0447* + ID_VENDOR_FROM_DATABASE=Momentum Microsystems + +usb:v0449* + ID_VENDOR_FROM_DATABASE=Duta Multi Robotik + +usb:v0449p0128* + ID_MODEL_FROM_DATABASE=Menengah + +usb:v0449p0210* + ID_MODEL_FROM_DATABASE=Dasar + +usb:v0449p0612* + ID_MODEL_FROM_DATABASE=Lanjutan + +usb:v044A* + ID_VENDOR_FROM_DATABASE=Shamrock Tech. Co., Ltd + +usb:v044B* + ID_VENDOR_FROM_DATABASE=WSI + +usb:v044C* + ID_VENDOR_FROM_DATABASE=CCL/ITRI + +usb:v044D* + ID_VENDOR_FROM_DATABASE=Siemens Nixdorf AG + +usb:v044E* + ID_VENDOR_FROM_DATABASE=Alps Electric Co., Ltd + +usb:v044Ep1104* + ID_MODEL_FROM_DATABASE=Japanese Keyboard + +usb:v044Ep2002* + ID_MODEL_FROM_DATABASE=MD-5500 Printer + +usb:v044Ep2014* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v044Ep3001* + ID_MODEL_FROM_DATABASE=UGTZ4 Bluetooth + +usb:v044Ep3002* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v044Ep3003* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v044Ep3004* + ID_MODEL_FROM_DATABASE=Bluetooth Adapter + +usb:v044Ep3005* + ID_MODEL_FROM_DATABASE=Integrated Bluetooth Device + +usb:v044Ep3006* + ID_MODEL_FROM_DATABASE=Bluetooth Adapter + +usb:v044Ep3007* + ID_MODEL_FROM_DATABASE=Bluetooth Controller (ALPS/UGX) + +usb:v044Ep300C* + ID_MODEL_FROM_DATABASE=Bluetooth Controller (ALPS/UGPZ6) + +usb:v044Ep300D* + ID_MODEL_FROM_DATABASE=Bluetooth Controller (ALPS/UGPZ6) + +usb:v044Ep3010* + ID_MODEL_FROM_DATABASE=Bluetooth Adapter + +usb:v044Ep3017* + ID_MODEL_FROM_DATABASE=BCM2046 Bluetooth Device + +usb:v044EpFFFF* + ID_MODEL_FROM_DATABASE=Compaq Bluetooth Multiport Module + +usb:v044F* + ID_VENDOR_FROM_DATABASE=ThrustMaster, Inc. + +usb:v044Fp0400* + ID_MODEL_FROM_DATABASE=HOTAS Cougar + +usb:v044Fp0402* + ID_MODEL_FROM_DATABASE=HOTAS Warthog Joystick + +usb:v044Fp0404* + ID_MODEL_FROM_DATABASE=HOTAS Warthog Throttle + +usb:v044Fp044F* + ID_MODEL_FROM_DATABASE=GP XID + +usb:v044Fp0F00* + ID_MODEL_FROM_DATABASE=Steering Wheel for Xbox + +usb:v044Fp0F03* + ID_MODEL_FROM_DATABASE=Steering Wheel for Xbox + +usb:v044Fp0F07* + ID_MODEL_FROM_DATABASE=Controller for Xbox + +usb:v044Fp0F0C* + ID_MODEL_FROM_DATABASE=Xbox Memory Unit (8MB) + +usb:v044Fp0F10* + ID_MODEL_FROM_DATABASE=Modena GT Wheel + +usb:v044FpA003* + ID_MODEL_FROM_DATABASE=Rage 3D Game Pad + +usb:v044FpA01B* + ID_MODEL_FROM_DATABASE=PK-GP301 Driving Wheel + +usb:v044FpA0A0* + ID_MODEL_FROM_DATABASE=Top Gun Joystick + +usb:v044FpA0A1* + ID_MODEL_FROM_DATABASE=Top Gun Joystick (rev2) + +usb:v044FpA0A3* + ID_MODEL_FROM_DATABASE=Fusion Digital GamePad + +usb:v044FpA201* + ID_MODEL_FROM_DATABASE=PK-GP201 PlayStick + +usb:v044FpB108* + ID_MODEL_FROM_DATABASE=T-Flight Hotas X Flight Stick + +usb:v044FpB10A* + ID_MODEL_FROM_DATABASE=T.16000M Joystick + +usb:v044FpB203* + ID_MODEL_FROM_DATABASE=360 Modena Pro Wheel + +usb:v044FpB300* + ID_MODEL_FROM_DATABASE=Firestorm Dual Power + +usb:v044FpB303* + ID_MODEL_FROM_DATABASE=FireStorm Dual Analog 2 + +usb:v044FpB304* + ID_MODEL_FROM_DATABASE=Firestorm Dual Power + +usb:v044FpB307* + ID_MODEL_FROM_DATABASE=vibrating Upad + +usb:v044FpB30B* + ID_MODEL_FROM_DATABASE=Wireless VibrationPad + +usb:v044FpB315* + ID_MODEL_FROM_DATABASE=Firestorm Dual Analog 3 + +usb:v044FpB323* + ID_MODEL_FROM_DATABASE=Dual Trigger 3-in-1 (PC Mode) + +usb:v044FpB324* + ID_MODEL_FROM_DATABASE=Dual Trigger 3-in-1 (PS3 Mode) + +usb:v044FpB326* + ID_MODEL_FROM_DATABASE=Gamepad GP XID + +usb:v044FpB351* + ID_MODEL_FROM_DATABASE=F16 MFD 1 + +usb:v044FpB352* + ID_MODEL_FROM_DATABASE=F16 MFD 2 + +usb:v044FpB365* + ID_MODEL_FROM_DATABASE=UbiSoft UbiConnect + +usb:v044FpB603* + ID_MODEL_FROM_DATABASE=force feedback Wheel + +usb:v044FpB605* + ID_MODEL_FROM_DATABASE=force feedback Racing Wheel + +usb:v044FpB651* + ID_MODEL_FROM_DATABASE=Ferrari GT Rumble Force Wheel + +usb:v044FpB653* + ID_MODEL_FROM_DATABASE=RGT Force Feedback Clutch Racing Wheel + +usb:v044FpB654* + ID_MODEL_FROM_DATABASE=Ferrari GT Force Feedback Wheel + +usb:v044FpB678* + ID_MODEL_FROM_DATABASE=T.Flight Rudder Pedals + +usb:v044FpB679* + ID_MODEL_FROM_DATABASE=T-Rudder + +usb:v044FpB687* + ID_MODEL_FROM_DATABASE=TWCS Throttle + +usb:v044FpB700* + ID_MODEL_FROM_DATABASE=Tacticalboard + +usb:v0450* + ID_VENDOR_FROM_DATABASE=DFI, Inc. + +usb:v0451* + ID_VENDOR_FROM_DATABASE=Texas Instruments, Inc. + +usb:v0451p1234* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0451p1428* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0451p1446* + ID_MODEL_FROM_DATABASE=TUSB2040/2070 Hub + +usb:v0451p16A6* + ID_MODEL_FROM_DATABASE=BM-USBD1 BlueRobin RF heart rate sensor receiver + +usb:v0451p2036* + ID_MODEL_FROM_DATABASE=TUSB2036 Hub + +usb:v0451p2046* + ID_MODEL_FROM_DATABASE=TUSB2046 Hub + +usb:v0451p2077* + ID_MODEL_FROM_DATABASE=TUSB2077 Hub + +usb:v0451p2F90* + ID_MODEL_FROM_DATABASE=SM-USB-DIG + +usb:v0451p3410* + ID_MODEL_FROM_DATABASE=TUSB3410 Microcontroller + +usb:v0451p3F00* + ID_MODEL_FROM_DATABASE=OMAP1610 + +usb:v0451p3F02* + ID_MODEL_FROM_DATABASE=SMC WSKP100 Wi-Fi Phone + +usb:v0451p505F* + ID_MODEL_FROM_DATABASE=TUSB5052 Serial + +usb:v0451p5153* + ID_MODEL_FROM_DATABASE=TUSB5052 Hub + +usb:v0451p5409* + ID_MODEL_FROM_DATABASE=Frontier Labs NEX IA+ Digital Audio Player + +usb:v0451p6000* + ID_MODEL_FROM_DATABASE=AU5 ADSL Modem (pre-reenum) + +usb:v0451p6001* + ID_MODEL_FROM_DATABASE=AU5 ADSL Modem + +usb:v0451p6060* + ID_MODEL_FROM_DATABASE=RNDIS/BeWAN ADSL2+ + +usb:v0451p6070* + ID_MODEL_FROM_DATABASE=RNDIS/BeWAN ADSL2+ + +usb:v0451p625F* + ID_MODEL_FROM_DATABASE=TUSB6250 ATA Bridge + +usb:v0451p8041* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0451p8042* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0451p8043* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0451p8140* + ID_MODEL_FROM_DATABASE=TUSB8041 4-Port Hub + +usb:v0451p8142* + ID_MODEL_FROM_DATABASE=TUSB8041 4-Port Hub + +usb:v0451p926B* + ID_MODEL_FROM_DATABASE=TUSB9260 Boot Loader + +usb:v0451pBEF3* + ID_MODEL_FROM_DATABASE=CC1352R1 Launchpad + +usb:v0451pDBC0* + ID_MODEL_FROM_DATABASE=Device Bay Controller + +usb:v0451pE001* + ID_MODEL_FROM_DATABASE=GraphLink [SilverLink] + +usb:v0451pE003* + ID_MODEL_FROM_DATABASE=TI-84 Plus Calculator + +usb:v0451pE004* + ID_MODEL_FROM_DATABASE=TI-89 Titanium Calculator + +usb:v0451pE008* + ID_MODEL_FROM_DATABASE=TI-84 Plus Silver Calculator + +usb:v0451pE00E* + ID_MODEL_FROM_DATABASE=TI-89 Titanium Presentation Link + +usb:v0451pE00F* + ID_MODEL_FROM_DATABASE=TI-84 Plus Presentation Link + +usb:v0451pE010* + ID_MODEL_FROM_DATABASE=TI SmartPad Keyboard + +usb:v0451pE011* + ID_MODEL_FROM_DATABASE=Nspire CAS+ prototype + +usb:v0451pE012* + ID_MODEL_FROM_DATABASE=TI-Nspire Calculator + +usb:v0451pE013* + ID_MODEL_FROM_DATABASE=Network Bridge + +usb:v0451pE01C* + ID_MODEL_FROM_DATABASE=Data Collection Sled [Nspire Lab Cradle, Nspire Datatracker Cradle] + +usb:v0451pE01F* + ID_MODEL_FROM_DATABASE=Python Adapter (firmware install mode) + +usb:v0451pE020* + ID_MODEL_FROM_DATABASE=Python Adapter + +usb:v0451pE022* + ID_MODEL_FROM_DATABASE=Nspire CX II + +usb:v0451pF430* + ID_MODEL_FROM_DATABASE=MSP-FET430UIF JTAG Tool + +usb:v0451pF432* + ID_MODEL_FROM_DATABASE=eZ430 Development Tool + +usb:v0451pFFFF* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0452* + ID_VENDOR_FROM_DATABASE=Mitsubishi Electronics America, Inc. + +usb:v0452p0021* + ID_MODEL_FROM_DATABASE=HID Monitor Controls + +usb:v0452p0050* + ID_MODEL_FROM_DATABASE=Diamond Pro 900u CRT Monitor + +usb:v0452p0051* + ID_MODEL_FROM_DATABASE=Integrated Hub + +usb:v0452p0100* + ID_MODEL_FROM_DATABASE=Control Panel for Leica TCS SP5 + +usb:v0453* + ID_VENDOR_FROM_DATABASE=CMD Technology + +usb:v0453p6781* + ID_MODEL_FROM_DATABASE=NMB Keyboard + +usb:v0453p6783* + ID_MODEL_FROM_DATABASE=Chicony Composite Keyboard + +usb:v0454* + ID_VENDOR_FROM_DATABASE=Vobis Microcomputer AG + +usb:v0455* + ID_VENDOR_FROM_DATABASE=Telematics International, Inc. + +usb:v0456* + ID_VENDOR_FROM_DATABASE=Analog Devices, Inc. + +usb:v0456pF000* + ID_MODEL_FROM_DATABASE=FT2232 JTAG ICE [gnICE] + +usb:v0456pF001* + ID_MODEL_FROM_DATABASE=FT2232H Hi-Speed JTAG ICE [gnICE+] + +usb:v0457* + ID_VENDOR_FROM_DATABASE=Silicon Integrated Systems Corp. + +usb:v0457p0150* + ID_MODEL_FROM_DATABASE=Super Talent 1GB Flash Drive + +usb:v0457p0151* + ID_MODEL_FROM_DATABASE=Super Flash 1GB / GXT 64MB Flash Drive + +usb:v0457p0162* + ID_MODEL_FROM_DATABASE=SiS162 usb Wireless LAN Adapter + +usb:v0457p0163* + ID_MODEL_FROM_DATABASE=SiS163U 802.11 Wireless LAN Adapter + +usb:v0457p0817* + ID_MODEL_FROM_DATABASE=SiS-184-ASUS-4352.17 touch panel + +usb:v0457p10E1* + ID_MODEL_FROM_DATABASE=HID Touch Controller + +usb:v0457p5401* + ID_MODEL_FROM_DATABASE=Wireless Adapter RO80211GS-USB + +usb:v0458* + ID_VENDOR_FROM_DATABASE=KYE Systems Corp. (Mouse Systems) + +usb:v0458p0001* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v0458p0002* + ID_MODEL_FROM_DATABASE=Genius NetMouse Pro + +usb:v0458p0003* + ID_MODEL_FROM_DATABASE=Genius NetScroll+ + +usb:v0458p0006* + ID_MODEL_FROM_DATABASE=Easy Mouse+ + +usb:v0458p000B* + ID_MODEL_FROM_DATABASE=NetMouse Wheel(P+U) + +usb:v0458p000C* + ID_MODEL_FROM_DATABASE=TACOMA Fingerprint V1.06.01 + +usb:v0458p000E* + ID_MODEL_FROM_DATABASE=Genius NetScroll Optical + +usb:v0458p0013* + ID_MODEL_FROM_DATABASE=TACOMA Fingerprint Mouse V1.06.01 + +usb:v0458p001A* + ID_MODEL_FROM_DATABASE=Genius WebScroll+ + +usb:v0458p002E* + ID_MODEL_FROM_DATABASE=NetScroll + Traveler / NetScroll 110 + +usb:v0458p0036* + ID_MODEL_FROM_DATABASE=Pocket Mouse LE + +usb:v0458p0039* + ID_MODEL_FROM_DATABASE=NetScroll+ Superior + +usb:v0458p003A* + ID_MODEL_FROM_DATABASE=NetScroll+ Mini Traveler / Genius NetScroll 120 + +usb:v0458p004C* + ID_MODEL_FROM_DATABASE=Slimstar Pro Keyboard + +usb:v0458p0056* + ID_MODEL_FROM_DATABASE=Ergo 300 Mouse + +usb:v0458p0057* + ID_MODEL_FROM_DATABASE=Enhanced Gaming Device + +usb:v0458p0059* + ID_MODEL_FROM_DATABASE=Enhanced Laser Device + +usb:v0458p005A* + ID_MODEL_FROM_DATABASE=Enhanced Device + +usb:v0458p005B* + ID_MODEL_FROM_DATABASE=Enhanced Device + +usb:v0458p005C* + ID_MODEL_FROM_DATABASE=Enhanced Laser Gaming Device + +usb:v0458p005D* + ID_MODEL_FROM_DATABASE=Enhanced Device + +usb:v0458p0061* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v0458p0066* + ID_MODEL_FROM_DATABASE=Genius Traveler 1000 Wireless Mouse + +usb:v0458p0072* + ID_MODEL_FROM_DATABASE=Navigator 335 + +usb:v0458p0083* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v0458p0087* + ID_MODEL_FROM_DATABASE=Ergo 525V Laser Mouse + +usb:v0458p0089* + ID_MODEL_FROM_DATABASE=Genius Traveler 350 + +usb:v0458p00CA* + ID_MODEL_FROM_DATABASE=Pen Mouse + +usb:v0458p0100* + ID_MODEL_FROM_DATABASE=EasyPen Tablet + +usb:v0458p0101* + ID_MODEL_FROM_DATABASE=CueCat + +usb:v0458p011B* + ID_MODEL_FROM_DATABASE=NetScroll T220 + +usb:v0458p0186* + ID_MODEL_FROM_DATABASE=Genius DX-120 Mouse + +usb:v0458p1001* + ID_MODEL_FROM_DATABASE=Joystick + +usb:v0458p1002* + ID_MODEL_FROM_DATABASE=Game Pad + +usb:v0458p1003* + ID_MODEL_FROM_DATABASE=Genius VideoCam + +usb:v0458p1004* + ID_MODEL_FROM_DATABASE=Flight2000 F-23 Joystick + +usb:v0458p100A* + ID_MODEL_FROM_DATABASE=Aashima Technology Trust Sight Fighter Vibration Feedback Joystick + +usb:v0458p2001* + ID_MODEL_FROM_DATABASE=ColorPage-Vivid Pro Scanner + +usb:v0458p2004* + ID_MODEL_FROM_DATABASE=ColorPage-HR6 V1 Scanner + +usb:v0458p2005* + ID_MODEL_FROM_DATABASE=ColorPage-HR6/Vivid3 + +usb:v0458p2007* + ID_MODEL_FROM_DATABASE=ColorPage-HR6 V2 Scanner + +usb:v0458p2008* + ID_MODEL_FROM_DATABASE=ColorPage-HR6 V2 Scanner + +usb:v0458p2009* + ID_MODEL_FROM_DATABASE=ColorPage-HR6A Scanner + +usb:v0458p2011* + ID_MODEL_FROM_DATABASE=ColorPage-Vivid3x Scanner + +usb:v0458p2012* + ID_MODEL_FROM_DATABASE=Plustek Scanner + +usb:v0458p2013* + ID_MODEL_FROM_DATABASE=ColorPage-HR7 Scanner + +usb:v0458p2014* + ID_MODEL_FROM_DATABASE=ColorPage-Vivid4 + +usb:v0458p2015* + ID_MODEL_FROM_DATABASE=ColorPage-HR7LE Scanner + +usb:v0458p2016* + ID_MODEL_FROM_DATABASE=ColorPage-HR6X Scanner + +usb:v0458p2017* + ID_MODEL_FROM_DATABASE=ColorPage-Vivid3xe + +usb:v0458p2018* + ID_MODEL_FROM_DATABASE=ColorPage-HR7X + +usb:v0458p2019* + ID_MODEL_FROM_DATABASE=ColorPage-HR6X Slim + +usb:v0458p201A* + ID_MODEL_FROM_DATABASE=ColorPage-Vivid4xe + +usb:v0458p201B* + ID_MODEL_FROM_DATABASE=ColorPage-Vivid4x + +usb:v0458p201C* + ID_MODEL_FROM_DATABASE=ColorPage-HR8 + +usb:v0458p201D* + ID_MODEL_FROM_DATABASE=ColorPage-Vivid 1200 X + +usb:v0458p201E* + ID_MODEL_FROM_DATABASE=ColorPage-Slim 1200 + +usb:v0458p201F* + ID_MODEL_FROM_DATABASE=ColorPage-Vivid 1200 XE + +usb:v0458p2020* + ID_MODEL_FROM_DATABASE=ColorPage-Slim 1200 USB2 + +usb:v0458p2021* + ID_MODEL_FROM_DATABASE=ColorPage-SF600 + +usb:v0458p3017* + ID_MODEL_FROM_DATABASE=SPEED WHEEL 3 Vibration + +usb:v0458p3018* + ID_MODEL_FROM_DATABASE=Wireless 2.4Ghz Game Pad + +usb:v0458p3019* + ID_MODEL_FROM_DATABASE=10-Button USB Joystick with Vibration + +usb:v0458p301A* + ID_MODEL_FROM_DATABASE=MaxFire G-12U Vibration + +usb:v0458p301C* + ID_MODEL_FROM_DATABASE=Genius MaxFighter F-16U + +usb:v0458p301D* + ID_MODEL_FROM_DATABASE=Genius MaxFire MiniPad + +usb:v0458p400F* + ID_MODEL_FROM_DATABASE=Genius TVGo DVB-T02Q MCE + +usb:v0458p4012* + ID_MODEL_FROM_DATABASE=TVGo DVB-T03 [AF9015] + +usb:v0458p5003* + ID_MODEL_FROM_DATABASE=G-pen 560 Tablet + +usb:v0458p5004* + ID_MODEL_FROM_DATABASE=G-pen Tablet + +usb:v0458p5005* + ID_MODEL_FROM_DATABASE=Genius EasyPen M406 + +usb:v0458p5012* + ID_MODEL_FROM_DATABASE=Genius EasyPen M406W + +usb:v0458p5014* + ID_MODEL_FROM_DATABASE=Genius EasyPen 340 + +usb:v0458p505E* + ID_MODEL_FROM_DATABASE=Genius iSlim 330 + +usb:v0458p6001* + ID_MODEL_FROM_DATABASE=GF3000F Ethernet Adapter + +usb:v0458p7004* + ID_MODEL_FROM_DATABASE=VideoCAM Express V2 + +usb:v0458p7006* + ID_MODEL_FROM_DATABASE=Dsc 1.3 Smart Camera Device + +usb:v0458p7007* + ID_MODEL_FROM_DATABASE=VideoCAM Web + +usb:v0458p7009* + ID_MODEL_FROM_DATABASE=G-Shot G312 Still Camera Device + +usb:v0458p700C* + ID_MODEL_FROM_DATABASE=VideoCAM Web V3 + +usb:v0458p700D* + ID_MODEL_FROM_DATABASE=G-Shot G511 Composite Device + +usb:v0458p700F* + ID_MODEL_FROM_DATABASE=VideoCAM Web + +usb:v0458p7012* + ID_MODEL_FROM_DATABASE=WebCAM USB2.0 + +usb:v0458p7014* + ID_MODEL_FROM_DATABASE=VideoCAM Live V3 + +usb:v0458p701C* + ID_MODEL_FROM_DATABASE=G-Shot G512 Still Camera + +usb:v0458p7020* + ID_MODEL_FROM_DATABASE=Sim 321C + +usb:v0458p7025* + ID_MODEL_FROM_DATABASE=Eye 311Q Camera + +usb:v0458p7029* + ID_MODEL_FROM_DATABASE=Genius Look 320s (SN9C201 + HV7131R) + +usb:v0458p702F* + ID_MODEL_FROM_DATABASE=Genius Slim 322 + +usb:v0458p7035* + ID_MODEL_FROM_DATABASE=i-Look 325T Camera + +usb:v0458p7045* + ID_MODEL_FROM_DATABASE=Genius Look 1320 V2 + +usb:v0458p704C* + ID_MODEL_FROM_DATABASE=Genius i-Look 1321 + +usb:v0458p704D* + ID_MODEL_FROM_DATABASE=Slim 1322AF + +usb:v0458p7055* + ID_MODEL_FROM_DATABASE=Slim 2020AF camera + +usb:v0458p705A* + ID_MODEL_FROM_DATABASE=Asus USB2.0 Webcam + +usb:v0458p705C* + ID_MODEL_FROM_DATABASE=Genius iSlim 1300AF + +usb:v0458p7061* + ID_MODEL_FROM_DATABASE=Genius iLook 1321 V2 + +usb:v0458p7066* + ID_MODEL_FROM_DATABASE=Acer Crystal Eye Webcam + +usb:v0458p7067* + ID_MODEL_FROM_DATABASE=Genius iSlim 1300AF V2 + +usb:v0458p7068* + ID_MODEL_FROM_DATABASE=Genius eFace 1325R + +usb:v0458p706D* + ID_MODEL_FROM_DATABASE=Genius iSlim 2000AF V2 + +usb:v0458p7076* + ID_MODEL_FROM_DATABASE=Genius FaceCam 312 + +usb:v0458p7079* + ID_MODEL_FROM_DATABASE=FaceCam 2025R + +usb:v0458p707F* + ID_MODEL_FROM_DATABASE=TVGo DVB-T03 [RTL2832] + +usb:v0458p7088* + ID_MODEL_FROM_DATABASE=WideCam 1050 + +usb:v0458p7089* + ID_MODEL_FROM_DATABASE=Genius FaceCam 320 + +usb:v0458p708C* + ID_MODEL_FROM_DATABASE=Genius WideCam F100 + +usb:v0459* + ID_VENDOR_FROM_DATABASE=Adobe Systems, Inc. + +usb:v045A* + ID_VENDOR_FROM_DATABASE=SONICblue, Inc. + +usb:v045Ap07DA* + ID_MODEL_FROM_DATABASE=Supra Express 56K modem + +usb:v045Ap0B4A* + ID_MODEL_FROM_DATABASE=SupraMax 2890 56K Modem [Lucent Atlas] + +usb:v045Ap0B68* + ID_MODEL_FROM_DATABASE=SupraMax 56K Modem + +usb:v045Ap5001* + ID_MODEL_FROM_DATABASE=Rio 600 MP3 Player + +usb:v045Ap5002* + ID_MODEL_FROM_DATABASE=Rio 800 MP3 Player + +usb:v045Ap5003* + ID_MODEL_FROM_DATABASE=Nike Psa/Play MP3 Player + +usb:v045Ap5005* + ID_MODEL_FROM_DATABASE=Rio S10 MP3 Player + +usb:v045Ap5006* + ID_MODEL_FROM_DATABASE=Rio S50 MP3 Player + +usb:v045Ap5007* + ID_MODEL_FROM_DATABASE=Rio S35 MP3 Player + +usb:v045Ap5008* + ID_MODEL_FROM_DATABASE=Rio 900 MP3 Player + +usb:v045Ap5009* + ID_MODEL_FROM_DATABASE=Rio S30 MP3 Player + +usb:v045Ap500D* + ID_MODEL_FROM_DATABASE=Fuse MP3 Player + +usb:v045Ap500E* + ID_MODEL_FROM_DATABASE=Chiba MP3 Player + +usb:v045Ap500F* + ID_MODEL_FROM_DATABASE=Cali MP3 Player + +usb:v045Ap5010* + ID_MODEL_FROM_DATABASE=Rio S11 MP3 Player + +usb:v045Ap501C* + ID_MODEL_FROM_DATABASE=Virgin MPF-1000 + +usb:v045Ap501D* + ID_MODEL_FROM_DATABASE=Rio Fuse + +usb:v045Ap501E* + ID_MODEL_FROM_DATABASE=Rio Chiba + +usb:v045Ap501F* + ID_MODEL_FROM_DATABASE=Rio Cali + +usb:v045Ap503F* + ID_MODEL_FROM_DATABASE=Cali256 MP3 Player + +usb:v045Ap5202* + ID_MODEL_FROM_DATABASE=Rio Riot MP3 Player + +usb:v045Ap5210* + ID_MODEL_FROM_DATABASE=Rio Karma Music Player + +usb:v045Ap5220* + ID_MODEL_FROM_DATABASE=Rio Nitrus MP3 Player + +usb:v045Ap5221* + ID_MODEL_FROM_DATABASE=Rio Eigen + +usb:v045B* + ID_VENDOR_FROM_DATABASE=Hitachi, Ltd + +usb:v045Bp0053* + ID_MODEL_FROM_DATABASE=RX610 RX-Stick + +usb:v045Bp0229* + ID_MODEL_FROM_DATABASE=mSATA Adapter [renkforce Pi-102] + +usb:v045D* + ID_VENDOR_FROM_DATABASE=Nortel Networks, Ltd + +usb:v045E* + ID_VENDOR_FROM_DATABASE=Microsoft Corp. + +usb:v045Ep0007* + ID_MODEL_FROM_DATABASE=SideWinder Game Pad + +usb:v045Ep0008* + ID_MODEL_FROM_DATABASE=SideWinder Precision Pro + +usb:v045Ep0009* + ID_MODEL_FROM_DATABASE=IntelliMouse + +usb:v045Ep000B* + ID_MODEL_FROM_DATABASE=Natural Keyboard Elite + +usb:v045Ep000E* + ID_MODEL_FROM_DATABASE=SideWinder® Freestyle Pro + +usb:v045Ep0014* + ID_MODEL_FROM_DATABASE=Digital Sound System 80 + +usb:v045Ep001A* + ID_MODEL_FROM_DATABASE=SideWinder Precision Racing Wheel + +usb:v045Ep001B* + ID_MODEL_FROM_DATABASE=SideWinder Force Feedback 2 Joystick + +usb:v045Ep001C* + ID_MODEL_FROM_DATABASE=Internet Keyboard Pro + +usb:v045Ep001D* + ID_MODEL_FROM_DATABASE=Natural Keyboard Pro + +usb:v045Ep001E* + ID_MODEL_FROM_DATABASE=IntelliMouse Explorer + +usb:v045Ep0023* + ID_MODEL_FROM_DATABASE=Trackball Optical + +usb:v045Ep0024* + ID_MODEL_FROM_DATABASE=Trackball Explorer + +usb:v045Ep0025* + ID_MODEL_FROM_DATABASE=IntelliEye Mouse + +usb:v045Ep0026* + ID_MODEL_FROM_DATABASE=SideWinder GamePad Pro + +usb:v045Ep0027* + ID_MODEL_FROM_DATABASE=SideWinder PnP GamePad + +usb:v045Ep0028* + ID_MODEL_FROM_DATABASE=SideWinder Dual Strike + +usb:v045Ep0029* + ID_MODEL_FROM_DATABASE=IntelliMouse Optical + +usb:v045Ep002B* + ID_MODEL_FROM_DATABASE=Internet Keyboard Pro + +usb:v045Ep002D* + ID_MODEL_FROM_DATABASE=Internet Keyboard + +usb:v045Ep002F* + ID_MODEL_FROM_DATABASE=Integrated Hub + +usb:v045Ep0033* + ID_MODEL_FROM_DATABASE=Sidewinder Strategic Commander + +usb:v045Ep0034* + ID_MODEL_FROM_DATABASE=SideWinder Force Feedback Wheel + +usb:v045Ep0038* + ID_MODEL_FROM_DATABASE=SideWinder Precision 2 + +usb:v045Ep0039* + ID_MODEL_FROM_DATABASE=IntelliMouse Optical + +usb:v045Ep003B* + ID_MODEL_FROM_DATABASE=SideWinder Game Voice + +usb:v045Ep003C* + ID_MODEL_FROM_DATABASE=SideWinder Joystick + +usb:v045Ep0040* + ID_MODEL_FROM_DATABASE=Wheel Mouse Optical + +usb:v045Ep0047* + ID_MODEL_FROM_DATABASE=IntelliMouse Explorer 3.0 + +usb:v045Ep0048* + ID_MODEL_FROM_DATABASE=Office Keyboard 1.0A + +usb:v045Ep0053* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v045Ep0059* + ID_MODEL_FROM_DATABASE=Wireless IntelliMouse Explorer + +usb:v045Ep005C* + ID_MODEL_FROM_DATABASE=Office Keyboard (106/109) + +usb:v045Ep005F* + ID_MODEL_FROM_DATABASE=Wireless MultiMedia Keyboard + +usb:v045Ep0061* + ID_MODEL_FROM_DATABASE=Wireless MultiMedia Keyboard (106/109) + +usb:v045Ep0063* + ID_MODEL_FROM_DATABASE=Wireless Natural MultiMedia Keyboard + +usb:v045Ep0065* + ID_MODEL_FROM_DATABASE=Wireless Natural MultiMedia Keyboard (106/109) + +usb:v045Ep006A* + ID_MODEL_FROM_DATABASE=Wireless Optical Mouse (IntelliPoint) + +usb:v045Ep006D* + ID_MODEL_FROM_DATABASE=eHome Remote Control Keyboard keys + +usb:v045Ep006E* + ID_MODEL_FROM_DATABASE=MN-510 802.11b Wireless Adapter [Intersil ISL3873B] + +usb:v045Ep006F* + ID_MODEL_FROM_DATABASE=Smart Display Reference Device + +usb:v045Ep0070* + ID_MODEL_FROM_DATABASE=Wireless MultiMedia Keyboard + +usb:v045Ep0071* + ID_MODEL_FROM_DATABASE=Wireless MultiMedia Keyboard (106/109) + +usb:v045Ep0072* + ID_MODEL_FROM_DATABASE=Wireless Natural MultiMedia Keyboard + +usb:v045Ep0073* + ID_MODEL_FROM_DATABASE=Wireless Natural MultiMedia Keyboard (106/109) + +usb:v045Ep0079* + ID_MODEL_FROM_DATABASE=IXI Ogo CT-17 handheld device + +usb:v045Ep007A* + ID_MODEL_FROM_DATABASE=10/100 USB NIC + +usb:v045Ep007D* + ID_MODEL_FROM_DATABASE=Notebook Optical Mouse + +usb:v045Ep007E* + ID_MODEL_FROM_DATABASE=Wireless Transceiver for Bluetooth + +usb:v045Ep0080* + ID_MODEL_FROM_DATABASE=Digital Media Pro Keyboard + +usb:v045Ep0083* + ID_MODEL_FROM_DATABASE=Basic Optical Mouse + +usb:v045Ep0084* + ID_MODEL_FROM_DATABASE=Basic Optical Mouse + +usb:v045Ep008A* + ID_MODEL_FROM_DATABASE=Wireless Optical Desktop Receiver 2.0A + +usb:v045Ep008B* + ID_MODEL_FROM_DATABASE=Dual Receiver Wireless Mouse (IntelliPoint) + +usb:v045Ep008C* + ID_MODEL_FROM_DATABASE=Wireless Intellimouse Explorer 2.0 + +usb:v045Ep0095* + ID_MODEL_FROM_DATABASE=IntelliMouse Explorer 4.0 (IntelliPoint) + +usb:v045Ep009C* + ID_MODEL_FROM_DATABASE=Wireless Transceiver for Bluetooth 2.0 + +usb:v045Ep009D* + ID_MODEL_FROM_DATABASE=Wireless Optical Desktop 3.0 + +usb:v045Ep00A0* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v045Ep00A4* + ID_MODEL_FROM_DATABASE=Compact Optical Mouse, model 1016 + +usb:v045Ep00B0* + ID_MODEL_FROM_DATABASE=Digital Media Pro Keyboard + +usb:v045Ep00B4* + ID_MODEL_FROM_DATABASE=Digital Media Keyboard 1.0A + +usb:v045Ep00B9* + ID_MODEL_FROM_DATABASE=Wireless Optical Mouse 3.0 + +usb:v045Ep00BB* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v045Ep00BC* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v045Ep00BD* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v045Ep00C2* + ID_MODEL_FROM_DATABASE=MN-710 802.11g Wireless Adapter [Intersil ISL3886] + +usb:v045Ep00C9* + ID_MODEL_FROM_DATABASE=MTP Device + +usb:v045Ep00CA* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v045Ep00CB* + ID_MODEL_FROM_DATABASE=Basic Optical Mouse v2.0 + +usb:v045Ep00CE* + ID_MODEL_FROM_DATABASE=Generic PPC Flash device + +usb:v045Ep00D1* + ID_MODEL_FROM_DATABASE=Optical Mouse with Tilt Wheel + +usb:v045Ep00DA* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v045Ep00DB* + ID_MODEL_FROM_DATABASE=Natural Ergonomic Keyboard 4000 V1.0 + +usb:v045Ep00DD* + ID_MODEL_FROM_DATABASE=Comfort Curve Keyboard 2000 V1.0 + +usb:v045Ep00E1* + ID_MODEL_FROM_DATABASE=Wireless Laser Mouse 6000 Receiver + +usb:v045Ep00F4* + ID_MODEL_FROM_DATABASE=LifeCam VX-6000 (SN9C20x + OV9650) + +usb:v045Ep00F5* + ID_MODEL_FROM_DATABASE=LifeCam VX-3000 + +usb:v045Ep00F6* + ID_MODEL_FROM_DATABASE=Comfort Optical Mouse 1000 + +usb:v045Ep00F7* + ID_MODEL_FROM_DATABASE=LifeCam VX-1000 + +usb:v045Ep00F8* + ID_MODEL_FROM_DATABASE=LifeCam NX-6000 + +usb:v045Ep00F9* + ID_MODEL_FROM_DATABASE=Wireless Desktop Receiver 3.1 + +usb:v045Ep0202* + ID_MODEL_FROM_DATABASE=Xbox Controller + +usb:v045Ep0280* + ID_MODEL_FROM_DATABASE=Xbox Memory Unit (8MB) + +usb:v045Ep0283* + ID_MODEL_FROM_DATABASE=Xbox Communicator + +usb:v045Ep0284* + ID_MODEL_FROM_DATABASE=Xbox DVD Playback Kit + +usb:v045Ep0285* + ID_MODEL_FROM_DATABASE=Xbox Controller S + +usb:v045Ep0288* + ID_MODEL_FROM_DATABASE=Xbox Controller S Hub + +usb:v045Ep0289* + ID_MODEL_FROM_DATABASE=Xbox Controller S + +usb:v045Ep028B* + ID_MODEL_FROM_DATABASE=Xbox360 DVD Emulator + +usb:v045Ep028D* + ID_MODEL_FROM_DATABASE=Xbox360 Memory Unit 64MB + +usb:v045Ep028E* + ID_MODEL_FROM_DATABASE=Xbox360 Controller + +usb:v045Ep028F* + ID_MODEL_FROM_DATABASE=Xbox360 Wireless Controller + +usb:v045Ep0290* + ID_MODEL_FROM_DATABASE=Xbox360 Performance Pipe (PIX) + +usb:v045Ep0291* + ID_MODEL_FROM_DATABASE=Xbox 360 Wireless Receiver for Windows + +usb:v045Ep0292* + ID_MODEL_FROM_DATABASE=Xbox360 Wireless Networking Adapter + +usb:v045Ep029C* + ID_MODEL_FROM_DATABASE=Xbox360 HD-DVD Drive + +usb:v045Ep029D* + ID_MODEL_FROM_DATABASE=Xbox360 HD-DVD Drive + +usb:v045Ep029E* + ID_MODEL_FROM_DATABASE=Xbox360 HD-DVD Memory Unit + +usb:v045Ep02A0* + ID_MODEL_FROM_DATABASE=Xbox360 Big Button IR + +usb:v045Ep02A1* + ID_MODEL_FROM_DATABASE=Xbox 360 Wireless Receiver for Windows + +usb:v045Ep02A8* + ID_MODEL_FROM_DATABASE=Xbox360 Wireless N Networking Adapter [Atheros AR7010+AR9280] + +usb:v045Ep02AD* + ID_MODEL_FROM_DATABASE=Xbox NUI Audio + +usb:v045Ep02AE* + ID_MODEL_FROM_DATABASE=Xbox NUI Camera + +usb:v045Ep02B0* + ID_MODEL_FROM_DATABASE=Xbox NUI Motor + +usb:v045Ep02B6* + ID_MODEL_FROM_DATABASE=Xbox360 Bluetooth Wireless Headset + +usb:v045Ep02BB* + ID_MODEL_FROM_DATABASE=Kinect Audio + +usb:v045Ep02BE* + ID_MODEL_FROM_DATABASE=Kinect for Windows NUI Audio + +usb:v045Ep02BF* + ID_MODEL_FROM_DATABASE=Kinect for Windows NUI Camera + +usb:v045Ep02C2* + ID_MODEL_FROM_DATABASE=Kinect for Windows NUI Motor + +usb:v045Ep02D1* + ID_MODEL_FROM_DATABASE=Xbox One Controller + +usb:v045Ep02D5* + ID_MODEL_FROM_DATABASE=Xbox One Digital TV Tuner + +usb:v045Ep02DD* + ID_MODEL_FROM_DATABASE=Xbox One Controller (Firmware 2015) + +usb:v045Ep02E3* + ID_MODEL_FROM_DATABASE=Xbox One Elite Controller + +usb:v045Ep02E6* + ID_MODEL_FROM_DATABASE=Wireless XBox Controller Dongle + +usb:v045Ep02EA* + ID_MODEL_FROM_DATABASE=Xbox One S Controller + +usb:v045Ep02FD* + ID_MODEL_FROM_DATABASE=Xbox One S Controller [Bluetooth] + +usb:v045Ep0400* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0401* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0402* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0403* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0404* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0405* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0406* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0407* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0408* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0409* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep040A* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep040B* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep040C* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep040D* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep040E* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep040F* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0410* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0411* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0412* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0413* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0414* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0415* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0416* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0417* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2002 + +usb:v045Ep0432* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0433* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0434* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0435* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0436* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0437* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0438* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0439* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep043A* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep043B* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep043C* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep043D* + ID_MODEL_FROM_DATABASE=Becker Traffic Assist Highspeed 7934 + +usb:v045Ep043E* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep043F* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0440* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0441* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0442* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0443* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0444* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0445* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0446* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0447* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0448* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0449* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep044A* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep044B* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep044C* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep044D* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep044E* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep044F* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0450* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0451* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0452* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0453* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0454* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0455* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0456* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0457* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0458* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0459* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep045A* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep045B* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep045C* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep045D* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep045E* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep045F* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0460* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0461* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0462* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0463* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0464* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0465* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0466* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0467* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0468* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0469* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep046A* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep046B* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep046C* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep046D* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep046E* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep046F* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0470* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0471* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0472* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0473* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0474* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0475* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0476* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0477* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0478* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep0479* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep047A* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep047B* + ID_MODEL_FROM_DATABASE=Windows Powered Pocket PC 2003 + +usb:v045Ep04C8* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 + +usb:v045Ep04C9* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 + +usb:v045Ep04CA* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 + +usb:v045Ep04CB* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 + +usb:v045Ep04CC* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 + +usb:v045Ep04CD* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 + +usb:v045Ep04CE* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2002 + +usb:v045Ep04D7* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04D8* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04D9* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04DA* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04DB* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04DC* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04DD* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04DE* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04DF* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04E0* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04E1* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04E2* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04E3* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04E4* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04E5* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04E6* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04E7* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04E8* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04E9* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04EA* + ID_MODEL_FROM_DATABASE=Windows Powered Smartphone 2003 + +usb:v045Ep04EC* + ID_MODEL_FROM_DATABASE=Windows Phone (Zune) + +usb:v045Ep063E* + ID_MODEL_FROM_DATABASE=Zune HD Media Player + +usb:v045Ep0640* + ID_MODEL_FROM_DATABASE=KIN Phone + +usb:v045Ep0641* + ID_MODEL_FROM_DATABASE=KIN Phone + +usb:v045Ep0642* + ID_MODEL_FROM_DATABASE=KIN Phone + +usb:v045Ep0707* + ID_MODEL_FROM_DATABASE=Wireless Laser Mouse 8000 + +usb:v045Ep0708* + ID_MODEL_FROM_DATABASE=Transceiver v 3.0 for Bluetooth + +usb:v045Ep070A* + ID_MODEL_FROM_DATABASE=Charon Bluetooth Dongle (DFU) + +usb:v045Ep070F* + ID_MODEL_FROM_DATABASE=LifeChat LX-3000 Headset + +usb:v045Ep0710* + ID_MODEL_FROM_DATABASE=Zune Media Player + +usb:v045Ep0713* + ID_MODEL_FROM_DATABASE=Wireless Presenter Mouse 8000 + +usb:v045Ep0719* + ID_MODEL_FROM_DATABASE=Xbox 360 Wireless Adapter + +usb:v045Ep071F* + ID_MODEL_FROM_DATABASE=Mouse/Keyboard 2.4GHz Transceiver V2.0 + +usb:v045Ep0721* + ID_MODEL_FROM_DATABASE=LifeCam NX-3000 (UVC-compliant) + +usb:v045Ep0723* + ID_MODEL_FROM_DATABASE=LifeCam VX-7000 (UVC-compliant) + +usb:v045Ep0724* + ID_MODEL_FROM_DATABASE=SideWinder Mouse + +usb:v045Ep0728* + ID_MODEL_FROM_DATABASE=LifeCam VX-5000 + +usb:v045Ep0730* + ID_MODEL_FROM_DATABASE=Digital Media Keyboard 3000 + +usb:v045Ep0734* + ID_MODEL_FROM_DATABASE=Wireless Optical Desktop 700 + +usb:v045Ep0736* + ID_MODEL_FROM_DATABASE=Sidewinder X5 Mouse + +usb:v045Ep0737* + ID_MODEL_FROM_DATABASE=Compact Optical Mouse 500 + +usb:v045Ep0745* + ID_MODEL_FROM_DATABASE=Nano Transceiver v1.0 for Bluetooth + +usb:v045Ep074A* + ID_MODEL_FROM_DATABASE=LifeCam VX-500 [1357] + +usb:v045Ep0750* + ID_MODEL_FROM_DATABASE=Wired Keyboard 600 + +usb:v045Ep0752* + ID_MODEL_FROM_DATABASE=Wired Keyboard 400 + +usb:v045Ep075D* + ID_MODEL_FROM_DATABASE=LifeCam Cinema + +usb:v045Ep0761* + ID_MODEL_FROM_DATABASE=LifeCam VX-2000 + +usb:v045Ep0765* + ID_MODEL_FROM_DATABASE=Xbox360 Slim Internal Wireless Module (1400) [Marvell 88W8786U] + +usb:v045Ep0766* + ID_MODEL_FROM_DATABASE=LifeCam VX-800 + +usb:v045Ep0768* + ID_MODEL_FROM_DATABASE=Sidewinder X4 + +usb:v045Ep076C* + ID_MODEL_FROM_DATABASE=Comfort Mouse 4500 + +usb:v045Ep076D* + ID_MODEL_FROM_DATABASE=LifeCam HD-5000 + +usb:v045Ep0770* + ID_MODEL_FROM_DATABASE=LifeCam VX-700 + +usb:v045Ep0772* + ID_MODEL_FROM_DATABASE=LifeCam Studio + +usb:v045Ep0779* + ID_MODEL_FROM_DATABASE=LifeCam HD-3000 + +usb:v045Ep077F* + ID_MODEL_FROM_DATABASE=LifeChat LX-6000 Headset + +usb:v045Ep0780* + ID_MODEL_FROM_DATABASE=Comfort Curve Keyboard 3000 + +usb:v045Ep0797* + ID_MODEL_FROM_DATABASE=Optical Mouse 200 + +usb:v045Ep0799* + ID_MODEL_FROM_DATABASE=Surface Pro embedded keyboard + +usb:v045Ep07A5* + ID_MODEL_FROM_DATABASE=Wireless Receiver 1461C + +usb:v045Ep07B2* + ID_MODEL_FROM_DATABASE=2.4GHz Transceiver v8.0 used by mouse Wireless Desktop 900 + +usb:v045Ep07B6* + ID_MODEL_FROM_DATABASE=Comfort Curve Keyboard 3000 + +usb:v045Ep07B9* + ID_MODEL_FROM_DATABASE=Wired Keyboard 200 + +usb:v045Ep07C6* + ID_MODEL_FROM_DATABASE=RTL8153 GigE [Surface Dock Ethernet] + +usb:v045Ep07CA* + ID_MODEL_FROM_DATABASE=Surface Pro 3 Docking Station Audio Device + +usb:v045Ep07CD* + ID_MODEL_FROM_DATABASE=Surface Keyboard + +usb:v045Ep07F8* + ID_MODEL_FROM_DATABASE=Wired Keyboard 600 (model 1576) + +usb:v045Ep07FD* + ID_MODEL_FROM_DATABASE=Nano Transceiver 1.1 + +usb:v045Ep0900* + ID_MODEL_FROM_DATABASE=Surface Dock Hub + +usb:v045Ep0901* + ID_MODEL_FROM_DATABASE=Surface Dock Hub + +usb:v045Ep0902* + ID_MODEL_FROM_DATABASE=Surface Dock Hub + +usb:v045Ep0903* + ID_MODEL_FROM_DATABASE=Surface Dock Hub + +usb:v045Ep0904* + ID_MODEL_FROM_DATABASE=Surface Dock Extender + +usb:v045Ep0905* + ID_MODEL_FROM_DATABASE=Surface Dock Audio + +usb:v045Ep090B* + ID_MODEL_FROM_DATABASE=Hub + +usb:v045Ep090C* + ID_MODEL_FROM_DATABASE=SD Card + +usb:v045Ep091A* + ID_MODEL_FROM_DATABASE=Hub + +usb:v045Ep09C0* + ID_MODEL_FROM_DATABASE=Surface Type Cover + +usb:v045Ep0A00* + ID_MODEL_FROM_DATABASE=Lumia 950 Dual SIM (RM-1118) + +usb:v045Ep930A* + ID_MODEL_FROM_DATABASE=ISOUSB.SYS Intel 82930 Isochronous IO Test Board + +usb:v045EpFFCA* + ID_MODEL_FROM_DATABASE=Catalina + +usb:v045EpFFF8* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v045EpFFFF* + ID_MODEL_FROM_DATABASE=Windows CE Mass Storage + +usb:v0460* + ID_VENDOR_FROM_DATABASE=Ace Cad Enterprise Co., Ltd + +usb:v0460p0004* + ID_MODEL_FROM_DATABASE=Tablet (5x3.75) + +usb:v0460p0006* + ID_MODEL_FROM_DATABASE=LCD Tablet (12x9) + +usb:v0460p0008* + ID_MODEL_FROM_DATABASE=Tablet (3x2.25) + +usb:v0461* + ID_VENDOR_FROM_DATABASE=Primax Electronics, Ltd + +usb:v0461p0010* + ID_MODEL_FROM_DATABASE=HP PR1101U / Primax PMX-KPR1101U Keyboard + +usb:v0461p0300* + ID_MODEL_FROM_DATABASE=G2-300 Scanner + +usb:v0461p0301* + ID_MODEL_FROM_DATABASE=G2E-300 Scanner + +usb:v0461p0302* + ID_MODEL_FROM_DATABASE=G2-300 #2 Scanner + +usb:v0461p0303* + ID_MODEL_FROM_DATABASE=G2E-300 #2 Scanner + +usb:v0461p0340* + ID_MODEL_FROM_DATABASE=Colorado 9600 Scanner + +usb:v0461p0341* + ID_MODEL_FROM_DATABASE=Colorado 600u Scanner + +usb:v0461p0345* + ID_MODEL_FROM_DATABASE=Visioneer 6200 Scanner + +usb:v0461p0346* + ID_MODEL_FROM_DATABASE=Memorex Maxx 6136u Scanner + +usb:v0461p0347* + ID_MODEL_FROM_DATABASE=Primascan Colorado 2600u/Visioneer 4400 Scanner + +usb:v0461p0360* + ID_MODEL_FROM_DATABASE=Colorado 19200 Scanner + +usb:v0461p0361* + ID_MODEL_FROM_DATABASE=Colorado 1200u Scanner + +usb:v0461p0363* + ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) + +usb:v0461p0364* + ID_MODEL_FROM_DATABASE=LG Electronics Scanworks 600U Scanner + +usb:v0461p0365* + ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) + +usb:v0461p0366* + ID_MODEL_FROM_DATABASE=6400 + +usb:v0461p0367* + ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) + +usb:v0461p0371* + ID_MODEL_FROM_DATABASE=Visioneer Onetouch 8920 Scanner + +usb:v0461p0374* + ID_MODEL_FROM_DATABASE=UMAX Astra 2500 + +usb:v0461p0375* + ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) + +usb:v0461p0377* + ID_MODEL_FROM_DATABASE=Medion MD 5345 Scanner + +usb:v0461p0378* + ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) + +usb:v0461p037B* + ID_MODEL_FROM_DATABASE=Medion MD 6190 Scanner + +usb:v0461p037C* + ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) + +usb:v0461p0380* + ID_MODEL_FROM_DATABASE=G2-600 Scanner + +usb:v0461p0381* + ID_MODEL_FROM_DATABASE=ReadyScan 636i Scanner + +usb:v0461p0382* + ID_MODEL_FROM_DATABASE=G2-600 #2 Scanner + +usb:v0461p0383* + ID_MODEL_FROM_DATABASE=G2E-600 Scanner + +usb:v0461p038A* + ID_MODEL_FROM_DATABASE=UMAX Astra 3000/3600 + +usb:v0461p038B* + ID_MODEL_FROM_DATABASE=Xerox 2400 Onetouch + +usb:v0461p038C* + ID_MODEL_FROM_DATABASE=UMAX Astra 4100 + +usb:v0461p0392* + ID_MODEL_FROM_DATABASE=Medion/Lifetec/Tevion/Cytron MD 6190 + +usb:v0461p03A8* + ID_MODEL_FROM_DATABASE=9420M + +usb:v0461p0813* + ID_MODEL_FROM_DATABASE=IBM UltraPort Camera + +usb:v0461p0815* + ID_MODEL_FROM_DATABASE=Micro Innovations IC200 Webcam + +usb:v0461p0819* + ID_MODEL_FROM_DATABASE=Fujifilm IX-30 Camera [webcam mode] + +usb:v0461p081A* + ID_MODEL_FROM_DATABASE=Fujifilm IX-30 Camera [storage mode] + +usb:v0461p081C* + ID_MODEL_FROM_DATABASE=Elitegroup ECS-C11 Camera + +usb:v0461p081D* + ID_MODEL_FROM_DATABASE=Elitegroup ECS-C11 Storage + +usb:v0461p0A00* + ID_MODEL_FROM_DATABASE=Micro Innovations Web Cam 320 + +usb:v0461p4D01* + ID_MODEL_FROM_DATABASE=Comfort Keyboard / Kensington Orbit Elite + +usb:v0461p4D02* + ID_MODEL_FROM_DATABASE=Mouse-in-a-Box + +usb:v0461p4D03* + ID_MODEL_FROM_DATABASE=Kensington Mouse-in-a-box + +usb:v0461p4D04* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v0461p4D06* + ID_MODEL_FROM_DATABASE=Balless Mouse (HID) + +usb:v0461p4D0F* + ID_MODEL_FROM_DATABASE=HP Optical Mouse + +usb:v0461p4D15* + ID_MODEL_FROM_DATABASE=Dell Optical Mouse + +usb:v0461p4D17* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v0461p4D20* + ID_MODEL_FROM_DATABASE=HP Optical Mouse + +usb:v0461p4D2A* + ID_MODEL_FROM_DATABASE=PoPo Elixir Mouse (HID) + +usb:v0461p4D2B* + ID_MODEL_FROM_DATABASE=Wireless Laser Mini Mouse (HID) + +usb:v0461p4D2C* + ID_MODEL_FROM_DATABASE=PoPo Mini Pointer Mouse (HID) + +usb:v0461p4D2E* + ID_MODEL_FROM_DATABASE=Optical Mobile Mouse (HID) + +usb:v0461p4D51* + ID_MODEL_FROM_DATABASE=0Y357C PMX-MMOCZUL (B) [Dell Laser Mouse] + +usb:v0461p4D62* + ID_MODEL_FROM_DATABASE=HP Laser Mobile Mini Mouse + +usb:v0461p4D75* + ID_MODEL_FROM_DATABASE=Rocketfish RF-FLBTAD Bluetooth Adapter + +usb:v0461p4D81* + ID_MODEL_FROM_DATABASE=Dell N889 Optical Mouse + +usb:v0461p4D91* + ID_MODEL_FROM_DATABASE=Laser mouse M-D16DL + +usb:v0461p4D92* + ID_MODEL_FROM_DATABASE=Optical mouse M-D17DR + +usb:v0461p4DB1* + ID_MODEL_FROM_DATABASE=Dell Laptop Integrated Webcam 2Mpix + +usb:v0461p4DE3* + ID_MODEL_FROM_DATABASE=HP 5-Button Optical Comfort Mouse + +usb:v0461p4DE7* + ID_MODEL_FROM_DATABASE=webcam + +usb:v0461p4E04* + ID_MODEL_FROM_DATABASE=Lenovo Keyboard KB1021 + +usb:v0463* + ID_VENDOR_FROM_DATABASE=MGE UPS Systems + +usb:v0463p0001* + ID_MODEL_FROM_DATABASE=UPS + +usb:v0463pFFFF* + ID_MODEL_FROM_DATABASE=UPS + +usb:v0464* + ID_VENDOR_FROM_DATABASE=AMP/Tycoelectronics Corp. + +usb:v0467* + ID_VENDOR_FROM_DATABASE=AT&T Paradyne + +usb:v0468* + ID_VENDOR_FROM_DATABASE=Wieson Technologies Co., Ltd + +usb:v046A* + ID_VENDOR_FROM_DATABASE=Cherry GmbH + +usb:v046Ap0001* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v046Ap0003* + ID_MODEL_FROM_DATABASE=My3000 Hub + +usb:v046Ap0004* + ID_MODEL_FROM_DATABASE=CyBoard Keyboard + +usb:v046Ap0005* + ID_MODEL_FROM_DATABASE=XX33 SmartCard Reader Keyboard + +usb:v046Ap0008* + ID_MODEL_FROM_DATABASE=Wireless Keyboard and Mouse + +usb:v046Ap0010* + ID_MODEL_FROM_DATABASE=SmartBoard XX44 + +usb:v046Ap0011* + ID_MODEL_FROM_DATABASE=G83 (RS 6000) Keyboard + +usb:v046Ap0021* + ID_MODEL_FROM_DATABASE=CyMotion Expert Combo + +usb:v046Ap0023* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v046Ap0027* + ID_MODEL_FROM_DATABASE=CyMotion Master Solar Keyboard + +usb:v046Ap002A* + ID_MODEL_FROM_DATABASE=Wireless Mouse & Keyboard + +usb:v046Ap002D* + ID_MODEL_FROM_DATABASE=SmartTerminal XX44 + +usb:v046Ap003C* + ID_MODEL_FROM_DATABASE=Raptor Gaming Keyboard + +usb:v046Ap003D* + ID_MODEL_FROM_DATABASE=Raptor Gaming Keyboard Integrated Hub + +usb:v046Ap003E* + ID_MODEL_FROM_DATABASE=SmartTerminal ST-2xxx + +usb:v046Ap0041* + ID_MODEL_FROM_DATABASE=G86 6240 Keyboard + +usb:v046Ap0080* + ID_MODEL_FROM_DATABASE=eHealth Terminal ST 1503 + +usb:v046Ap0081* + ID_MODEL_FROM_DATABASE=eHealth Keyboard G87 1504 + +usb:v046Ap00A1* + ID_MODEL_FROM_DATABASE=SmartCard Reader Keyboard KC 1000 SC + +usb:v046Ap0106* + ID_MODEL_FROM_DATABASE=R-300 Wireless Mouse Receiver + +usb:v046Ap010D* + ID_MODEL_FROM_DATABASE=MX-Board 3.0 Keyboard + +usb:v046ApB090* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v046ApB091* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v046B* + ID_VENDOR_FROM_DATABASE=American Megatrends, Inc. + +usb:v046Bp0001* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v046Bp0101* + ID_MODEL_FROM_DATABASE=PS/2 Keyboard, Mouse & Joystick Ports + +usb:v046Bp0301* + ID_MODEL_FROM_DATABASE=USB 1.0 Hub + +usb:v046Bp0500* + ID_MODEL_FROM_DATABASE=Serial & Parallel Ports + +usb:v046BpFF10* + ID_MODEL_FROM_DATABASE=Virtual Keyboard and Mouse + +usb:v046C* + ID_VENDOR_FROM_DATABASE=Toshiba Corp., Digital Media Equipment + +usb:v046D* + ID_VENDOR_FROM_DATABASE=Logitech, Inc. + +usb:v046Dp0082* + ID_MODEL_FROM_DATABASE=Acer Aspire 5672 Webcam + +usb:v046Dp0200* + ID_MODEL_FROM_DATABASE=WingMan Extreme Joystick + +usb:v046Dp0203* + ID_MODEL_FROM_DATABASE=M2452 Keyboard + +usb:v046Dp0242* + ID_MODEL_FROM_DATABASE=Chillstream for Xbox 360 + +usb:v046Dp0301* + ID_MODEL_FROM_DATABASE=M4848 Mouse + +usb:v046Dp0401* + ID_MODEL_FROM_DATABASE=HP PageScan + +usb:v046Dp0402* + ID_MODEL_FROM_DATABASE=NEC PageScan + +usb:v046Dp040F* + ID_MODEL_FROM_DATABASE=Logitech/Storm PageScan + +usb:v046Dp0430* + ID_MODEL_FROM_DATABASE=Mic (Cordless) + +usb:v046Dp0801* + ID_MODEL_FROM_DATABASE=QuickCam Home + +usb:v046Dp0802* + ID_MODEL_FROM_DATABASE=Webcam C200 + +usb:v046Dp0804* + ID_MODEL_FROM_DATABASE=Webcam C250 + +usb:v046Dp0805* + ID_MODEL_FROM_DATABASE=Webcam C300 + +usb:v046Dp0807* + ID_MODEL_FROM_DATABASE=Webcam B500 + +usb:v046Dp0808* + ID_MODEL_FROM_DATABASE=Webcam C600 + +usb:v046Dp0809* + ID_MODEL_FROM_DATABASE=Webcam Pro 9000 + +usb:v046Dp080A* + ID_MODEL_FROM_DATABASE=Portable Webcam C905 + +usb:v046Dp080F* + ID_MODEL_FROM_DATABASE=Webcam C120 + +usb:v046Dp0810* + ID_MODEL_FROM_DATABASE=QuickCam Pro + +usb:v046Dp0819* + ID_MODEL_FROM_DATABASE=Webcam C210 + +usb:v046Dp081A* + ID_MODEL_FROM_DATABASE=Webcam C260 + +usb:v046Dp081B* + ID_MODEL_FROM_DATABASE=Webcam C310 + +usb:v046Dp081D* + ID_MODEL_FROM_DATABASE=HD Webcam C510 + +usb:v046Dp0820* + ID_MODEL_FROM_DATABASE=QuickCam VC + +usb:v046Dp0821* + ID_MODEL_FROM_DATABASE=HD Webcam C910 + +usb:v046Dp0823* + ID_MODEL_FROM_DATABASE=HD Webcam B910 + +usb:v046Dp0825* + ID_MODEL_FROM_DATABASE=Webcam C270 + +usb:v046Dp0826* + ID_MODEL_FROM_DATABASE=HD Webcam C525 + +usb:v046Dp0828* + ID_MODEL_FROM_DATABASE=HD Webcam B990 + +usb:v046Dp082B* + ID_MODEL_FROM_DATABASE=Webcam C170 + +usb:v046Dp082C* + ID_MODEL_FROM_DATABASE=HD Webcam C615 + +usb:v046Dp082D* + ID_MODEL_FROM_DATABASE=HD Pro Webcam C920 + +usb:v046Dp0830* + ID_MODEL_FROM_DATABASE=QuickClip + +usb:v046Dp0836* + ID_MODEL_FROM_DATABASE=B525 HD Webcam + +usb:v046Dp0837* + ID_MODEL_FROM_DATABASE=BCC950 ConferenceCam + +usb:v046Dp0840* + ID_MODEL_FROM_DATABASE=QuickCam Express + +usb:v046Dp0843* + ID_MODEL_FROM_DATABASE=Webcam C930e + +usb:v046Dp0850* + ID_MODEL_FROM_DATABASE=QuickCam Web + +usb:v046Dp085C* + ID_MODEL_FROM_DATABASE=C922 Pro Stream Webcam + +usb:v046Dp0870* + ID_MODEL_FROM_DATABASE=QuickCam Express + +usb:v046Dp0890* + ID_MODEL_FROM_DATABASE=QuickCam Traveler + +usb:v046Dp0892* + ID_MODEL_FROM_DATABASE=OrbiCam + +usb:v046Dp0894* + ID_MODEL_FROM_DATABASE=CrystalCam + +usb:v046Dp0895* + ID_MODEL_FROM_DATABASE=QuickCam for Dell Notebooks + +usb:v046Dp0896* + ID_MODEL_FROM_DATABASE=OrbiCam + +usb:v046Dp0897* + ID_MODEL_FROM_DATABASE=QuickCam for Dell Notebooks + +usb:v046Dp0899* + ID_MODEL_FROM_DATABASE=QuickCam for Dell Notebooks + +usb:v046Dp089D* + ID_MODEL_FROM_DATABASE=QuickCam E2500 series + +usb:v046Dp08A0* + ID_MODEL_FROM_DATABASE=QuickCam IM + +usb:v046Dp08A1* + ID_MODEL_FROM_DATABASE=QuickCam IM with sound + +usb:v046Dp08A2* + ID_MODEL_FROM_DATABASE=Labtec Webcam Pro + +usb:v046Dp08A3* + ID_MODEL_FROM_DATABASE=QuickCam QuickCam Chat + +usb:v046Dp08A6* + ID_MODEL_FROM_DATABASE=QuickCam IM + +usb:v046Dp08A7* + ID_MODEL_FROM_DATABASE=QuickCam Image + +usb:v046Dp08A9* + ID_MODEL_FROM_DATABASE=Notebook Deluxe + +usb:v046Dp08AA* + ID_MODEL_FROM_DATABASE=Labtec Notebooks + +usb:v046Dp08AC* + ID_MODEL_FROM_DATABASE=QuickCam Cool + +usb:v046Dp08AD* + ID_MODEL_FROM_DATABASE=QuickCam Communicate STX + +usb:v046Dp08AE* + ID_MODEL_FROM_DATABASE=QuickCam for Notebooks + +usb:v046Dp08AF* + ID_MODEL_FROM_DATABASE=QuickCam Easy/Cool + +usb:v046Dp08B0* + ID_MODEL_FROM_DATABASE=QuickCam 3000 Pro [pwc] + +usb:v046Dp08B1* + ID_MODEL_FROM_DATABASE=QuickCam Notebook Pro + +usb:v046Dp08B2* + ID_MODEL_FROM_DATABASE=QuickCam Pro 4000 + +usb:v046Dp08B3* + ID_MODEL_FROM_DATABASE=QuickCam Zoom + +usb:v046Dp08B4* + ID_MODEL_FROM_DATABASE=QuickCam Zoom + +usb:v046Dp08B5* + ID_MODEL_FROM_DATABASE=QuickCam Sphere + +usb:v046Dp08B9* + ID_MODEL_FROM_DATABASE=QuickCam IM + +usb:v046Dp08BD* + ID_MODEL_FROM_DATABASE=Microphone (Pro 4000) + +usb:v046Dp08C0* + ID_MODEL_FROM_DATABASE=QuickCam Pro 3000 + +usb:v046Dp08C1* + ID_MODEL_FROM_DATABASE=QuickCam Fusion + +usb:v046Dp08C2* + ID_MODEL_FROM_DATABASE=QuickCam PTZ + +usb:v046Dp08C3* + ID_MODEL_FROM_DATABASE=Camera (Notebooks Pro) + +usb:v046Dp08C5* + ID_MODEL_FROM_DATABASE=QuickCam Pro 5000 + +usb:v046Dp08C6* + ID_MODEL_FROM_DATABASE=QuickCam for DELL Notebooks + +usb:v046Dp08C7* + ID_MODEL_FROM_DATABASE=QuickCam OEM Cisco VT Camera II + +usb:v046Dp08C9* + ID_MODEL_FROM_DATABASE=QuickCam Ultra Vision + +usb:v046Dp08CA* + ID_MODEL_FROM_DATABASE=Mic (Fusion) + +usb:v046Dp08CB* + ID_MODEL_FROM_DATABASE=Mic (Notebooks Pro) + +usb:v046Dp08CC* + ID_MODEL_FROM_DATABASE=Mic (PTZ) + +usb:v046Dp08CE* + ID_MODEL_FROM_DATABASE=QuickCam Pro 5000 + +usb:v046Dp08CF* + ID_MODEL_FROM_DATABASE=QuickCam UpdateMe + +usb:v046Dp08D0* + ID_MODEL_FROM_DATABASE=QuickCam Express + +usb:v046Dp08D7* + ID_MODEL_FROM_DATABASE=QuickCam Communicate STX + +usb:v046Dp08D8* + ID_MODEL_FROM_DATABASE=QuickCam for Notebook Deluxe + +usb:v046Dp08D9* + ID_MODEL_FROM_DATABASE=QuickCam IM/Connect + +usb:v046Dp08DA* + ID_MODEL_FROM_DATABASE=QuickCam Messanger + +usb:v046Dp08DD* + ID_MODEL_FROM_DATABASE=QuickCam for Notebooks + +usb:v046Dp08E0* + ID_MODEL_FROM_DATABASE=QuickCam Express + +usb:v046Dp08E1* + ID_MODEL_FROM_DATABASE=Labtec Webcam + +usb:v046Dp08F0* + ID_MODEL_FROM_DATABASE=QuickCam Messenger + +usb:v046Dp08F1* + ID_MODEL_FROM_DATABASE=QuickCam Express + +usb:v046Dp08F2* + ID_MODEL_FROM_DATABASE=Microphone (Messenger) + +usb:v046Dp08F3* + ID_MODEL_FROM_DATABASE=QuickCam Express + +usb:v046Dp08F4* + ID_MODEL_FROM_DATABASE=Labtec Webcam + +usb:v046Dp08F5* + ID_MODEL_FROM_DATABASE=QuickCam Messenger Communicate + +usb:v046Dp08F6* + ID_MODEL_FROM_DATABASE=QuickCam Messenger Plus + +usb:v046Dp0900* + ID_MODEL_FROM_DATABASE=ClickSmart 310 + +usb:v046Dp0901* + ID_MODEL_FROM_DATABASE=ClickSmart 510 + +usb:v046Dp0903* + ID_MODEL_FROM_DATABASE=ClickSmart 820 + +usb:v046Dp0905* + ID_MODEL_FROM_DATABASE=ClickSmart 820 + +usb:v046Dp0910* + ID_MODEL_FROM_DATABASE=QuickCam Cordless + +usb:v046Dp0920* + ID_MODEL_FROM_DATABASE=QuickCam Express + +usb:v046Dp0921* + ID_MODEL_FROM_DATABASE=Labtec Webcam + +usb:v046Dp0922* + ID_MODEL_FROM_DATABASE=QuickCam Live + +usb:v046Dp0928* + ID_MODEL_FROM_DATABASE=QuickCam Express + +usb:v046Dp0929* + ID_MODEL_FROM_DATABASE=Labtec Webcam Pro + +usb:v046Dp092A* + ID_MODEL_FROM_DATABASE=QuickCam for Notebooks + +usb:v046Dp092B* + ID_MODEL_FROM_DATABASE=Labtec Webcam Plus + +usb:v046Dp092C* + ID_MODEL_FROM_DATABASE=QuickCam Chat + +usb:v046Dp092D* + ID_MODEL_FROM_DATABASE=QuickCam Express / Go + +usb:v046Dp092E* + ID_MODEL_FROM_DATABASE=QuickCam Chat + +usb:v046Dp092F* + ID_MODEL_FROM_DATABASE=QuickCam Express Plus + +usb:v046Dp0950* + ID_MODEL_FROM_DATABASE=Pocket Camera + +usb:v046Dp0960* + ID_MODEL_FROM_DATABASE=ClickSmart 420 + +usb:v046Dp0970* + ID_MODEL_FROM_DATABASE=Pocket750 + +usb:v046Dp0990* + ID_MODEL_FROM_DATABASE=QuickCam Pro 9000 + +usb:v046Dp0991* + ID_MODEL_FROM_DATABASE=QuickCam Pro for Notebooks + +usb:v046Dp0992* + ID_MODEL_FROM_DATABASE=QuickCam Communicate Deluxe + +usb:v046Dp0994* + ID_MODEL_FROM_DATABASE=QuickCam Orbit/Sphere AF + +usb:v046Dp09A1* + ID_MODEL_FROM_DATABASE=QuickCam Communicate MP/S5500 + +usb:v046Dp09A2* + ID_MODEL_FROM_DATABASE=QuickCam Communicate Deluxe/S7500 + +usb:v046Dp09A4* + ID_MODEL_FROM_DATABASE=QuickCam E 3500 + +usb:v046Dp09A5* + ID_MODEL_FROM_DATABASE=Quickcam 3000 For Business + +usb:v046Dp09A6* + ID_MODEL_FROM_DATABASE=QuickCam Vision Pro + +usb:v046Dp09B0* + ID_MODEL_FROM_DATABASE=Acer OrbiCam + +usb:v046Dp09B2* + ID_MODEL_FROM_DATABASE=Fujitsu Webcam + +usb:v046Dp09C0* + ID_MODEL_FROM_DATABASE=QuickCam for Dell Notebooks Mic + +usb:v046Dp09C1* + ID_MODEL_FROM_DATABASE=QuickCam Deluxe for Notebooks + +usb:v046Dp0A01* + ID_MODEL_FROM_DATABASE=USB Headset + +usb:v046Dp0A02* + ID_MODEL_FROM_DATABASE=Premium Stereo USB Headset 350 + +usb:v046Dp0A03* + ID_MODEL_FROM_DATABASE=Logitech USB Microphone + +usb:v046Dp0A04* + ID_MODEL_FROM_DATABASE=V20 portable speakers (USB powered) + +usb:v046Dp0A07* + ID_MODEL_FROM_DATABASE=Z-10 Speakers + +usb:v046Dp0A0B* + ID_MODEL_FROM_DATABASE=ClearChat Pro USB + +usb:v046Dp0A0C* + ID_MODEL_FROM_DATABASE=Clear Chat Comfort USB Headset + +usb:v046Dp0A13* + ID_MODEL_FROM_DATABASE=Z-5 Speakers + +usb:v046Dp0A14* + ID_MODEL_FROM_DATABASE=USB Headset + +usb:v046Dp0A15* + ID_MODEL_FROM_DATABASE=G35 Headset + +usb:v046Dp0A17* + ID_MODEL_FROM_DATABASE=G330 Headset + +usb:v046Dp0A1F* + ID_MODEL_FROM_DATABASE=G930 + +usb:v046Dp0A29* + ID_MODEL_FROM_DATABASE=H600 [Wireless Headset] + +usb:v046Dp0A37* + ID_MODEL_FROM_DATABASE=USB Headset H540 + +usb:v046Dp0A38* + ID_MODEL_FROM_DATABASE=Headset H340 + +usb:v046Dp0A44* + ID_MODEL_FROM_DATABASE=Headset H390 + +usb:v046Dp0A45* + ID_MODEL_FROM_DATABASE=960 Headset + +usb:v046Dp0A4D* + ID_MODEL_FROM_DATABASE=G430 Surround Sound Gaming Headset + +usb:v046Dp0A5B* + ID_MODEL_FROM_DATABASE=G933 Wireless Headset Dongle + +usb:v046Dp0A66* + ID_MODEL_FROM_DATABASE=[G533 Wireless Headset Dongle] + +usb:v046Dp0B02* + ID_MODEL_FROM_DATABASE=C-UV35 [Bluetooth Mini-Receiver] (HID proxy mode) + +usb:v046Dp8801* + ID_MODEL_FROM_DATABASE=Video Camera + +usb:v046DpB014* + ID_MODEL_FROM_DATABASE=Bluetooth Mouse M336/M337/M535 + +usb:v046DpB305* + ID_MODEL_FROM_DATABASE=BT Mini-Receiver + +usb:v046DpBFE4* + ID_MODEL_FROM_DATABASE=Premium Optical Wheel Mouse + +usb:v046DpC000* + ID_MODEL_FROM_DATABASE=N43 [Pilot Mouse] + +usb:v046DpC001* + ID_MODEL_FROM_DATABASE=N48/M-BB48/M-UK96A [FirstMouse Plus] + +usb:v046DpC002* + ID_MODEL_FROM_DATABASE=M-BA47 [MouseMan Plus] + +usb:v046DpC003* + ID_MODEL_FROM_DATABASE=MouseMan + +usb:v046DpC004* + ID_MODEL_FROM_DATABASE=WingMan Gaming Mouse + +usb:v046DpC005* + ID_MODEL_FROM_DATABASE=WingMan Gaming Wheel Mouse + +usb:v046DpC00B* + ID_MODEL_FROM_DATABASE=MouseMan Wheel + +usb:v046DpC00C* + ID_MODEL_FROM_DATABASE=Optical Wheel Mouse + +usb:v046DpC00D* + ID_MODEL_FROM_DATABASE=MouseMan Wheel+ + +usb:v046DpC00E* + ID_MODEL_FROM_DATABASE=M-BJ58/M-BJ69 Optical Wheel Mouse + +usb:v046DpC00F* + ID_MODEL_FROM_DATABASE=MouseMan Traveler/Mobile + +usb:v046DpC011* + ID_MODEL_FROM_DATABASE=Optical MouseMan + +usb:v046DpC012* + ID_MODEL_FROM_DATABASE=Mouseman Dual Optical + +usb:v046DpC014* + ID_MODEL_FROM_DATABASE=Corded Workstation Mouse + +usb:v046DpC015* + ID_MODEL_FROM_DATABASE=Corded Workstation Mouse + +usb:v046DpC016* + ID_MODEL_FROM_DATABASE=Optical Wheel Mouse + +usb:v046DpC018* + ID_MODEL_FROM_DATABASE=Optical Wheel Mouse + +usb:v046DpC019* + ID_MODEL_FROM_DATABASE=Optical Tilt Wheel Mouse + +usb:v046DpC01A* + ID_MODEL_FROM_DATABASE=M-BQ85 Optical Wheel Mouse + +usb:v046DpC01B* + ID_MODEL_FROM_DATABASE=MX310 Optical Mouse + +usb:v046DpC01C* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v046DpC01D* + ID_MODEL_FROM_DATABASE=MX510 Optical Mouse + +usb:v046DpC01E* + ID_MODEL_FROM_DATABASE=MX518 Optical Mouse + +usb:v046DpC024* + ID_MODEL_FROM_DATABASE=MX300 Optical Mouse + +usb:v046DpC025* + ID_MODEL_FROM_DATABASE=MX500 Optical Mouse + +usb:v046DpC030* + ID_MODEL_FROM_DATABASE=iFeel Mouse + +usb:v046DpC031* + ID_MODEL_FROM_DATABASE=iFeel Mouse+ + +usb:v046DpC032* + ID_MODEL_FROM_DATABASE=MouseMan iFeel + +usb:v046DpC033* + ID_MODEL_FROM_DATABASE=iFeel MouseMan+ + +usb:v046DpC034* + ID_MODEL_FROM_DATABASE=MouseMan Optical + +usb:v046DpC035* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v046DpC036* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v046DpC037* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v046DpC038* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v046DpC03D* + ID_MODEL_FROM_DATABASE=M-BT96a Pilot Optical Mouse + +usb:v046DpC03E* + ID_MODEL_FROM_DATABASE=Premium Optical Wheel Mouse (M-BT58) + +usb:v046DpC03F* + ID_MODEL_FROM_DATABASE=M-BT85 [UltraX Optical Mouse] + +usb:v046DpC040* + ID_MODEL_FROM_DATABASE=Corded Tilt-Wheel Mouse + +usb:v046DpC041* + ID_MODEL_FROM_DATABASE=G5 Laser Mouse + +usb:v046DpC042* + ID_MODEL_FROM_DATABASE=G3 Laser Mouse + +usb:v046DpC043* + ID_MODEL_FROM_DATABASE=MX320/MX400 Laser Mouse + +usb:v046DpC044* + ID_MODEL_FROM_DATABASE=LX3 Optical Mouse + +usb:v046DpC045* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v046DpC046* + ID_MODEL_FROM_DATABASE=RX1000 Laser Mouse + +usb:v046DpC047* + ID_MODEL_FROM_DATABASE=Laser Mouse M-UAL120 + +usb:v046DpC048* + ID_MODEL_FROM_DATABASE=G9 Laser Mouse + +usb:v046DpC049* + ID_MODEL_FROM_DATABASE=G5 Laser Mouse + +usb:v046DpC050* + ID_MODEL_FROM_DATABASE=RX 250 Optical Mouse + +usb:v046DpC051* + ID_MODEL_FROM_DATABASE=G3 (MX518) Optical Mouse + +usb:v046DpC053* + ID_MODEL_FROM_DATABASE=Laser Mouse + +usb:v046DpC054* + ID_MODEL_FROM_DATABASE=Bluetooth mini-receiver + +usb:v046DpC058* + ID_MODEL_FROM_DATABASE=M115 Mouse + +usb:v046DpC05A* + ID_MODEL_FROM_DATABASE=M90/M100 Optical Mouse + +usb:v046DpC05B* + ID_MODEL_FROM_DATABASE=M-U0004 810-001317 [B110 Optical USB Mouse] + +usb:v046DpC05D* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v046DpC05F* + ID_MODEL_FROM_DATABASE=M115 Optical Mouse + +usb:v046DpC061* + ID_MODEL_FROM_DATABASE=RX1500 Laser Mouse + +usb:v046DpC062* + ID_MODEL_FROM_DATABASE=M-UAS144 [LS1 Laser Mouse] + +usb:v046DpC063* + ID_MODEL_FROM_DATABASE=DELL Laser Mouse + +usb:v046DpC064* + ID_MODEL_FROM_DATABASE=M110 corded optical mouse (M-B0001) + +usb:v046DpC066* + ID_MODEL_FROM_DATABASE=G9x Laser Mouse + +usb:v046DpC068* + ID_MODEL_FROM_DATABASE=G500 Laser Mouse + +usb:v046DpC069* + ID_MODEL_FROM_DATABASE=M-U0007 [Corded Mouse M500] + +usb:v046DpC06A* + ID_MODEL_FROM_DATABASE=USB Optical Mouse + +usb:v046DpC06B* + ID_MODEL_FROM_DATABASE=G700 Wireless Gaming Mouse + +usb:v046DpC06C* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v046DpC077* + ID_MODEL_FROM_DATABASE=M105 Optical Mouse + +usb:v046DpC07C* + ID_MODEL_FROM_DATABASE=M-R0017 [G700s Rechargeable Gaming Mouse] + +usb:v046DpC07D* + ID_MODEL_FROM_DATABASE=G502 Mouse + +usb:v046DpC07E* + ID_MODEL_FROM_DATABASE=G402 Gaming Mouse + +usb:v046DpC080* + ID_MODEL_FROM_DATABASE=G303 Gaming Mouse + +usb:v046DpC083* + ID_MODEL_FROM_DATABASE=G403 Prodigy Gaming Mouse + +usb:v046DpC084* + ID_MODEL_FROM_DATABASE=G203 Gaming Mouse + +usb:v046DpC101* + ID_MODEL_FROM_DATABASE=UltraX Media Remote + +usb:v046DpC110* + ID_MODEL_FROM_DATABASE=Harmony 785/880/885 Remote + +usb:v046DpC111* + ID_MODEL_FROM_DATABASE=Harmony 525 Remote + +usb:v046DpC112* + ID_MODEL_FROM_DATABASE=Harmony 890 Remote + +usb:v046DpC11F* + ID_MODEL_FROM_DATABASE=Harmony 900/1100 Remote + +usb:v046DpC121* + ID_MODEL_FROM_DATABASE=Harmony One Remote + +usb:v046DpC122* + ID_MODEL_FROM_DATABASE=Harmony 650/700 Remote + +usb:v046DpC124* + ID_MODEL_FROM_DATABASE=Harmony 300/350 Remote + +usb:v046DpC125* + ID_MODEL_FROM_DATABASE=Harmony 200 Remote + +usb:v046DpC126* + ID_MODEL_FROM_DATABASE=Harmony Link + +usb:v046DpC129* + ID_MODEL_FROM_DATABASE=Harmony Hub + +usb:v046DpC12B* + ID_MODEL_FROM_DATABASE=Harmony Touch/Ultimate Remote + +usb:v046DpC201* + ID_MODEL_FROM_DATABASE=WingMan Extreme Joystick with Throttle + +usb:v046DpC202* + ID_MODEL_FROM_DATABASE=WingMan Formula + +usb:v046DpC207* + ID_MODEL_FROM_DATABASE=WingMan Extreme Digital 3D + +usb:v046DpC208* + ID_MODEL_FROM_DATABASE=WingMan Gamepad Extreme + +usb:v046DpC209* + ID_MODEL_FROM_DATABASE=WingMan Gamepad + +usb:v046DpC20A* + ID_MODEL_FROM_DATABASE=WingMan RumblePad + +usb:v046DpC20B* + ID_MODEL_FROM_DATABASE=WingMan Action Pad + +usb:v046DpC20C* + ID_MODEL_FROM_DATABASE=WingMan Precision + +usb:v046DpC20D* + ID_MODEL_FROM_DATABASE=WingMan Attack 2 + +usb:v046DpC20E* + ID_MODEL_FROM_DATABASE=WingMan Formula GP + +usb:v046DpC211* + ID_MODEL_FROM_DATABASE=iTouch Cordless Receiver + +usb:v046DpC212* + ID_MODEL_FROM_DATABASE=WingMan Extreme Digital 3D + +usb:v046DpC213* + ID_MODEL_FROM_DATABASE=J-UH16 (Freedom 2.4 Cordless Joystick) + +usb:v046DpC214* + ID_MODEL_FROM_DATABASE=ATK3 (Attack III Joystick) + +usb:v046DpC215* + ID_MODEL_FROM_DATABASE=Extreme 3D Pro + +usb:v046DpC216* + ID_MODEL_FROM_DATABASE=F310 Gamepad [DirectInput Mode] + +usb:v046DpC218* + ID_MODEL_FROM_DATABASE=F510 Gamepad [DirectInput Mode] + +usb:v046DpC219* + ID_MODEL_FROM_DATABASE=F710 Gamepad [DirectInput Mode] + +usb:v046DpC21A* + ID_MODEL_FROM_DATABASE=Precision Gamepad + +usb:v046DpC21C* + ID_MODEL_FROM_DATABASE=G13 Advanced Gameboard + +usb:v046DpC21D* + ID_MODEL_FROM_DATABASE=F310 Gamepad [XInput Mode] + +usb:v046DpC21E* + ID_MODEL_FROM_DATABASE=F510 Gamepad [XInput Mode] + +usb:v046DpC21F* + ID_MODEL_FROM_DATABASE=F710 Wireless Gamepad [XInput Mode] + +usb:v046DpC221* + ID_MODEL_FROM_DATABASE=G11/G15 Keyboard / Keyboard + +usb:v046DpC222* + ID_MODEL_FROM_DATABASE=G15 Keyboard / LCD + +usb:v046DpC223* + ID_MODEL_FROM_DATABASE=G11/G15 Keyboard / USB Hub + +usb:v046DpC225* + ID_MODEL_FROM_DATABASE=G11/G15 Keyboard / G keys + +usb:v046DpC226* + ID_MODEL_FROM_DATABASE=G15 Refresh Keyboard + +usb:v046DpC227* + ID_MODEL_FROM_DATABASE=G15 Refresh Keyboard + +usb:v046DpC228* + ID_MODEL_FROM_DATABASE=G19 Gaming Keyboard + +usb:v046DpC229* + ID_MODEL_FROM_DATABASE=G19 Gaming Keyboard Macro Interface + +usb:v046DpC22A* + ID_MODEL_FROM_DATABASE=Gaming Keyboard G110 + +usb:v046DpC22B* + ID_MODEL_FROM_DATABASE=Gaming Keyboard G110 G-keys + +usb:v046DpC22D* + ID_MODEL_FROM_DATABASE=G510 Gaming Keyboard + +usb:v046DpC22E* + ID_MODEL_FROM_DATABASE=G510 Gaming Keyboard onboard audio + +usb:v046DpC231* + ID_MODEL_FROM_DATABASE=G13 Virtual Mouse + +usb:v046DpC245* + ID_MODEL_FROM_DATABASE=G400 Optical Mouse + +usb:v046DpC246* + ID_MODEL_FROM_DATABASE=Gaming Mouse G300 + +usb:v046DpC248* + ID_MODEL_FROM_DATABASE=G105 Gaming Keyboard + +usb:v046DpC24A* + ID_MODEL_FROM_DATABASE=G600 Gaming Mouse + +usb:v046DpC24C* + ID_MODEL_FROM_DATABASE=G400s Optical Mouse + +usb:v046DpC24D* + ID_MODEL_FROM_DATABASE=G710 Gaming Keyboard + +usb:v046DpC24E* + ID_MODEL_FROM_DATABASE=G500s Laser Gaming Mouse + +usb:v046DpC281* + ID_MODEL_FROM_DATABASE=WingMan Force + +usb:v046DpC283* + ID_MODEL_FROM_DATABASE=WingMan Force 3D + +usb:v046DpC285* + ID_MODEL_FROM_DATABASE=WingMan Strike Force 3D + +usb:v046DpC286* + ID_MODEL_FROM_DATABASE=Force 3D Pro + +usb:v046DpC287* + ID_MODEL_FROM_DATABASE=Flight System G940 + +usb:v046DpC291* + ID_MODEL_FROM_DATABASE=WingMan Formula Force + +usb:v046DpC293* + ID_MODEL_FROM_DATABASE=WingMan Formula Force GP + +usb:v046DpC294* + ID_MODEL_FROM_DATABASE=Driving Force + +usb:v046DpC295* + ID_MODEL_FROM_DATABASE=Momo Force Steering Wheel + +usb:v046DpC298* + ID_MODEL_FROM_DATABASE=Driving Force Pro + +usb:v046DpC299* + ID_MODEL_FROM_DATABASE=G25 Racing Wheel + +usb:v046DpC29B* + ID_MODEL_FROM_DATABASE=G27 Racing Wheel + +usb:v046DpC29C* + ID_MODEL_FROM_DATABASE=Speed Force Wireless Wheel for Wii + +usb:v046DpC2A0* + ID_MODEL_FROM_DATABASE=Wingman Force Feedback Mouse + +usb:v046DpC2A1* + ID_MODEL_FROM_DATABASE=WingMan Force Feedback Mouse + +usb:v046DpC2AB* + ID_MODEL_FROM_DATABASE=G13 Joystick + +usb:v046DpC301* + ID_MODEL_FROM_DATABASE=iTouch Keyboard + +usb:v046DpC302* + ID_MODEL_FROM_DATABASE=iTouch Pro Keyboard + +usb:v046DpC303* + ID_MODEL_FROM_DATABASE=iTouch Keyboard + +usb:v046DpC305* + ID_MODEL_FROM_DATABASE=Internet Keyboard + +usb:v046DpC307* + ID_MODEL_FROM_DATABASE=Internet Keyboard + +usb:v046DpC308* + ID_MODEL_FROM_DATABASE=Internet Navigator Keyboard + +usb:v046DpC309* + ID_MODEL_FROM_DATABASE=Y-BF37 [Internet Navigator Keyboard] + +usb:v046DpC30A* + ID_MODEL_FROM_DATABASE=iTouch Composite + +usb:v046DpC30B* + ID_MODEL_FROM_DATABASE=NetPlay Keyboard + +usb:v046DpC30C* + ID_MODEL_FROM_DATABASE=Internet Keys (X) + +usb:v046DpC30D* + ID_MODEL_FROM_DATABASE=Internet Keys + +usb:v046DpC30E* + ID_MODEL_FROM_DATABASE=UltraX Keyboard (Y-BL49) + +usb:v046DpC30F* + ID_MODEL_FROM_DATABASE=Logicool HID-Compliant Keyboard (106 key) + +usb:v046DpC311* + ID_MODEL_FROM_DATABASE=Y-UF49 [Internet Pro Keyboard] + +usb:v046DpC312* + ID_MODEL_FROM_DATABASE=DeLuxe 250 Keyboard + +usb:v046DpC313* + ID_MODEL_FROM_DATABASE=Internet 350 Keyboard + +usb:v046DpC315* + ID_MODEL_FROM_DATABASE=Classic Keyboard 200 + +usb:v046DpC316* + ID_MODEL_FROM_DATABASE=HID-Compliant Keyboard + +usb:v046DpC317* + ID_MODEL_FROM_DATABASE=Wave Corded Keyboard + +usb:v046DpC318* + ID_MODEL_FROM_DATABASE=Illuminated Keyboard + +usb:v046DpC31A* + ID_MODEL_FROM_DATABASE=Comfort Wave 450 + +usb:v046DpC31B* + ID_MODEL_FROM_DATABASE=Compact Keyboard K300 + +usb:v046DpC31C* + ID_MODEL_FROM_DATABASE=Keyboard K120 + +usb:v046DpC31D* + ID_MODEL_FROM_DATABASE=Media Keyboard K200 + +usb:v046DpC31F* + ID_MODEL_FROM_DATABASE=Comfort Keyboard K290 + +usb:v046DpC326* + ID_MODEL_FROM_DATABASE=Washable Keyboard K310 + +usb:v046DpC328* + ID_MODEL_FROM_DATABASE=Corded Keyboard K280e + +usb:v046DpC332* + ID_MODEL_FROM_DATABASE=G502 Proteus Spectrum Optical Mouse + +usb:v046DpC335* + ID_MODEL_FROM_DATABASE=G910 Orion Spectrum Mechanical Keyboard + +usb:v046DpC33A* + ID_MODEL_FROM_DATABASE=G413 Gaming Keyboard + +usb:v046DpC401* + ID_MODEL_FROM_DATABASE=TrackMan Marble Wheel + +usb:v046DpC402* + ID_MODEL_FROM_DATABASE=Marble Mouse (2-button) + +usb:v046DpC403* + ID_MODEL_FROM_DATABASE=Turbo TrackMan Marble FX + +usb:v046DpC404* + ID_MODEL_FROM_DATABASE=TrackMan Wheel + +usb:v046DpC408* + ID_MODEL_FROM_DATABASE=Marble Mouse (4-button) + +usb:v046DpC501* + ID_MODEL_FROM_DATABASE=Cordless Mouse Receiver + +usb:v046DpC502* + ID_MODEL_FROM_DATABASE=Cordless Mouse & iTouch Keys + +usb:v046DpC503* + ID_MODEL_FROM_DATABASE=Cordless Mouse+Keyboard Receiver + +usb:v046DpC504* + ID_MODEL_FROM_DATABASE=Cordless Mouse+Keyboard Receiver + +usb:v046DpC505* + ID_MODEL_FROM_DATABASE=Cordless Mouse+Keyboard Receiver + +usb:v046DpC506* + ID_MODEL_FROM_DATABASE=MX700 Cordless Mouse Receiver + +usb:v046DpC508* + ID_MODEL_FROM_DATABASE=Cordless Trackball + +usb:v046DpC509* + ID_MODEL_FROM_DATABASE=Cordless Keyboard & Mouse + +usb:v046DpC50A* + ID_MODEL_FROM_DATABASE=Cordless Mouse + +usb:v046DpC50B* + ID_MODEL_FROM_DATABASE=Cordless Desktop Optical + +usb:v046DpC50C* + ID_MODEL_FROM_DATABASE=Cordless Desktop S510 + +usb:v046DpC50D* + ID_MODEL_FROM_DATABASE=Cordless Mouse + +usb:v046DpC50E* + ID_MODEL_FROM_DATABASE=Cordless Mouse Receiver + +usb:v046DpC510* + ID_MODEL_FROM_DATABASE=Cordless Mouse + +usb:v046DpC512* + ID_MODEL_FROM_DATABASE=LX-700 Cordless Desktop Receiver + +usb:v046DpC513* + ID_MODEL_FROM_DATABASE=MX3000 Cordless Desktop Receiver + +usb:v046DpC514* + ID_MODEL_FROM_DATABASE=Cordless Mouse + +usb:v046DpC515* + ID_MODEL_FROM_DATABASE=Cordless 2.4 GHz Presenter Presentation remote control + +usb:v046DpC517* + ID_MODEL_FROM_DATABASE=LX710 Cordless Desktop Laser + +usb:v046DpC518* + ID_MODEL_FROM_DATABASE=MX610 Laser Cordless Mouse + +usb:v046DpC51A* + ID_MODEL_FROM_DATABASE=MX Revolution/G7 Cordless Mouse + +usb:v046DpC51B* + ID_MODEL_FROM_DATABASE=V220 Cordless Optical Mouse for Notebooks + +usb:v046DpC521* + ID_MODEL_FROM_DATABASE=Cordless Mouse Receiver + +usb:v046DpC525* + ID_MODEL_FROM_DATABASE=MX Revolution Cordless Mouse + +usb:v046DpC526* + ID_MODEL_FROM_DATABASE=Nano Receiver + +usb:v046DpC529* + ID_MODEL_FROM_DATABASE=Logitech Keyboard + Mice + +usb:v046DpC52B* + ID_MODEL_FROM_DATABASE=Unifying Receiver + +usb:v046DpC52D* + ID_MODEL_FROM_DATABASE=R700 Remote Presenter receiver + +usb:v046DpC52E* + ID_MODEL_FROM_DATABASE=MK260 Wireless Combo Receiver + +usb:v046DpC52F* + ID_MODEL_FROM_DATABASE=Unifying Receiver + +usb:v046DpC531* + ID_MODEL_FROM_DATABASE=C-U0007 [Unifying Receiver] + +usb:v046DpC532* + ID_MODEL_FROM_DATABASE=Unifying Receiver + +usb:v046DpC534* + ID_MODEL_FROM_DATABASE=Unifying Receiver + +usb:v046DpC603* + ID_MODEL_FROM_DATABASE=3Dconnexion Spacemouse Plus XT + +usb:v046DpC605* + ID_MODEL_FROM_DATABASE=3Dconnexion CADman + +usb:v046DpC606* + ID_MODEL_FROM_DATABASE=3Dconnexion Spacemouse Classic + +usb:v046DpC621* + ID_MODEL_FROM_DATABASE=3Dconnexion Spaceball 5000 + +usb:v046DpC623* + ID_MODEL_FROM_DATABASE=3Dconnexion Space Traveller 3D Mouse + +usb:v046DpC625* + ID_MODEL_FROM_DATABASE=3Dconnexion Space Pilot 3D Mouse + +usb:v046DpC626* + ID_MODEL_FROM_DATABASE=3Dconnexion Space Navigator 3D Mouse + +usb:v046DpC627* + ID_MODEL_FROM_DATABASE=3Dconnexion Space Explorer 3D Mouse + +usb:v046DpC628* + ID_MODEL_FROM_DATABASE=3Dconnexion Space Navigator for Notebooks + +usb:v046DpC629* + ID_MODEL_FROM_DATABASE=3Dconnexion SpacePilot Pro 3D Mouse + +usb:v046DpC62B* + ID_MODEL_FROM_DATABASE=3Dconnexion Space Mouse Pro + +usb:v046DpC640* + ID_MODEL_FROM_DATABASE=NuLOOQ navigator + +usb:v046DpC702* + ID_MODEL_FROM_DATABASE=Cordless Presenter + +usb:v046DpC703* + ID_MODEL_FROM_DATABASE=Elite Keyboard Y-RP20 + Mouse MX900 (Bluetooth) + +usb:v046DpC704* + ID_MODEL_FROM_DATABASE=diNovo Wireless Desktop + +usb:v046DpC705* + ID_MODEL_FROM_DATABASE=MX900 Bluetooth Wireless Hub (C-UJ16A) + +usb:v046DpC707* + ID_MODEL_FROM_DATABASE=Bluetooth wireless hub + +usb:v046DpC708* + ID_MODEL_FROM_DATABASE=Bluetooth wireless hub + +usb:v046DpC709* + ID_MODEL_FROM_DATABASE=BT Mini-Receiver (HCI mode) + +usb:v046DpC70A* + ID_MODEL_FROM_DATABASE=MX5000 Cordless Desktop + +usb:v046DpC70B* + ID_MODEL_FROM_DATABASE=BT Mini-Receiver (HID proxy mode) + +usb:v046DpC70C* + ID_MODEL_FROM_DATABASE=BT Mini-Receiver (HID proxy mode) + +usb:v046DpC70D* + ID_MODEL_FROM_DATABASE=Bluetooth wireless hub + +usb:v046DpC70E* + ID_MODEL_FROM_DATABASE=MX1000 Bluetooth Laser Mouse + +usb:v046DpC70F* + ID_MODEL_FROM_DATABASE=Bluetooth wireless hub + +usb:v046DpC712* + ID_MODEL_FROM_DATABASE=Bluetooth wireless hub + +usb:v046DpC714* + ID_MODEL_FROM_DATABASE=diNovo Edge Keyboard + +usb:v046DpC715* + ID_MODEL_FROM_DATABASE=Bluetooth wireless hub + +usb:v046DpC71A* + ID_MODEL_FROM_DATABASE=Bluetooth wireless hub + +usb:v046DpC71D* + ID_MODEL_FROM_DATABASE=Bluetooth wireless hub + +usb:v046DpC71F* + ID_MODEL_FROM_DATABASE=diNovo Mini Wireless Keyboard + +usb:v046DpC720* + ID_MODEL_FROM_DATABASE=Bluetooth wireless hub + +usb:v046DpCA03* + ID_MODEL_FROM_DATABASE=MOMO Racing + +usb:v046DpCA04* + ID_MODEL_FROM_DATABASE=Formula Vibration Feedback Wheel + +usb:v046DpCA84* + ID_MODEL_FROM_DATABASE=Cordless Controller for Xbox + +usb:v046DpCA88* + ID_MODEL_FROM_DATABASE=Thunderpad for Xbox + +usb:v046DpCA8A* + ID_MODEL_FROM_DATABASE=Precision Vibration Feedback Wheel for Xbox + +usb:v046DpCAA3* + ID_MODEL_FROM_DATABASE=DriveFX Racing Wheel + +usb:v046DpCAB1* + ID_MODEL_FROM_DATABASE=Cordless Keyboard for Wii HID Receiver + +usb:v046DpD001* + ID_MODEL_FROM_DATABASE=QuickCam Pro + +usb:v046DpF301* + ID_MODEL_FROM_DATABASE=Controller + +usb:v046E* + ID_VENDOR_FROM_DATABASE=Behavior Tech. Computer Corp. + +usb:v046Ep0100* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v046Ep3001* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v046Ep3002* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v046Ep3003* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v046Ep3005* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v046Ep3008* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v046Ep5250* + ID_MODEL_FROM_DATABASE=KeyMaestro Multimedia Keyboard + +usb:v046Ep5273* + ID_MODEL_FROM_DATABASE=KeyMaestro Multimedia Keyboard + +usb:v046Ep52E6* + ID_MODEL_FROM_DATABASE=Cordless Mouse + +usb:v046Ep5308* + ID_MODEL_FROM_DATABASE=KeyMaestro Keyboard + +usb:v046Ep5408* + ID_MODEL_FROM_DATABASE=KeyMaestro Multimedia Keyboard/Hub + +usb:v046Ep5500* + ID_MODEL_FROM_DATABASE=Portable Keyboard 86+9 keys (Model 6100C US) + +usb:v046Ep5550* + ID_MODEL_FROM_DATABASE=5 button optical mouse model M873U + +usb:v046Ep5720* + ID_MODEL_FROM_DATABASE=Smart Card Reader + +usb:v046Ep6782* + ID_MODEL_FROM_DATABASE=BTC 7932 mouse+keyboard + +usb:v046F* + ID_VENDOR_FROM_DATABASE=Crystal Semiconductor + +usb:v0471* + ID_VENDOR_FROM_DATABASE=Philips (or NXP) + +usb:v0471p0101* + ID_MODEL_FROM_DATABASE=DSS350 Digital Speaker System + +usb:v0471p0104* + ID_MODEL_FROM_DATABASE=DSS330 Digital Speaker System [uda1321] + +usb:v0471p0105* + ID_MODEL_FROM_DATABASE=UDA1321 + +usb:v0471p014F* + ID_MODEL_FROM_DATABASE=GoGear SA9200 + +usb:v0471p0160* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0471p0161* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0471p0163* + ID_MODEL_FROM_DATABASE=GoGear SA1100 + +usb:v0471p0164* + ID_MODEL_FROM_DATABASE=GoGear SA1110/02 + +usb:v0471p0165* + ID_MODEL_FROM_DATABASE=GoGear SA1330 + +usb:v0471p0201* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0471p0222* + ID_MODEL_FROM_DATABASE=Creative Nomad Jukebox + +usb:v0471p0302* + ID_MODEL_FROM_DATABASE=PCA645VC Webcam [pwc] + +usb:v0471p0303* + ID_MODEL_FROM_DATABASE=PCA646VC Webcam [pwc] + +usb:v0471p0304* + ID_MODEL_FROM_DATABASE=Askey VC010 Webcam [pwc] + +usb:v0471p0307* + ID_MODEL_FROM_DATABASE=PCVC675K Webcam [pwc] + +usb:v0471p0308* + ID_MODEL_FROM_DATABASE=PCVC680K Webcam [pwc] + +usb:v0471p030B* + ID_MODEL_FROM_DATABASE=PC VGA Camera (Vesta Fun) + +usb:v0471p030C* + ID_MODEL_FROM_DATABASE=PCVC690K Webcam [pwc] + +usb:v0471p0310* + ID_MODEL_FROM_DATABASE=PCVC730K Webcam [pwc] + +usb:v0471p0311* + ID_MODEL_FROM_DATABASE=PCVC740K ToUcam Pro [pwc] + +usb:v0471p0312* + ID_MODEL_FROM_DATABASE=PCVC750K Webcam [pwc] + +usb:v0471p0314* + ID_MODEL_FROM_DATABASE=DMVC 1000K + +usb:v0471p0316* + ID_MODEL_FROM_DATABASE=DMVC 2000K Video Capture + +usb:v0471p0321* + ID_MODEL_FROM_DATABASE=FunCam + +usb:v0471p0322* + ID_MODEL_FROM_DATABASE=DMVC1300K PC Camera + +usb:v0471p0325* + ID_MODEL_FROM_DATABASE=SPC 200NC PC Camera + +usb:v0471p0326* + ID_MODEL_FROM_DATABASE=SPC 300NC PC Camera + +usb:v0471p0327* + ID_MODEL_FROM_DATABASE=Webcam SPC 6000 NC (Webcam w/ mic) + +usb:v0471p0328* + ID_MODEL_FROM_DATABASE=SPC 700NC PC Camera + +usb:v0471p0329* + ID_MODEL_FROM_DATABASE=SPC 900NC PC Camera / ORITE CCD Webcam(PC370R) + +usb:v0471p032D* + ID_MODEL_FROM_DATABASE=SPC 210NC PC Camera + +usb:v0471p032E* + ID_MODEL_FROM_DATABASE=SPC 315NC PC Camera + +usb:v0471p0330* + ID_MODEL_FROM_DATABASE=SPC 710NC PC Camera + +usb:v0471p0331* + ID_MODEL_FROM_DATABASE=SPC 1300NC PC Camera + +usb:v0471p0332* + ID_MODEL_FROM_DATABASE=SPC 1000NC PC Camera + +usb:v0471p0333* + ID_MODEL_FROM_DATABASE=SPC 620NC PC Camera + +usb:v0471p0334* + ID_MODEL_FROM_DATABASE=SPC 520/525NC PC Camera + +usb:v0471p0401* + ID_MODEL_FROM_DATABASE=Semiconductors CICT Keyboard + +usb:v0471p0402* + ID_MODEL_FROM_DATABASE=PS/2 Mouse on Semiconductors CICT Keyboard + +usb:v0471p0406* + ID_MODEL_FROM_DATABASE=15 inch Detachable Monitor + +usb:v0471p0407* + ID_MODEL_FROM_DATABASE=10 inch Mobile Monitor + +usb:v0471p0408* + ID_MODEL_FROM_DATABASE=SG3WA1/74 802.11b WLAN Adapter [Atmel AT76C503A] + +usb:v0471p0471* + ID_MODEL_FROM_DATABASE=Digital Speaker System + +usb:v0471p0601* + ID_MODEL_FROM_DATABASE=OVU1020 IR Dongle (Kbd+Mouse) + +usb:v0471p0602* + ID_MODEL_FROM_DATABASE=ATI Remote Wonder II Input Device + +usb:v0471p0603* + ID_MODEL_FROM_DATABASE=ATI Remote Wonder II Controller + +usb:v0471p0608* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v0471p060A* + ID_MODEL_FROM_DATABASE=TSU9600 Remote Control + +usb:v0471p060C* + ID_MODEL_FROM_DATABASE=Consumer Infrared Transceiver (HP) + +usb:v0471p060D* + ID_MODEL_FROM_DATABASE=Consumer Infrared Transceiver (SRM5100) + +usb:v0471p060E* + ID_MODEL_FROM_DATABASE=RF Dongle + +usb:v0471p060F* + ID_MODEL_FROM_DATABASE=Consumer Infrared Transceiver + +usb:v0471p0613* + ID_MODEL_FROM_DATABASE=Infrared Transceiver + +usb:v0471p0617* + ID_MODEL_FROM_DATABASE=IEEE802.15.4 RF Dongle + +usb:v0471p0619* + ID_MODEL_FROM_DATABASE=TSU9400 Remote Control + +usb:v0471p0666* + ID_MODEL_FROM_DATABASE=Hantek DDS-3005 Arbitrary Waveform Generator + +usb:v0471p0700* + ID_MODEL_FROM_DATABASE=Semiconductors CICT Hub + +usb:v0471p0701* + ID_MODEL_FROM_DATABASE=150P1 TFT Display + +usb:v0471p0809* + ID_MODEL_FROM_DATABASE=AVNET Bluetooth Device + +usb:v0471p0811* + ID_MODEL_FROM_DATABASE=JR24 CDRW + +usb:v0471p0814* + ID_MODEL_FROM_DATABASE=DCCX38/P data cable + +usb:v0471p0815* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v0471p0844* + ID_MODEL_FROM_DATABASE=SA2111/02 1GB Flash Audio Player + +usb:v0471p084A* + ID_MODEL_FROM_DATABASE=GoGear SA3125 + +usb:v0471p084E* + ID_MODEL_FROM_DATABASE=GoGear SA60xx (mtp) + +usb:v0471p0888* + ID_MODEL_FROM_DATABASE=Hantek DDS-3005 Arbitrary Waveform Generator + +usb:v0471p1103* + ID_MODEL_FROM_DATABASE=Digital Speaker System + +usb:v0471p1120* + ID_MODEL_FROM_DATABASE=Creative Rhomba MP3 player + +usb:v0471p1125* + ID_MODEL_FROM_DATABASE=Nike psa[128max Player + +usb:v0471p1137* + ID_MODEL_FROM_DATABASE=HDD065 MP3 player + +usb:v0471p1201* + ID_MODEL_FROM_DATABASE=Arima Bluetooth Device + +usb:v0471p1230* + ID_MODEL_FROM_DATABASE=Wireless Adapter 11g + +usb:v0471p1232* + ID_MODEL_FROM_DATABASE=SNU6500 Wireless Adapter + +usb:v0471p1233* + ID_MODEL_FROM_DATABASE=Wireless Adapter Bootloader Download + +usb:v0471p1236* + ID_MODEL_FROM_DATABASE=SNU5600 802.11bg + +usb:v0471p1237* + ID_MODEL_FROM_DATABASE=TalkTalk SNU5630NS/05 802.11bg + +usb:v0471p1552* + ID_MODEL_FROM_DATABASE=ISP 1581 Hi-Speed USB MPEG2 Encoder Reference Kit + +usb:v0471p1801* + ID_MODEL_FROM_DATABASE=Diva MP3 player + +usb:v0471p200A* + ID_MODEL_FROM_DATABASE=Wireless Network Adapter + +usb:v0471p200F* + ID_MODEL_FROM_DATABASE=802.11n Wireless Adapter + +usb:v0471p2021* + ID_MODEL_FROM_DATABASE=SDE3273FC/97 2.5" SATA HDD Enclosure [INIC-1608L] + +usb:v0471p2022* + ID_MODEL_FROM_DATABASE=GoGear SA52XX + +usb:v0471p2034* + ID_MODEL_FROM_DATABASE=Webcam SPC530NC + +usb:v0471p2036* + ID_MODEL_FROM_DATABASE=Webcam SPC1030NC + +usb:v0471p203F* + ID_MODEL_FROM_DATABASE=TSU9200 Remote Control + +usb:v0471p2046* + ID_MODEL_FROM_DATABASE=TSU9800 Remote Control + +usb:v0471p204E* + ID_MODEL_FROM_DATABASE=GoGear RaGa (SA1942/02) + +usb:v0471p205E* + ID_MODEL_FROM_DATABASE=TSU9300 Remote Control + +usb:v0471p206C* + ID_MODEL_FROM_DATABASE=MCE IR Receiver - Spinel plusf0r ASUS + +usb:v0471p2070* + ID_MODEL_FROM_DATABASE=GoGear Mix + +usb:v0471p2076* + ID_MODEL_FROM_DATABASE=GoGear Aria + +usb:v0471p2079* + ID_MODEL_FROM_DATABASE=GoGear Opus + +usb:v0471p2088* + ID_MODEL_FROM_DATABASE=MCE IR Receiver with ALS- Spinel plus for ASUS + +usb:v0471p209E* + ID_MODEL_FROM_DATABASE=PTA01 Wireless Adapter + +usb:v0471p20B6* + ID_MODEL_FROM_DATABASE=GoGear Vibe + +usb:v0471p20D0* + ID_MODEL_FROM_DATABASE=SPZ2000 Webcam [PixArt PAC7332] + +usb:v0471p20E3* + ID_MODEL_FROM_DATABASE=GoGear Raga + +usb:v0471p20E4* + ID_MODEL_FROM_DATABASE=GoGear ViBE 8GB + +usb:v0471p2160* + ID_MODEL_FROM_DATABASE=Mio LINK Heart Rate Monitor + +usb:v0471p21E0* + ID_MODEL_FROM_DATABASE=GoGEAR Raga + +usb:v0471p262C* + ID_MODEL_FROM_DATABASE=SPC230NC Webcam + +usb:v0471p485D* + ID_MODEL_FROM_DATABASE=Senselock SenseIV v2.x + +usb:v0471pDF55* + ID_MODEL_FROM_DATABASE=LPCXpresso LPC-Link + +usb:v0472* + ID_VENDOR_FROM_DATABASE=Chicony Electronics Co., Ltd + +usb:v0472p0065* + ID_MODEL_FROM_DATABASE=PFU-65 Keyboard [Chicony] + +usb:v0472pB086* + ID_MODEL_FROM_DATABASE=Asus USB2.0 Webcam + +usb:v0472pB091* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v0473* + ID_VENDOR_FROM_DATABASE=Sanyo Information Business Co., Ltd + +usb:v0474* + ID_VENDOR_FROM_DATABASE=Sanyo Electric Co., Ltd + +usb:v0474p0110* + ID_MODEL_FROM_DATABASE=Digital Voice Recorder R200 + +usb:v0474p0217* + ID_MODEL_FROM_DATABASE=Xacti J2 + +usb:v0474p022F* + ID_MODEL_FROM_DATABASE=C5 Digital Media Camera (mass storage mode) + +usb:v0474p0230* + ID_MODEL_FROM_DATABASE=C5 Digital Media Camera (PictBridge mode) + +usb:v0474p0231* + ID_MODEL_FROM_DATABASE=C5 Digital Media Camera (PC control mode) + +usb:v0474p0401* + ID_MODEL_FROM_DATABASE=Optical Drive + +usb:v0474p0701* + ID_MODEL_FROM_DATABASE=SCP-4900 Cellphone + +usb:v0474p071F* + ID_MODEL_FROM_DATABASE=Usb Com Port Enumerator + +usb:v0474p0722* + ID_MODEL_FROM_DATABASE=W33SA Camera + +usb:v0475* + ID_VENDOR_FROM_DATABASE=Relisys/Teco Information System + +usb:v0475p0100* + ID_MODEL_FROM_DATABASE=NEC Petiscan + +usb:v0475p0103* + ID_MODEL_FROM_DATABASE=Eclipse 1200U/Episode + +usb:v0475p0210* + ID_MODEL_FROM_DATABASE=Scorpio Ultra 3 + +usb:v0476* + ID_VENDOR_FROM_DATABASE=AESP + +usb:v0477* + ID_VENDOR_FROM_DATABASE=Seagate Technology, Inc. + +usb:v0478* + ID_VENDOR_FROM_DATABASE=Connectix Corp. + +usb:v0478p0001* + ID_MODEL_FROM_DATABASE=QuickCam + +usb:v0478p0002* + ID_MODEL_FROM_DATABASE=QuickClip + +usb:v0478p0003* + ID_MODEL_FROM_DATABASE=QuickCam Pro + +usb:v0479* + ID_VENDOR_FROM_DATABASE=Advanced Peripheral Laboratories + +usb:v047A* + ID_VENDOR_FROM_DATABASE=Semtech Corp. + +usb:v047Ap0004* + ID_MODEL_FROM_DATABASE=ScreenCoder UR7HCTS2-USB + +usb:v047B* + ID_VENDOR_FROM_DATABASE=Silitek Corp. + +usb:v047Bp0001* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v047Bp0002* + ID_MODEL_FROM_DATABASE=Keyboard and Mouse + +usb:v047Bp0011* + ID_MODEL_FROM_DATABASE=SK-1688U Keyboard + +usb:v047Bp00F9* + ID_MODEL_FROM_DATABASE=SK-1789u Keyboard + +usb:v047Bp0101* + ID_MODEL_FROM_DATABASE=BlueTooth Keyboard and Mouse + +usb:v047Bp020B* + ID_MODEL_FROM_DATABASE=SK-3105 SmartCard Reader + +usb:v047Bp050E* + ID_MODEL_FROM_DATABASE=Internet Compact Keyboard + +usb:v047Bp1000* + ID_MODEL_FROM_DATABASE=Trust Office Scan USB 19200 + +usb:v047Bp1002* + ID_MODEL_FROM_DATABASE=HP ScanJet 4300c Parallel Port + +usb:v047C* + ID_VENDOR_FROM_DATABASE=Dell Computer Corp. + +usb:v047CpFFFF* + ID_MODEL_FROM_DATABASE=UPS Tower 500W LV + +usb:v047D* + ID_VENDOR_FROM_DATABASE=Kensington + +usb:v047Dp1001* + ID_MODEL_FROM_DATABASE=Mouse*in*a*Box + +usb:v047Dp1002* + ID_MODEL_FROM_DATABASE=Expert Mouse Pro + +usb:v047Dp1003* + ID_MODEL_FROM_DATABASE=Orbit TrackBall + +usb:v047Dp1004* + ID_MODEL_FROM_DATABASE=MouseWorks + +usb:v047Dp1005* + ID_MODEL_FROM_DATABASE=TurboBall + +usb:v047Dp1006* + ID_MODEL_FROM_DATABASE=TurboRing + +usb:v047Dp1009* + ID_MODEL_FROM_DATABASE=Orbit TrackBall for Mac + +usb:v047Dp1012* + ID_MODEL_FROM_DATABASE=PocketMouse + +usb:v047Dp1013* + ID_MODEL_FROM_DATABASE=Mouse*in*a*Box Optical Pro + +usb:v047Dp1014* + ID_MODEL_FROM_DATABASE=Expert Mouse Pro Wireless + +usb:v047Dp1015* + ID_MODEL_FROM_DATABASE=Expert Mouse + +usb:v047Dp1016* + ID_MODEL_FROM_DATABASE=ADB/USB Orbit + +usb:v047Dp1018* + ID_MODEL_FROM_DATABASE=Studio Mouse + +usb:v047Dp101D* + ID_MODEL_FROM_DATABASE=Mouse*in*a*Box Optical Pro + +usb:v047Dp101E* + ID_MODEL_FROM_DATABASE=Studio Mouse Wireless + +usb:v047Dp101F* + ID_MODEL_FROM_DATABASE=PocketMouse Pro + +usb:v047Dp1020* + ID_MODEL_FROM_DATABASE=Expert Mouse Trackball + +usb:v047Dp1021* + ID_MODEL_FROM_DATABASE=Expert Mouse Wireless + +usb:v047Dp1022* + ID_MODEL_FROM_DATABASE=Orbit Optical + +usb:v047Dp1023* + ID_MODEL_FROM_DATABASE=Pocket Mouse Pro Wireless + +usb:v047Dp1024* + ID_MODEL_FROM_DATABASE=PocketMouse + +usb:v047Dp1025* + ID_MODEL_FROM_DATABASE=Mouse*in*a*Box Optical Elite Wireless + +usb:v047Dp1026* + ID_MODEL_FROM_DATABASE=Pocket Mouse Pro + +usb:v047Dp1027* + ID_MODEL_FROM_DATABASE=StudioMouse + +usb:v047Dp1028* + ID_MODEL_FROM_DATABASE=StudioMouse Wireless + +usb:v047Dp1029* + ID_MODEL_FROM_DATABASE=Mouse*in*a*Box Optical Elite + +usb:v047Dp102A* + ID_MODEL_FROM_DATABASE=Mouse*in*a*Box Optical + +usb:v047Dp102B* + ID_MODEL_FROM_DATABASE=PocketMouse + +usb:v047Dp102C* + ID_MODEL_FROM_DATABASE=Iridio + +usb:v047Dp102D* + ID_MODEL_FROM_DATABASE=Pilot Optical + +usb:v047Dp102E* + ID_MODEL_FROM_DATABASE=Pilot Optical Pro + +usb:v047Dp102F* + ID_MODEL_FROM_DATABASE=Pilot Optical Pro Wireless + +usb:v047Dp1042* + ID_MODEL_FROM_DATABASE=Ci25m Notebook Optical Mouse [Diamond Eye Precision] + +usb:v047Dp1043* + ID_MODEL_FROM_DATABASE=Ci65m Wireless Notebook Optical Mouse + +usb:v047Dp104A* + ID_MODEL_FROM_DATABASE=PilotMouse Mini Retractable + +usb:v047Dp105D* + ID_MODEL_FROM_DATABASE=PocketMouse Bluetooth + +usb:v047Dp105E* + ID_MODEL_FROM_DATABASE=Bluetooth EDR Dongle + +usb:v047Dp1061* + ID_MODEL_FROM_DATABASE=PocketMouse Grip + +usb:v047Dp1062* + ID_MODEL_FROM_DATABASE=PocketMouse Max + +usb:v047Dp1063* + ID_MODEL_FROM_DATABASE=PocketMouse Max Wireless + +usb:v047Dp1064* + ID_MODEL_FROM_DATABASE=PocketMouse 2.0 Wireless + +usb:v047Dp1065* + ID_MODEL_FROM_DATABASE=PocketMouse 2.0 + +usb:v047Dp1066* + ID_MODEL_FROM_DATABASE=PocketMouse Max Glow + +usb:v047Dp1067* + ID_MODEL_FROM_DATABASE=ValueMouse + +usb:v047Dp1068* + ID_MODEL_FROM_DATABASE=ValueOpt White + +usb:v047Dp1069* + ID_MODEL_FROM_DATABASE=ValueOpt Black + +usb:v047Dp106A* + ID_MODEL_FROM_DATABASE=PilotMouse Laser Wireless Mini + +usb:v047Dp106B* + ID_MODEL_FROM_DATABASE=PilotMouse Laser - 3 Button + +usb:v047Dp106C* + ID_MODEL_FROM_DATABASE=PilotMouse Laser - Gaming + +usb:v047Dp106D* + ID_MODEL_FROM_DATABASE=PilotMouse Laser - Wired + +usb:v047Dp106E* + ID_MODEL_FROM_DATABASE=PilotMouse Micro Laser + +usb:v047Dp1070* + ID_MODEL_FROM_DATABASE=ValueOpt Travel + +usb:v047Dp1071* + ID_MODEL_FROM_DATABASE=ValueOpt RF TX + +usb:v047Dp1072* + ID_MODEL_FROM_DATABASE=PocketMouse Colour + +usb:v047Dp1073* + ID_MODEL_FROM_DATABASE=PilotMouse Laser - 6 Button + +usb:v047Dp1074* + ID_MODEL_FROM_DATABASE=PilotMouse Laser Wireless Mini + +usb:v047Dp1075* + ID_MODEL_FROM_DATABASE=SlimBlade Presenter Media Mouse + +usb:v047Dp1076* + ID_MODEL_FROM_DATABASE=SlimBlade Media Mouse + +usb:v047Dp1077* + ID_MODEL_FROM_DATABASE=SlimBlade Presenter Mouse + +usb:v047Dp1152* + ID_MODEL_FROM_DATABASE=Bluetooth EDR Dongle + +usb:v047Dp2002* + ID_MODEL_FROM_DATABASE=Optical Elite Wireless + +usb:v047Dp2010* + ID_MODEL_FROM_DATABASE=Wireless Presentation Remote + +usb:v047Dp2012* + ID_MODEL_FROM_DATABASE=Wireless Presenter with Laser Pointer + +usb:v047Dp2021* + ID_MODEL_FROM_DATABASE=PilotBoard Wireless + +usb:v047Dp2030* + ID_MODEL_FROM_DATABASE=PilotBoard Wireless + +usb:v047Dp2034* + ID_MODEL_FROM_DATABASE=SlimBlade Media Notebook Set + +usb:v047Dp2041* + ID_MODEL_FROM_DATABASE=SlimBlade Trackball + +usb:v047Dp2048* + ID_MODEL_FROM_DATABASE=Orbit Trackball with Scroll Ring + +usb:v047Dp4003* + ID_MODEL_FROM_DATABASE=Gravis Xterminator Digital Gamepad + +usb:v047Dp4005* + ID_MODEL_FROM_DATABASE=Gravis Eliminator GamePad Pro + +usb:v047Dp4006* + ID_MODEL_FROM_DATABASE=Gravis Eliminator AfterShock + +usb:v047Dp4007* + ID_MODEL_FROM_DATABASE=Gravis Xterminator Force + +usb:v047Dp4008* + ID_MODEL_FROM_DATABASE=Gravis Destroyer TiltPad + +usb:v047Dp5001* + ID_MODEL_FROM_DATABASE=Cabo I Camera + +usb:v047Dp5002* + ID_MODEL_FROM_DATABASE=VideoCam CABO II + +usb:v047Dp5003* + ID_MODEL_FROM_DATABASE=VideoCam + +usb:v047E* + ID_VENDOR_FROM_DATABASE=Agere Systems, Inc. (Lucent) + +usb:v047Ep0300* + ID_MODEL_FROM_DATABASE=ORiNOCO Card + +usb:v047Ep1001* + ID_MODEL_FROM_DATABASE=USS720 Parallel Port + +usb:v047Ep2892* + ID_MODEL_FROM_DATABASE=Systems Soft Modem + +usb:v047EpBAD1* + ID_MODEL_FROM_DATABASE=Lucent 56k Modem + +usb:v047EpF101* + ID_MODEL_FROM_DATABASE=Atlas Modem + +usb:v047F* + ID_VENDOR_FROM_DATABASE=Plantronics, Inc. + +usb:v047Fp0101* + ID_MODEL_FROM_DATABASE=Bulk Driver + +usb:v047Fp0301* + ID_MODEL_FROM_DATABASE=Bulk Driver + +usb:v047Fp0411* + ID_MODEL_FROM_DATABASE=Savi Office Base Station + +usb:v047Fp0CA1* + ID_MODEL_FROM_DATABASE=USB DSP v4 Audio Interface + +usb:v047Fp4254* + ID_MODEL_FROM_DATABASE=BUA-100 Bluetooth Adapter + +usb:v047FpAC01* + ID_MODEL_FROM_DATABASE=Savi 7xx + +usb:v047FpAD01* + ID_MODEL_FROM_DATABASE=GameCom 777 5.1 Headset + +usb:v047FpAF01* + ID_MODEL_FROM_DATABASE=DA80 + +usb:v047FpC008* + ID_MODEL_FROM_DATABASE=Audio 655 DSP + +usb:v047FpC00E* + ID_MODEL_FROM_DATABASE=Blackwire C310 headset + +usb:v0480* + ID_VENDOR_FROM_DATABASE=Toshiba America Inc + +usb:v0480p0001* + ID_MODEL_FROM_DATABASE=InTouch Module + +usb:v0480p0004* + ID_MODEL_FROM_DATABASE=InTouch Module + +usb:v0480p0011* + ID_MODEL_FROM_DATABASE=InTouch Module + +usb:v0480p0014* + ID_MODEL_FROM_DATABASE=InTouch Module + +usb:v0480p0100* + ID_MODEL_FROM_DATABASE=Stor.E Slim USB 3.0 + +usb:v0480p0200* + ID_MODEL_FROM_DATABASE=External Disk + +usb:v0480p0820* + ID_MODEL_FROM_DATABASE=Canvio Advance Disk + +usb:v0480p0821* + ID_MODEL_FROM_DATABASE=Canvio Advance 2TB model DTC920 + +usb:v0480pA006* + ID_MODEL_FROM_DATABASE=External Disk 1.5TB + +usb:v0480pA007* + ID_MODEL_FROM_DATABASE=External Disk USB 3.0 + +usb:v0480pA009* + ID_MODEL_FROM_DATABASE=Stor.E Basics + +usb:v0480pA00D* + ID_MODEL_FROM_DATABASE=STOR.E BASICS 500GB + +usb:v0480pA100* + ID_MODEL_FROM_DATABASE=Canvio Alu 2TB 2.5" Black External Disk Model HDTH320EK3CA + +usb:v0480pA102* + ID_MODEL_FROM_DATABASE=Canvio Alu 2TB 2.5" Black External Disk Model HDTH320EK3CA + +usb:v0480pA202* + ID_MODEL_FROM_DATABASE=Canvio Basics HDD + +usb:v0480pA208* + ID_MODEL_FROM_DATABASE=Canvio Basics 2TB USB 3.0 Portable Hard Drive + +usb:v0480pB001* + ID_MODEL_FROM_DATABASE=Stor.E Partner + +usb:v0480pB207* + ID_MODEL_FROM_DATABASE=Canvio Ready + +usb:v0480pD000* + ID_MODEL_FROM_DATABASE=External Disk 2TB Model DT01ABA200 + +usb:v0480pD010* + ID_MODEL_FROM_DATABASE=External Disk 3TB + +usb:v0480pD011* + ID_MODEL_FROM_DATABASE=Canvio Desk + +usb:v0481* + ID_VENDOR_FROM_DATABASE=Zenith Data Systems + +usb:v0482* + ID_VENDOR_FROM_DATABASE=Kyocera Corp. + +usb:v0482p000E* + ID_MODEL_FROM_DATABASE=FS-1020D Printer + +usb:v0482p000F* + ID_MODEL_FROM_DATABASE=FS-1920 Mono Printer + +usb:v0482p0015* + ID_MODEL_FROM_DATABASE=FS-1030D printer + +usb:v0482p0100* + ID_MODEL_FROM_DATABASE=Finecam S3x + +usb:v0482p0101* + ID_MODEL_FROM_DATABASE=Finecam S4 + +usb:v0482p0103* + ID_MODEL_FROM_DATABASE=Finecam S5 + +usb:v0482p0105* + ID_MODEL_FROM_DATABASE=Finecam L3 + +usb:v0482p0106* + ID_MODEL_FROM_DATABASE=Finecam + +usb:v0482p0107* + ID_MODEL_FROM_DATABASE=Digital Camera Device + +usb:v0482p0108* + ID_MODEL_FROM_DATABASE=Digital Camera Device + +usb:v0482p0203* + ID_MODEL_FROM_DATABASE=AH-K3001V + +usb:v0482p0204* + ID_MODEL_FROM_DATABASE=iBurst Terminal + +usb:v0482p0408* + ID_MODEL_FROM_DATABASE=FS-1320D Printer + +usb:v0482p0640* + ID_MODEL_FROM_DATABASE=ECOSYS M6026cdn + +usb:v0482p069B* + ID_MODEL_FROM_DATABASE=ECOSYS M2635dn + +usb:v0483* + ID_VENDOR_FROM_DATABASE=STMicroelectronics + +usb:v0483p0137* + ID_MODEL_FROM_DATABASE=BeWAN ADSL USB ST (blue or green) + +usb:v0483p0138* + ID_MODEL_FROM_DATABASE=Unicorn II (ST70138B + MTC-20174TQ chipset) + +usb:v0483p0ADB* + ID_MODEL_FROM_DATABASE=Android Debug Bridge (ADB) device + +usb:v0483p0AFB* + ID_MODEL_FROM_DATABASE=Android Fastboot device + +usb:v0483p1307* + ID_MODEL_FROM_DATABASE=Cytronix 6in1 Card Reader + +usb:v0483p163D* + ID_MODEL_FROM_DATABASE=Cool Icam Digi-MP3 + +usb:v0483p2015* + ID_MODEL_FROM_DATABASE=TouchChip® Fingerprint Reader + +usb:v0483p2016* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v0483p2017* + ID_MODEL_FROM_DATABASE=Biometric Smart Card Reader + +usb:v0483p2018* + ID_MODEL_FROM_DATABASE=BioSimKey + +usb:v0483p2302* + ID_MODEL_FROM_DATABASE=Portable Flash Device (PFD) + +usb:v0483p3744* + ID_MODEL_FROM_DATABASE=ST-LINK/V1 + +usb:v0483p3747* + ID_MODEL_FROM_DATABASE=ST Micro Connect Lite + +usb:v0483p3748* + ID_MODEL_FROM_DATABASE=ST-LINK/V2 + +usb:v0483p374B* + ID_MODEL_FROM_DATABASE=ST-LINK/V2.1 + +usb:v0483p374D* + ID_MODEL_FROM_DATABASE=STLINK-V3 Loader + +usb:v0483p374E* + ID_MODEL_FROM_DATABASE=STLINK-V3 + +usb:v0483p374F* + ID_MODEL_FROM_DATABASE=STLINK-V3 + +usb:v0483p3752* + ID_MODEL_FROM_DATABASE=ST-LINK/V2.1 + +usb:v0483p3753* + ID_MODEL_FROM_DATABASE=STLINK-V3 + +usb:v0483p4810* + ID_MODEL_FROM_DATABASE=ISDN adapter + +usb:v0483p481D* + ID_MODEL_FROM_DATABASE=BT Digital Access adapter + +usb:v0483p5000* + ID_MODEL_FROM_DATABASE=ST Micro/Ergenic ERG BT-002 Bluetooth Adapter + +usb:v0483p5001* + ID_MODEL_FROM_DATABASE=ST Micro Bluetooth Device + +usb:v0483p5710* + ID_MODEL_FROM_DATABASE=Joystick in FS Mode + +usb:v0483p5720* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0483p5721* + ID_MODEL_FROM_DATABASE=Interrupt Demo + +usb:v0483p5722* + ID_MODEL_FROM_DATABASE=Bulk Demo + +usb:v0483p5730* + ID_MODEL_FROM_DATABASE=Audio Speaker + +usb:v0483p5731* + ID_MODEL_FROM_DATABASE=Microphone + +usb:v0483p5740* + ID_MODEL_FROM_DATABASE=Virtual COM Port + +usb:v0483p5750* + ID_MODEL_FROM_DATABASE=LED badge -- mini LED display -- 11x44 + +usb:v0483p7270* + ID_MODEL_FROM_DATABASE=ST Micro Serial Bridge + +usb:v0483p7554* + ID_MODEL_FROM_DATABASE=56k SoftModem + +usb:v0483p8213* + ID_MODEL_FROM_DATABASE=ThermaData Logger Cradle + +usb:v0483p8259* + ID_MODEL_FROM_DATABASE=Probe + +usb:v0483p91D1* + ID_MODEL_FROM_DATABASE=Sensor Hub + +usb:v0483pA171* + ID_MODEL_FROM_DATABASE=ThermaData WiFi + +usb:v0483pDF11* + ID_MODEL_FROM_DATABASE=STM Device in DFU Mode + +usb:v0483pFF10* + ID_MODEL_FROM_DATABASE=Swann ST56 Modem + +usb:v0484* + ID_VENDOR_FROM_DATABASE=Specialix + +usb:v0485* + ID_VENDOR_FROM_DATABASE=Nokia Monitors + +usb:v0486* + ID_VENDOR_FROM_DATABASE=ASUS Computers, Inc. + +usb:v0486p0185* + ID_MODEL_FROM_DATABASE=EeePC T91MT HID Touch Panel + +usb:v0487* + ID_VENDOR_FROM_DATABASE=Stewart Connector + +usb:v0488* + ID_VENDOR_FROM_DATABASE=Cirque Corp. + +usb:v0489* + ID_VENDOR_FROM_DATABASE=Foxconn / Hon Hai + +usb:v0489p0502* + ID_MODEL_FROM_DATABASE=SmartMedia Card Reader Firmware Loader + +usb:v0489p0503* + ID_MODEL_FROM_DATABASE=SmartMedia Card Reader + +usb:v0489pD00C* + ID_MODEL_FROM_DATABASE=Rollei Compactline (Storage Mode) + +usb:v0489pD00E* + ID_MODEL_FROM_DATABASE=Rollei Compactline (Video Mode) + +usb:v0489pE000* + ID_MODEL_FROM_DATABASE=T-Com TC 300 + +usb:v0489pE003* + ID_MODEL_FROM_DATABASE=Pirelli DP-L10 + +usb:v0489pE00D* + ID_MODEL_FROM_DATABASE=Broadcom Bluetooth 2.1 Device + +usb:v0489pE00F* + ID_MODEL_FROM_DATABASE=Foxconn T77H114 BCM2070 [Single-Chip Bluetooth 2.1 + EDR Adapter] + +usb:v0489pE011* + ID_MODEL_FROM_DATABASE=Acer Bluetooth module + +usb:v0489pE016* + ID_MODEL_FROM_DATABASE=Ubee PXU1900 WiMAX Adapter [Beceem BCSM250] + +usb:v0489pE02C* + ID_MODEL_FROM_DATABASE=Atheros AR5BBU12 Bluetooth Device + +usb:v0489pE032* + ID_MODEL_FROM_DATABASE=Broadcom BCM20702 Bluetooth + +usb:v0489pE042* + ID_MODEL_FROM_DATABASE=Broadcom BCM20702 Bluetooth + +usb:v0489pE04D* + ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth + +usb:v0489pE055* + ID_MODEL_FROM_DATABASE=BCM43142A0 broadcom bluetooth + +usb:v048A* + ID_VENDOR_FROM_DATABASE=S-MOS Systems, Inc. + +usb:v048C* + ID_VENDOR_FROM_DATABASE=Alps Electric Ireland, Ltd + +usb:v048D* + ID_VENDOR_FROM_DATABASE=Integrated Technology Express, Inc. + +usb:v048Dp1165* + ID_MODEL_FROM_DATABASE=IT1165 Flash Controller + +usb:v048Dp1172* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v048Dp1336* + ID_MODEL_FROM_DATABASE=SD/MMC Cardreader + +usb:v048Dp1345* + ID_MODEL_FROM_DATABASE=Multi Cardreader + +usb:v048Dp9006* + ID_MODEL_FROM_DATABASE=IT9135 BDA Afatech DVB-T HDTV Dongle + +usb:v048Dp9009* + ID_MODEL_FROM_DATABASE=Zolid HD DVD Maker + +usb:v048Dp9135* + ID_MODEL_FROM_DATABASE=Zolid Mini DVB-T Stick + +usb:v048Dp9306* + ID_MODEL_FROM_DATABASE=IT930x DVB stick + +usb:v048Dp9503* + ID_MODEL_FROM_DATABASE=ITE it9503 feature-limited DVB-T transmission chip [ccHDtv] + +usb:v048Dp9507* + ID_MODEL_FROM_DATABASE=ITE it9507 full featured DVB-T transmission chip [ccHDtv] + +usb:v048Dp9910* + ID_MODEL_FROM_DATABASE=IT9910 chipset based grabber + +usb:v048DpFF59* + ID_MODEL_FROM_DATABASE=Hdmi-CEC Bridge + +usb:v048F* + ID_VENDOR_FROM_DATABASE=Eicon Tech. + +usb:v0490* + ID_VENDOR_FROM_DATABASE=United Microelectronics Corp. + +usb:v0491* + ID_VENDOR_FROM_DATABASE=Capetronic + +usb:v0491p0003* + ID_MODEL_FROM_DATABASE=Taxan Monitor Control + +usb:v0492* + ID_VENDOR_FROM_DATABASE=Samsung SemiConductor, Inc. + +usb:v0492p0140* + ID_MODEL_FROM_DATABASE=MP3 player + +usb:v0492p0141* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0493* + ID_VENDOR_FROM_DATABASE=MAG Technology Co., Ltd + +usb:v0495* + ID_VENDOR_FROM_DATABASE=ESS Technology, Inc. + +usb:v0496* + ID_VENDOR_FROM_DATABASE=Micron Electronics + +usb:v0497* + ID_VENDOR_FROM_DATABASE=Smile International + +usb:v0497pC001* + ID_MODEL_FROM_DATABASE=Camera Device + +usb:v0498* + ID_VENDOR_FROM_DATABASE=Capetronic (Kaohsiung) Corp. + +usb:v0499* + ID_VENDOR_FROM_DATABASE=Yamaha Corp. + +usb:v0499p1000* + ID_MODEL_FROM_DATABASE=UX256 MIDI I/F + +usb:v0499p1001* + ID_MODEL_FROM_DATABASE=MU1000 + +usb:v0499p1002* + ID_MODEL_FROM_DATABASE=MU2000 + +usb:v0499p1003* + ID_MODEL_FROM_DATABASE=MU500 + +usb:v0499p1004* + ID_MODEL_FROM_DATABASE=UW500 + +usb:v0499p1005* + ID_MODEL_FROM_DATABASE=MOTIF6 + +usb:v0499p1006* + ID_MODEL_FROM_DATABASE=MOTIF7 + +usb:v0499p1007* + ID_MODEL_FROM_DATABASE=MOTIF8 + +usb:v0499p1008* + ID_MODEL_FROM_DATABASE=UX96 MIDI I/F + +usb:v0499p1009* + ID_MODEL_FROM_DATABASE=UX16 MIDI I/F + +usb:v0499p100A* + ID_MODEL_FROM_DATABASE=EOS BX + +usb:v0499p100C* + ID_MODEL_FROM_DATABASE=UC-MX + +usb:v0499p100D* + ID_MODEL_FROM_DATABASE=UC-KX + +usb:v0499p100E* + ID_MODEL_FROM_DATABASE=S08 + +usb:v0499p100F* + ID_MODEL_FROM_DATABASE=CLP-150 + +usb:v0499p1010* + ID_MODEL_FROM_DATABASE=CLP-170 + +usb:v0499p1011* + ID_MODEL_FROM_DATABASE=P-250 + +usb:v0499p1012* + ID_MODEL_FROM_DATABASE=TYROS + +usb:v0499p1013* + ID_MODEL_FROM_DATABASE=PF-500 + +usb:v0499p1014* + ID_MODEL_FROM_DATABASE=S90 + +usb:v0499p1015* + ID_MODEL_FROM_DATABASE=MOTIF-R + +usb:v0499p1016* + ID_MODEL_FROM_DATABASE=MDP-5 + +usb:v0499p1017* + ID_MODEL_FROM_DATABASE=CVP-204 + +usb:v0499p1018* + ID_MODEL_FROM_DATABASE=CVP-206 + +usb:v0499p1019* + ID_MODEL_FROM_DATABASE=CVP-208 + +usb:v0499p101A* + ID_MODEL_FROM_DATABASE=CVP-210 + +usb:v0499p101B* + ID_MODEL_FROM_DATABASE=PSR-1100 + +usb:v0499p101C* + ID_MODEL_FROM_DATABASE=PSR-2100 + +usb:v0499p101D* + ID_MODEL_FROM_DATABASE=CLP-175 + +usb:v0499p101E* + ID_MODEL_FROM_DATABASE=PSR-K1 + +usb:v0499p101F* + ID_MODEL_FROM_DATABASE=EZ-J24 + +usb:v0499p1020* + ID_MODEL_FROM_DATABASE=EZ-250i + +usb:v0499p1021* + ID_MODEL_FROM_DATABASE=MOTIF ES 6 + +usb:v0499p1022* + ID_MODEL_FROM_DATABASE=MOTIF ES 7 + +usb:v0499p1023* + ID_MODEL_FROM_DATABASE=MOTIF ES 8 + +usb:v0499p1024* + ID_MODEL_FROM_DATABASE=CVP-301 + +usb:v0499p1025* + ID_MODEL_FROM_DATABASE=CVP-303 + +usb:v0499p1026* + ID_MODEL_FROM_DATABASE=CVP-305 + +usb:v0499p1027* + ID_MODEL_FROM_DATABASE=CVP-307 + +usb:v0499p1028* + ID_MODEL_FROM_DATABASE=CVP-309 + +usb:v0499p1029* + ID_MODEL_FROM_DATABASE=CVP-309GP + +usb:v0499p102A* + ID_MODEL_FROM_DATABASE=PSR-1500 + +usb:v0499p102B* + ID_MODEL_FROM_DATABASE=PSR-3000 + +usb:v0499p102E* + ID_MODEL_FROM_DATABASE=ELS-01/01C + +usb:v0499p1030* + ID_MODEL_FROM_DATABASE=PSR-295/293 + +usb:v0499p1031* + ID_MODEL_FROM_DATABASE=DGX-205/203 + +usb:v0499p1032* + ID_MODEL_FROM_DATABASE=DGX-305 + +usb:v0499p1033* + ID_MODEL_FROM_DATABASE=DGX-505 + +usb:v0499p1037* + ID_MODEL_FROM_DATABASE=PSR-E403 + +usb:v0499p103C* + ID_MODEL_FROM_DATABASE=MOTIF-RACK ES + +usb:v0499p1054* + ID_MODEL_FROM_DATABASE=S90XS Keyboard/Music Synthesizer + +usb:v0499p160F* + ID_MODEL_FROM_DATABASE=P-105 + +usb:v0499p1613* + ID_MODEL_FROM_DATABASE=Clavinova CLP535 + +usb:v0499p1617* + ID_MODEL_FROM_DATABASE=PSR-E353 digital keyboard + +usb:v0499p1704* + ID_MODEL_FROM_DATABASE=Steinberg UR44 + +usb:v0499p2000* + ID_MODEL_FROM_DATABASE=DGP-7 + +usb:v0499p2001* + ID_MODEL_FROM_DATABASE=DGP-5 + +usb:v0499p3001* + ID_MODEL_FROM_DATABASE=YST-MS55D USB Speaker + +usb:v0499p3003* + ID_MODEL_FROM_DATABASE=YST-M45D USB Speaker + +usb:v0499p4000* + ID_MODEL_FROM_DATABASE=NetVolante RTA54i Broadband&ISDN Router + +usb:v0499p4001* + ID_MODEL_FROM_DATABASE=NetVolante RTW65b Broadband Wireless Router + +usb:v0499p4002* + ID_MODEL_FROM_DATABASE=NetVolante RTW65i Broadband&ISDN Wireless Router + +usb:v0499p4004* + ID_MODEL_FROM_DATABASE=NetVolante RTA55i Broadband VoIP Router + +usb:v0499p5000* + ID_MODEL_FROM_DATABASE=CS1D + +usb:v0499p5001* + ID_MODEL_FROM_DATABASE=DSP1D + +usb:v0499p5002* + ID_MODEL_FROM_DATABASE=DME32 + +usb:v0499p5003* + ID_MODEL_FROM_DATABASE=DM2000 + +usb:v0499p5004* + ID_MODEL_FROM_DATABASE=02R96 + +usb:v0499p5005* + ID_MODEL_FROM_DATABASE=ACU16-C + +usb:v0499p5006* + ID_MODEL_FROM_DATABASE=NHB32-C + +usb:v0499p5007* + ID_MODEL_FROM_DATABASE=DM1000 + +usb:v0499p5008* + ID_MODEL_FROM_DATABASE=01V96 + +usb:v0499p5009* + ID_MODEL_FROM_DATABASE=SPX2000 + +usb:v0499p500A* + ID_MODEL_FROM_DATABASE=PM5D + +usb:v0499p500B* + ID_MODEL_FROM_DATABASE=DME64N + +usb:v0499p500C* + ID_MODEL_FROM_DATABASE=DME24N + +usb:v0499p6001* + ID_MODEL_FROM_DATABASE=CRW2200UX Lightspeed 2 External CD-RW Drive + +usb:v0499p7000* + ID_MODEL_FROM_DATABASE=DTX + +usb:v0499p7010* + ID_MODEL_FROM_DATABASE=UB99 + +usb:v049A* + ID_VENDOR_FROM_DATABASE=Gandalf Technologies, Ltd + +usb:v049B* + ID_VENDOR_FROM_DATABASE=Curtis Computer Products + +usb:v049C* + ID_VENDOR_FROM_DATABASE=Acer Advanced Labs, Inc. + +usb:v049Cp0002* + ID_MODEL_FROM_DATABASE=Keyboard (???) + +usb:v049D* + ID_VENDOR_FROM_DATABASE=VLSI Technology + +usb:v049F* + ID_VENDOR_FROM_DATABASE=Compaq Computer Corp. + +usb:v049Fp0002* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v049Fp0003* + ID_MODEL_FROM_DATABASE=iPAQ PocketPC + +usb:v049Fp000E* + ID_MODEL_FROM_DATABASE=Internet Keyboard + +usb:v049Fp0012* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v049Fp0018* + ID_MODEL_FROM_DATABASE=PA-1/PA-2 MP3 Player + +usb:v049Fp0019* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v049Fp001A* + ID_MODEL_FROM_DATABASE=S4 100 Scanner + +usb:v049Fp001E* + ID_MODEL_FROM_DATABASE=IJ650 Inkjet Printer + +usb:v049Fp001F* + ID_MODEL_FROM_DATABASE=WL215 Adapter + +usb:v049Fp0021* + ID_MODEL_FROM_DATABASE=S200 Scanner + +usb:v049Fp0027* + ID_MODEL_FROM_DATABASE=Bluetooth Multiport Module by Compaq + +usb:v049Fp002A* + ID_MODEL_FROM_DATABASE=1400P Inkjet Printer + +usb:v049Fp002B* + ID_MODEL_FROM_DATABASE=A3000 + +usb:v049Fp002C* + ID_MODEL_FROM_DATABASE=Lexmark X125 + +usb:v049Fp0032* + ID_MODEL_FROM_DATABASE=802.11b Adapter [ipaq h5400] + +usb:v049Fp0033* + ID_MODEL_FROM_DATABASE=Wireless LAN MultiPort W100 [Intersil PRISM 2.5] + +usb:v049Fp0036* + ID_MODEL_FROM_DATABASE=Bluetooth Multiport Module + +usb:v049Fp0051* + ID_MODEL_FROM_DATABASE=KU-0133 Easy Access Interner Keyboard + +usb:v049Fp0076* + ID_MODEL_FROM_DATABASE=Wireless LAN MultiPort W200 + +usb:v049Fp0080* + ID_MODEL_FROM_DATABASE=GPRS Multiport + +usb:v049Fp0086* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v049Fp504A* + ID_MODEL_FROM_DATABASE=Personal Jukebox PJB100 + +usb:v049Fp505A* + ID_MODEL_FROM_DATABASE=Linux-USB "CDC Subset" Device, or Itsy (experimental) + +usb:v049Fp8511* + ID_MODEL_FROM_DATABASE=iPAQ Networking 10/100 Ethernet [pegasus2] + +usb:v04A0* + ID_VENDOR_FROM_DATABASE=Digital Equipment Corp. + +usb:v04A1* + ID_VENDOR_FROM_DATABASE=SystemSoft Corp. + +usb:v04A1pFFF0* + ID_MODEL_FROM_DATABASE=Telex Composite Device + +usb:v04A2* + ID_VENDOR_FROM_DATABASE=FirePower Systems + +usb:v04A3* + ID_VENDOR_FROM_DATABASE=Trident Microsystems, Inc. + +usb:v04A4* + ID_VENDOR_FROM_DATABASE=Hitachi, Ltd + +usb:v04A4p0004* + ID_MODEL_FROM_DATABASE=DVD-CAM DZ-MV100A Camcorder + +usb:v04A4p001E* + ID_MODEL_FROM_DATABASE=DVDCAM USB HS Interface + +usb:v04A5* + ID_VENDOR_FROM_DATABASE=Acer Peripherals Inc. (now BenQ Corp.) + +usb:v04A5p0001* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v04A5p0002* + ID_MODEL_FROM_DATABASE=API Ergo K/B + +usb:v04A5p0003* + ID_MODEL_FROM_DATABASE=API Generic K/B Mouse + +usb:v04A5p12A6* + ID_MODEL_FROM_DATABASE=AcerScan C310U + +usb:v04A5p1A20* + ID_MODEL_FROM_DATABASE=Prisa 310U + +usb:v04A5p1A2A* + ID_MODEL_FROM_DATABASE=Prisa 620U + +usb:v04A5p2022* + ID_MODEL_FROM_DATABASE=Prisa 320U/340U + +usb:v04A5p2040* + ID_MODEL_FROM_DATABASE=Prisa 620UT + +usb:v04A5p205E* + ID_MODEL_FROM_DATABASE=ScanPrisa 640BU + +usb:v04A5p2060* + ID_MODEL_FROM_DATABASE=Prisa 620U+/640U + +usb:v04A5p207E* + ID_MODEL_FROM_DATABASE=Prisa 640BU + +usb:v04A5p209E* + ID_MODEL_FROM_DATABASE=ScanPrisa 640BT + +usb:v04A5p20AE* + ID_MODEL_FROM_DATABASE=S2W 3000U + +usb:v04A5p20B0* + ID_MODEL_FROM_DATABASE=S2W 3300U/4300U + +usb:v04A5p20BE* + ID_MODEL_FROM_DATABASE=Prisa 640BT + +usb:v04A5p20C0* + ID_MODEL_FROM_DATABASE=Prisa 1240UT + +usb:v04A5p20DE* + ID_MODEL_FROM_DATABASE=S2W 4300U+ + +usb:v04A5p20F8* + ID_MODEL_FROM_DATABASE=Benq 5000 + +usb:v04A5p20FC* + ID_MODEL_FROM_DATABASE=Benq 5000 + +usb:v04A5p20FE* + ID_MODEL_FROM_DATABASE=SW2 5300U + +usb:v04A5p2137* + ID_MODEL_FROM_DATABASE=Benq 5150/5250 + +usb:v04A5p2202* + ID_MODEL_FROM_DATABASE=Benq 7400UT + +usb:v04A5p2311* + ID_MODEL_FROM_DATABASE=Benq 5560 + +usb:v04A5p3003* + ID_MODEL_FROM_DATABASE=Benq Webcam + +usb:v04A5p3008* + ID_MODEL_FROM_DATABASE=Benq 1500 + +usb:v04A5p300A* + ID_MODEL_FROM_DATABASE=Benq 3410 + +usb:v04A5p300C* + ID_MODEL_FROM_DATABASE=Benq 1016 + +usb:v04A5p3019* + ID_MODEL_FROM_DATABASE=Benq DC C40 + +usb:v04A5p4000* + ID_MODEL_FROM_DATABASE=P30 Composite Device + +usb:v04A5p4013* + ID_MODEL_FROM_DATABASE=BenQ-Siemens EF82/SL91 + +usb:v04A5p4044* + ID_MODEL_FROM_DATABASE=BenQ-Siemens SF71 + +usb:v04A5p4045* + ID_MODEL_FROM_DATABASE=BenQ-Siemens E81 + +usb:v04A5p4048* + ID_MODEL_FROM_DATABASE=BenQ M7 + +usb:v04A5p6001* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6002* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6003* + ID_MODEL_FROM_DATABASE=ATA/ATAPI Adapter + +usb:v04A5p6004* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6005* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6006* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6007* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6008* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6009* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p600A* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p600B* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p600C* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p600D* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p600E* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p600F* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6010* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6011* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6012* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6013* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6014* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6015* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v04A5p6125* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v04A5p6180* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v04A5p6200* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v04A5p7500* + ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device + +usb:v04A5p9000* + ID_MODEL_FROM_DATABASE=AWL300 Wireless Adapter + +usb:v04A5p9001* + ID_MODEL_FROM_DATABASE=AWL400 Wireless Adapter + +usb:v04A5p9213* + ID_MODEL_FROM_DATABASE=Kbd Hub + +usb:v04A6* + ID_VENDOR_FROM_DATABASE=Nokia Display Products + +usb:v04A6p00B9* + ID_MODEL_FROM_DATABASE=Audio + +usb:v04A6p0180* + ID_MODEL_FROM_DATABASE=Hub Type P + +usb:v04A6p0181* + ID_MODEL_FROM_DATABASE=HID Monitor Controls + +usb:v04A7* + ID_VENDOR_FROM_DATABASE=Visioneer + +usb:v04A7p0100* + ID_MODEL_FROM_DATABASE=StrobePro + +usb:v04A7p0101* + ID_MODEL_FROM_DATABASE=Strobe Pro Scanner (1.01) + +usb:v04A7p0102* + ID_MODEL_FROM_DATABASE=StrobePro Scanner + +usb:v04A7p0211* + ID_MODEL_FROM_DATABASE=OneTouch 7600 Scanner + +usb:v04A7p0221* + ID_MODEL_FROM_DATABASE=OneTouch 5300 Scanner + +usb:v04A7p0223* + ID_MODEL_FROM_DATABASE=OneTouch 8200 + +usb:v04A7p0224* + ID_MODEL_FROM_DATABASE=OneTouch 4800 USB/Microtek Scanport 3000 + +usb:v04A7p0225* + ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) + +usb:v04A7p0226* + ID_MODEL_FROM_DATABASE=OneTouch 5300 USB + +usb:v04A7p0229* + ID_MODEL_FROM_DATABASE=OneTouch 7100 + +usb:v04A7p022A* + ID_MODEL_FROM_DATABASE=OneTouch 6600 + +usb:v04A7p022C* + ID_MODEL_FROM_DATABASE=OneTouch 9000/9020 + +usb:v04A7p0231* + ID_MODEL_FROM_DATABASE=6100 Scanner + +usb:v04A7p0311* + ID_MODEL_FROM_DATABASE=6200 EPP/USB Scanner + +usb:v04A7p0321* + ID_MODEL_FROM_DATABASE=OneTouch 8100 EPP/USB Scanner + +usb:v04A7p0331* + ID_MODEL_FROM_DATABASE=OneTouch 8600 EPP/USB Scanner + +usb:v04A7p0341* + ID_MODEL_FROM_DATABASE=6400 + +usb:v04A7p0361* + ID_MODEL_FROM_DATABASE=VistaScan Astra 3600(ENG) + +usb:v04A7p0362* + ID_MODEL_FROM_DATABASE=OneTouch 9320 + +usb:v04A7p0371* + ID_MODEL_FROM_DATABASE=OneTouch 8700/8920 + +usb:v04A7p0380* + ID_MODEL_FROM_DATABASE=OneTouch 7700 + +usb:v04A7p0382* + ID_MODEL_FROM_DATABASE=Photo Port 7700 + +usb:v04A7p0390* + ID_MODEL_FROM_DATABASE=9650 + +usb:v04A7p03A0* + ID_MODEL_FROM_DATABASE=Xerox 4800 One Touch + +usb:v04A7p0410* + ID_MODEL_FROM_DATABASE=OneTouch Pro 8800/8820 + +usb:v04A7p0421* + ID_MODEL_FROM_DATABASE=9450 USB + +usb:v04A7p0423* + ID_MODEL_FROM_DATABASE=9750 Scanner + +usb:v04A7p0424* + ID_MODEL_FROM_DATABASE=Strobe XP 450 + +usb:v04A7p0425* + ID_MODEL_FROM_DATABASE=Strobe XP 100 + +usb:v04A7p0426* + ID_MODEL_FROM_DATABASE=Strobe XP 200 + +usb:v04A7p0427* + ID_MODEL_FROM_DATABASE=Strobe XP 100 + +usb:v04A7p0444* + ID_MODEL_FROM_DATABASE=OneTouch 7300 + +usb:v04A7p0445* + ID_MODEL_FROM_DATABASE=CardReader 100 + +usb:v04A7p0446* + ID_MODEL_FROM_DATABASE=Xerox DocuMate 510 + +usb:v04A7p0447* + ID_MODEL_FROM_DATABASE=XEROX DocuMate 520 + +usb:v04A7p0448* + ID_MODEL_FROM_DATABASE=XEROX DocuMate 250 + +usb:v04A7p0449* + ID_MODEL_FROM_DATABASE=Xerox DocuMate 252 + +usb:v04A7p044A* + ID_MODEL_FROM_DATABASE=Xerox 6400 + +usb:v04A7p044C* + ID_MODEL_FROM_DATABASE=Xerox DocuMate 262 + +usb:v04A7p0474* + ID_MODEL_FROM_DATABASE=Strobe XP 300 + +usb:v04A7p0475* + ID_MODEL_FROM_DATABASE=Xerox DocuMate 272 + +usb:v04A7p0478* + ID_MODEL_FROM_DATABASE=Strobe XP 220 + +usb:v04A7p0479* + ID_MODEL_FROM_DATABASE=Strobe XP 470 + +usb:v04A7p047A* + ID_MODEL_FROM_DATABASE=9450 + +usb:v04A7p047B* + ID_MODEL_FROM_DATABASE=9650 + +usb:v04A7p047D* + ID_MODEL_FROM_DATABASE=9420 + +usb:v04A7p0480* + ID_MODEL_FROM_DATABASE=9520 + +usb:v04A7p048F* + ID_MODEL_FROM_DATABASE=Strobe XP 470 + +usb:v04A7p0491* + ID_MODEL_FROM_DATABASE=Strobe XP 450 + +usb:v04A7p0493* + ID_MODEL_FROM_DATABASE=9750 + +usb:v04A7p0494* + ID_MODEL_FROM_DATABASE=Strobe XP 120 + +usb:v04A7p0497* + ID_MODEL_FROM_DATABASE=Patriot 430 + +usb:v04A7p0498* + ID_MODEL_FROM_DATABASE=Patriot 680 + +usb:v04A7p0499* + ID_MODEL_FROM_DATABASE=Patriot 780 + +usb:v04A7p049B* + ID_MODEL_FROM_DATABASE=Strobe XP 100 + +usb:v04A7p04A0* + ID_MODEL_FROM_DATABASE=7400 + +usb:v04A7p04AC* + ID_MODEL_FROM_DATABASE=Xerox Travel Scanner 100 + +usb:v04A7p04BB* + ID_MODEL_FROM_DATABASE=strobe 400 scanner + +usb:v04A7p04CD* + ID_MODEL_FROM_DATABASE=Xerox Travel Scanner 150 + +usb:v04A8* + ID_VENDOR_FROM_DATABASE=Multivideo Labs, Inc. + +usb:v04A8p0101* + ID_MODEL_FROM_DATABASE=Hub + +usb:v04A8p0303* + ID_MODEL_FROM_DATABASE=Peripheral Switch + +usb:v04A8p0404* + ID_MODEL_FROM_DATABASE=Peripheral Switch + +usb:v04A9* + ID_VENDOR_FROM_DATABASE=Canon, Inc. + +usb:v04A9p1005* + ID_MODEL_FROM_DATABASE=BJ Printer Hub + +usb:v04A9p1035* + ID_MODEL_FROM_DATABASE=PD Printer Storage + +usb:v04A9p1050* + ID_MODEL_FROM_DATABASE=BJC-8200 + +usb:v04A9p1051* + ID_MODEL_FROM_DATABASE=BJC-3000 Color Printer + +usb:v04A9p1052* + ID_MODEL_FROM_DATABASE=BJC-6100 + +usb:v04A9p1053* + ID_MODEL_FROM_DATABASE=BJC-6200 + +usb:v04A9p1054* + ID_MODEL_FROM_DATABASE=BJC-6500 + +usb:v04A9p1055* + ID_MODEL_FROM_DATABASE=BJC-85 + +usb:v04A9p1056* + ID_MODEL_FROM_DATABASE=BJC-2110 Color Printer + +usb:v04A9p1057* + ID_MODEL_FROM_DATABASE=LR1 + +usb:v04A9p105A* + ID_MODEL_FROM_DATABASE=BJC-55 + +usb:v04A9p105B* + ID_MODEL_FROM_DATABASE=S600 Printer + +usb:v04A9p105C* + ID_MODEL_FROM_DATABASE=S400 + +usb:v04A9p105D* + ID_MODEL_FROM_DATABASE=S450 Printer + +usb:v04A9p105E* + ID_MODEL_FROM_DATABASE=S800 + +usb:v04A9p1062* + ID_MODEL_FROM_DATABASE=S500 Printer + +usb:v04A9p1063* + ID_MODEL_FROM_DATABASE=S4500 + +usb:v04A9p1064* + ID_MODEL_FROM_DATABASE=S300 Printer + +usb:v04A9p1065* + ID_MODEL_FROM_DATABASE=S100 + +usb:v04A9p1066* + ID_MODEL_FROM_DATABASE=S630 + +usb:v04A9p1067* + ID_MODEL_FROM_DATABASE=S900 + +usb:v04A9p1068* + ID_MODEL_FROM_DATABASE=S9000 + +usb:v04A9p1069* + ID_MODEL_FROM_DATABASE=S820 + +usb:v04A9p106A* + ID_MODEL_FROM_DATABASE=S200 Printer + +usb:v04A9p106B* + ID_MODEL_FROM_DATABASE=S520 Printer + +usb:v04A9p106D* + ID_MODEL_FROM_DATABASE=S750 Printer + +usb:v04A9p106E* + ID_MODEL_FROM_DATABASE=S820D + +usb:v04A9p1070* + ID_MODEL_FROM_DATABASE=S530D + +usb:v04A9p1072* + ID_MODEL_FROM_DATABASE=I850 Printer + +usb:v04A9p1073* + ID_MODEL_FROM_DATABASE=I550 Printer + +usb:v04A9p1074* + ID_MODEL_FROM_DATABASE=S330 Printer + +usb:v04A9p1076* + ID_MODEL_FROM_DATABASE=i70 + +usb:v04A9p1077* + ID_MODEL_FROM_DATABASE=i950 + +usb:v04A9p107A* + ID_MODEL_FROM_DATABASE=S830D + +usb:v04A9p107B* + ID_MODEL_FROM_DATABASE=i320 + +usb:v04A9p107C* + ID_MODEL_FROM_DATABASE=i470D + +usb:v04A9p107D* + ID_MODEL_FROM_DATABASE=i9100 + +usb:v04A9p107E* + ID_MODEL_FROM_DATABASE=i450 + +usb:v04A9p107F* + ID_MODEL_FROM_DATABASE=i860 + +usb:v04A9p1082* + ID_MODEL_FROM_DATABASE=i350 + +usb:v04A9p1084* + ID_MODEL_FROM_DATABASE=i250 + +usb:v04A9p1085* + ID_MODEL_FROM_DATABASE=i255 + +usb:v04A9p1086* + ID_MODEL_FROM_DATABASE=i560 + +usb:v04A9p1088* + ID_MODEL_FROM_DATABASE=i965 + +usb:v04A9p108A* + ID_MODEL_FROM_DATABASE=i455 + +usb:v04A9p108B* + ID_MODEL_FROM_DATABASE=i900D + +usb:v04A9p108C* + ID_MODEL_FROM_DATABASE=i475D + +usb:v04A9p108D* + ID_MODEL_FROM_DATABASE=PIXMA iP2000 + +usb:v04A9p108F* + ID_MODEL_FROM_DATABASE=i80 + +usb:v04A9p1090* + ID_MODEL_FROM_DATABASE=i9900 Photo Printer + +usb:v04A9p1091* + ID_MODEL_FROM_DATABASE=PIXMA iP1500 + +usb:v04A9p1093* + ID_MODEL_FROM_DATABASE=PIXMA iP4000 + +usb:v04A9p1094* + ID_MODEL_FROM_DATABASE=PIXMA iP3000x Printer + +usb:v04A9p1095* + ID_MODEL_FROM_DATABASE=PIXMA iP6000D + +usb:v04A9p1097* + ID_MODEL_FROM_DATABASE=PIXMA iP5000 + +usb:v04A9p1098* + ID_MODEL_FROM_DATABASE=PIXMA iP1000 + +usb:v04A9p1099* + ID_MODEL_FROM_DATABASE=PIXMA iP8500 + +usb:v04A9p109C* + ID_MODEL_FROM_DATABASE=PIXMA iP4000R + +usb:v04A9p109D* + ID_MODEL_FROM_DATABASE=iP90 + +usb:v04A9p10A0* + ID_MODEL_FROM_DATABASE=PIXMA iP1600 Printer + +usb:v04A9p10A2* + ID_MODEL_FROM_DATABASE=iP4200 + +usb:v04A9p10A4* + ID_MODEL_FROM_DATABASE=iP5200R + +usb:v04A9p10A5* + ID_MODEL_FROM_DATABASE=iP5200 + +usb:v04A9p10A7* + ID_MODEL_FROM_DATABASE=iP6210D + +usb:v04A9p10A8* + ID_MODEL_FROM_DATABASE=iP6220D + +usb:v04A9p10A9* + ID_MODEL_FROM_DATABASE=iP6600D + +usb:v04A9p10B6* + ID_MODEL_FROM_DATABASE=PIXMA iP4300 Printer + +usb:v04A9p10B7* + ID_MODEL_FROM_DATABASE=PIXMA iP5300 Printer + +usb:v04A9p10C2* + ID_MODEL_FROM_DATABASE=PIXMA iP1800 Printer + +usb:v04A9p10C4* + ID_MODEL_FROM_DATABASE=Pixma iP4500 Printer + +usb:v04A9p10C9* + ID_MODEL_FROM_DATABASE=PIXMA iP4600 Printer + +usb:v04A9p10CA* + ID_MODEL_FROM_DATABASE=PIXMA iP3600 Printer + +usb:v04A9p10E3* + ID_MODEL_FROM_DATABASE=PIXMA iX6850 Printer + +usb:v04A9p1404* + ID_MODEL_FROM_DATABASE=W6400PG + +usb:v04A9p1405* + ID_MODEL_FROM_DATABASE=W8400PG + +usb:v04A9p150F* + ID_MODEL_FROM_DATABASE=BIJ2350 PCL + +usb:v04A9p1510* + ID_MODEL_FROM_DATABASE=BIJ1350 PCL + +usb:v04A9p1512* + ID_MODEL_FROM_DATABASE=BIJ1350D PCL + +usb:v04A9p1601* + ID_MODEL_FROM_DATABASE=DR-2080C Scanner + +usb:v04A9p1607* + ID_MODEL_FROM_DATABASE=DR-6080 Scanner + +usb:v04A9p1608* + ID_MODEL_FROM_DATABASE=DR-2580C Scanner + +usb:v04A9p1609* + ID_MODEL_FROM_DATABASE=DR-3080CII + +usb:v04A9p160A* + ID_MODEL_FROM_DATABASE=DR-2050C Scanner + +usb:v04A9p1700* + ID_MODEL_FROM_DATABASE=PIXMA MP110 Scanner + +usb:v04A9p1701* + ID_MODEL_FROM_DATABASE=PIXMA MP130 Scanner + +usb:v04A9p1702* + ID_MODEL_FROM_DATABASE=MP410 Composite + +usb:v04A9p1703* + ID_MODEL_FROM_DATABASE=MP430 Composite + +usb:v04A9p1704* + ID_MODEL_FROM_DATABASE=MP330 Composite + +usb:v04A9p1706* + ID_MODEL_FROM_DATABASE=PIXMA MP750 Scanner + +usb:v04A9p1707* + ID_MODEL_FROM_DATABASE=PIXMA MP780/MP790 + +usb:v04A9p1708* + ID_MODEL_FROM_DATABASE=PIXMA MP760/MP770 + +usb:v04A9p1709* + ID_MODEL_FROM_DATABASE=PIXMA MP150 Scanner + +usb:v04A9p170A* + ID_MODEL_FROM_DATABASE=PIXMA MP170 Scanner + +usb:v04A9p170B* + ID_MODEL_FROM_DATABASE=PIXMA MP450 Scanner + +usb:v04A9p170C* + ID_MODEL_FROM_DATABASE=PIXMA MP500 Scanner + +usb:v04A9p170D* + ID_MODEL_FROM_DATABASE=PIXMA MP800 Scanner + +usb:v04A9p170E* + ID_MODEL_FROM_DATABASE=PIXMA MP800R + +usb:v04A9p1710* + ID_MODEL_FROM_DATABASE=MP950 + +usb:v04A9p1712* + ID_MODEL_FROM_DATABASE=PIXMA MP530 + +usb:v04A9p1713* + ID_MODEL_FROM_DATABASE=PIXMA MP830 Scanner + +usb:v04A9p1714* + ID_MODEL_FROM_DATABASE=MP160 + +usb:v04A9p1715* + ID_MODEL_FROM_DATABASE=PIXMA MP180 + +usb:v04A9p1716* + ID_MODEL_FROM_DATABASE=PIXMA MP460 + +usb:v04A9p1717* + ID_MODEL_FROM_DATABASE=PIXMA MP510 + +usb:v04A9p1718* + ID_MODEL_FROM_DATABASE=PIXMA MP600 + +usb:v04A9p1719* + ID_MODEL_FROM_DATABASE=PIXMA MP600R + +usb:v04A9p171A* + ID_MODEL_FROM_DATABASE=PIXMA MP810 + +usb:v04A9p171B* + ID_MODEL_FROM_DATABASE=PIXMA MP960 + +usb:v04A9p171C* + ID_MODEL_FROM_DATABASE=PIXMA MX7600 + +usb:v04A9p1721* + ID_MODEL_FROM_DATABASE=PIXMA MP210 + +usb:v04A9p1722* + ID_MODEL_FROM_DATABASE=PIXMA MP220 + +usb:v04A9p1723* + ID_MODEL_FROM_DATABASE=PIXMA MP470 + +usb:v04A9p1724* + ID_MODEL_FROM_DATABASE=PIXMA MP520 series + +usb:v04A9p1725* + ID_MODEL_FROM_DATABASE=PIXMA MP610 + +usb:v04A9p1726* + ID_MODEL_FROM_DATABASE=PIXMA MP970 + +usb:v04A9p1727* + ID_MODEL_FROM_DATABASE=PIXMA MX300 + +usb:v04A9p1728* + ID_MODEL_FROM_DATABASE=PIXMA MX310 series + +usb:v04A9p1729* + ID_MODEL_FROM_DATABASE=PIXMA MX700 + +usb:v04A9p172B* + ID_MODEL_FROM_DATABASE=MP140 ser + +usb:v04A9p172C* + ID_MODEL_FROM_DATABASE=PIXMA MX850 + +usb:v04A9p172D* + ID_MODEL_FROM_DATABASE=PIXMA MP980 + +usb:v04A9p172E* + ID_MODEL_FROM_DATABASE=PIXMA MP630 + +usb:v04A9p172F* + ID_MODEL_FROM_DATABASE=PIXMA MP620 + +usb:v04A9p1730* + ID_MODEL_FROM_DATABASE=PIXMA MP540 + +usb:v04A9p1731* + ID_MODEL_FROM_DATABASE=PIXMA MP480 + +usb:v04A9p1732* + ID_MODEL_FROM_DATABASE=PIXMA MP240 + +usb:v04A9p1733* + ID_MODEL_FROM_DATABASE=PIXMA MP260 + +usb:v04A9p1734* + ID_MODEL_FROM_DATABASE=PIXMA MP190 + +usb:v04A9p1735* + ID_MODEL_FROM_DATABASE=PIXMA MX860 + +usb:v04A9p1736* + ID_MODEL_FROM_DATABASE=PIXMA MX320 series + +usb:v04A9p1737* + ID_MODEL_FROM_DATABASE=PIXMA MX330 + +usb:v04A9p173A* + ID_MODEL_FROM_DATABASE=PIXMA MP250 + +usb:v04A9p173B* + ID_MODEL_FROM_DATABASE=PIXMA MP270 All-In-One Printer + +usb:v04A9p173C* + ID_MODEL_FROM_DATABASE=PIXMA MP490 + +usb:v04A9p173D* + ID_MODEL_FROM_DATABASE=PIXMA MP550 + +usb:v04A9p173E* + ID_MODEL_FROM_DATABASE=PIXMA MP560 + +usb:v04A9p173F* + ID_MODEL_FROM_DATABASE=PIXMA MP640 + +usb:v04A9p1740* + ID_MODEL_FROM_DATABASE=PIXMA MP990 + +usb:v04A9p1741* + ID_MODEL_FROM_DATABASE=PIXMA MX340 + +usb:v04A9p1742* + ID_MODEL_FROM_DATABASE=PIXMA MX350 + +usb:v04A9p1743* + ID_MODEL_FROM_DATABASE=PIXMA MX870 + +usb:v04A9p1746* + ID_MODEL_FROM_DATABASE=PIXMA MP280 + +usb:v04A9p1747* + ID_MODEL_FROM_DATABASE=PIXMA MP495 + +usb:v04A9p1748* + ID_MODEL_FROM_DATABASE=PIXMA MG5100 Series + +usb:v04A9p1749* + ID_MODEL_FROM_DATABASE=PIXMA MG5200 Series + +usb:v04A9p174A* + ID_MODEL_FROM_DATABASE=PIXMA MG6100 Series + +usb:v04A9p174B* + ID_MODEL_FROM_DATABASE=PIXMA MG8100 Series + +usb:v04A9p174D* + ID_MODEL_FROM_DATABASE=PIXMA MX360 + +usb:v04A9p174E* + ID_MODEL_FROM_DATABASE=PIXMA MX410 + +usb:v04A9p174F* + ID_MODEL_FROM_DATABASE=PIXMA MX420 + +usb:v04A9p1750* + ID_MODEL_FROM_DATABASE=PIXMA MX880 Series + +usb:v04A9p1752* + ID_MODEL_FROM_DATABASE=PIXMA MG3100 Series + +usb:v04A9p1753* + ID_MODEL_FROM_DATABASE=PIXMA MG4100 Series + +usb:v04A9p1754* + ID_MODEL_FROM_DATABASE=PIXMA MG5300 Series + +usb:v04A9p1755* + ID_MODEL_FROM_DATABASE=PIXMA MG6200 Series + +usb:v04A9p1756* + ID_MODEL_FROM_DATABASE=PIXMA MG8200 Series + +usb:v04A9p1757* + ID_MODEL_FROM_DATABASE=PIXMA MP493 + +usb:v04A9p1759* + ID_MODEL_FROM_DATABASE=PIXMA MX370 Series + +usb:v04A9p175B* + ID_MODEL_FROM_DATABASE=PIXMA MX430 Series + +usb:v04A9p175C* + ID_MODEL_FROM_DATABASE=PIXMA MX510 Series + +usb:v04A9p175D* + ID_MODEL_FROM_DATABASE=PIXMA MX710 Series + +usb:v04A9p175E* + ID_MODEL_FROM_DATABASE=PIXMA MX890 Series + +usb:v04A9p175F* + ID_MODEL_FROM_DATABASE=PIXMA MP230 + +usb:v04A9p1762* + ID_MODEL_FROM_DATABASE=PIXMA MG3200 Series + +usb:v04A9p1763* + ID_MODEL_FROM_DATABASE=PIXMA MG4200 Series + +usb:v04A9p1764* + ID_MODEL_FROM_DATABASE=PIXMA MG5400 Series + +usb:v04A9p1765* + ID_MODEL_FROM_DATABASE=PIXMA MG6300 Series + +usb:v04A9p1766* + ID_MODEL_FROM_DATABASE=PIXMA MX390 Series + +usb:v04A9p1768* + ID_MODEL_FROM_DATABASE=PIXMA MX450 Series + +usb:v04A9p1769* + ID_MODEL_FROM_DATABASE=PIXMA MX520 Series + +usb:v04A9p176A* + ID_MODEL_FROM_DATABASE=PIXMA MX720 Series + +usb:v04A9p176B* + ID_MODEL_FROM_DATABASE=PIXMA MX920 Series + +usb:v04A9p176D* + ID_MODEL_FROM_DATABASE=PIXMA MG2500 Series + +usb:v04A9p176E* + ID_MODEL_FROM_DATABASE=PIXMA MG3500 Series + +usb:v04A9p176F* + ID_MODEL_FROM_DATABASE=PIXMA MG6500 Series + +usb:v04A9p1770* + ID_MODEL_FROM_DATABASE=PIXMA MG6400 Series + +usb:v04A9p1771* + ID_MODEL_FROM_DATABASE=PIXMA MG5500 Series + +usb:v04A9p1772* + ID_MODEL_FROM_DATABASE=PIXMA MG7100 Series + +usb:v04A9p1774* + ID_MODEL_FROM_DATABASE=PIXMA MX470 Series + +usb:v04A9p1775* + ID_MODEL_FROM_DATABASE=PIXMA MX530 Series + +usb:v04A9p177C* + ID_MODEL_FROM_DATABASE=PIXMA MG7500 Series + +usb:v04A9p177E* + ID_MODEL_FROM_DATABASE=PIXMA MG6600 Series + +usb:v04A9p177F* + ID_MODEL_FROM_DATABASE=PIXMA MG5600 Series + +usb:v04A9p1780* + ID_MODEL_FROM_DATABASE=PIXMA MG2900 Series + +usb:v04A9p1787* + ID_MODEL_FROM_DATABASE=PIXMA MX490 Series + +usb:v04A9p178A* + ID_MODEL_FROM_DATABASE=PIXMA MG3600 Series + +usb:v04A9p178D* + ID_MODEL_FROM_DATABASE=PIXMA MG6853 + +usb:v04A9p180B* + ID_MODEL_FROM_DATABASE=PIXMA MG3000 series + +usb:v04A9p1900* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 90 + +usb:v04A9p1901* + ID_MODEL_FROM_DATABASE=CanoScan 8800F + +usb:v04A9p1904* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 100 + +usb:v04A9p1905* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 200 + +usb:v04A9p1906* + ID_MODEL_FROM_DATABASE=CanoScan 5600F + +usb:v04A9p1907* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 700F + +usb:v04A9p1909* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 110 + +usb:v04A9p190A* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 210 + +usb:v04A9p190D* + ID_MODEL_FROM_DATABASE=CanoScan 9000F Mark II + +usb:v04A9p190E* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 120 + +usb:v04A9p190F* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 220 + +usb:v04A9p2200* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 25 + +usb:v04A9p2201* + ID_MODEL_FROM_DATABASE=CanoScan FB320U + +usb:v04A9p2202* + ID_MODEL_FROM_DATABASE=CanoScan FB620U + +usb:v04A9p2204* + ID_MODEL_FROM_DATABASE=CanoScan FB630U + +usb:v04A9p2205* + ID_MODEL_FROM_DATABASE=CanoScan FB1210U + +usb:v04A9p2206* + ID_MODEL_FROM_DATABASE=CanoScan N650U/N656U + +usb:v04A9p2207* + ID_MODEL_FROM_DATABASE=CanoScan 1220U + +usb:v04A9p2208* + ID_MODEL_FROM_DATABASE=CanoScan D660U + +usb:v04A9p220A* + ID_MODEL_FROM_DATABASE=CanoScan D2400UF + +usb:v04A9p220B* + ID_MODEL_FROM_DATABASE=CanoScan D646U + +usb:v04A9p220C* + ID_MODEL_FROM_DATABASE=CanoScan D1250U2 + +usb:v04A9p220D* + ID_MODEL_FROM_DATABASE=CanoScan N670U/N676U/LiDE 20 + +usb:v04A9p220E* + ID_MODEL_FROM_DATABASE=CanoScan N1240U/LiDE 30 + +usb:v04A9p220F* + ID_MODEL_FROM_DATABASE=CanoScan 8000F + +usb:v04A9p2210* + ID_MODEL_FROM_DATABASE=CanoScan 9900F + +usb:v04A9p2212* + ID_MODEL_FROM_DATABASE=CanoScan 5000F + +usb:v04A9p2213* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 50/LiDE 35/LiDE 40 + +usb:v04A9p2214* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 80 + +usb:v04A9p2215* + ID_MODEL_FROM_DATABASE=CanoScan 3000/3000F/3000ex + +usb:v04A9p2216* + ID_MODEL_FROM_DATABASE=CanoScan 3200F + +usb:v04A9p2217* + ID_MODEL_FROM_DATABASE=CanoScan 5200F + +usb:v04A9p2219* + ID_MODEL_FROM_DATABASE=CanoScan 9950F + +usb:v04A9p221B* + ID_MODEL_FROM_DATABASE=CanoScan 4200F + +usb:v04A9p221C* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 60 + +usb:v04A9p221E* + ID_MODEL_FROM_DATABASE=CanoScan 8400F + +usb:v04A9p221F* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 500F + +usb:v04A9p2220* + ID_MODEL_FROM_DATABASE=CanoScan LIDE 25 + +usb:v04A9p2224* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 600F + +usb:v04A9p2225* + ID_MODEL_FROM_DATABASE=CanoScan LiDE 70 + +usb:v04A9p2228* + ID_MODEL_FROM_DATABASE=CanoScan 4400F + +usb:v04A9p2229* + ID_MODEL_FROM_DATABASE=CanoScan 8600F + +usb:v04A9p2602* + ID_MODEL_FROM_DATABASE=MultiPASS C555 + +usb:v04A9p2603* + ID_MODEL_FROM_DATABASE=MultiPASS C755 + +usb:v04A9p260A* + ID_MODEL_FROM_DATABASE=LBP810 + +usb:v04A9p260E* + ID_MODEL_FROM_DATABASE=LBP-2000 + +usb:v04A9p2610* + ID_MODEL_FROM_DATABASE=MPC600F + +usb:v04A9p2611* + ID_MODEL_FROM_DATABASE=SmartBase MPC400 + +usb:v04A9p2612* + ID_MODEL_FROM_DATABASE=MultiPASS C855 + +usb:v04A9p2617* + ID_MODEL_FROM_DATABASE=LBP1210 + +usb:v04A9p261A* + ID_MODEL_FROM_DATABASE=iR1600 + +usb:v04A9p261B* + ID_MODEL_FROM_DATABASE=iR1610 + +usb:v04A9p261C* + ID_MODEL_FROM_DATABASE=iC2300 + +usb:v04A9p261F* + ID_MODEL_FROM_DATABASE=MPC200 Printer + +usb:v04A9p2621* + ID_MODEL_FROM_DATABASE=iR2000 + +usb:v04A9p2622* + ID_MODEL_FROM_DATABASE=iR2010 + +usb:v04A9p2623* + ID_MODEL_FROM_DATABASE=FAX-B180C + +usb:v04A9p2629* + ID_MODEL_FROM_DATABASE=FAXPHONE L75 + +usb:v04A9p262B* + ID_MODEL_FROM_DATABASE=LaserShot LBP-1120 Printer + +usb:v04A9p262C* + ID_MODEL_FROM_DATABASE=imageCLASS D300 + +usb:v04A9p262D* + ID_MODEL_FROM_DATABASE=iR C3200 + +usb:v04A9p262F* + ID_MODEL_FROM_DATABASE=PIXMA MP730 + +usb:v04A9p2630* + ID_MODEL_FROM_DATABASE=PIXMA MP700 + +usb:v04A9p2631* + ID_MODEL_FROM_DATABASE=LASER CLASS 700 + +usb:v04A9p2632* + ID_MODEL_FROM_DATABASE=FAX-L2000 + +usb:v04A9p2633* + ID_MODEL_FROM_DATABASE=LASERCLASS 500 + +usb:v04A9p2634* + ID_MODEL_FROM_DATABASE=PC-D300/FAX-L400/ICD300 + +usb:v04A9p2635* + ID_MODEL_FROM_DATABASE=MPC190 + +usb:v04A9p2637* + ID_MODEL_FROM_DATABASE=iR C6800 + +usb:v04A9p2638* + ID_MODEL_FROM_DATABASE=iR C3100 + +usb:v04A9p263C* + ID_MODEL_FROM_DATABASE=PIXMA MP360 + +usb:v04A9p263D* + ID_MODEL_FROM_DATABASE=PIXMA MP370 + +usb:v04A9p263E* + ID_MODEL_FROM_DATABASE=PIXMA MP390 + +usb:v04A9p263F* + ID_MODEL_FROM_DATABASE=PIXMA MP375R + +usb:v04A9p2646* + ID_MODEL_FROM_DATABASE=MF5530 Scanner Device V1.9.1 + +usb:v04A9p2647* + ID_MODEL_FROM_DATABASE=MF5550 Composite + +usb:v04A9p264C* + ID_MODEL_FROM_DATABASE=PIXMA MP740 + +usb:v04A9p264D* + ID_MODEL_FROM_DATABASE=PIXMA MP710 + +usb:v04A9p264E* + ID_MODEL_FROM_DATABASE=MF5630 + +usb:v04A9p264F* + ID_MODEL_FROM_DATABASE=MF5650 (FAX) + +usb:v04A9p2650* + ID_MODEL_FROM_DATABASE=iR 6800C EUR + +usb:v04A9p2651* + ID_MODEL_FROM_DATABASE=iR 3100C EUR + +usb:v04A9p2655* + ID_MODEL_FROM_DATABASE=FP-L170/MF350/L380/L398 + +usb:v04A9p2656* + ID_MODEL_FROM_DATABASE=iR1510-1670 CAPT Printer + +usb:v04A9p2659* + ID_MODEL_FROM_DATABASE=MF8100 + +usb:v04A9p265B* + ID_MODEL_FROM_DATABASE=CAPT Printer + +usb:v04A9p265C* + ID_MODEL_FROM_DATABASE=iR C3220 + +usb:v04A9p265D* + ID_MODEL_FROM_DATABASE=MF5730 + +usb:v04A9p265E* + ID_MODEL_FROM_DATABASE=MF5750 + +usb:v04A9p265F* + ID_MODEL_FROM_DATABASE=MF5770 + +usb:v04A9p2660* + ID_MODEL_FROM_DATABASE=MF3110 + +usb:v04A9p2663* + ID_MODEL_FROM_DATABASE=iR3570/iR4570 + +usb:v04A9p2664* + ID_MODEL_FROM_DATABASE=iR2270/iR2870 + +usb:v04A9p2665* + ID_MODEL_FROM_DATABASE=iR C2620 + +usb:v04A9p2666* + ID_MODEL_FROM_DATABASE=iR C5800 + +usb:v04A9p2667* + ID_MODEL_FROM_DATABASE=iR85PLUS + +usb:v04A9p2669* + ID_MODEL_FROM_DATABASE=iR105PLUS + +usb:v04A9p266A* + ID_MODEL_FROM_DATABASE=CAPT Device + +usb:v04A9p266B* + ID_MODEL_FROM_DATABASE=iR8070 + +usb:v04A9p266C* + ID_MODEL_FROM_DATABASE=iR9070 + +usb:v04A9p266D* + ID_MODEL_FROM_DATABASE=iR 5800C EUR + +usb:v04A9p266E* + ID_MODEL_FROM_DATABASE=CAPT Device + +usb:v04A9p266F* + ID_MODEL_FROM_DATABASE=iR2230 + +usb:v04A9p2670* + ID_MODEL_FROM_DATABASE=iR3530 + +usb:v04A9p2671* + ID_MODEL_FROM_DATABASE=iR5570/iR6570 + +usb:v04A9p2672* + ID_MODEL_FROM_DATABASE=iR C3170 + +usb:v04A9p2673* + ID_MODEL_FROM_DATABASE=iR 3170C EUR + +usb:v04A9p2674* + ID_MODEL_FROM_DATABASE=FAX-L120 + +usb:v04A9p2675* + ID_MODEL_FROM_DATABASE=iR2830 + +usb:v04A9p2676* + ID_MODEL_FROM_DATABASE=LBP2900 + +usb:v04A9p2677* + ID_MODEL_FROM_DATABASE=iR C2570 + +usb:v04A9p2678* + ID_MODEL_FROM_DATABASE=iR 2570C EUR + +usb:v04A9p2679* + ID_MODEL_FROM_DATABASE=CAPT Device + +usb:v04A9p267A* + ID_MODEL_FROM_DATABASE=iR2016 + +usb:v04A9p267B* + ID_MODEL_FROM_DATABASE=iR2020 + +usb:v04A9p267D* + ID_MODEL_FROM_DATABASE=MF7100 series + +usb:v04A9p2684* + ID_MODEL_FROM_DATABASE=MF3200 series + +usb:v04A9p2686* + ID_MODEL_FROM_DATABASE=MF6500 series + +usb:v04A9p2687* + ID_MODEL_FROM_DATABASE=iR4530 + +usb:v04A9p2688* + ID_MODEL_FROM_DATABASE=LBP3460 + +usb:v04A9p2689* + ID_MODEL_FROM_DATABASE=FAX-L180/L380S/L398S + +usb:v04A9p268A* + ID_MODEL_FROM_DATABASE=LC310/L390/L408S + +usb:v04A9p268C* + ID_MODEL_FROM_DATABASE=iR C6870 + +usb:v04A9p268D* + ID_MODEL_FROM_DATABASE=iR 6870C EUR + +usb:v04A9p268E* + ID_MODEL_FROM_DATABASE=iR C5870 + +usb:v04A9p268F* + ID_MODEL_FROM_DATABASE=iR 5870C EUR + +usb:v04A9p2691* + ID_MODEL_FROM_DATABASE=iR7105 + +usb:v04A9p26A3* + ID_MODEL_FROM_DATABASE=MF4100 series + +usb:v04A9p26B0* + ID_MODEL_FROM_DATABASE=MF4600 series + +usb:v04A9p26B4* + ID_MODEL_FROM_DATABASE=MF4010 series + +usb:v04A9p26B5* + ID_MODEL_FROM_DATABASE=MF4200 series + +usb:v04A9p26B6* + ID_MODEL_FROM_DATABASE=FAX-L140/L130 + +usb:v04A9p26DA* + ID_MODEL_FROM_DATABASE=LBP3010B printer + +usb:v04A9p26E6* + ID_MODEL_FROM_DATABASE=iR1024 + +usb:v04A9p271A* + ID_MODEL_FROM_DATABASE=LBP6000 + +usb:v04A9p2736* + ID_MODEL_FROM_DATABASE=I-SENSYS MF4550d + +usb:v04A9p2737* + ID_MODEL_FROM_DATABASE=MF4410 + +usb:v04A9p3041* + ID_MODEL_FROM_DATABASE=PowerShot S10 + +usb:v04A9p3042* + ID_MODEL_FROM_DATABASE=CanoScan FS4000US Film Scanner + +usb:v04A9p3043* + ID_MODEL_FROM_DATABASE=PowerShot S20 + +usb:v04A9p3044* + ID_MODEL_FROM_DATABASE=EOS D30 + +usb:v04A9p3045* + ID_MODEL_FROM_DATABASE=PowerShot S100 + +usb:v04A9p3046* + ID_MODEL_FROM_DATABASE=IXY Digital + +usb:v04A9p3047* + ID_MODEL_FROM_DATABASE=Digital IXUS + +usb:v04A9p3048* + ID_MODEL_FROM_DATABASE=PowerShot G1 + +usb:v04A9p3049* + ID_MODEL_FROM_DATABASE=PowerShot Pro90 IS + +usb:v04A9p304A* + ID_MODEL_FROM_DATABASE=CP-10 + +usb:v04A9p304B* + ID_MODEL_FROM_DATABASE=IXY Digital 300 + +usb:v04A9p304C* + ID_MODEL_FROM_DATABASE=PowerShot S300 + +usb:v04A9p304D* + ID_MODEL_FROM_DATABASE=Digital IXUS 300 + +usb:v04A9p304E* + ID_MODEL_FROM_DATABASE=PowerShot A20 + +usb:v04A9p304F* + ID_MODEL_FROM_DATABASE=PowerShot A10 + +usb:v04A9p3050* + ID_MODEL_FROM_DATABASE=PowerShot unknown 1 + +usb:v04A9p3051* + ID_MODEL_FROM_DATABASE=PowerShot S110 + +usb:v04A9p3052* + ID_MODEL_FROM_DATABASE=Digital IXUS V + +usb:v04A9p3055* + ID_MODEL_FROM_DATABASE=PowerShot G2 + +usb:v04A9p3056* + ID_MODEL_FROM_DATABASE=PowerShot S40 + +usb:v04A9p3057* + ID_MODEL_FROM_DATABASE=PowerShot S30 + +usb:v04A9p3058* + ID_MODEL_FROM_DATABASE=PowerShot A40 + +usb:v04A9p3059* + ID_MODEL_FROM_DATABASE=PowerShot A30 + +usb:v04A9p305B* + ID_MODEL_FROM_DATABASE=ZR45MC Digital Camcorder + +usb:v04A9p305C* + ID_MODEL_FROM_DATABASE=PowerShot unknown 2 + +usb:v04A9p3060* + ID_MODEL_FROM_DATABASE=EOS D60 + +usb:v04A9p3061* + ID_MODEL_FROM_DATABASE=PowerShot A100 + +usb:v04A9p3062* + ID_MODEL_FROM_DATABASE=PowerShot A200 + +usb:v04A9p3063* + ID_MODEL_FROM_DATABASE=CP-100 + +usb:v04A9p3065* + ID_MODEL_FROM_DATABASE=PowerShot S200 + +usb:v04A9p3066* + ID_MODEL_FROM_DATABASE=Digital IXUS 330 + +usb:v04A9p3067* + ID_MODEL_FROM_DATABASE=MV550i Digital Video Camera + +usb:v04A9p3069* + ID_MODEL_FROM_DATABASE=PowerShot G3 + +usb:v04A9p306A* + ID_MODEL_FROM_DATABASE=Digital unknown 3 + +usb:v04A9p306B* + ID_MODEL_FROM_DATABASE=MVX2i Digital Video Camera + +usb:v04A9p306C* + ID_MODEL_FROM_DATABASE=PowerShot S45 + +usb:v04A9p306D* + ID_MODEL_FROM_DATABASE=PowerShot S45 PtP Mode + +usb:v04A9p306E* + ID_MODEL_FROM_DATABASE=PowerShot G3 (normal mode) + +usb:v04A9p306F* + ID_MODEL_FROM_DATABASE=PowerShot G3 (ptp) + +usb:v04A9p3070* + ID_MODEL_FROM_DATABASE=PowerShot S230 + +usb:v04A9p3071* + ID_MODEL_FROM_DATABASE=PowerShot S230 (ptp) + +usb:v04A9p3072* + ID_MODEL_FROM_DATABASE=PowerShot SD100 / Digital IXUS II (ptp) + +usb:v04A9p3073* + ID_MODEL_FROM_DATABASE=PowerShot A70 (ptp) + +usb:v04A9p3074* + ID_MODEL_FROM_DATABASE=PowerShot A60 (ptp) + +usb:v04A9p3075* + ID_MODEL_FROM_DATABASE=IXUS 400 Camera + +usb:v04A9p3076* + ID_MODEL_FROM_DATABASE=PowerShot A300 + +usb:v04A9p3077* + ID_MODEL_FROM_DATABASE=PowerShot S50 + +usb:v04A9p3078* + ID_MODEL_FROM_DATABASE=ZR70MC Digital Camcorder + +usb:v04A9p307A* + ID_MODEL_FROM_DATABASE=MV650i (normal mode) + +usb:v04A9p307B* + ID_MODEL_FROM_DATABASE=MV630i Digital Video Camera + +usb:v04A9p307C* + ID_MODEL_FROM_DATABASE=CP-200 + +usb:v04A9p307D* + ID_MODEL_FROM_DATABASE=CP-300 + +usb:v04A9p307F* + ID_MODEL_FROM_DATABASE=Optura 20 + +usb:v04A9p3080* + ID_MODEL_FROM_DATABASE=MVX150i (normal mode) / Optura 20 (normal mode) + +usb:v04A9p3081* + ID_MODEL_FROM_DATABASE=Optura 10 + +usb:v04A9p3082* + ID_MODEL_FROM_DATABASE=MVX100i / Optura 10 + +usb:v04A9p3083* + ID_MODEL_FROM_DATABASE=EOS 10D + +usb:v04A9p3084* + ID_MODEL_FROM_DATABASE=EOS 300D / EOS Digital Rebel + +usb:v04A9p3085* + ID_MODEL_FROM_DATABASE=PowerShot G5 + +usb:v04A9p3087* + ID_MODEL_FROM_DATABASE=Elura 50 (PTP mode) + +usb:v04A9p3088* + ID_MODEL_FROM_DATABASE=Elura 50 (normal mode) + +usb:v04A9p308D* + ID_MODEL_FROM_DATABASE=MVX3i + +usb:v04A9p308E* + ID_MODEL_FROM_DATABASE=FV M1 (normal mode) / MVX 3i (normal mode) / Optura Xi (normal mode) + +usb:v04A9p3093* + ID_MODEL_FROM_DATABASE=Optura 300 + +usb:v04A9p3096* + ID_MODEL_FROM_DATABASE=IXY DV M2 (normal mode) / MVX 10i (normal mode) + +usb:v04A9p3099* + ID_MODEL_FROM_DATABASE=EOS 300D (ptp) + +usb:v04A9p309A* + ID_MODEL_FROM_DATABASE=PowerShot A80 + +usb:v04A9p309B* + ID_MODEL_FROM_DATABASE=Digital IXUS (ptp) + +usb:v04A9p309C* + ID_MODEL_FROM_DATABASE=PowerShot S1 IS + +usb:v04A9p309D* + ID_MODEL_FROM_DATABASE=Powershot Pro 1 + +usb:v04A9p309F* + ID_MODEL_FROM_DATABASE=Camera + +usb:v04A9p30A0* + ID_MODEL_FROM_DATABASE=Camera + +usb:v04A9p30A1* + ID_MODEL_FROM_DATABASE=Camera + +usb:v04A9p30A2* + ID_MODEL_FROM_DATABASE=Camera + +usb:v04A9p30A8* + ID_MODEL_FROM_DATABASE=Elura 60E/Optura 40 (ptp) + +usb:v04A9p30A9* + ID_MODEL_FROM_DATABASE=MVX25i (normal mode) / Optura 40 (normal mode) + +usb:v04A9p30B1* + ID_MODEL_FROM_DATABASE=PowerShot S70 (normal mode) / PowerShot S70 (PTP mode) + +usb:v04A9p30B2* + ID_MODEL_FROM_DATABASE=PowerShot S60 (normal mode) / PowerShot S60 (PTP mode) + +usb:v04A9p30B3* + ID_MODEL_FROM_DATABASE=PowerShot G6 (normal mode) / PowerShot G6 (PTP mode) + +usb:v04A9p30B4* + ID_MODEL_FROM_DATABASE=PowerShot S500 + +usb:v04A9p30B5* + ID_MODEL_FROM_DATABASE=PowerShot A75 + +usb:v04A9p30B6* + ID_MODEL_FROM_DATABASE=Digital IXUS II2 / Digital IXUS II2 (PTP mode) / PowerShot SD110 (PTP mode) / PowerShot SD110 Digital ELPH + +usb:v04A9p30B7* + ID_MODEL_FROM_DATABASE=PowerShot A400 / PowerShot A400 (PTP mode) + +usb:v04A9p30B8* + ID_MODEL_FROM_DATABASE=PowerShot A310 / PowerShot A310 (PTP mode) + +usb:v04A9p30B9* + ID_MODEL_FROM_DATABASE=Powershot A85 + +usb:v04A9p30BA* + ID_MODEL_FROM_DATABASE=PowerShot S410 Digital Elph + +usb:v04A9p30BB* + ID_MODEL_FROM_DATABASE=PowerShot A95 + +usb:v04A9p30BD* + ID_MODEL_FROM_DATABASE=CP-220 + +usb:v04A9p30BE* + ID_MODEL_FROM_DATABASE=CP-330 + +usb:v04A9p30BF* + ID_MODEL_FROM_DATABASE=Digital IXUS 40 + +usb:v04A9p30C0* + ID_MODEL_FROM_DATABASE=Digital IXUS 30 (PTP mode) / PowerShot SD200 (PTP mode) + +usb:v04A9p30C1* + ID_MODEL_FROM_DATABASE=Digital IXUS 50 (normal mode) / IXY Digital 55 (normal mode) / PowerShot A520 (PTP mode) / PowerShot SD400 (normal mode) + +usb:v04A9p30C2* + ID_MODEL_FROM_DATABASE=PowerShot A510 (normal mode) / PowerShot A510 (PTP mode) + +usb:v04A9p30C4* + ID_MODEL_FROM_DATABASE=Digital IXUS i5 (normal mode) / IXY Digital L2 (normal mode) / PowerShot SD20 (normal mode) + +usb:v04A9p30EA* + ID_MODEL_FROM_DATABASE=EOS 1D Mark II (PTP mode) + +usb:v04A9p30EB* + ID_MODEL_FROM_DATABASE=EOS 20D + +usb:v04A9p30EC* + ID_MODEL_FROM_DATABASE=EOS 20D (ptp) + +usb:v04A9p30EE* + ID_MODEL_FROM_DATABASE=EOS 350D + +usb:v04A9p30EF* + ID_MODEL_FROM_DATABASE=EOS 350D (ptp) + +usb:v04A9p30F0* + ID_MODEL_FROM_DATABASE=PowerShot S2 IS (PTP mode) + +usb:v04A9p30F2* + ID_MODEL_FROM_DATABASE=Digital IXUS 700 (normal mode) / Digital IXUS 700 (PTP mode) / IXY Digital 600 (normal mode) / PowerShot SD500 (normal mode) / PowerShot SD500 (PTP mode) + +usb:v04A9p30F4* + ID_MODEL_FROM_DATABASE=PowerShot SD30 / Ixus iZoom / IXY DIGITAL L3 + +usb:v04A9p30F5* + ID_MODEL_FROM_DATABASE=SELPHY CP500 + +usb:v04A9p30F6* + ID_MODEL_FROM_DATABASE=SELPHY CP400 + +usb:v04A9p30F8* + ID_MODEL_FROM_DATABASE=Powershot A430 + +usb:v04A9p30F9* + ID_MODEL_FROM_DATABASE=PowerShot A410 (PTP mode) + +usb:v04A9p30FA* + ID_MODEL_FROM_DATABASE=PowerShot S80 + +usb:v04A9p30FC* + ID_MODEL_FROM_DATABASE=PowerShot A620 (PTP mode) + +usb:v04A9p30FD* + ID_MODEL_FROM_DATABASE=PowerShot A610 (normal mode)/PowerShot A610 (PTP mode) + +usb:v04A9p30FE* + ID_MODEL_FROM_DATABASE=Digital IXUS 65 (PTP mode)/PowerShot SD630 (PTP mode) + +usb:v04A9p30FF* + ID_MODEL_FROM_DATABASE=Digital IXUS 55 (PTP mode)/PowerShot SD450 (PTP mode) + +usb:v04A9p3100* + ID_MODEL_FROM_DATABASE=PowerShot TX1 + +usb:v04A9p310B* + ID_MODEL_FROM_DATABASE=SELPHY CP600 + +usb:v04A9p310E* + ID_MODEL_FROM_DATABASE=Digital IXUS 50 (PTP mode) + +usb:v04A9p310F* + ID_MODEL_FROM_DATABASE=PowerShot A420 + +usb:v04A9p3110* + ID_MODEL_FROM_DATABASE=EOS Digital Rebel XTi + +usb:v04A9p3115* + ID_MODEL_FROM_DATABASE=PowerShot SD900 / Digital IXUS 900 Ti / IXY DIGITAL 1000 + +usb:v04A9p3116* + ID_MODEL_FROM_DATABASE=Digital IXUS 750 / PowerShot SD550 (PTP mode) + +usb:v04A9p3117* + ID_MODEL_FROM_DATABASE=PowerShot A700 + +usb:v04A9p3119* + ID_MODEL_FROM_DATABASE=PowerShot SD700 IS / Digital IXUS 800 IS / IXY Digital 800 IS + +usb:v04A9p311A* + ID_MODEL_FROM_DATABASE=PowerShot S3 IS + +usb:v04A9p311B* + ID_MODEL_FROM_DATABASE=PowerShot A540 + +usb:v04A9p311C* + ID_MODEL_FROM_DATABASE=PowerShot SD600 DIGITAL ELPH / DIGITAL IXUS 60 / IXY DIGITAL 70 + +usb:v04A9p3125* + ID_MODEL_FROM_DATABASE=PowerShot G7 + +usb:v04A9p3126* + ID_MODEL_FROM_DATABASE=PowerShot A530 + +usb:v04A9p3127* + ID_MODEL_FROM_DATABASE=SELPHY CP710 + +usb:v04A9p3128* + ID_MODEL_FROM_DATABASE=SELPHY CP510 + +usb:v04A9p312D* + ID_MODEL_FROM_DATABASE=Elura 100 + +usb:v04A9p3136* + ID_MODEL_FROM_DATABASE=PowerShot SD800 IS / Digital IXUS 850 IS / IXY DIGITAL 900 IS + +usb:v04A9p3137* + ID_MODEL_FROM_DATABASE=PowerShot SD40 / Digital IXUS i7 IXY / DIGITAL L4 + +usb:v04A9p3138* + ID_MODEL_FROM_DATABASE=PowerShot A710 IS + +usb:v04A9p3139* + ID_MODEL_FROM_DATABASE=PowerShot A640 + +usb:v04A9p313A* + ID_MODEL_FROM_DATABASE=PowerShot A630 + +usb:v04A9p3141* + ID_MODEL_FROM_DATABASE=SELPHY ES1 + +usb:v04A9p3142* + ID_MODEL_FROM_DATABASE=SELPHY CP730 + +usb:v04A9p3143* + ID_MODEL_FROM_DATABASE=SELPHY CP720 + +usb:v04A9p3145* + ID_MODEL_FROM_DATABASE=EOS 450D + +usb:v04A9p3146* + ID_MODEL_FROM_DATABASE=EOS 40D + +usb:v04A9p3147* + ID_MODEL_FROM_DATABASE=EOS 1Ds Mark III + +usb:v04A9p3148* + ID_MODEL_FROM_DATABASE=PowerShot S5 IS + +usb:v04A9p3149* + ID_MODEL_FROM_DATABASE=PowerShot A460 + +usb:v04A9p314B* + ID_MODEL_FROM_DATABASE=PowerShot SD850 IS DIGITAL ELPH / Digital IXUS 950 IS / IXY DIGITAL 810 IS + +usb:v04A9p314C* + ID_MODEL_FROM_DATABASE=PowerShot A570 IS + +usb:v04A9p314D* + ID_MODEL_FROM_DATABASE=PowerShot A560 + +usb:v04A9p314E* + ID_MODEL_FROM_DATABASE=PowerShot SD750 DIGITAL ELPH / DIGITAL IXUS 75 / IXY DIGITAL 90 + +usb:v04A9p314F* + ID_MODEL_FROM_DATABASE=PowerShot SD1000 DIGITAL ELPH / DIGITAL IXUS 70 / IXY DIGITAL 10 + +usb:v04A9p3150* + ID_MODEL_FROM_DATABASE=PowerShot A550 + +usb:v04A9p3155* + ID_MODEL_FROM_DATABASE=PowerShot A450 + +usb:v04A9p315A* + ID_MODEL_FROM_DATABASE=PowerShot G9 + +usb:v04A9p315B* + ID_MODEL_FROM_DATABASE=PowerShot A650 IS + +usb:v04A9p315D* + ID_MODEL_FROM_DATABASE=PowerShot A720 + +usb:v04A9p315E* + ID_MODEL_FROM_DATABASE=PowerShot SX100 IS + +usb:v04A9p315F* + ID_MODEL_FROM_DATABASE=PowerShot SD950 IS DIGITAL ELPH / DIGITAL IXUS 960 IS / IXY DIGITAL 2000 IS + +usb:v04A9p3160* + ID_MODEL_FROM_DATABASE=Digital IXUS 860 IS + +usb:v04A9p3170* + ID_MODEL_FROM_DATABASE=SELPHY CP750 + +usb:v04A9p3171* + ID_MODEL_FROM_DATABASE=SELPHY CP740 + +usb:v04A9p3172* + ID_MODEL_FROM_DATABASE=SELPHY CP520 + +usb:v04A9p3173* + ID_MODEL_FROM_DATABASE=PowerShot SD890 IS DIGITAL ELPH / Digital IXUS 970 IS / IXY DIGITAL 820 IS + +usb:v04A9p3174* + ID_MODEL_FROM_DATABASE=PowerShot SD790 IS DIGITAL ELPH / Digital IXUS 90 IS / IXY DIGITAL 95 IS + +usb:v04A9p3175* + ID_MODEL_FROM_DATABASE=IXY Digital 25 IS + +usb:v04A9p3176* + ID_MODEL_FROM_DATABASE=PowerShot A590 + +usb:v04A9p3177* + ID_MODEL_FROM_DATABASE=PowerShot A580 + +usb:v04A9p317A* + ID_MODEL_FROM_DATABASE=PC1267 [Powershot A470] + +usb:v04A9p3184* + ID_MODEL_FROM_DATABASE=Digital IXUS 80 IS (PTP mode) + +usb:v04A9p3185* + ID_MODEL_FROM_DATABASE=SELPHY ES2 + +usb:v04A9p3186* + ID_MODEL_FROM_DATABASE=SELPHY ES20 + +usb:v04A9p318D* + ID_MODEL_FROM_DATABASE=PowerShot SX100 IS + +usb:v04A9p318E* + ID_MODEL_FROM_DATABASE=PowerShot A1000 IS + +usb:v04A9p318F* + ID_MODEL_FROM_DATABASE=PowerShot G10 + +usb:v04A9p3191* + ID_MODEL_FROM_DATABASE=PowerShot A2000 IS + +usb:v04A9p3192* + ID_MODEL_FROM_DATABASE=PowerShot SX110 IS + +usb:v04A9p3193* + ID_MODEL_FROM_DATABASE=PowerShot SD990 IS DIGITAL ELPH / Digital IXUS 980 IS / IXY DIGITAL 3000 IS + +usb:v04A9p3195* + ID_MODEL_FROM_DATABASE=PowerShot SX1 IS + +usb:v04A9p3196* + ID_MODEL_FROM_DATABASE=PowerShot SD880 IS DIGITAL ELPH / Digital IXUS 870 IS / IXY DIGITAL 920 IS + +usb:v04A9p3199* + ID_MODEL_FROM_DATABASE=EOS 5D Mark II + +usb:v04A9p319A* + ID_MODEL_FROM_DATABASE=EOS 7D + +usb:v04A9p319B* + ID_MODEL_FROM_DATABASE=EOS 50D + +usb:v04A9p31AA* + ID_MODEL_FROM_DATABASE=SELPHY CP770 + +usb:v04A9p31AB* + ID_MODEL_FROM_DATABASE=SELPHY CP760 + +usb:v04A9p31AD* + ID_MODEL_FROM_DATABASE=PowerShot E1 + +usb:v04A9p31AF* + ID_MODEL_FROM_DATABASE=SELPHY ES3 + +usb:v04A9p31B0* + ID_MODEL_FROM_DATABASE=SELPHY ES30 + +usb:v04A9p31B1* + ID_MODEL_FROM_DATABASE=SELPHY CP530 + +usb:v04A9p31BC* + ID_MODEL_FROM_DATABASE=PowerShot D10 + +usb:v04A9p31BD* + ID_MODEL_FROM_DATABASE=PowerShot SD960 IS DIGITAL ELPH / Digital IXUS 110 IS / IXY DIGITAL 510 IS + +usb:v04A9p31BE* + ID_MODEL_FROM_DATABASE=PowerShot A2100 IS + +usb:v04A9p31BF* + ID_MODEL_FROM_DATABASE=PowerShot A480 + +usb:v04A9p31C0* + ID_MODEL_FROM_DATABASE=PowerShot SX200 IS + +usb:v04A9p31C1* + ID_MODEL_FROM_DATABASE=PowerShot SD970 IS DIGITAL ELPH / Digital IXUS 990 IS / IXY DIGITAL 830 IS + +usb:v04A9p31C2* + ID_MODEL_FROM_DATABASE=PowerShot SD780 IS DIGITAL ELPH / Digital IXUS 100 IS / IXY DIGITAL 210 IS + +usb:v04A9p31C3* + ID_MODEL_FROM_DATABASE=PowerShot A1100 IS + +usb:v04A9p31C4* + ID_MODEL_FROM_DATABASE=PowerShot SD1200 IS DIGITAL ELPH / Digital IXUS 95 IS / IXY DIGITAL 110 IS + +usb:v04A9p31CF* + ID_MODEL_FROM_DATABASE=EOS Rebel T1i / EOS 500D / EOS Kiss X3 + +usb:v04A9p31DD* + ID_MODEL_FROM_DATABASE=SELPHY CP780 + +usb:v04A9p31DF* + ID_MODEL_FROM_DATABASE=PowerShot G11 + +usb:v04A9p31E0* + ID_MODEL_FROM_DATABASE=PowerShot SX120 IS + +usb:v04A9p31E1* + ID_MODEL_FROM_DATABASE=PowerShot S90 + +usb:v04A9p31E4* + ID_MODEL_FROM_DATABASE=PowerShot SX20 IS + +usb:v04A9p31E5* + ID_MODEL_FROM_DATABASE=Digital IXUS 200 IS + +usb:v04A9p31E6* + ID_MODEL_FROM_DATABASE=PowerShot SD940 IS DIGITAL ELPH / Digital IXUS 120 IS / IXY DIGITAL 220 IS + +usb:v04A9p31E7* + ID_MODEL_FROM_DATABASE=SELPHY CP790 + +usb:v04A9p31EA* + ID_MODEL_FROM_DATABASE=EOS Rebel T2i / EOS 550D / EOS Kiss X4 + +usb:v04A9p31EE* + ID_MODEL_FROM_DATABASE=SELPHY ES40 + +usb:v04A9p31EF* + ID_MODEL_FROM_DATABASE=PowerShot A495 + +usb:v04A9p31F0* + ID_MODEL_FROM_DATABASE=PowerShot A490 + +usb:v04A9p31F1* + ID_MODEL_FROM_DATABASE=PowerShot A3100 IS / PowerShot A3150 IS + +usb:v04A9p31F2* + ID_MODEL_FROM_DATABASE=PowerShot A3000 IS + +usb:v04A9p31F3* + ID_MODEL_FROM_DATABASE=PowerShot Digital ELPH SD1400 IS + +usb:v04A9p31F4* + ID_MODEL_FROM_DATABASE=PowerShot SD1300 IS / IXUS 105 + +usb:v04A9p31F5* + ID_MODEL_FROM_DATABASE=Powershot SD3500 IS / IXUS 210 IS + +usb:v04A9p31F6* + ID_MODEL_FROM_DATABASE=PowerShot SX210 IS + +usb:v04A9p31F7* + ID_MODEL_FROM_DATABASE=Powershot SD4000 IS / IXUS 300 HS / IXY 30S + +usb:v04A9p31F8* + ID_MODEL_FROM_DATABASE=Powershot SD4500 IS / IXUS 1000 HS / IXY 50S + +usb:v04A9p31FF* + ID_MODEL_FROM_DATABASE=Digital IXUS 55 + +usb:v04A9p3209* + ID_MODEL_FROM_DATABASE=Vixia HF S21 A + +usb:v04A9p320F* + ID_MODEL_FROM_DATABASE=PowerShot G12 + +usb:v04A9p3210* + ID_MODEL_FROM_DATABASE=Powershot SX30 IS + +usb:v04A9p3211* + ID_MODEL_FROM_DATABASE=PowerShot SX130 IS + +usb:v04A9p3212* + ID_MODEL_FROM_DATABASE=Powershot S95 + +usb:v04A9p3214* + ID_MODEL_FROM_DATABASE=SELPHY CP800 + +usb:v04A9p3215* + ID_MODEL_FROM_DATABASE=EOS 60D + +usb:v04A9p3218* + ID_MODEL_FROM_DATABASE=EOS 600D / Rebel T3i (ptp) + +usb:v04A9p3219* + ID_MODEL_FROM_DATABASE=EOS 1D X + +usb:v04A9p3223* + ID_MODEL_FROM_DATABASE=PowerShot A3300 IS + +usb:v04A9p3224* + ID_MODEL_FROM_DATABASE=PowerShot A3200 IS + +usb:v04A9p3225* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 500 HS / IXUS 310 HS + +usb:v04A9p3226* + ID_MODEL_FROM_DATABASE=PowerShow A800 + +usb:v04A9p3227* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 100 HS / IXUS 115 HS + +usb:v04A9p3228* + ID_MODEL_FROM_DATABASE=PowerShot SX230 HS + +usb:v04A9p3229* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 300 HS / IXUS 220 HS + +usb:v04A9p322A* + ID_MODEL_FROM_DATABASE=PowerShot A2200 + +usb:v04A9p322B* + ID_MODEL_FROM_DATABASE=Powershot A1200 + +usb:v04A9p322C* + ID_MODEL_FROM_DATABASE=PowerShot SX220 HS + +usb:v04A9p3233* + ID_MODEL_FROM_DATABASE=PowerShot G1 X + +usb:v04A9p3234* + ID_MODEL_FROM_DATABASE=PowerShot SX150 IS + +usb:v04A9p3235* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 510 HS / IXUS 1100 HS + +usb:v04A9p3236* + ID_MODEL_FROM_DATABASE=PowerShot S100 + +usb:v04A9p3237* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 310 HS / IXUS 230 HS + +usb:v04A9p3238* + ID_MODEL_FROM_DATABASE=PowerShot SX40 HS + +usb:v04A9p323A* + ID_MODEL_FROM_DATABASE=EOS 5D Mark III + +usb:v04A9p323B* + ID_MODEL_FROM_DATABASE=EOS Rebel T4i + +usb:v04A9p323D* + ID_MODEL_FROM_DATABASE=EOS M + +usb:v04A9p323E* + ID_MODEL_FROM_DATABASE=PowerShot A1300 + +usb:v04A9p323F* + ID_MODEL_FROM_DATABASE=PowerShot A810 + +usb:v04A9p3240* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 320 HS / IXUS 240 HS + +usb:v04A9p3241* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 110 HS / IXUS 125 HS + +usb:v04A9p3242* + ID_MODEL_FROM_DATABASE=PowerShot D20 + +usb:v04A9p3243* + ID_MODEL_FROM_DATABASE=PowerShot A4000 IS + +usb:v04A9p3244* + ID_MODEL_FROM_DATABASE=PowerShot SX260 HS + +usb:v04A9p3245* + ID_MODEL_FROM_DATABASE=PowerShot SX240 HS + +usb:v04A9p3246* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 530 HS / IXUS 510 HS + +usb:v04A9p3247* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 520 HS / IXUS 500 HS + +usb:v04A9p3248* + ID_MODEL_FROM_DATABASE=PowerShot A3400 IS + +usb:v04A9p3249* + ID_MODEL_FROM_DATABASE=PowerShot A2400 IS + +usb:v04A9p324A* + ID_MODEL_FROM_DATABASE=PowerShot A2300 + +usb:v04A9p3250* + ID_MODEL_FROM_DATABASE=EOS 6D + +usb:v04A9p3252* + ID_MODEL_FROM_DATABASE=EOS 1D C + +usb:v04A9p3253* + ID_MODEL_FROM_DATABASE=EOS 70D + +usb:v04A9p3255* + ID_MODEL_FROM_DATABASE=SELPHY CP900 + +usb:v04A9p3256* + ID_MODEL_FROM_DATABASE=SELPHY CP810 + +usb:v04A9p3258* + ID_MODEL_FROM_DATABASE=PowerShot G15 + +usb:v04A9p3259* + ID_MODEL_FROM_DATABASE=PowerShot SX50 HS + +usb:v04A9p325A* + ID_MODEL_FROM_DATABASE=PowerShot SX160 IS + +usb:v04A9p325B* + ID_MODEL_FROM_DATABASE=PowerShot S110 + +usb:v04A9p325C* + ID_MODEL_FROM_DATABASE=PowerShot SX500 IS + +usb:v04A9p325E* + ID_MODEL_FROM_DATABASE=PowerShot N + +usb:v04A9p325F* + ID_MODEL_FROM_DATABASE=PowerShot SX280 HS + +usb:v04A9p3260* + ID_MODEL_FROM_DATABASE=PowerShot SX270 HS + +usb:v04A9p3261* + ID_MODEL_FROM_DATABASE=PowerShot A3500 IS + +usb:v04A9p3262* + ID_MODEL_FROM_DATABASE=PowerShot A2600 + +usb:v04A9p3263* + ID_MODEL_FROM_DATABASE=PowerShot SX275 HS + +usb:v04A9p3264* + ID_MODEL_FROM_DATABASE=PowerShot A1400 + +usb:v04A9p3265* + ID_MODEL_FROM_DATABASE=Powershot ELPH 130 IS / IXUS 140 + +usb:v04A9p3266* + ID_MODEL_FROM_DATABASE=Powershot ELPH 120 IS / IXUS 135 + +usb:v04A9p3268* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 330 HS / IXUS 255 HS + +usb:v04A9p326F* + ID_MODEL_FROM_DATABASE=EOS 7D Mark II + +usb:v04A9p3270* + ID_MODEL_FROM_DATABASE=EOS 100D + +usb:v04A9p3271* + ID_MODEL_FROM_DATABASE=PowerShot A2500 + +usb:v04A9p3272* + ID_MODEL_FROM_DATABASE=EOS 700D + +usb:v04A9p3274* + ID_MODEL_FROM_DATABASE=PowerShot G16 + +usb:v04A9p3275* + ID_MODEL_FROM_DATABASE=PowerShot S120 + +usb:v04A9p3276* + ID_MODEL_FROM_DATABASE=PowerShot SX170 IS + +usb:v04A9p3277* + ID_MODEL_FROM_DATABASE=PowerShot SX510 HS + +usb:v04A9p3278* + ID_MODEL_FROM_DATABASE=PowerShot S200 + +usb:v04A9p327A* + ID_MODEL_FROM_DATABASE=SELPHY CP910 + +usb:v04A9p327B* + ID_MODEL_FROM_DATABASE=SELPHY CP820 + +usb:v04A9p327D* + ID_MODEL_FROM_DATABASE=Powershot ELPH 115 IS / IXUS 132 + +usb:v04A9p327F* + ID_MODEL_FROM_DATABASE=EOS Rebel T5 / EOS 1200D / EOS Kiss X70 + +usb:v04A9p3284* + ID_MODEL_FROM_DATABASE=PowerShot D30 + +usb:v04A9p3285* + ID_MODEL_FROM_DATABASE=PowerShot SX700 HS + +usb:v04A9p3286* + ID_MODEL_FROM_DATABASE=PowerShot SX600 HS + +usb:v04A9p3287* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 140 IS / IXUS 150 + +usb:v04A9p3288* + ID_MODEL_FROM_DATABASE=Powershot ELPH 135 / IXUS 145 + +usb:v04A9p3289* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 340 HS / IXUS 265 HS + +usb:v04A9p328A* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 150 IS / IXUS 155 + +usb:v04A9p328B* + ID_MODEL_FROM_DATABASE=PowerShot N Facebook(R) Ready + +usb:v04A9p3299* + ID_MODEL_FROM_DATABASE=EOS M3 + +usb:v04A9p329A* + ID_MODEL_FROM_DATABASE=PowerShot SX60 HS + +usb:v04A9p329B* + ID_MODEL_FROM_DATABASE=PowerShot SX520 HS + +usb:v04A9p329C* + ID_MODEL_FROM_DATABASE=PowerShot SX400 IS + +usb:v04A9p329D* + ID_MODEL_FROM_DATABASE=PowerShot G7 X + +usb:v04A9p329F* + ID_MODEL_FROM_DATABASE=PowerShot SX530 HS + +usb:v04A9p32A0* + ID_MODEL_FROM_DATABASE=EOS M10 + +usb:v04A9p32A6* + ID_MODEL_FROM_DATABASE=PowerShot SX710 HS + +usb:v04A9p32A7* + ID_MODEL_FROM_DATABASE=PowerShot SX610 HS + +usb:v04A9p32A8* + ID_MODEL_FROM_DATABASE=PowerShot G3 X + +usb:v04A9p32AA* + ID_MODEL_FROM_DATABASE=Powershot ELPH 160 / IXUS 160 + +usb:v04A9p32AB* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 350HS / IXUS 275 HS + +usb:v04A9p32AC* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 170 IS / IXUS 170 + +usb:v04A9p32AD* + ID_MODEL_FROM_DATABASE=PowerShot SX410 IS + +usb:v04A9p32B1* + ID_MODEL_FROM_DATABASE=SELPHY CP1200 + +usb:v04A9p32B2* + ID_MODEL_FROM_DATABASE=PowerShot G9 X + +usb:v04A9p32B3* + ID_MODEL_FROM_DATABASE=PowerShot G5 X + +usb:v04A9p32B4* + ID_MODEL_FROM_DATABASE=EOS Rebel T6 + +usb:v04A9p32BB* + ID_MODEL_FROM_DATABASE=EOS M5 + +usb:v04A9p32BF* + ID_MODEL_FROM_DATABASE=PowerShot SX420 IS + +usb:v04A9p32C1* + ID_MODEL_FROM_DATABASE=PowerShot ELPH 180 / IXUS 175 + +usb:v04A9p32C2* + ID_MODEL_FROM_DATABASE=PowerShot SX720 HS + +usb:v04A9p32C5* + ID_MODEL_FROM_DATABASE=EOS M6 + +usb:v04A9p32CC* + ID_MODEL_FROM_DATABASE=EOS 200D + +usb:v04A9p32D1* + ID_MODEL_FROM_DATABASE=EOS M100 + +usb:v04A9p32D2* + ID_MODEL_FROM_DATABASE=EOS M50 + +usb:v04A9p32D4* + ID_MODEL_FROM_DATABASE=Powershot ELPH 185 / IXUS 185 / IXY 200 + +usb:v04A9p32D5* + ID_MODEL_FROM_DATABASE=PowerShot SX430 IS + +usb:v04A9p32DB* + ID_MODEL_FROM_DATABASE=SELPHY CP1300 + +usb:v04AA* + ID_VENDOR_FROM_DATABASE=DaeWoo Telecom, Ltd + +usb:v04AB* + ID_VENDOR_FROM_DATABASE=Chromatic Research + +usb:v04AC* + ID_VENDOR_FROM_DATABASE=Micro Audiometrics Corp. + +usb:v04AD* + ID_VENDOR_FROM_DATABASE=Dooin Electronics + +usb:v04ADp2501* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v04AF* + ID_VENDOR_FROM_DATABASE=Winnov L.P. + +usb:v04B0* + ID_VENDOR_FROM_DATABASE=Nikon Corp. + +usb:v04B0p0102* + ID_MODEL_FROM_DATABASE=Coolpix 990 + +usb:v04B0p0103* + ID_MODEL_FROM_DATABASE=Coolpix 880 + +usb:v04B0p0104* + ID_MODEL_FROM_DATABASE=Coolpix 995 + +usb:v04B0p0106* + ID_MODEL_FROM_DATABASE=Coolpix 775 + +usb:v04B0p0107* + ID_MODEL_FROM_DATABASE=Coolpix 5000 + +usb:v04B0p0108* + ID_MODEL_FROM_DATABASE=Coolpix 2500 + +usb:v04B0p0109* + ID_MODEL_FROM_DATABASE=Coolpix 2500 (ptp) + +usb:v04B0p010A* + ID_MODEL_FROM_DATABASE=Coolpix 4500 + +usb:v04B0p010B* + ID_MODEL_FROM_DATABASE=Coolpix 4500 (ptp) + +usb:v04B0p010D* + ID_MODEL_FROM_DATABASE=Coolpix 5700 (ptp) + +usb:v04B0p010E* + ID_MODEL_FROM_DATABASE=Coolpix 4300 (storage) + +usb:v04B0p010F* + ID_MODEL_FROM_DATABASE=Coolpix 4300 (ptp) + +usb:v04B0p0110* + ID_MODEL_FROM_DATABASE=Coolpix 3500 (Sierra Mode) + +usb:v04B0p0111* + ID_MODEL_FROM_DATABASE=Coolpix 3500 (ptp) + +usb:v04B0p0112* + ID_MODEL_FROM_DATABASE=Coolpix 885 (ptp) + +usb:v04B0p0113* + ID_MODEL_FROM_DATABASE=Coolpix 5000 (ptp) + +usb:v04B0p0114* + ID_MODEL_FROM_DATABASE=Coolpix 3100 (storage) + +usb:v04B0p0115* + ID_MODEL_FROM_DATABASE=Coolpix 3100 (ptp) + +usb:v04B0p0117* + ID_MODEL_FROM_DATABASE=Coolpix 2100 (ptp) + +usb:v04B0p0119* + ID_MODEL_FROM_DATABASE=Coolpix 5400 (ptp) + +usb:v04B0p011D* + ID_MODEL_FROM_DATABASE=Coolpix 3700 (ptp) + +usb:v04B0p0121* + ID_MODEL_FROM_DATABASE=Coolpix 3200 (ptp) + +usb:v04B0p0122* + ID_MODEL_FROM_DATABASE=Coolpix 2200 (ptp) + +usb:v04B0p0124* + ID_MODEL_FROM_DATABASE=Coolpix 8400 (mass storage mode) + +usb:v04B0p0125* + ID_MODEL_FROM_DATABASE=Coolpix 8400 (ptp) + +usb:v04B0p0126* + ID_MODEL_FROM_DATABASE=Coolpix 8800 + +usb:v04B0p0129* + ID_MODEL_FROM_DATABASE=Coolpix 4800 (ptp) + +usb:v04B0p012C* + ID_MODEL_FROM_DATABASE=Coolpix 4100 (storage) + +usb:v04B0p012D* + ID_MODEL_FROM_DATABASE=Coolpix 4100 (ptp) + +usb:v04B0p012E* + ID_MODEL_FROM_DATABASE=Coolpix 5600 (ptp) + +usb:v04B0p0130* + ID_MODEL_FROM_DATABASE=Coolpix 4600 (ptp) + +usb:v04B0p0135* + ID_MODEL_FROM_DATABASE=Coolpix 5900 (ptp) + +usb:v04B0p0136* + ID_MODEL_FROM_DATABASE=Coolpix 7900 (storage) + +usb:v04B0p0137* + ID_MODEL_FROM_DATABASE=Coolpix 7900 (ptp) + +usb:v04B0p013A* + ID_MODEL_FROM_DATABASE=Coolpix 100 (storage) + +usb:v04B0p013B* + ID_MODEL_FROM_DATABASE=Coolpix 100 (ptp) + +usb:v04B0p0141* + ID_MODEL_FROM_DATABASE=Coolpix P2 (storage) + +usb:v04B0p0142* + ID_MODEL_FROM_DATABASE=Coolpix P2 (ptp) + +usb:v04B0p0163* + ID_MODEL_FROM_DATABASE=Coolpix P5100 (ptp) + +usb:v04B0p0169* + ID_MODEL_FROM_DATABASE=Coolpix P50 (ptp) + +usb:v04B0p0202* + ID_MODEL_FROM_DATABASE=Coolpix SQ (ptp) + +usb:v04B0p0203* + ID_MODEL_FROM_DATABASE=Coolpix 4200 (mass storage mode) + +usb:v04B0p0204* + ID_MODEL_FROM_DATABASE=Coolpix 4200 (ptp) + +usb:v04B0p0205* + ID_MODEL_FROM_DATABASE=Coolpix 5200 (storage) + +usb:v04B0p0206* + ID_MODEL_FROM_DATABASE=Coolpix 5200 (ptp) + +usb:v04B0p0301* + ID_MODEL_FROM_DATABASE=Coolpix 2000 (storage) + +usb:v04B0p0302* + ID_MODEL_FROM_DATABASE=Coolpix 2000 (ptp) + +usb:v04B0p0317* + ID_MODEL_FROM_DATABASE=Coolpix L20 (ptp) + +usb:v04B0p0402* + ID_MODEL_FROM_DATABASE=DSC D100 (ptp) + +usb:v04B0p0403* + ID_MODEL_FROM_DATABASE=D2H (mass storage mode) + +usb:v04B0p0404* + ID_MODEL_FROM_DATABASE=D2H SLR (ptp) + +usb:v04B0p0405* + ID_MODEL_FROM_DATABASE=D70 (mass storage mode) + +usb:v04B0p0406* + ID_MODEL_FROM_DATABASE=DSC D70 (ptp) + +usb:v04B0p0408* + ID_MODEL_FROM_DATABASE=D2X SLR (ptp) + +usb:v04B0p0409* + ID_MODEL_FROM_DATABASE=D50 digital camera + +usb:v04B0p040A* + ID_MODEL_FROM_DATABASE=D50 (ptp) + +usb:v04B0p040C* + ID_MODEL_FROM_DATABASE=D2Hs + +usb:v04B0p040E* + ID_MODEL_FROM_DATABASE=DSC D70s (ptp) + +usb:v04B0p040F* + ID_MODEL_FROM_DATABASE=D200 (mass storage mode) + +usb:v04B0p0410* + ID_MODEL_FROM_DATABASE=D200 (ptp) + +usb:v04B0p0413* + ID_MODEL_FROM_DATABASE=D40 (mass storage mode) + +usb:v04B0p041E* + ID_MODEL_FROM_DATABASE=D60 digital camera (mass storage mode) + +usb:v04B0p0422* + ID_MODEL_FROM_DATABASE=D700 (ptp) + +usb:v04B0p0423* + ID_MODEL_FROM_DATABASE=D5000 + +usb:v04B0p0424* + ID_MODEL_FROM_DATABASE=D3000 + +usb:v04B0p0425* + ID_MODEL_FROM_DATABASE=D300S + +usb:v04B0p0428* + ID_MODEL_FROM_DATABASE=D7000 + +usb:v04B0p0429* + ID_MODEL_FROM_DATABASE=D5100 + +usb:v04B0p042A* + ID_MODEL_FROM_DATABASE=D800 (ptp) + +usb:v04B0p0430* + ID_MODEL_FROM_DATABASE=D7100 + +usb:v04B0p043F* + ID_MODEL_FROM_DATABASE=D5600 + +usb:v04B0p0F03* + ID_MODEL_FROM_DATABASE=PD-10 Wireless Printer Adapter + +usb:v04B0p4000* + ID_MODEL_FROM_DATABASE=Coolscan LS 40 ED + +usb:v04B0p4001* + ID_MODEL_FROM_DATABASE=LS 50 ED/Coolscan V ED + +usb:v04B0p4002* + ID_MODEL_FROM_DATABASE=Super Coolscan LS-5000 ED + +usb:v04B1* + ID_VENDOR_FROM_DATABASE=Pan International + +usb:v04B3* + ID_VENDOR_FROM_DATABASE=IBM Corp. + +usb:v04B3p3003* + ID_MODEL_FROM_DATABASE=Rapid Access III Keyboard + +usb:v04B3p3004* + ID_MODEL_FROM_DATABASE=Media Access Pro Keyboard + +usb:v04B3p300A* + ID_MODEL_FROM_DATABASE=Rapid Access IIIe Keyboard + +usb:v04B3p3016* + ID_MODEL_FROM_DATABASE=UltraNav Keyboard Hub + +usb:v04B3p3018* + ID_MODEL_FROM_DATABASE=UltraNav Keyboard + +usb:v04B3p301A* + ID_MODEL_FROM_DATABASE=2-port low-power hub + +usb:v04B3p301B* + ID_MODEL_FROM_DATABASE=SK-8815 Keyboard + +usb:v04B3p301C* + ID_MODEL_FROM_DATABASE=Enhanced Performance Keyboard + +usb:v04B3p3020* + ID_MODEL_FROM_DATABASE=Enhanced Performance Keyboard + +usb:v04B3p3025* + ID_MODEL_FROM_DATABASE=NetVista Full Width Keyboard + +usb:v04B3p3100* + ID_MODEL_FROM_DATABASE=NetVista Mouse + +usb:v04B3p3103* + ID_MODEL_FROM_DATABASE=ScrollPoint Pro Mouse + +usb:v04B3p3104* + ID_MODEL_FROM_DATABASE=ScrollPoint Wireless Mouse + +usb:v04B3p3105* + ID_MODEL_FROM_DATABASE=ScrollPoint Optical (HID) + +usb:v04B3p3107* + ID_MODEL_FROM_DATABASE=ThinkPad 800dpi Optical Travel Mouse + +usb:v04B3p3108* + ID_MODEL_FROM_DATABASE=800dpi Optical Mouse w/ Scroll Point + +usb:v04B3p3109* + ID_MODEL_FROM_DATABASE=Optical ScrollPoint Pro Mouse + +usb:v04B3p310B* + ID_MODEL_FROM_DATABASE=Red Wheel Mouse + +usb:v04B3p310C* + ID_MODEL_FROM_DATABASE=Wheel Mouse + +usb:v04B3p4427* + ID_MODEL_FROM_DATABASE=Portable CD ROM + +usb:v04B3p4482* + ID_MODEL_FROM_DATABASE=Serial Converter + +usb:v04B3p4484* + ID_MODEL_FROM_DATABASE=SMSC USB20H04 3-Port Hub [ThinkPad X4 UltraBase, Wistron S Note-3 Media Slice] + +usb:v04B3p4485* + ID_MODEL_FROM_DATABASE=ThinkPad Dock Hub + +usb:v04B3p4524* + ID_MODEL_FROM_DATABASE=40 Character Vacuum Fluorescent Display + +usb:v04B3p4525* + ID_MODEL_FROM_DATABASE=Double sided CRT + +usb:v04B3p4535* + ID_MODEL_FROM_DATABASE=4610 Suremark Printer + +usb:v04B3p4550* + ID_MODEL_FROM_DATABASE=NVRAM (128 KB) + +usb:v04B3p4554* + ID_MODEL_FROM_DATABASE=Cash Drawer + +usb:v04B3p4580* + ID_MODEL_FROM_DATABASE=Hub w/ NVRAM + +usb:v04B3p4581* + ID_MODEL_FROM_DATABASE=4800-2xx Hub w/ Cash Drawer + +usb:v04B3p4604* + ID_MODEL_FROM_DATABASE=Keyboard w/ Card Reader + +usb:v04B3p4671* + ID_MODEL_FROM_DATABASE=4820 LCD w/ MSR/KB + +usb:v04B4* + ID_VENDOR_FROM_DATABASE=Cypress Semiconductor Corp. + +usb:v04B4p0001* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v04B4p0002* + ID_MODEL_FROM_DATABASE=CY7C63x0x Thermometer + +usb:v04B4p0033* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v04B4p0060* + ID_MODEL_FROM_DATABASE=Wireless optical mouse + +usb:v04B4p0100* + ID_MODEL_FROM_DATABASE=Cino FuzzyScan F760-B + +usb:v04B4p0101* + ID_MODEL_FROM_DATABASE=Keyboard/Hub + +usb:v04B4p0102* + ID_MODEL_FROM_DATABASE=Keyboard with APM + +usb:v04B4p0130* + ID_MODEL_FROM_DATABASE=MyIRC Remote Receiver + +usb:v04B4p0306* + ID_MODEL_FROM_DATABASE=Telephone Receiver + +usb:v04B4p0407* + ID_MODEL_FROM_DATABASE=Optical Skype Mouse + +usb:v04B4p0BAD* + ID_MODEL_FROM_DATABASE=MetaGeek Wi-Spy + +usb:v04B4p1002* + ID_MODEL_FROM_DATABASE=CY7C63001 R100 FM Radio + +usb:v04B4p1006* + ID_MODEL_FROM_DATABASE=Human Interface Device + +usb:v04B4p2050* + ID_MODEL_FROM_DATABASE=hub + +usb:v04B4p2830* + ID_MODEL_FROM_DATABASE=Opera1 DVB-S (cold state) + +usb:v04B4p3813* + ID_MODEL_FROM_DATABASE=NANO BIOS Programmer + +usb:v04B4p4235* + ID_MODEL_FROM_DATABASE=Monitor 02 Driver + +usb:v04B4p4381* + ID_MODEL_FROM_DATABASE=SCAPS USC-1 Scanner Controller + +usb:v04B4p4611* + ID_MODEL_FROM_DATABASE=Storage Adapter FX2 (CY) + +usb:v04B4p4616* + ID_MODEL_FROM_DATABASE=Flash Disk (TPP) + +usb:v04B4p4624* + ID_MODEL_FROM_DATABASE=DS-Xtreme Flash Card + +usb:v04B4p5201* + ID_MODEL_FROM_DATABASE=Combi Keyboard-Hub (Hub) + +usb:v04B4p5202* + ID_MODEL_FROM_DATABASE=Combi Keyboard-Hub (Keyboard) + +usb:v04B4p5500* + ID_MODEL_FROM_DATABASE=HID->COM RS232 Adapter + +usb:v04B4p5A9B* + ID_MODEL_FROM_DATABASE=Dacal CD/DVD Library D-101/DC-300/DC-016RW + +usb:v04B4p6370* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v04B4p6502* + ID_MODEL_FROM_DATABASE=CY4609 + +usb:v04B4p6506* + ID_MODEL_FROM_DATABASE=CY4603 + +usb:v04B4p650A* + ID_MODEL_FROM_DATABASE=CY4613 + +usb:v04B4p6560* + ID_MODEL_FROM_DATABASE=CY7C65640 USB-2.0 "TetraHub" + +usb:v04B4p6570* + ID_MODEL_FROM_DATABASE=Unprogrammed CY7C65632/34 hub HX2VL + +usb:v04B4p6572* + ID_MODEL_FROM_DATABASE=Unprogrammed CY7C65642 hub + +usb:v04B4p6830* + ID_MODEL_FROM_DATABASE=CY7C68300A EZ-USB AT2 USB 2.0 to ATA/ATAPI + +usb:v04B4p6831* + ID_MODEL_FROM_DATABASE=Storage Adapter ISD-300LP (CY) + +usb:v04B4p7417* + ID_MODEL_FROM_DATABASE=Wireless PC Lock/Ultra Mouse + +usb:v04B4p8329* + ID_MODEL_FROM_DATABASE=USB To keyboard/Mouse Converter + +usb:v04B4p8613* + ID_MODEL_FROM_DATABASE=CY7C68013 EZ-USB FX2 USB 2.0 Development Kit + +usb:v04B4p8614* + ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + +usb:v04B4p861F* + ID_MODEL_FROM_DATABASE=Anysee E30 USB 2.0 DVB-T Receiver + +usb:v04B4pBCA1* + ID_MODEL_FROM_DATABASE=Barcode Reader + +usb:v04B4pCC04* + ID_MODEL_FROM_DATABASE=Centor USB RACIA-ALVAR USB PORT + +usb:v04B4pCC06* + ID_MODEL_FROM_DATABASE=Centor-P RACIA-ALVAR USB PORT + +usb:v04B4pD5D5* + ID_MODEL_FROM_DATABASE=CY7C63x0x Zoltrix Z-Boxer GamePad + +usb:v04B4pDE61* + ID_MODEL_FROM_DATABASE=Barcode Reader + +usb:v04B4pDE64* + ID_MODEL_FROM_DATABASE=Barcode Reader + +usb:v04B4pF000* + ID_MODEL_FROM_DATABASE=CY30700 Licorice evaluation board + +usb:v04B4pF111* + ID_MODEL_FROM_DATABASE=CY8CKIT-002 PSoC MiniProg3 Rev A Program and debug kit + +usb:v04B4pF115* + ID_MODEL_FROM_DATABASE=PSoC FirstTouch Programmer + +usb:v04B4pF231* + ID_MODEL_FROM_DATABASE=DELLY Changer 4in1 universal IR remote + +usb:v04B4pF232* + ID_MODEL_FROM_DATABASE=Mono embedded computer + +usb:v04B4pFD13* + ID_MODEL_FROM_DATABASE=Programmable power socket + +usb:v04B5* + ID_VENDOR_FROM_DATABASE=ROHM LSI Systems USA, LLC + +usb:v04B5p3064* + ID_MODEL_FROM_DATABASE=Hantek DSO-3064 + +usb:v04B6* + ID_VENDOR_FROM_DATABASE=Hint Corp. + +usb:v04B7* + ID_VENDOR_FROM_DATABASE=Compal Electronics, Inc. + +usb:v04B8* + ID_VENDOR_FROM_DATABASE=Seiko Epson Corp. + +usb:v04B8p0001* + ID_MODEL_FROM_DATABASE=Stylus Color 740 / Photo 750 + +usb:v04B8p0002* + ID_MODEL_FROM_DATABASE=ISD Smart Cable for Mac + +usb:v04B8p0003* + ID_MODEL_FROM_DATABASE=ISD Smart Cable + +usb:v04B8p0004* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04B8p0005* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04B8p0006* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04B8p0007* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04B8p0015* + ID_MODEL_FROM_DATABASE=Stylus Photo R3000 + +usb:v04B8p0101* + ID_MODEL_FROM_DATABASE=GT-7000U [Perfection 636] + +usb:v04B8p0102* + ID_MODEL_FROM_DATABASE=GT-2200 + +usb:v04B8p0103* + ID_MODEL_FROM_DATABASE=GT-6600U [Perfection 610] + +usb:v04B8p0104* + ID_MODEL_FROM_DATABASE=GT-7600UF [Perfection 1200U/1200U Photo] + +usb:v04B8p0105* + ID_MODEL_FROM_DATABASE=Stylus Scan 2000 + +usb:v04B8p0106* + ID_MODEL_FROM_DATABASE=Stylus Scan 2500 + +usb:v04B8p0107* + ID_MODEL_FROM_DATABASE=ES-2000 [Expression 1600U] + +usb:v04B8p0108* + ID_MODEL_FROM_DATABASE=CC-700 + +usb:v04B8p0109* + ID_MODEL_FROM_DATABASE=ES-8500 [Expression 1640 XL] + +usb:v04B8p010A* + ID_MODEL_FROM_DATABASE=GT-8700/GT-8700F [Perfection 1640SU/1640SU PHOTO] + +usb:v04B8p010B* + ID_MODEL_FROM_DATABASE=GT-7700U [Perfection 1240U] + +usb:v04B8p010C* + ID_MODEL_FROM_DATABASE=GT-6700U [Perfection 640] + +usb:v04B8p010D* + ID_MODEL_FROM_DATABASE=CC-500L + +usb:v04B8p010E* + ID_MODEL_FROM_DATABASE=ES-2200 [Perfection 1680] + +usb:v04B8p010F* + ID_MODEL_FROM_DATABASE=GT-7200U [Perfection 1250/1250 PHOTO] + +usb:v04B8p0110* + ID_MODEL_FROM_DATABASE=GT-8200U/GT-8200UF [Perfection 1650/1650 PHOTO] + +usb:v04B8p0112* + ID_MODEL_FROM_DATABASE=GT-9700F [Perfection 2450 PHOTO] + +usb:v04B8p0114* + ID_MODEL_FROM_DATABASE=Perfection 660 + +usb:v04B8p0116* + ID_MODEL_FROM_DATABASE=GT-9400UF [Perfection 3170] + +usb:v04B8p0118* + ID_MODEL_FROM_DATABASE=GT-F600 [Perfection 4180] + +usb:v04B8p0119* + ID_MODEL_FROM_DATABASE=GT-X750 [Perfection 4490 Photo] + +usb:v04B8p011A* + ID_MODEL_FROM_DATABASE=CC-550L [1000 ICS] + +usb:v04B8p011B* + ID_MODEL_FROM_DATABASE=GT-9300UF [Perfection 2400 PHOTO] + +usb:v04B8p011C* + ID_MODEL_FROM_DATABASE=GT-9800F [Perfection 3200] + +usb:v04B8p011D* + ID_MODEL_FROM_DATABASE=GT-7300U [Perfection 1260/1260 PHOTO] + +usb:v04B8p011E* + ID_MODEL_FROM_DATABASE=GT-8300UF [Perfection 1660 PHOTO] + +usb:v04B8p011F* + ID_MODEL_FROM_DATABASE=GT-8400UF [Perfection 1670/1670 PHOTO] + +usb:v04B8p0120* + ID_MODEL_FROM_DATABASE=GT-7400U [Perfection 1270] + +usb:v04B8p0121* + ID_MODEL_FROM_DATABASE=GT-F500/GT-F550 [Perfection 2480/2580 PHOTO] + +usb:v04B8p0122* + ID_MODEL_FROM_DATABASE=GT-F520/GT-F570 [Perfection 3590 PHOTO] + +usb:v04B8p0126* + ID_MODEL_FROM_DATABASE=ES-7000H [GT-15000] + +usb:v04B8p0128* + ID_MODEL_FROM_DATABASE=GT-X700 [Perfection 4870] + +usb:v04B8p0129* + ID_MODEL_FROM_DATABASE=ES-10000G [Expression 10000XL] + +usb:v04B8p012A* + ID_MODEL_FROM_DATABASE=GT-X800 [Perfection 4990 PHOTO] + +usb:v04B8p012B* + ID_MODEL_FROM_DATABASE=ES-H300 [GT-2500] + +usb:v04B8p012C* + ID_MODEL_FROM_DATABASE=GT-X900 [Perfection V700/V750 Photo] + +usb:v04B8p012D* + ID_MODEL_FROM_DATABASE=GT-F650 [GT-S600/Perfection V10/V100] + +usb:v04B8p012E* + ID_MODEL_FROM_DATABASE=GT-F670 [Perfection V200 Photo] + +usb:v04B8p012F* + ID_MODEL_FROM_DATABASE=GT-F700 [Perfection V350] + +usb:v04B8p0130* + ID_MODEL_FROM_DATABASE=GT-X770 [Perfection V500] + +usb:v04B8p0131* + ID_MODEL_FROM_DATABASE=GT-F720 [GT-S620/Perfection V30/V300 Photo] + +usb:v04B8p0133* + ID_MODEL_FROM_DATABASE=GT-1500 [GT-D1000] + +usb:v04B8p0135* + ID_MODEL_FROM_DATABASE=GT-X970 + +usb:v04B8p0136* + ID_MODEL_FROM_DATABASE=ES-D400 [GT-S80] + +usb:v04B8p0137* + ID_MODEL_FROM_DATABASE=ES-D200 [GT-S50] + +usb:v04B8p0138* + ID_MODEL_FROM_DATABASE=ES-H7200 [GT-20000] + +usb:v04B8p013A* + ID_MODEL_FROM_DATABASE=GT-X820 [Perfection V600 Photo] + +usb:v04B8p0142* + ID_MODEL_FROM_DATABASE=GT-F730 [GT-S630/Perfection V33/V330 Photo] + +usb:v04B8p0143* + ID_MODEL_FROM_DATABASE=GT-S55 + +usb:v04B8p0144* + ID_MODEL_FROM_DATABASE=GT-S85 + +usb:v04B8p0151* + ID_MODEL_FROM_DATABASE=Perfection V800 Photo + +usb:v04B8p0202* + ID_MODEL_FROM_DATABASE=Receipt Printer M129C/TM-T70 + +usb:v04B8p0401* + ID_MODEL_FROM_DATABASE=CP 800 Digital Camera + +usb:v04B8p0402* + ID_MODEL_FROM_DATABASE=PhotoPC 850z + +usb:v04B8p0403* + ID_MODEL_FROM_DATABASE=PhotoPC 3000z + +usb:v04B8p0509* + ID_MODEL_FROM_DATABASE=JVC PIX-MC10 + +usb:v04B8p0601* + ID_MODEL_FROM_DATABASE=Stylus Photo 875DC Card Reader + +usb:v04B8p0602* + ID_MODEL_FROM_DATABASE=Stylus Photo 895 Card Reader + +usb:v04B8p0801* + ID_MODEL_FROM_DATABASE=CC-600PX [Stylus CX5200/CX5400/CX6600] + +usb:v04B8p0802* + ID_MODEL_FROM_DATABASE=CC-570L [Stylus CX3100/CX3200] + +usb:v04B8p0803* + ID_MODEL_FROM_DATABASE=Printer (Composite Device) + +usb:v04B8p0804* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v04B8p0805* + ID_MODEL_FROM_DATABASE=Stylus CX6300/CX6400 + +usb:v04B8p0806* + ID_MODEL_FROM_DATABASE=PM-A850 [Stylus Photo RX600/610] + +usb:v04B8p0807* + ID_MODEL_FROM_DATABASE=Stylus Photo RX500/510 + +usb:v04B8p0808* + ID_MODEL_FROM_DATABASE=Stylus CX5200/CX5300/CX5400 + +usb:v04B8p0809* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v04B8p080A* + ID_MODEL_FROM_DATABASE=F-3200 + +usb:v04B8p080C* + ID_MODEL_FROM_DATABASE=ME100 [Stylus CX1500] + +usb:v04B8p080D* + ID_MODEL_FROM_DATABASE=Stylus CX4500/4600 + +usb:v04B8p080E* + ID_MODEL_FROM_DATABASE=PX-A550 [CX-3500/3600/3650 MFP] + +usb:v04B8p080F* + ID_MODEL_FROM_DATABASE=Stylus Photo RX420/RX425/RX430 + +usb:v04B8p0810* + ID_MODEL_FROM_DATABASE=PM-A900 [Stylus Photo RX700] + +usb:v04B8p0811* + ID_MODEL_FROM_DATABASE=PM-A870 [Stylus Photo RX620/RX630] + +usb:v04B8p0812* + ID_MODEL_FROM_DATABASE=MFP Composite Device + +usb:v04B8p0813* + ID_MODEL_FROM_DATABASE=Stylus CX6500/6600 + +usb:v04B8p0814* + ID_MODEL_FROM_DATABASE=PM-A700 + +usb:v04B8p0815* + ID_MODEL_FROM_DATABASE=LP-A500 [AcuLaser CX1] + +usb:v04B8p0816* + ID_MODEL_FROM_DATABASE=Printer (Composite Device) + +usb:v04B8p0817* + ID_MODEL_FROM_DATABASE=LP-M5500/LP-M5500F + +usb:v04B8p0818* + ID_MODEL_FROM_DATABASE=Stylus CX3700/CX3800/DX3800 + +usb:v04B8p0819* + ID_MODEL_FROM_DATABASE=PX-A650 [Stylus CX4700/CX4800/DX4800/DX4850] + +usb:v04B8p081A* + ID_MODEL_FROM_DATABASE=PM-A750 [Stylus Photo RX520/RX530] + +usb:v04B8p081B* + ID_MODEL_FROM_DATABASE=MFP Composite Device + +usb:v04B8p081C* + ID_MODEL_FROM_DATABASE=PM-A890 [Stylus Photo RX640/RX650] + +usb:v04B8p081D* + ID_MODEL_FROM_DATABASE=PM-A950 + +usb:v04B8p081E* + ID_MODEL_FROM_DATABASE=MFP Composite Device + +usb:v04B8p081F* + ID_MODEL_FROM_DATABASE=Stylus CX7700/7800 + +usb:v04B8p0820* + ID_MODEL_FROM_DATABASE=Stylus CX4100/CX4200/DX4200 + +usb:v04B8p0821* + ID_MODEL_FROM_DATABASE=Stylus CX5700F/CX5800F + +usb:v04B8p0822* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v04B8p0823* + ID_MODEL_FROM_DATABASE=MFP Composite Device + +usb:v04B8p0824* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v04B8p0825* + ID_MODEL_FROM_DATABASE=MFP Composite Device + +usb:v04B8p0826* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v04B8p0827* + ID_MODEL_FROM_DATABASE=PM-A820 [Stylus Photo RX560/RX580/RX585/RX590] + +usb:v04B8p0828* + ID_MODEL_FROM_DATABASE=PM-A970 + +usb:v04B8p0829* + ID_MODEL_FROM_DATABASE=PM-T990 + +usb:v04B8p082A* + ID_MODEL_FROM_DATABASE=PM-A920 + +usb:v04B8p082B* + ID_MODEL_FROM_DATABASE=Stylus CX5900/CX5000/DX5000/DX5050 + +usb:v04B8p082C* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v04B8p082D* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v04B8p082E* + ID_MODEL_FROM_DATABASE=PX-A720 [Stylus CX5900/CX6000/DX6000] + +usb:v04B8p082F* + ID_MODEL_FROM_DATABASE=PX-A620 [Stylus CX3900/DX4000/DX4050] + +usb:v04B8p0830* + ID_MODEL_FROM_DATABASE=ME 200 [Stylus CX2800/CX2900] + +usb:v04B8p0831* + ID_MODEL_FROM_DATABASE=Stylus CX6900F/CX7000F/DX7000F + +usb:v04B8p0832* + ID_MODEL_FROM_DATABASE=MFP Composite Device + +usb:v04B8p0833* + ID_MODEL_FROM_DATABASE=LP-M5600 + +usb:v04B8p0834* + ID_MODEL_FROM_DATABASE=LP-M6000 + +usb:v04B8p0835* + ID_MODEL_FROM_DATABASE=AcuLaser CX21 + +usb:v04B8p0836* + ID_MODEL_FROM_DATABASE=PM-T960 + +usb:v04B8p0837* + ID_MODEL_FROM_DATABASE=PM-A940 [Stylus Photo RX680/RX685/RX690] + +usb:v04B8p0838* + ID_MODEL_FROM_DATABASE=PX-A640 [CX7300/CX7400/DX7400] + +usb:v04B8p0839* + ID_MODEL_FROM_DATABASE=PX-A740 [CX8300/CX8400/DX8400] + +usb:v04B8p083A* + ID_MODEL_FROM_DATABASE=PX-FA700 [CX9300F/CX9400Fax/DX9400F] + +usb:v04B8p083B* + ID_MODEL_FROM_DATABASE=MFP Composite Device + +usb:v04B8p083C* + ID_MODEL_FROM_DATABASE=PM-A840S [Stylus Photo RX595/RX610] + +usb:v04B8p083D* + ID_MODEL_FROM_DATABASE=MFP Composite Device + +usb:v04B8p083E* + ID_MODEL_FROM_DATABASE=MFP Composite Device + +usb:v04B8p083F* + ID_MODEL_FROM_DATABASE=Stylus CX4300/CX4400/CX5500/CX5600/DX4400/DX4450 + +usb:v04B8p0841* + ID_MODEL_FROM_DATABASE=PX-401A [ME 300/Stylus NX100] + +usb:v04B8p0843* + ID_MODEL_FROM_DATABASE=LP-M5000 + +usb:v04B8p0844* + ID_MODEL_FROM_DATABASE=EP-901A/EP-901F [Artisan 800/Stylus Photo PX800FW] + +usb:v04B8p0846* + ID_MODEL_FROM_DATABASE=EP-801A [Artisan 700/Stylus Photo PX700W/TX700W] + +usb:v04B8p0847* + ID_MODEL_FROM_DATABASE=PX-601F [ME Office 700FW/Stylus Office BX600FW/TX600FW] + +usb:v04B8p0848* + ID_MODEL_FROM_DATABASE=ME Office 600F/Stylus Office BX300F/TX300F + +usb:v04B8p0849* + ID_MODEL_FROM_DATABASE=Stylus SX205 + +usb:v04B8p084A* + ID_MODEL_FROM_DATABASE=PX-501A [Stylus NX400] + +usb:v04B8p084D* + ID_MODEL_FROM_DATABASE=PX-402A [Stylus SX115/Stylus NX110 Series] + +usb:v04B8p084F* + ID_MODEL_FROM_DATABASE=ME OFFICE 510 + +usb:v04B8p0850* + ID_MODEL_FROM_DATABASE=EP-702A [Stylus Photo PX650/TX650 Series] + +usb:v04B8p0851* + ID_MODEL_FROM_DATABASE=Stylus SX410 + +usb:v04B8p0852* + ID_MODEL_FROM_DATABASE=EP-802A [Artisan 710 Series/Stylus Photo PX710W/TX720W Series] + +usb:v04B8p0853* + ID_MODEL_FROM_DATABASE=EP-902A [Artisan 810 Series/Stylus Photo PX810FW Series] + +usb:v04B8p0854* + ID_MODEL_FROM_DATABASE=ME OFFICE 650FN Series/Stylus Office BX310FN/TX520FN Series + +usb:v04B8p0855* + ID_MODEL_FROM_DATABASE=PX-602F [Stylus Office BX610FW/TX620FW Series] + +usb:v04B8p0856* + ID_MODEL_FROM_DATABASE=PX-502A [Stylus SX515W] + +usb:v04B8p085C* + ID_MODEL_FROM_DATABASE=ME 320/330 Series [Stylus SX125] + +usb:v04B8p085D* + ID_MODEL_FROM_DATABASE=PX-603F [ME OFFICE 960FWD Series/Stylus Office BX625FWD/TX620FWD Series] + +usb:v04B8p085E* + ID_MODEL_FROM_DATABASE=PX-503A [ME OFFICE 900WD Series/Stylus Office BX525WD] + +usb:v04B8p085F* + ID_MODEL_FROM_DATABASE=Stylus Office BX320FW/TX525FW Series + +usb:v04B8p0860* + ID_MODEL_FROM_DATABASE=EP-903A/EP-903F [Artisan 835/Stylus Photo PX820FWD Series] + +usb:v04B8p0861* + ID_MODEL_FROM_DATABASE=EP-803A/EP-803AW [Artisan 725/Stylus Photo PX720WD/TX720WD Series] + +usb:v04B8p0862* + ID_MODEL_FROM_DATABASE=EP-703A [Stylus Photo PX660 Series] + +usb:v04B8p0863* + ID_MODEL_FROM_DATABASE=ME OFFICE 620F Series/Stylus Office BX305F/BX305FW/TX320F + +usb:v04B8p0864* + ID_MODEL_FROM_DATABASE=ME OFFICE 560W Series + +usb:v04B8p0865* + ID_MODEL_FROM_DATABASE=ME OFFICE 520 Series + +usb:v04B8p0866* + ID_MODEL_FROM_DATABASE=AcuLaser MX20DN/MX20DNF/MX21DNF + +usb:v04B8p0869* + ID_MODEL_FROM_DATABASE=PX-1600F + +usb:v04B8p086A* + ID_MODEL_FROM_DATABASE=PX-673F [Stylus Office BX925FWD] + +usb:v04B8p0870* + ID_MODEL_FROM_DATABASE=Stylus Office BX305FW Plus + +usb:v04B8p0871* + ID_MODEL_FROM_DATABASE=K200 Series + +usb:v04B8p0872* + ID_MODEL_FROM_DATABASE=K300 Series + +usb:v04B8p0873* + ID_MODEL_FROM_DATABASE=L200 Series + +usb:v04B8p0878* + ID_MODEL_FROM_DATABASE=EP-704A + +usb:v04B8p0879* + ID_MODEL_FROM_DATABASE=EP-904A/EP-904F [Artisan 837/Stylus Photo PX830FWD Series] + +usb:v04B8p087B* + ID_MODEL_FROM_DATABASE=EP-804A/EP-804AR/EP-804AW [Stylus Photo PX730WD/Artisan 730 Series] + +usb:v04B8p087C* + ID_MODEL_FROM_DATABASE=PX-1700F + +usb:v04B8p087D* + ID_MODEL_FROM_DATABASE=PX-B750F/WP-4525 Series + +usb:v04B8p087F* + ID_MODEL_FROM_DATABASE=PX-403A + +usb:v04B8p0880* + ID_MODEL_FROM_DATABASE=PX-434A [Stylus NX330 Series] + +usb:v04B8p0881* + ID_MODEL_FROM_DATABASE=PX-404A [ME OFFICE 535] + +usb:v04B8p0883* + ID_MODEL_FROM_DATABASE=ME 340 Series/Stylus NX130 Series + +usb:v04B8p0884* + ID_MODEL_FROM_DATABASE=Stylus NX430W Series + +usb:v04B8p0885* + ID_MODEL_FROM_DATABASE=Stylus NX230/SX235W Series + +usb:v04B8p088F* + ID_MODEL_FROM_DATABASE=Stylus Office BX635FWD + +usb:v04B8p0890* + ID_MODEL_FROM_DATABASE=ME OFFICE 940FW Series/Stylus Office BX630FW Series + +usb:v04B8p0891* + ID_MODEL_FROM_DATABASE=Stylus Office BX535WD + +usb:v04B8p0892* + ID_MODEL_FROM_DATABASE=Stylus Office BX935FWD + +usb:v04B8p0893* + ID_MODEL_FROM_DATABASE=EP-774A + +usb:v04B8p1114* + ID_MODEL_FROM_DATABASE=XP-440 [Expression Home Small-in-One Printer] + +usb:v04B8p1129* + ID_MODEL_FROM_DATABASE=ET-4750 [WorkForce ET-4750 EcoTank All-in-One] + +usb:v04B9* + ID_VENDOR_FROM_DATABASE=Rainbow Technologies, Inc. + +usb:v04B9p0300* + ID_MODEL_FROM_DATABASE=SafeNet USB SuperPro/UltraPro + +usb:v04B9p1000* + ID_MODEL_FROM_DATABASE=iKey 1000 Token + +usb:v04B9p1001* + ID_MODEL_FROM_DATABASE=iKey 1200 Token + +usb:v04B9p1002* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1003* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1004* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1005* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1006* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1200* + ID_MODEL_FROM_DATABASE=iKey 2000 Token + +usb:v04B9p1201* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1202* + ID_MODEL_FROM_DATABASE=iKey 2032 Token + +usb:v04B9p1203* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1204* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1205* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1206* + ID_MODEL_FROM_DATABASE=iKey 4000 Token + +usb:v04B9p1300* + ID_MODEL_FROM_DATABASE=iKey 3000 Token + +usb:v04B9p1301* + ID_MODEL_FROM_DATABASE=iKey 3000 + +usb:v04B9p1302* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1303* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1304* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1305* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p1306* + ID_MODEL_FROM_DATABASE=iKey Token + +usb:v04B9p8000* + ID_MODEL_FROM_DATABASE=SafeNet Sentinel Hardware Key + +usb:v04BA* + ID_VENDOR_FROM_DATABASE=Toucan Systems, Ltd + +usb:v04BB* + ID_VENDOR_FROM_DATABASE=I-O Data Device, Inc. + +usb:v04BBp0101* + ID_MODEL_FROM_DATABASE=USB2-IDE/ATAPI Bridge Adapter + +usb:v04BBp0201* + ID_MODEL_FROM_DATABASE=USB2-IDE/ATAPI Bridge Adapter + +usb:v04BBp0204* + ID_MODEL_FROM_DATABASE=DVD Multi-plus unit iU-CD2 + +usb:v04BBp0206* + ID_MODEL_FROM_DATABASE=DVD Multi-plus unit DVR-UEH8 + +usb:v04BBp0301* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v04BBp0314* + ID_MODEL_FROM_DATABASE=USB-SSMRW SD-card + +usb:v04BBp0319* + ID_MODEL_FROM_DATABASE=USB2-IDE/ATAPI Bridge Adapter + +usb:v04BBp031A* + ID_MODEL_FROM_DATABASE=USB2-IDE/ATAPI Bridge Adapter + +usb:v04BBp031B* + ID_MODEL_FROM_DATABASE=USB2-IDE/ATAPI Bridge Adapter + +usb:v04BBp031E* + ID_MODEL_FROM_DATABASE=USB-SDRW SD-card + +usb:v04BBp0502* + ID_MODEL_FROM_DATABASE=Nogatech Live! (BT) + +usb:v04BBp0528* + ID_MODEL_FROM_DATABASE=GV-USB Video Capture + +usb:v04BBp0901* + ID_MODEL_FROM_DATABASE=USB ETT + +usb:v04BBp0904* + ID_MODEL_FROM_DATABASE=ET/TX Ethernet [pegasus] + +usb:v04BBp0913* + ID_MODEL_FROM_DATABASE=ET/TX-S Ethernet [pegasus2] + +usb:v04BBp0919* + ID_MODEL_FROM_DATABASE=USB WN-B11 + +usb:v04BBp0922* + ID_MODEL_FROM_DATABASE=IOData AirPort WN-B11/USBS 802.11b + +usb:v04BBp0930* + ID_MODEL_FROM_DATABASE=ETG-US2 + +usb:v04BBp0937* + ID_MODEL_FROM_DATABASE=WN-WAG/USL Wireless LAN Adapter + +usb:v04BBp0938* + ID_MODEL_FROM_DATABASE=WN-G54/USL Wireless LAN Adapter + +usb:v04BBp093B* + ID_MODEL_FROM_DATABASE=WN-GDN/USB + +usb:v04BBp093F* + ID_MODEL_FROM_DATABASE=WNGDNUS2 802.11n + +usb:v04BBp0944* + ID_MODEL_FROM_DATABASE=WHG-AGDN/US Wireless LAN Adapter + +usb:v04BBp0945* + ID_MODEL_FROM_DATABASE=WN-GDN/US3 Wireless LAN Adapter + +usb:v04BBp0947* + ID_MODEL_FROM_DATABASE=WN-G150U Wireless LAN Adapter + +usb:v04BBp0948* + ID_MODEL_FROM_DATABASE=WN-G300U Wireless LAN Adapter + +usb:v04BBp0A03* + ID_MODEL_FROM_DATABASE=Serial USB-RSAQ1 + +usb:v04BBp0A07* + ID_MODEL_FROM_DATABASE=USB2-iCN Adapter + +usb:v04BBp0A08* + ID_MODEL_FROM_DATABASE=USB2-iCN Adapter + +usb:v04BBp0C01* + ID_MODEL_FROM_DATABASE=FM-10 Pro Disk + +usb:v04BD* + ID_VENDOR_FROM_DATABASE=Toshiba Electronics Taiwan Corp. + +usb:v04BE* + ID_VENDOR_FROM_DATABASE=Telia Research AB + +usb:v04BF* + ID_VENDOR_FROM_DATABASE=TDK Corp. + +usb:v04BFp0100* + ID_MODEL_FROM_DATABASE=MediaReader CF + +usb:v04BFp0115* + ID_MODEL_FROM_DATABASE=USB-PDC Adapter UPA9664 + +usb:v04BFp0116* + ID_MODEL_FROM_DATABASE=USB-cdmaOne Adapter UCA1464 + +usb:v04BFp0117* + ID_MODEL_FROM_DATABASE=USB-PHS Adapter UHA6400 + +usb:v04BFp0118* + ID_MODEL_FROM_DATABASE=USB-PHS Adapter UPA6400 + +usb:v04BFp0135* + ID_MODEL_FROM_DATABASE=MediaReader Dual + +usb:v04BFp0202* + ID_MODEL_FROM_DATABASE=73S1121F Smart Card Reader- + +usb:v04BFp0309* + ID_MODEL_FROM_DATABASE=Bluetooth USB dongle + +usb:v04BFp030A* + ID_MODEL_FROM_DATABASE=IBM Bluetooth Ultraport Module + +usb:v04BFp030B* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v04BFp030C* + ID_MODEL_FROM_DATABASE=Ultraport Bluetooth Device + +usb:v04BFp0310* + ID_MODEL_FROM_DATABASE=Integrated Bluetooth + +usb:v04BFp0311* + ID_MODEL_FROM_DATABASE=Integrated Bluetooth Device + +usb:v04BFp0317* + ID_MODEL_FROM_DATABASE=Bluetooth UltraPort Module from IBM + +usb:v04BFp0318* + ID_MODEL_FROM_DATABASE=IBM Integrated Bluetooth + +usb:v04BFp0319* + ID_MODEL_FROM_DATABASE=Bluetooth Adapter + +usb:v04BFp0320* + ID_MODEL_FROM_DATABASE=Bluetooth Adapter + +usb:v04BFp0321* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v04BFp0A28* + ID_MODEL_FROM_DATABASE=INDI AV-IN Device + +usb:v04C1* + ID_VENDOR_FROM_DATABASE=U.S. Robotics (3Com) + +usb:v04C1p0020* + ID_MODEL_FROM_DATABASE=56K Voice Pro + +usb:v04C1p0022* + ID_MODEL_FROM_DATABASE=56K Voice Pro + +usb:v04C1p007E* + ID_MODEL_FROM_DATABASE=ISDN TA + +usb:v04C1p0082* + ID_MODEL_FROM_DATABASE=OfficeConnect Analog Modem + +usb:v04C1p008F* + ID_MODEL_FROM_DATABASE=Pro ISDN TA + +usb:v04C1p0097* + ID_MODEL_FROM_DATABASE=OfficeConnect Analog + +usb:v04C1p009D* + ID_MODEL_FROM_DATABASE=HomeConnect Webcam [vicam] + +usb:v04C1p00A9* + ID_MODEL_FROM_DATABASE=ISDN Pro TA-U + +usb:v04C1p00B9* + ID_MODEL_FROM_DATABASE=HomeConnect IDSL Modem + +usb:v04C1p3021* + ID_MODEL_FROM_DATABASE=56k Voice FaxModem Pro + +usb:v04C2* + ID_VENDOR_FROM_DATABASE=Methode Electronics Far East PTE, Ltd + +usb:v04C3* + ID_VENDOR_FROM_DATABASE=Maxi Switch, Inc. + +usb:v04C3p1102* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v04C3p2102* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v04C4* + ID_VENDOR_FROM_DATABASE=Lockheed Martin Energy Research + +usb:v04C5* + ID_VENDOR_FROM_DATABASE=Fujitsu, Ltd + +usb:v04C5p1029* + ID_MODEL_FROM_DATABASE=fi-4010c Scanner + +usb:v04C5p1033* + ID_MODEL_FROM_DATABASE=fi-4110CU + +usb:v04C5p1041* + ID_MODEL_FROM_DATABASE=fi-4120c Scanner + +usb:v04C5p1042* + ID_MODEL_FROM_DATABASE=fi-4220c Scanner + +usb:v04C5p105B* + ID_MODEL_FROM_DATABASE=AH-F401U Air H device + +usb:v04C5p1084* + ID_MODEL_FROM_DATABASE=PalmSecure Sensor V2 + +usb:v04C5p1096* + ID_MODEL_FROM_DATABASE=fi-5110EOX + +usb:v04C5p1097* + ID_MODEL_FROM_DATABASE=fi-5110C + +usb:v04C5p10AE* + ID_MODEL_FROM_DATABASE=fi-4120C2 + +usb:v04C5p10AF* + ID_MODEL_FROM_DATABASE=fi-4220C2 + +usb:v04C5p10C7* + ID_MODEL_FROM_DATABASE=fi-60f scanner + +usb:v04C5p10E0* + ID_MODEL_FROM_DATABASE=fi-5120c Scanner + +usb:v04C5p10E1* + ID_MODEL_FROM_DATABASE=fi-5220C + +usb:v04C5p10E7* + ID_MODEL_FROM_DATABASE=fi-5900C + +usb:v04C5p10FE* + ID_MODEL_FROM_DATABASE=S500 + +usb:v04C5p1104* + ID_MODEL_FROM_DATABASE=KD02906 Line Thermal Printer + +usb:v04C5p114F* + ID_MODEL_FROM_DATABASE=fi-6130 + +usb:v04C5p1150* + ID_MODEL_FROM_DATABASE=fi-6230 + +usb:v04C5p11F3* + ID_MODEL_FROM_DATABASE=fi-6130Z + +usb:v04C5p125A* + ID_MODEL_FROM_DATABASE=PalmSecure Sensor Device - MP + +usb:v04C5p132E* + ID_MODEL_FROM_DATABASE=fi-7160 + +usb:v04C5p200F* + ID_MODEL_FROM_DATABASE=Sigma DP2 (Mass Storage) + +usb:v04C5p2010* + ID_MODEL_FROM_DATABASE=Sigma DP2 (PictBridge) + +usb:v04C5p201D* + ID_MODEL_FROM_DATABASE=SATA 3.0 6Gbit/s Adaptor [GROOVY] + +usb:v04C6* + ID_VENDOR_FROM_DATABASE=Toshiba America Electronic Components + +usb:v04C7* + ID_VENDOR_FROM_DATABASE=Micro Macro Technologies + +usb:v04C8* + ID_VENDOR_FROM_DATABASE=Konica Corp. + +usb:v04C8p0720* + ID_MODEL_FROM_DATABASE=Digital Color Camera + +usb:v04C8p0721* + ID_MODEL_FROM_DATABASE=e-miniD Camera + +usb:v04C8p0722* + ID_MODEL_FROM_DATABASE=e-mini + +usb:v04C8p0723* + ID_MODEL_FROM_DATABASE=KD-200Z Camera + +usb:v04C8p0726* + ID_MODEL_FROM_DATABASE=KD-310Z Camera + +usb:v04C8p0728* + ID_MODEL_FROM_DATABASE=Revio C2 Mass Storage Device + +usb:v04C8p0729* + ID_MODEL_FROM_DATABASE=Revio C2 Digital Camera + +usb:v04C8p072C* + ID_MODEL_FROM_DATABASE=Revio KD20M + +usb:v04C8p072D* + ID_MODEL_FROM_DATABASE=Revio KD410Z + +usb:v04CA* + ID_VENDOR_FROM_DATABASE=Lite-On Technology Corp. + +usb:v04CAp004B* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v04CAp004F* + ID_MODEL_FROM_DATABASE=SK-9020 keyboard + +usb:v04CAp1766* + ID_MODEL_FROM_DATABASE=HID Monitor Controls + +usb:v04CAp2004* + ID_MODEL_FROM_DATABASE=Bluetooth 4.0 [Broadcom BCM20702A0] + +usb:v04CAp2006* + ID_MODEL_FROM_DATABASE=Broadcom BCM43142A0 Bluetooth Device + +usb:v04CAp2007* + ID_MODEL_FROM_DATABASE=Broadcom BCM43142A0 Bluetooth Device + +usb:v04CAp3005* + ID_MODEL_FROM_DATABASE=Atheros Bluetooth + +usb:v04CAp300B* + ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth + +usb:v04CAp300D* + ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth + +usb:v04CAp300F* + ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth + +usb:v04CAp3014* + ID_MODEL_FROM_DATABASE=Qualcomm Atheros Bluetooth + +usb:v04CAp7022* + ID_MODEL_FROM_DATABASE=HP HD Webcam + +usb:v04CAp7025* + ID_MODEL_FROM_DATABASE=HP HD Webcam + +usb:v04CAp7046* + ID_MODEL_FROM_DATABASE=TOSHIBA Web Camera - HD + +usb:v04CAp9304* + ID_MODEL_FROM_DATABASE=Hub + +usb:v04CApF01C* + ID_MODEL_FROM_DATABASE=TT1280DA DVB-T TV Tuner + +usb:v04CB* + ID_VENDOR_FROM_DATABASE=Fuji Photo Film Co., Ltd + +usb:v04CBp0100* + ID_MODEL_FROM_DATABASE=FinePix 30i/40i/50i, A101/201, 1300/2200, 1400/2400/2600/2800/4500/4700/4800/4900/6800/6900 Zoom + +usb:v04CBp0103* + ID_MODEL_FROM_DATABASE=FinePix NX-500/NX-700 printer + +usb:v04CBp0104* + ID_MODEL_FROM_DATABASE=FinePix A101, 2600/2800/4800/6800 Zoom (PC CAM) + +usb:v04CBp0108* + ID_MODEL_FROM_DATABASE=FinePix F601 Zoom (DSC) + +usb:v04CBp0109* + ID_MODEL_FROM_DATABASE=FinePix F601 Zoom (PC CAM) + +usb:v04CBp010A* + ID_MODEL_FROM_DATABASE=FinePix S602 (Pro) Zoom (DSC) + +usb:v04CBp010B* + ID_MODEL_FROM_DATABASE=FinePix S602 (Pro) Zoom (PC CAM) + +usb:v04CBp010D* + ID_MODEL_FROM_DATABASE=FinePix S2 pro + +usb:v04CBp010E* + ID_MODEL_FROM_DATABASE=FinePix F402 Zoom (DSC) + +usb:v04CBp010F* + ID_MODEL_FROM_DATABASE=FinePix F402 Zoom (PC CAM) + +usb:v04CBp0110* + ID_MODEL_FROM_DATABASE=FinePix M603 Zoom (DSC) + +usb:v04CBp0111* + ID_MODEL_FROM_DATABASE=FinePix M603 Zoom (PC CAM) + +usb:v04CBp0112* + ID_MODEL_FROM_DATABASE=FinePix A202, A200 Zoom (DSC) + +usb:v04CBp0113* + ID_MODEL_FROM_DATABASE=FinePix A202, A200 Zoom (PC CAM) + +usb:v04CBp0114* + ID_MODEL_FROM_DATABASE=FinePix F401 Zoom (DSC) + +usb:v04CBp0115* + ID_MODEL_FROM_DATABASE=FinePix F401 Zoom (PC CAM) + +usb:v04CBp0116* + ID_MODEL_FROM_DATABASE=FinePix A203 Zoom (DSC) + +usb:v04CBp0117* + ID_MODEL_FROM_DATABASE=FinePix A203 Zoom (PC CAM) + +usb:v04CBp0118* + ID_MODEL_FROM_DATABASE=FinePix A303 Zoom (DSC) + +usb:v04CBp0119* + ID_MODEL_FROM_DATABASE=FinePix A303 Zoom (PC CAM) + +usb:v04CBp011A* + ID_MODEL_FROM_DATABASE=FinePix S304/3800 Zoom (DSC) + +usb:v04CBp011B* + ID_MODEL_FROM_DATABASE=FinePix S304/3800 Zoom (PC CAM) + +usb:v04CBp011C* + ID_MODEL_FROM_DATABASE=FinePix A204/2650 Zoom (DSC) + +usb:v04CBp011D* + ID_MODEL_FROM_DATABASE=FinePix A204/2650 Zoom (PC CAM) + +usb:v04CBp0120* + ID_MODEL_FROM_DATABASE=FinePix F700 Zoom (DSC) + +usb:v04CBp0121* + ID_MODEL_FROM_DATABASE=FinePix F700 Zoom (PC CAM) + +usb:v04CBp0122* + ID_MODEL_FROM_DATABASE=FinePix F410 Zoom (DSC) + +usb:v04CBp0123* + ID_MODEL_FROM_DATABASE=FinePix F410 Zoom (PC CAM) + +usb:v04CBp0124* + ID_MODEL_FROM_DATABASE=FinePix A310 Zoom (DSC) + +usb:v04CBp0125* + ID_MODEL_FROM_DATABASE=FinePix A310 Zoom (PC CAM) + +usb:v04CBp0126* + ID_MODEL_FROM_DATABASE=FinePix A210 Zoom (DSC) + +usb:v04CBp0127* + ID_MODEL_FROM_DATABASE=FinePix A210 Zoom (PC CAM) + +usb:v04CBp0128* + ID_MODEL_FROM_DATABASE=FinePix A205(S) Zoom (DSC) + +usb:v04CBp0129* + ID_MODEL_FROM_DATABASE=FinePix A205(S) Zoom (PC CAM) + +usb:v04CBp012A* + ID_MODEL_FROM_DATABASE=FinePix F610 Zoom (DSC) + +usb:v04CBp012B* + ID_MODEL_FROM_DATABASE=FinePix Digital Camera 030513 + +usb:v04CBp012C* + ID_MODEL_FROM_DATABASE=FinePix S7000 Zoom (DSC) + +usb:v04CBp012D* + ID_MODEL_FROM_DATABASE=FinePix S7000 Zoom (PC CAM) + +usb:v04CBp012F* + ID_MODEL_FROM_DATABASE=FinePix Digital Camera 030731 + +usb:v04CBp0130* + ID_MODEL_FROM_DATABASE=FinePix S5000 Zoom (DSC) + +usb:v04CBp0131* + ID_MODEL_FROM_DATABASE=FinePix S5000 Zoom (PC CAM) + +usb:v04CBp013B* + ID_MODEL_FROM_DATABASE=FinePix Digital Camera 030722 + +usb:v04CBp013C* + ID_MODEL_FROM_DATABASE=FinePix S3000 Zoom (DSC) + +usb:v04CBp013D* + ID_MODEL_FROM_DATABASE=FinePix S3000 Zoom (PC CAM) + +usb:v04CBp013E* + ID_MODEL_FROM_DATABASE=FinePix F420 Zoom (DSC) + +usb:v04CBp013F* + ID_MODEL_FROM_DATABASE=FinePix F420 Zoom (PC CAM) + +usb:v04CBp0142* + ID_MODEL_FROM_DATABASE=FinePix S7000 Zoom (PTP) + +usb:v04CBp0148* + ID_MODEL_FROM_DATABASE=FinePix A330 Zoom (DSC) + +usb:v04CBp0149* + ID_MODEL_FROM_DATABASE=FinePix A330 Zoom (UVC) + +usb:v04CBp014A* + ID_MODEL_FROM_DATABASE=FinePix A330 Zoom (PTP) + +usb:v04CBp014B* + ID_MODEL_FROM_DATABASE=FinePix A340 Zoom (DSC) + +usb:v04CBp014C* + ID_MODEL_FROM_DATABASE=FinePix A340 Zoom (UVC) + +usb:v04CBp0159* + ID_MODEL_FROM_DATABASE=FinePix F710 Zoom (DSC) + +usb:v04CBp0165* + ID_MODEL_FROM_DATABASE=FinePix S3500 Zoom (DSC) + +usb:v04CBp0168* + ID_MODEL_FROM_DATABASE=FinePix E500 Zoom (DSC) + +usb:v04CBp0169* + ID_MODEL_FROM_DATABASE=FinePix E500 Zoom (UVC) + +usb:v04CBp016B* + ID_MODEL_FROM_DATABASE=FinePix E510 Zoom (DSC) + +usb:v04CBp016C* + ID_MODEL_FROM_DATABASE=FinePix E510 Zoom (PC CAM) + +usb:v04CBp016E* + ID_MODEL_FROM_DATABASE=FinePix S5500 Zoom (DSC) + +usb:v04CBp016F* + ID_MODEL_FROM_DATABASE=FinePix S5500 Zoom (UVC) + +usb:v04CBp0171* + ID_MODEL_FROM_DATABASE=FinePix E550 Zoom (DSC) + +usb:v04CBp0172* + ID_MODEL_FROM_DATABASE=FinePix E550 Zoom (UVC) + +usb:v04CBp0177* + ID_MODEL_FROM_DATABASE=FinePix F10 (DSC) + +usb:v04CBp0179* + ID_MODEL_FROM_DATABASE=Finepix F10 (PTP) + +usb:v04CBp0186* + ID_MODEL_FROM_DATABASE=FinePix S5200/S5600 Zoom (DSC) + +usb:v04CBp0188* + ID_MODEL_FROM_DATABASE=FinePix S5200/S5600 Zoom (PTP) + +usb:v04CBp018E* + ID_MODEL_FROM_DATABASE=FinePix S9500 Zoom (DSC) + +usb:v04CBp018F* + ID_MODEL_FROM_DATABASE=FinePix S9500 Zoom (PTP) + +usb:v04CBp0192* + ID_MODEL_FROM_DATABASE=FinePix E900 Zoom (DSC) + +usb:v04CBp0193* + ID_MODEL_FROM_DATABASE=FinePix E900 Zoom (PTP) + +usb:v04CBp019B* + ID_MODEL_FROM_DATABASE=FinePix F30 (PTP) + +usb:v04CBp01AF* + ID_MODEL_FROM_DATABASE=FinePix A700 (PTP) + +usb:v04CBp01BF* + ID_MODEL_FROM_DATABASE=FinePix F6000fd/S6500fd Zoom (PTP) + +usb:v04CBp01C0* + ID_MODEL_FROM_DATABASE=FinePix F20 (PTP) + +usb:v04CBp01C1* + ID_MODEL_FROM_DATABASE=FinePix F31fd (PTP) + +usb:v04CBp01C3* + ID_MODEL_FROM_DATABASE=FinePix S5 Pro + +usb:v04CBp01C4* + ID_MODEL_FROM_DATABASE=FinePix S5700 Zoom (PTP) + +usb:v04CBp01C5* + ID_MODEL_FROM_DATABASE=FinePix F40fd (PTP) + +usb:v04CBp01C6* + ID_MODEL_FROM_DATABASE=FinePix A820 Zoom (PTP) + +usb:v04CBp01D2* + ID_MODEL_FROM_DATABASE=FinePix A800 Zoom (PTP) + +usb:v04CBp01D3* + ID_MODEL_FROM_DATABASE=FinePix A920 (PTP) + +usb:v04CBp01D4* + ID_MODEL_FROM_DATABASE=FinePix F50fd (PTP) + +usb:v04CBp01D5* + ID_MODEL_FROM_DATABASE=FinePix F47 (PTP) + +usb:v04CBp01F7* + ID_MODEL_FROM_DATABASE=FinePix J250 (PTP) + +usb:v04CBp01FD* + ID_MODEL_FROM_DATABASE=A160 + +usb:v04CBp023E* + ID_MODEL_FROM_DATABASE=FinePix AX300 + +usb:v04CBp0240* + ID_MODEL_FROM_DATABASE=FinePix S2950 Digital Camera + +usb:v04CBp0241* + ID_MODEL_FROM_DATABASE=FinePix S3200 Digital Camera + +usb:v04CBp0278* + ID_MODEL_FROM_DATABASE=FinePix JV300 + +usb:v04CBp02C5* + ID_MODEL_FROM_DATABASE=FinePix S9900W Digital Camera (PTP) + +usb:v04CBp5006* + ID_MODEL_FROM_DATABASE=ASK-300 + +usb:v04CC* + ID_VENDOR_FROM_DATABASE=ST-Ericsson + +usb:v04CCp1122* + ID_MODEL_FROM_DATABASE=Hub + +usb:v04CCp1520* + ID_MODEL_FROM_DATABASE=USB 2.0 Hub (Avocent KVM) + +usb:v04CCp1521* + ID_MODEL_FROM_DATABASE=USB 2.0 Hub + +usb:v04CCp1A62* + ID_MODEL_FROM_DATABASE=GW Instek GSP-830 Spectrum Analyzer (HID) + +usb:v04CCp2323* + ID_MODEL_FROM_DATABASE=Ux500 serial debug port + +usb:v04CCp2533* + ID_MODEL_FROM_DATABASE=NFC device (PN533) + +usb:v04CCp8116* + ID_MODEL_FROM_DATABASE=Camera + +usb:v04CD* + ID_VENDOR_FROM_DATABASE=Tatung Co. Of America + +usb:v04CE* + ID_VENDOR_FROM_DATABASE=ScanLogic Corp. + +usb:v04CEp0002* + ID_MODEL_FROM_DATABASE=SL11R-IDE IDE Bridge + +usb:v04CEp0100* + ID_MODEL_FROM_DATABASE=USB2PRN Printer Class + +usb:v04CEp0300* + ID_MODEL_FROM_DATABASE=Phantom 336CX - C3 scanner + +usb:v04CEp04CE* + ID_MODEL_FROM_DATABASE=SL11DEMO, VID: 0x4ce, PID: 0x4ce + +usb:v04CEp07D1* + ID_MODEL_FROM_DATABASE=SL11R, VID: 0x4ce, PID: 0x07D1 + +usb:v04CF* + ID_VENDOR_FROM_DATABASE=Myson Century, Inc. + +usb:v04CFp0022* + ID_MODEL_FROM_DATABASE=OCZ Alchemy Series Elixir II Keyboard + +usb:v04CFp0800* + ID_MODEL_FROM_DATABASE=MTP800 Mass Storage Device + +usb:v04CFp8810* + ID_MODEL_FROM_DATABASE=CS8810 Mass Storage Device + +usb:v04CFp8811* + ID_MODEL_FROM_DATABASE=CS8811 Mass Storage Device + +usb:v04CFp8813* + ID_MODEL_FROM_DATABASE=CS8813 Mass Storage Device + +usb:v04CFp8818* + ID_MODEL_FROM_DATABASE=USB2.0 to ATAPI Bridge Controller + +usb:v04CFp8819* + ID_MODEL_FROM_DATABASE=USB 2.0 SD/MMC Reader + +usb:v04CFp9920* + ID_MODEL_FROM_DATABASE=CS8819A2-114 Mass Storage Device + +usb:v04D0* + ID_VENDOR_FROM_DATABASE=Digi International + +usb:v04D1* + ID_VENDOR_FROM_DATABASE=ITT Canon + +usb:v04D2* + ID_VENDOR_FROM_DATABASE=Altec Lansing Technologies + +usb:v04D2p0070* + ID_MODEL_FROM_DATABASE=ADA70 Speakers + +usb:v04D2p0305* + ID_MODEL_FROM_DATABASE=Non-Compliant Audio Device + +usb:v04D2p0311* + ID_MODEL_FROM_DATABASE=ADA-310 Speakers + +usb:v04D2p2060* + ID_MODEL_FROM_DATABASE=Claritel-i750 - vp + +usb:v04D2pFF05* + ID_MODEL_FROM_DATABASE=ADA-305 Speakers + +usb:v04D2pFF47* + ID_MODEL_FROM_DATABASE=Lansing HID Audio Controls + +usb:v04D2pFF49* + ID_MODEL_FROM_DATABASE=Lansing HID Audio Controls + +usb:v04D3* + ID_VENDOR_FROM_DATABASE=VidUS, Inc. + +usb:v04D4* + ID_VENDOR_FROM_DATABASE=LSI Logic, Inc. + +usb:v04D5* + ID_VENDOR_FROM_DATABASE=Forte Technologies, Inc. + +usb:v04D6* + ID_VENDOR_FROM_DATABASE=Mentor Graphics + +usb:v04D7* + ID_VENDOR_FROM_DATABASE=Oki Semiconductor + +usb:v04D7p1BE4* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v04D8* + ID_VENDOR_FROM_DATABASE=Microchip Technology, Inc. + +usb:v04D8p0002* + ID_MODEL_FROM_DATABASE=PicoLCD 20x2 + +usb:v04D8p0003* + ID_MODEL_FROM_DATABASE=PICkit 2 Microcontroller Programmer + +usb:v04D8p000A* + ID_MODEL_FROM_DATABASE=CDC RS-232 Emulation Demo + +usb:v04D8p000B* + ID_MODEL_FROM_DATABASE=PIC18F2550 (32K Flashable 10 Channel, 10 Bit A/D USB Microcontroller) + +usb:v04D8p0032* + ID_MODEL_FROM_DATABASE=PICkit1 + +usb:v04D8p0033* + ID_MODEL_FROM_DATABASE=PICkit2 + +usb:v04D8p0036* + ID_MODEL_FROM_DATABASE=PICkit Serial Analyzer + +usb:v04D8p00E0* + ID_MODEL_FROM_DATABASE=PIC32 Starter Board + +usb:v04D8p04CD* + ID_MODEL_FROM_DATABASE=28Cxxx EEPROM Programmer + +usb:v04D8p0A04* + ID_MODEL_FROM_DATABASE=AGP LIN Serial Analyzer + +usb:v04D8p8000* + ID_MODEL_FROM_DATABASE=In-Circuit Debugger + +usb:v04D8p8001* + ID_MODEL_FROM_DATABASE=ICD2 in-circuit debugger + +usb:v04D8p8101* + ID_MODEL_FROM_DATABASE=PIC24F Starter Kit + +usb:v04D8p8107* + ID_MODEL_FROM_DATABASE=Microstick II + +usb:v04D8p8108* + ID_MODEL_FROM_DATABASE=ChipKit Pro MX7 (PIC32MX) + +usb:v04D8p9004* + ID_MODEL_FROM_DATABASE=Microchip REAL ICE + +usb:v04D8p900A* + ID_MODEL_FROM_DATABASE=PICkit3 + +usb:v04D8p9012* + ID_MODEL_FROM_DATABASE=PICkit4 + +usb:v04D8p9015* + ID_MODEL_FROM_DATABASE=ICD 4 In-Circuit Debugger + +usb:v04D8pC001* + ID_MODEL_FROM_DATABASE=PicoLCD 20x4 + +usb:v04D8pE11C* + ID_MODEL_FROM_DATABASE=TL866CS EEPROM Programmer [MiniPRO] + +usb:v04D8pEDB4* + ID_MODEL_FROM_DATABASE=micro PLC (ATSAMD51G19A) [Black Brix ECU II] + +usb:v04D8pEDB5* + ID_MODEL_FROM_DATABASE=ATMEGA32U4 [Black Brix ECU] + +usb:v04D8pF2C4* + ID_MODEL_FROM_DATABASE=Macareux-labs Hygrometry Temperature Sensor + +usb:v04D8pF2F7* + ID_MODEL_FROM_DATABASE=Yepkit YKUSH + +usb:v04D8pF3AA* + ID_MODEL_FROM_DATABASE=Macareux-labs Usbce Bootloader mode + +usb:v04D8pF437* + ID_MODEL_FROM_DATABASE=SBE Tech Ultrasonic Anemometer + +usb:v04D8pF4B5* + ID_MODEL_FROM_DATABASE=SmartScope + +usb:v04D8pF5FE* + ID_MODEL_FROM_DATABASE=TrueRNG + +usb:v04D8pF8DA* + ID_MODEL_FROM_DATABASE=Hughski Ltd. ColorHug + +usb:v04D8pF8E8* + ID_MODEL_FROM_DATABASE=Harmony 300/350 Remote + +usb:v04D8pF91C* + ID_MODEL_FROM_DATABASE=SPROG IIv3 + +usb:v04D8pFAFF* + ID_MODEL_FROM_DATABASE=Dangerous Prototypes BusPirate v4 Bootloader mode + +usb:v04D8pFB00* + ID_MODEL_FROM_DATABASE=Dangerous Prototypes BusPirate v4 + +usb:v04D8pFBB2* + ID_MODEL_FROM_DATABASE=GCUSB-nStep stepper motor controller + +usb:v04D8pFBBA* + ID_MODEL_FROM_DATABASE=DiscFerret Magnetic Disc Analyser (bootloader mode) + +usb:v04D8pFBBB* + ID_MODEL_FROM_DATABASE=DiscFerret Magnetic Disc Analyser (active mode) + +usb:v04D8pFC1E* + ID_MODEL_FROM_DATABASE=Bachrus Speedometer Interface + +usb:v04D8pFC92* + ID_MODEL_FROM_DATABASE=Open Bench Logic Sniffer + +usb:v04D8pFFEE* + ID_MODEL_FROM_DATABASE=Devantech USB-ISS + +usb:v04D8pFFEF* + ID_MODEL_FROM_DATABASE=PICoPLC [APStech] + +usb:v04D9* + ID_VENDOR_FROM_DATABASE=Holtek Semiconductor, Inc. + +usb:v04D9p0022* + ID_MODEL_FROM_DATABASE=Portable Keyboard + +usb:v04D9p048E* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v04D9p0499* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v04D9p1135* + ID_MODEL_FROM_DATABASE=Mouse [MGK-15BU/MLK-15BU] + +usb:v04D9p1203* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v04D9p1400* + ID_MODEL_FROM_DATABASE=PS/2 keyboard + mouse controller + +usb:v04D9p1503* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v04D9p1603* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v04D9p1702* + ID_MODEL_FROM_DATABASE=Keyboard LKS02 + +usb:v04D9p1818* + ID_MODEL_FROM_DATABASE=Keyboard [Diatec Filco Majestouch 2] + +usb:v04D9p2011* + ID_MODEL_FROM_DATABASE=Keyboard [Diatec Filco Majestouch 1] + +usb:v04D9p2013* + ID_MODEL_FROM_DATABASE=Keyboard [Das Keyboard] + +usb:v04D9p2206* + ID_MODEL_FROM_DATABASE=Fujitsu Siemens Mouse Esprimo Q + +usb:v04D9p2221* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v04D9p2323* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v04D9p2519* + ID_MODEL_FROM_DATABASE=Shenzhen LogoTech 2.4GHz receiver + +usb:v04D9p2832* + ID_MODEL_FROM_DATABASE=HT82A832R Audio MCU + +usb:v04D9p2834* + ID_MODEL_FROM_DATABASE=HT82A834R Audio MCU + +usb:v04D9p4545* + ID_MODEL_FROM_DATABASE=Keyboard [Diatec Majestouch 2 Tenkeyless] + +usb:v04D9pA01C* + ID_MODEL_FROM_DATABASE=wireless multimedia keyboard with trackball [Trust ADURA 17911] + +usb:v04D9pA050* + ID_MODEL_FROM_DATABASE=Chatman V1 + +usb:v04D9pA052* + ID_MODEL_FROM_DATABASE=USB-zyTemp + +usb:v04D9pA055* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v04D9pA096* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v04D9pA09F* + ID_MODEL_FROM_DATABASE=E-Signal LUOM G10 Mechanical Gaming Mouse + +usb:v04D9pA100* + ID_MODEL_FROM_DATABASE=Mouse [HV-MS735] + +usb:v04D9pA11B* + ID_MODEL_FROM_DATABASE=Mouse [MX-3200] + +usb:v04D9pE002* + ID_MODEL_FROM_DATABASE=MCU + +usb:v04DA* + ID_VENDOR_FROM_DATABASE=Panasonic (Matsushita) + +usb:v04DAp0901* + ID_MODEL_FROM_DATABASE=LS-120 Camera + +usb:v04DAp0912* + ID_MODEL_FROM_DATABASE=SDR-S10 + +usb:v04DAp0B01* + ID_MODEL_FROM_DATABASE=CD-R/RW Drive + +usb:v04DAp0B03* + ID_MODEL_FROM_DATABASE=SuperDisk 240MB + +usb:v04DAp0D01* + ID_MODEL_FROM_DATABASE=CD-R Drive KXL-840AN + +usb:v04DAp0D09* + ID_MODEL_FROM_DATABASE=CD-R Drive KXL-RW32AN + +usb:v04DAp0D0A* + ID_MODEL_FROM_DATABASE=CD-R Drive KXL-CB20AN + +usb:v04DAp0D0D* + ID_MODEL_FROM_DATABASE=CDRCB03 + +usb:v04DAp0D0E* + ID_MODEL_FROM_DATABASE=DVD-ROM & CD-R/RW + +usb:v04DAp0D14* + ID_MODEL_FROM_DATABASE=DVD-RAM MLT08 + +usb:v04DAp0F07* + ID_MODEL_FROM_DATABASE=KX-MB2030 Multifunction Laser Printer + +usb:v04DAp0F40* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04DAp104D* + ID_MODEL_FROM_DATABASE=Elite Panaboard UB-T880 (HID) + +usb:v04DAp104E* + ID_MODEL_FROM_DATABASE=Elite Panaboard Pen Adaptor (HID) + +usb:v04DAp1500* + ID_MODEL_FROM_DATABASE=MFSUSB Driver + +usb:v04DAp1800* + ID_MODEL_FROM_DATABASE=DY-WL10 802.11abgn Adapter [Broadcom BCM4323] + +usb:v04DAp1B00* + ID_MODEL_FROM_DATABASE=MultiMediaCard + +usb:v04DAp2121* + ID_MODEL_FROM_DATABASE=EB-VS6 + +usb:v04DAp2316* + ID_MODEL_FROM_DATABASE=DVC Mass Storage Device + +usb:v04DAp2317* + ID_MODEL_FROM_DATABASE=DVC USB-SERIAL Driver for WinXP + +usb:v04DAp2318* + ID_MODEL_FROM_DATABASE=NV-GS11/230/250 (webcam mode) + +usb:v04DAp2319* + ID_MODEL_FROM_DATABASE=NV-GS15 (webcam mode) + +usb:v04DAp231A* + ID_MODEL_FROM_DATABASE=NV-GS11/230/250 (DV mode) + +usb:v04DAp231D* + ID_MODEL_FROM_DATABASE=DVC Web Camera Device + +usb:v04DAp231E* + ID_MODEL_FROM_DATABASE=DVC DV Stream Device + +usb:v04DAp2372* + ID_MODEL_FROM_DATABASE=Lumix Camera (Storage mode) + +usb:v04DAp2374* + ID_MODEL_FROM_DATABASE=Lumix Camera (PTP mode) + +usb:v04DAp2451* + ID_MODEL_FROM_DATABASE=HDC-SD9 + +usb:v04DAp245B* + ID_MODEL_FROM_DATABASE=HC-X920K (3MOS Full HD video camcorder) + +usb:v04DAp2477* + ID_MODEL_FROM_DATABASE=SDR-H85 Camcorder (PC mode) + +usb:v04DAp2478* + ID_MODEL_FROM_DATABASE=SDR-H85 Camcorder (recorder mode - SD card) + +usb:v04DAp2479* + ID_MODEL_FROM_DATABASE=SDR-H85 Camcorder (recorder mode - HDD) + +usb:v04DAp2497* + ID_MODEL_FROM_DATABASE=HDC-TM700 + +usb:v04DAp250C* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) + +usb:v04DAp250D* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem + +usb:v04DAp3904* + ID_MODEL_FROM_DATABASE=N5HBZ0000055 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] + +usb:v04DAp3908* + ID_MODEL_FROM_DATABASE=N5HBZ0000062 802.11abgn Wireless Adapter [Atheros AR9374v1.1] + +usb:v04DAp3C04* + ID_MODEL_FROM_DATABASE=JT-P100MR-20 [ePassport Reader] + +usb:v04DB* + ID_VENDOR_FROM_DATABASE=Hypertec Pty, Ltd + +usb:v04DC* + ID_VENDOR_FROM_DATABASE=Huan Hsin Holdings, Ltd + +usb:v04DD* + ID_VENDOR_FROM_DATABASE=Sharp Corp. + +usb:v04DDp13A6* + ID_MODEL_FROM_DATABASE=MFC2000 + +usb:v04DDp6006* + ID_MODEL_FROM_DATABASE=AL-1216 + +usb:v04DDp6007* + ID_MODEL_FROM_DATABASE=AL-1045 + +usb:v04DDp6008* + ID_MODEL_FROM_DATABASE=AL-1255 + +usb:v04DDp6009* + ID_MODEL_FROM_DATABASE=AL-1530CS + +usb:v04DDp600A* + ID_MODEL_FROM_DATABASE=AL-1540CS + +usb:v04DDp600B* + ID_MODEL_FROM_DATABASE=AL-1456 + +usb:v04DDp600C* + ID_MODEL_FROM_DATABASE=AL-1555 + +usb:v04DDp600D* + ID_MODEL_FROM_DATABASE=AL-1225 + +usb:v04DDp600E* + ID_MODEL_FROM_DATABASE=AL-1551CS + +usb:v04DDp600F* + ID_MODEL_FROM_DATABASE=AR-122E + +usb:v04DDp6010* + ID_MODEL_FROM_DATABASE=AR-152E + +usb:v04DDp6011* + ID_MODEL_FROM_DATABASE=AR-157E + +usb:v04DDp6012* + ID_MODEL_FROM_DATABASE=SN-1045 + +usb:v04DDp6013* + ID_MODEL_FROM_DATABASE=SN-1255 + +usb:v04DDp6014* + ID_MODEL_FROM_DATABASE=SN-1456 + +usb:v04DDp6015* + ID_MODEL_FROM_DATABASE=SN-1555 + +usb:v04DDp6016* + ID_MODEL_FROM_DATABASE=AR-153E + +usb:v04DDp6017* + ID_MODEL_FROM_DATABASE=AR-122E N + +usb:v04DDp6018* + ID_MODEL_FROM_DATABASE=AR-153E N + +usb:v04DDp6019* + ID_MODEL_FROM_DATABASE=AR-152E N + +usb:v04DDp601A* + ID_MODEL_FROM_DATABASE=AR-157E N + +usb:v04DDp601B* + ID_MODEL_FROM_DATABASE=AL-1217 + +usb:v04DDp601C* + ID_MODEL_FROM_DATABASE=AL-1226 + +usb:v04DDp601D* + ID_MODEL_FROM_DATABASE=AR-123E + +usb:v04DDp6021* + ID_MODEL_FROM_DATABASE=IS01 + +usb:v04DDp7002* + ID_MODEL_FROM_DATABASE=DVC Ver.1.0 + +usb:v04DDp7004* + ID_MODEL_FROM_DATABASE=VE-CG40U Digital Still Camera + +usb:v04DDp7005* + ID_MODEL_FROM_DATABASE=VE-CG30 Digital Still Camera + +usb:v04DDp7007* + ID_MODEL_FROM_DATABASE=VL-Z7S Digital Camcorder + +usb:v04DDp8004* + ID_MODEL_FROM_DATABASE=Zaurus SL-5000D/SL-5500 PDA + +usb:v04DDp8005* + ID_MODEL_FROM_DATABASE=Zaurus A-300 + +usb:v04DDp8006* + ID_MODEL_FROM_DATABASE=Zaurus SL-B500/SL-5600 PDA + +usb:v04DDp8007* + ID_MODEL_FROM_DATABASE=Zaurus C-700 PDA + +usb:v04DDp9009* + ID_MODEL_FROM_DATABASE=AR-M160 + +usb:v04DDp9014* + ID_MODEL_FROM_DATABASE=IM-DR80 Portable NetMD Player + +usb:v04DDp9031* + ID_MODEL_FROM_DATABASE=Zaurus C-750/C-760/C-860/SL-C3000 PDA + +usb:v04DDp9032* + ID_MODEL_FROM_DATABASE=Zaurus SL-6000 + +usb:v04DDp903A* + ID_MODEL_FROM_DATABASE=GSM GPRS + +usb:v04DDp9050* + ID_MODEL_FROM_DATABASE=Zaurus C-860 PDA + +usb:v04DDp9056* + ID_MODEL_FROM_DATABASE=Viewcam Z + +usb:v04DDp9073* + ID_MODEL_FROM_DATABASE=AM-900 + +usb:v04DDp9074* + ID_MODEL_FROM_DATABASE=GSM GPRS + +usb:v04DDp90A9* + ID_MODEL_FROM_DATABASE=Sharp Composite + +usb:v04DDp90D0* + ID_MODEL_FROM_DATABASE=USB-to-Serial Comm. Port + +usb:v04DDp90F2* + ID_MODEL_FROM_DATABASE=Sharp 3G GSM USB Control + +usb:v04DDp9120* + ID_MODEL_FROM_DATABASE=WS004SH + +usb:v04DDp9122* + ID_MODEL_FROM_DATABASE=WS007SH + +usb:v04DDp9123* + ID_MODEL_FROM_DATABASE=W-ZERO3 ES Smartphone + +usb:v04DDp91A3* + ID_MODEL_FROM_DATABASE=922SH Internet Machine + +usb:v04DDp939A* + ID_MODEL_FROM_DATABASE=IS03 + +usb:v04DE* + ID_VENDOR_FROM_DATABASE=MindShare, Inc. + +usb:v04DF* + ID_VENDOR_FROM_DATABASE=Interlink Electronics + +usb:v04E1* + ID_VENDOR_FROM_DATABASE=Iiyama North America, Inc. + +usb:v04E1p0201* + ID_MODEL_FROM_DATABASE=Monitor Hub + +usb:v04E2* + ID_VENDOR_FROM_DATABASE=Exar Corp. + +usb:v04E2p1410* + ID_MODEL_FROM_DATABASE=XR21V1410 USB-UART IC + +usb:v04E3* + ID_VENDOR_FROM_DATABASE=Zilog, Inc. + +usb:v04E4* + ID_VENDOR_FROM_DATABASE=ACC Microelectronics + +usb:v04E5* + ID_VENDOR_FROM_DATABASE=Promise Technology + +usb:v04E6* + ID_VENDOR_FROM_DATABASE=SCM Microsystems, Inc. + +usb:v04E6p0001* + ID_MODEL_FROM_DATABASE=E-USB ATA Bridge + +usb:v04E6p0002* + ID_MODEL_FROM_DATABASE=eUSCSI SCSI Bridge + +usb:v04E6p0003* + ID_MODEL_FROM_DATABASE=eUSB SmartMedia Card Reader + +usb:v04E6p0005* + ID_MODEL_FROM_DATABASE=eUSB SmartMedia/CompactFlash Card Reader + +usb:v04E6p0006* + ID_MODEL_FROM_DATABASE=eUSB SmartMedia Card Reader + +usb:v04E6p0007* + ID_MODEL_FROM_DATABASE=Hifd + +usb:v04E6p0009* + ID_MODEL_FROM_DATABASE=eUSB ATA/ATAPI Adapter + +usb:v04E6p000A* + ID_MODEL_FROM_DATABASE=eUSB CompactFlash Adapter + +usb:v04E6p000B* + ID_MODEL_FROM_DATABASE=eUSCSI Bridge + +usb:v04E6p000C* + ID_MODEL_FROM_DATABASE=eUSCSI Bridge + +usb:v04E6p000D* + ID_MODEL_FROM_DATABASE=Dazzle MS + +usb:v04E6p0012* + ID_MODEL_FROM_DATABASE=Dazzle SD/MMC + +usb:v04E6p0101* + ID_MODEL_FROM_DATABASE=eUSB ATA Bridge (Sony Spressa USB CDRW) + +usb:v04E6p0311* + ID_MODEL_FROM_DATABASE=Dazzle DM-CF + +usb:v04E6p0312* + ID_MODEL_FROM_DATABASE=Dazzle DM-SD/MMC + +usb:v04E6p0313* + ID_MODEL_FROM_DATABASE=Dazzle SM + +usb:v04E6p0314* + ID_MODEL_FROM_DATABASE=Dazzle MS + +usb:v04E6p0322* + ID_MODEL_FROM_DATABASE=e-Film Reader-5 + +usb:v04E6p0325* + ID_MODEL_FROM_DATABASE=eUSB ORCA Quad Reader + +usb:v04E6p0327* + ID_MODEL_FROM_DATABASE=Digital Media Reader + +usb:v04E6p03FE* + ID_MODEL_FROM_DATABASE=DMHS2 DFU Adapter + +usb:v04E6p0406* + ID_MODEL_FROM_DATABASE=eUSB SmartDM Reader + +usb:v04E6p04E6* + ID_MODEL_FROM_DATABASE=eUSB DFU Adapter + +usb:v04E6p04E7* + ID_MODEL_FROM_DATABASE=STCII DFU Adapter + +usb:v04E6p04E8* + ID_MODEL_FROM_DATABASE=eUSBDM DFU Adapter + +usb:v04E6p04E9* + ID_MODEL_FROM_DATABASE=DM-E DFU Adapter + +usb:v04E6p0500* + ID_MODEL_FROM_DATABASE=Veridicom 5thSense Fingerprint Sensor and eUSB SmartCard + +usb:v04E6p0701* + ID_MODEL_FROM_DATABASE=DCS200 Loader Device + +usb:v04E6p0702* + ID_MODEL_FROM_DATABASE=DVD Creation Station 200 + +usb:v04E6p0703* + ID_MODEL_FROM_DATABASE=DVC100 Loader Device + +usb:v04E6p0704* + ID_MODEL_FROM_DATABASE=Digital Video Creator 100 + +usb:v04E6p1001* + ID_MODEL_FROM_DATABASE=SCR300 Smart Card Reader + +usb:v04E6p1010* + ID_MODEL_FROM_DATABASE=USBAT-2 CompactFlash Card Reader + +usb:v04E6p1014* + ID_MODEL_FROM_DATABASE=e-Film Reader-3 + +usb:v04E6p1020* + ID_MODEL_FROM_DATABASE=USBAT ATA/ATAPI Adapter + +usb:v04E6p2007* + ID_MODEL_FROM_DATABASE=RSA SecurID ComboReader + +usb:v04E6p2009* + ID_MODEL_FROM_DATABASE=Citibank Smart Card Reader + +usb:v04E6p200A* + ID_MODEL_FROM_DATABASE=Reflex v.2 Smart Card Reader + +usb:v04E6p200D* + ID_MODEL_FROM_DATABASE=STR391 Reader + +usb:v04E6p5111* + ID_MODEL_FROM_DATABASE=SCR331-DI SmartCard Reader + +usb:v04E6p5113* + ID_MODEL_FROM_DATABASE=SCR333 SmartCard Reader + +usb:v04E6p5114* + ID_MODEL_FROM_DATABASE=SCR331-DI SmartCard Reader + +usb:v04E6p5115* + ID_MODEL_FROM_DATABASE=SCR335 SmartCard Reader + +usb:v04E6p5116* + ID_MODEL_FROM_DATABASE=SCR331-LC1 / SCR3310 SmartCard Reader + +usb:v04E6p5117* + ID_MODEL_FROM_DATABASE=SCR3320 - Smart Card Reader + +usb:v04E6p5118* + ID_MODEL_FROM_DATABASE=Expresscard SIM Card Reader + +usb:v04E6p5119* + ID_MODEL_FROM_DATABASE=SCR3340 - ExpressCard54 Smart Card Reader + +usb:v04E6p511B* + ID_MODEL_FROM_DATABASE=SmartCard Reader + +usb:v04E6p511D* + ID_MODEL_FROM_DATABASE=SCR3311 Smart Card Reader + +usb:v04E6p5120* + ID_MODEL_FROM_DATABASE=SCR331-DI SmartCard Reader + +usb:v04E6p5121* + ID_MODEL_FROM_DATABASE=SDI010 Smart Card Reader + +usb:v04E6p5151* + ID_MODEL_FROM_DATABASE=SCR338 Keyboard Smart Card Reader + +usb:v04E6p5292* + ID_MODEL_FROM_DATABASE=SCL011 RFID reader + +usb:v04E6p5410* + ID_MODEL_FROM_DATABASE=SCR35xx Smart Card Reader + +usb:v04E6p5591* + ID_MODEL_FROM_DATABASE=SCL3711-NFC&RW + +usb:v04E6p5810* + ID_MODEL_FROM_DATABASE=uTrust 2700 R Smart Card Reader + +usb:v04E6pE000* + ID_MODEL_FROM_DATABASE=SCRx31 Reader + +usb:v04E6pE001* + ID_MODEL_FROM_DATABASE=SCR331 SmartCard Reader + +usb:v04E6pE003* + ID_MODEL_FROM_DATABASE=SPR532 PinPad SmartCard Reader + +usb:v04E7* + ID_VENDOR_FROM_DATABASE=Elo TouchSystems + +usb:v04E7p0001* + ID_MODEL_FROM_DATABASE=TouchScreen + +usb:v04E7p0002* + ID_MODEL_FROM_DATABASE=Touchmonitor Interface 2600 Rev 2 + +usb:v04E7p0004* + ID_MODEL_FROM_DATABASE=4000U CarrollTouch® Touchmonitor Interface + +usb:v04E7p0007* + ID_MODEL_FROM_DATABASE=2500U IntelliTouch® Touchmonitor Interface + +usb:v04E7p0008* + ID_MODEL_FROM_DATABASE=3000U AccuTouch® Touchmonitor Interface + +usb:v04E7p0009* + ID_MODEL_FROM_DATABASE=4000U CarrollTouch® Touchmonitor Interface + +usb:v04E7p0020* + ID_MODEL_FROM_DATABASE=Touchscreen Interface (2700) + +usb:v04E7p0021* + ID_MODEL_FROM_DATABASE=Touchmonitor Interface + +usb:v04E7p0030* + ID_MODEL_FROM_DATABASE=4500U CarrollTouch® Touchmonitor Interface + +usb:v04E7p0032* + ID_MODEL_FROM_DATABASE=Touchmonitor Interface + +usb:v04E7p0033* + ID_MODEL_FROM_DATABASE=Touchmonitor Interface + +usb:v04E7p0041* + ID_MODEL_FROM_DATABASE=5010 Surface Capacitive Touchmonitor Interface + +usb:v04E7p0042* + ID_MODEL_FROM_DATABASE=Touchmonitor Interface + +usb:v04E7p0050* + ID_MODEL_FROM_DATABASE=2216 AccuTouch® Touchmonitor Interface + +usb:v04E7p0071* + ID_MODEL_FROM_DATABASE=Touchmonitor Interface + +usb:v04E7p0072* + ID_MODEL_FROM_DATABASE=Touchmonitor Interface + +usb:v04E7p0081* + ID_MODEL_FROM_DATABASE=Touchmonitor Interface + +usb:v04E7p0082* + ID_MODEL_FROM_DATABASE=Touchmonitor Interface + +usb:v04E7p00FF* + ID_MODEL_FROM_DATABASE=Touchmonitor Interface + +usb:v04E8* + ID_VENDOR_FROM_DATABASE=Samsung Electronics Co., Ltd + +usb:v04E8p0001* + ID_MODEL_FROM_DATABASE=Printer Bootloader + +usb:v04E8p0100* + ID_MODEL_FROM_DATABASE=Kingston Flash Drive (128MB) + +usb:v04E8p0110* + ID_MODEL_FROM_DATABASE=Connect3D Flash Drive + +usb:v04E8p0111* + ID_MODEL_FROM_DATABASE=Connect3D Flash Drive + +usb:v04E8p0300* + ID_MODEL_FROM_DATABASE=E2530 / GT-C3350 Phones (Mass storage mode) + +usb:v04E8p1003* + ID_MODEL_FROM_DATABASE=MP3 Player and Recorder + +usb:v04E8p1006* + ID_MODEL_FROM_DATABASE=SDC-200Z + +usb:v04E8p130C* + ID_MODEL_FROM_DATABASE=NX100 + +usb:v04E8p1323* + ID_MODEL_FROM_DATABASE=WB700 Camera + +usb:v04E8p1F05* + ID_MODEL_FROM_DATABASE=S2 Portable [JMicron] (500GB) + +usb:v04E8p1F06* + ID_MODEL_FROM_DATABASE=HX-MU064DA portable harddisk + +usb:v04E8p2018* + ID_MODEL_FROM_DATABASE=WIS09ABGN LinkStick Wireless LAN Adapter + +usb:v04E8p2035* + ID_MODEL_FROM_DATABASE=Digital Photo Frame Mass Storage + +usb:v04E8p2036* + ID_MODEL_FROM_DATABASE=Digital Photo Frame Mini Monitor + +usb:v04E8p3004* + ID_MODEL_FROM_DATABASE=ML-4600 + +usb:v04E8p3005* + ID_MODEL_FROM_DATABASE=Docuprint P1210 + +usb:v04E8p3008* + ID_MODEL_FROM_DATABASE=ML-6060 laser printer + +usb:v04E8p300C* + ID_MODEL_FROM_DATABASE=ML-1210 Printer + +usb:v04E8p300E* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v04E8p3104* + ID_MODEL_FROM_DATABASE=ML-3550N + +usb:v04E8p3210* + ID_MODEL_FROM_DATABASE=ML-5200A Laser Printer + +usb:v04E8p3226* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v04E8p3228* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v04E8p322A* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v04E8p322C* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v04E8p3230* + ID_MODEL_FROM_DATABASE=ML-1440 + +usb:v04E8p3232* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v04E8p3236* + ID_MODEL_FROM_DATABASE=ML-1450 + +usb:v04E8p3238* + ID_MODEL_FROM_DATABASE=ML-1430 + +usb:v04E8p323A* + ID_MODEL_FROM_DATABASE=ML-1710 Printer + +usb:v04E8p323B* + ID_MODEL_FROM_DATABASE=Phaser 3130 + +usb:v04E8p323C* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v04E8p323D* + ID_MODEL_FROM_DATABASE=Phaser 3120 + +usb:v04E8p323E* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v04E8p3240* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v04E8p3242* + ID_MODEL_FROM_DATABASE=ML-1510 Laser Printer + +usb:v04E8p3248* + ID_MODEL_FROM_DATABASE=Color Laser Printer + +usb:v04E8p324A* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v04E8p324C* + ID_MODEL_FROM_DATABASE=ML-1740 Printer + +usb:v04E8p324D* + ID_MODEL_FROM_DATABASE=Phaser 3121 + +usb:v04E8p3256* + ID_MODEL_FROM_DATABASE=ML-1520 Laser Printer + +usb:v04E8p325B* + ID_MODEL_FROM_DATABASE=Xerox Phaser 3117 Laser Printer + +usb:v04E8p325F* + ID_MODEL_FROM_DATABASE=Phaser 3425 Laser Printer + +usb:v04E8p3260* + ID_MODEL_FROM_DATABASE=CLP-510 Color Laser Printer + +usb:v04E8p3268* + ID_MODEL_FROM_DATABASE=ML-1610 Mono Laser Printer + +usb:v04E8p326C* + ID_MODEL_FROM_DATABASE=ML-2010P Mono Laser Printer + +usb:v04E8p3276* + ID_MODEL_FROM_DATABASE=ML-3050/ML-3051 Laser Printer + +usb:v04E8p327E* + ID_MODEL_FROM_DATABASE=ML-2510 Series + +usb:v04E8p328E* + ID_MODEL_FROM_DATABASE=CLP-310 Color Laser Printer + +usb:v04E8p3292* + ID_MODEL_FROM_DATABASE=ML-1640 Series Laser Printer + +usb:v04E8p3296* + ID_MODEL_FROM_DATABASE=ML-2580N Mono Laser Printer + +usb:v04E8p3297* + ID_MODEL_FROM_DATABASE=ML-191x/ML-252x Laser Printer + +usb:v04E8p329F* + ID_MODEL_FROM_DATABASE=CLP-325 Color Laser Printer + +usb:v04E8p3301* + ID_MODEL_FROM_DATABASE=ML-1660 Series + +usb:v04E8p330C* + ID_MODEL_FROM_DATABASE=ML-1865 + +usb:v04E8p330F* + ID_MODEL_FROM_DATABASE=ML-216x Series Laser Printer + +usb:v04E8p3310* + ID_MODEL_FROM_DATABASE=ML-331x Series Laser Printer + +usb:v04E8p3315* + ID_MODEL_FROM_DATABASE=ML-2540 Series Laser Printer + +usb:v04E8p331E* + ID_MODEL_FROM_DATABASE=M262x/M282x Xpress Series Laser Printer + +usb:v04E8p3409* + ID_MODEL_FROM_DATABASE=SCX-4216F Scanner + +usb:v04E8p340C* + ID_MODEL_FROM_DATABASE=SCX-5x15 series + +usb:v04E8p340D* + ID_MODEL_FROM_DATABASE=SCX-6x20 series + +usb:v04E8p340E* + ID_MODEL_FROM_DATABASE=MFP 560 series + +usb:v04E8p340F* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v04E8p3412* + ID_MODEL_FROM_DATABASE=SCX-4x20 series + +usb:v04E8p3413* + ID_MODEL_FROM_DATABASE=SCX-4100 Scanner + +usb:v04E8p3415* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v04E8p3419* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v04E8p341A* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v04E8p341B* + ID_MODEL_FROM_DATABASE=SCX-4200 series + +usb:v04E8p341C* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v04E8p341D* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v04E8p341F* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v04E8p3420* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v04E8p3426* + ID_MODEL_FROM_DATABASE=SCX-4500 Laser Printer + +usb:v04E8p342D* + ID_MODEL_FROM_DATABASE=SCX-4x28 Series + +usb:v04E8p344F* + ID_MODEL_FROM_DATABASE=SCX-3400 Series + +usb:v04E8p347E* + ID_MODEL_FROM_DATABASE=C48x Series Color Laser Multifunction Printer + +usb:v04E8p3605* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v04E8p3606* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v04E8p3609* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v04E8p3902* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v04E8p3903* + ID_MODEL_FROM_DATABASE=Xerox WorkCentre XK50cx + +usb:v04E8p390F* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v04E8p3911* + ID_MODEL_FROM_DATABASE=SCX-1020 series + +usb:v04E8p4005* + ID_MODEL_FROM_DATABASE=GT-S8000 Jet (msc) + +usb:v04E8p4F1F* + ID_MODEL_FROM_DATABASE=GT-S8000 Jet (mtp) + +usb:v04E8p5000* + ID_MODEL_FROM_DATABASE=YP-MF series + +usb:v04E8p5001* + ID_MODEL_FROM_DATABASE=YP-100 + +usb:v04E8p5002* + ID_MODEL_FROM_DATABASE=YP-30 + +usb:v04E8p5003* + ID_MODEL_FROM_DATABASE=YP-700 + +usb:v04E8p5004* + ID_MODEL_FROM_DATABASE=YP-30 + +usb:v04E8p5005* + ID_MODEL_FROM_DATABASE=YP-300 + +usb:v04E8p5006* + ID_MODEL_FROM_DATABASE=YP-750 + +usb:v04E8p500D* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v04E8p5010* + ID_MODEL_FROM_DATABASE=Yepp YP-35 + +usb:v04E8p5011* + ID_MODEL_FROM_DATABASE=YP-780 + +usb:v04E8p5013* + ID_MODEL_FROM_DATABASE=YP-60 + +usb:v04E8p5015* + ID_MODEL_FROM_DATABASE=yepp upgrade + +usb:v04E8p501B* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v04E8p5021* + ID_MODEL_FROM_DATABASE=Yepp YP-ST5 + +usb:v04E8p5026* + ID_MODEL_FROM_DATABASE=YP-MT6V + +usb:v04E8p5027* + ID_MODEL_FROM_DATABASE=YP-T7 + +usb:v04E8p502B* + ID_MODEL_FROM_DATABASE=YP-F1 + +usb:v04E8p5032* + ID_MODEL_FROM_DATABASE=YP-J70 + +usb:v04E8p503B* + ID_MODEL_FROM_DATABASE=YP-U1 MP3 Player + +usb:v04E8p503D* + ID_MODEL_FROM_DATABASE=YP-T7F + +usb:v04E8p5041* + ID_MODEL_FROM_DATABASE=YP-Z5 + +usb:v04E8p5050* + ID_MODEL_FROM_DATABASE=YP-U2 MP3 Player + +usb:v04E8p5051* + ID_MODEL_FROM_DATABASE=YP-F2R + +usb:v04E8p5055* + ID_MODEL_FROM_DATABASE=YP-T9 + +usb:v04E8p507D* + ID_MODEL_FROM_DATABASE=YP-U3 (mtp) + +usb:v04E8p507F* + ID_MODEL_FROM_DATABASE=YP-T9J + +usb:v04E8p5080* + ID_MODEL_FROM_DATABASE=Yepp YP-K3 (msc) + +usb:v04E8p5081* + ID_MODEL_FROM_DATABASE=Yepp YP-K3 (mtp) + +usb:v04E8p5082* + ID_MODEL_FROM_DATABASE=YP-P2 (msc) + +usb:v04E8p5083* + ID_MODEL_FROM_DATABASE=YP-P2 (mtp) + +usb:v04E8p508A* + ID_MODEL_FROM_DATABASE=YP-T10 + +usb:v04E8p508B* + ID_MODEL_FROM_DATABASE=YP-S5 MP3 Player + +usb:v04E8p508C* + ID_MODEL_FROM_DATABASE=YP-S5 + +usb:v04E8p5090* + ID_MODEL_FROM_DATABASE=YP-S3 (msc) + +usb:v04E8p5091* + ID_MODEL_FROM_DATABASE=YP-S3 (mtp) + +usb:v04E8p5092* + ID_MODEL_FROM_DATABASE=YP-U4 (msc) + +usb:v04E8p5093* + ID_MODEL_FROM_DATABASE=YP-U4 (mtp) + +usb:v04E8p5095* + ID_MODEL_FROM_DATABASE=YP-S2 + +usb:v04E8p510F* + ID_MODEL_FROM_DATABASE=YP-R1 + +usb:v04E8p5119* + ID_MODEL_FROM_DATABASE=Yepp YP-P3 + +usb:v04E8p511C* + ID_MODEL_FROM_DATABASE=YP-Q2 + +usb:v04E8p5121* + ID_MODEL_FROM_DATABASE=YP-U5 + +usb:v04E8p5123* + ID_MODEL_FROM_DATABASE=Yepp YP-M1 + +usb:v04E8p5A00* + ID_MODEL_FROM_DATABASE=YP-NEU + +usb:v04E8p5A01* + ID_MODEL_FROM_DATABASE=YP-NDU + +usb:v04E8p5A03* + ID_MODEL_FROM_DATABASE=Yepp MP3 Player + +usb:v04E8p5A04* + ID_MODEL_FROM_DATABASE=YP-800 + +usb:v04E8p5A08* + ID_MODEL_FROM_DATABASE=YP-90 + +usb:v04E8p5A0F* + ID_MODEL_FROM_DATABASE=Meizu M6 MiniPlayer + +usb:v04E8p5B01* + ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer + +usb:v04E8p5B02* + ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer + +usb:v04E8p5B03* + ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer + +usb:v04E8p5B04* + ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer + +usb:v04E8p5B05* + ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer + +usb:v04E8p5B11* + ID_MODEL_FROM_DATABASE=SEW-2001u Card + +usb:v04E8p5F00* + ID_MODEL_FROM_DATABASE=NEXiO Sync + +usb:v04E8p5F01* + ID_MODEL_FROM_DATABASE=NEXiO Sync + +usb:v04E8p5F02* + ID_MODEL_FROM_DATABASE=NEXiO Sync + +usb:v04E8p5F03* + ID_MODEL_FROM_DATABASE=NEXiO Sync + +usb:v04E8p5F04* + ID_MODEL_FROM_DATABASE=NEXiO Sync + +usb:v04E8p5F05* + ID_MODEL_FROM_DATABASE=STORY Station 1TB + +usb:v04E8p6032* + ID_MODEL_FROM_DATABASE=G2 Portable hard drive + +usb:v04E8p6033* + ID_MODEL_FROM_DATABASE=G2 Portable device + +usb:v04E8p6034* + ID_MODEL_FROM_DATABASE=G2 Portable hard drive + +usb:v04E8p60B3* + ID_MODEL_FROM_DATABASE=M2 Portable Hard Drive + +usb:v04E8p60C4* + ID_MODEL_FROM_DATABASE=M2 Portable Hard Drive USB 3.0 + +usb:v04E8p6124* + ID_MODEL_FROM_DATABASE=D3 Station External Hard Drive + +usb:v04E8p6125* + ID_MODEL_FROM_DATABASE=D3 Station External Hard Drive + +usb:v04E8p61B5* + ID_MODEL_FROM_DATABASE=M3 Portable Hard Drive 2TB + +usb:v04E8p61B6* + ID_MODEL_FROM_DATABASE=M3 Portable Hard Drive 1TB + +usb:v04E8p61B7* + ID_MODEL_FROM_DATABASE=M3 Portable Hard Drive 4TB + +usb:v04E8p61F3* + ID_MODEL_FROM_DATABASE=Portable SSD T3 (MU-PT250B, MU-PT500B) + +usb:v04E8p61F5* + ID_MODEL_FROM_DATABASE=Portable SSD T5 + +usb:v04E8p6601* + ID_MODEL_FROM_DATABASE=Mobile Phone + +usb:v04E8p6602* + ID_MODEL_FROM_DATABASE=Galaxy + +usb:v04E8p6603* + ID_MODEL_FROM_DATABASE=Galaxy + +usb:v04E8p6611* + ID_MODEL_FROM_DATABASE=MITs Sync + +usb:v04E8p6613* + ID_MODEL_FROM_DATABASE=MITs Sync + +usb:v04E8p6615* + ID_MODEL_FROM_DATABASE=MITs Sync + +usb:v04E8p6617* + ID_MODEL_FROM_DATABASE=MITs Sync + +usb:v04E8p6619* + ID_MODEL_FROM_DATABASE=MITs Sync + +usb:v04E8p661B* + ID_MODEL_FROM_DATABASE=MITs Sync + +usb:v04E8p661E* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v04E8p6620* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v04E8p6622* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v04E8p6624* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v04E8p662E* + ID_MODEL_FROM_DATABASE=MITs Sync + +usb:v04E8p6630* + ID_MODEL_FROM_DATABASE=MITs Sync + +usb:v04E8p6632* + ID_MODEL_FROM_DATABASE=MITs Sync + +usb:v04E8p663E* + ID_MODEL_FROM_DATABASE=D900e/B2100 Phone + +usb:v04E8p663F* + ID_MODEL_FROM_DATABASE=SGH-E720/SGH-E840 + +usb:v04E8p6640* + ID_MODEL_FROM_DATABASE=Usb Modem Enumerator + +usb:v04E8p6651* + ID_MODEL_FROM_DATABASE=i8510 Innov8 + +usb:v04E8p6702* + ID_MODEL_FROM_DATABASE=X830 + +usb:v04E8p6708* + ID_MODEL_FROM_DATABASE=U600 Phone + +usb:v04E8p6709* + ID_MODEL_FROM_DATABASE=U600 + +usb:v04E8p6734* + ID_MODEL_FROM_DATABASE=Juke + +usb:v04E8p6759* + ID_MODEL_FROM_DATABASE=D900e/B2100 Media Player + +usb:v04E8p675A* + ID_MODEL_FROM_DATABASE=D900e/B2100 Mass Storage + +usb:v04E8p675B* + ID_MODEL_FROM_DATABASE=D900e Camera + +usb:v04E8p6772* + ID_MODEL_FROM_DATABASE=Standalone LTE device (Trial) + +usb:v04E8p6795* + ID_MODEL_FROM_DATABASE=S5230 + +usb:v04E8p6802* + ID_MODEL_FROM_DATABASE=Standalone HSPA device + +usb:v04E8p6806* + ID_MODEL_FROM_DATABASE=Composite LTE device (Trial) + +usb:v04E8p6807* + ID_MODEL_FROM_DATABASE=Composite HSPA device + +usb:v04E8p681C* + ID_MODEL_FROM_DATABASE=Galaxy Portal/Spica/S + +usb:v04E8p681D* + ID_MODEL_FROM_DATABASE=Galaxy Portal/Spica Android Phone + +usb:v04E8p6843* + ID_MODEL_FROM_DATABASE=E2530 Phone (Samsung Kies mode) + +usb:v04E8p684E* + ID_MODEL_FROM_DATABASE=Wave (GT-S8500) + +usb:v04E8p685B* + ID_MODEL_FROM_DATABASE=GT-I9100 Phone [Galaxy S II] (mass storage mode) + +usb:v04E8p685C* + ID_MODEL_FROM_DATABASE=GT-I9250 Phone [Galaxy Nexus] (Mass storage mode) + +usb:v04E8p685D* + ID_MODEL_FROM_DATABASE=GT-I9100 Phone [Galaxy S II] (Download mode) + +usb:v04E8p685E* + ID_MODEL_FROM_DATABASE=GT-I9100 / GT-C3350 Phones (USB Debugging mode) + +usb:v04E8p6860* + ID_MODEL_FROM_DATABASE=Galaxy series, misc. (MTP mode) + +usb:v04E8p6863* + ID_MODEL_FROM_DATABASE=Galaxy series, misc. (tethering mode) + +usb:v04E8p6864* + ID_MODEL_FROM_DATABASE=GT-I9070 (network tethering, USB debugging enabled) + +usb:v04E8p6865* + ID_MODEL_FROM_DATABASE=Galaxy (PTP mode) + +usb:v04E8p6866* + ID_MODEL_FROM_DATABASE=Galaxy (debugging mode) + +usb:v04E8p6868* + ID_MODEL_FROM_DATABASE=Escape Composite driver for Android Phones: Modem+Diagnostic+ADB + +usb:v04E8p6875* + ID_MODEL_FROM_DATABASE=GT-B3710 Standalone LTE device (Commercial) + +usb:v04E8p6876* + ID_MODEL_FROM_DATABASE=GT-B3710 LTE Modem + +usb:v04E8p6877* + ID_MODEL_FROM_DATABASE=Galaxy S + +usb:v04E8p687A* + ID_MODEL_FROM_DATABASE=GT-E2370 mobile phone + +usb:v04E8p6888* + ID_MODEL_FROM_DATABASE=GT-B3730 Composite LTE device (Commercial) + +usb:v04E8p6889* + ID_MODEL_FROM_DATABASE=GT-B3730 Composite LTE device (Commercial) + +usb:v04E8p689A* + ID_MODEL_FROM_DATABASE=LTE Storage Driver [CMC2xx] + +usb:v04E8p689E* + ID_MODEL_FROM_DATABASE=GT-S5670 [Galaxy Fit] + +usb:v04E8p68AA* + ID_MODEL_FROM_DATABASE=Reality + +usb:v04E8p7011* + ID_MODEL_FROM_DATABASE=SEW-2003U Card + +usb:v04E8p7021* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v04E8p7061* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v04E8p7080* + ID_MODEL_FROM_DATABASE=Anycall SCH-W580 + +usb:v04E8p7081* + ID_MODEL_FROM_DATABASE=Human Interface Device + +usb:v04E8p7301* + ID_MODEL_FROM_DATABASE=Fingerprint Device + +usb:v04E8p8001* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v04E8pD003* + ID_MODEL_FROM_DATABASE=GT-I9003 + +usb:v04E8pE020* + ID_MODEL_FROM_DATABASE=SERI E02 SCOM 6200 UMTS Phone + +usb:v04E8pE021* + ID_MODEL_FROM_DATABASE=SERI E02 SCOM 6200 Virtual UARTs + +usb:v04E8pE022* + ID_MODEL_FROM_DATABASE=SERI E02 SCOM 6200 Flash Load Disk + +usb:v04E8pF000* + ID_MODEL_FROM_DATABASE=Intensity 3 (Mass Storage Mode) + +usb:v04E8pFF30* + ID_MODEL_FROM_DATABASE=SG_iMON + +usb:v04E9* + ID_VENDOR_FROM_DATABASE=PC-Tel, Inc. + +usb:v04EA* + ID_VENDOR_FROM_DATABASE=Brooktree Corp. + +usb:v04EB* + ID_VENDOR_FROM_DATABASE=Northstar Systems, Inc. + +usb:v04EBpE004* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v04EC* + ID_VENDOR_FROM_DATABASE=Tokyo Electron Device, Ltd + +usb:v04ED* + ID_VENDOR_FROM_DATABASE=Annabooks + +usb:v04EF* + ID_VENDOR_FROM_DATABASE=Pacific Electronic International, Inc. + +usb:v04F0* + ID_VENDOR_FROM_DATABASE=Daewoo Electronics Co., Ltd + +usb:v04F1* + ID_VENDOR_FROM_DATABASE=Victor Company of Japan, Ltd + +usb:v04F1p0001* + ID_MODEL_FROM_DATABASE=GC-QX3 Digital Still Camera + +usb:v04F1p0004* + ID_MODEL_FROM_DATABASE=GR-DVL815U Digital Video Camera + +usb:v04F1p0006* + ID_MODEL_FROM_DATABASE=DV Camera Storage + +usb:v04F1p0008* + ID_MODEL_FROM_DATABASE=GZ-MG30AA/MC500E Digital Video Camera + +usb:v04F1p0009* + ID_MODEL_FROM_DATABASE=GR-DX25EK Digital Video Camera + +usb:v04F1p000A* + ID_MODEL_FROM_DATABASE=GR-D72 Digital Video Camera + +usb:v04F1p1001* + ID_MODEL_FROM_DATABASE=GC-A50 Camera Device + +usb:v04F1p3008* + ID_MODEL_FROM_DATABASE=MP-PRX1 Ethernet + +usb:v04F1p3009* + ID_MODEL_FROM_DATABASE=MP-XP7250 WLAN Adapter + +usb:v04F2* + ID_VENDOR_FROM_DATABASE=Chicony Electronics Co., Ltd + +usb:v04F2p0001* + ID_MODEL_FROM_DATABASE=KU-8933 Keyboard + +usb:v04F2p0002* + ID_MODEL_FROM_DATABASE=NT68P81 Keyboard + +usb:v04F2p0110* + ID_MODEL_FROM_DATABASE=KU-2971 Keyboard + +usb:v04F2p0111* + ID_MODEL_FROM_DATABASE=KU-9908 Keyboard + +usb:v04F2p0112* + ID_MODEL_FROM_DATABASE=KU-8933 Keyboard with PS/2 Mouse port + +usb:v04F2p0116* + ID_MODEL_FROM_DATABASE=KU-2971/KU-0325 Keyboard + +usb:v04F2p0200* + ID_MODEL_FROM_DATABASE=KBR-0108 + +usb:v04F2p0201* + ID_MODEL_FROM_DATABASE=Gaming Keyboard KPD0250 + +usb:v04F2p0220* + ID_MODEL_FROM_DATABASE=Wireless HID Receiver + +usb:v04F2p0402* + ID_MODEL_FROM_DATABASE=Genius LuxeMate i200 Keyboard + +usb:v04F2p0403* + ID_MODEL_FROM_DATABASE=KU-0420 keyboard + +usb:v04F2p0418* + ID_MODEL_FROM_DATABASE=KU-0418 Tactical Pad + +usb:v04F2p0618* + ID_MODEL_FROM_DATABASE=RG-0618U Wireless HID Receiver & KG-0609 Wireless Keyboard with Touchpad + +usb:v04F2p0718* + ID_MODEL_FROM_DATABASE=wired mouse + +usb:v04F2p0760* + ID_MODEL_FROM_DATABASE=Acer KU-0760 Keyboard + +usb:v04F2p0833* + ID_MODEL_FROM_DATABASE=KU-0833 Keyboard + +usb:v04F2p0841* + ID_MODEL_FROM_DATABASE=HP Multimedia Keyboard + +usb:v04F2p0860* + ID_MODEL_FROM_DATABASE=2.4G Multimedia Wireless Kit + +usb:v04F2p1061* + ID_MODEL_FROM_DATABASE=HP KG-1061 Wireless Keyboard+Mouse + +usb:v04F2p1121* + ID_MODEL_FROM_DATABASE=Periboard 717 Mini Wireless Keyboard + +usb:v04F2pA001* + ID_MODEL_FROM_DATABASE=E-Video DC-100 Camera + +usb:v04F2pA120* + ID_MODEL_FROM_DATABASE=ORITE CCD Webcam(PC370R) + +usb:v04F2pA121* + ID_MODEL_FROM_DATABASE=ORITE CCD Webcam(PC370R) + +usb:v04F2pA122* + ID_MODEL_FROM_DATABASE=ORITE CCD Webcam(PC370R) + +usb:v04F2pA123* + ID_MODEL_FROM_DATABASE=ORITE CCD Webcam(PC370R) + +usb:v04F2pA124* + ID_MODEL_FROM_DATABASE=ORITE CCD Webcam(PC370R) + +usb:v04F2pA128* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C202 + OV7663 + EEPROM) + +usb:v04F2pA133* + ID_MODEL_FROM_DATABASE=Gateway Webcam + +usb:v04F2pA136* + ID_MODEL_FROM_DATABASE=LabTec Webcam 5500 + +usb:v04F2pA147* + ID_MODEL_FROM_DATABASE=Medion Webcam + +usb:v04F2pA204* + ID_MODEL_FROM_DATABASE=DSC WIA Device (1300) + +usb:v04F2pA208* + ID_MODEL_FROM_DATABASE=DSC WIA Device (2320) + +usb:v04F2pA209* + ID_MODEL_FROM_DATABASE=Labtec DC-2320 + +usb:v04F2pA20A* + ID_MODEL_FROM_DATABASE=DSC WIA Device (3310) + +usb:v04F2pA20C* + ID_MODEL_FROM_DATABASE=DSC WIA Device (3320) + +usb:v04F2pA210* + ID_MODEL_FROM_DATABASE=Audio Device + +usb:v04F2pB008* + ID_MODEL_FROM_DATABASE=USB 2.0 Camera + +usb:v04F2pB009* + ID_MODEL_FROM_DATABASE=Integrated Camera + +usb:v04F2pB010* + ID_MODEL_FROM_DATABASE=Integrated Camera + +usb:v04F2pB012* + ID_MODEL_FROM_DATABASE=1.3 MPixel UVC Webcam + +usb:v04F2pB013* + ID_MODEL_FROM_DATABASE=USB 2.0 Camera + +usb:v04F2pB015* + ID_MODEL_FROM_DATABASE=VGA 24fps UVC Webcam + +usb:v04F2pB016* + ID_MODEL_FROM_DATABASE=VGA 30fps UVC Webcam + +usb:v04F2pB018* + ID_MODEL_FROM_DATABASE=2M UVC Webcam + +usb:v04F2pB021* + ID_MODEL_FROM_DATABASE=ViewSonic 1.3M, USB2.0 Webcam + +usb:v04F2pB022* + ID_MODEL_FROM_DATABASE=Gateway USB 2.0 Webcam + +usb:v04F2pB023* + ID_MODEL_FROM_DATABASE=Gateway USB 2.0 Webcam + +usb:v04F2pB024* + ID_MODEL_FROM_DATABASE=USB 2.0 Webcam + +usb:v04F2pB025* + ID_MODEL_FROM_DATABASE=Camera + +usb:v04F2pB027* + ID_MODEL_FROM_DATABASE=Gateway USB 2.0 Webcam + +usb:v04F2pB028* + ID_MODEL_FROM_DATABASE=VGA UVC Webcam + +usb:v04F2pB029* + ID_MODEL_FROM_DATABASE=1.3M UVC Webcam + +usb:v04F2pB036* + ID_MODEL_FROM_DATABASE=Asus Integrated 0.3M UVC Webcam + +usb:v04F2pB044* + ID_MODEL_FROM_DATABASE=Acer CrystalEye Webcam + +usb:v04F2pB057* + ID_MODEL_FROM_DATABASE=integrated USB webcam + +usb:v04F2pB059* + ID_MODEL_FROM_DATABASE=CKF7037 HP webcam + +usb:v04F2pB064* + ID_MODEL_FROM_DATABASE=CNA7137 Integrated Webcam + +usb:v04F2pB070* + ID_MODEL_FROM_DATABASE=Camera + +usb:v04F2pB071* + ID_MODEL_FROM_DATABASE=2.0M UVC Webcam / CNF7129 + +usb:v04F2pB083* + ID_MODEL_FROM_DATABASE=CKF7063 Webcam (HP) + +usb:v04F2pB091* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v04F2pB104* + ID_MODEL_FROM_DATABASE=CNF7069 Webcam + +usb:v04F2pB107* + ID_MODEL_FROM_DATABASE=CNF7070 Webcam + +usb:v04F2pB14C* + ID_MODEL_FROM_DATABASE=CNF8050 Webcam + +usb:v04F2pB159* + ID_MODEL_FROM_DATABASE=CNF8243 Webcam + +usb:v04F2pB15C* + ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Camera + +usb:v04F2pB175* + ID_MODEL_FROM_DATABASE=4-Port Hub + +usb:v04F2pB1AA* + ID_MODEL_FROM_DATABASE=Webcam-101 + +usb:v04F2pB1AC* + ID_MODEL_FROM_DATABASE=HP Laptop Integrated Webcam [2 MP Fixed] + +usb:v04F2pB1B4* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera + +usb:v04F2pB1B9* + ID_MODEL_FROM_DATABASE=Asus Integrated Webcam + +usb:v04F2pB1CF* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera + +usb:v04F2pB1D6* + ID_MODEL_FROM_DATABASE=CNF9055 Toshiba Webcam + +usb:v04F2pB1D8* + ID_MODEL_FROM_DATABASE=1.3M Webcam + +usb:v04F2pB1E4* + ID_MODEL_FROM_DATABASE=Toshiba Integrated Webcam + +usb:v04F2pB213* + ID_MODEL_FROM_DATABASE=Fujitsu Integrated Camera + +usb:v04F2pB217* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera (0.3MP) + +usb:v04F2pB221* + ID_MODEL_FROM_DATABASE=integrated camera + +usb:v04F2pB230* + ID_MODEL_FROM_DATABASE=Integrated HP HD Webcam + +usb:v04F2pB257* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera + +usb:v04F2pB26B* + ID_MODEL_FROM_DATABASE=Sony Visual Communication Camera + +usb:v04F2pB272* + ID_MODEL_FROM_DATABASE=Lenovo EasyCamera + +usb:v04F2pB2B0* + ID_MODEL_FROM_DATABASE=Camera + +usb:v04F2pB2B9* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Camera UVC + +usb:v04F2pB2DA* + ID_MODEL_FROM_DATABASE=thinkpad t430s camera + +usb:v04F2pB2DB* + ID_MODEL_FROM_DATABASE=Thinkpad T430 camera + +usb:v04F2pB2EA* + ID_MODEL_FROM_DATABASE=Integrated Camera [ThinkPad] + +usb:v04F2pB2F4* + ID_MODEL_FROM_DATABASE=HP Webcam-50 + +usb:v04F2pB330* + ID_MODEL_FROM_DATABASE=Asus 720p CMOS webcam + +usb:v04F2pB354* + ID_MODEL_FROM_DATABASE=UVC 1.00 device HD UVC WebCam + +usb:v04F2pB394* + ID_MODEL_FROM_DATABASE=Integrated Camera + +usb:v04F2pB3EB* + ID_MODEL_FROM_DATABASE=HP 720p HD Monitor Webcam + +usb:v04F2pB3F6* + ID_MODEL_FROM_DATABASE=HD WebCam (Acer) + +usb:v04F2pB3FD* + ID_MODEL_FROM_DATABASE=HD WebCam (Asus N-series) + +usb:v04F2pB40E* + ID_MODEL_FROM_DATABASE=HP Truevision HD camera + +usb:v04F2pB444* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam + +usb:v04F2pB563* + ID_MODEL_FROM_DATABASE=Integrated Camera + +usb:v04F2pB5CE* + ID_MODEL_FROM_DATABASE=Integrated Camera + +usb:v04F2pB5CF* + ID_MODEL_FROM_DATABASE=Integrated IR Camera + +usb:v04F2pB5DB* + ID_MODEL_FROM_DATABASE=HP Webcam + +usb:v04F2pB604* + ID_MODEL_FROM_DATABASE=Integrated Camera (1280x720@30) + +usb:v04F3* + ID_VENDOR_FROM_DATABASE=Elan Microelectronics Corp. + +usb:v04F3p000A* + ID_MODEL_FROM_DATABASE=Touchscreen + +usb:v04F3p0103* + ID_MODEL_FROM_DATABASE=ActiveJet K-2024 Multimedia Keyboard + +usb:v04F3p016F* + ID_MODEL_FROM_DATABASE=Touchscreen + +usb:v04F3p01A4* + ID_MODEL_FROM_DATABASE=Wireless Keyboard + +usb:v04F3p0201* + ID_MODEL_FROM_DATABASE=Touchscreen + +usb:v04F3p0210* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v04F3p0212* + ID_MODEL_FROM_DATABASE=Laser Mouse + +usb:v04F3p0214* + ID_MODEL_FROM_DATABASE=Lynx M9 Optical Mouse + +usb:v04F3p0230* + ID_MODEL_FROM_DATABASE=3D Optical Mouse + +usb:v04F3p0232* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v04F3p0234* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v04F3p0235* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v04F3p02F4* + ID_MODEL_FROM_DATABASE=2.4G Cordless Mouse + +usb:v04F3p0381* + ID_MODEL_FROM_DATABASE=Touchscreen + +usb:v04F3p04A0* + ID_MODEL_FROM_DATABASE=Dream Cheeky Stress/Panic Button + +usb:v04F3p2234* + ID_MODEL_FROM_DATABASE=Touchscreen + +usb:v04F4* + ID_VENDOR_FROM_DATABASE=Harting Elektronik, Inc. + +usb:v04F5* + ID_VENDOR_FROM_DATABASE=Fujitsu-ICL Systems, Inc. + +usb:v04F6* + ID_VENDOR_FROM_DATABASE=Norand Corp. + +usb:v04F7* + ID_VENDOR_FROM_DATABASE=Newnex Technology Corp. + +usb:v04F8* + ID_VENDOR_FROM_DATABASE=FuturePlus Systems + +usb:v04F9* + ID_VENDOR_FROM_DATABASE=Brother Industries, Ltd + +usb:v04F9p0002* + ID_MODEL_FROM_DATABASE=HL-1050 Laser Printer + +usb:v04F9p0005* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0006* + ID_MODEL_FROM_DATABASE=HL-1240 Laser Printer + +usb:v04F9p0007* + ID_MODEL_FROM_DATABASE=HL-1250 Laser Printer + +usb:v04F9p0008* + ID_MODEL_FROM_DATABASE=HL-1270 Laser Printer + +usb:v04F9p0009* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p000A* + ID_MODEL_FROM_DATABASE=P2500 series + +usb:v04F9p000B* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p000C* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p000D* + ID_MODEL_FROM_DATABASE=HL-1440 Laser Printer + +usb:v04F9p000E* + ID_MODEL_FROM_DATABASE=HL-1450 series + +usb:v04F9p000F* + ID_MODEL_FROM_DATABASE=HL-1470N series + +usb:v04F9p0010* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0011* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0012* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0013* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0014* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0015* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0016* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0017* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0018* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p001A* + ID_MODEL_FROM_DATABASE=HL-1430 Laser Printer + +usb:v04F9p001C* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p001E* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0020* + ID_MODEL_FROM_DATABASE=HL-5130 series + +usb:v04F9p0021* + ID_MODEL_FROM_DATABASE=HL-5140 series + +usb:v04F9p0022* + ID_MODEL_FROM_DATABASE=HL-5150D series + +usb:v04F9p0023* + ID_MODEL_FROM_DATABASE=HL-5170DN series + +usb:v04F9p0024* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0025* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0027* + ID_MODEL_FROM_DATABASE=HL-2030 Laser Printer + +usb:v04F9p0028* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0029* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p002A* + ID_MODEL_FROM_DATABASE=HL-52x0 series + +usb:v04F9p002B* + ID_MODEL_FROM_DATABASE=HL-5250DN Printer + +usb:v04F9p002C* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p002D* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p0039* + ID_MODEL_FROM_DATABASE=HL-5340 series + +usb:v04F9p0041* + ID_MODEL_FROM_DATABASE=HL-2250DN Laser Printer + +usb:v04F9p0042* + ID_MODEL_FROM_DATABASE=HL-2270DW Laser Printer + +usb:v04F9p0100* + ID_MODEL_FROM_DATABASE=MFC8600/9650 series + +usb:v04F9p0101* + ID_MODEL_FROM_DATABASE=MFC9600/9870 series + +usb:v04F9p0102* + ID_MODEL_FROM_DATABASE=MFC9750/1200 series + +usb:v04F9p0104* + ID_MODEL_FROM_DATABASE=MFC-8300J + +usb:v04F9p0105* + ID_MODEL_FROM_DATABASE=MFC-9600J + +usb:v04F9p0106* + ID_MODEL_FROM_DATABASE=MFC-7300C + +usb:v04F9p0107* + ID_MODEL_FROM_DATABASE=MFC-7400C + +usb:v04F9p0108* + ID_MODEL_FROM_DATABASE=MFC-9200C + +usb:v04F9p0109* + ID_MODEL_FROM_DATABASE=MFC-830 + +usb:v04F9p010A* + ID_MODEL_FROM_DATABASE=MFC-840 + +usb:v04F9p010B* + ID_MODEL_FROM_DATABASE=MFC-860 + +usb:v04F9p010C* + ID_MODEL_FROM_DATABASE=MFC-7400J + +usb:v04F9p010D* + ID_MODEL_FROM_DATABASE=MFC-9200J + +usb:v04F9p010E* + ID_MODEL_FROM_DATABASE=MFC-3100C Scanner + +usb:v04F9p010F* + ID_MODEL_FROM_DATABASE=MFC-5100C + +usb:v04F9p0110* + ID_MODEL_FROM_DATABASE=MFC-4800 Scanner + +usb:v04F9p0111* + ID_MODEL_FROM_DATABASE=MFC-6800 + +usb:v04F9p0112* + ID_MODEL_FROM_DATABASE=DCP1000 Port(FaxModem) + +usb:v04F9p0113* + ID_MODEL_FROM_DATABASE=MFC-8500 + +usb:v04F9p0114* + ID_MODEL_FROM_DATABASE=MFC9700 Port(FaxModem) + +usb:v04F9p0115* + ID_MODEL_FROM_DATABASE=MFC-9800 Scanner + +usb:v04F9p0116* + ID_MODEL_FROM_DATABASE=DCP1400 Scanner + +usb:v04F9p0119* + ID_MODEL_FROM_DATABASE=MFC-9660 + +usb:v04F9p011A* + ID_MODEL_FROM_DATABASE=MFC-9860 + +usb:v04F9p011B* + ID_MODEL_FROM_DATABASE=MFC-9880 + +usb:v04F9p011C* + ID_MODEL_FROM_DATABASE=MFC-9760 + +usb:v04F9p011D* + ID_MODEL_FROM_DATABASE=MFC-9070 + +usb:v04F9p011E* + ID_MODEL_FROM_DATABASE=MFC-9180 + +usb:v04F9p011F* + ID_MODEL_FROM_DATABASE=MFC-9160 + +usb:v04F9p0120* + ID_MODEL_FROM_DATABASE=MFC580 Port(FaxModem) + +usb:v04F9p0121* + ID_MODEL_FROM_DATABASE=MFC-590 + +usb:v04F9p0122* + ID_MODEL_FROM_DATABASE=MFC-5100J + +usb:v04F9p0124* + ID_MODEL_FROM_DATABASE=MFC-4800J + +usb:v04F9p0125* + ID_MODEL_FROM_DATABASE=MFC-6800J + +usb:v04F9p0127* + ID_MODEL_FROM_DATABASE=MFC-9800J + +usb:v04F9p0128* + ID_MODEL_FROM_DATABASE=MFC-8500J + +usb:v04F9p0129* + ID_MODEL_FROM_DATABASE=Imagistics 2500 (MFC-8640D clone) + +usb:v04F9p012B* + ID_MODEL_FROM_DATABASE=MFC-9030 + +usb:v04F9p012E* + ID_MODEL_FROM_DATABASE=FAX4100e IntelliFax 4100e + +usb:v04F9p012F* + ID_MODEL_FROM_DATABASE=FAX-4750e + +usb:v04F9p0130* + ID_MODEL_FROM_DATABASE=FAX-5750e + +usb:v04F9p0132* + ID_MODEL_FROM_DATABASE=MFC-5200C RemovableDisk + +usb:v04F9p0135* + ID_MODEL_FROM_DATABASE=MFC-100 Scanner + +usb:v04F9p0136* + ID_MODEL_FROM_DATABASE=MFC-150CL Scanner + +usb:v04F9p013C* + ID_MODEL_FROM_DATABASE=MFC-890 Port + +usb:v04F9p013D* + ID_MODEL_FROM_DATABASE=MFC-5200J + +usb:v04F9p013E* + ID_MODEL_FROM_DATABASE=MFC-4420C RemovableDisk + +usb:v04F9p013F* + ID_MODEL_FROM_DATABASE=MFC-4820C RemovableDisk + +usb:v04F9p0140* + ID_MODEL_FROM_DATABASE=DCP-8020 + +usb:v04F9p0141* + ID_MODEL_FROM_DATABASE=DCP-8025D + +usb:v04F9p0142* + ID_MODEL_FROM_DATABASE=MFC-8420 + +usb:v04F9p0143* + ID_MODEL_FROM_DATABASE=MFC-8820D + +usb:v04F9p0144* + ID_MODEL_FROM_DATABASE=DCP-4020C RemovableDisk + +usb:v04F9p0146* + ID_MODEL_FROM_DATABASE=MFC-3220C + +usb:v04F9p0147* + ID_MODEL_FROM_DATABASE=FAX-1820C Printer + +usb:v04F9p0148* + ID_MODEL_FROM_DATABASE=MFC-3320CN + +usb:v04F9p0149* + ID_MODEL_FROM_DATABASE=FAX-1920CN Printer + +usb:v04F9p014A* + ID_MODEL_FROM_DATABASE=MFC-3420C + +usb:v04F9p014B* + ID_MODEL_FROM_DATABASE=MFC-3820CN + +usb:v04F9p014C* + ID_MODEL_FROM_DATABASE=DCP-3020C + +usb:v04F9p014D* + ID_MODEL_FROM_DATABASE=FAX-1815C Printer + +usb:v04F9p014E* + ID_MODEL_FROM_DATABASE=MFC-8820J + +usb:v04F9p014F* + ID_MODEL_FROM_DATABASE=DCP-8025J + +usb:v04F9p0150* + ID_MODEL_FROM_DATABASE=MFC-8220 Port(FaxModem) + +usb:v04F9p0151* + ID_MODEL_FROM_DATABASE=MFC-8210J + +usb:v04F9p0153* + ID_MODEL_FROM_DATABASE=DCP-1000J + +usb:v04F9p0157* + ID_MODEL_FROM_DATABASE=MFC-3420J Printer + +usb:v04F9p0158* + ID_MODEL_FROM_DATABASE=MFC-3820JN Port(FaxModem) + +usb:v04F9p015D* + ID_MODEL_FROM_DATABASE=MFC Composite Device + +usb:v04F9p015E* + ID_MODEL_FROM_DATABASE=DCP-8045D + +usb:v04F9p015F* + ID_MODEL_FROM_DATABASE=MFC-8440 + +usb:v04F9p0160* + ID_MODEL_FROM_DATABASE=MFC-8840D + +usb:v04F9p0161* + ID_MODEL_FROM_DATABASE=MFC-210C + +usb:v04F9p0162* + ID_MODEL_FROM_DATABASE=MFC-420CN Remote Setup Port + +usb:v04F9p0163* + ID_MODEL_FROM_DATABASE=MFC-410CN RemovableDisk + +usb:v04F9p0165* + ID_MODEL_FROM_DATABASE=MFC-620CN + +usb:v04F9p0166* + ID_MODEL_FROM_DATABASE=MFC-610CLN RemovableDisk + +usb:v04F9p0168* + ID_MODEL_FROM_DATABASE=MFC-620CLN + +usb:v04F9p0169* + ID_MODEL_FROM_DATABASE=DCP-110C RemovableDisk + +usb:v04F9p016B* + ID_MODEL_FROM_DATABASE=DCP-310CN RemovableDisk + +usb:v04F9p016C* + ID_MODEL_FROM_DATABASE=FAX-2440C Printer + +usb:v04F9p016D* + ID_MODEL_FROM_DATABASE=MFC-5440CN + +usb:v04F9p016E* + ID_MODEL_FROM_DATABASE=MFC-5840CN Remote Setup Port + +usb:v04F9p0170* + ID_MODEL_FROM_DATABASE=FAX-1840C Printer + +usb:v04F9p0171* + ID_MODEL_FROM_DATABASE=FAX-1835C Printer + +usb:v04F9p0172* + ID_MODEL_FROM_DATABASE=FAX-1940CN Printer + +usb:v04F9p0173* + ID_MODEL_FROM_DATABASE=MFC-3240C Remote Setup Port + +usb:v04F9p0174* + ID_MODEL_FROM_DATABASE=MFC-3340CN RemovableDisk + +usb:v04F9p017B* + ID_MODEL_FROM_DATABASE=Imagistics sx2100 + +usb:v04F9p0180* + ID_MODEL_FROM_DATABASE=MFC-7420 + +usb:v04F9p0181* + ID_MODEL_FROM_DATABASE=MFC-7820N Port(FaxModem) + +usb:v04F9p0182* + ID_MODEL_FROM_DATABASE=DCP-7010 + +usb:v04F9p0183* + ID_MODEL_FROM_DATABASE=DCP-7020 + +usb:v04F9p0184* + ID_MODEL_FROM_DATABASE=DCP-7025 Printer + +usb:v04F9p0185* + ID_MODEL_FROM_DATABASE=MFC-7220 Printer + +usb:v04F9p0186* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v04F9p0187* + ID_MODEL_FROM_DATABASE=FAX-2820 Printer + +usb:v04F9p0188* + ID_MODEL_FROM_DATABASE=FAX-2920 Printer + +usb:v04F9p018A* + ID_MODEL_FROM_DATABASE=MFC-9420CN + +usb:v04F9p018C* + ID_MODEL_FROM_DATABASE=DCP-115C + +usb:v04F9p018D* + ID_MODEL_FROM_DATABASE=DCP-116C + +usb:v04F9p018E* + ID_MODEL_FROM_DATABASE=DCP-117C + +usb:v04F9p018F* + ID_MODEL_FROM_DATABASE=DCP-118C + +usb:v04F9p0190* + ID_MODEL_FROM_DATABASE=DCP-120C + +usb:v04F9p0191* + ID_MODEL_FROM_DATABASE=DCP-315CN + +usb:v04F9p0192* + ID_MODEL_FROM_DATABASE=DCP-340CW + +usb:v04F9p0193* + ID_MODEL_FROM_DATABASE=MFC-215C + +usb:v04F9p0194* + ID_MODEL_FROM_DATABASE=MFC-425CN + +usb:v04F9p0195* + ID_MODEL_FROM_DATABASE=MFC-820CW Remote Setup Port + +usb:v04F9p0196* + ID_MODEL_FROM_DATABASE=MFC-820CN Remote Setup Port + +usb:v04F9p0197* + ID_MODEL_FROM_DATABASE=MFC-640CW + +usb:v04F9p019A* + ID_MODEL_FROM_DATABASE=MFC-840CLN Remote Setup Port + +usb:v04F9p01A2* + ID_MODEL_FROM_DATABASE=MFC-8640D + +usb:v04F9p01A3* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v04F9p01A4* + ID_MODEL_FROM_DATABASE=DCP-8065DN Printer + +usb:v04F9p01A5* + ID_MODEL_FROM_DATABASE=MFC-8460N Port(FaxModem) + +usb:v04F9p01A6* + ID_MODEL_FROM_DATABASE=MFC-8860DN Port(FaxModem) + +usb:v04F9p01A7* + ID_MODEL_FROM_DATABASE=MFC-8870DW Printer + +usb:v04F9p01A8* + ID_MODEL_FROM_DATABASE=DCP-130C + +usb:v04F9p01A9* + ID_MODEL_FROM_DATABASE=DCP-330C + +usb:v04F9p01AA* + ID_MODEL_FROM_DATABASE=DCP-540CN + +usb:v04F9p01AB* + ID_MODEL_FROM_DATABASE=MFC-240C + +usb:v04F9p01AE* + ID_MODEL_FROM_DATABASE=DCP-750CW RemovableDisk + +usb:v04F9p01AF* + ID_MODEL_FROM_DATABASE=MFC-440CN + +usb:v04F9p01B0* + ID_MODEL_FROM_DATABASE=MFC-660CN + +usb:v04F9p01B1* + ID_MODEL_FROM_DATABASE=MFC-665CW + +usb:v04F9p01B2* + ID_MODEL_FROM_DATABASE=MFC-845CW + +usb:v04F9p01B4* + ID_MODEL_FROM_DATABASE=MFC-460CN + +usb:v04F9p01B5* + ID_MODEL_FROM_DATABASE=MFC-630CD + +usb:v04F9p01B6* + ID_MODEL_FROM_DATABASE=MFC-850CDN + +usb:v04F9p01B7* + ID_MODEL_FROM_DATABASE=MFC-5460CN + +usb:v04F9p01B8* + ID_MODEL_FROM_DATABASE=MFC-5860CN + +usb:v04F9p01BA* + ID_MODEL_FROM_DATABASE=MFC-3360C + +usb:v04F9p01BD* + ID_MODEL_FROM_DATABASE=MFC-8660DN + +usb:v04F9p01BE* + ID_MODEL_FROM_DATABASE=DCP-750CN RemovableDisk + +usb:v04F9p01BF* + ID_MODEL_FROM_DATABASE=MFC-860CDN + +usb:v04F9p01C0* + ID_MODEL_FROM_DATABASE=DCP-128C + +usb:v04F9p01C1* + ID_MODEL_FROM_DATABASE=DCP-129C + +usb:v04F9p01C2* + ID_MODEL_FROM_DATABASE=DCP-131C + +usb:v04F9p01C3* + ID_MODEL_FROM_DATABASE=DCP-329C + +usb:v04F9p01C4* + ID_MODEL_FROM_DATABASE=DCP-331C + +usb:v04F9p01C5* + ID_MODEL_FROM_DATABASE=MFC-239C + +usb:v04F9p01C9* + ID_MODEL_FROM_DATABASE=DCP-9040CN + +usb:v04F9p01CA* + ID_MODEL_FROM_DATABASE=MFC-9440CN + +usb:v04F9p01CB* + ID_MODEL_FROM_DATABASE=DCP-9045CDN + +usb:v04F9p01CC* + ID_MODEL_FROM_DATABASE=MFC-9840CDW + +usb:v04F9p01CE* + ID_MODEL_FROM_DATABASE=DCP-135C + +usb:v04F9p01CF* + ID_MODEL_FROM_DATABASE=DCP-150C + +usb:v04F9p01D0* + ID_MODEL_FROM_DATABASE=DCP-350C + +usb:v04F9p01D1* + ID_MODEL_FROM_DATABASE=DCP-560CN + +usb:v04F9p01D2* + ID_MODEL_FROM_DATABASE=DCP-770CW + +usb:v04F9p01D3* + ID_MODEL_FROM_DATABASE=DCP-770CN + +usb:v04F9p01D4* + ID_MODEL_FROM_DATABASE=MFC-230C + +usb:v04F9p01D5* + ID_MODEL_FROM_DATABASE=MFC-235C + +usb:v04F9p01D6* + ID_MODEL_FROM_DATABASE=MFC-260C + +usb:v04F9p01D7* + ID_MODEL_FROM_DATABASE=MFC-465CN + +usb:v04F9p01D8* + ID_MODEL_FROM_DATABASE=MFC-680CN + +usb:v04F9p01D9* + ID_MODEL_FROM_DATABASE=MFC-685CW + +usb:v04F9p01DA* + ID_MODEL_FROM_DATABASE=MFC-885CW + +usb:v04F9p01DB* + ID_MODEL_FROM_DATABASE=MFC-480CN + +usb:v04F9p01DC* + ID_MODEL_FROM_DATABASE=MFC-650CD + +usb:v04F9p01DD* + ID_MODEL_FROM_DATABASE=MFC-870CDN + +usb:v04F9p01DE* + ID_MODEL_FROM_DATABASE=MFC-880CDN + +usb:v04F9p01DF* + ID_MODEL_FROM_DATABASE=DCP-155C + +usb:v04F9p01E0* + ID_MODEL_FROM_DATABASE=MFC-265C + +usb:v04F9p01E1* + ID_MODEL_FROM_DATABASE=DCP-153C + +usb:v04F9p01E2* + ID_MODEL_FROM_DATABASE=DCP-157C + +usb:v04F9p01E3* + ID_MODEL_FROM_DATABASE=DCP-353C + +usb:v04F9p01E4* + ID_MODEL_FROM_DATABASE=DCP-357C + +usb:v04F9p01E7* + ID_MODEL_FROM_DATABASE=MFC-7340 + +usb:v04F9p01E9* + ID_MODEL_FROM_DATABASE=DCP-7040 + +usb:v04F9p01EA* + ID_MODEL_FROM_DATABASE=DCP-7030 + +usb:v04F9p01EB* + ID_MODEL_FROM_DATABASE=MFC-7320 + +usb:v04F9p01EC* + ID_MODEL_FROM_DATABASE=MFC-9640CW + +usb:v04F9p01F4* + ID_MODEL_FROM_DATABASE=MFC-5890CN + +usb:v04F9p020A* + ID_MODEL_FROM_DATABASE=MFC-8670DN + +usb:v04F9p020C* + ID_MODEL_FROM_DATABASE=DCP-9042CDN + +usb:v04F9p020D* + ID_MODEL_FROM_DATABASE=MFC-9450CDN + +usb:v04F9p0216* + ID_MODEL_FROM_DATABASE=MFC-8880DN + +usb:v04F9p0217* + ID_MODEL_FROM_DATABASE=MFC-8480DN + +usb:v04F9p0219* + ID_MODEL_FROM_DATABASE=MFC-8380DN + +usb:v04F9p021A* + ID_MODEL_FROM_DATABASE=MFC-8370DN + +usb:v04F9p021B* + ID_MODEL_FROM_DATABASE=DCP-8070D + +usb:v04F9p021C* + ID_MODEL_FROM_DATABASE=MFC-9320CW + +usb:v04F9p021D* + ID_MODEL_FROM_DATABASE=MFC-9120CN + +usb:v04F9p021E* + ID_MODEL_FROM_DATABASE=DCP-9010CN + +usb:v04F9p021F* + ID_MODEL_FROM_DATABASE=DCP-8085DN + +usb:v04F9p0220* + ID_MODEL_FROM_DATABASE=MFC-9010CN + +usb:v04F9p0222* + ID_MODEL_FROM_DATABASE=DCP-195C + +usb:v04F9p0223* + ID_MODEL_FROM_DATABASE=DCP-365CN + +usb:v04F9p0224* + ID_MODEL_FROM_DATABASE=DCP-375CW + +usb:v04F9p0225* + ID_MODEL_FROM_DATABASE=DCP-395CN + +usb:v04F9p0227* + ID_MODEL_FROM_DATABASE=DCP-595CN + +usb:v04F9p0228* + ID_MODEL_FROM_DATABASE=MFC-255CW + +usb:v04F9p0229* + ID_MODEL_FROM_DATABASE=MFC-295CN + +usb:v04F9p022A* + ID_MODEL_FROM_DATABASE=MFC-495CW + +usb:v04F9p022B* + ID_MODEL_FROM_DATABASE=MFC-495CN + +usb:v04F9p022C* + ID_MODEL_FROM_DATABASE=MFC-795CW + +usb:v04F9p022D* + ID_MODEL_FROM_DATABASE=MFC-675CD + +usb:v04F9p022E* + ID_MODEL_FROM_DATABASE=MFC-695CDN + +usb:v04F9p022F* + ID_MODEL_FROM_DATABASE=MFC-735CD + +usb:v04F9p0230* + ID_MODEL_FROM_DATABASE=MFC-935CDN + +usb:v04F9p0234* + ID_MODEL_FROM_DATABASE=DCP-373CW + +usb:v04F9p0235* + ID_MODEL_FROM_DATABASE=DCP-377CW + +usb:v04F9p0236* + ID_MODEL_FROM_DATABASE=DCP-390CN + +usb:v04F9p0239* + ID_MODEL_FROM_DATABASE=MFC-253CW + +usb:v04F9p023A* + ID_MODEL_FROM_DATABASE=MFC-257CW + +usb:v04F9p023E* + ID_MODEL_FROM_DATABASE=DCP-197C + +usb:v04F9p023F* + ID_MODEL_FROM_DATABASE=MFC-8680DN + +usb:v04F9p0240* + ID_MODEL_FROM_DATABASE=MFC-J950DN + +usb:v04F9p0248* + ID_MODEL_FROM_DATABASE=DCP-7055 scanner/printer + +usb:v04F9p024E* + ID_MODEL_FROM_DATABASE=MFC-7460DN + +usb:v04F9p0253* + ID_MODEL_FROM_DATABASE=DCP-J125 + +usb:v04F9p0254* + ID_MODEL_FROM_DATABASE=DCP-J315W + +usb:v04F9p0255* + ID_MODEL_FROM_DATABASE=DCP-J515W + +usb:v04F9p0256* + ID_MODEL_FROM_DATABASE=DCP-J515N + +usb:v04F9p0257* + ID_MODEL_FROM_DATABASE=DCP-J715W + +usb:v04F9p0258* + ID_MODEL_FROM_DATABASE=DCP-J715N + +usb:v04F9p0259* + ID_MODEL_FROM_DATABASE=MFC-J220 + +usb:v04F9p025A* + ID_MODEL_FROM_DATABASE=MFC-J410 + +usb:v04F9p025B* + ID_MODEL_FROM_DATABASE=MFC-J265W + +usb:v04F9p025C* + ID_MODEL_FROM_DATABASE=MFC-J415W + +usb:v04F9p025D* + ID_MODEL_FROM_DATABASE=MFC-J615W + +usb:v04F9p025E* + ID_MODEL_FROM_DATABASE=MFC-J615N + +usb:v04F9p025F* + ID_MODEL_FROM_DATABASE=MFC-J700D + +usb:v04F9p0260* + ID_MODEL_FROM_DATABASE=MFC-J800D + +usb:v04F9p0261* + ID_MODEL_FROM_DATABASE=MFC-J850DN + +usb:v04F9p026B* + ID_MODEL_FROM_DATABASE=MFC-J630W + +usb:v04F9p026D* + ID_MODEL_FROM_DATABASE=MFC-J805D + +usb:v04F9p026E* + ID_MODEL_FROM_DATABASE=MFC-J855DN + +usb:v04F9p026F* + ID_MODEL_FROM_DATABASE=MFC-J270W + +usb:v04F9p0270* + ID_MODEL_FROM_DATABASE=MFC-7360N + +usb:v04F9p0273* + ID_MODEL_FROM_DATABASE=DCP-7057 scanner/printer + +usb:v04F9p0276* + ID_MODEL_FROM_DATABASE=MFC-5895CW + +usb:v04F9p0278* + ID_MODEL_FROM_DATABASE=MFC-J410W + +usb:v04F9p0279* + ID_MODEL_FROM_DATABASE=DCP-J525W + +usb:v04F9p027A* + ID_MODEL_FROM_DATABASE=DCP-J525N + +usb:v04F9p027B* + ID_MODEL_FROM_DATABASE=DCP-J725DW + +usb:v04F9p027C* + ID_MODEL_FROM_DATABASE=DCP-J725N + +usb:v04F9p027D* + ID_MODEL_FROM_DATABASE=DCP-J925DW + +usb:v04F9p027E* + ID_MODEL_FROM_DATABASE=MFC-J955DN + +usb:v04F9p027F* + ID_MODEL_FROM_DATABASE=MFC-J280W + +usb:v04F9p0280* + ID_MODEL_FROM_DATABASE=MFC-J435W + +usb:v04F9p0281* + ID_MODEL_FROM_DATABASE=MFC-J430W + +usb:v04F9p0282* + ID_MODEL_FROM_DATABASE=MFC-J625DW + +usb:v04F9p0283* + ID_MODEL_FROM_DATABASE=MFC-J825DW + +usb:v04F9p0284* + ID_MODEL_FROM_DATABASE=MFC-J825N + +usb:v04F9p0285* + ID_MODEL_FROM_DATABASE=MFC-J705D + +usb:v04F9p0287* + ID_MODEL_FROM_DATABASE=MFC-J860DN + +usb:v04F9p0288* + ID_MODEL_FROM_DATABASE=MFC-J5910DW + +usb:v04F9p0289* + ID_MODEL_FROM_DATABASE=MFC-J5910CDW + +usb:v04F9p028A* + ID_MODEL_FROM_DATABASE=DCP-J925N + +usb:v04F9p028D* + ID_MODEL_FROM_DATABASE=MFC-J835DW + +usb:v04F9p028F* + ID_MODEL_FROM_DATABASE=MFC-J425W + +usb:v04F9p0290* + ID_MODEL_FROM_DATABASE=MFC-J432W + +usb:v04F9p0291* + ID_MODEL_FROM_DATABASE=DCP-8110DN + +usb:v04F9p0292* + ID_MODEL_FROM_DATABASE=DCP-8150DN + +usb:v04F9p0293* + ID_MODEL_FROM_DATABASE=DCP-8155DN + +usb:v04F9p0294* + ID_MODEL_FROM_DATABASE=DCP-8250DN + +usb:v04F9p0295* + ID_MODEL_FROM_DATABASE=MFC-8510DN + +usb:v04F9p0296* + ID_MODEL_FROM_DATABASE=MFC-8520DN + +usb:v04F9p0298* + ID_MODEL_FROM_DATABASE=MFC-8910DW + +usb:v04F9p0299* + ID_MODEL_FROM_DATABASE=MFC-8950DW + +usb:v04F9p029A* + ID_MODEL_FROM_DATABASE=MFC-8690DW + +usb:v04F9p029C* + ID_MODEL_FROM_DATABASE=MFC-8515DN + +usb:v04F9p029E* + ID_MODEL_FROM_DATABASE=MFC-9125CN + +usb:v04F9p029F* + ID_MODEL_FROM_DATABASE=MFC-9325CW + +usb:v04F9p02A0* + ID_MODEL_FROM_DATABASE=DCP-J140W + +usb:v04F9p02A5* + ID_MODEL_FROM_DATABASE=MFC-7240 + +usb:v04F9p02A6* + ID_MODEL_FROM_DATABASE=FAX-2940 + +usb:v04F9p02A7* + ID_MODEL_FROM_DATABASE=FAX-2950 + +usb:v04F9p02A8* + ID_MODEL_FROM_DATABASE=MFC-7290 + +usb:v04F9p02AB* + ID_MODEL_FROM_DATABASE=FAX-2990 + +usb:v04F9p02AC* + ID_MODEL_FROM_DATABASE=DCP-8110D + +usb:v04F9p02AD* + ID_MODEL_FROM_DATABASE=MFC-9130CW + +usb:v04F9p02AE* + ID_MODEL_FROM_DATABASE=MFC-9140CDN + +usb:v04F9p02AF* + ID_MODEL_FROM_DATABASE=MFC-9330CDW + +usb:v04F9p02B0* + ID_MODEL_FROM_DATABASE=MFC-9340CDW + +usb:v04F9p02B1* + ID_MODEL_FROM_DATABASE=DCP-9020CDN + +usb:v04F9p02B2* + ID_MODEL_FROM_DATABASE=MFC-J810DN + +usb:v04F9p02B3* + ID_MODEL_FROM_DATABASE=MFC-J4510DW + +usb:v04F9p02B4* + ID_MODEL_FROM_DATABASE=MFC-J4710DW + +usb:v04F9p02B5* + ID_MODEL_FROM_DATABASE=DCP-8112DN + +usb:v04F9p02B6* + ID_MODEL_FROM_DATABASE=DCP-8152DN + +usb:v04F9p02B7* + ID_MODEL_FROM_DATABASE=DCP-8157DN + +usb:v04F9p02B8* + ID_MODEL_FROM_DATABASE=MFC-8512DN + +usb:v04F9p02BA* + ID_MODEL_FROM_DATABASE=MFC-8912DW + +usb:v04F9p02BB* + ID_MODEL_FROM_DATABASE=MFC-8952DW + +usb:v04F9p02BC* + ID_MODEL_FROM_DATABASE=DCP-J540N + +usb:v04F9p02BD* + ID_MODEL_FROM_DATABASE=DCP-J740N + +usb:v04F9p02BE* + ID_MODEL_FROM_DATABASE=MFC-J710D + +usb:v04F9p02BF* + ID_MODEL_FROM_DATABASE=MFC-J840N + +usb:v04F9p02C0* + ID_MODEL_FROM_DATABASE=DCP-J940N + +usb:v04F9p02C1* + ID_MODEL_FROM_DATABASE=MFC-J960DN + +usb:v04F9p02C2* + ID_MODEL_FROM_DATABASE=DCP-J4110DW + +usb:v04F9p02C3* + ID_MODEL_FROM_DATABASE=MFC-J4310DW + +usb:v04F9p02C4* + ID_MODEL_FROM_DATABASE=MFC-J4410DW + +usb:v04F9p02C5* + ID_MODEL_FROM_DATABASE=MFC-J4610DW + +usb:v04F9p02C6* + ID_MODEL_FROM_DATABASE=DCP-J4210N + +usb:v04F9p02C7* + ID_MODEL_FROM_DATABASE=MFC-J4510N + +usb:v04F9p02C8* + ID_MODEL_FROM_DATABASE=MFC-J4910CDW + +usb:v04F9p02C9* + ID_MODEL_FROM_DATABASE=MFC-J4810DN + +usb:v04F9p02CA* + ID_MODEL_FROM_DATABASE=MFC-8712DW + +usb:v04F9p02CB* + ID_MODEL_FROM_DATABASE=MFC-8710DW + +usb:v04F9p02CC* + ID_MODEL_FROM_DATABASE=MFC-J2310 + +usb:v04F9p02CD* + ID_MODEL_FROM_DATABASE=MFC-J2510 + +usb:v04F9p02CE* + ID_MODEL_FROM_DATABASE=DCP-7055W + +usb:v04F9p02CF* + ID_MODEL_FROM_DATABASE=DCP-7057W + +usb:v04F9p02D0* + ID_MODEL_FROM_DATABASE=DCP-1510 + +usb:v04F9p02D1* + ID_MODEL_FROM_DATABASE=MFC-1810 + +usb:v04F9p02D3* + ID_MODEL_FROM_DATABASE=DCP-9020CDW + +usb:v04F9p02D4* + ID_MODEL_FROM_DATABASE=MFC-8810DW + +usb:v04F9p02DD* + ID_MODEL_FROM_DATABASE=DCP-J4215N + +usb:v04F9p02DE* + ID_MODEL_FROM_DATABASE=DCP-J132W + +usb:v04F9p02DF* + ID_MODEL_FROM_DATABASE=DCP-J152W + +usb:v04F9p02E0* + ID_MODEL_FROM_DATABASE=DCP-J152N + +usb:v04F9p02E1* + ID_MODEL_FROM_DATABASE=DCP-J172W + +usb:v04F9p02E2* + ID_MODEL_FROM_DATABASE=DCP-J552DW + +usb:v04F9p02E3* + ID_MODEL_FROM_DATABASE=DCP-J552N + +usb:v04F9p02E4* + ID_MODEL_FROM_DATABASE=DCP-J752DW + +usb:v04F9p02E5* + ID_MODEL_FROM_DATABASE=DCP-J752N + +usb:v04F9p02E6* + ID_MODEL_FROM_DATABASE=DCP-J952N + +usb:v04F9p02E7* + ID_MODEL_FROM_DATABASE=MFC-J245 + +usb:v04F9p02E8* + ID_MODEL_FROM_DATABASE=MFC-J470DW + +usb:v04F9p02E9* + ID_MODEL_FROM_DATABASE=MFC-J475DW + +usb:v04F9p02EA* + ID_MODEL_FROM_DATABASE=MFC-J285DW + +usb:v04F9p02EB* + ID_MODEL_FROM_DATABASE=MFC-J650DW + +usb:v04F9p02EC* + ID_MODEL_FROM_DATABASE=MFC-J870DW + +usb:v04F9p02ED* + ID_MODEL_FROM_DATABASE=MFC-J870N + +usb:v04F9p02EE* + ID_MODEL_FROM_DATABASE=MFC-J720D + +usb:v04F9p02EF* + ID_MODEL_FROM_DATABASE=MFC-J820DN + +usb:v04F9p02F0* + ID_MODEL_FROM_DATABASE=MFC-J980DN + +usb:v04F9p02F1* + ID_MODEL_FROM_DATABASE=MFC-J890DN + +usb:v04F9p02F2* + ID_MODEL_FROM_DATABASE=MFC-J6520DW + +usb:v04F9p02F3* + ID_MODEL_FROM_DATABASE=MFC-J6570CDW + +usb:v04F9p02F4* + ID_MODEL_FROM_DATABASE=MFC-J6720DW + +usb:v04F9p02F5* + ID_MODEL_FROM_DATABASE=MFC-J6920DW + +usb:v04F9p02F6* + ID_MODEL_FROM_DATABASE=MFC-J6970CDW + +usb:v04F9p02F7* + ID_MODEL_FROM_DATABASE=MFC-J6975CDW + +usb:v04F9p02F8* + ID_MODEL_FROM_DATABASE=MFC-J6770CDW + +usb:v04F9p02F9* + ID_MODEL_FROM_DATABASE=DCP-J132N + +usb:v04F9p02FA* + ID_MODEL_FROM_DATABASE=MFC-J450DW + +usb:v04F9p02FB* + ID_MODEL_FROM_DATABASE=MFC-J875DW + +usb:v04F9p02FC* + ID_MODEL_FROM_DATABASE=DCP-J100 + +usb:v04F9p02FD* + ID_MODEL_FROM_DATABASE=DCP-J105 + +usb:v04F9p02FE* + ID_MODEL_FROM_DATABASE=MFC-J200 + +usb:v04F9p02FF* + ID_MODEL_FROM_DATABASE=MFC-J3520 + +usb:v04F9p0300* + ID_MODEL_FROM_DATABASE=MFC-J3720 + +usb:v04F9p030F* + ID_MODEL_FROM_DATABASE=DCP-L8400CDN + +usb:v04F9p0310* + ID_MODEL_FROM_DATABASE=DCP-L8450CDW + +usb:v04F9p0311* + ID_MODEL_FROM_DATABASE=MFC-L8600CDW + +usb:v04F9p0312* + ID_MODEL_FROM_DATABASE=MFC-L8650CDW + +usb:v04F9p0313* + ID_MODEL_FROM_DATABASE=MFC-L8850CDW + +usb:v04F9p0314* + ID_MODEL_FROM_DATABASE=MFC-L9550CDW + +usb:v04F9p0318* + ID_MODEL_FROM_DATABASE=MFC-7365DN + +usb:v04F9p0320* + ID_MODEL_FROM_DATABASE=MFC-L2740DW + +usb:v04F9p0321* + ID_MODEL_FROM_DATABASE=DCP-L2500D + +usb:v04F9p0322* + ID_MODEL_FROM_DATABASE=DCP-L2520DW + +usb:v04F9p0324* + ID_MODEL_FROM_DATABASE=DCP-L2520D + +usb:v04F9p0326* + ID_MODEL_FROM_DATABASE=DCP-L2540DN + +usb:v04F9p0328* + ID_MODEL_FROM_DATABASE=DCP-L2540DW + +usb:v04F9p0329* + ID_MODEL_FROM_DATABASE=DCP-L2560DW + +usb:v04F9p0330* + ID_MODEL_FROM_DATABASE=HL-L2380DW + +usb:v04F9p0331* + ID_MODEL_FROM_DATABASE=MFC-L2700DW + +usb:v04F9p0335* + ID_MODEL_FROM_DATABASE=FAX-L2700DN + +usb:v04F9p0337* + ID_MODEL_FROM_DATABASE=MFC-L2720DW + +usb:v04F9p0338* + ID_MODEL_FROM_DATABASE=MFC-L2720DN + +usb:v04F9p0339* + ID_MODEL_FROM_DATABASE=DCP-J4120DW + +usb:v04F9p033A* + ID_MODEL_FROM_DATABASE=MFC-J4320DW + +usb:v04F9p033C* + ID_MODEL_FROM_DATABASE=MFC-J2320 + +usb:v04F9p033D* + ID_MODEL_FROM_DATABASE=MFC-J4420DW + +usb:v04F9p0340* + ID_MODEL_FROM_DATABASE=MFC-J4620DW + +usb:v04F9p0341* + ID_MODEL_FROM_DATABASE=MFC-J2720 + +usb:v04F9p0342* + ID_MODEL_FROM_DATABASE=MFC-J4625DW + +usb:v04F9p0343* + ID_MODEL_FROM_DATABASE=MFC-J5320DW + +usb:v04F9p0346* + ID_MODEL_FROM_DATABASE=MFC-J5620DW + +usb:v04F9p0347* + ID_MODEL_FROM_DATABASE=MFC-J5720DW + +usb:v04F9p0349* + ID_MODEL_FROM_DATABASE=DCP-J4220N + +usb:v04F9p034B* + ID_MODEL_FROM_DATABASE=MFC-J4720N + +usb:v04F9p034E* + ID_MODEL_FROM_DATABASE=MFC-J5720CDW + +usb:v04F9p034F* + ID_MODEL_FROM_DATABASE=MFC-J5820DN + +usb:v04F9p0350* + ID_MODEL_FROM_DATABASE=MFC-J5620CDW + +usb:v04F9p0351* + ID_MODEL_FROM_DATABASE=DCP-J137N + +usb:v04F9p0353* + ID_MODEL_FROM_DATABASE=DCP-J557N + +usb:v04F9p0354* + ID_MODEL_FROM_DATABASE=DCP-J757N + +usb:v04F9p0355* + ID_MODEL_FROM_DATABASE=DCP-J957N + +usb:v04F9p0356* + ID_MODEL_FROM_DATABASE=MFC-J877N + +usb:v04F9p0357* + ID_MODEL_FROM_DATABASE=MFC-J727D + +usb:v04F9p0358* + ID_MODEL_FROM_DATABASE=MFC-J987DN + +usb:v04F9p0359* + ID_MODEL_FROM_DATABASE=MFC-J827DN + +usb:v04F9p035A* + ID_MODEL_FROM_DATABASE=MFC-J897DN + +usb:v04F9p035B* + ID_MODEL_FROM_DATABASE=DCP-1610W + +usb:v04F9p035C* + ID_MODEL_FROM_DATABASE=DCP-1610NW + +usb:v04F9p035D* + ID_MODEL_FROM_DATABASE=MFC-1910W + +usb:v04F9p035E* + ID_MODEL_FROM_DATABASE=MFC-1910NW + +usb:v04F9p0360* + ID_MODEL_FROM_DATABASE=DCP-1618W + +usb:v04F9p0361* + ID_MODEL_FROM_DATABASE=MFC-1919NW + +usb:v04F9p0364* + ID_MODEL_FROM_DATABASE=MFC-J5625DW + +usb:v04F9p0365* + ID_MODEL_FROM_DATABASE=MFC-J4520DW + +usb:v04F9p0366* + ID_MODEL_FROM_DATABASE=MFC-J5520DW + +usb:v04F9p0367* + ID_MODEL_FROM_DATABASE=DCP-7080D + +usb:v04F9p0368* + ID_MODEL_FROM_DATABASE=DCP-7080 + +usb:v04F9p0369* + ID_MODEL_FROM_DATABASE=DCP-7180DN + +usb:v04F9p036A* + ID_MODEL_FROM_DATABASE=DCP-7189DW + +usb:v04F9p036B* + ID_MODEL_FROM_DATABASE=MFC-7380 + +usb:v04F9p036C* + ID_MODEL_FROM_DATABASE=MFC-7480D + +usb:v04F9p036D* + ID_MODEL_FROM_DATABASE=MFC-7880DN + +usb:v04F9p036E* + ID_MODEL_FROM_DATABASE=MFC-7889DW + +usb:v04F9p036F* + ID_MODEL_FROM_DATABASE=DCP-9022CDW + +usb:v04F9p0370* + ID_MODEL_FROM_DATABASE=MFC-9142CDN + +usb:v04F9p0371* + ID_MODEL_FROM_DATABASE=MFC-9332CDW + +usb:v04F9p0372* + ID_MODEL_FROM_DATABASE=MFC-9342CDW + +usb:v04F9p0373* + ID_MODEL_FROM_DATABASE=MFC-L2700D + +usb:v04F9p0376* + ID_MODEL_FROM_DATABASE=DCP-1600 + +usb:v04F9p0377* + ID_MODEL_FROM_DATABASE=MFC-1900 + +usb:v04F9p0378* + ID_MODEL_FROM_DATABASE=DCP-1608 + +usb:v04F9p0379* + ID_MODEL_FROM_DATABASE=DCP-1619 + +usb:v04F9p037A* + ID_MODEL_FROM_DATABASE=MFC-1906 + +usb:v04F9p037B* + ID_MODEL_FROM_DATABASE=MFC-1908 + +usb:v04F9p037C* + ID_MODEL_FROM_DATABASE=ADS-2000e + +usb:v04F9p037D* + ID_MODEL_FROM_DATABASE=ADS-2100e + +usb:v04F9p037E* + ID_MODEL_FROM_DATABASE=ADS-2500We + +usb:v04F9p037F* + ID_MODEL_FROM_DATABASE=ADS-2600We + +usb:v04F9p0380* + ID_MODEL_FROM_DATABASE=DCP-J562DW + +usb:v04F9p0381* + ID_MODEL_FROM_DATABASE=DCP-J562N + +usb:v04F9p0383* + ID_MODEL_FROM_DATABASE=DCP-J962N + +usb:v04F9p0384* + ID_MODEL_FROM_DATABASE=MFC-J480DW + +usb:v04F9p0385* + ID_MODEL_FROM_DATABASE=MFC-J485DW + +usb:v04F9p0386* + ID_MODEL_FROM_DATABASE=MFC-J460DW + +usb:v04F9p0388* + ID_MODEL_FROM_DATABASE=MFC-J680DW + +usb:v04F9p0389* + ID_MODEL_FROM_DATABASE=MFC-J880DW + +usb:v04F9p038A* + ID_MODEL_FROM_DATABASE=MFC-J885DW + +usb:v04F9p038B* + ID_MODEL_FROM_DATABASE=MFC-J880N + +usb:v04F9p038C* + ID_MODEL_FROM_DATABASE=MFC-J730DN + +usb:v04F9p038D* + ID_MODEL_FROM_DATABASE=MFC-J990DN + +usb:v04F9p038E* + ID_MODEL_FROM_DATABASE=MFC-J830DN + +usb:v04F9p038F* + ID_MODEL_FROM_DATABASE=MFC-J900DN + +usb:v04F9p0390* + ID_MODEL_FROM_DATABASE=MFC-J5920DW + +usb:v04F9p0392* + ID_MODEL_FROM_DATABASE=MFC-L2705DW + +usb:v04F9p0393* + ID_MODEL_FROM_DATABASE=DCP-T300 + +usb:v04F9p0394* + ID_MODEL_FROM_DATABASE=DCP-T500W + +usb:v04F9p0395* + ID_MODEL_FROM_DATABASE=DCP-T700W + +usb:v04F9p0396* + ID_MODEL_FROM_DATABASE=MFC-T800W + +usb:v04F9p0397* + ID_MODEL_FROM_DATABASE=DCP-J963N + +usb:v04F9p03B3* + ID_MODEL_FROM_DATABASE=MFC-J6925DW + +usb:v04F9p03B4* + ID_MODEL_FROM_DATABASE=MFC-J6573CDW + +usb:v04F9p03B5* + ID_MODEL_FROM_DATABASE=MFC-J6973CDW + +usb:v04F9p03B6* + ID_MODEL_FROM_DATABASE=MFC-J6990CDW + +usb:v04F9p03BB* + ID_MODEL_FROM_DATABASE=MFC-L2680W + +usb:v04F9p03BC* + ID_MODEL_FROM_DATABASE=MFC-L2700DN + +usb:v04F9p03BD* + ID_MODEL_FROM_DATABASE=DCP-J762N + +usb:v04F9p1000* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p1002* + ID_MODEL_FROM_DATABASE=Printer + +usb:v04F9p2002* + ID_MODEL_FROM_DATABASE=PTUSB Printing + +usb:v04F9p2004* + ID_MODEL_FROM_DATABASE=PT-2300/2310 p-Touch Laber Printer + +usb:v04F9p2007* + ID_MODEL_FROM_DATABASE=PT-2420PC P-touch Label Printer + +usb:v04F9p2015* + ID_MODEL_FROM_DATABASE=QL-500 P-touch label printer + +usb:v04F9p2016* + ID_MODEL_FROM_DATABASE=QL-550 P-touch label printer + +usb:v04F9p201A* + ID_MODEL_FROM_DATABASE=PT-18R P-touch label printer + +usb:v04F9p201B* + ID_MODEL_FROM_DATABASE=QL-650TD P-touch Label Printer + +usb:v04F9p2027* + ID_MODEL_FROM_DATABASE=QL-560 P-touch Label Printer + +usb:v04F9p2028* + ID_MODEL_FROM_DATABASE=QL-570 P-touch Label Printer + +usb:v04F9p202B* + ID_MODEL_FROM_DATABASE=PT-7600 P-touch Label Printer + +usb:v04F9p2041* + ID_MODEL_FROM_DATABASE=PT-2730 P-touch Label Printer + +usb:v04F9p2061* + ID_MODEL_FROM_DATABASE=PT-P700 P-touch Label Printer + +usb:v04F9p2064* + ID_MODEL_FROM_DATABASE=PT-P700 P-touch Label Printer RemovableDisk + +usb:v04F9p209B* + ID_MODEL_FROM_DATABASE=QL-800 P-touch Label Printer + +usb:v04F9p209C* + ID_MODEL_FROM_DATABASE=QL-810W P-touch Label Printer + +usb:v04F9p209D* + ID_MODEL_FROM_DATABASE=QL-820NWB P-touch Label Printer + +usb:v04F9p2100* + ID_MODEL_FROM_DATABASE=Card Reader Writer + +usb:v04F9p2102* + ID_MODEL_FROM_DATABASE=Sewing machine + +usb:v04F9p60A0* + ID_MODEL_FROM_DATABASE=ADS-2000 + +usb:v04F9p60A1* + ID_MODEL_FROM_DATABASE=ADS-2100 + +usb:v04F9p60A4* + ID_MODEL_FROM_DATABASE=ADS-2500W + +usb:v04F9p60A5* + ID_MODEL_FROM_DATABASE=ADS-2600W + +usb:v04F9p60A6* + ID_MODEL_FROM_DATABASE=ADS-1000W + +usb:v04F9p60A7* + ID_MODEL_FROM_DATABASE=ADS-1100W + +usb:v04F9p60A8* + ID_MODEL_FROM_DATABASE=ADS-1500W + +usb:v04F9p60A9* + ID_MODEL_FROM_DATABASE=ADS-1600W + +usb:v04FA* + ID_VENDOR_FROM_DATABASE=Dallas Semiconductor + +usb:v04FAp2490* + ID_MODEL_FROM_DATABASE=DS1490F 2-in-1 Fob, 1-Wire adapter + +usb:v04FAp4201* + ID_MODEL_FROM_DATABASE=DS4201 Audio DAC + +usb:v04FB* + ID_VENDOR_FROM_DATABASE=Biostar Microtech International Corp. + +usb:v04FC* + ID_VENDOR_FROM_DATABASE=Sunplus Technology Co., Ltd + +usb:v04FCp0003* + ID_MODEL_FROM_DATABASE=CM1092 / Wintech CM-5098 Optical Mouse + +usb:v04FCp0005* + ID_MODEL_FROM_DATABASE=USB OpticalWheel Mouse + +usb:v04FCp0013* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v04FCp0015* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v04FCp00D3* + ID_MODEL_FROM_DATABASE=00052486 / Laser Mouse M1052 [hama] + +usb:v04FCp0171* + ID_MODEL_FROM_DATABASE=SPCA1527A/SPCA1528 SD card camera (Mass Storage mode) + +usb:v04FCp0201* + ID_MODEL_FROM_DATABASE=SPCP825 RS232C Adapter + +usb:v04FCp0232* + ID_MODEL_FROM_DATABASE=Fingerprint + +usb:v04FCp0538* + ID_MODEL_FROM_DATABASE=Wireless Optical Mouse 2.4G [Bright] + +usb:v04FCp0561* + ID_MODEL_FROM_DATABASE=Flexcam 100 + +usb:v04FCp05D8* + ID_MODEL_FROM_DATABASE=Wireless keyboard/mouse + +usb:v04FCp05DA* + ID_MODEL_FROM_DATABASE=SPEEDLINK SNAPPY Wireless Mouse Nano + +usb:v04FCp0C15* + ID_MODEL_FROM_DATABASE=SPIF215A SATA bridge + +usb:v04FCp0C25* + ID_MODEL_FROM_DATABASE=SATALink SPIF225A + +usb:v04FCp1528* + ID_MODEL_FROM_DATABASE=SPCA1527A/SPCA1528 SD card camera (webcam mode) + +usb:v04FCp1533* + ID_MODEL_FROM_DATABASE=Mass Storage + +usb:v04FCp2080* + ID_MODEL_FROM_DATABASE=ASUS Webcam + +usb:v04FCp500C* + ID_MODEL_FROM_DATABASE=CA500C Digital Camera + +usb:v04FCp504A* + ID_MODEL_FROM_DATABASE=Aiptek Mini PenCam 1.3 + +usb:v04FCp504B* + ID_MODEL_FROM_DATABASE=Aiptek Mega PockerCam 1.3/Maxell MaxPocket LE 1.3 + +usb:v04FCp5330* + ID_MODEL_FROM_DATABASE=Digitrex 2110 + +usb:v04FCp5331* + ID_MODEL_FROM_DATABASE=Vivitar Vivicam 10 + +usb:v04FCp5360* + ID_MODEL_FROM_DATABASE=Sunplus Generic Digital Camera + +usb:v04FCp5563* + ID_MODEL_FROM_DATABASE=Digital Media Player MP3/WMA [The Sharper Image] + +usb:v04FCp5720* + ID_MODEL_FROM_DATABASE=Card Reader Driver + +usb:v04FCp6333* + ID_MODEL_FROM_DATABASE=Siri A9 UVC chipset + +usb:v04FCp7333* + ID_MODEL_FROM_DATABASE=Finet Technology Palmpix DC-85 + +usb:v04FCp757A* + ID_MODEL_FROM_DATABASE=Aiptek, MP315 MP3 Player + +usb:v04FCpFFFF* + ID_MODEL_FROM_DATABASE=PureDigital Ritz Disposable + +usb:v04FD* + ID_VENDOR_FROM_DATABASE=Soliton Systems, K.K. + +usb:v04FDp0003* + ID_MODEL_FROM_DATABASE=Smart Card Reader II + +usb:v04FE* + ID_VENDOR_FROM_DATABASE=PFU, Ltd + +usb:v04FEp0006* + ID_MODEL_FROM_DATABASE=Happy Hacking Keyboard Lite2 + +usb:v04FF* + ID_VENDOR_FROM_DATABASE=E-CMOS Corp. + +usb:v0500* + ID_VENDOR_FROM_DATABASE=Siam United Hi-Tech + +usb:v0500p0001* + ID_MODEL_FROM_DATABASE=DART Keyboard Mouse + +usb:v0500p0002* + ID_MODEL_FROM_DATABASE=DART-2 Keyboard + +usb:v0501* + ID_VENDOR_FROM_DATABASE=Fujikura DDK, Ltd + +usb:v0502* + ID_VENDOR_FROM_DATABASE=Acer, Inc. + +usb:v0502p0001* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0502p0736* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0502p15B1* + ID_MODEL_FROM_DATABASE=PDA n311 + +usb:v0502p1631* + ID_MODEL_FROM_DATABASE=c10 Series + +usb:v0502p1632* + ID_MODEL_FROM_DATABASE=c20 Series + +usb:v0502p16E1* + ID_MODEL_FROM_DATABASE=n10 Handheld Sync + +usb:v0502p16E2* + ID_MODEL_FROM_DATABASE=n20 Pocket PC Sync + +usb:v0502p16E3* + ID_MODEL_FROM_DATABASE=n30 Handheld Sync + +usb:v0502p2008* + ID_MODEL_FROM_DATABASE=Liquid Gallant Duo E350 (preloader) + +usb:v0502p3202* + ID_MODEL_FROM_DATABASE=Liquid + +usb:v0502p3203* + ID_MODEL_FROM_DATABASE=Liquid (Debug mode) + +usb:v0502p3230* + ID_MODEL_FROM_DATABASE=BeTouch E120 + +usb:v0502p3317* + ID_MODEL_FROM_DATABASE=Liquid + +usb:v0502p3325* + ID_MODEL_FROM_DATABASE=Iconia tablet A500 + +usb:v0502p3341* + ID_MODEL_FROM_DATABASE=Iconia tablet A500 + +usb:v0502p33C3* + ID_MODEL_FROM_DATABASE=Liquid Gallant Duo E350 + +usb:v0502p33C4* + ID_MODEL_FROM_DATABASE=Liquid Gallant Duo E350 (debug mode) + +usb:v0502p33C7* + ID_MODEL_FROM_DATABASE=Liquid Gallant Duo E350 (USB tethering) + +usb:v0502p33C8* + ID_MODEL_FROM_DATABASE=Liquid Gallant Duo E350 (debug mode, USB tethering) + +usb:v0502pD001* + ID_MODEL_FROM_DATABASE=Divio NW801/DVC-V6+ Digital Camera + +usb:v0503* + ID_VENDOR_FROM_DATABASE=Hitachi America, Ltd + +usb:v0504* + ID_VENDOR_FROM_DATABASE=Hayes Microcomputer Products + +usb:v0506* + ID_VENDOR_FROM_DATABASE=3Com Corp. + +usb:v0506p009D* + ID_MODEL_FROM_DATABASE=HomeConnect Camera + +usb:v0506p00A0* + ID_MODEL_FROM_DATABASE=3CREB96 Bluetooth Adapter + +usb:v0506p00A1* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0506p00A2* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0506p00DF* + ID_MODEL_FROM_DATABASE=3Com Home Connect lite + +usb:v0506p0100* + ID_MODEL_FROM_DATABASE=HomeConnect ADSL Modem Driver + +usb:v0506p03E8* + ID_MODEL_FROM_DATABASE=3C19250 Ethernet [klsi] + +usb:v0506p0A01* + ID_MODEL_FROM_DATABASE=3CRSHEW696 Wireless Adapter + +usb:v0506p0A11* + ID_MODEL_FROM_DATABASE=3CRWE254G72 802.11g Adapter + +usb:v0506p11F8* + ID_MODEL_FROM_DATABASE=HomeConnect 3C460 + +usb:v0506p2922* + ID_MODEL_FROM_DATABASE=HomeConnect Cable Modem External with + +usb:v0506p3021* + ID_MODEL_FROM_DATABASE=U.S.Robotics 56000 Voice FaxModem Pro + +usb:v0506p4601* + ID_MODEL_FROM_DATABASE=3C460B 10/100 Ethernet Adapter + +usb:v0506pF002* + ID_MODEL_FROM_DATABASE=3CP4218 ADSL Modem (pre-init) + +usb:v0506pF003* + ID_MODEL_FROM_DATABASE=3CP4218 ADSL Modem + +usb:v0506pF100* + ID_MODEL_FROM_DATABASE=3CP4218 ADSL Modem (pre-init) + +usb:v0507* + ID_VENDOR_FROM_DATABASE=Hosiden Corp. + +usb:v0507p0011* + ID_MODEL_FROM_DATABASE=Konami ParaParaParadise Controller + +usb:v0508* + ID_VENDOR_FROM_DATABASE=Clarion Co., Ltd + +usb:v0509* + ID_VENDOR_FROM_DATABASE=Aztech Systems, Ltd + +usb:v0509p0801* + ID_MODEL_FROM_DATABASE=ADSL Modem + +usb:v0509p0802* + ID_MODEL_FROM_DATABASE=ADSL Modem (RFC1483) + +usb:v0509p0806* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v0509p080F* + ID_MODEL_FROM_DATABASE=Binatone ADSL500 Modem Network Interface + +usb:v0509p0812* + ID_MODEL_FROM_DATABASE=Pirelli ADSL Modem Network Interface + +usb:v050A* + ID_VENDOR_FROM_DATABASE=Cinch Connectors + +usb:v050B* + ID_VENDOR_FROM_DATABASE=Cable System International + +usb:v050C* + ID_VENDOR_FROM_DATABASE=InnoMedia, Inc. + +usb:v050D* + ID_VENDOR_FROM_DATABASE=Belkin Components + +usb:v050Dp0004* + ID_MODEL_FROM_DATABASE=Direct Connect + +usb:v050Dp0012* + ID_MODEL_FROM_DATABASE=F8T012 Bluetooth Adapter + +usb:v050Dp0013* + ID_MODEL_FROM_DATABASE=F8T013 Bluetooth Adapter + +usb:v050Dp0017* + ID_MODEL_FROM_DATABASE=B8T017 Bluetooth+EDR 2.1 / F4U017 USB 2.0 7-port Hub + +usb:v050Dp003A* + ID_MODEL_FROM_DATABASE=Universal Media Reader + +usb:v050Dp0050* + ID_MODEL_FROM_DATABASE=F5D6050 802.11b Wireless Adapter v2000 [Atmel at76c503a] + +usb:v050Dp0081* + ID_MODEL_FROM_DATABASE=F8T001v2 Bluetooth + +usb:v050Dp0083* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v050Dp0084* + ID_MODEL_FROM_DATABASE=F8T003v2 Bluetooth + +usb:v050Dp0102* + ID_MODEL_FROM_DATABASE=Flip KVM + +usb:v050Dp0103* + ID_MODEL_FROM_DATABASE=F5U103 Serial Adapter [etek] + +usb:v050Dp0106* + ID_MODEL_FROM_DATABASE=VideoBus II Adapter, Video + +usb:v050Dp0108* + ID_MODEL_FROM_DATABASE=F1DE108B KVM + +usb:v050Dp0109* + ID_MODEL_FROM_DATABASE=F5U109/F5U409 PDA Adapter + +usb:v050Dp0115* + ID_MODEL_FROM_DATABASE=SCSI Adapter + +usb:v050Dp0119* + ID_MODEL_FROM_DATABASE=F5U120-PC Dual PS/2 Ports / F5U118-UNV ADB Adapter + +usb:v050Dp0121* + ID_MODEL_FROM_DATABASE=F5D5050 100Mbps Ethernet + +usb:v050Dp0122* + ID_MODEL_FROM_DATABASE=Ethernet Adapter + +usb:v050Dp0131* + ID_MODEL_FROM_DATABASE=Bluetooth Device with trace filter + +usb:v050Dp016A* + ID_MODEL_FROM_DATABASE=Bluetooth Mini Dongle + +usb:v050Dp0200* + ID_MODEL_FROM_DATABASE=Nostromo SpeedPad n52te Gaming Keyboard + +usb:v050Dp0201* + ID_MODEL_FROM_DATABASE=Peripheral Switch + +usb:v050Dp0208* + ID_MODEL_FROM_DATABASE=USBView II Video Adapter [nt1004] + +usb:v050Dp0210* + ID_MODEL_FROM_DATABASE=F5U228 Hi-Speed USB 2.0 DVD Creator + +usb:v050Dp0211* + ID_MODEL_FROM_DATABASE=F5U211 USB 2.0 15-in-1 Media Reader & Writer + +usb:v050Dp0224* + ID_MODEL_FROM_DATABASE=F5U224 USB 2.0 4-Port Hub + +usb:v050Dp0234* + ID_MODEL_FROM_DATABASE=F5U234 USB 2.0 4-Port Hub + +usb:v050Dp0237* + ID_MODEL_FROM_DATABASE=F5U237 USB 2.0 7-Port Hub + +usb:v050Dp0240* + ID_MODEL_FROM_DATABASE=F5U240 USB 2.0 CF Card Reader + +usb:v050Dp0249* + ID_MODEL_FROM_DATABASE=USB 2 Flash Media Device + +usb:v050Dp0257* + ID_MODEL_FROM_DATABASE=F5U257 Serial + +usb:v050Dp0304* + ID_MODEL_FROM_DATABASE=FSU304 USB 2.0 - 4 Ports Hub + +usb:v050Dp0307* + ID_MODEL_FROM_DATABASE=USB 2.0 - 7 ports Hub [FSU307] + +usb:v050Dp038C* + ID_MODEL_FROM_DATABASE=F2CU038 HDMI Adapter + +usb:v050Dp0409* + ID_MODEL_FROM_DATABASE=F5U409 Serial + +usb:v050Dp0416* + ID_MODEL_FROM_DATABASE=Staples 12416 7 port desktop hub + +usb:v050Dp0551* + ID_MODEL_FROM_DATABASE=F6C550-AVR UPS + +usb:v050Dp065A* + ID_MODEL_FROM_DATABASE=F8T065BF Mini Bluetooth 4.0 Adapter + +usb:v050Dp0706* + ID_MODEL_FROM_DATABASE=2-N-1 7-Port Hub (Lower half) + +usb:v050Dp0802* + ID_MODEL_FROM_DATABASE=Nostromo n40 Gamepad + +usb:v050Dp0803* + ID_MODEL_FROM_DATABASE=Nostromo 1745 GamePad + +usb:v050Dp0805* + ID_MODEL_FROM_DATABASE=Nostromo N50 GamePad + +usb:v050Dp0815* + ID_MODEL_FROM_DATABASE=Nostromo n52 HID SpeedPad Mouse Wheel + +usb:v050Dp0826* + ID_MODEL_FROM_DATABASE=ErgoFit Wireless Optical Mouse (HID) + +usb:v050Dp0980* + ID_MODEL_FROM_DATABASE=HID UPS Battery + +usb:v050Dp1004* + ID_MODEL_FROM_DATABASE=F9L1004 802.11n Surf N300 XR Wireless Adapter [Realtek RTL8192CU] + +usb:v050Dp1102* + ID_MODEL_FROM_DATABASE=F7D1102 N150/Surf Micro Wireless Adapter v1000 [Realtek RTL8188CUS] + +usb:v050Dp1103* + ID_MODEL_FROM_DATABASE=F9L1103 N750 DB 802.11abgn 2x3:3 [Ralink RT3573] + +usb:v050Dp1106* + ID_MODEL_FROM_DATABASE=F9L1106v1 802.11a/b/g/n/ac Wireless Adapter [Broadcom BCM43526] + +usb:v050Dp1109* + ID_MODEL_FROM_DATABASE=F9L1109v1 802.11a/b/g/n/ac Wireless Adapter [Realtek RTL8812AU] + +usb:v050Dp110A* + ID_MODEL_FROM_DATABASE=F9L1101v2 802.11abgn Wireless Adapter [Realtek RTL8192DU] + +usb:v050Dp11F2* + ID_MODEL_FROM_DATABASE=ISY Wireless Micro Adapter IWL 2000 [RTL8188CUS] + +usb:v050Dp1202* + ID_MODEL_FROM_DATABASE=F5U120-PC Parallel Printer Port + +usb:v050Dp1203* + ID_MODEL_FROM_DATABASE=F5U120-PC Serial Port + +usb:v050Dp2103* + ID_MODEL_FROM_DATABASE=F7D2102 802.11n N300 Micro Wireless Adapter v3000 [Realtek RTL8192CU] + +usb:v050Dp21F1* + ID_MODEL_FROM_DATABASE=N300 WLAN N Adapter [ISY] + +usb:v050Dp21F2* + ID_MODEL_FROM_DATABASE=RTL8192CU 802.11n WLAN Adapter [ISY IWL 4000] + +usb:v050Dp258A* + ID_MODEL_FROM_DATABASE=F5U258 Host to Host cable + +usb:v050Dp3101* + ID_MODEL_FROM_DATABASE=F1DF102U/F1DG102U Flip Hub + +usb:v050Dp3201* + ID_MODEL_FROM_DATABASE=F1DF102U/F1DG102U Flip KVM + +usb:v050Dp4050* + ID_MODEL_FROM_DATABASE=ZD1211B + +usb:v050Dp5055* + ID_MODEL_FROM_DATABASE=F5D5055 Gigabit Network Adapter [AX88xxx] + +usb:v050Dp6050* + ID_MODEL_FROM_DATABASE=F6D6050 802.11abgn Wireless Adapter [Broadcom BCM4323] + +usb:v050Dp6051* + ID_MODEL_FROM_DATABASE=F5D6051 802.11b Wireless Network Adapter [ZyDAS ZD1201] + +usb:v050Dp615A* + ID_MODEL_FROM_DATABASE=F7D4101 / F9L1101v1 802.11abgn Wireless Adapter [Broadcom BCM4323] + +usb:v050Dp7050* + ID_MODEL_FROM_DATABASE=F5D7050 Wireless G Adapter v1000/v2000 [Intersil ISL3887] + +usb:v050Dp7051* + ID_MODEL_FROM_DATABASE=F5D7051 802.11g Adapter v1000 [Broadcom 4320 USB] + +usb:v050Dp705A* + ID_MODEL_FROM_DATABASE=F5D7050 Wireless G Adapter v3000 [Ralink RT2571W] + +usb:v050Dp705B* + ID_MODEL_FROM_DATABASE=Wireless G Adapter + +usb:v050Dp705C* + ID_MODEL_FROM_DATABASE=F5D7050 Wireless G Adapter v4000 [Zydas ZD1211B] + +usb:v050Dp705E* + ID_MODEL_FROM_DATABASE=F5D7050 Wireless G Adapter v5000 [Realtek RTL8187B] + +usb:v050Dp706A* + ID_MODEL_FROM_DATABASE=2-N-1 7-Port Hub (Upper half) + +usb:v050Dp8053* + ID_MODEL_FROM_DATABASE=F5D8053 N Wireless USB Adapter v1000/v4000 [Ralink RT2870] + +usb:v050Dp805C* + ID_MODEL_FROM_DATABASE=F5D8053 N Wireless Adapter v3000 [Ralink RT2870] + +usb:v050Dp805E* + ID_MODEL_FROM_DATABASE=F5D8053 N Wireless USB Adapter v5000 [Realtek RTL8192U] + +usb:v050Dp815C* + ID_MODEL_FROM_DATABASE=F5D8053 N Wireless USB Adapter v3000 [Ralink RT2870] + +usb:v050Dp815F* + ID_MODEL_FROM_DATABASE=F5D8053 N Wireless USB Adapter v6000 [Realtek RTL8192SU] + +usb:v050Dp825A* + ID_MODEL_FROM_DATABASE=F5D8055 N+ Wireless Adapter v1000 [Ralink RT2870] + +usb:v050Dp825B* + ID_MODEL_FROM_DATABASE=F5D8055 N+ Wireless Adapter v2000 [Ralink RT3072] + +usb:v050Dp845A* + ID_MODEL_FROM_DATABASE=F7D2101 802.11n Surf & Share Wireless Adapter v1000 [Realtek RTL8192SU] + +usb:v050Dp905B* + ID_MODEL_FROM_DATABASE=F5D9050 Wireless G+ MIMO Network Adapter v3000 [Ralink RT2573] + +usb:v050Dp905C* + ID_MODEL_FROM_DATABASE=F5D9050 Wireless G+ MIMO Network Adapter v4000 [Ralink RT2573] + +usb:v050Dp935A* + ID_MODEL_FROM_DATABASE=F6D4050 N150 Enhanced Wireless Network Adapter v1000 [Ralink RT3070] + +usb:v050Dp935B* + ID_MODEL_FROM_DATABASE=F6D4050 N150 Enhanced Wireless Network Adapter v2000 [Ralink RT3070] + +usb:v050Dp945A* + ID_MODEL_FROM_DATABASE=F7D1101 v1 Basic Wireless Adapter [Realtek RTL8188SU] + +usb:v050Dp945B* + ID_MODEL_FROM_DATABASE=F7D1101 v2 Basic Wireless Adapter [Ralink RT3370] + +usb:v050DpD321* + ID_MODEL_FROM_DATABASE=Dynex DX-NUSB 802.11bgn Wireless Adapter [Broadcom BCM43231] + +usb:v050E* + ID_VENDOR_FROM_DATABASE=Neon Technology, Inc. + +usb:v050F* + ID_VENDOR_FROM_DATABASE=KC Technology, Inc. + +usb:v050Fp0001* + ID_MODEL_FROM_DATABASE=Hub + +usb:v050Fp0003* + ID_MODEL_FROM_DATABASE=KC82C160S Hub + +usb:v050Fp0180* + ID_MODEL_FROM_DATABASE=KC-180 IrDA Dongle + +usb:v050Fp0190* + ID_MODEL_FROM_DATABASE=KC2190 USB Host-to-Host cable + +usb:v0510* + ID_VENDOR_FROM_DATABASE=Sejin Electron, Inc. + +usb:v0510p0001* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0510p1000* + ID_MODEL_FROM_DATABASE=Keyboard with PS/2 Mouse Port + +usb:v0510pE001* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v0511* + ID_VENDOR_FROM_DATABASE=N'Able (DataBook) Technologies, Inc. + +usb:v0511p002B* + ID_MODEL_FROM_DATABASE=AOC DVB + +usb:v0512* + ID_VENDOR_FROM_DATABASE=Hualon Microelectronics Corp. + +usb:v0513* + ID_VENDOR_FROM_DATABASE=digital-X, Inc. + +usb:v0514* + ID_VENDOR_FROM_DATABASE=FCI Electronics + +usb:v0515* + ID_VENDOR_FROM_DATABASE=ACTC + +usb:v0516* + ID_VENDOR_FROM_DATABASE=Longwell Electronics + +usb:v0517* + ID_VENDOR_FROM_DATABASE=Butterfly Communications + +usb:v0518* + ID_VENDOR_FROM_DATABASE=EzKEY Corp. + +usb:v0518p0001* + ID_MODEL_FROM_DATABASE=USB to PS2 Adaptor v1.09 + +usb:v0518p0002* + ID_MODEL_FROM_DATABASE=EZ-9900C Keyboard + +usb:v0519* + ID_VENDOR_FROM_DATABASE=Star Micronics Co., Ltd + +usb:v0519p0003* + ID_MODEL_FROM_DATABASE=TSP100ECO/TSP100II + +usb:v0519pC002* + ID_MODEL_FROM_DATABASE=Xlive Bluetooth XBM-100S MP3 Player + +usb:v051A* + ID_VENDOR_FROM_DATABASE=WYSE Technology + +usb:v051ApA005* + ID_MODEL_FROM_DATABASE=Smart Display Version 9973 + +usb:v051B* + ID_VENDOR_FROM_DATABASE=Silicon Graphics + +usb:v051C* + ID_VENDOR_FROM_DATABASE=Shuttle, Inc. + +usb:v051Cp0005* + ID_MODEL_FROM_DATABASE=VFD Module + +usb:v051CpC001* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v051CpC002* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v051D* + ID_VENDOR_FROM_DATABASE=American Power Conversion + +usb:v051Dp0001* + ID_MODEL_FROM_DATABASE=UPS + +usb:v051Dp0002* + ID_MODEL_FROM_DATABASE=Uninterruptible Power Supply + +usb:v051Dp0003* + ID_MODEL_FROM_DATABASE=UPS + +usb:v051E* + ID_VENDOR_FROM_DATABASE=Scientific Atlanta, Inc. + +usb:v051F* + ID_VENDOR_FROM_DATABASE=IO Systems (Elite Electronics), Inc. + +usb:v0520* + ID_VENDOR_FROM_DATABASE=Taiwan Semiconductor Manufacturing Co. + +usb:v0521* + ID_VENDOR_FROM_DATABASE=Airborn Connectors + +usb:v0522* + ID_VENDOR_FROM_DATABASE=Advanced Connectek, Inc. + +usb:v0523* + ID_VENDOR_FROM_DATABASE=ATEN GmbH + +usb:v0524* + ID_VENDOR_FROM_DATABASE=Sola Electronics + +usb:v0525* + ID_VENDOR_FROM_DATABASE=Netchip Technology, Inc. + +usb:v0525p100D* + ID_MODEL_FROM_DATABASE=RFMD Bluetooth Device + +usb:v0525p1080* + ID_MODEL_FROM_DATABASE=NET1080 USB-USB Bridge + +usb:v0525p1200* + ID_MODEL_FROM_DATABASE=SSDC Adapter II + +usb:v0525p1265* + ID_MODEL_FROM_DATABASE=File-backed Storage Gadget + +usb:v0525p3424* + ID_MODEL_FROM_DATABASE=Lumidigm Venus fingerprint sensor + +usb:v0525pA0F0* + ID_MODEL_FROM_DATABASE=Cambridge Electronic Devices Power1401 mk 2 + +usb:v0525pA140* + ID_MODEL_FROM_DATABASE=USB Clik! 40 + +usb:v0525pA141* + ID_MODEL_FROM_DATABASE=(OME) PocketZip 40 MP3 Player Driver + +usb:v0525pA220* + ID_MODEL_FROM_DATABASE=GVC Bluetooth Wireless Adapter + +usb:v0525pA4A0* + ID_MODEL_FROM_DATABASE=Linux-USB "Gadget Zero" + +usb:v0525pA4A1* + ID_MODEL_FROM_DATABASE=Linux-USB Ethernet Gadget + +usb:v0525pA4A2* + ID_MODEL_FROM_DATABASE=Linux-USB Ethernet/RNDIS Gadget + +usb:v0525pA4A3* + ID_MODEL_FROM_DATABASE=Linux-USB user-mode isochronous source/sink + +usb:v0525pA4A4* + ID_MODEL_FROM_DATABASE=Linux-USB user-mode bulk source/sink + +usb:v0525pA4A5* + ID_MODEL_FROM_DATABASE=Pocketbook Pro 903 / Mobius 2 Action Cam + +usb:v0525pA4A6* + ID_MODEL_FROM_DATABASE=Linux-USB Serial Gadget + +usb:v0525pA4A7* + ID_MODEL_FROM_DATABASE=Linux-USB Serial Gadget (CDC ACM mode) + +usb:v0525pA4A8* + ID_MODEL_FROM_DATABASE=Linux-USB Printer Gadget + +usb:v0525pA4A9* + ID_MODEL_FROM_DATABASE=Linux-USB OBEX Gadget + +usb:v0525pA4AA* + ID_MODEL_FROM_DATABASE=Linux-USB CDC Composite Gadge (Ethernet and ACM) + +usb:v0526* + ID_VENDOR_FROM_DATABASE=Temic MHS S.A. + +usb:v0527* + ID_VENDOR_FROM_DATABASE=ALTRA + +usb:v0528* + ID_VENDOR_FROM_DATABASE=ATI Technologies, Inc. + +usb:v0528p7561* + ID_MODEL_FROM_DATABASE=TV Wonder + +usb:v0528p7562* + ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FN5) + +usb:v0528p7563* + ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FI) + +usb:v0528p7564* + ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FQ) + +usb:v0528p7565* + ID_MODEL_FROM_DATABASE=TV Wonder, Edition (NTSC+) + +usb:v0528p7566* + ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FN5) + +usb:v0528p7567* + ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FI) + +usb:v0528p7568* + ID_MODEL_FROM_DATABASE=TV Wonder, Edition (FQ) + +usb:v0528p7569* + ID_MODEL_FROM_DATABASE=Live! Pro (A) + +usb:v0528p756A* + ID_MODEL_FROM_DATABASE=Live! Pro Audio (O) + +usb:v0529* + ID_VENDOR_FROM_DATABASE=Aladdin Knowledge Systems + +usb:v0529p0001* + ID_MODEL_FROM_DATABASE=HASP copy protection dongle + +usb:v0529p030B* + ID_MODEL_FROM_DATABASE=eToken R1 v3.1.3.x + +usb:v0529p0313* + ID_MODEL_FROM_DATABASE=eToken R1 v3.2.3.x + +usb:v0529p031B* + ID_MODEL_FROM_DATABASE=eToken R1 v3.3.3.x + +usb:v0529p0323* + ID_MODEL_FROM_DATABASE=eToken R1 v3.4.3.x + +usb:v0529p0412* + ID_MODEL_FROM_DATABASE=eToken R2 v2.2.4.x + +usb:v0529p041A* + ID_MODEL_FROM_DATABASE=eToken R2 v2.2.4.x + +usb:v0529p0422* + ID_MODEL_FROM_DATABASE=eToken R2 v2.4.4.x + +usb:v0529p042A* + ID_MODEL_FROM_DATABASE=eToken R2 v2.5.4.x + +usb:v0529p050C* + ID_MODEL_FROM_DATABASE=eToken Pro v4.1.5.x + +usb:v0529p0514* + ID_MODEL_FROM_DATABASE=eToken Pro v4.2.5.4 + +usb:v0529p0600* + ID_MODEL_FROM_DATABASE=eToken Pro 64k (4.2) + +usb:v0529p0620* + ID_MODEL_FROM_DATABASE=Token JC + +usb:v052A* + ID_VENDOR_FROM_DATABASE=Crescent Heart Software + +usb:v052B* + ID_VENDOR_FROM_DATABASE=Tekom Technologies, Inc. + +usb:v052Bp0102* + ID_MODEL_FROM_DATABASE=Ca508A HP1020 Camera v.1.3.1.6 + +usb:v052Bp0801* + ID_MODEL_FROM_DATABASE=Yakumo MegaImage 37 + +usb:v052Bp1512* + ID_MODEL_FROM_DATABASE=Yakumo MegaImage IV + +usb:v052Bp1513* + ID_MODEL_FROM_DATABASE=Aosta CX100 Webcam + +usb:v052Bp1514* + ID_MODEL_FROM_DATABASE=Aosta CX100 Webcam Storage + +usb:v052Bp1905* + ID_MODEL_FROM_DATABASE=Yakumo MegaImage 47 + +usb:v052Bp1911* + ID_MODEL_FROM_DATABASE=Yakumo MegaImage 47 SL + +usb:v052Bp2202* + ID_MODEL_FROM_DATABASE=WDM Still Image Capture + +usb:v052Bp2203* + ID_MODEL_FROM_DATABASE=Sound Vision Stream Driver + +usb:v052Bp3A06* + ID_MODEL_FROM_DATABASE=DigiLife DDV-5120A + +usb:v052BpD001* + ID_MODEL_FROM_DATABASE=P35U Camera Capture + +usb:v052C* + ID_VENDOR_FROM_DATABASE=Canon Information Systems, Inc. + +usb:v052D* + ID_VENDOR_FROM_DATABASE=Avid Electronics Corp. + +usb:v052E* + ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp. + +usb:v052F* + ID_VENDOR_FROM_DATABASE=Unicore Software, Inc. + +usb:v0530* + ID_VENDOR_FROM_DATABASE=American Microsystems, Inc. + +usb:v0531* + ID_VENDOR_FROM_DATABASE=Wacom Technology Corp. + +usb:v0532* + ID_VENDOR_FROM_DATABASE=Systech Corp. + +usb:v0533* + ID_VENDOR_FROM_DATABASE=Alcatel Mobile Phones + +usb:v0534* + ID_VENDOR_FROM_DATABASE=Motorola, Inc. + +usb:v0535* + ID_VENDOR_FROM_DATABASE=LIH TZU Electric Co., Ltd + +usb:v0536* + ID_VENDOR_FROM_DATABASE=Hand Held Products (Welch Allyn, Inc.) + +usb:v0536p01A0* + ID_MODEL_FROM_DATABASE=PDT + +usb:v0537* + ID_VENDOR_FROM_DATABASE=Inventec Corp. + +usb:v0538* + ID_VENDOR_FROM_DATABASE=Caldera International, Inc. (SCO) + +usb:v0539* + ID_VENDOR_FROM_DATABASE=Shyh Shiun Terminals Co., Ltd + +usb:v053A* + ID_VENDOR_FROM_DATABASE=PrehKeyTec GmbH + +usb:v053Ap0B00* + ID_MODEL_FROM_DATABASE=Hub + +usb:v053Ap0B01* + ID_MODEL_FROM_DATABASE=Preh MCI 3100 + +usb:v053B* + ID_VENDOR_FROM_DATABASE=Global Village Communication + +usb:v053C* + ID_VENDOR_FROM_DATABASE=Institut of Microelectronic & Mechatronic Systems + +usb:v053D* + ID_VENDOR_FROM_DATABASE=Silicon Architect + +usb:v053E* + ID_VENDOR_FROM_DATABASE=Mobility Electronics + +usb:v053F* + ID_VENDOR_FROM_DATABASE=Synopsys, Inc. + +usb:v0540* + ID_VENDOR_FROM_DATABASE=UniAccess AB + +usb:v0540p0101* + ID_MODEL_FROM_DATABASE=Panache Surf ISDN TA + +usb:v0541* + ID_VENDOR_FROM_DATABASE=Sirf Technology, Inc. + +usb:v0543* + ID_VENDOR_FROM_DATABASE=ViewSonic Corp. + +usb:v0543p00FE* + ID_MODEL_FROM_DATABASE=G773 Monitor Hub + +usb:v0543p00FF* + ID_MODEL_FROM_DATABASE=P815 Monitor Hub + +usb:v0543p0BF2* + ID_MODEL_FROM_DATABASE=airpanel V150 Wireless Smart Display + +usb:v0543p0BF3* + ID_MODEL_FROM_DATABASE=airpanel V110 Wireless Smart Display + +usb:v0543p0ED9* + ID_MODEL_FROM_DATABASE=Color Pocket PC V35 + +usb:v0543p0F01* + ID_MODEL_FROM_DATABASE=airsync Wi-Fi Wireless Adapter + +usb:v0543p1527* + ID_MODEL_FROM_DATABASE=Color Pocket PC V36 + +usb:v0543p1529* + ID_MODEL_FROM_DATABASE=Color Pocket PC V37 + +usb:v0543p152B* + ID_MODEL_FROM_DATABASE=Color Pocket PC V38 + +usb:v0543p152E* + ID_MODEL_FROM_DATABASE=Pocket PC + +usb:v0543p1921* + ID_MODEL_FROM_DATABASE=Communicator Pocket PC + +usb:v0543p1922* + ID_MODEL_FROM_DATABASE=Smartphone + +usb:v0543p1923* + ID_MODEL_FROM_DATABASE=Pocket PC V30 + +usb:v0543p1A11* + ID_MODEL_FROM_DATABASE=Wireless 802.11g Adapter + +usb:v0543p1E60* + ID_MODEL_FROM_DATABASE=TA310 - ATSC/NTSC/PAL Driver(PCM4) + +usb:v0543p4153* + ID_MODEL_FROM_DATABASE=ViewSonic G773 Control (?) + +usb:v0544* + ID_VENDOR_FROM_DATABASE=Cristie Electronics, Ltd + +usb:v0545* + ID_VENDOR_FROM_DATABASE=Xirlink, Inc. + +usb:v0545p7333* + ID_MODEL_FROM_DATABASE=Trution Web Camera + +usb:v0545p8002* + ID_MODEL_FROM_DATABASE=IBM NetCamera + +usb:v0545p8009* + ID_MODEL_FROM_DATABASE=Veo PC Camera + +usb:v0545p800C* + ID_MODEL_FROM_DATABASE=Veo Stingray + +usb:v0545p800D* + ID_MODEL_FROM_DATABASE=Veo PC Camera + +usb:v0545p8080* + ID_MODEL_FROM_DATABASE=IBM C-It Webcam + +usb:v0545p808A* + ID_MODEL_FROM_DATABASE=Veo PC Camera + +usb:v0545p808B* + ID_MODEL_FROM_DATABASE=Veo Stingray + +usb:v0545p808D* + ID_MODEL_FROM_DATABASE=Veo PC Camera + +usb:v0545p810A* + ID_MODEL_FROM_DATABASE=Veo Advanced Connect Webcam + +usb:v0545p810B* + ID_MODEL_FROM_DATABASE=Veo PC Camera + +usb:v0545p810C* + ID_MODEL_FROM_DATABASE=Veo PC Camera + +usb:v0545p8135* + ID_MODEL_FROM_DATABASE=Veo Mobile/Advanced Web Camera + +usb:v0545p813A* + ID_MODEL_FROM_DATABASE=Veo PC Camera + +usb:v0545p813B* + ID_MODEL_FROM_DATABASE=Veo PC Camera + +usb:v0545p813C* + ID_MODEL_FROM_DATABASE=Veo Mobile/Advanced Web Camera + +usb:v0545p8333* + ID_MODEL_FROM_DATABASE=Veo Stingray/Connect Web Camera + +usb:v0545p888C* + ID_MODEL_FROM_DATABASE=eVision 123 digital camera + +usb:v0545p888D* + ID_MODEL_FROM_DATABASE=eVision 123 digital camera + +usb:v0546* + ID_VENDOR_FROM_DATABASE=Polaroid Corp. + +usb:v0546p0DAF* + ID_MODEL_FROM_DATABASE=PDC 2300Z + +usb:v0546p1BED* + ID_MODEL_FROM_DATABASE=PDC 1320 Camera + +usb:v0546p3097* + ID_MODEL_FROM_DATABASE=PDC 310 + +usb:v0546p3155* + ID_MODEL_FROM_DATABASE=PDC 3070 Camera + +usb:v0546p3187* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0546p3191* + ID_MODEL_FROM_DATABASE=Ion 80 Camera + +usb:v0546p3273* + ID_MODEL_FROM_DATABASE=PDC 2030 Camera + +usb:v0546p3304* + ID_MODEL_FROM_DATABASE=a500 Digital Camera + +usb:v0546pDCCF* + ID_MODEL_FROM_DATABASE=Sound Vision Stream Driver + +usb:v0547* + ID_VENDOR_FROM_DATABASE=Anchor Chips, Inc. + +usb:v0547p0001* + ID_MODEL_FROM_DATABASE=ICSI Bluetooth Device + +usb:v0547p0080* + ID_MODEL_FROM_DATABASE=I3SYSTEM HYUNY + +usb:v0547p1002* + ID_MODEL_FROM_DATABASE=Python2 WDM Encoder + +usb:v0547p1006* + ID_MODEL_FROM_DATABASE=Hantek DSO-2100 UF + +usb:v0547p2131* + ID_MODEL_FROM_DATABASE=AN2131 EZUSB Microcontroller + +usb:v0547p2235* + ID_MODEL_FROM_DATABASE=AN2235 EZUSB-FX Microcontroller + +usb:v0547p2710* + ID_MODEL_FROM_DATABASE=EZ-Link Loader (EZLNKLDR.SYS) + +usb:v0547p2720* + ID_MODEL_FROM_DATABASE=AN2720 USB-USB Bridge + +usb:v0547p2727* + ID_MODEL_FROM_DATABASE=Xircom PGUNET USB-USB Bridge + +usb:v0547p2750* + ID_MODEL_FROM_DATABASE=EZ-Link (EZLNKUSB.SYS) + +usb:v0547p2810* + ID_MODEL_FROM_DATABASE=Cypress ATAPI Bridge + +usb:v0547p4018* + ID_MODEL_FROM_DATABASE=AmScope MU1803 + +usb:v0547p4D90* + ID_MODEL_FROM_DATABASE=AmScope MD1900 camera + +usb:v0547p6010* + ID_MODEL_FROM_DATABASE=AmScope MU1000 camera + +usb:v0547p6510* + ID_MODEL_FROM_DATABASE=Touptek UCMOS05100KPA + +usb:v0547p7000* + ID_MODEL_FROM_DATABASE=PowerSpec MCE460 Front Panel LED Display + +usb:v0547p7777* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0547p9999* + ID_MODEL_FROM_DATABASE=AN2131 uninitialized (?) + +usb:v0548* + ID_VENDOR_FROM_DATABASE=Tyan Computer Corp. + +usb:v0548p1005* + ID_MODEL_FROM_DATABASE=EZ Cart II GameBoy Flash Programmer + +usb:v0549* + ID_VENDOR_FROM_DATABASE=Pixera Corp. + +usb:v054A* + ID_VENDOR_FROM_DATABASE=Fujitsu Microelectronics, Inc. + +usb:v054B* + ID_VENDOR_FROM_DATABASE=New Media Corp. + +usb:v054C* + ID_VENDOR_FROM_DATABASE=Sony Corp. + +usb:v054Cp0001* + ID_MODEL_FROM_DATABASE=HUB + +usb:v054Cp0002* + ID_MODEL_FROM_DATABASE=Standard HUB + +usb:v054Cp0010* + ID_MODEL_FROM_DATABASE=Cyber-shot, Mavica (msc) + +usb:v054Cp0014* + ID_MODEL_FROM_DATABASE=Nogatech USBVision (SY) + +usb:v054Cp0022* + ID_MODEL_FROM_DATABASE=Storage Adapter V2 (TPP) + +usb:v054Cp0023* + ID_MODEL_FROM_DATABASE=CD Writer + +usb:v054Cp0024* + ID_MODEL_FROM_DATABASE=Mavica CD-1000 Camera + +usb:v054Cp0025* + ID_MODEL_FROM_DATABASE=NW-MS7 Walkman MemoryStick Reader + +usb:v054Cp002B* + ID_MODEL_FROM_DATABASE=Portable USB Harddrive V2 + +usb:v054Cp002C* + ID_MODEL_FROM_DATABASE=USB Floppy Disk Drive + +usb:v054Cp002D* + ID_MODEL_FROM_DATABASE=MSAC-US1 MemoryStick Reader + +usb:v054Cp002E* + ID_MODEL_FROM_DATABASE=HandyCam MemoryStick Reader + +usb:v054Cp0030* + ID_MODEL_FROM_DATABASE=Storage Adapter V2 (TPP) + +usb:v054Cp0032* + ID_MODEL_FROM_DATABASE=MemoryStick MSC-U01 Reader + +usb:v054Cp0035* + ID_MODEL_FROM_DATABASE=Network Walkman (E) + +usb:v054Cp0036* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0037* + ID_MODEL_FROM_DATABASE=MG Memory Stick Reader/Writer + +usb:v054Cp0038* + ID_MODEL_FROM_DATABASE=Clie PEG-S300/D PalmOS PDA + +usb:v054Cp0039* + ID_MODEL_FROM_DATABASE=Network Walkman (MS) + +usb:v054Cp003C* + ID_MODEL_FROM_DATABASE=VAIO-MX LCD Control + +usb:v054Cp0045* + ID_MODEL_FROM_DATABASE=Digital Imaging Video + +usb:v054Cp0046* + ID_MODEL_FROM_DATABASE=Network Walkman + +usb:v054Cp0049* + ID_MODEL_FROM_DATABASE=UP-D895 + +usb:v054Cp004A* + ID_MODEL_FROM_DATABASE=Memory Stick Hi-Fi System + +usb:v054Cp004B* + ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer + +usb:v054Cp004E* + ID_MODEL_FROM_DATABASE=DSC-xxx (ptp) + +usb:v054Cp0056* + ID_MODEL_FROM_DATABASE=MG Memory Stick Reader/Writer + +usb:v054Cp0058* + ID_MODEL_FROM_DATABASE=Clie PEG-N7x0C PalmOS PDA Mass Storage + +usb:v054Cp0066* + ID_MODEL_FROM_DATABASE=Clie PEG-N7x0C/PEG-T425 PalmOS PDA Serial + +usb:v054Cp0067* + ID_MODEL_FROM_DATABASE=CMR-PC3 Webcam + +usb:v054Cp0069* + ID_MODEL_FROM_DATABASE=Memorystick MSC-U03 Reader + +usb:v054Cp006C* + ID_MODEL_FROM_DATABASE=FeliCa S310 [PaSoRi] + +usb:v054Cp006D* + ID_MODEL_FROM_DATABASE=Clie PEG-T425 PDA Mass Storage + +usb:v054Cp006F* + ID_MODEL_FROM_DATABASE=Network Walkman (EV) + +usb:v054Cp0073* + ID_MODEL_FROM_DATABASE=Storage CRX1750U + +usb:v054Cp0075* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0076* + ID_MODEL_FROM_DATABASE=Storage Adapter ACR-U20 + +usb:v054Cp007C* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp007F* + ID_MODEL_FROM_DATABASE=IC Recorder (MS) + +usb:v054Cp0080* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0081* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0084* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0085* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0086* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp008B* + ID_MODEL_FROM_DATABASE=Micro Vault 64M Mass Storage + +usb:v054Cp0095* + ID_MODEL_FROM_DATABASE=Clie s360 + +usb:v054Cp0099* + ID_MODEL_FROM_DATABASE=Clie NR70 PDA Mass Storage + +usb:v054Cp009A* + ID_MODEL_FROM_DATABASE=Clie NR70 PDA Serial + +usb:v054Cp00AB* + ID_MODEL_FROM_DATABASE=Visual Communication Camera (PCGA-UVC10) + +usb:v054Cp00AF* + ID_MODEL_FROM_DATABASE=DPP-EX Series Digital Photo Printer + +usb:v054Cp00BF* + ID_MODEL_FROM_DATABASE=IC Recorder (S) + +usb:v054Cp00C0* + ID_MODEL_FROM_DATABASE=Handycam DCR-30 + +usb:v054Cp00C6* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp00C7* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp00C8* + ID_MODEL_FROM_DATABASE=MZ-N710 Minidisc Walkman + +usb:v054Cp00C9* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp00CA* + ID_MODEL_FROM_DATABASE=MZ-DN430 Minidisc Walkman + +usb:v054Cp00CB* + ID_MODEL_FROM_DATABASE=MSAC-US20 Memory Stick Reader + +usb:v054Cp00DA* + ID_MODEL_FROM_DATABASE=Clie nx60 + +usb:v054Cp00E8* + ID_MODEL_FROM_DATABASE=Network Walkman (MS) + +usb:v054Cp00E9* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v054Cp00EB* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0101* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0103* + ID_MODEL_FROM_DATABASE=IC Recorder (ST) + +usb:v054Cp0105* + ID_MODEL_FROM_DATABASE=Micro Vault Hub + +usb:v054Cp0107* + ID_MODEL_FROM_DATABASE=VCC-U01 Visual Communication Camera + +usb:v054Cp0110* + ID_MODEL_FROM_DATABASE=Digital Imaging Video + +usb:v054Cp0113* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0116* + ID_MODEL_FROM_DATABASE=IC Recorder (P) + +usb:v054Cp0144* + ID_MODEL_FROM_DATABASE=Clie PEG-TH55 PDA + +usb:v054Cp0147* + ID_MODEL_FROM_DATABASE=Visual Communication Camera (PCGA-UVC11) + +usb:v054Cp014C* + ID_MODEL_FROM_DATABASE=Aiwa AM-NX9 Net MD Music Recorder MDLP + +usb:v054Cp014D* + ID_MODEL_FROM_DATABASE=Memory Stick Reader/Writer + +usb:v054Cp0154* + ID_MODEL_FROM_DATABASE=Eyetoy Audio Device + +usb:v054Cp0155* + ID_MODEL_FROM_DATABASE=Eyetoy Video Device + +usb:v054Cp015F* + ID_MODEL_FROM_DATABASE=IC Recorder (BM) + +usb:v054Cp0169* + ID_MODEL_FROM_DATABASE=Clie PEG-TJ35 PDA Serial + +usb:v054Cp016A* + ID_MODEL_FROM_DATABASE=Clie PEG-TJ35 PDA Mass Storage + +usb:v054Cp016B* + ID_MODEL_FROM_DATABASE=Mobile HDD + +usb:v054Cp016D* + ID_MODEL_FROM_DATABASE=IC Recorder (SX) + +usb:v054Cp016E* + ID_MODEL_FROM_DATABASE=DPP-EX50 Digital Photo Printer + +usb:v054Cp0171* + ID_MODEL_FROM_DATABASE=Fingerprint Sensor 3500 + +usb:v054Cp017E* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp017F* + ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN + +usb:v054Cp0180* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0181* + ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN + +usb:v054Cp0182* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0183* + ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN + +usb:v054Cp0184* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0185* + ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN + +usb:v054Cp0186* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0187* + ID_MODEL_FROM_DATABASE=Hi-MD MZ-NH600 WALKMAN + +usb:v054Cp0188* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp018A* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp018B* + ID_MODEL_FROM_DATABASE=Hi-MD SOUND GATE + +usb:v054Cp019E* + ID_MODEL_FROM_DATABASE=Micro Vault 1.0G Mass Storage + +usb:v054Cp01AD* + ID_MODEL_FROM_DATABASE=ATRAC HDD PA + +usb:v054Cp01BB* + ID_MODEL_FROM_DATABASE=FeliCa S320 [PaSoRi] + +usb:v054Cp01BD* + ID_MODEL_FROM_DATABASE=MRW62E Multi-Card Reader/Writer + +usb:v054Cp01C3* + ID_MODEL_FROM_DATABASE=NW-E55 Network Walkman + +usb:v054Cp01C6* + ID_MODEL_FROM_DATABASE=MEMORY P-AUDIO + +usb:v054Cp01C7* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v054Cp01C8* + ID_MODEL_FROM_DATABASE=PSP Type A + +usb:v054Cp01C9* + ID_MODEL_FROM_DATABASE=PSP Type B + +usb:v054Cp01D0* + ID_MODEL_FROM_DATABASE=DVD+RW External Drive DRU-700A + +usb:v054Cp01D5* + ID_MODEL_FROM_DATABASE=IC RECORDER + +usb:v054Cp01DE* + ID_MODEL_FROM_DATABASE=VRD-VC10 [Video Capture] + +usb:v054Cp01E7* + ID_MODEL_FROM_DATABASE=UP-D897 + +usb:v054Cp01E8* + ID_MODEL_FROM_DATABASE=UP-DR150 Photo Printer + +usb:v054Cp01E9* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp01EA* + ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN + +usb:v054Cp01EE* + ID_MODEL_FROM_DATABASE=IC RECORDER + +usb:v054Cp01FA* + ID_MODEL_FROM_DATABASE=IC Recorder (P) + +usb:v054Cp01FB* + ID_MODEL_FROM_DATABASE=NW-E405 Network Walkman + +usb:v054Cp020F* + ID_MODEL_FROM_DATABASE=Device + +usb:v054Cp0210* + ID_MODEL_FROM_DATABASE=ATRAC HDD PA + +usb:v054Cp0219* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp021A* + ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN + +usb:v054Cp021B* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp021C* + ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN + +usb:v054Cp021D* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0226* + ID_MODEL_FROM_DATABASE=UP-CR10L + +usb:v054Cp0227* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v054Cp022C* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp022D* + ID_MODEL_FROM_DATABASE=Hi-MD AUDIO + +usb:v054Cp0233* + ID_MODEL_FROM_DATABASE=ATRAC HDD PA + +usb:v054Cp0236* + ID_MODEL_FROM_DATABASE=Mobile HDD + +usb:v054Cp023B* + ID_MODEL_FROM_DATABASE=DVD+RW External Drive DRU-800UL + +usb:v054Cp023C* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp023D* + ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN + +usb:v054Cp0243* + ID_MODEL_FROM_DATABASE=MicroVault Flash Drive + +usb:v054Cp024B* + ID_MODEL_FROM_DATABASE=Vaio VGX Mouse + +usb:v054Cp0257* + ID_MODEL_FROM_DATABASE=IFU-WLM2 USB Wireless LAN Module (Wireless Mode) + +usb:v054Cp0258* + ID_MODEL_FROM_DATABASE=IFU-WLM2 USB Wireless LAN Module (Memory Mode) + +usb:v054Cp0259* + ID_MODEL_FROM_DATABASE=IC RECORDER + +usb:v054Cp0267* + ID_MODEL_FROM_DATABASE=Tachikoma Device + +usb:v054Cp0268* + ID_MODEL_FROM_DATABASE=Batoh Device / PlayStation 3 Controller + +usb:v054Cp0269* + ID_MODEL_FROM_DATABASE=HDD WALKMAN + +usb:v054Cp026A* + ID_MODEL_FROM_DATABASE=HDD WALKMAN + +usb:v054Cp0271* + ID_MODEL_FROM_DATABASE=IC Recorder (P) + +usb:v054Cp027C* + ID_MODEL_FROM_DATABASE=NETWORK WALKMAN + +usb:v054Cp027E* + ID_MODEL_FROM_DATABASE=SONY Communicator + +usb:v054Cp027F* + ID_MODEL_FROM_DATABASE=IC RECORDER + +usb:v054Cp0286* + ID_MODEL_FROM_DATABASE=Net MD + +usb:v054Cp0287* + ID_MODEL_FROM_DATABASE=Hi-MD WALKMAN + +usb:v054Cp0290* + ID_MODEL_FROM_DATABASE=VGP-UVC100 Visual Communication Camera + +usb:v054Cp029B* + ID_MODEL_FROM_DATABASE=PRS-500 eBook reader + +usb:v054Cp02A5* + ID_MODEL_FROM_DATABASE=MicroVault Flash Drive + +usb:v054Cp02AF* + ID_MODEL_FROM_DATABASE=Handycam DCR-DVD306E + +usb:v054Cp02C4* + ID_MODEL_FROM_DATABASE=Device + +usb:v054Cp02D1* + ID_MODEL_FROM_DATABASE=DVD RW + +usb:v054Cp02D2* + ID_MODEL_FROM_DATABASE=PSP Slim + +usb:v054Cp02D8* + ID_MODEL_FROM_DATABASE=SBAC-US10 SxS PRO memory card reader/writer + +usb:v054Cp02E1* + ID_MODEL_FROM_DATABASE=FeliCa S330 [PaSoRi] + +usb:v054Cp02EA* + ID_MODEL_FROM_DATABASE=PlayStation 3 Memory Card Adaptor + +usb:v054Cp02F9* + ID_MODEL_FROM_DATABASE=DSC-H9 + +usb:v054Cp0317* + ID_MODEL_FROM_DATABASE=WALKMAN + +usb:v054Cp031A* + ID_MODEL_FROM_DATABASE=Walkman NWD-B103F + +usb:v054Cp031E* + ID_MODEL_FROM_DATABASE=PRS-300/PRS-505 eBook reader + +usb:v054Cp0325* + ID_MODEL_FROM_DATABASE=NWZ-A818 + +usb:v054Cp033E* + ID_MODEL_FROM_DATABASE=DSC-W120/W290 + +usb:v054Cp0346* + ID_MODEL_FROM_DATABASE=Handycam DCR-SR55E + +usb:v054Cp0348* + ID_MODEL_FROM_DATABASE=HandyCam HDR-TG3E + +usb:v054Cp035B* + ID_MODEL_FROM_DATABASE=Walkman NWZ-A828 + +usb:v054Cp035C* + ID_MODEL_FROM_DATABASE=NWZ-A726/A728/A729 + +usb:v054Cp035F* + ID_MODEL_FROM_DATABASE=UP-DR200 Photo Printer + +usb:v054Cp0382* + ID_MODEL_FROM_DATABASE=Memory Stick PRO-HG Duo Adaptor (MSAC-UAH1) + +usb:v054Cp0385* + ID_MODEL_FROM_DATABASE=Walkman NWZ-E436F + +usb:v054Cp0387* + ID_MODEL_FROM_DATABASE=IC Recorder (P) + +usb:v054Cp03BC* + ID_MODEL_FROM_DATABASE=Webbie HD - MHS-CM1 + +usb:v054Cp03CC* + ID_MODEL_FROM_DATABASE=SD Card Reader + +usb:v054Cp03D1* + ID_MODEL_FROM_DATABASE=DPF-X95 + +usb:v054Cp03D3* + ID_MODEL_FROM_DATABASE=DR-BT100CX + +usb:v054Cp03D5* + ID_MODEL_FROM_DATABASE=PlayStation Move motion controller + +usb:v054Cp03FC* + ID_MODEL_FROM_DATABASE=WALKMAN [NWZ-E345] + +usb:v054Cp03FD* + ID_MODEL_FROM_DATABASE=Walkman NWZ-E443 + +usb:v054Cp042F* + ID_MODEL_FROM_DATABASE=PlayStation Move navigation controller + +usb:v054Cp0440* + ID_MODEL_FROM_DATABASE=DSC-H55 + +usb:v054Cp0485* + ID_MODEL_FROM_DATABASE=MHS-PM5 HD camcorder + +usb:v054Cp04CB* + ID_MODEL_FROM_DATABASE=WALKMAN NWZ-E354 + +usb:v054Cp0541* + ID_MODEL_FROM_DATABASE=DSC-HX100V [Cybershot Digital Still Camera] + +usb:v054Cp05C4* + ID_MODEL_FROM_DATABASE=DualShock 4 [CUH-ZCT1x] + +usb:v054Cp0689* + ID_MODEL_FROM_DATABASE=Walkman NWZ-B173F + +usb:v054Cp06BB* + ID_MODEL_FROM_DATABASE=WALKMAN NWZ-F805 + +usb:v054Cp06C3* + ID_MODEL_FROM_DATABASE=RC-S380 + +usb:v054Cp07C4* + ID_MODEL_FROM_DATABASE=ILCE-6000 (aka Alpha-6000) in Mass Storage mode + +usb:v054Cp082F* + ID_MODEL_FROM_DATABASE=Walkman NWZW Series + +usb:v054Cp0847* + ID_MODEL_FROM_DATABASE=WG-C10 Portable Wireless Server + +usb:v054Cp0884* + ID_MODEL_FROM_DATABASE=MDR-ZX770BN [Wireless Noise Canceling Stereo Headset] + +usb:v054Cp088C* + ID_MODEL_FROM_DATABASE=Portable Headphone Amplifier + +usb:v054Cp08B7* + ID_MODEL_FROM_DATABASE=ILCE-6000 (aka Alpha-6000) in MTP mode + +usb:v054Cp094E* + ID_MODEL_FROM_DATABASE=ILCE-6000 (aka Alpha-6000) in PC Remote mode + +usb:v054Cp0994* + ID_MODEL_FROM_DATABASE=ILCE-6000 (aka Alpha-6000) in charging mode + +usb:v054Cp09CC* + ID_MODEL_FROM_DATABASE=DualShock 4 [CUH-ZCT2x] + +usb:v054Cp0BA0* + ID_MODEL_FROM_DATABASE=Dualshock4 Wireless Adaptor + +usb:v054Cp0BB5* + ID_MODEL_FROM_DATABASE=Headset MDR-1000X + +usb:v054Cp0C02* + ID_MODEL_FROM_DATABASE=ILCE-7M3 [A7III] in Mass Storage mode + +usb:v054Cp0C03* + ID_MODEL_FROM_DATABASE=ILCE-7M3 [A7III] in MTP mode + +usb:v054Cp0C34* + ID_MODEL_FROM_DATABASE=ILCE-7M3 [A7III] in PC Remote mode + +usb:v054Cp0CDA* + ID_MODEL_FROM_DATABASE=PlayStation Classic controller + +usb:v054Cp1000* + ID_MODEL_FROM_DATABASE=Wireless Buzz! Receiver + +usb:v054D* + ID_VENDOR_FROM_DATABASE=Try Corp. + +usb:v054E* + ID_VENDOR_FROM_DATABASE=Proside Corp. + +usb:v054F* + ID_VENDOR_FROM_DATABASE=WYSE Technology Taiwan + +usb:v0550* + ID_VENDOR_FROM_DATABASE=Fuji Xerox Co., Ltd + +usb:v0550p0002* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v0550p0004* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v0550p0005* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v0550p000B* + ID_MODEL_FROM_DATABASE=Workcentre 24 + +usb:v0550p014E* + ID_MODEL_FROM_DATABASE=CM215b Printer + +usb:v0550p0165* + ID_MODEL_FROM_DATABASE=DocuPrint M215b + +usb:v0551* + ID_VENDOR_FROM_DATABASE=CompuTrend Systems, Inc. + +usb:v0552* + ID_VENDOR_FROM_DATABASE=Philips Monitors + +usb:v0553* + ID_VENDOR_FROM_DATABASE=STMicroelectronics Imaging Division (VLSI Vision) + +usb:v0553p0001* + ID_MODEL_FROM_DATABASE=TerraCAM + +usb:v0553p0002* + ID_MODEL_FROM_DATABASE=CPiA Webcam + +usb:v0553p0100* + ID_MODEL_FROM_DATABASE=STV0672 Camera + +usb:v0553p0140* + ID_MODEL_FROM_DATABASE=Video Camera + +usb:v0553p0150* + ID_MODEL_FROM_DATABASE=CDE CAM 100 + +usb:v0553p0151* + ID_MODEL_FROM_DATABASE=Digital Blue QX5 Microscope + +usb:v0553p0200* + ID_MODEL_FROM_DATABASE=Dual-mode Camera0 + +usb:v0553p0201* + ID_MODEL_FROM_DATABASE=Dual-mode Camera1 + +usb:v0553p0202* + ID_MODEL_FROM_DATABASE=STV0680 Camera + +usb:v0553p0674* + ID_MODEL_FROM_DATABASE=Multi-mode Camera + +usb:v0553p0679* + ID_MODEL_FROM_DATABASE=NMS Video Camera (Webcam) + +usb:v0553p1002* + ID_MODEL_FROM_DATABASE=Che-ez! Splash + +usb:v0554* + ID_VENDOR_FROM_DATABASE=Dictaphone Corp. + +usb:v0555* + ID_VENDOR_FROM_DATABASE=ANAM S&T Co., Ltd + +usb:v0556* + ID_VENDOR_FROM_DATABASE=Asahi Kasei Microsystems Co., Ltd + +usb:v0556p0001* + ID_MODEL_FROM_DATABASE=AK5370 I/F A/D Converter + +usb:v0557* + ID_VENDOR_FROM_DATABASE=ATEN International Co., Ltd + +usb:v0557p2001* + ID_MODEL_FROM_DATABASE=UC-1284 Printer Port + +usb:v0557p2002* + ID_MODEL_FROM_DATABASE=10Mbps Ethernet [klsi] + +usb:v0557p2004* + ID_MODEL_FROM_DATABASE=UC-100KM PS/2 Mouse and Keyboard adapter + +usb:v0557p2006* + ID_MODEL_FROM_DATABASE=UC-1284B Printer Port + +usb:v0557p2007* + ID_MODEL_FROM_DATABASE=UC-110T 100Mbps Ethernet [pegasus] + +usb:v0557p2008* + ID_MODEL_FROM_DATABASE=UC-232A Serial Port [pl2303] + +usb:v0557p2009* + ID_MODEL_FROM_DATABASE=UC-210T Ethernet + +usb:v0557p2011* + ID_MODEL_FROM_DATABASE=UC-2324 4xSerial Ports [mos7840] + +usb:v0557p2202* + ID_MODEL_FROM_DATABASE=CS124U Miniview II KVM Switch + +usb:v0557p2212* + ID_MODEL_FROM_DATABASE=Keyboard/Mouse + +usb:v0557p2213* + ID_MODEL_FROM_DATABASE=CS682 2-Port USB 2.0 DVI KVM Switch + +usb:v0557p2221* + ID_MODEL_FROM_DATABASE=Winbond Hermon + +usb:v0557p2404* + ID_MODEL_FROM_DATABASE=4-port switch + +usb:v0557p2600* + ID_MODEL_FROM_DATABASE=IDE Bridge + +usb:v0557p2701* + ID_MODEL_FROM_DATABASE=CE700A KVM Extender + +usb:v0557p4000* + ID_MODEL_FROM_DATABASE=DSB-650 10Mbps Ethernet [klsi] + +usb:v0557p7000* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0557p7820* + ID_MODEL_FROM_DATABASE=UC-2322 2xSerial Ports [mos7820] + +usb:v0557p8021* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0558* + ID_VENDOR_FROM_DATABASE=Truevision, Inc. + +usb:v0558p1009* + ID_MODEL_FROM_DATABASE=GW Instek GDS-1000 Oscilloscope + +usb:v0558p100A* + ID_MODEL_FROM_DATABASE=GW Instek GDS-1000A Oscilloscope + +usb:v0558p2009* + ID_MODEL_FROM_DATABASE=GW Instek GDS-2000 Oscilloscope + +usb:v0559* + ID_VENDOR_FROM_DATABASE=Cadence Design Systems, Inc. + +usb:v055A* + ID_VENDOR_FROM_DATABASE=Kenwood USA + +usb:v055B* + ID_VENDOR_FROM_DATABASE=KnowledgeTek, Inc. + +usb:v055C* + ID_VENDOR_FROM_DATABASE=Proton Electronic Ind. + +usb:v055D* + ID_VENDOR_FROM_DATABASE=Samsung Electro-Mechanics Co. + +usb:v055Dp0001* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v055Dp0BB1* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v055Dp1030* + ID_MODEL_FROM_DATABASE=Optical Wheel Mouse (OMS3CB/OMGB30) + +usb:v055Dp1031* + ID_MODEL_FROM_DATABASE=Optical Wheel Mouse (OMA3CB/OMGI30) + +usb:v055Dp1040* + ID_MODEL_FROM_DATABASE=Mouse HID Device + +usb:v055Dp1050* + ID_MODEL_FROM_DATABASE=E-Mail Optical Wheel Mouse (OMS3CE) + +usb:v055Dp1080* + ID_MODEL_FROM_DATABASE=Optical Wheel Mouse (OMS3CH) + +usb:v055Dp2020* + ID_MODEL_FROM_DATABASE=Floppy Disk Drive + +usb:v055Dp6780* + ID_MODEL_FROM_DATABASE=Keyboard V1 + +usb:v055Dp6781* + ID_MODEL_FROM_DATABASE=Keyboard Mouse + +usb:v055Dp8001* + ID_MODEL_FROM_DATABASE=E.M. Hub + +usb:v055Dp9000* + ID_MODEL_FROM_DATABASE=AnyCam [pwc] + +usb:v055Dp9001* + ID_MODEL_FROM_DATABASE=MPC-C30 AnyCam Premium for Notebooks [pwc] + +usb:v055DpA000* + ID_MODEL_FROM_DATABASE=SWL-2100U + +usb:v055DpA010* + ID_MODEL_FROM_DATABASE=WLAN Adapter(SWL-2300) + +usb:v055DpA011* + ID_MODEL_FROM_DATABASE=Boot Device + +usb:v055DpA012* + ID_MODEL_FROM_DATABASE=WLAN Adapter(SWL-2300) + +usb:v055DpA013* + ID_MODEL_FROM_DATABASE=WLAN Adapter(SWL-2350) + +usb:v055DpA230* + ID_MODEL_FROM_DATABASE=Boot Device + +usb:v055DpB000* + ID_MODEL_FROM_DATABASE=11Mbps WLAN Mini Adapter + +usb:v055DpB230* + ID_MODEL_FROM_DATABASE=Netopia 802.11b WLAN Adapter + +usb:v055DpB231* + ID_MODEL_FROM_DATABASE=LG Wireless LAN 11b Adapter + +usb:v055E* + ID_VENDOR_FROM_DATABASE=CTX Opto-Electronics Corp. + +usb:v055F* + ID_VENDOR_FROM_DATABASE=Mustek Systems, Inc. + +usb:v055Fp0001* + ID_MODEL_FROM_DATABASE=ScanExpress 1200 CU + +usb:v055Fp0002* + ID_MODEL_FROM_DATABASE=ScanExpress 600 CU + +usb:v055Fp0003* + ID_MODEL_FROM_DATABASE=ScanExpress 1200 USB + +usb:v055Fp0006* + ID_MODEL_FROM_DATABASE=ScanExpress 1200 UB + +usb:v055Fp0007* + ID_MODEL_FROM_DATABASE=ScanExpress 1200 USB Plus + +usb:v055Fp0008* + ID_MODEL_FROM_DATABASE=ScanExpress 1200 CU Plus + +usb:v055Fp0010* + ID_MODEL_FROM_DATABASE=BearPaw 1200F + +usb:v055Fp0210* + ID_MODEL_FROM_DATABASE=ScanExpress A3 USB + +usb:v055Fp0218* + ID_MODEL_FROM_DATABASE=BearPaw 2400 TA + +usb:v055Fp0219* + ID_MODEL_FROM_DATABASE=BearPaw 2400 TA Plus + +usb:v055Fp021A* + ID_MODEL_FROM_DATABASE=BearPaw 2448 TA Plus + +usb:v055Fp021B* + ID_MODEL_FROM_DATABASE=BearPaw 1200 CU Plus + +usb:v055Fp021C* + ID_MODEL_FROM_DATABASE=BearPaw 1200 CU Plus + +usb:v055Fp021D* + ID_MODEL_FROM_DATABASE=BearPaw 2400 CU Plus + +usb:v055Fp021E* + ID_MODEL_FROM_DATABASE=BearPaw 1200 TA/CS + +usb:v055Fp021F* + ID_MODEL_FROM_DATABASE=SNAPSCAN e22 + +usb:v055Fp0400* + ID_MODEL_FROM_DATABASE=BearPaw 2400 TA Pro + +usb:v055Fp0401* + ID_MODEL_FROM_DATABASE=P 3600 A3 Pro + +usb:v055Fp0408* + ID_MODEL_FROM_DATABASE=BearPaw 2448 CU Pro + +usb:v055Fp0409* + ID_MODEL_FROM_DATABASE=BearPaw 2448 TA Pro + +usb:v055Fp040B* + ID_MODEL_FROM_DATABASE=ScanExpress A3 USB 1200 PRO + +usb:v055Fp0501* + ID_MODEL_FROM_DATABASE=ScanExpress A3 2400 Pro + +usb:v055Fp0873* + ID_MODEL_FROM_DATABASE=ScanExpress 600 USB + +usb:v055Fp1000* + ID_MODEL_FROM_DATABASE=BearPaw 4800 TA Pro + +usb:v055FpA350* + ID_MODEL_FROM_DATABASE=gSmart 350 Camera + +usb:v055FpA800* + ID_MODEL_FROM_DATABASE=MDC 800 Camera + +usb:v055FpB500* + ID_MODEL_FROM_DATABASE=MDC 3000 Camera + +usb:v055FpC005* + ID_MODEL_FROM_DATABASE=PC CAM 300A + +usb:v055FpC200* + ID_MODEL_FROM_DATABASE=gSmart 300 + +usb:v055FpC211* + ID_MODEL_FROM_DATABASE=Kowa Bs888e Microcamera + +usb:v055FpC220* + ID_MODEL_FROM_DATABASE=gSmart mini + +usb:v055FpC230* + ID_MODEL_FROM_DATABASE=Digicam 330K + +usb:v055FpC232* + ID_MODEL_FROM_DATABASE=MDC3500 Camera + +usb:v055FpC360* + ID_MODEL_FROM_DATABASE=DV 4000 Camera + +usb:v055FpC420* + ID_MODEL_FROM_DATABASE=gSmart mini 2 Camera + +usb:v055FpC430* + ID_MODEL_FROM_DATABASE=gSmart LCD 2 Camera + +usb:v055FpC440* + ID_MODEL_FROM_DATABASE=DV 3000 Camera + +usb:v055FpC520* + ID_MODEL_FROM_DATABASE=gSmart mini 3 Camera + +usb:v055FpC530* + ID_MODEL_FROM_DATABASE=gSmart LCD 2 Camera + +usb:v055FpC540* + ID_MODEL_FROM_DATABASE=gSmart D30 Camera + +usb:v055FpC630* + ID_MODEL_FROM_DATABASE=MDC 4000 Camera + +usb:v055FpC631* + ID_MODEL_FROM_DATABASE=MDC 4000 Camera + +usb:v055FpC650* + ID_MODEL_FROM_DATABASE=MDC 5500Z Camera + +usb:v055FpD001* + ID_MODEL_FROM_DATABASE=WCam 300 + +usb:v055FpD003* + ID_MODEL_FROM_DATABASE=WCam 300A + +usb:v055FpD004* + ID_MODEL_FROM_DATABASE=WCam 300AN + +usb:v0560* + ID_VENDOR_FROM_DATABASE=Interface Corp. + +usb:v0561* + ID_VENDOR_FROM_DATABASE=Oasis Design, Inc. + +usb:v0562* + ID_VENDOR_FROM_DATABASE=Telex Communications, Inc. + +usb:v0562p0001* + ID_MODEL_FROM_DATABASE=Enhanced Microphone + +usb:v0562p0002* + ID_MODEL_FROM_DATABASE=Telex Microphone + +usb:v0563* + ID_VENDOR_FROM_DATABASE=Immersion Corp. + +usb:v0564* + ID_VENDOR_FROM_DATABASE=Kodak Digital Product Center, Japan Ltd. (formerly Chinon Industries Inc.) + +usb:v0565* + ID_VENDOR_FROM_DATABASE=Peracom Networks, Inc. + +usb:v0565p0001* + ID_MODEL_FROM_DATABASE=Serial Port [etek] + +usb:v0565p0002* + ID_MODEL_FROM_DATABASE=Enet Ethernet [klsi] + +usb:v0565p0003* + ID_MODEL_FROM_DATABASE=@Home Networks Ethernet [klsi] + +usb:v0565p0005* + ID_MODEL_FROM_DATABASE=Enet2 Ethernet [klsi] + +usb:v0565p0041* + ID_MODEL_FROM_DATABASE=Peracom Remote NDIS Ethernet Adapter + +usb:v0566* + ID_VENDOR_FROM_DATABASE=Monterey International Corp. + +usb:v0566p0110* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v0566p1001* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v0566p1002* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v0566p1003* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v0566p1004* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v0566p1005* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v0566p1006* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v0566p1007* + ID_MODEL_FROM_DATABASE=ViewMate Desktop Mouse CC2201 + +usb:v0566p2800* + ID_MODEL_FROM_DATABASE=MIC K/B + +usb:v0566p2801* + ID_MODEL_FROM_DATABASE=MIC K/B Mouse + +usb:v0566p2802* + ID_MODEL_FROM_DATABASE=Kbd Hub + +usb:v0566p3002* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0566p3004* + ID_MODEL_FROM_DATABASE=Genius KB-29E + +usb:v0566p3027* + ID_MODEL_FROM_DATABASE=Sun-Flex ProTouch + +usb:v0566p3107* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0566p3132* + ID_MODEL_FROM_DATABASE=Optical mouse M-DY4DR / M-DY6DR + +usb:v0566p4006* + ID_MODEL_FROM_DATABASE=FID 638 Mouse (Sun Microsystems) + +usb:v0567* + ID_VENDOR_FROM_DATABASE=Xyratex International, Ltd + +usb:v0568* + ID_VENDOR_FROM_DATABASE=Quartz Ingenierie + +usb:v0569* + ID_VENDOR_FROM_DATABASE=SegaSoft + +usb:v056A* + ID_VENDOR_FROM_DATABASE=Wacom Co., Ltd + +usb:v056Ap0000* + ID_MODEL_FROM_DATABASE=PenPartner + +usb:v056Ap0001* + ID_MODEL_FROM_DATABASE=PenPartner 4x5 + +usb:v056Ap0002* + ID_MODEL_FROM_DATABASE=PenPartner 6x8 + +usb:v056Ap0003* + ID_MODEL_FROM_DATABASE=PTU-600 [Cintiq Partner] + +usb:v056Ap0010* + ID_MODEL_FROM_DATABASE=ET-0405 [Graphire] + +usb:v056Ap0011* + ID_MODEL_FROM_DATABASE=ET-0405A [Graphire2 (4x5)] + +usb:v056Ap0012* + ID_MODEL_FROM_DATABASE=ET-0507A [Graphire2 (5x7)] + +usb:v056Ap0013* + ID_MODEL_FROM_DATABASE=CTE-430 [Graphire3 (4x5)] + +usb:v056Ap0014* + ID_MODEL_FROM_DATABASE=CTE-630 [Graphire3 (6x8)] + +usb:v056Ap0015* + ID_MODEL_FROM_DATABASE=CTE-440 [Graphire4 (4x5)] + +usb:v056Ap0016* + ID_MODEL_FROM_DATABASE=CTE-640 [Graphire4 (6x8)] + +usb:v056Ap0017* + ID_MODEL_FROM_DATABASE=CTE-450 [Bamboo Fun (small)] + +usb:v056Ap0018* + ID_MODEL_FROM_DATABASE=CTE-650 [Bamboo Fun (medium)] + +usb:v056Ap0019* + ID_MODEL_FROM_DATABASE=CTE-631 [Bamboo One] + +usb:v056Ap0020* + ID_MODEL_FROM_DATABASE=GD-0405 [Intuos (4x5)] + +usb:v056Ap0021* + ID_MODEL_FROM_DATABASE=GD-0608 [Intuos (6x8)] + +usb:v056Ap0022* + ID_MODEL_FROM_DATABASE=GD-0912 [Intuos (9x12)] + +usb:v056Ap0023* + ID_MODEL_FROM_DATABASE=GD-1212 [Intuos (12x12)] + +usb:v056Ap0024* + ID_MODEL_FROM_DATABASE=GD-1218 [Intuos (12x18)] + +usb:v056Ap0026* + ID_MODEL_FROM_DATABASE=PTH-450 [Intuos5 touch (S)] + +usb:v056Ap0027* + ID_MODEL_FROM_DATABASE=PTH-650 [Intuos5 touch (M)] + +usb:v056Ap0028* + ID_MODEL_FROM_DATABASE=PTH-850 [Intuos5 touch (L)] + +usb:v056Ap0029* + ID_MODEL_FROM_DATABASE=PTK-450 [Intuos5 (S)] + +usb:v056Ap002A* + ID_MODEL_FROM_DATABASE=PTK-650 [Intuos5 (M)] + +usb:v056Ap0030* + ID_MODEL_FROM_DATABASE=PL400 + +usb:v056Ap0031* + ID_MODEL_FROM_DATABASE=PL500 + +usb:v056Ap0032* + ID_MODEL_FROM_DATABASE=PL600 + +usb:v056Ap0033* + ID_MODEL_FROM_DATABASE=PL600SX + +usb:v056Ap0034* + ID_MODEL_FROM_DATABASE=PL550 + +usb:v056Ap0035* + ID_MODEL_FROM_DATABASE=PL800 + +usb:v056Ap0037* + ID_MODEL_FROM_DATABASE=PL700 + +usb:v056Ap0038* + ID_MODEL_FROM_DATABASE=PL510 + +usb:v056Ap0039* + ID_MODEL_FROM_DATABASE=DTU-710 + +usb:v056Ap003A* + ID_MODEL_FROM_DATABASE=DTI-520 + +usb:v056Ap003B* + ID_MODEL_FROM_DATABASE=Integrated Hub + +usb:v056Ap003F* + ID_MODEL_FROM_DATABASE=DTZ-2100 [Cintiq 21UX] + +usb:v056Ap0041* + ID_MODEL_FROM_DATABASE=XD-0405-U [Intuos2 (4x5)] + +usb:v056Ap0042* + ID_MODEL_FROM_DATABASE=XD-0608-U [Intuos2 (6x8)] + +usb:v056Ap0043* + ID_MODEL_FROM_DATABASE=XD-0912-U [Intuos2 (9x12)] + +usb:v056Ap0044* + ID_MODEL_FROM_DATABASE=XD-1212-U [Intuos2 (12x12)] + +usb:v056Ap0045* + ID_MODEL_FROM_DATABASE=XD-1218-U [Intuos2 (12x18)] + +usb:v056Ap0047* + ID_MODEL_FROM_DATABASE=Intuos2 6x8 + +usb:v056Ap0057* + ID_MODEL_FROM_DATABASE=DTK-2241 + +usb:v056Ap0059* + ID_MODEL_FROM_DATABASE=DTH-2242 tablet + +usb:v056Ap005B* + ID_MODEL_FROM_DATABASE=DTH-2200 [Cintiq 22HD Touch] tablet + +usb:v056Ap005D* + ID_MODEL_FROM_DATABASE=DTH-2242 touchscreen + +usb:v056Ap005E* + ID_MODEL_FROM_DATABASE=DTH-2200 [Cintiq 22HD Touch] touchscreen + +usb:v056Ap0060* + ID_MODEL_FROM_DATABASE=FT-0405 [Volito, PenPartner, PenStation (4x5)] + +usb:v056Ap0061* + ID_MODEL_FROM_DATABASE=FT-0203 [Volito, PenPartner, PenStation (2x3)] + +usb:v056Ap0062* + ID_MODEL_FROM_DATABASE=CTF-420 [Volito2] + +usb:v056Ap0063* + ID_MODEL_FROM_DATABASE=CTF-220 [BizTablet] + +usb:v056Ap0064* + ID_MODEL_FROM_DATABASE=CTF-221 [PenPartner2] + +usb:v056Ap0065* + ID_MODEL_FROM_DATABASE=MTE-450 [Bamboo] + +usb:v056Ap0069* + ID_MODEL_FROM_DATABASE=CTF-430 [Bamboo One] + +usb:v056Ap006A* + ID_MODEL_FROM_DATABASE=CTE-460 [Bamboo One Pen (S)] + +usb:v056Ap006B* + ID_MODEL_FROM_DATABASE=CTE-660 [Bamboo One Pen (M)] + +usb:v056Ap0081* + ID_MODEL_FROM_DATABASE=CTE-630BT [Graphire Wireless (6x8)] + +usb:v056Ap0084* + ID_MODEL_FROM_DATABASE=ACK-40401 [Wireless Accessory Kit] + +usb:v056Ap0090* + ID_MODEL_FROM_DATABASE=TPC90 + +usb:v056Ap0093* + ID_MODEL_FROM_DATABASE=TPC93 + +usb:v056Ap0097* + ID_MODEL_FROM_DATABASE=TPC97 + +usb:v056Ap009A* + ID_MODEL_FROM_DATABASE=TPC9A + +usb:v056Ap00B0* + ID_MODEL_FROM_DATABASE=PTZ-430 [Intuos3 (4x5)] + +usb:v056Ap00B1* + ID_MODEL_FROM_DATABASE=PTZ-630 [Intuos3 (6x8)] + +usb:v056Ap00B2* + ID_MODEL_FROM_DATABASE=PTZ-930 [Intuos3 (9x12)] + +usb:v056Ap00B3* + ID_MODEL_FROM_DATABASE=PTZ-1230 [Intuos3 (12x12)] + +usb:v056Ap00B4* + ID_MODEL_FROM_DATABASE=PTZ-1231W [Intuos3 (12x19)] + +usb:v056Ap00B5* + ID_MODEL_FROM_DATABASE=PTZ-631W [Intuos3 (6x11)] + +usb:v056Ap00B7* + ID_MODEL_FROM_DATABASE=PTZ-431W [Intuos3 (4x6)] + +usb:v056Ap00B8* + ID_MODEL_FROM_DATABASE=PTK-440 [Intuos4 (4x6)] + +usb:v056Ap00B9* + ID_MODEL_FROM_DATABASE=PTK-640 [Intuos4 (6x9)] + +usb:v056Ap00BA* + ID_MODEL_FROM_DATABASE=PTK-840 [Intuos4 (8x13)] + +usb:v056Ap00BB* + ID_MODEL_FROM_DATABASE=PTK-1240 [Intuos4 (12x19)] + +usb:v056Ap00C0* + ID_MODEL_FROM_DATABASE=DTF-521 + +usb:v056Ap00C4* + ID_MODEL_FROM_DATABASE=DTF-720 + +usb:v056Ap00C5* + ID_MODEL_FROM_DATABASE=DTZ-2000W [Cintiq 20WSX] + +usb:v056Ap00C6* + ID_MODEL_FROM_DATABASE=DTZ-1200W [Cintiq 12WX] + +usb:v056Ap00C7* + ID_MODEL_FROM_DATABASE=DTU-1931 + +usb:v056Ap00CC* + ID_MODEL_FROM_DATABASE=DTK-2100 [Cintiq 21UX] + +usb:v056Ap00CE* + ID_MODEL_FROM_DATABASE=DTU-2231 + +usb:v056Ap00D0* + ID_MODEL_FROM_DATABASE=CTT-460 [Bamboo Touch] + +usb:v056Ap00D1* + ID_MODEL_FROM_DATABASE=CTH-460 [Bamboo Pen & Touch] + +usb:v056Ap00D2* + ID_MODEL_FROM_DATABASE=CTH-461 [Bamboo Fun/Craft/Comic Pen & Touch (S)] + +usb:v056Ap00D3* + ID_MODEL_FROM_DATABASE=CTH-661 [Bamboo Fun/Comic Pen & Touch (M)] + +usb:v056Ap00D4* + ID_MODEL_FROM_DATABASE=CTL-460 [Bamboo Pen (S)] + +usb:v056Ap00D5* + ID_MODEL_FROM_DATABASE=CTL-660 [Bamboo Pen (M)] + +usb:v056Ap00D6* + ID_MODEL_FROM_DATABASE=CTH-460 [Bamboo Pen & Touch] + +usb:v056Ap00D7* + ID_MODEL_FROM_DATABASE=CTH-461 [Bamboo Fun/Craft/Comic Pen & Touch (S)] + +usb:v056Ap00D8* + ID_MODEL_FROM_DATABASE=CTH-661 [Bamboo Fun/Comic Pen & Touch (M)] + +usb:v056Ap00D9* + ID_MODEL_FROM_DATABASE=CTT-460 [Bamboo Touch] + +usb:v056Ap00DA* + ID_MODEL_FROM_DATABASE=CTH-461SE [Bamboo Pen & Touch Special Edition (S)] + +usb:v056Ap00DB* + ID_MODEL_FROM_DATABASE=CTH-661SE [Bamboo Pen & Touch Special Edition (M)] + +usb:v056Ap00DC* + ID_MODEL_FROM_DATABASE=CTT-470 [Bamboo Touch] + +usb:v056Ap00DD* + ID_MODEL_FROM_DATABASE=CTL-470 [Bamboo Connect] + +usb:v056Ap00DE* + ID_MODEL_FROM_DATABASE=CTH-470 [Bamboo Fun Pen & Touch] + +usb:v056Ap00DF* + ID_MODEL_FROM_DATABASE=CTH-670 [Bamboo Create/Fun] + +usb:v056Ap00E2* + ID_MODEL_FROM_DATABASE=TPCE2 + +usb:v056Ap00E3* + ID_MODEL_FROM_DATABASE=TPCE3 + +usb:v056Ap00E5* + ID_MODEL_FROM_DATABASE=TPCE5 + +usb:v056Ap00E6* + ID_MODEL_FROM_DATABASE=TPCE6 + +usb:v056Ap00EC* + ID_MODEL_FROM_DATABASE=TPCEC + +usb:v056Ap00ED* + ID_MODEL_FROM_DATABASE=TPCED + +usb:v056Ap00EF* + ID_MODEL_FROM_DATABASE=TPCEF + +usb:v056Ap00F0* + ID_MODEL_FROM_DATABASE=DTU-1631 + +usb:v056Ap00F4* + ID_MODEL_FROM_DATABASE=DTK-2400 [Cintiq 24HD] tablet + +usb:v056Ap00F6* + ID_MODEL_FROM_DATABASE=DTH-2400 [Cintiq 24HD touch] touchscreen + +usb:v056Ap00F8* + ID_MODEL_FROM_DATABASE=DTH-2400 [Cintiq 24HD touch] tablet + +usb:v056Ap00FA* + ID_MODEL_FROM_DATABASE=DTK-2200 [Cintiq 22HD] tablet + +usb:v056Ap00FB* + ID_MODEL_FROM_DATABASE=DTU-1031 + +usb:v056Ap0100* + ID_MODEL_FROM_DATABASE=TPC100 + +usb:v056Ap0101* + ID_MODEL_FROM_DATABASE=TPC101 + +usb:v056Ap010D* + ID_MODEL_FROM_DATABASE=TPC10D + +usb:v056Ap010E* + ID_MODEL_FROM_DATABASE=TPC10E + +usb:v056Ap010F* + ID_MODEL_FROM_DATABASE=TPC10F + +usb:v056Ap0116* + ID_MODEL_FROM_DATABASE=TPC116 + +usb:v056Ap012C* + ID_MODEL_FROM_DATABASE=TPC12C + +usb:v056Ap0221* + ID_MODEL_FROM_DATABASE=MDP-123 [Inkling] + +usb:v056Ap0300* + ID_MODEL_FROM_DATABASE=CTL-471 [Bamboo Splash, One by Wacom (S)] + +usb:v056Ap0301* + ID_MODEL_FROM_DATABASE=CTL-671 [One by Wacom (M)] + +usb:v056Ap0302* + ID_MODEL_FROM_DATABASE=CTH-480 [Intuos Pen & Touch (S)] + +usb:v056Ap0303* + ID_MODEL_FROM_DATABASE=CTH-680 [Intuos Pen & Touch (M)] + +usb:v056Ap0304* + ID_MODEL_FROM_DATABASE=DTK-1300 [Cintiq 13HD] + +usb:v056Ap0307* + ID_MODEL_FROM_DATABASE=DTH-A1300 [Cintiq Companion Hybrid] tablet + +usb:v056Ap0309* + ID_MODEL_FROM_DATABASE=DTH-A1300 [Cintiq Companion Hybrid] touchscreen + +usb:v056Ap030E* + ID_MODEL_FROM_DATABASE=CTL-480 [Intuos Pen (S)] + +usb:v056Ap0314* + ID_MODEL_FROM_DATABASE=PTH-451 [Intuos pro (S)] + +usb:v056Ap0315* + ID_MODEL_FROM_DATABASE=PTH-651 [Intuos pro (M)] + +usb:v056Ap0317* + ID_MODEL_FROM_DATABASE=PTH-851 [Intuos pro (L)] + +usb:v056Ap0318* + ID_MODEL_FROM_DATABASE=CTH-301 [Bamboo] + +usb:v056Ap0319* + ID_MODEL_FROM_DATABASE=CTH-300 [Bamboo Pad wireless] + +usb:v056Ap0323* + ID_MODEL_FROM_DATABASE=CTL-680 [Intuos Pen (M)] + +usb:v056Ap032A* + ID_MODEL_FROM_DATABASE=DTK-2700 [Cintiq 27QHD] + +usb:v056Ap032B* + ID_MODEL_FROM_DATABASE=DTH-2700 [Cintiq 27QHD touch] tablet + +usb:v056Ap032C* + ID_MODEL_FROM_DATABASE=DTH-2700 [Cintiq 27QHD touch] touchscreen + +usb:v056Ap032F* + ID_MODEL_FROM_DATABASE=DTU-1031X + +usb:v056Ap0331* + ID_MODEL_FROM_DATABASE=ACK-411050 [ExpressKey Remote] + +usb:v056Ap0333* + ID_MODEL_FROM_DATABASE=DTH-1300 [Cintiq 13HD Touch] tablet + +usb:v056Ap0335* + ID_MODEL_FROM_DATABASE=DTH-1300 [Cintiq 13HD Touch] touchscreen + +usb:v056Ap0336* + ID_MODEL_FROM_DATABASE=DTU-1141 + +usb:v056Ap033B* + ID_MODEL_FROM_DATABASE=CTL-490 [Intuos Draw (S)] + +usb:v056Ap033C* + ID_MODEL_FROM_DATABASE=CTH-490 [Intuos Art/Photo/Comic (S)] + +usb:v056Ap033D* + ID_MODEL_FROM_DATABASE=CTL-690 [Intuos Draw (M)] + +usb:v056Ap033E* + ID_MODEL_FROM_DATABASE=CTH-690 [Intuos Art (M)] + +usb:v056Ap0343* + ID_MODEL_FROM_DATABASE=DTK-1651 + +usb:v056Ap0347* + ID_MODEL_FROM_DATABASE=Integrated Hub + +usb:v056Ap0348* + ID_MODEL_FROM_DATABASE=Integrated Hub + +usb:v056Ap034A* + ID_MODEL_FROM_DATABASE=DTH-W1320 [MobileStudio Pro 13] touchscreen + +usb:v056Ap034B* + ID_MODEL_FROM_DATABASE=DTH-W1620 [MobileStudio Pro 16] touchscreen + +usb:v056Ap034D* + ID_MODEL_FROM_DATABASE=DTH-W1320 [MobileStudio Pro 13] tablet + +usb:v056Ap034E* + ID_MODEL_FROM_DATABASE=DTH-W1620 [MobileStudio Pro 16] tablet + +usb:v056Ap034F* + ID_MODEL_FROM_DATABASE=DTH-1320 [Cintiq Pro 13] tablet + +usb:v056Ap0350* + ID_MODEL_FROM_DATABASE=DTH-1620 [Cintiq Pro 16] tablet + +usb:v056Ap0351* + ID_MODEL_FROM_DATABASE=DTH-2420 [Cintiq Pro 24 PT] tablet + +usb:v056Ap0352* + ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] tablet + +usb:v056Ap0353* + ID_MODEL_FROM_DATABASE=DTH-1320 [Cintiq Pro 13] touchscreen + +usb:v056Ap0354* + ID_MODEL_FROM_DATABASE=DTH-1620 [Cintiq Pro 16] touchscreen + +usb:v056Ap0355* + ID_MODEL_FROM_DATABASE=DTH-2420 [Cintiq Pro 24 PT] touchscreen + +usb:v056Ap0356* + ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] touchscreen + +usb:v056Ap0357* + ID_MODEL_FROM_DATABASE=PTH-660 [Intuos Pro (M)] + +usb:v056Ap0358* + ID_MODEL_FROM_DATABASE=PTH-860 [Intuos Pro (L)] + +usb:v056Ap0359* + ID_MODEL_FROM_DATABASE=DTU-1141B + +usb:v056Ap035A* + ID_MODEL_FROM_DATABASE=DTH-1152 tablet + +usb:v056Ap0368* + ID_MODEL_FROM_DATABASE=DTH-1152 touchscreen + +usb:v056Ap0374* + ID_MODEL_FROM_DATABASE=CTL-4100 [Intuos (S)] + +usb:v056Ap0375* + ID_MODEL_FROM_DATABASE=CTL-6100 [Intuos (M)] + +usb:v056Ap0376* + ID_MODEL_FROM_DATABASE=CTL-4100WL [Intuos BT (S)] + +usb:v056Ap0378* + ID_MODEL_FROM_DATABASE=CTL-6100WL [Intuos BT (M)] + +usb:v056Ap037A* + ID_MODEL_FROM_DATABASE=CTL-472 [One by Wacom (S)] + +usb:v056Ap037B* + ID_MODEL_FROM_DATABASE=CTL-672 [One by Wacom (M)] + +usb:v056Ap037C* + ID_MODEL_FROM_DATABASE=DTK-2420 [Cintiq Pro 24 P] + +usb:v056Ap037D* + ID_MODEL_FROM_DATABASE=DTH-2452 tablet + +usb:v056Ap037E* + ID_MODEL_FROM_DATABASE=DTH-2452 touchscreen + +usb:v056Ap0382* + ID_MODEL_FROM_DATABASE=DTK-2451 tablet + +usb:v056Ap038A* + ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] internal hub + +usb:v056Ap038D* + ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] internal hub + +usb:v056Ap038E* + ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] external hub + +usb:v056Ap038F* + ID_MODEL_FROM_DATABASE=DTH-3220 [Cintiq Pro 32] internal hub + +usb:v056Ap0390* + ID_MODEL_FROM_DATABASE=DTK-1660 [Cintiq 16] + +usb:v056Ap0400* + ID_MODEL_FROM_DATABASE=PenPartner 4x5 + +usb:v056Ap4001* + ID_MODEL_FROM_DATABASE=TPC4001 + +usb:v056Ap4004* + ID_MODEL_FROM_DATABASE=TPC4004 + +usb:v056Ap4850* + ID_MODEL_FROM_DATABASE=PenPartner 6x8 + +usb:v056Ap5000* + ID_MODEL_FROM_DATABASE=TPC5000 + +usb:v056Ap5002* + ID_MODEL_FROM_DATABASE=TPC5002 + +usb:v056Ap5010* + ID_MODEL_FROM_DATABASE=TPC5010 + +usb:v056B* + ID_VENDOR_FROM_DATABASE=Decicon, Inc. + +usb:v056C* + ID_VENDOR_FROM_DATABASE=eTEK Labs + +usb:v056Cp0006* + ID_MODEL_FROM_DATABASE=KwikLink Host-Host Connector + +usb:v056Cp8007* + ID_MODEL_FROM_DATABASE=Kwik232 Serial Port + +usb:v056Cp8100* + ID_MODEL_FROM_DATABASE=KwikLink Host-Host Connector + +usb:v056Cp8101* + ID_MODEL_FROM_DATABASE=KwikLink USB-USB Bridge + +usb:v056D* + ID_VENDOR_FROM_DATABASE=EIZO Corp. + +usb:v056Dp0000* + ID_MODEL_FROM_DATABASE=Hub + +usb:v056Dp0001* + ID_MODEL_FROM_DATABASE=Monitor + +usb:v056Dp0002* + ID_MODEL_FROM_DATABASE=HID Monitor Controls + +usb:v056Dp0003* + ID_MODEL_FROM_DATABASE=Device Bay Controller + +usb:v056E* + ID_VENDOR_FROM_DATABASE=Elecom Co., Ltd + +usb:v056Ep0002* + ID_MODEL_FROM_DATABASE=29UO Mouse + +usb:v056Ep0057* + ID_MODEL_FROM_DATABASE=Micro Grast Pop M-PGDL + +usb:v056Ep005C* + ID_MODEL_FROM_DATABASE=Micro Grast Pop M-PG2DL + +usb:v056Ep005D* + ID_MODEL_FROM_DATABASE=Micro Grast Fit M-FGDL + +usb:v056Ep005E* + ID_MODEL_FROM_DATABASE=Micro Grast Fit M-FG2DL + +usb:v056Ep0062* + ID_MODEL_FROM_DATABASE=Optical mouse M-D18DR + +usb:v056Ep0063* + ID_MODEL_FROM_DATABASE=Laser mouse M-SODL + +usb:v056Ep0069* + ID_MODEL_FROM_DATABASE=Laser mouse M-GE1UL + +usb:v056Ep0071* + ID_MODEL_FROM_DATABASE=Laser mouse M-GE3DL + +usb:v056Ep0072* + ID_MODEL_FROM_DATABASE=Laser mouse M-LS6UL + +usb:v056Ep0073* + ID_MODEL_FROM_DATABASE=Laser mouse M-LS7UL + +usb:v056Ep0074* + ID_MODEL_FROM_DATABASE=Optical mouse M-FW1UL + +usb:v056Ep0075* + ID_MODEL_FROM_DATABASE=Laser mouse M-FW2DL + +usb:v056Ep0077* + ID_MODEL_FROM_DATABASE=Laser mouse M-LY2UL + +usb:v056Ep0079* + ID_MODEL_FROM_DATABASE=Laser mouse M-D21DL + +usb:v056Ep007B* + ID_MODEL_FROM_DATABASE=Laser mouse M-D20DR + +usb:v056Ep007C* + ID_MODEL_FROM_DATABASE=Laser Bluetooth mouse M-BT5BL + +usb:v056Ep007E* + ID_MODEL_FROM_DATABASE=Option mouse M-M8UR + +usb:v056Ep007F* + ID_MODEL_FROM_DATABASE=Option mouse M-M9UR + +usb:v056Ep0081* + ID_MODEL_FROM_DATABASE=Option mouse M-DY6DR + +usb:v056Ep0082* + ID_MODEL_FROM_DATABASE=Laser mouse M-D22DR + +usb:v056Ep0088* + ID_MODEL_FROM_DATABASE=Micro Grast2 Bit M-BG3DL + +usb:v056Ep0089* + ID_MODEL_FROM_DATABASE=Micro Grast2 Pop M-PG3DL + +usb:v056Ep008C* + ID_MODEL_FROM_DATABASE=M-NE3DL Mouse + +usb:v056Ep008D* + ID_MODEL_FROM_DATABASE=ORIME M-NE4DR + +usb:v056Ep008F* + ID_MODEL_FROM_DATABASE=M-BT8BL Bluetooth Mouse + +usb:v056Ep0092* + ID_MODEL_FROM_DATABASE=Wireless BlueLED Mouse (M-BL2DB) + +usb:v056Ep009C* + ID_MODEL_FROM_DATABASE=IR Mouse M-IR02DR + +usb:v056Ep009D* + ID_MODEL_FROM_DATABASE=IR Mouse M-IR03DR + +usb:v056Ep009F* + ID_MODEL_FROM_DATABASE=BlueLED Mouse M-HS1DB + +usb:v056Ep00A1* + ID_MODEL_FROM_DATABASE=IR Mouse M-IR05DR + +usb:v056Ep00A4* + ID_MODEL_FROM_DATABASE=Blue LED Mouse M-BL06DB + +usb:v056Ep00A5* + ID_MODEL_FROM_DATABASE=M-NV1BR Bluetooth Mouse + +usb:v056Ep00A7* + ID_MODEL_FROM_DATABASE=Blue LED Mouse M-BL08DB + +usb:v056Ep2003* + ID_MODEL_FROM_DATABASE=JC-U3613M + +usb:v056Ep2004* + ID_MODEL_FROM_DATABASE=JC-U3613M + +usb:v056Ep200C* + ID_MODEL_FROM_DATABASE=LD-USB/TX + +usb:v056Ep2012* + ID_MODEL_FROM_DATABASE=JC-U4013S Gamepad + +usb:v056Ep4002* + ID_MODEL_FROM_DATABASE=Laneed 100Mbps Ethernet LD-USB/TX [pegasus] + +usb:v056Ep4005* + ID_MODEL_FROM_DATABASE=LD-USBL/TX + +usb:v056Ep400B* + ID_MODEL_FROM_DATABASE=LD-USB/TX + +usb:v056Ep4010* + ID_MODEL_FROM_DATABASE=LD-USB20 + +usb:v056Ep5003* + ID_MODEL_FROM_DATABASE=UC-SGT + +usb:v056Ep5004* + ID_MODEL_FROM_DATABASE=UC-SGT + +usb:v056Ep6008* + ID_MODEL_FROM_DATABASE=Flash Disk + +usb:v056EpABC1* + ID_MODEL_FROM_DATABASE=LD-USB/TX + +usb:v056F* + ID_VENDOR_FROM_DATABASE=Korea Data Systems Co., Ltd + +usb:v056FpCD00* + ID_MODEL_FROM_DATABASE=CDM-751 CD organizer + +usb:v0570* + ID_VENDOR_FROM_DATABASE=Epson America + +usb:v0571* + ID_VENDOR_FROM_DATABASE=Interex, Inc. + +usb:v0571p0002* + ID_MODEL_FROM_DATABASE=echoFX InterView Lite + +usb:v0572* + ID_VENDOR_FROM_DATABASE=Conexant Systems (Rockwell), Inc. + +usb:v0572p0001* + ID_MODEL_FROM_DATABASE=Ezcam II Webcam + +usb:v0572p0002* + ID_MODEL_FROM_DATABASE=Ezcam II Webcam + +usb:v0572p0040* + ID_MODEL_FROM_DATABASE=Wondereye CP-115 Webcam + +usb:v0572p0041* + ID_MODEL_FROM_DATABASE=Webcam Notebook + +usb:v0572p0042* + ID_MODEL_FROM_DATABASE=Webcam Notebook + +usb:v0572p0320* + ID_MODEL_FROM_DATABASE=DVBSky T330 DVB-T2/C tuner + +usb:v0572p1232* + ID_MODEL_FROM_DATABASE=V.90 modem + +usb:v0572p1234* + ID_MODEL_FROM_DATABASE=Typhoon Redfun Modem V90 56k + +usb:v0572p1252* + ID_MODEL_FROM_DATABASE=HCF V90 Data Fax Voice Modem + +usb:v0572p1253* + ID_MODEL_FROM_DATABASE=Zoom V.92 Faxmodem + +usb:v0572p1300* + ID_MODEL_FROM_DATABASE=SoftK56 Data Fax Voice CARP + +usb:v0572p1301* + ID_MODEL_FROM_DATABASE=Modem Enumerator + +usb:v0572p1328* + ID_MODEL_FROM_DATABASE=TrendNet TFM-561 modem + +usb:v0572p1804* + ID_MODEL_FROM_DATABASE=HP Dock Audio + +usb:v0572p2000* + ID_MODEL_FROM_DATABASE=SoftGate 802.11 Adapter + +usb:v0572p2002* + ID_MODEL_FROM_DATABASE=SoftGate 802.11 Adapter + +usb:v0572p262A* + ID_MODEL_FROM_DATABASE=tm5600 Video & Audio Grabber Capture + +usb:v0572p680C* + ID_MODEL_FROM_DATABASE=DVBSky T680C DVB-T2/C tuner + +usb:v0572p6831* + ID_MODEL_FROM_DATABASE=DVBSky S960 DVB-S2 tuner + +usb:v0572p8390* + ID_MODEL_FROM_DATABASE=WinFast PalmTop/Novo TV Video + +usb:v0572p8392* + ID_MODEL_FROM_DATABASE=WinFast PalmTop/Novo TV Video + +usb:v0572p960C* + ID_MODEL_FROM_DATABASE=DVBSky S960C DVB-S2 tuner + +usb:v0572pC686* + ID_MODEL_FROM_DATABASE=Geniatech T220A DVB-T2 TV Stick + +usb:v0572pC688* + ID_MODEL_FROM_DATABASE=Geniatech T230 DVB-T2 TV Stick + +usb:v0572pCAFC* + ID_MODEL_FROM_DATABASE=CX861xx ROM Boot Loader + +usb:v0572pCAFD* + ID_MODEL_FROM_DATABASE=CX82310 ROM Boot Loader + +usb:v0572pCAFE* + ID_MODEL_FROM_DATABASE=AccessRunner ADSL Modem + +usb:v0572pCB00* + ID_MODEL_FROM_DATABASE=ADSL Modem + +usb:v0572pCB01* + ID_MODEL_FROM_DATABASE=ADSL Modem + +usb:v0572pCB06* + ID_MODEL_FROM_DATABASE=StarModem Network Interface + +usb:v0573* + ID_VENDOR_FROM_DATABASE=Zoran Co. Personal Media Division (Nogatech) + +usb:v0573p0003* + ID_MODEL_FROM_DATABASE=USBGear USBG-V1 + +usb:v0573p0400* + ID_MODEL_FROM_DATABASE=D-Link V100 + +usb:v0573p0600* + ID_MODEL_FROM_DATABASE=Dazzle USBVision (1006) + +usb:v0573p1300* + ID_MODEL_FROM_DATABASE=leadtek USBVision (1006) + +usb:v0573p2000* + ID_MODEL_FROM_DATABASE=X10 va10a Wireless Camera + +usb:v0573p2001* + ID_MODEL_FROM_DATABASE=Dazzle EmMe (2001) + +usb:v0573p2101* + ID_MODEL_FROM_DATABASE=Zoran Co. PMD (Nogatech) AV-grabber Manhattan + +usb:v0573p2D00* + ID_MODEL_FROM_DATABASE=Osprey 50 + +usb:v0573p2D01* + ID_MODEL_FROM_DATABASE=Hauppauge USB-Live Model 600 + +usb:v0573p3000* + ID_MODEL_FROM_DATABASE=Dazzle MicroCam (NTSC) + +usb:v0573p3001* + ID_MODEL_FROM_DATABASE=Dazzle MicroCam (PAL) + +usb:v0573p4000* + ID_MODEL_FROM_DATABASE=Nogatech TV! (NTSC) + +usb:v0573p4001* + ID_MODEL_FROM_DATABASE=Nogatech TV! (PAL) + +usb:v0573p4002* + ID_MODEL_FROM_DATABASE=Nogatech TV! (PAL-I-) + +usb:v0573p4003* + ID_MODEL_FROM_DATABASE=Nogatech TV! (MF-) + +usb:v0573p4008* + ID_MODEL_FROM_DATABASE=Nogatech TV! (NTSC) (T) + +usb:v0573p4009* + ID_MODEL_FROM_DATABASE=Nogatech TV! (PAL) (T) + +usb:v0573p4010* + ID_MODEL_FROM_DATABASE=Nogatech TV! (NTSC) (A) + +usb:v0573p4100* + ID_MODEL_FROM_DATABASE=USB-TV FM (NTSC) + +usb:v0573p4110* + ID_MODEL_FROM_DATABASE=PNY USB-TV (NTSC) FM + +usb:v0573p4400* + ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (NTSC) + +usb:v0573p4401* + ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (PAL) + +usb:v0573p4450* + ID_MODEL_FROM_DATABASE=PixelView PlayTv-USB PRO (PAL) FM + +usb:v0573p4451* + ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (PAL+) + +usb:v0573p4452* + ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (PAL-I+) + +usb:v0573p4500* + ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (NTSC) + +usb:v0573p4501* + ID_MODEL_FROM_DATABASE=Nogatech TV! Pro (PAL) + +usb:v0573p4550* + ID_MODEL_FROM_DATABASE=ZTV ZT-721 2.4GHz A/V Receiver + +usb:v0573p4551* + ID_MODEL_FROM_DATABASE=Dazzle TV! Pro Audio (P+) + +usb:v0573p4D00* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB USA + +usb:v0573p4D01* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB + +usb:v0573p4D02* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB UK + +usb:v0573p4D03* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB France + +usb:v0573p4D04* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV (PAL D/K) + +usb:v0573p4D10* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB with FM USA radio + +usb:v0573p4D11* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB (PAL) with FM radio + +usb:v0573p4D12* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB UK with FM Radio + +usb:v0573p4D14* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV (PAL D/K FM) + +usb:v0573p4D20* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB II (PAL) with FM radio + +usb:v0573p4D21* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB II (PAL) + +usb:v0573p4D22* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB II (PAL) Model 566 + +usb:v0573p4D23* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB France 4D23 + +usb:v0573p4D24* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV Pro (PAL D/K) + +usb:v0573p4D25* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40209 rev B234 + +usb:v0573p4D26* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40209 rev B243 + +usb:v0573p4D27* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40204 Rev B281 + +usb:v0573p4D28* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40204 rev B283 + +usb:v0573p4D29* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40205 rev B298 + +usb:v0573p4D2A* + ID_MODEL_FROM_DATABASE=Hauppague WinTV-USB Model 602 Rev B285 + +usb:v0573p4D2B* + ID_MODEL_FROM_DATABASE=Hauppague WinTV-USB Model 602 Rev B282 + +usb:v0573p4D2C* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV Pro (PAL/SECAM) + +usb:v0573p4D30* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB FM Model 40211 Rev B123 + +usb:v0573p4D31* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB III (PAL) with FM radio Model 568 + +usb:v0573p4D32* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB III (PAL) FM Model 573 + +usb:v0573p4D34* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV Pro (PAL D/K FM) + +usb:v0573p4D35* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB III (PAL) FM Model 597 + +usb:v0573p4D36* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV Pro (PAL B/G FM) + +usb:v0573p4D37* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV-USB Model 40219 rev E189 + +usb:v0573p4D38* + ID_MODEL_FROM_DATABASE=Hauppauge WinTV Pro (NTSC FM) + +usb:v0574* + ID_VENDOR_FROM_DATABASE=City University of Hong Kong + +usb:v0575* + ID_VENDOR_FROM_DATABASE=Philips Creative Display Solutions + +usb:v0576* + ID_VENDOR_FROM_DATABASE=BAFO/Quality Computer Accessories + +usb:v0577* + ID_VENDOR_FROM_DATABASE=ELSA + +usb:v0578* + ID_VENDOR_FROM_DATABASE=Intrinsix Corp. + +usb:v0579* + ID_VENDOR_FROM_DATABASE=GVC Corp. + +usb:v057A* + ID_VENDOR_FROM_DATABASE=Samsung Electronics America + +usb:v057B* + ID_VENDOR_FROM_DATABASE=Y-E Data, Inc. + +usb:v057Bp0000* + ID_MODEL_FROM_DATABASE=FlashBuster-U Floppy + +usb:v057Bp0001* + ID_MODEL_FROM_DATABASE=Tri-Media Reader Floppy + +usb:v057Bp0006* + ID_MODEL_FROM_DATABASE=Tri-Media Reader Card Reader + +usb:v057Bp0010* + ID_MODEL_FROM_DATABASE=Memory Stick Reader Writer + +usb:v057Bp0020* + ID_MODEL_FROM_DATABASE=HEXA Media Drive 6-in-1 Card Reader Writer + +usb:v057Bp0030* + ID_MODEL_FROM_DATABASE=Memory Card Viewer (TV) + +usb:v057C* + ID_VENDOR_FROM_DATABASE=AVM GmbH + +usb:v057Cp0B00* + ID_MODEL_FROM_DATABASE=ISDN-Controller B1 Family + +usb:v057Cp0C00* + ID_MODEL_FROM_DATABASE=ISDN-Controller FRITZ!Card + +usb:v057Cp1000* + ID_MODEL_FROM_DATABASE=ISDN-Controller FRITZ!Card v2.0 + +usb:v057Cp1900* + ID_MODEL_FROM_DATABASE=ISDN-Controller FRITZ!Card v2.1 + +usb:v057Cp2000* + ID_MODEL_FROM_DATABASE=ISDN-Connector FRITZ!X + +usb:v057Cp2200* + ID_MODEL_FROM_DATABASE=BlueFRITZ! + +usb:v057Cp2300* + ID_MODEL_FROM_DATABASE=Teledat X130 DSL + +usb:v057Cp2800* + ID_MODEL_FROM_DATABASE=Teledat 2a/b / X120 / NetXXL ISDN Terminal Adapter + +usb:v057Cp3200* + ID_MODEL_FROM_DATABASE=Teledat X130 DSL + +usb:v057Cp3500* + ID_MODEL_FROM_DATABASE=FRITZ!Card DSL SL + +usb:v057Cp3701* + ID_MODEL_FROM_DATABASE=FRITZ!Box SL + +usb:v057Cp3702* + ID_MODEL_FROM_DATABASE=FRITZ!Box + +usb:v057Cp3800* + ID_MODEL_FROM_DATABASE=BlueFRITZ! Bluetooth Stick + +usb:v057Cp3A00* + ID_MODEL_FROM_DATABASE=FRITZ!Box Fon + +usb:v057Cp3C00* + ID_MODEL_FROM_DATABASE=FRITZ!Box WLAN + +usb:v057Cp3D00* + ID_MODEL_FROM_DATABASE=FRITZ!Box Fon WLAN 7050/7140/7170/IAD3331 + +usb:v057Cp3E01* + ID_MODEL_FROM_DATABASE=FRITZ!Box (Annex A) + +usb:v057Cp4001* + ID_MODEL_FROM_DATABASE=FRITZ!Box Fon (Annex A) + +usb:v057Cp4101* + ID_MODEL_FROM_DATABASE=FRITZ!Box WLAN (Annex A) + +usb:v057Cp4201* + ID_MODEL_FROM_DATABASE=FRITZ!Box Fon WLAN (Annex A) + +usb:v057Cp4601* + ID_MODEL_FROM_DATABASE=Eumex 5520PC (WinXP/2000) + +usb:v057Cp4602* + ID_MODEL_FROM_DATABASE=Eumex 400 (WinXP/2000) + +usb:v057Cp4701* + ID_MODEL_FROM_DATABASE=AVM FRITZ!Box Fon ata + +usb:v057Cp5401* + ID_MODEL_FROM_DATABASE=Eumex 300 IP + +usb:v057Cp5601* + ID_MODEL_FROM_DATABASE=AVM Fritz!WLAN [Texas Instruments TNETW1450] + +usb:v057Cp6201* + ID_MODEL_FROM_DATABASE=AVM Fritz!WLAN v1.1 [Texas Instruments TNETW1450] + +usb:v057Cp62FF* + ID_MODEL_FROM_DATABASE=AVM Fritz!WLAN USB (in CD-ROM-mode) + +usb:v057Cp8401* + ID_MODEL_FROM_DATABASE=Fritz!WLAN N [Atheros AR9001U] + +usb:v057Cp8402* + ID_MODEL_FROM_DATABASE=Fritz!WLAN N 2.4 [Atheros AR9001U] + +usb:v057Cp8403* + ID_MODEL_FROM_DATABASE=Fritz!WLAN N v2 [Atheros AR9271] + +usb:v057Cp84FF* + ID_MODEL_FROM_DATABASE=AVM Fritz!WLAN USB N (in CD-ROM-mode) + +usb:v057Cp8501* + ID_MODEL_FROM_DATABASE=FRITZ WLAN N v2 [RT5572/rt2870.bin] + +usb:v057D* + ID_VENDOR_FROM_DATABASE=Shark Multimedia, Inc. + +usb:v057E* + ID_VENDOR_FROM_DATABASE=Nintendo Co., Ltd + +usb:v057Ep0305* + ID_MODEL_FROM_DATABASE=Broadcom BCM2045A Bluetooth Radio [Nintendo Wii] + +usb:v057Ep0306* + ID_MODEL_FROM_DATABASE=Wii Remote Controller RVL-003 + +usb:v057Ep0337* + ID_MODEL_FROM_DATABASE=Wii U GameCube Controller Adapter + +usb:v057Ep2006* + ID_MODEL_FROM_DATABASE=Joy-Con L + +usb:v057Ep2007* + ID_MODEL_FROM_DATABASE=Joy-Con R + +usb:v057F* + ID_VENDOR_FROM_DATABASE=QuickShot, Ltd + +usb:v057Fp6238* + ID_MODEL_FROM_DATABASE=USB StrikePad + +usb:v0580* + ID_VENDOR_FROM_DATABASE=Denron, Inc. + +usb:v0581* + ID_VENDOR_FROM_DATABASE=Racal Data Group + +usb:v0582* + ID_VENDOR_FROM_DATABASE=Roland Corp. + +usb:v0582p0000* + ID_MODEL_FROM_DATABASE=UA-100(G) + +usb:v0582p0002* + ID_MODEL_FROM_DATABASE=UM-4/MPU-64 MIDI Interface + +usb:v0582p0003* + ID_MODEL_FROM_DATABASE=SoundCanvas SC-8850 + +usb:v0582p0004* + ID_MODEL_FROM_DATABASE=U-8 + +usb:v0582p0005* + ID_MODEL_FROM_DATABASE=UM-2(C/EX) + +usb:v0582p0007* + ID_MODEL_FROM_DATABASE=SoundCanvas SC-8820 + +usb:v0582p0008* + ID_MODEL_FROM_DATABASE=PC-300 + +usb:v0582p0009* + ID_MODEL_FROM_DATABASE=UM-1(E/S/X) + +usb:v0582p000B* + ID_MODEL_FROM_DATABASE=SK-500 + +usb:v0582p000C* + ID_MODEL_FROM_DATABASE=SC-D70 + +usb:v0582p0010* + ID_MODEL_FROM_DATABASE=EDIROL UA-5 + +usb:v0582p0011* + ID_MODEL_FROM_DATABASE=Edirol UA-5 Sound Capture + +usb:v0582p0012* + ID_MODEL_FROM_DATABASE=XV-5050 + +usb:v0582p0013* + ID_MODEL_FROM_DATABASE=XV-5050 + +usb:v0582p0014* + ID_MODEL_FROM_DATABASE=EDIROL UM-880 MIDI I/F (native) + +usb:v0582p0015* + ID_MODEL_FROM_DATABASE=EDIROL UM-880 MIDI I/F (generic) + +usb:v0582p0016* + ID_MODEL_FROM_DATABASE=EDIROL SD-90 + +usb:v0582p0017* + ID_MODEL_FROM_DATABASE=EDIROL SD-90 + +usb:v0582p0018* + ID_MODEL_FROM_DATABASE=UA-1A + +usb:v0582p001B* + ID_MODEL_FROM_DATABASE=MMP-2 + +usb:v0582p001C* + ID_MODEL_FROM_DATABASE=MMP-2 + +usb:v0582p001D* + ID_MODEL_FROM_DATABASE=V-SYNTH + +usb:v0582p001E* + ID_MODEL_FROM_DATABASE=V-SYNTH + +usb:v0582p0023* + ID_MODEL_FROM_DATABASE=EDIROL UM-550 + +usb:v0582p0024* + ID_MODEL_FROM_DATABASE=EDIROL UM-550 + +usb:v0582p0025* + ID_MODEL_FROM_DATABASE=EDIROL UA-20 + +usb:v0582p0026* + ID_MODEL_FROM_DATABASE=EDIROL UA-20 + +usb:v0582p0027* + ID_MODEL_FROM_DATABASE=EDIROL SD-20 + +usb:v0582p0028* + ID_MODEL_FROM_DATABASE=EDIROL SD-20 + +usb:v0582p0029* + ID_MODEL_FROM_DATABASE=EDIROL SD-80 + +usb:v0582p002A* + ID_MODEL_FROM_DATABASE=EDIROL SD-80 + +usb:v0582p002B* + ID_MODEL_FROM_DATABASE=EDIROL UA-700 + +usb:v0582p002C* + ID_MODEL_FROM_DATABASE=EDIROL UA-700 + +usb:v0582p002D* + ID_MODEL_FROM_DATABASE=XV-2020 Synthesizer + +usb:v0582p002E* + ID_MODEL_FROM_DATABASE=XV-2020 Synthesizer + +usb:v0582p002F* + ID_MODEL_FROM_DATABASE=VariOS + +usb:v0582p0030* + ID_MODEL_FROM_DATABASE=VariOS + +usb:v0582p0033* + ID_MODEL_FROM_DATABASE=EDIROL PCR + +usb:v0582p0034* + ID_MODEL_FROM_DATABASE=EDIROL PCR + +usb:v0582p0035* + ID_MODEL_FROM_DATABASE=M-1000 + +usb:v0582p0037* + ID_MODEL_FROM_DATABASE=Digital Piano + +usb:v0582p0038* + ID_MODEL_FROM_DATABASE=Digital Piano + +usb:v0582p003B* + ID_MODEL_FROM_DATABASE=BOSS GS-10 + +usb:v0582p003C* + ID_MODEL_FROM_DATABASE=BOSS GS-10 + +usb:v0582p0040* + ID_MODEL_FROM_DATABASE=GI-20 + +usb:v0582p0041* + ID_MODEL_FROM_DATABASE=GI-20 + +usb:v0582p0042* + ID_MODEL_FROM_DATABASE=RS-70 + +usb:v0582p0043* + ID_MODEL_FROM_DATABASE=RS-70 + +usb:v0582p0044* + ID_MODEL_FROM_DATABASE=EDIROL UA-1000 + +usb:v0582p0047* + ID_MODEL_FROM_DATABASE=EDIROL UR-80 WAVE + +usb:v0582p0048* + ID_MODEL_FROM_DATABASE=EDIROL UR-80 MIDI + +usb:v0582p0049* + ID_MODEL_FROM_DATABASE=EDIROL UR-80 WAVE + +usb:v0582p004A* + ID_MODEL_FROM_DATABASE=EDIROL UR-80 MIDI + +usb:v0582p004B* + ID_MODEL_FROM_DATABASE=EDIROL M-100FX + +usb:v0582p004C* + ID_MODEL_FROM_DATABASE=EDIROL PCR-A WAVE + +usb:v0582p004D* + ID_MODEL_FROM_DATABASE=EDIROL PCR-A MIDI + +usb:v0582p004E* + ID_MODEL_FROM_DATABASE=EDIROL PCR-A WAVE + +usb:v0582p004F* + ID_MODEL_FROM_DATABASE=EDIROL PCR-A MIDI + +usb:v0582p0050* + ID_MODEL_FROM_DATABASE=EDIROL UA-3FX + +usb:v0582p0052* + ID_MODEL_FROM_DATABASE=EDIROL UM-1SX + +usb:v0582p0054* + ID_MODEL_FROM_DATABASE=Digital Piano + +usb:v0582p0060* + ID_MODEL_FROM_DATABASE=EXR Series + +usb:v0582p0064* + ID_MODEL_FROM_DATABASE=EDIROL PCR-1 WAVE + +usb:v0582p0065* + ID_MODEL_FROM_DATABASE=EDIROL PCR-1 MIDI + +usb:v0582p0066* + ID_MODEL_FROM_DATABASE=EDIROL PCR-1 WAVE + +usb:v0582p0067* + ID_MODEL_FROM_DATABASE=EDIROL PCR-1 MIDI + +usb:v0582p006A* + ID_MODEL_FROM_DATABASE=SP-606 + +usb:v0582p006B* + ID_MODEL_FROM_DATABASE=SP-606 + +usb:v0582p006D* + ID_MODEL_FROM_DATABASE=FANTOM-X + +usb:v0582p006E* + ID_MODEL_FROM_DATABASE=FANTOM-X + +usb:v0582p0073* + ID_MODEL_FROM_DATABASE=EDIROL UA-25 + +usb:v0582p0074* + ID_MODEL_FROM_DATABASE=EDIROL UA-25 + +usb:v0582p0075* + ID_MODEL_FROM_DATABASE=BOSS DR-880 + +usb:v0582p0076* + ID_MODEL_FROM_DATABASE=BOSS DR-880 + +usb:v0582p007A* + ID_MODEL_FROM_DATABASE=RD + +usb:v0582p007B* + ID_MODEL_FROM_DATABASE=RD + +usb:v0582p007D* + ID_MODEL_FROM_DATABASE=EDIROL UA-101 + +usb:v0582p0080* + ID_MODEL_FROM_DATABASE=G-70 + +usb:v0582p0081* + ID_MODEL_FROM_DATABASE=G-70 + +usb:v0582p0084* + ID_MODEL_FROM_DATABASE=V-SYNTH XT + +usb:v0582p0089* + ID_MODEL_FROM_DATABASE=BOSS GT-PRO + +usb:v0582p008B* + ID_MODEL_FROM_DATABASE=EDIROL PC-50 + +usb:v0582p008C* + ID_MODEL_FROM_DATABASE=EDIROL PC-50 + +usb:v0582p008D* + ID_MODEL_FROM_DATABASE=EDIROL UA-101 USB1 + +usb:v0582p0092* + ID_MODEL_FROM_DATABASE=EDIROL PC-80 WAVE + +usb:v0582p0093* + ID_MODEL_FROM_DATABASE=EDIROL PC-80 MIDI + +usb:v0582p0096* + ID_MODEL_FROM_DATABASE=EDIROL UA-1EX + +usb:v0582p009A* + ID_MODEL_FROM_DATABASE=EDIROL UM-3EX + +usb:v0582p009D* + ID_MODEL_FROM_DATABASE=EDIROL UM-1 + +usb:v0582p00A0* + ID_MODEL_FROM_DATABASE=MD-P1 + +usb:v0582p00A2* + ID_MODEL_FROM_DATABASE=Digital Piano + +usb:v0582p00A3* + ID_MODEL_FROM_DATABASE=EDIROL UA-4FX + +usb:v0582p00A6* + ID_MODEL_FROM_DATABASE=Juno-G + +usb:v0582p00A9* + ID_MODEL_FROM_DATABASE=MC-808 + +usb:v0582p00AD* + ID_MODEL_FROM_DATABASE=SH-201 + +usb:v0582p00B2* + ID_MODEL_FROM_DATABASE=VG-99 + +usb:v0582p00B3* + ID_MODEL_FROM_DATABASE=VG-99 + +usb:v0582p00B7* + ID_MODEL_FROM_DATABASE=BK-7m/VIMA JM-5/8 + +usb:v0582p00C2* + ID_MODEL_FROM_DATABASE=SonicCell + +usb:v0582p00C4* + ID_MODEL_FROM_DATABASE=EDIROL M-16DX + +usb:v0582p00C5* + ID_MODEL_FROM_DATABASE=SP-555 + +usb:v0582p00C7* + ID_MODEL_FROM_DATABASE=V-Synth GT + +usb:v0582p00D1* + ID_MODEL_FROM_DATABASE=Music Atelier + +usb:v0582p00D3* + ID_MODEL_FROM_DATABASE=M-380/400 + +usb:v0582p00DA* + ID_MODEL_FROM_DATABASE=BOSS GT-10 + +usb:v0582p00DB* + ID_MODEL_FROM_DATABASE=BOSS GT-10 Guitar Effects Processor + +usb:v0582p00DC* + ID_MODEL_FROM_DATABASE=BOSS GT-10B + +usb:v0582p00DE* + ID_MODEL_FROM_DATABASE=Fantom G + +usb:v0582p00E6* + ID_MODEL_FROM_DATABASE=EDIROL UA-25EX (Advanced mode) + +usb:v0582p00E7* + ID_MODEL_FROM_DATABASE=EDIROL UA-25EX + +usb:v0582p00E9* + ID_MODEL_FROM_DATABASE=UA-1G + +usb:v0582p00EB* + ID_MODEL_FROM_DATABASE=VS-100 + +usb:v0582p00F6* + ID_MODEL_FROM_DATABASE=GW-8/AX-Synth + +usb:v0582p00F8* + ID_MODEL_FROM_DATABASE=JUNO Series + +usb:v0582p00FC* + ID_MODEL_FROM_DATABASE=VS-700C + +usb:v0582p00FD* + ID_MODEL_FROM_DATABASE=VS-700 + +usb:v0582p00FE* + ID_MODEL_FROM_DATABASE=VS-700 M1 + +usb:v0582p00FF* + ID_MODEL_FROM_DATABASE=VS-700 M2 + +usb:v0582p0100* + ID_MODEL_FROM_DATABASE=VS-700 + +usb:v0582p0101* + ID_MODEL_FROM_DATABASE=VS-700 M2 + +usb:v0582p0102* + ID_MODEL_FROM_DATABASE=VB-99 + +usb:v0582p0104* + ID_MODEL_FROM_DATABASE=UM-1G + +usb:v0582p0106* + ID_MODEL_FROM_DATABASE=UM-2G + +usb:v0582p0108* + ID_MODEL_FROM_DATABASE=UM-3G + +usb:v0582p0109* + ID_MODEL_FROM_DATABASE=eBand JS-8 + +usb:v0582p010D* + ID_MODEL_FROM_DATABASE=A-500S + +usb:v0582p010F* + ID_MODEL_FROM_DATABASE=A-PRO + +usb:v0582p0110* + ID_MODEL_FROM_DATABASE=A-PRO + +usb:v0582p0111* + ID_MODEL_FROM_DATABASE=GAIA SH-01 + +usb:v0582p0113* + ID_MODEL_FROM_DATABASE=ME-25 + +usb:v0582p0114* + ID_MODEL_FROM_DATABASE=SD-50 + +usb:v0582p0116* + ID_MODEL_FROM_DATABASE=WAVE/MP3 RECORDER R-05 + +usb:v0582p0117* + ID_MODEL_FROM_DATABASE=VS-20 + +usb:v0582p0119* + ID_MODEL_FROM_DATABASE=OCTAPAD SPD-30 + +usb:v0582p011C* + ID_MODEL_FROM_DATABASE=Lucina AX-09 + +usb:v0582p011E* + ID_MODEL_FROM_DATABASE=BR-800 + +usb:v0582p0120* + ID_MODEL_FROM_DATABASE=OCTA-CAPTURE + +usb:v0582p0121* + ID_MODEL_FROM_DATABASE=OCTA-CAPTURE + +usb:v0582p0123* + ID_MODEL_FROM_DATABASE=JUNO-Gi + +usb:v0582p0124* + ID_MODEL_FROM_DATABASE=M-300 + +usb:v0582p0127* + ID_MODEL_FROM_DATABASE=GR-55 + +usb:v0582p012A* + ID_MODEL_FROM_DATABASE=UM-ONE + +usb:v0582p012B* + ID_MODEL_FROM_DATABASE=DUO-CAPTURE + +usb:v0582p012F* + ID_MODEL_FROM_DATABASE=QUAD-CAPTURE + +usb:v0582p0130* + ID_MODEL_FROM_DATABASE=MICRO BR BR-80 + +usb:v0582p0132* + ID_MODEL_FROM_DATABASE=TRI-CAPTURE + +usb:v0582p0134* + ID_MODEL_FROM_DATABASE=V-Mixer + +usb:v0582p0138* + ID_MODEL_FROM_DATABASE=Boss RC-300 (Audio mode) + +usb:v0582p0139* + ID_MODEL_FROM_DATABASE=Boss RC-300 (Storage mode) + +usb:v0582p013A* + ID_MODEL_FROM_DATABASE=JUPITER-80 + +usb:v0582p013E* + ID_MODEL_FROM_DATABASE=R-26 + +usb:v0582p0145* + ID_MODEL_FROM_DATABASE=SPD-SX + +usb:v0582p014B* + ID_MODEL_FROM_DATABASE=eBand JS-10 + +usb:v0582p014D* + ID_MODEL_FROM_DATABASE=GT-100 + +usb:v0582p0150* + ID_MODEL_FROM_DATABASE=TD-15 + +usb:v0582p0151* + ID_MODEL_FROM_DATABASE=TD-11 + +usb:v0582p0154* + ID_MODEL_FROM_DATABASE=JUPITER-50 + +usb:v0582p0156* + ID_MODEL_FROM_DATABASE=A-Series + +usb:v0582p0158* + ID_MODEL_FROM_DATABASE=TD-30 + +usb:v0582p0159* + ID_MODEL_FROM_DATABASE=DUO-CAPTURE EX + +usb:v0582p015B* + ID_MODEL_FROM_DATABASE=INTEGRA-7 + +usb:v0582p015D* + ID_MODEL_FROM_DATABASE=R-88 + +usb:v0582p0505* + ID_MODEL_FROM_DATABASE=EDIROL UA-101 + +usb:v0583* + ID_VENDOR_FROM_DATABASE=Padix Co., Ltd (Rockfire) + +usb:v0583p0001* + ID_MODEL_FROM_DATABASE=4 Axis 12 button +POV + +usb:v0583p0002* + ID_MODEL_FROM_DATABASE=4 Axis 12 button +POV + +usb:v0583p2030* + ID_MODEL_FROM_DATABASE=RM-203 USB Nest [mode 1] + +usb:v0583p2031* + ID_MODEL_FROM_DATABASE=RM-203 USB Nest [mode 2] + +usb:v0583p2032* + ID_MODEL_FROM_DATABASE=RM-203 USB Nest [mode 3] + +usb:v0583p2033* + ID_MODEL_FROM_DATABASE=RM-203 USB Nest [mode 4] + +usb:v0583p2050* + ID_MODEL_FROM_DATABASE=PX-205 PSX Bridge + +usb:v0583p205F* + ID_MODEL_FROM_DATABASE=PSX/USB converter + +usb:v0583p206F* + ID_MODEL_FROM_DATABASE=USB, 2-axis 8-button gamepad + +usb:v0583p3050* + ID_MODEL_FROM_DATABASE=QF-305u Gamepad + +usb:v0583p3379* + ID_MODEL_FROM_DATABASE=Rockfire X-Force + +usb:v0583p337F* + ID_MODEL_FROM_DATABASE=Rockfire USB RacingStar Vibra + +usb:v0583p509F* + ID_MODEL_FROM_DATABASE=USB,4-Axis,12-Button with POV + +usb:v0583p5259* + ID_MODEL_FROM_DATABASE=Rockfire USB SkyShuttle Vibra + +usb:v0583p525F* + ID_MODEL_FROM_DATABASE=USB Vibration Pad + +usb:v0583p5308* + ID_MODEL_FROM_DATABASE=USB Wireless VibrationPad + +usb:v0583p5359* + ID_MODEL_FROM_DATABASE=Rockfire USB SkyShuttle Pro + +usb:v0583p535F* + ID_MODEL_FROM_DATABASE=USB,real VibrationPad + +usb:v0583p5659* + ID_MODEL_FROM_DATABASE=Rockfire USB SkyShuttle Vibra + +usb:v0583p565F* + ID_MODEL_FROM_DATABASE=USB VibrationPad + +usb:v0583p6009* + ID_MODEL_FROM_DATABASE=Revenger + +usb:v0583p600F* + ID_MODEL_FROM_DATABASE=USB,GameBoard II + +usb:v0583p6258* + ID_MODEL_FROM_DATABASE=USB, 4-axis, 6-button joystick w/view finder + +usb:v0583p6889* + ID_MODEL_FROM_DATABASE=Windstorm Pro + +usb:v0583p688F* + ID_MODEL_FROM_DATABASE=QF-688uv Windstorm Pro Joystick + +usb:v0583p7070* + ID_MODEL_FROM_DATABASE=QF-707u Bazooka Joystick + +usb:v0583pA000* + ID_MODEL_FROM_DATABASE=MaxFire G-08XU Gamepad + +usb:v0583pA015* + ID_MODEL_FROM_DATABASE=4-Axis,16-Button with POV + +usb:v0583pA019* + ID_MODEL_FROM_DATABASE=USB, Vibration ,4-axis, 8-button joystick w/view finder + +usb:v0583pA020* + ID_MODEL_FROM_DATABASE=USB,4-Axis,10-Button with POV + +usb:v0583pA021* + ID_MODEL_FROM_DATABASE=USB,4-Axis,12-Button with POV + +usb:v0583pA022* + ID_MODEL_FROM_DATABASE=USB,4-Axis,14-Button with POV + +usb:v0583pA023* + ID_MODEL_FROM_DATABASE=USB,4-Axis,16-Button with POV + +usb:v0583pA024* + ID_MODEL_FROM_DATABASE=4axis,12button vibrition audio gamepad + +usb:v0583pA025* + ID_MODEL_FROM_DATABASE=4axis,12button vibrition audio gamepad + +usb:v0583pA130* + ID_MODEL_FROM_DATABASE=USB Wireless 2.4GHz Gamepad + +usb:v0583pA131* + ID_MODEL_FROM_DATABASE=USB Wireless 2.4GHz Joystick + +usb:v0583pA132* + ID_MODEL_FROM_DATABASE=USB Wireless 2.4GHz Wheelpad + +usb:v0583pA133* + ID_MODEL_FROM_DATABASE=USB Wireless 2.4GHz Wheel&Gamepad + +usb:v0583pA202* + ID_MODEL_FROM_DATABASE=ForceFeedbackWheel + +usb:v0583pA209* + ID_MODEL_FROM_DATABASE=MetalStrike FF + +usb:v0583pB000* + ID_MODEL_FROM_DATABASE=USB,4-Axis,12-Button with POV + +usb:v0583pB001* + ID_MODEL_FROM_DATABASE=USB,4-Axis,12-Button with POV + +usb:v0583pB002* + ID_MODEL_FROM_DATABASE=Vibration,12-Button USB Wheel + +usb:v0583pB005* + ID_MODEL_FROM_DATABASE=USB,12-Button Wheel + +usb:v0583pB008* + ID_MODEL_FROM_DATABASE=USB Wireless 2.4GHz Wheel + +usb:v0583pB009* + ID_MODEL_FROM_DATABASE=USB,12-Button Wheel + +usb:v0583pB00A* + ID_MODEL_FROM_DATABASE=PSX/USB converter + +usb:v0583pB00B* + ID_MODEL_FROM_DATABASE=PSX/USB converter + +usb:v0583pB00C* + ID_MODEL_FROM_DATABASE=PSX/USB converter + +usb:v0583pB00D* + ID_MODEL_FROM_DATABASE=PSX/USB converter + +usb:v0583pB00E* + ID_MODEL_FROM_DATABASE=4-Axis,12-Button with POV + +usb:v0583pB00F* + ID_MODEL_FROM_DATABASE=USB,5-Axis,10-Button with POV + +usb:v0583pB010* + ID_MODEL_FROM_DATABASE=MetalStrike Pro + +usb:v0583pB012* + ID_MODEL_FROM_DATABASE=Wireless MetalStrike + +usb:v0583pB013* + ID_MODEL_FROM_DATABASE=USB,Wiress 2.4GHZ Joystick + +usb:v0583pB016* + ID_MODEL_FROM_DATABASE=USB,5-Axis,10-Button with POV + +usb:v0583pB018* + ID_MODEL_FROM_DATABASE=TW6 Wheel + +usb:v0583pFF60* + ID_MODEL_FROM_DATABASE=USB Wireless VibrationPad + +usb:v0584* + ID_VENDOR_FROM_DATABASE=RATOC System, Inc. + +usb:v0584p0008* + ID_MODEL_FROM_DATABASE=Fujifilm MemoryCard ReaderWriter + +usb:v0584p0220* + ID_MODEL_FROM_DATABASE=U2SCX SCSI Converter + +usb:v0584p0304* + ID_MODEL_FROM_DATABASE=U2SCX-LVD (SCSI Converter) + +usb:v0584pB000* + ID_MODEL_FROM_DATABASE=REX-USB60 + +usb:v0584pB020* + ID_MODEL_FROM_DATABASE=REX-USB60F + +usb:v0585* + ID_VENDOR_FROM_DATABASE=FlashPoint Technology, Inc. + +usb:v0585p0001* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p0002* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p0003* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p0004* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p0005* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p0006* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p0007* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p0008* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p0009* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p000A* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p000B* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p000C* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p000D* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p000E* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0585p000F* + ID_MODEL_FROM_DATABASE=Digital Camera + +usb:v0586* + ID_VENDOR_FROM_DATABASE=ZyXEL Communications Corp. + +usb:v0586p0025* + ID_MODEL_FROM_DATABASE=802.11b/g/n USB Wireless Network Adapter + +usb:v0586p0100* + ID_MODEL_FROM_DATABASE=omni.net + +usb:v0586p0102* + ID_MODEL_FROM_DATABASE=omni.net II ISDN TA [HFC-S] + +usb:v0586p0110* + ID_MODEL_FROM_DATABASE=omni.net Plus + +usb:v0586p1000* + ID_MODEL_FROM_DATABASE=omni.net LCD Plus - ISDN TA + +usb:v0586p1500* + ID_MODEL_FROM_DATABASE=Omni 56K Plus + +usb:v0586p2011* + ID_MODEL_FROM_DATABASE=Scorpion-980N keyboard + +usb:v0586p3304* + ID_MODEL_FROM_DATABASE=LAN Modem + +usb:v0586p3309* + ID_MODEL_FROM_DATABASE=ADSL Modem Prestige 600 series + +usb:v0586p330A* + ID_MODEL_FROM_DATABASE=ADSL Modem Interface + +usb:v0586p330E* + ID_MODEL_FROM_DATABASE=USB Broadband ADSL Modem Rev 1.10 + +usb:v0586p3400* + ID_MODEL_FROM_DATABASE=ZyAIR B-220 IEEE 802.11b Adapter + +usb:v0586p3401* + ID_MODEL_FROM_DATABASE=ZyAIR G-220 802.11bg + +usb:v0586p3402* + ID_MODEL_FROM_DATABASE=ZyAIR G-220F 802.11bg + +usb:v0586p3403* + ID_MODEL_FROM_DATABASE=AG-200 802.11abg Wireless Adapter [Atheros AR5523] + +usb:v0586p3407* + ID_MODEL_FROM_DATABASE=G-200 v2 802.11bg + +usb:v0586p3408* + ID_MODEL_FROM_DATABASE=G-260 802.11bg + +usb:v0586p3409* + ID_MODEL_FROM_DATABASE=AG-225H 802.11bg + +usb:v0586p340A* + ID_MODEL_FROM_DATABASE=M-202 802.11bg + +usb:v0586p340C* + ID_MODEL_FROM_DATABASE=G-270S 802.11bg Wireless Adapter [Atheros AR5523] + +usb:v0586p340F* + ID_MODEL_FROM_DATABASE=G-220 v2 802.11bg + +usb:v0586p3410* + ID_MODEL_FROM_DATABASE=ZyAIR G-202 802.11bg + +usb:v0586p3412* + ID_MODEL_FROM_DATABASE=802.11bg + +usb:v0586p3413* + ID_MODEL_FROM_DATABASE=ZyAIR AG-225H v2 802.11bg + +usb:v0586p3415* + ID_MODEL_FROM_DATABASE=G-210H 802.11g Wireless Adapter + +usb:v0586p3416* + ID_MODEL_FROM_DATABASE=NWD-210N 802.11b/g/n-draft wireless adapter + +usb:v0586p3417* + ID_MODEL_FROM_DATABASE=NWD271N 802.11n Wireless Adapter [Atheros AR9001U-(2)NG] + +usb:v0586p3418* + ID_MODEL_FROM_DATABASE=NWD211AN 802.11abgn Wireless Adapter [Ralink RT2870] + +usb:v0586p3419* + ID_MODEL_FROM_DATABASE=G-220 v3 802.11bg Wireless Adapter [ZyDAS ZD1211B] + +usb:v0586p341A* + ID_MODEL_FROM_DATABASE=NWD-270N Wireless N-lite USB Adapter + +usb:v0586p341E* + ID_MODEL_FROM_DATABASE=NWD2105 802.11bgn Wireless Adapter [Ralink RT3070] + +usb:v0586p341F* + ID_MODEL_FROM_DATABASE=NWD2205 802.11n Wireless N Adapter [Realtek RTL8192CU] + +usb:v0586p3425* + ID_MODEL_FROM_DATABASE=NWD6505 802.11a/b/g/n/ac Wireless Adapter [MediaTek MT7610U] + +usb:v0586p343E* + ID_MODEL_FROM_DATABASE=N220 802.11bgn Wireless Adapter + +usb:v0587* + ID_VENDOR_FROM_DATABASE=America Kotobuki Electronics Industries, Inc. + +usb:v0588* + ID_VENDOR_FROM_DATABASE=Sapien Design + +usb:v0589* + ID_VENDOR_FROM_DATABASE=Victron + +usb:v058A* + ID_VENDOR_FROM_DATABASE=Nohau Corp. + +usb:v058B* + ID_VENDOR_FROM_DATABASE=Infineon Technologies + +usb:v058Bp0015* + ID_MODEL_FROM_DATABASE=Flash Loader utility + +usb:v058Bp001C* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v058Bp0041* + ID_MODEL_FROM_DATABASE=Flash Loader utility + +usb:v058C* + ID_VENDOR_FROM_DATABASE=In Focus Systems + +usb:v058Cp0007* + ID_MODEL_FROM_DATABASE=Flash + +usb:v058Cp0008* + ID_MODEL_FROM_DATABASE=LP130 + +usb:v058Cp000A* + ID_MODEL_FROM_DATABASE=LP530 + +usb:v058Cp0010* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp0011* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp0012* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp0013* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp0014* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp0015* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp0016* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp0017* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp0018* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp0019* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp001A* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp001B* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp001C* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp001D* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp001E* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058Cp001F* + ID_MODEL_FROM_DATABASE=Projector + +usb:v058CpFFE5* + ID_MODEL_FROM_DATABASE=IN34 Projector + +usb:v058CpFFEB* + ID_MODEL_FROM_DATABASE=Projector IN76 + +usb:v058D* + ID_VENDOR_FROM_DATABASE=Micrel Semiconductor + +usb:v058E* + ID_VENDOR_FROM_DATABASE=Tripath Technology, Inc. + +usb:v058F* + ID_VENDOR_FROM_DATABASE=Alcor Micro Corp. + +usb:v058Fp1234* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v058Fp2412* + ID_MODEL_FROM_DATABASE=SCard R/W CSR-145 + +usb:v058Fp2802* + ID_MODEL_FROM_DATABASE=Monterey Keyboard + +usb:v058Fp5492* + ID_MODEL_FROM_DATABASE=Hub + +usb:v058Fp6232* + ID_MODEL_FROM_DATABASE=Hi-Speed 16-in-1 Flash Card Reader/Writer + +usb:v058Fp6254* + ID_MODEL_FROM_DATABASE=USB Hub + +usb:v058Fp6331* + ID_MODEL_FROM_DATABASE=SD/MMC/MS Card Reader + +usb:v058Fp6332* + ID_MODEL_FROM_DATABASE=Multi-Function Card Reader + +usb:v058Fp6335* + ID_MODEL_FROM_DATABASE=SD/MMC Card Reader + +usb:v058Fp6360* + ID_MODEL_FROM_DATABASE=Multimedia Card Reader + +usb:v058Fp6361* + ID_MODEL_FROM_DATABASE=Multimedia Card Reader + +usb:v058Fp6362* + ID_MODEL_FROM_DATABASE=Flash Card Reader/Writer + +usb:v058Fp6364* + ID_MODEL_FROM_DATABASE=AU6477 Card Reader Controller + +usb:v058Fp6366* + ID_MODEL_FROM_DATABASE=Multi Flash Reader + +usb:v058Fp6377* + ID_MODEL_FROM_DATABASE=AU6375 4-LUN card reader + +usb:v058Fp6386* + ID_MODEL_FROM_DATABASE=Memory Card + +usb:v058Fp6387* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v058Fp6390* + ID_MODEL_FROM_DATABASE=USB 2.0-IDE bridge + +usb:v058Fp6391* + ID_MODEL_FROM_DATABASE=IDE Bridge + +usb:v058Fp9213* + ID_MODEL_FROM_DATABASE=MacAlly Kbd Hub + +usb:v058Fp9215* + ID_MODEL_FROM_DATABASE=AU9814 Hub + +usb:v058Fp9254* + ID_MODEL_FROM_DATABASE=Hub + +usb:v058Fp9310* + ID_MODEL_FROM_DATABASE=Mass Storage (UID4/5A & UID7A) + +usb:v058Fp9320* + ID_MODEL_FROM_DATABASE=Micro Storage Driver for Win98 + +usb:v058Fp9321* + ID_MODEL_FROM_DATABASE=Micro Storage Driver for Win98 + +usb:v058Fp9330* + ID_MODEL_FROM_DATABASE=SD Reader + +usb:v058Fp9331* + ID_MODEL_FROM_DATABASE=Micro Storage Driver for Win98 + +usb:v058Fp9340* + ID_MODEL_FROM_DATABASE=Delkin eFilm Reader-32 + +usb:v058Fp9350* + ID_MODEL_FROM_DATABASE=Delkin eFilm Reader-32 + +usb:v058Fp9360* + ID_MODEL_FROM_DATABASE=8-in-1 Media Card Reader + +usb:v058Fp9361* + ID_MODEL_FROM_DATABASE=Multimedia Card Reader + +usb:v058Fp9368* + ID_MODEL_FROM_DATABASE=Multimedia Card Reader + +usb:v058Fp9380* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v058Fp9381* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v058Fp9382* + ID_MODEL_FROM_DATABASE=Acer/Sweex Flash drive + +usb:v058Fp9384* + ID_MODEL_FROM_DATABASE=qdi U2Disk T209M + +usb:v058Fp9410* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v058Fp9472* + ID_MODEL_FROM_DATABASE=Keyboard Hub + +usb:v058Fp9510* + ID_MODEL_FROM_DATABASE=ChunghwaTL USB02 Smartcard Reader + +usb:v058Fp9520* + ID_MODEL_FROM_DATABASE=Watchdata W 1981 + +usb:v058Fp9540* + ID_MODEL_FROM_DATABASE=AU9540 Smartcard Reader + +usb:v058Fp9720* + ID_MODEL_FROM_DATABASE=USB-Serial Adapter + +usb:v058FpA014* + ID_MODEL_FROM_DATABASE=Asus Integrated Webcam + +usb:v058FpB002* + ID_MODEL_FROM_DATABASE=Acer Integrated Webcam + +usb:v0590* + ID_VENDOR_FROM_DATABASE=Omron Corp. + +usb:v0590p0004* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v0590p000B* + ID_MODEL_FROM_DATABASE=MR56SVS + +usb:v0590p0028* + ID_MODEL_FROM_DATABASE=HJ-720IT / HEM-7080IT-E / HEM-790IT + +usb:v0591* + ID_VENDOR_FROM_DATABASE=Questra Consulting + +usb:v0592* + ID_VENDOR_FROM_DATABASE=Powerware Corp. + +usb:v0592p0002* + ID_MODEL_FROM_DATABASE=UPS (X-Slot) + +usb:v0593* + ID_VENDOR_FROM_DATABASE=Incite + +usb:v0594* + ID_VENDOR_FROM_DATABASE=Princeton Graphic Systems + +usb:v0595* + ID_VENDOR_FROM_DATABASE=Zoran Microelectronics, Ltd + +usb:v0595p1001* + ID_MODEL_FROM_DATABASE=Digitrex DSC-1300/DSC-2100 (mass storage mode) + +usb:v0595p2002* + ID_MODEL_FROM_DATABASE=DIGITAL STILL CAMERA 6M 4X + +usb:v0595p4343* + ID_MODEL_FROM_DATABASE=Digital Camera EX-20 DSC + +usb:v0596* + ID_VENDOR_FROM_DATABASE=MicroTouch Systems, Inc. + +usb:v0596p0001* + ID_MODEL_FROM_DATABASE=Touchscreen + +usb:v0596p0002* + ID_MODEL_FROM_DATABASE=Touch Screen Controller + +usb:v0596p0500* + ID_MODEL_FROM_DATABASE=PCT Multitouch HID Controller + +usb:v0596p0543* + ID_MODEL_FROM_DATABASE=DELL XPS touchscreen + +usb:v0597* + ID_VENDOR_FROM_DATABASE=Trisignal Communications + +usb:v0598* + ID_VENDOR_FROM_DATABASE=Niigata Canotec Co., Inc. + +usb:v0599* + ID_VENDOR_FROM_DATABASE=Brilliance Semiconductor, Inc. + +usb:v059A* + ID_VENDOR_FROM_DATABASE=Spectrum Signal Processing, Inc. + +usb:v059B* + ID_VENDOR_FROM_DATABASE=Iomega Corp. + +usb:v059Bp0001* + ID_MODEL_FROM_DATABASE=Zip 100 (Type 1) + +usb:v059Bp000B* + ID_MODEL_FROM_DATABASE=Zip 100 (Type 2) + +usb:v059Bp0021* + ID_MODEL_FROM_DATABASE=Win98 Disk Controller + +usb:v059Bp0030* + ID_MODEL_FROM_DATABASE=Zip 250 (Ver 1) + +usb:v059Bp0031* + ID_MODEL_FROM_DATABASE=Zip 100 (Type 3) + +usb:v059Bp0032* + ID_MODEL_FROM_DATABASE=Zip 250 (Ver 2) + +usb:v059Bp0034* + ID_MODEL_FROM_DATABASE=Zip 100 Driver + +usb:v059Bp0037* + ID_MODEL_FROM_DATABASE=Zip 750 MB + +usb:v059Bp0040* + ID_MODEL_FROM_DATABASE=SCSI Bridge + +usb:v059Bp0042* + ID_MODEL_FROM_DATABASE=Rev 70 GB + +usb:v059Bp0050* + ID_MODEL_FROM_DATABASE=Zip CD 650 Writer + +usb:v059Bp0053* + ID_MODEL_FROM_DATABASE=CDRW55292EXT CD-RW External Drive + +usb:v059Bp0056* + ID_MODEL_FROM_DATABASE=External CD-RW Drive Enclosure + +usb:v059Bp0057* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v059Bp005D* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v059Bp005F* + ID_MODEL_FROM_DATABASE=CDRW64892EXT3-C CD-RW 52x24x52x External Drive + +usb:v059Bp0060* + ID_MODEL_FROM_DATABASE=PCMCIA PocketZip Dock + +usb:v059Bp0061* + ID_MODEL_FROM_DATABASE=Varo PocketZip 40 MP3 Player + +usb:v059Bp006D* + ID_MODEL_FROM_DATABASE=HipZip MP3 Player + +usb:v059Bp0070* + ID_MODEL_FROM_DATABASE=eGo Portable Hard Drive + +usb:v059Bp007C* + ID_MODEL_FROM_DATABASE=Ultra Max USB/1394 + +usb:v059Bp007D* + ID_MODEL_FROM_DATABASE=HTC42606 0G9AT00 [Iomega HDD] + +usb:v059Bp007E* + ID_MODEL_FROM_DATABASE=Mini 256MB/512MB Flash Drive [IOM2D5] + +usb:v059Bp00DB* + ID_MODEL_FROM_DATABASE=FotoShow Zip 250 Driver + +usb:v059Bp0150* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v059Bp015D* + ID_MODEL_FROM_DATABASE=Super DVD Writer + +usb:v059Bp0173* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller + +usb:v059Bp0174* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller + +usb:v059Bp0176* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller + +usb:v059Bp0177* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller + +usb:v059Bp0178* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller + +usb:v059Bp0179* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller + +usb:v059Bp017A* + ID_MODEL_FROM_DATABASE=HDD + +usb:v059Bp017B* + ID_MODEL_FROM_DATABASE=HDD/1394A + +usb:v059Bp017C* + ID_MODEL_FROM_DATABASE=HDD/1394B + +usb:v059Bp0251* + ID_MODEL_FROM_DATABASE=Optical + +usb:v059Bp0252* + ID_MODEL_FROM_DATABASE=Optical + +usb:v059Bp0275* + ID_MODEL_FROM_DATABASE=ST332082 0A + +usb:v059Bp0278* + ID_MODEL_FROM_DATABASE=LDHD-UPS [Professional Desktop Hard Drive eSATA / USB2.0] + +usb:v059Bp027A* + ID_MODEL_FROM_DATABASE=LPHD250-U [Portable Hard Drive Silver Series 250 Go] + +usb:v059Bp0470* + ID_MODEL_FROM_DATABASE=Prestige Portable Hard Drive + +usb:v059Bp047A* + ID_MODEL_FROM_DATABASE=Select Portable Hard Drive + +usb:v059Bp0571* + ID_MODEL_FROM_DATABASE=Prestige Portable Hard Drive + +usb:v059Bp0579* + ID_MODEL_FROM_DATABASE=eGo Portable Hard Drive + +usb:v059Bp1052* + ID_MODEL_FROM_DATABASE=DVD+RW External Drive + +usb:v059C* + ID_VENDOR_FROM_DATABASE=A-Trend Technology Co., Ltd + +usb:v059D* + ID_VENDOR_FROM_DATABASE=Advanced Input Devices + +usb:v059E* + ID_VENDOR_FROM_DATABASE=Intelligent Instrumentation + +usb:v059F* + ID_VENDOR_FROM_DATABASE=LaCie, Ltd + +usb:v059Fp0201* + ID_MODEL_FROM_DATABASE=StudioDrive USB2 + +usb:v059Fp0202* + ID_MODEL_FROM_DATABASE=StudioDrive USB2 + +usb:v059Fp0203* + ID_MODEL_FROM_DATABASE=StudioDrive USB2 + +usb:v059Fp0211* + ID_MODEL_FROM_DATABASE=PocketDrive + +usb:v059Fp0212* + ID_MODEL_FROM_DATABASE=PocketDrive + +usb:v059Fp0213* + ID_MODEL_FROM_DATABASE=PocketDrive USB2 + +usb:v059Fp0323* + ID_MODEL_FROM_DATABASE=LaCie d2 Drive USB2 + +usb:v059Fp0421* + ID_MODEL_FROM_DATABASE=Big Disk G465 + +usb:v059Fp0525* + ID_MODEL_FROM_DATABASE=BigDisk Extreme 500 + +usb:v059Fp0641* + ID_MODEL_FROM_DATABASE=Mobile Hard Drive + +usb:v059Fp0829* + ID_MODEL_FROM_DATABASE=BigDisk Extreme+ + +usb:v059Fp1004* + ID_MODEL_FROM_DATABASE=Little Disk 20 GB + +usb:v059Fp100C* + ID_MODEL_FROM_DATABASE=Rugged Triple Interface Mobile Hard Drive + +usb:v059Fp1010* + ID_MODEL_FROM_DATABASE=Desktop Hard Drive + +usb:v059Fp1016* + ID_MODEL_FROM_DATABASE=Desktop Hard Drive + +usb:v059Fp1018* + ID_MODEL_FROM_DATABASE=Desktop Hard Drive + +usb:v059Fp1019* + ID_MODEL_FROM_DATABASE=Desktop Hard Drive + +usb:v059Fp1021* + ID_MODEL_FROM_DATABASE=Little Disk + +usb:v059Fp1027* + ID_MODEL_FROM_DATABASE=iamaKey V2 + +usb:v059Fp102A* + ID_MODEL_FROM_DATABASE=Rikiki Hard Drive + +usb:v059Fp1049* + ID_MODEL_FROM_DATABASE=rikiki Harddrive + +usb:v059Fp1052* + ID_MODEL_FROM_DATABASE=P'9220 Mobile Drive + +usb:v059Fp1061* + ID_MODEL_FROM_DATABASE=Rugged USB3-FW + +usb:v059Fp1064* + ID_MODEL_FROM_DATABASE=Rugged 16 and 32 GB + +usb:v059Fp106B* + ID_MODEL_FROM_DATABASE=Rugged Mini HDD + +usb:v059Fp106D* + ID_MODEL_FROM_DATABASE=Porsche Design Mobile Drive + +usb:v059Fp106E* + ID_MODEL_FROM_DATABASE=Porsche Design Desktop Drive + +usb:v059FpA601* + ID_MODEL_FROM_DATABASE=HardDrive + +usb:v059FpA602* + ID_MODEL_FROM_DATABASE=CD R/W + +usb:v05A0* + ID_VENDOR_FROM_DATABASE=Vetronix Corp. + +usb:v05A1* + ID_VENDOR_FROM_DATABASE=USC Corp. + +usb:v05A2* + ID_VENDOR_FROM_DATABASE=Fuji Film Microdevices Co., Ltd + +usb:v05A3* + ID_VENDOR_FROM_DATABASE=ARC International + +usb:v05A3p8388* + ID_MODEL_FROM_DATABASE=Marvell 88W8388 802.11a/b/g WLAN + +usb:v05A3p9230* + ID_MODEL_FROM_DATABASE=Camera + +usb:v05A3p9320* + ID_MODEL_FROM_DATABASE=Camera + +usb:v05A3p9331* + ID_MODEL_FROM_DATABASE=Camera + +usb:v05A3p9422* + ID_MODEL_FROM_DATABASE=Camera + +usb:v05A3p9520* + ID_MODEL_FROM_DATABASE=Camera + +usb:v05A4* + ID_VENDOR_FROM_DATABASE=Ortek Technology, Inc. + +usb:v05A4p1000* + ID_MODEL_FROM_DATABASE=WKB-1000S Wireless Ergo Keyboard with Touchpad + +usb:v05A4p2000* + ID_MODEL_FROM_DATABASE=WKB-2000 Wireless Keyboard with Touchpad + +usb:v05A4p9720* + ID_MODEL_FROM_DATABASE=Keyboard Mouse + +usb:v05A4p9722* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v05A4p9731* + ID_MODEL_FROM_DATABASE=MCK-600W/MCK-800USB Keyboard + +usb:v05A4p9783* + ID_MODEL_FROM_DATABASE=Wireless Keypad + +usb:v05A4p9837* + ID_MODEL_FROM_DATABASE=Targus Number Keypad + +usb:v05A4p9862* + ID_MODEL_FROM_DATABASE=Targus Number Keypad (Composite Device) + +usb:v05A4p9881* + ID_MODEL_FROM_DATABASE=IR receiver [VRC-1100 Vista MCE Remote Control] + +usb:v05A5* + ID_VENDOR_FROM_DATABASE=Sampo Technology Corp. + +usb:v05A6* + ID_VENDOR_FROM_DATABASE=Cisco Systems, Inc. + +usb:v05A6p0001* + ID_MODEL_FROM_DATABASE=CVA124 Cable Voice Adapter (WDM) + +usb:v05A6p0002* + ID_MODEL_FROM_DATABASE=CVA122 Cable Voice Adapter (WDM) + +usb:v05A6p0003* + ID_MODEL_FROM_DATABASE=CVA124E Cable Voice Adapter (WDM) + +usb:v05A6p0004* + ID_MODEL_FROM_DATABASE=CVA122E Cable Voice Adapter (WDM) + +usb:v05A6p0A00* + ID_MODEL_FROM_DATABASE=Integrated Management Controller Hub + +usb:v05A6p0A01* + ID_MODEL_FROM_DATABASE=Virtual Keyboard/Mouse + +usb:v05A6p0A02* + ID_MODEL_FROM_DATABASE=Virtual Mass Storage + +usb:v05A6p0A03* + ID_MODEL_FROM_DATABASE=Virtual Ethernet/RNDIS + +usb:v05A7* + ID_VENDOR_FROM_DATABASE=Bose Corp. + +usb:v05A7p4000* + ID_MODEL_FROM_DATABASE=Bluetooth Headset + +usb:v05A7p4001* + ID_MODEL_FROM_DATABASE=Bluetooth Headset in DFU mode + +usb:v05A7p4002* + ID_MODEL_FROM_DATABASE=Bluetooth Headset Series 2 + +usb:v05A7p4003* + ID_MODEL_FROM_DATABASE=Bluetooth Headset Series 2 in DFU mode + +usb:v05A7pBC50* + ID_MODEL_FROM_DATABASE=SoundLink Wireless Mobile speaker + +usb:v05A7pBC51* + ID_MODEL_FROM_DATABASE=SoundLink Wireless Mobile speaker in DFU mode + +usb:v05A8* + ID_VENDOR_FROM_DATABASE=Spacetec IMC Corp. + +usb:v05A9* + ID_VENDOR_FROM_DATABASE=OmniVision Technologies, Inc. + +usb:v05A9p0511* + ID_MODEL_FROM_DATABASE=OV511 Webcam + +usb:v05A9p0518* + ID_MODEL_FROM_DATABASE=OV518 Webcam + +usb:v05A9p0519* + ID_MODEL_FROM_DATABASE=OV519 Microphone + +usb:v05A9p1550* + ID_MODEL_FROM_DATABASE=VEHO Filmscanner + +usb:v05A9p2640* + ID_MODEL_FROM_DATABASE=OV2640 Webcam + +usb:v05A9p2643* + ID_MODEL_FROM_DATABASE=Monitor Webcam + +usb:v05A9p264B* + ID_MODEL_FROM_DATABASE=Monitor Webcam + +usb:v05A9p2800* + ID_MODEL_FROM_DATABASE=SuperCAM + +usb:v05A9p4519* + ID_MODEL_FROM_DATABASE=Webcam Classic + +usb:v05A9p7670* + ID_MODEL_FROM_DATABASE=OV7670 Webcam + +usb:v05A9p8065* + ID_MODEL_FROM_DATABASE=GAIA Sensor FPGA Demo Board + +usb:v05A9p8519* + ID_MODEL_FROM_DATABASE=OV519 Webcam + +usb:v05A9pA511* + ID_MODEL_FROM_DATABASE=OV511+ Webcam + +usb:v05A9pA518* + ID_MODEL_FROM_DATABASE=D-Link DSB-C310 Webcam + +usb:v05AA* + ID_VENDOR_FROM_DATABASE=Utilux South China, Ltd + +usb:v05AB* + ID_VENDOR_FROM_DATABASE=In-System Design + +usb:v05ABp0002* + ID_MODEL_FROM_DATABASE=Parallel Port + +usb:v05ABp0030* + ID_MODEL_FROM_DATABASE=Storage Adapter V2 (TPP) + +usb:v05ABp0031* + ID_MODEL_FROM_DATABASE=ATA Bridge + +usb:v05ABp0060* + ID_MODEL_FROM_DATABASE=USB 2.0 ATA Bridge + +usb:v05ABp0061* + ID_MODEL_FROM_DATABASE=Storage Adapter V3 (TPP-I) + +usb:v05ABp0101* + ID_MODEL_FROM_DATABASE=Storage Adapter (TPP) + +usb:v05ABp0130* + ID_MODEL_FROM_DATABASE=Compact Flash and Microdrive Reader (TPP) + +usb:v05ABp0200* + ID_MODEL_FROM_DATABASE=USS725 ATA Bridge + +usb:v05ABp0201* + ID_MODEL_FROM_DATABASE=Storage Adapter (TPP) + +usb:v05ABp0202* + ID_MODEL_FROM_DATABASE=ATA Bridge + +usb:v05ABp0300* + ID_MODEL_FROM_DATABASE=Portable Hard Drive (TPP) + +usb:v05ABp0301* + ID_MODEL_FROM_DATABASE=Portable Hard Drive V2 + +usb:v05ABp0350* + ID_MODEL_FROM_DATABASE=Portable Hard Drive (TPP) + +usb:v05ABp0351* + ID_MODEL_FROM_DATABASE=Portable Hard Drive V2 + +usb:v05ABp081A* + ID_MODEL_FROM_DATABASE=ATA Bridge + +usb:v05ABp0CDA* + ID_MODEL_FROM_DATABASE=ATA Bridge for CD-R/RW + +usb:v05ABp1001* + ID_MODEL_FROM_DATABASE=BAYI Printer Class Support + +usb:v05ABp5700* + ID_MODEL_FROM_DATABASE=Storage Adapter V2 (TPP) + +usb:v05ABp5701* + ID_MODEL_FROM_DATABASE=USB Storage Adapter V2 + +usb:v05ABp5901* + ID_MODEL_FROM_DATABASE=Smart Board (TPP) + +usb:v05ABp5A01* + ID_MODEL_FROM_DATABASE=ATI Storage Adapter (TPP) + +usb:v05ABp5D01* + ID_MODEL_FROM_DATABASE=DataBook Adapter (TPP) + +usb:v05AC* + ID_VENDOR_FROM_DATABASE=Apple, Inc. + +usb:v05ACp0201* + ID_MODEL_FROM_DATABASE=USB Keyboard [Alps or Logitech, M2452] + +usb:v05ACp0202* + ID_MODEL_FROM_DATABASE=Keyboard [ALPS] + +usb:v05ACp0205* + ID_MODEL_FROM_DATABASE=Extended Keyboard [Mitsumi] + +usb:v05ACp0206* + ID_MODEL_FROM_DATABASE=Extended Keyboard [Mitsumi] + +usb:v05ACp020B* + ID_MODEL_FROM_DATABASE=Pro Keyboard [Mitsumi, A1048/US layout] + +usb:v05ACp020C* + ID_MODEL_FROM_DATABASE=Extended Keyboard [Mitsumi] + +usb:v05ACp020D* + ID_MODEL_FROM_DATABASE=Pro Keyboard [Mitsumi, A1048/JIS layout] + +usb:v05ACp020E* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp020F* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp0214* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp0215* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp0216* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) + +usb:v05ACp0217* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp0218* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp0219* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) + +usb:v05ACp021A* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp021B* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp021C* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) + +usb:v05ACp021D* + ID_MODEL_FROM_DATABASE=Aluminum Mini Keyboard (ANSI) + +usb:v05ACp021E* + ID_MODEL_FROM_DATABASE=Aluminum Mini Keyboard (ISO) + +usb:v05ACp021F* + ID_MODEL_FROM_DATABASE=Aluminum Mini Keyboard (JIS) + +usb:v05ACp0220* + ID_MODEL_FROM_DATABASE=Aluminum Keyboard (ANSI) + +usb:v05ACp0221* + ID_MODEL_FROM_DATABASE=Aluminum Keyboard (ISO) + +usb:v05ACp0222* + ID_MODEL_FROM_DATABASE=Aluminum Keyboard (JIS) + +usb:v05ACp0223* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp0224* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp0225* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) + +usb:v05ACp0229* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp022A* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Pro) (ISO) + +usb:v05ACp022B* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Pro) (JIS) + +usb:v05ACp0230* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Pro 4,1) (ANSI) + +usb:v05ACp0231* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Pro 4,1) (ISO) + +usb:v05ACp0232* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Pro 4,1) (JIS) + +usb:v05ACp0236* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp0237* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp0238* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) + +usb:v05ACp023F* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp0240* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp0241* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) + +usb:v05ACp0242* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp0243* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp0244* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) + +usb:v05ACp0245* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp0246* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp0247* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) + +usb:v05ACp024A* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Air) (ISO) + +usb:v05ACp024D* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (MacBook Air) (ISO) + +usb:v05ACp0250* + ID_MODEL_FROM_DATABASE=Aluminium Keyboard (ISO) + +usb:v05ACp0252* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ANSI) + +usb:v05ACp0253* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp0254* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (JIS) + +usb:v05ACp0259* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad + +usb:v05ACp0263* + ID_MODEL_FROM_DATABASE=Apple Internal Keyboard / Trackpad (MacBook Retina) + +usb:v05ACp0267* + ID_MODEL_FROM_DATABASE=Magic Keyboard A1644 + +usb:v05ACp0269* + ID_MODEL_FROM_DATABASE=Magic Mouse 2 (Lightning connector) + +usb:v05ACp0273* + ID_MODEL_FROM_DATABASE=Internal Keyboard/Trackpad (ISO) + +usb:v05ACp0301* + ID_MODEL_FROM_DATABASE=USB Mouse [Mitsumi, M4848] + +usb:v05ACp0302* + ID_MODEL_FROM_DATABASE=Optical Mouse [Fujitsu] + +usb:v05ACp0304* + ID_MODEL_FROM_DATABASE=Mighty Mouse [Mitsumi, M1152] + +usb:v05ACp0306* + ID_MODEL_FROM_DATABASE=Optical USB Mouse [Fujitsu] + +usb:v05ACp030A* + ID_MODEL_FROM_DATABASE=Internal Trackpad + +usb:v05ACp030B* + ID_MODEL_FROM_DATABASE=Internal Trackpad + +usb:v05ACp030D* + ID_MODEL_FROM_DATABASE=Magic Mouse + +usb:v05ACp030E* + ID_MODEL_FROM_DATABASE=MC380Z/A [Magic Trackpad] + +usb:v05ACp1000* + ID_MODEL_FROM_DATABASE=Bluetooth HCI MacBookPro (HID mode) + +usb:v05ACp1001* + ID_MODEL_FROM_DATABASE=Keyboard Hub [ALPS] + +usb:v05ACp1002* + ID_MODEL_FROM_DATABASE=Extended Keyboard Hub [Mitsumi] + +usb:v05ACp1003* + ID_MODEL_FROM_DATABASE=Hub in Pro Keyboard [Mitsumi, A1048] + +usb:v05ACp1006* + ID_MODEL_FROM_DATABASE=Hub in Aluminum Keyboard + +usb:v05ACp1008* + ID_MODEL_FROM_DATABASE=Mini DisplayPort to Dual-Link DVI Adapter + +usb:v05ACp1101* + ID_MODEL_FROM_DATABASE=Speakers + +usb:v05ACp1105* + ID_MODEL_FROM_DATABASE=Audio in LED Cinema Display + +usb:v05ACp1107* + ID_MODEL_FROM_DATABASE=Thunderbolt Display Audio + +usb:v05ACp1112* + ID_MODEL_FROM_DATABASE=FaceTime HD Camera (Display) + +usb:v05ACp1201* + ID_MODEL_FROM_DATABASE=3G iPod + +usb:v05ACp1202* + ID_MODEL_FROM_DATABASE=iPod 2G + +usb:v05ACp1203* + ID_MODEL_FROM_DATABASE=iPod 4.Gen Grayscale 40G + +usb:v05ACp1204* + ID_MODEL_FROM_DATABASE=iPod [Photo] + +usb:v05ACp1205* + ID_MODEL_FROM_DATABASE=iPod Mini 1.Gen/2.Gen + +usb:v05ACp1206* + ID_MODEL_FROM_DATABASE=iPod '06' + +usb:v05ACp1207* + ID_MODEL_FROM_DATABASE=iPod '07' + +usb:v05ACp1208* + ID_MODEL_FROM_DATABASE=iPod '08' + +usb:v05ACp1209* + ID_MODEL_FROM_DATABASE=iPod Video + +usb:v05ACp120A* + ID_MODEL_FROM_DATABASE=iPod Nano + +usb:v05ACp1223* + ID_MODEL_FROM_DATABASE=iPod Classic/Nano 3.Gen (DFU mode) + +usb:v05ACp1224* + ID_MODEL_FROM_DATABASE=iPod Nano 3.Gen (DFU mode) + +usb:v05ACp1225* + ID_MODEL_FROM_DATABASE=iPod Nano 4.Gen (DFU mode) + +usb:v05ACp1227* + ID_MODEL_FROM_DATABASE=Mobile Device (DFU Mode) + +usb:v05ACp1231* + ID_MODEL_FROM_DATABASE=iPod Nano 5.Gen (DFU mode) + +usb:v05ACp1240* + ID_MODEL_FROM_DATABASE=iPod Nano 2.Gen (DFU mode) + +usb:v05ACp1242* + ID_MODEL_FROM_DATABASE=iPod Nano 3.Gen (WTF mode) + +usb:v05ACp1243* + ID_MODEL_FROM_DATABASE=iPod Nano 4.Gen (WTF mode) + +usb:v05ACp1245* + ID_MODEL_FROM_DATABASE=iPod Classic 3.Gen (WTF mode) + +usb:v05ACp1246* + ID_MODEL_FROM_DATABASE=iPod Nano 5.Gen (WTF mode) + +usb:v05ACp1255* + ID_MODEL_FROM_DATABASE=iPod Nano 4.Gen (DFU mode) + +usb:v05ACp1260* + ID_MODEL_FROM_DATABASE=iPod Nano 2.Gen + +usb:v05ACp1261* + ID_MODEL_FROM_DATABASE=iPod Classic + +usb:v05ACp1262* + ID_MODEL_FROM_DATABASE=iPod Nano 3.Gen + +usb:v05ACp1263* + ID_MODEL_FROM_DATABASE=iPod Nano 4.Gen + +usb:v05ACp1265* + ID_MODEL_FROM_DATABASE=iPod Nano 5.Gen + +usb:v05ACp1266* + ID_MODEL_FROM_DATABASE=iPod Nano 6.Gen + +usb:v05ACp1267* + ID_MODEL_FROM_DATABASE=iPod Nano 7.Gen + +usb:v05ACp1281* + ID_MODEL_FROM_DATABASE=Apple Mobile Device [Recovery Mode] + +usb:v05ACp1290* + ID_MODEL_FROM_DATABASE=iPhone + +usb:v05ACp1291* + ID_MODEL_FROM_DATABASE=iPod Touch 1.Gen + +usb:v05ACp1292* + ID_MODEL_FROM_DATABASE=iPhone 3G + +usb:v05ACp1293* + ID_MODEL_FROM_DATABASE=iPod Touch 2.Gen + +usb:v05ACp1294* + ID_MODEL_FROM_DATABASE=iPhone 3GS + +usb:v05ACp1296* + ID_MODEL_FROM_DATABASE=iPod Touch 3.Gen (8GB) + +usb:v05ACp1297* + ID_MODEL_FROM_DATABASE=iPhone 4 + +usb:v05ACp1299* + ID_MODEL_FROM_DATABASE=iPod Touch 3.Gen + +usb:v05ACp129A* + ID_MODEL_FROM_DATABASE=iPad + +usb:v05ACp129C* + ID_MODEL_FROM_DATABASE=iPhone 4(CDMA) + +usb:v05ACp129E* + ID_MODEL_FROM_DATABASE=iPod Touch 4.Gen + +usb:v05ACp129F* + ID_MODEL_FROM_DATABASE=iPad 2 + +usb:v05ACp12A0* + ID_MODEL_FROM_DATABASE=iPhone 4S + +usb:v05ACp12A2* + ID_MODEL_FROM_DATABASE=iPad 2 (3G; 64GB) + +usb:v05ACp12A3* + ID_MODEL_FROM_DATABASE=iPad 2 (CDMA) + +usb:v05ACp12A4* + ID_MODEL_FROM_DATABASE=iPad 3 (wifi) + +usb:v05ACp12A5* + ID_MODEL_FROM_DATABASE=iPad 3 (CDMA) + +usb:v05ACp12A6* + ID_MODEL_FROM_DATABASE=iPad 3 (3G, 16 GB) + +usb:v05ACp12A8* + ID_MODEL_FROM_DATABASE=iPhone5/5C/5S/6 + +usb:v05ACp12A9* + ID_MODEL_FROM_DATABASE=iPad 2 + +usb:v05ACp12AA* + ID_MODEL_FROM_DATABASE=iPod Touch 5.Gen [A1421] + +usb:v05ACp12AB* + ID_MODEL_FROM_DATABASE=iPad 4/Mini1 + +usb:v05ACp1300* + ID_MODEL_FROM_DATABASE=iPod Shuffle + +usb:v05ACp1301* + ID_MODEL_FROM_DATABASE=iPod Shuffle 2.Gen + +usb:v05ACp1302* + ID_MODEL_FROM_DATABASE=iPod Shuffle 3.Gen + +usb:v05ACp1303* + ID_MODEL_FROM_DATABASE=iPod Shuffle 4.Gen + +usb:v05ACp1401* + ID_MODEL_FROM_DATABASE=Modem + +usb:v05ACp1402* + ID_MODEL_FROM_DATABASE=Ethernet Adapter [A1277] + +usb:v05ACp1500* + ID_MODEL_FROM_DATABASE=SuperDrive [A1379] + +usb:v05ACp8005* + ID_MODEL_FROM_DATABASE=OHCI Root Hub Simulation + +usb:v05ACp8006* + ID_MODEL_FROM_DATABASE=EHCI Root Hub Simulation + +usb:v05ACp8007* + ID_MODEL_FROM_DATABASE=XHCI Root Hub USB 2.0 Simulation + +usb:v05ACp8202* + ID_MODEL_FROM_DATABASE=HCF V.90 Data/Fax Modem + +usb:v05ACp8203* + ID_MODEL_FROM_DATABASE=Bluetooth HCI + +usb:v05ACp8204* + ID_MODEL_FROM_DATABASE=Built-in Bluetooth 2.0+EDR HCI + +usb:v05ACp8205* + ID_MODEL_FROM_DATABASE=Bluetooth HCI + +usb:v05ACp8206* + ID_MODEL_FROM_DATABASE=Bluetooth HCI + +usb:v05ACp820A* + ID_MODEL_FROM_DATABASE=Bluetooth HID Keyboard + +usb:v05ACp820B* + ID_MODEL_FROM_DATABASE=Bluetooth HID Mouse + +usb:v05ACp820F* + ID_MODEL_FROM_DATABASE=Bluetooth HCI + +usb:v05ACp8213* + ID_MODEL_FROM_DATABASE=Bluetooth Host Controller + +usb:v05ACp8215* + ID_MODEL_FROM_DATABASE=Built-in Bluetooth 2.0+EDR HCI + +usb:v05ACp8216* + ID_MODEL_FROM_DATABASE=Bluetooth USB Host Controller + +usb:v05ACp8217* + ID_MODEL_FROM_DATABASE=Bluetooth USB Host Controller + +usb:v05ACp8218* + ID_MODEL_FROM_DATABASE=Bluetooth Host Controller + +usb:v05ACp821A* + ID_MODEL_FROM_DATABASE=Bluetooth Host Controller + +usb:v05ACp821F* + ID_MODEL_FROM_DATABASE=Built-in Bluetooth 2.0+EDR HCI + +usb:v05ACp8240* + ID_MODEL_FROM_DATABASE=Built-in IR Receiver + +usb:v05ACp8241* + ID_MODEL_FROM_DATABASE=Built-in IR Receiver + +usb:v05ACp8242* + ID_MODEL_FROM_DATABASE=Built-in IR Receiver + +usb:v05ACp8281* + ID_MODEL_FROM_DATABASE=Bluetooth Host Controller + +usb:v05ACp8286* + ID_MODEL_FROM_DATABASE=Bluetooth Host Controller + +usb:v05ACp828C* + ID_MODEL_FROM_DATABASE=Bluetooth Host Controller + +usb:v05ACp8290* + ID_MODEL_FROM_DATABASE=Bluetooth Host Controller + +usb:v05ACp8300* + ID_MODEL_FROM_DATABASE=Built-in iSight (no firmware loaded) + +usb:v05ACp8403* + ID_MODEL_FROM_DATABASE=Internal Memory Card Reader + +usb:v05ACp8404* + ID_MODEL_FROM_DATABASE=Internal Memory Card Reader + +usb:v05ACp8501* + ID_MODEL_FROM_DATABASE=Built-in iSight [Micron] + +usb:v05ACp8502* + ID_MODEL_FROM_DATABASE=Built-in iSight + +usb:v05ACp8505* + ID_MODEL_FROM_DATABASE=Built-in iSight + +usb:v05ACp8507* + ID_MODEL_FROM_DATABASE=Built-in iSight + +usb:v05ACp8508* + ID_MODEL_FROM_DATABASE=iSight in LED Cinema Display + +usb:v05ACp8509* + ID_MODEL_FROM_DATABASE=FaceTime HD Camera + +usb:v05ACp850A* + ID_MODEL_FROM_DATABASE=FaceTime Camera + +usb:v05ACp8510* + ID_MODEL_FROM_DATABASE=FaceTime HD Camera (Built-in) + +usb:v05ACp911C* + ID_MODEL_FROM_DATABASE=Hub in A1082 [Cinema HD Display 23"] + +usb:v05ACp9127* + ID_MODEL_FROM_DATABASE=Hub in Thunderbolt Display + +usb:v05ACp912F* + ID_MODEL_FROM_DATABASE=Hub in 30" Cinema Display + +usb:v05ACp9215* + ID_MODEL_FROM_DATABASE=Studio Display 15" + +usb:v05ACp9217* + ID_MODEL_FROM_DATABASE=Studio Display 17" + +usb:v05ACp9218* + ID_MODEL_FROM_DATABASE=Cinema Display 23" + +usb:v05ACp9219* + ID_MODEL_FROM_DATABASE=Cinema Display 20" + +usb:v05ACp921C* + ID_MODEL_FROM_DATABASE=A1082 [Cinema HD Display 23"] + +usb:v05ACp921E* + ID_MODEL_FROM_DATABASE=Cinema Display 24" + +usb:v05ACp9221* + ID_MODEL_FROM_DATABASE=30" Cinema Display + +usb:v05ACp9226* + ID_MODEL_FROM_DATABASE=LED Cinema Display + +usb:v05ACp9227* + ID_MODEL_FROM_DATABASE=Thunderbolt Display + +usb:v05ACp9232* + ID_MODEL_FROM_DATABASE=Cinema HD Display 30" + +usb:v05ACpFFFF* + ID_MODEL_FROM_DATABASE=Bluetooth in DFU mode - Driver + +usb:v05AD* + ID_VENDOR_FROM_DATABASE=Y.C. Cable U.S.A., Inc. + +usb:v05AE* + ID_VENDOR_FROM_DATABASE=Synopsys, Inc. + +usb:v05AF* + ID_VENDOR_FROM_DATABASE=Jing-Mold Enterprise Co., Ltd + +usb:v05AFp0806* + ID_MODEL_FROM_DATABASE=HP SK806A Keyboard + +usb:v05AFp0809* + ID_MODEL_FROM_DATABASE=Wireless Keyboard and Mouse + +usb:v05AFp0821* + ID_MODEL_FROM_DATABASE=IDE to + +usb:v05AFp3062* + ID_MODEL_FROM_DATABASE=Cordless Keyboard + +usb:v05AFp9167* + ID_MODEL_FROM_DATABASE=KB 9151B - 678 + +usb:v05AFp9267* + ID_MODEL_FROM_DATABASE=KB 9251B - 678 Mouse + +usb:v05B0* + ID_VENDOR_FROM_DATABASE=Fountain Technologies, Inc. + +usb:v05B1* + ID_VENDOR_FROM_DATABASE=First International Computer, Inc. + +usb:v05B1p1389* + ID_MODEL_FROM_DATABASE=Bluetooth Wireless Adapter + +usb:v05B4* + ID_VENDOR_FROM_DATABASE=LG Semicon Co., Ltd + +usb:v05B4p4857* + ID_MODEL_FROM_DATABASE=M-Any DAH-210 + +usb:v05B4p6001* + ID_MODEL_FROM_DATABASE=HYUNDAI GDS30C6001 SSFDC / MMC I/F Controller + +usb:v05B5* + ID_VENDOR_FROM_DATABASE=Dialogic Corp. + +usb:v05B6* + ID_VENDOR_FROM_DATABASE=Proxima Corp. + +usb:v05B7* + ID_VENDOR_FROM_DATABASE=Medianix Semiconductor, Inc. + +usb:v05B8* + ID_VENDOR_FROM_DATABASE=Agiler, Inc. + +usb:v05B8p3002* + ID_MODEL_FROM_DATABASE=Scroll Mouse + +usb:v05B8p3223* + ID_MODEL_FROM_DATABASE=ISY Wireless Presenter + +usb:v05B9* + ID_VENDOR_FROM_DATABASE=Philips Research Laboratories + +usb:v05BA* + ID_VENDOR_FROM_DATABASE=DigitalPersona, Inc. + +usb:v05BAp0007* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v05BAp0008* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v05BAp000A* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v05BB* + ID_VENDOR_FROM_DATABASE=Grey Cell Systems + +usb:v05BC* + ID_VENDOR_FROM_DATABASE=3G Green Green Globe Co., Ltd + +usb:v05BCp0004* + ID_MODEL_FROM_DATABASE=Trackball + +usb:v05BD* + ID_VENDOR_FROM_DATABASE=RAFI GmbH & Co. KG + +usb:v05BE* + ID_VENDOR_FROM_DATABASE=Tyco Electronics (Raychem) + +usb:v05BF* + ID_VENDOR_FROM_DATABASE=S & S Research + +usb:v05C0* + ID_VENDOR_FROM_DATABASE=Keil Software + +usb:v05C1* + ID_VENDOR_FROM_DATABASE=Kawasaki Microelectronics, Inc. + +usb:v05C2* + ID_VENDOR_FROM_DATABASE=Media Phonics (Suisse) S.A. + +usb:v05C5* + ID_VENDOR_FROM_DATABASE=Digi International, Inc. + +usb:v05C5p0002* + ID_MODEL_FROM_DATABASE=AccelePort USB 2 + +usb:v05C5p0004* + ID_MODEL_FROM_DATABASE=AccelePort USB 4 + +usb:v05C5p0008* + ID_MODEL_FROM_DATABASE=AccelePort USB 8 + +usb:v05C6* + ID_VENDOR_FROM_DATABASE=Qualcomm, Inc. + +usb:v05C6p0114* + ID_MODEL_FROM_DATABASE=Select RW-200 CDMA Wireless Modem + +usb:v05C6p1000* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v05C6p3100* + ID_MODEL_FROM_DATABASE=CDMA Wireless Modem/Phone + +usb:v05C6p3196* + ID_MODEL_FROM_DATABASE=CDMA Wireless Modem + +usb:v05C6p3197* + ID_MODEL_FROM_DATABASE=CDMA Wireless Modem/Phone + +usb:v05C6p6000* + ID_MODEL_FROM_DATABASE=Siemens SG75 + +usb:v05C6p6503* + ID_MODEL_FROM_DATABASE=AnyData APE-540H + +usb:v05C6p6613* + ID_MODEL_FROM_DATABASE=Onda H600/N501HS ZTE MF330 + +usb:v05C6p6764* + ID_MODEL_FROM_DATABASE=A0001 Phone [OnePlus One] + +usb:v05C6p9000* + ID_MODEL_FROM_DATABASE=SIMCom SIM5218 modem + +usb:v05C6p9001* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem + +usb:v05C6p9002* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem + +usb:v05C6p9003* + ID_MODEL_FROM_DATABASE=Quectel UC20 + +usb:v05C6p9008* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) + +usb:v05C6p9018* + ID_MODEL_FROM_DATABASE=Qualcomm HSUSB Device + +usb:v05C6p9025* + ID_MODEL_FROM_DATABASE=Qualcomm HSUSB Device + +usb:v05C6p9201* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) + +usb:v05C6p9202* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem + +usb:v05C6p9203* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem + +usb:v05C6p9205* + ID_MODEL_FROM_DATABASE=Gobi 2000 + +usb:v05C6p9211* + ID_MODEL_FROM_DATABASE=Acer Gobi Wireless Modem (QDL mode) + +usb:v05C6p9212* + ID_MODEL_FROM_DATABASE=Acer Gobi Wireless Modem + +usb:v05C6p9214* + ID_MODEL_FROM_DATABASE=Acer Gobi 2000 Wireless Modem (QDL mode) + +usb:v05C6p9215* + ID_MODEL_FROM_DATABASE=Acer Gobi 2000 Wireless Modem + +usb:v05C6p9221* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) + +usb:v05C6p9222* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem + +usb:v05C6p9224* + ID_MODEL_FROM_DATABASE=Sony Gobi 2000 Wireless Modem (QDL mode) + +usb:v05C6p9225* + ID_MODEL_FROM_DATABASE=Sony Gobi 2000 Wireless Modem + +usb:v05C6p9231* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) + +usb:v05C6p9234* + ID_MODEL_FROM_DATABASE=Top Global Gobi 2000 Wireless Modem (QDL mode) + +usb:v05C6p9235* + ID_MODEL_FROM_DATABASE=Top Global Gobi 2000 Wireless Modem + +usb:v05C6p9244* + ID_MODEL_FROM_DATABASE=Samsung Gobi 2000 Wireless Modem (QDL mode) + +usb:v05C6p9245* + ID_MODEL_FROM_DATABASE=Samsung Gobi 2000 Wireless Modem + +usb:v05C6p9264* + ID_MODEL_FROM_DATABASE=Asus Gobi 2000 Wireless Modem (QDL mode) + +usb:v05C6p9265* + ID_MODEL_FROM_DATABASE=Asus Gobi 2000 Wireless Modem + +usb:v05C6p9274* + ID_MODEL_FROM_DATABASE=iRex Technologies Gobi 2000 Wireless Modem (QDL mode) + +usb:v05C6p9275* + ID_MODEL_FROM_DATABASE=iRex Technologies Gobi 2000 Wireless Modem + +usb:v05C7* + ID_VENDOR_FROM_DATABASE=Qtronix Corp. + +usb:v05C7p0113* + ID_MODEL_FROM_DATABASE=PC Line Mouse + +usb:v05C7p1001* + ID_MODEL_FROM_DATABASE=Lynx Mouse + +usb:v05C7p2001* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v05C7p2011* + ID_MODEL_FROM_DATABASE=SCorpius Keyboard + +usb:v05C7p6001* + ID_MODEL_FROM_DATABASE=Ten-Keypad + +usb:v05C8* + ID_VENDOR_FROM_DATABASE=Cheng Uei Precision Industry Co., Ltd (Foxlink) + +usb:v05C8p0103* + ID_MODEL_FROM_DATABASE=FO13FF-65 PC-CAM + +usb:v05C8p010B* + ID_MODEL_FROM_DATABASE=Webcam (UVC) + +usb:v05C8p021A* + ID_MODEL_FROM_DATABASE=HP Webcam + +usb:v05C8p0318* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v05C8p0361* + ID_MODEL_FROM_DATABASE=SunplusIT INC. HP Truevision HD Webcam + +usb:v05C8p036E* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v05C8p0403* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v05C8p041B* + ID_MODEL_FROM_DATABASE=HP 2.0MP High Definition Webcam + +usb:v05C9* + ID_VENDOR_FROM_DATABASE=Semtech Corp. + +usb:v05CA* + ID_VENDOR_FROM_DATABASE=Ricoh Co., Ltd + +usb:v05CAp0101* + ID_MODEL_FROM_DATABASE=RDC-5300 Camera + +usb:v05CAp0325* + ID_MODEL_FROM_DATABASE=Caplio GX (ptp) + +usb:v05CAp032D* + ID_MODEL_FROM_DATABASE=Caplio GX 8 (ptp) + +usb:v05CAp032F* + ID_MODEL_FROM_DATABASE=Caplio R3 (ptp) + +usb:v05CAp03A1* + ID_MODEL_FROM_DATABASE=IS200e + +usb:v05CAp0403* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v05CAp0405* + ID_MODEL_FROM_DATABASE=Type 101 + +usb:v05CAp0406* + ID_MODEL_FROM_DATABASE=Type 102 + +usb:v05CAp1803* + ID_MODEL_FROM_DATABASE=V5 camera [R5U870] + +usb:v05CAp1810* + ID_MODEL_FROM_DATABASE=Pavilion Webcam [R5U870] + +usb:v05CAp1812* + ID_MODEL_FROM_DATABASE=Pavilion Webcam + +usb:v05CAp1814* + ID_MODEL_FROM_DATABASE=HD Webcam + +usb:v05CAp1815* + ID_MODEL_FROM_DATABASE=Dell Laptop Integrated Webcam + +usb:v05CAp1820* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v05CAp1830* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC2 [R5U870] + +usb:v05CAp1832* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC3 [R5U870] + +usb:v05CAp1833* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC2 [R5U870] + +usb:v05CAp1834* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC2 [R5U870] + +usb:v05CAp1835* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC5 [R5U870] + +usb:v05CAp1836* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC4 [R5U870] + +usb:v05CAp1837* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC4 [R5U870] + +usb:v05CAp1839* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC6 [R5U870] + +usb:v05CAp183A* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC7 [R5U870] + +usb:v05CAp183B* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC8 [R5U870] + +usb:v05CAp183D* + ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Webcam + +usb:v05CAp183E* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC9 [R5U870] + +usb:v05CAp1841* + ID_MODEL_FROM_DATABASE=Fujitsu F01/ Lifebook U810 [R5U870] + +usb:v05CAp1870* + ID_MODEL_FROM_DATABASE=Webcam 1000 + +usb:v05CAp18B0* + ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Webcam + +usb:v05CAp18B1* + ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Webcam + +usb:v05CAp18B3* + ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Webcam + +usb:v05CAp18B5* + ID_MODEL_FROM_DATABASE=Sony Vaio Integrated Webcam + +usb:v05CAp2201* + ID_MODEL_FROM_DATABASE=RDC-7 Camera + +usb:v05CAp2202* + ID_MODEL_FROM_DATABASE=Caplio RR30 + +usb:v05CAp2203* + ID_MODEL_FROM_DATABASE=Caplio 300G + +usb:v05CAp2204* + ID_MODEL_FROM_DATABASE=Caplio G3 + +usb:v05CAp2205* + ID_MODEL_FROM_DATABASE=Caplio RR30 / Medion MD 6126 Camera + +usb:v05CAp2206* + ID_MODEL_FROM_DATABASE=Konica DG-3Z + +usb:v05CAp2207* + ID_MODEL_FROM_DATABASE=Caplio Pro G3 + +usb:v05CAp2208* + ID_MODEL_FROM_DATABASE=Caplio G4 + +usb:v05CAp2209* + ID_MODEL_FROM_DATABASE=Caplio 400G wide + +usb:v05CAp220A* + ID_MODEL_FROM_DATABASE=KONICA MINOLTA DG-4Wide + +usb:v05CAp220B* + ID_MODEL_FROM_DATABASE=Caplio RX + +usb:v05CAp220C* + ID_MODEL_FROM_DATABASE=Caplio GX + +usb:v05CAp220D* + ID_MODEL_FROM_DATABASE=Caplio R1/RZ1 + +usb:v05CAp220E* + ID_MODEL_FROM_DATABASE=Sea & Sea 5000G + +usb:v05CAp220F* + ID_MODEL_FROM_DATABASE=Rollei dr5 / Rollei dr5 (PTP mode) + +usb:v05CAp2211* + ID_MODEL_FROM_DATABASE=Caplio R1S + +usb:v05CAp2212* + ID_MODEL_FROM_DATABASE=Caplio R1v Camera + +usb:v05CAp2213* + ID_MODEL_FROM_DATABASE=Caplio R2 + +usb:v05CAp2214* + ID_MODEL_FROM_DATABASE=Caplio GX 8 + +usb:v05CAp2215* + ID_MODEL_FROM_DATABASE=DSC 725 + +usb:v05CAp2216* + ID_MODEL_FROM_DATABASE=Caplio R3 + +usb:v05CAp2222* + ID_MODEL_FROM_DATABASE=RDC-i500 + +usb:v05CB* + ID_VENDOR_FROM_DATABASE=PowerVision Technologies, Inc. + +usb:v05CBp1483* + ID_MODEL_FROM_DATABASE=PV8630 interface (scanners, webcams) + +usb:v05CC* + ID_VENDOR_FROM_DATABASE=ELSA AG + +usb:v05CCp2100* + ID_MODEL_FROM_DATABASE=MicroLink ISDN Office + +usb:v05CCp2219* + ID_MODEL_FROM_DATABASE=MicroLink ISDN + +usb:v05CCp2265* + ID_MODEL_FROM_DATABASE=MicroLink 56k + +usb:v05CCp2267* + ID_MODEL_FROM_DATABASE=MicroLink 56k (V.250) + +usb:v05CCp2280* + ID_MODEL_FROM_DATABASE=MicroLink 56k Fun + +usb:v05CCp3000* + ID_MODEL_FROM_DATABASE=Micolink USB2Ethernet [pegasus] + +usb:v05CCp3100* + ID_MODEL_FROM_DATABASE=AirLancer USB-11 + +usb:v05CCp3363* + ID_MODEL_FROM_DATABASE=MicroLink ADSL Fun + +usb:v05CD* + ID_VENDOR_FROM_DATABASE=Silicom, Ltd + +usb:v05CE* + ID_VENDOR_FROM_DATABASE=sci-worx GmbH + +usb:v05CF* + ID_VENDOR_FROM_DATABASE=Sung Forn Co., Ltd + +usb:v05D0* + ID_VENDOR_FROM_DATABASE=GE Medical Systems Lunar + +usb:v05D1* + ID_VENDOR_FROM_DATABASE=Brainboxes, Ltd + +usb:v05D1p0003* + ID_MODEL_FROM_DATABASE=Bluetooth Adapter BL-554 + +usb:v05D2* + ID_VENDOR_FROM_DATABASE=Wave Systems Corp. + +usb:v05D3* + ID_VENDOR_FROM_DATABASE=Tohoku Ricoh Co., Ltd + +usb:v05D5* + ID_VENDOR_FROM_DATABASE=Super Gate Technology Co., Ltd + +usb:v05D6* + ID_VENDOR_FROM_DATABASE=Philips Semiconductors, CICT + +usb:v05D7* + ID_VENDOR_FROM_DATABASE=Thomas & Betts Corp. + +usb:v05D7p0099* + ID_MODEL_FROM_DATABASE=10Mbps Ethernet [klsi] + +usb:v05D8* + ID_VENDOR_FROM_DATABASE=Ultima Electronics Corp. + +usb:v05D8p4001* + ID_MODEL_FROM_DATABASE=Artec Ultima 2000 + +usb:v05D8p4002* + ID_MODEL_FROM_DATABASE=Artec Ultima 2000 (GT6801 based)/Lifetec LT9385/ScanMagic 1200 UB Plus Scanner + +usb:v05D8p4003* + ID_MODEL_FROM_DATABASE=Artec E+ 48U + +usb:v05D8p4004* + ID_MODEL_FROM_DATABASE=Artec E+ Pro + +usb:v05D8p4005* + ID_MODEL_FROM_DATABASE=MEM48U + +usb:v05D8p4006* + ID_MODEL_FROM_DATABASE=TRUST EASY WEBSCAN 19200 + +usb:v05D8p4007* + ID_MODEL_FROM_DATABASE=TRUST 240H EASY WEBSCAN GOLD + +usb:v05D8p4008* + ID_MODEL_FROM_DATABASE=Trust Easy Webscan 19200 + +usb:v05D8p4009* + ID_MODEL_FROM_DATABASE=Umax Astraslim + +usb:v05D8p4013* + ID_MODEL_FROM_DATABASE=IT Scan 1200 + +usb:v05D8p8105* + ID_MODEL_FROM_DATABASE=Artec T1 USB TVBOX (cold) + +usb:v05D8p8106* + ID_MODEL_FROM_DATABASE=Artec T1 USB TVBOX (warm) + +usb:v05D8p8107* + ID_MODEL_FROM_DATABASE=Artec T1 USB TVBOX with AN2235 (cold) + +usb:v05D8p8108* + ID_MODEL_FROM_DATABASE=Artec T1 USB TVBOX with AN2235 (warm) + +usb:v05D8p8109* + ID_MODEL_FROM_DATABASE=Artec T1 USB2.0 TVBOX (cold + +usb:v05D9* + ID_VENDOR_FROM_DATABASE=Axiohm Transaction Solutions + +usb:v05D9pA225* + ID_MODEL_FROM_DATABASE=A225 Printer + +usb:v05D9pA758* + ID_MODEL_FROM_DATABASE=A758 Printer + +usb:v05D9pA794* + ID_MODEL_FROM_DATABASE=A794 Printer + +usb:v05DA* + ID_VENDOR_FROM_DATABASE=Microtek International, Inc. + +usb:v05DAp0091* + ID_MODEL_FROM_DATABASE=ScanMaker X6u + +usb:v05DAp0093* + ID_MODEL_FROM_DATABASE=ScanMaker V6USL + +usb:v05DAp0094* + ID_MODEL_FROM_DATABASE=Phantom 336CX/C3 + +usb:v05DAp0099* + ID_MODEL_FROM_DATABASE=ScanMaker X6/X6U + +usb:v05DAp009A* + ID_MODEL_FROM_DATABASE=Phantom C6 + +usb:v05DAp00A0* + ID_MODEL_FROM_DATABASE=Phantom 336CX/C3 (#2) + +usb:v05DAp00A3* + ID_MODEL_FROM_DATABASE=ScanMaker V6USL + +usb:v05DAp00AC* + ID_MODEL_FROM_DATABASE=ScanMaker V6UL + +usb:v05DAp00B6* + ID_MODEL_FROM_DATABASE=ScanMaker V6UPL + +usb:v05DAp00EF* + ID_MODEL_FROM_DATABASE=ScanMaker V6UPL + +usb:v05DAp1006* + ID_MODEL_FROM_DATABASE=Jenoptik JD350 entrance + +usb:v05DAp1011* + ID_MODEL_FROM_DATABASE=NHJ Che-ez! Kiss Digital Camera + +usb:v05DAp1018* + ID_MODEL_FROM_DATABASE=Digital Dream Enigma 1.3 + +usb:v05DAp1020* + ID_MODEL_FROM_DATABASE=Digital Dream l'espion xtra + +usb:v05DAp1025* + ID_MODEL_FROM_DATABASE=Take-it Still Camera Device + +usb:v05DAp1026* + ID_MODEL_FROM_DATABASE=Take-it + +usb:v05DAp1043* + ID_MODEL_FROM_DATABASE=Take-It 1300 DSC Bulk Driver + +usb:v05DAp1045* + ID_MODEL_FROM_DATABASE=Take-it D1 + +usb:v05DAp1047* + ID_MODEL_FROM_DATABASE=Take-it Camera Composite Device + +usb:v05DAp1048* + ID_MODEL_FROM_DATABASE=Take-it Q3 + +usb:v05DAp1049* + ID_MODEL_FROM_DATABASE=3M Still Camera Device + +usb:v05DAp1051* + ID_MODEL_FROM_DATABASE=Camcorder Series + +usb:v05DAp1052* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v05DAp1053* + ID_MODEL_FROM_DATABASE=Take-it DV Composite Device + +usb:v05DAp1054* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v05DAp1055* + ID_MODEL_FROM_DATABASE=Digital Camera Series(536) + +usb:v05DAp1056* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v05DAp1057* + ID_MODEL_FROM_DATABASE=Take-it DSC Camera Device(536) + +usb:v05DAp1058* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v05DAp1059* + ID_MODEL_FROM_DATABASE=Camcorder DSC Series + +usb:v05DAp1060* + ID_MODEL_FROM_DATABASE=Microtek Take-it MV500 + +usb:v05DAp2007* + ID_MODEL_FROM_DATABASE=ArtixScan DI 1210 + +usb:v05DAp200C* + ID_MODEL_FROM_DATABASE=1394_USB2 Scanner + +usb:v05DAp200E* + ID_MODEL_FROM_DATABASE=ArtixScan DI 810 + +usb:v05DAp2017* + ID_MODEL_FROM_DATABASE=UF ICE Scanner + +usb:v05DAp201C* + ID_MODEL_FROM_DATABASE=4800 Scanner + +usb:v05DAp201D* + ID_MODEL_FROM_DATABASE=ArtixScan DI 1610 + +usb:v05DAp201F* + ID_MODEL_FROM_DATABASE=4800 Scanner-ICE + +usb:v05DAp202E* + ID_MODEL_FROM_DATABASE=ArtixScan DI 2020 + +usb:v05DAp208B* + ID_MODEL_FROM_DATABASE=ScanMaker 6800 + +usb:v05DAp208F* + ID_MODEL_FROM_DATABASE=ArtixScan DI 2010 + +usb:v05DAp209E* + ID_MODEL_FROM_DATABASE=ScanMaker 4700LP + +usb:v05DAp20A7* + ID_MODEL_FROM_DATABASE=ScanMaker 5600 + +usb:v05DAp20B0* + ID_MODEL_FROM_DATABASE=ScanMaker X12USL + +usb:v05DAp20B1* + ID_MODEL_FROM_DATABASE=ScanMaker 8700 + +usb:v05DAp20B4* + ID_MODEL_FROM_DATABASE=ScanMaker 4700 + +usb:v05DAp20BD* + ID_MODEL_FROM_DATABASE=ScanMaker 5700 + +usb:v05DAp20C9* + ID_MODEL_FROM_DATABASE=ScanMaker 6700 + +usb:v05DAp20D2* + ID_MODEL_FROM_DATABASE=Microtek ArtixScan 1800f + +usb:v05DAp20D6* + ID_MODEL_FROM_DATABASE=PS4000 + +usb:v05DAp20DE* + ID_MODEL_FROM_DATABASE=ScanMaker 9800XL + +usb:v05DAp20E0* + ID_MODEL_FROM_DATABASE=ScanMaker 9700XL + +usb:v05DAp20ED* + ID_MODEL_FROM_DATABASE=ScanMaker 4700 + +usb:v05DAp20EE* + ID_MODEL_FROM_DATABASE=Micortek ScanMaker X12USL + +usb:v05DAp2838* + ID_MODEL_FROM_DATABASE=RT2832U + +usb:v05DAp3008* + ID_MODEL_FROM_DATABASE=Scanner + +usb:v05DAp300A* + ID_MODEL_FROM_DATABASE=4800 ICE Scanner + +usb:v05DAp300B* + ID_MODEL_FROM_DATABASE=4800 Scanner + +usb:v05DAp300F* + ID_MODEL_FROM_DATABASE=MiniScan C5 + +usb:v05DAp3020* + ID_MODEL_FROM_DATABASE=4800dpi Scanner + +usb:v05DAp3021* + ID_MODEL_FROM_DATABASE=1200dpi Scanner + +usb:v05DAp3022* + ID_MODEL_FROM_DATABASE=Scanner 4800dpi + +usb:v05DAp3023* + ID_MODEL_FROM_DATABASE=USB1200II Scanner + +usb:v05DAp3025* + ID_MODEL_FROM_DATABASE=ScanMaker S460 + +usb:v05DAp30C1* + ID_MODEL_FROM_DATABASE=USB600 Scanner + +usb:v05DAp30CE* + ID_MODEL_FROM_DATABASE=ScanMaker 3800 + +usb:v05DAp30CF* + ID_MODEL_FROM_DATABASE=ScanMaker 4800 + +usb:v05DAp30D4* + ID_MODEL_FROM_DATABASE=USB1200 Scanner + +usb:v05DAp30D8* + ID_MODEL_FROM_DATABASE=Scanner + +usb:v05DAp30D9* + ID_MODEL_FROM_DATABASE=USB2400 Scanner + +usb:v05DAp30E4* + ID_MODEL_FROM_DATABASE=ScanMaker 4100 + +usb:v05DAp30E5* + ID_MODEL_FROM_DATABASE=USB3200 Scanner + +usb:v05DAp30E6* + ID_MODEL_FROM_DATABASE=ScanMaker i320 + +usb:v05DAp40B3* + ID_MODEL_FROM_DATABASE=ScanMaker 3600 + +usb:v05DAp40B8* + ID_MODEL_FROM_DATABASE=ScanMaker 3700 + +usb:v05DAp40C7* + ID_MODEL_FROM_DATABASE=ScanMaker 4600 + +usb:v05DAp40CA* + ID_MODEL_FROM_DATABASE=ScanMaker 3600 + +usb:v05DAp40CB* + ID_MODEL_FROM_DATABASE=ScanMaker 3700 + +usb:v05DAp40DD* + ID_MODEL_FROM_DATABASE=ScanMaker 3750i + +usb:v05DAp40FF* + ID_MODEL_FROM_DATABASE=ScanMaker 3600 + +usb:v05DAp5003* + ID_MODEL_FROM_DATABASE=Goya + +usb:v05DAp5013* + ID_MODEL_FROM_DATABASE=3200 Scanner + +usb:v05DAp6072* + ID_MODEL_FROM_DATABASE=XT-3500 A4 HD Scanner + +usb:v05DAp80A3* + ID_MODEL_FROM_DATABASE=ScanMaker V6USL (#2) + +usb:v05DAp80AC* + ID_MODEL_FROM_DATABASE=ScanMaker V6UL/SpicyU + +usb:v05DB* + ID_VENDOR_FROM_DATABASE=Sun Corp. (Suntac?) + +usb:v05DBp0003* + ID_MODEL_FROM_DATABASE=SUNTAC U-Cable type D2 + +usb:v05DBp0005* + ID_MODEL_FROM_DATABASE=SUNTAC U-Cable type P1 + +usb:v05DBp0009* + ID_MODEL_FROM_DATABASE=SUNTAC Slipper U + +usb:v05DBp000A* + ID_MODEL_FROM_DATABASE=SUNTAC Ir-Trinity + +usb:v05DBp000B* + ID_MODEL_FROM_DATABASE=SUNTAC U-Cable type A3 + +usb:v05DBp0011* + ID_MODEL_FROM_DATABASE=SUNTAC U-Cable type A4 + +usb:v05DC* + ID_VENDOR_FROM_DATABASE=Lexar Media, Inc. + +usb:v05DCp0001* + ID_MODEL_FROM_DATABASE=jumpSHOT CompactFlash Reader + +usb:v05DCp0002* + ID_MODEL_FROM_DATABASE=JumpShot + +usb:v05DCp0003* + ID_MODEL_FROM_DATABASE=JumpShot + +usb:v05DCp0080* + ID_MODEL_FROM_DATABASE=Jumpdrive Secure 64MB + +usb:v05DCp0081* + ID_MODEL_FROM_DATABASE=RBC Compact Flash Drive + +usb:v05DCp00A7* + ID_MODEL_FROM_DATABASE=JumpDrive Impact + +usb:v05DCp0100* + ID_MODEL_FROM_DATABASE=JumpDrive PRO + +usb:v05DCp0200* + ID_MODEL_FROM_DATABASE=JumpDrive 2.0 Pro + +usb:v05DCp0300* + ID_MODEL_FROM_DATABASE=Jumpdrive Geysr + +usb:v05DCp0301* + ID_MODEL_FROM_DATABASE=JumpDrive Classic + +usb:v05DCp0302* + ID_MODEL_FROM_DATABASE=JD Micro + +usb:v05DCp0303* + ID_MODEL_FROM_DATABASE=JD Micro Pro + +usb:v05DCp0304* + ID_MODEL_FROM_DATABASE=JD Secure II + +usb:v05DCp0310* + ID_MODEL_FROM_DATABASE=JumpDrive + +usb:v05DCp0311* + ID_MODEL_FROM_DATABASE=JumpDrive Classic + +usb:v05DCp0312* + ID_MODEL_FROM_DATABASE=JD Micro + +usb:v05DCp0313* + ID_MODEL_FROM_DATABASE=JD Micro Pro + +usb:v05DCp0320* + ID_MODEL_FROM_DATABASE=JumpDrive + +usb:v05DCp0321* + ID_MODEL_FROM_DATABASE=JD Micro + +usb:v05DCp0322* + ID_MODEL_FROM_DATABASE=JD Micro Pro + +usb:v05DCp0323* + ID_MODEL_FROM_DATABASE=UFC + +usb:v05DCp0330* + ID_MODEL_FROM_DATABASE=JumpDrive Expression + +usb:v05DCp0340* + ID_MODEL_FROM_DATABASE=JumpDrive TAD + +usb:v05DCp0350* + ID_MODEL_FROM_DATABASE=Express Card + +usb:v05DCp0400* + ID_MODEL_FROM_DATABASE=UFDC + +usb:v05DCp0401* + ID_MODEL_FROM_DATABASE=UFDC + +usb:v05DCp0403* + ID_MODEL_FROM_DATABASE=Locked B Device + +usb:v05DCp0405* + ID_MODEL_FROM_DATABASE=Locked C Device + +usb:v05DCp0407* + ID_MODEL_FROM_DATABASE=Locked D Device + +usb:v05DCp0409* + ID_MODEL_FROM_DATABASE=Locked E Device + +usb:v05DCp040B* + ID_MODEL_FROM_DATABASE=Locked F Device + +usb:v05DCp040D* + ID_MODEL_FROM_DATABASE=Locked G Device + +usb:v05DCp040F* + ID_MODEL_FROM_DATABASE=Locked H Device + +usb:v05DCp0410* + ID_MODEL_FROM_DATABASE=JumpDrive + +usb:v05DCp0411* + ID_MODEL_FROM_DATABASE=JumpDrive + +usb:v05DCp0413* + ID_MODEL_FROM_DATABASE=Locked J Device + +usb:v05DCp0415* + ID_MODEL_FROM_DATABASE=Locked K Device + +usb:v05DCp0417* + ID_MODEL_FROM_DATABASE=Locked L Device + +usb:v05DCp0419* + ID_MODEL_FROM_DATABASE=Locked M Device + +usb:v05DCp041B* + ID_MODEL_FROM_DATABASE=Locked N Device + +usb:v05DCp041D* + ID_MODEL_FROM_DATABASE=Locked O Device + +usb:v05DCp041F* + ID_MODEL_FROM_DATABASE=Locked P Device + +usb:v05DCp0420* + ID_MODEL_FROM_DATABASE=JumpDrive + +usb:v05DCp0421* + ID_MODEL_FROM_DATABASE=JumpDrive + +usb:v05DCp0423* + ID_MODEL_FROM_DATABASE=Locked R Device + +usb:v05DCp0425* + ID_MODEL_FROM_DATABASE=Locked S Device + +usb:v05DCp0427* + ID_MODEL_FROM_DATABASE=Locked T Device + +usb:v05DCp0429* + ID_MODEL_FROM_DATABASE=Locked U Device + +usb:v05DCp042B* + ID_MODEL_FROM_DATABASE=Locked V Device + +usb:v05DCp042D* + ID_MODEL_FROM_DATABASE=Locked W Device + +usb:v05DCp042F* + ID_MODEL_FROM_DATABASE=Locked X Device + +usb:v05DCp0431* + ID_MODEL_FROM_DATABASE=Locked Y Device + +usb:v05DCp0433* + ID_MODEL_FROM_DATABASE=Locked Z Device + +usb:v05DCp4D02* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v05DCp4D12* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v05DCp4D30* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v05DCpA209* + ID_MODEL_FROM_DATABASE=JumpDrive S70 + +usb:v05DCpA300* + ID_MODEL_FROM_DATABASE=JumpDrive2 + +usb:v05DCpA400* + ID_MODEL_FROM_DATABASE=JumpDrive trade; Pro 40-501 + +usb:v05DCpA410* + ID_MODEL_FROM_DATABASE=JumpDrive 128MB/256MB + +usb:v05DCpA411* + ID_MODEL_FROM_DATABASE=JumpDrive Traveler + +usb:v05DCpA420* + ID_MODEL_FROM_DATABASE=JumpDrive Pro + +usb:v05DCpA421* + ID_MODEL_FROM_DATABASE=JumpDrive Pro II + +usb:v05DCpA422* + ID_MODEL_FROM_DATABASE=JumpDrive Micro Pro + +usb:v05DCpA430* + ID_MODEL_FROM_DATABASE=JumpDrive Secure + +usb:v05DCpA431* + ID_MODEL_FROM_DATABASE=JumpDrive Secure II + +usb:v05DCpA432* + ID_MODEL_FROM_DATABASE=JumpDrive Classic + +usb:v05DCpA440* + ID_MODEL_FROM_DATABASE=JumpDrive Lightning + +usb:v05DCpA450* + ID_MODEL_FROM_DATABASE=JumpDrive TouchGuard + +usb:v05DCpA460* + ID_MODEL_FROM_DATABASE=JD Mercury + +usb:v05DCpA501* + ID_MODEL_FROM_DATABASE=JumpDrive Classic + +usb:v05DCpA510* + ID_MODEL_FROM_DATABASE=JumpDrive Sport + +usb:v05DCpA530* + ID_MODEL_FROM_DATABASE=JumpDrive Expression + +usb:v05DCpA531* + ID_MODEL_FROM_DATABASE=JumpDrive Secure II + +usb:v05DCpA560* + ID_MODEL_FROM_DATABASE=JumpDrive FireFly + +usb:v05DCpA701* + ID_MODEL_FROM_DATABASE=JumpDrive FireFly + +usb:v05DCpA731* + ID_MODEL_FROM_DATABASE=JumpDrive FireFly + +usb:v05DCpA762* + ID_MODEL_FROM_DATABASE=JumpDrive FireFly + +usb:v05DCpA768* + ID_MODEL_FROM_DATABASE=JumpDrive Retrax + +usb:v05DCpA790* + ID_MODEL_FROM_DATABASE=JumpDrive 2GB + +usb:v05DCpA811* + ID_MODEL_FROM_DATABASE=16GB Gizmo! + +usb:v05DCpA813* + ID_MODEL_FROM_DATABASE=16gB flash thumb drive + +usb:v05DCpA815* + ID_MODEL_FROM_DATABASE=JumpDrive V10 + +usb:v05DCpA81D* + ID_MODEL_FROM_DATABASE=LJDTT16G [JumpDrive 16GB] + +usb:v05DCpA833* + ID_MODEL_FROM_DATABASE=JumpDrive S23 64GB + +usb:v05DCpA838* + ID_MODEL_FROM_DATABASE=JumpDrive Tough + +usb:v05DCpB002* + ID_MODEL_FROM_DATABASE=USB CF Reader + +usb:v05DCpB018* + ID_MODEL_FROM_DATABASE=Multi-Card Reader + +usb:v05DCpB047* + ID_MODEL_FROM_DATABASE=SDHC Reader [RW047-7000] + +usb:v05DCpB051* + ID_MODEL_FROM_DATABASE=microSD RDR UHS-I Card Reader [LRWM03U-7000] + +usb:v05DCpBA02* + ID_MODEL_FROM_DATABASE=Workflow CFR1 + +usb:v05DCpBA0A* + ID_MODEL_FROM_DATABASE=Workflow DD512 + +usb:v05DCpC753* + ID_MODEL_FROM_DATABASE=JumpDrive TwistTurn + +usb:v05DCpC75C* + ID_MODEL_FROM_DATABASE=JumpDrive V10 + +usb:v05DD* + ID_VENDOR_FROM_DATABASE=Delta Electronics, Inc. + +usb:v05DDpFF31* + ID_MODEL_FROM_DATABASE=AWU-120 + +usb:v05DDpFF32* + ID_MODEL_FROM_DATABASE=FriendlyNET AeroLAN AL2011 + +usb:v05DDpFF35* + ID_MODEL_FROM_DATABASE=PCW 100 - Wireless 802.11b Adapter + +usb:v05DDpFF91* + ID_MODEL_FROM_DATABASE=2Wire PC Port Phoneline 10Mbps Adapter + +usb:v05DF* + ID_VENDOR_FROM_DATABASE=Silicon Vision, Inc. + +usb:v05E0* + ID_VENDOR_FROM_DATABASE=Symbol Technologies + +usb:v05E0p0700* + ID_MODEL_FROM_DATABASE=Bar Code Scanner (CS1504) + +usb:v05E0p0800* + ID_MODEL_FROM_DATABASE=Spectrum24 Wireless LAN Adapter + +usb:v05E0p1200* + ID_MODEL_FROM_DATABASE=Bar Code Scanner + +usb:v05E0p1701* + ID_MODEL_FROM_DATABASE=Bar Code Scanner (CDC) + +usb:v05E0p1900* + ID_MODEL_FROM_DATABASE=SNAPI Imaging Device + +usb:v05E0p2000* + ID_MODEL_FROM_DATABASE=MC3090 Rugged Mobile Computer + +usb:v05E0p200D* + ID_MODEL_FROM_DATABASE=MC70 Rugged Mobile Computer + +usb:v05E1* + ID_VENDOR_FROM_DATABASE=Syntek Semiconductor Co., Ltd + +usb:v05E1p0100* + ID_MODEL_FROM_DATABASE=802.11g + Bluetooth Wireless Adapter + +usb:v05E1p0408* + ID_MODEL_FROM_DATABASE=STK1160 Video Capture Device + +usb:v05E1p0500* + ID_MODEL_FROM_DATABASE=DC-112X Webcam + +usb:v05E1p0501* + ID_MODEL_FROM_DATABASE=DC-1125 Webcam + +usb:v05E1p0890* + ID_MODEL_FROM_DATABASE=STK011 Camera + +usb:v05E1p0892* + ID_MODEL_FROM_DATABASE=STK013 Camera + +usb:v05E1p0895* + ID_MODEL_FROM_DATABASE=STK016 Camera + +usb:v05E1p0896* + ID_MODEL_FROM_DATABASE=STK017 Camera + +usb:v05E1p2010* + ID_MODEL_FROM_DATABASE=ARCTIC Sound P261 Headphones + +usb:v05E2* + ID_VENDOR_FROM_DATABASE=ElecVision, Inc. + +usb:v05E3* + ID_VENDOR_FROM_DATABASE=Genesys Logic, Inc. + +usb:v05E3p000A* + ID_MODEL_FROM_DATABASE=Keyboard with PS/2 Port + +usb:v05E3p000B* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v05E3p0100* + ID_MODEL_FROM_DATABASE=Nintendo Game Boy Advance SP + +usb:v05E3p0120* + ID_MODEL_FROM_DATABASE=Pacific Image Electronics PrimeFilm 1800u slide/negative scanner + +usb:v05E3p0131* + ID_MODEL_FROM_DATABASE=CF/SM Reader/Writer + +usb:v05E3p0142* + ID_MODEL_FROM_DATABASE=Multiple Slides Scanner-3600 + +usb:v05E3p0143* + ID_MODEL_FROM_DATABASE=Multiple Frames Film Scanner-36series + +usb:v05E3p0145* + ID_MODEL_FROM_DATABASE=Reflecta CrystalScan 7200 Photo-Scanner + +usb:v05E3p0180* + ID_MODEL_FROM_DATABASE=Plustek Scanner + +usb:v05E3p0182* + ID_MODEL_FROM_DATABASE=Wize Media 1000 + +usb:v05E3p0189* + ID_MODEL_FROM_DATABASE=ScanJet 4600 series + +usb:v05E3p018A* + ID_MODEL_FROM_DATABASE=Xerox 6400 + +usb:v05E3p0300* + ID_MODEL_FROM_DATABASE=GLUSB98PT Parallel Port + +usb:v05E3p0301* + ID_MODEL_FROM_DATABASE=USB2LPT Cable Release2 + +usb:v05E3p0406* + ID_MODEL_FROM_DATABASE=Hub + +usb:v05E3p0501* + ID_MODEL_FROM_DATABASE=GL620USB Host-Host interface + +usb:v05E3p0502* + ID_MODEL_FROM_DATABASE=GL620USB-A GeneLink USB-USB Bridge + +usb:v05E3p0503* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v05E3p0504* + ID_MODEL_FROM_DATABASE=HID Keyboard Filter + +usb:v05E3p0604* + ID_MODEL_FROM_DATABASE=USB 1.1 Hub + +usb:v05E3p0605* + ID_MODEL_FROM_DATABASE=USB 2.0 Hub + +usb:v05E3p0606* + ID_MODEL_FROM_DATABASE=USB 2.0 Hub / D-Link DUB-H4 USB 2.0 Hub + +usb:v05E3p0607* + ID_MODEL_FROM_DATABASE=Logitech G110 Hub + +usb:v05E3p0608* + ID_MODEL_FROM_DATABASE=Hub + +usb:v05E3p0610* + ID_MODEL_FROM_DATABASE=4-port hub + +usb:v05E3p0612* + ID_MODEL_FROM_DATABASE=Hub + +usb:v05E3p0616* + ID_MODEL_FROM_DATABASE=hub + +usb:v05E3p0660* + ID_MODEL_FROM_DATABASE=USB 2.0 Hub + +usb:v05E3p0700* + ID_MODEL_FROM_DATABASE=SIIG US2256 CompactFlash Card Reader + +usb:v05E3p0701* + ID_MODEL_FROM_DATABASE=USB 2.0 IDE Adapter + +usb:v05E3p0702* + ID_MODEL_FROM_DATABASE=USB 2.0 IDE Adapter [GL811E] + +usb:v05E3p0703* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v05E3p0704* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v05E3p0705* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v05E3p0706* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v05E3p0707* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v05E3p0708* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v05E3p0709* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v05E3p070A* + ID_MODEL_FROM_DATABASE=Pen Flash + +usb:v05E3p070B* + ID_MODEL_FROM_DATABASE=DMHS1B Rev 3 DFU Adapter + +usb:v05E3p070E* + ID_MODEL_FROM_DATABASE=USB 2.0 Card Reader + +usb:v05E3p070F* + ID_MODEL_FROM_DATABASE=Pen Flash + +usb:v05E3p0710* + ID_MODEL_FROM_DATABASE=USB 2.0 33-in-1 Card Reader + +usb:v05E3p0711* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v05E3p0712* + ID_MODEL_FROM_DATABASE=Delkin Mass Storage Device + +usb:v05E3p0715* + ID_MODEL_FROM_DATABASE=USB 2.0 microSD Reader + +usb:v05E3p0716* + ID_MODEL_FROM_DATABASE=USB 2.0 Multislot Card Reader/Writer + +usb:v05E3p0717* + ID_MODEL_FROM_DATABASE=All-in-1 Card Reader + +usb:v05E3p0718* + ID_MODEL_FROM_DATABASE=IDE/SATA Adapter + +usb:v05E3p0719* + ID_MODEL_FROM_DATABASE=SATA adapter + +usb:v05E3p0722* + ID_MODEL_FROM_DATABASE=SD/MMC card reader + +usb:v05E3p0723* + ID_MODEL_FROM_DATABASE=GL827L SD/MMC/MS Flash Card Reader + +usb:v05E3p0726* + ID_MODEL_FROM_DATABASE=SD Card Reader + +usb:v05E3p0727* + ID_MODEL_FROM_DATABASE=microSD Reader/Writer + +usb:v05E3p0731* + ID_MODEL_FROM_DATABASE=GL3310 SATA 3Gb/s Bridge Controller + +usb:v05E3p0732* + ID_MODEL_FROM_DATABASE=All-in-One Cardreader + +usb:v05E3p0736* + ID_MODEL_FROM_DATABASE=microSD Reader/Writer + +usb:v05E3p0738* + ID_MODEL_FROM_DATABASE=Card reader + +usb:v05E3p0741* + ID_MODEL_FROM_DATABASE=microSD Card Reader + +usb:v05E3p0743* + ID_MODEL_FROM_DATABASE=SDXC and microSDXC CardReader + +usb:v05E3p0745* + ID_MODEL_FROM_DATABASE=Logilink CR0012 + +usb:v05E3p0748* + ID_MODEL_FROM_DATABASE=All-in-One Cardreader + +usb:v05E3p0751* + ID_MODEL_FROM_DATABASE=microSD Card Reader + +usb:v05E3p0760* + ID_MODEL_FROM_DATABASE=USB 2.0 Card Reader/Writer + +usb:v05E3p0761* + ID_MODEL_FROM_DATABASE=Genesys Mass Storage Device + +usb:v05E3p0780* + ID_MODEL_FROM_DATABASE=USBFS DFU Adapter + +usb:v05E3p07A0* + ID_MODEL_FROM_DATABASE=Pen Flash + +usb:v05E3p0880* + ID_MODEL_FROM_DATABASE=Wasp (SL-6612) + +usb:v05E3p0927* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v05E3p1205* + ID_MODEL_FROM_DATABASE=Afilias Optical Mouse H3003 / Trust Optical USB MultiColour Mouse MI-2330 + +usb:v05E3pA700* + ID_MODEL_FROM_DATABASE=Pen Flash + +usb:v05E3pF102* + ID_MODEL_FROM_DATABASE=VX7012 TV Box + +usb:v05E3pF103* + ID_MODEL_FROM_DATABASE=VX7012 TV Box + +usb:v05E3pF104* + ID_MODEL_FROM_DATABASE=VX7012 TV Box + +usb:v05E3pFD21* + ID_MODEL_FROM_DATABASE=3M TL20 Temperature Logger + +usb:v05E3pFE00* + ID_MODEL_FROM_DATABASE=Razer Mouse + +usb:v05E4* + ID_VENDOR_FROM_DATABASE=Red Wing Corp. + +usb:v05E5* + ID_VENDOR_FROM_DATABASE=Fuji Electric Co., Ltd + +usb:v05E6* + ID_VENDOR_FROM_DATABASE=Keithley Instruments + +usb:v05E8* + ID_VENDOR_FROM_DATABASE=ICC, Inc. + +usb:v05E9* + ID_VENDOR_FROM_DATABASE=Kawasaki LSI + +usb:v05E9p0008* + ID_MODEL_FROM_DATABASE=KL5KUSB101B Ethernet [klsi] + +usb:v05E9p0009* + ID_MODEL_FROM_DATABASE=Sony 10Mbps Ethernet [pegasus] + +usb:v05E9p000C* + ID_MODEL_FROM_DATABASE=USB-to-RS-232 + +usb:v05E9p000D* + ID_MODEL_FROM_DATABASE=USB-to-RS-232 + +usb:v05E9p0014* + ID_MODEL_FROM_DATABASE=RS-232 J104 + +usb:v05E9p0040* + ID_MODEL_FROM_DATABASE=Ethernet Adapter + +usb:v05E9p2008* + ID_MODEL_FROM_DATABASE=Ethernet Adapter + +usb:v05EB* + ID_VENDOR_FROM_DATABASE=FFC, Ltd + +usb:v05EC* + ID_VENDOR_FROM_DATABASE=COM21, Inc. + +usb:v05EE* + ID_VENDOR_FROM_DATABASE=Cytechinfo Inc. + +usb:v05EF* + ID_VENDOR_FROM_DATABASE=AVB, Inc. [anko?] + +usb:v05EFp020A* + ID_MODEL_FROM_DATABASE=Top Shot Pegasus Joystick + +usb:v05EFp8884* + ID_MODEL_FROM_DATABASE=Mag Turbo Force Wheel + +usb:v05EFp8888* + ID_MODEL_FROM_DATABASE=Top Shot Force Feedback Racing Wheel + +usb:v05F0* + ID_VENDOR_FROM_DATABASE=Canopus Co., Ltd + +usb:v05F0p0101* + ID_MODEL_FROM_DATABASE=DA-Port DAC + +usb:v05F1* + ID_VENDOR_FROM_DATABASE=Compass Communications + +usb:v05F2* + ID_VENDOR_FROM_DATABASE=Dexin Corp., Ltd + +usb:v05F2p0010* + ID_MODEL_FROM_DATABASE=AQ Mouse + +usb:v05F3* + ID_VENDOR_FROM_DATABASE=PI Engineering, Inc. + +usb:v05F3p0007* + ID_MODEL_FROM_DATABASE=Kinesis Advantage PRO MPC/USB Keyboard + +usb:v05F3p0081* + ID_MODEL_FROM_DATABASE=Kinesis Integrated Hub + +usb:v05F3p00FF* + ID_MODEL_FROM_DATABASE=VEC Footpedal + +usb:v05F3p0203* + ID_MODEL_FROM_DATABASE=Y-mouse Keyboard & Mouse Adapter + +usb:v05F3p020B* + ID_MODEL_FROM_DATABASE=PS2 Adapter + +usb:v05F3p0232* + ID_MODEL_FROM_DATABASE=X-Keys Switch Interface, Programming Mode + +usb:v05F3p0261* + ID_MODEL_FROM_DATABASE=X-Keys Switch Interface, SPLAT Mode + +usb:v05F3p0264* + ID_MODEL_FROM_DATABASE=X-Keys Switch Interface, Composite Mode + +usb:v05F5* + ID_VENDOR_FROM_DATABASE=Unixtar Technology, Inc. + +usb:v05F6* + ID_VENDOR_FROM_DATABASE=AOC International + +usb:v05F7* + ID_VENDOR_FROM_DATABASE=RFC Distribution(s) PTE, Ltd + +usb:v05F9* + ID_VENDOR_FROM_DATABASE=PSC Scanning, Inc. + +usb:v05F9p1104* + ID_MODEL_FROM_DATABASE=Magellan 2200VS + +usb:v05F9p1206* + ID_MODEL_FROM_DATABASE=Gryphon series (OEM mode) + +usb:v05F9p2202* + ID_MODEL_FROM_DATABASE=Point of Sale Handheld Scanner + +usb:v05F9p2206* + ID_MODEL_FROM_DATABASE=Gryphon series (keyboard emulation mode) + +usb:v05F9p220C* + ID_MODEL_FROM_DATABASE=Datalogic Gryphon GD4430 + +usb:v05F9p2601* + ID_MODEL_FROM_DATABASE=Datalogic Magellan 1000i Barcode Scanner + +usb:v05F9p2602* + ID_MODEL_FROM_DATABASE=Datalogic Magellan 1100i Barcode Scanner + +usb:v05F9p4204* + ID_MODEL_FROM_DATABASE=Gryphon series (RS-232 emulation mode) + +usb:v05F9p5204* + ID_MODEL_FROM_DATABASE=Datalogic Gryphon GFS4170 (config mode) + +usb:v05FA* + ID_VENDOR_FROM_DATABASE=Siemens Telecommunications Systems, Ltd + +usb:v05FAp3301* + ID_MODEL_FROM_DATABASE=Keyboard with PS/2 Mouse Port + +usb:v05FAp3302* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v05FAp3303* + ID_MODEL_FROM_DATABASE=Keyboard with PS/2 Mouse Port + +usb:v05FC* + ID_VENDOR_FROM_DATABASE=Harman + +usb:v05FCp0001* + ID_MODEL_FROM_DATABASE=Soundcraft Si Multi Digital Card + +usb:v05FCp0010* + ID_MODEL_FROM_DATABASE=Soundcraft Si MADI combo card + +usb:v05FCp7849* + ID_MODEL_FROM_DATABASE=Harman/Kardon SoundSticks + +usb:v05FD* + ID_VENDOR_FROM_DATABASE=InterAct, Inc. + +usb:v05FDp0239* + ID_MODEL_FROM_DATABASE=SV-239 HammerHead Digital + +usb:v05FDp0251* + ID_MODEL_FROM_DATABASE=Raider Pro + +usb:v05FDp0253* + ID_MODEL_FROM_DATABASE=ProPad 8 Digital + +usb:v05FDp0286* + ID_MODEL_FROM_DATABASE=SV-286 Cyclone Digital + +usb:v05FDp107A* + ID_MODEL_FROM_DATABASE=PowerPad Pro X-Box pad + +usb:v05FDp262A* + ID_MODEL_FROM_DATABASE=3dfx HammerHead FX + +usb:v05FDp262F* + ID_MODEL_FROM_DATABASE=HammerHead Fx + +usb:v05FDpDAAE* + ID_MODEL_FROM_DATABASE=Game Shark + +usb:v05FDpDBAE* + ID_MODEL_FROM_DATABASE=Datel XBoxMC + +usb:v05FE* + ID_VENDOR_FROM_DATABASE=Chic Technology Corp. + +usb:v05FEp0001* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v05FEp0003* + ID_MODEL_FROM_DATABASE=Cypress USB Mouse + +usb:v05FEp0005* + ID_MODEL_FROM_DATABASE=Viewmaster 4D Browser Mouse + +usb:v05FEp0007* + ID_MODEL_FROM_DATABASE=Twinhead Mouse + +usb:v05FEp0009* + ID_MODEL_FROM_DATABASE=Inland Pro 4500/5000 Mouse + +usb:v05FEp0011* + ID_MODEL_FROM_DATABASE=Browser Mouse + +usb:v05FEp0014* + ID_MODEL_FROM_DATABASE=Gamepad + +usb:v05FEp1010* + ID_MODEL_FROM_DATABASE=Optical Wireless + +usb:v05FEp2001* + ID_MODEL_FROM_DATABASE=Microsoft Wireless Receiver 700 + +usb:v05FF* + ID_VENDOR_FROM_DATABASE=LeCroy Corp. + +usb:v0600* + ID_VENDOR_FROM_DATABASE=Barco Display Systems + +usb:v0601* + ID_VENDOR_FROM_DATABASE=Jazz Hipster Corp. + +usb:v0601p0003* + ID_MODEL_FROM_DATABASE=Internet Security Co., Ltd. SecureKey + +usb:v0602* + ID_VENDOR_FROM_DATABASE=Vista Imaging, Inc. + +usb:v0602p1001* + ID_MODEL_FROM_DATABASE=ViCam Webcam + +usb:v0603* + ID_VENDOR_FROM_DATABASE=Novatek Microelectronics Corp. + +usb:v0603p00F1* + ID_MODEL_FROM_DATABASE=Keyboard (Labtec Ultra Flat Keyboard) + +usb:v0603p00F2* + ID_MODEL_FROM_DATABASE=Keyboard (Labtec Ultra Flat Keyboard) + +usb:v0603p6871* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v0603p8611* + ID_MODEL_FROM_DATABASE=NTK96550 based camera + +usb:v0604* + ID_VENDOR_FROM_DATABASE=Jean Co., Ltd + +usb:v0605* + ID_VENDOR_FROM_DATABASE=Anchor C&C Co., Ltd + +usb:v0606* + ID_VENDOR_FROM_DATABASE=Royal Information Electronics Co., Ltd + +usb:v0607* + ID_VENDOR_FROM_DATABASE=Bridge Information Co., Ltd + +usb:v0608* + ID_VENDOR_FROM_DATABASE=Genrad Ads + +usb:v0609* + ID_VENDOR_FROM_DATABASE=SMK Manufacturing, Inc. + +usb:v0609p031D* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v0609p0322* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v0609p0334* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v0609pFF12* + ID_MODEL_FROM_DATABASE=SMK Bluetooth Device + +usb:v060A* + ID_VENDOR_FROM_DATABASE=Worthington Data Solutions, Inc. + +usb:v060B* + ID_VENDOR_FROM_DATABASE=Solid Year + +usb:v060Bp0001* + ID_MODEL_FROM_DATABASE=MacAlly Keyboard + +usb:v060Bp0230* + ID_MODEL_FROM_DATABASE=KSK-8003 UX Keyboard + +usb:v060Bp0540* + ID_MODEL_FROM_DATABASE=DeltaCo TB-106U Keyboard + +usb:v060Bp1006* + ID_MODEL_FROM_DATABASE=Japanese Keyboard - 260U + +usb:v060Bp2101* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v060Bp2231* + ID_MODEL_FROM_DATABASE=KSK-6001 UELX Keyboard + +usb:v060Bp2270* + ID_MODEL_FROM_DATABASE=Gigabyte K8100 Aivia Gaming Keyboard + +usb:v060Bp5253* + ID_MODEL_FROM_DATABASE=Thermaltake MEKA G-Unit Gaming Keyboard + +usb:v060Bp5811* + ID_MODEL_FROM_DATABASE=ACK-571U Wireless Keyboard + +usb:v060Bp5903* + ID_MODEL_FROM_DATABASE=Japanese Keyboard - 595U + +usb:v060Bp6001* + ID_MODEL_FROM_DATABASE=SolidTek USB 2p HUB + +usb:v060Bp6002* + ID_MODEL_FROM_DATABASE=SolidTek USB Keyboard + +usb:v060Bp6003* + ID_MODEL_FROM_DATABASE=Japanese Keyboard - 600HM + +usb:v060Bp6231* + ID_MODEL_FROM_DATABASE=Thermaltake eSPORTS Meka Keyboard + +usb:v060Bp8007* + ID_MODEL_FROM_DATABASE=P-W1G1F12 VER:1 [Macally MegaCam] + +usb:v060BpA001* + ID_MODEL_FROM_DATABASE=Maxwell Compact Pc PM3 + +usb:v060C* + ID_VENDOR_FROM_DATABASE=EEH Datalink GmbH + +usb:v060D* + ID_VENDOR_FROM_DATABASE=Auctor Corp. + +usb:v060E* + ID_VENDOR_FROM_DATABASE=Transmonde Technologies, Inc. + +usb:v060F* + ID_VENDOR_FROM_DATABASE=Joinsoon Electronics Mfg. Co., Ltd + +usb:v0610* + ID_VENDOR_FROM_DATABASE=Costar Electronics, Inc. + +usb:v0611* + ID_VENDOR_FROM_DATABASE=Totoku Electric Co., Ltd + +usb:v0613* + ID_VENDOR_FROM_DATABASE=TransAct Technologies, Inc. + +usb:v0614* + ID_VENDOR_FROM_DATABASE=Bio-Rad Laboratories + +usb:v0615* + ID_VENDOR_FROM_DATABASE=Quabbin Wire & Cable Co., Inc. + +usb:v0616* + ID_VENDOR_FROM_DATABASE=Future Techno Designs PVT, Ltd + +usb:v0617* + ID_VENDOR_FROM_DATABASE=Swiss Federal Insitute of Technology + +usb:v0617p000A* + ID_MODEL_FROM_DATABASE=Thymio-II + +usb:v0617p000C* + ID_MODEL_FROM_DATABASE=Thymio-II Wireless + +usb:v0618* + ID_VENDOR_FROM_DATABASE=MacAlly + +usb:v0618p0101* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v0619* + ID_VENDOR_FROM_DATABASE=Seiko Instruments, Inc. + +usb:v0619p0101* + ID_MODEL_FROM_DATABASE=SLP-100 Driver + +usb:v0619p0102* + ID_MODEL_FROM_DATABASE=SLP-200 Driver + +usb:v0619p0103* + ID_MODEL_FROM_DATABASE=SLP-100N Driver + +usb:v0619p0104* + ID_MODEL_FROM_DATABASE=SLP-200N Driver + +usb:v0619p0105* + ID_MODEL_FROM_DATABASE=SLP-240 Driver + +usb:v0619p0501* + ID_MODEL_FROM_DATABASE=SLP-440 Driver + +usb:v0619p0502* + ID_MODEL_FROM_DATABASE=SLP-450 Driver + +usb:v061A* + ID_VENDOR_FROM_DATABASE=Veridicom International, Inc. + +usb:v061Ap0110* + ID_MODEL_FROM_DATABASE=5thSense Fingerprint Sensor + +usb:v061Ap0200* + ID_MODEL_FROM_DATABASE=FPS200 Fingerprint Sensor + +usb:v061Ap8200* + ID_MODEL_FROM_DATABASE=VKI-A Fingerprint Sensor/Flash Storage (dumb) + +usb:v061Ap9200* + ID_MODEL_FROM_DATABASE=VKI-B Fingerprint Sensor/Flash Storage (smart) + +usb:v061B* + ID_VENDOR_FROM_DATABASE=Promptus Communications, Inc. + +usb:v061C* + ID_VENDOR_FROM_DATABASE=Act Labs, Ltd + +usb:v061D* + ID_VENDOR_FROM_DATABASE=Quatech, Inc. + +usb:v061DpC020* + ID_MODEL_FROM_DATABASE=SSU-100 + +usb:v061E* + ID_VENDOR_FROM_DATABASE=Nissei Electric Co. + +usb:v061Ep0001* + ID_MODEL_FROM_DATABASE=nissei 128DE-USB - + +usb:v061Ep0010* + ID_MODEL_FROM_DATABASE=nissei 128DE-PNA - + +usb:v0620* + ID_VENDOR_FROM_DATABASE=Alaris, Inc. + +usb:v0620p0004* + ID_MODEL_FROM_DATABASE=QuickVideo weeCam + +usb:v0620p0007* + ID_MODEL_FROM_DATABASE=QuickVideo weeCam + +usb:v0620p000A* + ID_MODEL_FROM_DATABASE=QuickVideo weeCam + +usb:v0620p000B* + ID_MODEL_FROM_DATABASE=QuickVideo weeCam + +usb:v0621* + ID_VENDOR_FROM_DATABASE=ODU-Steckverbindungssysteme GmbH & Co. KG + +usb:v0622* + ID_VENDOR_FROM_DATABASE=Iotech, Inc. + +usb:v0623* + ID_VENDOR_FROM_DATABASE=Littelfuse, Inc. + +usb:v0624* + ID_VENDOR_FROM_DATABASE=Avocent Corp. + +usb:v0624p0248* + ID_MODEL_FROM_DATABASE=Virtual Hub + +usb:v0624p0249* + ID_MODEL_FROM_DATABASE=Virtual Keyboard/Mouse + +usb:v0624p0251* + ID_MODEL_FROM_DATABASE=Virtual Mass Storage + +usb:v0624p0294* + ID_MODEL_FROM_DATABASE=Dell 03R874 KVM dongle + +usb:v0624p0402* + ID_MODEL_FROM_DATABASE=Cisco Virtual Keyboard and Mouse + +usb:v0624p0403* + ID_MODEL_FROM_DATABASE=Cisco Virtual Mass Storage + +usb:v0625* + ID_VENDOR_FROM_DATABASE=TiMedia Technology Co., Ltd + +usb:v0626* + ID_VENDOR_FROM_DATABASE=Nippon Systems Development Co., Ltd + +usb:v0627* + ID_VENDOR_FROM_DATABASE=Adomax Technology Co., Ltd + +usb:v0628* + ID_VENDOR_FROM_DATABASE=Tasking Software, Inc. + +usb:v0629* + ID_VENDOR_FROM_DATABASE=Zida Technologies, Ltd + +usb:v062A* + ID_VENDOR_FROM_DATABASE=MosArt Semiconductor Corp. + +usb:v062Ap0000* + ID_MODEL_FROM_DATABASE=Optical mouse + +usb:v062Ap0001* + ID_MODEL_FROM_DATABASE=Notebook Optical Mouse + +usb:v062Ap0102* + ID_MODEL_FROM_DATABASE=Wireless Keyboard/Mouse Combo [MK1152WC] + +usb:v062Ap0201* + ID_MODEL_FROM_DATABASE=Defender Office Keyboard (K7310) S Zodiak KM-9010 + +usb:v062Ap0252* + ID_MODEL_FROM_DATABASE=Emerge Uni-retractable Laser Mouse + +usb:v062Ap2410* + ID_MODEL_FROM_DATABASE=Wireless PS3 gamepad + +usb:v062Ap3286* + ID_MODEL_FROM_DATABASE=Nano Receiver [Sandstrom Laser Mouse SMWLL11] + +usb:v062Ap4101* + ID_MODEL_FROM_DATABASE=Wireless Keyboard/Mouse + +usb:v062Ap6301* + ID_MODEL_FROM_DATABASE=Trust Wireless Optical Mouse MI-4150K + +usb:v062Ap9003* + ID_MODEL_FROM_DATABASE=VoIP Conference Hub (A16GH) + +usb:v062Ap9004* + ID_MODEL_FROM_DATABASE=USR9602 USB Internet Mini Phone + +usb:v062B* + ID_VENDOR_FROM_DATABASE=Greatlink Electronics Taiwan, Ltd + +usb:v062C* + ID_VENDOR_FROM_DATABASE=Institute for Information Industry + +usb:v062D* + ID_VENDOR_FROM_DATABASE=Taiwan Tai-Hao Enterprises Co., Ltd + +usb:v062E* + ID_VENDOR_FROM_DATABASE=Mainsuper Enterprises Co., Ltd + +usb:v062F* + ID_VENDOR_FROM_DATABASE=Sin Sheng Terminal & Machine, Inc. + +usb:v0631* + ID_VENDOR_FROM_DATABASE=JUJO Electronics Corp. + +usb:v0633* + ID_VENDOR_FROM_DATABASE=Cyrix Corp. + +usb:v0634* + ID_VENDOR_FROM_DATABASE=Micron Technology, Inc. + +usb:v0634p0655* + ID_MODEL_FROM_DATABASE=Embedded Mass Storage Drive [RealSSD] + +usb:v0635* + ID_VENDOR_FROM_DATABASE=Methode Electronics, Inc. + +usb:v0636* + ID_VENDOR_FROM_DATABASE=Sierra Imaging, Inc. + +usb:v0636p0003* + ID_MODEL_FROM_DATABASE=Vivicam 35Xx + +usb:v0638* + ID_VENDOR_FROM_DATABASE=Avision, Inc. + +usb:v0638p0268* + ID_MODEL_FROM_DATABASE=iVina 1200U Scanner + +usb:v0638p026A* + ID_MODEL_FROM_DATABASE=Minolta Dimage Scan Dual II AF-2820U (2886) + +usb:v0638p0A10* + ID_MODEL_FROM_DATABASE=iVina FB1600/UMAX Astra 4500 + +usb:v0638p0A13* + ID_MODEL_FROM_DATABASE=AV600U + +usb:v0638p0A15* + ID_MODEL_FROM_DATABASE=Konica Minolta SC-110 + +usb:v0638p0A16* + ID_MODEL_FROM_DATABASE=Konica Minolta SC-215 + +usb:v0638p0A30* + ID_MODEL_FROM_DATABASE=UMAX Astra 6700 Scanner + +usb:v0638p0A41* + ID_MODEL_FROM_DATABASE=Avision AM3000/MF3000 Series + +usb:v0638p0F01* + ID_MODEL_FROM_DATABASE=fi-4010CU + +usb:v0638p4004* + ID_MODEL_FROM_DATABASE=Minolta Dimage Scan Elite II AF-2920 (2888) + +usb:v0639* + ID_VENDOR_FROM_DATABASE=Chrontel, Inc. + +usb:v063A* + ID_VENDOR_FROM_DATABASE=Techwin Corp. + +usb:v063B* + ID_VENDOR_FROM_DATABASE=Taugagreining HF + +usb:v063C* + ID_VENDOR_FROM_DATABASE=Yamaichi Electronics Co., Ltd (Sakura) + +usb:v063D* + ID_VENDOR_FROM_DATABASE=Fong Kai Industrial Co., Ltd + +usb:v063E* + ID_VENDOR_FROM_DATABASE=RealMedia Technology, Inc. + +usb:v063F* + ID_VENDOR_FROM_DATABASE=New Technology Cable, Ltd + +usb:v0640* + ID_VENDOR_FROM_DATABASE=Hitex Development Tools + +usb:v0640p0026* + ID_MODEL_FROM_DATABASE=LPC-Stick + +usb:v0641* + ID_VENDOR_FROM_DATABASE=Woods Industries, Inc. + +usb:v0642* + ID_VENDOR_FROM_DATABASE=VIA Medical Corp. + +usb:v0644* + ID_VENDOR_FROM_DATABASE=TEAC Corp. + +usb:v0644p0000* + ID_MODEL_FROM_DATABASE=Floppy + +usb:v0644p0200* + ID_MODEL_FROM_DATABASE=All-In-One Multi-Card Reader CA200/B/S + +usb:v0644p1000* + ID_MODEL_FROM_DATABASE=CD-ROM Drive + +usb:v0644p800D* + ID_MODEL_FROM_DATABASE=TASCAM Portastudio DP-01FX + +usb:v0644p800E* + ID_MODEL_FROM_DATABASE=TASCAM US-122L + +usb:v0644p801D* + ID_MODEL_FROM_DATABASE=TASCAM DR-100 + +usb:v0644p8021* + ID_MODEL_FROM_DATABASE=TASCAM US-122mkII + +usb:v0644pD001* + ID_MODEL_FROM_DATABASE=CD-R/RW Unit + +usb:v0644pD002* + ID_MODEL_FROM_DATABASE=CD-R/RW Unit + +usb:v0644pD010* + ID_MODEL_FROM_DATABASE=CD-RW/DVD Unit + +usb:v0645* + ID_VENDOR_FROM_DATABASE=Who? Vision Systems, Inc. + +usb:v0646* + ID_VENDOR_FROM_DATABASE=UMAX + +usb:v0647* + ID_VENDOR_FROM_DATABASE=Acton Research Corp. + +usb:v0647p0100* + ID_MODEL_FROM_DATABASE=ARC SpectraPro UV/VIS/IR Monochromator/Spectrograph + +usb:v0647p0101* + ID_MODEL_FROM_DATABASE=ARC AM-VM Mono Airpath/Vacuum Monochromator/Spectrograph + +usb:v0647p0102* + ID_MODEL_FROM_DATABASE=ARC Inspectrum Mono + +usb:v0647p0103* + ID_MODEL_FROM_DATABASE=ARC Filterwheel + +usb:v0647p03E9* + ID_MODEL_FROM_DATABASE=Inspectrum 128x1024 F VIS Spectrograph + +usb:v0647p03EA* + ID_MODEL_FROM_DATABASE=Inspectrum 256x1024 F VIS Spectrograph + +usb:v0647p03EB* + ID_MODEL_FROM_DATABASE=Inspectrum 128x1024 B VIS Spectrograph + +usb:v0647p03EC* + ID_MODEL_FROM_DATABASE=Inspectrum 256x1024 B VIS Spectrograph + +usb:v0648* + ID_VENDOR_FROM_DATABASE=Inside Out Networks + +usb:v0649* + ID_VENDOR_FROM_DATABASE=Weli Science Co., Ltd + +usb:v064B* + ID_VENDOR_FROM_DATABASE=Analog Devices, Inc. (White Mountain DSP) + +usb:v064Bp0165* + ID_MODEL_FROM_DATABASE=Blackfin 535 [ADZS HPUSB ICE] + +usb:v064C* + ID_VENDOR_FROM_DATABASE=Ji-Haw Industrial Co., Ltd + +usb:v064D* + ID_VENDOR_FROM_DATABASE=TriTech Microelectronics, Ltd + +usb:v064E* + ID_VENDOR_FROM_DATABASE=Suyin Corp. + +usb:v064Ep2100* + ID_MODEL_FROM_DATABASE=Sony Visual Communication Camera + +usb:v064Ep9700* + ID_MODEL_FROM_DATABASE=Asus Integrated Webcam + +usb:v064EpA100* + ID_MODEL_FROM_DATABASE=Acer OrbiCam + +usb:v064EpA101* + ID_MODEL_FROM_DATABASE=Acer CrystalEye Webcam + +usb:v064EpA102* + ID_MODEL_FROM_DATABASE=Acer/Lenovo Webcam [CN0316] + +usb:v064EpA103* + ID_MODEL_FROM_DATABASE=Acer/HP Integrated Webcam [CN0314] + +usb:v064EpA110* + ID_MODEL_FROM_DATABASE=HP Webcam + +usb:v064EpA114* + ID_MODEL_FROM_DATABASE=Lemote Webcam + +usb:v064EpA116* + ID_MODEL_FROM_DATABASE=UVC 1.3MPixel WebCam + +usb:v064EpA136* + ID_MODEL_FROM_DATABASE=Asus Integrated Webcam [CN031B] + +usb:v064EpA219* + ID_MODEL_FROM_DATABASE=1.3M WebCam (notebook emachines E730, Acer sub-brand) + +usb:v064EpC107* + ID_MODEL_FROM_DATABASE=HP webcam [dv6-1190en] + +usb:v064EpC335* + ID_MODEL_FROM_DATABASE=HP TrueVision HD + +usb:v064EpD101* + ID_MODEL_FROM_DATABASE=Acer CrystalEye Webcam + +usb:v064EpD213* + ID_MODEL_FROM_DATABASE=UVC HD Webcam + +usb:v064EpD217* + ID_MODEL_FROM_DATABASE=HP TrueVision HD + +usb:v064EpE201* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam + +usb:v064EpE203* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam + +usb:v064EpE258* + ID_MODEL_FROM_DATABASE=HP TrueVision HD Integrated Webcam + +usb:v064EpE263* + ID_MODEL_FROM_DATABASE=HP TrueVision HD Integrated Webcam + +usb:v064EpF102* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam [R5U877] + +usb:v064EpF103* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam [R5U877] + +usb:v064EpF209* + ID_MODEL_FROM_DATABASE=HP Webcam + +usb:v064EpF300* + ID_MODEL_FROM_DATABASE=UVC 0.3M Webcam + +usb:v064F* + ID_VENDOR_FROM_DATABASE=WIBU-Systems AG + +usb:v064Fp03E9* + ID_MODEL_FROM_DATABASE=CmStick (MSD, article no. 1001-xx-xxx) + +usb:v064Fp03F2* + ID_MODEL_FROM_DATABASE=CmStick/M (MSD, article no. 1010-xx-xxx) + +usb:v064Fp03F3* + ID_MODEL_FROM_DATABASE=CmStick/M (MSD, article no. 1011-xx-xxx) + +usb:v064Fp0BD7* + ID_MODEL_FROM_DATABASE=Wibu-Box/U (article no. 3031-xx-xxx) + +usb:v064Fp0BD8* + ID_MODEL_FROM_DATABASE=Wibu-Box/RU (article no. 3032-xx-xxx) + +usb:v064Fp2AF9* + ID_MODEL_FROM_DATABASE=CmStick (HID, article no. 1001-xx-xxx) + +usb:v064Fp2B03* + ID_MODEL_FROM_DATABASE=CmStick/M (HID, article no. 1011-xx-xxx) + +usb:v064Fp5213* + ID_MODEL_FROM_DATABASE=CmStick/M (COMPOSITE, article no. 1011-xx-xxx) + +usb:v0650* + ID_VENDOR_FROM_DATABASE=Dynapro Systems + +usb:v0651* + ID_VENDOR_FROM_DATABASE=Likom Technology Sdn. Bhd. + +usb:v0652* + ID_VENDOR_FROM_DATABASE=Stargate Solutions, Inc. + +usb:v0653* + ID_VENDOR_FROM_DATABASE=CNF, Inc. + +usb:v0654* + ID_VENDOR_FROM_DATABASE=Granite Microsystems, Inc. + +usb:v0654p0005* + ID_MODEL_FROM_DATABASE=Device Bay Controller + +usb:v0654p0006* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0654p0007* + ID_MODEL_FROM_DATABASE=Device Bay Controller + +usb:v0654p0016* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0655* + ID_VENDOR_FROM_DATABASE=Space Shuttle Hi-Tech Co., Ltd + +usb:v0656* + ID_VENDOR_FROM_DATABASE=Glory Mark Electronic, Ltd + +usb:v0657* + ID_VENDOR_FROM_DATABASE=Tekcon Electronics Corp. + +usb:v0658* + ID_VENDOR_FROM_DATABASE=Sigma Designs, Inc. + +usb:v0658p0200* + ID_MODEL_FROM_DATABASE=Aeotec Z-Stick Gen5 (ZW090) - UZB + +usb:v0659* + ID_VENDOR_FROM_DATABASE=Aethra + +usb:v065A* + ID_VENDOR_FROM_DATABASE=Optoelectronics Co., Ltd + +usb:v065Ap0001* + ID_MODEL_FROM_DATABASE=Opticon OPR-2001 / NLV-1001 (keyboard mode) + +usb:v065Ap0009* + ID_MODEL_FROM_DATABASE=NLV-1001 (serial mode) / OPN-2001 [Opticon] + +usb:v065B* + ID_VENDOR_FROM_DATABASE=Tracewell Systems + +usb:v065E* + ID_VENDOR_FROM_DATABASE=Silicon Graphics + +usb:v065F* + ID_VENDOR_FROM_DATABASE=Good Way Technology Co., Ltd & GWC technology Inc. + +usb:v0660* + ID_VENDOR_FROM_DATABASE=TSAY-E (BVI) International, Inc. + +usb:v0661* + ID_VENDOR_FROM_DATABASE=Hamamatsu Photonics K.K. + +usb:v0662* + ID_VENDOR_FROM_DATABASE=Kansai Electric Co., Ltd + +usb:v0663* + ID_VENDOR_FROM_DATABASE=Topmax Electronic Co., Ltd + +usb:v0663p0103* + ID_MODEL_FROM_DATABASE=CobraPad + +usb:v0664* + ID_VENDOR_FROM_DATABASE=ET&T Technology Co., Ltd. + +usb:v0664p0301* + ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen + +usb:v0664p0302* + ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen + +usb:v0664p0303* + ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen + +usb:v0664p0304* + ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen + +usb:v0664p0305* + ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen + +usb:v0664p0306* + ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen + +usb:v0664p0307* + ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen + +usb:v0664p0309* + ID_MODEL_FROM_DATABASE=Groovy Technology Corp. GTouch Touch Screen + +usb:v0665* + ID_VENDOR_FROM_DATABASE=Cypress Semiconductor + +usb:v0665p5161* + ID_MODEL_FROM_DATABASE=USB to Serial + +usb:v0667* + ID_VENDOR_FROM_DATABASE=Aiwa Co., Ltd + +usb:v0667p0FA1* + ID_MODEL_FROM_DATABASE=TD-U8000 Tape Drive + +usb:v0668* + ID_VENDOR_FROM_DATABASE=WordWand + +usb:v0669* + ID_VENDOR_FROM_DATABASE=Oce' Printing Systems GmbH + +usb:v066A* + ID_VENDOR_FROM_DATABASE=Total Technologies, Ltd + +usb:v066B* + ID_VENDOR_FROM_DATABASE=Linksys, Inc. + +usb:v066Bp0105* + ID_MODEL_FROM_DATABASE=SCM eUSB SmartMedia Card Reader + +usb:v066Bp010A* + ID_MODEL_FROM_DATABASE=Melco MCR-U2 SmartMedia / CompactFlash Reader + +usb:v066Bp200C* + ID_MODEL_FROM_DATABASE=USB10TX + +usb:v066Bp2202* + ID_MODEL_FROM_DATABASE=USB10TX Ethernet [pegasus] + +usb:v066Bp2203* + ID_MODEL_FROM_DATABASE=USB100TX Ethernet [pegasus] + +usb:v066Bp2204* + ID_MODEL_FROM_DATABASE=USB100TX HomePNA Ethernet [pegasus] + +usb:v066Bp2206* + ID_MODEL_FROM_DATABASE=USB Ethernet [pegasus] + +usb:v066Bp2207* + ID_MODEL_FROM_DATABASE=HomeLink Phoneline 10M Network Adapter + +usb:v066Bp2211* + ID_MODEL_FROM_DATABASE=WUSB11 802.11b Adapter + +usb:v066Bp2212* + ID_MODEL_FROM_DATABASE=WUSB11v2.5 802.11b Adapter + +usb:v066Bp2213* + ID_MODEL_FROM_DATABASE=WUSB12v1.1 802.11b Adapter + +usb:v066Bp2219* + ID_MODEL_FROM_DATABASE=Instant Wireless Network Adapter + +usb:v066Bp400B* + ID_MODEL_FROM_DATABASE=USB10TX + +usb:v066D* + ID_VENDOR_FROM_DATABASE=Entrega, Inc. + +usb:v066E* + ID_VENDOR_FROM_DATABASE=Acer Semiconductor America, Inc. + +usb:v066F* + ID_VENDOR_FROM_DATABASE=SigmaTel, Inc. + +usb:v066Fp003B* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp003E* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp003F* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp0040* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp0041* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp0042* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp0043* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp004B* + ID_MODEL_FROM_DATABASE=A-Max PA11 MP3 Player + +usb:v066Fp3400* + ID_MODEL_FROM_DATABASE=STMP3400 D-Major MP3 Player + +usb:v066Fp3410* + ID_MODEL_FROM_DATABASE=STMP3410 D-Major MP3 Player + +usb:v066Fp3500* + ID_MODEL_FROM_DATABASE=Player Recovery Device + +usb:v066Fp3780* + ID_MODEL_FROM_DATABASE=STMP3780/i.MX23 SystemOnChip in RecoveryMode + +usb:v066Fp4200* + ID_MODEL_FROM_DATABASE=STIr4200 IrDA Bridge + +usb:v066Fp4210* + ID_MODEL_FROM_DATABASE=STIr4210 IrDA Bridge + +usb:v066Fp8000* + ID_MODEL_FROM_DATABASE=MSCN MP3 Player + +usb:v066Fp8001* + ID_MODEL_FROM_DATABASE=SigmaTel MSCN Audio Player + +usb:v066Fp8004* + ID_MODEL_FROM_DATABASE=MSCNMMC MP3 Player + +usb:v066Fp8008* + ID_MODEL_FROM_DATABASE=i-Bead 100 MP3 Player + +usb:v066Fp8020* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8034* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8036* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8038* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8056* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8060* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8066* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp807E* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8092* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8096* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp809A* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp80AA* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp80AC* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp80B8* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp80BA* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp80BC* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp80BF* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp80C5* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp80C8* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp80CA* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp80CC* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8104* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8106* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8108* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp810A* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp810C* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8122* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8124* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8126* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8128* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8134* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8136* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8138* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp813A* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp813E* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8140* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8142* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8144* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8146* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8148* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp814C* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8201* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8202* + ID_MODEL_FROM_DATABASE=Jens of Sweden / I-BEAD 150M/150H MP3 player + +usb:v066Fp8203* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8204* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8205* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8206* + ID_MODEL_FROM_DATABASE=Digital MP3 Music Player + +usb:v066Fp8207* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8208* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8209* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp820A* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp820B* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp820C* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp820D* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp820E* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp820F* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8210* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8211* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8212* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8213* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8214* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8215* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8216* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8217* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8218* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8219* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp821A* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp821B* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp821C* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp821D* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp821E* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp821F* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8220* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8221* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8222* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8223* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8224* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8225* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8226* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8227* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8228* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8229* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8230* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp829C* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp82E0* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp8320* + ID_MODEL_FROM_DATABASE=TrekStor i.Beat fun + +usb:v066Fp835D* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp9000* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp9001* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v066Fp9002* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0670* + ID_VENDOR_FROM_DATABASE=Sequel Imaging + +usb:v0670p0001* + ID_MODEL_FROM_DATABASE=Calibrator + +usb:v0670p0005* + ID_MODEL_FROM_DATABASE=Enable Cable + +usb:v0672* + ID_VENDOR_FROM_DATABASE=Labtec, Inc. + +usb:v0672p1041* + ID_MODEL_FROM_DATABASE=LCS1040 Speaker System + +usb:v0672p5000* + ID_MODEL_FROM_DATABASE=SpaceBall 4000 FLX + +usb:v0673* + ID_VENDOR_FROM_DATABASE=HCL + +usb:v0673p5000* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0674* + ID_VENDOR_FROM_DATABASE=Key Mouse Electronic Enterprise Co., Ltd + +usb:v0675* + ID_VENDOR_FROM_DATABASE=DrayTek Corp. + +usb:v0675p0110* + ID_MODEL_FROM_DATABASE=Vigor 128 ISDN TA + +usb:v0675p0530* + ID_MODEL_FROM_DATABASE=Vigor530 IEEE 802.11G Adapter (ISL3880+NET2280) + +usb:v0675p0550* + ID_MODEL_FROM_DATABASE=Vigor550 + +usb:v0675p1688* + ID_MODEL_FROM_DATABASE=miniVigor 128 ISDN TA [HFC-S] + +usb:v0675p6694* + ID_MODEL_FROM_DATABASE=miniVigor 128 ISDN TA + +usb:v0676* + ID_VENDOR_FROM_DATABASE=Teles AG + +usb:v0677* + ID_VENDOR_FROM_DATABASE=Aiwa Co., Ltd + +usb:v0677p07D5* + ID_MODEL_FROM_DATABASE=TM-ED1285(USB) + +usb:v0677p0FA1* + ID_MODEL_FROM_DATABASE=TD-U8000 Tape Drive + +usb:v0678* + ID_VENDOR_FROM_DATABASE=ACard Technology Corp. + +usb:v067B* + ID_VENDOR_FROM_DATABASE=Prolific Technology, Inc. + +usb:v067Bp0000* + ID_MODEL_FROM_DATABASE=PL2301 USB-USB Bridge + +usb:v067Bp0001* + ID_MODEL_FROM_DATABASE=PL2302 USB-USB Bridge + +usb:v067Bp0307* + ID_MODEL_FROM_DATABASE=Motorola Serial Adapter + +usb:v067Bp04BB* + ID_MODEL_FROM_DATABASE=PL2303 Serial (IODATA USB-RSAQ2) + +usb:v067Bp0600* + ID_MODEL_FROM_DATABASE=IDE Bridge + +usb:v067Bp0610* + ID_MODEL_FROM_DATABASE=Onext EG210U MODEM + +usb:v067Bp0611* + ID_MODEL_FROM_DATABASE=AlDiga AL-11U Quad-band GSM/GPRS/EDGE modem + +usb:v067Bp2303* + ID_MODEL_FROM_DATABASE=PL2303 Serial Port + +usb:v067Bp2305* + ID_MODEL_FROM_DATABASE=PL2305 Parallel Port + +usb:v067Bp2306* + ID_MODEL_FROM_DATABASE=Raylink Bridge Controller + +usb:v067Bp2307* + ID_MODEL_FROM_DATABASE=PL2307 USB-ATAPI4 Bridge + +usb:v067Bp2313* + ID_MODEL_FROM_DATABASE=FITEL PHS U Cable Adaptor + +usb:v067Bp2315* + ID_MODEL_FROM_DATABASE=Flash Disk Embedded Hub + +usb:v067Bp2316* + ID_MODEL_FROM_DATABASE=Flash Disk Security Device + +usb:v067Bp2317* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v067Bp2501* + ID_MODEL_FROM_DATABASE=PL2501 USB-USB Bridge (USB 2.0) + +usb:v067Bp2506* + ID_MODEL_FROM_DATABASE=Kaser 8gB micro hard drive + +usb:v067Bp2507* + ID_MODEL_FROM_DATABASE=PL2507 Hi-speed USB to IDE bridge controller + +usb:v067Bp2515* + ID_MODEL_FROM_DATABASE=Flash Disk Embedded Hub + +usb:v067Bp2517* + ID_MODEL_FROM_DATABASE=Flash Disk Mass Storage Device + +usb:v067Bp2528* + ID_MODEL_FROM_DATABASE=Storage device (8gB thumb drive) + +usb:v067Bp25A1* + ID_MODEL_FROM_DATABASE=PL25A1 Host-Host Bridge + +usb:v067Bp2773* + ID_MODEL_FROM_DATABASE=PL2773 SATAII bridge controller + +usb:v067Bp3400* + ID_MODEL_FROM_DATABASE=Hi-Speed Flash Disk with TruePrint AES3400 + +usb:v067Bp3500* + ID_MODEL_FROM_DATABASE=Hi-Speed Flash Disk with TruePrint AES3500 + +usb:v067Bp3507* + ID_MODEL_FROM_DATABASE=PL3507 ATAPI6 Bridge + +usb:v067BpAAA0* + ID_MODEL_FROM_DATABASE=Prolific Pharos + +usb:v067BpAAA2* + ID_MODEL_FROM_DATABASE=PL2303 Serial Adapter (IODATA USB-RSAQ3) + +usb:v067BpAAA3* + ID_MODEL_FROM_DATABASE=PL2303x Serial Adapter + +usb:v067C* + ID_VENDOR_FROM_DATABASE=Efficient Networks, Inc. + +usb:v067Cp1001* + ID_MODEL_FROM_DATABASE=Siemens SpeedStream 100MBps Ethernet + +usb:v067Cp1022* + ID_MODEL_FROM_DATABASE=Siemens SpeedStream 1022 802.11b Adapter + +usb:v067Cp1023* + ID_MODEL_FROM_DATABASE=SpeedStream Wireless + +usb:v067Cp4020* + ID_MODEL_FROM_DATABASE=SpeedStream 4020 ATM/ADSL Installer + +usb:v067Cp4031* + ID_MODEL_FROM_DATABASE=Efficient ADSL Modem + +usb:v067Cp4032* + ID_MODEL_FROM_DATABASE=SpeedStream 4031 ATM/ADSL Installer + +usb:v067Cp4033* + ID_MODEL_FROM_DATABASE=SpeedStream 4031 ATM/ADSL Installer + +usb:v067Cp4060* + ID_MODEL_FROM_DATABASE=Alcatel Speedstream 4060 ADSL Modem + +usb:v067Cp4062* + ID_MODEL_FROM_DATABASE=Efficient Networks 4060 Loader + +usb:v067Cp5667* + ID_MODEL_FROM_DATABASE=Efficient Networks Virtual Bus for ADSL Modem + +usb:v067CpC031* + ID_MODEL_FROM_DATABASE=SpeedStream 4031 ATM/ADSL Installer + +usb:v067CpC032* + ID_MODEL_FROM_DATABASE=SpeedStream 4031 ATM/ADSL Installer + +usb:v067CpC033* + ID_MODEL_FROM_DATABASE=SpeedStream 4031 ATM/ADSL Installer + +usb:v067CpC060* + ID_MODEL_FROM_DATABASE=SpeedStream 4060 Miniport ATM/ADSL Adapter + +usb:v067CpD667* + ID_MODEL_FROM_DATABASE=Efficient Networks Virtual Bus for ADSL Modem + +usb:v067CpE240* + ID_MODEL_FROM_DATABASE=Speedstream Ethernet Adapter E240 + +usb:v067CpE540* + ID_MODEL_FROM_DATABASE=Speedstream Ethernet Adapter E240 + +usb:v067D* + ID_VENDOR_FROM_DATABASE=Hohner Corp. + +usb:v067E* + ID_VENDOR_FROM_DATABASE=Intermec Technologies Corp. + +usb:v067Ep0801* + ID_MODEL_FROM_DATABASE=HID Keyboard, Barcode scanner + +usb:v067Ep0803* + ID_MODEL_FROM_DATABASE=VCP, Barcode scanner + +usb:v067Ep0805* + ID_MODEL_FROM_DATABASE=VCP + UVC, Barcode scanner + +usb:v067Ep1001* + ID_MODEL_FROM_DATABASE=Mobile Computer + +usb:v067F* + ID_VENDOR_FROM_DATABASE=Virata, Ltd + +usb:v067Fp4552* + ID_MODEL_FROM_DATABASE=DSL-200 ADSL Modem + +usb:v067Fp6542* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v067Fp6549* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v067Fp7541* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v0680* + ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corp., CPP Div. (Avance Logic) + +usb:v0680p0002* + ID_MODEL_FROM_DATABASE=Arowana Optical Wheel Mouse MSOP-01 + +usb:v0681* + ID_VENDOR_FROM_DATABASE=Siemens Information and Communication Products + +usb:v0681p0001* + ID_MODEL_FROM_DATABASE=Dect Base + +usb:v0681p0002* + ID_MODEL_FROM_DATABASE=Gigaset 3075 Passive ISDN + +usb:v0681p0005* + ID_MODEL_FROM_DATABASE=ID-Mouse with Fingerprint Reader + +usb:v0681p0012* + ID_MODEL_FROM_DATABASE=I-Gate 802.11b Adapter + +usb:v0681p001B* + ID_MODEL_FROM_DATABASE=WLL013 + +usb:v0681p001D* + ID_MODEL_FROM_DATABASE=Hipath 1000 + +usb:v0681p0022* + ID_MODEL_FROM_DATABASE=Gigaset SX353 ISDN + +usb:v0681p0026* + ID_MODEL_FROM_DATABASE=DECT Data - Gigaset M34 + +usb:v0681p002B* + ID_MODEL_FROM_DATABASE=A-100-I ADSL Modem + +usb:v0681p002E* + ID_MODEL_FROM_DATABASE=ADSL Router_S-141 + +usb:v0681p0034* + ID_MODEL_FROM_DATABASE=GSM module MC35/ES75 USB Modem + +usb:v0681p3C06* + ID_MODEL_FROM_DATABASE=54g USB Network Adapter + +usb:v0682* + ID_VENDOR_FROM_DATABASE=Victor Company of Japan, Ltd + +usb:v0684* + ID_VENDOR_FROM_DATABASE=Actiontec Electronics, Inc. + +usb:v0685* + ID_VENDOR_FROM_DATABASE=ZD Incorporated + +usb:v0685p7000* + ID_MODEL_FROM_DATABASE=HSDPA Modem + +usb:v0686* + ID_VENDOR_FROM_DATABASE=Minolta Co., Ltd + +usb:v0686p2001* + ID_MODEL_FROM_DATABASE=PagePro 4110W + +usb:v0686p2004* + ID_MODEL_FROM_DATABASE=PagePro 1200W + +usb:v0686p2005* + ID_MODEL_FROM_DATABASE=Magicolor 2300 DL + +usb:v0686p3001* + ID_MODEL_FROM_DATABASE=PagePro 4100 + +usb:v0686p3005* + ID_MODEL_FROM_DATABASE=PagePro 1250E + +usb:v0686p3006* + ID_MODEL_FROM_DATABASE=PagePro 1250W + +usb:v0686p3009* + ID_MODEL_FROM_DATABASE=Magicolor 2300W + +usb:v0686p300B* + ID_MODEL_FROM_DATABASE=PagePro 1350W + +usb:v0686p300C* + ID_MODEL_FROM_DATABASE=PagePro 1300W + +usb:v0686p302E* + ID_MODEL_FROM_DATABASE=Develop D 1650iD PCL + +usb:v0686p3034* + ID_MODEL_FROM_DATABASE=Develop D 2050iD PCL + +usb:v0686p4001* + ID_MODEL_FROM_DATABASE=Dimage 2300 + +usb:v0686p4003* + ID_MODEL_FROM_DATABASE=Dimage 2330 Zoom Camera + +usb:v0686p4004* + ID_MODEL_FROM_DATABASE=Dimage Scan Elite II AF-2920 (2888) + +usb:v0686p4005* + ID_MODEL_FROM_DATABASE=Minolta DiMAGE E201 Mass Storage Device + +usb:v0686p4006* + ID_MODEL_FROM_DATABASE=Dimage 7 Camera + +usb:v0686p4007* + ID_MODEL_FROM_DATABASE=Dimage S304 Camera + +usb:v0686p4008* + ID_MODEL_FROM_DATABASE=Dimage 5 Camera + +usb:v0686p4009* + ID_MODEL_FROM_DATABASE=Dimage X Camera + +usb:v0686p400A* + ID_MODEL_FROM_DATABASE=Dimage S404 Camera + +usb:v0686p400B* + ID_MODEL_FROM_DATABASE=Dimage 7i Camera + +usb:v0686p400C* + ID_MODEL_FROM_DATABASE=Dimage F100 Camera + +usb:v0686p400D* + ID_MODEL_FROM_DATABASE=Dimage Scan Dual III AF-2840 (2889) + +usb:v0686p400E* + ID_MODEL_FROM_DATABASE=Dimage Scan Elite 5400 (2890) + +usb:v0686p400F* + ID_MODEL_FROM_DATABASE=Dimage 7Hi Camera + +usb:v0686p4010* + ID_MODEL_FROM_DATABASE=Dimage Xi Camera + +usb:v0686p4011* + ID_MODEL_FROM_DATABASE=Dimage F300 Camera + +usb:v0686p4012* + ID_MODEL_FROM_DATABASE=Dimage F200 Camera + +usb:v0686p4014* + ID_MODEL_FROM_DATABASE=Dimage S414 Camera + +usb:v0686p4015* + ID_MODEL_FROM_DATABASE=Dimage XT Camera [storage] + +usb:v0686p4016* + ID_MODEL_FROM_DATABASE=Dimage XT Camera [remote mode] + +usb:v0686p4017* + ID_MODEL_FROM_DATABASE=Dimage E223 + +usb:v0686p4018* + ID_MODEL_FROM_DATABASE=Dimage Z1 Camera + +usb:v0686p4019* + ID_MODEL_FROM_DATABASE=Dimage A1 Camera [remote mode] + +usb:v0686p401A* + ID_MODEL_FROM_DATABASE=Dimage A1 Camera [storage] + +usb:v0686p401C* + ID_MODEL_FROM_DATABASE=Dimage X20 Camera + +usb:v0686p401E* + ID_MODEL_FROM_DATABASE=Dimage E323 Camera + +usb:v068A* + ID_VENDOR_FROM_DATABASE=Pertech, Inc. + +usb:v068B* + ID_VENDOR_FROM_DATABASE=Potrans International, Inc. + +usb:v068E* + ID_VENDOR_FROM_DATABASE=CH Products, Inc. + +usb:v068Ep00D3* + ID_MODEL_FROM_DATABASE=OEM 3 axis 5 button joystick + +usb:v068Ep00E2* + ID_MODEL_FROM_DATABASE=HFX OEM Joystick + +usb:v068Ep00F0* + ID_MODEL_FROM_DATABASE=Multi-Function Panel + +usb:v068Ep00F1* + ID_MODEL_FROM_DATABASE=Pro Throttle + +usb:v068Ep00F2* + ID_MODEL_FROM_DATABASE=Flight Sim Pedals + +usb:v068Ep00F3* + ID_MODEL_FROM_DATABASE=Fighterstick + +usb:v068Ep00F4* + ID_MODEL_FROM_DATABASE=Combatstick + +usb:v068Ep00FA* + ID_MODEL_FROM_DATABASE=Ch Throttle Quadrant + +usb:v068Ep00FF* + ID_MODEL_FROM_DATABASE=Flight Sim Yoke + +usb:v068Ep0500* + ID_MODEL_FROM_DATABASE=GameStick 3D + +usb:v068Ep0501* + ID_MODEL_FROM_DATABASE=CH Pro Pedals + +usb:v068Ep0504* + ID_MODEL_FROM_DATABASE=F-16 Combat Stick + +usb:v0690* + ID_VENDOR_FROM_DATABASE=Golden Bridge Electech, Inc. + +usb:v0693* + ID_VENDOR_FROM_DATABASE=Hagiwara Sys-Com Co., Ltd + +usb:v0693p0002* + ID_MODEL_FROM_DATABASE=FlashGate SmartMedia Card Reader + +usb:v0693p0003* + ID_MODEL_FROM_DATABASE=FlashGate CompactFlash Card Reader + +usb:v0693p0005* + ID_MODEL_FROM_DATABASE=FlashGate + +usb:v0693p0006* + ID_MODEL_FROM_DATABASE=SM PCCard R/W and SPD + +usb:v0693p0007* + ID_MODEL_FROM_DATABASE=FlashGate ME (Authenticated) + +usb:v0693p000A* + ID_MODEL_FROM_DATABASE=SDCard/MMC Reader/Writer + +usb:v0694* + ID_VENDOR_FROM_DATABASE=Lego Group + +usb:v0694p0001* + ID_MODEL_FROM_DATABASE=Mindstorms Tower + +usb:v0694p0002* + ID_MODEL_FROM_DATABASE=Mindstorms NXT + +usb:v0694p0005* + ID_MODEL_FROM_DATABASE=Mindstorms EV3 + +usb:v0694p0006* + ID_MODEL_FROM_DATABASE=Mindstorms EV3 Firmware Update + +usb:v0698* + ID_VENDOR_FROM_DATABASE=Chuntex (CTX) + +usb:v0698p1786* + ID_MODEL_FROM_DATABASE=1300ex Monitor + +usb:v0698p2003* + ID_MODEL_FROM_DATABASE=CTX M730V built in Camera + +usb:v0698p9999* + ID_MODEL_FROM_DATABASE=VLxxxx Monitor+Hub + +usb:v0699* + ID_VENDOR_FROM_DATABASE=Tektronix, Inc. + +usb:v0699p0347* + ID_MODEL_FROM_DATABASE=AFG 3022B + +usb:v0699p036A* + ID_MODEL_FROM_DATABASE=TDS 2024B + +usb:v069A* + ID_VENDOR_FROM_DATABASE=Askey Computer Corp. + +usb:v069Ap0001* + ID_MODEL_FROM_DATABASE=VC010 Webcam [pwc] + +usb:v069Ap0303* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v069Ap0311* + ID_MODEL_FROM_DATABASE=ADSL Router Remote NDIS Device + +usb:v069Ap0318* + ID_MODEL_FROM_DATABASE=Remote NDIS Device + +usb:v069Ap0319* + ID_MODEL_FROM_DATABASE=220V Remote NDIS Device + +usb:v069Ap0320* + ID_MODEL_FROM_DATABASE=IEEE 802.11b Wireless LAN Card + +usb:v069Ap0321* + ID_MODEL_FROM_DATABASE=Dynalink WLL013 / Compex WLU11A 802.11b Adapter + +usb:v069Ap0402* + ID_MODEL_FROM_DATABASE=Scientific Atlanta WebSTAR 100 & 200 series Cable Modem + +usb:v069Ap0811* + ID_MODEL_FROM_DATABASE=BT Virtual Bus for Helium + +usb:v069Ap0821* + ID_MODEL_FROM_DATABASE=BT Voyager 1010 802.11b Adapter + +usb:v069Ap4402* + ID_MODEL_FROM_DATABASE=Scientific Atlanta WebSTAR 2000 series Cable Modem + +usb:v069Ap4403* + ID_MODEL_FROM_DATABASE=Scientific Atlanta WebSTAR 300 series Cable Modem + +usb:v069Ap4501* + ID_MODEL_FROM_DATABASE=Scientific-Atlanta WebSTAR 2000 series Cable Modem + +usb:v069B* + ID_VENDOR_FROM_DATABASE=Thomson, Inc. + +usb:v069Bp0704* + ID_MODEL_FROM_DATABASE=DCM245 Cable Modem + +usb:v069Bp0705* + ID_MODEL_FROM_DATABASE=THG540K Cable Modem + +usb:v069Bp0709* + ID_MODEL_FROM_DATABASE=Lyra PDP2424 + +usb:v069Bp070C* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v069Bp070D* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v069Bp070E* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v069Bp070F* + ID_MODEL_FROM_DATABASE=RCA Lyra RD1071 MP3 Player + +usb:v069Bp0731* + ID_MODEL_FROM_DATABASE=Lyra M200E256 + +usb:v069Bp0761* + ID_MODEL_FROM_DATABASE=RCA H100A + +usb:v069Bp0778* + ID_MODEL_FROM_DATABASE=PEARL USB Device + +usb:v069Bp2220* + ID_MODEL_FROM_DATABASE=RCA Kazoo RD1000 MP3 Player + +usb:v069Bp300A* + ID_MODEL_FROM_DATABASE=RCA Lyra MP3 Player + +usb:v069Bp3012* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v069Bp3013* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v069Bp5557* + ID_MODEL_FROM_DATABASE=RCA CDS6300 + +usb:v069D* + ID_VENDOR_FROM_DATABASE=Hughes Network Systems (HNS) + +usb:v069Dp0001* + ID_MODEL_FROM_DATABASE=Satellite Receiver Device + +usb:v069Dp0002* + ID_MODEL_FROM_DATABASE=Satellite Device + +usb:v069E* + ID_VENDOR_FROM_DATABASE=Welcat Inc. + +usb:v069Ep0005* + ID_MODEL_FROM_DATABASE=Marx CryptoBox v1.2 + +usb:v069F* + ID_VENDOR_FROM_DATABASE=Allied Data Technologies BV + +usb:v069Fp0010* + ID_MODEL_FROM_DATABASE=Tornado Speakerphone FaxModem 56.0 + +usb:v069Fp0011* + ID_MODEL_FROM_DATABASE=Tornado Speakerphone FaxModem 56.0 + +usb:v069Fp1000* + ID_MODEL_FROM_DATABASE=ADT VvBus for CopperJet + +usb:v069Fp1004* + ID_MODEL_FROM_DATABASE=CopperJet 821 RouterPlus + +usb:v06A2* + ID_VENDOR_FROM_DATABASE=Topro Technology, Inc. + +usb:v06A2p0033* + ID_MODEL_FROM_DATABASE=USB Mouse + +usb:v06A3* + ID_VENDOR_FROM_DATABASE=Saitek PLC + +usb:v06A3p0006* + ID_MODEL_FROM_DATABASE=Cyborg Gold Joystick + +usb:v06A3p0109* + ID_MODEL_FROM_DATABASE=P880 Pad + +usb:v06A3p0160* + ID_MODEL_FROM_DATABASE=ST290 Pro + +usb:v06A3p0200* + ID_MODEL_FROM_DATABASE=Xbox Adrenalin Hub + +usb:v06A3p0241* + ID_MODEL_FROM_DATABASE=Xbox Adrenalin Gamepad + +usb:v06A3p0255* + ID_MODEL_FROM_DATABASE=X52 Flight Controller + +usb:v06A3p040B* + ID_MODEL_FROM_DATABASE=P990 Dual Analog Pad + +usb:v06A3p040C* + ID_MODEL_FROM_DATABASE=P2900 Wireless Pad + +usb:v06A3p0422* + ID_MODEL_FROM_DATABASE=ST90 Joystick + +usb:v06A3p0460* + ID_MODEL_FROM_DATABASE=ST290 Pro Flight Stick + +usb:v06A3p0463* + ID_MODEL_FROM_DATABASE=ST290 + +usb:v06A3p0464* + ID_MODEL_FROM_DATABASE=Cyborg Evo + +usb:v06A3p0471* + ID_MODEL_FROM_DATABASE=Cyborg Graphite Stick + +usb:v06A3p0501* + ID_MODEL_FROM_DATABASE=R100 Sports Wheel + +usb:v06A3p0502* + ID_MODEL_FROM_DATABASE=ST200 Stick + +usb:v06A3p0506* + ID_MODEL_FROM_DATABASE=R220 Digital Wheel + +usb:v06A3p051E* + ID_MODEL_FROM_DATABASE=Cyborg Digital II Stick + +usb:v06A3p052D* + ID_MODEL_FROM_DATABASE=P750 Gamepad + +usb:v06A3p053C* + ID_MODEL_FROM_DATABASE=X45 Flight Controller + +usb:v06A3p053F* + ID_MODEL_FROM_DATABASE=X36F Flightstick + +usb:v06A3p056C* + ID_MODEL_FROM_DATABASE=P2000 Tilt Pad + +usb:v06A3p056F* + ID_MODEL_FROM_DATABASE=P2000 Tilt Pad + +usb:v06A3p05D2* + ID_MODEL_FROM_DATABASE=PC Dash 2 + +usb:v06A3p075C* + ID_MODEL_FROM_DATABASE=X52 Flight Controller + +usb:v06A3p0762* + ID_MODEL_FROM_DATABASE=Saitek X52 Pro Flight Control System + +usb:v06A3p0763* + ID_MODEL_FROM_DATABASE=Pro Flight Rudder Pedals + +usb:v06A3p0764* + ID_MODEL_FROM_DATABASE=Flight Pro Combat Rudder + +usb:v06A3p0805* + ID_MODEL_FROM_DATABASE=R440 Force Wheel + +usb:v06A3p0B4E* + ID_MODEL_FROM_DATABASE=Pro Flight Backlit Information Panel + +usb:v06A3p0BAC* + ID_MODEL_FROM_DATABASE=Pro Flight Yoke + +usb:v06A3p0C2D* + ID_MODEL_FROM_DATABASE=Pro Flight Quadrant + +usb:v06A3p0D05* + ID_MODEL_FROM_DATABASE=Pro Flight Radio Panel + +usb:v06A3p0D06* + ID_MODEL_FROM_DATABASE=Flight Pro Multi Panel + +usb:v06A3p0D67* + ID_MODEL_FROM_DATABASE=Pro Flight Switch Panel + +usb:v06A3p1003* + ID_MODEL_FROM_DATABASE=GM2 Action Pad + +usb:v06A3p1009* + ID_MODEL_FROM_DATABASE=Action Pad + +usb:v06A3p100A* + ID_MODEL_FROM_DATABASE=SP550 Pad and Joystick Combo + +usb:v06A3p100B* + ID_MODEL_FROM_DATABASE=SP550 Pad + +usb:v06A3p1509* + ID_MODEL_FROM_DATABASE=P3000 Wireless Pad + +usb:v06A3p1589* + ID_MODEL_FROM_DATABASE=P3000 Wireless Pad + +usb:v06A3p2541* + ID_MODEL_FROM_DATABASE=X45 Flight Controller + +usb:v06A3p3509* + ID_MODEL_FROM_DATABASE=P3000 RF GamePad + +usb:v06A3p353E* + ID_MODEL_FROM_DATABASE=Cyborg Evo Wireless + +usb:v06A3p3589* + ID_MODEL_FROM_DATABASE=P3000 Wireless Pad + +usb:v06A3p35BE* + ID_MODEL_FROM_DATABASE=Cyborg Evo + +usb:v06A3p5509* + ID_MODEL_FROM_DATABASE=P3000 Wireless Pad + +usb:v06A3p712C* + ID_MODEL_FROM_DATABASE=Pro Flight Yoke integrated hub + +usb:v06A3p8000* + ID_MODEL_FROM_DATABASE=Gamers' Keyboard + +usb:v06A3p801E* + ID_MODEL_FROM_DATABASE=Cyborg 3D Digital Stick II + +usb:v06A3p8020* + ID_MODEL_FROM_DATABASE=Eclipse Keyboard + +usb:v06A3p8021* + ID_MODEL_FROM_DATABASE=Eclipse II Keyboard + +usb:v06A3p802D* + ID_MODEL_FROM_DATABASE=P750 Pad + +usb:v06A3p803F* + ID_MODEL_FROM_DATABASE=X36 Flight Controller + +usb:v06A3p806F* + ID_MODEL_FROM_DATABASE=P2000 Tilt Pad + +usb:v06A3p80C0* + ID_MODEL_FROM_DATABASE=Pro Gamer Command Unit + +usb:v06A3p80C1* + ID_MODEL_FROM_DATABASE=Cyborg Command Pad Unit + +usb:v06A3pA2AE* + ID_MODEL_FROM_DATABASE=Pro Flight Instrument Panel + +usb:v06A3pA502* + ID_MODEL_FROM_DATABASE=Gaming Mouse + +usb:v06A3pF518* + ID_MODEL_FROM_DATABASE=P3200 Rumble Force Game Pad + +usb:v06A3pFF04* + ID_MODEL_FROM_DATABASE=R440 Force Wheel + +usb:v06A3pFF0C* + ID_MODEL_FROM_DATABASE=Cyborg Force Rumble Pad + +usb:v06A3pFF0D* + ID_MODEL_FROM_DATABASE=P2600 Rumble Force Pad + +usb:v06A3pFF12* + ID_MODEL_FROM_DATABASE=Cyborg 3D Force Stick + +usb:v06A3pFF17* + ID_MODEL_FROM_DATABASE=ST 330 Rumble Force Stick + +usb:v06A3pFF52* + ID_MODEL_FROM_DATABASE=Cyborg 3D Rumble Force Joystick + +usb:v06A3pFFB5* + ID_MODEL_FROM_DATABASE=Cyborg Evo Force Joystick + +usb:v06A4* + ID_VENDOR_FROM_DATABASE=Xiamen Doowell Electron Co., Ltd + +usb:v06A5* + ID_VENDOR_FROM_DATABASE=Divio + +usb:v06A5p0000* + ID_MODEL_FROM_DATABASE=Typhoon Webcam 100k [nw8000] + +usb:v06A5pD001* + ID_MODEL_FROM_DATABASE=ProLink DS3303u Webcam + +usb:v06A5pD800* + ID_MODEL_FROM_DATABASE=Chicony TwinkleCam + +usb:v06A5pD820* + ID_MODEL_FROM_DATABASE=Wize Media 1000 + +usb:v06A7* + ID_VENDOR_FROM_DATABASE=MicroStore, Inc. + +usb:v06A8* + ID_VENDOR_FROM_DATABASE=Topaz Systems, Inc. + +usb:v06A8p0042* + ID_MODEL_FROM_DATABASE=SignatureGem 1X5 Pad + +usb:v06A8p0043* + ID_MODEL_FROM_DATABASE=SignatureGem 1X5-HID Pad + +usb:v06A9* + ID_VENDOR_FROM_DATABASE=Westell + +usb:v06A9p0005* + ID_MODEL_FROM_DATABASE=WireSpeed Dual Connect Modem + +usb:v06A9p0006* + ID_MODEL_FROM_DATABASE=WireSpeed Dual Connect Modem + +usb:v06A9p000A* + ID_MODEL_FROM_DATABASE=WireSpeed Dual Connect Modem + +usb:v06A9p000B* + ID_MODEL_FROM_DATABASE=WireSpeed Dual Connect Modem + +usb:v06A9p000E* + ID_MODEL_FROM_DATABASE=A90-211WG-01 802.11g Adapter [Intersil ISL3887] + +usb:v06AA* + ID_VENDOR_FROM_DATABASE=Sysgration, Ltd + +usb:v06AC* + ID_VENDOR_FROM_DATABASE=Fujitsu Laboratories of America, Inc. + +usb:v06AD* + ID_VENDOR_FROM_DATABASE=Greatland Electronics Taiwan, Ltd + +usb:v06AE* + ID_VENDOR_FROM_DATABASE=Professional Multimedia Testing Centre + +usb:v06AF* + ID_VENDOR_FROM_DATABASE=Harting, Inc. of North America + +usb:v06B8* + ID_VENDOR_FROM_DATABASE=Pixela Corp. + +usb:v06B9* + ID_VENDOR_FROM_DATABASE=Alcatel Telecom + +usb:v06B9p0120* + ID_MODEL_FROM_DATABASE=SpeedTouch 120g 802.11g Wireless Adapter [Intersil ISL3886] + +usb:v06B9p0121* + ID_MODEL_FROM_DATABASE=SpeedTouch 121g Wireless Dongle + +usb:v06B9p2001* + ID_MODEL_FROM_DATABASE=SPEED TOUCH Card + +usb:v06B9p4061* + ID_MODEL_FROM_DATABASE=SpeedTouch ISDN or ADSL Modem + +usb:v06B9p4062* + ID_MODEL_FROM_DATABASE=SpeedTouch ISDN or ADSL router + +usb:v06B9pA5A5* + ID_MODEL_FROM_DATABASE=DynaMiTe Modem + +usb:v06BA* + ID_VENDOR_FROM_DATABASE=Smooth Cord & Connector Co., Ltd + +usb:v06BB* + ID_VENDOR_FROM_DATABASE=EDA, Inc. + +usb:v06BC* + ID_VENDOR_FROM_DATABASE=Oki Data Corp. + +usb:v06BCp000B* + ID_MODEL_FROM_DATABASE=Okipage 14ex Printer + +usb:v06BCp0027* + ID_MODEL_FROM_DATABASE=Okipage 14e + +usb:v06BCp00F7* + ID_MODEL_FROM_DATABASE=OKI B4600 Mono Printer + +usb:v06BCp015E* + ID_MODEL_FROM_DATABASE=OKIPOS 411/412 POS Printer + +usb:v06BCp01C9* + ID_MODEL_FROM_DATABASE=OKI B430 Mono Printer + +usb:v06BCp020B* + ID_MODEL_FROM_DATABASE=OKI ES4140 Mono Printer + +usb:v06BCp02BB* + ID_MODEL_FROM_DATABASE=OKI PT390 POS Printer + +usb:v06BCp0A91* + ID_MODEL_FROM_DATABASE=B2500MFP (printer+scanner) + +usb:v06BCp3801* + ID_MODEL_FROM_DATABASE=B6100 Laser Printer + +usb:v06BD* + ID_VENDOR_FROM_DATABASE=AGFA-Gevaert NV + +usb:v06BDp0001* + ID_MODEL_FROM_DATABASE=SnapScan 1212U + +usb:v06BDp0002* + ID_MODEL_FROM_DATABASE=SnapScan 1236U + +usb:v06BDp0100* + ID_MODEL_FROM_DATABASE=SnapScan Touch + +usb:v06BDp0101* + ID_MODEL_FROM_DATABASE=SNAPSCAN ELITE + +usb:v06BDp0200* + ID_MODEL_FROM_DATABASE=ScanMaker 8700 + +usb:v06BDp02BF* + ID_MODEL_FROM_DATABASE=DUOSCAN f40 + +usb:v06BDp0400* + ID_MODEL_FROM_DATABASE=CL30 + +usb:v06BDp0401* + ID_MODEL_FROM_DATABASE=Mass Storage + +usb:v06BDp0403* + ID_MODEL_FROM_DATABASE=ePhoto CL18 Camera + +usb:v06BDp0404* + ID_MODEL_FROM_DATABASE=ePhoto CL20 Camera + +usb:v06BDp2061* + ID_MODEL_FROM_DATABASE=SnapScan 1212U (?) + +usb:v06BDp208D* + ID_MODEL_FROM_DATABASE=Snapscan e40 + +usb:v06BDp208F* + ID_MODEL_FROM_DATABASE=SnapScan e50 + +usb:v06BDp2091* + ID_MODEL_FROM_DATABASE=SnapScan e20 + +usb:v06BDp2093* + ID_MODEL_FROM_DATABASE=SnapScan e10 + +usb:v06BDp2095* + ID_MODEL_FROM_DATABASE=SnapScan e25 + +usb:v06BDp2097* + ID_MODEL_FROM_DATABASE=SnapScan e26 + +usb:v06BDp20FD* + ID_MODEL_FROM_DATABASE=SnapScan e52 + +usb:v06BDp20FF* + ID_MODEL_FROM_DATABASE=SnapScan e42 + +usb:v06BE* + ID_VENDOR_FROM_DATABASE=AME Optimedia Technology Co., Ltd + +usb:v06BEp0800* + ID_MODEL_FROM_DATABASE=Optimedia Camera + +usb:v06BEp1005* + ID_MODEL_FROM_DATABASE=Dazzle DPVM! (1005) + +usb:v06BEpD001* + ID_MODEL_FROM_DATABASE=P35U Camera Capture + +usb:v06BF* + ID_VENDOR_FROM_DATABASE=Leoco Corp. + +usb:v06C2* + ID_VENDOR_FROM_DATABASE=Phidgets Inc. (formerly GLAB) + +usb:v06C2p0030* + ID_MODEL_FROM_DATABASE=PhidgetRFID + +usb:v06C2p0031* + ID_MODEL_FROM_DATABASE=RFID reader + +usb:v06C2p0038* + ID_MODEL_FROM_DATABASE=4-Motor PhidgetServo v3.0 + +usb:v06C2p0039* + ID_MODEL_FROM_DATABASE=1-Motor PhidgetServo v3.0 + +usb:v06C2p003A* + ID_MODEL_FROM_DATABASE=8-Motor PhidgetAvancedServo + +usb:v06C2p0040* + ID_MODEL_FROM_DATABASE=PhidgetInterface Kit 0-0-4 + +usb:v06C2p0044* + ID_MODEL_FROM_DATABASE=PhidgetInterface Kit 0-16-16 + +usb:v06C2p0045* + ID_MODEL_FROM_DATABASE=PhidgetInterface Kit 8-8-8 + +usb:v06C2p0048* + ID_MODEL_FROM_DATABASE=PhidgetStepper (Under Development) + +usb:v06C2p0049* + ID_MODEL_FROM_DATABASE=PhidgetTextLED Ver 1.0 + +usb:v06C2p004A* + ID_MODEL_FROM_DATABASE=PhidgetLED Ver 1.0 + +usb:v06C2p004B* + ID_MODEL_FROM_DATABASE=PhidgetEncoder Ver 1.0 + +usb:v06C2p0051* + ID_MODEL_FROM_DATABASE=PhidgetInterface Kit 0-5-7 (Custom) + +usb:v06C2p0052* + ID_MODEL_FROM_DATABASE=PhidgetTextLCD + +usb:v06C2p0053* + ID_MODEL_FROM_DATABASE=PhidgetInterfaceKit 0-8-8 + +usb:v06C2p0058* + ID_MODEL_FROM_DATABASE=PhidgetMotorControl Ver 1.0 + +usb:v06C2p0070* + ID_MODEL_FROM_DATABASE=PhidgetTemperatureSensor Ver 1.0 + +usb:v06C2p0071* + ID_MODEL_FROM_DATABASE=PhidgetAccelerometer Ver 1.0 + +usb:v06C2p0072* + ID_MODEL_FROM_DATABASE=PhidgetWeightSensor Ver 1.0 + +usb:v06C2p0073* + ID_MODEL_FROM_DATABASE=PhidgetHumiditySensor + +usb:v06C2p0074* + ID_MODEL_FROM_DATABASE=PhidgetPHSensor + +usb:v06C2p0075* + ID_MODEL_FROM_DATABASE=PhidgetGyroscope + +usb:v06C4* + ID_VENDOR_FROM_DATABASE=Bizlink International Corp. + +usb:v06C5* + ID_VENDOR_FROM_DATABASE=Hagenuk, GmbH + +usb:v06C6* + ID_VENDOR_FROM_DATABASE=Infowave Software, Inc. + +usb:v06C8* + ID_VENDOR_FROM_DATABASE=SIIG, Inc. + +usb:v06C9* + ID_VENDOR_FROM_DATABASE=Taxan (Europe), Ltd + +usb:v06C9p0005* + ID_MODEL_FROM_DATABASE=Monitor Control + +usb:v06C9p0007* + ID_MODEL_FROM_DATABASE=Monitor Control + +usb:v06C9p0009* + ID_MODEL_FROM_DATABASE=Monitor Control + +usb:v06CA* + ID_VENDOR_FROM_DATABASE=Newer Technology, Inc. + +usb:v06CAp2003* + ID_MODEL_FROM_DATABASE=uSCSI + +usb:v06CB* + ID_VENDOR_FROM_DATABASE=Synaptics, Inc. + +usb:v06CBp0001* + ID_MODEL_FROM_DATABASE=TouchPad + +usb:v06CBp0002* + ID_MODEL_FROM_DATABASE=Integrated TouchPad + +usb:v06CBp0003* + ID_MODEL_FROM_DATABASE=cPad + +usb:v06CBp0005* + ID_MODEL_FROM_DATABASE=Touchpad/FPS + +usb:v06CBp0006* + ID_MODEL_FROM_DATABASE=TouchScreen + +usb:v06CBp0007* + ID_MODEL_FROM_DATABASE=USB Styk + +usb:v06CBp0008* + ID_MODEL_FROM_DATABASE=WheelPad + +usb:v06CBp0009* + ID_MODEL_FROM_DATABASE=Composite TouchPad and TrackPoint + +usb:v06CBp000E* + ID_MODEL_FROM_DATABASE=HID Device + +usb:v06CBp0010* + ID_MODEL_FROM_DATABASE=Wireless TouchPad + +usb:v06CBp0013* + ID_MODEL_FROM_DATABASE=DisplayPad + +usb:v06CBp2970* + ID_MODEL_FROM_DATABASE=touchpad + +usb:v06CC* + ID_VENDOR_FROM_DATABASE=Terayon Communication Systems + +usb:v06CCp0101* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v06CCp0102* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v06CCp0103* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v06CCp0104* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v06CCp0304* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v06CD* + ID_VENDOR_FROM_DATABASE=Keyspan + +usb:v06CDp0101* + ID_MODEL_FROM_DATABASE=USA-28 PDA [no firmware] + +usb:v06CDp0102* + ID_MODEL_FROM_DATABASE=USA-28X PDA [no firmware] + +usb:v06CDp0103* + ID_MODEL_FROM_DATABASE=USA-19 PDA [no firmware] + +usb:v06CDp0104* + ID_MODEL_FROM_DATABASE=PDA [prerenum] + +usb:v06CDp0105* + ID_MODEL_FROM_DATABASE=USA-18X PDA [no firmware] + +usb:v06CDp0106* + ID_MODEL_FROM_DATABASE=USA-19W PDA [no firmware] + +usb:v06CDp0107* + ID_MODEL_FROM_DATABASE=USA-19 PDA + +usb:v06CDp0108* + ID_MODEL_FROM_DATABASE=USA-19W PDA + +usb:v06CDp0109* + ID_MODEL_FROM_DATABASE=USA-49W serial adapter [no firmware] + +usb:v06CDp010A* + ID_MODEL_FROM_DATABASE=USA-49W serial adapter + +usb:v06CDp010B* + ID_MODEL_FROM_DATABASE=USA-19Qi serial adapter [no firmware] + +usb:v06CDp010C* + ID_MODEL_FROM_DATABASE=USA-19Qi serial adapter + +usb:v06CDp010D* + ID_MODEL_FROM_DATABASE=USA-19Q serial Adapter (no firmware) + +usb:v06CDp010E* + ID_MODEL_FROM_DATABASE=USA-19Q serial Adapter + +usb:v06CDp010F* + ID_MODEL_FROM_DATABASE=USA-28 PDA + +usb:v06CDp0110* + ID_MODEL_FROM_DATABASE=USA-28Xb PDA + +usb:v06CDp0111* + ID_MODEL_FROM_DATABASE=USA-18 serial Adapter + +usb:v06CDp0112* + ID_MODEL_FROM_DATABASE=USA-18X PDA + +usb:v06CDp0113* + ID_MODEL_FROM_DATABASE=USA-28Xb PDA [no firmware] + +usb:v06CDp0114* + ID_MODEL_FROM_DATABASE=USA-28Xa PDA [no firmware] + +usb:v06CDp0115* + ID_MODEL_FROM_DATABASE=USA-28Xa PDA + +usb:v06CDp0116* + ID_MODEL_FROM_DATABASE=USA-18XA serial Adapter (no firmware) + +usb:v06CDp0117* + ID_MODEL_FROM_DATABASE=USA-18XA serial Adapter + +usb:v06CDp0118* + ID_MODEL_FROM_DATABASE=USA-19QW PDA [no firmware] + +usb:v06CDp0119* + ID_MODEL_FROM_DATABASE=USA-19QW PDA + +usb:v06CDp011A* + ID_MODEL_FROM_DATABASE=USA-49Wlc serial adapter [no firmware] + +usb:v06CDp011B* + ID_MODEL_FROM_DATABASE=MPR Serial Preloader (MPRQI) + +usb:v06CDp011C* + ID_MODEL_FROM_DATABASE=MPR Serial (MPRQI) + +usb:v06CDp011D* + ID_MODEL_FROM_DATABASE=MPR Serial Preloader (MPRQ) + +usb:v06CDp011E* + ID_MODEL_FROM_DATABASE=MPR Serial (MPRQ) + +usb:v06CDp0121* + ID_MODEL_FROM_DATABASE=USA-19hs serial adapter + +usb:v06CDp012A* + ID_MODEL_FROM_DATABASE=USA-49Wlc serial adapter + +usb:v06CDp0201* + ID_MODEL_FROM_DATABASE=UIA-10 Digital Media Remote [Cypress AN2131SC] + +usb:v06CDp0202* + ID_MODEL_FROM_DATABASE=UIA-11 Digital Media Remote + +usb:v06CE* + ID_VENDOR_FROM_DATABASE=Contec + +usb:v06CEp8311* + ID_MODEL_FROM_DATABASE=COM-1(USB)H + +usb:v06CF* + ID_VENDOR_FROM_DATABASE=SpheronVR AG + +usb:v06CFp1010* + ID_MODEL_FROM_DATABASE=PanoCam 10 + +usb:v06CFp1012* + ID_MODEL_FROM_DATABASE=PanoCam 12/12X + +usb:v06D0* + ID_VENDOR_FROM_DATABASE=LapLink, Inc. + +usb:v06D0p0622* + ID_MODEL_FROM_DATABASE=LapLink Gold USB-USB Bridge [net1080] + +usb:v06D1* + ID_VENDOR_FROM_DATABASE=Daewoo Electronics Co., Ltd + +usb:v06D3* + ID_VENDOR_FROM_DATABASE=Mitsubishi Electric Corp. + +usb:v06D3p0284* + ID_MODEL_FROM_DATABASE=FX-USB-AW/-BD RS482 Converters + +usb:v06D3p0380* + ID_MODEL_FROM_DATABASE=CP8000D Port + +usb:v06D3p0381* + ID_MODEL_FROM_DATABASE=CP770D Port + +usb:v06D3p0385* + ID_MODEL_FROM_DATABASE=CP900D Port + +usb:v06D3p0387* + ID_MODEL_FROM_DATABASE=CP980D Port + +usb:v06D3p038B* + ID_MODEL_FROM_DATABASE=CP3020D Port + +usb:v06D3p038C* + ID_MODEL_FROM_DATABASE=CP900DW(ID) Port + +usb:v06D3p0393* + ID_MODEL_FROM_DATABASE=CP9500D/DW Port + +usb:v06D3p0394* + ID_MODEL_FROM_DATABASE=CP9000D/DW Port + +usb:v06D3p0398* + ID_MODEL_FROM_DATABASE=P93D + +usb:v06D3p03A1* + ID_MODEL_FROM_DATABASE=CP9550D/DW Port + +usb:v06D3p03A5* + ID_MODEL_FROM_DATABASE=CP9550DW-S + +usb:v06D3p03A9* + ID_MODEL_FROM_DATABASE=CP-9600DW + +usb:v06D3p03AA* + ID_MODEL_FROM_DATABASE=CP3020DA + +usb:v06D3p03AD* + ID_MODEL_FROM_DATABASE=CP-9800D/DW + +usb:v06D3p03AE* + ID_MODEL_FROM_DATABASE=CP-9800DW-S + +usb:v06D3p3B10* + ID_MODEL_FROM_DATABASE=P95D + +usb:v06D3p3B21* + ID_MODEL_FROM_DATABASE=CP-9810D/DW + +usb:v06D3p3B30* + ID_MODEL_FROM_DATABASE=CP-D70DW / CP-D707DW + +usb:v06D3p3B31* + ID_MODEL_FROM_DATABASE=CP-K60DW-S + +usb:v06D3p3B36* + ID_MODEL_FROM_DATABASE=CP-D80DW + +usb:v06D3p3B50* + ID_MODEL_FROM_DATABASE=CP-W5000DW + +usb:v06D3p3B60* + ID_MODEL_FROM_DATABASE=CP-D90DW + +usb:v06D4* + ID_VENDOR_FROM_DATABASE=Cisco Systems + +usb:v06D5* + ID_VENDOR_FROM_DATABASE=Toshiba + +usb:v06D5p4000* + ID_MODEL_FROM_DATABASE=Japanese Keyboard + +usb:v06D6* + ID_VENDOR_FROM_DATABASE=Aashima Technology B.V. + +usb:v06D6p0025* + ID_MODEL_FROM_DATABASE=Gamepad + +usb:v06D6p0026* + ID_MODEL_FROM_DATABASE=Predator TH 400 Gamepad + +usb:v06D6p002D* + ID_MODEL_FROM_DATABASE=Trust PowerC@m 350FT + +usb:v06D6p002E* + ID_MODEL_FROM_DATABASE=Trust PowerC@m 350FS + +usb:v06D6p0030* + ID_MODEL_FROM_DATABASE=Trust 710 LCD POWERC@M ZOOM - MSD + +usb:v06D6p0031* + ID_MODEL_FROM_DATABASE=Trust 610/710 LCD POWERC@M ZOOM + +usb:v06D6p003A* + ID_MODEL_FROM_DATABASE=Trust PowerC@m 770Z (mass storage mode) + +usb:v06D6p003B* + ID_MODEL_FROM_DATABASE=Trust PowerC@m 770Z (webcam mode) + +usb:v06D6p003C* + ID_MODEL_FROM_DATABASE=Trust 910z PowerC@m + +usb:v06D6p003F* + ID_MODEL_FROM_DATABASE=Trust 735S POWERC@M ZOOM, WDM DSC Bulk Driver + +usb:v06D6p0050* + ID_MODEL_FROM_DATABASE=Trust 738AV LCD PV Digital Camera + +usb:v06D6p0062* + ID_MODEL_FROM_DATABASE=TRUST 782AV LCD P. V. Video Capture + +usb:v06D6p0066* + ID_MODEL_FROM_DATABASE=TRUST Digital PCTV and Movie Editor + +usb:v06D6p0067* + ID_MODEL_FROM_DATABASE=Trust 350FS POWERC@M FLASH + +usb:v06D6p006B* + ID_MODEL_FROM_DATABASE=TRUST AUDIO VIDEO EDITOR + +usb:v06D7* + ID_VENDOR_FROM_DATABASE=Network Computing Devices (NCD) + +usb:v06D8* + ID_VENDOR_FROM_DATABASE=Technical Marketing Research, Inc. + +usb:v06DA* + ID_VENDOR_FROM_DATABASE=Phoenixtec Power Co., Ltd + +usb:v06DAp0002* + ID_MODEL_FROM_DATABASE=UPS + +usb:v06DAp0003* + ID_MODEL_FROM_DATABASE=1300VA UPS + +usb:v06DB* + ID_VENDOR_FROM_DATABASE=Paradyne + +usb:v06DC* + ID_VENDOR_FROM_DATABASE=Foxlink Image Technology Co., Ltd + +usb:v06DCp0012* + ID_MODEL_FROM_DATABASE=Scan 1200c Scanner + +usb:v06DCp0014* + ID_MODEL_FROM_DATABASE=Prolink Winscan Pro 2448U + +usb:v06DE* + ID_VENDOR_FROM_DATABASE=Heisei Electronics Co., Ltd + +usb:v06E0* + ID_VENDOR_FROM_DATABASE=Multi-Tech Systems, Inc. + +usb:v06E0p0319* + ID_MODEL_FROM_DATABASE=MT9234ZBA-USB MultiModem ZBA + +usb:v06E0pF101* + ID_MODEL_FROM_DATABASE=MT5634ZBA-USB MultiModemUSB (old firmware) + +usb:v06E0pF103* + ID_MODEL_FROM_DATABASE=MT5634MU MultiMobileUSB + +usb:v06E0pF104* + ID_MODEL_FROM_DATABASE=MT5634ZBA-USB MultiModemUSB (new firmware) + +usb:v06E0pF107* + ID_MODEL_FROM_DATABASE=MT5634ZBA-USB-V92 MultiModemUSB + +usb:v06E0pF120* + ID_MODEL_FROM_DATABASE=MT9234ZBA-USB-CDC-ACM-XR MultiModem ZBA CDC-ACM-XR + +usb:v06E1* + ID_VENDOR_FROM_DATABASE=ADS Technologies, Inc. + +usb:v06E1p0008* + ID_MODEL_FROM_DATABASE=UBS-10BT Ethernet [klsi] + +usb:v06E1p0009* + ID_MODEL_FROM_DATABASE=UBS-10BT Ethernet + +usb:v06E1p0833* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v06E1pA155* + ID_MODEL_FROM_DATABASE=FM Radio Receiver/Instant FM Music (RDX-155-EF) + +usb:v06E1pA160* + ID_MODEL_FROM_DATABASE=Instant Video-To-Go RDX-160 (no firmware) + +usb:v06E1pA161* + ID_MODEL_FROM_DATABASE=Instant Video-To-Go RDX-160 + +usb:v06E1pA190* + ID_MODEL_FROM_DATABASE=Instand VCD Capture + +usb:v06E1pA191* + ID_MODEL_FROM_DATABASE=Instant VideoXpress + +usb:v06E1pA337* + ID_MODEL_FROM_DATABASE=Mini DigitalTV + +usb:v06E1pA701* + ID_MODEL_FROM_DATABASE=DVD Xpress + +usb:v06E1pA708* + ID_MODEL_FROM_DATABASE=saa7114H video input card (Instant VideoMPX) + +usb:v06E1pB337* + ID_MODEL_FROM_DATABASE=Mini DigitalTV + +usb:v06E1pB701* + ID_MODEL_FROM_DATABASE=DVD Xpress B + +usb:v06E4* + ID_VENDOR_FROM_DATABASE=Alcatel Microelectronics + +usb:v06E6* + ID_VENDOR_FROM_DATABASE=Tiger Jet Network, Inc. + +usb:v06E6p0200* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p0201* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p0202* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6p0203* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p0210* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6p0211* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p0212* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p031C* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p031D* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p031E* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p3200* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6p3201* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p3202* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6p3203* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6p7200* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6p7210* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6p7250* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6p825C* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p831C* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6p831D* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6p831E* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pB200* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pB201* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pB202* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pB210* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pB211* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pB212* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pB250* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pB251* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pB252* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pC200* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pC201* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pC202* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pC203* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pC210* + ID_MODEL_FROM_DATABASE=Personal PhoneGateway + +usb:v06E6pC211* + ID_MODEL_FROM_DATABASE=Personal PhoneGateway + +usb:v06E6pC212* + ID_MODEL_FROM_DATABASE=Personal PhoneGateway + +usb:v06E6pC213* + ID_MODEL_FROM_DATABASE=PPG Device + +usb:v06E6pC25C* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pC290* + ID_MODEL_FROM_DATABASE=PPG Device + +usb:v06E6pC291* + ID_MODEL_FROM_DATABASE=PPG Device + +usb:v06E6pC292* + ID_MODEL_FROM_DATABASE=PPG Device + +usb:v06E6pC293* + ID_MODEL_FROM_DATABASE=Personal PhoneGateway + +usb:v06E6pC31C* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pC39C* + ID_MODEL_FROM_DATABASE=Personal PhoneGateway + +usb:v06E6pC39D* + ID_MODEL_FROM_DATABASE=PPG Device + +usb:v06E6pC39E* + ID_MODEL_FROM_DATABASE=PPG Device + +usb:v06E6pC39F* + ID_MODEL_FROM_DATABASE=PPG Device + +usb:v06E6pC700* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pC701* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pC702* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pC703* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pC710* + ID_MODEL_FROM_DATABASE=VoIP Combo Device + +usb:v06E6pC711* + ID_MODEL_FROM_DATABASE=VoIP Combo + +usb:v06E6pC712* + ID_MODEL_FROM_DATABASE=VoIP Combo Device + +usb:v06E6pC713* + ID_MODEL_FROM_DATABASE=VoIP Combo Device + +usb:v06E6pCF00* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pCF01* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pCF02* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pCF03* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pD210* + ID_MODEL_FROM_DATABASE=Personal PhoneGateway + +usb:v06E6pD211* + ID_MODEL_FROM_DATABASE=PPG Device + +usb:v06E6pD212* + ID_MODEL_FROM_DATABASE=PPG Device + +usb:v06E6pD213* + ID_MODEL_FROM_DATABASE=Personal PhoneGateway + +usb:v06E6pD700* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pD701* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pD702* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pD703* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pD710* + ID_MODEL_FROM_DATABASE=VoIP Combo + +usb:v06E6pD711* + ID_MODEL_FROM_DATABASE=VoIP Combo Device + +usb:v06E6pD712* + ID_MODEL_FROM_DATABASE=VoIP Combo + +usb:v06E6pD713* + ID_MODEL_FROM_DATABASE=VoIP Combo + +usb:v06E6pDF00* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pDF01* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pDF02* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pDF03* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pF200* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pF201* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pF202* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pF203* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pF210* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pF250* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06E6pF252* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pF310* + ID_MODEL_FROM_DATABASE=Internet Phone + +usb:v06E6pF350* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v06EA* + ID_VENDOR_FROM_DATABASE=Sirius Technologies + +usb:v06EAp0001* + ID_MODEL_FROM_DATABASE=NetCom Roadster II 56k + +usb:v06EAp0002* + ID_MODEL_FROM_DATABASE=Roadster II 56k + +usb:v06EB* + ID_VENDOR_FROM_DATABASE=PC Expert Tech. Co., Ltd + +usb:v06EF* + ID_VENDOR_FROM_DATABASE=I.A.C. Geometrische Ingenieurs B.V. + +usb:v06F0* + ID_VENDOR_FROM_DATABASE=T.N.C Industrial Co., Ltd + +usb:v06F0pDE01* + ID_MODEL_FROM_DATABASE=DualCam Video Camera + +usb:v06F0pDE02* + ID_MODEL_FROM_DATABASE=DualCam Still Camera + +usb:v06F1* + ID_VENDOR_FROM_DATABASE=Opcode Systems, Inc. + +usb:v06F1pA011* + ID_MODEL_FROM_DATABASE=SonicPort + +usb:v06F1pA021* + ID_MODEL_FROM_DATABASE=SonicPort Optical + +usb:v06F2* + ID_VENDOR_FROM_DATABASE=Emine Technology Co. + +usb:v06F2p0011* + ID_MODEL_FROM_DATABASE=KVM Switch Keyboard + +usb:v06F6* + ID_VENDOR_FROM_DATABASE=Wintrend Technology Co., Ltd + +usb:v06F7* + ID_VENDOR_FROM_DATABASE=Wailly Technology Ltd + +usb:v06F7p0003* + ID_MODEL_FROM_DATABASE=USB->Din 4 Adaptor + +usb:v06F8* + ID_VENDOR_FROM_DATABASE=Guillemot Corp. + +usb:v06F8p3002* + ID_MODEL_FROM_DATABASE=Hercules Blog Webcam + +usb:v06F8p3004* + ID_MODEL_FROM_DATABASE=Hercules Classic Silver + +usb:v06F8p3005* + ID_MODEL_FROM_DATABASE=Hercules Dualpix Exchange + +usb:v06F8p3007* + ID_MODEL_FROM_DATABASE=Hercules Dualpix Chat and Show + +usb:v06F8p3020* + ID_MODEL_FROM_DATABASE=Hercules Webcam EC300 + +usb:v06F8pA300* + ID_MODEL_FROM_DATABASE=Dual Analog Leader GamePad + +usb:v06F8pB000* + ID_MODEL_FROM_DATABASE=Hercules DJ Console + +usb:v06F8pB121* + ID_MODEL_FROM_DATABASE=Hercules P32 DJ + +usb:v06F8pC000* + ID_MODEL_FROM_DATABASE=Hercules Muse Pocket + +usb:v06F8pD002* + ID_MODEL_FROM_DATABASE=Hercules DJ Console + +usb:v06F8pE000* + ID_MODEL_FROM_DATABASE=HWGUSB2-54 WLAN + +usb:v06F8pE010* + ID_MODEL_FROM_DATABASE=HWGUSB2-54-LB + +usb:v06F8pE020* + ID_MODEL_FROM_DATABASE=HWGUSB2-54V2-AP + +usb:v06F8pE031* + ID_MODEL_FROM_DATABASE=Hercules HWNUm-300 Wireless N mini [Realtek RTL8191SU] + +usb:v06F8pE032* + ID_MODEL_FROM_DATABASE=HWGUm-54 [Hercules Wireless G Ultra Mini Key] + +usb:v06F8pE033* + ID_MODEL_FROM_DATABASE=Hercules HWNUp-150 802.11n Wireless N Pico [Realtek RTL8188CUS] + +usb:v06F9* + ID_VENDOR_FROM_DATABASE=ASYST electronic d.o.o. + +usb:v06FA* + ID_VENDOR_FROM_DATABASE=HSD S.r.L + +usb:v06FC* + ID_VENDOR_FROM_DATABASE=Motorola Semiconductor Products Sector + +usb:v06FD* + ID_VENDOR_FROM_DATABASE=Boston Acoustics + +usb:v06FDp0101* + ID_MODEL_FROM_DATABASE=Audio Device + +usb:v06FDp0102* + ID_MODEL_FROM_DATABASE=Audio Device + +usb:v06FDp0201* + ID_MODEL_FROM_DATABASE=2-piece Audio Device + +usb:v06FE* + ID_VENDOR_FROM_DATABASE=Gallant Computer, Inc. + +usb:v0701* + ID_VENDOR_FROM_DATABASE=Supercomal Wire & Cable SDN. BHD. + +usb:v0703* + ID_VENDOR_FROM_DATABASE=Bvtech Industry, Inc. + +usb:v0705* + ID_VENDOR_FROM_DATABASE=NKK Corp. + +usb:v0706* + ID_VENDOR_FROM_DATABASE=Ariel Corp. + +usb:v0707* + ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp. + +usb:v0707p0100* + ID_MODEL_FROM_DATABASE=2202 Ethernet [klsi] + +usb:v0707p0200* + ID_MODEL_FROM_DATABASE=2202 Ethernet [pegasus] + +usb:v0707p0201* + ID_MODEL_FROM_DATABASE=EZ Connect USB Ethernet + +usb:v0707pEE04* + ID_MODEL_FROM_DATABASE=SMCWUSB32 802.11b Wireless LAN Card + +usb:v0707pEE06* + ID_MODEL_FROM_DATABASE=SMC2862W-G v1 EZ Connect 802.11g Adapter [Intersil ISL3886] + +usb:v0707pEE13* + ID_MODEL_FROM_DATABASE=SMC2862W-G v2 EZ Connect 802.11g Adapter [Intersil ISL3887] + +usb:v0708* + ID_VENDOR_FROM_DATABASE=Putercom Co., Ltd + +usb:v0708p047E* + ID_MODEL_FROM_DATABASE=USB-1284 BRIDGE + +usb:v0709* + ID_VENDOR_FROM_DATABASE=Silicon Systems, Ltd (SSL) + +usb:v070A* + ID_VENDOR_FROM_DATABASE=Oki Electric Industry Co., Ltd + +usb:v070Ap4002* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v070Ap4003* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v070D* + ID_VENDOR_FROM_DATABASE=Comoss Electronic Co., Ltd + +usb:v070E* + ID_VENDOR_FROM_DATABASE=Excel Cell Electronic Co., Ltd + +usb:v0710* + ID_VENDOR_FROM_DATABASE=Connect Tech, Inc. + +usb:v0710p0001* + ID_MODEL_FROM_DATABASE=WhiteHeat (fake ID) + +usb:v0710p8001* + ID_MODEL_FROM_DATABASE=WhiteHeat + +usb:v0711* + ID_VENDOR_FROM_DATABASE=Magic Control Technology Corp. + +usb:v0711p0100* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0711p0180* + ID_MODEL_FROM_DATABASE=IRXpress Infrared Device + +usb:v0711p0181* + ID_MODEL_FROM_DATABASE=IRXpress Infrared Device + +usb:v0711p0200* + ID_MODEL_FROM_DATABASE=BAY-3U1S1P Serial Port + +usb:v0711p0210* + ID_MODEL_FROM_DATABASE=MCT1S Serial Port + +usb:v0711p0230* + ID_MODEL_FROM_DATABASE=MCT-232 Serial Port + +usb:v0711p0231* + ID_MODEL_FROM_DATABASE=PS/2 Mouse Port + +usb:v0711p0232* + ID_MODEL_FROM_DATABASE=Serial On Port + +usb:v0711p0240* + ID_MODEL_FROM_DATABASE=PS/2 to USB Converter + +usb:v0711p0300* + ID_MODEL_FROM_DATABASE=BAY-3U1S1P Parallel Port + +usb:v0711p0302* + ID_MODEL_FROM_DATABASE=Parallel Port + +usb:v0711p0900* + ID_MODEL_FROM_DATABASE=SVGA Adapter + +usb:v0711p5001* + ID_MODEL_FROM_DATABASE=Trigger UV-002BD[Startech USBVGAE] + +usb:v0711p5100* + ID_MODEL_FROM_DATABASE=Magic Control Technology Corp. (USB2VGA dongle) + +usb:v0713* + ID_VENDOR_FROM_DATABASE=Interval Research Corp. + +usb:v0714* + ID_VENDOR_FROM_DATABASE=NewMotion, Inc. + +usb:v0714p0003* + ID_MODEL_FROM_DATABASE=ADB converter + +usb:v0717* + ID_VENDOR_FROM_DATABASE=ZNK Corp. + +usb:v0718* + ID_VENDOR_FROM_DATABASE=Imation Corp. + +usb:v0718p0002* + ID_MODEL_FROM_DATABASE=SuperDisk 120MB + +usb:v0718p0003* + ID_MODEL_FROM_DATABASE=SuperDisk 120MB (Authenticated) + +usb:v0718p0060* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v0718p0061* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v0718p0062* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v0718p0063* + ID_MODEL_FROM_DATABASE=Swivel Flash Drive + +usb:v0718p0064* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v0718p0065* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v0718p0066* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v0718p0067* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v0718p0068* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v0718p0084* + ID_MODEL_FROM_DATABASE=Flash Drive Mini + +usb:v0718p043C* + ID_MODEL_FROM_DATABASE=Flash drive 16GB [Nano Pro] + +usb:v0718p0582* + ID_MODEL_FROM_DATABASE=Revo Flash Drive + +usb:v0718p0622* + ID_MODEL_FROM_DATABASE=TDK Trans-It 4GB + +usb:v0718p0624* + ID_MODEL_FROM_DATABASE=TDK Trans-It 16GB + +usb:v0718p1120* + ID_MODEL_FROM_DATABASE=RDX External dock (redbud) + +usb:v0718p4006* + ID_MODEL_FROM_DATABASE=8x Slim DVD Multi-Format Recorder External + +usb:v0718pD000* + ID_MODEL_FROM_DATABASE=Disc Stakka CD/DVD Manager + +usb:v0719* + ID_VENDOR_FROM_DATABASE=Tremon Enterprises Co., Ltd + +usb:v071B* + ID_VENDOR_FROM_DATABASE=Domain Technologies, Inc. + +usb:v071Bp0002* + ID_MODEL_FROM_DATABASE=DTI-56362-USB Digital Interface Unit + +usb:v071Bp0101* + ID_MODEL_FROM_DATABASE=Audio4-USB DSP Data Acquisition Unit + +usb:v071Bp0184* + ID_MODEL_FROM_DATABASE=Archos 2 8GB EM184RB + +usb:v071Bp0201* + ID_MODEL_FROM_DATABASE=Audio4-5410 DSP Data Acquisition Unit + +usb:v071Bp0301* + ID_MODEL_FROM_DATABASE=SB-USB JTAG Emulator + +usb:v071Bp3203* + ID_MODEL_FROM_DATABASE=Rockchip Media Player + +usb:v071Bp32BB* + ID_MODEL_FROM_DATABASE=Music Mediatouch + +usb:v071C* + ID_VENDOR_FROM_DATABASE=Xionics Document Technologies, Inc. + +usb:v071D* + ID_VENDOR_FROM_DATABASE=Eicon Networks Corp. + +usb:v071Dp1000* + ID_MODEL_FROM_DATABASE=Diva 2.01 S/T [PSB2115F] + +usb:v071Dp1003* + ID_MODEL_FROM_DATABASE=Diva ISDN 2.0 + +usb:v071Dp1005* + ID_MODEL_FROM_DATABASE=Diva ISDN 4.0 [HFC-S] + +usb:v071Dp2000* + ID_MODEL_FROM_DATABASE=Teledat Surf + +usb:v071E* + ID_VENDOR_FROM_DATABASE=Ariston Technologies + +usb:v0720* + ID_VENDOR_FROM_DATABASE=Keyence Corp. + +usb:v0720p8001* + ID_MODEL_FROM_DATABASE=LJ-V7001 + +usb:v0723* + ID_VENDOR_FROM_DATABASE=Centillium Communications Corp. + +usb:v0723p0002* + ID_MODEL_FROM_DATABASE=Palladia 300/400 Adsl Modem + +usb:v0726* + ID_VENDOR_FROM_DATABASE=Vanguard International Semiconductor-America + +usb:v0729* + ID_VENDOR_FROM_DATABASE=Amitm + +usb:v0729p1000* + ID_MODEL_FROM_DATABASE=USC-1000 Serial Port + +usb:v072E* + ID_VENDOR_FROM_DATABASE=Sunix Co., Ltd + +usb:v072F* + ID_VENDOR_FROM_DATABASE=Advanced Card Systems, Ltd + +usb:v072Fp0001* + ID_MODEL_FROM_DATABASE=AC1030-based SmartCard Reader + +usb:v072Fp0008* + ID_MODEL_FROM_DATABASE=ACR 80 Smart Card Reader + +usb:v072Fp0100* + ID_MODEL_FROM_DATABASE=AET65 + +usb:v072Fp0101* + ID_MODEL_FROM_DATABASE=AET65 + +usb:v072Fp0102* + ID_MODEL_FROM_DATABASE=AET62 + +usb:v072Fp0103* + ID_MODEL_FROM_DATABASE=AET62 + +usb:v072Fp0901* + ID_MODEL_FROM_DATABASE=ACR1281U-C4 (BSI) + +usb:v072Fp1000* + ID_MODEL_FROM_DATABASE=PLDT Drive + +usb:v072Fp1001* + ID_MODEL_FROM_DATABASE=PLDT Drive + +usb:v072Fp2011* + ID_MODEL_FROM_DATABASE=ACR88U + +usb:v072Fp2100* + ID_MODEL_FROM_DATABASE=ACR128U + +usb:v072Fp2200* + ID_MODEL_FROM_DATABASE=ACR122U + +usb:v072Fp220A* + ID_MODEL_FROM_DATABASE=ACR1281U-C5 (BSI) + +usb:v072Fp220C* + ID_MODEL_FROM_DATABASE=ACR1283 Bootloader + +usb:v072Fp220F* + ID_MODEL_FROM_DATABASE=ACR1281U-C2 (qPBOC) + +usb:v072Fp2211* + ID_MODEL_FROM_DATABASE=ACR1261 1S Dual Reader + +usb:v072Fp2214* + ID_MODEL_FROM_DATABASE=ACR1222 1SAM PICC Reader + +usb:v072Fp2215* + ID_MODEL_FROM_DATABASE=ACR1281 2S CL Reader + +usb:v072Fp221A* + ID_MODEL_FROM_DATABASE=ACR1251U-A1 + +usb:v072Fp221B* + ID_MODEL_FROM_DATABASE=ACR1251U-C + +usb:v072Fp2224* + ID_MODEL_FROM_DATABASE=ACR1281 1S Dual Reader + +usb:v072Fp222B* + ID_MODEL_FROM_DATABASE=ACR1222U-C8 + +usb:v072Fp222C* + ID_MODEL_FROM_DATABASE=ACR1283L-D2 + +usb:v072Fp222D* + ID_MODEL_FROM_DATABASE=[OEM Reader] + +usb:v072Fp222E* + ID_MODEL_FROM_DATABASE=ACR123U + +usb:v072Fp2242* + ID_MODEL_FROM_DATABASE=ACR1251 1S Dual Reader + +usb:v072Fp8002* + ID_MODEL_FROM_DATABASE=AET63 BioTRUSTKey + +usb:v072Fp8003* + ID_MODEL_FROM_DATABASE=ACR120 + +usb:v072Fp8103* + ID_MODEL_FROM_DATABASE=ACR120 + +usb:v072Fp8201* + ID_MODEL_FROM_DATABASE=APG8201 + +usb:v072Fp8900* + ID_MODEL_FROM_DATABASE=ACR89U-A1 + +usb:v072Fp8901* + ID_MODEL_FROM_DATABASE=ACR89U-A2 + +usb:v072Fp8902* + ID_MODEL_FROM_DATABASE=ACR89U-A3 + +usb:v072Fp9000* + ID_MODEL_FROM_DATABASE=ACR38 AC1038-based Smart Card Reader + +usb:v072Fp9006* + ID_MODEL_FROM_DATABASE=CryptoMate + +usb:v072Fp90CC* + ID_MODEL_FROM_DATABASE=ACR38 SmartCard Reader + +usb:v072Fp90CE* + ID_MODEL_FROM_DATABASE=[OEM Reader] + +usb:v072Fp90CF* + ID_MODEL_FROM_DATABASE=ACR38 SAM Smart Card Reader + +usb:v072Fp90D0* + ID_MODEL_FROM_DATABASE=PertoSmart EMV - Card Reader + +usb:v072Fp90D2* + ID_MODEL_FROM_DATABASE=ACR83U + +usb:v072Fp90D8* + ID_MODEL_FROM_DATABASE=ACR3801 + +usb:v072Fp90DB* + ID_MODEL_FROM_DATABASE=CryptoMate64 + +usb:v072FpB000* + ID_MODEL_FROM_DATABASE=ACR3901U + +usb:v072FpB100* + ID_MODEL_FROM_DATABASE=ACR39U + +usb:v072FpB101* + ID_MODEL_FROM_DATABASE=ACR39K + +usb:v072FpB102* + ID_MODEL_FROM_DATABASE=ACR39T + +usb:v072FpB103* + ID_MODEL_FROM_DATABASE=ACR39F + +usb:v072FpB104* + ID_MODEL_FROM_DATABASE=ACR39U-SAM + +usb:v072FpB106* + ID_MODEL_FROM_DATABASE=ACOS5T2 + +usb:v072FpB200* + ID_MODEL_FROM_DATABASE=ACOS5T1 + +usb:v072FpB301* + ID_MODEL_FROM_DATABASE=ACR32-A1 + +usb:v0731* + ID_VENDOR_FROM_DATABASE=Susteen, Inc. + +usb:v0731p0528* + ID_MODEL_FROM_DATABASE=SonyEricsson DCU-11 Cable + +usb:v0732* + ID_VENDOR_FROM_DATABASE=Goldfull Electronics & Telecommunications Corp. + +usb:v0733* + ID_VENDOR_FROM_DATABASE=ViewQuest Technologies, Inc. + +usb:v0733p0101* + ID_MODEL_FROM_DATABASE=Digital Video Camera + +usb:v0733p0110* + ID_MODEL_FROM_DATABASE=VQ110 Video Camera + +usb:v0733p0401* + ID_MODEL_FROM_DATABASE=CS330 Webcam + +usb:v0733p0402* + ID_MODEL_FROM_DATABASE=M-318B Webcam + +usb:v0733p0430* + ID_MODEL_FROM_DATABASE=Intel Pro Share Webcam + +usb:v0733p0630* + ID_MODEL_FROM_DATABASE=VQ630 Dual Mode Digital Camera(Bulk) + +usb:v0733p0631* + ID_MODEL_FROM_DATABASE=Hercules Dualpix + +usb:v0733p0780* + ID_MODEL_FROM_DATABASE=Smart Cam Deluxe(composite) + +usb:v0733p1310* + ID_MODEL_FROM_DATABASE=Epsilon 1.3/Jenoptik JD C1.3/UMAX AstraPix 470 (mass storage mode) + +usb:v0733p1311* + ID_MODEL_FROM_DATABASE=Epsilon 1.3/Jenoptik JD C1.3/UMAX AstraPix 470 (PC Cam mode) + +usb:v0733p1314* + ID_MODEL_FROM_DATABASE=Mercury 2.1MEG Deluxe Classic Cam + +usb:v0733p2211* + ID_MODEL_FROM_DATABASE=Jenoptik jdc 21 LCD Camera + +usb:v0733p2221* + ID_MODEL_FROM_DATABASE=Mercury Digital Pro 3.1p + +usb:v0733p3261* + ID_MODEL_FROM_DATABASE=Concord 3045 spca536a Camera + +usb:v0733p3281* + ID_MODEL_FROM_DATABASE=Cyberpix S550V + +usb:v0734* + ID_VENDOR_FROM_DATABASE=Lasat Communications A/S + +usb:v0734p0001* + ID_MODEL_FROM_DATABASE=560V Modem + +usb:v0734p0002* + ID_MODEL_FROM_DATABASE=Lasat 560V Modem + +usb:v0734p043A* + ID_MODEL_FROM_DATABASE=DVS Audio + +usb:v0734p043B* + ID_MODEL_FROM_DATABASE=3DeMon USB Capture + +usb:v0735* + ID_VENDOR_FROM_DATABASE=Asuscom Network + +usb:v0735p2100* + ID_MODEL_FROM_DATABASE=ISDN Adapter + +usb:v0735p2101* + ID_MODEL_FROM_DATABASE=ISDN Adapter + +usb:v0735p6694* + ID_MODEL_FROM_DATABASE=ISDNlink 128K + +usb:v0735pC541* + ID_MODEL_FROM_DATABASE=ISDN TA 280 + +usb:v0736* + ID_VENDOR_FROM_DATABASE=Lorom Industrial Co., Ltd + +usb:v0738* + ID_VENDOR_FROM_DATABASE=Mad Catz, Inc. + +usb:v0738p4507* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p4516* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p4520* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p4526* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p4536* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p4540* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p4556* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p4566* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p4576* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p4586* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p4588* + ID_MODEL_FROM_DATABASE=XBox Device + +usb:v0738p8818* + ID_MODEL_FROM_DATABASE=Street Fighter IV Arcade FightStick (PS3) + +usb:v073A* + ID_VENDOR_FROM_DATABASE=Chaplet Systems, Inc. + +usb:v073Ap2230* + ID_MODEL_FROM_DATABASE=infrared dongle for remote + +usb:v073B* + ID_VENDOR_FROM_DATABASE=Suncom Technologies + +usb:v073C* + ID_VENDOR_FROM_DATABASE=Industrial Electronic Engineers, Inc. + +usb:v073Cp0305* + ID_MODEL_FROM_DATABASE=Pole Display (PC305-3415 2 x 20 Line Display) + +usb:v073Cp0322* + ID_MODEL_FROM_DATABASE=Pole Display (PC322-3415 2 x 20 Line Display) + +usb:v073Cp0324* + ID_MODEL_FROM_DATABASE=Pole Display (LB324-USB 4 x 20 Line Display) + +usb:v073Cp0330* + ID_MODEL_FROM_DATABASE=Pole Display (P330-3415 2 x 20 Line Display) + +usb:v073Cp0424* + ID_MODEL_FROM_DATABASE=Pole Display (SP324-4415 4 x 20 Line Display) + +usb:v073Cp0450* + ID_MODEL_FROM_DATABASE=Pole Display (L450-USB Graphic Line Display) + +usb:v073Cp0505* + ID_MODEL_FROM_DATABASE=Pole Display (SPC505-3415 2 x 20 Line Display) + +usb:v073Cp0522* + ID_MODEL_FROM_DATABASE=Pole Display (SPC522-3415 2 x 20 Line Display) + +usb:v073Cp0624* + ID_MODEL_FROM_DATABASE=Pole Display (SP324-3415 4 x 20 Line Display) + +usb:v073D* + ID_VENDOR_FROM_DATABASE=Eutron S.p.a. + +usb:v073Dp0005* + ID_MODEL_FROM_DATABASE=Crypto Token + +usb:v073Dp0007* + ID_MODEL_FROM_DATABASE=CryptoIdentity CCID + +usb:v073Dp0025* + ID_MODEL_FROM_DATABASE=SmartKey 3 + +usb:v073Dp0C00* + ID_MODEL_FROM_DATABASE=Pocket Reader + +usb:v073Dp0D00* + ID_MODEL_FROM_DATABASE=StarSign Bio Token 3.0 EU + +usb:v073E* + ID_VENDOR_FROM_DATABASE=NEC, Inc. + +usb:v073Ep0301* + ID_MODEL_FROM_DATABASE=Game Pad + +usb:v0742* + ID_VENDOR_FROM_DATABASE=Stollmann + +usb:v0742p2008* + ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] + +usb:v0742p2009* + ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] + +usb:v0742p200A* + ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] + +usb:v0745* + ID_VENDOR_FROM_DATABASE=Syntech Information Co., Ltd + +usb:v0746* + ID_VENDOR_FROM_DATABASE=Onkyo Corp. + +usb:v0746p5500* + ID_MODEL_FROM_DATABASE=SE-U55 Audio Device + +usb:v0747* + ID_VENDOR_FROM_DATABASE=Labway Corp. + +usb:v0748* + ID_VENDOR_FROM_DATABASE=Strong Man Enterprise Co., Ltd + +usb:v0749* + ID_VENDOR_FROM_DATABASE=EVer Electronics Corp. + +usb:v074A* + ID_VENDOR_FROM_DATABASE=Ming Fortune Industry Co., Ltd + +usb:v074B* + ID_VENDOR_FROM_DATABASE=Polestar Tech. Corp. + +usb:v074C* + ID_VENDOR_FROM_DATABASE=C-C-C Group PLC + +usb:v074D* + ID_VENDOR_FROM_DATABASE=Micronas GmbH + +usb:v074Dp3553* + ID_MODEL_FROM_DATABASE=Composite USB-Device + +usb:v074Dp3554* + ID_MODEL_FROM_DATABASE=Composite USB-Device + +usb:v074Dp3556* + ID_MODEL_FROM_DATABASE=Composite USB-Device + +usb:v074E* + ID_VENDOR_FROM_DATABASE=Digital Stream Corp. + +usb:v074Ep0001* + ID_MODEL_FROM_DATABASE=PS/2 Adapter + +usb:v074Ep0002* + ID_MODEL_FROM_DATABASE=PS/2 Adapter + +usb:v0755* + ID_VENDOR_FROM_DATABASE=Aureal Semiconductor + +usb:v0757* + ID_VENDOR_FROM_DATABASE=Network Technologies, Inc. + +usb:v0758* + ID_VENDOR_FROM_DATABASE=Carl Zeiss Microscopy GmbH + +usb:v075B* + ID_VENDOR_FROM_DATABASE=Sophisticated Circuits, Inc. + +usb:v075Bp0001* + ID_MODEL_FROM_DATABASE=Kick-off! Watchdog + +usb:v0763* + ID_VENDOR_FROM_DATABASE=M-Audio + +usb:v0763p0115* + ID_MODEL_FROM_DATABASE=O2 / KeyRig 25 + +usb:v0763p0117* + ID_MODEL_FROM_DATABASE=Trigger Finger + +usb:v0763p0119* + ID_MODEL_FROM_DATABASE=MidAir + +usb:v0763p0150* + ID_MODEL_FROM_DATABASE=M-Audio Uno + +usb:v0763p0160* + ID_MODEL_FROM_DATABASE=M-Audio 1x1 + +usb:v0763p0192* + ID_MODEL_FROM_DATABASE=M-Audio Keystation 88es + +usb:v0763p0193* + ID_MODEL_FROM_DATABASE=ProKeys 88 + +usb:v0763p0194* + ID_MODEL_FROM_DATABASE=ProKeys 88sx + +usb:v0763p0195* + ID_MODEL_FROM_DATABASE=Oxygen 8 v2 + +usb:v0763p0196* + ID_MODEL_FROM_DATABASE=Oxygen 49 + +usb:v0763p0197* + ID_MODEL_FROM_DATABASE=Oxygen 61 + +usb:v0763p0198* + ID_MODEL_FROM_DATABASE=Axiom 25 + +usb:v0763p0199* + ID_MODEL_FROM_DATABASE=Axiom 49 + +usb:v0763p019A* + ID_MODEL_FROM_DATABASE=Axiom 61 + +usb:v0763p019B* + ID_MODEL_FROM_DATABASE=KeyRig 49 + +usb:v0763p019C* + ID_MODEL_FROM_DATABASE=KeyStudio + +usb:v0763p1001* + ID_MODEL_FROM_DATABASE=MidiSport 2x2 + +usb:v0763p1002* + ID_MODEL_FROM_DATABASE=MidiSport 2x2 + +usb:v0763p1003* + ID_MODEL_FROM_DATABASE=MidiSport 2x2 + +usb:v0763p1010* + ID_MODEL_FROM_DATABASE=MidiSport 1x1 + +usb:v0763p1011* + ID_MODEL_FROM_DATABASE=MidiSport 1x1 + +usb:v0763p1014* + ID_MODEL_FROM_DATABASE=M-Audio Keystation Loader + +usb:v0763p1015* + ID_MODEL_FROM_DATABASE=M-Audio Keystation + +usb:v0763p1020* + ID_MODEL_FROM_DATABASE=Midisport 4x4 + +usb:v0763p1021* + ID_MODEL_FROM_DATABASE=MidiSport 4x4 + +usb:v0763p1030* + ID_MODEL_FROM_DATABASE=M-Audio MIDISPORT 8x8 + +usb:v0763p1031* + ID_MODEL_FROM_DATABASE=MidiSport 8x8/s Loader + +usb:v0763p1033* + ID_MODEL_FROM_DATABASE=MidiSport 8x8/s + +usb:v0763p1040* + ID_MODEL_FROM_DATABASE=M-Audio MidiSport 2x4 Loader + +usb:v0763p1041* + ID_MODEL_FROM_DATABASE=M-Audio MidiSport 2x4 + +usb:v0763p1110* + ID_MODEL_FROM_DATABASE=MidiSport 1x1 + +usb:v0763p2001* + ID_MODEL_FROM_DATABASE=M Audio Quattro + +usb:v0763p2002* + ID_MODEL_FROM_DATABASE=M Audio Duo + +usb:v0763p2003* + ID_MODEL_FROM_DATABASE=M Audio AudioPhile + +usb:v0763p2004* + ID_MODEL_FROM_DATABASE=M-Audio MobilePre + +usb:v0763p2006* + ID_MODEL_FROM_DATABASE=M-Audio Transit + +usb:v0763p2007* + ID_MODEL_FROM_DATABASE=M-Audio Sonica Theater + +usb:v0763p2008* + ID_MODEL_FROM_DATABASE=M-Audio Ozone + +usb:v0763p200D* + ID_MODEL_FROM_DATABASE=M-Audio OmniStudio + +usb:v0763p200F* + ID_MODEL_FROM_DATABASE=M-Audio MobilePre + +usb:v0763p2010* + ID_MODEL_FROM_DATABASE=M-Audio Fast Track + +usb:v0763p2012* + ID_MODEL_FROM_DATABASE=M-Audio Fast Track Pro + +usb:v0763p2013* + ID_MODEL_FROM_DATABASE=M-Audio JamLab + +usb:v0763p2015* + ID_MODEL_FROM_DATABASE=M-Audio RunTime DFU + +usb:v0763p2016* + ID_MODEL_FROM_DATABASE=M-Audio RunTime DFU + +usb:v0763p2019* + ID_MODEL_FROM_DATABASE=M-Audio Ozone Academic + +usb:v0763p201A* + ID_MODEL_FROM_DATABASE=M-Audio Micro + +usb:v0763p201B* + ID_MODEL_FROM_DATABASE=M-Audio RunTime DFU + +usb:v0763p201D* + ID_MODEL_FROM_DATABASE=M-Audio Producer + +usb:v0763p2024* + ID_MODEL_FROM_DATABASE=M-Audio Fast Track MKII + +usb:v0763p2080* + ID_MODEL_FROM_DATABASE=M-Audio Fast Track Ultra + +usb:v0763p2081* + ID_MODEL_FROM_DATABASE=M-Audio RunTime DFU / Fast Track Ultra 8R + +usb:v0763p2803* + ID_MODEL_FROM_DATABASE=M-Audio Audiophile DFU + +usb:v0763p2804* + ID_MODEL_FROM_DATABASE=M-Audio MobilePre DFU + +usb:v0763p2806* + ID_MODEL_FROM_DATABASE=M-Audio Transit DFU + +usb:v0763p2815* + ID_MODEL_FROM_DATABASE=M-Audio DFU + +usb:v0763p2816* + ID_MODEL_FROM_DATABASE=M-Audio DFU + +usb:v0763p281B* + ID_MODEL_FROM_DATABASE=M-Audio DFU + +usb:v0763p2880* + ID_MODEL_FROM_DATABASE=M-Audio DFU + +usb:v0763p2881* + ID_MODEL_FROM_DATABASE=M-Audio DFU + +usb:v0764* + ID_VENDOR_FROM_DATABASE=Cyber Power System, Inc. + +usb:v0764p0005* + ID_MODEL_FROM_DATABASE=Cyber Power UPS + +usb:v0764p0501* + ID_MODEL_FROM_DATABASE=CP1500 AVR UPS + +usb:v0764p0601* + ID_MODEL_FROM_DATABASE=PR1500LCDRT2U UPS + +usb:v0765* + ID_VENDOR_FROM_DATABASE=X-Rite, Inc. + +usb:v0765p5001* + ID_MODEL_FROM_DATABASE=Huey PRO Colorimeter + +usb:v0765p5010* + ID_MODEL_FROM_DATABASE=X-Rite Pantone Color Sensor + +usb:v0765p5020* + ID_MODEL_FROM_DATABASE=i1 Display Pro + +usb:v0765p6003* + ID_MODEL_FROM_DATABASE=ColorMunki Smile + +usb:v0765pD094* + ID_MODEL_FROM_DATABASE=X-Rite DTP94 [Quato Silver Haze Pro] + +usb:v0766* + ID_VENDOR_FROM_DATABASE=Jess-Link Products Co., Ltd + +usb:v0766p001B* + ID_MODEL_FROM_DATABASE=Packard Bell Go + +usb:v0766p0204* + ID_MODEL_FROM_DATABASE=TopSpeed Cyberlink Remote Control + +usb:v0767* + ID_VENDOR_FROM_DATABASE=Tokheim Corp. + +usb:v0768* + ID_VENDOR_FROM_DATABASE=Camtel Technology Corp. + +usb:v0768p0006* + ID_MODEL_FROM_DATABASE=Camtel Technology USB TV Genie Pro FM Model TVB330 + +usb:v0768p0023* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v0769* + ID_VENDOR_FROM_DATABASE=Surecom Technology Corp. + +usb:v0769p11F2* + ID_MODEL_FROM_DATABASE=EP-9001-g 802.11g 54M WLAN Adapter + +usb:v0769p11F3* + ID_MODEL_FROM_DATABASE=RT2570 + +usb:v0769p11F7* + ID_MODEL_FROM_DATABASE=802.11g 54M WLAN Adapter + +usb:v0769p31F3* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v076A* + ID_VENDOR_FROM_DATABASE=Smart Technology Enablers, Inc. + +usb:v076B* + ID_VENDOR_FROM_DATABASE=OmniKey AG + +usb:v076Bp0596* + ID_MODEL_FROM_DATABASE=CardMan 2020 + +usb:v076Bp1021* + ID_MODEL_FROM_DATABASE=CardMan 1021 + +usb:v076Bp1221* + ID_MODEL_FROM_DATABASE=CardMan 1221 + +usb:v076Bp1784* + ID_MODEL_FROM_DATABASE=CardMan 6020 + +usb:v076Bp3021* + ID_MODEL_FROM_DATABASE=CardMan 3121 + +usb:v076Bp3022* + ID_MODEL_FROM_DATABASE=CardMan 3021 + +usb:v076Bp3610* + ID_MODEL_FROM_DATABASE=CardMan 3620 + +usb:v076Bp3621* + ID_MODEL_FROM_DATABASE=CardMan 3621 + +usb:v076Bp3821* + ID_MODEL_FROM_DATABASE=CardMan 3821 + +usb:v076Bp4321* + ID_MODEL_FROM_DATABASE=CardMan 4321 + +usb:v076Bp5121* + ID_MODEL_FROM_DATABASE=CardMan 5121 + +usb:v076Bp5125* + ID_MODEL_FROM_DATABASE=CardMan 5125 + +usb:v076Bp5321* + ID_MODEL_FROM_DATABASE=CardMan 5321 + +usb:v076Bp5340* + ID_MODEL_FROM_DATABASE=CardMan 5021 CL + +usb:v076Bp6622* + ID_MODEL_FROM_DATABASE=CardMan 6121 + +usb:v076BpA011* + ID_MODEL_FROM_DATABASE=CCID Smart Card Reader Keyboard + +usb:v076BpA021* + ID_MODEL_FROM_DATABASE=CCID Smart Card Reader + +usb:v076BpA022* + ID_MODEL_FROM_DATABASE=CardMan Smart@Link + +usb:v076BpC000* + ID_MODEL_FROM_DATABASE=CardMan 3x21 CS + +usb:v076BpC001* + ID_MODEL_FROM_DATABASE=CardMan 5121 CS + +usb:v076C* + ID_VENDOR_FROM_DATABASE=Partner Tech + +usb:v076D* + ID_VENDOR_FROM_DATABASE=Denso Corp. + +usb:v076E* + ID_VENDOR_FROM_DATABASE=Kuan Tech Enterprise Co., Ltd + +usb:v076F* + ID_VENDOR_FROM_DATABASE=Jhen Vei Electronic Co., Ltd + +usb:v0770* + ID_VENDOR_FROM_DATABASE=Welch Allyn, Inc - Medical Division + +usb:v0771* + ID_VENDOR_FROM_DATABASE=Observator Instruments BV + +usb:v0771p4455* + ID_MODEL_FROM_DATABASE=OMC45III + +usb:v0771pAE0F* + ID_MODEL_FROM_DATABASE=OMC45III + +usb:v0772* + ID_VENDOR_FROM_DATABASE=Your data Our Care + +usb:v0774* + ID_VENDOR_FROM_DATABASE=AmTRAN Technology Co., Ltd + +usb:v0775* + ID_VENDOR_FROM_DATABASE=Longshine Electronics Corp. + +usb:v0776* + ID_VENDOR_FROM_DATABASE=Inalways Corp. + +usb:v0777* + ID_VENDOR_FROM_DATABASE=Comda Enterprise Corp. + +usb:v0778* + ID_VENDOR_FROM_DATABASE=Volex, Inc. + +usb:v0779* + ID_VENDOR_FROM_DATABASE=Fairchild Semiconductor + +usb:v077A* + ID_VENDOR_FROM_DATABASE=Sankyo Seiki Mfg. Co., Ltd + +usb:v077B* + ID_VENDOR_FROM_DATABASE=Linksys + +usb:v077Bp08BE* + ID_MODEL_FROM_DATABASE=BEFCMU10 v4 Cable Modem + +usb:v077Bp2219* + ID_MODEL_FROM_DATABASE=WUSB11 V2.6 802.11b Adapter + +usb:v077Bp2226* + ID_MODEL_FROM_DATABASE=USB200M 100baseTX Adapter + +usb:v077Bp2227* + ID_MODEL_FROM_DATABASE=Network Everywhere NWU11B + +usb:v077C* + ID_VENDOR_FROM_DATABASE=Forward Electronics Co., Ltd + +usb:v077Cp0005* + ID_MODEL_FROM_DATABASE=NEC Keyboard + +usb:v077D* + ID_VENDOR_FROM_DATABASE=Griffin Technology + +usb:v077Dp0223* + ID_MODEL_FROM_DATABASE=IMic Audio In/Out + +usb:v077Dp0405* + ID_MODEL_FROM_DATABASE=iMate, ADB Adapter + +usb:v077Dp0410* + ID_MODEL_FROM_DATABASE=PowerMate + +usb:v077Dp041A* + ID_MODEL_FROM_DATABASE=PowerWave + +usb:v077Dp04AA* + ID_MODEL_FROM_DATABASE=SoundKnob + +usb:v077Dp07AF* + ID_MODEL_FROM_DATABASE=iMic + +usb:v077Dp1016* + ID_MODEL_FROM_DATABASE=AirClick + +usb:v077Dp627A* + ID_MODEL_FROM_DATABASE=Radio SHARK + +usb:v077F* + ID_VENDOR_FROM_DATABASE=Well Excellent & Most Corp. + +usb:v0780* + ID_VENDOR_FROM_DATABASE=Sagem Monetel GmbH + +usb:v0780p1202* + ID_MODEL_FROM_DATABASE=ORGA 900 Smart Card Terminal Virtual Com Port + +usb:v0780p1302* + ID_MODEL_FROM_DATABASE=ORGA 6000 Smart Card Terminal Virtual Com Port + +usb:v0780p1303* + ID_MODEL_FROM_DATABASE=ORGA 6000 Smart Card Terminal USB RNDIS + +usb:v0780pDF55* + ID_MODEL_FROM_DATABASE=ORGA 900/6000 Smart Card Terminal DFU + +usb:v0781* + ID_VENDOR_FROM_DATABASE=SanDisk Corp. + +usb:v0781p0001* + ID_MODEL_FROM_DATABASE=SDDR-05a ImageMate CompactFlash Reader + +usb:v0781p0002* + ID_MODEL_FROM_DATABASE=SDDR-31 ImageMate II CompactFlash Reader + +usb:v0781p0005* + ID_MODEL_FROM_DATABASE=SDDR-05b (CF II) ImageMate CompactFlash Reader + +usb:v0781p0100* + ID_MODEL_FROM_DATABASE=ImageMate SDDR-12 + +usb:v0781p0200* + ID_MODEL_FROM_DATABASE=SDDR-09 (SSFDC) ImageMate SmartMedia Reader [eusb] + +usb:v0781p0400* + ID_MODEL_FROM_DATABASE=SecureMate SD/MMC Reader + +usb:v0781p0621* + ID_MODEL_FROM_DATABASE=SDDR-86 Imagemate 6-in-1 Reader + +usb:v0781p0720* + ID_MODEL_FROM_DATABASE=Sansa C200 series in recovery mode + +usb:v0781p0729* + ID_MODEL_FROM_DATABASE=Sansa E200 series in recovery mode + +usb:v0781p0810* + ID_MODEL_FROM_DATABASE=SDDR-75 ImageMate CF-SM Reader + +usb:v0781p0830* + ID_MODEL_FROM_DATABASE=ImageMate CF/MMC/SD Reader + +usb:v0781p1234* + ID_MODEL_FROM_DATABASE=Cruzer Mini Flash Drive + +usb:v0781p5150* + ID_MODEL_FROM_DATABASE=SDCZ2 Cruzer Mini Flash Drive (thin) + +usb:v0781p5151* + ID_MODEL_FROM_DATABASE=Cruzer Micro Flash Drive + +usb:v0781p5153* + ID_MODEL_FROM_DATABASE=Cruzer Flash Drive + +usb:v0781p5204* + ID_MODEL_FROM_DATABASE=Cruzer Crossfire + +usb:v0781p5402* + ID_MODEL_FROM_DATABASE=U3 Cruzer Micro + +usb:v0781p5406* + ID_MODEL_FROM_DATABASE=Cruzer Micro U3 + +usb:v0781p5408* + ID_MODEL_FROM_DATABASE=Cruzer Titanium U3 + +usb:v0781p540E* + ID_MODEL_FROM_DATABASE=Cruzer Contour Flash Drive + +usb:v0781p5530* + ID_MODEL_FROM_DATABASE=Cruzer + +usb:v0781p5567* + ID_MODEL_FROM_DATABASE=Cruzer Blade + +usb:v0781p556B* + ID_MODEL_FROM_DATABASE=Cruzer Edge + +usb:v0781p556C* + ID_MODEL_FROM_DATABASE=Ultra + +usb:v0781p556D* + ID_MODEL_FROM_DATABASE=Memory Vault + +usb:v0781p5571* + ID_MODEL_FROM_DATABASE=Cruzer Fit + +usb:v0781p5575* + ID_MODEL_FROM_DATABASE=Cruzer Glide + +usb:v0781p5576* + ID_MODEL_FROM_DATABASE=Cruzer Facet + +usb:v0781p5577* + ID_MODEL_FROM_DATABASE=Cruzer Pop (8GB) + +usb:v0781p557D* + ID_MODEL_FROM_DATABASE=Cruzer Force (64GB) + +usb:v0781p5580* + ID_MODEL_FROM_DATABASE=SDCZ80 Flash Drive + +usb:v0781p5581* + ID_MODEL_FROM_DATABASE=Ultra + +usb:v0781p5583* + ID_MODEL_FROM_DATABASE=Ultra Fit + +usb:v0781p5590* + ID_MODEL_FROM_DATABASE=Ultra Dual + +usb:v0781p5591* + ID_MODEL_FROM_DATABASE=Ultra Flair + +usb:v0781p5E10* + ID_MODEL_FROM_DATABASE=Encrypted + +usb:v0781p6100* + ID_MODEL_FROM_DATABASE=Ultra II SD Plus 2GB + +usb:v0781p7100* + ID_MODEL_FROM_DATABASE=Cruzer Mini + +usb:v0781p7101* + ID_MODEL_FROM_DATABASE=Pen Flash + +usb:v0781p7102* + ID_MODEL_FROM_DATABASE=Cruzer Mini + +usb:v0781p7103* + ID_MODEL_FROM_DATABASE=Cruzer Mini + +usb:v0781p7104* + ID_MODEL_FROM_DATABASE=Cruzer Micro Mini 256MB Flash Drive + +usb:v0781p7105* + ID_MODEL_FROM_DATABASE=Cruzer Mini + +usb:v0781p7106* + ID_MODEL_FROM_DATABASE=Cruzer Mini + +usb:v0781p7112* + ID_MODEL_FROM_DATABASE=Cruzer Micro 128MB Flash Drive + +usb:v0781p7113* + ID_MODEL_FROM_DATABASE=Cruzer Micro 256MB Flash Drive + +usb:v0781p7114* + ID_MODEL_FROM_DATABASE=Cruzer Mini + +usb:v0781p7115* + ID_MODEL_FROM_DATABASE=Cruzer Mini + +usb:v0781p7301* + ID_MODEL_FROM_DATABASE=Sansa e100 series (mtp) + +usb:v0781p7302* + ID_MODEL_FROM_DATABASE=Sansa e100 series (msc) + +usb:v0781p7400* + ID_MODEL_FROM_DATABASE=Sansa M200 series (mtp) + +usb:v0781p7401* + ID_MODEL_FROM_DATABASE=Sansa M200 series (msc) + +usb:v0781p7420* + ID_MODEL_FROM_DATABASE=Sansa E200 series (mtp) + +usb:v0781p7421* + ID_MODEL_FROM_DATABASE=Sansa E200 Series (msc) + +usb:v0781p7422* + ID_MODEL_FROM_DATABASE=Sansa E200 series v2 (mtp) + +usb:v0781p7423* + ID_MODEL_FROM_DATABASE=Sansa E200 series v2 (msc) + +usb:v0781p7430* + ID_MODEL_FROM_DATABASE=Sansa M200 series + +usb:v0781p7431* + ID_MODEL_FROM_DATABASE=Sansa M200 series V4 (msc) + +usb:v0781p7432* + ID_MODEL_FROM_DATABASE=Sansa Clip (mtp) + +usb:v0781p7433* + ID_MODEL_FROM_DATABASE=Sansa Clip (msc) + +usb:v0781p7434* + ID_MODEL_FROM_DATABASE=Sansa Clip V2 (mtp) + +usb:v0781p7435* + ID_MODEL_FROM_DATABASE=Sansa Clip V2 (msc) + +usb:v0781p7450* + ID_MODEL_FROM_DATABASE=Sansa C250 + +usb:v0781p7451* + ID_MODEL_FROM_DATABASE=Sansa C240 + +usb:v0781p7460* + ID_MODEL_FROM_DATABASE=Sansa Express + +usb:v0781p7480* + ID_MODEL_FROM_DATABASE=Sansa Connect + +usb:v0781p7481* + ID_MODEL_FROM_DATABASE=Sansa Connect (in recovery mode) + +usb:v0781p74B0* + ID_MODEL_FROM_DATABASE=Sansa View (msc) + +usb:v0781p74B1* + ID_MODEL_FROM_DATABASE=Sansa View (mtp) + +usb:v0781p74C0* + ID_MODEL_FROM_DATABASE=Sansa Fuze (mtp) + +usb:v0781p74C1* + ID_MODEL_FROM_DATABASE=Sansa Fuze (msc) + +usb:v0781p74C2* + ID_MODEL_FROM_DATABASE=Sansa Fuze V2 (mtp) + +usb:v0781p74C3* + ID_MODEL_FROM_DATABASE=Sansa Fuze V2 (msc) + +usb:v0781p74D0* + ID_MODEL_FROM_DATABASE=Sansa Clip+ (mtp) + +usb:v0781p74D1* + ID_MODEL_FROM_DATABASE=Sansa Clip+ (msc) + +usb:v0781p74E5* + ID_MODEL_FROM_DATABASE=Sansa Clip Zip + +usb:v0781p8181* + ID_MODEL_FROM_DATABASE=Pen Flash + +usb:v0781p8183* + ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device + +usb:v0781p8185* + ID_MODEL_FROM_DATABASE=SDCZ2 Cruzer Mini Flash Drive (older, thick) + +usb:v0781p8888* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v0781p8889* + ID_MODEL_FROM_DATABASE=SDDR-88 Imagemate 8-in-1 Reader + +usb:v0781p8919* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v0781p8989* + ID_MODEL_FROM_DATABASE=ImageMate 12-in-1 Reader + +usb:v0781p9191* + ID_MODEL_FROM_DATABASE=ImageMate CF + +usb:v0781p9219* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v0781p9292* + ID_MODEL_FROM_DATABASE=ImageMate CF Reader/Writer + +usb:v0781p9393* + ID_MODEL_FROM_DATABASE=ImageMate SD-MMC + +usb:v0781p9595* + ID_MODEL_FROM_DATABASE=ImageMate xD-SM + +usb:v0781p9797* + ID_MODEL_FROM_DATABASE=ImageMate MS-PRO + +usb:v0781p9919* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v0781p9999* + ID_MODEL_FROM_DATABASE=SDDR-99 5-in-1 Reader + +usb:v0781pA7C1* + ID_MODEL_FROM_DATABASE=Storage device (SD card reader) + +usb:v0781pA7E8* + ID_MODEL_FROM_DATABASE=SDDR-113 MicroMate SDHC Reader + +usb:v0781pB2B3* + ID_MODEL_FROM_DATABASE=SDDR-103 MobileMate SD+ Reader + +usb:v0781pB4B5* + ID_MODEL_FROM_DATABASE=SDDR-89 V4 ImageMate 12-in-1 Reader + +usb:v0781pB6BA* + ID_MODEL_FROM_DATABASE=CF SDDR-289 + +usb:v0782* + ID_VENDOR_FROM_DATABASE=Trackerball + +usb:v0783* + ID_VENDOR_FROM_DATABASE=C3PO + +usb:v0783p0003* + ID_MODEL_FROM_DATABASE=LTC31 SmartCard Reader + +usb:v0783p0006* + ID_MODEL_FROM_DATABASE=LTC31v2 + +usb:v0783p0009* + ID_MODEL_FROM_DATABASE=KBR36 + +usb:v0783p0010* + ID_MODEL_FROM_DATABASE=LTC32 + +usb:v0784* + ID_VENDOR_FROM_DATABASE=Vivitar, Inc. + +usb:v0784p0100* + ID_MODEL_FROM_DATABASE=Vivicam 2655 + +usb:v0784p1310* + ID_MODEL_FROM_DATABASE=Vivicam 3305 + +usb:v0784p1688* + ID_MODEL_FROM_DATABASE=Vivicam 3665 + +usb:v0784p1689* + ID_MODEL_FROM_DATABASE=Gateway DC-M42/Labtec DC-505/Vivitar Vivicam 3705 + +usb:v0784p2620* + ID_MODEL_FROM_DATABASE=AOL Photocam Plus + +usb:v0784p2888* + ID_MODEL_FROM_DATABASE=Polaroid DC700 + +usb:v0784p3330* + ID_MODEL_FROM_DATABASE=Nytec ND-3200 Camera + +usb:v0784p4300* + ID_MODEL_FROM_DATABASE=Traveler D1 + +usb:v0784p5260* + ID_MODEL_FROM_DATABASE=Werlisa Sport PX 100 / JVC GC-A33 Camera + +usb:v0784p5300* + ID_MODEL_FROM_DATABASE=Pretec dc530 + +usb:v0785* + ID_VENDOR_FROM_DATABASE=NTT-ME + +usb:v0785p0001* + ID_MODEL_FROM_DATABASE=MN128mini-V ISDN TA + +usb:v0785p0003* + ID_MODEL_FROM_DATABASE=MN128mini-J ISDN TA + +usb:v0789* + ID_VENDOR_FROM_DATABASE=Logitec Corp. + +usb:v0789p0026* + ID_MODEL_FROM_DATABASE=LHD Device + +usb:v0789p0033* + ID_MODEL_FROM_DATABASE=DVD Multi-plus unit LDR-H443SU2 + +usb:v0789p0063* + ID_MODEL_FROM_DATABASE=LDR Device + +usb:v0789p0064* + ID_MODEL_FROM_DATABASE=LDR-R Device + +usb:v0789p00B3* + ID_MODEL_FROM_DATABASE=DVD Multi-plus unit LDR-H443U2 + +usb:v0789p0105* + ID_MODEL_FROM_DATABASE=LAN-TX/U1H2 10/100 Ethernet Adapter [pegasus II] + +usb:v0789p010C* + ID_MODEL_FROM_DATABASE=Realtek RTL8187 Wireless 802.11g 54Mbps Network Adapter + +usb:v0789p0160* + ID_MODEL_FROM_DATABASE=LAN-GTJ/U2A + +usb:v0789p0162* + ID_MODEL_FROM_DATABASE=LAN-WN22/U2 Wireless LAN Adapter + +usb:v0789p0163* + ID_MODEL_FROM_DATABASE=LAN-WN12/U2 Wireless LAN Adapter + +usb:v0789p0164* + ID_MODEL_FROM_DATABASE=LAN-W150/U2M Wireless LAN Adapter + +usb:v0789p0166* + ID_MODEL_FROM_DATABASE=LAN-W300N/U2 Wireless LAN Adapter + +usb:v0789p0168* + ID_MODEL_FROM_DATABASE=LAN-W150N/U2 Wireless LAN Adapter + +usb:v0789p0170* + ID_MODEL_FROM_DATABASE=LAN-W300AN/U2 Wireless LAN Adapter + +usb:v078B* + ID_VENDOR_FROM_DATABASE=Happ Controls, Inc. + +usb:v078Bp0010* + ID_MODEL_FROM_DATABASE=Driving UGCI + +usb:v078Bp0020* + ID_MODEL_FROM_DATABASE=Flying UGCI + +usb:v078Bp0030* + ID_MODEL_FROM_DATABASE=Fighting UGCI + +usb:v078C* + ID_VENDOR_FROM_DATABASE=GTCO/CalComp + +usb:v078Cp0090* + ID_MODEL_FROM_DATABASE=Tablet Adapter + +usb:v078Cp0100* + ID_MODEL_FROM_DATABASE=Tablet Adapter + +usb:v078Cp0200* + ID_MODEL_FROM_DATABASE=Tablet Adapter + +usb:v078Cp0300* + ID_MODEL_FROM_DATABASE=Tablet Adapter + +usb:v078Cp0400* + ID_MODEL_FROM_DATABASE=Digitizer (Whiteboard) + +usb:v078E* + ID_VENDOR_FROM_DATABASE=Brincom, Inc. + +usb:v0790* + ID_VENDOR_FROM_DATABASE=Pro-Image Manufacturing Co., Ltd + +usb:v0791* + ID_VENDOR_FROM_DATABASE=Copartner Wire and Cable Mfg. Corp. + +usb:v0792* + ID_VENDOR_FROM_DATABASE=Axis Communications AB + +usb:v0793* + ID_VENDOR_FROM_DATABASE=Wha Yu Industrial Co., Ltd + +usb:v0794* + ID_VENDOR_FROM_DATABASE=ABL Electronics Corp. + +usb:v0795* + ID_VENDOR_FROM_DATABASE=RealChip, Inc. + +usb:v0796* + ID_VENDOR_FROM_DATABASE=Certicom Corp. + +usb:v0797* + ID_VENDOR_FROM_DATABASE=Grandtech Semiconductor Corp. + +usb:v0797p6801* + ID_MODEL_FROM_DATABASE=Flatbed Scanner + +usb:v0797p6802* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v0797p8001* + ID_MODEL_FROM_DATABASE=SmartCam + +usb:v0797p801A* + ID_MODEL_FROM_DATABASE=Typhoon StyloCam + +usb:v0797p801C* + ID_MODEL_FROM_DATABASE=Meade Binoculars/Camera + +usb:v0797p8901* + ID_MODEL_FROM_DATABASE=ScanHex SX-35a + +usb:v0797p8909* + ID_MODEL_FROM_DATABASE=ScanHex SX-35b + +usb:v0797p8911* + ID_MODEL_FROM_DATABASE=ScanHex SX-35c + +usb:v0798* + ID_VENDOR_FROM_DATABASE=Optelec + +usb:v0798p0001* + ID_MODEL_FROM_DATABASE=Braille Voyager + +usb:v0798p0640* + ID_MODEL_FROM_DATABASE=BC640 + +usb:v0798p0680* + ID_MODEL_FROM_DATABASE=BC680 + +usb:v0799* + ID_VENDOR_FROM_DATABASE=Altera + +usb:v0799p7651* + ID_MODEL_FROM_DATABASE=Programming Unit + +usb:v079B* + ID_VENDOR_FROM_DATABASE=Sagem + +usb:v079Bp0024* + ID_MODEL_FROM_DATABASE=MSO300/MSO301 Fingerprint Sensor + +usb:v079Bp0026* + ID_MODEL_FROM_DATABASE=MSO350/MSO351 Fingerprint Sensor & SmartCard Reader + +usb:v079Bp0027* + ID_MODEL_FROM_DATABASE=USB-Serial Controller + +usb:v079Bp002F* + ID_MODEL_FROM_DATABASE=Mobile + +usb:v079Bp0030* + ID_MODEL_FROM_DATABASE=Mobile Communication Device + +usb:v079Bp0042* + ID_MODEL_FROM_DATABASE=Mobile + +usb:v079Bp0047* + ID_MODEL_FROM_DATABASE=CBM/MSO1300 Fingerprint Sensor + +usb:v079Bp004A* + ID_MODEL_FROM_DATABASE=XG-760A 802.11bg + +usb:v079Bp004B* + ID_MODEL_FROM_DATABASE=Wi-Fi 11g adapter + +usb:v079Bp0052* + ID_MODEL_FROM_DATABASE=MSO1350 Fingerprint Sensor & SmartCard Reader + +usb:v079Bp0056* + ID_MODEL_FROM_DATABASE=Agfa AP1100 Photo Printer + +usb:v079Bp005D* + ID_MODEL_FROM_DATABASE=Mobile Mass Storage + +usb:v079Bp0062* + ID_MODEL_FROM_DATABASE=XG-76NA 802.11bg + +usb:v079Bp0078* + ID_MODEL_FROM_DATABASE=Laser Pro Monochrome MFP + +usb:v079D* + ID_VENDOR_FROM_DATABASE=Alfadata Computer Corp. + +usb:v079Dp0201* + ID_MODEL_FROM_DATABASE=GamePort Adapter + +usb:v07A1* + ID_VENDOR_FROM_DATABASE=Digicom S.p.A. + +usb:v07A1pD952* + ID_MODEL_FROM_DATABASE=Palladio USB V.92 Modem + +usb:v07A2* + ID_VENDOR_FROM_DATABASE=National Technical Systems + +usb:v07A3* + ID_VENDOR_FROM_DATABASE=Onnto Corp. + +usb:v07A4* + ID_VENDOR_FROM_DATABASE=Be, Inc. + +usb:v07A6* + ID_VENDOR_FROM_DATABASE=ADMtek, Inc. + +usb:v07A6p07C2* + ID_MODEL_FROM_DATABASE=AN986A Ethernet + +usb:v07A6p0986* + ID_MODEL_FROM_DATABASE=AN986 Pegasus Ethernet + +usb:v07A6p8266* + ID_MODEL_FROM_DATABASE=Infineon WildCard-USB Wireless LAN Adapter + +usb:v07A6p8511* + ID_MODEL_FROM_DATABASE=ADM8511 Pegasus II Ethernet + +usb:v07A6p8513* + ID_MODEL_FROM_DATABASE=AN8513 Ethernet + +usb:v07A6p8515* + ID_MODEL_FROM_DATABASE=AN8515 Ethernet + +usb:v07AA* + ID_VENDOR_FROM_DATABASE=Corega K.K. + +usb:v07AAp0001* + ID_MODEL_FROM_DATABASE=Ether USB-T Ethernet [klsi] + +usb:v07AAp0004* + ID_MODEL_FROM_DATABASE=FEther USB-TX Ethernet [pegasus] + +usb:v07AAp000C* + ID_MODEL_FROM_DATABASE=WirelessLAN USB-11 + +usb:v07AAp000D* + ID_MODEL_FROM_DATABASE=FEther USB-TXS + +usb:v07AAp0011* + ID_MODEL_FROM_DATABASE=Wireless LAN USB-11 mini + +usb:v07AAp0012* + ID_MODEL_FROM_DATABASE=Stick-11 802.11b Adapter + +usb:v07AAp0017* + ID_MODEL_FROM_DATABASE=FEther USB2-TX + +usb:v07AAp0018* + ID_MODEL_FROM_DATABASE=Wireless LAN USB-11 mini 2 + +usb:v07AAp001A* + ID_MODEL_FROM_DATABASE=ULUSB-11 Key + +usb:v07AAp001C* + ID_MODEL_FROM_DATABASE=CG-WLUSB2GT 802.11g Wireless Adapter [Intersil ISL3880] + +usb:v07AAp0020* + ID_MODEL_FROM_DATABASE=CG-WLUSB2GTST 802.11g Wireless Adapter [Intersil ISL3887] + +usb:v07AAp002E* + ID_MODEL_FROM_DATABASE=CG-WLUSB2GPX [Ralink RT2571W] + +usb:v07AAp002F* + ID_MODEL_FROM_DATABASE=CG-WLUSB2GNL + +usb:v07AAp0031* + ID_MODEL_FROM_DATABASE=CG-WLUSB2GS 802.11bg [Atheros AR5523] + +usb:v07AAp003C* + ID_MODEL_FROM_DATABASE=CG-WLUSB2GNL + +usb:v07AAp003F* + ID_MODEL_FROM_DATABASE=CG-WLUSB300AGN + +usb:v07AAp0041* + ID_MODEL_FROM_DATABASE=CG-WLUSB300GNS + +usb:v07AAp0042* + ID_MODEL_FROM_DATABASE=CG-WLUSB300GNM + +usb:v07AAp0043* + ID_MODEL_FROM_DATABASE=CG-WLUSB300N rev A2 [Realtek RTL8192U] + +usb:v07AAp0047* + ID_MODEL_FROM_DATABASE=CG-WLUSBNM + +usb:v07AAp0051* + ID_MODEL_FROM_DATABASE=CG-WLUSB300NM + +usb:v07AAp7613* + ID_MODEL_FROM_DATABASE=Stick-11 V2 802.11b Adapter + +usb:v07AAp9601* + ID_MODEL_FROM_DATABASE=FEther USB-TXC + +usb:v07AB* + ID_VENDOR_FROM_DATABASE=Freecom Technologies + +usb:v07ABpFC01* + ID_MODEL_FROM_DATABASE=IDE bridge + +usb:v07ABpFC02* + ID_MODEL_FROM_DATABASE=Cable II USB-2 + +usb:v07ABpFC03* + ID_MODEL_FROM_DATABASE=USB2-IDE IDE bridge + +usb:v07ABpFCD6* + ID_MODEL_FROM_DATABASE=Freecom HD Classic + +usb:v07ABpFCF6* + ID_MODEL_FROM_DATABASE=DataBar + +usb:v07ABpFCF8* + ID_MODEL_FROM_DATABASE=Freecom Classic SL Network Drive + +usb:v07ABpFCFE* + ID_MODEL_FROM_DATABASE=Hard Drive 80GB + +usb:v07AF* + ID_VENDOR_FROM_DATABASE=Microtech + +usb:v07AFp0004* + ID_MODEL_FROM_DATABASE=SCSI-DB25 SCSI Bridge [shuttle] + +usb:v07AFp0005* + ID_MODEL_FROM_DATABASE=SCSI-HD50 SCSI Bridge [shuttle] + +usb:v07AFp0006* + ID_MODEL_FROM_DATABASE=CameraMate SmartMedia and CompactFlash Card Reader [eusb/shuttle] + +usb:v07AFpFC01* + ID_MODEL_FROM_DATABASE=Freecom USB-IDE + +usb:v07B0* + ID_VENDOR_FROM_DATABASE=Trust Technologies + +usb:v07B0p0001* + ID_MODEL_FROM_DATABASE=ISDN TA + +usb:v07B0p0002* + ID_MODEL_FROM_DATABASE=ISDN TA128 Plus + +usb:v07B0p0003* + ID_MODEL_FROM_DATABASE=ISDN TA128 Deluxe + +usb:v07B0p0005* + ID_MODEL_FROM_DATABASE=ISDN TA128 SE + +usb:v07B0p0006* + ID_MODEL_FROM_DATABASE=ISDN TA 128 [HFC-S] + +usb:v07B0p0007* + ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] + +usb:v07B0p0008* + ID_MODEL_FROM_DATABASE=ISDN TA + +usb:v07B1* + ID_VENDOR_FROM_DATABASE=IMP, Inc. + +usb:v07B2* + ID_VENDOR_FROM_DATABASE=Motorola BCS, Inc. + +usb:v07B2p0100* + ID_MODEL_FROM_DATABASE=SURFboard Voice over IP Cable Modem + +usb:v07B2p0900* + ID_MODEL_FROM_DATABASE=SURFboard Gateway + +usb:v07B2p0950* + ID_MODEL_FROM_DATABASE=SURFboard SBG950 Gateway + +usb:v07B2p1000* + ID_MODEL_FROM_DATABASE=SURFboard SBG1000 Gateway + +usb:v07B2p4100* + ID_MODEL_FROM_DATABASE=SurfBoard SB4100 Cable Modem + +usb:v07B2p4200* + ID_MODEL_FROM_DATABASE=SurfBoard SB4200 Cable Modem + +usb:v07B2p4210* + ID_MODEL_FROM_DATABASE=SurfBoard 4210 Cable Modem + +usb:v07B2p4220* + ID_MODEL_FROM_DATABASE=SURFboard SB4220 Cable Modem + +usb:v07B2p4500* + ID_MODEL_FROM_DATABASE=CG4500 Communications Gateway + +usb:v07B2p450B* + ID_MODEL_FROM_DATABASE=CG4501 Communications Gateway + +usb:v07B2p450E* + ID_MODEL_FROM_DATABASE=CG4500E Communications Gateway + +usb:v07B2p5100* + ID_MODEL_FROM_DATABASE=SurfBoard SB5100 Cable Modem + +usb:v07B2p5101* + ID_MODEL_FROM_DATABASE=SurfBoard SB5101 Cable Modem + +usb:v07B2p5120* + ID_MODEL_FROM_DATABASE=SurfBoard SB5120 Cable Modem (RNDIS) + +usb:v07B2p5121* + ID_MODEL_FROM_DATABASE=Surfboard 5121 Cable Modem + +usb:v07B2p7030* + ID_MODEL_FROM_DATABASE=WU830G 802.11bg Wireless Adapter [Envara WiND512] + +usb:v07B3* + ID_VENDOR_FROM_DATABASE=Plustek, Inc. + +usb:v07B3p0001* + ID_MODEL_FROM_DATABASE=OpticPro 1212U Scanner + +usb:v07B3p0003* + ID_MODEL_FROM_DATABASE=Scanner + +usb:v07B3p0010* + ID_MODEL_FROM_DATABASE=OpticPro U12 Scanner + +usb:v07B3p0011* + ID_MODEL_FROM_DATABASE=OpticPro U24 Scanner + +usb:v07B3p0013* + ID_MODEL_FROM_DATABASE=OpticPro UT12 Scanner + +usb:v07B3p0014* + ID_MODEL_FROM_DATABASE=Scanner + +usb:v07B3p0015* + ID_MODEL_FROM_DATABASE=OpticPro U24 Scanner + +usb:v07B3p0017* + ID_MODEL_FROM_DATABASE=OpticPro UT12/16/24 Scanner + +usb:v07B3p0204* + ID_MODEL_FROM_DATABASE=Scanner + +usb:v07B3p0400* + ID_MODEL_FROM_DATABASE=OpticPro 1248U Scanner + +usb:v07B3p0401* + ID_MODEL_FROM_DATABASE=OpticPro 1248U Scanner #2 + +usb:v07B3p0403* + ID_MODEL_FROM_DATABASE=OpticPro U16B Scanner + +usb:v07B3p0404* + ID_MODEL_FROM_DATABASE=Scanner + +usb:v07B3p0405* + ID_MODEL_FROM_DATABASE=A8 Namecard-s Controller + +usb:v07B3p0406* + ID_MODEL_FROM_DATABASE=A8 Namecard-D Controller + +usb:v07B3p0410* + ID_MODEL_FROM_DATABASE=Scanner + +usb:v07B3p0412* + ID_MODEL_FROM_DATABASE=Scanner + +usb:v07B3p0413* + ID_MODEL_FROM_DATABASE=OpticSlim 1200 Scanner + +usb:v07B3p0601* + ID_MODEL_FROM_DATABASE=OpticPro ST24 Scanner + +usb:v07B3p0800* + ID_MODEL_FROM_DATABASE=OpticPro ST48 Scanner + +usb:v07B3p0900* + ID_MODEL_FROM_DATABASE=OpticBook 3600 Scanner + +usb:v07B3p090C* + ID_MODEL_FROM_DATABASE=OpticBook 3600 Plus Scanner + +usb:v07B3p0A06* + ID_MODEL_FROM_DATABASE=TVcam VD100 + +usb:v07B3p0B00* + ID_MODEL_FROM_DATABASE=SmartPhoto F50 + +usb:v07B3p0C00* + ID_MODEL_FROM_DATABASE=OpticPro ST64 Scanner + +usb:v07B3p0C03* + ID_MODEL_FROM_DATABASE=OpticPro ST64+ Scanner + +usb:v07B3p0C04* + ID_MODEL_FROM_DATABASE=Optic Film 7200i scanner + +usb:v07B3p0C0C* + ID_MODEL_FROM_DATABASE=PL806 Scanner + +usb:v07B3p0C26* + ID_MODEL_FROM_DATABASE=OpticBook 4600 Scanner + +usb:v07B3p0C2B* + ID_MODEL_FROM_DATABASE=Mobile Office D428 Scanner + +usb:v07B3p0E08* + ID_MODEL_FROM_DATABASE=OpticBook A300 Scanner + +usb:v07B3p1300* + ID_MODEL_FROM_DATABASE=OpticBook 3800 Scanner + +usb:v07B3p1301* + ID_MODEL_FROM_DATABASE=OpticBook 4800 Scanner + +usb:v07B4* + ID_VENDOR_FROM_DATABASE=Olympus Optical Co., Ltd + +usb:v07B4p0100* + ID_MODEL_FROM_DATABASE=Camedia C-2100/C-3000 Ultra Zoom Camera + +usb:v07B4p0102* + ID_MODEL_FROM_DATABASE=Camedia E-10/C-220/C-50 Camera + +usb:v07B4p0105* + ID_MODEL_FROM_DATABASE=Camedia C-310Z/C-700/C-750UZ/C-755/C-765UZ/C-3040/C-4000/C-5050Z/D-560/C-3020Z Zoom Camera + +usb:v07B4p0109* + ID_MODEL_FROM_DATABASE=C-370Z/C-500Z/D-535Z/X-450 + +usb:v07B4p010A* + ID_MODEL_FROM_DATABASE=MAUSB-10 xD and SmartMedia Card Reader + +usb:v07B4p0112* + ID_MODEL_FROM_DATABASE=MAUSB-100 xD Card Reader + +usb:v07B4p0113* + ID_MODEL_FROM_DATABASE=Mju 500 / Stylus Digital Camera (PTP) + +usb:v07B4p0114* + ID_MODEL_FROM_DATABASE=C-350Z Camera + +usb:v07B4p0118* + ID_MODEL_FROM_DATABASE=Mju Mini Digital/Mju Digital 500 Camera / Stylus 850 SW + +usb:v07B4p0125* + ID_MODEL_FROM_DATABASE=Tough TG-1 Camera + +usb:v07B4p0126* + ID_MODEL_FROM_DATABASE=VR340/D750 Digital Camera + +usb:v07B4p0184* + ID_MODEL_FROM_DATABASE=P-S100 port + +usb:v07B4p0202* + ID_MODEL_FROM_DATABASE=Foot Switch RS-26 + +usb:v07B4p0203* + ID_MODEL_FROM_DATABASE=Digital Voice Recorder DW-90 + +usb:v07B4p0206* + ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-330 + +usb:v07B4p0207* + ID_MODEL_FROM_DATABASE=Digital Voice Recorder & Camera W-10 + +usb:v07B4p0209* + ID_MODEL_FROM_DATABASE=Digital Voice Recorder DM-20 + +usb:v07B4p020B* + ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-4000 + +usb:v07B4p020D* + ID_MODEL_FROM_DATABASE=Digital Voice Recorder VN-240PC + +usb:v07B4p0211* + ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-2300 + +usb:v07B4p0218* + ID_MODEL_FROM_DATABASE=Foot Switch RS-28 + +usb:v07B4p0244* + ID_MODEL_FROM_DATABASE=Digital Voice Recorder VN-8500PC + +usb:v07B4p024F* + ID_MODEL_FROM_DATABASE=Digital Voice Recorder DS-7000 + +usb:v07B4p0280* + ID_MODEL_FROM_DATABASE=m:robe 100 + +usb:v07B5* + ID_VENDOR_FROM_DATABASE=Mega World International, Ltd + +usb:v07B5p0017* + ID_MODEL_FROM_DATABASE=Joystick + +usb:v07B5p0213* + ID_MODEL_FROM_DATABASE=Thrustmaster Firestorm Digital 3 Gamepad + +usb:v07B5p0312* + ID_MODEL_FROM_DATABASE=Gamepad + +usb:v07B5p9902* + ID_MODEL_FROM_DATABASE=GamePad + +usb:v07B6* + ID_VENDOR_FROM_DATABASE=Marubun Corp. + +usb:v07B7* + ID_VENDOR_FROM_DATABASE=TIME Interconnect, Ltd + +usb:v07B8* + ID_VENDOR_FROM_DATABASE=AboCom Systems Inc + +usb:v07B8p110C* + ID_MODEL_FROM_DATABASE=XX1 + +usb:v07B8p1201* + ID_MODEL_FROM_DATABASE=IEEE 802.11b Adapter + +usb:v07B8p200C* + ID_MODEL_FROM_DATABASE=XX2 + +usb:v07B8p2573* + ID_MODEL_FROM_DATABASE=Wireless LAN Card + +usb:v07B8p2770* + ID_MODEL_FROM_DATABASE=802.11n/b/g Mini Wireless LAN USB2.0 Adapter + +usb:v07B8p2870* + ID_MODEL_FROM_DATABASE=802.11n/b/g Wireless LAN USB2.0 Adapter + +usb:v07B8p3070* + ID_MODEL_FROM_DATABASE=802.11n/b/g Mini Wireless LAN USB2.0 Adapter + +usb:v07B8p3071* + ID_MODEL_FROM_DATABASE=802.11n/b/g Mini Wireless LAN USB2.0 Adapter + +usb:v07B8p3072* + ID_MODEL_FROM_DATABASE=802.11n/b/g Mini Wireless LAN USB2.0 Adapter + +usb:v07B8p4000* + ID_MODEL_FROM_DATABASE=DU-E10 Ethernet [klsi] + +usb:v07B8p4002* + ID_MODEL_FROM_DATABASE=DU-E100 Ethernet [pegasus] + +usb:v07B8p4003* + ID_MODEL_FROM_DATABASE=1/10/100 Ethernet Adapter + +usb:v07B8p4004* + ID_MODEL_FROM_DATABASE=XX4 + +usb:v07B8p4007* + ID_MODEL_FROM_DATABASE=XX5 + +usb:v07B8p400B* + ID_MODEL_FROM_DATABASE=XX6 + +usb:v07B8p400C* + ID_MODEL_FROM_DATABASE=XX7 + +usb:v07B8p401A* + ID_MODEL_FROM_DATABASE=RTL8151 + +usb:v07B8p4102* + ID_MODEL_FROM_DATABASE=USB 1.1 10/100M Fast Ethernet Adapter + +usb:v07B8p4104* + ID_MODEL_FROM_DATABASE=XX9 + +usb:v07B8p420A* + ID_MODEL_FROM_DATABASE=UF200 Ethernet + +usb:v07B8p5301* + ID_MODEL_FROM_DATABASE=GW-US54ZGL 802.11bg + +usb:v07B8p6001* + ID_MODEL_FROM_DATABASE=WUG2690 802.11bg Wireless Module [ZyDAS ZD1211+AL2230] + +usb:v07B8p8188* + ID_MODEL_FROM_DATABASE=AboCom Systems Inc [WN2001 Prolink Wireless-N Nano Adapter] + +usb:v07B8pA001* + ID_MODEL_FROM_DATABASE=WUG2200 802.11g Wireless Adapter [Envara WiND512] + +usb:v07B8pABC1* + ID_MODEL_FROM_DATABASE=DU-E10 Ethernet [pegasus] + +usb:v07B8pB000* + ID_MODEL_FROM_DATABASE=BWU613 + +usb:v07B8pB02A* + ID_MODEL_FROM_DATABASE=AboCom Bluetooth Device + +usb:v07B8pB02B* + ID_MODEL_FROM_DATABASE=Bluetooth dongle + +usb:v07B8pB02C* + ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter + +usb:v07B8pB02D* + ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter + +usb:v07B8pB02E* + ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter + +usb:v07B8pB030* + ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter + +usb:v07B8pB031* + ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter + +usb:v07B8pB032* + ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter + +usb:v07B8pB033* + ID_MODEL_FROM_DATABASE=BCM92045DG-Flash with trace filter + +usb:v07B8pB21A* + ID_MODEL_FROM_DATABASE=WUG2400 802.11g Wireless Adapter [Texas Instruments TNETW1450] + +usb:v07B8pB21B* + ID_MODEL_FROM_DATABASE=HWU54DM + +usb:v07B8pB21C* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v07B8pB21D* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v07B8pB21E* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v07B8pB21F* + ID_MODEL_FROM_DATABASE=WUG2700 + +usb:v07B8pD011* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v07B8pE001* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07B8pE002* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07B8pE003* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07B8pE004* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07B8pE005* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07B8pE006* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07B8pE007* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07B8pE008* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07B8pE009* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07B8pE00A* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07B8pE4F0* + ID_MODEL_FROM_DATABASE=Card Reader Driver + +usb:v07B8pF101* + ID_MODEL_FROM_DATABASE=DSB-560 Modem [atlas] + +usb:v07BC* + ID_VENDOR_FROM_DATABASE=Canon Computer Systems, Inc. + +usb:v07BD* + ID_VENDOR_FROM_DATABASE=Webgear, Inc. + +usb:v07BE* + ID_VENDOR_FROM_DATABASE=Veridicom + +usb:v07C0* + ID_VENDOR_FROM_DATABASE=Code Mercenaries Hard- und Software GmbH + +usb:v07C0p1113* + ID_MODEL_FROM_DATABASE=JoyWarrior24F8 + +usb:v07C0p1116* + ID_MODEL_FROM_DATABASE=JoyWarrior24F14 + +usb:v07C0p1121* + ID_MODEL_FROM_DATABASE=The Claw + +usb:v07C0p1500* + ID_MODEL_FROM_DATABASE=IO-Warrior 40 + +usb:v07C0p1501* + ID_MODEL_FROM_DATABASE=IO-Warrior 24 + +usb:v07C0p1502* + ID_MODEL_FROM_DATABASE=IO-Warrior 48 + +usb:v07C0p1503* + ID_MODEL_FROM_DATABASE=IO-Warrior 28 + +usb:v07C0p1511* + ID_MODEL_FROM_DATABASE=IO-Warrior 24 Power Vampire + +usb:v07C0p1512* + ID_MODEL_FROM_DATABASE=IO-Warrior 24 Power Vampire + +usb:v07C1* + ID_VENDOR_FROM_DATABASE=Keisokugiken + +usb:v07C1p0068* + ID_MODEL_FROM_DATABASE=HKS-0200 USBDAQ + +usb:v07C4* + ID_VENDOR_FROM_DATABASE=Datafab Systems, Inc. + +usb:v07C4p0102* + ID_MODEL_FROM_DATABASE=USB to LS120 + +usb:v07C4p0103* + ID_MODEL_FROM_DATABASE=USB to IDE + +usb:v07C4p1234* + ID_MODEL_FROM_DATABASE=USB to ATAPI + +usb:v07C4pA000* + ID_MODEL_FROM_DATABASE=CompactFlash Card Reader + +usb:v07C4pA001* + ID_MODEL_FROM_DATABASE=CompactFlash & SmartMedia Card Reader [eusb] + +usb:v07C4pA002* + ID_MODEL_FROM_DATABASE=Disk Drive + +usb:v07C4pA003* + ID_MODEL_FROM_DATABASE=Datafab-based Reader + +usb:v07C4pA004* + ID_MODEL_FROM_DATABASE=USB to MMC Class Drive + +usb:v07C4pA005* + ID_MODEL_FROM_DATABASE=CompactFlash & SmartMedia Card Reader + +usb:v07C4pA006* + ID_MODEL_FROM_DATABASE=SmartMedia Card Reader + +usb:v07C4pA007* + ID_MODEL_FROM_DATABASE=Memory Stick Class Drive + +usb:v07C4pA103* + ID_MODEL_FROM_DATABASE=MDSM-B reader + +usb:v07C4pA107* + ID_MODEL_FROM_DATABASE=USB to Memory Stick (LC1) Drive + +usb:v07C4pA109* + ID_MODEL_FROM_DATABASE=LC1 CompactFlash & SmartMedia Card Reader + +usb:v07C4pA10B* + ID_MODEL_FROM_DATABASE=USB to CF+MS(LC1) + +usb:v07C4pA200* + ID_MODEL_FROM_DATABASE=DF-UT-06 Hama MMC/SD Reader + +usb:v07C4pA400* + ID_MODEL_FROM_DATABASE=CompactFlash & Microdrive Reader + +usb:v07C4pA600* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v07C4pA604* + ID_MODEL_FROM_DATABASE=12-in-1 Card Reader + +usb:v07C4pAD01* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07C4pAE01* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07C4pAF01* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v07C4pB000* + ID_MODEL_FROM_DATABASE=USB to CF(LC1) + +usb:v07C4pB001* + ID_MODEL_FROM_DATABASE=USB to CF+PCMCIA + +usb:v07C4pB004* + ID_MODEL_FROM_DATABASE=MMC/SD Reader + +usb:v07C4pB006* + ID_MODEL_FROM_DATABASE=USB to PCMCIA + +usb:v07C4pB00A* + ID_MODEL_FROM_DATABASE=USB to CF+SD Drive(LC1) + +usb:v07C4pB00B* + ID_MODEL_FROM_DATABASE=USB to Memory Stick(LC1) + +usb:v07C4pC010* + ID_MODEL_FROM_DATABASE=Kingston FCR-HS2/ATA Card Reader + +usb:v07C5* + ID_VENDOR_FROM_DATABASE=APG Cash Drawer + +usb:v07C5p0500* + ID_MODEL_FROM_DATABASE=Cash Drawer + +usb:v07C6* + ID_VENDOR_FROM_DATABASE=ShareWave, Inc. + +usb:v07C6p0002* + ID_MODEL_FROM_DATABASE=Bodega Wireless Access Point + +usb:v07C6p0003* + ID_MODEL_FROM_DATABASE=Bodega Wireless Network Adapter + +usb:v07C7* + ID_VENDOR_FROM_DATABASE=Powertech Industrial Co., Ltd + +usb:v07C8* + ID_VENDOR_FROM_DATABASE=B.U.G., Inc. + +usb:v07C8p0202* + ID_MODEL_FROM_DATABASE=MN128-SOHO PAL + +usb:v07C9* + ID_VENDOR_FROM_DATABASE=Allied Telesyn International + +usb:v07C9pB100* + ID_MODEL_FROM_DATABASE=AT-USB100 + +usb:v07CA* + ID_VENDOR_FROM_DATABASE=AVerMedia Technologies, Inc. + +usb:v07CAp0002* + ID_MODEL_FROM_DATABASE=AVerTV PVR USB/EZMaker Pro Device + +usb:v07CAp0026* + ID_MODEL_FROM_DATABASE=AVerTV + +usb:v07CAp0337* + ID_MODEL_FROM_DATABASE=A867 DVB-T dongle + +usb:v07CAp0837* + ID_MODEL_FROM_DATABASE=H837 Hybrid ATSC/QAM + +usb:v07CAp1228* + ID_MODEL_FROM_DATABASE=MPEG-2 Capture Device (M038) + +usb:v07CAp1830* + ID_MODEL_FROM_DATABASE=AVerTV Volar Video Capture (H830) + +usb:v07CAp3835* + ID_MODEL_FROM_DATABASE=AVerTV Volar Green HD (A835B) + +usb:v07CAp850A* + ID_MODEL_FROM_DATABASE=AverTV Volar Black HD (A850) + +usb:v07CAp850B* + ID_MODEL_FROM_DATABASE=AverTV Red HD+ (A850T) + +usb:v07CApA309* + ID_MODEL_FROM_DATABASE=AVerTV DVB-T (A309) + +usb:v07CApA801* + ID_MODEL_FROM_DATABASE=AVerTV DVB-T (A800) + +usb:v07CApA815* + ID_MODEL_FROM_DATABASE=AVerTV DVB-T Volar X (A815) + +usb:v07CApA827* + ID_MODEL_FROM_DATABASE=AVerTV Hybrid Volar HX (A827) + +usb:v07CApA867* + ID_MODEL_FROM_DATABASE=AVerTV DVB-T (A867) + +usb:v07CApB300* + ID_MODEL_FROM_DATABASE=A300 DVB-T TV receiver + +usb:v07CApB800* + ID_MODEL_FROM_DATABASE=MR800 FM Radio + +usb:v07CApE880* + ID_MODEL_FROM_DATABASE=MPEG-2 Capture Device (E880) + +usb:v07CApE882* + ID_MODEL_FROM_DATABASE=MPEG-2 Capture Device (E882) + +usb:v07CB* + ID_VENDOR_FROM_DATABASE=Kingmax Technology, Inc. + +usb:v07CC* + ID_VENDOR_FROM_DATABASE=Carry Computer Eng., Co., Ltd + +usb:v07CCp0000* + ID_MODEL_FROM_DATABASE=CF Card Reader + +usb:v07CCp0001* + ID_MODEL_FROM_DATABASE=Reader (UICSE) + +usb:v07CCp0002* + ID_MODEL_FROM_DATABASE=Reader (UIS) + +usb:v07CCp0003* + ID_MODEL_FROM_DATABASE=SM Card Reader + +usb:v07CCp0004* + ID_MODEL_FROM_DATABASE=SM/CF/PCMCIA Card Reader + +usb:v07CCp0005* + ID_MODEL_FROM_DATABASE=Reader (UISA2SE) + +usb:v07CCp0006* + ID_MODEL_FROM_DATABASE=SM/CF/PCMCIA Card Reader + +usb:v07CCp0007* + ID_MODEL_FROM_DATABASE=Reader (UISA6SE) + +usb:v07CCp000C* + ID_MODEL_FROM_DATABASE=SM/CF Card Reader + +usb:v07CCp000D* + ID_MODEL_FROM_DATABASE=SM/CF Card Reader + +usb:v07CCp000E* + ID_MODEL_FROM_DATABASE=Reader (UISDA) + +usb:v07CCp000F* + ID_MODEL_FROM_DATABASE=Reader (UICLIK) + +usb:v07CCp0010* + ID_MODEL_FROM_DATABASE=Reader (UISMA) + +usb:v07CCp0012* + ID_MODEL_FROM_DATABASE=Reader (UISC6SE-FLASH) + +usb:v07CCp0014* + ID_MODEL_FROM_DATABASE=Litronic Fortezza Reader + +usb:v07CCp0030* + ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC12S) + +usb:v07CCp0040* + ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC13S) + +usb:v07CCp0100* + ID_MODEL_FROM_DATABASE=Reader (UID) + +usb:v07CCp0101* + ID_MODEL_FROM_DATABASE=Reader (UIM) + +usb:v07CCp0102* + ID_MODEL_FROM_DATABASE=Reader (UISDMA) + +usb:v07CCp0103* + ID_MODEL_FROM_DATABASE=Reader (UISDMC) + +usb:v07CCp0104* + ID_MODEL_FROM_DATABASE=Reader (UISDM) + +usb:v07CCp0200* + ID_MODEL_FROM_DATABASE=6-in-1 Card Reader + +usb:v07CCp0201* + ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC1S & UISDMC3S) + +usb:v07CCp0202* + ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC5S) + +usb:v07CCp0203* + ID_MODEL_FROM_DATABASE=Mass Storage (UISMC5S) + +usb:v07CCp0204* + ID_MODEL_FROM_DATABASE=Mass Storage (UIM4/5S & UIM7S) + +usb:v07CCp0205* + ID_MODEL_FROM_DATABASE=Mass Storage (UIS4/5S & UIS7S) + +usb:v07CCp0206* + ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC10S & UISDMC11S) + +usb:v07CCp0207* + ID_MODEL_FROM_DATABASE=Mass Storage (UPIDMA) + +usb:v07CCp0208* + ID_MODEL_FROM_DATABASE=Mass Storage (UCFC II) + +usb:v07CCp0210* + ID_MODEL_FROM_DATABASE=Mass Storage (UPIXXA) + +usb:v07CCp0213* + ID_MODEL_FROM_DATABASE=Mass Storage (UPIDA) + +usb:v07CCp0214* + ID_MODEL_FROM_DATABASE=Mass Storage (UPIMA) + +usb:v07CCp0215* + ID_MODEL_FROM_DATABASE=Mass Storage (UPISA) + +usb:v07CCp0217* + ID_MODEL_FROM_DATABASE=Mass Storage (UPISDMA) + +usb:v07CCp0223* + ID_MODEL_FROM_DATABASE=Mass Storage (UCIDA) + +usb:v07CCp0224* + ID_MODEL_FROM_DATABASE=Mass Storage (UCIMA) + +usb:v07CCp0225* + ID_MODEL_FROM_DATABASE=Mass Storage (UIS7S) + +usb:v07CCp0227* + ID_MODEL_FROM_DATABASE=Mass Storage (UCIDMA) + +usb:v07CCp0234* + ID_MODEL_FROM_DATABASE=Mass Storage (UIM7S) + +usb:v07CCp0235* + ID_MODEL_FROM_DATABASE=Mass Storage (UIS4S-S) + +usb:v07CCp0237* + ID_MODEL_FROM_DATABASE=Velper (UISDMC4S) + +usb:v07CCp0300* + ID_MODEL_FROM_DATABASE=6-in-1 Card Reader + +usb:v07CCp0301* + ID_MODEL_FROM_DATABASE=6-in-1 Card Reader + +usb:v07CCp0303* + ID_MODEL_FROM_DATABASE=Mass Storage (UID10W) + +usb:v07CCp0304* + ID_MODEL_FROM_DATABASE=Mass Storage (UIM10W) + +usb:v07CCp0305* + ID_MODEL_FROM_DATABASE=Mass Storage (UIS10W) + +usb:v07CCp0308* + ID_MODEL_FROM_DATABASE=Mass Storage (UIC10W) + +usb:v07CCp0309* + ID_MODEL_FROM_DATABASE=Mass Storage (UISC3W) + +usb:v07CCp0310* + ID_MODEL_FROM_DATABASE=Mass Storage (UISDMA2W) + +usb:v07CCp0311* + ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC14W) + +usb:v07CCp0320* + ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC4W) + +usb:v07CCp0321* + ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC37W) + +usb:v07CCp0330* + ID_MODEL_FROM_DATABASE=WINTERREADER Reader + +usb:v07CCp0350* + ID_MODEL_FROM_DATABASE=9-in-1 Card Reader + +usb:v07CCp0500* + ID_MODEL_FROM_DATABASE=Mass Storage + +usb:v07CCp0501* + ID_MODEL_FROM_DATABASE=Mass Storage + +usb:v07CD* + ID_VENDOR_FROM_DATABASE=Elektor + +usb:v07CDp0001* + ID_MODEL_FROM_DATABASE=USBuart Serial Port + +usb:v07CF* + ID_VENDOR_FROM_DATABASE=Casio Computer Co., Ltd + +usb:v07CFp1001* + ID_MODEL_FROM_DATABASE=QV-8000SX/5700/3000EX Digicam; Exilim EX-M20 + +usb:v07CFp1003* + ID_MODEL_FROM_DATABASE=Exilim EX-S500 + +usb:v07CFp1004* + ID_MODEL_FROM_DATABASE=Exilim EX-Z120 + +usb:v07CFp1011* + ID_MODEL_FROM_DATABASE=USB-CASIO PC CAMERA + +usb:v07CFp1116* + ID_MODEL_FROM_DATABASE=EXILIM EX-Z19 + +usb:v07CFp1125* + ID_MODEL_FROM_DATABASE=Exilim EX-H10 Digital Camera (mass storage mode) + +usb:v07CFp1133* + ID_MODEL_FROM_DATABASE=Exilim EX-Z350 Digital Camera (mass storage mode) + +usb:v07CFp1225* + ID_MODEL_FROM_DATABASE=Exilim EX-H10 Digital Camera (PictBridge mode) + +usb:v07CFp1233* + ID_MODEL_FROM_DATABASE=Exilim EX-Z350 Digital Camera (PictBridge mode) + +usb:v07CFp2002* + ID_MODEL_FROM_DATABASE=E-125 Cassiopeia Pocket PC + +usb:v07CFp3801* + ID_MODEL_FROM_DATABASE=WMP-1 MP3-Watch + +usb:v07CFp4001* + ID_MODEL_FROM_DATABASE=Label Printer KL-P1000 + +usb:v07CFp4007* + ID_MODEL_FROM_DATABASE=CW50 Device + +usb:v07CFp4104* + ID_MODEL_FROM_DATABASE=Cw75 Device + +usb:v07CFp4107* + ID_MODEL_FROM_DATABASE=CW-L300 Device + +usb:v07CFp4500* + ID_MODEL_FROM_DATABASE=LV-20 Digital Camera + +usb:v07CFp6101* + ID_MODEL_FROM_DATABASE=fx-9750gII + +usb:v07CFp6102* + ID_MODEL_FROM_DATABASE=fx-CP400 + +usb:v07CFp6801* + ID_MODEL_FROM_DATABASE=PL-40R + +usb:v07CFp6802* + ID_MODEL_FROM_DATABASE=MIDI Keyboard + +usb:v07D0* + ID_VENDOR_FROM_DATABASE=Dazzle + +usb:v07D0p0001* + ID_MODEL_FROM_DATABASE=Digital Video Creator I + +usb:v07D0p0002* + ID_MODEL_FROM_DATABASE=Global Village VideoFX Grabber + +usb:v07D0p0003* + ID_MODEL_FROM_DATABASE=Fusion Model DVC-50 Rev 1 (NTSC) + +usb:v07D0p0004* + ID_MODEL_FROM_DATABASE=DVC-800 (PAL) Grabber + +usb:v07D0p0005* + ID_MODEL_FROM_DATABASE=Fusion Video and Audio Ports + +usb:v07D0p0006* + ID_MODEL_FROM_DATABASE=DVC 150 Loader Device + +usb:v07D0p0007* + ID_MODEL_FROM_DATABASE=DVC 150 + +usb:v07D0p0327* + ID_MODEL_FROM_DATABASE=Fusion Digital Media Reader + +usb:v07D0p1001* + ID_MODEL_FROM_DATABASE=DM-FLEX DFU Adapter + +usb:v07D0p1002* + ID_MODEL_FROM_DATABASE=DMHS2 DFU Adapter + +usb:v07D0p1102* + ID_MODEL_FROM_DATABASE=CF Reader/Writer + +usb:v07D0p1103* + ID_MODEL_FROM_DATABASE=SD Reader/Writer + +usb:v07D0p1104* + ID_MODEL_FROM_DATABASE=SM Reader/Writer + +usb:v07D0p1105* + ID_MODEL_FROM_DATABASE=MS Reader/Writer + +usb:v07D0p1106* + ID_MODEL_FROM_DATABASE=xD/SM Reader/Writer + +usb:v07D0p1202* + ID_MODEL_FROM_DATABASE=MultiSlot Reader/Writer + +usb:v07D0p2000* + ID_MODEL_FROM_DATABASE=FX2 DFU Adapter + +usb:v07D0p2001* + ID_MODEL_FROM_DATABASE=eUSB CompactFlash Reader + +usb:v07D0p4100* + ID_MODEL_FROM_DATABASE=Kingsun SF-620 Infrared Adapter + +usb:v07D0p4101* + ID_MODEL_FROM_DATABASE=Connectivity Cable (CA-42 clone) + +usb:v07D0p4959* + ID_MODEL_FROM_DATABASE=Kingsun KS-959 Infrared Adapter + +usb:v07D1* + ID_VENDOR_FROM_DATABASE=D-Link System + +usb:v07D1p13EC* + ID_MODEL_FROM_DATABASE=VvBus for Helium 2xx + +usb:v07D1p13ED* + ID_MODEL_FROM_DATABASE=VvBus for Helium 2xx + +usb:v07D1p13F1* + ID_MODEL_FROM_DATABASE=DSL-302G Modem + +usb:v07D1p13F2* + ID_MODEL_FROM_DATABASE=DSL-502G Router + +usb:v07D1p3300* + ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.E) [Realtek RTL8191SU] + +usb:v07D1p3302* + ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.C2) [Realtek RTL8191SU] + +usb:v07D1p3303* + ID_MODEL_FROM_DATABASE=DWA-131 802.11n Wireless N Nano Adapter(rev.A1) [Realtek RTL8192SU] + +usb:v07D1p3304* + ID_MODEL_FROM_DATABASE=FR-300USB 802.11bgn Wireless Adapter + +usb:v07D1p3A07* + ID_MODEL_FROM_DATABASE=WUA-2340 RangeBooster G Adapter(rev.A) [Atheros AR5523] + +usb:v07D1p3A08* + ID_MODEL_FROM_DATABASE=WUA-2340 RangeBooster G Adapter(rev.A) (no firmware) [Atheros AR5523] + +usb:v07D1p3A09* + ID_MODEL_FROM_DATABASE=DWA-160 802.11abgn Xtreme N Dual Band Adapter(rev.A2) [Atheros AR9170+AR9104] + +usb:v07D1p3A0D* + ID_MODEL_FROM_DATABASE=DWA-120 802.11g Wireless 108G Adapter [Atheros AR5523] + +usb:v07D1p3A0F* + ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.D) [Atheros AR9170+AR9102] + +usb:v07D1p3A10* + ID_MODEL_FROM_DATABASE=DWA-126 802.11n Wireless Adapter [Atheros AR9271] + +usb:v07D1p3B01* + ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.D) [Marvell 88W8338+88W8010] + +usb:v07D1p3B10* + ID_MODEL_FROM_DATABASE=DWA-142 RangeBooster N Adapter [Marvell 88W8362+88W8060] + +usb:v07D1p3B11* + ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.A1) [Marvell 88W8362+88W8060] + +usb:v07D1p3C03* + ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.C1) [Ralink RT2571W] + +usb:v07D1p3C04* + ID_MODEL_FROM_DATABASE=WUA-1340 + +usb:v07D1p3C05* + ID_MODEL_FROM_DATABASE=EH103 Wireless G Adapter + +usb:v07D1p3C06* + ID_MODEL_FROM_DATABASE=DWA-111 802.11bg Wireless Adapter [Ralink RT2571W] + +usb:v07D1p3C07* + ID_MODEL_FROM_DATABASE=DWA-110 Wireless G Adapter(rev.A1) [Ralink RT2571W] + +usb:v07D1p3C09* + ID_MODEL_FROM_DATABASE=DWA-140 RangeBooster N Adapter(rev.B1) [Ralink RT2870] + +usb:v07D1p3C0A* + ID_MODEL_FROM_DATABASE=DWA-140 RangeBooster N Adapter(rev.B2) [Ralink RT3072] + +usb:v07D1p3C0B* + ID_MODEL_FROM_DATABASE=DWA-110 Wireless G Adapter(rev.B) [Ralink RT2870] + +usb:v07D1p3C0D* + ID_MODEL_FROM_DATABASE=DWA-125 Wireless N 150 Adapter(rev.A1) [Ralink RT3070] + +usb:v07D1p3C0E* + ID_MODEL_FROM_DATABASE=WUA-2340 RangeBooster G Adapter(rev.B) [Ralink RT2070] + +usb:v07D1p3C0F* + ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.E1) [Ralink RT2070] + +usb:v07D1p3C10* + ID_MODEL_FROM_DATABASE=DWA-160 802.11abgn Xtreme N Dual Band Adapter(rev.A1) [Atheros AR9170+AR9104] + +usb:v07D1p3C11* + ID_MODEL_FROM_DATABASE=DWA-160 Xtreme N Dual Band USB Adapter(rev.B) [Ralink RT2870] + +usb:v07D1p3C13* + ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.B) [Ralink RT2870] + +usb:v07D1p3C15* + ID_MODEL_FROM_DATABASE=DWA-140 RangeBooster N Adapter(rev.B3) [Ralink RT2870] + +usb:v07D1p3C16* + ID_MODEL_FROM_DATABASE=DWA-125 Wireless N 150 Adapter(rev.A2) [Ralink RT3070] + +usb:v07D1p3E02* + ID_MODEL_FROM_DATABASE=DWM-156 3.75G HSUPA Adapter + +usb:v07D1p5100* + ID_MODEL_FROM_DATABASE=Remote NDIS Device + +usb:v07D1pA800* + ID_MODEL_FROM_DATABASE=DWM-152 3.75G HSUPA Adapter + +usb:v07D1pF101* + ID_MODEL_FROM_DATABASE=DBT-122 Bluetooth + +usb:v07D1pFC01* + ID_MODEL_FROM_DATABASE=DBT-120 Bluetooth Adapter + +usb:v07D2* + ID_VENDOR_FROM_DATABASE=Aptio Products, Inc. + +usb:v07D3* + ID_VENDOR_FROM_DATABASE=Cyberdata Corp. + +usb:v07D5* + ID_VENDOR_FROM_DATABASE=Radiant Systems + +usb:v07D7* + ID_VENDOR_FROM_DATABASE=GCC Technologies, Inc. + +usb:v07DA* + ID_VENDOR_FROM_DATABASE=Arasan Chip Systems + +usb:v07DE* + ID_VENDOR_FROM_DATABASE=Diamond Multimedia + +usb:v07DEp2820* + ID_MODEL_FROM_DATABASE=VC500 Video Capture Dongle + +usb:v07DF* + ID_VENDOR_FROM_DATABASE=David Electronics Co., Ltd + +usb:v07E0* + ID_VENDOR_FROM_DATABASE=NCP engineering GmbH + +usb:v07E0p4742* + ID_MODEL_FROM_DATABASE=VPN GovNet Box + +usb:v07E1* + ID_VENDOR_FROM_DATABASE=Ambient Technologies, Inc. + +usb:v07E1p5201* + ID_MODEL_FROM_DATABASE=V.90 Modem + +usb:v07E2* + ID_VENDOR_FROM_DATABASE=Elmeg GmbH & Co., Ltd + +usb:v07E3* + ID_VENDOR_FROM_DATABASE=Planex Communications, Inc. + +usb:v07E4* + ID_VENDOR_FROM_DATABASE=Movado Enterprise Co., Ltd + +usb:v07E4p0967* + ID_MODEL_FROM_DATABASE=SCard R/W CSR-145 + +usb:v07E4p0968* + ID_MODEL_FROM_DATABASE=SCard R/W CSR-145 + +usb:v07E5* + ID_VENDOR_FROM_DATABASE=QPS, Inc. + +usb:v07E5p05C2* + ID_MODEL_FROM_DATABASE=IDE-to-USB2.0 PCA + +usb:v07E5p5C01* + ID_MODEL_FROM_DATABASE=Que! CDRW + +usb:v07E6* + ID_VENDOR_FROM_DATABASE=Allied Cable Corp. + +usb:v07E7* + ID_VENDOR_FROM_DATABASE=Mirvo Toys, Inc. + +usb:v07E8* + ID_VENDOR_FROM_DATABASE=Labsystems + +usb:v07EA* + ID_VENDOR_FROM_DATABASE=Iwatsu Electric Co., Ltd + +usb:v07EB* + ID_VENDOR_FROM_DATABASE=Double-H Technology Co., Ltd + +usb:v07EC* + ID_VENDOR_FROM_DATABASE=Taiyo Electric Wire & Cable Co., Ltd + +usb:v07EE* + ID_VENDOR_FROM_DATABASE=Torex Retail (formerly Logware) + +usb:v07EEp0002* + ID_MODEL_FROM_DATABASE=Cash Drawer I/F + +usb:v07EF* + ID_VENDOR_FROM_DATABASE=STSN + +usb:v07EFp0001* + ID_MODEL_FROM_DATABASE=Internet Access Device + +usb:v07F2* + ID_VENDOR_FROM_DATABASE=Microcomputer Applications, Inc. + +usb:v07F2p0001* + ID_MODEL_FROM_DATABASE=KEYLOK II + +usb:v07F6* + ID_VENDOR_FROM_DATABASE=Circuit Assembly Corp. + +usb:v07F7* + ID_VENDOR_FROM_DATABASE=Century Corp. + +usb:v07F7p0005* + ID_MODEL_FROM_DATABASE=ScanLogic/Century Corporation uATA + +usb:v07F7p011E* + ID_MODEL_FROM_DATABASE=Century USB Disk Enclosure + +usb:v07F9* + ID_VENDOR_FROM_DATABASE=Dotop Technology, Inc. + +usb:v07FA* + ID_VENDOR_FROM_DATABASE=DrayTek Corp. + +usb:v07FAp0778* + ID_MODEL_FROM_DATABASE=miniVigor 128 ISDN TA + +usb:v07FAp0846* + ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] + +usb:v07FAp0847* + ID_MODEL_FROM_DATABASE=ISDN TA [HFC-S] + +usb:v07FAp1012* + ID_MODEL_FROM_DATABASE=BeWAN ADSL USB ST (grey) + +usb:v07FAp1196* + ID_MODEL_FROM_DATABASE=BWIFI-USB54AR 802.11bg + +usb:v07FApA904* + ID_MODEL_FROM_DATABASE=BeWAN ADSL + +usb:v07FApA905* + ID_MODEL_FROM_DATABASE=BeWAN ADSL ST + +usb:v07FC* + ID_VENDOR_FROM_DATABASE=Thomann + +usb:v07FCp1113* + ID_MODEL_FROM_DATABASE=SWISSONIC EasyKeys61 Midikeyboard + +usb:v07FD* + ID_VENDOR_FROM_DATABASE=Mark of the Unicorn + +usb:v07FDp0000* + ID_MODEL_FROM_DATABASE=FastLane MIDI Interface + +usb:v07FDp0001* + ID_MODEL_FROM_DATABASE=MIDI Interface + +usb:v07FDp0002* + ID_MODEL_FROM_DATABASE=MOTU Audio for 64 bit + +usb:v07FF* + ID_VENDOR_FROM_DATABASE=Unknown + +usb:v07FFp00FF* + ID_MODEL_FROM_DATABASE=Portable Hard Drive + +usb:v0801* + ID_VENDOR_FROM_DATABASE=MagTek + +usb:v0801p0001* + ID_MODEL_FROM_DATABASE=Mini Swipe Reader (Keyboard Emulation) + +usb:v0801p0002* + ID_MODEL_FROM_DATABASE=Mini Swipe Reader + +usb:v0801p0003* + ID_MODEL_FROM_DATABASE=Magstripe Insert Reader + +usb:v0802* + ID_VENDOR_FROM_DATABASE=Mako Technologies, LLC + +usb:v0803* + ID_VENDOR_FROM_DATABASE=Zoom Telephonics, Inc. + +usb:v0803p1300* + ID_MODEL_FROM_DATABASE=V92 Faxmodem + +usb:v0803p3095* + ID_MODEL_FROM_DATABASE=V.92 56K Mini External Modem Model 3095 + +usb:v0803p4310* + ID_MODEL_FROM_DATABASE=4410a Wireless-G Adapter [Intersil ISL3887] + +usb:v0803p4410* + ID_MODEL_FROM_DATABASE=4410b Wireless-G Adapter [ZyDAS ZD1211B] + +usb:v0803p5241* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v0803p5551* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v0803p9700* + ID_MODEL_FROM_DATABASE=2986L FaxModem + +usb:v0803p9800* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v0803pA312* + ID_MODEL_FROM_DATABASE=Wireless-G + +usb:v0809* + ID_VENDOR_FROM_DATABASE=Genicom Technology, Inc. + +usb:v080A* + ID_VENDOR_FROM_DATABASE=Evermuch Technology Co., Ltd + +usb:v080B* + ID_VENDOR_FROM_DATABASE=Cross Match Technologies + +usb:v080Bp0002* + ID_MODEL_FROM_DATABASE=Fingerprint Scanner (After ReNumeration) + +usb:v080Bp0010* + ID_MODEL_FROM_DATABASE=300LC Series Fingerprint Scanner (Before ReNumeration) + +usb:v080C* + ID_VENDOR_FROM_DATABASE=Datalogic S.p.A. + +usb:v080Cp0300* + ID_MODEL_FROM_DATABASE=Gryphon D120 Barcode Scanner + +usb:v080Cp0400* + ID_MODEL_FROM_DATABASE=Gryphon D120 Barcode Scanner + +usb:v080Cp0500* + ID_MODEL_FROM_DATABASE=Gryphon D120 Barcode Scanner + +usb:v080Cp0600* + ID_MODEL_FROM_DATABASE=Gryphon M100 Barcode Scanner + +usb:v080D* + ID_VENDOR_FROM_DATABASE=Teco Image Systems Co., Ltd + +usb:v080Dp0102* + ID_MODEL_FROM_DATABASE=Hercules Scan@home 48 + +usb:v080Dp0104* + ID_MODEL_FROM_DATABASE=3.2Slim + +usb:v080Dp0110* + ID_MODEL_FROM_DATABASE=UMAX AstraSlim 1200 Scanner + +usb:v0810* + ID_VENDOR_FROM_DATABASE=Personal Communication Systems, Inc. + +usb:v0810p0001* + ID_MODEL_FROM_DATABASE=Dual PSX Adaptor + +usb:v0810p0002* + ID_MODEL_FROM_DATABASE=Dual PCS Adaptor + +usb:v0810p0003* + ID_MODEL_FROM_DATABASE=PlayStation Gamepad + +usb:v0810pE001* + ID_MODEL_FROM_DATABASE=Twin controller + +usb:v0810pE501* + ID_MODEL_FROM_DATABASE=SNES Gamepad + +usb:v0813* + ID_VENDOR_FROM_DATABASE=Mattel, Inc. + +usb:v0813p0001* + ID_MODEL_FROM_DATABASE=Intel Play QX3 Microscope + +usb:v0813p0002* + ID_MODEL_FROM_DATABASE=Dual Mode Camera Plus + +usb:v0819* + ID_VENDOR_FROM_DATABASE=eLicenser + +usb:v0819p0101* + ID_MODEL_FROM_DATABASE=License Management and Copy Protection + +usb:v081A* + ID_VENDOR_FROM_DATABASE=MG Logic + +usb:v081Ap1000* + ID_MODEL_FROM_DATABASE=Duo Pen Tablet + +usb:v081B* + ID_VENDOR_FROM_DATABASE=Indigita Corp. + +usb:v081Bp0600* + ID_MODEL_FROM_DATABASE=Storage Adapter + +usb:v081Bp0601* + ID_MODEL_FROM_DATABASE=Storage Adapter + +usb:v081C* + ID_VENDOR_FROM_DATABASE=Mipsys + +usb:v081E* + ID_VENDOR_FROM_DATABASE=AlphaSmart, Inc. + +usb:v081EpDF00* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0822* + ID_VENDOR_FROM_DATABASE=Reudo Corp. + +usb:v0822p2001* + ID_MODEL_FROM_DATABASE=IRXpress Infrared Device + +usb:v0825* + ID_VENDOR_FROM_DATABASE=GC Protronics + +usb:v0826* + ID_VENDOR_FROM_DATABASE=Data Transit + +usb:v0827* + ID_VENDOR_FROM_DATABASE=BroadLogic, Inc. + +usb:v0828* + ID_VENDOR_FROM_DATABASE=Sato Corp. + +usb:v0829* + ID_VENDOR_FROM_DATABASE=DirecTV Broadband, Inc. (Telocity) + +usb:v082D* + ID_VENDOR_FROM_DATABASE=Handspring + +usb:v082Dp0100* + ID_MODEL_FROM_DATABASE=Visor + +usb:v082Dp0200* + ID_MODEL_FROM_DATABASE=Treo + +usb:v082Dp0300* + ID_MODEL_FROM_DATABASE=Treo 600 + +usb:v082Dp0400* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v082Dp0500* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v082Dp0600* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830* + ID_VENDOR_FROM_DATABASE=Palm, Inc. + +usb:v0830p0001* + ID_MODEL_FROM_DATABASE=m500 + +usb:v0830p0002* + ID_MODEL_FROM_DATABASE=m505 + +usb:v0830p0003* + ID_MODEL_FROM_DATABASE=m515 + +usb:v0830p0004* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0005* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0006* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0010* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0011* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0012* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0013* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0014* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0020* + ID_MODEL_FROM_DATABASE=i705 + +usb:v0830p0021* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0022* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0023* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0024* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0030* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0031* + ID_MODEL_FROM_DATABASE=Tungsten W + +usb:v0830p0032* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0033* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0034* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0040* + ID_MODEL_FROM_DATABASE=m125 + +usb:v0830p0041* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0042* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0043* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0044* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0050* + ID_MODEL_FROM_DATABASE=m130 + +usb:v0830p0051* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0052* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0053* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0054* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0060* + ID_MODEL_FROM_DATABASE=Tungsten C/E/T/T2/T3 / Zire 71 + +usb:v0830p0061* + ID_MODEL_FROM_DATABASE=Lifedrive / Treo 650/680 / Tunsten E2/T5/TX / Centro / Zire 21/31/72 / Z22 + +usb:v0830p0062* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0063* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0064* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0070* + ID_MODEL_FROM_DATABASE=Zire + +usb:v0830p0071* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0072* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0080* + ID_MODEL_FROM_DATABASE=Serial Adapter [for Palm III] + +usb:v0830p0081* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p0082* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0830p00A0* + ID_MODEL_FROM_DATABASE=Treo 800w + +usb:v0830p0101* + ID_MODEL_FROM_DATABASE=Pre + +usb:v0832* + ID_VENDOR_FROM_DATABASE=Kouwell Electronics Corp. + +usb:v0832p5850* + ID_MODEL_FROM_DATABASE=Cable + +usb:v0833* + ID_VENDOR_FROM_DATABASE=Sourcenext Corp. + +usb:v0833p012E* + ID_MODEL_FROM_DATABASE=KeikaiDenwa 8 with charger + +usb:v0833p039F* + ID_MODEL_FROM_DATABASE=KeikaiDenwa 8 + +usb:v0835* + ID_VENDOR_FROM_DATABASE=Action Star Enterprise Co., Ltd + +usb:v0836* + ID_VENDOR_FROM_DATABASE=TrekStor + +usb:v0836p2836* + ID_MODEL_FROM_DATABASE=i.Beat mood + +usb:v0839* + ID_VENDOR_FROM_DATABASE=Samsung Techwin Co., Ltd + +usb:v0839p0005* + ID_MODEL_FROM_DATABASE=Digimax Camera + +usb:v0839p0008* + ID_MODEL_FROM_DATABASE=Digimax 230 Camera + +usb:v0839p0009* + ID_MODEL_FROM_DATABASE=Digimax 340 + +usb:v0839p000A* + ID_MODEL_FROM_DATABASE=Digimax 410 + +usb:v0839p000E* + ID_MODEL_FROM_DATABASE=Digimax 360 + +usb:v0839p0010* + ID_MODEL_FROM_DATABASE=Digimax 300 + +usb:v0839p1003* + ID_MODEL_FROM_DATABASE=Digimax 210SE + +usb:v0839p1005* + ID_MODEL_FROM_DATABASE=Digimax 220 + +usb:v0839p1009* + ID_MODEL_FROM_DATABASE=Digimax V4 + +usb:v0839p1012* + ID_MODEL_FROM_DATABASE=6500 Document Camera + +usb:v0839p1058* + ID_MODEL_FROM_DATABASE=S730 Camera + +usb:v0839p1064* + ID_MODEL_FROM_DATABASE=Digimax D830 Camera + +usb:v0839p1542* + ID_MODEL_FROM_DATABASE=Digimax 50 Duo + +usb:v0839p3000* + ID_MODEL_FROM_DATABASE=Digimax 35 MP3 + +usb:v083A* + ID_VENDOR_FROM_DATABASE=Accton Technology Corp. + +usb:v083Ap1046* + ID_MODEL_FROM_DATABASE=10/100 Ethernet [pegasus] + +usb:v083Ap1060* + ID_MODEL_FROM_DATABASE=HomeLine Adapter + +usb:v083Ap1F4D* + ID_MODEL_FROM_DATABASE=SMC8013WG Broadband Remote NDIS Device + +usb:v083Ap3046* + ID_MODEL_FROM_DATABASE=10/100 Series Adapter + +usb:v083Ap3060* + ID_MODEL_FROM_DATABASE=1/10/100 Adapter + +usb:v083Ap3501* + ID_MODEL_FROM_DATABASE=2664W + +usb:v083Ap3502* + ID_MODEL_FROM_DATABASE=WN3501D Wireless Adapter + +usb:v083Ap3503* + ID_MODEL_FROM_DATABASE=T-Sinus 111 Wireless Adapter + +usb:v083Ap4501* + ID_MODEL_FROM_DATABASE=T-Sinus 154data + +usb:v083Ap4502* + ID_MODEL_FROM_DATABASE=Siemens S30853-S1016-R107 802.11g Wireless Adapter [Intersil ISL3886] + +usb:v083Ap4505* + ID_MODEL_FROM_DATABASE=SMCWUSB-G 802.11bg + +usb:v083Ap4507* + ID_MODEL_FROM_DATABASE=SMCWUSBT-G2 802.11g Wireless Adapter [Atheros AR5523] + +usb:v083Ap4521* + ID_MODEL_FROM_DATABASE=Siemens S30863-S1016-R107-2 802.11g Wireless Adapter [Intersil ISL3887] + +usb:v083Ap4531* + ID_MODEL_FROM_DATABASE=T-Com Sinus 154 data II [Intersil ISL3887] + +usb:v083Ap5046* + ID_MODEL_FROM_DATABASE=SpeedStream 10/100 Ethernet [pegasus] + +usb:v083Ap5501* + ID_MODEL_FROM_DATABASE=Wireless Adapter 11g + +usb:v083Ap6500* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v083Ap6618* + ID_MODEL_FROM_DATABASE=802.11n Wireless Adapter + +usb:v083Ap7511* + ID_MODEL_FROM_DATABASE=Arcadyan 802.11N Wireless Adapter + +usb:v083Ap7512* + ID_MODEL_FROM_DATABASE=Arcadyan 802.11N Wireless Adapter + +usb:v083Ap7522* + ID_MODEL_FROM_DATABASE=Arcadyan 802.11N Wireless Adapter + +usb:v083Ap8522* + ID_MODEL_FROM_DATABASE=Arcadyan 802.11N Wireless Adapter + +usb:v083Ap8541* + ID_MODEL_FROM_DATABASE=WN4501F 802.11g Wireless Adapter [Intersil ISL3887] + +usb:v083ApA512* + ID_MODEL_FROM_DATABASE=Arcadyan 802.11N Wireless Adapter + +usb:v083ApA618* + ID_MODEL_FROM_DATABASE=SMCWUSBS-N EZ Connect N Draft 11n Wireless Adapter [Ralink RT2870] + +usb:v083ApA701* + ID_MODEL_FROM_DATABASE=SMCWUSBS-N3 EZ Connect N Wireless Adapter [Ralink RT3070] + +usb:v083ApB004* + ID_MODEL_FROM_DATABASE=CPWUE001 USB/Ethernet Adapter + +usb:v083ApB522* + ID_MODEL_FROM_DATABASE=SMCWUSBS-N2 EZ Connect N Wireless Adapter [Ralink RT2870] + +usb:v083ApBB01* + ID_MODEL_FROM_DATABASE=BlueExpert Bluetooth Device + +usb:v083ApC003* + ID_MODEL_FROM_DATABASE=802.11b Wireless Adapter + +usb:v083ApC501* + ID_MODEL_FROM_DATABASE=Zoom 4410 Wireless-G [Intersil ISL3887] + +usb:v083ApC561* + ID_MODEL_FROM_DATABASE=802.11a/g Wireless Adapter + +usb:v083ApD522* + ID_MODEL_FROM_DATABASE=Speedport W 102 Stick IEEE 802.11n USB 2.0 Adapter + +usb:v083ApE501* + ID_MODEL_FROM_DATABASE=ZD1211B + +usb:v083ApE503* + ID_MODEL_FROM_DATABASE=Arcadyan WN4501 802.11b/g + +usb:v083ApE506* + ID_MODEL_FROM_DATABASE=WUS-201 802.11bg + +usb:v083ApF501* + ID_MODEL_FROM_DATABASE=802.11g Wireless Adapter + +usb:v083ApF502* + ID_MODEL_FROM_DATABASE=802.11g Wireless Adapter + +usb:v083ApF522* + ID_MODEL_FROM_DATABASE=Arcadyan WN7512 802.11n + +usb:v083F* + ID_VENDOR_FROM_DATABASE=Global Village + +usb:v083FpB100* + ID_MODEL_FROM_DATABASE=TelePort V.90 Fax/Modem + +usb:v0840* + ID_VENDOR_FROM_DATABASE=Argosy Research, Inc. + +usb:v0840p0060* + ID_MODEL_FROM_DATABASE=Storage Adapter Bridge Module + +usb:v0841* + ID_VENDOR_FROM_DATABASE=Rioport.com, Inc. + +usb:v0841p0001* + ID_MODEL_FROM_DATABASE=Rio 500 + +usb:v0844* + ID_VENDOR_FROM_DATABASE=Welland Industrial Co., Ltd + +usb:v0846* + ID_VENDOR_FROM_DATABASE=NetGear, Inc. + +usb:v0846p1001* + ID_MODEL_FROM_DATABASE=EA101 10 Mbps 10BASE-T Ethernet [Kawasaki LSI KL5KLUSB101B] + +usb:v0846p1002* + ID_MODEL_FROM_DATABASE=Ethernet + +usb:v0846p1020* + ID_MODEL_FROM_DATABASE=FA101 Fast Ethernet USB 1.1 + +usb:v0846p1040* + ID_MODEL_FROM_DATABASE=FA120 Fast Ethernet USB 2.0 [Asix AX88172 / AX8817x] + +usb:v0846p1100* + ID_MODEL_FROM_DATABASE=Managed Switch M4100 series, M5300 series, M7100 series + +usb:v0846p4110* + ID_MODEL_FROM_DATABASE=MA111(v1) 802.11b Wireless [Intersil Prism 3.0] + +usb:v0846p4200* + ID_MODEL_FROM_DATABASE=WG121(v1) 54 Mbps Wireless [Intersil ISL3886] + +usb:v0846p4210* + ID_MODEL_FROM_DATABASE=WG121(v2) 54 Mbps Wireless [Intersil ISL3886] + +usb:v0846p4220* + ID_MODEL_FROM_DATABASE=WG111(v1) 54 Mbps Wireless [Intersil ISL3886] + +usb:v0846p4230* + ID_MODEL_FROM_DATABASE=MA111(v2) 802.11b Wireless [SIS SIS 162] + +usb:v0846p4240* + ID_MODEL_FROM_DATABASE=WG111(v1) rev 2 54 Mbps Wireless [Intersil ISL3887] + +usb:v0846p4260* + ID_MODEL_FROM_DATABASE=WG111v3 54 Mbps Wireless [realtek RTL8187B] + +usb:v0846p4300* + ID_MODEL_FROM_DATABASE=WG111U Double 108 Mbps Wireless [Atheros AR5004X / AR5005UX] + +usb:v0846p4301* + ID_MODEL_FROM_DATABASE=WG111U (no firmware) Double 108 Mbps Wireless [Atheros AR5004X / AR5005UX] + +usb:v0846p5F00* + ID_MODEL_FROM_DATABASE=WPN111 802.11g Wireless Adapter [Atheros AR5523] + +usb:v0846p6A00* + ID_MODEL_FROM_DATABASE=WG111v2 54 Mbps Wireless [RealTek RTL8187L] + +usb:v0846p7100* + ID_MODEL_FROM_DATABASE=WN121T RangeMax Next Wireless-N [Marvell TopDog] + +usb:v0846p9000* + ID_MODEL_FROM_DATABASE=WN111(v1) RangeMax Next Wireless [Marvell 88W8362+88W8060] + +usb:v0846p9001* + ID_MODEL_FROM_DATABASE=WN111(v2) RangeMax Next Wireless [Atheros AR9170+AR9101] + +usb:v0846p9010* + ID_MODEL_FROM_DATABASE=WNDA3100v1 802.11abgn [Atheros AR9170+AR9104] + +usb:v0846p9011* + ID_MODEL_FROM_DATABASE=WNDA3100v2 802.11abgn [Broadcom BCM4323] + +usb:v0846p9012* + ID_MODEL_FROM_DATABASE=WNDA4100 802.11abgn 3x3:3 [Ralink RT3573] + +usb:v0846p9014* + ID_MODEL_FROM_DATABASE=WNDA3100v3 802.11abgn 2x2:2 [MediaTek MT7632U] + +usb:v0846p9018* + ID_MODEL_FROM_DATABASE=WNDA3200 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] + +usb:v0846p9020* + ID_MODEL_FROM_DATABASE=WNA3100(v1) Wireless-N 300 [Broadcom BCM43231] + +usb:v0846p9021* + ID_MODEL_FROM_DATABASE=WNA3100M(v1) Wireless-N 300 [Realtek RTL8192CU] + +usb:v0846p9030* + ID_MODEL_FROM_DATABASE=WNA1100 Wireless-N 150 [Atheros AR9271] + +usb:v0846p9040* + ID_MODEL_FROM_DATABASE=WNA1000 Wireless-N 150 [Atheros AR9170+AR9101] + +usb:v0846p9041* + ID_MODEL_FROM_DATABASE=WNA1000M 802.11bgn [Realtek RTL8188CUS] + +usb:v0846p9042* + ID_MODEL_FROM_DATABASE=On Networks N150MA 802.11bgn [Realtek RTL8188CUS] + +usb:v0846p9043* + ID_MODEL_FROM_DATABASE=WNA1000Mv2 802.11bgn [Realtek RTL8188CUS?] + +usb:v0846p9050* + ID_MODEL_FROM_DATABASE=A6200 802.11a/b/g/n/ac Wireless Adapter [Broadcom BCM43526] + +usb:v0846p9051* + ID_MODEL_FROM_DATABASE=A6200v2 802.11a/b/g/n/ac (2x2) Wireless Adapter [Realtek RTL8812AU] + +usb:v0846p9052* + ID_MODEL_FROM_DATABASE=A6100 AC600 DB Wireless Adapter [Realtek RTL8811AU] + +usb:v0846pA001* + ID_MODEL_FROM_DATABASE=PA101 10 Mbps HPNA Home Phoneline RJ-1 + +usb:v0846pF001* + ID_MODEL_FROM_DATABASE=On Networks N300MA 802.11bgn [Realtek RTL8192CU] + +usb:v084D* + ID_VENDOR_FROM_DATABASE=Minton Optic Industry Co., Inc. + +usb:v084Dp0001* + ID_MODEL_FROM_DATABASE=Jenoptik JD800i + +usb:v084Dp0003* + ID_MODEL_FROM_DATABASE=S-Cam F5/D-Link DSC-350 Digital Camera + +usb:v084Dp0011* + ID_MODEL_FROM_DATABASE=Argus DC3500 Digital Camera + +usb:v084Dp0014* + ID_MODEL_FROM_DATABASE=Praktica DC 32 + +usb:v084Dp0019* + ID_MODEL_FROM_DATABASE=Praktica DPix3000 + +usb:v084Dp0025* + ID_MODEL_FROM_DATABASE=Praktica DC 60 + +usb:v084Dp1001* + ID_MODEL_FROM_DATABASE=ScanHex SX-35d + +usb:v084E* + ID_VENDOR_FROM_DATABASE=KB Gear + +usb:v084Ep0001* + ID_MODEL_FROM_DATABASE=JamCam Camera + +usb:v084Ep1001* + ID_MODEL_FROM_DATABASE=Jam Studio Tablet + +usb:v084Ep1002* + ID_MODEL_FROM_DATABASE=Pablo Tablet + +usb:v084F* + ID_VENDOR_FROM_DATABASE=Empeg + +usb:v084Fp0001* + ID_MODEL_FROM_DATABASE=Empeg-Car Mark I/II Player + +usb:v0850* + ID_VENDOR_FROM_DATABASE=Fast Point Technologies, Inc. + +usb:v0851* + ID_VENDOR_FROM_DATABASE=Macronix International Co., Ltd + +usb:v0851p1542* + ID_MODEL_FROM_DATABASE=SiPix Blink + +usb:v0851p1543* + ID_MODEL_FROM_DATABASE=Maxell WS30 Slim Digital Camera, or Pandigital PI8004W01 digital photo frame + +usb:v0851pA168* + ID_MODEL_FROM_DATABASE=MXIC + +usb:v0852* + ID_VENDOR_FROM_DATABASE=CSEM + +usb:v0853* + ID_VENDOR_FROM_DATABASE=Topre Corporation + +usb:v0853p0100* + ID_MODEL_FROM_DATABASE=HHKB Professional + +usb:v0854* + ID_VENDOR_FROM_DATABASE=ActiveWire, Inc. + +usb:v0854p0100* + ID_MODEL_FROM_DATABASE=I/O Board + +usb:v0854p0101* + ID_MODEL_FROM_DATABASE=I/O Board, rev1 + +usb:v0856* + ID_VENDOR_FROM_DATABASE=B&B Electronics + +usb:v0856pAC01* + ID_MODEL_FROM_DATABASE=uLinks USOTL4 RS422/485 Adapter + +usb:v0858* + ID_VENDOR_FROM_DATABASE=Hitachi Maxell, Ltd + +usb:v0858p3102* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0858pFFFF* + ID_MODEL_FROM_DATABASE=Maxell module with BlueCore in DFU mode + +usb:v0859* + ID_VENDOR_FROM_DATABASE=Minolta Systems Laboratory, Inc. + +usb:v085A* + ID_VENDOR_FROM_DATABASE=Xircom + +usb:v085Ap0001* + ID_MODEL_FROM_DATABASE=Portstation Dual Serial Port + +usb:v085Ap0003* + ID_MODEL_FROM_DATABASE=Portstation Paraller Port + +usb:v085Ap0008* + ID_MODEL_FROM_DATABASE=Ethernet + +usb:v085Ap0009* + ID_MODEL_FROM_DATABASE=Ethernet + +usb:v085Ap000B* + ID_MODEL_FROM_DATABASE=Portstation Dual PS/2 Port + +usb:v085Ap0021* + ID_MODEL_FROM_DATABASE=1 port to Serial Converter + +usb:v085Ap0022* + ID_MODEL_FROM_DATABASE=Parallel Port + +usb:v085Ap0023* + ID_MODEL_FROM_DATABASE=2 port to Serial Converter + +usb:v085Ap0024* + ID_MODEL_FROM_DATABASE=Parallel Port + +usb:v085Ap0026* + ID_MODEL_FROM_DATABASE=PortGear SCSI + +usb:v085Ap0027* + ID_MODEL_FROM_DATABASE=1 port to Serial Converter + +usb:v085Ap0028* + ID_MODEL_FROM_DATABASE=PortGear to SCSI Converter + +usb:v085Ap0032* + ID_MODEL_FROM_DATABASE=PortStation SCSI Module + +usb:v085Ap003C* + ID_MODEL_FROM_DATABASE=Bluetooth Adapter + +usb:v085Ap0299* + ID_MODEL_FROM_DATABASE=Colorvision, Inc. Monitor Spyder + +usb:v085Ap8021* + ID_MODEL_FROM_DATABASE=1 port to Serial + +usb:v085Ap8023* + ID_MODEL_FROM_DATABASE=2 port to Serial + +usb:v085Ap8027* + ID_MODEL_FROM_DATABASE=PGSDB9 Serial Port + +usb:v085C* + ID_VENDOR_FROM_DATABASE=ColorVision, Inc. + +usb:v085Cp0100* + ID_MODEL_FROM_DATABASE=Spyder 1 + +usb:v085Cp0200* + ID_MODEL_FROM_DATABASE=Spyder 2 + +usb:v085Cp0300* + ID_MODEL_FROM_DATABASE=Spyder 3 + +usb:v085Cp0400* + ID_MODEL_FROM_DATABASE=Spyder 4 + +usb:v0862* + ID_VENDOR_FROM_DATABASE=Teletrol Systems, Inc. + +usb:v0863* + ID_VENDOR_FROM_DATABASE=Filanet Corp. + +usb:v0864* + ID_VENDOR_FROM_DATABASE=NetGear, Inc. + +usb:v0864p4100* + ID_MODEL_FROM_DATABASE=MA101 802.11b Adapter + +usb:v0864p4102* + ID_MODEL_FROM_DATABASE=MA101 802.11b Adapter + +usb:v0867* + ID_VENDOR_FROM_DATABASE=Data Translation, Inc. + +usb:v0867p9812* + ID_MODEL_FROM_DATABASE=ECON Data acquisition unit + +usb:v0867p9816* + ID_MODEL_FROM_DATABASE=DT9816 ECON data acquisition module + +usb:v0867p9836* + ID_MODEL_FROM_DATABASE=DT9836 data acquisition card + +usb:v086A* + ID_VENDOR_FROM_DATABASE=Emagic Soft- und Hardware GmbH + +usb:v086Ap0001* + ID_MODEL_FROM_DATABASE=Unitor8 + +usb:v086Ap0002* + ID_MODEL_FROM_DATABASE=AMT8 + +usb:v086Ap0003* + ID_MODEL_FROM_DATABASE=MT4 + +usb:v086C* + ID_VENDOR_FROM_DATABASE=DeTeWe - Deutsche Telephonwerke AG & Co. + +usb:v086Cp1001* + ID_MODEL_FROM_DATABASE=Eumex 504PC ISDN TA + +usb:v086Cp1002* + ID_MODEL_FROM_DATABASE=Eumex 504PC (FlashLoad) + +usb:v086Cp1003* + ID_MODEL_FROM_DATABASE=TA33 ISDN TA + +usb:v086Cp1004* + ID_MODEL_FROM_DATABASE=TA33 (FlashLoad) + +usb:v086Cp1005* + ID_MODEL_FROM_DATABASE=Eumex 604PC HomeNet + +usb:v086Cp1006* + ID_MODEL_FROM_DATABASE=Eumex 604PC HomeNet (FlashLoad) + +usb:v086Cp1007* + ID_MODEL_FROM_DATABASE=Eumex 704PC DSL + +usb:v086Cp1008* + ID_MODEL_FROM_DATABASE=Eumex 704PC DSL (FlashLoad) + +usb:v086Cp1009* + ID_MODEL_FROM_DATABASE=Eumex 724PC DSL + +usb:v086Cp100A* + ID_MODEL_FROM_DATABASE=Eumex 724PC DSL (FlashLoad) + +usb:v086Cp100B* + ID_MODEL_FROM_DATABASE=OpenCom 30 + +usb:v086Cp100C* + ID_MODEL_FROM_DATABASE=OpenCom 30 (FlashLoad) + +usb:v086Cp100D* + ID_MODEL_FROM_DATABASE=BeeTel Home 100 + +usb:v086Cp100E* + ID_MODEL_FROM_DATABASE=BeeTel Home 100 (FlashLoad) + +usb:v086Cp1011* + ID_MODEL_FROM_DATABASE=USB2DECT + +usb:v086Cp1012* + ID_MODEL_FROM_DATABASE=USB2DECT (FlashLoad) + +usb:v086Cp1013* + ID_MODEL_FROM_DATABASE=Eumex 704PC LAN + +usb:v086Cp1014* + ID_MODEL_FROM_DATABASE=Eumex 704PC LAN (FlashLoad) + +usb:v086Cp1019* + ID_MODEL_FROM_DATABASE=Eumex 504 SE + +usb:v086Cp101A* + ID_MODEL_FROM_DATABASE=Eumex 504 SE (Flash-Mode) + +usb:v086Cp1021* + ID_MODEL_FROM_DATABASE=OpenCom 40 + +usb:v086Cp1022* + ID_MODEL_FROM_DATABASE=OpenCom 40 (FlashLoad) + +usb:v086Cp1023* + ID_MODEL_FROM_DATABASE=OpenCom 45 + +usb:v086Cp1024* + ID_MODEL_FROM_DATABASE=OpenCom 45 (FlashLoad) + +usb:v086Cp1025* + ID_MODEL_FROM_DATABASE=Sinus 61 data + +usb:v086Cp1029* + ID_MODEL_FROM_DATABASE=dect BOX + +usb:v086Cp102C* + ID_MODEL_FROM_DATABASE=Eumex 604PC HomeNet [FlashLoad] + +usb:v086Cp1030* + ID_MODEL_FROM_DATABASE=Eumex 704PC DSL [FlashLoad] + +usb:v086Cp1032* + ID_MODEL_FROM_DATABASE=OpenCom 40 [FlashLoad] + +usb:v086Cp1033* + ID_MODEL_FROM_DATABASE=OpenCom 30 plus + +usb:v086Cp1034* + ID_MODEL_FROM_DATABASE=OpenCom 30 plus (FlashLoad) + +usb:v086Cp1041* + ID_MODEL_FROM_DATABASE=Eumex 220PC + +usb:v086Cp1042* + ID_MODEL_FROM_DATABASE=Eumex 220PC (FlashMode) + +usb:v086Cp1055* + ID_MODEL_FROM_DATABASE=Eumex 220 Version 2 ISDN TA + +usb:v086Cp1056* + ID_MODEL_FROM_DATABASE=Eumex 220 Version 2 ISDN TA (Flash-Mode) + +usb:v086Cp2000* + ID_MODEL_FROM_DATABASE=OpenCom 1000 + +usb:v086E* + ID_VENDOR_FROM_DATABASE=System TALKS, Inc. + +usb:v086Ep1920* + ID_MODEL_FROM_DATABASE=SGC-X2UL + +usb:v086F* + ID_VENDOR_FROM_DATABASE=MEC IMEX, Inc. + +usb:v0870* + ID_VENDOR_FROM_DATABASE=Metricom + +usb:v0870p0001* + ID_MODEL_FROM_DATABASE=Ricochet GS + +usb:v0871* + ID_VENDOR_FROM_DATABASE=SanDisk, Inc. + +usb:v0871p0001* + ID_MODEL_FROM_DATABASE=SDDR-01 Compact Flash Reader + +usb:v0871p0002* + ID_MODEL_FROM_DATABASE=SDDR-31 Compact Flash Reader + +usb:v0871p0005* + ID_MODEL_FROM_DATABASE=SDDR-05 Compact Flash Reader + +usb:v0873* + ID_VENDOR_FROM_DATABASE=Xpeed, Inc. + +usb:v0874* + ID_VENDOR_FROM_DATABASE=A-Tec Subsystem, Inc. + +usb:v0879* + ID_VENDOR_FROM_DATABASE=Comtrol Corp. + +usb:v087C* + ID_VENDOR_FROM_DATABASE=Adesso/Kbtek America, Inc. + +usb:v087D* + ID_VENDOR_FROM_DATABASE=Jaton Corp. + +usb:v087Dp5704* + ID_MODEL_FROM_DATABASE=Ethernet + +usb:v087E* + ID_VENDOR_FROM_DATABASE=Fujitsu Computer Products of America + +usb:v087F* + ID_VENDOR_FROM_DATABASE=QualCore Logic Inc. + +usb:v0880* + ID_VENDOR_FROM_DATABASE=APT Technologies, Inc. + +usb:v0883* + ID_VENDOR_FROM_DATABASE=Recording Industry Association of America (RIAA) + +usb:v0885* + ID_VENDOR_FROM_DATABASE=Boca Research, Inc. + +usb:v0886* + ID_VENDOR_FROM_DATABASE=XAC Automation Corp. + +usb:v0886p0630* + ID_MODEL_FROM_DATABASE=Intel PC Camera CS630 + +usb:v0887* + ID_VENDOR_FROM_DATABASE=Hannstar Electronics Corp. + +usb:v088A* + ID_VENDOR_FROM_DATABASE=TechTools + +usb:v088Ap1002* + ID_MODEL_FROM_DATABASE=DigiView DV3100 + +usb:v088B* + ID_VENDOR_FROM_DATABASE=MassWorks, Inc. + +usb:v088Bp4944* + ID_MODEL_FROM_DATABASE=MassWorks ID-75 TouchScreen + +usb:v088C* + ID_VENDOR_FROM_DATABASE=Swecoin AB + +usb:v088Cp2030* + ID_MODEL_FROM_DATABASE=Ticket Printer TTP 2030 + +usb:v088E* + ID_VENDOR_FROM_DATABASE=iLok + +usb:v088Ep5036* + ID_MODEL_FROM_DATABASE=Portable secure storage for software licenses + +usb:v0892* + ID_VENDOR_FROM_DATABASE=DioGraphy, Inc. + +usb:v0892p0101* + ID_MODEL_FROM_DATABASE=Smartdio Reader/Writer + +usb:v0894* + ID_VENDOR_FROM_DATABASE=TSI Incorporated + +usb:v0894p0010* + ID_MODEL_FROM_DATABASE=Remote NDIS Network Device + +usb:v0897* + ID_VENDOR_FROM_DATABASE=Lauterbach + +usb:v0897p0001* + ID_MODEL_FROM_DATABASE=ICE In-Circuit Emulator + +usb:v0897p0002* + ID_MODEL_FROM_DATABASE=Power Debug/Power Debug II + +usb:v0897p0004* + ID_MODEL_FROM_DATABASE=PowerDebug + +usb:v0897p0005* + ID_MODEL_FROM_DATABASE=PowerDebug PRO + +usb:v089C* + ID_VENDOR_FROM_DATABASE=United Technologies Research Cntr. + +usb:v089D* + ID_VENDOR_FROM_DATABASE=Icron Technologies Corp. + +usb:v089E* + ID_VENDOR_FROM_DATABASE=NST Co., Ltd + +usb:v089F* + ID_VENDOR_FROM_DATABASE=Primex Aerospace Co. + +usb:v08A5* + ID_VENDOR_FROM_DATABASE=e9, Inc. + +usb:v08A6* + ID_VENDOR_FROM_DATABASE=Toshiba TEC + +usb:v08A6p0051* + ID_MODEL_FROM_DATABASE=B-SV4 + +usb:v08A8* + ID_VENDOR_FROM_DATABASE=Andrea Electronics + +usb:v08A9* + ID_VENDOR_FROM_DATABASE=CWAV Inc. + +usb:v08A9p0005* + ID_MODEL_FROM_DATABASE=USBee ZX + +usb:v08A9p0009* + ID_MODEL_FROM_DATABASE=USBee SX + +usb:v08A9p0012* + ID_MODEL_FROM_DATABASE=USBee AX-Standard + +usb:v08A9p0013* + ID_MODEL_FROM_DATABASE=USBee AX-Plus + +usb:v08A9p0014* + ID_MODEL_FROM_DATABASE=USBee AX-Pro + +usb:v08A9p0015* + ID_MODEL_FROM_DATABASE=USBee DX + +usb:v08AC* + ID_VENDOR_FROM_DATABASE=Macraigor Systems LLC + +usb:v08ACp2024* + ID_MODEL_FROM_DATABASE=usbWiggler + +usb:v08AE* + ID_VENDOR_FROM_DATABASE=Macally (Mace Group, Inc.) + +usb:v08B0* + ID_VENDOR_FROM_DATABASE=Metrohm + +usb:v08B0p0006* + ID_MODEL_FROM_DATABASE=814 Sample Processor + +usb:v08B0p0015* + ID_MODEL_FROM_DATABASE=857 Titrando + +usb:v08B0p001A* + ID_MODEL_FROM_DATABASE=852 Titrando + +usb:v08B4* + ID_VENDOR_FROM_DATABASE=Sorenson Vision, Inc. + +usb:v08B7* + ID_VENDOR_FROM_DATABASE=NATSU + +usb:v08B7p0001* + ID_MODEL_FROM_DATABASE=Playstation adapter + +usb:v08B8* + ID_VENDOR_FROM_DATABASE=J. Gordon Electronic Design, Inc. + +usb:v08B8p01F4* + ID_MODEL_FROM_DATABASE=USBSIMM1 + +usb:v08B9* + ID_VENDOR_FROM_DATABASE=RadioShack Corp. (Tandy) + +usb:v08BB* + ID_VENDOR_FROM_DATABASE=Texas Instruments + +usb:v08BBp2702* + ID_MODEL_FROM_DATABASE=PCM2702 16-bit stereo audio DAC + +usb:v08BBp2704* + ID_MODEL_FROM_DATABASE=PCM2704 16-bit stereo audio DAC + +usb:v08BBp2705* + ID_MODEL_FROM_DATABASE=PCM2705 stereo audio DAC + +usb:v08BBp2706* + ID_MODEL_FROM_DATABASE=PCM2706 stereo audio DAC + +usb:v08BBp2707* + ID_MODEL_FROM_DATABASE=PCM2707 stereo audio DAC + +usb:v08BBp27C4* + ID_MODEL_FROM_DATABASE=PCM2704C stereo audio DAC + +usb:v08BBp27C5* + ID_MODEL_FROM_DATABASE=PCM2705C stereo audio DAC + +usb:v08BBp27C6* + ID_MODEL_FROM_DATABASE=PCM2706C stereo audio DAC + +usb:v08BBp27C7* + ID_MODEL_FROM_DATABASE=PCM2707C stereo audio DAC + +usb:v08BBp2900* + ID_MODEL_FROM_DATABASE=PCM2900 Audio Codec + +usb:v08BBp2901* + ID_MODEL_FROM_DATABASE=PCM2901 Audio Codec + +usb:v08BBp2902* + ID_MODEL_FROM_DATABASE=PCM2902 Audio Codec + +usb:v08BBp2904* + ID_MODEL_FROM_DATABASE=PCM2904 Audio Codec + +usb:v08BBp2910* + ID_MODEL_FROM_DATABASE=PCM2912 Audio Codec + +usb:v08BBp2912* + ID_MODEL_FROM_DATABASE=PCM2912A Audio Codec + +usb:v08BBp29B0* + ID_MODEL_FROM_DATABASE=PCM2900B Audio CODEC + +usb:v08BBp29B2* + ID_MODEL_FROM_DATABASE=PCM2902 Audio CODEC + +usb:v08BBp29B3* + ID_MODEL_FROM_DATABASE=PCM2903B Audio CODEC + +usb:v08BBp29B6* + ID_MODEL_FROM_DATABASE=PCM2906B Audio CODEC + +usb:v08BBp29C0* + ID_MODEL_FROM_DATABASE=PCM2900C Audio CODEC + +usb:v08BBp29C2* + ID_MODEL_FROM_DATABASE=PCM2902C Audio CODEC + +usb:v08BBp29C3* + ID_MODEL_FROM_DATABASE=PCM2903C Audio CODEC + +usb:v08BBp29C6* + ID_MODEL_FROM_DATABASE=PCM2906C Audio CODEC + +usb:v08BD* + ID_VENDOR_FROM_DATABASE=Citizen Watch Co., Ltd + +usb:v08BDp0208* + ID_MODEL_FROM_DATABASE=CLP-521 Label Printer + +usb:v08BDp1100* + ID_MODEL_FROM_DATABASE=X1-USB Floppy + +usb:v08C3* + ID_VENDOR_FROM_DATABASE=Precise Biometrics + +usb:v08C3p0001* + ID_MODEL_FROM_DATABASE=100 SC + +usb:v08C3p0002* + ID_MODEL_FROM_DATABASE=100 A + +usb:v08C3p0003* + ID_MODEL_FROM_DATABASE=100 SC BioKeyboard + +usb:v08C3p0006* + ID_MODEL_FROM_DATABASE=100 A BioKeyboard + +usb:v08C3p0100* + ID_MODEL_FROM_DATABASE=100 MC ISP + +usb:v08C3p0101* + ID_MODEL_FROM_DATABASE=100 MC FingerPrint and SmartCard Reader + +usb:v08C3p0300* + ID_MODEL_FROM_DATABASE=100 AX + +usb:v08C3p0400* + ID_MODEL_FROM_DATABASE=100 SC + +usb:v08C3p0401* + ID_MODEL_FROM_DATABASE=150 MC + +usb:v08C3p0402* + ID_MODEL_FROM_DATABASE=200 MC FingerPrint and SmartCard Reader + +usb:v08C3p0404* + ID_MODEL_FROM_DATABASE=100 SC Upgrade + +usb:v08C3p0405* + ID_MODEL_FROM_DATABASE=150 MC Upgrade + +usb:v08C3p0406* + ID_MODEL_FROM_DATABASE=100 MC Upgrade + +usb:v08C4* + ID_VENDOR_FROM_DATABASE=Proxim, Inc. + +usb:v08C4p0100* + ID_MODEL_FROM_DATABASE=Skyline 802.11b Wireless Adapter + +usb:v08C4p02F2* + ID_MODEL_FROM_DATABASE=Farallon Home Phoneline Adapter + +usb:v08C7* + ID_VENDOR_FROM_DATABASE=Key Nice Enterprise Co., Ltd + +usb:v08C8* + ID_VENDOR_FROM_DATABASE=2Wire, Inc. + +usb:v08C9* + ID_VENDOR_FROM_DATABASE=Nippon Telegraph and Telephone Corp. + +usb:v08CA* + ID_VENDOR_FROM_DATABASE=Aiptek International, Inc. + +usb:v08CAp0001* + ID_MODEL_FROM_DATABASE=Tablet + +usb:v08CAp0010* + ID_MODEL_FROM_DATABASE=Tablet + +usb:v08CAp0020* + ID_MODEL_FROM_DATABASE=APT-6000U Tablet + +usb:v08CAp0021* + ID_MODEL_FROM_DATABASE=APT-2 Tablet + +usb:v08CAp0022* + ID_MODEL_FROM_DATABASE=Tablet + +usb:v08CAp0023* + ID_MODEL_FROM_DATABASE=Tablet + +usb:v08CAp0024* + ID_MODEL_FROM_DATABASE=Tablet + +usb:v08CAp0100* + ID_MODEL_FROM_DATABASE=Pen Drive + +usb:v08CAp0102* + ID_MODEL_FROM_DATABASE=DualCam + +usb:v08CAp0103* + ID_MODEL_FROM_DATABASE=Pocket DV Digital Camera + +usb:v08CAp0104* + ID_MODEL_FROM_DATABASE=Pocket DVII + +usb:v08CAp0105* + ID_MODEL_FROM_DATABASE=Mega DV(Disk) + +usb:v08CAp0106* + ID_MODEL_FROM_DATABASE=Pocket DV3100+ + +usb:v08CAp0107* + ID_MODEL_FROM_DATABASE=Pocket DV3100 + +usb:v08CAp0109* + ID_MODEL_FROM_DATABASE=Nisis DV4 Digital Camera + +usb:v08CAp010A* + ID_MODEL_FROM_DATABASE=Trust 738AV LCD PV Mass Storage + +usb:v08CAp0111* + ID_MODEL_FROM_DATABASE=PenCam VGA Plus + +usb:v08CAp2008* + ID_MODEL_FROM_DATABASE=Mini PenCam 2 + +usb:v08CAp2010* + ID_MODEL_FROM_DATABASE=Pocket CAM 3 Mega (webcam) + +usb:v08CAp2011* + ID_MODEL_FROM_DATABASE=Pocket CAM 3 Mega (storage) + +usb:v08CAp2016* + ID_MODEL_FROM_DATABASE=PocketCam 2 Mega + +usb:v08CAp2018* + ID_MODEL_FROM_DATABASE=Pencam SD 2M + +usb:v08CAp2019* + ID_MODEL_FROM_DATABASE=Pencam SD 2M (mass storage mode) + +usb:v08CAp2020* + ID_MODEL_FROM_DATABASE=Slim 3000F + +usb:v08CAp2022* + ID_MODEL_FROM_DATABASE=Slim 3200 + +usb:v08CAp2024* + ID_MODEL_FROM_DATABASE=Pocket DV3500 + +usb:v08CAp2028* + ID_MODEL_FROM_DATABASE=Pocket Cam4M + +usb:v08CAp2040* + ID_MODEL_FROM_DATABASE=Pocket DV4100M + +usb:v08CAp2042* + ID_MODEL_FROM_DATABASE=Pocket DV5100M Composite Device + +usb:v08CAp2043* + ID_MODEL_FROM_DATABASE=Pocket DV5100M (Disk) + +usb:v08CAp2060* + ID_MODEL_FROM_DATABASE=Pocket DV5300 + +usb:v08CD* + ID_VENDOR_FROM_DATABASE=Jue Hsun Ind. Corp. + +usb:v08CE* + ID_VENDOR_FROM_DATABASE=Long Well Electronics Corp. + +usb:v08CF* + ID_VENDOR_FROM_DATABASE=Productivity Enhancement Products + +usb:v08D1* + ID_VENDOR_FROM_DATABASE=smartBridges, Inc. + +usb:v08D1p0001* + ID_MODEL_FROM_DATABASE=smartNIC Ethernet [catc] + +usb:v08D1p0003* + ID_MODEL_FROM_DATABASE=smartNIC 2 PnP Ethernet + +usb:v08D3* + ID_VENDOR_FROM_DATABASE=Virtual Ink + +usb:v08D4* + ID_VENDOR_FROM_DATABASE=Fujitsu Siemens Computers + +usb:v08D4p0009* + ID_MODEL_FROM_DATABASE=SCR SmartCard Reader + +usb:v08D8* + ID_VENDOR_FROM_DATABASE=IXXAT Automation GmbH + +usb:v08D8p0002* + ID_MODEL_FROM_DATABASE=USB-to-CAN compact + +usb:v08D8p0003* + ID_MODEL_FROM_DATABASE=USB-to-CAN II + +usb:v08D8p0100* + ID_MODEL_FROM_DATABASE=USB-to-CAN + +usb:v08D9* + ID_VENDOR_FROM_DATABASE=Increment P Corp. + +usb:v08DD* + ID_VENDOR_FROM_DATABASE=Billionton Systems, Inc. + +usb:v08DDp0112* + ID_MODEL_FROM_DATABASE=Wireless LAN Adapter + +usb:v08DDp0113* + ID_MODEL_FROM_DATABASE=Wireless LAN Adapter + +usb:v08DDp0986* + ID_MODEL_FROM_DATABASE=USB-100N Ethernet [pegasus] + +usb:v08DDp0987* + ID_MODEL_FROM_DATABASE=USBLP-100 HomePNA Ethernet [pegasus] + +usb:v08DDp0988* + ID_MODEL_FROM_DATABASE=USBEL-100 Ethernet [pegasus] + +usb:v08DDp1986* + ID_MODEL_FROM_DATABASE=10/100 LAN Adapter + +usb:v08DDp2103* + ID_MODEL_FROM_DATABASE=DVB-T TV-Tuner Card-R + +usb:v08DDp8511* + ID_MODEL_FROM_DATABASE=USBE-100 Ethernet [pegasus2] + +usb:v08DDp90FF* + ID_MODEL_FROM_DATABASE=USB2AR Ethernet + +usb:v08DE* + ID_VENDOR_FROM_DATABASE=??? + +usb:v08DEp7A01* + ID_MODEL_FROM_DATABASE=802.11b Adapter + +usb:v08DF* + ID_VENDOR_FROM_DATABASE=Spyrus, Inc. + +usb:v08DFp0001* + ID_MODEL_FROM_DATABASE=Rosetta Token V1 + +usb:v08DFp0002* + ID_MODEL_FROM_DATABASE=Rosetta Token V2 + +usb:v08DFp0003* + ID_MODEL_FROM_DATABASE=Rosetta Token V3 + +usb:v08DFp0A00* + ID_MODEL_FROM_DATABASE=Lynks Interface + +usb:v08E3* + ID_VENDOR_FROM_DATABASE=Olitec, Inc. + +usb:v08E3p0002* + ID_MODEL_FROM_DATABASE=USB-RS232 Bridge + +usb:v08E3p0100* + ID_MODEL_FROM_DATABASE=Interface ADSL + +usb:v08E3p0101* + ID_MODEL_FROM_DATABASE=Interface ADSL + +usb:v08E3p0102* + ID_MODEL_FROM_DATABASE=ADSL + +usb:v08E3p0301* + ID_MODEL_FROM_DATABASE=RNIS ISDN TA [HFC-S] + +usb:v08E4* + ID_VENDOR_FROM_DATABASE=Pioneer Corp. + +usb:v08E4p0184* + ID_MODEL_FROM_DATABASE=DDJ-WeGO + +usb:v08E4p0185* + ID_MODEL_FROM_DATABASE=DDJ-WeGO2 + +usb:v08E5* + ID_VENDOR_FROM_DATABASE=Litronic + +usb:v08E6* + ID_VENDOR_FROM_DATABASE=Gemalto (was Gemplus) + +usb:v08E6p0001* + ID_MODEL_FROM_DATABASE=GemPC-Touch 430 + +usb:v08E6p0430* + ID_MODEL_FROM_DATABASE=GemPC430 SmartCard Reader + +usb:v08E6p0432* + ID_MODEL_FROM_DATABASE=GemPC432 SmartCard Reader + +usb:v08E6p0435* + ID_MODEL_FROM_DATABASE=GemPC435 SmartCard Reader + +usb:v08E6p0437* + ID_MODEL_FROM_DATABASE=GemPC433 SL SmartCard Reader + +usb:v08E6p1359* + ID_MODEL_FROM_DATABASE=UA SECURE STORAGE TOKEN + +usb:v08E6p2202* + ID_MODEL_FROM_DATABASE=Gem e-Seal Pro Token + +usb:v08E6p3437* + ID_MODEL_FROM_DATABASE=GemPC Twin SmartCard Reader + +usb:v08E6p3438* + ID_MODEL_FROM_DATABASE=GemPC Key SmartCard Reader + +usb:v08E6p3478* + ID_MODEL_FROM_DATABASE=PinPad Smart Card Reader + +usb:v08E6p34EC* + ID_MODEL_FROM_DATABASE=Compact Smart Card Reader Writer + +usb:v08E6p4433* + ID_MODEL_FROM_DATABASE=GemPC433-Swap + +usb:v08E6p5501* + ID_MODEL_FROM_DATABASE=GemProx-PU Contactless Smart Card Reader + +usb:v08E6p5503* + ID_MODEL_FROM_DATABASE=Prox-DU Contactless Interface + +usb:v08E6pACE0* + ID_MODEL_FROM_DATABASE=UA HYBRID TOKEN + +usb:v08E7* + ID_VENDOR_FROM_DATABASE=Pan-International Wire & Cable + +usb:v08E8* + ID_VENDOR_FROM_DATABASE=Integrated Memory Logic + +usb:v08E9* + ID_VENDOR_FROM_DATABASE=Extended Systems, Inc. + +usb:v08E9p0100* + ID_MODEL_FROM_DATABASE=XTNDAccess IrDA Dongle + +usb:v08EA* + ID_VENDOR_FROM_DATABASE=Ericsson, Inc., Blue Ridge Labs + +usb:v08EAp00C9* + ID_MODEL_FROM_DATABASE=ADSL Modem HM120dp Loader + +usb:v08EAp00CA* + ID_MODEL_FROM_DATABASE=ADSL WAN Modem HM120dp + +usb:v08EAp00CE* + ID_MODEL_FROM_DATABASE=HM230d Virtual Bus for Helium + +usb:v08EApABBA* + ID_MODEL_FROM_DATABASE=USB Driver for Bluetooth Wireless Technology + +usb:v08EApABBB* + ID_MODEL_FROM_DATABASE=Bluetooth Device in DFU State + +usb:v08EC* + ID_VENDOR_FROM_DATABASE=M-Systems Flash Disk Pioneers + +usb:v08ECp0001* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v08ECp0002* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v08ECp0005* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v08ECp0008* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v08ECp0010* + ID_MODEL_FROM_DATABASE=DiskOnKey + +usb:v08ECp0011* + ID_MODEL_FROM_DATABASE=DiskOnKey + +usb:v08ECp0012* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v08ECp0014* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v08ECp0015* + ID_MODEL_FROM_DATABASE=Kingston DataTraveler ELITE + +usb:v08ECp0016* + ID_MODEL_FROM_DATABASE=Kingston DataTraveler U3 + +usb:v08ECp0020* + ID_MODEL_FROM_DATABASE=TravelDrive Intuix U3 2GB + +usb:v08ECp0021* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp0022* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp0023* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp0024* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp0025* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp0026* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp0027* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp0028* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp0029* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp0030* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp0822* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v08ECp0832* + ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device + +usb:v08ECp0834* + ID_MODEL_FROM_DATABASE=M-Disk 220 + +usb:v08ECp0998* + ID_MODEL_FROM_DATABASE=Kingston Data Traveler2.0 Disk Driver + +usb:v08ECp0999* + ID_MODEL_FROM_DATABASE=Kingston Data Traveler2.0 Disk Driver + +usb:v08ECp1000* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v08ECp2000* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v08ECp2038* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp2039* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp204A* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ECp204B* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v08ED* + ID_VENDOR_FROM_DATABASE=MediaTek Inc. + +usb:v08EDp0002* + ID_MODEL_FROM_DATABASE=CECT M800 memory card + +usb:v08EE* + ID_VENDOR_FROM_DATABASE=CCSI/Hesso + +usb:v08F0* + ID_VENDOR_FROM_DATABASE=Corex Technologies + +usb:v08F0p0005* + ID_MODEL_FROM_DATABASE=CardScan 800c + +usb:v08F1* + ID_VENDOR_FROM_DATABASE=CTI Electronics Corp. + +usb:v08F2* + ID_VENDOR_FROM_DATABASE=Gotop Information Inc. + +usb:v08F2p007F* + ID_MODEL_FROM_DATABASE=Super Q2 Tablet + +usb:v08F5* + ID_VENDOR_FROM_DATABASE=SysTec Co., Ltd + +usb:v08F6* + ID_VENDOR_FROM_DATABASE=Logic 3 International, Ltd + +usb:v08F7* + ID_VENDOR_FROM_DATABASE=Vernier + +usb:v08F7p0001* + ID_MODEL_FROM_DATABASE=LabPro + +usb:v08F7p0002* + ID_MODEL_FROM_DATABASE=EasyTemp/Go!Temp + +usb:v08F7p0003* + ID_MODEL_FROM_DATABASE=Go!Link + +usb:v08F7p0004* + ID_MODEL_FROM_DATABASE=Go!Motion + +usb:v08F8* + ID_VENDOR_FROM_DATABASE=Keen Top International Enterprise Co., Ltd + +usb:v08F9* + ID_VENDOR_FROM_DATABASE=Wipro Technologies + +usb:v08FA* + ID_VENDOR_FROM_DATABASE=Caere + +usb:v08FB* + ID_VENDOR_FROM_DATABASE=Socket Communications + +usb:v08FC* + ID_VENDOR_FROM_DATABASE=Sicon Cable Technology Co., Ltd + +usb:v08FD* + ID_VENDOR_FROM_DATABASE=Digianswer A/S + +usb:v08FDp0001* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v08FF* + ID_VENDOR_FROM_DATABASE=AuthenTec, Inc. + +usb:v08FFp1600* + ID_MODEL_FROM_DATABASE=AES1600 + +usb:v08FFp1610* + ID_MODEL_FROM_DATABASE=AES1600 + +usb:v08FFp1660* + ID_MODEL_FROM_DATABASE=AES1660 Fingerprint Sensor + +usb:v08FFp1680* + ID_MODEL_FROM_DATABASE=AES1660 Fingerprint Sensor + +usb:v08FFp168F* + ID_MODEL_FROM_DATABASE=AES1660 Fingerprint Sensor + +usb:v08FFp2500* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2501* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2502* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2503* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2504* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2505* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2506* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2507* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2508* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2509* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp250A* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp250B* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp250C* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp250D* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp250E* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp250F* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2510* + ID_MODEL_FROM_DATABASE=AES2510 + +usb:v08FFp2550* + ID_MODEL_FROM_DATABASE=AES2550 Fingerprint Sensor + +usb:v08FFp2580* + ID_MODEL_FROM_DATABASE=AES2501 Fingerprint Sensor + +usb:v08FFp2588* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2589* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp258A* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp258B* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp258C* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp258D* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp258E* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp258F* + ID_MODEL_FROM_DATABASE=AES2501 + +usb:v08FFp2660* + ID_MODEL_FROM_DATABASE=AES2660 Fingerprint Sensor + +usb:v08FFp2680* + ID_MODEL_FROM_DATABASE=AES2660 Fingerprint Sensor + +usb:v08FFp268F* + ID_MODEL_FROM_DATABASE=AES2660 Fingerprint Sensor + +usb:v08FFp2810* + ID_MODEL_FROM_DATABASE=AES2810 + +usb:v08FFp3400* + ID_MODEL_FROM_DATABASE=AES3400 TruePrint Sensor + +usb:v08FFp3401* + ID_MODEL_FROM_DATABASE=AES3400 Sensor + +usb:v08FFp3402* + ID_MODEL_FROM_DATABASE=AES3400 Sensor + +usb:v08FFp3403* + ID_MODEL_FROM_DATABASE=AES3400 Sensor + +usb:v08FFp3404* + ID_MODEL_FROM_DATABASE=AES3400 TruePrint Sensor + +usb:v08FFp3405* + ID_MODEL_FROM_DATABASE=AES3400 TruePrint Sensor + +usb:v08FFp3406* + ID_MODEL_FROM_DATABASE=AES3400 TruePrint Sensor + +usb:v08FFp3407* + ID_MODEL_FROM_DATABASE=AES3400 TruePrint Sensor + +usb:v08FFp4902* + ID_MODEL_FROM_DATABASE=BioMV with TruePrint AES3500 + +usb:v08FFp4903* + ID_MODEL_FROM_DATABASE=BioMV with TruePrint AES3400 + +usb:v08FFp5500* + ID_MODEL_FROM_DATABASE=AES4000 + +usb:v08FFp5501* + ID_MODEL_FROM_DATABASE=AES4000 TruePrint Sensor + +usb:v08FFp5503* + ID_MODEL_FROM_DATABASE=AES4000 TruePrint Sensor + +usb:v08FFp5505* + ID_MODEL_FROM_DATABASE=AES4000 TruePrint Sensor + +usb:v08FFp5507* + ID_MODEL_FROM_DATABASE=AES4000 TruePrint Sensor + +usb:v08FFp55FF* + ID_MODEL_FROM_DATABASE=AES4000 TruePrint Sensor. + +usb:v08FFp5700* + ID_MODEL_FROM_DATABASE=AES3500 Fingerprint Reader + +usb:v08FFp5701* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5702* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5703* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5704* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5705* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5706* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5707* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5710* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5711* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5712* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5713* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5714* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5715* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5716* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5717* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5730* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5731* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5732* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5733* + ID_MODEL_FROM_DATABASE=AES3500 TruePrint Sensor + +usb:v08FFp5734* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5735* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5736* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFp5737* + ID_MODEL_FROM_DATABASE=AES3500-BZ TruePrint Sensor + +usb:v08FFpAFE3* + ID_MODEL_FROM_DATABASE=FingerLoc Sensor Module (Anchor) + +usb:v08FFpAFE4* + ID_MODEL_FROM_DATABASE=FingerLoc Sensor Module (Anchor) + +usb:v08FFpAFE5* + ID_MODEL_FROM_DATABASE=FingerLoc Sensor Module (Anchor) + +usb:v08FFpAFE6* + ID_MODEL_FROM_DATABASE=FingerLoc Sensor Module (Anchor) + +usb:v08FFpFFFD* + ID_MODEL_FROM_DATABASE=AES2510 Sensor (USB Emulator) + +usb:v08FFpFFFF* + ID_MODEL_FROM_DATABASE=Sensor (Emulator) + +usb:v0900* + ID_VENDOR_FROM_DATABASE=Pinnacle Systems, Inc. + +usb:v0901* + ID_VENDOR_FROM_DATABASE=VST Technologies + +usb:v0901p0001* + ID_MODEL_FROM_DATABASE=Hard Drive Adapter (TPP) + +usb:v0901p0002* + ID_MODEL_FROM_DATABASE=SigmaDrive Adapter (TPP) + +usb:v0906* + ID_VENDOR_FROM_DATABASE=Faraday Technology Corp. + +usb:v0908* + ID_VENDOR_FROM_DATABASE=Siemens AG + +usb:v0908p01F4* + ID_MODEL_FROM_DATABASE=SIMATIC NET CP 5711 + +usb:v0908p01FE* + ID_MODEL_FROM_DATABASE=SIMATIC NET PC Adapter A2 + +usb:v0908p04B1* + ID_MODEL_FROM_DATABASE=MediSET + +usb:v0908p04B2* + ID_MODEL_FROM_DATABASE=NC interface + +usb:v0908p04B3* + ID_MODEL_FROM_DATABASE=keyboard front panel Cockpit + +usb:v0908p04B4* + ID_MODEL_FROM_DATABASE=SCR_CCID + +usb:v0908p2701* + ID_MODEL_FROM_DATABASE=ShenZhen SANZHAI Technology Co.,Ltd Spy Pen VGA + +usb:v0909* + ID_VENDOR_FROM_DATABASE=Audio-Technica Corp. + +usb:v090A* + ID_VENDOR_FROM_DATABASE=Trumpion Microelectronics, Inc. + +usb:v090Ap1001* + ID_MODEL_FROM_DATABASE=T33520 Flash Card Controller + +usb:v090Ap1100* + ID_MODEL_FROM_DATABASE=Comotron C3310 MP3 player + +usb:v090Ap1200* + ID_MODEL_FROM_DATABASE=MP3 player + +usb:v090Ap1540* + ID_MODEL_FROM_DATABASE=Digitex Container Flash Disk + +usb:v090B* + ID_VENDOR_FROM_DATABASE=Neurosmith + +usb:v090C* + ID_VENDOR_FROM_DATABASE=Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.) + +usb:v090Cp0371* + ID_MODEL_FROM_DATABASE=Silicon Motion SM371 Camera + +usb:v090Cp0373* + ID_MODEL_FROM_DATABASE=Silicon Motion Camera + +usb:v090Cp037A* + ID_MODEL_FROM_DATABASE=Silicon Motion Camera + +usb:v090Cp037B* + ID_MODEL_FROM_DATABASE=Silicon Motion Camera + +usb:v090Cp037C* + ID_MODEL_FROM_DATABASE=300k Pixel Camera + +usb:v090Cp1000* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v090Cp1132* + ID_MODEL_FROM_DATABASE=5-in-1 Card Reader + +usb:v090Cp337B* + ID_MODEL_FROM_DATABASE=Silicon Motion Camera + +usb:v090Cp3710* + ID_MODEL_FROM_DATABASE=Silicon Motion Camera + +usb:v090Cp3720* + ID_MODEL_FROM_DATABASE=Silicon Motion Camera + +usb:v090Cp37BC* + ID_MODEL_FROM_DATABASE=HP Webcam-101 Integrated Camera + +usb:v090Cp37C0* + ID_MODEL_FROM_DATABASE=Silicon Motion Camera + +usb:v090Cp6000* + ID_MODEL_FROM_DATABASE=SD/SDHC Card Reader (SG365 / FlexiDrive XC+) + +usb:v090Cp6200* + ID_MODEL_FROM_DATABASE=microSD card reader + +usb:v090Cp71B3* + ID_MODEL_FROM_DATABASE=SM731 Camera + +usb:v090Cp837B* + ID_MODEL_FROM_DATABASE=Silicon Motion Camera + +usb:v090Cp937B* + ID_MODEL_FROM_DATABASE=Silicon Motion Camera + +usb:v090CpB370* + ID_MODEL_FROM_DATABASE=Silicon Motion SM370 Camera + +usb:v090CpB371* + ID_MODEL_FROM_DATABASE=Silicon Motion SM371 Camera + +usb:v090CpF37D* + ID_MODEL_FROM_DATABASE=Endoscope camera + +usb:v090D* + ID_VENDOR_FROM_DATABASE=Multiport Computer Vertriebs GmbH + +usb:v090E* + ID_VENDOR_FROM_DATABASE=Shining Technology, Inc. + +usb:v090F* + ID_VENDOR_FROM_DATABASE=Fujitsu Devices, Inc. + +usb:v0910* + ID_VENDOR_FROM_DATABASE=Alation Systems, Inc. + +usb:v0911* + ID_VENDOR_FROM_DATABASE=Philips Speech Processing + +usb:v0911p149A* + ID_MODEL_FROM_DATABASE=SpeechMike II Pro Plus LFH5276 + +usb:v0911p2512* + ID_MODEL_FROM_DATABASE=SpeechMike Pro + +usb:v0912* + ID_VENDOR_FROM_DATABASE=Voquette, Inc. + +usb:v0915* + ID_VENDOR_FROM_DATABASE=GlobeSpan, Inc. + +usb:v0915p0001* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v0915p0002* + ID_MODEL_FROM_DATABASE=ADSL ATM Modem + +usb:v0915p0005* + ID_MODEL_FROM_DATABASE=LAN Modem + +usb:v0915p2000* + ID_MODEL_FROM_DATABASE=802.11 Adapter + +usb:v0915p2002* + ID_MODEL_FROM_DATABASE=802.11 Adapter + +usb:v0915p8000* + ID_MODEL_FROM_DATABASE=ADSL LAN Modem + +usb:v0915p8005* + ID_MODEL_FROM_DATABASE=DSL-302G Modem + +usb:v0915p8101* + ID_MODEL_FROM_DATABASE=ADSL WAN Modem + +usb:v0915p8102* + ID_MODEL_FROM_DATABASE=DSL-200 ADSL Modem + +usb:v0915p8103* + ID_MODEL_FROM_DATABASE=DSL-200 ADSL Modem + +usb:v0915p8104* + ID_MODEL_FROM_DATABASE=DSL-200 Modem + +usb:v0915p8400* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v0915p8401* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v0915p8402* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v0915p8500* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v0915p8501* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v0917* + ID_VENDOR_FROM_DATABASE=SmartDisk Corp. + +usb:v0917p0001* + ID_MODEL_FROM_DATABASE=eFilm Reader-11 SM/CF + +usb:v0917p0002* + ID_MODEL_FROM_DATABASE=eFilm Reader-11 SM + +usb:v0917p0003* + ID_MODEL_FROM_DATABASE=eFilm Reader-11 CF + +usb:v0917p0200* + ID_MODEL_FROM_DATABASE=FireFly + +usb:v0917p0201* + ID_MODEL_FROM_DATABASE=FireLite + +usb:v0917p0202* + ID_MODEL_FROM_DATABASE=STORAGE ADAPTER (FirePower) + +usb:v0917p0204* + ID_MODEL_FROM_DATABASE=FlashTrax Storage + +usb:v0917p0205* + ID_MODEL_FROM_DATABASE=STORAGE ADAPTER (CrossFire) + +usb:v0917p0206* + ID_MODEL_FROM_DATABASE=FireFly 20G HDD + +usb:v0917p0207* + ID_MODEL_FROM_DATABASE=FireLite + +usb:v0917p020F* + ID_MODEL_FROM_DATABASE=STORAGE ADAPTER (FireLite) + +usb:v0917pDA01* + ID_MODEL_FROM_DATABASE=eFilm Reader-11 Test + +usb:v0917pFFFF* + ID_MODEL_FROM_DATABASE=eFilm Reader-11 (Class/PDR) + +usb:v0919* + ID_VENDOR_FROM_DATABASE=Tiger Electronics + +usb:v0919p0100* + ID_MODEL_FROM_DATABASE=Fast Flicks Digital Camera + +usb:v091E* + ID_VENDOR_FROM_DATABASE=Garmin International + +usb:v091Ep0003* + ID_MODEL_FROM_DATABASE=GPS (various models) + +usb:v091Ep0004* + ID_MODEL_FROM_DATABASE=iQue 3600 + +usb:v091Ep0200* + ID_MODEL_FROM_DATABASE=Data Card Programmer (install) + +usb:v091Ep086E* + ID_MODEL_FROM_DATABASE=Forerunner 735XT + +usb:v091Ep097F* + ID_MODEL_FROM_DATABASE=Forerunner 235 + +usb:v091Ep1200* + ID_MODEL_FROM_DATABASE=Data Card Programmer + +usb:v091Ep21A5* + ID_MODEL_FROM_DATABASE=etrex Cx (msc) + +usb:v091Ep2236* + ID_MODEL_FROM_DATABASE=nuvi 360 + +usb:v091Ep2271* + ID_MODEL_FROM_DATABASE=Edge 605/705 + +usb:v091Ep2295* + ID_MODEL_FROM_DATABASE=Colorado 300 + +usb:v091Ep22B6* + ID_MODEL_FROM_DATABASE=eTrex Vista HCx (Mass Storage mode) + +usb:v091Ep231B* + ID_MODEL_FROM_DATABASE=Oregon 400t + +usb:v091Ep2353* + ID_MODEL_FROM_DATABASE=Nüvi 205T + +usb:v091Ep2380* + ID_MODEL_FROM_DATABASE=Oregon series + +usb:v091Ep23CC* + ID_MODEL_FROM_DATABASE=nüvi 1350 + +usb:v091Ep2459* + ID_MODEL_FROM_DATABASE=GPSmap 62/78 series + +usb:v091Ep2491* + ID_MODEL_FROM_DATABASE=Edge 800 + +usb:v091Ep2519* + ID_MODEL_FROM_DATABASE=eTrex 30 + +usb:v091Ep2535* + ID_MODEL_FROM_DATABASE=Edge 800 + +usb:v091Ep253C* + ID_MODEL_FROM_DATABASE=GPSmap 62sc + +usb:v091Ep255B* + ID_MODEL_FROM_DATABASE=Nuvi 2505LM + +usb:v091Ep26A1* + ID_MODEL_FROM_DATABASE=Nuvi 55 + +usb:v091Ep47FB* + ID_MODEL_FROM_DATABASE=nuviCam + +usb:v0920* + ID_VENDOR_FROM_DATABASE=Echelon Co. + +usb:v0920p7500* + ID_MODEL_FROM_DATABASE=Network Interface + +usb:v0921* + ID_VENDOR_FROM_DATABASE=GoHubs, Inc. + +usb:v0921p1001* + ID_MODEL_FROM_DATABASE=GoCOM232 Serial + +usb:v0922* + ID_VENDOR_FROM_DATABASE=Dymo-CoStar Corp. + +usb:v0922p0007* + ID_MODEL_FROM_DATABASE=LabelWriter 330 + +usb:v0922p0009* + ID_MODEL_FROM_DATABASE=LabelWriter 310 + +usb:v0922p0019* + ID_MODEL_FROM_DATABASE=LabelWriter 400 + +usb:v0922p001A* + ID_MODEL_FROM_DATABASE=LabelWriter 400 Turbo + +usb:v0922p0020* + ID_MODEL_FROM_DATABASE=LabelWriter 450 + +usb:v0922p1001* + ID_MODEL_FROM_DATABASE=LabelManager PnP + +usb:v0922p8004* + ID_MODEL_FROM_DATABASE=M25 Digital Postal Scale + +usb:v0923* + ID_VENDOR_FROM_DATABASE=IC Media Corp. + +usb:v0923p010F* + ID_MODEL_FROM_DATABASE=SIIG MobileCam + +usb:v0924* + ID_VENDOR_FROM_DATABASE=Xerox + +usb:v0924p23DD* + ID_MODEL_FROM_DATABASE=DocuPrint M760 (X760_USB) + +usb:v0924p3CE8* + ID_MODEL_FROM_DATABASE=Phaser 3428 Printer + +usb:v0924p3CEA* + ID_MODEL_FROM_DATABASE=Phaser 3125 + +usb:v0924p3CEC* + ID_MODEL_FROM_DATABASE=Phaser 3250 + +usb:v0924p3D5B* + ID_MODEL_FROM_DATABASE=Phaser 6115MFP TWAIN Scanner + +usb:v0924p3D6D* + ID_MODEL_FROM_DATABASE=WorkCentre 6015N/NI + +usb:v0924p420F* + ID_MODEL_FROM_DATABASE=WorkCentre PE220 Series + +usb:v0924p421F* + ID_MODEL_FROM_DATABASE=M20 Scanner + +usb:v0924p423B* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v0924p4274* + ID_MODEL_FROM_DATABASE=Xerox Phaser 3635MFPX + +usb:v0924pFFEF* + ID_MODEL_FROM_DATABASE=WorkCenter M15 + +usb:v0924pFFFB* + ID_MODEL_FROM_DATABASE=DocuPrint M750 (X750_USB) + +usb:v0925* + ID_VENDOR_FROM_DATABASE=Lakeview Research + +usb:v0925p0005* + ID_MODEL_FROM_DATABASE=Gamtec.,Ltd SmartJoy PLUS Adapter + +usb:v0925p03E8* + ID_MODEL_FROM_DATABASE=Wii Classic Controller Adapter + +usb:v0925p3881* + ID_MODEL_FROM_DATABASE=Saleae Logic + +usb:v0925p8101* + ID_MODEL_FROM_DATABASE=Phidgets, Inc., 1-Motor PhidgetServo v2.0 + +usb:v0925p8104* + ID_MODEL_FROM_DATABASE=Phidgets, Inc., 4-Motor PhidgetServo v2.0 + +usb:v0925p8800* + ID_MODEL_FROM_DATABASE=WiseGroup Ltd, MP-8800 Quad Joypad + +usb:v0925p8866* + ID_MODEL_FROM_DATABASE=WiseGroup Ltd, MP-8866 Dual Joypad + +usb:v0927* + ID_VENDOR_FROM_DATABASE=Summus, Ltd + +usb:v0928* + ID_VENDOR_FROM_DATABASE=PLX Technology, Inc. (formerly Oxford Semiconductor, Ltd) + +usb:v0928p8000* + ID_MODEL_FROM_DATABASE=Firmware uploader + +usb:v0928pFFFF* + ID_MODEL_FROM_DATABASE=Blank Oxford Device + +usb:v0929* + ID_VENDOR_FROM_DATABASE=American Biometric Co. + +usb:v092A* + ID_VENDOR_FROM_DATABASE=Toshiba Information & Industrial Sys. And Services + +usb:v092B* + ID_VENDOR_FROM_DATABASE=Sena Technologies, Inc. + +usb:v092F* + ID_VENDOR_FROM_DATABASE=Northern Embedded Science/CAVNEX + +usb:v092Fp0004* + ID_MODEL_FROM_DATABASE=JTAG-4 + +usb:v092Fp0005* + ID_MODEL_FROM_DATABASE=JTAG-5 + +usb:v0930* + ID_VENDOR_FROM_DATABASE=Toshiba Corp. + +usb:v0930p0009* + ID_MODEL_FROM_DATABASE=Gigabeat F/X (HDD audio player) + +usb:v0930p000C* + ID_MODEL_FROM_DATABASE=Gigabeat F (mtp) + +usb:v0930p0010* + ID_MODEL_FROM_DATABASE=Gigabeat S (mtp) + +usb:v0930p01BF* + ID_MODEL_FROM_DATABASE=2.5"External Hard Disk + +usb:v0930p0200* + ID_MODEL_FROM_DATABASE=Integrated Bluetooth (Taiyo Yuden) + +usb:v0930p021C* + ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth + +usb:v0930p0301* + ID_MODEL_FROM_DATABASE=PCX1100U Cable Modem (WDM) + +usb:v0930p0302* + ID_MODEL_FROM_DATABASE=PCX2000 Cable Modem (WDM) + +usb:v0930p0305* + ID_MODEL_FROM_DATABASE=Cable Modem PCX3000 + +usb:v0930p0307* + ID_MODEL_FROM_DATABASE=Cable Modem PCX2500 + +usb:v0930p0308* + ID_MODEL_FROM_DATABASE=PCX2200 Cable Modem (WDM) + +usb:v0930p0309* + ID_MODEL_FROM_DATABASE=PCX5000 Cable Modem (WDM) + +usb:v0930p030B* + ID_MODEL_FROM_DATABASE=Cable Modem PCX2600 + +usb:v0930p0501* + ID_MODEL_FROM_DATABASE=Bluetooth Controller + +usb:v0930p0502* + ID_MODEL_FROM_DATABASE=Integrated Bluetooth + +usb:v0930p0503* + ID_MODEL_FROM_DATABASE=Bluetooth Controller + +usb:v0930p0505* + ID_MODEL_FROM_DATABASE=Integrated Bluetooth + +usb:v0930p0506* + ID_MODEL_FROM_DATABASE=Integrated Bluetooth + +usb:v0930p0507* + ID_MODEL_FROM_DATABASE=Bluetooth Adapter + +usb:v0930p0508* + ID_MODEL_FROM_DATABASE=Integrated Bluetooth HCI + +usb:v0930p0509* + ID_MODEL_FROM_DATABASE=BT EDR Dongle + +usb:v0930p0706* + ID_MODEL_FROM_DATABASE=PocketPC e740 + +usb:v0930p0707* + ID_MODEL_FROM_DATABASE=Pocket PC e330 Series + +usb:v0930p0708* + ID_MODEL_FROM_DATABASE=Pocket PC e350 Series + +usb:v0930p0709* + ID_MODEL_FROM_DATABASE=Pocket PC e750 Series + +usb:v0930p070A* + ID_MODEL_FROM_DATABASE=Pocket PC e400 Series + +usb:v0930p070B* + ID_MODEL_FROM_DATABASE=Pocket PC e800 Series + +usb:v0930p0A07* + ID_MODEL_FROM_DATABASE=WLM-10U1 802.11abgn Wireless Adapter [Ralink RT3572] + +usb:v0930p0A08* + ID_MODEL_FROM_DATABASE=WLM-20U2/GN-1080 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] + +usb:v0930p0A0B* + ID_MODEL_FROM_DATABASE=WLU5053 802.11abgn Wireless Module [Broadcom BCM43236B] + +usb:v0930p0A13* + ID_MODEL_FROM_DATABASE=AX88179 Gigabit Ethernet [Toshiba] + +usb:v0930p0B05* + ID_MODEL_FROM_DATABASE=PX1220E-1G25 External hard drive + +usb:v0930p0B09* + ID_MODEL_FROM_DATABASE=PX1396E-3T01 External hard drive + +usb:v0930p0B1A* + ID_MODEL_FROM_DATABASE=STOR.E ALU 2S + +usb:v0930p1300* + ID_MODEL_FROM_DATABASE=Wireless Broadband (CDMA EV-DO) SM-Bus Minicard Status Port + +usb:v0930p1301* + ID_MODEL_FROM_DATABASE=Wireless Broadband (CDMA EV-DO) Minicard Status Port + +usb:v0930p1302* + ID_MODEL_FROM_DATABASE=Wireless Broadband (3G HSDPA) SM-Bus Minicard Status Port + +usb:v0930p1303* + ID_MODEL_FROM_DATABASE=Wireless Broadband (3G HSDPA) Minicard Status Port + +usb:v0930p1308* + ID_MODEL_FROM_DATABASE=Broadband (3G HSDPA) SM-Bus Minicard Diagnostics Port + +usb:v0930p130B* + ID_MODEL_FROM_DATABASE=F3507g Mobile Broadband Module + +usb:v0930p130C* + ID_MODEL_FROM_DATABASE=F3607gw Mobile Broadband Module + +usb:v0930p1311* + ID_MODEL_FROM_DATABASE=F3607gw v2 Mobile Broadband Module + +usb:v0930p1400* + ID_MODEL_FROM_DATABASE=Memory Stick 2GB + +usb:v0930p642F* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p6506* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6507* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6508* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6509* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6510* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6517* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6518* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6519* + ID_MODEL_FROM_DATABASE=Kingston DataTraveler 2.0 USB Stick + +usb:v0930p651A* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p651B* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p651C* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p651D* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p651E* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p651F* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6520* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6521* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6522* + ID_MODEL_FROM_DATABASE=TravelDrive 2C + +usb:v0930p6523* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p6524* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p6525* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p6526* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p6527* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p6528* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p6529* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p652A* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p652B* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p652C* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p652D* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p652F* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p6530* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p6531* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p6532* + ID_MODEL_FROM_DATABASE=256M Stick + +usb:v0930p6533* + ID_MODEL_FROM_DATABASE=512M Stick + +usb:v0930p6534* + ID_MODEL_FROM_DATABASE=TravelDrive + +usb:v0930p653C* + ID_MODEL_FROM_DATABASE=Kingston DataTraveler 2.0 Stick (512M) + +usb:v0930p653D* + ID_MODEL_FROM_DATABASE=Kingston DataTraveler 2.0 Stick (1GB) + +usb:v0930p653E* + ID_MODEL_FROM_DATABASE=Flash Memory + +usb:v0930p6540* + ID_MODEL_FROM_DATABASE=TransMemory Flash Memory + +usb:v0930p6544* + ID_MODEL_FROM_DATABASE=TransMemory-Mini / Kingston DataTraveler 2.0 Stick + +usb:v0930p6545* + ID_MODEL_FROM_DATABASE=Kingston DataTraveler 102/2.0 / HEMA Flash Drive 2 GB / PNY Attache 4GB Stick + +usb:v0931* + ID_VENDOR_FROM_DATABASE=Harmonic Data Systems, Ltd + +usb:v0932* + ID_VENDOR_FROM_DATABASE=Crescentec Corp. + +usb:v0932p0300* + ID_MODEL_FROM_DATABASE=VideoAdvantage + +usb:v0932p0302* + ID_MODEL_FROM_DATABASE=Syntek DC-112X + +usb:v0932p0320* + ID_MODEL_FROM_DATABASE=VideoAdvantage + +usb:v0932p0482* + ID_MODEL_FROM_DATABASE=USB2.0 TVBOX + +usb:v0932p1100* + ID_MODEL_FROM_DATABASE=DC-1100 Video Enhamcement Device + +usb:v0932p1112* + ID_MODEL_FROM_DATABASE=Veo Web Camera + +usb:v0932pA311* + ID_MODEL_FROM_DATABASE=Video Enhancement Device + +usb:v0933* + ID_VENDOR_FROM_DATABASE=Quantum Corp. + +usb:v0934* + ID_VENDOR_FROM_DATABASE=Spirent Communications + +usb:v0936* + ID_VENDOR_FROM_DATABASE=NuTesla + +usb:v0936p000A* + ID_MODEL_FROM_DATABASE=Moebius + +usb:v0936p000B* + ID_MODEL_FROM_DATABASE=iMoebius + +usb:v0936p000C* + ID_MODEL_FROM_DATABASE=Rhythmedics 6 BioData Integrator + +usb:v0936p000D* + ID_MODEL_FROM_DATABASE=Hypurius + +usb:v0936p000E* + ID_MODEL_FROM_DATABASE=Millennius + +usb:v0936p000F* + ID_MODEL_FROM_DATABASE=Purius + +usb:v0936p0030* + ID_MODEL_FROM_DATABASE=Composite Device, Mass Storage Device (Flash Drive) amd HID + +usb:v0936p003C* + ID_MODEL_FROM_DATABASE=Rhythmedics HID Bootloader + +usb:v0939* + ID_VENDOR_FROM_DATABASE=Lumberg, Inc. + +usb:v0939p0B15* + ID_MODEL_FROM_DATABASE=Toshiba Stor.E Alu 2 + +usb:v093A* + ID_VENDOR_FROM_DATABASE=Pixart Imaging, Inc. + +usb:v093Ap0007* + ID_MODEL_FROM_DATABASE=CMOS 100K-R Rev. 1.90 + +usb:v093Ap010E* + ID_MODEL_FROM_DATABASE=Digital camera, CD302N/Elta Medi@ digi-cam/HE-501A + +usb:v093Ap010F* + ID_MODEL_FROM_DATABASE=Argus DC-1610/DC-1620/Emprex PCD3600/Philips P44417B keychain camera/Precision Mini,Model HA513A/Vivitar Vivicam 55 + +usb:v093Ap020F* + ID_MODEL_FROM_DATABASE=Bullet Line Photo Viewer + +usb:v093Ap050F* + ID_MODEL_FROM_DATABASE=Mars-Semi Pc-Camera + +usb:v093Ap2460* + ID_MODEL_FROM_DATABASE=Q-TEC WEBCAM 100 + +usb:v093Ap2468* + ID_MODEL_FROM_DATABASE=SoC PC-Camera + +usb:v093Ap2470* + ID_MODEL_FROM_DATABASE=SoC PC-Camera + +usb:v093Ap2471* + ID_MODEL_FROM_DATABASE=SoC PC-Camera + +usb:v093Ap2500* + ID_MODEL_FROM_DATABASE=USB Optical Mouse + +usb:v093Ap2510* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v093Ap2521* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v093Ap2600* + ID_MODEL_FROM_DATABASE=Typhoon Easycam USB 330K (newer)/Typhoon Easycam USB 2.0 VGA 1.3M/Sansun SN-508 + +usb:v093Ap2601* + ID_MODEL_FROM_DATABASE=SPC 610NC Laptop Camera + +usb:v093Ap2603* + ID_MODEL_FROM_DATABASE=PAC7312 Camera + +usb:v093Ap2608* + ID_MODEL_FROM_DATABASE=PAC7311 Trust WB-3300p + +usb:v093Ap260E* + ID_MODEL_FROM_DATABASE=PAC7311 Gigaware VGA PC Camera:Trust WB-3350p:SIGMA cam 2350 + +usb:v093Ap260F* + ID_MODEL_FROM_DATABASE=PAC7311 SnakeCam + +usb:v093Ap2621* + ID_MODEL_FROM_DATABASE=PAC731x Trust Webcam + +usb:v093Ap2622* + ID_MODEL_FROM_DATABASE=Webcam Genius + +usb:v093Ap2624* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v093B* + ID_VENDOR_FROM_DATABASE=Plextor Corp. + +usb:v093Bp0010* + ID_MODEL_FROM_DATABASE=Storage Adapter + +usb:v093Bp0011* + ID_MODEL_FROM_DATABASE=PlexWriter 40/12/40U + +usb:v093Bp0041* + ID_MODEL_FROM_DATABASE=PX-708A DVD RW + +usb:v093Bp0042* + ID_MODEL_FROM_DATABASE=PX-712UF DVD RW + +usb:v093BpA002* + ID_MODEL_FROM_DATABASE=ConvertX M402U XLOADER + +usb:v093BpA003* + ID_MODEL_FROM_DATABASE=ConvertX AV100U A/V Capture Audio + +usb:v093BpA004* + ID_MODEL_FROM_DATABASE=ConvertX TV402U XLOADER + +usb:v093BpA005* + ID_MODEL_FROM_DATABASE=ConvertX TV100U A/V Capture + +usb:v093BpA102* + ID_MODEL_FROM_DATABASE=ConvertX M402U A/V Capture + +usb:v093BpA104* + ID_MODEL_FROM_DATABASE=ConvertX PX-TV402U/NA + +usb:v093C* + ID_VENDOR_FROM_DATABASE=Intrepid Control Systems, Inc. + +usb:v093Cp0601* + ID_MODEL_FROM_DATABASE=ValueCAN + +usb:v093Cp0701* + ID_MODEL_FROM_DATABASE=NeoVI Blue vehicle bus interface + +usb:v093D* + ID_VENDOR_FROM_DATABASE=InnoSync, Inc. + +usb:v093E* + ID_VENDOR_FROM_DATABASE=J.S.T. Mfg. Co., Ltd + +usb:v093F* + ID_VENDOR_FROM_DATABASE=Olympia Telecom Vertriebs GmbH + +usb:v0940* + ID_VENDOR_FROM_DATABASE=Japan Storage Battery Co., Ltd + +usb:v0941* + ID_VENDOR_FROM_DATABASE=Photobit Corp. + +usb:v0942* + ID_VENDOR_FROM_DATABASE=i2Go.com, LLC + +usb:v0943* + ID_VENDOR_FROM_DATABASE=HCL Technologies India Private, Ltd + +usb:v0944* + ID_VENDOR_FROM_DATABASE=KORG, Inc. + +usb:v0944p0001* + ID_MODEL_FROM_DATABASE=PXR4 4-Track Digital Recorder + +usb:v0944p0020* + ID_MODEL_FROM_DATABASE=KAOSS Pad KP3 Dynamic Effect/Sampler + +usb:v0944p0023* + ID_MODEL_FROM_DATABASE=KAOSSILATOR PRO Dynamic Phrase Synthesizer + +usb:v0944p010D* + ID_MODEL_FROM_DATABASE=nanoKEY MIDI keyboard + +usb:v0944p010E* + ID_MODEL_FROM_DATABASE=nanoPAD pad controller + +usb:v0944p010F* + ID_MODEL_FROM_DATABASE=nanoKONTROL studio controller + +usb:v0944p0117* + ID_MODEL_FROM_DATABASE=nanoKONTROL2 MIDI Controller + +usb:v0944p0F03* + ID_MODEL_FROM_DATABASE=K-Series K61P MIDI studio controller + +usb:v0945* + ID_VENDOR_FROM_DATABASE=Pasco Scientific + +usb:v0948* + ID_VENDOR_FROM_DATABASE=Kronauer music in digital + +usb:v0948p0301* + ID_MODEL_FROM_DATABASE=USB Pro (24/48) + +usb:v0948p0302* + ID_MODEL_FROM_DATABASE=USB Pro (24/96 playback) + +usb:v0948p0303* + ID_MODEL_FROM_DATABASE=USB Pro (24/96 record) + +usb:v0948p0304* + ID_MODEL_FROM_DATABASE=USB Pro (16/48) + +usb:v0948p1105* + ID_MODEL_FROM_DATABASE=USB One + +usb:v094B* + ID_VENDOR_FROM_DATABASE=Linkup Systems Corp. + +usb:v094Bp0001* + ID_MODEL_FROM_DATABASE=neonode N2 + +usb:v094D* + ID_VENDOR_FROM_DATABASE=Cable Television Laboratories + +usb:v094F* + ID_VENDOR_FROM_DATABASE=Yano + +usb:v094Fp0101* + ID_MODEL_FROM_DATABASE=U640MO-03 + +usb:v094Fp05FC* + ID_MODEL_FROM_DATABASE=METALWEAR-HDD + +usb:v0951* + ID_VENDOR_FROM_DATABASE=Kingston Technology + +usb:v0951p0008* + ID_MODEL_FROM_DATABASE=Ethernet + +usb:v0951p000A* + ID_MODEL_FROM_DATABASE=KNU101TX 100baseTX Ethernet + +usb:v0951p1600* + ID_MODEL_FROM_DATABASE=DataTraveler II Pen Drive + +usb:v0951p1601* + ID_MODEL_FROM_DATABASE=DataTraveler II+ Pen Drive + +usb:v0951p1602* + ID_MODEL_FROM_DATABASE=DataTraveler Mini + +usb:v0951p1603* + ID_MODEL_FROM_DATABASE=DataTraveler 1GB/2GB Pen Drive + +usb:v0951p1606* + ID_MODEL_FROM_DATABASE=Eee PC 701 SD Card Reader [ENE UB6225] + +usb:v0951p1607* + ID_MODEL_FROM_DATABASE=DataTraveler 100 + +usb:v0951p160B* + ID_MODEL_FROM_DATABASE=DataTraveler 2.0 (2GB) + +usb:v0951p160D* + ID_MODEL_FROM_DATABASE=DataTraveler Vault Privacy + +usb:v0951p160E* + ID_MODEL_FROM_DATABASE=DT110P/1GB Capless + +usb:v0951p1613* + ID_MODEL_FROM_DATABASE=DataTraveler DT101C Flash Drive + +usb:v0951p1616* + ID_MODEL_FROM_DATABASE=DataTraveler Locker 4GB + +usb:v0951p161A* + ID_MODEL_FROM_DATABASE=Dell HyperVisor internal flash drive + +usb:v0951p1621* + ID_MODEL_FROM_DATABASE=DataTraveler 150 (32GB) + +usb:v0951p1624* + ID_MODEL_FROM_DATABASE=DataTraveler G2 + +usb:v0951p1625* + ID_MODEL_FROM_DATABASE=DataTraveler 101 II + +usb:v0951p162A* + ID_MODEL_FROM_DATABASE=DataTraveler 112 4GB Pen Drive + +usb:v0951p162B* + ID_MODEL_FROM_DATABASE=DataTraveler HyperX 3.0 + +usb:v0951p162D* + ID_MODEL_FROM_DATABASE=DataTraveler 102 + +usb:v0951p1630* + ID_MODEL_FROM_DATABASE=DataTraveler 200 (32GB) + +usb:v0951p1642* + ID_MODEL_FROM_DATABASE=DT101 G2 + +usb:v0951p1643* + ID_MODEL_FROM_DATABASE=DataTraveler G3 + +usb:v0951p1653* + ID_MODEL_FROM_DATABASE=Data Traveler 100 G2 8 GiB + +usb:v0951p1656* + ID_MODEL_FROM_DATABASE=DataTraveler Ultimate G2 + +usb:v0951p1660* + ID_MODEL_FROM_DATABASE=Data Traveller 108 + +usb:v0951p1665* + ID_MODEL_FROM_DATABASE=Digital DataTraveler SE9 64GB + +usb:v0951p1666* + ID_MODEL_FROM_DATABASE=DataTraveler 100 G3/G4/SE9 G2 + +usb:v0951p1689* + ID_MODEL_FROM_DATABASE=DataTraveler SE9 + +usb:v0951p168A* + ID_MODEL_FROM_DATABASE=DataTraveler Micro + +usb:v0951p168C* + ID_MODEL_FROM_DATABASE=DT Elite 3.0 + +usb:v0951p16B3* + ID_MODEL_FROM_DATABASE=HyperX Savage + +usb:v0954* + ID_VENDOR_FROM_DATABASE=RPM Systems Corp. + +usb:v0955* + ID_VENDOR_FROM_DATABASE=NVIDIA Corp. + +usb:v0955p7018* + ID_MODEL_FROM_DATABASE=T186 [Tegra Parker] + +usb:v0955p701A* + ID_MODEL_FROM_DATABASE=U-Boot running on Tegra + +usb:v0955p7020* + ID_MODEL_FROM_DATABASE=L4T (Linux for Tegra) running on Tegra + +usb:v0955p7030* + ID_MODEL_FROM_DATABASE=T30 [Tegra 3] recovery mode + +usb:v0955p7100* + ID_MODEL_FROM_DATABASE=Tegra Device + +usb:v0955p7140* + ID_MODEL_FROM_DATABASE=T124 [Tegra K1/Logan 32-bit] + +usb:v0955p7210* + ID_MODEL_FROM_DATABASE=SHIELD Controller + +usb:v0955p7721* + ID_MODEL_FROM_DATABASE=T210 [Tegra Erista] + +usb:v0955p7820* + ID_MODEL_FROM_DATABASE=T20 [Tegra 2] recovery mode + +usb:v0955pB400* + ID_MODEL_FROM_DATABASE=SHIELD (debug) + +usb:v0955pB401* + ID_MODEL_FROM_DATABASE=SHIELD + +usb:v0955pCF05* + ID_MODEL_FROM_DATABASE=SHIELD Tablet (debug) + +usb:v0955pCF06* + ID_MODEL_FROM_DATABASE=SHIELD Tablet + +usb:v0955pCF07* + ID_MODEL_FROM_DATABASE=SHIELD Tablet + +usb:v0955pCF08* + ID_MODEL_FROM_DATABASE=SHIELD Tablet + +usb:v0955pCF09* + ID_MODEL_FROM_DATABASE=SHIELD Tablet + +usb:v0956* + ID_VENDOR_FROM_DATABASE=BSquare Corp. + +usb:v0957* + ID_VENDOR_FROM_DATABASE=Agilent Technologies, Inc. + +usb:v0957p0200* + ID_MODEL_FROM_DATABASE=E-Video DC-350 Camera + +usb:v0957p0202* + ID_MODEL_FROM_DATABASE=E-Video DC-350 Camera + +usb:v0957p0407* + ID_MODEL_FROM_DATABASE=33220A Waveform Generator + +usb:v0957p0518* + ID_MODEL_FROM_DATABASE=82357B GPIB Interface + +usb:v0957p0A07* + ID_MODEL_FROM_DATABASE=34411A Multimeter + +usb:v0957p1507* + ID_MODEL_FROM_DATABASE=33210A Waveform Generator + +usb:v0957p1745* + ID_MODEL_FROM_DATABASE=Test and Measurement Device (IVI) + +usb:v0957p2918* + ID_MODEL_FROM_DATABASE=U2702A oscilloscope + +usb:v0957pFB18* + ID_MODEL_FROM_DATABASE=LC Device + +usb:v0958* + ID_VENDOR_FROM_DATABASE=CompuLink Research, Inc. + +usb:v0959* + ID_VENDOR_FROM_DATABASE=Cologne Chip AG + +usb:v0959p2BD0* + ID_MODEL_FROM_DATABASE=Intelligent ISDN (Ver. 3.60.04) [HFC-S] + +usb:v095A* + ID_VENDOR_FROM_DATABASE=Portsmith + +usb:v095Ap3003* + ID_MODEL_FROM_DATABASE=Express Ethernet + +usb:v095B* + ID_VENDOR_FROM_DATABASE=Medialogic Corp. + +usb:v095C* + ID_VENDOR_FROM_DATABASE=K-Tec Electronics + +usb:v095D* + ID_VENDOR_FROM_DATABASE=Polycom, Inc. + +usb:v095Dp0001* + ID_MODEL_FROM_DATABASE=Polycom ViaVideo + +usb:v0964* + ID_VENDOR_FROM_DATABASE=BITRAN + +usb:v0967* + ID_VENDOR_FROM_DATABASE=Acer NeWeb Corp. + +usb:v0967p0204* + ID_MODEL_FROM_DATABASE=WarpLink 802.11b Adapter + +usb:v0968* + ID_VENDOR_FROM_DATABASE=Catalyst Enterprises, Inc. + +usb:v096E* + ID_VENDOR_FROM_DATABASE=Feitian Technologies, Inc. + +usb:v096Ep0005* + ID_MODEL_FROM_DATABASE=ePass2000 + +usb:v096Ep0120* + ID_MODEL_FROM_DATABASE=Microcosm Ltd Dinkey + +usb:v096Ep0305* + ID_MODEL_FROM_DATABASE=ePass2000Auto + +usb:v096Ep0309* + ID_MODEL_FROM_DATABASE=ePass3000GM + +usb:v096Ep0401* + ID_MODEL_FROM_DATABASE=ePass3000 + +usb:v096Ep0702* + ID_MODEL_FROM_DATABASE=ePass3003 + +usb:v096Ep0703* + ID_MODEL_FROM_DATABASE=ePass3003Auto + +usb:v096Ep0802* + ID_MODEL_FROM_DATABASE=ePass2000 (G&D STARCOS SPK 2.4) + +usb:v096Ep0807* + ID_MODEL_FROM_DATABASE=ePass2003 + +usb:v0971* + ID_VENDOR_FROM_DATABASE=Gretag-Macbeth AG + +usb:v0971p2000* + ID_MODEL_FROM_DATABASE=i1 Pro + +usb:v0971p2001* + ID_MODEL_FROM_DATABASE=i1 Monitor + +usb:v0971p2003* + ID_MODEL_FROM_DATABASE=Eye-One display + +usb:v0971p2005* + ID_MODEL_FROM_DATABASE=Huey + +usb:v0971p2007* + ID_MODEL_FROM_DATABASE=ColorMunki Photo + +usb:v0973* + ID_VENDOR_FROM_DATABASE=Schlumberger + +usb:v0973p0001* + ID_MODEL_FROM_DATABASE=e-gate Smart Card + +usb:v0974* + ID_VENDOR_FROM_DATABASE=Datagraphix, a business unit of Anacomp + +usb:v0975* + ID_VENDOR_FROM_DATABASE=OL'E Communications, Inc. + +usb:v0976* + ID_VENDOR_FROM_DATABASE=Adirondack Wire & Cable + +usb:v0977* + ID_VENDOR_FROM_DATABASE=Lightsurf Technologies + +usb:v0978* + ID_VENDOR_FROM_DATABASE=Beckhoff GmbH + +usb:v0979* + ID_VENDOR_FROM_DATABASE=Jeilin Technology Corp., Ltd + +usb:v0979p0222* + ID_MODEL_FROM_DATABASE=Keychain Display + +usb:v0979p0224* + ID_MODEL_FROM_DATABASE=JL2005A Toy Camera + +usb:v0979p0226* + ID_MODEL_FROM_DATABASE=JL2005A Toy Camera + +usb:v0979p0227* + ID_MODEL_FROM_DATABASE=JL2005B/C/D Toy Camera + +usb:v097A* + ID_VENDOR_FROM_DATABASE=Minds At Work LLC + +usb:v097Ap0001* + ID_MODEL_FROM_DATABASE=Digital Wallet + +usb:v097B* + ID_VENDOR_FROM_DATABASE=Knudsen Engineering, Ltd + +usb:v097C* + ID_VENDOR_FROM_DATABASE=Marunix Co., Ltd + +usb:v097D* + ID_VENDOR_FROM_DATABASE=Rosun Technologies, Inc. + +usb:v097E* + ID_VENDOR_FROM_DATABASE=Biopac Systems Inc. + +usb:v097Ep0035* + ID_MODEL_FROM_DATABASE=MP35 v1.0 + +usb:v097F* + ID_VENDOR_FROM_DATABASE=Barun Electronics Co., Ltd + +usb:v0981* + ID_VENDOR_FROM_DATABASE=Oak Technology, Ltd + +usb:v0984* + ID_VENDOR_FROM_DATABASE=Apricorn + +usb:v0984p0040* + ID_MODEL_FROM_DATABASE=SATA Wire (2.5") + +usb:v0984p0200* + ID_MODEL_FROM_DATABASE=Hard Drive Storage (TPP) + +usb:v0985* + ID_VENDOR_FROM_DATABASE=cab Produkttechnik GmbH & Co KG + +usb:v0985p0045* + ID_MODEL_FROM_DATABASE=Mach4/200 Label Printer + +usb:v0985p00A3* + ID_MODEL_FROM_DATABASE=A3/200 or A3/300 Label Printer + +usb:v0986* + ID_VENDOR_FROM_DATABASE=Matsushita Electric Works, Ltd. + +usb:v098C* + ID_VENDOR_FROM_DATABASE=Vitana Corp. + +usb:v098D* + ID_VENDOR_FROM_DATABASE=INDesign + +usb:v098E* + ID_VENDOR_FROM_DATABASE=Integrated Intellectual Property, Inc. + +usb:v098F* + ID_VENDOR_FROM_DATABASE=Kenwood TMI Corp. + +usb:v0993* + ID_VENDOR_FROM_DATABASE=Gemstar eBook Group, Ltd + +usb:v0993p0001* + ID_MODEL_FROM_DATABASE=REB1100 eBook Reader + +usb:v0993p0002* + ID_MODEL_FROM_DATABASE=eBook + +usb:v0996* + ID_VENDOR_FROM_DATABASE=Integrated Telecom Express, Inc. + +usb:v099A* + ID_VENDOR_FROM_DATABASE=Zippy Technology Corp. + +usb:v099Ap0638* + ID_MODEL_FROM_DATABASE=Sanwa Supply Inc. Small Keyboard + +usb:v099Ap610C* + ID_MODEL_FROM_DATABASE=EL-610 Super Mini Electron luminescent Keyboard + +usb:v099Ap713A* + ID_MODEL_FROM_DATABASE=WK-713 Multimedia Keyboard + +usb:v099Ap7160* + ID_MODEL_FROM_DATABASE=Hyper Slim Keyboard + +usb:v099E* + ID_VENDOR_FROM_DATABASE=Trimble Navigation, Ltd + +usb:v09A3* + ID_VENDOR_FROM_DATABASE=PairGain Technologies + +usb:v09A4* + ID_VENDOR_FROM_DATABASE=Contech Research, Inc. + +usb:v09A5* + ID_VENDOR_FROM_DATABASE=VCON Telecommunications + +usb:v09A6* + ID_VENDOR_FROM_DATABASE=Poinchips + +usb:v09A6p8001* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v09A7* + ID_VENDOR_FROM_DATABASE=Data Transmission Network Corp. + +usb:v09A8* + ID_VENDOR_FROM_DATABASE=Lin Shiung Enterprise Co., Ltd + +usb:v09A9* + ID_VENDOR_FROM_DATABASE=Smart Card Technologies Co., Ltd + +usb:v09AA* + ID_VENDOR_FROM_DATABASE=Intersil Corp. + +usb:v09AAp1000* + ID_MODEL_FROM_DATABASE=Prism GT 802.11b/g Adapter + +usb:v09AAp3642* + ID_MODEL_FROM_DATABASE=Prism 2.x 802.11b Adapter + +usb:v09AB* + ID_VENDOR_FROM_DATABASE=Japan Cash Machine Co., Ltd. + +usb:v09AE* + ID_VENDOR_FROM_DATABASE=Tripp Lite + +usb:v09B2* + ID_VENDOR_FROM_DATABASE=Franklin Electronic Publishers, Inc. + +usb:v09B2p0001* + ID_MODEL_FROM_DATABASE=eBookman Palm Computer + +usb:v09B3* + ID_VENDOR_FROM_DATABASE=Altius Solutions, Inc. + +usb:v09B4* + ID_VENDOR_FROM_DATABASE=MDS Telephone Systems + +usb:v09B5* + ID_VENDOR_FROM_DATABASE=Celltrix Technology Co., Ltd + +usb:v09BC* + ID_VENDOR_FROM_DATABASE=Grundig + +usb:v09BCp0002* + ID_MODEL_FROM_DATABASE=MPaxx MP150 MP3 Player + +usb:v09BE* + ID_VENDOR_FROM_DATABASE=MySmart.Com + +usb:v09BEp0001* + ID_MODEL_FROM_DATABASE=MySmartPad + +usb:v09BF* + ID_VENDOR_FROM_DATABASE=Auerswald GmbH & Co. KG + +usb:v09BFp00C0* + ID_MODEL_FROM_DATABASE=COMpact 2104 ISDN PBX + +usb:v09BFp00DB* + ID_MODEL_FROM_DATABASE=COMpact 4410/2206 ISDN + +usb:v09BFp00DC* + ID_MODEL_FROM_DATABASE=COMpact 4406 DSL (PBX) + +usb:v09BFp00DD* + ID_MODEL_FROM_DATABASE=COMpact 2204 (PBX) + +usb:v09BFp00DE* + ID_MODEL_FROM_DATABASE=COMpact 2104 (Rev.2 PBX) + +usb:v09BFp00E0* + ID_MODEL_FROM_DATABASE=COMmander Business (PBX) + +usb:v09BFp00E2* + ID_MODEL_FROM_DATABASE=COMmander Basic.2 (PBX) + +usb:v09BFp00F1* + ID_MODEL_FROM_DATABASE=COMfort 2000 (System telephone) + +usb:v09BFp00F2* + ID_MODEL_FROM_DATABASE=COMfort 1200 (System telephone) + +usb:v09BFp00F5* + ID_MODEL_FROM_DATABASE=COMfortel 2500 (System telephone) + +usb:v09BFp8000* + ID_MODEL_FROM_DATABASE=COMpact 2104 DSL (DSL modem) + +usb:v09BFp8001* + ID_MODEL_FROM_DATABASE=COMpact 4406 DSL (DSL modem) + +usb:v09BFp8002* + ID_MODEL_FROM_DATABASE=Analog/ISDN Converter (Line converter) + +usb:v09BFp8005* + ID_MODEL_FROM_DATABASE=WG-640 (Automatic event dialer) + +usb:v09C0* + ID_VENDOR_FROM_DATABASE=Genpix Electronics, LLC + +usb:v09C0p0136* + ID_MODEL_FROM_DATABASE=Axon CNS, MultiClamp 700B + +usb:v09C0p0202* + ID_MODEL_FROM_DATABASE=8PSK DVB-S tuner + +usb:v09C0p0203* + ID_MODEL_FROM_DATABASE=Skywalker-1 DVB-S tuner + +usb:v09C0p0204* + ID_MODEL_FROM_DATABASE=Skywalker-CW3K DVB-S tuner + +usb:v09C0p0205* + ID_MODEL_FROM_DATABASE=Skywalker-CW3K DVB-S tuner + +usb:v09C0p0206* + ID_MODEL_FROM_DATABASE=Skywalker-2 DVB-S tuner + +usb:v09C1* + ID_VENDOR_FROM_DATABASE=Arris Interactive LLC + +usb:v09C1p1337* + ID_MODEL_FROM_DATABASE=TOUCHSTONE DEVICE + +usb:v09C2* + ID_VENDOR_FROM_DATABASE=Nisca Corp. + +usb:v09C3* + ID_VENDOR_FROM_DATABASE=ActivCard, Inc. + +usb:v09C3p0007* + ID_MODEL_FROM_DATABASE=Reader V2 + +usb:v09C3p0008* + ID_MODEL_FROM_DATABASE=ZFG-9800-AC SmartCard Reader + +usb:v09C3p0014* + ID_MODEL_FROM_DATABASE=ActivIdentity ActivKey SIM USB Token + +usb:v09C4* + ID_VENDOR_FROM_DATABASE=ACTiSYS Corp. + +usb:v09C4p0011* + ID_MODEL_FROM_DATABASE=ACT-IR2000U IrDA Dongle + +usb:v09C5* + ID_VENDOR_FROM_DATABASE=Memory Corp. + +usb:v09CA* + ID_VENDOR_FROM_DATABASE=BMC Messsysteme GmbH + +usb:v09CAp5544* + ID_MODEL_FROM_DATABASE=PIO + +usb:v09CB* + ID_VENDOR_FROM_DATABASE=FLIR Systems + +usb:v09CBp1001* + ID_MODEL_FROM_DATABASE=Network Adapter + +usb:v09CBp1002* + ID_MODEL_FROM_DATABASE=Ex-Series RNDIS interface + +usb:v09CBp1004* + ID_MODEL_FROM_DATABASE=Ex-Series UVC interface + +usb:v09CBp1005* + ID_MODEL_FROM_DATABASE=Ex-Series RNDIS and UVC interface + +usb:v09CBp1006* + ID_MODEL_FROM_DATABASE=Ex-Series RNDIS and MSD interface + +usb:v09CBp1007* + ID_MODEL_FROM_DATABASE=Ex-Series UVC and MSD interface + +usb:v09CBp1008* + ID_MODEL_FROM_DATABASE=Serial Port + +usb:v09CBp1996* + ID_MODEL_FROM_DATABASE=FLIR ONE Camera + +usb:v09CC* + ID_VENDOR_FROM_DATABASE=Workbit Corp. + +usb:v09CCp0404* + ID_MODEL_FROM_DATABASE=BAFO USB-ATA/ATAPI Bridge Controller + +usb:v09CD* + ID_VENDOR_FROM_DATABASE=Psion Dacom Home Networks, Ltd + +usb:v09CDp2001* + ID_MODEL_FROM_DATABASE=Psion WaveFinder DAB radio receiver + +usb:v09CE* + ID_VENDOR_FROM_DATABASE=City Electronics, Ltd + +usb:v09CF* + ID_VENDOR_FROM_DATABASE=Electronics Testing Center, Taiwan + +usb:v09D1* + ID_VENDOR_FROM_DATABASE=NeoMagic, Inc. + +usb:v09D2* + ID_VENDOR_FROM_DATABASE=Vreelin Engineering, Inc. + +usb:v09D3* + ID_VENDOR_FROM_DATABASE=Com One + +usb:v09D3p0001* + ID_MODEL_FROM_DATABASE=ISDN TA / Light Rider 128K + +usb:v09D3p000B* + ID_MODEL_FROM_DATABASE=Bluetooth Adapter class 1 [BlueLight] + +usb:v09D7* + ID_VENDOR_FROM_DATABASE=NovAtel Inc. + +usb:v09D7p0100* + ID_MODEL_FROM_DATABASE=NovAtel FlexPack GPS receiver + +usb:v09D8* + ID_VENDOR_FROM_DATABASE=ELATEC + +usb:v09D8p0406* + ID_MODEL_FROM_DATABASE=TWN4 MIFARE NFC + +usb:v09D9* + ID_VENDOR_FROM_DATABASE=KRF Tech, Ltd + +usb:v09DA* + ID_VENDOR_FROM_DATABASE=A4Tech Co., Ltd. + +usb:v09DAp0006* + ID_MODEL_FROM_DATABASE=Optical Mouse WOP-35 / Trust 450L Optical Mouse + +usb:v09DAp000A* + ID_MODEL_FROM_DATABASE=Optical Mouse Opto 510D / OP-620D + +usb:v09DAp000E* + ID_MODEL_FROM_DATABASE=X-F710F Optical Mouse 3xFire Gaming Mouse + +usb:v09DAp0018* + ID_MODEL_FROM_DATABASE=Trust Human Interface Device + +usb:v09DAp001A* + ID_MODEL_FROM_DATABASE=Wireless Mouse & RXM-15 Receiver + +usb:v09DAp002A* + ID_MODEL_FROM_DATABASE=Wireless Optical Mouse NB-30 + +usb:v09DAp022B* + ID_MODEL_FROM_DATABASE=Wireless Mouse (Battery Free) + +usb:v09DAp024F* + ID_MODEL_FROM_DATABASE=RF Receiver and G6-20D Wireless Optical Mouse + +usb:v09DAp0260* + ID_MODEL_FROM_DATABASE=KV-300H Isolation Keyboard + +usb:v09DAp032B* + ID_MODEL_FROM_DATABASE=Wireless Mouse (Battery Free) + +usb:v09DAp1068* + ID_MODEL_FROM_DATABASE=Bloody A90 Mouse + +usb:v09DAp8090* + ID_MODEL_FROM_DATABASE=X-718BK Oscar Optical Gaming Mouse + +usb:v09DAp9033* + ID_MODEL_FROM_DATABASE=X-718BK Optical Mouse + +usb:v09DAp9066* + ID_MODEL_FROM_DATABASE=F3 V-Track Gaming Mouse + +usb:v09DAp9090* + ID_MODEL_FROM_DATABASE=XL-730K / XL-750BK / XL-755BK Mice + +usb:v09DB* + ID_VENDOR_FROM_DATABASE=Measurement Computing Corp. + +usb:v09DBp0075* + ID_MODEL_FROM_DATABASE=MiniLab 1008 + +usb:v09DBp0076* + ID_MODEL_FROM_DATABASE=PMD-1024 + +usb:v09DBp007A* + ID_MODEL_FROM_DATABASE=PMD-1208LS + +usb:v09DBp0081* + ID_MODEL_FROM_DATABASE=USB-1616FS + +usb:v09DBp0082* + ID_MODEL_FROM_DATABASE=USB-1208FS + +usb:v09DBp0088* + ID_MODEL_FROM_DATABASE=USB-1616FS internal hub + +usb:v09DC* + ID_VENDOR_FROM_DATABASE=Aimex Corp. + +usb:v09DD* + ID_VENDOR_FROM_DATABASE=Fellowes, Inc. + +usb:v09DF* + ID_VENDOR_FROM_DATABASE=Addonics Technologies Corp. + +usb:v09E1* + ID_VENDOR_FROM_DATABASE=Intellon Corp. + +usb:v09E1p5121* + ID_MODEL_FROM_DATABASE=MicroLink dLAN + +usb:v09E5* + ID_VENDOR_FROM_DATABASE=Jo-Dan International, Inc. + +usb:v09E6* + ID_VENDOR_FROM_DATABASE=Silutia, Inc. + +usb:v09E7* + ID_VENDOR_FROM_DATABASE=Real 3D, Inc. + +usb:v09E8* + ID_VENDOR_FROM_DATABASE=AKAI Professional M.I. Corp. + +usb:v09E8p0062* + ID_MODEL_FROM_DATABASE=MPD16 MIDI Pad Controller Unit + +usb:v09E8p006D* + ID_MODEL_FROM_DATABASE=EWI electronic wind instrument + +usb:v09E8p0071* + ID_MODEL_FROM_DATABASE=MPK25 MIDI Keyboard + +usb:v09E8p0076* + ID_MODEL_FROM_DATABASE=LPK25 MIDI Keyboard + +usb:v09E9* + ID_VENDOR_FROM_DATABASE=Chen-Source, Inc. + +usb:v09EB* + ID_VENDOR_FROM_DATABASE=IM Networks, Inc. + +usb:v09EBp4331* + ID_MODEL_FROM_DATABASE=iRhythm Tuner Remote + +usb:v09EF* + ID_VENDOR_FROM_DATABASE=Xitel + +usb:v09EFp0101* + ID_MODEL_FROM_DATABASE=MD-Port DG2 MiniDisc Interface + +usb:v09F3* + ID_VENDOR_FROM_DATABASE=GoFlight, Inc. + +usb:v09F3p0018* + ID_MODEL_FROM_DATABASE=GF-46 Multi-Mode Display Module + +usb:v09F3p0028* + ID_MODEL_FROM_DATABASE=RP-48 Combination Pushbutton-Rotary Module + +usb:v09F3p0048* + ID_MODEL_FROM_DATABASE=LGTII - Landing Gear and Trim Control Module + +usb:v09F3p0064* + ID_MODEL_FROM_DATABASE=MCPPro - Airliner Mode Control Panel (Autopilot) + +usb:v09F3p0300* + ID_MODEL_FROM_DATABASE=EFIS - Electronic Flight Information System + +usb:v09F5* + ID_VENDOR_FROM_DATABASE=AresCom + +usb:v09F5p0168* + ID_MODEL_FROM_DATABASE=Network Adapter + +usb:v09F5p0188* + ID_MODEL_FROM_DATABASE=LAN Adapter + +usb:v09F5p0850* + ID_MODEL_FROM_DATABASE=Adapter + +usb:v09F6* + ID_VENDOR_FROM_DATABASE=RocketChips, Inc. + +usb:v09F7* + ID_VENDOR_FROM_DATABASE=Edu-Science (H.K.), Ltd + +usb:v09F8* + ID_VENDOR_FROM_DATABASE=SoftConnex Technologies, Inc. + +usb:v09F9* + ID_VENDOR_FROM_DATABASE=Bay Associates + +usb:v09FA* + ID_VENDOR_FROM_DATABASE=Mtek Vision + +usb:v09FB* + ID_VENDOR_FROM_DATABASE=Altera + +usb:v09FBp6001* + ID_MODEL_FROM_DATABASE=Blaster + +usb:v09FF* + ID_VENDOR_FROM_DATABASE=Gain Technology Corp. + +usb:v0A00* + ID_VENDOR_FROM_DATABASE=Liquid Audio + +usb:v0A01* + ID_VENDOR_FROM_DATABASE=ViA, Inc. + +usb:v0A05* + ID_VENDOR_FROM_DATABASE=Unknown Manufacturer + +usb:v0A05p0001* + ID_MODEL_FROM_DATABASE=Hub + +usb:v0A05p7211* + ID_MODEL_FROM_DATABASE=hub + +usb:v0A07* + ID_VENDOR_FROM_DATABASE=Ontrak Control Systems Inc. + +usb:v0A07p0064* + ID_MODEL_FROM_DATABASE=ADU100 Data Acquisition Interface + +usb:v0A07p0078* + ID_MODEL_FROM_DATABASE=ADU120 Data Acquisition Interface + +usb:v0A07p0082* + ID_MODEL_FROM_DATABASE=ADU130 Data Acquisition Interface + +usb:v0A07p00C8* + ID_MODEL_FROM_DATABASE=ADU200 Relay I/O Interface + +usb:v0A07p00D0* + ID_MODEL_FROM_DATABASE=ADU208 Relay I/O Interface + +usb:v0A07p00DA* + ID_MODEL_FROM_DATABASE=ADU218 Solid-State Relay I/O Interface + +usb:v0A0B* + ID_VENDOR_FROM_DATABASE=Cybex Computer Products Co. + +usb:v0A0D* + ID_VENDOR_FROM_DATABASE=Servergy, Inc + +usb:v0A0Dp2514* + ID_MODEL_FROM_DATABASE=CTS-1000 Internal Hub + +usb:v0A11* + ID_VENDOR_FROM_DATABASE=Xentec, Inc. + +usb:v0A12* + ID_VENDOR_FROM_DATABASE=Cambridge Silicon Radio, Ltd + +usb:v0A12p0001* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle (HCI mode) + +usb:v0A12p0002* + ID_MODEL_FROM_DATABASE=Frontline Test Equipment Bluetooth Device + +usb:v0A12p0003* + ID_MODEL_FROM_DATABASE=Nanosira + +usb:v0A12p0004* + ID_MODEL_FROM_DATABASE=Nanosira WHQL Reference Radio + +usb:v0A12p0005* + ID_MODEL_FROM_DATABASE=Nanosira-Multimedia + +usb:v0A12p0006* + ID_MODEL_FROM_DATABASE=Nanosira-Multimedia WHQL Reference Radio + +usb:v0A12p0007* + ID_MODEL_FROM_DATABASE=Nanosira3-ROM + +usb:v0A12p0008* + ID_MODEL_FROM_DATABASE=Nanosira3-ROM + +usb:v0A12p0009* + ID_MODEL_FROM_DATABASE=Nanosira4-EDR WHQL Reference Radio + +usb:v0A12p000A* + ID_MODEL_FROM_DATABASE=Nanosira4-EDR-ROM + +usb:v0A12p000B* + ID_MODEL_FROM_DATABASE=Nanosira5-ROM + +usb:v0A12p0042* + ID_MODEL_FROM_DATABASE=SPI Converter + +usb:v0A12p0043* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0A12p0100* + ID_MODEL_FROM_DATABASE=Casira with BlueCore2-External Module + +usb:v0A12p0101* + ID_MODEL_FROM_DATABASE=Casira with BlueCore2-Flash Module + +usb:v0A12p0102* + ID_MODEL_FROM_DATABASE=Casira with BlueCore3-Multimedia Module + +usb:v0A12p0103* + ID_MODEL_FROM_DATABASE=Casira with BlueCore3-Flash Module + +usb:v0A12p0104* + ID_MODEL_FROM_DATABASE=Casira with BlueCore4-External Module + +usb:v0A12p0105* + ID_MODEL_FROM_DATABASE=Casira with BlueCore4-Multimedia Module + +usb:v0A12p1000* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle (HID proxy mode) + +usb:v0A12p1010* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0A12p1011* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0A12p1012* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0A12pFFFF* + ID_MODEL_FROM_DATABASE=USB Bluetooth Device in DFU State + +usb:v0A13* + ID_VENDOR_FROM_DATABASE=Telebyte, Inc. + +usb:v0A14* + ID_VENDOR_FROM_DATABASE=Spacelabs Medical, Inc. + +usb:v0A15* + ID_VENDOR_FROM_DATABASE=Scalar Corp. + +usb:v0A16* + ID_VENDOR_FROM_DATABASE=Trek Technology (S) PTE, Ltd + +usb:v0A16p1111* + ID_MODEL_FROM_DATABASE=ThumbDrive + +usb:v0A16p8888* + ID_MODEL_FROM_DATABASE=IBM USB Memory Key + +usb:v0A16p9988* + ID_MODEL_FROM_DATABASE=Trek2000 TD-G2 + +usb:v0A17* + ID_VENDOR_FROM_DATABASE=Pentax Corp. + +usb:v0A17p0004* + ID_MODEL_FROM_DATABASE=Optio 330 + +usb:v0A17p0006* + ID_MODEL_FROM_DATABASE=Optio S / S4 + +usb:v0A17p0007* + ID_MODEL_FROM_DATABASE=Optio 550 + +usb:v0A17p0009* + ID_MODEL_FROM_DATABASE=Optio 33WR + +usb:v0A17p000A* + ID_MODEL_FROM_DATABASE=Optio 555 + +usb:v0A17p000C* + ID_MODEL_FROM_DATABASE=Optio 43WR (mass storage mode) + +usb:v0A17p000D* + ID_MODEL_FROM_DATABASE=Optio 43WR + +usb:v0A17p0015* + ID_MODEL_FROM_DATABASE=Optio S40/S5i + +usb:v0A17p003B* + ID_MODEL_FROM_DATABASE=Optio 50 (mass storage mode) + +usb:v0A17p003D* + ID_MODEL_FROM_DATABASE=Optio S55 + +usb:v0A17p0041* + ID_MODEL_FROM_DATABASE=Optio S5z + +usb:v0A17p0043* + ID_MODEL_FROM_DATABASE=*ist DL + +usb:v0A17p0047* + ID_MODEL_FROM_DATABASE=Optio S60 + +usb:v0A17p0052* + ID_MODEL_FROM_DATABASE=Optio 60 Digital Camera + +usb:v0A17p006E* + ID_MODEL_FROM_DATABASE=K10D + +usb:v0A17p0070* + ID_MODEL_FROM_DATABASE=K100D + +usb:v0A17p0093* + ID_MODEL_FROM_DATABASE=K200D + +usb:v0A17p00A7* + ID_MODEL_FROM_DATABASE=Optio E50 + +usb:v0A17p1001* + ID_MODEL_FROM_DATABASE=EI2000 Camera powered by Digita! + +usb:v0A18* + ID_VENDOR_FROM_DATABASE=Heidelberger Druckmaschinen AG + +usb:v0A19* + ID_VENDOR_FROM_DATABASE=Hua Geng Technologies, Inc. + +usb:v0A21* + ID_VENDOR_FROM_DATABASE=Medtronic Physio Control Corp. + +usb:v0A21p8001* + ID_MODEL_FROM_DATABASE=MMT-7305WW [Medtronic Minimed CareLink] + +usb:v0A22* + ID_VENDOR_FROM_DATABASE=Century Semiconductor USA, Inc. + +usb:v0A27* + ID_VENDOR_FROM_DATABASE=Datacard Group + +usb:v0A27p0102* + ID_MODEL_FROM_DATABASE=SP35 + +usb:v0A2C* + ID_VENDOR_FROM_DATABASE=AK-Modul-Bus Computer GmbH + +usb:v0A2Cp0008* + ID_MODEL_FROM_DATABASE=GPIO Ports + +usb:v0A34* + ID_VENDOR_FROM_DATABASE=TG3 Electronics, Inc. + +usb:v0A34p0101* + ID_MODEL_FROM_DATABASE=TG82tp + +usb:v0A34p0110* + ID_MODEL_FROM_DATABASE=Deck 82-key backlit keyboard + +usb:v0A35* + ID_VENDOR_FROM_DATABASE=Radikal Technologies + +usb:v0A35p002A* + ID_MODEL_FROM_DATABASE=SAC - Software Assigned Controller + +usb:v0A35p008A* + ID_MODEL_FROM_DATABASE=SAC Hub + +usb:v0A39* + ID_VENDOR_FROM_DATABASE=Gilat Satellite Networks, Ltd + +usb:v0A3A* + ID_VENDOR_FROM_DATABASE=PentaMedia Co., Ltd + +usb:v0A3Ap0163* + ID_MODEL_FROM_DATABASE=KN-W510U 1.0 Wireless LAN Adapter + +usb:v0A3C* + ID_VENDOR_FROM_DATABASE=NTT DoCoMo, Inc. + +usb:v0A3D* + ID_VENDOR_FROM_DATABASE=Varo Vision + +usb:v0A3F* + ID_VENDOR_FROM_DATABASE=Swissonic AG + +usb:v0A43* + ID_VENDOR_FROM_DATABASE=Boca Systems, Inc. + +usb:v0A46* + ID_VENDOR_FROM_DATABASE=Davicom Semiconductor, Inc. + +usb:v0A46p0268* + ID_MODEL_FROM_DATABASE=ST268 + +usb:v0A46p6688* + ID_MODEL_FROM_DATABASE=ZT6688 Fast Ethernet Adapter + +usb:v0A46p8515* + ID_MODEL_FROM_DATABASE=ADMtek ADM8515 NIC + +usb:v0A46p9000* + ID_MODEL_FROM_DATABASE=DM9000E Fast Ethernet Adapter + +usb:v0A46p9601* + ID_MODEL_FROM_DATABASE=DM9601 Fast Ethernet Adapter + +usb:v0A47* + ID_VENDOR_FROM_DATABASE=Hirose Electric + +usb:v0A48* + ID_VENDOR_FROM_DATABASE=I/O Interconnect + +usb:v0A48p3233* + ID_MODEL_FROM_DATABASE=Multimedia Card Reader + +usb:v0A48p3239* + ID_MODEL_FROM_DATABASE=Multimedia Card Reader + +usb:v0A48p3258* + ID_MODEL_FROM_DATABASE=Dane Elec zMate SD Reader + +usb:v0A48p3259* + ID_MODEL_FROM_DATABASE=Dane Elec zMate CF Reader + +usb:v0A48p5000* + ID_MODEL_FROM_DATABASE=MediaGear xD-SM + +usb:v0A48p500A* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A48p500F* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A48p5010* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A48p5011* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A48p5014* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A48p5020* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A48p5021* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A48p5022* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A48p5023* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A48p5024* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A48p5025* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0A4A* + ID_VENDOR_FROM_DATABASE=Ploytec GmbH + +usb:v0A4B* + ID_VENDOR_FROM_DATABASE=Fujitsu Media Devices, Ltd + +usb:v0A4C* + ID_VENDOR_FROM_DATABASE=Computex Co., Ltd + +usb:v0A4Cp15D9* + ID_MODEL_FROM_DATABASE=OPTICAL MOUSE + +usb:v0A4D* + ID_VENDOR_FROM_DATABASE=Evolution Electronics, Ltd + +usb:v0A4Dp0064* + ID_MODEL_FROM_DATABASE=MK-225 Driver + +usb:v0A4Dp0065* + ID_MODEL_FROM_DATABASE=MK-225C Driver + +usb:v0A4Dp0066* + ID_MODEL_FROM_DATABASE=MK-225C Driver + +usb:v0A4Dp0067* + ID_MODEL_FROM_DATABASE=MK-425C Driver + +usb:v0A4Dp0078* + ID_MODEL_FROM_DATABASE=MK-37 Driver + +usb:v0A4Dp0079* + ID_MODEL_FROM_DATABASE=MK-37C Driver + +usb:v0A4Dp007A* + ID_MODEL_FROM_DATABASE=MK-37C Driver + +usb:v0A4Dp008C* + ID_MODEL_FROM_DATABASE=TerraTec MIDI MASTER + +usb:v0A4Dp008D* + ID_MODEL_FROM_DATABASE=MK-249C Driver + +usb:v0A4Dp008E* + ID_MODEL_FROM_DATABASE=MK-249C MIDI Keyboard + +usb:v0A4Dp008F* + ID_MODEL_FROM_DATABASE=MK-449C Driver + +usb:v0A4Dp0090* + ID_MODEL_FROM_DATABASE=Keystation 49e Driver + +usb:v0A4Dp0091* + ID_MODEL_FROM_DATABASE=Keystation 61es Driver + +usb:v0A4Dp00A0* + ID_MODEL_FROM_DATABASE=MK-361 Driver + +usb:v0A4Dp00A1* + ID_MODEL_FROM_DATABASE=MK-361C Driver + +usb:v0A4Dp00A2* + ID_MODEL_FROM_DATABASE=MK-361C Driver + +usb:v0A4Dp00A3* + ID_MODEL_FROM_DATABASE=MK-461C MIDI Keyboard + +usb:v0A4Dp00B5* + ID_MODEL_FROM_DATABASE=Keystation Pro 88 Driver + +usb:v0A4Dp00D2* + ID_MODEL_FROM_DATABASE=E-Keys Driver + +usb:v0A4Dp00F0* + ID_MODEL_FROM_DATABASE=UC-16 Driver + +usb:v0A4Dp00F1* + ID_MODEL_FROM_DATABASE=X-Session Driver + +usb:v0A4Dp00F5* + ID_MODEL_FROM_DATABASE=UC-33e MIDI Controller + +usb:v0A4E* + ID_VENDOR_FROM_DATABASE=Steinberg Soft-und Hardware GmbH + +usb:v0A4F* + ID_VENDOR_FROM_DATABASE=Litton Systems, Inc. + +usb:v0A50* + ID_VENDOR_FROM_DATABASE=Mimaki Engineering Co., Ltd + +usb:v0A51* + ID_VENDOR_FROM_DATABASE=Sony Electronics, Inc. + +usb:v0A52* + ID_VENDOR_FROM_DATABASE=Jebsee Electronics Co., Ltd + +usb:v0A53* + ID_VENDOR_FROM_DATABASE=Portable Peripheral Co., Ltd + +usb:v0A53p1000* + ID_MODEL_FROM_DATABASE=Scanner + +usb:v0A53p2000* + ID_MODEL_FROM_DATABASE=Q-Scan A6 Scanner + +usb:v0A53p2001* + ID_MODEL_FROM_DATABASE=Q-Scan A6 Scanner + +usb:v0A53p2013* + ID_MODEL_FROM_DATABASE=Media Drive A6 Scanner + +usb:v0A53p2014* + ID_MODEL_FROM_DATABASE=Media Drive A6 Scanner + +usb:v0A53p2015* + ID_MODEL_FROM_DATABASE=BizCardReader 600C + +usb:v0A53p2016* + ID_MODEL_FROM_DATABASE=BizCardReader 600C + +usb:v0A53p202A* + ID_MODEL_FROM_DATABASE=Scanshell-CSSN + +usb:v0A53p3000* + ID_MODEL_FROM_DATABASE=Q-Scan A8 Scanner + +usb:v0A53p3002* + ID_MODEL_FROM_DATABASE=Q-Scan A8 Reader + +usb:v0A53p3015* + ID_MODEL_FROM_DATABASE=BizCardReader 300G + +usb:v0A53p302A* + ID_MODEL_FROM_DATABASE=LM9832 - PA570 Mini Business Card Scanner [Targus] + +usb:v0A53p5001* + ID_MODEL_FROM_DATABASE=BizCardReader 900C + +usb:v0A5A* + ID_VENDOR_FROM_DATABASE=Electronics For Imaging, Inc. + +usb:v0A5B* + ID_VENDOR_FROM_DATABASE=EAsics NV + +usb:v0A5C* + ID_VENDOR_FROM_DATABASE=Broadcom Corp. + +usb:v0A5Cp0201* + ID_MODEL_FROM_DATABASE=iLine10(tm) Network Adapter + +usb:v0A5Cp2000* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0A5Cp2001* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0A5Cp2009* + ID_MODEL_FROM_DATABASE=BCM2035 Bluetooth + +usb:v0A5Cp200A* + ID_MODEL_FROM_DATABASE=BCM2035 Bluetooth dongle + +usb:v0A5Cp200F* + ID_MODEL_FROM_DATABASE=Bluetooth Controller + +usb:v0A5Cp201D* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0A5Cp201E* + ID_MODEL_FROM_DATABASE=IBM Integrated Bluetooth IV + +usb:v0A5Cp2020* + ID_MODEL_FROM_DATABASE=Bluetooth dongle + +usb:v0A5Cp2021* + ID_MODEL_FROM_DATABASE=BCM2035B3 Bluetooth Adapter + +usb:v0A5Cp2033* + ID_MODEL_FROM_DATABASE=BCM2033 Bluetooth + +usb:v0A5Cp2035* + ID_MODEL_FROM_DATABASE=BCM2035 Bluetooth + +usb:v0A5Cp2038* + ID_MODEL_FROM_DATABASE=Blutonium Device + +usb:v0A5Cp2039* + ID_MODEL_FROM_DATABASE=BCM2045 Bluetooth + +usb:v0A5Cp2045* + ID_MODEL_FROM_DATABASE=Bluetooth Controller + +usb:v0A5Cp2046* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0A5Cp2047* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0A5Cp205E* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0A5Cp2100* + ID_MODEL_FROM_DATABASE=Bluetooth 2.0+eDR dongle + +usb:v0A5Cp2101* + ID_MODEL_FROM_DATABASE=BCM2045 Bluetooth + +usb:v0A5Cp2102* + ID_MODEL_FROM_DATABASE=ANYCOM Blue USB-200/250 + +usb:v0A5Cp2110* + ID_MODEL_FROM_DATABASE=BCM2045B (BDC-2) [Bluetooth Controller] + +usb:v0A5Cp2111* + ID_MODEL_FROM_DATABASE=ANYCOM Blue USB-UHE 200/250 + +usb:v0A5Cp2120* + ID_MODEL_FROM_DATABASE=2045 Bluetooth 2.0 USB-UHE Device with trace filter + +usb:v0A5Cp2121* + ID_MODEL_FROM_DATABASE=BCM2210 Bluetooth + +usb:v0A5Cp2122* + ID_MODEL_FROM_DATABASE=Bluetooth 2.0+EDR dongle + +usb:v0A5Cp2123* + ID_MODEL_FROM_DATABASE=Bluetooth dongle + +usb:v0A5Cp2130* + ID_MODEL_FROM_DATABASE=2045 Bluetooth 2.0 USB-UHE Device with trace filter + +usb:v0A5Cp2131* + ID_MODEL_FROM_DATABASE=2045 Bluetooth 2.0 Device with trace filter + +usb:v0A5Cp2145* + ID_MODEL_FROM_DATABASE=BCM2045B (BDC-2.1) [Bluetooth Controller] + +usb:v0A5Cp2148* + ID_MODEL_FROM_DATABASE=BCM92046DG-CL1ROM Bluetooth 2.1 Adapter + +usb:v0A5Cp2150* + ID_MODEL_FROM_DATABASE=BCM2046 Bluetooth Device + +usb:v0A5Cp2151* + ID_MODEL_FROM_DATABASE=Bluetooth + +usb:v0A5Cp2154* + ID_MODEL_FROM_DATABASE=BCM92046DG-CL1ROM Bluetooth 2.1 UHE Dongle + +usb:v0A5Cp216A* + ID_MODEL_FROM_DATABASE=BCM43142A0 Bluetooth + +usb:v0A5Cp216C* + ID_MODEL_FROM_DATABASE=BCM43142A0 Bluetooth Device + +usb:v0A5Cp216D* + ID_MODEL_FROM_DATABASE=BCM43142A0 Bluetooth 4.0 + +usb:v0A5Cp216F* + ID_MODEL_FROM_DATABASE=BCM20702A0 Bluetooth + +usb:v0A5Cp217D* + ID_MODEL_FROM_DATABASE=HP Bluethunder + +usb:v0A5Cp217F* + ID_MODEL_FROM_DATABASE=BCM2045B (BDC-2.1) + +usb:v0A5Cp2198* + ID_MODEL_FROM_DATABASE=Bluetooth 3.0 Device + +usb:v0A5Cp219B* + ID_MODEL_FROM_DATABASE=Bluetooth 2.1 Device + +usb:v0A5Cp21B1* + ID_MODEL_FROM_DATABASE=HP Bluetooth Module + +usb:v0A5Cp21B4* + ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR + +usb:v0A5Cp21B9* + ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR + +usb:v0A5Cp21BA* + ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR + +usb:v0A5Cp21BB* + ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR + +usb:v0A5Cp21BC* + ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR + +usb:v0A5Cp21BD* + ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 2.1 + EDR + +usb:v0A5Cp21D7* + ID_MODEL_FROM_DATABASE=BCM43142 Bluetooth 4.0 + +usb:v0A5Cp21E1* + ID_MODEL_FROM_DATABASE=HP Portable SoftSailing + +usb:v0A5Cp21E3* + ID_MODEL_FROM_DATABASE=HP Portable Valentine + +usb:v0A5Cp21E6* + ID_MODEL_FROM_DATABASE=BCM20702 Bluetooth 4.0 [ThinkPad] + +usb:v0A5Cp21E8* + ID_MODEL_FROM_DATABASE=BCM20702A0 Bluetooth 4.0 + +usb:v0A5Cp21F1* + ID_MODEL_FROM_DATABASE=HP Portable Bumble Bee + +usb:v0A5Cp22BE* + ID_MODEL_FROM_DATABASE=BCM2070 Bluetooth 3.0 + HS + +usb:v0A5Cp4500* + ID_MODEL_FROM_DATABASE=BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth) + +usb:v0A5Cp4502* + ID_MODEL_FROM_DATABASE=Keyboard (Boot Interface Subclass) + +usb:v0A5Cp4503* + ID_MODEL_FROM_DATABASE=Mouse (Boot Interface Subclass) + +usb:v0A5Cp5800* + ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor + +usb:v0A5Cp5801* + ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor with fingerprint swipe sensor + +usb:v0A5Cp5802* + ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor with fingerprint touch sensor + +usb:v0A5Cp5803* + ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor with secure keyboard + +usb:v0A5Cp5804* + ID_MODEL_FROM_DATABASE=BCM5880 Secure Applications Processor with fingerprint swipe sensor + +usb:v0A5Cp6300* + ID_MODEL_FROM_DATABASE=Pirelli Remote NDIS Device + +usb:v0A5Cp6410* + ID_MODEL_FROM_DATABASE=BCM20703A1 Bluetooth 4.1 + LE + +usb:v0A5CpBD11* + ID_MODEL_FROM_DATABASE=BCM4320 802.11bg Wireless Adapter + +usb:v0A5CpBD12* + ID_MODEL_FROM_DATABASE=BCM4326U 802.11bg Wireless Adapter + +usb:v0A5CpBD13* + ID_MODEL_FROM_DATABASE=BCM4323 802.11abgn Wireless Adapter + +usb:v0A5CpBD16* + ID_MODEL_FROM_DATABASE=BCM4319 802.11bgn Wireless Adapter + +usb:v0A5CpBD17* + ID_MODEL_FROM_DATABASE=BCM43236 802.11abgn Wireless Adapter + +usb:v0A5CpBD1D* + ID_MODEL_FROM_DATABASE=BCM43526 802.11a/b/g/n/ac (2x2) Wireless Adapter + +usb:v0A5CpBD1E* + ID_MODEL_FROM_DATABASE=BCM43143 802.11bgn (1x1) Wireless Adapter + +usb:v0A5CpBD1F* + ID_MODEL_FROM_DATABASE=BCM43242 802.11abgn Wireless Adapter + +usb:v0A5CpD11B* + ID_MODEL_FROM_DATABASE=Eminent EM4045 [Broadcom 4320 USB] + +usb:v0A5D* + ID_VENDOR_FROM_DATABASE=Diatrend Corp. + +usb:v0A5F* + ID_VENDOR_FROM_DATABASE=Zebra + +usb:v0A5Fp0009* + ID_MODEL_FROM_DATABASE=LP2844 Printer + +usb:v0A5Fp0081* + ID_MODEL_FROM_DATABASE=GK420t Label Printer + +usb:v0A5Fp008B* + ID_MODEL_FROM_DATABASE=HC100 wristbands Printer + +usb:v0A5Fp008C* + ID_MODEL_FROM_DATABASE=ZP 450 Printer + +usb:v0A5Fp00D1* + ID_MODEL_FROM_DATABASE=Zebra GC420d Label Printer + +usb:v0A5Fp930A* + ID_MODEL_FROM_DATABASE=Printer + +usb:v0A62* + ID_VENDOR_FROM_DATABASE=MPMan + +usb:v0A62p0010* + ID_MODEL_FROM_DATABASE=MPMan MP-F40 MP3 Player + +usb:v0A66* + ID_VENDOR_FROM_DATABASE=ClearCube Technology + +usb:v0A67* + ID_VENDOR_FROM_DATABASE=Medeli Electronics Co., Ltd + +usb:v0A68* + ID_VENDOR_FROM_DATABASE=Comaide Corp. + +usb:v0A69* + ID_VENDOR_FROM_DATABASE=Chroma ate, Inc. + +usb:v0A6B* + ID_VENDOR_FROM_DATABASE=Green House Co., Ltd + +usb:v0A6Bp0001* + ID_MODEL_FROM_DATABASE=Compact Flash R/W with MP3 player + +usb:v0A6Bp000F* + ID_MODEL_FROM_DATABASE=FlashDisk + +usb:v0A6C* + ID_VENDOR_FROM_DATABASE=Integrated Circuit Systems, Inc. + +usb:v0A6D* + ID_VENDOR_FROM_DATABASE=UPS Manufacturing + +usb:v0A6E* + ID_VENDOR_FROM_DATABASE=Benwin + +usb:v0A6F* + ID_VENDOR_FROM_DATABASE=Core Technology, Inc. + +usb:v0A6Fp0400* + ID_MODEL_FROM_DATABASE=Xanboo + +usb:v0A70* + ID_VENDOR_FROM_DATABASE=International Game Technology + +usb:v0A71* + ID_VENDOR_FROM_DATABASE=VIPColor Technologies USA, Inc. + +usb:v0A71p0001* + ID_MODEL_FROM_DATABASE=VP485 Printer + +usb:v0A72* + ID_VENDOR_FROM_DATABASE=Sanwa Denshi + +usb:v0A73* + ID_VENDOR_FROM_DATABASE=Mackie Designs + +usb:v0A73p0002* + ID_MODEL_FROM_DATABASE=XD-2 [Spike] + +usb:v0A7D* + ID_VENDOR_FROM_DATABASE=NSTL, Inc. + +usb:v0A7E* + ID_VENDOR_FROM_DATABASE=Octagon Systems Corp. + +usb:v0A80* + ID_VENDOR_FROM_DATABASE=Rexon Technology Corp., Ltd + +usb:v0A81* + ID_VENDOR_FROM_DATABASE=Chesen Electronics Corp. + +usb:v0A81p0101* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0A81p0103* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0A81p0203* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v0A81p0205* + ID_MODEL_FROM_DATABASE=PS/2 Keyboard+Mouse Adapter + +usb:v0A81p0701* + ID_MODEL_FROM_DATABASE=USB Missile Launcher + +usb:v0A81pFF01* + ID_MODEL_FROM_DATABASE=Wireless Missile Launcher + +usb:v0A82* + ID_VENDOR_FROM_DATABASE=Syscan + +usb:v0A82p4600* + ID_MODEL_FROM_DATABASE=TravelScan 460/464 + +usb:v0A83* + ID_VENDOR_FROM_DATABASE=NextComm, Inc. + +usb:v0A84* + ID_VENDOR_FROM_DATABASE=Maui Innovative Peripherals + +usb:v0A85* + ID_VENDOR_FROM_DATABASE=Idexx Labs + +usb:v0A86* + ID_VENDOR_FROM_DATABASE=NITGen Co., Ltd + +usb:v0A89* + ID_VENDOR_FROM_DATABASE=Aktiv + +usb:v0A89p0001* + ID_MODEL_FROM_DATABASE=Guardant Stealth/Net + +usb:v0A89p0002* + ID_MODEL_FROM_DATABASE=Guardant ID + +usb:v0A89p0003* + ID_MODEL_FROM_DATABASE=Guardant Stealth 2 + +usb:v0A89p0004* + ID_MODEL_FROM_DATABASE=Rutoken + +usb:v0A89p0005* + ID_MODEL_FROM_DATABASE=Guardant Fidus + +usb:v0A89p0006* + ID_MODEL_FROM_DATABASE=Guardant Stealth 3 + +usb:v0A89p0007* + ID_MODEL_FROM_DATABASE=Guardant Stealth 2 + +usb:v0A89p0008* + ID_MODEL_FROM_DATABASE=Guardant Stealth 3 Sign/Time + +usb:v0A89p0009* + ID_MODEL_FROM_DATABASE=Guardant Code + +usb:v0A89p000A* + ID_MODEL_FROM_DATABASE=Guardant Sign Pro + +usb:v0A89p000B* + ID_MODEL_FROM_DATABASE=Guardant Sign Pro HID + +usb:v0A89p000C* + ID_MODEL_FROM_DATABASE=Guardant Stealth 3 Sign/Time + +usb:v0A89p000D* + ID_MODEL_FROM_DATABASE=Guardant Code HID + +usb:v0A89p000F* + ID_MODEL_FROM_DATABASE=Guardant System Firmware Update + +usb:v0A89p0020* + ID_MODEL_FROM_DATABASE=Rutoken S + +usb:v0A89p0025* + ID_MODEL_FROM_DATABASE=Rutoken lite + +usb:v0A89p0026* + ID_MODEL_FROM_DATABASE=Rutoken lite HID + +usb:v0A89p002A* + ID_MODEL_FROM_DATABASE=Rutoken Mass Storage + +usb:v0A89p002B* + ID_MODEL_FROM_DATABASE=Guardant Mass Storage + +usb:v0A89p0030* + ID_MODEL_FROM_DATABASE=Rutoken ECP + +usb:v0A89p0040* + ID_MODEL_FROM_DATABASE=Rutoken ECP HID + +usb:v0A89p0060* + ID_MODEL_FROM_DATABASE=Rutoken Magistra + +usb:v0A89p0061* + ID_MODEL_FROM_DATABASE=Rutoken Magistra + +usb:v0A89p0069* + ID_MODEL_FROM_DATABASE=Reader + +usb:v0A89p0080* + ID_MODEL_FROM_DATABASE=Rutoken PinPad Ex + +usb:v0A89p0081* + ID_MODEL_FROM_DATABASE=Rutoken PinPad In + +usb:v0A89p0082* + ID_MODEL_FROM_DATABASE=Rutoken PinPad 2 + +usb:v0A8D* + ID_VENDOR_FROM_DATABASE=Picturetel + +usb:v0A8E* + ID_VENDOR_FROM_DATABASE=Japan Aviation Electronics Industry, Ltd + +usb:v0A8Ep2011* + ID_MODEL_FROM_DATABASE=Filter Driver For JAE XMC R/W + +usb:v0A90* + ID_VENDOR_FROM_DATABASE=Candy Technology Co., Ltd + +usb:v0A91* + ID_VENDOR_FROM_DATABASE=Globlink Technology, Inc. + +usb:v0A91p3801* + ID_MODEL_FROM_DATABASE=Targus PAKP003 Mouse + +usb:v0A92* + ID_VENDOR_FROM_DATABASE=EGO SYStems, Inc. + +usb:v0A92p0011* + ID_MODEL_FROM_DATABASE=SYS WaveTerminal U2A + +usb:v0A92p0021* + ID_MODEL_FROM_DATABASE=GIGAPort + +usb:v0A92p0031* + ID_MODEL_FROM_DATABASE=GIGAPortAG + +usb:v0A92p0053* + ID_MODEL_FROM_DATABASE=AudioTrak Optoplay + +usb:v0A92p0061* + ID_MODEL_FROM_DATABASE=Waveterminal U24 + +usb:v0A92p0071* + ID_MODEL_FROM_DATABASE=MAYA EX7 + +usb:v0A92p0091* + ID_MODEL_FROM_DATABASE=Maya 44 + +usb:v0A92p00B1* + ID_MODEL_FROM_DATABASE=MAYA EX5 + +usb:v0A92p1000* + ID_MODEL_FROM_DATABASE=MIDI Mate + +usb:v0A92p1010* + ID_MODEL_FROM_DATABASE=RoMI/O + +usb:v0A92p1020* + ID_MODEL_FROM_DATABASE=M4U + +usb:v0A92p1030* + ID_MODEL_FROM_DATABASE=M8U + +usb:v0A92p1090* + ID_MODEL_FROM_DATABASE=KeyControl49 + +usb:v0A92p10A0* + ID_MODEL_FROM_DATABASE=KeyControl25 + +usb:v0A93* + ID_VENDOR_FROM_DATABASE=C Technologies AB + +usb:v0A93p0002* + ID_MODEL_FROM_DATABASE=C-Pen 10 + +usb:v0A93p0005* + ID_MODEL_FROM_DATABASE=MyPen Light + +usb:v0A93p000D* + ID_MODEL_FROM_DATABASE=Input Pen + +usb:v0A93p0010* + ID_MODEL_FROM_DATABASE=C-Pen 20 + +usb:v0A93p0A93* + ID_MODEL_FROM_DATABASE=PayPen + +usb:v0A94* + ID_VENDOR_FROM_DATABASE=Intersense + +usb:v0AA3* + ID_VENDOR_FROM_DATABASE=Lava Computer Mfg., Inc. + +usb:v0AA4* + ID_VENDOR_FROM_DATABASE=Develco Elektronik + +usb:v0AA5* + ID_VENDOR_FROM_DATABASE=First International Digital + +usb:v0AA5p0002* + ID_MODEL_FROM_DATABASE=irock! 500 Series + +usb:v0AA5p0801* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0AA6* + ID_VENDOR_FROM_DATABASE=Perception Digital, Ltd + +usb:v0AA6p0101* + ID_MODEL_FROM_DATABASE=Hercules Jukebox + +usb:v0AA6p1501* + ID_MODEL_FROM_DATABASE=Store 'n' Go HD Drive + +usb:v0AA7* + ID_VENDOR_FROM_DATABASE=Wincor Nixdorf International GmbH + +usb:v0AA7p0100* + ID_MODEL_FROM_DATABASE=POS Keyboard, TA58P-USB + +usb:v0AA7p0101* + ID_MODEL_FROM_DATABASE=POS Keyboard, TA85P-USB + +usb:v0AA7p0102* + ID_MODEL_FROM_DATABASE=POS Keyboard, TA59-USB + +usb:v0AA7p0103* + ID_MODEL_FROM_DATABASE=POS Keyboard, TA60-USB + +usb:v0AA7p0104* + ID_MODEL_FROM_DATABASE=SNIkey Keyboard, SNIKey-KB-USB + +usb:v0AA7p0200* + ID_MODEL_FROM_DATABASE=Operator Display, BA63-USB + +usb:v0AA7p0201* + ID_MODEL_FROM_DATABASE=Operator Display, BA66-USB + +usb:v0AA7p0202* + ID_MODEL_FROM_DATABASE=Operator Display & Scanner, XiCheck-BA63 + +usb:v0AA7p0203* + ID_MODEL_FROM_DATABASE=Operator Display & Scanner, XiCheck-BA66 + +usb:v0AA7p0204* + ID_MODEL_FROM_DATABASE=Graphics Operator Display, BA63GV + +usb:v0AA7p0300* + ID_MODEL_FROM_DATABASE=POS Printer (printer class mode), TH210 + +usb:v0AA7p0301* + ID_MODEL_FROM_DATABASE=POS Printer (native mode), TH210 + +usb:v0AA7p0302* + ID_MODEL_FROM_DATABASE=POS Printer (printer class mode), TH220 + +usb:v0AA7p0303* + ID_MODEL_FROM_DATABASE=POS Printer (native mode), TH220 + +usb:v0AA7p0304* + ID_MODEL_FROM_DATABASE=POS Printer, TH230 + +usb:v0AA7p0305* + ID_MODEL_FROM_DATABASE=Lottery Printer, XiPrintPlus + +usb:v0AA7p0306* + ID_MODEL_FROM_DATABASE=POS Printer (printer class mode), TH320 + +usb:v0AA7p0307* + ID_MODEL_FROM_DATABASE=POS Printer (native mode), TH320 + +usb:v0AA7p0308* + ID_MODEL_FROM_DATABASE=POS Printer (printer class mode), TH420 + +usb:v0AA7p0309* + ID_MODEL_FROM_DATABASE=POS Printer (native mode), TH420 + +usb:v0AA7p030A* + ID_MODEL_FROM_DATABASE=POS Printer, TH200B + +usb:v0AA7p0400* + ID_MODEL_FROM_DATABASE=Lottery Scanner, Xiscan S + +usb:v0AA7p0401* + ID_MODEL_FROM_DATABASE=Lottery Scanner, Xiscan 3 + +usb:v0AA7p0402* + ID_MODEL_FROM_DATABASE=Programmable Magnetic Swipe Card Reader, MSRP-USB + +usb:v0AA7p0500* + ID_MODEL_FROM_DATABASE=IDE Adapter + +usb:v0AA7p0501* + ID_MODEL_FROM_DATABASE=Hub Printer Interface + +usb:v0AA7p0502* + ID_MODEL_FROM_DATABASE=Hub SNIKey Keyboard + +usb:v0AA7p4304* + ID_MODEL_FROM_DATABASE=Banking Printer TP07 + +usb:v0AA7p4305* + ID_MODEL_FROM_DATABASE=Banking Printer TP07c + +usb:v0AA7p4500* + ID_MODEL_FROM_DATABASE=WN Central Special Electronics + +usb:v0AA8* + ID_VENDOR_FROM_DATABASE=TriGem Computer, Inc. + +usb:v0AA8p0060* + ID_MODEL_FROM_DATABASE=TG 11Mbps WLAN Mini Adapter + +usb:v0AA8p1001* + ID_MODEL_FROM_DATABASE=DreamComboM4100 + +usb:v0AA8p3002* + ID_MODEL_FROM_DATABASE=InkJet Color Printer + +usb:v0AA8p8001* + ID_MODEL_FROM_DATABASE=TG_iMON + +usb:v0AA8p8002* + ID_MODEL_FROM_DATABASE=TG_KLOSS + +usb:v0AA8pA001* + ID_MODEL_FROM_DATABASE=TG_X2 + +usb:v0AA8pA002* + ID_MODEL_FROM_DATABASE=TGVFD_KLOSS + +usb:v0AA8pFFDA* + ID_MODEL_FROM_DATABASE=iMON_VFD + +usb:v0AA9* + ID_VENDOR_FROM_DATABASE=Baromtec Co. + +usb:v0AA9pF01B* + ID_MODEL_FROM_DATABASE=Medion MD 6242 MP3 Player + +usb:v0AAA* + ID_VENDOR_FROM_DATABASE=Japan CBM Corp. + +usb:v0AAB* + ID_VENDOR_FROM_DATABASE=Vision Shape Europe SA + +usb:v0AAC* + ID_VENDOR_FROM_DATABASE=iCompression, Inc. + +usb:v0AAD* + ID_VENDOR_FROM_DATABASE=Rohde & Schwarz GmbH & Co. KG + +usb:v0AADp0003* + ID_MODEL_FROM_DATABASE=NRP-Z21 + +usb:v0AADp000C* + ID_MODEL_FROM_DATABASE=NRP-Z11 + +usb:v0AADp0013* + ID_MODEL_FROM_DATABASE=NRP-Z22 + +usb:v0AADp0014* + ID_MODEL_FROM_DATABASE=NRP-Z23 + +usb:v0AADp0015* + ID_MODEL_FROM_DATABASE=NRP-Z24 + +usb:v0AADp0016* + ID_MODEL_FROM_DATABASE=NRP-Z51 + +usb:v0AADp0017* + ID_MODEL_FROM_DATABASE=NRP-Z52 + +usb:v0AADp0018* + ID_MODEL_FROM_DATABASE=NRP-Z55 + +usb:v0AADp0019* + ID_MODEL_FROM_DATABASE=NRP-Z56 + +usb:v0AADp0021* + ID_MODEL_FROM_DATABASE=NRP-Z91 + +usb:v0AADp0023* + ID_MODEL_FROM_DATABASE=NRP-Z81 + +usb:v0AADp002C* + ID_MODEL_FROM_DATABASE=NRP-Z31 + +usb:v0AADp002D* + ID_MODEL_FROM_DATABASE=NRP-Z37 + +usb:v0AADp002F* + ID_MODEL_FROM_DATABASE=NRP-Z27 + +usb:v0AADp0051* + ID_MODEL_FROM_DATABASE=NRP-Z28 + +usb:v0AADp0052* + ID_MODEL_FROM_DATABASE=NRP-Z98 + +usb:v0AADp0062* + ID_MODEL_FROM_DATABASE=NRP-Z92 + +usb:v0AADp0070* + ID_MODEL_FROM_DATABASE=NRP-Z57 + +usb:v0AADp0083* + ID_MODEL_FROM_DATABASE=NRP-Z85 + +usb:v0AADp0095* + ID_MODEL_FROM_DATABASE=NRP-Z86 + +usb:v0AADp0117* + ID_MODEL_FROM_DATABASE=HMF / HMP / HMS-X / HMO series Oscilloscopes + +usb:v0AADp0118* + ID_MODEL_FROM_DATABASE=HMF / HMP / HMS-X / HMO series Oscilloscopes + +usb:v0AADp0119* + ID_MODEL_FROM_DATABASE=HMF / HMP / HMS-X / HMO series Oscilloscopes + +usb:v0AAE* + ID_VENDOR_FROM_DATABASE=NEC infrontia Corp. (Nitsuko) + +usb:v0AAF* + ID_VENDOR_FROM_DATABASE=Digitalway Co., Ltd + +usb:v0AB0* + ID_VENDOR_FROM_DATABASE=Arrow Strong Electronics Co., Ltd + +usb:v0AB1* + ID_VENDOR_FROM_DATABASE=FEIG ELECTRONIC GmbH + +usb:v0AB1p0002* + ID_MODEL_FROM_DATABASE=OBID RFID-Reader + +usb:v0AB1p0004* + ID_MODEL_FROM_DATABASE=OBID classic-pro + +usb:v0ABA* + ID_VENDOR_FROM_DATABASE=Ellisys + +usb:v0ABAp8001* + ID_MODEL_FROM_DATABASE=Tracker 110 Protocol Analyzer + +usb:v0ABAp8002* + ID_MODEL_FROM_DATABASE=Explorer 200 Protocol Analyzer + +usb:v0ABE* + ID_VENDOR_FROM_DATABASE=Stereo-Link + +usb:v0ABEp0101* + ID_MODEL_FROM_DATABASE=SL1200 DAC + +usb:v0ABF* + ID_VENDOR_FROM_DATABASE=Diolan + +usb:v0ABFp3370* + ID_MODEL_FROM_DATABASE=I2C/SPI Adapter - U2C-12 + +usb:v0AC3* + ID_VENDOR_FROM_DATABASE=Sanyo Semiconductor Company Micro + +usb:v0AC4* + ID_VENDOR_FROM_DATABASE=Leco Corp. + +usb:v0AC5* + ID_VENDOR_FROM_DATABASE=I & C Corp. + +usb:v0AC6* + ID_VENDOR_FROM_DATABASE=Singing Electrons, Inc. + +usb:v0AC7* + ID_VENDOR_FROM_DATABASE=Panwest Corp. + +usb:v0AC8* + ID_VENDOR_FROM_DATABASE=Z-Star Microelectronics Corp. + +usb:v0AC8p0301* + ID_MODEL_FROM_DATABASE=Web Camera + +usb:v0AC8p0302* + ID_MODEL_FROM_DATABASE=ZC0302 Webcam + +usb:v0AC8p0321* + ID_MODEL_FROM_DATABASE=Vimicro generic vc0321 Camera + +usb:v0AC8p0323* + ID_MODEL_FROM_DATABASE=Luxya WC-1200 USB 2.0 Webcam + +usb:v0AC8p0328* + ID_MODEL_FROM_DATABASE=A4Tech PK-130MG + +usb:v0AC8p0336* + ID_MODEL_FROM_DATABASE=Elecom UCAM-DLQ30 + +usb:v0AC8p301B* + ID_MODEL_FROM_DATABASE=ZC0301 Webcam + +usb:v0AC8p303B* + ID_MODEL_FROM_DATABASE=ZC0303 Webcam + +usb:v0AC8p305B* + ID_MODEL_FROM_DATABASE=ZC0305 Webcam + +usb:v0AC8p307B* + ID_MODEL_FROM_DATABASE=USB 1.1 Webcam + +usb:v0AC8p332D* + ID_MODEL_FROM_DATABASE=Vega USB 2.0 Camera + +usb:v0AC8p3343* + ID_MODEL_FROM_DATABASE=Sirius USB 2.0 Camera + +usb:v0AC8p3370* + ID_MODEL_FROM_DATABASE=Traveler TV 6500 SF Dia-scanner + +usb:v0AC8p3420* + ID_MODEL_FROM_DATABASE=Venus USB2.0 Camera + +usb:v0AC8pC001* + ID_MODEL_FROM_DATABASE=Sony embedded vimicro Camera + +usb:v0AC8pC002* + ID_MODEL_FROM_DATABASE=Visual Communication Camera VGP-VCC1 + +usb:v0AC8pC302* + ID_MODEL_FROM_DATABASE=Vega USB 2.0 Camera + +usb:v0AC8pC303* + ID_MODEL_FROM_DATABASE=Saturn USB 2.0 Camera + +usb:v0AC8pC326* + ID_MODEL_FROM_DATABASE=Namuga 1.3M Webcam + +usb:v0AC8pC33F* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v0AC8pC429* + ID_MODEL_FROM_DATABASE=Lenovo ThinkCentre Web Camera + +usb:v0AC8pC42D* + ID_MODEL_FROM_DATABASE=Lenovo IdeaCentre Web Camera + +usb:v0AC9* + ID_VENDOR_FROM_DATABASE=Micro Solutions, Inc. + +usb:v0AC9p0000* + ID_MODEL_FROM_DATABASE=Backpack CD-ReWriter + +usb:v0AC9p0001* + ID_MODEL_FROM_DATABASE=BACKPACK 2 Cable + +usb:v0AC9p0010* + ID_MODEL_FROM_DATABASE=BACKPACK + +usb:v0AC9p0011* + ID_MODEL_FROM_DATABASE=Backpack 40GB Hard Drive + +usb:v0AC9p0110* + ID_MODEL_FROM_DATABASE=BACKPACK + +usb:v0AC9p0111* + ID_MODEL_FROM_DATABASE=BackPack + +usb:v0AC9p1234* + ID_MODEL_FROM_DATABASE=BACKPACK + +usb:v0ACA* + ID_VENDOR_FROM_DATABASE=OPEN Networks Ltd + +usb:v0ACAp1060* + ID_MODEL_FROM_DATABASE=OPEN NT1 Plus II + +usb:v0ACC* + ID_VENDOR_FROM_DATABASE=Koga Electronics Co. + +usb:v0ACD* + ID_VENDOR_FROM_DATABASE=ID Tech + +usb:v0ACDp0300* + ID_MODEL_FROM_DATABASE=IDT1221U RS-232 Adapter + +usb:v0ACDp0401* + ID_MODEL_FROM_DATABASE=Spectrum III Hybrid Smartcard Reader + +usb:v0ACDp0630* + ID_MODEL_FROM_DATABASE=Spectrum III Mag-Only Insert Reader (SPT3-355 Series) USB-CDC + +usb:v0ACDp0810* + ID_MODEL_FROM_DATABASE=SecurePIN (IDPA-506100Y) PIN Pad + +usb:v0ACDp2030* + ID_MODEL_FROM_DATABASE=ValueMag Magnetic Stripe Reader + +usb:v0ACDp3710* + ID_MODEL_FROM_DATABASE=ViVOpay Kiosk III + +usb:v0ACE* + ID_VENDOR_FROM_DATABASE=ZyDAS + +usb:v0ACEp1201* + ID_MODEL_FROM_DATABASE=ZD1201 802.11b + +usb:v0ACEp1211* + ID_MODEL_FROM_DATABASE=ZD1211 802.11g + +usb:v0ACEp1215* + ID_MODEL_FROM_DATABASE=ZD1211B 802.11g + +usb:v0ACEp1221* + ID_MODEL_FROM_DATABASE=ZD1221 802.11n + +usb:v0ACEp1602* + ID_MODEL_FROM_DATABASE=ZyXEL Omni FaxModem 56K + +usb:v0ACEp1608* + ID_MODEL_FROM_DATABASE=ZyXEL Omni FaxModem 56K UNO + +usb:v0ACEp1611* + ID_MODEL_FROM_DATABASE=ZyXEL Omni FaxModem 56K Plus + +usb:v0ACEp2011* + ID_MODEL_FROM_DATABASE=Virtual media for 802.11bg + +usb:v0ACEp20FF* + ID_MODEL_FROM_DATABASE=Virtual media for 802.11bg + +usb:v0ACEpA211* + ID_MODEL_FROM_DATABASE=ZD1211 802.11b/g Wireless Adapter + +usb:v0ACEpB215* + ID_MODEL_FROM_DATABASE=802.11bg + +usb:v0ACF* + ID_VENDOR_FROM_DATABASE=Intoto, Inc. + +usb:v0AD0* + ID_VENDOR_FROM_DATABASE=Intellix Corp. + +usb:v0AD1* + ID_VENDOR_FROM_DATABASE=Remotec Technology, Ltd + +usb:v0AD2* + ID_VENDOR_FROM_DATABASE=Service & Quality Technology Co., Ltd + +usb:v0ADA* + ID_VENDOR_FROM_DATABASE=Data Encryption Systems Ltd. + +usb:v0ADAp0005* + ID_MODEL_FROM_DATABASE=DK2 + +usb:v0AE3* + ID_VENDOR_FROM_DATABASE=Allion Computer, Inc. + +usb:v0AE4* + ID_VENDOR_FROM_DATABASE=Taito Corp. + +usb:v0AE7* + ID_VENDOR_FROM_DATABASE=Neodym Systems, Inc. + +usb:v0AE8* + ID_VENDOR_FROM_DATABASE=System Support Co., Ltd + +usb:v0AE9* + ID_VENDOR_FROM_DATABASE=North Shore Circuit Design L.L.P. + +usb:v0AEA* + ID_VENDOR_FROM_DATABASE=SciEssence, LLC + +usb:v0AEB* + ID_VENDOR_FROM_DATABASE=TTP Communications, Ltd + +usb:v0AEC* + ID_VENDOR_FROM_DATABASE=Neodio Technologies Corp. + +usb:v0AECp2101* + ID_MODEL_FROM_DATABASE=SmartMedia Card Reader + +usb:v0AECp2102* + ID_MODEL_FROM_DATABASE=CompactFlash Card Reader + +usb:v0AECp2103* + ID_MODEL_FROM_DATABASE=MMC/SD Card Reader + +usb:v0AECp2104* + ID_MODEL_FROM_DATABASE=MemoryStick Card Reader + +usb:v0AECp2201* + ID_MODEL_FROM_DATABASE=SmartMedia+CompactFlash Card Reader + +usb:v0AECp2202* + ID_MODEL_FROM_DATABASE=SmartMedia+MMC/SD Card Reader + +usb:v0AECp2203* + ID_MODEL_FROM_DATABASE=SmartMedia+MemoryStick Card Reader + +usb:v0AECp2204* + ID_MODEL_FROM_DATABASE=CompactFlash+MMC/SD Card Reader + +usb:v0AECp2205* + ID_MODEL_FROM_DATABASE=CompactFlash+MemoryStick Card Reader + +usb:v0AECp2206* + ID_MODEL_FROM_DATABASE=MMC/SD+MemoryStick Card Reader + +usb:v0AECp2301* + ID_MODEL_FROM_DATABASE=SmartMedia+CompactFlash+MMC/SD Card Reader + +usb:v0AECp2302* + ID_MODEL_FROM_DATABASE=SmartMedia+CompactFlash+MemoryStick Card Reader + +usb:v0AECp2303* + ID_MODEL_FROM_DATABASE=SmartMedia+MMC/SD+MemoryStick Card Reader + +usb:v0AECp2304* + ID_MODEL_FROM_DATABASE=CompactFlash+MMC/SD+MemoryStick Card Reader + +usb:v0AECp3016* + ID_MODEL_FROM_DATABASE=MMC/SD+Memory Stick Card Reader + +usb:v0AECp3050* + ID_MODEL_FROM_DATABASE=ND3050 8-in-1 Card Reader + +usb:v0AECp3060* + ID_MODEL_FROM_DATABASE=1.1 FS Card Reader + +usb:v0AECp3101* + ID_MODEL_FROM_DATABASE=MMC/SD Card Reader + +usb:v0AECp3102* + ID_MODEL_FROM_DATABASE=MemoryStick Card Reader + +usb:v0AECp3201* + ID_MODEL_FROM_DATABASE=MMC/SD+MemoryStick Card Reader + +usb:v0AECp3216* + ID_MODEL_FROM_DATABASE=HS Card Reader + +usb:v0AECp3260* + ID_MODEL_FROM_DATABASE=7-in-1 Card Reader + +usb:v0AECp5010* + ID_MODEL_FROM_DATABASE=ND5010 Card Reader + +usb:v0AF0* + ID_VENDOR_FROM_DATABASE=Option + +usb:v0AF0p5000* + ID_MODEL_FROM_DATABASE=UMTS Card + +usb:v0AF0p6000* + ID_MODEL_FROM_DATABASE=GlobeTrotter 3G datacard + +usb:v0AF0p6300* + ID_MODEL_FROM_DATABASE=GT 3G Quad UMTS/GPRS Card + +usb:v0AF0p6600* + ID_MODEL_FROM_DATABASE=GlobeTrotter 3G+ datacard + +usb:v0AF0p6711* + ID_MODEL_FROM_DATABASE=GlobeTrotter Express 7.2 v2 + +usb:v0AF0p6971* + ID_MODEL_FROM_DATABASE=Globetrotter HSDPA Modem + +usb:v0AF0p7251* + ID_MODEL_FROM_DATABASE=Globetrotter HSUPA Modem (aka iCON HSUPA E) + +usb:v0AF0p7501* + ID_MODEL_FROM_DATABASE=Globetrotter HSUPA Modem (icon 411 aka "Vodafone K3760") + +usb:v0AF0p7601* + ID_MODEL_FROM_DATABASE=Globetrotter MO40x 3G Modem (GTM 382) + +usb:v0AF0p7701* + ID_MODEL_FROM_DATABASE=Globetrotter HSUPA Modem (aka icon 451) + +usb:v0AF0pD055* + ID_MODEL_FROM_DATABASE=Globetrotter GI0505 [iCON 505] + +usb:v0AF6* + ID_VENDOR_FROM_DATABASE=Silver I Co., Ltd + +usb:v0AF7* + ID_VENDOR_FROM_DATABASE=B2C2, Inc. + +usb:v0AF7p0101* + ID_MODEL_FROM_DATABASE=Digital TV USB Receiver (DVB-S/T/C / ATSC) + +usb:v0AF9* + ID_VENDOR_FROM_DATABASE=Hama, Inc. + +usb:v0AF9p0010* + ID_MODEL_FROM_DATABASE=USB SightCam 100 + +usb:v0AF9p0011* + ID_MODEL_FROM_DATABASE=Micro Innovations IC50C Webcam + +usb:v0AFA* + ID_VENDOR_FROM_DATABASE=DMC Co., Ltd. + +usb:v0AFAp07D2* + ID_MODEL_FROM_DATABASE=Controller Board for Projected Capacitive Touch Screen DUS3000 + +usb:v0AFC* + ID_VENDOR_FROM_DATABASE=Zaptronix Ltd + +usb:v0AFD* + ID_VENDOR_FROM_DATABASE=Tateno Dennou, Inc. + +usb:v0AFE* + ID_VENDOR_FROM_DATABASE=Cummins Engine Co. + +usb:v0AFF* + ID_VENDOR_FROM_DATABASE=Jump Zone Network Products, Inc. + +usb:v0B00* + ID_VENDOR_FROM_DATABASE=INGENICO + +usb:v0B05* + ID_VENDOR_FROM_DATABASE=ASUSTek Computer, Inc. + +usb:v0B05p0001* + ID_MODEL_FROM_DATABASE=MeMO Pad HD 7 (CD-ROM mode) + +usb:v0B05p0301* + ID_MODEL_FROM_DATABASE=MyPal A696 GPS PDA + +usb:v0B05p1101* + ID_MODEL_FROM_DATABASE=Mass Storage (UISDMC4S) + +usb:v0B05p1706* + ID_MODEL_FROM_DATABASE=WL-167G v1 802.11g Adapter [Ralink RT2571] + +usb:v0B05p1707* + ID_MODEL_FROM_DATABASE=WL-167G v1 802.11g Adapter [Ralink RT2571] + +usb:v0B05p1708* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0B05p170B* + ID_MODEL_FROM_DATABASE=Multi card reader + +usb:v0B05p170C* + ID_MODEL_FROM_DATABASE=WL-159g 802.11bg [ZyDAS ZD1211B+AL2230] + +usb:v0B05p170D* + ID_MODEL_FROM_DATABASE=802.11b/g Wireless Network Adapter + +usb:v0B05p1712* + ID_MODEL_FROM_DATABASE=BT-183 Bluetooth 2.0+EDR adapter + +usb:v0B05p1715* + ID_MODEL_FROM_DATABASE=2045 Bluetooth 2.0 Device with trace filter + +usb:v0B05p1716* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0B05p1717* + ID_MODEL_FROM_DATABASE=WL169gE 802.11g Adapter [Broadcom 4320 USB] + +usb:v0B05p171B* + ID_MODEL_FROM_DATABASE=A9T wireless 802.11bg + +usb:v0B05p171C* + ID_MODEL_FROM_DATABASE=802.11b/g Wireless Network Adapter + +usb:v0B05p171F* + ID_MODEL_FROM_DATABASE=My Cinema U3000 Mini [DiBcom DiB7700P] + +usb:v0B05p1723* + ID_MODEL_FROM_DATABASE=WL-167G v2 802.11g Adapter [Ralink RT2571W] + +usb:v0B05p1724* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v0B05p1726* + ID_MODEL_FROM_DATABASE=Laptop OLED Display + +usb:v0B05p172A* + ID_MODEL_FROM_DATABASE=802.11n Network Adapter + +usb:v0B05p172B* + ID_MODEL_FROM_DATABASE=802.11n Network Adapter + +usb:v0B05p1731* + ID_MODEL_FROM_DATABASE=802.11n Network Adapter + +usb:v0B05p1732* + ID_MODEL_FROM_DATABASE=802.11n Network Adapter + +usb:v0B05p1734* + ID_MODEL_FROM_DATABASE=AF-200 + +usb:v0B05p173C* + ID_MODEL_FROM_DATABASE=BT-183 Bluetooth 2.0 + +usb:v0B05p173F* + ID_MODEL_FROM_DATABASE=My Cinema U3100 Mini + +usb:v0B05p1742* + ID_MODEL_FROM_DATABASE=802.11n Network Adapter + +usb:v0B05p1743* + ID_MODEL_FROM_DATABASE=Xonar U1 Audio Station + +usb:v0B05p1751* + ID_MODEL_FROM_DATABASE=BT-253 Bluetooth Adapter + +usb:v0B05p175B* + ID_MODEL_FROM_DATABASE=Laptop OLED Display + +usb:v0B05p1760* + ID_MODEL_FROM_DATABASE=802.11n Network Adapter + +usb:v0B05p1761* + ID_MODEL_FROM_DATABASE=USB-N11 802.11n Network Adapter [Ralink RT2870] + +usb:v0B05p1774* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) + +usb:v0B05p1776* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem + +usb:v0B05p1779* + ID_MODEL_FROM_DATABASE=My Cinema U3100 Mini Plus [AF9035A] + +usb:v0B05p1784* + ID_MODEL_FROM_DATABASE=USB-N13 802.11n Network Adapter (rev. A1) [Ralink RT3072] + +usb:v0B05p1786* + ID_MODEL_FROM_DATABASE=USB-N10 802.11n Network Adapter [Realtek RTL8188SU] + +usb:v0B05p1788* + ID_MODEL_FROM_DATABASE=BT-270 Bluetooth Adapter + +usb:v0B05p1791* + ID_MODEL_FROM_DATABASE=WL-167G v3 802.11n Adapter [Realtek RTL8188SU] + +usb:v0B05p179D* + ID_MODEL_FROM_DATABASE=USB-N53 802.11abgn Network Adapter [Ralink RT3572] + +usb:v0B05p179E* + ID_MODEL_FROM_DATABASE=Eee Note EA800 (network mode) + +usb:v0B05p179F* + ID_MODEL_FROM_DATABASE=Eee Note EA800 (tablet mode) + +usb:v0B05p17A0* + ID_MODEL_FROM_DATABASE=Xonar U3 sound card + +usb:v0B05p17A1* + ID_MODEL_FROM_DATABASE=Eee Note EA800 (mass storage mode) + +usb:v0B05p17AB* + ID_MODEL_FROM_DATABASE=USB-N13 802.11n Network Adapter (rev. B1) [Realtek RTL8192CU] + +usb:v0B05p17BA* + ID_MODEL_FROM_DATABASE=N10 Nano 802.11n Network Adapter [Realtek RTL8192CU] + +usb:v0B05p17C7* + ID_MODEL_FROM_DATABASE=WL-330NUL + +usb:v0B05p17C9* + ID_MODEL_FROM_DATABASE=USB-AC53 802.11a/b/g/n/ac Wireless Adapter [Broadcom BCM43526] + +usb:v0B05p17CB* + ID_MODEL_FROM_DATABASE=Broadcom BCM20702A0 Bluetooth + +usb:v0B05p17D1* + ID_MODEL_FROM_DATABASE=AC51 802.11a/b/g/n/ac Wireless Adapter [Mediatek MT7610U] + +usb:v0B05p17D2* + ID_MODEL_FROM_DATABASE=USB-AC56 802.11a/b/g/n/ac Wireless Adapter [Realtek RTL8812AU] + +usb:v0B05p17D3* + ID_MODEL_FROM_DATABASE=USB-N10 v2 802.11b/g/n Wireless Adapter [MediaTek MT7601U] + +usb:v0B05p17DB* + ID_MODEL_FROM_DATABASE=USB-AC50 802.11a/b/g/n/ac (1x1) Wireless Adapter [MediaTek MT7610U] + +usb:v0B05p17E8* + ID_MODEL_FROM_DATABASE=USB-N14 802.11b/g/n (2x2) Wireless Adapter [Ralink RT5372] + +usb:v0B05p17EB* + ID_MODEL_FROM_DATABASE=USB-AC55 802.11a/b/g/n/ac Wireless Adapter [MediaTek MT7612U] + +usb:v0B05p180A* + ID_MODEL_FROM_DATABASE=Broadcom BCM20702 Single-Chip Bluetooth 4.0 + LE + +usb:v0B05p1817* + ID_MODEL_FROM_DATABASE=USB-AC68 802.11a/b/g/n/ac (4x4) Wireless Adapter [Realtek RTL8814AU] + +usb:v0B05p1825* + ID_MODEL_FROM_DATABASE=Qualcomm Bluetooth 4.1 + +usb:v0B05p4C80* + ID_MODEL_FROM_DATABASE=Transformer Pad TF300TG + +usb:v0B05p4C90* + ID_MODEL_FROM_DATABASE=Transformer Pad Infinity TF700 + +usb:v0B05p4C91* + ID_MODEL_FROM_DATABASE=Transformer Pad Infinity TF700 (Debug mode) + +usb:v0B05p4CA0* + ID_MODEL_FROM_DATABASE=Transformer Pad TF701T + +usb:v0B05p4CA1* + ID_MODEL_FROM_DATABASE=Transformer Pad TF701T (Debug mode) + +usb:v0B05p4D00* + ID_MODEL_FROM_DATABASE=Transformer Prime TF201 + +usb:v0B05p4D01* + ID_MODEL_FROM_DATABASE=Transformer Prime TF201 (debug mode) + +usb:v0B05p4DAF* + ID_MODEL_FROM_DATABASE=Transformer Pad Infinity TF700 (Fastboot) + +usb:v0B05p5410* + ID_MODEL_FROM_DATABASE=MeMO Pad HD 7 (MTP mode) + +usb:v0B05p5412* + ID_MODEL_FROM_DATABASE=MeMO Pad HD 7 (PTP mode) + +usb:v0B05p550F* + ID_MODEL_FROM_DATABASE=Fonepad 7 + +usb:v0B05p6101* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v0B05p620A* + ID_MODEL_FROM_DATABASE=Remote NDIS Device + +usb:v0B05p7772* + ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (MTP mode) + +usb:v0B05p7773* + ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (Debug, MTP mode) + +usb:v0B05p7774* + ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (RNDIS mode) + +usb:v0B05p7775* + ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (Debug, RNDIS mode) + +usb:v0B05p7776* + ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (PTP mode) + +usb:v0B05p7777* + ID_MODEL_FROM_DATABASE=Zenfone GO (ZB500KL) (Debug, PTP mode) + +usb:v0B05pB700* + ID_MODEL_FROM_DATABASE=Broadcom Bluetooth 2.1 + +usb:v0B0B* + ID_VENDOR_FROM_DATABASE=Datamax-O'Neil + +usb:v0B0Bp106E* + ID_MODEL_FROM_DATABASE=Datamax E-4304 + +usb:v0B0C* + ID_VENDOR_FROM_DATABASE=Todos AB + +usb:v0B0Cp0009* + ID_MODEL_FROM_DATABASE=Todos Argos Mini II Smart Card Reader + +usb:v0B0Cp001E* + ID_MODEL_FROM_DATABASE=e.dentifier2 (ABN AMRO electronic banking card reader NL) + +usb:v0B0Cp002E* + ID_MODEL_FROM_DATABASE=C200 smartcard controller (Nordea card reader) + +usb:v0B0Cp003F* + ID_MODEL_FROM_DATABASE=Todos C400 smartcard controller (Handelsbanken card reader) + +usb:v0B0Cp0050* + ID_MODEL_FROM_DATABASE=Argos Mini II Smart Card Reader (CCID) + +usb:v0B0D* + ID_VENDOR_FROM_DATABASE=ProjectLab + +usb:v0B0Dp0000* + ID_MODEL_FROM_DATABASE=CenturyCD + +usb:v0B0E* + ID_VENDOR_FROM_DATABASE=GN Netcom + +usb:v0B0Ep0348* + ID_MODEL_FROM_DATABASE=Jabra UC VOICE 550a MS + +usb:v0B0Ep034C* + ID_MODEL_FROM_DATABASE=Jabra UC Voice 750 MS + +usb:v0B0Ep0410* + ID_MODEL_FROM_DATABASE=Jabra SPEAK 410 + +usb:v0B0Ep0420* + ID_MODEL_FROM_DATABASE=Jabra SPEAK 510 + +usb:v0B0Ep094D* + ID_MODEL_FROM_DATABASE=GN Netcom / Jabra REVO Wireless + +usb:v0B0Ep1017* + ID_MODEL_FROM_DATABASE=Jabra PRO 930 + +usb:v0B0Ep1022* + ID_MODEL_FROM_DATABASE=Jabra PRO 9450, Type 9400BS (DECT Headset) + +usb:v0B0Ep1041* + ID_MODEL_FROM_DATABASE=Jabra PRO 9460 + +usb:v0B0Ep1900* + ID_MODEL_FROM_DATABASE=Jabra Biz 1900 + +usb:v0B0Ep2007* + ID_MODEL_FROM_DATABASE=GN 2000 Stereo Corded Headset + +usb:v0B0Ep620C* + ID_MODEL_FROM_DATABASE=Jabra BT620s + +usb:v0B0Ep9330* + ID_MODEL_FROM_DATABASE=Jabra GN9330 Headset + +usb:v0B0F* + ID_VENDOR_FROM_DATABASE=AVID Technology + +usb:v0B10* + ID_VENDOR_FROM_DATABASE=Pcally + +usb:v0B11* + ID_VENDOR_FROM_DATABASE=I Tech Solutions Co., Ltd + +usb:v0B1E* + ID_VENDOR_FROM_DATABASE=Electronic Warfare Assoc., Inc. (EWA) + +usb:v0B1Ep8007* + ID_MODEL_FROM_DATABASE=Blackhawk USB560-BP JTAG Emulator + +usb:v0B1F* + ID_VENDOR_FROM_DATABASE=Insyde Software Corp. + +usb:v0B20* + ID_VENDOR_FROM_DATABASE=TransDimension, Inc. + +usb:v0B21* + ID_VENDOR_FROM_DATABASE=Yokogawa Electric Corp. + +usb:v0B22* + ID_VENDOR_FROM_DATABASE=Japan System Development Co., Ltd + +usb:v0B23* + ID_VENDOR_FROM_DATABASE=Pan-Asia Electronics Co., Ltd + +usb:v0B24* + ID_VENDOR_FROM_DATABASE=Link Evolution Corp. + +usb:v0B27* + ID_VENDOR_FROM_DATABASE=Ritek Corp. + +usb:v0B28* + ID_VENDOR_FROM_DATABASE=Kenwood Corp. + +usb:v0B2C* + ID_VENDOR_FROM_DATABASE=Village Center, Inc. + +usb:v0B30* + ID_VENDOR_FROM_DATABASE=PNY Technologies, Inc. + +usb:v0B30p0006* + ID_MODEL_FROM_DATABASE=SM Media-Shuttle Card Reader + +usb:v0B33* + ID_VENDOR_FROM_DATABASE=Contour Design, Inc. + +usb:v0B33p0020* + ID_MODEL_FROM_DATABASE=ShuttleXpress + +usb:v0B33p0030* + ID_MODEL_FROM_DATABASE=ShuttlePro v2 + +usb:v0B33p0401* + ID_MODEL_FROM_DATABASE=RollerMouse Free 2 + +usb:v0B33p0700* + ID_MODEL_FROM_DATABASE=RollerMouse Pro + +usb:v0B37* + ID_VENDOR_FROM_DATABASE=Hitachi ULSI Systems Co., Ltd + +usb:v0B38* + ID_VENDOR_FROM_DATABASE=Gear Head + +usb:v0B38p0003* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0B38p0010* + ID_MODEL_FROM_DATABASE=107-Key Keyboard + +usb:v0B39* + ID_VENDOR_FROM_DATABASE=Omnidirectional Control Technology, Inc. + +usb:v0B39p0001* + ID_MODEL_FROM_DATABASE=Composite USB PS2 Converter + +usb:v0B39p0109* + ID_MODEL_FROM_DATABASE=USB TO Ethernet + +usb:v0B39p0421* + ID_MODEL_FROM_DATABASE=Serial + +usb:v0B39p0801* + ID_MODEL_FROM_DATABASE=USB-Parallel Bridge + +usb:v0B39p0901* + ID_MODEL_FROM_DATABASE=OCT To Fast Ethernet Converter + +usb:v0B39p0C03* + ID_MODEL_FROM_DATABASE=LAN DOCK Serial Converter + +usb:v0B3A* + ID_VENDOR_FROM_DATABASE=IPaxess + +usb:v0B3B* + ID_VENDOR_FROM_DATABASE=Tekram Technology Co., Ltd + +usb:v0B3Bp0163* + ID_MODEL_FROM_DATABASE=TL-WN320G 1.0 WLAN Adapter + +usb:v0B3Bp1601* + ID_MODEL_FROM_DATABASE=Allnet 0193 802.11b Adapter + +usb:v0B3Bp1602* + ID_MODEL_FROM_DATABASE=ZyXEL ZyAIR B200 802.11b Adapter + +usb:v0B3Bp1612* + ID_MODEL_FROM_DATABASE=AIR.Mate 2@net 802.11b Adapter + +usb:v0B3Bp1613* + ID_MODEL_FROM_DATABASE=802.11b Wireless LAN Adapter + +usb:v0B3Bp1620* + ID_MODEL_FROM_DATABASE=Allnet Wireless Network Adapter [Envara WiND512] + +usb:v0B3Bp1630* + ID_MODEL_FROM_DATABASE=QuickWLAN 802.11bg + +usb:v0B3Bp5630* + ID_MODEL_FROM_DATABASE=802.11bg + +usb:v0B3Bp6630* + ID_MODEL_FROM_DATABASE=ZD1211 + +usb:v0B3C* + ID_VENDOR_FROM_DATABASE=Olivetti Techcenter + +usb:v0B3CpA010* + ID_MODEL_FROM_DATABASE=Simple_Way Printer/Scanner/Copier + +usb:v0B3CpC000* + ID_MODEL_FROM_DATABASE=Olicard 100 + +usb:v0B3CpC700* + ID_MODEL_FROM_DATABASE=Olicard 100 (Mass Storage mode) + +usb:v0B3E* + ID_VENDOR_FROM_DATABASE=Kikusui Electronics Corp. + +usb:v0B41* + ID_VENDOR_FROM_DATABASE=Hal Corp. + +usb:v0B41p0011* + ID_MODEL_FROM_DATABASE=Crossam2+USB IR commander + +usb:v0B43* + ID_VENDOR_FROM_DATABASE=Play.com, Inc. + +usb:v0B43p0003* + ID_MODEL_FROM_DATABASE=PS2 Controller Converter + +usb:v0B43p0005* + ID_MODEL_FROM_DATABASE=GameCube Adaptor + +usb:v0B47* + ID_VENDOR_FROM_DATABASE=Sportbug.com, Inc. + +usb:v0B48* + ID_VENDOR_FROM_DATABASE=TechnoTrend AG + +usb:v0B48p1003* + ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge USB-Nova + +usb:v0B48p1004* + ID_MODEL_FROM_DATABASE=TT-PCline + +usb:v0B48p1005* + ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge USB-Nova + +usb:v0B48p1006* + ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge DEC3000-s + +usb:v0B48p1007* + ID_MODEL_FROM_DATABASE=TT-micro plus Device + +usb:v0B48p1008* + ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge DEC2000-t + +usb:v0B48p1009* + ID_MODEL_FROM_DATABASE=Technotrend/Hauppauge DEC2540-t + +usb:v0B48p3001* + ID_MODEL_FROM_DATABASE=DVB-S receiver + +usb:v0B48p3002* + ID_MODEL_FROM_DATABASE=DVB-C receiver + +usb:v0B48p3003* + ID_MODEL_FROM_DATABASE=DVB-T receiver + +usb:v0B48p3004* + ID_MODEL_FROM_DATABASE=TT TV-Stick + +usb:v0B48p3005* + ID_MODEL_FROM_DATABASE=TT TV-Stick (8kB EEPROM) + +usb:v0B48p3006* + ID_MODEL_FROM_DATABASE=TT-connect S-2400 DVB-S receiver + +usb:v0B48p3007* + ID_MODEL_FROM_DATABASE=TT-connect S2-3600 + +usb:v0B48p3008* + ID_MODEL_FROM_DATABASE=TT-connect + +usb:v0B48p3009* + ID_MODEL_FROM_DATABASE=TT-connect S-2400 DVB-S receiver (8kB EEPROM) + +usb:v0B48p300A* + ID_MODEL_FROM_DATABASE=TT-connect S2-3650 CI + +usb:v0B48p300B* + ID_MODEL_FROM_DATABASE=TT-connect C-3650 CI + +usb:v0B48p300C* + ID_MODEL_FROM_DATABASE=TT-connect T-3650 CI + +usb:v0B48p300D* + ID_MODEL_FROM_DATABASE=TT-connect CT-3650 CI + +usb:v0B48p300E* + ID_MODEL_FROM_DATABASE=TT-connect C-2400 + +usb:v0B48p3011* + ID_MODEL_FROM_DATABASE=TT-connect S2-4600 + +usb:v0B48p3012* + ID_MODEL_FROM_DATABASE=TT-connect CT2-4650 CI + +usb:v0B48p3014* + ID_MODEL_FROM_DATABASE=TT-TVStick CT2-4400 + +usb:v0B48p3015* + ID_MODEL_FROM_DATABASE=TT-connect CT2-4650 CI + +usb:v0B48p3017* + ID_MODEL_FROM_DATABASE=TT-connect S2-4650 CI + +usb:v0B49* + ID_VENDOR_FROM_DATABASE=ASCII Corp. + +usb:v0B49p064F* + ID_MODEL_FROM_DATABASE=Trance Vibrator + +usb:v0B4B* + ID_VENDOR_FROM_DATABASE=Pine Corp. Ltd. + +usb:v0B4Bp0100* + ID_MODEL_FROM_DATABASE=D'music MP3 Player + +usb:v0B4D* + ID_VENDOR_FROM_DATABASE=Graphtec America, Inc. + +usb:v0B4Dp110A* + ID_MODEL_FROM_DATABASE=Graphtec CC200-20 + +usb:v0B4E* + ID_VENDOR_FROM_DATABASE=Musical Electronics, Ltd + +usb:v0B4Ep6500* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0B4Ep8028* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0B4Ep8920* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0B50* + ID_VENDOR_FROM_DATABASE=Dumpries Co., Ltd + +usb:v0B51* + ID_VENDOR_FROM_DATABASE=Comfort Keyboard Co. + +usb:v0B51p0020* + ID_MODEL_FROM_DATABASE=Comfort Keyboard + +usb:v0B52* + ID_VENDOR_FROM_DATABASE=Colorado MicroDisplay, Inc. + +usb:v0B54* + ID_VENDOR_FROM_DATABASE=Sinbon Electronics Co., Ltd + +usb:v0B56* + ID_VENDOR_FROM_DATABASE=TYI Systems, Ltd + +usb:v0B57* + ID_VENDOR_FROM_DATABASE=Beijing HanwangTechnology Co., Ltd + +usb:v0B59* + ID_VENDOR_FROM_DATABASE=Lake Communications, Ltd + +usb:v0B5A* + ID_VENDOR_FROM_DATABASE=Corel Corp. + +usb:v0B5F* + ID_VENDOR_FROM_DATABASE=Green Electronics Co., Ltd + +usb:v0B60* + ID_VENDOR_FROM_DATABASE=Nsine, Ltd + +usb:v0B61* + ID_VENDOR_FROM_DATABASE=NEC Viewtechnology, Ltd + +usb:v0B62* + ID_VENDOR_FROM_DATABASE=Orange Micro, Inc. + +usb:v0B62p000B* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0B62p0059* + ID_MODEL_FROM_DATABASE=iBOT2 Webcam + +usb:v0B63* + ID_VENDOR_FROM_DATABASE=ADLink Technology, Inc. + +usb:v0B64* + ID_VENDOR_FROM_DATABASE=Wonderful Wire Cable Co., Ltd + +usb:v0B65* + ID_VENDOR_FROM_DATABASE=Expert Magnetics Corp. + +usb:v0B66* + ID_VENDOR_FROM_DATABASE=Cybiko Inc. + +usb:v0B66p0041* + ID_MODEL_FROM_DATABASE=Xtreme + +usb:v0B67* + ID_VENDOR_FROM_DATABASE=Fairbanks Scales + +usb:v0B67p555E* + ID_MODEL_FROM_DATABASE=SCB-R9000 + +usb:v0B69* + ID_VENDOR_FROM_DATABASE=CacheVision + +usb:v0B6A* + ID_VENDOR_FROM_DATABASE=Maxim Integrated Products + +usb:v0B6ApA132* + ID_MODEL_FROM_DATABASE=WUP-005 [Nintendo Wii U Pro Controller] + +usb:v0B6F* + ID_VENDOR_FROM_DATABASE=Nagano Japan Radio Co., Ltd + +usb:v0B70* + ID_VENDOR_FROM_DATABASE=PortalPlayer, Inc. + +usb:v0B70p00BA* + ID_MODEL_FROM_DATABASE=iRiver H10 20GB + +usb:v0B71* + ID_VENDOR_FROM_DATABASE=SHIN-EI Sangyo Co., Ltd + +usb:v0B72* + ID_VENDOR_FROM_DATABASE=Embedded Wireless Technology Co., Ltd + +usb:v0B73* + ID_VENDOR_FROM_DATABASE=Computone Corp. + +usb:v0B75* + ID_VENDOR_FROM_DATABASE=Roland DG Corp. + +usb:v0B79* + ID_VENDOR_FROM_DATABASE=Sunrise Telecom, Inc. + +usb:v0B7A* + ID_VENDOR_FROM_DATABASE=Zeevo, Inc. + +usb:v0B7Ap07D0* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v0B7B* + ID_VENDOR_FROM_DATABASE=Taiko Denki Co., Ltd + +usb:v0B7C* + ID_VENDOR_FROM_DATABASE=ITRAN Communications, Ltd + +usb:v0B7D* + ID_VENDOR_FROM_DATABASE=Astrodesign, Inc. + +usb:v0B81* + ID_VENDOR_FROM_DATABASE=id3 Technologies + +usb:v0B81p0001* + ID_MODEL_FROM_DATABASE=Biothentic II smartcard reader with fingerprint sensor + +usb:v0B81p0002* + ID_MODEL_FROM_DATABASE=DFU-Enabled Devices (DFU) + +usb:v0B81p0012* + ID_MODEL_FROM_DATABASE=BioPAD biometric module (DFU + CDC) + +usb:v0B81p0102* + ID_MODEL_FROM_DATABASE=Certis V1 fingerprint reader + +usb:v0B81p0103* + ID_MODEL_FROM_DATABASE=Certis V2 fingerprint reader + +usb:v0B81p0200* + ID_MODEL_FROM_DATABASE=CL1356T / CL1356T5 / CL1356A smartcard readers (CCID) + +usb:v0B81p0201* + ID_MODEL_FROM_DATABASE=CL1356T / CL1356T5 / CL1356A smartcard readers (DFU + CCID) + +usb:v0B81p0220* + ID_MODEL_FROM_DATABASE=CL1356A FFPJP smartcard reader (CCID + HID) + +usb:v0B81p0221* + ID_MODEL_FROM_DATABASE=CL1356A smartcard reader (DFU + CCID + HID) + +usb:v0B84* + ID_VENDOR_FROM_DATABASE=Rextron Technology, Inc. + +usb:v0B85* + ID_VENDOR_FROM_DATABASE=Elkat Electronics, Sdn., Bhd. + +usb:v0B86* + ID_VENDOR_FROM_DATABASE=Exputer Systems, Inc. + +usb:v0B86p5100* + ID_MODEL_FROM_DATABASE=XMC5100 Zippy Drive + +usb:v0B86p5110* + ID_MODEL_FROM_DATABASE=XMC5110 Flash Drive + +usb:v0B86p5200* + ID_MODEL_FROM_DATABASE=XMC5200 Zippy Drive + +usb:v0B86p5201* + ID_MODEL_FROM_DATABASE=XMC5200 Zippy Drive + +usb:v0B86p5202* + ID_MODEL_FROM_DATABASE=XMC5200 Zippy Drive + +usb:v0B86p5280* + ID_MODEL_FROM_DATABASE=XMC5280 Storage Drive + +usb:v0B86pFFF0* + ID_MODEL_FROM_DATABASE=ISP5200 Debugger + +usb:v0B87* + ID_VENDOR_FROM_DATABASE=Plus-One I & T, Inc. + +usb:v0B88* + ID_VENDOR_FROM_DATABASE=Sigma Koki Co., Ltd, Technology Center + +usb:v0B89* + ID_VENDOR_FROM_DATABASE=Advanced Digital Broadcast, Ltd + +usb:v0B8C* + ID_VENDOR_FROM_DATABASE=SMART Technologies Inc. + +usb:v0B8Cp0001* + ID_MODEL_FROM_DATABASE=Interactive Whiteboard Controller (SB6) (HID) + +usb:v0B8Cp00C3* + ID_MODEL_FROM_DATABASE=Sympodium ID350 + +usb:v0B95* + ID_VENDOR_FROM_DATABASE=ASIX Electronics Corp. + +usb:v0B95p1720* + ID_MODEL_FROM_DATABASE=10/100 Ethernet + +usb:v0B95p1780* + ID_MODEL_FROM_DATABASE=AX88178 + +usb:v0B95p1790* + ID_MODEL_FROM_DATABASE=AX88179 Gigabit Ethernet + +usb:v0B95p7720* + ID_MODEL_FROM_DATABASE=AX88772 + +usb:v0B95p772A* + ID_MODEL_FROM_DATABASE=AX88772A Fast Ethernet + +usb:v0B95p772B* + ID_MODEL_FROM_DATABASE=AX88772B + +usb:v0B95p7E2B* + ID_MODEL_FROM_DATABASE=AX88772B Fast Ethernet Controller + +usb:v0B96* + ID_VENDOR_FROM_DATABASE=Sewon Telecom + +usb:v0B97* + ID_VENDOR_FROM_DATABASE=O2 Micro, Inc. + +usb:v0B97p7732* + ID_MODEL_FROM_DATABASE=Smart Card Reader + +usb:v0B97p7761* + ID_MODEL_FROM_DATABASE=Oz776 1.1 Hub + +usb:v0B97p7762* + ID_MODEL_FROM_DATABASE=Oz776 SmartCard Reader + +usb:v0B97p7772* + ID_MODEL_FROM_DATABASE=OZ776 CCID Smartcard Reader + +usb:v0B98* + ID_VENDOR_FROM_DATABASE=Playmates Toys, Inc. + +usb:v0B99* + ID_VENDOR_FROM_DATABASE=Audio International, Inc. + +usb:v0B9B* + ID_VENDOR_FROM_DATABASE=Dipl.-Ing. Stefan Kunde + +usb:v0B9Bp4012* + ID_MODEL_FROM_DATABASE=Reflex RC-controller Interface + +usb:v0B9D* + ID_VENDOR_FROM_DATABASE=Softprotec Co. + +usb:v0B9F* + ID_VENDOR_FROM_DATABASE=Chippo Technologies + +usb:v0BAF* + ID_VENDOR_FROM_DATABASE=U.S. Robotics + +usb:v0BAFp00E5* + ID_MODEL_FROM_DATABASE=USR6000 + +usb:v0BAFp00EB* + ID_MODEL_FROM_DATABASE=USR1120 802.11b Adapter + +usb:v0BAFp00EC* + ID_MODEL_FROM_DATABASE=56K Faxmodem + +usb:v0BAFp00F1* + ID_MODEL_FROM_DATABASE=SureConnect ADSL ATM Adapter + +usb:v0BAFp00F2* + ID_MODEL_FROM_DATABASE=SureConnect ADSL Loader + +usb:v0BAFp00F5* + ID_MODEL_FROM_DATABASE=SureConnect ADSL ATM Adapter + +usb:v0BAFp00F6* + ID_MODEL_FROM_DATABASE=SureConnect ADSL Loader + +usb:v0BAFp00F7* + ID_MODEL_FROM_DATABASE=SureConnect ADSL ATM Adapter + +usb:v0BAFp00F8* + ID_MODEL_FROM_DATABASE=SureConnect ADSL Loader + +usb:v0BAFp00F9* + ID_MODEL_FROM_DATABASE=SureConnect ADSL ATM Adapter + +usb:v0BAFp00FA* + ID_MODEL_FROM_DATABASE=SureConnect ADSL Loader + +usb:v0BAFp00FB* + ID_MODEL_FROM_DATABASE=SureConnect ADSL Ethernet/USB Router + +usb:v0BAFp0111* + ID_MODEL_FROM_DATABASE=USR5420 802.11g Adapter [Broadcom 4320 USB] + +usb:v0BAFp0118* + ID_MODEL_FROM_DATABASE=U5 802.11g Adapter + +usb:v0BAFp011B* + ID_MODEL_FROM_DATABASE=Wireless MAXg Adapter [Broadcom 4320] + +usb:v0BAFp0121* + ID_MODEL_FROM_DATABASE=USR5423 802.11bg Wireless Adapter [ZyDAS ZD1211B] + +usb:v0BAFp0303* + ID_MODEL_FROM_DATABASE=USR5637 56K Faxmodem + +usb:v0BAFp6112* + ID_MODEL_FROM_DATABASE=FaxModem Model 5633 + +usb:v0BB0* + ID_VENDOR_FROM_DATABASE=Concord Camera Corp. + +usb:v0BB0p0100* + ID_MODEL_FROM_DATABASE=Sound Vision Stream + +usb:v0BB0p5007* + ID_MODEL_FROM_DATABASE=3340z/Rollei DC3100 + +usb:v0BB1* + ID_VENDOR_FROM_DATABASE=Infinilink Corp. + +usb:v0BB2* + ID_VENDOR_FROM_DATABASE=Ambit Microsystems Corp. + +usb:v0BB2p0302* + ID_MODEL_FROM_DATABASE=U10H010 802.11b Wireless Adapter [Intersil PRISM 3] + +usb:v0BB2p6098* + ID_MODEL_FROM_DATABASE=USB Cable Modem + +usb:v0BB3* + ID_VENDOR_FROM_DATABASE=Ofuji Technology + +usb:v0BB4* + ID_VENDOR_FROM_DATABASE=HTC (High Tech Computer Corp.) + +usb:v0BB4p0001* + ID_MODEL_FROM_DATABASE=Android Phone via mass storage [Wiko Cink Peax 2] + +usb:v0BB4p00CE* + ID_MODEL_FROM_DATABASE=mmO2 XDA GSM/GPRS Pocket PC + +usb:v0BB4p00CF* + ID_MODEL_FROM_DATABASE=SPV C500 Smart Phone + +usb:v0BB4p0A01* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A02* + ID_MODEL_FROM_DATABASE=Himalaya GSM/GPRS Pocket PC + +usb:v0BB4p0A03* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A04* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A05* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A06* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A07* + ID_MODEL_FROM_DATABASE=Magician PocketPC SmartPhone / O2 XDA + +usb:v0BB4p0A08* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A09* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A0A* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A0B* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A0C* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A0D* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A0E* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A0F* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A10* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A11* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A12* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A13* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A14* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A15* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A16* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A17* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A18* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A19* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A1A* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A1B* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A1C* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A1D* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A1E* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A1F* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A20* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A21* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A22* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A23* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A24* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A25* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A26* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A27* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A28* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A29* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A2A* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A2B* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A2C* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A2D* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A2E* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A2F* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A30* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A31* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A32* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A33* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A34* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A35* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A36* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A37* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A38* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A39* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A3A* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A3B* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A3C* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A3D* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A3E* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A3F* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A40* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A41* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A42* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A43* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A44* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A45* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A46* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A47* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A48* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A49* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A4A* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A4B* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A4C* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A4D* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A4E* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A4F* + ID_MODEL_FROM_DATABASE=PocketPC Sync + +usb:v0BB4p0A50* + ID_MODEL_FROM_DATABASE=SmartPhone (MTP) + +usb:v0BB4p0A51* + ID_MODEL_FROM_DATABASE=SPV C400 / T-Mobile SDA GSM/GPRS Pocket PC + +usb:v0BB4p0A52* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A53* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A54* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A55* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A56* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A57* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A58* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A59* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A5A* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A5B* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A5C* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A5D* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A5E* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A5F* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A60* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A61* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A62* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A63* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A64* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A65* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A66* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A67* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A68* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A69* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A6A* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A6B* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A6C* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A6D* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A6E* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A6F* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A70* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A71* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A72* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A73* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A74* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A75* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A76* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A77* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A78* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A79* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A7A* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A7B* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A7C* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A7D* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A7E* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A7F* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A80* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A81* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A82* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A83* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A84* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A85* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A86* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A87* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A88* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A89* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A8A* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A8B* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A8C* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A8D* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A8E* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A8F* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A90* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A91* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A92* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A93* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A94* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A95* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A96* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A97* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A98* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A99* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A9A* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A9B* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A9C* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A9D* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A9E* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0A9F* + ID_MODEL_FROM_DATABASE=SmartPhone Sync + +usb:v0BB4p0B03* + ID_MODEL_FROM_DATABASE=Ozone Mobile Broadband + +usb:v0BB4p0B04* + ID_MODEL_FROM_DATABASE=Hermes / TyTN / T-Mobile MDA Vario II / O2 Xda Trion + +usb:v0BB4p0B05* + ID_MODEL_FROM_DATABASE=P3600 + +usb:v0BB4p0B06* + ID_MODEL_FROM_DATABASE=Athena / Advantage x7500 / Dopod U1000 / T-Mobile AMEO + +usb:v0BB4p0B0C* + ID_MODEL_FROM_DATABASE=Elf / Touch / P3450 / T-Mobile MDA Touch / O2 Xda Nova / Dopod S1 + +usb:v0BB4p0B1F* + ID_MODEL_FROM_DATABASE=Sony Ericsson XPERIA X1 + +usb:v0BB4p0B2F* + ID_MODEL_FROM_DATABASE=Rhodium + +usb:v0BB4p0B51* + ID_MODEL_FROM_DATABASE=Qtek 8310 mobile phone [Tornado Noble] + +usb:v0BB4p0BCE* + ID_MODEL_FROM_DATABASE=Vario MDA + +usb:v0BB4p0C01* + ID_MODEL_FROM_DATABASE=Dream / ADP1 / G1 / Magic / Tattoo + +usb:v0BB4p0C02* + ID_MODEL_FROM_DATABASE=Dream / ADP1 / G1 / Magic / Tattoo (Debug) + +usb:v0BB4p0C03* + ID_MODEL_FROM_DATABASE=Android Phone [Fairphone First Edition (FP1)] + +usb:v0BB4p0C13* + ID_MODEL_FROM_DATABASE=Diamond + +usb:v0BB4p0C1F* + ID_MODEL_FROM_DATABASE=Sony Ericsson XPERIA X1 + +usb:v0BB4p0C5F* + ID_MODEL_FROM_DATABASE=Snap + +usb:v0BB4p0C86* + ID_MODEL_FROM_DATABASE=Sensation + +usb:v0BB4p0C87* + ID_MODEL_FROM_DATABASE=Desire (debug) + +usb:v0BB4p0C8D* + ID_MODEL_FROM_DATABASE=EVO 4G (debug) + +usb:v0BB4p0C91* + ID_MODEL_FROM_DATABASE=Vision + +usb:v0BB4p0C94* + ID_MODEL_FROM_DATABASE=Vision + +usb:v0BB4p0C97* + ID_MODEL_FROM_DATABASE=Legend + +usb:v0BB4p0C99* + ID_MODEL_FROM_DATABASE=Desire (debug) + +usb:v0BB4p0C9E* + ID_MODEL_FROM_DATABASE=Incredible + +usb:v0BB4p0CA2* + ID_MODEL_FROM_DATABASE=Desire HD (debug mode) + +usb:v0BB4p0CA5* + ID_MODEL_FROM_DATABASE=Android Phone [Evo Shift 4G] + +usb:v0BB4p0CAE* + ID_MODEL_FROM_DATABASE=T-Mobile MyTouch 4G Slide [Doubleshot] + +usb:v0BB4p0DE5* + ID_MODEL_FROM_DATABASE=One (M7) + +usb:v0BB4p0DEA* + ID_MODEL_FROM_DATABASE=M7_UL [HTC One] + +usb:v0BB4p0F25* + ID_MODEL_FROM_DATABASE=One M8 + +usb:v0BB4p0F63* + ID_MODEL_FROM_DATABASE=Desire 610 Via MTP + +usb:v0BB4p0F64* + ID_MODEL_FROM_DATABASE=Desire 601 + +usb:v0BB4p0FB4* + ID_MODEL_FROM_DATABASE=Remote NDIS based Device + +usb:v0BB4p0FF8* + ID_MODEL_FROM_DATABASE=Desire HD (Tethering Mode) + +usb:v0BB4p0FF9* + ID_MODEL_FROM_DATABASE=Desire / Desire HD / Hero / Thunderbolt (Charge Mode) + +usb:v0BB4p0FFE* + ID_MODEL_FROM_DATABASE=Desire HD (modem mode) + +usb:v0BB4p0FFF* + ID_MODEL_FROM_DATABASE=Android Fastboot Bootloader + +usb:v0BB4p2008* + ID_MODEL_FROM_DATABASE=Android Phone via MTP [Wiko Cink Peax 2] + +usb:v0BB4p200B* + ID_MODEL_FROM_DATABASE=Android Phone via PTP [Wiko Cink Peax 2] + +usb:v0BB5* + ID_VENDOR_FROM_DATABASE=Murata Manufacturing Co., Ltd + +usb:v0BB6* + ID_VENDOR_FROM_DATABASE=Network Alchemy + +usb:v0BB7* + ID_VENDOR_FROM_DATABASE=Joytech Computer Co., Ltd + +usb:v0BB8* + ID_VENDOR_FROM_DATABASE=Hitachi Semiconductor and Devices Sales Co., Ltd + +usb:v0BB9* + ID_VENDOR_FROM_DATABASE=Eiger M&C Co., Ltd + +usb:v0BBA* + ID_VENDOR_FROM_DATABASE=ZAccess Systems + +usb:v0BBB* + ID_VENDOR_FROM_DATABASE=General Meters Corp. + +usb:v0BBC* + ID_VENDOR_FROM_DATABASE=Assistive Technology, Inc. + +usb:v0BBD* + ID_VENDOR_FROM_DATABASE=System Connection, Inc. + +usb:v0BC0* + ID_VENDOR_FROM_DATABASE=Knilink Technology, Inc. + +usb:v0BC1* + ID_VENDOR_FROM_DATABASE=Fuw Yng Electronics Co., Ltd + +usb:v0BC2* + ID_VENDOR_FROM_DATABASE=Seagate RSS LLC + +usb:v0BC2p0502* + ID_MODEL_FROM_DATABASE=ST3300601CB-RK 300 GB External Hard Drive + +usb:v0BC2p0503* + ID_MODEL_FROM_DATABASE=ST3250824A [Barracuda 7200.9] + +usb:v0BC2p2000* + ID_MODEL_FROM_DATABASE=Storage Adapter V3 (TPP) + +usb:v0BC2p2100* + ID_MODEL_FROM_DATABASE=FreeAgent Go + +usb:v0BC2p2200* + ID_MODEL_FROM_DATABASE=FreeAgent Go FW + +usb:v0BC2p2300* + ID_MODEL_FROM_DATABASE=Expansion Portable + +usb:v0BC2p231A* + ID_MODEL_FROM_DATABASE=Expansion Portable + +usb:v0BC2p2320* + ID_MODEL_FROM_DATABASE=USB 3.0 bridge [Portable Expansion Drive] + +usb:v0BC2p2321* + ID_MODEL_FROM_DATABASE=Expansion Portable + +usb:v0BC2p2322* + ID_MODEL_FROM_DATABASE=SRD0NF1 Expansion Portable (STEA) + +usb:v0BC2p2340* + ID_MODEL_FROM_DATABASE=FreeAgent External Hard Drive + +usb:v0BC2p3000* + ID_MODEL_FROM_DATABASE=FreeAgent Desktop + +usb:v0BC2p3008* + ID_MODEL_FROM_DATABASE=FreeAgent Desk 1TB + +usb:v0BC2p3101* + ID_MODEL_FROM_DATABASE=FreeAgent XTreme 640GB + +usb:v0BC2p3312* + ID_MODEL_FROM_DATABASE=SRD00F2 Expansion Desktop Drive (STBV) + +usb:v0BC2p3320* + ID_MODEL_FROM_DATABASE=SRD00F2 [Expansion Desktop Drive] + +usb:v0BC2p3322* + ID_MODEL_FROM_DATABASE=SRD0NF2 [Expansion Desktop Drive] + +usb:v0BC2p3332* + ID_MODEL_FROM_DATABASE=Expansion + +usb:v0BC2p5020* + ID_MODEL_FROM_DATABASE=FreeAgent GoFlex + +usb:v0BC2p5021* + ID_MODEL_FROM_DATABASE=FreeAgent GoFlex USB 2.0 + +usb:v0BC2p5030* + ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Upgrade Cable STAE104 + +usb:v0BC2p5031* + ID_MODEL_FROM_DATABASE=FreeAgent GoFlex USB 3.0 + +usb:v0BC2p5032* + ID_MODEL_FROM_DATABASE=SATA cable + +usb:v0BC2p5070* + ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Desk + +usb:v0BC2p5071* + ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Desk + +usb:v0BC2p50A1* + ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Desk + +usb:v0BC2p50A5* + ID_MODEL_FROM_DATABASE=FreeAgent GoFlex Desk USB 3.0 + +usb:v0BC2p5121* + ID_MODEL_FROM_DATABASE=FreeAgent GoFlex + +usb:v0BC2p5161* + ID_MODEL_FROM_DATABASE=FreeAgent GoFlex dock + +usb:v0BC2p6126* + ID_MODEL_FROM_DATABASE=Maxtor D3 Station 5TB + +usb:v0BC2p61B6* + ID_MODEL_FROM_DATABASE=Maxtor HX-M101TCB/GM [M3 Portable 1TB] + +usb:v0BC2p61B7* + ID_MODEL_FROM_DATABASE=Maxtor M3 Portable + +usb:v0BC2pA003* + ID_MODEL_FROM_DATABASE=Backup Plus + +usb:v0BC2pA0A1* + ID_MODEL_FROM_DATABASE=Backup Plus Desktop + +usb:v0BC2pA0A4* + ID_MODEL_FROM_DATABASE=Backup Plus Desktop Drive + +usb:v0BC2pAB00* + ID_MODEL_FROM_DATABASE=Slim Portable Drive + +usb:v0BC2pAB1E* + ID_MODEL_FROM_DATABASE=Backup Plus Portable Drive + +usb:v0BC2pAB20* + ID_MODEL_FROM_DATABASE=Backup Plus Portable Drive + +usb:v0BC2pAB21* + ID_MODEL_FROM_DATABASE=Backup Plus Slim + +usb:v0BC2pAB24* + ID_MODEL_FROM_DATABASE=Backup Plus Portable Drive + +usb:v0BC2pAB26* + ID_MODEL_FROM_DATABASE=Backup Plus Slim Portable Drive 1 TB + +usb:v0BC2pAB31* + ID_MODEL_FROM_DATABASE=Backup Plus Desktop Drive (5TB) + +usb:v0BC2pAB34* + ID_MODEL_FROM_DATABASE=Backup Plus + +usb:v0BC2pAB38* + ID_MODEL_FROM_DATABASE=Backup Plus Hub + +usb:v0BC3* + ID_VENDOR_FROM_DATABASE=IPWireless, Inc. + +usb:v0BC3p0001* + ID_MODEL_FROM_DATABASE=UMTS-TDD (TD-CDMA) modem + +usb:v0BC4* + ID_VENDOR_FROM_DATABASE=Microcube Corp. + +usb:v0BC5* + ID_VENDOR_FROM_DATABASE=JCN Co., Ltd + +usb:v0BC6* + ID_VENDOR_FROM_DATABASE=ExWAY, Inc. + +usb:v0BC7* + ID_VENDOR_FROM_DATABASE=X10 Wireless Technology, Inc. + +usb:v0BC7p0001* + ID_MODEL_FROM_DATABASE=ActiveHome (ACPI-compliant) + +usb:v0BC7p0002* + ID_MODEL_FROM_DATABASE=Firecracker Interface (ACPI-compliant) + +usb:v0BC7p0003* + ID_MODEL_FROM_DATABASE=VGA Video Sender (ACPI-compliant) + +usb:v0BC7p0004* + ID_MODEL_FROM_DATABASE=X10 Receiver + +usb:v0BC7p0005* + ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) + +usb:v0BC7p0006* + ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) + +usb:v0BC7p0007* + ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) + +usb:v0BC7p0008* + ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) + +usb:v0BC7p0009* + ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) + +usb:v0BC7p000A* + ID_MODEL_FROM_DATABASE=Wireless Transceiver (ACPI-compliant) + +usb:v0BC7p000B* + ID_MODEL_FROM_DATABASE=Transceiver (ACPI-compliant) + +usb:v0BC7p000C* + ID_MODEL_FROM_DATABASE=Transceiver (ACPI-compliant) + +usb:v0BC7p000D* + ID_MODEL_FROM_DATABASE=Transceiver (ACPI-compliant) + +usb:v0BC7p000E* + ID_MODEL_FROM_DATABASE=Transceiver (ACPI-compliant) + +usb:v0BC7p000F* + ID_MODEL_FROM_DATABASE=Transceiver (ACPI-compliant) + +usb:v0BC8* + ID_VENDOR_FROM_DATABASE=Telmax Communications + +usb:v0BC9* + ID_VENDOR_FROM_DATABASE=ECI Telecom, Ltd + +usb:v0BCA* + ID_VENDOR_FROM_DATABASE=Startek Engineering, Inc. + +usb:v0BCB* + ID_VENDOR_FROM_DATABASE=Perfect Technic Enterprise Co., Ltd + +usb:v0BD7* + ID_VENDOR_FROM_DATABASE=Andrew Pargeter & Associates + +usb:v0BD7pA021* + ID_MODEL_FROM_DATABASE=Amptek DP4 multichannel signal analyzer + +usb:v0BDA* + ID_VENDOR_FROM_DATABASE=Realtek Semiconductor Corp. + +usb:v0BDAp0103* + ID_MODEL_FROM_DATABASE=USB 2.0 Card Reader + +usb:v0BDAp0104* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0106* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0107* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0108* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0109* + ID_MODEL_FROM_DATABASE=microSDXC Card Reader [Hama 00091047] + +usb:v0BDAp0111* + ID_MODEL_FROM_DATABASE=RTS5111 Card Reader Controller + +usb:v0BDAp0113* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0115* + ID_MODEL_FROM_DATABASE=Mass Storage Device (Multicard Reader) + +usb:v0BDAp0116* + ID_MODEL_FROM_DATABASE=RTS5116 Card Reader Controller + +usb:v0BDAp0117* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0118* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0119* + ID_MODEL_FROM_DATABASE=Storage Device (SD card reader) + +usb:v0BDAp0129* + ID_MODEL_FROM_DATABASE=RTS5129 Card Reader Controller + +usb:v0BDAp0138* + ID_MODEL_FROM_DATABASE=RTS5138 Card Reader Controller + +usb:v0BDAp0139* + ID_MODEL_FROM_DATABASE=RTS5139 Card Reader Controller + +usb:v0BDAp0151* + ID_MODEL_FROM_DATABASE=Mass Storage Device (Multicard Reader) + +usb:v0BDAp0152* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0153* + ID_MODEL_FROM_DATABASE=3-in-1 (SD/SDHC/SDXC) Card Reader + +usb:v0BDAp0156* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0157* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0158* + ID_MODEL_FROM_DATABASE=USB 2.0 multicard reader + +usb:v0BDAp0159* + ID_MODEL_FROM_DATABASE=RTS5159 Card Reader Controller + +usb:v0BDAp0161* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0168* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0169* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0171* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0176* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0178* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0BDAp0179* + ID_MODEL_FROM_DATABASE=RTL8188ETV Wireless LAN 802.11n Network Adapter + +usb:v0BDAp0184* + ID_MODEL_FROM_DATABASE=RTS5182 Card Reader + +usb:v0BDAp0186* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v0BDAp0301* + ID_MODEL_FROM_DATABASE=multicard reader + +usb:v0BDAp0307* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v0BDAp0326* + ID_MODEL_FROM_DATABASE=Card reader + +usb:v0BDAp1724* + ID_MODEL_FROM_DATABASE=RTL8723AU 802.11n WLAN Adapter + +usb:v0BDAp2831* + ID_MODEL_FROM_DATABASE=RTL2831U DVB-T + +usb:v0BDAp2832* + ID_MODEL_FROM_DATABASE=RTL2832U DVB-T + +usb:v0BDAp2838* + ID_MODEL_FROM_DATABASE=RTL2838 DVB-T + +usb:v0BDAp5401* + ID_MODEL_FROM_DATABASE=RTL 8153 USB 3.0 hub with gigabit ethernet + +usb:v0BDAp570C* + ID_MODEL_FROM_DATABASE=Asus laptop camera + +usb:v0BDAp5730* + ID_MODEL_FROM_DATABASE=HP 2.0MP High Definition Webcam + +usb:v0BDAp5751* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v0BDAp5775* + ID_MODEL_FROM_DATABASE=HP "Truevision HD" laptop camera + +usb:v0BDAp57B3* + ID_MODEL_FROM_DATABASE=Acer 640 × 480 laptop camera + +usb:v0BDAp57DA* + ID_MODEL_FROM_DATABASE=Built-In Video Camera + +usb:v0BDAp58C8* + ID_MODEL_FROM_DATABASE=Integrated Webcam HD + +usb:v0BDAp8150* + ID_MODEL_FROM_DATABASE=RTL8150 Fast Ethernet Adapter + +usb:v0BDAp8151* + ID_MODEL_FROM_DATABASE=RTL8151 Adapteon Business Mobile Networks BV + +usb:v0BDAp8152* + ID_MODEL_FROM_DATABASE=RTL8152 Fast Ethernet Adapter + +usb:v0BDAp8153* + ID_MODEL_FROM_DATABASE=RTL8153 Gigabit Ethernet Adapter + +usb:v0BDAp8171* + ID_MODEL_FROM_DATABASE=RTL8188SU 802.11n WLAN Adapter + +usb:v0BDAp8172* + ID_MODEL_FROM_DATABASE=RTL8191SU 802.11n WLAN Adapter + +usb:v0BDAp8174* + ID_MODEL_FROM_DATABASE=RTL8192SU 802.11n WLAN Adapter + +usb:v0BDAp8176* + ID_MODEL_FROM_DATABASE=RTL8188CUS 802.11n WLAN Adapter + +usb:v0BDAp8178* + ID_MODEL_FROM_DATABASE=RTL8192CU 802.11n WLAN Adapter + +usb:v0BDAp8179* + ID_MODEL_FROM_DATABASE=RTL8188EUS 802.11n Wireless Network Adapter + +usb:v0BDAp817F* + ID_MODEL_FROM_DATABASE=RTL8188RU 802.11n WLAN Adapter + +usb:v0BDAp8187* + ID_MODEL_FROM_DATABASE=RTL8187 Wireless Adapter + +usb:v0BDAp8189* + ID_MODEL_FROM_DATABASE=RTL8187B Wireless 802.11g 54Mbps Network Adapter + +usb:v0BDAp818B* + ID_MODEL_FROM_DATABASE=RTL8192EU 802.11b/g/n WLAN Adapter + +usb:v0BDAp8192* + ID_MODEL_FROM_DATABASE=RTL8191SU 802.11n Wireless Adapter + +usb:v0BDAp8193* + ID_MODEL_FROM_DATABASE=RTL8192DU 802.11an WLAN Adapter + +usb:v0BDAp8197* + ID_MODEL_FROM_DATABASE=RTL8187B Wireless Adapter + +usb:v0BDAp8198* + ID_MODEL_FROM_DATABASE=RTL8187B Wireless Adapter + +usb:v0BDAp8199* + ID_MODEL_FROM_DATABASE=RTL8187SU 802.11g WLAN Adapter + +usb:v0BDAp8812* + ID_MODEL_FROM_DATABASE=RTL8812AU 802.11a/b/g/n/ac 2T2R DB WLAN Adapter + +usb:v0BDAp8813* + ID_MODEL_FROM_DATABASE=RTL8814AU 802.11a/b/g/n/ac Wireless Adapter + +usb:v0BDApA811* + ID_MODEL_FROM_DATABASE=RTL8811AU 802.11a/b/g/n/ac WLAN Adapter + +usb:v0BDB* + ID_VENDOR_FROM_DATABASE=Ericsson Business Mobile Networks BV + +usb:v0BDBp1000* + ID_MODEL_FROM_DATABASE=BV Bluetooth Device + +usb:v0BDBp1002* + ID_MODEL_FROM_DATABASE=Bluetooth Device 1.2 + +usb:v0BDBp1049* + ID_MODEL_FROM_DATABASE=C3607w Mobile Broadband Module + +usb:v0BDBp1900* + ID_MODEL_FROM_DATABASE=F3507g Mobile Broadband Module + +usb:v0BDBp1902* + ID_MODEL_FROM_DATABASE=F3507g v2 Mobile Broadband Module + +usb:v0BDBp1904* + ID_MODEL_FROM_DATABASE=F3607gw Mobile Broadband Module + +usb:v0BDBp1905* + ID_MODEL_FROM_DATABASE=F3607gw v2 Mobile Broadband Module + +usb:v0BDBp1906* + ID_MODEL_FROM_DATABASE=F3607gw v3 Mobile Broadband Module + +usb:v0BDBp1909* + ID_MODEL_FROM_DATABASE=F3307 v2 Mobile Broadband Module + +usb:v0BDBp190A* + ID_MODEL_FROM_DATABASE=F3307 Mobile Broadband Module + +usb:v0BDBp190B* + ID_MODEL_FROM_DATABASE=C3607w v2 Mobile Broadband Module + +usb:v0BDBp1926* + ID_MODEL_FROM_DATABASE=H5321 gw Mobile Broadband Driver + +usb:v0BDC* + ID_VENDOR_FROM_DATABASE=Y Media Corp. + +usb:v0BDD* + ID_VENDOR_FROM_DATABASE=Orange PCS + +usb:v0BE2* + ID_VENDOR_FROM_DATABASE=Kanda Tsushin Kogyo Co., Ltd + +usb:v0BE3* + ID_VENDOR_FROM_DATABASE=TOYO Corp. + +usb:v0BE4* + ID_VENDOR_FROM_DATABASE=Elka International, Ltd + +usb:v0BE5* + ID_VENDOR_FROM_DATABASE=DOME imaging systems, Inc. + +usb:v0BE6* + ID_VENDOR_FROM_DATABASE=Dong Guan Humen Wonderful Wire Cable Factory + +usb:v0BED* + ID_VENDOR_FROM_DATABASE=MEI + +usb:v0BEDp1100* + ID_MODEL_FROM_DATABASE=CASHFLOW SC + +usb:v0BEDp1101* + ID_MODEL_FROM_DATABASE=Series 2000 Combo Acceptor + +usb:v0BEE* + ID_VENDOR_FROM_DATABASE=LTK Industries, Ltd + +usb:v0BEF* + ID_VENDOR_FROM_DATABASE=Way2Call Communications + +usb:v0BF0* + ID_VENDOR_FROM_DATABASE=Pace Micro Technology PLC + +usb:v0BF1* + ID_VENDOR_FROM_DATABASE=Intracom S.A. + +usb:v0BF1p0001* + ID_MODEL_FROM_DATABASE=netMod Driver Ver 2.4.17 (CAPI) + +usb:v0BF1p0002* + ID_MODEL_FROM_DATABASE=netMod Driver Ver 2.4 (CAPI) + +usb:v0BF1p0003* + ID_MODEL_FROM_DATABASE=netMod Driver Ver 2.4 (CAPI) + +usb:v0BF2* + ID_VENDOR_FROM_DATABASE=Konexx + +usb:v0BF6* + ID_VENDOR_FROM_DATABASE=Addonics Technologies, Inc. + +usb:v0BF6p0103* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v0BF6p1234* + ID_MODEL_FROM_DATABASE=Storage Device + +usb:v0BF6pA000* + ID_MODEL_FROM_DATABASE=Cable 205 (TPP) + +usb:v0BF6pA001* + ID_MODEL_FROM_DATABASE=Cable 205 + +usb:v0BF6pA002* + ID_MODEL_FROM_DATABASE=IDE Bridge + +usb:v0BF7* + ID_VENDOR_FROM_DATABASE=Sunny Giken, Inc. + +usb:v0BF8* + ID_VENDOR_FROM_DATABASE=Fujitsu Siemens Computers + +usb:v0BF8p1001* + ID_MODEL_FROM_DATABASE=Fujitsu Pocket Loox 600 PDA + +usb:v0BF8p1006* + ID_MODEL_FROM_DATABASE=SmartCard Reader 2A + +usb:v0BF8p1007* + ID_MODEL_FROM_DATABASE=Connect2Air E-5400 802.11g Wireless Adapter + +usb:v0BF8p1009* + ID_MODEL_FROM_DATABASE=Connect2Air E-5400 D1700 802.11g Wireless Adapter [Intersil ISL3887] + +usb:v0BF8p100C* + ID_MODEL_FROM_DATABASE=Keyboard FSC KBPC PX + +usb:v0BF8p100F* + ID_MODEL_FROM_DATABASE=miniCard D2301 802.11bg Wireless Module [SiS 163U] + +usb:v0BF8p1017* + ID_MODEL_FROM_DATABASE=Keyboard KB SCR + +usb:v0BF8p101F* + ID_MODEL_FROM_DATABASE=Fujitsu Full HD Pro Webcam + +usb:v0BFD* + ID_VENDOR_FROM_DATABASE=Kvaser AB + +usb:v0BFDp0004* + ID_MODEL_FROM_DATABASE=USBcan II + +usb:v0BFDp000B* + ID_MODEL_FROM_DATABASE=Leaf Light HS + +usb:v0BFDp000E* + ID_MODEL_FROM_DATABASE=Leaf SemiPro HS + +usb:v0C00* + ID_VENDOR_FROM_DATABASE=FireFly Mouse Mat + +usb:v0C00p1607* + ID_MODEL_FROM_DATABASE=Apex M500 + +usb:v0C04* + ID_VENDOR_FROM_DATABASE=MOTO Development Group, Inc. + +usb:v0C05* + ID_VENDOR_FROM_DATABASE=Appian Graphics + +usb:v0C06* + ID_VENDOR_FROM_DATABASE=Hasbro Games, Inc. + +usb:v0C07* + ID_VENDOR_FROM_DATABASE=Infinite Data Storage, Ltd + +usb:v0C08* + ID_VENDOR_FROM_DATABASE=Agate + +usb:v0C08p0378* + ID_MODEL_FROM_DATABASE=Q 16MB Storage Device + +usb:v0C09* + ID_VENDOR_FROM_DATABASE=Comjet Information System + +usb:v0C09pA5A5* + ID_MODEL_FROM_DATABASE=Litto Version USB2.0 + +usb:v0C0A* + ID_VENDOR_FROM_DATABASE=Highpoint Technologies, Inc. + +usb:v0C0B* + ID_VENDOR_FROM_DATABASE=Dura Micro, Inc. (Acomdata) + +usb:v0C0Bp27CB* + ID_MODEL_FROM_DATABASE=6-in-1 Flash Reader and Writer + +usb:v0C0Bp27D7* + ID_MODEL_FROM_DATABASE=Multi Memory reader/writer MD-005 + +usb:v0C0Bp27DA* + ID_MODEL_FROM_DATABASE=Multi Memory reader/writer MD-005 + +usb:v0C0Bp27DC* + ID_MODEL_FROM_DATABASE=Multi Memory reader/writer MD-005 + +usb:v0C0Bp27E7* + ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 + +usb:v0C0Bp27EE* + ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 + +usb:v0C0Bp2814* + ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 + +usb:v0C0Bp2815* + ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 + +usb:v0C0Bp281D* + ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 + +usb:v0C0Bp5FAB* + ID_MODEL_FROM_DATABASE=Storage Adaptor + +usb:v0C0BpA109* + ID_MODEL_FROM_DATABASE=CF/SM Reader and Writer + +usb:v0C0BpA10C* + ID_MODEL_FROM_DATABASE=SD/MS Reader and Writer + +usb:v0C0BpB001* + ID_MODEL_FROM_DATABASE=USB 2.0 Mass Storage IDE adapter + +usb:v0C0BpB004* + ID_MODEL_FROM_DATABASE=MMC/SD Reader and Writer + +usb:v0C12* + ID_VENDOR_FROM_DATABASE=Zeroplus + +usb:v0C12p0005* + ID_MODEL_FROM_DATABASE=PSX Vibration Feedback Converter + +usb:v0C12p0030* + ID_MODEL_FROM_DATABASE=PSX Vibration Feedback Converter + +usb:v0C12p700E* + ID_MODEL_FROM_DATABASE=Logic Analyzer (LAP-C-16032) + +usb:v0C12p8801* + ID_MODEL_FROM_DATABASE=Xbox Controller + +usb:v0C12p8802* + ID_MODEL_FROM_DATABASE=Xbox Controller + +usb:v0C12p8809* + ID_MODEL_FROM_DATABASE=Red Octane Ignition Xbox DDR Pad + +usb:v0C12p880A* + ID_MODEL_FROM_DATABASE=Pelican Eclipse PL-2023 + +usb:v0C12p8810* + ID_MODEL_FROM_DATABASE=Xbox Controller + +usb:v0C12p9902* + ID_MODEL_FROM_DATABASE=VibraX + +usb:v0C15* + ID_VENDOR_FROM_DATABASE=Iris Graphics + +usb:v0C16* + ID_VENDOR_FROM_DATABASE=Gyration, Inc. + +usb:v0C16p0002* + ID_MODEL_FROM_DATABASE=RF Technology Receiver + +usb:v0C16p0003* + ID_MODEL_FROM_DATABASE=RF Technology Receiver + +usb:v0C16p0008* + ID_MODEL_FROM_DATABASE=RF Technology Receiver + +usb:v0C16p0080* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v0C16p0081* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v0C17* + ID_VENDOR_FROM_DATABASE=Cyberboard A/S + +usb:v0C18* + ID_VENDOR_FROM_DATABASE=SynerTek Korea, Inc. + +usb:v0C19* + ID_VENDOR_FROM_DATABASE=cyberPIXIE, Inc. + +usb:v0C1A* + ID_VENDOR_FROM_DATABASE=Silicon Motion, Inc. + +usb:v0C1B* + ID_VENDOR_FROM_DATABASE=MIPS Technologies + +usb:v0C1C* + ID_VENDOR_FROM_DATABASE=Hang Zhou Silan Electronics Co., Ltd + +usb:v0C22* + ID_VENDOR_FROM_DATABASE=Tally Printer Corp. + +usb:v0C23* + ID_VENDOR_FROM_DATABASE=Lernout + Hauspie + +usb:v0C24* + ID_VENDOR_FROM_DATABASE=Taiyo Yuden + +usb:v0C24p0001* + ID_MODEL_FROM_DATABASE=Bluetooth Adaptor + +usb:v0C24p0002* + ID_MODEL_FROM_DATABASE=Bluetooth Device2 + +usb:v0C24p0005* + ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) + +usb:v0C24p000B* + ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) + +usb:v0C24p000C* + ID_MODEL_FROM_DATABASE=Bluetooth Adaptor + +usb:v0C24p000E* + ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) + +usb:v0C24p000F* + ID_MODEL_FROM_DATABASE=Bluetooth Device (V2.0+EDR) + +usb:v0C24p0010* + ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) + +usb:v0C24p0012* + ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) + +usb:v0C24p0018* + ID_MODEL_FROM_DATABASE=Bluetooth Device(BC04-External) + +usb:v0C24p0019* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0C24p0021* + ID_MODEL_FROM_DATABASE=Bluetooth Device (V2.1+EDR) + +usb:v0C24p0C24* + ID_MODEL_FROM_DATABASE=Bluetooth Device(SAMPLE) + +usb:v0C24pFFFF* + ID_MODEL_FROM_DATABASE=Bluetooth module with BlueCore in DFU mode + +usb:v0C25* + ID_VENDOR_FROM_DATABASE=Sampo Corp. + +usb:v0C25p0310* + ID_MODEL_FROM_DATABASE=Scream Cam + +usb:v0C26* + ID_VENDOR_FROM_DATABASE=Prolific Technology Inc. + +usb:v0C26p0018* + ID_MODEL_FROM_DATABASE=USB-Serial Controller [Icom Inc. OPC-478UC] + +usb:v0C27* + ID_VENDOR_FROM_DATABASE=RFIDeas, Inc + +usb:v0C27p3BFA* + ID_MODEL_FROM_DATABASE=pcProx Card Reader + +usb:v0C2E* + ID_VENDOR_FROM_DATABASE=Metrologic Instruments + +usb:v0C2Ep0007* + ID_MODEL_FROM_DATABASE=Metrologic MS7120 Barcode Scanner (IBM SurePOS mode) + +usb:v0C2Ep0200* + ID_MODEL_FROM_DATABASE=MS7120 Barcode Scanner + +usb:v0C2Ep0204* + ID_MODEL_FROM_DATABASE=Metrologic MS7120 Barcode Scanner (keyboard mode) + +usb:v0C2Ep0206* + ID_MODEL_FROM_DATABASE=Metrologic MS4980 Barcode Scanner + +usb:v0C2Ep0700* + ID_MODEL_FROM_DATABASE=Metrologic MS7120 Barcode Scanner (uni-directional serial mode) + +usb:v0C2Ep0720* + ID_MODEL_FROM_DATABASE=Metrologic MS7120 Barcode Scanner (bi-directional serial mode) + +usb:v0C2Ep0B61* + ID_MODEL_FROM_DATABASE=Vuquest 3310g + +usb:v0C2Ep0B6A* + ID_MODEL_FROM_DATABASE=Vuquest 3310 Area-Imaging Scanner + +usb:v0C2Ep0B81* + ID_MODEL_FROM_DATABASE=Barcode scanner Voyager 1400g Series + +usb:v0C30* + ID_VENDOR_FROM_DATABASE=Mutoh Industries Ltd + +usb:v0C30p6010* + ID_MODEL_FROM_DATABASE=Kona 1400 Cutting Plotter + +usb:v0C35* + ID_VENDOR_FROM_DATABASE=Eagletron, Inc. + +usb:v0C36* + ID_VENDOR_FROM_DATABASE=E Ink Corp. + +usb:v0C37* + ID_VENDOR_FROM_DATABASE=e.Digital + +usb:v0C38* + ID_VENDOR_FROM_DATABASE=Der An Electric Wire & Cable Co., Ltd + +usb:v0C39* + ID_VENDOR_FROM_DATABASE=IFR + +usb:v0C3A* + ID_VENDOR_FROM_DATABASE=Furui Precise Component (Kunshan) Co., Ltd + +usb:v0C3B* + ID_VENDOR_FROM_DATABASE=Komatsu, Ltd + +usb:v0C3C* + ID_VENDOR_FROM_DATABASE=Radius Co., Ltd + +usb:v0C3D* + ID_VENDOR_FROM_DATABASE=Innocom, Inc. + +usb:v0C3E* + ID_VENDOR_FROM_DATABASE=Nextcell, Inc. + +usb:v0C44* + ID_VENDOR_FROM_DATABASE=Motorola iDEN + +usb:v0C44p0021* + ID_MODEL_FROM_DATABASE=iDEN P2k0 Device + +usb:v0C44p0022* + ID_MODEL_FROM_DATABASE=iDEN P2k1 Device + +usb:v0C44p03A2* + ID_MODEL_FROM_DATABASE=iDEN Smartphone + +usb:v0C44p41D9* + ID_MODEL_FROM_DATABASE=i1 phone + +usb:v0C45* + ID_VENDOR_FROM_DATABASE=Microdia + +usb:v0C45p0011* + ID_MODEL_FROM_DATABASE=EBUDDY + +usb:v0C45p0520* + ID_MODEL_FROM_DATABASE=MaxTrack Wireless Mouse + +usb:v0C45p1018* + ID_MODEL_FROM_DATABASE=Compact Flash storage memory card reader + +usb:v0C45p1020* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1028* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1030* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1031* + ID_MODEL_FROM_DATABASE=Sonix Mass Storage Device + +usb:v0C45p1032* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1033* + ID_MODEL_FROM_DATABASE=Sonix Mass Storage Device + +usb:v0C45p1034* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1035* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1036* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1037* + ID_MODEL_FROM_DATABASE=Sonix Mass Storage Device + +usb:v0C45p1050* + ID_MODEL_FROM_DATABASE=CF Card Reader + +usb:v0C45p1058* + ID_MODEL_FROM_DATABASE=HDD Reader + +usb:v0C45p1060* + ID_MODEL_FROM_DATABASE=iFlash SM-Direct Card Reader + +usb:v0C45p1061* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1062* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1063* + ID_MODEL_FROM_DATABASE=Sonix Mass Storage Device + +usb:v0C45p1064* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1065* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1066* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1067* + ID_MODEL_FROM_DATABASE=Mass Storage Reader + +usb:v0C45p1158* + ID_MODEL_FROM_DATABASE=A56AK + +usb:v0C45p184C* + ID_MODEL_FROM_DATABASE=VoIP Phone + +usb:v0C45p6001* + ID_MODEL_FROM_DATABASE=Genius VideoCAM NB + +usb:v0C45p6005* + ID_MODEL_FROM_DATABASE=Sweex Mini Webcam + +usb:v0C45p6007* + ID_MODEL_FROM_DATABASE=VideoCAM Eye + +usb:v0C45p6009* + ID_MODEL_FROM_DATABASE=VideoCAM ExpressII + +usb:v0C45p600D* + ID_MODEL_FROM_DATABASE=TwinkleCam USB camera + +usb:v0C45p6011* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C102) + +usb:v0C45p6019* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C102) + +usb:v0C45p6024* + ID_MODEL_FROM_DATABASE=VideoCAM ExpressII + +usb:v0C45p6025* + ID_MODEL_FROM_DATABASE=VideoCAM ExpressII + +usb:v0C45p6028* + ID_MODEL_FROM_DATABASE=Typhoon Easycam USB 330K (older) + +usb:v0C45p6029* + ID_MODEL_FROM_DATABASE=Triplex i-mini PC Camera + +usb:v0C45p602A* + ID_MODEL_FROM_DATABASE=Meade ETX-105EC Camera + +usb:v0C45p602B* + ID_MODEL_FROM_DATABASE=VideoCAM NB 300 + +usb:v0C45p602C* + ID_MODEL_FROM_DATABASE=Clas Ohlson TWC-30XOP Webcam + +usb:v0C45p602D* + ID_MODEL_FROM_DATABASE=VideoCAM ExpressII + +usb:v0C45p602E* + ID_MODEL_FROM_DATABASE=VideoCAM Messenger + +usb:v0C45p6030* + ID_MODEL_FROM_DATABASE=VideoCAM ExpressII + +usb:v0C45p603F* + ID_MODEL_FROM_DATABASE=VideoCAM ExpressII + +usb:v0C45p6040* + ID_MODEL_FROM_DATABASE=CCD PC Camera (PC390A) + +usb:v0C45p606A* + ID_MODEL_FROM_DATABASE=CCD PC Camera (PC390A) + +usb:v0C45p607A* + ID_MODEL_FROM_DATABASE=CCD PC Camera (PC390A) + +usb:v0C45p607B* + ID_MODEL_FROM_DATABASE=Win2 PC Camera + +usb:v0C45p607C* + ID_MODEL_FROM_DATABASE=CCD PC Camera (PC390A) + +usb:v0C45p607E* + ID_MODEL_FROM_DATABASE=CCD PC Camera (PC390A) + +usb:v0C45p6080* + ID_MODEL_FROM_DATABASE=Audio (Microphone) + +usb:v0C45p6082* + ID_MODEL_FROM_DATABASE=VideoCAM Look + +usb:v0C45p6083* + ID_MODEL_FROM_DATABASE=VideoCAM Look + +usb:v0C45p608C* + ID_MODEL_FROM_DATABASE=VideoCAM Look + +usb:v0C45p608E* + ID_MODEL_FROM_DATABASE=VideoCAM Look + +usb:v0C45p608F* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C103 + OV7630) + +usb:v0C45p60A8* + ID_MODEL_FROM_DATABASE=VideoCAM Look + +usb:v0C45p60AA* + ID_MODEL_FROM_DATABASE=VideoCAM Look + +usb:v0C45p60AB* + ID_MODEL_FROM_DATABASE=PC Camera + +usb:v0C45p60AF* + ID_MODEL_FROM_DATABASE=VideoCAM Look + +usb:v0C45p60B0* + ID_MODEL_FROM_DATABASE=Genius VideoCam Look + +usb:v0C45p60C0* + ID_MODEL_FROM_DATABASE=PC Camera with Mic (SN9C105) + +usb:v0C45p60C8* + ID_MODEL_FROM_DATABASE=Win2 PC Camera + +usb:v0C45p60CC* + ID_MODEL_FROM_DATABASE=PC Camera with Mic (SN9C105) + +usb:v0C45p60EC* + ID_MODEL_FROM_DATABASE=PC Camera with Mic (SN9C105) + +usb:v0C45p60EF* + ID_MODEL_FROM_DATABASE=Win2 PC Camera + +usb:v0C45p60FA* + ID_MODEL_FROM_DATABASE=PC Camera with Mic (SN9C105) + +usb:v0C45p60FB* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v0C45p60FC* + ID_MODEL_FROM_DATABASE=PC Camera with Mic (SN9C105) + +usb:v0C45p60FE* + ID_MODEL_FROM_DATABASE=Audio (Microphone) + +usb:v0C45p6108* + ID_MODEL_FROM_DATABASE=Win2 PC Camera + +usb:v0C45p6122* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C110) + +usb:v0C45p6123* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C110) + +usb:v0C45p6128* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C325 + OM6802) + +usb:v0C45p612A* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C325) + +usb:v0C45p612C* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C110) + +usb:v0C45p612E* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C110) + +usb:v0C45p612F* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C110) + +usb:v0C45p6130* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C120) + +usb:v0C45p6138* + ID_MODEL_FROM_DATABASE=Win2 PC Camera + +usb:v0C45p613A* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C120) + +usb:v0C45p613B* + ID_MODEL_FROM_DATABASE=Win2 PC Camera + +usb:v0C45p613C* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C120) + +usb:v0C45p613E* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C120) + +usb:v0C45p6143* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C120 + SP80708) + +usb:v0C45p6240* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + MI1300) + +usb:v0C45p6242* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + MI1310) + +usb:v0C45p6243* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + S5K4AAFX) + +usb:v0C45p6248* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV9655) + +usb:v0C45p624B* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + CX1332) + +usb:v0C45p624C* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + MI1320) + +usb:v0C45p624E* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + SOI968) + +usb:v0C45p624F* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV9650) + +usb:v0C45p6251* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV9650) + +usb:v0C45p6253* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV9650) + +usb:v0C45p6260* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV7670ISP) + +usb:v0C45p6262* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OM6802) + +usb:v0C45p6270* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + MI0360/MT9V011 or MI0360SOC/MT9V111) U-CAM PC Camera NE878, Whitcom WHC017, ... + +usb:v0C45p627A* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + S5K53BEB) + +usb:v0C45p627B* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV7660) + +usb:v0C45p627C* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + HV7131R) + +usb:v0C45p627F* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV965x + EEPROM) + +usb:v0C45p6280* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + MI1300) + +usb:v0C45p6282* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + MI1310) + +usb:v0C45p6283* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + S5K4AAFX) + +usb:v0C45p6288* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV9655) + +usb:v0C45p628A* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + ICM107) + +usb:v0C45p628B* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + CX1332) + +usb:v0C45p628C* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + MI1320) + +usb:v0C45p628E* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + SOI968) + +usb:v0C45p628F* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV9650) + +usb:v0C45p62A0* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV7670ISP) + +usb:v0C45p62A2* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OM6802) + +usb:v0C45p62B0* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + MI0360/MT9V011 or MI0360SOC/MT9V111) + +usb:v0C45p62B3* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV9655) + +usb:v0C45p62BA* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + S5K53BEB) + +usb:v0C45p62BB* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV7660) + +usb:v0C45p62BC* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + HV7131R) + +usb:v0C45p62BE* + ID_MODEL_FROM_DATABASE=PC Camera with Microphone (SN9C202 + OV7663) + +usb:v0C45p62C0* + ID_MODEL_FROM_DATABASE=Sonix USB 2.0 Camera + +usb:v0C45p62E0* + ID_MODEL_FROM_DATABASE=MSI Starcam Racer + +usb:v0C45p6300* + ID_MODEL_FROM_DATABASE=PC Microscope camera + +usb:v0C45p6310* + ID_MODEL_FROM_DATABASE=Sonix USB 2.0 Camera + +usb:v0C45p6340* + ID_MODEL_FROM_DATABASE=Camera + +usb:v0C45p6341* + ID_MODEL_FROM_DATABASE=Defender G-Lens 2577 HD720p Camera + +usb:v0C45p63E0* + ID_MODEL_FROM_DATABASE=Sonix Integrated Webcam + +usb:v0C45p63F1* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v0C45p63F8* + ID_MODEL_FROM_DATABASE=Sonix Integrated Webcam + +usb:v0C45p6409* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v0C45p6413* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v0C45p6417* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v0C45p6419* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v0C45p641D* + ID_MODEL_FROM_DATABASE=1.3 MPixel Integrated Webcam + +usb:v0C45p6433* + ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam HD (Composite Device) + +usb:v0C45p643F* + ID_MODEL_FROM_DATABASE=Dell Integrated HD Webcam + +usb:v0C45p644D* + ID_MODEL_FROM_DATABASE=1.3 MPixel Integrated Webcam + +usb:v0C45p6480* + ID_MODEL_FROM_DATABASE=Sonix 1.3 MP Laptop Integrated Webcam + +usb:v0C45p648B* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v0C45p64BD* + ID_MODEL_FROM_DATABASE=Sony Visual Communication Camera + +usb:v0C45p64D0* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v0C45p64D2* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v0C45p651B* + ID_MODEL_FROM_DATABASE=HP Webcam + +usb:v0C45p6705* + ID_MODEL_FROM_DATABASE=Integrated HD Webcam + +usb:v0C45p6710* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v0C45p7401* + ID_MODEL_FROM_DATABASE=TEMPer Temperature Sensor + +usb:v0C45p7402* + ID_MODEL_FROM_DATABASE=TEMPerHUM Temperature & Humidity Sensor + +usb:v0C45p7403* + ID_MODEL_FROM_DATABASE=Foot Switch + +usb:v0C45p7404* + ID_MODEL_FROM_DATABASE=Foot switch FS1-P + +usb:v0C45p8000* + ID_MODEL_FROM_DATABASE=DC31VC + +usb:v0C45p8006* + ID_MODEL_FROM_DATABASE=Dual Mode Camera (8006 VGA) + +usb:v0C45p800A* + ID_MODEL_FROM_DATABASE=Vivitar Vivicam3350B + +usb:v0C46* + ID_VENDOR_FROM_DATABASE=WaveRider Communications, Inc. + +usb:v0C4A* + ID_VENDOR_FROM_DATABASE=ALGE-TIMING GmbH + +usb:v0C4Ap0889* + ID_MODEL_FROM_DATABASE=Timy + +usb:v0C4Ap088A* + ID_MODEL_FROM_DATABASE=Timy 2 + +usb:v0C4B* + ID_VENDOR_FROM_DATABASE=Reiner SCT Kartensysteme GmbH + +usb:v0C4Bp0100* + ID_MODEL_FROM_DATABASE=cyberJack e-com/pinpad + +usb:v0C4Bp0300* + ID_MODEL_FROM_DATABASE=cyberJack pinpad(a) + +usb:v0C4Bp0400* + ID_MODEL_FROM_DATABASE=cyberJack e-com(a) + +usb:v0C4Bp0401* + ID_MODEL_FROM_DATABASE=cyberJack pinpad(a2) + +usb:v0C4Bp0500* + ID_MODEL_FROM_DATABASE=cyberJack RFID standard dual interface smartcard reader + +usb:v0C4Bp0501* + ID_MODEL_FROM_DATABASE=cyberJack RFID comfort dual interface smartcard reader + +usb:v0C4Bp0502* + ID_MODEL_FROM_DATABASE=cyberJack compact + +usb:v0C4Bp0504* + ID_MODEL_FROM_DATABASE=cyberJack go / go plus + +usb:v0C4Bp0505* + ID_MODEL_FROM_DATABASE=cyberJack wave + +usb:v0C4Bp9102* + ID_MODEL_FROM_DATABASE=cyberJack RFID basis contactless smartcard reader + +usb:v0C4C* + ID_VENDOR_FROM_DATABASE=Needham's Electronics + +usb:v0C4Cp0021* + ID_MODEL_FROM_DATABASE=EMP-21 Universal Programmer + +usb:v0C52* + ID_VENDOR_FROM_DATABASE=Sealevel Systems, Inc. + +usb:v0C52p2101* + ID_MODEL_FROM_DATABASE=SeaLINK+232 + +usb:v0C52p2102* + ID_MODEL_FROM_DATABASE=SeaLINK+485 + +usb:v0C52p2103* + ID_MODEL_FROM_DATABASE=SeaLINK+232I + +usb:v0C52p2104* + ID_MODEL_FROM_DATABASE=SeaLINK+485I + +usb:v0C52p2211* + ID_MODEL_FROM_DATABASE=SeaPORT+2/232 (Port 1) + +usb:v0C52p2212* + ID_MODEL_FROM_DATABASE=SeaPORT+2/485 (Port 1) + +usb:v0C52p2213* + ID_MODEL_FROM_DATABASE=SeaPORT+2 (Port 1) + +usb:v0C52p2221* + ID_MODEL_FROM_DATABASE=SeaPORT+2/232 (Port 2) + +usb:v0C52p2222* + ID_MODEL_FROM_DATABASE=SeaPORT+2/485 (Port 2) + +usb:v0C52p2223* + ID_MODEL_FROM_DATABASE=SeaPORT+2 (Port 2) + +usb:v0C52p2411* + ID_MODEL_FROM_DATABASE=SeaPORT+4/232 (Port 1) + +usb:v0C52p2412* + ID_MODEL_FROM_DATABASE=SeaPORT+4/485 (Port 1) + +usb:v0C52p2413* + ID_MODEL_FROM_DATABASE=SeaPORT+4 (Port 1) + +usb:v0C52p2421* + ID_MODEL_FROM_DATABASE=SeaPORT+4/232 (Port 2) + +usb:v0C52p2422* + ID_MODEL_FROM_DATABASE=SeaPORT+4/485 (Port 2) + +usb:v0C52p2423* + ID_MODEL_FROM_DATABASE=SeaPORT+4 (Port 2) + +usb:v0C52p2431* + ID_MODEL_FROM_DATABASE=SeaPORT+4/232 (Port 3) + +usb:v0C52p2432* + ID_MODEL_FROM_DATABASE=SeaPORT+4/485 (Port 3) + +usb:v0C52p2433* + ID_MODEL_FROM_DATABASE=SeaPORT+4 (Port 3) + +usb:v0C52p2441* + ID_MODEL_FROM_DATABASE=SeaPORT+4/232 (Port 4) + +usb:v0C52p2442* + ID_MODEL_FROM_DATABASE=SeaPORT+4/485 (Port 4) + +usb:v0C52p2443* + ID_MODEL_FROM_DATABASE=SeaPORT+4 (Port 4) + +usb:v0C52p2811* + ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 1) + +usb:v0C52p2812* + ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 1) + +usb:v0C52p2813* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 1) + +usb:v0C52p2821* + ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 2) + +usb:v0C52p2822* + ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 2) + +usb:v0C52p2823* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 2) + +usb:v0C52p2831* + ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 3) + +usb:v0C52p2832* + ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 3) + +usb:v0C52p2833* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 3) + +usb:v0C52p2841* + ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 4) + +usb:v0C52p2842* + ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 4) + +usb:v0C52p2843* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 4) + +usb:v0C52p2851* + ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 5) + +usb:v0C52p2852* + ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 5) + +usb:v0C52p2853* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 5) + +usb:v0C52p2861* + ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 6) + +usb:v0C52p2862* + ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 6) + +usb:v0C52p2863* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 6) + +usb:v0C52p2871* + ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 7) + +usb:v0C52p2872* + ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 7) + +usb:v0C52p2873* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 7) + +usb:v0C52p2881* + ID_MODEL_FROM_DATABASE=SeaLINK+8/232 (Port 8) + +usb:v0C52p2882* + ID_MODEL_FROM_DATABASE=SeaLINK+8/485 (Port 8) + +usb:v0C52p2883* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 8) + +usb:v0C52p9020* + ID_MODEL_FROM_DATABASE=SeaLINK+422 + +usb:v0C52pA02A* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 1+2) + +usb:v0C52pA02B* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 3+4) + +usb:v0C52pA02C* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 5+6) + +usb:v0C52pA02D* + ID_MODEL_FROM_DATABASE=SeaLINK+8 (Port 7+8) + +usb:v0C53* + ID_VENDOR_FROM_DATABASE=ViewPLUS, Inc. + +usb:v0C54* + ID_VENDOR_FROM_DATABASE=Glory, Ltd + +usb:v0C55* + ID_VENDOR_FROM_DATABASE=Spectrum Digital, Inc. + +usb:v0C55p0510* + ID_MODEL_FROM_DATABASE=Spectrum Digital XDS510 JTAG Debugger + +usb:v0C55p0540* + ID_MODEL_FROM_DATABASE=SPI540 + +usb:v0C55p5416* + ID_MODEL_FROM_DATABASE=TMS320C5416 DSK + +usb:v0C55p6416* + ID_MODEL_FROM_DATABASE=TMS320C6416 DDB + +usb:v0C56* + ID_VENDOR_FROM_DATABASE=Billion Bright, Ltd + +usb:v0C57* + ID_VENDOR_FROM_DATABASE=Imaginative Design Operation Co., Ltd + +usb:v0C58* + ID_VENDOR_FROM_DATABASE=Vidar Systems Corp. + +usb:v0C59* + ID_VENDOR_FROM_DATABASE=Dong Guan Shinko Wire Co., Ltd + +usb:v0C5A* + ID_VENDOR_FROM_DATABASE=TRS International Mfg., Inc. + +usb:v0C5E* + ID_VENDOR_FROM_DATABASE=Xytronix Research & Design + +usb:v0C60* + ID_VENDOR_FROM_DATABASE=Apogee Electronics Corp. + +usb:v0C60p0001* + ID_MODEL_FROM_DATABASE=MiniMe + +usb:v0C60p0002* + ID_MODEL_FROM_DATABASE=MiniDAC + +usb:v0C60p0003* + ID_MODEL_FROM_DATABASE=ONE + +usb:v0C60p0004* + ID_MODEL_FROM_DATABASE=GiO + +usb:v0C60p0007* + ID_MODEL_FROM_DATABASE=Duet + +usb:v0C60p0009* + ID_MODEL_FROM_DATABASE=Jam + +usb:v0C60p000A* + ID_MODEL_FROM_DATABASE=Jam Bootloader + +usb:v0C60p000B* + ID_MODEL_FROM_DATABASE=MiC + +usb:v0C60p000C* + ID_MODEL_FROM_DATABASE=MiC Bootloader + +usb:v0C60p8007* + ID_MODEL_FROM_DATABASE=Duet DFU Mode + +usb:v0C62* + ID_VENDOR_FROM_DATABASE=Chant Sincere Co., Ltd + +usb:v0C63* + ID_VENDOR_FROM_DATABASE=Toko, Inc. + +usb:v0C64* + ID_VENDOR_FROM_DATABASE=Signality System Engineering Co., Ltd + +usb:v0C65* + ID_VENDOR_FROM_DATABASE=Eminence Enterprise Co., Ltd + +usb:v0C66* + ID_VENDOR_FROM_DATABASE=Rexon Electronics Corp. + +usb:v0C67* + ID_VENDOR_FROM_DATABASE=Concept Telecom, Ltd + +usb:v0C6A* + ID_VENDOR_FROM_DATABASE=ACS + +usb:v0C6Ap0005* + ID_MODEL_FROM_DATABASE=Color 320 x 240 LCD Display Terminal with Touchscreen + +usb:v0C6C* + ID_VENDOR_FROM_DATABASE=JETI Technische Instrumente GmbH + +usb:v0C6Cp04B2* + ID_MODEL_FROM_DATABASE=Specbos 1201 + +usb:v0C70* + ID_VENDOR_FROM_DATABASE=MCT Elektronikladen + +usb:v0C70p0000* + ID_MODEL_FROM_DATABASE=USB08 Development board + +usb:v0C70p0747* + ID_MODEL_FROM_DATABASE=Eye Movement Recorder [Visagraph]/[ReadAlyzer] + +usb:v0C72* + ID_VENDOR_FROM_DATABASE=PEAK System + +usb:v0C72p000C* + ID_MODEL_FROM_DATABASE=PCAN-USB + +usb:v0C72p000D* + ID_MODEL_FROM_DATABASE=PCAN Pro + +usb:v0C74* + ID_VENDOR_FROM_DATABASE=Optronic Laboratories Inc. + +usb:v0C74p0002* + ID_MODEL_FROM_DATABASE=OL 700-30 Goniometer + +usb:v0C76* + ID_VENDOR_FROM_DATABASE=JMTek, LLC. + +usb:v0C76p0001* + ID_MODEL_FROM_DATABASE=Mass Storage Controller + +usb:v0C76p0002* + ID_MODEL_FROM_DATABASE=Mass Storage Controller + +usb:v0C76p0003* + ID_MODEL_FROM_DATABASE=USBdisk + +usb:v0C76p0004* + ID_MODEL_FROM_DATABASE=Mass Storage Controller + +usb:v0C76p0005* + ID_MODEL_FROM_DATABASE=Transcend Flash disk + +usb:v0C76p0006* + ID_MODEL_FROM_DATABASE=Transcend JetFlash + +usb:v0C76p0007* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0C76p1600* + ID_MODEL_FROM_DATABASE=Ion Quick Play LP turntable + +usb:v0C76p1605* + ID_MODEL_FROM_DATABASE=SSS Headphone Set + +usb:v0C76p1607* + ID_MODEL_FROM_DATABASE=audio controller + +usb:v0C77* + ID_VENDOR_FROM_DATABASE=Sipix Group, Ltd + +usb:v0C77p1001* + ID_MODEL_FROM_DATABASE=SiPix Web2 + +usb:v0C77p1002* + ID_MODEL_FROM_DATABASE=SiPix SC2100 + +usb:v0C77p1010* + ID_MODEL_FROM_DATABASE=SiPix Snap + +usb:v0C77p1011* + ID_MODEL_FROM_DATABASE=SiPix Blink 2 + +usb:v0C77p1015* + ID_MODEL_FROM_DATABASE=SiPix CAMeleon + +usb:v0C78* + ID_VENDOR_FROM_DATABASE=Detto Corp. + +usb:v0C79* + ID_VENDOR_FROM_DATABASE=NuConnex Technologies Pte., Ltd + +usb:v0C7A* + ID_VENDOR_FROM_DATABASE=Wing-Span Enterprise Co., Ltd + +usb:v0C86* + ID_VENDOR_FROM_DATABASE=NDA Technologies, Inc. + +usb:v0C88* + ID_VENDOR_FROM_DATABASE=Kyocera Wireless Corp. + +usb:v0C88p0021* + ID_MODEL_FROM_DATABASE=Handheld + +usb:v0C88p17DA* + ID_MODEL_FROM_DATABASE=Qualcomm Kyocera CDMA Technologies MSM + +usb:v0C89* + ID_VENDOR_FROM_DATABASE=Honda Tsushin Kogyo Co., Ltd + +usb:v0C8A* + ID_VENDOR_FROM_DATABASE=Pathway Connectivity, Inc. + +usb:v0C8B* + ID_VENDOR_FROM_DATABASE=Wavefly Corp. + +usb:v0C8C* + ID_VENDOR_FROM_DATABASE=Coactive Networks + +usb:v0C8D* + ID_VENDOR_FROM_DATABASE=Tempo + +usb:v0C8E* + ID_VENDOR_FROM_DATABASE=Cesscom Co., Ltd + +usb:v0C8Ep6000* + ID_MODEL_FROM_DATABASE=Luxian Series + +usb:v0C8F* + ID_VENDOR_FROM_DATABASE=Applied Microsystems + +usb:v0C94* + ID_VENDOR_FROM_DATABASE=Cryptera + +usb:v0C94pA000* + ID_MODEL_FROM_DATABASE=EPP 1217 + +usb:v0C98* + ID_VENDOR_FROM_DATABASE=Berkshire Products, Inc. + +usb:v0C98p1140* + ID_MODEL_FROM_DATABASE=USB PC Watchdog + +usb:v0C99* + ID_VENDOR_FROM_DATABASE=Innochips Co., Ltd + +usb:v0C9A* + ID_VENDOR_FROM_DATABASE=Hanwool Robotics Corp. + +usb:v0C9B* + ID_VENDOR_FROM_DATABASE=Jobin Yvon, Inc. + +usb:v0C9D* + ID_VENDOR_FROM_DATABASE=SemTek + +usb:v0C9Dp0170* + ID_MODEL_FROM_DATABASE=3873 Manual Insert card reader + +usb:v0CA2* + ID_VENDOR_FROM_DATABASE=Zyfer + +usb:v0CA3* + ID_VENDOR_FROM_DATABASE=Sega Corp. + +usb:v0CA4* + ID_VENDOR_FROM_DATABASE=ST&T Instrument Corp. + +usb:v0CA5* + ID_VENDOR_FROM_DATABASE=BAE Systems Canada, Inc. + +usb:v0CA6* + ID_VENDOR_FROM_DATABASE=Castles Technology Co., Ltd + +usb:v0CA6p0010* + ID_MODEL_FROM_DATABASE=EZUSB PC/SC Smart Card Reader + +usb:v0CA6p0050* + ID_MODEL_FROM_DATABASE=EZ220PU Reader Controller + +usb:v0CA6p1077* + ID_MODEL_FROM_DATABASE=Bludrive Family Smart Card Reader + +usb:v0CA6p107E* + ID_MODEL_FROM_DATABASE=Reader Controller + +usb:v0CA6p2010* + ID_MODEL_FROM_DATABASE=myPad110 PC/SC Smart Card Reader + +usb:v0CA6p3050* + ID_MODEL_FROM_DATABASE=EZ710 Smart Card Reader + +usb:v0CA7* + ID_VENDOR_FROM_DATABASE=Information Systems Laboratories + +usb:v0CAD* + ID_VENDOR_FROM_DATABASE=Motorola CGISS + +usb:v0CADp1007* + ID_MODEL_FROM_DATABASE=APX Series Consolette + +usb:v0CADp1020* + ID_MODEL_FROM_DATABASE=MOTOTRBO Series Radio (Portable) + +usb:v0CADp1030* + ID_MODEL_FROM_DATABASE=APX Series Radio (Portable) + +usb:v0CADp1031* + ID_MODEL_FROM_DATABASE=APX Series Radio (Mobile) + +usb:v0CADp1602* + ID_MODEL_FROM_DATABASE=IMPRES Battery Data Reader + +usb:v0CADp9001* + ID_MODEL_FROM_DATABASE=PowerPad Pocket PC Device + +usb:v0CAE* + ID_VENDOR_FROM_DATABASE=Ascom Business Systems, Ltd + +usb:v0CAF* + ID_VENDOR_FROM_DATABASE=Buslink + +usb:v0CAFp2507* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller + +usb:v0CAFp2515* + ID_MODEL_FROM_DATABASE=Flash Disk Embedded Hub + +usb:v0CAFp2516* + ID_MODEL_FROM_DATABASE=Flash Disk Security Device + +usb:v0CAFp2517* + ID_MODEL_FROM_DATABASE=Flash Disk Mass Storage Device + +usb:v0CAFp25C7* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller + +usb:v0CAFp3A00* + ID_MODEL_FROM_DATABASE=Hard Drive + +usb:v0CAFp3A20* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0CAFp3ACD* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0CB0* + ID_VENDOR_FROM_DATABASE=Flying Pig Systems + +usb:v0CB1* + ID_VENDOR_FROM_DATABASE=Innovonics, Inc. + +usb:v0CB6* + ID_VENDOR_FROM_DATABASE=Celestix Networks, Pte., Ltd + +usb:v0CB7* + ID_VENDOR_FROM_DATABASE=Singatron Enterprise Co., Ltd + +usb:v0CB8* + ID_VENDOR_FROM_DATABASE=Opticis Co., Ltd + +usb:v0CBA* + ID_VENDOR_FROM_DATABASE=Trust Electronic (Shanghai) Co., Ltd + +usb:v0CBB* + ID_VENDOR_FROM_DATABASE=Shanghai Darong Electronics Co., Ltd + +usb:v0CBC* + ID_VENDOR_FROM_DATABASE=Palmax Technology Co., Ltd + +usb:v0CBCp0101* + ID_MODEL_FROM_DATABASE=Pocket PC P6C + +usb:v0CBCp0201* + ID_MODEL_FROM_DATABASE=Personal Digital Assistant + +usb:v0CBCp0301* + ID_MODEL_FROM_DATABASE=Personal Digital Assistant P6M+ + +usb:v0CBCp0401* + ID_MODEL_FROM_DATABASE=Pocket PC + +usb:v0CBD* + ID_VENDOR_FROM_DATABASE=Pentel Co., Ltd (Electronics Equipment Div.) + +usb:v0CBE* + ID_VENDOR_FROM_DATABASE=Keryx Technologies, Inc. + +usb:v0CBF* + ID_VENDOR_FROM_DATABASE=Union Genius Computer Co., Ltd + +usb:v0CC0* + ID_VENDOR_FROM_DATABASE=Kuon Yi Industrial Corp. + +usb:v0CC1* + ID_VENDOR_FROM_DATABASE=Given Imaging, Ltd + +usb:v0CC2* + ID_VENDOR_FROM_DATABASE=Timex Corp. + +usb:v0CC3* + ID_VENDOR_FROM_DATABASE=Rimage Corp. + +usb:v0CC4* + ID_VENDOR_FROM_DATABASE=emsys GmbH + +usb:v0CC5* + ID_VENDOR_FROM_DATABASE=Sendo + +usb:v0CC6* + ID_VENDOR_FROM_DATABASE=Intermagic Corp. + +usb:v0CC8* + ID_VENDOR_FROM_DATABASE=Technotools Corp. + +usb:v0CC9* + ID_VENDOR_FROM_DATABASE=BroadMAX Technologies, Inc. + +usb:v0CCA* + ID_VENDOR_FROM_DATABASE=Amphenol + +usb:v0CCB* + ID_VENDOR_FROM_DATABASE=SKNet Co., Ltd + +usb:v0CCC* + ID_VENDOR_FROM_DATABASE=Domex Technology Corp. + +usb:v0CCD* + ID_VENDOR_FROM_DATABASE=TerraTec Electronic GmbH + +usb:v0CCDp0012* + ID_MODEL_FROM_DATABASE=PHASE 26 + +usb:v0CCDp0013* + ID_MODEL_FROM_DATABASE=PHASE 26 + +usb:v0CCDp0014* + ID_MODEL_FROM_DATABASE=PHASE 26 + +usb:v0CCDp0015* + ID_MODEL_FROM_DATABASE=Flash Update for TerraTec PHASE 26 + +usb:v0CCDp0021* + ID_MODEL_FROM_DATABASE=Cameo Grabster 200 + +usb:v0CCDp0023* + ID_MODEL_FROM_DATABASE=Mystify Claw + +usb:v0CCDp0028* + ID_MODEL_FROM_DATABASE=Aureon 5.1 MkII + +usb:v0CCDp0032* + ID_MODEL_FROM_DATABASE=MIDI HUBBLE + +usb:v0CCDp0035* + ID_MODEL_FROM_DATABASE=Miditech Play'n Roll + +usb:v0CCDp0036* + ID_MODEL_FROM_DATABASE=Cinergy 250 Audio + +usb:v0CCDp0037* + ID_MODEL_FROM_DATABASE=Cinergy 250 Audio + +usb:v0CCDp0038* + ID_MODEL_FROM_DATABASE=Cinergy T² DVB-T Receiver + +usb:v0CCDp0039* + ID_MODEL_FROM_DATABASE=Grabster AV 400 + +usb:v0CCDp003B* + ID_MODEL_FROM_DATABASE=Cinergy 400 + +usb:v0CCDp003C* + ID_MODEL_FROM_DATABASE=Grabster AV 250 + +usb:v0CCDp0042* + ID_MODEL_FROM_DATABASE=Cinergy Hybrid T XS + +usb:v0CCDp0043* + ID_MODEL_FROM_DATABASE=Cinergy T XS + +usb:v0CCDp004E* + ID_MODEL_FROM_DATABASE=Cinergy T XS + +usb:v0CCDp004F* + ID_MODEL_FROM_DATABASE=Cinergy Analog XS + +usb:v0CCDp0055* + ID_MODEL_FROM_DATABASE=Cinergy T XE (Version 1, AF9005) + +usb:v0CCDp005C* + ID_MODEL_FROM_DATABASE=Cinergy T² + +usb:v0CCDp0069* + ID_MODEL_FROM_DATABASE=Cinergy T XE (Version 2, AF9015) + +usb:v0CCDp006B* + ID_MODEL_FROM_DATABASE=Cinergy HT PVR (EU) + +usb:v0CCDp0072* + ID_MODEL_FROM_DATABASE=Cinergy Hybrid T + +usb:v0CCDp0077* + ID_MODEL_FROM_DATABASE=Aureon Dual USB + +usb:v0CCDp0078* + ID_MODEL_FROM_DATABASE=Cinergy T XXS + +usb:v0CCDp0086* + ID_MODEL_FROM_DATABASE=Cinergy Hybrid XE + +usb:v0CCDp008E* + ID_MODEL_FROM_DATABASE=Cinergy HTC XS + +usb:v0CCDp0096* + ID_MODEL_FROM_DATABASE=Grabby + +usb:v0CCDp0097* + ID_MODEL_FROM_DATABASE=Cinergy T RC MKII + +usb:v0CCDp0099* + ID_MODEL_FROM_DATABASE=AfaTech 9015 [Cinergy T Stick Dual] + +usb:v0CCDp00A5* + ID_MODEL_FROM_DATABASE=Cinergy Hybrid Stick + +usb:v0CCDp00A9* + ID_MODEL_FROM_DATABASE=RTL2838 DVB-T COFDM Demodulator [TerraTec Cinergy T Stick Black] + +usb:v0CCDp00B3* + ID_MODEL_FROM_DATABASE=NOXON DAB/DAB+ Stick + +usb:v0CCDp00E0* + ID_MODEL_FROM_DATABASE=NOXON DAB/DAB+ Stick V2 + +usb:v0CCDp0102* + ID_MODEL_FROM_DATABASE=Cinergy S2 Stick + +usb:v0CCDp0105* + ID_MODEL_FROM_DATABASE=Cinergy S2 Box + +usb:v0CCDp10A7* + ID_MODEL_FROM_DATABASE=TerraTec G3 + +usb:v0CD4* + ID_VENDOR_FROM_DATABASE=Bang Olufsen + +usb:v0CD4p0101* + ID_MODEL_FROM_DATABASE=BeolinkPC2 + +usb:v0CD5* + ID_VENDOR_FROM_DATABASE=LabJack Corporation + +usb:v0CD5p0003* + ID_MODEL_FROM_DATABASE=U3 + +usb:v0CD5p0009* + ID_MODEL_FROM_DATABASE=UE9 + +usb:v0CD6* + ID_VENDOR_FROM_DATABASE=Scheidt & Bachmann + +usb:v0CD6p000C* + ID_MODEL_FROM_DATABASE=S&B TPU + +usb:v0CD6p000E* + ID_MODEL_FROM_DATABASE=S&B BKV + +usb:v0CD6p0011* + ID_MODEL_FROM_DATABASE=Money Coin Unit + +usb:v0CD7* + ID_VENDOR_FROM_DATABASE=NewChip S.r.l. + +usb:v0CD8* + ID_VENDOR_FROM_DATABASE=JS Digitech, Inc. + +usb:v0CD8p2007* + ID_MODEL_FROM_DATABASE=Smart Card Reader/JSTU-9700 + +usb:v0CD9* + ID_VENDOR_FROM_DATABASE=Hitachi Shin Din Cable, Ltd + +usb:v0CDE* + ID_VENDOR_FROM_DATABASE=Z-Com + +usb:v0CDEp0001* + ID_MODEL_FROM_DATABASE=XI-750 802.11b Wireless Adapter [Atmel AT76C503A] + +usb:v0CDEp0002* + ID_MODEL_FROM_DATABASE=XI-725/726 Prism2.5 802.11b Adapter + +usb:v0CDEp0003* + ID_MODEL_FROM_DATABASE=Sagem 802.11b Dongle + +usb:v0CDEp0004* + ID_MODEL_FROM_DATABASE=Sagem 802.11b Dongle + +usb:v0CDEp0005* + ID_MODEL_FROM_DATABASE=XI-735 Prism3 802.11b Adapter + +usb:v0CDEp0006* + ID_MODEL_FROM_DATABASE=XG-300 802.11b Adapter + +usb:v0CDEp0008* + ID_MODEL_FROM_DATABASE=XG-703A 802.11g Wireless Adapter [Intersil ISL3887] + +usb:v0CDEp0009* + ID_MODEL_FROM_DATABASE=(ZD1211)IEEE 802.11b+g Adapter + +usb:v0CDEp0011* + ID_MODEL_FROM_DATABASE=ZD1211 + +usb:v0CDEp0012* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v0CDEp0013* + ID_MODEL_FROM_DATABASE=AR5523 driver (no firmware) + +usb:v0CDEp0014* + ID_MODEL_FROM_DATABASE=NB 802.11g Wireless LAN Adapter(3887A) + +usb:v0CDEp0015* + ID_MODEL_FROM_DATABASE=XG-705A 802.11g Wireless Adapter [Intersil ISL3887] + +usb:v0CDEp0016* + ID_MODEL_FROM_DATABASE=NB 802.11g Wireless LAN Adapter(3887A) + +usb:v0CDEp0018* + ID_MODEL_FROM_DATABASE=NB 802.11a/b/g Wireless LAN Adapter(3887A) + +usb:v0CDEp001A* + ID_MODEL_FROM_DATABASE=802.11bg + +usb:v0CDEp001C* + ID_MODEL_FROM_DATABASE=802.11b/g Wireless Network Adapter + +usb:v0CDEp0020* + ID_MODEL_FROM_DATABASE=AG-760A 802.11abg Wireless Adapter [ZyDAS ZD1211B] + +usb:v0CDEp0022* + ID_MODEL_FROM_DATABASE=802.11b/g/n Wireless Network Adapter + +usb:v0CDEp0023* + ID_MODEL_FROM_DATABASE=UB81 802.11bgn + +usb:v0CDEp0025* + ID_MODEL_FROM_DATABASE=802.11b/g/n USB Wireless Network Adapter + +usb:v0CDEp0026* + ID_MODEL_FROM_DATABASE=UB82 802.11abgn + +usb:v0CDEp0027* + ID_MODEL_FROM_DATABASE=Sphairon Homelink 1202 802.11n Wireless Adapter [Atheros AR9170] + +usb:v0CE5* + ID_VENDOR_FROM_DATABASE=Validation Technologies International + +usb:v0CE5p0003* + ID_MODEL_FROM_DATABASE=Matrix + +usb:v0CE9* + ID_VENDOR_FROM_DATABASE=Pico Technology + +usb:v0CE9p1001* + ID_MODEL_FROM_DATABASE=PicoScope3000 series PC Oscilloscope + +usb:v0CE9p1007* + ID_MODEL_FROM_DATABASE=PicoScope 2000 series PC Oscilloscope + +usb:v0CE9p1008* + ID_MODEL_FROM_DATABASE=PicoScope 5000 series PC Oscilloscope + +usb:v0CE9p1009* + ID_MODEL_FROM_DATABASE=PicoScope 4000 series PC Oscilloscope + +usb:v0CE9p100E* + ID_MODEL_FROM_DATABASE=PicoScope 6000 series PC Oscilloscope + +usb:v0CE9p1012* + ID_MODEL_FROM_DATABASE=PicoScope 3000A series PC Oscilloscope + +usb:v0CE9p1016* + ID_MODEL_FROM_DATABASE=PicoScope 2000A series PC Oscilloscope + +usb:v0CE9p1018* + ID_MODEL_FROM_DATABASE=PicoScope 4000A series PC Oscilloscope + +usb:v0CE9p1200* + ID_MODEL_FROM_DATABASE=PicoScope 2000 series PC Oscilloscope + +usb:v0CE9p1201* + ID_MODEL_FROM_DATABASE=PicoScope 3000 series PC Oscilloscope + +usb:v0CE9p1202* + ID_MODEL_FROM_DATABASE=PicoScope 4000 series PC Oscilloscope + +usb:v0CE9p1203* + ID_MODEL_FROM_DATABASE=PicoScope 5000 series PC Oscilloscope + +usb:v0CE9p1204* + ID_MODEL_FROM_DATABASE=PicoScope 6000 series PC Oscilloscope + +usb:v0CE9p1211* + ID_MODEL_FROM_DATABASE=PicoScope 3000 series PC Oscilloscope + +usb:v0CE9p1212* + ID_MODEL_FROM_DATABASE=PicoScope 4000 series PC Oscilloscope + +usb:v0CF1* + ID_VENDOR_FROM_DATABASE=e-Conn Electronic Co., Ltd + +usb:v0CF2* + ID_VENDOR_FROM_DATABASE=ENE Technology, Inc. + +usb:v0CF2p6220* + ID_MODEL_FROM_DATABASE=SD Card Reader (SG361) + +usb:v0CF2p6225* + ID_MODEL_FROM_DATABASE=SD card reader (UB6225) + +usb:v0CF2p6230* + ID_MODEL_FROM_DATABASE=SD Card Reader (UB623X) + +usb:v0CF2p6250* + ID_MODEL_FROM_DATABASE=SD card reader (UB6250) + +usb:v0CF3* + ID_VENDOR_FROM_DATABASE=Qualcomm Atheros Communications + +usb:v0CF3p0001* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v0CF3p0002* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v0CF3p0003* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v0CF3p0004* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v0CF3p0005* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v0CF3p0006* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v0CF3p1001* + ID_MODEL_FROM_DATABASE=Thomson TG121N [Atheros AR9001U-(2)NG] + +usb:v0CF3p1002* + ID_MODEL_FROM_DATABASE=TP-Link TL-WN821N v2 / TL-WN822N v1 802.11n [Atheros AR9170] + +usb:v0CF3p1006* + ID_MODEL_FROM_DATABASE=TP-Link TL-WN322G v3 / TL-WN422G v2 802.11g [Atheros AR9271] + +usb:v0CF3p1010* + ID_MODEL_FROM_DATABASE=3Com 3CRUSBN275 802.11abgn Wireless Adapter [Atheros AR9170] + +usb:v0CF3p20FF* + ID_MODEL_FROM_DATABASE=AR7010 (no firmware) + +usb:v0CF3p3000* + ID_MODEL_FROM_DATABASE=AR3011 Bluetooth (no firmware) + +usb:v0CF3p3002* + ID_MODEL_FROM_DATABASE=AR3011 Bluetooth + +usb:v0CF3p3004* + ID_MODEL_FROM_DATABASE=AR3012 Bluetooth 4.0 + +usb:v0CF3p3005* + ID_MODEL_FROM_DATABASE=AR3011 Bluetooth + +usb:v0CF3p3007* + ID_MODEL_FROM_DATABASE=AR3012 Bluetooth 4.0 (no firmware) + +usb:v0CF3p3008* + ID_MODEL_FROM_DATABASE=Bluetooth (AR3011) + +usb:v0CF3p311F* + ID_MODEL_FROM_DATABASE=AR3012 Bluetooth + +usb:v0CF3p7015* + ID_MODEL_FROM_DATABASE=TP-Link TL-WN821N v3 / TL-WN822N v2 802.11n [Atheros AR7010+AR9287] + +usb:v0CF3p9170* + ID_MODEL_FROM_DATABASE=AR9170 802.11n + +usb:v0CF3p9271* + ID_MODEL_FROM_DATABASE=AR9271 802.11n + +usb:v0CF3pB002* + ID_MODEL_FROM_DATABASE=Ubiquiti WiFiStation 802.11n [Atheros AR9271] + +usb:v0CF3pB003* + ID_MODEL_FROM_DATABASE=Ubiquiti WiFiStationEXT 802.11n [Atheros AR9271] + +usb:v0CF3pE006* + ID_MODEL_FROM_DATABASE=Dell Wireless 1802 Bluetooth 4.0 LE + +usb:v0CF4* + ID_VENDOR_FROM_DATABASE=Fomtex Corp. + +usb:v0CF5* + ID_VENDOR_FROM_DATABASE=Cellink Co., Ltd + +usb:v0CF6* + ID_VENDOR_FROM_DATABASE=Compucable Corp. + +usb:v0CF7* + ID_VENDOR_FROM_DATABASE=ishoni Networks + +usb:v0CF8* + ID_VENDOR_FROM_DATABASE=Clarisys, Inc. + +usb:v0CF8p0750* + ID_MODEL_FROM_DATABASE=Claritel-i750 - vp + +usb:v0CF9* + ID_VENDOR_FROM_DATABASE=Central System Research Co., Ltd + +usb:v0CFA* + ID_VENDOR_FROM_DATABASE=Inviso, Inc. + +usb:v0CFC* + ID_VENDOR_FROM_DATABASE=Minolta-QMS, Inc. + +usb:v0CFCp2301* + ID_MODEL_FROM_DATABASE=Magicolor 2300 DL + +usb:v0CFCp2350* + ID_MODEL_FROM_DATABASE=Magicolor 2350EN/3300 + +usb:v0CFCp3100* + ID_MODEL_FROM_DATABASE=Magicolor 3100 + +usb:v0CFCp7300* + ID_MODEL_FROM_DATABASE=Magicolor 5450/5550 + +usb:v0CFF* + ID_VENDOR_FROM_DATABASE=SAFA MEDIA Co., Ltd. + +usb:v0CFFp0320* + ID_MODEL_FROM_DATABASE=SR-380N + +usb:v0D06* + ID_VENDOR_FROM_DATABASE=telos EDV Systementwicklung GmbH + +usb:v0D08* + ID_VENDOR_FROM_DATABASE=UTStarcom + +usb:v0D08p0602* + ID_MODEL_FROM_DATABASE=DV007 [serial] + +usb:v0D08p0603* + ID_MODEL_FROM_DATABASE=DV007 [storage] + +usb:v0D0B* + ID_VENDOR_FROM_DATABASE=Contemporary Controls + +usb:v0D0C* + ID_VENDOR_FROM_DATABASE=Astron Electronics Co., Ltd + +usb:v0D0D* + ID_VENDOR_FROM_DATABASE=MKNet Corp. + +usb:v0D0E* + ID_VENDOR_FROM_DATABASE=Hybrid Networks, Inc. + +usb:v0D0F* + ID_VENDOR_FROM_DATABASE=Feng Shin Cable Co., Ltd + +usb:v0D10* + ID_VENDOR_FROM_DATABASE=Elastic Networks + +usb:v0D10p0001* + ID_MODEL_FROM_DATABASE=StormPort (WDM) + +usb:v0D11* + ID_VENDOR_FROM_DATABASE=Maspro Denkoh Corp. + +usb:v0D12* + ID_VENDOR_FROM_DATABASE=Hansol Electronics, Inc. + +usb:v0D13* + ID_VENDOR_FROM_DATABASE=BMF Corp. + +usb:v0D14* + ID_VENDOR_FROM_DATABASE=Array Comm, Inc. + +usb:v0D15* + ID_VENDOR_FROM_DATABASE=OnStream b.v. + +usb:v0D16* + ID_VENDOR_FROM_DATABASE=Hi-Touch Imaging Technologies Co., Ltd + +usb:v0D16p0001* + ID_MODEL_FROM_DATABASE=PhotoShuttle + +usb:v0D16p0002* + ID_MODEL_FROM_DATABASE=Photo Printer 730 series + +usb:v0D16p0004* + ID_MODEL_FROM_DATABASE=Photo Printer 63xPL/PS + +usb:v0D16p000E* + ID_MODEL_FROM_DATABASE=P910L + +usb:v0D16p0100* + ID_MODEL_FROM_DATABASE=Photo Printer 63xPL/PS + +usb:v0D16p0102* + ID_MODEL_FROM_DATABASE=Photo Printer 64xPS + +usb:v0D16p0103* + ID_MODEL_FROM_DATABASE=Photo Printer 730 series + +usb:v0D16p0104* + ID_MODEL_FROM_DATABASE=Photo Printer 63xPL/PS + +usb:v0D16p0105* + ID_MODEL_FROM_DATABASE=Photo Printer 64xPS + +usb:v0D16p0200* + ID_MODEL_FROM_DATABASE=Photo Printer 64xDL + +usb:v0D17* + ID_VENDOR_FROM_DATABASE=NALTEC, Inc. + +usb:v0D18* + ID_VENDOR_FROM_DATABASE=coaXmedia + +usb:v0D19* + ID_VENDOR_FROM_DATABASE=Hank Connection Industrial Co., Ltd + +usb:v0D28* + ID_VENDOR_FROM_DATABASE=NXP + +usb:v0D28p0204* + ID_MODEL_FROM_DATABASE=ARM mbed + +usb:v0D32* + ID_VENDOR_FROM_DATABASE=Leo Hui Electric Wire & Cable Co., Ltd + +usb:v0D33* + ID_VENDOR_FROM_DATABASE=AirSpeak, Inc. + +usb:v0D34* + ID_VENDOR_FROM_DATABASE=Rearden Steel Technologies + +usb:v0D35* + ID_VENDOR_FROM_DATABASE=Dah Kun Co., Ltd + +usb:v0D3A* + ID_VENDOR_FROM_DATABASE=Posiflex Technologies, Inc. + +usb:v0D3Ap0206* + ID_MODEL_FROM_DATABASE=Series 3xxx Cash Drawer + +usb:v0D3Ap0207* + ID_MODEL_FROM_DATABASE=Series 3xxx Cash Drawer + +usb:v0D3Ap0500* + ID_MODEL_FROM_DATABASE=Magnetic Stripe Reader + +usb:v0D3C* + ID_VENDOR_FROM_DATABASE=Sri Cable Technology, Ltd + +usb:v0D3D* + ID_VENDOR_FROM_DATABASE=Tangtop Technology Co., Ltd + +usb:v0D3Dp0001* + ID_MODEL_FROM_DATABASE=HID Keyboard + +usb:v0D3Dp0040* + ID_MODEL_FROM_DATABASE=PS/2 Adapter + +usb:v0D3E* + ID_VENDOR_FROM_DATABASE=Fitcom, inc. + +usb:v0D3F* + ID_VENDOR_FROM_DATABASE=MTS Systems Corp. + +usb:v0D40* + ID_VENDOR_FROM_DATABASE=Ascor, Inc. + +usb:v0D41* + ID_VENDOR_FROM_DATABASE=Ta Yun Terminals Industrial Co., Ltd + +usb:v0D42* + ID_VENDOR_FROM_DATABASE=Full Der Co., Ltd + +usb:v0D46* + ID_VENDOR_FROM_DATABASE=Kobil Systems GmbH + +usb:v0D46p2012* + ID_MODEL_FROM_DATABASE=KAAN Standard Plus (Smartcard reader) + +usb:v0D46p3003* + ID_MODEL_FROM_DATABASE=mIDentity Light / KAAN SIM III + +usb:v0D46p3014* + ID_MODEL_FROM_DATABASE=Smart Token + +usb:v0D46p4000* + ID_MODEL_FROM_DATABASE=mIDentity (mass storage) + +usb:v0D46p4001* + ID_MODEL_FROM_DATABASE=mIDentity Basic/Classic (composite device) + +usb:v0D46p4081* + ID_MODEL_FROM_DATABASE=mIDentity Basic/Classic (installationless) + +usb:v0D48* + ID_VENDOR_FROM_DATABASE=Promethean Limited + +usb:v0D48p0001* + ID_MODEL_FROM_DATABASE=ACTIVboard + +usb:v0D48p0004* + ID_MODEL_FROM_DATABASE=ACTIVboard + +usb:v0D48p0100* + ID_MODEL_FROM_DATABASE=Audio + +usb:v0D49* + ID_VENDOR_FROM_DATABASE=Maxtor + +usb:v0D49p3000* + ID_MODEL_FROM_DATABASE=Drive + +usb:v0D49p3010* + ID_MODEL_FROM_DATABASE=3000LE Drive + +usb:v0D49p3100* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-IDE Bridge Controller + +usb:v0D49p3200* + ID_MODEL_FROM_DATABASE=Personal Storage 3200 + +usb:v0D49p5000* + ID_MODEL_FROM_DATABASE=5000XT Drive + +usb:v0D49p5010* + ID_MODEL_FROM_DATABASE=5000LE Drive + +usb:v0D49p5020* + ID_MODEL_FROM_DATABASE=Mobile Hard Disk Drive + +usb:v0D49p7000* + ID_MODEL_FROM_DATABASE=OneTouch + +usb:v0D49p7010* + ID_MODEL_FROM_DATABASE=OneTouch + +usb:v0D49p7100* + ID_MODEL_FROM_DATABASE=OneTouch II 300GB External Hard Disk + +usb:v0D49p7310* + ID_MODEL_FROM_DATABASE=OneTouch 4 + +usb:v0D49p7410* + ID_MODEL_FROM_DATABASE=Mobile Hard Disk Drive (1TB) + +usb:v0D49p7450* + ID_MODEL_FROM_DATABASE=Basics Portable USB Device + +usb:v0D4A* + ID_VENDOR_FROM_DATABASE=NF Corp. + +usb:v0D4B* + ID_VENDOR_FROM_DATABASE=Grape Systems, Inc. + +usb:v0D4C* + ID_VENDOR_FROM_DATABASE=Tedas AG + +usb:v0D4D* + ID_VENDOR_FROM_DATABASE=Coherent, Inc. + +usb:v0D4E* + ID_VENDOR_FROM_DATABASE=Agere Systems Netherland BV + +usb:v0D4Ep047A* + ID_MODEL_FROM_DATABASE=WLAN Card + +usb:v0D4Ep1000* + ID_MODEL_FROM_DATABASE=Wireless Card Model 0801 + +usb:v0D4Ep1001* + ID_MODEL_FROM_DATABASE=Wireless Card Model 0802 + +usb:v0D4F* + ID_VENDOR_FROM_DATABASE=EADS Airbus France + +usb:v0D50* + ID_VENDOR_FROM_DATABASE=Cleware GmbH + +usb:v0D50p0011* + ID_MODEL_FROM_DATABASE=USB-Temp2 Thermometer + +usb:v0D50p0040* + ID_MODEL_FROM_DATABASE=F4 foot switch + +usb:v0D51* + ID_VENDOR_FROM_DATABASE=Volex (Asia) Pte., Ltd + +usb:v0D53* + ID_VENDOR_FROM_DATABASE=HMI Co., Ltd + +usb:v0D54* + ID_VENDOR_FROM_DATABASE=Holon Corp. + +usb:v0D55* + ID_VENDOR_FROM_DATABASE=ASKA Technologies, Inc. + +usb:v0D56* + ID_VENDOR_FROM_DATABASE=AVLAB Technology, Inc. + +usb:v0D57* + ID_VENDOR_FROM_DATABASE=Solomon Microtech, Ltd + +usb:v0D5C* + ID_VENDOR_FROM_DATABASE=SMC Networks, Inc. + +usb:v0D5CpA001* + ID_MODEL_FROM_DATABASE=SMC2662W (v1) EZ Connect 802.11b Wireless Adapter [Atmel AT76C503A] + +usb:v0D5CpA002* + ID_MODEL_FROM_DATABASE=SMC2662W v2 / SMC2662W-AR / Belkin F5D6050 [Atmel at76c503a] + +usb:v0D5E* + ID_VENDOR_FROM_DATABASE=Myacom, Ltd + +usb:v0D5Ep2346* + ID_MODEL_FROM_DATABASE=BT Digital Access adapter + +usb:v0D5F* + ID_VENDOR_FROM_DATABASE=CSI, Inc. + +usb:v0D60* + ID_VENDOR_FROM_DATABASE=IVL Technologies, Ltd + +usb:v0D61* + ID_VENDOR_FROM_DATABASE=Meilu Electronics (Shenzhen) Co., Ltd + +usb:v0D62* + ID_VENDOR_FROM_DATABASE=Darfon Electronics Corp. + +usb:v0D62p0003* + ID_MODEL_FROM_DATABASE=Smartcard Reader + +usb:v0D62p0004* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0D62p001B* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v0D62p001C* + ID_MODEL_FROM_DATABASE=Benq X120 Internet Keyboard Pro + +usb:v0D62p0306* + ID_MODEL_FROM_DATABASE=M530 Mouse + +usb:v0D62p0800* + ID_MODEL_FROM_DATABASE=Magic Wheel + +usb:v0D62p2021* + ID_MODEL_FROM_DATABASE=AM805 Keyboard + +usb:v0D62p2026* + ID_MODEL_FROM_DATABASE=TECOM Bluetooth Device + +usb:v0D62p2050* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v0D62p2106* + ID_MODEL_FROM_DATABASE=Dell L20U Multimedia Keyboard + +usb:v0D62pA100* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v0D63* + ID_VENDOR_FROM_DATABASE=Fritz Gegauf AG + +usb:v0D64* + ID_VENDOR_FROM_DATABASE=DXG Technology Corp. + +usb:v0D64p0105* + ID_MODEL_FROM_DATABASE=Dual Mode Digital Camera 1.3M + +usb:v0D64p0107* + ID_MODEL_FROM_DATABASE=Horus MT-409 Camera + +usb:v0D64p0108* + ID_MODEL_FROM_DATABASE=Dual Mode Digital Camera + +usb:v0D64p0202* + ID_MODEL_FROM_DATABASE=Dual Mode Video Camera Device + +usb:v0D64p0303* + ID_MODEL_FROM_DATABASE=DXG-305V Camera + +usb:v0D64p1001* + ID_MODEL_FROM_DATABASE=SiPix Stylecam/UMAX AstraPix 320s + +usb:v0D64p1002* + ID_MODEL_FROM_DATABASE=Fashion Cam 01 Dual-Mode DSC (Video Camera) + +usb:v0D64p1003* + ID_MODEL_FROM_DATABASE=Fashion Cam Dual-Mode DSC (Controller) + +usb:v0D64p1021* + ID_MODEL_FROM_DATABASE=D-Link DSC 350F + +usb:v0D64p1208* + ID_MODEL_FROM_DATABASE=Dual Mode Still Camera Device + +usb:v0D64p2208* + ID_MODEL_FROM_DATABASE=Mass Storage + +usb:v0D64p3105* + ID_MODEL_FROM_DATABASE=Dual Mode Digital Camera Disk + +usb:v0D64p3108* + ID_MODEL_FROM_DATABASE=Digicam Mass Storage Device + +usb:v0D64p5566* + ID_MODEL_FROM_DATABASE=Contour Roam Model 1600 + +usb:v0D65* + ID_VENDOR_FROM_DATABASE=KMJP Co., Ltd + +usb:v0D66* + ID_VENDOR_FROM_DATABASE=TMT + +usb:v0D67* + ID_VENDOR_FROM_DATABASE=Advanet, Inc. + +usb:v0D68* + ID_VENDOR_FROM_DATABASE=Super Link Electronics Co., Ltd + +usb:v0D69* + ID_VENDOR_FROM_DATABASE=NSI + +usb:v0D6A* + ID_VENDOR_FROM_DATABASE=Megapower International Corp. + +usb:v0D6B* + ID_VENDOR_FROM_DATABASE=And-Or Logic + +usb:v0D70* + ID_VENDOR_FROM_DATABASE=Try Computer Co., Ltd + +usb:v0D71* + ID_VENDOR_FROM_DATABASE=Hirakawa Hewtech Corp. + +usb:v0D72* + ID_VENDOR_FROM_DATABASE=Winmate Communication, Inc. + +usb:v0D73* + ID_VENDOR_FROM_DATABASE=Hit's Communications, Inc. + +usb:v0D76* + ID_VENDOR_FROM_DATABASE=MFP Korea, Inc. + +usb:v0D77* + ID_VENDOR_FROM_DATABASE=Power Sentry/Newpoint + +usb:v0D78* + ID_VENDOR_FROM_DATABASE=Japan Distributor Corp. + +usb:v0D7A* + ID_VENDOR_FROM_DATABASE=MARX Datentechnik GmbH + +usb:v0D7Ap0001* + ID_MODEL_FROM_DATABASE=CrypToken + +usb:v0D7B* + ID_VENDOR_FROM_DATABASE=Wellco Technology Co., Ltd + +usb:v0D7C* + ID_VENDOR_FROM_DATABASE=Taiwan Line Tek Electronic Co., Ltd + +usb:v0D7D* + ID_VENDOR_FROM_DATABASE=Phison Electronics Corp. + +usb:v0D7Dp0100* + ID_MODEL_FROM_DATABASE=PS1001/1011/1006/1026 Flash Disk + +usb:v0D7Dp0110* + ID_MODEL_FROM_DATABASE=Gigabyte FlexDrive + +usb:v0D7Dp0120* + ID_MODEL_FROM_DATABASE=Disk Pro 64MB + +usb:v0D7Dp0124* + ID_MODEL_FROM_DATABASE=GIGABYTE Disk + +usb:v0D7Dp0240* + ID_MODEL_FROM_DATABASE=I/O-Magic/Transcend 6-in-1 Card Reader + +usb:v0D7Dp110E* + ID_MODEL_FROM_DATABASE=NEC uPD720121/130 USB-ATA/ATAPI Bridge + +usb:v0D7Dp1240* + ID_MODEL_FROM_DATABASE=Apacer 6-in-1 Card Reader 2.0 + +usb:v0D7Dp1270* + ID_MODEL_FROM_DATABASE=Wolverine SixPac 6000 + +usb:v0D7Dp1300* + ID_MODEL_FROM_DATABASE=Flash Disk + +usb:v0D7Dp1320* + ID_MODEL_FROM_DATABASE=PS2031 Flash Disk + +usb:v0D7Dp1400* + ID_MODEL_FROM_DATABASE=Attache 256MB USB 2.0 Flash Drive + +usb:v0D7Dp1420* + ID_MODEL_FROM_DATABASE=PS2044 Pen Drive + +usb:v0D7Dp1470* + ID_MODEL_FROM_DATABASE=Vosonic X's-Drive II+ VP2160 + +usb:v0D7Dp1620* + ID_MODEL_FROM_DATABASE=USB Disk Pro + +usb:v0D7Dp1900* + ID_MODEL_FROM_DATABASE=USB Thumb Drive + +usb:v0D7E* + ID_VENDOR_FROM_DATABASE=American Computer & Digital Components + +usb:v0D7Ep2507* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller + +usb:v0D7Ep2517* + ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device + +usb:v0D7Ep25C7* + ID_MODEL_FROM_DATABASE=Hi-Speed USB-to-IDE Bridge Controller + +usb:v0D7F* + ID_VENDOR_FROM_DATABASE=Essential Reality LLC + +usb:v0D7Fp0100* + ID_MODEL_FROM_DATABASE=P5 Glove glove controller + +usb:v0D80* + ID_VENDOR_FROM_DATABASE=H.R. Silvine Electronics, Inc. + +usb:v0D81* + ID_VENDOR_FROM_DATABASE=TechnoVision + +usb:v0D83* + ID_VENDOR_FROM_DATABASE=Think Outside, Inc. + +usb:v0D87* + ID_VENDOR_FROM_DATABASE=Dolby Laboratories Inc. + +usb:v0D89* + ID_VENDOR_FROM_DATABASE=Oz Software + +usb:v0D8A* + ID_VENDOR_FROM_DATABASE=King Jim Co., Ltd + +usb:v0D8Ap0101* + ID_MODEL_FROM_DATABASE=TEPRA PRO + +usb:v0D8B* + ID_VENDOR_FROM_DATABASE=Ascom Telecommunications, Ltd + +usb:v0D8C* + ID_VENDOR_FROM_DATABASE=C-Media Electronics, Inc. + +usb:v0D8Cp0001* + ID_MODEL_FROM_DATABASE=Audio Device + +usb:v0D8Cp0002* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v0D8Cp0003* + ID_MODEL_FROM_DATABASE=Sound Device + +usb:v0D8Cp0005* + ID_MODEL_FROM_DATABASE=Blue Snowball + +usb:v0D8Cp0006* + ID_MODEL_FROM_DATABASE=Storm HP-USB500 5.1 Headset + +usb:v0D8Cp000C* + ID_MODEL_FROM_DATABASE=Audio Adapter + +usb:v0D8Cp000D* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v0D8Cp000E* + ID_MODEL_FROM_DATABASE=Audio Adapter (Planet UP-100, Genius G-Talk) + +usb:v0D8Cp0014* + ID_MODEL_FROM_DATABASE=Audio Adapter (Unitek Y-247A) + +usb:v0D8Cp001F* + ID_MODEL_FROM_DATABASE=CM108 Audio Controller + +usb:v0D8Cp0102* + ID_MODEL_FROM_DATABASE=CM106 Like Sound Device + +usb:v0D8Cp0103* + ID_MODEL_FROM_DATABASE=CM102-A+/102S+ Audio Controller + +usb:v0D8Cp0104* + ID_MODEL_FROM_DATABASE=CM103+ Audio Controller + +usb:v0D8Cp0105* + ID_MODEL_FROM_DATABASE=CM108 Audio Controller + +usb:v0D8Cp0107* + ID_MODEL_FROM_DATABASE=CM108 Audio Controller + +usb:v0D8Cp010F* + ID_MODEL_FROM_DATABASE=CM108 Audio Controller + +usb:v0D8Cp0115* + ID_MODEL_FROM_DATABASE=CM108 Audio Controller + +usb:v0D8Cp0139* + ID_MODEL_FROM_DATABASE=Multimedia Headset [Gigaware by Ignition L.P.] + +usb:v0D8Cp013C* + ID_MODEL_FROM_DATABASE=CM108 Audio Controller + +usb:v0D8Cp0201* + ID_MODEL_FROM_DATABASE=CM6501 + +usb:v0D8Cp5000* + ID_MODEL_FROM_DATABASE=Mass Storage Controller + +usb:v0D8Cp5200* + ID_MODEL_FROM_DATABASE=Mass Storage Controller(0D8C,5200) + +usb:v0D8CpB213* + ID_MODEL_FROM_DATABASE=USB Phone CM109 (aka CT2000,VPT1000) + +usb:v0D8D* + ID_VENDOR_FROM_DATABASE=Promotion & Display Technology, Ltd + +usb:v0D8Dp0234* + ID_MODEL_FROM_DATABASE=V-234 Composite Device + +usb:v0D8Dp0550* + ID_MODEL_FROM_DATABASE=V-550 Composite Device + +usb:v0D8Dp0551* + ID_MODEL_FROM_DATABASE=V-551 Composite Device + +usb:v0D8Dp0552* + ID_MODEL_FROM_DATABASE=V-552 Composite Device + +usb:v0D8Dp0651* + ID_MODEL_FROM_DATABASE=V-651 Composite Device + +usb:v0D8Dp0652* + ID_MODEL_FROM_DATABASE=V-652 Composite Device + +usb:v0D8Dp0653* + ID_MODEL_FROM_DATABASE=V-653 Composite Device + +usb:v0D8Dp0654* + ID_MODEL_FROM_DATABASE=V-654 Composite Device + +usb:v0D8Dp0655* + ID_MODEL_FROM_DATABASE=V-655 Composite Device + +usb:v0D8Dp0656* + ID_MODEL_FROM_DATABASE=V-656 Composite Device + +usb:v0D8Dp0657* + ID_MODEL_FROM_DATABASE=V-657 Composite Device + +usb:v0D8Dp0658* + ID_MODEL_FROM_DATABASE=V-658 Composite Device + +usb:v0D8Dp0659* + ID_MODEL_FROM_DATABASE=V-659 Composite Device + +usb:v0D8Dp0660* + ID_MODEL_FROM_DATABASE=V-660 Composite Device + +usb:v0D8Dp0661* + ID_MODEL_FROM_DATABASE=V-661 Composite Device + +usb:v0D8Dp0662* + ID_MODEL_FROM_DATABASE=V-662 Composite Device + +usb:v0D8Dp0850* + ID_MODEL_FROM_DATABASE=V-850 Composite Device + +usb:v0D8Dp0851* + ID_MODEL_FROM_DATABASE=V-851 Composite Device + +usb:v0D8Dp0852* + ID_MODEL_FROM_DATABASE=V-852 Composite Device + +usb:v0D8Dp0901* + ID_MODEL_FROM_DATABASE=V-901 Composite Device + +usb:v0D8Dp0902* + ID_MODEL_FROM_DATABASE=V-902 Composite Device + +usb:v0D8Dp0903* + ID_MODEL_FROM_DATABASE=V-903 Composite Device + +usb:v0D8Dp4754* + ID_MODEL_FROM_DATABASE=Voyager DMP Composite Device + +usb:v0D8DpBB00* + ID_MODEL_FROM_DATABASE=Bloomberg Composite Device + +usb:v0D8DpBB01* + ID_MODEL_FROM_DATABASE=Bloomberg Composite Device + +usb:v0D8DpBB02* + ID_MODEL_FROM_DATABASE=Bloomberg Composite Device + +usb:v0D8DpBB03* + ID_MODEL_FROM_DATABASE=Bloomberg Composite Device + +usb:v0D8DpBB04* + ID_MODEL_FROM_DATABASE=Bloomberg Composite Device + +usb:v0D8DpBB05* + ID_MODEL_FROM_DATABASE=Bloomberg Composite Device + +usb:v0D8DpFFFE* + ID_MODEL_FROM_DATABASE=Global Tuner Composite Device + +usb:v0D8DpFFFF* + ID_MODEL_FROM_DATABASE=Voyager DMP Composite Device + +usb:v0D8E* + ID_VENDOR_FROM_DATABASE=Global Sun Technology, Inc. + +usb:v0D8Ep0163* + ID_MODEL_FROM_DATABASE=802.11g 54 Mbps Wireless Dongle + +usb:v0D8Ep1621* + ID_MODEL_FROM_DATABASE=802.11b Wireless Adapter + +usb:v0D8Ep3762* + ID_MODEL_FROM_DATABASE=Cohiba 802.11g Wireless Mini adapter [Intersil ISL3887] + +usb:v0D8Ep3763* + ID_MODEL_FROM_DATABASE=802.11g Wireless dongle + +usb:v0D8Ep7100* + ID_MODEL_FROM_DATABASE=802.11b Adapter + +usb:v0D8Ep7110* + ID_MODEL_FROM_DATABASE=WL-210 / WU210P 802.11b Wireless Adapter [Atmel AT76C503A] + +usb:v0D8Ep7605* + ID_MODEL_FROM_DATABASE=TRENDnet TEW-224UB 802.11b Wireless Adapter [Atmel AT76C503A] + +usb:v0D8Ep7801* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v0D8Ep7802* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v0D8Ep7811* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v0D8Ep7812* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v0D8Ep7A01* + ID_MODEL_FROM_DATABASE=PRISM25 802.11b Adapter + +usb:v0D8F* + ID_VENDOR_FROM_DATABASE=Pitney Bowes + +usb:v0D90* + ID_VENDOR_FROM_DATABASE=Sure-Fire Electrical Corp. + +usb:v0D96* + ID_VENDOR_FROM_DATABASE=Skanhex Technology, Inc. + +usb:v0D96p0000* + ID_MODEL_FROM_DATABASE=Jenoptik JD350 video + +usb:v0D96p3300* + ID_MODEL_FROM_DATABASE=SX330z Camera + +usb:v0D96p4100* + ID_MODEL_FROM_DATABASE=SX410z Camera + +usb:v0D96p4102* + ID_MODEL_FROM_DATABASE=MD 9700 Camera + +usb:v0D96p4104* + ID_MODEL_FROM_DATABASE=Jenoptik JD-4100z3s + +usb:v0D96p410A* + ID_MODEL_FROM_DATABASE=Medion 9801/Novatech SX-410z + +usb:v0D96p5200* + ID_MODEL_FROM_DATABASE=SX-520z Camera + +usb:v0D97* + ID_VENDOR_FROM_DATABASE=Santa Barbara Instrument Group + +usb:v0D97p0001* + ID_MODEL_FROM_DATABASE=SBIG Astronomy Camera (without firmware) + +usb:v0D97p0101* + ID_MODEL_FROM_DATABASE=SBIG Astronomy Camera (with firmware) + +usb:v0D98* + ID_VENDOR_FROM_DATABASE=Mars Semiconductor Corp. + +usb:v0D98p0300* + ID_MODEL_FROM_DATABASE=Avaya Wireless Card + +usb:v0D98p1007* + ID_MODEL_FROM_DATABASE=Discovery Kids Digital Camera + +usb:v0D99* + ID_VENDOR_FROM_DATABASE=Trazer Technologies, Inc. + +usb:v0D9A* + ID_VENDOR_FROM_DATABASE=RTX AS + +usb:v0D9Ap0001* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0D9B* + ID_VENDOR_FROM_DATABASE=Tat Shing Electrical Co. + +usb:v0D9C* + ID_VENDOR_FROM_DATABASE=Chee Chen Hi-Technology Co., Ltd + +usb:v0D9D* + ID_VENDOR_FROM_DATABASE=Sanwa Supply, Inc. + +usb:v0D9E* + ID_VENDOR_FROM_DATABASE=Avaya + +usb:v0D9Ep0300* + ID_MODEL_FROM_DATABASE=Wireless Card + +usb:v0D9F* + ID_VENDOR_FROM_DATABASE=Powercom Co., Ltd + +usb:v0D9Fp0001* + ID_MODEL_FROM_DATABASE=Uninterruptible Power Supply + +usb:v0D9Fp0002* + ID_MODEL_FROM_DATABASE=Black Knight PRO / WOW Uninterruptible Power Supply (Cypress HID->COM RS232) + +usb:v0D9Fp00A2* + ID_MODEL_FROM_DATABASE=Imperial Uninterruptible Power Supply (HID PDC) + +usb:v0D9Fp00A3* + ID_MODEL_FROM_DATABASE=Smart King PRO Uninterruptible Power Supply (HID PDC) + +usb:v0D9Fp00A4* + ID_MODEL_FROM_DATABASE=WOW Uninterruptible Power Supply (HID PDC) + +usb:v0D9Fp00A5* + ID_MODEL_FROM_DATABASE=Vanguard Uninterruptible Power Supply (HID PDC) + +usb:v0D9Fp00A6* + ID_MODEL_FROM_DATABASE=Black Knight PRO Uninterruptible Power Supply (HID PDC) + +usb:v0DA0* + ID_VENDOR_FROM_DATABASE=Danger Research + +usb:v0DA1* + ID_VENDOR_FROM_DATABASE=Suzhou Peter's Precise Industrial Co., Ltd + +usb:v0DA2* + ID_VENDOR_FROM_DATABASE=Land Instruments International, Ltd + +usb:v0DA3* + ID_VENDOR_FROM_DATABASE=Nippon Electro-Sensory Devices Corp. + +usb:v0DA4* + ID_VENDOR_FROM_DATABASE=Polar Electro Oy + +usb:v0DA4p0001* + ID_MODEL_FROM_DATABASE=Interface + +usb:v0DA4p0008* + ID_MODEL_FROM_DATABASE=Loop + +usb:v0DA7* + ID_VENDOR_FROM_DATABASE=IOGear, Inc. + +usb:v0DA8* + ID_VENDOR_FROM_DATABASE=softDSP Co., Ltd + +usb:v0DA8p0001* + ID_MODEL_FROM_DATABASE=SDS 200A Oscilloscope + +usb:v0DAB* + ID_VENDOR_FROM_DATABASE=Cubig Group + +usb:v0DABp0100* + ID_MODEL_FROM_DATABASE=DVR/CVR-M140 MP3 Player + +usb:v0DAD* + ID_VENDOR_FROM_DATABASE=Westover Scientific + +usb:v0DB0* + ID_VENDOR_FROM_DATABASE=Micro Star International + +usb:v0DB0p1020* + ID_MODEL_FROM_DATABASE=PC2PC WLAN Card + +usb:v0DB0p1967* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v0DB0p3713* + ID_MODEL_FROM_DATABASE=Primo 73 + +usb:v0DB0p3801* + ID_MODEL_FROM_DATABASE=Motorola Bluetooth 2.1+EDR Device + +usb:v0DB0p3870* + ID_MODEL_FROM_DATABASE=MS-3870 802.11bgn Wireless Module [Ralink RT3070] + +usb:v0DB0p3871* + ID_MODEL_FROM_DATABASE=MS-3871 802.11bgn Wireless Module [Ralink RT8070] + +usb:v0DB0p4011* + ID_MODEL_FROM_DATABASE=Medion Flash XL V2.0 Card Reader + +usb:v0DB0p4023* + ID_MODEL_FROM_DATABASE=Lexar Mobile Card Reader + +usb:v0DB0p4600* + ID_MODEL_FROM_DATABASE=802.11b/g Turbo Wireless Adapter + +usb:v0DB0p5501* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0DB0p5502* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0DB0p5513* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0DB0p5515* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0DB0p5516* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0DB0p5580* + ID_MODEL_FROM_DATABASE=Mega Sky 580 DVB-T Tuner [M902x] + +usb:v0DB0p5581* + ID_MODEL_FROM_DATABASE=Mega Sky 580 DVB-T Tuner [GL861] + +usb:v0DB0p6823* + ID_MODEL_FROM_DATABASE=UB11B/MS-6823 802.11b Wi-Fi adapter + +usb:v0DB0p6826* + ID_MODEL_FROM_DATABASE=IEEE 802.11g Wireless Network Adapter + +usb:v0DB0p6855* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0DB0p6861* + ID_MODEL_FROM_DATABASE=MSI-6861 802.11g WiFi adapter + +usb:v0DB0p6865* + ID_MODEL_FROM_DATABASE=RT2570 + +usb:v0DB0p6869* + ID_MODEL_FROM_DATABASE=RT2570 + +usb:v0DB0p6874* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v0DB0p6877* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v0DB0p6881* + ID_MODEL_FROM_DATABASE=Bluetooth Class I EDR Device + +usb:v0DB0p688A* + ID_MODEL_FROM_DATABASE=Bluetooth Class I EDR Device + +usb:v0DB0p6899* + ID_MODEL_FROM_DATABASE=802.11bgn 1T1R Mini Card Wireless Adapter + +usb:v0DB0p6970* + ID_MODEL_FROM_DATABASE=MS-6970 BToes Bluetooth adapter + +usb:v0DB0p697A* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v0DB0p6982* + ID_MODEL_FROM_DATABASE=Medion Flash XL Card Reader + +usb:v0DB0pA861* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v0DB0pA874* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v0DB0pA970* + ID_MODEL_FROM_DATABASE=Bluetooth dongle + +usb:v0DB0pA97A* + ID_MODEL_FROM_DATABASE=Bluetooth EDR Device + +usb:v0DB0pB970* + ID_MODEL_FROM_DATABASE=Bluetooth EDR Device + +usb:v0DB0pB97A* + ID_MODEL_FROM_DATABASE=Bluetooth EDR Device + +usb:v0DB1* + ID_VENDOR_FROM_DATABASE=Wen Te Electronics Co., Ltd + +usb:v0DB2* + ID_VENDOR_FROM_DATABASE=Shian Hwi Plug Parts, Plastic Factory + +usb:v0DB3* + ID_VENDOR_FROM_DATABASE=Tekram Technology Co., Ltd + +usb:v0DB4* + ID_VENDOR_FROM_DATABASE=Chung Fu Chen Yeh Enterprise Corp. + +usb:v0DB5* + ID_VENDOR_FROM_DATABASE=Access IS + +usb:v0DB5p0139* + ID_MODEL_FROM_DATABASE=Barcode Module - CDC serial + +usb:v0DB5p013A* + ID_MODEL_FROM_DATABASE=Barcode Module - Virtual Keyboard + +usb:v0DB5p013B* + ID_MODEL_FROM_DATABASE=Barcode Module - HID + +usb:v0DB5p0160* + ID_MODEL_FROM_DATABASE=NFC and Smartcard Module (NSM) + +usb:v0DB7* + ID_VENDOR_FROM_DATABASE=ELCON Systemtechnik + +usb:v0DB7p0002* + ID_MODEL_FROM_DATABASE=Goldpfeil P-LAN + +usb:v0DBA* + ID_VENDOR_FROM_DATABASE=Digidesign + +usb:v0DBAp1000* + ID_MODEL_FROM_DATABASE=Mbox 1 [Mbox] + +usb:v0DBAp3000* + ID_MODEL_FROM_DATABASE=Mbox 2 + +usb:v0DBApB011* + ID_MODEL_FROM_DATABASE=Eleven Rack + +usb:v0DBC* + ID_VENDOR_FROM_DATABASE=A&D Medical + +usb:v0DBCp0003* + ID_MODEL_FROM_DATABASE=AND Serial Cable [AND Smart Cable] + +usb:v0DBE* + ID_VENDOR_FROM_DATABASE=Jiuh Shiuh Precision Industry Co., Ltd + +usb:v0DBF* + ID_VENDOR_FROM_DATABASE=Jess-Link International + +usb:v0DBFp0002* + ID_MODEL_FROM_DATABASE=SmartDongle Security Key + +usb:v0DBFp0200* + ID_MODEL_FROM_DATABASE=HDD Storage Solution + +usb:v0DBFp021B* + ID_MODEL_FROM_DATABASE=USB-2.0 IDE Adapter + +usb:v0DBFp0300* + ID_MODEL_FROM_DATABASE=Storage Adapter + +usb:v0DBFp0333* + ID_MODEL_FROM_DATABASE=Storage Adapter + +usb:v0DBFp0502* + ID_MODEL_FROM_DATABASE=FSC Storagebird XL hard disk + +usb:v0DBFp0707* + ID_MODEL_FROM_DATABASE=ZIV Drive + +usb:v0DC0* + ID_VENDOR_FROM_DATABASE=G7 Solutions (formerly Great Notions) + +usb:v0DC1* + ID_VENDOR_FROM_DATABASE=Tamagawa Seiki Co., Ltd + +usb:v0DC3* + ID_VENDOR_FROM_DATABASE=Athena Smartcard Solutions, Inc. + +usb:v0DC3p0801* + ID_MODEL_FROM_DATABASE=ASEDrive III + +usb:v0DC3p0802* + ID_MODEL_FROM_DATABASE=ASEDrive IIIe + +usb:v0DC3p1104* + ID_MODEL_FROM_DATABASE=ASEDrive IIIe KB + +usb:v0DC3p1701* + ID_MODEL_FROM_DATABASE=ASEKey + +usb:v0DC3p1702* + ID_MODEL_FROM_DATABASE=ASEKey + +usb:v0DC4* + ID_VENDOR_FROM_DATABASE=inXtron, Inc. + +usb:v0DC4p0040* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0DC4p0041* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0DC4p0042* + ID_MODEL_FROM_DATABASE=Mass Storage Device + +usb:v0DC4p0101* + ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device + +usb:v0DC4p0209* + ID_MODEL_FROM_DATABASE=SK-3500 S2 + +usb:v0DC4p020A* + ID_MODEL_FROM_DATABASE=Oyen Digital MiniPro 2.5" hard drive enclosure + +usb:v0DC5* + ID_VENDOR_FROM_DATABASE=SDK Co., Ltd + +usb:v0DC6* + ID_VENDOR_FROM_DATABASE=Precision Squared Technology Corp. + +usb:v0DC6p2301* + ID_MODEL_FROM_DATABASE=Wireless Touchpad Keyboard + +usb:v0DC7* + ID_VENDOR_FROM_DATABASE=First Cable Line, Inc. + +usb:v0DCD* + ID_VENDOR_FROM_DATABASE=NetworkFab Corp. + +usb:v0DCDp0001* + ID_MODEL_FROM_DATABASE=Remote Interface Adapter + +usb:v0DCDp0002* + ID_MODEL_FROM_DATABASE=High Bandwidth Codec + +usb:v0DD0* + ID_VENDOR_FROM_DATABASE=Access Solutions + +usb:v0DD0p1002* + ID_MODEL_FROM_DATABASE=Triple Talk Speech Synthesizer + +usb:v0DD1* + ID_VENDOR_FROM_DATABASE=Contek Electronics Co., Ltd + +usb:v0DD2* + ID_VENDOR_FROM_DATABASE=Power Quotient International Co., Ltd + +usb:v0DD2p0003* + ID_MODEL_FROM_DATABASE=Mass Storage (P) + +usb:v0DD3* + ID_VENDOR_FROM_DATABASE=MediaQ + +usb:v0DD4* + ID_VENDOR_FROM_DATABASE=Custom Engineering SPA + +usb:v0DD5* + ID_VENDOR_FROM_DATABASE=California Micro Devices + +usb:v0DD7* + ID_VENDOR_FROM_DATABASE=Kocom Co., Ltd + +usb:v0DD8* + ID_VENDOR_FROM_DATABASE=Netac Technology Co., Ltd + +usb:v0DD8p1060* + ID_MODEL_FROM_DATABASE=USB-CF-Card + +usb:v0DD8pE007* + ID_MODEL_FROM_DATABASE=OnlyDisk U222 Pendrive + +usb:v0DD8pF607* + ID_MODEL_FROM_DATABASE=OnlyDisk U208 1G flash drive [U-SAFE] + +usb:v0DD9* + ID_VENDOR_FROM_DATABASE=HighSpeed Surfing + +usb:v0DDA* + ID_VENDOR_FROM_DATABASE=Integrated Circuit Solution, Inc. + +usb:v0DDAp0001* + ID_MODEL_FROM_DATABASE=Multi-Card Reader 6in1 + +usb:v0DDAp0002* + ID_MODEL_FROM_DATABASE=Multi-Card Reader 7in1 + +usb:v0DDAp0003* + ID_MODEL_FROM_DATABASE=Flash Disk + +usb:v0DDAp0005* + ID_MODEL_FROM_DATABASE=Internal Multi-Card Reader 6in1 + +usb:v0DDAp0008* + ID_MODEL_FROM_DATABASE=SD single card reader + +usb:v0DDAp0009* + ID_MODEL_FROM_DATABASE=MS single card reader + +usb:v0DDAp000A* + ID_MODEL_FROM_DATABASE=MS+SD Dual Card Reader + +usb:v0DDAp000B* + ID_MODEL_FROM_DATABASE=SM single card reader + +usb:v0DDAp0101* + ID_MODEL_FROM_DATABASE=All-In-One Card Reader + +usb:v0DDAp0102* + ID_MODEL_FROM_DATABASE=All-In-One Card Reader + +usb:v0DDAp0301* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0DDAp0302* + ID_MODEL_FROM_DATABASE=Multi-Card MP3 Player + +usb:v0DDAp1001* + ID_MODEL_FROM_DATABASE=Multi-Flash Disk + +usb:v0DDAp2001* + ID_MODEL_FROM_DATABASE=Multi-Card Reader + +usb:v0DDAp2002* + ID_MODEL_FROM_DATABASE=Q018 default PID + +usb:v0DDAp2003* + ID_MODEL_FROM_DATABASE=Multi-Card Reader + +usb:v0DDAp2005* + ID_MODEL_FROM_DATABASE=Datalux DLX-1611 16in1 Card Reader + +usb:v0DDAp2006* + ID_MODEL_FROM_DATABASE=All-In-One Card Reader + +usb:v0DDAp2007* + ID_MODEL_FROM_DATABASE=USB to ATAPI bridge + +usb:v0DDAp2008* + ID_MODEL_FROM_DATABASE=All-In-One Card Reader + +usb:v0DDAp2013* + ID_MODEL_FROM_DATABASE=SD/MS Combo Card Reader + +usb:v0DDAp2014* + ID_MODEL_FROM_DATABASE=SD/MS Single Card Reader + +usb:v0DDAp2023* + ID_MODEL_FROM_DATABASE=card reader SD/MS DEMO board with ICSI brand name (MaskROM version) + +usb:v0DDAp2024* + ID_MODEL_FROM_DATABASE=card reader SD/MS DEMO board with Generic brand name (MaskROM version) + +usb:v0DDAp2026* + ID_MODEL_FROM_DATABASE=USB2.0 Card Reader + +usb:v0DDAp2027* + ID_MODEL_FROM_DATABASE=USB 2.0 Card Reader + +usb:v0DDAp2315* + ID_MODEL_FROM_DATABASE=UFD MP3 player (model 2) + +usb:v0DDAp2318* + ID_MODEL_FROM_DATABASE=UFD MP3 player (model 1) + +usb:v0DDAp2321* + ID_MODEL_FROM_DATABASE=UFD MP3 player + +usb:v0DDB* + ID_VENDOR_FROM_DATABASE=Tamarack, Inc. + +usb:v0DDD* + ID_VENDOR_FROM_DATABASE=Datelink Technology Co., Ltd + +usb:v0DDE* + ID_VENDOR_FROM_DATABASE=Ubicom, Inc. + +usb:v0DE0* + ID_VENDOR_FROM_DATABASE=BD Consumer Healthcare + +usb:v0DE7* + ID_VENDOR_FROM_DATABASE=USBmicro + +usb:v0DE7p0191* + ID_MODEL_FROM_DATABASE=U401 Interface card + +usb:v0DE7p01A5* + ID_MODEL_FROM_DATABASE=U421 interface card + +usb:v0DE7p01C3* + ID_MODEL_FROM_DATABASE=U451 relay interface card + +usb:v0DEA* + ID_VENDOR_FROM_DATABASE=UTECH Electronic (D.G.) Co., Ltd. + +usb:v0DED* + ID_VENDOR_FROM_DATABASE=Novasonics + +usb:v0DEE* + ID_VENDOR_FROM_DATABASE=Lifetime Memory Products + +usb:v0DEEp4010* + ID_MODEL_FROM_DATABASE=Storage Adapter + +usb:v0DEF* + ID_VENDOR_FROM_DATABASE=Full Rise Electronic Co., Ltd + +usb:v0DF4* + ID_VENDOR_FROM_DATABASE=NET&SYS + +usb:v0DF4p0201* + ID_MODEL_FROM_DATABASE=MNG-2005 + +usb:v0DF6* + ID_VENDOR_FROM_DATABASE=Sitecom Europe B.V. + +usb:v0DF6p0001* + ID_MODEL_FROM_DATABASE=C-Media VOIP Device + +usb:v0DF6p0004* + ID_MODEL_FROM_DATABASE=Bluetooth 2.0 Adapter 100m + +usb:v0DF6p0007* + ID_MODEL_FROM_DATABASE=Bluetooth 2.0 Adapter 10m + +usb:v0DF6p000B* + ID_MODEL_FROM_DATABASE=Bluetooth 2.0 Adapter DFU + +usb:v0DF6p000D* + ID_MODEL_FROM_DATABASE=WL-168 Wireless Network Adapter 54g + +usb:v0DF6p0017* + ID_MODEL_FROM_DATABASE=WL-182 Wireless-N Network USB Card + +usb:v0DF6p0019* + ID_MODEL_FROM_DATABASE=Bluetooth 2.0 adapter 10m CN-512v2 001 + +usb:v0DF6p001A* + ID_MODEL_FROM_DATABASE=Bluetooth 2.0 adapter 100m CN-521v2 001 + +usb:v0DF6p002B* + ID_MODEL_FROM_DATABASE=WL-188 Wireless Network 300N USB Adapter + +usb:v0DF6p002C* + ID_MODEL_FROM_DATABASE=WL-301 Wireless Network 300N USB Adapter + +usb:v0DF6p002D* + ID_MODEL_FROM_DATABASE=WL-302 Wireless Network 300N USB dongle + +usb:v0DF6p0036* + ID_MODEL_FROM_DATABASE=WL-603 Wireless Adapter + +usb:v0DF6p0039* + ID_MODEL_FROM_DATABASE=WL-315 Wireless-N USB Adapter + +usb:v0DF6p003B* + ID_MODEL_FROM_DATABASE=WL-321 Wireless USB Gaming Adapter 300N + +usb:v0DF6p003C* + ID_MODEL_FROM_DATABASE=WL-323 Wireless-N USB Adapter + +usb:v0DF6p003D* + ID_MODEL_FROM_DATABASE=WL-324 Wireless USB Adapter 300N + +usb:v0DF6p003E* + ID_MODEL_FROM_DATABASE=WL-343 Wireless USB Adapter 150N X1 + +usb:v0DF6p003F* + ID_MODEL_FROM_DATABASE=WL-608 Wireless USB Adapter 54g + +usb:v0DF6p0040* + ID_MODEL_FROM_DATABASE=WL-344 Wireless Adapter 300N X2 [Ralink RT3071] + +usb:v0DF6p0041* + ID_MODEL_FROM_DATABASE=WL-329 Wireless Dualband USB adapter 300N + +usb:v0DF6p0042* + ID_MODEL_FROM_DATABASE=WL-345 Wireless USB adapter 300N X3 + +usb:v0DF6p0045* + ID_MODEL_FROM_DATABASE=WL-353 Wireless USB Adapter 150N Nano + +usb:v0DF6p0047* + ID_MODEL_FROM_DATABASE=WL-352v1 Wireless USB Adapter 300N 002 + +usb:v0DF6p0048* + ID_MODEL_FROM_DATABASE=WL-349v1 Wireless Adapter 150N 002 [Ralink RT3070] + +usb:v0DF6p0049* + ID_MODEL_FROM_DATABASE=WL-356 Wireless Adapter 300N + +usb:v0DF6p004A* + ID_MODEL_FROM_DATABASE=WL-358v1 Wireless Micro USB Adapter 300N X3 002 + +usb:v0DF6p004B* + ID_MODEL_FROM_DATABASE=WL-349v3 Wireless Micro Adapter 150N X1 [Realtek RTL8192SU] + +usb:v0DF6p004C* + ID_MODEL_FROM_DATABASE=WL-352 802.11n Adapter [Realtek RTL8191SU] + +usb:v0DF6p0050* + ID_MODEL_FROM_DATABASE=WL-349v4 Wireless Micro Adapter 150N X1 [Ralink RT3370] + +usb:v0DF6p0056* + ID_MODEL_FROM_DATABASE=LN-031 10/100/1000 Ethernet Adapter + +usb:v0DF6p005D* + ID_MODEL_FROM_DATABASE=WLA-2000 v1.001 WLAN [RTL8191SU] + +usb:v0DF6p0060* + ID_MODEL_FROM_DATABASE=WLA-4000 802.11bgn [Ralink RT3072] + +usb:v0DF6p0062* + ID_MODEL_FROM_DATABASE=WLA-5000 802.11abgn [Ralink RT3572] + +usb:v0DF6p006F* + ID_MODEL_FROM_DATABASE=WLA-5100 + +usb:v0DF6p0072* + ID_MODEL_FROM_DATABASE=AX88179 Gigabit Ethernet [Sitecom] + +usb:v0DF6p061C* + ID_MODEL_FROM_DATABASE=LN-028 Network USB 2.0 Adapter + +usb:v0DF6p214A* + ID_MODEL_FROM_DATABASE=IDE/SATA Combo Adapter [CN-330] + +usb:v0DF6p21F4* + ID_MODEL_FROM_DATABASE=44 St Bluetooth Device + +usb:v0DF6p2200* + ID_MODEL_FROM_DATABASE=Sitecom bluetooth2.0 class 2 dongle CN-512 + +usb:v0DF6p2208* + ID_MODEL_FROM_DATABASE=Sitecom bluetooth2.0 class 2 dongle CN-520 + +usb:v0DF6p2209* + ID_MODEL_FROM_DATABASE=Sitecom bluetooth2.0 class 1 dongle CN-521 + +usb:v0DF6p3068* + ID_MODEL_FROM_DATABASE=DC-104v2 ISDN Adapter [HFC-S] + +usb:v0DF6p9071* + ID_MODEL_FROM_DATABASE=WL-113 rev 1 Wireless Network USB Adapter + +usb:v0DF6p9075* + ID_MODEL_FROM_DATABASE=WL-117 Hi-Speed USB Adapter + +usb:v0DF6p90AC* + ID_MODEL_FROM_DATABASE=WL-172 Wireless Network USB Adapter 54g Turbo + +usb:v0DF6p9712* + ID_MODEL_FROM_DATABASE=WL-113 rev 2 Wireless Network USB Adapter + +usb:v0DF7* + ID_VENDOR_FROM_DATABASE=Mobile Action Technology, Inc. + +usb:v0DF7p0620* + ID_MODEL_FROM_DATABASE=MA-620 Infrared Adapter + +usb:v0DF7p0700* + ID_MODEL_FROM_DATABASE=MA-700 Bluetooth Adapter + +usb:v0DF7p0720* + ID_MODEL_FROM_DATABASE=MA-720 Bluetooth Adapter + +usb:v0DF7p0722* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v0DF7p0730* + ID_MODEL_FROM_DATABASE=MA-730/MA-730G Bluetooth Adapter + +usb:v0DF7p0800* + ID_MODEL_FROM_DATABASE=Data Cable + +usb:v0DF7p0820* + ID_MODEL_FROM_DATABASE=Data Cable + +usb:v0DF7p0900* + ID_MODEL_FROM_DATABASE=MA i-gotU Travel Logger GPS + +usb:v0DF7p1800* + ID_MODEL_FROM_DATABASE=Generic Card Reader + +usb:v0DF7p1802* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v0DFA* + ID_VENDOR_FROM_DATABASE=Toyo Communication Equipment Co., Ltd + +usb:v0DFC* + ID_VENDOR_FROM_DATABASE=GeneralTouch Technology Co., Ltd + +usb:v0DFCp0001* + ID_MODEL_FROM_DATABASE=Touchscreen + +usb:v0DFCp0101* + ID_MODEL_FROM_DATABASE=5-point Touch Screen + +usb:v0E03* + ID_VENDOR_FROM_DATABASE=Nippon Systemware Co., Ltd + +usb:v0E08* + ID_VENDOR_FROM_DATABASE=Winbest Technology Co., Ltd + +usb:v0E0B* + ID_VENDOR_FROM_DATABASE=Amigo Technology Inc. + +usb:v0E0Bp9031* + ID_MODEL_FROM_DATABASE=802.11n Wireless USB Card + +usb:v0E0Bp9041* + ID_MODEL_FROM_DATABASE=802.11n Wireless USB Card + +usb:v0E0C* + ID_VENDOR_FROM_DATABASE=Gesytec + +usb:v0E0Cp0101* + ID_MODEL_FROM_DATABASE=LonUSB LonTalk Network Adapter + +usb:v0E0D* + ID_VENDOR_FROM_DATABASE=PicoQuant GmbH + +usb:v0E0Dp0003* + ID_MODEL_FROM_DATABASE=PicoHarp 300 + +usb:v0E0F* + ID_VENDOR_FROM_DATABASE=VMware, Inc. + +usb:v0E0Fp0001* + ID_MODEL_FROM_DATABASE=Device + +usb:v0E0Fp0002* + ID_MODEL_FROM_DATABASE=Virtual USB Hub + +usb:v0E0Fp0003* + ID_MODEL_FROM_DATABASE=Virtual Mouse + +usb:v0E0Fp0004* + ID_MODEL_FROM_DATABASE=Virtual CCID + +usb:v0E0Fp0005* + ID_MODEL_FROM_DATABASE=Virtual Mass Storage + +usb:v0E0Fp0006* + ID_MODEL_FROM_DATABASE=Virtual Keyboard + +usb:v0E0Fp8001* + ID_MODEL_FROM_DATABASE=Root Hub + +usb:v0E0Fp8002* + ID_MODEL_FROM_DATABASE=Root Hub + +usb:v0E0Fp8003* + ID_MODEL_FROM_DATABASE=Root Hub + +usb:v0E0FpF80A* + ID_MODEL_FROM_DATABASE=Smoker FX2 + +usb:v0E16* + ID_VENDOR_FROM_DATABASE=JMTek, LLC + +usb:v0E17* + ID_VENDOR_FROM_DATABASE=Walex Electronic, Ltd + +usb:v0E1A* + ID_VENDOR_FROM_DATABASE=Unisys + +usb:v0E1B* + ID_VENDOR_FROM_DATABASE=Crewave + +usb:v0E20* + ID_VENDOR_FROM_DATABASE=Pegasus Technologies Ltd. + +usb:v0E20p0101* + ID_MODEL_FROM_DATABASE=NoteTaker + +usb:v0E20p0200* + ID_MODEL_FROM_DATABASE=Seiko Instruments InkLink Handwriting System + +usb:v0E21* + ID_VENDOR_FROM_DATABASE=Cowon Systems, Inc. + +usb:v0E21p0300* + ID_MODEL_FROM_DATABASE=iAudio CW200 + +usb:v0E21p0400* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0E21p0500* + ID_MODEL_FROM_DATABASE=iAudio M3 + +usb:v0E21p0510* + ID_MODEL_FROM_DATABASE=iAudio X5, subpack USB port + +usb:v0E21p0513* + ID_MODEL_FROM_DATABASE=iAudio X5, side USB port + +usb:v0E21p0520* + ID_MODEL_FROM_DATABASE=iAudio M5, side USB port + +usb:v0E21p0601* + ID_MODEL_FROM_DATABASE=iAudio G3 + +usb:v0E21p0681* + ID_MODEL_FROM_DATABASE=iAUDIO E2 + +usb:v0E21p0700* + ID_MODEL_FROM_DATABASE=iAudio U3 + +usb:v0E21p0751* + ID_MODEL_FROM_DATABASE=iAudio 7 + +usb:v0E21p0760* + ID_MODEL_FROM_DATABASE=iAUDIO U5 / iAUDIO G2 + +usb:v0E21p0800* + ID_MODEL_FROM_DATABASE=Cowon D2 (UMS mode) + +usb:v0E21p0801* + ID_MODEL_FROM_DATABASE=Cowon D2 (MTP mode) + +usb:v0E21p0910* + ID_MODEL_FROM_DATABASE=iAUDIO 9 + +usb:v0E21p0920* + ID_MODEL_FROM_DATABASE=J3 + +usb:v0E22* + ID_VENDOR_FROM_DATABASE=Symbian Ltd. + +usb:v0E23* + ID_VENDOR_FROM_DATABASE=Liou Yuane Enterprise Co., Ltd + +usb:v0E25* + ID_VENDOR_FROM_DATABASE=VinChip Systems, Inc. + +usb:v0E26* + ID_VENDOR_FROM_DATABASE=J-Phone East Co., Ltd + +usb:v0E30* + ID_VENDOR_FROM_DATABASE=HeartMath LLC + +usb:v0E34* + ID_VENDOR_FROM_DATABASE=Micro Computer Control Corp. + +usb:v0E35* + ID_VENDOR_FROM_DATABASE=3Pea Technologies, Inc. + +usb:v0E36* + ID_VENDOR_FROM_DATABASE=TiePie engineering + +usb:v0E36p0009* + ID_MODEL_FROM_DATABASE=Handyscope HS3 + +usb:v0E36p000B* + ID_MODEL_FROM_DATABASE=Handyscope HS4 + +usb:v0E36p000F* + ID_MODEL_FROM_DATABASE=Handyscope HS4-DIFF (br) + +usb:v0E36p0010* + ID_MODEL_FROM_DATABASE=Handyscope HS2 + +usb:v0E36p0011* + ID_MODEL_FROM_DATABASE=TiePieSCOPE HS805 (br) + +usb:v0E36p0012* + ID_MODEL_FROM_DATABASE=TiePieSCOPE HS805 + +usb:v0E36p0013* + ID_MODEL_FROM_DATABASE=Handyprobe HP3 + +usb:v0E36p0014* + ID_MODEL_FROM_DATABASE=Handyprobe HP3 + +usb:v0E36p0018* + ID_MODEL_FROM_DATABASE=Handyprobe HP2 + +usb:v0E36p001B* + ID_MODEL_FROM_DATABASE=Handyscope HS5 + +usb:v0E36p0042* + ID_MODEL_FROM_DATABASE=TiePieSCOPE HS801 + +usb:v0E36p00FD* + ID_MODEL_FROM_DATABASE=USB To Parallel adapter + +usb:v0E36p00FE* + ID_MODEL_FROM_DATABASE=USB To Parallel adapter + +usb:v0E38* + ID_VENDOR_FROM_DATABASE=Stratitec, Inc. + +usb:v0E39* + ID_VENDOR_FROM_DATABASE=Smart Modular Technologies, Inc. + +usb:v0E39p0137* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v0E3A* + ID_VENDOR_FROM_DATABASE=Neostar Technology Co., Ltd + +usb:v0E3Ap1100* + ID_MODEL_FROM_DATABASE=CW-1100 Wireless Network Adapter + +usb:v0E3B* + ID_VENDOR_FROM_DATABASE=Mansella, Ltd + +usb:v0E41* + ID_VENDOR_FROM_DATABASE=Line6, Inc. + +usb:v0E41p4147* + ID_MODEL_FROM_DATABASE=TonePort GX + +usb:v0E41p414D* + ID_MODEL_FROM_DATABASE=Pod HD500 + +usb:v0E41p4156* + ID_MODEL_FROM_DATABASE=POD HD Desktop + +usb:v0E41p4250* + ID_MODEL_FROM_DATABASE=BassPODxt + +usb:v0E41p4252* + ID_MODEL_FROM_DATABASE=BassPODxt Pro + +usb:v0E41p4642* + ID_MODEL_FROM_DATABASE=BassPODxt Live + +usb:v0E41p4650* + ID_MODEL_FROM_DATABASE=PODxt Live + +usb:v0E41p4750* + ID_MODEL_FROM_DATABASE=GuitarPort + +usb:v0E41p5044* + ID_MODEL_FROM_DATABASE=PODxt + +usb:v0E41p5050* + ID_MODEL_FROM_DATABASE=PODxt Pro + +usb:v0E41p534D* + ID_MODEL_FROM_DATABASE=SeaMonkey + +usb:v0E44* + ID_VENDOR_FROM_DATABASE=Sun-Riseful Technology Co., Ltd. + +usb:v0E48* + ID_VENDOR_FROM_DATABASE=Julia Corp., Ltd + +usb:v0E48p0100* + ID_MODEL_FROM_DATABASE=CardPro SmartCard Reader + +usb:v0E4A* + ID_VENDOR_FROM_DATABASE=Shenzhen Bao Hing Electric Wire & Cable Mfr. Co. + +usb:v0E4C* + ID_VENDOR_FROM_DATABASE=Radica Games, Ltd + +usb:v0E4Cp1097* + ID_MODEL_FROM_DATABASE=Gamester Controller + +usb:v0E4Cp2390* + ID_MODEL_FROM_DATABASE=Games Jtech Controller + +usb:v0E4Cp7288* + ID_MODEL_FROM_DATABASE=funkey reader + +usb:v0E50* + ID_VENDOR_FROM_DATABASE=TechnoData Interware + +usb:v0E50p0001* + ID_MODEL_FROM_DATABASE=Matrix USB-Key + +usb:v0E50p0002* + ID_MODEL_FROM_DATABASE=Matrixlock Dongle (HID) + +usb:v0E55* + ID_VENDOR_FROM_DATABASE=Speed Dragon Multimedia, Ltd + +usb:v0E55p110A* + ID_MODEL_FROM_DATABASE=Tanic S110-SG1 + ISSC IS1002N [Slow Infra-Red (SIR) & Bluetooth 1.2 (Class 2) Adapter] + +usb:v0E55p110B* + ID_MODEL_FROM_DATABASE=MS3303H USB-to-Serial Bridge + +usb:v0E56* + ID_VENDOR_FROM_DATABASE=Kingston Technology Company, Inc. + +usb:v0E56p6021* + ID_MODEL_FROM_DATABASE=K-PEX 100 + +usb:v0E5A* + ID_VENDOR_FROM_DATABASE=Active Co., Ltd + +usb:v0E5B* + ID_VENDOR_FROM_DATABASE=Union Power Information Industrial Co., Ltd + +usb:v0E5C* + ID_VENDOR_FROM_DATABASE=Bitland Information Technology Co., Ltd + +usb:v0E5Cp6118* + ID_MODEL_FROM_DATABASE=LCD Device + +usb:v0E5Cp6119* + ID_MODEL_FROM_DATABASE=remote receive and control device + +usb:v0E5Cp6441* + ID_MODEL_FROM_DATABASE=C-Media Sound Device + +usb:v0E5D* + ID_VENDOR_FROM_DATABASE=Neltron Industrial Co., Ltd + +usb:v0E5E* + ID_VENDOR_FROM_DATABASE=Conwise Technology Co., Ltd. + +usb:v0E5Ep6622* + ID_MODEL_FROM_DATABASE=CW6622 + +usb:v0E66* + ID_VENDOR_FROM_DATABASE=Hawking Technologies + +usb:v0E66p0001* + ID_MODEL_FROM_DATABASE=HWUN1 Hi-Gain Wireless-300N Adapter w/ Upgradable Antenna [Ralink RT2870] + +usb:v0E66p0003* + ID_MODEL_FROM_DATABASE=HWDN1 Hi-Gain Wireless-300N Dish Adapter [Ralink RT2870] + +usb:v0E66p0009* + ID_MODEL_FROM_DATABASE=HWUN2 Hi-Gain Wireless-150N Adapter w/ Upgradable Antenna [Ralink RT2770] + +usb:v0E66p000B* + ID_MODEL_FROM_DATABASE=HWDN2 Hi-Gain Wireless-150N Dish Adapter [Ralink RT2770] + +usb:v0E66p0013* + ID_MODEL_FROM_DATABASE=HWUN3 Hi-Gain Wireless-N Adapter [Ralink RT3070] + +usb:v0E66p0015* + ID_MODEL_FROM_DATABASE=HWDN2 Rev. E Hi-Gain Wireless-150N Dish Adapter [Realtek RTL8191SU] + +usb:v0E66p0017* + ID_MODEL_FROM_DATABASE=HAWNU1 Hi-Gain Wireless-150N Network Adapter with Range Amplifier [Ralink RT3070] + +usb:v0E66p0018* + ID_MODEL_FROM_DATABASE=Wireless-N Network Adapter [Ralink RT2870] + +usb:v0E66p400B* + ID_MODEL_FROM_DATABASE=UF100 10/100 Network Adapter + +usb:v0E66p400C* + ID_MODEL_FROM_DATABASE=UF100 Ethernet [pegasus2] + +usb:v0E67* + ID_VENDOR_FROM_DATABASE=Fossil, Inc. + +usb:v0E67p0002* + ID_MODEL_FROM_DATABASE=Wrist PDA + +usb:v0E6A* + ID_VENDOR_FROM_DATABASE=Megawin Technology Co., Ltd + +usb:v0E6Ap0101* + ID_MODEL_FROM_DATABASE=MA100 [USB-UART Bridge IC] + +usb:v0E6Ap030B* + ID_MODEL_FROM_DATABASE=Truly Ergonomic Computer Keyboard (Device Firmware Update mode) + +usb:v0E6Ap030C* + ID_MODEL_FROM_DATABASE=Truly Ergonomic Computer Keyboard + +usb:v0E6Ap6001* + ID_MODEL_FROM_DATABASE=GEMBIRD Flexible keyboard KB-109F-B-DE + +usb:v0E6Ap7F5C* + ID_MODEL_FROM_DATABASE=BPF-015 Key Chain Photo Frame + +usb:v0E6F* + ID_VENDOR_FROM_DATABASE=Logic3 + +usb:v0E6Fp0003* + ID_MODEL_FROM_DATABASE=Freebird wireless Controller + +usb:v0E6Fp0005* + ID_MODEL_FROM_DATABASE=Eclipse wireless Controller + +usb:v0E6Fp0006* + ID_MODEL_FROM_DATABASE=Edge wireless Controller + +usb:v0E6Fp0128* + ID_MODEL_FROM_DATABASE=Wireless PS3 Controller + +usb:v0E70* + ID_VENDOR_FROM_DATABASE=Tokyo Electronic Industry Co., Ltd + +usb:v0E72* + ID_VENDOR_FROM_DATABASE=Hsi-Chin Electronics Co., Ltd + +usb:v0E75* + ID_VENDOR_FROM_DATABASE=TVS Electronics, Ltd + +usb:v0E79* + ID_VENDOR_FROM_DATABASE=Archos, Inc. + +usb:v0E79p1106* + ID_MODEL_FROM_DATABASE=Pocket Media Assistant - PMA400 + +usb:v0E79p1204* + ID_MODEL_FROM_DATABASE=Gmini XS 200 + +usb:v0E79p1306* + ID_MODEL_FROM_DATABASE=504 Portable Multimedia Player + +usb:v0E79p1330* + ID_MODEL_FROM_DATABASE=5 Tablet + +usb:v0E79p1332* + ID_MODEL_FROM_DATABASE=5 IMT + +usb:v0E79p1416* + ID_MODEL_FROM_DATABASE=32 IT + +usb:v0E79p1417* + ID_MODEL_FROM_DATABASE=A43 IT + +usb:v0E79p14AD* + ID_MODEL_FROM_DATABASE=97 Titanium HD + +usb:v0E79p150E* + ID_MODEL_FROM_DATABASE=80 G9 + +usb:v0E79p3001* + ID_MODEL_FROM_DATABASE=40 Titanium + +usb:v0E7B* + ID_VENDOR_FROM_DATABASE=On-Tech Industry Co., Ltd + +usb:v0E7E* + ID_VENDOR_FROM_DATABASE=Gmate, Inc. + +usb:v0E7Ep0001* + ID_MODEL_FROM_DATABASE=Yopy 3000 PDA + +usb:v0E7Ep1001* + ID_MODEL_FROM_DATABASE=YP3X00 PDA + +usb:v0E82* + ID_VENDOR_FROM_DATABASE=Ching Tai Electric Wire & Cable Co., Ltd + +usb:v0E83* + ID_VENDOR_FROM_DATABASE=Shin An Wire & Cable Co. + +usb:v0E8C* + ID_VENDOR_FROM_DATABASE=Well Force Electronic Co., Ltd + +usb:v0E8D* + ID_VENDOR_FROM_DATABASE=MediaTek Inc. + +usb:v0E8Dp0003* + ID_MODEL_FROM_DATABASE=MT6227 phone + +usb:v0E8Dp0004* + ID_MODEL_FROM_DATABASE=MT6227 phone + +usb:v0E8Dp0023* + ID_MODEL_FROM_DATABASE=S103 + +usb:v0E8Dp00A5* + ID_MODEL_FROM_DATABASE=GSM modem [Medion Surfstick Model:S4222] + +usb:v0E8Dp1806* + ID_MODEL_FROM_DATABASE=Samsung SE-208 Slim Portable DVD Writer + +usb:v0E8Dp1836* + ID_MODEL_FROM_DATABASE=Samsung SE-S084 Super WriteMaster Slim External DVD writer + +usb:v0E8Dp1956* + ID_MODEL_FROM_DATABASE=Samsung SE-506 Portable BluRay Disc Writer + +usb:v0E8Dp2000* + ID_MODEL_FROM_DATABASE=MT65xx Preloader + +usb:v0E8Dp3329* + ID_MODEL_FROM_DATABASE=Qstarz BT-Q1000XT + +usb:v0E8Dp763E* + ID_MODEL_FROM_DATABASE=MT7630e Bluetooth Adapter + +usb:v0E8F* + ID_VENDOR_FROM_DATABASE=GreenAsia Inc. + +usb:v0E8Fp0003* + ID_MODEL_FROM_DATABASE=MaxFire Blaze2 + +usb:v0E8Fp0012* + ID_MODEL_FROM_DATABASE=Joystick/Gamepad + +usb:v0E8Fp0016* + ID_MODEL_FROM_DATABASE=4 port USB 1.1 hub UH-174 + +usb:v0E8Fp0020* + ID_MODEL_FROM_DATABASE=USB to PS/2 Adapter + +usb:v0E8Fp0021* + ID_MODEL_FROM_DATABASE=Multimedia Keyboard Controller + +usb:v0E8Fp0022* + ID_MODEL_FROM_DATABASE=multimedia keyboard controller + +usb:v0E8Fp0201* + ID_MODEL_FROM_DATABASE=SmartJoy Frag Xpad/PS2 adaptor + +usb:v0E8Fp300A* + ID_MODEL_FROM_DATABASE=steering Wheel + +usb:v0E90* + ID_VENDOR_FROM_DATABASE=WiebeTech, LLC + +usb:v0E90p0100* + ID_MODEL_FROM_DATABASE=Storage Adapter V1 + +usb:v0E91* + ID_VENDOR_FROM_DATABASE=VTech Engineering Canada, Ltd + +usb:v0E92* + ID_VENDOR_FROM_DATABASE=C's Glory Enterprise Co., Ltd + +usb:v0E93* + ID_VENDOR_FROM_DATABASE=eM Technics Co., Ltd + +usb:v0E95* + ID_VENDOR_FROM_DATABASE=Future Technology Co., Ltd + +usb:v0E96* + ID_VENDOR_FROM_DATABASE=Aplux Communications, Ltd + +usb:v0E96pC001* + ID_MODEL_FROM_DATABASE=TRUST 380 USB2 SPACEC@M + +usb:v0E97* + ID_VENDOR_FROM_DATABASE=Fingerworks, Inc. + +usb:v0E97p0908* + ID_MODEL_FROM_DATABASE=Composite HID (Keyboard and Mouse) + +usb:v0E98* + ID_VENDOR_FROM_DATABASE=Advanced Analogic Technologies, Inc. + +usb:v0E99* + ID_VENDOR_FROM_DATABASE=Parallel Dice Co., Ltd + +usb:v0E9A* + ID_VENDOR_FROM_DATABASE=TA HSING Industries, Ltd + +usb:v0E9B* + ID_VENDOR_FROM_DATABASE=ADTEC Corp. + +usb:v0E9C* + ID_VENDOR_FROM_DATABASE=Streamzap, Inc. + +usb:v0E9Cp0000* + ID_MODEL_FROM_DATABASE=Streamzap Remote Control + +usb:v0E9F* + ID_VENDOR_FROM_DATABASE=Tamura Corp. + +usb:v0EA0* + ID_VENDOR_FROM_DATABASE=Ours Technology, Inc. + +usb:v0EA0p2126* + ID_MODEL_FROM_DATABASE=7-in-1 Card Reader + +usb:v0EA0p2153* + ID_MODEL_FROM_DATABASE=SD Card Reader Key + +usb:v0EA0p2168* + ID_MODEL_FROM_DATABASE=Transcend JetFlash 2.0 / Astone USB Drive / Intellegent Stick 2.0 + +usb:v0EA0p6803* + ID_MODEL_FROM_DATABASE=OTI-6803 Flash Disk + +usb:v0EA0p6808* + ID_MODEL_FROM_DATABASE=OTI-6808 Flash Disk + +usb:v0EA0p6828* + ID_MODEL_FROM_DATABASE=OTI-6828 Flash Disk + +usb:v0EA0p6858* + ID_MODEL_FROM_DATABASE=OTi-6858 serial adapter + +usb:v0EA6* + ID_VENDOR_FROM_DATABASE=Nihon Computer Co., Ltd + +usb:v0EA7* + ID_VENDOR_FROM_DATABASE=MSL Enterprises Corp. + +usb:v0EA8* + ID_VENDOR_FROM_DATABASE=CenDyne, Inc. + +usb:v0EAD* + ID_VENDOR_FROM_DATABASE=Humax Co., Ltd + +usb:v0EB0* + ID_VENDOR_FROM_DATABASE=NovaTech + +usb:v0EB0p9020* + ID_MODEL_FROM_DATABASE=NovaTech NV-902W + +usb:v0EB0p9021* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v0EB1* + ID_VENDOR_FROM_DATABASE=WIS Technologies, Inc. + +usb:v0EB1p6666* + ID_MODEL_FROM_DATABASE=WinFast WalkieTV TV Loader + +usb:v0EB1p6668* + ID_MODEL_FROM_DATABASE=WinFast WalkieTV TV Loader + +usb:v0EB1p7007* + ID_MODEL_FROM_DATABASE=WinFast WalkieTV WDM Capture + +usb:v0EB2* + ID_VENDOR_FROM_DATABASE=Y-S Electronic Co., Ltd + +usb:v0EB3* + ID_VENDOR_FROM_DATABASE=Saint Technology Corp. + +usb:v0EB7* + ID_VENDOR_FROM_DATABASE=Endor AG + +usb:v0EB8* + ID_VENDOR_FROM_DATABASE=Mettler Toledo + +usb:v0EB8p2200* + ID_MODEL_FROM_DATABASE=Ariva Scale + +usb:v0EB8pF000* + ID_MODEL_FROM_DATABASE=PS60 Scale + +usb:v0EBB* + ID_VENDOR_FROM_DATABASE=Thermo Fisher Scientific + +usb:v0EBBp0002* + ID_MODEL_FROM_DATABASE=FT-IR Spectrometer + +usb:v0EBE* + ID_VENDOR_FROM_DATABASE=VWeb Corp. + +usb:v0EBF* + ID_VENDOR_FROM_DATABASE=Omega Technology of Taiwan, Inc. + +usb:v0EC0* + ID_VENDOR_FROM_DATABASE=LHI Technology (China) Co., Ltd + +usb:v0EC1* + ID_VENDOR_FROM_DATABASE=Abit Computer Corp. + +usb:v0EC2* + ID_VENDOR_FROM_DATABASE=Sweetray Industrial, Ltd + +usb:v0EC3* + ID_VENDOR_FROM_DATABASE=Axell Co., Ltd + +usb:v0EC4* + ID_VENDOR_FROM_DATABASE=Ballracing Developments, Ltd + +usb:v0EC5* + ID_VENDOR_FROM_DATABASE=GT Information System Co., Ltd + +usb:v0EC6* + ID_VENDOR_FROM_DATABASE=InnoVISION Multimedia, Ltd + +usb:v0EC7* + ID_VENDOR_FROM_DATABASE=Theta Link Corp. + +usb:v0EC7p1008* + ID_MODEL_FROM_DATABASE=So., Show 301 Digital Camera + +usb:v0ECD* + ID_VENDOR_FROM_DATABASE=Lite-On IT Corp. + +usb:v0ECDp1400* + ID_MODEL_FROM_DATABASE=CD\RW 40X + +usb:v0ECDpA100* + ID_MODEL_FROM_DATABASE=LDW-411SX DVD/CD Rewritable Drive + +usb:v0ECE* + ID_VENDOR_FROM_DATABASE=TaiSol Electronics Co., Ltd + +usb:v0ECF* + ID_VENDOR_FROM_DATABASE=Phogenix Imaging, LLC + +usb:v0ED1* + ID_VENDOR_FROM_DATABASE=WinMaxGroup + +usb:v0ED1p6660* + ID_MODEL_FROM_DATABASE=Flash Disk 64M-C + +usb:v0ED1p6680* + ID_MODEL_FROM_DATABASE=Flash Disk 64M-B + +usb:v0ED1p7634* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v0ED2* + ID_VENDOR_FROM_DATABASE=Kyoto Micro Computer Co., Ltd + +usb:v0ED3* + ID_VENDOR_FROM_DATABASE=Wing-Tech Enterprise Co., Ltd + +usb:v0ED5* + ID_VENDOR_FROM_DATABASE=Fiberbyte + +usb:v0ED5pE000* + ID_MODEL_FROM_DATABASE=USB-inSync Device + +usb:v0ED5pF000* + ID_MODEL_FROM_DATABASE=Fiberbyte USB-inSync Device + +usb:v0ED5pF201* + ID_MODEL_FROM_DATABASE=Fiberbyte USB-inSync DAQ-2500X + +usb:v0EDA* + ID_VENDOR_FROM_DATABASE=Noriake Itron Corp. + +usb:v0EDF* + ID_VENDOR_FROM_DATABASE=e-MDT Co., Ltd + +usb:v0EDFp2060* + ID_MODEL_FROM_DATABASE=FID irock! 100 Series + +usb:v0EE0* + ID_VENDOR_FROM_DATABASE=Shima Seiki Mfg., Ltd + +usb:v0EE1* + ID_VENDOR_FROM_DATABASE=Sarotech Co., Ltd + +usb:v0EE2* + ID_VENDOR_FROM_DATABASE=AMI Semiconductor, Inc. + +usb:v0EE3* + ID_VENDOR_FROM_DATABASE=ComTrue Technology Corp. + +usb:v0EE3p1000* + ID_MODEL_FROM_DATABASE=Image Tank 1.5 + +usb:v0EE4* + ID_VENDOR_FROM_DATABASE=Sunrich Technology, Ltd + +usb:v0EE4p0690* + ID_MODEL_FROM_DATABASE=SATA 3 Adapter + +usb:v0EEE* + ID_VENDOR_FROM_DATABASE=Digital Stream Technology, Inc. + +usb:v0EEEp8810* + ID_MODEL_FROM_DATABASE=Mass Storage Drive + +usb:v0EEF* + ID_VENDOR_FROM_DATABASE=D-WAV Scientific Co., Ltd + +usb:v0EEFp0001* + ID_MODEL_FROM_DATABASE=eGalax TouchScreen + +usb:v0EEFp0002* + ID_MODEL_FROM_DATABASE=Touchscreen Controller(Professional) + +usb:v0EEFp7200* + ID_MODEL_FROM_DATABASE=Touchscreen Controller + +usb:v0EEFpA802* + ID_MODEL_FROM_DATABASE=eGalaxTouch EXC7920 + +usb:v0EF0* + ID_VENDOR_FROM_DATABASE=Hitachi Cable, Ltd + +usb:v0EF1* + ID_VENDOR_FROM_DATABASE=Aichi Micro Intelligent Corp. + +usb:v0EF2* + ID_VENDOR_FROM_DATABASE=I/O Magic Corp. + +usb:v0EF3* + ID_VENDOR_FROM_DATABASE=Lynn Products, Inc. + +usb:v0EF4* + ID_VENDOR_FROM_DATABASE=DSI Datotech + +usb:v0EF5* + ID_VENDOR_FROM_DATABASE=PointChips + +usb:v0EF5p2202* + ID_MODEL_FROM_DATABASE=Flash Disk + +usb:v0EF5p2366* + ID_MODEL_FROM_DATABASE=Flash Disk + +usb:v0EF6* + ID_VENDOR_FROM_DATABASE=Yield Microelectronics Corp. + +usb:v0EF7* + ID_VENDOR_FROM_DATABASE=SM Tech Co., Ltd (Tulip) + +usb:v0EFD* + ID_VENDOR_FROM_DATABASE=Oasis Semiconductor + +usb:v0EFE* + ID_VENDOR_FROM_DATABASE=Wem Technology, Inc. + +usb:v0F03* + ID_VENDOR_FROM_DATABASE=Unitek UPS Systems + +usb:v0F03p0001* + ID_MODEL_FROM_DATABASE=Alpha 1200Sx + +usb:v0F06* + ID_VENDOR_FROM_DATABASE=Visual Frontier Enterprise Co., Ltd + +usb:v0F08* + ID_VENDOR_FROM_DATABASE=CSL Wire & Plug (Shen Zhen) Co. + +usb:v0F0C* + ID_VENDOR_FROM_DATABASE=CAS Corp. + +usb:v0F0D* + ID_VENDOR_FROM_DATABASE=Hori Co., Ltd + +usb:v0F0Dp0011* + ID_MODEL_FROM_DATABASE=Real Arcade Pro 3 + +usb:v0F0E* + ID_VENDOR_FROM_DATABASE=Energy Full Corp. + +usb:v0F0F* + ID_VENDOR_FROM_DATABASE=Silego Technology Inc + +usb:v0F0Fp0006* + ID_MODEL_FROM_DATABASE=GreenPak Universal Dev Board (Active Mode) + +usb:v0F0Fp8006* + ID_MODEL_FROM_DATABASE=GreenPak Universal Dev Board (Reset Mode) + +usb:v0F11* + ID_VENDOR_FROM_DATABASE=LD Didactic GmbH + +usb:v0F11p1000* + ID_MODEL_FROM_DATABASE=CASSY-S + +usb:v0F11p1010* + ID_MODEL_FROM_DATABASE=Pocket-CASSY + +usb:v0F11p1020* + ID_MODEL_FROM_DATABASE=Mobile-CASSY + +usb:v0F11p1080* + ID_MODEL_FROM_DATABASE=Joule and Wattmeter + +usb:v0F11p1081* + ID_MODEL_FROM_DATABASE=Digital Multimeter P + +usb:v0F11p1090* + ID_MODEL_FROM_DATABASE=UMI P + +usb:v0F11p1100* + ID_MODEL_FROM_DATABASE=X-Ray Apparatus + +usb:v0F11p1101* + ID_MODEL_FROM_DATABASE=X-Ray Apparatus + +usb:v0F11p1200* + ID_MODEL_FROM_DATABASE=VideoCom + +usb:v0F11p2000* + ID_MODEL_FROM_DATABASE=COM3LAB + +usb:v0F11p2010* + ID_MODEL_FROM_DATABASE=Terminal Adapter + +usb:v0F11p2020* + ID_MODEL_FROM_DATABASE=Network Analyser + +usb:v0F11p2030* + ID_MODEL_FROM_DATABASE=Converter Control Unit + +usb:v0F11p2040* + ID_MODEL_FROM_DATABASE=Machine Test System + +usb:v0F12* + ID_VENDOR_FROM_DATABASE=Mars Engineering Corp. + +usb:v0F13* + ID_VENDOR_FROM_DATABASE=Acetek Technology Co., Ltd + +usb:v0F14* + ID_VENDOR_FROM_DATABASE=Ingenico + +usb:v0F14p0012* + ID_MODEL_FROM_DATABASE=Vital'Act 3S + +usb:v0F14p0038* + ID_MODEL_FROM_DATABASE=XIRING Smart Card Terminal LEO V2 + +usb:v0F18* + ID_VENDOR_FROM_DATABASE=Finger Lakes Instrumentation + +usb:v0F18p0002* + ID_MODEL_FROM_DATABASE=CCD + +usb:v0F18p0006* + ID_MODEL_FROM_DATABASE=Focuser + +usb:v0F18p0007* + ID_MODEL_FROM_DATABASE=Filter Wheel + +usb:v0F18p000A* + ID_MODEL_FROM_DATABASE=ProLine CCD + +usb:v0F18p000B* + ID_MODEL_FROM_DATABASE=Color Filter Wheel 4 + +usb:v0F18p000C* + ID_MODEL_FROM_DATABASE=PDF2 + +usb:v0F18p000D* + ID_MODEL_FROM_DATABASE=Guider + +usb:v0F19* + ID_VENDOR_FROM_DATABASE=Oracom Co., Ltd + +usb:v0F1B* + ID_VENDOR_FROM_DATABASE=Onset Computer Corp. + +usb:v0F1C* + ID_VENDOR_FROM_DATABASE=Funai Electric Co., Ltd + +usb:v0F1D* + ID_VENDOR_FROM_DATABASE=Iwill Corp. + +usb:v0F21* + ID_VENDOR_FROM_DATABASE=IOI Technology Corp. + +usb:v0F22* + ID_VENDOR_FROM_DATABASE=Senior Industries, Inc. + +usb:v0F23* + ID_VENDOR_FROM_DATABASE=Leader Tech Manufacturer Co., Ltd + +usb:v0F24* + ID_VENDOR_FROM_DATABASE=Flex-P Industries, Snd., Bhd. + +usb:v0F2D* + ID_VENDOR_FROM_DATABASE=ViPower, Inc. + +usb:v0F2E* + ID_VENDOR_FROM_DATABASE=Geniality Maple Technology Co., Ltd + +usb:v0F2F* + ID_VENDOR_FROM_DATABASE=Priva Design Services + +usb:v0F30* + ID_VENDOR_FROM_DATABASE=Jess Technology Co., Ltd + +usb:v0F30p001C* + ID_MODEL_FROM_DATABASE=PS3 Guitar Controller Dongle + +usb:v0F30p0110* + ID_MODEL_FROM_DATABASE=Dual Analog Rumble Pad + +usb:v0F30p0111* + ID_MODEL_FROM_DATABASE=Colour Rumble Pad + +usb:v0F30p0208* + ID_MODEL_FROM_DATABASE=Xbox & PC Gamepad + +usb:v0F31* + ID_VENDOR_FROM_DATABASE=Chrysalis Development + +usb:v0F32* + ID_VENDOR_FROM_DATABASE=YFC-BonEagle Electric Co., Ltd + +usb:v0F37* + ID_VENDOR_FROM_DATABASE=Kokuyo Co., Ltd + +usb:v0F38* + ID_VENDOR_FROM_DATABASE=Nien-Yi Industrial Corp. + +usb:v0F39* + ID_VENDOR_FROM_DATABASE=TG3 Electronics + +usb:v0F39p0876* + ID_MODEL_FROM_DATABASE=Keyboard [87 Francium Pro] + +usb:v0F39p1086* + ID_MODEL_FROM_DATABASE=DK2108SZ Keyboard [Ducky Zero] + +usb:v0F3D* + ID_VENDOR_FROM_DATABASE=Airprime, Incorporated + +usb:v0F3Dp0112* + ID_MODEL_FROM_DATABASE=CDMA 1xEVDO PC Card, PC 5220 + +usb:v0F41* + ID_VENDOR_FROM_DATABASE=RDC Semiconductor Co., Ltd + +usb:v0F42* + ID_VENDOR_FROM_DATABASE=Nital Consulting Services, Inc. + +usb:v0F44* + ID_VENDOR_FROM_DATABASE=Polhemus + +usb:v0F44pEF11* + ID_MODEL_FROM_DATABASE=Patriot (firmware not loaded) + +usb:v0F44pEF12* + ID_MODEL_FROM_DATABASE=Patriot + +usb:v0F44pFF11* + ID_MODEL_FROM_DATABASE=Liberty (firmware not loaded) + +usb:v0F44pFF12* + ID_MODEL_FROM_DATABASE=Liberty + +usb:v0F4B* + ID_VENDOR_FROM_DATABASE=St. John Technology Co., Ltd + +usb:v0F4C* + ID_VENDOR_FROM_DATABASE=WorldWide Cable Opto Corp. + +usb:v0F4D* + ID_VENDOR_FROM_DATABASE=Microtune, Inc. + +usb:v0F4Dp1000* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v0F4E* + ID_VENDOR_FROM_DATABASE=Freedom Scientific + +usb:v0F52* + ID_VENDOR_FROM_DATABASE=Wing Key Electrical Co., Ltd + +usb:v0F53* + ID_VENDOR_FROM_DATABASE=Dongguan White Horse Cable Factory, Ltd + +usb:v0F54* + ID_VENDOR_FROM_DATABASE=Kawai Musical Instruments Mfg. Co., Ltd + +usb:v0F54p0101* + ID_MODEL_FROM_DATABASE=MP6 Stage Piano + +usb:v0F55* + ID_VENDOR_FROM_DATABASE=AmbiCom, Inc. + +usb:v0F5C* + ID_VENDOR_FROM_DATABASE=Prairiecomm, Inc. + +usb:v0F5D* + ID_VENDOR_FROM_DATABASE=NewAge International, LLC + +usb:v0F5Dp9455* + ID_MODEL_FROM_DATABASE=Compact Drive + +usb:v0F5F* + ID_VENDOR_FROM_DATABASE=Key Technology Corp. + +usb:v0F60* + ID_VENDOR_FROM_DATABASE=NTK, Ltd + +usb:v0F61* + ID_VENDOR_FROM_DATABASE=Varian, Inc. + +usb:v0F62* + ID_VENDOR_FROM_DATABASE=Acrox Technologies Co., Ltd + +usb:v0F62p1001* + ID_MODEL_FROM_DATABASE=Targus Mini Trackball Optical Mouse + +usb:v0F63* + ID_VENDOR_FROM_DATABASE=LeapFrog Enterprises + +usb:v0F63p0010* + ID_MODEL_FROM_DATABASE=Leapster Explorer + +usb:v0F63p0022* + ID_MODEL_FROM_DATABASE=Leap Reader + +usb:v0F63p0500* + ID_MODEL_FROM_DATABASE=Fly Fusion + +usb:v0F63p0600* + ID_MODEL_FROM_DATABASE=Leap Port Turbo + +usb:v0F63p0700* + ID_MODEL_FROM_DATABASE=POGO + +usb:v0F63p0800* + ID_MODEL_FROM_DATABASE=Didj + +usb:v0F63p0900* + ID_MODEL_FROM_DATABASE=TAGSchool + +usb:v0F63p0A00* + ID_MODEL_FROM_DATABASE=Leapster 2 + +usb:v0F63p0B00* + ID_MODEL_FROM_DATABASE=Crammer + +usb:v0F63p0C00* + ID_MODEL_FROM_DATABASE=Tag Jr + +usb:v0F63p0D00* + ID_MODEL_FROM_DATABASE=My Pal Scout + +usb:v0F63p0E00* + ID_MODEL_FROM_DATABASE=Tag32 + +usb:v0F63p0F00* + ID_MODEL_FROM_DATABASE=Tag64 + +usb:v0F63p1000* + ID_MODEL_FROM_DATABASE=Kiwi16 + +usb:v0F63p1100* + ID_MODEL_FROM_DATABASE=Leapster L2x + +usb:v0F63p1111* + ID_MODEL_FROM_DATABASE=Fly Fusion + +usb:v0F63p1300* + ID_MODEL_FROM_DATABASE=Didj UK/France (Leapster Advance) + +usb:v0F68* + ID_VENDOR_FROM_DATABASE=Kobe Steel, Ltd + +usb:v0F69* + ID_VENDOR_FROM_DATABASE=Dionex Corp. + +usb:v0F6A* + ID_VENDOR_FROM_DATABASE=Vibren Technologies, Inc. + +usb:v0F6E* + ID_VENDOR_FROM_DATABASE=INTELLIGENT SYSTEMS + +usb:v0F6Ep0100* + ID_MODEL_FROM_DATABASE=GameBoy Color Emulator + +usb:v0F6Ep0201* + ID_MODEL_FROM_DATABASE=GameBoy Advance Flash Gang Writer + +usb:v0F6Ep0202* + ID_MODEL_FROM_DATABASE=GameBoy Advance Capture + +usb:v0F6Ep0300* + ID_MODEL_FROM_DATABASE=Gamecube DOL Viewer + +usb:v0F6Ep0400* + ID_MODEL_FROM_DATABASE=NDS Emulator + +usb:v0F6Ep0401* + ID_MODEL_FROM_DATABASE=NDS UIC + +usb:v0F6Ep0402* + ID_MODEL_FROM_DATABASE=NDS Writer + +usb:v0F6Ep0403* + ID_MODEL_FROM_DATABASE=NDS Capture + +usb:v0F6Ep0404* + ID_MODEL_FROM_DATABASE=NDS Emulator (Lite) + +usb:v0F73* + ID_VENDOR_FROM_DATABASE=DFI + +usb:v0F78* + ID_VENDOR_FROM_DATABASE=Guntermann & Drunck GmbH + +usb:v0F7C* + ID_VENDOR_FROM_DATABASE=DQ Technology, Inc. + +usb:v0F7D* + ID_VENDOR_FROM_DATABASE=NetBotz, Inc. + +usb:v0F7E* + ID_VENDOR_FROM_DATABASE=Fluke Corp. + +usb:v0F88* + ID_VENDOR_FROM_DATABASE=VTech Holdings, Ltd + +usb:v0F88p3012* + ID_MODEL_FROM_DATABASE=RT2570 + +usb:v0F88p3014* + ID_MODEL_FROM_DATABASE=ZD1211B + +usb:v0F8B* + ID_VENDOR_FROM_DATABASE=Yazaki Corp. + +usb:v0F8C* + ID_VENDOR_FROM_DATABASE=Young Generation International Corp. + +usb:v0F8D* + ID_VENDOR_FROM_DATABASE=Uniwill Computer Corp. + +usb:v0F8E* + ID_VENDOR_FROM_DATABASE=Kingnet Technology Co., Ltd + +usb:v0F8F* + ID_VENDOR_FROM_DATABASE=Soma Networks + +usb:v0F97* + ID_VENDOR_FROM_DATABASE=CviLux Corp. + +usb:v0F98* + ID_VENDOR_FROM_DATABASE=CyberBank Corp. + +usb:v0F9C* + ID_VENDOR_FROM_DATABASE=Hyun Won, Inc. + +usb:v0F9Cp0301* + ID_MODEL_FROM_DATABASE=M-Any Premium DAH-610 MP3/WMA Player + +usb:v0F9Cp0332* + ID_MODEL_FROM_DATABASE=mobiBLU DAH-1200 MP3/Ogg Player + +usb:v0F9E* + ID_VENDOR_FROM_DATABASE=Lucent Technologies + +usb:v0FA3* + ID_VENDOR_FROM_DATABASE=Starconn Electronic Co., Ltd + +usb:v0FA4* + ID_VENDOR_FROM_DATABASE=ATL Technology + +usb:v0FA5* + ID_VENDOR_FROM_DATABASE=Sotec Co., Ltd + +usb:v0FA7* + ID_VENDOR_FROM_DATABASE=Epox Computer Co., Ltd + +usb:v0FA8* + ID_VENDOR_FROM_DATABASE=Logic Controls, Inc. + +usb:v0FAF* + ID_VENDOR_FROM_DATABASE=Winpoint Electronic Corp. + +usb:v0FB0* + ID_VENDOR_FROM_DATABASE=Haurtian Wire & Cable Co., Ltd + +usb:v0FB1* + ID_VENDOR_FROM_DATABASE=Inclose Design, Inc. + +usb:v0FB2* + ID_VENDOR_FROM_DATABASE=Juan-Chern Industrial Co., Ltd + +usb:v0FB6* + ID_VENDOR_FROM_DATABASE=Heber Ltd + +usb:v0FB6p3FC3* + ID_MODEL_FROM_DATABASE=Firefly X10i I/O Board (with firmware) + +usb:v0FB6p3FC4* + ID_MODEL_FROM_DATABASE=Firefly X10i I/O Board (without firmware) + +usb:v0FB8* + ID_VENDOR_FROM_DATABASE=Wistron Corp. + +usb:v0FB8p0002* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v0FB9* + ID_VENDOR_FROM_DATABASE=AACom Corp. + +usb:v0FBA* + ID_VENDOR_FROM_DATABASE=San Shing Electronics Co., Ltd + +usb:v0FBB* + ID_VENDOR_FROM_DATABASE=Bitwise Systems, Inc. + +usb:v0FC1* + ID_VENDOR_FROM_DATABASE=Mitac Internatinal Corp. + +usb:v0FC2* + ID_VENDOR_FROM_DATABASE=Plug and Jack Industrial, Inc. + +usb:v0FC5* + ID_VENDOR_FROM_DATABASE=Delcom Engineering + +usb:v0FC5p1222* + ID_MODEL_FROM_DATABASE=I/O Development Board + +usb:v0FC6* + ID_VENDOR_FROM_DATABASE=Dataplus Supplies, Inc. + +usb:v0FCA* + ID_VENDOR_FROM_DATABASE=Research In Motion, Ltd. + +usb:v0FCAp0001* + ID_MODEL_FROM_DATABASE=Blackberry Handheld + +usb:v0FCAp0004* + ID_MODEL_FROM_DATABASE=Blackberry Handheld + +usb:v0FCAp0006* + ID_MODEL_FROM_DATABASE=Blackberry Pearl + +usb:v0FCAp0008* + ID_MODEL_FROM_DATABASE=Blackberry Pearl + +usb:v0FCAp8001* + ID_MODEL_FROM_DATABASE=Blackberry Handheld + +usb:v0FCAp8004* + ID_MODEL_FROM_DATABASE=Blackberry + +usb:v0FCAp8007* + ID_MODEL_FROM_DATABASE=Blackberry Handheld + +usb:v0FCAp8010* + ID_MODEL_FROM_DATABASE=Blackberry Playbook (Connect to Windows mode) + +usb:v0FCAp8011* + ID_MODEL_FROM_DATABASE=Blackberry Playbook (Connect to Mac mode) + +usb:v0FCAp8020* + ID_MODEL_FROM_DATABASE=Blackberry Playbook (CD-Rom mode) + +usb:v0FCAp8037* + ID_MODEL_FROM_DATABASE=Blackberry PRIV + +usb:v0FCE* + ID_VENDOR_FROM_DATABASE=Sony Ericsson Mobile Communications AB + +usb:v0FCEp0076* + ID_MODEL_FROM_DATABASE=W910i (Multimedia mode) + +usb:v0FCEp00AF* + ID_MODEL_FROM_DATABASE=V640i Phone [PTP Camera] + +usb:v0FCEp00D4* + ID_MODEL_FROM_DATABASE=C902 [MTP] + +usb:v0FCEp00D9* + ID_MODEL_FROM_DATABASE=C702 Phone + +usb:v0FCEp0112* + ID_MODEL_FROM_DATABASE=W995 Walkman Phone + +usb:v0FCEp014E* + ID_MODEL_FROM_DATABASE=J108i Cedar (MTP mode) + +usb:v0FCEp015A* + ID_MODEL_FROM_DATABASE=Xperia Pro [Media Transfer Protocol] + +usb:v0FCEp0166* + ID_MODEL_FROM_DATABASE=Xperia Mini Pro + +usb:v0FCEp0167* + ID_MODEL_FROM_DATABASE=ST15i (Xperia mini) + +usb:v0FCEp0169* + ID_MODEL_FROM_DATABASE=Xperia S + +usb:v0FCEp0172* + ID_MODEL_FROM_DATABASE=Xperia P + +usb:v0FCEp0177* + ID_MODEL_FROM_DATABASE=Xperia Ion [Mass Storage] + +usb:v0FCEp0188* + ID_MODEL_FROM_DATABASE=ST26i + +usb:v0FCEp019C* + ID_MODEL_FROM_DATABASE=C6833 + +usb:v0FCEp019E* + ID_MODEL_FROM_DATABASE=C6903 + +usb:v0FCEp01A5* + ID_MODEL_FROM_DATABASE=SO-04F + +usb:v0FCEp01A7* + ID_MODEL_FROM_DATABASE=D5503 + +usb:v0FCEp01BA* + ID_MODEL_FROM_DATABASE=D6603 [Xperia Z3] + +usb:v0FCEp01BB* + ID_MODEL_FROM_DATABASE=D5803 [Xperia Z3 Compact] (MTP mode) + +usb:v0FCEp0DDE* + ID_MODEL_FROM_DATABASE=Xperia Mini Pro Bootloader + +usb:v0FCEp1010* + ID_MODEL_FROM_DATABASE=WMC Modem + +usb:v0FCEp10AF* + ID_MODEL_FROM_DATABASE=V640i Phone [PictBridge] + +usb:v0FCEp10D4* + ID_MODEL_FROM_DATABASE=C902 Phone [PictBridge] + +usb:v0FCEp2105* + ID_MODEL_FROM_DATABASE=W715 Phone + +usb:v0FCEp2137* + ID_MODEL_FROM_DATABASE=Xperia X10 mini (USB debug) + +usb:v0FCEp2138* + ID_MODEL_FROM_DATABASE=Xperia X10 mini pro (Debug) + +usb:v0FCEp2149* + ID_MODEL_FROM_DATABASE=Xperia X8 (debug) + +usb:v0FCEp214E* + ID_MODEL_FROM_DATABASE=J108i Cedar (Windows-driver mode) + +usb:v0FCEp3137* + ID_MODEL_FROM_DATABASE=Xperia X10 mini + +usb:v0FCEp3138* + ID_MODEL_FROM_DATABASE=Xperia X10 mini pro + +usb:v0FCEp3149* + ID_MODEL_FROM_DATABASE=Xperia X8 + +usb:v0FCEp514F* + ID_MODEL_FROM_DATABASE=Xperia arc S [Adb-Enable Mode] + +usb:v0FCEp5169* + ID_MODEL_FROM_DATABASE=Xperia S [Adb-Enable Mode] + +usb:v0FCEp5177* + ID_MODEL_FROM_DATABASE=Xperia Ion [Debug Mode] + +usb:v0FCEp518C* + ID_MODEL_FROM_DATABASE=C1605 [Xperia E dual] MTD mode + +usb:v0FCEp51A7* + ID_MODEL_FROM_DATABASE=D5503 (Xperia Z1 Compact) + +usb:v0FCEp614F* + ID_MODEL_FROM_DATABASE=Xperia X12 (debug mode) + +usb:v0FCEp6166* + ID_MODEL_FROM_DATABASE=Xperia Mini Pro + +usb:v0FCEp618C* + ID_MODEL_FROM_DATABASE=C1605 [Xperia E dual] MSC mode + +usb:v0FCEp715A* + ID_MODEL_FROM_DATABASE=Xperia Pro [Tethering] + +usb:v0FCEp7166* + ID_MODEL_FROM_DATABASE=Xperia Mini Pro (Tethering mode) + +usb:v0FCEp7177* + ID_MODEL_FROM_DATABASE=Xperia Ion [Tethering] + +usb:v0FCEp8004* + ID_MODEL_FROM_DATABASE=9000 Phone [Mass Storage] + +usb:v0FCEpADDE* + ID_MODEL_FROM_DATABASE=C2005 (Xperia M dual) in service mode + +usb:v0FCEpD008* + ID_MODEL_FROM_DATABASE=V800-Vodafone 802SE Phone + +usb:v0FCEpD016* + ID_MODEL_FROM_DATABASE=K750i Phone + +usb:v0FCEpD017* + ID_MODEL_FROM_DATABASE=K608i Phone + +usb:v0FCEpD019* + ID_MODEL_FROM_DATABASE=VDC EGPRS Modem + +usb:v0FCEpD025* + ID_MODEL_FROM_DATABASE=520 WMC Data Modem + +usb:v0FCEpD028* + ID_MODEL_FROM_DATABASE=W800i + +usb:v0FCEpD038* + ID_MODEL_FROM_DATABASE=W850i Phone + +usb:v0FCEpD039* + ID_MODEL_FROM_DATABASE=K800i (phone mode) + +usb:v0FCEpD041* + ID_MODEL_FROM_DATABASE=K510i Phone + +usb:v0FCEpD042* + ID_MODEL_FROM_DATABASE=W810i Phone + +usb:v0FCEpD043* + ID_MODEL_FROM_DATABASE=V630i Phone + +usb:v0FCEpD046* + ID_MODEL_FROM_DATABASE=K610i Phone + +usb:v0FCEpD065* + ID_MODEL_FROM_DATABASE=W960i Phone (PC Suite) + +usb:v0FCEpD076* + ID_MODEL_FROM_DATABASE=W910i (Phone mode) + +usb:v0FCEpD089* + ID_MODEL_FROM_DATABASE=W580i Phone (mass storage) + +usb:v0FCEpD0A1* + ID_MODEL_FROM_DATABASE=K810 + +usb:v0FCEpD0AF* + ID_MODEL_FROM_DATABASE=V640i Phone + +usb:v0FCEpD0CF* + ID_MODEL_FROM_DATABASE=MD300 Mobile Broadband Modem + +usb:v0FCEpD0D4* + ID_MODEL_FROM_DATABASE=C902 Phone [Modem] + +usb:v0FCEpD0E1* + ID_MODEL_FROM_DATABASE=MD400 Mobile Broadband Modem + +usb:v0FCEpD12A* + ID_MODEL_FROM_DATABASE=U100i Yari Phone + +usb:v0FCEpD12E* + ID_MODEL_FROM_DATABASE=Xperia X10 + +usb:v0FCEpD14E* + ID_MODEL_FROM_DATABASE=J108i Cedar (modem mode) + +usb:v0FCEpE000* + ID_MODEL_FROM_DATABASE=K810 (PictBridge mode) + +usb:v0FCEpE039* + ID_MODEL_FROM_DATABASE=K800i (msc mode) + +usb:v0FCEpE042* + ID_MODEL_FROM_DATABASE=W810i Phone + +usb:v0FCEpE043* + ID_MODEL_FROM_DATABASE=V630i Phone [Mass Storage] + +usb:v0FCEpE075* + ID_MODEL_FROM_DATABASE=K850i + +usb:v0FCEpE076* + ID_MODEL_FROM_DATABASE=W910i (Mass storage) + +usb:v0FCEpE089* + ID_MODEL_FROM_DATABASE=W580i Phone + +usb:v0FCEpE090* + ID_MODEL_FROM_DATABASE=W200 Phone (Mass Storage) + +usb:v0FCEpE0A1* + ID_MODEL_FROM_DATABASE=K810 (Mass Storage mode) + +usb:v0FCEpE0A3* + ID_MODEL_FROM_DATABASE=W660i + +usb:v0FCEpE0AF* + ID_MODEL_FROM_DATABASE=V640i Phone [Mass Storage] + +usb:v0FCEpE0D4* + ID_MODEL_FROM_DATABASE=C902 Phone [Mass Storage] + +usb:v0FCEpE0EF* + ID_MODEL_FROM_DATABASE=C905 Phone [Mass Storage] + +usb:v0FCEpE0F3* + ID_MODEL_FROM_DATABASE=W595 + +usb:v0FCEpE105* + ID_MODEL_FROM_DATABASE=W705 + +usb:v0FCEpE112* + ID_MODEL_FROM_DATABASE=W995 Phone (Mass Storage) + +usb:v0FCEpE12E* + ID_MODEL_FROM_DATABASE=X10i Phone + +usb:v0FCEpE133* + ID_MODEL_FROM_DATABASE=Vivaz + +usb:v0FCEpE14E* + ID_MODEL_FROM_DATABASE=J108i Cedar (mass-storage mode) + +usb:v0FCEpE14F* + ID_MODEL_FROM_DATABASE=Xperia Arc/X12 + +usb:v0FCEpE15A* + ID_MODEL_FROM_DATABASE=Xperia Pro [Mass Storage Class] + +usb:v0FCEpE161* + ID_MODEL_FROM_DATABASE=Xperia Ray + +usb:v0FCEpE166* + ID_MODEL_FROM_DATABASE=Xperia Mini Pro + +usb:v0FCEpE167* + ID_MODEL_FROM_DATABASE=XPERIA mini + +usb:v0FCEpE19B* + ID_MODEL_FROM_DATABASE=C2005 [Xperia M dual] (Mass Storage) + +usb:v0FCEpE1A9* + ID_MODEL_FROM_DATABASE=D5303 + +usb:v0FCEpE1AA* + ID_MODEL_FROM_DATABASE=D2303 + +usb:v0FCEpE1AD* + ID_MODEL_FROM_DATABASE=D5103 + +usb:v0FCEpE1B0* + ID_MODEL_FROM_DATABASE=D6708 + +usb:v0FCEpE1B5* + ID_MODEL_FROM_DATABASE=D2004 + +usb:v0FCEpE1BA* + ID_MODEL_FROM_DATABASE=D6683 + +usb:v0FCEpE1BB* + ID_MODEL_FROM_DATABASE=SO-02G + +usb:v0FCEpE1BC* + ID_MODEL_FROM_DATABASE=D2203 + +usb:v0FCEpE1C0* + ID_MODEL_FROM_DATABASE=SGP621 + +usb:v0FCEpE1C2* + ID_MODEL_FROM_DATABASE=D2533 + +usb:v0FCEpE1C9* + ID_MODEL_FROM_DATABASE=E6553 + +usb:v0FCEpE1CF* + ID_MODEL_FROM_DATABASE=SGP771 + +usb:v0FCEpF0FA* + ID_MODEL_FROM_DATABASE=MN800 / Smartwatch 2 (DFU mode) + +usb:v0FCF* + ID_VENDOR_FROM_DATABASE=Dynastream Innovations, Inc. + +usb:v0FCFp1003* + ID_MODEL_FROM_DATABASE=ANT Development Board + +usb:v0FCFp1004* + ID_MODEL_FROM_DATABASE=ANTUSB Stick + +usb:v0FCFp1006* + ID_MODEL_FROM_DATABASE=ANT Development Board + +usb:v0FCFp1008* + ID_MODEL_FROM_DATABASE=ANTUSB2 Stick + +usb:v0FCFp1009* + ID_MODEL_FROM_DATABASE=ANTUSB-m Stick + +usb:v0FD0* + ID_VENDOR_FROM_DATABASE=Tulip Computers B.V. + +usb:v0FD1* + ID_VENDOR_FROM_DATABASE=Giant Electronics Ltd. + +usb:v0FD2* + ID_VENDOR_FROM_DATABASE=Seac Banche + +usb:v0FD2p0001* + ID_MODEL_FROM_DATABASE=RDS 6000 + +usb:v0FD4* + ID_VENDOR_FROM_DATABASE=Tenovis GmbH & Co., KG + +usb:v0FD5* + ID_VENDOR_FROM_DATABASE=Direct Access Technology, Inc. + +usb:v0FD9* + ID_VENDOR_FROM_DATABASE=Elgato Systems GmbH + +usb:v0FD9p0011* + ID_MODEL_FROM_DATABASE=EyeTV Diversity + +usb:v0FD9p0018* + ID_MODEL_FROM_DATABASE=EyeTV Hybrid + +usb:v0FD9p0020* + ID_MODEL_FROM_DATABASE=EyeTV DTT Deluxe + +usb:v0FD9p0021* + ID_MODEL_FROM_DATABASE=EyeTV DTT + +usb:v0FD9p002A* + ID_MODEL_FROM_DATABASE=EyeTV Sat + +usb:v0FD9p002C* + ID_MODEL_FROM_DATABASE=EyeTV DTT Deluxe v2 + +usb:v0FD9p0033* + ID_MODEL_FROM_DATABASE=Video Capture + +usb:v0FD9p0037* + ID_MODEL_FROM_DATABASE=Video Capture v2 + +usb:v0FDA* + ID_VENDOR_FROM_DATABASE=Quantec Networks GmbH + +usb:v0FDAp0100* + ID_MODEL_FROM_DATABASE=quanton flight control + +usb:v0FDC* + ID_VENDOR_FROM_DATABASE=Micro Plus + +usb:v0FDE* + ID_VENDOR_FROM_DATABASE=Oregon Scientific + +usb:v0FDEpCA01* + ID_MODEL_FROM_DATABASE=WMRS200 weather station + +usb:v0FDEpCA05* + ID_MODEL_FROM_DATABASE=CM160 + +usb:v0FE0* + ID_VENDOR_FROM_DATABASE=Osterhout Design Group + +usb:v0FE0p0100* + ID_MODEL_FROM_DATABASE=Bluetooth Mouse + +usb:v0FE0p0101* + ID_MODEL_FROM_DATABASE=Bluetooth IMU + +usb:v0FE0p0200* + ID_MODEL_FROM_DATABASE=Bluetooth Keypad + +usb:v0FE2* + ID_VENDOR_FROM_DATABASE=Air Techniques + +usb:v0FE4* + ID_VENDOR_FROM_DATABASE=IN-Tech Electronics, Ltd + +usb:v0FE5* + ID_VENDOR_FROM_DATABASE=Greenconn (U.S.A.), Inc. + +usb:v0FE6* + ID_VENDOR_FROM_DATABASE=ICS Advent + +usb:v0FE6p8101* + ID_MODEL_FROM_DATABASE=DM9601 Fast Ethernet Adapter + +usb:v0FE6p811E* + ID_MODEL_FROM_DATABASE=Parallel Adapter + +usb:v0FE6p9700* + ID_MODEL_FROM_DATABASE=DM9601 Fast Ethernet Adapter + +usb:v0FE9* + ID_VENDOR_FROM_DATABASE=DVICO + +usb:v0FE9p4020* + ID_MODEL_FROM_DATABASE=TViX M-6500 + +usb:v0FE9p9010* + ID_MODEL_FROM_DATABASE=FusionRemote IR receiver + +usb:v0FE9pDB00* + ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T (MT352+LgZ201) (uninitialized) + +usb:v0FE9pDB01* + ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T (MT352+LgZ201) (initialized) + +usb:v0FE9pDB10* + ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T (MT352+Thomson7579) (uninitialized) + +usb:v0FE9pDB11* + ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T (MT352+Thomson7579) (initialized) + +usb:v0FE9pDB78* + ID_MODEL_FROM_DATABASE=FusionHDTV DVB-T Dual Digital 4 (ZL10353+xc2028/xc3028) (initialized) + +usb:v0FEA* + ID_VENDOR_FROM_DATABASE=United Computer Accessories + +usb:v0FEB* + ID_VENDOR_FROM_DATABASE=CRS Electronic Co., Ltd + +usb:v0FEC* + ID_VENDOR_FROM_DATABASE=UMC Electronics Co., Ltd + +usb:v0FED* + ID_VENDOR_FROM_DATABASE=Access Co., Ltd + +usb:v0FEE* + ID_VENDOR_FROM_DATABASE=Xsido Corp. + +usb:v0FEF* + ID_VENDOR_FROM_DATABASE=MJ Research, Inc. + +usb:v0FF6* + ID_VENDOR_FROM_DATABASE=Core Valley Co., Ltd + +usb:v0FF7* + ID_VENDOR_FROM_DATABASE=CHI SHING Computer Accessories Co., Ltd + +usb:v0FFC* + ID_VENDOR_FROM_DATABASE=Clavia DMI AB + +usb:v0FFCp0021* + ID_MODEL_FROM_DATABASE=Nord Stage 2 + +usb:v0FFD* + ID_VENDOR_FROM_DATABASE=EarlySense + +usb:v0FFDpFF00* + ID_MODEL_FROM_DATABASE=OEM + +usb:v0FFF* + ID_VENDOR_FROM_DATABASE=Aopen, Inc. + +usb:v1000* + ID_VENDOR_FROM_DATABASE=Speed Tech Corp. + +usb:v1000p153B* + ID_MODEL_FROM_DATABASE=TerraTec Electronic GmbH + +usb:v1001* + ID_VENDOR_FROM_DATABASE=Ritronics Components (S) Pte., Ltd + +usb:v1003* + ID_VENDOR_FROM_DATABASE=Sigma Corp. + +usb:v1003p0003* + ID_MODEL_FROM_DATABASE=SD14 + +usb:v1003p0100* + ID_MODEL_FROM_DATABASE=SD9/SD10 + +usb:v1004* + ID_VENDOR_FROM_DATABASE=LG Electronics, Inc. + +usb:v1004p1FAE* + ID_MODEL_FROM_DATABASE=U8120 3G Cellphone + +usb:v1004p6000* + ID_MODEL_FROM_DATABASE=Various Mobile Phones + +usb:v1004p6005* + ID_MODEL_FROM_DATABASE=T5100 + +usb:v1004p6018* + ID_MODEL_FROM_DATABASE=GM360/GD510/GW520/KP501 + +usb:v1004p618E* + ID_MODEL_FROM_DATABASE=Ally/Optimus One/Vortex (debug mode) + +usb:v1004p618F* + ID_MODEL_FROM_DATABASE=Ally/Optimus One + +usb:v1004p61C5* + ID_MODEL_FROM_DATABASE=P880 / Charge only + +usb:v1004p61C6* + ID_MODEL_FROM_DATABASE=Vortex (msc) + +usb:v1004p61CC* + ID_MODEL_FROM_DATABASE=Optimus S + +usb:v1004p61DA* + ID_MODEL_FROM_DATABASE=G2 Android Phone [tethering mode] + +usb:v1004p61F1* + ID_MODEL_FROM_DATABASE=Optimus Android Phone [LG Software mode] + +usb:v1004p61F9* + ID_MODEL_FROM_DATABASE=Optimus (Various Models) MTP Mode + +usb:v1004p61FC* + ID_MODEL_FROM_DATABASE=Optimus 3 + +usb:v1004p61FE* + ID_MODEL_FROM_DATABASE=Optimus Android Phone [USB tethering mode] + +usb:v1004p627F* + ID_MODEL_FROM_DATABASE=G3 (VS985) Android Phone (MTP/Download mode) + +usb:v1004p6300* + ID_MODEL_FROM_DATABASE=G2/Optimus Android Phone [Charge mode] + +usb:v1004p631C* + ID_MODEL_FROM_DATABASE=G2/Optimus Android Phone [MTP mode] + +usb:v1004p631D* + ID_MODEL_FROM_DATABASE=Optimus Android Phone (Camera/PTP Mode) + +usb:v1004p631E* + ID_MODEL_FROM_DATABASE=G2/Optimus Android Phone [Camera/PTP mode] + +usb:v1004p631F* + ID_MODEL_FROM_DATABASE=Optimus Android Phone (Charge Mode) + +usb:v1004p633A* + ID_MODEL_FROM_DATABASE=Ultimate 2 Android Phone L41C + +usb:v1004p633E* + ID_MODEL_FROM_DATABASE=G2/G3 Android Phone [MTP/PTP/Download mode] + +usb:v1004p6344* + ID_MODEL_FROM_DATABASE=G2 Android Phone [tethering mode] + +usb:v1004p6356* + ID_MODEL_FROM_DATABASE=Optimus Android Phone [Virtual CD mode] + +usb:v1004p6800* + ID_MODEL_FROM_DATABASE=CDMA Modem + +usb:v1004p7000* + ID_MODEL_FROM_DATABASE=LG LDP-7024D(LD)USB + +usb:v1004p91C8* + ID_MODEL_FROM_DATABASE=P880 / USB tethering + +usb:v1004pA400* + ID_MODEL_FROM_DATABASE=Renoir (KC910) + +usb:v1005* + ID_VENDOR_FROM_DATABASE=Apacer Technology, Inc. + +usb:v1005p1001* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v1005p1004* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v1005p1006* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v1005pB113* + ID_MODEL_FROM_DATABASE=Handy Steno/AH123 / Handy Steno 2.0/HT203 + +usb:v1005pB223* + ID_MODEL_FROM_DATABASE=CD-RW + 6in1 Card Reader Digital Storage / Converter + +usb:v1006* + ID_VENDOR_FROM_DATABASE=iRiver, Ltd. + +usb:v1006p3001* + ID_MODEL_FROM_DATABASE=iHP-100 + +usb:v1006p3002* + ID_MODEL_FROM_DATABASE=iHP-120/140 MP3 Player + +usb:v1006p3003* + ID_MODEL_FROM_DATABASE=H320/H340 + +usb:v1006p3004* + ID_MODEL_FROM_DATABASE=H340 (mtp) + +usb:v1009* + ID_VENDOR_FROM_DATABASE=Emuzed, Inc. + +usb:v1009p000E* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v1009p0013* + ID_MODEL_FROM_DATABASE=Angel MPEG Device + +usb:v1009p0015* + ID_MODEL_FROM_DATABASE=Lumanate Wave PAL SECAM DVBT Device + +usb:v1009p0016* + ID_MODEL_FROM_DATABASE=Lumanate Wave NTSC/ATSC Combo Device + +usb:v100A* + ID_VENDOR_FROM_DATABASE=AV Chaseway, Ltd + +usb:v100Ap2402* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v100Ap2404* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v100Ap2405* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v100Ap2406* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v100ApA0C0* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v100B* + ID_VENDOR_FROM_DATABASE=Chou Chin Industrial Co., Ltd + +usb:v100D* + ID_VENDOR_FROM_DATABASE=Netopia, Inc. + +usb:v100Dp3342* + ID_MODEL_FROM_DATABASE=Cayman 3352 DSL Modem + +usb:v100Dp3382* + ID_MODEL_FROM_DATABASE=3380 Series Network Interface + +usb:v100Dp6072* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v100Dp9031* + ID_MODEL_FROM_DATABASE=Motorola 802.11n Dualband USB Wireless Adapter + +usb:v100Dp9032* + ID_MODEL_FROM_DATABASE=Motorola 802.11n 5G USB Wireless Adapter + +usb:v100DpCB01* + ID_MODEL_FROM_DATABASE=Cayman 3341 Ethernet DSL Router + +usb:v1010* + ID_VENDOR_FROM_DATABASE=Fukuda Denshi Co., Ltd + +usb:v1011* + ID_VENDOR_FROM_DATABASE=Mobile Media Tech. + +usb:v1011p0001* + ID_MODEL_FROM_DATABASE=AccFast Mp3 + +usb:v1012* + ID_VENDOR_FROM_DATABASE=SDKM Fibres, Wires & Cables Berhad + +usb:v1013* + ID_VENDOR_FROM_DATABASE=TST-Touchless Sensor Technology AG + +usb:v1014* + ID_VENDOR_FROM_DATABASE=Densitron Technologies PLC + +usb:v1015* + ID_VENDOR_FROM_DATABASE=Softronics Pty., Ltd + +usb:v1016* + ID_VENDOR_FROM_DATABASE=Xiamen Hung's Enterprise Co., Ltd + +usb:v1017* + ID_VENDOR_FROM_DATABASE=Speedy Industrial Supplies, Pte., Ltd + +usb:v1019* + ID_VENDOR_FROM_DATABASE=Elitegroup Computer Systems (ECS) + +usb:v1019p0C55* + ID_MODEL_FROM_DATABASE=Flash Reader, Desknote UCR-61S2B + +usb:v1019p0F38* + ID_MODEL_FROM_DATABASE=Infrared Receiver + +usb:v1020* + ID_VENDOR_FROM_DATABASE=Labtec + +usb:v1020p0006* + ID_MODEL_FROM_DATABASE=Wireless Keyboard + +usb:v1020p000A* + ID_MODEL_FROM_DATABASE=Wireless Optical Mouse + +usb:v1020p0106* + ID_MODEL_FROM_DATABASE=Wireless Optical Mouse + +usb:v1022* + ID_VENDOR_FROM_DATABASE=Shinko Shoji Co., Ltd + +usb:v1025* + ID_VENDOR_FROM_DATABASE=Hyper-Paltek + +usb:v1025p005E* + ID_MODEL_FROM_DATABASE=USB DVB-T device + +usb:v1025p005F* + ID_MODEL_FROM_DATABASE=USB DVB-T device + +usb:v1025p0300* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v1025p0350* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v1026* + ID_VENDOR_FROM_DATABASE=Newly Corp. + +usb:v1027* + ID_VENDOR_FROM_DATABASE=Time Domain + +usb:v1028* + ID_VENDOR_FROM_DATABASE=Inovys Corp. + +usb:v1029* + ID_VENDOR_FROM_DATABASE=Atlantic Coast Telesys + +usb:v102A* + ID_VENDOR_FROM_DATABASE=Ramos Technology Co., Ltd + +usb:v102B* + ID_VENDOR_FROM_DATABASE=Infotronic America, Inc. + +usb:v102C* + ID_VENDOR_FROM_DATABASE=Etoms Electronics Corp. + +usb:v102Cp6151* + ID_MODEL_FROM_DATABASE=Q-Cam Sangha CIF + +usb:v102Cp6251* + ID_MODEL_FROM_DATABASE=Q-Cam VGA + +usb:v102D* + ID_VENDOR_FROM_DATABASE=Winic Corp. + +usb:v1031* + ID_VENDOR_FROM_DATABASE=Comax Technology, Inc. + +usb:v1032* + ID_VENDOR_FROM_DATABASE=C-One Technology Corp. + +usb:v1033* + ID_VENDOR_FROM_DATABASE=Nucam Corp. + +usb:v1033p0068* + ID_MODEL_FROM_DATABASE=3,5'' HDD case MD-231 + +usb:v1038* + ID_VENDOR_FROM_DATABASE=SteelSeries ApS + +usb:v1038p0100* + ID_MODEL_FROM_DATABASE=Ideazon Zboard + +usb:v1038p1361* + ID_MODEL_FROM_DATABASE=Ideazon Sensei + +usb:v1039* + ID_VENDOR_FROM_DATABASE=devolo AG + +usb:v1039p0824* + ID_MODEL_FROM_DATABASE=1866 802.11bg [Texas Instruments TNETW1450] + +usb:v1039p2140* + ID_MODEL_FROM_DATABASE=dsl+ 1100 duo + +usb:v103A* + ID_VENDOR_FROM_DATABASE=PSA + +usb:v103ApF000* + ID_MODEL_FROM_DATABASE=Actia Evo XS + +usb:v103D* + ID_VENDOR_FROM_DATABASE=Stanton + +usb:v103Dp0100* + ID_MODEL_FROM_DATABASE=ScratchAmp + +usb:v103Dp0101* + ID_MODEL_FROM_DATABASE=ScratchAmp + +usb:v1043* + ID_VENDOR_FROM_DATABASE=iCreate Technologies Corp. + +usb:v1043p160F* + ID_MODEL_FROM_DATABASE=Wireless Network Adapter + +usb:v1043p4901* + ID_MODEL_FROM_DATABASE=AV-836 Video Capture Device + +usb:v1043p8006* + ID_MODEL_FROM_DATABASE=Flash Disk 32-256 MB + +usb:v1043p8012* + ID_MODEL_FROM_DATABASE=Flash Disk 256 MB + +usb:v1044* + ID_VENDOR_FROM_DATABASE=Chu Yuen Enterprise Co., Ltd + +usb:v1044p7001* + ID_MODEL_FROM_DATABASE=Gigabyte U7000 DVB-T tuner + +usb:v1044p7002* + ID_MODEL_FROM_DATABASE=Gigabyte U8000 DVB-T tuner + +usb:v1044p7004* + ID_MODEL_FROM_DATABASE=Gigabyte U7100 DVB-T tuner + +usb:v1044p7005* + ID_MODEL_FROM_DATABASE=Gigabyte U7200 DVB-T tuner [AF9035] + +usb:v1044p7006* + ID_MODEL_FROM_DATABASE=Gigabyte U6000 DVB-T tuner [em2863] + +usb:v1044p8001* + ID_MODEL_FROM_DATABASE=GN-54G + +usb:v1044p8002* + ID_MODEL_FROM_DATABASE=GN-BR402W + +usb:v1044p8003* + ID_MODEL_FROM_DATABASE=GN-WLBM101 + +usb:v1044p8004* + ID_MODEL_FROM_DATABASE=GN-WLBZ101 802.11b Adapter + +usb:v1044p8005* + ID_MODEL_FROM_DATABASE=GN-WLBZ201 802.11b Adapter + +usb:v1044p8006* + ID_MODEL_FROM_DATABASE=GN-WBZB-M 802.11b Adapter + +usb:v1044p8007* + ID_MODEL_FROM_DATABASE=GN-WBKG + +usb:v1044p8008* + ID_MODEL_FROM_DATABASE=GN-WB01GS + +usb:v1044p800A* + ID_MODEL_FROM_DATABASE=GN-WI05GS + +usb:v1044p800B* + ID_MODEL_FROM_DATABASE=GN-WB30N 802.11n WLAN Card + +usb:v1044p800C* + ID_MODEL_FROM_DATABASE=GN-WB31N 802.11n USB WLAN Card + +usb:v1044p800D* + ID_MODEL_FROM_DATABASE=GN-WB32L 802.11n USB WLAN Card + +usb:v1046* + ID_VENDOR_FROM_DATABASE=Winbond Electronics Corp. [hex] + +usb:v1046p6694* + ID_MODEL_FROM_DATABASE=Generic W6694 USB + +usb:v1046p8901* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v1046p9967* + ID_MODEL_FROM_DATABASE=W9967CF/W9968CF Webcam IC + +usb:v1048* + ID_VENDOR_FROM_DATABASE=Targus Group International + +usb:v1048p2010* + ID_MODEL_FROM_DATABASE=4-Port hub + +usb:v104B* + ID_VENDOR_FROM_DATABASE=Mylex / Buslogic + +usb:v104C* + ID_VENDOR_FROM_DATABASE=AMCO TEC International, Inc. + +usb:v104D* + ID_VENDOR_FROM_DATABASE=Newport Corporation + +usb:v104Dp1003* + ID_MODEL_FROM_DATABASE=Model-52 LED Light Source Power Supply and Driver + +usb:v104F* + ID_VENDOR_FROM_DATABASE=WB Electronics + +usb:v104Fp0001* + ID_MODEL_FROM_DATABASE=Infinity Phoenix + +usb:v104Fp0002* + ID_MODEL_FROM_DATABASE=Smartmouse + +usb:v104Fp0003* + ID_MODEL_FROM_DATABASE=FunProgrammer + +usb:v104Fp0004* + ID_MODEL_FROM_DATABASE=Infinity Unlimited + +usb:v104Fp0006* + ID_MODEL_FROM_DATABASE=Infinity Smart + +usb:v104Fp0007* + ID_MODEL_FROM_DATABASE=Infinity Smart module + +usb:v104Fp0008* + ID_MODEL_FROM_DATABASE=Infinity CryptoKey + +usb:v104Fp0009* + ID_MODEL_FROM_DATABASE=RE-BL PlayStation 3 IR-to-Bluetooth converter + +usb:v1050* + ID_VENDOR_FROM_DATABASE=Yubico.com + +usb:v1050p0010* + ID_MODEL_FROM_DATABASE=Yubikey (v1 or v2) + +usb:v1050p0110* + ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) OTP + +usb:v1050p0111* + ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) OTP+CCID + +usb:v1050p0112* + ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) CCID + +usb:v1050p0113* + ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) U2F + +usb:v1050p0114* + ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) OTP+U2F + +usb:v1050p0115* + ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) U2F+CCID + +usb:v1050p0116* + ID_MODEL_FROM_DATABASE=Yubikey NEO(-N) OTP+U2F+CCID + +usb:v1050p0120* + ID_MODEL_FROM_DATABASE=Yubikey Touch U2F Security Key + +usb:v1050p0200* + ID_MODEL_FROM_DATABASE=Gnubby U2F + +usb:v1050p0211* + ID_MODEL_FROM_DATABASE=Gnubby + +usb:v1050p0401* + ID_MODEL_FROM_DATABASE=Yubikey 4 OTP + +usb:v1050p0402* + ID_MODEL_FROM_DATABASE=Yubikey 4 U2F + +usb:v1050p0403* + ID_MODEL_FROM_DATABASE=Yubikey 4 OTP+U2F + +usb:v1050p0404* + ID_MODEL_FROM_DATABASE=Yubikey 4 CCID + +usb:v1050p0405* + ID_MODEL_FROM_DATABASE=Yubikey 4 OTP+CCID + +usb:v1050p0406* + ID_MODEL_FROM_DATABASE=Yubikey 4 U2F+CCID + +usb:v1050p0407* + ID_MODEL_FROM_DATABASE=Yubikey 4 OTP+U2F+CCID + +usb:v1050p0410* + ID_MODEL_FROM_DATABASE=Yubikey plus OTP+U2F + +usb:v1053* + ID_VENDOR_FROM_DATABASE=Immanuel Electronics Co., Ltd + +usb:v1054* + ID_VENDOR_FROM_DATABASE=BMS International Beheer N.V. + +usb:v1054p5004* + ID_MODEL_FROM_DATABASE=DSL 7420 Loader + +usb:v1054p5005* + ID_MODEL_FROM_DATABASE=DSL 7420 LAN Modem + +usb:v1055* + ID_VENDOR_FROM_DATABASE=Complex Micro Interconnection Co., Ltd + +usb:v1056* + ID_VENDOR_FROM_DATABASE=Hsin Chen Ent Co., Ltd + +usb:v1057* + ID_VENDOR_FROM_DATABASE=ON Semiconductor + +usb:v1058* + ID_VENDOR_FROM_DATABASE=Western Digital Technologies, Inc. + +usb:v1058p0200* + ID_MODEL_FROM_DATABASE=FireWire USB Combo + +usb:v1058p0400* + ID_MODEL_FROM_DATABASE=External HDD + +usb:v1058p0500* + ID_MODEL_FROM_DATABASE=hub + +usb:v1058p0701* + ID_MODEL_FROM_DATABASE=WD Passport (WDXMS) + +usb:v1058p0702* + ID_MODEL_FROM_DATABASE=WD Passport (WDXMS) + +usb:v1058p0704* + ID_MODEL_FROM_DATABASE=My Passport Essential (WDME) + +usb:v1058p0705* + ID_MODEL_FROM_DATABASE=My Passport Elite (WDML) + +usb:v1058p070A* + ID_MODEL_FROM_DATABASE=My Passport Essential (WDBAAA), My Passport for Mac (WDBAAB), My Passport Essential SE (WDBABM), My Passport SE for Mac (WDBABW) + +usb:v1058p070B* + ID_MODEL_FROM_DATABASE=My Passport Elite (WDBAAC) + +usb:v1058p070C* + ID_MODEL_FROM_DATABASE=My Passport Studio (WDBAAE) + +usb:v1058p071A* + ID_MODEL_FROM_DATABASE=My Passport Essential (WDBAAA) + +usb:v1058p071D* + ID_MODEL_FROM_DATABASE=My Passport Studio (WDBALG) + +usb:v1058p0730* + ID_MODEL_FROM_DATABASE=My Passport Essential (WDBACY) + +usb:v1058p0732* + ID_MODEL_FROM_DATABASE=My Passport Essential SE (WDBGYS) + +usb:v1058p0740* + ID_MODEL_FROM_DATABASE=My Passport Essential (WDBACY) + +usb:v1058p0741* + ID_MODEL_FROM_DATABASE=My Passport Ultra + +usb:v1058p0742* + ID_MODEL_FROM_DATABASE=My Passport Essential SE (WDBGYS) + +usb:v1058p0748* + ID_MODEL_FROM_DATABASE=My Passport (WDBKXH, WDBY8L) + +usb:v1058p07A8* + ID_MODEL_FROM_DATABASE=My Passport (WDBBEP), My Passport for Mac (WDBLUZ) + +usb:v1058p07AE* + ID_MODEL_FROM_DATABASE=My Passport Edge for Mac (WDBJBH) + +usb:v1058p07BA* + ID_MODEL_FROM_DATABASE=PiDrive (WDLB) + +usb:v1058p0810* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBZFP) + +usb:v1058p0816* + ID_MODEL_FROM_DATABASE=My Passport Air (WDBBLW) + +usb:v1058p0820* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBMWV, WDBZFP) + +usb:v1058p0822* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBBUZ) + +usb:v1058p0824* + ID_MODEL_FROM_DATABASE=My Passport Slim (WDBPDZ) + +usb:v1058p0830* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBZFP) + +usb:v1058p0837* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBBKD) + +usb:v1058p0900* + ID_MODEL_FROM_DATABASE=MyBook Essential External HDD + +usb:v1058p0901* + ID_MODEL_FROM_DATABASE=My Book Essential Edition (Green Ring) (WDG1U) + +usb:v1058p0902* + ID_MODEL_FROM_DATABASE=My Book Pro Edition (WDG1T) + +usb:v1058p0903* + ID_MODEL_FROM_DATABASE=My Book Premium Edition + +usb:v1058p0905* + ID_MODEL_FROM_DATABASE=My Book Pro Edition II (WD10000C033-001) + +usb:v1058p0910* + ID_MODEL_FROM_DATABASE=My Book Essential Edition (Green Ring) (WDG1U) + +usb:v1058p1001* + ID_MODEL_FROM_DATABASE=Elements Desktop (WDE1U) + +usb:v1058p1003* + ID_MODEL_FROM_DATABASE=WD Elements Desktop (WDE1UBK) + +usb:v1058p1010* + ID_MODEL_FROM_DATABASE=Elements Portable (WDBAAR) + +usb:v1058p1021* + ID_MODEL_FROM_DATABASE=Elements Desktop (WDBAAU) + +usb:v1058p1023* + ID_MODEL_FROM_DATABASE=Elements SE Portable (WDBABV) + +usb:v1058p1042* + ID_MODEL_FROM_DATABASE=Elements SE Portable (WDBPCK) + +usb:v1058p1048* + ID_MODEL_FROM_DATABASE=Elements Portable (WDBU6Y) + +usb:v1058p1078* + ID_MODEL_FROM_DATABASE=Elements Portable (WDBUZG) + +usb:v1058p107C* + ID_MODEL_FROM_DATABASE=Elements Desktop (WDBWLG) + +usb:v1058p10A2* + ID_MODEL_FROM_DATABASE=Elements SE Portable (WDBPCK) + +usb:v1058p10A8* + ID_MODEL_FROM_DATABASE=Elements Portable (WDBUZG) + +usb:v1058p10B8* + ID_MODEL_FROM_DATABASE=Elements Portable (WDBU6Y, WDBUZG) + +usb:v1058p1100* + ID_MODEL_FROM_DATABASE=My Book Essential Edition 2.0 (WDH1U) + +usb:v1058p1102* + ID_MODEL_FROM_DATABASE=My Book Home Edition (WDH1CS) + +usb:v1058p1103* + ID_MODEL_FROM_DATABASE=My Book Studio + +usb:v1058p1104* + ID_MODEL_FROM_DATABASE=My Book Mirror Edition (WDH2U) + +usb:v1058p1105* + ID_MODEL_FROM_DATABASE=My Book Studio II + +usb:v1058p1110* + ID_MODEL_FROM_DATABASE=My Book Essential (WDBAAF), My Book for Mac (WDBAAG) + +usb:v1058p1111* + ID_MODEL_FROM_DATABASE=My Book Elite (WDBAAH) + +usb:v1058p1112* + ID_MODEL_FROM_DATABASE=My Book Studio (WDBAAJ), My Book Studio LX (WDBACH) + +usb:v1058p1123* + ID_MODEL_FROM_DATABASE=My Book 3.0 (WDBABP) + +usb:v1058p1130* + ID_MODEL_FROM_DATABASE=My Book Essential (WDBACW) + +usb:v1058p1140* + ID_MODEL_FROM_DATABASE=My Book Essential (WDBACW) + +usb:v1058p1230* + ID_MODEL_FROM_DATABASE=My Book (WDBFJK) + +usb:v1058p1235* + ID_MODEL_FROM_DATABASE=My Book (WDBFJK0040HBK) + +usb:v1058p2599* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WD40NMZW) + +usb:v1058p259D* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WDBBKD) + +usb:v1058p259F* + ID_MODEL_FROM_DATABASE=My Passport Ultra (WD10JMVW) + +usb:v1058p25A1* + ID_MODEL_FROM_DATABASE=Elements / My Passport (WD20NMVW) + +usb:v1058p25A2* + ID_MODEL_FROM_DATABASE=Elements 25A2 + +usb:v1058p25A3* + ID_MODEL_FROM_DATABASE=Elements Desktop (WDBWLG) + +usb:v1058p25E2* + ID_MODEL_FROM_DATABASE=My Passport (WD40NMZW) + +usb:v1058p30A0* + ID_MODEL_FROM_DATABASE=SATA adapter cable + +usb:v1059* + ID_VENDOR_FROM_DATABASE=Giesecke & Devrient GmbH + +usb:v1059p000B* + ID_MODEL_FROM_DATABASE=StarSign Bio Token 3.0 + +usb:v105B* + ID_VENDOR_FROM_DATABASE=Foxconn International, Inc. + +usb:v105BpE065* + ID_MODEL_FROM_DATABASE=BCM43142A0 Bluetooth module + +usb:v105C* + ID_VENDOR_FROM_DATABASE=Hong Ji Electric Wire & Cable (Dongguan) Co., Ltd + +usb:v105D* + ID_VENDOR_FROM_DATABASE=Delkin Devices, Inc. + +usb:v105E* + ID_VENDOR_FROM_DATABASE=Valence Semiconductor Design, Ltd + +usb:v105F* + ID_VENDOR_FROM_DATABASE=Chin Shong Enterprise Co., Ltd + +usb:v1060* + ID_VENDOR_FROM_DATABASE=Easthome Industrial Co., Ltd + +usb:v1063* + ID_VENDOR_FROM_DATABASE=Motorola Electronics Taiwan, Ltd [hex] + +usb:v1063p1555* + ID_MODEL_FROM_DATABASE=MC141555 Hub + +usb:v1063p4100* + ID_MODEL_FROM_DATABASE=SB4100 USB Cable Modem + +usb:v1065* + ID_VENDOR_FROM_DATABASE=CCYU Technology + +usb:v1065p0020* + ID_MODEL_FROM_DATABASE=USB-DVR2 Dev Board + +usb:v1065p2136* + ID_MODEL_FROM_DATABASE=EasyDisk ED1064 + +usb:v1068* + ID_VENDOR_FROM_DATABASE=Micropi Elettronica + +usb:v1068p0001* + ID_MODEL_FROM_DATABASE=CPUSB - V 1.8 - software-rights management key + +usb:v106A* + ID_VENDOR_FROM_DATABASE=Loyal Legend, Ltd + +usb:v106C* + ID_VENDOR_FROM_DATABASE=Curitel Communications, Inc. + +usb:v106Cp1101* + ID_MODEL_FROM_DATABASE=CDMA 2000 1xRTT USB modem (HX-550C) + +usb:v106Cp1102* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp1103* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp1104* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp1105* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v106Cp1106* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp1301* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v106Cp1302* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp1303* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp1304* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp1401* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v106Cp1402* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp1403* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp1501* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp1502* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp1503* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp1601* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp1602* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp1603* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp2101* + ID_MODEL_FROM_DATABASE=AudioVox 8900 Cell Phone + +usb:v106Cp2102* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp2103* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp2301* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp2302* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp2303* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp2401* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp2402* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp2403* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp2501* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp2502* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp2503* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp2601* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp2602* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp2603* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp3701* + ID_MODEL_FROM_DATABASE=Broadband Wireless modem + +usb:v106Cp3702* + ID_MODEL_FROM_DATABASE=Pantech PX-500 + +usb:v106Cp3714* + ID_MODEL_FROM_DATABASE=PANTECH USB MODEM [UM175] + +usb:v106Cp3716* + ID_MODEL_FROM_DATABASE=UMW190 Modem + +usb:v106Cp3721* + ID_MODEL_FROM_DATABASE=Option Beemo (GI0801) LTE surfstick + +usb:v106Cp3B14* + ID_MODEL_FROM_DATABASE=Option Beemo (GI0801) LTE surfstick + +usb:v106Cp3EB4* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp4101* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp4102* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp4301* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v106Cp4302* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp4401* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v106Cp4402* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp4501* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp4502* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp4601* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v106Cp4602* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp5101* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp5102* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp5301* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp5302* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp5401* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp5402* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp5501* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp5502* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp5601* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106Cp5602* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106Cp7101* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v106Cp7102* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106CpA000* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106CpA001* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106CpC100* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106CpC200* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106CpC500* + ID_MODEL_FROM_DATABASE=Packet Service Diagnostic Serial Port (WDM) + +usb:v106CpE200* + ID_MODEL_FROM_DATABASE=Packet Service + +usb:v106D* + ID_VENDOR_FROM_DATABASE=San Chieh Manufacturing, Ltd + +usb:v106E* + ID_VENDOR_FROM_DATABASE=ConectL + +usb:v106F* + ID_VENDOR_FROM_DATABASE=Money Controls + +usb:v106Fp0009* + ID_MODEL_FROM_DATABASE=CT10x Coin Transaction + +usb:v106Fp000A* + ID_MODEL_FROM_DATABASE=CR10x Coin Recycler + +usb:v106Fp000C* + ID_MODEL_FROM_DATABASE=Xchange + +usb:v1076* + ID_VENDOR_FROM_DATABASE=GCT Semiconductor, Inc. + +usb:v1076p0031* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v1076p0032* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v1076p8002* + ID_MODEL_FROM_DATABASE=LU150 LTE Modem [Yota LU150] + +usb:v107B* + ID_VENDOR_FROM_DATABASE=Gateway, Inc. + +usb:v107Bp3009* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v107Bp55B2* + ID_MODEL_FROM_DATABASE=WBU-110 802.11b Wireless Adapter [Intersil PRISM 3] + +usb:v107Bp55F2* + ID_MODEL_FROM_DATABASE=WGU-210 802.11g Adapter [Intersil ISL3886] + +usb:v107D* + ID_VENDOR_FROM_DATABASE=Arlec Australia, Ltd + +usb:v107E* + ID_VENDOR_FROM_DATABASE=Midoriya Electric Co., Ltd + +usb:v107F* + ID_VENDOR_FROM_DATABASE=KidzMouse, Inc. + +usb:v1082* + ID_VENDOR_FROM_DATABASE=Shin-Etsukaken Co., Ltd + +usb:v1083* + ID_VENDOR_FROM_DATABASE=Canon Electronics, Inc. + +usb:v1083p160C* + ID_MODEL_FROM_DATABASE=CR-55 + +usb:v1083p160F* + ID_MODEL_FROM_DATABASE=DR-1210C + +usb:v1083p1614* + ID_MODEL_FROM_DATABASE=DR-4010C + +usb:v1083p1617* + ID_MODEL_FROM_DATABASE=DR-2510C + +usb:v1083p1618* + ID_MODEL_FROM_DATABASE=DR-X10C + +usb:v1083p161A* + ID_MODEL_FROM_DATABASE=CR-25 + +usb:v1083p161B* + ID_MODEL_FROM_DATABASE=DR-2010C Scanner + +usb:v1083p161D* + ID_MODEL_FROM_DATABASE=DR-3010C + +usb:v1083p1620* + ID_MODEL_FROM_DATABASE=DR-7090C + +usb:v1083p1622* + ID_MODEL_FROM_DATABASE=DR-9050C + +usb:v1083p1623* + ID_MODEL_FROM_DATABASE=DR-7550C + +usb:v1083p1624* + ID_MODEL_FROM_DATABASE=DR-6050C + +usb:v1083p1626* + ID_MODEL_FROM_DATABASE=DR-6010C + +usb:v1083p162C* + ID_MODEL_FROM_DATABASE=P-150 Scanner + +usb:v1083p1638* + ID_MODEL_FROM_DATABASE=DR-6030C + +usb:v1083p1639* + ID_MODEL_FROM_DATABASE=CR-135i + +usb:v1083p163E* + ID_MODEL_FROM_DATABASE=DR-M160 + +usb:v1083p163F* + ID_MODEL_FROM_DATABASE=DR-M140 + +usb:v1083p1640* + ID_MODEL_FROM_DATABASE=DR-C125 + +usb:v1083p1641* + ID_MODEL_FROM_DATABASE=DR-P215 + +usb:v1083p1648* + ID_MODEL_FROM_DATABASE=FSU-201 + +usb:v1083p164A* + ID_MODEL_FROM_DATABASE=DR-C130 + +usb:v1083p164B* + ID_MODEL_FROM_DATABASE=DR-P208 + +usb:v1083p164F* + ID_MODEL_FROM_DATABASE=DR-G1130 + +usb:v1083p1650* + ID_MODEL_FROM_DATABASE=DR-G1100 + +usb:v1083p1651* + ID_MODEL_FROM_DATABASE=DR-C120 + +usb:v1083p1654* + ID_MODEL_FROM_DATABASE=DR-F120 + +usb:v1083p1657* + ID_MODEL_FROM_DATABASE=DR-M1060 + +usb:v1083p1658* + ID_MODEL_FROM_DATABASE=DR-C225 + +usb:v1083p1659* + ID_MODEL_FROM_DATABASE=DR-P215II + +usb:v1083p165D* + ID_MODEL_FROM_DATABASE=DR-P208II + +usb:v1084* + ID_VENDOR_FROM_DATABASE=Pantech Co., Ltd + +usb:v108A* + ID_VENDOR_FROM_DATABASE=Chloride Power Protection + +usb:v108B* + ID_VENDOR_FROM_DATABASE=Grand-tek Technology Co., Ltd + +usb:v108Bp0005* + ID_MODEL_FROM_DATABASE=HID Keyboard/Mouse PS/2 Translator + +usb:v108C* + ID_VENDOR_FROM_DATABASE=Robert Bosch GmbH + +usb:v108E* + ID_VENDOR_FROM_DATABASE=Lotes Co., Ltd. + +usb:v1091* + ID_VENDOR_FROM_DATABASE=Numerik Jena + +usb:v1091p8101* + ID_MODEL_FROM_DATABASE=Absoflex + +usb:v1099* + ID_VENDOR_FROM_DATABASE=Surface Optics Corp. + +usb:v109A* + ID_VENDOR_FROM_DATABASE=DATASOFT Systems GmbH + +usb:v109B* + ID_VENDOR_FROM_DATABASE=Hisense + +usb:v109Bp9118* + ID_MODEL_FROM_DATABASE=Medion P4013 Mobile + +usb:v109F* + ID_VENDOR_FROM_DATABASE=eSOL Co., Ltd + +usb:v109Fp3163* + ID_MODEL_FROM_DATABASE=Trigem Mobile SmartDisplay84 + +usb:v109Fp3164* + ID_MODEL_FROM_DATABASE=Trigem Mobile SmartDisplay121 + +usb:v10A0* + ID_VENDOR_FROM_DATABASE=Hirotech, Inc. + +usb:v10A3* + ID_VENDOR_FROM_DATABASE=Mitsubishi Materials Corp. + +usb:v10A9* + ID_VENDOR_FROM_DATABASE=SK Teletech Co., Ltd + +usb:v10A9p1102* + ID_MODEL_FROM_DATABASE=Sky Love Actually IM-U460K + +usb:v10A9p1104* + ID_MODEL_FROM_DATABASE=Sky Vega IM-A650S + +usb:v10A9p1105* + ID_MODEL_FROM_DATABASE=VEGA Android composite + +usb:v10A9p1106* + ID_MODEL_FROM_DATABASE=VEGA Android composite + +usb:v10A9p1107* + ID_MODEL_FROM_DATABASE=VEGA Android composite + +usb:v10A9p1108* + ID_MODEL_FROM_DATABASE=VEGA Android composite + +usb:v10A9p1109* + ID_MODEL_FROM_DATABASE=VEGA Android composite + +usb:v10A9p6021* + ID_MODEL_FROM_DATABASE=SIRIUS alpha + +usb:v10A9p6031* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6032* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6033* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6034* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6035* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6036* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6037* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6050* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6051* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6052* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6053* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6054* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6055* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6056* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6057* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6058* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6059* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p6080* + ID_MODEL_FROM_DATABASE=MHS291LVW LTE Modem [Verizon Jetpack 4G LTE Mobile Hotspot MHS291L] (Zero CD Mode) + +usb:v10A9p6085* + ID_MODEL_FROM_DATABASE=MHS291LVW LTE Modem [Verizon Jetpack 4G LTE Mobile Hotspot MHS291L] (Modem Mode) + +usb:v10A9p7031* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p7032* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p7033* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p7034* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p7035* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p7036* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10A9p7037* + ID_MODEL_FROM_DATABASE=Pantech Android composite + +usb:v10AA* + ID_VENDOR_FROM_DATABASE=Cables To Go + +usb:v10AB* + ID_VENDOR_FROM_DATABASE=USI Co., Ltd + +usb:v10ABp1002* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v10ABp1003* + ID_MODEL_FROM_DATABASE=BC02-EXT in DFU + +usb:v10ABp1005* + ID_MODEL_FROM_DATABASE=Bluetooth Adptr + +usb:v10ABp1006* + ID_MODEL_FROM_DATABASE=BC04-EXT in DFU + +usb:v10ABp10C5* + ID_MODEL_FROM_DATABASE=Sony-Ericsson / Samsung DataCable + +usb:v10AC* + ID_VENDOR_FROM_DATABASE=Honeywell, Inc. + +usb:v10AE* + ID_VENDOR_FROM_DATABASE=Princeton Technology Corp. + +usb:v10AF* + ID_VENDOR_FROM_DATABASE=Liebert Corp. + +usb:v10AFp0000* + ID_MODEL_FROM_DATABASE=UPS + +usb:v10AFp0001* + ID_MODEL_FROM_DATABASE=PowerSure PSA UPS + +usb:v10AFp0002* + ID_MODEL_FROM_DATABASE=PowerSure PST UPS + +usb:v10AFp0003* + ID_MODEL_FROM_DATABASE=PowerSure PSP UPS + +usb:v10AFp0004* + ID_MODEL_FROM_DATABASE=PowerSure PSI UPS + +usb:v10AFp0005* + ID_MODEL_FROM_DATABASE=UPStation GXT 2U UPS + +usb:v10AFp0006* + ID_MODEL_FROM_DATABASE=UPStation GXT UPS + +usb:v10AFp0007* + ID_MODEL_FROM_DATABASE=Nfinity Power Systems UPS + +usb:v10AFp0008* + ID_MODEL_FROM_DATABASE=PowerSure Interactive UPS + +usb:v10B5* + ID_VENDOR_FROM_DATABASE=Comodo (PLX?) + +usb:v10B5p9060* + ID_MODEL_FROM_DATABASE=Test Board + +usb:v10B8* + ID_VENDOR_FROM_DATABASE=DiBcom + +usb:v10B8p0BB8* + ID_MODEL_FROM_DATABASE=DVB-T reference design (MOD300) (cold) + +usb:v10B8p0BB9* + ID_MODEL_FROM_DATABASE=DVB-T reference design (MOD300) (warm) + +usb:v10B8p0BC6* + ID_MODEL_FROM_DATABASE=DVB-T reference design (MOD3000P) (cold) + +usb:v10B8p0BC7* + ID_MODEL_FROM_DATABASE=DVB-T reference design (MOD3000P) (warm) + +usb:v10BB* + ID_VENDOR_FROM_DATABASE=TM Technology, Inc. + +usb:v10BC* + ID_VENDOR_FROM_DATABASE=Dinging Technology Co., Ltd + +usb:v10BD* + ID_VENDOR_FROM_DATABASE=TMT Technology, Inc. + +usb:v10BDp1427* + ID_MODEL_FROM_DATABASE=Ethernet + +usb:v10BF* + ID_VENDOR_FROM_DATABASE=SmartHome + +usb:v10BFp0001* + ID_MODEL_FROM_DATABASE=SmartHome PowerLinc + +usb:v10C3* + ID_VENDOR_FROM_DATABASE=Universal Laser Systems, Inc. + +usb:v10C3p00A4* + ID_MODEL_FROM_DATABASE=ULS PLS Series Laser Engraver Firmware Loader + +usb:v10C3p00A5* + ID_MODEL_FROM_DATABASE=ULS Print Support + +usb:v10C4* + ID_VENDOR_FROM_DATABASE=Silicon Labs + +usb:v10C4p0002* + ID_MODEL_FROM_DATABASE=F32x USBXpress Device + +usb:v10C4p0003* + ID_MODEL_FROM_DATABASE=CommandIR + +usb:v10C4p800A* + ID_MODEL_FROM_DATABASE=SPORTident + +usb:v10C4p800B* + ID_MODEL_FROM_DATABASE=AES + +usb:v10C4p8030* + ID_MODEL_FROM_DATABASE=K4JRG Ham Radio devices + +usb:v10C4p8044* + ID_MODEL_FROM_DATABASE=USB Debug Adapter + +usb:v10C4p804E* + ID_MODEL_FROM_DATABASE=Software Bisque Paramount ME + +usb:v10C4p80A9* + ID_MODEL_FROM_DATABASE=CP210x to UART Bridge Controller + +usb:v10C4p80C4* + ID_MODEL_FROM_DATABASE=Infrared Thermometer Adapter + +usb:v10C4p80CA* + ID_MODEL_FROM_DATABASE=ATM2400 Sensor Device + +usb:v10C4p813F* + ID_MODEL_FROM_DATABASE=tams EasyControl + +usb:v10C4p8149* + ID_MODEL_FROM_DATABASE=West Mountain Radio Computerized Battery Analyzer + +usb:v10C4p814A* + ID_MODEL_FROM_DATABASE=West Mountain Radio RIGblaster P&P + +usb:v10C4p814B* + ID_MODEL_FROM_DATABASE=West Mountain Radio RIGtalk + +usb:v10C4p818A* + ID_MODEL_FROM_DATABASE=Silicon Labs FM Radio Reference Design + +usb:v10C4p81E8* + ID_MODEL_FROM_DATABASE=Zephyr BioHarness + +usb:v10C4p834B* + ID_MODEL_FROM_DATABASE=Infrared Online Sensor Adapter + +usb:v10C4p834E* + ID_MODEL_FROM_DATABASE=Infrared Sensor Adapter + +usb:v10C4p8460* + ID_MODEL_FROM_DATABASE=Sangoma Wanpipe VoiceTime + +usb:v10C4p8461* + ID_MODEL_FROM_DATABASE=Sangoma U100 + +usb:v10C4p8470* + ID_MODEL_FROM_DATABASE=Juniper Networks BX Series System Console + +usb:v10C4p8477* + ID_MODEL_FROM_DATABASE=Balluff RFID Reader + +usb:v10C4p8496* + ID_MODEL_FROM_DATABASE=SiLabs Cypress FW downloader + +usb:v10C4p8497* + ID_MODEL_FROM_DATABASE=SiLabs Cypress EVB + +usb:v10C4p84FB* + ID_MODEL_FROM_DATABASE=Infrared Blackbody Adapter + +usb:v10C4p8508* + ID_MODEL_FROM_DATABASE=RS485 Adapter + +usb:v10C4p8605* + ID_MODEL_FROM_DATABASE=dilitronics ESoLUX solar lighting controller + +usb:v10C4p8660* + ID_MODEL_FROM_DATABASE=Netronics CANdoISO + +usb:v10C4p86BC* + ID_MODEL_FROM_DATABASE=C8051F34x AudioDelay [AD-340] + +usb:v10C4p8789* + ID_MODEL_FROM_DATABASE=C8051F34x Extender & EDID MGR [EMX-DVI] + +usb:v10C4p87BE* + ID_MODEL_FROM_DATABASE=C8051F34x HDMI Audio Extractor [EMX-HD-AUD] + +usb:v10C4p8863* + ID_MODEL_FROM_DATABASE=C8051F34x Bootloader + +usb:v10C4p8897* + ID_MODEL_FROM_DATABASE=C8051F38x HDMI Splitter [UHBX] + +usb:v10C4p88C9* + ID_MODEL_FROM_DATABASE=AES HID device + +usb:v10C4p8918* + ID_MODEL_FROM_DATABASE=C8051F38x HDMI Audio Extractor [VSA-HA-DP] + +usb:v10C4p8973* + ID_MODEL_FROM_DATABASE=C8051F38x HDMI Extender [UHBX-8X] + +usb:v10C4p89C6* + ID_MODEL_FROM_DATABASE=SPORTident HID device + +usb:v10C4p89E1* + ID_MODEL_FROM_DATABASE=C8051F38x HDMI Extender [UHBX-SW3-WP] + +usb:v10C4p89FB* + ID_MODEL_FROM_DATABASE=Qivicon ZigBee Stick + +usb:v10C4p8A3C* + ID_MODEL_FROM_DATABASE=C8051F38x HDBaseT Receiver [UHBX-R-XT] + +usb:v10C4p8A6C* + ID_MODEL_FROM_DATABASE=C8051F38x 4K HDMI Audio Extractor [EMX-AMP] + +usb:v10C4p8ACB* + ID_MODEL_FROM_DATABASE=C8051F38x HDBaseT Wall Plate Receiver with IR, RS-232, and PoH [UHBX-R-WP] + +usb:v10C4p8AF8* + ID_MODEL_FROM_DATABASE=C8051F38x 4K HDMI Audio Extractor w/Audio Amplifier, HDBT Input, Line Audio Input RS-232 Ports and IP Control [VSA-X21] + +usb:v10C4p8B8C* + ID_MODEL_FROM_DATABASE=C8051F38x 4K HDMI Audio Extractor w/Audio Amplifier, HDBT Input, Line Audio Input RS-232 Ports and IP Control [SC-3H] + +usb:v10C4p8DB5* + ID_MODEL_FROM_DATABASE=C8051F38x CATx HDMI Receiver with USB [EX-HDU-R] + +usb:v10C4p8DB6* + ID_MODEL_FROM_DATABASE=C8051F38x CATx HDMI Receiver + +usb:v10C4pEA60* + ID_MODEL_FROM_DATABASE=CP210x UART Bridge + +usb:v10C4pEA61* + ID_MODEL_FROM_DATABASE=CP210x UART Bridge + +usb:v10C4pEA63* + ID_MODEL_FROM_DATABASE=CP210x UART Bridge + +usb:v10C4pEA70* + ID_MODEL_FROM_DATABASE=CP2105 Dual UART Bridge + +usb:v10C4pEA71* + ID_MODEL_FROM_DATABASE=CP2108 Quad UART Bridge + +usb:v10C4pEA80* + ID_MODEL_FROM_DATABASE=CP2110 HID UART Bridge + +usb:v10C4pEA90* + ID_MODEL_FROM_DATABASE=CP2112 HID I2C Bridge + +usb:v10C4pEA91* + ID_MODEL_FROM_DATABASE=CP2112 HID SMBus/I2C Bridge for CP2614 Evaluation Kit + +usb:v10C4pEA93* + ID_MODEL_FROM_DATABASE=CP2112 HID SMBus/I2C Bridge for CP2615 Evaluation Kit + +usb:v10C4pEAB0* + ID_MODEL_FROM_DATABASE=CP2114 I2S Audio Bridge + +usb:v10C4pEAC0* + ID_MODEL_FROM_DATABASE=CP2614 MFi Accessory Digital Audio Bridge + +usb:v10C4pEAC1* + ID_MODEL_FROM_DATABASE=CP2615 I2S Audio Bridge + +usb:v10C4pEAC9* + ID_MODEL_FROM_DATABASE=EFM8UB1 Bootloader + +usb:v10C4pEACA* + ID_MODEL_FROM_DATABASE=EFM8UB2 Bootloader + +usb:v10C4pEACB* + ID_MODEL_FROM_DATABASE=EFM8UB3 Bootloader + +usb:v10C5* + ID_VENDOR_FROM_DATABASE=Sanei Electric, Inc. + +usb:v10C5p819A* + ID_MODEL_FROM_DATABASE=FM Radio + +usb:v10C6* + ID_VENDOR_FROM_DATABASE=Intec, Inc. + +usb:v10CB* + ID_VENDOR_FROM_DATABASE=Eratech + +usb:v10CC* + ID_VENDOR_FROM_DATABASE=GBM Connector Co., Ltd + +usb:v10CCp1101* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v10CD* + ID_VENDOR_FROM_DATABASE=Kycon, Inc. + +usb:v10CE* + ID_VENDOR_FROM_DATABASE=Silicon Labs + +usb:v10CEp0007* + ID_MODEL_FROM_DATABASE=Shinko/Sinfonia CHC-S1245 + +usb:v10CEp000E* + ID_MODEL_FROM_DATABASE=Shinko/Sinfonia CHC-S2145 + +usb:v10CEp0019* + ID_MODEL_FROM_DATABASE=Shinko/Sinfonia CHC-S6145 + +usb:v10CEp001D* + ID_MODEL_FROM_DATABASE=Shinko/Sinfonia CHC-S6245 + +usb:v10CEp001E* + ID_MODEL_FROM_DATABASE=Ciaat Brava 21 + +usb:v10CEpEA6A* + ID_MODEL_FROM_DATABASE=MobiData EDGE USB Modem + +usb:v10CF* + ID_VENDOR_FROM_DATABASE=Velleman Components, Inc. + +usb:v10CFp2011* + ID_MODEL_FROM_DATABASE=R-Engine MPEG2 encoder/decoder + +usb:v10CFp5500* + ID_MODEL_FROM_DATABASE=8055 Experiment Interface Board (address=0) + +usb:v10CFp5501* + ID_MODEL_FROM_DATABASE=8055 Experiment Interface Board (address=1) + +usb:v10CFp5502* + ID_MODEL_FROM_DATABASE=8055 Experiment Interface Board (address=2) + +usb:v10CFp5503* + ID_MODEL_FROM_DATABASE=8055 Experiment Interface Board (address=3) + +usb:v10D1* + ID_VENDOR_FROM_DATABASE=Hottinger Baldwin Measurement + +usb:v10D1p0101* + ID_MODEL_FROM_DATABASE=USB-Module for Spider8, CP32 + +usb:v10D1p0202* + ID_MODEL_FROM_DATABASE=CP22 - Communication Processor + +usb:v10D1p0301* + ID_MODEL_FROM_DATABASE=CP42 - Communication Processor + +usb:v10D2* + ID_VENDOR_FROM_DATABASE=RayComposer - R. Adams + +usb:v10D2p5243* + ID_MODEL_FROM_DATABASE=RayComposer + +usb:v10D4* + ID_VENDOR_FROM_DATABASE=Man Boon Manufactory, Ltd + +usb:v10D5* + ID_VENDOR_FROM_DATABASE=Uni Class Technology Co., Ltd + +usb:v10D5p0004* + ID_MODEL_FROM_DATABASE=PS/2 Converter + +usb:v10D5p5552* + ID_MODEL_FROM_DATABASE=KVM Human Interface Composite Device (Keyboard/Mouse ports) + +usb:v10D5p55A2* + ID_MODEL_FROM_DATABASE=2Port KVMSwitcher + +usb:v10D6* + ID_VENDOR_FROM_DATABASE=Actions Semiconductor Co., Ltd + +usb:v10D6p0C02* + ID_MODEL_FROM_DATABASE=BioniQ 1001 Tablet + +usb:v10D6p1000* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v10D6p1100* + ID_MODEL_FROM_DATABASE=MPMan MP-Ki 128 MP3 Player/Recorder + +usb:v10D6p1101* + ID_MODEL_FROM_DATABASE=D-Wave 2GB MP4 Player / AK1025 MP3/MP4 Player + +usb:v10D6p2200* + ID_MODEL_FROM_DATABASE=Acer MP-120 MP3 player + +usb:v10D6p8888* + ID_MODEL_FROM_DATABASE=ADFU Device + +usb:v10D6pFF51* + ID_MODEL_FROM_DATABASE=ADFU Device + +usb:v10D6pFF61* + ID_MODEL_FROM_DATABASE=MP4 Player + +usb:v10D6pFF66* + ID_MODEL_FROM_DATABASE=Craig 2GB MP3/Video Player + +usb:v10DE* + ID_VENDOR_FROM_DATABASE=Authenex, Inc. + +usb:v10DF* + ID_VENDOR_FROM_DATABASE=In-Win Development, Inc. + +usb:v10DFp0500* + ID_MODEL_FROM_DATABASE=iAPP CR-e500 Card reader + +usb:v10E0* + ID_VENDOR_FROM_DATABASE=Post-Op Video, Inc. + +usb:v10E1* + ID_VENDOR_FROM_DATABASE=CablePlus, Ltd + +usb:v10E2* + ID_VENDOR_FROM_DATABASE=Nada Electronics, Ltd + +usb:v10EC* + ID_VENDOR_FROM_DATABASE=Vast Technologies, Inc. + +usb:v10F0* + ID_VENDOR_FROM_DATABASE=Nexio Co., Ltd + +usb:v10F0p2002* + ID_MODEL_FROM_DATABASE=iNexio Touchscreen controller + +usb:v10F1* + ID_VENDOR_FROM_DATABASE=Importek + +usb:v10F1p1A08* + ID_MODEL_FROM_DATABASE=Internal Webcam + +usb:v10F1p1A1E* + ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam 1.3M + +usb:v10F1p1A2A* + ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam + +usb:v10F1p1A2E* + ID_MODEL_FROM_DATABASE=HP Truevision HD Integrated Webcam + +usb:v10F5* + ID_VENDOR_FROM_DATABASE=Turtle Beach + +usb:v10F5p0200* + ID_MODEL_FROM_DATABASE=Audio Advantage Roadie + +usb:v10FB* + ID_VENDOR_FROM_DATABASE=Pictos Technologies, Inc. + +usb:v10FD* + ID_VENDOR_FROM_DATABASE=Anubis Electronics, Ltd + +usb:v10FDp7E50* + ID_MODEL_FROM_DATABASE=FlyCam Usb 100 + +usb:v10FDp804D* + ID_MODEL_FROM_DATABASE=Typhoon Webshot II Webcam [zc0301] + +usb:v10FDp8050* + ID_MODEL_FROM_DATABASE=FlyCAM-USB 300 XP2 + +usb:v10FDpDE00* + ID_MODEL_FROM_DATABASE=WinFast WalkieTV WDM Capture Driver. + +usb:v10FE* + ID_VENDOR_FROM_DATABASE=Thrane & Thrane + +usb:v10FEp000C* + ID_MODEL_FROM_DATABASE=TT-3750 BGAN-XL Radio Module + +usb:v1100* + ID_VENDOR_FROM_DATABASE=VirTouch, Ltd + +usb:v1100p0001* + ID_MODEL_FROM_DATABASE=VTPlayer VTP-1 Braille Mouse + +usb:v1101* + ID_VENDOR_FROM_DATABASE=EasyPass Industrial Co., Ltd + +usb:v1101p0001* + ID_MODEL_FROM_DATABASE=FSK Electronics Super GSM Reader + +usb:v1108* + ID_VENDOR_FROM_DATABASE=Brightcom Technologies, Ltd + +usb:v110A* + ID_VENDOR_FROM_DATABASE=Moxa Technologies Co., Ltd. + +usb:v110Ap1250* + ID_MODEL_FROM_DATABASE=UPort 1250 2-Port RS-232/422/485 + +usb:v110Ap1251* + ID_MODEL_FROM_DATABASE=UPort 1250I 2-Port RS-232/422/485 with Isolation + +usb:v110Ap1410* + ID_MODEL_FROM_DATABASE=UPort 1410 4-Port RS-232 + +usb:v110Ap1450* + ID_MODEL_FROM_DATABASE=UPort 1450 4-Port RS-232/422/485 + +usb:v110Ap1451* + ID_MODEL_FROM_DATABASE=UPort 1450I 4-Port RS-232/422/485 with Isolation + +usb:v110Ap1613* + ID_MODEL_FROM_DATABASE=UPort 1610-16 16-Port RS-232 + +usb:v110Ap1618* + ID_MODEL_FROM_DATABASE=UPort 1610-8 8-Port RS-232 + +usb:v110Ap1653* + ID_MODEL_FROM_DATABASE=UPort 1650-16 16-Port RS-232/422/485 + +usb:v110Ap1658* + ID_MODEL_FROM_DATABASE=UPort 1650-8 8-Port RS-232/422/485 + +usb:v1110* + ID_VENDOR_FROM_DATABASE=Analog Devices Canada, Ltd (Allied Telesyn) + +usb:v1110p5C01* + ID_MODEL_FROM_DATABASE=Huawei MT-882 Remote NDIS Network Device + +usb:v1110p6489* + ID_MODEL_FROM_DATABASE=ADSL ETH/USB RTR + +usb:v1110p9000* + ID_MODEL_FROM_DATABASE=ADSL LAN Adapter + +usb:v1110p9001* + ID_MODEL_FROM_DATABASE=ADSL Loader + +usb:v1110p900F* + ID_MODEL_FROM_DATABASE=AT-AR215 DSL Modem + +usb:v1110p9010* + ID_MODEL_FROM_DATABASE=AT-AR215 DSL Modem + +usb:v1110p9021* + ID_MODEL_FROM_DATABASE=ADSL WAN Adapter + +usb:v1110p9022* + ID_MODEL_FROM_DATABASE=ADSL Loader + +usb:v1110p9023* + ID_MODEL_FROM_DATABASE=ADSL WAN Adapter + +usb:v1110p9024* + ID_MODEL_FROM_DATABASE=ADSL Loader + +usb:v1110p9031* + ID_MODEL_FROM_DATABASE=ADSL LAN Adapter + +usb:v1110p9032* + ID_MODEL_FROM_DATABASE=ADSL Loader + +usb:v1111* + ID_VENDOR_FROM_DATABASE=Pandora International Ltd. + +usb:v1111p8888* + ID_MODEL_FROM_DATABASE=Evolution Device + +usb:v1112* + ID_VENDOR_FROM_DATABASE=YM ELECTRIC CO., Ltd + +usb:v1113* + ID_VENDOR_FROM_DATABASE=Medion AG + +usb:v1113pA0A2* + ID_MODEL_FROM_DATABASE=Active Sync device + +usb:v111E* + ID_VENDOR_FROM_DATABASE=VSO Electric Co., Ltd + +usb:v112A* + ID_VENDOR_FROM_DATABASE=RedRat + +usb:v112Ap0001* + ID_MODEL_FROM_DATABASE=RedRat3 IR Transceiver + +usb:v112Ap0005* + ID_MODEL_FROM_DATABASE=RedRat3II IR Transceiver + +usb:v112E* + ID_VENDOR_FROM_DATABASE=Master Hill Electric Wire and Cable Co., Ltd + +usb:v112F* + ID_VENDOR_FROM_DATABASE=Cellon International, Inc. + +usb:v1130* + ID_VENDOR_FROM_DATABASE=Tenx Technology, Inc. + +usb:v1130p0001* + ID_MODEL_FROM_DATABASE=BlyncLight + +usb:v1130p0002* + ID_MODEL_FROM_DATABASE=iBuddy + +usb:v1130p0202* + ID_MODEL_FROM_DATABASE=Rocket Launcher + +usb:v1130p6604* + ID_MODEL_FROM_DATABASE=MCE IR-Receiver + +usb:v1130p660C* + ID_MODEL_FROM_DATABASE=Foot Pedal/Thermometer + +usb:v1130p6626* + ID_MODEL_FROM_DATABASE=Key + +usb:v1130p6806* + ID_MODEL_FROM_DATABASE=Keychain photo frame + +usb:v1130pC301* + ID_MODEL_FROM_DATABASE=Digital Photo viewer [Wallet Pix] + +usb:v1130pF211* + ID_MODEL_FROM_DATABASE=TP6911 Audio Headset + +usb:v1131* + ID_VENDOR_FROM_DATABASE=Integrated System Solution Corp. + +usb:v1131p1001* + ID_MODEL_FROM_DATABASE=KY-BT100 Bluetooth Adapter + +usb:v1131p1002* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v1131p1003* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v1131p1004* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v1132* + ID_VENDOR_FROM_DATABASE=Toshiba Corp., Digital Media Equipment [hex] + +usb:v1132p4331* + ID_MODEL_FROM_DATABASE=PDR-M4/M5/M70 Digital Camera + +usb:v1132p4332* + ID_MODEL_FROM_DATABASE=PDR-M60 Digital Camera + +usb:v1132p4333* + ID_MODEL_FROM_DATABASE=PDR-M2300/PDR-M700 + +usb:v1132p4334* + ID_MODEL_FROM_DATABASE=PDR-M65 + +usb:v1132p4335* + ID_MODEL_FROM_DATABASE=PDR-M61 + +usb:v1132p4337* + ID_MODEL_FROM_DATABASE=PDR-M11 + +usb:v1132p4338* + ID_MODEL_FROM_DATABASE=PDR-M25 + +usb:v1136* + ID_VENDOR_FROM_DATABASE=CTS Electronincs + +usb:v1136p3131* + ID_MODEL_FROM_DATABASE=CTS LS515 + +usb:v113C* + ID_VENDOR_FROM_DATABASE=Arin Tech Co., Ltd + +usb:v113D* + ID_VENDOR_FROM_DATABASE=Mapower Electronics Co., Ltd + +usb:v113F* + ID_VENDOR_FROM_DATABASE=Integrated Biometrics, LLC + +usb:v113Fp1020* + ID_MODEL_FROM_DATABASE=Watson Two-Finger Roll Scanner + +usb:v113Fp1100* + ID_MODEL_FROM_DATABASE=Columbo Single-Finger Scanner + +usb:v1141* + ID_VENDOR_FROM_DATABASE=V One Multimedia, Pte., Ltd + +usb:v1142* + ID_VENDOR_FROM_DATABASE=CyberScan Technologies, Inc. + +usb:v1142p0709* + ID_MODEL_FROM_DATABASE=Cyberview High Speed Scanner + +usb:v1145* + ID_VENDOR_FROM_DATABASE=Japan Radio Company + +usb:v1145p0001* + ID_MODEL_FROM_DATABASE=AirH PHONE AH-J3001V/J3002V + +usb:v1146* + ID_VENDOR_FROM_DATABASE=Shimane SANYO Electric Co., Ltd. + +usb:v1147* + ID_VENDOR_FROM_DATABASE=Ever Great Electric Wire and Cable Co., Ltd + +usb:v114B* + ID_VENDOR_FROM_DATABASE=Sphairon Access Systems GmbH + +usb:v114Bp0110* + ID_MODEL_FROM_DATABASE=Turbolink UB801R WLAN Adapter + +usb:v114Bp0150* + ID_MODEL_FROM_DATABASE=Turbolink UB801RE Wireless 802.11g 54Mbps Network Adapter [RTL8187] + +usb:v114C* + ID_VENDOR_FROM_DATABASE=Tinius Olsen Testing Machine Co., Inc. + +usb:v114D* + ID_VENDOR_FROM_DATABASE=Alpha Imaging Technology Corp. + +usb:v114F* + ID_VENDOR_FROM_DATABASE=Wavecom + +usb:v114Fp1234* + ID_MODEL_FROM_DATABASE=Fastrack Xtend FXT001 Modem + +usb:v115B* + ID_VENDOR_FROM_DATABASE=Salix Technology Co., Ltd. + +usb:v1162* + ID_VENDOR_FROM_DATABASE=Secugen Corp. + +usb:v1163* + ID_VENDOR_FROM_DATABASE=DeLorme Publishing, Inc. + +usb:v1163p0100* + ID_MODEL_FROM_DATABASE=Earthmate GPS (orig) + +usb:v1163p0200* + ID_MODEL_FROM_DATABASE=Earthmate GPS (LT-20, LT-40) + +usb:v1163p2020* + ID_MODEL_FROM_DATABASE=Earthmate GPS (PN-40) + +usb:v1164* + ID_VENDOR_FROM_DATABASE=YUAN High-Tech Development Co., Ltd + +usb:v1164p0300* + ID_MODEL_FROM_DATABASE=ELSAVISION 460D + +usb:v1164p0601* + ID_MODEL_FROM_DATABASE=Analog TV Tuner + +usb:v1164p0900* + ID_MODEL_FROM_DATABASE=TigerBird BMP837 USB2.0 WDM Encoder + +usb:v1164p0BC7* + ID_MODEL_FROM_DATABASE=Digital TV Tuner + +usb:v1164p521B* + ID_MODEL_FROM_DATABASE=MC521A mini Card ATSC Tuner + +usb:v1164p6601* + ID_MODEL_FROM_DATABASE=Digital TV Tuner Card [RTL2832U] + +usb:v1165* + ID_VENDOR_FROM_DATABASE=Telson Electronics Co., Ltd + +usb:v1166* + ID_VENDOR_FROM_DATABASE=Bantam Interactive Technologies + +usb:v1167* + ID_VENDOR_FROM_DATABASE=Salient Systems Corp. + +usb:v1168* + ID_VENDOR_FROM_DATABASE=BizConn International Corp. + +usb:v116E* + ID_VENDOR_FROM_DATABASE=Gigastorage Corp. + +usb:v116F* + ID_VENDOR_FROM_DATABASE=Silicon 10 Technology Corp. + +usb:v116Fp0005* + ID_MODEL_FROM_DATABASE=Flash Card Reader + +usb:v116FpC108* + ID_MODEL_FROM_DATABASE=Flash Card Reader + +usb:v116FpC109* + ID_MODEL_FROM_DATABASE=Flash Card Reader + +usb:v1175* + ID_VENDOR_FROM_DATABASE=Shengyih Steel Mold Co., Ltd + +usb:v117D* + ID_VENDOR_FROM_DATABASE=Santa Electronic, Inc. + +usb:v117E* + ID_VENDOR_FROM_DATABASE=JNC, Inc. + +usb:v1182* + ID_VENDOR_FROM_DATABASE=Venture Corp., Ltd + +usb:v1183* + ID_VENDOR_FROM_DATABASE=Compaq Computer Corp. [hex] (Digital Dream ??) + +usb:v1183p0001* + ID_MODEL_FROM_DATABASE=DigitalDream l'espion XS + +usb:v1183p19C7* + ID_MODEL_FROM_DATABASE=ISDN TA + +usb:v1183p4008* + ID_MODEL_FROM_DATABASE=56k FaxModem + +usb:v1183p504A* + ID_MODEL_FROM_DATABASE=PJB-100 Personal Jukebox + +usb:v1184* + ID_VENDOR_FROM_DATABASE=Kyocera Elco Corp. + +usb:v1188* + ID_VENDOR_FROM_DATABASE=Bloomberg L.P. + +usb:v1189* + ID_VENDOR_FROM_DATABASE=Acer Communications & Multimedia + +usb:v1189p0893* + ID_MODEL_FROM_DATABASE=EP-1427X-2 Ethernet Adapter [Acer] + +usb:v118F* + ID_VENDOR_FROM_DATABASE=You Yang Technology Co., Ltd + +usb:v1190* + ID_VENDOR_FROM_DATABASE=Tripace + +usb:v1191* + ID_VENDOR_FROM_DATABASE=Loyalty Founder Enterprise Co., Ltd + +usb:v1196* + ID_VENDOR_FROM_DATABASE=Yankee Robotics, LLC + +usb:v1196p0010* + ID_MODEL_FROM_DATABASE=Trifid Camera without code + +usb:v1196p0011* + ID_MODEL_FROM_DATABASE=Trifid Camera + +usb:v1197* + ID_VENDOR_FROM_DATABASE=Technoimagia Co., Ltd + +usb:v1198* + ID_VENDOR_FROM_DATABASE=StarShine Technology Corp. + +usb:v1199* + ID_VENDOR_FROM_DATABASE=Sierra Wireless, Inc. + +usb:v1199p0019* + ID_MODEL_FROM_DATABASE=AC595U + +usb:v1199p0021* + ID_MODEL_FROM_DATABASE=AC597E + +usb:v1199p0024* + ID_MODEL_FROM_DATABASE=MC5727 CDMA modem + +usb:v1199p0110* + ID_MODEL_FROM_DATABASE=Composite Device + +usb:v1199p0112* + ID_MODEL_FROM_DATABASE=CDMA 1xEVDO PC Card, AirCard 580 + +usb:v1199p0120* + ID_MODEL_FROM_DATABASE=AC595U + +usb:v1199p0218* + ID_MODEL_FROM_DATABASE=MC5720 Wireless Modem + +usb:v1199p6467* + ID_MODEL_FROM_DATABASE=MP Series Network Adapter + +usb:v1199p6468* + ID_MODEL_FROM_DATABASE=MP Series Network Adapter + +usb:v1199p6469* + ID_MODEL_FROM_DATABASE=MP Series Network Adapter + +usb:v1199p6802* + ID_MODEL_FROM_DATABASE=MC8755 Device + +usb:v1199p6803* + ID_MODEL_FROM_DATABASE=MC8765 Device + +usb:v1199p6804* + ID_MODEL_FROM_DATABASE=MC8755 Device + +usb:v1199p6805* + ID_MODEL_FROM_DATABASE=MC8765 Device + +usb:v1199p6812* + ID_MODEL_FROM_DATABASE=MC8775 Device + +usb:v1199p6820* + ID_MODEL_FROM_DATABASE=AC875 Device + +usb:v1199p6832* + ID_MODEL_FROM_DATABASE=MC8780 Device + +usb:v1199p6833* + ID_MODEL_FROM_DATABASE=MC8781 Device + +usb:v1199p683A* + ID_MODEL_FROM_DATABASE=MC8785 Device + +usb:v1199p683C* + ID_MODEL_FROM_DATABASE=Mobile Broadband 3G/UMTS (MC8790 Device) + +usb:v1199p6850* + ID_MODEL_FROM_DATABASE=AirCard 880 Device + +usb:v1199p6851* + ID_MODEL_FROM_DATABASE=AirCard 881 Device + +usb:v1199p6852* + ID_MODEL_FROM_DATABASE=AirCard 880E Device + +usb:v1199p6853* + ID_MODEL_FROM_DATABASE=AirCard 881E Device + +usb:v1199p6854* + ID_MODEL_FROM_DATABASE=AirCard 885 Device + +usb:v1199p6856* + ID_MODEL_FROM_DATABASE=ATT "USB Connect 881" + +usb:v1199p6870* + ID_MODEL_FROM_DATABASE=MC8780 Device + +usb:v1199p6871* + ID_MODEL_FROM_DATABASE=MC8781 Device + +usb:v1199p6893* + ID_MODEL_FROM_DATABASE=MC8777 Device + +usb:v1199p68A3* + ID_MODEL_FROM_DATABASE=MC8700 Modem + +usb:v1199p68AA* + ID_MODEL_FROM_DATABASE=4G LTE adapter + +usb:v1199p9000* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem (QDL mode) + +usb:v1199p9001* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v1199p9002* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v1199p9003* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v1199p9004* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v1199p9005* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v1199p9006* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v1199p9007* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v1199p9008* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v1199p9009* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v1199p900A* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v1199p9013* + ID_MODEL_FROM_DATABASE=Sierra Wireless Gobi 3000 Modem device (MC8355) + +usb:v1199p9055* + ID_MODEL_FROM_DATABASE=Gobi 9x15 Multimode 3G/4G LTE Modem (NAT mode) + +usb:v1199p9057* + ID_MODEL_FROM_DATABASE=Gobi 9x15 Multimode 3G/4G LTE Modem (IP passthrough mode) + +usb:v119A* + ID_VENDOR_FROM_DATABASE=ZHAN QI Technology Co., Ltd + +usb:v119B* + ID_VENDOR_FROM_DATABASE=ruwido austria GmbH + +usb:v119Bp0400* + ID_MODEL_FROM_DATABASE=Infrared Keyboard V2.01 + +usb:v11A0* + ID_VENDOR_FROM_DATABASE=Chipcon AS + +usb:v11A0pEB11* + ID_MODEL_FROM_DATABASE=CC2400EB 2.0 ZigBee Sniffer + +usb:v11A3* + ID_VENDOR_FROM_DATABASE=Technovas Co., Ltd + +usb:v11A3p8031* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v11A3p8032* + ID_MODEL_FROM_DATABASE=MP3 Player + +usb:v11AA* + ID_VENDOR_FROM_DATABASE=GlobalMedia Group, LLC + +usb:v11AAp1518* + ID_MODEL_FROM_DATABASE=iREZ K2 + +usb:v11AB* + ID_VENDOR_FROM_DATABASE=Exito Electronics Co., Ltd + +usb:v11AC* + ID_VENDOR_FROM_DATABASE=Nike + +usb:v11ACp6565* + ID_MODEL_FROM_DATABASE=FuelBand + +usb:v11B0* + ID_VENDOR_FROM_DATABASE=ATECH FLASH TECHNOLOGY + +usb:v11B0p6208* + ID_MODEL_FROM_DATABASE=PRO-28U + +usb:v11BE* + ID_VENDOR_FROM_DATABASE=R&D International NV + +usb:v11BEpF0A0* + ID_MODEL_FROM_DATABASE=Martin Maxxyz DMX + +usb:v11C0* + ID_VENDOR_FROM_DATABASE=Betop + +usb:v11C0p5506* + ID_MODEL_FROM_DATABASE=Gamepad + +usb:v11C5* + ID_VENDOR_FROM_DATABASE=Inmax + +usb:v11C5p0521* + ID_MODEL_FROM_DATABASE=IMT-0521 Smartcard Reader + +usb:v11CA* + ID_VENDOR_FROM_DATABASE=VeriFone Inc + +usb:v11CAp0207* + ID_MODEL_FROM_DATABASE=PIN Pad VX 810 + +usb:v11CAp0220* + ID_MODEL_FROM_DATABASE=PIN Pad VX 805 + +usb:v11DB* + ID_VENDOR_FROM_DATABASE=Topfield Co., Ltd. + +usb:v11DBp1000* + ID_MODEL_FROM_DATABASE=PVR + +usb:v11DBp1100* + ID_MODEL_FROM_DATABASE=PVR + +usb:v11E6* + ID_VENDOR_FROM_DATABASE=K.I. Technology Co. Ltd. + +usb:v11F5* + ID_VENDOR_FROM_DATABASE=Siemens AG + +usb:v11F5p0001* + ID_MODEL_FROM_DATABASE=SX1 + +usb:v11F5p0003* + ID_MODEL_FROM_DATABASE=Mobile phone USB cable + +usb:v11F5p0004* + ID_MODEL_FROM_DATABASE=X75 + +usb:v11F5p0005* + ID_MODEL_FROM_DATABASE=SXG75/EF81 + +usb:v11F5p0008* + ID_MODEL_FROM_DATABASE=UMTS/HSDPA Data Card + +usb:v11F5p0101* + ID_MODEL_FROM_DATABASE=RCU Connect + +usb:v11F6* + ID_VENDOR_FROM_DATABASE=Prolific + +usb:v11F6p2001* + ID_MODEL_FROM_DATABASE=Willcom WSIM + +usb:v11F7* + ID_VENDOR_FROM_DATABASE=Alcatel (?) + +usb:v11F7p02DF* + ID_MODEL_FROM_DATABASE=Serial cable (v2) for TD-10 Mobile Phone + +usb:v1203* + ID_VENDOR_FROM_DATABASE=TSC Auto ID Technology Co., Ltd + +usb:v1203p0140* + ID_MODEL_FROM_DATABASE=TTP-245C + +usb:v1209* + ID_VENDOR_FROM_DATABASE=Generic + +usb:v1209p0001* + ID_MODEL_FROM_DATABASE=pid.codes Test PID + +usb:v1209p01C0* + ID_MODEL_FROM_DATABASE=Input Club Kiibohd Device + +usb:v1209p01CB* + ID_MODEL_FROM_DATABASE=Input Club Kiibohd Device Bootloader + +usb:v1209p0256* + ID_MODEL_FROM_DATABASE=Schwalm & Tate LLC pISO Raspberry Pi Hat + +usb:v1209p053A* + ID_MODEL_FROM_DATABASE=Hackerspace San Salvador HSSV SAMR21-Mote + +usb:v1209p0CBD* + ID_MODEL_FROM_DATABASE=Andrzej Szombierski kuku.eu.org keyboard + +usb:v1209p0D32* + ID_MODEL_FROM_DATABASE=ODrive Robotics ODrive v3 + +usb:v1209p1001* + ID_MODEL_FROM_DATABASE=InterBiometrics Hub + +usb:v1209p1002* + ID_MODEL_FROM_DATABASE=InterBiometrics Relais + +usb:v1209p1003* + ID_MODEL_FROM_DATABASE=InterBiometrics IBSecureCam-P + +usb:v1209p1004* + ID_MODEL_FROM_DATABASE=InterBiometrics IBSecureCam-O + +usb:v1209p1005* + ID_MODEL_FROM_DATABASE=InterBiometrics IBSecureCam-N + +usb:v1209p1006* + ID_MODEL_FROM_DATABASE=InterBiometrics Mini IO-Board + +usb:v1209p1007* + ID_MODEL_FROM_DATABASE=e-radionica.com Croduino SAMD + +usb:v1209p1986* + ID_MODEL_FROM_DATABASE=dgrubb Jaguar Tap + +usb:v1209p1AB5* + ID_MODEL_FROM_DATABASE=Arachnid Labs Tsunami + +usb:v1209p1AB6* + ID_MODEL_FROM_DATABASE=Arachnid Labs Tsunami Bootloader + +usb:v1209p2000* + ID_MODEL_FROM_DATABASE=Zygmunt Krynicki Lantern Brightness Sensor + +usb:v1209p2001* + ID_MODEL_FROM_DATABASE=OSHEC Pi-pilot opensource and openhardware autopilot system + +usb:v1209p2002* + ID_MODEL_FROM_DATABASE=Peter Lawrence PIC16F1-USB-DFU-Bootloader + +usb:v1209p2003* + ID_MODEL_FROM_DATABASE=Peter Lawrence SAMDx1-USB-DFU-Bootloader + +usb:v1209p2004* + ID_MODEL_FROM_DATABASE=GCBASIC Serial CDC Stack + +usb:v1209p2005* + ID_MODEL_FROM_DATABASE=GCBASIC OakTree Stack + +usb:v1209p2006* + ID_MODEL_FROM_DATABASE=GCBASIC Simulation Stack + +usb:v1209p2016* + ID_MODEL_FROM_DATABASE=Cupkee + +usb:v1209p2017* + ID_MODEL_FROM_DATABASE=Benjamin Shockley Mini SAM + +usb:v1209p2020* + ID_MODEL_FROM_DATABASE=Captain Credible Gate Crystal + +usb:v1209p2048* + ID_MODEL_FROM_DATABASE=Housedillon.com MRF49XA Transciever + +usb:v1209p2100* + ID_MODEL_FROM_DATABASE=TinyFPGA B1 and B2 Boards + +usb:v1209p2101* + ID_MODEL_FROM_DATABASE=TinyFPGA A-Series Programmer + +usb:v1209p2200* + ID_MODEL_FROM_DATABASE=Dygma Shortcut Bootloader + +usb:v1209p2201* + ID_MODEL_FROM_DATABASE=Dygma Shortcut Keyboard + +usb:v1209p2222* + ID_MODEL_FROM_DATABASE=LabConnect Signalgenerator + +usb:v1209p2300* + ID_MODEL_FROM_DATABASE=Keyboardio Model 01 Bootloader + +usb:v1209p2301* + ID_MODEL_FROM_DATABASE=Keyboardio Model 01 + +usb:v1209p2323* + ID_MODEL_FROM_DATABASE=bytewerk.org candleLight + +usb:v1209p2327* + ID_MODEL_FROM_DATABASE=K.T.E.C. Bootloader Device + +usb:v1209p2328* + ID_MODEL_FROM_DATABASE=K.T.E.C. Keyboard Device + +usb:v1209p2333* + ID_MODEL_FROM_DATABASE=Kai Ryu Kimera + +usb:v1209p2334* + ID_MODEL_FROM_DATABASE=Kai Ryu Staryu + +usb:v1209p2335* + ID_MODEL_FROM_DATABASE=Portwell Sense8 + +usb:v1209p2336* + ID_MODEL_FROM_DATABASE=Portwell Sense8 + +usb:v1209p2337* + ID_MODEL_FROM_DATABASE=/Dev /Net + +usb:v1209p2342* + ID_MODEL_FROM_DATABASE=Andreas Bogk Big Red Button + +usb:v1209p2345* + ID_MODEL_FROM_DATABASE=VV-Soft Simple Generic HID IO + +usb:v1209p2357* + ID_MODEL_FROM_DATABASE=KarolKucza TinyPassword + +usb:v1209p2400* + ID_MODEL_FROM_DATABASE=phooky Snap-Pad + +usb:v1209p2488* + ID_MODEL_FROM_DATABASE=Peter Lawrence CMSIS-DAP Dapper Miser + +usb:v1209p2552* + ID_MODEL_FROM_DATABASE=ProjectIota Electrolink + +usb:v1209p2600* + ID_MODEL_FROM_DATABASE=Majenko Technologies chipKIT Lenny + +usb:v1209p2635* + ID_MODEL_FROM_DATABASE=Sevinz GameBot + +usb:v1209p2800* + ID_MODEL_FROM_DATABASE=Entropic Engineering Triangulation + +usb:v1209p2801* + ID_MODEL_FROM_DATABASE=Entropic Engineering Object Manipulation + +usb:v1209p2A00* + ID_MODEL_FROM_DATABASE=mooware Wii adapter + +usb:v1209p2A01* + ID_MODEL_FROM_DATABASE=mooware SNES adapter + +usb:v1209p3000* + ID_MODEL_FROM_DATABASE=lloyd3000 + +usb:v1209p3100* + ID_MODEL_FROM_DATABASE=OpenSimHardware Pedals & Buttons Controller + +usb:v1209p317E* + ID_MODEL_FROM_DATABASE=Codecrete Wirekite + +usb:v1209p3210* + ID_MODEL_FROM_DATABASE=OSH Lab, LLC Magic Keys + +usb:v1209p3333* + ID_MODEL_FROM_DATABASE=LabConnect Digitalnetzteil + +usb:v1209p3690* + ID_MODEL_FROM_DATABASE=Kigakudoh TouchMIDI32 + +usb:v1209p4096* + ID_MODEL_FROM_DATABASE=CynaraKrewe Cynara + +usb:v1209p414C* + ID_MODEL_FROM_DATABASE=Adi Linden + +usb:v1209p414D* + ID_MODEL_FROM_DATABASE=Adi Linden + +usb:v1209p4242* + ID_MODEL_FROM_DATABASE=Komakallio Astrophotography Community KomaHub Remote Power Switch + +usb:v1209p4256* + ID_MODEL_FROM_DATABASE=CuVoodoo BusVoodoo multi-protocol debugging adapter + +usb:v1209p4321* + ID_MODEL_FROM_DATABASE=mooltipass Offline Password Keeper Bootloader + +usb:v1209p4322* + ID_MODEL_FROM_DATABASE=mooltipass Arduino Sketch + +usb:v1209p4356* + ID_MODEL_FROM_DATABASE=CuVoodoo firmware + +usb:v1209p4443* + ID_MODEL_FROM_DATABASE=j1rie IRMP_STM32 Bootloader + +usb:v1209p4444* + ID_MODEL_FROM_DATABASE=j1rie IRMP_STM32 + +usb:v1209p4545* + ID_MODEL_FROM_DATABASE=SlothCo Enterprises Teletype Adapter + +usb:v1209p4646* + ID_MODEL_FROM_DATABASE=SmartPID SPC1000 + +usb:v1209p4748* + ID_MODEL_FROM_DATABASE=Kate Gray GHETT-iO Bootloader + +usb:v1209p4750* + ID_MODEL_FROM_DATABASE=Chris Pavlina (c4757p) C4-x computer (development interface) + +usb:v1209p4757* + ID_MODEL_FROM_DATABASE=Chris Pavlina (c4757p) WCP52 Gain/Phase Analyzer + +usb:v1209p4801* + ID_MODEL_FROM_DATABASE=Wojciech Krutnik NVMemProg + +usb:v1209p4C60* + ID_MODEL_FROM_DATABASE=MightyPork GEX module + +usb:v1209p4C61* + ID_MODEL_FROM_DATABASE=MightyPork GEX wireless dongle + +usb:v1209p4D53* + ID_MODEL_FROM_DATABASE=mindsensors.com NXTCam5 + +usb:v1209p5038* + ID_MODEL_FROM_DATABASE=frotz.net mdebug rswd protocol + +usb:v1209p5039* + ID_MODEL_FROM_DATABASE=frotz.net lpcboot protocol + +usb:v1209p5050* + ID_MODEL_FROM_DATABASE=trebb ISO50 + +usb:v1209p5222* + ID_MODEL_FROM_DATABASE=telavivmakers attami + +usb:v1209p53C0* + ID_MODEL_FROM_DATABASE=SatoshiLabs TREZOR Bootloader + +usb:v1209p53C1* + ID_MODEL_FROM_DATABASE=SatoshiLabs TREZOR + +usb:v1209p5432* + ID_MODEL_FROM_DATABASE=Open Programmer + +usb:v1209p5457* + ID_MODEL_FROM_DATABASE=Openlab.Taipei Taiwanduino + +usb:v1209p571C* + ID_MODEL_FROM_DATABASE=StreetoArcade PancadariaStick + +usb:v1209p5A22* + ID_MODEL_FROM_DATABASE=ikari_01 sd2snes + +usb:v1209p6000* + ID_MODEL_FROM_DATABASE=Pulsar Heavy Industries Cenx4 + +usb:v1209p600D* + ID_MODEL_FROM_DATABASE=Makdaam N93 Interface + +usb:v1209p6464* + ID_MODEL_FROM_DATABASE=Electric Exploits Shinewave + +usb:v1209p6502* + ID_MODEL_FROM_DATABASE=jj1bdx avrhwrng v2rev1 + +usb:v1209p6570* + ID_MODEL_FROM_DATABASE=Iowa Scaled Engineering, LLC CKT-AVRPROGRAMMER + +usb:v1209p6666* + ID_MODEL_FROM_DATABASE=Talpa Chen VSFLogic + +usb:v1209p6667* + ID_MODEL_FROM_DATABASE=SensePost Universal Serial aBUSe - Generic HID + +usb:v1209p6742* + ID_MODEL_FROM_DATABASE=NPK Cubitel Atomic Force Microscope + +usb:v1209p6809* + ID_MODEL_FROM_DATABASE=Tach Radio Doppelganger + +usb:v1209p6948* + ID_MODEL_FROM_DATABASE=MySensors Sensebender Gateway BootLoader + +usb:v1209p6949* + ID_MODEL_FROM_DATABASE=MySensors Sensebender Gateway + +usb:v1209p6BCF* + ID_MODEL_FROM_DATABASE=blaste Gameboy Cart Flasher + +usb:v1209p7000* + ID_MODEL_FROM_DATABASE=Secalot Dongle + +usb:v1209p7001* + ID_MODEL_FROM_DATABASE=Secalot Bootloader + +usb:v1209p70B1* + ID_MODEL_FROM_DATABASE=Sutajio Ko-Usagi (Kosagi) Tomu + +usb:v1209p7331* + ID_MODEL_FROM_DATABASE=Dangerous Prototypes Bus Pirate Next Gen CDC + +usb:v1209p7332* + ID_MODEL_FROM_DATABASE=Dangerous Prototypes Bus Pirate Next Gen Logic Analyzer + +usb:v1209p7401* + ID_MODEL_FROM_DATABASE=Beststream-jp Tool_CDC + +usb:v1209p7530* + ID_MODEL_FROM_DATABASE=PotentialLabs Refflion - IoT Development Board - Bootloader + +usb:v1209p7531* + ID_MODEL_FROM_DATABASE=PotentialLabs Refflion - IoT Development Board - Sketch + +usb:v1209p7551* + ID_MODEL_FROM_DATABASE=The Tessel Project Tessel 2 + +usb:v1209p7777* + ID_MODEL_FROM_DATABASE=circuitvalley IO Board V3 + +usb:v1209p7778* + ID_MODEL_FROM_DATABASE=circuitvalley IO Board V3 Bootloader + +usb:v1209p7BD0* + ID_MODEL_FROM_DATABASE=pokey9000 Tiny Bit Dingus + +usb:v1209p8000* + ID_MODEL_FROM_DATABASE=Autonomii NODii 2 + +usb:v1209p8086* + ID_MODEL_FROM_DATABASE=MisfitTech Nano Zero Bootloader + +usb:v1209p8087* + ID_MODEL_FROM_DATABASE=MisfitTech Nano Zero + +usb:v1209p8123* + ID_MODEL_FROM_DATABASE=Danyboard M0 bootloader + +usb:v1209p812A* + ID_MODEL_FROM_DATABASE=Danyboard M0 + +usb:v1209p813A* + ID_MODEL_FROM_DATABASE=MickMad HACK Bootloader + +usb:v1209p813B* + ID_MODEL_FROM_DATABASE=MickMad HACK Sketch + +usb:v1209p8242* + ID_MODEL_FROM_DATABASE=Tom Wimmenhove Electronics NBS-DAC 192/24 UAC1 + +usb:v1209p8243* + ID_MODEL_FROM_DATABASE=Tom Wimmenhove Electronics NBS-DAC 192/24 UAC2 + +usb:v1209p8472* + ID_MODEL_FROM_DATABASE=Shantea Controls OpenDeck + +usb:v1209p8661* + ID_MODEL_FROM_DATABASE=ProgHQ TL866 programmer + +usb:v1209p8844* + ID_MODEL_FROM_DATABASE=munia.io MUNIA + +usb:v1209p8888* + ID_MODEL_FROM_DATABASE=Blinkinlabs POV Pendant + +usb:v1209p8889* + ID_MODEL_FROM_DATABASE=Blinkinlabs POV Pendant (bootloader) + +usb:v1209p8B00* + ID_MODEL_FROM_DATABASE=ReSwitched Libtransistor Serial Console + +usb:v1209p9021* + ID_MODEL_FROM_DATABASE=Connected Community Hackerspace ESPlant + +usb:v1209p9317* + ID_MODEL_FROM_DATABASE=Sutajio Ko-Usagi (Kosagi) Palawan-Tx + +usb:v1209p9999* + ID_MODEL_FROM_DATABASE=Sandeepan Sengupta CodeBridge Infineo + +usb:v1209p9DB5* + ID_MODEL_FROM_DATABASE=PD Buddy Sink + +usb:v1209pA033* + ID_MODEL_FROM_DATABASE=area0x33 Memtype + +usb:v1209pA100* + ID_MODEL_FROM_DATABASE=KB LES Narsil analog breakout + +usb:v1209pA10C* + ID_MODEL_FROM_DATABASE=KB LES Aminoacid Synthesizer + +usb:v1209pA1E5* + ID_MODEL_FROM_DATABASE=Atreus Keyboards Atreus Keyboard + +usb:v1209pA3A4* + ID_MODEL_FROM_DATABASE=MK::Box MK::Kbd + +usb:v1209pA3A5* + ID_MODEL_FROM_DATABASE=MK::Box MK::Kbd Bootloader + +usb:v1209pA55A* + ID_MODEL_FROM_DATABASE=Forever Young Software ATTINY2313 + +usb:v1209pA602* + ID_MODEL_FROM_DATABASE=Robotips RTBoard + +usb:v1209pA7EA* + ID_MODEL_FROM_DATABASE=area3001 Knixx SW04 + +usb:v1209pA800* + ID_MODEL_FROM_DATABASE=sowbug.com WebLight + +usb:v1209pA8B0* + ID_MODEL_FROM_DATABASE=Intelectron BootWare + +usb:v1209pA8B1* + ID_MODEL_FROM_DATABASE=Intelectron FrameWare + +usb:v1209pAA00* + ID_MODEL_FROM_DATABASE=Serg Oskin LinuxCNC HID Extender + +usb:v1209pAA0B* + ID_MODEL_FROM_DATABASE=Open Bionics + +usb:v1209pAB3D* + ID_MODEL_FROM_DATABASE=3DArtists Alligator board + +usb:v1209pABBA* + ID_MODEL_FROM_DATABASE=CoinWISE SafeWISE + +usb:v1209pABC0* + ID_MODEL_FROM_DATABASE=Omzlo controller + +usb:v1209pABCD* + ID_MODEL_FROM_DATABASE=Sandeepan Sengupta CodeBridge + +usb:v1209pABD1* + ID_MODEL_FROM_DATABASE=OpenMV Cam + +usb:v1209pACDC* + ID_MODEL_FROM_DATABASE=Gediminas Zukaitis midi-grid + +usb:v1209pACE5* + ID_MODEL_FROM_DATABASE=SimAces Panel Ace + +usb:v1209pACED* + ID_MODEL_FROM_DATABASE=Open Lighting Project Ja Rule Device + +usb:v1209pACEE* + ID_MODEL_FROM_DATABASE=Open Lighting Project Ja Rule Bootloader + +usb:v1209pADB0* + ID_MODEL_FROM_DATABASE=tibounise ADB converter + +usb:v1209pADDA* + ID_MODEL_FROM_DATABASE=MicroPython Boards + +usb:v1209pB007* + ID_MODEL_FROM_DATABASE=Konsgn Global_Boot + +usb:v1209pB00B* + ID_MODEL_FROM_DATABASE=CrapLab Random Device + +usb:v1209pB010* + ID_MODEL_FROM_DATABASE=IObitZ CodeBridge + +usb:v1209pB01D* + ID_MODEL_FROM_DATABASE=WyoLum VeloKey + +usb:v1209pB058* + ID_MODEL_FROM_DATABASE=Model B, LLC Holoseat + +usb:v1209pB0B0* + ID_MODEL_FROM_DATABASE=Monero Hardware Monero Bootloader + +usb:v1209pB100* + ID_MODEL_FROM_DATABASE=ptrandem iBizi + +usb:v1209pB101* + ID_MODEL_FROM_DATABASE=IObitZ Infineo + +usb:v1209pB195* + ID_MODEL_FROM_DATABASE=flehrad Big Switch PCB + +usb:v1209pBAB1* + ID_MODEL_FROM_DATABASE=ElectronicCats Meow Meow + +usb:v1209pBABE* + ID_MODEL_FROM_DATABASE=brunofreitas.com STM32 HID Bootloader + +usb:v1209pBAD1* + ID_MODEL_FROM_DATABASE=Gregory POTEAU CommLinkUSB + +usb:v1209pBAD2* + ID_MODEL_FROM_DATABASE=Gregory POTEAU XLinkUSB + +usb:v1209pBADE* + ID_MODEL_FROM_DATABASE=Semarme SemarmeHID + +usb:v1209pBB00* + ID_MODEL_FROM_DATABASE=keyplus split keyboard firmware + +usb:v1209pBB01* + ID_MODEL_FROM_DATABASE=keyplus xusb bootloader + +usb:v1209pBB02* + ID_MODEL_FROM_DATABASE=keyplus nRF24 wireless keyboard dongle + +usb:v1209pBB03* + ID_MODEL_FROM_DATABASE=keyplus nrf24lu1p-512 bootloader + +usb:v1209pBB05* + ID_MODEL_FROM_DATABASE=keyplus kp_boot_32u4 bootloader + +usb:v1209pBEBA* + ID_MODEL_FROM_DATABASE=serasidis.gr STM32 HID Bootloader + +usb:v1209pBEEF* + ID_MODEL_FROM_DATABASE=Modal MC-USB + +usb:v1209pC001* + ID_MODEL_FROM_DATABASE=Cynteract Alpha + +usb:v1209pC0C0* + ID_MODEL_FROM_DATABASE=Geppetto_Electronics Orthrus + +usb:v1209pC0C1* + ID_MODEL_FROM_DATABASE=Michael Bemmerl cookie-mouse + +usb:v1209pC0CA* + ID_MODEL_FROM_DATABASE=Jean THOMAS DirtyJTAG + +usb:v1209pC0D3* + ID_MODEL_FROM_DATABASE=Samy Kamkar USBdriveby + +usb:v1209pC0DA* + ID_MODEL_FROM_DATABASE=Monero Hardware Monero Firmware + +usb:v1209pC0DE* + ID_MODEL_FROM_DATABASE=KMRH Labs SBL Brain + +usb:v1209pC0F5* + ID_MODEL_FROM_DATABASE=unethi PERswitch + +usb:v1209pC1AA* + ID_MODEL_FROM_DATABASE=Proyecto CIAA Computadora Industrial Abierta Argentina + +usb:v1209pC1B1* + ID_MODEL_FROM_DATABASE=Chibitronics Love-to-Code + +usb:v1209pC311* + ID_MODEL_FROM_DATABASE=bg nerilex GB-USB-Link + +usb:v1209pCA1C* + ID_MODEL_FROM_DATABASE=KnightOS Generic Hub + +usb:v1209pCA1D* + ID_MODEL_FROM_DATABASE=KnightOS MTP Device + +usb:v1209pCAEA* + ID_MODEL_FROM_DATABASE=Open Music Kontrollers Chimaera + +usb:v1209pCAFE* + ID_MODEL_FROM_DATABASE=ii iigadget + +usb:v1209pCC14* + ID_MODEL_FROM_DATABASE=trebb NaN-15 + +usb:v1209pCC86* + ID_MODEL_FROM_DATABASE=Manfred's Technologies Anastasia Bootloader + +usb:v1209pCEB0* + ID_MODEL_FROM_DATABASE=KG4LNE GE-FlashUSB + +usb:v1209pCF20* + ID_MODEL_FROM_DATABASE=Smart Citizen SCK 2.0 + +usb:v1209pD00D* + ID_MODEL_FROM_DATABASE=Monero Hardware Monero Developer + +usb:v1209pD017* + ID_MODEL_FROM_DATABASE=empiriKit empiriKit Controller + +usb:v1209pD11D* + ID_MODEL_FROM_DATABASE=Koi Science DI-Lambda AVR + +usb:v1209pD3D8* + ID_MODEL_FROM_DATABASE=Duet3d Duet 0.8.5 + +usb:v1209pD706* + ID_MODEL_FROM_DATABASE=SkyBean SkyDrop + +usb:v1209pDA42* + ID_MODEL_FROM_DATABASE=Devan Lai dap42 debug access probe + +usb:v1209pDAA0* + ID_MODEL_FROM_DATABASE=darknao btClubSportWheel + +usb:v1209pDADA* + ID_MODEL_FROM_DATABASE=Rebel Technology OWL + +usb:v1209pDB42* + ID_MODEL_FROM_DATABASE=Devan Lai dapboot DFU bootloader + +usb:v1209pDC21* + ID_MODEL_FROM_DATABASE=FPGA-Computer Dual Charger + +usb:v1209pDDDD* + ID_MODEL_FROM_DATABASE=Stephan Electronics OpenCVMeter + +usb:v1209pDEAD* + ID_MODEL_FROM_DATABASE=chaosfield.at AVR-Ruler + +usb:v1209pDEAF* + ID_MODEL_FROM_DATABASE=CrapLab 4chord MIDI + +usb:v1209pDED1* + ID_MODEL_FROM_DATABASE=ManCave Made Quark One + +usb:v1209pDF00* + ID_MODEL_FROM_DATABASE=D.F.Mac. @TripArts Music mi:muz:tuch + +usb:v1209pDF01* + ID_MODEL_FROM_DATABASE=D.F.Mac. @TripArts Music mi:muz:can + +usb:v1209pDF02* + ID_MODEL_FROM_DATABASE=D.F.Mac. @TripArts Music mi:muz:can-lite + +usb:v1209pE116* + ID_MODEL_FROM_DATABASE=Elijah Motornyy open-oscilloscope-stm32f3 + +usb:v1209pE1EC* + ID_MODEL_FROM_DATABASE=FreeSRP + +usb:v1209pE4EE* + ID_MODEL_FROM_DATABASE=trebb keytee + +usb:v1209pE500* + ID_MODEL_FROM_DATABASE=GitleMikkelsen Helios Laser DAC + +usb:v1209pEAEA* + ID_MODEL_FROM_DATABASE=Pinscape Controller + +usb:v1209pEB01* + ID_MODEL_FROM_DATABASE=RobotMaker.club EB1 + +usb:v1209pEBA7* + ID_MODEL_FROM_DATABASE=VictorGrigoryev USBscope + +usb:v1209pEE00* + ID_MODEL_FROM_DATABASE=Explore Embedded SODA(SWD OpenSource Debug Adapter) + +usb:v1209pEE02* + ID_MODEL_FROM_DATABASE=Explore Embedded Explore M3 VCOM + +usb:v1209pEE03* + ID_MODEL_FROM_DATABASE=Explore Embedded Explore M3 DFU + +usb:v1209pEE2C* + ID_MODEL_FROM_DATABASE=jaka USB2RS485 + +usb:v1209pEFFA* + ID_MODEL_FROM_DATABASE=EffigyLabs atmega32u4-USB-LUFA-Bootloader + +usb:v1209pEFFE* + ID_MODEL_FROM_DATABASE=EffigyLabs Control Pedal + +usb:v1209pF000* + ID_MODEL_FROM_DATABASE=Uniti ARC + +usb:v1209pF00D* + ID_MODEL_FROM_DATABASE=RomanStepanov Shifter/Pedals Adapter + +usb:v1209pF12E* + ID_MODEL_FROM_DATABASE=Michael Bemmerl Feuermelder + +usb:v1209pF16A* + ID_MODEL_FROM_DATABASE=uri_ba Cougar TQS adapter + +usb:v1209pF16C* + ID_MODEL_FROM_DATABASE=uri_ba adapter for Vipercore's FCC3 Force Sensing Module + +usb:v1209pF380* + ID_MODEL_FROM_DATABASE=Windsor Schmidt MD-380 Open Radio Firmware + +usb:v1209pF3FC* + ID_MODEL_FROM_DATABASE=dRonin Flight controller-Lumenier Lux + +usb:v1209pF49A* + ID_MODEL_FROM_DATABASE=TimVideos.us & HDMI2USB.tv Projects FPGA Programmer & UART Bridge (PIC based Firmware) + +usb:v1209pFA11* + ID_MODEL_FROM_DATABASE=moonglow OpenXHC + +usb:v1209pFA57* + ID_MODEL_FROM_DATABASE=3DRacers Pilot Board + +usb:v1209pFA58* + ID_MODEL_FROM_DATABASE=3DRacers Pilot Board (Bootloader) + +usb:v1209pFAB1* + ID_MODEL_FROM_DATABASE=PAP Mechatronic Technology LamDiNao + +usb:v1209pFACE* + ID_MODEL_FROM_DATABASE=Protean Synth Craft + +usb:v1209pFADE* + ID_MODEL_FROM_DATABASE=Open Collector dude + +usb:v1209pFEED* + ID_MODEL_FROM_DATABASE=ProgramGyar AVR-IR Sender + +usb:v1209pFFFF* + ID_MODEL_FROM_DATABASE=Life2Device Smart House + +usb:v120E* + ID_VENDOR_FROM_DATABASE=Hudson Soft Co., Ltd + +usb:v120F* + ID_VENDOR_FROM_DATABASE=Magellan + +usb:v120Fp524E* + ID_MODEL_FROM_DATABASE=RoadMate 1475T + +usb:v120Fp5260* + ID_MODEL_FROM_DATABASE=Triton Handheld GPS Receiver (300/400/500/1500/2000) + +usb:v1210* + ID_VENDOR_FROM_DATABASE=DigiTech + +usb:v1210p0016* + ID_MODEL_FROM_DATABASE=RP500 Guitar Multi-Effects Processor + +usb:v1210p001B* + ID_MODEL_FROM_DATABASE=RP155 Guitar Multi-Effects Processor + +usb:v1210p001C* + ID_MODEL_FROM_DATABASE=RP255 Guitar Multi-Effects Processor + +usb:v121E* + ID_VENDOR_FROM_DATABASE=Jungsoft Co., Ltd + +usb:v121Ep3403* + ID_MODEL_FROM_DATABASE=Muzio JM250 Audio Player + +usb:v1220* + ID_VENDOR_FROM_DATABASE=TC Electronic + +usb:v1220p000A* + ID_MODEL_FROM_DATABASE=Hall of Fame Reverb + +usb:v1220p002A* + ID_MODEL_FROM_DATABASE=Polytune + +usb:v1220p0032* + ID_MODEL_FROM_DATABASE=Ditto X2 Looper + +usb:v1220p0039* + ID_MODEL_FROM_DATABASE=Alter Ego X4 Vintage Echo + +usb:v1221* + ID_VENDOR_FROM_DATABASE=Unknown manufacturer + +usb:v1221p3234* + ID_MODEL_FROM_DATABASE=Disk (Thumb drive) + +usb:v1223* + ID_VENDOR_FROM_DATABASE=SKYCABLE ENTERPRISE. CO., LTD. + +usb:v1228* + ID_VENDOR_FROM_DATABASE=Datapaq Limited + +usb:v1228p0012* + ID_MODEL_FROM_DATABASE=Q18 Data Logger + +usb:v1228p0015* + ID_MODEL_FROM_DATABASE=TPaq21/MPaq21 Datalogger + +usb:v1228p584C* + ID_MODEL_FROM_DATABASE=XL2 Logger + +usb:v1230* + ID_VENDOR_FROM_DATABASE=Chipidea-Microelectronica, S.A. + +usb:v1233* + ID_VENDOR_FROM_DATABASE=Denver Electronics + +usb:v1233p5677* + ID_MODEL_FROM_DATABASE=FUSB200 mp3 player + +usb:v1234* + ID_VENDOR_FROM_DATABASE=Brain Actuated Technologies + +usb:v1234p0000* + ID_MODEL_FROM_DATABASE=Neural Impulse Actuator Prototype 1.0 [NIA] + +usb:v1234p4321* + ID_MODEL_FROM_DATABASE=Human Interface Device + +usb:v1234pED02* + ID_MODEL_FROM_DATABASE=Emotiv EPOC Developer Headset Wireless Dongle + +usb:v1235* + ID_VENDOR_FROM_DATABASE=Focusrite-Novation + +usb:v1235p0001* + ID_MODEL_FROM_DATABASE=ReMOTE Audio/XStation First Edition + +usb:v1235p0002* + ID_MODEL_FROM_DATABASE=Speedio + +usb:v1235p0003* + ID_MODEL_FROM_DATABASE=RemoteSL + ZeroSL + +usb:v1235p0004* + ID_MODEL_FROM_DATABASE=ReMOTE LE + +usb:v1235p0005* + ID_MODEL_FROM_DATABASE=XIOSynth [First Edition] + +usb:v1235p0006* + ID_MODEL_FROM_DATABASE=XStation + +usb:v1235p0007* + ID_MODEL_FROM_DATABASE=XIOSynth + +usb:v1235p0008* + ID_MODEL_FROM_DATABASE=ReMOTE SL Compact + +usb:v1235p0009* + ID_MODEL_FROM_DATABASE=nIO + +usb:v1235p000A* + ID_MODEL_FROM_DATABASE=Nocturn + +usb:v1235p000B* + ID_MODEL_FROM_DATABASE=ReMOTE SL MkII + +usb:v1235p000C* + ID_MODEL_FROM_DATABASE=ZeRO MkII + +usb:v1235p000E* + ID_MODEL_FROM_DATABASE=Launchpad + +usb:v1235p0010* + ID_MODEL_FROM_DATABASE=Saffire 6 + +usb:v1235p0011* + ID_MODEL_FROM_DATABASE=Ultranova + +usb:v1235p0012* + ID_MODEL_FROM_DATABASE=Nocturn Keyboard + +usb:v1235p0013* + ID_MODEL_FROM_DATABASE=VRM Box + +usb:v1235p0014* + ID_MODEL_FROM_DATABASE=VRM Box Audio Class (2-out) + +usb:v1235p0015* + ID_MODEL_FROM_DATABASE=Dicer + +usb:v1235p0016* + ID_MODEL_FROM_DATABASE=Ultranova + +usb:v1235p0018* + ID_MODEL_FROM_DATABASE=Twitch + +usb:v1235p0019* + ID_MODEL_FROM_DATABASE=Impulse 25 + +usb:v1235p001A* + ID_MODEL_FROM_DATABASE=Impulse 49 + +usb:v1235p001B* + ID_MODEL_FROM_DATABASE=Impulse 61 + +usb:v1235p4661* + ID_MODEL_FROM_DATABASE=ReMOTE25 + +usb:v1235p8000* + ID_MODEL_FROM_DATABASE=Scarlett 18i6 + +usb:v1235p8002* + ID_MODEL_FROM_DATABASE=Scarlett 8i6 + +usb:v1235p8006* + ID_MODEL_FROM_DATABASE=Focusrite Scarlett 2i2 + +usb:v1235p8008* + ID_MODEL_FROM_DATABASE=Saffire 6 + +usb:v1235p800A* + ID_MODEL_FROM_DATABASE=Scarlett 2i4 + +usb:v1235p800C* + ID_MODEL_FROM_DATABASE=Scarlett 18i20 + +usb:v1235p800E* + ID_MODEL_FROM_DATABASE=iTrack Solo + +usb:v1235p8010* + ID_MODEL_FROM_DATABASE=Forte + +usb:v1235p8012* + ID_MODEL_FROM_DATABASE=Scarlett 6i6 + +usb:v1235p8014* + ID_MODEL_FROM_DATABASE=Scarlett 18i8 + +usb:v1235p8016* + ID_MODEL_FROM_DATABASE=Focusrite Scarlett 2i2 + +usb:v1235p8203* + ID_MODEL_FROM_DATABASE=Focusrite Scarlett 6i6 + +usb:v1235p8204* + ID_MODEL_FROM_DATABASE=Scarlett 18i8 2nd Gen + +usb:v1241* + ID_VENDOR_FROM_DATABASE=Belkin + +usb:v1241p0504* + ID_MODEL_FROM_DATABASE=Wireless Trackball Keyboard + +usb:v1241p1111* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v1241p1122* + ID_MODEL_FROM_DATABASE=Typhoon Stream Optical Mouse USB+PS/2 + +usb:v1241p1155* + ID_MODEL_FROM_DATABASE=Memorex Optical ScrollPro Mouse SE MX4600 + +usb:v1241p1166* + ID_MODEL_FROM_DATABASE=MI-2150 Trust Mouse + +usb:v1241p1177* + ID_MODEL_FROM_DATABASE=Mouse [HT82M21A] + +usb:v1241p1503* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v1241p1603* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v1241pF767* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v124A* + ID_VENDOR_FROM_DATABASE=AirVast + +usb:v124Ap168B* + ID_MODEL_FROM_DATABASE=PRISM3 WLAN Adapter + +usb:v124Ap4017* + ID_MODEL_FROM_DATABASE=PC-Chips 802.11b Adapter + +usb:v124Ap4023* + ID_MODEL_FROM_DATABASE=WM168g 802.11bg Wireless Adapter [Intersil ISL3886] + +usb:v124Ap4025* + ID_MODEL_FROM_DATABASE=IOGear GWU513 v2 802.11bg Wireless Adapter [Intersil ISL3887] + +usb:v124B* + ID_VENDOR_FROM_DATABASE=Nyko (Honey Bee) + +usb:v124Bp4D01* + ID_MODEL_FROM_DATABASE=Airflo EX Joystick + +usb:v124C* + ID_VENDOR_FROM_DATABASE=MXI - Memory Experts International, Inc. + +usb:v124Cp3200* + ID_MODEL_FROM_DATABASE=Stealth MXP 1GB + +usb:v125C* + ID_VENDOR_FROM_DATABASE=Apogee Inc. + +usb:v125Cp0010* + ID_MODEL_FROM_DATABASE=Alta series CCD + +usb:v125F* + ID_VENDOR_FROM_DATABASE=A-DATA Technology Co., Ltd. + +usb:v125Fp312A* + ID_MODEL_FROM_DATABASE=Superior S102 + +usb:v125Fp312B* + ID_MODEL_FROM_DATABASE=Superior S102 Pro + +usb:v125FpA15A* + ID_MODEL_FROM_DATABASE=DashDrive Durable HD710 portable HDD various size + +usb:v125FpA22A* + ID_MODEL_FROM_DATABASE=DashDrive Elite HE720 500GB + +usb:v125FpA91A* + ID_MODEL_FROM_DATABASE=Portable HDD CH91 + +usb:v125FpC08A* + ID_MODEL_FROM_DATABASE=C008 Flash Drive + +usb:v125FpC81A* + ID_MODEL_FROM_DATABASE=Flash drive + +usb:v125FpC93A* + ID_MODEL_FROM_DATABASE=4GB Pen Drive + +usb:v125FpC96A* + ID_MODEL_FROM_DATABASE=C906 Flash Drive + +usb:v125FpCB10* + ID_MODEL_FROM_DATABASE=Dash Drive UV100 + +usb:v125FpCB20* + ID_MODEL_FROM_DATABASE=DashDrive UV110 + +usb:v1260* + ID_VENDOR_FROM_DATABASE=Standard Microsystems Corp. + +usb:v1260pEE22* + ID_MODEL_FROM_DATABASE=SMC2862W-G v3 EZ Connect 802.11g Adapter [Intersil ISL3887] + +usb:v1264* + ID_VENDOR_FROM_DATABASE=Covidien Energy-based Devices + +usb:v1266* + ID_VENDOR_FROM_DATABASE=Pirelli Broadband Solutions + +usb:v1266p6302* + ID_MODEL_FROM_DATABASE=Fastweb DRG A226M ADSL Router + +usb:v1267* + ID_VENDOR_FROM_DATABASE=Logic3 / SpectraVideo plc + +usb:v1267p0103* + ID_MODEL_FROM_DATABASE=G-720 Keyboard + +usb:v1267p0201* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v1267p0210* + ID_MODEL_FROM_DATABASE=LG Optical Mouse 3D-310 + +usb:v1267pA001* + ID_MODEL_FROM_DATABASE=JP260 PC Game Pad + +usb:v1267pC002* + ID_MODEL_FROM_DATABASE=Wireless Optical Mouse + +usb:v126C* + ID_VENDOR_FROM_DATABASE=Aristocrat Technologies + +usb:v126D* + ID_VENDOR_FROM_DATABASE=Bel Stewart + +usb:v126E* + ID_VENDOR_FROM_DATABASE=Strobe Data, Inc. + +usb:v126F* + ID_VENDOR_FROM_DATABASE=TwinMOS + +usb:v126Fp0163* + ID_MODEL_FROM_DATABASE=Storage device (2gB thumb drive) + +usb:v126Fp1325* + ID_MODEL_FROM_DATABASE=Mobile Disk + +usb:v126Fp2168* + ID_MODEL_FROM_DATABASE=Mobile Disk III + +usb:v126FpA006* + ID_MODEL_FROM_DATABASE=G240 802.11bg + +usb:v1274* + ID_VENDOR_FROM_DATABASE=Ensoniq + +usb:v1275* + ID_VENDOR_FROM_DATABASE=Xaxero Marine Software Engineering, Ltd. + +usb:v1275p0002* + ID_MODEL_FROM_DATABASE=WeatherFax 2000 Demodulator + +usb:v1275p0080* + ID_MODEL_FROM_DATABASE=SkyEye Weather Satellite Receiver + +usb:v1278* + ID_VENDOR_FROM_DATABASE=Starlight Xpress + +usb:v1278p0105* + ID_MODEL_FROM_DATABASE=SXV-M5 + +usb:v1278p0107* + ID_MODEL_FROM_DATABASE=SXV-M7 + +usb:v1278p0109* + ID_MODEL_FROM_DATABASE=SXV-M9 + +usb:v1278p0110* + ID_MODEL_FROM_DATABASE=SXVF-H16 + +usb:v1278p0115* + ID_MODEL_FROM_DATABASE=SXVF-H5 + +usb:v1278p0119* + ID_MODEL_FROM_DATABASE=SXV-H9 + +usb:v1278p0135* + ID_MODEL_FROM_DATABASE=SXVF-H35 + +usb:v1278p0136* + ID_MODEL_FROM_DATABASE=SXVF-H36 + +usb:v1278p0200* + ID_MODEL_FROM_DATABASE=SXV interface for paraller MX cameras + +usb:v1278p0305* + ID_MODEL_FROM_DATABASE=SXV-M5C + +usb:v1278p0307* + ID_MODEL_FROM_DATABASE=SXV-M7C + +usb:v1278p0319* + ID_MODEL_FROM_DATABASE=SXV-H9C + +usb:v1278p0325* + ID_MODEL_FROM_DATABASE=SXV-M25C + +usb:v1278p0326* + ID_MODEL_FROM_DATABASE=SXVR-M26C + +usb:v1278p0507* + ID_MODEL_FROM_DATABASE=Lodestar autoguider + +usb:v1278p0517* + ID_MODEL_FROM_DATABASE=CoStar + +usb:v1283* + ID_VENDOR_FROM_DATABASE=zebris Medical GmbH + +usb:v1283p0100* + ID_MODEL_FROM_DATABASE=USB-RS232 Adaptor + +usb:v1283p0110* + ID_MODEL_FROM_DATABASE=CMS20 + +usb:v1283p0111* + ID_MODEL_FROM_DATABASE=CMS 10 + +usb:v1283p0112* + ID_MODEL_FROM_DATABASE=CMS 05 + +usb:v1283p0114* + ID_MODEL_FROM_DATABASE=ARCUS digma PC-Interface + +usb:v1283p0115* + ID_MODEL_FROM_DATABASE=SAM Axioquick recorder + +usb:v1283p0116* + ID_MODEL_FROM_DATABASE=SAM Axioquick recorder + +usb:v1283p0120* + ID_MODEL_FROM_DATABASE=emed-X + +usb:v1283p0121* + ID_MODEL_FROM_DATABASE=emed-AT + +usb:v1283p0130* + ID_MODEL_FROM_DATABASE=PDM + +usb:v1283p0150* + ID_MODEL_FROM_DATABASE=CMS10GI (Golf) + +usb:v1286* + ID_VENDOR_FROM_DATABASE=Marvell Semiconductor, Inc. + +usb:v1286p00BC* + ID_MODEL_FROM_DATABASE=Marvell JTAG Probe + +usb:v1286p1FAB* + ID_MODEL_FROM_DATABASE=88W8338 [Libertas] 802.11g + +usb:v1286p2001* + ID_MODEL_FROM_DATABASE=88W8388 802.11a/b/g WLAN + +usb:v1286p2006* + ID_MODEL_FROM_DATABASE=88W8362 802.11n WLAN + +usb:v1286p203C* + ID_MODEL_FROM_DATABASE=K30326 802.11bgn Wireless Module [Marvell 88W8786U] + +usb:v1286p8001* + ID_MODEL_FROM_DATABASE=BLOB boot loader firmware + +usb:v1291* + ID_VENDOR_FROM_DATABASE=Qualcomm Flarion Technologies, Inc. / Leadtek Research, Inc. + +usb:v1291p0010* + ID_MODEL_FROM_DATABASE=FDM 2xxx Flash-OFDM modem + +usb:v1291p0011* + ID_MODEL_FROM_DATABASE=LR7F06/LR7F14 Flash-OFDM modem + +usb:v1292* + ID_VENDOR_FROM_DATABASE=Innomedia + +usb:v1292p0258* + ID_MODEL_FROM_DATABASE=Creative Labs VoIP Blaster + +usb:v1292p4154* + ID_MODEL_FROM_DATABASE=Retro Link Atari cable + +usb:v1293* + ID_VENDOR_FROM_DATABASE=Belkin Components [hex] + +usb:v1293p0002* + ID_MODEL_FROM_DATABASE=F5U002 Parallel Port [uss720] + +usb:v1293p2101* + ID_MODEL_FROM_DATABASE=104-key keyboard + +usb:v1294* + ID_VENDOR_FROM_DATABASE=RISO KAGAKU CORP. + +usb:v1294p1320* + ID_MODEL_FROM_DATABASE=Webmail Notifier + +usb:v1297* + ID_VENDOR_FROM_DATABASE=DekTec + +usb:v1297p020F* + ID_MODEL_FROM_DATABASE=DTU-215 Multi-Standard Modulator + +usb:v129B* + ID_VENDOR_FROM_DATABASE=CyberTAN Technology + +usb:v129Bp160B* + ID_MODEL_FROM_DATABASE=Siemens S30853-S1031-R351 802.11g Wireless Adapter [Atheros AR5523] + +usb:v129Bp160C* + ID_MODEL_FROM_DATABASE=Siemens S30853-S1038-R351 802.11g Wireless Adapter [Atheros AR5523] + +usb:v129Bp1666* + ID_MODEL_FROM_DATABASE=TG54USB 802.11bg + +usb:v129Bp1667* + ID_MODEL_FROM_DATABASE=802.11bg + +usb:v129Bp1828* + ID_MODEL_FROM_DATABASE=Gigaset USB Adapter 300 + +usb:v12A7* + ID_VENDOR_FROM_DATABASE=Trendchip Technologies Corp. + +usb:v12AB* + ID_VENDOR_FROM_DATABASE=Honey Bee Electronic International Ltd. + +usb:v12B8* + ID_VENDOR_FROM_DATABASE=Zhejiang Xinya Electronic Technology Co., Ltd. + +usb:v12B9* + ID_VENDOR_FROM_DATABASE=E28 + +usb:v12BA* + ID_VENDOR_FROM_DATABASE=Licensed by Sony Computer Entertainment America + +usb:v12BAp0032* + ID_MODEL_FROM_DATABASE=Wireless Stereo Headset + +usb:v12BAp0042* + ID_MODEL_FROM_DATABASE=Wireless Stereo Headset + +usb:v12BAp00FF* + ID_MODEL_FROM_DATABASE=Rocksmith Guitar Adapter + +usb:v12BAp0100* + ID_MODEL_FROM_DATABASE=RedOctane Guitar for PlayStation(R)3 + +usb:v12BAp0120* + ID_MODEL_FROM_DATABASE=RedOctane Drum Kit for PlayStation(R)3 + +usb:v12BAp0200* + ID_MODEL_FROM_DATABASE=Harmonix Guitar for PlayStation(R)3 + +usb:v12BAp0210* + ID_MODEL_FROM_DATABASE=Harmonix Drum Kit for PlayStation(R)3 + +usb:v12BD* + ID_VENDOR_FROM_DATABASE=Gembird + +usb:v12BDpD012* + ID_MODEL_FROM_DATABASE=JPD Shockforce gamepad + +usb:v12BDpD015* + ID_MODEL_FROM_DATABASE=Generic 4-button NES USB Controller + +usb:v12C4* + ID_VENDOR_FROM_DATABASE=Autocue Group Ltd + +usb:v12C4p0006* + ID_MODEL_FROM_DATABASE=Teleprompter Two-button Hand Control (v1) + +usb:v12C4p0008* + ID_MODEL_FROM_DATABASE=Teleprompter Foot Control (v1) + +usb:v12CF* + ID_VENDOR_FROM_DATABASE=DEXIN + +usb:v12CFp0170* + ID_MODEL_FROM_DATABASE=Tt eSPORTS BLACK Gaming mouse + +usb:v12CFp600B* + ID_MODEL_FROM_DATABASE=Cougar 600M Gaming Mouse + +usb:v12D1* + ID_VENDOR_FROM_DATABASE=Huawei Technologies Co., Ltd. + +usb:v12D1p1001* + ID_MODEL_FROM_DATABASE=E161/E169/E620/E800 HSDPA Modem + +usb:v12D1p1003* + ID_MODEL_FROM_DATABASE=E220 HSDPA Modem / E230/E270/E870 HSDPA/HSUPA Modem + +usb:v12D1p1004* + ID_MODEL_FROM_DATABASE=E220 (bis) + +usb:v12D1p1009* + ID_MODEL_FROM_DATABASE=U120 + +usb:v12D1p1010* + ID_MODEL_FROM_DATABASE=ETS2252+ CDMA Fixed Wireless Terminal + +usb:v12D1p1021* + ID_MODEL_FROM_DATABASE=U8520 + +usb:v12D1p1035* + ID_MODEL_FROM_DATABASE=U8120 + +usb:v12D1p1037* + ID_MODEL_FROM_DATABASE=Ideos + +usb:v12D1p1038* + ID_MODEL_FROM_DATABASE=Ideos (debug mode) + +usb:v12D1p1039* + ID_MODEL_FROM_DATABASE=Ideos (tethering mode) + +usb:v12D1p1052* + ID_MODEL_FROM_DATABASE=MT7-L09 + +usb:v12D1p1404* + ID_MODEL_FROM_DATABASE=EM770W miniPCI WCDMA Modem + +usb:v12D1p1406* + ID_MODEL_FROM_DATABASE=E1750 + +usb:v12D1p140B* + ID_MODEL_FROM_DATABASE=EC1260 Wireless Data Modem HSD USB Card + +usb:v12D1p140C* + ID_MODEL_FROM_DATABASE=E180v + +usb:v12D1p1412* + ID_MODEL_FROM_DATABASE=EC168c + +usb:v12D1p1436* + ID_MODEL_FROM_DATABASE=Broadband stick + +usb:v12D1p1446* + ID_MODEL_FROM_DATABASE=HSPA modem + +usb:v12D1p1465* + ID_MODEL_FROM_DATABASE=K3765 HSPA + +usb:v12D1p14AC* + ID_MODEL_FROM_DATABASE=E815 + +usb:v12D1p14C3* + ID_MODEL_FROM_DATABASE=K5005 Vodafone LTE/UMTS/GSM Modem/Networkcard + +usb:v12D1p14C8* + ID_MODEL_FROM_DATABASE=K5005 Vodafone LTE/UMTS/GSM MOdem/Networkcard + +usb:v12D1p14C9* + ID_MODEL_FROM_DATABASE=K3770 3G Modem + +usb:v12D1p14CF* + ID_MODEL_FROM_DATABASE=K3772 + +usb:v12D1p14D1* + ID_MODEL_FROM_DATABASE=K3770 3G Modem (Mass Storage Mode) + +usb:v12D1p14DB* + ID_MODEL_FROM_DATABASE=E353/E3131 + +usb:v12D1p14DC* + ID_MODEL_FROM_DATABASE=E33372 LTE/UMTS/GSM HiLink Modem/Networkcard + +usb:v12D1p14F1* + ID_MODEL_FROM_DATABASE=Gobi 3000 HSPA+ Modem + +usb:v12D1p14FE* + ID_MODEL_FROM_DATABASE=Modem (Mass Storage Mode) + +usb:v12D1p1501* + ID_MODEL_FROM_DATABASE=Pulse + +usb:v12D1p1505* + ID_MODEL_FROM_DATABASE=E398 LTE/UMTS/GSM Modem/Networkcard + +usb:v12D1p1506* + ID_MODEL_FROM_DATABASE=Modem/Networkcard + +usb:v12D1p150A* + ID_MODEL_FROM_DATABASE=E398 LTE/UMTS/GSM Modem/Networkcard + +usb:v12D1p1520* + ID_MODEL_FROM_DATABASE=K3765 HSPA + +usb:v12D1p1521* + ID_MODEL_FROM_DATABASE=K4505 HSPA+ + +usb:v12D1p155A* + ID_MODEL_FROM_DATABASE=R205 Mobile WiFi (CD-ROM mode) + +usb:v12D1p1575* + ID_MODEL_FROM_DATABASE=K5150 LTE modem + +usb:v12D1p15BB* + ID_MODEL_FROM_DATABASE=ME936 LTE/HSDPA+ 4G modem + +usb:v12D1p15C1* + ID_MODEL_FROM_DATABASE=ME906s LTE M.2 Module + +usb:v12D1p15CA* + ID_MODEL_FROM_DATABASE=E3131 3G/UMTS/HSPA+ Modem (Mass Storage Mode) + +usb:v12D1p1805* + ID_MODEL_FROM_DATABASE=AT&T Go Phone U2800A phone + +usb:v12D1p1C05* + ID_MODEL_FROM_DATABASE=Broadband stick (modem on) + +usb:v12D1p1C0B* + ID_MODEL_FROM_DATABASE=E173s 3G broadband stick (modem off) + +usb:v12D1p1C20* + ID_MODEL_FROM_DATABASE=R205 Mobile WiFi (Charging) + +usb:v12D1p1D50* + ID_MODEL_FROM_DATABASE=ET302s TD-SCDMA/TD-HSDPA Mobile Broadband + +usb:v12D1p1F01* + ID_MODEL_FROM_DATABASE=E353/E3131 (Mass storage mode) + +usb:v12D1p1F16* + ID_MODEL_FROM_DATABASE=K5150 LTE modem (Mass Storage Mode) + +usb:v12D1p380B* + ID_MODEL_FROM_DATABASE=WiMAX USB modem(s) + +usb:v12D2* + ID_VENDOR_FROM_DATABASE=LINE TECH INDUSTRIAL CO., LTD. + +usb:v12D6* + ID_VENDOR_FROM_DATABASE=EMS Dr. Thomas Wuensche + +usb:v12D6p0444* + ID_MODEL_FROM_DATABASE=CPC-USB/ARM7 + +usb:v12D6p0888* + ID_MODEL_FROM_DATABASE=CPC-USB/M16C + +usb:v12D7* + ID_VENDOR_FROM_DATABASE=BETTER WIRE FACTORY CO., LTD. + +usb:v12D8* + ID_VENDOR_FROM_DATABASE=Araneus Information Systems Oy + +usb:v12D8p0001* + ID_MODEL_FROM_DATABASE=Alea I True Random Number Generator + +usb:v12E6* + ID_VENDOR_FROM_DATABASE=Waldorf Music GmbH + +usb:v12E6p0013* + ID_MODEL_FROM_DATABASE=Blofeld + +usb:v12EF* + ID_VENDOR_FROM_DATABASE=Tapwave, Inc. + +usb:v12EFp0100* + ID_MODEL_FROM_DATABASE=Tapwave Handheld [Tapwave Zodiac] + +usb:v12F2* + ID_VENDOR_FROM_DATABASE=ViewPlus Technologies, Inc. + +usb:v12F2p000A* + ID_MODEL_FROM_DATABASE=Braille embosser [SpotDot Emprint] + +usb:v12F5* + ID_VENDOR_FROM_DATABASE=Dynamic System Electronics Corp. + +usb:v12F7* + ID_VENDOR_FROM_DATABASE=Memorex Products, Inc. + +usb:v12F7p1A00* + ID_MODEL_FROM_DATABASE=TD Classic 003B + +usb:v12F7p1E23* + ID_MODEL_FROM_DATABASE=TravelDrive 2007 Flash Drive + +usb:v12FD* + ID_VENDOR_FROM_DATABASE=AIN Comm. Technology Co., Ltd + +usb:v12FDp1001* + ID_MODEL_FROM_DATABASE=AWU2000b 802.11b Stick + +usb:v12FF* + ID_VENDOR_FROM_DATABASE=Fascinating Electronics, Inc. + +usb:v12FFp0101* + ID_MODEL_FROM_DATABASE=Advanced RC Servo Controller + +usb:v1307* + ID_VENDOR_FROM_DATABASE=Transcend Information, Inc. + +usb:v1307p0163* + ID_MODEL_FROM_DATABASE=256MB/512MB/1GB Flash Drive + +usb:v1307p0165* + ID_MODEL_FROM_DATABASE=2GB/4GB/8GB Flash Drive + +usb:v1307p0190* + ID_MODEL_FROM_DATABASE=Ut190 8 GB Flash Drive with MicroSD reader + +usb:v1307p0310* + ID_MODEL_FROM_DATABASE=SD/MicroSD CardReader [hama]/IT1327E [Basic Line flash drive] + +usb:v1307p0330* + ID_MODEL_FROM_DATABASE=63-in-1 Multi-Card Reader/Writer + +usb:v1307p0361* + ID_MODEL_FROM_DATABASE=CR-75: 51-in-1 Card Reader/Writer [Sakar] + +usb:v1307p1169* + ID_MODEL_FROM_DATABASE=TS2GJF210 JetFlash 210 2GB + +usb:v1307p1171* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v1308* + ID_VENDOR_FROM_DATABASE=Shuttle, Inc. + +usb:v1308p0003* + ID_MODEL_FROM_DATABASE=VFD Module + +usb:v1308pC001* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v1310* + ID_VENDOR_FROM_DATABASE=Roper + +usb:v1310p0001* + ID_MODEL_FROM_DATABASE=Class 1 Bluetooth Dongle + +usb:v1312* + ID_VENDOR_FROM_DATABASE=ICS Electronics + +usb:v1313* + ID_VENDOR_FROM_DATABASE=ThorLabs + +usb:v1313p0010* + ID_MODEL_FROM_DATABASE=LC1 Linear Camera (Jungo) + +usb:v1313p0011* + ID_MODEL_FROM_DATABASE=SP1 Spectrometer (Jungo) + +usb:v1313p0012* + ID_MODEL_FROM_DATABASE=SP2 Spectrometer (Jungo) + +usb:v1313p0110* + ID_MODEL_FROM_DATABASE=LC1 Linear Camera (VISA) + +usb:v1313p0111* + ID_MODEL_FROM_DATABASE=SP1 Spectrometer (VISA) + +usb:v1313p0112* + ID_MODEL_FROM_DATABASE=SP2 Spectrometer (VISA) + +usb:v1313p8001* + ID_MODEL_FROM_DATABASE=TXP-Series Slot (TXP5001, TXP5004) + +usb:v1313p8012* + ID_MODEL_FROM_DATABASE=BC106 Camera Beam Profiler + +usb:v1313p8013* + ID_MODEL_FROM_DATABASE=WFS10 Wavefront Sensor + +usb:v1313p8017* + ID_MODEL_FROM_DATABASE=BC206 Camera Beam Profiler + +usb:v1313p8019* + ID_MODEL_FROM_DATABASE=BP2 Multi Slit Beam Profiler + +usb:v1313p8020* + ID_MODEL_FROM_DATABASE=PM300 Optical Power Meter + +usb:v1313p8021* + ID_MODEL_FROM_DATABASE=PM300E Optical Power and Energy Meter + +usb:v1313p8022* + ID_MODEL_FROM_DATABASE=PM320E Optical Power and Energy Meter + +usb:v1313p8030* + ID_MODEL_FROM_DATABASE=ER100 Extinction Ratio Meter + +usb:v1313p8070* + ID_MODEL_FROM_DATABASE=PM100D + +usb:v1313p8072* + ID_MODEL_FROM_DATABASE=PM100USB Power and Energy Meter Interface + +usb:v1313p8078* + ID_MODEL_FROM_DATABASE=PM100D Compact Power and Energy Meter Console + +usb:v1313p8080* + ID_MODEL_FROM_DATABASE=CCS100 - Compact Spectrometer + +usb:v131D* + ID_VENDOR_FROM_DATABASE=Natural Point + +usb:v131Dp0155* + ID_MODEL_FROM_DATABASE=TrackIR 3 Pro Head Tracker + +usb:v131Dp0156* + ID_MODEL_FROM_DATABASE=TrackIR 4 Pro Head Tracker + +usb:v131Dp0158* + ID_MODEL_FROM_DATABASE=TrackIR 5 Pro Head Tracker + +usb:v1325* + ID_VENDOR_FROM_DATABASE=ams AG + +usb:v1325p4002* + ID_MODEL_FROM_DATABASE=I2C Dongle + +usb:v132A* + ID_VENDOR_FROM_DATABASE=Envara Inc. + +usb:v132Ap1502* + ID_MODEL_FROM_DATABASE=WiND 802.11abg / 802.11bg WLAN + +usb:v132B* + ID_VENDOR_FROM_DATABASE=Konica Minolta + +usb:v132Bp0000* + ID_MODEL_FROM_DATABASE=Dimage A2 Camera + +usb:v132Bp0001* + ID_MODEL_FROM_DATABASE=Minolta DiMAGE A2 (ptp) + +usb:v132Bp0003* + ID_MODEL_FROM_DATABASE=Dimage Xg Camera + +usb:v132Bp0006* + ID_MODEL_FROM_DATABASE=Dimage Z2 Camera + +usb:v132Bp0007* + ID_MODEL_FROM_DATABASE=Minolta DiMAGE Z2 (PictBridge mode) + +usb:v132Bp0008* + ID_MODEL_FROM_DATABASE=Dimage X21 Camera + +usb:v132Bp000A* + ID_MODEL_FROM_DATABASE=Dimage Scan Dual IV AF-3200 (2891) + +usb:v132Bp000B* + ID_MODEL_FROM_DATABASE=Dimage Z10 Camera + +usb:v132Bp000D* + ID_MODEL_FROM_DATABASE=Dimage X50 Camera [storage?] + +usb:v132Bp000F* + ID_MODEL_FROM_DATABASE=Dimage X50 Camera [p2p?] + +usb:v132Bp0010* + ID_MODEL_FROM_DATABASE=Dimage G600 Camera + +usb:v132Bp0012* + ID_MODEL_FROM_DATABASE=Dimage Scan Elite 5400 II (2892) + +usb:v132Bp0013* + ID_MODEL_FROM_DATABASE=Dimage X31 Camera + +usb:v132Bp0015* + ID_MODEL_FROM_DATABASE=Dimage G530 Camera + +usb:v132Bp0017* + ID_MODEL_FROM_DATABASE=Dimage Z3 Camera + +usb:v132Bp0018* + ID_MODEL_FROM_DATABASE=Minolta DiMAGE Z3 (PictBridge mode) + +usb:v132Bp0019* + ID_MODEL_FROM_DATABASE=Dimage A200 Camera + +usb:v132Bp0021* + ID_MODEL_FROM_DATABASE=Dimage Z5 Camera + +usb:v132Bp0022* + ID_MODEL_FROM_DATABASE=Minolta DiMAGE Z5 (PictBridge mode) + +usb:v132Bp002C* + ID_MODEL_FROM_DATABASE=Dynax 5D camera + +usb:v132Bp2001* + ID_MODEL_FROM_DATABASE=Magicolor 2400w + +usb:v132Bp2004* + ID_MODEL_FROM_DATABASE=Magicolor 5430DL + +usb:v132Bp2005* + ID_MODEL_FROM_DATABASE=Magicolor 2430 DL + +usb:v132Bp2029* + ID_MODEL_FROM_DATABASE=Magicolor 5440DL + +usb:v132Bp2030* + ID_MODEL_FROM_DATABASE=PagePro 1350E(N) + +usb:v132Bp2033* + ID_MODEL_FROM_DATABASE=PagePro 1400W + +usb:v132Bp2043* + ID_MODEL_FROM_DATABASE=Magicolor 2530DL + +usb:v132Bp2045* + ID_MODEL_FROM_DATABASE=Magicolor 2500W + +usb:v132Bp2049* + ID_MODEL_FROM_DATABASE=Magicolor 2490MF + +usb:v133E* + ID_VENDOR_FROM_DATABASE=Kemper Digital GmbH + +usb:v133Ep0815* + ID_MODEL_FROM_DATABASE=Virus TI Desktop + +usb:v1342* + ID_VENDOR_FROM_DATABASE=Mobility + +usb:v1342p0200* + ID_MODEL_FROM_DATABASE=EasiDock 200 Hub + +usb:v1342p0201* + ID_MODEL_FROM_DATABASE=EasiDock 200 Keyboard and Mouse Port + +usb:v1342p0202* + ID_MODEL_FROM_DATABASE=EasiDock 200 Serial Port + +usb:v1342p0203* + ID_MODEL_FROM_DATABASE=EasiDock 200 Printer Port + +usb:v1342p0204* + ID_MODEL_FROM_DATABASE=Ethernet + +usb:v1342p0304* + ID_MODEL_FROM_DATABASE=EasiDock Ethernet + +usb:v1343* + ID_VENDOR_FROM_DATABASE=Citizen Systems + +usb:v1343p0002* + ID_MODEL_FROM_DATABASE=CW-01 + +usb:v1343p0003* + ID_MODEL_FROM_DATABASE=CX / DNP DS40 + +usb:v1343p0004* + ID_MODEL_FROM_DATABASE=CX-W / DNP DS80 / Mitsubishi CP3800 + +usb:v1343p0005* + ID_MODEL_FROM_DATABASE=CY / DNP DSRX1 + +usb:v1343p0006* + ID_MODEL_FROM_DATABASE=CW-02 + +usb:v1343p0007* + ID_MODEL_FROM_DATABASE=DNP DS80DX + +usb:v1343p0008* + ID_MODEL_FROM_DATABASE=CX2 / DNP DS620 + +usb:v1345* + ID_VENDOR_FROM_DATABASE=Sino Lite Technology Corp. + +usb:v1345p001C* + ID_MODEL_FROM_DATABASE=Xbox Controller Hub + +usb:v1345p6006* + ID_MODEL_FROM_DATABASE=Defender Wireless Controller + +usb:v1347* + ID_VENDOR_FROM_DATABASE=Moravian Instruments + +usb:v1347p0400* + ID_MODEL_FROM_DATABASE=G2CCD USB 1.1 obsolete + +usb:v1347p0401* + ID_MODEL_FROM_DATABASE=G2CCD-S with Sony ICX285 CCD + +usb:v1347p0402* + ID_MODEL_FROM_DATABASE=G2CCD2 + +usb:v1347p0403* + ID_MODEL_FROM_DATABASE=G2/G3CCD-I KAI CCD + +usb:v1347p0404* + ID_MODEL_FROM_DATABASE=G2/G3/G4 CCD-F KAF CCD + +usb:v1347p0405* + ID_MODEL_FROM_DATABASE=Gx CCD-I CCD + +usb:v1347p0406* + ID_MODEL_FROM_DATABASE=Gx CCD-F CCD + +usb:v1347p0410* + ID_MODEL_FROM_DATABASE=G1-0400 CCD + +usb:v1347p0411* + ID_MODEL_FROM_DATABASE=G1-0800 CCD + +usb:v1347p0412* + ID_MODEL_FROM_DATABASE=G1-0300 CCD + +usb:v1347p0413* + ID_MODEL_FROM_DATABASE=G1-2000 CCD + +usb:v1347p0414* + ID_MODEL_FROM_DATABASE=G1-1400 CCD + +usb:v1347p0415* + ID_MODEL_FROM_DATABASE=G1-1200 CCD + +usb:v1347p04B0* + ID_MODEL_FROM_DATABASE=Gx CCD-B CCD + +usb:v1347p04B1* + ID_MODEL_FROM_DATABASE=Gx CCD-BI CCD + +usb:v1348* + ID_VENDOR_FROM_DATABASE=Katsuragawa Electric Co., Ltd. + +usb:v134C* + ID_VENDOR_FROM_DATABASE=PanJit International Inc. + +usb:v134Cp0001* + ID_MODEL_FROM_DATABASE=Touch Panel Controller + +usb:v134Cp0002* + ID_MODEL_FROM_DATABASE=Touch Panel Controller + +usb:v134Cp0003* + ID_MODEL_FROM_DATABASE=Touch Panel Controller + +usb:v134Cp0004* + ID_MODEL_FROM_DATABASE=Touch Panel Controller + +usb:v134E* + ID_VENDOR_FROM_DATABASE=Digby's Bitpile, Inc. DBA D Bit + +usb:v1357* + ID_VENDOR_FROM_DATABASE=P&E Microcomputer Systems + +usb:v1357p0089* + ID_MODEL_FROM_DATABASE=OpenSDA - CDC Serial Port + +usb:v1357p0503* + ID_MODEL_FROM_DATABASE=USB-ML-12 HCS08/HCS12 Multilink + +usb:v1357p0504* + ID_MODEL_FROM_DATABASE=DEMOJM + +usb:v135F* + ID_VENDOR_FROM_DATABASE=Control Development Inc. + +usb:v135Fp0110* + ID_MODEL_FROM_DATABASE=Linear Spectrograph + +usb:v135Fp0111* + ID_MODEL_FROM_DATABASE=Spectrograph - Renumerated + +usb:v135Fp0200* + ID_MODEL_FROM_DATABASE=Linear Spectrograph + +usb:v135Fp0201* + ID_MODEL_FROM_DATABASE=Spectrograph - Renumerated + +usb:v135Fp0240* + ID_MODEL_FROM_DATABASE=MPP Spectrograph + +usb:v1366* + ID_VENDOR_FROM_DATABASE=SEGGER + +usb:v1366p0101* + ID_MODEL_FROM_DATABASE=J-Link PLUS + +usb:v136B* + ID_VENDOR_FROM_DATABASE=STEC + +usb:v136E* + ID_VENDOR_FROM_DATABASE=Andor Technology Ltd. + +usb:v136Ep0012* + ID_MODEL_FROM_DATABASE=iXon Ultra CCD + +usb:v136Ep0014* + ID_MODEL_FROM_DATABASE=Zyla 5.5 sCMOS camera + +usb:v1370* + ID_VENDOR_FROM_DATABASE=Swissbit + +usb:v1370p0323* + ID_MODEL_FROM_DATABASE=Swissmemory cirrusWHITE + +usb:v1370p6828* + ID_MODEL_FROM_DATABASE=Victorinox Flash Drive + +usb:v1371* + ID_VENDOR_FROM_DATABASE=CNet Technology Inc. + +usb:v1371p0001* + ID_MODEL_FROM_DATABASE=CNUSB-611AR Wireless Adapter-G [AT76C503] + +usb:v1371p0002* + ID_MODEL_FROM_DATABASE=CNUSB-611AR Wireless Adapter-G [AT76C503] (FiberLine WL-240U) + +usb:v1371p0013* + ID_MODEL_FROM_DATABASE=CNUSB-611 Wireless Adapter [AT76C505] + +usb:v1371p0014* + ID_MODEL_FROM_DATABASE=CNUSB-611 Wireless Adapter [AT76C505] (FiberLine WL-240U) + +usb:v1371p5743* + ID_MODEL_FROM_DATABASE=CNUSB-611 (D) Wireless Adapter [AT76C503] + +usb:v1371p9022* + ID_MODEL_FROM_DATABASE=CWD-854 [RT2573] + +usb:v1371p9032* + ID_MODEL_FROM_DATABASE=CWD-854 rev F + +usb:v1371p9401* + ID_MODEL_FROM_DATABASE=CWD-854 Wireless 802.11g 54Mbps Network Adapter [RTL8187] + +usb:v1376* + ID_VENDOR_FROM_DATABASE=Vimtron Electronics Co., Ltd. + +usb:v1377* + ID_VENDOR_FROM_DATABASE=Sennheiser electronic GmbH & Co. KG + +usb:v1377p4000* + ID_MODEL_FROM_DATABASE=HDVD800 + +usb:v137B* + ID_VENDOR_FROM_DATABASE=SCAPS GmbH + +usb:v137Bp0002* + ID_MODEL_FROM_DATABASE=SCAPS USC-2 Scanner Controller + +usb:v1385* + ID_VENDOR_FROM_DATABASE=Netgear, Inc + +usb:v1385p4250* + ID_MODEL_FROM_DATABASE=WG111T + +usb:v1385p4251* + ID_MODEL_FROM_DATABASE=WG111T (no firmware) + +usb:v1385p5F00* + ID_MODEL_FROM_DATABASE=WPN111 RangeMax(TM) Wireless USB 2.0 Adapter + +usb:v1385p5F01* + ID_MODEL_FROM_DATABASE=WPN111 (no firmware) + +usb:v1385p5F02* + ID_MODEL_FROM_DATABASE=WPN111 (no firmware) + +usb:v1385p6E00* + ID_MODEL_FROM_DATABASE=WPNT121 802.11g 240Mbps Wireless Adapter [Airgo AGN300] + +usb:v138A* + ID_VENDOR_FROM_DATABASE=Validity Sensors, Inc. + +usb:v138Ap0001* + ID_MODEL_FROM_DATABASE=VFS101 Fingerprint Reader + +usb:v138Ap0005* + ID_MODEL_FROM_DATABASE=VFS301 Fingerprint Reader + +usb:v138Ap0007* + ID_MODEL_FROM_DATABASE=VFS451 Fingerprint Reader + +usb:v138Ap0008* + ID_MODEL_FROM_DATABASE=VFS300 Fingerprint Reader + +usb:v138Ap0010* + ID_MODEL_FROM_DATABASE=VFS Fingerprint sensor + +usb:v138Ap0011* + ID_MODEL_FROM_DATABASE=VFS5011 Fingerprint Reader + +usb:v138Ap0015* + ID_MODEL_FROM_DATABASE=VFS 5011 fingerprint sensor + +usb:v138Ap0017* + ID_MODEL_FROM_DATABASE=VFS 5011 fingerprint sensor + +usb:v138Ap0018* + ID_MODEL_FROM_DATABASE=Fingerprint scanner + +usb:v138Ap003C* + ID_MODEL_FROM_DATABASE=VFS471 Fingerprint Reader + +usb:v138Ap003D* + ID_MODEL_FROM_DATABASE=VFS491 + +usb:v138Ap003F* + ID_MODEL_FROM_DATABASE=VFS495 Fingerprint Reader + +usb:v138Ap0050* + ID_MODEL_FROM_DATABASE=Swipe Fingerprint Sensor + +usb:v138Ap0090* + ID_MODEL_FROM_DATABASE=VFS7500 Touch Fingerprint Sensor + +usb:v138Ap0091* + ID_MODEL_FROM_DATABASE=VFS7552 Touch Fingerprint Sensor + +usb:v138E* + ID_VENDOR_FROM_DATABASE=Jungo LTD + +usb:v138Ep9000* + ID_MODEL_FROM_DATABASE=Raisonance S.A. STM32 ARM evaluation board / RLink dongle + +usb:v1390* + ID_VENDOR_FROM_DATABASE=TOMTOM B.V. + +usb:v1390p0001* + ID_MODEL_FROM_DATABASE=GO 520 T/GO 630/ONE XL (v9) + +usb:v1390p5454* + ID_MODEL_FROM_DATABASE=Blue & Me 2 + +usb:v1390p7474* + ID_MODEL_FROM_DATABASE=GPS Sport Watch [Runner, Multi-Sport] + +usb:v1390pA001* + ID_MODEL_FROM_DATABASE=Bandit Action Camera Batt-Stick + +usb:v1391* + ID_VENDOR_FROM_DATABASE=IdealTEK, Inc. + +usb:v1391p1000* + ID_MODEL_FROM_DATABASE=URTC-1000 + +usb:v1395* + ID_VENDOR_FROM_DATABASE=Sennheiser Communications + +usb:v1395p0025* + ID_MODEL_FROM_DATABASE=Headset [PC 8] + +usb:v1395p0046* + ID_MODEL_FROM_DATABASE=PXC 550 + +usb:v1395p3556* + ID_MODEL_FROM_DATABASE=USB Headset + +usb:v1397* + ID_VENDOR_FROM_DATABASE=BEHRINGER International GmbH + +usb:v1397p00BC* + ID_MODEL_FROM_DATABASE=BCF2000 + +usb:v1398* + ID_VENDOR_FROM_DATABASE=Q-tec + +usb:v1398p2103* + ID_MODEL_FROM_DATABASE=USB 2.0 Storage Device + +usb:v13AD* + ID_VENDOR_FROM_DATABASE=Baltech + +usb:v13ADp9999* + ID_MODEL_FROM_DATABASE=Card reader + +usb:v13B0* + ID_VENDOR_FROM_DATABASE=PerkinElmer Optoelectronics + +usb:v13B0p000A* + ID_MODEL_FROM_DATABASE=Alesis Photon X25 MIDI Controller + +usb:v13B1* + ID_VENDOR_FROM_DATABASE=Linksys + +usb:v13B1p000A* + ID_MODEL_FROM_DATABASE=WUSB54G v2 802.11g Adapter [Intersil ISL3887] + +usb:v13B1p000B* + ID_MODEL_FROM_DATABASE=WUSB11 v4.0 802.11b Adapter [ALi M4301] + +usb:v13B1p000C* + ID_MODEL_FROM_DATABASE=WUSB54AG 802.11a/g Adapter [Intersil ISL3887] + +usb:v13B1p000D* + ID_MODEL_FROM_DATABASE=WUSB54G v4 802.11g Adapter [Ralink RT2500USB] + +usb:v13B1p000E* + ID_MODEL_FROM_DATABASE=WUSB54GS v1 802.11g Adapter [Broadcom 4320 USB] + +usb:v13B1p0011* + ID_MODEL_FROM_DATABASE=WUSB54GP v4.0 802.11g Adapter [Ralink RT2500USB] + +usb:v13B1p0014* + ID_MODEL_FROM_DATABASE=WUSB54GS v2 802.11g Adapter [Broadcom 4320 USB] + +usb:v13B1p0018* + ID_MODEL_FROM_DATABASE=USB200M 10/100 Ethernet Adapter + +usb:v13B1p001A* + ID_MODEL_FROM_DATABASE=HU200TS Wireless Adapter + +usb:v13B1p001E* + ID_MODEL_FROM_DATABASE=WUSBF54G 802.11bg + +usb:v13B1p0020* + ID_MODEL_FROM_DATABASE=WUSB54GC v1 802.11g Adapter [Ralink RT73] + +usb:v13B1p0022* + ID_MODEL_FROM_DATABASE=WUSB54GX4 802.11g 240Mbps Wireless Adapter [Airgo AGN300] + +usb:v13B1p0023* + ID_MODEL_FROM_DATABASE=WUSB54GR + +usb:v13B1p0024* + ID_MODEL_FROM_DATABASE=WUSBF54G v1.1 802.11bg + +usb:v13B1p0026* + ID_MODEL_FROM_DATABASE=WUSB54GSC v1 802.11g Adapter [Broadcom 4320 USB] + +usb:v13B1p0028* + ID_MODEL_FROM_DATABASE=WUSB200 802.11g Adapter [Ralink RT2671] + +usb:v13B1p0029* + ID_MODEL_FROM_DATABASE=WUSB300N 802.11bgn Wireless Adapter [Marvell 88W8362+88W8060] + +usb:v13B1p002F* + ID_MODEL_FROM_DATABASE=AE1000 v1 802.11n [Ralink RT3572] + +usb:v13B1p0031* + ID_MODEL_FROM_DATABASE=AM10 v1 802.11n [Ralink RT3072] + +usb:v13B1p0039* + ID_MODEL_FROM_DATABASE=AE1200 802.11bgn Wireless Adapter [Broadcom BCM43235] + +usb:v13B1p003A* + ID_MODEL_FROM_DATABASE=AE2500 802.11abgn Wireless Adapter [Broadcom BCM43236] + +usb:v13B1p003B* + ID_MODEL_FROM_DATABASE=AE3000 802.11abgn (3x3) Wireless Adapter [Ralink RT3573] + +usb:v13B1p003E* + ID_MODEL_FROM_DATABASE=AE6000 802.11a/b/g/n/ac Wireless Adapter [MediaTek MT7610U] + +usb:v13B1p003F* + ID_MODEL_FROM_DATABASE=WUSB6300 802.11a/b/g/n/ac Wireless Adapter [Realtek RTL8812AU] + +usb:v13B1p0041* + ID_MODEL_FROM_DATABASE=Gigabit Ethernet Adapter + +usb:v13B1p0042* + ID_MODEL_FROM_DATABASE=WUSB6100M 802.11a/b/g/n/ac Wireless Adapter + +usb:v13B1p13B1* + ID_MODEL_FROM_DATABASE=WUSB200: Wireless-G Business Network Adapter with Rangebooster + +usb:v13B2* + ID_VENDOR_FROM_DATABASE=Alesis + +usb:v13B2p0030* + ID_MODEL_FROM_DATABASE=Multimix 8 + +usb:v13B3* + ID_VENDOR_FROM_DATABASE=Nippon Dics Co., Ltd. + +usb:v13BA* + ID_VENDOR_FROM_DATABASE=PCPlay + +usb:v13BAp0001* + ID_MODEL_FROM_DATABASE=Konig Electronic CMP-KEYPAD12 Numeric Keypad + +usb:v13BAp0017* + ID_MODEL_FROM_DATABASE=PS/2 Keyboard+Mouse Adapter + +usb:v13BAp0018* + ID_MODEL_FROM_DATABASE=Barcode PCP-BCG4209 + +usb:v13BE* + ID_VENDOR_FROM_DATABASE=Ricoh Printing Systems, Ltd. + +usb:v13CA* + ID_VENDOR_FROM_DATABASE=JyeTai Precision Industrial Co., Ltd. + +usb:v13CF* + ID_VENDOR_FROM_DATABASE=Wisair Ltd. + +usb:v13CFp1200* + ID_MODEL_FROM_DATABASE=Olidata Wireless Multimedia Adapter + +usb:v13D0* + ID_VENDOR_FROM_DATABASE=Techsan Electronics Co., Ltd. + +usb:v13D0p2282* + ID_MODEL_FROM_DATABASE=TechniSat DVB-PC TV Star 2 + +usb:v13D1* + ID_VENDOR_FROM_DATABASE=A-Max Technology Macao Commercial Offshore Co. Ltd. + +usb:v13D1p7019* + ID_MODEL_FROM_DATABASE=MD 82288 + +usb:v13D1pABE6* + ID_MODEL_FROM_DATABASE=Wireless 802.11g 54Mbps Network Adapter [RTL8187] + +usb:v13D2* + ID_VENDOR_FROM_DATABASE=Shark Multimedia + +usb:v13D2p0400* + ID_MODEL_FROM_DATABASE=Pocket Ethernet [klsi] + +usb:v13D3* + ID_VENDOR_FROM_DATABASE=IMC Networks + +usb:v13D3p3201* + ID_MODEL_FROM_DATABASE=VisionDTV USB-Ter/HAMA USB DVB-T device cold + +usb:v13D3p3202* + ID_MODEL_FROM_DATABASE=VisionDTV USB-Ter/HAMA USB DVB-T device warm + +usb:v13D3p3203* + ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + +usb:v13D3p3204* + ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + +usb:v13D3p3205* + ID_MODEL_FROM_DATABASE=DNTV Live! Tiny USB2 BDA (No Remote) + +usb:v13D3p3206* + ID_MODEL_FROM_DATABASE=DNTV Live! Tiny USB2 BDA (No Remote) + +usb:v13D3p3207* + ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + +usb:v13D3p3208* + ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + +usb:v13D3p3209* + ID_MODEL_FROM_DATABASE=DTV-DVB UDST7022BDA DVB-S Box(Without HID) + +usb:v13D3p3211* + ID_MODEL_FROM_DATABASE=DTV-DVB Hybrid Analog/Capture / Pinnacle PCTV 310e + +usb:v13D3p3212* + ID_MODEL_FROM_DATABASE=DTV-DVB UDTT704C - DVBT/NTSC/PAL Driver(PCM4) + +usb:v13D3p3213* + ID_MODEL_FROM_DATABASE=DTV-DVB UDTT704D - DVBT/NTSC/PAL Driver (PCM4) + +usb:v13D3p3214* + ID_MODEL_FROM_DATABASE=DTV-DVB UDTT704F -(MiniCard) DVBT/NTSC/PAL Driver(Without HID) + +usb:v13D3p3215* + ID_MODEL_FROM_DATABASE=DTV-DVB UDAT7240 - ATSC/NTSC/PAL Driver(PCM4) + +usb:v13D3p3216* + ID_MODEL_FROM_DATABASE=DTV-DVB UDTT 7047-USB 2.0 DVB-T Driver + +usb:v13D3p3217* + ID_MODEL_FROM_DATABASE=Digital-TV Receiver. + +usb:v13D3p3219* + ID_MODEL_FROM_DATABASE=DTV-DVB UDTT7049 - DVB-T Driver(Without HID) + +usb:v13D3p3220* + ID_MODEL_FROM_DATABASE=DTV-DVB UDTT 7047M-USB 2.0 DVB-T Driver + +usb:v13D3p3223* + ID_MODEL_FROM_DATABASE=DNTV Live! Tiny USB2 BDA (No Remote) + +usb:v13D3p3224* + ID_MODEL_FROM_DATABASE=DNTV Live! Tiny USB2 BDA (No Remote) + +usb:v13D3p3226* + ID_MODEL_FROM_DATABASE=DigitalNow TinyTwin DVB-T Receiver + +usb:v13D3p3234* + ID_MODEL_FROM_DATABASE=DVB-T FTA Half Minicard [RTL2832U] + +usb:v13D3p3236* + ID_MODEL_FROM_DATABASE=DTV-DVB UDTT 7047A-USB 2.0 DVB-T Driver + +usb:v13D3p3237* + ID_MODEL_FROM_DATABASE=DTV-DVB UDTT 704J - dual DVB-T Driver + +usb:v13D3p3239* + ID_MODEL_FROM_DATABASE=DTV-DVB UDTT704D - DVBT/NTSC/PAL Driver(Without HID) + +usb:v13D3p3240* + ID_MODEL_FROM_DATABASE=DTV-DVB UDXTTM6010 - A/D Driver(Without HID) + +usb:v13D3p3241* + ID_MODEL_FROM_DATABASE=DTV-DVB UDXTTM6010 - A/D Driver(Without HID) + +usb:v13D3p3242* + ID_MODEL_FROM_DATABASE=DTV-DVB UDAT7240LP - ATSC/NTSC/PAL Driver(Without HID) + +usb:v13D3p3243* + ID_MODEL_FROM_DATABASE=DTV-DVB UDXTTM6010 - A/D Driver(Without HID) + +usb:v13D3p3244* + ID_MODEL_FROM_DATABASE=DTV-DVB UDTT 7047Z-USB 2.0 DVB-T Driver + +usb:v13D3p3247* + ID_MODEL_FROM_DATABASE=AW-NU222 802.11bgn Wireless Module [Ralink RT2770+RT2720] + +usb:v13D3p3249* + ID_MODEL_FROM_DATABASE=Internal Bluetooth + +usb:v13D3p3250* + ID_MODEL_FROM_DATABASE=Broadcom Bluetooth 2.1 + +usb:v13D3p3262* + ID_MODEL_FROM_DATABASE=802.11 n/g/b Wireless LAN USB Adapter + +usb:v13D3p3273* + ID_MODEL_FROM_DATABASE=802.11 n/g/b Wireless LAN USB Mini-Card + +usb:v13D3p3274* + ID_MODEL_FROM_DATABASE=DVB-T Dongle [RTL2832U] + +usb:v13D3p3282* + ID_MODEL_FROM_DATABASE=DVB-T + GPS Minicard [RTL2832U] + +usb:v13D3p3284* + ID_MODEL_FROM_DATABASE=Wireless LAN USB Mini-Card + +usb:v13D3p3304* + ID_MODEL_FROM_DATABASE=Asus Integrated Bluetooth module [AR3011] + +usb:v13D3p3306* + ID_MODEL_FROM_DATABASE=Mediao 802.11n WLAN [Realtek RTL8191SU] + +usb:v13D3p3315* + ID_MODEL_FROM_DATABASE=Bluetooth module + +usb:v13D3p3327* + ID_MODEL_FROM_DATABASE=AW-NU137 802.11bgn Wireless Module [Atheros AR9271] + +usb:v13D3p3362* + ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth 4.0 Adapter + +usb:v13D3p3375* + ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth 4.0 Adapter + +usb:v13D3p3392* + ID_MODEL_FROM_DATABASE=Azurewave 43228+20702 + +usb:v13D3p3394* + ID_MODEL_FROM_DATABASE=Bluetooth + +usb:v13D3p3474* + ID_MODEL_FROM_DATABASE=Atheros AR3012 Bluetooth + +usb:v13D3p5070* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v13D3p5111* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v13D3p5115* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v13D3p5116* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v13D3p5122* + ID_MODEL_FROM_DATABASE=2M Integrated Webcam + +usb:v13D3p5126* + ID_MODEL_FROM_DATABASE=PC Cam + +usb:v13D3p5130* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v13D3p5134* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v13D3p5702* + ID_MODEL_FROM_DATABASE=UVC VGA Webcam + +usb:v13D3p5710* + ID_MODEL_FROM_DATABASE=UVC VGA Webcam + +usb:v13D3p5716* + ID_MODEL_FROM_DATABASE=UVC VGA Webcam + +usb:v13D3p7020* + ID_MODEL_FROM_DATABASE=DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + +usb:v13D3p7022* + ID_MODEL_FROM_DATABASE=DTV-DVB UDST7022BDA DVB-S Box(Without HID) + +usb:v13D7* + ID_VENDOR_FROM_DATABASE=Guidance Software, Inc. + +usb:v13D7p0001* + ID_MODEL_FROM_DATABASE=T5 PATA forensic bridge + +usb:v13D7p000C* + ID_MODEL_FROM_DATABASE=T8-R2 forensic bridge + +usb:v13DC* + ID_VENDOR_FROM_DATABASE=ALEREON, INC. + +usb:v13DD* + ID_VENDOR_FROM_DATABASE=i.Tech Dynamic Limited + +usb:v13E1* + ID_VENDOR_FROM_DATABASE=Kaibo Wire & Cable (Shenzhen) Co., Ltd. + +usb:v13E5* + ID_VENDOR_FROM_DATABASE=Rane + +usb:v13E5p0001* + ID_MODEL_FROM_DATABASE=SL-1 + +usb:v13E5p0003* + ID_MODEL_FROM_DATABASE=TTM 57SL + +usb:v13E6* + ID_VENDOR_FROM_DATABASE=TechnoScope Co., Ltd. + +usb:v13EA* + ID_VENDOR_FROM_DATABASE=Hengstler + +usb:v13EAp0001* + ID_MODEL_FROM_DATABASE=C-56 Thermal Printer + +usb:v13EC* + ID_VENDOR_FROM_DATABASE=Zydacron + +usb:v13ECp0006* + ID_MODEL_FROM_DATABASE=HID Remote Control + +usb:v13EE* + ID_VENDOR_FROM_DATABASE=MosArt + +usb:v13EEp0001* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v13EEp0003* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v13FD* + ID_VENDOR_FROM_DATABASE=Initio Corporation + +usb:v13FDp0840* + ID_MODEL_FROM_DATABASE=INIC-1618L SATA + +usb:v13FDp0841* + ID_MODEL_FROM_DATABASE=Samsung SE-T084M DVD-RW + +usb:v13FDp0940* + ID_MODEL_FROM_DATABASE=ASUS SBW-06D2X-U + +usb:v13FDp1040* + ID_MODEL_FROM_DATABASE=INIC-1511L PATA Bridge + +usb:v13FDp1340* + ID_MODEL_FROM_DATABASE=Hi-Speed USB to SATA Bridge + +usb:v13FDp160F* + ID_MODEL_FROM_DATABASE=RocketFish SATA Bridge [INIC-1611] + +usb:v13FDp1640* + ID_MODEL_FROM_DATABASE=INIC-1610L SATA Bridge + +usb:v13FDp1669* + ID_MODEL_FROM_DATABASE=INIC-1609PN + +usb:v13FDp1840* + ID_MODEL_FROM_DATABASE=INIC-1608 SATA bridge + +usb:v13FDp1E40* + ID_MODEL_FROM_DATABASE=INIC-1610P SATA bridge + +usb:v13FDp2040* + ID_MODEL_FROM_DATABASE=Samsung Writemaster external DVD writer + +usb:v13FDp3940* + ID_MODEL_FROM_DATABASE=external DVD burner ECD819-SU3 + +usb:v13FDp3E40* + ID_MODEL_FROM_DATABASE=ZALMAN ZM-VE350 + +usb:v13FE* + ID_VENDOR_FROM_DATABASE=Kingston Technology Company Inc. + +usb:v13FEp1A00* + ID_MODEL_FROM_DATABASE=512MB/1GB Flash Drive + +usb:v13FEp1A23* + ID_MODEL_FROM_DATABASE=512MB Flash Drive + +usb:v13FEp1D00* + ID_MODEL_FROM_DATABASE=DataTraveler 2.0 1GB/4GB Flash Drive / Patriot Xporter 4GB Flash Drive + +usb:v13FEp1E00* + ID_MODEL_FROM_DATABASE=Flash Drive 2 GB [ICIDU 2 GB] + +usb:v13FEp1E50* + ID_MODEL_FROM_DATABASE=U3 Smart Drive + +usb:v13FEp1F00* + ID_MODEL_FROM_DATABASE=Kingston DataTraveler / Patriot Xporter + +usb:v13FEp1F23* + ID_MODEL_FROM_DATABASE=PS2232 flash drive controller + +usb:v13FEp2240* + ID_MODEL_FROM_DATABASE=microSD card reader + +usb:v13FEp3100* + ID_MODEL_FROM_DATABASE=2/4 GB stick + +usb:v13FEp3123* + ID_MODEL_FROM_DATABASE=Verbatim STORE N GO 4GB + +usb:v13FEp3600* + ID_MODEL_FROM_DATABASE=flash drive (4GB, EMTEC) + +usb:v13FEp3800* + ID_MODEL_FROM_DATABASE=Rage XT Flash Drive + +usb:v13FEp3E00* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v13FEp4100* + ID_MODEL_FROM_DATABASE=Flash drive + +usb:v13FEp5000* + ID_MODEL_FROM_DATABASE=USB flash drive (32 GB SHARKOON Accelerate) + +usb:v13FEp5100* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v13FEp5200* + ID_MODEL_FROM_DATABASE=DataTraveler R3.0 + +usb:v1400* + ID_VENDOR_FROM_DATABASE=Axxion Group Corp. + +usb:v1402* + ID_VENDOR_FROM_DATABASE=Bowe Bell & Howell + +usb:v1403* + ID_VENDOR_FROM_DATABASE=Sitronix + +usb:v1403p0001* + ID_MODEL_FROM_DATABASE=Digital Photo Frame + +usb:v1403p0003* + ID_MODEL_FROM_DATABASE=Digital Photo Frame (DPF-1104) + +usb:v1409* + ID_VENDOR_FROM_DATABASE=IDS Imaging Development Systems GmbH + +usb:v1409p1000* + ID_MODEL_FROM_DATABASE=generic (firmware not loaded yet) + +usb:v1409p1485* + ID_MODEL_FROM_DATABASE=uEye UI1485 + +usb:v140E* + ID_VENDOR_FROM_DATABASE=Telechips, Inc. + +usb:v140EpB011* + ID_MODEL_FROM_DATABASE=TCC780X-based player (USB Boot mode) + +usb:v140EpB021* + ID_MODEL_FROM_DATABASE=TCC77X-based players (USB Boot mode) + +usb:v1410* + ID_VENDOR_FROM_DATABASE=Novatel Wireless + +usb:v1410p1110* + ID_MODEL_FROM_DATABASE=Merlin S620 + +usb:v1410p1120* + ID_MODEL_FROM_DATABASE=Merlin EX720 + +usb:v1410p1130* + ID_MODEL_FROM_DATABASE=Merlin S720 + +usb:v1410p1400* + ID_MODEL_FROM_DATABASE=Merlin U730/U740 (Vodafone) + +usb:v1410p1410* + ID_MODEL_FROM_DATABASE=Merlin U740 (non-Vodafone) + +usb:v1410p1430* + ID_MODEL_FROM_DATABASE=Merlin XU870 + +usb:v1410p1450* + ID_MODEL_FROM_DATABASE=Merlin X950D + +usb:v1410p2110* + ID_MODEL_FROM_DATABASE=Ovation U720/MCD3000 + +usb:v1410p2410* + ID_MODEL_FROM_DATABASE=Expedite EU740 + +usb:v1410p2420* + ID_MODEL_FROM_DATABASE=Expedite EU850D/EU860D/EU870D + +usb:v1410p4100* + ID_MODEL_FROM_DATABASE=U727 + +usb:v1410p4400* + ID_MODEL_FROM_DATABASE=Ovation MC930D/MC950D + +usb:v1410p9010* + ID_MODEL_FROM_DATABASE=Expedite E362 + +usb:v1410pA001* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem + +usb:v1410pA008* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) + +usb:v1410pB001* + ID_MODEL_FROM_DATABASE=Ovation MC551 + +usb:v1415* + ID_VENDOR_FROM_DATABASE=Nam Tai E&E Products Ltd. or OmniVision Technologies, Inc. + +usb:v1415p0000* + ID_MODEL_FROM_DATABASE=Sony SingStar USBMIC + +usb:v1415p0020* + ID_MODEL_FROM_DATABASE=Sony Wireless SingStar + +usb:v1415p2000* + ID_MODEL_FROM_DATABASE=Sony Playstation Eye + +usb:v1419* + ID_VENDOR_FROM_DATABASE=ABILITY ENTERPRISE CO., LTD. + +usb:v1421* + ID_VENDOR_FROM_DATABASE=Sensor Technology + +usb:v1421p0605* + ID_MODEL_FROM_DATABASE=Sentech Camera + +usb:v1424* + ID_VENDOR_FROM_DATABASE=Posnet Polska S.A. + +usb:v1424p1001* + ID_MODEL_FROM_DATABASE=Temo + +usb:v1424p1002* + ID_MODEL_FROM_DATABASE=Thermal + +usb:v1424p1003* + ID_MODEL_FROM_DATABASE=Neo + +usb:v1424p1004* + ID_MODEL_FROM_DATABASE=Combo DF + +usb:v1424p1005* + ID_MODEL_FROM_DATABASE=Thermal-A + +usb:v1424p1006* + ID_MODEL_FROM_DATABASE=Thermal FV + +usb:v1424p1007* + ID_MODEL_FROM_DATABASE=Bingo HS + +usb:v1424p1008* + ID_MODEL_FROM_DATABASE=Thermal HS FV + +usb:v1424p1009* + ID_MODEL_FROM_DATABASE=Thermal FV EJ + +usb:v1424p100A* + ID_MODEL_FROM_DATABASE=Thermal HD + +usb:v1424p100B* + ID_MODEL_FROM_DATABASE=Thermal + +usb:v1424p100C* + ID_MODEL_FROM_DATABASE=Neo + +usb:v1424p100D* + ID_MODEL_FROM_DATABASE=Ergo + +usb:v1424p100E* + ID_MODEL_FROM_DATABASE=Trio + +usb:v1424p1010* + ID_MODEL_FROM_DATABASE=Thermal HS FV EJ + +usb:v1424p1011* + ID_MODEL_FROM_DATABASE=Neo EJ + +usb:v1424p1012* + ID_MODEL_FROM_DATABASE=Thermal-A + +usb:v1424p1013* + ID_MODEL_FROM_DATABASE=Thermal-A EJ + +usb:v1424p1014* + ID_MODEL_FROM_DATABASE=Mobile + +usb:v1424p1015* + ID_MODEL_FROM_DATABASE=Temo HS + +usb:v1424p1016* + ID_MODEL_FROM_DATABASE=Mobile HS + +usb:v1424p1017* + ID_MODEL_FROM_DATABASE=TH230+ FV EJ + +usb:v1424p1018* + ID_MODEL_FROM_DATABASE=4610-1NR FV EJ + +usb:v1429* + ID_VENDOR_FROM_DATABASE=Vega Technologies Industrial (Austria) Co. + +usb:v142A* + ID_VENDOR_FROM_DATABASE=Thales E-Transactions + +usb:v142Ap0003* + ID_MODEL_FROM_DATABASE=Artema Hybrid + +usb:v142Ap0005* + ID_MODEL_FROM_DATABASE=Artema Modular + +usb:v142Ap0043* + ID_MODEL_FROM_DATABASE=medCompact + +usb:v142B* + ID_VENDOR_FROM_DATABASE=Arbiter Systems, Inc. + +usb:v142Bp03A5* + ID_MODEL_FROM_DATABASE=933A Portable Power Sentinel + +usb:v1430* + ID_VENDOR_FROM_DATABASE=RedOctane + +usb:v1430p0150* + ID_MODEL_FROM_DATABASE=wireless receiver for skylanders wii + +usb:v1430p4734* + ID_MODEL_FROM_DATABASE=Guitar Hero4 hub + +usb:v1430p474B* + ID_MODEL_FROM_DATABASE=Guitar Hero MIDI interface + +usb:v1431* + ID_VENDOR_FROM_DATABASE=Pertech Resources, Inc. + +usb:v1435* + ID_VENDOR_FROM_DATABASE=Wistron NeWeb + +usb:v1435p0427* + ID_MODEL_FROM_DATABASE=UR054g 802.11g Wireless Adapter [Intersil ISL3887] + +usb:v1435p0711* + ID_MODEL_FROM_DATABASE=UR055G 802.11bg + +usb:v1435p0804* + ID_MODEL_FROM_DATABASE=AR9170+AR9104 802.11abgn Wireless Adapter + +usb:v1435p0826* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v1435p0827* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v1435p0828* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v1435p0829* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v1436* + ID_VENDOR_FROM_DATABASE=Denali Software, Inc. + +usb:v143C* + ID_VENDOR_FROM_DATABASE=Altek Corporation + +usb:v1443* + ID_VENDOR_FROM_DATABASE=Digilent + +usb:v1443p0007* + ID_MODEL_FROM_DATABASE=Development board JTAG + +usb:v1446* + ID_VENDOR_FROM_DATABASE=X.J.GROUP + +usb:v1446p6A73* + ID_MODEL_FROM_DATABASE=Stamps.com Model 510 5LB Scale + +usb:v1446p6A78* + ID_MODEL_FROM_DATABASE=DYMO Endicia 75lb Digital Scale + +usb:v1451* + ID_VENDOR_FROM_DATABASE=Force Dimension + +usb:v1451p0301* + ID_MODEL_FROM_DATABASE=haptic device + +usb:v1451p0302* + ID_MODEL_FROM_DATABASE=haptic device + +usb:v1451p0400* + ID_MODEL_FROM_DATABASE=haptic device + +usb:v1451p0401* + ID_MODEL_FROM_DATABASE=delta.x haptic device + +usb:v1451p0402* + ID_MODEL_FROM_DATABASE=omega.x haptic device + +usb:v1451p0403* + ID_MODEL_FROM_DATABASE=sigma.x haptic device + +usb:v1451p0404* + ID_MODEL_FROM_DATABASE=haptic controller + +usb:v1451p0405* + ID_MODEL_FROM_DATABASE=dedicated haptic device + +usb:v1451p0406* + ID_MODEL_FROM_DATABASE=dedicated haptic device + +usb:v1451p0407* + ID_MODEL_FROM_DATABASE=dedicated haptic device + +usb:v1451p0408* + ID_MODEL_FROM_DATABASE=dedicated haptic device + +usb:v1452* + ID_VENDOR_FROM_DATABASE=Dai Nippon Printing, Inc + +usb:v1452p8B01* + ID_MODEL_FROM_DATABASE=DS620 + +usb:v1453* + ID_VENDOR_FROM_DATABASE=Radio Shack + +usb:v1453p4026* + ID_MODEL_FROM_DATABASE=26-183 Serial Cable + +usb:v1456* + ID_VENDOR_FROM_DATABASE=Extending Wire & Cable Co., Ltd. + +usb:v1457* + ID_VENDOR_FROM_DATABASE=First International Computer, Inc. + +usb:v1457p5117* + ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 kernel usbnet (g_ether, CDC Ethernet) mode + +usb:v1457p5118* + ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 Debug board (V2+) + +usb:v1457p5119* + ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 u-boot cdc_acm serial port + +usb:v1457p511A* + ID_MODEL_FROM_DATABASE=HXD8 u-boot usbtty CDC ACM Mode + +usb:v1457p511B* + ID_MODEL_FROM_DATABASE=SMDK2440 u-boot usbtty CDC ACM mode + +usb:v1457p511C* + ID_MODEL_FROM_DATABASE=SMDK2443 u-boot usbtty CDC ACM mode + +usb:v1457p511D* + ID_MODEL_FROM_DATABASE=QT2410 u-boot usbtty CDC ACM mode + +usb:v1457p5120* + ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 u-boot usbtty generic serial + +usb:v1457p5121* + ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 kernel mass storage (g_storage) mode + +usb:v1457p5122* + ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 / Neo Freerunner kernel cdc_ether USB network + +usb:v1457p5123* + ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 internal USB CSR4 module + +usb:v1457p5124* + ID_MODEL_FROM_DATABASE=OpenMoko Neo1973 Bluetooth Device ID service + +usb:v145F* + ID_VENDOR_FROM_DATABASE=Trust + +usb:v145Fp0106* + ID_MODEL_FROM_DATABASE=K56 V92 Modem + +usb:v145Fp013D* + ID_MODEL_FROM_DATABASE=PC Camera (SN9C201 + OV7660) + +usb:v145Fp013F* + ID_MODEL_FROM_DATABASE=Megapixel Auto Focus Webcam + +usb:v145Fp0142* + ID_MODEL_FROM_DATABASE=WB-6250X Webcam + +usb:v145Fp015A* + ID_MODEL_FROM_DATABASE=WB-8300X 2MP Webcam + +usb:v145Fp0161* + ID_MODEL_FROM_DATABASE=15901 802.11bg Wireless Adapter [Realtek RTL8187L] + +usb:v145Fp0167* + ID_MODEL_FROM_DATABASE=Widescreen 3MP Webcam + +usb:v145Fp0176* + ID_MODEL_FROM_DATABASE=Isla Keyboard + +usb:v1460* + ID_VENDOR_FROM_DATABASE=Tatung Co. + +usb:v1460p9150* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v1461* + ID_VENDOR_FROM_DATABASE=Staccato Communications + +usb:v1462* + ID_VENDOR_FROM_DATABASE=Micro Star International + +usb:v1462p5512* + ID_MODEL_FROM_DATABASE=MegaStick-1 Flash Stick + +usb:v1462p8807* + ID_MODEL_FROM_DATABASE=DIGIVOX mini III [af9015] + +usb:v1472* + ID_VENDOR_FROM_DATABASE=Huawei-3Com + +usb:v1472p0007* + ID_MODEL_FROM_DATABASE=Aolynk WUB300g [ZyDAS ZD1211] + +usb:v1472p0009* + ID_MODEL_FROM_DATABASE=Aolynk WUB320g + +usb:v147A* + ID_VENDOR_FROM_DATABASE=Formosa Industrial Computing, Inc. + +usb:v147ApE015* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v147ApE016* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v147ApE017* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v147ApE018* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v147ApE02C* + ID_MODEL_FROM_DATABASE=Infrared Receiver + +usb:v147ApE03A* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v147ApE03C* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v147ApE03D* + ID_MODEL_FROM_DATABASE=2 Channel Audio + +usb:v147ApE03E* + ID_MODEL_FROM_DATABASE=Infrared Receiver [IR605A/Q] + +usb:v147E* + ID_VENDOR_FROM_DATABASE=Upek + +usb:v147Ep1000* + ID_MODEL_FROM_DATABASE=Biometric Touchchip/Touchstrip Fingerprint Sensor + +usb:v147Ep1001* + ID_MODEL_FROM_DATABASE=TCS5B Fingerprint sensor + +usb:v147Ep1002* + ID_MODEL_FROM_DATABASE=Biometric Touchchip/Touchstrip Fingerprint Sensor + +usb:v147Ep2016* + ID_MODEL_FROM_DATABASE=Biometric Touchchip/Touchstrip Fingerprint Sensor + +usb:v147Ep2020* + ID_MODEL_FROM_DATABASE=TouchChip Fingerprint Coprocessor (WBF advanced mode) + +usb:v147Ep3000* + ID_MODEL_FROM_DATABASE=TCS1C EIM/Cypress Fingerprint sensor + +usb:v147Ep3001* + ID_MODEL_FROM_DATABASE=TCS1C EIM/STM32 Fingerprint sensor + +usb:v147F* + ID_VENDOR_FROM_DATABASE=Hama GmbH & Co., KG + +usb:v1482* + ID_VENDOR_FROM_DATABASE=Vaillant + +usb:v1482p1005* + ID_MODEL_FROM_DATABASE=VRD PC-Interface + +usb:v1484* + ID_VENDOR_FROM_DATABASE=Elsa AG [hex] + +usb:v1484p1746* + ID_MODEL_FROM_DATABASE=Ecomo 19H99 Monitor + +usb:v1484p7616* + ID_MODEL_FROM_DATABASE=Elsa Hub + +usb:v1485* + ID_VENDOR_FROM_DATABASE=Silicom + +usb:v1485p0001* + ID_MODEL_FROM_DATABASE=U2E + +usb:v1485p0002* + ID_MODEL_FROM_DATABASE=Psion Gold Port Ethernet + +usb:v1487* + ID_VENDOR_FROM_DATABASE=DSP Group, Ltd. + +usb:v148E* + ID_VENDOR_FROM_DATABASE=EVATRONIX SA + +usb:v148F* + ID_VENDOR_FROM_DATABASE=Ralink Technology, Corp. + +usb:v148Fp1000* + ID_MODEL_FROM_DATABASE=Motorola BC4 Bluetooth 3.0+HS Adapter + +usb:v148Fp1706* + ID_MODEL_FROM_DATABASE=RT2500USB Wireless Adapter + +usb:v148Fp2070* + ID_MODEL_FROM_DATABASE=RT2070 Wireless Adapter + +usb:v148Fp2570* + ID_MODEL_FROM_DATABASE=RT2570 Wireless Adapter + +usb:v148Fp2573* + ID_MODEL_FROM_DATABASE=RT2501/RT2573 Wireless Adapter + +usb:v148Fp2671* + ID_MODEL_FROM_DATABASE=RT2601/RT2671 Wireless Adapter + +usb:v148Fp2770* + ID_MODEL_FROM_DATABASE=RT2770 Wireless Adapter + +usb:v148Fp2870* + ID_MODEL_FROM_DATABASE=RT2870 Wireless Adapter + +usb:v148Fp3070* + ID_MODEL_FROM_DATABASE=RT2870/RT3070 Wireless Adapter + +usb:v148Fp3071* + ID_MODEL_FROM_DATABASE=RT3071 Wireless Adapter + +usb:v148Fp3072* + ID_MODEL_FROM_DATABASE=RT3072 Wireless Adapter + +usb:v148Fp3370* + ID_MODEL_FROM_DATABASE=RT3370 Wireless Adapter + +usb:v148Fp3572* + ID_MODEL_FROM_DATABASE=RT3572 Wireless Adapter + +usb:v148Fp3573* + ID_MODEL_FROM_DATABASE=RT3573 Wireless Adapter + +usb:v148Fp5370* + ID_MODEL_FROM_DATABASE=RT5370 Wireless Adapter + +usb:v148Fp5372* + ID_MODEL_FROM_DATABASE=RT5372 Wireless Adapter + +usb:v148Fp5572* + ID_MODEL_FROM_DATABASE=RT5572 Wireless Adapter + +usb:v148Fp7601* + ID_MODEL_FROM_DATABASE=MT7601U Wireless Adapter + +usb:v148Fp760B* + ID_MODEL_FROM_DATABASE=MT7601U Wireless Adapter + +usb:v148Fp761A* + ID_MODEL_FROM_DATABASE=MT7610U ("Archer T2U" 2.4G+5G WLAN Adapter + +usb:v148Fp9020* + ID_MODEL_FROM_DATABASE=RT2500USB Wireless Adapter + +usb:v148Fp9021* + ID_MODEL_FROM_DATABASE=RT2501USB Wireless Adapter + +usb:v1491* + ID_VENDOR_FROM_DATABASE=Futronic Technology Co. Ltd. + +usb:v1491p0020* + ID_MODEL_FROM_DATABASE=FS81 Fingerprint Scanner Module + +usb:v1491p0088* + ID_MODEL_FROM_DATABASE=Fingerprint Scanner Model FS88 + +usb:v1493* + ID_VENDOR_FROM_DATABASE=Suunto + +usb:v1493p0010* + ID_MODEL_FROM_DATABASE=Bluebird [Ambit] + +usb:v1493p0019* + ID_MODEL_FROM_DATABASE=Duck [Ambit2] + +usb:v1493p001A* + ID_MODEL_FROM_DATABASE=Colibri [Ambit2 S] + +usb:v1493p001B* + ID_MODEL_FROM_DATABASE=Emu [Ambit3 Peak] + +usb:v1493p001C* + ID_MODEL_FROM_DATABASE=Finch [Ambit3 Sport] + +usb:v1493p001D* + ID_MODEL_FROM_DATABASE=Greentit [Ambit2 R] + +usb:v1493p001E* + ID_MODEL_FROM_DATABASE=Ibisbill [Ambit3 Run] + +usb:v1497* + ID_VENDOR_FROM_DATABASE=Panstrong Company Ltd. + +usb:v1498* + ID_VENDOR_FROM_DATABASE=Microtek International Inc. + +usb:v1498pA090* + ID_MODEL_FROM_DATABASE=DVB-T Tuner + +usb:v149A* + ID_VENDOR_FROM_DATABASE=Imagination Technologies + +usb:v149Ap2107* + ID_MODEL_FROM_DATABASE=DBX1 DSP core + +usb:v14AA* + ID_VENDOR_FROM_DATABASE=WideView Technology Inc. + +usb:v14AAp0001* + ID_MODEL_FROM_DATABASE=Avermedia AverTV DVBT USB1.1 (cold) + +usb:v14AAp0002* + ID_MODEL_FROM_DATABASE=Avermedia AverTV DVBT USB1.1 (warm) + +usb:v14AAp0201* + ID_MODEL_FROM_DATABASE=AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0 (cold) + +usb:v14AAp0221* + ID_MODEL_FROM_DATABASE=WT-220U DVB-T dongle + +usb:v14AAp022B* + ID_MODEL_FROM_DATABASE=WT-220U DVB-T dongle + +usb:v14AAp0301* + ID_MODEL_FROM_DATABASE=AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0 (warm) + +usb:v14AD* + ID_VENDOR_FROM_DATABASE=CTK Corporation + +usb:v14AE* + ID_VENDOR_FROM_DATABASE=Printronix Inc. + +usb:v14AF* + ID_VENDOR_FROM_DATABASE=ATP Electronics Inc. + +usb:v14B0* + ID_VENDOR_FROM_DATABASE=StarTech.com Ltd. + +usb:v14B2* + ID_VENDOR_FROM_DATABASE=Ralink Technology, Corp. + +usb:v14B2p3A93* + ID_MODEL_FROM_DATABASE=Topcom 802.11bg Wireless Adapter [Atheros AR5523] + +usb:v14B2p3A95* + ID_MODEL_FROM_DATABASE=Toshiba WUS-G06G-JT 802.11bg Wireless Adapter [Atheros AR5523] + +usb:v14B2p3A98* + ID_MODEL_FROM_DATABASE=Airlink101 AWLL4130 802.11bg Wireless Adapter [Atheros AR5523] + +usb:v14B2p3C02* + ID_MODEL_FROM_DATABASE=Conceptronic C54RU v2 802.11bg Wireless Adapter [Ralink RT2571] + +usb:v14B2p3C05* + ID_MODEL_FROM_DATABASE=rt2570 802.11g WLAN + +usb:v14B2p3C06* + ID_MODEL_FROM_DATABASE=Conceptronic C300RU v1 802.11bgn Wireless Adapter [Ralink RT2870] + +usb:v14B2p3C07* + ID_MODEL_FROM_DATABASE=802.11n adapter + +usb:v14B2p3C09* + ID_MODEL_FROM_DATABASE=802.11n adapter + +usb:v14B2p3C22* + ID_MODEL_FROM_DATABASE=Conceptronic C54RU v3 802.11bg Wireless Adapter [Ralink RT2571W] + +usb:v14B2p3C23* + ID_MODEL_FROM_DATABASE=Airlink101 AWLL6080 802.11bgn Wireless Adapter [Ralink RT2870] + +usb:v14B2p3C24* + ID_MODEL_FROM_DATABASE=NEC NP01LM 802.11abg Wireless Adapter [Ralink RT2571W] + +usb:v14B2p3C25* + ID_MODEL_FROM_DATABASE=DrayTek Vigor N61 802.11bgn Wireless Adapter [Ralink RT2870] + +usb:v14B2p3C27* + ID_MODEL_FROM_DATABASE=Airlink101 AWLL6070 802.11bgn Wireless Adapter [Ralink RT2770] + +usb:v14B2p3C28* + ID_MODEL_FROM_DATABASE=Conceptronic C300RU v2 802.11bgn Wireless Adapter [Ralink RT2770] + +usb:v14B2p3C2B* + ID_MODEL_FROM_DATABASE=NEC NP02LM 802.11bgn Wireless Adapter [Ralink RT3072] + +usb:v14B2p3C2C* + ID_MODEL_FROM_DATABASE=Keebox W150NU 802.11bgn Wireless Adapter [Ralink RT3070] + +usb:v14C0* + ID_VENDOR_FROM_DATABASE=Rockwell Automation, Inc. + +usb:v14C2* + ID_VENDOR_FROM_DATABASE=Gemlight Computer, Ltd + +usb:v14C2p0250* + ID_MODEL_FROM_DATABASE=Storage Adapter V2 + +usb:v14C2p0350* + ID_MODEL_FROM_DATABASE=Storage Adapter V2 + +usb:v14C8* + ID_VENDOR_FROM_DATABASE=Zytronic + +usb:v14C8p0005* + ID_MODEL_FROM_DATABASE=Touchscreen Controller + +usb:v14CD* + ID_VENDOR_FROM_DATABASE=Super Top + +usb:v14CDp1212* + ID_MODEL_FROM_DATABASE=microSD card reader (SY-T18) + +usb:v14CDp121C* + ID_MODEL_FROM_DATABASE=microSD card reader + +usb:v14CDp121F* + ID_MODEL_FROM_DATABASE=microSD CardReader SY-T18 + +usb:v14CDp123A* + ID_MODEL_FROM_DATABASE=SD/MMC/RS-MMC Card Reader + +usb:v14CDp125C* + ID_MODEL_FROM_DATABASE=SD card reader + +usb:v14CDp127B* + ID_MODEL_FROM_DATABASE=SDXC Reader + +usb:v14CDp6116* + ID_MODEL_FROM_DATABASE=M6116 SATA Bridge + +usb:v14CDp6600* + ID_MODEL_FROM_DATABASE=M110E PATA bridge + +usb:v14CDp6700* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v14CDp6900* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v14CDp8123* + ID_MODEL_FROM_DATABASE=SD MMC Reader + +usb:v14CDp8125* + ID_MODEL_FROM_DATABASE=SD MMC Reader + +usb:v14CDp8601* + ID_MODEL_FROM_DATABASE=4-Port hub + +usb:v14CDp8608* + ID_MODEL_FROM_DATABASE=Hub [Super Top] + +usb:v14D8* + ID_VENDOR_FROM_DATABASE=JAMER INDUSTRIES CO., LTD. + +usb:v14DD* + ID_VENDOR_FROM_DATABASE=Raritan Computer, Inc. + +usb:v14DDp1007* + ID_MODEL_FROM_DATABASE=D2CIM-VUSB KVM connector + +usb:v14E0* + ID_VENDOR_FROM_DATABASE=WiNRADiO Communications + +usb:v14E0p0501* + ID_MODEL_FROM_DATABASE=WR-G528e 'CHEETAH' + +usb:v14E1* + ID_VENDOR_FROM_DATABASE=Dialogue Technology Corp. + +usb:v14E1p5000* + ID_MODEL_FROM_DATABASE=PenMount 5000 Touch Controller + +usb:v14E5* + ID_VENDOR_FROM_DATABASE=SAIN Information & Communications Co., Ltd. + +usb:v14EA* + ID_VENDOR_FROM_DATABASE=Planex Communications + +usb:v14EApAB10* + ID_MODEL_FROM_DATABASE=GW-US54GZ + +usb:v14EApAB11* + ID_MODEL_FROM_DATABASE=GU-1000T + +usb:v14EApAB13* + ID_MODEL_FROM_DATABASE=GW-US54Mini 802.11bg + +usb:v14ED* + ID_VENDOR_FROM_DATABASE=Shure Inc. + +usb:v14EDp29B6* + ID_MODEL_FROM_DATABASE=X2u Adapter + +usb:v14F7* + ID_VENDOR_FROM_DATABASE=TechniSat Digital GmbH + +usb:v14F7p0001* + ID_MODEL_FROM_DATABASE=SkyStar 2 HD CI + +usb:v14F7p0002* + ID_MODEL_FROM_DATABASE=SkyStar 2 HD CI + +usb:v14F7p0003* + ID_MODEL_FROM_DATABASE=CableStar Combo HD CI + +usb:v14F7p0004* + ID_MODEL_FROM_DATABASE=AirStar TeleStick 2 + +usb:v14F7p0500* + ID_MODEL_FROM_DATABASE=DVB-PC TV Star HD + +usb:v1500* + ID_VENDOR_FROM_DATABASE=Ellisys + +usb:v1501* + ID_VENDOR_FROM_DATABASE=Pine-Tum Enterprise Co., Ltd. + +usb:v1509* + ID_VENDOR_FROM_DATABASE=First International Computer, Inc. + +usb:v1509p0A01* + ID_MODEL_FROM_DATABASE=LI-3100 Area Meter + +usb:v1509p0A02* + ID_MODEL_FROM_DATABASE=LI-7000 CO2/H2O Gas Analyzer + +usb:v1509p0A03* + ID_MODEL_FROM_DATABASE=C-DiGit Blot Scanner + +usb:v1509p9242* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v1513* + ID_VENDOR_FROM_DATABASE=medMobile + +usb:v1513p0444* + ID_MODEL_FROM_DATABASE=medMobile + +usb:v1514* + ID_VENDOR_FROM_DATABASE=Actel + +usb:v1514p2003* + ID_MODEL_FROM_DATABASE=FlashPro3 Programmer + +usb:v1514p2004* + ID_MODEL_FROM_DATABASE=FlashPro3 Programmer + +usb:v1514p2005* + ID_MODEL_FROM_DATABASE=FlashPro3 Programmer + +usb:v1516* + ID_VENDOR_FROM_DATABASE=CompUSA + +usb:v1516p1603* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v1516p8628* + ID_MODEL_FROM_DATABASE=Pen Drive + +usb:v1518* + ID_VENDOR_FROM_DATABASE=Cheshire Engineering Corp. + +usb:v1518p0001* + ID_MODEL_FROM_DATABASE=HDReye High Dynamic Range Camera + +usb:v1518p0002* + ID_MODEL_FROM_DATABASE=HDReye (before firmware loads) + +usb:v1519* + ID_VENDOR_FROM_DATABASE=Comneon + +usb:v1519p0020* + ID_MODEL_FROM_DATABASE=HSIC Device + +usb:v151F* + ID_VENDOR_FROM_DATABASE=Opal Kelly Incorporated + +usb:v151Fp0020* + ID_MODEL_FROM_DATABASE=XEM3001v1 + +usb:v151Fp0021* + ID_MODEL_FROM_DATABASE=XEM3001v2 + +usb:v151Fp0022* + ID_MODEL_FROM_DATABASE=XEM3010 + +usb:v151Fp0023* + ID_MODEL_FROM_DATABASE=XEM3005 + +usb:v151Fp0028* + ID_MODEL_FROM_DATABASE=XEM3050 + +usb:v151Fp002B* + ID_MODEL_FROM_DATABASE=XEM5010 + +usb:v151Fp002C* + ID_MODEL_FROM_DATABASE=XEM6001 + +usb:v151Fp002D* + ID_MODEL_FROM_DATABASE=XEM6010-LX45 + +usb:v151Fp002E* + ID_MODEL_FROM_DATABASE=XEM6010-LX150 + +usb:v151Fp0030* + ID_MODEL_FROM_DATABASE=XEM6006-LX16 + +usb:v151Fp0033* + ID_MODEL_FROM_DATABASE=XEM6002-LX9 + +usb:v151Fp0034* + ID_MODEL_FROM_DATABASE=XEM7001-A15 + +usb:v151Fp0036* + ID_MODEL_FROM_DATABASE=XEM7010-A50 + +usb:v151Fp0037* + ID_MODEL_FROM_DATABASE=XEM7010-A200 + +usb:v151Fp0120* + ID_MODEL_FROM_DATABASE=ZEM4310 + +usb:v151Fp0121* + ID_MODEL_FROM_DATABASE=XEM6310-LX45 + +usb:v151Fp0122* + ID_MODEL_FROM_DATABASE=XEM6310-LX150 + +usb:v151Fp0123* + ID_MODEL_FROM_DATABASE=XEM6310MT-LX45T + +usb:v151Fp0125* + ID_MODEL_FROM_DATABASE=XEM7350-K70T + +usb:v151Fp0126* + ID_MODEL_FROM_DATABASE=XEM7350-K160T + +usb:v151Fp0127* + ID_MODEL_FROM_DATABASE=XEM7350-K410T + +usb:v151Fp0128* + ID_MODEL_FROM_DATABASE=XEM6310MT-LX150T + +usb:v151Fp0129* + ID_MODEL_FROM_DATABASE=ZEM5305-A2 + +usb:v151Fp012B* + ID_MODEL_FROM_DATABASE=XEM7360-K160T + +usb:v151Fp012C* + ID_MODEL_FROM_DATABASE=XEM7360-K410T + +usb:v151Fp012D* + ID_MODEL_FROM_DATABASE=ZEM5310-A4 + +usb:v151Fp0130* + ID_MODEL_FROM_DATABASE=XEM7310-A75 + +usb:v151Fp0131* + ID_MODEL_FROM_DATABASE=XEM7310-A200 + +usb:v1520* + ID_VENDOR_FROM_DATABASE=Bitwire Corp. + +usb:v1524* + ID_VENDOR_FROM_DATABASE=ENE Technology Inc + +usb:v1524p6680* + ID_MODEL_FROM_DATABASE=UTS 6680 + +usb:v1527* + ID_VENDOR_FROM_DATABASE=Silicon Portals + +usb:v1527p0200* + ID_MODEL_FROM_DATABASE=YAP Phone (no firmware) + +usb:v1527p0201* + ID_MODEL_FROM_DATABASE=YAP Phone + +usb:v1529* + ID_VENDOR_FROM_DATABASE=UBIQUAM Co., Ltd. + +usb:v1529p3100* + ID_MODEL_FROM_DATABASE=CDMA 1xRTT USB Modem (U-100/105/200/300/520) + +usb:v152A* + ID_VENDOR_FROM_DATABASE=Thesycon Systemsoftware & Consulting GmbH + +usb:v152Ap8350* + ID_MODEL_FROM_DATABASE=NET Gmbh iCube Camera + +usb:v152Ap8400* + ID_MODEL_FROM_DATABASE=INI DVS128 + +usb:v152Ap840D* + ID_MODEL_FROM_DATABASE=INI DAViS + +usb:v152Ap841A* + ID_MODEL_FROM_DATABASE=INI DAViS FX3 + +usb:v152B* + ID_VENDOR_FROM_DATABASE=MIR Srl + +usb:v152Bp0001* + ID_MODEL_FROM_DATABASE=spirobank II + +usb:v152Bp0002* + ID_MODEL_FROM_DATABASE=spirolab III + +usb:v152Bp0003* + ID_MODEL_FROM_DATABASE=MiniSpir + +usb:v152Bp0004* + ID_MODEL_FROM_DATABASE=Oxi + +usb:v152Bp0005* + ID_MODEL_FROM_DATABASE=spiros II + +usb:v152Bp0006* + ID_MODEL_FROM_DATABASE=smiths spirobank II + +usb:v152Bp0007* + ID_MODEL_FROM_DATABASE=smiths spirobank G-USB + +usb:v152Bp0008* + ID_MODEL_FROM_DATABASE=smiths MiniSpir + +usb:v152Bp0009* + ID_MODEL_FROM_DATABASE=spirobank G-USB + +usb:v152Bp000A* + ID_MODEL_FROM_DATABASE=smiths Oxi + +usb:v152Bp000B* + ID_MODEL_FROM_DATABASE=smiths spirolab III + +usb:v152Bp000C* + ID_MODEL_FROM_DATABASE=chorus III + +usb:v152Bp000D* + ID_MODEL_FROM_DATABASE=spirolab III Bw + +usb:v152Bp000E* + ID_MODEL_FROM_DATABASE=spirolab III + +usb:v152Bp000F* + ID_MODEL_FROM_DATABASE=easySpiro + +usb:v152Bp0010* + ID_MODEL_FROM_DATABASE=Spirotel converter + +usb:v152Bp0011* + ID_MODEL_FROM_DATABASE=spirobank + +usb:v152Bp0012* + ID_MODEL_FROM_DATABASE=spiro3 Zimmer + +usb:v152Bp0013* + ID_MODEL_FROM_DATABASE=spirotel serial + +usb:v152Bp0014* + ID_MODEL_FROM_DATABASE=spirotel II + +usb:v152Bp0015* + ID_MODEL_FROM_DATABASE=spirodoc + +usb:v152D* + ID_VENDOR_FROM_DATABASE=JMicron Technology Corp. / JMicron USA Technology Corp. + +usb:v152Dp0539* + ID_MODEL_FROM_DATABASE=JMS539/567 SuperSpeed SATA II/III 3.0G/6.0G Bridge + +usb:v152Dp0551* + ID_MODEL_FROM_DATABASE=JMS551 SuperSpeed two ports SATA 3Gb/s bridge + +usb:v152Dp0561* + ID_MODEL_FROM_DATABASE=JMS551 - Sharkoon SATA QuickPort Duo + +usb:v152Dp0567* + ID_MODEL_FROM_DATABASE=JMS567 SATA 6Gb/s bridge + +usb:v152Dp0578* + ID_MODEL_FROM_DATABASE=JMS567 SATA 6Gb/s bridge + +usb:v152Dp0770* + ID_MODEL_FROM_DATABASE=Alienware Integrated Webcam + +usb:v152Dp1561* + ID_MODEL_FROM_DATABASE=JMS561U two ports SATA 6Gb/s bridge + +usb:v152Dp2329* + ID_MODEL_FROM_DATABASE=JM20329 SATA Bridge + +usb:v152Dp2335* + ID_MODEL_FROM_DATABASE=ATA/ATAPI Bridge + +usb:v152Dp2336* + ID_MODEL_FROM_DATABASE=Hard Disk Drive + +usb:v152Dp2337* + ID_MODEL_FROM_DATABASE=ATA/ATAPI Bridge + +usb:v152Dp2338* + ID_MODEL_FROM_DATABASE=JM20337 Hi-Speed USB to SATA & PATA Combo Bridge + +usb:v152Dp2339* + ID_MODEL_FROM_DATABASE=JM20339 SATA Bridge + +usb:v152Dp2352* + ID_MODEL_FROM_DATABASE=ATA/ATAPI Bridge + +usb:v152Dp2509* + ID_MODEL_FROM_DATABASE=JMS539, JMS551 SATA 3Gb/s bridge + +usb:v152Dp2551* + ID_MODEL_FROM_DATABASE=JMS551 SATA 3Gb/s bridge + +usb:v152Dp2561* + ID_MODEL_FROM_DATABASE=CEB-2235S-U3 external RAID box + +usb:v152Dp2566* + ID_MODEL_FROM_DATABASE=JMS566 SATA 3Gb/s bridge + +usb:v152Dp2590* + ID_MODEL_FROM_DATABASE=JMS567 SATA 6Gb/s bridge + +usb:v152Dp3562* + ID_MODEL_FROM_DATABASE=JMS567 SATA 6Gb/s bridge + +usb:v152Dp3569* + ID_MODEL_FROM_DATABASE=JMS566 SATA 3Gb/s bridge + +usb:v152E* + ID_VENDOR_FROM_DATABASE=LG (HLDS) + +usb:v152Ep2507* + ID_MODEL_FROM_DATABASE=PL-2507 IDE Controller + +usb:v152EpE001* + ID_MODEL_FROM_DATABASE=GSA-5120D DVD-RW + +usb:v1532* + ID_VENDOR_FROM_DATABASE=Razer USA, Ltd + +usb:v1532p0001* + ID_MODEL_FROM_DATABASE=RZ01-020300 Optical Mouse [Diamondback] + +usb:v1532p0003* + ID_MODEL_FROM_DATABASE=Krait Mouse + +usb:v1532p0007* + ID_MODEL_FROM_DATABASE=DeathAdder Mouse + +usb:v1532p0013* + ID_MODEL_FROM_DATABASE=Orochi mouse + +usb:v1532p0015* + ID_MODEL_FROM_DATABASE=Naga Mouse + +usb:v1532p0016* + ID_MODEL_FROM_DATABASE=DeathAdder Mouse + +usb:v1532p0017* + ID_MODEL_FROM_DATABASE=RZ01-0035 Laser Gaming Mouse [Imperator] + +usb:v1532p001C* + ID_MODEL_FROM_DATABASE=RZ01-0036 Optical Gaming Mouse [Abyssus] + +usb:v1532p0024* + ID_MODEL_FROM_DATABASE=Mamba + +usb:v1532p002E* + ID_MODEL_FROM_DATABASE=RZ01-0058 Gaming Mouse [Naga] + +usb:v1532p002F* + ID_MODEL_FROM_DATABASE=Imperator 2012 + +usb:v1532p0036* + ID_MODEL_FROM_DATABASE=RZ01-0075, Gaming Mouse [Naga Hex] + +usb:v1532p0042* + ID_MODEL_FROM_DATABASE=Abyssus 2014 + +usb:v1532p0043* + ID_MODEL_FROM_DATABASE=DeathAdder Chroma + +usb:v1532p0044* + ID_MODEL_FROM_DATABASE=Mamba Chroma (Wired) + +usb:v1532p0045* + ID_MODEL_FROM_DATABASE=Mamba Chroma (Wireless) + +usb:v1532p0046* + ID_MODEL_FROM_DATABASE=Mamba 2015 Tournament Edition [RZ01-01370100-R3] + +usb:v1532p0048* + ID_MODEL_FROM_DATABASE=Orochi (Wired) + +usb:v1532p0101* + ID_MODEL_FROM_DATABASE=Copperhead Mouse + +usb:v1532p0102* + ID_MODEL_FROM_DATABASE=Tarantula Keyboard + +usb:v1532p0109* + ID_MODEL_FROM_DATABASE=Lycosa Keyboard + +usb:v1532p010D* + ID_MODEL_FROM_DATABASE=BlackWidow Ultimate 2012 + +usb:v1532p0113* + ID_MODEL_FROM_DATABASE=RZ07-0074 Gaming Keypad [Orbweaver] + +usb:v1532p0118* + ID_MODEL_FROM_DATABASE=RZ03-0080, Gaming Keyboard [Deathstalker] + +usb:v1532p011A* + ID_MODEL_FROM_DATABASE=BlackWidow Ultimate 2013 + +usb:v1532p011B* + ID_MODEL_FROM_DATABASE=BlackWidow Classic + +usb:v1532p0203* + ID_MODEL_FROM_DATABASE=BlackWidow Chroma + +usb:v1532p0205* + ID_MODEL_FROM_DATABASE=Blade Stealth + +usb:v1532p0208* + ID_MODEL_FROM_DATABASE=Tartarus + +usb:v1532p0209* + ID_MODEL_FROM_DATABASE=BlackWidow Tournament Edition Chroma + +usb:v1532p0214* + ID_MODEL_FROM_DATABASE=BlackWidow Ultimate 2016 + +usb:v1532p0216* + ID_MODEL_FROM_DATABASE=BlackWidow X Chroma + +usb:v1532p021A* + ID_MODEL_FROM_DATABASE=BlackWidow X Tournament Edition Chroma + +usb:v1532p0220* + ID_MODEL_FROM_DATABASE=Blade Stealth (2016) + +usb:v1532p0300* + ID_MODEL_FROM_DATABASE=RZ06-0063 Motion Sensing Controllers [Hydra] + +usb:v1532p0C00* + ID_MODEL_FROM_DATABASE=Firefly + +usb:v153B* + ID_VENDOR_FROM_DATABASE=TerraTec Electronic GmbH + +usb:v153Bp1181* + ID_MODEL_FROM_DATABASE=Cinergy S2 PCIe Dual Port 1 + +usb:v153Bp1182* + ID_MODEL_FROM_DATABASE=Cinergy S2 PCIe Dual Port 2 + +usb:v1546* + ID_VENDOR_FROM_DATABASE=U-Blox AG + +usb:v1546p01A4* + ID_MODEL_FROM_DATABASE=Antaris 4 + +usb:v1546p01A5* + ID_MODEL_FROM_DATABASE=[u-blox 5] + +usb:v1546p01A6* + ID_MODEL_FROM_DATABASE=[u-blox 6] + +usb:v1546p01A7* + ID_MODEL_FROM_DATABASE=[u-blox 7] + +usb:v1546p01A8* + ID_MODEL_FROM_DATABASE=[u-blox 8] + +usb:v1546p1102* + ID_MODEL_FROM_DATABASE=LISA-U2 + +usb:v1547* + ID_VENDOR_FROM_DATABASE=SG Intec Ltd & Co KG + +usb:v1547p1000* + ID_MODEL_FROM_DATABASE=SG-Lock[U2] + +usb:v154A* + ID_VENDOR_FROM_DATABASE=Celectronic GmbH + +usb:v154Ap8180* + ID_MODEL_FROM_DATABASE=CARD STAR/medic2 + +usb:v154B* + ID_VENDOR_FROM_DATABASE=PNY + +usb:v154Bp0010* + ID_MODEL_FROM_DATABASE=USB 2.0 Flash Drive + +usb:v154Bp0048* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v154Bp004D* + ID_MODEL_FROM_DATABASE=8 GB Flash Drive + +usb:v154Bp0053* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v154Bp0057* + ID_MODEL_FROM_DATABASE=32GB Micro Slide Attache Flash Drive + +usb:v154Bp005B* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v154Bp0062* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v154Bp007A* + ID_MODEL_FROM_DATABASE=Classic Attache Flash Drive + +usb:v154Bp6545* + ID_MODEL_FROM_DATABASE=FD Device + +usb:v154BpFA05* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v154D* + ID_VENDOR_FROM_DATABASE=ConnectCounty Holdings Berhad + +usb:v154E* + ID_VENDOR_FROM_DATABASE=D&M Holdings, Inc. (Denon/Marantz) + +usb:v154Ep3000* + ID_MODEL_FROM_DATABASE=Marantz RC9001 Remote Control + +usb:v154F* + ID_VENDOR_FROM_DATABASE=SNBC CO., Ltd + +usb:v1554* + ID_VENDOR_FROM_DATABASE=Prolink Microsystems Corp. + +usb:v1554p5010* + ID_MODEL_FROM_DATABASE=PV-D231U(RN)-F [PixelView PlayTV SBTVD Full-Seg] + +usb:v1557* + ID_VENDOR_FROM_DATABASE=OQO + +usb:v1557p0002* + ID_MODEL_FROM_DATABASE=model 01 WiFi interface + +usb:v1557p0003* + ID_MODEL_FROM_DATABASE=model 01 Bluetooth interface + +usb:v1557p0A80* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) + +usb:v1557p7720* + ID_MODEL_FROM_DATABASE=model 01+ Ethernet + +usb:v1557p8150* + ID_MODEL_FROM_DATABASE=model 01 Ethernet interface + +usb:v1568* + ID_VENDOR_FROM_DATABASE=Sunf Pu Technology Co., Ltd + +usb:v156F* + ID_VENDOR_FROM_DATABASE=Quantum Corporation + +usb:v1570* + ID_VENDOR_FROM_DATABASE=ALLTOP TECHNOLOGY CO., LTD. + +usb:v157B* + ID_VENDOR_FROM_DATABASE=Ketron SRL + +usb:v157E* + ID_VENDOR_FROM_DATABASE=TRENDnet + +usb:v157Ep3006* + ID_MODEL_FROM_DATABASE=TEW-444UB EU [TRENDnet] + +usb:v157Ep3007* + ID_MODEL_FROM_DATABASE=TEW-444UB EU (no firmware) + +usb:v157Ep300A* + ID_MODEL_FROM_DATABASE=TEW-429UB 802.11bg + +usb:v157Ep300B* + ID_MODEL_FROM_DATABASE=TEW-429UB 802.11bg + +usb:v157Ep300C* + ID_MODEL_FROM_DATABASE=TEW-429UF A1 802.11bg Wireless Adapter [ZyDAS ZD1211B] + +usb:v157Ep300D* + ID_MODEL_FROM_DATABASE=TEW-429UB C1 802.11bg + +usb:v157Ep300E* + ID_MODEL_FROM_DATABASE=SMC SMCWUSB-N 802.11bgn 2x2:2 Wireless Adapter [Ralink RT2870] + +usb:v157Ep3012* + ID_MODEL_FROM_DATABASE=TEW-604UB 802.11bg Wireless Adapter [Atheros AR5523] + +usb:v157Ep3013* + ID_MODEL_FROM_DATABASE=TEW-645UB 802.11bgn 1x2:2 Wireless Adapter [Ralink RT2770] + +usb:v157Ep3204* + ID_MODEL_FROM_DATABASE=Allnet ALL0298 v2 802.11bg + +usb:v157Ep3205* + ID_MODEL_FROM_DATABASE=Allnet ALL0283 [AR5523] + +usb:v157Ep3206* + ID_MODEL_FROM_DATABASE=Allnet ALL0283 [AR5523](no firmware) + +usb:v157Ep3207* + ID_MODEL_FROM_DATABASE=TEW-509UB A1 802.11abg Wireless Adapter [ZyDAS ZD1211] + +usb:v157Ep3208* + ID_MODEL_FROM_DATABASE=TEW-509UB 1.1R 802.11abg Wireless Adapter + +usb:v1582* + ID_VENDOR_FROM_DATABASE=Fiberline + +usb:v1582p6003* + ID_MODEL_FROM_DATABASE=WL-430U 802.11bg + +usb:v1587* + ID_VENDOR_FROM_DATABASE=SMA Technologie AG + +usb:v158D* + ID_VENDOR_FROM_DATABASE=Oakley Inc. + +usb:v158E* + ID_VENDOR_FROM_DATABASE=JDS Uniphase Corporation (JDSU) + +usb:v158Ep0820* + ID_MODEL_FROM_DATABASE=SmartPocket Class Device + +usb:v1598* + ID_VENDOR_FROM_DATABASE=Kunshan Guoji Electronics Co., Ltd. + +usb:v15A2* + ID_VENDOR_FROM_DATABASE=Freescale Semiconductor, Inc. + +usb:v15A2p0038* + ID_MODEL_FROM_DATABASE=9S08JS Bootloader + +usb:v15A2p003B* + ID_MODEL_FROM_DATABASE=USB2CAN Application for ColdFire DEMOJM board + +usb:v15A2p0042* + ID_MODEL_FROM_DATABASE=OSBDM - Debug Port + +usb:v15A2p004F* + ID_MODEL_FROM_DATABASE=i.MX28 SystemOnChip in RecoveryMode + +usb:v15A2p0052* + ID_MODEL_FROM_DATABASE=i.MX50 SystemOnChip in RecoveryMode + +usb:v15A2p0054* + ID_MODEL_FROM_DATABASE=i.MX 6Dual/6Quad SystemOnChip in RecoveryMode + +usb:v15A2p0061* + ID_MODEL_FROM_DATABASE=i.MX 6Solo/6DualLite SystemOnChip in RecoveryMode + +usb:v15A4* + ID_VENDOR_FROM_DATABASE=Afatech Technologies, Inc. + +usb:v15A4p1000* + ID_MODEL_FROM_DATABASE=AF9015/AF9035 DVB-T stick + +usb:v15A4p1001* + ID_MODEL_FROM_DATABASE=AF9015/AF9035 DVB-T stick + +usb:v15A4p1336* + ID_MODEL_FROM_DATABASE=SDHC/MicroSD/MMC/MS/M2/CF/XD Flash Card Reader + +usb:v15A4p9015* + ID_MODEL_FROM_DATABASE=AF9015 DVB-T USB2.0 stick + +usb:v15A4p9016* + ID_MODEL_FROM_DATABASE=AF9015 DVB-T USB2.0 stick + +usb:v15A8* + ID_VENDOR_FROM_DATABASE=Teams Power Limited + +usb:v15A9* + ID_VENDOR_FROM_DATABASE=Gemtek + +usb:v15A9p0002* + ID_MODEL_FROM_DATABASE=SparkLAN WL-682 802.11bg Wireless Adapter [Intersil ISL3887] + +usb:v15A9p0004* + ID_MODEL_FROM_DATABASE=WUBR-177G [Ralink RT2571W] + +usb:v15A9p0006* + ID_MODEL_FROM_DATABASE=Wireless 11n USB Adapter + +usb:v15A9p0010* + ID_MODEL_FROM_DATABASE=802.11n USB Wireless Card + +usb:v15A9p0012* + ID_MODEL_FROM_DATABASE=WUBR-208N 802.11abgn Wireless Adapter [Ralink RT2870] + +usb:v15A9p002D* + ID_MODEL_FROM_DATABASE=WLTUBA-107 [Yota 4G LTE] + +usb:v15AA* + ID_VENDOR_FROM_DATABASE=Gearway Electronics (Dong Guan) Co., Ltd. + +usb:v15AD* + ID_VENDOR_FROM_DATABASE=VMware Inc. + +usb:v15BA* + ID_VENDOR_FROM_DATABASE=Olimex Ltd. + +usb:v15BAp0003* + ID_MODEL_FROM_DATABASE=OpenOCD JTAG + +usb:v15BAp0004* + ID_MODEL_FROM_DATABASE=OpenOCD JTAG TINY + +usb:v15BAp002A* + ID_MODEL_FROM_DATABASE=ARM-USB-TINY-H JTAG interface + +usb:v15BAp002B* + ID_MODEL_FROM_DATABASE=ARM-USB-OCD-H JTAG+RS232 + +usb:v15C0* + ID_VENDOR_FROM_DATABASE=XL Imaging + +usb:v15C0p0001* + ID_MODEL_FROM_DATABASE=2M pixel Microscope Camera + +usb:v15C0p0002* + ID_MODEL_FROM_DATABASE=3M pixel Microscope Camera + +usb:v15C0p0003* + ID_MODEL_FROM_DATABASE=1.3M pixel Microscope Camera (mono) + +usb:v15C0p0004* + ID_MODEL_FROM_DATABASE=1.3M pixel Microscope Camera (colour) + +usb:v15C0p0005* + ID_MODEL_FROM_DATABASE=3M pixel Microscope Camera (Mk 2) + +usb:v15C0p0006* + ID_MODEL_FROM_DATABASE=2M pixel Microscope Camera (with capture button) + +usb:v15C0p0007* + ID_MODEL_FROM_DATABASE=3M pixel Microscope Camera (with capture button) + +usb:v15C0p0008* + ID_MODEL_FROM_DATABASE=1.3M pixel Microscope Camera (colour, with capture button) + +usb:v15C0p0009* + ID_MODEL_FROM_DATABASE=1.3M pixel Microscope Camera (colour, with capture button) + +usb:v15C0p000A* + ID_MODEL_FROM_DATABASE=2M pixel Microscope Camera (Mk 2) + +usb:v15C0p0010* + ID_MODEL_FROM_DATABASE=1.3M pixel "Tinycam" + +usb:v15C0p0101* + ID_MODEL_FROM_DATABASE=3M pixel Microscope Camera + +usb:v15C2* + ID_VENDOR_FROM_DATABASE=SoundGraph Inc. + +usb:v15C2p0036* + ID_MODEL_FROM_DATABASE=LC16M VFD Display/IR Receiver + +usb:v15C2p0038* + ID_MODEL_FROM_DATABASE=GD01 MX LCD Display/IR Receiver + +usb:v15C2p0042* + ID_MODEL_FROM_DATABASE=Antec Veris Multimedia Station E-Z IR Receiver + +usb:v15C2pFFDA* + ID_MODEL_FROM_DATABASE=iMON PAD Remote Controller + +usb:v15C2pFFDC* + ID_MODEL_FROM_DATABASE=iMON PAD Remote Controller + +usb:v15C5* + ID_VENDOR_FROM_DATABASE=Advance Multimedia Internet Technology Inc. (AMIT) + +usb:v15C5p0008* + ID_MODEL_FROM_DATABASE=WL532U 802.11g Adapter + +usb:v15C6* + ID_VENDOR_FROM_DATABASE=Laboratoires MXM + +usb:v15C6p1000* + ID_MODEL_FROM_DATABASE=DigistimSP (cold) + +usb:v15C6p1001* + ID_MODEL_FROM_DATABASE=DigistimSP (warm) + +usb:v15C6p1002* + ID_MODEL_FROM_DATABASE=DigimapSP USB (cold) + +usb:v15C6p1003* + ID_MODEL_FROM_DATABASE=DigimapSP USB (warm) + +usb:v15C6p1004* + ID_MODEL_FROM_DATABASE=DigistimSP (cold) + +usb:v15C6p1005* + ID_MODEL_FROM_DATABASE=DigistimSP (warm) + +usb:v15C6p1100* + ID_MODEL_FROM_DATABASE=Odyssee (cold) + +usb:v15C6p1101* + ID_MODEL_FROM_DATABASE=Odyssee (warm) + +usb:v15C6p1200* + ID_MODEL_FROM_DATABASE=Digispy + +usb:v15C8* + ID_VENDOR_FROM_DATABASE=KTF Technologies + +usb:v15C8p3201* + ID_MODEL_FROM_DATABASE=EVER EV-W100/EV-W250 + +usb:v15C9* + ID_VENDOR_FROM_DATABASE=D-Box Technologies + +usb:v15CA* + ID_VENDOR_FROM_DATABASE=Textech International Ltd. + +usb:v15CAp00C3* + ID_MODEL_FROM_DATABASE=Mini Optical Mouse + +usb:v15CAp0101* + ID_MODEL_FROM_DATABASE=MIDI Interface cable + +usb:v15CAp1806* + ID_MODEL_FROM_DATABASE=MIDI Interface cable + +usb:v15D5* + ID_VENDOR_FROM_DATABASE=Coulomb Electronics Ltd. + +usb:v15D9* + ID_VENDOR_FROM_DATABASE=Trust International B.V. + +usb:v15D9p0A33* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v15D9p0A37* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v15D9p0A41* + ID_MODEL_FROM_DATABASE=MI-2540D [Optical mouse] + +usb:v15D9p0A4C* + ID_MODEL_FROM_DATABASE=USB+PS/2 Optical Mouse + +usb:v15D9p0A4D* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v15D9p0A4F* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v15DC* + ID_VENDOR_FROM_DATABASE=Hynix Semiconductor Inc. + +usb:v15E0* + ID_VENDOR_FROM_DATABASE=Seong Ji Industrial Co., Ltd. + +usb:v15E1* + ID_VENDOR_FROM_DATABASE=RSA + +usb:v15E1p2007* + ID_MODEL_FROM_DATABASE=RSA SecurID (R) Authenticator + +usb:v15E4* + ID_VENDOR_FROM_DATABASE=Numark + +usb:v15E4p0024* + ID_MODEL_FROM_DATABASE=Mixtrack + +usb:v15E4p0140* + ID_MODEL_FROM_DATABASE=ION VCR 2 PC / Video 2 PC + +usb:v15E8* + ID_VENDOR_FROM_DATABASE=SohoWare + +usb:v15E8p9100* + ID_MODEL_FROM_DATABASE=NUB100 Ethernet [pegasus] + +usb:v15E8p9110* + ID_MODEL_FROM_DATABASE=10/100 USB Ethernet + +usb:v15E9* + ID_VENDOR_FROM_DATABASE=Pacific Digital Corp. + +usb:v15E9p04CE* + ID_MODEL_FROM_DATABASE=MemoryFrame MF-570 + +usb:v15E9p1968* + ID_MODEL_FROM_DATABASE=MemoryFrame MF-570 + +usb:v15E9p1969* + ID_MODEL_FROM_DATABASE=Digital Frame + +usb:v15EC* + ID_VENDOR_FROM_DATABASE=Belcarra Technologies Corp. + +usb:v15F4* + ID_VENDOR_FROM_DATABASE=HanfTek + +usb:v15F4p0001* + ID_MODEL_FROM_DATABASE=HanfTek UMT-010 USB2.0 DVB-T (cold) + +usb:v15F4p0025* + ID_MODEL_FROM_DATABASE=HanfTek UMT-010 USB2.0 DVB-T (warm) + +usb:v15F4p0135* + ID_MODEL_FROM_DATABASE=Astrometa T2hybrid + +usb:v1604* + ID_VENDOR_FROM_DATABASE=Tascam + +usb:v1604p8000* + ID_MODEL_FROM_DATABASE=US-428 Audio/Midi Controller (without fw) + +usb:v1604p8001* + ID_MODEL_FROM_DATABASE=US-428 Audio/Midi Controller + +usb:v1604p8004* + ID_MODEL_FROM_DATABASE=US-224 Audio/Midi Controller (without fw) + +usb:v1604p8005* + ID_MODEL_FROM_DATABASE=US-224 Audio/Midi Controller + +usb:v1604p8006* + ID_MODEL_FROM_DATABASE=US-122 Audio/Midi Interface (without fw) + +usb:v1604p8007* + ID_MODEL_FROM_DATABASE=US-122 Audio/Midi Interface + +usb:v1605* + ID_VENDOR_FROM_DATABASE=ACCES I/O Products, Inc. + +usb:v1605p0001* + ID_MODEL_FROM_DATABASE=DIO-32 (No Firmware Yet) + +usb:v1606* + ID_VENDOR_FROM_DATABASE=Umax + +usb:v1606p0002* + ID_MODEL_FROM_DATABASE=Astra 1236U Scanner + +usb:v1606p0010* + ID_MODEL_FROM_DATABASE=Astra 1220U + +usb:v1606p0030* + ID_MODEL_FROM_DATABASE=Astra 1600U/2000U + +usb:v1606p0050* + ID_MODEL_FROM_DATABASE=Scanner + +usb:v1606p0060* + ID_MODEL_FROM_DATABASE=Astra 3400/3450 + +usb:v1606p0070* + ID_MODEL_FROM_DATABASE=Astra 4400/4450 + +usb:v1606p0130* + ID_MODEL_FROM_DATABASE=Astra 2100U + +usb:v1606p0160* + ID_MODEL_FROM_DATABASE=Astra 5400U + +usb:v1606p0170* + ID_MODEL_FROM_DATABASE=Uniscan D50 + +usb:v1606p0230* + ID_MODEL_FROM_DATABASE=Astra 2200/2200SU + +usb:v1606p0350* + ID_MODEL_FROM_DATABASE=Astra 4800/4850 Scanner + +usb:v1606p1030* + ID_MODEL_FROM_DATABASE=Astra 4000U + +usb:v1606p1220* + ID_MODEL_FROM_DATABASE=Genesys Logic Scanner Controller NT5.0 + +usb:v1606p2010* + ID_MODEL_FROM_DATABASE=AstraCam Digital Camera + +usb:v1606p2020* + ID_MODEL_FROM_DATABASE=AstraCam 1000 + +usb:v1606p2030* + ID_MODEL_FROM_DATABASE=AstraCam 1800 Digital Camera + +usb:v1608* + ID_VENDOR_FROM_DATABASE=Inside Out Networks [hex] + +usb:v1608p0001* + ID_MODEL_FROM_DATABASE=EdgePort/4 Serial Port + +usb:v1608p0002* + ID_MODEL_FROM_DATABASE=Edgeport/8 + +usb:v1608p0003* + ID_MODEL_FROM_DATABASE=Rapidport/4 + +usb:v1608p0004* + ID_MODEL_FROM_DATABASE=Edgeport/4 + +usb:v1608p0005* + ID_MODEL_FROM_DATABASE=Edgeport/2 + +usb:v1608p0006* + ID_MODEL_FROM_DATABASE=Edgeport/4i + +usb:v1608p0007* + ID_MODEL_FROM_DATABASE=Edgeport/2i + +usb:v1608p0008* + ID_MODEL_FROM_DATABASE=Edgeport/8 + +usb:v1608p000C* + ID_MODEL_FROM_DATABASE=Edgeport/421 + +usb:v1608p000D* + ID_MODEL_FROM_DATABASE=Edgeport/21 + +usb:v1608p000E* + ID_MODEL_FROM_DATABASE=Edgeport/4 + +usb:v1608p000F* + ID_MODEL_FROM_DATABASE=Edgeport/8 + +usb:v1608p0010* + ID_MODEL_FROM_DATABASE=Edgeport/2 + +usb:v1608p0011* + ID_MODEL_FROM_DATABASE=Edgeport/4 + +usb:v1608p0012* + ID_MODEL_FROM_DATABASE=Edgeport/416 + +usb:v1608p0014* + ID_MODEL_FROM_DATABASE=Edgeport/8i + +usb:v1608p0018* + ID_MODEL_FROM_DATABASE=Edgeport/412 + +usb:v1608p0019* + ID_MODEL_FROM_DATABASE=Edgeport/412 + +usb:v1608p001A* + ID_MODEL_FROM_DATABASE=Edgeport/2+2i + +usb:v1608p0101* + ID_MODEL_FROM_DATABASE=Edgeport/4 + +usb:v1608p0105* + ID_MODEL_FROM_DATABASE=Edgeport/2 + +usb:v1608p0106* + ID_MODEL_FROM_DATABASE=Edgeport/4i + +usb:v1608p0107* + ID_MODEL_FROM_DATABASE=Edgeport/2i + +usb:v1608p010C* + ID_MODEL_FROM_DATABASE=Edgeport/421 + +usb:v1608p010D* + ID_MODEL_FROM_DATABASE=Edgeport/21 + +usb:v1608p0110* + ID_MODEL_FROM_DATABASE=Edgeport/2 + +usb:v1608p0111* + ID_MODEL_FROM_DATABASE=Edgeport/4 + +usb:v1608p0112* + ID_MODEL_FROM_DATABASE=Edgeport/416 + +usb:v1608p0114* + ID_MODEL_FROM_DATABASE=Edgeport/8i + +usb:v1608p0201* + ID_MODEL_FROM_DATABASE=Edgeport/4 + +usb:v1608p0203* + ID_MODEL_FROM_DATABASE=Rapidport/4 + +usb:v1608p0204* + ID_MODEL_FROM_DATABASE=Edgeport/4 + +usb:v1608p0205* + ID_MODEL_FROM_DATABASE=Edgeport/2 + +usb:v1608p0206* + ID_MODEL_FROM_DATABASE=Edgeport/4i + +usb:v1608p0207* + ID_MODEL_FROM_DATABASE=Edgeport/2i + +usb:v1608p020C* + ID_MODEL_FROM_DATABASE=Edgeport/421 + +usb:v1608p020D* + ID_MODEL_FROM_DATABASE=Edgeport/21 + +usb:v1608p020E* + ID_MODEL_FROM_DATABASE=Edgeport/4 + +usb:v1608p020F* + ID_MODEL_FROM_DATABASE=Edgeport/8 + +usb:v1608p0210* + ID_MODEL_FROM_DATABASE=Edgeport/2 + +usb:v1608p0211* + ID_MODEL_FROM_DATABASE=Edgeport/4 + +usb:v1608p0212* + ID_MODEL_FROM_DATABASE=Edgeport/416 + +usb:v1608p0214* + ID_MODEL_FROM_DATABASE=Edgeport/8i + +usb:v1608p0215* + ID_MODEL_FROM_DATABASE=Edgeport/1 + +usb:v1608p0216* + ID_MODEL_FROM_DATABASE=EPOS/44 + +usb:v1608p0217* + ID_MODEL_FROM_DATABASE=Edgeport/42 + +usb:v1608p021A* + ID_MODEL_FROM_DATABASE=Edgeport/2+2i + +usb:v1608p021B* + ID_MODEL_FROM_DATABASE=Edgeport/2c + +usb:v1608p021C* + ID_MODEL_FROM_DATABASE=Edgeport/221c + +usb:v1608p021D* + ID_MODEL_FROM_DATABASE=Edgeport/22c + +usb:v1608p021E* + ID_MODEL_FROM_DATABASE=Edgeport/21c + +usb:v1608p021F* + ID_MODEL_FROM_DATABASE=Edgeport/62 + +usb:v1608p0240* + ID_MODEL_FROM_DATABASE=Edgeport/1 + +usb:v1608p0241* + ID_MODEL_FROM_DATABASE=Edgeport/1i + +usb:v1608p0242* + ID_MODEL_FROM_DATABASE=Edgeport/4s + +usb:v1608p0243* + ID_MODEL_FROM_DATABASE=Edgeport/8s + +usb:v1608p0244* + ID_MODEL_FROM_DATABASE=Edgeport/8 + +usb:v1608p0245* + ID_MODEL_FROM_DATABASE=Edgeport/22c + +usb:v1608p0301* + ID_MODEL_FROM_DATABASE=Watchport/P + +usb:v1608p0302* + ID_MODEL_FROM_DATABASE=Watchport/M + +usb:v1608p0303* + ID_MODEL_FROM_DATABASE=Watchport/W + +usb:v1608p0304* + ID_MODEL_FROM_DATABASE=Watchport/T + +usb:v1608p0305* + ID_MODEL_FROM_DATABASE=Watchport/H + +usb:v1608p0306* + ID_MODEL_FROM_DATABASE=Watchport/E + +usb:v1608p0307* + ID_MODEL_FROM_DATABASE=Watchport/L + +usb:v1608p0308* + ID_MODEL_FROM_DATABASE=Watchport/R + +usb:v1608p0309* + ID_MODEL_FROM_DATABASE=Watchport/A + +usb:v1608p030A* + ID_MODEL_FROM_DATABASE=Watchport/D + +usb:v1608p030B* + ID_MODEL_FROM_DATABASE=Watchport/D + +usb:v1608p030C* + ID_MODEL_FROM_DATABASE=Power Management Port + +usb:v1608p030E* + ID_MODEL_FROM_DATABASE=Power Management Port + +usb:v1608p030F* + ID_MODEL_FROM_DATABASE=Watchport/G + +usb:v1608p0310* + ID_MODEL_FROM_DATABASE=Watchport/Tc + +usb:v1608p0311* + ID_MODEL_FROM_DATABASE=Watchport/Hc + +usb:v1608p1403* + ID_MODEL_FROM_DATABASE=MultiTech Systems MT4X56 Modem + +usb:v1608p1A17* + ID_MODEL_FROM_DATABASE=Agilent Technologies (E6473) + +usb:v160A* + ID_VENDOR_FROM_DATABASE=VIA Technologies, Inc. + +usb:v160Ap3184* + ID_MODEL_FROM_DATABASE=VIA VNT-6656 [WiFi 802.11b/g USB Dongle] + +usb:v160E* + ID_VENDOR_FROM_DATABASE=INRO + +usb:v160Ep0001* + ID_MODEL_FROM_DATABASE=E2USBKey + +usb:v1614* + ID_VENDOR_FROM_DATABASE=Amoi Electronics + +usb:v1614p0404* + ID_MODEL_FROM_DATABASE=WMA9109 UMTS Phone + +usb:v1614p0600* + ID_MODEL_FROM_DATABASE=Vodafone VDA GPS / Toschiba Protege G710 + +usb:v1614p0804* + ID_MODEL_FROM_DATABASE=WP-S1 Phone + +usb:v1617* + ID_VENDOR_FROM_DATABASE=Sony Corp. + +usb:v1617p2002* + ID_MODEL_FROM_DATABASE=NVX-P1 Personal Navigation System + +usb:v1619* + ID_VENDOR_FROM_DATABASE=L & K Precision Technology Co., Ltd. + +usb:v161C* + ID_VENDOR_FROM_DATABASE=Digitech Systems + +usb:v161Cp0002* + ID_MODEL_FROM_DATABASE=DTC-02U [Digi Touch Controller] + +usb:v1621* + ID_VENDOR_FROM_DATABASE=Wionics Research + +usb:v1628* + ID_VENDOR_FROM_DATABASE=Stonestreet One, Inc. + +usb:v162A* + ID_VENDOR_FROM_DATABASE=Airgo Networks Inc. + +usb:v162F* + ID_VENDOR_FROM_DATABASE=WiQuest Communications, Inc. + +usb:v1630* + ID_VENDOR_FROM_DATABASE=2Wire, Inc. + +usb:v1630p0005* + ID_MODEL_FROM_DATABASE=802.11g Wireless Adapter [Intersil ISL3886] + +usb:v1630p0011* + ID_MODEL_FROM_DATABASE=PC Port 10 Mps Adapter + +usb:v1630pFF81* + ID_MODEL_FROM_DATABASE=802.11b Wireless Adapter [Lucent/Agere Hermes I] + +usb:v1631* + ID_VENDOR_FROM_DATABASE=Good Way Technology + +usb:v1631p6200* + ID_MODEL_FROM_DATABASE=GWUSB2E + +usb:v1631pC019* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v1645* + ID_VENDOR_FROM_DATABASE=Entrega [hex] + +usb:v1645p0001* + ID_MODEL_FROM_DATABASE=1S Serial Port + +usb:v1645p0002* + ID_MODEL_FROM_DATABASE=2S Serial Port + +usb:v1645p0003* + ID_MODEL_FROM_DATABASE=1S25 Serial Port + +usb:v1645p0004* + ID_MODEL_FROM_DATABASE=4S Serial Port + +usb:v1645p0005* + ID_MODEL_FROM_DATABASE=E45 Ethernet [klsi] + +usb:v1645p0006* + ID_MODEL_FROM_DATABASE=Parallel Port + +usb:v1645p0007* + ID_MODEL_FROM_DATABASE=U1-SC25 SCSI + +usb:v1645p0008* + ID_MODEL_FROM_DATABASE=Ethernet + +usb:v1645p0016* + ID_MODEL_FROM_DATABASE=Bi-directional to Parallel Printer Converter + +usb:v1645p0080* + ID_MODEL_FROM_DATABASE=1 port to Serial Converter + +usb:v1645p0081* + ID_MODEL_FROM_DATABASE=1 port to Serial Converter + +usb:v1645p0093* + ID_MODEL_FROM_DATABASE=1S9 Serial Port + +usb:v1645p8000* + ID_MODEL_FROM_DATABASE=EZ-USB + +usb:v1645p8001* + ID_MODEL_FROM_DATABASE=1 port to Serial + +usb:v1645p8002* + ID_MODEL_FROM_DATABASE=2x Serial Port + +usb:v1645p8003* + ID_MODEL_FROM_DATABASE=1 port to Serial + +usb:v1645p8004* + ID_MODEL_FROM_DATABASE=2U4S serial/usb hub + +usb:v1645p8005* + ID_MODEL_FROM_DATABASE=Ethernet + +usb:v1645p8080* + ID_MODEL_FROM_DATABASE=1 port to Serial + +usb:v1645p8081* + ID_MODEL_FROM_DATABASE=1 port to Serial + +usb:v1645p8093* + ID_MODEL_FROM_DATABASE=PortGear Serial Port + +usb:v1649* + ID_VENDOR_FROM_DATABASE=SofTec Microsystems + +usb:v1649p0102* + ID_MODEL_FROM_DATABASE=uDART In-Circuit Debugger + +usb:v1649p0200* + ID_MODEL_FROM_DATABASE=SpYder USBSPYDER08 + +usb:v164A* + ID_VENDOR_FROM_DATABASE=ChipX + +usb:v164C* + ID_VENDOR_FROM_DATABASE=Matrix Vision GmbH + +usb:v164Cp0101* + ID_MODEL_FROM_DATABASE=mvBlueFOX camera (no firmware) + +usb:v164Cp0103* + ID_MODEL_FROM_DATABASE=mvBlueFOX camera + +usb:v164Cp0201* + ID_MODEL_FROM_DATABASE=mvBlueLYNX-X intelligent camera (bootloader) + +usb:v164Cp0203* + ID_MODEL_FROM_DATABASE=mvBlueLYNX-X intelligent camera + +usb:v1657* + ID_VENDOR_FROM_DATABASE=Struck Innovative Systeme GmbH + +usb:v1657p3150* + ID_MODEL_FROM_DATABASE=SIS3150 USB2.0 to VME interface + +usb:v165B* + ID_VENDOR_FROM_DATABASE=Frontier Design Group + +usb:v165Bp8101* + ID_MODEL_FROM_DATABASE=Tranzport Control Surface + +usb:v165BpFAD1* + ID_MODEL_FROM_DATABASE=Alphatrack Control Surface + +usb:v165C* + ID_VENDOR_FROM_DATABASE=Kondo Kagaku + +usb:v165Cp0002* + ID_MODEL_FROM_DATABASE=Serial Adapter + +usb:v165Cp0006* + ID_MODEL_FROM_DATABASE=FT232 [ICS adapter HS] + +usb:v165Cp0008* + ID_MODEL_FROM_DATABASE=FT232 [Dual adapter HS] + +usb:v1660* + ID_VENDOR_FROM_DATABASE=Creatix Polymedia GmbH + +usb:v1667* + ID_VENDOR_FROM_DATABASE=GIGA-TMS INC. + +usb:v1667p0005* + ID_MODEL_FROM_DATABASE=PCR330A RFID Reader (125 kHz, keyboard emulation) + +usb:v1668* + ID_VENDOR_FROM_DATABASE=Actiontec Electronics, Inc. [hex] + +usb:v1668p0009* + ID_MODEL_FROM_DATABASE=Gateway + +usb:v1668p0333* + ID_MODEL_FROM_DATABASE=Modem + +usb:v1668p0358* + ID_MODEL_FROM_DATABASE=InternetPhoneWizard + +usb:v1668p0405* + ID_MODEL_FROM_DATABASE=Gateway + +usb:v1668p0408* + ID_MODEL_FROM_DATABASE=Prism2.5 802.11b Adapter + +usb:v1668p0413* + ID_MODEL_FROM_DATABASE=Gateway + +usb:v1668p0421* + ID_MODEL_FROM_DATABASE=Prism2.5 802.11b Adapter + +usb:v1668p0441* + ID_MODEL_FROM_DATABASE=IBM Integrated Bluetooth II + +usb:v1668p0500* + ID_MODEL_FROM_DATABASE=BTM200B BlueTooth Adapter + +usb:v1668p1050* + ID_MODEL_FROM_DATABASE=802UIG-1 802.11g Wireless Mini Adapter [Intersil ISL3887] + +usb:v1668p1200* + ID_MODEL_FROM_DATABASE=802AIN Wireless N Network Adapter [Atheros AR9170+AR9101] + +usb:v1668p1441* + ID_MODEL_FROM_DATABASE=IBM Integrated Bluetooth II + +usb:v1668p2441* + ID_MODEL_FROM_DATABASE=BMDC-2 IBM Bluetooth III w.56k + +usb:v1668p3441* + ID_MODEL_FROM_DATABASE=IBM Integrated Bluetooth III + +usb:v1668p6010* + ID_MODEL_FROM_DATABASE=Gateway + +usb:v1668p6097* + ID_MODEL_FROM_DATABASE=802.11b Wireless Adapter + +usb:v1668p6106* + ID_MODEL_FROM_DATABASE=802UI3(B) 802.11b Wireless Adapter [Intersil PRISM 3] + +usb:v1668p7605* + ID_MODEL_FROM_DATABASE=UAT1 Wireless Ethernet Adapter + +usb:v1669* + ID_VENDOR_FROM_DATABASE=PiKRON Ltd. [hex] + +usb:v1669p1001* + ID_MODEL_FROM_DATABASE=uLan2USB Converter - PS1 protocol + +usb:v166A* + ID_VENDOR_FROM_DATABASE=Clipsal + +usb:v166Ap0101* + ID_MODEL_FROM_DATABASE=C-Bus Multi-room Audio Matrix Switcher + +usb:v166Ap0201* + ID_MODEL_FROM_DATABASE=C-Bus Pascal Automation Controller + +usb:v166Ap0301* + ID_MODEL_FROM_DATABASE=C-Bus Wireless PC Interface + +usb:v166Ap0303* + ID_MODEL_FROM_DATABASE=C-Bus interface + +usb:v166Ap0304* + ID_MODEL_FROM_DATABASE=C-Bus Black and White Touchscreen + +usb:v166Ap0305* + ID_MODEL_FROM_DATABASE=C-Bus Spectrum Colour Touchscreen + +usb:v166Ap0401* + ID_MODEL_FROM_DATABASE=C-Bus Architectural Dimmer + +usb:v1677* + ID_VENDOR_FROM_DATABASE=China Huada Integrated Circuit Design (Group) Co., Ltd. (CIDC Group) + +usb:v1677p0103* + ID_MODEL_FROM_DATABASE=Token + +usb:v1679* + ID_VENDOR_FROM_DATABASE=Total Phase + +usb:v1679p2001* + ID_MODEL_FROM_DATABASE=Beagle Protocol Analyzer + +usb:v1679p2002* + ID_MODEL_FROM_DATABASE=Cheetah SPI Host Adapter + +usb:v1680* + ID_VENDOR_FROM_DATABASE=Golden Bridge Electech Inc. + +usb:v1680pA332* + ID_MODEL_FROM_DATABASE=DVB-T Dongle [RTL2832U] + +usb:v1681* + ID_VENDOR_FROM_DATABASE=Prevo Technologies, Inc. + +usb:v1681p0001* + ID_MODEL_FROM_DATABASE=Tuner's Dashboard + +usb:v1681p0002* + ID_MODEL_FROM_DATABASE=DocuBrain(R) Tubachron + +usb:v1681p0003* + ID_MODEL_FROM_DATABASE=DocuBrain(R) I2C + +usb:v1681p0004* + ID_MODEL_FROM_DATABASE=DocuBrain(R) WWVB Receiver + +usb:v1681p0005* + ID_MODEL_FROM_DATABASE=DocuBrain(R) WWVB Transmitter + +usb:v1682* + ID_VENDOR_FROM_DATABASE=Maxwise Production Enterprise Ltd. + +usb:v1684* + ID_VENDOR_FROM_DATABASE=Godspeed Computer Corp. + +usb:v1685* + ID_VENDOR_FROM_DATABASE=Delock + +usb:v1685p0200* + ID_MODEL_FROM_DATABASE=Infrared adapter + +usb:v1686* + ID_VENDOR_FROM_DATABASE=ZOOM Corporation + +usb:v1686p0045* + ID_MODEL_FROM_DATABASE=H4 Digital Recorder + +usb:v1687* + ID_VENDOR_FROM_DATABASE=Kingmax Digital Inc. + +usb:v1687p5289* + ID_MODEL_FROM_DATABASE=FlashDisk + +usb:v1687p6211* + ID_MODEL_FROM_DATABASE=FlashDisk + +usb:v1687p6213* + ID_MODEL_FROM_DATABASE=FlashDisk + +usb:v1688* + ID_VENDOR_FROM_DATABASE=Saab AB + +usb:v1689* + ID_VENDOR_FROM_DATABASE=Razer USA, Ltd + +usb:v1689pFD00* + ID_MODEL_FROM_DATABASE=Onza Tournament Edition controller + +usb:v168C* + ID_VENDOR_FROM_DATABASE=Atheros Communications + +usb:v168Cp0001* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v168Cp0002* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v1690* + ID_VENDOR_FROM_DATABASE=Askey Computer Corp. [hex] + +usb:v1690p0001* + ID_MODEL_FROM_DATABASE=Arcaze Gamepad + +usb:v1690p0101* + ID_MODEL_FROM_DATABASE=Creative Modem Blaster DE5670 + +usb:v1690p0102* + ID_MODEL_FROM_DATABASE=V1456 VQE-R2 Modem [conexant] + +usb:v1690p0103* + ID_MODEL_FROM_DATABASE=1456 VQE-R3 Modem [conexant] + +usb:v1690p0104* + ID_MODEL_FROM_DATABASE=HCF V90 Data Fax RTAD Modem + +usb:v1690p0107* + ID_MODEL_FROM_DATABASE=HCF V.90 Data,Fax,RTAD Modem + +usb:v1690p0109* + ID_MODEL_FROM_DATABASE=MagicXpress V.90 Pocket Modem [conexant] + +usb:v1690p0203* + ID_MODEL_FROM_DATABASE=Voyager ADSL Modem Loader + +usb:v1690p0204* + ID_MODEL_FROM_DATABASE=Voyager ADSL Modem + +usb:v1690p0205* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v1690p0206* + ID_MODEL_FROM_DATABASE=GlobeSpan ADSL WAN Modem + +usb:v1690p0208* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v1690p0209* + ID_MODEL_FROM_DATABASE=Voyager 100 ADSL Modem + +usb:v1690p0211* + ID_MODEL_FROM_DATABASE=Globespan Virata ADSL LAN Modem + +usb:v1690p0212* + ID_MODEL_FROM_DATABASE=DSL Modem + +usb:v1690p0213* + ID_MODEL_FROM_DATABASE=HM121d DSL Modem + +usb:v1690p0214* + ID_MODEL_FROM_DATABASE=HM121d DSL Modem + +usb:v1690p0215* + ID_MODEL_FROM_DATABASE=Voyager 105 ADSL Modem + +usb:v1690p0701* + ID_MODEL_FROM_DATABASE=WLAN + +usb:v1690p0710* + ID_MODEL_FROM_DATABASE=SMCWUSBT-G + +usb:v1690p0711* + ID_MODEL_FROM_DATABASE=SMCWUSBT-G (no firmware) + +usb:v1690p0712* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v1690p0713* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v1690p0715* + ID_MODEL_FROM_DATABASE=Name: Voyager 1055 Laptop 802.11g Adapter [Broadcom 4320] + +usb:v1690p0722* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v1690p0726* + ID_MODEL_FROM_DATABASE=Wi-Fi Wireless LAN Adapter + +usb:v1690p0740* + ID_MODEL_FROM_DATABASE=802.11n Wireless LAN Card + +usb:v1690p0901* + ID_MODEL_FROM_DATABASE=Voyager 205 ADSL Router + +usb:v1690p2000* + ID_MODEL_FROM_DATABASE=naturaSign Pad Standard + +usb:v1690p2001* + ID_MODEL_FROM_DATABASE=naturaSign Pad Standard + +usb:v1690pFE12* + ID_MODEL_FROM_DATABASE=Bootloader + +usb:v1696* + ID_VENDOR_FROM_DATABASE=Hitachi Video and Information System, Inc. + +usb:v1697* + ID_VENDOR_FROM_DATABASE=VTec Test, Inc. + +usb:v16A5* + ID_VENDOR_FROM_DATABASE=Shenzhen Zhengerya Cable Co., Ltd. + +usb:v16A6* + ID_VENDOR_FROM_DATABASE=Unigraf + +usb:v16A6p3000* + ID_MODEL_FROM_DATABASE=VTG-3xxx Video Test Generator family + +usb:v16A6p4000* + ID_MODEL_FROM_DATABASE=VTG-4xxx Video Test Generator family + +usb:v16A6p5000* + ID_MODEL_FROM_DATABASE=VTG-5xxx Video Test Generator family + +usb:v16A6p5001* + ID_MODEL_FROM_DATABASE=VTG-5xxx Special (update) mode of VTG-5xxx family + +usb:v16AB* + ID_VENDOR_FROM_DATABASE=Global Sun Technology + +usb:v16ABp7801* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v16ABp7802* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v16ABp7811* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:v16ABp7812* + ID_MODEL_FROM_DATABASE=AR5523 (no firmware) + +usb:v16AC* + ID_VENDOR_FROM_DATABASE=Dongguan ChingLung Wire & Cable Co., Ltd. + +usb:v16B4* + ID_VENDOR_FROM_DATABASE=iStation + +usb:v16B4p0801* + ID_MODEL_FROM_DATABASE=U43 + +usb:v16B5* + ID_VENDOR_FROM_DATABASE=Persentec, Inc. + +usb:v16B5p0002* + ID_MODEL_FROM_DATABASE=Otto driving companion + +usb:v16C0* + ID_VENDOR_FROM_DATABASE=Van Ooijen Technische Informatica + +usb:v16C0p03E8* + ID_MODEL_FROM_DATABASE=free for internal lab use 1000 + +usb:v16C0p03E9* + ID_MODEL_FROM_DATABASE=free for internal lab use 1001 + +usb:v16C0p03EA* + ID_MODEL_FROM_DATABASE=free for internal lab use 1002 + +usb:v16C0p03EB* + ID_MODEL_FROM_DATABASE=free for internal lab use 1003 + +usb:v16C0p03EC* + ID_MODEL_FROM_DATABASE=free for internal lab use 1004 + +usb:v16C0p03ED* + ID_MODEL_FROM_DATABASE=free for internal lab use 1005 + +usb:v16C0p03EE* + ID_MODEL_FROM_DATABASE=free for internal lab use 1006 + +usb:v16C0p03EF* + ID_MODEL_FROM_DATABASE=free for internal lab use 1007 + +usb:v16C0p03F0* + ID_MODEL_FROM_DATABASE=free for internal lab use 1008 + +usb:v16C0p03F1* + ID_MODEL_FROM_DATABASE=free for internal lab use 1009 + +usb:v16C0p0477* + ID_MODEL_FROM_DATABASE=Teensy Rebootor + +usb:v16C0p0478* + ID_MODEL_FROM_DATABASE=Teensy Halfkay Bootloader + +usb:v16C0p0479* + ID_MODEL_FROM_DATABASE=Teensy Debug + +usb:v16C0p047A* + ID_MODEL_FROM_DATABASE=Teensy Serial + +usb:v16C0p047B* + ID_MODEL_FROM_DATABASE=Teensy Serial+Debug + +usb:v16C0p047C* + ID_MODEL_FROM_DATABASE=Teensy Keyboard + +usb:v16C0p047D* + ID_MODEL_FROM_DATABASE=Teensy Keyboard+Debug + +usb:v16C0p047E* + ID_MODEL_FROM_DATABASE=Teensy Mouse + +usb:v16C0p047F* + ID_MODEL_FROM_DATABASE=Teensy Mouse+Debug + +usb:v16C0p0480* + ID_MODEL_FROM_DATABASE=Teensy RawHID + +usb:v16C0p0481* + ID_MODEL_FROM_DATABASE=Teensy RawHID+Debug + +usb:v16C0p0482* + ID_MODEL_FROM_DATABASE=Teensyduino Keyboard+Mouse+Joystick + +usb:v16C0p0483* + ID_MODEL_FROM_DATABASE=Teensyduino Serial + +usb:v16C0p0484* + ID_MODEL_FROM_DATABASE=Teensyduino Disk + +usb:v16C0p0485* + ID_MODEL_FROM_DATABASE=Teensyduino MIDI + +usb:v16C0p0486* + ID_MODEL_FROM_DATABASE=Teensyduino RawHID + +usb:v16C0p0487* + ID_MODEL_FROM_DATABASE=Teensyduino Serial+Keyboard+Mouse+Joystick + +usb:v16C0p0488* + ID_MODEL_FROM_DATABASE=Teensyduino Flight Sim Controls + +usb:v16C0p05DC* + ID_MODEL_FROM_DATABASE=shared ID for use with libusb + +usb:v16C0p05DD* + ID_MODEL_FROM_DATABASE=BlackcatUSB2 + +usb:v16C0p05DF* + ID_MODEL_FROM_DATABASE=HID device except mice, keyboards, and joysticks + +usb:v16C0p05E1* + ID_MODEL_FROM_DATABASE=Free shared USB VID/PID pair for CDC devices + +usb:v16C0p05E4* + ID_MODEL_FROM_DATABASE=Free shared USB VID/PID pair for MIDI devices + +usb:v16C0p06B4* + ID_MODEL_FROM_DATABASE=USB2LPT with 2 interfaces + +usb:v16C0p06B5* + ID_MODEL_FROM_DATABASE=USB2LPT with 3 interfaces (native, HID, printer) + +usb:v16C0p074E* + ID_MODEL_FROM_DATABASE=DSP-Weuffen USB-HPI-Programmer + +usb:v16C0p074F* + ID_MODEL_FROM_DATABASE=DSP-Weuffen USB2-HPI-Programmer + +usb:v16C0p0762* + ID_MODEL_FROM_DATABASE=Osmocom SIMtrace + +usb:v16C0p076B* + ID_MODEL_FROM_DATABASE=OpenPCD 13.56MHz RFID Reader + +usb:v16C0p076C* + ID_MODEL_FROM_DATABASE=OpenPICC 13.56MHz RFID Simulator (native) + +usb:v16C0p08AC* + ID_MODEL_FROM_DATABASE=OpenBeacon USB stick + +usb:v16C0p08CA* + ID_MODEL_FROM_DATABASE=Alpermann+Velte Universal Display + +usb:v16C0p08CB* + ID_MODEL_FROM_DATABASE=Alpermann+Velte Studio Clock + +usb:v16C0p08CC* + ID_MODEL_FROM_DATABASE=Alpermann+Velte SAM7S MT Boot Loader + +usb:v16C0p08CD* + ID_MODEL_FROM_DATABASE=Alpermann+Velte SAM7X MT Boot Loader + +usb:v16C0p0A32* + ID_MODEL_FROM_DATABASE=jbmedia Light-Manager Pro + +usb:v16C0p27D8* + ID_MODEL_FROM_DATABASE=libusb-bound devices + +usb:v16C0p27D9* + ID_MODEL_FROM_DATABASE=HID device except mice, keyboards, and joysticks + +usb:v16C0p27DA* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v16C0p27DB* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v16C0p27DC* + ID_MODEL_FROM_DATABASE=Joystick + +usb:v16C0p27DD* + ID_MODEL_FROM_DATABASE=CDC-ACM class devices (modems) + +usb:v16C0p27DE* + ID_MODEL_FROM_DATABASE=MIDI class devices + +usb:v16C0p294A* + ID_MODEL_FROM_DATABASE=Eye Movement Recorder [Visagraph] + +usb:v16C0p294B* + ID_MODEL_FROM_DATABASE=Eye Movement Recorder [ReadAlyzer] + +usb:v16CA* + ID_VENDOR_FROM_DATABASE=Wireless Cables, Inc. + +usb:v16CAp1502* + ID_MODEL_FROM_DATABASE=Bluetooth Dongle + +usb:v16CC* + ID_VENDOR_FROM_DATABASE=silex technology, Inc. + +usb:v16D0* + ID_VENDOR_FROM_DATABASE=MCS + +usb:v16D0p0436* + ID_MODEL_FROM_DATABASE=Xylanta Ltd, XSP Device + +usb:v16D0p0498* + ID_MODEL_FROM_DATABASE=Braintechnology USB-LPS + +usb:v16D0p0504* + ID_MODEL_FROM_DATABASE=RETRO Innovations ZoomFloppy + +usb:v16D0p054B* + ID_MODEL_FROM_DATABASE=GrauTec ReelBox OLED Display (external) + +usb:v16D0p05BE* + ID_MODEL_FROM_DATABASE=EasyLogic Board + +usb:v16D0p06CC* + ID_MODEL_FROM_DATABASE=Trinamic TMCM-3110 + +usb:v16D0p06F9* + ID_MODEL_FROM_DATABASE=Gabotronics Xminilab + +usb:v16D0p0753* + ID_MODEL_FROM_DATABASE=Digistump DigiSpark + +usb:v16D0p075C* + ID_MODEL_FROM_DATABASE=AB-1.x UAC1 [Audio Widget] + +usb:v16D0p075D* + ID_MODEL_FROM_DATABASE=AB-1.x UAC2 [Audio Widget] + +usb:v16D0p080A* + ID_MODEL_FROM_DATABASE=S2E1 Interface + +usb:v16D0p0870* + ID_MODEL_FROM_DATABASE=Kaufmann Automotive GmbH, RKS+CAN Interface + +usb:v16D0p0B03* + ID_MODEL_FROM_DATABASE=AIS Receiver [dAISy] + +usb:v16D0p0BD4* + ID_MODEL_FROM_DATABASE=codesrc SCSI2SD + +usb:v16D1* + ID_VENDOR_FROM_DATABASE=Suprema Inc. + +usb:v16D1p0401* + ID_MODEL_FROM_DATABASE=SUP-SFR400(A) BioMini Fingerprint Reader + +usb:v16D3* + ID_VENDOR_FROM_DATABASE=Frontline Test Equipment, Inc. + +usb:v16D5* + ID_VENDOR_FROM_DATABASE=AnyDATA Corporation + +usb:v16D5p6202* + ID_MODEL_FROM_DATABASE=CDMA/UMTS/GPRS modem + +usb:v16D5p6501* + ID_MODEL_FROM_DATABASE=CDMA 2000 1xRTT/EV-DO Modem + +usb:v16D5p6502* + ID_MODEL_FROM_DATABASE=CDMA/UMTS/GPRS modem + +usb:v16D5p6603* + ID_MODEL_FROM_DATABASE=ADU-890WH modem + +usb:v16D6* + ID_VENDOR_FROM_DATABASE=JABLOCOM s.r.o. + +usb:v16D6p8000* + ID_MODEL_FROM_DATABASE=GDP-04 desktop phone + +usb:v16D6p8001* + ID_MODEL_FROM_DATABASE=EYE-02 + +usb:v16D6p8003* + ID_MODEL_FROM_DATABASE=GDP-04 modem + +usb:v16D6p8004* + ID_MODEL_FROM_DATABASE=Bootloader + +usb:v16D6p8005* + ID_MODEL_FROM_DATABASE=GDP-04i + +usb:v16D6p8007* + ID_MODEL_FROM_DATABASE=BTP-06 modem + +usb:v16D8* + ID_VENDOR_FROM_DATABASE=CMOTECH Co., Ltd. + +usb:v16D8p5141* + ID_MODEL_FROM_DATABASE=CMOTECH CDMA Technologies modem + +usb:v16D8p5533* + ID_MODEL_FROM_DATABASE=CCU-550 CDMA EV-DO modem + +usb:v16D8p5543* + ID_MODEL_FROM_DATABASE=CDMA 2000 1xRTT/1xEVDO modem + +usb:v16D8p6280* + ID_MODEL_FROM_DATABASE=CMOTECH CDMA Technologies modem + +usb:v16D8p6803* + ID_MODEL_FROM_DATABASE=CNU-680 CDMA EV-DO modem + +usb:v16D8p8001* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem (QDL mode) + +usb:v16D8p8002* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v16DC* + ID_VENDOR_FROM_DATABASE=Wiener, Plein & Baus + +usb:v16DCp0001* + ID_MODEL_FROM_DATABASE=CC + +usb:v16DCp000B* + ID_MODEL_FROM_DATABASE=VM + +usb:v16DCp0010* + ID_MODEL_FROM_DATABASE=PL512 Power Supply System + +usb:v16DCp0011* + ID_MODEL_FROM_DATABASE=MARATON Power Supply System + +usb:v16DCp0012* + ID_MODEL_FROM_DATABASE=MPOD Multi Channel Power Supply System + +usb:v16DCp0015* + ID_MODEL_FROM_DATABASE=CML Control, Measurement and Data Logging System + +usb:v16DE* + ID_VENDOR_FROM_DATABASE=Telemecanique + +usb:v16DF* + ID_VENDOR_FROM_DATABASE=King Billion Electronics Co., Ltd. + +usb:v16F0* + ID_VENDOR_FROM_DATABASE=GN ReSound A/S + +usb:v16F0p0001* + ID_MODEL_FROM_DATABASE=Speedlink Programming Interface + +usb:v16F0p0003* + ID_MODEL_FROM_DATABASE=Airlink Wireless Programming Interface + +usb:v16F5* + ID_VENDOR_FROM_DATABASE=Futurelogic Inc. + +usb:v1706* + ID_VENDOR_FROM_DATABASE=BlueView Technologies, Inc. + +usb:v1707* + ID_VENDOR_FROM_DATABASE=ARTIMI + +usb:v170B* + ID_VENDOR_FROM_DATABASE=Swissonic + +usb:v170Bp0011* + ID_MODEL_FROM_DATABASE=MIDI-USB 1x1 + +usb:v170D* + ID_VENDOR_FROM_DATABASE=Avnera + +usb:v1711* + ID_VENDOR_FROM_DATABASE=Leica Microsystems + +usb:v1711p0101* + ID_MODEL_FROM_DATABASE=DFC-365FX camera + +usb:v1711p3020* + ID_MODEL_FROM_DATABASE=IC80 HD Camera + +usb:v1724* + ID_VENDOR_FROM_DATABASE=Meyer Instruments (MIS) + +usb:v1724p0115* + ID_MODEL_FROM_DATABASE=PAXcam5 + +usb:v1725* + ID_VENDOR_FROM_DATABASE=Vitesse Semiconductor + +usb:v1726* + ID_VENDOR_FROM_DATABASE=Axesstel, Inc. + +usb:v1726p1000* + ID_MODEL_FROM_DATABASE=wireless modem + +usb:v1726p2000* + ID_MODEL_FROM_DATABASE=wireless modem + +usb:v1726p3000* + ID_MODEL_FROM_DATABASE=wireless modem + +usb:v172F* + ID_VENDOR_FROM_DATABASE=Waltop International Corp. + +usb:v172Fp0022* + ID_MODEL_FROM_DATABASE=Tablet + +usb:v172Fp0024* + ID_MODEL_FROM_DATABASE=Tablet + +usb:v172Fp0025* + ID_MODEL_FROM_DATABASE=Tablet + +usb:v172Fp0026* + ID_MODEL_FROM_DATABASE=Tablet + +usb:v172Fp0031* + ID_MODEL_FROM_DATABASE=Slim Tablet 12.1" + +usb:v172Fp0032* + ID_MODEL_FROM_DATABASE=Slim Tablet 5.8" + +usb:v172Fp0034* + ID_MODEL_FROM_DATABASE=Slim Tablet 12.1" + +usb:v172Fp0038* + ID_MODEL_FROM_DATABASE=Genius G-Pen F509 + +usb:v172Fp0500* + ID_MODEL_FROM_DATABASE=Media Tablet 14.1" + +usb:v172Fp0501* + ID_MODEL_FROM_DATABASE=Media Tablet 10.6" + +usb:v172Fp0502* + ID_MODEL_FROM_DATABASE=Sirius Battery Free Tablet + +usb:v1733* + ID_VENDOR_FROM_DATABASE=Cellink Technology Co., Ltd + +usb:v1733p0101* + ID_MODEL_FROM_DATABASE=RF Wireless Optical Mouse OP-701 + +usb:v1736* + ID_VENDOR_FROM_DATABASE=CANON IMAGING SYSTEM TECHNOLOGIES INC. + +usb:v1737* + ID_VENDOR_FROM_DATABASE=Linksys + +usb:v1737p0039* + ID_MODEL_FROM_DATABASE=USB1000 Gigabit Notebook Adapter + +usb:v1737p0070* + ID_MODEL_FROM_DATABASE=WUSB100 v1 RangePlus Wireless Network Adapter [Ralink RT2870] + +usb:v1737p0071* + ID_MODEL_FROM_DATABASE=WUSB600N v1 Dual-Band Wireless-N Network Adapter [Ralink RT2870] + +usb:v1737p0073* + ID_MODEL_FROM_DATABASE=WUSB54GC v2 802.11g Adapter [Realtek RTL8187B] + +usb:v1737p0075* + ID_MODEL_FROM_DATABASE=WUSB54GSC v2 802.11g Adapter [Broadcom 4326U] + +usb:v1737p0077* + ID_MODEL_FROM_DATABASE=WUSB54GC v3 802.11g Adapter [Ralink RT2070L] + +usb:v1737p0078* + ID_MODEL_FROM_DATABASE=WUSB100 v2 RangePlus Wireless Network Adapter [Ralink RT3070] + +usb:v1737p0079* + ID_MODEL_FROM_DATABASE=WUSB600N v2 Dual-Band Wireless-N Network Adapter [Ralink RT3572] + +usb:v173A* + ID_VENDOR_FROM_DATABASE=Roche + +usb:v173Ap2198* + ID_MODEL_FROM_DATABASE=Accu-Chek Mobile + +usb:v173Ap21CA* + ID_MODEL_FROM_DATABASE=ACCU-CHEK Mobile Model U1 + +usb:v173D* + ID_VENDOR_FROM_DATABASE=QSENN + +usb:v173Dp0002* + ID_MODEL_FROM_DATABASE=GP-K7000 keyboard + +usb:v1740* + ID_VENDOR_FROM_DATABASE=Senao + +usb:v1740p0100* + ID_MODEL_FROM_DATABASE=EUB1200AC AC1200 DB Wireless Adapter [Realtek RTL8812AU] + +usb:v1740p0600* + ID_MODEL_FROM_DATABASE=EUB600v1 802.11abgn Wireless Adapter [Ralink RT3572] + +usb:v1740p0605* + ID_MODEL_FROM_DATABASE=LevelOne WUA-0605 N_Max Wireless USB Adapter + +usb:v1740p0615* + ID_MODEL_FROM_DATABASE=LevelOne WUA-0615 N_Max Wireless USB Adapter + +usb:v1740p1000* + ID_MODEL_FROM_DATABASE=NUB-350 802.11g Wireless Adapter [Intersil ISL3887] + +usb:v1740p2000* + ID_MODEL_FROM_DATABASE=NUB-8301 802.11bg + +usb:v1740p3701* + ID_MODEL_FROM_DATABASE=EUB-3701 EXT 802.11g Wireless Adapter [Ralink RT2571W] + +usb:v1740p9603* + ID_MODEL_FROM_DATABASE=RTL8188S WLAN Adapter + +usb:v1740p9701* + ID_MODEL_FROM_DATABASE=EnGenius 802.11n Wireless USB Adapter + +usb:v1740p9702* + ID_MODEL_FROM_DATABASE=EnGenius 802.11n Wireless USB Adapter + +usb:v1740p9703* + ID_MODEL_FROM_DATABASE=EnGenius 802.11n Wireless USB Adapter + +usb:v1740p9705* + ID_MODEL_FROM_DATABASE=EnGenius 802.11n Wireless USB Adapter + +usb:v1740p9706* + ID_MODEL_FROM_DATABASE=EUB9706 802.11n Wireless Adapter [Ralink RT3072] + +usb:v1740p9801* + ID_MODEL_FROM_DATABASE=EUB9801 802.11abgn Wireless Adapter [Ralink RT3572] + +usb:v1743* + ID_VENDOR_FROM_DATABASE=General Atomics + +usb:v1748* + ID_VENDOR_FROM_DATABASE=MQP Electronics + +usb:v1748p0101* + ID_MODEL_FROM_DATABASE=Packet-Master USB12 + +usb:v174C* + ID_VENDOR_FROM_DATABASE=ASMedia Technology Inc. + +usb:v174Cp07D1* + ID_MODEL_FROM_DATABASE=Transcend ESD400 Portable SSD (USB 3.0) + +usb:v174Cp1153* + ID_MODEL_FROM_DATABASE=ASM1153 SATA 3Gb/s bridge + +usb:v174Cp2074* + ID_MODEL_FROM_DATABASE=ASM1074 High-Speed hub + +usb:v174Cp3074* + ID_MODEL_FROM_DATABASE=ASM1074 SuperSpeed hub + +usb:v174Cp5106* + ID_MODEL_FROM_DATABASE=ASM1051 SATA 3Gb/s bridge + +usb:v174Cp5136* + ID_MODEL_FROM_DATABASE=ASM1053 SATA 3Gb/s bridge + +usb:v174Cp51D6* + ID_MODEL_FROM_DATABASE=ASM1051W SATA 3Gb/s bridge + +usb:v174Cp55AA* + ID_MODEL_FROM_DATABASE=Name: ASM1051E SATA 6Gb/s bridge, ASM1053E SATA 6Gb/s bridge, ASM1153 SATA 3Gb/s bridge, ASM1153E SATA 6Gb/s bridge + +usb:v174F* + ID_VENDOR_FROM_DATABASE=Syntek + +usb:v174Fp1105* + ID_MODEL_FROM_DATABASE=SM-MS/Pro-MMC-XD Card Reader + +usb:v174Fp110B* + ID_MODEL_FROM_DATABASE=HP Webcam + +usb:v174Fp1403* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v174Fp1404* + ID_MODEL_FROM_DATABASE=USB Camera device, 1.3 MPixel Web Cam + +usb:v174Fp5212* + ID_MODEL_FROM_DATABASE=USB 2.0 UVC PC Camera + +usb:v174Fp5A11* + ID_MODEL_FROM_DATABASE=PC Camera + +usb:v174Fp5A31* + ID_MODEL_FROM_DATABASE=Sonix USB 2.0 Camera + +usb:v174Fp5A35* + ID_MODEL_FROM_DATABASE=Sonix 1.3MPixel USB 2.0 Camera + +usb:v174Fp6A31* + ID_MODEL_FROM_DATABASE=Web Cam - Asus A8J, F3S, F5R, VX2S, V1S + +usb:v174Fp6A33* + ID_MODEL_FROM_DATABASE=Web Cam - Asus F3SA, F9J, F9S + +usb:v174Fp6A51* + ID_MODEL_FROM_DATABASE=2.0MPixel Web Cam - Asus Z96J, Z96S, S96S + +usb:v174Fp6A54* + ID_MODEL_FROM_DATABASE=Web Cam + +usb:v174Fp6D51* + ID_MODEL_FROM_DATABASE=2.0Mpixel Web Cam - Eurocom D900C + +usb:v174Fp8A12* + ID_MODEL_FROM_DATABASE=Syntek 0.3MPixel USB 2.0 UVC PC Camera + +usb:v174Fp8A33* + ID_MODEL_FROM_DATABASE=Syntek USB 2.0 UVC PC Camera + +usb:v174FpA311* + ID_MODEL_FROM_DATABASE=1.3MPixel Web Cam - Asus A3A, A6J, A6K, A6M, A6R, A6T, A6V, A7T, A7sv, A7U + +usb:v174FpA312* + ID_MODEL_FROM_DATABASE=1.3MPixel Web Cam + +usb:v174FpA821* + ID_MODEL_FROM_DATABASE=Web Cam - Packard Bell BU45, PB Easynote MX66-208W + +usb:v174FpAA11* + ID_MODEL_FROM_DATABASE=Web Cam + +usb:v1753* + ID_VENDOR_FROM_DATABASE=GERTEC Telecomunicacoes Ltda. + +usb:v1753pC901* + ID_MODEL_FROM_DATABASE=PPC900 Pinpad Terminal + +usb:v1756* + ID_VENDOR_FROM_DATABASE=ENENSYS Technologies + +usb:v1756p0006* + ID_MODEL_FROM_DATABASE=DiviPitch + +usb:v1759* + ID_VENDOR_FROM_DATABASE=LucidPort Technology, Inc. + +usb:v1761* + ID_VENDOR_FROM_DATABASE=ASUSTek Computer, Inc. (wrong ID) + +usb:v1761p0B05* + ID_MODEL_FROM_DATABASE=802.11n Network Adapter (wrong ID - swapped vendor and device) + +usb:v1772* + ID_VENDOR_FROM_DATABASE=System Level Solutions, Inc. + +usb:v1776* + ID_VENDOR_FROM_DATABASE=Arowana + +usb:v1776p501C* + ID_MODEL_FROM_DATABASE=300K CMOS Camera + +usb:v177F* + ID_VENDOR_FROM_DATABASE=Sweex + +usb:v177Fp0004* + ID_MODEL_FROM_DATABASE=MM004V5 Photo Key Chain (Digital Photo Frame) 1.5" + +usb:v177Fp0153* + ID_MODEL_FROM_DATABASE=LW153 802.11n Adapter [ralink rt3070] + +usb:v177Fp0154* + ID_MODEL_FROM_DATABASE=LW154 802.11bgn (1x1:1) Wireless Adapter [Realtek RTL8188SU] + +usb:v177Fp0313* + ID_MODEL_FROM_DATABASE=LW313 802.11n Adapter [ralink rt2770 + rt2720] + +usb:v1781* + ID_VENDOR_FROM_DATABASE=Multiple Vendors + +usb:v1781p083E* + ID_MODEL_FROM_DATABASE=MetaGeek Wi-Spy + +usb:v1781p083F* + ID_MODEL_FROM_DATABASE=MetaGeek Wi-Spy 2.4x + +usb:v1781p0938* + ID_MODEL_FROM_DATABASE=Iguanaworks USB IR Transceiver + +usb:v1781p0A96* + ID_MODEL_FROM_DATABASE=raphnet.net usb_game12 + +usb:v1781p0A97* + ID_MODEL_FROM_DATABASE=raphnet.net SNES mouse adapter + +usb:v1781p0A98* + ID_MODEL_FROM_DATABASE=raphnet.net USBTenki + +usb:v1781p0A99* + ID_MODEL_FROM_DATABASE=raphnet.net NES + +usb:v1781p0A9A* + ID_MODEL_FROM_DATABASE=raphnet.net Gamecube/N64 controller + +usb:v1781p0A9B* + ID_MODEL_FROM_DATABASE=raphnet.net DB9Joy + +usb:v1781p0A9C* + ID_MODEL_FROM_DATABASE=raphnet.net Intellivision + +usb:v1781p0A9D* + ID_MODEL_FROM_DATABASE=raphnet.net 4nes4snes + +usb:v1781p0A9E* + ID_MODEL_FROM_DATABASE=raphnet.net Megadrive multitap + +usb:v1781p0A9F* + ID_MODEL_FROM_DATABASE=raphnet.net MultiDB9joy + +usb:v1781p0C30* + ID_MODEL_FROM_DATABASE=Telldus TellStick + +usb:v1781p0C31* + ID_MODEL_FROM_DATABASE=Telldus TellStick Duo + +usb:v1781p0C9F* + ID_MODEL_FROM_DATABASE=USBtiny + +usb:v1781p1EEF* + ID_MODEL_FROM_DATABASE=OpenAPC SecuKey + +usb:v1781p1EF0* + ID_MODEL_FROM_DATABASE=E1701 Modular Controller Card + +usb:v1781p1EF1* + ID_MODEL_FROM_DATABASE=E1701 Modular Controller Card + +usb:v1782* + ID_VENDOR_FROM_DATABASE=Spreadtrum Communications Inc. + +usb:v1784* + ID_VENDOR_FROM_DATABASE=TopSeed Technology Corp. + +usb:v1784p0001* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v1784p0004* + ID_MODEL_FROM_DATABASE=RF Combo Device + +usb:v1784p0006* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v1784p0007* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v1784p0008* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v1784p000A* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v1784p0011* + ID_MODEL_FROM_DATABASE=eHome Infrared Transceiver + +usb:v1787* + ID_VENDOR_FROM_DATABASE=ATI AIB + +usb:v1788* + ID_VENDOR_FROM_DATABASE=ShenZhen Litkconn Technology Co., Ltd. + +usb:v1796* + ID_VENDOR_FROM_DATABASE=Printrex, Inc. + +usb:v1797* + ID_VENDOR_FROM_DATABASE=JALCO CO., LTD. + +usb:v1799* + ID_VENDOR_FROM_DATABASE=Thales Norway A/S + +usb:v1799p7051* + ID_MODEL_FROM_DATABASE=Belkin F5D7051 802.11g Adapter v1000 [Broadcom 4320] + +usb:v1799p8051* + ID_MODEL_FROM_DATABASE=Belkin F5D8051 v2 802.11bgn Wireless Adapter [Marvell 88W8362] + +usb:v179D* + ID_VENDOR_FROM_DATABASE=Ricavision International, Inc. + +usb:v179Dp0010* + ID_MODEL_FROM_DATABASE=Internal Infrared Transceiver + +usb:v17A0* + ID_VENDOR_FROM_DATABASE=Samson Technologies Corp. + +usb:v17A0p0001* + ID_MODEL_FROM_DATABASE=C01U condenser microphone + +usb:v17A0p0002* + ID_MODEL_FROM_DATABASE=Q1U dynamic microphone + +usb:v17A0p0100* + ID_MODEL_FROM_DATABASE=C03U multi-pattern microphone + +usb:v17A0p0101* + ID_MODEL_FROM_DATABASE=UB1 boundary microphone + +usb:v17A0p0120* + ID_MODEL_FROM_DATABASE=Meteorite condenser microphone + +usb:v17A0p0200* + ID_MODEL_FROM_DATABASE=StudioDock monitors (internal hub) + +usb:v17A0p0201* + ID_MODEL_FROM_DATABASE=StudioDock monitors (audio) + +usb:v17A0p0210* + ID_MODEL_FROM_DATABASE=StudioGT monitors + +usb:v17A0p0301* + ID_MODEL_FROM_DATABASE=Q2U handheld microphone with XLR + +usb:v17A0p0302* + ID_MODEL_FROM_DATABASE=GoMic compact condenser microphone + +usb:v17A0p0303* + ID_MODEL_FROM_DATABASE=C01U Pro condenser microphone + +usb:v17A0p0304* + ID_MODEL_FROM_DATABASE=Q2U handheld mic with XLR + +usb:v17A0p0305* + ID_MODEL_FROM_DATABASE=GoMic compact condenser mic + +usb:v17A0p0310* + ID_MODEL_FROM_DATABASE=Meteor condenser microphone + +usb:v17A4* + ID_VENDOR_FROM_DATABASE=Concept2 + +usb:v17A4p0001* + ID_MODEL_FROM_DATABASE=Performance Monitor 3 + +usb:v17A4p0002* + ID_MODEL_FROM_DATABASE=Performance Monitor 4 + +usb:v17A5* + ID_VENDOR_FROM_DATABASE=Advanced Connection Technology Inc. + +usb:v17A7* + ID_VENDOR_FROM_DATABASE=MICOMSOFT CO., LTD. + +usb:v17A8* + ID_VENDOR_FROM_DATABASE=Kamstrup A/S + +usb:v17A8p0001* + ID_MODEL_FROM_DATABASE=Optical Eye/3-wire + +usb:v17A8p0005* + ID_MODEL_FROM_DATABASE=M-Bus Master MultiPort 250D + +usb:v17B3* + ID_VENDOR_FROM_DATABASE=Grey Innovation + +usb:v17B3p0004* + ID_MODEL_FROM_DATABASE=Linux-USB Midi Gadget + +usb:v17B5* + ID_VENDOR_FROM_DATABASE=Lunatone + +usb:v17B5p0010* + ID_MODEL_FROM_DATABASE=MFT Sensor + +usb:v17BA* + ID_VENDOR_FROM_DATABASE=SAURIS GmbH + +usb:v17BAp0001* + ID_MODEL_FROM_DATABASE=SAU510-USB [no firmware] + +usb:v17BAp0510* + ID_MODEL_FROM_DATABASE=SAU510-USB and SAU510-USB plus JTAG Emulators + +usb:v17BAp0511* + ID_MODEL_FROM_DATABASE=SAU510-USB Iso Plus JTAG Emulator + +usb:v17BAp0520* + ID_MODEL_FROM_DATABASE=SAU510-USB Nano JTAG Emulator + +usb:v17BAp1511* + ID_MODEL_FROM_DATABASE=Onboard Emulator on SAUModule development kit + +usb:v17C3* + ID_VENDOR_FROM_DATABASE=Singim International Corp. + +usb:v17CC* + ID_VENDOR_FROM_DATABASE=Native Instruments + +usb:v17CCp041C* + ID_MODEL_FROM_DATABASE=Audio 2 DJ + +usb:v17CCp0808* + ID_MODEL_FROM_DATABASE=Maschine Controller + +usb:v17CCp0815* + ID_MODEL_FROM_DATABASE=Audio Kontrol 1 + +usb:v17CCp0839* + ID_MODEL_FROM_DATABASE=Audio 4 DJ + +usb:v17CCp0D8D* + ID_MODEL_FROM_DATABASE=Guitarrig Mobile + +usb:v17CCp1915* + ID_MODEL_FROM_DATABASE=Session I/O + +usb:v17CCp1940* + ID_MODEL_FROM_DATABASE=RigKontrol3 + +usb:v17CCp1969* + ID_MODEL_FROM_DATABASE=RigKontrol2 + +usb:v17CCp1978* + ID_MODEL_FROM_DATABASE=Audio 8 DJ + +usb:v17CCp2280* + ID_MODEL_FROM_DATABASE=Medion MDPNA1500 in card reader mode + +usb:v17CCp2305* + ID_MODEL_FROM_DATABASE=Traktor Kontrol X1 + +usb:v17CCp4711* + ID_MODEL_FROM_DATABASE=Kore Controller + +usb:v17CCp4712* + ID_MODEL_FROM_DATABASE=Kore Controller 2 + +usb:v17CCpBAFF* + ID_MODEL_FROM_DATABASE=Traktor Kontrol S4 + +usb:v17CF* + ID_VENDOR_FROM_DATABASE=Hip Hing Cable & Plug Mfy. Ltd. + +usb:v17D0* + ID_VENDOR_FROM_DATABASE=Sanford L.P. + +usb:v17D3* + ID_VENDOR_FROM_DATABASE=Korea Techtron Co., Ltd. + +usb:v17E9* + ID_VENDOR_FROM_DATABASE=DisplayLink + +usb:v17E9p0051* + ID_MODEL_FROM_DATABASE=USB VGA Adaptor + +usb:v17E9p030B* + ID_MODEL_FROM_DATABASE=HP T100 + +usb:v17E9p0377* + ID_MODEL_FROM_DATABASE=Plugable UD-160-A (M) + +usb:v17E9p0378* + ID_MODEL_FROM_DATABASE=Plugable UGA-2K-A + +usb:v17E9p0379* + ID_MODEL_FROM_DATABASE=Plugable UGA-125 + +usb:v17E9p037A* + ID_MODEL_FROM_DATABASE=Plugable UGA-165 + +usb:v17E9p037B* + ID_MODEL_FROM_DATABASE=Plugable USB-VGA-165 + +usb:v17E9p037C* + ID_MODEL_FROM_DATABASE=Plugable DC-125 + +usb:v17E9p037D* + ID_MODEL_FROM_DATABASE=Plugable USB2-HDMI-165 + +usb:v17E9p410A* + ID_MODEL_FROM_DATABASE=HDMI Adapter + +usb:v17E9p430A* + ID_MODEL_FROM_DATABASE=HP Port Replicator (Composite Device) + +usb:v17E9p4312* + ID_MODEL_FROM_DATABASE=S2340T + +usb:v17EB* + ID_VENDOR_FROM_DATABASE=Cornice, Inc. + +usb:v17EF* + ID_VENDOR_FROM_DATABASE=Lenovo + +usb:v17EFp1000* + ID_MODEL_FROM_DATABASE=Hub + +usb:v17EFp1003* + ID_MODEL_FROM_DATABASE=Integrated Smart Card Reader + +usb:v17EFp1004* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v17EFp1008* + ID_MODEL_FROM_DATABASE=Hub + +usb:v17EFp100A* + ID_MODEL_FROM_DATABASE=ThinkPad Mini Dock Plus Series 3 + +usb:v17EFp304B* + ID_MODEL_FROM_DATABASE=AX88179 Gigabit Ethernet [ThinkPad OneLink GigaLAN] + +usb:v17EFp3815* + ID_MODEL_FROM_DATABASE=ChipsBnk 2GB USB Stick + +usb:v17EFp4802* + ID_MODEL_FROM_DATABASE=Lenovo Vc0323+MI1310_SOC Camera + +usb:v17EFp4807* + ID_MODEL_FROM_DATABASE=UVC Camera + +usb:v17EFp480C* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v17EFp480D* + ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] + +usb:v17EFp480E* + ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] + +usb:v17EFp480F* + ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] + +usb:v17EFp4810* + ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] + +usb:v17EFp4811* + ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] + +usb:v17EFp4812* + ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] + +usb:v17EFp4813* + ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] + +usb:v17EFp4814* + ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] + +usb:v17EFp4815* + ID_MODEL_FROM_DATABASE=Integrated Webcam [R5U877] + +usb:v17EFp4816* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v17EFp481C* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v17EFp481D* + ID_MODEL_FROM_DATABASE=Integrated Webcam + +usb:v17EFp6004* + ID_MODEL_FROM_DATABASE=ISD-V4 Tablet Pen + +usb:v17EFp6007* + ID_MODEL_FROM_DATABASE=Smartcard Keyboard + +usb:v17EFp6009* + ID_MODEL_FROM_DATABASE=ThinkPad Keyboard with TrackPoint + +usb:v17EFp6014* + ID_MODEL_FROM_DATABASE=Mini Wireless Keyboard N5901 + +usb:v17EFp6025* + ID_MODEL_FROM_DATABASE=ThinkPad Travel Mouse + +usb:v17EFp7203* + ID_MODEL_FROM_DATABASE=Ethernet adapter [U2L 100P-Y1] + +usb:v17EFp7423* + ID_MODEL_FROM_DATABASE=IdeaPad A1 Tablet + +usb:v17EFp7435* + ID_MODEL_FROM_DATABASE=A789 (Mass Storage mode, with debug) + +usb:v17EFp743A* + ID_MODEL_FROM_DATABASE=A789 (Mass Storage mode) + +usb:v17EFp7497* + ID_MODEL_FROM_DATABASE=A789 (MTP mode) + +usb:v17EFp7498* + ID_MODEL_FROM_DATABASE=A789 (MTP mode, with debug) + +usb:v17EFp749A* + ID_MODEL_FROM_DATABASE=A789 (PTP mode) + +usb:v17EFp749B* + ID_MODEL_FROM_DATABASE=A789 (PTP mode, with debug) + +usb:v17F4* + ID_VENDOR_FROM_DATABASE=WaveSense + +usb:v17F4pAAAA* + ID_MODEL_FROM_DATABASE=Jazz Blood Glucose Meter + +usb:v17F5* + ID_VENDOR_FROM_DATABASE=K.K. Rocky + +usb:v17F6* + ID_VENDOR_FROM_DATABASE=Unicomp, Inc + +usb:v17F6p0709* + ID_MODEL_FROM_DATABASE=Model M Keyboard + +usb:v1809* + ID_VENDOR_FROM_DATABASE=Advantech + +usb:v1809p4604* + ID_MODEL_FROM_DATABASE=USB-4604 + +usb:v1809p4761* + ID_MODEL_FROM_DATABASE=USB-4761 Portable Data Acquisition Module + +usb:v1822* + ID_VENDOR_FROM_DATABASE=Twinhan + +usb:v1822p3201* + ID_MODEL_FROM_DATABASE=VisionDTV USB-Ter/HAMA USB DVB-T device cold + +usb:v1822p3202* + ID_MODEL_FROM_DATABASE=VisionDTV USB-Ter/HAMA USB DVB-T device warm + +usb:v1831* + ID_VENDOR_FROM_DATABASE=Gwo Jinn Industries Co., Ltd. + +usb:v1832* + ID_VENDOR_FROM_DATABASE=Huizhou Shenghua Industrial Co., Ltd. + +usb:v183D* + ID_VENDOR_FROM_DATABASE=VIVOphone + +usb:v183Dp0010* + ID_MODEL_FROM_DATABASE=VoiceKey + +usb:v1843* + ID_VENDOR_FROM_DATABASE=Vaisala + +usb:v1849* + ID_VENDOR_FROM_DATABASE=ASRock Incorporation + +usb:v1852* + ID_VENDOR_FROM_DATABASE=GYROCOM C&C Co., LTD + +usb:v1852p7922* + ID_MODEL_FROM_DATABASE=Audiotrak DR.DAC2 DX [GYROCOM C&C] + +usb:v1854* + ID_VENDOR_FROM_DATABASE=Memory Devices Ltd. + +usb:v185B* + ID_VENDOR_FROM_DATABASE=Compro + +usb:v185Bp3020* + ID_MODEL_FROM_DATABASE=K100 Infrared Receiver + +usb:v185Bp3082* + ID_MODEL_FROM_DATABASE=K100 Infrared Receiver v2 + +usb:v185BpD000* + ID_MODEL_FROM_DATABASE=Compro Videomate DVB-U2000 - DVB-T USB cold + +usb:v185BpD001* + ID_MODEL_FROM_DATABASE=Compro Videomate DVB-U2000 - DVB-T USB warm + +usb:v1861* + ID_VENDOR_FROM_DATABASE=Tech Technology Industrial Company + +usb:v1862* + ID_VENDOR_FROM_DATABASE=Teridian Semiconductor Corp. + +usb:v1870* + ID_VENDOR_FROM_DATABASE=Nexio Co., Ltd + +usb:v1870p0001* + ID_MODEL_FROM_DATABASE=iNexio Touchscreen controller + +usb:v1871* + ID_VENDOR_FROM_DATABASE=Aveo Technology Corp. + +usb:v1871p0101* + ID_MODEL_FROM_DATABASE=UVC camera (Bresser microscope) + +usb:v1871p0141* + ID_MODEL_FROM_DATABASE=Camera + +usb:v1871p0D01* + ID_MODEL_FROM_DATABASE=USB2.0 Camera + +usb:v1873* + ID_VENDOR_FROM_DATABASE=Navilock + +usb:v1873pEE93* + ID_MODEL_FROM_DATABASE=EasyLogger + +usb:v187C* + ID_VENDOR_FROM_DATABASE=Alienware Corporation + +usb:v187Cp0511* + ID_MODEL_FROM_DATABASE=AlienFX Mobile lighting + +usb:v187Cp0600* + ID_MODEL_FROM_DATABASE=Dual Compatible Game Pad + +usb:v187F* + ID_VENDOR_FROM_DATABASE=Siano Mobile Silicon + +usb:v187Fp0010* + ID_MODEL_FROM_DATABASE=Stallar Board + +usb:v187Fp0100* + ID_MODEL_FROM_DATABASE=Stallar Board + +usb:v187Fp0200* + ID_MODEL_FROM_DATABASE=Nova A + +usb:v187Fp0201* + ID_MODEL_FROM_DATABASE=Nova B + +usb:v187Fp0202* + ID_MODEL_FROM_DATABASE=Nice + +usb:v187Fp0300* + ID_MODEL_FROM_DATABASE=Vega + +usb:v187Fp0301* + ID_MODEL_FROM_DATABASE=VeNice + +usb:v1892* + ID_VENDOR_FROM_DATABASE=Vast Technologies, Inc. + +usb:v1894* + ID_VENDOR_FROM_DATABASE=Topseed + +usb:v1894p5632* + ID_MODEL_FROM_DATABASE=Atek Tote Remote + +usb:v1894p5641* + ID_MODEL_FROM_DATABASE=TSAM-004 Presentation Remote + +usb:v1897* + ID_VENDOR_FROM_DATABASE=Evertop Wire Cable Co. + +usb:v189F* + ID_VENDOR_FROM_DATABASE=3Shape A/S + +usb:v189Fp0002* + ID_MODEL_FROM_DATABASE=Legato2 3D Scanner + +usb:v18A4* + ID_VENDOR_FROM_DATABASE=CSSN + +usb:v18A4p0001* + ID_MODEL_FROM_DATABASE=Snapshell IDR + +usb:v18A5* + ID_VENDOR_FROM_DATABASE=Verbatim, Ltd + +usb:v18A5p0214* + ID_MODEL_FROM_DATABASE=Portable Hard Drive + +usb:v18A5p0216* + ID_MODEL_FROM_DATABASE=External Hard Drive + +usb:v18A5p0218* + ID_MODEL_FROM_DATABASE=External Hard Drive + +usb:v18A5p0224* + ID_MODEL_FROM_DATABASE=Store 'n' Go Micro Plus + +usb:v18A5p0227* + ID_MODEL_FROM_DATABASE=Pocket Hard Drive + +usb:v18A5p022B* + ID_MODEL_FROM_DATABASE=Portable Hard Drive (Store'n'Go) + +usb:v18A5p0237* + ID_MODEL_FROM_DATABASE=Portable Harddrive + +usb:v18A5p0243* + ID_MODEL_FROM_DATABASE=Flash Drive (Store'n'Go) + +usb:v18A5p0302* + ID_MODEL_FROM_DATABASE=Flash Drive + +usb:v18A5p0304* + ID_MODEL_FROM_DATABASE=Store 'n' Go + +usb:v18A5p4123* + ID_MODEL_FROM_DATABASE=Store N Go + +usb:v18B1* + ID_VENDOR_FROM_DATABASE=Petalynx + +usb:v18B1p0037* + ID_MODEL_FROM_DATABASE=Maxter Remote Control + +usb:v18B4* + ID_VENDOR_FROM_DATABASE=e3C Technologies + +usb:v18B4p1001* + ID_MODEL_FROM_DATABASE=DUTV007 + +usb:v18B4p1002* + ID_MODEL_FROM_DATABASE=EC168 (v5) based USB DVB-T receiver + +usb:v18B4p1689* + ID_MODEL_FROM_DATABASE=DUTV009 + +usb:v18B4pFFFA* + ID_MODEL_FROM_DATABASE=EC168 (v2) based USB DVB-T receiver + +usb:v18B4pFFFB* + ID_MODEL_FROM_DATABASE=EC168 (v3) based USB DVB-T receiver + +usb:v18B6* + ID_VENDOR_FROM_DATABASE=Mikkon Technology Limited + +usb:v18B7* + ID_VENDOR_FROM_DATABASE=Zotek Electronic Co., Ltd. + +usb:v18C5* + ID_VENDOR_FROM_DATABASE=AMIT Technology, Inc. + +usb:v18C5p0002* + ID_MODEL_FROM_DATABASE=CG-WLUSB2GO + +usb:v18C5p0008* + ID_MODEL_FROM_DATABASE=CG-WLUSB2GNR Corega Wireless USB Adapter + +usb:v18C5p0012* + ID_MODEL_FROM_DATABASE=CG-WLUSB10 Corega Wireless USB Adapter + +usb:v18CD* + ID_VENDOR_FROM_DATABASE=Ecamm + +usb:v18CDpCAFE* + ID_MODEL_FROM_DATABASE=Pico iMage + +usb:v18D1* + ID_VENDOR_FROM_DATABASE=Google Inc. + +usb:v18D1p0001* + ID_MODEL_FROM_DATABASE=Onda V972 (storage access) + +usb:v18D1p0003* + ID_MODEL_FROM_DATABASE=Android-powered device using AllWinner Technology SoC + +usb:v18D1p0006* + ID_MODEL_FROM_DATABASE=Onda V972 MTP + +usb:v18D1p0008* + ID_MODEL_FROM_DATABASE=Onda V972 PTP (camera) + +usb:v18D1p0D02* + ID_MODEL_FROM_DATABASE=Celkon A88 + +usb:v18D1p2D00* + ID_MODEL_FROM_DATABASE=Android-powered device in accessory mode + +usb:v18D1p2D01* + ID_MODEL_FROM_DATABASE=Android-powered device in accessory mode with ADB support + +usb:v18D1p4E11* + ID_MODEL_FROM_DATABASE=Nexus One + +usb:v18D1p4E12* + ID_MODEL_FROM_DATABASE=Nexus One (debug) + +usb:v18D1p4E13* + ID_MODEL_FROM_DATABASE=Nexus One (tether) + +usb:v18D1p4E20* + ID_MODEL_FROM_DATABASE=Nexus S (fastboot) + +usb:v18D1p4E21* + ID_MODEL_FROM_DATABASE=Nexus S + +usb:v18D1p4E22* + ID_MODEL_FROM_DATABASE=Nexus S (debug) + +usb:v18D1p4E24* + ID_MODEL_FROM_DATABASE=Nexus S (tether) + +usb:v18D1p4E30* + ID_MODEL_FROM_DATABASE=Galaxy Nexus (fastboot) + +usb:v18D1p4E40* + ID_MODEL_FROM_DATABASE=Nexus 7 (fastboot) + +usb:v18D1p4E41* + ID_MODEL_FROM_DATABASE=Nexus 7 (MTP) + +usb:v18D1p4E42* + ID_MODEL_FROM_DATABASE=Nexus 7 (debug) + +usb:v18D1p4E43* + ID_MODEL_FROM_DATABASE=Nexus 7 (PTP) + +usb:v18D1p4E44* + ID_MODEL_FROM_DATABASE=Nexus 7 2012 (PTP) + +usb:v18D1p4EE0* + ID_MODEL_FROM_DATABASE=Nexus 4 (bootloader) + +usb:v18D1p4EE1* + ID_MODEL_FROM_DATABASE=Nexus Device (MTP) + +usb:v18D1p4EE2* + ID_MODEL_FROM_DATABASE=Nexus Device (debug) + +usb:v18D1p4EE3* + ID_MODEL_FROM_DATABASE=Nexus 4/5/7/10 (tether) + +usb:v18D1p4EE4* + ID_MODEL_FROM_DATABASE=Nexus 4/5/7/10 (debug + tether) + +usb:v18D1p4EE5* + ID_MODEL_FROM_DATABASE=Nexus 4 (PTP) + +usb:v18D1p4EE6* + ID_MODEL_FROM_DATABASE=Nexus 4/5 (PTP + debug) + +usb:v18D1p7102* + ID_MODEL_FROM_DATABASE=Toshiba Thrive tablet + +usb:v18D1pB004* + ID_MODEL_FROM_DATABASE=Pandigital / B&N Novel 9" tablet + +usb:v18D1pD001* + ID_MODEL_FROM_DATABASE=Nexus 4 (fastboot) + +usb:v18D1pD002* + ID_MODEL_FROM_DATABASE=Nexus 4 (debug) + +usb:v18D1pD109* + ID_MODEL_FROM_DATABASE=LG G2x MTP + +usb:v18D1pD10A* + ID_MODEL_FROM_DATABASE=LG G2x MTP (debug) + +usb:v18D5* + ID_VENDOR_FROM_DATABASE=Starline International Group Limited + +usb:v18D9* + ID_VENDOR_FROM_DATABASE=Kaba + +usb:v18D9p01A0* + ID_MODEL_FROM_DATABASE=B-Net 91 07 + +usb:v18DC* + ID_VENDOR_FROM_DATABASE=LKC Technologies, Inc. + +usb:v18DD* + ID_VENDOR_FROM_DATABASE=Planon System Solutions Inc. + +usb:v18DDp1000* + ID_MODEL_FROM_DATABASE=DocuPen RC800 + +usb:v18E3* + ID_VENDOR_FROM_DATABASE=Fitipower Integrated Technology Inc + +usb:v18E3p7102* + ID_MODEL_FROM_DATABASE=Multi Card Reader (Internal) + +usb:v18E3p9101* + ID_MODEL_FROM_DATABASE=All-in-1 Card Reader + +usb:v18E3p9102* + ID_MODEL_FROM_DATABASE=Multi Card Reader + +usb:v18E3p9512* + ID_MODEL_FROM_DATABASE=Webcam + +usb:v18E8* + ID_VENDOR_FROM_DATABASE=Qcom + +usb:v18E8p6144* + ID_MODEL_FROM_DATABASE=LR802UA 802.11b Wireless Adapter [ALi M4301AU] + +usb:v18E8p6196* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v18E8p6229* + ID_MODEL_FROM_DATABASE=RT2573 + +usb:v18E8p6232* + ID_MODEL_FROM_DATABASE=Wireless 802.11g 54Mbps Network Adapter [RTL8187] + +usb:v18EA* + ID_VENDOR_FROM_DATABASE=Matrox Graphics, Inc. + +usb:v18EAp0002* + ID_MODEL_FROM_DATABASE=DualHead2Go [Analog Edition] + +usb:v18EAp0004* + ID_MODEL_FROM_DATABASE=TripleHead2Go [Digital Edition] + +usb:v18EC* + ID_VENDOR_FROM_DATABASE=Arkmicro Technologies Inc. + +usb:v18ECp3118* + ID_MODEL_FROM_DATABASE=USB to IrDA adapter [ARK3116T] + +usb:v18ECp3188* + ID_MODEL_FROM_DATABASE=ARK3188 UVC Webcam + +usb:v18ECp3299* + ID_MODEL_FROM_DATABASE=Webcam Carrefour + +usb:v18ECp3366* + ID_MODEL_FROM_DATABASE=Bresser Biolux NV + +usb:v18F8* + ID_VENDOR_FROM_DATABASE=[Maxxter] + +usb:v18F8p0F99* + ID_MODEL_FROM_DATABASE=Optical gaming mouse + +usb:v18FB* + ID_VENDOR_FROM_DATABASE=Scriptel Corporation + +usb:v18FBp01C0* + ID_MODEL_FROM_DATABASE=ST1501-STN + +usb:v18FBp01C1* + ID_MODEL_FROM_DATABASE=ST1526-STN + +usb:v18FBp01C2* + ID_MODEL_FROM_DATABASE=ST1501-PYJ + +usb:v18FBp01C3* + ID_MODEL_FROM_DATABASE=ST1501B-PYJ + +usb:v18FBp01C4* + ID_MODEL_FROM_DATABASE=ST1501-PUN + +usb:v18FBp01C5* + ID_MODEL_FROM_DATABASE=ST1401-STN + +usb:v18FBp01C7* + ID_MODEL_FROM_DATABASE=ST1526-PYJ + +usb:v18FBp01C8* + ID_MODEL_FROM_DATABASE=ST1501-ECA + +usb:v18FBp01C9* + ID_MODEL_FROM_DATABASE=ST1476-STN + +usb:v18FBp01CB* + ID_MODEL_FROM_DATABASE=ST1571-STN + +usb:v18FBp0200* + ID_MODEL_FROM_DATABASE=ST1500 + +usb:v18FBp0201* + ID_MODEL_FROM_DATABASE=ST1550 + +usb:v18FBp0202* + ID_MODEL_FROM_DATABASE=ST1525 + +usb:v18FBp0204* + ID_MODEL_FROM_DATABASE=ST1400 + +usb:v18FBp0206* + ID_MODEL_FROM_DATABASE=ST1475 + +usb:v18FBp0207* + ID_MODEL_FROM_DATABASE=ST1570 + +usb:v18FD* + ID_VENDOR_FROM_DATABASE=FineArch Inc. + +usb:v1901* + ID_VENDOR_FROM_DATABASE=GE Healthcare + +usb:v1901p0015* + ID_MODEL_FROM_DATABASE=Nemo Tracker + +usb:v1908* + ID_VENDOR_FROM_DATABASE=GEMBIRD + +usb:v1908p1320* + ID_MODEL_FROM_DATABASE=PhotoFrame PF-15-1 + +usb:v190D* + ID_VENDOR_FROM_DATABASE=Motorola GSG + +usb:v1914* + ID_VENDOR_FROM_DATABASE=Alco Digital Devices Limited + +usb:v1915* + ID_VENDOR_FROM_DATABASE=Nordic Semiconductor ASA + +usb:v1915p000C* + ID_MODEL_FROM_DATABASE=Wireless Desktop nRF24L01 CX-1766 + +usb:v1915p2233* + ID_MODEL_FROM_DATABASE=Linksys WUSB11 v2.8 802.11b Adapter [Atmel AT76C505] + +usb:v1915p2234* + ID_MODEL_FROM_DATABASE=Linksys WUSB54G v1 OEM 802.11g Adapter [Intersil ISL3886] + +usb:v1915p2235* + ID_MODEL_FROM_DATABASE=Linksys WUSB54GP v1 OEM 802.11g Adapter [Intersil ISL3886] + +usb:v1915p2236* + ID_MODEL_FROM_DATABASE=Linksys WUSB11 v3.0 802.11b Adapter [Intersil PRISM 3] + +usb:v191C* + ID_VENDOR_FROM_DATABASE=Innovative Technology LTD + +usb:v191Cp4104* + ID_MODEL_FROM_DATABASE=Banknote validator NV-150 + +usb:v1923* + ID_VENDOR_FROM_DATABASE=FitLinxx + +usb:v1923p0002* + ID_MODEL_FROM_DATABASE=Personal SyncPoint + +usb:v1926* + ID_VENDOR_FROM_DATABASE=NextWindow + +usb:v1926p0003* + ID_MODEL_FROM_DATABASE=1900 HID Touchscreen + +usb:v1926p0006* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0064* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0065* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0066* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0067* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0068* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0069* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0071* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0072* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0073* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0074* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0075* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0076* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0077* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0078* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0079* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p007A* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p007E* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p007F* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0080* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0081* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0082* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0083* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0084* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0085* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0086* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0087* + ID_MODEL_FROM_DATABASE=1950 HID Touchscreen + +usb:v1926p0DC2* + ID_MODEL_FROM_DATABASE=HID Touchscreen + +usb:v192F* + ID_VENDOR_FROM_DATABASE=Avago Technologies, Pte. + +usb:v192Fp0000* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v192Fp0416* + ID_MODEL_FROM_DATABASE=ADNS-5700 Optical Mouse Controller (3-button) + +usb:v192Fp0616* + ID_MODEL_FROM_DATABASE=ADNS-5700 Optical Mouse Controller (5-button) + +usb:v1930* + ID_VENDOR_FROM_DATABASE=Shenzhen Xianhe Technology Co., Ltd. + +usb:v1931* + ID_VENDOR_FROM_DATABASE=Ningbo Broad Telecommunication Co., Ltd. + +usb:v1934* + ID_VENDOR_FROM_DATABASE=Feature Integration Technology Inc. (Fintek) + +usb:v1934p0602* + ID_MODEL_FROM_DATABASE=F71610 or F71612 Consumer Infrared Receiver/Transceiver + +usb:v1934p0702* + ID_MODEL_FROM_DATABASE=Integrated Consumer Infrared Receiver/Transceiver + +usb:v1934p5168* + ID_MODEL_FROM_DATABASE=F71610A or F71612A Consumer Infrared Receiver/Transceiver + +usb:v1938* + ID_VENDOR_FROM_DATABASE=Meinberg Funkuhren GmbH & Co. KG + +usb:v1938p0501* + ID_MODEL_FROM_DATABASE=TCR51USB IRIG Time Code Reader + +usb:v1941* + ID_VENDOR_FROM_DATABASE=Dream Link + +usb:v1941p8021* + ID_MODEL_FROM_DATABASE=WH1080 Weather Station / USB Missile Launcher + +usb:v1943* + ID_VENDOR_FROM_DATABASE=Sensoray Co., Inc. + +usb:v1943p2250* + ID_MODEL_FROM_DATABASE=Model 2250 MPEG and JPEG Capture Card + +usb:v1943p2253* + ID_MODEL_FROM_DATABASE=Model 2253 Audio/Video Codec Card + +usb:v1943p2255* + ID_MODEL_FROM_DATABASE=Model 2255 4 Channel Capture Card + +usb:v1943p2257* + ID_MODEL_FROM_DATABASE=Model 2257 4 Channel Capture Card + +usb:v1943pA250* + ID_MODEL_FROM_DATABASE=Model 2250 MPEG and JPEG Capture Card (cold) + +usb:v1943pA253* + ID_MODEL_FROM_DATABASE=Model 2253 Audio/Video Codec Card (cold) + +usb:v1949* + ID_VENDOR_FROM_DATABASE=Lab126, Inc. + +usb:v1949p0002* + ID_MODEL_FROM_DATABASE=Amazon Kindle + +usb:v1949p0004* + ID_MODEL_FROM_DATABASE=Amazon Kindle 3/4/Paperwhite + +usb:v1949p0006* + ID_MODEL_FROM_DATABASE=Kindle Fire + +usb:v1949p0008* + ID_MODEL_FROM_DATABASE=Amazon Kindle Fire HD 8.9" + +usb:v194F* + ID_VENDOR_FROM_DATABASE=PreSonus Audio Electronics, Inc. + +usb:v194Fp0101* + ID_MODEL_FROM_DATABASE=AudioBox 22 VSL + +usb:v194Fp0102* + ID_MODEL_FROM_DATABASE=AudioBox 44 VSL + +usb:v194Fp0103* + ID_MODEL_FROM_DATABASE=AudioBox 1818 VSL + +usb:v194Fp0301* + ID_MODEL_FROM_DATABASE=AudioBox + +usb:v1951* + ID_VENDOR_FROM_DATABASE=Hyperstone AG + +usb:v1953* + ID_VENDOR_FROM_DATABASE=Ironkey Inc. + +usb:v1953p0202* + ID_MODEL_FROM_DATABASE=S200 2GB Rev. 1 + +usb:v1954* + ID_VENDOR_FROM_DATABASE=Radiient Technologies + +usb:v195D* + ID_VENDOR_FROM_DATABASE=Itron Technology iONE + +usb:v195Dp7002* + ID_MODEL_FROM_DATABASE=Libra-Q11 IR remote + +usb:v195Dp7006* + ID_MODEL_FROM_DATABASE=Libra-Q26 / 1.0 Remote + +usb:v195Dp7777* + ID_MODEL_FROM_DATABASE=Scorpius wireless keyboard + +usb:v195Dp7779* + ID_MODEL_FROM_DATABASE=Scorpius-P20MT + +usb:v1965* + ID_VENDOR_FROM_DATABASE=Uniden Corporation + +usb:v1965p0016* + ID_MODEL_FROM_DATABASE=HomePatrol-1 + +usb:v1967* + ID_VENDOR_FROM_DATABASE=CASIO HITACHI Mobile Communications Co., Ltd. + +usb:v196B* + ID_VENDOR_FROM_DATABASE=Wispro Technology Inc. + +usb:v1970* + ID_VENDOR_FROM_DATABASE=Dane-Elec Corp. USA + +usb:v1970p0000* + ID_MODEL_FROM_DATABASE=Z Mate 16GB + +usb:v1975* + ID_VENDOR_FROM_DATABASE=Dongguan Guneetal Wire & Cable Co., Ltd. + +usb:v1976* + ID_VENDOR_FROM_DATABASE=Chipsbrand Microelectronics (HK) Co., Ltd. + +usb:v1976p6025* + ID_MODEL_FROM_DATABASE=Flash Drive 512 MB + +usb:v1977* + ID_VENDOR_FROM_DATABASE=T-Logic + +usb:v1977p0111* + ID_MODEL_FROM_DATABASE=TL203 MP3 Player and Voice Recorder + +usb:v197D* + ID_VENDOR_FROM_DATABASE=Leuze electronic + +usb:v197Dp0222* + ID_MODEL_FROM_DATABASE=BCL 508i + +usb:v1989* + ID_VENDOR_FROM_DATABASE=Nuconn Technology Corp. + +usb:v198F* + ID_VENDOR_FROM_DATABASE=Beceem Communications Inc. + +usb:v198Fp0210* + ID_MODEL_FROM_DATABASE=BCS200 WiMAX Adapter + +usb:v198Fp0220* + ID_MODEL_FROM_DATABASE=BCSM250 WiMAX Adapter + +usb:v1990* + ID_VENDOR_FROM_DATABASE=Acron Precision Industrial Co., Ltd. + +usb:v1995* + ID_VENDOR_FROM_DATABASE=Trillium Technology Pty. Ltd. + +usb:v1995p3202* + ID_MODEL_FROM_DATABASE=REC-ADPT-USB (recorder) + +usb:v1995p3203* + ID_MODEL_FROM_DATABASE=REC-A-ADPT-USB (recorder) + +usb:v1996* + ID_VENDOR_FROM_DATABASE=PixeLINK + +usb:v1996p3010* + ID_MODEL_FROM_DATABASE=Camera Release 4 + +usb:v1996p3011* + ID_MODEL_FROM_DATABASE=OEM Camera + +usb:v1996p3012* + ID_MODEL_FROM_DATABASE=e-ImageData Corp. ScanPro + +usb:v199B* + ID_VENDOR_FROM_DATABASE=MicroStrain, Inc. + +usb:v199Bp3065* + ID_MODEL_FROM_DATABASE=3DM-GX3-25 Orientation Sensor + +usb:v199E* + ID_VENDOR_FROM_DATABASE=The Imaging Source Europe GmbH + +usb:v199Ep8101* + ID_MODEL_FROM_DATABASE=DFx 21BU04 Camera + +usb:v199F* + ID_VENDOR_FROM_DATABASE=Benica Corporation + +usb:v19A8* + ID_VENDOR_FROM_DATABASE=Biforst Technology Inc. + +usb:v19AB* + ID_VENDOR_FROM_DATABASE=Bodelin + +usb:v19ABp1000* + ID_MODEL_FROM_DATABASE=ProScope HR + +usb:v19AF* + ID_VENDOR_FROM_DATABASE=S Life + +usb:v19AFp6611* + ID_MODEL_FROM_DATABASE=Celestia VoIP Phone + +usb:v19B2* + ID_VENDOR_FROM_DATABASE=Batronix + +usb:v19B2p0010* + ID_MODEL_FROM_DATABASE=BX32 Batupo + +usb:v19B2p0011* + ID_MODEL_FROM_DATABASE=BX32P Barlino + +usb:v19B2p0012* + ID_MODEL_FROM_DATABASE=BX40 Bagero + +usb:v19B2p0013* + ID_MODEL_FROM_DATABASE=BX48 Batego + +usb:v19B4* + ID_VENDOR_FROM_DATABASE=Celestron + +usb:v19B4p0002* + ID_MODEL_FROM_DATABASE=SkyScout Personal Planetarium + +usb:v19B4p0101* + ID_MODEL_FROM_DATABASE=Handheld Digital Microscope 44302 + +usb:v19B5* + ID_VENDOR_FROM_DATABASE=B & W Group + +usb:v19B6* + ID_VENDOR_FROM_DATABASE=Infotech Logistic, LLC + +usb:v19B9* + ID_VENDOR_FROM_DATABASE=Data Robotics + +usb:v19B9p8D20* + ID_MODEL_FROM_DATABASE=Drobo Elite + +usb:v19C2* + ID_VENDOR_FROM_DATABASE=Futuba + +usb:v19C2p6A11* + ID_MODEL_FROM_DATABASE=MDM166A Fluorescent Display + +usb:v19CA* + ID_VENDOR_FROM_DATABASE=Mindtribe + +usb:v19CAp0001* + ID_MODEL_FROM_DATABASE=Sandio 3D HID Mouse + +usb:v19CF* + ID_VENDOR_FROM_DATABASE=Parrot SA + +usb:v19D2* + ID_VENDOR_FROM_DATABASE=ZTE WCDMA Technologies MSM + +usb:v19D2p0001* + ID_MODEL_FROM_DATABASE=CDMA Wireless Modem + +usb:v19D2p0002* + ID_MODEL_FROM_DATABASE=MF632/ONDA ET502HS/MT505UP + +usb:v19D2p0007* + ID_MODEL_FROM_DATABASE=TU25 WiMAX Adapter [Beceem BCS200] + +usb:v19D2p0031* + ID_MODEL_FROM_DATABASE=MF110/MF627/MF636 + +usb:v19D2p0063* + ID_MODEL_FROM_DATABASE=K3565-Z HSDPA + +usb:v19D2p0064* + ID_MODEL_FROM_DATABASE=MF627 AU + +usb:v19D2p0083* + ID_MODEL_FROM_DATABASE=MF190 + +usb:v19D2p0103* + ID_MODEL_FROM_DATABASE=MF112 + +usb:v19D2p0104* + ID_MODEL_FROM_DATABASE=K4505-Z + +usb:v19D2p0146* + ID_MODEL_FROM_DATABASE=MF 195E (HSPA+ Modem) + +usb:v19D2p0167* + ID_MODEL_FROM_DATABASE=MF820 4G LTE + +usb:v19D2p0172* + ID_MODEL_FROM_DATABASE=AX226 WIMAX MODEM (After Modeswitch) + +usb:v19D2p0325* + ID_MODEL_FROM_DATABASE=LTE4G O2 ZTE MF821D LTE/UMTS/GSM Modem/Networkcard + +usb:v19D2p0326* + ID_MODEL_FROM_DATABASE=LTE4G O2 ZTE MF821D LTE/UMTS/GSM Modem/Networkcard + +usb:v19D2p1008* + ID_MODEL_FROM_DATABASE=K3570-Z + +usb:v19D2p1010* + ID_MODEL_FROM_DATABASE=K3571-Z + +usb:v19D2p1017* + ID_MODEL_FROM_DATABASE=K5006-Z vodafone LTE/UMTS/GSM Modem/Networkcard + +usb:v19D2p1018* + ID_MODEL_FROM_DATABASE=K5006-Z vodafone LTE/UMTS/GSM Modem/Networkcard + +usb:v19D2p1203* + ID_MODEL_FROM_DATABASE=MF691 [ T-Mobile webConnect Rocket 2.0] + +usb:v19D2p1217* + ID_MODEL_FROM_DATABASE=MF652 + +usb:v19D2p1218* + ID_MODEL_FROM_DATABASE=MF652 + +usb:v19D2p2000* + ID_MODEL_FROM_DATABASE=MF627/MF628/MF628+/MF636+ HSDPA/HSUPA + +usb:v19D2pFFF2* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) + +usb:v19D2pFFF3* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem + +usb:v19DB* + ID_VENDOR_FROM_DATABASE=KFI Printers + +usb:v19DBp02F1* + ID_MODEL_FROM_DATABASE=NAUT324C + +usb:v19E1* + ID_VENDOR_FROM_DATABASE=WeiDuan Electronic Accessory (S.Z.) Co., Ltd. + +usb:v19E8* + ID_VENDOR_FROM_DATABASE=Industrial Technology Research Institute + +usb:v19EF* + ID_VENDOR_FROM_DATABASE=Pak Heng Technology (Shenzhen) Co., Ltd. + +usb:v19F7* + ID_VENDOR_FROM_DATABASE=RODE Microphones + +usb:v19F7p0001* + ID_MODEL_FROM_DATABASE=Podcaster + +usb:v19FA* + ID_VENDOR_FROM_DATABASE=Gampaq Co.Ltd + +usb:v19FAp0703* + ID_MODEL_FROM_DATABASE=Steering Wheel + +usb:v19FF* + ID_VENDOR_FROM_DATABASE=Dynex + +usb:v19FFp0102* + ID_MODEL_FROM_DATABASE=1.3MP Webcam + +usb:v19FFp0201* + ID_MODEL_FROM_DATABASE=Rocketfish Wireless 2.4G Laser Mouse + +usb:v19FFp0238* + ID_MODEL_FROM_DATABASE=DX-WRM1401 Mouse + +usb:v1A08* + ID_VENDOR_FROM_DATABASE=Bellwood International, Inc. + +usb:v1A0A* + ID_VENDOR_FROM_DATABASE=USB-IF non-workshop + +usb:v1A0ApBADD* + ID_MODEL_FROM_DATABASE=USB OTG Compliance test device + +usb:v1A12* + ID_VENDOR_FROM_DATABASE=KES Co., Ltd. + +usb:v1A1D* + ID_VENDOR_FROM_DATABASE=Veho + +usb:v1A1Dp0407* + ID_MODEL_FROM_DATABASE=Mimi WiFi speakers + +usb:v1A25* + ID_VENDOR_FROM_DATABASE=Amphenol East Asia Ltd. + +usb:v1A2A* + ID_VENDOR_FROM_DATABASE=Seagate Branded Solutions + +usb:v1A2C* + ID_VENDOR_FROM_DATABASE=China Resource Semico Co., Ltd + +usb:v1A2Cp0021* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v1A2Cp0024* + ID_MODEL_FROM_DATABASE=Multimedia Keyboard + +usb:v1A32* + ID_VENDOR_FROM_DATABASE=Quanta Microsystems, Inc. + +usb:v1A32p0304* + ID_MODEL_FROM_DATABASE=802.11n Wireless LAN Card + +usb:v1A34* + ID_VENDOR_FROM_DATABASE=ACRUX + +usb:v1A34p0802* + ID_MODEL_FROM_DATABASE=Gamepad + +usb:v1A36* + ID_VENDOR_FROM_DATABASE=Biwin Technology Ltd. + +usb:v1A40* + ID_VENDOR_FROM_DATABASE=Terminus Technology Inc. + +usb:v1A40p0101* + ID_MODEL_FROM_DATABASE=Hub + +usb:v1A40p0201* + ID_MODEL_FROM_DATABASE=FE 2.1 7-port Hub + +usb:v1A41* + ID_VENDOR_FROM_DATABASE=Action Electronics Co., Ltd. + +usb:v1A44* + ID_VENDOR_FROM_DATABASE=VASCO Data Security International + +usb:v1A44p0001* + ID_MODEL_FROM_DATABASE=Digipass 905 SmartCard Reader + +usb:v1A4A* + ID_VENDOR_FROM_DATABASE=Silicon Image + +usb:v1A4B* + ID_VENDOR_FROM_DATABASE=SafeBoot International B.V. + +usb:v1A5A* + ID_VENDOR_FROM_DATABASE=Tandberg Data + +usb:v1A61* + ID_VENDOR_FROM_DATABASE=Abbott Diabetes Care + +usb:v1A61p3410* + ID_MODEL_FROM_DATABASE=CoPilot System Cable + +usb:v1A6A* + ID_VENDOR_FROM_DATABASE=Spansion Inc. + +usb:v1A6D* + ID_VENDOR_FROM_DATABASE=SamYoung Electronics Co., Ltd + +usb:v1A6E* + ID_VENDOR_FROM_DATABASE=Global Unichip Corp. + +usb:v1A6F* + ID_VENDOR_FROM_DATABASE=Sagem Orga GmbH + +usb:v1A72* + ID_VENDOR_FROM_DATABASE=Physik Instrumente + +usb:v1A72p1008* + ID_MODEL_FROM_DATABASE=E-861 PiezoWalk NEXACT Controller + +usb:v1A79* + ID_VENDOR_FROM_DATABASE=Bayer Health Care LLC + +usb:v1A79p6002* + ID_MODEL_FROM_DATABASE=Contour + +usb:v1A79p7410* + ID_MODEL_FROM_DATABASE=Contour Next + +usb:v1A7B* + ID_VENDOR_FROM_DATABASE=Lumberg Connect GmbH & Co. KG + +usb:v1A7C* + ID_VENDOR_FROM_DATABASE=Evoluent + +usb:v1A7Cp0068* + ID_MODEL_FROM_DATABASE=VerticalMouse 3 + +usb:v1A7Cp0168* + ID_MODEL_FROM_DATABASE=VerticalMouse 3 Wireless + +usb:v1A7Cp0191* + ID_MODEL_FROM_DATABASE=VerticalMouse 4 + +usb:v1A81* + ID_VENDOR_FROM_DATABASE=Holtek Semiconductor, Inc. + +usb:v1A81p2203* + ID_MODEL_FROM_DATABASE=Laser Gaming mouse + +usb:v1A81p2204* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v1A81p2205* + ID_MODEL_FROM_DATABASE=Laser Mouse + +usb:v1A86* + ID_VENDOR_FROM_DATABASE=QinHeng Electronics + +usb:v1A86p5512* + ID_MODEL_FROM_DATABASE=CH341 in EPP/MEM/I2C mode, EPP/I2C adapter + +usb:v1A86p5523* + ID_MODEL_FROM_DATABASE=CH341 in serial mode, usb to serial port converter + +usb:v1A86p5584* + ID_MODEL_FROM_DATABASE=CH341 in parallel mode, usb to printer port converter + +usb:v1A86p7523* + ID_MODEL_FROM_DATABASE=HL-340 USB-Serial adapter + +usb:v1A86p752D* + ID_MODEL_FROM_DATABASE=CH345 MIDI adapter + +usb:v1A86p7584* + ID_MODEL_FROM_DATABASE=CH340S + +usb:v1A86pE008* + ID_MODEL_FROM_DATABASE=HID-based serial adapater + +usb:v1A89* + ID_VENDOR_FROM_DATABASE=Dynalith Systems Co., Ltd. + +usb:v1A8B* + ID_VENDOR_FROM_DATABASE=SGS Taiwan Ltd. + +usb:v1A8D* + ID_VENDOR_FROM_DATABASE=BandRich, Inc. + +usb:v1A8Dp1002* + ID_MODEL_FROM_DATABASE=BandLuxe 3.5G HSDPA Adapter + +usb:v1A8Dp1009* + ID_MODEL_FROM_DATABASE=BandLuxe 3.5G HSPA Adapter + +usb:v1A8Dp100D* + ID_MODEL_FROM_DATABASE=4G LTE adapter + +usb:v1A98* + ID_VENDOR_FROM_DATABASE=Leica Camera AG + +usb:v1AA4* + ID_VENDOR_FROM_DATABASE=Data Drive Thru, Inc. + +usb:v1AA5* + ID_VENDOR_FROM_DATABASE=UBeacon Technologies, Inc. + +usb:v1AA6* + ID_VENDOR_FROM_DATABASE=eFortune Technology Corp. + +usb:v1AAD* + ID_VENDOR_FROM_DATABASE=KeeTouch + +usb:v1AADp0001* + ID_MODEL_FROM_DATABASE=Touchscreen + +usb:v1AB1* + ID_VENDOR_FROM_DATABASE=Rigol Technologies + +usb:v1AB1p0588* + ID_MODEL_FROM_DATABASE=DS1000 SERIES + +usb:v1ACB* + ID_VENDOR_FROM_DATABASE=Salcomp Plc + +usb:v1ACC* + ID_VENDOR_FROM_DATABASE=Midiplus Co, Ltd. + +usb:v1ACCp0103* + ID_MODEL_FROM_DATABASE=AudioLink plus 4x4 2.9.28 + +usb:v1AD1* + ID_VENDOR_FROM_DATABASE=Desay Wire Co., Ltd. + +usb:v1AD4* + ID_VENDOR_FROM_DATABASE=APS + +usb:v1AD4p0002* + ID_MODEL_FROM_DATABASE=KM290-HRS + +usb:v1ADB* + ID_VENDOR_FROM_DATABASE=SEL C662 Serial Cable + +usb:v1AE4* + ID_VENDOR_FROM_DATABASE=ic-design Reinhard Gottinger GmbH + +usb:v1AE7* + ID_VENDOR_FROM_DATABASE=X-TENSIONS + +usb:v1AE7p0381* + ID_MODEL_FROM_DATABASE=VS-DVB-T 380U (af9015 based) + +usb:v1AE7p2001* + ID_MODEL_FROM_DATABASE=SpeedLink Snappy Mic webcam (SL-6825-SBK) + +usb:v1AE7p9003* + ID_MODEL_FROM_DATABASE=SpeedLink Vicious And Devine Laplace webcam, white (VD-1504-SWT) + +usb:v1AE7p9004* + ID_MODEL_FROM_DATABASE=SpeedLink Vicious And Devine Laplace webcam, black (VD-1504-SBK) + +usb:v1AED* + ID_VENDOR_FROM_DATABASE=High Top Precision Electronic Co., Ltd. + +usb:v1AEF* + ID_VENDOR_FROM_DATABASE=Conntech Electronic (Suzhou) Corporation + +usb:v1AF1* + ID_VENDOR_FROM_DATABASE=Connect One Ltd. + +usb:v1AFE* + ID_VENDOR_FROM_DATABASE=A. Eberle GmbH & Co. KG + +usb:v1AFEp0001* + ID_MODEL_FROM_DATABASE=PQ Box 100 + +usb:v1B04* + ID_VENDOR_FROM_DATABASE=Meilhaus Electronic GmbH + +usb:v1B04p0630* + ID_MODEL_FROM_DATABASE=ME-630 + +usb:v1B04p0940* + ID_MODEL_FROM_DATABASE=ME-94 + +usb:v1B04p0950* + ID_MODEL_FROM_DATABASE=ME-95 + +usb:v1B04p0960* + ID_MODEL_FROM_DATABASE=ME-96 + +usb:v1B04p1000* + ID_MODEL_FROM_DATABASE=ME-1000 + +usb:v1B04p100A* + ID_MODEL_FROM_DATABASE=ME-1000 + +usb:v1B04p100B* + ID_MODEL_FROM_DATABASE=ME-1000 + +usb:v1B04p1400* + ID_MODEL_FROM_DATABASE=ME-1400 + +usb:v1B04p140A* + ID_MODEL_FROM_DATABASE=ME-1400A + +usb:v1B04p140B* + ID_MODEL_FROM_DATABASE=ME-1400B + +usb:v1B04p140C* + ID_MODEL_FROM_DATABASE=ME-1400C + +usb:v1B04p140D* + ID_MODEL_FROM_DATABASE=ME-1400D + +usb:v1B04p140E* + ID_MODEL_FROM_DATABASE=ME-1400E + +usb:v1B04p14EA* + ID_MODEL_FROM_DATABASE=ME-1400EA + +usb:v1B04p14EB* + ID_MODEL_FROM_DATABASE=ME-1400EB + +usb:v1B04p1604* + ID_MODEL_FROM_DATABASE=ME-1600/4U + +usb:v1B04p1608* + ID_MODEL_FROM_DATABASE=ME-1600/8U + +usb:v1B04p160C* + ID_MODEL_FROM_DATABASE=ME-1600/12U + +usb:v1B04p160F* + ID_MODEL_FROM_DATABASE=ME-1600/16U + +usb:v1B04p168F* + ID_MODEL_FROM_DATABASE=ME-1600/16U8I + +usb:v1B04p4610* + ID_MODEL_FROM_DATABASE=ME-4610 + +usb:v1B04p4650* + ID_MODEL_FROM_DATABASE=ME-4650 + +usb:v1B04p4660* + ID_MODEL_FROM_DATABASE=ME-4660 + +usb:v1B04p4661* + ID_MODEL_FROM_DATABASE=ME-4660I + +usb:v1B04p4662* + ID_MODEL_FROM_DATABASE=ME-4660 + +usb:v1B04p4663* + ID_MODEL_FROM_DATABASE=ME-4660I + +usb:v1B04p4670* + ID_MODEL_FROM_DATABASE=ME-4670 + +usb:v1B04p4671* + ID_MODEL_FROM_DATABASE=ME-4670I + +usb:v1B04p4672* + ID_MODEL_FROM_DATABASE=ME-4670S + +usb:v1B04p4673* + ID_MODEL_FROM_DATABASE=ME-4670IS + +usb:v1B04p4680* + ID_MODEL_FROM_DATABASE=ME-4680 + +usb:v1B04p4681* + ID_MODEL_FROM_DATABASE=ME-4680I + +usb:v1B04p4682* + ID_MODEL_FROM_DATABASE=ME-4680S + +usb:v1B04p4683* + ID_MODEL_FROM_DATABASE=ME-4680IS + +usb:v1B04p6004* + ID_MODEL_FROM_DATABASE=ME-6000/4 + +usb:v1B04p6008* + ID_MODEL_FROM_DATABASE=ME-6000/8 + +usb:v1B04p600F* + ID_MODEL_FROM_DATABASE=ME-6000/16 + +usb:v1B04p6014* + ID_MODEL_FROM_DATABASE=ME-6000I/4 + +usb:v1B04p6018* + ID_MODEL_FROM_DATABASE=ME-6000I/8 + +usb:v1B04p601F* + ID_MODEL_FROM_DATABASE=ME-6000I/16 + +usb:v1B04p6034* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/4 + +usb:v1B04p6038* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/8 + +usb:v1B04p603F* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/16 + +usb:v1B04p6044* + ID_MODEL_FROM_DATABASE=ME-6000/4/DIO + +usb:v1B04p6048* + ID_MODEL_FROM_DATABASE=ME-6000/8/DIO + +usb:v1B04p604F* + ID_MODEL_FROM_DATABASE=ME-6000/16/DIO + +usb:v1B04p6054* + ID_MODEL_FROM_DATABASE=ME-6000I/4/DIO + +usb:v1B04p6058* + ID_MODEL_FROM_DATABASE=ME-6000I/8/DIO + +usb:v1B04p605F* + ID_MODEL_FROM_DATABASE=ME-6000I/16/DIO + +usb:v1B04p6074* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/4/DIO + +usb:v1B04p6078* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/8/DIO + +usb:v1B04p607F* + ID_MODEL_FROM_DATABASE=ME-6000ISLE/16/DIO + +usb:v1B04p6104* + ID_MODEL_FROM_DATABASE=ME-6100/4 + +usb:v1B04p6108* + ID_MODEL_FROM_DATABASE=ME-6100/8 + +usb:v1B04p610F* + ID_MODEL_FROM_DATABASE=ME-6100/16 + +usb:v1B04p6114* + ID_MODEL_FROM_DATABASE=ME-6100I/4 + +usb:v1B04p6118* + ID_MODEL_FROM_DATABASE=ME-6100I/8 + +usb:v1B04p611F* + ID_MODEL_FROM_DATABASE=ME-6100I/16 + +usb:v1B04p6134* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/4 + +usb:v1B04p6138* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/8 + +usb:v1B04p613F* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/16 + +usb:v1B04p6144* + ID_MODEL_FROM_DATABASE=ME-6100/4/DIO + +usb:v1B04p6148* + ID_MODEL_FROM_DATABASE=ME-6100/8/DIO + +usb:v1B04p614F* + ID_MODEL_FROM_DATABASE=ME-6100/16/DIO + +usb:v1B04p6154* + ID_MODEL_FROM_DATABASE=ME-6100I/4/DIO + +usb:v1B04p6158* + ID_MODEL_FROM_DATABASE=ME-6100I/8/DIO + +usb:v1B04p615F* + ID_MODEL_FROM_DATABASE=ME-6100I/16/DIO + +usb:v1B04p6174* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/4/DIO + +usb:v1B04p6178* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/8/DIO + +usb:v1B04p617F* + ID_MODEL_FROM_DATABASE=ME-6100ISLE/16/DIO + +usb:v1B04p6259* + ID_MODEL_FROM_DATABASE=ME-6200I/9/DIO + +usb:v1B04p6359* + ID_MODEL_FROM_DATABASE=ME-6300I/9/DIO + +usb:v1B04p810A* + ID_MODEL_FROM_DATABASE=ME-8100A + +usb:v1B04p810B* + ID_MODEL_FROM_DATABASE=ME-8100B + +usb:v1B04p820A* + ID_MODEL_FROM_DATABASE=ME-8200A + +usb:v1B04p820B* + ID_MODEL_FROM_DATABASE=ME-8200B + +usb:v1B0E* + ID_VENDOR_FROM_DATABASE=BLUTRONICS S.r.l. + +usb:v1B0Ep1078* + ID_MODEL_FROM_DATABASE=BLUDRIVE II CCID + +usb:v1B0Ep1079* + ID_MODEL_FROM_DATABASE=BLUDRIVE II CCID + +usb:v1B0Ep1080* + ID_MODEL_FROM_DATABASE=WRITECHIP II CCID + +usb:v1B1C* + ID_VENDOR_FROM_DATABASE=Corsair + +usb:v1B1Cp0890* + ID_MODEL_FROM_DATABASE=Flash Padlock + +usb:v1B1Cp0A00* + ID_MODEL_FROM_DATABASE=SP2500 Speakers + +usb:v1B1Cp0A60* + ID_MODEL_FROM_DATABASE=Vengeance K60 Keyboard + +usb:v1B1Cp0C04* + ID_MODEL_FROM_DATABASE=Link Cooling Node + +usb:v1B1Cp1A01* + ID_MODEL_FROM_DATABASE=Flash Voyager GT + +usb:v1B1Cp1A03* + ID_MODEL_FROM_DATABASE=Voyager 3.0 + +usb:v1B1Cp1A09* + ID_MODEL_FROM_DATABASE=Voyager GT 3.0 + +usb:v1B1Cp1A0A* + ID_MODEL_FROM_DATABASE=Survivor Stealth Flash Drive + +usb:v1B1Cp1A0B* + ID_MODEL_FROM_DATABASE=Flash Voyager LS + +usb:v1B1Cp1A15* + ID_MODEL_FROM_DATABASE=Voyager Slider Flash Drive + +usb:v1B1Cp1A90* + ID_MODEL_FROM_DATABASE=Flash Voyager GT + +usb:v1B1Cp1AB1* + ID_MODEL_FROM_DATABASE=Voyager + +usb:v1B1Cp1B04* + ID_MODEL_FROM_DATABASE=Raptor K50 Keyboard + +usb:v1B1Cp1B07* + ID_MODEL_FROM_DATABASE=Vengeance K65 Gaming Keyboard + +usb:v1B1Cp1B08* + ID_MODEL_FROM_DATABASE=Vengeance K95 Keyboard + +usb:v1B1Cp1B09* + ID_MODEL_FROM_DATABASE=Vengeance K70R keyboard + +usb:v1B1Cp1B11* + ID_MODEL_FROM_DATABASE=K95 RGB Mechanical Gaming Keyboard + +usb:v1B1Cp1B13* + ID_MODEL_FROM_DATABASE=Vengeance K70RGB keyboard + +usb:v1B1Cp1C00* + ID_MODEL_FROM_DATABASE=Controller for Corsair Link + +usb:v1B1Cp1C0C* + ID_MODEL_FROM_DATABASE=RM850i Power Supply + +usb:v1B1F* + ID_VENDOR_FROM_DATABASE=eQ-3 Entwicklung GmbH + +usb:v1B1FpC00F* + ID_MODEL_FROM_DATABASE=HM-CFG-USB/HM-CFG-USB-2 [HomeMatic Configuration adapter] + +usb:v1B20* + ID_VENDOR_FROM_DATABASE=MStar Semiconductor, Inc. + +usb:v1B22* + ID_VENDOR_FROM_DATABASE=WiLinx Corp. + +usb:v1B26* + ID_VENDOR_FROM_DATABASE=Cellex Power Products, Inc. + +usb:v1B27* + ID_VENDOR_FROM_DATABASE=Current Electronics Inc. + +usb:v1B28* + ID_VENDOR_FROM_DATABASE=NAVIsis Inc. + +usb:v1B32* + ID_VENDOR_FROM_DATABASE=Ugobe Life Forms, Inc. + +usb:v1B32p0064* + ID_MODEL_FROM_DATABASE=Pleo robotic dinosaur + +usb:v1B36* + ID_VENDOR_FROM_DATABASE=ViXS Systems, Inc. + +usb:v1B3B* + ID_VENDOR_FROM_DATABASE=iPassion Technology Inc. + +usb:v1B3Bp2933* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2935* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2936* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2937* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2938* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2939* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2950* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2951* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2952* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2953* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2955* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2956* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2957* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2958* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2959* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2960* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2961* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2962* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2963* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2965* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2966* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2967* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2968* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3Bp2969* + ID_MODEL_FROM_DATABASE=PC Camera/Webcam controller + +usb:v1B3F* + ID_VENDOR_FROM_DATABASE=Generalplus Technology Inc. + +usb:v1B3Fp0C52* + ID_MODEL_FROM_DATABASE=808 Camera #9 (mass storage mode) + +usb:v1B3Fp2002* + ID_MODEL_FROM_DATABASE=808 Camera #9 (web-cam mode) + +usb:v1B47* + ID_VENDOR_FROM_DATABASE=Energizer Holdings, Inc. + +usb:v1B47p0001* + ID_MODEL_FROM_DATABASE=CHUSB Duo Charger (NiMH AA/AAA USB smart charger) + +usb:v1B48* + ID_VENDOR_FROM_DATABASE=Plastron Precision Co., Ltd. + +usb:v1B52* + ID_VENDOR_FROM_DATABASE=ARH Inc. + +usb:v1B52p2101* + ID_MODEL_FROM_DATABASE=FXMC Neural Network Controller + +usb:v1B52p2102* + ID_MODEL_FROM_DATABASE=FXMC Neural Network Controller V2 + +usb:v1B52p2103* + ID_MODEL_FROM_DATABASE=FXMC Neural Network Controller V3 + +usb:v1B52p4101* + ID_MODEL_FROM_DATABASE=Passport Reader CLR device + +usb:v1B52p4201* + ID_MODEL_FROM_DATABASE=Passport Reader PRM device + +usb:v1B52p4202* + ID_MODEL_FROM_DATABASE=Passport Reader PRM extension device + +usb:v1B52p4203* + ID_MODEL_FROM_DATABASE=Passport Reader PRM DSP device + +usb:v1B52p4204* + ID_MODEL_FROM_DATABASE=Passport Reader PRMC device + +usb:v1B52p4205* + ID_MODEL_FROM_DATABASE=Passport Reader CSHR device + +usb:v1B52p4206* + ID_MODEL_FROM_DATABASE=Passport Reader PRMC V2 device + +usb:v1B52p4301* + ID_MODEL_FROM_DATABASE=Passport Reader MRZ device + +usb:v1B52p4302* + ID_MODEL_FROM_DATABASE=Passport Reader MRZ DSP device + +usb:v1B52p4303* + ID_MODEL_FROM_DATABASE=Passport Reader CSLR device + +usb:v1B52p4401* + ID_MODEL_FROM_DATABASE=Card Reader + +usb:v1B52p4501* + ID_MODEL_FROM_DATABASE=Passport Reader RFID device + +usb:v1B52p4502* + ID_MODEL_FROM_DATABASE=Passport Reader RFID AIG device + +usb:v1B52p6101* + ID_MODEL_FROM_DATABASE=Neural Network Controller + +usb:v1B52p6202* + ID_MODEL_FROM_DATABASE=Fingerprint Reader device + +usb:v1B52p6203* + ID_MODEL_FROM_DATABASE=Fingerprint Scanner device + +usb:v1B52p8101* + ID_MODEL_FROM_DATABASE=Camera V1 + +usb:v1B52p8102* + ID_MODEL_FROM_DATABASE=Recovery / Camera V2 + +usb:v1B52p8103* + ID_MODEL_FROM_DATABASE=Camera V3 + +usb:v1B59* + ID_VENDOR_FROM_DATABASE=K.S. Terminals Inc. + +usb:v1B5A* + ID_VENDOR_FROM_DATABASE=Chao Zhou Kai Yuan Electric Co., Ltd. + +usb:v1B65* + ID_VENDOR_FROM_DATABASE=The Hong Kong Standards and Testing Centre Ltd. + +usb:v1B71* + ID_VENDOR_FROM_DATABASE=Fushicai + +usb:v1B71p3002* + ID_MODEL_FROM_DATABASE=USBTV007 Video Grabber [EasyCAP] + +usb:v1B72* + ID_VENDOR_FROM_DATABASE=ATERGI TECHNOLOGY CO., LTD. + +usb:v1B73* + ID_VENDOR_FROM_DATABASE=Fresco Logic + +usb:v1B73p1000* + ID_MODEL_FROM_DATABASE=xHC1 Controller + +usb:v1B75* + ID_VENDOR_FROM_DATABASE=Ovislink Corp. + +usb:v1B75p3072* + ID_MODEL_FROM_DATABASE=AirLive WN-360USB adapter + +usb:v1B75p8171* + ID_MODEL_FROM_DATABASE=WN-370USB 802.11bgn Wireless Adapter [Realtek RTL8188SU] + +usb:v1B75p8187* + ID_MODEL_FROM_DATABASE=AirLive WL-1600USB 802.11g Adapter [Realtek RTL8187L] + +usb:v1B75p9170* + ID_MODEL_FROM_DATABASE=AirLive X.USB 802.11abgn [Atheros AR9170+AR9104] + +usb:v1B75pA200* + ID_MODEL_FROM_DATABASE=AirLive WN-200USB wireless 11b/g/n dongle + +usb:v1B76* + ID_VENDOR_FROM_DATABASE=Legend Silicon Corp. + +usb:v1B80* + ID_VENDOR_FROM_DATABASE=Afatech + +usb:v1B80pC810* + ID_MODEL_FROM_DATABASE=MC810 [af9015] + +usb:v1B80pD393* + ID_MODEL_FROM_DATABASE=DVB-T receiver [RTL2832U] + +usb:v1B80pD396* + ID_MODEL_FROM_DATABASE=UB396-T [RTL2832U] + +usb:v1B80pD397* + ID_MODEL_FROM_DATABASE=DVB-T receiver [RTL2832U] + +usb:v1B80pD398* + ID_MODEL_FROM_DATABASE=DVB-T receiver [RTL2832U] + +usb:v1B80pD700* + ID_MODEL_FROM_DATABASE=FM Radio SnapMusic Mobile 700 (FM700) + +usb:v1B80pE297* + ID_MODEL_FROM_DATABASE=Conceptronic DVB-T CTVDIGRCU V3.0 + +usb:v1B80pE383* + ID_MODEL_FROM_DATABASE=DVB-T UB383-T [af9015] + +usb:v1B80pE385* + ID_MODEL_FROM_DATABASE=DVB-T UB385-T [af9015] + +usb:v1B80pE386* + ID_MODEL_FROM_DATABASE=DVB-T UB385-T [af9015] + +usb:v1B80pE399* + ID_MODEL_FROM_DATABASE=DVB-T KWorld PlusTV 399U [af9015] + +usb:v1B80pE39A* + ID_MODEL_FROM_DATABASE=DVB-T395U [af9015] + +usb:v1B80pE39B* + ID_MODEL_FROM_DATABASE=DVB-T395U [af9015] + +usb:v1B80pE401* + ID_MODEL_FROM_DATABASE=Sveon STV22 DVB-T [af9015] + +usb:v1B80pE409* + ID_MODEL_FROM_DATABASE=IT9137FN Dual DVB-T [KWorld UB499-2T] + +usb:v1B86* + ID_VENDOR_FROM_DATABASE=Dongguan Guanshang Electronics Co., Ltd. + +usb:v1B88* + ID_VENDOR_FROM_DATABASE=ShenMing Electron (Dong Guan) Co., Ltd. + +usb:v1B8C* + ID_VENDOR_FROM_DATABASE=Altium Limited + +usb:v1B8D* + ID_VENDOR_FROM_DATABASE=e-MOVE Technology Co., Ltd. + +usb:v1B8E* + ID_VENDOR_FROM_DATABASE=Amlogic, Inc. + +usb:v1B8F* + ID_VENDOR_FROM_DATABASE=MA LABS, Inc. + +usb:v1B96* + ID_VENDOR_FROM_DATABASE=N-Trig + +usb:v1B96p0001* + ID_MODEL_FROM_DATABASE=Duosense Transparent Electromagnetic Digitizer + +usb:v1B98* + ID_VENDOR_FROM_DATABASE=YMax Communications Corp. + +usb:v1B99* + ID_VENDOR_FROM_DATABASE=Shenzhen Yuanchuan Electronic + +usb:v1BA1* + ID_VENDOR_FROM_DATABASE=JINQ CHERN ENTERPRISE CO., LTD. + +usb:v1BA2* + ID_VENDOR_FROM_DATABASE=Lite Metals & Plastic (Shenzhen) Co., Ltd. + +usb:v1BA4* + ID_VENDOR_FROM_DATABASE=Ember Corporation + +usb:v1BA4p0001* + ID_MODEL_FROM_DATABASE=InSight USB Link + +usb:v1BA6* + ID_VENDOR_FROM_DATABASE=Abilis Systems + +usb:v1BA8* + ID_VENDOR_FROM_DATABASE=China Telecommunication Technology Labs + +usb:v1BAD* + ID_VENDOR_FROM_DATABASE=Harmonix Music + +usb:v1BADp0002* + ID_MODEL_FROM_DATABASE=Guitar for Xbox 360 + +usb:v1BADp0003* + ID_MODEL_FROM_DATABASE=Drum Kit for Xbox 360 + +usb:v1BAE* + ID_VENDOR_FROM_DATABASE=Vuzix Corporation + +usb:v1BAEp0002* + ID_MODEL_FROM_DATABASE=VR920 Immersive Eyewear + +usb:v1BBB* + ID_VENDOR_FROM_DATABASE=T & A Mobile Phones + +usb:v1BBBp011E* + ID_MODEL_FROM_DATABASE=Alcatel One Touch L100V / Telekom Speedstick LTE II + +usb:v1BBBpF017* + ID_MODEL_FROM_DATABASE=Alcatel One Touch L100V / Telekom Speedstick LTE II + +usb:v1BC4* + ID_VENDOR_FROM_DATABASE=Ford Motor Co. + +usb:v1BC5* + ID_VENDOR_FROM_DATABASE=AVIXE Technology (China) Ltd. + +usb:v1BC7* + ID_VENDOR_FROM_DATABASE=Telit Wireless Solutions + +usb:v1BC7p0020* + ID_MODEL_FROM_DATABASE=HE863 + +usb:v1BC7p0021* + ID_MODEL_FROM_DATABASE=HE910 + +usb:v1BC7p0023* + ID_MODEL_FROM_DATABASE=HE910-D ECM + +usb:v1BC7p1003* + ID_MODEL_FROM_DATABASE=UC864-E + +usb:v1BC7p1004* + ID_MODEL_FROM_DATABASE=UC864-G + +usb:v1BC7p1005* + ID_MODEL_FROM_DATABASE=CC864-DUAL + +usb:v1BC7p1006* + ID_MODEL_FROM_DATABASE=CC864-SINGLE + +usb:v1BC7p1010* + ID_MODEL_FROM_DATABASE=DE910-DUAL + +usb:v1BC7p1011* + ID_MODEL_FROM_DATABASE=CE910-DUAL + +usb:v1BC7p1200* + ID_MODEL_FROM_DATABASE=LE920 + +usb:v1BCE* + ID_VENDOR_FROM_DATABASE=Contac Cable Industrial Limited + +usb:v1BCF* + ID_VENDOR_FROM_DATABASE=Sunplus Innovation Technology Inc. + +usb:v1BCFp0005* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v1BCFp0007* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v1BCFp053A* + ID_MODEL_FROM_DATABASE=Targa Silvercrest OMC807-C optische Funkmaus + +usb:v1BCFp05C5* + ID_MODEL_FROM_DATABASE=SPRF2413A [2.4GHz Wireless Keyboard/Mouse Receiver] + +usb:v1BCFp05CF* + ID_MODEL_FROM_DATABASE=Micro keyboard & mouse receiver + +usb:v1BCFp0C31* + ID_MODEL_FROM_DATABASE=SPIF30x Serial-ATA bridge + +usb:v1BCFp2880* + ID_MODEL_FROM_DATABASE=Dell HD Webcam + +usb:v1BCFp2885* + ID_MODEL_FROM_DATABASE=ASUS Webcam + +usb:v1BCFp2888* + ID_MODEL_FROM_DATABASE=HP Universal Camera + +usb:v1BCFp28A2* + ID_MODEL_FROM_DATABASE=Dell Integrated Webcam + +usb:v1BCFp28A6* + ID_MODEL_FROM_DATABASE=DELL XPS Integrated Webcam + +usb:v1BCFp28AE* + ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam HD + +usb:v1BCFp28BD* + ID_MODEL_FROM_DATABASE=Dell Integrated HD Webcam + +usb:v1BCFp2985* + ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam HD + +usb:v1BCFp2B83* + ID_MODEL_FROM_DATABASE=Laptop Integrated Webcam FHD + +usb:v1BD0* + ID_VENDOR_FROM_DATABASE=Hangzhou Riyue Electronic Co., Ltd. + +usb:v1BD5* + ID_VENDOR_FROM_DATABASE=BG Systems, Inc. + +usb:v1BDE* + ID_VENDOR_FROM_DATABASE=P-TWO INDUSTRIES, INC. + +usb:v1BEF* + ID_VENDOR_FROM_DATABASE=Shenzhen Tongyuan Network-Communication Cables Co., Ltd + +usb:v1BF0* + ID_VENDOR_FROM_DATABASE=RealVision Inc. + +usb:v1BF5* + ID_VENDOR_FROM_DATABASE=Extranet Systems Inc. + +usb:v1BF6* + ID_VENDOR_FROM_DATABASE=Orient Semiconductor Electronics, Ltd. + +usb:v1BFD* + ID_VENDOR_FROM_DATABASE=TouchPack + +usb:v1BFDp1268* + ID_MODEL_FROM_DATABASE=Touch Screen + +usb:v1BFDp1368* + ID_MODEL_FROM_DATABASE=Touch Screen + +usb:v1BFDp1568* + ID_MODEL_FROM_DATABASE=Capacitive Touch Screen + +usb:v1BFDp1668* + ID_MODEL_FROM_DATABASE=IR Touch Screen + +usb:v1BFDp1688* + ID_MODEL_FROM_DATABASE=Resistive Touch Screen + +usb:v1BFDp2968* + ID_MODEL_FROM_DATABASE=Touch Screen + +usb:v1BFDp5968* + ID_MODEL_FROM_DATABASE=Touch Screen + +usb:v1BFDp6968* + ID_MODEL_FROM_DATABASE=Touch Screen + +usb:v1C02* + ID_VENDOR_FROM_DATABASE=Kreton Corporation + +usb:v1C04* + ID_VENDOR_FROM_DATABASE=QNAP System Inc. + +usb:v1C0C* + ID_VENDOR_FROM_DATABASE=Ionics EMS, Inc. + +usb:v1C0Cp0102* + ID_MODEL_FROM_DATABASE=Plug Computer + +usb:v1C0D* + ID_VENDOR_FROM_DATABASE=Relm Wireless + +usb:v1C10* + ID_VENDOR_FROM_DATABASE=Lanterra Industrial Co., Ltd. + +usb:v1C13* + ID_VENDOR_FROM_DATABASE=ALECTRONIC LIMITED + +usb:v1C1A* + ID_VENDOR_FROM_DATABASE=Datel Electronics Ltd. + +usb:v1C1B* + ID_VENDOR_FROM_DATABASE=Volkswagen of America, Inc. + +usb:v1C1F* + ID_VENDOR_FROM_DATABASE=Goldvish S.A. + +usb:v1C20* + ID_VENDOR_FROM_DATABASE=Fuji Electric Device Technology Co., Ltd. + +usb:v1C21* + ID_VENDOR_FROM_DATABASE=ADDMM LLC + +usb:v1C22* + ID_VENDOR_FROM_DATABASE=ZHONGSHAN CHIANG YU ELECTRIC CO., LTD. + +usb:v1C26* + ID_VENDOR_FROM_DATABASE=Shanghai Haiying Electronics Co., Ltd. + +usb:v1C27* + ID_VENDOR_FROM_DATABASE=HuiYang D & S Cable Co., Ltd. + +usb:v1C29* + ID_VENDOR_FROM_DATABASE=Elster GmbH + +usb:v1C29p0001* + ID_MODEL_FROM_DATABASE=ExMFE5 Simulator + +usb:v1C29p10FC* + ID_MODEL_FROM_DATABASE=enCore device + +usb:v1C31* + ID_VENDOR_FROM_DATABASE=LS Cable Ltd. + +usb:v1C34* + ID_VENDOR_FROM_DATABASE=SpringCard + +usb:v1C34p7241* + ID_MODEL_FROM_DATABASE=Prox'N'Roll RFID Scanner + +usb:v1C37* + ID_VENDOR_FROM_DATABASE=Authorizer Technologies, Inc. + +usb:v1C3D* + ID_VENDOR_FROM_DATABASE=NONIN MEDICAL INC. + +usb:v1C3E* + ID_VENDOR_FROM_DATABASE=Wep Peripherals + +usb:v1C40* + ID_VENDOR_FROM_DATABASE=EZPrototypes + +usb:v1C40p0533* + ID_MODEL_FROM_DATABASE=TiltStick + +usb:v1C40p0534* + ID_MODEL_FROM_DATABASE=i2c-tiny-usb interface + +usb:v1C40p0535* + ID_MODEL_FROM_DATABASE=glcd2usb interface + +usb:v1C40p0536* + ID_MODEL_FROM_DATABASE=Swiss ColorPAL + +usb:v1C49* + ID_VENDOR_FROM_DATABASE=Cherng Weei Technology Corp. + +usb:v1C4F* + ID_VENDOR_FROM_DATABASE=SiGma Micro + +usb:v1C4Fp0002* + ID_MODEL_FROM_DATABASE=Keyboard TRACER Gamma Ivory + +usb:v1C4Fp0003* + ID_MODEL_FROM_DATABASE=HID controller + +usb:v1C4Fp000E* + ID_MODEL_FROM_DATABASE=Genius KB-120 Keyboard + +usb:v1C4Fp0026* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v1C4Fp3000* + ID_MODEL_FROM_DATABASE=Micro USB Web Camera + +usb:v1C4Fp3002* + ID_MODEL_FROM_DATABASE=WebCam SiGma Micro + +usb:v1C6B* + ID_VENDOR_FROM_DATABASE=Philips & Lite-ON Digital Solutions Corporation + +usb:v1C6BpA222* + ID_MODEL_FROM_DATABASE=DVD Writer Slimtype eTAU108 + +usb:v1C6C* + ID_VENDOR_FROM_DATABASE=Skydigital Inc. + +usb:v1C73* + ID_VENDOR_FROM_DATABASE=AMT + +usb:v1C73p861F* + ID_MODEL_FROM_DATABASE=Anysee E30 USB 2.0 DVB-T Receiver + +usb:v1C77* + ID_VENDOR_FROM_DATABASE=Kaetat Industrial Co., Ltd. + +usb:v1C78* + ID_VENDOR_FROM_DATABASE=Datascope Corp. + +usb:v1C79* + ID_VENDOR_FROM_DATABASE=Unigen Corporation + +usb:v1C7A* + ID_VENDOR_FROM_DATABASE=LighTuning Technology Inc. + +usb:v1C7Ap0801* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v1C7B* + ID_VENDOR_FROM_DATABASE=LUXSHARE PRECISION INDUSTRY (SHENZHEN) CO., LTD. + +usb:v1C83* + ID_VENDOR_FROM_DATABASE=Schomaecker GmbH + +usb:v1C83p0001* + ID_MODEL_FROM_DATABASE=RS150 V2 + +usb:v1C87* + ID_VENDOR_FROM_DATABASE=2N TELEKOMUNIKACE a.s. + +usb:v1C88* + ID_VENDOR_FROM_DATABASE=Somagic, Inc. + +usb:v1C88p0007* + ID_MODEL_FROM_DATABASE=SMI Grabber (EasyCAP DC60+ clone) (no firmware) [SMI-2021CBE] + +usb:v1C88p003C* + ID_MODEL_FROM_DATABASE=SMI Grabber (EasyCAP DC60+ clone) [SMI-2021CBE] + +usb:v1C89* + ID_VENDOR_FROM_DATABASE=HONGKONG WEIDIDA ELECTRON LIMITED + +usb:v1C8E* + ID_VENDOR_FROM_DATABASE=ASTRON INTERNATIONAL CORP. + +usb:v1C98* + ID_VENDOR_FROM_DATABASE=ALPINE ELECTRONICS, INC. + +usb:v1C9E* + ID_VENDOR_FROM_DATABASE=OMEGA TECHNOLOGY + +usb:v1C9Ep6061* + ID_MODEL_FROM_DATABASE=WL-72B 3.5G MODEM + +usb:v1CA0* + ID_VENDOR_FROM_DATABASE=ACCARIO Inc. + +usb:v1CA1* + ID_VENDOR_FROM_DATABASE=Symwave + +usb:v1CA1p18AB* + ID_MODEL_FROM_DATABASE=SATA bridge + +usb:v1CAC* + ID_VENDOR_FROM_DATABASE=Kinstone + +usb:v1CACpA332* + ID_MODEL_FROM_DATABASE=C8 Webcam + +usb:v1CACpB288* + ID_MODEL_FROM_DATABASE=C18 Webcam + +usb:v1CB3* + ID_VENDOR_FROM_DATABASE=Aces Electronic Co., Ltd. + +usb:v1CB4* + ID_VENDOR_FROM_DATABASE=OPEX CORPORATION + +usb:v1CB6* + ID_VENDOR_FROM_DATABASE=IdeaCom Technology Inc. + +usb:v1CB6p6681* + ID_MODEL_FROM_DATABASE=IDC6681 + +usb:v1CBE* + ID_VENDOR_FROM_DATABASE=Luminary Micro Inc. + +usb:v1CBEp00FD* + ID_MODEL_FROM_DATABASE=In-Circuit Debug Interface + +usb:v1CBEp00FF* + ID_MODEL_FROM_DATABASE=Stellaris ROM DFU Bootloader + +usb:v1CBEp0166* + ID_MODEL_FROM_DATABASE=CANAL USB2CAN + +usb:v1CBF* + ID_VENDOR_FROM_DATABASE=FORTAT SKYMARK INDUSTRIAL COMPANY + +usb:v1CC0* + ID_VENDOR_FROM_DATABASE=PlantSense + +usb:v1CCA* + ID_VENDOR_FROM_DATABASE=NextWave Broadband Inc. + +usb:v1CCD* + ID_VENDOR_FROM_DATABASE=Bodatong Technology (Shenzhen) Co., Ltd. + +usb:v1CD4* + ID_VENDOR_FROM_DATABASE=adp corporation + +usb:v1CD5* + ID_VENDOR_FROM_DATABASE=Firecomms Ltd. + +usb:v1CD6* + ID_VENDOR_FROM_DATABASE=Antonio Precise Products Manufactory Ltd. + +usb:v1CDE* + ID_VENDOR_FROM_DATABASE=Telecommunications Technology Association (TTA) + +usb:v1CDF* + ID_VENDOR_FROM_DATABASE=WonTen Technology Co., Ltd. + +usb:v1CE0* + ID_VENDOR_FROM_DATABASE=EDIMAX TECHNOLOGY CO., LTD. + +usb:v1CE1* + ID_VENDOR_FROM_DATABASE=Amphenol KAE + +usb:v1CF1* + ID_VENDOR_FROM_DATABASE=Dresden Elektronik + +usb:v1CF1p0001* + ID_MODEL_FROM_DATABASE=Sensor Terminal Board + +usb:v1CF1p0004* + ID_MODEL_FROM_DATABASE=Wireless Handheld Terminal + +usb:v1CF1p0017* + ID_MODEL_FROM_DATABASE=deRFusbSniffer 2.4 GHz + +usb:v1CF1p0018* + ID_MODEL_FROM_DATABASE=deRFusb24E001 + +usb:v1CF1p0019* + ID_MODEL_FROM_DATABASE=deRFusb14E001 + +usb:v1CF1p001A* + ID_MODEL_FROM_DATABASE=deRFusb23E00 + +usb:v1CF1p001B* + ID_MODEL_FROM_DATABASE=deRFusb13E00 + +usb:v1CF1p001C* + ID_MODEL_FROM_DATABASE=deRFnode + +usb:v1CF1p001D* + ID_MODEL_FROM_DATABASE=deRFnode / gateway + +usb:v1CF1p0022* + ID_MODEL_FROM_DATABASE=deUSB level shifter + +usb:v1CF1p0023* + ID_MODEL_FROM_DATABASE=deRFusbSniffer Sub-GHz + +usb:v1CF1p0025* + ID_MODEL_FROM_DATABASE=deRFusb23E06 + +usb:v1CF1p0027* + ID_MODEL_FROM_DATABASE=deRFusb13E06 + +usb:v1CFC* + ID_VENDOR_FROM_DATABASE=ANDES TECHNOLOGY CORPORATION + +usb:v1CFD* + ID_VENDOR_FROM_DATABASE=Flextronics Digital Design Japan, LTD. + +usb:v1D03* + ID_VENDOR_FROM_DATABASE=iCON + +usb:v1D03p0028* + ID_MODEL_FROM_DATABASE=iCreativ MIDI Controller + +usb:v1D07* + ID_VENDOR_FROM_DATABASE=Solid-Motion + +usb:v1D08* + ID_VENDOR_FROM_DATABASE=NINGBO HENTEK DRAGON ELECTRONICS CO., LTD. + +usb:v1D09* + ID_VENDOR_FROM_DATABASE=TechFaith Wireless Technology Limited + +usb:v1D09p1026* + ID_MODEL_FROM_DATABASE=HSUPA Modem FLYING-LARK46-VER0.07 [Flying Angel] + +usb:v1D0A* + ID_VENDOR_FROM_DATABASE=Johnson Controls, Inc. The Automotive Business Unit + +usb:v1D0B* + ID_VENDOR_FROM_DATABASE=HAN HUA CABLE & WIRE TECHNOLOGY (J.X.) CO., LTD. + +usb:v1D0F* + ID_VENDOR_FROM_DATABASE=Sonix Technology Co., Ltd. + +usb:v1D14* + ID_VENDOR_FROM_DATABASE=ALPHA-SAT TECHNOLOGY LIMITED + +usb:v1D17* + ID_VENDOR_FROM_DATABASE=C-Thru Music Ltd. + +usb:v1D17p0001* + ID_MODEL_FROM_DATABASE=AXiS-49 Harmonic Table MIDI Keyboard + +usb:v1D19* + ID_VENDOR_FROM_DATABASE=Dexatek Technology Ltd. + +usb:v1D19p1101* + ID_MODEL_FROM_DATABASE=DK DVB-T Dongle + +usb:v1D19p1102* + ID_MODEL_FROM_DATABASE=DK mini DVB-T Dongle + +usb:v1D19p1103* + ID_MODEL_FROM_DATABASE=DK 5217 DVB-T Dongle + +usb:v1D19p6105* + ID_MODEL_FROM_DATABASE=Video grabber + +usb:v1D19p8202* + ID_MODEL_FROM_DATABASE=DK DVBC/T DONGLE + +usb:v1D1F* + ID_VENDOR_FROM_DATABASE=Diostech Co., Ltd. + +usb:v1D20* + ID_VENDOR_FROM_DATABASE=SAMTACK INC. + +usb:v1D27* + ID_VENDOR_FROM_DATABASE=ASUS + +usb:v1D34* + ID_VENDOR_FROM_DATABASE=Dream Cheeky + +usb:v1D34p0001* + ID_MODEL_FROM_DATABASE=Dream Cheeky Fidget + +usb:v1D34p0004* + ID_MODEL_FROM_DATABASE=Dream Cheeky Webmail Notifier + +usb:v1D34p0008* + ID_MODEL_FROM_DATABASE=Dream Cheeky button + +usb:v1D34p000A* + ID_MODEL_FROM_DATABASE=Dream Cheeky Mailbox Friends Alert + +usb:v1D34p000D* + ID_MODEL_FROM_DATABASE=Dream Cheeky Big Red Button + +usb:v1D34p0013* + ID_MODEL_FROM_DATABASE=Dream Cheeky LED Message Board + +usb:v1D45* + ID_VENDOR_FROM_DATABASE=Touch + +usb:v1D45p1D45* + ID_MODEL_FROM_DATABASE=Foxlink Optical touch sensor + +usb:v1D4D* + ID_VENDOR_FROM_DATABASE=PEGATRON CORPORATION + +usb:v1D4Dp0002* + ID_MODEL_FROM_DATABASE=Ralink RT2770/2720 802.11b/g/n Wireless LAN Mini-USB Device + +usb:v1D4Dp000C* + ID_MODEL_FROM_DATABASE=Ralink RT3070 802.11b/g/n Wireless Lan USB Device + +usb:v1D4Dp000E* + ID_MODEL_FROM_DATABASE=Ralink RT3070 802.11b/g/n Wireless Lan USB Device + +usb:v1D50* + ID_VENDOR_FROM_DATABASE=OpenMoko, Inc. + +usb:v1D50p1DB5* + ID_MODEL_FROM_DATABASE=IDBG (DFU) + +usb:v1D50p1DB6* + ID_MODEL_FROM_DATABASE=IDBG + +usb:v1D50p5117* + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner kernel usbnet (g_ether, CDC Ethernet) mode + +usb:v1D50p5118* + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner Debug board (V2+) + +usb:v1D50p5119* + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner u-boot cdc_acm serial port + +usb:v1D50p511A* + ID_MODEL_FROM_DATABASE=HXD8 u-boot usbtty CDC ACM Mode + +usb:v1D50p511B* + ID_MODEL_FROM_DATABASE=SMDK2440 u-boot usbtty CDC ACM mode + +usb:v1D50p511C* + ID_MODEL_FROM_DATABASE=SMDK2443 u-boot usbtty CDC ACM mode + +usb:v1D50p511D* + ID_MODEL_FROM_DATABASE=QT2410 u-boot usbtty CDC ACM mode + +usb:v1D50p5120* + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner u-boot usbtty generic serial + +usb:v1D50p5121* + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner kernel mass storage (g_storage) mode + +usb:v1D50p5122* + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner kernel cdc_ether USB network + +usb:v1D50p5123* + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner internal USB CSR4 module + +usb:v1D50p5124* + ID_MODEL_FROM_DATABASE=Neo1973/FreeRunner Bluetooth Device ID service + +usb:v1D50p5300* + ID_MODEL_FROM_DATABASE=Rockbox + +usb:v1D50p6000* + ID_MODEL_FROM_DATABASE=Ubertooth Zero + +usb:v1D50p6001* + ID_MODEL_FROM_DATABASE=Ubertooth Zero (DFU) + +usb:v1D50p6002* + ID_MODEL_FROM_DATABASE=Ubertooth One + +usb:v1D50p6003* + ID_MODEL_FROM_DATABASE=Ubertooth One (DFU) + +usb:v1D50p6004* + ID_MODEL_FROM_DATABASE=LeoLipo + +usb:v1D50p6005* + ID_MODEL_FROM_DATABASE=LED Flower S + +usb:v1D50p6006* + ID_MODEL_FROM_DATABASE=LED Cube + +usb:v1D50p6007* + ID_MODEL_FROM_DATABASE=LED Flower + +usb:v1D50p6008* + ID_MODEL_FROM_DATABASE=Kisbee 802.15.4 transceiver + +usb:v1D50p6009* + ID_MODEL_FROM_DATABASE=Adjacent Reality Tracker + +usb:v1D50p600A* + ID_MODEL_FROM_DATABASE=AVR Programmer + +usb:v1D50p600B* + ID_MODEL_FROM_DATABASE=Hypna Go Go + +usb:v1D50p600C* + ID_MODEL_FROM_DATABASE=CatNip LPC1343 development board + +usb:v1D50p600D* + ID_MODEL_FROM_DATABASE=Enhanced RoboBrrd Brain board + +usb:v1D50p600E* + ID_MODEL_FROM_DATABASE=OpenRISC Ordb2a-ep4ce22 development board + +usb:v1D50p600F* + ID_MODEL_FROM_DATABASE=Paparazzi Lisa/M (DFU) + +usb:v1D50p6010* + ID_MODEL_FROM_DATABASE=OpenPipe: OSHW Bagpipes MIDI controller + +usb:v1D50p6011* + ID_MODEL_FROM_DATABASE=LeoLipo (DFU) + +usb:v1D50p6012* + ID_MODEL_FROM_DATABASE=Universal C64 Cartridge + +usb:v1D50p6013* + ID_MODEL_FROM_DATABASE=DiscFerret magnetic disc analyser (bootloader) + +usb:v1D50p6014* + ID_MODEL_FROM_DATABASE=DiscFerret magnetic disc analyser + +usb:v1D50p6015* + ID_MODEL_FROM_DATABASE=Smoothieboard + +usb:v1D50p6016* + ID_MODEL_FROM_DATABASE=phInterface + +usb:v1D50p6017* + ID_MODEL_FROM_DATABASE=Black Magic Debug Probe (DFU) + +usb:v1D50p6018* + ID_MODEL_FROM_DATABASE=Black Magic Debug Probe (Application) + +usb:v1D50p6019* + ID_MODEL_FROM_DATABASE=4pi 5 axis motion controller + +usb:v1D50p601A* + ID_MODEL_FROM_DATABASE=Paparazzi Lisa/M + +usb:v1D50p601B* + ID_MODEL_FROM_DATABASE=IST-2 chronograph for bullet speeds + +usb:v1D50p601C* + ID_MODEL_FROM_DATABASE=EPOSMote II + +usb:v1D50p601E* + ID_MODEL_FROM_DATABASE=5x5 STM32 prototyping board + +usb:v1D50p601F* + ID_MODEL_FROM_DATABASE=uNSF + +usb:v1D50p6020* + ID_MODEL_FROM_DATABASE=Toad3 + +usb:v1D50p6021* + ID_MODEL_FROM_DATABASE=AlphaSphere + +usb:v1D50p6022* + ID_MODEL_FROM_DATABASE=LightPack + +usb:v1D50p6023* + ID_MODEL_FROM_DATABASE=Pixelkit + +usb:v1D50p6024* + ID_MODEL_FROM_DATABASE=Illucia + +usb:v1D50p6025* + ID_MODEL_FROM_DATABASE=Keyglove (HID) + +usb:v1D50p6027* + ID_MODEL_FROM_DATABASE=Key64 Keyboard + +usb:v1D50p6028* + ID_MODEL_FROM_DATABASE=Teensy 2.0 Development Board [ErgoDox Keyboard] + +usb:v1D50p602A* + ID_MODEL_FROM_DATABASE=Marlin 2.0 (Mass Storage) + +usb:v1D50p602B* + ID_MODEL_FROM_DATABASE=FPGALink + +usb:v1D50p602C* + ID_MODEL_FROM_DATABASE=5nes5snes (5x8) + +usb:v1D50p602D* + ID_MODEL_FROM_DATABASE=5nes5snes (4x12) + +usb:v1D50p602E* + ID_MODEL_FROM_DATABASE=Flexibity + +usb:v1D50p602F* + ID_MODEL_FROM_DATABASE=K-copter + +usb:v1D50p6030* + ID_MODEL_FROM_DATABASE=USB-oscope + +usb:v1D50p6031* + ID_MODEL_FROM_DATABASE=Handmade GSM GPS tracker + +usb:v1D50p6033* + ID_MODEL_FROM_DATABASE=frobiac / adnw keyboard + +usb:v1D50p6034* + ID_MODEL_FROM_DATABASE=Tiflomag Ergo 2 + +usb:v1D50p6035* + ID_MODEL_FROM_DATABASE=FreeLaserTag Gun + +usb:v1D50p6036* + ID_MODEL_FROM_DATABASE=FreeLaserTag Big Brother + +usb:v1D50p6037* + ID_MODEL_FROM_DATABASE=FreeLaserTag Node + +usb:v1D50p6038* + ID_MODEL_FROM_DATABASE=Monaka + +usb:v1D50p6039* + ID_MODEL_FROM_DATABASE=eXtreme Feedback Device + +usb:v1D50p603A* + ID_MODEL_FROM_DATABASE=TiLDA + +usb:v1D50p603B* + ID_MODEL_FROM_DATABASE=Raspiface + +usb:v1D50p603C* + ID_MODEL_FROM_DATABASE=Paparazzi (bootloader) + +usb:v1D50p603D* + ID_MODEL_FROM_DATABASE=Paparazzi (Serial) + +usb:v1D50p603E* + ID_MODEL_FROM_DATABASE=Paparazzi (Mass Storage) + +usb:v1D50p603F* + ID_MODEL_FROM_DATABASE=airGuitar + +usb:v1D50p6040* + ID_MODEL_FROM_DATABASE=moco + +usb:v1D50p6041* + ID_MODEL_FROM_DATABASE=AlphaSphere (bootloader) + +usb:v1D50p6042* + ID_MODEL_FROM_DATABASE=Dspace robot controller + +usb:v1D50p6043* + ID_MODEL_FROM_DATABASE=pc-power + +usb:v1D50p6044* + ID_MODEL_FROM_DATABASE=open-usb-can (DFU) + +usb:v1D50p6045* + ID_MODEL_FROM_DATABASE=open-usb-can + +usb:v1D50p6046* + ID_MODEL_FROM_DATABASE=mimus-weigand + +usb:v1D50p6047* + ID_MODEL_FROM_DATABASE=RfCat Chronos Dongle + +usb:v1D50p6048* + ID_MODEL_FROM_DATABASE=RfCat Dons Dongle + +usb:v1D50p6049* + ID_MODEL_FROM_DATABASE=RfCat Chronos bootloader + +usb:v1D50p604A* + ID_MODEL_FROM_DATABASE=RfCat Dons bootloader + +usb:v1D50p604B* + ID_MODEL_FROM_DATABASE=HackRF Jawbreaker Software-Defined Radio + +usb:v1D50p604C* + ID_MODEL_FROM_DATABASE=Makibox A6 + +usb:v1D50p604D* + ID_MODEL_FROM_DATABASE=Paella Pulse height analyzer + +usb:v1D50p604E* + ID_MODEL_FROM_DATABASE=Miniscope v2b + +usb:v1D50p604F* + ID_MODEL_FROM_DATABASE=Miniscope v2c + +usb:v1D50p6050* + ID_MODEL_FROM_DATABASE=GoodFET + +usb:v1D50p6051* + ID_MODEL_FROM_DATABASE=pinocc.io + +usb:v1D50p6052* + ID_MODEL_FROM_DATABASE=APB Team Robotic Development Board + +usb:v1D50p6053* + ID_MODEL_FROM_DATABASE=Darkgame Controller + +usb:v1D50p6054* + ID_MODEL_FROM_DATABASE=Satlab/AAUSAT3 BlueBox + +usb:v1D50p6056* + ID_MODEL_FROM_DATABASE=The Glitch + +usb:v1D50p605B* + ID_MODEL_FROM_DATABASE=RfCat YARD Stick One + +usb:v1D50p605C* + ID_MODEL_FROM_DATABASE=YARD Stick One bootloader + +usb:v1D50p605D* + ID_MODEL_FROM_DATABASE=Funky Sensor v2 + +usb:v1D50p605E* + ID_MODEL_FROM_DATABASE=Blinkiverse Analog LED Fader + +usb:v1D50p605F* + ID_MODEL_FROM_DATABASE=Small DIP package Cypress FX2 + +usb:v1D50p6060* + ID_MODEL_FROM_DATABASE=Data logger using the Cypress FX2 + +usb:v1D50p6061* + ID_MODEL_FROM_DATABASE=Power Manager + +usb:v1D50p6063* + ID_MODEL_FROM_DATABASE=CPC FPGA + +usb:v1D50p6064* + ID_MODEL_FROM_DATABASE=CPC FPGA (DFU) + +usb:v1D50p6065* + ID_MODEL_FROM_DATABASE=CPC FPGA (Serial) + +usb:v1D50p6066* + ID_MODEL_FROM_DATABASE=Nuand BladeRF + +usb:v1D50p6067* + ID_MODEL_FROM_DATABASE=Orbotron 9000 (Serial) + +usb:v1D50p6068* + ID_MODEL_FROM_DATABASE=Orbotron 9000 (HID) + +usb:v1D50p6069* + ID_MODEL_FROM_DATABASE=xser (DFU) + +usb:v1D50p606A* + ID_MODEL_FROM_DATABASE=xser (legacy) + +usb:v1D50p606B* + ID_MODEL_FROM_DATABASE=S08-245, urJtag compatible firmware for S08JS + +usb:v1D50p606C* + ID_MODEL_FROM_DATABASE=Blinkytape full-color light tape + +usb:v1D50p606D* + ID_MODEL_FROM_DATABASE=TinyG open source motion controller + +usb:v1D50p606E* + ID_MODEL_FROM_DATABASE=Reefangel Evolution 1.0 + +usb:v1D50p6070* + ID_MODEL_FROM_DATABASE=Open Pinball Project + +usb:v1D50p6071* + ID_MODEL_FROM_DATABASE=The Glitch HID + +usb:v1D50p6072* + ID_MODEL_FROM_DATABASE=The Glitch Disk + +usb:v1D50p6073* + ID_MODEL_FROM_DATABASE=The Glitch Serial + +usb:v1D50p6074* + ID_MODEL_FROM_DATABASE=The Glitch MIDI + +usb:v1D50p6075* + ID_MODEL_FROM_DATABASE=The Glitch RawHID + +usb:v1D50p6076* + ID_MODEL_FROM_DATABASE=Vultureprog BIOS chip programmer + +usb:v1D50p6077* + ID_MODEL_FROM_DATABASE=PaintDuino + +usb:v1D50p6078* + ID_MODEL_FROM_DATABASE=DTplug + +usb:v1D50p607A* + ID_MODEL_FROM_DATABASE=Fadecandy + +usb:v1D50p607B* + ID_MODEL_FROM_DATABASE=RCDongle for IR remote control + +usb:v1D50p607C* + ID_MODEL_FROM_DATABASE=OpenVizsla USB sniffer/analyzer + +usb:v1D50p607D* + ID_MODEL_FROM_DATABASE=Spark Core Arduino-compatible board with WiFi + +usb:v1D50p607F* + ID_MODEL_FROM_DATABASE=Spark Core Arduino-compatible board with WiFi (bootloader) + +usb:v1D50p6080* + ID_MODEL_FROM_DATABASE=arcin arcade controller + +usb:v1D50p6081* + ID_MODEL_FROM_DATABASE=BladeRF (bootloader) + +usb:v1D50p6082* + ID_MODEL_FROM_DATABASE=Facecandy (DFU) + +usb:v1D50p6083* + ID_MODEL_FROM_DATABASE=LightUp (bootloader) + +usb:v1D50p6084* + ID_MODEL_FROM_DATABASE=arcin arcade controller (DFU) + +usb:v1D50p6085* + ID_MODEL_FROM_DATABASE=IRKit for controlloing home electronics from iOS devices + +usb:v1D50p6086* + ID_MODEL_FROM_DATABASE=OneRNG entropy device + +usb:v1D50p6088* + ID_MODEL_FROM_DATABASE=picp PIC16F145x based PIC16F145x programmer + +usb:v1D50p6089* + ID_MODEL_FROM_DATABASE=Great Scott Gadgets HackRF One SDR + +usb:v1D50p608A* + ID_MODEL_FROM_DATABASE=BLEduino + +usb:v1D50p608B* + ID_MODEL_FROM_DATABASE=Loctronix ASR-2300 SDR/motion sensing module + +usb:v1D50p608C* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p608D* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p608E* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p608F* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6090* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6091* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6092* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6093* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6094* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6095* + ID_MODEL_FROM_DATABASE=Fx2lafw + +usb:v1D50p6096* + ID_MODEL_FROM_DATABASE=LightUp (sketch) + +usb:v1D50p6097* + ID_MODEL_FROM_DATABASE=Tessel JavaScript enabled Microcontroller with built-in WiFi + +usb:v1D50p6098* + ID_MODEL_FROM_DATABASE=RFIDler + +usb:v1D50p6099* + ID_MODEL_FROM_DATABASE=RASDR Radio Astronomy SDR Rx Interface + +usb:v1D50p609A* + ID_MODEL_FROM_DATABASE=RASDR Radio Astronomy SDR Tx Interface + +usb:v1D50p609B* + ID_MODEL_FROM_DATABASE=RASDR Radio Astronomy SDR (bootloader) + +usb:v1D50p609C* + ID_MODEL_FROM_DATABASE=antiAFK keyboard + +usb:v1D50p609D* + ID_MODEL_FROM_DATABASE=PIC16F145x bootloader + +usb:v1D50p609E* + ID_MODEL_FROM_DATABASE=Clyde Lamp by Fabule (bootloader) + +usb:v1D50p609F* + ID_MODEL_FROM_DATABASE=Clyde Lamp by Fabule (sketch) + +usb:v1D50p60A0* + ID_MODEL_FROM_DATABASE=Smoothiepanel robotic control interface + +usb:v1D50p60A1* + ID_MODEL_FROM_DATABASE=Airspy + +usb:v1D50p60A2* + ID_MODEL_FROM_DATABASE=barebox (DFU) + +usb:v1D50p60A3* + ID_MODEL_FROM_DATABASE=keyboard (bootloader) + +usb:v1D50p60A4* + ID_MODEL_FROM_DATABASE=Papilio Duo (AVR) + +usb:v1D50p60A5* + ID_MODEL_FROM_DATABASE=Papilio Duo (FPGA) + +usb:v1D50p60A6* + ID_MODEL_FROM_DATABASE=HydraBus/HydraNFC (bootloader) + +usb:v1D50p60A7* + ID_MODEL_FROM_DATABASE=HydraBus/HydraNFC + +usb:v1D50p60A8* + ID_MODEL_FROM_DATABASE=reserved + +usb:v1D50p60A9* + ID_MODEL_FROM_DATABASE=Blinky Light Controller (DFU) + +usb:v1D50p60AA* + ID_MODEL_FROM_DATABASE=Blinky Light Controller + +usb:v1D50p60AB* + ID_MODEL_FROM_DATABASE=AllPixel + +usb:v1D50p60AC* + ID_MODEL_FROM_DATABASE=OpenBLT generic microcontroller (bootloader) + +usb:v1D50p60B0* + ID_MODEL_FROM_DATABASE=Waterott Arduino based Clock (caterina bootloader) + +usb:v1D50p60B1* + ID_MODEL_FROM_DATABASE=Drinkbot (processing) + +usb:v1D50p60B2* + ID_MODEL_FROM_DATABASE=Drinkbot (OTG-tablet support) + +usb:v1D50p60B3* + ID_MODEL_FROM_DATABASE=calc.pw password generator device (standard) + +usb:v1D50p60B4* + ID_MODEL_FROM_DATABASE=calc.pw password generator device (enhanced) + +usb:v1D50p60B5* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (FX2) - Unconfigured device + +usb:v1D50p60B6* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (FX2) - Firmware load/upgrade + +usb:v1D50p60B7* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (FX2) - HDMI/DVI Capture Device + +usb:v1D50p60B8* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (Soft+UTMI) - Unconfigured device + +usb:v1D50p60B9* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (Soft+UTMI) - Firmware upgrade + +usb:v1D50p60BA* + ID_MODEL_FROM_DATABASE=TimVideos' HDMI2USB (Soft+UTMI) - HDMI/DVI Capture Device + +usb:v1D50p60BC* + ID_MODEL_FROM_DATABASE=Simple CC25xx programmer / serial board + +usb:v1D50p60BD* + ID_MODEL_FROM_DATABASE=Open Source control interface for multimedia applications + +usb:v1D50p60BE* + ID_MODEL_FROM_DATABASE=Pixelmatix Aurora (bootloader) + +usb:v1D50p60BF* + ID_MODEL_FROM_DATABASE=Pixelmatix Aurora + +usb:v1D50p60C1* + ID_MODEL_FROM_DATABASE=BrewBit Model-T pOSHW temperature controller for homebrewers (bootloader) + +usb:v1D50p60C2* + ID_MODEL_FROM_DATABASE=BrewBit Model-T pOSHW temperature controller for homebrewers + +usb:v1D50p60C3* + ID_MODEL_FROM_DATABASE=X Antenna Tracker arduino board + +usb:v1D50p60C6* + ID_MODEL_FROM_DATABASE=USBtrng hardware random number generator + +usb:v1D50p60C7* + ID_MODEL_FROM_DATABASE=Zubax GNSS positioning module for light UAV systems + +usb:v1D50p60C8* + ID_MODEL_FROM_DATABASE=Xlink data transfer and control system for Commodore C64 + +usb:v1D50p60C9* + ID_MODEL_FROM_DATABASE=random number generator + +usb:v1D50p60CA* + ID_MODEL_FROM_DATABASE=FinalKey password manager + +usb:v1D50p60CB* + ID_MODEL_FROM_DATABASE=PteroDAQ Data Acquisition on FRDM-KL25Z and future boards + +usb:v1D50p60CC* + ID_MODEL_FROM_DATABASE=LamDiNao + +usb:v1D50p60DE* + ID_MODEL_FROM_DATABASE=Cryptech.is random number generator + +usb:v1D50p60DF* + ID_MODEL_FROM_DATABASE=Numato Opsis HDMI2USB board (unconfigured) + +usb:v1D50p60E0* + ID_MODEL_FROM_DATABASE=Numato Opsis HDMI2USB board (JTAG Programming Mode) + +usb:v1D50p60E1* + ID_MODEL_FROM_DATABASE=Numato Opsis HDMI2USB board (User Mode) + +usb:v1D50p60E2* + ID_MODEL_FROM_DATABASE=Osmocom SIMtrace 2 (DFU) + +usb:v1D50p60E3* + ID_MODEL_FROM_DATABASE=Osmocom SIMtrace 2 + +usb:v1D50p60E4* + ID_MODEL_FROM_DATABASE=3D printed racing game - (Catalina CDC bootloader) + +usb:v1D50p60E5* + ID_MODEL_FROM_DATABASE=3D printed racing game + +usb:v1D50p60E6* + ID_MODEL_FROM_DATABASE=replacement for GoodFET/FaceDancer - GreatFet + +usb:v1D50p60E7* + ID_MODEL_FROM_DATABASE=replacement for GoodFET/FaceDancer - GreatFet target + +usb:v1D50p60E8* + ID_MODEL_FROM_DATABASE=Alpen Clack keyboard + +usb:v1D50p60E9* + ID_MODEL_FROM_DATABASE=keyman64 keyboard itercepter + +usb:v1D50p60EA* + ID_MODEL_FROM_DATABASE=Wiggleport FPGA-based I/O board + +usb:v1D50p60EC* + ID_MODEL_FROM_DATABASE=Duet 3D Printer Controller + +usb:v1D50p60F0* + ID_MODEL_FROM_DATABASE=UDAD-T1 data aquisition device (boot) + +usb:v1D50p60F1* + ID_MODEL_FROM_DATABASE=UDAD-T1 data aquisition device + +usb:v1D50p60F2* + ID_MODEL_FROM_DATABASE=UDAD-T2 data aquisition device (boot) + +usb:v1D50p60F3* + ID_MODEL_FROM_DATABASE=UDAD-T2 data aquisition device + +usb:v1D50p60F4* + ID_MODEL_FROM_DATABASE=Uniti ARC motor controller + +usb:v1D50p60F5* + ID_MODEL_FROM_DATABASE=EightByEight Blinky Badge (DFU) + +usb:v1D50p60F6* + ID_MODEL_FROM_DATABASE=EightByEight Blinky Badge + +usb:v1D50p60F7* + ID_MODEL_FROM_DATABASE=cardio NFC/RFID card reader (bootloader) + +usb:v1D50p60F8* + ID_MODEL_FROM_DATABASE=cardio NFC/RFID card reader + +usb:v1D50p60FC* + ID_MODEL_FROM_DATABASE=OnlyKey Two-factor Authentication and Password Solution + +usb:v1D50p6100* + ID_MODEL_FROM_DATABASE=overlay64 video overlay module + +usb:v1D50p6104* + ID_MODEL_FROM_DATABASE=ScopeFun open source instrumentation + +usb:v1D50p6108* + ID_MODEL_FROM_DATABASE=Myriad-RF LimeSDR + +usb:v1D50p610C* + ID_MODEL_FROM_DATABASE=Magic Keys (boot) + +usb:v1D50p610D* + ID_MODEL_FROM_DATABASE=Magic Keys + +usb:v1D50p8085* + ID_MODEL_FROM_DATABASE=Box0 (box0-v5) + +usb:v1D50pCC15* + ID_MODEL_FROM_DATABASE=rad1o badge for CCC congress 2015 + +usb:v1D57* + ID_VENDOR_FROM_DATABASE=Xenta + +usb:v1D57p0005* + ID_MODEL_FROM_DATABASE=Wireless Receiver (Keyboard and Mouse) + +usb:v1D57p0006* + ID_MODEL_FROM_DATABASE=Wireless Receiver (RC Laser Pointer) + +usb:v1D57p000C* + ID_MODEL_FROM_DATABASE=Optical Mouse + +usb:v1D57p2400* + ID_MODEL_FROM_DATABASE=Wireless Mouse Receiver + +usb:v1D57p32DA* + ID_MODEL_FROM_DATABASE=2.4GHz Receiver (Keyboard and Mouse) + +usb:v1D57p83D0* + ID_MODEL_FROM_DATABASE=Click-mouse! + +usb:v1D57pAC01* + ID_MODEL_FROM_DATABASE=Wireless Receiver (Keyboard and Mouse) + +usb:v1D57pAD02* + ID_MODEL_FROM_DATABASE=SE340D PC Remote Control + +usb:v1D57pAF01* + ID_MODEL_FROM_DATABASE=AUVIO Universal Remote Receiver for PlayStation 3 + +usb:v1D5B* + ID_VENDOR_FROM_DATABASE=Smartronix, Inc. + +usb:v1D5C* + ID_VENDOR_FROM_DATABASE=Fresco Logic + +usb:v1D5Cp2000* + ID_MODEL_FROM_DATABASE=FL2000/FL2000DX VGA/DVI/HDMI Adapter + +usb:v1D6B* + ID_VENDOR_FROM_DATABASE=Linux Foundation + +usb:v1D6Bp0001* + ID_MODEL_FROM_DATABASE=1.1 root hub + +usb:v1D6Bp0002* + ID_MODEL_FROM_DATABASE=2.0 root hub + +usb:v1D6Bp0003* + ID_MODEL_FROM_DATABASE=3.0 root hub + +usb:v1D6Bp0100* + ID_MODEL_FROM_DATABASE=PTP Gadget + +usb:v1D6Bp0101* + ID_MODEL_FROM_DATABASE=Audio Gadget + +usb:v1D6Bp0102* + ID_MODEL_FROM_DATABASE=EEM Gadget + +usb:v1D6Bp0103* + ID_MODEL_FROM_DATABASE=NCM (Ethernet) Gadget + +usb:v1D6Bp0104* + ID_MODEL_FROM_DATABASE=Multifunction Composite Gadget + +usb:v1D6Bp0105* + ID_MODEL_FROM_DATABASE=FunctionFS Gadget + +usb:v1D6Bp0200* + ID_MODEL_FROM_DATABASE=Qemu Audio Device + +usb:v1D90* + ID_VENDOR_FROM_DATABASE=Citizen + +usb:v1D90p201E* + ID_MODEL_FROM_DATABASE=PPU-700 + +usb:v1D9D* + ID_VENDOR_FROM_DATABASE=Sigma Sport + +usb:v1D9Dp1010* + ID_MODEL_FROM_DATABASE=Docking Station Topline 2009 + +usb:v1D9Dp1011* + ID_MODEL_FROM_DATABASE=Docking Station Topline 2012 + +usb:v1DE1* + ID_VENDOR_FROM_DATABASE=Actions Microelectronics Co. + +usb:v1DE1p1101* + ID_MODEL_FROM_DATABASE=Generic Display Device (Mass storage mode) + +usb:v1DE1pC101* + ID_MODEL_FROM_DATABASE=Generic Display Device + +usb:v1E0E* + ID_VENDOR_FROM_DATABASE=Qualcomm / Option + +usb:v1E0EpF000* + ID_MODEL_FROM_DATABASE=iCON 210 UMTS Surfstick + +usb:v1E10* + ID_VENDOR_FROM_DATABASE=Point Grey Research, Inc. + +usb:v1E10p2004* + ID_MODEL_FROM_DATABASE=Sony 1.3MP 1/3" ICX445 IIDC video camera [Chameleon] + +usb:v1E17* + ID_VENDOR_FROM_DATABASE=Mirion Technologies Dosimetry Services Division + +usb:v1E17p0001* + ID_MODEL_FROM_DATABASE=instadose dosimeter + +usb:v1E1D* + ID_VENDOR_FROM_DATABASE=Kanguru Solutions + +usb:v1E1Dp0165* + ID_MODEL_FROM_DATABASE=Secure Pen drive + +usb:v1E1Dp1101* + ID_MODEL_FROM_DATABASE=FlashBlu Flash Drive + +usb:v1E1F* + ID_VENDOR_FROM_DATABASE=INVIA + +usb:v1E29* + ID_VENDOR_FROM_DATABASE=Festo AG & Co. KG + +usb:v1E29p0101* + ID_MODEL_FROM_DATABASE=CPX Adapter + +usb:v1E29p0102* + ID_MODEL_FROM_DATABASE=CPX Adapter >=HW10.09 [CP2102] + +usb:v1E29p0401* + ID_MODEL_FROM_DATABASE=iL3-TP [AT90USB646] + +usb:v1E29p0402* + ID_MODEL_FROM_DATABASE=FTDI232 [EasyPort] + +usb:v1E29p0403* + ID_MODEL_FROM_DATABASE=FTDI232 [EasyPort Mini] + +usb:v1E29p0404* + ID_MODEL_FROM_DATABASE=FTDI232 [Netzteil-GL] + +usb:v1E29p0405* + ID_MODEL_FROM_DATABASE=FTDI232 [MotorPrüfstand] + +usb:v1E29p0406* + ID_MODEL_FROM_DATABASE=STM32F103 [EasyKit] + +usb:v1E29p0407* + ID_MODEL_FROM_DATABASE=LPC2378 [Robotino] + +usb:v1E29p0408* + ID_MODEL_FROM_DATABASE=LPC2378 [Robotino-Arm] + +usb:v1E29p0409* + ID_MODEL_FROM_DATABASE=LPC2378 [Robotino-Arm Bootloader] + +usb:v1E29p040A* + ID_MODEL_FROM_DATABASE=LPC2378 [Robotino Bootloader] + +usb:v1E29p040B* + ID_MODEL_FROM_DATABASE=LPC2378 [Robotino XT] + +usb:v1E29p040C* + ID_MODEL_FROM_DATABASE=LPC2378 [Robotino XT Bootloader] + +usb:v1E29p040D* + ID_MODEL_FROM_DATABASE=LPC2378 [Robotino 3] + +usb:v1E29p040E* + ID_MODEL_FROM_DATABASE=LPC2378 [Robotino 3 Bootloader] + +usb:v1E29p0501* + ID_MODEL_FROM_DATABASE=CP2102 [CMSP] + +usb:v1E29p0601* + ID_MODEL_FROM_DATABASE=CMMP-AS + +usb:v1E3D* + ID_VENDOR_FROM_DATABASE=Chipsbank Microelectronics Co., Ltd + +usb:v1E3Dp2093* + ID_MODEL_FROM_DATABASE=CBM209x Flash Drive (OEM) + +usb:v1E3Dp4082* + ID_MODEL_FROM_DATABASE=CBM4082 SD Card Reader + +usb:v1E41* + ID_VENDOR_FROM_DATABASE=Cleverscope + +usb:v1E41p0001* + ID_MODEL_FROM_DATABASE=CS328A PC Oscilloscope + +usb:v1E4E* + ID_VENDOR_FROM_DATABASE=Cubeternet + +usb:v1E4Ep0100* + ID_MODEL_FROM_DATABASE=WebCam + +usb:v1E4Ep0102* + ID_MODEL_FROM_DATABASE=GL-UPC822 UVC WebCam + +usb:v1E54* + ID_VENDOR_FROM_DATABASE=TypeMatrix + +usb:v1E54p2030* + ID_MODEL_FROM_DATABASE=2030 USB Keyboard + +usb:v1E68* + ID_VENDOR_FROM_DATABASE=TrekStor GmbH & Co. KG + +usb:v1E68p001B* + ID_MODEL_FROM_DATABASE=DataStation maxi g.u + +usb:v1E68p0050* + ID_MODEL_FROM_DATABASE=DataStation maxi light + +usb:v1E71* + ID_VENDOR_FROM_DATABASE=NZXT + +usb:v1E71p0001* + ID_MODEL_FROM_DATABASE=Avatar Optical Mouse + +usb:v1E74* + ID_VENDOR_FROM_DATABASE=Coby Electronics Corporation + +usb:v1E74p2211* + ID_MODEL_FROM_DATABASE=MP300 + +usb:v1E74p2647* + ID_MODEL_FROM_DATABASE=2 GB 2 Go Video MP3 Player [MP601-2G] + +usb:v1E74p2659* + ID_MODEL_FROM_DATABASE=Coby 4GB Go Video MP3 Player [MP620-4G] + +usb:v1E74p4641* + ID_MODEL_FROM_DATABASE=A8705 MP3/Video Player + +usb:v1E74p6511* + ID_MODEL_FROM_DATABASE=MP705-8G MP3 player + +usb:v1E74p6512* + ID_MODEL_FROM_DATABASE=MP705-4G + +usb:v1E74p7111* + ID_MODEL_FROM_DATABASE=MP957 Music and Video Player + +usb:v1E7D* + ID_VENDOR_FROM_DATABASE=ROCCAT + +usb:v1E7Dp2C24* + ID_MODEL_FROM_DATABASE=Pyra Mouse (wired) + +usb:v1E7Dp2CED* + ID_MODEL_FROM_DATABASE=Kone Mouse + +usb:v1E7Dp2CF6* + ID_MODEL_FROM_DATABASE=Pyra Mouse (wireless) + +usb:v1E7Dp2D50* + ID_MODEL_FROM_DATABASE=Kova+ Mouse + +usb:v1E7Dp2D51* + ID_MODEL_FROM_DATABASE=Kone+ Mouse + +usb:v1E7Dp2E22* + ID_MODEL_FROM_DATABASE=Kone XTD Mouse + +usb:v1E7Dp30D4* + ID_MODEL_FROM_DATABASE=Arvo Keyboard + +usb:v1EA7* + ID_VENDOR_FROM_DATABASE=SHARKOON Technologies GmbH + +usb:v1EA7p0066* + ID_MODEL_FROM_DATABASE=[Mediatrack Edge Mini Keyboard] + +usb:v1EA7p2007* + ID_MODEL_FROM_DATABASE=SHARK ZONE K30 Illuminated Gaming Keyboard + +usb:v1EBB* + ID_VENDOR_FROM_DATABASE=NuCORE Technology, Inc. + +usb:v1EDA* + ID_VENDOR_FROM_DATABASE=AirTies Wireless Networks + +usb:v1EDAp2012* + ID_MODEL_FROM_DATABASE=Air2210 54 Mbps Wireless Adapter + +usb:v1EDAp2210* + ID_MODEL_FROM_DATABASE=Air2210 54 Mbps Wireless Adapter + +usb:v1EDAp2310* + ID_MODEL_FROM_DATABASE=Air2310 150 Mbps Wireless Adapter + +usb:v1EDAp2410* + ID_MODEL_FROM_DATABASE=Air2410 300 Mbps Wireless Adapter + +usb:v1EDB* + ID_VENDOR_FROM_DATABASE=Blackmagic design + +usb:v1EDBpBD3B* + ID_MODEL_FROM_DATABASE=Intensity Shuttle + +usb:v1EE8* + ID_VENDOR_FROM_DATABASE=ONDA COMMUNICATION S.p.a. + +usb:v1EE8p0014* + ID_MODEL_FROM_DATABASE=MT833UP + +usb:v1EF6* + ID_VENDOR_FROM_DATABASE=EADS Deutschland GmbH + +usb:v1EF6p2233* + ID_MODEL_FROM_DATABASE=Cassidian NH90 STTE + +usb:v1EF6p5064* + ID_MODEL_FROM_DATABASE=FDR Interface + +usb:v1EF6p5523* + ID_MODEL_FROM_DATABASE=Cassidian SSDC Adapter II + +usb:v1EF6p5545* + ID_MODEL_FROM_DATABASE=Cassidian SSDC Adapter III + +usb:v1EF6p5648* + ID_MODEL_FROM_DATABASE=RIU CSMU/BSD + +usb:v1EF6p564A* + ID_MODEL_FROM_DATABASE=Cassidian RIU CSMU/BSD Simulator + +usb:v1F28* + ID_VENDOR_FROM_DATABASE=Cal-Comp + +usb:v1F28p0020* + ID_MODEL_FROM_DATABASE=CDMA USB Modem A600 + +usb:v1F28p0021* + ID_MODEL_FROM_DATABASE=CD INSTALLER USB Device + +usb:v1F3A* + ID_VENDOR_FROM_DATABASE=Onda (unverified) + +usb:v1F3ApEFE8* + ID_MODEL_FROM_DATABASE=V972 tablet in flashing mode + +usb:v1F44* + ID_VENDOR_FROM_DATABASE=The Neat Company + +usb:v1F44p0001* + ID_MODEL_FROM_DATABASE=NM-1000 scanner + +usb:v1F48* + ID_VENDOR_FROM_DATABASE=H-TRONIC GmbH + +usb:v1F48p0627* + ID_MODEL_FROM_DATABASE=Data capturing system + +usb:v1F48p0628* + ID_MODEL_FROM_DATABASE=Data capturing and control module + +usb:v1F4D* + ID_VENDOR_FROM_DATABASE=G-Tek Electronics Group + +usb:v1F4DpB803* + ID_MODEL_FROM_DATABASE=Lifeview LV5TDLX DVB-T [RTL2832U] + +usb:v1F4DpD220* + ID_MODEL_FROM_DATABASE=Geniatech T220 DVB-T2 TV Stick + +usb:v1F6F* + ID_VENDOR_FROM_DATABASE=Aliph + +usb:v1F6Fp0023* + ID_MODEL_FROM_DATABASE=Jawbone Jambox + +usb:v1F6Fp8000* + ID_MODEL_FROM_DATABASE=Jawbone Jambox - Updating + +usb:v1F75* + ID_VENDOR_FROM_DATABASE=Innostor Technology Corporation + +usb:v1F75p0888* + ID_MODEL_FROM_DATABASE=IS888 SATA Storage Controller + +usb:v1F75p0902* + ID_MODEL_FROM_DATABASE=IS902 UFD controller + +usb:v1F82* + ID_VENDOR_FROM_DATABASE=TANDBERG + +usb:v1F82p0001* + ID_MODEL_FROM_DATABASE=PrecisionHD Camera + +usb:v1F84* + ID_VENDOR_FROM_DATABASE=Alere, Inc. + +usb:v1F87* + ID_VENDOR_FROM_DATABASE=Stantum + +usb:v1F87p0002* + ID_MODEL_FROM_DATABASE=Multi-touch HID Controller + +usb:v1F9B* + ID_VENDOR_FROM_DATABASE=Ubiquiti Networks, Inc. + +usb:v1F9Bp0241* + ID_MODEL_FROM_DATABASE=AirView2-EXT + +usb:v1FAB* + ID_VENDOR_FROM_DATABASE=Samsung Opto-Electroncs Co., Ltd. + +usb:v1FABp104D* + ID_MODEL_FROM_DATABASE=ES65 + +usb:v1FBD* + ID_VENDOR_FROM_DATABASE=Delphin Technology AG + +usb:v1FBDp0001* + ID_MODEL_FROM_DATABASE=Expert Key - Data aquisition system + +usb:v1FC9* + ID_VENDOR_FROM_DATABASE=NXP Semiconductors + +usb:v1FC9p0003* + ID_MODEL_FROM_DATABASE=LPC1343 + +usb:v1FC9p010B* + ID_MODEL_FROM_DATABASE=PR533 + +usb:v1FC9p012B* + ID_MODEL_FROM_DATABASE=i.MX 8M Dual/8M QuadLite/8M Quad Serial Downloader + +usb:v1FDE* + ID_VENDOR_FROM_DATABASE=ILX Lightwave Corporation + +usb:v1FDEp0001* + ID_MODEL_FROM_DATABASE=UART Bridge + +usb:v1FE7* + ID_VENDOR_FROM_DATABASE=Vertex Wireless Co., Ltd. + +usb:v1FE7p1000* + ID_MODEL_FROM_DATABASE=VW100 series CDMA EV-DO Rev.A modem + +usb:v1FF7* + ID_VENDOR_FROM_DATABASE=CVT Electronics.Co.,Ltd + +usb:v1FF7p0013* + ID_MODEL_FROM_DATABASE=CVTouch Screen (HID) + +usb:v1FF7p001A* + ID_MODEL_FROM_DATABASE=Human Interface Device + +usb:v1FFF* + ID_VENDOR_FROM_DATABASE=Ideofy Inc. + +usb:v2001* + ID_VENDOR_FROM_DATABASE=D-Link Corp. + +usb:v2001p0001* + ID_MODEL_FROM_DATABASE=DWL-120 WIRELESS ADAPTER + +usb:v2001p0201* + ID_MODEL_FROM_DATABASE=DHN-120 10Mb Home Phoneline Adapter + +usb:v2001p1A00* + ID_MODEL_FROM_DATABASE=DUB-E100 Fast Ethernet Adapter(rev.A) [ASIX AX88172] + +usb:v2001p1A02* + ID_MODEL_FROM_DATABASE=DUB-E100 Fast Ethernet Adapter(rev.C1) [ASIX AX88772] + +usb:v2001p200C* + ID_MODEL_FROM_DATABASE=10/100 Ethernet + +usb:v2001p3200* + ID_MODEL_FROM_DATABASE=DWL-120 802.11b Wireless Adapter(rev.E1) [Atmel at76c503a] + +usb:v2001p3301* + ID_MODEL_FROM_DATABASE=DWA-130 802.11n Wireless N Adapter(rev.C1) [Realtek RTL8192U] + +usb:v2001p3306* + ID_MODEL_FROM_DATABASE=DWL-G122 Wireless Adapter(rev.F1) [Realtek RTL8188SU] + +usb:v2001p3308* + ID_MODEL_FROM_DATABASE=DWA-121 802.11n Wireless N 150 Pico Adapter [Realtek RTL8188CUS] + +usb:v2001p3309* + ID_MODEL_FROM_DATABASE=DWA-135 802.11n Wireless N Adapter(rev.A1) [Realtek RTL8192CU] + +usb:v2001p330A* + ID_MODEL_FROM_DATABASE=DWA-133 802.11n Wireless N Adapter [Realtek RTL8192CU] + +usb:v2001p3500* + ID_MODEL_FROM_DATABASE=Elitegroup Computer Systems WLAN card WL-162 + +usb:v2001p3700* + ID_MODEL_FROM_DATABASE=DWL-122 802.11b [Intersil Prism 3] + +usb:v2001p3701* + ID_MODEL_FROM_DATABASE=DWL-G120 Spinnaker 802.11g [Intersil ISL3886] + +usb:v2001p3702* + ID_MODEL_FROM_DATABASE=DWL-120 802.11b Wireless Adapter(rev.F) [Intersil ISL3871] + +usb:v2001p3703* + ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.A1) [Intersil ISL3880] + +usb:v2001p3704* + ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.A2) [Intersil ISL3887] + +usb:v2001p3705* + ID_MODEL_FROM_DATABASE=AirPlus G DWL-G120 Wireless Adapter(rev.C) [Intersil ISL3887] + +usb:v2001p3761* + ID_MODEL_FROM_DATABASE=IEEE 802.11g USB2.0 Wireless Network Adapter-PN + +usb:v2001p3A00* + ID_MODEL_FROM_DATABASE=DWL-AG132 [Atheros AR5523] + +usb:v2001p3A01* + ID_MODEL_FROM_DATABASE=DWL-AG132 (no firmware) [Atheros AR5523] + +usb:v2001p3A02* + ID_MODEL_FROM_DATABASE=DWL-G132 [Atheros AR5523] + +usb:v2001p3A03* + ID_MODEL_FROM_DATABASE=DWL-G132 (no firmware) [Atheros AR5523] + +usb:v2001p3A04* + ID_MODEL_FROM_DATABASE=DWL-AG122 [Atheros AR5523] + +usb:v2001p3A05* + ID_MODEL_FROM_DATABASE=DWL-AG122 (no firmware) [Atheros AR5523] + +usb:v2001p3A80* + ID_MODEL_FROM_DATABASE=AirPlus Xtreme G DWL-G132 Wireless Adapter + +usb:v2001p3A81* + ID_MODEL_FROM_DATABASE=predator Bootloader Download + +usb:v2001p3A82* + ID_MODEL_FROM_DATABASE=AirPremier AG DWL-AG132 Wireless Adapter + +usb:v2001p3A83* + ID_MODEL_FROM_DATABASE=predator Bootloader Download + +usb:v2001p3B00* + ID_MODEL_FROM_DATABASE=AirPlus DWL-120+ Wireless Adapter [Texas Instruments ACX100USB] + +usb:v2001p3B01* + ID_MODEL_FROM_DATABASE=WLAN Boot Device + +usb:v2001p3C00* + ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter(rev.B1) [Ralink RT2571] + +usb:v2001p3C01* + ID_MODEL_FROM_DATABASE=AirPlus AG DWL-AG122 Wireless Adapter + +usb:v2001p3C02* + ID_MODEL_FROM_DATABASE=AirPlus G DWL-G122 Wireless Adapter + +usb:v2001p3C05* + ID_MODEL_FROM_DATABASE=DUB-E100 Fast Ethernet Adapter(rev.B1) [ASIX AX88772] + +usb:v2001p3C15* + ID_MODEL_FROM_DATABASE=DWA-140 RangeBooster N Adapter(rev.B3) [Ralink RT5372] + +usb:v2001p3C17* + ID_MODEL_FROM_DATABASE=DWA-123 Wireless N 150 Adapter(rev.A1) [Ralink RT3370] + +usb:v2001p3C19* + ID_MODEL_FROM_DATABASE=DWA-125 Wireless N 150 Adapter(rev.A3) [Ralink RT5370] + +usb:v2001p3C1A* + ID_MODEL_FROM_DATABASE=DWA-160 802.11abgn Xtreme N Dual Band Adapter(rev.B2) [Ralink RT5572] + +usb:v2001p3C1B* + ID_MODEL_FROM_DATABASE=DWA-127 Wireless N 150 High-Gain Adapter(rev.A1) [Ralink RT3070] + +usb:v2001p4000* + ID_MODEL_FROM_DATABASE=DSB-650C Ethernet [klsi] + +usb:v2001p4001* + ID_MODEL_FROM_DATABASE=DSB-650TX Ethernet [pegasus] + +usb:v2001p4002* + ID_MODEL_FROM_DATABASE=DSB-650TX Ethernet [pegasus] + +usb:v2001p4003* + ID_MODEL_FROM_DATABASE=DSB-650TX-PNA Ethernet [pegasus] + +usb:v2001p400B* + ID_MODEL_FROM_DATABASE=10/100 Ethernet + +usb:v2001p4102* + ID_MODEL_FROM_DATABASE=10/100 Ethernet + +usb:v2001p5100* + ID_MODEL_FROM_DATABASE=DSL-200 ADSL ATM Modem + +usb:v2001p5102* + ID_MODEL_FROM_DATABASE=DSL-200 ADSL Loader + +usb:v2001p5B00* + ID_MODEL_FROM_DATABASE=Remote NDIS Network Device + +usb:v2001p9414* + ID_MODEL_FROM_DATABASE=Cable Modem + +usb:v2001p9B00* + ID_MODEL_FROM_DATABASE=Broadband Cable Modem Remote NDIS Device + +usb:v2001pABC1* + ID_MODEL_FROM_DATABASE=DSB-650 Ethernet [pegasus] + +usb:v2001pF013* + ID_MODEL_FROM_DATABASE=DLink 7 port USB2.0 Hub + +usb:v2001pF103* + ID_MODEL_FROM_DATABASE=DUB-H7 7-port USB 2.0 hub + +usb:v2001pF10D* + ID_MODEL_FROM_DATABASE=Accent Communications Modem + +usb:v2001pF110* + ID_MODEL_FROM_DATABASE=DUB-AV300 A/V Capture + +usb:v2001pF111* + ID_MODEL_FROM_DATABASE=DBT-122 Bluetooth adapter + +usb:v2001pF112* + ID_MODEL_FROM_DATABASE=DUB-T210 Audio Device + +usb:v2001pF116* + ID_MODEL_FROM_DATABASE=Formosa 2 + +usb:v2001pF117* + ID_MODEL_FROM_DATABASE=Formosa 3 + +usb:v2001pF118* + ID_MODEL_FROM_DATABASE=Formosa 4 + +usb:v2002* + ID_VENDOR_FROM_DATABASE=DAP Technologies + +usb:v2003* + ID_VENDOR_FROM_DATABASE=detectomat + +usb:v2003pEA61* + ID_MODEL_FROM_DATABASE=dc3500 + +usb:v200C* + ID_VENDOR_FROM_DATABASE=Reloop + +usb:v200Cp100B* + ID_MODEL_FROM_DATABASE=Play audio soundcard + +usb:v2013* + ID_VENDOR_FROM_DATABASE=PCTV Systems + +usb:v2013p0245* + ID_MODEL_FROM_DATABASE=PCTV 73ESE + +usb:v2013p0246* + ID_MODEL_FROM_DATABASE=PCTV 74E + +usb:v2013p0248* + ID_MODEL_FROM_DATABASE=PCTV 282E + +usb:v2013p024F* + ID_MODEL_FROM_DATABASE=nanoStick T2 290e + +usb:v2019* + ID_VENDOR_FROM_DATABASE=PLANEX + +usb:v2019p3220* + ID_MODEL_FROM_DATABASE=GW-US11S WLAN [Atmel AT76C503A] + +usb:v2019p4901* + ID_MODEL_FROM_DATABASE=GW-USSuper300 802.11bgn Wireless Adapter [Realtek RTL8191SU] + +usb:v2019p4903* + ID_MODEL_FROM_DATABASE=GW-USFang300 802.11abgn Wireless Adapter [Realtek RTL8192DU] + +usb:v2019p4904* + ID_MODEL_FROM_DATABASE=GW-USUltra300 802.11abgn Wireless Adapter [Realtek RTL8192DU] + +usb:v2019p5303* + ID_MODEL_FROM_DATABASE=GW-US54GXS 802.11bg + +usb:v2019p5304* + ID_MODEL_FROM_DATABASE=GWUS300 802.11n + +usb:v2019pAB01* + ID_MODEL_FROM_DATABASE=GW-US54HP + +usb:v2019pAB24* + ID_MODEL_FROM_DATABASE=GW-US300MiniS + +usb:v2019pAB25* + ID_MODEL_FROM_DATABASE=GW-USMini2N 802.11n Wireless Adapter [Ralink RT2870] + +usb:v2019pAB28* + ID_MODEL_FROM_DATABASE=GW-USNano + +usb:v2019pAB29* + ID_MODEL_FROM_DATABASE=GW-USMicro300 + +usb:v2019pAB2A* + ID_MODEL_FROM_DATABASE=GW-USNano2 802.11n Wireless Adapter [Realtek RTL8188CUS] + +usb:v2019pAB2B* + ID_MODEL_FROM_DATABASE=GW-USEco300 802.11bgn Wireless Adapter [Realtek RTL8192CU] + +usb:v2019pAB2C* + ID_MODEL_FROM_DATABASE=GW-USDual300 802.11abgn Wireless Adapter [Realtek RTL8192DU] + +usb:v2019pAB50* + ID_MODEL_FROM_DATABASE=GW-US54Mini2 + +usb:v2019pC002* + ID_MODEL_FROM_DATABASE=GW-US54SG + +usb:v2019pC007* + ID_MODEL_FROM_DATABASE=GW-US54GZL + +usb:v2019pED02* + ID_MODEL_FROM_DATABASE=GW-USMM + +usb:v2019pED06* + ID_MODEL_FROM_DATABASE=GW-US300MiniW 802.11bgn Wireless Adapter + +usb:v2019pED10* + ID_MODEL_FROM_DATABASE=GW-US300Mini2 + +usb:v2019pED14* + ID_MODEL_FROM_DATABASE=GW-USMicroN + +usb:v2019pED16* + ID_MODEL_FROM_DATABASE=GW-USMicroN2W 802.11bgn Wireless Adapter [Realtek RTL8188SU] + +usb:v2019pED17* + ID_MODEL_FROM_DATABASE=GW-USValue-EZ 802.11n Wireless Adapter [Realtek RTL8188CUS] + +usb:v2019pED18* + ID_MODEL_FROM_DATABASE=GW-USHyper300 / GW-USH300N 802.11bgn Wireless Adapter [Realtek RTL8191SU] + +usb:v203D* + ID_VENDOR_FROM_DATABASE=Encore Electronics Inc. + +usb:v203Dp1480* + ID_MODEL_FROM_DATABASE=ENUWI-N3 [802.11n Wireless N150 Adapter] + +usb:v2040* + ID_VENDOR_FROM_DATABASE=Hauppauge + +usb:v2040p0C80* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040p0C90* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040p1700* + ID_MODEL_FROM_DATABASE=CataMount + +usb:v2040p1800* + ID_MODEL_FROM_DATABASE=Okemo A + +usb:v2040p1801* + ID_MODEL_FROM_DATABASE=Okemo B + +usb:v2040p2000* + ID_MODEL_FROM_DATABASE=Tiger Minicard + +usb:v2040p2009* + ID_MODEL_FROM_DATABASE=Tiger Minicard R2 + +usb:v2040p200A* + ID_MODEL_FROM_DATABASE=Tiger Minicard + +usb:v2040p2010* + ID_MODEL_FROM_DATABASE=Tiger Minicard + +usb:v2040p2011* + ID_MODEL_FROM_DATABASE=WinTV MiniCard [Dell Digital TV Receiver] + +usb:v2040p2019* + ID_MODEL_FROM_DATABASE=Tiger Minicard + +usb:v2040p2400* + ID_MODEL_FROM_DATABASE=WinTV PVR USB2 (Model 24019) + +usb:v2040p4700* + ID_MODEL_FROM_DATABASE=WinTV Nova-S-USB2 + +usb:v2040p4902* + ID_MODEL_FROM_DATABASE=HD PVR + +usb:v2040p4903* + ID_MODEL_FROM_DATABASE=HS PVR + +usb:v2040p4982* + ID_MODEL_FROM_DATABASE=HD PVR + +usb:v2040p5500* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040p5510* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040p5520* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040p5530* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040p5580* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040p5590* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040p6500* + ID_MODEL_FROM_DATABASE=WinTV HVR-900 + +usb:v2040p6502* + ID_MODEL_FROM_DATABASE=WinTV HVR-900 + +usb:v2040p6503* + ID_MODEL_FROM_DATABASE=WinTV HVR-930 + +usb:v2040p6513* + ID_MODEL_FROM_DATABASE=WinTV HVR-980 + +usb:v2040p7050* + ID_MODEL_FROM_DATABASE=Nova-T Stick + +usb:v2040p7060* + ID_MODEL_FROM_DATABASE=Nova-T Stick 2 + +usb:v2040p7070* + ID_MODEL_FROM_DATABASE=Nova-T Stick 3 + +usb:v2040p7240* + ID_MODEL_FROM_DATABASE=WinTV HVR-850 + +usb:v2040p8400* + ID_MODEL_FROM_DATABASE=WinTV Nova-T-500 + +usb:v2040p9300* + ID_MODEL_FROM_DATABASE=WinTV NOVA-T USB2 (cold) + +usb:v2040p9301* + ID_MODEL_FROM_DATABASE=WinTV NOVA-T USB2 (warm) + +usb:v2040p9941* + ID_MODEL_FROM_DATABASE=WinTV Nova-T-500 + +usb:v2040p9950* + ID_MODEL_FROM_DATABASE=WinTV Nova-T-500 + +usb:v2040pB910* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040pB980* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040pB990* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040pC000* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2040pC010* + ID_MODEL_FROM_DATABASE=Windham + +usb:v2047* + ID_VENDOR_FROM_DATABASE=Texas Instruments + +usb:v2047p0200* + ID_MODEL_FROM_DATABASE=MSP430 USB HID Bootstrap Loader + +usb:v2047p0855* + ID_MODEL_FROM_DATABASE=Invensense Embedded MotionApp HID Sensor + +usb:v2047p0964* + ID_MODEL_FROM_DATABASE=Inventio Software MSP430 + +usb:v2058* + ID_VENDOR_FROM_DATABASE=Nano River Technology + +usb:v2058p2058* + ID_MODEL_FROM_DATABASE=ViperBoard I2C, SPI, GPIO interface + +usb:v2077* + ID_VENDOR_FROM_DATABASE=Taicang T&W Electronics Co. Ltd + +usb:v2077p9002* + ID_MODEL_FROM_DATABASE=W1M100 HSPA/WCDMA Module + +usb:v2080* + ID_VENDOR_FROM_DATABASE=Barnes & Noble + +usb:v2080p0001* + ID_MODEL_FROM_DATABASE=nook + +usb:v2080p0002* + ID_MODEL_FROM_DATABASE=NOOKcolor + +usb:v2080p0003* + ID_MODEL_FROM_DATABASE=NOOK Simple Touch + +usb:v2080p0004* + ID_MODEL_FROM_DATABASE=NOOK Tablet + +usb:v2086* + ID_VENDOR_FROM_DATABASE=SIMPASS + +usb:v2087* + ID_VENDOR_FROM_DATABASE=Cando + +usb:v2087p0A01* + ID_MODEL_FROM_DATABASE=Multi Touch Panel + +usb:v2087p0A02* + ID_MODEL_FROM_DATABASE=Multi Touch Panel + +usb:v2087p0B03* + ID_MODEL_FROM_DATABASE=Multi Touch Panel + +usb:v20A0* + ID_VENDOR_FROM_DATABASE=Clay Logic + +usb:v20A0p4123* + ID_MODEL_FROM_DATABASE=IKALOGIC SCANALOGIC 2 + +usb:v20A0p414A* + ID_MODEL_FROM_DATABASE=MDE SPI Interface + +usb:v20A0p415A* + ID_MODEL_FROM_DATABASE=OpenPilot + +usb:v20A0p415B* + ID_MODEL_FROM_DATABASE=CopterControl + +usb:v20A0p415C* + ID_MODEL_FROM_DATABASE=PipXtreme + +usb:v20B1* + ID_VENDOR_FROM_DATABASE=XMOS Ltd + +usb:v20B1p10AD* + ID_MODEL_FROM_DATABASE=XUSB Loader + +usb:v20B1pF7D1* + ID_MODEL_FROM_DATABASE=XTAG2 - JTAG Adapter + +usb:v20B3* + ID_VENDOR_FROM_DATABASE=Hanvon + +usb:v20B3p0A18* + ID_MODEL_FROM_DATABASE=10.1 Touch screen overlay + +usb:v20B7* + ID_VENDOR_FROM_DATABASE=Qi Hardware + +usb:v20B7p0713* + ID_MODEL_FROM_DATABASE=Milkymist JTAG/serial + +usb:v20B7p1540* + ID_MODEL_FROM_DATABASE=ben-wpan, AT86RF230-based + +usb:v20B7p1DB5* + ID_MODEL_FROM_DATABASE=IDBG in DFU mode + +usb:v20B7p1DB6* + ID_MODEL_FROM_DATABASE=IDBG in normal mode + +usb:v20B7pC25B* + ID_MODEL_FROM_DATABASE=C2 Dongle + +usb:v20B7pCB72* + ID_MODEL_FROM_DATABASE=ben-wpan, cntr + +usb:v20CE* + ID_VENDOR_FROM_DATABASE=Minicircuits + +usb:v20CEp0012* + ID_MODEL_FROM_DATABASE=RF Sythesizer 250-4200MHz model SSG-4000LH + +usb:v20CEp0021* + ID_MODEL_FROM_DATABASE=RF Switch Matrix + +usb:v20CEp0022* + ID_MODEL_FROM_DATABASE=I/O Controller + +usb:v20DF* + ID_VENDOR_FROM_DATABASE=Simtec Electronics + +usb:v20DFp0001* + ID_MODEL_FROM_DATABASE=Entropy Key [UDEKEY01] + +usb:v20F1* + ID_VENDOR_FROM_DATABASE=NET New Electronic Technology GmbH + +usb:v20F1p0101* + ID_MODEL_FROM_DATABASE=iCube3 Camera + +usb:v20F4* + ID_VENDOR_FROM_DATABASE=TRENDnet + +usb:v20F4p648B* + ID_MODEL_FROM_DATABASE=TEW-648UBM 802.11n 150Mbps Micro Wireless N Adapter [Realtek RTL8188CUS] + +usb:v20F7* + ID_VENDOR_FROM_DATABASE=XIMEA + +usb:v20F7p3001* + ID_MODEL_FROM_DATABASE=MQ or MD camera + +usb:v20F7p3002* + ID_MODEL_FROM_DATABASE=MU camera + +usb:v20F7p3021* + ID_MODEL_FROM_DATABASE=MJ camera + +usb:v20F7p30B3* + ID_MODEL_FROM_DATABASE=MQ in U3V mode or MC camera + +usb:v20F7pA003* + ID_MODEL_FROM_DATABASE=MU camera + +usb:v2100* + ID_VENDOR_FROM_DATABASE=RT Systems + +usb:v2100p9E52* + ID_MODEL_FROM_DATABASE=Yaesu VX-7 + +usb:v2100p9E54* + ID_MODEL_FROM_DATABASE=CT29B Radio Cable + +usb:v2100p9E57* + ID_MODEL_FROM_DATABASE=RTS01 Radio Cable + +usb:v2100p9E5D* + ID_MODEL_FROM_DATABASE=K4Y Radio Cable + +usb:v2100p9E5F* + ID_MODEL_FROM_DATABASE=FT232RL [RTS05 Serial Cable] + +usb:v2101* + ID_VENDOR_FROM_DATABASE=ActionStar + +usb:v2101p0201* + ID_MODEL_FROM_DATABASE=SIIG 4-to-2 Printer Switch + +usb:v2109* + ID_VENDOR_FROM_DATABASE=VIA Labs, Inc. + +usb:v2109p0700* + ID_MODEL_FROM_DATABASE=VL700 SATA 3Gb/s bridge + +usb:v2109p0701* + ID_MODEL_FROM_DATABASE=VL701 SATA 3Gb/s bridge + +usb:v2109p0810* + ID_MODEL_FROM_DATABASE=VL81x Hub + +usb:v2109p0811* + ID_MODEL_FROM_DATABASE=Hub + +usb:v2109p0812* + ID_MODEL_FROM_DATABASE=VL812 Hub + +usb:v2109p2811* + ID_MODEL_FROM_DATABASE=Hub + +usb:v2109p2812* + ID_MODEL_FROM_DATABASE=VL812 Hub + +usb:v2109p3431* + ID_MODEL_FROM_DATABASE=Hub + +usb:v2109p8110* + ID_MODEL_FROM_DATABASE=Hub + +usb:v2113* + ID_VENDOR_FROM_DATABASE=Softkinetic + +usb:v2113p0137* + ID_MODEL_FROM_DATABASE=DepthSense 311 (3D) + +usb:v2113p0145* + ID_MODEL_FROM_DATABASE=DepthSense 325 + +usb:v2113p8000* + ID_MODEL_FROM_DATABASE=DepthSense 311 (Color) + +usb:v2149* + ID_VENDOR_FROM_DATABASE=Advanced Silicon S.A. + +usb:v2149p211B* + ID_MODEL_FROM_DATABASE=Touchscreen Controller + +usb:v2149p2703* + ID_MODEL_FROM_DATABASE=TS58xxA/TC56xxA [CoolTouch] + +usb:v2162* + ID_VENDOR_FROM_DATABASE=Creative (?) + +usb:v2162p2031* + ID_MODEL_FROM_DATABASE=Network Blaster Wireless Adapter + +usb:v2162p500C* + ID_MODEL_FROM_DATABASE=DE5771 Modem Blaster + +usb:v2162p8001* + ID_MODEL_FROM_DATABASE=Broadxent BritePort DSL Bridge 8010U + +usb:v2184* + ID_VENDOR_FROM_DATABASE=GW Instek + +usb:v2184p0005* + ID_MODEL_FROM_DATABASE=GDS-3000 Oscilloscope + +usb:v2184p0006* + ID_MODEL_FROM_DATABASE=GDS-3000 Oscilloscope + +usb:v2184p0011* + ID_MODEL_FROM_DATABASE=AFG Function Generator (CDC) + +usb:v21A1* + ID_VENDOR_FROM_DATABASE=Emotiv Systems Pty. Ltd. + +usb:v21A1p0001* + ID_MODEL_FROM_DATABASE=EPOC Consumer Headset Wireless Dongle + +usb:v21D6* + ID_VENDOR_FROM_DATABASE=Agecodagis SARL + +usb:v21D6p0002* + ID_MODEL_FROM_DATABASE=Seismic recorder [Tellus] + +usb:v2207* + ID_VENDOR_FROM_DATABASE=Fuzhou Rockchip Electronics Company + +usb:v2207p0010* + ID_MODEL_FROM_DATABASE=GoClever Tab R83 + +usb:v2207p0011* + ID_MODEL_FROM_DATABASE=SmartTab + +usb:v2207p281A* + ID_MODEL_FROM_DATABASE=RK2818 in Mask ROM mode + +usb:v2207p290A* + ID_MODEL_FROM_DATABASE=RK2918 in Mask ROM mode + +usb:v2207p292A* + ID_MODEL_FROM_DATABASE=RK2928 in Mask ROM mode + +usb:v2207p292C* + ID_MODEL_FROM_DATABASE=RK3026 in Mask ROM mode + +usb:v2207p300A* + ID_MODEL_FROM_DATABASE=RK3066 in Mask ROM mode + +usb:v2207p300B* + ID_MODEL_FROM_DATABASE=RK3168 in Mask ROM mode + +usb:v2207p301A* + ID_MODEL_FROM_DATABASE=RK3036 in Mask ROM mode + +usb:v2207p310A* + ID_MODEL_FROM_DATABASE=RK3066B in Mask ROM mode + +usb:v2207p310B* + ID_MODEL_FROM_DATABASE=RK3188 in Mask ROM mode + +usb:v2207p310C* + ID_MODEL_FROM_DATABASE=RK3126/RK3128 in Mask ROM mode + +usb:v2207p310D* + ID_MODEL_FROM_DATABASE=RK3126 in Mask ROM mode + +usb:v2207p320A* + ID_MODEL_FROM_DATABASE=RK3288 in Mask ROM mode + +usb:v2207p320B* + ID_MODEL_FROM_DATABASE=RK3228/RK3229 in Mask ROM mode + +usb:v2207p320C* + ID_MODEL_FROM_DATABASE=RK3328 in Mask ROM mode + +usb:v2207p330A* + ID_MODEL_FROM_DATABASE=RK3368 in Mask ROM mode + +usb:v2207p330C* + ID_MODEL_FROM_DATABASE=RK3399 in Mask ROM mode + +usb:v2222* + ID_VENDOR_FROM_DATABASE=MacAlly + +usb:v2222p0004* + ID_MODEL_FROM_DATABASE=iWebKey Keyboard + +usb:v2222p2520* + ID_MODEL_FROM_DATABASE=Mini Tablet + +usb:v2222p4050* + ID_MODEL_FROM_DATABASE=AirStick joystick + +usb:v2227* + ID_VENDOR_FROM_DATABASE=SAMWOO Enterprise + +usb:v2227p3105* + ID_MODEL_FROM_DATABASE=SKYDATA SKD-U100 + +usb:v2232* + ID_VENDOR_FROM_DATABASE=Silicon Motion + +usb:v2232p1005* + ID_MODEL_FROM_DATABASE=WebCam SCB-0385N + +usb:v2232p1028* + ID_MODEL_FROM_DATABASE=WebCam SC-03FFL11939N + +usb:v2232p1029* + ID_MODEL_FROM_DATABASE=WebCam SC-13HDL11939N + +usb:v2232p1037* + ID_MODEL_FROM_DATABASE=WebCam SC-03FFM12339N + +usb:v2233* + ID_VENDOR_FROM_DATABASE=RadioShack Corporation + +usb:v2233p6323* + ID_MODEL_FROM_DATABASE=USB Electronic Scale + +usb:v2237* + ID_VENDOR_FROM_DATABASE=Kobo Inc. + +usb:v2237p4161* + ID_MODEL_FROM_DATABASE=eReader White + +usb:v224F* + ID_VENDOR_FROM_DATABASE=APDM + +usb:v224Fp0001* + ID_MODEL_FROM_DATABASE=Access Point + +usb:v224Fp0002* + ID_MODEL_FROM_DATABASE=Docking Station + +usb:v224Fp0004* + ID_MODEL_FROM_DATABASE=V2 Opal ACM + +usb:v224Fp0005* + ID_MODEL_FROM_DATABASE=V2 Opal + +usb:v224Fp0006* + ID_MODEL_FROM_DATABASE=V2 Docking Station + +usb:v224Fp0007* + ID_MODEL_FROM_DATABASE=V2 Access Point ACM + +usb:v224Fp0008* + ID_MODEL_FROM_DATABASE=V2 Access Point + +usb:v225D* + ID_VENDOR_FROM_DATABASE=Morpho + +usb:v225Dp0001* + ID_MODEL_FROM_DATABASE=FINGER VP Multimodal Biometric Sensor + +usb:v225Dp0008* + ID_MODEL_FROM_DATABASE=CBM-E3 Fingerprint Sensor + +usb:v225Dp0009* + ID_MODEL_FROM_DATABASE=CBM Fingerprint Sensor [CBM-V3] + +usb:v225Dp000A* + ID_MODEL_FROM_DATABASE=MSO1300-E3 Fingerprint Sensor + +usb:v225Dp000B* + ID_MODEL_FROM_DATABASE=MSO1300 Fingerprint Sensor [MSO1300-V3] + +usb:v225Dp000C* + ID_MODEL_FROM_DATABASE=MSO1350-E3 Fingerprint Sensor & SmartCard Reader + +usb:v225Dp000D* + ID_MODEL_FROM_DATABASE=MSO1350 Fingerprint Sensor & SmartCard Reader [MSO1350-V3] + +usb:v225Dp000E* + ID_MODEL_FROM_DATABASE=MorphoAccess SIGMA Biometric Access Control Terminal + +usb:v228D* + ID_VENDOR_FROM_DATABASE=8D Technologies inc. + +usb:v228Dp0001* + ID_MODEL_FROM_DATABASE=Terminal Bike Key Reader + +usb:v22A6* + ID_VENDOR_FROM_DATABASE=Pie Digital, Inc. + +usb:v22A6pFFFF* + ID_MODEL_FROM_DATABASE=PieKey "beta" 4GB model 4E4F41482E4F5247 (SM3251Q BB) + +usb:v22B8* + ID_VENDOR_FROM_DATABASE=Motorola PCS + +usb:v22B8p0001* + ID_MODEL_FROM_DATABASE=Wally 2.2 chipset + +usb:v22B8p0002* + ID_MODEL_FROM_DATABASE=Wally 2.4 chipset + +usb:v22B8p0005* + ID_MODEL_FROM_DATABASE=V.60c/V.60i GSM Phone + +usb:v22B8p0830* + ID_MODEL_FROM_DATABASE=2386C-HT820 + +usb:v22B8p0833* + ID_MODEL_FROM_DATABASE=2386C-HT820 [Flash Mode] + +usb:v22B8p0850* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v22B8p1001* + ID_MODEL_FROM_DATABASE=Patriot 1.0 (GSM) chipset + +usb:v22B8p1002* + ID_MODEL_FROM_DATABASE=Patriot 2.0 chipset + +usb:v22B8p1005* + ID_MODEL_FROM_DATABASE=T280e GSM/GPRS Phone + +usb:v22B8p1101* + ID_MODEL_FROM_DATABASE=Patriot 1.0 (TDMA) chipset + +usb:v22B8p1801* + ID_MODEL_FROM_DATABASE=Rainbow chipset flash + +usb:v22B8p2035* + ID_MODEL_FROM_DATABASE=Bluetooth Device + +usb:v22B8p2805* + ID_MODEL_FROM_DATABASE=GSM Modem + +usb:v22B8p2821* + ID_MODEL_FROM_DATABASE=T720 GSM Phone + +usb:v22B8p2822* + ID_MODEL_FROM_DATABASE=V.120e GSM Phone + +usb:v22B8p2823* + ID_MODEL_FROM_DATABASE=Flash Interface + +usb:v22B8p2A01* + ID_MODEL_FROM_DATABASE=MSM6050 chipset + +usb:v22B8p2A02* + ID_MODEL_FROM_DATABASE=CDMA modem + +usb:v22B8p2A03* + ID_MODEL_FROM_DATABASE=MSM6050 chipset flash + +usb:v22B8p2A21* + ID_MODEL_FROM_DATABASE=V710 GSM Phone (P2K) + +usb:v22B8p2A22* + ID_MODEL_FROM_DATABASE=V710 GSM Phone (AT) + +usb:v22B8p2A23* + ID_MODEL_FROM_DATABASE=MSM6100 chipset flash + +usb:v22B8p2A41* + ID_MODEL_FROM_DATABASE=MSM6300 chipset + +usb:v22B8p2A42* + ID_MODEL_FROM_DATABASE=Usb Modem + +usb:v22B8p2A43* + ID_MODEL_FROM_DATABASE=MSM6300 chipset flash + +usb:v22B8p2A61* + ID_MODEL_FROM_DATABASE=E815 GSM Phone (P2K) + +usb:v22B8p2A62* + ID_MODEL_FROM_DATABASE=E815 GSM Phone (AT) + +usb:v22B8p2A63* + ID_MODEL_FROM_DATABASE=MSM6500 chipset flash + +usb:v22B8p2A81* + ID_MODEL_FROM_DATABASE=MSM6025 chipset + +usb:v22B8p2A83* + ID_MODEL_FROM_DATABASE=MSM6025 chipset flash + +usb:v22B8p2AC1* + ID_MODEL_FROM_DATABASE=MSM6100 chipset + +usb:v22B8p2AC3* + ID_MODEL_FROM_DATABASE=MSM6100 chipset flash + +usb:v22B8p2D78* + ID_MODEL_FROM_DATABASE=XT300[SPICE] + +usb:v22B8p3001* + ID_MODEL_FROM_DATABASE=A835/E1000 GSM Phone (P2K) + +usb:v22B8p3002* + ID_MODEL_FROM_DATABASE=A835/E1000 GSM Phone (AT) + +usb:v22B8p3801* + ID_MODEL_FROM_DATABASE=C350L/C450 (P2K) + +usb:v22B8p3802* + ID_MODEL_FROM_DATABASE=C330/C350L/C450/EZX GSM Phone (AT) + +usb:v22B8p3803* + ID_MODEL_FROM_DATABASE=Neptune LT chipset flash + +usb:v22B8p4001* + ID_MODEL_FROM_DATABASE=OMAP 1.0 chipset + +usb:v22B8p4002* + ID_MODEL_FROM_DATABASE=A920/A925 UMTS Phone + +usb:v22B8p4003* + ID_MODEL_FROM_DATABASE=OMAP 1.0 chipset flash + +usb:v22B8p4008* + ID_MODEL_FROM_DATABASE=OMAP 1.0 chipset RDL + +usb:v22B8p41D6* + ID_MODEL_FROM_DATABASE=Droid X (Windows media mode) + +usb:v22B8p41D9* + ID_MODEL_FROM_DATABASE=Droid/Milestone + +usb:v22B8p41DB* + ID_MODEL_FROM_DATABASE=Droid/Milestone (Debug mode) + +usb:v22B8p41DE* + ID_MODEL_FROM_DATABASE=Droid X (PC mode) + +usb:v22B8p4204* + ID_MODEL_FROM_DATABASE=MPx200 Smartphone + +usb:v22B8p4214* + ID_MODEL_FROM_DATABASE=MPc GSM + +usb:v22B8p4224* + ID_MODEL_FROM_DATABASE=MPx220 Smartphone + +usb:v22B8p4234* + ID_MODEL_FROM_DATABASE=MPc CDMA + +usb:v22B8p4244* + ID_MODEL_FROM_DATABASE=MPx100 Smartphone + +usb:v22B8p4285* + ID_MODEL_FROM_DATABASE=Droid X (Mass storage) + +usb:v22B8p4801* + ID_MODEL_FROM_DATABASE=Neptune LTS chipset + +usb:v22B8p4803* + ID_MODEL_FROM_DATABASE=Neptune LTS chipset flash + +usb:v22B8p4810* + ID_MODEL_FROM_DATABASE=Triplet GSM Phone (storage) + +usb:v22B8p4901* + ID_MODEL_FROM_DATABASE=Triplet GSM Phone (P2K) + +usb:v22B8p4902* + ID_MODEL_FROM_DATABASE=Triplet GSM Phone (AT) + +usb:v22B8p4903* + ID_MODEL_FROM_DATABASE=Neptune LTE chipset flash + +usb:v22B8p4A01* + ID_MODEL_FROM_DATABASE=Neptune LTX chipset + +usb:v22B8p4A03* + ID_MODEL_FROM_DATABASE=Neptune LTX chipset flash + +usb:v22B8p4A32* + ID_MODEL_FROM_DATABASE=L6-imode Phone + +usb:v22B8p5801* + ID_MODEL_FROM_DATABASE=Neptune ULS chipset + +usb:v22B8p5803* + ID_MODEL_FROM_DATABASE=Neptune ULS chipset flash + +usb:v22B8p5901* + ID_MODEL_FROM_DATABASE=Neptune VLT chipset + +usb:v22B8p5903* + ID_MODEL_FROM_DATABASE=Neptune VLT chipset flash + +usb:v22B8p6001* + ID_MODEL_FROM_DATABASE=Dalhart EZX + +usb:v22B8p6003* + ID_MODEL_FROM_DATABASE=Dalhart flash + +usb:v22B8p6004* + ID_MODEL_FROM_DATABASE=EZX GSM Phone (CDC Net) + +usb:v22B8p6006* + ID_MODEL_FROM_DATABASE=MOTOROKR E6 + +usb:v22B8p6008* + ID_MODEL_FROM_DATABASE=Dalhart RDL + +usb:v22B8p6009* + ID_MODEL_FROM_DATABASE=EZX GSM Phone (P2K) + +usb:v22B8p600A* + ID_MODEL_FROM_DATABASE=Dalhart EZX config 17 + +usb:v22B8p600B* + ID_MODEL_FROM_DATABASE=Dalhart EZX config 18 + +usb:v22B8p600C* + ID_MODEL_FROM_DATABASE=EZX GSM Phone (USBLAN) + +usb:v22B8p6021* + ID_MODEL_FROM_DATABASE=JUIX chipset + +usb:v22B8p6023* + ID_MODEL_FROM_DATABASE=JUIX chipset flash + +usb:v22B8p6026* + ID_MODEL_FROM_DATABASE=Flash RAM Downloader/miniOS + +usb:v22B8p6027* + ID_MODEL_FROM_DATABASE=USBLAN + +usb:v22B8p604C* + ID_MODEL_FROM_DATABASE=EZX GSM Phone (Storage) + +usb:v22B8p6101* + ID_MODEL_FROM_DATABASE=Talon integrated chipset + +usb:v22B8p6401* + ID_MODEL_FROM_DATABASE=Argon chipset + +usb:v22B8p6403* + ID_MODEL_FROM_DATABASE=Argon chipset flash + +usb:v22B8p6415* + ID_MODEL_FROM_DATABASE=ROKR Z6 (MTP mode) + +usb:v22B8p6604* + ID_MODEL_FROM_DATABASE=Washington CDMA Phone + +usb:v22B8p6631* + ID_MODEL_FROM_DATABASE=CDC Modem + +usb:v22B8p7001* + ID_MODEL_FROM_DATABASE=Q Smartphone + +usb:v22B8pFE01* + ID_MODEL_FROM_DATABASE=StarTAC III MS900 + +usb:v22B9* + ID_VENDOR_FROM_DATABASE=eTurboTouch Technology, Inc. + +usb:v22B9p0006* + ID_MODEL_FROM_DATABASE=Touch Screen + +usb:v22BA* + ID_VENDOR_FROM_DATABASE=Technology Innovation Holdings, Ltd + +usb:v22E0* + ID_VENDOR_FROM_DATABASE=secunet Security Networks AG + +usb:v22E0p0002* + ID_MODEL_FROM_DATABASE=SINA Flash Drive + +usb:v22E0p0003* + ID_MODEL_FROM_DATABASE=SINA ID Token A + +usb:v2304* + ID_VENDOR_FROM_DATABASE=Pinnacle Systems, Inc. + +usb:v2304p0109* + ID_MODEL_FROM_DATABASE=Studio PCTV USB (SECAM) + +usb:v2304p0110* + ID_MODEL_FROM_DATABASE=Studio PCTV USB (PAL) + +usb:v2304p0111* + ID_MODEL_FROM_DATABASE=Miro PCTV USB + +usb:v2304p0112* + ID_MODEL_FROM_DATABASE=Studio PCTV USB (NTSC) with FM radio + +usb:v2304p0201* + ID_MODEL_FROM_DATABASE=Systems MovieBox Device + +usb:v2304p0204* + ID_MODEL_FROM_DATABASE=MovieBox USB_B + +usb:v2304p0205* + ID_MODEL_FROM_DATABASE=DVC 150B + +usb:v2304p0206* + ID_MODEL_FROM_DATABASE=Systems MovieBox Deluxe Device + +usb:v2304p0207* + ID_MODEL_FROM_DATABASE=Dazzle DVC90 Video Device + +usb:v2304p0208* + ID_MODEL_FROM_DATABASE=Studio PCTV USB2 + +usb:v2304p020E* + ID_MODEL_FROM_DATABASE=PCTV 200e + +usb:v2304p020F* + ID_MODEL_FROM_DATABASE=PCTV 400e BDA Device + +usb:v2304p0210* + ID_MODEL_FROM_DATABASE=Studio PCTV USB (PAL) with FM radio + +usb:v2304p0212* + ID_MODEL_FROM_DATABASE=Studio PCTV USB (NTSC) + +usb:v2304p0213* + ID_MODEL_FROM_DATABASE=500-USB Device + +usb:v2304p0214* + ID_MODEL_FROM_DATABASE=Studio PCTV USB (PAL) with FM radio + +usb:v2304p0216* + ID_MODEL_FROM_DATABASE=PCTV 60e + +usb:v2304p0219* + ID_MODEL_FROM_DATABASE=PCTV 260e + +usb:v2304p021A* + ID_MODEL_FROM_DATABASE=Dazzle DVC100 Audio Device + +usb:v2304p021B* + ID_MODEL_FROM_DATABASE=Dazzle DVC130/DVC170 + +usb:v2304p021D* + ID_MODEL_FROM_DATABASE=Dazzle DVC130 + +usb:v2304p021E* + ID_MODEL_FROM_DATABASE=Dazzle DVC170 + +usb:v2304p021F* + ID_MODEL_FROM_DATABASE=PCTV Sat HDTV Pro BDA Device + +usb:v2304p0222* + ID_MODEL_FROM_DATABASE=PCTV Sat Pro BDA Device + +usb:v2304p0223* + ID_MODEL_FROM_DATABASE=DazzleTV Sat BDA Device + +usb:v2304p0225* + ID_MODEL_FROM_DATABASE=Remote Kit Infrared Transceiver + +usb:v2304p0226* + ID_MODEL_FROM_DATABASE=PCTV 330e + +usb:v2304p0227* + ID_MODEL_FROM_DATABASE=PCTV for Mac, HD Stick + +usb:v2304p0228* + ID_MODEL_FROM_DATABASE=PCTV DVB-T Flash Stick + +usb:v2304p0229* + ID_MODEL_FROM_DATABASE=PCTV Dual DVB-T 2001e + +usb:v2304p022A* + ID_MODEL_FROM_DATABASE=PCTV 160e + +usb:v2304p022B* + ID_MODEL_FROM_DATABASE=PCTV 71e [Afatech AF9015] + +usb:v2304p0232* + ID_MODEL_FROM_DATABASE=PCTV 170e + +usb:v2304p0236* + ID_MODEL_FROM_DATABASE=PCTV 72e [DiBcom DiB7000PC] + +usb:v2304p0237* + ID_MODEL_FROM_DATABASE=PCTV 73e [DiBcom DiB7000PC] + +usb:v2304p023A* + ID_MODEL_FROM_DATABASE=PCTV 801e + +usb:v2304p023B* + ID_MODEL_FROM_DATABASE=PCTV 801e SE + +usb:v2304p023D* + ID_MODEL_FROM_DATABASE=PCTV 340e + +usb:v2304p023E* + ID_MODEL_FROM_DATABASE=PCTV 340e SE + +usb:v2304p0300* + ID_MODEL_FROM_DATABASE=Studio Linx Video input cable (NTSC) + +usb:v2304p0301* + ID_MODEL_FROM_DATABASE=Studio Linx Video input cable (PAL) + +usb:v2304p0302* + ID_MODEL_FROM_DATABASE=Dazzle DVC120 + +usb:v2304p0419* + ID_MODEL_FROM_DATABASE=PCTV Bungee USB (PAL) with FM radio + +usb:v2304p061D* + ID_MODEL_FROM_DATABASE=PCTV Deluxe (NTSC) Device + +usb:v2304p061E* + ID_MODEL_FROM_DATABASE=PCTV Deluxe (PAL) Device + +usb:v2318* + ID_VENDOR_FROM_DATABASE=Shining Technologies, Inc. [hex] + +usb:v2318p0011* + ID_MODEL_FROM_DATABASE=CitiDISK Jr. IDE Enclosure + +usb:v2341* + ID_VENDOR_FROM_DATABASE=Arduino SA + +usb:v2341p0001* + ID_MODEL_FROM_DATABASE=Uno (CDC ACM) + +usb:v2341p0010* + ID_MODEL_FROM_DATABASE=Mega 2560 (CDC ACM) + +usb:v2341p003B* + ID_MODEL_FROM_DATABASE=Serial Adapter (CDC ACM) + +usb:v2341p003F* + ID_MODEL_FROM_DATABASE=Mega ADK (CDC ACM) + +usb:v2341p0042* + ID_MODEL_FROM_DATABASE=Mega 2560 R3 (CDC ACM) + +usb:v2341p0043* + ID_MODEL_FROM_DATABASE=Uno R3 (CDC ACM) + +usb:v2341p0044* + ID_MODEL_FROM_DATABASE=Mega ADK R3 (CDC ACM) + +usb:v2341p0045* + ID_MODEL_FROM_DATABASE=Serial R3 (CDC ACM) + +usb:v2341p8036* + ID_MODEL_FROM_DATABASE=Leonardo (CDC ACM, HID) + +usb:v2357* + ID_VENDOR_FROM_DATABASE=TP-Link + +usb:v2357p0100* + ID_MODEL_FROM_DATABASE=TL-WN8200ND [Realtek RTL8192CU] + +usb:v2357p0101* + ID_MODEL_FROM_DATABASE=RTL8812AU Archer T4U 802.11ac + +usb:v2357p0103* + ID_MODEL_FROM_DATABASE=Archer T4UH wireless Realtek 8812AU + +usb:v2357p0105* + ID_MODEL_FROM_DATABASE=Archer T1U 802.11a/n/ac Wireless Adapter [MediaTek MT7610U] + +usb:v2357p0106* + ID_MODEL_FROM_DATABASE=Archer T9UH v1 [Realtek RTL8814AU] + +usb:v2357p0107* + ID_MODEL_FROM_DATABASE=TL-WN821N Version 5 RTL8192EU + +usb:v2357p0108* + ID_MODEL_FROM_DATABASE=TL-WN822N Version 4 RTL8192EU + +usb:v2357p0109* + ID_MODEL_FROM_DATABASE=TL WN823N RTL8192EU + +usb:v2357p010C* + ID_MODEL_FROM_DATABASE=TL-WN722N v2 + +usb:v2357p010E* + ID_MODEL_FROM_DATABASE=TL-WN722N v2 + +usb:v2357p0200* + ID_MODEL_FROM_DATABASE=MA 180 Zero CD + +usb:v2357p0201* + ID_MODEL_FROM_DATABASE=HSUPA Modem MA180 + +usb:v2373* + ID_VENDOR_FROM_DATABASE=Pumatronix Ltda + +usb:v2373p0001* + ID_MODEL_FROM_DATABASE=5 MegaPixel Digital Still Camera [DSC5M] + +usb:v2375* + ID_VENDOR_FROM_DATABASE=Digit@lway, Inc. + +usb:v2375p0001* + ID_MODEL_FROM_DATABASE=Digital Audio Player + +usb:v2406* + ID_VENDOR_FROM_DATABASE=SANHO Digital Electronics Co., Ltd. + +usb:v2406p6688* + ID_MODEL_FROM_DATABASE=PD7X Portable Storage + +usb:v2443* + ID_VENDOR_FROM_DATABASE=Aessent Technology Ltd + +usb:v2443p00DC* + ID_MODEL_FROM_DATABASE=aes220 FPGA Mini-Module + +usb:v2478* + ID_VENDOR_FROM_DATABASE=Tripp-Lite + +usb:v2478p2008* + ID_MODEL_FROM_DATABASE=U209-000-R Serial Port + +usb:v248A* + ID_VENDOR_FROM_DATABASE=Maxxter + +usb:v248Ap8366* + ID_MODEL_FROM_DATABASE=Wireless Optical Mouse ACT-MUSW-002 + +usb:v249C* + ID_VENDOR_FROM_DATABASE=M2Tech s.r.l. + +usb:v24E1* + ID_VENDOR_FROM_DATABASE=Paratronic + +usb:v24E1p3001* + ID_MODEL_FROM_DATABASE=Adp-usb + +usb:v24E1p3005* + ID_MODEL_FROM_DATABASE=Radius + +usb:v2516* + ID_VENDOR_FROM_DATABASE=Cooler Master Co., Ltd. + +usb:v2516p0003* + ID_MODEL_FROM_DATABASE=Storm Xornet + +usb:v2516p0004* + ID_MODEL_FROM_DATABASE=Storm QuickFire Rapid Mechanical Keyboard + +usb:v2516p0006* + ID_MODEL_FROM_DATABASE=Storm Recon + +usb:v2516p0007* + ID_MODEL_FROM_DATABASE=Storm Sentinel Advance II + +usb:v2516p0009* + ID_MODEL_FROM_DATABASE=Storm Quick Fire PRO + +usb:v2516p0011* + ID_MODEL_FROM_DATABASE=Storm Quick Fire TK + +usb:v2516p0017* + ID_MODEL_FROM_DATABASE=CM Storm Quick Fire Stealth + +usb:v2516p0020* + ID_MODEL_FROM_DATABASE=QuickFire Rapid-i Keyboard + +usb:v2516p0027* + ID_MODEL_FROM_DATABASE=CM Storm Coolermaster Novatouch TKL + +usb:v2516p002D* + ID_MODEL_FROM_DATABASE=Alcor mouse + +usb:v2516p0047* + ID_MODEL_FROM_DATABASE=MasterKeys Pro L + +usb:v2516p9494* + ID_MODEL_FROM_DATABASE=Sirus Headset + +usb:v2548* + ID_VENDOR_FROM_DATABASE=Pulse-Eight + +usb:v2548p1001* + ID_MODEL_FROM_DATABASE=CEC Adapter + +usb:v2548p1002* + ID_MODEL_FROM_DATABASE=CEC Adapter + +usb:v2632* + ID_VENDOR_FROM_DATABASE=TwinMOS + +usb:v2632p3209* + ID_MODEL_FROM_DATABASE=7-in-1 Card Reader + +usb:v2639* + ID_VENDOR_FROM_DATABASE=Xsens + +usb:v2639p0001* + ID_MODEL_FROM_DATABASE=MTi-10 IMU + +usb:v2639p0002* + ID_MODEL_FROM_DATABASE=MTi-20 VRU + +usb:v2639p0003* + ID_MODEL_FROM_DATABASE=MTi-30 AHRS + +usb:v2639p0011* + ID_MODEL_FROM_DATABASE=MTi-100 IMU + +usb:v2639p0012* + ID_MODEL_FROM_DATABASE=MTi-200 VRU + +usb:v2639p0013* + ID_MODEL_FROM_DATABASE=MTi-300 AHRS + +usb:v2639p0017* + ID_MODEL_FROM_DATABASE=MTi-G 7xx GNSS/INS + +usb:v2639p0100* + ID_MODEL_FROM_DATABASE=Body Pack + +usb:v2639p0101* + ID_MODEL_FROM_DATABASE=Awinda Station + +usb:v2639p0102* + ID_MODEL_FROM_DATABASE=Awinda Dongle + +usb:v2639p0103* + ID_MODEL_FROM_DATABASE=Sync Station + +usb:v2639p0200* + ID_MODEL_FROM_DATABASE=MTw + +usb:v2639pD00D* + ID_MODEL_FROM_DATABASE=Wireless Receiver + +usb:v2650* + ID_VENDOR_FROM_DATABASE=Electronics For Imaging, Inc. [hex] + +usb:v2659* + ID_VENDOR_FROM_DATABASE=Sundtek + +usb:v2659p1101* + ID_MODEL_FROM_DATABASE=TNT DVB-T/DAB/DAB+/FM + +usb:v2659p1201* + ID_MODEL_FROM_DATABASE=FM Transmitter/Receiver + +usb:v2659p1202* + ID_MODEL_FROM_DATABASE=MediaTV Analog/FM/DVB-T + +usb:v2659p1203* + ID_MODEL_FROM_DATABASE=MediaTV Analog/FM/DVB-T MiniPCIe + +usb:v2659p1204* + ID_MODEL_FROM_DATABASE=MediaTV Analog/FM/ATSC + +usb:v2659p1205* + ID_MODEL_FROM_DATABASE=SkyTV Ultimate V + +usb:v2659p1206* + ID_MODEL_FROM_DATABASE=MediaTV DVB-T MiniPCIe + +usb:v2659p1207* + ID_MODEL_FROM_DATABASE=Sundtek HD Capture + +usb:v2659p1208* + ID_MODEL_FROM_DATABASE=Sundtek SkyTV Ultimate III + +usb:v2659p1209* + ID_MODEL_FROM_DATABASE=MediaTV Analog/FM/ATSC MiniPCIe + +usb:v2659p1210* + ID_MODEL_FROM_DATABASE=MediaTV Pro III (EU) + +usb:v2659p1211* + ID_MODEL_FROM_DATABASE=MediaTV Pro III (US) + +usb:v2659p1212* + ID_MODEL_FROM_DATABASE=MediaTV Pro III MiniPCIe (EU) + +usb:v2659p1213* + ID_MODEL_FROM_DATABASE=MediaTV Pro III MiniPCIe (US) + +usb:v2676* + ID_VENDOR_FROM_DATABASE=Basler AG + +usb:v2676pBA02* + ID_MODEL_FROM_DATABASE=ace + +usb:v2717* + ID_VENDOR_FROM_DATABASE=Xiaomi Inc. + +usb:v2717p0011* + ID_MODEL_FROM_DATABASE=100Mbps Network Card Adapter + +usb:v2717p0360* + ID_MODEL_FROM_DATABASE=Mi3W + +usb:v2717p0368* + ID_MODEL_FROM_DATABASE=Mi4 LTE + +usb:v2717p3801* + ID_MODEL_FROM_DATABASE=Mi ANC & Type-C In-Ear Earphones + +usb:v2717p4106* + ID_MODEL_FROM_DATABASE=MediaTek MT7601U [MI WiFi] + +usb:v2717pFF08* + ID_MODEL_FROM_DATABASE=Redmi Note 3 (ADB Interface) + +usb:v2717pFF10* + ID_MODEL_FROM_DATABASE=Mi/Redmi series (PTP) + +usb:v2717pFF18* + ID_MODEL_FROM_DATABASE=Mi/Redmi series (PTP + ADB) + +usb:v2717pFF40* + ID_MODEL_FROM_DATABASE=Mi/Redmi series (MTP) + +usb:v2717pFF48* + ID_MODEL_FROM_DATABASE=Mi/Redmi series (MTP + ADB) + +usb:v2717pFF60* + ID_MODEL_FROM_DATABASE=redmi prime 2 + +usb:v2717pFF68* + ID_MODEL_FROM_DATABASE=Mi-4c + +usb:v2717pFF80* + ID_MODEL_FROM_DATABASE=Mi/Redmi series (RNDIS) + +usb:v2717pFF88* + ID_MODEL_FROM_DATABASE=Mi/Redmi series (RNDIS + ADB) + +usb:v2730* + ID_VENDOR_FROM_DATABASE=Citizen + +usb:v2730p200F* + ID_MODEL_FROM_DATABASE=CT-S310 Label printer + +usb:v2735* + ID_VENDOR_FROM_DATABASE=DigitalWay + +usb:v2735p0003* + ID_MODEL_FROM_DATABASE=MPIO HS100 + +usb:v2735p1001* + ID_MODEL_FROM_DATABASE=MPIO FY200 + +usb:v2735p1002* + ID_MODEL_FROM_DATABASE=MPIO FL100 + +usb:v2735p1003* + ID_MODEL_FROM_DATABASE=MPIO FD100 + +usb:v2735p1004* + ID_MODEL_FROM_DATABASE=MPIO HD200 + +usb:v2735p1005* + ID_MODEL_FROM_DATABASE=MPIO HD300 + +usb:v2735p1006* + ID_MODEL_FROM_DATABASE=MPIO FG100 + +usb:v2735p1007* + ID_MODEL_FROM_DATABASE=MPIO FG130 + +usb:v2735p1008* + ID_MODEL_FROM_DATABASE=MPIO FY300 + +usb:v2735p1009* + ID_MODEL_FROM_DATABASE=MPIO FY400 + +usb:v2735p100A* + ID_MODEL_FROM_DATABASE=MPIO FL300 + +usb:v2735p100B* + ID_MODEL_FROM_DATABASE=MPIO HS200 + +usb:v2735p100C* + ID_MODEL_FROM_DATABASE=MPIO FL350 + +usb:v2735p100D* + ID_MODEL_FROM_DATABASE=MPIO FY500 + +usb:v2735p100E* + ID_MODEL_FROM_DATABASE=MPIO FY500 + +usb:v2735p100F* + ID_MODEL_FROM_DATABASE=MPIO FY600 + +usb:v2735p1012* + ID_MODEL_FROM_DATABASE=MPIO FL400 + +usb:v2735p1013* + ID_MODEL_FROM_DATABASE=MPIO HD400 + +usb:v2735p1014* + ID_MODEL_FROM_DATABASE=MPIO HD400 + +usb:v2735p1016* + ID_MODEL_FROM_DATABASE=MPIO FY700 + +usb:v2735p1017* + ID_MODEL_FROM_DATABASE=MPIO FY700 + +usb:v2735p1018* + ID_MODEL_FROM_DATABASE=MPIO FY800 + +usb:v2735p1019* + ID_MODEL_FROM_DATABASE=MPIO FY800 + +usb:v2735p101A* + ID_MODEL_FROM_DATABASE=MPIO FY900 + +usb:v2735p101B* + ID_MODEL_FROM_DATABASE=MPIO FY900 + +usb:v2735p102B* + ID_MODEL_FROM_DATABASE=MPIO FL500 + +usb:v2735p102C* + ID_MODEL_FROM_DATABASE=MPIO FL500 + +usb:v2735p103F* + ID_MODEL_FROM_DATABASE=MPIO FY570 + +usb:v2735p1040* + ID_MODEL_FROM_DATABASE=MPIO FY570 + +usb:v2735p1041* + ID_MODEL_FROM_DATABASE=MPIO FY670 + +usb:v2735p1042* + ID_MODEL_FROM_DATABASE=MPIO FY670 + +usb:v2735p1043* + ID_MODEL_FROM_DATABASE=HCT HMD-180A + +usb:v2735p1044* + ID_MODEL_FROM_DATABASE=HCT HMD-180A + +usb:v273F* + ID_VENDOR_FROM_DATABASE=Hughski Limited + +usb:v273Fp1000* + ID_MODEL_FROM_DATABASE=ColorHug bootloader + +usb:v273Fp1001* + ID_MODEL_FROM_DATABASE=ColorHug + +usb:v273Fp1002* + ID_MODEL_FROM_DATABASE=ColorHug+ + +usb:v273Fp1003* + ID_MODEL_FROM_DATABASE=ColorHug+ Bootloader + +usb:v273Fp1004* + ID_MODEL_FROM_DATABASE=ColorHug2 + +usb:v273Fp1005* + ID_MODEL_FROM_DATABASE=ColorHug2 bootloader + +usb:v2770* + ID_VENDOR_FROM_DATABASE=NHJ, Ltd + +usb:v2770p0A01* + ID_MODEL_FROM_DATABASE=ScanJet 4600 series + +usb:v2770p905C* + ID_MODEL_FROM_DATABASE=Che-Ez Snap SNAP-U/Digigr8/Soundstar TDC-35 + +usb:v2770p9060* + ID_MODEL_FROM_DATABASE=A130 + +usb:v2770p9120* + ID_MODEL_FROM_DATABASE=Che-ez! Snap / iClick Tiny VGA Digital Camera + +usb:v2770p9130* + ID_MODEL_FROM_DATABASE=TCG 501 + +usb:v2770p913C* + ID_MODEL_FROM_DATABASE=Argus DC-1730 + +usb:v2770p9150* + ID_MODEL_FROM_DATABASE=Mini Cam + +usb:v2770p9153* + ID_MODEL_FROM_DATABASE=iClick 5X + +usb:v2770p915D* + ID_MODEL_FROM_DATABASE=Cyberpix S-210S / Little Tikes My Real Digital Camera + +usb:v2770p930B* + ID_MODEL_FROM_DATABASE=CCD Webcam(PC370R) + +usb:v2770p930C* + ID_MODEL_FROM_DATABASE=CCD Webcam(PC370R) + +usb:v27B8* + ID_VENDOR_FROM_DATABASE=ThingM + +usb:v27B8p01ED* + ID_MODEL_FROM_DATABASE=blink(1) + +usb:v27C6* + ID_VENDOR_FROM_DATABASE=Shenzhen Goodix Technology Co.,Ltd. + +usb:v27C6p5117* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v27C6p5201* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v27C6p5301* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v27C6p530C* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v27C6p5385* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v27C6p538C* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v27C6p5395* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v27C6p5584* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v27C6p55B4* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v27C6p5740* + ID_MODEL_FROM_DATABASE=Fingerprint Reader + +usb:v2821* + ID_VENDOR_FROM_DATABASE=ASUSTek Computer Inc. + +usb:v2821p0161* + ID_MODEL_FROM_DATABASE=WL-161 802.11b Wireless Adapter [SiS 162U] + +usb:v2821p160F* + ID_MODEL_FROM_DATABASE=WL-160g 802.11g Wireless Adapter [Envara WiND512] + +usb:v2821p3300* + ID_MODEL_FROM_DATABASE=WL-140 / Hawking HWU36D 802.11b Wireless Adapter [Intersil PRISM 3] + +usb:v2899* + ID_VENDOR_FROM_DATABASE=Toptronic Industrial Co., Ltd + +usb:v2899p012C* + ID_MODEL_FROM_DATABASE=Camera Device + +usb:v289B* + ID_VENDOR_FROM_DATABASE=Dracal/Raphnet technologies + +usb:v289Bp0001* + ID_MODEL_FROM_DATABASE=Gamecube/N64 controller v2.2 + +usb:v289Bp0002* + ID_MODEL_FROM_DATABASE=2nes2snes + +usb:v289Bp0003* + ID_MODEL_FROM_DATABASE=4nes4snes + +usb:v289Bp0004* + ID_MODEL_FROM_DATABASE=Gamecube/N64 controller v2.3 + +usb:v289Bp0005* + ID_MODEL_FROM_DATABASE=Saturn (Joystick mode) + +usb:v289Bp0006* + ID_MODEL_FROM_DATABASE=Saturn (Mouse mode) + +usb:v289Bp0007* + ID_MODEL_FROM_DATABASE=Famicom controller + +usb:v289Bp0008* + ID_MODEL_FROM_DATABASE=Dreamcast (Joystick mode) + +usb:v289Bp0009* + ID_MODEL_FROM_DATABASE=Dreamcast (Mouse mode) + +usb:v289Bp000A* + ID_MODEL_FROM_DATABASE=Dreamcast (Keyboard mode) + +usb:v289Bp000B* + ID_MODEL_FROM_DATABASE=Gamecube/N64 controller v2.9 (Keyboard mode) + +usb:v289Bp000C* + ID_MODEL_FROM_DATABASE=Gamecube/N64 controller v2.9 (Joystick mode) + +usb:v289Bp0100* + ID_MODEL_FROM_DATABASE=Dual-relay board + +usb:v289Bp0500* + ID_MODEL_FROM_DATABASE=Energy meter + +usb:v289Bp0502* + ID_MODEL_FROM_DATABASE=Precision barometer + +usb:v28DE* + ID_VENDOR_FROM_DATABASE=Valve Software + +usb:v28DEp1102* + ID_MODEL_FROM_DATABASE=Wired Controller + +usb:v28DEp1142* + ID_MODEL_FROM_DATABASE=Wireless Steam Controller + +usb:v28DEp2000* + ID_MODEL_FROM_DATABASE=Lighthouse FPGA RX + +usb:v28DEp2101* + ID_MODEL_FROM_DATABASE=Watchman Dongle + +usb:v2931* + ID_VENDOR_FROM_DATABASE=Jolla Oy + +usb:v2931p0A01* + ID_MODEL_FROM_DATABASE=Jolla Phone MTP + +usb:v2931p0A02* + ID_MODEL_FROM_DATABASE=Jolla Phone Developer + +usb:v2931p0A05* + ID_MODEL_FROM_DATABASE=Jolla PC connection + +usb:v2931p0AFE* + ID_MODEL_FROM_DATABASE=Jolla charging only + +usb:v2939* + ID_VENDOR_FROM_DATABASE=Zaber Technologies Inc. + +usb:v2939p4959* + ID_MODEL_FROM_DATABASE=A-MCB2 + +usb:v2939p495A* + ID_MODEL_FROM_DATABASE=X-MCB1 + +usb:v2939p495B* + ID_MODEL_FROM_DATABASE=X-MCB2 + +usb:v2A03* + ID_VENDOR_FROM_DATABASE=dog hunter AG + +usb:v2A03p0001* + ID_MODEL_FROM_DATABASE=Linino ONE (bootloader) + +usb:v2A03p0036* + ID_MODEL_FROM_DATABASE=Arduino Leonardo (bootloader) + +usb:v2A03p0037* + ID_MODEL_FROM_DATABASE=Arduino Micro (bootloader) + +usb:v2A03p0038* + ID_MODEL_FROM_DATABASE=Arduino Robot Control (bootloader) + +usb:v2A03p0039* + ID_MODEL_FROM_DATABASE=Arduino Robot Motor (bootloader) + +usb:v2A03p003A* + ID_MODEL_FROM_DATABASE=Arduino Micro ADK rev3 (bootloader) + +usb:v2A03p003B* + ID_MODEL_FROM_DATABASE=Arduino Serial + +usb:v2A03p003C* + ID_MODEL_FROM_DATABASE=Arduino Explora (bootloader) + +usb:v2A03p003D* + ID_MODEL_FROM_DATABASE=Arduino Due (usb2serial) + +usb:v2A03p003E* + ID_MODEL_FROM_DATABASE=Arduino Due + +usb:v2A03p0041* + ID_MODEL_FROM_DATABASE=Arduino Yun (bootloader) + +usb:v2A03p0042* + ID_MODEL_FROM_DATABASE=Arduino Mega 2560 Rev3 + +usb:v2A03p0043* + ID_MODEL_FROM_DATABASE=Arduino Uno Rev3 + +usb:v2A03p004D* + ID_MODEL_FROM_DATABASE=Arduino Zero Pro (bootloader) + +usb:v2A03p8001* + ID_MODEL_FROM_DATABASE=Linino ONE (CDC ACM) + +usb:v2A03p8036* + ID_MODEL_FROM_DATABASE=Arduino Leonardo (CDC ACM) + +usb:v2A03p8037* + ID_MODEL_FROM_DATABASE=Arduino Micro (CDC ACM) + +usb:v2A03p8038* + ID_MODEL_FROM_DATABASE=Arduino Robot Control (CDC ACM) + +usb:v2A03p8039* + ID_MODEL_FROM_DATABASE=Arduino Robot Motor (CDC ACM) + +usb:v2A03p803A* + ID_MODEL_FROM_DATABASE=Arduino Micro ADK rev3 (CDC ACM) + +usb:v2A03p803C* + ID_MODEL_FROM_DATABASE=Arduino Explora (CDC ACM) + +usb:v2A03p8041* + ID_MODEL_FROM_DATABASE=Arduino Yun (CDC ACM) + +usb:v2A03p804D* + ID_MODEL_FROM_DATABASE=Arduino Zero Pro (CDC ACM) + +usb:v2A37* + ID_VENDOR_FROM_DATABASE=RTD Embedded Technologies, Inc. + +usb:v2A37p5110* + ID_MODEL_FROM_DATABASE=UPS35110/UPS25110 + +usb:v2A45* + ID_VENDOR_FROM_DATABASE=Meizu Corp. + +usb:v2A45p0001* + ID_MODEL_FROM_DATABASE=MX Phone (BICR) + +usb:v2A45p0C02* + ID_MODEL_FROM_DATABASE=MX Phone (MTP & ADB) + +usb:v2A45p0C03* + ID_MODEL_FROM_DATABASE=MX Phone (BICR & ADB) + +usb:v2A45p2008* + ID_MODEL_FROM_DATABASE=MX Phone (MTP) + +usb:v2A45p200A* + ID_MODEL_FROM_DATABASE=MX Phone (MTP & ACM & ADB) + +usb:v2A45p200B* + ID_MODEL_FROM_DATABASE=MX Phone (PTP) + +usb:v2A45p200C* + ID_MODEL_FROM_DATABASE=MX Phone (PTP & ADB) + +usb:v2A45p2012* + ID_MODEL_FROM_DATABASE=MX Phone (MTP & ACM) + +usb:v2AC7* + ID_VENDOR_FROM_DATABASE=Ultrahaptics Ltd. + +usb:v2AC7p0101* + ID_MODEL_FROM_DATABASE=Evaluation Kit [Dragonfly] + +usb:v2AC7p0102* + ID_MODEL_FROM_DATABASE=UHDK5 + +usb:v2AC7p0104* + ID_MODEL_FROM_DATABASE=Touchbase + +usb:v2AC7p0110* + ID_MODEL_FROM_DATABASE=STRATOS Explore + +usb:v2AC7p0111* + ID_MODEL_FROM_DATABASE=STRATOS Explore DFU + +usb:v2AC7p0112* + ID_MODEL_FROM_DATABASE=STRATOS Inspire + +usb:v2AC7p0113* + ID_MODEL_FROM_DATABASE=STRATOS Inspire DFU + +usb:v2AC7pFFFF* + ID_MODEL_FROM_DATABASE=DFU + +usb:v2B24* + ID_VENDOR_FROM_DATABASE=KeepKey LLC + +usb:v2B24p0001* + ID_MODEL_FROM_DATABASE=Bitcoin hardware wallet + +usb:v2C02* + ID_VENDOR_FROM_DATABASE=Planex Communications + +usb:v2C02p14EA* + ID_MODEL_FROM_DATABASE=GW-US11H WLAN + +usb:v2C1A* + ID_VENDOR_FROM_DATABASE=Dolphin Peripherals + +usb:v2C1Ap0000* + ID_MODEL_FROM_DATABASE=Wireless Optical Mouse + +usb:v2C7C* + ID_VENDOR_FROM_DATABASE=Quectel Wireless Solutions Co., Ltd. + +usb:v2C7Cp0121* + ID_MODEL_FROM_DATABASE=EC21 LTE modem + +usb:v2C7Cp0125* + ID_MODEL_FROM_DATABASE=EC25 LTE modem + +usb:v2C7Cp0191* + ID_MODEL_FROM_DATABASE=EG91 LTE modem + +usb:v2C7Cp0195* + ID_MODEL_FROM_DATABASE=EG95 LTE modem + +usb:v2C7Cp0296* + ID_MODEL_FROM_DATABASE=BG96 CAT-M1/NB-IoT modem + +usb:v2C7Cp0306* + ID_MODEL_FROM_DATABASE=EG06/EP06/EM06 LTE-A modem + +usb:v2C7Cp0435* + ID_MODEL_FROM_DATABASE=AG35 LTE modem + +usb:v2CDC* + ID_VENDOR_FROM_DATABASE=Sea & Sun Technology GmbH + +usb:v2CDCpF232* + ID_MODEL_FROM_DATABASE=CTD48Mc CTD Probe + +usb:v2DCF* + ID_VENDOR_FROM_DATABASE=Dialog Semiconductor + +usb:v2DCFpC952* + ID_MODEL_FROM_DATABASE=Audio Class 2.0 Devices + +usb:v2FB2* + ID_VENDOR_FROM_DATABASE=Fujitsu, Ltd + +usb:v3016* + ID_VENDOR_FROM_DATABASE=Boundary Devices, LLC + +usb:v3016p0001* + ID_MODEL_FROM_DATABASE=Nitrogen Bootloader + +usb:v30A4* + ID_VENDOR_FROM_DATABASE=Blues Wireless + +usb:v30A4p0001* + ID_MODEL_FROM_DATABASE=Notecard + +usb:v30C2* + ID_VENDOR_FROM_DATABASE=UNPARALLEL Innovation, Lda + +usb:v30C2p1388* + ID_MODEL_FROM_DATABASE=SPL Meter + +usb:v30EE* + ID_VENDOR_FROM_DATABASE=Fujitsu Connected Technologies Limited + +usb:v30EEp1001* + ID_MODEL_FROM_DATABASE=F-01L + +usb:v3125* + ID_VENDOR_FROM_DATABASE=Eagletron + +usb:v3125p0001* + ID_MODEL_FROM_DATABASE=TrackerPod Camera Stand + +usb:v3136* + ID_VENDOR_FROM_DATABASE=Navini Networks + +usb:v3176* + ID_VENDOR_FROM_DATABASE=Whanam Electronics Co., Ltd + +usb:v3195* + ID_VENDOR_FROM_DATABASE=Link Instruments + +usb:v3195pF190* + ID_MODEL_FROM_DATABASE=MSO-19 + +usb:v3195pF280* + ID_MODEL_FROM_DATABASE=MSO-28 + +usb:v3195pF281* + ID_MODEL_FROM_DATABASE=MSO-28 + +usb:v3275* + ID_VENDOR_FROM_DATABASE=VidzMedia Pte Ltd + +usb:v3275p4FB1* + ID_MODEL_FROM_DATABASE=MonsterTV P2H + +usb:v3333* + ID_VENDOR_FROM_DATABASE=InLine + +usb:v3333p3333* + ID_MODEL_FROM_DATABASE=2 port KVM switch model 60652K + +usb:v3334* + ID_VENDOR_FROM_DATABASE=AEI + +usb:v3334p1701* + ID_MODEL_FROM_DATABASE=Fast Ethernet + +usb:v3340* + ID_VENDOR_FROM_DATABASE=Yakumo + +usb:v3340p043A* + ID_MODEL_FROM_DATABASE=Mio A701 DigiWalker PPCPhone + +usb:v3340p0E3A* + ID_MODEL_FROM_DATABASE=Pocket PC 300 GPS SL / Typhoon MyGuide 3500 + +usb:v3340pA0A3* + ID_MODEL_FROM_DATABASE=deltaX 5 BT (D) PDA + +usb:v3344* + ID_VENDOR_FROM_DATABASE=Leaguer Microelectronics (LME) + +usb:v3344p3744* + ID_MODEL_FROM_DATABASE=OEM PC Remote + +usb:v3504* + ID_VENDOR_FROM_DATABASE=Micro Star + +usb:v3504pF110* + ID_MODEL_FROM_DATABASE=Security Key + +usb:v3538* + ID_VENDOR_FROM_DATABASE=Power Quotient International Co., Ltd + +usb:v3538p0001* + ID_MODEL_FROM_DATABASE=Travel Flash + +usb:v3538p0015* + ID_MODEL_FROM_DATABASE=Mass Storge Device + +usb:v3538p0022* + ID_MODEL_FROM_DATABASE=Hi-Speed Mass Storage Device + +usb:v3538p0042* + ID_MODEL_FROM_DATABASE=Cool Drive U339 Flash Disk + +usb:v3538p0054* + ID_MODEL_FROM_DATABASE=Flash Drive (2GB) + +usb:v3579* + ID_VENDOR_FROM_DATABASE=DIVA + +usb:v3579p6901* + ID_MODEL_FROM_DATABASE=Media Reader + +usb:v357D* + ID_VENDOR_FROM_DATABASE=Sharkoon + +usb:v357Dp7788* + ID_MODEL_FROM_DATABASE=QuickPort XT + +usb:v3636* + ID_VENDOR_FROM_DATABASE=InVibro + +usb:v3838* + ID_VENDOR_FROM_DATABASE=WEM + +usb:v3838p0001* + ID_MODEL_FROM_DATABASE=5-in-1 Card Reader + +usb:v3923* + ID_VENDOR_FROM_DATABASE=National Instruments Corp. + +usb:v3923p12C0* + ID_MODEL_FROM_DATABASE=DAQPad-6020E + +usb:v3923p12D0* + ID_MODEL_FROM_DATABASE=DAQPad-6507 + +usb:v3923p12E0* + ID_MODEL_FROM_DATABASE=NI 4350 + +usb:v3923p12F0* + ID_MODEL_FROM_DATABASE=NI 5102 + +usb:v3923p1750* + ID_MODEL_FROM_DATABASE=DAQPad-6508 + +usb:v3923p17B0* + ID_MODEL_FROM_DATABASE=USB-ISA-Bridge + +usb:v3923p1820* + ID_MODEL_FROM_DATABASE=DAQPad-6020E (68 pin I/O) + +usb:v3923p1830* + ID_MODEL_FROM_DATABASE=DAQPad-6020E (BNC) + +usb:v3923p1F00* + ID_MODEL_FROM_DATABASE=DAQPad-6024E + +usb:v3923p1F10* + ID_MODEL_FROM_DATABASE=DAQPad-6024E + +usb:v3923p1F20* + ID_MODEL_FROM_DATABASE=DAQPad-6025E + +usb:v3923p1F30* + ID_MODEL_FROM_DATABASE=DAQPad-6025E + +usb:v3923p1F40* + ID_MODEL_FROM_DATABASE=DAQPad-6036E + +usb:v3923p1F50* + ID_MODEL_FROM_DATABASE=DAQPad-6036E + +usb:v3923p2F80* + ID_MODEL_FROM_DATABASE=DAQPad-6052E + +usb:v3923p2F90* + ID_MODEL_FROM_DATABASE=DAQPad-6052E + +usb:v3923p702B* + ID_MODEL_FROM_DATABASE=GPIB-USB-B + +usb:v3923p703C* + ID_MODEL_FROM_DATABASE=USB-485 RS485 Cable + +usb:v3923p709B* + ID_MODEL_FROM_DATABASE=GPIB-USB-HS + +usb:v3923p7254* + ID_MODEL_FROM_DATABASE=NI MIO (data acquisition card) firmware updater + +usb:v3923p729E* + ID_MODEL_FROM_DATABASE=USB-6251 (OEM) data acquisition card + +usb:v40BB* + ID_VENDOR_FROM_DATABASE=I-O Data + +usb:v40BBp0A09* + ID_MODEL_FROM_DATABASE=USB2.0-SCSI Bridge USB2-SC + +usb:v4101* + ID_VENDOR_FROM_DATABASE=i-rocks + +usb:v4101p1301* + ID_MODEL_FROM_DATABASE=IR-2510 usb phone + +usb:v4102* + ID_VENDOR_FROM_DATABASE=iRiver, Ltd. + +usb:v4102p1001* + ID_MODEL_FROM_DATABASE=iFP-100 series mp3 player + +usb:v4102p1003* + ID_MODEL_FROM_DATABASE=iFP-300 series mp3 player + +usb:v4102p1005* + ID_MODEL_FROM_DATABASE=iFP-500 series mp3 player + +usb:v4102p1007* + ID_MODEL_FROM_DATABASE=iFP-700 series mp3/ogg vorbis player + +usb:v4102p1008* + ID_MODEL_FROM_DATABASE=iFP-800 series mp3/ogg vorbis player + +usb:v4102p100A* + ID_MODEL_FROM_DATABASE=iFP-1000 series mp3/ogg vorbis player + +usb:v4102p1014* + ID_MODEL_FROM_DATABASE=T20 series mp3/ogg vorbis player (ums firmware) + +usb:v4102p1019* + ID_MODEL_FROM_DATABASE=T30 + +usb:v4102p1034* + ID_MODEL_FROM_DATABASE=T60 + +usb:v4102p1040* + ID_MODEL_FROM_DATABASE=M1Player + +usb:v4102p1041* + ID_MODEL_FROM_DATABASE=E100 (ums) + +usb:v4102p1101* + ID_MODEL_FROM_DATABASE=iFP-100 series mp3 player (ums firmware) + +usb:v4102p1103* + ID_MODEL_FROM_DATABASE=iFP-300 series mp3 player (ums firmware) + +usb:v4102p1105* + ID_MODEL_FROM_DATABASE=iFP-500 series mp3 player (ums firmware) + +usb:v4102p1113* + ID_MODEL_FROM_DATABASE=T10 (alternate) + +usb:v4102p1117* + ID_MODEL_FROM_DATABASE=T10 + +usb:v4102p1119* + ID_MODEL_FROM_DATABASE=T30 series mp3/ogg/wma player + +usb:v4102p1141* + ID_MODEL_FROM_DATABASE=E100 (mtp) + +usb:v4102p2002* + ID_MODEL_FROM_DATABASE=H10 6GB + +usb:v4102p2101* + ID_MODEL_FROM_DATABASE=H10 20GB (mtp) + +usb:v4102p2102* + ID_MODEL_FROM_DATABASE=H10 5GB (mtp) + +usb:v4102p2105* + ID_MODEL_FROM_DATABASE=H10 5/6GB (mtp) + +usb:v413C* + ID_VENDOR_FROM_DATABASE=Dell Computer Corp. + +usb:v413Cp0000* + ID_MODEL_FROM_DATABASE=DRAC 5 Virtual Keyboard and Mouse + +usb:v413Cp0001* + ID_MODEL_FROM_DATABASE=DRAC 5 Virtual Media + +usb:v413Cp0058* + ID_MODEL_FROM_DATABASE=Port Replicator + +usb:v413Cp1001* + ID_MODEL_FROM_DATABASE=Keyboard Hub + +usb:v413Cp1002* + ID_MODEL_FROM_DATABASE=Keyboard Hub + +usb:v413Cp1003* + ID_MODEL_FROM_DATABASE=Keyboard Hub + +usb:v413Cp1005* + ID_MODEL_FROM_DATABASE=Multimedia Pro Keyboard Hub + +usb:v413Cp2001* + ID_MODEL_FROM_DATABASE=Keyboard HID Support + +usb:v413Cp2002* + ID_MODEL_FROM_DATABASE=SK-8125 Keyboard + +usb:v413Cp2003* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v413Cp2005* + ID_MODEL_FROM_DATABASE=RT7D50 Keyboard + +usb:v413Cp2010* + ID_MODEL_FROM_DATABASE=Keyboard + +usb:v413Cp2011* + ID_MODEL_FROM_DATABASE=Multimedia Pro Keyboard + +usb:v413Cp2100* + ID_MODEL_FROM_DATABASE=SK-3106 Keyboard + +usb:v413Cp2101* + ID_MODEL_FROM_DATABASE=SmartCard Reader Keyboard + +usb:v413Cp2105* + ID_MODEL_FROM_DATABASE=Model L100 Keyboard + +usb:v413Cp2106* + ID_MODEL_FROM_DATABASE=Dell QuietKey Keyboard + +usb:v413Cp2500* + ID_MODEL_FROM_DATABASE=DRAC4 Remote Access Card + +usb:v413Cp2513* + ID_MODEL_FROM_DATABASE=internal USB Hub of E-Port Replicator + +usb:v413Cp3010* + ID_MODEL_FROM_DATABASE=Optical Wheel Mouse + +usb:v413Cp3012* + ID_MODEL_FROM_DATABASE=Optical Wheel Mouse + +usb:v413Cp3016* + ID_MODEL_FROM_DATABASE=Optical 5-Button Wheel Mouse + +usb:v413Cp3200* + ID_MODEL_FROM_DATABASE=Mouse + +usb:v413Cp4001* + ID_MODEL_FROM_DATABASE=Axim X5 + +usb:v413Cp4002* + ID_MODEL_FROM_DATABASE=Axim X3 + +usb:v413Cp4003* + ID_MODEL_FROM_DATABASE=Axim X30 + +usb:v413Cp4004* + ID_MODEL_FROM_DATABASE=Axim Sync + +usb:v413Cp4005* + ID_MODEL_FROM_DATABASE=Axim Sync + +usb:v413Cp4006* + ID_MODEL_FROM_DATABASE=Axim Sync + +usb:v413Cp4007* + ID_MODEL_FROM_DATABASE=Axim Sync + +usb:v413Cp4008* + ID_MODEL_FROM_DATABASE=Axim Sync + +usb:v413Cp4009* + ID_MODEL_FROM_DATABASE=Axim Sync + +usb:v413Cp4011* + ID_MODEL_FROM_DATABASE=Axim X51v + +usb:v413Cp5103* + ID_MODEL_FROM_DATABASE=AIO Printer A940 + +usb:v413Cp5105* + ID_MODEL_FROM_DATABASE=AIO Printer A920 + +usb:v413Cp5107* + ID_MODEL_FROM_DATABASE=AIO Printer A960 + +usb:v413Cp5109* + ID_MODEL_FROM_DATABASE=Photo AIO Printer 922 + +usb:v413Cp5110* + ID_MODEL_FROM_DATABASE=Photo AIO Printer 962 + +usb:v413Cp5111* + ID_MODEL_FROM_DATABASE=Photo AIO Printer 942 + +usb:v413Cp5112* + ID_MODEL_FROM_DATABASE=Photo AIO Printer 924 + +usb:v413Cp5113* + ID_MODEL_FROM_DATABASE=Photo AIO Printer 944 + +usb:v413Cp5114* + ID_MODEL_FROM_DATABASE=Photo AIO Printer 964 + +usb:v413Cp5115* + ID_MODEL_FROM_DATABASE=Photo AIO Printer 926 + +usb:v413Cp5116* + ID_MODEL_FROM_DATABASE=AIO Printer 946 + +usb:v413Cp5117* + ID_MODEL_FROM_DATABASE=Photo AIO Printer 966 + +usb:v413Cp5118* + ID_MODEL_FROM_DATABASE=AIO 810 + +usb:v413Cp5124* + ID_MODEL_FROM_DATABASE=Laser MFP 1815 + +usb:v413Cp5128* + ID_MODEL_FROM_DATABASE=Photo AIO 928 + +usb:v413Cp5200* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v413Cp5202* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v413Cp5203* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v413Cp5210* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v413Cp5211* + ID_MODEL_FROM_DATABASE=1110 Laser Printer + +usb:v413Cp5220* + ID_MODEL_FROM_DATABASE=Laser MFP 1600n + +usb:v413Cp5225* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v413Cp5226* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v413Cp5300* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v413Cp5400* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v413Cp5401* + ID_MODEL_FROM_DATABASE=Laser Printer + +usb:v413Cp5513* + ID_MODEL_FROM_DATABASE=WLA3310 Wireless Adapter [Intersil ISL3887] + +usb:v413Cp5601* + ID_MODEL_FROM_DATABASE=Laser Printer 3100cn + +usb:v413Cp5602* + ID_MODEL_FROM_DATABASE=Laser Printer 3000cn + +usb:v413Cp5631* + ID_MODEL_FROM_DATABASE=Laser Printer 5100cn + +usb:v413Cp5905* + ID_MODEL_FROM_DATABASE=Printing Support + +usb:v413Cp8000* + ID_MODEL_FROM_DATABASE=BC02 Bluetooth Adapter + +usb:v413Cp8010* + ID_MODEL_FROM_DATABASE=TrueMobile Bluetooth Module in + +usb:v413Cp8100* + ID_MODEL_FROM_DATABASE=TrueMobile 1180 802.11b Adapter [Intersil PRISM 3] + +usb:v413Cp8102* + ID_MODEL_FROM_DATABASE=TrueMobile 1300 802.11g Wireless Adapter [Intersil ISL3880] + +usb:v413Cp8103* + ID_MODEL_FROM_DATABASE=Wireless 350 Bluetooth + +usb:v413Cp8104* + ID_MODEL_FROM_DATABASE=Wireless 1450 Dual-band (802.11a/b/g) Adapter [Intersil ISL3887] + +usb:v413Cp8105* + ID_MODEL_FROM_DATABASE=U2 in HID - Driver + +usb:v413Cp8106* + ID_MODEL_FROM_DATABASE=Wireless 350 Bluetooth Internal Card in + +usb:v413Cp8110* + ID_MODEL_FROM_DATABASE=Wireless 3xx Bluetooth Internal Card + +usb:v413Cp8111* + ID_MODEL_FROM_DATABASE=Wireless 3xx Bluetooth Internal Card in + +usb:v413Cp8114* + ID_MODEL_FROM_DATABASE=Wireless 5700 Mobile Broadband (CDMA EV-DO) Minicard Modem + +usb:v413Cp8115* + ID_MODEL_FROM_DATABASE=Wireless 5500 Mobile Broadband (3G HSDPA) Minicard Modem + +usb:v413Cp8116* + ID_MODEL_FROM_DATABASE=Wireless 5505 Mobile Broadband (3G HSDPA) Minicard Modem + +usb:v413Cp8117* + ID_MODEL_FROM_DATABASE=Wireless 5700 Mobile Broadband (CDMA EV-DO) Expresscard Modem + +usb:v413Cp8118* + ID_MODEL_FROM_DATABASE=Wireless 5510 Mobile Broadband (3G HSDPA) Expresscard Status Port + +usb:v413Cp8120* + ID_MODEL_FROM_DATABASE=Bluetooth adapter + +usb:v413Cp8121* + ID_MODEL_FROM_DATABASE=Eastfold in HID + +usb:v413Cp8122* + ID_MODEL_FROM_DATABASE=Eastfold in DFU + +usb:v413Cp8123* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v413Cp8124* + ID_MODEL_FROM_DATABASE=eHome Infrared Receiver + +usb:v413Cp8126* + ID_MODEL_FROM_DATABASE=Wireless 355 Bluetooth + +usb:v413Cp8127* + ID_MODEL_FROM_DATABASE=Wireless 355 Module with Bluetooth 2.0 + EDR Technology. + +usb:v413Cp8128* + ID_MODEL_FROM_DATABASE=Wireless 5700-Sprint Mobile Broadband (CDMA EV-DO) Mini-Card Status Port + +usb:v413Cp8129* + ID_MODEL_FROM_DATABASE=Wireless 5700-Telus Mobile Broadband (CDMA EV-DO) Mini-Card Status Port + +usb:v413Cp8131* + ID_MODEL_FROM_DATABASE=Wireless 360 Bluetooth 2.0 + EDR module. + +usb:v413Cp8133* + ID_MODEL_FROM_DATABASE=Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port + +usb:v413Cp8134* + ID_MODEL_FROM_DATABASE=Wireless 5720 Sprint Mobile Broadband (EVDO Rev-A) Minicard Status Port + +usb:v413Cp8135* + ID_MODEL_FROM_DATABASE=Wireless 5720 TELUS Mobile Broadband (EVDO Rev-A) Minicard Diagnostics Port + +usb:v413Cp8136* + ID_MODEL_FROM_DATABASE=Wireless 5520 Cingular Mobile Broadband (3G HSDPA) Minicard Diagnostics Port + +usb:v413Cp8137* + ID_MODEL_FROM_DATABASE=Wireless 5520 Voda L Mobile Broadband (3G HSDPA) Minicard Status Port + +usb:v413Cp8138* + ID_MODEL_FROM_DATABASE=Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard EAP-SIM Port + +usb:v413Cp8140* + ID_MODEL_FROM_DATABASE=Wireless 360 Bluetooth + +usb:v413Cp8142* + ID_MODEL_FROM_DATABASE=Mobile 360 in DFU + +usb:v413Cp8147* + ID_MODEL_FROM_DATABASE=F3507g Mobile Broadband Module + +usb:v413Cp8156* + ID_MODEL_FROM_DATABASE=Wireless 370 Bluetooth Mini-card + +usb:v413Cp8157* + ID_MODEL_FROM_DATABASE=Integrated Keyboard + +usb:v413Cp8158* + ID_MODEL_FROM_DATABASE=Integrated Touchpad / Trackstick + +usb:v413Cp8160* + ID_MODEL_FROM_DATABASE=Wireless 365 Bluetooth + +usb:v413Cp8161* + ID_MODEL_FROM_DATABASE=Integrated Keyboard + +usb:v413Cp8162* + ID_MODEL_FROM_DATABASE=Integrated Touchpad [Synaptics] + +usb:v413Cp8171* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem (QDL mode) + +usb:v413Cp8172* + ID_MODEL_FROM_DATABASE=Gobi Wireless Modem + +usb:v413Cp8183* + ID_MODEL_FROM_DATABASE=F3607gw Mobile Broadband Module + +usb:v413Cp8184* + ID_MODEL_FROM_DATABASE=F3607gw v2 Mobile Broadband Module + +usb:v413Cp8185* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem (QDL mode) + +usb:v413Cp8186* + ID_MODEL_FROM_DATABASE=Gobi 2000 Wireless Modem + +usb:v413Cp8187* + ID_MODEL_FROM_DATABASE=DW375 Bluetooth Module + +usb:v413Cp8501* + ID_MODEL_FROM_DATABASE=Bluetooth Adapter + +usb:v413Cp9500* + ID_MODEL_FROM_DATABASE=USB CP210x UART Bridge Controller [DW700] + +usb:v413CpA001* + ID_MODEL_FROM_DATABASE=Hub + +usb:v413CpA005* + ID_MODEL_FROM_DATABASE=Internal 2.0 Hub + +usb:v413CpA700* + ID_MODEL_FROM_DATABASE=Hub (in 1905FP LCD Monitor) + +usb:v4146* + ID_VENDOR_FROM_DATABASE=USBest Technology + +usb:v4146p9281* + ID_MODEL_FROM_DATABASE=Iomega Micro Mini 128MB Flash Drive + +usb:v4146pBA01* + ID_MODEL_FROM_DATABASE=Intuix Flash Drive + +usb:v4168* + ID_VENDOR_FROM_DATABASE=Targus + +usb:v4168p1010* + ID_MODEL_FROM_DATABASE=Wireless Compact Laser Mouse + +usb:v4242* + ID_VENDOR_FROM_DATABASE=USB Design by Example + +usb:v4242p4201* + ID_MODEL_FROM_DATABASE=Buttons and Lights HID device + +usb:v4242p4220* + ID_MODEL_FROM_DATABASE=Echo 1 Camera + +usb:v4255* + ID_VENDOR_FROM_DATABASE=GoPro + +usb:v4255p1000* + ID_MODEL_FROM_DATABASE=9FF2 [Digital Photo Display] + +usb:v4255p2000* + ID_MODEL_FROM_DATABASE=HD2-14 [Hero 2 Camera] + +usb:v4317* + ID_VENDOR_FROM_DATABASE=Broadcom Corp. + +usb:v4317p0700* + ID_MODEL_FROM_DATABASE=U.S. Robotics USR5426 802.11g Adapter + +usb:v4317p0701* + ID_MODEL_FROM_DATABASE=U.S. Robotics USR5425 Wireless MAXg Adapter + +usb:v4317p0711* + ID_MODEL_FROM_DATABASE=Belkin F5D7051 v3000 802.11g + +usb:v4317p0720* + ID_MODEL_FROM_DATABASE=Dynex DX-BUSB + +usb:v4348* + ID_VENDOR_FROM_DATABASE=WinChipHead + +usb:v4348p5523* + ID_MODEL_FROM_DATABASE=USB->RS 232 adapter with Prolifec PL 2303 chipset + +usb:v4348p5537* + ID_MODEL_FROM_DATABASE=13.56Mhz RFID Card Reader and Writer + +usb:v4348p5584* + ID_MODEL_FROM_DATABASE=CH34x printer adapter cable + +usb:v4572* + ID_VENDOR_FROM_DATABASE=Shuttle, Inc. + +usb:v4572p4572* + ID_MODEL_FROM_DATABASE=Shuttle PN31 Remote + +usb:v4586* + ID_VENDOR_FROM_DATABASE=Panram + +usb:v4586p1026* + ID_MODEL_FROM_DATABASE=Crystal Bar Flash Drive + +usb:v4670* + ID_VENDOR_FROM_DATABASE=EMS Production + +usb:v4670p9394* + ID_MODEL_FROM_DATABASE=Game Cube USB Memory Adaptor 64M + +usb:v4752* + ID_VENDOR_FROM_DATABASE=Miditech + +usb:v4752p0011* + ID_MODEL_FROM_DATABASE=Midistart-2 + +usb:v4757* + ID_VENDOR_FROM_DATABASE=GW Instek + +usb:v4757p2009* + ID_MODEL_FROM_DATABASE=PEL-2000 Series Electronic Load (CDC) + +usb:v4757p2010* + ID_MODEL_FROM_DATABASE=PEL-2000 Series Electronic Load (CDC) + +usb:v4766* + ID_VENDOR_FROM_DATABASE=Aceeca + +usb:v4766p0001* + ID_MODEL_FROM_DATABASE=MEZ1000 RDA + +usb:v4855* + ID_VENDOR_FROM_DATABASE=Memorex + +usb:v4855p7288* + ID_MODEL_FROM_DATABASE=Ultra Traveldrive 160G 2.5" HDD + +usb:v4971* + ID_VENDOR_FROM_DATABASE=SimpleTech + +usb:v4971pCB01* + ID_MODEL_FROM_DATABASE=SP-U25/120G + +usb:v4971pCE17* + ID_MODEL_FROM_DATABASE=1TB SimpleDrive II USB External Hard Drive + +usb:v4D46* + ID_VENDOR_FROM_DATABASE=Musical Fidelity + +usb:v4D46p0001* + ID_MODEL_FROM_DATABASE=V-Link + +usb:v4D46p0002* + ID_MODEL_FROM_DATABASE=V-DAC II + +usb:v5032* + ID_VENDOR_FROM_DATABASE=Grandtec + +usb:v5032p0BB8* + ID_MODEL_FROM_DATABASE=Grandtec USB1.1 DVB-T (cold) + +usb:v5032p0BB9* + ID_MODEL_FROM_DATABASE=Grandtec USB1.1 DVB-T (warm) + +usb:v5032p0FA0* + ID_MODEL_FROM_DATABASE=Grandtec USB1.1 DVB-T (cold) + +usb:v5032p0FA1* + ID_MODEL_FROM_DATABASE=Grandtec USB1.1 DVB-T (warm) + +usb:v5041* + ID_VENDOR_FROM_DATABASE=Linksys (?) + +usb:v5041p2234* + ID_MODEL_FROM_DATABASE=WUSB54G v1 802.11g Adapter [Intersil ISL3886] + +usb:v5041p2235* + ID_MODEL_FROM_DATABASE=WUSB54GP v1 802.11g Adapter [Intersil ISL3886] + +usb:v50C2* + ID_VENDOR_FROM_DATABASE=Averatec (?) + +usb:v50C2p4013* + ID_MODEL_FROM_DATABASE=WLAN Adapter + +usb:v5173* + ID_VENDOR_FROM_DATABASE=Sweex + +usb:v5173p1809* + ID_MODEL_FROM_DATABASE=ZD1211 + +usb:v5219* + ID_VENDOR_FROM_DATABASE=I-Tetra + +usb:v5219p1001* + ID_MODEL_FROM_DATABASE=Cetus CDC Device + +usb:v5345* + ID_VENDOR_FROM_DATABASE=Owon + +usb:v5345p1234* + ID_MODEL_FROM_DATABASE=PDS6062T Oscilloscope + +usb:v534C* + ID_VENDOR_FROM_DATABASE=SatoshiLabs + +usb:v534Cp0001* + ID_MODEL_FROM_DATABASE=Bitcoin Wallet [TREZOR] + +usb:v5354* + ID_VENDOR_FROM_DATABASE=Meyer Instruments (MIS) + +usb:v5354p0017* + ID_MODEL_FROM_DATABASE=PAXcam2 + +usb:v544D* + ID_VENDOR_FROM_DATABASE=Transmeta Corp. + +usb:v5543* + ID_VENDOR_FROM_DATABASE=UC-Logic Technology Corp. + +usb:v5543p0002* + ID_MODEL_FROM_DATABASE=SuperPen WP3325U Tablet + +usb:v5543p0003* + ID_MODEL_FROM_DATABASE=Tablet WP4030U + +usb:v5543p0004* + ID_MODEL_FROM_DATABASE=Tablet WP5540U + +usb:v5543p0005* + ID_MODEL_FROM_DATABASE=Tablet WP8060U + +usb:v5543p0041* + ID_MODEL_FROM_DATABASE=Genius PenSketch 6x8 Tablet + +usb:v5543p0042* + ID_MODEL_FROM_DATABASE=Tablet PF1209 + +usb:v5543p0064* + ID_MODEL_FROM_DATABASE=Aiptek HyperPen 10000U + +usb:v5555* + ID_VENDOR_FROM_DATABASE=Epiphan Systems Inc. + +usb:v5555p1110* + ID_MODEL_FROM_DATABASE=VGA2USB + +usb:v5555p1120* + ID_MODEL_FROM_DATABASE=KVM2USB + +usb:v5555p2222* + ID_MODEL_FROM_DATABASE=DVI2USB + +usb:v5555p3333* + ID_MODEL_FROM_DATABASE=VGA2USB Pro + +usb:v5555p3337* + ID_MODEL_FROM_DATABASE=KVM2USB Pro + +usb:v5555p3340* + ID_MODEL_FROM_DATABASE=VGA2USB LR + +usb:v5555p3344* + ID_MODEL_FROM_DATABASE=KVM2USB LR + +usb:v5555p3411* + ID_MODEL_FROM_DATABASE=DVI2USB Solo + +usb:v5555p3422* + ID_MODEL_FROM_DATABASE=DVI2USB Duo + +usb:v55AA* + ID_VENDOR_FROM_DATABASE=OnSpec Electronic, Inc. + +usb:v55AAp0015* + ID_MODEL_FROM_DATABASE=Hard Drive + +usb:v55AAp0102* + ID_MODEL_FROM_DATABASE=SuperDisk + +usb:v55AAp0103* + ID_MODEL_FROM_DATABASE=IDE Hard Drive + +usb:v55AAp0201* + ID_MODEL_FROM_DATABASE=DDI to Reader-19 + +usb:v55AAp1234* + ID_MODEL_FROM_DATABASE=ATAPI Bridge + +usb:v55AApA103* + ID_MODEL_FROM_DATABASE=Sandisk SDDR-55 SmartMedia Card Reader + +usb:v55AApB000* + ID_MODEL_FROM_DATABASE=USB to CompactFlash Card Reader + +usb:v55AApB004* + ID_MODEL_FROM_DATABASE=OnSpec MMC/SD Reader/Writer + +usb:v55AApB00B* + ID_MODEL_FROM_DATABASE=USB to Memory Stick Card Reader + +usb:v55AApB00C* + ID_MODEL_FROM_DATABASE=USB to SmartMedia Card Reader + +usb:v55AApB012* + ID_MODEL_FROM_DATABASE=Mitsumi FA402M 8-in-2 Card Reader + +usb:v55AApB200* + ID_MODEL_FROM_DATABASE=Compact Flash Reader + +usb:v55AApB204* + ID_MODEL_FROM_DATABASE=MMC/ SD Reader + +usb:v55AApB207* + ID_MODEL_FROM_DATABASE=Memory Stick Reader + +usb:v5654* + ID_VENDOR_FROM_DATABASE=Gotview + +usb:v5654pCA42* + ID_MODEL_FROM_DATABASE=MasterHD 3 + +usb:v5656* + ID_VENDOR_FROM_DATABASE=Uni-Trend Group Limited + +usb:v5656p0832* + ID_MODEL_FROM_DATABASE=UT2000/UT3000 Digital Storage Oscilloscope + +usb:v595A* + ID_VENDOR_FROM_DATABASE=IRTOUCHSYSTEMS Co. Ltd. + +usb:v595Ap0001* + ID_MODEL_FROM_DATABASE=Touchscreen + +usb:v5986* + ID_VENDOR_FROM_DATABASE=Acer, Inc + +usb:v5986p0100* + ID_MODEL_FROM_DATABASE=Orbicam + +usb:v5986p0101* + ID_MODEL_FROM_DATABASE=USB2.0 Camera + +usb:v5986p0102* + ID_MODEL_FROM_DATABASE=Crystal Eye Webcam + +usb:v5986p01A6* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam + +usb:v5986p01A7* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam + +usb:v5986p01A9* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam + +usb:v5986p0200* + ID_MODEL_FROM_DATABASE=OrbiCam + +usb:v5986p0203* + ID_MODEL_FROM_DATABASE=BisonCam NB Pro 1300 + +usb:v5986p0241* + ID_MODEL_FROM_DATABASE=BisonCam, NB Pro + +usb:v5986p02D0* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam [R5U877] + +usb:v5986p03D0* + ID_MODEL_FROM_DATABASE=Lenovo Integrated Webcam [R5U877] + +usb:v59E3* + ID_VENDOR_FROM_DATABASE=Nonolith Labs + +usb:v5A57* + ID_VENDOR_FROM_DATABASE=Zinwell + +usb:v5A57p0260* + ID_MODEL_FROM_DATABASE=RT2570 + +usb:v5A57p0280* + ID_MODEL_FROM_DATABASE=802.11a/b/g/n USB Wireless LAN Card + +usb:v5A57p0282* + ID_MODEL_FROM_DATABASE=802.11b/g/n USB Wireless LAN Card + +usb:v5A57p0283* + ID_MODEL_FROM_DATABASE=802.11b/g/n USB Wireless LAN Card + +usb:v5A57p0284* + ID_MODEL_FROM_DATABASE=802.11a/b/g/n USB Wireless LAN Card + +usb:v5A57p0290* + ID_MODEL_FROM_DATABASE=ZW-N290 802.11n [Realtek RTL8192SU] + +usb:v5A57p5257* + ID_MODEL_FROM_DATABASE=Metronic 495257 wifi 802.11ng + +usb:v6000* + ID_VENDOR_FROM_DATABASE=Beholder International Ltd. + +usb:v6000pDEC0* + ID_MODEL_FROM_DATABASE=TV Wander + +usb:v6000pDEC1* + ID_MODEL_FROM_DATABASE=TV Voyage + +usb:v601A* + ID_VENDOR_FROM_DATABASE=Ingenic Semiconductor Ltd. + +usb:v601Ap4740* + ID_MODEL_FROM_DATABASE=XBurst Jz4740 boot mode + +usb:v6189* + ID_VENDOR_FROM_DATABASE=Sitecom + +usb:v6189p182D* + ID_MODEL_FROM_DATABASE=USB 2.0 Ethernet + +usb:v6189p2068* + ID_MODEL_FROM_DATABASE=USB to serial cable (v2) + +usb:v6244* + ID_VENDOR_FROM_DATABASE=LightingSoft AG + +usb:v6244p0101* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI5A + +usb:v6244p0201* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI5C + +usb:v6244p0300* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI6 Firmware download + +usb:v6244p0301* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI6C + +usb:v6244p0302* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI6A + +usb:v6244p0303* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI6D + +usb:v6244p0400* + ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK1A + +usb:v6244p0401* + ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK1A + +usb:v6244p0410* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI7 Firmware Download + +usb:v6244p0411* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI7A + +usb:v6244p0420* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI8A Firmware Download + +usb:v6244p0421* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI8A + +usb:v6244p0430* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI8C Firmware Download + +usb:v6244p0431* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI8C + +usb:v6244p0440* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9A Firmware Download + +usb:v6244p0441* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9A + +usb:v6244p0450* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9C Firmware Download + +usb:v6244p0451* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9C + +usb:v6244p0460* + ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK2 Firmware download + +usb:v6244p0461* + ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK2 + +usb:v6244p0470* + ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK1B Firmware download + +usb:v6244p0471* + ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK1B + +usb:v6244p0480* + ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK3 Firmware download + +usb:v6244p0481* + ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK3 + +usb:v6244p0490* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9D Firmware Download + +usb:v6244p0491* + ID_MODEL_FROM_DATABASE=Intelligent Usb Dmx Interface SIUDI9D + +usb:v6244p0500* + ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK2B Firmware download + +usb:v6244p0501* + ID_MODEL_FROM_DATABASE=Touch Sensitive Intelligent Control Keypad STICK2B + +usb:v6253* + ID_VENDOR_FROM_DATABASE=TwinHan Technology Co., Ltd + +usb:v6253p0100* + ID_MODEL_FROM_DATABASE=Ir reciver f. remote control + +usb:v636C* + ID_VENDOR_FROM_DATABASE=CoreLogic, Inc. + +usb:v6472* + ID_VENDOR_FROM_DATABASE=Unknown (Sony?) + +usb:v6472p01C8* + ID_MODEL_FROM_DATABASE=PlayStation Portable [Mass Storage] + +usb:v6547* + ID_VENDOR_FROM_DATABASE=Arkmicro Technologies Inc. + +usb:v6547p0232* + ID_MODEL_FROM_DATABASE=ARK3116 Serial + +usb:v6615* + ID_VENDOR_FROM_DATABASE=IRTOUCHSYSTEMS Co. Ltd. + +usb:v6615p0001* + ID_MODEL_FROM_DATABASE=Touchscreen + +usb:v6666* + ID_VENDOR_FROM_DATABASE=Prototype product Vendor ID + +usb:v6666p0667* + ID_MODEL_FROM_DATABASE=WiseGroup Smart Joy PSX, PS-PC Smart JoyPad + +usb:v6666p2667* + ID_MODEL_FROM_DATABASE=JCOP BlueZ Smartcard reader + +usb:v6666p8802* + ID_MODEL_FROM_DATABASE=SmartJoy Dual Plus PS2 converter + +usb:v6666p8804* + ID_MODEL_FROM_DATABASE=WiseGroup SuperJoy Box 5 + +usb:v6677* + ID_VENDOR_FROM_DATABASE=WiseGroup, Ltd. + +usb:v6677p8802* + ID_MODEL_FROM_DATABASE=SmartJoy Dual Plus PS2 converter + +usb:v6677p8811* + ID_MODEL_FROM_DATABASE=Deluxe Dance Mat + +usb:v6891* + ID_VENDOR_FROM_DATABASE=3Com + +usb:v6891pA727* + ID_MODEL_FROM_DATABASE=3CRUSB10075 802.11bg [ZyDAS ZD1211] + +usb:v695C* + ID_VENDOR_FROM_DATABASE=Opera1 + +usb:v695Cp3829* + ID_MODEL_FROM_DATABASE=Opera1 DVB-S (warm state) + +usb:v6993* + ID_VENDOR_FROM_DATABASE=Yealink Network Technology Co., Ltd. + +usb:v6993pB001* + ID_MODEL_FROM_DATABASE=VoIP Phone + +usb:v6A75* + ID_VENDOR_FROM_DATABASE=Shanghai Jujo Electronics Co., Ltd + +usb:v7104* + ID_VENDOR_FROM_DATABASE=CME (Central Music Co.) + +usb:v7104p2202* + ID_MODEL_FROM_DATABASE=UF5/UF6/UF7/UF8 MIDI Master Keyboard + +usb:v726C* + ID_VENDOR_FROM_DATABASE=StackFoundry LLC + +usb:v726Cp2149* + ID_MODEL_FROM_DATABASE=EntropyKing Random Number Generator + +usb:v734C* + ID_VENDOR_FROM_DATABASE=TBS Technologies China + +usb:v734Cp5920* + ID_MODEL_FROM_DATABASE=Q-Box II DVB-S2 HD + +usb:v734Cp5928* + ID_MODEL_FROM_DATABASE=Q-Box II DVB-S2 HD + +usb:v7373* + ID_VENDOR_FROM_DATABASE=Beijing STONE Technology Co. Ltd. + +usb:v7373p5740* + ID_MODEL_FROM_DATABASE=Intelligent TFT-LCD Module + +usb:v7392* + ID_VENDOR_FROM_DATABASE=Edimax Technology Co., Ltd + +usb:v7392p7711* + ID_MODEL_FROM_DATABASE=EW-7711UTn nLite Wireless Adapter [Ralink RT2870] + +usb:v7392p7717* + ID_MODEL_FROM_DATABASE=EW-7717UN 802.11n Wireless Adapter [Ralink RT2870] + +usb:v7392p7718* + ID_MODEL_FROM_DATABASE=EW-7718UN 802.11n Wireless Adapter [Ralink RT2870] + +usb:v7392p7722* + ID_MODEL_FROM_DATABASE=EW-7722UTn 802.11n Wireless Adapter [Ralink RT307x] + +usb:v7392p7811* + ID_MODEL_FROM_DATABASE=EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS] + +usb:v8086* + ID_VENDOR_FROM_DATABASE=Intel Corp. + +usb:v8086p0001* + ID_MODEL_FROM_DATABASE=AnyPoint (TM) Home Network 1.6 Mbps Wireless Adapter + +usb:v8086p0044* + ID_MODEL_FROM_DATABASE=CPU DRAM Controller + +usb:v8086p0046* + ID_MODEL_FROM_DATABASE=HD Graphics + +usb:v8086p0100* + ID_MODEL_FROM_DATABASE=Personal Audio Player 3000 + +usb:v8086p0101* + ID_MODEL_FROM_DATABASE=Personal Audio Player 3000 + +usb:v8086p0110* + ID_MODEL_FROM_DATABASE=Easy PC Camera + +usb:v8086p0120* + ID_MODEL_FROM_DATABASE=PC Camera CS120 + +usb:v8086p0180* + ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m + +usb:v8086p0181* + ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m + +usb:v8086p0182* + ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m + +usb:v8086p0186* + ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m + +usb:v8086p0188* + ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m + +usb:v8086p0200* + ID_MODEL_FROM_DATABASE=AnyPoint(TM) Wireless II Network 11Mbps Adapter [Atmel AT76C503A] + +usb:v8086p0431* + ID_MODEL_FROM_DATABASE=Intel Pro Video PC Camera + +usb:v8086p0510* + ID_MODEL_FROM_DATABASE=Digital Movie Creator + +usb:v8086p0630* + ID_MODEL_FROM_DATABASE=Pocket PC Camera + +usb:v8086p0780* + ID_MODEL_FROM_DATABASE=CS780 Microphone Input + +usb:v8086p07D3* + ID_MODEL_FROM_DATABASE=BLOB boot loader firmware + +usb:v8086p0DAD* + ID_MODEL_FROM_DATABASE=Cherry MiniatureCard Keyboard + +usb:v8086p1010* + ID_MODEL_FROM_DATABASE=AnyPoint(TM) Home Network 10 Mbps Phoneline Adapter + +usb:v8086p110A* + ID_MODEL_FROM_DATABASE=Bluetooth Controller from (Ericsson P4A) + +usb:v8086p110B* + ID_MODEL_FROM_DATABASE=Bluetooth Controller from (Intel/CSR) + +usb:v8086p1110* + ID_MODEL_FROM_DATABASE=PRO/Wireless LAN Module + +usb:v8086p1111* + ID_MODEL_FROM_DATABASE=PRO/Wireless 2011B 802.11b Adapter [Intersil PRISM 2.5] + +usb:v8086p1134* + ID_MODEL_FROM_DATABASE=Hollister Mobile Monitor + +usb:v8086p1139* + ID_MODEL_FROM_DATABASE=In-Target Probe (ITP) + +usb:v8086p1234* + ID_MODEL_FROM_DATABASE=Prototype Reader/Writer + +usb:v8086p1403* + ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m + +usb:v8086p1405* + ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m + +usb:v8086p1406* + ID_MODEL_FROM_DATABASE=WiMAX Connection 2400m + +usb:v8086p2448* + ID_MODEL_FROM_DATABASE=82801 PCI Bridge + +usb:v8086p3100* + ID_MODEL_FROM_DATABASE=PRO/DSL 3220 Modem - WAN + +usb:v8086p3101* + ID_MODEL_FROM_DATABASE=PRO/DSL 3220 Modem + +usb:v8086p3240* + ID_MODEL_FROM_DATABASE=AnyPoint® 3240 Modem - WAN + +usb:v8086p3241* + ID_MODEL_FROM_DATABASE=AnyPoint® 3240 Modem + +usb:v8086p8602* + ID_MODEL_FROM_DATABASE=Miniature Card Slot + +usb:v8086p9303* + ID_MODEL_FROM_DATABASE=Intel 8x930Hx Hub + +usb:v8086p9500* + ID_MODEL_FROM_DATABASE=CE 9500 DVB-T + +usb:v8086p9890* + ID_MODEL_FROM_DATABASE=82930 Test Board + +usb:v8086pBEEF* + ID_MODEL_FROM_DATABASE=SCM Miniature Card Reader/Writer + +usb:v8086pC013* + ID_MODEL_FROM_DATABASE=Wireless HID Station + +usb:v8086pF001* + ID_MODEL_FROM_DATABASE=XScale PXA27x Bulverde flash + +usb:v8086pF1A5* + ID_MODEL_FROM_DATABASE=Z-U130 [Value Solid State Drive] + +usb:v8087* + ID_VENDOR_FROM_DATABASE=Intel Corp. + +usb:v8087p0020* + ID_MODEL_FROM_DATABASE=Integrated Rate Matching Hub + +usb:v8087p0024* + ID_MODEL_FROM_DATABASE=Integrated Rate Matching Hub + +usb:v80EE* + ID_VENDOR_FROM_DATABASE=VirtualBox + +usb:v80EEp0021* + ID_MODEL_FROM_DATABASE=USB Tablet + +usb:v8282* + ID_VENDOR_FROM_DATABASE=Keio + +usb:v8282p3201* + ID_MODEL_FROM_DATABASE=Retro Adapter + +usb:v8282p3301* + ID_MODEL_FROM_DATABASE=Retro Adapter Mouse + +usb:v8341* + ID_VENDOR_FROM_DATABASE=EGO Systems, Inc. + +usb:v8341p2000* + ID_MODEL_FROM_DATABASE=Flashdisk + +usb:v8564* + ID_VENDOR_FROM_DATABASE=Transcend Information, Inc. + +usb:v8564p1000* + ID_MODEL_FROM_DATABASE=JetFlash + +usb:v8564p4000* + ID_MODEL_FROM_DATABASE=RDF8 + +usb:v8644* + ID_VENDOR_FROM_DATABASE=Intenso GmbG + +usb:v8644p8003* + ID_MODEL_FROM_DATABASE=Micro Line + +usb:v8644p800B* + ID_MODEL_FROM_DATABASE=Micro Line (4GB) + +usb:v8E06* + ID_VENDOR_FROM_DATABASE=CH Products, Inc. + +usb:v8E06pF700* + ID_MODEL_FROM_DATABASE=DT225 Trackball + +usb:v9016* + ID_VENDOR_FROM_DATABASE=Sitecom + +usb:v9016p182D* + ID_MODEL_FROM_DATABASE=WL-022 802.11b Adapter + +usb:v9022* + ID_VENDOR_FROM_DATABASE=TeVii Technology Ltd. + +usb:v9022pD630* + ID_MODEL_FROM_DATABASE=DVB-S S630 + +usb:v9022pD650* + ID_MODEL_FROM_DATABASE=DVB-S2 S650 + +usb:v9022pD660* + ID_MODEL_FROM_DATABASE=DVB-S2 S660 + +usb:v9148* + ID_VENDOR_FROM_DATABASE=GeoLab, Ltd + +usb:v9148p0004* + ID_MODEL_FROM_DATABASE=R3 Compatible Device + +usb:v9710* + ID_VENDOR_FROM_DATABASE=MosChip Semiconductor + +usb:v9710p7703* + ID_MODEL_FROM_DATABASE=MCS7703 Serial Port Adapter + +usb:v9710p7705* + ID_MODEL_FROM_DATABASE=MCS7705 Parallel port adapter + +usb:v9710p7715* + ID_MODEL_FROM_DATABASE=MCS7715 Parallel and serial port adapter + +usb:v9710p7717* + ID_MODEL_FROM_DATABASE=MCS7717 3-port hub with serial and parallel adapter + +usb:v9710p7720* + ID_MODEL_FROM_DATABASE=MCS7720 Dual serial port adapter + +usb:v9710p7730* + ID_MODEL_FROM_DATABASE=MCS7730 10/100 Mbps Ethernet adapter + +usb:v9710p7780* + ID_MODEL_FROM_DATABASE=MCS7780 4Mbps Fast IrDA Adapter + +usb:v9710p7830* + ID_MODEL_FROM_DATABASE=MCS7830 10/100 Mbps Ethernet adapter + +usb:v9710p7832* + ID_MODEL_FROM_DATABASE=MCS7832 10/100 Mbps Ethernet adapter + +usb:v9710p7840* + ID_MODEL_FROM_DATABASE=MCS7820/MCS7840 2/4 port serial adapter + +usb:v9849* + ID_VENDOR_FROM_DATABASE=Bestmedia CD Recordable GmbH & Co. KG + +usb:v9849p0701* + ID_MODEL_FROM_DATABASE=Platinum MyDrive HP + +usb:v9999* + ID_VENDOR_FROM_DATABASE=Odeon + +usb:v9999p0001* + ID_MODEL_FROM_DATABASE=JAF Mobile Phone Flasher Interface + +usb:v99FA* + ID_VENDOR_FROM_DATABASE=Grandtec + +usb:v99FAp8988* + ID_MODEL_FROM_DATABASE=V.cap Camera Device + +usb:v9AC4* + ID_VENDOR_FROM_DATABASE=J. Westhues + +usb:v9AC4p4B8F* + ID_MODEL_FROM_DATABASE=ProxMark-3 RFID Instrument + +usb:v9E88* + ID_VENDOR_FROM_DATABASE=Marvell Semiconductor, Inc. + +usb:v9E88p9E8F* + ID_MODEL_FROM_DATABASE=Plug Computer Basic [SheevaPlug] + +usb:vA128* + ID_VENDOR_FROM_DATABASE=AnMo Electronics Corp. / Dino-Lite (?) + +usb:vA128p0610* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + HV7131R) + +usb:vA128p0611* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + HV7131R) + +usb:vA128p0612* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C120 + HV7131R) + +usb:vA128p0613* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + HV7131R) + +usb:vA128p0614* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + MI1310/MT9M111) + +usb:vA128p0615* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + MI1310/MT9M111) + +usb:vA128p0616* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C120 + HV7131R) + +usb:vA128p0617* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + MI1310/MT9M111) + +usb:vA128p0618* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope (SN9C201 + HV7131R) + +usb:vA168* + ID_VENDOR_FROM_DATABASE=AnMo Electronics Corporation + +usb:vA168p0610* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope + +usb:vA168p0611* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope + +usb:vA168p0613* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope + +usb:vA168p0614* + ID_MODEL_FROM_DATABASE=Dino-Lite Pro Digital Microscope + +usb:vA168p0615* + ID_MODEL_FROM_DATABASE=Dino-Lite Pro Digital Microscope + +usb:vA168p0617* + ID_MODEL_FROM_DATABASE=Dino-Lite Pro Digital Microscope + +usb:vA168p0618* + ID_MODEL_FROM_DATABASE=Dino-Lite Digital Microscope + +usb:vA600* + ID_VENDOR_FROM_DATABASE=Asix + +usb:vA600pE110* + ID_MODEL_FROM_DATABASE=OK1ZIA Davac 4.x + +usb:vA727* + ID_VENDOR_FROM_DATABASE=3Com + +usb:vA727p6893* + ID_MODEL_FROM_DATABASE=3CRUSB20075 OfficeConnect Wireless 108Mbps 11g Adapter [Atheros AR5523] + +usb:vA727p6895* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:vA727p6897* + ID_MODEL_FROM_DATABASE=AR5523 + +usb:vAAAA* + ID_VENDOR_FROM_DATABASE=MXT + +usb:vAAAAp8815* + ID_MODEL_FROM_DATABASE=microSD CardReader + +usb:vABCD* + ID_VENDOR_FROM_DATABASE=Unknown + +usb:vABCDpCDEE* + ID_MODEL_FROM_DATABASE=Petcam + +usb:vB58E* + ID_VENDOR_FROM_DATABASE=Blue Microphones + +usb:vB58Ep9E84* + ID_MODEL_FROM_DATABASE=Yeti Stereo Microphone + +usb:vC216* + ID_VENDOR_FROM_DATABASE=Card Device Expert Co., LTD + +usb:vC216p0180* + ID_MODEL_FROM_DATABASE=MSR90 MagStripe reader + +usb:vC251* + ID_VENDOR_FROM_DATABASE=Keil Software, Inc. + +usb:vC251p2710* + ID_MODEL_FROM_DATABASE=ULink + +usb:vCACE* + ID_VENDOR_FROM_DATABASE=CACE Technologies Inc. + +usb:vCACEp0002* + ID_MODEL_FROM_DATABASE=AirPCAP Classic 802.11 packet capture adapter + +usb:vCACEp0300* + ID_MODEL_FROM_DATABASE=AirPcap NX [Atheros AR9001U-(2)NG] + +usb:vCD12* + ID_VENDOR_FROM_DATABASE=SMART TECHNOLOGY INDUSTRIAL LTD. + +usb:vD208* + ID_VENDOR_FROM_DATABASE=Ultimarc + +usb:vD208p0310* + ID_MODEL_FROM_DATABASE=Mini-PAC Arcade Control Interface + +usb:vD209* + ID_VENDOR_FROM_DATABASE=Ultimarc + +usb:vD209p0301* + ID_MODEL_FROM_DATABASE=I-PAC Arcade Control Interface + +usb:vD209p0501* + ID_MODEL_FROM_DATABASE=Ultra-Stik Ultimarc Ultra-Stik Player 1 + +usb:vD904* + ID_VENDOR_FROM_DATABASE=LogiLink + +usb:vD904p0003* + ID_MODEL_FROM_DATABASE=Laser Mouse (ID0009A) + +usb:vE4E4* + ID_VENDOR_FROM_DATABASE=Xorcom Ltd. + +usb:vE4E4p1130* + ID_MODEL_FROM_DATABASE=Astribank series + +usb:vE4E4p1131* + ID_MODEL_FROM_DATABASE=Astribank series + +usb:vE4E4p1132* + ID_MODEL_FROM_DATABASE=Astribank series + +usb:vE4E4p1140* + ID_MODEL_FROM_DATABASE=Astribank series + +usb:vE4E4p1141* + ID_MODEL_FROM_DATABASE=Astribank series + +usb:vE4E4p1142* + ID_MODEL_FROM_DATABASE=Astribank series + +usb:vE4E4p1150* + ID_MODEL_FROM_DATABASE=Astribank series + +usb:vE4E4p1151* + ID_MODEL_FROM_DATABASE=Astribank series + +usb:vE4E4p1152* + ID_MODEL_FROM_DATABASE=Astribank series + +usb:vE4E4p1160* + ID_MODEL_FROM_DATABASE=Astribank 2 series + +usb:vE4E4p1161* + ID_MODEL_FROM_DATABASE=Astribank 2 series + +usb:vE4E4p1162* + ID_MODEL_FROM_DATABASE=Astribank 2 series + +usb:vEB03* + ID_VENDOR_FROM_DATABASE=MakingThings + +usb:vEB03p0920* + ID_MODEL_FROM_DATABASE=Make Controller Kit + +usb:vEB1A* + ID_VENDOR_FROM_DATABASE=eMPIA Technology, Inc. + +usb:vEB1Ap17DE* + ID_MODEL_FROM_DATABASE=KWorld V-Stream XPERT DTV - DVB-T USB cold + +usb:vEB1Ap17DF* + ID_MODEL_FROM_DATABASE=KWorld V-Stream XPERT DTV - DVB-T USB warm + +usb:vEB1Ap2571* + ID_MODEL_FROM_DATABASE=M035 Compact Web Cam + +usb:vEB1Ap2710* + ID_MODEL_FROM_DATABASE=SilverCrest Webcam + +usb:vEB1Ap2750* + ID_MODEL_FROM_DATABASE=ECS Elitegroup G220 integrated Webcam + +usb:vEB1Ap2761* + ID_MODEL_FROM_DATABASE=EeePC 701 integrated Webcam + +usb:vEB1Ap2776* + ID_MODEL_FROM_DATABASE=Combined audio and video input device + +usb:vEB1Ap2800* + ID_MODEL_FROM_DATABASE=Terratec Cinergy 200 + +usb:vEB1Ap2801* + ID_MODEL_FROM_DATABASE=GrabBeeX+ Video Encoder + +usb:vEB1Ap2863* + ID_MODEL_FROM_DATABASE=Video Grabber + +usb:vEB1Ap2870* + ID_MODEL_FROM_DATABASE=Pinnacle PCTV Stick + +usb:vEB1Ap2881* + ID_MODEL_FROM_DATABASE=EM2881 Video Controller + +usb:vEB1Ap50A3* + ID_MODEL_FROM_DATABASE=Gadmei UTV380 TV Box + +usb:vEB1Ap50A6* + ID_MODEL_FROM_DATABASE=Gadmei UTV330 TV Box + +usb:vEB1ApE355* + ID_MODEL_FROM_DATABASE=KWorld DVB-T 355U Digital TV Dongle + +usb:vEB2A* + ID_VENDOR_FROM_DATABASE=KWorld + +usb:vEF18* + ID_VENDOR_FROM_DATABASE=SMART TECHNOLOGY INDUSTRIAL LTD. + +usb:vF003* + ID_VENDOR_FROM_DATABASE=Hewlett Packard + +usb:vF003p6002* + ID_MODEL_FROM_DATABASE=PhotoSmart C500 + +usb:vF182* + ID_VENDOR_FROM_DATABASE=Leap Motion + +usb:vF182p0003* + ID_MODEL_FROM_DATABASE=Controller + +usb:vF4EC* + ID_VENDOR_FROM_DATABASE=Atten Electronics / Siglent Technologies + +usb:vF4ECpEE38* + ID_MODEL_FROM_DATABASE=Digital Storage Oscilloscope + +usb:vF4ED* + ID_VENDOR_FROM_DATABASE=Shenzhen Siglent Co., Ltd. + +usb:vF4EDpEE37* + ID_MODEL_FROM_DATABASE=SDG1010 Waveform Generator + +usb:vF4EDpEE3A* + ID_MODEL_FROM_DATABASE=SDG1010 Waveform Generator (TMC mode) + +usb:vF766* + ID_VENDOR_FROM_DATABASE=Hama + +usb:vF766p0001* + ID_MODEL_FROM_DATABASE=PC-Gamepad "Greystorm" + +usb:vFC08* + ID_VENDOR_FROM_DATABASE=Conrad Electronic SE + +usb:vFC08p0101* + ID_MODEL_FROM_DATABASE=MIDI Cable UA0037 + +usb:vFFEE* + ID_VENDOR_FROM_DATABASE=FNK Tech + +usb:vFFEEp0100* + ID_MODEL_FROM_DATABASE=Card Reader Controller RTS5101/RTS5111/RTS5116 diff --git a/hwdb.d/20-vmbus-class.hwdb b/hwdb.d/20-vmbus-class.hwdb new file mode 100644 index 00000000..ba96b383 --- /dev/null +++ b/hwdb.d/20-vmbus-class.hwdb @@ -0,0 +1,57 @@ +# This file is part of systemd. +# +# Data extracted from Linux hyperv.h + +vmbus:02780ada77e3ac4a8e770558eb1073f8 + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Video + +vmbus:1657e6f8b33c064a9a601889c5cccab5 + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Remote Desktop Control + +vmbus:1df6c444444400449d52802e27ede19f + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V PCI Controller + +vmbus:292efa3523ea364296ae3a6ebacba440 + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Backup/Restore + +vmbus:30e62795aed07b49adcee80ab0175caf + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Time Sync + +vmbus:31600b0e13523449818b38d90ced39db + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Guest Shutdown + +vmbus:32264132cb86a2449b5c50d1417354f5 + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V IDE Controller + +vmbus:394f16571591784eab55382f3bd5422d + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Heartbeat + +vmbus:3daf2e8ca732094bab99bd1f1c86b501 + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Guest RDMA + +vmbus:635161f83edfc546913ff2d2f965ed0e + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Network Adapter + +vmbus:6dad12f9172bea48bd65f927a61c7684 + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Keyboard + +vmbus:9eb6a8cf4a5bc04cb98b8ba1a1f3f95a + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Mouse + +vmbus:d96361baa104294db60572e2ffb1dc7f + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V SCSI Controller + +vmbus:dc7450528589e2468057a307dc18a502 + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Dynamic Memory + +vmbus:e34bd134e4dec8419ae76b174977c192 + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V File Copy + +vmbus:e7f4a0a9455a964db8278a841e8c03e6 + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Data Exchange + +vmbus:f4ac6a2715ac6c4298dd7521ad3f01fe + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Remote Desktop Virtualization + +vmbus:f4ba7533159e304bb76567acb10d607b + ID_MODEL_FROM_DATABASE=Microsoft Hyper-V Virtual Machine Activation diff --git a/hwdb.d/60-evdev.hwdb b/hwdb.d/60-evdev.hwdb new file mode 100644 index 00000000..a6a3c5c2 --- /dev/null +++ b/hwdb.d/60-evdev.hwdb @@ -0,0 +1,615 @@ +# This file is part of systemd. +# +# The lookup keys are composed in: +# 60-evdev.rules +# +# Note: The format of the "evdev:" prefix match key is a +# contract between the rules file and the hardware data, it might +# change in later revisions to support more or better matches, it +# is not necessarily expected to be a stable ABI. +# +# Match string formats: +# evdev: +# evdev:name::dmi: +# +# To add local entries, create a new file +# /etc/udev/hwdb.d/61-evdev-local.hwdb +# and add your rules there. To load the new rules execute (as root): +# systemd-hwdb update +# udevadm trigger /dev/input/eventXX +# where /dev/input/eventXX is the device in question. If in +# doubt, simply use /dev/input/event* to reload all input rules. +# +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of +# udevadm info /dev/input/eventXX. +# +# Allowed properties are: +# EVDEV_ABS_=:::: +# +# where is the hexadecimal EV_ABS code as listed in linux/input.h +# and min, max, res, fuzz, flat are the decimal values to the respective +# fields of the struct input_absinfo as listed in linux/input.h. +# If a field is missing the field will be left as-is. Not all fields need to +# be present. e.g. ::45 sets the resolution to 45 units/mm. + +# +# Sort by brand, model + +######################################### +# AIPTEK +######################################### + +# Hyperpen 12000U +evdev:input:b0003v08CAp0010* + EVDEV_ABS_00=::20 + EVDEV_ABS_01=::20 + +######################################### +# Apple +######################################### + +# Macbook2,1 (late 2006), single-button touchpad +evdev:input:b0003v05ACp021B* +# Macbook4,1 +evdev:input:b0003v05ACp0229* +evdev:input:b0003v05ACp022A* + EVDEV_ABS_00=256:1471:12 + EVDEV_ABS_01=256:831:12 + +# Macbook5,1 (unibody), aka wellspring3 +evdev:input:b0003v05ACp0236* +evdev:input:b0003v05ACp0237* +evdev:input:b0003v05ACp0238* + EVDEV_ABS_00=::92 + EVDEV_ABS_01=::90 + EVDEV_ABS_35=::92 + EVDEV_ABS_36=::90 + +# Macbook8 (unibody, March 2011) +evdev:input:b0003v05ACp0245* +evdev:input:b0003v05ACp0246* +evdev:input:b0003v05ACp0247* + EVDEV_ABS_00=::92 + EVDEV_ABS_01=::91 + EVDEV_ABS_35=::92 + EVDEV_ABS_36=::91 + +# Macbook8,2 (unibody) +evdev:input:b0003v05ACp0252* +evdev:input:b0003v05ACp0253* +evdev:input:b0003v05ACp0254* + EVDEV_ABS_00=::94 + EVDEV_ABS_01=::92 + EVDEV_ABS_35=::94 + EVDEV_ABS_36=::92 + +# MacbookPro10,1 (unibody, June 2012) +evdev:input:b0003v05ACp0262* +evdev:input:b0003v05ACp0263* +evdev:input:b0003v05ACp0264* +# MacbookPro10,2 (unibody, October 2012) +evdev:input:b0003v05ACp0259* +evdev:input:b0003v05ACp025A* +evdev:input:b0003v05ACp025B* + EVDEV_ABS_00=::94 + EVDEV_ABS_01=::92 + EVDEV_ABS_35=::94 + EVDEV_ABS_36=::92 + +# MacBook8,1 (2015), MacBook9,1 (2016), MacBook10,1 (2017) +evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBook8,1:* +evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBook9,1:* +evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBook10,1:* + EVDEV_ABS_00=::95 + EVDEV_ABS_01=::90 + EVDEV_ABS_35=::95 + EVDEV_ABS_36=::90 + +# MacBookPro13,* (Late 2016), MacBookPro14,* (Mid 2017) +evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro13,1:* +evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro13,2:* +evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro14,1:* +evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro14,2:* + EVDEV_ABS_00=::96 + EVDEV_ABS_01=::94 + EVDEV_ABS_35=::96 + EVDEV_ABS_36=::94 + +evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro13,3:* +evdev:name:Apple SPI Touchpad:dmi:*:svnAppleInc.:pnMacBookPro14,3:* + EVDEV_ABS_00=::96 + EVDEV_ABS_01=::95 + EVDEV_ABS_35=::96 + EVDEV_ABS_36=::95 + +######################################### +# ASUS +######################################### + +# Asus N53SV +evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnASUSTeKComputerInc.:pnN53SV* + EVDEV_ABS_00=0:1152:14 + EVDEV_ABS_01=0:576:10 + EVDEV_ABS_35=0:1152:14 + EVDEV_ABS_36=0:576:10 + +# Asus F3Sg +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnASUSTeKComputerInc.:pnF3Sg:* + EVDEV_ABS_00=0:6143:136 + EVDEV_ABS_01=1103:5856:61 + +# Asus VivoBook E402SA +evdev:name:Elan Touchpad:dmi:*svnASUSTeKCOMPUTERINC.:pnE402SA* + EVDEV_ABS_00=::29 + EVDEV_ABS_01=::29 + EVDEV_ABS_35=::29 + EVDEV_ABS_36=::29 + +# Asus K52JT +evdev:name:ETPS/2 Elantech Touchpad:dmi:bvn*:bvr*:bd*:svnASUSTeKComputerInc.:pnK52JT:* + EVDEV_ABS_00=::18 + EVDEV_ABS_01=::16 + EVDEV_ABS_35=::18 + EVDEV_ABS_36=::16 + +# Asus X550CC, S550CB and N550JV +evdev:name:ETPS/2 Elantech Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnX550CC:* +evdev:name:ETPS/2 Elantech Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnS550CB:* +evdev:name:ETPS/2 Elantech Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnN550JV:* + EVDEV_ABS_00=::31 + EVDEV_ABS_01=::30 + EVDEV_ABS_35=::31 + EVDEV_ABS_36=::30 + +# Asus UX301L +evdev:name:Elan Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnUX301LAA:* + EVDEV_ABS_00=::30 + EVDEV_ABS_01=::29 + EVDEV_ABS_35=::30 + EVDEV_ABS_36=::29 + +# Asus UX305 +evdev:name:Elan Touchpad:dmi:*:svnASUSTeKCOMPUTERINC.:pnUX305UA:* + EVDEV_ABS_00=0:3097:32 + EVDEV_ABS_01=0:2119:33 + EVDEV_ABS_35=0:3097:32 + EVDEV_ABS_36=0:2119:33 + +######################################### +# Bangho +######################################### + +# Bangho Cloud Pro +evdev:name:SYNA3602:00 0911:5288 Touchpad:dmi:*svnBANGHO:pnCLOUDPRO:* + EVDEV_ABS_00=52:1747:17 + EVDEV_ABS_01=45:954:14 + EVDEV_ABS_35=52:1747:17 + EVDEV_ABS_36=45:954:14 + +######################################### +# Dell +######################################### + +# Dell Vostro 1510 +evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnDellInc.:pnVostro1510* + EVDEV_ABS_00=::14 + EVDEV_ABS_01=::18 + +# Dell Inspiron 3537 - PS/2 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnDellInc.:pnInspiron3537* + EVDEV_ABS_00=1268:5675:41 + EVDEV_ABS_01=1101:4792:61 + EVDEV_ABS_35=1268:5675:41 + EVDEV_ABS_36=1101:4792:61 + +# Dell Inspiron 3537 - RMI4 +evdev:name:Synaptics TM2382-001:dmi:*svnDellInc.:pnInspiron3537* + EVDEV_ABS_00=::24 + EVDEV_ABS_01=::34 + EVDEV_ABS_35=::24 + EVDEV_ABS_36=::34 + +# Dell Inspiron N5040 +evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnInspironN5040* + EVDEV_ABS_00=25:2000:22 + EVDEV_ABS_01=0:1351:28 + EVDEV_ABS_35=25:2000:22 + EVDEV_ABS_36=0:1351:28 + +# Dell Inspiron MM061 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*bvn*:bvr*:bd*:svnDellInc.:pnMM061:* + EVDEV_ABS_00=1008:5793:66 + EVDEV_ABS_01=687:5176:107 + +# Dell Latitude E6220 +evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6220* + EVDEV_ABS_00=76:1815:22 + EVDEV_ABS_01=131:1330:30 + EVDEV_ABS_35=76:1815:22 + EVDEV_ABS_36=131:1330:30 + +# Dell Latitude E6320 +evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320* + EVDEV_ABS_00=79:1841:22 + EVDEV_ABS_01=140:1325:29 + EVDEV_ABS_35=79:1841:22 + EVDEV_ABS_36=140:1325:29 + +# Dell Latitude E7250 +evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7250* + EVDEV_ABS_00=179:3903:38 + EVDEV_ABS_01=277:1916:32 + EVDEV_ABS_35=179:3903:38 + EVDEV_ABS_36=277:1916:32 + +# Dell Latitude E7470 +evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470* + EVDEV_ABS_00=29:2930:30 + EVDEV_ABS_01=26:1533:29 + EVDEV_ABS_35=29:2930:30 + EVDEV_ABS_36=26:1533:29 + +# Dell Precision 5510 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnPrecision5510* + EVDEV_ABS_00=::42 + EVDEV_ABS_01=::43 + EVDEV_ABS_35=::42 + EVDEV_ABS_36=::43 + +# Dell Precision M4700 +evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*svnDellInc.:pnPrecisionM4700* + EVDEV_ABS_00=0:1960:24 + EVDEV_ABS_01=113:1436:30 + EVDEV_ABS_35=0:1960:24 + EVDEV_ABS_36=113:1436:30 + +# Dell XPS13 9360 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnDellInc.:pnXPS139360:cvr:* + EVDEV_ABS_00=::42 + EVDEV_ABS_01=::60 + EVDEV_ABS_35=::42 + EVDEV_ABS_36=::60 + +# Dell XPS15 9550 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPS159550* + EVDEV_ABS_00=::41 + EVDEV_ABS_01=::43 + EVDEV_ABS_35=::41 + EVDEV_ABS_36=::43 + +# Dell XPS M1530 +evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:bvn*:bvr*:bd*:svnDellInc.:pnXPSM1530* + EVDEV_ABS_00=85:947:15 + EVDEV_ABS_01=154:726:18 + +##### +# Sun +##### + +# Fujitsu Component - USB Touch Panel +evdev:input:b0003v0430p0530* + EVDEV_ABS_00=0:4096:16 + EVDEV_ABS_01=0:4096:16 + +######################################### +# Google +######################################### + +# Chromebook Pixel (2015) - Samus +evdev:name:Atmel maXTouch Touch*:dmi:bvn*:bvr*:bd*:svnGOOGLE:pnSamus* + EVDEV_ABS_00=::10 + EVDEV_ABS_01=::10 + EVDEV_ABS_35=::10 + EVDEV_ABS_36=::10 + +######################################### +# HP +######################################### + +# HP Chromebook 14 (Falco) +evdev:name:Cypress APA Trackpad ?cyapa?:dmi:*:svnHewlett-Packard*:pnFalco*: + EVDEV_ABS_00=:::8 + EVDEV_ABS_01=:::8 + EVDEV_ABS_35=:::8 + EVDEV_ABS_36=:::8 + +# HP Pavilion dm4 +evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondm4* + EVDEV_ABS_00=1360:5563:47 + EVDEV_ABS_01=1269:4618:61 + EVDEV_ABS_35=1360:5563:47 + EVDEV_ABS_36=1269:4618:61 + +# HP Pavilion g6 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:bvnHewlett-Packard:*svnHewlett-Packard:pnHPPaviliong6* + EVDEV_ABS_00=1255:5728:50 + EVDEV_ABS_01=1215:4761:71 + EVDEV_ABS_35=1255:5728:50 + EVDEV_ABS_36=1215:4761:71 + +# HP Pavilion dv7 +evdev:name:SynPS/2 Synaptics TouchPad*:dmi:*svnHewlett-Packard:pnHPPaviliondv7* + EVDEV_ABS_00=1068:5805:44 + EVDEV_ABS_01=1197:4890:57 + EVDEV_ABS_35=1068:5805:44 + EVDEV_ABS_36=1197:4890:57 + +# HP Pavilion 15 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnHP:pnHPLaptop15-bs0xx:* + EVDEV_ABS_00=1272:5689:38 + EVDEV_ABS_01=1029:4916:78 + EVDEV_ABS_35=1272:5689:38 + EVDEV_ABS_36=1029:4916:78 + +# HP Spectre +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnHP:pnHPSpectreNotebook* + EVDEV_ABS_00=1205:5691:47 + EVDEV_ABS_01=1083:4808:65 + EVDEV_ABS_35=1205:5691:47 + EVDEV_ABS_36=1083:4808:65 + +# HP Envy x360 +evdev:name:SynPS/2 Synaptics TouchPad:*svnHP:pnHPENVYx360Convertible15m-cn0xxx* + EVDEV_ABS_00=1302:5640:36 + EVDEV_ABS_01=1119:4741:61 + EVDEV_ABS_35=1302:5640:36 + EVDEV_ABS_36=1119:4741:61 + +######################################### +# Lenovo +######################################### + +# Lenovo B590 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrLenovoB590* + EVDEV_ABS_00=1243:5759:48 + EVDEV_ABS_01=1130:4832:65 + EVDEV_ABS_35=1243:5759:48 + EVDEV_ABS_36=1130:4832:65 + +# Lenovo E530 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:pn*ThinkPadEdgeE530* + EVDEV_ABS_00=1241:5703:49 + EVDEV_ABS_01=1105:4820:68 + EVDEV_ABS_35=1241:5703:49 + EVDEV_ABS_36=1105:4820:68 + +# Lenovo L430 +evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnLENOVO*:pvrThinkPadL430* + EVDEV_ABS_00=19:2197:29 + EVDEV_ABS_01=12:1151:25 + EVDEV_ABS_35=19:2197:29 + EVDEV_ABS_36=12:1151:25 + +# Lenovo P50 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*P50* + EVDEV_ABS_00=::44 + EVDEV_ABS_01=::67 + EVDEV_ABS_35=::44 + EVDEV_ABS_36=::67 + +# Lenovo *40 series +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPad??40:* +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPad??40?:* + EVDEV_ABS_00=::41 + EVDEV_ABS_01=::37 + EVDEV_ABS_35=::41 + EVDEV_ABS_36=::37 + +# Lenovo ThinkPad X140e +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX140e* + EVDEV_ABS_00=1176:5767:62 + EVDEV_ABS_01=416:5534:160 + EVDEV_ABS_35=1176:5767:62 + EVDEV_ABS_36=416:5534:160 + +# Lenovo ThinkPad T430 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadT430* + EVDEV_ABS_00=1250:5631:58 + EVDEV_ABS_01=1309:4826:78 + EVDEV_ABS_35=1250:5631:58 + EVDEV_ABS_36=1309:4826:78 + +# Lenovo Thinkpad Carbon X1 4th gen. and X1 Yoga 1st gen. +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX1Carbon4th* + EVDEV_ABS_00=1262:5679:44 + EVDEV_ABS_01=1101:4824:65 + EVDEV_ABS_35=1262:5679:44 + EVDEV_ABS_36=1101:4824:65 + +# Lenovo Thinkpad Carbon X1 5th gen. +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pvrThinkPadX1Carbon5th* + EVDEV_ABS_00=::44 + EVDEV_ABS_01=::65 + EVDEV_ABS_35=::44 + EVDEV_ABS_36=::65 + +# Lenovo Thinkpad Carbon X1 5th gen. (rmi4) +evdev:name:Synaptics TM3289-002:dmi:*svnLENOVO*:pvrThinkPadX1Carbon5th* + EVDEV_ABS_00=::19 + EVDEV_ABS_01=::19 + EVDEV_ABS_35=::19 + EVDEV_ABS_36=::19 + +# Lenovo T460 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T460* + EVDEV_ABS_00=1266:5677:44 + EVDEV_ABS_01=1093:4832:65 + EVDEV_ABS_35=1266:5677:44 + EVDEV_ABS_36=1093:4832:65 + +# Lenovo T510 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*T510* + EVDEV_ABS_00=778:6239:72 + EVDEV_ABS_01=841:5330:100 + EVDEV_ABS_35=778:6239:72 + EVDEV_ABS_36=841:5330:100 + +# Lenovo V360 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrLenovoV360* + EVDEV_ABS_00=1243:5927:60 + EVDEV_ABS_01=902:5330:108 + +# Lenovo W530 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadW530* + EVDEV_ABS_00=1250:5631:59 + EVDEV_ABS_01=1205:4834:81 + EVDEV_ABS_35=1250:5631:59 + EVDEV_ABS_36=1205:4834:81 + +# Lenovo X220 series +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO:*pvrThinkPadX220* + EVDEV_ABS_00=1316:5627:58 + EVDEV_ABS_01=1355:4826:81 + EVDEV_ABS_35=1316:5627:58 + EVDEV_ABS_36=1355:4826:81 + +# Lenovo X230 series +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*ThinkPad*X230* + EVDEV_ABS_01=::100 + EVDEV_ABS_36=::100 + +# Lenovo Y700-14ISK +evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapadY700-14ISK* + EVDEV_ABS_00=::27 + EVDEV_ABS_01=::29 + EVDEV_ABS_35=::27 + EVDEV_ABS_36=::29 + +# Lenovo Ideapad 310S-14ISK +evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapad310S-14ISK* + EVDEV_ABS_00=113:3960:37 + EVDEV_ABS_01=100:1959:27 + EVDEV_ABS_35=113:3960:37 + EVDEV_ABS_36=100:1959:27 + +# Lenovo Ideapad 500S-13ISK +evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoideapad500S-13ISK* + EVDEV_ABS_00=125:3955:37 + EVDEV_ABS_01=104:1959:27 + EVDEV_ABS_35=125:3954:37 + EVDEV_ABS_36=104:1959:27 + +# Lenovo Yoga 500-14ISK +evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoYoga500-14ISK* + EVDEV_ABS_00=124:3955:36 + EVDEV_ABS_01=103:1959:26 + EVDEV_ABS_35=124:3955:36 + EVDEV_ABS_36=103:1959:26 + +# Lenovo Flex 3 15-inch +evdev:name:AlpsPS/2 ALPS GlidePoint*:dmi:bvn*:bvr*:bd*:svnLENOVO*:pvrFlex3-15* + EVDEV_ABS_00=::38 + EVDEV_ABS_01=::28 + EVDEV_ABS_35=::38 + EVDEV_ABS_36=::28 + +# Lenovo ThinkPad Edge 13 (02173BG) +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnLENOVO*:pn*02173BG*:*pvrThinkPadEdge* + EVDEV_ABS_00=916:6077:55 + EVDEV_ABS_01=653:5395:116 + EVDEV_ABS_35=916:6077:55 + EVDEV_ABS_36=653:5395:116 + +# Lenovo Yoga 500-14IBD, 80N4 +evdev:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnLENOVO:*pvrLenovoYoga500-14IBD* + EVDEV_ABS_00=117:3952:36 + EVDEV_ABS_01=105:1960:26 + EVDEV_ABS_35=117:3952:36 + EVDEV_ABS_36=105:1960:26 + +# Lenovo Thinkpad T490 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*:svnLENOVO:*pvrThinkPadT490:* + EVDEV_ABS_00=::57 + EVDEV_ABS_01=::33 + EVDEV_ABS_35=::57 + EVDEV_ABS_36=::33 + +######################################### +# Razer +######################################### + +# Razer Blade Stealth +evdev:name:1A58675*:00 06CB:8323 Touchpad:dmi:*svnRazer:pnBladeStealth:* + EVDEV_ABS_00=::12:8 + EVDEV_ABS_01=::11:8 + EVDEV_ABS_35=::12:8 + EVDEV_ABS_36=::11:8 + +# Razer Blade Stealth (2016) +evdev:name:Synaptics TM2438-005:dmi:*svnRazer:pnBladeStealth* + EVDEV_ABS_00=0:4064:29 + EVDEV_ABS_01=0:2405:37 + EVDEV_ABS_35=0:4064:29 + EVDEV_ABS_36=0:2405:37 + +######################################### +# Samsung +######################################### + +# Samsung 305V4 +evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn305V4A/305V5A* + EVDEV_ABS_00=0:2480:28 + EVDEV_ABS_01=0:1116:24 + EVDEV_ABS_35=0:2480:28 + EVDEV_ABS_36=0:1116:24 + +# Samsung 880Z5E +evdev:name:ETPS/2 Elantech Touchpad:dmi:*svnSAMSUNGELECTRONICSCO.,LTD.:pn870Z5E/880Z5E/680Z5E* + EVDEV_ABS_00=::30 + EVDEV_ABS_01=::29 + EVDEV_ABS_35=::30 + EVDEV_ABS_36=::29 + +######################################### +# System76 +######################################### + +# GalagoPro 2 (galp2) +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnSystem76:pnGalagoPro:pvrgalp2:* + EVDEV_ABS_00=1238:5747:50 + EVDEV_ABS_01=901:4900:83 + EVDEV_ABS_35=1238:5747:50 + EVDEV_ABS_36=901:4900:83 + +######################################### +# Toshiba +######################################### + +# Toshiba Tecra M11 +evdev:name:AlpsPS/2 ALPS DualPoint TouchPad:dmi:*svnTOSHIBA:pnTECRAM11* + EVDEV_ABS_00=90:962:11 + EVDEV_ABS_01=51:681:14 + +# Toshiba Satellite R830 +evdev:name:SynPS/2 Synaptics TouchPad:dmi:*svnTOSHIBA:pnSATELLITER830* + EVDEV_ABS_00=1238:5785:53 + EVDEV_ABS_01=1045:4826:76 + EVDEV_ABS_35=1238:5785:53 + EVDEV_ABS_36=1045:4826:76 + +######################################### +# UGTablet +######################################### + +# Trust Flex Graphics Tablet +evdev:input:b0003v2179p0004* + EVDEV_ABS_00=::234 + EVDEV_ABS_01=::328 + +######################################### +# Waltop +######################################### + +# WALTOP International Corp. Slim Tablet +evdev:input:b0003v172Fp0031* + EVDEV_ABS_00=0:10000:400 + EVDEV_ABS_01=0:6250:400 + +#WALTOP International Corp. Graphics Tablet +evdev:input:b0003v172Fp0047* + EVDEV_ABS_00=0:20000:80 + EVDEV_ABS_01=0:12500:80 diff --git a/hwdb.d/60-input-id.hwdb b/hwdb.d/60-input-id.hwdb new file mode 100644 index 00000000..20c1e7ea --- /dev/null +++ b/hwdb.d/60-input-id.hwdb @@ -0,0 +1,72 @@ +# This file is part of systemd. +# +# The lookup keys are composed in: +# 60-input-id.rules +# +# Note: The format of the "input-id:" prefix match key is a +# contract between the rules file and the hardware data, it might +# change in later revisions to support more or better matches, it +# is not necessarily expected to be a stable ABI. +# +# Match string formats: +# id-input:modalias: +# +# To add local entries, create a new file +# /etc/udev/hwdb.d/61-input-id-local.hwdb +# and add your rules there. To load the new rules execute (as root): +# systemd-hwdb update +# udevadm trigger /dev/input/eventXX +# where /dev/input/eventXX is the device in question. If in +# doubt, simply use /dev/input/event* to reload all input rules. +# +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of +# udevadm info /dev/input/eventXX. +# +# This file must only be used where the input_id builtin assigns the wrong +# properties or lacks the assignment of some properties. This is almost +# always caused by a device not adhering to the standard of the device's +# type. +# +# Allowed properties are: +# ID_INPUT +# ID_INPUT_ACCELEROMETER, ID_INPUT_MOUSE, +# ID_INPUT_POINTINGSTICK, ID_INPUT_TOUCHSCREEN, ID_INPUT_TOUCHPAD, +# ID_INPUT_TABLET, ID_INPUT_TABLET_PAD, ID_INPUT_JOYSTICK, ID_INPUT_KEY, +# ID_INPUT_KEYBOARD, ID_INPUT_SWITCH, ID_INPUT_TRACKBALL +# +# ID_INPUT +# * MUST be set when ANY of ID_INPUT_* is set +# * MUST be unset when ALL of ID_INPUT_* are unset +# +# ID_INPUT_TABLET +# * MUST be set when setting ID_INPUT_TABLET_PAD +# +# Allowed values are 1 and 0 to set or unset, repsectively. +# +# NOT allowed in this file are: +# ID_INPUT_WIDTH_MM, ID_INPUT_HEIGHT_MM, ID_INPUT_TOUCHPAD_INTEGRATION +# + +# Example: +# id-input:modalias:input:b0003v1234pABCD* +# ID_INPUT_TOUCHPAD=1 +# ID_INPUT=1 + +# Sort by brand, model + +# UC-Logic TABLET 1060N Pad +id-input:modalias:input:b0003v5543p0081* + ID_INPUT_TABLET=1 + ID_INPUT_TABLET_PAD=1 + +# XP-PEN STAR 06 +id-input:modalias:input:b0003v28bdp0078* + ID_INPUT_TABLET=1 + +# Lite-On Tech IBM USB Travel Keyboard with Ultra Nav Mouse +id-input:modalias:input:b0003v04B3p301Ee0100-e0,1,2,4* + ID_INPUT_POINTINGSTICK=1 diff --git a/hwdb.d/60-keyboard.hwdb b/hwdb.d/60-keyboard.hwdb new file mode 100644 index 00000000..1f6a8f05 --- /dev/null +++ b/hwdb.d/60-keyboard.hwdb @@ -0,0 +1,1740 @@ +# This file is part of systemd. +# +# This file contains 3 types of metadata to apply to keyboards and +# keyboard-like input devices: +# - Key mapping +# - Hard-coded layouts +# - Absence of modifier LEDs +# +# The matching process is the same for the different types of metadata. +# +# ########################### MATCHING ####################################### +# +# The lookup keys are composed in: +# 60-evdev.rules +# +# Note: The format of the "evdev:" prefix match key is a +# contract between the rules file and the hardware data, it might +# change in later revisions to support more or better matches, it +# is not necessarily expected to be a stable ABI. +# +# Supported hardware matches are: +# - Generic input devices match: +# evdev:input:bZZZZvYYYYpXXXXeWWWW-VVVV +# This matches on the kernel modalias of the input-device, mainly: +# ZZZZ is the bus-id (see /usr/include/linux/input.h BUS_*), YYYY, XXXX and +# WWWW are the 4-digit hex uppercase vendor, product and version ID and VVVV +# is an arbitrary length input-modalias describing the device capabilities. +# The vendor, product and version ID for a device node "eventX" is listed +# in /sys/class/input/eventX/device/id. +# +# - AT keyboard DMI data matches: +# evdev:atkbd:dmi:bvn*:bvr*:bd*:svn:pn:pvr* +# and are the firmware-provided strings +# exported by the kernel DMI modalias, see /sys/class/dmi/id/modalias +# +# - Input driver device name and DMI data match: +# evdev:name::dmi:bvn*:bvr*:bd*:svn:pn* +# is the name device specified by the +# driver, is the firmware-provided string exported +# by the kernel DMI modalias, see /sys/class/dmi/id/modalias +# +# - Extended input driver device name, properties and DMI data match: +# evdev:name::phys::ev::dmi:bvn*:bvr*:bd*:svn:pn* +# is the name device specified by the +# driver, is the physical-device-path, "cat +# /sys/class/input/input?/phys", is the event bitmask, "cat +# /sys/class/input/input?/capabilities/ev" and is the +# firmware-provided string exported by the kernel DMI modalias, +# see /sys/class/dmi/id/modalias + + +# ######################### KEY MAPPING ###################################### +# +# Keyboard mapping of scan codes to key codes, and +# scan codes to add to the AT keyboard's 'force-release' list. +# +# Scan codes are specified as: +# KEYBOARD_KEY_= +# The scan code should be expressed in hex lowercase. The key codes +# are retrieved and normalized from the kernel input API header. +# Keycodes are either KEY_* defines in lowercase with the key_ prefix +# optionally removed or BTN_ defines in lowercase with btn_ preserved. +# +# An '!' as the first character of the key identifier string +# will add the scan code to the AT keyboard's list of scan codes +# where the driver will synthesize a release event and not expect +# it to be generated by the hardware. +# +# To debug key presses and access scan code mapping data of +# an input device use the commonly available tool: evtest(1). + +# A device with a fixed keyboard layout that must not be changed by +# the desktop environment may specify that layout as: +# XKB_FIXED_LAYOUT="us" +# XKB_FIXED_VARIANT="" +# Examples of such devices: the Yubikey or other key-code generating +# devices. + +# A device where the scan code to key code mapping is insufficient and +# requires a special key code to symbol configuration may specify that with: +# XKB_FIXED_MODEL="xkbmodel" +# Examples of such devices: Chromebooks where the top row is used for both +# media and F1-F10 keys. + +# To update this file, create a new file +# /etc/udev/hwdb.d/70-keyboard.hwdb +# and add your rules there. To load the new rules execute (as root): +# systemd-hwdb update +# udevadm trigger /dev/input/eventXX +# where /dev/input/eventXX is the keyboard in question. If in +# doubt, simply reload all input rules +# udevadm trigger --verbose --sysname-match="event*" +# +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of +# udevadm info /dev/input/eventXX. + +########################################## +# Acer +########################################## + +# common keys +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pnA0A1*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svneMachines:pneMachines*E725:pvr* + KEYBOARD_KEY_86=wlan # Fn+F3 or Fn+Q for comunication key + KEYBOARD_KEY_a5=help # Fn+F1 + KEYBOARD_KEY_a6=setup # Fn+F2 Acer eSettings + KEYBOARD_KEY_a7=battery # Fn+F3 Power Management + KEYBOARD_KEY_a9=switchvideomode # Fn+F5 + KEYBOARD_KEY_b2=www + KEYBOARD_KEY_b3=euro + KEYBOARD_KEY_b4=dollar + KEYBOARD_KEY_ce=brightnessup # Fn+Right + KEYBOARD_KEY_d4=bluetooth # (toggle) off-to-on + KEYBOARD_KEY_d5=wlan # (toggle) on-to-off + KEYBOARD_KEY_d6=wlan # (toggle) off-to-on + KEYBOARD_KEY_d7=bluetooth # (toggle) on-to-off + KEYBOARD_KEY_d8=bluetooth # (toggle) off-to-on + KEYBOARD_KEY_d9=brightnessup # Fn+Right + KEYBOARD_KEY_ee=brightnessup # Fn+Right + KEYBOARD_KEY_ef=brightnessdown # Fn+Left + KEYBOARD_KEY_f1=f22 # Fn+F7 Touchpad toggle (off-to-on) + KEYBOARD_KEY_f2=f23 # Fn+F7 Touchpad toggle (on-to-off) + KEYBOARD_KEY_f3=prog2 # "P2" programmable button + KEYBOARD_KEY_f4=prog1 # "P1" programmable button + KEYBOARD_KEY_f5=presentation + KEYBOARD_KEY_f6=power # Power button + KEYBOARD_KEY_f8=fn + KEYBOARD_KEY_f9=prog1 # Launch NTI shadow + +# Acer kernel driver +evdev:name:Acer WMI hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnAcer*:pvr* + KEYBOARD_KEY_82=f21 # Touchpad toggle + +# Aspire models +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*:pvr* + KEYBOARD_KEY_84=bluetooth # sent when bluetooth module missing, and key pressed + KEYBOARD_KEY_d9=bluetooth # Bluetooth off + KEYBOARD_KEY_92=media # Acer arcade + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*5720*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnZG8*:pvr* + KEYBOARD_KEY_f4=prog3 # e-key + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*5920G:* + KEYBOARD_KEY_8a=media + KEYBOARD_KEY_a6=setup + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*6920:* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*8930:* + KEYBOARD_KEY_ca=prog3 # key 'HOLD' on CineDash Media Console + KEYBOARD_KEY_83=rewind + KEYBOARD_KEY_89=fastforward + KEYBOARD_KEY_9e=back + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*7750G:pvr* + KEYBOARD_KEY_e0=!pageup + +# Travelmate C300 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*C3[01]0*:pvr* + KEYBOARD_KEY_67=f24 # FIXME: rotate screen + KEYBOARD_KEY_68=up + KEYBOARD_KEY_69=down + KEYBOARD_KEY_6b=fn + KEYBOARD_KEY_6c=screenlock # FIXME: lock tablet device/buttons + +# Travelmate P648-G2-MG, P648-G3-M and P645-S +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*P648-G2-MG*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*P648-G3-M*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*P645-S*:pvr* + KEYBOARD_KEY_8a=f20 # Microphone mute button; should be micmute + +# on some models this isn't brightnessup +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5210*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5220*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5610*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5620*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn*5720*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*4720*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*6593:* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*1640:* + KEYBOARD_KEY_ee=screenlock + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAOA*:pvr* + KEYBOARD_KEY_a9=!switchvideomode # Fn+F5 + +# Packard Bell and Gateway models +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGateway*:pn* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPackard*Bell*:pn* + KEYBOARD_KEY_86=wlan # Fn+F3 or Fn+Q for comunication key + +########################################################### +# Alienware +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pn* + KEYBOARD_KEY_81=f21 # Touchpad toggle + KEYBOARD_KEY_8a=ejectcd + +# Alienware/Dell reserves these keys; safe to apply on all their devices +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pn*:pvr* + KEYBOARD_KEY_bf=!prog1 #graphics amplifier, cable plug-in event + KEYBOARD_KEY_c1=!prog2 #graphics amplifier, undock-button event + KEYBOARD_KEY_c2=!power #graphics amplifier, surprise undock event + +# Alienware M17xR3 laptops +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAlienware*:pnM17xR3:* + KEYBOARD_KEY_89=ejectcd + +########################################################### +# Asus +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnASUS:pn* + KEYBOARD_KEY_ed=volumeup + KEYBOARD_KEY_ee=volumedown + KEYBOARD_KEY_ef=mute + +evdev:name:Asus WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr* +evdev:name:Eee PC WMI hotkeys:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr* +evdev:name:Asus Laptop extra buttons:dmi:bvn*:bvr*:bd*:svnASUS*:pn*:pvr* + KEYBOARD_KEY_6b=f21 # Touchpad Toggle + +# USB keyboard in Asus FX503VD +evdev:input:b0003v0B05p1869* + KEYBOARD_KEY_ff31007c=f20 # Remap micmute to f20 + +########################################################### +# BenQ +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*BenQ*:pn*Joybook*R22*:pvr* + KEYBOARD_KEY_6e=wlan + +########################################################### +# Clevo +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnNotebook:pnW65_67SZ:pvr* + KEYBOARD_KEY_a0=!mute + KEYBOARD_KEY_a2=!playpause + KEYBOARD_KEY_ae=!volumedown + KEYBOARD_KEY_b0=!volumeup + +########################################################### +# Compal +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnCOMPAL:pnHEL80I:* + KEYBOARD_KEY_84=wlan + +########################################################### +# COMPAQ +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnCompaq*:pn*E500*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnCompaq*:pn*Evo*N*:pvr* + KEYBOARD_KEY_a3=www # I key + KEYBOARD_KEY_9a=search + KEYBOARD_KEY_9e=email + KEYBOARD_KEY_9f=homepage + +evdev:input:b0003v049Fp0051* + KEYBOARD_KEY_0c0011=presentation + KEYBOARD_KEY_0c0012=addressbook + KEYBOARD_KEY_0c0013=info + KEYBOARD_KEY_0c0014=prog1 + KEYBOARD_KEY_0c0015=messenger + +########################################################### +# Cube +########################################################### + +evdev:name:gpio-keys:phys:gpio-keys/input0:ev:3:dmi:bvn*:bvr*:bd*:svncube:pni1-TF:* + KEYBOARD_KEY_0=leftmeta + KEYBOARD_KEY_1=power + +########################################################### +# Dell +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pn* + KEYBOARD_KEY_81=playpause # Play/Pause + KEYBOARD_KEY_82=stopcd # Stop + KEYBOARD_KEY_83=previoussong # Previous song + KEYBOARD_KEY_84=nextsong # Next song + KEYBOARD_KEY_85=brightnessdown # Fn+Down Brightness Down + KEYBOARD_KEY_86=brightnessup # Fn+Up Brightness Up + KEYBOARD_KEY_87=battery # Fn+F3 battery icon + KEYBOARD_KEY_88=unknown # Fn+F2 Turn On/Off Wireless - handled in hardware + KEYBOARD_KEY_89=ejectclosecd # Fn+F10 Eject CD + KEYBOARD_KEY_8a=suspend # Fn+F1 hibernate + KEYBOARD_KEY_8b=switchvideomode # Fn+F8 CRT/LCD (high keycode: "displaytoggle") + KEYBOARD_KEY_8c=unknown # Fn+Right Auto Brightness + KEYBOARD_KEY_8f=switchvideomode # Fn+F7 aspect ratio + KEYBOARD_KEY_90=previoussong # Front panel previous song + KEYBOARD_KEY_91=prog1 # Wi-Fi Catcher (Dell-specific) + KEYBOARD_KEY_92=media # MediaDirect button (house icon) + KEYBOARD_KEY_93=unknown # FIXME Fn+Left Auto Brightness + KEYBOARD_KEY_95=camera # Shutter button - Takes a picture if optional camera available + KEYBOARD_KEY_97=email # Tablet email button + KEYBOARD_KEY_98=f21 # FIXME: Tablet screen rotation + KEYBOARD_KEY_99=nextsong # Front panel next song + KEYBOARD_KEY_9a=setup # Tablet tools button + KEYBOARD_KEY_9b=switchvideomode # Display toggle button + KEYBOARD_KEY_9e=f21 # Touchpad toggle + KEYBOARD_KEY_a2=playpause # Front panel play/pause + KEYBOARD_KEY_a4=stopcd # Front panel stop + KEYBOARD_KEY_ed=media # MediaDirect button + KEYBOARD_KEY_d8=screenlock # FIXME: Tablet lock button + KEYBOARD_KEY_d9=f21 # Touchpad toggle + +# +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*910:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*101[012]:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1110:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1210:pvr* + KEYBOARD_KEY_84=wlan + +# Dell Inspiron 1520 and Latitude 2110 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron*1520:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*2110:pvr* + KEYBOARD_KEY_85=unknown # Brightness Down, also emitted by acpi-video, ignore + KEYBOARD_KEY_86=unknown # Brightness Up, also emitted by acpi-video, ignore + +# Dell Inspiron 537* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnInspiron537*:pvr* + KEYBOARD_KEY_88=!wlan # Fn-PrtScr rfkill + +# Latitude XT2 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*XT2:pvr* + KEYBOARD_KEY_9b=up # tablet rocker up + KEYBOARD_KEY_9e=enter # tablet rocker press + KEYBOARD_KEY_9f=back # tablet back + KEYBOARD_KEY_a3=down # tablet rocker down + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnStudio*155[78]:pvr* + KEYBOARD_KEY_a0=! # mute + KEYBOARD_KEY_ae=! # volume down + KEYBOARD_KEY_b0=! # volume up + +# Dell Touchpad +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision*:pvr* + KEYBOARD_KEY_88=! # wireless switch + KEYBOARD_KEY_9e=!f21 + +# Dell Latitude E7* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude*E7*:pvr* + KEYBOARD_KEY_88=unknown # Fn-PrtScr rfkill - handled in HW + +# Dell XPS +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnXPS*:pvr* + KEYBOARD_KEY_8c=!unknown + +# Dell XPS L702x +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDellInc.:pnDellSystemXPSL702X:pvr* + KEYBOARD_KEY_84=prog1 + KEYBOARD_KEY_85=prog2 + +# Dell XPS12 9Q33 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDell*:pnXPS12-9Q33*:pvr* + KEYBOARD_KEY_88=wlan + KEYBOARD_KEY_65=direction # Screen Rotate + +# Dell Latitude microphone mute +evdev:name:Dell WMI hotkeys:dmi:bvn*:bvr*:bd*:svnDell*:pnLatitude* +# Dell Precision microphone mute +evdev:name:Dell WMI hotkeys:dmi:bvn*:bvr*:bd*:svnDell*:pnPrecision* + KEYBOARD_KEY_100150=f20 # Mic mute toggle, should be micmute + +########################################################### +# Everex +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnEverex:pnXT5000*:pvr* + KEYBOARD_KEY_5c=media + KEYBOARD_KEY_65=f21 # Fn+F5 Touchpad toggle + KEYBOARD_KEY_67=prog3 # Fan speed control button + KEYBOARD_KEY_6f=brightnessup + KEYBOARD_KEY_7f=brightnessdown + KEYBOARD_KEY_b2=www + KEYBOARD_KEY_ec=mail + +########################################## +# Fujitsu +########################################## + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAMILO*M*:pvr* + KEYBOARD_KEY_97=prog2 + KEYBOARD_KEY_9f=prog1 + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAmilo*Li*1718:* + KEYBOARD_KEY_d6=wlan + +# Amilo Li 2732 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pnAMILO*Li*2732:* + KEYBOARD_KEY_d9=brightnessdown # Fn+F8 brightness down + KEYBOARD_KEY_ef=brightnessup # Fn+F9 brightness up + KEYBOARD_KEY_a9=switchvideomode # Fn+F10 Cycle between available video outputs + +# Amilo Pa 2548 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pa*2548*:pvr* + KEYBOARD_KEY_e0=volumedown + KEYBOARD_KEY_e1=volumeup + KEYBOARD_KEY_e5=prog1 + +# Amilo Pro Edition V3505 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pro*Edition*V3505*:pvr* + KEYBOARD_KEY_a5=help # Fn+F1 + KEYBOARD_KEY_a9=switchvideomode # Fn+F3 + KEYBOARD_KEY_d9=brightnessdown # Fn+F8 + KEYBOARD_KEY_e0=brightnessup # Fn+F9 + +# Amilo Pro v3205 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*AMILO*Pro*V3205*:pvr* + KEYBOARD_KEY_f4=f21 # FIXME: silent-mode decrease CPU/GPU clock + KEYBOARD_KEY_f7=switchvideomode # Fn+F3 + +# Amilo Si 1520 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*Amilo*Si*1520*:pvr* + KEYBOARD_KEY_e1=wlan + KEYBOARD_KEY_f3=wlan + KEYBOARD_KEY_ee=brightnessdown + KEYBOARD_KEY_e0=brightnessup + KEYBOARD_KEY_e2=bluetooth + KEYBOARD_KEY_f7=video + +# Esprimo Mobile V5 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*ESPRIMO*Mobile*V5*:pvr* + KEYBOARD_KEY_a9=switchvideomode + KEYBOARD_KEY_d9=brightnessdown + KEYBOARD_KEY_df=sleep + KEYBOARD_KEY_ef=brightnessup + +# Esprimo Mobile V6 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*:pn*ESPRIMO*Mobile*V6*:pvr* + KEYBOARD_KEY_ce=brightnessup + KEYBOARD_KEY_ef=brightnessdown + +########################################################### +# GIGABYTE +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGIGABYTE:pnU2442:* + KEYBOARD_KEY_a0=! # mute + +########################################################### +# Gemini +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGeminiDevices:pnNC14V1006:* + KEYBOARD_KEY_9c=enter + +########################################################### +# Genius +########################################################### + +# Slimstar 320 +evdev:input:b0003v0458p0708* + KEYBOARD_KEY_0900f0=scrollup + KEYBOARD_KEY_0900f1=scrolldown + KEYBOARD_KEY_0900f3=back + KEYBOARD_KEY_0900f2=forward + KEYBOARD_KEY_0900f5=wordprocessor + KEYBOARD_KEY_0900f6=spreadsheet + KEYBOARD_KEY_0900f4=presentation + KEYBOARD_KEY_0c0223=www + KEYBOARD_KEY_0900f7=chat + KEYBOARD_KEY_0900fb=prog1 + KEYBOARD_KEY_0900f8=close + KEYBOARD_KEY_0900f9=graphicseditor + KEYBOARD_KEY_0900fd=scale + KEYBOARD_KEY_0900fc=screenlock + +########################################################### +# Hewlett Packard +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pn*:pvr* + KEYBOARD_KEY_81=fn_esc + KEYBOARD_KEY_89=battery # Fn+F8 + KEYBOARD_KEY_8a=screenlock # Fn+F6 + KEYBOARD_KEY_8b=camera + KEYBOARD_KEY_8c=media # music + KEYBOARD_KEY_8e=dvd + KEYBOARD_KEY_b1=help + KEYBOARD_KEY_b3=unknown # FIXME: Auto brightness + KEYBOARD_KEY_d7=wlan + KEYBOARD_KEY_92=brightnessdown # Fn+F7 (Fn+F9 on 6730b) + KEYBOARD_KEY_97=brightnessup # Fn+F8 (Fn+F10 on 6730b) + KEYBOARD_KEY_ee=switchvideomode # Fn+F4 + +# Tablet +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[tT][aA][bB][lL][eE][tT]*:pvr* + KEYBOARD_KEY_82=prog2 # Funny Key + KEYBOARD_KEY_83=prog1 # Q + KEYBOARD_KEY_84=tab + KEYBOARD_KEY_85=esc + KEYBOARD_KEY_86=pageup + KEYBOARD_KEY_87=pagedown + +# Pavilion +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[pP][aA][vV][iI][lL][iI][oO][nN]*:pvr* + KEYBOARD_KEY_88=media # FIXME: quick play + KEYBOARD_KEY_b7=print + KEYBOARD_KEY_d8=!f23 # touchpad off + KEYBOARD_KEY_d9=!f22 # touchpad on + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*Pavilion*dv7*Notebook*PC:pvr* + KEYBOARD_KEY_b7=print + KEYBOARD_KEY_c2=media # FIXME: quick play + KEYBOARD_KEY_c6=break + KEYBOARD_KEY_94=reserved + +# Pavilion and Spectre x360 13 (Prevents random airplane mode activation) +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[sS][pP][eE][cC][tT][rR][eE]*x360*13*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pn*[sS][pP][eE][cC][tT][rR][eE]*x360Convertible*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[pP][aA][vV][iI][lL][iI][oO][nN]*13*x360*:pvr* + KEYBOARD_KEY_d7=unknown + +# Elitebook +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Compaq*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*EliteBook*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2230s*:pvr* + KEYBOARD_KEY_88=presentation + KEYBOARD_KEY_d9=help # I key (high keycode: "info") + +# Presario +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*Presario*CQ*:pvr* + KEYBOARD_KEY_d8=f21 + KEYBOARD_KEY_d9=f21 + +# 2510p 2530p +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2510p*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2530p*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*G60*Notebook*PC:pvr* + KEYBOARD_KEY_d8=!f23 # touchpad off + KEYBOARD_KEY_d9=!f22 # touchpad on + +# 2570p +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*2570p*:pvr* + KEYBOARD_KEY_f8=wlan # Wireless HW switch button + +# TX2 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pn*[tT][xX]2*:pvr* + KEYBOARD_KEY_c2=media + KEYBOARD_KEY_d8=!f23 # Toggle touchpad button on tx2 (OFF) + KEYBOARD_KEY_d9=!f22 # Toggle touchpad button on tx2 (ON) + +# Presario 2100 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnPresario*2100*:pvr* + KEYBOARD_KEY_f0=help + KEYBOARD_KEY_f1=screenlock + KEYBOARD_KEY_f3=search + +# Elitebook 8440p +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*EliteBook*8440p:pvr* + KEYBOARD_KEY_88=www + KEYBOARD_KEY_a0=mute + KEYBOARD_KEY_ae=volumedown + KEYBOARD_KEY_b0=volumeup + KEYBOARD_KEY_ec=mail + +# Elitebook 8460p +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*EliteBook*8460p:pvr* + KEYBOARD_KEY_f8=wlan # Wireless HW switch button + KEYBOARD_KEY_b3=prog1 # Fn+F11 - Ambient Light Sensor button + KEYBOARD_KEY_b1=prog2 # Fn+ESC - System information button + +# HDX9494nr +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHDX9494NR:pvr* + KEYBOARD_KEY_b2=www # Fn+F3 + KEYBOARD_KEY_d8=!f23 # touchpad off + KEYBOARD_KEY_d9=!f22 # touchpad on + +# HP EliteBook 725 G2 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPLicrice:pvr* +# HP ProBook 440 G2 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP440G2:pvr* +# several HP ProBooks 4xx +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*ProBook4*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHP*ProBook*4*:pvr* +# HP ZBook +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPZBook*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP*:pnHPZBook*:pvr* + KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute + +# HP ZBook 15 G2 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPZBook15G2:pvr* + KEYBOARD_KEY_f8=wlan # Wireless HW switch button + +# HP ProBook 11 G1 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPProBook11G1:pvr* + KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute + KEYBOARD_KEY_d8=f21 # touchpad toggle + KEYBOARD_KEY_d9=f21 # touchpad toggle + +# HP ZBook Studio G4 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP:pnHPZBookStudioG4:pvr* + KEYBOARD_KEY_f8=wlan # Wireless HW switch button + +# HP Folio 1040g2 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPEliteBookFolio1040G2:pvr* + KEYBOARD_KEY_81=f20 # Fn+F8; Microphone mute button, should be micmute + KEYBOARD_KEY_d8=!f23 # touchpad off + KEYBOARD_KEY_d9=!f22 # touchpad on + +# HP ProBook 650 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*ProBook*650*:pvr* + KEYBOARD_KEY_f8=wlan # Wireless HW switch button + +# HP ProBook 6555b +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard:pnHPProBook6555b:* + KEYBOARD_KEY_b2=www # Earth + +# HP ProBook 440 G3 +evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*440*G3* +# HP ProBook 640 G2 +evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*640*G2* + KEYBOARD_KEY_85=unknown # lid close; also reported via special evdev + KEYBOARD_KEY_f8=unknown # rf kill; also reported via special evdev + +# HP ProBook 645 G4 +evdev:atkbd:dmi:bvn*:bvr*:svnHP*:pnHP*ProBook*645*G4* + KEYBOARD_KEY_73=slash # Slash key + KEYBOARD_KEY_f8=wlan # Wireless HW switch button + +# HP Stream 7 +# The ACPI tables contains a gpio-keys entry for a non connected GPIO +# causing spurious events, map this to unknown to disable it +# older kernels use "ev:23" newer kernels "ev:3" +evdev:name:gpio-keys:phys:gpio-keys/input0:ev:3:dmi:*:svnHewlett-Packard:pnHPStream7Tablet:* +evdev:name:gpio-keys:phys:gpio-keys/input0:ev:23:dmi:*:svnHewlett-Packard:pnHPStream7Tablet:* + KEYBOARD_KEY_0=unknown + +########################################################## +# Huawei +########################################################## + +# Huawei WMI hotkeys driver +evdev:name:Huawei WMI hotkeys:dmi:bvn*:bvr*:bd*:svnHUAWEI* + KEYBOARD_KEY_287=f20 # Microphone mute button, should be micmute + +# Huawei MACH-WX9 +evdev:atkbd:dmi:bvn*:bvr*:svnHUAWEI*:pnMACH-WX9:pvr* + KEYBOARD_KEY_f7=unknown + KEYBOARD_KEY_f8=fn + +evdev:name:Huawei WMI hotkeys:dmi:bvn*:bvr*:bd*:svnHUAWEI*:pnMACH-WX9:pvr* + KEYBOARD_KEY_281=unknown # Brightness Down, also emitted by acpi-video, ignore + KEYBOARD_KEY_282=unknown # Brightness Up, also emitted by acpi-video, ignore + +########################################################### +# IBM +########################################################### + +# thinkpad_acpi driver +evdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnIBM*:pn*:pvr* + KEYBOARD_KEY_01=battery # Fn+F2 + KEYBOARD_KEY_02=screenlock # Fn+F3 + KEYBOARD_KEY_03=sleep # Fn+F4 + KEYBOARD_KEY_04=wlan # Fn+F5 + KEYBOARD_KEY_06=switchvideomode # Fn+F7 + KEYBOARD_KEY_07=zoom # Fn+F8 screen expand + KEYBOARD_KEY_08=f24 # Fn+F9 undock + KEYBOARD_KEY_0b=suspend # Fn+F12 + KEYBOARD_KEY_0f=brightnessup # Fn+Home + KEYBOARD_KEY_10=brightnessdown # Fn+End + KEYBOARD_KEY_11=kbdillumtoggle # Fn+PgUp - ThinkLight + KEYBOARD_KEY_13=zoom # Fn+Space + KEYBOARD_KEY_14=volumeup + KEYBOARD_KEY_15=volumedown + KEYBOARD_KEY_16=mute + KEYBOARD_KEY_17=prog1 # ThinkPad/ThinkVantage button (high keycode: "vendor") + +# IBM Thinkpad USB Keyboard Trackpoint +evdev:input:b0003v04B3p301[89]* + KEYBOARD_KEY_900f0=screenlock + KEYBOARD_KEY_900f1=wlan + KEYBOARD_KEY_900f2=switchvideomode + KEYBOARD_KEY_900f3=suspend + KEYBOARD_KEY_900f4=brightnessup + KEYBOARD_KEY_900f5=brightnessdown + KEYBOARD_KEY_900f8=zoom + +########################################################### +# Inventec +########################################################### + +# Symphony +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnINVENTEC:pnSYMPHONY*6.0/7.0:pvr* + KEYBOARD_KEY_f3=prog2 + KEYBOARD_KEY_f4=prog1 + +########################################################### +# Lenovo +########################################################### + +# thinkpad_acpi driver +evdev:name:ThinkPad Extra Buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn* + KEYBOARD_KEY_01=screenlock + KEYBOARD_KEY_02=battery + KEYBOARD_KEY_03=sleep + KEYBOARD_KEY_04=wlan + KEYBOARD_KEY_06=switchvideomode + KEYBOARD_KEY_07=f21 + KEYBOARD_KEY_08=f24 + KEYBOARD_KEY_0b=suspend + KEYBOARD_KEY_0f=brightnessup + KEYBOARD_KEY_10=brightnessdown + KEYBOARD_KEY_11=kbdillumtoggle + KEYBOARD_KEY_13=zoom + KEYBOARD_KEY_14=volumeup + KEYBOARD_KEY_15=volumedown + KEYBOARD_KEY_16=mute + KEYBOARD_KEY_17=prog1 + KEYBOARD_KEY_1a=f20 # Microphone mute button; should be micmute + KEYBOARD_KEY_45=bookmarks + +# ThinkPad Keyboard with TrackPoint +evdev:input:b0003v17EFp6009* + KEYBOARD_KEY_090012=screenlock # Fn+F2 + KEYBOARD_KEY_090013=battery # Fn+F3 + KEYBOARD_KEY_090014=wlan # Fn+F5 + KEYBOARD_KEY_090016=switchvideomode # Fn+F7 + KEYBOARD_KEY_090017=f21 # Fn+F8 touchpad toggle + KEYBOARD_KEY_090019=suspend # Fn+F12 + KEYBOARD_KEY_09001a=brightnessup # Fn+Home + KEYBOARD_KEY_09001b=brightnessdown # Fn+End + KEYBOARD_KEY_09001d=zoom # Fn+Space + KEYBOARD_KEY_090011=prog1 # ThinkVantage button + KEYBOARD_KEY_090015=camera # Fn+F6 headset/camera VoIP key ?? + KEYBOARD_KEY_090010=f20 # Microphone mute button; should be micmute + +# Lenovo 3000 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*3000*:pvr* + KEYBOARD_KEY_8b=switchvideomode # Fn+F7 video + KEYBOARD_KEY_96=wlan # Fn+F5 wireless + KEYBOARD_KEY_97=sleep # Fn+F4 suspend + KEYBOARD_KEY_98=suspend # Fn+F12 hibernate + KEYBOARD_KEY_b4=prog1 # Lenovo Care + +# "Lenovo Care" Key of the 3000 N200 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn0769AP2:pvr3000N200:* + KEYBOARD_KEY_b4=prog1 + +# lenovo-ideapad +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pnS10-*:pvr* + KEYBOARD_KEY_81=rfkill # does nothing in BIOS + KEYBOARD_KEY_83=display_off # BIOS toggles screen state + KEYBOARD_KEY_b9=brightnessup # does nothing in BIOS + KEYBOARD_KEY_ba=brightnessdown # does nothing in BIOS + KEYBOARD_KEY_f1=camera # BIOS toggles camera power + KEYBOARD_KEY_f2=f21 # touchpad toggle (key alternately emits F2 and F3) + KEYBOARD_KEY_f3=f21 + +# Thinkpad X200_Tablet +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:pvrThinkPad*X2*Tablet* + KEYBOARD_KEY_5d=menu + KEYBOARD_KEY_63=fn + KEYBOARD_KEY_66=screenlock + KEYBOARD_KEY_67=cyclewindows # bezel circular arrow + KEYBOARD_KEY_68=setup # bezel setup / menu + KEYBOARD_KEY_6c=direction # rotate screen + +# ThinkPad X6 Tablet +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*:pvrThinkPad*X6*Tablet* + KEYBOARD_KEY_6c=direction # rotate + KEYBOARD_KEY_68=leftmeta # toolbox + KEYBOARD_KEY_6b=esc # escape + KEYBOARD_KEY_6d=right # right on d-pad + KEYBOARD_KEY_6e=left # left on d-pad + KEYBOARD_KEY_71=up # up on d-pad + KEYBOARD_KEY_6f=down # down on d-pad + KEYBOARD_KEY_69=enter # enter on d-pad + +# ThinkPad X41 Tablet +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnIBM*:pn18666TU:pvr* + KEYBOARD_KEY_6c=direction # rotate + KEYBOARD_KEY_68=leftmeta # toolbox + KEYBOARD_KEY_6b=esc # escape + KEYBOARD_KEY_69=enter # enter on d-pad + +# IdeaPad +evdev:name:Ideapad extra buttons:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn* + KEYBOARD_KEY_0d=rfkill # airplane mode switch (toggle all wireless devices) + KEYBOARD_KEY_08=f20 # micmute + KEYBOARD_KEY_42=f23 + KEYBOARD_KEY_43=f22 + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*Y550*:pvr* + KEYBOARD_KEY_95=media + KEYBOARD_KEY_a3=play + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*IdeaPad*U300s*:pvr* + KEYBOARD_KEY_f1=f21 + KEYBOARD_KEY_ce=f20 # micmute + +evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*IdeaPad*Z370*:pvr* + KEYBOARD_KEY_a0=!mute + KEYBOARD_KEY_ae=!volumedown + KEYBOARD_KEY_b0=!volumeup + +# Lenovo Y50-70 +evdev:atkbd:dmi:bvn*:bvr*:svnLENOVO*:pn*20378*:pvr* + KEYBOARD_KEY_f3=f21 # Fn+F6 (toggle touchpad) + +# V480 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn*Lenovo*V480*:pvr* + KEYBOARD_KEY_f1=f21 + +# Lenovo ThinkCentre M800z/M820z/M920z AIO machines +# key_scancode 00 is KEY_MICMUTE +evdev:name:Microphone Mute Button:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn* + KEYBOARD_KEY_00=f20 + +# enhanced USB keyboard +evdev:input:b0003v04B3p301B* + KEYBOARD_KEY_90001=prog1 # ThinkVantage + KEYBOARD_KEY_90002=screenlock + KEYBOARD_KEY_90003=file + KEYBOARD_KEY_90004=wordprocessor + KEYBOARD_KEY_90005=spreadsheet + KEYBOARD_KEY_90006=calc + KEYBOARD_KEY_90007=mail + KEYBOARD_KEY_90008=www + + +########################################################### +# Logitech +########################################################### + +# 27MHz wireless keyboards, these all have a PID of 00?? and all send c10xx +# logitech custom consumer usage-page codes. The mappings below are the most +# common, but some mapping may differ, especially the Fn F1-F12 mappings +evdev:input:b0003v046Dp00* + KEYBOARD_KEY_c0183=media # HUT:config, kbd:Media/Music player button + KEYBOARD_KEY_c1001=chat # Messenger button + KEYBOARD_KEY_c1002=camera # Webcam button + KEYBOARD_KEY_c1003=audio # Music Browser button + KEYBOARD_KEY_c1004=video # Video Browser button + KEYBOARD_KEY_c1005=images # Image Browser button + KEYBOARD_KEY_c100a=documents # Document Browser button + KEYBOARD_KEY_c100b=rewind # Rewind button + KEYBOARD_KEY_c100c=fastforward # Fast Forward button + KEYBOARD_KEY_c100f=f14 # Track 1 button → f14 → XF86Launch5 + KEYBOARD_KEY_c1010=f15 # Track 2 button → f15 → XF86Launch6 + KEYBOARD_KEY_c1011=channeldown # Playlist back button + KEYBOARD_KEY_c1012=channelup # Playlist advance button + KEYBOARD_KEY_c1013=camera # Webcam button + KEYBOARD_KEY_c1014=coffee # Status button + KEYBOARD_KEY_c1015=record # Record symbol button + KEYBOARD_KEY_c1016=sound # Flame/CD burning → sound → XF86AudioPreset + KEYBOARD_KEY_c1017=ejectcd # Eject button + KEYBOARD_KEY_c1018=config # Remote-control ico + KEYBOARD_KEY_c1019=f14 # Preset 1 → f14 → XF86Launch5 + KEYBOARD_KEY_c101a=f15 # Preset 2 → f15 → XF86Launch6 + KEYBOARD_KEY_c101b=f16 # Preset 3 → f16 → XF86Launch7 + KEYBOARD_KEY_c101c=cyclewindows # 2 overlapping windows icon + KEYBOARD_KEY_c101f=zoomout # zoom - button / - side of zoomrocker + KEYBOARD_KEY_c1020=zoomin # zoom + button / + side off zoom rocker + KEYBOARD_KEY_c1021=zoomreset # 100% symbol on kbd left side + KEYBOARD_KEY_c1023=close # [x] symbol on kbd left side + KEYBOARD_KEY_c1027=menu # Hamburger menu icon + KEYBOARD_KEY_c1028=angle # Rotate button + KEYBOARD_KEY_c1029=shuffle # Shuffle button + KEYBOARD_KEY_c102a=back # Back button + KEYBOARD_KEY_c102b=cyclewindows # Empty window icon + KEYBOARD_KEY_c102d=www # www text + magnifierglass icon + KEYBOARD_KEY_c1031=connect # Pickup phone button → connect → XF86Go + KEYBOARD_KEY_c1032=cancel # Hangup phone button → cancel → Cancel + KEYBOARD_KEY_c1041=help # Help text or icon (Fn + F1) + KEYBOARD_KEY_c1042=wordprocessor # Word icon (Fn + F2) + KEYBOARD_KEY_c1043=spreadsheet # Excel icon (Fn + F3) + KEYBOARD_KEY_c1044=presentation # Presentation icon (Fn + F4) + KEYBOARD_KEY_c1045=undo # Undo Icon (Fn + F5) + KEYBOARD_KEY_c1046=redo # Redo Icon (Fn + F6) + KEYBOARD_KEY_c1047=print # Printer Icon (Fn + F7) + KEYBOARD_KEY_c1048=save # Floppy Icon (Fn + F8) + KEYBOARD_KEY_c1049=prog1 # Smartkey A (Fn + F9) → XF86Launch1 + KEYBOARD_KEY_c104a=prog2 # Smartkey B (Fn + F10) → XF86Launch2 + KEYBOARD_KEY_c104b=prog3 # Smartkey C (Fn + F11) → XF86Launch3 + KEYBOARD_KEY_c104c=prog4 # Smartkey D (Fn + F12) → XF86Launch4 + +# Cordless Access Keyboard (27 MHz, modelnumber Y-RH35) +evdev:input:b0003v046Dp0042* + KEYBOARD_KEY_c1041=new + KEYBOARD_KEY_c1042=reply + KEYBOARD_KEY_c1043=forward + KEYBOARD_KEY_c1044=send + KEYBOARD_KEY_c1045=previoussong + KEYBOARD_KEY_c1046=nextsong + KEYBOARD_KEY_c1047=playpause + KEYBOARD_KEY_c1048=stopcd + KEYBOARD_KEY_c1049=file + KEYBOARD_KEY_c104a=documents + KEYBOARD_KEY_c104b=images + KEYBOARD_KEY_c104c=audio + +# "Cordless Rechargeable Desktop" keyboard (27 MHz, modelnumber Y-RK49) +evdev:input:b0003v046Dp0045* + KEYBOARD_KEY_c1041=new + KEYBOARD_KEY_c1042=reply + KEYBOARD_KEY_c1043=forward + KEYBOARD_KEY_c1044=send + KEYBOARD_KEY_c1049=file + KEYBOARD_KEY_c104a=documents + KEYBOARD_KEY_c104b=images + KEYBOARD_KEY_c104c=audio + +# S510 keyboard (27 MHz, modelnumber Y-RAK73) +evdev:input:b0003v046Dp0056* + KEYBOARD_KEY_c1041=battery # Battery icon (Fn + F1) + +# MX3000 keyboard (27 MHz, modelnumber Y-RAM74) +# We ignore the scroll up / down keypress events since these buttons also +# generate scroll-wheel events and we do not want to generate duplicate events +# Note if the "Special Button Function" in the HID++ features register gets +# cleared then the scroll-wheel events for these buttons go away and then +# tilting the scrollwheel left/right starts sending c1022 / c1024 events +evdev:input:b0003v046Dp0057* + KEYBOARD_KEY_c1041=battery # Battery icon (Fn + F1) + +#KEYBOARD_KEY_c101d=scrolldown # Button below scrollwheel (see note above) +#KEYBOARD_KEY_c101e=scrollup # Button above scrollwheel (see note above) +#KEYBOARD_KEY_c1022=scrollleft # Left click on scroll-wheel (see note above) +#KEYBOARD_KEY_c1024=scrollright # Right click on scroll-wheel (see note above) + +# MX3200 keyboard (27 MHz, modelnumber Y-RAV80) +evdev:input:b0003v046Dp005C* + KEYBOARD_KEY_c1001=phone # VOIP button + KEYBOARD_KEY_c1016=record # Record button + KEYBOARD_KEY_c1041=wordprocessor # Word icon (Fn + F1) + KEYBOARD_KEY_c1042=spreadsheet # Excel icon (Fn + F2) + KEYBOARD_KEY_c1043=calendar # Calendar icon (Fn + F3) + KEYBOARD_KEY_c1044=documents # My Documents icon (Fn + F4) + KEYBOARD_KEY_c1045=prog1 # Smartkey A (Fn + F5) → XF86Launch1 + KEYBOARD_KEY_c1046=prog2 # Smartkey B (Fn + F6) → XF86Launch2 + KEYBOARD_KEY_c1047=prog3 # Smartkey C (Fn + F7) → XF86Launch3 + KEYBOARD_KEY_c1048=prog4 # Smartkey D (Fn + F8) → XF86Launch4 + +# EX100 keyboard (27 MHz, modelnumber Y-RBH94) +evdev:input:b0003v046Dp0065* + KEYBOARD_KEY_c104b=battery # Battery icon (Fn + F11) + KEYBOARD_KEY_c104c=ejectcd # Eject icon (Fn + F12) + +# S520 keyboard (27 MHz, modelnumber Y-RBA97) +# Note this one uses non-standard codes for FN + F9 - Fn + F12? +evdev:input:b0003v046Dp0066* + KEYBOARD_KEY_c100e=prog4 # Smartkey D (Fn + F12) → XF86Launch4 + KEYBOARD_KEY_c1019=prog1 # Smartkey A (Fn + F9) → XF86Launch1 + KEYBOARD_KEY_c101a=prog2 # Smartkey B (Fn + F10) → XF86Launch2 + KEYBOARD_KEY_c101b=prog3 # Smartkey C (Fn + F11) → XF86Launch3 + KEYBOARD_KEY_c1041=wordprocessor # Word icon (Fn + F1) + KEYBOARD_KEY_c1042=spreadsheet # Excel icon (Fn + F2) + KEYBOARD_KEY_c1043=presentation # Presentation icon (Fn + F3) + KEYBOARD_KEY_c1044=calendar # Calendar icon (Fn + F4) + KEYBOARD_KEY_c1045=homepage # Home icon (Fn + F5) + KEYBOARD_KEY_c1046=email # Letter icon (Fn + F6) + KEYBOARD_KEY_c1047=search # Magnifying glass icon (Fn + F7) + KEYBOARD_KEY_c1048=config # Window with gear icon (Fn + F8) + KEYBOARD_KEY_c106f=battery # Battery icon + +# S510 remote control (27 MHz) +evdev:input:b0003v046Dp00FE* + KEYBOARD_KEY_c1018=media # Media button + +# MX5000 keyboard (HID proxy mode and bluetooth matches) +# The 4 buttons below the LCD send codes 0xc100c - 0xc100f. They only send +# these codes when the LCD is displaying text send to it. These codes are +# directly consumed by recent versions of lcdproc when it is driving the LCD, +# so these codes should not be mapped +evdev:input:b0003v046DpB305* +evdev:input:b0005v046DpB305* + KEYBOARD_KEY_c0230=zoomreset # HUT says fullscreen, kbd says 100% + KEYBOARD_KEY_c1004=send # Send and receive / sync button + KEYBOARD_KEY_c1006=coffee # Status (online/away) button + KEYBOARD_KEY_c1007=camera # Webcam button + KEYBOARD_KEY_c1038=prog1 # Smartkey A → XF86Launch1 + KEYBOARD_KEY_c1039=prog2 # Smartkey B → XF86Launch2 + KEYBOARD_KEY_c103a=prog3 # Smartkey C → XF86Launch3 + KEYBOARD_KEY_c103b=prog4 # Smartkey D → XF86Launch4 + +# MX5500 keyboard (HID proxy mode and bluetooth matches) +evdev:input:b0003v046DpB30B* +evdev:input:b0005v046DpB30B* + KEYBOARD_KEY_c0183=media # HUT says consumer control configuration, kbd says Media Center + KEYBOARD_KEY_c100e=images # Camera icon, "Photo Gallery" + KEYBOARD_KEY_c100f=config # Window with gear icon + KEYBOARD_KEY_c1038=prog1 # Smartkey A → XF86Launch1 + KEYBOARD_KEY_c1039=prog2 # Smartkey B → XF86Launch2 + KEYBOARD_KEY_c103a=prog3 # Smartkey C → XF86Launch3 + KEYBOARD_KEY_c103b=prog4 # Smartkey D → XF86Launch4 + +# iTouch +evdev:input:b0003v046DpC308* + KEYBOARD_KEY_90001=shop # Shopping + KEYBOARD_KEY_90002=config # iTouch + KEYBOARD_KEY_90003=finance # Finance + KEYBOARD_KEY_90004=prog1 # My Sites + KEYBOARD_KEY_90005=prog2 # Community + KEYBOARD_KEY_c0183=media # Media + +# Cordless Desktop S510 +evdev:input:b0003v046DpC50C* + KEYBOARD_KEY_d4=up # zoomin + KEYBOARD_KEY_cc=down # zoomout + +# Wave cordless +evdev:input:b0003v046DpC317* + KEYBOARD_KEY_9001c=scale # expo + KEYBOARD_KEY_9001f=down # zoomout + KEYBOARD_KEY_90020=up # zoomin + KEYBOARD_KEY_9003d=prog1 # gadget + KEYBOARD_KEY_90005=camera + KEYBOARD_KEY_90018=media + KEYBOARD_KEY_90041=wordprocessor + KEYBOARD_KEY_90042=spreadsheet + KEYBOARD_KEY_90043=calendar + KEYBOARD_KEY_90044=prog2 # fn+f4 (program a) + KEYBOARD_KEY_90045=prog3 # fn+f5 (program b) + KEYBOARD_KEY_90046=prog4 # fn+f6 (program c) + KEYBOARD_KEY_90048=messenger # fn+f8 (msn messenger) + KEYBOARD_KEY_9002d=search # fn+f10 (search www) + KEYBOARD_KEY_9004b=find # fn+f11 (search pc) + KEYBOARD_KEY_9004c=ejectclosecd + +# Wave cordless +evdev:input:b0003v046DpC517* + KEYBOARD_KEY_c101f=down # zoomout + KEYBOARD_KEY_c1020=up # zoomin + KEYBOARD_KEY_c1005=camera + KEYBOARD_KEY_c0183=media + KEYBOARD_KEY_c1041=wordprocessor + KEYBOARD_KEY_c1042=spreadsheet + KEYBOARD_KEY_c1043=calendar + KEYBOARD_KEY_c1044=prog2 # fn+f4 (program a) + KEYBOARD_KEY_c1045=prog3 # fn+f5 (program b) + KEYBOARD_KEY_c1046=prog4 # fn+f6 (program c) + KEYBOARD_KEY_c1048=messenger # fn+f8 (msn messenger) + KEYBOARD_KEY_c104a=find # fn+f10 (search www) + KEYBOARD_KEY_c104c=ejectclosecd + +# Cordless Wave Pro +evdev:input:b0003v046DpC529* + KEYBOARD_KEY_0c01b6=camera + KEYBOARD_KEY_0c0183=media + KEYBOARD_KEY_0c0184=wordprocessor + KEYBOARD_KEY_0c0186=spreadsheet + KEYBOARD_KEY_0c018e=calendar + KEYBOARD_KEY_0c0223=homepage + KEYBOARD_KEY_0c01bc=messenger + KEYBOARD_KEY_0c018a=mail + KEYBOARD_KEY_0c0221=search + KEYBOARD_KEY_0c00b8=ejectcd + KEYBOARD_KEY_0c022d=up # zoomin + KEYBOARD_KEY_0c022e=down # zoomout + +# Logitech Presenter R400 +evdev:input:b0003v046DpC52D* + KEYBOARD_KEY_070029=presentation + KEYBOARD_KEY_07003e=presentation + KEYBOARD_KEY_070037=displaytoggle + +# Internet Navigator +evdev:input:b0003v046DpC309* + KEYBOARD_KEY_90001=chat # Messenger/SMS + KEYBOARD_KEY_90002=camera # webcam + KEYBOARD_KEY_90003=prog1 # iTouch + KEYBOARD_KEY_90004=shop # Shopping + KEYBOARD_KEY_c0201=new # New (F1) + KEYBOARD_KEY_c0289=reply # Reply mail (F2) + KEYBOARD_KEY_c028b=forwardmail # Forward mail (F3) + KEYBOARD_KEY_c028c=send # Send (F4) + KEYBOARD_KEY_c021a=undo # Undo (F5) + KEYBOARD_KEY_c0279=redo # Redo (F6) + KEYBOARD_KEY_c0208=print # Print (F7) + KEYBOARD_KEY_c0207=save # Save (F8) + KEYBOARD_KEY_c0194=file # My Computer (F9) + KEYBOARD_KEY_c01a7=documents # My Documents (F10) + KEYBOARD_KEY_c01b6=images # My Pictures (F11) + KEYBOARD_KEY_c01b7=audio # My Music (F12) + + +########################################################### +# Maxdata +########################################################### + +# Pro 7000 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMAXDATA:pnPro*7000*:pvr* + KEYBOARD_KEY_97=prog2 + KEYBOARD_KEY_9f=prog1 + KEYBOARD_KEY_a0=mute # Fn+F5 + KEYBOARD_KEY_82=www + KEYBOARD_KEY_ec=email + KEYBOARD_KEY_ae=volumedown # Fn+Down + KEYBOARD_KEY_b0=volumeup # Fn+Up + KEYBOARD_KEY_df=suspend # Fn+F2 + KEYBOARD_KEY_f5=help + +########################################################### +# Medion +########################################################### + +# Akoya +evdev:atkbd:dmi:bvn*:bvr*:svnMEDION*:pnS3409*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:svnMedion*:pnAkoya*:pvr* + KEYBOARD_KEY_a0=!mute + KEYBOARD_KEY_ae=!volumedown + KEYBOARD_KEY_b0=!volumeup + KEYBOARD_KEY_19=!p + KEYBOARD_KEY_df=sleep + +# FID2060 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMEDION*:pn*FID2060*:pvr* + KEYBOARD_KEY_6b=channeldown # Thottle Down + KEYBOARD_KEY_6d=channelup # Thottle Up + +# NB-A555 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMEDIONNB:pnA555*:pvr* + KEYBOARD_KEY_63=www # N button + KEYBOARD_KEY_66=prog1 # link 1 button + KEYBOARD_KEY_67=email # envelope button + KEYBOARD_KEY_69=prog2 # link 2 button + +# Erazer +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMedion*:pnErazer*:pvr* + KEYBOARD_KEY_a0=!mute + KEYBOARD_KEY_ae=!volumedown + KEYBOARD_KEY_b0=!volumeup + +########################################################### +# Microsoft +########################################################### + +# Microsoft Natural Ergonomic Keyboard 4000 +evdev:input:b0003v045Ep00DB* + KEYBOARD_KEY_c022d=up # zoomin + KEYBOARD_KEY_c022e=down # zoomout + +# Microsoft (Razer produced) Reclusa keyboard +evdev:input:b0003v1532p0200* + KEYBOARD_KEY_c01c9=shuffle + KEYBOARD_KEY_c01ca=up # zoomin + KEYBOARD_KEY_c01cb=down # zoomout + +########################################################### +# Micro Star +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn* + KEYBOARD_KEY_a0=mute # Fn+F9 + KEYBOARD_KEY_ae=volumedown # Fn+F7 + KEYBOARD_KEY_b0=volumeup # Fn+F8 + KEYBOARD_KEY_b2=www # e button + KEYBOARD_KEY_df=sleep # Fn+F12 + KEYBOARD_KEY_e2=bluetooth # satellite dish2 + KEYBOARD_KEY_e4=f21 # Fn+F3 Touchpad disable + KEYBOARD_KEY_ec=email # envelope button + KEYBOARD_KEY_ee=camera # Fn+F6 camera disable + KEYBOARD_KEY_f6=wlan # satellite dish1 + KEYBOARD_KEY_f7=brightnessdown # Fn+F4 + KEYBOARD_KEY_f8=brightnessup # Fn+F5 + KEYBOARD_KEY_f9=search + +# +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnGE60*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnGE70*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*:pvr* + KEYBOARD_KEY_c2=ejectcd + +# some MSI models generate ACPI/input events on the LNXVIDEO input devices, +# plus some extra synthesized ones on atkbd as an echo of actually changing the +# brightness; so ignore those atkbd ones, to avoid loops +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*U-100*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*U100*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pn*N033:* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*VR420*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMicro-Star*:pn*PR200*:pvr* + KEYBOARD_KEY_f7=reserved + KEYBOARD_KEY_f8=reserved + +# MSI Wind U90/U100 generates separate touchpad on/off keycodes so ignore touchpad toggle keycode +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMICRO-STAR*:pnU90/U100:* + KEYBOARD_KEY_e4=reserved + +########################################################### +# MSI +########################################################### + +evdev:name:MSI Laptop hotkeys:dmi:bvn*:bvr*:bd*:svn*:pnM[iI][cC][rR][oO]-S[tT][aA][rR]*:pvr* + KEYBOARD_KEY_0213=f22 + KEYBOARD_KEY_0214=f23 + +########################################################### +# OLPC +########################################################### + +# XO-1 and XO-1.5 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOLPC:pnXO:* +# XO-1.75 and XO-1.4 (sp/ is the Security Processor) +evdev:name:AT Translated Set 2 keyboard:phys:sp/serio*/input*:ev:120013:* + KEYBOARD_LED_CAPSLOCK=0 + KEYBOARD_LED_NUMLOCK=0 + KEYBOARD_KEY_59=fn + KEYBOARD_KEY_81=fn_esc + KEYBOARD_KEY_f9=camera + KEYBOARD_KEY_f8=sound # Fn+CAMERA = Mic + KEYBOARD_KEY_43=brightnessdown + KEYBOARD_KEY_44=brightnessup + KEYBOARD_KEY_57=volumedown + KEYBOARD_KEY_58=volumeup + KEYBOARD_KEY_bb=f1 + KEYBOARD_KEY_bc=f2 + KEYBOARD_KEY_bd=f3 + KEYBOARD_KEY_be=f4 + KEYBOARD_KEY_bf=f5 + KEYBOARD_KEY_c0=f6 + KEYBOARD_KEY_c1=f7 + KEYBOARD_KEY_c2=f8 + KEYBOARD_KEY_c3=f9 + KEYBOARD_KEY_c4=f10 + KEYBOARD_KEY_d8=f12 + KEYBOARD_KEY_f7=f13 + KEYBOARD_KEY_f6=f14 + KEYBOARD_KEY_f5=f15 + KEYBOARD_KEY_f4=f16 + KEYBOARD_KEY_f3=f17 + KEYBOARD_KEY_f2=f18 + KEYBOARD_KEY_f1=f19 + KEYBOARD_KEY_f0=f20 # micmute + KEYBOARD_KEY_ef=f21 + KEYBOARD_KEY_ee=chat + KEYBOARD_KEY_e4=chat + KEYBOARD_KEY_dd=menu # Frame + KEYBOARD_KEY_da=prog1 # Fn+Frame + KEYBOARD_KEY_d3=delete + KEYBOARD_KEY_d2=insert + KEYBOARD_KEY_c9=pageup + KEYBOARD_KEY_d1=pagedown + KEYBOARD_KEY_c7=home + KEYBOARD_KEY_cf=end + KEYBOARD_KEY_73=hp + KEYBOARD_KEY_7e=hp + KEYBOARD_KEY_db=leftmeta # left grab + KEYBOARD_KEY_dc=rightmeta # right grab + KEYBOARD_KEY_85=rightmeta # Right grab releases on a different scancode + KEYBOARD_KEY_d6=kbdillumtoggle # Fn+Space + KEYBOARD_KEY_69=rotate_display + KEYBOARD_KEY_65=btn_dpad_up + KEYBOARD_KEY_66=btn_dpad_down + KEYBOARD_KEY_67=btn_dpad_left + KEYBOARD_KEY_68=btn_dpad_right + KEYBOARD_KEY_e5=btn_north + KEYBOARD_KEY_e6=btn_south + KEYBOARD_KEY_e7=btn_west + KEYBOARD_KEY_e8=btn_east + +########################################################### +# Onkyo +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnONKYO*CORPORATION:pnONKYOPC:* + KEYBOARD_KEY_a0=mute # Fn+D + KEYBOARD_KEY_ae=volumedown # Fn+F + KEYBOARD_KEY_b0=volumeup # Fn+G + KEYBOARD_KEY_df=sleep # Fn+W + KEYBOARD_KEY_e0=bluetooth # Fn+H + KEYBOARD_KEY_e2=cyclewindows # Fn+Esc + KEYBOARD_KEY_ee=battery # Fn+Q + KEYBOARD_KEY_f0=media # Fn+R + KEYBOARD_KEY_f5=switchvideomode # Fn+E + KEYBOARD_KEY_f6=camera # Fn+T + KEYBOARD_KEY_f7=f21 # Fn+Y (touchpad toggle) + KEYBOARD_KEY_f8=brightnessup # Fn+S + KEYBOARD_KEY_f9=brightnessdown # Fn+A + KEYBOARD_KEY_fb=wlan # Fn+J + +########################################################### +# OQO +########################################################### + +# Model 2 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnOQO*Inc.*:pnOQO*Model*2*:pvr* + KEYBOARD_KEY_8e=wlan + KEYBOARD_KEY_f0=switchvideomode + KEYBOARD_KEY_f1=mute + KEYBOARD_KEY_f2=volumedown + KEYBOARD_KEY_f3=volumeup + +########################################################### +# Plantronics +########################################################### + +# Plantronics .Audio 626 DSP +evdev:input:b0003v047FpC006* + KEYBOARD_KEY_b002f=f20 # Microphone mute button; should be micmute + +########################################################### +# Purism +########################################################### + +# Purism Librem 13 V2 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v2*:pvr* + KEYBOARD_KEY_56=backslash + +# Purism Librem 13 V3 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v3*:pvr* + KEYBOARD_KEY_56=backslash + +# Purism Librem 13 V4 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPurism*:pn*Librem13v4*:pvr* + KEYBOARD_KEY_56=backslash + +########################################################### +# Quanta +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*:pn*:pvr*:rvnQuanta:rn30B7:rvr65.2B:* + KEYBOARD_KEY_88=media # "quick play + +########################################################### +# Samsung +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn* + KEYBOARD_KEY_74=prog1 # User key + KEYBOARD_KEY_75=www + KEYBOARD_KEY_78=mail + KEYBOARD_KEY_82=!switchvideomode # Fn+F4 CRT/LCD (high keycode: "displaytoggle") + KEYBOARD_KEY_83=!battery # Fn+F2 + KEYBOARD_KEY_84=!prog1 # Fn+F5 backlight on/off + KEYBOARD_KEY_86=!wlan # Fn+F9 + KEYBOARD_KEY_88=!brightnessup # Fn+Up + KEYBOARD_KEY_89=!brightnessdown # Fn+Down + KEYBOARD_KEY_b1=!prog2 # Fn+F7 run Samsung Magic Doctor (keypressed event is generated twice) + KEYBOARD_KEY_b3=!prog3 # Fn+F8 switch power mode (battery/dynamic/performance) + KEYBOARD_KEY_b4=!wlan # Fn+F9 (X60P) + KEYBOARD_KEY_c5=!prog3 # Fn+F8 switch power mode (battery/dynamic/performance) + KEYBOARD_KEY_d5=!wlan # Fn+F12 wlan/airplane switch + KEYBOARD_KEY_f7=!f22 # Fn+F10 Touchpad on + KEYBOARD_KEY_f9=!f23 # Fn+F10 Touchpad off + +# Series 3 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*300E[457]*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*200E[45]*:pvr* + KEYBOARD_KEY_ce=! # Fn+F1 launch control setting + +# Series 5 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*530U*:pvr* + KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings + KEYBOARD_KEY_a8=! # Fn Lock - Function lock on + KEYBOARD_KEY_a9=! # Fn Lock - Function lock off + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*550P*:pvr* + KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings + KEYBOARD_KEY_a8=! # Fn Lock - Function lock on + KEYBOARD_KEY_a9=! # Fn Lock - Function lock off + +# Series 7 / 9 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*350V*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*670Z*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700Z*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700G*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*900X[34]*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*940X3G*:pvr* + KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings + KEYBOARD_KEY_a0=!mute # Fn+F6 mute + KEYBOARD_KEY_ae=!volumedown # Fn+F7 + KEYBOARD_KEY_b0=!volumeup # Fn+F8 + KEYBOARD_KEY_97=!kbdillumdown # Fn+F9 keyboard backlight down + KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up + KEYBOARD_KEY_b3=!prog3 # Fn+F11 fan/cooling mode changer + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*900X[34][AB]*:pvr* + KEYBOARD_KEY_ce=! # Fn+F8 keyboard backlight up + KEYBOARD_KEY_8d=! # Fn+F7 keyboard backlight down + KEYBOARD_KEY_96=! # Fn+F1 performance mode (?) + KEYBOARD_KEY_97=! # Fn+F12 Wi-Fi toggle + KEYBOARD_KEY_d5=! # Fn+F6 battery life extender + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*90X3A*:pvr* + KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings + KEYBOARD_KEY_8d=!prog3 # Fn+F6 performance mode + KEYBOARD_KEY_97=!kbdillumdown # Fn+F7 keyboard backlight down + KEYBOARD_KEY_96=!kbdillumup # Fn+F8 keyboard backlight up + KEYBOARD_KEY_d5=!wlan # Fn+F12 Wi-Fi toggle + +# Series 7 Ultra +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*7[34]0U3E*:pvr* + KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings + KEYBOARD_KEY_97=!kbdillumdown # Fn+F9 keyboard backlight down + KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up + KEYBOARD_KEY_b3=!prog3 # Fn+F11 fan/cooling mode changer + KEYBOARD_KEY_d5=!wlan # Fn+F12 wlan/airplane switch + +# ATIV Book 6 / 8 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*[68][78]0Z*:pvr* + KEYBOARD_KEY_ce=!prog1 # Fn+F1 launch settings + KEYBOARD_KEY_96=!kbdillumup # Fn+F10 keyboard backlight up + KEYBOARD_KEY_97=!kbdillumdown # Fn+F9 keyboard backlight down + +# SQ1US +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pnSQ1US:pvr* + KEYBOARD_KEY_d4=menu + KEYBOARD_KEY_d8=f1 + KEYBOARD_KEY_d9=f10 + KEYBOARD_KEY_d6=f3 + KEYBOARD_KEY_d7=f9 + KEYBOARD_KEY_e4=f5 + KEYBOARD_KEY_ee=f11 + +# SX20S +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*SX20S*:pvr* + KEYBOARD_KEY_74=mute + KEYBOARD_KEY_75=mute + KEYBOARD_KEY_77=f22 # Touchpad on + KEYBOARD_KEY_79=f23 # Touchpad off + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svn[sS][aA][mM][sS][uU][nN][gG]*:pn*700T*:pvr* + KEYBOARD_KEY_ad=leftmeta + +########################################################### +# SONY +########################################################### + +# sony-laptop driver +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn* + KEYBOARD_KEY_06=mute # Fn+F2 + KEYBOARD_KEY_07=volumedown # Fn+F3 + KEYBOARD_KEY_08=volumeup # Fn+F4 + KEYBOARD_KEY_09=brightnessdown # Fn+F5 + KEYBOARD_KEY_0a=brightnessup # Fn+F6 + KEYBOARD_KEY_0b=switchvideomode # Fn+F7 + KEYBOARD_KEY_0e=zoom # Fn+F10 + KEYBOARD_KEY_10=suspend # Fn+F12 + +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-C1*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-K25*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-F[1-6]*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-FX*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-FRV*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-GR*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-TR*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-NV*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*PCG-Z*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pn*VGN-S360*:pvr* + KEYBOARD_KEY_06=battery + KEYBOARD_KEY_07=mute + +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-AR71*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-FW*:pvr* +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-Z21*:pvr* + KEYBOARD_KEY_00=brightnessdown # Fn+F5 + KEYBOARD_KEY_10=brightnessup # Fn+F6 + KEYBOARD_KEY_11=switchvideomode # Fn+F7 + KEYBOARD_KEY_12=down # zoomout + KEYBOARD_KEY_14=up # zoomin + KEYBOARD_KEY_15=suspend # Fn+F12 + KEYBOARD_KEY_17=prog1 + KEYBOARD_KEY_20=media + +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVGN-FW250*:pvr* + KEYBOARD_KEY_10=suspend # Fn+F12 + +evdev:name:Sony Vaio Keys:dmi:bvn*:bvr*:bd*:svnSony*:pnVPC*:pvr* + KEYBOARD_KEY_05=f21 # Fn+F1 -> KEY_F21 (The actual touchpad toggle) + KEYBOARD_KEY_0d=down # Fn+F9 zoomout + KEYBOARD_KEY_0e=up # Fn+F10 zoomin + +########################################################### +# System76 +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnSystem76*:pn* + KEYBOARD_KEY_f7=f21 # Touchpad toggle + KEYBOARD_KEY_f8=f21 # Touchpad toggle + +########################################################### +# T-bao +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnT-bao:pnTbookair:pvr* + KEYBOARD_KEY_76=f21 # Touchpad toggle + +########################################################### +# Toshiba +########################################################### + +# Satellite A100 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSATELLITE*A100:pvr* + KEYBOARD_KEY_a4=stopcd + KEYBOARD_KEY_b2=www + +# Satellite A110 +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*A110:pvr* + KEYBOARD_KEY_92=stop + KEYBOARD_KEY_93=www + KEYBOARD_KEY_94=media + KEYBOARD_KEY_9e=f22 # Touchpad on + KEYBOARD_KEY_9f=f23 # Touchpad off + KEYBOARD_KEY_b9=nextsong + KEYBOARD_KEY_d9=brightnessup + KEYBOARD_KEY_ee=screenlock + KEYBOARD_KEY_f4=previoussong + KEYBOARD_KEY_f7=playpause + +# Satellite M30X +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*M30X:pvr* + KEYBOARD_KEY_ef=brightnessdown + KEYBOARD_KEY_d9=brightnessup + KEYBOARD_KEY_ee=screenlock + KEYBOARD_KEY_93=media + KEYBOARD_KEY_9e=f22 # touchpad enable + KEYBOARD_KEY_9f=f23 # touchpad disable + +# Satellite P75-A +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*P75-A:pvr* + KEYBOARD_KEY_ef=brightnessdown + KEYBOARD_KEY_ee=brightnessup + KEYBOARD_KEY_a9=switchvideomode # switch display outputs + KEYBOARD_KEY_d4=wlan # RF Switch Off + +# Satellite U940 +evdev:name:Toshiba*input*device:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSATELLITEU940:pvr* + KEYBOARD_KEY_13c=brightnessdown + KEYBOARD_KEY_13d=brightnessup + KEYBOARD_KEY_13e=switchvideomode + KEYBOARD_KEY_13f=f21 # Touchpad toggle + +# Satellite P75-A7200 +evdev:name:Toshiba*input*device:dmi:bvn*:bvr*:bd*:svnTOSHIBA*:pnSatellite*P75-A:pvr* + KEYBOARD_KEY_13c=brightnessdown + KEYBOARD_KEY_13d=brightnessup + KEYBOARD_KEY_13e=switchvideomode + KEYBOARD_KEY_13f=f21 # Touchpad toggle + KEYBOARD_KEY_9e=wlan + +########################################################### +# VIA +########################################################### + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnVIA:pnK8N800:pvr* + KEYBOARD_KEY_81=prog1 + +########################################################### +# VIOS +########################################################### + +evdev:name:SIPODEV USB Composite Device:dmi:bvn*:bvr*:bd*:svnVIOS:pnLTH17:pvr* + KEYBOARD_KEY_70073=f21 # Touchpad toggle + +########################################################### +# Zepto +########################################################### + +# Znote +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnZepto:pnZnote:* + KEYBOARD_KEY_93=switchvideomode # Fn+F3 Toggle Video Output + KEYBOARD_KEY_95=brightnessdown # Fn+F4 Brightness Down + KEYBOARD_KEY_91=brightnessup # Fn+F5 Brightness Up + KEYBOARD_KEY_a5=f23 # Fn+F6 Disable Touchpad + KEYBOARD_KEY_a6=f22 # Fn+F6 Enable Touchpad + KEYBOARD_KEY_a7=bluetooth # Fn+F10 Enable Bluetooth + KEYBOARD_KEY_a9=bluetooth # Fn+F10 Disable Bluetooth + KEYBOARD_KEY_f1=wlan # RF Switch Off + KEYBOARD_KEY_f2=wlan # RF Switch On + KEYBOARD_KEY_f4=prog1 # P1 Button + KEYBOARD_KEY_f3=prog2 # P2 Button + KEYBOARD_KEY_a0=! # mute + KEYBOARD_KEY_ae=! # volume down + KEYBOARD_KEY_b0=! # volume up + +# Znote 6615WD +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnZepto:pnZnote*6615WD:* + KEYBOARD_KEY_a0=! # mute + KEYBOARD_KEY_ae=! # volume down + KEYBOARD_KEY_b0=! # volume up + +########################################## +# Ideazon +########################################## + +# Ideazon Zboard Merc +evdev:input:b0003v1038p0210* + KEYBOARD_KEY_c0227=q + KEYBOARD_KEY_c0223=w + KEYBOARD_KEY_c0221=e + KEYBOARD_KEY_c0224=a + KEYBOARD_KEY_c0226=s + KEYBOARD_KEY_c0225=d + KEYBOARD_KEY_c0192=tab + KEYBOARD_KEY_c018a=leftalt + KEYBOARD_KEY_c022a=r + KEYBOARD_KEY_c0183=f10 + KEYBOARD_KEY_70059=1 + KEYBOARD_KEY_7005a=2 + KEYBOARD_KEY_7005b=3 + KEYBOARD_KEY_7005c=4 + KEYBOARD_KEY_7005d=5 + KEYBOARD_KEY_7005e=6 + KEYBOARD_KEY_7005f=7 + KEYBOARD_KEY_70060=8 + KEYBOARD_KEY_70061=9 + KEYBOARD_KEY_70062=0 + KEYBOARD_KEY_70057=equal + KEYBOARD_KEY_70077=capslock + KEYBOARD_KEY_70054=leftshift + KEYBOARD_KEY_70063=leftctrl + KEYBOARD_KEY_7006b=t + KEYBOARD_KEY_70067=f + KEYBOARD_KEY_7006c=g + KEYBOARD_KEY_7006d=v + KEYBOARD_KEY_7006e=b + KEYBOARD_KEY_70074=p + KEYBOARD_KEY_7006f=c + KEYBOARD_KEY_70055=space + KEYBOARD_KEY_70076=f9 + KEYBOARD_KEY_70046=f11 + KEYBOARD_KEY_70079=f6 + +# Ideazon Zboard Fang +evdev:input:b0003v1038p0310* + KEYBOARD_KEY_70059=1 + KEYBOARD_KEY_7005b=3 + KEYBOARD_KEY_70040=equal + KEYBOARD_KEY_70042=l + KEYBOARD_KEY_7002b=tab + KEYBOARD_KEY_7005e=capslock + KEYBOARD_KEY_700e2=leftalt + KEYBOARD_KEY_700e1=leftshift + KEYBOARD_KEY_700e0=leftctrl + KEYBOARD_KEY_70038=z + KEYBOARD_KEY_7003e=t + KEYBOARD_KEY_70015=r + KEYBOARD_KEY_70010=g + KEYBOARD_KEY_70050=n + KEYBOARD_KEY_70030=f9 + KEYBOARD_KEY_7002f=f11 + KEYBOARD_KEY_70046=f6 + +########################################################### +# Other +########################################################### + +# Common Volume Keys +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFUJITSU*SIEMENS:pnAMILO*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnFOXCONN:pnQBOOK:* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMTC:pn*:pvrA0:* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnMio*Technology:pnN890:* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnPEGATRON*CORP.:pnSpring*Peak:* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSatellite*[uU][35]0[05]*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSATELLITE*[uU][35]0[05]*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnSatellite*Pro*[uU]300*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnTOSHIBA:pnEQUIUM [uU][35]0[05]*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnViooo*Corporation:pnPT17:* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHANNspree:pnSN10E100:* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGIGABYTE:pni1520M:* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnBenQ:pn*nScreen*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnBenQ:pnJoybook*Lite*:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnDIXONSP:pnDIXON*:pvr* + KEYBOARD_KEY_a0=! # mute + KEYBOARD_KEY_ae=! # volume down + KEYBOARD_KEY_b0=! # volume up + +######################### FIXED LAYOUT DEVICES ############################# +# This section lists devices for which only one keyboard layout is possible +# or useful such as devices which "type" expecting the user's keymap to match +# a particular one. For example, barcode readers and OTP keys. +# +# The layout must be an xkb compatible layout (defined with XKB_FIXED_LAYOUT), +# with an accompanying variant (defined with XKB_FIXED_VARIANT) if necessary. + +# Yubico Yubico Yubikey II" +evdev:input:b0003v1050p0010* +# Yubico Yubikey NEO OTP+CCID +evdev:input:b0003v1050p0111* +# Yubico Yubikey NEO OTP+U2F+CCID +evdev:input:b0003v1050p0116* +# OKE Electron Company USB barcode reader +evdev:input:b0003v05FEp1010* + XKB_FIXED_LAYOUT="us" + XKB_FIXED_VARIANT="" + +######################### LACK OF MODIFIER LEDS ############################ +# This section lists keyboard which do not have their own LEDs for some +# modifiers. Only Caps-Lock (KEYBOARD_LED_CAPSLOCK) and Num-Lock +# (KEYBOARD_LED_CAPSLOCK) are currently handled and need their values set +# to "0" to indicate the absence of LED. +# +# Presence of a LED is implicit when the property is absent. + +# Logitech K750 +evdev:input:b0003v046Dp4002* + KEYBOARD_LED_NUMLOCK=0 + KEYBOARD_LED_CAPSLOCK=0 + +# PFU Limited HHKB Professional JP +evdev:input:b0003v04FEp000D* + KEYBOARD_LED_NUMLOCK=0 + KEYBOARD_LED_CAPSLOCK=0 + +# Lenovo ThinkPad T430s +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT430s + KEYBOARD_LED_CAPSLOCK=0 + +# Lenovo ThinkPad T440s +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT440s + KEYBOARD_LED_CAPSLOCK=0 + +# Lenovo ThinkPad T450s +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT450s + KEYBOARD_LED_CAPSLOCK=0 + +# Lenovo ThinkPad T560s +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadT560s + KEYBOARD_LED_CAPSLOCK=0 + KEYBOARD_LED_NUMLOCK=0 + +# Lenovo ThinkPad X1 Carbon 3rd Gen +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd + KEYBOARD_LED_CAPSLOCK=0 + +######################### FIXED MODEL DEVICES ############################# +# This section lists devices which require special handling in their key +# code to keysym mapping by setting the xkb model. +# The model must be an xkb compatible model (defined with XKB_FIXED_MODEL). + +# Chromebooks +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnFalco:pvr* +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPeppy:pvr* + XKB_FIXED_MODEL="chromebook" diff --git a/hwdb.d/60-sensor.hwdb b/hwdb.d/60-sensor.hwdb new file mode 100644 index 00000000..931e760e --- /dev/null +++ b/hwdb.d/60-sensor.hwdb @@ -0,0 +1,628 @@ +# This file is part of systemd. +# +# The lookup keys are composed in: +# 60-sensor.rules +# +# Note: The format of the "sensor:" prefix match key is a +# contract between the rules file and the hardware data, it might +# change in later revisions to support more or better matches, it +# is not necessarily expected to be a stable ABI. +# +# Match string formats: +# sensor:modalias::dmi: +# +# The device modalias can be seen in the `modalias` file +# of the sensor parent, for example: +# cat /sys/`udevadm info -q path -n /dev/iio:device0`/../modalias +# +# The full DMI string of the running machine can be read from +# /sys/class/dmi/id/modalias +# That requires a kernel built with CONFIG_DMIID set, which is common. +# The full DMI string is not needed here and the meaning of individual parts +# can be seen in the source of the DMIID kernel module +# https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/firmware/dmi-id.c +# +# To add local entries, create a new file +# /etc/udev/hwdb.d/61-sensor-local.hwdb +# and add your rules there. To load the new rules execute (as root): +# systemd-hwdb update +# udevadm trigger -v -p DEVNAME=/dev/iio:deviceXXX +# where /dev/iio:deviceXXX is the device in question. +# +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of +# udevadm info --export-db +# +# For hwdb format and systemd behavior: +# https://www.freedesktop.org/software/systemd/man/hwdb.html +# +# Allowed properties are: +# ACCEL_MOUNT_MATRIX= +# +# where is a mount-matrix in the format specified in the IIO +# subsystem[1]. The default, when unset, is equivalent to: +# ACCEL_MOUNT_MATRIX=1, 0, 0; 0, 1, 0; 0, 0, 1 +# eg. the identity matrix. +# +# [1]: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=dfc57732ad38f93ae6232a3b4e64fd077383a0f1 +# +# Note for devices where the display (LCD panel) is mounted non upright +# in the device's casing, e.g. mounted upside-down or 90 degree rotated, +# the ACCEL_MOUNT_MATRIX should be such that the x and y axis matches the +# x and y axis of the display, not those of the casing, so that desktop +# environments using the accelerometer data for rotation will e.g. +# automatically flip their output for an upside-down display when the device +# is held upright. +# +# ACCEL_LOCATION= +# +# where is the location of the sensor. This value could be 'base' +# or 'display'. The default, when unset, is equivalent to: +# ACCEL_LOCATION=display +# +# Sort by brand, model + +######################################### +# Acer +######################################### +sensor:modalias:acpi:INVN6500*:dmi:*svn*Acer*:*pn*AspireSW5-011* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:INVN6500*:dmi:*svn*Acer*:*pn*AspireSW5-012* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:BMA250E*:dmi:*:svnAcer:pnIconiaW1-810:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +sensor:modalias:acpi:SMO8500:*:dmi:*Acer*:pnOneS1002* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, -1 + +sensor:modalias:acpi:KIOX0009*:dmi:*:svnAcer:pnOneS1003:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +sensor:modalias:acpi:BOSC0200*:dmi:*:svnAcer*:pnSwitchSW312-31:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:BOSC0200*:dmi:*svn*Acer*:*pn*Spin*SP111-33* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# Archos +######################################### +sensor:modalias:acpi:SMO8500*:dmi:*:svnARCHOS:pnARCHOS80Cesium:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +######################################### +# AsusTek +######################################### +sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100CHI* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pnT300CHI* + ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnT100TA* +sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pnT200TA* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pnTP201SA* +sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:pn*E205SA* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LA* +sensor:modalias:acpi:INVN6500*:dmi:*svn*ASUSTeK*:*pn*TP300LD* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:INVN6500*:dmi:*svnASUSTeK*:*pn*Q551LN* + ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:KXJ2109*:dmi:*:svnASUSTeK*:pnME176C* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LJ* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LAB* +sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP500LB* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:SMO8500*:dmi:*svn*ASUSTeK*:*pn*TP300LD* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:BOSC0200*:dmi:*svn*ASUSTeK*:*pn*TP412UA* + ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# Axxo +######################################### +sensor:modalias:acpi:SMO8500*:dmi:*:svnStandard:pnWCBT1011:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +######################################### +# Chuwi +######################################### + +# Chuwi Vi8 (CWI506) +sensor:modalias:acpi:BMA250E*:dmi:bvnINSYDECorp.:bvrCHUWI.D86JLBNR*:svnInsyde:pni86:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +# Chuwi Vi8 Plus (CWI519) +sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo:pnD2D3_Vi8A1:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +# Chuwi Vi10 (CWI505) +sensor:modalias:acpi:BMA250E*:dmi:bvnINSYDECorp.:bvrG1D_S165*:svnilife:pnS165:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +# Chuwi Hi8 Pro (CWI513) +sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo:pnX1D3_C806N:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +# Chuwi Hi10 (CWI515) +sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:*:svnDefaultstring:pnDefaultstring:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +# Chuwi Hi10 (CWI1515) +sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvrP02A_C106.60E:*:svnDefaultstring:pnDefaultstring:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +# Chuwi Hi10 Pro +sensor:modalias:acpi:BOSC0200*:dmi:*:svn*CHUWIINNOVATIONANDTECHNOLOGY*:pnHi10protablet:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +# Chuwi Hi12 +sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo:pnP02BD6_HI-122LP:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +# Chuwi Hi13 +sensor:modalias:acpi:KIOX000A*:dmi:*:svnChuwi*:pnHi13:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +# Chuwi HiBook +# Chuwi HiBook does not have its product name filled, so we +# match the entire dmi-alias, assuming that the use of a BOSC0200 + +# bios-version + bios-date combo is unique +sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/07/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnHampoo:rnCherryTrailCR:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring: +sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/28/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnHampoo:rnCherryTrailCR:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring: + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +# Chuwi CoreBook +# Chuwi CoreBook does not have its product name filled, so we +# match the entire dmi-alias +sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvrY13D_KB133.103:bd06/01/2018:svnHampoo:pnDefaultstring:pvrV100:rvnHampoo:rnY13D_KB133:rvrV100:cvnDefaultstring:ct9:cvrDefaultstring: + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +######################################### +# Connect +######################################### +sensor:modalias:acpi:KIOX000A*:dmi:*:svnConnect:pnTablet9:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# Cube +######################################### + +# Cube iWork8 Air +sensor:modalias:acpi:KIOX000A*:dmi:*:svncube:pni1-TF:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +# Cube i7 Stylus +sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni7Stylus:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +# Cube i7 Book (i16) +sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni16:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +# Cube i7 Stylus I8L Model +sensor:modalias:acpi:KIOX000A*:dmi:*:svnCube:pni8-L:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +# Cube iWork 10 Flagship +sensor:modalias:acpi:BOSC0200*:dmi:*:svnCube:pnI15-TC:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +# Cube iWork 11 Stylus +sensor:modalias:acpi:KIOX000A*:dmi:*:svncube:pni8-T:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# Cytrix (Mytrix) +######################################### +sensor:modalias:acpi:*KIOX000A*:dmi:*svn*CytrixTechnology:*pn*Complex11t* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +######################################### +# Dell +######################################### +sensor:modalias:platform:HID-SENSOR-200073:dmi:*svnDell*:pnVostro5581:* + ACCEL_LOCATION=base + +# Dell Venue 10 Pro 5055 +sensor:modalias:acpi:INVN6500*:dmi:*svnDell*:pnVenue10Pro5055* + ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# DEXP +######################################### +sensor:modalias:acpi:SMO8500*:dmi:*svn*DEXP*:*pn*DEXPOEM* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# DIGMA +######################################### + +# Digma CITI E203 +sensor:modalias:acpi:BOSC0200*:dmi:*:svnDigma:pnCITIE203ES2010EW:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# Endless +######################################### +sensor:modalias:acpi:ACCE0001*:dmi:*svnEndless*:*pnELT-NL3* + ACCEL_MOUNT_MATRIX=0, 1, 0; 0, 0, -1; -1, 0, 0 + +######################################### +# Eve Technology +######################################### +sensor:modalias:acpi:KIOX000A*:dmi:*:svnEVE*:pnEveV:* + ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# Google Chromebooks +######################################### +sensor:modalias:platform:cros-ec-accel:dmi:*:svnGOOGLE* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1 + +######################################### +# GP-electronic +######################################### +sensor:modalias:acpi:KIOX000A*:dmi:bvnINSYDECorp.:bvrBYT70A.YNCHENG.WIN.007:*:svnInsyde:pnT701:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# GPD +######################################### + +# GPD win (version 1, with the X5-Z8750 CPU) +# Note we match all dmi fields including the BIOS date checking for all known +# BIOS dates, since the strings are unfortunately very generic. +# Out of a sample set of 15 similar boards only the GPDwin has board_vendor=AMI +# and no other devices have both board_name *and* product_name set to +# "Default string". So combined with the sensor modalias and BIOS date this +# should be unique enough to identify the GPDwin +sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd10/25/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring: +sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd11/18/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring: +sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd12/23/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring: +sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd12/26/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring: +sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd02/21/2017:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring: +sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd03/20/2017:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring: +sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/25/2017:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring: + ACCEL_LOCATION=base + +######################################### +# HP +######################################### + +# Most HP Laptop using the lis3lv02d device have it in the base, +# mark these sensors as such. +sensor:modalias:platform:lis3lv02d:dmi:*svn*Hewlett-Packard*:* +sensor:modalias:platform:lis3lv02d:dmi:*svn*HP*:* + ACCEL_LOCATION=base + +sensor:modalias:acpi:SMO8500*:dmi:*:svnHewlett-Packard:pnHPStream7Tablet:* +sensor:modalias:acpi:SMO8500*:dmi:*:svnHewlett-Packard:pnHPStream8Tablet:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +# HP Pavillion X2 10-n000nd +sensor:modalias:i2c:bmc150_accel:dmi:*:svnHewlett-Packard:pnHPPavilionx2Detachable:*:rn815D:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# I.T.Works +######################################### + +# The I.T.Works TW891 2-in-1's DMI has the product-name field set, but not +# the sys-vendor field. This makes the DMI data a bit generic, so we match +# the whole dmi modalias, except for the BIOS version/date +sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:*:svnTobefilledbyO.E.M.:pnTW891:pvrTobefilledbyO.E.M.:rvnTobefilledbyO.E.M.:rnTW891:rvr1.0:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.: + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +# I.T.Works TW701 7" windows tablet, same hw as Trekstor ST70416-6 +sensor:modalias:acpi:BMA250*:dmi:*:bvritWORKS.G.WI71C.JGBMRB*:*:svnInsyde:pni71c:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# Irbis TW90 +######################################### +sensor:modalias:acpi:BOSC0200*:dmi:*:svnIRBIS:pnTW90:* + ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# iOTA 360 +######################################### +sensor:modalias:acpi:KIOX000A*:dmi:*svn*iOTA*:*pn*IOTA2210* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# Jumper +######################################### + +# EZpad mini 3 +sensor:modalias:acpi:BOSC0200*:dmi:bvnINSYDECorp.:bvrjumperx.T87.KFBNEE* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +# EZpad 6 Pro +sensor:modalias:acpi:BOSC0200*:dmi:*:svnJumper:pnEZpad:*:rvr.A006:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, 1 + +# EZpad Go +sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:*:svnjumper:pnEZpad:*:ct31:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +######################################### +# Kazam +######################################### +sensor:modalias:acpi:KIOX000A*:dmi:bvnINSYDECorp.:bvrVISION.I22K*:svnKAZAM:pnVISION:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# Lamina +######################################### +sensor:modalias:acpi:SMO8500*:dmi:*svnLamina*:*pnT701BR.SE* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +sensor:modalias:acpi:KIOX000A*:dmi:*svnLAMINA:pnT-1016BNORD* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# Lenovo +######################################### +sensor:modalias:acpi:NCPE0388*:dmi:*:rnLenovoYOGA510-14IKB:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, 1 + +sensor:modalias:acpi:BOSC0200:BOSC0200:dmi:*ThinkPadYoga11e3rdGen* + ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1 + +# Miix3-1030 +sensor:modalias:acpi:BMA250E*:dmi:bvnLENOVO:*:pvrLenovoMIIX3-1030:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +# Miix3-830 +sensor:modalias:acpi:SMO8500*:dmi:bvnLENOVO:*:pvrLenovoMIIX3-830:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +# IdeaPad D330 +sensor:modalias:acpi:BOSC0200*:dmi:*:svnLENOVO:pn81H3:* + ACCEL_MOUNT_MATRIX=0, 1, 0; -1, 0, 0; 0, 0, 1 + +# IdeaPad Miix 310 note this only is for BIOS version (bvr) 1HCN4?WW and 1HCN2?WW, which has +# a portrait LCD panel, versions with bvr 1HCN3?WW have a landscape panel +sensor:modalias:acpi:KIOX000A*:dmi:bvnLENOVO:bvr1HCN4?WW:*:svnLENOVO:pn80SG:* +sensor:modalias:acpi:KIOX000A*:dmi:bvnLENOVO:bvr1HCN2?WW:*:svnLENOVO:pn80SG:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +# IdeaPad Miix 320, different batches use a different sensor +sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80XF:* +sensor:modalias:acpi:SMO8840*:dmi:*:svnLENOVO:pn80XF:pvrLenovoMIIX320* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +# IdeaPad Miix 510, multiple expressions match different internal names +# pn80U1 matches IdeaPad Miix510-12ISK +sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80XE:* +sensor:modalias:acpi:*BOSC0200*:dmi:*:svnLENOVO*:pn80U1:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# LINX +######################################### + +# Linx 1010B +sensor:modalias:acpi:BOSC0200*:dmi:*:svnLINX*:pnLINX1010B:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, -1 + +# Linx 12X64 and 12V64 +sensor:modalias:acpi:KIOX000A*:dmi:*:svnLINX*:pnLINX12*64:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# Medion +######################################### +sensor:modalias:acpi:SMO8500*:dmi:*:svnMEDION:pnAkoyaE2212TMD99720:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +# Medion Akoya E2215T MD60198 +# Medion Akoya E3216 MD60900 +# Medion Akoya E3221 MD61237 +# Medion Akoya E2292 MD63390 +# Medion Akoya E2293 MD61130 +# Medion Akoya E2293 MD61144 +# Medion Akoya E3222 MD62450 +# and presumably all other Akoya Exxxx +sensor:modalias:acpi:KIOX010A*:dmi:*:svnMEDION:pnE*:* +# Medion Akoya E3222 MD62450 +sensor:modalias:acpi:KIOX010A*:dmi:*:svnMEDION:pnMEDION*:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# MSI +######################################### +sensor:modalias:acpi:SMO8500*:dmi:*:svnMicro-StarInternationalCo.,Ltd.:pnS100:* + ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# MYRIA +######################################### + +# MY8307 +sensor:modalias:acpi:BOSC0200*:dmi:*:svnCompletElectroServ:pnMY8307:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +######################################### +# Nuvision (TMax) +######################################### + +# Nuvision/TMAX 8" Windows signature edition. TM800W560L +sensor:modalias:acpi:KIOX000A*:dmi:*:svnTMAX:pnTM800W560L:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +# Nuvision Solo 10 Draw. TM101W610L +sensor:modalias:acpi:KIOX000A*:dmi:*:svnTMAX:pnTM101W610L:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# Onda +######################################### +sensor:modalias:acpi:BOSC0200*:dmi:*:svnONDA:pnV80PLUS:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:BMA250E*:dmi:bvnINSYDECorp.:bvrONDA.D89*:svnInsyde:pnONDATablet:* +sensor:modalias:acpi:BMA250E*:dmi:bvnINSYDECorp.:bvrONDA.D86*:svnONDA:pnV820wDualOS:* +sensor:modalias:acpi:BMA250E*:dmi:bvnINSYDECorp.:bvrONDA.W89*:svnInsyde:pnONDATablet:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +# Onda v975w, generic DMI strings, match entire dmi modalias inc. bios-date +sensor:modalias:acpi:SMO8500*:dmi:bvnAmericanMegatrendsInc.:bvr5.6.5:bd07/25/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.: + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# Peaq +######################################### +sensor:modalias:acpi:SMO8500*:dmi:*:svnPEAQ:pnPEAQPMMC1010MD99187:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +######################################### +# Pipo +######################################### +sensor:modalias:acpi:KIOX000A*:dmi:*:svnPIPO:pnW2S:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +# Pipo W4 +sensor:modalias:acpi:SMO8500*:dmi:*:bvrV8L_WIN32_CHIPHD_*_DX:*:rvnAMICorporation:rnAptioCRB:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# Ployer +######################################### +sensor:modalias:acpi:BMA250E*:dmi:*:svnShenzhenPLOYER*:pnMOMO7W:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +######################################### +# Point of View +######################################### + +# The Point of View TAB-P800W does not have its product name filled, so we +# match the entire dmi-alias, assuming that the use of a BMA250E + +# bios-version + bios-date combo is unique +sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1013:bd08/22/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.: +sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr3BAIR1014:bd10/24/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.: + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +# Point of View TAB-P1005W-232 (v2.0) +sensor:modalias:acpi:KIOX000A*:dmi:*:rvnPOV:rnI102A:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +# Point of View TAB-P1006W-232-3G (v1.0) +sensor:modalias:i2c:bmc150_accel:dmi:bvnINSYDECorp.:*:svnInsyde:pnBayTrail:*:rvn105B:rn0E57:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +######################################### +# Prowise +######################################### +sensor:modalias:acpi:SMO8500*:dmi:*:svnProwise:pnPT301:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +######################################### +# Schneider +######################################### + +# SCT101CTM +sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvrSCH12i.WJ210Z.KtBJRCA03* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +######################################### +# Teclast +######################################### +# Teclast F5 +sensor:modalias:acpi:KIOX010A*:dmi:*:svnTECLAST:pnF5:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +# Teclast F6 Pro (2 sensors) +sensor:modalias:acpi:KIOX010A*:dmi:*:svnTECLAST:pnF6Pro:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1 + ACCEL_LOCATION=display + +sensor:modalias:acpi:KIOX020A*:dmi:*:svnTECLAST:pnF6Pro:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + ACCEL_LOCATION=base + +# Teclast X80 Plus (H5C5) +sensor:modalias:acpi:KIOX000A*:dmi:*:svnTECLAST:pnDefaultstring:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +# Teclast X80 Pro (E3E6) +sensor:modalias:acpi:KIOX000A*:dmi:*:svnTECLAST:pnX80Pro:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +# Teclast X89 (E7ED), "tPAD" is too generic also match on BIOS date +sensor:modalias:acpi:SMO8500*:dmi:*bd12/19/2014:*:rvnTECLAST:rntPAD:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +# Teclast X98 Plus I (A5C6), generic DMI strings, match entire dmi modalias inc. bios-date +sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.011:bd11/03/2015:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnCherryTrailCR:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.: + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +# Teclast X98 Plus II +sensor:modalias:acpi:KIOX000A*:dmi:*:svnTECLAST:pnX98PlusII:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +######################################### +# Thundersoft +######################################### + +# Thundersoft TST168 tablet, generic DMI strings, match entire dmi modalias inc. bios-date +sensor:modalias:acpi:BMA250E*:dmi:bvnAmericanMegatrendsInc.:bvr5.6.5:bd04/15/2014:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnAMICorporation:rnAptioCRB:rvrTobefilledbyO.E.M.:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.: + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 + +######################################### +# Trekstor +######################################### +sensor:modalias:acpi:BMA250*:dmi:*:bvrTREK.G.WI71C.JGBMRBA*:*:svnInsyde:pnST70416-6:* +sensor:modalias:acpi:BMA250*:dmi:*:bvrTREK.G.WI71C.JGBMRBA*:*:svnTrekStor:pnSurfTabwintron7.0ST70416-6:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + +sensor:modalias:acpi:KIOX000A*:dmi:*:svnTREKSTOR*:pnPrimetabS11B:* +sensor:modalias:acpi:KIOX000A*:dmi:*:svnTREKSTOR:pnPrimetabT13B:* +sensor:modalias:acpi:BOSC0200*:dmi:*:svnTrekStor*:pnSurfTabtwin11.6:* + ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1 + +sensor:modalias:acpi:KIOX010A*:dmi:*:svnTREKSTOR:pnPrimebookC11B:* +sensor:modalias:acpi:KIOX010A*:dmi:*:svnTREKSTOR:pnPRIMEBOOKC11B:* + ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, -1 + ACCEL_LOCATION=display + +sensor:modalias:acpi:KIOX020A*:dmi:*:svnTREKSTOR:pnPrimebookC11B:* +sensor:modalias:acpi:KIOX020A*:dmi:*:svnTREKSTOR:pnPRIMEBOOKC11B:* + ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1 + ACCEL_LOCATION=base + +######################################### +# Umax +######################################### +sensor:modalias:acpi:SMO8500*:dmi:*:svnUMAX:pnVisionBook10WiPlus:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 + +######################################### +# Wortmann +######################################### +sensor:modalias:acpi:KIOX000A*:dmi:*:svnWortmann_AG:pnTERRA_PAD_1061:* + ACCEL_MOUNT_MATRIX=0, -1, 0; 1, 0, 0; 0, 0, -1 + +######################################### +# Yours +######################################### +sensor:modalias:acpi:BMA250E*:dmi:*:svnYOURS:pnY8W81:* + ACCEL_MOUNT_MATRIX=0, -1, 0; -1, 0, 0; 0, 0, 1 diff --git a/hwdb.d/70-joystick.hwdb b/hwdb.d/70-joystick.hwdb new file mode 100644 index 00000000..9d5c4fc0 --- /dev/null +++ b/hwdb.d/70-joystick.hwdb @@ -0,0 +1,50 @@ +# This file is part of systemd. +# +# Database for joystick device information that cannot be queried directly. +# +# The lookup keys are composed in: +# 70-joystick.rules +# +# Note: The format of the "joystick:" prefix match key is a +# contract between the rules file and the hardware data, it might +# change in later revisions to support more or better matches, it +# is not necessarily expected to be a stable ABI. +# +# Match string format: +# joystick::vp:name:: +# +# vid/pid as 4-digit hex lowercase vendor/product +# +# To add local entries, create a new file +# /etc/udev/hwdb.d/71-joystick-local.hwdb +# and add your rules there. To load the new rules execute (as root): +# systemd-hwdb update +# udevadm trigger /dev/input/eventXX +# where /dev/input/eventXX is the joystick in question. If in +# doubt, simply use /dev/input/event* to reload all input rules. +# +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of +# udevadm info /dev/input/eventXX. +# +# Permitted keys: +# Specify if a joystick is a built-in one or external: +# ID_INPUT_JOYSTICK_INTEGRATION=internal|external +# +# If the property is missing, user-space can assume: +# ID_INPUT_JOYSTICK_INTEGRATION=external + +joystick:bluetooth:* + ID_INPUT_JOYSTICK_INTEGRATION=external + +########################################################### +# GPD +########################################################### + +# GPD Win, Classic and XBox 360 compat modes +joystick:usb:v11c5p5507* +joystick:usb:v045ep028e* + ID_INPUT_JOYSTICK_INTEGRATION=internal diff --git a/hwdb.d/70-mouse.hwdb b/hwdb.d/70-mouse.hwdb new file mode 100644 index 00000000..2e6c3bd3 --- /dev/null +++ b/hwdb.d/70-mouse.hwdb @@ -0,0 +1,756 @@ +# This file is part of systemd. +# +# Database for the DPI setting of mice, trackballs, other pointer devices that +# cannot be queried directly. +# +# The lookup keys are composed in: +# 70-mouse.rules +# +# Note: The format of the "mouse:" prefix match key is a +# contract between the rules file and the hardware data, it might +# change in later revisions to support more or better matches, it +# is not necessarily expected to be a stable ABI. +# +# Match string format: +# mouse::vp:name:: +# +# Supported subsystems: usb, bluetooth +# vid/pid as 4-digit hex lowercase vendor/product +# +# if vid/pid is unavailable, use +# mouse:*:name:: +# if name is unavailable, use +# mouse::vp:* +# +# For example, the following 5 matches all match the same mouse: +# mouse:usb:v17efp6019:name:Lenovo Optical USB Mouse: +# mouse:usb:*:name:Lenovo Optical USB Mouse: +# mouse:usb:v17efp6019:* +# mouse:*:name:Lenovo Optical USB Mouse: +# +# To add local entries, create a new file +# /etc/udev/hwdb.d/71-mouse-local.hwdb +# and add your rules there. To load the new rules execute (as root): +# systemd-hwdb update +# udevadm trigger /dev/input/eventXX +# where /dev/input/eventXX is the mouse in question. If in +# doubt, simply use /dev/input/event* to reload all input rules. +# +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of +# udevadm info /dev/input/eventXX. +# +# Allowed properties are: +# ID_INPUT_TRACKBALL +# MOUSE_DPI +# MOUSE_WHEEL_CLICK_ANGLE +# MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL +# MOUSE_WHEEL_CLICK_COUNT +# MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL +# MOUSE_WHEEL_TILT_HORIZONTAL +# MOUSE_WHEEL_TILT_VERTICAL +# +######################################### +# ID_INPUT_TRACKBALL # +######################################### +# +# Specified *in additition* to ID_INPUT_MOUSE if the device is a trackball. +# Removing ID_INPUT_MOUSE will break backwards compatibility. +# +######################################### +# MOUSE_DPI # +######################################### +# +# DPI settings are specified as +# MOUSE_DPI=[@] +# +# Where is the resolution in dots per inch, and the +# sampling frequency in Hz (optional). If a device supports dynamic +# frequency scaling, the maximum frequency should be used. For devices +# supporting multiple fixed frequencies, see below. +# +# The value of MOUSE_DPI is: +# - a single integer for single-resolution mice, e.g. +# MOUSE_DPI=800 +# or, if the frequency is known: +# MOUSE_DPI=800@120 +# - a space-separated list of resolutions for multi-resolution mice. +# The default resolution must be prefixed by an asterisk, the resolutions +# in the database must be as shipped by the manufacturer. e.g. +# MOUSE_DPI=400 *800 2000 +# +# The order of resolutions is as configured by the HW manufacturer or in +# ascending order, whichever appropriate. +# +# The frequency must be given to either none or all resolutions. If the +# device supports multiple fixed frequencies, the order of items is +# MOUSE_DPI=r1@f1 r2@f1 r3@f1 r1@f2 r2@f2 r3@f2 +# +# If the default manufacturer-set resolution is unclear, a resolution of +# 800 or 1000 should be set as default, if available. If neither is +# available, choose the "middle" resolution value of those available. +# +# The list may contain a single item which must be marked with an +# asterisk. +# +# Local changes to the non-default resolution of the mouse (e.g. through +# third-party software) must not be entered into this file, use a local +# hwdb instead. +# +######################################### +# MOUSE_WHEEL_CLICK_ANGLE # +######################################### +# +# The angle in degrees per mouse wheel 'click', specified as +# MOUSE_WHEEL_CLICK_ANGLE= +# +# Most mice have a 15 degree click stop (24 clicks per full rotation). +# For backwards-compatibility, the click angle must be an integer. +# Where a device has non-integer click angles, the MOUSE_WHEEL_CLICK_COUNT +# property should also be specified. +# +######################################### +# MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL # +######################################### +# +# Identical to MOUSE_WHEEL_CLICK_ANGLE but for the horizontal scroll wheel. +# This property may only be specified if the angle for the horizontal +# scroll wheel differs from the vertical wheel. If so, *both* click angles +# must be specified. +# +######################################### +# MOUSE_WHEEL_CLICK_COUNT # +# MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL # +######################################### +# +# The number of clicks the wheel sends per 360 degree rotation. This +# property should only be used where the click angle is not an integer. +# For backwards compatibility it must be specified in addition to +# MOUSE_WHEEL_CLICK_ANGLE. +# Clients should prefer MOUSE_WHEEL_CLICK_COUNT where available, it is more +# precise than MOUSE_WHEEL_CLICK_ANGLE. +# +# MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL works the same way but also follows the +# rules of MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL. + +######################################### +# MOUSE_WHEEL_TILT_HORIZONTAL # +# MOUSE_WHEEL_TILT_VERTICAL # +######################################### +# +# Indicates that the respective axis is not a mouse wheel rotation but a +# tilt along that axis. Wheel tilt is most commonly used for horizontal +# scroll wheel emulation on mice with only a single vertical wheel. +# +# The vertical and horizontal Axes are independently marked as tilt axes, +# for example it is permitted to have a MOUSE_WHEEL_CLICK_COUNT or +# MOUSE_WHEEL_CLICK_ANGLE for the vertical axis and mark the horizontal axis +# marked as as MOUSE_WHEEL_TILT_HORIZONTAL. +# +# It is a bug to have either CLICK_COUNT or CLICK_ANGLE set on the same axis +# as WHEEL_TILT. Applications should give priority to WHEEL_TILT and ignore +# other settings. +# +# This is a flag only, permitted values: 0 or 1 + +# +# Sort by brand, type (usb, bluetooth), DPI, frequency. +# For mice with switchable resolution, sort by the starred entry. + +########################################## +# Generic +########################################## +mouse:*:name:*Trackball*: +mouse:*:name:*trackball*: +mouse:*:name:*TrackBall*: + ID_INPUT_TRACKBALL=1 + +########################################## +# Apple +########################################## + +# Apple MagicMouse +# Note: this device changes name once connected to a mac, the name ends up +# as $username`s mouse +mouse:bluetooth:v05acp030d:name:*: + MOUSE_DPI=1300@1000 + +########################################## +# Chicony +########################################## + +# Chicony 2.4G Multimedia Wireless Kit MG-0919 +mouse:usb:v04f2p0963:name:Chicony 2.4G Multimedia Wireless Kit: + MOUSE_DPI=1000@142 + +########################################## +# Dell +########################################## + +# Dell MUAR DEL7 +mouse:usb:v413cp3012:name:Dell Dell USB Optical Mouse: + MOUSE_DPI=400@166 + +# Dell USB Laser Mouse +mouse:usb:v046dpc063:name:DELL DELL USB Laser Mouse: + MOUSE_DPI=1000@125 + +# Dell MS116t +mouse:usb:v413cp301a:name:PixArt Dell MS116 USB Optical Mouse: + MOUSE_DPI=1000@125 + +########################################## +# Dynex +######################################### + +# Dynex Wired Optical Mouse (DX-WMSE2) +mouse:usb:v0461p4d46:name:USB Optical Mouse: + MOUSE_DPI=1000@125 + +########################################## +# Fujitsu Siemens +########################################## + +mouse:usb:v0461p4d16:name:USB Optical Mouse: + MOUSE_DPI=500@125 + +########################################## +# Future Technology Devices International +########################################## + +# SNES Mouse plugged into a Retrode 2 +mouse:usb:v0403p97c1:name:Retrode SNES Mouse: + MOUSE_DPI=235@126 + +########################################## +# Generic +########################################## + +# FM-901 Wireless Mouse +mouse:usb:v1ea7p000b:name:2.4G RF Mouse: + MOUSE_DPI=*800@125 1600@125 + +# WK-727 +mouse:usb:v04d9p0499:name:* + MOUSE_DPI=800@125 + +########################################## +# HandShoe Mouse +########################################## + +# HandShoe Mouse +mouse:usb:v192fp0916:name:USB Optical Mouse: + MOUSE_DPI=1000@128 + +########################################## +# HoverStop +########################################## + +# Hoverstop active ergonomic mouse +mouse:usb:v088dp1234:name:HoverStop NL Hoverstop active ergonomic mouse: + MOUSE_DPI=400@129 + +########################################## +# HP +########################################## + +# HP USB 1000dpi Laser Mouse +mouse:usb:v0458p0133:name:Mouse Laser Mouse: + MOUSE_DPI=1000@125 + MOUSE_WHEEL_CLICK_ANGLE=15 + +# HP X1000 +# Dell MS111-T +mouse:usb:v093ap2510:name:PixArt USB Optical Mouse: +mouse:usb:v093ap2510:name:PIXART USB OPTICAL MOUSE: + MOUSE_DPI=1000@125 + +# HP X1200 Optical Mouse +mouse:usb:v03f0p0641:name:PixArt HP X1200 USB Optical Mouse: + MOUSE_DPI=1100@125 + +########################################## +# IBM +########################################## + +# IBM USB Travel Mouse (MO32BO) +mouse:usb:v04b3p3107:name:* + MOUSE_DPI=800@125 + +########################################## +# Kensington +########################################## + +# Kensington Expert Mouse trackball +mouse:usb:v047dp1020:*Kensington Expert Mouse* + ID_INPUT_TRACKBALL=1 + +########################################## +# Lenovo +########################################## + +# Lenovo Optical USB Mouse +mouse:usb:v17efp6019:name:Lenovo Optical USB Mouse: + MOUSE_DPI=1000@125 + +# Lenovo M-U0025-O +mouse:usb:v17efp6019:name:Logitech Lenovo USB Optical Mouse: + MOUSE_DPI=1000@166 + +# Lenovo USB mouse model MO28UOL +mouse:usb:v04b3p310c:name:USB Optical Mouse: + MOUSE_DPI=400@142 + +# Lenovo Precision USB Mouse +mouse:usb:v17efp6050:name:Lenovo Precision USB Mouse: + MOUSE_DPI=1200@127 + +# Lenovo MOBGUL +mouse:usb:v17efp601d:name:Primax Lenovo Laser Mouse: + MOUSE_DPI=1600@125 + +# Lenovo MOBGULA +mouse:usb:v17efp6045:name:Lenovo USB Laser Mouse: + MOUSE_DPI=1600@125 + +# ThinkPad USB Laser Mouse +mouse:usb:v17efp6044:name:ThinkPad USB Laser Mouse: + MOUSE_DPI=1200@125 + +########################################## +# Logitech +########################################## + +# Note: devices using the Logitech Unifying receiver will need two entries, +# one for pre 3.19 with the wireless PID in the name, one for 3.19 with the +# model name. The usb vid/pid is the same for all those devices. +# Until 3.19 is available, this list just has the Wireless PID entry. + +## G Series ## + +# Logitech G5 Laser Mouse +mouse:usb:v046dpc049:name:Logitech USB Gaming Mouse: + MOUSE_DPI=400@500 *800@500 2000@500 + +# Logitech G500s Laser Gaming Mouse +mouse:usb:v046dpc24e:name:Logitech G500s Laser Gaming Mouse: + MOUSE_DPI=400@500 *800@500 2000@500 + +# Logitech G9 +mouse:usb:v046dpc048:name:Logitech G9 Laser Mouse: + MOUSE_DPI=400@1000 800@1000 *1600@1000 + +# Logitech G9x [Call of Duty MW3 Edition] +mouse:usb:v046dpc249:name:Logitech G9x Laser Mouse: + MOUSE_DPI=400@1000 800@1000 *1600@1000 3200@1000 + +# Logitech G100s Optical Gaming Mouse +mouse:usb:v046dpc247:name:Logitech G100s Optical Gaming Mouse: + MOUSE_DPI=*1000@500 1750@500 2500@500 + +# Logitech G400 (Wired) +mouse:usb:v046dpc245:name:Logitech Gaming Mouse G400: + MOUSE_DPI=400@1000 *800@1000 1800@1000 3600@1000 + +# Logitech G400s (Wired) +mouse:usb:v046dpc24c:name:Logitech G400s Optical Gaming Mouse: + MOUSE_DPI=400@1000 *800@1000 2000@1000 4000@1000 + +# Logitech G402 Hyperion Fury +mouse:usb:v046dpc07e:name:Logitech Gaming Mouse G402: + MOUSE_DPI=400@1000 *800@1000 1600@1000 3200@1000 + +# Logitech G500 Mouse +mouse:usb:v046dpc068:name:Logitech G500: + MOUSE_DPI=*1600@500 2600@500 3600@500 + +# Logitech G502 Proteus Spectrum +mouse:usb:v046dpc332:name:Logitech Gaming Mouse G502: + MOUSE_DPI=1200@1000 *2400@1000 3200@1000 6400@1000 + +# Logitech G700 Laser Mouse (Wired) +mouse:usb:v046dpc06b:name:Logitech G700 Laser Mouse: +# Logitech G700 Laser Mouse (Wireless) +mouse:usb:v046dpc531:name:Logitech USB Receiver: + MOUSE_DPI=*1000@500 3800@500 500@1000 1500@1000 2000@1000 + +# Logitech G703 (Wired) +mouse:usb:v046dpc087:name:Logitech G703 Wired/Wireless Gaming Mouse: +# Logitech G703 (Wireless) +mouse:usb:v046dpc539:name:Logitech USB Receiver Mouse: + MOUSE_DPI=400@1000 800@1000 *1600@1000 3200@1000 + +## M Series ## + +# Logitech Wireless Mouse M185 +mouse:usb:v046dp4008:name:Logitech M185: +mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4008: + MOUSE_DPI=1000@125 + +# Logitech Wireless Mouse M510 +mouse:usb:v046dp1025:name:Logitech M510: + MOUSE_DPI=1000@125 + +# Logitech M705 (marathon mouse) +mouse:usb:v046dp101b:name:Logitech M705: +mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:101b: + MOUSE_DPI=1000@125 + +# Logitech M305 Wireless Optical Mouse +mouse:usb:v046dpc52f:name:Logitech USB Receiver: + MOUSE_DPI=1000@170 + +# Logitech Wireless Mouse M310 +mouse:usb:v046dp1024:name:Logitech M310: + MOUSE_DPI=1100@168 + +# Logitech Wireless Mouse M325 +mouse:usb:v046dp400a:name:Logitech M325: +mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:400a: + MOUSE_DPI=600@166 + MOUSE_WHEEL_CLICK_ANGLE=20 + +# Logitech M570 trackball +mouse:usb:v046dp1028:name:Logitech M570: + MOUSE_DPI=540@167 + ID_INPUT_TRACKBALL=1 + +## MX Series ## + +# Logitech Performance MX +mouse:usb:v046dp101a:name:Logitech Performance MX: + MOUSE_DPI=1000@166 + +# Logitech MX Revolution +mouse:usb:v046dpc51a:name:Logitech USB Receiver: + MOUSE_DPI=800@200 + +# Logitech MX 518 +mouse:usb:v046dpc01e:name:Logitech USB-PS/2 Optical Mouse: + MOUSE_DPI=400@125 *800@125 1600@125 + +# Logitech MX1000 Laser Cordless Mouse +mouse:bluetooth:v046dpb003:name:Logitech MX1000 mouse: + MOUSE_DPI=800@80 + +# Logitech Anywhere MX +mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:1017: +mouse:usb:v046dp1017:name:Logitech Anywhere MX: + MOUSE_WHEEL_CLICK_ANGLE=20 + +# Logitech Anywhere MX 2S (via Logitech Unifying Receiver) +mouse:usb:v046dp406a:name:Logitech MX Anywhere 2S: + MOUSE_WHEEL_CLICK_ANGLE=20 + +# Logitech Anywhere MX 2S (via Bluetooth) +mouse:bluetooth:v046dpb01a:name:MX Anywhere 2S Mouse: + MOUSE_WHEEL_CLICK_ANGLE=20 + +# Logitech MX Master (via Logitech Unifying Receiver) +# Horiz wheel has 14 stops, angle is rounded up +mouse:usb:v046dp4060:name:Logitech MX Master: +mouse:usb:v046dp4041:name:Logitech MX Master: + MOUSE_DPI=1000@166 + MOUSE_WHEEL_CLICK_ANGLE=15 + MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26 + MOUSE_WHEEL_CLICK_COUNT=24 + MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL=14 + +# Logitech MX Master (via Bluetooth) +# Horiz wheel has 14 stops, angle is rounded up +mouse:bluetooth:v046dpb012:name:MX Master Mouse: + MOUSE_DPI=1000@2000 + MOUSE_WHEEL_CLICK_ANGLE=15 + MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26 + MOUSE_WHEEL_CLICK_COUNT=24 + MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL=14 + +# Logitech MX Master 2S (via Logitech Unifying Receiver) +# Horiz wheel has 14 stops, angle is rounded up +mouse:usb:v046dp4069:name:Logitech MX Master 2s: + MOUSE_DPI=1000@125 + MOUSE_WHEEL_CLICK_ANGLE=15 + MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26 + MOUSE_WHEEL_CLICK_COUNT=24 + MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL=14 + +# Logitech MX Master 2S (via Bluetooth) +# Horiz wheel has 14 stops, angle is rounded up +mouse:bluetooth:v046dpb019:name:MX Master 2S Mouse: + MOUSE_DPI=1000@2000 + MOUSE_WHEEL_CLICK_ANGLE=15 + MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26 + MOUSE_WHEEL_CLICK_COUNT=24 + MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL=14 + +# Logitech MX Ergo (via Bluetooth) +mouse:bluetooth:v046dpb01d:name:MX Ergo Mouse: + ID_INPUT_TRACKBALL=1 + +## Other ## + +# Logitech M-BJ58 Optical Mouse +mouse:usb:v046dpc00e:name:Logitech USB-PS/2 Optical Mouse: + MOUSE_DPI=400@125 + +# Logitech Mini Optical Mouse +mouse:usb:v046dpc016:name:Logitech Optical USB Mouse: + MOUSE_DPI=400@125 + +# Logitech MX310 Optical Mouse +mouse:usb:v046dpc01b:name:Logitech USB-PS/2 Optical Mouse: + MOUSE_DPI=400@125 + +# Logitech USB-PS/2 M-BT58 +mouse:usb:v046dpc03e:name:Logitech USB-PS/2 Optical Mouse: + MOUSE_DPI=400@125 + +# Logitech TrackMan Marble Wheel USB +mouse:usb:v046dpc401:name:Logitech USB-PS/2 Trackball: + MOUSE_DPI=400@125 + +# Logitech Cordless MouseMan Optical M-RM63 +mouse:usb:v046dpc501:name:Logitech USB Receiver: + MOUSE_DPI=800@63 + +# Logitech USB-PS/2 M-BZ96C +mouse:usb:v046dpc045:name:Logitech USB-PS/2 Optical Mouse: + MOUSE_DPI=600@125 + +# Logitech MX400 Performance Laser Mouse +mouse:usb:v046dpc043:name:Logitech USB-PS/2 Optical Mouse: + MOUSE_DPI=800@125 + +# Logitech MX1000 Laser Cordless Mouse +mouse:usb:v046dpc50e:name:Logitech USB RECEIVER: + MOUSE_DPI=800@125 + +# Logitech Cordless Click! Plus +mouse:usb:v046dpc50e:name:Logitech USB Receiver: + MOUSE_DPI=800@125 + +# Logitech, Inc. RX 300 Optical Mouse +mouse:usb:v046dpc040:name:Logitech USB-PS/2 Optical Mouse: + MOUSE_DPI=800@125 + +# Logitech, Inc. RX 250 Optical Mouse +mouse:usb:v046dpc050:name:Logitech USB-PS/2 Optical Mouse: + MOUSE_DPI=1000@142 + +# Logitech B605 Wireless Mouse (also M505) +mouse:usb:v046dp101d:name:Logitech B605: +mouse:usb:v046dp101d:name:Logitech M505: +mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:101d: + MOUSE_DPI=900@166 + +# Logitech Cordless Desktop Wave Mouse +mouse:usb:v046dpc517:name:Logitech USB Receiver: + MOUSE_DPI=950@125 + +# Logitech RX1000 Laser Mouse +mouse:usb:v046dpc046:name:Logitech USB Optical Mouse: + MOUSE_DPI=1000@125 + +# Logitech M100 Optical Mouse +mouse:usb:v046dpc05a:name:Logitech USB Optical Mouse: + MOUSE_DPI=1000@125 + +# Logitech USB Laser Mouse M-U0011-O rebranded as "terra Laser" +mouse:usb:v046dpc065:name:Logitech USB Laser Mouse: + MOUSE_DPI=1000@125 + +# Logitech USB Laser Mouse M-U0007 [M500] +mouse:usb:v046dpc069:name:Logitech USB Laser Mouse: + MOUSE_DPI=1000@125 + +# Logitech V500 Cordless Notebook Mouse +mouse:usb:v046dpc510:name:Logitech USB Receiver: + MOUSE_DPI=1000@125 + +# Logitech M560 Wireless Mouse +mouse:usb:v046dp402d:name:Logitech M560: +mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:402d: + MOUSE_DPI=1000@125 + +# Logitech MK260 Wireless Combo Receiver aka M-R0011 +mouse:usb:v046dpc52e:name:Logitech USB Receiver: + MOUSE_DPI=1000@200 + +# Logitech USB Laser Mouse M-UAS144 [LS1 Laser Mouse] +mouse:usb:v046dpc062:name:Logitech USB Laser Mouse: + MOUSE_DPI=1200@125 + +# Logitech T620 (or, the soap) +mouse:usb:v046dp4027:name:Logitech T620: +mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4027: + MOUSE_DPI=1200@250 + +# Logitech ZoneTouch Mouse T400 +mouse:usb:v046dp4026:name:Logitech T400: +mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:4026: + MOUSE_DPI=1300@166 + +# Logitech TrackMan Wheel (USB) +mouse:usb:v046dpc404:name:Logitech Trackball: + MOUSE_DPI=300@125 + +# Logitech Ultrathin Touch Mouse +mouse:bluetooth:v046dpb00d:name:Ultrathin Touch Mouse: + MOUSE_DPI=1000@1000 + +# ImPS/2 Logitech Wheel Mouse +mouse:ps2:*:name:ImPS/2 Logitech Wheel Mouse: + MOUSE_DPI=400@100 + +# ImExPS/2 Logitech Wheel Mouse +mouse:ps2:*:name:ImExPS/2 Logitech Wheel Mouse: + MOUSE_DPI=400@250 + +########################################## +# Microsoft +########################################## + +mouse:usb:v045ep0040:name:Microsoft Microsoft 3-Button Mouse with IntelliEye(TM): + MOUSE_DPI=400@125 + +# Note: unsure that these work, it's likely that all devices on these +# receivers show up with the same vid/pid/name + +# Microsoft Wireless Mouse 5000 +mouse:usb:v045ep0745:name:Microsoft Microsoft® 2.4GHz Transceiver v6.0: + MOUSE_DPI=800@142 + +# Microsoft Comfort Mouse 4500 +mouse:usb:v045ep076c:name:Microsoft Microsoft® Comfort Mouse 4500: + MOUSE_DPI=1000@125 + +# Microsoft Wireless Mobile Mouse 4000 +mouse:usb:v045ep0745:name:Microsoft Microsoft® Nano Transceiver v2.0: + MOUSE_DPI=1000@142 + +# Microsoft Sculpt Ergonomic Mouse +mouse:usb:v045ep07a5:name:Microsoft Microsoft® 2.4GHz Transceiver v9.0: + MOUSE_DPI=1000@142 + +# Microsoft Arc Touch Mouse USB +mouse:usb:v045ep07b1:name:Microsoft Microsoft® Nano Transceiver v1.0: + MOUSE_DPI=1400@142 + +# Microsoft Wireless Laser Mouse 8000 +mouse:bluetooth:v045ep0702:name:Microsoft Wireless Laser Mouse 8000: + MOUSE_DPI=1000@1000 + +# Microsoft Sculpt Comfort Mouse +mouse:bluetooth:v045ep07a2:name:Microsoft Sculpt Comfort Mouse: + MOUSE_DPI=1000@2000 + +# Microsoft Arc Touch Mouse SE: +mouse:bluetooth:v045ep07f3:name:Arc Touch Mouse SE: + MOUSE_DPI=1000@2000 + +# Microsoft Surface Mouse +mouse:bluetooth:v0000p0000:name:Surface Mouse: + MOUSE_DPI=2000@2000 + +# Microsoft Classic IntelliMouse +mouse:usb:v045ep0823:name:Microsoft Microsoft?? Classic IntelliMouse??: + MOUSE_DPI=3200@1000 + +########################################## +# Mionix +########################################## + +#Mionix Avior 7000 +mouse:usb:v22d4p1308:name:Laview Technology Mionix Avior 7000: + MOUSE_DPI=400@1000 *1600@1000 7000@1000 + MOUSE_WHEEL_CLICK_ANGLE=15 + +########################################## +# MODECOM +########################################## + +# MODECOM MC-WM4 Wireless Optical Mouse +mouse:usb:v0e8fp00a7:name:DaKai 2.4G RX: + MOUSE_DPI=*800@126 1600@126 + +########################################## +# Oklick +########################################## + +# Oklick 406S Bluetooth Laser Mouse +mouse:bluetooth:v056ep0061:name:Laser BTmouse: + MOUSE_DPI=*800@333 1600@333 + +########################################## +# P-Active +########################################## + +# P-Active Wireless Mouse PA-27K2 +mouse:usb:v0425p0101:name:G-Tech CHINA USB Wireless Mouse & KeyBoard V1.01 : + MOUSE_DPI=800@125 + +########################################## +# Razer +########################################## + +# Razer Abyssus +mouse:usb:v1532p0042:name:Razer Razer Abyssus: + MOUSE_DPI=1600@1000 + +# Razer DeathAdder Black Edition +mouse:usb:v1532p0029:name:Razer Razer DeathAdder: + MOUSE_DPI=3500@1000 + +########################################## +# Roccat +########################################## + +# Roccat Lua (ROC-11-310) +mouse:usb:v1e7dp2c2e:name:ROCCAT ROCCAT Lua: + MOUSE_DPI=250@125 500@125 1000@125 1250@125 1500@125 1750@125 2000@125 250@250 500@250 1000@250 1250@250 1500@250 1750@250 2000@250 250@500 500@500 1000@500 1250@500 1500@500 1750@500 2000@500 250@1000 500@1000 *1000@1000 1250@1000 1500@1000 1750@1000 2000@1000 + MOUSE_WHEEL_CLICK_ANGLE=15 + +########################################## +# Sharkoon +########################################## + +# Sharkoon Shark Force Gaming Mouse +mouse:usb:v093ap2521:name:USB OPTICAL MOUSE: + MOUSE_DPI=*1000@125 1600@125 600@125 + +########################################## +# SteelSeries +########################################## + +# SteelSeries Sensei Raw +mouse:usb:v1038p1369:name:SteelSeries Sensei Raw Gaming Mouse: + MOUSE_DPI=1000@1022 + +########################################## +# Trust +########################################## + +# Trust illuminated mouse gxt 152 +mouse:usb:v145fp01ac:name:HID-compliant Mouse Trust Gaming Mouse: + MOUSE_DPI=*800@528 1200@537 1600@536 2400@521 + +########################################## +# Zelotes +########################################## + +# Zelotes 5500 DPI 7 Button USB Wired Gaming Mouse +mouse:usb:v1d57pad17:* + MOUSE_DPI=1000@500 1600@500 2400@500 3200@500 5500@500 *1000@1000 1600@1000 2400@1000 3200@1000 5500@1000 + +########################################## +# Zowie +########################################## + +# Zowie FK2 +mouse:usb:v3057p0001:* + MOUSE_DPI=400@125 *800@125 1600@125 3200@125 400@500 800@500 1600@500 3200@500 400@1000 800@1000 1600@1000 3200@1000 + MOUSE_WHEEL_CLICK_COUNT=16 + MOUSE_WHEEL_CLICK_ANGLE=23 diff --git a/hwdb.d/70-pointingstick.hwdb b/hwdb.d/70-pointingstick.hwdb new file mode 100644 index 00000000..c5c7dd97 --- /dev/null +++ b/hwdb.d/70-pointingstick.hwdb @@ -0,0 +1,161 @@ +# This file is part of systemd. +# +# Pointingstick const-accel configuration, to make different brand / model +# laptop pointingsticks have the same speed / feel, and per model adjustment +# of the IBM TrackPoint driver's sensitivity setting +# +# The lookup keys are composed in: +# 60-evdev.rules +# +# Note: The format of the "evdev:" prefix match key is a contract between the +# rules file and the hardware data, it might change in later revisions to +# support more or better matches, it is not necessarily a stable ABI. +# +# Supported hardware matches are: +# - Generic input devices match: +# evdev:input:bZZZZvYYYYpXXXXeWWWW-VVVV +# This matches on the kernel modalias of the input-device, mainly: +# ZZZZ is the bus-id (see /usr/include/linux/input.h BUS_*), YYYY, XXXX and +# WWW are the 4-digit hex uppercase vendor, product and version ID and VVVV +# is an arbitrary length input-modalias describing the device capabilities. +# The vendor, product and version ID for a device node "eventX" is listed +# in /sys/class/input/eventX/device/id. +# +# - Input driver device name and DMI data match: +# evdev:name::dmi:bvn*:bvr*:bd*:svn:pn* +# is the name device specified by the driver, +# is the firmware-provided string from the kernel DMI modalias, +# see /sys/class/dmi/id/modalias +# +# To add local entries, create a new file +# /etc/udev/hwdb.d/71-pointingstick-local.hwdb +# and add your rules there. To load the new rules execute (as root): +# systemd-hwdb update +# udevadm trigger /dev/input/eventXX +# where /dev/input/eventXX is the pointingstick in question. If in +# doubt, simply use /dev/input/event* to reload all input rules. +# +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of +# udevadm info /dev/input/eventXX. +# +# Allowed properties are: +# POINTINGSTICK_CONST_ACCEL (deprecated) +# POINTINGSTICK_SENSITIVITY +# +# Entries should be sorted with growing _SENSITIVITY and _CONST_ACCEL. +# +######################################### +# POINTINGSTICK_CONST_ACCEL # +######################################### +# +# DO NOT USE THIS PROPERTY. This property is kept for backwards +# compatibility. The only known consumer, libinput, stopped reading this +# property in version 1.9.0. No new entries for this property should be +# added. +# +# Trackpoint const accel settings are specified as +# POINTINGSTICK_CONST_ACCEL= +# +# Where is a floating point number, using a '.' separator, specifying +# by how much to multiply deltas generated by the pointingstick to get +# normalized deltas. +# +######################################### +# POINTINGSTICK_SENSITIVITY # +######################################### +# +# TPPS/2 IBM TrackPoint driver sensitivity sysfs setting +# POINTINGSTICK_SENSITIVITY= +# +# Where is a number between 0 and 255, note this property +# only applies to TPPS/2 IBM TrackPoint devices, see +# drivers/input/mouse/trackpoint.c in the Linux kernel sources. +# + +# +# Sort by brand, model + +######################################### +# Dell +######################################### + +# Latitude D620 +evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeD620*:pvr* + POINTINGSTICK_CONST_ACCEL=0.5 + +# Latitude E5570 +evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE5570*:pvr* + POINTINGSTICK_CONST_ACCEL=0.1 + +# Latitude E6320 +evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6320*:pvr* + POINTINGSTICK_CONST_ACCEL=2.0 + +# Latitude E6400 +evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE6400*:pvr* + POINTINGSTICK_CONST_ACCEL=1.5 + +# Latitude E7470 +evdev:name:*DualPoint Stick:dmi:bvn*:bvr*:bd*:svnDellInc.:pnLatitudeE7470*:pvr* + POINTINGSTICK_CONST_ACCEL=0.6 + +######################################### +# Lenovo +######################################### + +# Lenovo Thinkpad X220 +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX220:* +# Lenovo Thinkpad X220 tablet +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX220Tablet:* +# Lenovo Thinkpad X230 +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX230:* +# Lenovo Thinkpad X230 tablet +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX230Tablet:* +# Lenovo ThinkPad *30 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??30:* +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??30?:* +# Lenovo Thinkpad *40 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??40:* +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??40?:* +# Lenovo Thinkpad *50 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??50:* +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??50?:* +# Lenovo Thinkpad *60 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??60:* +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??60?:* +# Lenovo Thinkpad *70 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??70:* +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??70?:* +# Lenovo Thinkpad *80 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??80:* +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??80?:* +# Lenovo Thinkpad *90 series +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??90:* +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPad??90?:* +# Lenovo Thinkpad X1 Carbon 3rd gen +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon3rd:* +# Lenovo Thinkpad X1 Carbon 4th gen +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Carbon4th:* +# Lenovo Thinkpad X1 Tablet +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX1Tablet:* + POINTINGSTICK_SENSITIVITY=200 + POINTINGSTICK_CONST_ACCEL=1.0 + +# Lenovo Thinkpad X200/X201/X200s/X201s/X200 Tablet/X201 Tablet +# Note these come with 2 revisions of keyboard, with the trackpoints having a +# different sensitivity in the different revisions. 1.25 is a bit slow for the +# least sensitive revision, but it is better to be a bit slow than too fast. +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX20?:* +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX20??:* +evdev:name:TPPS/2 IBM TrackPoint:dmi:bvn*:bvr*:bd*:svnLENOVO:pn*:pvrThinkPadX20?Tablet:* + POINTINGSTICK_SENSITIVITY=200 + POINTINGSTICK_CONST_ACCEL=1.25 + +# Lenovo UltraNav SK-8845 (USB keyboard) +evdev:input:b0003v06CBp0009* + POINTINGSTICK_CONST_ACCEL=2.5 + POINTINGSTICK_SENSITIVITY=200 diff --git a/hwdb.d/70-touchpad.hwdb b/hwdb.d/70-touchpad.hwdb new file mode 100644 index 00000000..8194d983 --- /dev/null +++ b/hwdb.d/70-touchpad.hwdb @@ -0,0 +1,69 @@ +# This file is part of systemd. +# +# Database for touchpad device information that cannot be queried directly. +# +# The lookup keys are composed in: +# 70-touchpad.rules +# +# Note: The format of the "touchpad:" prefix match key is a +# contract between the rules file and the hardware data, it might +# change in later revisions to support more or better matches, it +# is not necessarily expected to be a stable ABI. +# +# Match string format: +# touchpad::vp:name:: +# +# vid/pid as 4-digit hex lowercase vendor/product +# +# To add local entries, create a new file +# /etc/udev/hwdb.d/71-touchpad-local.hwdb +# and add your rules there. To load the new rules execute (as root): +# systemd-hwdb update +# udevadm trigger /dev/input/eventXX +# where /dev/input/eventXX is the touchpad in question. If in +# doubt, simply use /dev/input/event* to reload all input rules. +# +# If your changes are generally applicable, preferably send them as a pull +# request to +# https://github.com/systemd/systemd +# or create a bug report on https://github.com/systemd/systemd/issues and +# include your new rules, a description of the device, and the output of +# udevadm info /dev/input/eventXX. +# +# Permitted keys: +# Specify if a touchpad is a built-in one or external: +# ID_INPUT_TOUCHPAD_INTEGRATION=internal|external + +touchpad:i8042:* +touchpad:rmi:* +touchpad:usb:* + ID_INPUT_TOUCHPAD_INTEGRATION=internal + +touchpad:bluetooth:* + ID_INPUT_TOUCHPAD_INTEGRATION=external + +########################################################### +# Apple +########################################################### +# Magic Trackpad (1 and 2) +touchpad:usb:v05acp030e:* +touchpad:usb:v05acp0265:* + ID_INPUT_TOUCHPAD_INTEGRATION=external + +########################################################### +# HP Elite x2 1013 G3 +########################################################### +touchpad:usb:v044ep1221:* + ID_INPUT_TOUCHPAD_INTEGRATION=external + +########################################################### +# Logitech +########################################################### +touchpad:usb:v046d* + ID_INPUT_TOUCHPAD_INTEGRATION=external + +########################################################### +# Wacom +########################################################### +touchpad:usb:v056a* + ID_INPUT_TOUCHPAD_INTEGRATION=external diff --git a/hwdb.d/acpi-update.py b/hwdb.d/acpi-update.py new file mode 100755 index 00000000..7bdd3f93 --- /dev/null +++ b/hwdb.d/acpi-update.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 + +from html.parser import HTMLParser +from enum import Enum + +class State(Enum): + NOWHERE = 0 + COMPANY = 1 + AFTER_COMPANY = 2 + PNPID = 3 + AFTER_PNPID = 4 + DATE = 5 + +class PNPTableParser(HTMLParser): + + def __init__(self): + HTMLParser.__init__(self) + self.state = State.NOWHERE + self.data = "" + self.pnpid = None + self.company = None + self.table = [] + + def handle_starttag(self, tag, attrs): + + if tag == "td": + if self.state == State.NOWHERE: + self.state = State.COMPANY + elif self.state == State.AFTER_COMPANY: + self.state = State.PNPID + elif self.state == State.AFTER_PNPID: + self.state = State.DATE + else: + raise ValueError + + self.data = "" + + def handle_endtag(self, tag): + + if tag == "td": + if self.state == State.COMPANY: + self.company = ' '.join(self.data.strip().split()) + self.state = State.AFTER_COMPANY + elif self.state == State.PNPID: + self.pnpid = self.data.strip() + self.state = State.AFTER_PNPID + self.table.append((self.pnpid, self.company)) + elif self.state == State.DATE: + self.state = State.NOWHERE + else: + raise ValueError + + def handle_data(self, data): + self.data += data + +def read_table(a): + + parser = PNPTableParser() + + for line in a: + parser.feed(line) + + parser.close() + parser.table.sort() + + for pnpid, company in parser.table: + print("\nacpi:{0}*:\n ID_VENDOR_FROM_DATABASE={1}".format(pnpid, company)) + +a = open("acpi_id_registry.html") +b = open("pnp_id_registry.html") + +print('# This file is part of systemd.\n' + '#\n' + '# Data imported from:\n' + '# https://uefi.org/uefi-pnp-export\n' + '# https://uefi.org/uefi-acpi-export') + +read_table(a) +read_table(b) diff --git a/hwdb.d/acpi_id_registry.html b/hwdb.d/acpi_id_registry.html new file mode 100644 index 00000000..98307538 --- /dev/null +++ b/hwdb.d/acpi_id_registry.html @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CompanyACPI IDApproved on Date
Aava Mobile OyAAVA04/02/2014
AMDAMDI08/06/2014
Applied Micro Circuits CorporationAPMC11/14/2013
Aptina Imaging CorporationAPTA10/28/2013
ARM Ltd.ARMH08/13/2012
ARM Ltd.ARML02/24/2015
ASUSASUS09/13/2012
AtmelATML11/17/2011
AuthenTecAUTH06/01/2012
Broadcom CorporationBRCM05/14/2015
Capella Microsystems Inc.CPLM05/09/2012
Dell, Inc.DLLK04/17/2012
Dell, Inc.DELL07/26/2012
ELAN MICROELECTRONICS CORPORATIONELAN11/14/2014
Everest Semiconductor Co., Ltd.ESSX11/17/2014
FocalTech Systems Co., Ltd.FTSC07/23/2013
Freescale, IncFRSC01/01/2010
Fuzhou Rockchip Electronics Co., Ltd.RKCP07/20/2015
Google, Inc.GOOG12/05/2013
Hewlett-Packard CompanyHPQC11/26/2012
Hewlett Packard EnterpriseHWPE01/15/2015
Himax Technologies, Inc.HIMX03/19/2014
HiSilicon Technologies Co., Ltd.HISI11/14/2014
HP Inc. HPIC01/15/2015
HTBLuVA MödlingHTLM02/18/2014
IBMIBMX11/15/2012
ImpinjIMPJ08/14/2012
Inphi CorporationIPHI07/15/2014
Intel CorporationACPI11/18/2011
Intel CorporationINTC01/01/2010
Intel CorporationINTL01/01/2010
Invensense, IncINVN02/09/2012
IP3 Technology Ltd.IP3T11/11/2013
Kionix, Inc.KIOX12/23/2013
Lenovo Beijing Co. Ltd.IDEA05/22/2012
Linaro, Ltd.LNRO11/26/2013
Microsoft CorporationMSAY03/01/2012
Microsoft CorporationMSFT01/01/2010
Microsoft CorporationMSHW01/10/2011
MIPI AllianceMIPI04/17/2015
Nuvoton Technology CorporationNVTN11/14/2014
NvidiaNVDA01/01/2010
OmniVision Technologies, Inc.OVTI02/26/2014
Pegatron CorporationPEGA08/27/2013
Qualcomm IncQCOM01/01/2010
REALTEK Semiconductor Corp. OBDA11/07/2013
Red Hat, Inc.QEMU07/30/2015
Robert Bosch GmbHBOSC05/16/2014
Rozsnyó, s.r.o.RZSN03/24/2014
Sharp CorporationSHRP01/27/2015
Shenzhen DSO Microelectronics Co.,Ltd.DSUO10/10/2013
Shenzhen South-Top Computer Co., Ltd.ST8612/06/2013
Shenzhen three Connaught Information Technology Co., Ltd. (3nod Group)3NOD09/23/2013
Sierra WirelessSWEM01/22/2013
Sony CorporationSONY09/12/2012
Synaptics IncSYNA11/17/2011
Teracue AGTCAG12/07/2012
Texas InstrumentsTXNW01/01/2010
The Linux FoundationLNUX04/04/2014
Toshiba CorporationTOSB07/07/2015
VAIO CorporationVAIO04/18/2014
Validity Sensors, IncVFSI06/17/2013
WacomWCOM11/17/2011
Winsider Seminars & Solutions Inc.WSDR07/07/2015
Maxim IntegratedMXIM10/16/2015
Xiaomi Inc.XMCC12/08/2015
u-blox AGUBLX12/08/2015
Raydium Semiconductor CorporationRAYD04/13/2016
Dialog Semiconductor PLCDLGS04/27/2016
OmniPreSenseOMPS05/25/2016
CoreOS, IncCORE07/01/2016
Microchip Technology IncMCHP08/03/2016
Green Hills SoftwareGHSW08/11/2016
AAEON Technology Inc.AANT09/01/2016
VR Technology Holdings Limited 3GVR01/19/2017
Exar CorporationEXAR02/28/2017
Coreboot ProjectBOOT02/28/2017
Marvell Technology Group Ltd.MRVL05/25/2017
IHSE GmbHIHSE06/22/2017
Insyde SoftwareINSY11/10/2017
Nexstgo Company LimitedNXGO11/13/2017
Ampere ComputingAMPC03/29/2018
IDEMIAIDEM06/26/2018
Vishay Intertechnology, Inc.VSHY07/09/2018
DMIST RESEARCH LTDDMST07/09/2018
COMHEAR, INC.CMHR08/02/2018
Sensel, Inc.SNSL08/20/2018
G2touch Co., LTDGTCH12/04/2018
Guizhou Huaxintong Semiconductor Technology Co., LtdHXTS01/18/2019
Amazon CorporationAMZN02/06/2019
ASEM S.p.A.ASEM04/29/2019
Fujitsu LimitedFUJI06/18/2019
+ + \ No newline at end of file diff --git a/hwdb.d/ids_parser.py b/hwdb.d/ids_parser.py new file mode 100755 index 00000000..6f3a88f8 --- /dev/null +++ b/hwdb.d/ids_parser.py @@ -0,0 +1,369 @@ +#!/usr/bin/env python3 + +import re +import sys +from pyparsing import (Word, White, Literal, Regex, + LineEnd, SkipTo, + ZeroOrMore, OneOrMore, Combine, Optional, Suppress, + Group, + stringEnd, pythonStyleComment) + +EOL = LineEnd().suppress() +NUM1 = Word('0123456789abcdefABCDEF', exact=1) +NUM2 = Word('0123456789abcdefABCDEF', exact=2) +NUM3 = Word('0123456789abcdefABCDEF', exact=3) +NUM4 = Word('0123456789abcdefABCDEF', exact=4) +NUM6 = Word('0123456789abcdefABCDEF', exact=6) +TAB = White('\t', exact=1).suppress() +COMMENTLINE = pythonStyleComment + EOL +EMPTYLINE = LineEnd() +text_eol = lambda name: Regex(r'[^\n]+')(name) + EOL + +def klass_grammar(): + klass_line = Literal('C ').suppress() + NUM2('klass') + text_eol('text') + subclass_line = TAB + NUM2('subclass') + text_eol('text') + protocol_line = TAB + TAB + NUM2('protocol') + text_eol('name') + subclass = (subclass_line('SUBCLASS') - + ZeroOrMore(Group(protocol_line)('PROTOCOLS*') + ^ COMMENTLINE.suppress())) + klass = (klass_line('KLASS') - + ZeroOrMore(Group(subclass)('SUBCLASSES*') + ^ COMMENTLINE.suppress())) + return klass + +def usb_ids_grammar(): + vendor_line = NUM4('vendor') + text_eol('text') + device_line = TAB + NUM4('device') + text_eol('text') + vendor = (vendor_line('VENDOR') + + ZeroOrMore(Group(device_line)('VENDOR_DEV*') ^ COMMENTLINE.suppress())) + + klass = klass_grammar() + + other_line = (Literal('AT ') ^ Literal('HID ') ^ Literal('R ') + ^ Literal('PHY ') ^ Literal('BIAS ') ^ Literal('HUT ') + ^ Literal('L ') ^ Literal('VT ') ^ Literal('HCC ')) + text_eol('text') + other_group = (other_line - ZeroOrMore(TAB + text_eol('text'))) + + commentgroup = OneOrMore(COMMENTLINE).suppress() ^ EMPTYLINE.suppress() + grammar = OneOrMore(Group(vendor)('VENDORS*') + ^ Group(klass)('CLASSES*') + ^ other_group.suppress() ^ commentgroup) + stringEnd() + + grammar.parseWithTabs() + return grammar + +def pci_ids_grammar(): + vendor_line = NUM4('vendor') + text_eol('text') + device_line = TAB + NUM4('device') + text_eol('text') + subvendor_line = TAB + TAB + NUM4('a') + White(' ') + NUM4('b') + text_eol('name') + + device = (device_line('DEVICE') + + ZeroOrMore(Group(subvendor_line)('SUBVENDORS*') ^ COMMENTLINE.suppress())) + vendor = (vendor_line('VENDOR') + + ZeroOrMore(Group(device)('DEVICES*') ^ COMMENTLINE.suppress())) + + klass = klass_grammar() + + commentgroup = OneOrMore(COMMENTLINE).suppress() ^ EMPTYLINE.suppress() + grammar = OneOrMore(Group(vendor)('VENDORS*') + ^ Group(klass)('CLASSES*') + ^ commentgroup) + stringEnd() + + grammar.parseWithTabs() + return grammar + +def sdio_ids_grammar(): + vendor_line = NUM4('vendor') + text_eol('text') + device_line = TAB + NUM4('device') + text_eol('text') + vendor = (vendor_line('VENDOR') + + ZeroOrMore(Group(device_line)('DEVICES*') ^ COMMENTLINE.suppress())) + + klass = klass_grammar() + + commentgroup = OneOrMore(COMMENTLINE).suppress() ^ EMPTYLINE.suppress() + grammar = OneOrMore(Group(vendor)('VENDORS*') + ^ Group(klass)('CLASSES*') + ^ commentgroup) + stringEnd() + + grammar.parseWithTabs() + return grammar + +def oui_grammar(type): + prefix_line = (Combine(NUM2 - Suppress('-') - NUM2 - Suppress('-') - NUM2)('prefix') + - Literal('(hex)') - text_eol('text')) + if type == 'small': + vendor_line = (NUM3('start') - '000-' - NUM3('end') - 'FFF' + - Literal('(base 16)') - text_eol('text2')) + elif type == 'medium': + vendor_line = (NUM1('start') - '00000-' - NUM1('end') - 'FFFFF' + - Literal('(base 16)') - text_eol('text2')) + else: + assert type == 'large' + vendor_line = (NUM6('start') + - Literal('(base 16)') - text_eol('text2')) + + extra_line = TAB - TAB - TAB - TAB - SkipTo(EOL) + vendor = prefix_line + vendor_line + ZeroOrMore(extra_line) + Optional(EMPTYLINE) + + grammar = (Literal('OUI') + text_eol('header') + + text_eol('header') + text_eol('header') + EMPTYLINE + + OneOrMore(Group(vendor)('VENDORS*')) + stringEnd()) + + grammar.parseWithTabs() + return grammar + + +def header(file, *sources): + print('''\ +# This file is part of systemd. +# +# Data imported from:{}{}'''.format(' ' if len(sources) == 1 else '\n# ', + '\n# '.join(sources)), + file=file) + +def add_item(items, key, value): + if key in items: + print(f'Ignoring duplicate entry: {key} = "{items[key]}", "{value}"') + else: + items[key] = value + +def usb_vendor_model(p): + items = {} + + for vendor_group in p.VENDORS: + vendor = vendor_group.vendor.upper() + text = vendor_group.text.strip() + add_item(items, (vendor,), text) + + for vendor_dev in vendor_group.VENDOR_DEV: + device = vendor_dev.device.upper() + text = vendor_dev.text.strip() + add_item(items, (vendor, device), text) + + with open('20-usb-vendor-model.hwdb', 'wt') as out: + header(out, 'http://www.linux-usb.org/usb.ids') + + for key in sorted(items): + if len(key) == 1: + p, n = 'usb:v{}*', 'VENDOR' + else: + p, n = 'usb:v{}p{}*', 'MODEL', + print('', p.format(*key), + f' ID_{n}_FROM_DATABASE={items[key]}', sep='\n', file=out) + + print(f'Wrote {out.name}') + +def usb_classes(p): + items = {} + + for klass_group in p.CLASSES: + klass = klass_group.klass.upper() + text = klass_group.text.strip() + + if klass != '00' and not re.match(r'(\?|None|Unused)\s*$', text): + add_item(items, (klass,), text) + + for subclass_group in klass_group.SUBCLASSES: + subclass = subclass_group.subclass.upper() + text = subclass_group.text.strip() + if subclass != '00' and not re.match(r'(\?|None|Unused)\s*$', text): + add_item(items, (klass, subclass), text) + + for protocol_group in subclass_group.PROTOCOLS: + protocol = protocol_group.protocol.upper() + text = protocol_group.name.strip() + if klass != '00' and not re.match(r'(\?|None|Unused)\s*$', text): + add_item(items, (klass, subclass, protocol), text) + + with open('20-usb-classes.hwdb', 'wt') as out: + header(out, 'http://www.linux-usb.org/usb.ids') + + for key in sorted(items): + if len(key) == 1: + p, n = 'usb:v*p*d*dc{}*', 'CLASS' + elif len(key) == 2: + p, n = 'usb:v*p*d*dc{}dsc{}*', 'SUBCLASS' + else: + p, n = 'usb:v*p*d*dc{}dsc{}dp{}*', 'PROTOCOL' + print('', p.format(*key), + f' ID_USB_{n}_FROM_DATABASE={items[key]}', sep='\n', file=out) + + print(f'Wrote {out.name}') + +def pci_vendor_model(p): + items = {} + + for vendor_group in p.VENDORS: + vendor = vendor_group.vendor.upper() + text = vendor_group.text.strip() + add_item(items, (vendor,), text) + + for device_group in vendor_group.DEVICES: + device = device_group.device.upper() + text = device_group.text.strip() + add_item(items, (vendor, device), text) + + for subvendor_group in device_group.SUBVENDORS: + sub_vendor = subvendor_group.a.upper() + sub_model = subvendor_group.b.upper() + sub_text = subvendor_group.name.strip() + if sub_text.startswith(text): + sub_text = sub_text[len(text):].lstrip() + if sub_text: + sub_text = f' ({sub_text})' + add_item(items, (vendor, device, sub_vendor, sub_model), text + sub_text) + + with open('20-pci-vendor-model.hwdb', 'wt') as out: + header(out, 'http://pci-ids.ucw.cz/v2.2/pci.ids') + + for key in sorted(items): + if len(key) == 1: + p, n = 'pci:v0000{}*', 'VENDOR' + elif len(key) == 2: + p, n = 'pci:v0000{}d0000{}*', 'MODEL' + else: + p, n = 'pci:v0000{}d0000{}sv0000{}sd0000{}*', 'MODEL' + print('', p.format(*key), + f' ID_{n}_FROM_DATABASE={items[key]}', sep='\n', file=out) + + print(f'Wrote {out.name}') + +def pci_classes(p): + items = {} + + for klass_group in p.CLASSES: + klass = klass_group.klass.upper() + text = klass_group.text.strip() + add_item(items, (klass,), text) + + for subclass_group in klass_group.SUBCLASSES: + subclass = subclass_group.subclass.upper() + text = subclass_group.text.strip() + add_item(items, (klass, subclass), text) + + for protocol_group in subclass_group.PROTOCOLS: + protocol = protocol_group.protocol.upper() + text = protocol_group.name.strip() + add_item(items, (klass, subclass, protocol), text) + + with open('20-pci-classes.hwdb', 'wt') as out: + header(out, 'http://pci-ids.ucw.cz/v2.2/pci.ids') + + for key in sorted(items): + if len(key) == 1: + p, n = 'pci:v*d*sv*sd*bc{}*', 'CLASS' + elif len(key) == 2: + p, n = 'pci:v*d*sv*sd*bc{}sc{}*', 'SUBCLASS' + else: + p, n = 'pci:v*d*sv*sd*bc{}sc{}i{}*', 'INTERFACE' + print('', p.format(*key), + f' ID_PCI_{n}_FROM_DATABASE={items[key]}', sep='\n', file=out) + + print(f'Wrote {out.name}') + +def sdio_vendor_model(p): + items = {} + + for vendor_group in p.VENDORS: + vendor = vendor_group.vendor.upper() + text = vendor_group.text.strip() + add_item(items, (vendor,), text) + + for device_group in vendor_group.DEVICES: + device = device_group.device.upper() + text = device_group.text.strip() + add_item(items, (vendor, device), text) + + with open('20-sdio-vendor-model.hwdb', 'wt') as out: + header(out, 'hwdb.d/sdio.ids') + + for key in sorted(items): + if len(key) == 1: + p, n = 'sdio:c*v{}*', 'VENDOR' + else: + p, n = 'sdio:c*v{}d{}*', 'MODEL' + print('', p.format(*key), + f' ID_{n}_FROM_DATABASE={items[key]}', sep='\n', file=out) + + print(f'Wrote {out.name}') + +def sdio_classes(p): + items = {} + + for klass_group in p.CLASSES: + klass = klass_group.klass.upper() + text = klass_group.text.strip() + add_item(items, klass, text) + + with open('20-sdio-classes.hwdb', 'wt') as out: + header(out, 'hwdb.d/sdio.ids') + + for klass in sorted(items): + print(f'', + f'sdio:c{klass}v*d*', + f' ID_SDIO_CLASS_FROM_DATABASE={items[klass]}', sep='\n', file=out) + + print(f'Wrote {out.name}') + +# MAC Address Block Large/Medium/Small +# Large MA-L 24/24 bit (OUI) +# Medium MA-M 28/20 bit (OUI prefix owned by IEEE) +# Small MA-S 36/12 bit (OUI prefix owned by IEEE) +def oui(p1, p2, p3): + prefixes = set() + items = {} + + for p, check in ((p1, False), (p2, False), (p3, True)): + for vendor_group in p.VENDORS: + prefix = vendor_group.prefix.upper() + if check: + if prefix in prefixes: + continue + else: + prefixes.add(prefix) + start = vendor_group.start.upper() + end = vendor_group.end.upper() + + if end and start != end: + print(f'{prefix:} {start} != {end}', file=sys.stderr) + text = vendor_group.text.strip() + + key = prefix + start if end else prefix + add_item(items, key, text) + + with open('20-OUI.hwdb', 'wt') as out: + header(out, + 'https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-L&format=txt', + 'https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-M&format=txt', + 'https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-S&format=txt') + + for pattern in sorted(items): + print(f'', + f'OUI:{pattern}*', + f' ID_OUI_FROM_DATABASE={items[pattern]}', sep='\n', file=out) + + print(f'Wrote {out.name}') + +if __name__ == '__main__': + args = sys.argv[1:] + + if not args or 'usb' in args: + p = usb_ids_grammar().parseFile(open('usb.ids', errors='replace')) + usb_vendor_model(p) + usb_classes(p) + + if not args or 'pci' in args: + p = pci_ids_grammar().parseFile(open('pci.ids', errors='replace')) + pci_vendor_model(p) + pci_classes(p) + + if not args or 'sdio' in args: + p = pci_ids_grammar().parseFile(open('sdio.ids', errors='replace')) + sdio_vendor_model(p) + sdio_classes(p) + + if not args or 'oui' in args: + p = oui_grammar('small').parseFile(open('ma-small.txt')) + p2 = oui_grammar('medium').parseFile(open('ma-medium.txt')) + p3 = oui_grammar('large').parseFile(open('ma-large.txt')) + oui(p, p2, p3) diff --git a/hwdb.d/ma-large.txt b/hwdb.d/ma-large.txt new file mode 100644 index 00000000..b99b3ccc --- /dev/null +++ b/hwdb.d/ma-large.txt @@ -0,0 +1,164760 @@ +OUI/MA-L Organization +company_id Organization + Address + +00-22-72 (hex) American Micro-Fuel Device Corp. +002272 (base 16) American Micro-Fuel Device Corp. + 2181 Buchanan Loop + Ferndale WA 98248 + US + +00-D0-EF (hex) IGT +00D0EF (base 16) IGT + 9295 PROTOTYPE DRIVE + RENO NV 89511 + US + +08-61-95 (hex) Rockwell Automation +086195 (base 16) Rockwell Automation + 1 Allen-Bradley Dr. + Mayfield Heights OH 44124-6118 + US + +F4-BD-9E (hex) Cisco Systems, Inc +F4BD9E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +58-85-E9 (hex) Realme Chongqing MobileTelecommunications Corp Ltd +5885E9 (base 16) Realme Chongqing MobileTelecommunications Corp Ltd + No.24 Nichang Boulevard, Huixing Block, Yubei District, Chongqing. + Chongqing China 401120 + CN + +BC-23-92 (hex) BYD Precision Manufacture Company Ltd. +BC2392 (base 16) BYD Precision Manufacture Company Ltd. + No.3001, Bao He Road, Baolong Industrial, Longgang Street,Longgang Zone, Shenzhen + shenzhen 518116 + CN + +94-E6-F7 (hex) Intel Corporate +94E6F7 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +40-55-82 (hex) Nokia +405582 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +A4-E3-1B (hex) Nokia +A4E31B (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +D8-97-90 (hex) Commonwealth Scientific and Industrial Research Organisation +D89790 (base 16) Commonwealth Scientific and Industrial Research Organisation + GPO Box 1700 + Canberra ACT 2601 + AU + +88-3A-30 (hex) Aruba, a Hewlett Packard Enterprise Company +883A30 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +B8-A5-8D (hex) Axe Group Holdings Limited +B8A58D (base 16) Axe Group Holdings Limited + Road Town + tortola VG1110 + VG + +50-CE-E3 (hex) Gigafirm.co.LTD +50CEE3 (base 16) Gigafirm.co.LTD + 3-21-8,kisonishi + machida-city tokyo 1940037 + JP + +98-E7-43 (hex) Dell Inc. +98E743 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +C4-19-D1 (hex) Telink Semiconductor (Shanghai) Co., Ltd. +C419D1 (base 16) Telink Semiconductor (Shanghai) Co., Ltd. + No. 1500 Zuchongzhi Rd, Building #3 + Shanghai 201203 + CN + +4C-1D-96 (hex) Intel Corporate +4C1D96 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +88-7E-25 (hex) Extreme Networks, Inc. +887E25 (base 16) Extreme Networks, Inc. + 6480 Via Del Oro + San Jose CA 95119 + US + +08-60-83 (hex) zte corporation +086083 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +E0-19-54 (hex) zte corporation +E01954 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +10-32-7E (hex) Huawei Device Co., Ltd. +10327E (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +F8-08-4F (hex) Sagemcom Broadband SAS +F8084F (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +30-FB-B8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +30FBB8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-97-C2 (hex) Nebulon Inc +F497C2 (base 16) Nebulon Inc + 3089 Skyway Court + Fremont CA 94539 + US + +A4-45-19 (hex) Xiaomi Communications Co Ltd +A44519 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +68-DB-F5 (hex) Amazon Technologies Inc. +68DBF5 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +24-46-C8 (hex) Motorola Mobility LLC, a Lenovo Company +2446C8 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +18-02-AE (hex) vivo Mobile Communication Co., Ltd. +1802AE (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +0C-20-D3 (hex) vivo Mobile Communication Co., Ltd. +0C20D3 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +44-D7-91 (hex) HUAWEI TECHNOLOGIES CO.,LTD +44D791 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +84-46-FE (hex) HUAWEI TECHNOLOGIES CO.,LTD +8446FE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D8-29-18 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D82918 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D0-D0-03 (hex) Samsung Electronics Co.,LTD +D0D003 (base 16) Samsung Electronics Co.,LTD + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +64-B2-1D (hex) Chengdu Phycom Tech Co., Ltd. +64B21D (base 16) Chengdu Phycom Tech Co., Ltd. + No.216 beisen road + Chengdu Sichuan 610000 + CN + +C4-29-96 (hex) Signify B.V. +C42996 (base 16) Signify B.V. + High Tech Campus 7 + Eindhoven 5656AE + NL + +98-06-37 (hex) IEEE Registration Authority +980637 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +8C-B8-4A (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +8CB84A (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +98-E8-FA (hex) Nintendo Co.,Ltd +98E8FA (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +38-C4-E8 (hex) NSS Sp. z o.o. +38C4E8 (base 16) NSS Sp. z o.o. + Modularna 11 + Warszawa 02-238 + PL + +34-DD-7E (hex) Umeox Innovations Co.,Ltd +34DD7E (base 16) Umeox Innovations Co.,Ltd + Room 1208-09, Research Building, Tsinghua Information Port, No. 1, Xindong Road, Nanshan District, Shenzhen + Shenzhen Guangdong 518000 + CN + +CC-CD-64 (hex) SM-Electronic GmbH +CCCD64 (base 16) SM-Electronic GmbH + Waldweg 2 + Stapelfeld / Braak 22145 + DE + +24-DF-A7 (hex) Hangzhou BroadLink Technology Co.,Ltd +24DFA7 (base 16) Hangzhou BroadLink Technology Co.,Ltd + Room 101,1/F,Unit C,Building 1,No.57 Jiang'er Road,Changhe Street,Binjiang District,Hangzhou,Zhejiang,P.R.China + Hangzhou Zhejiang 310052 + CN + +B0-65-F1 (hex) WIO Manufacturing HK Limited +B065F1 (base 16) WIO Manufacturing HK Limited + 15/F OTB Building, 160 Glocester Road + Hong Kong 00000 + HK + +90-12-34 (hex) Shenzhen YOUHUA Technology Co., Ltd +901234 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +54-2A-1B (hex) Sonos, Inc. +542A1B (base 16) Sonos, Inc. + 614 Chapala St + Santa Barbara CA 93101 + US + +5C-92-5E (hex) Zioncom Electronics (Shenzhen) Ltd. +5C925E (base 16) Zioncom Electronics (Shenzhen) Ltd. + A1&A2 Building,Lantian Technology Park, Xinyu Road, Xingqiao Henggang Block, Shajing Street, Baoan District + Shenzhen Guangdong 518000 + CN + +08-4F-A9 (hex) Cisco Systems, Inc +084FA9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +08-4F-F9 (hex) Cisco Systems, Inc +084FF9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +50-98-B8 (hex) New H3C Technologies Co., Ltd +5098B8 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +11-00-AA (hex) Private +1100AA (base 16) Private + +B8-4D-EE (hex) Hisense broadband multimedia technology Co.,Ltd +B84DEE (base 16) Hisense broadband multimedia technology Co.,Ltd + Song ling Road 399 + Qingdao 266000 + CN + +A8-93-52 (hex) SHANGHAI ZHONGMI COMMUNICATION TECHNOLOGY CO.,LTD +A89352 (base 16) SHANGHAI ZHONGMI COMMUNICATION TECHNOLOGY CO.,LTD + RM510,418 Guiping Road,xuhui-Park + shanghai shanghai 200233 + CN + +E4-CC-9D (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +E4CC9D (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +A8-D0-E3 (hex) Systech Electronics Ltd +A8D0E3 (base 16) Systech Electronics Ltd + Lever Tech Centre, 69-71 King Yip Street, + , 852 + HK + +98-BA-39 (hex) Doro AB +98BA39 (base 16) Doro AB + Jörgen Kocksgatan 1B + Malmö Skane 211 20 + SE + +D4-6B-A6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D46BA6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +CC-05-77 (hex) HUAWEI TECHNOLOGIES CO.,LTD +CC0577 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +30-8B-B2 (hex) Cisco Systems, Inc +308BB2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E0-EB-62 (hex) Shanghai Hulu Devices Co., Ltd +E0EB62 (base 16) Shanghai Hulu Devices Co., Ltd + 509 Caobao Road, Rm 101-2 Bld 9 + Shanghai 200233 + CN + +08-68-8D (hex) New H3C Technologies Co., Ltd +08688D (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +E8-6F-38 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +E86F38 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +48-21-6C (hex) China Mobile IOT Company Limited +48216C (base 16) China Mobile IOT Company Limited + Building D3,No.8 Yangliu North Road,Yubei District + CHONGQING CHONGQING 401121 + CN + +8C-BE-24 (hex) Tashang Semiconductor(Shanghai) Co., Ltd. +8CBE24 (base 16) Tashang Semiconductor(Shanghai) Co., Ltd. + Room 903, Building 5, Minggu Science Park,No. 7001, Zhong Chun Road, Minhang District ,Shanghai 201101, P.R. China + Shanghai 123456 + CN + +08-B3-AF (hex) vivo Mobile Communication Co., Ltd. +08B3AF (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +30-86-2D (hex) Arista Network, Inc. +30862D (base 16) Arista Network, Inc. + 5453 Great America Parkway + Santa Clara CA 95054 + US + +6C-E8-C6 (hex) Earda Technologies co Ltd +6CE8C6 (base 16) Earda Technologies co Ltd + Block A,Lianfeng Creative Park, #2 Jisheng Rd., Nansha District + Guangzhou Guangdong 511455 + CN + +1C-41-76 (hex) China Mobile Group Device Co.,Ltd. +1C4176 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +60-8B-0E (hex) Apple, Inc. +608B0E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-71-D5 (hex) Hazens Automotive Electronics(SZ)Co.,Ltd. +1871D5 (base 16) Hazens Automotive Electronics(SZ)Co.,Ltd. + C8 Building, Building 13, Zhongxin Innovation Industry City, No.12, Ganli No.6 Road, Ganli Industrial Park, Buji Street, Longgang District + Shenzhen Guangdong 518100 + CN + +AC-B1-EE (hex) SHENZHEN FENDA TECHNOLOGY CO., LTD +ACB1EE (base 16) SHENZHEN FENDA TECHNOLOGY CO., LTD + Fenda Hi-Tech Park, Zhoushi Road, Shiyan, Baoan + ShenZhen GuangDong 518108 + CN + +F8-AD-CB (hex) HMD Global Oy +F8ADCB (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +D4-62-EA (hex) HUAWEI TECHNOLOGIES CO.,LTD +D462EA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +54-BA-D6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +54BAD6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-DC-4E (hex) AEV, spol. s r. o. +94DC4E (base 16) AEV, spol. s r. o. + Jozky Silneho 2783/9 + Kromeriz 76701 + CZ + +14-42-FC (hex) Texas Instruments +1442FC (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +AC-5D-5C (hex) FN-LINK TECHNOLOGY LIMITED +AC5D5C (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +A4-AE-11 (hex) Hon Hai Precision Ind. Co., Ltd. +A4AE11 (base 16) Hon Hai Precision Ind. Co., Ltd. + GuangDongShenZhen + ShenZhen GuangDong 518109 + CN + +54-DE-D0 (hex) Sevio Srl +54DED0 (base 16) Sevio Srl + Via Dei Caniana 6/A + Bergamo Bergamo 24127 + IT + +6C-5E-3B (hex) Cisco Systems, Inc +6C5E3B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +40-19-20 (hex) Movon Corporation +401920 (base 16) Movon Corporation + 3Fl, Hyunjuk Bldg. 7 selleung-ro, 94gil, Gangnam-gu + Seoul 06161 + KR + +D0-37-45 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +D03745 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +60-3A-7C (hex) TP-LINK TECHNOLOGIES CO.,LTD. +603A7C (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +00-01-78 (hex) MARGI Systems, Inc. +000178 (base 16) MARGI Systems, Inc. + 3155 Kearney Street. - Ste.#200 + Fremont CA 94538 + US + +0C-B7-71 (hex) ARRIS Group, Inc. +0CB771 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +58-C8-76 (hex) China Mobile (Hangzhou) Information Technology Co., Ltd. +58C876 (base 16) China Mobile (Hangzhou) Information Technology Co., Ltd. + No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District + Hangzhou Zhejiang 310000 + CN + +2C-1E-4F (hex) Chengdu Qianli Network Technology Co., Ltd. +2C1E4F (base 16) Chengdu Qianli Network Technology Co., Ltd. + Room 1208, 4 Building, Ideal Center, NO.38 Tianyi Street, Chengdu High-tech Zone + Chengdu Sichuan 610000 + CN + +00-90-52 (hex) SELCOM ELETTRONICA S.R.L. +009052 (base 16) SELCOM ELETTRONICA S.R.L. + VIA GRANDI, 5 + 40013 CASTELMAGGIORE BO + IT + +00-1A-83 (hex) Pegasus Technologies Inc. +001A83 (base 16) Pegasus Technologies Inc. + 108 Pawnook Farm Rd. + Lenoir City TN 37771 + US + +50-E0-85 (hex) Intel Corporate +50E085 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +24-16-6D (hex) HUAWEI TECHNOLOGIES CO.,LTD +24166D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-0B-19 (hex) HUAWEI TECHNOLOGIES CO.,LTD +940B19 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +70-C7-F2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +70C7F2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +38-94-ED (hex) NETGEAR +3894ED (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +70-04-33 (hex) California Things Inc. +700433 (base 16) California Things Inc. + 650 main st + redwood city CA 94063 + US + +DC-A6-32 (hex) Raspberry Pi Trading Ltd +DCA632 (base 16) Raspberry Pi Trading Ltd + Maurice Wilkes Building, Cowley Road + Cambridge CB4 0DS + GB + +88-F5-6E (hex) HUAWEI TECHNOLOGIES CO.,LTD +88F56E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +BC-97-E1 (hex) Broadcom Limited +BC97E1 (base 16) Broadcom Limited + 15191 Alton Parkway + Irvine CA 92618 + US + +28-D1-B7 (hex) Shenzhen YOUHUA Technology Co., Ltd +28D1B7 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +C8-C2-FA (hex) HUAWEI TECHNOLOGIES CO.,LTD +C8C2FA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-B3-62 (hex) Nokia Shanghai Bell Co., Ltd. +88B362 (base 16) Nokia Shanghai Bell Co., Ltd. + No.388 Ning Qiao Road,Jin Qiao Pudong Shanghai 201206,P.R.China + Shanghai Pudong 201206 + CN + +08-47-D0 (hex) Nokia Shanghai Bell Co., Ltd. +0847D0 (base 16) Nokia Shanghai Bell Co., Ltd. + No.388 Ning Qiao Road,Jin Qiao Pudong Shanghai 201206,P.R.China + Shanghai Pudong 201206 + CN + +08-9C-86 (hex) Nokia Shanghai Bell Co., Ltd. +089C86 (base 16) Nokia Shanghai Bell Co., Ltd. + No.388 Ning Qiao Road,Jin Qiao Pudong Shanghai 201206,P.R.China + Shanghai Pudong 201206 + CN + +7C-89-56 (hex) Samsung Electronics Co.,Ltd +7C8956 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +9C-93-E4 (hex) Private +9C93E4 (base 16) Private + +88-29-9C (hex) Samsung Electronics Co.,Ltd +88299C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +CC-90-93 (hex) Hansong Tehnologies +CC9093 (base 16) Hansong Tehnologies + 8 Kangping road, New development zone + Nanjing Jiangsu 210006 + CN + +CC-64-A6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +CC64A6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +30-31-7D (hex) Hosiden Corporation +30317D (base 16) Hosiden Corporation + 4-33, Kitakyuhoji 1-chome + Yao Osaka 5810071 + JP + +F0-A9-68 (hex) Antailiye Technology Co.,Ltd +F0A968 (base 16) Antailiye Technology Co.,Ltd + 7/F,Zhengjiyuan Buiding,2 Road,Qianjing, Xixiang, Baoan District,Shenzhen + SHEN ZHEN GUANGDONG 518000 + CN + +48-E1-E9 (hex) Chengdu Meross Technology Co., Ltd. +48E1E9 (base 16) Chengdu Meross Technology Co., Ltd. + No. 25, Yizhou Avenue, Gaoxin + Chengdu Sichuan 610000 + CN + +D8-13-99 (hex) Hui Zhou Gaoshengda Technology Co.,LTD +D81399 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +54-E0-19 (hex) Ring LLC +54E019 (base 16) Ring LLC + 1523 26th St + Santa Monica CA 90404 + US + +14-84-30 (hex) MITAC COMPUTING TECHNOLOGY CORPORATION +148430 (base 16) MITAC COMPUTING TECHNOLOGY CORPORATION + 3F., NO.1, R&D ROAD 2, HSINCHU SCIENCE PARK + HSINCHU 30076 + TW + +B8-A4-4F (hex) Axis Communications AB +B8A44F (base 16) Axis Communications AB + Emdalavägen 14 + LUND 22369 + SE + +00-24-EB (hex) ClearPath Networks, Inc. +0024EB (base 16) ClearPath Networks, Inc. + 1940 E. Mariposa Ave + El Segundo CA 90245 + US + +50-AF-4D (hex) zte corporation +50AF4D (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +C8-EA-F8 (hex) zte corporation +C8EAF8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +70-9F-2D (hex) zte corporation +709F2D (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +38-3B-26 (hex) Jiangsu Qinheng Co., Ltd. +383B26 (base 16) Jiangsu Qinheng Co., Ltd. + No. 18, Ningshuang Road + Nanjing Jiangsu 210012 + CN + +5C-FA-FB (hex) Acubit +5CFAFB (base 16) Acubit + Afred Nobels Vej 21A + Aalborg Ø 9220 + DK + +9C-7B-EF (hex) Hewlett Packard +9C7BEF (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +74-2E-DB (hex) Perinet GmbH +742EDB (base 16) Perinet GmbH + Rudower Chaussee 29 + Berlin Berlin 12489 + DE + +20-17-42 (hex) LG Electronics +201742 (base 16) LG Electronics + 222 LG-ro, JINWI-MYEON + Pyeongtaek-si Gyeonggi-do 451-713 + KR + +CC-88-26 (hex) LG Innotek +CC8826 (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +EC-5B-73 (hex) Advanced & Wise Technology Corp. +EC5B73 (base 16) Advanced & Wise Technology Corp. + 5F, No. 3-2, Industry East 9th Road, Hsinchu Science Park, + Hsinchu City Hsinchu 30075 + TW + +E0-CB-1D (hex) Private +E0CB1D (base 16) Private + +84-8B-CD (hex) IEEE Registration Authority +848BCD (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +14-C0-3E (hex) ARRIS Group, Inc. +14C03E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +C0-89-AB (hex) ARRIS Group, Inc. +C089AB (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D4-4D-A4 (hex) Murata Manufacturing Co., Ltd. +D44DA4 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +DC-71-96 (hex) Intel Corporate +DC7196 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +F8-E5-CF (hex) CGI IT UK LIMITED +F8E5CF (base 16) CGI IT UK LIMITED + 20 Fenchurch Street, 14th Floor + London EC3M 3BY + GB + +68-82-F2 (hex) grandcentrix GmbH +6882F2 (base 16) grandcentrix GmbH + Holzmarkt 1 + Cologne NW 50676 + DE + +D4-20-B0 (hex) Mist Systems, Inc. +D420B0 (base 16) Mist Systems, Inc. + 1601 South De Anza Blvd, Suite 248 + Cupertino CA 95014 + US + +08-ED-ED (hex) Zhejiang Dahua Technology Co., Ltd. +08EDED (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199,Waterfront Road + Hangzhou Zhejiang 310053 + CN + +60-92-F5 (hex) ARRIS Group, Inc. +6092F5 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-22-AF (hex) Safety Vision, LLC +0022AF (base 16) Safety Vision, LLC + 6100 W. Sam Houston Pkwy. North + Houston 77041 + US + +A0-91-A2 (hex) OnePlus Electronics (Shenzhen) Co., Ltd. +A091A2 (base 16) OnePlus Electronics (Shenzhen) Co., Ltd. + Room 201, Block A, No.1, 1st Qian Wan Road, Qianhai Shenzhen-Hong Kong Cooperation Zone, Shenzhen, China. + Shenzhen Guangdong 518000 + CN + +00-80-B5 (hex) UNITED NETWORKS INC. +0080B5 (base 16) UNITED NETWORKS INC. + 2178 PARAGON DRIVE + SAN JOSE CA 95131 + US + +B8-08-CF (hex) Intel Corporate +B808CF (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +1C-69-7A (hex) EliteGroup Computer Systems Co., LTD +1C697A (base 16) EliteGroup Computer Systems Co., LTD + No.239, Sec. 2, TiDing Blvd. Nei-Hu Dist. + Taipei Taiwan 11439 + TW + +4C-17-44 (hex) Amazon Technologies Inc. +4C1744 (base 16) Amazon Technologies Inc. + P.O. Box 8102 + Reno NV 89507 + US + +B0-30-55 (hex) China Mobile IOT Company Limited +B03055 (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +90-5C-34 (hex) Sirius Electronic Systems Srl +905C34 (base 16) Sirius Electronic Systems Srl + via Robinie, 33 + Gravellona Toce VB 28883 + IT + +D4-6A-35 (hex) Cisco Systems, Inc +D46A35 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D0-9C-7A (hex) Xiaomi Communications Co Ltd +D09C7A (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +C8-2C-2B (hex) IEEE Registration Authority +C82C2B (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +80-20-DA (hex) Sagemcom Broadband SAS +8020DA (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +68-84-7E (hex) FUJITSU LIMITED +68847E (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +00-30-85 (hex) Cisco Systems, Inc +003085 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +60-5F-8D (hex) eero inc. +605F8D (base 16) eero inc. + 500 Howard Street, Suite 900 + SAN FRANCISCO CA 94105 + US + +C4-B3-6A (hex) Cisco Systems, Inc +C4B36A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +70-F7-54 (hex) AMPAK Technology,Inc. +70F754 (base 16) AMPAK Technology,Inc. + 3F, No.15-1 Zhonghua Road, Hsinchu Industrail Park, Hukou, + Hsinchu Hsinchu,Taiwan R.O.C. 30352 + TW + +6C-8B-D3 (hex) Cisco Systems, Inc +6C8BD3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +68-97-4B (hex) Shenzhen Costar Electronics Co. Ltd. +68974B (base 16) Shenzhen Costar Electronics Co. Ltd. + No.94 Fuyuan 1st Road,Yuyuan Industrial Park, + Shenzhen Guangdong 518103 + CN + +34-E1-D1 (hex) IEEE Registration Authority +34E1D1 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-21-B7 (hex) LEXMARK INTERNATIONAL, INC. +0021B7 (base 16) LEXMARK INTERNATIONAL, INC. + 740 West New Circle Road + Lexington KY 40550 + US + +00-A0-B0 (hex) I-O DATA DEVICE,INC. +00A0B0 (base 16) I-O DATA DEVICE,INC. + 24-1, SAKURADA-MACHI + KANAZAWA, ISHIKAWA 920 na + JP + +24-79-F3 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +2479F3 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +80-A2-35 (hex) Edgecore Networks Corporation +80A235 (base 16) Edgecore Networks Corporation + 1 Creation RD 3. + Hsinchu 30077 + TW + +C8-C6-4A (hex) Flextronics Tech.(Ind) Pvt Ltd +C8C64A (base 16) Flextronics Tech.(Ind) Pvt Ltd + SURVEYNO.381, PADUR ROAD, KUTHAMBAKKAM VILLAGE, 602107 POONAMALLEE TALUK, THIRUVALLUR DISTRIC + Chennai 602107 + IN + +30-EA-26 (hex) Sycada BV +30EA26 (base 16) Sycada BV + Burgemeester Stramanweg 105B + Amsterdam 1101 AA + NL + +9C-49-7F (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +9C497F (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +C4-E3-9F (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +C4E39F (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +F8-9A-78 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F89A78 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-F8-72 (hex) HUAWEI TECHNOLOGIES CO.,LTD +88F872 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +EC-56-23 (hex) HUAWEI TECHNOLOGIES CO.,LTD +EC5623 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +54-86-BC (hex) Cisco Systems, Inc +5486BC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +40-23-43 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +402343 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +18-F1-8E (hex) ChipER Technology co. ltd +18F18E (base 16) ChipER Technology co. ltd + 907 University Ave#299 + Middleton WI 53562 + US + +00-04-22 (hex) Studio Technologies, Inc +000422 (base 16) Studio Technologies, Inc + 7440 Frontage Rd + Skokie IL 60077-3212 + US + +80-DA-13 (hex) eero inc. +80DA13 (base 16) eero inc. + 660 3rd Street + San Francisco CA 94107 + US + +50-EC-50 (hex) Beijing Xiaomi Mobile Software Co., Ltd +50EC50 (base 16) Beijing Xiaomi Mobile Software Co., Ltd + The Rainbow City Office Building, 68 Qinghe Middle Street Haidian District + Beijing Beijing 100085 + CN + +60-61-DF (hex) Z-meta Research LLC +6061DF (base 16) Z-meta Research LLC + 8365 Quay Drive + Arvada CO 80003 + US + +70-57-BF (hex) New H3C Technologies Co., Ltd +7057BF (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +8C-E7-48 (hex) Private +8CE748 (base 16) Private + +10-82-86 (hex) Luxshare Precision Industry Co.,Ltd +108286 (base 16) Luxshare Precision Industry Co.,Ltd + 2nd floor, A building, Sanyo New Industrial Area, West of Maoyi, Shajing Baoan District + Shenzhen Shenzhen 518104 + CN + +14-B4-57 (hex) Silicon Laboratories +14B457 (base 16) Silicon Laboratories + 7000 W. William Cannon Dr. + Austin TX 78735 + US + +DC-96-2C (hex) NST Audio Ltd +DC962C (base 16) NST Audio Ltd + 32 Whitewall + Norton North Yorkshire YO17 9EH + GB + +18-02-2D (hex) HUAWEI TECHNOLOGIES CO.,LTD +18022D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D8-BC-59 (hex) Shenzhen DAPU Microelectronics Co., Ltd +D8BC59 (base 16) Shenzhen DAPU Microelectronics Co., Ltd + Room B 503, No.2 Building, Tian’an Digital New Town, Huangge Middle Road, Longgang District + Shenzhen Guangdong 518100 + CN + +08-97-98 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +089798 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +24-6F-28 (hex) Espressif Inc. +246F28 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +8C-79-F5 (hex) Samsung Electronics Co.,Ltd +8C79F5 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +48-F8-DB (hex) HUAWEI TECHNOLOGIES CO.,LTD +48F8DB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-12-2A (hex) VTech Telecommunications Ltd. +00122A (base 16) VTech Telecommunications Ltd. + 23/F, Tai Ping Industrial Centre, Block 1 + NA 00000 + HK + +B0-51-8E (hex) Holl technology CO.Ltd. +B0518E (base 16) Holl technology CO.Ltd. + F2,Bld 27,Anle Industrial Park,Nantou Guankou No.2 Road + Shenzhen Guangdong 518052 + CN + +68-17-29 (hex) Intel Corporate +681729 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +28-52-E0 (hex) Layon international Electronic & Telecom Co.,Ltd +2852E0 (base 16) Layon international Electronic & Telecom Co.,Ltd + 4rd Floor, Building 15, Juda Industrial Zone, ShiBei Industrial Road, HuiJiang , Da Shi Street, PanYu District,Guangzhou,China + guangzhou guangdong 511430 + CN + +58-CB-52 (hex) Google, Inc. +58CB52 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +7C-61-66 (hex) Amazon Technologies Inc. +7C6166 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +98-9B-CB (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +989BCB (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +94-F7-AD (hex) Juniper Networks +94F7AD (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +60-63-F9 (hex) Ciholas, Inc. +6063F9 (base 16) Ciholas, Inc. + 3700 Bell Rd + Newburgh IN 47630-7907 + US + +AC-8F-F8 (hex) Nokia +AC8FF8 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +60-03-A6 (hex) Inteno Broadband Technology AB +6003A6 (base 16) Inteno Broadband Technology AB + Stensätravägen 13 + Skärholmen SE 127 39 + SE + +7C-52-59 (hex) Sichuan Jiuzhou Electronic Technology Co., Ltd. +7C5259 (base 16) Sichuan Jiuzhou Electronic Technology Co., Ltd. + No. 259, Jiuzhou Road + Mianyang City Sichuan Province 621000 + CN + +44-B2-95 (hex) Sichuan AI-Link Technology Co., Ltd. +44B295 (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou,Industrial Park + Anzhou,Industrial Park Sichuan 621000 + CN + +94-24-E1 (hex) Alcatel-Lucent Enterprise +9424E1 (base 16) Alcatel-Lucent Enterprise + 26801 West Agoura Rd + Calabasas CA 91301 + US + +F8-CA-59 (hex) NetComm Wireless +F8CA59 (base 16) NetComm Wireless + LEVEL 5, 18-20 ORION RD. LANE COVE + LANE COVE WEST NSW 2066 + AU + +88-B2-91 (hex) Apple, Inc. +88B291 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C4-2A-D0 (hex) Apple, Inc. +C42AD0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +CC-D2-81 (hex) Apple, Inc. +CCD281 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-0D-B0 (hex) Shenzhen Four Seas Global Link Network Technology Co., Ltd. +200DB0 (base 16) Shenzhen Four Seas Global Link Network Technology Co., Ltd. + Room 607-610, Block B, TAOJINDI Electronic Business Incubation Base + Tenglong Road, Longhua District, Shenzhen Guangdong 518000 + CN + +D8-1E-DD (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +D81EDD (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +D4-3F-CB (hex) ARRIS Group, Inc. +D43FCB (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +5C-76-95 (hex) Technicolor CH USA Inc. +5C7695 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +F8-4D-33 (hex) Fiberhome Telecommunication Technologies Co.,LTD +F84D33 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +C0-8A-CD (hex) Guangzhou Shiyuan Electronic Technology Company Limited +C08ACD (base 16) Guangzhou Shiyuan Electronic Technology Company Limited + No.6, 4th Yunpu Road, Yunpu industry District + Guangzhou Guangdong 510530 + CN + +AC-F6-F7 (hex) LG Electronics (Mobile Communications) +ACF6F7 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +E8-9E-0C (hex) Private +E89E0C (base 16) Private + +48-E6-C0 (hex) SIMCom Wireless Solutions Co.,Ltd. +48E6C0 (base 16) SIMCom Wireless Solutions Co.,Ltd. + Building B,SIM Technology Building,No.633,Jinzhong Road + Shanghai 200335 + CN + +38-3C-9C (hex) Fujian Newland Payment Technology Co.,Ltd. +383C9C (base 16) Fujian Newland Payment Technology Co.,Ltd. + No. B602,Building #1,Haixia Jingmao Plaza,Fuzhou Bonded Area + Fuzhou Fujian 350015 + CN + +C0-2E-25 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +C02E25 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +10-77-17 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD +107717 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + Unit East Block22-24/F,Skyworth semiconductor design Bldg., Gaoxin Ave.4.S.,Nanshan District,Shenzhen,China + SHENZHEN GUANGDONG 518057 + CN + +A8-6D-5F (hex) Raisecom Technology CO., LTD +A86D5F (base 16) Raisecom Technology CO., LTD + No. 11, East Area, No. 10 Block, East Xibeiwang Road + Beijing 100094 + CN + +58-EC-ED (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +58ECED (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +A4-68-BC (hex) Private +A468BC (base 16) Private + +00-50-79 (hex) Private +005079 (base 16) Private + +10-0C-6B (hex) NETGEAR +100C6B (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +50-5F-B5 (hex) Askey Computer Corp. +505FB5 (base 16) Askey Computer Corp. + 10F, NO. 119, JIANKANG RD., ZHONGHE DIST. + NEW TAIPEI 235 + TW + +C4-F0-EC (hex) Fiberhome Telecommunication Technologies Co.,LTD +C4F0EC (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +E8-0F-C8 (hex) Universal Electronics, Inc. +E80FC8 (base 16) Universal Electronics, Inc. + 201 E. Sandpointe Ave + Santa Ana CA 92707 + US + +E4-5D-37 (hex) Juniper Networks +E45D37 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-EE-AB (hex) Cisco Systems, Inc +00EEAB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +54-A7-03 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +54A703 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +90-7A-58 (hex) Zegna-Daidong Limited +907A58 (base 16) Zegna-Daidong Limited + Rooms 14-17, 18/F, Nan Fung Commercial, Centre 19 Lam Lok Street, Kowloon Bay + Hong Kong 999077 + HK + +E0-09-BF (hex) SHENZHEN TONG BO WEI TECHNOLOGY Co.,LTD +E009BF (base 16) SHENZHEN TONG BO WEI TECHNOLOGY Co.,LTD + 5th floor building 4 pengtengda industrial,langkou community,dalang street longhua newly developed area + Shenzhen GuangDong 518000 + CN + +00-13-1E (hex) peiker acustic GmbH +00131E (base 16) peiker acustic GmbH + Max-Planck-Strasse 28-32 + Friedrichsdorf 61381 + DE + +84-69-91 (hex) Nokia +846991 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +00-1B-F7 (hex) Lund IP Products AB +001BF7 (base 16) Lund IP Products AB + Dalbyv. 1 + Lund Skåne 224 60 + SE + +78-36-07 (hex) Cermate Technologies Inc. +783607 (base 16) Cermate Technologies Inc. + 7F-1, No 168 Lien-Chen Rd. + Chung-Ho Dist New Taipei City + TW + +B0-00-73 (hex) Wistron Neweb Corporation +B00073 (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +D8-8D-C8 (hex) Atil Technology Co., LTD +D88DC8 (base 16) Atil Technology Co., LTD + Rm. 3, 21F., No.93, Sec. 2, Roosevelt Rd., + Da’an Dist., Taipei City 106 + TW + +D0-AB-D5 (hex) Intel Corporate +D0ABD5 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +88-DE-7C (hex) Askey Computer Corp. +88DE7C (base 16) Askey Computer Corp. + 10F, No.119, JIANKANG RD.,ZHINGHE DIST, + NEW TAIPEI CITY 23585 + TW + +A8-E2-C1 (hex) Texas Instruments +A8E2C1 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +90-9A-77 (hex) Texas Instruments +909A77 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +04-EE-03 (hex) Texas Instruments +04EE03 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +4C-24-98 (hex) Texas Instruments +4C2498 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +7C-D9-5C (hex) Google, Inc. +7CD95C (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +C8-AA-CC (hex) Private +C8AACC (base 16) Private + +00-21-67 (hex) HWA JIN T&I Corp. +002167 (base 16) HWA JIN T&I Corp. + 5F., SEHWA Bldg 164-24, Poi-dong, Gangnam-gu, Seoul, Korea + Gangnam-gu Seoul 135-960 + KR + +00-0B-86 (hex) Aruba, a Hewlett Packard Enterprise Company +000B86 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +DC-31-D1 (hex) vivo Mobile Communication Co., Ltd. +DC31D1 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +C8-F7-50 (hex) Dell Inc. +C8F750 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +D4-92-34 (hex) NEC Corporation +D49234 (base 16) NEC Corporation + 7-1 Shiba 5-chome + Minato-Ku Tokyo 108-8001 + JP + +00-07-CB (hex) FREEBOX SAS +0007CB (base 16) FREEBOX SAS + 8 rue de la Ville l'Eveque + Paris 75008 + FR + +14-9F-B6 (hex) GUANGDONG GENIUS TECHNOLOGY CO., LTD. +149FB6 (base 16) GUANGDONG GENIUS TECHNOLOGY CO., LTD. + #126,BBK Road,Wusha,Chang'An + Dong Guan Guang Dong 523860 + CN + +00-11-5A (hex) Ivoclar Vivadent AG +00115A (base 16) Ivoclar Vivadent AG + Bendererstrasse 2 + Schaan 9494 + LI + +4C-AE-A3 (hex) Hewlett Packard Enterprise +4CAEA3 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +1C-2E-1B (hex) Suzhou Tremenet Communication Technology Co., Ltd. +1C2E1B (base 16) Suzhou Tremenet Communication Technology Co., Ltd. + Room 413, Nangong Building, 399 Linquan Street, SIP + Suzhou Jiangsu 215123 + CN + +1C-24-EB (hex) Burlywood +1C24EB (base 16) Burlywood + 1501 S Sunset Street + Longmont CO 80501 + US + +00-10-13 (hex) Kontron America, Inc. +001013 (base 16) Kontron America, Inc. + 14118 Stowe Drive + Poway, CA 9206 + US + +2C-2B-F9 (hex) LG Innotek +2C2BF9 (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +D8-C7-C8 (hex) Aruba, a Hewlett Packard Enterprise Company +D8C7C8 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +70-3A-0E (hex) Aruba, a Hewlett Packard Enterprise Company +703A0E (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +20-4C-03 (hex) Aruba, a Hewlett Packard Enterprise Company +204C03 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +58-C6-F0 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +58C6F0 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +84-A0-6E (hex) Sagemcom Broadband SAS +84A06E (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +A4-3E-A0 (hex) iComm HK LIMITED +A43EA0 (base 16) iComm HK LIMITED + Room 702 Kowloon Building 555 Nathan Road Kowloon HongKong + Kowloon NA + HK + +64-C2-DE (hex) LG Electronics (Mobile Communications) +64C2DE (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +8C-44-4F (hex) HUMAX Co., Ltd. +8C444F (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +00-67-62 (hex) Fiberhome Telecommunication Technologies Co.,LTD +006762 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +2C-C4-07 (hex) machineQ +2CC407 (base 16) machineQ + 1900 market st + philadelphia PA 19103 + US + +B4-ED-19 (hex) Pie Digital, Inc. +B4ED19 (base 16) Pie Digital, Inc. + 575 Market st., 8th floor + San Francisco CA 94105-2823 + US + +40-DF-02 (hex) LINE BIZ Plus +40DF02 (base 16) LINE BIZ Plus + Alphadom Tower IV (6F), Bundangnaegok-ro 117, Bundang-gu + Seongnam Gyeonggi 13529 + KR + +D4-3B-04 (hex) Intel Corporate +D43B04 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +CC-E1-94 (hex) Juniper Networks +CCE194 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +90-02-18 (hex) BSkyB Ltd +900218 (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +14-4E-2A (hex) Ciena Corporation +144E2A (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +84-13-9F (hex) zte corporation +84139F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +F0-51-EA (hex) Fitbit, Inc. +F051EA (base 16) Fitbit, Inc. + 199 Fremont Street, 14th Fl + San Francisco CA 94105 + US + +50-33-F0 (hex) YICHEN (SHENZHEN) TECHNOLOGY CO.LTD +5033F0 (base 16) YICHEN (SHENZHEN) TECHNOLOGY CO.LTD + 23F, Building C1, Nanshan iPark, No. 1001 Xueyuan Road, Nanshan District, Shenzhen City, Guangdong, China + shenzhen 518044 + CN + +FC-2B-B2 (hex) Actiontec Electronics, Inc +FC2BB2 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +E0-9F-2A (hex) Iton Technology Corp. +E09F2A (base 16) Iton Technology Corp. + Room 1302, Block A, Building 4,Huangge Road, Longgang District + Shenzhen Guangdong 518116 + CN + +4C-E1-9E (hex) TECNO MOBILE LIMITED +4CE19E (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +74-95-EC (hex) ALPS ELECTRIC CO., LTD. +7495EC (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + Kakuda Miyagi-Pref 981-1595 + JP + +AC-5A-EE (hex) China Mobile Group Device Co.,Ltd. +AC5AEE (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +70-BC-10 (hex) Microsoft Corporation +70BC10 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +88-4A-18 (hex) Opulinks +884A18 (base 16) Opulinks + F 28, No.328, Huashan Rd + Shanghai 200040 + CN + +00-06-F7 (hex) ALPS ELECTRIC CO., LTD. +0006F7 (base 16) ALPS ELECTRIC CO., LTD. + 6-3-36 Furukawanakazato, + Osaki Miyagi-pref 989-6181 + JP + +00-07-04 (hex) ALPS ELECTRIC CO., LTD. +000704 (base 16) ALPS ELECTRIC CO., LTD. + 6-3-36 Furukawanakazato, + Osaki Miyagi-pref 989-6181 + JP + +00-06-F5 (hex) ALPS ELECTRIC CO., LTD. +0006F5 (base 16) ALPS ELECTRIC CO., LTD. + 6-3-36 Furukawanakazato, + Osaki Miyagi-pref 989-6181 + JP + +34-C7-31 (hex) ALPS ELECTRIC CO., LTD. +34C731 (base 16) ALPS ELECTRIC CO., LTD. + 6-3-36 Furukawanakazato, + Osaki Miyagi-pref 989-6181 + JP + +9C-69-B4 (hex) IEEE Registration Authority +9C69B4 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +50-00-84 (hex) Siemens Canada +500084 (base 16) Siemens Canada + 300 Applewood Crescent + Concord Ontario L4K 5C7 + CA + +64-D4-BD (hex) ALPS ELECTRIC CO., LTD. +64D4BD (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + KAKUDA-CITY MIYAGI-PREF 981-1595 + JP + +04-98-F3 (hex) ALPS ELECTRIC CO., LTD. +0498F3 (base 16) ALPS ELECTRIC CO., LTD. + 6-1 NISHIDA + KAKUDA MIYAGI PREF 9876-8501 + JP + +00-21-4F (hex) ALPS ELECTRIC CO., LTD. +00214F (base 16) ALPS ELECTRIC CO., LTD. + 1-2-1, Okinouchi, + Soma-city, Fukushima-pref., 976-8501 + JP + +44-B4-33 (hex) tide.co.,ltd +44B433 (base 16) tide.co.,ltd + 9F Kapeul GreatValley A-dong, Digitalro 9-ghil 32, Geumcheon-gu + seoul seoul ASIKRKS006 + KR + +D8-A6-FD (hex) Ghost Locomotion +D8A6FD (base 16) Ghost Locomotion + 800 California St. Suite 200 + Mountain View CA 94041 + US + +DC-21-B9 (hex) Sentec Co.Ltd +DC21B9 (base 16) Sentec Co.Ltd + 10, Baekseokgongdan 1-ro, Seobuk-gu + Cheonan-si Chungcheongnam-do 31094 + KR + +6C-DF-FB (hex) IEEE Registration Authority +6CDFFB (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +24-7D-4D (hex) Texas Instruments +247D4D (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +88-50-F6 (hex) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd +8850F6 (base 16) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + 3/F,A5 Building Zhiyuan Community No.1001,Xueyuan Road Nanshan Distric + Shenzhen Guangdong 518055 + CN + +E4-98-BB (hex) Phyplus Microelectronics Limited +E498BB (base 16) Phyplus Microelectronics Limited + 304 Building 1 No.608 Sheng Xia Road + Shanghai 200000 + CN + +60-A1-1E (hex) Wuhan Maxsine Electric Co.,Ltd. +60A11E (base 16) Wuhan Maxsine Electric Co.,Ltd. + Building A6, Hangyu Building, No 7, Wuhan University Science Park Road, East Lake Development District,Wuhan,China. + Wuhan Hubei 430000 + CN + +C4-5B-F7 (hex) ants +C45BF7 (base 16) ants + 1164-21,Haeun-daero, Haeundae-gu, + Busan 48069 + KR + +8C-DF-9D (hex) NEC Corporation +8CDF9D (base 16) NEC Corporation + 7-1, Shiba 5-chome, + Tokyo Tokyo 108-8001 + JP + +5C-41-5A (hex) Amazon.com, LLC +5C415A (base 16) Amazon.com, LLC + 1200 12th Ave. South, Suite 1200 + Seattle 98144 + US + +70-5E-55 (hex) Realme Chongqing MobileTelecommunications Corp Ltd +705E55 (base 16) Realme Chongqing MobileTelecommunications Corp Ltd + No.24 Nichang Boulevard, Huixing Block, Yubei District, Chongqing. + Chongqing China 401120 + CN + +B0-D5-68 (hex) Shenzhen Cultraview Digital Technology Co., Ltd +B0D568 (base 16) Shenzhen Cultraview Digital Technology Co., Ltd + F6,M6,Maqueling, High-tech park, Nanshan district + Shenzhen Guangdong 518057 + CN + +F0-0E-BF (hex) ZettaHash Inc. +F00EBF (base 16) ZettaHash Inc. + 6F Chiyoda Ogawamachi Crosta, 1-11, Kanda Ogawamachi + Chiyoda-ku Tokyo 101-0052 + JP + +70-35-09 (hex) Cisco Systems, Inc +703509 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +04-EA-56 (hex) Intel Corporate +04EA56 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +D0-C6-37 (hex) Intel Corporate +D0C637 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +44-1A-FA (hex) New H3C Technologies Co., Ltd +441AFA (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +04-07-2E (hex) VTech Electronics Ltd. +04072E (base 16) VTech Electronics Ltd. + 23rd Floor, Block 1, Tai Ping Industrial Centre, 57 Ting Kok Road + Tai Po, N.T. NA + HK + +78-0E-D1 (hex) TRUMPF Werkzeugmaschinen GmbH+Co.KG +780ED1 (base 16) TRUMPF Werkzeugmaschinen GmbH+Co.KG + Johann-Maus-Straße 2 + Ditzingen 71254 + DE + +44-EC-CE (hex) Juniper Networks +44ECCE (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +F8-2F-08 (hex) Molex CMS +F82F08 (base 16) Molex CMS + 2222 Wellington Court + Lisle IL 60532 + US + +44-1C-12 (hex) Technicolor CH USA Inc. +441C12 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +44-28-A3 (hex) Jiangsu fulian Communication Technology Co., Ltd. +4428A3 (base 16) Jiangsu fulian Communication Technology Co., Ltd. + The south of lanling road, yongan new district + Danyang Jiangsu 212300 + CN + +10-C5-95 (hex) Lenovo +10C595 (base 16) Lenovo + 1009 Think Place + Morrisvilee NC 27560 + US + +20-32-33 (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD +203233 (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD + NO.268, Fuqian Rd, Jutang community, Guanlan Town, Longhua New district + shenzhen guangdong 518000 + CN + +68-29-DC (hex) Ficosa Electronics S.L.U. +6829DC (base 16) Ficosa Electronics S.L.U. + Pol.Ind Can Mitjans s/n Viladecavalls Barcelona + Viladecavalls Barcelona ES08232 + ES + +94-54-DF (hex) YST CORP. +9454DF (base 16) YST CORP. + A-1407, 767, Sinsu-ro, Suji-gu, + Yongin-si Gyeonggi-do 16827 + KR + +7C-BC-84 (hex) IEEE Registration Authority +7CBC84 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F8-0D-F1 (hex) Sontex SA +F80DF1 (base 16) Sontex SA + rue de la gare + sonceboz Bern 2605 + CH + +A4-94-26 (hex) Elgama-Elektronika Ltd. +A49426 (base 16) Elgama-Elektronika Ltd. + Visoriu str. 2 + Vilnius LT-08300 + LT + +E4-F1-4C (hex) Private +E4F14C (base 16) Private + +A8-B4-56 (hex) Cisco Systems, Inc +A8B456 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +2C-A9-F0 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +2CA9F0 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +54-9B-72 (hex) Ericsson AB +549B72 (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +A0-47-D7 (hex) Best IT World (India) Pvt Ltd +A047D7 (base 16) Best IT World (India) Pvt Ltd + 87, Mistry Complex,, Midc Cross Road A, Andheri-East + Mumbai Maharashtra 400093 + IN + +68-99-CD (hex) Cisco Systems, Inc +6899CD (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +10-40-F3 (hex) Apple, Inc. +1040F3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +58-6B-14 (hex) Apple, Inc. +586B14 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-B8-63 (hex) Apple, Inc. +BCB863 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-1C-F6 (hex) Alien Green LLC +2C1CF6 (base 16) Alien Green LLC + A. Kazbegi Ave., No24g, apt 227 + Tbilisi Tbilisi 0160 + GE + +6C-2B-59 (hex) Dell Inc. +6C2B59 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +44-E6-6E (hex) Apple, Inc. +44E66E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-E8-62 (hex) Apple, Inc. +C0E862 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-06-16 (hex) Apple, Inc. +F40616 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +0C-FE-5D (hex) IEEE Registration Authority +0CFE5D (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +3C-8D-20 (hex) Google, Inc. +3C8D20 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +60-1D-91 (hex) Motorola Mobility LLC, a Lenovo Company +601D91 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +D4-C9-4B (hex) Motorola Mobility LLC, a Lenovo Company +D4C94B (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +08-35-1B (hex) Shenzhen Jialihua Electronic Technology Co., Ltd +08351B (base 16) Shenzhen Jialihua Electronic Technology Co., Ltd + Building 26,Xin'e Industrial Area,E'gongling Village,Pinghu Town,Longgang District + Shenzhen Guangdong 518111 + CN + +AC-15-85 (hex) silergy corp +AC1585 (base 16) silergy corp + Oleander Way,802 West Bay Road,P.O. BOX 32052 + Grand Cayman KYI-1208,Cayman Islands 32052 + US + +AC-50-93 (hex) Magna Electronics Europe GmbH & Co. OHG +AC5093 (base 16) Magna Electronics Europe GmbH & Co. OHG + Kurfürst-Eppstein-Ring 9 + Sailauf Bavaria 63877 + DE + +70-BB-E9 (hex) Xiaomi Communications Co Ltd +70BBE9 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +50-A0-A4 (hex) Nokia +50A0A4 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +00-D0-2D (hex) Resideo +00D02D (base 16) Resideo + 2 Corporate Center Dr. + Melville NY 11747 + US + +80-69-40 (hex) LEXAR CO.,LIMITED +806940 (base 16) LEXAR CO.,LIMITED + 10TH FLOOR,CHINA AEROSPACE CENTRE,143 HOI BUN ROAD,KWUN TONG,KOWLOON, HONG KONG + HONG KONG 999077 + HK + +64-F8-1C (hex) Huawei Technologies Co., Ltd. +64F81C (base 16) Huawei Technologies Co., Ltd. + Bantian, Longgang District, Shenzhen, 518129, P.R.C + Shenzhen GUANGDONG Province 518000 + CN + +10-98-C3 (hex) Murata Manufacturing Co., Ltd. +1098C3 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +9C-C8-FC (hex) ARRIS Group, Inc. +9CC8FC (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +B0-7E-11 (hex) Texas Instruments +B07E11 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +10-C7-53 (hex) Qingdao Intelligent&Precise Electronics Co.,Ltd. +10C753 (base 16) Qingdao Intelligent&Precise Electronics Co.,Ltd. + No.218 Qianwangang Road + Qingdao Shangdong 266510 + CN + +F4-95-1B (hex) Hefei Radio Communication Technology Co., Ltd +F4951B (base 16) Hefei Radio Communication Technology Co., Ltd + No.108, YinXing Road, High-tech Development Zone + Hefei Anhui 230088 + CN + +6C-38-45 (hex) Fiberhome Telecommunication Technologies Co.,LTD +6C3845 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +2C-61-04 (hex) SHENZHEN FENGLIAN TECHNOLOGY CO., LTD. +2C6104 (base 16) SHENZHEN FENGLIAN TECHNOLOGY CO., LTD. + ORIENTAL CYBERPORT, HIGHTECH 6 ROAD + SHENZHEN GUANGDONG 518057 + CN + +BC-93-25 (hex) Ningbo Joyson Preh Car Connect Co.,Ltd. +BC9325 (base 16) Ningbo Joyson Preh Car Connect Co.,Ltd. + No. 99, Qingyi Road + Ningbo Zhejiang 315040 + CN + +D0-B6-0A (hex) Xingluo Technology Company Limited +D0B60A (base 16) Xingluo Technology Company Limited + 28F, Building A, Aerospace Science And Technology Square, Nanshan District + ShenZhen GuangDong 518067 + CN + +04-92-26 (hex) ASUSTek COMPUTER INC. +049226 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +E8-AD-A6 (hex) Sagemcom Broadband SAS +E8ADA6 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +0C-1C-19 (hex) LONGCONN ELECTRONICS(SHENZHEN) CO.,LTD +0C1C19 (base 16) LONGCONN ELECTRONICS(SHENZHEN) CO.,LTD + Building B, No. 42 Xingye Road, Phoenix First Industrial Zone, Fuyong, Baoan District + Shenzhen Guangdong 518103 + CN + +90-E7-10 (hex) New H3C Technologies Co., Ltd +90E710 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +30-29-52 (hex) Hillstone Networks Inc +302952 (base 16) Hillstone Networks Inc + North Olympic Science & Technology Park Building #20, Floor #5, SouthBaosheng + Beijing 100192 + CN + +E0-13-B5 (hex) vivo Mobile Communication Co., Ltd. +E013B5 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +E0-79-5E (hex) Wuxi Xiaohu Technology Co.,Ltd. +E0795E (base 16) Wuxi Xiaohu Technology Co.,Ltd. + FL.2, Building A10, 777 West Jianzhu Road, Binhu District + Wuxi Jiangsu Province 214000 + CN + +00-B1-E3 (hex) Cisco Systems, Inc +00B1E3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A4-11-94 (hex) Lenovo +A41194 (base 16) Lenovo + 1009 Think Place + Morrisvilee NC 27560 + US + +00-CB-00 (hex) Private +00CB00 (base 16) Private + +DC-F4-01 (hex) Dell Inc. +DCF401 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +0C-41-01 (hex) Ruichi Auto Technology (Guangzhou) Co., Ltd. +0C4101 (base 16) Ruichi Auto Technology (Guangzhou) Co., Ltd. + No. 171 Haibin Road, Nansha District, Guangzhou, China + Guangzhou Guangdong Province 511400 + CN + +00-B7-71 (hex) Cisco Systems, Inc +00B771 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E4-B2-FB (hex) Apple, Inc. +E4B2FB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-CA-0C (hex) WITHUS PLANET +2CCA0C (base 16) WITHUS PLANET + 1604, O'BIZTOWER, Pyeong Chon, 126, Beolmal-ro, Dongan-gu + Anyang-si Gyeonggi-do 14057 + KR + +84-32-6F (hex) GUANGZHOU AVA ELECTRONICS TECHNOLOGY CO.,LTD +84326F (base 16) GUANGZHOU AVA ELECTRONICS TECHNOLOGY CO.,LTD + Science town luogang district guangzhou city branch bead road 232 profit people park 301, building 2 + guangzhou guangdong 510000 + CN + +C8-9C-13 (hex) Inspiremobile +C89C13 (base 16) Inspiremobile + Rm1412, Daeryung Techno-Town, 15th, 401 , Simin-daero, Dongan-gu + Anyang-si Gyeonggi-do 14057 + KR + +8C-85-E6 (hex) Cleondris GmbH +8C85E6 (base 16) Cleondris GmbH + Zuercherstrasse 42 + Uitikon ZH 8142 + CH + +80-7D-14 (hex) HUAWEI TECHNOLOGIES CO.,LTD +807D14 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +20-28-3E (hex) HUAWEI TECHNOLOGIES CO.,LTD +20283E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-FC-77 (hex) Mega Well Limited +A4FC77 (base 16) Mega Well Limited + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +4C-56-9D (hex) Apple, Inc. +4C569D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-53-9C (hex) Apple, Inc. +38539C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-26-19 (hex) Apple, Inc. +402619 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-E8-5C (hex) Apple, Inc. +6CE85C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-91-62 (hex) Microchip Technology Inc. +049162 (base 16) Microchip Technology Inc. + 2355 W. Chandler Blvd. + Chandler AZ 85224 + US + +F8-38-80 (hex) Apple, Inc. +F83880 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-79-D7 (hex) Sagemcom Broadband SAS +2C79D7 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +00-B4-F5 (hex) DongGuan Siyoto Electronics Co., Ltd +00B4F5 (base 16) DongGuan Siyoto Electronics Co., Ltd + Hecheng Industrial District, QiaoTou Town + DongGuan City Guangdong 523520 + CN + +BC-3F-4E (hex) Teleepoch Ltd +BC3F4E (base 16) Teleepoch Ltd + No.13 Langshan Rd,HiTech Park,Nanshan District + Shenzhen Guangdong 518000 + CN + +18-38-AE (hex) CONSPIN SOLUTION +1838AE (base 16) CONSPIN SOLUTION + 2F, Geonwoong Bldg. 109, Gwanak-ro, Gwanak-gu + Seoul 08833 + KR + +04-CF-8C (hex) XIAOMI Electronics,CO.,LTD +04CF8C (base 16) XIAOMI Electronics,CO.,LTD + Xiaomi Building, No.68 Qinghe Middle Street + Haidian District Beijing 100085 + CN + +0C-75-12 (hex) Shenzhen Kunlun TongTai Technology Co.,Ltd. +0C7512 (base 16) Shenzhen Kunlun TongTai Technology Co.,Ltd. + Room 2401,B,Building 3,Tianan Yungu Industry Park,Gangtou community,bantian streets,Longgang District + Shenzhen Guangdong 518129 + CN + +74-83-C2 (hex) Ubiquiti Networks Inc. +7483C2 (base 16) Ubiquiti Networks Inc. + 2580 Orchard Pkwy + San Jose CA 95131 + US + +E0-63-DA (hex) Ubiquiti Networks Inc. +E063DA (base 16) Ubiquiti Networks Inc. + 2580 Orchard Pkwy + San Jose CA 95131 + US + +50-57-9C (hex) Seiko Epson Corporation +50579C (base 16) Seiko Epson Corporation + 2070 Kotobuki Koaka + Matsumoto-shi Nagano-ken 399-8702 + JP + +98-3B-8F (hex) Intel Corporate +983B8F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +54-27-8D (hex) NXP (China) Management Ltd. +54278D (base 16) NXP (China) Management Ltd. + 21F, BM InterContinental Business Center, 100 Yu Tong Road + Shanghai Shanghai 200070 + CN + +B0-BE-76 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +B0BE76 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +44-47-CC (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +4447CC (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road + Hangzhou Zhejiang 310052 + CN + +4C-D9-8F (hex) Dell Inc. +4CD98F (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +B0-AE-25 (hex) Varikorea +B0AE25 (base 16) Varikorea + #505 kolon digital tower aston, gasan, geumcheon + seoul 08502 + KR + +4C-1B-86 (hex) Arcadyan Corporation +4C1B86 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +EC-C4-0D (hex) Nintendo Co.,Ltd +ECC40D (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +44-00-49 (hex) Amazon Technologies Inc. +440049 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +E8-6A-64 (hex) LCFC(HeFei) Electronics Technology co., ltd +E86A64 (base 16) LCFC(HeFei) Electronics Technology co., ltd + YunGu Road 3188-1 + Hefei Anhui 230000 + CN + +10-A2-4E (hex) GOLD3LINK ELECTRONICS CO., LTD +10A24E (base 16) GOLD3LINK ELECTRONICS CO., LTD + No.90,Sec.1,Com Lin Rd,Taipei 114,Taiwan,R.O.C + Taipei Taiwan 114 + TW + +CC-C5-E5 (hex) Dell Inc. +CCC5E5 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +6C-C3-74 (hex) Texas Instruments +6CC374 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +68-47-49 (hex) Texas Instruments +684749 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +F8-D9-B8 (hex) Open Mesh, Inc. +F8D9B8 (base 16) Open Mesh, Inc. + 111 SW 5th Ave Ste1150 + Portland OR 97204 + US + +7C-69-6B (hex) Atmosic Technologies +7C696B (base 16) Atmosic Technologies + 12930 Saratoga Ave, Suite B6 + Saratoga CA 95070 + US + +5C-D2-0B (hex) Yytek Co., Ltd. +5CD20B (base 16) Yytek Co., Ltd. + No.1 Bao Sheng South Road, Room 401, Ao Bei Technology Park, Ling Zhi Center + Beijing 100192 + CN + +70-03-7E (hex) Technicolor CH USA Inc. +70037E (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +D0-03-DF (hex) Samsung Electronics Co.,Ltd +D003DF (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +C4-23-A2 (hex) PT. Emsonic Indonesia +C423A2 (base 16) PT. Emsonic Indonesia + Jl.Timor Blok E5, MM2100 Industrial Town Jatiwangi Cikarang Barat + Bekasi Jawa Barat 17530 + ID + +B4-CB-57 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +B4CB57 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +4C-12-65 (hex) ARRIS Group, Inc. +4C1265 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-50-0C (hex) e-Tek Labs, Inc. +00500C (base 16) e-Tek Labs, Inc. + 1057 EAST HENRIETTA RD. + ROCHESTER NY 14623 + US + +48-5F-99 (hex) Cloud Network Technology (Samoa) Limited +485F99 (base 16) Cloud Network Technology (Samoa) Limited + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +88-34-FE (hex) Bosch Automotive Products (Suzhou) Co. Ltd +8834FE (base 16) Bosch Automotive Products (Suzhou) Co. Ltd + No. 455 Xing Long Street,Suzhou Industrial Park,Suzhou P.R., 215021 China + Suzhou Jiangsu 215021 + CN + +88-F7-BF (hex) vivo Mobile Communication Co., Ltd. +88F7BF (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +D8-7D-7F (hex) Sagemcom Broadband SAS +D87D7F (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +00-05-1A (hex) 3COM EUROPE LTD +00051A (base 16) 3COM EUROPE LTD + 3COM CENTRE + vvvvv UNITED KINGDOM + GB + +08-00-4E (hex) 3COM EUROPE LTD +08004E (base 16) 3COM EUROPE LTD + 3COM CENTRE + vvvvv UNITED KINGDOM + GB + +00-30-1E (hex) 3COM EUROPE LTD +00301E (base 16) 3COM EUROPE LTD + BOUNDARY WAY + vvvvv UNITED KINGDOM + GB + +00-50-04 (hex) 3COM +005004 (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +00-01-03 (hex) 3COM +000103 (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +58-B5-68 (hex) SECURITAS DIRECT ESPAÑA, SAU +58B568 (base 16) SECURITAS DIRECT ESPAÑA, SAU + C/ Priégola, 2 + Pozuelo de Alarcon Madrid 28224 + ES + +48-4A-E9 (hex) Hewlett Packard Enterprise +484AE9 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +84-6A-66 (hex) Sumitomo Kizai Co.,Ltd. +846A66 (base 16) Sumitomo Kizai Co.,Ltd. + 1-45-1higashiikebukuro + tosimaku tokyo 170-0013 + JP + +18-D7-17 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +18D717 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +80-B6-24 (hex) IVS +80B624 (base 16) IVS + 807-809 , Woorim E-biz center, 35, Gwangnaru-ro 6-gil + Seoul Seongdong-gu 04799 + KR + +DC-F5-05 (hex) AzureWave Technology Inc. +DCF505 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +CC-F0-FD (hex) China Mobile (Hangzhou) Information Technology Co., Ltd. +CCF0FD (base 16) China Mobile (Hangzhou) Information Technology Co., Ltd. + No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District, Hangzhou, Zhejiang + Hangzhou Zhejiang 310000 + CN + +84-89-EC (hex) IEEE Registration Authority +8489EC (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +88-10-8F (hex) HUAWEI TECHNOLOGIES CO.,LTD +88108F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-63-1F (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4631F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-9B-4F (hex) HUAWEI TECHNOLOGIES CO.,LTD +A49B4F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-07-3A (hex) INVENTEL +00073A (base 16) INVENTEL + 35, rue Toumefort + 000 0000 + FR + +00-26-6C (hex) INVENTEC CORPORATION +00266C (base 16) INVENTEC CORPORATION + Inventec Building, 66 Hou-Kang Street Shih-Lin District, + Taipei 111 + TW + +00-8C-FA (hex) INVENTEC CORPORATION +008CFA (base 16) INVENTEC CORPORATION + No. 255, Jen-Ho Road Sec. 2, 33547, + Tachi Taoyuan 33547 + TW + +5C-FB-7C (hex) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd +5CFB7C (base 16) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + 3/F,A5 Building Zhiyuan Community No.1001,Xueyuan Road Nanshan District + Shenzhen Guangdong 518055 + CN + +FC-03-9F (hex) Samsung Electronics Co.,Ltd +FC039F (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +02-C0-8C (hex) 3COM +02C08C (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +00-57-C1 (hex) LG Electronics (Mobile Communications) +0057C1 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +7C-24-0C (hex) Telechips, Inc. +7C240C (base 16) Telechips, Inc. + 19F~23F,Luther Bldg.42, Olympic-ro 35da-gil, Songpa-gu, + Seoul Seoul 05510 + KR + +00-20-3D (hex) Honeywell Environmental & Combustion Controls +00203D (base 16) Honeywell Environmental & Combustion Controls + 1985 Douglas Drive + Golden Valley MN 55422 + US + +00-40-84 (hex) Honeywell International HPS +004084 (base 16) Honeywell International HPS + consolidation + Fort Washington PA 19034 + US + +1C-1B-B5 (hex) Intel Corporate +1C1BB5 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A4-D9-90 (hex) Samsung Electronics Co.,Ltd +A4D990 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-60-87 (hex) KANSAI ELECTRIC CO., LTD. +006087 (base 16) KANSAI ELECTRIC CO., LTD. + 6-14-9 MIDORII, ASAMINAMI-KU + HIROSHIMA 731-01 + JO + +DC-F7-19 (hex) Cisco Systems, Inc +DCF719 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A0-95-0C (hex) China Mobile IOT Company Limited +A0950C (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +D4-74-1B (hex) Beijing HuaDa ZhiBao Electronic System Co.,Ltd. +D4741B (base 16) Beijing HuaDa ZhiBao Electronic System Co.,Ltd. + No.1 Gaojiayuan,Chaoyang District,Beijing,China + Beijing Beijing 100015 + CN + +00-1B-C0 (hex) Juniper Networks +001BC0 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +2C-15-E1 (hex) Phicomm (Shanghai) Co., Ltd. +2C15E1 (base 16) Phicomm (Shanghai) Co., Ltd. + 3666 SiXian Rd.,Songjiang District + Shanghai Shanghai 201616 + CN + +30-D1-6B (hex) Liteon Technology Corporation +30D16B (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +98-AE-71 (hex) VVDN Technologies Pvt Ltd +98AE71 (base 16) VVDN Technologies Pvt Ltd + B-22, Sec-34 , Info-city -I + Gurugram Haryana 122001 + IN + +A4-56-CC (hex) Technicolor CH USA Inc. +A456CC (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +AC-6E-1A (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +AC6E1A (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + B116,B118,A211-A213,B201-B213,A311-A313,B411-413,BF08-09 Nanshan Medical Instrument Industry Park, + Shenzhen Guangdong 518067 + CN + +00-80-EB (hex) COMPCONTROL B.V. +0080EB (base 16) COMPCONTROL B.V. + STRATUMSED K31 + THE + NL + +00-02-EB (hex) Pico Communications +0002EB (base 16) Pico Communications + 20085 Stevens Creek Blvd. + Cupertino CA 95014 + US + +34-2E-B6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +342EB6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +AC-92-32 (hex) HUAWEI TECHNOLOGIES CO.,LTD +AC9232 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-0F-B0 (hex) Compal Electronics INC. +000FB0 (base 16) Compal Electronics INC. + No.8 , Nandong Road , PingZhen Dist. + Taoyuan Taiwan 32455 + TW + +00-02-3F (hex) Compal Electronics INC. +00023F (base 16) Compal Electronics INC. + No.8 , Nandong Road , PingZhen Dist. + Taoyuan Taiwan 32455 + TW + +68-A8-E1 (hex) Wacom Co.,Ltd. +68A8E1 (base 16) Wacom Co.,Ltd. + Sumitomo Fudosan Shinjuku Grand Tower 31F,8-17-1 + Nishi-shinjuku,Shinjuku-ku Tokyo 160-6131 + JP + +30-D3-2D (hex) devolo AG +30D32D (base 16) devolo AG + Charlottenburger Allee 67 + Aachen NRW 52068 + DE + +BC-F2-AF (hex) devolo AG +BCF2AF (base 16) devolo AG + Charlottenburger Allee 67 + Aachen NRW 52068 + DE + +E0-AF-4F (hex) Deutsche Telekom AG +E0AF4F (base 16) Deutsche Telekom AG + Friedrich-Ebert-Allee 140 + Bonn 53113 + DE + +DC-8B-28 (hex) Intel Corporate +DC8B28 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B8-69-F4 (hex) Routerboard.com +B869F4 (base 16) Routerboard.com + Mikrotikls SIA + Riga Riga LV1009 + LV + +28-3A-4D (hex) Cloud Network Technology (Samoa) Limited +283A4D (base 16) Cloud Network Technology (Samoa) Limited + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +B8-7C-6F (hex) NXP (China) Management Ltd. +B87C6F (base 16) NXP (China) Management Ltd. + 21F, BM InterContinental Business Center, 100 Yu Tong Road + Shanghai Shanghai 200070 + CN + +30-5D-A6 (hex) ADVALY SYSTEM Inc. +305DA6 (base 16) ADVALY SYSTEM Inc. + 7 KITA2 NISHI2 CYUO-KU + SAPPORO HOKKAIDO 060-0002 + JP + +BC-30-D9 (hex) Arcadyan Corporation +BC30D9 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +04-79-B7 (hex) Texas Instruments +0479B7 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +C0-D0-FF (hex) China Mobile IOT Company Limited +C0D0FF (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +88-DF-9E (hex) New H3C Technologies Co., Ltd +88DF9E (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +2C-7C-E4 (hex) Wuhan Tianyu Information Industry Co., Ltd. +2C7CE4 (base 16) Wuhan Tianyu Information Industry Co., Ltd. + HUST Industry Park, East-Lake Development Zone + Wuhan Hubei 430223 + CN + +58-03-FB (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +5803FB (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road + Hangzhou Zhejiang 310052 + CN + +14-48-02 (hex) THE YEOLRIM Co.,Ltd. +144802 (base 16) THE YEOLRIM Co.,Ltd. + D-311,H Business Park,26,Beobwon-ro 9-gil Songpa-gu,Seoul Korea + Seoul 05836 + KR + +FC-4A-E9 (hex) Castlenet Technology Inc. +FC4AE9 (base 16) Castlenet Technology Inc. + No.64, Chung-Shan Rd. + New Taipei City 23680 + TW + +40-31-3C (hex) XIAOMI Electronics,CO.,LTD +40313C (base 16) XIAOMI Electronics,CO.,LTD + Xiaomi Building, No.68 Qinghe Middle Street + Haidian District Beijing 100085 + CN + +FC-45-96 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +FC4596 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZON + KUNSHAN SUZHOU 215300 + CN + +A0-E5-34 (hex) Stratec Biomedical AG +A0E534 (base 16) Stratec Biomedical AG + Gewerbestrasse 37 + Birkenfeld Baden Wuertemberg 75217 + DE + +44-4B-5D (hex) GE Healthcare +444B5D (base 16) GE Healthcare + Kuortaneenkatu 2 + Helsinki 00510 + FI + +00-15-55 (hex) DFM GmbH +001555 (base 16) DFM GmbH + Lahrer Strasse 6 + Lahr Baden-Württemberg 77933 + US + +1C-75-08 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +1C7508 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +00-1B-38 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +001B38 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD AVENUE + KUNSHAN CITY SUZHOU PROVINCE 215300 + CN + +00-23-5A (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +00235A (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO 25, The 3rd street, + KuanShan SUZHOU 215300 + CN + +24-D7-6B (hex) Syntronic AB +24D76B (base 16) Syntronic AB + Utmarksvägen 33c + Gävle 80291 + SE + +C4-FE-E2 (hex) AMICCOM Electronics Corporation +C4FEE2 (base 16) AMICCOM Electronics Corporation + 10F, No.18, Taiyuan St., Zhubei City + Hsinchu Country Taiwan 30265 + TW + +78-0C-F0 (hex) Cisco Systems, Inc +780CF0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +0C-8C-24 (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD +0C8C24 (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD + NO.268, Fuqian Rd, Jutang community, Guanlan Town, Longhua New district + shenzhen guangdong 518000 + CN + +8C-6D-77 (hex) HUAWEI TECHNOLOGIES CO.,LTD +8C6D77 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E8-C5-7A (hex) Ufispace Co., LTD. +E8C57A (base 16) Ufispace Co., LTD. + 9F., No. 81 Jhongcheng Rd., Tucheng Dist., + New Taipei 23674 + TW + +E0-12-83 (hex) Shenzhen Fanzhuo Communication Technology Co., Lt +E01283 (base 16) Shenzhen Fanzhuo Communication Technology Co., Lt + No.1003 Kesi Road, Hi-Tech Park, + Shenzhen Nanshan District 2602-2603 + CN + +A0-CF-5B (hex) Cisco Systems, Inc +A0CF5B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-21 (hex) MICRO-STAR INT'L CO., LTD. +002421 (base 16) MICRO-STAR INT'L CO., LTD. + No.69, Li-De St + Taipei Hsien 235 + TW + +00-60-D1 (hex) CASCADE COMMUNICATIONS +0060D1 (base 16) CASCADE COMMUNICATIONS + 6 TECHNOLOGY PARK DRIVE + WESTFORD MA 01886 + US + +84-C9-C6 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +84C9C6 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +88-B6-6B (hex) easynetworks +88B66B (base 16) easynetworks + Rd kaituo 1# kaituohuiyuan B 1020, shangdi + Beijing 100084 + CN + +24-F5-7E (hex) HWH CO., LTD. +24F57E (base 16) HWH CO., LTD. + 102-708, Digital Empire2, Sin-dong, Youngtong-gu + Suwon-si Gyeonggi-do 443-734 + KR + +8C-A0-48 (hex) Beijing NeTopChip Technology Co.,LTD +8CA048 (base 16) Beijing NeTopChip Technology Co.,LTD + 309,Intergration Building Olympic Center, No.1 An Ding Road,Chao Yang District,, + Beijing 100029 + CN + +24-D3-F2 (hex) zte corporation +24D3F2 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +D4-69-A5 (hex) Miura Systems Ltd. +D469A5 (base 16) Miura Systems Ltd. + Axis 40, Oxford Road, Stokenchurch + High Wycombe Buckinghamshire HP143SX + GB + +8C-81-26 (hex) ARCOM +8C8126 (base 16) ARCOM + ZAC de la Loyère + FRAGNES LA LOYERE 71530 + FR + +D4-7C-44 (hex) IEEE Registration Authority +D47C44 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +80-5E-4F (hex) FN-LINK TECHNOLOGY LIMITED +805E4F (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +84-17-EF (hex) Technicolor CH USA Inc. +8417EF (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +38-56-B5 (hex) Peerbridge Health Inc +3856B5 (base 16) Peerbridge Health Inc + 3 Columbus Circle 15th Fl + New York NY 10019 + US + +7C-96-D2 (hex) Fihonest communication co.,Ltd +7C96D2 (base 16) Fihonest communication co.,Ltd + The Frist Building ,ShangKeng Industrial Zone, Changping Town + Dongguan Guangdong 523560 + CN + +30-24-32 (hex) Intel Corporate +302432 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C0-42-D0 (hex) Juniper Networks +C042D0 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +D0-C5-D8 (hex) LATECOERE +D0C5D8 (base 16) LATECOERE + 135 Rue de Périole, BP25211 + Toulouse Cedex 5 31 Haute-Garonne 31079 + FR + +70-54-B4 (hex) Vestel Elektronik San ve Tic. A.Ş. +7054B4 (base 16) Vestel Elektronik San ve Tic. A.Ş. + Organize san + Manisa Turket 45030 + TR + +20-A6-0C (hex) Xiaomi Communications Co Ltd +20A60C (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +48-8A-D2 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +488AD2 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan + Shenzhen Guangdong 518057 + CN + +DC-E8-38 (hex) CK Telecom (Shenzhen) Limited +DCE838 (base 16) CK Telecom (Shenzhen) Limited + Floor 9th, Building 4C,Software Industry Base, Xuefu Road, Hi-Tech Park, Nanshan Dist. + Shenzhen Guangdong 518057 + CN + +A8-D4-98 (hex) Avira Operations GmbH & Co. KG +A8D498 (base 16) Avira Operations GmbH & Co. KG + Kaplaneiweg 1 + Tettnang Baden-Wuerttermberg 88069 + DE + +50-59-67 (hex) Intent Solutions Inc +505967 (base 16) Intent Solutions Inc + 730 Peachtree St NE, Suite 550 + ATLANTA GA 30308 + US + +00-06-80 (hex) Card Access, Inc. +000680 (base 16) Card Access, Inc. + 11778 S. Election Rd + Salt Lake City UT 80420 + US + +3C-57-6C (hex) Samsung Electronics Co.,Ltd +3C576C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +84-17-66 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +841766 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China + Wei Fang Shan Dong + CN + +2C-4D-79 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +2C4D79 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + No.268 Dongfang Road + Weifang Shandong 261000 + CN + +00-0C-42 (hex) Routerboard.com +000C42 (base 16) Routerboard.com + Pernavas 46 + Riga LV-1009 + LV + +00-26-BD (hex) JTEC Card & Communication Co., Ltd +0026BD (base 16) JTEC Card & Communication Co., Ltd + Dabo Bldg, 4F, 61-1, Gyesu-dong, Sosa-gu + Bucheon Gyunggi-do 422-070 + KR + +60-D0-2C (hex) Ruckus Wireless +60D02C (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +D0-58-FC (hex) BSkyB Ltd +D058FC (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +14-57-9F (hex) HUAWEI TECHNOLOGIES CO.,LTD +14579F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B4-43-26 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B44326 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +04-AB-18 (hex) ELECOM CO.,LTD. +04AB18 (base 16) ELECOM CO.,LTD. + 11F Tokyubancho Bldg. 6-2, + Chiyoda-ku Tokyo 102-0081 + JP + +78-D2-94 (hex) NETGEAR +78D294 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +70-9F-A9 (hex) TECNO MOBILE LIMITED +709FA9 (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +0C-01-DB (hex) Infinix mobility limited +0C01DB (base 16) Infinix mobility limited + RMS 05-15, 13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG + HongKong HongKong 999077 + HK + +08-C5-E1 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +08C5E1 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +18-66-C7 (hex) Shenzhen Libre Technology Co., Ltd +1866C7 (base 16) Shenzhen Libre Technology Co., Ltd + 634, Tian Hui Building #B, You Song Lu, Long Hua District + Shenzhen 511700 + CN + +5C-B3-F6 (hex) Human, Incorporated +5CB3F6 (base 16) Human, Incorporated + 3100 Airport Way S, 25-512 + Seattle WA 98134 + US + +2C-48-35 (hex) IEEE Registration Authority +2C4835 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +48-2A-E3 (hex) Wistron InfoComm(Kunshan)Co.,Ltd. +482AE3 (base 16) Wistron InfoComm(Kunshan)Co.,Ltd. + 168# First Avenue,Kunshan Integrated Free Trade Zone,Kunshan,Jiangsu,China + Kunshan Jiangsu 215300 + CN + +FC-A6-CD (hex) Fiberhome Telecommunication Technologies Co.,LTD +FCA6CD (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +44-C8-74 (hex) China Mobile Group Device Co.,Ltd. +44C874 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +74-C1-4F (hex) HUAWEI TECHNOLOGIES CO.,LTD +74C14F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B0-EB-57 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B0EB57 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-69-DA (hex) China Mobile Group Device Co.,Ltd. +1869DA (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +F8-5C-4D (hex) Nokia +F85C4D (base 16) Nokia + 1 Robbins Road + Westford MA 01886-4113 + US + +2C-58-4F (hex) ARRIS Group, Inc. +2C584F (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F0-4B-3A (hex) Juniper Networks +F04B3A (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +54-BF-64 (hex) Dell Inc. +54BF64 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +A8-5B-6C (hex) Robert Bosch Gmbh, CM-CI2 +A85B6C (base 16) Robert Bosch Gmbh, CM-CI2 + Renningen + Stuttgart D-70465 + DE + +C8-B1-EE (hex) Qorvo +C8B1EE (base 16) Qorvo + 1 Changi Business Park Crescent, Avenue 1, #04-01 + NA 486058 + SG + +00-FC-BA (hex) Cisco Systems, Inc +00FCBA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-CB-B4 (hex) SHENZHEN ATEKO PHOTOELECTRICITY CO.,LTD +00CBB4 (base 16) SHENZHEN ATEKO PHOTOELECTRICITY CO.,LTD + 4-5F,E1 Building,TCL International E City,No.1001 Zhongshanyuan Road,Nanshan District,Shenzhen + SHENZHEN GUANGDONG 518052 + CN + +4C-C0-0A (hex) vivo Mobile Communication Co., Ltd. +4CC00A (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +9C-E8-2B (hex) vivo Mobile Communication Co., Ltd. +9CE82B (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +70-79-B3 (hex) Cisco Systems, Inc +7079B3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D8-18-D3 (hex) Juniper Networks +D818D3 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +14-9B-2F (hex) JiangSu ZhongXie Intelligent Technology co., LTD +149B2F (base 16) JiangSu ZhongXie Intelligent Technology co., LTD + Room 201,building 15, 16,FengJi set avenue (C08),YuHua district economic development zone ,NanJing city,JiangSu province,China,PRC. + NanJing JiangSu 210000 + CN + +38-35-FB (hex) Sagemcom Broadband SAS +3835FB (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +48-DD-9D (hex) ITEL MOBILE LIMITED +48DD9D (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +A0-75-EA (hex) BoxLock, Inc. +A075EA (base 16) BoxLock, Inc. + 931 Monroe Dr Ste A 102-405 + Atlanta GA 30308 + US + +F0-4C-D5 (hex) Maxlinear, Inc +F04CD5 (base 16) Maxlinear, Inc + 5966 La Place Ct. Ste# 100 + Carlsbad CA 92008 + US + +00-01-AE (hex) Trex Enterprises +0001AE (base 16) Trex Enterprises + 590 Lipoa Parkway + Kihei HI 96753 + US + +00-E0-09 (hex) Stratus Technologies +00E009 (base 16) Stratus Technologies + 5 Mill and Main Place, Suite 500 + Maynard MA 01754 + US + +E4-EA-83 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +E4EA83 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +74-EC-42 (hex) Fiberhome Telecommunication Technologies Co.,LTD +74EC42 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +D4-FC-13 (hex) Fiberhome Telecommunication Technologies Co.,LTD +D4FC13 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +80-7D-3A (hex) Espressif Inc. +807D3A (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +EC-AF-97 (hex) GIT +ECAF97 (base 16) GIT + 05655, GIT Bldg., 87, Macheon-ro, Songpa-gu, Seoul, Korea + Songpa-gu Seoul 05655 + KR + +A0-B0-45 (hex) Halong Mining +A0B045 (base 16) Halong Mining + 13/F TCL Tower, No.8 Tai Chung Road + Tsuen Wan New Territories Tsuen Wan New Territories + HK + +E0-BA-B4 (hex) Arrcus, Inc +E0BAB4 (base 16) Arrcus, Inc + 2077 Gateway Pl, Suite 250, + San Jose CA 95110 + US + +58-9B-0B (hex) Shineway Technologies, Inc. +589B0B (base 16) Shineway Technologies, Inc. + Floor 5, Huanxing Building + Beijing 100191 + CN + +D8-16-0A (hex) Nippon Electro-Sensory Devices +D8160A (base 16) Nippon Electro-Sensory Devices + Itachibori 2-5-12 + Nishi-ku Osaka 550-0012 + JP + +10-C0-7C (hex) Blu-ray Disc Association +10C07C (base 16) Blu-ray Disc Association + 4444 Riverside Drive #103 + Burbank California 91505 + US + +40-A6-77 (hex) Juniper Networks +40A677 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +E4-B0-21 (hex) Samsung Electronics Co.,Ltd +E4B021 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +9C-7F-57 (hex) UNIC Memory Technology Co Ltd +9C7F57 (base 16) UNIC Memory Technology Co Ltd + 15/F, Building B, Truth Plaza, No.7 Zhichun Road + Beijing Haidian District 102208 + CN + +B4-E0-1D (hex) CONCEPTION ELECTRONIQUE +B4E01D (base 16) CONCEPTION ELECTRONIQUE + 3 boulevard de l'europe + NEUFCHATEL EN BRAY 76270 + FR + +1C-00-42 (hex) NARI Technology Co., Ltd. +1C0042 (base 16) NARI Technology Co., Ltd. + NO.19 Chengxin Avenue, Nanjing + Nanjing 211106 + CN + +44-34-A7 (hex) ARRIS Group, Inc. +4434A7 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +3C-E1-A1 (hex) Universal Global Scientific Industrial Co., Ltd. +3CE1A1 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, Lane 351, Taiping Road, Sec.1,Tsao Tuen + Nan-Tou Taiwan 54261 + TW + +F8-98-EF (hex) HUAWEI TECHNOLOGIES CO.,LTD +F898EF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +58-F9-87 (hex) HUAWEI TECHNOLOGIES CO.,LTD +58F987 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A8-F5-AC (hex) HUAWEI TECHNOLOGIES CO.,LTD +A8F5AC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +58-BA-D4 (hex) HUAWEI TECHNOLOGIES CO.,LTD +58BAD4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +70-1D-08 (hex) 99IOT Shenzhen co.,ltd +701D08 (base 16) 99IOT Shenzhen co.,ltd + 609C north block, Cangsong Building, Tairan Seven Road, Futian District + Shenzhen Guangdong 518000 + CN + +74-12-BB (hex) Fiberhome Telecommunication Technologies Co.,LTD +7412BB (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +00-10-27 (hex) L-3 COMMUNICATIONS EAST +001027 (base 16) L-3 COMMUNICATIONS EAST + ONE FEDERAL STREET - A&E-3ES + CAMDEN NJ 08102 + US + +BC-26-43 (hex) Elprotronic Inc. +BC2643 (base 16) Elprotronic Inc. + 35 Austin Rumble Crt. + King City ON L7B0B2 + CA + +04-E2-29 (hex) Qingdao Haier Technology Co.,Ltd +04E229 (base 16) Qingdao Haier Technology Co.,Ltd + Building A01,Haier Information Park, No.1 Haier Road, + Qingdao Shandong 266101 + CN + +34-8B-75 (hex) LAVA INTERNATIONAL(H.K) LIMITED +348B75 (base 16) LAVA INTERNATIONAL(H.K) LIMITED + UNIT L 1/F MAU LAM COMM BLDG 16-18 MAU LAM ST, JORDAN KL, HK + Hong kong 999077 + CN + +9C-E8-95 (hex) New H3C Technologies Co., Ltd +9CE895 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +00-58-3F (hex) PC Aquarius +00583F (base 16) PC Aquarius + Comcity Office Park, Kievskoe shosse, est.6, bld. 1, Rumyantsevo, Moscow, 108811, RF + Moscow 108811 + RU + +90-3D-68 (hex) G-Printec, Inc. +903D68 (base 16) G-Printec, Inc. + Kawasaki Tech Center 5F, 580-16, Horikawacho + Saiwai-ku, Kawasaki-shi Kanagawa 212-0013 + JP + +10-94-BB (hex) Apple, Inc. +1094BB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-1D-4A (hex) zte corporation +781D4A (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +94-E1-AC (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +94E1AC (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road + Hangzhou Zhejiang 310052 + CN + +34-E8-94 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +34E894 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +F8-6F-C1 (hex) Apple, Inc. +F86FC1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-FF-3C (hex) Apple, Inc. +28FF3C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-99-B6 (hex) Apple, Inc. +F099B6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-E9-FE (hex) Apple, Inc. +88E9FE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-89-2C (hex) Apple, Inc. +38892C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +74-9E-AF (hex) Apple, Inc. +749EAF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +94-BF-2D (hex) Apple, Inc. +94BF2D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-CA-E4 (hex) Cisco Systems, Inc +68CAE4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-BE-3B (hex) HUAWEI TECHNOLOGIES CO.,LTD +00BE3B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-A1-77 (hex) HUAWEI TECHNOLOGIES CO.,LTD +7CA177 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-2E-02 (hex) HUAWEI TECHNOLOGIES CO.,LTD +242E02 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +78-B6-EC (hex) Scuf Gaming International LLC +78B6EC (base 16) Scuf Gaming International LLC + 3970 Johns Creek Court Suite 325 Suwanee + Atlanta GA 30024 + US + +80-35-C1 (hex) Xiaomi Communications Co Ltd +8035C1 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +58-B3-FC (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +58B3FC (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District, + Shenzhen Guangdong 518000 + CN + +20-47-DA (hex) Xiaomi Communications Co Ltd +2047DA (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +24-29-FE (hex) KYOCERA Corporation +2429FE (base 16) KYOCERA Corporation + 30 Hoji + Kitami, Hokkaido 099-1595 + JP + +7C-49-EB (hex) XIAOMI Electronics,CO.,LTD +7C49EB (base 16) XIAOMI Electronics,CO.,LTD + Xiaomi Building, No.68 Qinghe Middle Street + Haidian District Beijing 100085 + CN + +C4-33-06 (hex) China Mobile Group Device Co.,Ltd. +C43306 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +08-DF-CB (hex) Systrome Networks +08DFCB (base 16) Systrome Networks + Sohna Road + Gurgaon Haryana 122018 + IN + +A4-93-3F (hex) HUAWEI TECHNOLOGIES CO.,LTD +A4933F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +28-AC-9E (hex) Cisco Systems, Inc +28AC9E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +2C-B8-ED (hex) SonicWall +2CB8ED (base 16) SonicWall + 5455 Great America Parkway + Santa Clara CA 95054 + US + +68-D4-82 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +68D482 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +98-45-62 (hex) Shanghai Baud Data Communication Co.,Ltd. +984562 (base 16) Shanghai Baud Data Communication Co.,Ltd. + NO.123 JULI RD + PUDONG ZHANGJIANG HIGH-TECH PARK SHANGHAI 201203 + CN + +E4-C4-83 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +E4C483 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +00-1F-BA (hex) Boyoung Tech +001FBA (base 16) Boyoung Tech + Youngdeungpo-Gu Munrae3ga 84-2 + Seoul 150-093 + KR + +A4-33-D7 (hex) MitraStar Technology Corp. +A433D7 (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +B0-AC-D2 (hex) zte corporation +B0ACD2 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +20-0F-70 (hex) FOXTECH +200F70 (base 16) FOXTECH + 152-160 City Road + LONDON KEMP HOUSE EC1V 2NX + GB + +20-2D-23 (hex) Collinear Networks Inc. +202D23 (base 16) Collinear Networks Inc. + 2901 Tasman Drive + Santa Clara CA 95054 + US + +90-83-4B (hex) BEIJING YUNYI TIMES TECHNOLOGY CO,.LTD +90834B (base 16) BEIJING YUNYI TIMES TECHNOLOGY CO,.LTD + 1-411Room 19#Building No.26 Xihuan South Rd. BDA Daxing District, + BEIJING 100176 + CN + +18-50-2A (hex) SOARNEX +18502A (base 16) SOARNEX + NO.158, RUIHU ST., NEIHU DIST., + TAIPEI CITY TAIWAN (R.O.C.) 11494 + TW + +A8-36-7A (hex) frogblue TECHNOLOGY GmbH +A8367A (base 16) frogblue TECHNOLOGY GmbH + Luxemburger Straße 6 + Kaiserslautern Rheinland-Pfalz 67657 + DE + +6C-E4-DA (hex) NEC Platforms, Ltd. +6CE4DA (base 16) NEC Platforms, Ltd. + 2-3 Kandatsukasamachi + Chiyodaku Tokyo 101-8532 + JP + +10-E7-C6 (hex) Hewlett Packard +10E7C6 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +18-31-BF (hex) ASUSTek COMPUTER INC. +1831BF (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +C8-FA-E1 (hex) ARQ Digital LLC +C8FAE1 (base 16) ARQ Digital LLC + 2430 Auto Park Way + Escondido CA 92029 + US + +DC-A3-33 (hex) Shenzhen YOUHUA Technology Co., Ltd +DCA333 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +78-8C-54 (hex) Ping Communication +788C54 (base 16) Ping Communication + Brenden 18 + Appenzell Meistersrüte AI 9050 + CH + +B8-AF-67 (hex) Hewlett Packard +B8AF67 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +C0-98-DA (hex) China Mobile IOT Company Limited +C098DA (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +F0-0F-EC (hex) HUAWEI TECHNOLOGIES CO.,LTD +F00FEC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +AC-07-5F (hex) HUAWEI TECHNOLOGIES CO.,LTD +AC075F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C0-48-E6 (hex) Samsung Electronics Co.,Ltd +C048E6 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +88-2E-5A (hex) storONE +882E5A (base 16) storONE + POB 2660 + Ra'anana + IL + +00-71-47 (hex) Amazon Technologies Inc. +007147 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +00-BE-75 (hex) Cisco Systems, Inc +00BE75 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +64-DB-8B (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +64DB8B (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road + Hangzhou Zhejiang 310052 + CN + +78-25-7A (hex) LEO Innovation Lab +78257A (base 16) LEO Innovation Lab + Silkegade 8 + Copenhagen K Denmark 1113 + DK + +10-A4-B9 (hex) Baidu Online Network Technology (Beijing) Co., Ltd +10A4B9 (base 16) Baidu Online Network Technology (Beijing) Co., Ltd + Baidu Campus, No.10 Shangdi 10th Street, Haidian District + Beijing 100085 + CN + +50-1C-B0 (hex) Cisco Systems, Inc +501CB0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +04-AC-44 (hex) Holtek Semiconductor Inc. +04AC44 (base 16) Holtek Semiconductor Inc. + No.3, Creation Rd. II, Science Park + Hsinchu 300 + TW + +F4-DC-A5 (hex) DAWON DNS +F4DCA5 (base 16) DAWON DNS + 217ho, Sauphwajiwon-dong, KETI, 226, Cheomdangwagi-ro, Buk-gu + Gwangju 61011 + KR + +0C-54-15 (hex) Intel Corporate +0C5415 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +80-CE-62 (hex) Hewlett Packard +80CE62 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +80-1F-12 (hex) Microchip Technology Inc. +801F12 (base 16) Microchip Technology Inc. + 2355 W. Chandler Blvd. + Chandler AZ 85224 + US + +50-6C-BE (hex) InnosiliconTechnology Ltd +506CBE (base 16) InnosiliconTechnology Ltd + WuHan East Lake Wuhan New Technology Development Zone + Wuhan Hubei Province 430223 + CN + +24-7E-12 (hex) Cisco Systems, Inc +247E12 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +04-C2-41 (hex) Nokia +04C241 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +3C-47-9B (hex) Theissen Training Systems, Inc. +3C479B (base 16) Theissen Training Systems, Inc. + 1225 SE 4th Terrace + Chiefland FL 32626 + US + +60-6B-FF (hex) Nintendo Co.,Ltd +606BFF (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +8C-F7-10 (hex) AMPAK Technology, Inc. +8CF710 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +30-7B-AC (hex) New H3C Technologies Co., Ltd +307BAC (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +78-5D-C8 (hex) LG Electronics +785DC8 (base 16) LG Electronics + 222 LG-ro, JINWI-MYEON + Pyeongtaek-si Gyeonggi-do 451-713 + KR + +3C-04-61 (hex) ARRIS Group, Inc. +3C0461 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +88-3D-24 (hex) Google, Inc. +883D24 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +E8-C1-B8 (hex) Nanjing Bangzhong Electronic Commerce Limited +E8C1B8 (base 16) Nanjing Bangzhong Electronic Commerce Limited + No.22, Liuzhou East Road, High - tech Zone + Nanjing 210000 + CN + +D8-D7-75 (hex) Sagemcom Broadband SAS +D8D775 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +E8-33-0D (hex) Xaptec GmbH +E8330D (base 16) Xaptec GmbH + Neidenburger Str. 10 + Gelsenkirchen 45897 + DE + +D4-60-E3 (hex) Sercomm Corporation. +D460E3 (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +B4-A8-B9 (hex) Cisco Systems, Inc +B4A8B9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +50-DC-E7 (hex) Amazon Technologies Inc. +50DCE7 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +64-98-29 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +649829 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +08-1D-C4 (hex) Thermo Fisher Scientific Messtechnik GmbH +081DC4 (base 16) Thermo Fisher Scientific Messtechnik GmbH + Frauenauracher Strasse 96 + Erlangen 91056 + DE + +78-53-64 (hex) SHIFT GmbH +785364 (base 16) SHIFT GmbH + Am Gänsemarkt 6 + Wabern Falkenberg Hessen 34590 + DE + +38-E6-0A (hex) Xiaomi Communications Co Ltd +38E60A (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +40-CB-C0 (hex) Apple, Inc. +40CBC0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C4-61-8B (hex) Apple, Inc. +C4618B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +CC-6E-A4 (hex) Samsung Electronics Co.,Ltd +CC6EA4 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +5C-5F-67 (hex) Intel Corporate +5C5F67 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +80-3A-59 (hex) AT&T +803A59 (base 16) AT&T + 1025 Lenox Park Blvd + Atlanta GA 30319 + US + +58-8D-64 (hex) Xi'an Clevbee Technology Co.,Ltd +588D64 (base 16) Xi'an Clevbee Technology Co.,Ltd + FLOOR 7, TOWER B, POSCO CENTER, NO. 13 ZONE FOUR WANGJING EAST PARK, CHAOYANG DISTRICT, BEIJING + Beijing 100012 + CN + +00-5D-73 (hex) Cisco Systems, Inc +005D73 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +60-6D-3C (hex) Luxshare Precision Industry Company Limited +606D3C (base 16) Luxshare Precision Industry Company Limited + Floor 2, Block A, Sanyo New Industrial Area + West Haoyi Community, Shajing Subdistrict Office Bao'an District, Shenzhen, Guangdong 523000 + CN + +44-F0-34 (hex) Kaonmedia CO., LTD. +44F034 (base 16) Kaonmedia CO., LTD. + 884-3, Seongnam-daero, Bundang-gu + Seongnam-si Gyeonggi-do 13517 + KR + +00-27-90 (hex) Cisco Systems, Inc +002790 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +34-BA-38 (hex) PAL MOHAN ELECTRONICS PVT LTD +34BA38 (base 16) PAL MOHAN ELECTRONICS PVT LTD + 40 DLF, INDUSTRIAL AREA, KIRTI NAGAR + NEW DELHI DELHI 110015 + IN + +98-29-A6 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +9829A6 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +CC-4D-38 (hex) Carnegie Technologies +CC4D38 (base 16) Carnegie Technologies + 9737 Great Hills Trail #260 + Austin TX 78759 + US + +08-E6-89 (hex) Apple, Inc. +08E689 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +DC-56-E7 (hex) Apple, Inc. +DC56E7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-16-D0 (hex) Samsung Electronics Co.,Ltd +A816D0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A4-6C-F1 (hex) Samsung Electronics Co.,Ltd +A46CF1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +08-AE-D6 (hex) Samsung Electronics Co.,Ltd +08AED6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +DC-BF-E9 (hex) Motorola Mobility LLC, a Lenovo Company +DCBFE9 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +B4-2D-56 (hex) Extreme Networks, Inc. +B42D56 (base 16) Extreme Networks, Inc. + 6480 Via Del Oro + San Jose CA 95119 + US + +40-64-A4 (hex) THE FURUKAWA ELECTRIC CO., LTD +4064A4 (base 16) THE FURUKAWA ELECTRIC CO., LTD + 2-2-3,Marunouchi + Chiyoda-ku Tokyo 100-8322 + JP + +6C-B2-AE (hex) Cisco Systems, Inc +6CB2AE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B0-98-2B (hex) Sagemcom Broadband SAS +B0982B (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +34-FA-9F (hex) Ruckus Wireless +34FA9F (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +F0-65-C2 (hex) Yanfeng Visteon Electronics Technology (Shanghai) Co.,Ltd. +F065C2 (base 16) Yanfeng Visteon Electronics Technology (Shanghai) Co.,Ltd. + 1001 North Qin Zhou Road + Shang Hai 200233 + CN + +70-B7-E2 (hex) Jiangsu Miter Technology Co.,Ltd. +70B7E2 (base 16) Jiangsu Miter Technology Co.,Ltd. + No.86 fuyuan community,the town of houbei + Jurong Jiangsu 212400 + CN + +80-8D-B7 (hex) Hewlett Packard Enterprise +808DB7 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +A0-9D-86 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +A09D86 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +00-C0-FF (hex) Seagate Cloud Systems Inc +00C0FF (base 16) Seagate Cloud Systems Inc + 6305 El Camino Real + Carlsbad CA 92009 + US + +D4-5D-DF (hex) PEGATRON CORPORATION +D45DDF (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +F8-B5-68 (hex) IEEE Registration Authority +F8B568 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +2C-6B-7D (hex) Texas Instruments +2C6B7D (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +88-D1-71 (hex) BEGHELLI S.P.A +88D171 (base 16) BEGHELLI S.P.A + VIA MOZZEGHINE 13/15 + LOCALITA' MONTEVEGLIO - COMUNE VALSAMOGGIA BOLOGNA 40053 + IT + +A0-9D-C1 (hex) China Dragon Technology Limited +A09DC1 (base 16) China Dragon Technology Limited + B4 Bldg.Haoshan 1st Industry Park, + Shenzhen Guangdong 518104 + CN + +2C-42-05 (hex) Lytx +2C4205 (base 16) Lytx + 9785 Towne Centre Drive + San Diego CA 92121 + US + +A8-25-EB (hex) Cambridge Industries(Group) Co.,Ltd. +A825EB (base 16) Cambridge Industries(Group) Co.,Ltd. + 5/F,Building 8, 2388 ChenHang Road, MinHang District + shanghai 201114 + CN + +34-E3-80 (hex) Genexis B.V. +34E380 (base 16) Genexis B.V. + Lodewijkstraat 1A + Eindhoven 5652AC + NL + +5C-58-19 (hex) Jingsheng Technology Co., Ltd. +5C5819 (base 16) Jingsheng Technology Co., Ltd. + Linyin street 5# + chengdu sichuan 610000 + CN + +B8-CA-04 (hex) Holtek Semiconductor Inc. +B8CA04 (base 16) Holtek Semiconductor Inc. + No.3, Creation Rd. II, Science Park + Hsinchu 300 + TW + +C4-C5-63 (hex) TECNO MOBILE LIMITED +C4C563 (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +80-B7-08 (hex) Blue Danube Systems, Inc +80B708 (base 16) Blue Danube Systems, Inc + 3131 Jay Street, Suite 201 + Santa Clara CA 95054 + US + +08-BC-20 (hex) Hangzhou Royal Cloud Technology Co., Ltd +08BC20 (base 16) Hangzhou Royal Cloud Technology Co., Ltd + Hangzhou Xixi Road 957, 24, Unit 2, 302 + Hangzhou 310030 + CN + +94-2A-3F (hex) Diversey Inc +942A3F (base 16) Diversey Inc + 2415 Cascade Pointe Blvd + Charlotte NC 28208 + US + +20-31-EB (hex) HDSN +2031EB (base 16) HDSN + 4 allée des roseaux + Saint mitre les remparts BDR 13920 + FR + +F8-C9-6C (hex) Fiberhome Telecommunication Technologies Co.,LTD +F8C96C (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +84-48-23 (hex) WOXTER TECHNOLOGY Co. Ltd +844823 (base 16) WOXTER TECHNOLOGY Co. Ltd + 23F Doushiyangguang, Chegongmiao + Shenzhen 518040 + CN + +F4-1E-5E (hex) RtBrick Inc. +F41E5E (base 16) RtBrick Inc. + 26 Kingston Terrace + Princeton NJ 08540 + US + +6C-76-60 (hex) KYOCERA CORPORATION +6C7660 (base 16) KYOCERA CORPORATION + 2-1-1 Kagahara + Yokohama-shi Kanagawa 224-8502 + JP + +00-21-02 (hex) UpdateLogic Inc. +002102 (base 16) UpdateLogic Inc. + 2 Willow Street, Suite 101 + Southborough MA 01745 + US + +50-58-00 (hex) WyTec International, Inc. +505800 (base 16) WyTec International, Inc. + 19206 Huebner Rd Suite 202 + San Antonio Texas 78258 + US + +C8-D1-2A (hex) Comtrend Corporation +C8D12A (base 16) Comtrend Corporation + 3F-1, 10 Lane 609, Chongxin Road, Section 5, + New Taipei City, Taiwan 24159 + TW + +0C-EA-C9 (hex) ARRIS Group, Inc. +0CEAC9 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E8-2A-44 (hex) Liteon Technology Corporation +E82A44 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +10-A4-BE (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD +10A4BE (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD + NO.268, Fuqian Rd, Jutang community, Guanlan Town, Longhua New district + shenzhen guangdong 518000 + CN + +94-7B-BE (hex) Ubicquia +947BBE (base 16) Ubicquia + 3281 Fairlane Farms Rd + Wellington FL 33449 + US + +EC-C0-6A (hex) PowerChord Group Limited +ECC06A (base 16) PowerChord Group Limited + 1 Blythe Road + London W14 0HG + GB + +94-49-96 (hex) WiSilica Inc +944996 (base 16) WiSilica Inc + 23282 Mill Creek Dr #340 + Laguna Hills CA 92653 + US + +F8-1D-0F (hex) Hitron Technologies. Inc +F81D0F (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +58-C9-35 (hex) Chiun Mai Communication Systems, Inc +58C935 (base 16) Chiun Mai Communication Systems, Inc + No.4, Minsheng St., Tucheng District + New Taipei City 23678 + TW + +00-94-A1 (hex) F5 Networks, Inc. +0094A1 (base 16) F5 Networks, Inc. + 401 Elliott Ave. W. + Seattle WA 98119 + US + +BC-F2-92 (hex) PLANTRONICS, INC. +BCF292 (base 16) PLANTRONICS, INC. + 345 ENCINAL STREET + SANTA CRUZ CA 95060 + US + +04-50-DA (hex) Qiku Internet Network Scientific (Shenzhen) Co., Ltd +0450DA (base 16) Qiku Internet Network Scientific (Shenzhen) Co., Ltd + Building A2, Chi Yuen Technology Park 1001 College Avenue, Nanshan District Shenzhen, Guangdong + Shenzhen Guangdong 518000 + CN + +E8-20-E2 (hex) HUMAX Co., Ltd. +E820E2 (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +00-26-A8 (hex) DAEHAP HYPER-TECH +0026A8 (base 16) DAEHAP HYPER-TECH + Mega center #1108, SK Techno-Park, #190-1, Sangdaewon-Dong, Jungwon-Gu + Seongnam Gyeonggi-Do 462-807 + KR + +78-5C-28 (hex) Prime Motion Inc. +785C28 (base 16) Prime Motion Inc. + Akaho 1134-12 + Komagane Nagano 399-4117 + JP + +8C-5B-F0 (hex) ARRIS Group, Inc. +8C5BF0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +18-90-D8 (hex) Sagemcom Broadband SAS +1890D8 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +88-83-5D (hex) FN-LINK TECHNOLOGY LIMITED +88835D (base 16) FN-LINK TECHNOLOGY LIMITED + No.8, Litong Road, Liuyang Economic & Technical Development Zone + ChangSha Hu Nan 410300 + CN + +EC-9F-0D (hex) IEEE Registration Authority +EC9F0D (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E0-78-A3 (hex) Shanghai Winner Information Technology Co.,Inc +E078A3 (base 16) Shanghai Winner Information Technology Co.,Inc + Lujiazui Software Park,No.190,Lane 91,Eshan Road,Pudong New Area + Shanghai Shanghai 200127 + CN + +00-05-A7 (hex) HYPERCHIP Inc. +0005A7 (base 16) HYPERCHIP Inc. + 180 Peel Street - Ste. #333 + 123 H3C 2G7 + CA + +08-84-66 (hex) Novartis Pharma AG +088466 (base 16) Novartis Pharma AG + Lichtstrasse 35 + Basel 4056 + CH + +30-9F-FB (hex) Ardomus Networks Corporation +309FFB (base 16) Ardomus Networks Corporation + 4F,No. 6 Innovation Road II, Hsinchu Science Park + Hsinchu 300 + TW + +28-23-73 (hex) Digita +282373 (base 16) Digita + Jämsänkatu 2 + Helsinki Uusimaa 00520 + FI + +64-9A-08 (hex) Shenzhen SuperElectron Technology Co.,LTD +649A08 (base 16) Shenzhen SuperElectron Technology Co.,LTD + Layer 13,Haosheng Business Center,Dongbin Road,Nanshan District + Shenzhen guangdong 518052 + CN + +68-A6-82 (hex) Shenzhen YOUHUA Technology Co., Ltd +68A682 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +58-7A-62 (hex) Texas Instruments +587A62 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +54-7A-52 (hex) CTE International srl +547A52 (base 16) CTE International srl + Via Sevardi 7 + Reggio Emilia 42124 + IT + +F0-6E-0B (hex) Microsoft Corporation +F06E0B (base 16) Microsoft Corporation + One Microsoft Way + REDMOND 98052 + US + +34-6F-ED (hex) Enovation Controls +346FED (base 16) Enovation Controls + 5311 S. 122nd E. Ave. + Tulsa OK 74146 + US + +54-33-CB (hex) Apple, Inc. +5433CB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-08-BC (hex) Apple, Inc. +3408BC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +1C-36-BB (hex) Apple, Inc. +1C36BB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-2E-FF (hex) Apple, Inc. +3C2EFF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-E0-25 (hex) dit Co., Ltd. +00E025 (base 16) dit Co., Ltd. + Premier Toyocho Building + Koto-ku Tokyo 135-0056 + JP + +AC-84-C6 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +AC84C6 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +00-15-30 (hex) Dell EMC +001530 (base 16) Dell EMC + 176 South Street + Hopkinton MA 01748 + US + +0C-B2-B7 (hex) Texas Instruments +0CB2B7 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +24-F6-77 (hex) Apple, Inc. +24F677 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B0-CA-68 (hex) Apple, Inc. +B0CA68 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-3C-85 (hex) Apple, Inc. +C83C85 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-87-0D (hex) Unifiedgateways India Private Limited +78870D (base 16) Unifiedgateways India Private Limited + 25 1st Floor 4th Cross KR Road Jayanagar 7th Block West + Bangalore Karnataka 560082 + IN + +A8-82-00 (hex) Hisense Electric Co.,Ltd +A88200 (base 16) Hisense Electric Co.,Ltd + Qianwangang Roard 218 + Qingdao Shandong 266510 + CN + +38-20-A8 (hex) ColorTokens, Inc. +3820A8 (base 16) ColorTokens, Inc. + 2101 Tasman Dr. Suite 200A + Santa Clara CA 95054 + US + +70-58-96 (hex) InShow Technology +705896 (base 16) InShow Technology + Jinqi Zhigu Building, Chongwen Garden, Liuxian Avenue, Nanshan District + shenzhen Guangdong 518055 + CN + +00-05-89 (hex) National Datacomputer +000589 (base 16) National Datacomputer + 900 Middlesex Tpk. + Billerica MA 01821 + US + +3C-A6-16 (hex) vivo Mobile Communication Co., Ltd. +3CA616 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +9C-E0-63 (hex) Samsung Electronics Co.,Ltd +9CE063 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D0-31-69 (hex) Samsung Electronics Co.,Ltd +D03169 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +24-F2-7F (hex) Hewlett Packard Enterprise +24F27F (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +BC-05-43 (hex) AVM GmbH +BC0543 (base 16) AVM GmbH + Alt-Moabit 95 + Berlin 10559 + DE + +00-B6-9F (hex) Latch +00B69F (base 16) Latch + 450 W 33rd St + New York NY 10001 + US + +84-2C-80 (hex) Sichuan Changhong Electric Ltd. +842C80 (base 16) Sichuan Changhong Electric Ltd. + No.35,East MianXin Road,MianYang,Sichaun,China. + MianYang SiChuan PRC 621000 + CN + +3C-C0-79 (hex) Shenzhen One-Nine Intelligent Electronic Science and Technology Co., Ltd +3CC079 (base 16) Shenzhen One-Nine Intelligent Electronic Science and Technology Co., Ltd + Office 3015, Chuangxingda Business Building, No.36. Liuxian 3 Road, Baoan District + Shenzhen Guangdong 518133 + CN + +98-C5-DB (hex) Ericsson AB +98C5DB (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +14-9F-3C (hex) Samsung Electronics Co.,Ltd +149F3C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-EE-E6 (hex) FORMIKE ELECTRONIC CO., LTD +FCEEE6 (base 16) FORMIKE ELECTRONIC CO., LTD + Flats 401-403, Block B, iPARK Building, 26 Dengliang Rd., NanShan Distric + Shenzhen Guang Dong 518054 + CN + +84-E3-27 (hex) TAILYN TECHNOLOGIES INC +84E327 (base 16) TAILYN TECHNOLOGIES INC + NO 10 RUNG-AN ROAD, LU-ZHU DISTRICT + TAOYUAN CITY TAIWAN ROC 33852 + TW + +00-21-B8 (hex) Inphi Corporation +0021B8 (base 16) Inphi Corporation + 112 S. Lakeview Canyon Rd., Suite 100 + Westlake Village CA 91362 + US + +0C-91-60 (hex) Hui Zhou Gaoshengda Technology Co.,LTD +0C9160 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +D8-ED-1C (hex) Magna Technology SL +D8ED1C (base 16) Magna Technology SL + C/Principe de Vergara, 55. 3ª planta + Madrid 28006 + ES + +D8-31-34 (hex) Roku, Inc +D83134 (base 16) Roku, Inc + 150 Winchester Circle + Los Gatos CA 95032 + US + +40-8B-F6 (hex) Shenzhen TCL New Technology Co., Ltd +408BF6 (base 16) Shenzhen TCL New Technology Co., Ltd + TCL Building, #5 Central Nanhai Road, Nanshan District, + Shenzhen, Guangdong, 518067 + CN + +00-00-6B (hex) Silicon Graphics +00006B (base 16) Silicon Graphics + 2011 NORTH SHORELINE BLVD. + MOUNTAIN VIEW CA 94039-7311 + US + +74-37-3B (hex) UNINET Co.,Ltd. +74373B (base 16) UNINET Co.,Ltd. + #1803, Daerung Techno Town15, 401, Simin-daero, Dongan-gu + Anyang-si Gyunggi-do 14057 + KR + +7C-64-56 (hex) Samsung Electronics Co.,Ltd +7C6456 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +F4-6E-24 (hex) NEC Personal Computers, Ltd. +F46E24 (base 16) NEC Personal Computers, Ltd. + Akihabara UDX,14-1, Sotokanda 4-Chome + Chiyoda-ku Tokyo 101-0021 + JP + +88-82-79 (hex) Shenzhen RB-LINK Intelligent Technology Co.Ltd +888279 (base 16) Shenzhen RB-LINK Intelligent Technology Co.Ltd + Second floor, No 22, Wanfeng the third industry area, Shajing , BaoAn district + Shenzhen City 518125 + CN + +68-C6-3A (hex) Espressif Inc. +68C63A (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +A0-64-8F (hex) ASKEY COMPUTER CORP +A0648F (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +C8-50-E9 (hex) Raisecom Technology CO., LTD +C850E9 (base 16) Raisecom Technology CO., LTD + No. 11, East Area, No. 10 Block, East Xibeiwang Road + Beijing 100094 + CN + +10-F1-63 (hex) TNK CO.,LTD +10F163 (base 16) TNK CO.,LTD + 1 Kasugayama.Iitoyo + Tenei-village.Iwase-country Fukushima-prefecture 962-0512 + JP + +88-DA-1A (hex) Redpine Signals, Inc. +88DA1A (base 16) Redpine Signals, Inc. + 2107, N. First St + San Jose CA 95131-2019 + US + +98-EF-9B (hex) OHSUNG +98EF9B (base 16) OHSUNG + 335-4,SANHODAERO,GUMI,GYEONG BUK,KOREA + GUMI GYEONG BUK 730-030 + KR + +14-CF-8D (hex) OHSUNG +14CF8D (base 16) OHSUNG + 181 + GUMI KYUNGBUK 730-030 + KR + +10-44-00 (hex) HUAWEI TECHNOLOGIES CO.,LTD +104400 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B0-E1-7E (hex) HUAWEI TECHNOLOGIES CO.,LTD +B0E17E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E4-A7-C5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E4A7C5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +5C-8D-2D (hex) Shanghai Wellpay Information Technology Co., Ltd +5C8D2D (base 16) Shanghai Wellpay Information Technology Co., Ltd + Loushanguan Road 523, Jin Hongqiao International Center Building, 1501 + Shanghai 200000 + CN + +90-FD-9F (hex) Silicon Laboratories +90FD9F (base 16) Silicon Laboratories + 400 W. Cesar Chavez St. + Austin TX 78701 + US + +B4-30-C0 (hex) York Instruments Ltd +B430C0 (base 16) York Instruments Ltd + The Biocentre, York Science Park + York North Yorkshire YO10 5NY + GB + +E8-1D-A8 (hex) Ruckus Wireless +E81DA8 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +F0-3D-03 (hex) TECNO MOBILE LIMITED +F03D03 (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +DC-F0-90 (hex) Nubia Technology Co.,Ltd. +DCF090 (base 16) Nubia Technology Co.,Ltd. + 6/F-8/F 10/F-11/F A Tower,6/F B Tower,6/F-10/F C Tower Dazu Innovation Mansion, North Ring Rd,No.9018,High-Tech Park Nanshan District + Shenzhen Guandong 518057 + CN + +A0-FE-61 (hex) Vivint Wireless Inc. +A0FE61 (base 16) Vivint Wireless Inc. + 4931 N 300 W + Provo UT 84604 + US + +5C-2B-F5 (hex) Vivint Wireless Inc. +5C2BF5 (base 16) Vivint Wireless Inc. + 4931 N 300 W + Provo UT 84604 + US + +CC-5A-53 (hex) Cisco Systems, Inc +CC5A53 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-60-88 (hex) Analog Devices, Inc. +006088 (base 16) Analog Devices, Inc. + 410 AMHERST STREET-STE #325 + NASHUA NH 03063 + US + +08-4A-CF (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +084ACF (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +2C-27-9E (hex) IEEE Registration Authority +2C279E (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +8C-5F-48 (hex) Continental Intelligent Transportation Systems LLC +8C5F48 (base 16) Continental Intelligent Transportation Systems LLC + 3901 North First Street + San Jose CA 95134 + US + +94-7E-B9 (hex) National Narrowband Network Communications Pty Ltd +947EB9 (base 16) National Narrowband Network Communications Pty Ltd + Unit 10, 1 Talavera Road + Macquarie Park New South Wales 2113 + AU + +64-6E-69 (hex) Liteon Technology Corporation +646E69 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +70-6B-B9 (hex) Cisco Systems, Inc +706BB9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D4-38-9C (hex) Sony Mobile Communications Inc +D4389C (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-C0-EE (hex) KYOCERA Display Corporation +00C0EE (base 16) KYOCERA Display Corporation + 2-14-9 TAMAGAWADAI + tokyo 158 0000 + JP + +24-5F-DF (hex) KYOCERA CORPORATION +245FDF (base 16) KYOCERA CORPORATION + 2-1-1,Kagahara, + Yokohama-shi Kanagawa 224-8502 + JP + +9C-63-ED (hex) zte corporation +9C63ED (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +74-F6-61 (hex) Schneider Electric Fire & Security Oy +74F661 (base 16) Schneider Electric Fire & Security Oy + Sokerilinnantie 11 C + Espoo 02650 + FI + +B8-63-4D (hex) Apple, Inc. +B8634D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +24-C4-2F (hex) Philips Lifeline +24C42F (base 16) Philips Lifeline + 111 Lawrence st + Framingham MA 01702 + US + +2C-B2-1A (hex) Phicomm (Shanghai) Co., Ltd. +2CB21A (base 16) Phicomm (Shanghai) Co., Ltd. + 3666 SiXian Rd.,Songjiang District + Shanghai Shanghai 201616 + CN + +A4-E9-75 (hex) Apple, Inc. +A4E975 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +30-35-AD (hex) Apple, Inc. +3035AD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-41-67 (hex) Apple, Inc. +844167 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-00-C6 (hex) Apple, Inc. +9800C6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-1F-74 (hex) Apple, Inc. +AC1F74 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-5C-2C (hex) Apple, Inc. +A85C2C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-DB-70 (hex) Apple, Inc. +00DB70 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-E5-57 (hex) Nokia Corporation +FCE557 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu Ou 90590 + FI + +48-C5-8D (hex) Lear Corporation GmbH +48C58D (base 16) Lear Corporation GmbH + Industriestrasse 48 + Kronach Bavaria 96317 + DE + +00-28-9F (hex) Semptian Co., Ltd. +00289F (base 16) Semptian Co., Ltd. + Block 5D, 8/F, Software Industry Park, No.14, Haitian 2nd Road, GaoxinSouth, Nanshan District, Shenzhen, China + Shen Zhen GuangDong 518061 + CN + +9C-30-5B (hex) Hon Hai Precision Ind. Co.,Ltd. +9C305B (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +10-4E-89 (hex) Garmin International +104E89 (base 16) Garmin International + 1200 E. 151st St + Olathe KS 66062 + US + +D8-C4-97 (hex) Quanta Computer Inc. +D8C497 (base 16) Quanta Computer Inc. + No. 211, Wen-Hwa 2nd Rd.,Kuei-Shan Dist. + Taoyuan City Taiwan 33377 + TW + +BC-C3-42 (hex) Panasonic Communications Co., Ltd. +BCC342 (base 16) Panasonic Communications Co., Ltd. + 4-1-62 Minoshima Hakata-ku + Fukuoka city Fukuoka 812-8531 + JP + +00-1B-D3 (hex) Panasonic Corporation AVC Networks Company +001BD3 (base 16) Panasonic Corporation AVC Networks Company + 1-15 Matsuo-cho + Kadoma Osaka 571-8504 + JP + +CC-7E-E7 (hex) Panasonic Corporation AVC Networks Company +CC7EE7 (base 16) Panasonic Corporation AVC Networks Company + 1-15 Matsuo-cho + Kadoma City Osaka 571-8504 + JP + +20-C6-EB (hex) Panasonic Corporation AVC Networks Company +20C6EB (base 16) Panasonic Corporation AVC Networks Company + 1-15 Matsuo-cho + Kadoma Osaka 571-8504 + JP + +64-B5-C6 (hex) Nintendo Co.,Ltd +64B5C6 (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +28-30-AC (hex) Frontiir Co. Ltd. +2830AC (base 16) Frontiir Co. Ltd. + 5 Bayint Naung Road, Hlaing Township + Yangon 11052 + MM + +D4-D2-E5 (hex) BKAV Corporation +D4D2E5 (base 16) BKAV Corporation + 2nd floor - HH1 Building - Yen Hoa Urban Area, Yen Hoa Ward, Cau Giay District + HaNoi 100000 + VN + +00-50-B5 (hex) FICHET SECURITE ELECTRONIQUE +0050B5 (base 16) FICHET SECURITE ELECTRONIQUE + 15-17 AVE. MORANE-SAULNIER + + FR + +00-14-39 (hex) Blonder Tongue Laboratories, Inc +001439 (base 16) Blonder Tongue Laboratories, Inc + One Jake Brown Road + Old Bridge 08857 + US + +20-A6-CD (hex) Hewlett Packard Enterprise +20A6CD (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +84-80-2D (hex) Cisco Systems, Inc +84802D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-19-87 (hex) Panasonic Mobile Communications Co.,Ltd. +001987 (base 16) Panasonic Mobile Communications Co.,Ltd. + 600 Saedo-cho, Tsuzuki-ku, + Yokohama City Kanagawa Prefecture 224-8539 + JP + +E4-70-B8 (hex) Intel Corporate +E470B8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +74-1C-27 (hex) ITEL MOBILE LIMITED +741C27 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +00-A0-AC (hex) GILAT SATELLITE NETWORKS, LTD. +00A0AC (base 16) GILAT SATELLITE NETWORKS, LTD. + 24A HABARZEL STREET + + IL + +00-26-09 (hex) Phyllis Co., Ltd. +002609 (base 16) Phyllis Co., Ltd. + 9th Fl., Room 3/4, No. 52, Sec. 2, Chung Shan North Road, + Taipei 104 + TW + +28-F5-37 (hex) IEEE Registration Authority +28F537 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +94-D9-B3 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +94D9B3 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +C8-40-29 (hex) Fiberhome Telecommunication Technologies Co.,LTD +C84029 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +F8-6E-EE (hex) HUAWEI TECHNOLOGIES CO.,LTD +F86EEE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +78-02-B1 (hex) Cisco Systems, Inc +7802B1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B4-0F-3B (hex) Tenda Technology Co.,Ltd.Dongguan branch +B40F3B (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +00-18-8D (hex) Nokia Danmark A/S +00188D (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V 1790 + DK + +00-15-AB (hex) PRO CO SOUND INC +0015AB (base 16) PRO CO SOUND INC + 225 PARSONS STREET + KALAMAZOO MICHIGAN 49008 + US + +58-76-C5 (hex) DIGI I'S LTD +5876C5 (base 16) DIGI I'S LTD + 31, Takahata, Maesawa + Oshu Iwate 029-4204 + JP + +A8-B2-DA (hex) FUJITSU LIMITED +A8B2DA (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +00-13-54 (hex) Zcomax Technologies, Inc. +001354 (base 16) Zcomax Technologies, Inc. + 98 Ford Road + Denville NJ 07834 + US + +78-D8-00 (hex) IEEE Registration Authority +78D800 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +08-35-B2 (hex) CoreEdge Networks Co., Ltd +0835B2 (base 16) CoreEdge Networks Co., Ltd + #806 G Plus Tower, 123, Digital-ro 26gil, Guro-gu + Seoul 08390 + KR + +4C-49-E3 (hex) Xiaomi Communications Co Ltd +4C49E3 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +24-58-80 (hex) VIZEO +245880 (base 16) VIZEO + 13 rue Emile Decorps + Villeurbanne 69100 + FR + +54-66-6C (hex) Shenzhen YOUHUA Technology Co., Ltd +54666C (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +A8-96-75 (hex) Motorola Mobility LLC, a Lenovo Company +A89675 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +38-9A-F6 (hex) Samsung Electronics Co.,Ltd +389AF6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E0-AA-96 (hex) Samsung Electronics Co.,Ltd +E0AA96 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +50-77-05 (hex) Samsung Electronics Co.,Ltd +507705 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F8-34-41 (hex) Intel Corporate +F83441 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +28-D4-36 (hex) Jiangsu dewosi electric co., LTD +28D436 (base 16) Jiangsu dewosi electric co., LTD + Dantu district fengjingchengbang xibanya 503, building 6 + Zhenjiang Jiangsu 212028 + CN + +D4-B2-7A (hex) ARRIS Group, Inc. +D4B27A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +44-EA-4B (hex) Actlas Inc. +44EA4B (base 16) Actlas Inc. + 2-2-32, Asahikawa, + Yokote Akita 013-0033 + JP + +C4-CB-6B (hex) Airista Flow, Inc. +C4CB6B (base 16) Airista Flow, Inc. + 913 Ridgebrook Road Suite 110 + Sparks MD 21152 + US + +18-80-90 (hex) Cisco Systems, Inc +188090 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +78-62-56 (hex) HUAWEI TECHNOLOGIES CO.,LTD +786256 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B0-55-08 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B05508 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B8-75-C0 (hex) PayPal, Inc. +B875C0 (base 16) PayPal, Inc. + 2211 North 1st Street + San Jose California 95131 + US + +00-1C-71 (hex) Emergent Electronics +001C71 (base 16) Emergent Electronics + Bldg 2 Level 3 Suite 305 + Sewickley PA 15143 + US + +00-1A-93 (hex) ERCO Leuchten GmbH +001A93 (base 16) ERCO Leuchten GmbH + Brockhauser Weg 80-82 + Lüdenscheid NRW D-58507 + DE + +94-F6-65 (hex) Ruckus Wireless +94F665 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +B0-90-D4 (hex) Shenzhen Hoin Internet Technology Co., Ltd +B090D4 (base 16) Shenzhen Hoin Internet Technology Co., Ltd + Xusheng Building, No. 4004, Bao’an, Room 1616 Bao’an District + Shenzhen Guangdong 518000 + CN + +C0-BA-E6 (hex) Application Solutions (Electronics and Vision) Ltd +C0BAE6 (base 16) Application Solutions (Electronics and Vision) Ltd + The Riverside Centre + Lewes East Sussex BN7 2AQ + GB + +8C-9F-3B (hex) Qingdao Hisense Communications Co.,Ltd. +8C9F3B (base 16) Qingdao Hisense Communications Co.,Ltd. + Qianwangang Road 218 + Qingdao Shandong 266510 + CN + +00-14-B8 (hex) Hill-Rom +0014B8 (base 16) Hill-Rom + 1125 E. Pearl Street + Batesville IN 47006 + US + +AC-ED-5C (hex) Intel Corporate +ACED5C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +84-20-96 (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +842096 (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District, + Shenzhen Guangdong 518000 + CN + +B4-C1-70 (hex) Yi chip Microelectronics (Hangzhou) Co., Ltd +B4C170 (base 16) Yi chip Microelectronics (Hangzhou) Co., Ltd + Suite 401, Building #13, No. 498 Guoshoujing Rd., Pudong + Shanghai 201210 + CN + +AC-67-06 (hex) Ruckus Wireless +AC6706 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +04-4F-AA (hex) Ruckus Wireless +044FAA (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +58-93-96 (hex) Ruckus Wireless +589396 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +00-1F-41 (hex) Ruckus Wireless +001F41 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +C4-10-8A (hex) Ruckus Wireless +C4108A (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +F0-B0-52 (hex) Ruckus Wireless +F0B052 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +70-DF-2F (hex) Cisco Systems, Inc +70DF2F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +38-94-E0 (hex) Syrotech Networks. Ltd. +3894E0 (base 16) Syrotech Networks. Ltd. + UNIT NO.-5 20F, KIN WING INDUSTERIAL BUILDING,33 KIN WING STREET + TUEN MUN 999077 + HK + +34-F6-4B (hex) Intel Corporate +34F64B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +F4-6B-EF (hex) Sagemcom Broadband SAS +F46BEF (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +10-CD-B6 (hex) Essential Products, Inc. +10CDB6 (base 16) Essential Products, Inc. + 380 Portage Avenue + Palo Alto CA 94306 + US + +A4-F3-E7 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +A4F3E7 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +E4-3A-6E (hex) Shenzhen Zeroone Technology CO.,LTD +E43A6E (base 16) Shenzhen Zeroone Technology CO.,LTD + 9/F.,Building B Tianan Cyber Park ,North Huangge Road,Longgang District + Shenzhen Guangdong 518000 + CN + +7C-E2-CA (hex) Juniper Networks +7CE2CA (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +90-61-AE (hex) Intel Corporate +9061AE (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +6C-F9-D2 (hex) CHENGDU POVODO ELECTRONIC TECHNOLOGY CO., LTD +6CF9D2 (base 16) CHENGDU POVODO ELECTRONIC TECHNOLOGY CO., LTD + High - West West West Center Road on the 4th + Chengdu Sichuan 611731 + CN + +30-B6-2D (hex) Mojo Networks, Inc. +30B62D (base 16) Mojo Networks, Inc. + 339 N.Bernardo Ave + Mountain View CA 94043 + US + +50-18-4C (hex) Platina Systems Inc. +50184C (base 16) Platina Systems Inc. + 3180 De La Cruz Blvd. Ste# 110 + Santa Clara CA 95054 + US + +F4-B7-B3 (hex) vivo Mobile Communication Co., Ltd. +F4B7B3 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +CC-03-D9 (hex) Cisco Meraki +CC03D9 (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco null 94158 + US + +FC-A6-67 (hex) Amazon Technologies Inc. +FCA667 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +C8-1F-EA (hex) Avaya Inc +C81FEA (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +00-27-E3 (hex) Cisco Systems, Inc +0027E3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-18-AE (hex) TVT CO.,LTD +0018AE (base 16) TVT CO.,LTD + 5/F,North Block,CE Lighting House + shenzhen guangdong 518026 + CN + +88-91-DD (hex) Racktivity +8891DD (base 16) Racktivity + Hertstokweg 5 + Ternat Flanders 1741 + BE + +1C-45-93 (hex) Texas Instruments +1C4593 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +90-EC-50 (hex) C.O.B.O. SPA +90EC50 (base 16) C.O.B.O. SPA + via Tito Speri, 10 + Leno Brescia 25024 + IT + +E0-D8-48 (hex) Dell Inc. +E0D848 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +60-27-1C (hex) VIDEOR E. Hartig GmbH +60271C (base 16) VIDEOR E. Hartig GmbH + Carl-Zeiss-Straße 8 + Rödermark Hessen 63322 + DE + +00-EC-0A (hex) Xiaomi Communications Co Ltd +00EC0A (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +C8-D7-B0 (hex) Samsung Electronics Co.,Ltd +C8D7B0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +6C-60-EB (hex) ZHI YUAN ELECTRONICS CO., LIMITED +6C60EB (base 16) ZHI YUAN ELECTRONICS CO., LIMITED + UNIT 2508A 25/F BANK OF AMERICA TOWER, 12 HARCOURT RD CENTRAL  + HONGKONG 999077 + HK + +74-DA-DA (hex) D-Link International +74DADA (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +D8-F1-F0 (hex) Pepxim International Limited +D8F1F0 (base 16) Pepxim International Limited + A5, 5/F, HK Spinners Industrial Building, Phase 6 + Cheung Sha Wan Hong Kong 0 + HK + +DC-C8-F5 (hex) Shanghai UMEinfo CO.,LTD. +DCC8F5 (base 16) Shanghai UMEinfo CO.,LTD. + 16/F,Building B ,NO.15 Changyi Road ,Baoshan District, + Shanghai 200441 + CN + +88-D7-F6 (hex) ASUSTek COMPUTER INC. +88D7F6 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +90-97-F3 (hex) Samsung Electronics Co.,Ltd +9097F3 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +7C-1C-68 (hex) Samsung Electronics Co.,Ltd +7C1C68 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C0-87-EB (hex) Samsung Electronics Co.,Ltd +C087EB (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +04-71-4B (hex) IEEE Registration Authority +04714B (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +2C-41-A1 (hex) Bose Corporation +2C41A1 (base 16) Bose Corporation + The Mountain + Framingham MA 01701-9168 + US + +4C-38-D8 (hex) ARRIS Group, Inc. +4C38D8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +44-7B-BB (hex) Shenzhen YOUHUA Technology Co., Ltd +447BBB (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +9C-7B-D2 (hex) NEOLAB Convergence +9C7BD2 (base 16) NEOLAB Convergence + 4F Yujung bldg., + Seoul 137-070 + KR + +D0-F8-8C (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +D0F88C (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan + Wuhan Hubei 430000 + CN + +2C-B1-15 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +2CB115 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +34-87-3D (hex) Quectel Wireless Solution Co.,Ltd. +34873D (base 16) Quectel Wireless Solution Co.,Ltd. + RM501,Building 13,No.99 TianZhou Road,Xuhui District,Shanghai,China + Shanghai Shanghai 200233 + CN + +10-D0-7A (hex) AMPAK Technology, Inc. +10D07A (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +D4-C1-C8 (hex) zte corporation +D4C1C8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +88-D2-74 (hex) zte corporation +88D274 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-24-49 (hex) Shen Zhen Lite Star Electronics Technology Co., Ltd +002449 (base 16) Shen Zhen Lite Star Electronics Technology Co., Ltd + Xinghong Science Park,1st Ind.Area, + ShenZhen GuangDong 518102 + CN + +00-E1-8C (hex) Intel Corporate +00E18C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +84-79-33 (hex) profichip GmbH +847933 (base 16) profichip GmbH + Einsteinstrasse 6 + Herzogenaurach 91074 + DE + +88-15-44 (hex) Cisco Meraki +881544 (base 16) Cisco Meraki + 660 Alabama St + San Francisco CA 94110 + US + +C4-AB-B2 (hex) vivo Mobile Communication Co., Ltd. +C4ABB2 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +80-B2-34 (hex) Technicolor CH USA Inc. +80B234 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +44-B4-12 (hex) SIUS AG +44B412 (base 16) SIUS AG + Im Langhag 1 + Effretikon 8307 + CH + +0C-B9-12 (hex) JM-DATA GmbH +0CB912 (base 16) JM-DATA GmbH + Hackl-Str. 1 + Traun Upper Austria 4050 + AT + +3C-A3-08 (hex) Texas Instruments +3CA308 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +F4-3E-61 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +F43E61 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + 2F Baiying Building + Shenzhen Guangdong 518067 + CN + +B4-41-7A (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +B4417A (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + 4F,Baiying Building, No.1019,Nanhai RD,Shekou + ShenZhen GuangDong 518067 + CN + +18-52-07 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +185207 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +00-00-62 (hex) BULL HN INFORMATION SYSTEMS +000062 (base 16) BULL HN INFORMATION SYSTEMS + 300 CONCORD ROAD M/S 864A + BILLERICA MA 01821 + US + +E8-C1-D7 (hex) Philips +E8C1D7 (base 16) Philips + TussenDiepen 4 + Drachten Friesland 9206 AD + NL + +4C-81-20 (hex) Taicang T&W Electronics +4C8120 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +28-A6-DB (hex) HUAWEI TECHNOLOGIES CO.,LTD +28A6DB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +14-A0-F8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +14A0F8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C8-F8-6D (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +C8F86D (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +60-45-CB (hex) ASUSTek COMPUTER INC. +6045CB (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +00-11-8B (hex) Alcatel-Lucent Enterprise +00118B (base 16) Alcatel-Lucent Enterprise + 26801 West Agoura Road + Calabasas CA 91301 + US + +00-E0-B1 (hex) Alcatel-Lucent Enterprise +00E0B1 (base 16) Alcatel-Lucent Enterprise + 26801 West Agoura Road + Calabasas CA 91301 + US + +00-E0-DA (hex) Alcatel-Lucent Enterprise +00E0DA (base 16) Alcatel-Lucent Enterprise + 26801 West Agoura Road + CALABASAS CA 91301 + US + +F8-BE-0D (hex) A2UICT Co.,Ltd. +F8BE0D (base 16) A2UICT Co.,Ltd. + 1202, OWNER'S TOWER, 28, + Hwangsaeul-ro 200 beon-gil, Bundang-gu, Seongnam-si, Gyeonggi-do 13595 + KR + +E4-42-A6 (hex) Intel Corporate +E442A6 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +3C-67-8C (hex) HUAWEI TECHNOLOGIES CO.,LTD +3C678C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D4-50-3F (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +D4503F (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +38-8C-50 (hex) LG Electronics +388C50 (base 16) LG Electronics + 222 LG-ro, JINWI-MYEON + Pyeongtaek-si Gyeonggi-do 451-713 + KR + +DC-08-56 (hex) Alcatel-Lucent Enterprise +DC0856 (base 16) Alcatel-Lucent Enterprise + 26801 West Agoura Rd + Calabasas CA 91301 + US + +1C-DA-27 (hex) vivo Mobile Communication Co., Ltd. +1CDA27 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +90-F3-05 (hex) HUMAX Co., Ltd. +90F305 (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +40-95-BD (hex) NTmore.Co.,Ltd +4095BD (base 16) NTmore.Co.,Ltd + 38, Heungan-daero 427 beon-gil, Dongan-gu + Anyang Gyeonggi 431-801 + KR + +98-AA-FC (hex) IEEE Registration Authority +98AAFC (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-14-3F (hex) Hotway Technology Corporation +00143F (base 16) Hotway Technology Corporation + 3F.-4, No.81, Sec. 1, Xintai 5th Rd. + Xizhi Dist. New Taipei City 22101 + TW + +D0-55-B2 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +D055B2 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +14-4F-D7 (hex) IEEE Registration Authority +144FD7 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +B8-55-10 (hex) Zioncom Electronics (Shenzhen) Ltd. +B85510 (base 16) Zioncom Electronics (Shenzhen) Ltd. + A1&A2 Building,Lantian Technology Park, Xinyu Road, Xingqiao Henggang Block, Shajing Street, + Shenzhen Guangdong 518000 + CN + +04-95-73 (hex) zte corporation +049573 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +F0-D7-AA (hex) Motorola Mobility LLC, a Lenovo Company +F0D7AA (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +F8-FF-0B (hex) Electronic Technology Inc. +F8FF0B (base 16) Electronic Technology Inc. + 511 Lyons Ave + Irvington NJ 07111 + US + +7C-6B-F7 (hex) NTI co., ltd. +7C6BF7 (base 16) NTI co., ltd. + 5th floor takei building 2-19-6 + taito taito-ku , Tokyo 1100016 + JP + +00-D3-18 (hex) SPG Controls +00D318 (base 16) SPG Controls + Blue gates business park Stortford road + Dunmow Essex CM61SN + GB + +30-96-FB (hex) Samsung Electronics Co.,Ltd +3096FB (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +48-27-EA (hex) Samsung Electronics Co.,Ltd +4827EA (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +7C-78-7E (hex) Samsung Electronics Co.,Ltd +7C787E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +24-5B-A7 (hex) Apple, Inc. +245BA7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-F0-87 (hex) Apple, Inc. +70F087 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-C6-3C (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +E0C63C (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +00-0C-46 (hex) Allied Telesyn Inc. +000C46 (base 16) Allied Telesyn Inc. + 960 Stewart Drive, Suite B + Sunnyvale California 94085 + US + +00-1F-72 (hex) QingDao Hiphone Technology Co,.Ltd +001F72 (base 16) QingDao Hiphone Technology Co,.Ltd + NO.106,JiangXi Road + QingDao ShanDong 266071 + CN + +00-23-65 (hex) Insta Elektro GmbH +002365 (base 16) Insta Elektro GmbH + Hohe Steinert 10 + Luedenscheid NRW 58509 + DE + +60-91-F3 (hex) vivo Mobile Communication Co., Ltd. +6091F3 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +28-39-5E (hex) Samsung Electronics Co.,Ltd +28395E (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +38-29-5A (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +38295A (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +88-E6-28 (hex) Shenzhen Kezhonglong Optoelectronic Technology Co.,Ltd +88E628 (base 16) Shenzhen Kezhonglong Optoelectronic Technology Co.,Ltd + Floor 3, Bldg. 5, Area B, Xinfu Industrial Park, Chongqing Rd., Baoan Dist,Shenzhen,Guangdong, China + Shenzhen Guangdong 518103 + CN + +58-23-8C (hex) Technicolor CH USA Inc. +58238C (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +CC-82-EB (hex) KYOCERA CORPORATION +CC82EB (base 16) KYOCERA CORPORATION + 2-1-1,Kagahara, Tsuzuki-ku, + Yokohama-shi Kanagawa 224-8502 + JP + +14-98-7D (hex) Technicolor CH USA Inc. +14987D (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +D4-CF-37 (hex) Symbolic IO +D4CF37 (base 16) Symbolic IO + 101 Crawfords Corner Rd. + Holmdel NJ 07733 + US + +D4-7D-FC (hex) TECNO MOBILE LIMITED +D47DFC (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +40-9F-38 (hex) AzureWave Technology Inc. +409F38 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +00-06-31 (hex) Calix Inc. +000631 (base 16) Calix Inc. + 2777 Orchard Parkway + San Jose CA 95134 + US + +BC-2F-3D (hex) vivo Mobile Communication Co., Ltd. +BC2F3D (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +40-FA-7F (hex) Preh Car Connect GmbH +40FA7F (base 16) Preh Car Connect GmbH + Gewerbepark 5 + Dresden 01156 + DE + +00-0D-BB (hex) Nippon Dentsu Co.,Ltd. +000DBB (base 16) Nippon Dentsu Co.,Ltd. + 2-21-1,Isoji + Osaka 552-0003 + JP + +2C-7E-81 (hex) ARRIS Group, Inc. +2C7E81 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +40-7D-0F (hex) HUAWEI TECHNOLOGIES CO.,LTD +407D0F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +68-CC-6E (hex) HUAWEI TECHNOLOGIES CO.,LTD +68CC6E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +30-34-D2 (hex) Availink, Inc. +3034D2 (base 16) Availink, Inc. + Scotia Centre P.O. Box 268GT,Grand Cayman, Cayman Islands + Grand Cayman Grand Cayman 999159 + KY + +50-40-61 (hex) Nokia +504061 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +00-10-8E (hex) HUGH SYMONS CONCEPT Technologies Ltd. +00108E (base 16) HUGH SYMONS CONCEPT Technologies Ltd. + Alder Hills Park + Poole, Dorset BM12 4AR + GB + +E0-51-63 (hex) Arcadyan Corporation +E05163 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +54-E3-F6 (hex) Alcatel-Lucent +54E3F6 (base 16) Alcatel-Lucent + 777 East Middlefield Road + Mountain View CA 94043 + US + +40-B0-34 (hex) Hewlett Packard +40B034 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +B8-16-DB (hex) CHANT SINCERE CO.,LTD +B816DB (base 16) CHANT SINCERE CO.,LTD + 7F-2,NO.188,SEC.3,TA TUNG ROAD + XIZHI DISTRICT, NEW TAIPEI CITY TAIWAN,ROC 22103 + TW + +40-B4-CD (hex) Amazon Technologies Inc. +40B4CD (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +D4-81-D7 (hex) Dell Inc. +D481D7 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +F4-2B-48 (hex) Ubiqam +F42B48 (base 16) Ubiqam + 15 Gonen + Petah Tiqva 4925915 + IL + +50-F1-4A (hex) Texas Instruments +50F14A (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +04-DE-F2 (hex) Shenzhen ECOM Technology Co. Ltd +04DEF2 (base 16) Shenzhen ECOM Technology Co. Ltd + Longhua Street Qinghu Community Longhu Junhui Fashion Apartment + Longhua New District, Shenzhen Guangdong 518012 + CN + +78-C1-A7 (hex) zte corporation +78C1A7 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +4C-78-72 (hex) Cav. Uff. Giacomo Cimberio S.p.A. +4C7872 (base 16) Cav. Uff. Giacomo Cimberio S.p.A. + Via Torchio, 57 + San Maurizio d'Opaglio (Novara) 28017 + IT + +8C-F5-A3 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +8CF5A3 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +8C-C8-F4 (hex) IEEE Registration Authority +8CC8F4 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F4-83-E1 (hex) Shanghai Clouder Semiconductor Co.,Ltd +F483E1 (base 16) Shanghai Clouder Semiconductor Co.,Ltd + Room515,No.8,Wuzhong Rd,Xuhui District + Shanghai Shanghai 200336 + CN + +08-3E-5D (hex) Sagemcom Broadband SAS +083E5D (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +3C-BD-3E (hex) Beijing Xiaomi Electronics Co., Ltd. +3CBD3E (base 16) Beijing Xiaomi Electronics Co., Ltd. + Building C, QingHe ShunShiJiaYe Technology Park, #66 ZhuFang Rd, HaiDian District + Beijing Beijing 10085 + CN + +64-1A-22 (hex) Heliospectra AB +641A22 (base 16) Heliospectra AB + Frans Perssons väg 6 + + SE + +A0-84-CB (hex) SonicSensory,Inc. +A084CB (base 16) SonicSensory,Inc. + 1161 Logan St + Los Angeles CA 90026 + US + +D4-7A-E2 (hex) Samsung Electronics Co.,Ltd +D47AE2 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +68-54-FD (hex) Amazon Technologies Inc. +6854FD (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +00-03-BC (hex) COT GmbH +0003BC (base 16) COT GmbH + Güterstraße 5 + + DE + +D4-B1-69 (hex) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited +D4B169 (base 16) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited + ,Le Shi Building, No.105 Yaojiayuan Road,Chaoyang District,Beijing,China + beijing beijing 100025 + CN + +E4-47-90 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +E44790 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +38-45-4C (hex) Light Labs, Inc. +38454C (base 16) Light Labs, Inc. + 636 Ramona St. + Palo Alto CA 94301 + US + +00-0A-49 (hex) F5 Networks, Inc. +000A49 (base 16) F5 Networks, Inc. + 401 Elliott Ave. W. + Seattle WA 98119 + US + +00-A0-C8 (hex) Adtran Inc +00A0C8 (base 16) Adtran Inc + 901 EXPLORER BLVD. + HUNTSVILLE AL 35806-2807 + US + +F4-96-51 (hex) NAKAYO Inc +F49651 (base 16) NAKAYO Inc + 1-3-2, Soja-machi + Maebashi-shi Gunma 371-0853 + JP + +44-62-46 (hex) Comat AG +446246 (base 16) Comat AG + Bernstrasse 4 + Worb 3076 + CH + +34-FC-B9 (hex) Hewlett Packard Enterprise +34FCB9 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +70-91-8F (hex) Weber-Stephen Products LLC +70918F (base 16) Weber-Stephen Products LLC + 1415 S. Roselle Rd + Palatine IL 60067 + US + +D8-E0-E1 (hex) Samsung Electronics Co.,Ltd +D8E0E1 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +7C-10-15 (hex) Brilliant Home Technology, Inc. +7C1015 (base 16) Brilliant Home Technology, Inc. + 762 Judith Ct + Incline Village NV 89451 + US + +D8-C7-71 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D8C771 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E0-2A-82 (hex) Universal Global Scientific Industrial Co., Ltd. +E02A82 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, LANE 351,SEC.1, TAIPING RD. + TSAOTUEN, NANTOU 54261 + TW + +B0-F9-63 (hex) Hangzhou H3C Technologies Co., Limited +B0F963 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +D4-90-E0 (hex) Topcon Electronics GmbH & Co. KG +D490E0 (base 16) Topcon Electronics GmbH & Co. KG + Industriestraße 7 + Geisenheim 65366 + DE + +A8-40-41 (hex) Dragino Technology Co., Limited +A84041 (base 16) Dragino Technology Co., Limited + 303, Block B, No 8; 349, Jian'An 1 Road,Bao'An + Shenzhen GuangDong 518101 + CN + +E0-22-02 (hex) ARRIS Group, Inc. +E02202 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D8-25-B0 (hex) Rockeetech Systems Co.,Ltd. +D825B0 (base 16) Rockeetech Systems Co.,Ltd. + Unit 201, #6 Lane 51, Shuicheng S Rd. + Shanghai 201103 + CN + +74-61-4B (hex) Chongqing Huijiatong Information Technology Co., Ltd. +74614B (base 16) Chongqing Huijiatong Information Technology Co., Ltd. + Yubei District Longxi Street Hongjin Road No. 498, building Jialeziguang No.1 12-12, 12-13, 12-13, 12-14, 12-15 + Chongqing Chongqing City 401120 + CN + +98-D2-93 (hex) Google, Inc. +98D293 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +CC-B8-A8 (hex) AMPAK Technology, Inc. +CCB8A8 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +10-77-B0 (hex) Fiberhome Telecommunication Technologies Co.,LTD +1077B0 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +F0-1D-BC (hex) Microsoft Corporation +F01DBC (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +34-04-9E (hex) IEEE Registration Authority +34049E (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +94-FB-29 (hex) Zebra Technologies Inc. +94FB29 (base 16) Zebra Technologies Inc. + ONE ZEBRA PLAZA + HOLTSVILLE NY 11742 + US + +B0-70-2D (hex) Apple, Inc. +B0702D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-19-C0 (hex) Apple, Inc. +6C19C0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-20-4F (hex) DEUTSCHE AEROSPACE AG +00204F (base 16) DEUTSCHE AEROSPACE AG + GESCHAEFTSFELD + BUNDESREPUBLIK DEUTSCHLAND + DE + +00-DB-DF (hex) Intel Corporate +00DBDF (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +94-A0-4E (hex) Bostex Technology Co., LTD +94A04E (base 16) Bostex Technology Co., LTD + NO.148 West MinZhou Road + Cixi City Zhejiang Province 315301 + CN + +8C-E1-17 (hex) zte corporation +8CE117 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +68-8A-F0 (hex) zte corporation +688AF0 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +C0-21-0D (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +C0210D (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District, + Shenzhen Guangdong 518000 + CN + +4C-E2-F1 (hex) sclak srl +4CE2F1 (base 16) sclak srl + via borgonuovo 7 + milano mi 20121 + IT + +50-4B-5B (hex) CONTROLtronic GmbH +504B5B (base 16) CONTROLtronic GmbH + Schragenhofstr. 35 + Munich 80992 + DE + +B4-74-47 (hex) CoreOS +B47447 (base 16) CoreOS + PO Box 7775 #55097 + San Francisco CA 94120-7775 + US + +80-D4-A5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +80D4A5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +04-B0-E7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +04B0E7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +44-6A-2E (hex) HUAWEI TECHNOLOGIES CO.,LTD +446A2E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +0C-8D-DB (hex) Cisco Meraki +0C8DDB (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco null 94158 + US + +B0-EE-7B (hex) Roku, Inc +B0EE7B (base 16) Roku, Inc + 150 Winchester Circle + Los Gatos CA 95032 + US + +AC-58-7B (hex) JCT Healthcare +AC587B (base 16) JCT Healthcare + 1/25 London Road + Mile End South South Australia 5031 + AU + +10-62-EB (hex) D-Link International +1062EB (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +00-08-94 (hex) InnoVISION Multimedia Ltd. +000894 (base 16) InnoVISION Multimedia Ltd. + Rm 608, 6/F Tins Enterprises Centre, + Kowloon, + HK + +48-00-33 (hex) Technicolor CH USA Inc. +480033 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +A0-6F-AA (hex) LG Innotek +A06FAA (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +00-26-AB (hex) Seiko Epson Corporation +0026AB (base 16) Seiko Epson Corporation + 3-3-5 OWA + SUWA-SHI NAGANO-KEN 392-8502 + JP + +FC-10-C6 (hex) Taicang T&W Electronics +FC10C6 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +2C-6F-C9 (hex) Hon Hai Precision Ind. Co.,Ltd. +2C6FC9 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +58-EF-68 (hex) Belkin International Inc. +58EF68 (base 16) Belkin International Inc. + 12045 East Waterfront Drive + Playa Vista null 90094 + US + +00-0B-4F (hex) Verifone +000B4F (base 16) Verifone + 2099 Gateway Place + San Jose 95110 + US + +60-C7-98 (hex) Verifone +60C798 (base 16) Verifone + 2455 Augustine Drive + Santa Clara California 95054 + + +C8-66-2C (hex) Beijing Haitai Fangyuan High Technology Co,.Ltd. +C8662C (base 16) Beijing Haitai Fangyuan High Technology Co,.Ltd. + B1st&2nd floor,Unit E,NO.9 Building,Zhongguancun Software Park,Dongbeiwang West Road 8.Haidian District,Beijing + Bei Jing 100094 + CN + +80-96-CA (hex) Hon Hai Precision Ind. Co.,Ltd. +8096CA (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +18-65-71 (hex) Top Victory Electronics (Taiwan) Co., Ltd. +186571 (base 16) Top Victory Electronics (Taiwan) Co., Ltd. + 14F,No.166,Jian 1st Rd + New Taipei City Taiwan 23511 + TW + +F8-3F-51 (hex) Samsung Electronics Co.,Ltd +F83F51 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +50-D7-53 (hex) CONELCOM GmbH +50D753 (base 16) CONELCOM GmbH + Trientlgasse 18c + Innsbruck 6020 + AT + +0C-C4-7A (hex) Super Micro Computer, Inc. +0CC47A (base 16) Super Micro Computer, Inc. + 980 Rock Avenue + San Jose California 95131 + US + +34-D2-70 (hex) Amazon Technologies Inc. +34D270 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +50-79-5B (hex) Interexport Telecomunicaciones S.A. +50795B (base 16) Interexport Telecomunicaciones S.A. + Cerro Colorado 5240 piso 14 + Santiago Region Metropolitana 8320000 + US + +00-16-D9 (hex) NINGBO BIRD CO.,LTD. +0016D9 (base 16) NINGBO BIRD CO.,LTD. + No.999 Dacheng East Road + Fenghua Zhejiang 315500 + CN + +6C-A7-FA (hex) YOUNGBO ENGINEERING INC. +6CA7FA (base 16) YOUNGBO ENGINEERING INC. + 132, Haewian-gil, Dunpo-myeon + Asan-si Chungcheongnam-do 336-873 + KR + +8C-7E-B3 (hex) Lytro, Inc. +8C7EB3 (base 16) Lytro, Inc. + 1300 Terra Bella Avenue + Mountain View California 94043 + US + +B4-B3-84 (hex) ShenZhen Figigantic Electronic Co.,Ltd +B4B384 (base 16) ShenZhen Figigantic Electronic Co.,Ltd + 5F NO.1 Bld East,Guole Industrial Zone,Lirong Road,Longhua New + ShenZhen GuangDong 518109 + CN + +78-28-CA (hex) Sonos, Inc. +7828CA (base 16) Sonos, Inc. + 614 Chapala St + Santa Barbara CA 93101 + US + +00-C0-03 (hex) GLOBALNET COMMUNICATIONS +00C003 (base 16) GLOBALNET COMMUNICATIONS + 912, PLACE TRANS CANADA + CANADA J4G 2M1 + CA + +00-23-4A (hex) Private +00234A (base 16) Private + +2C-40-2B (hex) Smart iBlue Technology Limited +2C402B (base 16) Smart iBlue Technology Limited + Unit 12, 10/F., Hong Man Industrial Centre,2 Hong Man Street, Chai Wan, Hong Kong + Hong Kong 000 + HK + +5C-6B-4F (hex) Hello Inc. +5C6B4F (base 16) Hello Inc. + 438 Shotwell Street + San Francisco CA 94110 + US + +2C-99-24 (hex) ARRIS Group, Inc. +2C9924 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D0-58-A8 (hex) zte corporation +D058A8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +D0-71-C4 (hex) zte corporation +D071C4 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +A0-CC-2B (hex) Murata Manufacturing Co., Ltd. +A0CC2B (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +50-01-D9 (hex) HUAWEI TECHNOLOGIES CO.,LTD +5001D9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-27-1C (hex) MERCURY CORPORATION +00271C (base 16) MERCURY CORPORATION + 90, Gajaeul-ro, Seo-gu + INCHEON 22830 + KR + +E0-D9-E3 (hex) Eltex Enterprise Ltd. +E0D9E3 (base 16) Eltex Enterprise Ltd. + Okruzhnaya st. 29v + Novosibirsk 630020 + RU + +80-5E-C0 (hex) YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD. +805EC0 (base 16) YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD. + 309, 3th Floor, No.16, Yun Ding North Road, Huli District + xiamen Fujian 361015 + CN + +00-7B-18 (hex) SENTRY Co., LTD. +007B18 (base 16) SENTRY Co., LTD. + 792,Pyeongcheon-ro,Wonmi-gu + Bucheon-si, Gyeonggi-do 420-805 + KR + +14-4D-67 (hex) Zioncom Electronics (Shenzhen) Ltd. +144D67 (base 16) Zioncom Electronics (Shenzhen) Ltd. + A1&A2 Building,Lantian Technology Park, Xinyu Road, Xingqiao Henggang Block, Shajing Street, Baoan District + Shenzhen Guangdong 518000 + CN + +4C-E1-73 (hex) IEEE Registration Authority +4CE173 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +0C-D8-6C (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +0CD86C (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +04-97-90 (hex) Lartech telecom LLC +049790 (base 16) Lartech telecom LLC + Bolshoi Sampsonievski 68, lit. N, office 237 + Saint-Petersburg 194100 + RU + +28-EE-D3 (hex) Shenzhen Super D Technology Co., Ltd +28EED3 (base 16) Shenzhen Super D Technology Co., Ltd + Room 201 , Building A former Qianhai Shenzhen-Hong Kong cooperation zone Shenzhen Bay all the way to No. 1 ( settled in Shenzhen Qianhai Business Secretary , Ltd. ) + Shenzhen Guangdong 518000 + CN + +24-C4-4A (hex) zte corporation +24C44A (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +98-54-1B (hex) Intel Corporate +98541B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +1C-40-E8 (hex) SHENZHEN PROGRESS&WIN TECHNOLOGY CO.,LTD +1C40E8 (base 16) SHENZHEN PROGRESS&WIN TECHNOLOGY CO.,LTD + 9F, K1 Mall, Xinsha street, Shajing District, Baoan + Shenzhen Guangdong 518000 + CN + +00-23-D2 (hex) Inhand Electronics, Inc. +0023D2 (base 16) Inhand Electronics, Inc. + 30 West Gude Drive + Rockville Maryland 20850 + US + +DC-0B-34 (hex) LG Electronics (Mobile Communications) +DC0B34 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +40-4E-36 (hex) HTC Corporation +404E36 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +A8-E7-05 (hex) Fiberhome Telecommunication Technologies Co.,LTD +A8E705 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +98-40-BB (hex) Dell Inc. +9840BB (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-60-D6 (hex) NovAtel Inc. +0060D6 (base 16) NovAtel Inc. + SUITE 200, 6715-8TH STREET NE + CALGARY, ALBERTA T2E 8M4 0000 + CA + +50-3A-A0 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +503AA0 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + 3/F, Building R1-B, High-Tech Industrial Park, Nanshan District + Shenzhen Guangdong 518057 + CN + +B0-95-8E (hex) TP-LINK TECHNOLOGIES CO.,LTD. +B0958E (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +C0-25-E9 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +C025E9 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +80-2A-A8 (hex) Ubiquiti Networks Inc. +802AA8 (base 16) Ubiquiti Networks Inc. + 2580 Orchard Parkway + San Jose CA 95131 + US + +F0-9F-C2 (hex) Ubiquiti Networks Inc. +F09FC2 (base 16) Ubiquiti Networks Inc. + 2580 Orchard Parkway + San Jose CA 95131 + US + +18-8B-15 (hex) ShenZhen ZhongRuiJing Technology co.,LTD +188B15 (base 16) ShenZhen ZhongRuiJing Technology co.,LTD + 4th Floor,Building 3,Meng Liyuan Industrial Park, Yousong Road, Longhua New District,Shenzhen,Guangdong Province,China + Shenzhen Guangdong 518109 + CN + +78-8A-20 (hex) Ubiquiti Networks Inc. +788A20 (base 16) Ubiquiti Networks Inc. + 2580 Orchard Pkwy + San Jose CA 95131 + US + +88-6B-0F (hex) Bluegiga Technologies OY +886B0F (base 16) Bluegiga Technologies OY + P.O. BOX 120 + FIN-02631 Espoo + FI + +AC-84-C9 (hex) Sagemcom Broadband SAS +AC84C9 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +24-5C-BF (hex) NCSE +245CBF (base 16) NCSE + Future of China Electronics Science & Technology + Beijing Changping District 102200 + CN + +2C-33-61 (hex) Apple, Inc. +2C3361 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-A4-D0 (hex) Samsung Electronics Co.,Ltd +60A4D0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-87-01 (hex) Samsung Electronics Co.,Ltd +008701 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +5C-99-60 (hex) Samsung Electronics Co.,Ltd +5C9960 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +9C-62-AB (hex) Sumavision Technologies Co.,Ltd +9C62AB (base 16) Sumavision Technologies Co.,Ltd + 6F, Block A2, Power Creative Building,No.1 Shangdi East Road, Haidian District + Beijing 100085 + CN + +C8-F9-46 (hex) LOCOSYS Technology Inc. +C8F946 (base 16) LOCOSYS Technology Inc. + 20F.-13, No. 79, Sec. 1, Xintai 5th Rd, Xizhi Dist. + New Taipei City Taiwan 22101 + TW + +48-7B-6B (hex) HUAWEI TECHNOLOGIES CO.,LTD +487B6B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-3F-D3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +883FD3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-0D-65 (hex) Shenzhen Vsun Communication Technology Co., Ltd. +240D65 (base 16) Shenzhen Vsun Communication Technology Co., Ltd. + 3/F., 19 Block, Wisdomland Business Park, No.2 Nantou Gateway Road, Nanshan District + Shenzhen Guangdong 518000 + CN + +00-0B-14 (hex) ViewSonic Corporation +000B14 (base 16) ViewSonic Corporation + 381 Brea Canyon Road + Walnut California 91789 + US + +C8-02-8F (hex) Nova Electronics (Shanghai) Co., Ltd. +C8028F (base 16) Nova Electronics (Shanghai) Co., Ltd. + Room B706, 7th Floor, MET Plaza, No.268 Tongxie Road + Shanghai Changning District 200335 + CN + +A4-60-11 (hex) Verifone +A46011 (base 16) Verifone + 2099 Gateway Place + San Jose CA 95110 + US + +5C-A9-33 (hex) Luma Home +5CA933 (base 16) Luma Home + 75 5th St + Atlanta GA 30308 + US + +00-13-7E (hex) CorEdge Networks, Inc. +00137E (base 16) CorEdge Networks, Inc. + 7600 Boone Ave N + Brooklyn Park MN 55428 + US + +D8-14-D6 (hex) SURE SYSTEM Co Ltd +D814D6 (base 16) SURE SYSTEM Co Ltd + Bakurou-machi 4-7-5 + Cyuou-ku Osaka 541-0059 + JP + +6C-EF-C6 (hex) SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. +6CEFC6 (base 16) SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. + Nangang Industrial Building, Tangtou Industrial Park, Shiyan, Baoan + Shenzhen Guangdong 518108 + CN + +10-1D-C0 (hex) Samsung Electronics Co.,Ltd +101DC0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-23-41 (hex) Vanderbilt International (SWE) AB +002341 (base 16) Vanderbilt International (SWE) AB + Englundavaegen 7 + Solna SE-171 41 + SE + +40-7C-7D (hex) Nokia +407C7D (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +24-59-0B (hex) White Sky Inc. Limited +24590B (base 16) White Sky Inc. Limited + Floor 5, Building 1, No. 6, Lane 365, Xinhua Road + Shanghai 200052 + CN + +68-EB-AE (hex) Samsung Electronics Co.,Ltd +68EBAE (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +44-4E-1A (hex) Samsung Electronics Co.,Ltd +444E1A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-33-65 (hex) TEM Mobile Limited +143365 (base 16) TEM Mobile Limited + RM1703, North Block, Cangsong Building, Tairan 6 road, Futian District, Shenzhen. + Shenzhen Guangdong 518000 + CN + +80-18-44 (hex) Dell Inc. +801844 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +78-47-1D (hex) Samsung Electronics Co.,Ltd +78471D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A0-75-91 (hex) Samsung Electronics Co.,Ltd +A07591 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +0C-DF-A4 (hex) Samsung Electronics Co.,Ltd +0CDFA4 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-72-BF (hex) Murata Manufacturing Co., Ltd. +B072BF (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +70-1D-C4 (hex) NorthStar Battery Company, LLC +701DC4 (base 16) NorthStar Battery Company, LLC + 4000 Continental Way + Springfield MO 65803 + US + +64-DA-A0 (hex) Robert Bosch Smart Home GmbH +64DAA0 (base 16) Robert Bosch Smart Home GmbH + Schockenriedstraße 17 + Stuttgart 70565 + DE + +14-B8-37 (hex) Shenzhen YOUHUA Technology Co., Ltd +14B837 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +5C-86-13 (hex) Beijing Zhoenet Technology Co., Ltd +5C8613 (base 16) Beijing Zhoenet Technology Co., Ltd + Room B16,No. 8 WenHua East Road,Changping District + Beijing Beijing 102208 + CN + +CC-73-14 (hex) HONG KONG WHEATEK TECHNOLOGY LIMITED +CC7314 (base 16) HONG KONG WHEATEK TECHNOLOGY LIMITED + Building 20,No.2277, ZuChongZhi Road, PuDong District, Shanghai + shanghai 201203 + CN + +B8-EE-65 (hex) Liteon Technology Corporation +B8EE65 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +98-5B-B0 (hex) KMDATA INC. +985BB0 (base 16) KMDATA INC. + 505-2, Daeryung Techno Town 1cha, 18, Gasan Digital 2-ro, Geumcheon-gu + Seoul 153771 + KR + +E0-06-E6 (hex) Hon Hai Precision Ind. Co.,Ltd. +E006E6 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +BC-85-56 (hex) Hon Hai Precision Ind. Co.,Ltd. +BC8556 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +34-23-87 (hex) Hon Hai Precision Ind. Co.,Ltd. +342387 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-26-37 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +002637 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Metan dong + Suwon Kyung-ki do 443-743 + KR + +00-21-19 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +002119 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Metan 3 dong + Suwon Kyung-gi do 443-743 + KR + +F4-D9-FB (hex) Samsung Electronics Co.,Ltd +F4D9FB (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3dong, Yeongtong-gu, + Suwon Gyeonggi-do 443-742 + KR + +3C-62-00 (hex) Samsung Electronics Co.,Ltd +3C6200 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3dong, Yeongtong-gu, + Suwon-City Gyeonggi-do 443-742 + KR + +C4-17-FE (hex) Hon Hai Precision Ind. Co.,Ltd. +C417FE (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +94-39-E5 (hex) Hon Hai Precision Ind. Co.,Ltd. +9439E5 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +64-27-37 (hex) Hon Hai Precision Ind. Co.,Ltd. +642737 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +A4-17-31 (hex) Hon Hai Precision Ind. Co.,Ltd. +A41731 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +5C-A3-9D (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +5CA39D (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Maetan3-Dong, Yeongtong-Gu + Suwon 443-743 + US + +90-18-7C (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +90187C (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Maetan3-Dong, Yeongtong-Gu + Suwon KYUNGGI-DO 443-743 + KR + +50-CC-F8 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +50CCF8 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + Metan Dong 314, Youngtong Gu + Suwon Kyung-gi Do. 443-743 + KR + +00-22-3B (hex) Communication Networks, LLC +00223B (base 16) Communication Networks, LLC + 3 Corporate Drive + Danbury CT 06810 + US + +C0-F8-DA (hex) Hon Hai Precision Ind. Co.,Ltd. +C0F8DA (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-11-FF (hex) Digitro Tecnologia Ltda +0011FF (base 16) Digitro Tecnologia Ltda + Rua: Professora Sofia Quint de Souza, 167 + Florianópolis Santa Catarina 88085-040 + BR + +00-1B-94 (hex) T.E.M.A. S.p.A. +001B94 (base 16) T.E.M.A. S.p.A. + via della Scienza 21 A/C + Castelnuovo Rangone Modena 41051 + IT + +F0-F0-02 (hex) Hon Hai Precision Ind. Co.,Ltd. +F0F002 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +C0-CB-38 (hex) Hon Hai Precision Ind. Co.,Ltd. +C0CB38 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +F0-7B-CB (hex) Hon Hai Precision Ind. Co.,Ltd. +F07BCB (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +50-B7-C3 (hex) Samsung Electronics Co.,Ltd +50B7C3 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3Dong, Yeongtong-Gu + Suwon Geyonggi 443742 + KR + +1C-5A-3E (hex) Samsung Electronics Co.,Ltd +1C5A3E (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3dong, Yeongtong-Gu + Suwon 443742 + US + +A0-21-95 (hex) Samsung Electronics Co.,Ltd +A02195 (base 16) Samsung Electronics Co.,Ltd + #416, Maetan 3-dong + Suwon-si Gyeonggi-do 443-742 + KR + +B0-78-70 (hex) Wi-NEXT, Inc. +B07870 (base 16) Wi-NEXT, Inc. + 530 Lytton Avenue + Palo Alto CA 94301 + US + +E4-7C-F9 (hex) Samsung Electronics Co.,Ltd +E47CF9 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3dong, Yeongtong-gu + Suwon Gyeonggi-do 443742 + KR + +48-44-F7 (hex) Samsung Electronics Co.,Ltd +4844F7 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3dong, Yeongtong-gu + Suwon Gyeonggi-do 443742 + KR + +00-13-77 (hex) Samsung Electronics Co.,Ltd +001377 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3Dong, Yeongtong-Gu + Suwon Geyonggi 443742 + KR + +00-24-54 (hex) Samsung Electronics Co.,Ltd +002454 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3Dong, Yeongtong-Gu + Suwon Geyonggi 443742 + KR + +E8-11-32 (hex) Samsung Electronics Co.,Ltd +E81132 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3Dong, Yeongtong-Gu + Suwon Geyonggi 443742 + KR + +C0-65-99 (hex) Samsung Electronics Co.,Ltd +C06599 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +BC-79-AD (hex) Samsung Electronics Co.,Ltd +BC79AD (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +4C-3C-16 (hex) Samsung Electronics Co.,Ltd +4C3C16 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-73-E0 (hex) Samsung Electronics Co.,Ltd +0073E0 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-17-D5 (hex) Samsung Electronics Co.,Ltd +0017D5 (base 16) Samsung Electronics Co.,Ltd + #94-1 + Gumi-City Gyeong-Buk 730-350 + KR + +00-1E-7D (hex) Samsung Electronics Co.,Ltd +001E7D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-1D-F6 (hex) Samsung Electronics Co.,Ltd +001DF6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F0-08-F1 (hex) Samsung Electronics Co.,Ltd +F008F1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +58-C3-8B (hex) Samsung Electronics Co.,Ltd +58C38B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-E3-B2 (hex) Samsung Electronics Co.,Ltd +00E3B2 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +30-19-66 (hex) Samsung Electronics Co.,Ltd +301966 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F0-E7-7E (hex) Samsung Electronics Co.,Ltd +F0E77E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +94-35-0A (hex) Samsung Electronics Co.,Ltd +94350A (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-1D-25 (hex) Samsung Electronics Co.,Ltd +001D25 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E4-C1-F1 (hex) SHENZHEN SPOTMAU INFORMATION TECHNOLIGY CO., Ltd +E4C1F1 (base 16) SHENZHEN SPOTMAU INFORMATION TECHNOLIGY CO., Ltd + 10F, Block D, 5th Building, Shenzhen Software Industrial Base, Haitian 2nd Rd,Nanshan District + Shenzhen Guangdong 518057 + CN + +24-0A-C4 (hex) Espressif Inc. +240AC4 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +34-31-11 (hex) Samsung Electronics Co.,Ltd +343111 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +08-FD-0E (hex) Samsung Electronics Co.,Ltd +08FD0E (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +04-1B-BA (hex) Samsung Electronics Co.,Ltd +041BBA (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +88-9B-39 (hex) Samsung Electronics Co.,Ltd +889B39 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E4-32-CB (hex) Samsung Electronics Co.,Ltd +E432CB (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +BC-8C-CD (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +BC8CCD (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong 24180 + US + +D0-22-BE (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +D022BE (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong 24180 + US + +EC-9B-F3 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +EC9BF3 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +F4-09-D8 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +F409D8 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +10-D5-42 (hex) Samsung Electronics Co.,Ltd +10D542 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A0-82-1F (hex) Samsung Electronics Co.,Ltd +A0821F (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F0-6B-CA (hex) Samsung Electronics Co.,Ltd +F06BCA (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +AC-36-13 (hex) Samsung Electronics Co.,Ltd +AC3613 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-26-11 (hex) Licera AB +002611 (base 16) Licera AB + Teknikringen 1C + Linköping 58330 + SE + +00-50-94 (hex) ARRIS Group, Inc. +005094 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E0-B7-B1 (hex) ARRIS Group, Inc. +E0B7B1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D8-25-22 (hex) ARRIS Group, Inc. +D82522 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F0-03-8C (hex) AzureWave Technology Inc. +F0038C (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +18-D2-76 (hex) HUAWEI TECHNOLOGIES CO.,LTD +18D276 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-52-18 (hex) Wuxi Keboda Electron Co.Ltd +005218 (base 16) Wuxi Keboda Electron Co.Ltd + No.155 Chunhui Road, Xishan District, + Wuxi Jiangsu 214101 + CN + +00-1E-81 (hex) CNB Technology Inc. +001E81 (base 16) CNB Technology Inc. + #701 Star Valley, 60-11 Gasan-Dong, + Seoul 153777 + KR + +7C-A9-7D (hex) Objenious +7CA97D (base 16) Objenious + 20 rue de Troyon + SEVRES 92310 + FR + +A8-A6-48 (hex) Qingdao Hisense Communications Co.,Ltd. +A8A648 (base 16) Qingdao Hisense Communications Co.,Ltd. + Jiangxi Road + Qingdao Shandong 266071 + CN + +98-5D-AD (hex) Texas Instruments +985DAD (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +D4-36-39 (hex) Texas Instruments +D43639 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +BC-28-2C (hex) e-Smart Systems Pvt. Ltd +BC282C (base 16) e-Smart Systems Pvt. Ltd + 483 FIE, , Patparganj Industrial Area + Delhi Delhi 110092 + IN + +A4-0D-BC (hex) Xiamen Intretech Inc. +A40DBC (base 16) Xiamen Intretech Inc. + FL 7 NO 588 JIAHE RD TORCH CARDEN HIGH-TECH ZONE + Xiamen FUJIAN 361006 + CN + +84-EF-18 (hex) Intel Corporate +84EF18 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +84-C1-C1 (hex) Juniper Networks +84C1C1 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +A8-1B-6A (hex) Texas Instruments +A81B6A (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +34-3D-C4 (hex) BUFFALO.INC +343DC4 (base 16) BUFFALO.INC + AKAMONDORI Bld.,30-20,Ohsu 3-chome,Naka-ku + Nagoya Aichi Pref. 460-8315 + JP + +B0-F8-93 (hex) Shanghai MXCHIP Information Technology Co., Ltd. +B0F893 (base 16) Shanghai MXCHIP Information Technology Co., Ltd. + 9th Floor, No. 5 Building, 2145 Jinshajiang Rd., Putuo District + Shanghai 200333 + CN + +C4-11-E0 (hex) Bull Group Co., Ltd +C411E0 (base 16) Bull Group Co., Ltd + No.32 Sanhai Road,East Guanhaiwei Industrial Zone, Cixi City, Zhejiang, P.R.China + Cixi Zhejiang 315314 + CN + +28-C8-7A (hex) ARRIS Group, Inc. +28C87A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +48-FD-8E (hex) HUAWEI TECHNOLOGIES CO.,LTD +48FD8E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-06-23 (hex) Ultra Electronics Sonar System Division +7C0623 (base 16) Ultra Electronics Sonar System Division + 419 Bridport Road + Greenford Middlesex UB6 8UA + GB + +28-AC-67 (hex) Mach Power, Rappresentanze Internazionali s.r.l. +28AC67 (base 16) Mach Power, Rappresentanze Internazionali s.r.l. + CUPA S.ANIELLO, 112 + NAPOLI Napoli 80146 + IT + +14-82-5B (hex) Hefei Radio Communication Technology Co., Ltd +14825B (base 16) Hefei Radio Communication Technology Co., Ltd + No.108, YinXing Road, High-tech Development Zone, Hefei, Anhui Province, China + Hefei Anhui Province 230088 + CN + +64-12-69 (hex) ARRIS Group, Inc. +641269 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-02-C9 (hex) Mellanox Technologies, Inc. +0002C9 (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +08-00-51 (hex) ExperData +080051 (base 16) ExperData + 88, RUE BRILLAT SAVARIN + 0000 0000 + FR + +00-12-6C (hex) Visonic Technologies 1993 Ltd. +00126C (base 16) Visonic Technologies 1993 Ltd. + 24 Habarzel St. + Tel Aviv 69710 + IL + +AC-61-75 (hex) HUAWEI TECHNOLOGIES CO.,LTD +AC6175 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-44-27 (hex) HUAWEI TECHNOLOGIES CO.,LTD +244427 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-80-C7 (hex) XIRCOM +0080C7 (base 16) XIRCOM + 26025 MUREAU ROAD + CALABASAS CA 91302 + US + +00-01-38 (hex) XAVi Technologies Corp. +000138 (base 16) XAVi Technologies Corp. + 9F, No. 129, Hsing Te Rd, + 241 TAIWAN 241 TAIWAN R.O.C. + TW + +00-16-6D (hex) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd +00166D (base 16) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + 8/F.high Tech Plaza,TianAn Cyberpark,Chegongmiao + Shenzhen Guangdong 518040 + CN + +3C-91-57 (hex) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd +3C9157 (base 16) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + 5F Building 2,No.56,Liuhe Road,Xihu District + Hangzhou Zhejiang 310023 + CN + +00-00-D8 (hex) Novell, Inc. +0000D8 (base 16) Novell, Inc. + 122 EAST 1700 SOUTH M/S:E-12-1 + PROVO UT 84601 + US + +00-1F-46 (hex) Nortel Networks +001F46 (base 16) Nortel Networks + 2221 Lakeside Blvd + Richardson 75082 + US + +00-30-93 (hex) Sonnet Technologies, Inc +003093 (base 16) Sonnet Technologies, Inc + 8 Autry + Irvine, CA 92618 + US + +00-03-4B (hex) Nortel Networks +00034B (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-25-61 (hex) ProCurve Networking by HP +002561 (base 16) ProCurve Networking by HP + 60 Alexandra Terrace + 0000 118502 + SG + +00-80-58 (hex) PRINTER SYSTEMS CORP. +008058 (base 16) PRINTER SYSTEMS CORP. + 207 PARRY PARKWAY + GAITHERSBURG MD 20877 + US + +00-15-7D (hex) POSDATA +00157D (base 16) POSDATA + 276-2,Seohyeon-dong,Bundang-gu, + Seongnam-City Kyeonggi-Do 463-775 + KR + +48-49-C7 (hex) Samsung Electronics Co.,Ltd +4849C7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +84-98-66 (hex) Samsung Electronics Co.,Ltd +849866 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-1C-9C (hex) Nortel Networks +001C9C (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1B-25 (hex) Nortel Networks +001B25 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-19-E1 (hex) Nortel Networks +0019E1 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1D-42 (hex) Nortel Networks +001D42 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-14-0D (hex) Nortel Networks +00140D (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-0E-40 (hex) Nortel Networks +000E40 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +FC-B0-C4 (hex) Shanghai DareGlobal Technologies Co.,Ltd +FCB0C4 (base 16) Shanghai DareGlobal Technologies Co.,Ltd + 22F Info-Tech Building + Shanghai Shanghai 200092 + CN + +A8-9D-D2 (hex) Shanghai DareGlobal Technologies Co.,Ltd +A89DD2 (base 16) Shanghai DareGlobal Technologies Co.,Ltd + 22F Info-Tech Building + Shanghai Shanghai 200092 + CN + +00-E0-0F (hex) Shanghai Baud Data Communication Co.,Ltd. +00E00F (base 16) Shanghai Baud Data Communication Co.,Ltd. + COMMUNICATION DEVELOPMENT CORP + SHANGHAI 0000 + CN + +28-BE-03 (hex) TCT mobile ltd +28BE03 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +90-3A-E6 (hex) PARROT SA +903AE6 (base 16) PARROT SA + 174 Quai de Jemmapes + Paris 75010 + FR + +A0-98-ED (hex) Shandong Intelligent Optical Communication Development Co., Ltd. +A098ED (base 16) Shandong Intelligent Optical Communication Development Co., Ltd. + No.149 Yingcui Road,Torch Town,Advanced Technique Development Area + Jining Shandong 272023 + CN + +00-0E-F4 (hex) Kasda Networks Inc +000EF4 (base 16) Kasda Networks Inc + B-31 Building, Tanglang Industry Zone + Shenzhen Guangdong Province 518055 + CN + +00-16-7A (hex) Skyworth Overseas Development Ltd. +00167A (base 16) Skyworth Overseas Development Ltd. + Room 1505-06,Westlands Centre + 0000 0000 + HK + +A4-29-40 (hex) Shenzhen YOUHUA Technology Co., Ltd +A42940 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +E4-A3-87 (hex) Control Solutions LLC +E4A387 (base 16) Control Solutions LLC + 2520 Diehl Rd + Aurora IL 60502 + US + +18-80-F5 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +1880F5 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +10-E8-78 (hex) Nokia +10E878 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +10-F9-6F (hex) LG Electronics (Mobile Communications) +10F96F (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +C4-43-8F (hex) LG Electronics (Mobile Communications) +C4438F (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +A0-91-69 (hex) LG Electronics (Mobile Communications) +A09169 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +28-6C-07 (hex) XIAOMI Electronics,CO.,LTD +286C07 (base 16) XIAOMI Electronics,CO.,LTD + Xiaomi Building, No.68 Qinghe Middle Street + Haidian District Beijing 100085 + CN + +00-22-80 (hex) A2B Electronics AB +002280 (base 16) A2B Electronics AB + Box 14 + Motala S-591 21 + SE + +40-4A-D4 (hex) Widex A/S +404AD4 (base 16) Widex A/S + Nymoellevej 6 + Lynge Alleroed DK3540 + DK + +98-93-CC (hex) LG ELECTRONICS INC +9893CC (base 16) LG ELECTRONICS INC + 19-1, Cheongho-ri, Jinwi-myeon + Pyeongtaek-si Gyeonggi-do 451-713 + KR + +3C-CD-93 (hex) LG ELECTRONICS INC +3CCD93 (base 16) LG ELECTRONICS INC + 19-1, CHEONGHO-RI, JINWI-MYEON + PYEONGTAEK GYEONGGI-DO 451-713 + KR + +20-21-A5 (hex) LG Electronics (Mobile Communications) +2021A5 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +6C-D6-8A (hex) LG Electronics (Mobile Communications) +6CD68A (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +CC-79-CF (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +CC79CF (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District,Shenzhen,P.R.C + ShenZhen Guangdong 518000 + CN + +00-19-25 (hex) Intelicis Corporation +001925 (base 16) Intelicis Corporation + 4633 Old Ironsides Drive, Suite 150 + Santa Clara CA 95054 + US + +94-76-B7 (hex) Samsung Electronics Co.,Ltd +9476B7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +2C-54-CF (hex) LG Electronics (Mobile Communications) +2C54CF (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +48-59-29 (hex) LG Electronics (Mobile Communications) +485929 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +58-A2-B5 (hex) LG Electronics (Mobile Communications) +58A2B5 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-24-83 (hex) LG Electronics (Mobile Communications) +002483 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-1F-E3 (hex) LG Electronics (Mobile Communications) +001FE3 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +F0-42-1C (hex) Intel Corporate +F0421C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-0F-62 (hex) Alcatel Bell Space N.V. +000F62 (base 16) Alcatel Bell Space N.V. + Berkenrodelei 33 + Hoboken Antwerpen B-2660 + BE + +00-1C-D8 (hex) BlueAnt Wireless +001CD8 (base 16) BlueAnt Wireless + 245 St.Kilda Rd, St Kilda + Melbourne Victoria 3182 + AU + +00-19-AB (hex) Raycom CO ., LTD +0019AB (base 16) Raycom CO ., LTD + A,3-4/FL, Building 1,27 Chuangxin Road, + Beijing 102200 + CN + +4C-33-4E (hex) HIGHTECH +4C334E (base 16) HIGHTECH + No202.gsif, 4 Gyeonggang-ro 2326 beon-gil + Gangneung-si Gangwon-do 25570 + KR + +7C-70-BC (hex) IEEE Registration Authority +7C70BC (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E8-18-63 (hex) IEEE Registration Authority +E81863 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +2C-D1-41 (hex) IEEE Registration Authority +2CD141 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +3C-39-E7 (hex) IEEE Registration Authority +3C39E7 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +BC-66-41 (hex) IEEE Registration Authority +BC6641 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +80-E4-DA (hex) IEEE Registration Authority +80E4DA (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +88-5D-90 (hex) IEEE Registration Authority +885D90 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +C8-8E-D1 (hex) IEEE Registration Authority +C88ED1 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +B0-1F-81 (hex) IEEE Registration Authority +B01F81 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +54-9A-11 (hex) IEEE Registration Authority +549A11 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +B8-D8-12 (hex) IEEE Registration Authority +B8D812 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +1C-21-D1 (hex) IEEE Registration Authority +1C21D1 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +28-36-38 (hex) IEEE Registration Authority +283638 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F4-85-C6 (hex) FDT Technologies +F485C6 (base 16) FDT Technologies + 14027 Memorial Drive #132 + Houston TX 77024 + US + +60-EB-69 (hex) QUANTA COMPUTER INC. +60EB69 (base 16) QUANTA COMPUTER INC. + 211, Wen Hwa 2nd Rd.,Kuei Shan, + Tao Yuan 33377 + TW + +C8-0A-A9 (hex) QUANTA COMPUTER INC. +C80AA9 (base 16) QUANTA COMPUTER INC. + 211, Wen Hwa 2nd Rd., + Tao Yuan Kuei Shan 33377 + TW + +D4-04-FF (hex) Juniper Networks +D404FF (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +C8-75-5B (hex) Quantify Technology Pty. Ltd. +C8755B (base 16) Quantify Technology Pty. Ltd. + Suite 1, 4 Sarich Way + Bentley Western Australia 6102 + AU + +00-1B-24 (hex) QUANTA COMPUTER INC. +001B24 (base 16) QUANTA COMPUTER INC. + No. 211, Wen Hwa 2nd Rd., + Kuei Shan Hsiang Tao Yuan Shien 333 + TW + +00-C0-9F (hex) QUANTA COMPUTER INC. +00C09F (base 16) QUANTA COMPUTER INC. + 7F., 116, HOU-KANG ST., + TAIWAN TAIWAN R.O.C. + TW + +C4-54-44 (hex) QUANTA COMPUTER INC. +C45444 (base 16) QUANTA COMPUTER INC. + No.211, Wen Hwa 2nd Rd., Kuei Shan Hsiang, Tao Yuan Shien, Taiwan, R. O. C. + Taoyuan Taiwan 33377 + TW + +00-26-9E (hex) QUANTA COMPUTER INC. +00269E (base 16) QUANTA COMPUTER INC. + NO. 211, WEN HWA 2RD., KUEI SHAN HSIANG, TAIPEI, SHIEN + TAO YUAN 333 + TW + +88-12-4E (hex) Qualcomm Inc. +88124E (base 16) Qualcomm Inc. + 1700 Technology Drive + San Jose CA 95110 + US + +00-14-28 (hex) Vocollect Inc +001428 (base 16) Vocollect Inc + 703 Rodi Road + Pittsburgh PA 15235 + US + +00-6B-9E (hex) Vizio, Inc +006B9E (base 16) Vizio, Inc + 39 Tesla + Irvine CA 92618 + US + +4C-66-41 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +4C6641 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +5C-A8-6A (hex) HUAWEI TECHNOLOGIES CO.,LTD +5CA86A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-1B-32 (hex) QLogic Corporation +001B32 (base 16) QLogic Corporation + 26650 Aliso Viejo Parkway + Aliso Viejo CA 92656 + US + +00-17-CA (hex) Qisda Corporation +0017CA (base 16) Qisda Corporation + 157 Shan Ying Road, + GueiShan Taoyuan, 333 + TW + +70-F3-95 (hex) Universal Global Scientific Industrial Co., Ltd. +70F395 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, LANE 351,SEC.1, TAIPING RD. + TSAOTUEN, NANTOU 54261 + TW + +48-F7-C0 (hex) Technicolor CH USA Inc. +48F7C0 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +00-15-B7 (hex) Toshiba +0015B7 (base 16) Toshiba + 2-9,Suehiro-Cho + Ome 1988710 + JP + +E8-9D-87 (hex) Toshiba +E89D87 (base 16) Toshiba + 2-9,Suehiro-Cho + Ome Tokyo 1988710 + JP + +E0-95-79 (hex) ORTHOsoft inc, d/b/a Zimmer CAS +E09579 (base 16) ORTHOsoft inc, d/b/a Zimmer CAS + 75 Queen Street, Suite 3300 + Montreal Quebec H3C 2N6 + CA + +A0-AD-A1 (hex) JMR Electronics, Inc +A0ADA1 (base 16) JMR Electronics, Inc + 8968 Fullbright Avenue + Chatsworth California 91311 + US + +BC-C0-0F (hex) Fiberhome Telecommunication Technologies Co.,LTD +BCC00F (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +9C-A5-C0 (hex) vivo Mobile Communication Co., Ltd. +9CA5C0 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong 523860 + CN + +80-C6-AB (hex) Technicolor CH USA Inc. +80C6AB (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +90-A4-DE (hex) Wistron Neweb Corporation +90A4DE (base 16) Wistron Neweb Corporation + 20 Park Avenue II, Hsinchu Science Park, + Hsinchu 308 + TW + +70-E2-84 (hex) Wistron Infocomm (Zhongshan) Corporation +70E284 (base 16) Wistron Infocomm (Zhongshan) Corporation + No.38,East Keji Road,Zhongshan Torch Development Zone,Zhongshan City,Guangdong,China + Zhongshan Guangdong 528437 + CN + +A8-54-B2 (hex) Wistron Neweb Corporation +A854B2 (base 16) Wistron Neweb Corporation + 20 Park Avenue II, Hsin Science Park, Hsinchu 308, Taiwan + HsinChu Taiwan 308 + TW + +30-44-A1 (hex) Shanghai Nanchao Information Technology +3044A1 (base 16) Shanghai Nanchao Information Technology + Floor 1th, building 13, No.368 Zhangjiang Road, Pudong New District, Shanghai + shanghai 200000 + CN + +CC-03-FA (hex) Technicolor CH USA Inc. +CC03FA (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +E0-AC-F1 (hex) Cisco Systems, Inc +E0ACF1 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-01-5B (hex) ITALTEL S.p.A/RF-UP-I +00015B (base 16) ITALTEL S.p.A/RF-UP-I + 20019 Cast.Settimo M.se (MI) + + IT + +00-A0-A8 (hex) RENEX CORPORATION +00A0A8 (base 16) RENEX CORPORATION + 2750 KILLARNEY DRIVE + WOODBRIDGE VA 22192 + US + +00-C0-AB (hex) Telco Systems, Inc. +00C0AB (base 16) Telco Systems, Inc. + 15 Berkshire Road + Mansfield MA 02048 + US + +00-23-F8 (hex) Zyxel Communications Corporation +0023F8 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +00-19-CB (hex) Zyxel Communications Corporation +0019CB (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +2C-09-4D (hex) Raptor Engineering, LLC +2C094D (base 16) Raptor Engineering, LLC + 2556 Anderson Dr. + Belvidere IL 61008 + US + +AC-37-43 (hex) HTC Corporation +AC3743 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +00-1D-7E (hex) Cisco-Linksys, LLC +001D7E (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +E4-FB-8F (hex) MOBIWIRE MOBILES (NINGBO) CO.,LTD +E4FB8F (base 16) MOBIWIRE MOBILES (NINGBO) CO.,LTD + No.999,Dacheng East Road,Fenghua City,Zhejiang Province,China. + Fenghua Zhejiang 315500 + CN + +10-BD-55 (hex) Q-Lab Corporation +10BD55 (base 16) Q-Lab Corporation + 800 Canterbury Rd + Westlake OH 44145 + US + +C4-49-BB (hex) MITSUMI ELECTRIC CO.,LTD. +C449BB (base 16) MITSUMI ELECTRIC CO.,LTD. + 2-11-2, Tsurumaki + Tama-shi Tokyo 206-8567 + JP + +FC-2D-5E (hex) zte corporation +FC2D5E (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +B4-04-18 (hex) Smartchip Integrated Inc. +B40418 (base 16) Smartchip Integrated Inc. + 9B,Science Plaza,1355 JinJiHu Avenue,Suzhou Industrial Park + Suzhou Jiangsu 215021 + CN + +90-CF-7D (hex) Qingdao Hisense Communications Co.,Ltd. +90CF7D (base 16) Qingdao Hisense Communications Co.,Ltd. + Qianwangang Road 218 + Qingdao Shandong 266510 + CN + +F4-0A-4A (hex) INDUSNET Communication Technology Co.,LTD +F40A4A (base 16) INDUSNET Communication Technology Co.,LTD + 3th floor A block,No11 Gaopeng st,Wuhou district + chengdu sichuan 610041 + CN + +F8-5A-00 (hex) Sanford LP +F85A00 (base 16) Sanford LP + 6655 Peachtree Dunwoody Road + Atlanta GA 30228 + US + +FC-55-DC (hex) Baltic Latvian Universal Electronics LLC +FC55DC (base 16) Baltic Latvian Universal Electronics LLC + 5706 Corsa Avenue Suite 102 + Westlake Village CA 91362 + US + +08-01-0F (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +08010F (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +94-18-82 (hex) Hewlett Packard Enterprise +941882 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +60-38-E0 (hex) Belkin International Inc. +6038E0 (base 16) Belkin International Inc. + 12045 E. Waterfront Drive + Playa Vista CA 90094 + US + +88-50-DD (hex) Infiniband Trade Association +8850DD (base 16) Infiniband Trade Association + 3855 SW 153rd Drive + Beaverton OR 97003 + US + +00-25-50 (hex) Riverbed Technology, Inc. +002550 (base 16) Riverbed Technology, Inc. + 125 Cambridge Park Drive + Cambridge MA 02140 + US + +D0-B2-C4 (hex) Technicolor CH USA Inc. +D0B2C4 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +50-AB-3E (hex) Qibixx AG +50AB3E (base 16) Qibixx AG + Bahnhofstrasse 2 + Buchs SG 9471 + CH + +38-76-CA (hex) Shenzhen Smart Intelligent Technology Co.Ltd +3876CA (base 16) Shenzhen Smart Intelligent Technology Co.Ltd + Gaoxin South 4th Road Hi-Tech Industry Park, Nanshan District + Shenzhen Guangdong 518000 + CN + +04-27-58 (hex) HUAWEI TECHNOLOGIES CO.,LTD +042758 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +9C-E3-74 (hex) HUAWEI TECHNOLOGIES CO.,LTD +9CE374 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +8C-D2-E9 (hex) YOKOTE SEIKO CO., LTD. +8CD2E9 (base 16) YOKOTE SEIKO CO., LTD. + 10-18 Minami-Gosyono Yasumoto + Yokote-City Akita 013-0811 + JP + +B8-BB-AF (hex) Samsung Electronics Co.,Ltd +B8BBAF (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +60-C5-AD (hex) Samsung Electronics Co.,Ltd +60C5AD (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +44-2C-05 (hex) AMPAK Technology, Inc. +442C05 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +8C-89-7A (hex) AUGTEK +8C897A (base 16) AUGTEK + Tuanjie Road No.100, Building C, Room 521 + Nanjing Jiangsu 211899 + CN + +F8-45-AD (hex) Konka Group Co., Ltd. +F845AD (base 16) Konka Group Co., Ltd. + Shenzhen Konka R & D Building, 28th floor 15-24 + Nanshan District Guangdong 00000 + CN + +00-0F-E2 (hex) Hangzhou H3C Technologies Co., Limited +000FE2 (base 16) Hangzhou H3C Technologies Co., Limited + Oriental Electronic Bld., NO.2,Chuangye Road + Hai-Dian District Beijing 100085 + CN + +80-F6-2E (hex) Hangzhou H3C Technologies Co., Limited +80F62E (base 16) Hangzhou H3C Technologies Co., Limited + 310 Liuhe Road, Zhijiang Science Park + Hangzhou Zhejiang, 310053 + CN + +60-8D-17 (hex) Sentrus Government Systems Division, Inc +608D17 (base 16) Sentrus Government Systems Division, Inc + 141 Chesterfield Industrial Blvd + Chesterfield MO 63005-1219 + US + +EC-AD-B8 (hex) Apple, Inc. +ECADB8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-01-A7 (hex) Apple, Inc. +9801A7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-79-ED (hex) SHARP Corporation +6879ED (base 16) SHARP Corporation + 22-22,Nagaike-cho + Osaka city Osaka prefecture 545-8522 + JP + +00-23-82 (hex) Lih Rong electronic Enterprise Co., Ltd. +002382 (base 16) Lih Rong electronic Enterprise Co., Ltd. + No. 2, Lane 387, Hsin Shu Rd. + Hsin Chuang City, Taipei 242 + TW + +24-F0-94 (hex) Apple, Inc. +24F094 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +08-6D-41 (hex) Apple, Inc. +086D41 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B4-D5-BD (hex) Intel Corporate +B4D5BD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +98-AA-3C (hex) Will i-tech Co., Ltd. +98AA3C (base 16) Will i-tech Co., Ltd. + 34, Deokcheon-ro, Manan-gu, Anyang-si, Gyeonggi-do, Korea + Anyang 14088 + KR + +BC-AD-28 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +BCAD28 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.469,Jianghui Road + Hangzhou Zhejiang 310052 + CN + +F4-91-1E (hex) ZHUHAI EWPE INFORMATION TECHNOLOGY INC +F4911E (base 16) ZHUHAI EWPE INFORMATION TECHNOLOGY INC + Room 409,NO.10,Technology 1st Road, Gangwan Av.,Tangjia Bay Town,Zhuhai,Guangdong,China + Zhuhai Guangdong 519070 + CN + +00-25-52 (hex) VXi Corporation +002552 (base 16) VXi Corporation + 271 Locust Street + Dover NH 03820 + US + +6C-E9-83 (hex) Gastron Co., LTD. +6CE983 (base 16) Gastron Co., LTD. + #75-10, Palgok2-dong, Sangnok-gu, + Ansan-city Kyunggi-do 426-190 + KR + +28-E3-1F (hex) Xiaomi Communications Co Ltd +28E31F (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +98-90-96 (hex) Dell Inc. +989096 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +DC-37-52 (hex) GE +DC3752 (base 16) GE + 650 Markland Street + Markham Ontario L6C 0M1 + CA + +DC-D9-16 (hex) HUAWEI TECHNOLOGIES CO.,LTD +DCD916 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-02-2E (hex) TEAC Corp. R& D +00022E (base 16) TEAC Corp. R& D + 857 Koyata, Iruma + + JP + +00-60-B0 (hex) Hewlett Packard +0060B0 (base 16) Hewlett Packard + MS 42LE + CUPERTINO CA 95014 + US + +7C-73-8B (hex) Cocoon Alarm Ltd +7C738B (base 16) Cocoon Alarm Ltd + 46 The Calls + Leeds West Yorkshire LS2 7EY + GB + +F8-0F-84 (hex) Natural Security SAS +F80F84 (base 16) Natural Security SAS + 165 Avenue de Bretagne + Lille 59000 + FR + +44-A4-2D (hex) TCT mobile ltd +44A42D (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +70-F9-6D (hex) Hangzhou H3C Technologies Co., Limited +70F96D (base 16) Hangzhou H3C Technologies Co., Limited + 310 Liuhe Road, Zhijiang Science Park + Hangzhou Zhejiang, 310053 + CN + +BC-6A-44 (hex) Commend International GmbH +BC6A44 (base 16) Commend International GmbH + Saalachstrasse 51 + Salzburg Salzburg A-5020 + AT + +F0-EE-58 (hex) PACE Telematics GmbH +F0EE58 (base 16) PACE Telematics GmbH + Haid-und-Neu-Str. 18 + Karlsruhe 76131 + DE + +08-3F-BC (hex) zte corporation +083FBC (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-C0-F0 (hex) Kingston Technology Company, Inc. +00C0F0 (base 16) Kingston Technology Company, Inc. + 17600 NEWHOPE STREET + FOUNTAIN VALLEY CA 92708 + US + +94-3B-B1 (hex) Kaonmedia CO., LTD. +943BB1 (base 16) Kaonmedia CO., LTD. + KAONMEDIA Building 513-4 + Sungnam-City Kyonggi-Do 463-839, KOREA + KR + +00-18-D7 (hex) JAVAD GNSS, Inc. +0018D7 (base 16) JAVAD GNSS, Inc. + 1731 Technology Drive, Suite 680 + San Jose CA 95110 + US + +00-1F-09 (hex) Jastec +001F09 (base 16) Jastec + Jastec B/D 2F, 92-7 Kumgok-dong, + Boondang-gu, 463-804 + KR + +AC-62-0D (hex) Jabil Circuit(Wuxi) Co.,Ltd +AC620D (base 16) Jabil Circuit(Wuxi) Co.,Ltd + Lot J9, J10 Export Processing Zone + Wuxi City Jiangsu 214028 + CN + +08-00-0D (hex) International Computers, Ltd +08000D (base 16) International Computers, Ltd + WENLOCK WAY + na UNITED KINGDOM + GB + +1C-73-70 (hex) Neotech +1C7370 (base 16) Neotech + 104, 37 Yaeun-ro + Gumi-si Gyoungsangbuk-do 730-711 + KR + +30-E3-7A (hex) Intel Corporate +30E37A (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-00-C9 (hex) Emulex Corporation +0000C9 (base 16) Emulex Corporation + 3333 Susan Street + Costa Mesa CA 92626 + US + +00-40-AA (hex) Valmet Automation +0040AA (base 16) Valmet Automation + Lentokentänkatu 11, P.O.Box 237 + Tampere FIN-3310 + FI + +D0-B0-CD (hex) Moen +D0B0CD (base 16) Moen + 25300 Al Moen Dr + North Olmstead OH 44070-8022 + US + +70-50-AF (hex) BSkyB Ltd +7050AF (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +F4-EF-9E (hex) SGSG SCIENCE & TECHNOLOGY CO. LTD +F4EF9E (base 16) SGSG SCIENCE & TECHNOLOGY CO. LTD + 3RD Fl, Bldg A3, No.1 software Park Rd + Zhuhai Guangdong 519085 + CN + +1C-74-0D (hex) Zyxel Communications Corporation +1C740D (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +60-3E-CA (hex) Cambridge Medical Robotics Ltd +603ECA (base 16) Cambridge Medical Robotics Ltd + Unit 2, Crome Lea Business Park + Madingley Road Cambridgeshire CB23 7PH + GB + +00-1F-1F (hex) Edimax Technology Co. Ltd. +001F1F (base 16) Edimax Technology Co. Ltd. + No. 278, Xinhu 1st Road + Taipei City Neihu Dist 248 + TW + +00-02-0E (hex) ECI Telecom Ltd. +00020E (base 16) ECI Telecom Ltd. + 30 Hasivim St + Petach-Tikva 49133 49133 + IL + +20-0A-5E (hex) Xiangshan Giant Eagle Technology Developing Co., Ltd. +200A5E (base 16) Xiangshan Giant Eagle Technology Developing Co., Ltd. + Juexi Road no.9 Juexi street + Ningbo Zhejiang 315708 + CN + +9C-74-1A (hex) HUAWEI TECHNOLOGIES CO.,LTD +9C741A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E4-A8-B6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E4A8B6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-4C-07 (hex) HUAWEI TECHNOLOGIES CO.,LTD +244C07 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +74-6F-F7 (hex) Wistron Neweb Corporation +746FF7 (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +B8-AE-ED (hex) Elitegroup Computer Systems Co.,Ltd. +B8AEED (base 16) Elitegroup Computer Systems Co.,Ltd. + No. 239, Sec. 2, Ti Ding Blvd., + Taipei 11493 + TW + +00-0D-B0 (hex) Olym-tech Co.,Ltd. +000DB0 (base 16) Olym-tech Co.,Ltd. + Room 401/402,No.1,Songling Road,Hi-tech + Shenzhen Guangdong 518031 + CN + +30-F6-B9 (hex) Ecocentric Energy +30F6B9 (base 16) Ecocentric Energy + E3 The Innovation Centre, 9 De Laeter Way, Technology Park + Bentley Western Australia 6102 + AU + +84-7B-EB (hex) Dell Inc. +847BEB (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +54-51-1B (hex) HUAWEI TECHNOLOGIES CO.,LTD +54511B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +68-53-6C (hex) SPnS Co.,Ltd +68536C (base 16) SPnS Co.,Ltd + #315, Woolim Lions Valley 2nd, Gasan-dong, Geumcheon-gu + Seoul 08591 + KR + +1C-EA-1B (hex) Nokia +1CEA1B (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +D4-61-2E (hex) HUAWEI TECHNOLOGIES CO.,LTD +D4612E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B0-E2-E5 (hex) Fiberhome Telecommunication Technologies Co.,LTD +B0E2E5 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +00-1F-A7 (hex) Sony Interactive Entertainment Inc. +001FA7 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +90-46-A2 (hex) Tedipay UK Ltd +9046A2 (base 16) Tedipay UK Ltd + Level 39, One Canada Square + London E14 5AB + GB + +64-79-A7 (hex) Phison Electronics Corp. +6479A7 (base 16) Phison Electronics Corp. + No.1, Qun Yi Rd., Jhunan, + Miaoli 350 + TW + +CC-B1-1A (hex) Samsung Electronics Co.,Ltd +CCB11A (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +70-3C-03 (hex) RadiAnt Co.,Ltd +703C03 (base 16) RadiAnt Co.,Ltd + 102-610, 36, Bucheon-ro 198beon-gil, Wonmi-gu + Bucheon-si Gyeonggi-do 14557 + KR + +00-C1-64 (hex) Cisco Systems, Inc +00C164 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +DC-2D-CB (hex) Beijing Unis HengYue Technology Co., Ltd. +DC2DCB (base 16) Beijing Unis HengYue Technology Co., Ltd. + Room 402, No. 2 Block, No. 1 yard, Zhongguancun east road, Haidian District + Beijing 100190 + CN + +2C-96-62 (hex) Invenit BV +2C9662 (base 16) Invenit BV + Lange Broekstraat 3 + Raamsdonk Noord-Brabant 4944 XH + NL + +CC-D3-E2 (hex) Jiangsu Yinhe Electronics Co.,Ltd. +CCD3E2 (base 16) Jiangsu Yinhe Electronics Co.,Ltd. + No.188 Nanhuan Road, TangQiao Town + Zhangjiagang Jiangsu 215611 + CN + +E4-FA-ED (hex) Samsung Electronics Co.,Ltd +E4FAED (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +28-83-35 (hex) Samsung Electronics Co.,Ltd +288335 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +DC-CF-96 (hex) Samsung Electronics Co.,Ltd +DCCF96 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +AC-44-F2 (hex) YAMAHA CORPORATION +AC44F2 (base 16) YAMAHA CORPORATION + 10-1 Nakazawa-cho, Naka-ku + Hamamatsu Shizuoka 430-8650 + JP + +1C-5F-2B (hex) D-Link International +1C5F2B (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +1C-98-EC (hex) Hewlett Packard Enterprise +1C98EC (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +70-66-1B (hex) Sonova AG +70661B (base 16) Sonova AG + Laubisruetistrasse 28 + Staefa 8712 + CH + +B0-7F-B9 (hex) NETGEAR +B07FB9 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +04-7E-4A (hex) moobox CO., Ltd. +047E4A (base 16) moobox CO., Ltd. + No 801, Yanchang Zhong Road + Shanghai Shanghai 200072 + CN + +00-80-E5 (hex) NetApp +0080E5 (base 16) NetApp + 1395 Crossman Ave + Sunnyvale, CA 94089 + US + +9C-5C-8E (hex) ASUSTek COMPUTER INC. +9C5C8E (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +C8-87-22 (hex) Lumenpulse +C88722 (base 16) Lumenpulse + 1751 Richardson, suite 1505 + Montreal Quebec H3K 1G6 + CA + +84-68-3E (hex) Intel Corporate +84683E (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +E0-CD-FD (hex) Beijing E3Control Technology Co, LTD +E0CDFD (base 16) Beijing E3Control Technology Co, LTD + 1 Shangdi East Rd, Building A, Rm 205 + Beijing Beijing 100085 + CN + +00-08-95 (hex) DIRC Technologie GmbH & Co.KG +000895 (base 16) DIRC Technologie GmbH & Co.KG + Borsigstraße 13 + Ratingen NRW 40880 + DE + +60-AC-C8 (hex) KunTeng Inc. +60ACC8 (base 16) KunTeng Inc. + Room302, 3rd Floor, Building1 ,No.8 NongDa South street + HaiDian District BeiJing 100084 + CN + +CC-B3-AB (hex) shenzhen Biocare Bio-Medical Equipment Co.,Ltd. +CCB3AB (base 16) shenzhen Biocare Bio-Medical Equipment Co.,Ltd. + #A735, 7/F, Block A, Shenzhen Mingyou Industrial Products Exhibition & Procurement Center, Baoyuan Road, Xixiang Sub-district, Bao'an District, 518102 Shenzhen, P.R. China + Shenzhen 518000 + CN + +E4-B3-18 (hex) Intel Corporate +E4B318 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +74-3E-2B (hex) Ruckus Wireless +743E2B (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +E0-C7-67 (hex) Apple, Inc. +E0C767 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +80-ED-2C (hex) Apple, Inc. +80ED2C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-34-04 (hex) TCT mobile ltd +F03404 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +80-D1-60 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +80D160 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +30-78-5C (hex) Partow Tamas Novin (Parman) +30785C (base 16) Partow Tamas Novin (Parman) + UNIT 32 NO.31 26TH WEST AVE ,ALLAMEH TABATABAIE ST.SAADAT ABAD + Tehran Tehran 1997968413 + IR + +24-69-68 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +246968 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +8C-A2-FD (hex) Starry, Inc. +8CA2FD (base 16) Starry, Inc. + PO Box 52226 + Boston MA 02205 + US + +84-BA-3B (hex) CANON INC. +84BA3B (base 16) CANON INC. + 30-2 Shimomaruko 3-chome, + Ohta-ku Tokyo 146-8501 + JP + +00-05-85 (hex) Juniper Networks +000585 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +20-4E-71 (hex) Juniper Networks +204E71 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-19-4F (hex) Nokia Danmark A/S +00194F (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-BD-3A (hex) Nokia Corporation +00BD3A (base 16) Nokia Corporation + Joensuunkatu 7 + Salo Varsinais-Suomi 24101 + FI + +80-50-1B (hex) Nokia Corporation +80501B (base 16) Nokia Corporation + Joensuunkatu 7 + Salo Varsinais-Suomi 24101 + FI + +A0-4E-04 (hex) Nokia Corporation +A04E04 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo Varsinais-Suomi 24101 + FI + +00-12-62 (hex) Nokia Danmark A/S +001262 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-14-A7 (hex) Nokia Danmark A/S +0014A7 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-15-A0 (hex) Nokia Danmark A/S +0015A0 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-16-BC (hex) Nokia Danmark A/S +0016BC (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-17-4B (hex) Nokia Danmark A/S +00174B (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-26-69 (hex) Nokia Danmark A/S +002669 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +AC-61-EA (hex) Apple, Inc. +AC61EA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-B5-4D (hex) Apple, Inc. +38B54D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +1C-5C-F2 (hex) Apple, Inc. +1C5CF2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-7E-33 (hex) Nokia Danmark A/S +A87E33 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-24-03 (hex) Nokia Danmark A/S +002403 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-24-04 (hex) Nokia Danmark A/S +002404 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-19-B7 (hex) Nokia Danmark A/S +0019B7 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-17-B0 (hex) Nokia Danmark A/S +0017B0 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-21-09 (hex) Nokia Danmark A/S +002109 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-21-08 (hex) Nokia Danmark A/S +002108 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1B-33 (hex) Nokia Danmark A/S +001B33 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-15-DE (hex) Nokia Danmark A/S +0015DE (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-02-EE (hex) Nokia Danmark A/S +0002EE (base 16) Nokia Danmark A/S + Frederikskaj, Copenhagen V + copenhagen 12345 + DK + +D8-F7-10 (hex) Libre Wireless Technologies Inc. +D8F710 (base 16) Libre Wireless Technologies Inc. + 5405 Alton Parkway + Irvine, CA CA 92604 + US + +3C-59-1E (hex) TCL King Electrical Appliances (Huizhou) Co., Ltd +3C591E (base 16) TCL King Electrical Appliances (Huizhou) Co., Ltd + 7/FTCL Multimedia Building, TCL International E City, No.1001 Zhongshanyuan Road, Nanshan + Shenzhen Guangdong 518052 + CN + +C4-36-55 (hex) Shenzhen Fenglian Technology Co., Ltd. +C43655 (base 16) Shenzhen Fenglian Technology Co., Ltd. + Room 302, 3F, Block 2, Oriental Cyberport, No. 2, Xinxi Road + Shenzhen Guangdong 518057 + CN + +E0-B9-E5 (hex) Technicolor +E0B9E5 (base 16) Technicolor + Prins Boudewijnlaan 47 + Edegem - Belgium B-2650 + BE + +00-30-DA (hex) Comtrend Corporation +0030DA (base 16) Comtrend Corporation + 3F-1, 10 Lane 609, Chongxin Road, Section 5, + New Taipei City, Taiwan 24159 + TW + +64-68-0C (hex) Comtrend Corporation +64680C (base 16) Comtrend Corporation + 3F-1, 10 Lane 609, Chongxin Road, Section 5, + New Taipei City, Taiwan 24159 + TW + +38-72-C0 (hex) Comtrend Corporation +3872C0 (base 16) Comtrend Corporation + 3F-1, 10 Lane 609, Chongxin Road, Section 5, + New Taipei City, Taiwan 24159 + TW + +A8-06-00 (hex) Samsung Electronics Co.,Ltd +A80600 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-26-82 (hex) Gemtek Technology Co., Ltd. +002682 (base 16) Gemtek Technology Co., Ltd. + No.1 Jen Ai Road, Hsinchu Industrial Park, + Hukou, Hsinchu 303 + TW + +00-09-E1 (hex) Gemtek Technology Co., Ltd. +0009E1 (base 16) Gemtek Technology Co., Ltd. + No.1 Jen Ai Road + Hukou Hsinchu 303 + TW + +14-C1-26 (hex) Nokia Corporation +14C126 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo Varsinais-Suomi 24101 + FI + +60-01-94 (hex) Espressif Inc. +600194 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +F0-5A-09 (hex) Samsung Electronics Co.,Ltd +F05A09 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +50-32-75 (hex) Samsung Electronics Co.,Ltd +503275 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +08-FC-88 (hex) Samsung Electronics Co.,Ltd +08FC88 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +02-70-B3 (hex) DATA RECALL LTD. +0270B3 (base 16) DATA RECALL LTD. + SONDES PLACE + 12345 UNITED KINGDOM + GB + +00-01-36 (hex) CyberTAN Technology Inc. +000136 (base 16) CyberTAN Technology Inc. + 99, Park Avenue III + Hsinchu 12345 + TW + +D0-4D-2C (hex) Roku, Inc. +D04D2C (base 16) Roku, Inc. + 12980 Saratoga Ave + Saratoga CA 95070 + US + +B0-A7-37 (hex) Roku, Inc. +B0A737 (base 16) Roku, Inc. + 12980 Saratoga Ave + Saratoga CA 95070 + US + +14-0C-76 (hex) FREEBOX SAS +140C76 (base 16) FREEBOX SAS + 16 rue de la Ville l'Eveque + PARIS 75008 + FR + +00-1B-E9 (hex) Broadcom +001BE9 (base 16) Broadcom + 16215 Alton Parkway + Irvine CA 92618 + US + +00-19-C7 (hex) Cambridge Industries(Group) Co.,Ltd. +0019C7 (base 16) Cambridge Industries(Group) Co.,Ltd. + Room 309,333 Hong Qiao Road + Shanghai 200030 + CN + +70-D9-31 (hex) Cambridge Industries(Group) Co.,Ltd. +70D931 (base 16) Cambridge Industries(Group) Co.,Ltd. + 22Floor,Qilai Tower;889Yishan Road + shanghai 200233 + CN + +02-9D-8E (hex) CARDIAC RECORDERS, INC. +029D8E (base 16) CARDIAC RECORDERS, INC. + 34 SCARBORO RD + UK UNITED KINGDOM + GB + +00-40-2A (hex) Canoga Perkins Corporation +00402A (base 16) Canoga Perkins Corporation + 21012 LASSEN STREET + CHATSWORTH CA 91311-4241 + US + +A4-C7-DE (hex) Cambridge Industries(Group) Co.,Ltd. +A4C7DE (base 16) Cambridge Industries(Group) Co.,Ltd. + 22 Floor,Qilai Tower;889 Yishan Road + Shanghai 200233 + CN + +D8-B8-F6 (hex) Nantworks +D8B8F6 (base 16) Nantworks + 12230 El Camino Real, Suite 400 + San Diego CA 92130 + US + +00-80-77 (hex) Brother industries, LTD. +008077 (base 16) Brother industries, LTD. + RESEARCH LABORATORY + piscatawa 12345 + JP + +24-F5-AA (hex) Samsung Electronics Co.,Ltd +24F5AA (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +98-83-89 (hex) Samsung Electronics Co.,Ltd +988389 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +84-A4-66 (hex) Samsung Electronics Co.,Ltd +84A466 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +C4-57-6E (hex) Samsung Electronics Co.,Ltd +C4576E (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +50-85-69 (hex) Samsung Electronics Co.,Ltd +508569 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +00-60-BB (hex) Cabletron Systems, Inc. +0060BB (base 16) Cabletron Systems, Inc. + 35 INDUSTRIAL WAY + ROCHESTER NH 03866-5005 + US + +F8-D0-BD (hex) Samsung Electronics Co.,Ltd +F8D0BD (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +78-59-5E (hex) Samsung Electronics Co.,Ltd +78595E (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +0C-14-20 (hex) Samsung Electronics Co.,Ltd +0C1420 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +94-B1-0A (hex) Samsung Electronics Co.,Ltd +94B10A (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +3C-BB-FD (hex) Samsung Electronics Co.,Ltd +3CBBFD (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A4-84-31 (hex) Samsung Electronics Co.,Ltd +A48431 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A0-B4-A5 (hex) Samsung Electronics Co.,Ltd +A0B4A5 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E4-F8-EF (hex) Samsung Electronics Co.,Ltd +E4F8EF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +DC-44-6D (hex) Allwinner Technology Co., Ltd +DC446D (base 16) Allwinner Technology Co., Ltd + No.9 Technology Road 2, High-Tech Zone + Zhuhai Guangdong 519085 + CN + +74-5A-AA (hex) HUAWEI TECHNOLOGIES CO.,LTD +745AAA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +04-FE-8D (hex) HUAWEI TECHNOLOGIES CO.,LTD +04FE8D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-13-33 (hex) BaudTec Corporation +001333 (base 16) BaudTec Corporation + 12F, NO.181, Sec. 1. Tatung Rd., + Hsichih Taipei Hsien 221 + TW + +58-67-1A (hex) Barnes&Noble +58671A (base 16) Barnes&Noble + 400 HAMILTON AVENUE + PALO ALTO CA 94301 + US + +00-26-75 (hex) Aztech Electronics Pte Ltd +002675 (base 16) Aztech Electronics Pte Ltd + 31 Ubi Road 1 + Singapore 408694 + SG + +00-24-FE (hex) AVM GmbH +0024FE (base 16) AVM GmbH + Alt-Moabit 95 + Berlin 10559 + DE + +C0-25-06 (hex) AVM GmbH +C02506 (base 16) AVM GmbH + Alt-Moabit 95 + Berlin 10559 + DE + +40-5D-82 (hex) NETGEAR +405D82 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +DC-EF-09 (hex) NETGEAR +DCEF09 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +DC-64-B8 (hex) Shenzhen JingHanDa Electronics Co.Ltd +DC64B8 (base 16) Shenzhen JingHanDa Electronics Co.Ltd + 5th Floor,No 4 ,Road 1,ShangXue Technology industrial Park,LongGang district,ShenZhen,GuangDong,China + ShenZhen GuangDong 518129 + CN + +00-0D-92 (hex) ARIMA Communications Corp. +000D92 (base 16) ARIMA Communications Corp. + 16, lane 658, Ying-Tao Road + Yingko Taipei County 23943 + TW + +00-21-63 (hex) ASKEY COMPUTER CORP +002163 (base 16) ASKEY COMPUTER CORP + 10F,NO.119.CHIENKANG RD,CHUNG-HO, + taipei TAIPEI 235 + TW + +A8-D3-F7 (hex) Arcadyan Technology Corporation +A8D3F7 (base 16) Arcadyan Technology Corporation + No.8, Sec.2, Guangfu Rd., + Hsinchu City Hsinchu 30071 + TW + +4C-60-DE (hex) NETGEAR +4C60DE (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +C4-3D-C7 (hex) NETGEAR +C43DC7 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +48-9D-24 (hex) BlackBerry RTS +489D24 (base 16) BlackBerry RTS + 451 Phillip Street + Waterloo ON N2L 3X2 + CA + +08-BD-43 (hex) NETGEAR +08BD43 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +44-EE-02 (hex) MTI Ltd. +44EE02 (base 16) MTI Ltd. + Nishi-shinjuku Tokyo Opera City Tower 3-20-2 35F + Shinjuku-ku Tokyo 163-1435 + JP + +58-56-E8 (hex) ARRIS Group, Inc. +5856E8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F8-0B-BE (hex) ARRIS Group, Inc. +F80BBE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +DC-45-17 (hex) ARRIS Group, Inc. +DC4517 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +C8-AA-21 (hex) ARRIS Group, Inc. +C8AA21 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-17-EE (hex) ARRIS Group, Inc. +0017EE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-11-1A (hex) ARRIS Group, Inc. +00111A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-0F-9F (hex) ARRIS Group, Inc. +000F9F (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-04-BD (hex) ARRIS Group, Inc. +0004BD (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-26-42 (hex) ARRIS Group, Inc. +002642 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-24-A1 (hex) ARRIS Group, Inc. +0024A1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-22-10 (hex) ARRIS Group, Inc. +002210 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-22-B4 (hex) ARRIS Group, Inc. +0022B4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-14-9A (hex) ARRIS Group, Inc. +00149A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-14-E8 (hex) ARRIS Group, Inc. +0014E8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-19-C0 (hex) ARRIS Group, Inc. +0019C0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-E0-6F (hex) ARRIS Group, Inc. +00E06F (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +80-96-B1 (hex) ARRIS Group, Inc. +8096B1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +70-7E-43 (hex) ARRIS Group, Inc. +707E43 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-15-2F (hex) ARRIS Group, Inc. +00152F (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1F-C4 (hex) ARRIS Group, Inc. +001FC4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1C-FB (hex) ARRIS Group, Inc. +001CFB (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-23-95 (hex) ARRIS Group, Inc. +002395 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-23-AF (hex) ARRIS Group, Inc. +0023AF (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F8-7B-7A (hex) ARRIS Group, Inc. +F87B7A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-00-F4 (hex) Allied Telesis, Inc. +0000F4 (base 16) Allied Telesis, Inc. + CORPORATION + SUNNYVALE CA 94086 + US + +00-15-77 (hex) Allied Telesis, Inc. +001577 (base 16) Allied Telesis, Inc. + 3200 North First Street + San Jose 95134 + US + +00-1A-EB (hex) Allied Telesis R&D Center K.K. +001AEB (base 16) Allied Telesis R&D Center K.K. + No.2 TOC Bldg. + Shinagawa-ku Tokyo 141-0031 + JP + +70-3C-39 (hex) SEAWING Kft +703C39 (base 16) SEAWING Kft + Palánkai utca 5. + Székesfehérvár Fejér 8000 + HU + +90-97-D5 (hex) Espressif Inc. +9097D5 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +AC-D0-74 (hex) Espressif Inc. +ACD074 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +38-E3-C5 (hex) Taicang T&W Electronics +38E3C5 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +00-15-CE (hex) ARRIS Group, Inc. +0015CE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-15-A2 (hex) ARRIS Group, Inc. +0015A2 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-15-A3 (hex) ARRIS Group, Inc. +0015A3 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-15-A4 (hex) ARRIS Group, Inc. +0015A4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-00-CA (hex) ARRIS Group, Inc. +0000CA (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +70-9E-29 (hex) Sony Interactive Entertainment Inc. +709E29 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +A4-DB-30 (hex) Liteon Technology Corporation +A4DB30 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +40-F0-2F (hex) Liteon Technology Corporation +40F02F (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +74-C2-46 (hex) Amazon Technologies Inc. +74C246 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +00-0F-A3 (hex) Alpha Networks Inc. +000FA3 (base 16) Alpha Networks Inc. + No.8 Li-shing 7th Rd.,Science-based Industrial Park + Hsinchu 300 + TW + +00-1D-6A (hex) Alpha Networks Inc. +001D6A (base 16) Alpha Networks Inc. + No.8 Li-shing Seventh Road,Science-based + Hsinchu 300 + US + +00-23-45 (hex) Sony Mobile Communications Inc +002345 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +6C-0E-0D (hex) Sony Mobile Communications Inc +6C0E0D (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +6C-23-B9 (hex) Sony Mobile Communications Inc +6C23B9 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +30-17-C8 (hex) Sony Mobile Communications Inc +3017C8 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-12-EE (hex) Sony Mobile Communications Inc +0012EE (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-16-20 (hex) Sony Mobile Communications Inc +001620 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-19-63 (hex) Sony Mobile Communications Inc +001963 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-1F-E4 (hex) Sony Mobile Communications Inc +001FE4 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +20-54-76 (hex) Sony Mobile Communications Inc +205476 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-1A-80 (hex) Sony Corporation +001A80 (base 16) Sony Corporation + Gotenyama Tec, 5-1-2 Kitashinagawa + Tokyo 141-0001 + JP + +88-41-FC (hex) AirTies Wireless Networks +8841FC (base 16) AirTies Wireless Networks + Gulbahar Mahallesi, Avni Diligil Sokak + ISTANBUL ISTANBUL 34394 + TR + +00-30-D3 (hex) Agilent Technologies, Inc. +0030D3 (base 16) Agilent Technologies, Inc. + 1501 Page Mill Road + Palo Alto CA 94304-1126 + US + +00-A0-2F (hex) ADB Broadband Italia +00A02F (base 16) ADB Broadband Italia + VIALE SARCA 222 + 20126 MILAN 12345 + IT + +98-74-3D (hex) Shenzhen Jun Kai Hengye Technology Co. Ltd +98743D (base 16) Shenzhen Jun Kai Hengye Technology Co. Ltd + 5th floor,Yahua Building,#1Hongwan Gonghegongye RD,Xixiang Gushu Community,Baoan District,Shenzhen + Shenzhen Guangdong 518000 + CN + +A0-F4-59 (hex) FN-LINK TECHNOLOGY LIMITED +A0F459 (base 16) FN-LINK TECHNOLOGY LIMITED + 5th Floor, A Building, Haoye Logistics Park, Shugang Channel, Bao'an District, + SHENZHEN GUANGDONG 518000 + CN + +58-63-56 (hex) FN-LINK TECHNOLOGY LIMITED +586356 (base 16) FN-LINK TECHNOLOGY LIMITED + 5th Floor, A Building, Haoye Logistics Park, Shugang Channel, Bao'an District, + SHENZHEN GUANGDONG 518000 + CN + +8C-B8-64 (hex) AcSiP Technology Corp. +8CB864 (base 16) AcSiP Technology Corp. + 3F., No.22, Dalin Rd., + Taoyuan City 330 + TW + +5C-E2-F4 (hex) AcSiP Technology Corp. +5CE2F4 (base 16) AcSiP Technology Corp. + 3F., No.22, Dalin Rd. + Taoyuan Taoyuan County 33067 + TW + +B8-61-6F (hex) Accton Technology Corp +B8616F (base 16) Accton Technology Corp + No.1 Creation Rd III, Science-based Industrial Park + Hsinchu 30077 + TW + +00-12-CF (hex) Accton Technology Corp +0012CF (base 16) Accton Technology Corp + No. 1 Creation Rd. III, Science-based Industrial Park + Hsinchu 300 + TW + +00-30-F1 (hex) Accton Technology Corp +0030F1 (base 16) Accton Technology Corp + No. 1, Creation Rd. IV + Hsinchu 12345 + TW + +70-5A-0F (hex) Hewlett Packard +705A0F (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +44-95-FA (hex) Qingdao Santong Digital Technology Co.Ltd +4495FA (base 16) Qingdao Santong Digital Technology Co.Ltd + Room701, No.1£¬Fu Ying Building,No.443East Changjiang Road,Qingdao Economic and Technological Development District + Qingdao Shandong 266555 + CN + +00-25-D3 (hex) AzureWave Technology Inc. +0025D3 (base 16) AzureWave Technology Inc. + 8F ., No.94, Baozhong Rd. + Xindian City 231 + TW + +1C-4B-D6 (hex) AzureWave Technology Inc. +1C4BD6 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baoshong Rd. + Xindian City, Taipei County 231 + TW + +08-A9-5A (hex) AzureWave Technology Inc. +08A95A (base 16) AzureWave Technology Inc. + 8F., No. 94, Baoshong Rd. + Xindian City, Taipei County 231 + TW + +94-DB-C9 (hex) AzureWave Technology Inc. +94DBC9 (base 16) AzureWave Technology Inc. + 8F No94 Baozhong Rd + XindianDistrict, New Taipei City 231 + TW + +24-0A-64 (hex) AzureWave Technology Inc. +240A64 (base 16) AzureWave Technology Inc. + 9F.,No.92,Baozhong Rd + Xindian NewTaipeiCity 231 + TW + +40-E2-30 (hex) AzureWave Technology Inc. +40E230 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd., + New Taipei City Taiwan 231 + TW + +80-D2-1D (hex) AzureWave Technology Inc. +80D21D (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +D4-D1-84 (hex) ADB Broadband Italia +D4D184 (base 16) ADB Broadband Italia + via Sarca 222 + Milano 20126 + IT + +A0-4F-D4 (hex) ADB Broadband Italia +A04FD4 (base 16) ADB Broadband Italia + VIALE SARCA 336 + MILANO 20126 + IT + +D0-0E-D9 (hex) Taicang T&W Electronics +D00ED9 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD, Lu Du + Taicang Jiangsu 215412 + CN + +54-14-73 (hex) Wingtech Group (HongKong)Limited +541473 (base 16) Wingtech Group (HongKong)Limited + FLAT/RM 1903 19/F PODIUM PLAZA 5HANOI ROAD TSIM SHA TSUI + HongKong 999077 + HK + +80-86-F2 (hex) Intel Corporate +8086F2 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +E0-94-67 (hex) Intel Corporate +E09467 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +08-D4-0C (hex) Intel Corporate +08D40C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +6C-88-14 (hex) Intel Corporate +6C8814 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +30-3A-64 (hex) Intel Corporate +303A64 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +AC-FD-CE (hex) Intel Corporate +ACFDCE (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +7C-CC-B8 (hex) Intel Corporate +7CCCB8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +F4-06-69 (hex) Intel Corporate +F40669 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1D-E1 (hex) Intel Corporate +001DE1 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +90-E2-BA (hex) Intel Corporate +90E2BA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-26-C7 (hex) Intel Corporate +0026C7 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-26-C6 (hex) Intel Corporate +0026C6 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +0C-CC-26 (hex) Airenetworks +0CCC26 (base 16) Airenetworks + Ramon y Cajal 11 + Elche Alicante 03203 + ES + +E0-9D-31 (hex) Intel Corporate +E09D31 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +88-53-2E (hex) Intel Corporate +88532E (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +74-C9-9A (hex) Ericsson AB +74C99A (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +5C-C2-13 (hex) Fr. Sauter AG +5CC213 (base 16) Fr. Sauter AG + Im Surinam 55 + Basel BS CH4016 + CH + +28-10-1B (hex) MagnaCom +28101B (base 16) MagnaCom + 9 Bareket Street + Petah Tikva 4951777 + IL + +00-16-76 (hex) Intel Corporate +001676 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-16-EA (hex) Intel Corporate +0016EA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1B-77 (hex) Intel Corporate +001B77 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1C-C0 (hex) Intel Corporate +001CC0 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +10-4A-7D (hex) Intel Corporate +104A7D (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1A-A0 (hex) Dell Inc. +001AA0 (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +00-19-B9 (hex) Dell Inc. +0019B9 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-B0-D0 (hex) Dell Inc. +00B0D0 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-C0-4F (hex) Dell Inc. +00C04F (base 16) Dell Inc. + 1807 WEST BRAKER LANE-BLDG. + AUSTIN TX 78758-3610 + US + +B0-79-94 (hex) Motorola Mobility LLC, a Lenovo Company +B07994 (base 16) Motorola Mobility LLC, a Lenovo Company + 600 North US Hwy 45 + Libertyville IL 60048 + US + +A4-70-D6 (hex) Motorola Mobility LLC, a Lenovo Company +A470D6 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 Merchandise Mart Plaza, Suite 1800 + Chicago IL 60654 + US + +74-86-7A (hex) Dell Inc. +74867A (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +18-03-73 (hex) Dell Inc. +180373 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +14-FE-B5 (hex) Dell Inc. +14FEB5 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +78-2B-CB (hex) Dell Inc. +782BCB (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-1F-3B (hex) Intel Corporate +001F3B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-21-5D (hex) Intel Corporate +00215D (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-21-6A (hex) Intel Corporate +00216A (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1C-23 (hex) Dell Inc. +001C23 (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +A4-BA-DB (hex) Dell Inc. +A4BADB (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +00-25-64 (hex) Dell Inc. +002564 (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +A4-1F-72 (hex) Dell Inc. +A41F72 (base 16) Dell Inc. + One Dell way + Round Rock 78682 + US + +C4-66-99 (hex) vivo Mobile Communication Co., Ltd. +C46699 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +C8-F2-30 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +C8F230 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD + DONGGUAN GUANGDONG 523860 + CN + +8C-0E-E3 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +8C0EE3 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD,WUSHA,CHANG'AN + DONGGUAN GUANGDONG 523860 + CN + +C8-CD-72 (hex) Sagemcom Broadband SAS +C8CD72 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison Cedex Hauts de Seine 92848 + FR + +F8-2C-18 (hex) 2Wire Inc +F82C18 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +18-01-7D (hex) Harbin Arteor technology co., LTD +18017D (base 16) Harbin Arteor technology co., LTD + Yushan Road 49-2 + Harbin Heilongjiang 150090 + CN + +00-15-56 (hex) Sagemcom Broadband SAS +001556 (base 16) Sagemcom Broadband SAS + Le Ponnant de Paris + CEDEX Paris 75512 + FR + +C0-D0-44 (hex) Sagemcom Broadband SAS +C0D044 (base 16) Sagemcom Broadband SAS + 250, Route de l'Empereur + RUEIL-MALMAISON 92500 + FR + +A0-1B-29 (hex) Sagemcom Broadband SAS +A01B29 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison Cedex Hauts de Seine 92848 + FR + +74-E1-4A (hex) IEEE Registration Authority +74E14A (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +0C-EF-AF (hex) IEEE Registration Authority +0CEFAF (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F8-02-78 (hex) IEEE Registration Authority +F80278 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +A0-BB-3E (hex) IEEE Registration Authority +A0BB3E (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +88-4A-EA (hex) Texas Instruments +884AEA (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +00-22-A4 (hex) 2Wire Inc +0022A4 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +98-2C-BE (hex) 2Wire Inc +982CBE (base 16) 2Wire Inc + 1764 Automation Pkwy + San Jose CA 95131 + US + +64-0F-28 (hex) 2Wire Inc +640F28 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +00-12-3F (hex) Dell Inc. +00123F (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-0B-DB (hex) Dell Inc. +000BDB (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +20-47-47 (hex) Dell Inc. +204747 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-14-95 (hex) 2Wire Inc +001495 (base 16) 2Wire Inc + 1704 Automation Parkway + San Jose CA 95131 + US + +34-8A-AE (hex) Sagemcom Broadband SAS +348AAE (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + RUEIL MALMAISON CEDEX Hauts de Seine 92848 + FR + +7C-03-D8 (hex) Sagemcom Broadband SAS +7C03D8 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + RUEIL MALMAISON CEDEX Hauts de Seine 92848 + FR + +C0-AC-54 (hex) Sagemcom Broadband SAS +C0AC54 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison HAUTS DE SEINE 92848 + FR + +2C-39-96 (hex) Sagemcom Broadband SAS +2C3996 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison HAUTS DE SEINE 92848 + FR + +F0-82-61 (hex) Sagemcom Broadband SAS +F08261 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison HAUTS DE SEINE 92848 + FR + +00-30-C5 (hex) CADENCE DESIGN SYSTEMS, INC. +0030C5 (base 16) CADENCE DESIGN SYSTEMS, INC. + 555 RIVER OAKS PARKWAY + SAN JOSE CA 95134 + US + +D0-8C-B5 (hex) Texas Instruments +D08CB5 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-18-2F (hex) Texas Instruments +00182F (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-17-EA (hex) Texas Instruments +0017EA (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-21-BA (hex) Texas Instruments +0021BA (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +BC-0D-A5 (hex) Texas Instruments +BC0DA5 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +CC-8C-E3 (hex) Texas Instruments +CC8CE3 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +E0-D7-BA (hex) Texas Instruments +E0D7BA (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +1C-E2-CC (hex) Texas Instruments +1CE2CC (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +98-59-45 (hex) Texas Instruments +985945 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +94-44-52 (hex) Belkin International Inc. +944452 (base 16) Belkin International Inc. + 12045 E. Waterfront Drive + Playa Vista CA 90094 + US + +B0-B4-48 (hex) Texas Instruments +B0B448 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +D4-94-A1 (hex) Texas Instruments +D494A1 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-14-BF (hex) Cisco-Linksys, LLC +0014BF (base 16) Cisco-Linksys, LLC + 121 Theory Dr. + Irvine CA 92612 + US + +CC-B2-55 (hex) D-Link International +CCB255 (base 16) D-Link International + 1 International Business Park, #03-12, The Synergy + SINGAPORE 609917 + SG + +28-10-7B (hex) D-Link International +28107B (base 16) D-Link International + 1 International Business Park, #03-12, The Synergy + SINGAPORE 609917 + SG + +FC-75-16 (hex) D-Link International +FC7516 (base 16) D-Link International + 1 International Business Park, #03-12, The Synergy + SINGAPORE 609917 + SG + +84-C9-B2 (hex) D-Link International +84C9B2 (base 16) D-Link International + 1 International Business Park, #03-12, The Synergy + SINGAPORE 609917 + SG + +C8-D3-A3 (hex) D-Link International +C8D3A3 (base 16) D-Link International + 1 Internal Business Park, #03-12. The Synergy Singapore + Singapore 609917 + US + +3C-BB-73 (hex) Shenzhen Xinguodu Technology Co., Ltd. +3CBB73 (base 16) Shenzhen Xinguodu Technology Co., Ltd. + F17A, JinSong Building, Tairan Industrial & Trade Park, Chegongmiao, Shennan Road,Futian District + Shenzhen Guangdong 518040 + CN + +0C-47-C9 (hex) Amazon Technologies Inc. +0C47C9 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +00-50-BA (hex) D-Link Corporation +0050BA (base 16) D-Link Corporation + 2F, NO. 233L-2, PAO-CHIAO RD. + TAIPEI 0000 + TW + +00-17-9A (hex) D-Link Corporation +00179A (base 16) D-Link Corporation + No. 289, Sinhu 3rd Rd., Neihu District, + Taipei 114 + TW + +00-1C-F0 (hex) D-Link Corporation +001CF0 (base 16) D-Link Corporation + NO.289, Sinhu 3rd Rd., + Neihu District, Taipei City 114 + TW + +00-1E-58 (hex) D-Link Corporation +001E58 (base 16) D-Link Corporation + NO.289, Sinhu 3rd Rd., + Neihu District, Taipei City 114 + TW + +00-22-B0 (hex) D-Link Corporation +0022B0 (base 16) D-Link Corporation + No.289, Sinhu 3rd RD., + Neihu District, Taipei City 114 + TW + +00-24-01 (hex) D-Link Corporation +002401 (base 16) D-Link Corporation + No.289, Sinhu 3rd RD., + Neihu District, Taipei City 114 + TW + +1C-AF-F7 (hex) D-Link International +1CAFF7 (base 16) D-Link International + 1 INTERNATIONAL BUSINESS PARK, + SINGAPORE 609917 + SG + +14-D6-4D (hex) D-Link International +14D64D (base 16) D-Link International + 1 INTERNATIONAL BUSINESS PARK + SINGAPORE 609917 + SG + +90-94-E4 (hex) D-Link International +9094E4 (base 16) D-Link International + 1 International Business Park, #03-12, The Synergy + SINGAPORE 609917 + SG + +B4-99-BA (hex) Hewlett Packard +B499BA (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +04-78-63 (hex) Shanghai MXCHIP Information Technology Co., Ltd. +047863 (base 16) Shanghai MXCHIP Information Technology Co., Ltd. + 9th Floor, No. 5 Building, 2145 Jinshajiang Rd., Putuo District + Shanghai 200333 + CN + +40-9F-87 (hex) Jide Technology (Hong Kong) Limited +409F87 (base 16) Jide Technology (Hong Kong) Limited + jiahua Mansion 3F, 133 North 4th Ring Road East, Chaoyang District + Beijing 100101 + CN + +0C-F9-C0 (hex) BSkyB Ltd +0CF9C0 (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +4C-FF-12 (hex) Fuze Entertainment Co., ltd +4CFF12 (base 16) Fuze Entertainment Co., ltd + 3rd Floor Harbour Centre + George Town George Town P.O. Box 613GT + KY + +AC-9A-22 (hex) NXP Semiconductors +AC9A22 (base 16) NXP Semiconductors + 411 E. Plumeria Drive + San Jose CA 95134 + US + +28-7C-DB (hex) Hefei Toycloud Technology Co.,ltd +287CDB (base 16) Hefei Toycloud Technology Co.,ltd + FLOOR 13,XUNFEI BUILDING,NO.666 WANGJIANG ROAD,HIGH & NEW TECHNOLOGY DEVELOPMENT ZONE.HEFEI. + Hefei Anhui 230088 + CN + +80-6A-B0 (hex) Shenzhen TINNO Mobile Technology Corp. +806AB0 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F.,H-3 Building,OCT Eastern lndustrial Park + Nanshan District, Shenzhen GUANGDONG 518053 + CN + +48-AD-08 (hex) HUAWEI TECHNOLOGIES CO.,LTD +48AD08 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +4C-FB-45 (hex) HUAWEI TECHNOLOGIES CO.,LTD +4CFB45 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan Guangdong 523808 + CN + +00-9A-CD (hex) HUAWEI TECHNOLOGIES CO.,LTD +009ACD (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan Guangdong 523808 + CN + +3C-5A-B4 (hex) Google, Inc. +3C5AB4 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View 94043 + US + +F4-F5-E8 (hex) Google, Inc. +F4F5E8 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View 94043 + US + +94-EB-2C (hex) Google, Inc. +94EB2C (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View 94043 + US + +0C-C7-31 (hex) Currant, Inc. +0CC731 (base 16) Currant, Inc. + 927 Industrial Ave + Palo Alto CA 94303 + US + +70-B3-D5 (hex) IEEE Registration Authority +70B3D5 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +28-ED-6A (hex) Apple, Inc. +28ED6A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-56-E3 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +C056E3 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.469,Jianghui Road + Hangzhou Zhejiang 310052 + CN + +EC-3E-F7 (hex) Juniper Networks +EC3EF7 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +0C-F8-93 (hex) ARRIS Group, Inc. +0CF893 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +3C-DF-A9 (hex) ARRIS Group, Inc. +3CDFA9 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +84-61-A0 (hex) ARRIS Group, Inc. +8461A0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-15-D1 (hex) ARRIS Group, Inc. +0015D1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-D0 (hex) ARRIS Group, Inc. +001DD0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-D3 (hex) ARRIS Group, Inc. +001DD3 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +AC-B3-13 (hex) ARRIS Group, Inc. +ACB313 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +38-F2-3E (hex) Microsoft Mobile Oy +38F23E (base 16) Microsoft Mobile Oy + Keilalahdentie 4 + Espoo 02150 + FI + +E4-F8-9C (hex) Intel Corporate +E4F89C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +6C-A1-00 (hex) Intel Corporate +6CA100 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +2C-41-38 (hex) Hewlett Packard +2C4138 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +44-1E-A1 (hex) Hewlett Packard +441EA1 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +78-E7-D1 (hex) Hewlett Packard +78E7D1 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +5C-8F-E0 (hex) ARRIS Group, Inc. +5C8FE0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +90-C7-92 (hex) ARRIS Group, Inc. +90C792 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +BC-CA-B5 (hex) ARRIS Group, Inc. +BCCAB5 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D0-39-B3 (hex) ARRIS Group, Inc. +D039B3 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-0F-CC (hex) ARRIS Group, Inc. +000FCC (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-12-F0 (hex) Intel Corporate +0012F0 (base 16) Intel Corporate + Lot 8, Jalan Hi-tech 2/3 + Kulim Kedah 09000 + MY + +00-07-40 (hex) BUFFALO.INC +000740 (base 16) BUFFALO.INC + AKAMONDORI Bldg., 30-20,Ohsu 3-chome + Naka-ku,Nagoya Aichi Pref. 460-8315 + JP + +00-24-A5 (hex) BUFFALO.INC +0024A5 (base 16) BUFFALO.INC + AKAMONDORI Bldg., 30-20,Ohsu 3-chome + Naka-ku,Nagoya Aichi Pref. 460-8315 + JP + +CC-E1-D5 (hex) BUFFALO.INC +CCE1D5 (base 16) BUFFALO.INC + AKAMONDORI Bldg.,30-20,Ohsu 3-chome + Naka-ku,Nagoya Aichi Pref 460-8315 + JP + +A4-02-B9 (hex) Intel Corporate +A402B9 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +DC-53-60 (hex) Intel Corporate +DC5360 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1C-C4 (hex) Hewlett Packard +001CC4 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-1E-0B (hex) Hewlett Packard +001E0B (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-22-64 (hex) Hewlett Packard +002264 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-25-B3 (hex) Hewlett Packard +0025B3 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-0C-F1 (hex) Intel Corporation +000CF1 (base 16) Intel Corporation + MS: JF3-420 + Hillsboro OR 97124 + US + +78-48-59 (hex) Hewlett Packard +784859 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +58-DC-6D (hex) Exceptional Innovation, Inc. +58DC6D (base 16) Exceptional Innovation, Inc. + 480 Olde Worthington Rd, Suite 350 + Westerville OH 43082 + US + +90-21-55 (hex) HTC Corporation +902155 (base 16) HTC Corporation + No.23 Xinghua Road + Taoyuan County 330 + TW + +64-31-50 (hex) Hewlett Packard +643150 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +7C-B1-5D (hex) HUAWEI TECHNOLOGIES CO.,LTD +7CB15D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan Guangdong 523808 + CN + +00-26-5E (hex) Hon Hai Precision Ind. Co.,Ltd. +00265E (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-24-2C (hex) Hon Hai Precision Ind. Co.,Ltd. +00242C (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +D8-B3-77 (hex) HTC Corporation +D8B377 (base 16) HTC Corporation + No. 23, Xinghua Rd., + Taoyuan City 330 + TW + +B0-F1-A3 (hex) Fengfan (BeiJing) Technology Co., Ltd. +B0F1A3 (base 16) Fengfan (BeiJing) Technology Co., Ltd. + Room518,Dianzichengdasha Town,No12,Jiuxianqiao Road + Beijing Chaoyang District 100016 + CN + +34-64-A9 (hex) Hewlett Packard +3464A9 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +38-63-BB (hex) Hewlett Packard +3863BB (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +5C-B9-01 (hex) Hewlett Packard +5CB901 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +DC-4A-3E (hex) Hewlett Packard +DC4A3E (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +B0-5A-DA (hex) Hewlett Packard +B05ADA (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +00-10-83 (hex) Hewlett Packard +001083 (base 16) Hewlett Packard + MAIL STOP 42LE + CUPERTINO CA 95014 + US + +A0-B3-CC (hex) Hewlett Packard +A0B3CC (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +EC-B1-D7 (hex) Hewlett Packard +ECB1D7 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +9C-B6-54 (hex) Hewlett Packard +9CB654 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +6C-3B-E5 (hex) Hewlett Packard +6C3BE5 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +B0-AA-36 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +B0AA36 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD + DONGGUAN GUANGDONG 523860 + CN + +78-4B-87 (hex) Murata Manufacturing Co., Ltd. +784B87 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1,Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +E4-CE-02 (hex) WyreStorm Technologies Ltd +E4CE02 (base 16) WyreStorm Technologies Ltd + Tech Valley Park, 23 Wood Road + Round Lake New York 12151 + GB + +40-F3-08 (hex) Murata Manufacturing Co., Ltd. +40F308 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1 Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +80-89-17 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +808917 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4)  + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +A0-93-47 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +A09347 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD,WUSHA,CHANG'AN,DONGGUAN,GUANGDONG,CHINA + DONGGUAN GUANGDONG 523860 + CN + +E8-BB-A8 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +E8BBA8 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD,WUSHA,CHANG'AN,DONGGUAN,GUANGDONG,CHINA + DONGGUAN GUANGDONG 523860 + CN + +94-2C-B3 (hex) HUMAX Co., Ltd. +942CB3 (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +00-27-19 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +002719 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 7, Second Part, Honghualing Industrial Zone + Shenzhen Guangdong 518057 + CN + +40-16-9F (hex) TP-LINK TECHNOLOGIES CO.,LTD. +40169F (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + 1-6F, Building 2, Pingshandayuan Industrial, South Zone, + Shenzhen Guangdong 518000 + CN + +F4-EC-38 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +F4EC38 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + 1-6F, Building 2, Pingshandayuan Industrial, South Zone, + Shenzhen Guangdong 518000 + CN + +14-04-67 (hex) SNK Technologies Co.,Ltd. +140467 (base 16) SNK Technologies Co.,Ltd. + #1001, Byuksan Sunyoung Technopia, A-dong, 13 + Ojeongongeop-gil, Uiwang-si, Gyeonggi-do 16072 + KR + +80-30-DC (hex) Texas Instruments +8030DC (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +A4-D5-78 (hex) Texas Instruments +A4D578 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +14-CF-92 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +14CF92 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) + shenzhen guangdong Province 518057 + CN + +20-DC-E6 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +20DCE6 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) + shenzhen guangdong Province 518057 + CN + +14-CC-20 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +14CC20 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +24-60-81 (hex) razberi technologies +246081 (base 16) razberi technologies + 13755 Hutton Drive Suite 500 + Farmers Branch TX 75234 + US + +A4-D1-8C (hex) Apple, Inc. +A4D18C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-F6-52 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +90F652 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan, + Shenzhen Guangdong Province, 518057 + CN + +24-1E-EB (hex) Apple, Inc. +241EEB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +CC-25-EF (hex) Apple, Inc. +CC25EF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-CF-98 (hex) HUAWEI TECHNOLOGIES CO.,LTD +88CF98 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F8-0D-43 (hex) Hon Hai Precision Ind. Co.,Ltd. +F80D43 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +38-F8-89 (hex) HUAWEI TECHNOLOGIES CO.,LTD +38F889 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D0-7A-B5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D07AB5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-19-C6 (hex) zte corporation +0019C6 (base 16) zte corporation + Technology Management Department, + Shenzhen Guangdong 518057 + CN + +00-1D-D9 (hex) Hon Hai Precision Ind. Co.,Ltd. +001DD9 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-19-7D (hex) Hon Hai Precision Ind. Co.,Ltd. +00197D (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +7C-4C-A5 (hex) BSkyB Ltd +7C4CA5 (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +CC-4E-24 (hex) Brocade Communications Systems, Inc. +CC4E24 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-E0-52 (hex) Brocade Communications Systems, Inc. +00E052 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-14-A4 (hex) Hon Hai Precision Ind. Co.,Ltd. +0014A4 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +78-DD-08 (hex) Hon Hai Precision Ind. Co.,Ltd. +78DD08 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +9C-D2-1E (hex) Hon Hai Precision Ind. Co.,Ltd. +9CD21E (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +B4-30-52 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B43052 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +80-D0-9B (hex) HUAWEI TECHNOLOGIES CO.,LTD +80D09B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +1C-8E-5C (hex) HUAWEI TECHNOLOGIES CO.,LTD +1C8E5C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +84-74-2A (hex) zte corporation +84742A (base 16) zte corporation + 12/F.,zte R&D building,kejinan Road, + shenzhen guangdong 518057 + CN + +9C-D2-4B (hex) zte corporation +9CD24B (base 16) zte corporation + 12/F.,zte R&D building,kejinan Road, + shenzhen guangdong 518057 + CN + +C8-7B-5B (hex) zte corporation +C87B5B (base 16) zte corporation + 12/F.,zte R&D building,kejinan Road, + shenzhen guangdong 518057 + CN + +00-07-D8 (hex) Hitron Technologies. Inc +0007D8 (base 16) Hitron Technologies. Inc + 135-220 Hitron B/D 726-5 + Seoul 13456 + KR + +C0-3E-0F (hex) BSkyB Ltd +C03E0F (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +90-4E-2B (hex) HUAWEI TECHNOLOGIES CO.,LTD +904E2B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +20-08-ED (hex) HUAWEI TECHNOLOGIES CO.,LTD +2008ED (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-01-0F (hex) Brocade Communications Systems, Inc. +00010F (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +08-00-88 (hex) Brocade Communications Systems, Inc. +080088 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-34-FE (hex) HUAWEI TECHNOLOGIES CO.,LTD +0034FE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C8-51-95 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C85195 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +40-CB-A8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +40CBA8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate + Shenzhen GuangDong 518057 + CN + +D4-6E-5C (hex) HUAWEI TECHNOLOGIES CO.,LTD +D46E5C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate + Shenzhen GuangDong 518057 + CN + +88-53-D4 (hex) HUAWEI TECHNOLOGIES CO.,LTD +8853D4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District + Shenzhen Guangdong 518057 + CN + +04-C0-6F (hex) HUAWEI TECHNOLOGIES CO.,LTD +04C06F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +20-2B-C1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +202BC1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +54-A5-1B (hex) HUAWEI TECHNOLOGIES CO.,LTD +54A51B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +00-25-68 (hex) HUAWEI TECHNOLOGIES CO.,LTD +002568 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +78-1D-BA (hex) HUAWEI TECHNOLOGIES CO.,LTD +781DBA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + HUAWEI Industrial Base Bantian,Longgang + Shenzhen guangdong 518129 + CN + +00-25-9E (hex) HUAWEI TECHNOLOGIES CO.,LTD +00259E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + B1-7,Huawei Base,Bantian, Longgang District,ShenZhen,GuangDong,CHINA + ShenZhen GuangDong 518129 + CN + +00-6B-8E (hex) Shanghai Feixun Communication Co.,Ltd. +006B8E (base 16) Shanghai Feixun Communication Co.,Ltd. + Building 90,No,4855,Guangfulin Road + shanghai Shanghai 201616 + CN + +D4-6A-A8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D46AA8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen 518129 + CN + +BC-AD-AB (hex) Avaya Inc +BCADAB (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +FC-A8-41 (hex) Avaya Inc +FCA841 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +3C-B1-5B (hex) Avaya Inc +3CB15B (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +34-75-C7 (hex) Avaya Inc +3475C7 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +B0-AD-AA (hex) Avaya Inc +B0ADAA (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +B4-47-5E (hex) Avaya Inc +B4475E (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +B8-BC-1B (hex) HUAWEI TECHNOLOGIES CO.,LTD +B8BC1B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +58-2A-F7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +582AF7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-D9-21 (hex) Avaya Inc +24D921 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +84-83-71 (hex) Avaya Inc +848371 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +00-1B-4F (hex) Avaya Inc +001B4F (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +4C-8B-EF (hex) HUAWEI TECHNOLOGIES CO.,LTD +4C8BEF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, + Shenzhen Guangdong 518057 + CN + +50-06-AB (hex) Cisco Systems, Inc +5006AB (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +FC-48-EF (hex) HUAWEI TECHNOLOGIES CO.,LTD +FC48EF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +70-7B-E8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +707BE8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +4C-1F-CC (hex) HUAWEI TECHNOLOGIES CO.,LTD +4C1FCC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +00-90-6D (hex) Cisco Systems, Inc +00906D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-90-AB (hex) Cisco Systems, Inc +0090AB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-50-54 (hex) Cisco Systems, Inc +005054 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-50-0B (hex) Cisco Systems, Inc +00500B (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-03-DD (hex) Comark Interactive Solutions +0003DD (base 16) Comark Interactive Solutions + 93 West St. + Medfield MA 02052 + US + +00-50-53 (hex) Cisco Systems, Inc +005053 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-50-50 (hex) Cisco Systems, Inc +005050 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D4-B1-10 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D4B110 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +E4-68-A3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E468A3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +24-71-89 (hex) Texas Instruments +247189 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +98-7B-F3 (hex) Texas Instruments +987BF3 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +A0-F6-FD (hex) Texas Instruments +A0F6FD (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +D0-B5-C2 (hex) Texas Instruments +D0B5C2 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +78-A5-04 (hex) Texas Instruments +78A504 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +6C-EC-EB (hex) Texas Instruments +6CECEB (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +34-00-A3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +3400A3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base + Shenzhen Guangdong 518129 + CN + +00-90-2B (hex) Cisco Systems, Inc +00902B (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-E0-8F (hex) Cisco Systems, Inc +00E08F (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-18-68 (hex) Cisco SPVTG +001868 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +88-75-56 (hex) Cisco Systems, Inc +887556 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +FC-99-47 (hex) Cisco Systems, Inc +FC9947 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +6C-20-56 (hex) Cisco Systems, Inc +6C2056 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-15-F2 (hex) ASUSTek COMPUTER INC. +0015F2 (base 16) ASUSTek COMPUTER INC. + No.5 Shing Yeh Street,Kwei Shan Hsiang,Taoyuan + Taipei 333 + TW + +90-E6-BA (hex) ASUSTek COMPUTER INC. +90E6BA (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou,Taipei 112 ,Taiwan + Taipei Taiwan 112 + TW + +00-26-18 (hex) ASUSTek COMPUTER INC. +002618 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou,Taipei 112 ,Taiwan + Taipei Taiwan 112 + TW + +F4-6D-04 (hex) ASUSTek COMPUTER INC. +F46D04 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou, + Taipei 112 + TW + +00-E0-18 (hex) ASUSTek COMPUTER INC. +00E018 (base 16) ASUSTek COMPUTER INC. + 150 LI-TE RD. + PEITOU, TAIPEI 77777 + TW + +00-0C-6E (hex) ASUSTek COMPUTER INC. +000C6E (base 16) ASUSTek COMPUTER INC. + 150, Li-Te Rd., PeiTou + Taipei 112 + TW + +00-0E-A6 (hex) ASUSTek COMPUTER INC. +000EA6 (base 16) ASUSTek COMPUTER INC. + 150, Li-Te Rd., PeiTou + Taipei 112 + TW + +00-1D-60 (hex) ASUSTek COMPUTER INC. +001D60 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou + Taipei 112 + TW + +6C-41-6A (hex) Cisco Systems, Inc +6C416A (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +EC-E1-A9 (hex) Cisco Systems, Inc +ECE1A9 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +C0-67-AF (hex) Cisco Systems, Inc +C067AF (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +AC-F2-C5 (hex) Cisco Systems, Inc +ACF2C5 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +24-01-C7 (hex) Cisco Systems, Inc +2401C7 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +68-86-A7 (hex) Cisco Systems, Inc +6886A7 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +C0-25-5C (hex) Cisco Systems, Inc +C0255C (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +3C-0E-23 (hex) Cisco Systems, Inc +3C0E23 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +08-CC-68 (hex) Cisco Systems, Inc +08CC68 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +0C-27-24 (hex) Cisco Systems, Inc +0C2724 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +6C-FA-89 (hex) Cisco Systems, Inc +6CFA89 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-E0-A3 (hex) Cisco Systems, Inc +00E0A3 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +60-2A-D0 (hex) Cisco SPVTG +602AD0 (base 16) Cisco SPVTG + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +74-5E-1C (hex) PIONEER CORPORATION +745E1C (base 16) PIONEER CORPORATION + 1-1 Shin-ogura + Kawasaki-shi Kanagawa Prefecture 2120031 + JP + +04-62-73 (hex) Cisco Systems, Inc +046273 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +D8-B1-90 (hex) Cisco Systems, Inc +D8B190 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +80-E8-6F (hex) Cisco Systems, Inc +80E86F (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +AC-7E-8A (hex) Cisco Systems, Inc +AC7E8A (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +1C-E8-5D (hex) Cisco Systems, Inc +1CE85D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +A8-9D-21 (hex) Cisco Systems, Inc +A89D21 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +68-9C-E2 (hex) Cisco Systems, Inc +689CE2 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-23-BE (hex) Cisco SPVTG +0023BE (base 16) Cisco SPVTG + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +18-59-33 (hex) Cisco SPVTG +185933 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +44-58-29 (hex) Cisco SPVTG +445829 (base 16) Cisco SPVTG + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +F4-4E-05 (hex) Cisco Systems, Inc +F44E05 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +88-1D-FC (hex) Cisco Systems, Inc +881DFC (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-10-11 (hex) Cisco Systems, Inc +001011 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-00-0C (hex) Cisco Systems, Inc +00000C (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +28-CF-E9 (hex) Apple, Inc. +28CFE9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-A0-40 (hex) Apple, Inc. +00A040 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-F8-49 (hex) Cisco Systems, Inc +A0F849 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +3C-D0-F8 (hex) Apple, Inc. +3CD0F8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-09-27 (hex) Apple, Inc. +680927 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-C2-6B (hex) Apple, Inc. +6CC26B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +44-D8-84 (hex) Apple, Inc. +44D884 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-26-08 (hex) Apple, Inc. +002608 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-26-B0 (hex) Apple, Inc. +0026B0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-26-BB (hex) Apple, Inc. +0026BB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D4-9A-20 (hex) Apple, Inc. +D49A20 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-1E-DF (hex) Apple, Inc. +F81EDF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-2A-14 (hex) Apple, Inc. +C82A14 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-07-54 (hex) Apple, Inc. +3C0754 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A4-B1-97 (hex) Apple, Inc. +A4B197 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-B4-79 (hex) Apple, Inc. +F0B479 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +10-93-E9 (hex) Apple, Inc. +1093E9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +44-2A-60 (hex) Apple, Inc. +442A60 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A4-D1-D2 (hex) Apple, Inc. +A4D1D2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-CF-DA (hex) Apple, Inc. +28CFDA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-30-65 (hex) Apple, Inc. +003065 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-14-51 (hex) Apple, Inc. +001451 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-1E-52 (hex) Apple, Inc. +001E52 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-21-E9 (hex) Apple, Inc. +0021E9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +CC-08-E0 (hex) Apple, Inc. +CC08E0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-54-53 (hex) Apple, Inc. +045453 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-F9-51 (hex) Apple, Inc. +F4F951 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-63-94 (hex) Apple, Inc. +C06394 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-AF-8F (hex) Apple, Inc. +18AF8F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-B5-B7 (hex) Apple, Inc. +C8B5B7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-B2-1F (hex) Apple, Inc. +90B21F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +30-F7-C5 (hex) Apple, Inc. +30F7C5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-B3-95 (hex) Apple, Inc. +40B395 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +44-FB-42 (hex) Apple, Inc. +44FB42 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E8-8D-28 (hex) Apple, Inc. +E88D28 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +94-94-26 (hex) Apple, Inc. +949426 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-7D-74 (hex) Apple, Inc. +207D74 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-F1-5A (hex) Apple, Inc. +F4F15A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-6F-1D (hex) Apple, Inc. +C86F1D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +30-90-AB (hex) Apple, Inc. +3090AB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +8C-2D-AA (hex) Apple, Inc. +8C2DAA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-85-06 (hex) Apple, Inc. +848506 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-FE-94 (hex) Apple, Inc. +98FE94 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D8-00-4D (hex) Apple, Inc. +D8004D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-20-0C (hex) Apple, Inc. +64200C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-33-4B (hex) Apple, Inc. +C8334B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-E6-82 (hex) Apple, Inc. +64E682 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B8-E8-56 (hex) Apple, Inc. +B8E856 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D8-96-95 (hex) Apple, Inc. +D89695 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-99-E2 (hex) Apple, Inc. +1499E2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B4-18-D1 (hex) Apple, Inc. +B418D1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-20-7B (hex) Apple, Inc. +9C207B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B0-65-BD (hex) Apple, Inc. +B065BD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-26-96 (hex) Apple, Inc. +542696 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-A3-CB (hex) Apple, Inc. +64A3CB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-3C-92 (hex) Apple, Inc. +903C92 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D8-1D-72 (hex) Apple, Inc. +D81D72 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-12-98 (hex) Apple, Inc. +341298 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-E7-2C (hex) Apple, Inc. +70E72C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-EC-E4 (hex) Apple, Inc. +70ECE4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-AE-20 (hex) Apple, Inc. +68AE20 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-87-A3 (hex) Apple, Inc. +AC87A3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D8-BB-2C (hex) Apple, Inc. +D8BB2C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-4F-7E (hex) Apple, Inc. +D04F7E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-78-F0 (hex) Apple, Inc. +2078F0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-AC-CB (hex) Apple, Inc. +E0ACCB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-99-9B (hex) Apple, Inc. +A0999B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +24-24-0E (hex) Apple, Inc. +24240E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-DB-F8 (hex) Apple, Inc. +F0DBF8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-74-6E (hex) Apple, Inc. +48746E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-AE-27 (hex) Apple, Inc. +54AE27 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-E9-98 (hex) Apple, Inc. +FCE998 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +0C-BC-9F (hex) Apple, Inc. +0CBC9F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-36-3B (hex) Apple, Inc. +34363B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-A6-37 (hex) Apple, Inc. +D0A637 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-9F-70 (hex) Apple, Inc. +789F70 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-F3-87 (hex) Apple, Inc. +9CF387 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-5B-78 (hex) Apple, Inc. +A85B78 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-F6-50 (hex) Apple, Inc. +C8F650 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-8E-24 (hex) Apple, Inc. +A88E24 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-4A-39 (hex) BITA +6C4A39 (base 16) BITA + 6/F, New Century Hotel Office Tower + BEI JING 100044 + CN + +84-7D-50 (hex) Holley Metering Limited +847D50 (base 16) Holley Metering Limited + 181 Wuchang Avenue + Hangzhou Zhejiang 310023 + CN + +50-D5-9C (hex) Thai Habel Industrial Co., Ltd. +50D59C (base 16) Thai Habel Industrial Co., Ltd. + 3/1 - 3/3 RAMA 3 RD, + ฺBangkholaem Bangkok 10120 + TH + +20-89-6F (hex) Fiberhome Telecommunication Technologies Co.,LTD +20896F (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +30-52-CB (hex) Liteon Technology Corporation +3052CB (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +04-96-45 (hex) WUXI SKY CHIP INTERCONNECTION TECHNOLOGY CO.,LTD. +049645 (base 16) WUXI SKY CHIP INTERCONNECTION TECHNOLOGY CO.,LTD. + Building F12, China Sensor Network International Innovation park,200# Linghu Avenue,Wuxi. + WUXI Jiangsu 214135 + CN + +1C-CD-E5 (hex) Shanghai Wind Technologies Co.,Ltd +1CCDE5 (base 16) Shanghai Wind Technologies Co.,Ltd + Room 208,Section A, Building 3#, No.7 GuiQing Road, Xuhui District, Shanghai, China(Headquarter) + Shanghai Shanghai 200233 + CN + +68-14-01 (hex) Hon Hai Precision Ind. Co.,Ltd. +681401 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +50-A9-DE (hex) Smartcom - Bulgaria AD +50A9DE (base 16) Smartcom - Bulgaria AD + BIC IZOT, Building 1, Floor 3, Office 317 + Sofia Sofia 1784 + BG + +AC-1F-D7 (hex) Real Vision Technology Co.,Ltd. +AC1FD7 (base 16) Real Vision Technology Co.,Ltd. + A-805, 537, Dunchon-daero, Jungwon-gu + Seongnam-si Gyeonggi-do 13216 + KR + +88-C2-42 (hex) Poynt Co. +88C242 (base 16) Poynt Co. + 490 S. California Avenue + Palo Alto California 94306 + US + +14-02-EC (hex) Hewlett Packard Enterprise +1402EC (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +E0-34-E4 (hex) Feit Electric Company, Inc. +E034E4 (base 16) Feit Electric Company, Inc. + 4901 Gregg Road + Pico Rivera CA 90660 + US + +34-C9-F0 (hex) LM Technologies Ltd +34C9F0 (base 16) LM Technologies Ltd + Unit 19 Spectrum House + London England NW5 1LP + GB + +68-A8-28 (hex) HUAWEI TECHNOLOGIES CO.,LTD +68A828 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +CC-20-E8 (hex) Apple, Inc. +CC20E8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-BF-74 (hex) Baicells Technologies Co.,LTD +48BF74 (base 16) Baicells Technologies Co.,LTD + 10F,Dinghao Electronics Plaza-B,No.3 Haidian St.,Haidian Dist.,Beijing,China + Beijing Beijing 10080 + CN + +6C-93-54 (hex) Yaojin Technology (Shenzhen) Co., LTD. +6C9354 (base 16) Yaojin Technology (Shenzhen) Co., LTD. + No.18,Zhulong Tian Road,Shuitian No.4 Industrial Area,Shiyan Street, Baoan District,Shenzhen,China + Shenzhen Guangdong 518108 + CN + +DC-DC-07 (hex) TRP Systems BV +DCDC07 (base 16) TRP Systems BV + Televisieweg 159 1322 BH Almere + Almere - - + NL + +38-91-D5 (hex) Hangzhou H3C Technologies Co., Limited +3891D5 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +8C-E2-DA (hex) Circle Media Inc +8CE2DA (base 16) Circle Media Inc + 1319 SE Martin Luther King Jr. Blvd. + Portland Oregon 97214 + US + +38-21-87 (hex) Midea Group Co., Ltd. +382187 (base 16) Midea Group Co., Ltd. + No. 6 Midea Avenue, + Foshan Guangdong 528311 + CN + +78-D6-B2 (hex) Toshiba +78D6B2 (base 16) Toshiba + 2-9,Suehiro-Cho + Ome Tokyo 1988710 + JP + +E8-DE-D6 (hex) Intrising Networks, Inc. +E8DED6 (base 16) Intrising Networks, Inc. + 8F., No.67, Shitan Rd., Neihu Dist., Taipei City 11469 + Taipei + TW + +DC-82-F6 (hex) iPort +DC82F6 (base 16) iPort + 236 Calle Pintoresco + San Clemente CA 92672 + US + +70-48-0F (hex) Apple, Inc. +70480F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-B7-2B (hex) PLUMgrid Inc +3CB72B (base 16) PLUMgrid Inc + 5155 OLD IRONSIDES DR + Santa Clara CA 95054 + US + +48-9A-42 (hex) Technomate Ltd +489A42 (base 16) Technomate Ltd + Unit 11 Nobel Road + London N18 3BH + GB + +20-D1-60 (hex) Private +20D160 (base 16) Private + +BC-9C-31 (hex) HUAWEI TECHNOLOGIES CO.,LTD +BC9C31 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D8-8B-4C (hex) KingTing Tech. +D88B4C (base 16) KingTing Tech. + 8 Holly St + Irvine California 92612 + US + +38-4C-90 (hex) ARRIS Group, Inc. +384C90 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F0-B0-E7 (hex) Apple, Inc. +F0B0E7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-1C-23 (hex) Hilan Technology CO.,LTD +381C23 (base 16) Hilan Technology CO.,LTD + 604,Block 1,Kai Da Er Building,No.168 TongSha Road,XiLi Town,Nanshan,Shenzhen,P.R.C + Shenzhen Guandong 518055 + CN + +64-9A-12 (hex) P2 Mobile Technologies Limited +649A12 (base 16) P2 Mobile Technologies Limited + Unit 708, 7/F, Bio-Informatics Centre, No.2 Science Park West Avenue, + Hong Kong Hong Kong 00000 + HK + +AC-89-95 (hex) AzureWave Technology Inc. +AC8995 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +04-69-F8 (hex) Apple, Inc. +0469F8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +30-29-BE (hex) Shanghai MRDcom Co.,Ltd +3029BE (base 16) Shanghai MRDcom Co.,Ltd + NO.123 JULI RD + SHANGHAI PUDONG ZHANGJIANG HIGH-TECH PARK 201203 + CN + +20-C3-A4 (hex) RetailNext +20C3A4 (base 16) RetailNext + 60 S. Market St, 10th Floor + San Jose CA 95113 + US + +E4-C2-D1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E4C2D1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D4-F4-BE (hex) Palo Alto Networks +D4F4BE (base 16) Palo Alto Networks + 4401 Great America Parkway + Santa Clara CA 95054 + US + +48-B6-20 (hex) ROLI Ltd. +48B620 (base 16) ROLI Ltd. + 2 Glebe Road + London E8 4BD + GB + +D8-88-CE (hex) RF Technology Pty Ltd +D888CE (base 16) RF Technology Pty Ltd + 46/7 Sefton Rd + Thornleigh NSW 2120 + AU + +30-7C-B2 (hex) ANOV FRANCE +307CB2 (base 16) ANOV FRANCE + 100 CHEMIN DE BAILLOT + MONTAUBAN TARN ET GARONNE 82000 + FR + +84-79-73 (hex) Shanghai Baud Data Communication Co.,Ltd. +847973 (base 16) Shanghai Baud Data Communication Co.,Ltd. + NO.123 JULI RD + PUDONG ZHANGJIANG HIGH-TECH PARK SHANGHAI 201203 + CN + +E8-B4-C8 (hex) Samsung Electronics Co.,Ltd +E8B4C8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D0-87-E2 (hex) Samsung Electronics Co.,Ltd +D087E2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F0-5B-7B (hex) Samsung Electronics Co.,Ltd +F05B7B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-47-BF (hex) Samsung Electronics Co.,Ltd +B047BF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +7C-0B-C6 (hex) Samsung Electronics Co.,Ltd +7C0BC6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +7C-FE-90 (hex) Mellanox Technologies, Inc. +7CFE90 (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +84-5B-12 (hex) HUAWEI TECHNOLOGIES CO.,LTD +845B12 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +20-55-31 (hex) Samsung Electronics Co.,Ltd +205531 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +10-86-8C (hex) ARRIS Group, Inc. +10868C (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +44-FD-A3 (hex) Everysight LTD. +44FDA3 (base 16) Everysight LTD. + Advanced Technology Center P.O.B 539 + Haifa Haifa 31053 + IL + +A8-A7-95 (hex) Hon Hai Precision Ind. Co.,Ltd. +A8A795 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +90-6F-A9 (hex) NANJING PUTIAN TELECOMMUNICATIONS TECHNOLOGY CO.,LTD. +906FA9 (base 16) NANJING PUTIAN TELECOMMUNICATIONS TECHNOLOGY CO.,LTD. + No.1 Putian Road,Yuhuamenwai,Nanjing + Nan Jing Jiang Su 210022 + CN + +60-FD-56 (hex) WOORISYSTEMS CO., Ltd +60FD56 (base 16) WOORISYSTEMS CO., Ltd + 357-4, Neungpyeong-ri, Opo-eup + Gwangjiu-si Gyeonggi-do 464-921 + KR + +98-70-E8 (hex) INNATECH SDN BHD +9870E8 (base 16) INNATECH SDN BHD + 2, JALAN TIARA 3, TIARA SQUARE + SUBANG JAYA SELANGOR 47600 + MY + +44-65-6A (hex) Mega Video Electronic(HK) Industry Co., Ltd +44656A (base 16) Mega Video Electronic(HK) Industry Co., Ltd + Room 503, No.43 Fushun Street, Huanghai West Road, + Dalian Liaoning 116600 + CN + +78-EB-39 (hex) Instituto Nacional de Tecnología Industrial +78EB39 (base 16) Instituto Nacional de Tecnología Industrial + Av. Gral. Paz 5445 + San Martín Buenos Aires 1650 + AR + +0C-75-6C (hex) Anaren Microwave, Inc. +0C756C (base 16) Anaren Microwave, Inc. + 6635 Kirkville Road + East Syracuse NY 13057 + US + +D4-7B-B0 (hex) ASKEY COMPUTER CORP +D47BB0 (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +F0-22-4E (hex) Esan electronic co. +F0224E (base 16) Esan electronic co. + D&I Building 2nd floor + Gun-Po Kyunggido 435-862 + KR + +CC-5F-BF (hex) Topwise 3G Communication Co., Ltd. +CC5FBF (base 16) Topwise 3G Communication Co., Ltd. + 6 Floor, A8 Music Building, Keyuan Road, High-Tech Park, Nanshan District, Shenzhen, China + Shenzhen Guangdong 518000 + CN + +C8-F9-C8 (hex) NewSharp Technology(SuZhou)Co,Ltd +C8F9C8 (base 16) NewSharp Technology(SuZhou)Co,Ltd + 1st/f.building 7th No.328 XingHu street SuZhou City + SuZhou City JiangSu Province 215123 + CN + +80-C5-E6 (hex) Microsoft Corporation +80C5E6 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +10-DF-8B (hex) Shenzhen CareDear Communication Technology Co.,Ltd +10DF8B (base 16) Shenzhen CareDear Communication Technology Co.,Ltd + No.605,6th floor, 1st Section, 25th Building, Science and Technology Park Industrial Zone, median space, High-tech Zone + ShenZhen Guangdong 518000 + CN + +C4-12-F5 (hex) D-Link International +C412F5 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +5C-45-27 (hex) Juniper Networks +5C4527 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +E0-2C-B2 (hex) Lenovo Mobile Communication (Wuhan) Company Limited +E02CB2 (base 16) Lenovo Mobile Communication (Wuhan) Company Limited + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan, China 430205 + Wuhan Hubei 430205 + CN + +60-6D-C7 (hex) Hon Hai Precision Ind. Co.,Ltd. +606DC7 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +68-ED-A4 (hex) Shenzhen Seavo Technology Co.,Ltd +68EDA4 (base 16) Shenzhen Seavo Technology Co.,Ltd + 5H,West Building,NO.210,Terra Hi-Tech Industrial Park, + Shenzhen Guangdong 518040 + CN + +2C-C5-D3 (hex) Ruckus Wireless +2CC5D3 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +F4-57-3E (hex) Fiberhome Telecommunication Technologies Co.,LTD +F4573E (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +D0-43-1E (hex) Dell Inc. +D0431E (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +54-CD-10 (hex) Panasonic Mobile Communications Co.,Ltd. +54CD10 (base 16) Panasonic Mobile Communications Co.,Ltd. + 600 Saedo-cho Tsuzuki-ku + Yokohama City Kanagawa 224-8539 + JP + +40-8D-5C (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +408D5C (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + Pin-Jen City, Taoyuan, Taiwan, R.O.C. + Pin-Jen Taoyuan 324 + TW + +FC-E1-FB (hex) Array Networks +FCE1FB (base 16) Array Networks + 1371 McCarthy Blvd + Milpitas California 95035 + US + +E8-91-20 (hex) Motorola Mobility LLC, a Lenovo Company +E89120 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +D4-F9-A1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D4F9A1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +54-40-AD (hex) Samsung Electronics Co.,Ltd +5440AD (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A4-24-DD (hex) Cambrionix Ltd +A424DD (base 16) Cambrionix Ltd + St Johns Innovation Centre + Cambridge Cambridgeshire CB4 0WS + GB + +14-5A-83 (hex) Logi-D inc +145A83 (base 16) Logi-D inc + 5550 Des Rossignol Blvd + Laval Quebec H7L 5W6 + CA + +80-4E-81 (hex) Samsung Electronics Co.,Ltd +804E81 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C0-9A-71 (hex) XIAMEN MEITU MOBILE TECHNOLOGY CO.LTD +C09A71 (base 16) XIAMEN MEITU MOBILE TECHNOLOGY CO.LTD + 1-3F, Block2, No.6 Wanghai Rd,Siming District, Xiamen, Fujian, China (”MEITU”) + Xiamen Fujian 361008 + CN + +64-16-7F (hex) Polycom +64167F (base 16) Polycom + 6001 America Center Drive + San Jose CA 95002 + US + +34-0B-40 (hex) MIOS ELETTRONICA SRL +340B40 (base 16) MIOS ELETTRONICA SRL + VIA ARCHIMEDE, 10 + SAN MARTINO B.A. (VR) VERONA 37036 + IT + +48-06-6A (hex) Tempered Networks, Inc. +48066A (base 16) Tempered Networks, Inc. + 100 West Harrison St + Seattle WA 98119 + US + +BC-F8-11 (hex) Xiamen DNAKE Technology Co.,Ltd +BCF811 (base 16) Xiamen DNAKE Technology Co.,Ltd + 5F,Xingtel Building,Chuangxin Rd. + Xiamen Fujian 361006 + CN + +90-0A-39 (hex) Wiio, Inc. +900A39 (base 16) Wiio, Inc. + 99 S. Almaden Boulevard + San Jose California 95113 + US + +D0-C0-BF (hex) Actions Microelectronics Co., Ltd +D0C0BF (base 16) Actions Microelectronics Co., Ltd + 201, No 9 Building, Software Park,Kejizhonger Rd., + Shenzhen Gangdong 518057 + CN + +E8-61-BE (hex) Melec Inc. +E861BE (base 16) Melec Inc. + 516-10 Higashiasakawamachi + Hachioji Tokyo 193-0834 + JP + +58-70-C6 (hex) Shanghai Xiaoyi Technology Co., Ltd. +5870C6 (base 16) Shanghai Xiaoyi Technology Co., Ltd. + Shanghai Zhangjiang hi-tech park of Pudong New Area + Shanghai Shanghai 201120 + CN + +FC-8F-90 (hex) Samsung Electronics Co.,Ltd +FC8F90 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +74-04-2B (hex) Lenovo Mobile Communication (Wuhan) Company Limited +74042B (base 16) Lenovo Mobile Communication (Wuhan) Company Limited + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan, China 430205 + Wuhan Hubei 430205 + CN + +F8-7A-EF (hex) Rosonix Technology, Inc. +F87AEF (base 16) Rosonix Technology, Inc. + 10F, No.235, Sec. 4, Chengde Rd., + Taipei Taiwan 11167 + TW + +20-28-BC (hex) Visionscape Co,. Ltd. +2028BC (base 16) Visionscape Co,. Ltd. + 503, 145, Gasan Digital 1-ro, Geumcheon-gu, + Seoul Korea 153-787 + KR + +24-1C-04 (hex) SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD. +241C04 (base 16) SHENZHEN JEHE TECHNOLOGY DEVELOPMENT CO., LTD. + 2/F, Block A, Tsinghua Information Harbor, North Section + Shenzhen Guangdong 518057 + CN + +D0-5C-7A (hex) Sartura d.o.o. +D05C7A (base 16) Sartura d.o.o. + Kuniscak 28 + Zagreb 10000 + HR + +BC-5C-4C (hex) ELECOM CO.,LTD. +BC5C4C (base 16) ELECOM CO.,LTD. + 11F Tokyubancho Bldg. 6-2, + Chiyoda-ku Tokyo 102-0081 + JP + +88-70-33 (hex) Hangzhou Silan Microelectronic Inc +887033 (base 16) Hangzhou Silan Microelectronic Inc + No.4 HuangGuShan Road + Hangzhou Zhejiang 310012 + CN + +DC-56-E6 (hex) Shenzhen Bococom Technology Co.,LTD +DC56E6 (base 16) Shenzhen Bococom Technology Co.,LTD + 303, Dongjiang Environmental Build, LangShan Road. + Shenzhen Guangdong 518000 + CN + +CC-96-35 (hex) LVS Co.,Ltd. +CC9635 (base 16) LVS Co.,Ltd. + SmartValley B # 801 + Incheon 406-840 + KR + +44-80-EB (hex) Motorola Mobility LLC, a Lenovo Company +4480EB (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +40-28-14 (hex) RFI Engineering +402814 (base 16) RFI Engineering + Markerkant 13-76 + Almere Flevoland 1314AN + NL + +14-41-46 (hex) Honeywell (China) Co., LTD +144146 (base 16) Honeywell (China) Co., LTD + No. 100, Zunyi Road, Changning District + Shanghai Shanghai 200051 + CN + +94-F1-9E (hex) HUIZHOU MAORONG INTELLIGENT TECHNOLOGY CO.,LTD +94F19E (base 16) HUIZHOU MAORONG INTELLIGENT TECHNOLOGY CO.,LTD + China Guangdong Huizhou + Huizhou Guangdong 516000 + CN + +B8-56-BD (hex) ITT LLC +B856BD (base 16) ITT LLC + 1-ya Brestkaya St, building 35 + Moscow 125047 + RU + +40-A5-EF (hex) Shenzhen Four Seas Global Link Network Technology Co., Ltd. +40A5EF (base 16) Shenzhen Four Seas Global Link Network Technology Co., Ltd. + Room 607-610, Block B, TAOJINDI Electronic Business Incubation Base + Tenglong Road, Longhua District, Shenzhen Guangdong 518000 + CN + +C4-92-4C (hex) KEISOKUKI CENTER CO.,LTD. +C4924C (base 16) KEISOKUKI CENTER CO.,LTD. + 2-6-7 SAKANE + KAWANISHI-CITY HYOGO 666-0021 + JP + +74-9C-E3 (hex) KodaCloud Canada, Inc +749CE3 (base 16) KodaCloud Canada, Inc + Suite 310 + Ottawa Ontario K2K3G4 + CA + +D4-55-56 (hex) Fiber Mountain Inc. +D45556 (base 16) Fiber Mountain Inc. + 700 W Johnson Ave + Cheshire CT 06410 + US + +50-50-2A (hex) Egardia +50502A (base 16) Egardia + Kleine Landtong 19 + Gorinchem Zuid Holland 4201 HL + NL + +74-96-37 (hex) Todaair Electronic Co., Ltd +749637 (base 16) Todaair Electronic Co., Ltd + F.6 Electronic Building, No.1 Shuinan Guangdeli Road,Peng’Jiang District, Jiangmen, Guangdong, China + JiangMen Guangdong 529000 + CN + +88-E6-03 (hex) Avotek corporation +88E603 (base 16) Avotek corporation + 9-17, Dongil-ro 174-gil, Nowon-gu, Seoul + Seoul Seoul 139-808 + KR + +2C-AD-13 (hex) SHENZHEN ZHILU TECHNOLOGY CO.,LTD +2CAD13 (base 16) SHENZHEN ZHILU TECHNOLOGY CO.,LTD + B2-402 Kexin Science Park, Keyuan Road, Hi-tech Park, Nanshan District, Shenzhen + shenzhen Guangdong 518052 + CN + +78-AC-BF (hex) Igneous Systems +78ACBF (base 16) Igneous Systems + 2401 4th Ave + Seattle WA 98121 + US + +C4-8E-8F (hex) Hon Hai Precision Ind. Co.,Ltd. +C48E8F (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +C4-36-6C (hex) LG Innotek +C4366C (base 16) LG Innotek + Jangduk-dong 978-1 + Gwang-ju Gwangsan-gu 506-731 + KR + +54-36-9B (hex) 1Verge Internet Technology (Beijing) Co., Ltd. +54369B (base 16) 1Verge Internet Technology (Beijing) Co., Ltd. + 5th Floor, Sinosteel International Plaza + Haidian District Beijing + CN + +40-D2-8A (hex) Nintendo Co., Ltd. +40D28A (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +40-62-B6 (hex) Tele system communication +4062B6 (base 16) Tele system communication + 5F, No.437, Tao Ying Rd + Taoyuan 33068 + TW + +60-12-8B (hex) CANON INC. +60128B (base 16) CANON INC. + 30-2 Shimomaruko 3-chome, + Ohta-ku Tokyo 146-8501 + JP + +84-C3-E8 (hex) Vaillant GmbH +84C3E8 (base 16) Vaillant GmbH + Berghauser Straße 40 + Remscheid NRW D-42859 + DE + +9C-D3-5B (hex) Samsung Electronics Co.,Ltd +9CD35B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A8-9F-BA (hex) Samsung Electronics Co.,Ltd +A89FBA (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B8-8E-C6 (hex) Stateless Networks +B88EC6 (base 16) Stateless Networks + 388 Market Street + San Francisco CA 94111 + US + +BC-D1-65 (hex) Cisco SPVTG +BCD165 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +28-E4-76 (hex) Pi-Coral +28E476 (base 16) Pi-Coral + 2130 Gold Street, Ste. 200 + San Jose CA - California 95002 + US + +4C-A5-15 (hex) Baikal Electronics JSC +4CA515 (base 16) Baikal Electronics JSC + Highway Baltic 26 km, BC 'RigaLand, Block B, 3-rd entrance, 2-nd floor. + Krasnogorsk district Moscow region 143421 + RU + +7C-3C-B6 (hex) Shenzhen Homecare Technology Co.,Ltd. +7C3CB6 (base 16) Shenzhen Homecare Technology Co.,Ltd. + Homecare Industrial Zone,NO.30,Langdong road,Yangchuan,Songgang Town,Bao'an Distric , + Shenzhen Guangdong 5108105 + CN + +1C-7D-22 (hex) Fuji Xerox Co., Ltd. +1C7D22 (base 16) Fuji Xerox Co., Ltd. + 6-1 Minatomirai, Nishi-ku + Yokohama Kanagawa 220-8668 + JP + +20-C0-6D (hex) SHENZHEN SPACETEK TECHNOLOGY CO.,LTD +20C06D (base 16) SHENZHEN SPACETEK TECHNOLOGY CO.,LTD + 3F, NO.2, ChaXiSanWei Industrial Park, Gushu Community, XiXiang Street, BaoAn District + ShenZhen GuangDong 518100 + + +48-86-E8 (hex) Microsoft Corporation +4886E8 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +74-A3-4A (hex) ZIMI CORPORATION +74A34A (base 16) ZIMI CORPORATION + Room A913, 159 Chengjiang Road, Jiangyin City, Jiangsu Province, P, R.China + 214400 + CN + +A8-64-05 (hex) nimbus 9, Inc +A86405 (base 16) nimbus 9, Inc + 29 W. Cimarron St. + Colorado Springs CO 80903 + US + +30-D5-87 (hex) Samsung Electronics Co.,Ltd +30D587 (base 16) Samsung Electronics Co.,Ltd + #416, Maetan 3-dong + Suwon-si Gyeonggi-do 443-742 + KR + +68-28-F6 (hex) Vubiq Networks, Inc. +6828F6 (base 16) Vubiq Networks, Inc. + 9231 Irvine Blvd. + Irvine California 92618 + US + +DC-60-A1 (hex) Teledyne DALSA Professional Imaging +DC60A1 (base 16) Teledyne DALSA Professional Imaging + High Tech Campus 27 + Eindhoven NB 5656 AE + NL + +10-A6-59 (hex) Mobile Create Co.,Ltd. +10A659 (base 16) Mobile Create Co.,Ltd. + Kakukita 2-20-8 + Oita 870-0848 + JP + +58-85-6E (hex) QSC AG +58856E (base 16) QSC AG + Mathias-Brueggen-Str. 55 + Köln 50829 + DE + +8C-91-09 (hex) Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd. +8C9109 (base 16) Toyoshima Electric Technoeogy(Suzhou) Co.,Ltd. + No.399,Baisheng Road,Jinxi Town + Kunshan Jiangsu 215324 + CN + +54-09-8D (hex) deister electronic GmbH +54098D (base 16) deister electronic GmbH + Hermann-Bahlsen-Str. 11 + Barsinghausen Niedersachsen 30890 + DE + +D0-5B-A8 (hex) zte corporation +D05BA8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +E4-BA-D9 (hex) 360 Fly Inc. +E4BAD9 (base 16) 360 Fly Inc. + 1000 Town Center Blvd + Canonsburg PA 15317 + US + +EC-59-E7 (hex) Microsoft Corporation +EC59E7 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +C0-35-C5 (hex) Prosoft Systems LTD +C035C5 (base 16) Prosoft Systems LTD + Volgogradskaya 194-a + Ekaterinburg Sverdlovskay 620102 + RU + +A0-A3-E2 (hex) Actiontec Electronics, Inc +A0A3E2 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +74-54-7D (hex) Cisco SPVTG +74547D (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +00-E6-E8 (hex) Netzin Technology Corporation,.Ltd. +00E6E8 (base 16) Netzin Technology Corporation,.Ltd. + 4F-17, No. 26, Lane 321, Yang-Kuang St.,Neihu District, Taipei, Taiwan, + Taiwan Taipei Taiwan Taipei 11491 + TW + +50-F4-3C (hex) Leeo Inc +50F43C (base 16) Leeo Inc + 989 Comercial St + Palo Alto CA 94303 + US + +E8-87-A3 (hex) Loxley Public Company Limited +E887A3 (base 16) Loxley Public Company Limited + 102 Na Ranong Road, Klongtoey, + Bangkok 10110 + TH + +10-C6-7E (hex) SHENZHEN JUCHIN TECHNOLOGY CO., LTD +10C67E (base 16) SHENZHEN JUCHIN TECHNOLOGY CO., LTD + Unit 423 4/B NO.1, Central Business District + Shenzhen Guangdong 518000 + CN + +08-A5-C8 (hex) Sunnovo International Limited +08A5C8 (base 16) Sunnovo International Limited + 1717 Haitai Building + Beijing Beijing 100083 + CN + +F8-84-79 (hex) Yaojin Technology(Shenzhen)Co.,Ltd +F88479 (base 16) Yaojin Technology(Shenzhen)Co.,Ltd + Yaojin Park, Shui Tian No.4 Industrial Area ShiYan Tow, + SHENZHEN GUANGDONG 518108 + CN + +2C-29-97 (hex) Microsoft Corporation +2C2997 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +D4-61-32 (hex) Pro Concept Manufacturer Co.,Ltd. +D46132 (base 16) Pro Concept Manufacturer Co.,Ltd. + 88/1 Moo12 Soi Phetkasem120 + Kratumbaen Samutsakorn 74130 + TH + +54-A0-50 (hex) ASUSTek COMPUTER INC. +54A050 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +4C-2C-83 (hex) Zhejiang KaNong Network Technology Co.,Ltd. +4C2C83 (base 16) Zhejiang KaNong Network Technology Co.,Ltd. + Room 633, Building B, ShunFan Technology Park,JingChang Road No.768, YuHang District + Hangzhou Zhejiang 310000 + CN + +90-8C-09 (hex) Total Phase +908C09 (base 16) Total Phase + 735 Palomar Ave + Sunnyvale CA 94085 + US + +DC-2F-03 (hex) Step forward Group Co., Ltd. +DC2F03 (base 16) Step forward Group Co., Ltd. + 1/3 Park Village Rama2 Floor 2 C2-2 + Bangkok Bangkok 10150 + TH + +38-0E-7B (hex) V.P.S. Thai Co., Ltd +380E7B (base 16) V.P.S. Thai Co., Ltd + 279-281 Mangkorn Rd., Pomprab District + Bangkok Bangkok 10100 + TH + +2C-37-96 (hex) CYBO CO.,LTD. +2C3796 (base 16) CYBO CO.,LTD. + 218 MOO 3 LAEM CHA BANG + SRIRACHA CHONBURI 20230 + TH + +58-7F-B7 (hex) SONAR INDUSTRIAL CO., LTD. +587FB7 (base 16) SONAR INDUSTRIAL CO., LTD. + 29, 29/1, 29/2, MOO.3, THATALAD, + SAMPRAN NAKORN PATHOM 73110 + TH + +08-EB-29 (hex) Jiangsu Huitong Group Co.,Ltd. +08EB29 (base 16) Jiangsu Huitong Group Co.,Ltd. + No. 24, Block 2, Taohuawu New District + Zhenjiang Jiangsu 212003 + CN + +40-9B-0D (hex) Shenzhen Yourf Kwan Industrial Co., Ltd +409B0D (base 16) Shenzhen Yourf Kwan Industrial Co., Ltd + MCN Edifice 5D, R1 Building, No.21 4th Hi-tech Road South, High-tech Industrial Park(south) + Shenzhen Guangdong 518057 + CN + +D8-CB-8A (hex) Micro-Star INTL CO., LTD. +D8CB8A (base 16) Micro-Star INTL CO., LTD. + No.69, Lide St., + New Taipei City Taiwan 235 + TW + +70-FC-8C (hex) OneAccess SA +70FC8C (base 16) OneAccess SA + 381 avenue du général de Gaulle + CLAMART France 92140 + FR + +58-10-8C (hex) Intelbras +58108C (base 16) Intelbras + BR 101, km 210, S/N° + São José Santa Catarina 88104800 + BR + +4C-74-03 (hex) BQ +4C7403 (base 16) BQ + c Sofía 10. Polígono Európolis + Las Rozas de Madrid Madrid 28230 + ES + +8C-5D-60 (hex) UCI Corporation Co.,Ltd. +8C5D60 (base 16) UCI Corporation Co.,Ltd. + 299/195-7, Chaengwattana Road, + Bangkok Bangkok 10210 + TH + +BC-6B-4D (hex) Nokia +BC6B4D (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +C8-D0-19 (hex) Shanghai Tigercel Communication Technology Co.,Ltd +C8D019 (base 16) Shanghai Tigercel Communication Technology Co.,Ltd + Room 805, building 1 + Shanghai 200235 + CN + +90-21-81 (hex) Shanghai Huaqin Telecom Technology Co.,Ltd +902181 (base 16) Shanghai Huaqin Telecom Technology Co.,Ltd + No.1 Building,399 Keyuan Road, Zhangjian Hi-Tech Park, + shanghai shanghai 201203 + CN + +84-96-81 (hex) Cathay Communication Co.,Ltd +849681 (base 16) Cathay Communication Co.,Ltd + Tsinghua Institude A319 of Hi-tech Park,Nanshan district,Shenzhen China + Shenzhen Canton 0755 + CN + +2C-A3-0E (hex) POWER DRAGON DEVELOPMENT LIMITED +2CA30E (base 16) POWER DRAGON DEVELOPMENT LIMITED + Room D, 10/F Tower A, Billion Centre, 1 Wang Kwong Road, Kowloon Bay + HONG KONG HONG KONG 999077 + CN + +84-86-F3 (hex) Greenvity Communications +8486F3 (base 16) Greenvity Communications + 673 S. Milpitas Blvd Suite 204 + Milpitas California 95035 + US + +1C-52-16 (hex) DONGGUAN HELE ELECTRONICS CO., LTD +1C5216 (base 16) DONGGUAN HELE ELECTRONICS CO., LTD + Lijiangwei Group, + Dongguan City Guangdong 86 + CN + +60-99-D1 (hex) Vuzix / Lenovo +6099D1 (base 16) Vuzix / Lenovo + 2166 Brighton Henrietta Town Line Road + Rochester NY 14623 + US + +B0-45-15 (hex) mira fitness,LLC. +B04515 (base 16) mira fitness,LLC. + 1925 West Field Court Suite100 + Lake Forest IL 60045 + US + +14-48-8B (hex) Shenzhen Doov Technology Co.,Ltd +14488B (base 16) Shenzhen Doov Technology Co.,Ltd + 11st Floor,East,2nd Phase + Futian District, Shenzhen Guangdong 518040 + CN + +20-12-D5 (hex) Scientech Materials Corporation +2012D5 (base 16) Scientech Materials Corporation + No.7, Hejiang 2nd Rd., Chungli , Taoyuan Hsien 320, Taiwan + Taoyuan Hsien Chungli 320 + TW + +6C-6E-FE (hex) Core Logic Inc. +6C6EFE (base 16) Core Logic Inc. + 11th Fl., 1-B U-SPACE Bldg. + Seongnam Gyeonggi-do 463-400 + KR + +38-08-FD (hex) Silca Spa +3808FD (base 16) Silca Spa + Via Podgora, 20 (Z.I.) + Vittorio Veneto TV 31029 + IT + +78-45-61 (hex) CyberTAN Technology Inc. +784561 (base 16) CyberTAN Technology Inc. + 99 Park Ave III, Hsinchu Science Park + Hsinchu 308 + TW + +94-CE-31 (hex) CTS Limited +94CE31 (base 16) CTS Limited + 1st district, 23D, 21 + Moscow - 142784 + RU + +80-F8-EB (hex) RayTight +80F8EB (base 16) RayTight + Room 1-216, Building 25, No 9, Anningzhuang West Road + Haidian District Beijing 100085 + CN + +D4-37-D7 (hex) zte corporation +D437D7 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +2C-01-0B (hex) NASCENT Technology, LLC - RemKon +2C010B (base 16) NASCENT Technology, LLC - RemKon + 2744 Yorkmont Road + Charlotte NC 28208 + + +04-DE-DB (hex) Rockport Networks Inc +04DEDB (base 16) Rockport Networks Inc + 515 Legget Dr., Suite 600 + Kanata ON K2K 3G4 + CA + +1C-48-40 (hex) IMS Messsysteme GmbH +1C4840 (base 16) IMS Messsysteme GmbH + Dieselstr. 55 + Heiligenhaus NRW D-42579 + DE + +60-50-C1 (hex) Kinetek Sports +6050C1 (base 16) Kinetek Sports + 16885 Via Del Campo Ct. + San Diego Ca 92127 + US + +2C-1A-31 (hex) Electronics Company Limited +2C1A31 (base 16) Electronics Company Limited + Units 12,15&16,8/F,Metro Centre 2 + Kowloon Bay HongKong 852 + CN + +90-B6-86 (hex) Murata Manufacturing Co., Ltd. +90B686 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +EC-D9-D1 (hex) Shenzhen TG-NET Botone Technology Co.,Ltd. +ECD9D1 (base 16) Shenzhen TG-NET Botone Technology Co.,Ltd. + East F/3,No.38 Huarong Second Industry Zone + Shenzhen Guangdong 518109 + CN + +6C-02-73 (hex) Shenzhen Jin Yun Video Equipment Co., Ltd. +6C0273 (base 16) Shenzhen Jin Yun Video Equipment Co., Ltd. + 4th floor, 78th, Matou Road + Shenzhen Guangdong 518000 + CN + +54-DF-00 (hex) Ulterius Technologies, LLC +54DF00 (base 16) Ulterius Technologies, LLC + 1625 N. Waterfront Parkway + Wichita KS 67206 + US + +20-ED-74 (hex) Ability enterprise co.,Ltd. +20ED74 (base 16) Ability enterprise co.,Ltd. + 4F., No.8, Ln.7, Wuquan Rd, Wugu Dist, New Taipei City 24886, Taiwan(R.O.C) + Taipei Taipei 24886 + TW + +A0-56-B2 (hex) Harman/Becker Automotive Systems GmbH +A056B2 (base 16) Harman/Becker Automotive Systems GmbH + Becker-Göring-Straße 16 + Karlsbad Baden-Württemberg 76307 + DE + +44-66-6E (hex) IP-LINE +44666E (base 16) IP-LINE + #204, Gangseo B/D + Guro-gu Seoul 152-826 + KR + +24-4F-1D (hex) iRule LLC +244F1D (base 16) iRule LLC + 1555 Broadway St + Detroit MI 48226 + US + +94-AE-E3 (hex) Belden Hirschmann Industries (Suzhou) Ltd. +94AEE3 (base 16) Belden Hirschmann Industries (Suzhou) Ltd. + 333 Yanhu Road, Huaqiao Town + Kunshan Jiangsu 215332 + CN + +5C-B6-CC (hex) NovaComm Technologies Inc. +5CB6CC (base 16) NovaComm Technologies Inc. + 902A, #560 Shengxia Rd., ZJ Inno Park + Shanghai 201203 + CN + +70-5B-2E (hex) M2Communication Inc. +705B2E (base 16) M2Communication Inc. + Room 12, 18F., No.65, Gaotie 7th Road + Zhubei City Hsinchu County 302 + TW + +5C-15-15 (hex) ADVAN +5C1515 (base 16) ADVAN + Wisma SMR.JL.Yos Sudarso Kav 89,Lt8.Suite 804,Jakarta Utara 10730 + Jakarta Jakarta Utara 14350 + ID + +D0-59-E4 (hex) Samsung Electronics Co.,Ltd +D059E4 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-A3-64 (hex) Samsung Electronics Co.,Ltd +14A364 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B4-0A-C6 (hex) DEXON Systems Ltd. +B40AC6 (base 16) DEXON Systems Ltd. + Baross u. 165 + Budaors Pest H-2040 + HU + +D8-66-EE (hex) BOXIN COMMUNICATION CO.,LTD. +D866EE (base 16) BOXIN COMMUNICATION CO.,LTD. + Room 309,Block A,New materials business building + Haidian District Beijing 100094 + CN + +28-29-CC (hex) Corsa Technology Incorporated +2829CC (base 16) Corsa Technology Incorporated + 505 March Road + Ottawa Ontario K2K 3A4 + CA + +18-4A-6F (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +184A6F (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +10-C3-7B (hex) ASUSTek COMPUTER INC. +10C37B (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +E8-5D-6B (hex) Luminate Wireless +E85D6B (base 16) Luminate Wireless + 20823 Stevens Creek Blvd, Suite 300 + Cupertino CA 95014 + US + +B4-0B-44 (hex) Smartisan Technology Co., Ltd. +B40B44 (base 16) Smartisan Technology Co., Ltd. + 7/F, Motorola Bldg., 1st Wangjing East Rd, + Beijing 100102 + CN + +34-31-C4 (hex) AVM GmbH +3431C4 (base 16) AVM GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +50-FE-F2 (hex) Sify Technologies Ltd +50FEF2 (base 16) Sify Technologies Ltd + II floor, TIDEL Park, + chennai Tamilnadu 600113 + IN + +34-C5-D0 (hex) Hagleitner Hygiene International GmbH +34C5D0 (base 16) Hagleitner Hygiene International GmbH + Lunastrasse 5 + Zell am See Salzburg 5700 + AT + +A0-12-DB (hex) TABUCHI ELECTRIC CO.,LTD +A012DB (base 16) TABUCHI ELECTRIC CO.,LTD + 4-2-21 + OSAKA 532-0003 + JP + +48-1A-84 (hex) Pointer Telocation Ltd +481A84 (base 16) Pointer Telocation Ltd + 14 Hamelacha Street, + Rosh Ha’ayin Israel 48091 + IL + +DC-66-3A (hex) Apacer Technology Inc. +DC663A (base 16) Apacer Technology Inc. + 1F., No.32, Zhongcheng Rd., Tucheng Dist., + New Taipei City Taiwan R.O.C. 236 + TW + +08-DF-1F (hex) Bose Corporation +08DF1F (base 16) Bose Corporation + The Mountain + Framingham MA 01701-9168 + US + +58-1F-67 (hex) Open-m technology limited +581F67 (base 16) Open-m technology limited + logan century buildding ,No.23 of Hai xiu road + Shenzhen Guangdong 518000 + CN + +48-26-E8 (hex) Tek-Air Systems, Inc. +4826E8 (base 16) Tek-Air Systems, Inc. + 41 Eagle Road + Danbury CT 06810 + US + +D0-5A-F1 (hex) Shenzhen Pulier Tech CO.,Ltd +D05AF1 (base 16) Shenzhen Pulier Tech CO.,Ltd + 3rd Floor, NO. B Buliding, District A, Shajing minzhu jiujiu industrial park , Shenzhen, China + Shenzhen Guangdong 518104 + CN + +FC-E1-86 (hex) A3M Co., LTD +FCE186 (base 16) A3M Co., LTD + KeumJeong Highview 2F #205, + Gunpo Gyeonggi 435-845 + KR + +54-EF-92 (hex) Shenzhen Elink Technology Co., LTD +54EF92 (base 16) Shenzhen Elink Technology Co., LTD + A531, Famous, No 168 Bao Yuan Road, + Shenzhen Guangdong 518000 + CN + +EC-E5-12 (hex) tado GmbH +ECE512 (base 16) tado GmbH + Lindwurmstr. 76 + Munich Bavaria 80337 + DE + +30-91-8F (hex) Technicolor +30918F (base 16) Technicolor + Prins Boudewijnlaan 47 + Edegem - Belgium B-2650 + BE + +5C-F4-AB (hex) Zyxel Communications Corporation +5CF4AB (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +08-B2-A3 (hex) Cynny Italia S.r.L. +08B2A3 (base 16) Cynny Italia S.r.L. + Via delle Mantellate, 8 + Firenze FI 59021 + IT + +70-30-5D (hex) Ubiquoss Inc +70305D (base 16) Ubiquoss Inc + 8F Ubiquoss B/D, 68, Pangyo-ro 255beon-gil, Bundang-gu + Seongnam-si Gyeonggi-do 463-400 + KR + +48-82-44 (hex) Life Fitness / Div. of Brunswick +488244 (base 16) Life Fitness / Div. of Brunswick + 10601 W. Belmont Ave + Franklin Park IL 60131 + US + +C8-31-68 (hex) eZEX corporation +C83168 (base 16) eZEX corporation + Rm 508, Ssangyong IT Twin-Tower II, 442-5 + Seongnam-si Gyeonggi-do 462-120 + KR + +40-B3-CD (hex) Chiyoda Electronics Co.,Ltd. +40B3CD (base 16) Chiyoda Electronics Co.,Ltd. + 1-3-11 Nishiki-cho + Warabi Saitama + JP + +24-33-6C (hex) Private +24336C (base 16) Private + +20-25-64 (hex) PEGATRON CORPORATION +202564 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +C8-D5-90 (hex) FLIGHT DATA SYSTEMS +C8D590 (base 16) FLIGHT DATA SYSTEMS + 31 MCGREGORS DRIVE + KEILOR PARK VICTORIA 3042 + AU + +7C-FF-62 (hex) Huizhou Super Electron Technology Co.,Ltd. +7CFF62 (base 16) Huizhou Super Electron Technology Co.,Ltd. + 10F,Financial Tower,No.23,Xiapu Road + Huizhou City Guangdong Province 516001 + CN + +84-B5-9C (hex) Juniper Networks +84B59C (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +C0-9D-26 (hex) Topicon HK Lmd. +C09D26 (base 16) Topicon HK Lmd. + 302, 3F, Lee Loong Building + Central Hong Kong 0000 + US + +44-29-38 (hex) NietZsche enterprise Co.Ltd. +442938 (base 16) NietZsche enterprise Co.Ltd. + 4F. No.560 Sec2 Chung Shan Rd. + New Taipei City Taiwan R.O.C Taipei ( 臺 北 縣 / 市 ) 220 + TW + +A0-DA-92 (hex) Nanjing Glarun Atten Technology Co. Ltd. +A0DA92 (base 16) Nanjing Glarun Atten Technology Co. Ltd. + Dinghuai men No. 1, Gulou District + + CN + +EC-F7-2B (hex) HD DIGITAL TECH CO., LTD. +ECF72B (base 16) HD DIGITAL TECH CO., LTD. + Room 602, Baoyuan road, Banan District + Shenzhen Guangdong 518102 + US + +4C-F4-5B (hex) Blue Clover Devices +4CF45B (base 16) Blue Clover Devices + 1001 Bayhill Dr + San Bruno CA 94066 + US + +B0-69-71 (hex) DEI Sales, Inc. +B06971 (base 16) DEI Sales, Inc. + 1 Viper Way + Vista CA 92081 + US + +18-89-DF (hex) CerebrEX Inc. +1889DF (base 16) CerebrEX Inc. + Central Shin-Osaka Building 10F + Osaka Osaka 532-0003 + JP + +54-C8-0F (hex) TP-LINK TECHNOLOGIES CO.,LTD. +54C80F (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +E4-D3-32 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +E4D332 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +0C-20-26 (hex) noax Technologies AG +0C2026 (base 16) noax Technologies AG + Am Forst 6 + Ebersberg 85560 + DE + +28-3B-96 (hex) Cool Control LTD +283B96 (base 16) Cool Control LTD + Mivtahim 2 + Petah Tikva Israel 4951774 + IL + +64-8D-9E (hex) IVT Electronic Co.,Ltd +648D9E (base 16) IVT Electronic Co.,Ltd + F building Dongxing Insdustrial Area + Dongguan City Guangdong provice 523457 + CN + +CC-95-D7 (hex) Vizio, Inc +CC95D7 (base 16) Vizio, Inc + 39 Tesla + Irvine CA 92618 + US + +FC-09-F6 (hex) GUANGDONG TONZE ELECTRIC CO.,LTD +FC09F6 (base 16) GUANGDONG TONZE ELECTRIC CO.,LTD + No.12-12 Block,Jinyuan Industrical City,Chaoshan Road,Shantou,Guangdong,china + Shantou Guangdong 515021 + CN + +BC-F6-1C (hex) Geomodeling Wuxi Technology Co. Ltd. +BCF61C (base 16) Geomodeling Wuxi Technology Co. Ltd. + Room1708, 17/F, North Star Times Tower, No.8 BeiChen East Road + Beijing 100101 + CN + +FC-92-3B (hex) Nokia Corporation +FC923B (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +E0-3F-49 (hex) ASUSTek COMPUTER INC. +E03F49 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +88-A7-3C (hex) Ragentek Technology Group +88A73C (base 16) Ragentek Technology Group + D10/D11, No.3188, Xiupu Road + Shanghai 201315 + CN + +88-D9-62 (hex) Canopus Systems US LLC +88D962 (base 16) Canopus Systems US LLC + Nasa Ames Research Park + Moffett Field CALIFORNIA 94035 + US + +D0-9C-30 (hex) Foster Electric Company, Limited +D09C30 (base 16) Foster Electric Company, Limited + 1-1-109, Tsutsujigaoka + Akishima Tokyo 196-8550 + JP + +94-9F-3F (hex) Optek Digital Technology company limited +949F3F (base 16) Optek Digital Technology company limited + Room508 Build A, Shennan Garden, Shenzhen Science and Industry Park, Nanshan + Shenzhen GuangDong 518057 + CN + +E8-17-FC (hex) Fujitsu Cloud Technologies Limited +E817FC (base 16) Fujitsu Cloud Technologies Limited + Shinjuku Front Tower 21-1 + Kita-shinjuku 2-chome Shinjuku-ku, Tokyo 169-0074 + JP + +78-FE-E2 (hex) Shanghai Diveo Technology Co., Ltd +78FEE2 (base 16) Shanghai Diveo Technology Co., Ltd + No.8,Lane 777,LongWu Rd + Shanghai 200232 + CN + +08-6D-F2 (hex) Shenzhen MIMOWAVE Technology Co.,Ltd +086DF2 (base 16) Shenzhen MIMOWAVE Technology Co.,Ltd + + Shenzhen Guangdong 518172 + CN + +68-78-48 (hex) Westunitis Co., Ltd. +687848 (base 16) Westunitis Co., Ltd. + North Building 7F, 3-1 Ofuka-cho, Kita-ku + Osaka-city Osaka-pref 5300011 + JP + +48-D0-CF (hex) Universal Electronics, Inc. +48D0CF (base 16) Universal Electronics, Inc. + 201 E. Sandpointe Ave + Santa Ana CA 92707 + US + +9C-3E-AA (hex) EnvyLogic Co.,Ltd. +9C3EAA (base 16) EnvyLogic Co.,Ltd. + #605,Gwanyang Doosan Ven Digm B/D + Anyang-si Gyeonggi-do 431-810 + KR + +1C-FC-BB (hex) Realfiction ApS +1CFCBB (base 16) Realfiction ApS + Oester Alle 42, 5 + Copenhagen OE 2100 + DK + +F8-F0-05 (hex) Newport Media Inc. +F8F005 (base 16) Newport Media Inc. + 1 Spectrum Pointe Drive Suite 225 + Lake Forest CA 92630 + US + +28-65-6B (hex) Keystone Microtech Corporation +28656B (base 16) Keystone Microtech Corporation + 9F., No.255, Dong Sec. 1, + Jhubei City, Hsinchu County 302 + TW + +CC-9F-35 (hex) Transbit Sp. z o.o. +CC9F35 (base 16) Transbit Sp. z o.o. + Przyczolkowa 109A + Warsaw 02-968 + PL + +DC-C7-93 (hex) Nokia Corporation +DCC793 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +44-48-91 (hex) HDMI Licensing, LLC +444891 (base 16) HDMI Licensing, LLC + 1140 East Arques, Suite 100 + Sunnyvale CA 94085 + US + +5C-25-4C (hex) Avire Global Pte Ltd +5C254C (base 16) Avire Global Pte Ltd + 8 Admiralty Street + Singapore 757438 + SG + +D4-2F-23 (hex) Akenori PTE Ltd +D42F23 (base 16) Akenori PTE Ltd + 176 Joo Chiat Road, #02-02 + Singapore 427447 + SG + +98-C0-EB (hex) Global Regency Ltd +98C0EB (base 16) Global Regency Ltd + 20F, Phase A, Wenjin Plaza, + Shen Zhen Guangdong 518000 + CN + +F0-3F-F8 (hex) R L Drake +F03FF8 (base 16) R L Drake + 1 Jake Brown Road + Old Bridge NJ 08857 + US + +B0-C5-54 (hex) D-Link International +B0C554 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +48-EE-86 (hex) UTStarcom (China) Co.,Ltd +48EE86 (base 16) UTStarcom (China) Co.,Ltd + 25 Floor,A Block,1#Building,TianZuo International Center, + Haidian District BeiJing 100081 + CN + +88-89-14 (hex) All Components Incorporated +888914 (base 16) All Components Incorporated + 828 New Meister Lane + Pflugerville TX 78660 + US + +F0-32-1A (hex) Mita-Teknik A/S +F0321A (base 16) Mita-Teknik A/S + Aktieselskabet af 12.12.2006 + Roedkaersbro 8840 + DK + +A8-81-F1 (hex) BMEYE B.V. +A881F1 (base 16) BMEYE B.V. + Hoogoorddreef 60 + Amsterdam 1101BE + NL + +C4-E9-84 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +C4E984 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +D0-69-D0 (hex) Verto Medical Solutions, LLC +D069D0 (base 16) Verto Medical Solutions, LLC + 900 Spruce St., Suite 550 + St. Louis Missouri 63012 + US + +FC-13-49 (hex) Global Apps Corp. +FC1349 (base 16) Global Apps Corp. + 12F., No 225, Sec. 5 Nanjing E. Rd + Taipei 105 + TW + +84-84-33 (hex) Paradox Engineering SA +848433 (base 16) Paradox Engineering SA + Via Passeggiata, 7 + Novazzano Ticino 6883 + CH + +44-C3-06 (hex) SIFROM Inc. +44C306 (base 16) SIFROM Inc. + 1201 N. Orange St., Ste 700 #7112 + Wilmington DE 19801-1186 + US + +60-21-03 (hex) I4VINE, INC +602103 (base 16) I4VINE, INC + TLI Building 6th floor, 195 + Seongnam-si Gyeonggi-do 462-100 + KR + +FC-07-A0 (hex) LRE Medical GmbH +FC07A0 (base 16) LRE Medical GmbH + Hofer Strasse 5 + Noerdlingen Bavaria 86720 + DE + +1C-EE-E8 (hex) Ilshin Elecom +1CEEE8 (base 16) Ilshin Elecom + 2973, Hagun-ri, Yangchon-eup + Gimpo-si Gyeonggi-do 415-843 + KR + +90-31-CD (hex) Onyx Healthcare Inc. +9031CD (base 16) Onyx Healthcare Inc. + 2F ,No135, Lane235, + New Taipei City 231 + TW + +E4-81-84 (hex) Nokia +E48184 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +14-C0-89 (hex) DUNE HD LTD +14C089 (base 16) DUNE HD LTD + 2F., No.297, Sec. 2, Tiding Blvd., + Taipei 11493 + TW + +F4-B6-E5 (hex) TerraSem Co.,Ltd +F4B6E5 (base 16) TerraSem Co.,Ltd + 9,Gwahaksaneop 5-ro + Cheongwon-Gu ChungBuk 363-885 + KR + +60-FF-DD (hex) C.E. ELECTRONICS, INC +60FFDD (base 16) C.E. ELECTRONICS, INC + 2107 INDUSTRIAL DR + BRYAN OHIO 43506 + US + +24-05-0F (hex) MTN Electronic Co. Ltd +24050F (base 16) MTN Electronic Co. Ltd + MTN Industrial Park,No 3, Fuhua Road, + Shenzhen Guangdong Province 518117 + CN + +AC-2D-A3 (hex) TXTR GmbH +AC2DA3 (base 16) TXTR GmbH + Rosenthaler Str. 13 + Berlin 10119 + DE + +88-9C-A6 (hex) BTB Korea INC +889CA6 (base 16) BTB Korea INC + #1001, Suntech City 1st + Sungnam Kyunggido 462-725 + KR + +90-83-7A (hex) General Electric Water & Process Technologies +90837A (base 16) General Electric Water & Process Technologies + 6060 Spine Road + Boulder Colorado 80301-3687 + US + +80-BA-E6 (hex) Neets +80BAE6 (base 16) Neets + Langballe 4 + Horsens Jylland 8700 + DK + +F8-A2-B4 (hex) RHEWA-WAAGENFABRIK August Freudewald GmbH &Co. KG +F8A2B4 (base 16) RHEWA-WAAGENFABRIK August Freudewald GmbH &Co. KG + Feldstr. 17 + Mettmann 40822 + DE + +E0-56-F4 (hex) AxesNetwork Solutions inc. +E056F4 (base 16) AxesNetwork Solutions inc. + 410 pepin + Sherbrooke qc j1l2y8 + CA + +84-56-9C (hex) Coho Data, Inc., +84569C (base 16) Coho Data, Inc., + 1230 Midas Way, Suite 110 + Sunnyvale CA 94085 + US + +78-AE-0C (hex) Far South Networks +78AE0C (base 16) Far South Networks + 49 Bell Crescent + Westlake Western Cape 7945 + ZA + +B0-24-F3 (hex) Progeny Systems +B024F3 (base 16) Progeny Systems + 9500 Innovation Drive + Manassas VA 20110 + US + +0C-54-A5 (hex) PEGATRON CORPORATION +0C54A5 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +8C-4D-B9 (hex) Unmonday Ltd +8C4DB9 (base 16) Unmonday Ltd + Laivakatu 3 + Helsinki Uusimaa 00150 + FI + +78-CA-5E (hex) ELNO +78CA5E (base 16) ELNO + 43 rue Michel Carré + Argenteuil - F95102 + US + +2C-5A-05 (hex) Nokia Corporation +2C5A05 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +D4-81-CA (hex) iDevices, LLC +D481CA (base 16) iDevices, LLC + 136 Simsbury, Rd + Avon CT 06001 + US + +D8-58-D7 (hex) CZ.NIC, z.s.p.o. +D858D7 (base 16) CZ.NIC, z.s.p.o. + Americka 23 + Prague 12000 + CZ + +B0-D7-C5 (hex) Logipix Ltd +B0D7C5 (base 16) Logipix Ltd + Kesmark utca 11-13 + Budapest - 1158 + HU + +A4-3A-69 (hex) Vers Inc +A43A69 (base 16) Vers Inc + PO Box 5265 + Wayland MA 01778 + US + +9C-44-A6 (hex) SwiftTest, Inc. +9C44A6 (base 16) SwiftTest, Inc. + 3255 Scott Blvd. + Santa Clara California 95054 + US + +4C-D9-C4 (hex) Magneti Marelli Automotive Electronics (Guangzhou) Co. Ltd +4CD9C4 (base 16) Magneti Marelli Automotive Electronics (Guangzhou) Co. Ltd + Building B10, No.8 Jinghu Road + Guangzhou Guangdong 510800 + CN + +50-E0-C7 (hex) TurControlSystme AG +50E0C7 (base 16) TurControlSystme AG + Geschwister-Scholl-Strasse 7 + Genthin Sachsen-Anhalt 39307 + DE + +B4-82-7B (hex) AKG Acoustics GmbH +B4827B (base 16) AKG Acoustics GmbH + Lemboeckgasse 21-25 + Vienna 1230 + AT + +DC-5E-36 (hex) Paterson Technology +DC5E36 (base 16) Paterson Technology + 23490 SE 51st Pl + Issaquah WA 98029 + US + +DC-AD-9E (hex) GreenPriz +DCAD9E (base 16) GreenPriz + 549, boulevard Pierre Sauvaigo + La Colle sur Loup 06480 + FR + +B8-DF-6B (hex) SpotCam Co., Ltd. +B8DF6B (base 16) SpotCam Co., Ltd. + 12F.-1, No.125, Jianguo Rd. + New Taipei City 239 + TW + +9C-88-88 (hex) Simac Techniek NV +9C8888 (base 16) Simac Techniek NV + De Run 1101 + Veldhoven NB 5503LB + NL + +10-B2-6B (hex) base Co.,Ltd. +10B26B (base 16) base Co.,Ltd. + F1 92 building taoyuancun longzhu road + Shenzhen Guangdong 518000 + CN + +4C-F0-2E (hex) Vifa Denmark A/S +4CF02E (base 16) Vifa Denmark A/S + Mariendalsvej 2A + Viborg DK-8800 + US + +28-8A-1C (hex) Juniper Networks +288A1C (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +DC-CE-BC (hex) Shenzhen JSR Technology Co.,Ltd. +DCCEBC (base 16) Shenzhen JSR Technology Co.,Ltd. + 2-3F,E building,Yu Jianfeng science and industry park + Shenzhen City Guangdong 518109 + CN + +18-C8-E7 (hex) Shenzhen Hualistone Technology Co.,Ltd +18C8E7 (base 16) Shenzhen Hualistone Technology Co.,Ltd + 1708RM,Huafeng HQ Economic Building, + Shenzhen Guangdong 518102 + CN + +A0-3B-1B (hex) Inspire Tech +A03B1B (base 16) Inspire Tech + No.588-10,Zhongzheng Rd.,Xinzhuang Dist + New Taipei Taiwan 24255 + TW + +7C-CD-3C (hex) Guangzhou Juzing Technology Co., Ltd +7CCD3C (base 16) Guangzhou Juzing Technology Co., Ltd + Building C Rm 1906-1909 + Guangzhou Guangdong 510630 + US + +98-43-DA (hex) INTERTECH +9843DA (base 16) INTERTECH + 3F. 14-9 Sarihyun-Ro. Ilsandong-Gu + Goyang-Si Gyeonggi-Do 410-821 + KR + +08-CA-45 (hex) Toyou Feiji Electronics Co., Ltd. +08CA45 (base 16) Toyou Feiji Electronics Co., Ltd. + No.2 Building No.9 Yard, Dijin Road, + Beijing 100095 + CN + +3C-CA-87 (hex) Iders Incorporated +3CCA87 (base 16) Iders Incorporated + 27047 Oakwood Rd + Oakbank Manitoba R0E 1J2 + CA + +7C-6A-B3 (hex) IBC TECHNOLOGIES INC. +7C6AB3 (base 16) IBC TECHNOLOGIES INC. + 1445 CHARLES STREET + Vancouver British Columbia V5L2S7 + CA + +18-1B-EB (hex) Actiontec Electronics, Inc +181BEB (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +84-A7-83 (hex) Alcatel Lucent +84A783 (base 16) Alcatel Lucent + Via Energy Park, 14 + Vimercate MB 20871 + IT + +04-1A-04 (hex) WaveIP +041A04 (base 16) WaveIP + 1 Sky street + Misgav 20179 + IL + +68-76-4F (hex) Sony Mobile Communications Inc +68764F (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +34-A5-E1 (hex) Sensorist ApS +34A5E1 (base 16) Sensorist ApS + Nyhavn 16 + Copenhagen K Sjaelland 1051 + DK + +80-79-AE (hex) ShanDong Tecsunrise Co.,Ltd +8079AE (base 16) ShanDong Tecsunrise Co.,Ltd + B316,F-2,QiLu Soft Park, + JiNan ShanDong 250101 + CN + +7C-BD-06 (hex) AE REFUsol +7CBD06 (base 16) AE REFUsol + Uracher Str. 91 + Metzingen Baden-Württemberg 72555 + DE + +94-BA-56 (hex) Shenzhen Coship Electronics Co., Ltd. +94BA56 (base 16) Shenzhen Coship Electronics Co., Ltd. + Rainbow Bldg., North, Hi-Tech Industrial Park + Shenzhen Guangdong 518057 + CN + +38-DB-BB (hex) Sunbow Telecom Co., Ltd. +38DBBB (base 16) Sunbow Telecom Co., Ltd. + 3F, 501-21, Chung Cheng Rd., Hsin Tien Dist. + New Taipei City 23148 + TW + +44-8A-5B (hex) Micro-Star INT'L CO., LTD. +448A5B (base 16) Micro-Star INT'L CO., LTD. + No69, LIde St. + Taipei 235 + TW + +6C-4B-7F (hex) Vossloh-Schwabe Deutschland GmbH +6C4B7F (base 16) Vossloh-Schwabe Deutschland GmbH + Wasenstrasse 25 + Urbach 73660 + DE + +90-8C-44 (hex) H.K ZONGMU TECHNOLOGY CO., LTD. +908C44 (base 16) H.K ZONGMU TECHNOLOGY CO., LTD. + ROOM 604, BUILDING B, 977 SHANGFENG RD + SHANGHAI 201201 + CN + +68-8A-B5 (hex) EDP Servicos +688AB5 (base 16) EDP Servicos + Rua Castilho, número 165, 5º andar + Lisboa 1070-050 + PT + +24-93-CA (hex) Voxtronic Austria +2493CA (base 16) Voxtronic Austria + Modecenterstrasse 17 Objekt 1 + Vienna 1110 + AT + +0C-CB-8D (hex) ASCO Numatics GmbH +0CCB8D (base 16) ASCO Numatics GmbH + Otto-Hahn-Str. 7-11 + Oelbronn-Duerrn 75248 + DE + +90-79-90 (hex) Benchmark Electronics Romania SRL +907990 (base 16) Benchmark Electronics Romania SRL + Aeroportului no 6 Ghimbav + Brasov 507075 + US + +74-0E-DB (hex) Optowiz Co., Ltd +740EDB (base 16) Optowiz Co., Ltd + D-901 Bundang Techno Park + Seongnam-si Kyeonggi-do 463-760 + KR + +6C-83-66 (hex) Nanjing SAC Power Grid Automation Co., Ltd. +6C8366 (base 16) Nanjing SAC Power Grid Automation Co., Ltd. + No.11 Phoenix Road + Nanjing Jiangsu Provience 211100 + CN + +F8-3D-4E (hex) Softlink Automation System Co., Ltd +F83D4E (base 16) Softlink Automation System Co., Ltd + No.12, Hi-tech South 7th Rd., + Shenzhen GuangDong 518057 + CN + +74-D4-35 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +74D435 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + Pin-Jen City, Taoyuan, Taiwan, R.O.C. + Pin-Jen Taoyuan 324 + TW + +78-D9-9F (hex) NuCom HK Ltd. +78D99F (base 16) NuCom HK Ltd. + Unit B 11/F, Eton Bldg, 288 Des Voeux Rd. Central + Hong Kong Hong Kong 00852 + CN + +14-2B-D2 (hex) Armtel Ltd. +142BD2 (base 16) Armtel Ltd. + 33A Smolenskaya str. + St. Petersburg 196084 + RU + +9C-A1-0A (hex) SCLE SFE +9CA10A (base 16) SCLE SFE + Parc des Aygalades – Bât 10 + MARSEILLE PACA 13014 + FR + +88-78-9C (hex) Game Technologies SA +88789C (base 16) Game Technologies SA + Plac W. Andersa 3 + Poznan 61894 + PL + +A4-89-5B (hex) ARK INFOSOLUTIONS PVT LTD +A4895B (base 16) ARK INFOSOLUTIONS PVT LTD + 4428, GANESH BAZAR CLOTH MARKET + DELHI 110006 + IN + +D0-9D-0A (hex) LINKCOM +D09D0A (base 16) LINKCOM + 11 Rue du Soleil Levant + Clamart 92140 + FR + +EC-21-9F (hex) VidaBox LLC +EC219F (base 16) VidaBox LLC + 240 Madison Ave + Garden City Park NEW YORK 11040 + US + +A8-CC-C5 (hex) Saab AB (publ) +A8CCC5 (base 16) Saab AB (publ) + Nobymalmsvagen + Linkoping SE-581 82 + SE + +58-46-8F (hex) Koncar Electronics and Informatics +58468F (base 16) Koncar Electronics and Informatics + Fallerovo setaliste 22 + Zagreb Drvinje 10000 + HR + +98-5D-46 (hex) PeopleNet Communication +985D46 (base 16) PeopleNet Communication + 4400 Baker Road + Minnetonka Minnesota 55343 + US + +F8-9F-B8 (hex) YAZAKI Energy System Corporation +F89FB8 (base 16) YAZAKI Energy System Corporation + 1-7-1 YOKOI + Shimada -shi,Shizuoka 427-8555 + JP + +F0-F5-AE (hex) Adaptrum Inc. +F0F5AE (base 16) Adaptrum Inc. + 25 E Trimble Rd. + San Jose California 95131 + US + +FC-3F-AB (hex) Henan Lanxin Technology Co., Ltd +FC3FAB (base 16) Henan Lanxin Technology Co., Ltd + 4/F-B, Building No.1, 863 Central China Software Park, No.6 Cuizhu Street, High & New Technology Industries Development Zone + Zhengzhou Henan 450001 + CN + +98-8E-4A (hex) NOXUS(BEIJING) TECHNOLOGY CO.,LTD +988E4A (base 16) NOXUS(BEIJING) TECHNOLOGY CO.,LTD + 02-1205,11/F, No.2 Building,No.8,Worker’s Stadium North Road Chaoyang District + Beijing 100027 + CN + +EC-2A-F0 (hex) Ypsomed AG +EC2AF0 (base 16) Ypsomed AG + Brunnmattstrasse 6 + Burgdorf BE 3400 + CH + +F8-54-AF (hex) ECI Telecom Ltd. +F854AF (base 16) ECI Telecom Ltd. + 30 Hasivim St. + Petah Tikva 49133 + IL + +54-BE-F7 (hex) PEGATRON CORPORATION +54BEF7 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +50-B8-88 (hex) wi2be Tecnologia S/A +50B888 (base 16) wi2be Tecnologia S/A + Rua Manoel Valdomiro de Macedo, 2285 + Curitiba Parana 81170-150 + BR + +7C-83-06 (hex) Glen Dimplex Nordic as +7C8306 (base 16) Glen Dimplex Nordic as + Postboks 16 + Stjoerdal N-T 7501 + NO + +44-2A-FF (hex) E3 Technology, Inc. +442AFF (base 16) E3 Technology, Inc. + Martell-house 2F, 2-28-3 Sekimachi-Kita, + Nerima-ku Tokyo 177-0051 + JP + +14-0D-4F (hex) Flextronics International +140D4F (base 16) Flextronics International + Stretton Green Distribution Centre Langford Way + Warrington Cheshire WA4 4TQ + GB + +44-67-55 (hex) Orbit Irrigation +446755 (base 16) Orbit Irrigation + P.O. Box 328 + Bountiful Utah 84011 + US + +E0-FA-EC (hex) Platan sp. z o.o. sp. k. +E0FAEC (base 16) Platan sp. z o.o. sp. k. + ul.Platanowa 2 + Sopot pomorskie 81-855 + PL + +7C-E5-6B (hex) ESEN Optoelectronics Technology Co.,Ltd. +7CE56B (base 16) ESEN Optoelectronics Technology Co.,Ltd. + Houcheng Yuanjiaqiao ,Jingang Town + Zhangjiagang Jiangsu 215631 + CN + +D4-4C-9C (hex) Shenzhen YOOBAO Technology Co.Ltd +D44C9C (base 16) Shenzhen YOOBAO Technology Co.Ltd + F3,A5,Hua Tong Yuan Logistics Center,Minzhi Street,Longhua Town,Bao’an District,Shenzhen City,China + Shenzhen Guangdong 518000 + CN + +20-CE-C4 (hex) Peraso Technologies +20CEC4 (base 16) Peraso Technologies + 144 Front St. West, Suite 685 + Toronto ON M5J 2L7 + CA + +CC-47-03 (hex) Intercon Systems Co., Ltd. +CC4703 (base 16) Intercon Systems Co., Ltd. + #915 Hanlim Human Tower,1-40 Geumjeong-dong + Gunpo-si Gyeonggi-do 435-824 + KR + +AC-CA-8E (hex) ODA Technologies +ACCA8E (base 16) ODA Technologies + 607-A Woorim Lions Valley, #425 + Incheon KSXX0009 + KR + +08-8E-4F (hex) SF Software Solutions +088E4F (base 16) SF Software Solutions + Buchenweg 32 + Großbettlingen Baden-Württemberg 72663 + US + +54-05-36 (hex) Vivago Oy +540536 (base 16) Vivago Oy + Itsehallintokuja 6 + Espoo FI-02600 + FI + +6C-90-B1 (hex) SanLogic Inc +6C90B1 (base 16) SanLogic Inc + 2350 Mission College Blvd + Santa Clara CA 95054 + US + +CC-7B-35 (hex) zte corporation +CC7B35 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +04-D4-37 (hex) ZNV +04D437 (base 16) ZNV + 4/F, W1-A, Bldg, Gaoxin S, 1st Ave., Hi-tech Park, Nanshan District, Shenzhen, P.R.C + Shenzhen Guangdong 518057 + US + +CC-F4-07 (hex) EUKREA ELECTROMATIQUE SARL +CCF407 (base 16) EUKREA ELECTROMATIQUE SARL + 74 AVENUE JEAN JAURES + PESSAC GIRONDE 33600 + FR + +DC-17-92 (hex) Captivate Network +DC1792 (base 16) Captivate Network + 2 Executive Drive Suite 301 + Chelmsford Massachusetts 01824 + US + +28-A2-41 (hex) exlar corp +28A241 (base 16) exlar corp + 18400 west 77th street + chanhassen mn 55317 + US + +50-98-71 (hex) Inventum Technologies Private Limited +509871 (base 16) Inventum Technologies Private Limited + C-70, Phase 2 Extension + NOIDA Uttar Pradesh 201305 + IN + +04-8C-03 (hex) ThinPAD Technology (Shenzhen)CO.,LTD +048C03 (base 16) ThinPAD Technology (Shenzhen)CO.,LTD + Room 2305, Xingji Building, Xinsha Road + Shenzhen Guangdong 518104 + CN + +88-46-2A (hex) Telechips Inc. +88462A (base 16) Telechips Inc. + Luther Building,7-20, Sincheon-dong,Songpa-gu, + Seoul Seoul 138-240 + KR + +C8-02-58 (hex) ITW GSE ApS +C80258 (base 16) ITW GSE ApS + Smedebakken 31-33 + Odense N 5270 + DK + +30-78-6B (hex) TIANJIN Golden Pentagon Electronics Co., Ltd. +30786B (base 16) TIANJIN Golden Pentagon Electronics Co., Ltd. + No. 196 Rixin Road, Binhai Science Park, + Tianjin 300457 + CN + +20-DF-3F (hex) Nanjing SAC Power Grid Automation Co., Ltd. +20DF3F (base 16) Nanjing SAC Power Grid Automation Co., Ltd. + No.11 Phoenix Road + Nanjing Jiangsu 211106 + CN + +F8-51-6D (hex) Denwa Technology Corp. +F8516D (base 16) Denwa Technology Corp. + 1931 NW 150 TH AVE + Penbroke Pines Florida 33028 + US + +44-4A-65 (hex) Silverflare Ltd. +444A65 (base 16) Silverflare Ltd. + 2 Bakers Yard + Uxbridge Greater London UB8 1JZ + GB + +74-4B-E9 (hex) EXPLORER HYPERTECH CO.,LTD +744BE9 (base 16) EXPLORER HYPERTECH CO.,LTD + 7F.-9,NO.112,Xinmin St + New Taipei City 235 + TW + +FC-60-18 (hex) Zhejiang Kangtai Electric Co., Ltd. +FC6018 (base 16) Zhejiang Kangtai Electric Co., Ltd. + No.5, Kangtai Rd + Yueqing Zhejiang 325605 + CN + +F4-20-12 (hex) Cuciniale GmbH +F42012 (base 16) Cuciniale GmbH + Heuriedweg 65 + Lindau 88131 + DE + +98-B0-39 (hex) Nokia +98B039 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +B8-30-A8 (hex) Road-Track Telematics Development +B830A8 (base 16) Road-Track Telematics Development + 15th Keren Hayesod St. + Tirat Hacarmel Israel 15223 + IL + +4C-D6-37 (hex) Qsono Electronics Co., Ltd +4CD637 (base 16) Qsono Electronics Co., Ltd + 2nd Floor,Dingxin Industry park,jiayuan Road,East Lake Development Zone + Wuhan Hubei 430074 + CN + +94-36-E0 (hex) Sichuan Bihong Broadcast & Television New Technologies Co.,Ltd +9436E0 (base 16) Sichuan Bihong Broadcast & Television New Technologies Co.,Ltd + Guanghan City, Sichuan province Zhongshan road south three period of 36 + Deyang Guanghan Sichuan Province 618300 + CN + +54-22-F8 (hex) zte corporation +5422F8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +48-6E-73 (hex) Pica8, Inc. +486E73 (base 16) Pica8, Inc. + 1032 Elwell Court, Suite 105 + Palo Alto CA 94303 + US + +64-05-BE (hex) NEW LIGHT LED +6405BE (base 16) NEW LIGHT LED + No.50, Siyuan Rd + New Taipei 24251 + TW + +64-6E-EA (hex) Iskratel d.o.o. +646EEA (base 16) Iskratel d.o.o. + Ljubljanska cesta 24a + Kranj 4000 + SI + +D0-73-7F (hex) Mini-Circuits +D0737F (base 16) Mini-Circuits + 50 Yosef Levi Street + Kiryat Bialik Industrial Zone 27000 + US + +E8-BB-3D (hex) Sino Prime-Tech Limited +E8BB3D (base 16) Sino Prime-Tech Limited + Room 418, Building 1, Hua Mei Ju (D), + Shenzhen Guangdong 518101 + CN + +28-28-5D (hex) Zyxel Communications Corporation +28285D (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +0C-F0-19 (hex) Malgn Technology Co., Ltd. +0CF019 (base 16) Malgn Technology Co., Ltd. + Star Tower #305, 223-25 + Seongnam-Si Kyounggi-Do 462-738 + KR + +94-9F-B4 (hex) ChengDu JiaFaAnTai Technology Co.,Ltd +949FB4 (base 16) ChengDu JiaFaAnTai Technology Co.,Ltd + 8th Floor, Building No.2, Zone A of Wisdom Valley + Chengdu Sichuan 610000 + CN + +40-68-26 (hex) Thales UK Limited +406826 (base 16) Thales UK Limited + 1 Linthouse Road + Glasgow Scotland G51 4BZ + GB + +F8-2B-C8 (hex) Jiangsu Switter Co., Ltd +F82BC8 (base 16) Jiangsu Switter Co., Ltd + Room 512, Buliding 8, 118 Nanyuanbei Road + Suzhou City Jiangsu Province 215006 + CN + +60-C3-97 (hex) 2Wire Inc +60C397 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +E0-7F-88 (hex) EVIDENCE Network SIA +E07F88 (base 16) EVIDENCE Network SIA + Zilupes 4A + Rīga LV-1019 + LV + +1C-7C-C7 (hex) Coriant GmbH +1C7CC7 (base 16) Coriant GmbH + St.-Martin-Str. 76 + Munich Germany 81541 + DE + +34-1B-22 (hex) Grandbeing Technology Co., Ltd +341B22 (base 16) Grandbeing Technology Co., Ltd + B-301,Science and Technology Building Phase II + Shenzhen Guangdong 518000 + CN + +40-56-0C (hex) In Home Displays Ltd +40560C (base 16) In Home Displays Ltd + Waterside House + Edinburgh Lothian EH6 6QU + GB + +58-E0-2C (hex) Micro Technic A/S +58E02C (base 16) Micro Technic A/S + Smedevaenget 5 + Aarup 5560 + DK + +78-B3-CE (hex) Elo touch solutions +78B3CE (base 16) Elo touch solutions + 1033 McCarthy Boulevard + Milpitas CA 95035 + US + +88-14-2B (hex) Protonic Holland +88142B (base 16) Protonic Holland + Factorij 36 + Zwaag NH Netherlands 1689 AL + NL + +A4-FC-CE (hex) Security Expert Ltd. +A4FCCE (base 16) Security Expert Ltd. + 75, Ekaterininskaya Street, of. 105 + Perm Perm region 614000 + RU + +1C-08-C1 (hex) Lg Innotek +1C08C1 (base 16) Lg Innotek + 978-1 Jangduk dong, Gwangsangu + Gwangju Gwangju 506-731 + KR + +34-A6-8C (hex) Shine Profit Development Limited +34A68C (base 16) Shine Profit Development Limited + Unit 1401B Telecom Tower + Kwun Tong Kowloon 000001 + HK + +34-1A-4C (hex) SHENZHEN WEIBU ELECTRONICS CO.,LTD. +341A4C (base 16) SHENZHEN WEIBU ELECTRONICS CO.,LTD. + 3/F, Block 132,Jindi Industrial Zone + Shenzhen Guangdong 518048 + CN + +04-88-E2 (hex) Beats Electronics LLC +0488E2 (base 16) Beats Electronics LLC + 1601 Cloverfield Blvd. + Santa Monica California 90404 + US + +A4-7A-CF (hex) VIBICOM COMMUNICATIONS INC. +A47ACF (base 16) VIBICOM COMMUNICATIONS INC. + 900 CORPORATE DRIVE + MAHWAH NEW JERSEY 074030 + US + +BC-26-1D (hex) HONG KONG TECON TECHNOLOGY +BC261D (base 16) HONG KONG TECON TECHNOLOGY + ROOM 2802,BLOCK A,SHEN FANG OLAZA + Shenzhen Guangdong 518000 + CN + +E8-CE-06 (hex) SkyHawke Technologies, LLC. +E8CE06 (base 16) SkyHawke Technologies, LLC. + 274 Commerce Park Drive + Ridgeland MS 39157 + US + +C8-F3-86 (hex) Shenzhen Xiaoniao Technology Co.,Ltd +C8F386 (base 16) Shenzhen Xiaoniao Technology Co.,Ltd + Floor 13 C-D Yunsong Buliding + Futian District, Shenzhen Guangdong 518040 + CN + +E0-DC-A0 (hex) Siemens Industrial Automation Products Ltd Chengdu +E0DCA0 (base 16) Siemens Industrial Automation Products Ltd Chengdu + Tianyuan Road 99 + Cheng Du Si Chuan 611731 + CN + +84-2F-75 (hex) Innokas Group +842F75 (base 16) Innokas Group + Tarjusojantie 12 + Kempele Oulu 90440 + FI + +CC-3C-3F (hex) SA.S.S. Datentechnik AG +CC3C3F (base 16) SA.S.S. Datentechnik AG + Talhofstr. 32 + Gilching Bayern 82205 + DE + +2C-69-BA (hex) RF Controls, LLC +2C69BA (base 16) RF Controls, LLC + 622 Bates Street + Saint Louis Missouri 63111 + US + +D4-BF-7F (hex) UPVEL +D4BF7F (base 16) UPVEL + 13139 Ramona Blvd. #F + Irwindale CA 91706 + US + +2C-72-C3 (hex) Soundmatters +2C72C3 (base 16) Soundmatters + 8060 Double R Blvd Suite 100 + Reno NV 89511 + US + +C4-48-38 (hex) Satcom Direct, Inc. +C44838 (base 16) Satcom Direct, Inc. + 1901 Hwy A1A + Satellite Beach FL 32937 + US + +C8-DD-C9 (hex) Lenovo Mobile Communication Technology Ltd. +C8DDC9 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999,Qishan North 2nd Road, + Xiamen Fujian 361006 + US + +6C-86-86 (hex) Technonia +6C8686 (base 16) Technonia + #1101, Hanshin IT Tower 235 + Seoul 152-768 + KR + +D4-AC-4E (hex) BODi rS, LLC +D4AC4E (base 16) BODi rS, LLC + 7622 Rickenbacker Drive + Gaithersburg MD 20879 + US + +20-4C-6D (hex) Hugo Brennenstuhl Gmbh & Co. KG. +204C6D (base 16) Hugo Brennenstuhl Gmbh & Co. KG. + Seestr. 1-3 + Tuebingen Baden-Wuerttemberg 72074 + DE + +40-C4-D6 (hex) ChongQing Camyu Technology Development Co.,Ltd. +40C4D6 (base 16) ChongQing Camyu Technology Development Co.,Ltd. + 4th Floor,Tower of Venus Technology Building ,NO 60 Xing Guang Road + Chong Qing 401121 + CN + +A8-29-4C (hex) Precision Optical Transceivers, Inc. +A8294C (base 16) Precision Optical Transceivers, Inc. + 2328 Innovation Way + Rochester NY 14624 + US + +70-C6-AC (hex) Bosch Automotive Aftermarket +70C6AC (base 16) Bosch Automotive Aftermarket + Franz Oechsle Str. 4 + Plochingen D-73201 + DE + +7C-05-07 (hex) PEGATRON CORPORATION +7C0507 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +88-09-05 (hex) MTMCommunications +880905 (base 16) MTMCommunications + 2-3-10 Honmachi + Ichinomiya-shi Aichi-ken 491-0853 + US + +30-D4-6A (hex) Autosales Incorporated +30D46A (base 16) Autosales Incorporated + 1200 Souteat Avenue + Tallmadge Ohio 44278 + US + +28-2C-B2 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +282CB2 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +64-E5-99 (hex) EFM Networks +64E599 (base 16) EFM Networks + 6F, Benposra II 1197-1 Bojeong Giheung Gu + Yong In Kyunggi do 446913 + KR + +30-89-99 (hex) Guangdong East Power Co., +308999 (base 16) Guangdong East Power Co., + No.6 Northern Industry Road,Songshan lake SCI&TECH Industry Park + DongGuan GuangDong 523808 + CN + +C8-93-46 (hex) MXCHIP Company Limited +C89346 (base 16) MXCHIP Company Limited + Room 811,Tongpu Building, + Shanghai Shanghai 200333 + CN + +F4-B3-81 (hex) WindowMaster A/S +F4B381 (base 16) WindowMaster A/S + Skelstedet 13 + Vedbaek 2950 + DK + +74-F1-02 (hex) Beijing HCHCOM Technology Co., Ltd +74F102 (base 16) Beijing HCHCOM Technology Co., Ltd + Patton Building 8 floor,11# Wan liu zhong lu,Haidian District,Beijing,China + Beijing China 100089 + CN + +A0-86-1D (hex) Chengdu Fuhuaxin Technology co.,Ltd +A0861D (base 16) Chengdu Fuhuaxin Technology co.,Ltd + Room 1608,Building G1,No.1800 of Yizhou Ave + Chengdu Sichuan 610041 + CN + +50-8D-6F (hex) CHAHOO Limited +508D6F (base 16) CHAHOO Limited + B-4thFloor, 631 + Sungnam Gyeonggi 463-400 + KR + +E8-DE-27 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +E8DE27 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +94-AC-CA (hex) trivum technologies GmbH +94ACCA (base 16) trivum technologies GmbH + Heusteigstraße 37 + Stuttgart 70108 + DE + +9C-97-26 (hex) Technicolor +9C9726 (base 16) Technicolor + Prins Boudewijnlaan 47 + Edegem - Belgium B-2650 + BE + +90-82-60 (hex) IEEE 1904.1 Working Group +908260 (base 16) IEEE 1904.1 Working Group + 1351 Redwood Way, + Petaluma CA 94954 + US + +D4-EE-07 (hex) HIWIFI Co., Ltd. +D4EE07 (base 16) HIWIFI Co., Ltd. + Room 1002, Zhongguancun e-Plaza A, + Haidian District Beijing 100080 + CN + +FC-AD-0F (hex) QTS NETWORKS +FCAD0F (base 16) QTS NETWORKS + Jinyanlong Plaza, Huilongguan, + Beijing 100092 + CN + +98-4C-04 (hex) Zhangzhou Keneng Electrical Equipment Co Ltd +984C04 (base 16) Zhangzhou Keneng Electrical Equipment Co Ltd + Keneng Technology Park,No.12 Wuqiao Zhong Rd + Zhangzhou Fujian 363005 + CN + +A4-E9-91 (hex) SISTEMAS AUDIOVISUALES ITELSIS S.L. +A4E991 (base 16) SISTEMAS AUDIOVISUALES ITELSIS S.L. + POL.IND. DEL TAMBRE + SANTIAGO COMPOSTELA A CORUÑA 15890 + ES + +3C-86-A8 (hex) Sangshin elecom .co,, LTD +3C86A8 (base 16) Sangshin elecom .co,, LTD + 614-1 Wolhari Suhmyon + Choongnam 339-814 + KR + +84-F4-93 (hex) OMS spol. s.r.o. +84F493 (base 16) OMS spol. s.r.o. + Dojc 419 + Dojc Slovakia 90602 + SK + +BC-D1-77 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +BCD177 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +AC-DB-DA (hex) Shenzhen Geniatech Inc, Ltd +ACDBDA (base 16) Shenzhen Geniatech Inc, Ltd + 18th F, GDC Building,No.9 ,Gaoxin Central Avenue 3rd + Shenzhen GuangDong 518057 + CN + +D4-27-51 (hex) Infopia Co., Ltd +D42751 (base 16) Infopia Co., Ltd + 891, Hogye-dong, Dongan-gu + Anyang Gyeonggi 431-080 + KR + +10-3D-EA (hex) HFC Technology (Beijing) Ltd. Co. +103DEA (base 16) HFC Technology (Beijing) Ltd. Co. + Building #3, Room 1214 + Beijing AP (Area Pacific) 100193 + CN + +F0-5D-C8 (hex) Duracell Powermat +F05DC8 (base 16) Duracell Powermat + 230 Park Ave, suit 910 + new york NY 10169 + US + +CC-5D-57 (hex) Information System Research Institute,Inc. +CC5D57 (base 16) Information System Research Institute,Inc. + Metro city minamiikebukuro-bldg.5F + Toshima-ku Tokyo 171-0022 + JP + +64-C6-67 (hex) Barnes&Noble +64C667 (base 16) Barnes&Noble + 400 Hamilton Avenue + Palo Alto CA 94301 + US + +F0-F2-60 (hex) Mobitec AB +F0F260 (base 16) Mobitec AB + Box 97 + Herrljunga VG 52421 + SE + +04-4C-EF (hex) Fujian Sanao Technology Co.,Ltd +044CEF (base 16) Fujian Sanao Technology Co.,Ltd + Fuzhou shibei bicyclic road no. 117 + Fuzhou Fujian 350000 + CN + +4C-80-4F (hex) Armstrong Monitoring Corp +4C804F (base 16) Armstrong Monitoring Corp + 215 Colonnade Rd + Nepean Ontario K2E 7K3 + CA + +7C-D7-62 (hex) Freestyle Technology Pty Ltd +7CD762 (base 16) Freestyle Technology Pty Ltd + 1A 24 Ricketts Road + Mount Waverley Victoria 3149 + AU + +90-1D-27 (hex) zte corporation +901D27 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +9C-31-78 (hex) Foshan Huadian Intelligent Communications Teachnologies Co.,Ltd +9C3178 (base 16) Foshan Huadian Intelligent Communications Teachnologies Co.,Ltd + Building B,No.8 of Shishan Industrial Avenue + Foshan Guangdong 528225 + CN + +B0-C9-5B (hex) Beijing Symtech CO.,LTD +B0C95B (base 16) Beijing Symtech CO.,LTD + Technology Park Building 2-1,The Hung Fu Pioneer Park + Beijing 102209 + CN + +4C-CA-53 (hex) Skyera, Inc. +4CCA53 (base 16) Skyera, Inc. + 1704 Automation Pkwy + San Jose CA 95131 + US + +90-FF-79 (hex) Metro Ethernet Forum +90FF79 (base 16) Metro Ethernet Forum + 6033 W. Century Boulevard + Los Angeles California 90045 + US + +B0-14-08 (hex) LIGHTSPEED INTERNATIONAL CO. +B01408 (base 16) LIGHTSPEED INTERNATIONAL CO. + No.20, LANE 526 NIUPU East RD. + Hsinchu Not US/Canada 30091 + TW + +08-1D-FB (hex) Shanghai Mexon Communication Technology Co.,Ltd +081DFB (base 16) Shanghai Mexon Communication Technology Co.,Ltd + Floor4-5, Unit B, Building 5 ,Lane 128, Jiujing Road + Shanghai Shanghai 201615 + CN + +98-3F-9F (hex) China SSJ (Suzhou) Network Technology Inc. +983F9F (base 16) China SSJ (Suzhou) Network Technology Inc. + 399 Linquan St., Dongnan Building 411 + Suzhou Jiangsu 215123 + CN + +B8-38-CA (hex) Kyokko Tsushin System CO.,LTD +B838CA (base 16) Kyokko Tsushin System CO.,LTD + 2-25-7 sakado,Takatsu-ku + Kawasaki Kanagawa 213-0012 + JP + +C4-4E-AC (hex) Shenzhen Shiningworth Technology Co., Ltd. +C44EAC (base 16) Shenzhen Shiningworth Technology Co., Ltd. + Room 610, Block B, Huameiju Business Center, + Shenzhen Guangdong 518000 + CN + +A8-01-80 (hex) IMAGO Technologies GmbH +A80180 (base 16) IMAGO Technologies GmbH + Strassheimer Str. 45 + Friedberg Hessen 61169 + DE + +0C-55-21 (hex) Axiros GmbH +0C5521 (base 16) Axiros GmbH + Altlaufstrasse 34 + Munich Hoehenkirchen Bavaria 85635 + DE + +68-A4-0E (hex) BSH Hausgeräte GmbH +68A40E (base 16) BSH Hausgeräte GmbH + Im Gewerbepark B35 + Regensburg Bayern 93059 + DE + +F4-C6-D7 (hex) blackned GmbH +F4C6D7 (base 16) blackned GmbH + Am Hartholz 21 + Alling Bavaria 82239 + DE + +D4-CA-6E (hex) u-blox AG +D4CA6E (base 16) u-blox AG + Zuercherstrasse 68 + Thalwil 8800 + CH + +5C-43-D2 (hex) HAZEMEYER +5C43D2 (base 16) HAZEMEYER + ZI Route de Grugies + GAUCHY FRANCE 02430 + FR + +D8-09-C3 (hex) Cercacor Labs +D809C3 (base 16) Cercacor Labs + 189 Technology Dr + Irvine CA 92618 + US + +E0-C2-B7 (hex) Masimo Corporation +E0C2B7 (base 16) Masimo Corporation + 40 Parker + Irvine CA 92618 + US + +A0-19-17 (hex) Bertel S.p.a. +A01917 (base 16) Bertel S.p.a. + Frazione Rimale, Via Emilia Ovest 61 + Fidenza Parma 43036 + IT + +68-B8-D9 (hex) Act KDE, Inc. +68B8D9 (base 16) Act KDE, Inc. + 196-14, Bangi-dong, Songpa-gu + Seoul 138-834 + KR + +90-CC-24 (hex) Synaptics, Inc +90CC24 (base 16) Synaptics, Inc + 1251 McKay Drive + San Jose CA 95131-1709 + US + +2C-E8-71 (hex) Alert Metalguard ApS +2CE871 (base 16) Alert Metalguard ApS + Vester Voldgade 104, st, th + Copenhagen V 1552 + DK + +F8-7B-62 (hex) FASTWEL INTERNATIONAL CO., LTD. Taiwan Branch +F87B62 (base 16) FASTWEL INTERNATIONAL CO., LTD. Taiwan Branch + 6F., No.118, Ln. 235, Baociao Rd., Sindian City, Taipei County 231, Taiwan R.O.C. + Taipei 231 + TW + +40-27-0B (hex) Mobileeco Co., Ltd +40270B (base 16) Mobileeco Co., Ltd + #2126, IT Tower B, Keumkang Penterium Bldg, 810 + Anyang City Kyunggi-Do 431810 + KR + +74-FE-48 (hex) ADVANTECH CO., LTD. +74FE48 (base 16) ADVANTECH CO., LTD. + NO.1, Alley 20, Lane 26 + TAIPEI 231 + TW + +80-B9-5C (hex) ELFTECH Co., Ltd. +80B95C (base 16) ELFTECH Co., Ltd. + 174, Daehyeon Techno World 6F 609, + Uiwang-Si Gyeonggi-Do 437-753 + KR + +38-B5-BD (hex) E.G.O. Elektro-Ger +38B5BD (base 16) E.G.O. Elektro-Ger + Einkauf + Oberderdingen 75038 + DE + +20-91-8A (hex) PROFALUX +20918A (base 16) PROFALUX + 377 rue des Cypr + THYEZ Haute Savoie 74300 + FR + +E4-EE-FD (hex) MR&D Manufacturing +E4EEFD (base 16) MR&D Manufacturing + Viale dell'Unione Europea, 8 + Gallarate Varese 21013 + US + +10-5C-BF (hex) DuroByte Inc +105CBF (base 16) DuroByte Inc + 875 Foster Ave, Unit 101 + Windsor Ontario N8X4W3 + CA + +A4-6E-79 (hex) DFT System Co.Ltd +A46E79 (base 16) DFT System Co.Ltd + Room 6B XINHAOFANG Building + SHENZHEN GUANGDONG 518052 + CN + +C8-8A-83 (hex) Dongguan HuaHong Electronics Co.,Ltd +C88A83 (base 16) Dongguan HuaHong Electronics Co.,Ltd + NO.25,Xing Er Road,Chen Wu Industrial Zone,Wusha Village,Chang£§an Town + Dongguan City China/Guangdong 523858 + CN + +8C-C5-E1 (hex) ShenZhen Konka Telecommunication Technology Co.,Ltd +8CC5E1 (base 16) ShenZhen Konka Telecommunication Technology Co.,Ltd + No.9008 Shennan Road + ShenZhen GuangDong 518053 + CN + +64-A3-41 (hex) Wonderlan (Beijing) Technology Co., Ltd. +64A341 (base 16) Wonderlan (Beijing) Technology Co., Ltd. + Room 04D, Building D, KeShi Plaza + Haidian District Beijing 100085 + CN + +78-98-FD (hex) Q9 Networks Inc. +7898FD (base 16) Q9 Networks Inc. + Suite 4400, PO Box 235 + Toronto ON M5K 1J3 + CA + +D0-63-B4 (hex) SolidRun Ltd. +D063B4 (base 16) SolidRun Ltd. + P.O Box 50782 + Nazareth ISRAEL 16165 + IL + +9C-54-1C (hex) Shenzhen My-power Technology Co.,Ltd +9C541C (base 16) Shenzhen My-power Technology Co.,Ltd + 202¬Building 3¬Shenzhen Software Park + Shenzhen Nanshan 518000 + CN + +8C-33-30 (hex) EmFirst Co., Ltd. +8C3330 (base 16) EmFirst Co., Ltd. + 701 Suwon Venture Center + Suwon Gyeonggi-do 442-833 + KR + +08-7B-AA (hex) SVYAZKOMPLEKTSERVICE, LLC +087BAA (base 16) SVYAZKOMPLEKTSERVICE, LLC + Lenskaya 2-21 + Moscow 129327 + US + +24-F2-DD (hex) Radiant Zemax LLC +24F2DD (base 16) Radiant Zemax LLC + 22908 NE Alder Crest Dr NE Ste 100 + Redmond WA 98053 + US + +20-B5-C6 (hex) Mimosa Networks +20B5C6 (base 16) Mimosa Networks + 656 N. Santa Cruz. Ave., Suite B + Los Gatos CA 95030 + US + +E4-E4-09 (hex) LEIFHEIT AG +E4E409 (base 16) LEIFHEIT AG + Leifhheitstreet + Nassau Rheinland-Pfalz 56377 + DE + +B8-77-C3 (hex) METER Group +B877C3 (base 16) METER Group + 2365 NE Hopkins Court + Pullman WA 99163 + US + +00-4D-32 (hex) Andon Health Co.,Ltd. +004D32 (base 16) Andon Health Co.,Ltd. + NO.3Jin PIng Road Ya An Street + Tianjin 300190 + CN + +FC-A9-B0 (hex) MIARTECH (SHANGHAI),INC. +FCA9B0 (base 16) MIARTECH (SHANGHAI),INC. + 3F,Building 4,No 290 Zhangheng Road Zhangjiang Hi-Tech Park,Pudong New District Shanghai,P.R.China + SHANGHAI SHANGHAI 201204 + CN + +94-DE-80 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +94DE80 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + + Pin-Jen Taoyuan 324 + TW + +2C-44-1B (hex) Spectrum Medical Limited +2C441B (base 16) Spectrum Medical Limited + Harrier 4, Meteor Business Park + Gloucester GL2 9QL + US + +EC-49-93 (hex) Qihan Technology Co., Ltd +EC4993 (base 16) Qihan Technology Co., Ltd + 20th Floor,Times Technology BuildingNo.7028,Shennan Road,Futian, + Shenzhen Guangdong 518040 + CN + +B0-AC-FA (hex) FUJITSU LIMITED +B0ACFA (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +8C-E0-81 (hex) zte corporation +8CE081 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +58-65-E6 (hex) INFOMARK CO., LTD. +5865E6 (base 16) INFOMARK CO., LTD. + #801, KINS TOWER, JEONGJA-DONG + SEONGNAM GYOUNGGI 463-847 + KR + +A4-4E-2D (hex) Adaptive Wireless Solutions, LLC +A44E2D (base 16) Adaptive Wireless Solutions, LLC + 577 Main Street + Hudson MA 01749 + US + +0C-CD-FB (hex) EDIC Systems Inc. +0CCDFB (base 16) EDIC Systems Inc. + 1-3-7 Nakamachidai + Yokohama Kanagawa 224-0041 + JP + +9C-8D-1A (hex) INTEG process group inc +9C8D1A (base 16) INTEG process group inc + 2919 E Hardies Rd, First Floor + Gibsonia PA 15044 + US + +48-03-62 (hex) DESAY ELECTRONICS(HUIZHOU)CO.,LTD +480362 (base 16) DESAY ELECTRONICS(HUIZHOU)CO.,LTD + BuildingA,No.3 Desay Industrial Zone + Huizhou Guangdong 516029 + CN + +18-67-3F (hex) Hanover Displays Limited +18673F (base 16) Hanover Displays Limited + Unit 24 + Lewes East Sussex BN8 6JL + GB + +7C-0A-50 (hex) J-MEX Inc. +7C0A50 (base 16) J-MEX Inc. + B2, 3F, No.1, Li-Hsin 1st Road, + Hsinchu Taiwan 300 + TW + +50-11-EB (hex) SilverNet Ltd +5011EB (base 16) SilverNet Ltd + 16 Cocran Close + Milton Keynes Bucks MK8 0AJ + GB + +54-DF-63 (hex) Intrakey technologies GmbH +54DF63 (base 16) Intrakey technologies GmbH + Wiener Strasse 114-116 + Dresden Saxony 01219 + DE + +40-F2-E9 (hex) IBM +40F2E9 (base 16) IBM + 3039 E Cornwallis Rd + Research Triangle Park NC 27709 + US + +74-4D-79 (hex) Arrive Systems Inc. +744D79 (base 16) Arrive Systems Inc. + 1404 Franklin Street, # 350 + Oakland CA 94612 + US + +9C-04-73 (hex) Tecmobile (International) Ltd. +9C0473 (base 16) Tecmobile (International) Ltd. + Unit L, Braintree Industrial Estate, + HA4 0EJ + GB + +B4-DF-FA (hex) Litemax Electronics Inc. +B4DFFA (base 16) Litemax Electronics Inc. + 8F, No.137,Lane 235 + Shin-dian-Dist New Taipei 23145 + TW + +68-1C-A2 (hex) Rosewill Inc. +681CA2 (base 16) Rosewill Inc. + 17708 Rowland St., + City of Industry CA 91748 + US + +60-46-16 (hex) XIAMEN VANN INTELLIGENT CO., LTD +604616 (base 16) XIAMEN VANN INTELLIGENT CO., LTD + UNIT 101£¬NO.28 GUANRI RD., SOFTWARE PARK ¢ò + XIAMEN FUJIAN 361009 + CN + +E4-56-14 (hex) Suttle Apparatus +E45614 (base 16) Suttle Apparatus + 1001 East Highway 212 + Hector MN 55342 + US + +3C-83-B5 (hex) Advance Vision Electronics Co. Ltd. +3C83B5 (base 16) Advance Vision Electronics Co. Ltd. + 6F, No. 199, Lide St. Jhonghe Dist + New Taipei City, Jhonghe Dist 23556 + TW + +28-A1-92 (hex) GERP Solution +28A192 (base 16) GERP Solution + Rua Costa Aguiar, 1710 + São Paulo SP 04204002 + BR + +10-6F-EF (hex) Ad-Sol Nissin Corp +106FEF (base 16) Ad-Sol Nissin Corp + Rivage Shinagawa, 4-1-8 Kounan + Minato-ku Tokyo 108-0075 + JP + +6C-40-C6 (hex) Nimbus Data, Inc. +6C40C6 (base 16) Nimbus Data, Inc. + 5151 California Ave, Ste 100 + Irvine CA 92617 + US + +10-48-B1 (hex) Beijing Duokan Technology Limited +1048B1 (base 16) Beijing Duokan Technology Limited + Room 1105, Changxin Building, No.39 Anding Road + Chaoyang District Beijing 100029 + CN + +D4-93-A0 (hex) Fidelix Oy +D493A0 (base 16) Fidelix Oy + Martinkyläntie 41 + VANTAA International 01720 + FI + +08-EB-ED (hex) World Elite Technology Co.,LTD +08EBED (base 16) World Elite Technology Co.,LTD + 6/F Liyuan floor ,Dragon City North Road on the 3rd + ShenZhen GuangDong 518100 + CN + +DC-9F-A4 (hex) Nokia Corporation +DC9FA4 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +44-C3-9B (hex) OOO RUBEZH NPO +44C39B (base 16) OOO RUBEZH NPO + Pionerskaya 11a + Bratsk Irkutsk 665717 + RU + +C4-45-67 (hex) SAMBON PRECISON and ELECTRONICS +C44567 (base 16) SAMBON PRECISON and ELECTRONICS + 204, Samjeong-dong, Ojeong-gu + Bucheon-city Kyeonggi-do 421-810 + KR + +48-F8-B3 (hex) Cisco-Linksys, LLC +48F8B3 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +D8-D2-7C (hex) JEMA ENERGY, SA +D8D27C (base 16) JEMA ENERGY, SA + Pº Circuito nº10 + Lasarte-Oria Guipuzcoa 20160 + ES + +B0-12-03 (hex) Dynamics Hong Kong Limited +B01203 (base 16) Dynamics Hong Kong Limited + Room A4, 3/F, Friend's House , No.6A Carnarvon Road, + 999077 + HK + +98-86-B1 (hex) Flyaudio corporation (China) +9886B1 (base 16) Flyaudio corporation (China) + No.16 Mingzhu RD Economic&Technology + Guangzhou Guangdong Province 510730 + CN + +70-93-F8 (hex) Space Monkey, Inc. +7093F8 (base 16) Space Monkey, Inc. + 7707 south main street + Midvale Utah 84047 + US + +28-B3-AB (hex) Genmark Automation +28B3AB (base 16) Genmark Automation + 1201 Cadillac Ct + Milpitas CA 95035 + US + +C4-E7-BE (hex) SCSpro Co.,Ltd +C4E7BE (base 16) SCSpro Co.,Ltd + #1203, KCC welltz valley 470-8 + Seoul Korea 153-710 + KR + +58-87-4C (hex) LITE-ON CLEAN ENERGY TECHNOLOGY CORP. +58874C (base 16) LITE-ON CLEAN ENERGY TECHNOLOGY CORP. + 3F, 392, Ruey Kuang Road, Neihu, + Taipei 11492 + TW + +28-91-D0 (hex) Stage Tec Entwicklungsgesellschaft für professionelle Audiotechnik mbH +2891D0 (base 16) Stage Tec Entwicklungsgesellschaft für professionelle Audiotechnik mbH + Tabbertstraße 10 + Berlin 12459 + DE + +C0-BD-42 (hex) ZPA Smart Energy a.s. +C0BD42 (base 16) ZPA Smart Energy a.s. + Komenskeho 821 + Trutnov 54101 + CZ + +FC-52-CE (hex) Control iD +FC52CE (base 16) Control iD + Rua Hungria, 574 + São Paulo SP 01455-000 + BR + +5C-4A-26 (hex) Enguity Technology Corp +5C4A26 (base 16) Enguity Technology Corp + 2020 Pennsylvania Ave., NW + Washington DC 20006 + US + +60-F2-EF (hex) VisionVera International Co., Ltd. +60F2EF (base 16) VisionVera International Co., Ltd. + A1103 Gehua Building + Beijing 100007 + CN + +C0-3F-2A (hex) Biscotti, Inc. +C03F2A (base 16) Biscotti, Inc. + 5900 South Lake Forest Drive + McKinney TX 75070 + US + +38-1C-4A (hex) SIMCom Wireless Solutions Co.,Ltd. +381C4A (base 16) SIMCom Wireless Solutions Co.,Ltd. + Building A,SIM Technology Building,No.633,Jinzhong Road, + Shanghai 200335 + CN + +D8-C6-91 (hex) Hichan Technology Corp. +D8C691 (base 16) Hichan Technology Corp. + 12F., No.2, Jian 8th Rd., Zhonghe Dist + New Taipei City 23511 + TW + +E4-3F-A2 (hex) Wuxi DSP Technologies Inc. +E43FA2 (base 16) Wuxi DSP Technologies Inc. + Rm A801,530Mansion,International High-Tech Park,Qingyuan Road + Wuxi Jiangsu 214000 + US + +F4-B7-2A (hex) TIME INTERCONNECT LTD +F4B72A (base 16) TIME INTERCONNECT LTD + 6/F, Photonics Centre + + HK + +74-99-75 (hex) IBM Corporation +749975 (base 16) IBM Corporation + 4400 North First Street + San Jose CA 95134 + US + +2C-62-5A (hex) Finest Security Systems Co., Ltd +2C625A (base 16) Finest Security Systems Co., Ltd + 12F, No.103, Sec3, Nan King E. RD + Taipei 104 + US + +20-74-CF (hex) Shenzhen Voxtech Co.,Ltd +2074CF (base 16) Shenzhen Voxtech Co.,Ltd + 4/F East, Building 4, Minqi Science&Technology Park, Pingshan, + Shenzhen Guangdong 518055 + CN + +E0-F5-CA (hex) CHENG UEI PRECISION INDUSTRY CO.,LTD. +E0F5CA (base 16) CHENG UEI PRECISION INDUSTRY CO.,LTD. + No. 18, ZhongShan Rd., TuCheng Dist., + New Taipei City Taiwan 23680 + TW + +A8-EF-26 (hex) Tritonwave +A8EF26 (base 16) Tritonwave + 795 Lakeshore Dr, Suite 307 + Quebec H9S 0A8 + CA + +20-DC-93 (hex) Cheetah Hi-Tech, Inc. +20DC93 (base 16) Cheetah Hi-Tech, Inc. + Rm 804, No. 5, Sec. 2, Anhe Rd. + Taipei Taiwan 10680 + TW + +44-23-AA (hex) Farmage Co., Ltd. +4423AA (base 16) Farmage Co., Ltd. + 166-8 Kanazawa Toubetsu + Hokkaido 061-0212 + JP + +7C-FE-28 (hex) Salutron Inc. +7CFE28 (base 16) Salutron Inc. + 40979 Encyclopedia Circle + Fremont CA 94538 + US + +E8-10-2E (hex) Really Simple Software, Inc +E8102E (base 16) Really Simple Software, Inc + P.O. Box 1086 + Tiburon California 94920 + US + +0C-56-5C (hex) HyBroad Vision (Hong Kong) Technology Co Ltd +0C565C (base 16) HyBroad Vision (Hong Kong) Technology Co Ltd + Unit 1808 18/F Tower 3 Enterprise Square + Kowloon Bay + HK + +8C-6A-E4 (hex) Viogem Limited +8C6AE4 (base 16) Viogem Limited + Paddock House + Orlingbury Northamptonshire NN141JH + GB + +54-39-68 (hex) Edgewater Networks Inc +543968 (base 16) Edgewater Networks Inc + 2895 Northwestern Parkway + Santa Clara CA 95051 + US + +44-0C-FD (hex) NetMan Co., Ltd. +440CFD (base 16) NetMan Co., Ltd. + Rm 406, DIP, 2139, Daemyeong-dong, + Daegu 705-701 + KR + +8C-D3-A2 (hex) VisSim AS +8CD3A2 (base 16) VisSim AS + Vollveien 5 + Horten Vestfold 3183 + NO + +D8-2D-E1 (hex) Tricascade Inc. +D82DE1 (base 16) Tricascade Inc. + 5020 Campus Drv. + Newport Beach CA 92660 + US + +14-35-8B (hex) Mediabridge Products, LLC. +14358B (base 16) Mediabridge Products, LLC. + 1951 Old Cuthbert Rd + Cherry Hill New Jersey 08034 + US + +00-F4-03 (hex) Orbis Systems Oy +00F403 (base 16) Orbis Systems Oy + Taivaltie 5 + Vantaa 01610 + FI + +54-73-98 (hex) Toyo Electronics Corporation +547398 (base 16) Toyo Electronics Corporation + 1860-38, Simoakasaka + Kawagoe Saitama 3501155 + JP + +E0-A3-0F (hex) Pevco +E0A30F (base 16) Pevco + 1401 Tangier Drive + Baltimore MD 21220 + US + +88-DC-96 (hex) SENAO Networks, Inc. +88DC96 (base 16) SENAO Networks, Inc. + No. 500, Fusing 3rd Rd., Hwa-Ya Technology Park + Kuei-Shan Hsiang TaoYuan County 333 + TW + +20-44-3A (hex) Schneider Electric Asia Pacific Ltd +20443A (base 16) Schneider Electric Asia Pacific Ltd + 13F East Wing, Warwick House, Taikoo Place + Quarry Bay + HK + +C4-39-3A (hex) SMC Networks Inc +C4393A (base 16) SMC Networks Inc + 20 Mason + Irvine CA 92618 + US + +5C-24-79 (hex) Baltech AG +5C2479 (base 16) Baltech AG + Lilienthalstrasse 27 + Hallbergmoos 85399 + DE + +EC-93-27 (hex) MEMMERT GmbH + Co. KG +EC9327 (base 16) MEMMERT GmbH + Co. KG + Aeussere Rittersbacher Strasse 38 + Schwabach Bavaria 91126 + DE + +A0-EF-84 (hex) Seine Image Int'l Co., Ltd +A0EF84 (base 16) Seine Image Int'l Co., Ltd + 6F,4Building, NO.63,Mingz North Road + ZhuHai 519075 + CN + +64-51-7E (hex) LONG BEN (DONGGUAN) ELECTRONIC TECHNOLOGY CO.,LTD. +64517E (base 16) LONG BEN (DONGGUAN) ELECTRONIC TECHNOLOGY CO.,LTD. + NO.19.Jian she Road,Shi ma Village,Tang xia Town,Dong guan,Guang dong,China + Dong guan Guang dong 523731 + CN + +D4-3D-7E (hex) Micro-Star Int'l Co, Ltd +D43D7E (base 16) Micro-Star Int'l Co, Ltd + No.69, Lide St., Jhonghe City + Taipei County 235 + US + +AC-D9-D6 (hex) tci GmbH +ACD9D6 (base 16) tci GmbH + Ludwig-Rinn-Straße 10-14 + Heuchelheim Hessen 35452 + US + +48-28-2F (hex) zte corporation +48282F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +60-CB-FB (hex) AirScape Inc. +60CBFB (base 16) AirScape Inc. + 625 Charles Way + Medford OR 97501 + US + +7C-16-0D (hex) Saia-Burgess Controls AG +7C160D (base 16) Saia-Burgess Controls AG + Bahnhofstrasse 18 + Murten FR 3280 + CH + +A4-97-BB (hex) Hitachi Industrial Equipment Systems Co.,Ltd +A497BB (base 16) Hitachi Industrial Equipment Systems Co.,Ltd + 3, Kanda Neribei-cho + Chiyoda-ku Tokyo 101-0022 + US + +4C-54-27 (hex) Linepro Sp. z o.o. +4C5427 (base 16) Linepro Sp. z o.o. + ul. Miedziana 11 + Warszawa mazowieckie 00-835 + PL + +80-D1-8B (hex) Hangzhou I'converge Technology Co.,Ltd +80D18B (base 16) Hangzhou I'converge Technology Co.,Ltd + No.618 Xixi Road, + Hangzhou Zhejiang 310012 + CN + +40-88-E0 (hex) Beijing Ereneben Information Technology Limited Shenzhen Branch +4088E0 (base 16) Beijing Ereneben Information Technology Limited Shenzhen Branch + Room 14A, Building A, Honglong Central Plaza, No.3001,Heping Road, Luohu District, Shenzhen City + Shenzhen Guangdong 518001 + CN + +E8-54-84 (hex) NEO Information Systems Co., Ltd. +E85484 (base 16) NEO Information Systems Co., Ltd. + 609, Junganginduspia, #517-13, Sangdaeweon-Dong, Jungweon-Gu + Seongnam Gyunggi-Do 462-713 + KR + +74-AE-76 (hex) iNovo Broadband, Inc. +74AE76 (base 16) iNovo Broadband, Inc. + 3475 Corporate Way + Duluth Georgia 30096 + US + +EC-1A-59 (hex) Belkin International Inc. +EC1A59 (base 16) Belkin International Inc. + 12045 East Waterfront Drive + Playa Vista Ca. 90094 + US + +88-10-36 (hex) Panodic(ShenZhen) Electronics Limted +881036 (base 16) Panodic(ShenZhen) Electronics Limted + Floor 12, Grentech Building, Keji.C. Road + ShenZhen GuangDong 518052 + CN + +68-B6-FC (hex) Hitron Technologies. Inc +68B6FC (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +EC-A2-9B (hex) Kemppi Oy +ECA29B (base 16) Kemppi Oy + Kempinkatu 1 + Lahti Lahti 15810 + FI + +04-CE-14 (hex) Wilocity LTD. +04CE14 (base 16) Wilocity LTD. + 21 Bareket St. + Caesarea Israel 38900 + US + +C4-BA-99 (hex) I+ME Actia Informatik und Mikro-Elektronik GmbH +C4BA99 (base 16) I+ME Actia Informatik und Mikro-Elektronik GmbH + Dresdenstrasse 17/18 + Braunschweig Niedersachsen 38690 + DE + +A4-93-4C (hex) Cisco Systems, Inc +A4934C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D0-D2-12 (hex) K2NET Co.,Ltd. +D0D212 (base 16) K2NET Co.,Ltd. + K2Net Building + Seoul 158-092 + KR + +B0-43-5D (hex) NuLEDs, Inc. +B0435D (base 16) NuLEDs, Inc. + 1497 Poinsettia Ave. + Vista CA 92081 + US + +08-08-EA (hex) AMSC +0808EA (base 16) AMSC + 15775 W Schaefer Court + New Berlin WI 53151 + US + +E8-D4-83 (hex) ULTIMATE Europe Transportation Equipment GmbH +E8D483 (base 16) ULTIMATE Europe Transportation Equipment GmbH + Industriestraße 3 + 3300 Niederösterreich 3300 + AT + +1C-84-64 (hex) FORMOSA WIRELESS COMMUNICATION CORP. +1C8464 (base 16) FORMOSA WIRELESS COMMUNICATION CORP. + 11F., No.3-2, Yuanqu St., Nangang Dist., + Taipei City 115 + TW + +34-6E-8A (hex) Ecosense +346E8A (base 16) Ecosense + 1414 Kolon science vallet-II., #811 + Seoul Guro-gu 152-878 + KR + +64-F2-42 (hex) Gerdes Aktiengesellschaft +64F242 (base 16) Gerdes Aktiengesellschaft + Bergerwiesenstraße 9 + Meckenheim NRW 53340 + DE + +60-F2-81 (hex) TRANWO TECHNOLOGY CO., LTD. +60F281 (base 16) TRANWO TECHNOLOGY CO., LTD. + No.236, Sec.3, Huanbei Rd. + Jubei City Hsinchu County 30265 + TW + +94-21-97 (hex) Stalmart Technology Limited +942197 (base 16) Stalmart Technology Limited + Rm1106-1107E, Building F, Xihaimingzhu, No.1, Taoyuan Road + Shenzhen Gunagdong 518052 + CN + +A0-C3-DE (hex) Triton Electronic Systems Ltd. +A0C3DE (base 16) Triton Electronic Systems Ltd. + 620063, Ekaterinburg, P/O box 522 + Ekaterinburg Sverdlovskaya obl. 620063 + RU + +D0-69-9E (hex) LUMINEX Lighting Control Equipment +D0699E (base 16) LUMINEX Lighting Control Equipment + Berkenlaan 8 A + Hechtel - Eksel Limburg 3940 + BE + +0C-C0-C0 (hex) MAGNETI MARELLI SISTEMAS ELECTRONICOS MEXICO +0CC0C0 (base 16) MAGNETI MARELLI SISTEMAS ELECTRONICOS MEXICO + AV. INDUSTRIA 20/21 + TEPOTZOTLAN MEXICO 54600 + MX + +08-37-9C (hex) Topaz Co. LTD. +08379C (base 16) Topaz Co. LTD. + B305-22, Acrotower, 1591 Gwanyang-dong + Anyang-si Gyeonggi-Do 431-060 + KR + +D8-0D-E3 (hex) FXI TECHNOLOGIES AS +D80DE3 (base 16) FXI TECHNOLOGIES AS + Postboks 609 + TRONDHEIM Norge 7406 + NO + +B0-D2-F5 (hex) Vello Systems, Inc. +B0D2F5 (base 16) Vello Systems, Inc. + 1530 O'Brien Drive + Menlo Park California 94025 + US + +70-9A-0B (hex) Italian Institute of Technology +709A0B (base 16) Italian Institute of Technology + Via Morego 30 + Genova GE 16163 + IT + +F0-FD-A0 (hex) Acurix Networks Pty Ltd +F0FDA0 (base 16) Acurix Networks Pty Ltd + Unit 5, 348 Victoria Road, + Malaga, Perth Western Austraila 6090 + NZ + +B4-55-70 (hex) Borea +B45570 (base 16) Borea + Mlaka 1b + Begunje SI-4275 + SI + +10-0D-2F (hex) Online Security Pty. Ltd. +100D2F (base 16) Online Security Pty. Ltd. + 5/21-25 Redland Drive + Mitcham VIC 3132 + AU + +14-2D-F5 (hex) Amphitech +142DF5 (base 16) Amphitech + 1, rue Robert & Sonia DELAUNAY + Paris 75011 + FR + +50-57-A8 (hex) Cisco Systems, Inc +5057A8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-DE-FB (hex) Cisco Systems, Inc +00DEFB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +3C-A3-15 (hex) Bless Information & Communications Co., Ltd +3CA315 (base 16) Bless Information & Communications Co., Ltd + #64-1, Wonhyoro 3-ga, Yongsan-gu, + Seoul 140-848 + KR + +F8-30-94 (hex) Alcatel-Lucent Telecom Limited +F83094 (base 16) Alcatel-Lucent Telecom Limited + The Quadrant, Stonehill Green + SWINDON SN5 7DJ + GB + +10-A9-32 (hex) Beijing Cyber Cloud Technology Co. ,Ltd. +10A932 (base 16) Beijing Cyber Cloud Technology Co. ,Ltd. + 2/F, Tower B, Jingmeng High-tech Building. No. 5 Shangdi East Road, Haidian District. + Beijing 100085 + CN + +34-FC-6F (hex) ALCEA +34FC6F (base 16) ALCEA + 3 Rue Joly de Bammeville + 91460 Marcoussis + FR + +C0-B3-57 (hex) Yoshiki Electronics Industry Ltd. +C0B357 (base 16) Yoshiki Electronics Industry Ltd. + Ooicyoyo Building 7f + Shinagawa-ku Tokyo 140-0011 + JP + +3C-98-BF (hex) Quest Controls, Inc. +3C98BF (base 16) Quest Controls, Inc. + 208 9th Street Dr. West + Palmetto FL 34221 + US + +D0-AE-EC (hex) Alpha Networks Inc. +D0AEEC (base 16) Alpha Networks Inc. + No.8 Li-shing 7th Rd., Science-based Industrial Park, Hsinchu, Taiwan, R.O.C + Hsinchu Taiwan 300 + TW + +E8-13-24 (hex) GuangZhou Bonsoninfo System CO.,LTD +E81324 (base 16) GuangZhou Bonsoninfo System CO.,LTD + 4/F,NO.1029/31,GaoPu Road,GaoTang New Building District + Guangzhou Guangdong 510663 + CN + +E4-77-D4 (hex) Minrray Industry Co.,Ltd +E477D4 (base 16) Minrray Industry Co.,Ltd + C5, Building 2, ZhongHaiXin ,Science&Technology Park, Ganli Rd, LiLang Blvd., Buji + Shenzhen GuangDong 518112 + CN + +38-E0-8E (hex) Mitsubishi Electric Corporation +38E08E (base 16) Mitsubishi Electric Corporation + 2-7-3 Marunouchi Chiyoda-ku + Tokyo 100-8310 + JP + +E4-C8-06 (hex) Ceiec Electric Technology Inc. +E4C806 (base 16) Ceiec Electric Technology Inc. + 8/F West Side, Building 201, Terra Industrial & Tradepark, Che Gong Miao, + Shenzhen Guangdong 518040 + CN + +E0-F9-BE (hex) Cloudena Corp. +E0F9BE (base 16) Cloudena Corp. + 6F., No. 5, Alley 22, Lane 513 + Taipei City 114 + TW + +B8-8F-14 (hex) Analytica GmbH +B88F14 (base 16) Analytica GmbH + Vorholzstraße 36 + Karlsruhe Baden-Württemberg 76137 + DE + +7C-94-B2 (hex) Philips Healthcare PCCI +7C94B2 (base 16) Philips Healthcare PCCI + 2271 Cosmos Ct + Carlsbad CA 92011 + US + +44-2B-03 (hex) Cisco Systems, Inc +442B03 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F4-73-CA (hex) Conversion Sound Inc. +F473CA (base 16) Conversion Sound Inc. + 960 N. Northwest Hwy + Park Ridge IL 60068 + US + +F8-F7-FF (hex) SYN-TECH SYSTEMS INC +F8F7FF (base 16) SYN-TECH SYSTEMS INC + 100 FOUR POINTS WAY + TALLAHASSEE FL 32305 + US + +A8-17-58 (hex) Elektronik System i Umeå AB +A81758 (base 16) Elektronik System i Umeå AB + Box 7978 + Umeå Västerbotten 907 19 + SE + +88-20-12 (hex) LMI Technologies +882012 (base 16) LMI Technologies + 1673 Cliveden Avenue + Delta British Columbia V3M 6V5 + CA + +60-E9-56 (hex) Ayla Networks, Inc +60E956 (base 16) Ayla Networks, Inc + 218 Morgan Lane + Menlo Park CA 94025 + US + +EC-11-20 (hex) FloDesign Wind Turbine Corporation +EC1120 (base 16) FloDesign Wind Turbine Corporation + Papirfabrikken 28 + Silkeborg 8600 + DK + +F8-97-CF (hex) DAESHIN-INFORMATION TECHNOLOGY CO., LTD. +F897CF (base 16) DAESHIN-INFORMATION TECHNOLOGY CO., LTD. + 6F, Chungwon Bldg., 828-5 Yuksam-Dong,Kangnam-Gu, + Seoul 135935 + KR + +08-B4-CF (hex) Abicom International +08B4CF (base 16) Abicom International + The Old Grammar School + Market Drayton Shropshire TF9 1JR + GB + +C4-95-A2 (hex) SHENZHEN WEIJIU INDUSTRY AND TRADE DEVELOPMENT CO., LTD +C495A2 (base 16) SHENZHEN WEIJIU INDUSTRY AND TRADE DEVELOPMENT CO., LTD + ROOM 1713,BAOHUA BUILDING, HUAQIANG NORTH ROAD, FUTIAN DISTRICT, + SHENZHEN GUANGDONG 518031 + CN + +8C-68-78 (hex) Nortek-AS +8C6878 (base 16) Nortek-AS + Vangkroken 2 + Akreshus 1351 RUD + NO + +20-25-98 (hex) Teleview +202598 (base 16) Teleview + #401 Sehwa, 355-1 + Sungnam Gyeonggi 463-828 + KR + +38-F8-B7 (hex) V2COM PARTICIPACOES S.A. +38F8B7 (base 16) V2COM PARTICIPACOES S.A. + Rua Cunha Gago, 700 + São Paulo 05421001 + BR + +F8-D4-62 (hex) Pumatronix Equipamentos Eletronicos Ltda. +F8D462 (base 16) Pumatronix Equipamentos Eletronicos Ltda. + Rua Bartolomeu Lourenco de Gusmao 2021 + Curitiba PR 81650050 + BR + +A0-DC-04 (hex) Becker-Antriebe GmbH +A0DC04 (base 16) Becker-Antriebe GmbH + Friedrich-Ebert-Straße 2 - 4 + 35764 Sinn Hessen DE811177977 + DE + +40-60-5A (hex) Hawkeye Tech Co. Ltd +40605A (base 16) Hawkeye Tech Co. Ltd + 13F-5, No. 736 Chung Cheng Road, Chung He + New Taipei 23511 + TW + +A0-4C-C1 (hex) Helixtech Corp. +A04CC1 (base 16) Helixtech Corp. + 6F Lions bldg., 160-2 Gangnam-daero, + Seoul 137-888 + KR + +34-A7-BA (hex) Fischer International Systems Corporation +34A7BA (base 16) Fischer International Systems Corporation + 5801 Pelican Bay Boulevard #300 + Naples Florida 34108 + US + +04-63-E0 (hex) Nome Oy +0463E0 (base 16) Nome Oy + Lunkintie 9 + Oulunsalo Oulun lللni 90460 + FI + +B4-9E-E6 (hex) SHENZHEN TECHNOLOGY CO LTD +B49EE6 (base 16) SHENZHEN TECHNOLOGY CO LTD + NO34 SHILONG RD + SHENZHEN GUANGDONG 91732 + CN + +BC-4B-79 (hex) SensingTek +BC4B79 (base 16) SensingTek + 2F, No.6-2,Dusing Rd.,Hsinchu Science Park, + Hsinchu 30078 + TW + +A4-90-05 (hex) CHINA GREATWALL COMPUTER SHENZHEN CO.,LTD +A49005 (base 16) CHINA GREATWALL COMPUTER SHENZHEN CO.,LTD + 409,2#,Greatwall Bldg,No.3 Kefa Road,Science & Industry Park,Nanshan District, + Shenzhen Guangdong 51807 + CN + +C4-0A-CB (hex) Cisco Systems, Inc +C40ACB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E8-6D-6E (hex) voestalpine SIGNALING Fareham Ltd. +E86D6E (base 16) voestalpine SIGNALING Fareham Ltd. + Unit 1, Fulcrum 4, Solent Way + Whiteley Hampshire PO15 7FT + GB + +68-16-05 (hex) Systems And Electronic Development FZCO +681605 (base 16) Systems And Electronic Development FZCO + Roundabout no. 8 + Jebel Ali free Zone Dubai P.O.Box 61129 + AE + +D4-A0-2A (hex) Cisco Systems, Inc +D4A02A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +3C-4E-47 (hex) Etronic A/S +3C4E47 (base 16) Etronic A/S + Rødeledsvej 95 + Svendborg South Denmark 5700 + DK + +F4-87-71 (hex) Infoblox +F48771 (base 16) Infoblox + 4750 Patrick Henry Drive + Santa Clara California 95054 + US + +54-53-ED (hex) Sony Corporation +5453ED (base 16) Sony Corporation + Gotenyama Tec 5-1-2 + Tokyo Shinagawa-ku 141-0001 + JP + +00-37-6D (hex) Murata Manufacturing Co., Ltd. +00376D (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +50-00-8C (hex) Hong Kong Telecommunications (HKT) Limited +50008C (base 16) Hong Kong Telecommunications (HKT) Limited + 41/F, PCCW Tower, Taikoo Place, + + HK + +90-2B-34 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +902B34 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + Pin-Jen City, + Pin-Jen Taoyuan 324 + TW + +88-C3-6E (hex) Beijing Ereneben lnformation Technology Limited +88C36E (base 16) Beijing Ereneben lnformation Technology Limited + Room 14F,Building F,Honglong Central Plaza,NO,3001,Heping Road,LuoHu + ShenZhen GuangDong 518110 + CN + +4C-9E-80 (hex) KYOKKO ELECTRIC Co., Ltd. +4C9E80 (base 16) KYOKKO ELECTRIC Co., Ltd. + 5-7-20, Motomachi-dori, Chuo-Ku + Kobe Hyogo 6500022 + JP + +5C-EB-4E (hex) R. STAHL HMI Systems GmbH +5CEB4E (base 16) R. STAHL HMI Systems GmbH + Im Gewerbegebiet Pesch 14 + Cologne 50767 + DE + +34-AA-99 (hex) Nokia +34AA99 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +64-55-63 (hex) Intelight Inc. +645563 (base 16) Intelight Inc. + 3450 S Broadmont Drive #126 + Tucson Arizona 85713 + US + +94-3A-F0 (hex) Nokia Corporation +943AF0 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +64-54-22 (hex) Equinox Payments +645422 (base 16) Equinox Payments + 8888 E. Raintree Dr., Suite 300 + Scottsdale Arizona 85260 + US + +08-0D-84 (hex) GECO, Inc. +080D84 (base 16) GECO, Inc. + 1754 N. 48th St. + Mesa AZ 85205 + US + +88-E7-12 (hex) Whirlpool Corporation +88E712 (base 16) Whirlpool Corporation + 750 Monte Dr. + Benton Harbor Michigan 49022 + US + +D4-12-BB (hex) Quadrant Components Inc. Ltd +D412BB (base 16) Quadrant Components Inc. Ltd + Unit 5, 17/F, Metro Loft, + Kwai Chung, New Territory + HK + +24-B8-8C (hex) Crenus Co.,Ltd. +24B88C (base 16) Crenus Co.,Ltd. + Mario Tower 814, 222-12 + Seoul 152-050 + KR + +BC-FE-8C (hex) Altronic, LLC +BCFE8C (base 16) Altronic, LLC + 712 Trumbull Ave + Girard Ohio 44420 + US + +64-9E-F3 (hex) Cisco Systems, Inc +649EF3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +24-BB-C1 (hex) Absolute Analysis +24BBC1 (base 16) Absolute Analysis + 2393 Teller Road Ste #109 + Newbury Park California 91320 + US + +9C-CA-D9 (hex) Nokia Corporation +9CCAD9 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +04-6D-42 (hex) Bryston Ltd. +046D42 (base 16) Bryston Ltd. + P.O. Box 2170 + Peterborough Ontario K9J 7Y4 + CA + +D8-E7-43 (hex) Wush, Inc +D8E743 (base 16) Wush, Inc + 17F.No 268, Liancheng Rd., Zhonghe District + New Taipei City 235 + TW + +64-4D-70 (hex) dSPACE GmbH +644D70 (base 16) dSPACE GmbH + Rathenaustraße 26 + Paderborn 33102 + DE + +DC-C1-01 (hex) SOLiD Technologies, Inc. +DCC101 (base 16) SOLiD Technologies, Inc. + 9th Floor, SOLiD Space, Pangyoyeok-ro 220 + Seongnam-si Gyeonggi-do 463-400 + KR + +3C-E6-24 (hex) LG Display +3CE624 (base 16) LG Display + 9th, Fl., LG U+ building, 65-228, Hangangro, 3-ga, Yongsan-gu + Seoul 140-716 + KR + +D8-F0-F2 (hex) Zeebo Inc +D8F0F2 (base 16) Zeebo Inc + 5405 Morehouse Drive + San Diego California 92121 + US + +80-60-07 (hex) RIM +806007 (base 16) RIM + Phillip Street + Waterloo Ontario N2L 3W8 + CA + +38-A8-51 (hex) Moog, Ing +38A851 (base 16) Moog, Ing + 3650 Woodhead Drive + Northbrook IL 60062 + US + +94-E0-D0 (hex) HealthStream Taiwan Inc. +94E0D0 (base 16) HealthStream Taiwan Inc. + 16-3, Zichiang 1st Road + Jhongli, Taoyuan county 32063 + TW + +D8-05-2E (hex) Skyviia Corporation +D8052E (base 16) Skyviia Corporation + No. 10-1, Lixing 1st Rd., Science Park, + Hsinchu City 300 + TW + +80-94-6C (hex) TOKYO RADAR CORPORATION +80946C (base 16) TOKYO RADAR CORPORATION + 15-7 Nishikubo-cho + Hodogaya-ku, Yokohama-shi Kanagawa 240-0022 + JP + +D0-CF-5E (hex) Energy Micro AS +D0CF5E (base 16) Energy Micro AS + Sandakerveien 118 + Oslo N-0484 + NO + +18-03-FA (hex) IBT Interfaces +1803FA (base 16) IBT Interfaces + Im Taubhaus 19 + Roedermark Hessen 63322 + DE + +30-6E-5C (hex) Validus Technologies +306E5C (base 16) Validus Technologies + 420 North Main Street + East Peoria Illinois 61611 + US + +C8-94-D2 (hex) Jiangsu Datang Electronic Products Co., Ltd +C894D2 (base 16) Jiangsu Datang Electronic Products Co., Ltd + NO.20 + Nanjing Jiangsu 211800 + CN + +C8-A6-20 (hex) Nebula, Inc +C8A620 (base 16) Nebula, Inc + 215 Castro St + Mountain View CA 94041 + US + +EC-62-64 (hex) Global411 Internet Services, LLC +EC6264 (base 16) Global411 Internet Services, LLC + 10400 W Overland Rd #371 + Boise Idaho 83709 + US + +00-F0-51 (hex) KWB Gmbh +00F051 (base 16) KWB Gmbh + Industriestraße 235 + St. Margarethen Styria 8321 + AT + +FC-94-6C (hex) UBIVELOX +FC946C (base 16) UBIVELOX + #1301 KOLONG Digital Villent 222-7 Guro-dong Guro-gu + SEOUL 152-777 + KR + +40-7B-1B (hex) Mettle Networks Inc. +407B1B (base 16) Mettle Networks Inc. + 111 N. Market St STE 300 + San Jose CA 95113 + US + +40-D5-59 (hex) MICRO S.E.R.I. +40D559 (base 16) MICRO S.E.R.I. + 24, rue Henri FARMAN + TREMBLAY EN FRANCE Ile de France 93290 + FR + +30-6C-BE (hex) Skymotion Technology (HK) Limited +306CBE (base 16) Skymotion Technology (HK) Limited + Unit 2603, 26/F, Metropole Square, + 852 + HK + +18-38-25 (hex) Wuhan Lingjiu High-tech Co.,Ltd. +183825 (base 16) Wuhan Lingjiu High-tech Co.,Ltd. + No.718 + Wuhan Hubei 430074 + CN + +7C-4B-78 (hex) Red Sun Synthesis Pte Ltd +7C4B78 (base 16) Red Sun Synthesis Pte Ltd + 639, #11-544 + 510539 + SG + +64-A0-E7 (hex) Cisco Systems, Inc +64A0E7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +DC-F8-58 (hex) Lorent Networks, Inc. +DCF858 (base 16) Lorent Networks, Inc. + Third Floor, Technology Complex, HAO Science Park + Foshan Guangdong Province 528200 + CN + +94-0B-2D (hex) NetView Technologies(Shenzhen) Co., Ltd +940B2D (base 16) NetView Technologies(Shenzhen) Co., Ltd + RM2902,East Tower, Nanshan Software Park + Shenzhen Guangdong 518052 + CN + +80-3F-5D (hex) Winstars Technology Ltd +803F5D (base 16) Winstars Technology Ltd + Block4,Taisong Industrial Park, DaLang Street, LongHua Town , Bao'an District + Shenzhen Guangdong 518109 + CN + +40-BF-17 (hex) Digistar Telecom. SA +40BF17 (base 16) Digistar Telecom. SA + Av. Theodomiro Porto da Fonseca, 3101 + Sao Leopoldo RS 9302080 + BR + +78-07-38 (hex) Z.U.K. Elzab S.A. +780738 (base 16) Z.U.K. Elzab S.A. + ul. Kruczkowskiego 39 + Zabrze 41-813 + PL + +20-37-BC (hex) Kuipers Electronic Engineering BV +2037BC (base 16) Kuipers Electronic Engineering BV + Houtkopersstraat 6 + Zwijndrecht Zuid-Holland 3334 KD + NL + +94-31-9B (hex) Alphatronics BV +94319B (base 16) Alphatronics BV + Watergoorweg 71 + NIJKERK Gld 3861 MA + NL + +00-E1-75 (hex) AK-Systems Ltd +00E175 (base 16) AK-Systems Ltd + off 62, 27/29 Pavlovskaya str. + Moscow 115093 + RU + +CC-50-1C (hex) KVH Industries, Inc. +CC501C (base 16) KVH Industries, Inc. + 50 Enterprise Center + Middletown RI 02842-5279 + US + +04-D7-83 (hex) Y&H E&C Co.,LTD. +04D783 (base 16) Y&H E&C Co.,LTD. + 1501 Daerung Technotown 224-5 + Anyang-city Gyeonggi-do 431-062 + KR + +54-A9-D4 (hex) Minibar Systems +54A9D4 (base 16) Minibar Systems + 7340 Westmore Road + Rockville MD 20850 + US + +B0-E5-0E (hex) NRG SYSTEMS INC +B0E50E (base 16) NRG SYSTEMS INC + PO BOX 0509 + Hinesburg VT 054610509 + US + +64-80-8B (hex) VG Controls, Inc. +64808B (base 16) VG Controls, Inc. + 11 Butternut Drive + Vernon NJ 07462 + US + +48-C1-AC (hex) PLANTRONICS, INC. +48C1AC (base 16) PLANTRONICS, INC. + 345 ENCINAL STREET + SANTA CRUZ CA 95060 + US + +98-58-8A (hex) SYSGRATION Ltd. +98588A (base 16) SYSGRATION Ltd. + 10Fl.NO.868-3.Chung Cheng Rd. + NewTaipei City 235 + TW + +24-37-EF (hex) EMC Electronic Media Communication SA +2437EF (base 16) EMC Electronic Media Communication SA + Via Cantonale 4 + S. Antonino Ticino 6592 + CH + +28-B0-CC (hex) Xenya d.o.o. +28B0CC (base 16) Xenya d.o.o. + Celovska cesta 172 + Ljubljana 1000 + SI + +20-5B-5E (hex) Shenzhen Wonhe Technology Co., Ltd +205B5E (base 16) Shenzhen Wonhe Technology Co., Ltd + South Block 10th floor, Yuanxing Building, No. 1 + Shenzhen Guangdong 518057 + CN + +C0-58-A7 (hex) Pico Systems Co., Ltd. +C058A7 (base 16) Pico Systems Co., Ltd. + 332-7 Kouya + Matsudo Chiba pref. 270-0017 + JP + +EC-3F-05 (hex) Institute 706, The Second Academy China Aerospace Science & Industry Corp +EC3F05 (base 16) Institute 706, The Second Academy China Aerospace Science & Industry Corp + YongDing Road ,HaiDian District.BeiJing ,No.51 + BeiJing 100854 + CN + +48-9B-E2 (hex) SCI Innovations Ltd +489BE2 (base 16) SCI Innovations Ltd + 16C Hurst End + Newport Pagnell Buckinghamshire MK16 9HS + GB + +80-FF-A8 (hex) UNIDIS +80FFA8 (base 16) UNIDIS + 4 floors(401), 144-4, Gumi-dong + Sungnam-si Gyeonggi-do 463-810 + KR + +E4-35-FB (hex) Sabre Technology (Hull) Ltd +E435FB (base 16) Sabre Technology (Hull) Ltd + 3a Newlands Science Park + Hull East Yorkshire HU6 7TQ + GB + +C8-3B-45 (hex) JRI +C83B45 (base 16) JRI + 16 rue louis rameau + Bezons Cedex 95872 + FR + +E8-78-A1 (hex) BEOVIEW INTERCOM DOO +E878A1 (base 16) BEOVIEW INTERCOM DOO + TRESNJINOG CVETA 5/17 + BELGRADE 11070 + RS + +CC-EF-48 (hex) Cisco Systems, Inc +CCEF48 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F0-4B-6A (hex) Scientific Production Association Siberian Arsenal, Ltd. +F04B6A (base 16) Scientific Production Association Siberian Arsenal, Ltd. + Bld.8A, Gorskiy Microdistrict + Novosibirsk 630073 + RU + +64-AE-0C (hex) Cisco Systems, Inc +64AE0C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E8-DA-96 (hex) Zhuhai Tianrui Electrical Power Tech. Co., Ltd. +E8DA96 (base 16) Zhuhai Tianrui Electrical Power Tech. Co., Ltd. + Minying Technology Zone, 10# Keji 1 Road, Gangwan Main Road, Tangjia + Zhuhai Guangdong 519085 + CN + +B4-D8-DE (hex) iota Computing, Inc. +B4D8DE (base 16) iota Computing, Inc. + 2275 East Bayshore Road + Palo Alto CA 94303-3222 + US + +C8-90-3E (hex) Pakton Technologies +C8903E (base 16) Pakton Technologies + 1 Helium St + Narangba QLD 4504 + AU + +54-CD-A7 (hex) Fujian Shenzhou Electronic Co.,Ltd +54CDA7 (base 16) Fujian Shenzhou Electronic Co.,Ltd + Quanzhou Economical&Technological Development Zone,Quanzhou,Fujian,China + QUANZHOU FUJIAN 362005 + CN + +88-6B-76 (hex) CHINA HOPEFUL GROUP HOPEFUL ELECTRIC CO.,LTD +886B76 (base 16) CHINA HOPEFUL GROUP HOPEFUL ELECTRIC CO.,LTD + Shunde District of Foshan City, Guangdong Province, Guangxi Rong Ronggui Town Road, No. 148 + Foshan GuangDong 528305 + CN + +78-F7-D0 (hex) Silverbrook Research +78F7D0 (base 16) Silverbrook Research + 3 Montague Street + Balmain New South Wales 2041 + AU + +20-76-00 (hex) Actiontec Electronics, Inc +207600 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +F0-13-C3 (hex) SHENZHEN FENDA TECHNOLOGY CO., LTD +F013C3 (base 16) SHENZHEN FENDA TECHNOLOGY CO., LTD + Fenda Hi-Tech Park, Zhoushi Road, Shiyan, Baoan + ShenZhen GuangDong 518108 + CN + +04-A8-2A (hex) Nokia Corporation +04A82A (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +E4-4E-18 (hex) Gardasoft VisionLimited +E44E18 (base 16) Gardasoft VisionLimited + Units 1 and 2, Castle Acres + Cambridge CB23 4JQ + GB + +20-46-A1 (hex) VECOW Co., Ltd +2046A1 (base 16) VECOW Co., Ltd + 7F., No.105, Zhongcheng Rd., Tucheng Dist., + New Taipei City 23674 + TW + +FC-01-CD (hex) FUNDACION TEKNIKER +FC01CD (base 16) FUNDACION TEKNIKER + Avenida Otaola, 20 + Eibar Gipuzkoa 20600 + ES + +9C-8B-F1 (hex) The Warehouse Limited +9C8BF1 (base 16) The Warehouse Limited + Suite 601, City Point, 1600 Zhonghua Road, Huangpu District + Shanghai 200010 + CN + +DC-2E-6A (hex) HCT. Co., Ltd. +DC2E6A (base 16) HCT. Co., Ltd. + 105-1, Jangam-ri, Majang-myen + Icheon-si Gyeonggi-do 467-811 + KR + +14-8A-70 (hex) ADS GmbH +148A70 (base 16) ADS GmbH + Im Rohnweiher 39 + Lohmar Germany D-53797 + DE + +00-B3-38 (hex) Kontron Asia Pacific Design Sdn. Bhd +00B338 (base 16) Kontron Asia Pacific Design Sdn. Bhd + Plot 554, Lorong Perusahaan 4 + Prai Free Trade Zone Prai, Penang 13600 + MY + +84-24-8D (hex) Zebra Technologies Inc +84248D (base 16) Zebra Technologies Inc + 475 Half Day Road + Lincolnshire IL 60069 + US + +FC-E8-92 (hex) Hangzhou Lancable Technology Co.,Ltd +FCE892 (base 16) Hangzhou Lancable Technology Co.,Ltd + Zone A,Floor 16,Zhongcai Building,68#,Tonghe Road,Binjiang District, + Hangzhou Zhejiang 310051 + CN + +10-71-F9 (hex) Cloud Telecomputers, LLC +1071F9 (base 16) Cloud Telecomputers, LLC + 1032 Elwell Court + Palo Alto CA 94303 + US + +B8-62-1F (hex) Cisco Systems, Inc +B8621F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F0-02-2B (hex) Chrontel +F0022B (base 16) Chrontel + 2210 OToole Ave., Suite 100 + San Jose CA 95131 + US + +D4-53-AF (hex) VIGO System S.A. +D453AF (base 16) VIGO System S.A. + 129/133 Poznanska str + Ozarow Mazowiecki Mazowieckie 05-850 + PL + +18-AD-4D (hex) Polostar Technology Corporation +18AD4D (base 16) Polostar Technology Corporation + 2F, No.351, Yangguang St. + Taipei 11491 + TW + +94-C6-EB (hex) NOVA electronics, Inc. +94C6EB (base 16) NOVA electronics, Inc. + Grand Axe Bldg. 3F. + Shibuya-ku Tokyo 151-0064 + JP + +84-3F-4E (hex) Tri-Tech Manufacturing, Inc. +843F4E (base 16) Tri-Tech Manufacturing, Inc. + 333 Turbine Drive + Rapid City SD 57703 + US + +C8-32-32 (hex) Hunting Innova +C83232 (base 16) Hunting Innova + 8383 N Sam Houston Pkwy West + Houston Texas 77064 + US + +54-94-78 (hex) Silvershore Technology Partners +549478 (base 16) Silvershore Technology Partners + 800 High Street + Palo Alto CA 94301 + US + +A0-6E-50 (hex) Nanotek Elektronik Sistemler Ltd. Sti. +A06E50 (base 16) Nanotek Elektronik Sistemler Ltd. Sti. + Ivedik Organize Sanayi + Ankara 06370 + TR + +4C-77-4F (hex) Embedded Wireless Labs +4C774F (base 16) Embedded Wireless Labs + 702 Level 7 Uptown 2 No.2 + Petaling Jaya Selangor 47400 + MY + +D0-C2-82 (hex) Cisco Systems, Inc +D0C282 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +14-7D-B3 (hex) JOA TELECOM.CO.,LTD +147DB3 (base 16) JOA TELECOM.CO.,LTD + 1007,Sicox tower,513-14,Sangdaewon-dong,Jungwon-gu + Seongnam-si Gyeonggi-do 462-806 + KR + +EC-BD-09 (hex) FUSION Electronics Ltd +ECBD09 (base 16) FUSION Electronics Ltd + PO Box 137 - 142 + Auckland 1151 + NZ + +94-46-96 (hex) BaudTec Corporation +944696 (base 16) BaudTec Corporation + 12F, No.181, Sec.1.Tatung Rd. + Hsi-chih Taipei 221 + TW + +54-84-7B (hex) Digital Devices GmbH +54847B (base 16) Digital Devices GmbH + Moewestr 45 A + Muenchen 81827 + DE + +3C-27-63 (hex) SLE quality engineering GmbH & Co. KG +3C2763 (base 16) SLE quality engineering GmbH & Co. KG + Josef-Buchinger-Str. 9 + Grafenau Bavaria 94481 + DE + +B0-F1-BC (hex) Dhemax Ingenieros Ltda +B0F1BC (base 16) Dhemax Ingenieros Ltda + Siete Oriente 1234 + Vina del Mar Region de Valparaiso 2530954 + CL + +B8-28-8B (hex) Parker Hannifin Manufacturing (UK) Ltd +B8288B (base 16) Parker Hannifin Manufacturing (UK) Ltd + Condition Monitoring Centre + Thetford Norfolk IP24 1HP + GB + +90-D1-1B (hex) Palomar Medical Technologies +90D11B (base 16) Palomar Medical Technologies + 15 Network Drive + Burlington MA 01803 + US + +34-A5-5D (hex) TECHNOSOFT INTERNATIONAL SRL +34A55D (base 16) TECHNOSOFT INTERNATIONAL SRL + RO6640904 + Bucuresti - Sector 6 061992 + RO + +80-2E-14 (hex) azeti Networks AG +802E14 (base 16) azeti Networks AG + Am Brambusch 1a + Luenen NRW 44536 + DE + +D4-C1-FC (hex) Nokia Corporation +D4C1FC (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +34-BC-A6 (hex) Beijing Ding Qing Technology, Ltd. +34BCA6 (base 16) Beijing Ding Qing Technology, Ltd. + 218 Han Tai Hua Office Building, 13 Huan Yuan Lu, + Haidian District Beijing 100083 + CN + +58-35-D9 (hex) Cisco Systems, Inc +5835D9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +64-D9-12 (hex) Solidica, Inc. +64D912 (base 16) Solidica, Inc. + 5840 Interface Drive + Ann Arbor Michigan 48103 + US + +C4-7B-2F (hex) Beijing JoinHope Image Technology Ltd. +C47B2F (base 16) Beijing JoinHope Image Technology Ltd. + 624 Room .Automation Building.95# Zhong Guancun East Road.Haidian District + Beijing 100190 + CN + +50-8A-CB (hex) SHENZHEN MAXMADE TECHNOLOGY CO., LTD. +508ACB (base 16) SHENZHEN MAXMADE TECHNOLOGY CO., LTD. + Building 3,No.5 Fuqiao Industrial Estate, + Shenzhen Guangdong 518103 + CN + +3C-D1-6E (hex) Telepower Communication Co., Ltd +3CD16E (base 16) Telepower Communication Co., Ltd + 5/F,Zonghe Building, Hantian Technology Town,Guiping RD,Nanhai District,F + Foshan City Guangdong 528251 + CN + +FC-2E-2D (hex) Lorom Industrial Co.LTD. +FC2E2D (base 16) Lorom Industrial Co.LTD. + F1.13,Rm.2,No.78,Sec.2,An-HoRd. + Taipei 106 + TW + +40-04-0C (hex) A&T +40040C (base 16) A&T + #411, Will Town, 402-3 + Bucheon-Si Gyeonggi-Do 420-814 + KR + +DC-3C-84 (hex) Ticom Geomatics, Inc. +DC3C84 (base 16) Ticom Geomatics, Inc. + 9130 Jollyville Rd. Ste. 300 + Austin Texas 78759 + US + +D0-13-1E (hex) Sunrex Technology Corp +D0131E (base 16) Sunrex Technology Corp + No. 188-1,Chung Cheng Road.,Ta Ya Shiang + Taichung 428 + TW + +00-FC-70 (hex) Intrepid Control Systems, Inc. +00FC70 (base 16) Intrepid Control Systems, Inc. + 31601 Research Park Dr. + Madison Heights MI 48071 + US + +70-3A-D8 (hex) Shenzhen Afoundry Electronic Co., Ltd +703AD8 (base 16) Shenzhen Afoundry Electronic Co., Ltd + 201, A Building, Bole Industrial Zone, Bantian, Longgang District + Shenzhen Guangdong 518129 + CN + +70-4A-AE (hex) Xstream Flow (Pty) Ltd +704AAE (base 16) Xstream Flow (Pty) Ltd + Room 123, Building 16, CSIR campus + Pretoria Gauteng 0184 + ZA + +40-B3-FC (hex) Logital Co. Limited +40B3FC (base 16) Logital Co. Limited + Rm 901-902, 9/F, Nathan Centre, + Kowloon + HK + +A4-13-4E (hex) Luxul +A4134E (base 16) Luxul + 14203 Minuteman Drive + Draper UT 84020 + US + +B0-99-28 (hex) FUJITSU LIMITED +B09928 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +04-E1-C8 (hex) IMS Soluções em Energia Ltda. +04E1C8 (base 16) IMS Soluções em Energia Ltda. + Av. Bernardino Silveira Pastoriza, 720 + Porto Alegre RS 91160-310 + BR + +94-8F-EE (hex) Verizon Telematics +948FEE (base 16) Verizon Telematics + 2002 Summit Blvd + Atlanta GA 30319 + US + +50-D6-D7 (hex) Takahata Precision +50D6D7 (base 16) Takahata Precision + 4-17-1 Suniyoshi + Kofu 400-0851 + JP + +88-F0-77 (hex) Cisco Systems, Inc +88F077 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +58-75-21 (hex) CJSC RTSoft +587521 (base 16) CJSC RTSoft + Nikitinskaya str., 3 + Moscow 105037 + RU + +C4-0F-09 (hex) Hermes electronic GmbH +C40F09 (base 16) Hermes electronic GmbH + Am Handwerkerpark 1 + Essen NRW 45309 + DE + +48-F4-7D (hex) TechVision Holding Internation Limited +48F47D (base 16) TechVision Holding Internation Limited + Offshore Incorporations Centre + Road Town Tortola VG1110 + VG + +F0-81-AF (hex) IRZ AUTOMATION TECHNOLOGIES LTD +F081AF (base 16) IRZ AUTOMATION TECHNOLOGIES LTD + Unit 9-10 27/F Seapower Tower + Kowloon + HK + +70-14-04 (hex) Limited Liability Company +701404 (base 16) Limited Liability Company + I.Yakovleva St., 1 + Cheboksary Chuvash Republic 428003 + RU + +B4-35-F7 (hex) Zhejiang Pearmain Electronics Co.ltd. +B435F7 (base 16) Zhejiang Pearmain Electronics Co.ltd. + 4F Yitai Mansion, 76 Gucui Road, + Hangzhou Zhejiang 310012 + CN + +98-66-EA (hex) Industrial Control Communications, Inc. +9866EA (base 16) Industrial Control Communications, Inc. + 1600 Aspen Commons + Middleton WI 53562 + US + +98-30-00 (hex) Beijing KEMACOM Technologies Co., Ltd. +983000 (base 16) Beijing KEMACOM Technologies Co., Ltd. + Room 208, Building 6, No.50, Xi San Huan Bei Road + Beijing 100044 + CN + +90-CF-15 (hex) Nokia Corporation +90CF15 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +94-8B-03 (hex) EAGET Innovation and Technology Co., Ltd. +948B03 (base 16) EAGET Innovation and Technology Co., Ltd. + 3/F, Building 4, Lianchuang Technology Park,Buji Town, + Shenzhen Guangdong 518112 + CN + +2C-00-33 (hex) EControls, LLC +2C0033 (base 16) EControls, LLC + 5757 Farinon Dr + San Antonio TX 78249 + US + +AC-19-9F (hex) SUNGROW POWER SUPPLY CO.,LTD. +AC199F (base 16) SUNGROW POWER SUPPLY CO.,LTD. + NO.2 Tianhu Road, New and High Technology Industrial Development Zone + Hefei Anhui 230088 + CN + +7C-4A-82 (hex) Portsmith LLC +7C4A82 (base 16) Portsmith LLC + 850 E. Franklin Road + Meridian ID 83642 + US + +94-E8-48 (hex) FYLDE MICRO LTD +94E848 (base 16) FYLDE MICRO LTD + 8 AVROE CRESCENT + BLACKPOOL LANCASHIRE FY4 2DP + GB + +AC-5E-8C (hex) Utillink +AC5E8C (base 16) Utillink + 817 Woolim Lions Valley 1, 311-3 Sangdaewon-dong Jungwon-gu + Seongnam-si Gyeonggi-do 462160 + KR + +18-E2-88 (hex) STT Condigi +18E288 (base 16) STT Condigi + Agnesfridsvagen 113 A + Malmö Skåne 21237 + SE + +1C-35-F1 (hex) NEW Lift Neue Elektronische Wege Steuerungsbau GmbH +1C35F1 (base 16) NEW Lift Neue Elektronische Wege Steuerungsbau GmbH + Lochhamer Schlag 8 + Graefelfing Bavaria 82166 + DE + +80-34-57 (hex) OT Systems Limited +803457 (base 16) OT Systems Limited + Unit 1023, 10/F., Landmark North, + Sheung Shui, N. T. + HK + +5C-0C-BB (hex) CELIZION Inc. +5C0CBB (base 16) CELIZION Inc. + #206 Lordland EZ Tower, GuMi-Dong 153 BunDang-Gu + SeongNam-Si GyeongGi-Do 463-870 + KR + +C4-24-2E (hex) Galvanic Applied Sciences Inc +C4242E (base 16) Galvanic Applied Sciences Inc + 7000 Fisher Road SE + Calgary Alberta T2H 0W3 + CA + +24-C8-6E (hex) Chaney Instrument Co. +24C86E (base 16) Chaney Instrument Co. + 965 Wells Street + Lake Geneva WI 53147 + US + +F0-AE-51 (hex) Xi3 Corp +F0AE51 (base 16) Xi3 Corp + 299 S. Main St. + Salt Lake City UT 84111 + US + +B8-0B-9D (hex) ROPEX Industrie-Elektronik GmbH +B80B9D (base 16) ROPEX Industrie-Elektronik GmbH + Adolf-Heim-Str. 4 + Bietigheim-Bissingen Baden Wuerttemberg 74321 + DE + +30-61-18 (hex) Paradom Inc. +306118 (base 16) Paradom Inc. + 8F, N0. 178, Sec-2, Gongdaowu Rd. + Hsinchu City 300 + TW + +4C-73-67 (hex) Genius Bytes Software Solutions GmbH +4C7367 (base 16) Genius Bytes Software Solutions GmbH + Merianstraße 30 + Bochum NRW 44801 + DE + +90-EA-60 (hex) SPI Lasers Ltd +90EA60 (base 16) SPI Lasers Ltd + 6 wellington Park + Southampton Hampshire S0302QU + GB + +50-70-E5 (hex) He Shan World Fair Electronics Technology Limited +5070E5 (base 16) He Shan World Fair Electronics Technology Limited + New Material Base, Gonghe Town + Jiangmen Guangdong 529728 + CN + +80-22-75 (hex) Beijing Beny Wave Technology Co Ltd +802275 (base 16) Beijing Beny Wave Technology Co Ltd + No.55, Jiachuang Road + Tongzhou District Beijing 101111 + CN + +CC-F3-A5 (hex) Chi Mei Communication Systems, Inc +CCF3A5 (base 16) Chi Mei Communication Systems, Inc + No.4 + Tucheng City Taipei County 23678 + TW + +14-A9-E3 (hex) MST CORPORATION +14A9E3 (base 16) MST CORPORATION + 4th Floor Lawford House + London England N3 1 RL + GB + +F8-EA-0A (hex) Dipl.-Math. Michael Rauch +F8EA0A (base 16) Dipl.-Math. Michael Rauch + Kapellenstraße 31 + Bretten BaWü 75015 + DE + +38-31-AC (hex) WEG +3831AC (base 16) WEG + Av. Pref. Waldemar Grubba, 3000 + Jaraguá do Sul Santa Catarina 89256-900 + BR + +58-4C-19 (hex) Chongqing Guohong Technology Development Company Limited +584C19 (base 16) Chongqing Guohong Technology Development Company Limited + Rongzhi Building, Science & Technology Venture Center, + Chongqing 401336 + CN + +64-69-BC (hex) Hytera Communications Co .,ltd +6469BC (base 16) Hytera Communications Co .,ltd + HYT Tower ,Hi-Tech Industrial Park North,Nanshan District, + Shenzhen Guangdong 518057 + CN + +B4-F3-23 (hex) PETATEL INC. +B4F323 (base 16) PETATEL INC. + #322 THE O VILLE 720-25, YEOKSAM-DONG + GANGNAM-GU SEOUL 135080 + KR + +28-51-32 (hex) Shenzhen Prayfly Technology Co.,Ltd +285132 (base 16) Shenzhen Prayfly Technology Co.,Ltd + 16F B International Chamber of Commerce Building + Shenzhen Guangdong Province 518048 + CN + +E4-2F-F6 (hex) Unicore communication Inc. +E42FF6 (base 16) Unicore communication Inc. + Rm.312 Building 2 IRICO, No.11St.4,Shangdi, Haidian District, + Beijing 100085 + CN + +84-D9-C8 (hex) Unipattern Co., +84D9C8 (base 16) Unipattern Co., + 16F., No.30., Beiping E. Rd., Zhongzheng Dist., + Taipei 100 + TW + +94-AA-B8 (hex) Joview(Beijing) Technology Co. Ltd. +94AAB8 (base 16) Joview(Beijing) Technology Co. Ltd. + Room 302, South Building + Beijing 100081 + CN + +28-F3-58 (hex) 2C - Trifonov & Co +28F358 (base 16) 2C - Trifonov & Co + 133, Tsarigradsko Shose Blvd, BIZ IZOT, + Sofia 1784 + BG + +14-C2-1D (hex) Sabtech Industries +14C21D (base 16) Sabtech Industries + 23231 La Palma Ave + Yorba Linda Ca. 92887-4788 + US + +C8-84-39 (hex) Sunrise Technologies +C88439 (base 16) Sunrise Technologies + 54 Commercial Street + Raynham MA 02767 + US + +F0-BF-97 (hex) Sony Corporation +F0BF97 (base 16) Sony Corporation + Gotenyama Tec 5-1-2 + Tokyo Shinagawa-ku 141-0001 + JP + +C4-4A-D0 (hex) FIREFLIES SYSTEMS +C44AD0 (base 16) FIREFLIES SYSTEMS + 3 CHEMIN DU PRE CARRE + MEYLAN 38240 + FR + +EC-7D-9D (hex) CPI +EC7D9D (base 16) CPI + 3222 Phoenixville Pike Suite 200 + Malvern PA 19355 + US + +C8-1E-8E (hex) ADV Security (S) Pte Ltd +C81E8E (base 16) ADV Security (S) Pte Ltd + 56 Dunlop Street + 209386 + SG + +A8-87-92 (hex) Broadband Antenna Tracking Systems +A88792 (base 16) Broadband Antenna Tracking Systems + 8902 Vincennes Circle, Suite D-2 + Indianapolis IN 46268 + US + +14-F0-C5 (hex) Xtremio Ltd. +14F0C5 (base 16) Xtremio Ltd. + POB 5246 + Herzelyia 46152 + IL + +E8-C2-29 (hex) H-Displays (MSC) Bhd +E8C229 (base 16) H-Displays (MSC) Bhd + No. 31 & 32, Jalan Gangsa Dua + Johor Bahru 81700 + MY + +3C-A7-2B (hex) MRV Communications (Networks) LTD +3CA72B (base 16) MRV Communications (Networks) LTD + P.O Box 614 + Yokneam 20692 + IL + +30-1A-28 (hex) Mako Networks Ltd +301A28 (base 16) Mako Networks Ltd + 1/62 Paul Matthews Rd + Auckland 0632 + NZ + +04-E6-62 (hex) Acroname Inc. +04E662 (base 16) Acroname Inc. + 4822 Sterling Drive + Boulder CO 80301-2350 + US + +F8-7B-8C (hex) Amped Wireless +F87B8C (base 16) Amped Wireless + 13089 Peyton Dr. #C307 + Chino Hills CA 91709 + US + +28-34-10 (hex) Enigma Diagnostics Limited +283410 (base 16) Enigma Diagnostics Limited + Building 224 + DSTL Porton Down Salisbury SP4 0JQ + GB + +0C-E8-2F (hex) Bonfiglioli Vectron GmbH +0CE82F (base 16) Bonfiglioli Vectron GmbH + Europark Fichtenhain B6 + Krefeld NRW 47807 + DE + +40-F4-EC (hex) Cisco Systems, Inc +40F4EC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +14-B7-3D (hex) ARCHEAN Technologies +14B73D (base 16) ARCHEAN Technologies + 1899 avenue d'Italie + MONTAUBAN 82000 + FR + +94-8D-50 (hex) Beamex Oy Ab +948D50 (base 16) Beamex Oy Ab + Ristisuonraitti 10 + Pietarsaari FI-68600 + FI + +A4-33-D1 (hex) Fibrlink Communications Co.,Ltd. +A433D1 (base 16) Fibrlink Communications Co.,Ltd. + 28F Ages Wealth World, No.1 Hangfeng Road + Beijing 100070 + CN + +5C-BD-9E (hex) HONGKONG MIRACLE EAGLE TECHNOLOGY(GROUP) LIMITED +5CBD9E (base 16) HONGKONG MIRACLE EAGLE TECHNOLOGY(GROUP) LIMITED + FLAT RM 2103, EASEY COMMERCIAL BLDG,253-261 HENNESSY RD, + WANCHAI 999077 + HK + +08-E6-72 (hex) JEBSEE ELECTRONICS CO.,LTD. +08E672 (base 16) JEBSEE ELECTRONICS CO.,LTD. + 24-3, SIN LE ROAD, + TAINAN 70268 + TW + +B8-E5-89 (hex) Payter BV +B8E589 (base 16) Payter BV + Rozenlaan 115 + Rotterdam Zuid-Holland 3051 LP + NL + +88-E0-A0 (hex) Shenzhen VisionSTOR Technologies Co., Ltd +88E0A0 (base 16) Shenzhen VisionSTOR Technologies Co., Ltd + 12/F, East Tower,Nanshan Software Park + Shenzhen Guangdong 518000 + CN + +FC-10-BD (hex) Control Sistematizado S.A. +FC10BD (base 16) Control Sistematizado S.A. + Cra 43 N 31 52 + Medellin Antioquia 10101 + CO + +F0-C2-7C (hex) Mianyang Netop Telecom Equipment Co.,Ltd. +F0C27C (base 16) Mianyang Netop Telecom Equipment Co.,Ltd. + No.111,East section of Puming South Road, + Mianyang City Sichuan Province, 621000 + CN + +24-1A-8C (hex) Squarehead Technology AS +241A8C (base 16) Squarehead Technology AS + PO Box 13 Nydalen + Oslo NO-0410 + NO + +D4-4F-80 (hex) Kemper Digital GmbH +D44F80 (base 16) Kemper Digital GmbH + Koenigswall 16-18 + Recklinghausen North-Rhine-Westphalia 45657 + DE + +A4-1B-C0 (hex) Fastec Imaging Corporation +A41BC0 (base 16) Fastec Imaging Corporation + 17150 Via Del Campo + San Diego California 92127 + US + +20-5B-2A (hex) Private +205B2A (base 16) Private + +F4-03-21 (hex) BeNeXt B.V. +F40321 (base 16) BeNeXt B.V. + Ter Gouwstraat 3 + Amsterdam NH 1093JX + NL + +A0-71-A9 (hex) Nokia Corporation +A071A9 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +A4-E3-2E (hex) Silicon & Software Systems Ltd. +A4E32E (base 16) Silicon & Software Systems Ltd. + South County Business Park + Leopardstown Dublin 18 + IE + +C8-C1-26 (hex) ZPM Industria e Comercio Ltda +C8C126 (base 16) ZPM Industria e Comercio Ltda + Rua Araguaia, 175 + Canoas RS 92410-000 + BR + +64-DE-1C (hex) Kingnetic Pte Ltd +64DE1C (base 16) Kingnetic Pte Ltd + 47 Kaki Bukit Place + 416225 + SG + +A8-62-A2 (hex) JIWUMEDIA CO., LTD. +A862A2 (base 16) JIWUMEDIA CO., LTD. + #902, Daerug Techno Town 13'th, 664 + Geumcheon-gu Seoul 153-803 + KR + +98-4E-97 (hex) Starlight Marketing (H. K.) Ltd. +984E97 (base 16) Starlight Marketing (H. K.) Ltd. + 5/F., Shing Dao Industrial Building, + + HK + +64-DC-01 (hex) Static Systems Group PLC +64DC01 (base 16) Static Systems Group PLC + Heathmill Road + Wolverhampton West Midlands WV5 8AN + GB + +FC-1F-C0 (hex) EURECAM +FC1FC0 (base 16) EURECAM + BAT 9 - Miniparc + LES ULIS 91940 + FR + +BC-67-84 (hex) Environics Oy +BC6784 (base 16) Environics Oy + Graanintie 5 + Mikkeli 50190 + FI + +68-DC-E8 (hex) PacketStorm Communications +68DCE8 (base 16) PacketStorm Communications + 20 Meridian Rd + Eatontown NJ 07724 + US + +48-8E-42 (hex) DIGALOG GmbH +488E42 (base 16) DIGALOG GmbH + Wattstraße 11-13 + Berlin D-13355 + DE + +60-76-88 (hex) Velodyne +607688 (base 16) Velodyne + 345 Digital Drive + Morgan Hill CA 95037 + US + +78-CD-8E (hex) SMC Networks Inc +78CD8E (base 16) SMC Networks Inc + 20 Mason + Irvine CA 92618 + US + +2C-80-65 (hex) HARTING Inc. of North America +2C8065 (base 16) HARTING Inc. of North America + 1370 Bowes Road + Elgin Illinois 60123 + US + +3C-C0-C6 (hex) d&b audiotechnik GmbH +3CC0C6 (base 16) d&b audiotechnik GmbH + Eugen Adolff Str 134 + Backnang Baden Wuerttemberg 71522 + DE + +44-68-AB (hex) JUIN COMPANY, LIMITED +4468AB (base 16) JUIN COMPANY, LIMITED + 2FL, 1075-1, Wonpyeong-Dong + Gumi City Gyeongsangbuk-Do 730-010 + KR + +F8-10-37 (hex) Atopia Systems, LP +F81037 (base 16) Atopia Systems, LP + 681 N. Plano Road + Richardson TX 75082 + US + +78-A6-83 (hex) Precidata +78A683 (base 16) Precidata + CP 672 + 2002 NE 2002 + CH + +F0-25-72 (hex) Cisco Systems, Inc +F02572 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +04-FF-51 (hex) NOVAMEDIA INNOVISION SP. Z O.O. +04FF51 (base 16) NOVAMEDIA INNOVISION SP. Z O.O. + WODNA 7 + KALISZ WIELKOPOLSKA 62-800 + PL + +4C-B4-EA (hex) HRD (S) PTE., LTD. +4CB4EA (base 16) HRD (S) PTE., LTD. + Lot 7, Block 9, Phase 1, Cavite Eco-Zone, + Rosario Cavite 4106 + PH + +D4-4C-24 (hex) Vuppalamritha Magnetic Components LTD +D44C24 (base 16) Vuppalamritha Magnetic Components LTD + 3rd Floor, 307 ,My Home Ashoka Chambers,S.P Road, + Secunderabad AndhraPradesh 500003 + IN + +F8-C6-78 (hex) Carefusion +F8C678 (base 16) Carefusion + 10020 Pacific Mesa Blvd + San Diego CA 92121 + US + +6C-AB-4D (hex) Digital Payment Technologies +6CAB4D (base 16) Digital Payment Technologies + 4105 Grandview Hwy + Burnaby BC V5C 6B4 + CA + +2C-B0-DF (hex) Soliton Technologies Pvt Ltd +2CB0DF (base 16) Soliton Technologies Pvt Ltd + # 683, 15th Cross + Bangalore Karnataka 560 078 + IN + +EC-E5-55 (hex) Hirschmann Automation +ECE555 (base 16) Hirschmann Automation + Stuttgarter Straße 45-51 + Neckartenzlingen Baden-Württemberg 72654 + DE + +58-F9-8E (hex) SECUDOS GmbH +58F98E (base 16) SECUDOS GmbH + Rhenus-Platz 2 + Holzwickede NRW 59439 + DE + +B4-C4-4E (hex) VXL eTech Pvt Ltd +B4C44E (base 16) VXL eTech Pvt Ltd + #91, 11th Main, Begur Main Road + Bangalore Karnataka 560068 + IN + +70-7E-DE (hex) NASTEC LTD. +707EDE (base 16) NASTEC LTD. + 111-D, Krasnorechenskaya str. + Khabarovsk 680006 + RU + +C0-7E-40 (hex) SHENZHEN XDK COMMUNICATION EQUIPMENT CO.,LTD +C07E40 (base 16) SHENZHEN XDK COMMUNICATION EQUIPMENT CO.,LTD + XDK BUILDING,NO.1 INDUSTRIAL AREA,BANTIAN,LONGGANG DISTRICT + SHENZHEN GUANGDONG 518129 + CN + +E4-4F-29 (hex) MA Lighting Technology GmbH +E44F29 (base 16) MA Lighting Technology GmbH + Dachdeckerstraße16 + Waldbüttelbrunn Bavaria 97297 + DE + +B4-74-9F (hex) ASKEY COMPUTER CORP +B4749F (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +7C-4A-A8 (hex) MindTree Wireless PVT Ltd +7C4AA8 (base 16) MindTree Wireless PVT Ltd + LGF, Phase III, Mindtree West Campus, + Bangalore Karnataka 560 059 + IN + +80-91-C0 (hex) AgileMesh, Inc. +8091C0 (base 16) AgileMesh, Inc. + 1671 International Pkwy + Richardson TX 75081 + US + +08-4E-BF (hex) Broad Net Mux Corporation +084EBF (base 16) Broad Net Mux Corporation + 4-1-8 Kounan Minato-ku + Tokyo 108-0075 + JP + +E0-5F-B9 (hex) Cisco Systems, Inc +E05FB9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E0-14-3E (hex) Modoosis Inc. +E0143E (base 16) Modoosis Inc. + #302, Samil Bldg., 656-282 + Seoul 133-110 + KR + +90-D8-52 (hex) Comtec Co., Ltd. +90D852 (base 16) Comtec Co., Ltd. + 3F., No.81, Jiankang Rd., + Zhonghe City Taipei County 23586 + TW + +38-01-97 (hex) TSST Global,Inc +380197 (base 16) TSST Global,Inc + 14 Floor, Bldg. No. 102, Digital Empire2, 486, Sin-dong, Yeongtong-gu, Suwon-si, + Su-won Gyeonggi 443-734 + KR + +AC-02-CF (hex) RW Tecnologia Industria e Comercio Ltda +AC02CF (base 16) RW Tecnologia Industria e Comercio Ltda + Centro Empresarial Paulo Frederico de Toledo, 80 A + Santa Rita do Sapucai Minas Gerais 37540000 + BR + +D4-12-96 (hex) Anobit Technologies Ltd. +D41296 (base 16) Anobit Technologies Ltd. + 8 Hasadnaot St. + Herzeliya Pituach 46728 + IL + +48-17-4C (hex) MicroPower technologies +48174C (base 16) MicroPower technologies + 4225 Executive Sq. + La Jolla California 92037 + US + +34-9A-0D (hex) ZBD Displays Ltd +349A0D (base 16) ZBD Displays Ltd + Orchard Lea + Windsor Berkshire SL4 4RU + GB + +90-50-7B (hex) Advanced PANMOBIL Systems GmbH & Co. KG +90507B (base 16) Advanced PANMOBIL Systems GmbH & Co. KG + Hansestraße 91 + Cologne NRW 51149 + DE + +08-76-FF (hex) Thomson Telecom Belgium +0876FF (base 16) Thomson Telecom Belgium + Prins Boudewijnlaan 47 + Edegem Antwerp B-2650 + BE + +1C-7C-11 (hex) EID +1C7C11 (base 16) EID + Rua Quinta dos Medronheiros + Charneca da Caparica 2820-486 + PT + +20-AA-25 (hex) IP-NET LLC +20AA25 (base 16) IP-NET LLC + 10256 N.W. 47th St. + Sunrise FL 33351 + US + +C4-EE-F5 (hex) II-VI Incorporated +C4EEF5 (base 16) II-VI Incorporated + Network Solutions,343 Daniel Zenker Dr., Suite 102 + Horseheads NY 14845 + US + +E0-CF-2D (hex) Gemintek Corporation +E0CF2D (base 16) Gemintek Corporation + 5F-1, No.8, Alley 30, Lane 358, Rueiguang Rd. + Taipei 114 + TW + +D4-91-AF (hex) Electroacustica General Iberica, S.A. +D491AF (base 16) Electroacustica General Iberica, S.A. + Avda. Almozara, 79 + Zaragoza 50003 + ES + +C4-B5-12 (hex) General Electric Digital Energy +C4B512 (base 16) General Electric Digital Energy + 4200 Wildwood Pkwy + Atlanta GA 30339 + US + +00-34-F1 (hex) Radicom Research, Inc. +0034F1 (base 16) Radicom Research, Inc. + 2148 Bering Drive + San Jose Ca 95131 + US + +94-33-DD (hex) Taco Inc +9433DD (base 16) Taco Inc + 1160 Cranston Street + Cranston RI 02920 + US + +E0-25-38 (hex) Titan Pet Products +E02538 (base 16) Titan Pet Products + 6521 Creedmoor Rd. Suite 101 + Raleigh NC 27613 + US + +CC-7A-30 (hex) CMAX Wireless Co., Ltd. +CC7A30 (base 16) CMAX Wireless Co., Ltd. + KT Bongduk B/D 9F, 627-15, Bongduk-dong + Namgu Daegu 705710 + KR + +B8-8E-3A (hex) Infinite Technologies JLT +B88E3A (base 16) Infinite Technologies JLT + Office 3203, Level 32 + Jumeirah Lake Towers Dubai + AE + +58-8D-09 (hex) Cisco Systems, Inc +588D09 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C0-C1-C0 (hex) Cisco-Linksys, LLC +C0C1C0 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +60-15-C7 (hex) IdaTech +6015C7 (base 16) IdaTech + 63065 NE 18th St. + Bend OR 97701 + US + +DC-20-08 (hex) ASD Electronics Ltd +DC2008 (base 16) ASD Electronics Ltd + DEDE INDUSTRIAL PARK,JIAN'AN ROAD,HIGH-TECH + Shenzhen Guang Dong 518103 + CN + +1C-83-B0 (hex) Linked IP GmbH +1C83B0 (base 16) Linked IP GmbH + Kirchenstrasse 9 + Anif / Niederalm SBG 5081 + AT + +A4-D1-D1 (hex) ECOtality North America +A4D1D1 (base 16) ECOtality North America + 430 S 2nd Avenue + Phoenix AZ 85003 + US + +C4-93-13 (hex) 100fio networks technology llc +C49313 (base 16) 100fio networks technology llc + 2534 crescent st. apt 3F + Astoria New york 11102 + US + +7C-39-20 (hex) SSOMA SECURITY +7C3920 (base 16) SSOMA SECURITY + Unit 703, Daeryung Technotown 13th, + Geumcheongu Seoul 153754 + KR + +28-C0-DA (hex) Juniper Networks +28C0DA (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +9C-77-AA (hex) NADASNV +9C77AA (base 16) NADASNV + 2203, T-dong, Poonglim I-won Plus + Seongnam-si Gyeonggi-do 463-862 + KR + +10-E8-EE (hex) PhaseSpace +10E8EE (base 16) PhaseSpace + 1933 Davis St Suite 312 + San Leandro CA 94577 + US + +A4-7C-1F (hex) Cobham plc +A47C1F (base 16) Cobham plc + 3985 Gateway Centre Blvd + Pinellas Park FL 33782 + US + +D4-6C-DA (hex) CSM GmbH +D46CDA (base 16) CSM GmbH + Raiffeisenstraße 34 + Filderstadt Baden-Württemberg 70794 + DE + +5C-D9-98 (hex) D-Link Corporation +5CD998 (base 16) D-Link Corporation + No.289, Sinhu 3rd Rd., Neihu District, + Taipei City 114 + TW + +68-59-7F (hex) Alcatel Lucent +68597F (base 16) Alcatel Lucent + Via Energy Park, 14 + Vimercate MB 20871 + IT + +F0-65-DD (hex) Primax Electronics Ltd. +F065DD (base 16) Primax Electronics Ltd. + 669, Ruey Kuang Road, Neihu + Taipei 114 + TW + +70-65-82 (hex) Suzhou Hanming Technologies Co., Ltd. +706582 (base 16) Suzhou Hanming Technologies Co., Ltd. + Suite 407, No. 166, Ren Ai Road + Suzhou Jiangsu 215123 + CN + +34-D2-C4 (hex) RENA GmbH Print Systeme +34D2C4 (base 16) RENA GmbH Print Systeme + Hienlohestrasse 24 + Otterfing Bavaria 83624 + DE + +D4-CB-AF (hex) Nokia Corporation +D4CBAF (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +04-5D-56 (hex) camtron industrial inc. +045D56 (base 16) camtron industrial inc. + 5F, Kuem-Ah B/D, 31-3, Karak-dong, Songpa-gu + Seoul 138-801 + KR + +68-23-4B (hex) Nihon Dengyo Kousaku +68234B (base 16) Nihon Dengyo Kousaku + shinmachi 21-1 + kawagoe-shi saitama 350-1107 + JP + +1C-3D-E7 (hex) Sigma Koki Co.,Ltd. +1C3DE7 (base 16) Sigma Koki Co.,Ltd. + 1-19-9 Midori + Sumida-ku Tokyo 130-0021 + JP + +58-BC-27 (hex) Cisco Systems, Inc +58BC27 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +20-D6-07 (hex) Nokia Corporation +20D607 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +6C-E0-B0 (hex) SOUND4 +6CE0B0 (base 16) SOUND4 + 11 quai Joseph Gillet + LYON 69004 + FR + +9C-FF-BE (hex) OTSL Inc. +9CFFBE (base 16) OTSL Inc. + HANROKU Bldg. 2F, 2-1-2 + Shinjuku-ku Tokyo 160-0021 + JP + +00-F8-60 (hex) PT. Panggung Electric Citrabuana +00F860 (base 16) PT. Panggung Electric Citrabuana + Jl. Raya Waru no. 1 + Sidoarjo Jawa Timur 61256 + ID + +B8-BA-72 (hex) Cynove +B8BA72 (base 16) Cynove + 10 cite rougemont + Paris 75009 + FR + +44-3D-21 (hex) Nuvolt +443D21 (base 16) Nuvolt + 8087 Boul. de la Rive Sud + Levis Quebec G6V 9G9 + CA + +30-49-3B (hex) Nanjing Z-Com Wireless Co.,Ltd +30493B (base 16) Nanjing Z-Com Wireless Co.,Ltd + Z-Com Building,NO.30 Jiangsu Software Park,NO.699-22 Xuanwu Avenue, + Nanjing Jiangsu 210042 + CN + +A4-5C-27 (hex) Nintendo Co., Ltd. +A45C27 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +6C-04-60 (hex) RBH Access Technologies Inc. +6C0460 (base 16) RBH Access Technologies Inc. + 2 Automatic Road + Brampton Ontario L6S 6K8 + CA + +70-64-17 (hex) ORBIS TECNOLOGIA ELECTRICA S.A. +706417 (base 16) ORBIS TECNOLOGIA ELECTRICA S.A. + Lerida, 61 + Madrid Madrid E28020 + US + +18-EF-63 (hex) Cisco Systems, Inc +18EF63 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +20-6F-EC (hex) Braemac CA LLC +206FEC (base 16) Braemac CA LLC + 43134 Osgood Road + Fremont CA 94539 + US + +10-0D-32 (hex) Embedian, Inc. +100D32 (base 16) Embedian, Inc. + 10F., 95, Nanjing E. Rd. Sec. 4, + Taipei 10580 + TW + +88-AC-C1 (hex) Generiton Co., Ltd. +88ACC1 (base 16) Generiton Co., Ltd. + 8F-1, No. 81, Shuili Rd., + Hsinchu City, 30059 + TW + +88-18-AE (hex) Tamron Co., Ltd +8818AE (base 16) Tamron Co., Ltd + 1385,Hasunuma, Minuma-ku + Saitama-shi Saitama 337-8556 + JP + +7C-ED-8D (hex) Microsoft +7CED8D (base 16) Microsoft + 1 Microsoft Way + Redmond Washington 98052 + US + +A4-BE-61 (hex) EutroVision System, Inc. +A4BE61 (base 16) EutroVision System, Inc. + Rm 403,Building33,No.680 GuipingRd,Xuhui, + Shanghai 200233 + CN + +D0-7D-E5 (hex) Forward Pay Systems, Inc. +D07DE5 (base 16) Forward Pay Systems, Inc. + 9531 West 78th St., #245 + Eden Prairie MN 55344 + US + +04-DD-4C (hex) Velocytech +04DD4C (base 16) Velocytech + Poppelgårdvej 11 + Søborg DK 2860 + DK + +A4-0C-C3 (hex) Cisco Systems, Inc +A40CC3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +4C-BA-A3 (hex) Bison Electronics Inc. +4CBAA3 (base 16) Bison Electronics Inc. + 3F., No.28, Lane 583, Rueiguang Rd., Neihu District + Taipei City 11492 + TW + +A8-B1-D4 (hex) Cisco Systems, Inc +A8B1D4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +EC-7C-74 (hex) Justone Technologies Co., Ltd. +EC7C74 (base 16) Justone Technologies Co., Ltd. + Tongguang Building F19, 12# South Agriculture Exhibition Center Road, + Beijing 100125 + CN + +CC-FC-B1 (hex) Wireless Technology, Inc. +CCFCB1 (base 16) Wireless Technology, Inc. + 2064 Eastman Ave. #113 + Ventura CA 93003-7787 + US + +3C-1A-79 (hex) Huayuan Technology CO.,LTD +3C1A79 (base 16) Huayuan Technology CO.,LTD + R308 Block Jingmeng High-Tech Building,NO.5-1 Shangdi East Road, + Beijing 100085 + CN + +9C-F6-1A (hex) UTC Fire and Security +9CF61A (base 16) UTC Fire and Security + 2955 Red Hill Ave. + Costa Mesa CA 92626 + US + +7C-F0-98 (hex) Bee Beans Technologies, Inc. +7CF098 (base 16) Bee Beans Technologies, Inc. + TCI B5 + Tsukuba City Ibaraki 305-0047 + JP + +EC-66-D1 (hex) B&W Group LTD +EC66D1 (base 16) B&W Group LTD + Dale Road + Worthing Sussex BN11 2BH + GB + +38-5F-C3 (hex) Yu Jeong System, Co.Ltd +385FC3 (base 16) Yu Jeong System, Co.Ltd + #503, Dong il B/D, 826, Guro-3dong, + Seoul 152-879 + KR + +88-8B-5D (hex) Storage Appliance Corporation +888B5D (base 16) Storage Appliance Corporation + 29 Su Zhou Jie, Haidian Dist. + Beijing 100080 + CN + +78-C6-BB (hex) Innovasic, Inc. +78C6BB (base 16) Innovasic, Inc. + 5635 Jefferson St. NE, Suite A + Albuquerque NM 87109 + US + +84-A9-91 (hex) Cyber Trans Japan Co.,Ltd. +84A991 (base 16) Cyber Trans Japan Co.,Ltd. + + Setagaya-ku Tokyo 155-0031 + JP + +68-78-4C (hex) Nortel Networks +68784C (base 16) Nortel Networks + CARRETERA BASE AEREA # 5850 + Zapopan Jalisco 44130 + MX + +F8-D7-56 (hex) Simm Tronic Limited +F8D756 (base 16) Simm Tronic Limited + Unit 3, Waterside + Hoddesdon Hertfordshire EN11 0QR + GB + +04-A3-F3 (hex) Emicon +04A3F3 (base 16) Emicon + shelkovskoe shosse, 77 + Moscow 107241 + RU + +1C-17-D3 (hex) Cisco Systems, Inc +1C17D3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +7C-E0-44 (hex) NEON Inc +7CE044 (base 16) NEON Inc + 5340 Airport Boulevard + Boulder CO 80301 + US + +28-4C-53 (hex) Intune Networks +284C53 (base 16) Intune Networks + 9B Beckett Way + Dublin 12 + IE + +64-D0-2D (hex) Next Generation Integration (NGI) +64D02D (base 16) Next Generation Integration (NGI) + 137 rue de Versailles + Le Chesnay 78150 + FR + +90-51-3F (hex) Elettronica Santerno SpA +90513F (base 16) Elettronica Santerno SpA + Via della Concia 7 + Castel Guelfo (BO) 40026 + IT + +88-41-C1 (hex) ORBISAT DA AMAZONIA IND E AEROL SA +8841C1 (base 16) ORBISAT DA AMAZONIA IND E AEROL SA + AV SHISHIMA HIFUMI, 2911 + SAO JOSE DOS CAMPOS São Paulo 12244-000 + BR + +9C-75-14 (hex) Wildix srl +9C7514 (base 16) Wildix srl + loc. Le Basse, 3 + Trento TN 38100 + IT + +4C-F7-37 (hex) SamJi Electronics Co., Ltd +4CF737 (base 16) SamJi Electronics Co., Ltd + 459-21, Gasan-dong, Gumchun-ku + Seoul 153-803 + KR + +F0-D7-67 (hex) Axema Passagekontroll AB +F0D767 (base 16) Axema Passagekontroll AB + Box 90 215 + Stockholm 120 23 + SE + +C8-4C-75 (hex) Cisco Systems, Inc +C84C75 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C8-02-A6 (hex) Beijing Newmine Technology +C802A6 (base 16) Beijing Newmine Technology + 10 floor,Keshi Plaza + Beijing 100085 + CN + +4C-8B-55 (hex) Grupo Digicon +4C8B55 (base 16) Grupo Digicon + Rua Nissin Castiel, 640 + Gravataí Rio Grande do Sul 94045420 + BR + +6C-5C-DE (hex) SunReports, Inc. +6C5CDE (base 16) SunReports, Inc. + 1406 Cedarwood Dr. + San Mateo CA 94403 + US + +34-F3-9B (hex) WizLAN Ltd. +34F39B (base 16) WizLAN Ltd. + P.O.Box 7948 + Haifa 31078 + IL + +E8-6C-DA (hex) Supercomputers and Neurocomputers Research Center +E86CDA (base 16) Supercomputers and Neurocomputers Research Center + 2, Chekhov st + Taganrog Rostov-on-Don region 347922 + RU + +24-0B-2A (hex) Viettel Group +240B2A (base 16) Viettel Group + Center for Research and Development + Hanoi 1111 + VN + +00-B5-D6 (hex) Omnibit Inc. +00B5D6 (base 16) Omnibit Inc. + 2-7-9, Soto-Kanda + Chiyoda-ku Tokyo 101-0021 + JP + +54-89-22 (hex) Zelfy Inc +548922 (base 16) Zelfy Inc + 4655 Old Ironsides Dr, Suite#200 + Santa Clara Ca 95054 + US + +50-C5-8D (hex) Juniper Networks +50C58D (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +24-A4-2C (hex) KOUKAAM a.s. +24A42C (base 16) KOUKAAM a.s. + U vinnych sklepu 7 + Prague 190 00 + CZ + +4C-30-89 (hex) Thales Transportation Systems GmbH +4C3089 (base 16) Thales Transportation Systems GmbH + Bierweg 2 + Arnstadt Thuringia 99310 + DE + +48-12-49 (hex) Luxcom Technologies Inc. +481249 (base 16) Luxcom Technologies Inc. + 102 Walgreen Road + Ottawa Ontario K0A 1L0 + CA + +24-A9-37 (hex) PURE Storage +24A937 (base 16) PURE Storage + 650 Castro Street + Mt. View CA 94041 + US + +34-83-02 (hex) iFORCOM Co., Ltd +348302 (base 16) iFORCOM Co., Ltd + 1326 + Sagamihara Kanagawa 252-0157 + JP + +B4-3D-B2 (hex) Degreane Horizon +B43DB2 (base 16) Degreane Horizon + 730 Rue de l'Initiative + Cuers Var 83390 + FR + +84-F6-4C (hex) Cross Point BV +84F64C (base 16) Cross Point BV + Postbus 2112 + Emmen Drenthe 7801 CC + NL + +C0-8B-6F (hex) S I Sistemas Inteligentes Eletrônicos Ltda +C08B6F (base 16) S I Sistemas Inteligentes Eletrônicos Ltda + Rua Amadeu Piotto 161 + Curitiba Paraná 81280020 + BR + +F8-6E-CF (hex) Arcx Inc +F86ECF (base 16) Arcx Inc + 151 Amber St, Unit 1 + Markham ON L3R 3B3 + CA + +8C-84-01 (hex) Private +8C8401 (base 16) Private + +40-84-93 (hex) Clavister AB +408493 (base 16) Clavister AB + Sjogatan 6J + Ornskoldsvik 89160 + SE + +78-A6-BD (hex) DAEYEON Control&Instrument Co,.Ltd +78A6BD (base 16) DAEYEON Control&Instrument Co,.Ltd + ACETECHNOTOWER 2-108, 197-7, Guro3-Dong, Guro-Gu, + Seoul 152-766 + KR + +3C-19-15 (hex) GFI Chrono Time +3C1915 (base 16) GFI Chrono Time + 121 rue des Guillees + CHAURAY 79180 + FR + +EC-B1-06 (hex) Acuro Networks, Inc +ECB106 (base 16) Acuro Networks, Inc + 42808 Christy St., Suite 100 + Fremont CA 94538 + US + +C8-35-B8 (hex) Ericsson, EAB/RWI/K +C835B8 (base 16) Ericsson, EAB/RWI/K + Skolgången 17 + SE-800 06 + SE + +F8-9D-0D (hex) Control Technology Inc. +F89D0D (base 16) Control Technology Inc. + 7608 North Hudson Ave + Oklahoma City OK 73116 + US + +2C-3F-3E (hex) Alge-Timing GmbH +2C3F3E (base 16) Alge-Timing GmbH + Rotkreuzstrasse 39 + Lustenau 6890 + AT + +08-9F-97 (hex) LEROY AUTOMATION +089F97 (base 16) LEROY AUTOMATION + 35, Boulevard du Libre Echange + Saint Orens de Gameville 31650 + FR + +34-BA-51 (hex) Se-Kure Controls, Inc. +34BA51 (base 16) Se-Kure Controls, Inc. + 3714 Runge Street + Franklin Park IL 60131 + US + +6C-70-39 (hex) Novar GmbH +6C7039 (base 16) Novar GmbH + Johannes-Mauthe-Str. 14 + Albstadt Baden-Württemberg 72458 + DE + +98-2D-56 (hex) Resolution Audio +982D56 (base 16) Resolution Audio + 88 Hoff Street #106 + San Francisco CA 94110 + US + +14-73-73 (hex) TUBITAK UEKAE +147373 (base 16) TUBITAK UEKAE + ANIBAL ST. + KOCAELI 41470 + TR + +FC-CF-62 (hex) IBM Corp +FCCF62 (base 16) IBM Corp + 2051 Mission College Blvd + Santa Clara CA 95054 + US + +08-4E-1C (hex) H2A Systems, LLC +084E1C (base 16) H2A Systems, LLC + 7545 Irvine Center Drive + Irvine CA 92618 + US + +88-B6-27 (hex) Gembird Europe BV +88B627 (base 16) Gembird Europe BV + Wittevrouwen 56 + Almere Flevoland 1358CD + NL + +F0-68-53 (hex) Integrated Corporation +F06853 (base 16) Integrated Corporation + 3/F, Shun On Commercial Bldg., + Cetnral, + HK + +A4-AD-B8 (hex) Vitec Group, Camera Dynamics Ltd +A4ADB8 (base 16) Vitec Group, Camera Dynamics Ltd + William Vinten Building + Bury St Edmunds Suffolk IP33 3TB + GB + +A4-B1-21 (hex) Arantia 2010 S.L. +A4B121 (base 16) Arantia 2010 S.L. + Volta do Castro s/n + Santiago de Compostela A Coruña 15706 + ES + +E0-26-36 (hex) Nortel Networks +E02636 (base 16) Nortel Networks + CARRETERA BASE AEREA # 5850 + Zapopan Jalisco 44130 + MX + +5C-57-C8 (hex) Nokia Corporation +5C57C8 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +D4-6C-BF (hex) Goodrich ISR +D46CBF (base 16) Goodrich ISR + 6600 Gulton Crt + Albuquerque NM 87109 + US + +E0-26-30 (hex) Intrigue Technologies, Inc. +E02630 (base 16) Intrigue Technologies, Inc. + 800 Old Pond Road + Bridgeville PA 15017 + US + +EC-C8-82 (hex) Cisco Systems, Inc +ECC882 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +6C-FD-B9 (hex) Proware Technologies Co Ltd. +6CFDB9 (base 16) Proware Technologies Co Ltd. + 2nd F1 East Wing,South Section,Factory Building 24,Science&Technology Park + Shenzhen Guangdong 518000 + CN + +10-18-9E (hex) Elmo Motion Control +10189E (base 16) Elmo Motion Control + 64 Gisin St. + Petach Tikva 49103 + IL + +8C-56-C5 (hex) Nintendo Co., Ltd. +8C56C5 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +CC-B8-88 (hex) AnB Securite s.a. +CCB888 (base 16) AnB Securite s.a. + Rue de Joie,38-40 + Liege 4000 + BE + +6C-5E-7A (hex) Ubiquitous Internet Telecom Co., Ltd +6C5E7A (base 16) Ubiquitous Internet Telecom Co., Ltd + #512, 5th Floor, Kolon Digital Valley,Guro 3(sam)-dong, Guro-gu + Seoul 152-777 + KR + +B4-2C-BE (hex) Direct Payment Solutions Limited +B42CBE (base 16) Direct Payment Solutions Limited + 98 Anzac Avenue + Auckland 1035 + NZ + +CC-22-18 (hex) InnoDigital Co., Ltd. +CC2218 (base 16) InnoDigital Co., Ltd. + No.310 3F Kofomo Tower + Sungnam-city Kyunggi-do 463-825 + KR + +C8-6C-1E (hex) Display Systems Ltd +C86C1E (base 16) Display Systems Ltd + 16-Parkovaja Street 26 + Moscow 105484 + RU + +A0-18-59 (hex) Shenzhen Yidashi Electronics Co Ltd +A01859 (base 16) Shenzhen Yidashi Electronics Co Ltd + Building A10, Fukang Industrial Zone + Shenzhen Guangdong 518110 + CN + +E8-05-6D (hex) Nortel Networks +E8056D (base 16) Nortel Networks + CARRETERA BASE AEREA # 5850 + Zapopan Jalisco 44130 + MX + +C4-59-76 (hex) Fugoo Coorporation +C45976 (base 16) Fugoo Coorporation + 8001 Irvine Center Drive + Irvine CA 62618 + US + +90-A7-C1 (hex) Pakedge Device and Software Inc. +90A7C1 (base 16) Pakedge Device and Software Inc. + 1011 Edwards Road + Burlingame CA 94010 + US + +80-BA-AC (hex) TeleAdapt Ltd +80BAAC (base 16) TeleAdapt Ltd + Axis 5 + Watford Hertfordshire WD244YW + GB + +50-2D-F4 (hex) Phytec Messtechnik GmbH +502DF4 (base 16) Phytec Messtechnik GmbH + Robert-Koch-Straße 39 + Mainz Rheinland-Pfalz 55129 + DE + +2C-CD-27 (hex) Precor Inc +2CCD27 (base 16) Precor Inc + 20031 142nd Avenue NE + Woodinville WA 98072 + US + +10-43-69 (hex) Soundmax Electronic Limited +104369 (base 16) Soundmax Electronic Limited + Room#1505, Oriental plaza, #1072 JianShe Road + SHENZHEN Guangdong 518001 + CN + +C0-6C-0F (hex) Dobbs Stanford +C06C0F (base 16) Dobbs Stanford + 2715 Electronic Lane + Dallas Texas 75220 + US + +C8-6C-B6 (hex) Optcom Co., Ltd. +C86CB6 (base 16) Optcom Co., Ltd. + 792-3 Tomigaoka + Iwata Shizuoka 438-0803 + JP + +58-49-BA (hex) Chitai Electronic Corp. +5849BA (base 16) Chitai Electronic Corp. + 5F., No. 1 Lane 123, Pao-Chung Rd., Hsin-Tien City + Taiepi 23144 + TW + +00-D1-1C (hex) ACETEL +00D11C (base 16) ACETEL + #1006, World Merdian 2-cha, 426-5, + Seoul 153-759 + KR + +60-1D-0F (hex) Midnite Solar +601D0F (base 16) Midnite Solar + 17722 67th Ave NE #C + Arlington WA 98223 + US + +A8-F9-4B (hex) Eltex Enterprise Ltd. +A8F94B (base 16) Eltex Enterprise Ltd. + Okruzhnaya st. 29v + Novosibirsk 630020 + RU + +0C-82-30 (hex) SHENZHEN MAGNUS TECHNOLOGIES CO.,LTD +0C8230 (base 16) SHENZHEN MAGNUS TECHNOLOGIES CO.,LTD + c-504,Skyworth Building,No.8 Road,High-tech south,Nanshan District, + Shenzhen Guangdong 518057 + CN + +74-6B-82 (hex) MOVEK +746B82 (base 16) MOVEK + 6517 Navaho Trail + Edina Minnesota 55439 + US + +9C-C0-77 (hex) PrintCounts, LLC +9CC077 (base 16) PrintCounts, LLC + 5109 W Lemon St + Tampa FL 33609 + US + +3C-B1-7F (hex) Wattwatchers Pty Ld +3CB17F (base 16) Wattwatchers Pty Ld + 22 Woodbury Rd St. Ives + Sydney NSW 2075 + AU + +CC-54-59 (hex) OnTime Networks AS +CC5459 (base 16) OnTime Networks AS + Gladsvei 20 + Oslo 0489 + NO + +F8-DC-7A (hex) Variscite LTD +F8DC7A (base 16) Variscite LTD + 60 Medinat Hayehudim st. + Hertzelia 46722 + IL + +D4-F1-43 (hex) IPROAD.,Inc +D4F143 (base 16) IPROAD.,Inc + #505 Byuksan digital valley 7, 170-13, + Seoul 152-847 + KR + +B8-F7-32 (hex) Aryaka Networks Inc +B8F732 (base 16) Aryaka Networks Inc + 691 S. Milpitas Blvd., + Milpitas CA 95035 + US + +E8-DF-F2 (hex) PRF Co., Ltd. +E8DFF2 (base 16) PRF Co., Ltd. + #510, Leaders B/D, Yatop-dong + Seongnam-city Gyeonggi-do 463-828 + KR + +B4-ED-54 (hex) Wohler Technologies +B4ED54 (base 16) Wohler Technologies + 31055 Huntwood Avenue + Hayward CA 94544 + US + +00-64-40 (hex) Cisco Systems, Inc +006440 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +94-C4-E9 (hex) PowerLayer Microsystems HongKong Limited +94C4E9 (base 16) PowerLayer Microsystems HongKong Limited + 23 Zhichun Rd,Liangziyinzuo Rm1009 + Beijing 100083 + CN + +88-43-E1 (hex) Cisco Systems, Inc +8843E1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +34-86-2A (hex) Heinz Lackmann GmbH & Co KG +34862A (base 16) Heinz Lackmann GmbH & Co KG + Harkortstraße 15 + Münster NRW 48163 + DE + +AC-E3-48 (hex) MadgeTech, Inc +ACE348 (base 16) MadgeTech, Inc + 879 Maple St + Contoocook NH 03229 + US + +54-9A-16 (hex) Uzushio Electric Co.,Ltd. +549A16 (base 16) Uzushio Electric Co.,Ltd. + 105 + Imabari-city Ehime pref. 7948582 + JP + +90-18-AE (hex) Shanghai Meridian Technologies, Co. Ltd. +9018AE (base 16) Shanghai Meridian Technologies, Co. Ltd. + Suite 6A Tongsheng Tower + Pudong shanghai 200122 + CN + +04-94-A1 (hex) CATCH THE WIND INC +0494A1 (base 16) CATCH THE WIND INC + 10781 JAMES PAYNE COURT + MANASSAS VA 20110 + US + +00-3A-99 (hex) Cisco Systems, Inc +003A99 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-3A-9A (hex) Cisco Systems, Inc +003A9A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-3A-98 (hex) Cisco Systems, Inc +003A98 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +50-A6-E3 (hex) David Clark Company +50A6E3 (base 16) David Clark Company + 360 Franklin St. + Worcester MA 01615 + US + +50-93-4F (hex) Gradual Tecnologia Ltda. +50934F (base 16) Gradual Tecnologia Ltda. + Rua Attilio Giaretta, 110 + Itatiba SP 13257-584 + BR + +B8-B1-C7 (hex) BT&COM CO.,LTD +B8B1C7 (base 16) BT&COM CO.,LTD + #1103, E&C Venture Dream Tower II + Seoul 152-719 + KR + +DC-2C-26 (hex) Iton Technology Limited +DC2C26 (base 16) Iton Technology Limited + Room 10E, JingFeng Building, + ShenZhen GuangDong 518034 + CN + +D4-11-D6 (hex) ShotSpotter, Inc. +D411D6 (base 16) ShotSpotter, Inc. + 1060 Terra Bella Ave. + Mountain View CA 94043 + US + +9C-AF-CA (hex) Cisco Systems, Inc +9CAFCA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +1C-0F-CF (hex) Sypro Optics GmbH +1C0FCF (base 16) Sypro Optics GmbH + Carl-Zeiss-Promenade 10 + Jena Thuringia 07745 + DE + +9C-4E-8E (hex) ALT Systems Ltd +9C4E8E (base 16) ALT Systems Ltd + PoBox 17 + Helsinki 00761 + FI + +70-72-CF (hex) EdgeCore Networks +7072CF (base 16) EdgeCore Networks + 20 Mason + Irvine CA 92618 + US + +EC-D0-0E (hex) MiraeRecognition Co., Ltd. +ECD00E (base 16) MiraeRecognition Co., Ltd. + PrimeBank Bldg. Annex-3F, #278-3 + Seoul 135-833 + KR + +A4-AD-00 (hex) Ragsdale Technology +A4AD00 (base 16) Ragsdale Technology + 505 Echo Lane + Big Bear Lake CA 92315 + US + +4C-9E-E4 (hex) Hanyang Navicom Co.,Ltd. +4C9EE4 (base 16) Hanyang Navicom Co.,Ltd. + 713, Gwanpyeong-dong, Yusung-gu + Daejeon 305-509 + KR + +C8-72-48 (hex) Aplicom Oy +C87248 (base 16) Aplicom Oy + Rautatienkatu 56 + Äänekoski Länsi-Suomi 44101 + FI + +C4-7D-4F (hex) Cisco Systems, Inc +C47D4F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +3C-DF-1E (hex) Cisco Systems, Inc +3CDF1E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +98-6D-C8 (hex) TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION +986DC8 (base 16) TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORPORATION + TOKYO SQUARE GARDEN + 3-1-1 Kyobashi, CHUO-KU Tokyo 104-0031 + JP + +6C-AC-60 (hex) Venetex Corp +6CAC60 (base 16) Venetex Corp + 8-3-9,Shin-machi + Ome-shi, Tokyo 198-0024 + JP + +F0-4B-F2 (hex) JTECH Communications, Inc. +F04BF2 (base 16) JTECH Communications, Inc. + 6413 Congress Ave. + Boca Raton FL 33487 + US + +04-2B-BB (hex) PicoCELA, Inc. +042BBB (base 16) PicoCELA, Inc. + 3-8-33, Momochihama + Fukuoka-city Fukuoka 814-0001 + JP + +FC-08-77 (hex) Prentke Romich Company +FC0877 (base 16) Prentke Romich Company + 1022 Heyl Rd + Wooster OH 44691 + US + +64-F9-70 (hex) Kenade Electronics Technology Co.,LTD. +64F970 (base 16) Kenade Electronics Technology Co.,LTD. + F/G room,11/F,Hangdu building,Huafu Rd, Futian district, + ShenZhen GuangDong 518028 + CN + +C8-2E-94 (hex) Halfa Enterprise Co., Ltd. +C82E94 (base 16) Halfa Enterprise Co., Ltd. + 5F, No.102, Ming Chuan Road + Hsin Tien Taipei County 23141 + TW + +80-17-7D (hex) Nortel Networks +80177D (base 16) Nortel Networks + CARRETERA BASE AEREA # 5850 + Zapopan Jalisco 44130 + MX + +7C-7B-E4 (hex) Z'SEDAI KENKYUSHO CORPORATION +7C7BE4 (base 16) Z'SEDAI KENKYUSHO CORPORATION + Meikai sannomiya 2nd Bldg. 11th/fl. + Kobe Hyogo 650-0034 + JP + +F0-DE-71 (hex) Shanghai EDO Technologies Co.,Ltd. +F0DE71 (base 16) Shanghai EDO Technologies Co.,Ltd. + Unit 12302, Building 12,498 Guoshoujing Road, Pudong New Area + Shanghai 201203 + CN + +60-D3-0A (hex) Quatius Limited +60D30A (base 16) Quatius Limited + Units 05-07, 16/F, Greenfield Tower, Concordia Plaza, + Kowloon + HK + +24-CF-21 (hex) Shenzhen State Micro Technology Co., Ltd +24CF21 (base 16) Shenzhen State Micro Technology Co., Ltd + SSMEC Building2/F, Gao Xin Nan First Avenue, Hi-Tech Park South, Nanshan + Shenzhen City Guangdong Province 518057 + CN + +10-BA-A5 (hex) GANA I&C CO., LTD +10BAA5 (base 16) GANA I&C CO., LTD + 154-17 kyoungdong B/D 3F karak-dong songpa-gu + Seoul Korea 138-160 + KR + +BC-9D-A5 (hex) DASCOM Europe GmbH +BC9DA5 (base 16) DASCOM Europe GmbH + Heuweg 3 + Ulm Baden-Württemberg 89079 + DE + +28-FB-D3 (hex) Ragentek Technology Group +28FBD3 (base 16) Ragentek Technology Group + D10/D11,No.3188, Xiupu Road, PuDong District, Shanghai + Shanghai 201703 + CN + +58-6E-D6 (hex) Private +586ED6 (base 16) Private + +EC-30-91 (hex) Cisco Systems, Inc +EC3091 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +64-BC-11 (hex) CombiQ AB +64BC11 (base 16) CombiQ AB + Science Park + Jonkoping 553 18 + SE + +C8-C1-3C (hex) RuggedTek Hangzhou Co., Ltd +C8C13C (base 16) RuggedTek Hangzhou Co., Ltd + Zhejiang University National Science Park + Hangzhou Zhejiang 310013 + CN + +F4-AC-C1 (hex) Cisco Systems, Inc +F4ACC1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +40-97-D1 (hex) BK Electronics cc +4097D1 (base 16) BK Electronics cc + 150 Swaardlelie Ave + Pretoria Gauteng 0184 + ZA + +0C-E9-36 (hex) ELIMOS srl +0CE936 (base 16) ELIMOS srl + Area Science Park - Padriciano 99 + TRIESTE 34149 + IT + +A0-2E-F3 (hex) United Integrated Services Co., Led. +A02EF3 (base 16) United Integrated Services Co., Led. + 5F No 3 Lane 7 Packao Road Hsintien + Taipei Hsien 23144 + TW + +A0-98-05 (hex) OpenVox Communication Co Ltd +A09805 (base 16) OpenVox Communication Co Ltd + F2,Building No.14,Shangsha Science & + ShenZhen GuangDong 518031 + CN + +60-39-1F (hex) ABB Ltd +60391F (base 16) ABB Ltd + Distribution Automation + Vadodara Gujarat 390013 + IN + +E8-A4-C1 (hex) Deep Sea Electronics Ltd +E8A4C1 (base 16) Deep Sea Electronics Ltd + Highfield House + Hunmanby North Yorkshire YO14 0PH + GB + +C8-D2-C1 (hex) Jetlun (Shenzhen) Corporation +C8D2C1 (base 16) Jetlun (Shenzhen) Corporation + 1008A Skyworth Building, Gao-xin Rd South + Shenzhen 518057 + CN + +E0-91-53 (hex) XAVi Technologies Corp. +E09153 (base 16) XAVi Technologies Corp. + 9F., No129, Xingde RD.,Sanchong Dist., + New Taipei Taiwan 24158 + TW + +88-A5-BD (hex) QPCOM INC. +88A5BD (base 16) QPCOM INC. + 6030 NW 99 AVE + DORAL FLORIDA 33178 + US + +D4-C7-66 (hex) Acentic GmbH +D4C766 (base 16) Acentic GmbH + Venloer Strasse 151-153 + Cologne 50672 + DE + +00-27-12 (hex) MaxVision LLC +002712 (base 16) MaxVision LLC + 495 Production Ave + Madison AL 35758 + US + +00-27-1F (hex) MIPRO Electronics Co., Ltd +00271F (base 16) MIPRO Electronics Co., Ltd + 814,Peikang Road + Chiayi 60096 + TW + +00-27-0C (hex) Cisco Systems, Inc +00270C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-26-CF (hex) DEKA R&D +0026CF (base 16) DEKA R&D + 340 Commercial Street + Manchester NH 03101 + US + +00-26-E7 (hex) Shanghai ONLAN Communication Tech. Co., Ltd. +0026E7 (base 16) Shanghai ONLAN Communication Tech. Co., Ltd. + 3F, 6C, No. 1658, Gumei Road, Xuhui District + Shanghai 200233 + CN + +00-26-E0 (hex) ASITEQ +0026E0 (base 16) ASITEQ + 5F, DONGYOUNG Bldg,382-6,Yatap dong + Sung Nam si Kyounggi-do 463-827 + KR + +00-27-03 (hex) Testech Electronics Pte Ltd +002703 (base 16) Testech Electronics Pte Ltd + Block 118, #05-110, + Singapore 380118 + SG + +00-26-F3 (hex) SMC Networks +0026F3 (base 16) SMC Networks + 20 Mason + Irvine CA 92618 + US + +00-26-A5 (hex) MICROROBOT.CO.,LTD +0026A5 (base 16) MICROROBOT.CO.,LTD + 167-3 Gungpyeong-ri + Gwangju-si Gyeonggi-Do 464-881 + KR + +00-26-A3 (hex) FQ Ingenieria Electronica S.A. +0026A3 (base 16) FQ Ingenieria Electronica S.A. + Avda. Roquetes 9 + Sant Pere de Ribes Barcelona 08812 + ES + +00-26-9D (hex) M2Mnet Co., Ltd. +00269D (base 16) M2Mnet Co., Ltd. + 607 Downtown Bld. 1043-1 Hogye-Dong Dongan-Gu + Anyang-City Kyunggi-Do 431-080 + KR + +00-26-97 (hex) Alpha Technologies Inc. +002697 (base 16) Alpha Technologies Inc. + 3767 Alpha Way + Bellingham WA 98226 + US + +00-26-8A (hex) Terrier SC Ltd +00268A (base 16) Terrier SC Ltd + Strettit Farm + East Peckham Kent TN12 5EE + GB + +00-26-89 (hex) General Dynamics Robotic Systems +002689 (base 16) General Dynamics Robotic Systems + 1231 Tech Court + Westminster MD 21157 + US + +00-26-C5 (hex) Guangdong Gosun Telecommunications Co.,Ltd +0026C5 (base 16) Guangdong Gosun Telecommunications Co.,Ltd + Guangdong software park D, No.11, CaiPing road , Guangzhou science city + Guangzhou Guangdong 510663 + CN + +00-26-C4 (hex) Cadmos microsystems S.r.l. +0026C4 (base 16) Cadmos microsystems S.r.l. + Via Pietro Frattini, 255 + Roma 00149 + IT + +00-26-C8 (hex) System Sensor +0026C8 (base 16) System Sensor + 3825 Ohio Avenue + Saint Charles IL 60174 + US + +00-26-7A (hex) wuhan hongxin telecommunication technologies co.,ltd +00267A (base 16) wuhan hongxin telecommunication technologies co.,ltd + No.5 Donxin Road,Wuhan East Lake High-Tech Development Zone + Wuhan Hubei 430073 + CN + +00-26-C2 (hex) SCDI Co. LTD +0026C2 (base 16) SCDI Co. LTD + #451, Hagal-Dong, Giheung-Gu, + Yongin-Si Gyeonggi-Do 446-930 + KR + +00-26-85 (hex) Digital Innovation +002685 (base 16) Digital Innovation + Travbaneveien 6 + Trondheim 7044 + NO + +00-26-A9 (hex) Strong Technologies Pty Ltd +0026A9 (base 16) Strong Technologies Pty Ltd + 60 Wedgewood Road + Hallam Victoria 3803 + AU + +00-26-72 (hex) AAMP of America +002672 (base 16) AAMP of America + 13190 56th Court + Clearwater Florida 33760 + US + +00-25-FD (hex) OBR Centrum Techniki Morskiej S.A. +0025FD (base 16) OBR Centrum Techniki Morskiej S.A. + Dickmana 62 + Gdynia 81-109 + US + +00-26-00 (hex) TEAC Australia Pty Ltd. +002600 (base 16) TEAC Australia Pty Ltd. + 75 Northgate Drive + Thomastown Victoria 3074 + AU + +00-25-FF (hex) CreNova Multimedia Co., Ltd +0025FF (base 16) CreNova Multimedia Co., Ltd + 7/F, Hana EZ Tower, Gumi-Dong 10, Sungnam Rd 43, + Sungnam-Si Kyunggi-Do 463-870 + KR + +00-26-04 (hex) Audio Processing Technology Ltd +002604 (base 16) Audio Processing Technology Ltd + Whiterock Business Park + Belfast BT12 7FP + GB + +00-26-59 (hex) Nintendo Co., Ltd. +002659 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-26-51 (hex) Cisco Systems, Inc +002651 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-26-12 (hex) Space Exploration Technologies +002612 (base 16) Space Exploration Technologies + 1 Rocket Road + Hawthorne CA 90250 + US + +00-26-16 (hex) Rosemount Inc. +002616 (base 16) Rosemount Inc. + 8200 Market Boulevard + Chanhassen MN 55317 + US + +00-26-0B (hex) Cisco Systems, Inc +00260B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-26-23 (hex) JRD Communication Inc +002623 (base 16) JRD Communication Inc + 16/F, TCL Tower, Gaoxin Nanyi Road, Nanshan District + Shenzhen Guangdong 518057 + CN + +00-26-27 (hex) Truesell +002627 (base 16) Truesell + 301 Sungyun Bldg, 89-2 + Seocho-gu, Seoul 137-130 + KR + +00-26-4E (hex) Rail & Road Protec GmbH +00264E (base 16) Rail & Road Protec GmbH + Norderhofenden 12-13 + Flensburg 24937 + DE + +00-26-4F (hex) Krüger &Gothe GmbH +00264F (base 16) Krüger &Gothe GmbH + Atzendorfer Straße 19 + Staßfurt Sachsen Anhalt 39418 + DE + +00-26-21 (hex) InteliCloud Technology Inc. +002621 (base 16) InteliCloud Technology Inc. + 895 Dove St. + Newport Beach CA 92660 + US + +00-26-1C (hex) NEOVIA INC. +00261C (base 16) NEOVIA INC. + 503 LOTTE IT CASTLE 1DONG,550-1 + SEOUL 153-768 + KR + +00-26-64 (hex) Core System Japan +002664 (base 16) Core System Japan + Bunshu Bldg,2-27-6,Myojin + Hachioji Tokyo 1920046 + JP + +00-26-39 (hex) T.M. Electronics, Inc. +002639 (base 16) T.M. Electronics, Inc. + 45 Main St + Boylston MA 01505 + US + +00-25-C6 (hex) kasercorp, ltd +0025C6 (base 16) kasercorp, ltd + South 20,Gaobu Road,Gaobu Town + Dongwan Guangdong 523000 + CN + +00-25-C5 (hex) Star Link Communication Pvt. Ltd. +0025C5 (base 16) Star Link Communication Pvt. Ltd. + HR114/6 & Hr132/6, Pulprehladpur, + New Delhi 110044 + IN + +00-25-C7 (hex) altek Corporation +0025C7 (base 16) altek Corporation + 3F, No. 10, Li-Hsin Road, Science-Based Industrial Park, + Hsinchu + TW + +00-25-E6 (hex) Belgian Monitoring Systems bvba +0025E6 (base 16) Belgian Monitoring Systems bvba + Th. Sevenslaan 106 + Kortrijk WVL 8500 + BE + +00-25-E0 (hex) CeedTec Sdn Bhd +0025E0 (base 16) CeedTec Sdn Bhd + 303-4-5, Krystal Point Business Center + Bayan Lepas Penang 11900 + MY + +00-25-DE (hex) Probits Co., LTD. +0025DE (base 16) Probits Co., LTD. + #1502, Kolon Science Valley II, 811 + Seoul 152-878 + KR + +00-25-B0 (hex) Schmartz Inc +0025B0 (base 16) Schmartz Inc + 2307 Valerian Trl + Round Rock TX 78665 + US + +00-25-AD (hex) Manufacturing Resources International +0025AD (base 16) Manufacturing Resources International + 6415 Shiloh Road East + Alpharetta GA 30005 + US + +00-25-AC (hex) I-Tech corporation +0025AC (base 16) I-Tech corporation + 1-15 Shin-ogawa machi + Shinjyuku-ku Tokyo 162-0814 + JP + +00-25-AB (hex) AIO LCD PC BU / TPV +0025AB (base 16) AIO LCD PC BU / TPV + 10F., No., 230, Liancheng Rd. + Zhonghe City Taipei Taiwan 23553 + TW + +00-25-EC (hex) Humanware +0025EC (base 16) Humanware + 445 rue du Parc Industriel + Longueuil Québec J4H 3V7 + CA + +00-25-ED (hex) NuVo Technologies LLC +0025ED (base 16) NuVo Technologies LLC + 3015 Kustom Drive + Hebron KY 41048 + US + +00-25-E9 (hex) i-mate Development, Inc. +0025E9 (base 16) i-mate Development, Inc. + 8383 158th Ave. N.E., Suite 300, Redmond, + Washington WA 98052-3871 + US + +00-25-BA (hex) Alcatel-Lucent IPD +0025BA (base 16) Alcatel-Lucent IPD + 701 E. Middlefield Rd. + Mountain View CA 94043 + US + +00-25-BB (hex) INNERINT Co., Ltd. +0025BB (base 16) INNERINT Co., Ltd. + Dongyoung CentralTower #202, Geumjung-dong, + Gunpo-si Kyunggi-do 430050 + KR + +00-25-B8 (hex) Agile Communications, Inc. +0025B8 (base 16) Agile Communications, Inc. + 810 Lawrence Dr + Thousand Oaks California 91320 + US + +00-25-B1 (hex) Maya-Creation Corporation +0025B1 (base 16) Maya-Creation Corporation + 3F, Building M-10, Centre od Hi-Tech Ind. Dist. + Shenzhen 518057 + CN + +00-25-A1 (hex) Enalasys +0025A1 (base 16) Enalasys + 250 Avenida Campillo + Calexico California 92231 + US + +00-25-F3 (hex) Nordwestdeutsche Zählerrevision +0025F3 (base 16) Nordwestdeutsche Zählerrevision + Ing. Aug. Knemeyer GmbH & Co. KG + Bad Laer Niedersachsen 49196 + DE + +00-25-DD (hex) SUNNYTEK INFORMATION CO., LTD. +0025DD (base 16) SUNNYTEK INFORMATION CO., LTD. + 12F, NO. 88, HSIN-TE ROAD + TAIPEI HSIEN 241 + TW + +00-25-CE (hex) InnerSpace +0025CE (base 16) InnerSpace + PO Box 2186 + Grand Rapids MI 49501 + US + +00-25-49 (hex) Jeorich Tech. Co.,Ltd. +002549 (base 16) Jeorich Tech. Co.,Ltd. + 4F., No.6, Ln. 70, Sec. 2, Academia Rd., Nangang District, Taipei City 115, Taiwan (R.O.C.) + Taipei Taiwan 110 + TW + +00-25-39 (hex) IfTA GmbH +002539 (base 16) IfTA GmbH + Industriestraße 33 + Groebenzell Bavaria 82194 + DE + +00-25-37 (hex) Runcom Technologies Ltd. +002537 (base 16) Runcom Technologies Ltd. + 11 Moshe Levi Str. 11th Flr. + Rishon Le Zion 75658 + IL + +00-25-38 (hex) Samsung Electronics Co., Ltd., Memory Division +002538 (base 16) Samsung Electronics Co., Ltd., Memory Division + San #16 Banwol-Dong, Taean-Gu + Hwasung City Gyeonggi Do 445-701 + KR + +00-25-44 (hex) LoJack Corporation +002544 (base 16) LoJack Corporation + 780 Dedham Street + Canton MA 02021 + US + +00-25-32 (hex) Digital Recorders +002532 (base 16) Digital Recorders + 4018 Patriot Drive + Durham NC 27709 + US + +00-25-5D (hex) Morningstar Corporation +00255D (base 16) Morningstar Corporation + 10611 Iron Bridge Road + Jessup MD 20794 + US + +00-25-58 (hex) MPEDIA +002558 (base 16) MPEDIA + Shinyoung Tower 12F 246-2 + Seongnam Gyeonggi-do 463-824 + KR + +00-25-4A (hex) RingCube Technologies, Inc. +00254A (base 16) RingCube Technologies, Inc. + 100 West Evelyn Ave, Suite 210 + Mountain View CA 94041 + US + +00-25-4F (hex) ELETTROLAB Srl +00254F (base 16) ELETTROLAB Srl + Via Dell'Industria 25 + San Vendemiano Treviso 31020 + IT + +00-25-83 (hex) Cisco Systems, Inc +002583 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-25-91 (hex) NEXTEK, Inc. +002591 (base 16) NEXTEK, Inc. + 410 Douglass Street + Reading PA 19601 + US + +00-25-8D (hex) Haier +00258D (base 16) Haier + No.1,Haier Road + Qingdao Shandong 266101 + CN + +00-25-71 (hex) Zhejiang Tianle Digital Electric Co.,Ltd +002571 (base 16) Zhejiang Tianle Digital Electric Co.,Ltd + No.8 Tianle Rd,Economic Development Zone + Shengzhou Zhejiang 312400 + CN + +00-25-9A (hex) CEStronics GmbH +00259A (base 16) CEStronics GmbH + Friedrichstraße 243 + Velbert 42551 + DE + +00-25-02 (hex) NaturalPoint +002502 (base 16) NaturalPoint + PO Box 2317 + Corvallis OR 97339 + US + +00-24-F8 (hex) Technical Solutions Company Ltd. +0024F8 (base 16) Technical Solutions Company Ltd. + Box 31750 + Whitehorse Yukon Y1A 6L3 + CA + +00-24-F9 (hex) Cisco Systems, Inc +0024F9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-F2 (hex) Uniphone Telecommunication Co., Ltd. +0024F2 (base 16) Uniphone Telecommunication Co., Ltd. + No. 25, Chu-Kung 3rd Lane, Chu-Hou Tsung, Jen-Wu Hsiang, + Kaohsiung Hsien 81448 + TW + +00-25-14 (hex) PC Worth Int'l Co., Ltd. +002514 (base 16) PC Worth Int'l Co., Ltd. + 18F, No.100, Sec. 1, Xintai 5th Rd., Xizhi Dist., + New Taipei City Taipei 22102 + TW + +00-25-0B (hex) CENTROFACTOR INC +00250B (base 16) CENTROFACTOR INC + Road Town, Tortola, P.O.Box 3161, + Tortola 194295 + VG + +00-25-06 (hex) A.I. ANTITACCHEGGIO ITALIA SRL +002506 (base 16) A.I. ANTITACCHEGGIO ITALIA SRL + VICOLO DELLE DAME 4 + BOLOGNA 40124 + IT + +00-25-1C (hex) EDT +00251C (base 16) EDT + 1400 SW Compton + Beaverton OR 97008 + US + +00-25-1A (hex) Psiber Data Systems Inc. +00251A (base 16) Psiber Data Systems Inc. + 7075-K Mission Gorge Rd + San Diego CA 92120 + US + +00-24-E1 (hex) Convey Computer Corp. +0024E1 (base 16) Convey Computer Corp. + 1302 E. Collins Blvd. + Richardson TX 75081 + US + +00-24-EE (hex) Wynmax Inc. +0024EE (base 16) Wynmax Inc. + 18F., No. 75, Sec. 1, XinTai 5th Rd., + Xizhi City, Taipei County 221 + TW + +00-24-E3 (hex) CAO Group +0024E3 (base 16) CAO Group + 4628 West Skyhawk Drive + West Jordan UT 84084 + US + +00-25-07 (hex) ASTAK Inc. +002507 (base 16) ASTAK Inc. + 1911 Hartog Drive + San Jose CA 95131 + US + +00-24-D9 (hex) BICOM, Inc. +0024D9 (base 16) BICOM, Inc. + 755 Main Street + Monroe CT 06468 + US + +00-24-8E (hex) Infoware ZRt. +00248E (base 16) Infoware ZRt. + Huseg u. 10/a + Budapest 1223 + HU + +00-24-94 (hex) Shenzhen Baoxin Tech CO., Ltd. +002494 (base 16) Shenzhen Baoxin Tech CO., Ltd. + 6F Huale BLDG., Zhonghangbei Rd., + Shenzhen GuangDong 518028 + CN + +00-24-89 (hex) Vodafone Omnitel N.V. +002489 (base 16) Vodafone Omnitel N.V. + Via Jervis 13 + 10015 Ivrea Torino + IT + +00-24-6F (hex) Onda Communication spa +00246F (base 16) Onda Communication spa + via del lavoro 9 + pordenone 33170 + IT + +00-24-69 (hex) Smart Doorphones +002469 (base 16) Smart Doorphones + Klipsenstraat 18A + Lokeren 9160 + BE + +00-24-7F (hex) Nortel Networks +00247F (base 16) Nortel Networks + 2221 Lakeside Blvd + Richardson TX 75081 + US + +00-24-75 (hex) Compass System(Embedded Dept.) +002475 (base 16) Compass System(Embedded Dept.) + 1403 ACE TechnoTower 8th + Seoul 152-050 + KR + +00-24-C3 (hex) Cisco Systems, Inc +0024C3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-B5 (hex) Nortel Networks +0024B5 (base 16) Nortel Networks + 2221 Lakeside Blvd + Richardson TX 75081 + US + +00-24-B0 (hex) ESAB AB +0024B0 (base 16) ESAB AB + Box 8004 + Göteborg SE-402 77 + SE + +00-24-C4 (hex) Cisco Systems, Inc +0024C4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-9D (hex) NES Technology Inc. +00249D (base 16) NES Technology Inc. + #205 ACE Technotower 10, 470-5 Gasan-dong + Seoul 153-789 + KR + +00-24-64 (hex) Bridge Technologies Co AS +002464 (base 16) Bridge Technologies Co AS + Mølleparken 4 + Oslo 0459 + NO + +00-24-62 (hex) Rayzone Corporation +002462 (base 16) Rayzone Corporation + #2008, B-Dong, Samho BLDG + Seoul 137-941 + KR + +00-24-20 (hex) NetUP Inc. +002420 (base 16) NetUP Inc. + Olof Palme st., 1, sect. 7 + Moscow 119311 + RU + +00-24-1E (hex) Nintendo Co., Ltd. +00241E (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-24-1F (hex) DCT-Delta GmbH +00241F (base 16) DCT-Delta GmbH + Bodanrückstraße 1 + Bodman - Ludwigshafen Baden-Württemberg 78351 + DE + +00-24-0E (hex) Inventec Besta Co., Ltd. +00240E (base 16) Inventec Besta Co., Ltd. + 10FL, No.36, Lane 513, Rui Guang Road, Nei Hu Dist. + Taipei 114 + TW + +00-24-60 (hex) Giaval Science Development Co. Ltd. +002460 (base 16) Giaval Science Development Co. Ltd. + 58 Bei Si Huan Xi Rd + Beijing 100080 + CN + +00-24-5C (hex) Design-Com Technologies Pty. Ltd. +00245C (base 16) Design-Com Technologies Pty. Ltd. + 14 Redland Drive + Mitcham Victoria 3132 + AU + +00-24-3D (hex) Emerson Appliance Motors and Controls +00243D (base 16) Emerson Appliance Motors and Controls + 1901 South St. + Elgin IL 60123 + US + +00-24-37 (hex) Motorola - BSG +002437 (base 16) Motorola - BSG + 1101 Marina Village Pkwy + Alameda CA 94501 + US + +00-24-44 (hex) Nintendo Co., Ltd. +002444 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-24-13 (hex) Cisco Systems, Inc +002413 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-4F (hex) Asantron Technologies Ltd. +00244F (base 16) Asantron Technologies Ltd. + 3F-1, No.30 Jihe Rd., 111 + Taipei 11166 + TW + +00-23-DD (hex) ELGIN S.A. +0023DD (base 16) ELGIN S.A. + RUA BARAO DE CAMPINAS, 305 + São Paulo 01201-901 + BR + +00-23-DE (hex) Ansync Inc. +0023DE (base 16) Ansync Inc. + 4970 Robert J Matthews Pky + El Dorado Hills CA 95762 + US + +00-23-D9 (hex) Banner Engineering +0023D9 (base 16) Banner Engineering + 9714 10th Ave. N. + Plymouth MN 55441 + US + +00-23-DA (hex) Industrial Computer Source (Deutschland)GmbH +0023DA (base 16) Industrial Computer Source (Deutschland)GmbH + Marie-Curie-Straße 9 + Pulheim NRW 50259 + DE + +00-24-05 (hex) Dilog Nordic AB +002405 (base 16) Dilog Nordic AB + Faktorvägen 9 + Kungsbacka Halland 439 34 + SE + +00-23-E8 (hex) Demco Corp. +0023E8 (base 16) Demco Corp. + #919, Doosan Venturedigm, 126-1 + Anyang-Si Kyungki-Do 431-070 + US + +00-23-E3 (hex) Microtronic AG +0023E3 (base 16) Microtronic AG + Duennernstrasse 32 + Oensingen Solothurn 4702 + CH + +00-23-B7 (hex) Q-Light Co., Ltd. +0023B7 (base 16) Q-Light Co., Ltd. + 178-1 Woogye-Ri, Sangdong-Myun, + Gimhae-Si GyungsangNam-Do 621-812 + KR + +00-23-FD (hex) AFT Atlas Fahrzeugtechnik GmbH +0023FD (base 16) AFT Atlas Fahrzeugtechnik GmbH + Gewerbestraße 14 + Werdohl 58791 + DE + +00-23-EF (hex) Zuend Systemtechnik AG +0023EF (base 16) Zuend Systemtechnik AG + Industriestrasse 8 + Altstaetten SG 9450 + CH + +00-23-AC (hex) Cisco Systems, Inc +0023AC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-23-D8 (hex) Ball-It Oy +0023D8 (base 16) Ball-It Oy + Uusikatu 24 G 76 + Oulu 90100 + FI + +00-23-9F (hex) Institut für Prüftechnik +00239F (base 16) Institut für Prüftechnik + Schulstraße 3 + Todtenweis Bayern 86447 + DE + +00-23-9D (hex) Mapower Electronics Co., Ltd +00239D (base 16) Mapower Electronics Co., Ltd + No. 50 Minquan Road + Taoyuan County 33846 + TW + +00-23-9C (hex) Juniper Networks +00239C (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-23-98 (hex) Vutlan sro +002398 (base 16) Vutlan sro + ul. Svornosti 43 + Bratislava BA 82 106 + SK + +00-23-5B (hex) Gulfstream +00235B (base 16) Gulfstream + 32 Lummus Drive + Savannah GA 31407 + US + +00-23-59 (hex) Benchmark Electronics ( Thailand ) Public Company Limited +002359 (base 16) Benchmark Electronics ( Thailand ) Public Company Limited + 94 Moo 1, Hi-Tech Industrial Estate + Bang Pa-in Ayudhaya 13160 + TH + +00-23-57 (hex) Pitronot Technologies and Engineering P.T.E. Ltd. +002357 (base 16) Pitronot Technologies and Engineering P.T.E. Ltd. + 8 Hatut st + Pardesiya 42815 + IL + +00-23-55 (hex) Kinco Automation(Shanghai) Ltd. +002355 (base 16) Kinco Automation(Shanghai) Ltd. + Bldg1, No.1387, Zhangdong Road, + Shanghai 201203 + CN + +00-23-73 (hex) GridIron Systems, Inc. +002373 (base 16) GridIron Systems, Inc. + 726 Palomar Ave + Sunnyvale CA 94085 + US + +00-23-67 (hex) UniControls a.s. +002367 (base 16) UniControls a.s. + Krenicka 2257 + Prague 10 100 00 + CZ + +00-23-68 (hex) Zebra Technologies Inc +002368 (base 16) Zebra Technologies Inc + 475 Half Day Road + Lincolnshire IL 60069 + US + +00-23-6E (hex) Burster GmbH & Co KG +00236E (base 16) Burster GmbH & Co KG + Talstraße 1-5 + Gernsbach Baden-Württemberg 76593 + DE + +00-23-66 (hex) Beijing Siasun Electronic System Co.,Ltd. +002366 (base 16) Beijing Siasun Electronic System Co.,Ltd. + Rm.1018 Huatian Bldg, No.6 Bei Xiaomachang + Beijing 100038 + CN + +00-23-8F (hex) NIDEC COPAL CORPORATION +00238F (base 16) NIDEC COPAL CORPORATION + 2-18-10,SHIMURA + ITABASHI-KU TOKYO 174-8550 + JP + +00-23-80 (hex) Nanoteq +002380 (base 16) Nanoteq + PO Box 7991 + Centurion Gauteng 0046 + ZA + +00-23-3D (hex) Laird Technologies +00233D (base 16) Laird Technologies + Meesmannstrasse 103 + Bochum 44807 + DE + +00-23-3F (hex) Purechoice Inc +00233F (base 16) Purechoice Inc + 11481 Rupp Drive + Burnsville MN 55337 + US + +00-23-1B (hex) Danaher Motion - Kollmorgen +00231B (base 16) Danaher Motion - Kollmorgen + 201 W. Rock Road + Radford VA 24141 + US + +00-23-1E (hex) Cezzer Multimedia Technologies +00231E (base 16) Cezzer Multimedia Technologies + Pépinière d'entreprises CREATIC + Plouzané 29280 + FR + +00-23-1F (hex) Guangda Electronic & Telecommunication Technology Development Co., Ltd. +00231F (base 16) Guangda Electronic & Telecommunication Technology Development Co., Ltd. + #8 Gaopengdong Road, Gaoxin District + Chengdu Sichuan 610041 + CN + +00-22-70 (hex) ABK North America, LLC +002270 (base 16) ABK North America, LLC + 440 North Wolfe Rd. + Sunnyvale CA 94085 + US + +00-23-13 (hex) Qool Technologies Ltd. +002313 (base 16) Qool Technologies Ltd. + Gotanda Chuo Bldg 8f, 2-3-5 + Shinagawa-ku Tokyo 141-0022 + JP + +00-23-10 (hex) LNC Technology Co., Ltd. +002310 (base 16) LNC Technology Co., Ltd. + 19F, No. 78-2, Sec. 3, Taichung Kang Rd. + Taichung 40764 + TW + +00-22-CD (hex) Ared Technology Co., Ltd. +0022CD (base 16) Ared Technology Co., Ltd. + 6F-8 No.83 Sec.1, Nankan Rd. Luzhu Shiang + Taoyuan County Taiwan 33859 + TW + +00-22-CC (hex) SciLog, Inc. +0022CC (base 16) SciLog, Inc. + 8845 South Greenview Drive + Middleton Wisconsin 53562 + US + +00-22-CB (hex) IONODES Inc. +0022CB (base 16) IONODES Inc. + 4001 boulevard Industriel + Laval Quebec H7L4S3 + CA + +00-22-C6 (hex) Sutus Inc +0022C6 (base 16) Sutus Inc + 301-3999 Henning Drive + Burnaby British Columbia V5C 6P9 + CA + +00-22-E8 (hex) Applition Co., Ltd. +0022E8 (base 16) Applition Co., Ltd. + 509-1, Bundang Techno Park D-dong, + SeongNam Kyunggi-do 463-760 + KR + +00-22-E9 (hex) ProVision Communications +0022E9 (base 16) ProVision Communications + 1 Portland Square + Bristol BS2 8RR + GB + +00-22-E6 (hex) Intelligent Data +0022E6 (base 16) Intelligent Data + Edf. Inverinnova – Avda. Punto Mobi, 4. Parque Científico Tecnológico + Alcalá de Henares Madrid 28805 + ES + +00-22-E3 (hex) Amerigon +0022E3 (base 16) Amerigon + 21680 Haggerty Road + Northville Michigan 48167 + US + +00-22-EB (hex) Data Respons A/S +0022EB (base 16) Data Respons A/S + Ellekær 6 + Herlev 2730 + DK + +00-22-EF (hex) iWDL Technologies +0022EF (base 16) iWDL Technologies + 10522 Meinert Rd + Wexford PA 15090 + US + +00-22-F2 (hex) SunPower Corp +0022F2 (base 16) SunPower Corp + 1414 Harbour Way South + Richmond CA 94804 + US + +00-22-E2 (hex) WABTEC Transit Division +0022E2 (base 16) WABTEC Transit Division + 130 Ridgeview Circle + Duncan SC 29334 + US + +00-23-01 (hex) Witron Technology Limited +002301 (base 16) Witron Technology Limited + 6/F, Xin Rui Building, 32 Tao Hua Road, Futian Free Trade Zone, + Shenzhen 86 + CN + +00-22-F7 (hex) Conceptronic +0022F7 (base 16) Conceptronic + Databankweg 7 + AMERSFOORT utrecht 3821 AL + NL + +00-23-0C (hex) CLOVER ELECTRONICS CO.,LTD. +00230C (base 16) CLOVER ELECTRONICS CO.,LTD. + AKENO 306-1 + ISE City MIE Prefecture 519-0501 + JP + +00-23-34 (hex) Cisco Systems, Inc +002334 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-22-C8 (hex) Applied Instruments B.V. +0022C8 (base 16) Applied Instruments B.V. + Dynamoweg 3 + Vlissingen Zeeland NL-4382WZ + NL + +00-22-C0 (hex) Shenzhen Forcelink Electronic Co, Ltd +0022C0 (base 16) Shenzhen Forcelink Electronic Co, Ltd + 2nd and 3rd floor, Hasse manufacture building, Hasee industrial park + Shenzhen Guangdong 518112 + CN + +00-22-A6 (hex) Sony Computer Entertainment America +0022A6 (base 16) Sony Computer Entertainment America + 919 East Hillsdale Blvd + Foster City California 94404-2175 + US + +00-22-A7 (hex) Tyco Electronics AMP GmbH +0022A7 (base 16) Tyco Electronics AMP GmbH + Amperestraße 12-14 + Bensheim Hessen 64625 + DE + +00-22-A1 (hex) Huawei Symantec Technologies Co.,Ltd. +0022A1 (base 16) Huawei Symantec Technologies Co.,Ltd. + Building 1,The West Zone Science Park of UESTC,No.88,Tianchen Road + Chengdu Sichuan 611731 + CN + +00-22-9D (hex) PYUNG-HWA IND.CO.,LTD +00229D (base 16) PYUNG-HWA IND.CO.,LTD + 230-1 + HWASUNG-SI KYUNGGI-DO 445-912 + KR + +00-22-96 (hex) LinoWave Corporation +002296 (base 16) LinoWave Corporation + 1001-101 Champlain Avenue + Burlington Ontario L7L 5Z4 + CA + +00-22-44 (hex) Chengdu Linkon Communications Device Co., Ltd +002244 (base 16) Chengdu Linkon Communications Device Co., Ltd + 5f-02, Juntong Building, No. 53,Shuangfeng Road, Wuhou District, + Chengdu Sichuan 610041 + CN + +00-22-50 (hex) Point Six Wireless, LLC +002250 (base 16) Point Six Wireless, LLC + 2333 Alumni Park Plaza + Lexington KY 40517 + US + +00-22-6F (hex) 3onedata Technology Co. Ltd. +00226F (base 16) 3onedata Technology Co. Ltd. + 3/F, B/2, Jiuxiangling Industrial District, Xili Town, Nanshan District, + Shenzhen Guangdong 518055 + CN + +00-22-78 (hex) Shenzhen Tongfang Multimedia Technology Co.,Ltd. +002278 (base 16) Shenzhen Tongfang Multimedia Technology Co.,Ltd. + 2f Sector D of TongFang Information Harbor + Nanshan District, Shenzhen GuangDong 518058 + CN + +00-22-7A (hex) Telecom Design +00227A (base 16) Telecom Design + Za Remora + 33170 Gradignan + FR + +00-22-60 (hex) AFREEY Inc. +002260 (base 16) AFREEY Inc. + 6F, No.249, Chien I Road + Chung Ho City Taipei County 235 + TW + +00-21-EF (hex) Kapsys +0021EF (base 16) Kapsys + 790 Av du Docteur Maurice Donat + 06250 Mougins Sophia Antipolis + FR + +00-21-ED (hex) Telegesis +0021ED (base 16) Telegesis + 84 Station Road + Marlow Bucks SL7 1NX + GB + +00-21-EB (hex) ESP SYSTEMS, LLC +0021EB (base 16) ESP SYSTEMS, LLC + 1422 East Fourth Street + Charlotte NC 28204 + US + +00-22-37 (hex) Shinhint Group +002237 (base 16) Shinhint Group + Unit 1506, 15/F, Nanyang Plaza,, 57 Hung To Road, + + HK + +00-22-2F (hex) Open Grid Computing, Inc. +00222F (base 16) Open Grid Computing, Inc. + 4030-1 West Braker Lane STE130 + Austin TX 78759 + US + +00-21-F6 (hex) Oracle Corporation +0021F6 (base 16) Oracle Corporation + 900 Chelmsford Street + Lowell MA 01851 + US + +00-22-06 (hex) Cyberdyne Inc. +002206 (base 16) Cyberdyne Inc. + 504 @C49-2 + Tsukuba-shi Ibaraki-ken 305-0817 + JP + +00-22-02 (hex) Excito Elektronik i Skåne AB +002202 (base 16) Excito Elektronik i Skåne AB + Box 126 + Löddeköpinge 246 22 + SE + +00-22-27 (hex) uv-electronic GmbH +002227 (base 16) uv-electronic GmbH + Grosswiesenstraße 20 + Durchhausen Baden-Württemberg 78591 + DE + +00-22-1E (hex) Media Devices Co., Ltd. +00221E (base 16) Media Devices Co., Ltd. + Rm1002 Ace TechnoTower(9th) 345-30 + Seoul 153-802 + KR + +00-22-25 (hex) Thales Avionics Ltd +002225 (base 16) Thales Avionics Ltd + 86 Bushey Road + London SW20 0JW + GB + +00-22-20 (hex) Mitac Technology Corp +002220 (base 16) Mitac Technology Corp + 9th Fl., #75, Min-sheng E. Road, Sec. 3, + Taipei 104 + TW + +00-22-0E (hex) Indigo Security Co., Ltd. +00220E (base 16) Indigo Security Co., Ltd. + 2nd Floor, 277-169 Sungsoo2-Ga, Sungdong-Gu + Seoul 133-832 + KR + +00-22-07 (hex) Inteno Broadband Technology AB +002207 (base 16) Inteno Broadband Technology AB + Stensätravägen 13 + Skärholmen SE 127 39 + SE + +00-22-3E (hex) IRTrans GmbH +00223E (base 16) IRTrans GmbH + Einsteinstrasse 14 + Unterschleissheim BAYERN 85716 + DE + +00-21-CE (hex) NTC-Metrotek +0021CE (base 16) NTC-Metrotek + 9, Nevzorovoy street + Saint-Petersburg 192148 + RU + +00-21-CA (hex) ART System Co., Ltd. +0021CA (base 16) ART System Co., Ltd. + Mobile Techno Bldg Room 910 + Dae-Gu 702-020 + KR + +00-21-CB (hex) SMS TECNOLOGIA ELETRONICA LTDA +0021CB (base 16) SMS TECNOLOGIA ELETRONICA LTDA + Av. Pirâmide, 661 + DIADEMA São Paulo 09970330 + BR + +00-21-C8 (hex) LOHUIS Networks +0021C8 (base 16) LOHUIS Networks + 2681 TV Monster + Votlaan 408 Votlaan 31 + NL + +00-21-DB (hex) Santachi Video Technology (Shenzhen) Co., Ltd. +0021DB (base 16) Santachi Video Technology (Shenzhen) Co., Ltd. + Santachi Building,#14 Kaifeng Road,Meilin, + Shenzhen Guangdong 518049 + CN + +00-21-BF (hex) Hitachi High-Tech Control Systems Corporation +0021BF (base 16) Hitachi High-Tech Control Systems Corporation + 500,Miyu-cho + Mito-shi Ibaraki-ken 319-0316 + JP + +00-21-BC (hex) ZALA COMPUTER +0021BC (base 16) ZALA COMPUTER + EL BOUNI + ANNABA 23000 + DZ + +00-21-B4 (hex) APRO MEDIA CO., LTD +0021B4 (base 16) APRO MEDIA CO., LTD + #13-5,Dodang-Dong,Wonmi-Gu, + Bucheon-City Kyunggi-Do 420-801 + KR + +00-21-A8 (hex) Telephonics Corporation +0021A8 (base 16) Telephonics Corporation + 815 Broad Hollow Road + Farmingdale New York 11790 + US + +00-21-A9 (hex) Mobilink Telecom Co.,Ltd +0021A9 (base 16) Mobilink Telecom Co.,Ltd + 292-3 Sindang-ri, Sandong-myun + Gumi Gyeongbuk 730-853 + KR + +00-21-8D (hex) AP Router Ind. Eletronica LTDA +00218D (base 16) AP Router Ind. Eletronica LTDA + Av. Lomanto Junior, 1000 + Ilheus Bahia 45654-000 + BR + +00-21-90 (hex) Goliath Solutions +002190 (base 16) Goliath Solutions + 3082 Sterling Circle + Boulder Colorado 80301 + US + +00-21-85 (hex) MICRO-STAR INT'L CO.,LTD. +002185 (base 16) MICRO-STAR INT'L CO.,LTD. + No.69,Li-De St,Jung-Ho City + Taipei Hsien 235 + TW + +00-21-9F (hex) SATEL OY +00219F (base 16) SATEL OY + Meriniitynkatu 17 + SALO Lansi-Suomen Laani 24100 + FI + +00-21-96 (hex) Telsey S.p.A. +002196 (base 16) Telsey S.p.A. + Viale dell'Industria, 1 + Quinto DiTreviso 31055 + IT + +00-21-82 (hex) SandLinks Systems, Ltd. +002182 (base 16) SandLinks Systems, Ltd. + P.O.Box 4629 + Petah-Tiqwa Israel 49277 + IL + +00-21-83 (hex) ANDRITZ HYDRO GmbH +002183 (base 16) ANDRITZ HYDRO GmbH + Eibesbrunnergasse 20 + Vienna 1120 + AT + +00-21-DF (hex) Martin Christ GmbH +0021DF (base 16) Martin Christ GmbH + An der Unteren Soese 50 + Osterode Niedersachsen 37520 + DE + +00-21-D4 (hex) Vollmer Werke GmbH +0021D4 (base 16) Vollmer Werke GmbH + Maschinenfabrik + Biberach Baden-Württemberg 88400 + DE + +00-21-D6 (hex) LXI Consortium +0021D6 (base 16) LXI Consortium + P.O. Box 1016 + Niwot CO 80544-1016 + US + +00-21-A6 (hex) Videotec Spa +0021A6 (base 16) Videotec Spa + Via Friuli,6 + Schio Vicenza 36015 + IT + +00-21-59 (hex) Juniper Networks +002159 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-21-55 (hex) Cisco Systems, Inc +002155 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-21-57 (hex) National Datacast, Inc. +002157 (base 16) National Datacast, Inc. + 2100 Crystal Drive, Suite 750 + Arlington VA 22202 + US + +00-21-3B (hex) Berkshire Products, Inc +00213B (base 16) Berkshire Products, Inc + PO Box 2819 + Cumming GA 30028 + US + +00-21-37 (hex) Bay Controls, LLC +002137 (base 16) Bay Controls, LLC + 6528 Weatherfield Ct + Maumee OH 43537 + US + +00-21-39 (hex) Escherlogic Inc. +002139 (base 16) Escherlogic Inc. + 1481 Rosebank Rd. + Pickering Ontario L1V 1P3 + CA + +00-21-2C (hex) SemIndia System Private Limited +00212C (base 16) SemIndia System Private Limited + No. 1106/9, A.M Industrial Estate, Garvebhavipalya + Bangalore Karnataka 560 068 + IN + +00-21-2B (hex) MSA Auer +00212B (base 16) MSA Auer + Thiemannstraße 1 + Berlin 12059 + DE + +00-21-74 (hex) AvaLAN Wireless +002174 (base 16) AvaLAN Wireless + 958 San Leandro Ave, Suite 900 + Mountain View CA 94043 + US + +00-21-79 (hex) IOGEAR, Inc. +002179 (base 16) IOGEAR, Inc. + 23 Hubble + Irvine CA 92618 + US + +00-21-68 (hex) iVeia, LLC +002168 (base 16) iVeia, LLC + 51 Franklin Street + Annapolis MD 21401 + US + +00-21-50 (hex) EYEVIEW ELECTRONICS +002150 (base 16) EYEVIEW ELECTRONICS + 3 Floor, No. 86, Kung Yeh 32 Road + TAICHUNG 407 + TW + +00-21-4D (hex) Guangzhou Skytone Transmission Technology Com. Ltd. +00214D (base 16) Guangzhou Skytone Transmission Technology Com. Ltd. + 3/F West, Block 4, Huangzhou + Guangzhou Guangdong 510660 + CN + +00-21-2A (hex) Audiovox Corporation +00212A (base 16) Audiovox Corporation + 150 Marcus Blvd + Hauppauge NY 11788 + US + +00-21-5E (hex) IBM Corp +00215E (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-1F-F6 (hex) PS Audio International +001FF6 (base 16) PS Audio International + 4826 Sterling Drive + Boulder CO 80301 + US + +00-21-10 (hex) Clearbox Systems +002110 (base 16) Clearbox Systems + Suite 2, Level 2 + Macquarie Park NSW 2113 + AU + +00-21-0C (hex) Cymtec Systems, Inc. +00210C (base 16) Cymtec Systems, Inc. + 10845 Olive Bouleveard + St Louis MO 63141 + US + +00-21-0B (hex) GEMINI TRAZE RFID PVT. LTD. +00210B (base 16) GEMINI TRAZE RFID PVT. LTD. + 1, DR. RANGA ROAD + CHENNAI TAMILNADU 600018 + IN + +00-1F-DD (hex) GDI LLC +001FDD (base 16) GDI LLC + One MidAmerica Plaza + Oakbrook Terrace IL 60181 + US + +00-1F-DA (hex) Nortel Networks +001FDA (base 16) Nortel Networks + 2221 Lakeside Blvd + Richardson TX 75081 + US + +00-21-04 (hex) Gigaset Communications GmbH +002104 (base 16) Gigaset Communications GmbH + Frankenstrasse 2 + 46395 Bocholt + DE + +00-1F-FB (hex) Green Packet Bhd +001FFB (base 16) Green Packet Bhd + Lot 1-4, Incubator 2, Technology Park Malaysia + Kuala Lumpur Wilayah Persekutuan 57000 + MY + +00-1F-E9 (hex) Printrex, Inc. +001FE9 (base 16) Printrex, Inc. + 276 East Gish Road + San Jose CA 95112 + US + +00-1F-F0 (hex) Audio Partnership +001FF0 (base 16) Audio Partnership + Gallery Court + London SE1 4BB + GB + +00-1F-EA (hex) Applied Media Technologies Corporation +001FEA (base 16) Applied Media Technologies Corporation + 4091 AMTC Center Drive + Clearwater FL 33764 + US + +00-1F-D9 (hex) RSD Communications Ltd +001FD9 (base 16) RSD Communications Ltd + 8 Borrowmeadow Road + Stirling Scotland FK7 7UW + GB + +00-1F-CE (hex) QTECH LLC +001FCE (base 16) QTECH LLC + Novozavodskaya st. 18 build. 1 + Moscow Moscow region 121309 + RU + +00-1F-8B (hex) Cache IQ +001F8B (base 16) Cache IQ + 8834 North Capital of Texas Hwy + Austin Texas 78759 + US + +00-1F-85 (hex) Apriva ISS, LLC +001F85 (base 16) Apriva ISS, LLC + 6900 E Camelback Rd + Scottsdale AZ 85251 + US + +00-1F-87 (hex) Skydigital Inc. +001F87 (base 16) Skydigital Inc. + #28-9 Wonhyoro1-ga, Yongsan-gu, + Seoul 140-846 + KR + +00-1F-88 (hex) FMS Force Measuring Systems AG +001F88 (base 16) FMS Force Measuring Systems AG + Aspstrasse 6 + Oberglatt Zurich 8154 + CH + +00-1F-86 (hex) digEcor +001F86 (base 16) digEcor + 1625 N. 1100 W. + Springville UT 84663 + US + +00-1F-A1 (hex) Gtran Inc +001FA1 (base 16) Gtran Inc + 2651 Lavery Court + Newbury Park CA 91320 + US + +00-1F-9F (hex) Thomson Telecom Belgium +001F9F (base 16) Thomson Telecom Belgium + Prins Boudewijnlaan 47 + Edegem Antwerp B-2650 + BE + +00-1F-99 (hex) SERONICS co.ltd +001F99 (base 16) SERONICS co.ltd + #401 Technopolis, + Daegu Gyeong-buk 704-230 + KR + +00-1F-80 (hex) Lucas Holding bv +001F80 (base 16) Lucas Holding bv + Domein 28 + Gemert NB 5421AR + NL + +00-1B-58 (hex) ACE CAD Enterprise Co., Ltd. +001B58 (base 16) ACE CAD Enterprise Co., Ltd. + 2F, No. 94, Bao Chung Road, + Hsin Tien City, Taipei Hsien 23144 + TW + +00-1F-B0 (hex) TimeIPS, Inc. +001FB0 (base 16) TimeIPS, Inc. + 3522 N Comotara St + Wichita KS 67226 + US + +00-1F-AE (hex) Blick South Africa (Pty) Ltd +001FAE (base 16) Blick South Africa (Pty) Ltd + PO Box 1908 + Johannesburg Gauteng 2108 + ZA + +00-1F-79 (hex) Lodam Electronics A/S +001F79 (base 16) Lodam Electronics A/S + Kærvej 77 + Sønderborg Als DK-6400 + DK + +00-1F-71 (hex) xG Technology, Inc. +001F71 (base 16) xG Technology, Inc. + 240 S. Pineapple Avenue + Sarasota FL 34236 + US + +00-1F-A5 (hex) Blue-White Industries +001FA5 (base 16) Blue-White Industries + 5300 Business Drive + Huntington Beach CA 92649 + US + +00-1F-9D (hex) Cisco Systems, Inc +001F9D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1F-96 (hex) APROTECH CO.LTD +001F96 (base 16) APROTECH CO.LTD + KOLONDIGITAL TOWER ASTON 201, 505-14 + SEOUL KSXX 0022 + KR + +00-1F-40 (hex) Speakercraft Inc. +001F40 (base 16) Speakercraft Inc. + 940 Columbia Ave., + Riverside CA 92507 + US + +00-1F-6C (hex) Cisco Systems, Inc +001F6C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1F-6F (hex) Fujian Sunnada Communication Co.,Ltd. +001F6F (base 16) Fujian Sunnada Communication Co.,Ltd. + 7/F Main Building,Fujian Torch Hi-Tech Innovation Park No.611 Industrial Road,Fuzhou Fuzhou Fujian China 350002 + Fuzhou Fujian 350002 + CN + +00-1F-60 (hex) COMPASS SYSTEMS CORP. +001F60 (base 16) COMPASS SYSTEMS CORP. + 6F, No. 413, Sec. 2, Ti-Ding Blvd., + Taipei NeihuDist 114 + TW + +00-1F-6A (hex) PacketFlux Technologies, Inc. +001F6A (base 16) PacketFlux Technologies, Inc. + 50 11th Avenue + Helena MT 59601 + US + +00-1F-65 (hex) KOREA ELECTRIC TERMINAL CO., LTD. +001F65 (base 16) KOREA ELECTRIC TERMINAL CO., LTD. + #7-38 SONGDO-DONG + YEONSU-GU INCHEON 406-840 + KR + +00-1F-17 (hex) IDX Company, Ltd. +001F17 (base 16) IDX Company, Ltd. + 6-28-11 Shukugawara, Tana-ku + Kawasaki-Shi Kanagawa-Ken 2140021 + JP + +00-1F-1B (hex) RoyalTek Company Ltd. +001F1B (base 16) RoyalTek Company Ltd. + Suite 9F-1, No. 1071, Chung Cheng Rd. + Taoyuan Shien Taoyuan 330 + TW + +00-1F-5E (hex) Dyna Technology Co.,Ltd. +001F5E (base 16) Dyna Technology Co.,Ltd. + HaoHai Building 1F,No.7,5th Street,Shangdi, + Beijing 100085 + CN + +00-1F-55 (hex) Honeywell Security (China) Co., Ltd. +001F55 (base 16) Honeywell Security (China) Co., Ltd. + Block 28, Section 2, Huai De Cui Gang Industrial Estate, Fu Yong, Bao An, ShenZhen, P.R. China + ShenZhen GuangDong 518103 + CN + +00-1F-54 (hex) Lorex Technology Inc. +001F54 (base 16) Lorex Technology Inc. + 250 Royal Crest Court + Markham Ontario L3R3S1 + CA + +00-1F-2E (hex) Triangle Research Int'l Pte Ltd +001F2E (base 16) Triangle Research Int'l Pte Ltd + 10 Ubi Crescent #05-83 + Ubi Techpark SG 408664 + SG + +00-1F-4B (hex) Lineage Power +001F4B (base 16) Lineage Power + 3000 Skyline Dr. + Mesquite TX 75149 + US + +00-1F-0D (hex) L3 Communications - Telemetry West +001F0D (base 16) L3 Communications - Telemetry West + 9020 Balboa Ave + San Diego CA 92123 + US + +00-1E-FC (hex) JSC MASSA-K +001EFC (base 16) JSC MASSA-K + 15, A, Pirogovskaya nab. + Saint-Petersburg Leningradskiy reg. 194044 + RU + +00-1F-23 (hex) Interacoustics +001F23 (base 16) Interacoustics + Drejervaenget 8 + Assens DK 5610 + DK + +00-1F-06 (hex) Integrated Dispatch Solutions +001F06 (base 16) Integrated Dispatch Solutions + 645 Mountain Ave + Wyckoff NJ 07481 + US + +00-1E-BA (hex) High Density Devices AS +001EBA (base 16) High Density Devices AS + Vestre Strandgate 26 + Kristiansand 4611 + NO + +00-1E-B8 (hex) Aloys, Inc +001EB8 (base 16) Aloys, Inc + #3F HANWHA TECHWIN R&D BLDG. 4-5, YANGHYEON-RO 405 BEON-GIL, + JUNGWON-GU, SEONGNAM-SI GYEONGGI-DO 13438 + KR + +00-1E-B4 (hex) UNIFAT TECHNOLOGY LTD. +001EB4 (base 16) UNIFAT TECHNOLOGY LTD. + 7/FLOOR, SUI HONG IND. BLDG., + KWAI CHUNG N.T. + HK + +00-1E-E0 (hex) Urmet Domus SpA +001EE0 (base 16) Urmet Domus SpA + Via Bologna 188/C + Torino TO I-10154 + IT + +00-1E-DA (hex) Wesemann Elektrotechniek B.V. +001EDA (base 16) Wesemann Elektrotechniek B.V. + Droogbloem 31 + Rotterdam Zuid-Holland 3068 AW + NL + +00-1E-D7 (hex) H-Stream Wireless, Inc. +001ED7 (base 16) H-Stream Wireless, Inc. + 2595 East Bayshore Road + Palo Alto CA 94303 + US + +00-1E-D5 (hex) Tekon-Automatics +001ED5 (base 16) Tekon-Automatics + Zelenograd, 512-29 + Moscow 124482 + RU + +00-1E-E8 (hex) Mytek +001EE8 (base 16) Mytek + 151 Lafayette Str 3 Fl + New York NY 10013 + US + +00-1E-EE (hex) ETL Systems Ltd +001EEE (base 16) ETL Systems Ltd + Coldwell Radio Station + Hereford Herefordshire HR2 9NE + GB + +00-1E-FA (hex) PROTEI Ltd. +001EFA (base 16) PROTEI Ltd. + 60A B.Sampsonievsky, Business Center + St.Petersburg RU 194044 + RU + +00-1E-FB (hex) Trio Motion Technology Ltd +001EFB (base 16) Trio Motion Technology Ltd + Shannon Way + Tewkesbury Gloucestershire GL20 8ND + GB + +00-1E-F8 (hex) Emfinity Inc. +001EF8 (base 16) Emfinity Inc. + 1305 Kelly Lake Road + Sudbury Ontario P3E5P5 + CA + +00-1E-CB (hex) RPC Energoautomatika Ltd +001ECB (base 16) RPC Energoautomatika Ltd + Krasnokazarmennaya st., 13/1 + Moscow 111250 + RU + +00-1E-A8 (hex) Datang Mobile Communications Equipment CO.,LTD +001EA8 (base 16) Datang Mobile Communications Equipment CO.,LTD + No.29,Xueyuan Rd. + Beijing 100083 + CN + +00-1E-AB (hex) TeleWell Oy +001EAB (base 16) TeleWell Oy + Alahotie 14 b + Jarvenpaa Uusimaa 04430 + FI + +00-1E-9F (hex) Visioneering Systems, Inc. +001E9F (base 16) Visioneering Systems, Inc. + 5931 Sea Lion Place + Carlsbad California 92010 + US + +00-1E-6B (hex) Cisco SPVTG +001E6B (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +00-1E-70 (hex) Cobham Antenna Systems +001E70 (base 16) Cobham Antenna Systems + Cobham Centre, Fourth Avenue + Marlow Buckinghamshire SL7 1TF + GB + +00-1E-61 (hex) ITEC GmbH +001E61 (base 16) ITEC GmbH + Lassnitzthal 300 + A-8200 Gleisdorf + AT + +00-1E-3E (hex) KMW Inc. +001E3E (base 16) KMW Inc. + 65 Youngchun-ri, Dongtan-myun + Hwasung-si Kyungki-do 445-813 + KR + +00-1E-38 (hex) Bluecard Software Technology Co., Ltd. +001E38 (base 16) Bluecard Software Technology Co., Ltd. + D-801 Shangdi Science Building + Beijing 100085 + CN + +00-1E-47 (hex) PT. Hariff Daya Tunggal Engineering +001E47 (base 16) PT. Hariff Daya Tunggal Engineering + Jl. Soekarno Hatta No. 450 + Bandung Jawa Barat 40266 + ID + +00-1E-48 (hex) Wi-Links +001E48 (base 16) Wi-Links + 332 Ayiou street + Limassol 3725 + CY + +00-1E-8A (hex) eCopy, Inc +001E8A (base 16) eCopy, Inc + 1 Oracle Dr + Nashua NH 03062 + US + +00-1E-9B (hex) San-Eisha, Ltd. +001E9B (base 16) San-Eisha, Ltd. + 2-1 Ebara 5-chome + Shinagawa-ku Tokyo 142-8611 + JP + +00-1E-96 (hex) Sepura Plc +001E96 (base 16) Sepura Plc + Radio House + Cambridge CAMBRIDGESHIRE CB4 1GR + GB + +00-1E-59 (hex) Silicon Turnkey Express, LLC +001E59 (base 16) Silicon Turnkey Express, LLC + 749 Miner Road + Highland Heights Ohio 44143 + US + +00-1E-51 (hex) Converter Industry Srl +001E51 (base 16) Converter Industry Srl + Via Euclide, 12 + Forli' FC 47100 + IT + +00-1E-71 (hex) MIrcom Group of Companies +001E71 (base 16) MIrcom Group of Companies + 25 Interchange Way + Vaughan, Ontario l4K 5W3 + CA + +00-1D-C4 (hex) AIOI Systems Co., Ltd. +001DC4 (base 16) AIOI Systems Co., Ltd. + KDX Omori, Bldg 8F + Tokyo 140-0016 + JP + +00-1D-C0 (hex) Enphase Energy +001DC0 (base 16) Enphase Energy + 201 1st Street, Suite 111 + Petaluma CA 94952 + US + +00-1D-BD (hex) Versamed Inc. +001DBD (base 16) Versamed Inc. + 2 Blue Hill Plaza + Pearl River NY 10965 + US + +00-1D-F8 (hex) Webpro Vision Technology Corporation +001DF8 (base 16) Webpro Vision Technology Corporation + 4F., No.573, Cingping Rd. + Anping District 708 + TW + +00-1D-F9 (hex) Cybiotronics (Far East) Limited +001DF9 (base 16) Cybiotronics (Far East) Limited + Unit 1906, Eastern Centre, + Quarry Bay + HK + +00-1D-F7 (hex) R. STAHL Schaltgeräte GmbH +001DF7 (base 16) R. STAHL Schaltgeräte GmbH + am Bahnhof 30 + Waldenburg Baden-Württemberg 74638 + DE + +00-1E-05 (hex) Xseed Technologies & Computing +001E05 (base 16) Xseed Technologies & Computing + Topaz House, MATAM + Haifa 39100 + IL + +00-1E-07 (hex) Winy Technology Co., Ltd. +001E07 (base 16) Winy Technology Co., Ltd. + 305-303, Bucheon Techno-park, #365 + Bucheon Gyeonggi-do 421-741 + KR + +00-1E-0A (hex) Syba Tech Limited +001E0A (base 16) Syba Tech Limited + RM1301, Vanta Industrial Centre, + Kwai Chung + HK + +00-1E-03 (hex) LiComm Co., Ltd. +001E03 (base 16) LiComm Co., Ltd. + 908-1 SEO-RI, IDONG-MYEON + YONGIN-SI GYEONGGI-DO 449-834 + KR + +00-1E-1B (hex) Digital Stream Technology, Inc. +001E1B (base 16) Digital Stream Technology, Inc. + 4,5,6th Fl., TaeChang B/D, 451-1 + Seoul 134-030 + KR + +00-1E-17 (hex) STN BV +001E17 (base 16) STN BV + Amerikaweg 4 + Hulst Zeeland 4561 PB + NL + +00-1E-18 (hex) Radio Activity srl +001E18 (base 16) Radio Activity srl + Via De Notaris 50 + Milano MI 20128 + IT + +00-1E-15 (hex) Beech Hill Electronics +001E15 (base 16) Beech Hill Electronics + Beechcroft, Beech Hill Road + Reading Berkshire RG7 2AU + GB + +00-1E-30 (hex) Shireen Inc +001E30 (base 16) Shireen Inc + 8531 Ziggy Lane + Gaithersburg MD 20877 + US + +00-1E-2E (hex) SIRTI S.p.A. +001E2E (base 16) SIRTI S.p.A. + Via Bombrini 11/3 + GENOA 16149 + IT + +00-1D-DC (hex) HangZhou DeChangLong Tech&Info Co.,Ltd +001DDC (base 16) HangZhou DeChangLong Tech&Info Co.,Ltd + Room 1102,KeJi Mansion, + HangZhou ZheJiang 310012 + CN + +00-1D-EB (hex) DINEC International +001DEB (base 16) DINEC International + Rue de la Gare, 30 + BRAINE L'ALLEUD BRABANT WALLON 1420 + BE + +00-1D-9A (hex) GODEX INTERNATIONAL CO., LTD +001D9A (base 16) GODEX INTERNATIONAL CO., LTD + 4F. NO.168, Lian-Cheng Road Chung-Ho City, + Taipei Hsien 235 + US + +00-1D-97 (hex) Alertus Technologies LLC +001D97 (base 16) Alertus Technologies LLC + 11785 Beltsville Drive + Beltsville MD 20705 + US + +00-1D-91 (hex) Digitize, Inc +001D91 (base 16) Digitize, Inc + 158 Edison Road + Lake Hopatcong New Jersey 07849 + US + +00-1D-95 (hex) Flash, Inc. +001D95 (base 16) Flash, Inc. + 3703 N. 200th St. + Elkhorn NE 68022-2922 + US + +00-1D-9D (hex) ARTJOY INTERNATIONAL LIMITED +001D9D (base 16) ARTJOY INTERNATIONAL LIMITED + Room 1601,No.239 ZhongXing Road,LuoHu District + Shenzhen Guangdong 518001 + CN + +00-1D-9E (hex) AXION TECHNOLOGIES +001D9E (base 16) AXION TECHNOLOGIES + 151 RUE PARC INNOVATION + LA POCATIERE QUEBEC G0R1Z0 + US + +00-1D-70 (hex) Cisco Systems, Inc +001D70 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1D-78 (hex) Invengo Information Technology Co.,Ltd +001D78 (base 16) Invengo Information Technology Co.,Ltd + 3/F,No.T2-B,High-Tech Industrial Park South + Shenzhen Guangdong 518057 + CN + +00-1D-6F (hex) Chainzone Technology Co., Ltd +001D6F (base 16) Chainzone Technology Co., Ltd + Chainzone Tech. Ind Park, Nanxin 1st Rd. + Foshan Guangdong 528200 + CN + +00-1D-7F (hex) Tekron International Ltd +001D7F (base 16) Tekron International Ltd + 409 Cuba Street, Alicetown + Lower Hutt Wellington 5010 + NZ + +00-1D-79 (hex) SIGNAMAX LLC +001D79 (base 16) SIGNAMAX LLC + 1090 Vermont Avenue + Washington Washington D.C. 20005 + US + +00-1D-AE (hex) CHANG TSENG TECHNOLOGY CO., LTD +001DAE (base 16) CHANG TSENG TECHNOLOGY CO., LTD + 2F NO.160 BACK BUILDING, LEN CHENG RD., CHUNG HO CITY + TAIPEI HSIEN 235 + TW + +00-1D-A6 (hex) Media Numerics Limited +001DA6 (base 16) Media Numerics Limited + Rodenbacher Chaussee 6 + Hanau Hessen 63457 + DE + +00-1D-62 (hex) InPhase Technologies +001D62 (base 16) InPhase Technologies + 2000 Pike Road + Longmont Colorado 80501 + US + +00-1D-63 (hex) Miele & Cie. KG +001D63 (base 16) Miele & Cie. KG + Carl-Miele-Straße 29 + Gütersloh 33332 + DE + +00-1D-B7 (hex) Tendril Networks, Inc. +001DB7 (base 16) Tendril Networks, Inc. + 5700-D Flatiron Parkway + Boulder CO 80301 + US + +00-1D-8D (hex) Fluke Process Instruments GmbH +001D8D (base 16) Fluke Process Instruments GmbH + Blankenburger Str. 135 + Berlin 13127 + DE + +00-1D-1F (hex) Siauliu Tauro Televizoriai, JSC +001D1F (base 16) Siauliu Tauro Televizoriai, JSC + Pramones,15 + Siauliai LT-57318 + LT + +00-1D-43 (hex) Shenzhen G-link Digital Technology Co., Ltd. +001D43 (base 16) Shenzhen G-link Digital Technology Co., Ltd. + 4F, E Building,Huachuang Da Technology Zone ,Hangcheng Highway,Gushu,Xixiang , + shenzhen GuangDong 518126 + CN + +00-1D-3F (hex) Mitron Pty Ltd +001D3F (base 16) Mitron Pty Ltd + Unit 11 + Artarmon NSW 2065 + AU + +00-1D-39 (hex) MOOHADIGITAL CO., LTD +001D39 (base 16) MOOHADIGITAL CO., LTD + Seoul Hightech Venture Center C-307 647-26 + SEOUL 157-030 + KR + +00-1D-37 (hex) Thales-Panda Transportation System +001D37 (base 16) Thales-Panda Transportation System + 6th floor, HUIJIE Plaza, 268 Zhongshan Rd. + nanjing jiangsu 210008 + CN + +00-1D-13 (hex) NextGTV +001D13 (base 16) NextGTV + 13F Byucksan/Kyungin Digital Valley ll + Seoul 153-803 + KR + +00-1D-14 (hex) SPERADTONE INFORMATION TECHNOLOGY LIMITED +001D14 (base 16) SPERADTONE INFORMATION TECHNOLOGY LIMITED + Room 1001 NO.418 Gui Ping Road, + Shanghai 200233 + CN + +00-1D-10 (hex) LightHaus Logic, Inc. +001D10 (base 16) LightHaus Logic, Inc. + 126-1020 Mainland Street + Vancouver BC V6B 2T4 + CA + +00-1D-04 (hex) Zipit Wireless, Inc. +001D04 (base 16) Zipit Wireless, Inc. + 49 Salters Road. + Greenville SC 29607 + US + +00-1C-F2 (hex) Tenlon Technology Co.,Ltd. +001CF2 (base 16) Tenlon Technology Co.,Ltd. + 4/F.,Shenhua Bldg,No.3155,Binhe Road,Futian District + Shenzhen Guangdong 518033 + CN + +00-1D-30 (hex) YX Wireless S.A. +001D30 (base 16) YX Wireless S.A. + Av. Vicuña Mackenna #4860 + Santiago 8580710 + US + +00-1C-B2 (hex) BPT SPA +001CB2 (base 16) BPT SPA + Via Stazione,48 + Sesto al Reghena Pordenone 33079 + IT + +00-1C-B5 (hex) Neihua Network Technology Co.,LTD.(NHN) +001CB5 (base 16) Neihua Network Technology Co.,LTD.(NHN) + Plot Xinmei Road 102-Q,New District + WuXi Jiangsu 214028 + CN + +00-1C-B4 (hex) Iridium Satellite LLC +001CB4 (base 16) Iridium Satellite LLC + 8440 S. River Parkway + Tempe AZ 85284 + US + +00-1C-B6 (hex) Duzon CNT Co., Ltd. +001CB6 (base 16) Duzon CNT Co., Ltd. + 14th Floor, IRE building 2 + Seoul 150-967 + KR + +00-1C-C7 (hex) Rembrandt Technologies, LLC d/b/a REMSTREAM +001CC7 (base 16) Rembrandt Technologies, LLC d/b/a REMSTREAM + 140 South Beverly Drive + Beverly Hills CA 90212 + US + +00-1C-BB (hex) MusicianLink +001CBB (base 16) MusicianLink + 2401 Cory Ave. + San Jose CA 95128 + US + +00-1C-8D (hex) Mesa Imaging +001C8D (base 16) Mesa Imaging + Badenerstrasse 569 + Zürich ZH 8048 + CH + +00-1C-89 (hex) Force Communications, Inc. +001C89 (base 16) Force Communications, Inc. + 3810 Arbordale Lane + Sachse TX 75048 + US + +00-1C-87 (hex) Uriver Inc. +001C87 (base 16) Uriver Inc. + 3rd., Fl., Bogwang Bldg., Poi-dong, 238-7 Gangnam-gu, + Seoul 135-964 + KR + +00-1C-CD (hex) Alektrona Corporation +001CCD (base 16) Alektrona Corporation + 95 Hathaway Street, Suite 10 + Providence RI 02907 + US + +00-1C-EC (hex) Mobilesoft (Aust.) Pty Ltd +001CEC (base 16) Mobilesoft (Aust.) Pty Ltd + Suite 2, 27-35 Grosvenor Street + Sydney NSW 2089 + AU + +00-1C-E8 (hex) Cummins Inc +001CE8 (base 16) Cummins Inc + 1400 73rd Ave NE + Fridley MN 55432 + US + +00-1C-D0 (hex) Circleone Co.,Ltd. +001CD0 (base 16) Circleone Co.,Ltd. + 860-1,Noda + Beppu-shi Ooita-ken 874-0016 + JP + +00-1C-9F (hex) Razorstream, LLC +001C9F (base 16) Razorstream, LLC + 2381-C Renaissance Drive + Las Vegas NV 89119 + US + +00-1C-7D (hex) Excelpoint Manufacturing Pte Ltd +001C7D (base 16) Excelpoint Manufacturing Pte Ltd + 15, Changi Business Park + 486057 + SG + +00-1C-5C (hex) Integrated Medical Systems, Inc. +001C5C (base 16) Integrated Medical Systems, Inc. + 1984 Obispo Avenue + Signal Hill CA 90755 + US + +00-1C-52 (hex) VISIONEE SRL +001C52 (base 16) VISIONEE SRL + VIALE DELLA REPUBBLICA, 22 + VILLORBA TREVISO 31050 + IT + +00-1C-47 (hex) Hangzhou Hollysys Automation Co., Ltd +001C47 (base 16) Hangzhou Hollysys Automation Co., Ltd + No.10 Middle Road, Jiancaicheng, Haidian District, + Beijing 100096 + CN + +00-1C-16 (hex) ThyssenKrupp Elevator +001C16 (base 16) ThyssenKrupp Elevator + 9280 Crestwyn Hills Drive + Memphis TN 38125 + US + +00-1C-19 (hex) secunet Security Networks AG +001C19 (base 16) secunet Security Networks AG + Kronprinzenstraße 30 + Essen NRW 45128 + DE + +00-1C-6C (hex) 30805 +001C6C (base 16) 30805 + 128, Jun Cheng Road,uangzhou Economic and Technological Development District + Guangzhou Guangdong 510530 + CN + +00-1C-61 (hex) Galaxy Microsystems LImited +001C61 (base 16) Galaxy Microsystems LImited + Room 1101-03, 11/F Enterprise Square Two + Kowloon Bay Kowloon + HK + +00-1C-3B (hex) AmRoad Technology Inc. +001C3B (base 16) AmRoad Technology Inc. + 18F-3 No. 150 , Chien I Rd + Chung Ho Taipei Hsien 23511 + TW + +00-1C-3F (hex) International Police Technologies, Inc. +001C3F (base 16) International Police Technologies, Inc. + 4150 S. 87th E. Avenue + Tulsa OK 74145 + US + +00-1C-28 (hex) Sphairon Technologies GmbH +001C28 (base 16) Sphairon Technologies GmbH + Philipp-Reis-Strasse 1 + Bautzen Saxony 02625 + DE + +00-1C-1F (hex) Quest Retail Technology Pty Ltd +001C1F (base 16) Quest Retail Technology Pty Ltd + 37-39 Walsh Street + Thebarton SA 5031 + AU + +00-1C-32 (hex) Telian Corporation +001C32 (base 16) Telian Corporation + 4FL. Namjeon Bldg. 53-3 Haandong + Kwangmyungsi Kyoungkido 423060 + KR + +00-1C-2B (hex) Alertme.com Limited +001C2B (base 16) Alertme.com Limited + 30 Station Road + Cambridge Cambridgeshire CB1 2RE + GB + +00-1C-77 (hex) Prodys +001C77 (base 16) Prodys + C/Trigo 54 Pol. Ind. Polvoranca + Leganes MADRID 28914 + ES + +00-1C-6F (hex) Emfit Ltd +001C6F (base 16) Emfit Ltd + Konttisentie 8 B + Vaajakoski 40800 + FI + +00-1C-49 (hex) Zoltan Technology Inc. +001C49 (base 16) Zoltan Technology Inc. + 4F, No.30, Wunsi St. + Jhubei Hsinchu 302 + TW + +00-1C-63 (hex) TRUEN +001C63 (base 16) TRUEN + 4F SAMWON BLDG., 451-7 + SEOUL 137-818 + KR + +00-1B-DF (hex) Iskra Sistemi d.d. +001BDF (base 16) Iskra Sistemi d.d. + Stegne 21 + Ljubljana Slovenia 1000 + SI + +00-1B-D9 (hex) Edgewater Wireless Systems Inc +001BD9 (base 16) Edgewater Wireless Systems Inc + 50 HInes Road Suite 200 + Ottawa Ontario K2K-2M5 + CA + +00-1B-C7 (hex) StarVedia Technology Inc. +001BC7 (base 16) StarVedia Technology Inc. + 3F, No. 247, Done Sec. 1, Guangming 6th Rd. + Jhubei Hsin-Chu County 302 + TW + +00-1B-EC (hex) Netio Technologies Co., Ltd +001BEC (base 16) Netio Technologies Co., Ltd + 4F-1, No. 582, Rueiguang Rd., Neihu District + Taipei 11492 + TW + +00-1C-09 (hex) SAE Electronic Co.,Ltd. +001C09 (base 16) SAE Electronic Co.,Ltd. + 23/F,Ying Long Zhan Ye Building, + Shenzhen Guang Dong 518040 + CN + +00-1C-0C (hex) TANITA Corporation +001C0C (base 16) TANITA Corporation + 1-14-2,Maeno-cho + Tokyo 174-8630 + JP + +00-1B-A6 (hex) intotech inc. +001BA6 (base 16) intotech inc. + 13F DMC R&D Center E3-2 Building Land Development District Sangam-Dong + Mapogu Seoul 121-270 + KR + +00-1B-A4 (hex) S.A.E Afikim +001BA4 (base 16) S.A.E Afikim + Kibutz Afikim + Kibutz Afikim 15148 + IL + +00-1B-B4 (hex) Airvod Limited +001BB4 (base 16) Airvod Limited + Heather House + Sandyford Ind Est Dublin 18 D18 + IE + +00-1B-B6 (hex) Bird Electronic Corp. +001BB6 (base 16) Bird Electronic Corp. + 30303 Aurora Road + Solon Ohio 44139 + US + +00-1B-E8 (hex) Ultratronik GmbH +001BE8 (base 16) Ultratronik GmbH + Dornierstr. 9 + Gilching 822205 + DE + +00-1B-E1 (hex) ViaLogy +001BE1 (base 16) ViaLogy + 2400 Lincoln Ave + Altadena CA 91001 + US + +00-1B-93 (hex) JC Decaux SA DNT +001B93 (base 16) JC Decaux SA DNT + 21 rue claude Bernard + MAUREPAS 78310 + FR + +00-1B-9B (hex) Hose-McCann Communications +001B9B (base 16) Hose-McCann Communications + 1241 West Newport Center Drive + Deerfield Beach FL 33442 + US + +00-1B-9C (hex) SATEL sp. z o.o. +001B9C (base 16) SATEL sp. z o.o. + Schuberta 79 + Gdansk pomorskie 80-172 + PL + +00-1B-92 (hex) l-acoustics +001B92 (base 16) l-acoustics + parc de la fontaine de jouvence + marcoussis essonne 91462 + FR + +00-1B-8E (hex) Hulu Sweden AB +001B8E (base 16) Hulu Sweden AB + Box 12328, 10228 + Kista Stockholm 164 40 + SE + +00-1B-45 (hex) ABB AS, Division Automation Products +001B45 (base 16) ABB AS, Division Automation Products + Bergerveien 12 + Billingstad NO-1375 + NO + +00-1B-3F (hex) ProCurve Networking by HP +001B3F (base 16) ProCurve Networking by HP + 60 Alexandra Terrace + 118502 + SG + +00-1B-41 (hex) General Infinity Co.,Ltd. +001B41 (base 16) General Infinity Co.,Ltd. + 3F,No.169, Xing-ai Rd, + Taipei 114 + TW + +00-1B-50 (hex) Nizhny Novgorod Factory named after M.Frunze, FSUE (NZiF) +001B50 (base 16) Nizhny Novgorod Factory named after M.Frunze, FSUE (NZiF) + 174, Gagarina Avenue + Nizhny Novgorod Russia 603950 + RU + +00-1B-47 (hex) Futarque A/S +001B47 (base 16) Futarque A/S + Aagade 15B + Aalborg 9000 + DK + +00-1B-6C (hex) LookX Digital Media BV +001B6C (base 16) LookX Digital Media BV + Roekenveldweg 1 + Brunssum Limburg 6446DK + NL + +00-1B-6B (hex) Swyx Solutions AG +001B6B (base 16) Swyx Solutions AG + Joseph-von-Fraunhofer-straße 13a + Dortmund 44227 + DE + +00-1B-69 (hex) Equaline Corporation +001B69 (base 16) Equaline Corporation + 9F, No. 234, Section 4, Cheng-De Road, + Taipei Hsien 25162 + TW + +00-1B-76 (hex) Ripcode, Inc. +001B76 (base 16) Ripcode, Inc. + 1130 E. Arapaho Road + Richardson TX 75081 + US + +00-1B-70 (hex) IRI Ubiteq, INC. +001B70 (base 16) IRI Ubiteq, INC. + Shinjuku-Nomura Bldg. 47F, + Shinjuku-ku Tokyo 163-0547 + JP + +00-1B-68 (hex) Modnnet Co., Ltd +001B68 (base 16) Modnnet Co., Ltd + 2139 Daemyung-Dong DIP main B/D Room#505, Namgu + Daegu Kyungsang Bookdo 705-701 + KR + +00-1B-62 (hex) JHT Optoelectronics Co.,Ltd. +001B62 (base 16) JHT Optoelectronics Co.,Ltd. + Hetian Industrial Park 2rd,Houjie Town, Donguan, + Dongguan Guangdong 523945 + CN + +00-1B-8A (hex) 2M Electronic A/S +001B8A (base 16) 2M Electronic A/S + Malervej 10 + Taastrup 2630 + DK + +00-1B-80 (hex) LORD Corporation +001B80 (base 16) LORD Corporation + 2000 West Grandview Blvd + Erie Pa 16509 + US + +00-1B-3E (hex) Curtis, Inc. +001B3E (base 16) Curtis, Inc. + 2405 Annapolis Lane + Minneapolis MN 55441 + US + +00-1B-37 (hex) Computec Oy +001B37 (base 16) Computec Oy + Juholankatu 8 + Kouvola Kymi 45200 + FI + +00-1B-07 (hex) Mendocino Software +001B07 (base 16) Mendocino Software + 47001 Benecia St. + Fremont CA 94538 + US + +00-1B-08 (hex) Danfoss Drives A/S +001B08 (base 16) Danfoss Drives A/S + Ulsnaes 1 + Graasten 6300 + DK + +00-1B-01 (hex) Applied Radio Technologies +001B01 (base 16) Applied Radio Technologies + 1124 South Service Road West + Oakville Ontario L6L 5T7 + CA + +00-1B-02 (hex) ED Co.Ltd +001B02 (base 16) ED Co.Ltd + 517-15 SangDaeWon-Dong + SeongNam-City GyeongGi-Do 462-806 + KR + +00-1A-FC (hex) ModusLink Corporation +001AFC (base 16) ModusLink Corporation + 2905 Prestonwood Drive + Plano Texas 75093 + US + +00-1B-10 (hex) ShenZhen Kang Hui Technology Co.,ltd +001B10 (base 16) ShenZhen Kang Hui Technology Co.,ltd + China GuangDong + ShenZhen GuangDong 518109 + CN + +00-1B-0B (hex) Phidgets Inc. +001B0B (base 16) Phidgets Inc. + 2715A 16A Street N.W. + Calgary Alberta T2M 3R7 + CA + +00-1B-0C (hex) Cisco Systems, Inc +001B0C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1A-E0 (hex) Mythology Tech Express Inc. +001AE0 (base 16) Mythology Tech Express Inc. + 2F, No.10, Lane 235, Bao Chiao road, + Taipei 231 + TW + +00-1A-E2 (hex) Cisco Systems, Inc +001AE2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1A-D7 (hex) Christie Digital Systems, Inc. +001AD7 (base 16) Christie Digital Systems, Inc. + 809 Wellington Street North + Kitchener Ontario N2G 4Y7 + CA + +00-1B-23 (hex) SimpleComTools +001B23 (base 16) SimpleComTools + 598 Indian Trail Rd S. + Indian Trail NC 28079 + US + +00-1A-F6 (hex) Woven Systems, Inc. +001AF6 (base 16) Woven Systems, Inc. + 2455 Augustine Drive + Santa Clara CA 95054 + US + +00-1A-F9 (hex) AeroVIronment (AV Inc) +001AF9 (base 16) AeroVIronment (AV Inc) + 4685 Industrial St + Simi Valley CA 93063 + US + +00-1B-30 (hex) Solitech Inc. +001B30 (base 16) Solitech Inc. + 1838 Main Street + Stevensville MD 21666 + US + +00-1B-18 (hex) Tsuken Electric Ind. Co.,Ltd +001B18 (base 16) Tsuken Electric Ind. Co.,Ltd + 3-9 Akedouri Izumi-ku + Sendai City Miyagi 981-3206 + JP + +00-1A-E7 (hex) Aztek Networks, Inc. +001AE7 (base 16) Aztek Networks, Inc. + 2477 55th St. #202 + Boulder CO 80301 + US + +00-1A-95 (hex) Hisense Mobile Communications Technoligy Co.,Ltd. +001A95 (base 16) Hisense Mobile Communications Technoligy Co.,Ltd. + 11,JiangXi Road, + QingDao ShanDong 266071 + CN + +00-1A-81 (hex) Zelax +001A81 (base 16) Zelax + 2nd buid., 1B, Zavodskaya st., + Moscow 124681 + RU + +00-1A-87 (hex) Canhold International Limited +001A87 (base 16) Canhold International Limited + Flat 4, 13/F., Block 4, Tai Ping Industrial Centre + 00852 + HK + +00-1A-88 (hex) Venergy,Co,Ltd +001A88 (base 16) Venergy,Co,Ltd + West 6th Floor,M-8 Building Maqueling Zone, + shenzhen guangdong 518000 + CN + +00-1A-C1 (hex) 3Com Ltd +001AC1 (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +00-1A-BB (hex) Fontal Technology Incorporation +001ABB (base 16) Fontal Technology Incorporation + Rm.522, Bldg. 52, 195, Sec. 4, ChungHsing Rd., Chutung + Hsinchu 310 + TW + +00-1A-BD (hex) Impatica Inc. +001ABD (base 16) Impatica Inc. + 205-1725 St. Laurent Blvd. + Ottawa ON K1G 3V4 + CA + +00-1A-AE (hex) Savant Systems LLC +001AAE (base 16) Savant Systems LLC + 45 Perseverance Way + Hyannis Massachusetts 02601 + US + +00-1A-CD (hex) Tidel Engineering LP +001ACD (base 16) Tidel Engineering LP + 2025 W Belt Line Road Suite 114 + Carrollton TX 75019 + US + +00-1A-C9 (hex) SUZUKEN CO.,LTD +001AC9 (base 16) SUZUKEN CO.,LTD + SUZUKEN TOMEI BLDG. + NAGOYA-SI AICHI-KEN 465-0045 + JP + +00-1A-79 (hex) TELECOMUNICATION TECHNOLOGIES LTD. +001A79 (base 16) TELECOMUNICATION TECHNOLOGIES LTD. + 4D ZHUKOVA BLV. + ODESSA 65121 + UA + +00-1A-AA (hex) Analogic Corp. +001AAA (base 16) Analogic Corp. + 8 Centennial Drive + Peabody MA 01960 + US + +00-1A-8B (hex) CHUNIL ELECTRIC IND., CO. +001A8B (base 16) CHUNIL ELECTRIC IND., CO. + 308,ByuckSan Digital Valley,132-7,Gamjeon-Dong,Sasang-Gu + Busan GyeongSangNamDo 617-800 + KR + +00-1A-8D (hex) AVECS Bergen GmbH +001A8D (base 16) AVECS Bergen GmbH + Billrothstraße 11 a + Bergen auf Rügen M/V 18528 + DE + +00-1A-B4 (hex) FFEI Ltd. +001AB4 (base 16) FFEI Ltd. + Graphics House + Hemel Hempstead Hertfordshire HP2 7SU + GB + +00-1A-B5 (hex) Home Network System +001AB5 (base 16) Home Network System + 107, Hyundai I-Vally + Seongnam-si Gyeonggi-do 462-714 + KR + +00-1A-A4 (hex) Future University-Hakodate +001AA4 (base 16) Future University-Hakodate + 116-2 Kamedanakano-cho + Hakodate Hokkaido 041-8655 + JP + +00-1A-9F (hex) A-Link Ltd +001A9F (base 16) A-Link Ltd + Kylavainiontie 20 + Espoo FI-02760 + FI + +00-1A-74 (hex) Procare International Co +001A74 (base 16) Procare International Co + 5F, No.88, Jhouzih Street, Neihu District + Taipei 114 + TW + +00-1A-BE (hex) COMPUTER HI-TECH INC. +001ABE (base 16) COMPUTER HI-TECH INC. + HigashiUeno3-18-7 + Taitoku Tokyo 110-0015 + JP + +00-1A-19 (hex) Computer Engineering Limited +001A19 (base 16) Computer Engineering Limited + PO Box 493 + Auckland AK 2340 + NZ + +00-1A-18 (hex) Advanced Simulation Technology inc. +001A18 (base 16) Advanced Simulation Technology inc. + 500A Huntmar Park Drive + Herndon VA 20170 + US + +00-1A-58 (hex) CCV Deutschland GmbH - Celectronic eHealth Div. +001A58 (base 16) CCV Deutschland GmbH - Celectronic eHealth Div. + Gertraudenstrasse 18 + Berlin D-10178 + DE + +00-1A-5E (hex) Thincom Technology Co.,Ltd +001A5E (base 16) Thincom Technology Co.,Ltd + 17F-3, No.398, Huanbei Rd., + Zhongli City Taoyuan Contry 320 + TW + +00-1A-5C (hex) Euchner GmbH+Co. KG +001A5C (base 16) Euchner GmbH+Co. KG + Kohlhammerstraße 16 + Leinfelden-Echterdingen BW 70771 + DE + +00-1A-5B (hex) NetCare Service Co., Ltd. +001A5B (base 16) NetCare Service Co., Ltd. + 5-13-16 Shimizu, Asahi-ku + Osaka 535-0021 + JP + +00-1A-24 (hex) Galaxy Telecom Technologies Ltd +001A24 (base 16) Galaxy Telecom Technologies Ltd + No.25, The 1st Gaoxin Road + Xi'an City Shannxi 710075 + CN + +00-1A-20 (hex) CMOTECH Co. Ltd. +001A20 (base 16) CMOTECH Co. Ltd. + 5F Etronix Bldg. 17-10 + Youngdungpo-Gu Seoul 150-874 + KR + +00-1A-4E (hex) NTI AG / LinMot +001A4E (base 16) NTI AG / LinMot + Haerdlistrasse 15 + Spreitenbach AG 8957 + CH + +00-1A-52 (hex) Meshlinx Wireless Inc. +001A52 (base 16) Meshlinx Wireless Inc. + 1410 G Avenue, Suite T + Plano Texas 75074 + US + +00-1A-13 (hex) Wanlida Group Co., LTD +001A13 (base 16) Wanlida Group Co., LTD + Jiahe Road No.618 + Xiamen Fujian 361006 + CN + +00-1A-0F (hex) Sistemas Avanzados de Control, S.A. +001A0F (base 16) Sistemas Avanzados de Control, S.A. + calle Colquide 6 + Las Rozas Madrid 28230 + ES + +00-1A-43 (hex) Logical Link Communications +001A43 (base 16) Logical Link Communications + 1909 Central Drive Suite 205 + Bedford TX 76021 + US + +00-1A-47 (hex) Agami Systems, Inc. +001A47 (base 16) Agami Systems, Inc. + 1269 Innsbruck Drive + Sunnyvale California 94089 + US + +00-1A-2D (hex) The Navvo Group +001A2D (base 16) The Navvo Group + 4400 Baker Road + Minnetonka MN 55343 + US + +00-1A-2F (hex) Cisco Systems, Inc +001A2F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-A9 (hex) Cisco Systems, Inc +0019A9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-AE (hex) Hopling Technologies b.v. +0019AE (base 16) Hopling Technologies b.v. + Camerastraat 10 + Almere Flevoland 1322 BC + NL + +00-19-AF (hex) Rigol Technologies, Inc. +0019AF (base 16) Rigol Technologies, Inc. + No. 156 Cai He Village, Sha He Town + Beijing 102206 + CN + +00-19-DE (hex) MOBITEK +0019DE (base 16) MOBITEK + 5F,No.60,Lane 321,Yang-Kwang Street + Taipei 114 + US + +00-19-E5 (hex) Lynx Studio Technology, Inc. +0019E5 (base 16) Lynx Studio Technology, Inc. + 1540 Barton Rd # 268 + Redlands CA 92373 + US + +00-19-DB (hex) MICRO-STAR INTERNATIONAL CO., LTD. +0019DB (base 16) MICRO-STAR INTERNATIONAL CO., LTD. + NO. 69, LI-DE ST. + JUNG-HE CITY TAIPEI HSIEN 235 + TW + +00-1A-03 (hex) Angel Electronics Co., Ltd. +001A03 (base 16) Angel Electronics Co., Ltd. + 17, Lane 134, Shou Shan Road, Tai Shan, + Taipei 243 + TW + +00-19-F9 (hex) TDK-Lambda +0019F9 (base 16) TDK-Lambda + 405 Essex Road + Neptune NJ 07753 + US + +00-19-CE (hex) Progressive Gaming International +0019CE (base 16) Progressive Gaming International + 920 Pilot Road + Las Vegas NV 89119 + US + +00-19-BD (hex) New Media Life +0019BD (base 16) New Media Life + Hea Ju Bild, 5F, 837-7, Yeoksam-dong + Kangnam-gu Seoul 135-080 + KR + +00-19-F2 (hex) Teradyne K.K. +0019F2 (base 16) Teradyne K.K. + 272-13, Heisei, Takaono + Kikuchi-gun Kumamoto 869-1232 + JP + +00-19-A7 (hex) ITU-T +0019A7 (base 16) ITU-T + Place des Nations + Geneva 20 CH-1211 + CH + +00-19-9F (hex) DKT A/S +00199F (base 16) DKT A/S + Fanoevej 6 + Kr. Saaby DK-4060 + DK + +00-19-8D (hex) Ocean Optics, Inc. +00198D (base 16) Ocean Optics, Inc. + 830 Douglas Ave + Dunedin FL 34698 + US + +00-19-82 (hex) SmarDTV +001982 (base 16) SmarDTV + Route de Genève 22 + Cheseaux CH-1033 + CH + +00-19-85 (hex) IT Watchdogs, Inc +001985 (base 16) IT Watchdogs, Inc + 12885 Research, Suite 210B + Austin TX 78750 + US + +00-19-51 (hex) NETCONS, s.r.o. +001951 (base 16) NETCONS, s.r.o. + Stara Vajnorska 37 + Bratislava Slovakia 831 04 + SK + +00-19-57 (hex) Saafnet Canada Inc. +001957 (base 16) Saafnet Canada Inc. + 107-1089 East Kent Ave (N) + Vancouver BC V5X 4V9 + CA + +00-19-58 (hex) Bluetooth SIG, Inc. +001958 (base 16) Bluetooth SIG, Inc. + 5209 Lake Washington Blvd NE + Kirkland WA 98033 + US + +00-19-56 (hex) Cisco Systems, Inc +001956 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-6B (hex) Danpex Corporation +00196B (base 16) Danpex Corporation + 2114 Ringwood Avenue + San Jose California 95131 + US + +00-19-3D (hex) GMC Guardian Mobility Corp. +00193D (base 16) GMC Guardian Mobility Corp. + Suite 200 + Ottawa ON K2E 7Y8 + CA + +00-19-86 (hex) Cheng Hongjian +001986 (base 16) Cheng Hongjian + Rm.2305B.Sege Plaza,Huaqiang North Rd., + Shenzhen Guangdong 518057 + US + +00-19-9E (hex) Nifty +00199E (base 16) Nifty + miwa4-2-22-105 + Nagano 3800803 + JP + +00-19-6A (hex) MikroM GmbH +00196A (base 16) MikroM GmbH + Dovestraße 1 + Berlin 10587 + DE + +00-18-FF (hex) PowerQuattro Co. +0018FF (base 16) PowerQuattro Co. + János u. 175. + Budapest H-1161 + HU + +00-18-F4 (hex) EO TECHNICS Co., Ltd. +0018F4 (base 16) EO TECHNICS Co., Ltd. + 91, Dongpyeon-ro + Anyang Kyeonggi-Do 431-803 + KR + +00-18-FC (hex) Altec Electronic AG +0018FC (base 16) Altec Electronic AG + Lenggenbachstrasse 3 + Fahrweid Zürich CH-8951 + CH + +00-18-F6 (hex) Thomson Telecom Belgium +0018F6 (base 16) Thomson Telecom Belgium + Prins Boudewijnlaan 47 + Edegem Antwerp B-2650 + BE + +00-18-F5 (hex) Shenzhen Streaming Video Technology Company Limited +0018F5 (base 16) Shenzhen Streaming Video Technology Company Limited + 5/F, Block 3, Software Part No.1, Keji Middle 2 Road, + Shenzhen GaungDong 518057 + CN + +00-18-F9 (hex) VVOND, Inc. +0018F9 (base 16) VVOND, Inc. + 3000 Bridge Parkway + Redwood City CA 94065 + US + +00-19-3B (hex) LigoWave +00193B (base 16) LigoWave + 138 Mountain Brook Drive + Canton GA 30115 + US + +00-19-35 (hex) DUERR DENTAL AG +001935 (base 16) DUERR DENTAL AG + Hoepfigheimer Strasse 17 + Bietigheim-Bissingen Baden-Wuerttemberg 74321 + DE + +00-19-32 (hex) Gude Analog- und Digialsysteme GmbH +001932 (base 16) Gude Analog- und Digialsysteme GmbH + Eintrachstrasse 113 + Cologne NRW 50668 + DE + +00-19-10 (hex) Knick Elektronische Messgeraete GmbH & Co. KG +001910 (base 16) Knick Elektronische Messgeraete GmbH & Co. KG + Beuckestraße 22 + Berlin 14163 + DE + +00-19-13 (hex) Chuang-Yi Network Equipment Co.Ltd. +001913 (base 16) Chuang-Yi Network Equipment Co.Ltd. + 238 TianMuShan Rd., West Lake district + HangZhou ZheJiang 310000 + CN + +00-18-FA (hex) Yushin Precision Equipment Co.,Ltd. +0018FA (base 16) Yushin Precision Equipment Co.,Ltd. + 11-260 KOGAHONMACHI + KYOTO 612-8492 JAP + JP + +00-18-EA (hex) Alltec GmbH +0018EA (base 16) Alltec GmbH + An der Trave 27-31 + Selmsdorf Mecklenburg-Vorpommern 23923 + DE + +00-18-E8 (hex) Hacetron Corporation +0018E8 (base 16) Hacetron Corporation + No. 542, + Yang-Mei, Tao-Yuan, 326 + TW + +00-19-14 (hex) Winix Co., Ltd +001914 (base 16) Winix Co., Ltd + 363 Angade Bldg., Yangjae-dong + Seoul 137-898 + KR + +00-19-06 (hex) Cisco Systems, Inc +001906 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-01 (hex) F1MEDIA +001901 (base 16) F1MEDIA + 610, Keumkang Hightech ¥±, 138-1 Sangdaewon-Dong, Jungwon-Gu + Seongnam-Si Gyeonggi-Do 462-707 + KR + +00-19-31 (hex) Balluff GmbH +001931 (base 16) Balluff GmbH + Schurwaldstraße 9 + Neuhausen BW 73765 + DE + +00-18-E3 (hex) Visualgate Systems, Inc. +0018E3 (base 16) Visualgate Systems, Inc. + 64 Bakersfield Street + Toronto Ontario M3J 2W7 + CA + +00-18-9F (hex) Lenntek Corporation +00189F (base 16) Lenntek Corporation + 4F, 125 GuangMing 3rd. Road + Jhu Bei Hsin Chu 302 + TW + +00-18-99 (hex) ShenZhen jieshun Science&Technology Industry CO,LTD. +001899 (base 16) ShenZhen jieshun Science&Technology Industry CO,LTD. + China GuangDong state Shenzhen City Futian section NO17. Meilin Road + Shenzhen GuangDong 518049 + CN + +00-18-6D (hex) Zhenjiang Sapphire Electronic Industry CO. +00186D (base 16) Zhenjiang Sapphire Electronic Industry CO. + Wei San Road,Dingmao Develop Area + zhenjiang jiangsu 212009 + CN + +00-18-6F (hex) Setha Industria Eletronica LTDA +00186F (base 16) Setha Industria Eletronica LTDA + Rua Alvaro de Macedo 134 + Rio de Janeiro RJ 21.250-620 + BR + +00-18-75 (hex) AnaCise Testnology Pte Ltd +001875 (base 16) AnaCise Testnology Pte Ltd + 3 Bishan Place #02-06 + 579838 + SG + +00-18-C1 (hex) Almitec Informática e Comércio +0018C1 (base 16) Almitec Informática e Comércio + 461, Francisco de Morais St. + São Paulo 04714-010 + BR + +00-18-C4 (hex) Raba Technologies LLC +0018C4 (base 16) Raba Technologies LLC + 8830 Stanford Blvd Suite 205 + Columbia Maryland 21045 + US + +00-18-C9 (hex) EOps Technology Limited +0018C9 (base 16) EOps Technology Limited + Room 2001, Fairmont House, + Hong Kong + HK + +00-18-D8 (hex) ARCH METER Corporation +0018D8 (base 16) ARCH METER Corporation + 4F, No.3-2, Industry E. Rd. + Hsinchu + TW + +00-18-D9 (hex) Santosha Internatonal, Inc +0018D9 (base 16) Santosha Internatonal, Inc + 3843 S. Bristol St. #242 + Santa Ana CA 92704 + US + +00-18-CF (hex) Baldor Electric Company +0018CF (base 16) Baldor Electric Company + 600 S. Zero St. + Fort Smith AR 72901 + US + +00-18-BC (hex) ZAO NVP Bolid +0018BC (base 16) ZAO NVP Bolid + Pionerskaya str., 4 + Korolyov Moscow region 141070 + RU + +00-18-B7 (hex) D3 LED, LLC +0018B7 (base 16) D3 LED, LLC + 380 Mountain Rd + Union City NJ 07087 + US + +00-18-95 (hex) Hansun Technologies Inc. +001895 (base 16) Hansun Technologies Inc. + Room 301, Building 103, Wangjingkejiyuan, Chaoyang District + Beijing 100102 + CN + +00-18-83 (hex) FORMOSA21 INC. +001883 (base 16) FORMOSA21 INC. + 8F-6, NO.351, CHUNG SHAN RD., SEC.2 + TAIPEI 235 + TW + +00-18-8E (hex) Ekahau, Inc. +00188E (base 16) Ekahau, Inc. + Hiilikatu 3 + HELSINKI UUSIMAA 00180 + FI + +00-18-14 (hex) Mitutoyo Corporation +001814 (base 16) Mitutoyo Corporation + 20-1, Sakado 1-chome, Takatsu-ku, + Kawasaki-shi 213-8533 + JP + +00-18-17 (hex) D. E. Shaw Research, LLC +001817 (base 16) D. E. Shaw Research, LLC + 120 W. 45th St., 33rd Floor + New York NY 10036 + US + +00-18-11 (hex) Neuros Technology International, LLC. +001811 (base 16) Neuros Technology International, LLC. + 650 W Lake St + Chicago IL 60661 + US + +00-17-DE (hex) Advantage Six Ltd +0017DE (base 16) Advantage Six Ltd + 208 George St + OLDHAM Lancs OL2 8DR + GB + +00-17-D7 (hex) ION Geophysical Corporation Inc. +0017D7 (base 16) ION Geophysical Corporation Inc. + 850 Dorothy + Richardson Texas 75081 + US + +00-18-37 (hex) Universal ABIT Co., Ltd. +001837 (base 16) Universal ABIT Co., Ltd. + 7F, No. 323 Yangguang St., + Neihu Taipei 114 + TW + +00-18-22 (hex) CEC TELECOM CO.,LTD. +001822 (base 16) CEC TELECOM CO.,LTD. + 10thFL.CEC Building,6 Zhongguancun South Street + Beijing 100086 + CN + +00-18-20 (hex) w5networks +001820 (base 16) w5networks + 48389 Fremont Blvd + Fremont CA 94538 + US + +00-18-5D (hex) TAIGUEN TECHNOLOGY (SHEN-ZHEN) CO., LTD. +00185D (base 16) TAIGUEN TECHNOLOGY (SHEN-ZHEN) CO., LTD. + No. 23, The Third Industrial Park of Xia Village, + Shenzhen City, Guangdong, 815106 + CN + +00-18-5E (hex) Nexterm Inc. +00185E (base 16) Nexterm Inc. + 1-12-3, Shibaura, Minato-ku, + Tokyo 105-0023 + JP + +00-18-28 (hex) e2v technologies (UK) ltd. +001828 (base 16) e2v technologies (UK) ltd. + 106 Waterhouse Lane + Chelmsford Essex CM1 2QU + GB + +00-18-35 (hex) Thoratec / ITC +001835 (base 16) Thoratec / ITC + 2656 Patton Road + Roseville MN 55113 + US + +00-18-01 (hex) Actiontec Electronics, Inc +001801 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +00-17-F3 (hex) Harris Corporation +0017F3 (base 16) Harris Corporation + 1025 West NASA Blvd + Melbourne FL 32919 + US + +00-18-4A (hex) Catcher, Inc. +00184A (base 16) Catcher, Inc. + 5864 Owens Ave. + Carlsbad CA 92008 + US + +00-18-4B (hex) Las Vegas Gaming, Inc. +00184B (base 16) Las Vegas Gaming, Inc. + 4000 West Ali Baba Lane, Suite D + Las Vegas Nevada 89118 + US + +00-18-0E (hex) Avega Systems +00180E (base 16) Avega Systems + 59 Victoria Street + McMahons Point NSW 2060 + AU + +00-17-BC (hex) Touchtunes Music Corporation +0017BC (base 16) Touchtunes Music Corporation + 3 Place du Commerce + Montréal Québec H3E 1H7 + CA + +00-17-C1 (hex) CM Precision Technology LTD. +0017C1 (base 16) CM Precision Technology LTD. + 2 Fl, No. 177, Chien-E Road, Chung-Ho City + Taipei Hsien 235 + TW + +00-17-B2 (hex) SK Telesys +0017B2 (base 16) SK Telesys + 4F, Kyungdong bldg, 4-4, Sunae-Dong, Pundang-Gu + Sungnam-City Kunggi-Do 463-825 + KR + +00-17-B1 (hex) ACIST Medical Systems, Inc. +0017B1 (base 16) ACIST Medical Systems, Inc. + 7450 Flying Cloud Drive + Eden Prairie MN 55344 + US + +00-17-A3 (hex) MIX s.r.l. +0017A3 (base 16) MIX s.r.l. + Via Caldera, 21 + Milan I-20153 + IT + +00-17-A6 (hex) YOSIN ELECTRONICS CO., LTD. +0017A6 (base 16) YOSIN ELECTRONICS CO., LTD. + 6F-2, No.17, Lan 174,Shin-Ming Road + Taipei 114 + TW + +00-17-9C (hex) DEPRAG SCHULZ GMBH u. CO. +00179C (base 16) DEPRAG SCHULZ GMBH u. CO. + Kurfürstenringg 12.18 + Amberg Bayern 92224 + DE + +00-17-96 (hex) Rittmeyer AG +001796 (base 16) Rittmeyer AG + Inwilerriedstrasse 57 + Baar ZG CH-6341 + CH + +00-17-E1 (hex) DACOS Technologies Co., Ltd. +0017E1 (base 16) DACOS Technologies Co., Ltd. + 104 Daeryung-Technotown III 448 + SEOUL Keumcheon-Gu 153-772 + KR + +00-17-E0 (hex) Cisco Systems, Inc +0017E0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-17-D2 (hex) THINLINX PTY LTD +0017D2 (base 16) THINLINX PTY LTD + 31 Carwoola Crescent + Mooloolaba Queensland 4557 + AU + +00-17-85 (hex) Sparr Electronics Ltd +001785 (base 16) Sparr Electronics Ltd + Sparr Electronics Ltd + Bangalore Karnataka 560054 + IN + +00-17-75 (hex) TTE Germany GmbH +001775 (base 16) TTE Germany GmbH + Hermann-Schwer-Straße 3 + Villingen-Schwenningen Baden-Württemberg 78048 + DE + +00-17-B8 (hex) NOVATRON CO., LTD. +0017B8 (base 16) NOVATRON CO., LTD. + #601 polaris bldg., 15-3 jeongja-dong, bundang-gu + Seong Nam Gyeonggi Do 463-811 + KR + +00-17-BB (hex) Syrinx Industrial Electronics +0017BB (base 16) Syrinx Industrial Electronics + De Factorij 13 + Zwaag Noord Holland 1689 AK + NL + +00-17-7C (hex) Smartlink Network Systems Limited +00177C (base 16) Smartlink Network Systems Limited + L-7, Verna Electronic city + Nagoa Goa 403 722 + IN + +00-17-81 (hex) Greystone Data System, Inc. +001781 (base 16) Greystone Data System, Inc. + 40800 Encycopedia Circle + Fremont CA 94538 + US + +00-17-8D (hex) Checkpoint Systems, Inc. +00178D (base 16) Checkpoint Systems, Inc. + 101 Wolf Drive + Thorofare NJ 08086 + US + +00-17-8E (hex) Gunnebo Cash Automation AB +00178E (base 16) Gunnebo Cash Automation AB + Fabriksgatan 10 + Göteborg 402 27 + SE + +00-17-C7 (hex) MARA Systems Consulting AB +0017C7 (base 16) MARA Systems Consulting AB + Instrumentvägen 45 + Stockholm 126 53 + SE + +00-17-5D (hex) Dongseo system. +00175D (base 16) Dongseo system. + 974-21 Mansu-dong Namdong-gu + Incheon In-Cheon 405-865 + KR + +00-17-50 (hex) GSI Group, MicroE Systems +001750 (base 16) GSI Group, MicroE Systems + 8 Erie Drive + Natick MA 01760 + US + +00-17-55 (hex) GE Security +001755 (base 16) GE Security + 12345 SW Leveton Drive + Tualatin OR 97062 + US + +00-17-1D (hex) DIGIT +00171D (base 16) DIGIT + Via Pasteur , 1/3 + S.Pietro Mosezzo NOVARA 28060 + IT + +00-17-18 (hex) Vansco Electronics Oy +001718 (base 16) Vansco Electronics Oy + Tiilenlyojankatu 5 + FORSSA 30101 + FI + +00-17-19 (hex) Audiocodes USA, Inc +001719 (base 16) Audiocodes USA, Inc + 27 World's Fair Drive + Somerset NJ 08873 + US + +00-17-76 (hex) Meso Scale Diagnostics, LLC +001776 (base 16) Meso Scale Diagnostics, LLC + 9238 Gaither Rd. + Gaithersburg MD 20877 + US + +00-17-79 (hex) QuickTel +001779 (base 16) QuickTel + Cornishe El-Nile, Maasara + Cairo 11743 + EG + +00-17-67 (hex) Earforce AS +001767 (base 16) Earforce AS + P.O.Box 4 + Bryne 4349 + NO + +00-17-39 (hex) Bright Headphone Electronics Company +001739 (base 16) Bright Headphone Electronics Company + 8F, 109, Li De Street + Chung Ho City Taipei County 235 + TW + +00-17-2C (hex) TAEJIN INFOTECH +00172C (base 16) TAEJIN INFOTECH + 6F Woolim e-Biz Center, 170-5 + Seoul 152-769 + KR + +00-17-51 (hex) Online Corporation +001751 (base 16) Online Corporation + 22F-3, No. 398, Huan Pei Road, + Chung Li Taoyuan 320 + TW + +00-17-4C (hex) Millipore +00174C (base 16) Millipore + 1, rue Jacques Monod + Guyancourt 78280 + FR + +00-17-11 (hex) GE Healthcare Bio-Sciences AB +001711 (base 16) GE Healthcare Bio-Sciences AB + Björkgatan 30 + Uppsala SE 75184 + SE + +00-17-45 (hex) INNOTZ CO., Ltd +001745 (base 16) INNOTZ CO., Ltd + 14F, Prime Center 546-4 Guui-Dong Kwanggin-Gu + Seoul Seoul + KR + +00-17-48 (hex) Neokoros Brasil Ltda +001748 (base 16) Neokoros Brasil Ltda + Rua 86, numero 501, Setor Sul + Goiania Goias 74083-330 + BR + +00-17-63 (hex) Essentia S.p.A. +001763 (base 16) Essentia S.p.A. + Via G.B. Vico, 29 + Cella (RE) Reggio Emilia 42040 + IT + +00-17-01 (hex) KDE, Inc. +001701 (base 16) KDE, Inc. + KDE TOWN, 42-7, Mangwol-dong + Hanam Gyeonggi-do 465-150 + KR + +00-16-F6 (hex) Video Products Group +0016F6 (base 16) Video Products Group + 1600 Emerson Avenue + Oxnard California 93033 + US + +00-16-EE (hex) Royaldigital Inc. +0016EE (base 16) Royaldigital Inc. + 8F., No.308, Sec.1, Neihu Rd. + Taipei City 114 + TW + +00-16-DE (hex) FAST Inc +0016DE (base 16) FAST Inc + 905 Honeyspot Rd + Stratford CT 06615 + US + +00-16-DA (hex) Futronic Technology Co. Ltd. +0016DA (base 16) Futronic Technology Co. Ltd. + Room 1016A, 10/F., Profit Ind. Bldg., + Kwai Chung 00000 + HK + +00-16-D4 (hex) Compal Communications, Inc. +0016D4 (base 16) Compal Communications, Inc. + 7th, FL, No. 319, Sec. 4, Pa-Teh rd. + Taipei 886 + TW + +00-16-D7 (hex) Sunways AG +0016D7 (base 16) Sunways AG + Macairestraße 3-5 + Konstanz Baden-Württemberg 78467 + DE + +00-16-FF (hex) Wamin Optocomm Mfg Corp +0016FF (base 16) Wamin Optocomm Mfg Corp + No. 239 Qiaohe Road + Zhonghe City Taipei County 235 + TW + +00-16-D1 (hex) ZAT a.s. +0016D1 (base 16) ZAT a.s. + K Podlesi 541 + Pribram VI 26180 + CZ + +00-16-C5 (hex) Shenzhen Xing Feng Industry Co.,Ltd +0016C5 (base 16) Shenzhen Xing Feng Industry Co.,Ltd + Floor 1 - 4, Block 25, Hongtian Jinyuan Industrial, + Shenzhen GuangDong 86 + CN + +00-16-CC (hex) Xcute Mobile Corp. +0016CC (base 16) Xcute Mobile Corp. + 3F. No.25, Ally15, Lane 120, Sec.1, Neihu Rd. + Taipei 114 + TW + +00-17-17 (hex) Leica Geosystems AG +001717 (base 16) Leica Geosystems AG + Heinrich Wild Strasse + Heerbrugg St. Gallen CH-9435 + CH + +00-17-15 (hex) Qstik +001715 (base 16) Qstik + Cartel Business Estate + Harlow Essex CM20 2TT + GB + +00-17-0E (hex) Cisco Systems, Inc +00170E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-17-05 (hex) Methode Electronics +001705 (base 16) Methode Electronics + 7401 W. Wilson + Chicago IL 60706 + US + +00-16-AA (hex) Kei Communication Technology Inc. +0016AA (base 16) Kei Communication Technology Inc. + 8-BAN CHUOU + KOBE HYOGO 650-0024 + JP + +00-16-A8 (hex) CWT CO., LTD. +0016A8 (base 16) CWT CO., LTD. + 10F No. 74 Sec. 1 Chung-Hua Rd. + Taipei 108 + TW + +00-16-A6 (hex) Dovado FZ-LLC +0016A6 (base 16) Dovado FZ-LLC + Al-Thuraya Tower 1, office 504 + Dubai + AE + +00-16-ED (hex) Utility, Inc +0016ED (base 16) Utility, Inc + 250 E Ponce de Leon Ave Suite 700 + Decatur GA 30030 + US + +00-16-C7 (hex) Cisco Systems, Inc +0016C7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-16-71 (hex) Symphox Information Co. +001671 (base 16) Symphox Information Co. + 15F, No. 51, Sec. 3, Minsheng E. Road + Taipei City 104 + TW + +00-16-69 (hex) MRV Communication (Networks) LTD +001669 (base 16) MRV Communication (Networks) LTD + P.O Box 614 + Yokneam 20692 + US + +00-16-68 (hex) Eishin Electronics +001668 (base 16) Eishin Electronics + Nishiku Miyashita 1-19 + Kobe City Hyogo Prefecture 651-2146 + JP + +00-16-40 (hex) Asmobile Communication Inc. +001640 (base 16) Asmobile Communication Inc. + No.11 Lane 120, Li-Te Rd., Peitou 112, Taipei, Taiwan, R.O.C + Taipei 112 + TW + +00-16-3C (hex) Rebox B.V. +00163C (base 16) Rebox B.V. + Hendrik Figeeweg 1X + Haarlem Noord-Holland 2031 BJ + NL + +00-16-7D (hex) Sky-Line Information Co., Ltd. +00167D (base 16) Sky-Line Information Co., Ltd. + 8F.,No.38,Sihyuan Rd., + Sinihuang Taipei 242 + TW + +00-16-77 (hex) Bihl + Wiedemann GmbH +001677 (base 16) Bihl + Wiedemann GmbH + Flosswoerthstr 41 + Mannheim 68199 + DE + +00-16-55 (hex) FUHO TECHNOLOGY Co., LTD +001655 (base 16) FUHO TECHNOLOGY Co., LTD + No. 30, Lane 726, Jinma Rd, Sec. 3 + Chang Hua 500 + TW + +00-16-46 (hex) Cisco Systems, Inc +001646 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-16-48 (hex) SSD Company Limited +001648 (base 16) SSD Company Limited + 3-3-4 Higashiyagura + Kusatsu-city Shiga 525-0054 + JP + +00-16-72 (hex) Zenway enterprise ltd +001672 (base 16) Zenway enterprise ltd + 6F., No.20, Lane 150, Jhongsing Rd., Sijhih City + Taipei 886 + TW + +00-16-5A (hex) Harman Specialty Group +00165A (base 16) Harman Specialty Group + 3 Oak Park Drive + Bedford MA 01730 + US + +00-16-59 (hex) Z.M.P. RADWAG +001659 (base 16) Z.M.P. RADWAG + Bracka 28 street + RADOM Mazowieckie 26-600 + PL + +00-16-A2 (hex) CentraLite Systems, Inc. +0016A2 (base 16) CentraLite Systems, Inc. + 6420 Wall Street + Mobile AL 36695 + US + +00-16-95 (hex) AVC Technology (International) Limited +001695 (base 16) AVC Technology (International) Limited + 6/F Enterprise Square III + Kowloon Bay + HK + +00-15-D8 (hex) Interlink Electronics +0015D8 (base 16) Interlink Electronics + 546 Flynn Road + Camarillo CA 93012 + US + +00-15-D2 (hex) Xantech Corporation +0015D2 (base 16) Xantech Corporation + 13100 Telfair Avenue + Sylmar CA 91342-3573 + US + +00-15-D4 (hex) Emitor AB +0015D4 (base 16) Emitor AB + Sjöviksbacken 14 + Stockholm 117 43 + SE + +00-15-D5 (hex) NICEVT +0015D5 (base 16) NICEVT + Warshawskoe shosse 125 + Moscow 117405 + RU + +00-16-0C (hex) LPL DEVELOPMENT S.A. DE C.V +00160C (base 16) LPL DEVELOPMENT S.A. DE C.V + LAGO GINEBRA 380 P3 + D.F. 11480 + MX + +00-16-12 (hex) Otsuka Electronics Co., Ltd. +001612 (base 16) Otsuka Electronics Co., Ltd. + 1-10 Sasagaoka, Minakuchi + kouka shiga 528-0061 + US + +00-16-0B (hex) TVWorks LLC +00160B (base 16) TVWorks LLC + Two Belvedere Place, #200 + Mill Valley CA 94941 + US + +00-16-03 (hex) COOLKSKY Co., LTD +001603 (base 16) COOLKSKY Co., LTD + Shingsung offcetel A511, 1588-1 Secho + Seoul 137-070 + KR + +00-15-EA (hex) Tellumat (Pty) Ltd +0015EA (base 16) Tellumat (Pty) Ltd + 64/74 White Road + Cape Town Western Province 7945 + ZA + +00-15-E2 (hex) Dr.Ing. Herbert Knauer GmbH +0015E2 (base 16) Dr.Ing. Herbert Knauer GmbH + Hegauer Weg 38 + Berlin 14163 + DE + +00-15-E1 (hex) Picochip Ltd +0015E1 (base 16) Picochip Ltd + Upper Borough Court + Bath BA1 1RG + GB + +00-15-DF (hex) Clivet S.p.A. +0015DF (base 16) Clivet S.p.A. + via Camp Lonc 25 + Feltre Belluno 32030 + IT + +00-16-1D (hex) Innovative Wireless Technologies, Inc. +00161D (base 16) Innovative Wireless Technologies, Inc. + 1047 Vista Park Dr. + Forest VA 24551 + US + +00-16-11 (hex) Altecon Srl +001611 (base 16) Altecon Srl + Via F.lli Cairoli, 17 + Lissone Milano 20035 + IT + +00-16-09 (hex) Unitech electronics co., ltd. +001609 (base 16) Unitech electronics co., ltd. + 5F,No.136,Lane 235 ,Pao-chiao Rd., + Hsin-Tien city Taipei Hsien 231 + TW + +00-15-F5 (hex) Sustainable Energy Systems +0015F5 (base 16) Sustainable Energy Systems + #500, 609 14th Street NW + Calgary Ab T2T 1P3 + CA + +00-15-F1 (hex) KYLINK Communications Corp. +0015F1 (base 16) KYLINK Communications Corp. + 8F-8, No. 351, Sec. 2, Zhongshan Rd., Zhonghe City + 23504 + TW + +00-16-23 (hex) Interval Media +001623 (base 16) Interval Media + 3200 Ash Street + Palo Alto CA 94306 + US + +00-16-19 (hex) Lancelan Technologies S.L. +001619 (base 16) Lancelan Technologies S.L. + C/Angel Guimera 208 bis + Terrassa Barcelona 08223 + ES + +00-16-25 (hex) Impinj, Inc. +001625 (base 16) Impinj, Inc. + 400 Fairview Ave N, Suite 1200 + Seattle WA 98109 + US + +00-15-86 (hex) Xiamen Overseas Chinese Electronic Co., Ltd. +001586 (base 16) Xiamen Overseas Chinese Electronic Co., Ltd. + No. 22, Huli Street, + Xiamen Fujian 361006 + CN + +00-15-7E (hex) Weidmüller Interface GmbH & Co. KG +00157E (base 16) Weidmüller Interface GmbH & Co. KG + Klingenbergstraße 16 + Detmold 32758 + DE + +00-15-80 (hex) U-WAY CORPORATION +001580 (base 16) U-WAY CORPORATION + 3F-2, NO. 125, LANE 235, PAO-CHIAO + HSINTIEN CITY TAIPEI HSIEN 231 + TW + +00-15-7C (hex) Dave Networks, Inc. +00157C (base 16) Dave Networks, Inc. + 2151 O'tool Avenue + San Jose CA 95131 + US + +00-15-7F (hex) ChuanG International Holding CO.,LTD. +00157F (base 16) ChuanG International Holding CO.,LTD. + 1F, NO.12, Alley 1, Lane 125, Guolian Street 4Lirn, Wuhan Village + Taoyuan Longtan 325 + US + +00-15-B3 (hex) Caretech AB +0015B3 (base 16) Caretech AB + Nyborgsvägen 197 + Kalix 95291 + SE + +00-15-AA (hex) Rextechnik International Co., +0015AA (base 16) Rextechnik International Co., + Room 5-3, No.51, Section 2, Keelung Road + Taipei 110 + TW + +00-15-A6 (hex) Digital Electronics Products Ltd. +0015A6 (base 16) Digital Electronics Products Ltd. + Room 301, 3 rd Floor, Tsun Yip Centre + Kwun Tong 852 + HK + +00-15-9D (hex) Tripp Lite +00159D (base 16) Tripp Lite + 1111 W 35th Street + Chicago IL 60609 + US + +00-15-D6 (hex) OSLiNK Sp. z o.o. +0015D6 (base 16) OSLiNK Sp. z o.o. + ul. Marsa 27 + Gdansk 80299 + PL + +00-15-92 (hex) Facom UK Ltd (Melksham) +001592 (base 16) Facom UK Ltd (Melksham) + Lancaster House + Melksham Wiltshire SN104FB + US + +00-15-8B (hex) Park Air Systems Ltd +00158B (base 16) Park Air Systems Ltd + Northfields + Peterborough PE6 8UE + GB + +00-15-76 (hex) LABiTec - Labor Biomedical Technologies GmbH +001576 (base 16) LABiTec - Labor Biomedical Technologies GmbH + An der Strusbek 6 + + DE + +00-15-BE (hex) Iqua Ltd. +0015BE (base 16) Iqua Ltd. + Hyvoninkatu 1 + Salo Varsinais-Suomi 24240 + US + +00-15-C7 (hex) Cisco Systems, Inc +0015C7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-15-5E (hex) Morgan Stanley +00155E (base 16) Morgan Stanley + 750 7th Avenue + New York NY 10019 + US + +00-15-0B (hex) SAGE INFOTECH LTD. +00150B (base 16) SAGE INFOTECH LTD. + 3F, No30, INDUSTRY E. 9TH RD.,SCIENCE-BASED + HSIN-CHU TAIWAN 300 + TW + +00-15-07 (hex) Renaissance Learning Inc +001507 (base 16) Renaissance Learning Inc + 2911 Peach Street + Wisconsin Rapids Wisconsin 54494 + US + +00-15-08 (hex) Global Target Enterprise Inc +001508 (base 16) Global Target Enterprise Inc + 5F, No. 186, Sec. 2, Chung-Hsing Rd., + Hsin Tien, Taipei county 231 + TW + +00-15-02 (hex) BETA tech +001502 (base 16) BETA tech + 15 rue d'apollo + L'UNION 31240 + FR + +00-14-FD (hex) Thecus Technology Corp. +0014FD (base 16) Thecus Technology Corp. + 15F.,No. 79,Sec. 1,Sintai 5th RD., + Sijhih City Taipei County 221 + TW + +00-14-FC (hex) Extandon, Inc. +0014FC (base 16) Extandon, Inc. + 39350 Civic Center Drive Ste. 160 + Fremont CA 94538 + US + +00-14-F8 (hex) Scientific Atlanta +0014F8 (base 16) Scientific Atlanta + 5030 Sugarloaf Parkway + Lawrenceville Ga 30042 + US + +00-14-F7 (hex) CREVIS Co., LTD +0014F7 (base 16) CREVIS Co., LTD + 157-1, Hagal-Dong + Youngin Kyungki 446930 + KR + +00-15-15 (hex) Leipold+Co.GmbH +001515 (base 16) Leipold+Co.GmbH + Kreuzwiese 12 + Rockenhausen RLP D-67806 + DE + +00-15-0F (hex) mingjong +00150F (base 16) mingjong + 8F,NO.1,LANE 16,SZE CHUAN ROAD,SEC.2,PANCHIAO CITY. + TAIPEI 220 + TW + +00-15-5C (hex) Dresser Wayne +00155C (base 16) Dresser Wayne + 3814 Jarrett Way + Austin Texas 78728 + US + +00-15-59 (hex) Securaplane Technologies, Inc. +001559 (base 16) Securaplane Technologies, Inc. + 10800 N. Mavinee Dr. + Tucson AZ 85737 + US + +00-15-57 (hex) Olivetti +001557 (base 16) Olivetti + Via Jervis 77 + Ivrea Torino 10015 + IT + +00-15-54 (hex) Atalum Wireless S.A. +001554 (base 16) Atalum Wireless S.A. + C/ Orellana 5, 1º I + Madrid 28004 + ES + +00-15-3B (hex) EMH metering GmbH & Co. KG +00153B (base 16) EMH metering GmbH & Co. KG + Neu- Galliner Weg 1 + Mecklenburg-Vorpommern + DE + +00-15-37 (hex) Ventus Networks +001537 (base 16) Ventus Networks + 800 Connecticut Ave + Norwalk CT 06854 + US + +00-15-33 (hex) NADAM.CO.,LTD +001533 (base 16) NADAM.CO.,LTD + #91-3 Wangrim-Li + Hwaseong Gyeonggi 445-895 + KR + +00-15-34 (hex) A Beltrónica-Companhia de Comunicações, Lda +001534 (base 16) A Beltrónica-Companhia de Comunicações, Lda + Rua Dr. José Baptista de Sousa, 27 + Lisbon 1549-002 Lis + PT + +00-15-3F (hex) Alcatel Alenia Space Italia +00153F (base 16) Alcatel Alenia Space Italia + Strada Padana Superiore 290 + Vimodrone MI 20090 + IT + +00-15-18 (hex) Shenzhen 10MOONS Technology Development CO.,Ltd +001518 (base 16) Shenzhen 10MOONS Technology Development CO.,Ltd + Add:3F,Huaxing building, QiaoXiang road, + shenzhen guangdong 518053 + CN + +00-15-26 (hex) Remote Technologies Inc +001526 (base 16) Remote Technologies Inc + 5775 12th Ave E, Suite 180 + Shakopee MN 55379 + US + +00-14-F1 (hex) Cisco Systems, Inc +0014F1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-14-EA (hex) S Digm Inc. (Safe Paradigm Inc.) +0014EA (base 16) S Digm Inc. (Safe Paradigm Inc.) + 5F, Shin-an Bldg. 89-8, + Songpa-Gu Seoul 138-201 + KR + +00-14-E5 (hex) Alticast +0014E5 (base 16) Alticast + 16th floor, Nara Bldg, 1328-3 + Seoul 137-070 + KR + +00-14-9F (hex) System and Chips, Inc. +00149F (base 16) System and Chips, Inc. + 4F,No. 1, Lane 50, NanKang Road, Section 3, + Taipei 115 + TW + +00-14-B3 (hex) CoreStar International Corp +0014B3 (base 16) CoreStar International Corp + 1044 Sandy Hill Rd + Irwin PA 15642 + US + +00-14-B1 (hex) Axell Wireless Limited +0014B1 (base 16) Axell Wireless Limited + Aerial HOuse + Chesham Buckinghamshire HP5 2QD + GB + +00-14-E0 (hex) LET'S Corporation +0014E0 (base 16) LET'S Corporation + Bancho Bldg. 4F, 2-18-20 Marunouchi, Naka + Nagoya Aichi 460-0002 + JP + +00-14-E2 (hex) datacom systems inc. +0014E2 (base 16) datacom systems inc. + 9 adler drive + east syracuse n.y. 13057 + US + +00-14-E4 (hex) infinias, LLC +0014E4 (base 16) infinias, LLC + 857 West Carmel Drive + Carmel IN 46032 + US + +00-14-CC (hex) Zetec, Inc. +0014CC (base 16) Zetec, Inc. + 8226 Bracken Place SE + Snoqualmie WA 98065 + US + +00-14-CB (hex) LifeSync Corporation +0014CB (base 16) LifeSync Corporation + 1 E Broward Boulevard, Suite 1701 + Fort Lauderdale Florida 33301 + US + +00-14-C6 (hex) Quixant Ltd +0014C6 (base 16) Quixant Ltd + 61A Mount Pleasant + England Kent TN16 3TP + GB + +00-14-98 (hex) Viking Design Technology +001498 (base 16) Viking Design Technology + 2F, No.2, Lane 42, + Taipei 111 + TW + +00-14-96 (hex) Phonic Corp. +001496 (base 16) Phonic Corp. + 12thFl, 59 Tung Hsing Rd + Taipei 110 + TW + +00-14-93 (hex) Systimax Solutions +001493 (base 16) Systimax Solutions + 1300 E Lookout Drive + Richardson Texas 75082 + US + +00-14-DB (hex) Elma Trenew Electronic GmbH +0014DB (base 16) Elma Trenew Electronic GmbH + Stuttgarter Straße 11 + Pforzheim 75179 + DE + +00-14-3A (hex) RAYTALK INTERNATIONAL SRL +00143A (base 16) RAYTALK INTERNATIONAL SRL + St. Marecchia 79 + Verucchio (RN) 47826 + IT + +00-14-36 (hex) Qwerty Elektronik AB +001436 (base 16) Qwerty Elektronik AB + Gryt 44 + Ösmo 610 60 + SE + +00-14-6B (hex) Anagran, Inc. +00146B (base 16) Anagran, Inc. + 580 North Pastoria Av + Sunnyvale CA 94085 + US + +00-14-61 (hex) CORONA CORPORATION +001461 (base 16) CORONA CORPORATION + 7-7, HIGASHI-SHINBO + SANJO-SHI NIIGATA 955-8510 + JP + +00-14-62 (hex) Digiwell Technology, inc +001462 (base 16) Digiwell Technology, inc + 4F, No.1, Prosperity 1st Road + Hsinchu Science Park 300 + TW + +00-14-63 (hex) IDCS N.V. +001463 (base 16) IDCS N.V. + Hellebeemden 9 + Hasselt Limburg 3500 + BE + +00-14-65 (hex) Novo Nordisk A/S +001465 (base 16) Novo Nordisk A/S + Novo Alle + Bagsvaerd 2880 + DK + +00-14-74 (hex) K40 Electronics +001474 (base 16) K40 Electronics + 600 Tollgate Rd. Unit A + Elgin IL 60123 + US + +00-14-6F (hex) Kohler Co +00146F (base 16) Kohler Co + 444 Highland Drive + Kohler WI 53044 + US + +00-14-66 (hex) Kleinhenz Elektronik GmbH +001466 (base 16) Kleinhenz Elektronik GmbH + Greinerberg 14 + Munich 81371 + DE + +00-14-7F (hex) Thomson Telecom Belgium +00147F (base 16) Thomson Telecom Belgium + Prins Boudewijnlaan 47 + Edegem Antwerp B-2650 + BE + +00-14-75 (hex) Wiline Networks, Inc. +001475 (base 16) Wiline Networks, Inc. + 741 Alexander Rd + Princeton NJ 08540 + US + +00-14-86 (hex) Echo Digital Audio Corporation +001486 (base 16) Echo Digital Audio Corporation + 402 E Carrillo St + Santa Barbara CA 93101 + US + +00-14-82 (hex) Aurora Networks +001482 (base 16) Aurora Networks + 5400 Betsy Ross Drive + Santa Clara CA 95054 + US + +00-14-55 (hex) Coder Electronics Corporation +001455 (base 16) Coder Electronics Corporation + Takeda Bldg, 1-30-6 Shirasagi, + Nakano-ku Tokyo 165-0035 + JP + +00-14-4E (hex) SRISA +00144E (base 16) SRISA + 36/1, Nakhimovskiy pr-t + Moscow 117218 + RU + +00-14-8D (hex) Cubic Defense Simulation Systems +00148D (base 16) Cubic Defense Simulation Systems + 2001 W. Oakridge Road + Orlando FL 32809 + US + +00-14-3D (hex) Aevoe Inc. +00143D (base 16) Aevoe Inc. + 11F, No 23, Keelung Road + Taipei HsinYi District 110 + TW + +00-14-15 (hex) Intec Automation inc. +001415 (base 16) Intec Automation inc. + 2751 Arbutus Rd. + Victoria British Columbia V8N 5X7 + CA + +00-14-10 (hex) Suzhou Keda Technology CO.,Ltd +001410 (base 16) Suzhou Keda Technology CO.,Ltd + 131,Jinshan Road + Suzhou JiangSu 215011 + CN + +00-14-17 (hex) RSE Informations Technologie GmbH +001417 (base 16) RSE Informations Technologie GmbH + Silberbergstrasse 9 + Wolfsberg Kärnten 9400 + AT + +00-14-33 (hex) Empower Technologies(Canada) Inc. +001433 (base 16) Empower Technologies(Canada) Inc. + Unit 405 - 5600 Parkwood Way, + Richmond British Columbia V6V 2M2 + CA + +00-14-34 (hex) Keri Systems, Inc +001434 (base 16) Keri Systems, Inc + 2305 Bering Dr + San Jose CA 95131 + US + +00-13-DE (hex) Adapt4, LLC +0013DE (base 16) Adapt4, LLC + 1050 W Nasa Blvd, + Melbourne FL 32901 + US + +00-13-DD (hex) Abbott Diagnostics +0013DD (base 16) Abbott Diagnostics + 5440 Patrick Henry Drive + Santa Clara CA 95054 + US + +00-13-D7 (hex) SPIDCOM Technologies SA +0013D7 (base 16) SPIDCOM Technologies SA + 137 avenue du General LECLERC + BOURG LA REINE 92340 + FR + +00-13-C7 (hex) IONOS Co.,Ltd. +0013C7 (base 16) IONOS Co.,Ltd. + 1-36-18 Miyasaka + Setagaya-ku Tokyo 156-0051 + JP + +00-14-23 (hex) J-S Co. NEUROCOM +001423 (base 16) J-S Co. NEUROCOM + Energeticheskii proezd, 6 + Moscow 111250 + RU + +00-14-25 (hex) Galactic Computing Corp. +001425 (base 16) Galactic Computing Corp. + 1/F + Chai Wan District + HK + +00-14-19 (hex) SIDSA +001419 (base 16) SIDSA + PTM - TORRES QUEVEDO 1 + TRES CANTOS MADRID 28760 + ES + +00-13-EE (hex) JBX Designs Inc. +0013EE (base 16) JBX Designs Inc. + PO Box 970158 + Boca Raton FL 33497 + US + +00-13-E5 (hex) TENOSYS, INC. +0013E5 (base 16) TENOSYS, INC. + Seojin B/D, 1564-1, Seocho-dong, + Seoul 137-070 + KR + +00-13-E2 (hex) GeoVision Inc. +0013E2 (base 16) GeoVision Inc. + 9F.,No.246,Sec.1, + Taipei 114 + TW + +00-14-02 (hex) kk-electronic a/s +001402 (base 16) kk-electronic a/s + Cypresvej 6 + Herning 7400 + DK + +00-13-FF (hex) Dage-MTI of MC, Inc. +0013FF (base 16) Dage-MTI of MC, Inc. + 701 N. Roeske Ave. + Michigan City IN 46360 + US + +00-13-BC (hex) Artimi Ltd +0013BC (base 16) Artimi Ltd + Betjeman House + Cambridge Cambridgeshire CB2 1LQ + GB + +00-14-08 (hex) Eka Systems Inc. +001408 (base 16) Eka Systems Inc. + 20251 Century Blvd + Germantown MD 20874 + US + +00-13-A7 (hex) BATTELLE MEMORIAL INSTITUTE +0013A7 (base 16) BATTELLE MEMORIAL INSTITUTE + 505 KING AVE + COLUMBUS OHIO 43201 + US + +00-13-A6 (hex) Extricom Ltd +0013A6 (base 16) Extricom Ltd + Glil Yam + Herzlia 46905 + IL + +00-13-A2 (hex) MaxStream, Inc +0013A2 (base 16) MaxStream, Inc + 355 South 520 West Suite 180 + Lindon Ut 84042 + US + +00-13-9F (hex) Electronics Design Services, Co., Ltd. +00139F (base 16) Electronics Design Services, Co., Ltd. + 5-10-20 Tokumaru + Itabashi-ku Tokyo 175-0083 + JP + +00-13-A0 (hex) ALGOSYSTEM Co., Ltd. +0013A0 (base 16) ALGOSYSTEM Co., Ltd. + 656 kobirao mihara-cho + sakai osaka 587-0021 + JP + +00-13-98 (hex) TrafficSim Co.,Ltd +001398 (base 16) TrafficSim Co.,Ltd + 23-9 Mita-biru 2F, Chiyoda 3-chome + Aichi Non 460-0012 + JP + +00-13-9B (hex) ioIMAGE Ltd. +00139B (base 16) ioIMAGE Ltd. + 3 Maskit Street + Herzliya Pituach IL 46733 + IL + +00-13-96 (hex) Acbel Polytech Inc. +001396 (base 16) Acbel Polytech Inc. + No.159,Sec.3, Tam-King Rd., + Tamsui Taipei 251 + TW + +00-13-93 (hex) Panta Systems, Inc. +001393 (base 16) Panta Systems, Inc. + 20450 Stevens Creek Blvd. + Cupertino California 95014 + US + +00-13-8B (hex) Phantom Technologies LLC +00138B (base 16) Phantom Technologies LLC + 7825 Fay Avenue, Suite 200 + La Jolla CA 92037 + US + +00-13-88 (hex) WiMedia Alliance +001388 (base 16) WiMedia Alliance + 2400 Camino Ramon + San Ramon CA 94583 + US + +00-13-6E (hex) Techmetro Corp. +00136E (base 16) Techmetro Corp. + 4F. Dongam B/D., 264-5, YangJae-Dong + Seoul 137-130 + KR + +00-13-6D (hex) Tentaculus AB +00136D (base 16) Tentaculus AB + Studiegangen 3 + Ostersund Jamtland SE - 831 40 + SE + +00-13-6A (hex) Hach Lange Sarl +00136A (base 16) Hach Lange Sarl + 6, route de Compois + VESENAZ GENEVA 1222 + CH + +00-13-B2 (hex) Carallon Limited +0013B2 (base 16) Carallon Limited + Studio G20 Shepherds Building + London W14 0DA + GB + +00-13-AD (hex) Sendo Ltd +0013AD (base 16) Sendo Ltd + Hatchford Brook + Birmingham West Midlands B26 3RZ + GB + +00-13-AA (hex) ALS & TEC Ltd. +0013AA (base 16) ALS & TEC Ltd. + 6 B. Kazachya str. + Saratov Saratov region 410600 + RU + +00-13-A4 (hex) KeyEye Communications +0013A4 (base 16) KeyEye Communications + 9785 Goethe + Sacramento CA 95827 + US + +00-13-4D (hex) Inepro BV +00134D (base 16) Inepro BV + Pondweg 7 + Nieuw- Vennep + NL + +00-13-4B (hex) ToGoldenNet Technology Inc. +00134B (base 16) ToGoldenNet Technology Inc. + 5F-1 No.25,Pu-ding., + Hsin-Chu 300 + TW + +00-13-84 (hex) Advanced Motion Controls +001384 (base 16) Advanced Motion Controls + 3805 Calle Tecate + Camarillo California 93012 + US + +00-13-7B (hex) Movon Corporation +00137B (base 16) Movon Corporation + 5th, Hyunjuk B/D + Seoul 135-092 + KR + +00-13-53 (hex) HYDAC Filtertechnik GMBH +001353 (base 16) HYDAC Filtertechnik GMBH + Industriegebiet + Sulzbach/Saar Saarland 66280 + DE + +00-13-63 (hex) Verascape, Inc. +001363 (base 16) Verascape, Inc. + 1101 31st St., Suite #190 + Downers Grove IL 60515 + US + +00-13-03 (hex) GateConnect +001303 (base 16) GateConnect + Eisenhutweg 69 + 12487 Berlin 12487 + DE + +00-13-04 (hex) Flaircomm Technologies Co. LTD +001304 (base 16) Flaircomm Technologies Co. LTD + 2088 Huashan Road + Shanghai 200030 + CN + +00-12-F9 (hex) URYU SEISAKU, LTD. +0012F9 (base 16) URYU SEISAKU, LTD. + 1-2-11 + HIGASHINARI-KU OSAKA 537-0002 + JP + +00-12-F3 (hex) connectBlue AB +0012F3 (base 16) connectBlue AB + Norra Vallgatan 64 + Malmoe SE-211 22 + SE + +00-13-37 (hex) Orient Power Home Network Ltd. +001337 (base 16) Orient Power Home Network Ltd. + 307 Harbour Centre, Tower 1, + + HK + +00-13-34 (hex) Arkados, Inc. +001334 (base 16) Arkados, Inc. + 948 US HWY 22 + North Plainfield NJ 07060 + US + +00-13-32 (hex) Beijing Topsec Network Security Technology Co., Ltd. +001332 (base 16) Beijing Topsec Network Security Technology Co., Ltd. + Huakong Tower + Haidian District Beijing 100085 + CN + +00-13-1F (hex) NxtPhase T&D, Corp. +00131F (base 16) NxtPhase T&D, Corp. + 3040 E. Broadway + Vancouver BC V5M 1Z4 + CA + +00-12-DC (hex) SunCorp Industrial Limited +0012DC (base 16) SunCorp Industrial Limited + No.68 Guowei Road, + Liantang Industrial District, Shenzhen, + CN + +00-12-FF (hex) Lely Industries N.V. +0012FF (base 16) Lely Industries N.V. + Weverskade 110 + Maassluis Zuid-Holland 3147PA + NL + +00-13-3A (hex) VadaTech Inc. +00133A (base 16) VadaTech Inc. + 11540 S. Eastern Avenue + Henderson Nevada 89052 + US + +00-13-2A (hex) Sitronics Telecom Solutions +00132A (base 16) Sitronics Telecom Solutions + Michelska 60 + Prague Prague 4 - Michle 140 00 + CZ + +00-12-E5 (hex) Time America, Inc. +0012E5 (base 16) Time America, Inc. + 51 W. 3rd Street #310 + Tempe AZ 85281 + US + +00-13-0E (hex) Focusrite Audio Engineering Limited +00130E (base 16) Focusrite Audio Engineering Limited + 19 Lincoln Road + High Wycombe Bucks HP12 3FX + GB + +00-13-09 (hex) Ocean Broadband Networks +001309 (base 16) Ocean Broadband Networks + 2078 Walsh Ave, Suite B + Santa Clara California 95050 + US + +00-13-19 (hex) Cisco Systems, Inc +001319 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-13-1C (hex) LiteTouch, Inc. +00131C (base 16) LiteTouch, Inc. + 3400 South West Temple + Salt Lake City UT 84115 + US + +00-13-4A (hex) Engim, Inc. +00134A (base 16) Engim, Inc. + 40 Nagog Park + Acton MA 01720 + US + +00-12-D7 (hex) Invento Networks, Inc. +0012D7 (base 16) Invento Networks, Inc. + 377 Simarano Drive + Marlborough MA 01752 + US + +00-12-C4 (hex) Viseon, Inc. +0012C4 (base 16) Viseon, Inc. + 8445 Freeport Parkway + Irving Texas 75063 + US + +00-12-93 (hex) GE Energy +001293 (base 16) GE Energy + 1501 Roanoke Blvd. + Salem VA 24153 + US + +00-12-94 (hex) SUMITOMO ELECTRIC DEVICE INNOVATIONS, INC +001294 (base 16) SUMITOMO ELECTRIC DEVICE INNOVATIONS, INC + 1000 Kamisukiawara,Showa-cho + Nakakoma-gun Yamanashi 409-3883 + JP + +00-12-96 (hex) Addlogix +001296 (base 16) Addlogix + 459 Wald + Irvine CA 92618 + US + +00-12-B3 (hex) Advance Wireless Technology Corp. +0012B3 (base 16) Advance Wireless Technology Corp. + 12F No. 27-6, Sec. 2, Chung Cheng East Road + Tamshui 251 + TW + +00-12-B0 (hex) Efore Oyj (Plc) +0012B0 (base 16) Efore Oyj (Plc) + Quartetto Business Park + Espoo FI - 02600 + FI + +00-12-7F (hex) Cisco Systems, Inc +00127F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-12-A6 (hex) Dolby Australia +0012A6 (base 16) Dolby Australia + Level 6 + Surry Hills NSW 2010 + AU + +00-12-A4 (hex) ThingMagic, LLC +0012A4 (base 16) ThingMagic, LLC + One Broadway + Cambridge MA 02142 + US + +00-12-A9 (hex) 3Com Ltd +0012A9 (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +00-12-D0 (hex) Gossen-Metrawatt-GmbH +0012D0 (base 16) Gossen-Metrawatt-GmbH + Thomas-Mann-Straße 16-20 + Nürnberg Bavaria 90471 + DE + +00-12-99 (hex) Ktech Telecommunications Inc +001299 (base 16) Ktech Telecommunications Inc + 21540 Prairie Street Unit B + Chatsworth CA 91311 + US + +00-12-8C (hex) Woodward Governor +00128C (base 16) Woodward Governor + 1000 E. Drake Road + Ft. Collins CO 80525 + US + +00-12-B8 (hex) G2 Microsystems +0012B8 (base 16) G2 Microsystems + 408 Euclid Ave + Oakland CA 94610 + US + +00-12-7B (hex) VIA Networking Technologies, Inc. +00127B (base 16) VIA Networking Technologies, Inc. + 8F,533, Chung-Cheng Road, Hsin-Tien + Taipei 231 + TW + +00-12-80 (hex) Cisco Systems, Inc +001280 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-12-75 (hex) Sentilla Corporation +001275 (base 16) Sentilla Corporation + 201 Marshall Street + Redwood City CA 94063 + US + +00-12-76 (hex) CG Power Systems Ireland Limited +001276 (base 16) CG Power Systems Ireland Limited + Herbert House., Harmony Row, + Dublin D2 + IE + +00-12-71 (hex) Measurement Computing Corp +001271 (base 16) Measurement Computing Corp + 10 Commerce Way + Norton MA 02766 + US + +00-12-73 (hex) Stoke Inc +001273 (base 16) Stoke Inc + 2189 Leghorn Street + Mountain View CA 94043 + US + +00-12-69 (hex) Value Electronics +001269 (base 16) Value Electronics + Dong-kwan B/D, 5F, 1566-2 + seoul 137-874 + KR + +00-12-50 (hex) Tokyo Aircaft Instrument Co., Ltd. +001250 (base 16) Tokyo Aircaft Instrument Co., Ltd. + 1-35-1, Izumi-Honcho + Komae-Shi Tokyo 201-8555 + JP + +00-12-52 (hex) Citronix, LLC +001252 (base 16) Citronix, LLC + 2214 South Watson Road + Arlington Texas 76010 + US + +00-12-40 (hex) AMOI ELECTRONICS CO.,LTD +001240 (base 16) AMOI ELECTRONICS CO.,LTD + 295 Lane,Zuchongzhi Road,Zhang jiang, + Shanghai 201203 + CN + +00-12-2E (hex) Signal Technology - AISD +00122E (base 16) Signal Technology - AISD + 1820 Preston Park Blvd. + Plano TX 75093 + US + +00-12-64 (hex) daum electronic gmbh +001264 (base 16) daum electronic gmbh + flugplatzstraße 100 + Fürth Bavaria 90768 + DE + +00-12-61 (hex) Adaptix, Inc +001261 (base 16) Adaptix, Inc + 1407 116th Ave. NE + Bellevue WA 98004 + US + +00-12-60 (hex) Stanton Magnetics,inc. +001260 (base 16) Stanton Magnetics,inc. + 3000 SW 42nd Street + Hollywood FL 33312 + US + +00-12-31 (hex) Motion Control Systems, Inc. +001231 (base 16) Motion Control Systems, Inc. + PO Box 115 + New River VA 24129 + US + +00-12-4B (hex) Texas Instruments +00124B (base 16) Texas Instruments + Gaustadalleen 21 + Oslo N-0349 + NO + +00-12-4A (hex) Dedicated Devices, Inc. +00124A (base 16) Dedicated Devices, Inc. + 5680 E. Franklin Road + Nampa Idaho 83687 + US + +00-12-43 (hex) Cisco Systems, Inc +001243 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-D9 (hex) TiVo +0011D9 (base 16) TiVo + 2160 Gold Ave + Alviso CA 95002-2160 + US + +00-11-D2 (hex) Perception Digital Ltd +0011D2 (base 16) Perception Digital Ltd + Flat A, 8/F, Shaw House + Clear Water Bay NT + HK + +00-11-CF (hex) Thrane & Thrane A/S +0011CF (base 16) Thrane & Thrane A/S + Lundtoftegårdsvej 93D + Lyngby København 2800 + DK + +00-11-D4 (hex) NetEnrich, Inc +0011D4 (base 16) NetEnrich, Inc + 890 Hillview Ct. + Milpitas CA 95035 + US + +00-11-D5 (hex) Hangzhou Sunyard System Engineering Co.,Ltd. +0011D5 (base 16) Hangzhou Sunyard System Engineering Co.,Ltd. + Sunyard Science & Technology Building Hi-Tech Software Park(Second Land Consolidation) + Hangzhou Zhejiang 310053 + CN + +00-11-F8 (hex) AIRAYA Corp +0011F8 (base 16) AIRAYA Corp + 637 Adair Court + Morgan Hill CA 95037 + US + +00-11-F4 (hex) woori-net +0011F4 (base 16) woori-net + #508, Hankook Moolyu, 853-1 Dongchun-Dong + Yongin-Si Kyungki-Do 449-843 + KR + +00-11-F6 (hex) Asia Pacific Microsystems , Inc. +0011F6 (base 16) Asia Pacific Microsystems , Inc. + No.2,R&D Road 6 ,Science-Based Industrial Park, + Hsinchu 300 + TW + +00-11-F0 (hex) Wideful Limited +0011F0 (base 16) Wideful Limited + F5, 3/F., Phase II, Superluck Industrial Centre, + + HK + +00-11-F1 (hex) QinetiQ Ltd +0011F1 (base 16) QinetiQ Ltd + Room E601 + Malvern Worcestershire WR14 3PS + GB + +00-11-ED (hex) 802 Global +0011ED (base 16) 802 Global + Studio 11,Intec 2,Wade Road + Hampshire RG24 BNE + GB + +00-12-11 (hex) Protechna Herbst GmbH & Co. KG +001211 (base 16) Protechna Herbst GmbH & Co. KG + Otto Hahn Str. 26 + Ottobrunn Germany/Bavaria 85521 + DE + +00-12-19 (hex) General Datacomm LLC +001219 (base 16) General Datacomm LLC + 353 Christian Street, Suite 4 + Oxford CT 06478 + US + +00-12-16 (hex) ICP Internet Communication Payment AG +001216 (base 16) ICP Internet Communication Payment AG + Wilhelm-Stein-Weg 24 + Hamburg D-22339 + DE + +00-12-15 (hex) iStor Networks, Inc. +001215 (base 16) iStor Networks, Inc. + 7585 Irvine Center Drive + Irvine CA 92618 + US + +00-12-03 (hex) ActivNetworks +001203 (base 16) ActivNetworks + BAT L - 1 rue de Terre Neuve + COURTABOEUF 91944 + FR + +00-11-CC (hex) Guangzhou Jinpeng Group Co.,Ltd. +0011CC (base 16) Guangzhou Jinpeng Group Co.,Ltd. + No.9 Shenzhou Road,Guangzhou Science City + Guangzhou Guangdong 510663 + CN + +00-11-C7 (hex) Raymarine UK Ltd +0011C7 (base 16) Raymarine UK Ltd + Marine House + Fareham Hampshire PO15 5RJ + GB + +00-11-C9 (hex) MTT Corporation +0011C9 (base 16) MTT Corporation + 2-7-12 + Nishi-ku Kobe 651-2241 + JP + +00-11-DB (hex) Land-Cellular Corporation +0011DB (base 16) Land-Cellular Corporation + 12054 Miramar Parkway + Miramar FL 33025 + US + +00-12-24 (hex) NexQL Corporation +001224 (base 16) NexQL Corporation + 12250 Inwood Road #6 + Dallas TX 75244 + US + +00-11-BD (hex) Bombardier Transportation +0011BD (base 16) Bombardier Transportation + 1501 Lebanon Church Road + Pittsburgh PA 15236 + US + +00-11-AA (hex) Uniclass Technology, Co., LTD +0011AA (base 16) Uniclass Technology, Co., LTD + 4F, No. 98, Ming chuan Rd + Hsintien City Taipei Hsien 231 + TW + +00-11-79 (hex) Singular Technology Co. Ltd. +001179 (base 16) Singular Technology Co. Ltd. + 21F, No.37, Sec.2, San Min Rd., + Taipei 220 + TW + +00-11-8A (hex) Viewtran Technology Limited +00118A (base 16) Viewtran Technology Limited + 3/F, R2-A builiding, High Tech Industrial Park, + Shenzhen Guangdong 518057 + CN + +00-11-84 (hex) Humo Laboratory,Ltd. +001184 (base 16) Humo Laboratory,Ltd. + Nishiogi-Kita 5-19-11 + Suginami-ku Tokyo 167-0042 + JP + +00-11-B1 (hex) BlueExpert Technology Corp. +0011B1 (base 16) BlueExpert Technology Corp. + 8F,No.16,Lane 77,Xing-Ai Rd,Nei-Hu District + Taipei 11494 + TW + +00-11-A6 (hex) Sypixx Networks +0011A6 (base 16) Sypixx Networks + 108 Bank Street + Waterbury CT 06702 + US + +00-11-B5 (hex) Shenzhen Powercom Co.,Ltd +0011B5 (base 16) Shenzhen Powercom Co.,Ltd + Floor 16,Tower B,Zhongyin Building,North Caitian Road,Futian District,Shenzhen,P.R.China + Shenzhen Guangdong province 518028 + CN + +00-11-BB (hex) Cisco Systems, Inc +0011BB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-66 (hex) Taelim Electronics Co., Ltd. +001166 (base 16) Taelim Electronics Co., Ltd. + 196-5, ANYANG7-DONG MANAN-GU + ANYANG-SI KYUGGI-DO 430-817 + KR + +00-11-64 (hex) ACARD Technology Corp. +001164 (base 16) ACARD Technology Corp. + 6F No.78 Sec1 Kwang Fu Road, Sanchung, + Taipei Hsien 241 + TW + +00-11-A2 (hex) Manufacturing Technology Inc +0011A2 (base 16) Manufacturing Technology Inc + 70 Ready Ave NW + Fort Walton Beach FL 32548 + US + +00-11-9E (hex) Solectron Brazil +00119E (base 16) Solectron Brazil + Rod. Campinas Mogi Mirim + Jaguariuna SP 13820-000 + BR + +00-11-73 (hex) SMART Storage Systems +001173 (base 16) SMART Storage Systems + 2600 W Geronimo Place + Chandler AZ 85224 + US + +00-11-25 (hex) IBM Corp +001125 (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-11-1C (hex) Pleora Technologies Inc. +00111C (base 16) Pleora Technologies Inc. + 359 Terry Fox Drive, Suite 230 + Kanata ON K2K 2E7 + CA + +00-11-1F (hex) Doremi Labs, Inc. +00111F (base 16) Doremi Labs, Inc. + 306 E. Alameda Ave. + Burbank CA 91502 + US + +00-11-1D (hex) Hectrix Limited +00111D (base 16) Hectrix Limited + Unit 906-911, 9/F, Stanhope Hosue, + North Point Hong Kong + CN + +00-11-19 (hex) Solteras, Inc. +001119 (base 16) Solteras, Inc. + 900 W. Santa Anita Street + San Gabriel CA 91776 + US + +00-11-50 (hex) Belkin Corporation +001150 (base 16) Belkin Corporation + 501 West Walnut Street + Compton CA 90220-5221 + US + +00-11-46 (hex) Telecard-Pribor Ltd +001146 (base 16) Telecard-Pribor Ltd + Lustdorfskaya doroga, 162 + Odessa 65115 + UA + +00-11-0D (hex) SANBlaze Technology, Inc. +00110D (base 16) SANBlaze Technology, Inc. + 2 Clock Tower Place + Maynard MA 01748 + US + +00-11-06 (hex) Siemens NV (Belgium) +001106 (base 16) Siemens NV (Belgium) + Atealaan 34 + Herentals Antwerp 2200 + BE + +00-0F-F4 (hex) Guntermann & Drunck GmbH +000FF4 (base 16) Guntermann & Drunck GmbH + Obere Leimbach 9 + Siegen NRW 57074 + DE + +00-0F-F8 (hex) Cisco Systems, Inc +000FF8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-2C (hex) IZT GmbH +00112C (base 16) IZT GmbH + Am Weichselgarten 5 + Erlangen Bavaria 91058 + DE + +00-11-14 (hex) EverFocus Electronics Corp. +001114 (base 16) EverFocus Electronics Corp. + 12F, No. 79, Sec. 1, Shin-Tai Wu Rd. + Hsi-Chi Taipei Hsien 221 + TW + +00-11-0E (hex) Tsurusaki Sealand Transportation Co. Ltd. +00110E (base 16) Tsurusaki Sealand Transportation Co. Ltd. + 1000 Misa + Oita 8700196 + JP + +00-11-4C (hex) caffeina applied research ltd. +00114C (base 16) caffeina applied research ltd. + 125 baird ave + cochrane alberta t4c 1c7 + CA + +00-11-41 (hex) GoodMan Corporation +001141 (base 16) GoodMan Corporation + 2F, No.572, Sec.1, Ming-Sheng N Road, Kwei-Shan Hsiang + Taoyuan Hsien 33300 + TW + +00-11-55 (hex) Sevis Systems +001155 (base 16) Sevis Systems + 2805 N Dallas Parkway, STE 530 + Plano Texas 75093 + US + +00-11-52 (hex) Eidsvoll Electronics AS +001152 (base 16) Eidsvoll Electronics AS + Nedre Vilberg vei 8 + Eidsvoll N-2080 + NO + +00-0F-CF (hex) DataWind Research +000FCF (base 16) DataWind Research + 555 Rene-Levesque West + Montreal Quebec H2Z 1B1 + CA + +00-0F-D2 (hex) EWA Technologies, Inc. +000FD2 (base 16) EWA Technologies, Inc. + 13873 Park Center Road + Herndon VA 20171 + US + +00-0F-CE (hex) Kikusui Electronics Corp. +000FCE (base 16) Kikusui Electronics Corp. + 1-1-3,Higashi yamata + Yokohama Kanagawa 224-0023 + JP + +00-0F-EB (hex) Cylon Controls +000FEB (base 16) Cylon Controls + Clonshaugh Industrial Estate + Dublin 17 + IE + +00-0F-DC (hex) Ueda Japan Radio Co., Ltd. +000FDC (base 16) Ueda Japan Radio Co., Ltd. + Fumiiri 2-10-19 + Ueda city Nagano prefecture 386-8608 + JP + +00-0F-8E (hex) DONGYANG TELECOM CO.,LTD. +000F8E (base 16) DONGYANG TELECOM CO.,LTD. + 642-7, DEUNGCHON-DONG, KANGSEO-GU + SEOUL KANGSE-GU 157-841 + KR + +00-0F-91 (hex) Aerotelecom Co.,Ltd. +000F91 (base 16) Aerotelecom Co.,Ltd. + 195-58 Anyang 7 Dong + Anyang Kyunggi 430-817 + US + +00-0F-87 (hex) Maxcess International +000F87 (base 16) Maxcess International + 222 W. Memorial Road + Oklahoma City OK 73114 + US + +00-0F-A1 (hex) Gigabit Systems Inc. +000FA1 (base 16) Gigabit Systems Inc. + Fuyoh Video Building 3F + Yokohama Kanagawa 241-0826 + JP + +00-0F-99 (hex) APAC opto Electronics Inc. +000F99 (base 16) APAC opto Electronics Inc. + 3 Tzu Chiang Road, Hsinchu Industrial Park + Hukow, Hsinchu Hsien 303 + TW + +00-0F-F5 (hex) GN&S company +000FF5 (base 16) GN&S company + 301 Ansan S/W center, 643-7 wongok-dong + Ansan city Gyeonggi-do 425-130 + KR + +00-0F-E8 (hex) Lobos, Inc. +000FE8 (base 16) Lobos, Inc. + U&T Bldg 3F, 1-2-3 Sarugaku-cho, Chiyoda-ku, + Tokyo 101-0064 + JP + +00-0F-B2 (hex) Broadband Pacenet (India) Pvt. Ltd. +000FB2 (base 16) Broadband Pacenet (India) Pvt. Ltd. + 7-B, Shah Industrial Estate, Off Veera Desai Road + Mumbai Maharashtra 400 053 + IN + +00-0F-D7 (hex) Harman Music Group +000FD7 (base 16) Harman Music Group + 8760 Sandy Parkway + Sandy Utah 84070 + US + +00-0F-D4 (hex) Soundcraft +000FD4 (base 16) Soundcraft + Cranborne House + Potters Bar Hertfordshire EN6 3JN + GB + +00-0F-AF (hex) Dialog Inc. +000FAF (base 16) Dialog Inc. + 1-47-9 + Toshima-ku Tokyo 1700013 + JP + +00-0F-A5 (hex) BWA Technology GmbH +000FA5 (base 16) BWA Technology GmbH + Johann-Krane-Weg 21 + Muenster 48149 + DE + +00-0F-80 (hex) Trinity Security Systems,Inc. +000F80 (base 16) Trinity Security Systems,Inc. + Alte Building Higashi Kanda 8F + Chiyoda-ku Tokyo 101-0031 + JP + +00-0F-32 (hex) Lootom Telcovideo Network Wuxi Co Ltd +000F32 (base 16) Lootom Telcovideo Network Wuxi Co Ltd + 5F, 9Building, + WuXi JiangSu 214072 + CN + +00-0F-2A (hex) Cableware Electronics +000F2A (base 16) Cableware Electronics + 1702 Western Ave. + Las Vegas Nevada 89102 + US + +00-0F-29 (hex) Augmentix Corporation +000F29 (base 16) Augmentix Corporation + 4030 W Braker Ln + Austin Texas 78759 + US + +00-0F-27 (hex) TEAL Electronics, Inc. +000F27 (base 16) TEAL Electronics, Inc. + 10350 Sorrento Valley Road + San Diego California 92121 + US + +00-0F-43 (hex) Wasabi Systems Inc. +000F43 (base 16) Wasabi Systems Inc. + 500 E. Main Street + Norfolk VA 23510 + US + +00-0F-48 (hex) Polypix Inc. +000F48 (base 16) Polypix Inc. + 1Fl, Sungdo Venture Tower, 165-2 Samsung-Dong, Kangnam-Ku + Seoul 135-881 + KR + +00-0F-50 (hex) StreamScale Limited +000F50 (base 16) StreamScale Limited + The Court, Alexandra Park + St Helens WA10 3TP + GB + +00-0F-4E (hex) Cellink +000F4E (base 16) Cellink + Catherinalaan 37 + Rotselaar Vlaams Brabant B-3110 + BE + +00-0F-47 (hex) ROBOX SPA +000F47 (base 16) ROBOX SPA + via Sempione 82 + Castelletto S.Ticino NO 28053 + IT + +00-0F-18 (hex) Industrial Control Systems +000F18 (base 16) Industrial Control Systems + Houtschelf 1 + Hardinxveld Zuid-Holland NL-3371 KB + NL + +00-0F-1D (hex) Cosmo Techs Co., Ltd. +000F1D (base 16) Cosmo Techs Co., Ltd. + 2-6-1, Matsue + Atsugi-shi Kanagawa-ken 243-0005 + JP + +00-0F-1B (hex) Ego Systems Inc. +000F1B (base 16) Ego Systems Inc. + 1206 Woolim e-Biz Center II + Seoul 150-834 + KR + +00-0F-78 (hex) Datacap Systems Inc +000F78 (base 16) Datacap Systems Inc + 100 New Britain Blvd + Chalfont PA 18914 + US + +00-0F-70 (hex) Wintec Industries, inc. +000F70 (base 16) Wintec Industries, inc. + 675 Sycamore Drive + Milpitas, CA 95035 + US + +00-0F-74 (hex) Qamcom Technology AB +000F74 (base 16) Qamcom Technology AB + Gruvgatan 8 + Vastra Frolunda + SE + +00-0F-6D (hex) Midas Engineering +000F6D (base 16) Midas Engineering + Ace Techno-Tower V #906 197-22 + Seoul 152-848 + KR + +00-0F-5F (hex) Nicety Technologies Inc. (NTS) +000F5F (base 16) Nicety Technologies Inc. (NTS) + 792-3 Tomioka Toyoda-cho + Iwata-gun Shizuoka 438-0803 + JP + +00-0F-5A (hex) Peribit Networks +000F5A (base 16) Peribit Networks + 2855 Bowers Ave + Santa Clara CA 95051 + US + +00-0F-31 (hex) Allied Vision Technologies Canada Inc +000F31 (base 16) Allied Vision Technologies Canada Inc + 101-3750 North Fraser Way + Burnaby BC V5J 5E9 + CA + +00-0F-73 (hex) RS Automation Co., Ltd +000F73 (base 16) RS Automation Co., Ltd + 447-6, Gongse-Dong , Giheung-Gu + Youngin-City Gyeonggi-Do 449-902 + KR + +00-0F-3C (hex) Endeleo Limited +000F3C (base 16) Endeleo Limited + 78 Cannon Street + London England EC4N 6NQ + GB + +00-0E-AB (hex) Cray Inc +000EAB (base 16) Cray Inc + 901 Fifth Avenue + Seattle WA 98104 + US + +00-0E-AD (hex) Metanoia Technologies, Inc. +000EAD (base 16) Metanoia Technologies, Inc. + 5918 W. courtyard Dr. + Austin TX 78730 + US + +00-0E-AF (hex) CASTEL +000EAF (base 16) CASTEL + ZI Saint Lambert des Levées + SAUMUR Maine et Loire 49412 + FR + +00-0E-F8 (hex) SBC ASI +000EF8 (base 16) SBC ASI + Network & Infrastructure Technical Support + San Antonio Texas 78215 + US + +00-0E-F9 (hex) REA Elektronik GmbH +000EF9 (base 16) REA Elektronik GmbH + Teichwiesenstraße 1 + Muehltal Hessen 64367 + DE + +00-0E-E6 (hex) Adimos Systems LTD +000EE6 (base 16) Adimos Systems LTD + 17 Atirey-Yeda Street + Kfar-Saba 44643 + IL + +00-0E-F6 (hex) E-TEN Information Systems Co., Ltd. +000EF6 (base 16) E-TEN Information Systems Co., Ltd. + No. 256, Yangguang Street, Neihu Chiu + Taipei 114 + TW + +00-0E-EA (hex) Shadong Luneng Jicheng Electronics,Co.,Ltd +000EEA (base 16) Shadong Luneng Jicheng Electronics,Co.,Ltd + No.188,east,Huayuan Road + Jinan Shandong 250100 + CN + +00-0F-0F (hex) Real ID Technology Co., Ltd. +000F0F (base 16) Real ID Technology Co., Ltd. + 9F Hanmi B/D 192-19 + Gangnam-Gu Seoul 135-010 + KR + +00-0F-16 (hex) JAY HOW TECHNOLOGY CO., +000F16 (base 16) JAY HOW TECHNOLOGY CO., + NO.486,SEC. 1, WAN SHOU RD., KUEI + TAOYUAN HSIEN 333 + TW + +00-0E-C6 (hex) ASIX ELECTRONICS CORP. +000EC6 (base 16) ASIX ELECTRONICS CORP. + 4F, NO.8, HSIN ANN RD., + HSINCHU 300 + TW + +00-0E-BF (hex) Remsdaq Limited +000EBF (base 16) Remsdaq Limited + Parkway + Deeside Flintshire CH5 2NL + GB + +00-0E-FF (hex) Megasolution,Inc. +000EFF (base 16) Megasolution,Inc. + 2-7-10 Shitaya + Taito TOKYO 110-0004 + JP + +00-0E-E0 (hex) Mcharge +000EE0 (base 16) Mcharge + Firstec Bldg,. 15-4 Youido-Dong + seoul Youido 150-010 + KR + +00-0E-9F (hex) TEMIC SDS GmbH +000E9F (base 16) TEMIC SDS GmbH + Soeflinger Strasse 100 + Ulm 89077 + DE + +00-0E-96 (hex) Cubic Defense Applications, Inc. +000E96 (base 16) Cubic Defense Applications, Inc. + P.O. Box 85587 + San Diego CA 92186-5587 + US + +00-0E-8E (hex) SparkLAN Communications, Inc. +000E8E (base 16) SparkLAN Communications, Inc. + 3Fl . , No. 246, Sec. 1, Neihu Road., Neihu Chiu, + Taipei 114 + TW + +00-0E-91 (hex) Navico Auckland Ltd +000E91 (base 16) Navico Auckland Ltd + 17-21 Kawana St + Northcote Auckland + NZ + +00-0E-48 (hex) Lipman TransAction Solutions +000E48 (base 16) Lipman TransAction Solutions + 11 Haamal St. + Rosh-Haayin 48092 + IL + +00-0E-3E (hex) Sun Optronics Inc +000E3E (base 16) Sun Optronics Inc + 4-38-4 Fuchinobe-honchou + Sagamihara Kanagawa 229-0002 + JP + +00-0E-33 (hex) Shuko Electronics Co.,Ltd +000E33 (base 16) Shuko Electronics Co.,Ltd + TOHSHIN HIGASHI-IKEBUKURO Building 3F + TOKYO KANTOH 170-0063 + JP + +00-0E-75 (hex) New York Air Brake Corp. +000E75 (base 16) New York Air Brake Corp. + 748 Starbuck Ave. + Watertown NY 13601 + US + +00-0E-7C (hex) Televes S.A. +000E7C (base 16) Televes S.A. + Rua Benefica Conxo 17 + Santiago de Compostela Coruña 15706 + ES + +00-0E-66 (hex) Hitachi Industry & Control Solutions, Ltd. +000E66 (base 16) Hitachi Industry & Control Solutions, Ltd. + 5-1-26, Omika-cho, Hitachi-shi, Ibaraki + 319-1221 + JP + +00-0E-68 (hex) E-TOP Network Technology Inc. +000E68 (base 16) E-TOP Network Technology Inc. + No. 7, Shin Shin Rd., + Tainan 702 + TW + +00-0E-5E (hex) Raisecom Technology +000E5E (base 16) Raisecom Technology + 2 Floor, South Building of Rainbow Plaza + Haidian District Beijing 100085 + CN + +00-0E-56 (hex) 4G Systems GmbH & Co. KG +000E56 (base 16) 4G Systems GmbH & Co. KG + Jarrestrasse 2-6 + 22303 Hamburg + DE + +00-0E-55 (hex) AUVITRAN +000E55 (base 16) AUVITRAN + 7c chemin des Prés + MEYLAN 38410 + FR + +00-0E-73 (hex) Tpack A/S +000E73 (base 16) Tpack A/S + Lautrupbjerg 7 - 11 + DK 2750 Ballerup DK 2750 + DK + +00-0E-72 (hex) CTS electronics +000E72 (base 16) CTS electronics + Corso Vercelli 332 + Ivrea Torino 10015 + IT + +00-0E-6E (hex) MAT S.A. (Mircrelec Advanced Technology) +000E6E (base 16) MAT S.A. (Mircrelec Advanced Technology) + Mousounitsis 15 + Peristeri Athens + GR + +00-0E-84 (hex) Cisco Systems, Inc +000E84 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0E-87 (hex) adp Gauselmann GmbH +000E87 (base 16) adp Gauselmann GmbH + Boschstraße 8 + Luebbecke NRW 32312 + DE + +00-0E-92 (hex) Open Telecom +000E92 (base 16) Open Telecom + 803-804 Daeryung Techno-town II + Keuncheon-Ku Seoul 153-771 + KR + +00-0E-53 (hex) AV TECH CORPORATION +000E53 (base 16) AV TECH CORPORATION + 10F,E Building,No.19-11 San Chung Rd.,NanKang + Taipei 115 + TW + +00-0D-F9 (hex) NDS Limited +000DF9 (base 16) NDS Limited + One Heathrow Boulevard + West Drayton Middlesex UB7 0DQ + GB + +00-0D-FD (hex) Huges Hi-Tech Inc., +000DFD (base 16) Huges Hi-Tech Inc., + 7F, 188, Sec. 2, Chung Hsing Road. + Hsin Tien Taipei Hsien 231 + TW + +00-0D-FB (hex) Komax AG +000DFB (base 16) Komax AG + Industriestrasse 6 + Dierikon LU 6036 + CH + +00-0E-00 (hex) Atrie +000E00 (base 16) Atrie + 10th Floor, 14, Lane 609, Sec. 5, Chung Hsin Rd., San Chung City, + Taipei Hsien San Chung 241 + TW + +00-0D-F4 (hex) Watertek Co. +000DF4 (base 16) Watertek Co. + Room 1006,Haitai building,north si Huan + Beijing 100083 + CN + +00-0D-FA (hex) Micro Control Systems Ltd. +000DFA (base 16) Micro Control Systems Ltd. + 8-7 Sakurai + Saku-shi Nagano 385-0056 + JP + +00-0D-FC (hex) ITFOR Inc. +000DFC (base 16) ITFOR Inc. + Ichibancho Tokyu Bidg., + Tokyo 102-0082 + JP + +00-0D-FE (hex) Hauppauge Computer Works, Inc. +000DFE (base 16) Hauppauge Computer Works, Inc. + 91 Cabot Court + Hauppauge New York 11788 + US + +00-0D-D6 (hex) ITI LTD +000DD6 (base 16) ITI LTD + R&D,ITI Bangalore Complex + Dooravani Nagar, Bangalore Karnataka State 560016 + IN + +00-0D-D5 (hex) O'RITE TECHNOLOGY CO.,LTD +000DD5 (base 16) O'RITE TECHNOLOGY CO.,LTD + 4f-8,NO 80,GUANGFU RD.SEC 2,SANCHUNG + TAIPEI COUNTY 241 + TW + +00-0E-0F (hex) ERMME +000E0F (base 16) ERMME + 9 rue Lavoisier + Vert-Le-Petit 91710 + FR + +00-0E-10 (hex) C-guys, Inc. +000E10 (base 16) C-guys, Inc. + Izumi Garden Wing 1F, 1-6-3 + Tokyo 106-0032 + JP + +00-0E-0A (hex) SAKUMA DESIGN OFFICE +000E0A (base 16) SAKUMA DESIGN OFFICE + 674-11 + KUKI-SHI SAITAMA 346-0029 + JP + +00-0E-0E (hex) ESA elettronica S.P.A. +000E0E (base 16) ESA elettronica S.P.A. + + Mariano Comense CO 22066 + IT + +00-0E-18 (hex) MyA Technology +000E18 (base 16) MyA Technology + 2100 Muirwood Way + San Jose CA 95132 + US + +00-0E-14 (hex) Visionary Solutions, Inc. +000E14 (base 16) Visionary Solutions, Inc. + 4193 Carpinteria Ave + Carpinteria CA 93013 + US + +00-0E-1B (hex) IAV GmbH +000E1B (base 16) IAV GmbH + Carnotstraße 1 + Berlin 10587 + DE + +00-0E-13 (hex) Accu-Sort Systems inc. +000E13 (base 16) Accu-Sort Systems inc. + 511 School House Road + Telford PA 18969 + US + +00-0D-DE (hex) Joyteck Co., Ltd. +000DDE (base 16) Joyteck Co., Ltd. + 19F, No.4, Sec. 3, Min Chuan East Rd. + Taipei 105 + TW + +00-0D-E2 (hex) CMZ Sistemi Elettronici +000DE2 (base 16) CMZ Sistemi Elettronici + Via dell'Artiginato, 21 + Vascon di Carbonera Treviso 31050 + IT + +00-0D-DA (hex) ALLIED TELESIS K.K. +000DDA (base 16) ALLIED TELESIS K.K. + PIAZZA TIRANA N. 24/4 B + MILANO 20147 + IT + +00-0D-CD (hex) GROUPE TXCOM +000DCD (base 16) GROUPE TXCOM + ZI DU PETIT CLAMART + LE PLESSIS ROBINSON HAUTS-DE-SEINE 92350 + FR + +00-0D-CA (hex) Tait Electronics +000DCA (base 16) Tait Electronics + 535 Wairakei Rd + Christchurch Canterbury 8005 + NZ + +00-0D-CF (hex) Cidra Corp. +000DCF (base 16) Cidra Corp. + 50 Barns Park North + Wallingford CT 06492 + US + +00-0E-3A (hex) Cirrus Logic +000E3A (base 16) Cirrus Logic + 2901 Via Fortuna + Austin TX 78746 + US + +00-0E-3B (hex) Hawking Technologies, Inc. +000E3B (base 16) Hawking Technologies, Inc. + 15281A Barranca Parkway + Irvine CA 92618 + US + +00-0D-EC (hex) Cisco Systems, Inc +000DEC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0D-F2 (hex) Private +000DF2 (base 16) Private + +00-0E-27 (hex) Crere Networks, Inc. +000E27 (base 16) Crere Networks, Inc. + Room 110 ETRI TBI, 52 Eoeun-dong + Daejeon 305-333 + KR + +00-0D-A0 (hex) NEDAP N.V. +000DA0 (base 16) NEDAP N.V. + P.O.Box 103 + GROENLO GLD 7141 AC + NL + +00-0D-8E (hex) Koden Electronics Co., Ltd. +000D8E (base 16) Koden Electronics Co., Ltd. + 5278 Uenohara + Yamanashi-Ken 409-0112 + JP + +00-0D-8A (hex) Winners Electronics Co., Ltd. +000D8A (base 16) Winners Electronics Co., Ltd. + #340-5,Wonchun-Dong,Paldal-Gu + Suwon-City Kyungki-Do 442-823 + KR + +00-0D-7E (hex) Axiowave Networks, Inc. +000D7E (base 16) Axiowave Networks, Inc. + 200 Nickerson Road + Marlborough MA 01752 + US + +00-0D-71 (hex) boca systems +000D71 (base 16) boca systems + 1065 s. rogers circle + boca raton fl 33487 + US + +00-0D-5A (hex) Tiesse SpA +000D5A (base 16) Tiesse SpA + Via Asti + Ivrea TO 10015 + IT + +00-0D-B8 (hex) SCHILLER AG +000DB8 (base 16) SCHILLER AG + Altgasse 68 + Baar Zug 6300 + CH + +00-0D-C4 (hex) Emcore Corporation +000DC4 (base 16) Emcore Corporation + 1600 Eubank Blvd, SE + Albuquerque New Mexico 87123 + US + +00-0D-9B (hex) Heraeus Electro-Nite International N.V. +000D9B (base 16) Heraeus Electro-Nite International N.V. + Centrum Zuid 1105 + Houthalen 3530 + BE + +00-0D-7C (hex) Codian Ltd +000D7C (base 16) Codian Ltd + 14 Waterside Drive + Langley Slough SL3 6EZ + GB + +00-0D-6B (hex) Mita-Teknik A/S +000D6B (base 16) Mita-Teknik A/S + Haandvaerkervej 1 + Roedkaersbro DK-8840 + DK + +00-0D-43 (hex) DRS Tactical Systems Inc. +000D43 (base 16) DRS Tactical Systems Inc. + 3520 U.S. Highway 1 + Palm Bay FL 32905 + US + +00-0D-44 (hex) Audio BU - Logitech +000D44 (base 16) Audio BU - Logitech + 1499 SE Tech Center Place + Vancouver WA 98683 + US + +00-0D-36 (hex) Wu Han Routon Electronic Co., Ltd +000D36 (base 16) Wu Han Routon Electronic Co., Ltd + Miao Shan District, East Lake Hi-Tech + Wuhan Hubei 430223 + CN + +00-0D-3D (hex) Hammerhead Systems, Inc. +000D3D (base 16) Hammerhead Systems, Inc. + 640 Clyde Court + Mountain View California 94043 + US + +00-0D-3E (hex) APLUX Communications Ltd. +000D3E (base 16) APLUX Communications Ltd. + 10F, No. 166, Dah-Yeh Rd., Peitou + Taipei 112 + TW + +00-0D-0D (hex) ITSupported, LLC +000D0D (base 16) ITSupported, LLC + 4989 Peachtree Parkway + Norcross GA 30092 + US + +00-0D-06 (hex) Compulogic Limited +000D06 (base 16) Compulogic Limited + Unit W3, MK TWO Business Centre + Water Eaton Milton Keynes MK2 3HU + GB + +00-0D-4A (hex) Steag ETA-Optik +000D4A (base 16) Steag ETA-Optik + Borsigstrasse 78.-80 + Heinsberg 52525 + DE + +00-0D-4F (hex) Kenwood Corporation +000D4F (base 16) Kenwood Corporation + 2967-3, Ishikawa-machi + Hachioji-shi Tokyo 192-8525 + JP + +00-0D-47 (hex) Collex +000D47 (base 16) Collex + 13F-3,No.142,Sec.1,Huamei W,St.,Shi Chiu + Taichung 403 + TW + +00-0D-61 (hex) Giga-Byte Technology Co., Ltd. +000D61 (base 16) Giga-Byte Technology Co., Ltd. + No 6, Bau Chiang Road, Hsin-Tien + Taipei Hsien 9999 + TW + +00-0D-3B (hex) Microelectronics Technology Inc. +000D3B (base 16) Microelectronics Technology Inc. + No1, Innovation Road II + 300 + TW + +00-0D-2D (hex) NCT Deutschland GmbH +000D2D (base 16) NCT Deutschland GmbH + Wildenbruchstraße 15 + Jena Thüringen 07745 + DE + +00-0D-1E (hex) Control Techniques +000D1E (base 16) Control Techniques + The Gro + Newtown Powys SY16 3BE + GB + +00-0D-52 (hex) Comart system +000D52 (base 16) Comart system + No. 211, Ace Techno Tower III, 197-48 + Seoul 152-050 + KR + +00-0D-1A (hex) Mustek System Inc. +000D1A (base 16) Mustek System Inc. + No. 25, R&D Road, Science-Based Industri + Hsin-Chu 300 + TW + +00-0C-B8 (hex) MEDION AG +000CB8 (base 16) MEDION AG + Am Zehnthof 77 + Essen NRW 45307 + DE + +00-0C-BB (hex) ISKRAEMECO +000CBB (base 16) ISKRAEMECO + Savska loka 4 + Kranj Gorenjska 4000 + SI + +00-0C-C0 (hex) Genera Oy +000CC0 (base 16) Genera Oy + Niittylanpolku 16 + Helsinki 00621 + FI + +00-0C-A8 (hex) Garuda Networks Corporation +000CA8 (base 16) Garuda Networks Corporation + 48499 Milmont Drive + Fremont CA 94538 + US + +00-0D-03 (hex) Matrics, Inc. +000D03 (base 16) Matrics, Inc. + 8850 Stanford Blvd + Columbia MD 21045 + US + +00-0C-FF (hex) MRO-TEK Realty Limited +000CFF (base 16) MRO-TEK Realty Limited + #6, New BEL Road + Chikkamaranahalli Bangalore 560 054 + IN + +00-0C-FA (hex) Digital Systems Corp +000CFA (base 16) Digital Systems Corp + 3 North Main Street + Walkersville Maryland 21793 + US + +00-0C-FD (hex) Hyundai ImageQuest Co.,Ltd. +000CFD (base 16) Hyundai ImageQuest Co.,Ltd. + San 136-1, Ami-ri, Bubal-eub + Ichon-si Kyoung ki-do 467-701 + KR + +00-0C-D3 (hex) Prettl Elektronik Radeberg GmbH +000CD3 (base 16) Prettl Elektronik Radeberg GmbH + Robert-Bosch-Str. 10 + Radeberg Saxony D-01454 + DE + +00-0C-D7 (hex) Nallatech Ltd +000CD7 (base 16) Nallatech Ltd + Boolean House + Glasgow Scotland G68 0BH + GB + +00-0C-D4 (hex) Positron Public Safety Systems inc. +000CD4 (base 16) Positron Public Safety Systems inc. + 5101 Buchan + Montreal Quebec H4P 2R9 + CA + +00-0C-D6 (hex) PARTNER TECH +000CD6 (base 16) PARTNER TECH + 10F, NO.233-2,PAO CHIAO ROAD, SHIN TIEN + TAIPEI 231 + TW + +00-0C-B9 (hex) LEA +000CB9 (base 16) LEA + Bat LA FAYETTE + Paris RP 924051 + FR + +00-0C-BD (hex) Interface Masters, Inc +000CBD (base 16) Interface Masters, Inc + 2381 Zanker Rd., Suite 130 + San Jose California 95131 + US + +00-0C-B2 (hex) UNION co., ltd. +000CB2 (base 16) UNION co., ltd. + 14Beon-Gil 17, UiChang-Gu, + GyeongSnagNam-Do 641-846 + KR + +00-0C-EB (hex) CNMP Networks, Inc. +000CEB (base 16) CNMP Networks, Inc. + 1245 S. Winchester Blvd. + San Jose CA 95128 + US + +00-0C-CC (hex) Aeroscout Ltd. +000CCC (base 16) Aeroscout Ltd. + 3 Pekeris St. + Rehovot 76701 + IL + +00-0C-C7 (hex) Intelligent Computer Solutions Inc. +000CC7 (base 16) Intelligent Computer Solutions Inc. + 9350 Eton St. + Chatsworth CA 91301 + US + +00-0C-BE (hex) Innominate Security Technologies AG +000CBE (base 16) Innominate Security Technologies AG + Rudower Chaussee 13 + 12489 Berlin + DE + +00-0C-A7 (hex) Metro (Suzhou) Technologies Co., Ltd. +000CA7 (base 16) Metro (Suzhou) Technologies Co., Ltd. + No.221 Xinghai Street, Suzhou Industrial Park + Suzhou Jiang Su Province 215021 + CN + +00-0C-EF (hex) Open Networks Engineering Ltd +000CEF (base 16) Open Networks Engineering Ltd + Classic House + Bishop's Stortford Hertfordshire CM23 5PD + GB + +00-0C-64 (hex) X2 MSA Group +000C64 (base 16) X2 MSA Group + Care of: Agilent Technologies + Ipswich, Suffolk IP1 5PB + GB + +00-0C-A0 (hex) StorCase Technology, Inc. +000CA0 (base 16) StorCase Technology, Inc. + 17600 Newhope St. + Fountain Valley CA 92708 + US + +00-0C-99 (hex) HITEL LINK Co.,Ltd +000C99 (base 16) HITEL LINK Co.,Ltd + Samsung Omni Tower 4th Fl., 395-62 + Seoul 156-010 + KR + +00-0C-5A (hex) IBSmm Embedded Electronics Consulting +000C5A (base 16) IBSmm Embedded Electronics Consulting + Teufelsgrabenweg 1 + Valley Bavaria D-83626 + DE + +00-0C-5E (hex) Calypso Medical +000C5E (base 16) Calypso Medical + 2101 Fourth Avenue, Suite 1550 + Seattle WA 98121 + US + +00-0C-61 (hex) AC Tech corporation DBA Advanced Digital +000C61 (base 16) AC Tech corporation DBA Advanced Digital + 1250-G Avenida Acaso + Camarillo CA 93010 + US + +00-0C-5F (hex) Avtec, Inc. +000C5F (base 16) Avtec, Inc. + 4335 Augusta Hwy + Gilbert SC 29054 + US + +00-0C-4B (hex) Cheops Elektronik +000C4B (base 16) Cheops Elektronik + Jeschkenstrasse 32 + Geretsried Bayern 82538 + DE + +00-0C-45 (hex) Animation Technologies Inc. +000C45 (base 16) Animation Technologies Inc. + 8F,No.138,Lane 235,Paochiao Road, + Taipei Hsien 231 + TW + +00-0C-3C (hex) MediaChorus, Inc. +000C3C (base 16) MediaChorus, Inc. + #205, ETRI TBI 2 Center + Daejon DJ 305-333 + KR + +00-0C-7C (hex) Internet Information Image Inc. +000C7C (base 16) Internet Information Image Inc. + Fl. 6, No. 1, Alley 20, Lane 26, Rueigua + Taipei 114 + TW + +00-0C-7B (hex) ALPHA PROJECT Co.,Ltd. +000C7B (base 16) ALPHA PROJECT Co.,Ltd. + 834 Sekishi,Higashi-ku,Hamamatsu-city + Shizuoka 431-3114 + JP + +00-0C-77 (hex) Life Racing Ltd +000C77 (base 16) Life Racing Ltd + Unit 6 Repton Close + Basildon Essex SS13 1LE + GB + +00-0C-69 (hex) National Radio Astronomy Observatory +000C69 (base 16) National Radio Astronomy Observatory + P.O. Box O + Socorro NM 87801 + US + +00-0C-66 (hex) Pronto Networks Inc +000C66 (base 16) Pronto Networks Inc + 4637 Chabot Dr + Pleasanton CA 94588 + US + +00-0C-88 (hex) Apache Micro Peripherals, Inc. +000C88 (base 16) Apache Micro Peripherals, Inc. + 17526 Von Karman Ave + Irvine CA 92614 + US + +00-0C-82 (hex) NETWORK TECHNOLOGIES INC +000C82 (base 16) NETWORK TECHNOLOGIES INC + 1275 DANNER DRIVE + AURORA OH 44202 + US + +00-0C-8D (hex) MATRIX VISION GmbH +000C8D (base 16) MATRIX VISION GmbH + Talstrasse 16 + Oppenweiler Baden-Württemberg D-71570 + DE + +00-0C-89 (hex) AC Electric Vehicles, Ltd. +000C89 (base 16) AC Electric Vehicles, Ltd. + Markkinakuja 3 + Jokela 05400 + FI + +00-0C-4E (hex) Winbest Technology CO,LT +000C4E (base 16) Winbest Technology CO,LT + 7F-5No.736 Chung ChengRd.,ChungHo + Taipei 235 + TW + +00-0B-FE (hex) CASTEL Broadband Limited +000BFE (base 16) CASTEL Broadband Limited + 9/F., Sui Ying Industrial Building., + Tokwawan Kowloon 150 + HK + +00-0B-F5 (hex) Shanghai Sibo Telecom Technology Co.,Ltd +000BF5 (base 16) Shanghai Sibo Telecom Technology Co.,Ltd + Floor 6 Building 18,300 Tianlin Rd. + Shanghai 200233 + CN + +00-0C-27 (hex) Sammy Corporation +000C27 (base 16) Sammy Corporation + SUN SHINE60 45F,3-1-1,HIGASHI-IKEBUKURO + TOSHIMA-KU TOKYO 170-6045 + JP + +00-0C-2A (hex) OCTTEL Communication Co., Ltd. +000C2A (base 16) OCTTEL Communication Co., Ltd. + 7F-1, No.300, Daduen 10th St. + Taichung City 408 + TW + +00-0C-1C (hex) MicroWeb Co., Ltd. +000C1C (base 16) MicroWeb Co., Ltd. + 403 T/S/S/C, 23-14 Jang-dong, Yusong-gu, + Daejeon ChoongChungDo 305-343 + KR + +00-0B-DF (hex) Shenzhen RouterD Networks Limited +000BDF (base 16) Shenzhen RouterD Networks Limited + 8/F, Building A, Tsinghua Hi-Tech Park + Shenzhen + CN + +00-0B-E6 (hex) Datel Electronics +000BE6 (base 16) Datel Electronics + Stafford Road + Stone Staffordshire ST15 0DG + GB + +00-0B-F2 (hex) Chih-Kan Technology Co., Ltd. +000BF2 (base 16) Chih-Kan Technology Co., Ltd. + No. 24-1, Pei Shih Chou, Ming Ho Vill. + Shan Sun Hsiang Tainan Hsien 180 + TW + +00-0B-EB (hex) Systegra AG +000BEB (base 16) Systegra AG + Burgunderstrasse 15 + Bellach SO 4512 + CH + +00-0B-EF (hex) Code Corporation +000BEF (base 16) Code Corporation + 11814 S. Election Rd., Ste 200 + Draper Utah 84020 + US + +00-0C-05 (hex) RPA Reserch Co., Ltd. +000C05 (base 16) RPA Reserch Co., Ltd. + 4F, 90-7, Yangjae-Dong, Seocho-Ku + Seoul 137-130 + US + +00-0C-22 (hex) Double D Electronics Ltd +000C22 (base 16) Double D Electronics Ltd + Unit 6, Robins Wharf + Northfleet Kent DA11 9AX + GB + +00-0C-0F (hex) Techno-One Co., Ltd +000C0F (base 16) Techno-One Co., Ltd + 9-17-1 Higashi Sonoda + Amagasaki Hyogo 661-0953 + JP + +00-0C-38 (hex) TelcoBridges Inc. +000C38 (base 16) TelcoBridges Inc. + 586 Du Chenal + Repentigny Quebec J6A 7C5 + CA + +00-0B-AF (hex) WOOJU COMMUNICATIONS Co,.Ltd +000BAF (base 16) WOOJU COMMUNICATIONS Co,.Ltd + B-713, SK Twin Tech Tower, 345-9, Ga-San + Seoul 153-802 + KR + +00-0B-B6 (hex) Metalligence Technology Corp. +000BB6 (base 16) Metalligence Technology Corp. + 9, Park Avenue II, Science-Based Industr + Hsinchu 300 + TW + +00-0B-B3 (hex) RiT technologies Ltd. +000BB3 (base 16) RiT technologies Ltd. + 24 Raoul Walenberg St. + Tel Aviv 69719 + IL + +00-0B-B7 (hex) Micro Systems Co.,Ltd. +000BB7 (base 16) Micro Systems Co.,Ltd. + 2-15-34 Nishikubo + Musashino-City Tokyo 180-0013 + JP + +00-0B-BA (hex) Harmonic, Inc +000BBA (base 16) Harmonic, Inc + 4300 North First Street + San Jose CA 95134 + US + +00-0B-62 (hex) ib-mohnen KG +000B62 (base 16) ib-mohnen KG + Stich 30 e + 52249 Eschweiler + DE + +00-0B-64 (hex) Kieback & Peter GmbH & Co KG +000B64 (base 16) Kieback & Peter GmbH & Co KG + Tempelhofer Weg 50 + Berlin 12347 + DE + +00-0B-67 (hex) Topview Technology Corporation +000B67 (base 16) Topview Technology Corporation + No. 8,Wu-Chuan Road,Wu Ku Industrial Par + Wu Ku Hsiang,Taipei Hsien, 248 + TW + +00-0B-7D (hex) SOLOMON EXTREME INTERNATIONAL LTD. +000B7D (base 16) SOLOMON EXTREME INTERNATIONAL LTD. + 3F, No.20, Lane 165, Duenhua N. Rd., Sun + Taipei + TW + +00-0B-94 (hex) Digital Monitoring Products, Inc. +000B94 (base 16) Digital Monitoring Products, Inc. + 2500 N. Partnership Boulevard + Springfield Missouri 65803 + US + +00-0B-AE (hex) Vitals System Inc. +000BAE (base 16) Vitals System Inc. + Jooheung B/D 4FL. 1005-1, Youngtong-Dong + Suwon City Kyonggi-Do 442-813 + KR + +00-0B-D9 (hex) General Hydrogen +000BD9 (base 16) General Hydrogen + 13120 Vanier Place + Richmond British Columbia V6V 2J2 + CA + +00-0B-AB (hex) Advantech Technology (CHINA) Co., Ltd. +000BAB (base 16) Advantech Technology (CHINA) Co., Ltd. + No.666, Han-Pu Rd. Yu-Shan + Kun-Shan Jiang Su 215316 + CN + +00-0B-6D (hex) SOLECTRON JAPAN NAKANIIDA +000B6D (base 16) SOLECTRON JAPAN NAKANIIDA + 325 GANBARA + KAMIGUN MIYAGIKEN 981-4263 + JP + +00-0B-C4 (hex) BIOTRONIK GmbH & Co +000BC4 (base 16) BIOTRONIK GmbH & Co + Woermannkehre 1 + Berlin 12359 + DE + +00-0B-57 (hex) Silicon Laboratories +000B57 (base 16) Silicon Laboratories + 7000 W. William Cannon Dr. + Austin TX 78735 + US + +00-0B-51 (hex) Micetek International Inc. +000B51 (base 16) Micetek International Inc. + 7F-1, #237, Sec. 1, wu Chuan W. Rd. + Taichung 403 + TW + +00-0B-53 (hex) INITIUM Co., Ltd. +000B53 (base 16) INITIUM Co., Ltd. + 8F. Gongduck Bldg. 272-6 Seohyun Bundang + Sungnam Kyunggi 463-824 + KR + +00-0A-FB (hex) Ambri Limited +000AFB (base 16) Ambri Limited + 126 Greville Street + Chatswood NSW 2067 + AU + +00-0A-FF (hex) Kilchherr Elektronik AG +000AFF (base 16) Kilchherr Elektronik AG + Aeschistrasse 25 + Muensingen BE 3110 + CH + +00-0B-4A (hex) Visimetrics (UK) Ltd +000B4A (base 16) Visimetrics (UK) Ltd + Skye House + Prestwick Ayrshire KA9 2TA + GB + +00-0B-48 (hex) sofrel +000B48 (base 16) sofrel + 2 rue du plessis + vern sur seiche ille et vilaine 35770 + FR + +00-0B-1E (hex) KAPPA opto-electronics GmbH +000B1E (base 16) KAPPA opto-electronics GmbH + Kleines Feld 6 + Gleichen Niedersachsen + DE + +00-0B-1C (hex) SIBCO bv +000B1C (base 16) SIBCO bv + Schoonhout 46 + Etten-Leur NB 4872 ME + NL + +00-0B-37 (hex) MANUFACTURE DES MONTRES ROLEX SA +000B37 (base 16) MANUFACTURE DES MONTRES ROLEX SA + LA HAUTE-ROUTE 82 + BIEL-BIENNE BE 2502 + CH + +00-0A-F8 (hex) American Telecare Inc. +000AF8 (base 16) American Telecare Inc. + 7640 Golden Triangle Drive + Eden Prairie MN 55344 + US + +00-0B-17 (hex) MKS Instruments +000B17 (base 16) MKS Instruments + 651 Lowell Street + Methuen MA 01844 + US + +00-0B-2D (hex) Danfoss Inc. +000B2D (base 16) Danfoss Inc. + 7941 Corporate Dr + Baltimore MD 21236 + US + +00-0A-A3 (hex) SHIMAFUJI ELECTRIC CO.,LTD. +000AA3 (base 16) SHIMAFUJI ELECTRIC CO.,LTD. + Daihyaku-seimei Kamata Bldg.3F + Tokyo 144-0051 + JP + +00-0A-A7 (hex) FEI Electron Optics +000AA7 (base 16) FEI Electron Optics + Achtseweg Noord 5 + Eindhoven 5651GG + NL + +00-0A-A6 (hex) Hochiki Corporation +000AA6 (base 16) Hochiki Corporation + 246, TSURUMA + MACHIDA TOKYO 194-8577 + JP + +00-0A-9A (hex) Aiptek International Inc +000A9A (base 16) Aiptek International Inc + No 5-1 Innovation Rd 1 + Hsin-Chu 300 + TW + +00-0A-94 (hex) ShangHai cellink CO., LTD +000A94 (base 16) ShangHai cellink CO., LTD + C3 MeiLong ZhongXin Industrial Park,No.1 + ShangHai 200237 + US + +00-0A-97 (hex) SONICblue, Inc. +000A97 (base 16) SONICblue, Inc. + 2841 Mission College Blvd. + Santa Clara CA 95054 + US + +00-0A-92 (hex) Presonus Corporation +000A92 (base 16) Presonus Corporation + 7257 Florida Blvd. + Baton Rouge Louisiana 70806 + US + +00-0A-85 (hex) PLAT'C2,Inc +000A85 (base 16) PLAT'C2,Inc + 2-3-6 SOTOKANDA + CHIYODA-KU TOKYO 101-0021 + JP + +00-0A-D0 (hex) Niigata Develoment Center, F.I.T. Co., Ltd. +000AD0 (base 16) Niigata Develoment Center, F.I.T. Co., Ltd. + Akane-Niigata Building 2F + Niigata Niigata Prefecture 950-0944 + JP + +00-0A-D4 (hex) CoreBell Systems Inc. +000AD4 (base 16) CoreBell Systems Inc. + HTVC 2317 KAIST + Yuseong-Gu Daejeon 305-701 + KR + +00-0A-CA (hex) YOKOYAMA SHOKAI CO.,Ltd. +000ACA (base 16) YOKOYAMA SHOKAI CO.,Ltd. + 6-96 Matsumura + Kanazawa Ishikawa 920-0348 + JP + +00-0A-CE (hex) RADIANTECH, INC. +000ACE (base 16) RADIANTECH, INC. + 2-1, INDUSTRY EAST RD. 1, SCIENCE-BASED + HSIN CHU 300 + TW + +00-0A-C7 (hex) Unication Group +000AC7 (base 16) Unication Group + 3F., No. 6, Wu-Kung 5Rd., Hsinchuang Cit + Taipei 242 + TW + +00-0A-DE (hex) Happy Communication Co., Ltd. +000ADE (base 16) Happy Communication Co., Ltd. + 42-11 WonMi-Dong + Bucheon-City KyungGi-Do 420-110 + KR + +00-0A-E2 (hex) Binatone Electronics International, Ltd +000AE2 (base 16) Binatone Electronics International, Ltd + Floor 23A, 9 Des Voeux Road West + Hong Kong China + HK + +00-0A-DB (hex) Trilliant +000ADB (base 16) Trilliant + 401 Harrison Oaks Blvd. Suite 300 + Cary NC 27513 + US + +00-0A-B8 (hex) Cisco Systems, Inc +000AB8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0A-AC (hex) TerraTec Electronic GmbH +000AAC (base 16) TerraTec Electronic GmbH + Herrenpfad 38 + Nettetal 41334 + DE + +00-0A-BF (hex) HIROTA SS +000ABF (base 16) HIROTA SS + Matukawa-Kougyoudanchi + Suzaka-shi Nagano 382-0005 + JP + +00-0A-BC (hex) Seabridge Ltd. +000ABC (base 16) Seabridge Ltd. + 3 Hanagar St. + Hod-Hasharon Israel 45241 + IL + +00-0A-50 (hex) REMOTEK CORPORATION +000A50 (base 16) REMOTEK CORPORATION + 6F-6, No 77, Sec 1, HSIN TAI WU ROAD, + HSI-CHIH TAIPEI HSIEN 221 + TW + +00-0A-58 (hex) Freyer & Siegel Elektronik GmbH & Co. KG +000A58 (base 16) Freyer & Siegel Elektronik GmbH & Co. KG + Neuendorfstraße 18 b + Hennigsdorf Brandenburg 16761 + DE + +00-0A-4E (hex) UNITEK Electronics INC. +000A4E (base 16) UNITEK Electronics INC. + 1-18-4 + Ohta-ku Tokyo 143-0016 + US + +00-0A-62 (hex) Crinis Networks, Inc. +000A62 (base 16) Crinis Networks, Inc. + 2099 N. Collins Blvd, Suite 200 + Richardson TX 75080 + US + +00-0A-6A (hex) SVM Microwaves s.r.o. +000A6A (base 16) SVM Microwaves s.r.o. + U Mrazovky 5 + Praha 5 15000 + CZ + +00-0A-66 (hex) MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD. +000A66 (base 16) MITSUBISHI ELECTRIC SYSTEM & SERVICE CO.,LTD. + 1-4-13 OOYODONAKA,KITA-KU + OSAKA 531-0076 + JP + +00-0A-31 (hex) HCV Consulting +000A31 (base 16) HCV Consulting + P O Box 3692 + Queensland 4212 + AU + +00-42-52 (hex) RLX Technologies +004252 (base 16) RLX Technologies + 25231 Grograns Mill Rd + The Woodlands Tx 77380 + US + +00-0A-70 (hex) MPLS Forum +000A70 (base 16) MPLS Forum + 39355 California Street + Fremont CA 94538 + US + +00-0A-72 (hex) STEC, INC. +000A72 (base 16) STEC, INC. + 3001 Daimler Street + Santa Ana CA 92705 + US + +00-0A-3D (hex) Elo Sistemas Eletronicos S.A. +000A3D (base 16) Elo Sistemas Eletronicos S.A. + Rua Edu Chaves, 547 + Porto Alegre RS 90.240-620 + BR + +00-0A-46 (hex) ARO WELDING TECHNOLOGIES SAS +000A46 (base 16) ARO WELDING TECHNOLOGIES SAS + 1, avenue de Tours + Chateau du Loir sarthe 72500 + FR + +00-0A-71 (hex) Avrio Technologies, Inc +000A71 (base 16) Avrio Technologies, Inc + 2655 A Park Center Drive + Simi Valley CA 91356 + US + +00-0A-64 (hex) Eracom Technologies +000A64 (base 16) Eracom Technologies + 28 Greg Chappell Drive + Burleigh Heads Qld 4220 + AU + +00-0A-83 (hex) SALTO SYSTEMS S.L. +000A83 (base 16) SALTO SYSTEMS S.L. + Arkotz, 9 + Polígonoo Lanbarren Oiartzun 20180 + ES + +00-0A-86 (hex) Lenze +000A86 (base 16) Lenze + PO box 101352 + Hameln Lower Saxony 31763 + DE + +00-0A-3F (hex) Data East Corporation +000A3F (base 16) Data East Corporation + 4-41-10 Minami-Ogikubo + Suginami-ku TOKYO 167-0052 + JP + +00-0A-0C (hex) Scientific Research Corporation +000A0C (base 16) Scientific Research Corporation + 2300 Windy Ridge Parkway + Atlanta GA 30339 + US + +00-09-F6 (hex) Shenzhen Eastern Digital Tech Ltd. +0009F6 (base 16) Shenzhen Eastern Digital Tech Ltd. + Shenzhen Futian Chegongmiao Tairan + Shenzhen Guangdong 518048 + CN + +00-0A-20 (hex) SVA Networks, Inc. +000A20 (base 16) SVA Networks, Inc. + 840 F Ave., Suite 104 + Plano TX 75074 + US + +00-0A-24 (hex) Octave Communications +000A24 (base 16) Octave Communications + 85 Northwest Boulevard + Nashua NH 03063 + US + +00-0A-19 (hex) Valere Power, Inc. +000A19 (base 16) Valere Power, Inc. + 661 N. Plano Rd. + Richardson Texas 75081 + US + +00-09-E5 (hex) Hottinger Baldwin Messtechnik GmbH +0009E5 (base 16) Hottinger Baldwin Messtechnik GmbH + Im Tiefen See 45 + Darmstadt Hessen 64293 + DE + +00-09-DE (hex) Samjin Information & Communications Co., Ltd. +0009DE (base 16) Samjin Information & Communications Co., Ltd. + MajangMyun DukPyungRi 235-2 + Ichon KyongGi 467-812 + KR + +00-09-E0 (hex) XEMICS S.A. +0009E0 (base 16) XEMICS S.A. + Rue de la Maladiere 71 + CH-2007 Neuchatel Neuchatel 2007 + CH + +00-0A-01 (hex) SOHOware, Inc. +000A01 (base 16) SOHOware, Inc. + 3050 Coronado Drive + Santa Clara CA 95054 + US + +00-09-EC (hex) Daktronics, Inc. +0009EC (base 16) Daktronics, Inc. + 315 32nd Ave + Brookings SD 57006 + US + +00-09-EE (hex) MEIKYO ELECTRIC CO.,LTD +0009EE (base 16) MEIKYO ELECTRIC CO.,LTD + 4-27-2 Higashiogu + Arakawa-ku Tokyo 116-0012 + JP + +00-09-CA (hex) iMaxNetworks(Shenzhen)Limited. +0009CA (base 16) iMaxNetworks(Shenzhen)Limited. + 4/B,South Bldg of 29th,South District of + Shenzhen GuangDong 518057 + CN + +00-09-CF (hex) iAd GmbH +0009CF (base 16) iAd GmbH + Unterschlauersbacher Hauptstraße 10 + Grosshabersdorf Bavaria 90613 + DE + +00-0A-11 (hex) ExPet Technologies, Inc +000A11 (base 16) ExPet Technologies, Inc + 6F, Kyonggi Small Business Center + Suwon, Kyonggi-do, 442-270 442-770 + KR + +00-0A-0F (hex) Ilryung Telesys, Inc +000A0F (base 16) Ilryung Telesys, Inc + Ilryung bldg, 34-2, Cheonho-dong + SEOUL 134-861 + KR + +00-09-E7 (hex) ADC Techonology +0009E7 (base 16) ADC Techonology + Sakae Members Office Bld. 4-16-8, Sakae, + Nagoya Aichi 4600008 + JP + +00-09-93 (hex) Visteon Corporation +000993 (base 16) Visteon Corporation + 16630 Southfield Road + Allen Park Michigan 48101 + US + +00-09-99 (hex) CP GEORGES RENAULT +000999 (base 16) CP GEORGES RENAULT + 38 Rue Bobby Sands + 44800 Saint Herblain + FR + +00-09-94 (hex) Cronyx Engineering +000994 (base 16) Cronyx Engineering + Marshala Sokolovskogo str. 4 + Moscow 123063 + RU + +00-09-B9 (hex) Action Imaging Solutions +0009B9 (base 16) Action Imaging Solutions + Kings Hall, St Ives Business Park + Huntingdon Cambridgeshire PE27 4WY + GB + +00-09-AC (hex) LANVOICE +0009AC (base 16) LANVOICE + 1364-39 SeochoDong, #201 Jihun Bldg + Seoul 137-072 + KR + +00-09-B1 (hex) Kanematsu Electronics, Ltd. +0009B1 (base 16) Kanematsu Electronics, Ltd. + 17-5, Kyobashi 2-chome + Chuo-ku Tokyo 104-8338 + JP + +00-09-B0 (hex) Onkyo Corporation +0009B0 (base 16) Onkyo Corporation + 2-1 Nisshin-cho + Neyagawa Osaka 5728540 + JP + +00-09-79 (hex) Advanced Television Systems Committee, Inc. +000979 (base 16) Advanced Television Systems Committee, Inc. + 1750 K Street NW + Washington DC 20006 + US + +00-09-63 (hex) Dominion Lasercom Inc. +000963 (base 16) Dominion Lasercom Inc. + 1716 Briarcrest Dr. Ste. 210 + Bryan TX 77802 + US + +00-09-66 (hex) TRIMBLE EUROPE BV +000966 (base 16) TRIMBLE EUROPE BV + Meerheide 45 + Eersel DZ 5521 + NL + +00-09-C1 (hex) PROCES-DATA A/S +0009C1 (base 16) PROCES-DATA A/S + Navervej 8 + Silkeborg DK-8600 + DK + +00-09-BB (hex) MathStar, Inc. +0009BB (base 16) MathStar, Inc. + 5900 Green Oak Drive + Minneapolis MN 55343 + US + +00-09-68 (hex) TECHNOVENTURE, INC. +000968 (base 16) TECHNOVENTURE, INC. + P. O. Box 5641 + Pasadena Texas 77508-5641 + US + +00-09-61 (hex) Switchgear and Instrumentation Ltd +000961 (base 16) Switchgear and Instrumentation Ltd + Ripley Road + Bradford West Yorkshire BD4 7EH + GB + +00-09-7C (hex) Cisco Systems, Inc +00097C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-7B (hex) Cisco Systems, Inc +00097B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-9D (hex) Haliplex Communications +00099D (base 16) Haliplex Communications + PO Box 147 + Mooroolbark Vic 3138 + AU + +00-09-9E (hex) Testech, Inc. +00099E (base 16) Testech, Inc. + Bundang-Technopark, C-Dong, 702-Ho, #145 + Sungnam-City Kyungki-Do 463-070 + KR + +00-09-88 (hex) Nudian Electron Co., Ltd. +000988 (base 16) Nudian Electron Co., Ltd. + 797-28 Bangbae-Dong, Seocho-Gu + Seoul 137-060 + KR + +00-09-8E (hex) ipcas GmbH +00098E (base 16) ipcas GmbH + Wetterkreuz 17 + Erlangen Bavaria 91058 + DE + +00-09-AB (hex) Netcontrol Oy +0009AB (base 16) Netcontrol Oy + Karvaamokuja 3 + Helsinki FIN 00380 + FI + +00-09-60 (hex) YOZAN Inc. +000960 (base 16) YOZAN Inc. + YOZAN Bld.,3-5-18, Kitazawa + Setagaya-ku Tokyo 155-0031 + JP + +00-09-56 (hex) Network Systems Group, Ltd. (NSG) +000956 (base 16) Network Systems Group, Ltd. (NSG) + 39 Kirpichnaya St., Suite 1302 + Moscow 105187 + RU + +00-09-00 (hex) TMT +000900 (base 16) TMT + 11 Kiryat Mada, POB 45199 + Jerusalem 91450 + IL + +00-09-01 (hex) Shenzhen Shixuntong Information & Technoligy Co +000901 (base 16) Shenzhen Shixuntong Information & Technoligy Co + Room 403,617 Bldg;Bagua 1 Road ,Shenzhen + Shenzhen Guangdong 518029 + CN + +00-09-13 (hex) SystemK Corporation +000913 (base 16) SystemK Corporation + 238-9 Higashi 1, Kita 15, Higashi-ku + Sapporo Hokkaido 065-0015 + JP + +00-09-0E (hex) Helix Technology Inc. +00090E (base 16) Helix Technology Inc. + 5F, No. 6, Sec 1, Jung-Shing Rd., Wugu-S + Taipei 248 + TW + +00-09-3C (hex) Jacques Technologies P/L +00093C (base 16) Jacques Technologies P/L + 268 Montague Rd + West End Queensland 4101 + AU + +00-09-35 (hex) Sandvine Incorporated +000935 (base 16) Sandvine Incorporated + 170 Columbia St. W. + Waterloo ON N2L 3L3 + CA + +00-09-36 (hex) Ipetronik GmbH & Co. KG +000936 (base 16) Ipetronik GmbH & Co. KG + Im Rollfeld 28 + Baden-Baden Baden-Württemberg 76532 + DE + +00-09-37 (hex) Inventec Appliance Corp +000937 (base 16) Inventec Appliance Corp + 113, Wugung 1 RD., WuKu Industrial nPark + Taipei + TW + +00-09-46 (hex) Cluster Labs GmbH +000946 (base 16) Cluster Labs GmbH + Dauerwaldweg 1 + Berlin Berlin 14055 + DE + +00-09-3F (hex) Double-Win Enterpirse CO., LTD +00093F (base 16) Double-Win Enterpirse CO., LTD + NO.300, Sec 1, Chung Feng Rd. + Ping Chen City Taoyuan Hsien 324 + TW + +00-09-48 (hex) Vista Control Systems, Corp. +000948 (base 16) Vista Control Systems, Corp. + 2001 West Melinda Lane + Phoenix AZ 85027 + US + +00-09-49 (hex) Glyph Technologies Inc. +000949 (base 16) Glyph Technologies Inc. + 735 W. Clinton Street + Ithaca NY 14850 + US + +00-09-2A (hex) MYTECS Co.,Ltd. +00092A (base 16) MYTECS Co.,Ltd. + 1-12-39, Taishidou + Setagaya-ku Tokyo 154-0004 + JP + +00-09-25 (hex) VSN Systemen BV +000925 (base 16) VSN Systemen BV + Keizersveld 83 + Venray Limburg 5803 AP + NL + +00-08-E0 (hex) ATO Technology Ltd. +0008E0 (base 16) ATO Technology Ltd. + Rm. 1314-1346, Block B1, Yau Tong Ind. C + Hong Kong + HK + +00-08-E4 (hex) Envenergy Inc +0008E4 (base 16) Envenergy Inc + 6307 Carpinteria Ave + Carpinteria CA 93013 + US + +00-08-E3 (hex) Cisco Systems, Inc +0008E3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-08-E5 (hex) IDK Corporation +0008E5 (base 16) IDK Corporation + 6-7-10 + Yamato Kanagawa 242-0007 + JP + +00-08-D9 (hex) Mitadenshi Co.,LTD +0008D9 (base 16) Mitadenshi Co.,LTD + 1-8-6 Furuichi Asaminamiku + Hiroshima 731-0123 + JP + +00-08-91 (hex) Lyan Inc. +000891 (base 16) Lyan Inc. + 5F-1, NO.51, SEC.2, KEELUNG RD. + TAIPEI 110 + TW + +00-08-92 (hex) EM Solutions +000892 (base 16) EM Solutions + 101 Hyde Rd + Yeronga Brisbane, QLD 4104 + AU + +00-08-8C (hex) Quanta Network Systems Inc. +00088C (base 16) Quanta Network Systems Inc. + 13, 13F, Sec. 2, Pei-Tou Rd + Taipei 112 + TW + +00-08-8A (hex) Minds@Work +00088A (base 16) Minds@Work + 15550 Rockfield Blvd. Suite C + Irvine CA 92618 + US + +00-08-FD (hex) BlueKorea Co., Ltd. +0008FD (base 16) BlueKorea Co., Ltd. + 3F, sejong Building, 379-15, Seokyo-Dong + Seoul 121-839 + KR + +00-08-F8 (hex) UTC CCS +0008F8 (base 16) UTC CCS + 791 Commerce Blvd + Boca Raton FL 33497 + US + +00-08-D5 (hex) Vanguard Networks Solutions, LLC +0008D5 (base 16) Vanguard Networks Solutions, LLC + 25 Forbes Boulevard + Foxboro MA 02035 + US + +00-08-CD (hex) With-Net Inc +0008CD (base 16) With-Net Inc + 4FL B&B B/D 1403-4 + Anyang Kyonggi 431-061 + US + +00-08-CC (hex) Remotec, Inc. +0008CC (base 16) Remotec, Inc. + 114 Union Valley Road + Oakridge TN 37830 + US + +00-08-D1 (hex) KAREL INC. +0008D1 (base 16) KAREL INC. + ORGANIZE SANAYI BOLGESI + ANKARA 06935 + TR + +00-08-A7 (hex) iLogic Inc. +0008A7 (base 16) iLogic Inc. + Rm#318, TechnoComplex Bldg., 126-16, 5-g + Seoul 136-701 + KR + +00-08-99 (hex) Netbind, Inc. +000899 (base 16) Netbind, Inc. + 5 Marine View Plaza + Hoboken NJ 07030 + US + +00-08-A0 (hex) Stotz Feinmesstechnik GmbH +0008A0 (base 16) Stotz Feinmesstechnik GmbH + Hermann-Dreher Str. 6 + Gerlingen 70839 + DE + +00-08-BC (hex) Ilevo AB +0008BC (base 16) Ilevo AB + Box 1561 + Karlstad Värmland S-651 21 + SE + +00-08-BD (hex) TEPG-US +0008BD (base 16) TEPG-US + 100 Simplex Drive + Westminster MA 01441 + US + +00-08-AE (hex) PacketFront Network Products AB +0008AE (base 16) PacketFront Network Products AB + PO 1217 + Kistagangen 2, IV Kista Stockholm SE -16428 + SE + +00-08-C3 (hex) Contex A/S +0008C3 (base 16) Contex A/S + Svanevang 2 + Allerod DK 3450 + DK + +00-08-F3 (hex) WANY +0008F3 (base 16) WANY + CEEI Cap Alpha + Montpellier Herault 34940 + FR + +00-08-DE (hex) 3UP Systems +0008DE (base 16) 3UP Systems + 6 Results Way + Cupertino CA 95014 + US + +00-08-22 (hex) InPro Comm +000822 (base 16) InPro Comm + 11F, No. 93 Shuei-Yuan Street + + TW + +00-08-23 (hex) Texa Corp. +000823 (base 16) Texa Corp. + Nara Bldg. 3F, 2-2-8 Shin-Yokohama, + 222-0033 + JP + +00-08-1D (hex) Ipsil, Incorporated +00081D (base 16) Ipsil, Incorporated + 7945 MacArthur Blvd. + Cabin John MD 20818 + US + +00-08-2D (hex) Indus Teqsite Private Limited +00082D (base 16) Indus Teqsite Private Limited + #7, Arya Gowder Road, + Tamil Nadu 600033 + IN + +00-08-20 (hex) Cisco Systems, Inc +000820 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-08-28 (hex) Koei Engineering Ltd. +000828 (base 16) Koei Engineering Ltd. + 3-40, 5-Chome + Osaku 547-0026 + JP + +00-08-24 (hex) Nuance Document Imaging +000824 (base 16) Nuance Document Imaging + 8390 Mayrand Street + Montreal Quebec H4P 2C9 + CA + +00-08-6C (hex) Plasmon LMS +00086C (base 16) Plasmon LMS + 4425 ArrowsWest Drive + Colorado Springs CO 80907 + US + +00-08-68 (hex) PurOptix +000868 (base 16) PurOptix + 1945 Camino Vida Roble + Carlsbad CA 92008 + US + +00-08-69 (hex) Command-e Technology Co.,Ltd. +000869 (base 16) Command-e Technology Co.,Ltd. + Suite 1108, Zhongsheng Mansion, + Beijing 100038 + CN + +00-08-62 (hex) NEC Eluminant Technologies, Inc. +000862 (base 16) NEC Eluminant Technologies, Inc. + 14700 Avion Parkway + Chantilly VA 20151 + US + +00-08-03 (hex) Cos Tron +000803 (base 16) Cos Tron + 4F Boolim B/D, 1431-22, + Anyang 431-061 + KR + +00-08-05 (hex) Techno-Holon Corporation +000805 (base 16) Techno-Holon Corporation + 3-19-2, Takamatsu-cho + Tokyo 190-0011 + JP + +00-08-08 (hex) PPT Vision, Inc. +000808 (base 16) PPT Vision, Inc. + 12988 Valley View Rd. + Eden Prairie MN 55344 + US + +00-08-14 (hex) TIL Technologies +000814 (base 16) TIL Technologies + Europark DePichaury, BAT 9 + + FR + +00-08-5C (hex) Shanghai Dare Technologies Co. Ltd. +00085C (base 16) Shanghai Dare Technologies Co. Ltd. + 23F, China Merchants Tower, + Pudong New Area, Shanghai + CN + +00-08-2C (hex) Homag AG +00082C (base 16) Homag AG + Abt. Ess-Mp., Homag Str. 3-5 + + DE + +00-08-21 (hex) Cisco Systems, Inc +000821 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-08-87 (hex) Maschinenfabrik Reinhausen GmbH +000887 (base 16) Maschinenfabrik Reinhausen GmbH + Falkensteinstraße 8 + Regensburg Bavaria 93059 + DE + +00-08-77 (hex) Liebert-Hiross Spa +000877 (base 16) Liebert-Hiross Spa + Via Leonardo da Vinci 8 + Piove di Sacco Z.I. Tognana 35020 + IT + +00-08-7B (hex) RTX Telecom A/S +00087B (base 16) RTX Telecom A/S + Stroemmen 6 + + DK + +00-08-61 (hex) SoftEnergy Co., Ltd. +000861 (base 16) SoftEnergy Co., Ltd. + 346 Sangwangsipli-Dong, + + KR + +00-08-4F (hex) Qualstar Corporation +00084F (base 16) Qualstar Corporation + 3990B Heritage Oak Court + Simi Valley CA 93063 + US + +00-08-54 (hex) Netronix, Inc. +000854 (base 16) Netronix, Inc. + 3F-1, No. 31, Hsin-Tai Road, + + TW + +00-08-76 (hex) SDSystem +000876 (base 16) SDSystem + 613,Hyundai I Valley,223-12, + Seongnam Gyeonggi-Do 462-807 + KR + +00-08-70 (hex) Rasvia Systems, Inc. +000870 (base 16) Rasvia Systems, Inc. + 3255-3 Scott Blvd. + Santa Clara CA 95054 + US + +00-08-6E (hex) Hyglo AB +00086E (base 16) Hyglo AB + Vastberga alle 60 + + SE + +00-07-FD (hex) LANergy Ltd. +0007FD (base 16) LANergy Ltd. + Rudloe Manor + + GB + +00-07-FE (hex) Rigaku Corporation +0007FE (base 16) Rigaku Corporation + 3-9-12, Matsubara-cho + Tokyo 196-8666 + JP + +00-04-7D (hex) Pelco +00047D (base 16) Pelco + 3500 Pelco Way + Clovis CA 93612 + US + +00-07-BF (hex) Armillaire Technologies, Inc. +0007BF (base 16) Armillaire Technologies, Inc. + 10411 Motor City Drive + Bethesda MD 20817 + US + +00-07-BB (hex) Candera Inc. +0007BB (base 16) Candera Inc. + 673 South Milpitas Blvd. + Milpitas CA 95035 + US + +00-07-BD (hex) Radionet Ltd. +0007BD (base 16) Radionet Ltd. + Keilaranta 6 + + FI + +00-07-C4 (hex) JEAN Co. Ltd. +0007C4 (base 16) JEAN Co. Ltd. + 7F, 2, Rei Kuang Road, + Taipei + TW + +00-07-B6 (hex) Telecom Technology Ltd. +0007B6 (base 16) Telecom Technology Ltd. + Docklands Innovation Park + Dublin 3 + IE + +00-07-B7 (hex) Samurai Ind. Prods Eletronicos Ltda +0007B7 (base 16) Samurai Ind. Prods Eletronicos Ltda + R-Nebraska, 443 S/2 2o Andar + 04560-011 + BR + +00-07-B0 (hex) Office Details, Inc. +0007B0 (base 16) Office Details, Inc. + 25 Ottawa + Grand Rapids MI 49503 + US + +00-07-D9 (hex) Splicecom +0007D9 (base 16) Splicecom + Little Gillions, The Green + Herts WD3 3HY + GB + +00-07-DA (hex) Neuro Telecom Co., Ltd. +0007DA (base 16) Neuro Telecom Co., Ltd. + 2F Misung B/D, 938-7 + Kyunggi-do + KR + +00-07-CD (hex) Kumoh Electronic Co, Ltd +0007CD (base 16) Kumoh Electronic Co, Ltd + 154-2 Chunui-dong + Gyeonggi-do + KR + +00-07-CF (hex) Anoto AB +0007CF (base 16) Anoto AB + Solvegatan 41 + + SE + +00-07-D2 (hex) Logopak Systeme GmbH & Co. KG +0007D2 (base 16) Logopak Systeme GmbH & Co. KG + Dorfstraße 40 + + DE + +00-07-C9 (hex) Technol Seven Co., Ltd. +0007C9 (base 16) Technol Seven Co., Ltd. + 25-16 Tobehon-cho, Nisi-ku, + + JP + +00-07-C7 (hex) Synectics Systems Limited +0007C7 (base 16) Synectics Systems Limited + 3 Acorn Business Park + S8 OTB + GB + +00-07-C3 (hex) Thomson +0007C3 (base 16) Thomson + 5-7, rue Salomon de Rothschild + 92150 + FR + +00-07-A5 (hex) Y.D.K Co. Ltd. +0007A5 (base 16) Y.D.K Co. Ltd. + 1705, Oshitate, Inagi-City, + + JP + +00-07-9C (hex) Golden Electronics Technology Co., Ltd. +00079C (base 16) Golden Electronics Technology Co., Ltd. + No. 29, 21st Road, + + TW + +00-07-E4 (hex) SoftRadio Co., Ltd. +0007E4 (base 16) SoftRadio Co., Ltd. + 2F, Dong-Bok B/D 645-18 + Seoul + KR + +00-07-8E (hex) Garz & Friche GmbH +00078E (base 16) Garz & Friche GmbH + Tempowerhving 4 + + DE + +00-07-54 (hex) Xyterra Computing, Inc. +000754 (base 16) Xyterra Computing, Inc. + 14505 Hayden Rd., + Scottsdale AZ 85260-6953 + US + +00-07-57 (hex) Topcall International AG +000757 (base 16) Topcall International AG + Talpagasse 1 + + AT + +00-07-53 (hex) Beijing Qxcomm Technology Co., Ltd. +000753 (base 16) Beijing Qxcomm Technology Co., Ltd. + 4F Tower B, TongTai Building No. 33, + Beijing 100032 + CN + +00-07-4C (hex) Beicom Inc. +00074C (base 16) Beicom Inc. + 114 King Street + Alexandria VA 22314 + US + +00-07-4D (hex) Zebra Technologies Corp. +00074D (base 16) Zebra Technologies Corp. + 333 Corporate Woods Parkway + Vernon Hills IL 60061 + US + +00-07-32 (hex) AAEON Technology Inc. +000732 (base 16) AAEON Technology Inc. + 5F, #135, Lane 235, Pao Chiao Road + Taipei + TW + +00-07-25 (hex) Bematech International Corp. +000725 (base 16) Bematech International Corp. + 5895 Shiloh Road + Alpharetta GA 30005 + US + +00-07-23 (hex) ELCON Systemtechnik GmbH +000723 (base 16) ELCON Systemtechnik GmbH + Obere Hauptstraße10 + + DE + +00-07-1D (hex) Satelsa Sistemas Y Aplicaciones De Telecomunicaciones, S.A. +00071D (base 16) Satelsa Sistemas Y Aplicaciones De Telecomunicaciones, S.A. + c/, Alejandro Moran, 56 + + ES + +00-07-20 (hex) Trutzschler GmbH & Co. KG +000720 (base 16) Trutzschler GmbH & Co. KG + Duvenstraße 82-92 + + DE + +00-07-6E (hex) Sinetica Corporation Limited +00076E (base 16) Sinetica Corporation Limited + Willow House + Monmouthshire Usk NP15 1HY + GB + +00-07-6F (hex) Synoptics Limited +00076F (base 16) Synoptics Limited + Beacon House, Nuffield Road, + + GB + +00-07-73 (hex) Ascom Powerline Communications Ltd. +000773 (base 16) Ascom Powerline Communications Ltd. + Belpstr. 37 + + CH + +00-07-6C (hex) Daehanet, Inc. +00076C (base 16) Daehanet, Inc. + #8-2 Chung Jung Rd 2- Ga + Seoul 120-012 + KR + +00-07-5D (hex) Celleritas Inc. +00075D (base 16) Celleritas Inc. + c/o Celeritas Ltd. + + IL + +00-07-3F (hex) Woojyun Systec Co., Ltd. +00073F (base 16) Woojyun Systec Co., Ltd. + 4F Han Yang B/D, Yoido-dong + Seoul 150-010 + KR + +00-07-28 (hex) Neo Telecom +000728 (base 16) Neo Telecom + East Building 9F, 1T + Songpa-gu, Seoul + KR + +00-07-2C (hex) Fabricom +00072C (base 16) Fabricom + Rue Gatti De Gamond 254 + + BE + +00-07-2D (hex) CNSystems +00072D (base 16) CNSystems + Baumkircherstrasse 1 + + AT + +00-07-2F (hex) Intransa, Inc. +00072F (base 16) Intransa, Inc. + 2670 Zanker + San Jose CA 95134 + US + +00-07-80 (hex) Bluegiga Technologies OY +000780 (base 16) Bluegiga Technologies OY + P.O. BOX 120 + FIN-02631 Espoo + FI + +00-07-77 (hex) Motah Ltd. +000777 (base 16) Motah Ltd. + 4-4-5 Koishikawa + 112-0002 + JP + +00-07-24 (hex) Telemax Co., Ltd. +000724 (base 16) Telemax Co., Ltd. + 6th Fl. Sungwoo B/D, 1099-1 + Kyungki-Do, 435-040 + KR + +00-07-1B (hex) CDVI Americas Ltd +00071B (base 16) CDVI Americas Ltd + 1637 Autoroute Laval West + Laval Quebec H7L 3W3 + CA + +00-07-15 (hex) General Research of Electronics, Inc. +000715 (base 16) General Research of Electronics, Inc. + 3-12-17, Mita, Minato-ku + Tokyo 108-0073 + JP + +00-07-37 (hex) Soriya Co. Ltd. +000737 (base 16) Soriya Co. Ltd. + 2, 8th Floor Hanshin B/O, 136-1, + Seoul, + KR + +00-07-34 (hex) ONStor, Inc. +000734 (base 16) ONStor, Inc. + 130-B Knowles Drive + Los Gatos CA 95032 + US + +00-07-65 (hex) Jade Quantum Technologies, Inc. +000765 (base 16) Jade Quantum Technologies, Inc. + 5F, No. 116, Hsien Fu Rd., + + TW + +00-05-EA (hex) Rednix +0005EA (base 16) Rednix + 502, Dong-A Resort Officetel + Taejon 305-709 + KR + +00-06-C9 (hex) Technical Marketing Research, Inc. +0006C9 (base 16) Technical Marketing Research, Inc. + Shin Nihon Gijutsu Bldg. + Tokyo 105-0012 105-0012 + JP + +00-06-C8 (hex) Sumitomo Metal Micro Devices, Inc. +0006C8 (base 16) Sumitomo Metal Micro Devices, Inc. + 1, Higashimukojima Higashino-cho + + JP + +00-06-F1 (hex) Optillion +0006F1 (base 16) Optillion + Kronborgsgr.9 + + SE + +00-06-A7 (hex) Primarion +0006A7 (base 16) Primarion + 3450 Torrance Blvd. + Torrance CA 90503 + US + +00-06-A9 (hex) Universal Instruments Corp. +0006A9 (base 16) Universal Instruments Corp. + PO Box 825 + Binghamton NY 13902 + US + +00-06-9E (hex) UNIQA, Inc. +00069E (base 16) UNIQA, Inc. + 477 Valley Way + Milpitas CA 95035 + US + +00-06-B1 (hex) Sonicwall +0006B1 (base 16) Sonicwall + 1160 Bordeaux Dr. + Sunnyvale CA 94089 + US + +00-06-AD (hex) KB Electronics Ltd. +0006AD (base 16) KB Electronics Ltd. + 150 Bluewater Rd. + B4B 1G9 + CA + +00-06-AF (hex) Xalted Networks +0006AF (base 16) Xalted Networks + 2901 Dallas Parkway + Plano TX 75093 + US + +00-06-D7 (hex) Cisco Systems, Inc +0006D7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-06-D5 (hex) Diamond Systems Corp. +0006D5 (base 16) Diamond Systems Corp. + 8430-D Central Ave. + Newark CA 94560 + US + +00-06-FD (hex) Comjet Information Systems Corp. +0006FD (base 16) Comjet Information Systems Corp. + 7Fl., No. 103, Fen Liao Street + + TW + +00-06-F9 (hex) Mitsui Zosen Systems Research Inc. +0006F9 (base 16) Mitsui Zosen Systems Research Inc. + 11-1, Uno 1-chome + 706-0011 + JP + +00-06-C0 (hex) United Internetworks, Inc. +0006C0 (base 16) United Internetworks, Inc. + 5072 North 300 West, Suite 2N + Provo UT 84604 + US + +00-06-E0 (hex) MAT Co., Ltd. +0006E0 (base 16) MAT Co., Ltd. + 864-3 Kwanyang-dong + Kyunggi-do 431-060 + KR + +00-D0-B9 (hex) MICROTEK INTERNATIONAL, INC. +00D0B9 (base 16) MICROTEK INTERNATIONAL, INC. + NO. 6 INDUSTRY EAST ROAD 3 + TAIWAN 30077 TAIWAN 30077 R.O.C. + TW + +00-D0-5F (hex) VALCOM, INC. +00D05F (base 16) VALCOM, INC. + 1111 INDUSTRY AVENUE + ROANOKE VA 24013 + US + +00-06-75 (hex) Banderacom, Inc. +000675 (base 16) Banderacom, Inc. + 9211 Waterford Centre Blvd. + Austin TX 78758 + US + +00-06-98 (hex) egnite GmbH +000698 (base 16) egnite GmbH + Erinstraße 9 + Castrop-Rauxel D-44575 + DE + +00-06-9C (hex) Transmode Systems AB +00069C (base 16) Transmode Systems AB + Jakobsdalsvagen 17 + Hägersten SE-126 53 + SE + +00-06-43 (hex) SONO Computer Co., Ltd. +000643 (base 16) SONO Computer Co., Ltd. + 1F., No. 8, Alley 35, Lane 91, + Taipei + TW + +00-06-49 (hex) 3M Deutschland GmbH +000649 (base 16) 3M Deutschland GmbH + Carl-Schurz-Str. 1 + Neuss D-41453 + DE + +00-06-3E (hex) Opthos Inc. +00063E (base 16) Opthos Inc. + 590 Taylor Way + San Carlos CA 94070 + US + +00-06-3B (hex) Arcturus Networks Inc. +00063B (base 16) Arcturus Networks Inc. + 701 Evans Ave. - Suite 300 + Toronto Ontario M9C 1A3 + CA + +00-06-7B (hex) Toplink C&C Corporation +00067B (base 16) Toplink C&C Corporation + 6F-15, No. 12, Lane 609, Sec. 5 + Taipei Hsien 241 + TW + +00-06-70 (hex) Upponetti Oy +000670 (base 16) Upponetti Oy + Tykistokatu 4D + + FI + +00-06-6F (hex) Korea Data Systems +00066F (base 16) Korea Data Systems + 170, Gongdan-Dong, Gumi-Si + Kyungbuk 730-030 + KR + +00-06-68 (hex) Vicon Industries Inc. +000668 (base 16) Vicon Industries Inc. + 89 Arkay Drive + Hauppauge NY 11788 + US + +00-06-6D (hex) Compuprint S.P.A. +00066D (base 16) Compuprint S.P.A. + Via Martiri D'Italia 26 + + IT + +00-06-26 (hex) MWE GmbH +000626 (base 16) MWE GmbH + Olbrichtstraße 21 + + DE + +00-06-20 (hex) Serial System Ltd. +000620 (base 16) Serial System Ltd. + 76 Playfair Road + 367996 + SG + +00-06-18 (hex) DigiPower Manufacturing Inc. +000618 (base 16) DigiPower Manufacturing Inc. + No. 114, Floor 13, Sec. 1, + Taipei + TW + +00-06-33 (hex) Cross Match Technologies GmbH +000633 (base 16) Cross Match Technologies GmbH + Unstrutweg 4 + Jena 07743 + DE + +00-06-86 (hex) ZARDCOM Co., Ltd. +000686 (base 16) ZARDCOM Co., Ltd. + 4F, 1548-1, Seocho Dong, Seocho-Gu + Seoul + KR + +00-06-89 (hex) yLez Technologies Pte Ltd +000689 (base 16) yLez Technologies Pte Ltd + No. 1, Tannery Road, Cencon 1, + + SG + +00-06-81 (hex) Goepel Electronic GmbH +000681 (base 16) Goepel Electronic GmbH + Goeschwitzer Str. 58-60 + + DE + +00-06-58 (hex) Helmut Fischer GmbH Institut für Elektronik und Messtechnik +000658 (base 16) Helmut Fischer GmbH Institut für Elektronik und Messtechnik + Industriestraße 21 + + DE + +00-05-D3 (hex) eProduction Solutions, Inc. +0005D3 (base 16) eProduction Solutions, Inc. + 22001 North Park Drive + Kingwood TX 77339-3804 + US + +00-06-04 (hex) @Track Communications, Inc. +000604 (base 16) @Track Communications, Inc. + 1155 Kas Dr. + Richardson TX 75081 + US + +00-06-06 (hex) RapidWAN, Inc. +000606 (base 16) RapidWAN, Inc. + 2085 Hamilton Ave. + San Jose CA 95125 + US + +00-06-03 (hex) Baker Hughes Inc. +000603 (base 16) Baker Hughes Inc. + 2001 Rankin Rd. + Houston TX 77073 + US + +00-06-07 (hex) Omni Directional Control Technology Inc. +000607 (base 16) Omni Directional Control Technology Inc. + 8F-2, No. 94, Pao-Chung Rd. + Taipei Hsien, + TW + +00-05-F7 (hex) Analog Devices, Inc. +0005F7 (base 16) Analog Devices, Inc. + Three Technology Way + Norwood MA 02062-2666 + US + +00-05-9C (hex) Kleinknecht GmbH, Ing. Büro +00059C (base 16) Kleinknecht GmbH, Ing. Büro + Bachstraße 30 + + DE + +00-05-AE (hex) Mediaport USA +0005AE (base 16) Mediaport USA + 17151 Newhope Ave. #202 + Fountain Valley CA 92708 + US + +00-05-B0 (hex) Korea Computer Technology Co., Ltd. +0005B0 (base 16) Korea Computer Technology Co., Ltd. + KCT Bldg, 111-3 Yangjae-Dong, + + KR + +00-05-B2 (hex) Medison Co., Ltd. +0005B2 (base 16) Medison Co., Ltd. + 997-4, Saechi-Dong, + 135-280 + KR + +00-05-97 (hex) Eagle Traffic Control Systems +000597 (base 16) Eagle Traffic Control Systems + 8004 Cameron Road + Austin TX 78754 + US + +00-05-B5 (hex) Broadcom Technologies +0005B5 (base 16) Broadcom Technologies + 137-060 + Secho-Gu Seoul, + KR + +00-05-CB (hex) ROIS Technologies, Inc. +0005CB (base 16) ROIS Technologies, Inc. + 6th F Changhyun B/D, 960-1 + 431-080 + KR + +00-05-C8 (hex) VERYTECH +0005C8 (base 16) VERYTECH + #402, Jang Young Shil Kwan, + + KR + +00-05-CD (hex) D&M Holdings Inc. +0005CD (base 16) D&M Holdings Inc. + D&M Building, 2-1 Nisshin-cho + Kawasaki-shi Kanagawa 210-8569 + JP + +00-05-A2 (hex) CELOX Networks +0005A2 (base 16) CELOX Networks + 940 West Port Plaza - Ste. #300 + St. Louis MO 63146 + US + +00-05-AA (hex) Moore Industries International Inc. +0005AA (base 16) Moore Industries International Inc. + 16650 Schoenborn St. + North Hills CA 91343 + US + +00-05-E7 (hex) Netrake an AudioCodes Company +0005E7 (base 16) Netrake an AudioCodes Company + 3000 Technology Drive + Plano TX 75074 + US + +00-05-F4 (hex) System Base Co., Ltd. +0005F4 (base 16) System Base Co., Ltd. + 475-22, BangBae 2 dong, + + KR + +00-05-E1 (hex) Trellis Photonics, Ltd. +0005E1 (base 16) Trellis Photonics, Ltd. + P.O.B. 36 + + IL + +00-05-E2 (hex) Creativ Network Technologies +0005E2 (base 16) Creativ Network Technologies + 1755 St. Regis Suite 240 + Quebec H9B-2M9 + CA + +00-06-13 (hex) Kawasaki Microelectronics Incorporated +000613 (base 16) Kawasaki Microelectronics Incorporated + MTG B-5, 1-3, Nakase, + Mihama-ku Chiba 261-8501 + JP + +00-06-17 (hex) Redswitch Inc. +000617 (base 16) Redswitch Inc. + 1815 McCandless Drive + Milpitas CA 95035-8046 + US + +00-05-51 (hex) F & S Elektronik Systeme GmbH +000551 (base 16) F & S Elektronik Systeme GmbH + Untere Waldplaetze 23 + Stuttgart 70569 + DE + +00-05-4D (hex) Brans Technologies, Inc. +00054D (base 16) Brans Technologies, Inc. + 501 Boramae Academy Tower + + KR + +00-05-47 (hex) Starent Networks +000547 (base 16) Starent Networks + 30 International Place + Tewksbury MA 01876 + US + +00-05-4E (hex) Philips +00054E (base 16) Philips + 1000 West Maude Avenue + Sunnyvale CA 94085-2810 + US + +00-05-46 (hex) KDDI Network & Solultions Inc. +000546 (base 16) KDDI Network & Solultions Inc. + 2-3-1, Nishishinjunku-ku, + Tokyo 163-0907 + JP + +00-05-40 (hex) FAST Corporation +000540 (base 16) FAST Corporation + 2791-5 Shimo-Tsuruma + 242-0001 + JP + +00-05-3C (hex) XIRCOM +00053C (base 16) XIRCOM + 2300 CORPORATE CENTER DR. + THOUSAND OAKS CA 91320 + US + +00-05-44 (hex) Valley Technologies, Inc. +000544 (base 16) Valley Technologies, Inc. + 1006 West College Ave. + State College PA 16801 + US + +00-05-2E (hex) Cinta Networks +00052E (base 16) Cinta Networks + 3010 North First Street + San Jose CA 95134 + US + +00-05-2F (hex) Leviton Network Solutions +00052F (base 16) Leviton Network Solutions + 2222 222nd Street S.E. + Bothell WA 98021 + US + +00-05-3B (hex) Harbour Networks Ltd., Co. Beijing +00053B (base 16) Harbour Networks Ltd., Co. Beijing + 13/F, JiuLing Building, No. 21, + 100089 + CN + +00-05-28 (hex) New Focus, Inc. +000528 (base 16) New Focus, Inc. + 2630 Walsh Ave. + Santa Clara CA 95051 + US + +00-05-6B (hex) C.P. Technology Co., Ltd. +00056B (base 16) C.P. Technology Co., Ltd. + 12F, No. 86, Hsin Tai Wu Rd., + 221 + TW + +00-05-60 (hex) LEADER COMM.CO., LTD +000560 (base 16) LEADER COMM.CO., LTD + 234, Komae-ri, Kiheung-eup, + 449-900 + KR + +00-05-5E (hex) Cisco Systems, Inc +00055E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-96 (hex) Genotech Co., Ltd. +000596 (base 16) Genotech Co., Ltd. + #308 Gunkook Bldg., + Gumchon-Gu Seoul + KR + +00-05-79 (hex) Universal Control Solution Corp. +000579 (base 16) Universal Control Solution Corp. + 12843 Foothill Blvd. + Sylmar CA 91342 + US + +00-05-7F (hex) Acqis Technology +00057F (base 16) Acqis Technology + 1621 West El Camino Real + Mt. View CA 94040 + US + +00-05-73 (hex) Cisco Systems, Inc +000573 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-75 (hex) CDS-Electronics BV +000575 (base 16) CDS-Electronics BV + Mozart laan 330 + + NL + +00-05-56 (hex) 360 Systems +000556 (base 16) 360 Systems + 31355 Agoura Road + Westlake Village CA 91361 + US + +00-05-59 (hex) Intracom S.A. +000559 (base 16) Intracom S.A. + 19 5 KM Markopoulou Ave. + Attika + GR + +00-05-8C (hex) Opentech Inc. +00058C (base 16) Opentech Inc. + 6F, DongWon Bldg., 275 + Seoul 137-130 + KR + +00-04-C9 (hex) Micro Electron Co., Ltd. +0004C9 (base 16) Micro Electron Co., Ltd. + 13-1-205 Aobaokakita + Suita-city Osaka + JP + +00-04-BE (hex) OptXCon, Inc. +0004BE (base 16) OptXCon, Inc. + P.O. Box 13449 + Research Triangle Park NC 27709-3449 + US + +00-04-C4 (hex) Audiotonix Group Limited +0004C4 (base 16) Audiotonix Group Limited + Unit 10, Silverglade Business Park + Chessington Surrey KT9 2QL + GB + +00-04-C1 (hex) Cisco Systems, Inc +0004C1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-04-D6 (hex) Takagi Industrial Co., Ltd. +0004D6 (base 16) Takagi Industrial Co., Ltd. + Electronic Instrument Div. + 418-0103 418-0103 + JP + +00-04-D1 (hex) Drew Technologies, Inc. +0004D1 (base 16) Drew Technologies, Inc. + 3915 Research Park Dr + Ann Arbor MI 48108 + US + +00-04-D0 (hex) Softlink s.r.o. +0004D0 (base 16) Softlink s.r.o. + Tomkova 409 + Czech Republic + CZ + +00-80-87 (hex) OKI ELECTRIC INDUSTRY CO., LTD +008087 (base 16) OKI ELECTRIC INDUSTRY CO., LTD + 10-3 SHIBAURA 4-CHOME + + JP + +00-04-D9 (hex) Titan Electronics, Inc. +0004D9 (base 16) Titan Electronics, Inc. + Rm 7, 11 Fl., No. 398, + Taoyuan Taoyuan TAIWAN + TW + +00-04-D8 (hex) IPWireless, Inc. +0004D8 (base 16) IPWireless, Inc. + 4 Landsowne Court + SN14 GRZ UK + GB + +00-05-24 (hex) BTL System (HK) Limited +000524 (base 16) BTL System (HK) Limited + 14/F., Blk. B, Vita Tower, + Aberdeen + HK + +00-05-22 (hex) LEA*D Corporation, Inc. +000522 (base 16) LEA*D Corporation, Inc. + Advatech Bldg. + + IL + +00-05-20 (hex) Smartronix, Inc. +000520 (base 16) Smartronix, Inc. + 22685 Three Notch Rd. + California MD 20619 + US + +00-04-EB (hex) Paxonet Communications, Inc. +0004EB (base 16) Paxonet Communications, Inc. + 4046 Clipper Court + Fremont CA 94538 + US + +00-04-EF (hex) Polestar Corp. +0004EF (base 16) Polestar Corp. + RM #802 SeoGeon B/D, 1480, + Korea (ROK) + KR + +00-05-14 (hex) KDT Systems Co., Ltd. +000514 (base 16) KDT Systems Co., Ltd. + 102-6, Chobu-Li, Mohyun-Myun, + + KR + +00-05-0B (hex) SICOM Systems, Inc. +00050B (base 16) SICOM Systems, Inc. + 4140 Skyron Drive + Doylestown PA 18901 + US + +00-05-05 (hex) Systems Integration Solutions, Inc. +000505 (base 16) Systems Integration Solutions, Inc. + 3922 Coconut Palm Drive, + Tampa FL 33619 + US + +00-04-FE (hex) Pelago Networks +0004FE (base 16) Pelago Networks + 701 E. Plano Parkway - Ste. #205 + Plano TX 75074 + US + +00-05-18 (hex) Jupiters Technology +000518 (base 16) Jupiters Technology + PO Box 12693 + + AU + +00-04-B7 (hex) AMB i.t. Holding +0004B7 (base 16) AMB i.t. Holding + Zuiderhoutlaan 4 + PJ Haarlem 2012 + NL + +00-04-B9 (hex) S.I. Soubou, Inc. +0004B9 (base 16) S.I. Soubou, Inc. + 4-2586-8 + Tokorozawa Sitama 359-0047 + JP + +00-04-BB (hex) Bardac Corporation +0004BB (base 16) Bardac Corporation + 40 Log Canoe Circle + Stevensville MD 21666 + US + +00-04-BC (hex) Giantec, Inc. +0004BC (base 16) Giantec, Inc. + 4F, No. 3, Lane 123, + TAIWAN 231 TAIWAN 231 R.O.C. + TW + +00-04-AF (hex) Digital Fountain, Inc. +0004AF (base 16) Digital Fountain, Inc. + 600 Alabama St. + San Francisco CA 94110 + US + +00-04-56 (hex) Cambium Networks Limited +000456 (base 16) Cambium Networks Limited + Unit B2, Linhay Business Park, + Ashburton Devon TQ13 7UP + GB + +00-04-58 (hex) Fusion X Co., Ltd. +000458 (base 16) Fusion X Co., Ltd. + #905 Hansol Techno Town + Zip 435-030 + KR + +00-04-4F (hex) Schubert System Elektronik Gmbh +00044F (base 16) Schubert System Elektronik Gmbh + Rudolf-Diesel-Str. 17 + + DE + +00-04-46 (hex) CYZENTECH Co., Ltd. +000446 (base 16) CYZENTECH Co., Ltd. + 601 Eunkyeong B/D 141-31, + 135-876 KOREA + KR + +00-04-4A (hex) iPolicy Networks, Inc. +00044A (base 16) iPolicy Networks, Inc. + 47467 Fremont Blvd. + Fremont CA 94538 + US + +00-04-40 (hex) cyberPIXIE, Inc. +000440 (base 16) cyberPIXIE, Inc. + 68 E. Wacker Place, + Chicago IL 60601 + US + +00-04-3C (hex) SONOS Co., Ltd. +00043C (base 16) SONOS Co., Ltd. + #725 Pungsan Apt. Factory + Rep. of KOREA Zip Code: 411-815 + KR + +00-04-B2 (hex) ESSEGI SRL +0004B2 (base 16) ESSEGI SRL + Via Del Cavaratori, 17 + + IT + +00-04-B4 (hex) CIAC +0004B4 (base 16) CIAC + 18 rue Joseph BARA + + FR + +00-04-AD (hex) Malibu Networks +0004AD (base 16) Malibu Networks + 26637 Agoura Rd. + Calabasas CA 91302 + US + +00-04-A9 (hex) SandStream Technologies, Inc. +0004A9 (base 16) SandStream Technologies, Inc. + 1955 Lakeway Dr. + Lewisville TX 75057 + US + +00-04-61 (hex) EPOX Computer Co., Ltd. +000461 (base 16) EPOX Computer Co., Ltd. + 11F, #346, Chung San Rd. + TAIWAN TAIWAN R.O.C. + TW + +00-04-62 (hex) DAKOS Data & Communication Co., Ltd. +000462 (base 16) DAKOS Data & Communication Co., Ltd. + 2nd Floor Bethel Building 324-1 + Zip code: 137-130 + TW + +00-04-5F (hex) Avalue Technology, Inc. +00045F (base 16) Avalue Technology, Inc. + 7F, 228, Lian-Cheng Road + TAIWAN TAIWAN R.O.C. + TW + +00-04-9C (hex) Surgient Networks, Inc. +00049C (base 16) Surgient Networks, Inc. + 3520 Executive Center Drive + Austin TX 78731 + US + +00-04-9D (hex) Ipanema Technologies +00049D (base 16) Ipanema Technologies + 28, Rue De La Redoute + + FR + +00-04-60 (hex) Knilink Technology, Inc. +000460 (base 16) Knilink Technology, Inc. + 10F, #96, Hsin Tai Wu Rd., + TAIWAN + TW + +00-04-8F (hex) TD Systems Corporation +00048F (base 16) TD Systems Corporation + 100 Bearfoot Rd. + Hudson MA 01749 + US + +00-04-95 (hex) Tejas Networks India Limited +000495 (base 16) Tejas Networks India Limited + #58, 1st Main Road, J.P. Nagar, + Bangalore 560078 + IN + +00-04-6F (hex) Digitel S/A Industria Eletronica +00046F (base 16) Digitel S/A Industria Eletronica + R. Doutor Joao Ignacio, 1165 + Zip: 90230.181 + BR + +00-04-69 (hex) Innocom, Inc. +000469 (base 16) Innocom, Inc. + 655-2 Naebalsan-Dong + 157-280 157-280 KOREA + KR + +00-04-87 (hex) Cogency Semiconductor, Inc. +000487 (base 16) Cogency Semiconductor, Inc. + 362 Terry Fox Drive, Suite 210 + + CA + +00-04-68 (hex) Vivity, Inc. +000468 (base 16) Vivity, Inc. + 3360 Mitchell Lane + Boulder CO 80301 + US + +00-03-E1 (hex) Winmate Communication, Inc. +0003E1 (base 16) Winmate Communication, Inc. + 9F,No.111-6,Shing-De Rd + Taipei 241 + TW + +00-03-E4 (hex) Cisco Systems, Inc +0003E4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-DC (hex) Lexar Media, Inc. +0003DC (base 16) Lexar Media, Inc. + 47421 Bayside Parkway + Fremont CA 94538 + US + +00-03-D8 (hex) iMPath Networks, Inc. +0003D8 (base 16) iMPath Networks, Inc. + 1431 Merivale Rd. + CANADA K2E 1B9 + CA + +00-03-D5 (hex) Advanced Communications Co., Ltd. +0003D5 (base 16) Advanced Communications Co., Ltd. + 2876-1 Ooka + Shizuoka 41-0022 + JP + +00-03-F7 (hex) Plast-Control GmbH +0003F7 (base 16) Plast-Control GmbH + Walter-Freitag-Str. 15 + + DE + +00-03-FC (hex) Intertex Data AB +0003FC (base 16) Intertex Data AB + Rissneleden 45 + + SE + +00-03-EF (hex) Oneline AG +0003EF (base 16) Oneline AG + Steinfeldstraße 3 + + DE + +00-03-F1 (hex) Cicada Semiconductor, Inc. +0003F1 (base 16) Cicada Semiconductor, Inc. + 811 Barton Springs Rd. + Austin TX 78704 + US + +00-04-30 (hex) Netgem +000430 (base 16) Netgem + 27 rue d'Orleans + + FR + +00-04-2C (hex) Minet, Inc. +00042C (base 16) Minet, Inc. + 3F Se-A Venture Tower + KOREA + KR + +00-04-2A (hex) Wireless Networks, Inc. +00042A (base 16) Wireless Networks, Inc. + 2322 El Camino Real + San Mateo CA 94403 + US + +00-04-2B (hex) IT Access Co., Ltd. +00042B (base 16) IT Access Co., Ltd. + 3-17-6, Shinyokohama, Kouhoku-ku + Yokohama-shi Kanagawa 222-8545 + JP + +00-03-D6 (hex) RADVision, Ltd. +0003D6 (base 16) RADVision, Ltd. + 24 Raul Wallenberg St. + + IL + +00-03-D4 (hex) Alloptic, Inc. +0003D4 (base 16) Alloptic, Inc. + 6960 Koll Center Parkway + Pleasanton CA 94566 + US + +00-03-CE (hex) ETEN Technologies, Inc. +0003CE (base 16) ETEN Technologies, Inc. + 2F, No. 9, Lane 235, Pao-Chiao Rd., + TAIWAN TAIWAN R.O.C. + TW + +00-03-C8 (hex) CML Emergency Services +0003C8 (base 16) CML Emergency Services + 75 Boulevard la Technologies + + CA + +00-03-C3 (hex) Micronik Multimedia +0003C3 (base 16) Micronik Multimedia + Brückenstraße 2 + + DE + +00-04-19 (hex) Fibercycle Networks, Inc. +000419 (base 16) Fibercycle Networks, Inc. + 20 South Santa Cruz Ave. + Los Gatos CA 95030 + US + +00-04-1C (hex) ipDialog, Inc. +00041C (base 16) ipDialog, Inc. + 1762 Technology Drive + San Jose CA 95110 + US + +00-04-18 (hex) Teltronic S.A.U. +000418 (base 16) Teltronic S.A.U. + Poligono de Malpica + + ES + +00-03-70 (hex) NXTV, Inc. +000370 (base 16) NXTV, Inc. + 5955 De Soto Ave, #160 + Woodland Hills CA 91367 + US + +00-04-02 (hex) Nexsan Technologies, Ltd. +000402 (base 16) Nexsan Technologies, Ltd. + Parker Centre + Derby DE21 4SZ + GB + +00-03-ED (hex) Shinkawa Electric Co., Ltd. +0003ED (base 16) Shinkawa Electric Co., Ltd. + 3-2-24 3 chome + + JP + +00-03-BD (hex) OmniCluster Technologies, Inc. +0003BD (base 16) OmniCluster Technologies, Inc. + 4950 Blue Lake Drive + Boca Raton FL 33431 + US + +00-03-C0 (hex) RFTNC Co., Ltd. +0003C0 (base 16) RFTNC Co., Ltd. + 3F, 1624-24, Bongchen-dong + SOUTH KOREA + KR + +00-03-B8 (hex) NetKit Solutions, LLC +0003B8 (base 16) NetKit Solutions, LLC + 26630 Agoura Road + Calabasas CA 91302 + US + +00-03-B7 (hex) ZACCESS Systems +0003B7 (base 16) ZACCESS Systems + 275 Shoreline Drive, #110 + Redwood City CA 94065 + US + +00-03-A0 (hex) Cisco Systems, Inc +0003A0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-A2 (hex) Catapult Communications +0003A2 (base 16) Catapult Communications + 160 S. Whisman Rd. + Mountain View CA 94041 + US + +00-03-9C (hex) OptiMight Communications, Inc. +00039C (base 16) OptiMight Communications, Inc. + 980 Linda Vista Avenue + Mountain View CA 94043 + US + +00-03-B0 (hex) Xsense Technology Corp. +0003B0 (base 16) Xsense Technology Corp. + 11 F, 232, Sec. 3, ChengTeh Rd. + Taipei TAIWAN, 103 + TW + +00-03-AA (hex) Watlow +0003AA (base 16) Watlow + 1241 Bundy Blvd. + Winona MN 55987 + US + +00-03-A8 (hex) IDOT Computers, Inc. +0003A8 (base 16) IDOT Computers, Inc. + 3F., No. 137, Lane 235 + TAIWAN TAIWAN R.O.C. + TW + +00-03-55 (hex) TeraBeam Internet Systems +000355 (base 16) TeraBeam Internet Systems + 14833 NE 87th St., Bldg. C + Redmond WA 98052 + US + +00-03-69 (hex) Nippon Antenna Co., Ltd. +000369 (base 16) Nippon Antenna Co., Ltd. + No. 49-8, Nishiogu, + Tokyo 116-8561 + JP + +00-03-73 (hex) Aselsan A.S +000373 (base 16) Aselsan A.S + Mehmet Akif Ersoy Mah. + + TR + +00-03-77 (hex) Gigabit Wireless +000377 (base 16) Gigabit Wireless + 3099 N. First Street + San Jose CA 95134 + US + +00-03-65 (hex) Kira Information & Communications, Ltd. +000365 (base 16) Kira Information & Communications, Ltd. + 6th Fl. Anam Tower, + + KR + +00-03-85 (hex) Actelis Networks, Inc. +000385 (base 16) Actelis Networks, Inc. + 1 Bazel St., P.O.B. 10173 + + IL + +00-03-54 (hex) Fiber Logic Communications +000354 (base 16) Fiber Logic Communications + 5F-3, No. 9, Prosperity Road One, + Hsinchu + TW + +00-03-50 (hex) BTICINO SPA +000350 (base 16) BTICINO SPA + Via L. Manara, 4 + + IT + +00-03-51 (hex) Diebold, Inc. +000351 (base 16) Diebold, Inc. + 5995 Mayfair Road + North Canton OH 44720 + US + +00-03-4E (hex) Pos Data Company, Ltd. +00034E (base 16) Pos Data Company, Ltd. + 276-2, Seo-Hyun Dong, + + KR + +00-03-48 (hex) Norscan Instruments, Ltd. +000348 (base 16) Norscan Instruments, Ltd. + 7 Terracon Place + R2J 4B3 + CA + +00-03-46 (hex) Hitachi Kokusai Electric, Inc. +000346 (base 16) Hitachi Kokusai Electric, Inc. + 1-6-10 Uchikanda + + JP + +00-03-44 (hex) Tietech.Co., Ltd. +000344 (base 16) Tietech.Co., Ltd. + 2-13-1 Chikamatoori Minamiku + + JP + +00-02-E6 (hex) Gould Instrument Systems, Inc. +0002E6 (base 16) Gould Instrument Systems, Inc. + 8333 Rockside Road + Valley View OH 44125 + US + +00-02-E4 (hex) JC HYUN Systems, Inc. +0002E4 (base 16) JC HYUN Systems, Inc. + Shinbong Bldg, 736-6, + Seoul (135-080) + KR + +00-02-DE (hex) Astrodesign, Inc. +0002DE (base 16) Astrodesign, Inc. + 2-22-12 Kamikodana Ka + Kanagawa + JP + +00-02-E2 (hex) NDC Infared Engineering +0002E2 (base 16) NDC Infared Engineering + 5314 N. Irwindale Ave. + Irwindale CA 91706 + US + +00-02-E1 (hex) Integrated Network Corporation +0002E1 (base 16) Integrated Network Corporation + 757 Route 202/206 + Bridgewater NJ 08807 + US + +00-02-F7 (hex) ARM +0002F7 (base 16) ARM + 110, Fulbourn Road + CB1 9NJ + GB + +00-D0-24 (hex) Cognex Corporation +00D024 (base 16) Cognex Corporation + Modular Vision Systems Division + Portland OR 97224 + US + +00-02-F1 (hex) Pinetron Co., Ltd. +0002F1 (base 16) Pinetron Co., Ltd. + Bldg. #1599-11, + Seoul 137-073 + KR + +00-02-ED (hex) DXO Telecom Co., Ltd. +0002ED (base 16) DXO Telecom Co., Ltd. + 8F, 300-11, Yumgok-Dong, + + KR + +00-02-EC (hex) Maschoff Design Engineering +0002EC (base 16) Maschoff Design Engineering + 1325 Kenilworth Drive + Woodbury MN 55125 + US + +00-03-36 (hex) Zetes Technologies +000336 (base 16) Zetes Technologies + 3 Rue De Stras Bourg + + BE + +00-03-37 (hex) Vaone, Inc. +000337 (base 16) Vaone, Inc. + 6F Kyemong Art Center, + 135-082 + KR + +00-03-3B (hex) TAMI Tech Co., Ltd. +00033B (base 16) TAMI Tech Co., Ltd. + 4F, Chungdo Bencher Town + Taejon + KR + +00-03-2D (hex) IBASE Technology, Inc. +00032D (base 16) IBASE Technology, Inc. + 5F, No. 221, + Taipei + TW + +00-B0-52 (hex) Atheros Communications +00B052 (base 16) Atheros Communications + 5955 T.G. Lee Blvd, Ste. 600 + Ocala FL 32822 + US + +00-03-43 (hex) Martin Professional A/S +000343 (base 16) Martin Professional A/S + Olof Palmes Alle 18 + + DK + +00-03-35 (hex) Mirae Technology +000335 (base 16) Mirae Technology + 211-15, Hon Hyun-dong, + Seoul + KR + +00-02-F8 (hex) SEAKR Engineering, Inc. +0002F8 (base 16) SEAKR Engineering, Inc. + 12847 E. Peakview Ave. + Englewood CO 80111 + US + +00-03-14 (hex) Teleware Network Systems +000314 (base 16) Teleware Network Systems + #7806 7th Dongil Technotown, + 431-062 + KR + +00-03-2F (hex) Global Sun Technology, Inc. +00032F (base 16) Global Sun Technology, Inc. + No. 13, Tung Yuan Rd., + + TW + +00-02-DC (hex) Fujitsu General Limited +0002DC (base 16) Fujitsu General Limited + 1116, Suenaga, Takatsu-Ku, + 213-8502 + JP + +00-02-D7 (hex) EMPEG Ltd +0002D7 (base 16) EMPEG Ltd + 1 Signet Court + CB5 8LA + GB + +00-02-D3 (hex) NetBotz, Inc. +0002D3 (base 16) NetBotz, Inc. + 110044 Research Blvd. + Austin TX 78759 + US + +00-02-DA (hex) ExiO Communications, Inc. +0002DA (base 16) ExiO Communications, Inc. + 2362 Qume Drive + San Jose CA 95131 + US + +00-02-D4 (hex) PDA Peripherals, Inc. +0002D4 (base 16) PDA Peripherals, Inc. + 205 Orange St. + New Haven CT 06510 + US + +00-02-D6 (hex) NICE Systems +0002D6 (base 16) NICE Systems + 8 Hapnina St., POB 690 + + IL + +00-02-7D (hex) Cisco Systems, Inc +00027D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-02-7C (hex) Trilithic, Inc. +00027C (base 16) Trilithic, Inc. + 9202 E. 33rd Street + Indianapolis IN 46235 + US + +00-02-8B (hex) VDSL Systems OY +00028B (base 16) VDSL Systems OY + Tekniikantie 12 + + FI + +00-02-8C (hex) Micrel-Synergy Semiconductor +00028C (base 16) Micrel-Synergy Semiconductor + 3250 Scott Boulevard + Santa Clara CA 95054 + US + +00-02-8D (hex) Movita Technologies, Inc. +00028D (base 16) Movita Technologies, Inc. + No. 26 Wu-Chuan 7th Road, + Taipei Taiwan, R.O.C. + TW + +00-02-98 (hex) Broadframe Corporation +000298 (base 16) Broadframe Corporation + 5828 Moonstone Ave. + Alta Loma CA 91701 + US + +00-02-97 (hex) C-COR.net +000297 (base 16) C-COR.net + 60 Decibel Road + State College PA 16801 + US + +00-02-91 (hex) Open Network Co., Ltd. +000291 (base 16) Open Network Co., Ltd. + Seishin Bldg., 2-5-10 Shinjuku + JAPAN 160-0022 + JP + +00-02-C1 (hex) Innovative Electronic Designs, Inc. +0002C1 (base 16) Innovative Electronic Designs, Inc. + 9701 Taylorsville Rd. + Louisville KY 40299 + US + +00-02-C0 (hex) Bencent Tzeng Industry Co., Ltd. +0002C0 (base 16) Bencent Tzeng Industry Co., Ltd. + 3rd fl., No. 3 Ruey Kuang Rd., + Taiwan Taiwan R.O.C. + TW + +00-02-99 (hex) Apex, Inc. +000299 (base 16) Apex, Inc. + 9911 Willows Rd. N.E. + Redmond WA 95052 + US + +00-02-75 (hex) SMART Technologies, Inc. +000275 (base 16) SMART Technologies, Inc. + 3636 Research Road NW + Calgary, Alberta T2L1Y1 + CA + +00-02-C6 (hex) Data Track Technology PLC +0002C6 (base 16) Data Track Technology PLC + 153 Somerford Road + UNITED KINGDOM + GB + +00-02-A6 (hex) Effinet Systems Co., Ltd. +0002A6 (base 16) Effinet Systems Co., Ltd. + Yugong Bldg. 502 + Korea + KR + +00-02-5F (hex) Nortel Networks +00025F (base 16) Nortel Networks + 9300 trans-CANADA Highway + H4S 1KS + CA + +00-02-5C (hex) SCI Systems (Kunshan) Co., Ltd. +00025C (base 16) SCI Systems (Kunshan) Co., Ltd. + 312 QING YANG ROAD + CHINA CHINA 215300 + CN + +00-00-87 (hex) HITACHI, LTD. +000087 (base 16) HITACHI, LTD. + NETWORK ENGINEERING DIV. + TOKYO 140 + JP + +00-02-58 (hex) Flying Packets Communications +000258 (base 16) Flying Packets Communications + 388 Market Street + San Francisco CA 94111 + US + +00-02-4E (hex) Datacard Group +00024E (base 16) Datacard Group + 11111 Bren Road West + Minnetonka MN 55343 + US + +00-02-42 (hex) Videoframe Systems +000242 (base 16) Videoframe Systems + 101 Providence Mine Road + Nevada City CA 95959 + US + +00-02-44 (hex) SURECOM Technology Co. +000244 (base 16) SURECOM Technology Co. + 6F, No. 125, Sec. 2, Datung Rd. + Taiwan Taiwan R.O.C. + TW + +00-02-3E (hex) Selta Telematica S.p.a +00023E (base 16) Selta Telematica S.p.a + Via Nazionale km 404.5 + + IT + +00-02-41 (hex) Amer.com +000241 (base 16) Amer.com + 7259 Bryan Dairy Road + Largo FL 33777 + US + +00-02-07 (hex) VisionGlobal Network Corp. +000207 (base 16) VisionGlobal Network Corp. + 826 E. Stale Road + American Fork UT 84003 + US + +00-02-08 (hex) Unify Networks, Inc. +000208 (base 16) Unify Networks, Inc. + 3160 De La Cruz Blvd. + Santa Clara CA 95054 + US + +00-02-04 (hex) Bodmann Industries Elektronik GmbH +000204 (base 16) Bodmann Industries Elektronik GmbH + Messerschmittring 33 + + DE + +00-02-29 (hex) Adtec Corporation +000229 (base 16) Adtec Corporation + 3F Megurohigashiyama Blg + + JP + +00-02-2D (hex) Agere Systems +00022D (base 16) Agere Systems + P.O. Box 755 + + NL + +00-02-26 (hex) XESystems, Inc. +000226 (base 16) XESystems, Inc. + 317 Main Street + East Rochester NY 14445 + US + +00-02-25 (hex) One Stop Systems +000225 (base 16) One Stop Systems + 2235 Enterprise Street + Escondido CA 92029 + US + +00-02-11 (hex) Nature Worldwide Technology Corp. +000211 (base 16) Nature Worldwide Technology Corp. + No. 1, Min-Chuan Street + Taiwan Taiwan R.O.C. + TW + +00-02-12 (hex) SierraCom +000212 (base 16) SierraCom + 99 South Street + Hopkinton Ma 01748 + US + +00-02-17 (hex) Cisco Systems, Inc +000217 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-01-7A (hex) Chengdu Maipu Electric Industrial Co., Ltd. +00017A (base 16) Chengdu Maipu Electric Industrial Co., Ltd. + NANYI BUILDING, CONSULATE RD., + P.R. + CN + +00-02-38 (hex) Serome Technology, Inc. +000238 (base 16) Serome Technology, Inc. + 555-14, Baekang B/D 7F + Seoul Korea 135-120 + KR + +00-02-69 (hex) Nadatel Co., Ltd +000269 (base 16) Nadatel Co., Ltd + 9F CoWell Bldg, 66-1 Banpo-Dong + KOREA 137-040 + KR + +00-02-64 (hex) AudioRamp.com +000264 (base 16) AudioRamp.com + 15941 Red Hill Suite 205 + Tustin CA 92780 + US + +00-02-55 (hex) IBM Corp +000255 (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-02-52 (hex) Carrier Corporation +000252 (base 16) Carrier Corporation + One Carrier Place + Farmington CT 06034-4015 + US + +00-02-20 (hex) CANON FINETECH INC. +000220 (base 16) CANON FINETECH INC. + 717, Yaguchi, Misato-shi, + Saitama 341-8527 + JP + +00-02-0D (hex) Micronpc.com +00020D (base 16) Micronpc.com + 900 E. Karcher Rd. + Nampa IA 83687 + US + +00-01-D4 (hex) Leisure Time, Inc. +0001D4 (base 16) Leisure Time, Inc. + 4258 Communications Drive + Norcross GA 30093 + US + +00-01-DD (hex) Avail Networks +0001DD (base 16) Avail Networks + 305 E. Eisenhower Parkway + Ann Arbor MI 48108 + US + +00-01-D5 (hex) HAEDONG INFO & COMM CO., LTD +0001D5 (base 16) HAEDONG INFO & COMM CO., LTD + #801 The Corporation Center for Universi + Taejeon Republic of Korea 305 + KR + +00-01-D7 (hex) F5 Networks, Inc. +0001D7 (base 16) F5 Networks, Inc. + 1322 N. Whitman Lane + Liberty Lake WA 99019 + US + +00-01-DE (hex) Trango Systems, Inc. +0001DE (base 16) Trango Systems, Inc. + 9939 V/A Pasar + San Diego CA 92126 + US + +00-01-DC (hex) Activetelco +0001DC (base 16) Activetelco + 43222 Christy Street + Fremont CA 94538 + US + +00-01-F9 (hex) TeraGlobal Communications Corp. +0001F9 (base 16) TeraGlobal Communications Corp. + 9171 Towne Centre Drive + San Diego CA 92122 + US + +00-01-FB (hex) DoTop Technology, Inc. +0001FB (base 16) DoTop Technology, Inc. + 10F, No. 100, Min-Chyuan Road + TAIWAN + TW + +00-01-F8 (hex) TEXIO TECHNOLOGY CORPORATION +0001F8 (base 16) TEXIO TECHNOLOGY CORPORATION + 2-18-13 Shin Yokohama, + 222-0033 + JP + +00-01-BE (hex) Gigalink Co., Ltd. +0001BE (base 16) Gigalink Co., Ltd. + 6th F/L Diplomatic Center 1376-1 + KOREA + KR + +00-01-B1 (hex) General Bandwidth +0001B1 (base 16) General Bandwidth + 12303-B Technology Blvd. + Austin TX 78727 + US + +00-01-BF (hex) Teleforce Co., Ltd. +0001BF (base 16) Teleforce Co., Ltd. + 721 yoshioka-cho kanonji-city + + JP + +00-01-B4 (hex) Wayport, Inc. +0001B4 (base 16) Wayport, Inc. + 1609 Shoal Creek Blvd. + Austin TX 78701 + US + +00-01-BA (hex) IC-Net, Inc. +0001BA (base 16) IC-Net, Inc. + 5 Fl. Seasung Bldg., 311-27 Noryangjin-D + KOREA + KR + +00-01-CF (hex) Alpha Data Parallel Systems, Ltd. +0001CF (base 16) Alpha Data Parallel Systems, Ltd. + 58 Timber Bush + UNITED KINGDOM + GB + +00-01-D0 (hex) VitalPoint, Inc. +0001D0 (base 16) VitalPoint, Inc. + 15770 Hopper Road + Peyton CO 80831 + US + +00-01-B0 (hex) Fulltek Technology Co., Ltd. +0001B0 (base 16) Fulltek Technology Co., Ltd. + 3F No. 8, Lane 130, Min Chuan Rd., Hsint + TAIWAN R.O.C. + TW + +00-01-A9 (hex) BMW AG +0001A9 (base 16) BMW AG + Dept. FG-322 + 80788 Munich + DE + +00-01-AA (hex) Airspan Communications, Ltd. +0001AA (base 16) Airspan Communications, Ltd. + Cambridge House, Oxford Rd., + + GB + +00-01-9E (hex) ESS Technology, Inc. +00019E (base 16) ESS Technology, Inc. + 48401 Fremont Blvd. + Fremont CA 94538 + US + +00-01-7D (hex) ThermoQuest +00017D (base 16) ThermoQuest + 355 River Oaks Parkway + San Jose CA 95134 + US + +00-01-81 (hex) Nortel Networks +000181 (base 16) Nortel Networks + 1100 Technology Park Drive + Billerica MA 01821 + US + +00-01-94 (hex) Capital Equipment Corporation +000194 (base 16) Capital Equipment Corporation + 900 Middlesex Turnpike - Bldg. 2 + Billerica MA 01821 + US + +00-01-98 (hex) Darim Vision +000198 (base 16) Darim Vision + Taejon Expo Venture Town + KOREA + KR + +00-01-E8 (hex) Force10 Networks, Inc. +0001E8 (base 16) Force10 Networks, Inc. + 1440 McCarthy Blvd. + Milpitas CA 95035 + US + +00-01-E9 (hex) Litton Marine Systems B.V. +0001E9 (base 16) Litton Marine Systems B.V. + 118 Burlington Road + ENGLAND KT3 4NR + GB + +00-01-E5 (hex) Supernet, Inc. +0001E5 (base 16) Supernet, Inc. + 135-080 Daemeong Bldg. + KOREA + KR + +00-01-A2 (hex) Logical Co., Ltd. +0001A2 (base 16) Logical Co., Ltd. + 4598 Murakushi-cho + 431-1207 + JP + +00-01-85 (hex) Hitachi Aloka Medical, Ltd. +000185 (base 16) Hitachi Aloka Medical, Ltd. + 3-7-19, Imai Ome-city + 198-8577 + JP + +00-01-C7 (hex) Cisco Systems, Inc +0001C7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-01-21 (hex) WatchGuard Technologies, Inc. +000121 (base 16) WatchGuard Technologies, Inc. + 605 Fifth Ave. S + Seattle WA 98104-3892 + US + +00-01-29 (hex) DFI Inc. +000129 (base 16) DFI Inc. + 100, Huan-Ho Street + Hsi-Chih City Taipei Hsien + TW + +00-01-19 (hex) RTUnet (Australia) +000119 (base 16) RTUnet (Australia) + 8/3-5 Gilda Court + Mulgrave Vic 3170 + AU + +00-01-22 (hex) Trend Communications, Ltd. +000122 (base 16) Trend Communications, Ltd. + Knaves Beech Estate + Bucks, HP10 9QZ + GB + +00-01-1A (hex) Hoffmann und Burmeister GbR +00011A (base 16) Hoffmann und Burmeister GbR + Niederberger Str. 75 + D-53909 Zuelpich + DE + +00-01-0A (hex) CIS TECHNOLOGY INC. +00010A (base 16) CIS TECHNOLOGY INC. + 16F, No. 75 Hsin Tai Wu Road + Taipei Hsien 221 + TW + +00-01-67 (hex) HIOKI E.E. CORPORATION +000167 (base 16) HIOKI E.E. CORPORATION + 81 Koizumi, Ueda, Nagano + 386-1192 386-1192 + JP + +00-01-68 (hex) VITANA CORPORATION +000168 (base 16) VITANA CORPORATION + 2500 Don Reid Drive + K1H 1E1 K1H 1E1 + CA + +00-01-62 (hex) Cygnet Technologies, Inc. +000162 (base 16) Cygnet Technologies, Inc. + 1411 LeMay Drive #301 + Carrollton TX 75007 + US + +00-01-54 (hex) G3M Corporation +000154 (base 16) G3M Corporation + 4320 Stevens Creek Blvd. - Ste. #275 + San Jose CA 95129 + US + +00-01-52 (hex) CHROMATEK INC. +000152 (base 16) CHROMATEK INC. + 6-10, Miyazaki 2-Chome + + JP + +00-01-50 (hex) GILAT COMMUNICATIONS, LTD. +000150 (base 16) GILAT COMMUNICATIONS, LTD. + 21/D Yegia Kapayim Street + + IL + +00-01-51 (hex) Ensemble Communications +000151 (base 16) Ensemble Communications + 6256 Greenman Drive - Ste. #400 + San Diego CA 92122 + US + +00-01-15 (hex) EXTRATECH CORPORATION +000115 (base 16) EXTRATECH CORPORATION + 760 Thornton St., Unit 2 + Post Falls ID 83854 + US + +00-01-01 (hex) Private +000101 (base 16) Private + +00-01-0D (hex) Teledyne DALSA Inc. +00010D (base 16) Teledyne DALSA Inc. + 880 McCaffrey + St-Laurent Quebec H4T 2C7 + CA + +00-01-05 (hex) Beckhoff Automation GmbH +000105 (base 16) Beckhoff Automation GmbH + Eiserstraße 5 + Verl NRW 33415 + DE + +00-B0-17 (hex) InfoGear Technology Corp. +00B017 (base 16) InfoGear Technology Corp. + 2055 Woodside Road + Redwood City CA 94061 + US + +00-01-2C (hex) Aravox Technologies, Inc. +00012C (base 16) Aravox Technologies, Inc. + 16725 40th Place North + Plymouth MN 55446 + US + +00-01-42 (hex) Cisco Systems, Inc +000142 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-01-64 (hex) Cisco Systems, Inc +000164 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-01-5F (hex) DIGITAL DESIGN GmbH +00015F (base 16) DIGITAL DESIGN GmbH + Rauchstr. 21 + Berlin D-10787 + DE + +00-01-2B (hex) TELENET Co., Ltd. +00012B (base 16) TELENET Co., Ltd. + + + + +00-01-3F (hex) Neighbor World Co., Ltd. +00013F (base 16) Neighbor World Co., Ltd. + 114A YERC, 134, Shinchon_dong + 120-749 120-749 KOREA + KR + +00-01-24 (hex) Acer Incorporated +000124 (base 16) Acer Incorporated + 21F, 88, Sec.1 + Taipei Hsien 221 + TW + +00-30-88 (hex) Ericsson +003088 (base 16) Ericsson + 250 Holger Way + SAN JOSE CA 95134 + US + +00-30-20 (hex) TSI, Inc.. +003020 (base 16) TSI, Inc.. + 500 Cardigan Road + Shoreview MN 55126 + US + +00-30-95 (hex) Procomp Informatics, Ltd. +003095 (base 16) Procomp Informatics, Ltd. + 5F, 69-10, Sec. 2, + Tamshui, Taipei, Hsien + TW + +00-30-CA (hex) Discovery Com +0030CA (base 16) Discovery Com + 4935 Century Street + Huntsville AL 35816 + US + +00-30-CE (hex) Zaffire +0030CE (base 16) Zaffire + 2630 Orchard Parkway + San Jose CA 95134-2020 + US + +00-30-7B (hex) Cisco Systems, Inc +00307B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-B5 (hex) Tadiran Microwave Networks +0030B5 (base 16) Tadiran Microwave Networks + 4000 Greenbriar Drive + Stafford TX 77477 + US + +00-30-B8 (hex) RiverDelta Networks +0030B8 (base 16) RiverDelta Networks + Three Highwood Drive East + Tewksbury MA 01876 + US + +00-30-71 (hex) Cisco Systems, Inc +003071 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-3A (hex) MAATEL +00303A (base 16) MAATEL + 495 RUE DE POMMARIN + 38360 VOREPPE + FR + +00-30-4E (hex) BUSTEC PRODUCTION LTD. +00304E (base 16) BUSTEC PRODUCTION LTD. + WORLD AVIATION PARK + Shannon County Clare + IE + +00-30-A4 (hex) Woodwind Communications System +0030A4 (base 16) Woodwind Communications System + 20300 Century Blvd., Suite 200B + Germantown MD 20874 + US + +00-30-3B (hex) PowerCom Technology +00303B (base 16) PowerCom Technology + 2F, No. 34, Industry E. Road IV + Hsinchu 300 + TW + +00-30-BC (hex) Optronic AG +0030BC (base 16) Optronic AG + untereggerstrasse 53 + 9403 Goldach + CH + +00-B0-2D (hex) ViaGate Technologies, Inc. +00B02D (base 16) ViaGate Technologies, Inc. + 745 Route 202/206 + Bridgewater NJ 08807 + US + +00-30-EE (hex) DSG Technology, Inc. +0030EE (base 16) DSG Technology, Inc. + 6F-4 No. 270, Chwig Hsiao + Taipei + TW + +00-30-9E (hex) WORKBIT CORPORATION. +00309E (base 16) WORKBIT CORPORATION. + 1-2-2 Chuou, Yamato + Kanagawa 242-0021 + JP + +00-30-DE (hex) WAGO Kontakttechnik GmbH +0030DE (base 16) WAGO Kontakttechnik GmbH + Hansastrasse 27 + 32423 Minden + DE + +00-30-3E (hex) Radcom Ltd. +00303E (base 16) Radcom Ltd. + 12 Hanechoshet Street + Tel-Aviv 69710 + IL + +00-30-D7 (hex) Innovative Systems, L.L.C. +0030D7 (base 16) Innovative Systems, L.L.C. + 1000 Innovative Drive + Mitchell SD 57301 + US + +00-B0-CE (hex) Viveris Technologies +00B0CE (base 16) Viveris Technologies + 1 rue Traversiere BP 20327 + Rungis Cedex 94598 + FR + +00-B0-1C (hex) Westport Technologies +00B01C (base 16) Westport Technologies + 15 Capella Court, Unit 116 + Nepean Ontario + CA + +00-B0-4A (hex) Cisco Systems, Inc +00B04A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-B0-48 (hex) Marconi Communications Inc. +00B048 (base 16) Marconi Communications Inc. + 8616 Freeport Parkway + Irving TX 75063 + US + +00-30-1B (hex) SHUTTLE, INC. +00301B (base 16) SHUTTLE, INC. + 5F, No. 34, Lane 60 + Taipei + TW + +00-30-21 (hex) HSING TECH. ENTERPRISE CO.,LTD +003021 (base 16) HSING TECH. ENTERPRISE CO.,LTD + 2F, NO. 22, ALLLEY 38, LANE 91 + TAIPEI + TW + +00-30-2C (hex) SYLANTRO SYSTEMS CORPORATION +00302C (base 16) SYLANTRO SYSTEMS CORPORATION + 1686 DELL AVENUE + CAMPBELL CA 95008 + US + +00-30-DF (hex) KB/TEL TELECOMUNICACIONES +0030DF (base 16) KB/TEL TELECOMUNICACIONES + S.A. DE C.V. + Mexico City 14060 + MX + +00-30-30 (hex) HARMONIX CORPORATION +003030 (base 16) HARMONIX CORPORATION + 1755 OSGOOD STREET + NORTH ANDOVER MA 01845 + US + +00-30-63 (hex) SANTERA SYSTEMS, INC. +003063 (base 16) SANTERA SYSTEMS, INC. + 2901 SUMMIT AVENUE - STE. #100 + PLANO TX 75074 + US + +00-30-A3 (hex) Cisco Systems, Inc +0030A3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-DD (hex) INDIGITA CORPORATION +0030DD (base 16) INDIGITA CORPORATION + 30 Corporate Park Drive + Irvine CA 92606 + US + +00-30-99 (hex) BOENIG UND KALLENBACH OHG +003099 (base 16) BOENIG UND KALLENBACH OHG + AM SPOERKEL 100 + + DE + +00-30-F2 (hex) Cisco Systems, Inc +0030F2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-51 (hex) ORBIT AVIONIC & COMMUNICATION +003051 (base 16) ORBIT AVIONIC & COMMUNICATION + SYSTEMS, LTD. + + IL + +00-30-8E (hex) CROSS MATCH TECHNOLOGIES, INC. +00308E (base 16) CROSS MATCH TECHNOLOGIES, INC. + 3960 RCA Blvd., Suite 6001 + Palm Beach FL 33410 + US + +00-30-27 (hex) KERBANGO, INC. +003027 (base 16) KERBANGO, INC. + 21771 STEVENS CREEK BLVD. #100 + CUPERTINO CA 95014 + US + +00-30-33 (hex) ORIENT TELECOM CO., LTD. +003033 (base 16) ORIENT TELECOM CO., LTD. + MISUNG BULDING 115-7 + KOREA + KR + +00-30-08 (hex) AVIO DIGITAL, INC. +003008 (base 16) AVIO DIGITAL, INC. + 957 INDUSTRIAL ROAD + SAN CARLOS CA 94070 + US + +00-30-1D (hex) SKYSTREAM, INC. +00301D (base 16) SKYSTREAM, INC. + 455 DeGuigne Drive + Sunnyvale CA 94086-3835 + US + +00-30-BA (hex) AC&T SYSTEM CO., LTD. +0030BA (base 16) AC&T SYSTEM CO., LTD. + ROOM 702, KEUM-WHA PLAZA + 435-040 SOUTH KOREA + KR + +00-30-FD (hex) INTEGRATED SYSTEMS DESIGN +0030FD (base 16) INTEGRATED SYSTEMS DESIGN + 3650-G CENTRE CIRCLE DRIVE + FORT MILL SC 29715 + US + +00-30-B9 (hex) ECTEL +0030B9 (base 16) ECTEL + 22240 COMSAT DRIVE + CLARKSBURG MD 20871 + US + +00-30-7D (hex) GRE AMERICA, INC. +00307D (base 16) GRE AMERICA, INC. + 425 HARBOR BLVD. + BELMONT CA 94002 + US + +00-30-EF (hex) NEON TECHNOLOGY, INC. +0030EF (base 16) NEON TECHNOLOGY, INC. + 85 WEST MONTAGUE EXPRESSWAY + MILPITAS CA 95035 + US + +00-30-96 (hex) Cisco Systems, Inc +003096 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-39 (hex) SOFTBOOK PRESS +003039 (base 16) SOFTBOOK PRESS + 7745 HERSCHEL AVENUE + LA JOLLA CA 92037 + US + +00-D0-F8 (hex) FUJIAN STAR TERMINAL +00D0F8 (base 16) FUJIAN STAR TERMINAL + DEVICE CO., LTD. + FUZHOU FUJIAN, CHINA 350002 + CN + +00-D0-ED (hex) XIOX +00D0ED (base 16) XIOX + 150 DOW STREET + MANCHESTER NH 03101 + US + +00-D0-97 (hex) Cisco Systems, Inc +00D097 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-8E (hex) Grass Valley, A Belden Brand +00D08E (base 16) Grass Valley, A Belden Brand + 3499, Douglas B. Floreani + Montreal Quebec H4S 2C6 + CA + +00-D0-56 (hex) SOMAT CORPORATION +00D056 (base 16) SOMAT CORPORATION + 702 KILLARNEY STREET + URBANA IL 61801 + US + +00-D0-E0 (hex) DOOIN ELECTRONICS CO. +00D0E0 (base 16) DOOIN ELECTRONICS CO. + DOOIN BLDG. 16-6, SOONAE-DONG + KOREA 463-020 + KR + +00-D0-00 (hex) FERRAN SCIENTIFIC, INC. +00D000 (base 16) FERRAN SCIENTIFIC, INC. + 11558 SORRENTO VALLEY ROAD + SAN DIEGO CA 92121 + US + +00-D0-D0 (hex) ZHONGXING TELECOM LTD. +00D0D0 (base 16) ZHONGXING TELECOM LTD. + 8-9F BUILDING 54,301# + + CN + +00-D0-53 (hex) CONNECTED SYSTEMS +00D053 (base 16) CONNECTED SYSTEMS + 126 W. FIGUEROA STREET + SANTA BARBARA CA 93101 + US + +00-D0-33 (hex) DALIAN DAXIAN NETWORK +00D033 (base 16) DALIAN DAXIAN NETWORK + SYSTEM CO., LTD. + + CN + +00-D0-D6 (hex) AETHRA TELECOMUNICAZIONI +00D0D6 (base 16) AETHRA TELECOMUNICAZIONI + VIA MATTEO RICCI, 10 + + IT + +00-D0-63 (hex) Cisco Systems, Inc +00D063 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-47 (hex) XN TECHNOLOGIES +00D047 (base 16) XN TECHNOLOGIES + P.O. BOX 350 + CHENEY WA 99004 + US + +00-D0-55 (hex) KATHREIN-WERKE KG +00D055 (base 16) KATHREIN-WERKE KG + ANTON-KATHREIN-STRASS 1-3 + + DE + +00-D0-3B (hex) VISION PRODUCTS PTY. LTD. +00D03B (base 16) VISION PRODUCTS PTY. LTD. + SECOND AVENUE, TECHNOLOGY PARK + AUSTRALIA 5095 + AU + +00-D0-B3 (hex) DRS Technologies Canada Ltd +00D0B3 (base 16) DRS Technologies Canada Ltd + 700 Palladium Drive + Ottawa Ontario K2V 1C6 + CA + +00-D0-AF (hex) CUTLER-HAMMER, INC. +00D0AF (base 16) CUTLER-HAMMER, INC. + PMP CENTER + PITTSBURGH PA 15205 + US + +00-D0-52 (hex) ASCEND COMMUNICATIONS, INC. +00D052 (base 16) ASCEND COMMUNICATIONS, INC. + 1701 HARBOR BAY PARKWAY + ALAMEDA CA 94502 + US + +00-D0-AD (hex) TL INDUSTRIES +00D0AD (base 16) TL INDUSTRIES + 2541 TRACY ROAD + NORTHWOOD OH 43619 + US + +00-D0-A4 (hex) ALANTRO COMMUNICATIONS +00D0A4 (base 16) ALANTRO COMMUNICATIONS + 141 STONY CIRCLE, STE. #210 + SANTAROSA CA 95401 + US + +00-D0-B0 (hex) BITSWITCH LTD. +00D0B0 (base 16) BITSWITCH LTD. + 3 MEADOW COURT, AMOS ROAD + UNITED KINGDOM + GB + +00-D0-30 (hex) Safetran Systems Corp +00D030 (base 16) Safetran Systems Corp + 10655 7th Street + Rancho Cucamonga CA 91730 + US + +00-30-2A (hex) SOUTHERN INFORMATION +00302A (base 16) SOUTHERN INFORMATION + SYSTEM, INC. + HSINCHU TAIWAN, R.O.C. + TW + +00-30-E1 (hex) Network Equipment Technologies, Inc. +0030E1 (base 16) Network Equipment Technologies, Inc. + 6900 Paseo Padre Parkway + Fremont CA 94555 + US + +00-30-2B (hex) INALP NETWORKS, INC. +00302B (base 16) INALP NETWORKS, INC. + MERIEDWEG 7 + + CH + +00-30-01 (hex) SMP +003001 (base 16) SMP + 22, RUE DES COSMONAUTES + + FR + +00-D0-8B (hex) ADVA Optical Networking Ltd. +00D08B (base 16) ADVA Optical Networking Ltd. + ADVAntage House + York YO30 4RY + GB + +00-D0-E4 (hex) Cisco Systems, Inc +00D0E4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-5A (hex) SYMBIONICS, LTD. +00D05A (base 16) SYMBIONICS, LTD. + ST. JOHN'S INNOVATION PARK + ENGLAND + GB + +00-D0-79 (hex) Cisco Systems, Inc +00D079 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-21 (hex) REGENT ELECTRONICS CORP. +00D021 (base 16) REGENT ELECTRONICS CORP. + 200 CENTENNIAL AVE.-STE. #201 + PISCATAWAY NJ 08854 + US + +00-D0-9F (hex) NOVTEK TEST SYSTEMS +00D09F (base 16) NOVTEK TEST SYSTEMS + 2170 PARAGON DRIVE + SAN JOSE CA 95131 + US + +00-D0-FE (hex) ASTRAL POINT +00D0FE (base 16) ASTRAL POINT + COMMUNICATIONS, INC. + CHELMSFORD MA 01824 + US + +00-D0-D4 (hex) V-BITS, INC. +00D0D4 (base 16) V-BITS, INC. + 2150 TRADE ZONE BLVD. + SAN JOSE CA 95131 + US + +00-D0-84 (hex) NEXCOMM SYSTEMS, INC. +00D084 (base 16) NEXCOMM SYSTEMS, INC. + SUIT #NAL-903, + SUNGNAM-CITY SUNGNAM-CITY KYUNGGI-DO,K + KR + +00-D0-99 (hex) Elcard Wireless Systems Oy +00D099 (base 16) Elcard Wireless Systems Oy + P.O. BOX 120/BECKERINTIC 38 + + FI + +00-D0-E7 (hex) VCON TELECOMMUNICATION LTD. +00D0E7 (base 16) VCON TELECOMMUNICATION LTD. + 22 MASKIT STREET + + IL + +00-D0-1B (hex) MIMAKI ENGINEERING CO., LTD. +00D01B (base 16) MIMAKI ENGINEERING CO., LTD. + 5-9-41 KITA SHINAGAWA + + JP + +00-D0-0D (hex) MICROMERITICS INSTRUMENT +00D00D (base 16) MICROMERITICS INSTRUMENT + CORPORATION + NORCROSS GA 30093-1877 + US + +00-D0-54 (hex) SAS INSTITUTE INC. +00D054 (base 16) SAS INSTITUTE INC. + SAS CAMPUS DRIVE, R4 + CARY NC 27511 + US + +00-D0-09 (hex) HSING TECH. ENTERPRISE CO. LTD +00D009 (base 16) HSING TECH. ENTERPRISE CO. LTD + NO.2, LANE 128, SEC. 2 + TAIWAN TAIWAN R.O.C. + TW + +00-D0-F4 (hex) CARINTHIAN TECH INSTITUTE +00D0F4 (base 16) CARINTHIAN TECH INSTITUTE + RICHARD-WAGNER STR. 19 + + AT + +00-D0-7D (hex) COSINE COMMUNICATIONS +00D07D (base 16) COSINE COMMUNICATIONS + 1200 BRIDGE PARKWAY + REDWOOD CITY CA 94065 + US + +00-D0-83 (hex) INVERTEX, INC. +00D083 (base 16) INVERTEX, INC. + 1012 MORSE AVENUE- STE.#9 + SUNNYVALE CA 94089 + US + +00-D0-BA (hex) Cisco Systems, Inc +00D0BA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-98 (hex) Photon Dynamics Canada Inc. +00D098 (base 16) Photon Dynamics Canada Inc. + 221 Whitehall Drive + L3R 9T1 + CA + +00-D0-BE (hex) EMUTEC INC. +00D0BE (base 16) EMUTEC INC. + P.O. BOX 3035 + EVERETT WA 98203 + US + +00-D0-92 (hex) GLENAYRE WESTERN MULTIPLEX +00D092 (base 16) GLENAYRE WESTERN MULTIPLEX + 1196 BORREGAS AVENUE + SUNNYVALE CA 94089 + US + +00-50-9D (hex) THE INDUSTREE B.V. +00509D (base 16) THE INDUSTREE B.V. + P.O. BOX 462 + THE + NL + +00-D0-B8 (hex) Iomega Corporation +00D0B8 (base 16) Iomega Corporation + 1821 West 4000 South + Roy UT 84067 + US + +00-50-F1 (hex) Intel Corporation +0050F1 (base 16) Intel Corporation + 94 Em-Hamoshavot Way. + Petach-Tikva + IL + +00-50-CB (hex) JETTER +0050CB (base 16) JETTER + GRAETERSTRASSE 2 + + DE + +00-50-58 (hex) Sangoma Technologies +005058 (base 16) Sangoma Technologies + 100 Renfrew Drive, Suite 100 + Markham ON L3R 9R6 + CA + +00-50-74 (hex) ADVANCED HI-TECH CORP. +005074 (base 16) ADVANCED HI-TECH CORP. + 1990 EAST GRAND AVE. + EL SEGUNDO CA 90505 + US + +00-50-0A (hex) IRIS TECHNOLOGIES, INC. +00500A (base 16) IRIS TECHNOLOGIES, INC. + WESTMORELAND INDUSRIAL PARK + GREENSBURG PA 15601 + US + +00-50-6D (hex) VIDEOJET SYSTEMS +00506D (base 16) VIDEOJET SYSTEMS + INTERNATIONAL INC. + WOODDALE IL 60091-1073 + US + +00-50-CA (hex) NET TO NET TECHNOLOGIES +0050CA (base 16) NET TO NET TECHNOLOGIES + 680 CENTRAL AVENUE - STE. #301 + DOVER NH 03820 + US + +00-D0-C7 (hex) PATHWAY, INC. +00D0C7 (base 16) PATHWAY, INC. + 777 BETA DRIVE + MAYFIELD VILLAGE OH 44143 + US + +00-D0-7A (hex) AMAQUEST COMPUTER CORP. +00D07A (base 16) AMAQUEST COMPUTER CORP. + 8/F, 79 HSIN-TAI + TAIWAN R.O.C. + TW + +00-50-3F (hex) ANCHOR GAMES +00503F (base 16) ANCHOR GAMES + 815 PILOT ROAD - STE + LAS VEGAS NV 89119 + US + +00-50-32 (hex) PICAZO COMMUNICATIONS, INC. +005032 (base 16) PICAZO COMMUNICATIONS, INC. + 61 DAGGETT DRIVE + SAN JOSE CA 95134 + US + +00-D0-4A (hex) PRESENCE TECHNOLOGY GMBH +00D04A (base 16) PRESENCE TECHNOLOGY GMBH + + CO. KG + + DE + +00-D0-74 (hex) TAQUA SYSTEMS, INC. +00D074 (base 16) TAQUA SYSTEMS, INC. + 1600 FALMOUTH RD. - STE + CENTERVILLE MA 02632 + US + +00-50-4D (hex) Tokyo Electron Device Limited +00504D (base 16) Tokyo Electron Device Limited + 1, Higashikata-machi, Tsuzuki-ku, + Yokohama-shi Kanagawa-ken + JP + +00-50-70 (hex) CHAINTECH COMPUTER CO., LTD. +005070 (base 16) CHAINTECH COMPUTER CO., LTD. + 5TH F, ALLEY 2, LANE 222 + TAIWAN R.O.C. + TW + +00-50-23 (hex) PG DESIGN ELECTRONICS, INC. +005023 (base 16) PG DESIGN ELECTRONICS, INC. + 48700 STRUCTURAL DRIVE + CHESTERFIELD MI 48051 + US + +00-50-9E (hex) Les Technologies SoftAcoustik Inc. +00509E (base 16) Les Technologies SoftAcoustik Inc. + + Quebec G1K 3P6 + CA + +00-50-71 (hex) AIWA CO., LTD. +005071 (base 16) AIWA CO., LTD. + 1-11, KAMITOMATSURI 4-CHOME + UTSUNOMIYA-SHI, TOCHIGI-KEN 320-85 + JP + +00-50-5F (hex) BRAND INNOVATORS +00505F (base 16) BRAND INNOVATORS + Steenovenweg 5 + Helmond 5708 HN + NL + +00-50-B4 (hex) SATCHWELL CONTROL SYSTEMS, LTD +0050B4 (base 16) SATCHWELL CONTROL SYSTEMS, LTD + P.O. BOX 57, 94 FARNHAM ROAD + BERKSHIRE SL1 4UH + GB + +00-50-D6 (hex) ATLAS COPCO TOOLS AB +0050D6 (base 16) ATLAS COPCO TOOLS AB + + S-105 23 STOCKHOLM + SE + +00-50-82 (hex) FORESSON CORPORATION +005082 (base 16) FORESSON CORPORATION + 3F, NO.9 SEC.1 + TAIPEI 10404 + TW + +00-50-DF (hex) AirFiber, Inc. +0050DF (base 16) AirFiber, Inc. + P.O. BOX 502148 + SAN DIEGO CA 92150-2148 + US + +00-50-C5 (hex) ADS Technologies, Inc +0050C5 (base 16) ADS Technologies, Inc + 12627 Hiddencreek Way + Cerritos CA 90703 + US + +00-50-8E (hex) OPTIMATION, INC. +00508E (base 16) OPTIMATION, INC. + P.O. BOX 14357 + HUNTSVILLE AL 35815 + US + +00-50-28 (hex) AVAL COMMUNICATIONS +005028 (base 16) AVAL COMMUNICATIONS + 1777 NORTH CALIFORNIA BLVD. + WALNUT CREEK CA 94596 + US + +00-50-2F (hex) TollBridge Technologies, Inc. +00502F (base 16) TollBridge Technologies, Inc. + 872 HERMOSA DRIVE + SUNNYVALE CA 94086 + US + +00-50-FE (hex) PCTVnet ASA +0050FE (base 16) PCTVnet ASA + STRANDVEILEN 50 + N-1324 LYSAKER + NO + +00-50-AB (hex) NALTEC, Inc. +0050AB (base 16) NALTEC, Inc. + 1-1-15, Nakanogo, Shimizu-ku + Shizuoka-shi Shizuoka 424-0888 + JP + +00-50-37 (hex) KOGA ELECTRONICS CO. +005037 (base 16) KOGA ELECTRONICS CO. + 5-8-10, TEHARA, RITTO-CHO + SHIGA, 420-3047 + JP + +00-50-A8 (hex) OpenCon Systems, Inc. +0050A8 (base 16) OpenCon Systems, Inc. + 377 HOES LANE + PISCATAWAY NJ 08854 + US + +00-50-9C (hex) BETA RESEARCH +00509C (base 16) BETA RESEARCH + BETASTR. 1 + 85774 UNTERFOEHRING + DE + +00-50-B1 (hex) GIDDINGS & LEWIS +0050B1 (base 16) GIDDINGS & LEWIS + 660 S. MILITARY RD. + FOND DU LAC WI 54935 + US + +00-50-06 (hex) TAC AB +005006 (base 16) TAC AB + JAGERSHILLGATON 18 + 21375 MALMO + SE + +00-50-09 (hex) PHILIPS BROADBAND NETWORKS +005009 (base 16) PHILIPS BROADBAND NETWORKS + 64 PERIMETER CENTRE EAST + ATLANTA GA 30346 + US + +00-50-30 (hex) FUTURE PLUS SYSTEMS +005030 (base 16) FUTURE PLUS SYSTEMS + 36 OLDE ENGLISH RD. + BEDFORD NH 03110 + US + +00-50-78 (hex) MEGATON HOUSE, LTD. +005078 (base 16) MEGATON HOUSE, LTD. + ZIP: 224 NO.1-3-5 NAKAMACHIBAI + YOKOHAMA + JP + +00-50-02 (hex) OMNISEC AG +005002 (base 16) OMNISEC AG + RIETSTRASSE 14 + CH-8108 DAELLIKON + CH + +00-50-6A (hex) EDEVA, INC. +00506A (base 16) EDEVA, INC. + 298 S. SUNNYVALE AVE. - #208 + SUNNYVALE CA 94086 + US + +00-50-AA (hex) KONICA MINOLTA HOLDINGS, INC. +0050AA (base 16) KONICA MINOLTA HOLDINGS, INC. + 1-6-1, Marunouchi, + Tokyo 100-0005 + JP + +00-50-38 (hex) DAIN TELECOM CO., LTD. +005038 (base 16) DAIN TELECOM CO., LTD. + 2ND Flr., OH-SUNG BLDG. #2-28 + YANGJAE-DONG, SEOCHO-GU SEOUL + KR + +00-50-B7 (hex) BOSER TECHNOLOGY CO., LTD. +0050B7 (base 16) BOSER TECHNOLOGY CO., LTD. + 15F-6, 77 HSIN TAI WU ROAD + TAIPEI HSIEN + TW + +00-90-88 (hex) BAXALL SECURITY LTD. +009088 (base 16) BAXALL SECURITY LTD. + UNIT 1 CASTLEHILL + STOCKPORT Great Britain SK6 2SV + GB + +00-90-6C (hex) Sartorius Hamburg GmbH +00906C (base 16) Sartorius Hamburg GmbH + Meiendorferstraße 205 + Hamburg D-22145 + DE + +00-90-A4 (hex) ALTIGA NETWORKS +0090A4 (base 16) ALTIGA NETWORKS + 124 GROVE STREET + FRANKLIN MA 02038-3206 + US + +00-90-F9 (hex) Imagine Communications +0090F9 (base 16) Imagine Communications + 3001 Dallas Parkway, Suite 300 + Frisco TX 75034 + US + +00-90-89 (hex) SOFTCOM MICROSYSTEMS, INC. +009089 (base 16) SOFTCOM MICROSYSTEMS, INC. + 47509 SEABRIDGE DRIVE + FREMONT CA 94538 + US + +00-90-EE (hex) PERSONAL COMMUNICATIONS TECHNOLOGIES +0090EE (base 16) PERSONAL COMMUNICATIONS TECHNOLOGIES + 50 STILES ROAD + SALEM NH 03079 + US + +00-90-80 (hex) NOT LIMITED, INC. +009080 (base 16) NOT LIMITED, INC. + 500 ALLERTON STREET, STE #102 + REDWOOD CITY CA 94063 + US + +00-90-E8 (hex) MOXA TECHNOLOGIES CORP., LTD. +0090E8 (base 16) MOXA TECHNOLOGIES CORP., LTD. + 7F, NO. 2, ALY6, LN 235 + SHIENG-TIEN CITY TAIPEI + TW + +00-90-A1 (hex) Flying Pig Systems/High End Systems Inc. +0090A1 (base 16) Flying Pig Systems/High End Systems Inc. + 2105 Gracy Farms Lane + Austin TX 78758 + US + +00-90-79 (hex) ClearOne, Inc. +009079 (base 16) ClearOne, Inc. + 299 WASHINGTON STREET + WOBURN MA 01801 + US + +00-90-9A (hex) ONE WORLD SYSTEMS, INC. +00909A (base 16) ONE WORLD SYSTEMS, INC. + 1144 EAST ARQUES AVENUE + SUNNYVALE CA 94086 + US + +00-90-C2 (hex) JK microsystems, Inc. +0090C2 (base 16) JK microsystems, Inc. + 1275 YUBA AVENUE + SAN PABLO CA 94806 + US + +00-50-D0 (hex) MINERVA SYSTEMS +0050D0 (base 16) MINERVA SYSTEMS + 1585 CHARLESTON ROAD + MOUNTAIN VIEW CA 84943 + US + +00-50-D8 (hex) UNICORN COMPUTER CORP. +0050D8 (base 16) UNICORN COMPUTER CORP. + 7 FL., NO. 96 KWANG FU NORTH ROAD + TAIPEI + TW + +00-50-B2 (hex) BRODEL GmbH +0050B2 (base 16) BRODEL GmbH + Distelbusch 24 + Velbert NRW 42549 + DE + +00-90-76 (hex) FMT AIRCRAFT GATE SUPPORT SYSTEMS AB +009076 (base 16) FMT AIRCRAFT GATE SUPPORT SYSTEMS AB + + SE-231 32 TRELLEBORG + SE + +00-90-17 (hex) Zypcom, Inc +009017 (base 16) Zypcom, Inc + 28400 Kohoutek Way + Union City CA 94587-1212 + US + +00-90-49 (hex) ENTRIDIA CORPORATION +009049 (base 16) ENTRIDIA CORPORATION + 101 PARK CENTER PLAZA + SAN JOSE CA 95113-2218 + US + +00-90-E6 (hex) ALi Corporation +0090E6 (base 16) ALi Corporation + 6F, 246 NeiHu Road, Sec. 1 + Taipei 114 + TW + +00-90-70 (hex) NEO NETWORKS, INC. +009070 (base 16) NEO NETWORKS, INC. + 10300 BREN ROAD EAST + MINNETONKA MN 55343 + US + +00-90-30 (hex) HONEYWELL-DATING +009030 (base 16) HONEYWELL-DATING + VIA TINTORETTO, 15 + 21012 CASSANO MAGNAGO (VA) + IT + +00-90-08 (hex) HanA Systems Inc. +009008 (base 16) HanA Systems Inc. + EAHO B/D 740-1 + SEOUL + KR + +00-90-AC (hex) OPTIVISION, INC. +0090AC (base 16) OPTIVISION, INC. + 3450 HILLVIEW AVENUE + PALO ALTO CA 94304 + US + +00-90-4E (hex) DELEM BV +00904E (base 16) DELEM BV + LUCHTHAVEN WEG 42 + 5657 EB EINDHOVEN + NL + +00-90-ED (hex) CENTRAL SYSTEM RESEARCH CO., LTD. +0090ED (base 16) CENTRAL SYSTEM RESEARCH CO., LTD. + 4-13-2 HIYOSHICHO + KOKUBUNJI-CITY TOKYO 18500032 + JP + +00-90-1E (hex) Selesta Ingegneria S.p.A. +00901E (base 16) Selesta Ingegneria S.p.A. + via di Francia, 28 + Genova 16149 + IT + +00-90-75 (hex) NEC DO BRASIL S.A. +009075 (base 16) NEC DO BRASIL S.A. + RODOVIA PRESIDENTE DUTRA, KM 218 + São Paulo-SP CEP - 07210-902 + BR + +00-90-AD (hex) ASPECT ELECTRONICS, INC. +0090AD (base 16) ASPECT ELECTRONICS, INC. + 12740 EARHART AVE. + AUBURN CA 95602 + US + +00-90-01 (hex) NISHIMU ELECTRONICS INDUSTRIES CO., LTD. +009001 (base 16) NISHIMU ELECTRONICS INDUSTRIES CO., LTD. + 700 TATENO MITAGAWA-CHO + KANZAKI-GUN SAGA PREF. + JP + +00-90-43 (hex) Tattile SRL +009043 (base 16) Tattile SRL + 1-13-10 SHIROGANE CHUO-KU + FUKUOKA-CITY + JP + +00-90-CB (hex) Wireless OnLine, Inc. +0090CB (base 16) Wireless OnLine, Inc. + 4410 EL CAMINO REAL, STE #101 + LOS ALTOS CA 94022 + US + +00-10-63 (hex) STARGUIDE DIGITAL NETWORKS +001063 (base 16) STARGUIDE DIGITAL NETWORKS + 5754 PACIFIC CENTER BLVD. + SAN DIEGO CA 92121 + US + +00-10-23 (hex) Network Equipment Technologies +001023 (base 16) Network Equipment Technologies + 6900 Paseo Padre Parkway + Freemont CA 94555-3660 + US + +00-10-2B (hex) UMAX DATA SYSTEMS, INC. +00102B (base 16) UMAX DATA SYSTEMS, INC. + NO. 1-1, R&D ROAD 2 + HSINCHU + TW + +00-90-8A (hex) BAYLY COMMUNICATIONS, INC. +00908A (base 16) BAYLY COMMUNICATIONS, INC. + 105 GREEN COURT + AJAX Ontario L1S 6W9 + CA + +00-90-0E (hex) HANDLINK TECHNOLOGIES, INC. +00900E (base 16) HANDLINK TECHNOLOGIES, INC. + 5F, 24-2, Industry E. Road IV, + Hsinchu 30077 + TW + +00-90-C1 (hex) Peco II, Inc. +0090C1 (base 16) Peco II, Inc. + 7060 Huntley Road + Columbus OH 43229 + US + +00-10-8D (hex) Johnson Controls, Inc. +00108D (base 16) Johnson Controls, Inc. + 507 E. Michigan St. + Milwaukee WI 53201 + US + +00-10-45 (hex) Nortel Networks +001045 (base 16) Nortel Networks + OPTera Solutions Division + Kanata Ontario K2K-2X3 + CA + +00-10-7D (hex) AURORA COMMUNICATIONS, LTD. +00107D (base 16) AURORA COMMUNICATIONS, LTD. + P.O. BOX 1942 + NSW 2113 + AU + +00-90-E4 (hex) NEC AMERICA, INC. +0090E4 (base 16) NEC AMERICA, INC. + 3100 N.E. SHUTE ROAD + HILLSBORO OR 97124 + US + +00-90-40 (hex) Siemens Network Convergence LLC +009040 (base 16) Siemens Network Convergence LLC + Ten Technology Park Drive + Westford MA 01886-3146 + US + +00-90-C8 (hex) WAVERIDER COMMUNICATIONS (CANADA) INC. +0090C8 (base 16) WAVERIDER COMMUNICATIONS (CANADA) INC. + + British Columbia V1E 4R9 + CA + +00-90-1B (hex) DIGITAL CONTROLS +00901B (base 16) DIGITAL CONTROLS + 305 PIONEER BLVD. + SPRINGBORO OH 45066-1100 + US + +00-90-F7 (hex) NBASE COMMUNICATIONS LTD. +0090F7 (base 16) NBASE COMMUNICATIONS LTD. + INDUSTRIAL PARK + + IL + +00-90-12 (hex) GLOBESPAN SEMICONDUCTOR, INC. +009012 (base 16) GLOBESPAN SEMICONDUCTOR, INC. + 100 SCHULZ DRIVE + RED BANK NJ 07701 + US + +00-90-B7 (hex) DIGITAL LIGHTWAVE, INC. +0090B7 (base 16) DIGITAL LIGHTWAVE, INC. + 601 CLEVELAND STREET- 5TH FL. + CLEARWATER FL 33755 + US + +00-90-A0 (hex) 8X8 INC. +0090A0 (base 16) 8X8 INC. + 2445 MISSION COLLEGE BLVD. + SANTA CLARA CA 95054 + US + +00-90-47 (hex) GIGA FAST E. LTD. +009047 (base 16) GIGA FAST E. LTD. + 14F, NO.112, SEC. 1 + Hsi-Chih Taipei Hsien + TW + +00-90-E1 (hex) TELENA S.P.A. +0090E1 (base 16) TELENA S.P.A. + VIA SAVONA, 146 + 20144 MILANO + IT + +00-90-32 (hex) PELCOMBE GROUP LTD. +009032 (base 16) PELCOMBE GROUP LTD. + MAIN ROAD + ESSEX C012 4LP + GB + +00-10-62 (hex) NX SERVER, ILNC. +001062 (base 16) NX SERVER, ILNC. + 5401 E. LA PALMA AVE. + ANAHEIM CA 92807 + US + +00-10-F0 (hex) RITTAL-WERK RUDOLF LOH GmbH & Co. +0010F0 (base 16) RITTAL-WERK RUDOLF LOH GmbH & Co. + AUF DEM STUTZELBERG + D-35745 HERBORN + DE + +00-10-01 (hex) Citel +001001 (base 16) Citel + Loughborough Innovation Centre + Loughborough LE11 3EH + GB + +00-10-5C (hex) QUANTUM DESIGNS (H.K.) LTD. +00105C (base 16) QUANTUM DESIGNS (H.K.) LTD. + 5/F., SOMERSET HOUSE, TAIKOO PLACE + QUARRY BAY + HK + +00-10-CF (hex) FIBERLANE COMMUNICATIONS +0010CF (base 16) FIBERLANE COMMUNICATIONS + 1318 REDWOOD WAY, #200 + PETALUMA CA 94954 + US + +00-10-69 (hex) HELIOSS COMMUNICATIONS, INC. +001069 (base 16) HELIOSS COMMUNICATIONS, INC. + 391 TOTTEM POND RD.- STE#303 + WALTHAM MA 02154 + US + +00-10-BF (hex) InterAir Wireless +0010BF (base 16) InterAir Wireless + 485 CAYUGA ROAD + BUFFALO NY 14225-0222 + US + +00-10-26 (hex) ACCELERATED NETWORKS, INC. +001026 (base 16) ACCELERATED NETWORKS, INC. + 31238 VIA COLINAS, UNIT + WESTLAKE VILLAGE CA 91362 + US + +00-10-36 (hex) INTER-TEL INTEGRATED SYSTEMS +001036 (base 16) INTER-TEL INTEGRATED SYSTEMS + 7300 W. BOSTON STREET + CHANDLER AZ 85226 + US + +00-10-39 (hex) Vectron Systems AG +001039 (base 16) Vectron Systems AG + Willy-Brandt-Weg 41 + 48155 Muenster + DE + +00-10-B6 (hex) ENTRATA COMMUNICATIONS CORP. +0010B6 (base 16) ENTRATA COMMUNICATIONS CORP. + 574 HERITAGE RD. + SOUTHBURY CT 06488 + US + +00-10-EC (hex) RPCG, LLC +0010EC (base 16) RPCG, LLC + 749 MINER ROAD + HIGHLAND HTS OH 44143-2117 + US + +00-10-59 (hex) DIABLO RESEARCH CO. LLC +001059 (base 16) DIABLO RESEARCH CO. LLC + 825 STEWART DRIVE + SUNNYVALE CA 94086 + US + +00-10-FC (hex) BROADBAND NETWORKS, INC. +0010FC (base 16) BROADBAND NETWORKS, INC. + 37 STEVENSON ROAD + WINNIPEG, MANITOBA R3H 0H9 + CA + +00-10-31 (hex) OBJECTIVE COMMUNICATIONS, INC. +001031 (base 16) OBJECTIVE COMMUNICATIONS, INC. + 75 ROCHESTER AVE. + PORTSMOUTH NH 03801 + US + +00-10-6D (hex) Axxcelera Broadband Wireless +00106D (base 16) Axxcelera Broadband Wireless + 1600 East Parham Road + Richmond VA 23228 + US + +00-10-4C (hex) Teledyne LeCroy, Inc +00104C (base 16) Teledyne LeCroy, Inc + 3385 Scott Blvd. + Santa Clara CA 95054 + US + +00-10-CC (hex) CLP COMPUTER LOGISTIK PLANUNG GmbH +0010CC (base 16) CLP COMPUTER LOGISTIK PLANUNG GmbH + BASSERMANNSTR. 21 + D-81245 MUENCHEN + DE + +00-10-30 (hex) EION Inc. +001030 (base 16) EION Inc. + 320 March Road + Ottawa ON K2K 2E3 + CA + +00-10-D0 (hex) WITCOM, LTD. +0010D0 (base 16) WITCOM, LTD. + P.O.B. 2250 + HAIFA 31021 + IL + +00-10-93 (hex) CMS COMPUTERS, LTD. +001093 (base 16) CMS COMPUTERS, LTD. + 201 ARCADIA + MUMBAI 400 0021 + IN + +00-10-8F (hex) RAPTOR SYSTEMS +00108F (base 16) RAPTOR SYSTEMS + 69 HICKORY AVE. + WALTHAM MA 02154 + US + +00-10-A4 (hex) XIRCOM +0010A4 (base 16) XIRCOM + 2300 CORPORATE CENTER DR. + THOUSAND OAKS CA 91320 + US + +00-10-F1 (hex) I-O CORPORATION +0010F1 (base 16) I-O CORPORATION + 2256 SOUTH 3600 WEST + SALT LAKE CITY UT 84119 + US + +00-10-66 (hex) ADVANCED CONTROL SYSTEMS, INC. +001066 (base 16) ADVANCED CONTROL SYSTEMS, INC. + 2755 NORTHWOODS PARKWAY + NORCROSS GA 30071 + US + +00-10-AC (hex) IMCI TECHNOLOGIES +0010AC (base 16) IMCI TECHNOLOGIES + 8401 OLD COURT HKOUSE RD + VIENNA VA 22182 + US + +00-10-B1 (hex) FOR-A CO., LTD. +0010B1 (base 16) FOR-A CO., LTD. + 2-3-3 OOSAKU + CHIBA PREF. 285 + JP + +00-10-EE (hex) CTI PRODUCTS, INC. +0010EE (base 16) CTI PRODUCTS, INC. + 1211 W. SHARON RD. + CINCINNATI OH 45240 + US + +00-10-41 (hex) BRISTOL BABCOCK, INC. +001041 (base 16) BRISTOL BABCOCK, INC. + 1100 BUCKINGHAM STREET + WATERTOWN CT 06795 + US + +00-10-AA (hex) MEDIA4, INC. +0010AA (base 16) MEDIA4, INC. + 250 14TH ST. NW - STE #4002 + ATLANTA GA 30318 + US + +00-10-E8 (hex) TELOCITY, INCORPORATED +0010E8 (base 16) TELOCITY, INCORPORATED + 992 SOUTH DE ANZA BLVD + SAN JOSE CA 95129 + US + +00-10-A2 (hex) TNS +0010A2 (base 16) TNS + 800 Third Street, Suite B100 + HERNDON VA 20170 + US + +00-10-65 (hex) RADYNE CORPORATION +001065 (base 16) RADYNE CORPORATION + 5225 S. 37TH STREET + PHOENIX AZ 85040 + US + +00-10-9F (hex) PAVO, INC. +00109F (base 16) PAVO, INC. + 95 YESLER WAY + SEATTLE WA 98104 + US + +00-10-1D (hex) WINBOND ELECTRONICS CORP. +00101D (base 16) WINBOND ELECTRONICS CORP. + NO. 4, CREATION RD. III + HSIN CHU + TW + +00-10-84 (hex) K-BOT COMMUNICATIONS +001084 (base 16) K-BOT COMMUNICATIONS + P.O. BOX 410 + NORTON MA 02766 + US + +00-10-00 (hex) CABLE TELEVISION LABORATORIES, INC. +001000 (base 16) CABLE TELEVISION LABORATORIES, INC. + 858 Coal Creek Circle + Louisville CO 80027 + US + +00-10-09 (hex) HORANET +001009 (base 16) HORANET + ZI Route de Niort – BP 70328 + FONTENAY LE COMTE CEDEX VENDEE 85206 + FR + +00-10-F8 (hex) TEXIO TECHNOLOGY CORPORATION +0010F8 (base 16) TEXIO TECHNOLOGY CORPORATION + 2-18-13 Shin Yokohama, + 222-0033 + JP + +00-10-C0 (hex) ARMA, Inc. +0010C0 (base 16) ARMA, Inc. + 4851 Northshore Lane + North Little Rock AR 72118 + US + +00-10-5B (hex) NET INSIGHT AB +00105B (base 16) NET INSIGHT AB + Västberga Allé 9 + SE-1260 30 Hägersten + SE + +00-10-02 (hex) ACTIA +001002 (base 16) ACTIA + 25 CHEMIN DE POUVOURVILLE + 31432 TOULOUSE, CEDEX 04 + FR + +00-10-EB (hex) SELSIUS SYSTEMS, INC. +0010EB (base 16) SELSIUS SYSTEMS, INC. + 5057 KELLER SPRINGS RD. + DALLAS TX 75248 + US + +00-10-57 (hex) Rebel.com, Inc. +001057 (base 16) Rebel.com, Inc. + 150 ISABELLA STREET--STE. 1000 + OTTAWA, ONTARIO K1S 1V7 + CA + +00-10-F9 (hex) UNIQUE SYSTEMS, INC. +0010F9 (base 16) UNIQUE SYSTEMS, INC. + 181 DON PARK RD + MARKHAM, ONTARIO L3R 1C2 + CA + +00-10-75 (hex) Segate Technology LLC +001075 (base 16) Segate Technology LLC + 10200 S De Anza Blvd + Cupertino CA 95014 + US + +00-E0-03 (hex) NOKIA WIRELESS BUSINESS COMMUN +00E003 (base 16) NOKIA WIRELESS BUSINESS COMMUN + ACCESS POINT PRODUCTS GROUP + CB4 0WS + GB + +00-E0-F3 (hex) WebSprint Communications, Inc. +00E0F3 (base 16) WebSprint Communications, Inc. + 3026 SCOTT BLVD. + SANTA CLARA CA 95054 + US + +08-BB-CC (hex) AK-NORD EDV VERTRIEBSGES. mbH +08BBCC (base 16) AK-NORD EDV VERTRIEBSGES. mbH + FRIEDRICHSTRASSE 10 + 25436 TORNESCH + DE + +00-E0-DB (hex) ViaVideo Communications, Inc. +00E0DB (base 16) ViaVideo Communications, Inc. + 8900 SHOAL CREEK BLVD. + AUSTIN TX 78757 + US + +00-E0-A6 (hex) TELOGY NETWORKS, INC. +00E0A6 (base 16) TELOGY NETWORKS, INC. + 20250 CENTURY BLVD. + GERMANTOWN MD 20874 + US + +00-E0-9F (hex) PIXEL VISION +00E09F (base 16) PIXEL VISION + 43 NAGOG PARK + ACTON MA 01720 + US + +00-E0-CC (hex) HERO SYSTEMS, LTD. +00E0CC (base 16) HERO SYSTEMS, LTD. + THE BARNES, COOMBELANDS LANE, + SURREY KT15 1HY ENGLAND + GB + +00-E0-80 (hex) CONTROL RESOURCES CORPORATION +00E080 (base 16) CONTROL RESOURCES CORPORATION + 16-00 POLLITT DRIVE + FAIR LAWN NJ 07410 + US + +00-E0-04 (hex) PMC-SIERRA, INC. +00E004 (base 16) PMC-SIERRA, INC. + 105-8555 BAXTER PLACE + BURNABY, BC V5A 4V7 + CA + +00-E0-3B (hex) PROMINET CORPORATION +00E03B (base 16) PROMINET CORPORATION + 110 TURNPIKE RD. - STE. #208 + WESTBOROUGH MA 01581 + US + +00-E0-F5 (hex) TELES AG +00E0F5 (base 16) TELES AG + DOVESTR. 2-4 + 10587 BERLIN + DE + +00-E0-D7 (hex) SUNSHINE ELECTRONICS, INC. +00E0D7 (base 16) SUNSHINE ELECTRONICS, INC. + 46560 FREMONT BLVD. -STE. #113 + FREMONT CA 94538 + US + +00-E0-B5 (hex) ARDENT COMMUNICATIONS CORP. +00E0B5 (base 16) ARDENT COMMUNICATIONS CORP. + 3801 ZANKER ROAD, Suite A + SAN JOSE CA 95134 + US + +00-E0-68 (hex) MERRIMAC SYSTEMS INC. +00E068 (base 16) MERRIMAC SYSTEMS INC. + 2144 MC COY ROAD + CARROLLTON TX 75006 + US + +00-E0-49 (hex) MICROWI ELECTRONIC GmbH +00E049 (base 16) MICROWI ELECTRONIC GmbH + ZUSAMSTRASSE 8 + D 86165 AUGSBURG + DE + +00-E0-95 (hex) ADVANCED-VISION TECHNOLGIES CORP. +00E095 (base 16) ADVANCED-VISION TECHNOLGIES CORP. + 8F-1, 87 SECTION 3, CHUNG YANG RD, + Tu Cheng Taipei + TW + +00-E0-0E (hex) AVALON IMAGING SYSTEMS, INC. +00E00E (base 16) AVALON IMAGING SYSTEMS, INC. + 3133 INDIAN ROAD + BOULDER CO 80301 + US + +00-E0-48 (hex) SDL COMMUNICATIONS, INC. +00E048 (base 16) SDL COMMUNICATIONS, INC. + P.O. BOX 1303 + EASTON MA 02334 + US + +00-E0-CB (hex) RESON, INC. +00E0CB (base 16) RESON, INC. + 300 LOPEZ ROAD + GOLETA CA 93117 + US + +00-E0-C8 (hex) VIRTUAL ACCESS, LTD. +00E0C8 (base 16) VIRTUAL ACCESS, LTD. + WOODSIDE HOUSE, WINKFIELD, + WINDSOR, BERKSHIRE SL4 2DX ENGLAND + GB + +00-E0-06 (hex) SILICON INTEGRATED SYS. CORP. +00E006 (base 16) SILICON INTEGRATED SYS. CORP. + 16, CREATION RD. I + HSIN CHU + TW + +00-E0-AC (hex) MIDSCO, INC. +00E0AC (base 16) MIDSCO, INC. + 710 ROUTE 46 EAST + FAIRFIELD NJ 07004 + US + +00-E0-08 (hex) AMAZING CONTROLS! INC. +00E008 (base 16) AMAZING CONTROLS! INC. + 1615 WYATT DRIVE + SANTA CLARA CA 95054 + US + +00-E0-AE (hex) XAQTI CORPORATION +00E0AE (base 16) XAQTI CORPORATION + 1630 OAKLAND RD. #A-214 + SAN JOSE CA 95131 + US + +00-E0-E0 (hex) SI ELECTRONICS, LTD. +00E0E0 (base 16) SI ELECTRONICS, LTD. + 28-16, SHIMOMARUKO 2-CHOME, + TOKYO 146 + JP + +00-E0-50 (hex) EXECUTONE INFORMATION SYSTEMS, INC. +00E050 (base 16) EXECUTONE INFORMATION SYSTEMS, INC. + 478 WHEELERS FARMS ROAD + MILFORD CT 06460 + US + +00-E0-23 (hex) TELRAD +00E023 (base 16) TELRAD + P.O. BOX 50 + LOD 71100 + IL + +00-E0-2C (hex) AST COMPUTER +00E02C (base 16) AST COMPUTER + 16215 ALTON PARKWAY + IRVINE CA 92718 + US + +00-E0-67 (hex) eac AUTOMATION-CONSULTING GmbH +00E067 (base 16) eac AUTOMATION-CONSULTING GmbH + HERMSDORFER DAMM 222 + 73467 BERLIN + DE + +00-E0-FA (hex) TRL TECHNOLOGY, LTD. +00E0FA (base 16) TRL TECHNOLOGY, LTD. + SHANNON WAY, ASHCHURCH, + TEWKESBURY, GLOS. GL20 8ND + GB + +00-E0-2A (hex) TANDBERG TELEVISION AS +00E02A (base 16) TANDBERG TELEVISION AS + PHILIP PEDERSENS V 20 + N-1324 LYSAKER + NO + +00-E0-4E (hex) SANYO DENKI CO., LTD. +00E04E (base 16) SANYO DENKI CO., LTD. + 812-3, Shimonogou, Ueda-Shi + Nagano 386-1211 + JP + +00-E0-12 (hex) PLUTO TECHNOLOGIES INTERNATIONAL INC. +00E012 (base 16) PLUTO TECHNOLOGIES INTERNATIONAL INC. + 2511 55TH STREET + BOULDER CO 80301 + US + +00-E0-4C (hex) REALTEK SEMICONDUCTOR CORP. +00E04C (base 16) REALTEK SEMICONDUCTOR CORP. + 1F, NO. 11, INDUSTRY E. RD. IX + HSINCHU 300 + TW + +00-E0-51 (hex) TALX CORPORATION +00E051 (base 16) TALX CORPORATION + 1850 BORMAN COURT + ST. LOUIS MO 63146 + US + +00-60-6B (hex) Synclayer Inc. +00606B (base 16) Synclayer Inc. + 1-20 Himegaoka + GIFU 509-0249 + JP + +00-60-3B (hex) AMTEC spa +00603B (base 16) AMTEC spa + LOC. S. MARTINO + 53025 PIANCASTAGNAIO (SIENA) + IT + +00-E0-39 (hex) PARADYNE CORP. +00E039 (base 16) PARADYNE CORP. + 8545 126TH AVENUE NORTH + LARGO FL 33773 + US + +00-60-0B (hex) LOGWARE GmbH +00600B (base 16) LOGWARE GmbH + SCHWEDENSTR. 9 + D-13359 BERLIN + DE + +00-E0-C7 (hex) EUROTECH SRL +00E0C7 (base 16) EUROTECH SRL + VIA JACOPO LINUSSIO 1 + 33030 AMAROO (UD) + IT + +00-E0-AF (hex) GENERAL DYNAMICS INFORMATION SYSTEMS +00E0AF (base 16) GENERAL DYNAMICS INFORMATION SYSTEMS + COMPUTING DEVICES, LTD. + FALLS CHURCH VA 22042-4523 + US + +00-E0-54 (hex) KODAI HITEC CO., LTD. +00E054 (base 16) KODAI HITEC CO., LTD. + 2-45 ONUMA HANYU CITY + SAITAMA.348 + JP + +00-E0-B9 (hex) BYAS SYSTEMS +00E0B9 (base 16) BYAS SYSTEMS + 2250 MONROE STREET, #371 + SANTA CLARA CA 95050 + US + +00-60-4B (hex) Safe-com GmbH & Co. KG +00604B (base 16) Safe-com GmbH & Co. KG + Burg Lichtenfels 1 + 35104 Lichtenfels + DE + +00-E0-EF (hex) DIONEX +00E0EF (base 16) DIONEX + PO BOX 3603 + SUNNYVALE CA 94088-3603 + US + +00-E0-2D (hex) InnoMediaLogic, Inc. +00E02D (base 16) InnoMediaLogic, Inc. + 3653 CHEMIN CHAMBLY + LONGUEUIL, QUEBEC J4L J4L IN9 + CA + +00-E0-35 (hex) Artesyn Embedded Technologies +00E035 (base 16) Artesyn Embedded Technologies + 2900 S. Diablo Way + Tempe AZ 85282 + US + +00-E0-90 (hex) BECKMAN LAB. AUTOMATION DIV. +00E090 (base 16) BECKMAN LAB. AUTOMATION DIV. + 90 BOROLINE ROAD + ALLENDALE NJ 07401 + US + +00-60-01 (hex) InnoSys, Inc. +006001 (base 16) InnoSys, Inc. + 3095 RICHMOND PKWY #207 + RICHMOND CA 94806 + US + +00-60-FE (hex) LYNX SYSTEM DEVELOPERS, INC. +0060FE (base 16) LYNX SYSTEM DEVELOPERS, INC. + 175N NEW BOSTON STREET + WOBURN MA 01801 + US + +00-60-BD (hex) Enginuity Communications +0060BD (base 16) Enginuity Communications + 3545 Stern Avenue + St Charles IL 60174 + US + +00-08-00 (hex) MULTITECH SYSTEMS, INC. +000800 (base 16) MULTITECH SYSTEMS, INC. + 2205 WOODALE DRIVE + MOUNDS VIEW MN 55112 + US + +00-E0-85 (hex) GLOBAL MAINTECH, INC. +00E085 (base 16) GLOBAL MAINTECH, INC. + 6468 CITY WEST PARKWAY + EDEN PRAIRIE MN 55344 + US + +00-E0-BE (hex) GENROCO INTERNATIONAL, INC. +00E0BE (base 16) GENROCO INTERNATIONAL, INC. + 255 ENDERS COURT + SLINGER WI 53086 + US + +00-E0-B6 (hex) Entrada Networks +00E0B6 (base 16) Entrada Networks + 9020 JUNCTION DRIVE + ANNAPOLIS JUNCTION MD 20701 + US + +00-E0-F4 (hex) INSIDE Technology A/S +00E0F4 (base 16) INSIDE Technology A/S + VENLIGHEDSVEJ 6 + DK-2970 HOERSHOLM + DK + +00-E0-A0 (hex) WILTRON CO. +00E0A0 (base 16) WILTRON CO. + 490 JARVIS DRIVE + MORGAN HILL CA 95037 + US + +00-E0-F1 (hex) THAT CORPORATION +00E0F1 (base 16) THAT CORPORATION + 734 FOREST STREET + MARLBOROUGH MA 01752 + US + +00-60-D5 (hex) AMADA MIYACHI Co., Ltd +0060D5 (base 16) AMADA MIYACHI Co., Ltd + 95-3, FUTASUZUKA NODA + CHIBA 278-0016 + JP + +00-60-3F (hex) PATAPSCO DESIGNS +00603F (base 16) PATAPSCO DESIGNS + 5350 PARTNERS COURT + FREDERICK MD 21703 + US + +00-60-B5 (hex) KEBA GmbH +0060B5 (base 16) KEBA GmbH + GEWERBEPARK URFAHR + A-4041 LINZ + AT + +00-60-14 (hex) EDEC CO., LTD. +006014 (base 16) EDEC CO., LTD. + 9F OF T.O.C. BUILDING + SHINAGAWAKU, TOKYO + JP + +00-60-AC (hex) RESILIENCE CORPORATION +0060AC (base 16) RESILIENCE CORPORATION + 1755 EMBARCADERO ROAD-STE #120 + PALO ALTO CA 94303 + US + +00-60-4E (hex) CYCLE COMPUTER CORPORATION, INC. +00604E (base 16) CYCLE COMPUTER CORPORATION, INC. + 20245 STEVENS CREEK BLVD. + CUPERTINO CA 95014 + US + +00-60-E1 (hex) ORCKIT COMMUNICATIONS LTD. +0060E1 (base 16) ORCKIT COMMUNICATIONS LTD. + 38 NAHALAT YIZHAK STREET + TEL-AVIV 67448 + IL + +00-60-D2 (hex) LUCENT TECHNOLOGIES TAIWAN TELECOMMUNICATIONS CO., LTD. +0060D2 (base 16) LUCENT TECHNOLOGIES TAIWAN TELECOMMUNICATIONS CO., LTD. + #2, INNOVATION ROAD II + HSIN CHU + TW + +00-60-42 (hex) TKS (USA), INC. +006042 (base 16) TKS (USA), INC. + 1201 COMMERCE + RICHARDSON TX 75081 + US + +00-60-79 (hex) Mainstream Data, Inc. +006079 (base 16) Mainstream Data, Inc. + 375 Chipeta Way, Suite B + Salt Lake City UT 84108 + US + +00-60-9A (hex) NJK TECHNO CO. +00609A (base 16) NJK TECHNO CO. + N1-25 KAMIYASATO + KOMATSU #923 + JP + +00-60-2B (hex) PEAK AUDIO +00602B (base 16) PEAK AUDIO + 1790 30TH STREET STE #414 + BOULDER CO 80301 + US + +00-60-F1 (hex) EXP COMPUTER, INC. +0060F1 (base 16) EXP COMPUTER, INC. + 141 EILEEN WAY + SYOSSET NY 11791 + US + +00-60-E6 (hex) SHOMITI SYSTEMS INCORPORATED +0060E6 (base 16) SHOMITI SYSTEMS INCORPORATED + 2099 GATEWAY PLACE - STE.#220 + SAN JOSE CA 95110 + US + +00-60-FF (hex) QuVis, Inc. +0060FF (base 16) QuVis, Inc. + 2921 SW WANAMAKER DRIVE + TOPEKA KS 66614 + US + +00-60-67 (hex) ACER NETXUS INC. +006067 (base 16) ACER NETXUS INC. + 5F-3, 5 HSIN ANN ROAD SBIP + HSINCHU 300 + TJ + +00-60-9F (hex) PHAST CORPORATION +00609F (base 16) PHAST CORPORATION + 79 WEST 4500 SOUTH - BLDG.#14 + SALT LAKE CITY UT 84107 + US + +00-60-40 (hex) NETRO CORP. +006040 (base 16) NETRO CORP. + 3120 SCOTT BLVD. + SANTA CLARA CA 95054 + US + +00-60-CC (hex) EMTRAK, INCORPORATED +0060CC (base 16) EMTRAK, INCORPORATED + 7150 CAMPUS DRIVE, STE #180 + COLORADO SPRINGS CO 80920 + US + +00-60-2C (hex) LINX Data Terminals, Inc. +00602C (base 16) LINX Data Terminals, Inc. + 625 DIGITAL DRIVE-STE #100 + PLANO TX 75075 + US + +00-60-7E (hex) GIGALABS, INC. +00607E (base 16) GIGALABS, INC. + 290 SANTA ANA COURT + SUNNYVALE CA 94086 + US + +00-60-CD (hex) VideoServer, Inc. +0060CD (base 16) VideoServer, Inc. + 5 FORBES ROAD + LEXINGTON MA 02173 + US + +00-60-AA (hex) INTELLIGENT DEVICES INC. (IDI) +0060AA (base 16) INTELLIGENT DEVICES INC. (IDI) + 1718-L BELMONT AVENUE + BALTIMORE MD 21244 + US + +00-60-25 (hex) ACTIVE IMAGING PLC +006025 (base 16) ACTIVE IMAGING PLC + HATTORI HOUSE + MAIDENHEAD Berkshire SL6 4UB + GB + +00-60-A7 (hex) MICROSENS GmbH & CO. KG +0060A7 (base 16) MICROSENS GmbH & CO. KG + Kueferstrasse 16 + D-59067 Hamm + DE + +00-05-A8 (hex) WYLE ELECTRONICS +0005A8 (base 16) WYLE ELECTRONICS + 3000 BOWERS AVENUE + SANTA CLARA CA 95051-0919 + US + +00-60-E5 (hex) FUJI AUTOMATION CO., LTD. +0060E5 (base 16) FUJI AUTOMATION CO., LTD. + 3-23-10, NEGISHI + URAWA-SHI, 336 SAITAMA + US + +00-60-5E (hex) LIBERTY TECHNOLOGY NETWORKING +00605E (base 16) LIBERTY TECHNOLOGY NETWORKING + P.O. BOX 11566 + HATFIELD, PRETORIA 0028 + ZA + +00-60-C6 (hex) DCS AG +0060C6 (base 16) DCS AG + SALZACHSTRASS 31 + D-14129 BERLIN + DE + +00-60-1E (hex) SOFTLAB, INC. +00601E (base 16) SOFTLAB, INC. + P.O. BOX 8 + CHIMNEY ROCK CO 81127 + US + +00-60-65 (hex) BERNECKER & RAINER INDUSTRIE-ELEKTRONIC GmbH +006065 (base 16) BERNECKER & RAINER INDUSTRIE-ELEKTRONIC GmbH + EGGELSBERG 120 + 5142 EGGELSBERG + AT + +00-60-5D (hex) SCANIVALVE CORP. +00605D (base 16) SCANIVALVE CORP. + 1722 N. MADSON STREET + LIBERTY LAKE WA 99019 + US + +00-60-6F (hex) CLARION CORPORATION OF AMERICA +00606F (base 16) CLARION CORPORATION OF AMERICA + 25 Commerce Drive + Allendale NJ 07401 + US + +00-A0-10 (hex) SYSLOGIC DATENTECHNIK AG +00A010 (base 16) SYSLOGIC DATENTECHNIK AG + Bruggerstrasse 69 + CH-5400 Baden + CH + +00-A0-59 (hex) HAMILTON HALLMARK +00A059 (base 16) HAMILTON HALLMARK + 2105 LUNDY AVENUE + SAN JOSE CA 95131 + US + +00-A0-39 (hex) ROSS TECHNOLOGY, INC. +00A039 (base 16) ROSS TECHNOLOGY, INC. + 5316 HWY 290 WEST - STE. #500 + AUSTIN TX 78735 + US + +00-A0-AD (hex) MARCONI SPA +00A0AD (base 16) MARCONI SPA + VIA NEGRONE, 1A + 16153 GENOVA CORNIGLIANO + IT + +00-A0-D6 (hex) SBE, Inc. +00A0D6 (base 16) SBE, Inc. + 4000 Executive Parkway + San Ramon CA 94583 + US + +00-A0-2E (hex) BRAND COMMUNICATIONS, LTD. +00A02E (base 16) BRAND COMMUNICATIONS, LTD. + ENTERPRISE HOUSE, CHIVERS WAY, + HISTON, CAMBRIDGE CB4 4ZR + GB + +00-60-4A (hex) SAIC IDEAS GROUP +00604A (base 16) SAIC IDEAS GROUP + 7120 COLUMBIA GATEWAY DRIVE + COLUMBIA MD 21046 + US + +00-A0-BD (hex) I-TECH CORP. +00A0BD (base 16) I-TECH CORP. + 10200 VALLEY VIEW ROAD + EDEN PRAIRIE MN 55344 + US + +00-60-90 (hex) Artiza Networks Inc +006090 (base 16) Artiza Networks Inc + Faret Tachikawa Center Square, 2-36-2 Akebono-cho, + Tachikawa-shi, Tokyo 190-0012 + JP + +00-60-0D (hex) Digital Logic GmbH +00600D (base 16) Digital Logic GmbH + Stahlwerkstraße 25 + Mudersbach 57555 + DE + +00-60-30 (hex) VILLAGE TRONIC ENTWICKLUNG +006030 (base 16) VILLAGE TRONIC ENTWICKLUNG + WELLWEG 95 + 31157 SARSTEDT + DE + +00-A0-8D (hex) JACOMO CORPORATION +00A08D (base 16) JACOMO CORPORATION + 26900 E. PINK HILL ROAD + INDEPENDENCE MO 64057 + US + +00-A0-8E (hex) Check Point Software Technologies +00A08E (base 16) Check Point Software Technologies + 8333 Ridgepoint Dr. + Irving TX 75063 + US + +00-A0-FC (hex) IMAGE SCIENCES, INC. +00A0FC (base 16) IMAGE SCIENCES, INC. + 7500 INNOVATION WAY + MASON OH 45040 + US + +00-A0-9C (hex) Xyplex, Inc. +00A09C (base 16) Xyplex, Inc. + 25 FOSTER STREET + LITTLETON MA 01460 + US + +00-A0-0D (hex) THE PANDA PROJECT +00A00D (base 16) THE PANDA PROJECT + 5201 CONGRESS AVE. - C-100 + BOCA RATON FL 33487 + US + +00-A0-E9 (hex) ELECTRONIC RETAILING SYSTEMS INTERNATIONAL +00A0E9 (base 16) ELECTRONIC RETAILING SYSTEMS INTERNATIONAL + 372 DANBURY ROAD + WILTON CT 06897-2523 + US + +00-A0-BE (hex) INTEGRATED CIRCUIT SYSTEMS, INC. COMMUNICATIONS GROUP +00A0BE (base 16) INTEGRATED CIRCUIT SYSTEMS, INC. COMMUNICATIONS GROUP + 1271 PARKMOOR AVENUE + SAN JOSE CA 95126-3448 + US + +00-A0-16 (hex) MICROPOLIS CORP. +00A016 (base 16) MICROPOLIS CORP. + 21211 NORDHOFF STREET + CHATSWORTH CA 91311 + US + +00-A0-48 (hex) QUESTECH, LTD. +00A048 (base 16) QUESTECH, LTD. + EASTHEATH AVENUE + BERKS, RG11 2PP + GB + +00-A0-03 (hex) Siemens Switzerland Ltd., I B T HVP +00A003 (base 16) Siemens Switzerland Ltd., I B T HVP + Building Technologies Division, International Headquarters + Zug 6301 + CH + +00-A0-F9 (hex) BINTEC COMMUNICATIONS GMBH +00A0F9 (base 16) BINTEC COMMUNICATIONS GMBH + SUEDWESTPARK 94 + 90449 NUERNBERG + DE + +00-A0-F5 (hex) RADGUARD LTD. +00A0F5 (base 16) RADGUARD LTD. + 8 HANECHOSHET STREET + TEL-AVIV 69710 + IL + +00-A0-CA (hex) FUJITSU DENSO LTD. +00A0CA (base 16) FUJITSU DENSO LTD. + 3055 ORCHARD DRIVE + SAN JOSE CA 95134 + US + +00-A0-22 (hex) CENTRE FOR DEVELOPMENT OF ADVANCED COMPUTING +00A022 (base 16) CENTRE FOR DEVELOPMENT OF ADVANCED COMPUTING + UNIVERSITY OF POONA CAMPUS + GANESH KHIND, Pune - 411 008 + IN + +00-A0-B6 (hex) SANRITZ AUTOMATION CO., LTD. +00A0B6 (base 16) SANRITZ AUTOMATION CO., LTD. + 4-21 MINAMI NARUSE + + + +00-A0-79 (hex) ALPS ELECTRIC (USA), INC. +00A079 (base 16) ALPS ELECTRIC (USA), INC. + 3553 NORTH 1ST STREET + SAN JOSE CA 95134 + US + +00-A0-C0 (hex) DIGITAL LINK CORP. +00A0C0 (base 16) DIGITAL LINK CORP. + 217 HUMBOLDT COURT + SUNNYVALE CA 94089 + US + +00-A0-1E (hex) EST CORPORATION +00A01E (base 16) EST CORPORATION + 120 ROYALL STREET + CANTON MA 02021 + US + +00-A0-AE (hex) NUCOM SYSTEMS, INC. +00A0AE (base 16) NUCOM SYSTEMS, INC. + 9F-6, NO 4, LANE + TAIWAN TAIWAN R.O.C. + TW + +00-A0-62 (hex) AES PRODATA +00A062 (base 16) AES PRODATA + 249 BALCATTA ROAD + WESTERN AUSTRALIA 6021 + AU + +00-A0-76 (hex) CARDWARE LAB, INC. +00A076 (base 16) CARDWARE LAB, INC. + 285 SOBRANTE WAY, STE. + SUNNYVALE CA 94086 + VI + +00-A0-A1 (hex) EPIC DATA INC. +00A0A1 (base 16) EPIC DATA INC. + 7280 RIVER ROAD + CANADA V6X 1X5 + + +00-A0-44 (hex) NTT IT CO., LTD. +00A044 (base 16) NTT IT CO., LTD. + + 231 + JP + +00-A0-11 (hex) MUTOH INDUSTRIES LTD. +00A011 (base 16) MUTOH INDUSTRIES LTD. + 253 KANAGAWA-KEN, + + JP + +00-A0-BA (hex) PATTON ELECTRONICS CO. +00A0BA (base 16) PATTON ELECTRONICS CO. + 7622 RICKENBACKER DRIVE + GAITHERSBURG MD 20879 + US + +00-A0-B5 (hex) 3H TECHNOLOGY +00A0B5 (base 16) 3H TECHNOLOGY + 3375 SCOTT BLVD. #336 + SANTA CLARA CA 95054 + US + +00-A0-4D (hex) EDA INSTRUMENTS, INC. +00A04D (base 16) EDA INSTRUMENTS, INC. + 4 THORNCLIFFE PARK DRIVE + M4H 1H1 + CA + +00-A0-86 (hex) AMBER WAVE SYSTEMS, INC. +00A086 (base 16) AMBER WAVE SYSTEMS, INC. + 403 MASSACHUSETTS AVENUE + ACTON MA 01720 + US + +00-A0-AF (hex) WMS INDUSTRIES +00A0AF (base 16) WMS INDUSTRIES + 3401 N. CALIFORNIA + CHICAGO IL 60618 + US + +00-A0-57 (hex) LANCOM Systems GmbH +00A057 (base 16) LANCOM Systems GmbH + Adenauer Straße 20 /B2 + Würselen 52146 + DE + +00-A0-30 (hex) CAPTOR NV/SA +00A030 (base 16) CAPTOR NV/SA + DE HENE 13 + + BE + +00-A0-DE (hex) YAMAHA CORPORATION +00A0DE (base 16) YAMAHA CORPORATION + 10-1 Nakazawa-cho, Naka-ku + Hamamatsu Shizuoka 430-8650 + JP + +00-A0-84 (hex) Dataplex Pty Ltd +00A084 (base 16) Dataplex Pty Ltd + Ground floor, + MACQUARIE PARK NSW 2113 + AU + +00-A0-49 (hex) DIGITECH INDUSTRIES, INC. +00A049 (base 16) DIGITECH INDUSTRIES, INC. + PO BOX 2267 + DANBURY CT 06810 + US + +00-A0-9D (hex) JOHNATHON FREEMAN TECHNOLOGIES +00A09D (base 16) JOHNATHON FREEMAN TECHNOLOGIES + P.O. BOX 880114 + SAN FRANCISCO CA 94188 + US + +00-A0-6B (hex) DMS DORSCH MIKROSYSTEM GMBH +00A06B (base 16) DMS DORSCH MIKROSYSTEM GMBH + HOLMLUECK 13-15 + + DE + +00-A0-F8 (hex) Zebra Technologies Inc +00A0F8 (base 16) Zebra Technologies Inc + 475 Half Day Road + Lincolnshire IL 60069 + US + +00-A0-9F (hex) COMMVISION CORP. +00A09F (base 16) COMMVISION CORP. + 510 LOGUE AVE. + MOUNTAIN VIEW CA 94043 + US + +00-A0-6E (hex) AUSTRON, INC. +00A06E (base 16) AUSTRON, INC. + P.O. BOX 14766 + AUSTIN TX 78761-4766 + US + +00-20-22 (hex) NMS Communications +002022 (base 16) NMS Communications + 100 Crossing Boulevard + Framingham MA 01702 + US + +00-20-AE (hex) ORNET DATA COMMUNICATION TECH. +0020AE (base 16) ORNET DATA COMMUNICATION TECH. + P.O. BOX 323 + + IL + +00-20-AA (hex) Ericsson Television Limited +0020AA (base 16) Ericsson Television Limited + Solution Area Media + Comines Way, Hedge End Southhampton SO 30 4DA + GB + +00-20-A4 (hex) MULTIPOINT NETWORKS +0020A4 (base 16) MULTIPOINT NETWORKS + 19 DAVIS DRIVE + BELMONT CA 94002-3001 + US + +00-02-67 (hex) NODE RUNNER, INC. +000267 (base 16) NODE RUNNER, INC. + 2202 N. FORBES BLVD. + TUCSON AZ 85745 + US + +00-20-B1 (hex) COMTECH RESEARCH INC. +0020B1 (base 16) COMTECH RESEARCH INC. + 24271 TAHOE + LAGUNA NIGUEL CA 92656 + US + +00-20-32 (hex) ALCATEL TAISEL +002032 (base 16) ALCATEL TAISEL + 4, MING SHENG STREET TU-CHENG + TAIWAN ROC + TW + +00-20-E9 (hex) DANTEL +0020E9 (base 16) DANTEL + P.O. BOX 55013 + FRESNO CA 93727-1388 + US + +00-20-38 (hex) VME MICROSYSTEMS INTERNATIONAL CORPORATION +002038 (base 16) VME MICROSYSTEMS INTERNATIONAL CORPORATION + 12090 S. MEMORIAL PARKWAY + HUNTSVILLE AL 35803 + US + +00-20-A3 (hex) Harmonic, Inc +0020A3 (base 16) Harmonic, Inc + 4300 North First Street + San Jose CA 95134 + US + +00-20-59 (hex) MIRO COMPUTER PRODUCTS AG +002059 (base 16) MIRO COMPUTER PRODUCTS AG + CARL MIELE STR. 4 + D-38112 BRAUNSCHWEIG + DE + +00-20-34 (hex) ROTEC INDUSTRIEAUTOMATION GMBH +002034 (base 16) ROTEC INDUSTRIEAUTOMATION GMBH + GUTENBERGSTR. 15 + + DE + +00-20-79 (hex) MIKRON GMBH +002079 (base 16) MIKRON GMBH + BRESLAUERSTR. 1-3 + 85386 ECHING + DE + +00-20-05 (hex) SIMPLE TECHNOLOGY +002005 (base 16) SIMPLE TECHNOLOGY + 3001 DAIMLER ROAD + SANTA ANA CA 92705 + US + +00-20-18 (hex) CIS TECHNOLOGY INC. +002018 (base 16) CIS TECHNOLOGY INC. + FL. 9-1, NO. 94, PAO CHUNG RD. + TAIPEI HSIEN + TW + +00-20-98 (hex) HECTRONIC AB +002098 (base 16) HECTRONIC AB + BOX 3002 + S-75003 UPPSALA + SE + +00-20-FD (hex) ITV TECHNOLOGIES, INC. +0020FD (base 16) ITV TECHNOLOGIES, INC. + 6800 OWENSMOUTH AVE. #230 + CANOGA PARK CA 91303 + US + +00-20-FA (hex) GDE SYSTEMS, INC. +0020FA (base 16) GDE SYSTEMS, INC. + P.O. BOX 85468 - BLDG.#61 + SAN DIEGO CA 92186-5468 + US + +00-20-C1 (hex) SAXA, Inc. +0020C1 (base 16) SAXA, Inc. + NBF Platinum Tower 1-17-3 Shirokane + Tokyo 108-8050 + JP + +00-20-80 (hex) SYNERGY (UK) LTD. +002080 (base 16) SYNERGY (UK) LTD. + HARTCRAN HOUSE + WATFORD HERTS. WD1 5EZ + GB + +00-C0-23 (hex) TUTANKHAMON ELECTRONICS +00C023 (base 16) TUTANKHAMON ELECTRONICS + 2446 ESTAND WAY + PLEASANT HILL CA 94523 + US + +00-C0-8B (hex) RISQ MODULAR SYSTEMS, INC. +00C08B (base 16) RISQ MODULAR SYSTEMS, INC. + 39899 BALENTINE DRIVE-STE #375 + NEWARK CA 94560 + US + +00-20-C4 (hex) INET,INC. +0020C4 (base 16) INET,INC. + 801 E. CAMPBELL-STE.#330 + RICHARDSON TX 75081 + US + +00-20-74 (hex) SUNGWOON SYSTEMS +002074 (base 16) SUNGWOON SYSTEMS + YUSUN BLDG.44-4 + KOREA + KR + +00-20-3C (hex) EUROTIME AB +00203C (base 16) EUROTIME AB + BOX 277 + + SE + +00-20-28 (hex) WEST EGG SYSTEMS, INC. +002028 (base 16) WEST EGG SYSTEMS, INC. + 65 HIGH RIDGE ROAD-STE.#286 + STAMFORD CT 06905 + US + +00-20-68 (hex) ISDYNE +002068 (base 16) ISDYNE + 11 ROXBURY AVENUE + NATICK MA 01760 + US + +00-20-C8 (hex) LARSCOM INCORPORATED +0020C8 (base 16) LARSCOM INCORPORATED + 4600 PATRICK HENRY DRIVE + SANTA CLARA CA 95054 + US + +00-20-9D (hex) LIPPERT AUTOMATIONSTECHNIK +00209D (base 16) LIPPERT AUTOMATIONSTECHNIK + D-68165 MANNHEIM + + DE + +00-20-9C (hex) PRIMARY ACCESS CORP. +00209C (base 16) PRIMARY ACCESS CORP. + 10080 CARROLL CANYON RD + SAN DIEGO CA 92131 + US + +00-20-6D (hex) DATA RACE, INC. +00206D (base 16) DATA RACE, INC. + 11550 IH-10WEST STE#395 + SAN ANTONIO TX 78230 + US + +00-20-3A (hex) DIGITAL BI0METRICS INC. +00203A (base 16) DIGITAL BI0METRICS INC. + 5600 ROWLAND ROAD- STE.#205 + MINNETONKA MN 55364 + US + +00-20-48 (hex) Marconi Communications +002048 (base 16) Marconi Communications + 1000 Fore Drive + Warrendale PA 15086-7502 + US + +00-20-DC (hex) DENSITRON TAIWAN LTD. +0020DC (base 16) DENSITRON TAIWAN LTD. + KYOWA NANABANKAN 5F + + JP + +00-20-0C (hex) ADASTRA SYSTEMS CORP. +00200C (base 16) ADASTRA SYSTEMS CORP. + 28310 INDUSTRIAL BLVD.-STE-K + HAYWARD CA 94545 + US + +00-20-11 (hex) CANOPUS CO., LTD. +002011 (base 16) CANOPUS CO., LTD. + KOBE HI-TECH PARK + 651-22 + JP + +00-20-51 (hex) Verilink Corporation +002051 (base 16) Verilink Corporation + 127 Jetplex Circle + Madison AL 35758 + US + +00-20-3B (hex) WISDM LTD. +00203B (base 16) WISDM LTD. + ST. JOHNS INNOVATION CENTRE + ENGLAND + GB + +00-20-BA (hex) CENTER FOR HIGH PERFORMANCE +0020BA (base 16) CENTER FOR HIGH PERFORMANCE + COMPUTING OF WPI + MARLBORO MA 01752 + US + +00-20-F5 (hex) PANDATEL AG +0020F5 (base 16) PANDATEL AG + FASANENWEG 25 + + DE + +00-20-0E (hex) NSSLGlobal Technologies AS +00200E (base 16) NSSLGlobal Technologies AS + Martin Linges vei 25 + Fornebu 1364 + NO + +00-20-E7 (hex) B&W NUCLEAR SERVICE COMPANY +0020E7 (base 16) B&W NUCLEAR SERVICE COMPANY + SPECIAL PRODUCTS & INTEG.SVCS. + LYNCHBURG VA 24502 + US + +00-20-F0 (hex) UNIVERSAL MICROELECTRONICS CO. +0020F0 (base 16) UNIVERSAL MICROELECTRONICS CO. + 3, 27TH RD., TAICHUNG IND.PARK + TAIWAN TAIWAN R.O.C. + TW + +00-20-89 (hex) T3PLUS NETWORKING, INC. +002089 (base 16) T3PLUS NETWORKING, INC. + 2840 SAN TOMAS EXPRESSWAY + SANTA CLARA CA 95051 + US + +00-20-61 (hex) GarrettCom, Inc. +002061 (base 16) GarrettCom, Inc. + 47823 Westinghouse Dr. + Fremont CA 94539 + US + +00-C0-80 (hex) NETSTAR, INC. +00C080 (base 16) NETSTAR, INC. + CEDAR BUSINESS CENTER + MINNEAPOLIS MN 55425-1235 + US + +00-C0-B4 (hex) MYSON TECHNOLOGY, INC. +00C0B4 (base 16) MYSON TECHNOLOGY, INC. + 2F, NO. 3, INDUSTRY E. RD.IV + TAIWAN + TW + +00-C0-45 (hex) ISOLATION SYSTEMS, LTD. +00C045 (base 16) ISOLATION SYSTEMS, LTD. + 26 SIX POINT ROAD + CANADA M8Z 2W9 + CA + +00-70-B3 (hex) DATA RECALL LTD. +0070B3 (base 16) DATA RECALL LTD. + SONDES PLACE + UNITED KINGDOM + GB + +00-70-B0 (hex) M/A-COM INC. COMPANIES +0070B0 (base 16) M/A-COM INC. COMPANIES + 11717 EXPLORATION LANE + GERMANTOWN MD 20767 + US + +00-E6-D3 (hex) NIXDORF COMPUTER CORP. +00E6D3 (base 16) NIXDORF COMPUTER CORP. + 2520 MISSION COLLEGE ROAD + SANTA CLARA CA 95054 + US + +00-C0-C3 (hex) ACUSON COMPUTED SONOGRAPHY +00C0C3 (base 16) ACUSON COMPUTED SONOGRAPHY + 1220 CHARLESTON ROAD + MOUNTAIN VIEW CA 94039-7393 + US + +00-C0-B3 (hex) COMSTAT DATACOMM CORPORATION +00C0B3 (base 16) COMSTAT DATACOMM CORPORATION + 1720 SPECTRUM DRIVE + LAWRENCEVILLE GA 30243 + US + +00-C0-E5 (hex) GESPAC, S.A. +00C0E5 (base 16) GESPAC, S.A. + CHEMIN DES AULX 18 + + CH + +00-C0-4D (hex) MITEC, INC. +00C04D (base 16) MITEC, INC. + BR-KAMEIDO 1 BUILDING + + JP + +00-C0-47 (hex) UNIMICRO SYSTEMS, INC. +00C047 (base 16) UNIMICRO SYSTEMS, INC. + 44382 S. GRIMMER BLVD. + FREMONT CA 94538 + US + +00-C0-84 (hex) DATA LINK CORP. LTD. +00C084 (base 16) DATA LINK CORP. LTD. + 3-15-3 MIDORICHO + + JP + +00-C0-41 (hex) DIGITAL TRANSMISSION SYSTEMS +00C041 (base 16) DIGITAL TRANSMISSION SYSTEMS + 4830 RIVER GREEN PARKWAY + DULUTH GA 30136 + US + +00-C0-1F (hex) S.E.R.C.E.L. +00C01F (base 16) S.E.R.C.E.L. + B.P. 439 + + FR + +00-60-86 (hex) LOGIC REPLACEMENT TECH. LTD. +006086 (base 16) LOGIC REPLACEMENT TECH. LTD. + 14 ARKWRIGHT ROAD + UNITED KINGDOM + GB + +00-C0-59 (hex) DENSO CORPORATION +00C059 (base 16) DENSO CORPORATION + 1-1, Showa-cho, + Kariya-shi, Aichi 448-8661 + JP + +00-C0-F1 (hex) SHINKO ELECTRIC CO., LTD. +00C0F1 (base 16) SHINKO ELECTRIC CO., LTD. + COMPUTER SYSTEM DIVISION + JAPAN 441-31 + JP + +00-C0-A1 (hex) TOKYO DENSHI SEKEI CO. +00C0A1 (base 16) TOKYO DENSHI SEKEI CO. + 255-1 RENKOJI, TAMA-SHI + JAPAN 206 + JP + +00-C0-2E (hex) NETWIZ +00C02E (base 16) NETWIZ + 26 GOLOMB STREET + + IL + +00-C0-0D (hex) ADVANCED LOGIC RESEARCH, INC. +00C00D (base 16) ADVANCED LOGIC RESEARCH, INC. + 9401 JERONIMO + IRVINE CA 92618 + US + +00-C0-81 (hex) METRODATA LTD. +00C081 (base 16) METRODATA LTD. + BLENHEIM HOUSE + TW20 8RY TW20 8RY ENGLAND + GB + +00-C0-3B (hex) MULTIACCESS COMPUTING CORP. +00C03B (base 16) MULTIACCESS COMPUTING CORP. + 5350 HOLLISTER AVE., STE. + SANTA BARBARA CA 93111 + US + +00-C0-82 (hex) MOORE PRODUCTS CO. +00C082 (base 16) MOORE PRODUCTS CO. + SUMNEYTOWN PIKE + SPRING HOUSE PA 19477 + US + +00-C0-99 (hex) YOSHIKI INDUSTRIAL CO.,LTD. +00C099 (base 16) YOSHIKI INDUSTRIAL CO.,LTD. + 1-38 MATSUGASAKI 2-CHOME + 992 + JP + +00-C0-01 (hex) DIATEK PATIENT MANAGMENT +00C001 (base 16) DIATEK PATIENT MANAGMENT + SYSTEMS, INC. + SAN DIEGO CA 92121-1723 + US + +00-C0-F4 (hex) INTERLINK SYSTEM CO., LTD. +00C0F4 (base 16) INTERLINK SYSTEM CO., LTD. + INTERLINK B/D, 476-20 + KOREA + KR + +00-C0-E2 (hex) CALCOMP, INC. +00C0E2 (base 16) CALCOMP, INC. + 2411 W. LAPALMA AVENUE + ANAHEIM CA 92803-3250 + US + +00-C0-7B (hex) ASCEND COMMUNICATIONS, INC. +00C07B (base 16) ASCEND COMMUNICATIONS, INC. + 1701 HARBOR BAY PARKWAY + ALAMEDA CA 94502 + US + +00-C0-3C (hex) TOWER TECH S.R.L. +00C03C (base 16) TOWER TECH S.R.L. + VIA RIDOLFI 6,8 + + IT + +00-C0-1D (hex) GRAND JUNCTION NETWORKS, INC. +00C01D (base 16) GRAND JUNCTION NETWORKS, INC. + 3101 WHIPPLE RD., #27 + UNION CITY CA 94587 + US + +00-C0-35 (hex) QUINTAR COMPANY +00C035 (base 16) QUINTAR COMPANY + 370 AMAPOLA AVE., STE.#106 + TORRANCE CA 90501 + US + +00-C0-70 (hex) SECTRA SECURE-TRANSMISSION AB +00C070 (base 16) SECTRA SECURE-TRANSMISSION AB + TEKNIKRINGEN 2 + + SE + +00-C0-6D (hex) BOCA RESEARCH, INC. +00C06D (base 16) BOCA RESEARCH, INC. + 6401 CONGRESS AVENUE + BOCA RATON FL 33487 + US + +00-C0-EA (hex) ARRAY TECHNOLOGY LTD. +00C0EA (base 16) ARRAY TECHNOLOGY LTD. + 145 FRIMLEY ROAD + ENGLAND GU15 2PS + GB + +00-C0-09 (hex) KT TECHNOLOGY (S) PTE LTD +00C009 (base 16) KT TECHNOLOGY (S) PTE LTD + KT BUILDING + SINGAPORE 0511 + SG + +00-C0-D6 (hex) J1 SYSTEMS, INC. +00C0D6 (base 16) J1 SYSTEMS, INC. + 3 DUNWOODY PARK-STE.#103 + ATLANTA GA 30338 + US + +00-C0-DC (hex) EOS TECHNOLOGIES, INC. +00C0DC (base 16) EOS TECHNOLOGIES, INC. + 3945 FREEDOM CIRCLE, STE.#770 + SANTA CLARA CA 95054 + US + +00-C0-72 (hex) KNX LTD. +00C072 (base 16) KNX LTD. + HOLLINGWOOD HOUSE + LS21 3HA UNITED KINGDOM + GB + +00-C0-AE (hex) TOWERCOM CO. INC. DBA PC HOUSE +00C0AE (base 16) TOWERCOM CO. INC. DBA PC HOUSE + 841 E. ARTESIA BLVD. + CARSON CA 90746 + US + +00-C0-C2 (hex) INFINITE NETWORKS LTD. +00C0C2 (base 16) INFINITE NETWORKS LTD. + 19 BROOKSIDE ROAD, OXHEY + UNITED KINGDOM + GB + +00-C0-AF (hex) TEKLOGIX INC. +00C0AF (base 16) TEKLOGIX INC. + 2100 MEADOWVALE BOULEVARD + CANADA L5N 7J9 + CA + +00-C0-7A (hex) PRIVA B.V. +00C07A (base 16) PRIVA B.V. + P.O. BOX 18 + + NL + +00-C0-F6 (hex) CELAN TECHNOLOGY INC. +00C0F6 (base 16) CELAN TECHNOLOGY INC. + NO. 101, MIN-HSIANG ST. + TAIWAN TAIWAN R.O.C. + CN + +00-C0-F8 (hex) ABOUT COMPUTING INC. +00C0F8 (base 16) ABOUT COMPUTING INC. + P.O. BOX 172 + BELMONT MA 02178 + US + +00-C0-78 (hex) COMPUTER SYSTEMS ENGINEERING +00C078 (base 16) COMPUTER SYSTEMS ENGINEERING + 46791 FREMONT BLVD. + FREMONT CA 94538 + US + +00-C0-9A (hex) PHOTONICS CORPORATION +00C09A (base 16) PHOTONICS CORPORATION + 2940 NORTH FIRST STREET + SAN JOSE CA 95123-2021 + US + +00-C0-1A (hex) COROMETRICS MEDICAL SYSTEMS +00C01A (base 16) COROMETRICS MEDICAL SYSTEMS + 61 BARNES PARK ROAD NORTH + WALLINGFORD CT 06492-0333 + US + +00-C0-68 (hex) HME Clear-Com LTD. +00C068 (base 16) HME Clear-Com LTD. + 7400 Beach Drive + Cambridgeshire CB25 9TP + GB + +00-C0-D8 (hex) UNIVERSAL DATA SYSTEMS +00C0D8 (base 16) UNIVERSAL DATA SYSTEMS + 5000 BRADFORD DRIVE + HUNTSVILLE AL 35805-1993 + US + +00-40-36 (hex) Zoom Telephonics, Inc +004036 (base 16) Zoom Telephonics, Inc + 207 South St + Boston MA 02111 + US + +00-40-16 (hex) ADC - Global Connectivity Solutions Division +004016 (base 16) ADC - Global Connectivity Solutions Division + P.O. Box 1101 + Minneapolis MN 55440-1101 + US + +00-40-6A (hex) KENTEK INFORMATION SYSTEMS,INC +00406A (base 16) KENTEK INFORMATION SYSTEMS,INC + 2945 WILDERNESS PLACE + BOULDER CO 80301 + US + +00-40-0A (hex) PIVOTAL TECHNOLOGIES, INC. +00400A (base 16) PIVOTAL TECHNOLOGIES, INC. + 100 W. RINCON AVENUE-STE #211 + CAMPBELL CA 95008 + US + +00-40-99 (hex) NEWGEN SYSTEMS CORP. +004099 (base 16) NEWGEN SYSTEMS CORP. + 17580 NEWHOPE STREET + FOUNTAIN VALLEY CA 92708 + US + +00-40-11 (hex) ANDOVER CONTROLS CORPORATION +004011 (base 16) ANDOVER CONTROLS CORPORATION + 300 BRICKSTONE SQUARE + ANDOVER MA 01810 + US + +00-40-A1 (hex) ERGO COMPUTING +0040A1 (base 16) ERGO COMPUTING + ONE INTERCONTINENTAL WAY + PEABODY MA 01960 + US + +00-40-81 (hex) MANNESMANN SCANGRAPHIC GMBH +004081 (base 16) MANNESMANN SCANGRAPHIC GMBH + RISSENER STRASSE 112-114 + + DE + +00-C0-8C (hex) PERFORMANCE TECHNOLOGIES, INC. +00C08C (base 16) PERFORMANCE TECHNOLOGIES, INC. + 315 SCIENCE PARKWAY + ROCHESTER NY 14620 + US + +00-C0-07 (hex) PINNACLE DATA SYSTEMS, INC. +00C007 (base 16) PINNACLE DATA SYSTEMS, INC. + 1350 WEST FIFTH AVENUE + COLUMBUS OH 43212 + US + +00-C0-98 (hex) CHUNTEX ELECTRONIC CO., LTD. +00C098 (base 16) CHUNTEX ELECTRONIC CO., LTD. + 6F., NO.2, ALLEY 6, LANE 235 + TAIWAN TAIWAN R.O.C. + TW + +00-C0-BE (hex) ALCATEL - SEL +00C0BE (base 16) ALCATEL - SEL + LORENZ STR + + DE + +00-C0-6E (hex) HAFT TECHNOLOGY, INC. +00C06E (base 16) HAFT TECHNOLOGY, INC. + DAINI-DOHO BLDG. + 305 + JP + +00-C0-8A (hex) Lauterbach GmbH +00C08A (base 16) Lauterbach GmbH + Altlaufstraße 40 + Höhenkirchen-Siegertsbrunn 85635 + DE + +00-C0-F7 (hex) ENGAGE COMMUNICATION, INC. +00C0F7 (base 16) ENGAGE COMMUNICATION, INC. + 9053 SOQUEL DRIVE + APTOS CA 95003-4034 + US + +00-40-B7 (hex) STEALTH COMPUTER SYSTEMS +0040B7 (base 16) STEALTH COMPUTER SYSTEMS + 2341 REGINA CT. + SANTA CLARA CA 95054 + US + +00-40-AC (hex) SUPER WORKSTATION, INC. +0040AC (base 16) SUPER WORKSTATION, INC. + 2190 PARAGON DRIVE + SAN JOSE CA 95131 + US + +10-00-5A (hex) IBM Corp +10005A (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-40-D1 (hex) FUKUDA DENSHI CO., LTD. +0040D1 (base 16) FUKUDA DENSHI CO., LTD. + R & D DEPARTMENT NO. 1 + + JP + +00-40-69 (hex) LEMCOM SYSTEMS, INC. +004069 (base 16) LEMCOM SYSTEMS, INC. + 2104 WEST PEORIA AVENUE + PHOENIX AZ 85029 + US + +00-40-3B (hex) SYNERJET INTERNATIONAL CORP. +00403B (base 16) SYNERJET INTERNATIONAL CORP. + 5F, NO 35, KUANG FU S. ROAD + TAIWAN R. O. C. + TW + +00-80-3B (hex) APT COMMUNICATIONS, INC. +00803B (base 16) APT COMMUNICATIONS, INC. + 9607 DR. PERRY ROAD + IJAMSVILLE MD 21754 + US + +00-80-6A (hex) ERI (EMPAC RESEARCH INC.) +00806A (base 16) ERI (EMPAC RESEARCH INC.) + 47560 SEABRIDGE DRIVE + FREMONT CA 94538 + US + +00-C0-A8 (hex) GVC CORPORATION +00C0A8 (base 16) GVC CORPORATION + 1961 CONCOURSE DRIVE-STE + SAN JOSE CA 95131 + US + +00-40-E0 (hex) ATOMWIDE LTD. +0040E0 (base 16) ATOMWIDE LTD. + 23 THE GREENWAY + UNITED KINGDOM + GB + +00-40-A8 (hex) IMF INTERNATIONAL LTD. +0040A8 (base 16) IMF INTERNATIONAL LTD. + NO.5 2/F KINGSFORD IND. CENTRE + HONG KONG + HK + +00-40-70 (hex) INTERWARE CO., LTD. +004070 (base 16) INTERWARE CO., LTD. + 7F KUDAN NEW CENTRAL BLDG., + TOKYO 102 TOKYO 102 + JP + +00-40-8A (hex) TPS TELEPROCESSING SYS. GMBH +00408A (base 16) TPS TELEPROCESSING SYS. GMBH + SCHWADERMUCHLSTRASSE 4-8 + + DE + +00-40-FD (hex) LXE +0040FD (base 16) LXE + 303 RESEARCH DRIVE + NORCROSS GA 30092 + US + +00-40-3F (hex) SSANGYONG COMPUTER SYSTEMS +00403F (base 16) SSANGYONG COMPUTER SYSTEMS + CORPORATION + KOREA 100-705 + KR + +00-40-82 (hex) LABORATORY EQUIPMENT CORP. +004082 (base 16) LABORATORY EQUIPMENT CORP. + 1-7-3 MINATOMACHI + 300 + JP + +00-40-F1 (hex) CHUO ELECTRONICS CO., LTD. +0040F1 (base 16) CHUO ELECTRONICS CO., LTD. + 1-9-9, MOTOHONGO-CHO + + JP + +00-40-A9 (hex) DATACOM INC. +0040A9 (base 16) DATACOM INC. + 146 HIGHWAY ROUTE 34 - STE 250 + HOLMDEL NJ 07733 + US + +00-40-E3 (hex) QUIN SYSTEMS LTD +0040E3 (base 16) QUIN SYSTEMS LTD + OAKLANDS BUSINESS CENTRE + UNITED KINGDOM + GB + +00-40-91 (hex) PROCOMP INDUSTRIA ELETRONICA +004091 (base 16) PROCOMP INDUSTRIA ELETRONICA + AV. KENKITI SIMOMOTO, 767 + + BR + +00-40-EA (hex) PLAIN TREE SYSTEMS INC +0040EA (base 16) PLAIN TREE SYSTEMS INC + CHIEF EXECTUVIE OFFICER + + CA + +00-40-A7 (hex) ITAUTEC PHILCO S.A. +0040A7 (base 16) ITAUTEC PHILCO S.A. + GRUPO ITAUTEC PHILCO + + BR + +00-40-64 (hex) KLA INSTRUMENTS CORPORATION +004064 (base 16) KLA INSTRUMENTS CORPORATION + 160 RIO ROBLES + SAN JOSE CA 95161-9055 + US + +00-40-43 (hex) Nokia Siemens Networks GmbH & Co. KG. +004043 (base 16) Nokia Siemens Networks GmbH & Co. KG. + Werner-von-Siemens Straße 2-6 + Bruchsal Baden-Württemberg 76646 + DE + +00-40-5A (hex) GOLDSTAR INFORMATION & COMM. +00405A (base 16) GOLDSTAR INFORMATION & COMM. + 533, HOGAE-DONG, ANYANG-SHI + KOREA + KR + +00-40-13 (hex) NTT DATA COMM. SYSTEMS CORP. +004013 (base 16) NTT DATA COMM. SYSTEMS CORP. + DEVELOPMENT HEADQUARTERS + TOKYO 135 TOKYO 135 + JP + +00-40-0C (hex) GENERAL MICRO SYSTEMS, INC. +00400C (base 16) GENERAL MICRO SYSTEMS, INC. + P.O. BOX 3689 + RANCHO CUCAMONGA CA 91729 + US + +00-40-5E (hex) NORTH HILLS ISRAEL +00405E (base 16) NORTH HILLS ISRAEL + P.O. BOX 1280 + + IL + +00-40-FA (hex) MICROBOARDS, INC. +0040FA (base 16) MICROBOARDS, INC. + 31-8, TAKASECHO,FUNABASHI-CITY + CHIBA 273 CHIBA 273 + JP + +00-40-14 (hex) COMSOFT GMBH +004014 (base 16) COMSOFT GMBH + WACHHAUSSTR. 5A + + DE + +00-40-00 (hex) PCI COMPONENTES DA AMZONIA LTD +004000 (base 16) PCI COMPONENTES DA AMZONIA LTD + RUA JOSEF KRYSS + 01140 BRASIL + BR + +00-40-6C (hex) COPERNIQUE +00406C (base 16) COPERNIQUE + 6, MAIL DE L'EUROPE BP 25 + + FR + +00-40-75 (hex) Tattile SRL +004075 (base 16) Tattile SRL + 11-12 NORTHFIELD PROSPECT + UNITED KINGDOM + GB + +00-40-53 (hex) AMPRO COMPUTERS +004053 (base 16) AMPRO COMPUTERS + 990 ALMONDOR AVENUE + SUNNYVALE CA 94086 + US + +00-80-38 (hex) DATA RESEARCH & APPLICATIONS +008038 (base 16) DATA RESEARCH & APPLICATIONS + 9041 EXECUTIVE PARK DR. + KNOXVILLE TN 37923-4609 + US + +00-80-5E (hex) LSI LOGIC CORPORATION +00805E (base 16) LSI LOGIC CORPORATION + 1551 MCCARTHY BOULEVARD + MILPITAS CA 95035 + US + +00-80-60 (hex) NETWORK INTERFACE CORPORATION +008060 (base 16) NETWORK INTERFACE CORPORATION + 15019 WEST 95 STREET + LENEXA KS 66215 + US + +00-80-C3 (hex) BICC INFORMATION SYSTEMS & SVC +0080C3 (base 16) BICC INFORMATION SYSTEMS & SVC + 500 CAPABILITY GREEN, LUTON + ENGLAND LU1 3LT + GB + +00-80-44 (hex) SYSTECH COMPUTER CORP. +008044 (base 16) SYSTECH COMPUTER CORP. + 6465 NANCY RIDGE DRIVE + SAN DIEGO CA 92121 + US + +00-80-06 (hex) COMPUADD CORPORATION +008006 (base 16) COMPUADD CORPORATION + ENGINEERING + AUSTIN TX 78727 + US + +00-80-9B (hex) JUSTSYSTEM CORPORATION +00809B (base 16) JUSTSYSTEM CORPORATION + 3-46 OKINOHAMAHIGASHI + + JP + +00-80-DF (hex) ADC CODENOLL TECHNOLOGY CORP. +0080DF (base 16) ADC CODENOLL TECHNOLOGY CORP. + 200 CORPORATE BLVD. SO. + YONKERS NY 10701 + US + +00-80-28 (hex) TRADPOST (HK) LTD +008028 (base 16) TRADPOST (HK) LTD + 5/F, STAR CENTRE + HONG KONG + HK + +00-80-61 (hex) LITTON SYSTEMS, INC. +008061 (base 16) LITTON SYSTEMS, INC. + M/S 44-20 + AGOURA HILLS CA 91301-0500 + US + +00-80-F5 (hex) Quantel Ltd +0080F5 (base 16) Quantel Ltd + Turnpike Road + Newbury Berkshire RG14 2NX + GB + +00-80-B9 (hex) ARCHE TECHNOLIGIES INC. +0080B9 (base 16) ARCHE TECHNOLIGIES INC. + 48502 KATO ROAD + FREMONT CA 94538 + US + +00-40-63 (hex) VIA TECHNOLOGIES, INC. +004063 (base 16) VIA TECHNOLOGIES, INC. + 5020 BRANDIN COURT + FREMONT CA 94538 + US + +00-80-8A (hex) SUMMIT MICROSYSTEMS CORP. +00808A (base 16) SUMMIT MICROSYSTEMS CORP. + 710 LAKEWAY-STE.#150 + SUNNYVALE CA 940867 + US + +00-80-A7 (hex) Honeywell International Inc +0080A7 (base 16) Honeywell International Inc + Vancouver Center of Excellence + North Vancouver V7J 3S4 + CA + +00-80-66 (hex) ARCOM CONTROL SYSTEMS, LTD. +008066 (base 16) ARCOM CONTROL SYSTEMS, LTD. + UNIT 8, CLIFTON ROAD + UNITED KINGDOM + GB + +00-80-CB (hex) FALCO DATA PRODUCTS +0080CB (base 16) FALCO DATA PRODUCTS + 440 POTRERO AVENUE + SUNNYVALE CA 94086-4196 + US + +00-80-07 (hex) DLOG NC-SYSTEME +008007 (base 16) DLOG NC-SYSTEME + WERNER-VON-SIEMENS STRASSE 13 + GERMANY + + +00-80-62 (hex) INTERFACE CO. +008062 (base 16) INTERFACE CO. + 8-26 OZU 5-CHOME MINAMI-KU + + JP + +00-80-1E (hex) XINETRON, INC. +00801E (base 16) XINETRON, INC. + 2330 B. WALSH AVE. + SANTA CLARA CA 95051 + US + +00-80-E2 (hex) T.D.I. CO., LTD. +0080E2 (base 16) T.D.I. CO., LTD. + DEVELOPMENT DIV. #3 FUJI BLDG + + JP + +00-80-49 (hex) NISSIN ELECTRIC CO., LTD. +008049 (base 16) NISSIN ELECTRIC CO., LTD. + 47, UMEZU - TAKASE - CHO + + JP + +00-80-C1 (hex) LANEX CORPORATION +0080C1 (base 16) LANEX CORPORATION + 10727 TUCKER STREET + BELTSVILLE MD 20705 + US + +00-80-A3 (hex) Lantronix +0080A3 (base 16) Lantronix + 15353 Barranca Parkway + Irvine CA 92618 + US + +00-80-BC (hex) HITACHI ENGINEERING CO., LTD +0080BC (base 16) HITACHI ENGINEERING CO., LTD + 4-8-26, OMIKACHO + + JP + +00-80-36 (hex) REFLEX MANUFACTURING SYSTEMS +008036 (base 16) REFLEX MANUFACTURING SYSTEMS + UNIT D, THE FLEMING CENTRE, + ENGLAND + GB + +00-80-83 (hex) AMDAHL +008083 (base 16) AMDAHL + 1250 EAST ARQUES AVENUE + SUNNYVALE CA 94088-3470 + US + +00-80-B8 (hex) DMG MORI B.U.G. CO., LTD. +0080B8 (base 16) DMG MORI B.U.G. CO., LTD. + 1-1-14 Techno park, + Shimonopporo, Atsubetsuku, Sapporo Hokkaido 004-0015 + JP + +00-80-4D (hex) CYCLONE MICROSYSTEMS, INC. +00804D (base 16) CYCLONE MICROSYSTEMS, INC. + 25 SCIENCE PARK + NEW HAVEN CT 06511 + US + +00-80-D4 (hex) CHASE RESEARCH LTD. +0080D4 (base 16) CHASE RESEARCH LTD. + 7 CHINEHAM BUSINESS PARK + ENGLAND + GB + +00-80-3D (hex) SURIGIKEN CO., LTD. +00803D (base 16) SURIGIKEN CO., LTD. + YOUTH BLDG, 4-1-9 SHINJUKU + + JP + +00-80-8B (hex) DACOLL LIMITED +00808B (base 16) DACOLL LIMITED + DACOLL HOUSE, GARDNERS LANE + SCOTLAND EH48 1TP + GB + +00-80-B2 (hex) NETWORK EQUIPMENT TECHNOLOGIES +0080B2 (base 16) NETWORK EQUIPMENT TECHNOLOGIES + 6900 PASEO PADRE PARKWAY + FREMONT CA 94555 + US + +00-80-76 (hex) MCNC +008076 (base 16) MCNC + P.O. BOX 12889 + RTP NC 27709 + US + +00-80-0B (hex) CSK CORPORATION +00800B (base 16) CSK CORPORATION + 18F MATSUSHITA IMP BLDG, + JAPAN 540 + JP + +00-80-18 (hex) KOBE STEEL, LTD. +008018 (base 16) KOBE STEEL, LTD. + KOBE ISUZU RECRUIT BLDG. + + JP + +00-80-68 (hex) YAMATECH SCIENTIFIC LTD. +008068 (base 16) YAMATECH SCIENTIFIC LTD. + 1255 LAIRD, SUITE 260 + + CA + +00-80-A8 (hex) VITACOM CORPORATION +0080A8 (base 16) VITACOM CORPORATION + 1330 CHARLESTON ROAD + MOUNTAIN VIEW CA 94043 + US + +00-80-33 (hex) EMS Aviation, Inc. +008033 (base 16) EMS Aviation, Inc. + 121 WHITTENDALE DRIVE + MOORESTOWN NJ 08057 + US + +00-80-7C (hex) FIBERCOM, INC. +00807C (base 16) FIBERCOM, INC. + 3353 ORANGE AVENUE NE + ROANOKE VA 24012 + US + +00-80-91 (hex) TOKYO ELECTRIC CO.,LTD +008091 (base 16) TOKYO ELECTRIC CO.,LTD + 10-14 UCHIKANDA + TOKYO JAPAN 101 + JP + +00-00-8E (hex) SOLBOURNE COMPUTER, INC. +00008E (base 16) SOLBOURNE COMPUTER, INC. + 1900 PIKE ROAD + LONGMONT COLORADO 80501 + US + +00-00-DC (hex) HAYES MICROCOMPUTER PRODUCTS +0000DC (base 16) HAYES MICROCOMPUTER PRODUCTS + P.O. BOX 105203 + ATLANTA GA 30348 + US + +00-00-63 (hex) BARCO CONTROL ROOMS GMBH +000063 (base 16) BARCO CONTROL ROOMS GMBH + An der Rossweid 5 + Karlsruhe D-76229 + DE + +00-00-4E (hex) AMPEX CORPORATION +00004E (base 16) AMPEX CORPORATION + 581 CONFERENCE PLACE + GOLDEN CO 80401 + US + +00-00-BD (hex) Mitsubishi Cable Industries, Ltd. / Ryosei Systems +0000BD (base 16) Mitsubishi Cable Industries, Ltd. / Ryosei Systems + 8, NISHINO-CHO, HIGASHI-MUKOJIMA + AMAGASAKI HYOGO 660-0856 + JP + +00-00-2E (hex) SOCIETE EVIRA +00002E (base 16) SOCIETE EVIRA + ZONE PORTUAIRE DE BREGAILLON + + FR + +00-00-3F (hex) SYNTREX, INC. +00003F (base 16) SYNTREX, INC. + 246 INDUSTRIAL WAY WEST + EATONTOWN NJ 07724 + US + +00-80-9D (hex) Commscraft Ltd. +00809D (base 16) Commscraft Ltd. + PO BOX 160 + + AU + +00-80-F4 (hex) TELEMECANIQUE ELECTRIQUE +0080F4 (base 16) TELEMECANIQUE ELECTRIQUE + 33 BIS AVENUE, + + FR + +00-80-22 (hex) SCAN-OPTICS +008022 (base 16) SCAN-OPTICS + 201 TECHNOLOGY DRIVE + IRVINE CA 92718 + US + +00-00-CD (hex) Allied Telesis Labs Ltd +0000CD (base 16) Allied Telesis Labs Ltd + 27 Nazareth Avenue + Middleton Christchurch 8024 + NZ + +00-80-DD (hex) GMX INC/GIMIX +0080DD (base 16) GMX INC/GIMIX + 3223 ARNOLD LANE + NORTHBROOK IL 60062-2406 + US + +00-80-FB (hex) BVM LIMITED +0080FB (base 16) BVM LIMITED + Lakeside House, Brickyard Road, + Swanmore SOUTHAMPTON SO32 2SA + GB + +00-80-B4 (hex) SOPHIA SYSTEMS +0080B4 (base 16) SOPHIA SYSTEMS + 3337 KIFER ROAD + SANTA CLARA CA 95051 + US + +00-80-7F (hex) DY-4 INCORPORATED +00807F (base 16) DY-4 INCORPORATED + 333 PALLADIUM DRIVE, MS 312 + + CA + +00-80-2D (hex) XYLOGICS INC +00802D (base 16) XYLOGICS INC + 53 THIRD AVENUE + BURLINGTON MA 01803 + US + +00-00-61 (hex) GATEWAY COMMUNICATIONS +000061 (base 16) GATEWAY COMMUNICATIONS + 2941 ALTON AVENUE + IRVINE CA 92714 + US + +00-00-EA (hex) UPNOD AB +0000EA (base 16) UPNOD AB + BOX 23051 + + SE + +00-00-43 (hex) MICRO TECHNOLOGY +000043 (base 16) MICRO TECHNOLOGY + 4905 EAST LAPALMA + ANAHEIM CA 92807 + US + +00-00-17 (hex) Oracle +000017 (base 16) Oracle + 4200 Network Circle + Santa Clara CA 95054 + US + +00-00-B2 (hex) TELEVIDEO SYSTEMS, INC. +0000B2 (base 16) TELEVIDEO SYSTEMS, INC. + 550 E. BROKAW ROAD + SAN JOSE CA 95161-9048 + US + +00-00-EE (hex) NETWORK DESIGNERS, LTD. +0000EE (base 16) NETWORK DESIGNERS, LTD. + UNIT 1A, HORNBEAM PARK + UNITED KINGDOM HG2 8QT + GB + +00-00-E5 (hex) SIGMEX LTD. +0000E5 (base 16) SIGMEX LTD. + SIGMA HOUSE + RH12 4UZ ENGLAND + GB + +00-00-89 (hex) CAYMAN SYSTEMS INC. +000089 (base 16) CAYMAN SYSTEMS INC. + 26 LANSDOWNE STREET + CAMBRIDGE MA 02139 + US + +00-00-FF (hex) CAMTEC ELECTRONICS LTD. +0000FF (base 16) CAMTEC ELECTRONICS LTD. + 101 VAUGHAN WAY + ENGLAND + GB + +00-00-B7 (hex) DOVE COMPUTER CORPORATION +0000B7 (base 16) DOVE COMPUTER CORPORATION + 1200 NORTH 23RD STREET + WILMINGTON NC 28405 + US + +00-00-F2 (hex) SPIDER COMMUNICATIONS +0000F2 (base 16) SPIDER COMMUNICATIONS + 7491 BRIAR ROAD + + CA + +00-00-CC (hex) DENSAN CO., LTD. +0000CC (base 16) DENSAN CO., LTD. + 1-23-11, KAMITAKAIDO + + JP + +00-00-A4 (hex) ACORN COMPUTERS LIMITED +0000A4 (base 16) ACORN COMPUTERS LIMITED + FULBOURN ROAD, CHERRY HINTON + ENGLAND + GB + +00-00-DB (hex) British Telecommunications plc +0000DB (base 16) British Telecommunications plc + 81 New Gate St + England + GB + +00-00-C1 (hex) Madge Ltd. +0000C1 (base 16) Madge Ltd. + Madge House + Maindenhead Berkshire SL6 2HP + GB + +00-00-F6 (hex) APPLIED MICROSYSTEMS CORP. +0000F6 (base 16) APPLIED MICROSYSTEMS CORP. + 5020 148 AVENUE, N.E. + REDMOND WA 98073-9702 + US + +00-00-77 (hex) INTERPHASE CORPORATION +000077 (base 16) INTERPHASE CORPORATION + 13800 SENLAC + DALLAS TX 75234 + US + +00-00-A2 (hex) Bay Networks +0000A2 (base 16) Bay Networks + PO Box 58185 + Santa Clara CA 95052-8185 + US + +00-00-EC (hex) MICROPROCESS +0000EC (base 16) MICROPROCESS + 97 BIS, RUE DE COLOMBES + + FR + +00-00-C2 (hex) INFORMATION PRESENTATION TECH. +0000C2 (base 16) INFORMATION PRESENTATION TECH. + 23801 CALABASAS ROAD + CALABASAS CA 91302 + US + +00-00-FC (hex) MEIKO +0000FC (base 16) MEIKO + 650 AZTEC WEST + UNITED KINGDOM + GB + +00-00-6D (hex) CRAY COMMUNICATIONS, LTD. +00006D (base 16) CRAY COMMUNICATIONS, LTD. + P.O. BOX 254, CAXTON WAY + UNITED KINGDOM + GB + +00-00-DA (hex) ATEX +0000DA (base 16) ATEX + 15 CROSBY DRIVE + BEDFORD MA 01730 + US + +00-00-DD (hex) TCL INCORPORATED +0000DD (base 16) TCL INCORPORATED + 41829 ALBRAE STREET + FREMONT CA 94538 + US + +00-00-AE (hex) DASSAULT ELECTRONIQUE +0000AE (base 16) DASSAULT ELECTRONIQUE + 55, QUAI MARCEL DASSAULT + + FR + +00-00-A0 (hex) SANYO Electric Co., Ltd. +0000A0 (base 16) SANYO Electric Co., Ltd. + 5-5, Keihan-hondori 2-chome, + Moriguchi City Osaka 570-8677 + JP + +00-00-C0 (hex) WESTERN DIGITAL CORPORATION +0000C0 (base 16) WESTERN DIGITAL CORPORATION + 8105 IRVINE CENTER DRIVE + IRVINE CA 92718 + US + +00-00-33 (hex) EGAN MACHINERY COMPANY +000033 (base 16) EGAN MACHINERY COMPANY + SOUTH ADAMSVILLE ROAD + SOMMERVILLE NJ 08876 + US + +00-00-9D (hex) LOCUS COMPUTING CORPORATION +00009D (base 16) LOCUS COMPUTING CORPORATION + 9800 LA CIENEGA + INGLEWOOD CA 90301 + US + +00-00-FD (hex) HIGH LEVEL HARDWARE +0000FD (base 16) HIGH LEVEL HARDWARE + PO BOX 170 WINDMILL ROAD + ENGLAND + GB + +00-00-65 (hex) Network General Corporation +000065 (base 16) Network General Corporation + 178 E Tsaman Dr + San Jose CA 95134 + US + +00-00-11 (hex) NORMEREL SYSTEMES +000011 (base 16) NORMEREL SYSTEMES + 58 RUE POTTIER + + FR + +00-00-10 (hex) SYTEK INC. +000010 (base 16) SYTEK INC. + 1225 CHARLESTON ROAD + MOUNTAIN VIEW CA 94043 + US + +00-00-BC (hex) Rockwell Automation +0000BC (base 16) Rockwell Automation + 1 Allen-Bradley Dr. + Mayfield Heights OH 44124-6118 + US + +08-00-7E (hex) AMALGAMATED WIRELESS(AUS) LTD +08007E (base 16) AMALGAMATED WIRELESS(AUS) LTD + NORTH RYDE DIVISION + AUSTRALIA 2113 + AU + +08-00-7F (hex) CARNEGIE-MELLON UNIVERSITY +08007F (base 16) CARNEGIE-MELLON UNIVERSITY + INFORMATION TECHNOLOGY + PITTSBURGE PA 15213 + US + +00-00-99 (hex) MTX, INC. +000099 (base 16) MTX, INC. + 3301 TERMINAL DRIVE + RALEIGH NC 27604 + US + +00-00-C4 (hex) WATERS DIV. OF MILLIPORE +0000C4 (base 16) WATERS DIV. OF MILLIPORE + 34 MAPLE STREET + MILFORD MA 01757 + US + +00-00-EB (hex) MATSUSHITA COMM. IND. CO. LTD. +0000EB (base 16) MATSUSHITA COMM. IND. CO. LTD. + 3-1 4-CHOME + + JP + +00-00-28 (hex) PRODIGY SYSTEMS CORPORATION +000028 (base 16) PRODIGY SYSTEMS CORPORATION + 2601 CASEY DRIVE + MOUNTAIN VIEW CA 94043 + US + +08-00-3B (hex) TORUS SYSTEMS LIMITED +08003B (base 16) TORUS SYSTEMS LIMITED + SCIENCE PARK + UNITED KINGDOM + GB + +08-00-3C (hex) SCHLUMBERGER WELL SERVICES +08003C (base 16) SCHLUMBERGER WELL SERVICES + AUSTIN ENGINEERING SERVICES + AUSTIN TX 78720-0015 + US + +08-00-34 (hex) FILENET CORPORATION +080034 (base 16) FILENET CORPORATION + 1575 CORPORATE DRIVE + COSTA MESA CA 92626 + US + +08-00-36 (hex) INTERGRAPH CORPORATION +080036 (base 16) INTERGRAPH CORPORATION + ONE MADISON INDUSTRIAL PARK + HUNTSVILLE AL 35807 + US + +08-00-33 (hex) BAUSCH & LOMB +080033 (base 16) BAUSCH & LOMB + INTERACTIVE GRAPHICS DIVISION + AUSITN TX 78671 + US + +08-00-48 (hex) EUROTHERM GAUGING SYSTEMS +080048 (base 16) EUROTHERM GAUGING SYSTEMS + 900 MIDDLESEX TURNPIKE, BDG. 6 + BILLERICA MA 01821 + US + +08-00-43 (hex) PIXEL COMPUTER INC. +080043 (base 16) PIXEL COMPUTER INC. + 260 FORDHAM ROAD + WILMINGTON MA 01887 + US + +08-00-45 (hex) CONCURRENT COMPUTER CORP. +080045 (base 16) CONCURRENT COMPUTER CORP. + 2 CRESCENT PLACE + OCEANPORT NJ 07757 + US + +08-00-78 (hex) ACCELL CORPORATION +080078 (base 16) ACCELL CORPORATION + 50 SAGINAW DRIVE + ROCHESTER NY 14623 + US + +08-00-6D (hex) WHITECHAPEL COMPUTER WORKS +08006D (base 16) WHITECHAPEL COMPUTER WORKS + 75 WHITECHAPEL ROAD + LONDON E1 1DU + GB + +08-00-30 (hex) NETWORK RESEARCH CORPORATION +080030 (base 16) NETWORK RESEARCH CORPORATION + 2380 N. ROSE AVENUE + OXNARD CA 93010 + US + +08-00-31 (hex) LITTLE MACHINES INC. +080031 (base 16) LITTLE MACHINES INC. + 4141 JUTLAND DRIVE + SAN DIEGO CA 92117 + US + +08-00-2E (hex) METAPHOR COMPUTER SYSTEMS +08002E (base 16) METAPHOR COMPUTER SYSTEMS + 2500 GARCIA AVENUE + MOUNTAIN VIEW CA 94043 + US + +08-00-56 (hex) STANFORD LINEAR ACCEL. CENTER +080056 (base 16) STANFORD LINEAR ACCEL. CENTER + 2575 SANDHILL ROAD + MENLO PARK CA 94025 + US + +08-00-4F (hex) CYGNET SYSTEMS +08004F (base 16) CYGNET SYSTEMS + 2560 JUNCTION AVENUE + SAN JOSE CA 95134 + US + +08-00-50 (hex) DAISY SYSTEMS CORP. +080050 (base 16) DAISY SYSTEMS CORP. + 139 KIFER COURT + SUNNYVALE CA 94086 + US + +08-00-5E (hex) COUNTERPOINT COMPUTER INC. +08005E (base 16) COUNTERPOINT COMPUTER INC. + 2127 RINGWOOD AVENUE + SAN JOSE CA 95131 + US + +08-00-76 (hex) PC LAN TECHNOLOGIES +080076 (base 16) PC LAN TECHNOLOGIES + 5780 LINCOLN DRIVE SUITE 106 + MINNEAPOLIS MN 55436 + US + +08-00-75 (hex) DANSK DATA ELECTRONIK +080075 (base 16) DANSK DATA ELECTRONIK + HERLEV HOVEDGADE 199 + + DK + +08-00-2B (hex) DIGITAL EQUIPMENT CORPORATION +08002B (base 16) DIGITAL EQUIPMENT CORPORATION + LKG 1-2/A19 + LITTLETON MA 01460-1289 + US + +08-00-29 (hex) Megatek Corporation +080029 (base 16) Megatek Corporation + 16868 Via Del Campo Court + San Diego CA 92127 + US + +02-70-B0 (hex) M/A-COM INC. COMPANIES +0270B0 (base 16) M/A-COM INC. COMPANIES + 11717 EXPLORATION LANE + GERMANTOWN MD 20767 + US + +00-00-53 (hex) COMPUCORP +000053 (base 16) COMPUCORP + 2211 MICHIGAN AVENUE + SANTA MONICA CA 90404 + US + +08-00-90 (hex) SONOMA SYSTEMS +080090 (base 16) SONOMA SYSTEMS + 4640 ADMIRALTY WAY, STE. #600 + MARINA DEL REY CA 90292-6695 + US + +08-00-0A (hex) NESTAR SYSTEMS INCORPORATED +08000A (base 16) NESTAR SYSTEMS INCORPORATED + 2585 EAST BAYSHORE ROAD + PALO ALTO CA 94303 + US + +00-80-0F (hex) STANDARD MICROSYSTEMS +00800F (base 16) STANDARD MICROSYSTEMS + 300 KENNEDY DRIVE + HAUPPAUGE NY 11788 + US + +00-40-6B (hex) SYSGEN +00406B (base 16) SYSGEN + 556 GIBRALTAR DRIVE + MILPITAS CA 95035 + US + +08-00-0F (hex) MITEL CORPORATION +08000F (base 16) MITEL CORPORATION + 350 LEGGET DRIVE + CANADA K2K 1X3 + CA + +08-00-23 (hex) Panasonic Communications Co., Ltd. +080023 (base 16) Panasonic Communications Co., Ltd. + 4-1-62 Minoshima Hakata Fukuoka + 812-8531 + JP + +B0-4F-C3 (hex) Shenzhen NVC Cloud Technology Co., Ltd. +B04FC3 (base 16) Shenzhen NVC Cloud Technology Co., Ltd. + Rm. 1406, Bld. 11A, Shenzhen Bay Eco-Technology Park, Nanshan Dist., + Shenzhen Guangdong 518063 + CN + +08-00-1C (hex) KDD-KOKUSAI DEBNSIN DENWA CO. +08001C (base 16) KDD-KOKUSAI DEBNSIN DENWA CO. + FUJI XEROX CO., LTD. TELEGRAPH + 107 + JP + +00-DD-0C (hex) UNGERMANN-BASS INC. +00DD0C (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +08-00-18 (hex) PIRELLI FOCOM NETWORKS +080018 (base 16) PIRELLI FOCOM NETWORKS + DENTON DRIVE + ENGLAND + GB + +00-00-A6 (hex) NETWORK GENERAL CORPORATION +0000A6 (base 16) NETWORK GENERAL CORPORATION + 1296 B LAWRENCE STATION ROAD + SUNNYVALE CA 94089 + US + +00-BB-F0 (hex) UNGERMANN-BASS INC. +00BBF0 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +00-40-8E (hex) Tattile SRL +00408E (base 16) Tattile SRL + 2360 MARYLAND ROAD + WILLOW GROVE PA 19090 + US + +00-00-04 (hex) XEROX CORPORATION +000004 (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +00-DD-0E (hex) UNGERMANN-BASS INC. +00DD0E (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +88-57-1D (hex) Seongji Industry Company +88571D (base 16) Seongji Industry Company + 54-33, Dongtanhana 1-gil + Hwaseong-si Gyeonggi-do 18423 + KR + +7C-F3-1B (hex) LG Electronics (Mobile Communications) +7CF31B (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-01-C8 (hex) THOMAS CONRAD CORP. +0001C8 (base 16) THOMAS CONRAD CORP. + 1908-R KRAMER LANE + AUSTIN TX 78758 + US + +CC-EF-03 (hex) Hunan Keyshare Communication Technology Co., Ltd. +CCEF03 (base 16) Hunan Keyshare Communication Technology Co., Ltd. + No. 19 Building, CEC Software Park, No. 39 jianshan Rd + Changsha Hunan 410205 + CN + +10-2F-A3 (hex) Shenzhen Uvision-tech Technology Co.Ltd +102FA3 (base 16) Shenzhen Uvision-tech Technology Co.Ltd + shenzhen longhua Street + shenzhen GuangDong 518000 + CN + +70-48-F7 (hex) Nintendo Co.,Ltd +7048F7 (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +18-E1-CA (hex) wanze +18E1CA (base 16) wanze + wanjinglu + dandong Liaoning 118000 + CN + +EC-BE-DD (hex) Sagemcom Broadband SAS +ECBEDD (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +00-C0-B6 (hex) HVE, Inc. +00C0B6 (base 16) HVE, Inc. + Suite 2, 100 Executive Court + Waxahachie TX 75165 + US + +30-91-76 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +309176 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +78-C8-81 (hex) Sony Interactive Entertainment Inc. +78C881 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +D4-4F-68 (hex) Eidetic Communications Inc +D44F68 (base 16) Eidetic Communications Inc + 3553 31st NW + Calgary Alberta T2L2K7 + CA + +74-9E-A5 (hex) OHSUNG +749EA5 (base 16) OHSUNG + 335-4,SANHODAERO,GUMI,GYEONG BUK,KOREA + GUMI GYEONG BUK 730-030 + KR + +34-0F-66 (hex) MicroArx Corporation +340F66 (base 16) MicroArx Corporation + P.O. Box 692 + Hanover NH 03755 + US + +8C-C8-4B (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +8CC84B (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +0C-2F-B0 (hex) Samsung Electronics Co.,Ltd +0C2FB0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B4-02-16 (hex) Cisco Systems, Inc +B40216 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +54-A4-93 (hex) IEEE Registration Authority +54A493 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +6C-1C-71 (hex) Zhejiang Dahua Technology Co., Ltd. +6C1C71 (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199,Waterfront Road + Hangzhou Zhejiang 310053 + CN + +CC-6A-10 (hex) The Chamberlain Group, Inc +CC6A10 (base 16) The Chamberlain Group, Inc + 300 Windsor Drive + Oak Brook IL 60523 + US + +F0-3F-95 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F03F95 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-56-44 (hex) HUAWEI TECHNOLOGIES CO.,LTD +185644 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +9C-69-D1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +9C69D1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-5A-58 (hex) Dell Inc. +185A58 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +C4-3A-35 (hex) FN-LINK TECHNOLOGY LIMITED +C43A35 (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +04-D1-6E (hex) IEEE Registration Authority +04D16E (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +04-0E-3C (hex) HP Inc. +040E3C (base 16) HP Inc. + 10300 Energy Dr + Spring TX 77389 + US + +C4-E0-DE (hex) Zhengzhou XindaJiean Information Technology Co.,Ltd. +C4E0DE (base 16) Zhengzhou XindaJiean Information Technology Co.,Ltd. + Tianli building A, wisdom park, no. 139, yangjin road, jinshui district + Zhengzhou Henan 450003 + CN + +90-1A-4F (hex) EM Microelectronic +901A4F (base 16) EM Microelectronic + Rue des Sors 3 + Marin-Epagnier Neuchatel 2074 + CH + +C8-4F-0E (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +C84F0E (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +6C-D2-BA (hex) zte corporation +6CD2BA (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +30-3A-BA (hex) Guangzhou BaoLun Electronics Co., Ltd +303ABA (base 16) Guangzhou BaoLun Electronics Co., Ltd + No.1 Building B Block, Zhongcun Street, Panyu District + Guangzhou guangdong 511400 + CN + +D8-8A-DC (hex) Huawei Device Co., Ltd. +D88ADC (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +10-E9-53 (hex) Huawei Device Co., Ltd. +10E953 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +7C-48-B2 (hex) Vida Resources Lte Ltd +7C48B2 (base 16) Vida Resources Lte Ltd + 10 Anson road, unit #16-20 International Plaza + Singapore 079903 + SG + +2C-AB-33 (hex) Texas Instruments +2CAB33 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +B8-87-C6 (hex) Prudential Technology co.,LTD +B887C6 (base 16) Prudential Technology co.,LTD + UNIT 4,7/F BRIGHT WAY TOWER, NO33 MONG KOK RD, + Hong Kong 999077 + CN + +EC-9C-32 (hex) Sichuan AI-Link Technology Co., Ltd. +EC9C32 (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou,Industrial Park + Anzhou,Industrial Park Sichuan 621000 + CN + +4C-AD-A8 (hex) PANOPTICS CORP. +4CADA8 (base 16) PANOPTICS CORP. + D-908 Bundang Technopark, 700 Pangyoro, Bundang + Seongnam Gyeonggi 13516 + KR + +FC-1C-A1 (hex) Nokia +FC1CA1 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +D4-2D-C5 (hex) Panasonic i-PRO Sensing Solutions Co., Ltd. +D42DC5 (base 16) Panasonic i-PRO Sensing Solutions Co., Ltd. + 4-1-62 Minoshima, Hakata-ku + Fukuoka City 812-8531 + JP + +E8-D0-3C (hex) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd +E8D03C (base 16) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + 3/F,A5 Building Zhiyuan Community No.1001,Xueyuan Road Nanshan District + Shenzhen Guangdong 518055 + CN + +1C-1A-DF (hex) Microsoft Corporation +1C1ADF (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +D4-F5-47 (hex) Google, Inc. +D4F547 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +98-1B-B5 (hex) ASSA ABLOY Korea Co., Ltd iRevo +981BB5 (base 16) ASSA ABLOY Korea Co., Ltd iRevo + 10F of JEI PLATZ Bldg., 186, Gasandigital-ro, Geumcheon-gu + Seoul 08502 + KR + +34-CB-1A (hex) Procter & Gamble Company +34CB1A (base 16) Procter & Gamble Company + 2 Procter & Gamble Plaza + Cincinnati OH 45202 + US + +F0-B1-07 (hex) Ericsson AB +F0B107 (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +78-4F-9B (hex) Juniper Networks +784F9B (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +78-3A-6C (hex) TECNO MOBILE LIMITED +783A6C (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +E0-40-07 (hex) Huawei Device Co., Ltd. +E04007 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +38-3F-B3 (hex) Technicolor CH USA Inc. +383FB3 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +70-CE-8C (hex) Samsung Electronics Co.,Ltd +70CE8C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +40-70-F5 (hex) Apple, Inc. +4070F5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B0-35-B5 (hex) Apple, Inc. +B035B5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-AF-D1 (hex) netKTI Co., Ltd +90AFD1 (base 16) netKTI Co., Ltd + 7-10F THE-ONE SQUARE, 135, Unjung-ro, Bundang-gu + Seongnam-si Gyeonggi-do 13461 + KR + +80-0C-67 (hex) Apple, Inc. +800C67 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-81-2A (hex) Apple, Inc. +90812A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-17-BE (hex) HUAWEI TECHNOLOGIES CO.,LTD +7817BE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F0-72-EA (hex) Google, Inc. +F072EA (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +B8-7B-C5 (hex) Apple, Inc. +B87BC5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-51-36 (hex) TCT mobile ltd +F05136 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +10-59-32 (hex) Roku, Inc +105932 (base 16) Roku, Inc + 150 Winchester Circle + Los Gatos CA 95032 + US + +20-74-54 (hex) vivo Mobile Communication Co., Ltd. +207454 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +B8-C9-B5 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +B8C9B5 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +88-AC-C0 (hex) Zyxel Communications Corporation +88ACC0 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +90-FD-73 (hex) zte corporation +90FD73 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +1C-1E-38 (hex) PCCW Global, Inc. +1C1E38 (base 16) PCCW Global, Inc. + 475 Spring Park Pl Suite 100 Herndon VA 20170 + Herndon WA 20170 + US + +3C-41-0E (hex) Cisco Systems, Inc +3C410E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +88-D9-8F (hex) Juniper Networks +88D98F (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-45-E2 (hex) CyberTAN Technology Inc. +0045E2 (base 16) CyberTAN Technology Inc. + 99 Park Ave III, Hsinchu Science Park + Hsinchu 308 + TW + +00-69-67 (hex) IEEE Registration Authority +006967 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F8-6F-DE (hex) Shenzhen Goodix Technology Co.,Ltd. +F86FDE (base 16) Shenzhen Goodix Technology Co.,Ltd. + F13,Phase B,Tengfei Industrial Building,Futian Free Trade Zone,Shenzhen,China + Shenzhen Guangdong 518045 + CN + +98-DF-82 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +98DF82 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +64-66-24 (hex) Sagemcom Broadband SAS +646624 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +B0-F5-30 (hex) Hitron Technologies. Inc +B0F530 (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +74-0A-E1 (hex) Huawei Device Co., Ltd. +740AE1 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +B4-A8-98 (hex) Huawei Device Co., Ltd. +B4A898 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +0C-E4-A0 (hex) Huawei Device Co., Ltd. +0CE4A0 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +BC-1A-E4 (hex) Huawei Device Co., Ltd. +BC1AE4 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +04-3F-72 (hex) Mellanox Technologies, Inc. +043F72 (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +1C-4D-66 (hex) Amazon Technologies Inc. +1C4D66 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +D8-3B-BF (hex) Intel Corporate +D83BBF (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +50-2C-C6 (hex) GREE ELECTRIC APPLIANCES, INC. OF ZHUHAI +502CC6 (base 16) GREE ELECTRIC APPLIANCES, INC. OF ZHUHAI + Jinji West Road, Qianshan, + Zhuhai Guangdong 519070 + CN + +F4-FE-FB (hex) Samsung Electronics Co.,Ltd +F4FEFB (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +98-49-14 (hex) Wistron Neweb Corporation +984914 (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +0C-EE-99 (hex) Amazon Technologies Inc. +0CEE99 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +00-11-7E (hex) Midmark Corp +00117E (base 16) Midmark Corp + 1001 Asbury Dr + Buffalo Grove IL 60089 + US + +D0-28-BA (hex) Realme Chongqing MobileTelecommunications Corp Ltd +D028BA (base 16) Realme Chongqing MobileTelecommunications Corp Ltd + No.24 Nichang Boulevard, Huixing Block, Yubei District, Chongqing. + Chongqing China 401120 + CN + +A4-28-B7 (hex) Yangtze Memory Technologies Co., Ltd. +A428B7 (base 16) Yangtze Memory Technologies Co., Ltd. + No.88 Weilai 3rd Road, East Lake High-tech Development Zone, Wuhan, Hubei, POC + Wuhan Hubei 430078 + CN + +94-92-D2 (hex) KCF Technologies, Inc. +9492D2 (base 16) KCF Technologies, Inc. + 336 S Fraser Street + State College PA 16801 + US + +E4-A8-DF (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +E4A8DF (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +8C-53-C3 (hex) Beijing Xiaomi Mobile Software Co., Ltd +8C53C3 (base 16) Beijing Xiaomi Mobile Software Co., Ltd + The Rainbow City Office Building, 68 Qinghe Middle Street Haidian District + Beijing Beijing 100085 + CN + +70-2F-35 (hex) HUAWEI TECHNOLOGIES CO.,LTD +702F35 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C0-14-B8 (hex) Nokia +C014B8 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +00-76-3D (hex) Veea +00763D (base 16) Veea + 164 E 83rd Street + New York NY 10028 + US + +30-93-BC (hex) Sagemcom Broadband SAS +3093BC (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +FC-F5-C4 (hex) Espressif Inc. +FCF5C4 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +E8-26-B6 (hex) Inside Biometrics International Limited +E826B6 (base 16) Inside Biometrics International Limited + Strathpeffer Road + Dingwall Scotland IV159QF + GB + +54-CE-69 (hex) Hikari Trading Co.,Ltd. +54CE69 (base 16) Hikari Trading Co.,Ltd. + Hikari Building,7-4-14,Ginza,Chuo-ku + Tokyo 104-0061 + JP + +6C-C6-3B (hex) Taicang T&W Electronics +6CC63B (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +58-8E-81 (hex) Silicon Laboratories +588E81 (base 16) Silicon Laboratories + 7000 W. William Cannon Dr. + Austin TX 78735 + US + +48-B0-2D (hex) NVIDIA Corporation +48B02D (base 16) NVIDIA Corporation + 2701 San Tomas Expressway + Santa Clara CA 95050 + US + +4C-E1-76 (hex) Cisco Systems, Inc +4CE176 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +6C-AE-F6 (hex) eero inc. +6CAEF6 (base 16) eero inc. + 660 3rd Street + San Francisco CA 94107 + US + +FC-8E-6E (hex) StreamCCTV, LLC +FC8E6E (base 16) StreamCCTV, LLC + 1129 Northern Blvd, STE. 404 + Manhasset 11030 + US + +E0-2A-E6 (hex) Fiberhome Telecommunication Technologies Co.,LTD +E02AE6 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +64-12-36 (hex) Technicolor CH USA Inc. +641236 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +78-8B-2A (hex) Zhen Shi Information Technology (Shanghai) Co., Ltd. +788B2A (base 16) Zhen Shi Information Technology (Shanghai) Co., Ltd. + 5F, Building 3?No. 401 Caobao Road, Xuhui District, Shanghai, China + Shanghai Shanghai 200233 + CN + +AC-64-CF (hex) FN-LINK TECHNOLOGY LIMITED +AC64CF (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +F0-67-28 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +F06728 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +BC-D7-67 (hex) Private +BCD767 (base 16) Private + +9C-E1-76 (hex) Cisco Systems, Inc +9CE176 (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +10-29-59 (hex) Apple, Inc. +102959 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-76-84 (hex) Apple, Inc. +E47684 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B4-1A-1D (hex) Samsung Electronics Co.,Ltd +B41A1D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F0-5C-D5 (hex) Apple, Inc. +F05CD5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-F6-D8 (hex) Intel Corporate +14F6D8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +3C-DA-6D (hex) Tiandy Technologies CO.,LTD +3CDA6D (base 16) Tiandy Technologies CO.,LTD + NO.8,haitai huake rd2 (outside ring road),huayuan new technology industrial park + Tianjin Tianjin 300384 + CN + +F8-0D-F0 (hex) zte corporation +F80DF0 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +9C-E9-1C (hex) zte corporation +9CE91C (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +5C-17-CF (hex) OnePlus Technology (Shenzhen) Co., Ltd +5C17CF (base 16) OnePlus Technology (Shenzhen) Co., Ltd + 18C02, 18C03, 18C04 ,18C05,TAIRAN BUILDING, + Shenzhen Guangdong 518000 + CN + +A4-FA-76 (hex) New H3C Technologies Co., Ltd +A4FA76 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +70-EA-5A (hex) Apple, Inc. +70EA5A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-FA-D3 (hex) IEEE Registration Authority +3CFAD3 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +8C-60-78 (hex) Swissbit AG +8C6078 (base 16) Swissbit AG + Industriestrasse 4 + Bronschhofen CH-9552 + CH + +00-DD-25 (hex) Shenzhen hechengdong Technology Co., Ltd +00DD25 (base 16) Shenzhen hechengdong Technology Co., Ltd + 302, floor 3, no.90-5, Dayang Road, Xintian community, Fuhai street, Bao'an District + Shenzhen GuangDong 518100 + CN + +80-20-E1 (hex) BVBA DPTechnics +8020E1 (base 16) BVBA DPTechnics + Westkapellestraat 396/44 + Knokke-Heist West-Vlaanderen 8300 + BE + +04-45-A1 (hex) NIRIT- Xinwei Telecom Technology Co., Ltd. +0445A1 (base 16) NIRIT- Xinwei Telecom Technology Co., Ltd. + 2-? ??????????? ??????, ?.12, ???.2 + Moscow 115432 + RU + +8C-97-EA (hex) FREEBOX SAS +8C97EA (base 16) FREEBOX SAS + 16 rue de la Ville l'Eveque + PARIS IdF 75008 + FR + +30-AB-6A (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +30AB6A (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +74-9B-E8 (hex) Hitron Technologies. Inc +749BE8 (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +5C-BA-EF (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +5CBAEF (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +4C-63-71 (hex) Xiaomi Communications Co Ltd +4C6371 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +D8-4D-B9 (hex) Wu Qi Technologies,Inc. +D84DB9 (base 16) Wu Qi Technologies,Inc. + 14/F, 107 Middle Road, Xiantao Big Data Valley, Yubei District + Chongqing Chongqing 401120 + CN + +A0-4F-85 (hex) LG Electronics (Mobile Communications) +A04F85 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +D8-07-B6 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +D807B6 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +64-6E-97 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +646E97 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +78-50-7C (hex) Juniper Networks +78507C (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-12-58 (hex) TechVoIP Sp z o.o. +001258 (base 16) TechVoIP Sp z o.o. + Os. Boleslawa Chrobrego 117 + Poznan Wielkopolska 60-681 + PL + +6C-16-32 (hex) HUAWEI TECHNOLOGIES CO.,LTD +6C1632 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +2C-1A-01 (hex) HUAWEI TECHNOLOGIES CO.,LTD +2C1A01 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +34-78-39 (hex) zte corporation +347839 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +24-16-9D (hex) Cisco Systems, Inc +24169D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F4-19-E2 (hex) Volterra +F419E2 (base 16) Volterra + 2550 Great America Way #350 + Santa Clara CA 95054 + US + +4C-A0-03 (hex) VITEC +4CA003 (base 16) VITEC + 99 rue Pierre Semard + Chatillon 92320 + FR + +64-F2-FB (hex) Hangzhou Ezviz Software Co.,Ltd. +64F2FB (base 16) Hangzhou Ezviz Software Co.,Ltd. + Room 302, Unit B, Building 2, 399 Danfeng Road,Binjiang District + Hangzhou Zhejiang 310051 + CN + +30-80-9B (hex) New H3C Technologies Co., Ltd +30809B (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +74-22-BB (hex) Huawei Device Co., Ltd. +7422BB (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +6C-0D-34 (hex) Nokia +6C0D34 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +4C-45-76 (hex) China Mobile(Hangzhou) Information Technology Co.,Ltd. +4C4576 (base 16) China Mobile(Hangzhou) Information Technology Co.,Ltd. + No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District + Hangzhou Zhejiang 310000 + CN + +B4-40-A4 (hex) Apple, Inc. +B440A4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-B8-A3 (hex) Apple, Inc. +48B8A3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-DB-E3 (hex) Apple, Inc. +F4DBE3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-42-8C (hex) ALPS ELECTRIC CO., LTD. +BC428C (base 16) ALPS ELECTRIC CO., LTD. + nishida 6-1 + Kakuda-City Miyagi-Pref 981-1595 + JP + +F0-7C-C7 (hex) Juniper Networks +F07CC7 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +D4-5E-EC (hex) Beijing Xiaomi Electronics Co., Ltd. +D45EEC (base 16) Beijing Xiaomi Electronics Co., Ltd. + Building C, QingHe ShunShiJiaYe Technology Park, #66 ZhuFang Rd, HaiDian District + Beijing Beijing 10085 + CN + +74-C9-29 (hex) Zhejiang Dahua Technology Co., Ltd. +74C929 (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199,Waterfront Road + Hangzhou Zhejiang 310053 + CN + +D4-CF-F9 (hex) Shenzhen SEI Robotics Co.,Ltd +D4CFF9 (base 16) Shenzhen SEI Robotics Co.,Ltd + 501,Productivity Building A, #5 Hi-Tech Middle 2nd Road + Shenzhen Guangdong 518057 + CN + +5C-B2-9E (hex) ASCO Power Technologies +5CB29E (base 16) ASCO Power Technologies + 160 Park Avenue + Florham Park NJ 07932 + US + +9C-C9-EB (hex) NETGEAR +9CC9EB (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +94-CC-04 (hex) IEEE Registration Authority +94CC04 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +90-EC-77 (hex) silicom +90EC77 (base 16) silicom + 14 Atir-Yeda St/ + Kfar-Sava Israel 44000 + IL + +88-C3-97 (hex) Beijing Xiaomi Mobile Software Co., Ltd +88C397 (base 16) Beijing Xiaomi Mobile Software Co., Ltd + The Rainbow City Office Building, 68 Qinghe Middle Street Haidian District + Beijing Beijing 100085 + CN + +F0-F6-C1 (hex) Sonos, Inc. +F0F6C1 (base 16) Sonos, Inc. + 614 Chapala St + Santa Barbara CA 93101 + US + +60-68-4E (hex) Samsung Electronics Co.,Ltd +60684E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +80-20-FD (hex) Samsung Electronics Co.,Ltd +8020FD (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B4-CE-40 (hex) Samsung Electronics Co.,Ltd +B4CE40 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-03-84 (hex) Hongkong Nano IC Technologies Co., Ltd +540384 (base 16) Hongkong Nano IC Technologies Co., Ltd + Rm. 19C, Lockhart Ctr., 301-307 Lockhart Rd., Wan Chai, Hong Kong + Hong Kong Hong Kong 999077 + CN + +04-BD-BF (hex) Samsung Electronics Co.,Ltd +04BDBF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +BC-7A-BF (hex) Samsung Electronics Co.,Ltd +BC7ABF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B4-09-31 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B40931 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-E7-EA (hex) HUAWEI TECHNOLOGIES CO.,LTD +94E7EA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-E4-BA (hex) Huawei Device Co., Ltd. +94E4BA (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +34-71-46 (hex) Huawei Device Co., Ltd. +347146 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +2C-C5-46 (hex) Huawei Device Co., Ltd. +2CC546 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +0C-83-9A (hex) Huawei Device Co., Ltd. +0C839A (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +E0-E0-FC (hex) Huawei Device Co., Ltd. +E0E0FC (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +E0-D4-E8 (hex) Intel Corporate +E0D4E8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +30-50-75 (hex) GN Audio A/S +305075 (base 16) GN Audio A/S + Lautrupbjerg 7 + Ballerup DK-2750 + DK + +F4-B7-8D (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4B78D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-16-E7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A416E7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +30-B9-B0 (hex) Intracom Asia Co., Ltd +30B9B0 (base 16) Intracom Asia Co., Ltd + 4F., No77, Sec. 1, Xintai 5th Rd., Xizhi Dist. + New Taipei City Taiwan 221 + TW + +0C-35-FE (hex) Fiberhome Telecommunication Technologies Co.,LTD +0C35FE (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +8C-83-DF (hex) Nokia +8C83DF (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +AC-4B-1E (hex) Integri-Sys.Com LLC +AC4B1E (base 16) Integri-Sys.Com LLC + 9130 South Dadeland Bvld. Suite 1509 + Miami FL 33156 + US + +B0-E4-D5 (hex) Google, Inc. +B0E4D5 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +D4-DA-CD (hex) BSkyB Ltd +D4DACD (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +68-69-CA (hex) Hitachi, Ltd. +6869CA (base 16) Hitachi, Ltd. + 27-18, Minami Oi 6-chome, Shinagawa-ku + Tokyo 140-8572 + JP + +AC-4A-56 (hex) Cisco Systems, Inc +AC4A56 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F4-EA-B5 (hex) Extreme Networks, Inc. +F4EAB5 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +00-19-77 (hex) Extreme Networks, Inc. +001977 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +08-EA-44 (hex) Extreme Networks, Inc. +08EA44 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +B0-B5-C3 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +B0B5C3 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +70-4A-0E (hex) AMPAK Technology,Inc. +704A0E (base 16) AMPAK Technology,Inc. + 3F, No.15-1 Zhonghua Road, Hsinchu Industrail Park, Hukou, + Hsinchu Hsinchu,Taiwan R.O.C. 30352 + TW + +08-30-6B (hex) Palo Alto Networks +08306B (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +00-86-9C (hex) Palo Alto Networks +00869C (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +4C-B9-11 (hex) Raisecom Technology CO.,LTD +4CB911 (base 16) Raisecom Technology CO.,LTD + No. 11, East Area, No. 10 Block, East Xibeiwang Road + Beijing 100094 + CN + +40-47-6A (hex) Astro Gaming +40476A (base 16) Astro Gaming + 340 Bryant St., Suite 101 + San Francisco CA 94107 + US + +4C-CE-2D (hex) Danlaw Inc +4CCE2D (base 16) Danlaw Inc + 23700 research Dr. + Farmington Hills MI 48335 + US + +B8-7C-F2 (hex) Extreme Networks, Inc. +B87CF2 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +9C-FF-C2 (hex) AVI Systems GmbH +9CFFC2 (base 16) AVI Systems GmbH + Dr. Franz Wilhelmstraße 2A + Krems a. d. Donau 3500 + AT + +44-D8-78 (hex) Hui Zhou Gaoshengda Technology Co.,LTD +44D878 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +A0-D8-07 (hex) Huawei Device Co., Ltd. +A0D807 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +2C-78-0E (hex) Huawei Device Co., Ltd. +2C780E (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +34-B2-0A (hex) Huawei Device Co., Ltd. +34B20A (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +98-F4-AB (hex) Espressif Inc. +98F4AB (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +D8-BF-C0 (hex) Espressif Inc. +D8BFC0 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +20-26-81 (hex) TECNO MOBILE LIMITED +202681 (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +F4-D6-20 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +F4D620 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +64-FB-92 (hex) PPC Broadband Inc. +64FB92 (base 16) PPC Broadband Inc. + 6176 E Molloy Rd + East Syracuse NY 13057 + US + +14-13-46 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +141346 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +94-90-34 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD +949034 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + Unit East Block22-24/F,Skyworth semiconductor design Bldg., Gaoxin Ave.4.S.,Nanshan District,Shenzhen,China + SHENZHEN GUANGDONG 518057 + CN + +98-7A-10 (hex) Ericsson AB +987A10 (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +54-2B-DE (hex) New H3C Technologies Co., Ltd +542BDE (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +98-F7-81 (hex) ARRIS Group, Inc. +98F781 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +78-97-C3 (hex) DINGXIN INFORMATION TECHNOLOGY CO.,LTD +7897C3 (base 16) DINGXIN INFORMATION TECHNOLOGY CO.,LTD + No.6 huasui Road,ZhuJiang Xincheng + Guangzhou Guangdong 510623 + CN + +4C-90-DB (hex) JL Audio +4C90DB (base 16) JL Audio + 10369 N Commerce Pkwy + Mirimar FL 33025 + US + +B8-99-AE (hex) Shenzhen MiaoMing Intelligent Technology Co.,Ltd +B899AE (base 16) Shenzhen MiaoMing Intelligent Technology Co.,Ltd + Chudong science and technology park, 111 shaxin road, tangxia town, + dongguan city guangdong province 523710 + CN + +E8-D0-B9 (hex) Taicang T&W Electronics +E8D0B9 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +3C-8F-06 (hex) Shenzhen Libtor Technology Co.,Ltd +3C8F06 (base 16) Shenzhen Libtor Technology Co.,Ltd + Room 608, Building A + Shenzhen City Guangdong Province 518000 + CN + +B0-08-75 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B00875 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +8C-F1-12 (hex) Motorola Mobility LLC, a Lenovo Company +8CF112 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +84-76-37 (hex) HUAWEI TECHNOLOGIES CO.,LTD +847637 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +FC-94-35 (hex) HUAWEI TECHNOLOGIES CO.,LTD +FC9435 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E0-24-81 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E02481 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A8-C0-EA (hex) Pepwave Limited +A8C0EA (base 16) Pepwave Limited + A5, 5/F, HK Spinners Industrial Building, Phase 6, 481 Castle Peak Road + Cheung Sha Wan Hong Kong 0 + HK + +18-2A-D3 (hex) Juniper Networks +182AD3 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +80-B0-7B (hex) zte corporation +80B07B (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +C8-5A-9F (hex) zte corporation +C85A9F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +44-AE-AB (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +44AEAB (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +A4-F0-5E (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +A4F05E (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +1C-68-7E (hex) Shenzhen Qihu Intelligent Technology Company Limited +1C687E (base 16) Shenzhen Qihu Intelligent Technology Company Limited + Room 201, Block A, No.1, Qianwan Road 1,Qianhai Shenzhen HongKong Modern Service Industry Cooperation Zone + Shenzhen Guangdong 518057 + CN + +C0-36-56 (hex) Fiberhome Telecommunication Technologies Co.,LTD +C03656 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +58-85-A2 (hex) Realme Chongqing MobileTelecommunications Corp Ltd +5885A2 (base 16) Realme Chongqing MobileTelecommunications Corp Ltd + No.24 Nichang Boulevard, Huixing Block, Yubei District, Chongqing. + Chongqing China 401120 + CN + +2C-F8-9B (hex) Cisco Systems, Inc +2CF89B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-07-1C (hex) AT&T +00071C (base 16) AT&T + 3300 E Renner Road + Richardson TX 75082 + US + +E0-E8-E6 (hex) Shenzhen C-Data Technology Co., Ltd. +E0E8E6 (base 16) Shenzhen C-Data Technology Co., Ltd. + #601, Fl6, Bldg F, No.1008  Yangguang Community, Xili, Nanshan + Shenzhen Guangdong 518055 + CN + +50-02-91 (hex) Espressif Inc. +500291 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +00-1D-DF (hex) Sunitec Enterprise Co.,Ltd +001DDF (base 16) Sunitec Enterprise Co.,Ltd + 3F., No. 98-1, Mincyuan Rd. + Sindian City Taipei County 231 + TW + +8C-0F-FA (hex) Hutec co.,ltd +8C0FFA (base 16) Hutec co.,ltd + 46, Gunpocheomdansaneop 2-ro + Gunpo-si Gyeonggi-do 15880 + KR + +AC-FE-05 (hex) ITEL MOBILE LIMITED +ACFE05 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +78-2A-79 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +782A79 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +78-65-59 (hex) Sagemcom Broadband SAS +786559 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +50-D2-F5 (hex) Beijing Xiaomi Mobile Software Co., Ltd +50D2F5 (base 16) Beijing Xiaomi Mobile Software Co., Ltd + The Rainbow City Office Building, 68 Qinghe Middle Street Haidian District + Beijing Beijing 100085 + CN + +24-52-6A (hex) Zhejiang Dahua Technology Co., Ltd. +24526A (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199,Waterfront Road + Hangzhou Zhejiang 310053 + CN + +20-DF-B9 (hex) Google, Inc. +20DFB9 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +5C-CA-D3 (hex) CHIPSEA TECHNOLOGIES (SHENZHEN) CORP. +5CCAD3 (base 16) CHIPSEA TECHNOLOGIES (SHENZHEN) CORP. + 9F,BLOCK A,GARDEN CITY DIGITAL BUILDING,NO.1079 NANHAI ROAD,NANSHAN DISTRICT + SHEN ZHEN GUANG DONG 518000 + CN + +28-16-7F (hex) Xiaomi Communications Co Ltd +28167F (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +08-71-90 (hex) Intel Corporate +087190 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B0-3E-51 (hex) BSkyB Ltd +B03E51 (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +5C-E8-83 (hex) HUAWEI TECHNOLOGIES CO.,LTD +5CE883 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +10-01-77 (hex) HUAWEI TECHNOLOGIES CO.,LTD +100177 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +44-A1-91 (hex) HUAWEI TECHNOLOGIES CO.,LTD +44A191 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +60-23-A4 (hex) Sichuan AI-Link Technology Co., Ltd. +6023A4 (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou,Industrial Park + Anzhou,Industrial Park Sichuan 621000 + CN + +A4-53-0E (hex) Cisco Systems, Inc +A4530E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-40-3A (hex) IMPACT TECHNOLOGIES +00403A (base 16) IMPACT TECHNOLOGIES + 6 RUE DE L'ACADIE + + FR + +F8-87-F1 (hex) Apple, Inc. +F887F1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-28-BF (hex) Continental Automotive Czech Republic s.r.o. +9C28BF (base 16) Continental Automotive Czech Republic s.r.o. + Průmyslová 1851 + Brandýs nad Labem 250 01 + CZ + +80-72-15 (hex) BSkyB Ltd +807215 (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +74-D6-37 (hex) Amazon Technologies Inc. +74D637 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +D0-5F-64 (hex) IEEE Registration Authority +D05F64 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +BC-C3-1B (hex) Kygo Life A +BCC31B (base 16) Kygo Life A + Sjolyst Plass 3 + Oslo 0278 + NO + +64-DF-10 (hex) JingLue Semiconductor(SH) Ltd. +64DF10 (base 16) JingLue Semiconductor(SH) Ltd. + No.800 Naxian Rd + Shanghai 201210 + CN + +C4-63-FB (hex) Neatframe AS +C463FB (base 16) Neatframe AS + Martin Linges Vei 25 + Fornebu Fornebu 1364 + NO + +0C-81-26 (hex) Juniper Networks +0C8126 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +30-57-14 (hex) Apple, Inc. +305714 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-44-7A (hex) Water-i.d. GmbH +60447A (base 16) Water-i.d. GmbH + Daimlerstr. 20 + Eggenstein 76344 + DE + +C8-B1-CD (hex) Apple, Inc. +C8B1CD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-60-CB (hex) Apple, Inc. +1460CB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B8-F1-2A (hex) Apple, Inc. +B8F12A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-AB-6A (hex) Chun-il Co.,Ltd. +04AB6A (base 16) Chun-il Co.,Ltd. + 13-7, Gimhae-daero 2694 beon-gil, + Gimhae-si Gyeongsangnam-do 50936 + KR + +54-4E-45 (hex) Private +544E45 (base 16) Private + +04-C8-07 (hex) Xiaomi Communications Co Ltd +04C807 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +04-A2-22 (hex) Arcadyan Corporation +04A222 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +48-9B-D5 (hex) Extreme Networks, Inc. +489BD5 (base 16) Extreme Networks, Inc. + 6480 Via Del Oro + San Jose CA 95119 + US + +3C-8C-93 (hex) Juniper Networks +3C8C93 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +28-FE-65 (hex) DongGuan Siyoto Electronics Co., Ltd +28FE65 (base 16) DongGuan Siyoto Electronics Co., Ltd + Hecheng Industrial District, QiaoTou Town + DongGuan City Guangdong 523520 + CN + +18-06-F5 (hex) RAD Data Communications, Ltd. +1806F5 (base 16) RAD Data Communications, Ltd. + 24 Raoul Wallenberg St. + Tel Aviv 69719 + IL + +74-84-E1 (hex) Dongguan Haoyuan Electronics Co.,Ltd +7484E1 (base 16) Dongguan Haoyuan Electronics Co.,Ltd + NO.161 Kejizhong RoadLiuwu Shijie Town + Dongguan Guangdong 523290 + CN + +44-FB-5A (hex) zte corporation +44FB5A (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +44-59-E3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +4459E3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +40-74-E0 (hex) Intel Corporate +4074E0 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +DC-54-D7 (hex) Amazon Technologies Inc. +DC54D7 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +44-D3-CA (hex) Cisco Systems, Inc +44D3CA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +88-9F-AA (hex) Hella Gutmann Solutions GmbH +889FAA (base 16) Hella Gutmann Solutions GmbH + Am Krebsbach 2 + Ihringen Baden Württemberg 79241 + DE + +E4-54-E8 (hex) Dell Inc. +E454E8 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +20-96-8A (hex) China Mobile (Hangzhou) Information Technology Co., Ltd. +20968A (base 16) China Mobile (Hangzhou) Information Technology Co., Ltd. + No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District + Hangzhou Zhejiang 310000 + CN + +8C-18-50 (hex) China Mobile (Hangzhou) Information Technology Co., Ltd. +8C1850 (base 16) China Mobile (Hangzhou) Information Technology Co., Ltd. + No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District + Hangzhou Hangzhou 310000 + CN + +D8-D4-E6 (hex) Hytec Inter Co., Ltd. +D8D4E6 (base 16) Hytec Inter Co., Ltd. + 3-28-6 Yoyogi + Shibuya-ku Tokyo 1510053 + JP + +68-3F-1E (hex) EFFECT Photonics B.V. +683F1E (base 16) EFFECT Photonics B.V. + Kastanjelaan 400 + Eindhoven Noord-Brabant 5616 LZ + NL + +00-35-FF (hex) Texas Instruments +0035FF (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +F8-E7-A0 (hex) vivo Mobile Communication Co., Ltd. +F8E7A0 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +2C-FF-EE (hex) vivo Mobile Communication Co., Ltd. +2CFFEE (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +84-0B-7C (hex) Hitron Technologies. Inc +840B7C (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +48-A7-3C (hex) Sichuan tianyi kanghe communications co., LTD +48A73C (base 16) Sichuan tianyi kanghe communications co., LTD + No.198, section 1, xueshan avenue, jinyuan town, dayi county + chengdu sichuan 611330 + CN + +C8-5D-38 (hex) HUMAX Co., Ltd. +C85D38 (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +F8-A7-63 (hex) Zhejiang Tmall Technology Co., Ltd. +F8A763 (base 16) Zhejiang Tmall Technology Co., Ltd. + Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District, Shenzhen Guangdong province + Shenzhen GuangDong 518000 + CN + +A4-98-13 (hex) ARRIS Group, Inc. +A49813 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +6C-29-90 (hex) WiZ Connected Lighting Company Limited +6C2990 (base 16) WiZ Connected Lighting Company Limited + Room 3805, 148 Electric Road + Hong Kong 0000 0000 + HK + +98-35-ED (hex) HUAWEI TECHNOLOGIES CO.,LTD +9835ED (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +08-4F-0A (hex) HUAWEI TECHNOLOGIES CO.,LTD +084F0A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A8-49-4D (hex) HUAWEI TECHNOLOGIES CO.,LTD +A8494D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +44-00-4D (hex) HUAWEI TECHNOLOGIES CO.,LTD +44004D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-CF-24 (hex) HUAWEI TECHNOLOGIES CO.,LTD +18CF24 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D8-9B-3B (hex) HUAWEI TECHNOLOGIES CO.,LTD +D89B3B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-40-3B (hex) HUAWEI TECHNOLOGIES CO.,LTD +88403B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +FC-87-43 (hex) HUAWEI TECHNOLOGIES CO.,LTD +FC8743 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +80-76-93 (hex) Newag SA +807693 (base 16) Newag SA + Wyspianskiego 3 + Nowy Sacz woj. Malopolskie 33-300 + PL + +BC-97-40 (hex) IEEE Registration Authority +BC9740 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +04-88-5F (hex) HUAWEI TECHNOLOGIES CO.,LTD +04885F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C8-50-CE (hex) HUAWEI TECHNOLOGIES CO.,LTD +C850CE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +50-F8-A5 (hex) eWBM Co., Ltd. +50F8A5 (base 16) eWBM Co., Ltd. + 14F, 9, Teheran-ro 20-gil + Gangnam-gu, Seoul 06236 + KR + +14-49-BC (hex) DrayTek Corp. +1449BC (base 16) DrayTek Corp. + No. 26, Fushing Rd., Hukou, Hsinchu Industrial Park, + Hsinchu county 30352 + TW + +20-F4-78 (hex) Xiaomi Communications Co Ltd +20F478 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +90-73-5A (hex) Motorola Mobility LLC, a Lenovo Company +90735A (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +1C-82-59 (hex) IEEE Registration Authority +1C8259 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-04-DF (hex) TERACOM TELEMATICA S.A +0004DF (base 16) TERACOM TELEMATICA S.A + RUA AMERICA N.1000 + Eldorado do Sul - RS Brazil + BR + +74-38-B7 (hex) CANON INC. +7438B7 (base 16) CANON INC. + 30-2 Shimomaruko 3-chome + Ohta-ku Tokyo 146-8501 + JP + +8C-04-BA (hex) Dell Inc. +8C04BA (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-FA-21 (hex) Samsung Electronics Co.,Ltd +00FA21 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +7C-23-02 (hex) Samsung Electronics Co.,Ltd +7C2302 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +18-B6-F7 (hex) NEW POS TECHNOLOGY LIMITED +18B6F7 (base 16) NEW POS TECHNOLOGY LIMITED + AB Unit, 14th Floor,Block A, Financial Technology Building.No. 11 Keyuan Rd + Shenzhen 518057 + CN + +5C-B1-5F (hex) Oceanblue Cloud Technology Limited +5CB15F (base 16) Oceanblue Cloud Technology Limited + 253-261 Hennessy Road + Hong Kong Hong Kong 999077 + HK + +18-AA-CA (hex) Sichuan tianyi kanghe communications co., LTD +18AACA (base 16) Sichuan tianyi kanghe communications co., LTD + No.198, section 1, xueshan avenue, jinyuan town, dayi county, sichuan province + chengdu sichuan 611330 + CN + +D4-9D-C0 (hex) Samsung Electronics Co.,Ltd +D49DC0 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +D0-19-6A (hex) Ciena Corporation +D0196A (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +44-13-D0 (hex) zte corporation +4413D0 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +24-62-AB (hex) Espressif Inc. +2462AB (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +88-B4-36 (hex) Private +88B436 (base 16) Private + +84-FD-D1 (hex) Intel Corporate +84FDD1 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +6C-AB-05 (hex) Cisco Systems, Inc +6CAB05 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-E4 (hex) Hosiden Corporation +000BE4 (base 16) Hosiden Corporation + 4-33 + Yao-city Osaka 581-0071 + JP + +60-D2-48 (hex) ARRIS Group, Inc. +60D248 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +48-5D-EB (hex) Just Add Power +485DEB (base 16) Just Add Power + 12505 STARKEY RD STE A + LARGO FL 33773 + US + +50-13-95 (hex) Sichuan AI-Link Technology Co., Ltd. +501395 (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou,Industrial Park + Anzhou,Industrial Park Sichuan 621000 + CN + +18-D9-EF (hex) Shuttle Inc. +18D9EF (base 16) Shuttle Inc. + No. 30 Lane 76, Rei Kuang Rd + Taipei 114 + TW + +88-DA-33 (hex) Beijing Xiaoyuer Network Technology Co., Ltd +88DA33 (base 16) Beijing Xiaoyuer Network Technology Co., Ltd + Block K1, North American International Business Centre, 86 Beiyuan Road, Chaoyang District + Beijing Beijing 100012 + CN + +84-C7-8F (hex) STORDIS GmbH +84C78F (base 16) STORDIS GmbH + Rosenwiesstr. 17 + Stuttgart 70567 + DE + +50-41-B9 (hex) I-O DATA DEVICE,INC. +5041B9 (base 16) I-O DATA DEVICE,INC. + 3-10,Sakurada-machi + Kanazawa Ishikawa 920-8512 + JP + +80-DA-BC (hex) Megafone Limited +80DABC (base 16) Megafone Limited + Unit 702,7/F,Bankok Bank Building,NO.18 Bonham Strand West + Hong Kong 999077 + HK + +C0-9F-E1 (hex) zte corporation +C09FE1 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +18-46-44 (hex) Home Control Singapore Pte Ltd +184644 (base 16) Home Control Singapore Pte Ltd + 151 Lorong Chuan + Singapore 556741 + SG + +B0-70-0D (hex) Nokia +B0700D (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +34-6B-5B (hex) New H3C Technologies Co., Ltd +346B5B (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +84-E8-92 (hex) Actiontec Electronics, Inc +84E892 (base 16) Actiontec Electronics, Inc + 301 Olcott St + Santa Clara CA 95054 + US + +78-E2-BD (hex) Vodafone Automotive S.p.A. +78E2BD (base 16) Vodafone Automotive S.p.A. + via Astico 41 + Varese Italy/VA 21100 + IT + +F8-48-FD (hex) China Mobile Group Device Co.,Ltd. +F848FD (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +20-DA-22 (hex) HUAWEI TECHNOLOGIES CO.,LTD +20DA22 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C8-21-DA (hex) Shenzhen YOUHUA Technology Co., Ltd +C821DA (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +E0-B6-55 (hex) Beijing Xiaomi Electronics Co., Ltd. +E0B655 (base 16) Beijing Xiaomi Electronics Co., Ltd. + Building C, QingHe ShunShiJiaYe Technology Park, #66 ZhuFang Rd, HaiDian District + Beijing Beijing 10085 + CN + +00-21-75 (hex) Pacific Satellite International Ltd. +002175 (base 16) Pacific Satellite International Ltd. + 20/F Tai Tung Building, + Wanchai 100000 + HK + +88-97-46 (hex) Sichuan AI-Link Technology Co., Ltd. +889746 (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou,Industrial Park + Anzhou,Industrial Park Sichuan 621000 + CN + +1C-DE-57 (hex) Fiberhome Telecommunication Technologies Co.,LTD +1CDE57 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +E0-DC-FF (hex) Xiaomi Communications Co Ltd +E0DCFF (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +60-8C-DF (hex) Private +608CDF (base 16) Private + +00-77-8D (hex) Cisco Systems, Inc +00778D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0E-8C (hex) Siemens AG +000E8C (base 16) Siemens AG + Siemensstraße 10 + Regensburg 93055 + DE + +00-87-64 (hex) Cisco Systems, Inc +008764 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +FC-33-42 (hex) Juniper Networks +FC3342 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +C4-68-D0 (hex) VTech Telecommunications Ltd. +C468D0 (base 16) VTech Telecommunications Ltd. + 23/F, Tai Ping Industrial Centre, Block 1, + HONG KONG NA 000000 + HK + +14-AE-DB (hex) VTech Telecommunications Ltd. +14AEDB (base 16) VTech Telecommunications Ltd. + 23/F, Tai Ping Industrial Centre, Block 1, + HONG KONG NA 000000 + HK + +78-DB-2F (hex) Texas Instruments +78DB2F (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +8C-0F-A0 (hex) di-soric GmbH & Co. KG +8C0FA0 (base 16) di-soric GmbH & Co. KG + Steinbeisstrasse 6 + Urbach 73660 + DE + +DC-B8-08 (hex) Extreme Networks, Inc. +DCB808 (base 16) Extreme Networks, Inc. + 6480 Via Del Oro + San Jose CA 95119 + US + +B0-E7-1D (hex) Shanghai Maigantech Co.,Ltd +B0E71D (base 16) Shanghai Maigantech Co.,Ltd + Room 2211,No.88 Caoxi North Rd,Xuhui District + Shanghai Shanghai 200030 + CN + +F8-BB-BF (hex) eero inc. +F8BBBF (base 16) eero inc. + 500 Howard St Suite 900 + San Francisco CA 94105 + US + +DC-FB-48 (hex) Intel Corporate +DCFB48 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +84-6F-CE (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +846FCE (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +20-65-8E (hex) HUAWEI TECHNOLOGIES CO.,LTD +20658E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-3D-5E (hex) HUAWEI TECHNOLOGIES CO.,LTD +183D5E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +DC-71-37 (hex) zte corporation +DC7137 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +84-7C-9B (hex) GD Midea Air-Conditioning Equipment Co.,Ltd. +847C9B (base 16) GD Midea Air-Conditioning Equipment Co.,Ltd. + Midea Global Innovation Center,Beijiao Town,Shunde + Foshan Guangdong 528311 + CN + +34-41-A8 (hex) ER-Telecom +3441A8 (base 16) ER-Telecom + Ovchinnikovskaya embankment, 20, Building 1 + Moscow 115324 + RU + +34-DB-9C (hex) Sagemcom Broadband SAS +34DB9C (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +74-40-BE (hex) LG Innotek +7440BE (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +04-D4-C4 (hex) ASUSTek COMPUTER INC. +04D4C4 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +A0-51-0B (hex) Intel Corporate +A0510B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +F0-D4-E2 (hex) Dell Inc. +F0D4E2 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +A8-E2-C3 (hex) Shenzhen YOUHUA Technology Co., Ltd +A8E2C3 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +90-20-C2 (hex) Aruba, a Hewlett Packard Enterprise Company +9020C2 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +0C-A0-6C (hex) Industrial Cyber Sensing Inc. +0CA06C (base 16) Industrial Cyber Sensing Inc. + Unit 1A - 343 Montrose Street North + Cambridge Ontario N3H 2H6 + CA + +FC-D2-B6 (hex) IEEE Registration Authority +FCD2B6 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +80-4A-14 (hex) Apple, Inc. +804A14 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-3C-69 (hex) Apple, Inc. +703C69 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-2D-A9 (hex) TECNO MOBILE LIMITED +AC2DA9 (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +FC-B6-62 (hex) IC Holdings LLC +FCB662 (base 16) IC Holdings LLC + 9066 S 300 W + Sandy UT 84070 + US + +48-04-9F (hex) ELECOM CO., LTD +48049F (base 16) ELECOM CO., LTD + 9FLand Axis Tower.1-1 fushimi machi,4-chome chuoku + osaka 5418765 + JP + +08-7F-98 (hex) vivo Mobile Communication Co., Ltd. +087F98 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +C8-52-61 (hex) ARRIS Group, Inc. +C85261 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +C0-41-21 (hex) Nokia +C04121 (base 16) Nokia + Karaportti 3 + Espoo Finland 02610 + FI + +74-88-BB (hex) Cisco Systems, Inc +7488BB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A4-CF-12 (hex) Espressif Inc. +A4CF12 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +4C-6A-F6 (hex) HMD Global Oy +4C6AF6 (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +48-9D-D1 (hex) Samsung Electronics Co.,Ltd +489DD1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-6F-E0 (hex) Samsung Electronics Co.,Ltd +B06FE0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +44-B9-94 (hex) Douglas Lighting Controls +44B994 (base 16) Douglas Lighting Controls + 280 - 3605 Gilmore Way + Burnaby BC V5G4X5 + CA + +40-A9-3F (hex) Pivotal Commware, Inc. +40A93F (base 16) Pivotal Commware, Inc. + 1555 132nd Ave. NE + Bellevue WA 98005 + US + +70-BF-92 (hex) GN Audio A/S +70BF92 (base 16) GN Audio A/S + Lautrupbjerg 7 + Ballerup DK-2750 + DK + +C0-8C-71 (hex) Motorola Mobility LLC, a Lenovo Company +C08C71 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +F4-6F-4E (hex) Echowell +F46F4E (base 16) Echowell + 7F-8, No. 8, Sec 1, JunShing Rd. + New Taipei City 24872 + TW + +2C-3F-0B (hex) Cisco Meraki +2C3F0B (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco null 94158 + US + +5C-88-16 (hex) Rockwell Automation +5C8816 (base 16) Rockwell Automation + 1 Allen-Bradley Dr. + Mayfield Heights OH 44124-6118 + US + +00-2F-5C (hex) Cisco Systems, Inc +002F5C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F4-64-5D (hex) Toshiba +F4645D (base 16) Toshiba + 2-9,Suehiro-Cho + Ome Tokyo 1988710 + JP + +38-F8-5E (hex) HUMAX Co., Ltd. +38F85E (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +AC-BB-61 (hex) YSTen Technology Co.,Ltd +ACBB61 (base 16) YSTen Technology Co.,Ltd + Room 1715,17/F North Star Times Tower,Chaoyang District,Beijing. + Beijing 100101 + CN + +24-79-F8 (hex) KUPSON spol. s r.o. +2479F8 (base 16) KUPSON spol. s r.o. + Hradecka 787/14 + Opava Czech Republic 74601 + CZ + +7C-FD-82 (hex) GUANGDONG GENIUS TECHNOLOGY CO., LTD. +7CFD82 (base 16) GUANGDONG GENIUS TECHNOLOGY CO., LTD. + No.168, Middle Road Of East Gate + Xiaobian Community Chang'an Town 523851 + CN + +18-0D-2C (hex) Intelbras +180D2C (base 16) Intelbras + BR 101, km 210, S/N° + São José Santa Catarina 88104800 + BR + +04-2D-B4 (hex) First Property (Beijing) Co., Ltd Modern MOMA Branch +042DB4 (base 16) First Property (Beijing) Co., Ltd Modern MOMA Branch + Room 301A,Building No.10, No.1 Xiangheyuan Road, Dongcheng District, Beijing City + Beijing Beijing 100028 + CN + +04-E0-B0 (hex) Shenzhen YOUHUA Technology Co., Ltd +04E0B0 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +08-EC-F5 (hex) Cisco Systems, Inc +08ECF5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D0-76-50 (hex) IEEE Registration Authority +D07650 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +60-D0-A9 (hex) Samsung Electronics Co.,Ltd +60D0A9 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +88-CE-FA (hex) HUAWEI TECHNOLOGIES CO.,LTD +88CEFA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-27-06 (hex) YOISYS +002706 (base 16) YOISYS + 309-52 SUNGSU-2GA, 1DONG, SUNGDONG-GU + SEOUL 133-827 + KR + +00-CB-51 (hex) Sagemcom Broadband SAS +00CB51 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +C4-64-B7 (hex) Fiberhome Telecommunication Technologies Co.,LTD +C464B7 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +EC-41-18 (hex) XIAOMI Electronics,CO.,LTD +EC4118 (base 16) XIAOMI Electronics,CO.,LTD + Xiaomi Building, No.68 Qinghe Middle Street + Haidian District Beijing 100085 + CN + +D8-86-0B (hex) IEEE Registration Authority +D8860B (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +34-20-03 (hex) Shenzhen Feitengyun Technology Co.,LTD +342003 (base 16) Shenzhen Feitengyun Technology Co.,LTD + 7F 4building,Yalianhaoshida industrial Park + Shenzhen Guangdong 518100 + CN + +F0-7D-68 (hex) D-Link Corporation +F07D68 (base 16) D-Link Corporation + No.289, Sinhu 3rd Rd., Neihu District, + Taipei City 114 + TW + +40-E3-D6 (hex) Aruba, a Hewlett Packard Enterprise Company +40E3D6 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +B4-5D-50 (hex) Aruba, a Hewlett Packard Enterprise Company +B45D50 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +78-DA-A2 (hex) Cynosure Technologies Co.,Ltd +78DAA2 (base 16) Cynosure Technologies Co.,Ltd + Room 2708/2710, Building No.9A, Shenzhen Bay Science and Technology Ecological Park,Nanshan + Shenzhen city Guangdong Province 518057 + CN + +38-B1-9E (hex) IEEE Registration Authority +38B19E (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +38-E2-6E (hex) ShenZhen Sweet Rain Electronics Co.,Ltd. +38E26E (base 16) ShenZhen Sweet Rain Electronics Co.,Ltd. + Xinghua Road + Shenzhen Bao'an 518101 + CN + +00-D0-50 (hex) Iskratel d.o.o. +00D050 (base 16) Iskratel d.o.o. + Ljubljanska cesta 24a + Kranj 4000 + SI + +70-C9-C6 (hex) Cisco Systems, Inc +70C9C6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D4-B9-2F (hex) Technicolor CH USA Inc. +D4B92F (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +68-9A-87 (hex) Amazon Technologies Inc. +689A87 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +64-AE-88 (hex) Polytec GmbH +64AE88 (base 16) Polytec GmbH + Polytec Platz 1-7 + Waldbronn BW 76337 + DE + +AC-A3-1E (hex) Aruba, a Hewlett Packard Enterprise Company +ACA31E (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +00-17-7B (hex) Azalea Networks inc +00177B (base 16) Azalea Networks inc + 673 S Milpitas Blvd + Milpitas CA 95035 + US + +98-DA-C4 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +98DAC4 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +F8-4D-FC (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +F84DFC (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555,qianmo road + Hangzhou Zhejiang 310052 + CN + +50-2B-98 (hex) Es-tech International +502B98 (base 16) Es-tech International + 228-70, Saneop-ro 155beon-gil, Gwonseon-gu, Suwon-si, Gyeonggi-do, Korea + Suwon 16648 + KR + +C8-28-32 (hex) Beijing Xiaomi Electronics Co., Ltd. +C82832 (base 16) Beijing Xiaomi Electronics Co., Ltd. + Building C, QingHe ShunShiJiaYe Technology Park, #66 ZhuFang Rd, HaiDian District + Beijing Beijing 10085 + CN + +94-6A-77 (hex) Technicolor CH USA Inc. +946A77 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +C4-34-6B (hex) Hewlett Packard +C4346B (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +48-F1-7F (hex) Intel Corporate +48F17F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +80-84-A9 (hex) oshkosh Corporation +8084A9 (base 16) oshkosh Corporation + 2307 Oregon Street + Oshkosh WI 54902 + US + +F4-6E-95 (hex) Extreme Networks, Inc. +F46E95 (base 16) Extreme Networks, Inc. + 6480 Via Del Oro + San Jose 95119 + US + +4C-C7-D6 (hex) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. +4CC7D6 (base 16) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + Xin Qing Science & Technology Industrial Park,Jin An Town,Doumen ,Zhuhai,Guangdong,PRC + Zhuhai Guangdong 519180 + CN + +C8-08-73 (hex) Ruckus Wireless +C80873 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +70-1B-FB (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +701BFB (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +04-76-6E (hex) ALPS ELECTRIC CO., LTD. +04766E (base 16) ALPS ELECTRIC CO., LTD. + 6-3-36 Furukawanakazato, + Osaki Miyagi-pref 989-6181 + JP + +AC-7A-4D (hex) ALPS ELECTRIC CO., LTD. +AC7A4D (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + KAKUDA-CITY MIYAGI-PREF 981-1595 + JP + +00-1B-B5 (hex) Cherry GmbH +001BB5 (base 16) Cherry GmbH + Cherrystraße 1 + Auerbach i. d. Opf. Bayern D-91275 + DE + +00-26-43 (hex) ALPS ELECTRIC CO., LTD. +002643 (base 16) ALPS ELECTRIC CO., LTD. + 1-2-1, Okinouchi, + Soma-city, Fukushima-pref., 976-8501 + JP + +38-C0-96 (hex) ALPS ELECTRIC CO., LTD. +38C096 (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + KAKUDA-CITY MIYAGI-PREF 981-1595 + JP + +D0-51-57 (hex) LEAX Arkivator Telecom +D05157 (base 16) LEAX Arkivator Telecom + NanShan District YueHaiMen Street + ShenZhen GuangDong 518061 + CN + +28-80-88 (hex) NETGEAR +288088 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +64-CE-6E (hex) Sierra Wireless +64CE6E (base 16) Sierra Wireless + 13811 Wireless Way + Richmond BC V6V 3A4 + CA + +1C-34-77 (hex) Innovation Wireless +1C3477 (base 16) Innovation Wireless + 11869 Teale Street + Culver City CA 90230 + US + +BC-3E-07 (hex) Hitron Technologies. Inc +BC3E07 (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +48-FD-A3 (hex) Xiaomi Communications Co Ltd +48FDA3 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +00-16-97 (hex) NEC Corporation +001697 (base 16) NEC Corporation + 7-1, Shiba 5-chome Minato-ku, + tokyo Tokyo 108-8001 + JP + +00-30-13 (hex) NEC Corporation +003013 (base 16) NEC Corporation + 1-10 Nisshincho, Fuchu + Tokyo 183-8501 0000 + JP + +04-9D-FE (hex) Hivesystem +049DFE (base 16) Hivesystem + 816 Kranz-techno Bldg. 388 dunchondaero, jun + Gyeonggi-do KSXX0024 + KR + +0C-EC-84 (hex) Shenzhen TINNO Mobile Technology Corp. +0CEC84 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F, H-3 Building, Qiao Cheng Eastern Industrial Park, Overseas Chinese Town, Shenzhen + Shenzhen guangdong 518053 + CN + +9C-DB-07 (hex) Thum+Mahr GmbH +9CDB07 (base 16) Thum+Mahr GmbH + Heinrich-Hertz-Strasse 1-3 + Monheim am Rhein NRW 40789 + DE + +DC-EB-69 (hex) Technicolor CH USA Inc. +DCEB69 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +00-4E-35 (hex) Hewlett Packard Enterprise +004E35 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +F8-13-08 (hex) Nokia +F81308 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +F8-A2-D6 (hex) Liteon Technology Corporation +F8A2D6 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +18-2A-44 (hex) HIROSE ELECTRONIC SYSTEM +182A44 (base 16) HIROSE ELECTRONIC SYSTEM + 1-9-6 Ebisuminami + Shibuya Tokyo 150-0022 + JP + +FC-94-CE (hex) zte corporation +FC94CE (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +90-86-9B (hex) zte corporation +90869B (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +E0-18-9F (hex) EM Microelectronic +E0189F (base 16) EM Microelectronic + Rue des Sors 3 + Marin-Epagnier Neuchatel 2074 + CH + +74-36-6D (hex) Vodafone Italia S.p.A. +74366D (base 16) Vodafone Italia S.p.A. + Via Lorenteggio nr. 240 + Milan Italy 20147 + IT + +84-DB-2F (hex) Sierra Wireless +84DB2F (base 16) Sierra Wireless + 1381 Wireless Way + Richmond BC V6V 3A4 + CA + +94-58-CB (hex) Nintendo Co.,Ltd +9458CB (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +28-EC-9A (hex) Texas Instruments +28EC9A (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +FC-BE-7B (hex) vivo Mobile Communication Co., Ltd. +FCBE7B (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +B4-0F-B3 (hex) vivo Mobile Communication Co., Ltd. +B40FB3 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +EC-5C-68 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +EC5C68 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +C4-E5-06 (hex) Piper Networks, Inc. +C4E506 (base 16) Piper Networks, Inc. + 3636 Nobel Drive + San Diego CA 92122 + US + +30-EB-5A (hex) LANDIS + GYR +30EB5A (base 16) LANDIS + GYR + 78th km Old National Road Athens-Corinth + Corinth 20100 + GR + +F8-0F-6F (hex) Cisco Systems, Inc +F80F6F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-80-E3 (hex) CORAL NETWORK CORPORATION +0080E3 (base 16) CORAL NETWORK CORPORATION + (NOW BAY NETWORKS) + SANTA CLARA CA 95052-8185 + US + +D8-F2-CA (hex) Intel Corporate +D8F2CA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B4-C6-2E (hex) Molex CMS +B4C62E (base 16) Molex CMS + 2222 Wellington Court + Lisle IL 60532 + US + +B8-25-9A (hex) Thalmic Labs +B8259A (base 16) Thalmic Labs + 24 Charles Street West + Kitchener Ontario N2G 1H2 + CA + +28-25-36 (hex) SHENZHEN HOLATEK CO.,LTD +282536 (base 16) SHENZHEN HOLATEK CO.,LTD + Rm.1001,Unit 4,Bld.B,Kexing Science Park,Keyuan Road, Nanshan District + Shenzhen Guangdong 518000 + CN + +B8-A1-75 (hex) Roku, Inc. +B8A175 (base 16) Roku, Inc. + 12980 Saratoga Ave + Saratoga CA 95070 + US + +CC-D3-C1 (hex) Vestel Elektronik San ve Tic. A.Ş. +CCD3C1 (base 16) Vestel Elektronik San ve Tic. A.Ş. + Organize san + Manisa Turket 45030 + TR + +0C-D0-F8 (hex) Cisco Systems, Inc +0CD0F8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +74-5F-90 (hex) LAM Technologies +745F90 (base 16) LAM Technologies + Viale Ludovico Ariosto, 492/D + Sesto Fiorentino FIRENZE 50019 + IT + +A4-26-55 (hex) LTI Motion (Shanghai) Co., Ltd. +A42655 (base 16) LTI Motion (Shanghai) Co., Ltd. + NO.80, Lane 2927, LaiYang Road Pudong New District + Shanghai Shanghai 200137 + CN + +60-A7-30 (hex) Shenzhen Yipinfang Internet Technology Co.,Ltd +60A730 (base 16) Shenzhen Yipinfang Internet Technology Co.,Ltd + Shenzhen Konka R & D Building, 28th floor 21 + GuangDong Nanshan District 518000 + CN + +3C-9B-D6 (hex) Vizio, Inc +3C9BD6 (base 16) Vizio, Inc + 39 Tesla + Irvine CA 92618 + US + +F8-5B-9C (hex) SB SYSTEMS Co.,Ltd +F85B9C (base 16) SB SYSTEMS Co.,Ltd + 2F Ventureforum, 323, Pangyo-ro, Bundang-gu + Seongnam-si Gyeonngi-do 453-400 + KR + +6C-A9-28 (hex) HMD Global Oy +6CA928 (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +00-D8-61 (hex) Micro-Star INTL CO., LTD. +00D861 (base 16) Micro-Star INTL CO., LTD. + No.69, Lide St., + New Taipei City Taiwan 235 + TW + +74-C1-7D (hex) Infinix mobility limited +74C17D (base 16) Infinix mobility limited + RMS 05-15, 13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG + HongKong HongKong 999077 + HK + +88-71-B1 (hex) ARRIS Group, Inc. +8871B1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F0-AF-85 (hex) ARRIS Group, Inc. +F0AF85 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +FC-AE-34 (hex) ARRIS Group, Inc. +FCAE34 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +DC-DA-80 (hex) New H3C Technologies Co., Ltd +DCDA80 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +CC-72-86 (hex) Xi'an Fengyu Information Technology Co., Ltd. +CC7286 (base 16) Xi'an Fengyu Information Technology Co., Ltd. + 5F, Block A, STRC, No.10, Zhangba 5th Road, Yanta + Xi'an Shaanxi 710077 + CN + +64-EE-B7 (hex) Netcore Technology Inc +64EEB7 (base 16) Netcore Technology Inc + Building 6, Baolong Plant, Able Technology Park, Longgang District, + Shenzhen 518116 + CN + +38-81-D7 (hex) Texas Instruments +3881D7 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +18-04-ED (hex) Texas Instruments +1804ED (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +D4-32-60 (hex) GoPro +D43260 (base 16) GoPro + 3000 Clearview Way + San Mateo CA 94402 + US + +50-DB-3F (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +50DB3F (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +10-81-B4 (hex) Hunan Greatwall Galaxy Science and Technology Co.,Ltd. +1081B4 (base 16) Hunan Greatwall Galaxy Science and Technology Co.,Ltd. + No. 39, Jian Shan Road + Changsha Hunan 410205 + CN + +00-42-79 (hex) Sunitec Enterprise Co.,Ltd +004279 (base 16) Sunitec Enterprise Co.,Ltd + 3F.,No.98-1,Mincyuan Rd.Sindian City + Taipei County 231 231141 + CN + +00-B8-B3 (hex) Cisco Systems, Inc +00B8B3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F4-DD-9E (hex) GoPro +F4DD9E (base 16) GoPro + 3000 Clearview Way + San Mateo CA 94402 + US + +D4-D9-19 (hex) GoPro +D4D919 (base 16) GoPro + 3000 Clearview Way + San Mateo CA 94402 + US + +14-11-14 (hex) TECNO MOBILE LIMITED +141114 (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +A4-50-46 (hex) Xiaomi Communications Co Ltd +A45046 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +1C-24-CD (hex) Askey Computer Corp. +1C24CD (base 16) Askey Computer Corp. + 10F, No.119, JIANKANG RD.,ZHINGHE DIST, + NEW TAIPEI CITY 23585 + TW + +00-7C-2D (hex) Samsung Electronics Co.,Ltd +007C2D (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +B4-77-48 (hex) Shenzhen Neoway Technology Co.,Ltd. +B47748 (base 16) Shenzhen Neoway Technology Co.,Ltd. + 4F-2#,Lian Jian Science & Industry Park,Huarong Road,Dalang Street,Longhua District + Shenzhen Guangdong 518000 + CN + +F8-50-1C (hex) Tianjin Geneuo Technology Co.,Ltd +F8501C (base 16) Tianjin Geneuo Technology Co.,Ltd + Technology Avenue South JingHai Economic Development Area,Tianjin China + Tianjin 301609 + CN + +44-07-0B (hex) Google, Inc. +44070B (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +F8-C2-49 (hex) Private +F8C249 (base 16) Private + +B8-31-B5 (hex) Microsoft Corporation +B831B5 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +EC-F6-BD (hex) SNCF MOBILITÉS +ECF6BD (base 16) SNCF MOBILITÉS + 9 rue Jean-Philippe Rameau + SAINT-DENIS 93200 + FR + +38-B4-D3 (hex) BSH Hausgeraete GmbH +38B4D3 (base 16) BSH Hausgeraete GmbH + Im Gewerbepark B10 + Regensburg 93059 + DE + +C8-47-82 (hex) Areson Technology Corp. +C84782 (base 16) Areson Technology Corp. + 11F., No. 646, Sec. 5, Chongxin Rd., Sanchong District + New Taipei City 24158 + TW + +E8-93-63 (hex) Nokia +E89363 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +7C-0C-F6 (hex) Guangdong Huiwei High-tech Co., Ltd. +7C0CF6 (base 16) Guangdong Huiwei High-tech Co., Ltd. + E Block No. 1 in Ecological Area in Puzhai NewArea + Fengshun County, Meizhou Guangdong province 514000 + CN + +74-9D-79 (hex) Sercomm Corporation. +749D79 (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +00-D6-FE (hex) Cisco Systems, Inc +00D6FE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +0C-BF-74 (hex) Morse Micro +0CBF74 (base 16) Morse Micro + 113 / 2-4 Cornwallis Street + Eveleigh NSW 2015 + AU + +FC-8F-7D (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +FC8F7D (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +24-BE-18 (hex) DADOUTEK COMPANY LIMITED +24BE18 (base 16) DADOUTEK COMPANY LIMITED + 14/F, Wilson Logistics Centre,No.24-28 Kung Yip St + Kwai Chung New Territories 000 + CN + +B4-1D-2B (hex) Shenzhen YOUHUA Technology Co., Ltd +B41D2B (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +14-C2-13 (hex) Apple, Inc. +14C213 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-D3-13 (hex) HUAWEI TECHNOLOGIES CO.,LTD +70D313 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +9C-1D-36 (hex) HUAWEI TECHNOLOGIES CO.,LTD +9C1D36 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +CC-BB-FE (hex) HUAWEI TECHNOLOGIES CO.,LTD +CCBBFE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-D9-31 (hex) Apple, Inc. +A4D931 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-FE-D9 (hex) Apple, Inc. +BCFED9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +80-82-23 (hex) Apple, Inc. +808223 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +30-0A-60 (hex) IEEE Registration Authority +300A60 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +80-D0-65 (hex) CKS Corporation +80D065 (base 16) CKS Corporation + 1-24-11 Akebono + Tachikawa Tokyo 190-0012 + JP + +28-31-66 (hex) vivo Mobile Communication Co., Ltd. +283166 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +C0-40-04 (hex) Medicaroid Corporation +C04004 (base 16) Medicaroid Corporation + 1-6-4, Minatojima-minamimachi, Chuo-ku + Kobe 650-0047 + JP + +20-AD-56 (hex) Continental Automotive Systems Inc. +20AD56 (base 16) Continental Automotive Systems Inc. + 21440 W. Lake Cook Rd. + Deer Park IL 60010 + US + +50-29-F5 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +5029F5 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +CC-08-FB (hex) TP-LINK TECHNOLOGIES CO.,LTD. +CC08FB (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +BC-AF-91 (hex) TE Connectivity Sensor Solutions +BCAF91 (base 16) TE Connectivity Sensor Solutions + 4 rue Gaye-Marie, CS 83163 + Toulouse 31027 + FR + +F0-D7-DC (hex) Wesine (Wuhan) Technology Co., Ltd. +F0D7DC (base 16) Wesine (Wuhan) Technology Co., Ltd. + 10th Floor, Building 2, SBI Venture Street, Hongshan District + Wuhan Hubei 430074 + CN + +00-72-04 (hex) Samsung Electronics Co., Ltd. ARTIK +007204 (base 16) Samsung Electronics Co., Ltd. ARTIK + 1-1, Samsungjeonja-ro + Hwaseong-si Gyeonggi-do 18448 + KR + +40-C8-1F (hex) Shenzhen Xinguodu Technology Co., Ltd. +40C81F (base 16) Shenzhen Xinguodu Technology Co., Ltd. + F17A, JinSong Building, Tairan Industrial & Trade Park, Chegongmiao, Shennan Road,Futian District + Shenzhen Guangdong 518040 + CN + +14-59-C0 (hex) NETGEAR +1459C0 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +8C-61-A3 (hex) ARRIS Group, Inc. +8C61A3 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +A8-10-87 (hex) Texas Instruments +A81087 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +A0-28-33 (hex) IEEE Registration Authority +A02833 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +C8-C2-F5 (hex) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. +C8C2F5 (base 16) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + Xin Qing Science & Technology Industrial Park,Jin An Town,Doumen ,Zhuhai,Guangdong,PRC + Zhuhai Guangdong 519180 + CN + +F0-58-49 (hex) CareView Communications +F05849 (base 16) CareView Communications + 405 State HWY 121 BYP + Lewisville Texas 75067 + US + +34-E5-EC (hex) Palo Alto Networks +34E5EC (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +A4-ED-43 (hex) IEEE Registration Authority +A4ED43 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +94-29-8D (hex) Shanghai AdaptComm Technology Co., Ltd. +94298D (base 16) Shanghai AdaptComm Technology Co., Ltd. + 3rd Floor, Building 14, No. 518 Xinzhuan Road, Songjiang District, + Shanghai 201600 + CN + +00-AA-6E (hex) Cisco Systems, Inc +00AA6E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +0C-7C-28 (hex) Nokia +0C7C28 (base 16) Nokia + Karaportti 3 + Espoo Finland 02610 + FI + +68-43-D7 (hex) Agilecom Photonics Solutions Guangdong Limited +6843D7 (base 16) Agilecom Photonics Solutions Guangdong Limited + No.1-6, Shenwan Industrial Park, Shenwan Town + Zhongshan Guangdong 528462 + CN + +20-D8-0B (hex) Juniper Networks +20D80B (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +8C-8F-8B (hex) China Mobile Chongqing branch +8C8F8B (base 16) China Mobile Chongqing branch + 6 building, No. 2, Xingguang three road + Yubei District Chongqing 401120 + CN + +B8-6A-97 (hex) Edgecore Networks Corporation +B86A97 (base 16) Edgecore Networks Corporation + 1 Creation RD 3. + Hsinchu 30077 + TW + +00-0A-5E (hex) 3COM +000A5E (base 16) 3COM + 5400 Bayfront Plaza + Santa Clara CA 95052-8145 + US + +00-10-5A (hex) 3COM +00105A (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +00-60-97 (hex) 3COM +006097 (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +00-60-08 (hex) 3COM +006008 (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +00-1B-6E (hex) Keysight Technologies, Inc. +001B6E (base 16) Keysight Technologies, Inc. + 1400 Fountaingrove Pkwy. + Santa Rosa CA 95403 + US + +00-04-0B (hex) 3COM EUROPE LTD +00040B (base 16) 3COM EUROPE LTD + BOUNDARY WAY + vvvvv UNITED KINGDOM + GB + +00-01-02 (hex) 3COM +000102 (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +8C-FE-74 (hex) Ruckus Wireless +8CFE74 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +A8-01-6D (hex) Aiwa Corporation +A8016D (base 16) Aiwa Corporation + 965 W Chicago Ave + Chicago IL 60642 + US + +04-40-A9 (hex) New H3C Technologies Co., Ltd +0440A9 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +48-A4-72 (hex) Intel Corporate +48A472 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +4C-01-43 (hex) eero inc. +4C0143 (base 16) eero inc. + 660 3rd Street + San Francisco CA 94107 + US + +E4-34-93 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E43493 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +34-29-12 (hex) HUAWEI TECHNOLOGIES CO.,LTD +342912 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +60-4B-AA (hex) Magic Leap, Inc. +604BAA (base 16) Magic Leap, Inc. + 1855 Griffin Rd, Room B454 + Dania Beach FL 33004 + US + +4C-36-4E (hex) Panasonic Corporation Connected Solutions Company +4C364E (base 16) Panasonic Corporation Connected Solutions Company + 4-1-62 Minoshima, Hakata-ku + Fukuoka-shi Fukuoka 812-8531 + JP + +BC-A5-8B (hex) Samsung Electronics Co.,Ltd +BCA58B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +80-CE-B9 (hex) Samsung Electronics Co.,Ltd +80CEB9 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D0-D3-FC (hex) Mios, Ltd. +D0D3FC (base 16) Mios, Ltd. + 645 W. 9th St. + Los Angeles CA 90015 + US + +6C-6C-D3 (hex) Cisco Systems, Inc +6C6CD3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E0-49-ED (hex) Audeze LLC +E049ED (base 16) Audeze LLC + 3410 S Susan st + Santa Ana CA 92704 + US + +80-30-E0 (hex) Hewlett Packard Enterprise +8030E0 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +E8-5D-86 (hex) CHANG YOW TECHNOLOGIES INTERNATIONAL CO.,LTD. +E85D86 (base 16) CHANG YOW TECHNOLOGIES INTERNATIONAL CO.,LTD. + No 88 Shuren 6th St Wufong District + Taichung 413 + TW + +14-37-19 (hex) PT Prakarsa Visi Valutama +143719 (base 16) PT Prakarsa Visi Valutama + Jl. Cideng Timur No.11D + Jakarta Pusat Indonesia 10130 + ID + +58-2F-40 (hex) Nintendo Co.,Ltd +582F40 (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +08-90-BA (hex) Danlaw Inc +0890BA (base 16) Danlaw Inc + 23700 research Dr. + Farmington Hills 48335 + US + +94-A3-CA (hex) KonnectONE, LLC +94A3CA (base 16) KonnectONE, LLC + 30 N Gould Street STE 4004 + Sheridan WY 82801 + US + +24-4C-E3 (hex) Amazon Technologies Inc. +244CE3 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno 89507 + US + +B8-BE-F4 (hex) devolo AG +B8BEF4 (base 16) devolo AG + Charlottenburger Allee 67 + Aachen NRW 52068 + DE + +00-01-57 (hex) SYSWAVE CO., LTD +000157 (base 16) SYSWAVE CO., LTD + Dongho B/D 5F, 221-2 + KOREA 135-010 + KR + +58-FD-BE (hex) Shenzhen Taikaida Technology Co., Ltd +58FDBE (base 16) Shenzhen Taikaida Technology Co., Ltd + Shenzhen Baoan District Fuyong town Fengtang road Xintian building 613 + shenzhen 518102 + CN + +F4-F1-97 (hex) EMTAKE Inc +F4F197 (base 16) EMTAKE Inc + 14, Pangyoyeok ro 192, Bundang gu + Seongnam city Kyeonggi do 13524 + KR + +6C-ED-51 (hex) NEXCONTROL Co.,Ltd +6CED51 (base 16) NEXCONTROL Co.,Ltd + (#303-1007, Ssangyong 3th) 397, Seokcheon-ro + Bucheon-si Gyeonggi-do 14449 + KR + +04-C3-E6 (hex) IEEE Registration Authority +04C3E6 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +28-63-36 (hex) Siemens AG +286336 (base 16) Siemens AG + Werner-von-Siemens Strasse 50 + Amberg 92224 + DE + +14-D1-69 (hex) HUAWEI TECHNOLOGIES CO.,LTD +14D169 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +10-62-E5 (hex) Hewlett Packard +1062E5 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +00-20-B5 (hex) YASKAWA ELECTRIC CORPORATION +0020B5 (base 16) YASKAWA ELECTRIC CORPORATION + 2-1 Kurosakishiroishi, Yahatanishi-ku, + Kitakyushu 806-0004 + JP + +E0-62-67 (hex) Xiaomi Communications Co Ltd +E06267 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +70-B7-AA (hex) vivo Mobile Communication Co., Ltd. +70B7AA (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +84-B3-1B (hex) Kinexon GmbH +84B31B (base 16) Kinexon GmbH + Schellingstrasse, 35 + München 80799 + DE + +08-25-25 (hex) Xiaomi Communications Co Ltd +082525 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +C4-95-00 (hex) Amazon Technologies Inc. +C49500 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +F4-60-E2 (hex) Xiaomi Communications Co Ltd +F460E2 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +E4-D1-24 (hex) Mojo Networks, Inc. +E4D124 (base 16) Mojo Networks, Inc. + 339 N.Bernardo Ave + Mountain View CA 94043 + US + +00-13-A3 (hex) Siemens Home & Office Comm. Devices +0013A3 (base 16) Siemens Home & Office Comm. Devices + 4849 Alpha Road + Dallas 75244 + US + +B0-B8-67 (hex) Hewlett Packard Enterprise +B0B867 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +C0-03-80 (hex) Juniper Networks +C00380 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +98-BB-99 (hex) Phicomm (Sichuan) Co.,Ltd. +98BB99 (base 16) Phicomm (Sichuan) Co.,Ltd. + 125 longquan street park road,longquan district,chengdu city + Sichuan Chengdu 610015 + CN + +00-26-22 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +002622 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +F8-27-2E (hex) Mercku +F8272E (base 16) Mercku + 509 Beaver Creek Rd. + Waterloo Ontario N2V 2L3 + CA + +9C-C9-50 (hex) Baumer Holding +9CC950 (base 16) Baumer Holding + Hummelstrasse 17 + Frauenfeld Thurgau 8501 + CH + +F8-99-10 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +F89910 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +50-E0-EF (hex) Nokia +50E0EF (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +84-8A-8D (hex) Cisco Systems, Inc +848A8D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +1C-C3-EB (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +1CC3EB (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +50-4C-7E (hex) THE 41ST INSTITUTE OF CETC +504C7E (base 16) THE 41ST INSTITUTE OF CETC + No.98 Xiangjiang Road,Huangdao District,Qingdao,Shandong + Qingdao Shangdong 266555 + CN + +00-14-13 (hex) Trebing & Himstedt Prozeßautomation GmbH & Co. KG +001413 (base 16) Trebing & Himstedt Prozeßautomation GmbH & Co. KG + Wilhelm Hennemann Straße 13 + Schwerin Mecklenburg-Vorpommern 19061 + DE + +00-07-99 (hex) Tipping Point Technologies, Inc. +000799 (base 16) Tipping Point Technologies, Inc. + 7501 B N. Capital of TX Hwy. + Austin TX 78731 + US + +D0-1C-BB (hex) Beijing Ctimes Digital Technology Co., Ltd. +D01CBB (base 16) Beijing Ctimes Digital Technology Co., Ltd. + 7th Floor, Jinzhou Building, Suzhou Street, No.79, Haidian District, + Beijing 100089 + CN + +74-87-BB (hex) Ciena Corporation +7487BB (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +C0-B6-F9 (hex) Intel Corporate +C0B6F9 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +68-DD-26 (hex) Shanghai Focus Vision Security Technology Co.,Ltd +68DD26 (base 16) Shanghai Focus Vision Security Technology Co.,Ltd + No.4888 Hunan Rd, Pudong New District + Shanghai Shanghai 201317 + CN + +28-66-E3 (hex) AzureWave Technology Inc. +2866E3 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +60-F1-8A (hex) HUAWEI TECHNOLOGIES CO.,LTD +60F18A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +EC-38-73 (hex) Juniper Networks +EC3873 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +78-04-73 (hex) Texas Instruments +780473 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +A8-3E-0E (hex) HMD Global Oy +A83E0E (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +10-C1-72 (hex) HUAWEI TECHNOLOGIES CO.,LTD +10C172 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-15-1E (hex) ETHERNET Powerlink Standarization Group (EPSG) +00151E (base 16) ETHERNET Powerlink Standarization Group (EPSG) + c/o Zurich University of Applied Sciences + Winterthur CH-8401 + CH + +00-11-1E (hex) ETHERNET Powerlink Standarization Group (EPSG) +00111E (base 16) ETHERNET Powerlink Standarization Group (EPSG) + c/o University of Applied Sciences + Winterthur ZH CH-8401 + CH + +00-40-9D (hex) DigiBoard +00409D (base 16) DigiBoard + 6400 FLYING CLOUD DRIVE + EDEN PRAIRIE MN 55344 + US + +CC-50-E3 (hex) Espressif Inc. +CC50E3 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +DC-E3-05 (hex) ZAO NPK Rotek +DCE305 (base 16) ZAO NPK Rotek + Prospekt Mira + Moscow 129223 + RU + +A4-DA-32 (hex) Texas Instruments +A4DA32 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +00-0E-EE (hex) Muco Industrie BV +000EEE (base 16) Muco Industrie BV + Pleimuiden 12e + Amsterdam NH 1046 AG + NL + +7C-1C-4E (hex) LG Innotek +7C1C4E (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +D8-B6-B7 (hex) Comtrend Corporation +D8B6B7 (base 16) Comtrend Corporation + 3F-1, 10 Lane 609, Chongxin Road, Section 5, + New Taipei City, Taiwan 24159 + TW + +14-4F-8A (hex) Intel Corporate +144F8A (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-21-06 (hex) RIM Testing Services +002106 (base 16) RIM Testing Services + 440 Phillip Street + Waterloo ON N2L 5R9 + CA + +8C-14-B4 (hex) zte corporation +8C14B4 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +3C-98-72 (hex) Sercomm Corporation. +3C9872 (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +40-C3-C6 (hex) SnapRoute +40C3C6 (base 16) SnapRoute + 3960 Freedom Circle, Suite 100 + Santa Clara CA 95054 + US + +5C-96-56 (hex) AzureWave Technology Inc. +5C9656 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +E0-60-66 (hex) Sercomm Corporation. +E06066 (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +14-93-46 (hex) PNI sensor corporation +149346 (base 16) PNI sensor corporation + 2331 Circadian Way + Santa Rosa CA 95407 + US + +DC-E0-EB (hex) Nanjing Aozheng Information Technology Co.Ltd +DCE0EB (base 16) Nanjing Aozheng Information Technology Co.Ltd + #E1-453, Zidong Road #1,Qixia District + Nanjing jiangsu 210000 + CN + +EC-8C-9A (hex) HUAWEI TECHNOLOGIES CO.,LTD +EC8C9A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B4-86-55 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B48655 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +2C-47-59 (hex) Beijing MEGA preponderance Science & Technology Co. Ltd +2C4759 (base 16) Beijing MEGA preponderance Science & Technology Co. Ltd + Room 2201,No.8,Ruichuang International B Block,Wangjing East Road + Beijing 100102 + CN + +A4-15-66 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +A41566 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Wei fang Export processing Zone + Wei Fang Shan Dong 261205 + CN + +1C-96-5A (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +1C965A (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China + Wei Fang Shan Dong 261205 + CN + +40-1B-5F (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +401B5F (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China + Weifang Shandong 261205 + CN + +A8-E5-52 (hex) JUWEL Aquarium AG & Co. KG +A8E552 (base 16) JUWEL Aquarium AG & Co. KG + Karl-Göx-Straße 1 + Rotenburg / Wümme 27356 + DE + +5C-CD-7C (hex) MEIZU Technology Co.,Ltd. +5CCD7C (base 16) MEIZU Technology Co.,Ltd. + MEIZU Tech Bldg., Technology& Innovation Coast + Zhuhai Guangdong 519085 + CN + +00-13-8A (hex) Qingdao GoerTek Technology Co., Ltd. +00138A (base 16) Qingdao GoerTek Technology Co., Ltd. + Room 605,Innovation Building,Hi-tech Industrial Park, + QINGDAO SHANDONG 266061 + CN + +A8-30-AD (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +A830AD (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Wei fang Export processing Zone + Wei Fang Shan Dong 261205 + CN + +BC-5F-F6 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +BC5FF6 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan + Shenzhen Guangdong 518057 + CN + +C8-E7-D8 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +C8E7D8 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + Mid-Fourth Flr., Building 28, Cui Xi Fourth Road,Ke Yuan West,Nanshan + Shenzhen Guangdong 518057 + CN + +60-D2-1C (hex) Sunnovo International Limited +60D21C (base 16) Sunnovo International Limited + 1717 Haitai Building + Beijing Beijing 100083 + CN + +CC-51-B4 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +CC51B4 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +00-C3-F4 (hex) Samsung Electronics Co.,Ltd +00C3F4 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +B8-8A-EC (hex) Nintendo Co.,Ltd +B88AEC (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +D0-D7-83 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D0D783 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +AC-3B-77 (hex) Sagemcom Broadband SAS +AC3B77 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +B4-6B-FC (hex) Intel Corporate +B46BFC (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B0-FC-0D (hex) Amazon Technologies Inc. +B0FC0D (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +CC-C9-2C (hex) Schindler - PORT Technology +CCC92C (base 16) Schindler - PORT Technology + via della Pace 22 + Locarno Ticino 6600 + CH + +00-1E-39 (hex) Comsys Communication Ltd. +001E39 (base 16) Comsys Communication Ltd. + 9 Hamenofim st. + Herzelia 46725 + IL + +78-72-5D (hex) Cisco Systems, Inc +78725D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +FC-E6-6A (hex) Industrial Software Co +FCE66A (base 16) Industrial Software Co + 85, Aleksandyr Malinov Blvd. Office 6 + Sofia 1715 + BG + +78-36-CC (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +7836CC (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +8C-CF-5C (hex) BEFEGA GmbH +8CCF5C (base 16) BEFEGA GmbH + Reichenbacher Str. 22 + Schwabach Bavaria 91126 + DE + +70-C8-33 (hex) Wirepas Oy +70C833 (base 16) Wirepas Oy + Visiokatu 4 + Tampere 33720 + FI + +0C-73-EB (hex) IEEE Registration Authority +0C73EB (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +04-8A-E1 (hex) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. +048AE1 (base 16) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + Xin Qing Science & Technology Industrial Park,Jin An Town,Doumen ,Zhuhai,Guangdong,PRC + Zhuhai Guangdong 519180 + CN + +F0-B5-D1 (hex) Texas Instruments +F0B5D1 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +00-E0-00 (hex) FUJITSU LIMITED +00E000 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +90-84-8B (hex) HDR10+ Technologies, LLC +90848B (base 16) HDR10+ Technologies, LLC + 3855 SW 153rd Drive + Beaverton OR 97006 + US + +C8-D7-79 (hex) QING DAO HAIER TELECOM CO.,LTD. +C8D779 (base 16) QING DAO HAIER TELECOM CO.,LTD. + No 1 Haier road,Hi-tech Zone,Qingdao,PR.China + Qingdao Shandong 266101 + CN + +10-B3-6F (hex) Bowei Technology Company Limited +10B36F (base 16) Bowei Technology Company Limited + 2F,Building No.6C,1658,Gumei Rd + Shanghai Shanghai 200233 + CN + +FC-9B-C6 (hex) Sumavision Technologies Co.,Ltd +FC9BC6 (base 16) Sumavision Technologies Co.,Ltd + 6F, Block A2, Power Creative Building,No.1 Shangdi East Road, Haidian District + Beijing 100085 + CN + +C8-29-2A (hex) Barun Electronics +C8292A (base 16) Barun Electronics + 869, Jangji-ri, Dongtan-myeon + Hwaseong-si Gyeonggi-do 445812 + KR + +E4-82-CC (hex) Jumptronic GmbH +E482CC (base 16) Jumptronic GmbH + An der Weide 5 + Springe 31832 + DE + +48-60-5F (hex) LG Electronics (Mobile Communications) +48605F (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +B0-41-6F (hex) Shenzhen Maxtang Computer Co.,Ltd +B0416F (base 16) Shenzhen Maxtang Computer Co.,Ltd + 6/F, Bldg.3, Honghui Industrial Park, Liuxian 2nd Rd., Bao'an Dist. + Shenzhen Guangdong 518101 + CN + +50-1D-93 (hex) HUAWEI TECHNOLOGIES CO.,LTD +501D93 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +28-16-A8 (hex) Microsoft Corporation +2816A8 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +F8-F5-32 (hex) ARRIS Group, Inc. +F8F532 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +B0-83-D6 (hex) ARRIS Group, Inc. +B083D6 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +80-C7-C5 (hex) Fiberhome Telecommunication Technologies Co.,LTD +80C7C5 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +E4-43-4B (hex) Dell Inc. +E4434B (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +0C-F5-A4 (hex) Cisco Systems, Inc +0CF5A4 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +9C-2E-A1 (hex) Xiaomi Communications Co Ltd +9C2EA1 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +08-97-34 (hex) Hewlett Packard Enterprise +089734 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +F0-9C-D7 (hex) Guangzhou Blue Cheetah Intelligent Technology Co., Ltd. +F09CD7 (base 16) Guangzhou Blue Cheetah Intelligent Technology Co., Ltd. + Panyu District, Guangzhou City Panyu Avenue North 555 Panyu Energy Technology Park,Industry Building 2 seats 406-407 + Guangzhou Guangdong 511400 + CN + +BC-E1-43 (hex) Apple, Inc. +BCE143 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-70-33 (hex) Apple, Inc. +647033 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-68-78 (hex) Apple, Inc. +846878 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-D0-83 (hex) Apple, Inc. +C8D083 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +0C-6A-BC (hex) Fiberhome Telecommunication Technologies Co.,LTD +0C6ABC (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +00-80-BA (hex) SPECIALIX (ASIA) PTE, LTD +0080BA (base 16) SPECIALIX (ASIA) PTE, LTD + 3 WINTERSELLS ROAD + UNITED KINGDOM + US + +48-0B-B2 (hex) IEEE Registration Authority +480BB2 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +CC-C0-79 (hex) Murata Manufacturing Co., Ltd. +CCC079 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +E0-19-D8 (hex) BH TECHNOLOGIES +E019D8 (base 16) BH TECHNOLOGIES + 12 RUE AMPERE + GRENOBLE 38000 + FR + +60-30-D4 (hex) Apple, Inc. +6030D4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-95-EA (hex) Apple, Inc. +F895EA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-F1-D8 (hex) Apple, Inc. +18F1D8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-CD-5D (hex) HUAWEI TECHNOLOGIES CO.,LTD +3CCD5D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-76-68 (hex) HUAWEI TECHNOLOGIES CO.,LTD +7C7668 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +6C-38-38 (hex) Marking System Technology Co., Ltd. +6C3838 (base 16) Marking System Technology Co., Ltd. + 76-1, Hirakawa Yokomichi + Joyo-shi Kyoto 610-0101 + JP + +30-D9-D9 (hex) Apple, Inc. +30D9D9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-0F-77 (hex) HangZhou Gubei Electronics Technology Co.,Ltd +780F77 (base 16) HangZhou Gubei Electronics Technology Co.,Ltd + HangZhou City, Zhejiang province Binjiang District Jiang Hong Road 611 Building 1 room 106 + Hangzhou ZheJiang 310052 + CN + +A4-38-CC (hex) Nintendo Co.,Ltd +A438CC (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +74-72-1E (hex) Edison Labs Inc. +74721E (base 16) Edison Labs Inc. + 1122 Stanyan St + San Francisco CA 94117 + US + +8C-4C-DC (hex) PLANEX COMMUNICATIONS INC. +8C4CDC (base 16) PLANEX COMMUNICATIONS INC. + Planex Volta Bldg., 2-11-9 Ebisu-Nishi,Shibuya-ku,Tokyo 150-0021,Japan + Tokyo Tokyo 150-0021 + JP + +50-65-F3 (hex) Hewlett Packard +5065F3 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +3C-95-09 (hex) Liteon Technology Corporation +3C9509 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +BC-AB-7C (hex) TRnP KOREA Co Ltd +BCAB7C (base 16) TRnP KOREA Co Ltd + room1308,239 SoHyungRo,WonMiGu, + BuChunCity KyungKiDo 1135 + KR + +64-CB-5D (hex) SIA TeleSet +64CB5D (base 16) SIA TeleSet + Krāslavas iela 5 + Vecstropi, Naujenes par., Daugavpils distr. LV-5413 + LV + +58-21-E9 (hex) TWPI +5821E9 (base 16) TWPI + PMB# 335; 1121 Annapolis Road + Odenton MD 21113 + US + +C4-9F-4C (hex) HUAWEI TECHNOLOGIES CO.,LTD +C49F4C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +0C-70-4A (hex) HUAWEI TECHNOLOGIES CO.,LTD +0C704A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F0-E3-DC (hex) Tecon MT, LLC +F0E3DC (base 16) Tecon MT, LLC + 3rd Khoroshevskaya st - 20 + Moscow 123298 + RU + +A8-DA-01 (hex) Shenzhen NUOLIJIA Digital Technology Co.,Ltd +A8DA01 (base 16) Shenzhen NUOLIJIA Digital Technology Co.,Ltd + A Area of The Second Flood and D Area of The First Floor,Factory Building A,Youxinda Industrial Park,Gengyu Road,Tianliao Community,Gongming Street Office,Guangming New District,Shenzhen City,Guangdong,P.R.China + Shenzhen Guangdong 518000 + CN + +7C-25-86 (hex) Juniper Networks +7C2586 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +F0-41-C8 (hex) IEEE Registration Authority +F041C8 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +CC-99-16 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +CC9916 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +EC-7F-C6 (hex) ECCEL CORPORATION SAS +EC7FC6 (base 16) ECCEL CORPORATION SAS + CRA 106 15A 25 LT 88 MZ 17 BG 1, ZONA FRANCA BOGOTA + BOGOTA D.C. 110921 + CO + +4C-AB-FC (hex) zte corporation +4CABFC (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +7C-2A-31 (hex) Intel Corporate +7C2A31 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-10-D8 (hex) CALISTA +0010D8 (base 16) CALISTA + 56A Packhorse Road + Bucks SL9 8EF ENGLAND + GB + +00-21-94 (hex) Ping Communication +002194 (base 16) Ping Communication + Brenden 18 + Appenzell Meistersrüte AI 9050 + CH + +5C-5A-EA (hex) FORD +5C5AEA (base 16) FORD + 17425 Federal Drive + Allen Park MI 48101 + US + +00-0B-7B (hex) Test-Um Inc. +000B7B (base 16) Test-Um Inc. + 808 Calle Plano + Camarillo CA 93012 + US + +30-FD-38 (hex) Google, Inc. +30FD38 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +00-13-86 (hex) ABB Inc/Totalflow +001386 (base 16) ABB Inc/Totalflow + 123 + Bartlesville OK 74006 + US + +00-3C-10 (hex) Cisco Systems, Inc +003C10 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +54-A6-5C (hex) Technicolor CH USA Inc. +54A65C (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +BC-DD-C2 (hex) Espressif Inc. +BCDDC2 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +98-D8-63 (hex) Shanghai High-Flying Electronics Technology Co., Ltd +98D863 (base 16) Shanghai High-Flying Electronics Technology Co., Ltd + Room 1002 ,#1Building,No.3000 Longdong Avenue,Pudong District,Shanghai,China + shanghai shanghai 201203 + CN + +0C-F3-46 (hex) Xiaomi Communications Co Ltd +0CF346 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +7C-FF-4D (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +7CFF4D (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +74-70-FD (hex) Intel Corporate +7470FD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C8-8F-26 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +C88F26 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +70-3A-73 (hex) Shenzhen Sundray Technologies Company Limited +703A73 (base 16) Shenzhen Sundray Technologies Company Limited + 6th Floor,Block A1, Nanshan iPark, No.1001 XueYuan Road, Nanshan District + Shenzhen Guangdong 518057 + CN + +10-F9-EB (hex) Industria Fueguina de Relojería Electrónica s.a. +10F9EB (base 16) Industria Fueguina de Relojería Electrónica s.a. + Sarmiento 2920 + Rio Grande Tierra de Fuego V9420GIV + AR + +80-AD-16 (hex) Xiaomi Communications Co Ltd +80AD16 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +04-4E-AF (hex) LG Innotek +044EAF (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +18-94-C6 (hex) ShenZhen Chenyee Technology Co., Ltd. +1894C6 (base 16) ShenZhen Chenyee Technology Co., Ltd. + 32F, Tower A, East Pacific International Center, No.7888, Shennan Avenue, Futian District + Shenzhen 518040 + CN + +40-BD-32 (hex) Texas Instruments +40BD32 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +CC-8E-71 (hex) Cisco Systems, Inc +CC8E71 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +38-F5-54 (hex) HISENSE ELECTRIC CO.,LTD +38F554 (base 16) HISENSE ELECTRIC CO.,LTD + No. 218, Qianwangang Rd + Qingdao Shandong 266555 + CN + +88-E9-0F (hex) innomdlelab +88E90F (base 16) innomdlelab + Unnam 1 gil, 3 + Seocho-gu Seoul 06778 + KR + +00-30-74 (hex) EQUIINET LTD. +003074 (base 16) EQUIINET LTD. + EDISON HOUSE + SWINDON, SN3 5JA + GB + +EC-9B-8B (hex) Hewlett Packard Enterprise +EC9B8B (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +B0-B3-AD (hex) HUMAX Co., Ltd. +B0B3AD (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +18-A2-8A (hex) Essel-T Co., Ltd +18A28A (base 16) Essel-T Co., Ltd + 1211 kranztechno, 388 Dunchon-daero + Seongnam-si Jungwon-gu, Gyeonggi-do 13403 + KR + +20-36-5B (hex) Megafone Limited +20365B (base 16) Megafone Limited + Unit 702,7/F,Bankok Bank Building,NO.18 Bonham Strand West + Hong Kong 999077 + HK + +E8-DE-00 (hex) ChongQing GuanFang Technology Co.,LTD +E8DE00 (base 16) ChongQing GuanFang Technology Co.,LTD + 2F, A District,No.3 Middle Section of Mount Huangshan Avenue + ChongQing ChongQing 401121 + CN + +70-C9-4E (hex) Liteon Technology Corporation +70C94E (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +70-D0-81 (hex) Beijing Netpower Technologies Inc. +70D081 (base 16) Beijing Netpower Technologies Inc. + Room 201, Block B, NO. 15 Building, EastZone + Courtyard10, Xibeiwang East Road Haidian District, Beijing 100094 + CN + +FC-64-3A (hex) Samsung Electronics Co.,Ltd +FC643A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A8-51-5B (hex) Samsung Electronics Co.,Ltd +A8515B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-B7-E5 (hex) Rayson Technology Co., Ltd. +54B7E5 (base 16) Rayson Technology Co., Ltd. + 1F No.9 R&D Rd.II, Science-Based Industrial Park + Hsin-Chu 300 + TW + +94-63-72 (hex) vivo Mobile Communication Co., Ltd. +946372 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +BC-0F-A7 (hex) Ouster +BC0FA7 (base 16) Ouster + 350 Treat Ave + San Francisco CA 94110 + US + +F8-C1-20 (hex) Xi'an Link-Science Technology Co.,Ltd +F8C120 (base 16) Xi'an Link-Science Technology Co.,Ltd + 1/F,Block F,Building zhichao Weilai,No.999,10#Caotan Road,Xi'an + xi'an 710016 + CN + +F0-C9-D1 (hex) GD Midea Air-Conditioning Equipment Co.,Ltd. +F0C9D1 (base 16) GD Midea Air-Conditioning Equipment Co.,Ltd. + Midea Global Innovation Center,Beijiao Town,Shunde + Foshan Guangdong 528311 + CN + +34-7E-5C (hex) Sonos, Inc. +347E5C (base 16) Sonos, Inc. + 614 Chapala St + Santa Barbara CA 93101 + US + +B4-FB-F9 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B4FBF9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +50-6F-77 (hex) HUAWEI TECHNOLOGIES CO.,LTD +506F77 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +0C-41-E9 (hex) HUAWEI TECHNOLOGIES CO.,LTD +0C41E9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +3C-E8-24 (hex) HUAWEI TECHNOLOGIES CO.,LTD +3CE824 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +34-5A-06 (hex) SHARP Corporation +345A06 (base 16) SHARP Corporation + 1 Takumi-cho, Sakai-ku + Sakai City Osaka 590-8522 + JP + +00-19-36 (hex) STERLITE OPTICAL TECHNOLOGIES LIMITED +001936 (base 16) STERLITE OPTICAL TECHNOLOGIES LIMITED + E-1,E-2,&E-3 + AURANGABAD MAHARASTRA 431136 + IN + +B8-9F-09 (hex) Wistron Neweb Corporation +B89F09 (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +04-02-CA (hex) Shenzhen Vtsonic Co.,ltd +0402CA (base 16) Shenzhen Vtsonic Co.,ltd + No.35,the 2nd Industrial Zone,Tangxiayong Village,Songgang Town,Bao'an District,Shenzhen,China. + Shenzhen Guangdong 518102 + CN + +3C-FB-5C (hex) Fiberhome Telecommunication Technologies Co.,LTD +3CFB5C (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +74-40-BB (hex) Hon Hai Precision Ind. Co.,Ltd. +7440BB (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +1C-11-61 (hex) Ciena Corporation +1C1161 (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +B4-DE-31 (hex) Cisco Systems, Inc +B4DE31 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A4-40-27 (hex) zte corporation +A44027 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +B4-F7-A1 (hex) LG Electronics (Mobile Communications) +B4F7A1 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +28-ED-E0 (hex) AMPAK Technology, Inc. +28EDE0 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +88-BD-45 (hex) Samsung Electronics Co.,Ltd +88BD45 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-FC-F0 (hex) Samsung Electronics Co.,Ltd +54FCF0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +30-6A-85 (hex) Samsung Electronics Co.,Ltd +306A85 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +4C-DD-31 (hex) Samsung Electronics Co.,Ltd +4CDD31 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +88-B6-EE (hex) Dish Technologies Corp +88B6EE (base 16) Dish Technologies Corp + 94 Inverness Terrace E + Englewood CO 80112 + US + +70-F2-20 (hex) Actiontec Electronics, Inc +70F220 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +D0-81-7A (hex) Apple, Inc. +D0817A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-CA-33 (hex) Apple, Inc. +98CA33 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-AB-1E (hex) Apple, Inc. +68AB1E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-EF-00 (hex) Apple, Inc. +70EF00 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-77-65 (hex) Tiesse SpA +C87765 (base 16) Tiesse SpA + Via Asti + Ivrea TO 10015 + IT + +2C-37-C5 (hex) Qingdao Haier Intelligent Home Appliance Technology Co.,Ltd +2C37C5 (base 16) Qingdao Haier Intelligent Home Appliance Technology Co.,Ltd + ingdao high-tech park haier road 1 + Qingdao Shandong 266101 + CN + +CC-40-D0 (hex) NETGEAR +CC40D0 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +7C-76-30 (hex) Shenzhen YOUHUA Technology Co., Ltd +7C7630 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +98-22-EF (hex) Liteon Technology Corporation +9822EF (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +7C-76-35 (hex) Intel Corporate +7C7635 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +78-80-38 (hex) FUNAI ELECTRIC CO., LTD. +788038 (base 16) FUNAI ELECTRIC CO., LTD. + 7-1, NAKAGAITO 7-CHOME + DAITO OSAKA 5740013 + JP + +BC-FF-EB (hex) Motorola Mobility LLC, a Lenovo Company +BCFFEB (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +00-01-30 (hex) Extreme Networks, Inc. +000130 (base 16) Extreme Networks, Inc. + 3585 Monroe Street + Santa Clara CA 95051 + US + +FC-0A-81 (hex) Extreme Networks, Inc. +FC0A81 (base 16) Extreme Networks, Inc. + 475 Half Day Road + Lincolnshire IL 60069 + US + +F0-45-DA (hex) Texas Instruments +F045DA (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +B8-07-16 (hex) vivo Mobile Communication Co., Ltd. +B80716 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +A8-EE-C6 (hex) Muuselabs NV/SA +A8EEC6 (base 16) Muuselabs NV/SA + Rue du Tocsin 12 + Brussels 1000 + BE + +E4-F0-42 (hex) Google, Inc. +E4F042 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +40-48-FD (hex) IEEE Registration Authority +4048FD (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +20-B3-99 (hex) Enterasys +20B399 (base 16) Enterasys + 50 Minuteman Rd + Andover MA 01810 + US + +CC-2D-21 (hex) Tenda Technology Co.,Ltd.Dongguan branch +CC2D21 (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +00-40-97 (hex) DATEX DIVISION OF +004097 (base 16) DATEX DIVISION OF + INSTRUMENTARIUM CORP. + + FI + +9C-4F-CF (hex) TCT mobile ltd +9C4FCF (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +D8-96-E0 (hex) Alibaba Cloud Computing Ltd. +D896E0 (base 16) Alibaba Cloud Computing Ltd. + Yuhang District of Hangzhou Wenyi Road, Building 1, No. 969 Xixi Park, Zhejiang Province + Hangzhou Zhejiang 310000 + CN + +00-18-62 (hex) Seagate Technology +001862 (base 16) Seagate Technology + 1280 Disc Drive + Shakopee MN 55379 + US + +1C-EE-C9 (hex) Elo touch solutions +1CEEC9 (base 16) Elo touch solutions + 1033 McCarthy Boulevard + Milpitas CA 95035 + US + +00-0C-50 (hex) Seagate Technology +000C50 (base 16) Seagate Technology + M/S NW1F01 + Longmont CO 80503 + US + +34-2A-F1 (hex) Texas Instruments +342AF1 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +20-78-52 (hex) Nokia +207852 (base 16) Nokia + Karaportti 3 + Espoo Finland 02610 + FI + +C8-DE-C9 (hex) Coriant +C8DEC9 (base 16) Coriant + 1415 W. Diehl Rd + Naperville IL 60563 + US + +44-D5-A5 (hex) AddOn Computer +44D5A5 (base 16) AddOn Computer + 15775 Gateway cir + tustin CA 92780 + US + +38-F7-3D (hex) Amazon Technologies Inc. +38F73D (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +C0-A0-0D (hex) ARRIS Group, Inc. +C0A00D (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +0C-61-11 (hex) Anda Technologies SAC +0C6111 (base 16) Anda Technologies SAC + Av. Santa Cruz 888, Miraflores + Lima Peru Lima18 + PE + +00-22-C4 (hex) epro GmbH +0022C4 (base 16) epro GmbH + Joebkesweg 3 + Gronau NRW 48599 + DE + +1C-33-0E (hex) PernixData +1C330E (base 16) PernixData + 1745 Technology Drive, Suite 800 + San Jose CA 95110 + US + +B8-F7-4A (hex) RCNTEC +B8F74A (base 16) RCNTEC + Polkovaya street 3 + Moscow 127018 + RU + +64-51-06 (hex) Hewlett Packard +645106 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +0C-15-39 (hex) Apple, Inc. +0C1539 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-56-97 (hex) Amazon Technologies Inc. +6C5697 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +00-05-FF (hex) SNS Solutions, Inc. +0005FF (base 16) SNS Solutions, Inc. + 2nd Fl. Hill House, + + KR + +F8-7B-20 (hex) Cisco Systems, Inc +F87B20 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E0-AA-DB (hex) Nanjing PANENG Technology Development Co.,Ltd +E0AADB (base 16) Nanjing PANENG Technology Development Co.,Ltd + NO.6 Paneng Road,Nanjing High-tech Zone,Jiang Su,China + Nanjing 210061 + CN + +EC-F4-51 (hex) Arcadyan Corporation +ECF451 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +58-12-43 (hex) AcSiP Technology Corp. +581243 (base 16) AcSiP Technology Corp. + 3F., No.22, Dalin Rd., + Taoyuan Taoyuan County 33067 + TW + +A8-9F-EC (hex) ARRIS Group, Inc. +A89FEC (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-BE-9E (hex) Fiberhome Telecommunication Technologies Co.,LTD +00BE9E (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +54-C5-7A (hex) Sunnovo International Limited +54C57A (base 16) Sunnovo International Limited + 1717 Haitai Building + Beijing Beijing 100083 + CN + +58-C1-7A (hex) Cambium Networks Limited +58C17A (base 16) Cambium Networks Limited + Unit B2, Linhay Business Park, + Ashburton Devon TQ13 7UP + GB + +38-01-9F (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +38019F (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +24-5C-CB (hex) AXIe Consortium, Inc. +245CCB (base 16) AXIe Consortium, Inc. + P.O. Box 1016 + Niwot CO 80544-1016 + US + +60-9B-C8 (hex) Hipad Intelligent Technology Co., Ltd. +609BC8 (base 16) Hipad Intelligent Technology Co., Ltd. + No. 688, East of Huangtang Street, LinkongEconomy District + Nanchang Jiangxi 330000 + CN + +40-6A-8E (hex) Hangzhou Puwell OE Tech Ltd. +406A8E (base 16) Hangzhou Puwell OE Tech Ltd. + Letel Technology Park, 500 Qiuyi Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +1C-0F-AF (hex) Lucid Vision Labs +1C0FAF (base 16) Lucid Vision Labs + Unit 130 - 13200 Delf Place + Richmond BC V6V2A2 + CA + +88-B4-A6 (hex) Motorola Mobility LLC, a Lenovo Company +88B4A6 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +28-CF-08 (hex) ESSYS +28CF08 (base 16) ESSYS + gaetbeol-ro + Incheon 21999 + KR + +00-21-28 (hex) Oracle Corporation +002128 (base 16) Oracle Corporation + 17 Network Circle + Menlo Park CA 95025 + US + +00-1C-73 (hex) Arista Networks +001C73 (base 16) Arista Networks + 5470 Great America Pkwy + Santa Clara 95054 + US + +2C-8A-72 (hex) HTC Corporation +2C8A72 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +38-AD-8E (hex) New H3C Technologies Co., Ltd +38AD8E (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +34-D0-B8 (hex) IEEE Registration Authority +34D0B8 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D0-67-26 (hex) Hewlett Packard Enterprise +D06726 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +EC-FA-F4 (hex) SenRa Tech Pvt. Ltd +ECFAF4 (base 16) SenRa Tech Pvt. Ltd + 133, First Floor, Lane No. 1, Westend Marg, Saidulajab + New Delhi 110030 + IN + +D8-8F-76 (hex) Apple, Inc. +D88F76 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-9C-28 (hex) Apple, Inc. +409C28 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-A1-76 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +5CA176 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +58-38-79 (hex) RICOH COMPANY, LTD. +583879 (base 16) RICOH COMPANY, LTD. + 1005, Shimo-ogino + Atsugi-City Kanagawa-Pref. 243-0298 + JP + +F4-4C-70 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +F44C70 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +C8-E7-F0 (hex) Juniper Networks +C8E7F0 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +B0-93-5B (hex) ARRIS Group, Inc. +B0935B (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F4-49-EF (hex) EMSTONE +F449EF (base 16) EMSTONE + #310, Ace Techno Tower 3rd, 38 Digital-ro-29-gil + Guro-Gu Seoul 08381 + KR + +54-DF-24 (hex) Fiberhome Telecommunication Technologies Co.,LTD +54DF24 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +AC-1D-DF (hex) IEEE Registration Authority +AC1DDF (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E8-D8-19 (hex) AzureWave Technology Inc. +E8D819 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +78-2D-7E (hex) TRENDnet, Inc. +782D7E (base 16) TRENDnet, Inc. + 20675 Manhattan Place + Torrance CA 90501 + US + +74-1A-E0 (hex) IEEE Registration Authority +741AE0 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +24-B2-09 (hex) Avaya Inc +24B209 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +FC-65-DE (hex) Amazon Technologies Inc. +FC65DE (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +B0-6E-BF (hex) ASUSTek COMPUTER INC. +B06EBF (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +60-3D-26 (hex) Technicolor CH USA Inc. +603D26 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +BC-90-3A (hex) Robert Bosch GmbH +BC903A (base 16) Robert Bosch GmbH + Postfach 1661 + Leonberg 71226 + DE + +D0-B1-28 (hex) Samsung Electronics Co.,Ltd +D0B128 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +BC-54-51 (hex) Samsung Electronics Co.,Ltd +BC5451 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +74-86-0B (hex) Cisco Systems, Inc +74860B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +18-2D-98 (hex) Jinwoo Industrial system +182D98 (base 16) Jinwoo Industrial system + 7F,Jinwoo Building,149 dosan-daero + seoul gangnamgu 06036 + KR + +D8-A5-34 (hex) Spectronix Corporation +D8A534 (base 16) Spectronix Corporation + 3-28-15, Tarumi-cho + Suita-city Osaka 564-0062 + JP + +EC-51-BC (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +EC51BC (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +F0-79-E8 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +F079E8 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +78-32-1B (hex) D-Link International +78321B (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +60-18-03 (hex) Daikin Air-conditioning (Shanghai) Co., Ltd. +601803 (base 16) Daikin Air-conditioning (Shanghai) Co., Ltd. + 318 Shen Fu Road, Xin Zhuang Industry Zone, Shanghai, 201108, China + Shanghai 201108 + CN + +00-A0-96 (hex) MITSUMI ELECTRIC CO.,LTD. +00A096 (base 16) MITSUMI ELECTRIC CO.,LTD. + 2-11-2, Tsurumaki + Tama-shi Tokyo 206-8567 + JP + +78-61-7C (hex) MITSUMI ELECTRIC CO.,LTD. +78617C (base 16) MITSUMI ELECTRIC CO.,LTD. + 2-11-2, Tsurumaki + Tama-shi Tokyo 206-8567 + JP + +94-0E-6B (hex) HUAWEI TECHNOLOGIES CO.,LTD +940E6B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +64-FB-50 (hex) RoomReady/Zdi, Inc. +64FB50 (base 16) RoomReady/Zdi, Inc. + 2200 N. Main Street + Normal IL 61761 + US + +74-EA-C8 (hex) New H3C Technologies Co., Ltd +74EAC8 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +B4-D6-4E (hex) Caldero Limited +B4D64E (base 16) Caldero Limited + Concordia Works, 30 Sovereign Street + Leeds West Yorkshire LS1 4BA + GB + +F8-9D-BB (hex) Tintri +F89DBB (base 16) Tintri + 303 Ravendale Dr + Mountain View CA 94070 + US + +D8-A0-1D (hex) Espressif Inc. +D8A01D (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +C4-F3-12 (hex) Texas Instruments +C4F312 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +90-4E-91 (hex) IEEE Registration Authority +904E91 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +5C-E8-B7 (hex) Oraimo Technology Limited +5CE8B7 (base 16) Oraimo Technology Limited + RMS 05-15,13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG + HONG KONG HONG KONG 999077 + HK + +3C-11-B2 (hex) Fraunhofer FIT +3C11B2 (base 16) Fraunhofer FIT + Schloss Birlinghoven + Sankt Augustin 53754 + DE + +10-4B-46 (hex) Mitsubishi Electric Corporation +104B46 (base 16) Mitsubishi Electric Corporation + 2-7-3 + Chiyoda-ku Tokyo 100-8310 + JP + +DC-0C-2D (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +DC0C2D (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Gaoxin 2 Road, Free Trade Zone,Weifang,Shandong,261205,P.R.China + Weifang Shandong 261205 + CN + +D0-67-E5 (hex) Dell Inc. +D067E5 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +8C-FE-B4 (hex) VSOONTECH ELECTRONICS CO., LIMITED +8CFEB4 (base 16) VSOONTECH ELECTRONICS CO., LIMITED + 18th, Floor, On Hong Commericial Building, 145 Hennessy Road, Wanchai, HONG KONG + HongKong 999077 + HK + +CC-66-B2 (hex) Nokia +CC66B2 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +68-EC-C5 (hex) Intel Corporate +68ECC5 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +9C-65-EE (hex) DASAN Network Solutions +9C65EE (base 16) DASAN Network Solutions + DASAN Tower 8F, 49 Daewangpangyo-ro644beon-gil Bundang-gu + Seongnam-si Gyeonggi-do 13493 + KR + +78-CA-04 (hex) Nokia Corporation +78CA04 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +34-29-8F (hex) IEEE Registration Authority +34298F (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +5C-EA-1D (hex) Hon Hai Precision Ind. Co.,Ltd. +5CEA1D (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +18-14-56 (hex) Nokia Corporation +181456 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu Ou 90590 + FI + +00-17-C8 (hex) KYOCERA Display Corporation +0017C8 (base 16) KYOCERA Display Corporation + 2-14-9, Tamagawadai + Tokyo 158-8610 + JP + +38-E2-DD (hex) zte corporation +38E2DD (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +88-5D-FB (hex) zte corporation +885DFB (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +58-B4-2D (hex) YSTen Technology Co.,Ltd +58B42D (base 16) YSTen Technology Co.,Ltd + Room 1715,17/F North Star Times Tower,Chaoyang District,Beijing. + Beijing 100101 + CN + +E0-48-D3 (hex) MOBIWIRE MOBILES (NINGBO) CO.,LTD +E048D3 (base 16) MOBIWIRE MOBILES (NINGBO) CO.,LTD + No.999,Dacheng East Road, + Fenghua Zhejiang 315500 + CN + +58-E2-8F (hex) Apple, Inc. +58E28F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-7B-8A (hex) Apple, Inc. +787B8A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +4C-16-FC (hex) Juniper Networks +4C16FC (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +48-BC-A6 (hex) ​ASUNG TECHNO CO.,Ltd +48BCA6 (base 16) ​ASUNG TECHNO CO.,Ltd + 462, Dogok-ro, Songpa-gu, Seoul, Republic of Korea + SEOUL Repubilc of KOREA 05574 + KR + +B0-09-DA (hex) Ring Solutions +B009DA (base 16) Ring Solutions + 1200 Atwater Drive, Suite 225 + Malvern PA 19355 + US + +00-05-4F (hex) Garmin International +00054F (base 16) Garmin International + 1200 E. 151st St + Olathe KS 66062 + US + +00-5C-86 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +005C86 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +30-05-3F (hex) JTI Co.,Ltd. +30053F (base 16) JTI Co.,Ltd. + 102-1508, 36, Bucheon-ro 198beon-gil, + Buchcheon-si Gyeonggi-do 14557 + KR + +B8-DB-1C (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +B8DB1C (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +3C-10-E6 (hex) PHAZR Inc. +3C10E6 (base 16) PHAZR Inc. + 8, Presitige Circle, Suite 104 + Allen TX 75002 + US + +90-45-06 (hex) Tokyo Boeki Medisys Inc. +904506 (base 16) Tokyo Boeki Medisys Inc. + 1-14-21, Higashitoyoda + Hino Tokyo 191-0052 + JP + +00-21-A1 (hex) Cisco Systems, Inc +0021A1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +FC-B6-98 (hex) Cambridge Industries(Group) Co.,Ltd. +FCB698 (base 16) Cambridge Industries(Group) Co.,Ltd. + 22 Floor,Qilai Tower;889 Yishan Road + Shanghai CHINA 200233 + CN + +00-01-CD (hex) ARtem +0001CD (base 16) ARtem + Olgastraße 152 + + DE + +5C-54-6D (hex) HUAWEI TECHNOLOGIES CO.,LTD +5C546D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +84-A1-D1 (hex) Sagemcom Broadband SAS +84A1D1 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +90-9D-7D (hex) ARRIS Group, Inc. +909D7D (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +78-8C-4D (hex) Indyme Solutions, LLC +788C4D (base 16) Indyme Solutions, LLC + 8295 Aero Place Ste 260 + San Diego CA 92123 + US + +78-BC-1A (hex) Cisco Systems, Inc +78BC1A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0E-59 (hex) Sagemcom Broadband SAS +000E59 (base 16) Sagemcom Broadband SAS + 2, rue du petit Albi + CERGY SAINT CHRISTOPHE val d'Oise 95800 + FR + +10-1D-51 (hex) 8Mesh Networks Limited +101D51 (base 16) 8Mesh Networks Limited + Unit 607, 6/F, Yen Sheng Centre, + 64 Hoi Yuen Road Kwun Tong 000 + HK + +DC-EB-53 (hex) Wuhan QianXiao Elecronic Technology CO.,LTD +DCEB53 (base 16) Wuhan QianXiao Elecronic Technology CO.,LTD + Guanggu Xinzhongxin, No.303 of Guanggu road, East lake development zone + wuhan hubei 430000 + CN + +EC-8A-C7 (hex) Fiberhome Telecommunication Technologies Co.,LTD +EC8AC7 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +88-36-5F (hex) LG Electronics (Mobile Communications) +88365F (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +28-8C-B8 (hex) zte corporation +288CB8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +FC-7F-56 (hex) CoSyst Control Systems GmbH +FC7F56 (base 16) CoSyst Control Systems GmbH + Martin-Albert-Str. 1 + Nürnberg Bayern 90491 + DE + +2C-40-53 (hex) Samsung Electronics Co.,Ltd +2C4053 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +0C-8F-FF (hex) HUAWEI TECHNOLOGIES CO.,LTD +0C8FFF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +54-B1-21 (hex) HUAWEI TECHNOLOGIES CO.,LTD +54B121 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +28-80-A2 (hex) Novatel Wireless Solutions, Inc. +2880A2 (base 16) Novatel Wireless Solutions, Inc. + 9605 Scranton Road Suite 200 + San Diego 92121 + US + +78-81-02 (hex) Sercomm Corporation. +788102 (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +84-AA-9C (hex) MitraStar Technology Corp. +84AA9C (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +F0-EF-D2 (hex) TF PAYMENT SERVICE CO., LTD +F0EFD2 (base 16) TF PAYMENT SERVICE CO., LTD + 5F Shibadaimon Center Building, 1-10-11 Shibadaimon + Minato-ku Tokyo 105-0012 + JP + +24-B2-DE (hex) Espressif Inc. +24B2DE (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +F4-93-9F (hex) Hon Hai Precision Ind. Co., Ltd. +F4939F (base 16) Hon Hai Precision Ind. Co., Ltd. + GuangDongShenZhen + ShenZhen GuangDong 518109 + CN + +00-07-26 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +000726 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + A211-A213 & B201-B210, 2F, Baiying Building, 1019#, Nanhai RD, Shekou Party, Nanshan District, + Shenzhen Guangdong 518067 + CN + +FC-8B-97 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +FC8B97 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + B116,B118,A211-A213,B201-B213,A311-A313,B411-413,BF08-09 Nanshan Medical Instrument Industry Park, + Shenzhen Guangdong 518067 + CN + +2C-AB-25 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +2CAB25 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + B116,B118,A211-A213,B201-B213,A311-A313,B411-413,BF08-09 Nanshan Medical Instrument Industry Park, + Shenzhen Guangdong 518067 + CN + +1C-A5-32 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +1CA532 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + 1#SongGang RD, Bao'an Dist., Shenzhen, Guangdong,China + Shenzhen Guangdong 518109 + CN + +00-1F-92 (hex) Avigilon Corporation +001F92 (base 16) Avigilon Corporation + Box 378, 101 - 1001 West Broadway + Vancouver BC V6H 4E4 + CA + +00-0C-03 (hex) HDMI Licensing, LLC +000C03 (base 16) HDMI Licensing, LLC + 1060 East Arques Ave. + Sunnyvale CA 94085 + US + +7C-BA-CC (hex) IEEE Registration Authority +7CBACC (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +94-F1-28 (hex) Hewlett Packard Enterprise +94F128 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville 95747 + US + +10-1B-54 (hex) HUAWEI TECHNOLOGIES CO.,LTD +101B54 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +A8-0C-63 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A80C63 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +5C-C3-07 (hex) HUAWEI TECHNOLOGIES CO.,LTD +5CC307 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E0-10-7F (hex) Ruckus Wireless +E0107F (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +C4-01-7C (hex) Ruckus Wireless +C4017C (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +04-FA-3F (hex) Opticore Inc. +04FA3F (base 16) Opticore Inc. + 97 Jungbudaero448beongil, Yeongtonggu + Suwonsi Gyeonggido 16521 + KR + +54-02-37 (hex) Teltronic AG +540237 (base 16) Teltronic AG + Gewerbestrasse 9 + Biberist 4562 + CH + +4C-B0-08 (hex) Shenzhen Gwelltimes Technology Co.,Ltd +4CB008 (base 16) Shenzhen Gwelltimes Technology Co.,Ltd + A4 building 15floor Zhongying Jewelry Industrial Park Bulan Road No.31 Nanwan Street Longgang District Shenzhen City China + Shenzhen 518112 + CN + +E8-6F-F2 (hex) Actiontec Electronics, Inc +E86FF2 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +00-50-18 (hex) AMIT, Inc. +005018 (base 16) AMIT, Inc. + No.32, Huangong Rd., + Yongkang City, Tainan County 71041 + TW + +70-DE-F9 (hex) FAI WAH INTERNATIONAL (HONG KONG) LIMITED +70DEF9 (base 16) FAI WAH INTERNATIONAL (HONG KONG) LIMITED + Room 19, 8F.,Corporation Park, 11 On Lai Street,Shatin,Shek Mun,N.T.Hong Kong + Hong Kong 999077 + HK + +B0-EA-BC (hex) ASKEY COMPUTER CORP +B0EABC (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +94-C6-91 (hex) EliteGroup Computer Systems Co., LTD +94C691 (base 16) EliteGroup Computer Systems Co., LTD + No.239, Sec. 2, TiDing Blvd. Nei-Hu Dist. + Taipei Taiwan 11439 + TW + +3C-F5-91 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +3CF591 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +60-21-01 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +602101 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +7C-EB-7F (hex) Dmet Products Corp. +7CEB7F (base 16) Dmet Products Corp. + 118, Fujisoft Akihabara Bldg 12F, Kanda Neribeicho 3 + Chiyodaku Tokyo 1010022 + JP + +8C-85-80 (hex) Smart Innovation LLC +8C8580 (base 16) Smart Innovation LLC + 7F,Tower B,Jianxing + ShenZhen GuangZhou 518055 + CN + +40-42-29 (hex) Layer3TV, Inc +404229 (base 16) Layer3TV, Inc + 1660 Wynkoop St - Suite 800 + Denver CO 80202 + US + +FC-2F-6B (hex) Everspin Technologies, Inc. +FC2F6B (base 16) Everspin Technologies, Inc. + 1347 N. Alma School Rd., Suite 220 + Chandler AZ 85224 + US + +28-7B-09 (hex) zte corporation +287B09 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-25-C4 (hex) Ruckus Wireless +0025C4 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +C0-C5-20 (hex) Ruckus Wireless +C0C520 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +78-B2-8D (hex) Beijing Tengling Technology CO.Ltd +78B28D (base 16) Beijing Tengling Technology CO.Ltd + beijing haidian shangdi san jie + beijing 100086 + CN + +A8-80-38 (hex) ShenZhen MovingComm Technology Co., Limited +A88038 (base 16) ShenZhen MovingComm Technology Co., Limited + 5F, FuXinFa Industrial Park, LiuXianDong Industrial Zone, + ShenZhen GuangDong 518055 + CN + +F8-1D-90 (hex) Solidwintech +F81D90 (base 16) Solidwintech + 6th Floor, SOLiD Space 220 Pangyoyeok-ro, Bundang-gu + Seongnam-si Gyeongi-do 13493 + KR + +A0-6A-44 (hex) Vizio, Inc +A06A44 (base 16) Vizio, Inc + 39 Tesla + Irvine CA 92618 + US + +DC-BE-7A (hex) Zhejiang Nurotron Biotechnology Co. +DCBE7A (base 16) Zhejiang Nurotron Biotechnology Co. + Building4, No.99 Xiaomao Rd + Hangzhou zhejiang 310011 + CN + +34-38-B7 (hex) HUMAX Co., Ltd. +3438B7 (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +CC-06-77 (hex) Fiberhome Telecommunication Technologies Co.,LTD +CC0677 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +78-45-01 (hex) Biamp Systems +784501 (base 16) Biamp Systems + 9300 SW Gemini Dr + Beaverton OR 97008 + US + +30-9C-23 (hex) Micro-Star INTL CO., LTD. +309C23 (base 16) Micro-Star INTL CO., LTD. + No.69, Lide St., + New Taipei City Taiwan 235 + TW + +14-5E-45 (hex) Kaleao Limited +145E45 (base 16) Kaleao Limited + Sheraton House, Castle Park + Cambridge CAMBRIDGESHIRE CB3 0AX + GB + +54-D7-51 (hex) Proximus +54D751 (base 16) Proximus + Bld du Roi Albert II 27 + Brussels 1030 + BE + +14-78-0B (hex) Varex Imaging Deutschland AG +14780B (base 16) Varex Imaging Deutschland AG + Zweigniederlassung/Branch Walluf + In der Rehbach 22 Walluf 65396 + DE + +AC-AF-B9 (hex) Samsung Electronics Co.,Ltd +ACAFB9 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +88-B1-11 (hex) Intel Corporate +88B111 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +8C-39-5C (hex) Bit4id Srl +8C395C (base 16) Bit4id Srl + Via Diocleziano, 107 + Naples 80125 + IT + +D4-25-8B (hex) Intel Corporate +D4258B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +04-1B-6D (hex) LG Electronics (Mobile Communications) +041B6D (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +F4-41-56 (hex) Arrikto Inc. +F44156 (base 16) Arrikto Inc. + 3505 El Camino Real + Palo Alto CA 94306 + US + +00-80-C2 (hex) IEEE 802.1 Working Group +0080C2 (base 16) IEEE 802.1 Working Group + 802.1 CHAIR c/o IEEE + Piscataway NJ 08554 + US + +68-8D-B6 (hex) AETEK INC. +688DB6 (base 16) AETEK INC. + 3F, No.192, Lien-Cheng Rd., Chung-Ho, + New Taipei City 23553 + TW + +EC-F3-42 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +ECF342 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +50-FF-20 (hex) Keenetic Limited +50FF20 (base 16) Keenetic Limited + 1202, 12/F., AT TOWER, 180 ELECTRIC ROAD, NORTH POINT + HONG KONG 852 + HK + +E4-57-40 (hex) ARRIS Group, Inc. +E45740 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F8-94-C2 (hex) Intel Corporate +F894C2 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +70-D3-79 (hex) Cisco Systems, Inc +70D379 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-F8-2C (hex) Cisco Systems, Inc +00F82C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-C1-B1 (hex) Cisco Systems, Inc +00C1B1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F4-FC-B1 (hex) JJ Corp +F4FCB1 (base 16) JJ Corp + 88 Soha-ro + Gwangmyeong-si 14316 + KR + +D8-C8-E9 (hex) Phicomm (Shanghai) Co., Ltd. +D8C8E9 (base 16) Phicomm (Shanghai) Co., Ltd. + 3666 SiXian Rd.,Songjiang District + Shanghai Shanghai 201616 + CN + +7C-B9-60 (hex) Shanghai X-Cheng telecom LTD +7CB960 (base 16) Shanghai X-Cheng telecom LTD + ROOM 401, Building 5, No.3000 LONG DONG Avenue, Pudong New District, Shanghai + Shanghai Shanghai 201203 + CN + +B0-3D-96 (hex) Vision Valley FZ LLC +B03D96 (base 16) Vision Valley FZ LLC + Dubai Internet City + Dubai Dubai 500294 + AE + +98-6C-5C (hex) Jiangxi Gosun Guard Security Co.,Ltd +986C5C (base 16) Jiangxi Gosun Guard Security Co.,Ltd + 2rd floor,8 building Middle,Zhongxing Software Park,Changdong Avenue,Nanchang High Tech Zone,Nanchang city,Jiangxi province + Nan Chang City Jiang Xi Province 330000 + CN + +24-79-2A (hex) Ruckus Wireless +24792A (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +30-D3-86 (hex) zte corporation +30D386 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +70-DB-98 (hex) Cisco Systems, Inc +70DB98 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B4-2A-0E (hex) Technicolor CH USA Inc. +B42A0E (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +9C-C8-AE (hex) Becton, Dickinson and Company +9CC8AE (base 16) Becton, Dickinson and Company + 1 Becton Drive + Franklin Lakes MA 07417-1880 + US + +B0-35-9F (hex) Intel Corporate +B0359F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C0-D9-62 (hex) ASKEY COMPUTER CORP +C0D962 (base 16) ASKEY COMPUTER CORP + 10F,NO.119,JIANKANG RD.,ZHONGHE DIST XINBEI CITY + taipei TAIPEI 23585 + TW + +F8-0B-CB (hex) Cisco Systems, Inc +F80BCB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +50-D3-7F (hex) Yu Fly Mikly Way Science and Technology Co., Ltd. +50D37F (base 16) Yu Fly Mikly Way Science and Technology Co., Ltd. + 6F, No. 1168 Huyi Road, Nanxiang Town Jiading District Shanghai 201800 CHINA + shanghai 201800 + CN + +18-12-12 (hex) Cepton Technologies +181212 (base 16) Cepton Technologies + 103 Bonaventura Dr + San Jose CA 95134 + US + +70-D9-23 (hex) vivo Mobile Communication Co., Ltd. +70D923 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'an DongGuan City,Guangdong 523860 + CN + +B8-3A-08 (hex) Tenda Technology Co.,Ltd.Dongguan branch +B83A08 (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +28-B4-48 (hex) HUAWEI TECHNOLOGIES CO.,LTD +28B448 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +10-05-01 (hex) PEGATRON CORPORATION +100501 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +2C-FA-A2 (hex) Alcatel-Lucent Enterprise +2CFAA2 (base 16) Alcatel-Lucent Enterprise + 26801 West Agoura Rd + Calabasas CA 91301 + US + +A4-9B-F5 (hex) Hybridserver Tec GmbH +A49BF5 (base 16) Hybridserver Tec GmbH + Gutenbergring 26a + Norderstedt Schleswig-Holstein 22848 + DE + +50-3D-A1 (hex) Samsung Electronics Co.,Ltd +503DA1 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +F0-97-E5 (hex) TAMIO, INC +F097E5 (base 16) TAMIO, INC + 12F-2, No.33, Sec. 1 , Mingsheng Rd.,Banqiao Dist + New Taipei City 22069 + TW + +4C-1A-3D (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +4C1A3D (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +08-02-8E (hex) NETGEAR +08028E (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +E8-E7-32 (hex) Alcatel-Lucent Enterprise +E8E732 (base 16) Alcatel-Lucent Enterprise + 26801 West Agoura Road + Calabasas CA 91301 + US + +B4-7C-9C (hex) Amazon Technologies Inc. +B47C9C (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +F4-A7-39 (hex) Juniper Networks +F4A739 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +F4-70-AB (hex) vivo Mobile Communication Co., Ltd. +F470AB (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +2C-5A-0F (hex) Cisco Systems, Inc +2C5A0F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +2C-31-24 (hex) Cisco Systems, Inc +2C3124 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +50-32-37 (hex) Apple, Inc. +503237 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B0-48-1A (hex) Apple, Inc. +B0481A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B4-9C-DF (hex) Apple, Inc. +B49CDF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-BF-6B (hex) Apple, Inc. +48BF6B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-1D-B8 (hex) ARRIS Group, Inc. +2C1DB8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +58-82-1D (hex) H. Schomäcker GmbH +58821D (base 16) H. Schomäcker GmbH + Heidestr. 183 + Köln 51147 + DE + +D8-A1-05 (hex) Syslane, Co., Ltd. +D8A105 (base 16) Syslane, Co., Ltd. + #1201, Megacenter, SKntechno-park,, Sangdaeweon-dong, Joongweon-gu + Seongnam Outside the US, Mexico, or Canada 462-721 + KR + +BC-A0-42 (hex) SHANGHAI FLYCO ELECTRICAL APPLIANCE CO.,LTD +BCA042 (base 16) SHANGHAI FLYCO ELECTRICAL APPLIANCE CO.,LTD + No.555,Guang Fu Lin east Road,Songjiang District + Shanghai Shanghai 201613 + CN + +3C-05-18 (hex) Samsung Electronics Co.,Ltd +3C0518 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +90-06-28 (hex) Samsung Electronics Co.,Ltd +900628 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B4-A9-FE (hex) GHIA Technology (Shenzhen) LTD +B4A9FE (base 16) GHIA Technology (Shenzhen) LTD + RM 1606, BLDG 3rd, COFCO Clouds Mansion + Shenzhen 518101 + CN + +08-B2-58 (hex) Juniper Networks +08B258 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +9C-84-BF (hex) Apple, Inc. +9C84BF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +1C-A0-D3 (hex) IEEE Registration Authority +1CA0D3 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +9C-FC-D1 (hex) Aetheris Technology (Shanghai) Co., Ltd. +9CFCD1 (base 16) Aetheris Technology (Shanghai) Co., Ltd. + Room 225, Building No. 8, 433 Yuyuan Road + Shanghai Shanghai 200040 + CN + +CC-CE-1E (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +CCCE1E (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +0C-F4-D5 (hex) Ruckus Wireless +0CF4D5 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +7C-26-64 (hex) Sagemcom Broadband SAS +7C2664 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +AC-6B-0F (hex) CADENCE DESIGN SYSTEMS INC +AC6B0F (base 16) CADENCE DESIGN SYSTEMS INC + 2670 SEELY AVE + SAN JOSE CA 95134 + US + +C8-B5-AD (hex) Hewlett Packard Enterprise +C8B5AD (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +7C-38-66 (hex) Texas Instruments +7C3866 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +0C-61-CF (hex) Texas Instruments +0C61CF (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +9C-1D-58 (hex) Texas Instruments +9C1D58 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +38-05-AC (hex) Piller Group GmbH +3805AC (base 16) Piller Group GmbH + Abgunst 24 + Osterode 37520 + DE + +34-6E-9D (hex) Ericsson AB +346E9D (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +68-54-C1 (hex) ColorTokens, Inc. +6854C1 (base 16) ColorTokens, Inc. + 2101 Tasman Dr. Suite 200A + Santa Clara CA 95054 + US + +00-11-1B (hex) Targa Systems Div L-3 Communications +00111B (base 16) Targa Systems Div L-3 Communications + 2081 Merivale Rd + Ottawa Ont K2G 1G9 + CA + +6C-75-0D (hex) WiFiSONG +6C750D (base 16) WiFiSONG + Rm. 605, Building 3, No. 75 Wenyi West Road + Hangzhou Zhejiang 310012 + CN + +BC-3F-8F (hex) HUAWEI TECHNOLOGIES CO.,LTD +BC3F8F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +14-30-04 (hex) HUAWEI TECHNOLOGIES CO.,LTD +143004 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-DC-41 (hex) YOUNGZONE CULTURE (SHANGHAI) CORP +F4DC41 (base 16) YOUNGZONE CULTURE (SHANGHAI) CORP + 7-8th floor, #1 Building, 1006 Jinshajiang Road + Shanghai Shanghai 200062 + CN + +C4-83-6F (hex) Ciena Corporation +C4836F (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +7C-C6-C4 (hex) Kolff Computer Supplies b.v. +7CC6C4 (base 16) Kolff Computer Supplies b.v. + Kuipershaven 22 + Dordrecht Zuid-Holland 3311 AL + NL + +00-0F-4F (hex) PCS Systemtechnik GmbH +000F4F (base 16) PCS Systemtechnik GmbH + 66 Hillside Rd + Auckland 1310 + NZ + +A8-0C-CA (hex) Shenzhen Sundray Technologies Company Limited +A80CCA (base 16) Shenzhen Sundray Technologies Company Limited + 6th Floor,Block A1, Nanshan iPark, No.1001 XueYuan Road, Nanshan District + Shenzhen Guangdong 518057 + CN + +38-AA-3C (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +38AA3C (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Maetan3-Dong, Yeongtong-Gu + Suwon 443-743 + US + +00-03-02 (hex) Charles Industries, Ltd. +000302 (base 16) Charles Industries, Ltd. + 5600 Apollo Drive + Rolling Meadows IL 60008 + US + +50-A4-D0 (hex) IEEE Registration Authority +50A4D0 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +80-00-10 (hex) AT&T +800010 (base 16) AT&T + 3300 E Renner Road + Richardson TX 75082 + US + +00-24-F1 (hex) Shenzhen Fanhai Sanjiang Electronics Co., Ltd. +0024F1 (base 16) Shenzhen Fanhai Sanjiang Electronics Co., Ltd. + 3Floor-Guangcai Xintiandi Building,Nanshan Rd,Nanshan, + Shenzhen Guangdong 518054 + CN + +14-2F-FD (hex) LT SECURITY INC +142FFD (base 16) LT SECURITY INC + 18738 SAN JOSE AVE + CITY OF INDUSTRY CA 91748 + US + +0C-3C-CD (hex) Universal Global Scientific Industrial Co., Ltd. +0C3CCD (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, Lane 351, Taiping Road, Sec.1,Tsao Tuen + Nan-Tou Taiwan 54261 + TW + +14-AB-C5 (hex) Intel Corporate +14ABC5 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +50-D2-13 (hex) CviLux Corporation +50D213 (base 16) CviLux Corporation + 9F,No.9,Lane 3,Sec.1,Chung-Cheng East Road, Tamshui + New Taipei City 25147 + TW + +00-1E-29 (hex) Hypertherm Inc +001E29 (base 16) Hypertherm Inc + 15 Great Hollow Rd + Hanover NH 03755 + US + +50-04-B8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +5004B8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-D0-B2 (hex) Xiotech Corporation +00D0B2 (base 16) Xiotech Corporation + 6455 FLYING CLOUD DRIVE + EDEN PRAIRIE MN 55344 + US + +5C-FF-35 (hex) Wistron Corporation +5CFF35 (base 16) Wistron Corporation + 21F, 88, Sec.1, Hsin Tai Wu Rd., Hsichih, + Taipei Hsien 221 + TW + +CC-9F-7A (hex) Chiun Mai Communication Systems, Inc +CC9F7A (base 16) Chiun Mai Communication Systems, Inc + No.4, Minsheng St., Tucheng District + New Taipei City 23678 + TW + +78-F2-9E (hex) PEGATRON CORPORATION +78F29E (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +64-77-7D (hex) Hitron Technologies. Inc +64777D (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +9C-50-EE (hex) Cambridge Industries(Group) Co.,Ltd. +9C50EE (base 16) Cambridge Industries(Group) Co.,Ltd. + 5/F,Building 8, 2388 ChenHang Road, MinHang District + shanghai 201114 + CN + +40-ED-98 (hex) IEEE Registration Authority +40ED98 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +C8-91-F9 (hex) Sagemcom Broadband SAS +C891F9 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison HAUTS DE SEINE 92848 + FR + +AC-DC-E5 (hex) Procter & Gamble Company +ACDCE5 (base 16) Procter & Gamble Company + 2 Procter & Gamble Plaza + Cincinnati OH 45202 + US + +00-B3-62 (hex) Apple, Inc. +00B362 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-E4-AB (hex) Apple, Inc. +E4E4AB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-D2-62 (hex) Tzukuri Pty Ltd +60D262 (base 16) Tzukuri Pty Ltd + 6 Lenthall Street + Kensington NSW 2033 + AU + +84-04-D2 (hex) Kirale Technologies SL +8404D2 (base 16) Kirale Technologies SL + General Vara de Rey 9, 5B + Logrono La Rioja 26001 + ES + +54-FA-96 (hex) Nokia +54FA96 (base 16) Nokia + Karaportti 3 + Espoo Finland 02610 + FI + +60-33-4B (hex) Apple, Inc. +60334B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-AF-D7 (hex) FUJITSU LIMITED +38AFD7 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +28-99-3A (hex) Arista Networks +28993A (base 16) Arista Networks + 5453 Great America Parkway + Santa Clara CA 95054 + US + +64-EB-8C (hex) Seiko Epson Corporation +64EB8C (base 16) Seiko Epson Corporation + 80 Harashinden + Shiojiri-shi Nagano-ken 399-0785 + JP + +F4-8C-50 (hex) Intel Corporate +F48C50 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +DC-D2-55 (hex) Kinpo Electronics, Inc. +DCD255 (base 16) Kinpo Electronics, Inc. + No.147, Sec. 3, Beishen Rd + Shenkeng Dist. New Taipei City 222 + TW + +00-13-51 (hex) Niles Audio Corporation +001351 (base 16) Niles Audio Corporation + 12331 SW 130th Street + Miami FL 33186 + US + +A0-2C-36 (hex) FN-LINK TECHNOLOGY LIMITED +A02C36 (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +00-03-20 (hex) Xpeed, Inc. +000320 (base 16) Xpeed, Inc. + 99 W. Tasman Drive + San Jose CA 95134 + US + +50-8A-0F (hex) SHENZHEN FISE TECHNOLOGY HOLDING CO.,LTD. +508A0F (base 16) SHENZHEN FISE TECHNOLOGY HOLDING CO.,LTD. + No.6 Building, Longfu Industrial Area, Huarong Road, Tongsheng Community, Dalang Street, Longhua New District + Shenzhen Guangdong 518000 + CN + +7C-CB-E2 (hex) IEEE Registration Authority +7CCBE2 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +A8-A5-E2 (hex) MSF-Vathauer Antriebstechnik GmbH & Co KG +A8A5E2 (base 16) MSF-Vathauer Antriebstechnik GmbH & Co KG + Am Hessentuch 6-8 + Detmold Nordrhein-Westfalen 32758 + DE + +BC-A8-A6 (hex) Intel Corporate +BCA8A6 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +74-FF-4C (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +74FF4C (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +68-AF-13 (hex) Futura Mobility +68AF13 (base 16) Futura Mobility + 515 PENNSYLVANIA AVE + FORT WASHINTON PA 19034 + US + +68-1A-B2 (hex) zte corporation +681AB2 (base 16) zte corporation + 12/F.,zte R&D building,kejinan Road, + shenzhen guangdong 518057 + CN + +E0-4F-BD (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +E04FBD (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +7C-EB-AE (hex) Ridgeline Instruments +7CEBAE (base 16) Ridgeline Instruments + 4803 Innovation Drive, Suite 3B + Fort Collins CO 80525 + US + +E0-50-8B (hex) Zhejiang Dahua Technology Co., Ltd. +E0508B (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199,Waterfront Road + Hangzhou Zhejiang 310053 + CN + +9C-1E-95 (hex) Actiontec Electronics, Inc +9C1E95 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +60-42-7F (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD +60427F (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + Unit East Block22-24/F,Skyworth semiconductor design Bldg., Gaoxin Ave.4.S.,Nanshan District,Shenzhen,China + SHENZHEN GUANGDONG 518057 + CN + +E8-9E-B4 (hex) Hon Hai Precision Ind. Co.,Ltd. +E89EB4 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +D4-6A-6A (hex) Hon Hai Precision Ind. Co.,Ltd. +D46A6A (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +98-FD-74 (hex) ACT.CO.LTD +98FD74 (base 16) ACT.CO.LTD + 3-RD Floor 93, Sanbon-ro + Gunpo-si Gyeonggi-do 15849 + KR + +64-DB-43 (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +64DB43 (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan + Wuhan Hubei 430000 + CN + +00-0E-58 (hex) Sonos, Inc. +000E58 (base 16) Sonos, Inc. + 614 Chapala St + Santa Barbara CA 93101 + US + +00-25-90 (hex) Super Micro Computer, Inc. +002590 (base 16) Super Micro Computer, Inc. + 980 Rock Avenue + San Jose California 95131 + US + +AC-1F-6B (hex) Super Micro Computer, Inc. +AC1F6B (base 16) Super Micro Computer, Inc. + 980 Rock Ave + San Jose CA 95131 + US + +00-0B-2E (hex) Cal-Comp Electronics & Communications Company Ltd. +000B2E (base 16) Cal-Comp Electronics & Communications Company Ltd. + No.147, Sec. 3, Beishen Rd + Shenkeng Dist New Taipei City --- + TW + +48-65-EE (hex) IEEE Registration Authority +4865EE (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D0-F7-3B (hex) Helmut Mauell GmbH Werk Weida +D0F73B (base 16) Helmut Mauell GmbH Werk Weida + Am Rosenhügel 1-7 + Velbert 42553 + DE + +18-06-75 (hex) Dilax Intelcom GmbH +180675 (base 16) Dilax Intelcom GmbH + Alt-Moabit 96b + Berlin 10559 + DE + +00-0F-C2 (hex) Uniwell Corporation +000FC2 (base 16) Uniwell Corporation + 5-25, 3-chome, Tenma, Kita-ku + Osaka 530-0043 + JP + +6C-EC-5A (hex) Hon Hai Precision Ind. CO.,Ltd. +6CEC5A (base 16) Hon Hai Precision Ind. CO.,Ltd. + B22 Building, NO.52,Tongle Road, Foxconn Industrial Park, District Jiangnan, Nanning, Guangxi, China + Nanning Guangxi 530031 + CN + +44-C3-46 (hex) HUAWEI TECHNOLOGIES CO.,LTD +44C346 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +30-74-96 (hex) HUAWEI TECHNOLOGIES CO.,LTD +307496 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +70-8A-09 (hex) HUAWEI TECHNOLOGIES CO.,LTD +708A09 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +CC-C5-EF (hex) Co-Comm Servicios Telecomunicaciones S.L. +CCC5EF (base 16) Co-Comm Servicios Telecomunicaciones S.L. + Lisboa, 20 Las Rozas + Madrid Madrid 28232 + ES + +90-02-A9 (hex) Zhejiang Dahua Technology Co., Ltd. +9002A9 (base 16) Zhejiang Dahua Technology Co., Ltd. + NO.1199 BinAn Road + Hangzhou Zhejiang 310053 + CN + +C0-28-8D (hex) Logitech, Inc +C0288D (base 16) Logitech, Inc + 4700 NW Camas Meadows Drive + Camas WA 98607 + US + +0C-49-33 (hex) Sichuan Jiuzhou Electronic Technology Co., Ltd. +0C4933 (base 16) Sichuan Jiuzhou Electronic Technology Co., Ltd. + No. 259, Jiuzhou Road + Mianyang City Sichuan Province 621000 + CN + +00-00-64 (hex) Yokogawa Digital Computer Corporation +000064 (base 16) Yokogawa Digital Computer Corporation + Shinjuku MIDWEST Bldg.4-30-3 + Yoyogi Shibuya-ku, Tokyo 151-0053 + JP + +50-6B-8D (hex) Nutanix +506B8D (base 16) Nutanix + 1740 Technology Drive Ste #150 + San Jose CA 95110 + US + +00-38-DF (hex) Cisco Systems, Inc +0038DF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F4-CA-E5 (hex) FREEBOX SAS +F4CAE5 (base 16) FREEBOX SAS + 8 rue de la Ville l'Eveque + PARIS IdF 75008 + FR + +90-00-4E (hex) Hon Hai Precision Ind. Co.,Ltd. +90004E (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +7C-26-34 (hex) ARRIS Group, Inc. +7C2634 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +40-F4-13 (hex) Rubezh +40F413 (base 16) Rubezh + Ulyanovskaya str. 28 + Saratov 410056 + RU + +C8-D3-FF (hex) Hewlett Packard +C8D3FF (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +C4-BE-84 (hex) Texas Instruments +C4BE84 (base 16) Texas Instruments + 12500 TI Blvd + Dallas 75243 + US + +F4-F5-24 (hex) Motorola Mobility LLC, a Lenovo Company +F4F524 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +00-BB-C1 (hex) CANON INC. +00BBC1 (base 16) CANON INC. + 30-2 Shimomaruko 3-chome, + Ohta-ku Tokyo 146-8501 + JP + +A8-1E-84 (hex) QUANTA COMPUTER INC. +A81E84 (base 16) QUANTA COMPUTER INC. + No.211, Wen Hwa 2nd Rd., Kuei Shan Hsiang + Tao Yuan 33377 + TW + +24-C1-BD (hex) CRRC DALIAN R&D CO.,LTD. +24C1BD (base 16) CRRC DALIAN R&D CO.,LTD. + No.1 Haoyang North Street,Lvshun Economic Deveopment Zone + Dalian Liaoning 116052 + CN + +00-A2-EE (hex) Cisco Systems, Inc +00A2EE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-59-DC (hex) Cisco Systems, Inc +0059DC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-FD-45 (hex) Hewlett Packard Enterprise +00FD45 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +50-98-F3 (hex) Rheem Australia Pty Ltd +5098F3 (base 16) Rheem Australia Pty Ltd + 1 Alan Street + Rydalmere NSW 2116 + AU + +B4-D1-35 (hex) Cloudistics +B4D135 (base 16) Cloudistics + 116000 Sunrise Valley Dr Suite 210 + Reston VA 20190 + US + +00-13-A5 (hex) General Solutions, LTD. +0013A5 (base 16) General Solutions, LTD. + 5902 Sovereign Drive + Houston Texas 77036 + US + +9C-3D-CF (hex) NETGEAR +9C3DCF (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +24-88-94 (hex) shenzhen lensun Communication Technology LTD +248894 (base 16) shenzhen lensun Communication Technology LTD + RM 201, Block 19, Zhiheng industry Park, Nantou Check point + Shenzhen Guangdong 518000 + CN + +B0-4B-BF (hex) PT HAN SUNG ELECTORONICS INDONESIA +B04BBF (base 16) PT HAN SUNG ELECTORONICS INDONESIA + JL.PALEM 1 BLOK DS-6 + KAWASAN INDUSTRI BATIK LIPPO CIKARANG, DESA CIBATU, KECAMATAN CIKARANG SELATAN BEKASI JAWA BARAT 17550 + ID + +CC-2D-83 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +CC2D83 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +00-15-FF (hex) Novatel Wireless Solutions, Inc. +0015FF (base 16) Novatel Wireless Solutions, Inc. + 9605 Scranton Road Suite 200 + San Diego 92121 + US + +D4-6E-0E (hex) TP-LINK TECHNOLOGIES CO.,LTD. +D46E0E (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +88-36-6C (hex) EFM Networks +88366C (base 16) EFM Networks + 6F, Benposra II 1197-1 Bojeong Giheung Gu + Yong In Kyunggi do 446913 + KR + +48-DA-96 (hex) Eddy Smart Home Solutions Inc. +48DA96 (base 16) Eddy Smart Home Solutions Inc. + 1600-25 Sheppard Avenue West + Toronto Ontario M2N 6S6 + CA + +F0-74-E4 (hex) Thundercomm Technology Co., Ltd +F074E4 (base 16) Thundercomm Technology Co., Ltd + Building NO.4, 99# Xiantao Data Valley Zhonglu, Yubei District, Chongqing, China + chongqing 404100 + CN + +A0-72-2C (hex) HUMAX Co., Ltd. +A0722C (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +FC-D8-48 (hex) Apple, Inc. +FCD848 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +EC-10-7B (hex) Samsung Electronics Co.,Ltd +EC107B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +1C-23-2C (hex) Samsung Electronics Co.,Ltd +1C232C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E0-0D-B9 (hex) Cree, Inc. +E00DB9 (base 16) Cree, Inc. + 4600 Silicon Drive + Durham NC 27703 + US + +DC-0D-30 (hex) Shenzhen Feasycom Technology Co., Ltd. +DC0D30 (base 16) Shenzhen Feasycom Technology Co., Ltd. + #2004, Huichao Science & Technology Building, Jinhai Road, Xixiang + Shenzhen Guangdong 18000 + CN + +F0-AC-D7 (hex) IEEE Registration Authority +F0ACD7 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +94-95-A0 (hex) Google, Inc. +9495A0 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +00-A6-CA (hex) Cisco Systems, Inc +00A6CA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +38-D5-47 (hex) ASUSTek COMPUTER INC. +38D547 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +FC-83-C6 (hex) N-Radio Technologies Co., Ltd. +FC83C6 (base 16) N-Radio Technologies Co., Ltd. + 2#, 7F, Satellite Buiding, Keyuan Road, Nanshan + ShenZhen GuangDong 518000 + CN + +30-B6-4F (hex) Juniper Networks +30B64F (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +1C-9D-3E (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +1C9D3E (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +F0-2F-A7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F02FA7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-DE-D7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +18DED7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C8-3D-D4 (hex) CyberTAN Technology Inc. +C83DD4 (base 16) CyberTAN Technology Inc. + 99 Park Ave III, Hsinchu Science Park + Hsinchu 308 + TW + +E0-B9-4D (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD +E0B94D (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD + NO.268, Fuqian Rd, Jutang community, Guanlan Town, Longhua New district + shenzhen guangdong 518000 + CN + +D8-45-2B (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +D8452B (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +E4-18-6B (hex) Zyxel Communications Corporation +E4186B (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +00-87-31 (hex) Cisco Systems, Inc +008731 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +88-DE-A9 (hex) Roku, Inc. +88DEA9 (base 16) Roku, Inc. + 12980 Saratoga Ave + Saratoga CA 95070 + US + +78-88-8A (hex) CDR Sp. z o.o. Sp. k. +78888A (base 16) CDR Sp. z o.o. Sp. k. + Palki 15 + Zory 44-240 + PL + +00-21-D1 (hex) Samsung Electronics Co.,Ltd +0021D1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-1F-CC (hex) Samsung Electronics Co.,Ltd +001FCC (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A4-29-83 (hex) Boeing Defence Australia +A42983 (base 16) Boeing Defence Australia + GPO Box 767 + Brisbane Queensland 4001 + AU + +EC-88-92 (hex) Motorola Mobility LLC, a Lenovo Company +EC8892 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 Merchandise Mart Plaza, Suite 1800 + Chicago IL 60654 + US + +74-87-A9 (hex) OCT Technology Co., Ltd. +7487A9 (base 16) OCT Technology Co., Ltd. + 8F. -2, No. 94, Baojhong Rd. Sindian Dist. + New Taipei City 231 + TW + +00-4A-77 (hex) zte corporation +004A77 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +A4-14-37 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +A41437 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.469,Jianghui Road + Hangzhou Zhejiang 310052 + CN + +60-A1-0A (hex) Samsung Electronics Co.,Ltd +60A10A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +8C-71-F8 (hex) Samsung Electronics Co.,Ltd +8C71F8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +CC-05-1B (hex) Samsung Electronics Co.,Ltd +CC051B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +8C-77-12 (hex) Samsung Electronics Co.,Ltd +8C7712 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +94-63-D1 (hex) Samsung Electronics Co.,Ltd +9463D1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-21-D2 (hex) Samsung Electronics Co.,Ltd +0021D2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +5C-49-7D (hex) Samsung Electronics Co.,Ltd +5C497D (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +98-23-4E (hex) Micromedia AG +98234E (base 16) Micromedia AG + Gartenweg 46 + Buonas Zug 6343 + CH + +50-3F-98 (hex) CMITECH +503F98 (base 16) CMITECH + 904-ho, 25, Simin-daero 248beon-gil, Dongan-gu + Anyang-si Gyeonggi-do 14067 + KR + +78-20-79 (hex) ID Tech +782079 (base 16) ID Tech + 10721 Walker St + Cypress CA 90630 + US + +0C-60-76 (hex) Hon Hai Precision Ind. Co.,Ltd. +0C6076 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +0C-EE-E6 (hex) Hon Hai Precision Ind. Co.,Ltd. +0CEEE6 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +E4-D5-3D (hex) Hon Hai Precision Ind. Co.,Ltd. +E4D53D (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +C0-14-3D (hex) Hon Hai Precision Ind. Co.,Ltd. +C0143D (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +C0-18-85 (hex) Hon Hai Precision Ind. Co.,Ltd. +C01885 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-74-9C (hex) Ruijie Networks Co.,LTD +00749C (base 16) Ruijie Networks Co.,LTD + 19# Building,Star-net Science Plaza,Juyuanzhou, 618 Jinshan Road + Fuzhou Fujian 350002 + CN + +58-94-CF (hex) Vertex Standard LMR, Inc. +5894CF (base 16) Vertex Standard LMR, Inc. + 4-8-8 Nakameguro + Meguro-ku Tokyo 153-8644 + JP + +20-F8-5E (hex) Delta Electronics +20F85E (base 16) Delta Electronics + 252 Shangying Road + Taoyuan County Taiwan 33341 + TW + +78-25-AD (hex) Samsung Electronics Co.,Ltd +7825AD (base 16) Samsung Electronics Co.,Ltd + 416, MAETAN-3DONG, PALDAL-GU + SUWON CITY KYUNGKI-DO 442-742 + KR + +EC-E0-9B (hex) Samsung Electronics Co.,Ltd +ECE09B (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3dong, Yeongtong-gu, + Suwon-City Gyeonggi-do 443-742 + KR + +00-23-E4 (hex) IPnect co. ltd. +0023E4 (base 16) IPnect co. ltd. + 808 albatross B/D 237-18 + Seoul 153-801 + KR + +70-D4-F2 (hex) RIM +70D4F2 (base 16) RIM + Phillip Street + Waterloo Ontario N2L 3W8 + CA + +78-D6-F0 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +78D6F0 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + Metan Dong 314, Youngtong Gu + Suwon Kyung-gi Do. 443-743 + KR + +BC-20-A4 (hex) Samsung Electronics Co.,Ltd +BC20A4 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +08-D4-2B (hex) Samsung Electronics Co.,Ltd +08D42B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +78-9E-D0 (hex) Samsung Electronics Co.,Ltd +789ED0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-C4-E7 (hex) Samsung Electronics Co.,Ltd +B0C4E7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A0-07-98 (hex) Samsung Electronics Co.,Ltd +A00798 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-1F-CD (hex) Samsung Electronics Co.,Ltd +001FCD (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +38-EC-E4 (hex) Samsung Electronics Co.,Ltd +38ECE4 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +94-51-03 (hex) Samsung Electronics Co.,Ltd +945103 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-24-90 (hex) Samsung Electronics Co.,Ltd +002490 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-23-D7 (hex) Samsung Electronics Co.,Ltd +0023D7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-9B-12 (hex) Samsung Electronics Co.,Ltd +549B12 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-A1-3E (hex) Samsung Electronics Co.,Ltd +FCA13E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +24-C6-96 (hex) Samsung Electronics Co.,Ltd +24C696 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +94-D7-71 (hex) Samsung Electronics Co.,Ltd +94D771 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E8-4E-84 (hex) Samsung Electronics Co.,Ltd +E84E84 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-16-32 (hex) Samsung Electronics Co.,Ltd +001632 (base 16) Samsung Electronics Co.,Ltd + 416, METAN-3DONG, + SUWON KYUNGKI-DO 442-742 + KR + +E4-E0-C5 (hex) Samsung Electronics Co.,Ltd +E4E0C5 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3dong, Yeongtong-gu + Suwon Gyeonggi-do 443742 + KR + +C8-14-79 (hex) Samsung Electronics Co.,Ltd +C81479 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +1C-AF-05 (hex) Samsung Electronics Co.,Ltd +1CAF05 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-16-DB (hex) Samsung Electronics Co.,Ltd +0016DB (base 16) Samsung Electronics Co.,Ltd + #94-1 + Gumi-City Gyeong-Buk 730-350 + KR + +00-1E-E2 (hex) Samsung Electronics Co.,Ltd +001EE2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +20-D5-BF (hex) Samsung Electronics Co.,Ltd +20D5BF (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3dong, Yeongtong-Gu + Suwon Gyeonggi-Do 443742 + KR + +5C-E8-EB (hex) Samsung Electronics Co.,Ltd +5CE8EB (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C0-BD-D1 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +C0BDD1 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +B4-79-A7 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +B479A7 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +7C-11-CB (hex) HUAWEI TECHNOLOGIES CO.,LTD +7C11CB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +1C-25-E1 (hex) China Mobile IOT Company Limited +1C25E1 (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +C0-F6-36 (hex) Hangzhou Kuaiyue Technologies, Ltd. +C0F636 (base 16) Hangzhou Kuaiyue Technologies, Ltd. + Dongguan Hitech Park, Building 1-805, 288 Qiuyi Rd, Bingjiang District + Hangzhou Zhejiang 310053 + CN + +00-1A-22 (hex) eQ-3 Entwicklung GmbH +001A22 (base 16) eQ-3 Entwicklung GmbH + Maiburger Str. 36 + Leer Niedersachsen D-26789 + DE + +B0-DF-3A (hex) Samsung Electronics Co.,Ltd +B0DF3A (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +80-57-19 (hex) Samsung Electronics Co.,Ltd +805719 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +34-BE-00 (hex) Samsung Electronics Co.,Ltd +34BE00 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-E2-E0 (hex) ARRIS Group, Inc. +54E2E0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +34-7A-60 (hex) ARRIS Group, Inc. +347A60 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1C-C3 (hex) ARRIS Group, Inc. +001CC3 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +24-0D-C2 (hex) TCT mobile ltd +240DC2 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +78-52-1A (hex) Samsung Electronics Co.,Ltd +78521A (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +70-85-C6 (hex) ARRIS Group, Inc. +7085C6 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +20-BB-C6 (hex) Jabil Circuit Hungary Ltd. +20BBC6 (base 16) Jabil Circuit Hungary Ltd. + Huszár Andor 1. + Tiszaújváros H-3580 + HU + +04-FE-A1 (hex) Fihonest communication co.,Ltd +04FEA1 (base 16) Fihonest communication co.,Ltd + Room902,Park road,Zhixing business-building + Dongguan Guangdong 523560 + CN + +EC-8C-A2 (hex) Ruckus Wireless +EC8CA2 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +B8-00-18 (hex) Htel +B80018 (base 16) Htel + Dunchon-dearo, Jungwon-gu + Seongnam-si Gyeonggi-do 13229 + KR + +74-72-B0 (hex) Guangzhou Shiyuan Electronics Co., Ltd. +7472B0 (base 16) Guangzhou Shiyuan Electronics Co., Ltd. + No.6, 4th Yunpu Road, Yunpu Industry District + Guangzhou Guangdong 510530 + CN + +54-6C-0E (hex) Texas Instruments +546C0E (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +EC-8E-AE (hex) Nagravision SA +EC8EAE (base 16) Nagravision SA + Route de Geneve 22-24, PO 7980 + Cheseaux Vaud 1033 + CH + +A0-43-DB (hex) Sitael S.p.A. +A043DB (base 16) Sitael S.p.A. + Via San Sabino, 21 + Mola di Bari BA 70042 + IT + +E0-E7-BB (hex) Nureva, Inc. +E0E7BB (base 16) Nureva, Inc. + 1000, 1221 8th Street SW + Calgary AB T2R 0L4 + CA + +00-80-8C (hex) NetAlly +00808C (base 16) NetAlly + 310 Littleton Road + Westford MA 01886 + US + +04-9F-81 (hex) NetAlly +049F81 (base 16) NetAlly + 310 Littleton Road + Westford MA 01886 + US + +00-10-87 (hex) XSTREAMIS PLC +001087 (base 16) XSTREAMIS PLC + OXFORD SCIENCE PARK + OXFORD 0X4 4GA 00000 + US + +00-B0-B3 (hex) XSTREAMIS PLC +00B0B3 (base 16) XSTREAMIS PLC + Magdalen Centre + Oxford 0X4 4GA 0000 + GB + +04-9F-CA (hex) HUAWEI TECHNOLOGIES CO.,LTD +049FCA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +50-01-6B (hex) HUAWEI TECHNOLOGIES CO.,LTD +50016B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +AC-48-2D (hex) Ralinwi Nanjing Electronic Technology Co., Ltd. +AC482D (base 16) Ralinwi Nanjing Electronic Technology Co., Ltd. + 3rd Floor, Building B,R&D Block 3, Xuzhuang Software Park, No. 699-27, Xuanwu Avenue + Nanjing Jiangsu 210046 + CN + +00-23-63 (hex) Zhuhai Raysharp Technology Co.,Ltd +002363 (base 16) Zhuhai Raysharp Technology Co.,Ltd + No.119 of Huawei Road, Qianshan Science & Technology Park, + Zhuhai Guangdong 519070 + CN + +00-00-1B (hex) Novell, Inc. +00001B (base 16) Novell, Inc. + 122 EAST 1700 SOUTH + PROVO UT 84606 + US + +00-90-58 (hex) Ultra Electronics Command & Control Systems +009058 (base 16) Ultra Electronics Command & Control Systems + Knaves Beech Business Centre + Hemel Hemstead Herts England HP2 7BW + GB + +00-1C-FD (hex) Universal Electronics, Inc. +001CFD (base 16) Universal Electronics, Inc. + 6101 Gateway Drive + Cypress 90630 + US + +08-00-87 (hex) Xyplex, Inc. +080087 (base 16) Xyplex, Inc. + 295 FOSTER STREET + LITTLETON MA 01460 + US + +DC-1A-01 (hex) Ecoliv Technology ( Shenzhen ) Ltd. +DC1A01 (base 16) Ecoliv Technology ( Shenzhen ) Ltd. + B-734, Tianhui building, Longhua Street, Pine Road, Longhua District + Shenzhen Guangdong 518109 + CN + +00-54-9F (hex) Avaya Inc +00549F (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +28-24-FF (hex) Wistron Neweb Corporation +2824FF (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +38-25-6B (hex) Microsoft Mobile Oy +38256B (base 16) Microsoft Mobile Oy + Keilalahdentie 4 + Espoo 02150 + FI + +00-1C-EF (hex) Primax Electronics Ltd. +001CEF (base 16) Primax Electronics Ltd. + 669, Ruey Kuang Road, Neihu + Taipei 114 + TW + +00-02-76 (hex) Primax Electronics Ltd. +000276 (base 16) Primax Electronics Ltd. + No. 669, Ruey Kuang Road, Neihu + Taipei Taiwan, R.O.C. + TW + +4C-B2-1C (hex) Maxphotonics Co.,Ltd +4CB21C (base 16) Maxphotonics Co.,Ltd + Maxphotonics Industrial Park,Third Furong Road,Furong Industrial Area,Shajing,BaoAn + ShenZhen GuangDong 518125 + CN + +20-5E-F7 (hex) Samsung Electronics Co.,Ltd +205EF7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-1F-78 (hex) Samsung Electronics Co.,Ltd +141F78 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D8-47-10 (hex) Sichuan Changhong Electric Ltd. +D84710 (base 16) Sichuan Changhong Electric Ltd. + 35 East Mianxing Road,High-Tech Park, + MianYang SiChuan 621000 + CN + +00-19-72 (hex) Plexus (Xiamen) Co.,ltd. +001972 (base 16) Plexus (Xiamen) Co.,ltd. + No.6 Xiangxing 2 Road + Xiamen Fujian 361006 + CN + +00-23-47 (hex) ProCurve Networking by HP +002347 (base 16) ProCurve Networking by HP + 60 Alexandra Terrace + 0000 118502 + SG + +00-24-A8 (hex) ProCurve Networking by HP +0024A8 (base 16) ProCurve Networking by HP + 60 Alexandra Terrace + 0000 118502 + SG + +C0-91-34 (hex) ProCurve Networking by HP +C09134 (base 16) ProCurve Networking by HP + 60 Alexandra Terrace + 0000 118502 + SG + +00-19-69 (hex) Nortel Networks +001969 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-18-B0 (hex) Nortel Networks +0018B0 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-16-CA (hex) Nortel Networks +0016CA (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-0F-CD (hex) Nortel Networks +000FCD (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1B-BA (hex) Nortel Networks +001BBA (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-04-DC (hex) Nortel Networks +0004DC (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-0C-F7 (hex) Nortel Networks +000CF7 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-14-0E (hex) Nortel Networks +00140E (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1E-1F (hex) Nortel Networks +001E1F (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +20-3A-EF (hex) Sivantos GmbH +203AEF (base 16) Sivantos GmbH + Henri-Dunant-Strasse 100 + Erlangen Bavaria 91058 + DE + +00-59-79 (hex) Networked Energy Services +005979 (base 16) Networked Energy Services + 5215 Hellyer Avenue + San Jose CA 95138 + US + +20-7C-8F (hex) Quanta Microsystems,Inc. +207C8F (base 16) Quanta Microsystems,Inc. + No.5 Lane 91,Dongmei Rd. + Hsinchu 300 + TW + +00-0B-34 (hex) ShangHai Broadband Technologies CO.LTD +000B34 (base 16) ShangHai Broadband Technologies CO.LTD + 17F,No.122,HuangXing Road + ShangHai 200090 + CN + +74-B5-7E (hex) zte corporation +74B57E (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +B8-BB-23 (hex) Guangdong Nufront CSC Co., Ltd +B8BB23 (base 16) Guangdong Nufront CSC Co., Ltd + A403-414, Building 13, No.232 Waihuan East Road, Higher Education Mega Center, Guangdong 510006, China + Guangzhou Guangdong 510006 + CN + +34-EA-34 (hex) HangZhou Gubei Electronics Technology Co.,Ltd +34EA34 (base 16) HangZhou Gubei Electronics Technology Co.,Ltd + Room 106, No.611 Jianghong Road, Binjiang District, Hangzhou, Zhejiang, China + Hangzhou ZheJiang 310052 + CN + +30-92-F6 (hex) SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD +3092F6 (base 16) SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD + Suite 604-605,Xing Yuan Technology Plaza + 00000 ShangHai 200233 + CN + +A8-AD-3D (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +A8AD3D (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +24-AF-4A (hex) Alcatel-Lucent IPD +24AF4A (base 16) Alcatel-Lucent IPD + 701 E. Middlefield Rd. + Mountain View CA 94043 + US + +7C-20-64 (hex) Alcatel-Lucent IPD +7C2064 (base 16) Alcatel-Lucent IPD + 600 March Drive + Kanata Ontario K2K2E6 + CA + +44-DC-91 (hex) PLANEX COMMUNICATIONS INC. +44DC91 (base 16) PLANEX COMMUNICATIONS INC. + 2F F-NISSAY Ebisu Bldg 3-16-3 Higashi, + Shibuya-ku Tokyo 150-0011 + JP + +E0-9D-B8 (hex) PLANEX COMMUNICATIONS INC. +E09DB8 (base 16) PLANEX COMMUNICATIONS INC. + Planex Volta Bldg., 2-11-9 Ebisu-Nishi,Shibuya-ku, + 00000 1500021 + US + +00-0F-59 (hex) Phonak AG +000F59 (base 16) Phonak AG + Länggasse 17 + Murten FR 3280 + CH + +00-14-78 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +001478 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + 3/F,Bldg.R1-B,Hi-tech Industrial Park, + ShenZhen GuangDong 518057 + CN + +48-F8-E1 (hex) Nokia +48F8E1 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +8C-90-D3 (hex) Nokia +8C90D3 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +00-28-F8 (hex) Intel Corporate +0028F8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +58-BC-8F (hex) Cognitive Systems Corp. +58BC8F (base 16) Cognitive Systems Corp. + 560 Westmount Road North + Waterloo Ontario N2L 0A9 + CA + +D4-55-BE (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +D455BE (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +64-0D-CE (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +640DCE (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + 3/F, Building R1-B, High-Tech Industrial Park, Nanshan District + Shenzhen Guangdong 518057 + CN + +54-D2-72 (hex) Nuki Home Solutions GmbH +54D272 (base 16) Nuki Home Solutions GmbH + Muenzgrabenstrasse 92 + Graz 8010 + AT + +EC-26-FB (hex) TECC CO.,LTD. +EC26FB (base 16) TECC CO.,LTD. + Guam-ro 15-gil, Buk-gu + Daegu 720-849 + KR + +00-20-F4 (hex) SPECTRIX CORPORATION +0020F4 (base 16) SPECTRIX CORPORATION + 106 WILMOT ROAD, SUITE 250 + DEERFIELD IL 60015-5150 + US + +04-EE-91 (hex) x-fabric GmbH +04EE91 (base 16) x-fabric GmbH + Nachodstraße 7 + Berlin 10779 + DE + +B4-74-43 (hex) Samsung Electronics Co.,Ltd +B47443 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-F6-47 (hex) Fiberhome Telecommunication Technologies Co.,LTD +FCF647 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +18-68-6A (hex) zte corporation +18686A (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +C4-4B-D1 (hex) Wallys Communications Teachnologies Co.,Ltd. +C44BD1 (base 16) Wallys Communications Teachnologies Co.,Ltd. + 5-207, DongHong Pioneer Park, #99 YangYu Lane, + SuZhou JiangSu 215000 + CN + +6C-B9-C5 (hex) Delta Networks, Inc. +6CB9C5 (base 16) Delta Networks, Inc. + 256 Yang Guang Street, Neihu + Taipei Taiwan 11491 + TW + +30-76-6F (hex) LG Electronics (Mobile Communications) +30766F (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +A8-92-2C (hex) LG Electronics (Mobile Communications) +A8922C (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +F8-0C-F3 (hex) LG Electronics (Mobile Communications) +F80CF3 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +C4-9A-02 (hex) LG Electronics (Mobile Communications) +C49A02 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-1F-6B (hex) LG Electronics (Mobile Communications) +001F6B (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-26-E2 (hex) LG Electronics (Mobile Communications) +0026E2 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +DC-44-27 (hex) IEEE Registration Authority +DC4427 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +BC-34-00 (hex) IEEE Registration Authority +BC3400 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E8-88-6C (hex) Shenzhen SC Technologies Co.,LTD +E8886C (base 16) Shenzhen SC Technologies Co.,LTD + 4/FL,2Block,LianChuang Industrial Park,Bulan Road,Longgang + Shenzhen Guangdong Province 518112 + CN + +00-24-FF (hex) QLogic Corporation +0024FF (base 16) QLogic Corporation + 26650 Aliso Viejo Parkway + Aliso Viejo CA 92656 + US + +00-1E-21 (hex) Qisda Corporation +001E21 (base 16) Qisda Corporation + 157 Shan-Ying Road, Gueishan + Taoyuan 333 + TW + +00-03-9D (hex) Qisda Corporation +00039D (base 16) Qisda Corporation + 157 Shan Ying Road + GueiShan Taoyuan 333 + TW + +00-08-0D (hex) Toshiba +00080D (base 16) Toshiba + 2-9, Suehiro-cho, + Tokyo 198-8710 + JP + +00-0E-7B (hex) Toshiba +000E7B (base 16) Toshiba + 2-9, Suehiro-Cho + Ome Tokyo 1988710 + JP + +00-03-B2 (hex) Radware +0003B2 (base 16) Radware + 8 Hamrpe Hochvim + 000 0000 + IL + +08-9E-01 (hex) QUANTA COMPUTER INC. +089E01 (base 16) QUANTA COMPUTER INC. + No.211, Wen Hwa 2nd Rd + Taoyuan Taiwan 33377 + TW + +04-7D-7B (hex) QUANTA COMPUTER INC. +047D7B (base 16) QUANTA COMPUTER INC. + NO. 211, WEN HWA 2RD.,KUEI SHAN HSIANG, TAO YUAN SHIEN, + TAIPEI TAIWAN 333 + TW + +9C-61-21 (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +9C6121 (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +00-A0-C6 (hex) Qualcomm Inc. +00A0C6 (base 16) Qualcomm Inc. + 6455 LUSK BLVD + SAN DIEGO CA 92121 + US + +64-9C-81 (hex) Qualcomm Inc. +649C81 (base 16) Qualcomm Inc. + 5665 Morehouse Drive + San Diego CA 92071 + US + +00-1A-6A (hex) Tranzas, Inc. +001A6A (base 16) Tranzas, Inc. + Queens tower C17 + Yokohama Kanagawa-ken 220-6217 + JP + +A4-71-74 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A47174 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-CB-52 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4CB52 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B8-08-D7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B808D7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-61-1E (hex) Wata Electronics Co.,Ltd. +94611E (base 16) Wata Electronics Co.,Ltd. + No 142,South Tanshen Road, Tanzhou Town,Zhongshan City,Guangdong,China + Zhongshan Guangdong 528467 + CN + +00-C0-E4 (hex) SIEMENS BUILDING +00C0E4 (base 16) SIEMENS BUILDING + TECHNOLOGIES, INC. + BUFFALO GROVE IL 60089 + US + +00-0D-10 (hex) Embedtronics Oy +000D10 (base 16) Embedtronics Oy + Leväsentie 23 + Kuopio 70780 + FI + +00-1F-A8 (hex) Smart Energy Instruments Inc. +001FA8 (base 16) Smart Energy Instruments Inc. + 297 Lakeshore Road East + Oakville Ontario L6J 1J3 + CA + +00-0F-DB (hex) Westell Technologies Inc. +000FDB (base 16) Westell Technologies Inc. + 750 N Commons Dr + Aurora IL 60504 + US + +3C-07-71 (hex) Sony Corporation +3C0771 (base 16) Sony Corporation + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +80-41-4E (hex) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. +80414E (base 16) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + LiWu INDUSTRIAL PARK,Wusha,Chang'an + Dong Guan Guang Dong 523860 + CN + +24-94-42 (hex) OPEN ROAD SOLUTIONS , INC. +249442 (base 16) OPEN ROAD SOLUTIONS , INC. + 88-13 SHUILI ROAD + HSINCHU 30059 + TW + +C4-64-13 (hex) Cisco Systems, Inc +C46413 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-10-CA (hex) Telco Systems, Inc. +0010CA (base 16) Telco Systems, Inc. + 15 Berkshire Road + Mansfield, MA 02048 + US + +00-E0-9E (hex) Quantum Corporation +00E09E (base 16) Quantum Corporation + 500 McCarthy Boulevard + Milpitas CA 95035 + US + +00-0A-08 (hex) Alpine Electronics, Inc. +000A08 (base 16) Alpine Electronics, Inc. + 20-1 Yoshima-Kogyodanchi + iwaki-city Fukushima 970-1192 + JP + +20-6A-8A (hex) Wistron Infocomm (Zhongshan) Corporation +206A8A (base 16) Wistron Infocomm (Zhongshan) Corporation + 168# First Avenue,Kunshan Export Processing Zone + Kunshan Jiangsu 215300 + CN + +78-44-76 (hex) Zioncom Electronics (Shenzhen) Ltd. +784476 (base 16) Zioncom Electronics (Shenzhen) Ltd. + A1&A2 building,lantian technology park, xinyu road, xingqiao henggang block, shajing street, Baoan District + shenzhen guangdong 518000 + CN + +00-11-65 (hex) ZNYX Networks, Inc. +001165 (base 16) ZNYX Networks, Inc. + 48421 Milmont Drive + Fremont CA 94538 + US + +00-0A-68 (hex) Solarflare Communications Inc. +000A68 (base 16) Solarflare Communications Inc. + Suite 100, 7505 Irvine Center Drive + Irvine CA 92618 + US + +00-21-86 (hex) Universal Global Scientific Industrial Co., Ltd. +002186 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, Lane 351, Sec.1, Taiping Road, + NANTOU 54261 + TW + +18-39-19 (hex) Unicoi Systems +183919 (base 16) Unicoi Systems + 410 Peachtree Pkwy + Cumming GA 30041 + US + +E8-E0-B7 (hex) Toshiba +E8E0B7 (base 16) Toshiba + 2-9,Suehiro-Cho + Ome Tokyo 1988710 + JP + +68-07-15 (hex) Intel Corporate +680715 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +3C-B6-B7 (hex) vivo Mobile Communication Co., Ltd. +3CB6B7 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong 523860 + CN + +C4-27-95 (hex) Technicolor CH USA Inc. +C42795 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +A0-20-A6 (hex) Espressif Inc. +A020A6 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +58-52-8A (hex) Mitsubishi Electric Corporation +58528A (base 16) Mitsubishi Electric Corporation + 2-7-3 Marunouchi Chiyoda-ku + Tokyo 100-8310 + JP + +C4-F1-D1 (hex) BEIJING SOGOU TECHNOLOGY DEVELOPMENT CO., LTD. +C4F1D1 (base 16) BEIJING SOGOU TECHNOLOGY DEVELOPMENT CO., LTD. + SOHU.COM INTERNET PLAZA, NO.1 PARK, ZHONGGUANCHUN EAST ROAD. HAIDIAN DISTRICT + Beijing 100000 + CN + +AC-E7-7B (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +ACE77B (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +2C-36-A0 (hex) Capisco Limited +2C36A0 (base 16) Capisco Limited + PO Box 938 + Auckland 0943 + NZ + +B0-B2-DC (hex) Zyxel Communications Corporation +B0B2DC (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +CC-5D-4E (hex) Zyxel Communications Corporation +CC5D4E (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +40-4A-03 (hex) Zyxel Communications Corporation +404A03 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +C8-6C-87 (hex) Zyxel Communications Corporation +C86C87 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +00-1E-C0 (hex) Microchip Technology Inc. +001EC0 (base 16) Microchip Technology Inc. + 2355 W. Chandler Blvd. + Chandler AZ 85224 + US + +64-5D-92 (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +645D92 (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, Chengdu, Sichuan + Chengdu Sichuan 610000 + CN + +38-BC-1A (hex) MEIZU Technology Co., Ltd. +38BC1A (base 16) MEIZU Technology Co., Ltd. + MEIZU Tech Bldg., Technology & Innovation Coast + Zhuhai Guangdong 519085 + CN + +38-F0-C8 (hex) Livestream +38F0C8 (base 16) Livestream + 195 Morgan Avenue + Brooklyn NY 11237 + US + +80-29-94 (hex) Technicolor CH USA Inc. +802994 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +E0-88-5D (hex) Technicolor CH USA Inc. +E0885D (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +34-0A-FF (hex) Qingdao Hisense Communications Co.,Ltd. +340AFF (base 16) Qingdao Hisense Communications Co.,Ltd. + Qianwangang Road 218 + Qingdao Shandong 266510 + CN + +58-7E-61 (hex) Qingdao Hisense Communications Co.,Ltd. +587E61 (base 16) Qingdao Hisense Communications Co.,Ltd. + Qianwangang Road 218 + Qingdao Shandong 266510 + CN + +C0-A1-A2 (hex) MarqMetrix +C0A1A2 (base 16) MarqMetrix + 410 West Harrison ST #200 + Seattle WA 98119 + US + +08-D0-B7 (hex) Qingdao Hisense Communications Co.,Ltd. +08D0B7 (base 16) Qingdao Hisense Communications Co.,Ltd. + Qianwangang Road 218 + Qingdao Shandong 266510 + CN + +EC-D6-8A (hex) Shenzhen JMicron Intelligent Technology Developmen +ECD68A (base 16) Shenzhen JMicron Intelligent Technology Developmen + Futian District, 13th Floor , Block B Building Tai + Shenzhen Guangdong Province 518040 + CN + +50-52-D2 (hex) Hangzhou Telin Technologies Co., Limited +5052D2 (base 16) Hangzhou Telin Technologies Co., Limited + 8 floor,D Building,Paradise Software Park,No. 3 Xidoumen Road, Xihu District, Hangzhou + Hangzhou Zhejiang 310013 + CN + +90-EE-D9 (hex) UNIVERSAL DE DESARROLLOS ELECTRÓNICOS, SA +90EED9 (base 16) UNIVERSAL DE DESARROLLOS ELECTRÓNICOS, SA + CRTA DE CASTELLAR, 298 + TERRASSA BARCELONA 08226 + ES + +60-64-53 (hex) AOD Co.,Ltd. +606453 (base 16) AOD Co.,Ltd. + No. 13155, Yuqing Street, High-Technology Development Zone, + Weifang Shandong 261061 + CN + +6C-98-EB (hex) Riverbed Technology, Inc. +6C98EB (base 16) Riverbed Technology, Inc. + 680 Folsom St. + San Francisco CA 94107 + US + +00-9E-1E (hex) Cisco Systems, Inc +009E1E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-25-3E (hex) Sensus Metering Systems +00253E (base 16) Sensus Metering Systems + 10147 W. Emerald Street + Boise Idaho 83704 + US + +C8-AF-E3 (hex) Hefei Radio Communication Technology Co., Ltd +C8AFE3 (base 16) Hefei Radio Communication Technology Co., Ltd + No.108, YinXing Road, High-tech Development Zone + Hefei Anhui 230088 + CN + +CC-A2-60 (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +CCA260 (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +7C-57-4E (hex) COBI GmbH +7C574E (base 16) COBI GmbH + Solmsstrasse 4 + Frankfurt am Main 60486 + DE + +28-F1-0E (hex) Dell Inc. +28F10E (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +04-56-04 (hex) Gionee Communication Equipment Co.,Ltd. +045604 (base 16) Gionee Communication Equipment Co.,Ltd. + 21/F,Times Technology Building,No. 7028,Shennan Avenue,Futian District + Shenzhen 518000 + CN + +34-C0-F9 (hex) Rockwell Automation +34C0F9 (base 16) Rockwell Automation + 1 Allen-Bradley Dr. + Mayfield Heights OH 44124-6118 + US + +00-FE-C8 (hex) Cisco Systems, Inc +00FEC8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +2C-5A-8D (hex) SYSTRONIK Elektronik u. Systemtechnik GmbH +2C5A8D (base 16) SYSTRONIK Elektronik u. Systemtechnik GmbH + Gewerbestrasse 57 + ILLMENSEE 88636 + DE + +10-BE-F5 (hex) D-Link International +10BEF5 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +E4-7B-3F (hex) BEIJING CO-CLOUD TECHNOLOGY LTD. +E47B3F (base 16) BEIJING CO-CLOUD TECHNOLOGY LTD. + 903 Room,Power Create E ,No.1 Shangdi East Road + Beijing Beijing 100085 + CN + +0C-8A-87 (hex) AgLogica Holdings, Inc +0C8A87 (base 16) AgLogica Holdings, Inc + 333 Research Ct NW Ste 230 + Norcross GA 30092 + US + +54-ED-A3 (hex) Navdy, Inc. +54EDA3 (base 16) Navdy, Inc. + 575 7th Street + San Francisco CA 94103 + US + +40-F4-20 (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +40F420 (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +34-A2-A2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +34A2A2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +74-9D-8F (hex) HUAWEI TECHNOLOGIES CO.,LTD +749D8F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-59-07 (hex) Shanghai HITE-BELDEN Network Technology Co., Ltd. +945907 (base 16) Shanghai HITE-BELDEN Network Technology Co., Ltd. + No. 777, Xinjun Ring Road, Pujiang Hi-Tech Park, Minhang District + Shanghai Shanghai 201114 + CN + +00-18-48 (hex) Vecima Networks Inc. +001848 (base 16) Vecima Networks Inc. + 150 Cardinal Place + Saskatoon SK S7L 6H7 + CA + +00-16-FB (hex) SHENZHEN MTC CO LTD +0016FB (base 16) SHENZHEN MTC CO LTD + 5/F BenYuan Bldg,6015 ShenNan Road + ShenZhen GuangDong 518040 + CN + +A0-41-5E (hex) Opsens Solution Inc. +A0415E (base 16) Opsens Solution Inc. + 2014 rue Cyrille-Duquet, suite 125 + Quebec QC G1N 4N6 + CA + +A8-60-B6 (hex) Apple, Inc. +A860B6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C4-B3-01 (hex) Apple, Inc. +C4B301 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-5F-45 (hex) Apple, Inc. +E05F45 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +74-CC-39 (hex) Fiberhome Telecommunication Technologies Co.,LTD +74CC39 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +38-22-D6 (hex) Hangzhou H3C Technologies Co., Limited +3822D6 (base 16) Hangzhou H3C Technologies Co., Limited + 310 Liuhe Road, Zhijiang Science Park + Hangzhou Zhejiang, 310053 + CN + +94-E8-C5 (hex) ARRIS Group, Inc. +94E8C5 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +6C-3B-6B (hex) Routerboard.com +6C3B6B (base 16) Routerboard.com + Mikrotikls SIA + Riga Riga LV1009 + LV + +00-22-E7 (hex) WPS Parking Systems +0022E7 (base 16) WPS Parking Systems + Hoevenweg 11 + Eindhoven Noord-Brabant 5652 AW + NL + +48-51-B7 (hex) Intel Corporate +4851B7 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B8-E7-79 (hex) 9Solutions Oy +B8E779 (base 16) 9Solutions Oy + Teknologiantie 2 + Oulu 90590 + FI + +C8-64-C7 (hex) zte corporation +C864C7 (base 16) zte corporation + 12/F.,zte R&D building,kejinan Road, + shenzhen guangdong 518057 + CN + +48-3B-38 (hex) Apple, Inc. +483B38 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +1C-91-48 (hex) Apple, Inc. +1C9148 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-5F-2E (hex) TCT mobile ltd +905F2E (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +F8-23-B2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F823B2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +34-12-90 (hex) Treeview Co.,Ltd. +341290 (base 16) Treeview Co.,Ltd. + 106/29 BANGLAMUNG + BANGLAMUNG CHONBURI 20150 + TH + +7C-FE-4E (hex) Shenzhen Safe vision Technology Co.,LTD +7CFE4E (base 16) Shenzhen Safe vision Technology Co.,LTD + Shenzhen ring view south road and 27 digital dragon industrial park industrial zone + shenzhen Guangdong province 518110 + CN + +64-4F-B0 (hex) Hyunjin.com +644FB0 (base 16) Hyunjin.com + Hyochang-dong 5-86, Yongsan-gu + Seoul 140-896 + KR + +00-E0-E6 (hex) INCAA Computers +00E0E6 (base 16) INCAA Computers + P.O. BOX 211 + 7300 AE APELDOORN na + NL + +28-F3-66 (hex) Shenzhen Bilian electronic CO.,LTD +28F366 (base 16) Shenzhen Bilian electronic CO.,LTD + NO 268,Fuqian Rd,Jutang Community,Guanlan town , LongHua new district,Shenzhen,518110,China. + Shenzhen 518110 + CN + +E0-A3-AC (hex) HUAWEI TECHNOLOGIES CO.,LTD +E0A3AC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +BC-75-74 (hex) HUAWEI TECHNOLOGIES CO.,LTD +BC7574 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +20-A6-80 (hex) HUAWEI TECHNOLOGIES CO.,LTD +20A680 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-28-B3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +8828B3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-E5-97 (hex) Gessler GmbH +A4E597 (base 16) Gessler GmbH + Gutenbergring 14 + Rodgau 63110 + DE + +00-6C-BC (hex) Cisco Systems, Inc +006CBC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +5C-70-A3 (hex) LG Electronics (Mobile Communications) +5C70A3 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-1D-08 (hex) Jiangsu Yinhe Electronics Co.,Ltd. +001D08 (base 16) Jiangsu Yinhe Electronics Co.,Ltd. + 188 NANHUAN ROAD + ZHANGJIAGANG JIANGSU 215611 + CN + +00-1D-82 (hex) GN Netcom A/S +001D82 (base 16) GN Netcom A/S + Lautrupbjerg 7 + Ballerup DK - 2750 + DK + +00-13-17 (hex) GN Netcom A/S +001317 (base 16) GN Netcom A/S + Metalbuen 66 + Ballerup Skovlunde DK-2750 + DK + +00-A0-A4 (hex) Oracle Corporation +00A0A4 (base 16) Oracle Corporation + 500 Oracle Parkway + Redwood Shores CA 94065 + US + +74-97-81 (hex) zte corporation +749781 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-01-F4 (hex) Enterasys +0001F4 (base 16) Enterasys + 35 Industrial Way + Rochester NH 03867 + US + +00-10-9B (hex) Emulex Corporation +00109B (base 16) Emulex Corporation + 3333 Susan Street + Costa Mesa CA 92626 + US + +00-14-2A (hex) Elitegroup Computer Systems Co.,Ltd. +00142A (base 16) Elitegroup Computer Systems Co.,Ltd. + No.22, Alley 38, Lane 91, Sec. 1, + Taipei 114 + TW + +00-11-5B (hex) Elitegroup Computer Systems Co.,Ltd. +00115B (base 16) Elitegroup Computer Systems Co.,Ltd. + No.22, Alley 38, Lane 91, Sec. 1, Nei Hu + Taipei 114 + TW + +C0-3F-D5 (hex) Elitegroup Computer Systems Co.,Ltd. +C03FD5 (base 16) Elitegroup Computer Systems Co.,Ltd. + No. 239, Sec. 2, Ti-Ding Blvd + Taipei 11493 + TW + +EC-A8-6B (hex) Elitegroup Computer Systems Co.,Ltd. +ECA86B (base 16) Elitegroup Computer Systems Co.,Ltd. + NO. 239, Sec. 2, Ti Ding Blvd. + Taipei 11493 + TW + +C8-9C-DC (hex) Elitegroup Computer Systems Co.,Ltd. +C89CDC (base 16) Elitegroup Computer Systems Co.,Ltd. + NO. 239, Sec. 2, Ti Ding Blvd. + Taipei 11493 + TW + +00-25-11 (hex) Elitegroup Computer Systems Co.,Ltd. +002511 (base 16) Elitegroup Computer Systems Co.,Ltd. + NO. 239, Sec. 2, Ti Ding Blvd. + Taipei Taiwan 11493 + TW + +44-87-FC (hex) Elitegroup Computer Systems Co.,Ltd. +4487FC (base 16) Elitegroup Computer Systems Co.,Ltd. + NO. 239, Sec. 2, Ti Ding Blvd. + Taipei Taiwan 11493 + TW + +A8-6B-AD (hex) Hon Hai Precision Ind. Co.,Ltd. +A86BAD (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +D8-0F-99 (hex) Hon Hai Precision Ind. Co.,Ltd. +D80F99 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +B4-B1-5A (hex) Siemens AG Energy Management Division +B4B15A (base 16) Siemens AG Energy Management Division + Humboldtstr. 59 + Nurnberg Bavaria 90459 + DE + +00-24-65 (hex) Elentec +002465 (base 16) Elentec + 401-13 Chunggye-Ri,Dongtan-Myun + Hwasung Kyunggi 445-811 + KR + +00-08-9F (hex) EFM Networks +00089F (base 16) EFM Networks + 403, 4th floor Elegance 1 Bldg. + Sungnam-si Kyunggi-do 463-808 + KR + +00-50-FC (hex) Edimax Technology Co. Ltd. +0050FC (base 16) Edimax Technology Co. Ltd. + No. 278, Xinhu 1st Road + Taipei City Neihu Dist 248 + TW + +9C-DF-03 (hex) Harman/Becker Automotive Systems GmbH +9CDF03 (base 16) Harman/Becker Automotive Systems GmbH + Becker-Göring-Straße 16 + Karlsbad Baden-Württemberg 76307 + DE + +00-11-88 (hex) Enterasys +001188 (base 16) Enterasys + 35 Industrial Way + Rochester NH 03867 + US + +00-16-FA (hex) ECI Telecom Ltd. +0016FA (base 16) ECI Telecom Ltd. + 30 Hasivim St. + Petah Tikva 49133 + US + +F8-A1-88 (hex) LED Roadway Lighting +F8A188 (base 16) LED Roadway Lighting + 115 Chain Lake Dr. + Halifax NS B3S 1B3 + CA + +A0-82-AC (hex) Linear DMS Solutions Sdn. Bhd. +A082AC (base 16) Linear DMS Solutions Sdn. Bhd. + 135, Jalan Utara + PENANG Pulau Pinang 11700 + MY + +A8-6A-C1 (hex) HanbitEDS Co., Ltd. +A86AC1 (base 16) HanbitEDS Co., Ltd. + 44-10, Techno 10-ro, Yuseong-gu + Daejeon Daejeon 34027 + KR + +D4-63-FE (hex) Arcadyan Corporation +D463FE (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +68-93-61 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +689361 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +BC-15-AC (hex) Vodafone Italia S.p.A. +BC15AC (base 16) Vodafone Italia S.p.A. + Via Lorenteggio nr. 240 + Milan Italy 20147 + IT + +00-BD-82 (hex) Shenzhen YOUHUA Technology Co., Ltd +00BD82 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +94-51-3D (hex) iSmart Alarm, Inc. +94513D (base 16) iSmart Alarm, Inc. + 1290 Kifer Road Suite 306 + Sunnyvale CA 94086 + US + +00-11-74 (hex) Mojo Networks, Inc. +001174 (base 16) Mojo Networks, Inc. + 339 N.Bernardo Ave + Mountain View CA 94043 + US + +00-19-54 (hex) Leaf Corporation. +001954 (base 16) Leaf Corporation. + Amuze 1F + Isehara City Kanagawa-Pref. 259-1117 + JP + +94-66-E7 (hex) WOM Engineering +9466E7 (base 16) WOM Engineering + 13F., No. 192, Sec. 2, Zhongxing Rd., Xindian Dist. + New Taipei City Taiwan 231 + TW + +4C-B8-B5 (hex) Shenzhen YOUHUA Technology Co., Ltd +4CB8B5 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +70-85-C2 (hex) ASRock Incorporation +7085C2 (base 16) ASRock Incorporation + 2F., No. 37, Sec. 2, Jhongyang S. Rd., Beitou District, + Taipei 112 + TW + +EC-93-ED (hex) DDoS-Guard LTD +EC93ED (base 16) DDoS-Guard LTD + goroda Volos, 6, 904 + Rostov-on-Don 344010 + RU + +30-FC-68 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +30FC68 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +00-8A-96 (hex) Cisco Systems, Inc +008A96 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +BC-60-A7 (hex) Sony Interactive Entertainment Inc. +BC60A7 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +80-8C-97 (hex) Kaonmedia CO., LTD. +808C97 (base 16) Kaonmedia CO., LTD. + 884-3, Seongnam-daero, Bundang-gu + Seongnam-si Gyeonggi-do 13517 + KR + +DC-EE-06 (hex) HUAWEI TECHNOLOGIES CO.,LTD +DCEE06 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +04-52-C7 (hex) Bose Corporation +0452C7 (base 16) Bose Corporation + The Mountain + Framingham MA 01701-9168 + US + +F0-27-45 (hex) F-Secure Corporation +F02745 (base 16) F-Secure Corporation + Tammasaarenkatu 7 + Helsinki 00181 + FI + +54-D0-B4 (hex) Xiamen Four-Faith Communication Technology Co.,Ltd +54D0B4 (base 16) Xiamen Four-Faith Communication Technology Co.,Ltd + 3rd Floor,No,44,GuanRi Road,Software Park,XiaMen + XiaMen Fujian 361000 + CN + +00-13-7C (hex) Kaicom co., Ltd. +00137C (base 16) Kaicom co., Ltd. + #109, Gayang Techno Town 1487, Gayang-dong,Kangso-gu + Seoul 157-810 + KR + +E8-56-59 (hex) Advanced-Connectek Inc. +E85659 (base 16) Advanced-Connectek Inc. + No. 2,Alley 9, Lane 45, Baoxing Rd., Xiadian Dist., + New Taipei City 231 + TW + +34-BF-90 (hex) Fiberhome Telecommunication Technologies Co.,LTD +34BF90 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +CC-B3-F8 (hex) FUJITSU ISOTEC LIMITED +CCB3F8 (base 16) FUJITSU ISOTEC LIMITED + 135,Higashinozaki,Hobara-machi, + Date-shi Fukushima 960-0695 + JP + +E4-A4-71 (hex) Intel Corporate +E4A471 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +10-F0-05 (hex) Intel Corporate +10F005 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +64-CC-2E (hex) Xiaomi Communications Co Ltd +64CC2E (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +88-01-F2 (hex) Vitec System Engineering Inc. +8801F2 (base 16) Vitec System Engineering Inc. + 203203 Kita-shinagawa + Shinagawa-ku Tokyo 140-0001 + JP + +14-D1-1F (hex) HUAWEI TECHNOLOGIES CO.,LTD +14D11F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +DC-09-4C (hex) HUAWEI TECHNOLOGIES CO.,LTD +DC094C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +1C-67-58 (hex) HUAWEI TECHNOLOGIES CO.,LTD +1C6758 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-BC-F8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +24BCF8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A0-04-3E (hex) Parker Hannifin Manufacturing Germany GmbH & Co. KG +A0043E (base 16) Parker Hannifin Manufacturing Germany GmbH & Co. KG + Gutenbergstrasse 38 + Kaarst Select State 41564 + DE + +C8-45-29 (hex) IMK Networks Co.,Ltd +C84529 (base 16) IMK Networks Co.,Ltd + 201-Ho jungribjunja, 16-3bunji, + Seoul 143-816 + KR + +7C-47-7C (hex) IEEE Registration Authority +7C477C (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F8-77-B8 (hex) Samsung Electronics Co.,Ltd +F877B8 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +F0-D2-F1 (hex) Amazon Technologies Inc. +F0D2F1 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +A8-E3-EE (hex) Sony Interactive Entertainment Inc. +A8E3EE (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +00-24-8D (hex) Sony Interactive Entertainment Inc. +00248D (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +00-04-1F (hex) Sony Interactive Entertainment Inc. +00041F (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +20-A9-0E (hex) TCT mobile ltd +20A90E (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +EC-43-8B (hex) YAPTV +EC438B (base 16) YAPTV + 623 GangNamDa-Ro + Seocho-Gu Seoul 06524 + KR + +98-0C-A5 (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +980CA5 (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan + Wuhan Hubei 430000 + CN + +44-11-02 (hex) EDMI Europe Ltd +441102 (base 16) EDMI Europe Ltd + The Grainger Suite, Dobson House + Newcastle upon Tyne NE3 3PF + GB + +A8-5E-E4 (hex) 12Sided Technology, LLC +A85EE4 (base 16) 12Sided Technology, LLC + 1 Penn Plaza, 36th Floor + New York NY 10119 + US + +18-21-95 (hex) Samsung Electronics Co.,Ltd +182195 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +44-78-3E (hex) Samsung Electronics Co.,Ltd +44783E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +0C-A2-F4 (hex) Chameleon Technology (UK) Limited +0CA2F4 (base 16) Chameleon Technology (UK) Limited + Gardner House, Hornbeam Park Avenue + Hornbeam Park Harrogate HG2 8NA + GB + +BC-44-B0 (hex) Elastifile +BC44B0 (base 16) Elastifile + Abba Even 8 + Herzlia 4672526 + IL + +74-BF-B7 (hex) Nusoft Corporation +74BFB7 (base 16) Nusoft Corporation + 3F.-1, No. 880, Zhongzheng Rd., + Zhonghe Dist., New Taipei City Taiwan (R.O.C.) 235-86 + TW + +50-DA-00 (hex) Hangzhou H3C Technologies Co., Limited +50DA00 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +F4-ED-5F (hex) SHENZHEN KTC TECHNOLOGY GROUP +F4ED5F (base 16) SHENZHEN KTC TECHNOLOGY GROUP + Wuhe Street + Shenzhen Guangdong 518129 + CN + +00-E0-E4 (hex) FANUC ROBOTICS NORTH AMERICA, Inc. +00E0E4 (base 16) FANUC ROBOTICS NORTH AMERICA, Inc. + 3900 W. HAMLIN RD. + ROCHESTER HILLS MI 48309-3253 + US + +00-08-96 (hex) Printronix, Inc. +000896 (base 16) Printronix, Inc. + 14600 Myford Rd. + Irvine California 92623-9559 + US + +24-5E-BE (hex) QNAP Systems, Inc. +245EBE (base 16) QNAP Systems, Inc. + 2F., No.22, Zhongxing Rd., Xizhi Dist. + New Taipei City 221 + TW + +04-04-EA (hex) Valens Semiconductor Ltd. +0404EA (base 16) Valens Semiconductor Ltd. + 8 Hanagar Street + Hod Hasharon Hod Hasharon 4501309 + IL + +80-0D-D7 (hex) Latticework, Inc +800DD7 (base 16) Latticework, Inc + 2210 O'Toole Ave, Suite 250 + San Jose CA 95131 + US + +D0-B5-3D (hex) SEPRO ROBOTIQUE +D0B53D (base 16) SEPRO ROBOTIQUE + ZI Acti-Est Les Ajoncs + LA ROCHE SUR YON F85003 + FR + +00-D0-EC (hex) NAKAYO Inc +00D0EC (base 16) NAKAYO Inc + Development Support Center 165 Higashiomuro-machi + Maebashi-shi Gunma 379-2105 + JP + +4C-CC-6A (hex) Micro-Star INTL CO., LTD. +4CCC6A (base 16) Micro-Star INTL CO., LTD. + No.69, Lide St., + New Taipei City Taiwan 235 + TW + +30-63-6B (hex) Apple, Inc. +30636B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-88-4D (hex) JAPAN RADIO CO., LTD. +70884D (base 16) JAPAN RADIO CO., LTD. + 5-1-1 SHIMORENJYAKU, + MITAKA-SHI, TOKYO 181-8510 + JP + +A4-F1-E8 (hex) Apple, Inc. +A4F1E8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-67-51 (hex) Compal Broadband Networks, Inc. +546751 (base 16) Compal Broadband Networks, Inc. + 13F., No.1, Taiyuan 1st St. + Zhubei City Hsinchu County 30265 + TW + +24-0B-0A (hex) Palo Alto Networks +240B0A (base 16) Palo Alto Networks + 4401 Great America Parkway + Santa Clara CA 95054 + US + +D0-99-D5 (hex) Alcatel-Lucent +D099D5 (base 16) Alcatel-Lucent + 777 East Middlefield Road + Mountain View CA 94043 + US + +14-C3-C2 (hex) K.A. Schmersal GmbH & Co. KG +14C3C2 (base 16) K.A. Schmersal GmbH & Co. KG + Möddinghofe 30 + Wuppertal NRW 42279 + DE + +10-78-5B (hex) Actiontec Electronics, Inc +10785B (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +DC-00-77 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +DC0077 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +F4-F5-A5 (hex) Nokia Corporation +F4F5A5 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo 24101 + FI + +EC-9B-5B (hex) Nokia Corporation +EC9B5B (base 16) Nokia Corporation + Joensuunkatu 7 + Salo Varsinais-Suomi 24101 + FI + +2C-CC-15 (hex) Nokia Corporation +2CCC15 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo Varsinais-Suomi 24101 + FI + +14-BB-6E (hex) Samsung Electronics Co.,Ltd +14BB6E (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +18-86-AC (hex) Nokia Danmark A/S +1886AC (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790V + DK + +00-1F-5C (hex) Nokia Danmark A/S +001F5C (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790V + DK + +00-1F-00 (hex) Nokia Danmark A/S +001F00 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790V + DK + +00-25-47 (hex) Nokia Danmark A/S +002547 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-18-C5 (hex) Nokia Danmark A/S +0018C5 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V 1790 + DK + +00-16-4E (hex) Nokia Danmark A/S +00164E (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-26-68 (hex) Nokia Danmark A/S +002668 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-24-7D (hex) Nokia Danmark A/S +00247D (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-22-65 (hex) Nokia Danmark A/S +002265 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +F8-80-96 (hex) Elsys Equipamentos Eletrônicos Ltda +F88096 (base 16) Elsys Equipamentos Eletrônicos Ltda + Rod. Visconde de Porto Seguro, n.º 2.660, Sitio Recreio dos Cafezais + Valinhos SP 13278327 + BR + +A8-11-FC (hex) ARRIS Group, Inc. +A811FC (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-AA (hex) DrayTek Corp. +001DAA (base 16) DrayTek Corp. + No. 26, Fu-Shing Road + Hsin-Chu 303 + TW + +E4-98-D1 (hex) Microsoft Mobile Oy +E498D1 (base 16) Microsoft Mobile Oy + Keilalahdentie 4 + ESPOO 02150 + FI + +6C-27-79 (hex) Microsoft Mobile Oy +6C2779 (base 16) Microsoft Mobile Oy + Keilalahdentie 4 + ESPOO 02150 + FI + +00-CF-1C (hex) Communication Machinery Corporation +00CF1C (base 16) Communication Machinery Corporation + 1226 ANACAPA + SANTA BARBARA CA 93101 + US + +28-CC-01 (hex) Samsung Electronics Co.,Ltd +28CC01 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D8-FB-5E (hex) ASKEY COMPUTER CORP +D8FB5E (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +00-23-26 (hex) FUJITSU LIMITED +002326 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +0C-BF-15 (hex) Genetec Inc. +0CBF15 (base 16) Genetec Inc. + 2280 boul Alfred-Nobel + St. Laurent Quebec H4S 2A4 + CA + +00-0D-4B (hex) Roku, Inc. +000D4B (base 16) Roku, Inc. + 399 Sherman Ave. #12 + Palo Alto CA 94306 + US + +00-40-FB (hex) CASCADE COMMUNICATIONS +0040FB (base 16) CASCADE COMMUNICATIONS + PRODUCTION QUALITY ENGINEER + WESTFORD MA 01886 + US + +D0-54-2D (hex) Cambridge Industries(Group) Co.,Ltd. +D0542D (base 16) Cambridge Industries(Group) Co.,Ltd. + 22 Floor,Qilai Tower;889 Yishan Road + Shanghai 200233 + CN + +74-4A-A4 (hex) zte corporation +744AA4 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-1B-A9 (hex) Brother industries, LTD. +001BA9 (base 16) Brother industries, LTD. + Printing & Solutions Company, Development Management Dept. + Nagoya Aichi 467-8561 + JP + +30-A2-20 (hex) ARG Telecom +30A220 (base 16) ARG Telecom + No.69, W. Lavasani St. , + Tehran Tehran 1936938194 + IR + +6C-F3-73 (hex) Samsung Electronics Co.,Ltd +6CF373 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +9C-3A-AF (hex) Samsung Electronics Co.,Ltd +9C3AAF (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +78-1F-DB (hex) Samsung Electronics Co.,Ltd +781FDB (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +4C-A5-6D (hex) Samsung Electronics Co.,Ltd +4CA56D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B8-6C-E8 (hex) Samsung Electronics Co.,Ltd +B86CE8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +0C-B3-19 (hex) Samsung Electronics Co.,Ltd +0CB319 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +18-3F-47 (hex) Samsung Electronics Co.,Ltd +183F47 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B4-62-93 (hex) Samsung Electronics Co.,Ltd +B46293 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +50-A4-C8 (hex) Samsung Electronics Co.,Ltd +50A4C8 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-00-1D (hex) Cabletron Systems, Inc. +00001D (base 16) Cabletron Systems, Inc. + 35 INDUSTRIAL WAY + ROCHESTER NH 03867 + US + +18-67-B0 (hex) Samsung Electronics Co.,Ltd +1867B0 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +6C-83-36 (hex) Samsung Electronics Co.,Ltd +6C8336 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +DC-D8-7C (hex) Beijing Jingdong Century Trading Co., LTD. +DCD87C (base 16) Beijing Jingdong Century Trading Co., LTD. + 28F,Building A Zhaolin Plaza,NO.19,Ronghua Middle road,BDA Beijing + Beijing 100176 + CN + +C4-DA-7D (hex) Ivium Technologies B.V. +C4DA7D (base 16) Ivium Technologies B.V. + De Zaale 11 + Eindhoven Noord Brabant 5612 AJ + NL + +00-0B-6A (hex) Asiarock Technology Limited +000B6A (base 16) Asiarock Technology Limited + P.O. Box957, Offshore Incorporations Cen + Road Town Tortola 12345 + VG + +00-90-96 (hex) ASKEY COMPUTER CORP +009096 (base 16) ASKEY COMPUTER CORP + 2F, NO. 2, LANE 497 + TAIPEI 23136 12345 + TW + +00-1B-9E (hex) ASKEY COMPUTER CORP +001B9E (base 16) ASKEY COMPUTER CORP + 10F,NO.119,CHIENKANG RD, + CHUNG-HO,TPIPEI 235 + TW + +E0-CA-94 (hex) ASKEY COMPUTER CORP +E0CA94 (base 16) ASKEY COMPUTER CORP + 10F,NO.119,CHIENKANG RD,CHUNG-HO,TAIPEI, + TAIWAN TAIPEI 235 + TW + +00-26-B6 (hex) ASKEY COMPUTER CORP +0026B6 (base 16) ASKEY COMPUTER CORP + 10F,NO.119,CHIENKANG RD,CHUNG-HO,TAIPEI, + TAIWAN TAIPEI 235 + TW + +00-25-57 (hex) BlackBerry RTS +002557 (base 16) BlackBerry RTS + 440 Phillip Street + Waterloo Ontario N2L 5W9 + CA + +00-1C-CC (hex) BlackBerry RTS +001CCC (base 16) BlackBerry RTS + 305 Phillip Street + Waterloo Ontario N2L 3W8 + CA + +00-30-0A (hex) Aztech Electronics Pte Ltd +00300A (base 16) Aztech Electronics Pte Ltd + 31 UBI ROAD 1 + singapore 408694 + SG + +00-1F-3F (hex) AVM GmbH +001F3F (base 16) AVM GmbH + Alt-Moabit 95 + Berlin 10559 + DE + +24-65-11 (hex) AVM GmbH +246511 (base 16) AVM GmbH + Alt-Moabit 95 + Berlin 10559 + DE + +C0-FF-D4 (hex) NETGEAR +C0FFD4 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +6C-B0-CE (hex) NETGEAR +6CB0CE (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-8E-F2 (hex) NETGEAR +008EF2 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +9C-D3-6D (hex) NETGEAR +9CD36D (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +C4-04-15 (hex) NETGEAR +C40415 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +E8-FC-AF (hex) NETGEAR +E8FCAF (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +84-1B-5E (hex) NETGEAR +841B5E (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +2C-B0-5D (hex) NETGEAR +2CB05D (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +A0-21-B7 (hex) NETGEAR +A021B7 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-24-B2 (hex) NETGEAR +0024B2 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-1B-2F (hex) NETGEAR +001B2F (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-26-4D (hex) Arcadyan Technology Corporation +00264D (base 16) Arcadyan Technology Corporation + 4F., No. 9 , Park Avenue II , + Hsinchu Taiwan 300 + TW + +84-9C-A6 (hex) Arcadyan Technology Corporation +849CA6 (base 16) Arcadyan Technology Corporation + 4F, No. 9, Park Avenue II , + Hsinchu 300 + TW + +E0-3E-44 (hex) Broadcom +E03E44 (base 16) Broadcom + 190 Mathilda Place + Sunnyvale CA 94086 + US + +00-1F-33 (hex) NETGEAR +001F33 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-20-40 (hex) ARRIS Group, Inc. +002040 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +38-6B-BB (hex) ARRIS Group, Inc. +386BBB (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E8-6D-52 (hex) ARRIS Group, Inc. +E86D52 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +3C-75-4A (hex) ARRIS Group, Inc. +3C754A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E4-83-99 (hex) ARRIS Group, Inc. +E48399 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-21-43 (hex) ARRIS Group, Inc. +002143 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +74-F6-12 (hex) ARRIS Group, Inc. +74F612 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-24-95 (hex) ARRIS Group, Inc. +002495 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-24-A0 (hex) ARRIS Group, Inc. +0024A0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-08-0E (hex) ARRIS Group, Inc. +00080E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-90-9C (hex) ARRIS Group, Inc. +00909C (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-12-25 (hex) ARRIS Group, Inc. +001225 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +14-5B-D1 (hex) ARRIS Group, Inc. +145BD1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +6C-C1-D2 (hex) ARRIS Group, Inc. +6CC1D2 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +1C-14-48 (hex) ARRIS Group, Inc. +1C1448 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-17-84 (hex) ARRIS Group, Inc. +001784 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1C-11 (hex) ARRIS Group, Inc. +001C11 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1E-46 (hex) ARRIS Group, Inc. +001E46 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-18-A4 (hex) ARRIS Group, Inc. +0018A4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-18-C0 (hex) ARRIS Group, Inc. +0018C0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-23-74 (hex) ARRIS Group, Inc. +002374 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +AC-E0-10 (hex) Liteon Technology Corporation +ACE010 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road, ChungHo + New Taipei City Taiwan 23585 + TW + +74-75-48 (hex) Amazon Technologies Inc. +747548 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +00-00-B1 (hex) Alpha Micro +0000B1 (base 16) Alpha Micro + 3501 SUNFLOWER + SANTA ANA CA 92704 + US + +00-18-02 (hex) Alpha Networks Inc. +001802 (base 16) Alpha Networks Inc. + No.8 Li-shing Seventh Road,Science-based Industrial Park + Hsinchu 300 + TW + +00-1E-45 (hex) Sony Mobile Communications Inc +001E45 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-1C-A4 (hex) Sony Mobile Communications Inc +001CA4 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-1A-75 (hex) Sony Mobile Communications Inc +001A75 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +78-84-3C (hex) Sony Corporation +78843C (base 16) Sony Corporation + Gotenyama Tec,5-1-12, + Shinagawa-ku Tokyo 141-0001 + JP + +00-13-A9 (hex) Sony Corporation +0013A9 (base 16) Sony Corporation + Gotenyama Tec, 5-1-2 Kitashinagawa + Tokyo 141-0001 + JP + +00-0A-D9 (hex) Sony Mobile Communications Inc +000AD9 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-0E-07 (hex) Sony Mobile Communications Inc +000E07 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +94-CE-2C (hex) Sony Mobile Communications Inc +94CE2C (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +FC-0F-E6 (hex) Sony Interactive Entertainment Inc. +FC0FE6 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +74-DE-2B (hex) Liteon Technology Corporation +74DE2B (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +00-22-5F (hex) Liteon Technology Corporation +00225F (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +5C-93-A2 (hex) Liteon Technology Corporation +5C93A2 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road, ChungHo, TaiPei Hsien + TaiPei TaiWan 23585 + TW + +24-FD-52 (hex) Liteon Technology Corporation +24FD52 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo + New Taipei City Taipei 23585 + TW + +2C-D0-5A (hex) Liteon Technology Corporation +2CD05A (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo + New Taipei City Taipei 23585 + TW + +74-E5-43 (hex) Liteon Technology Corporation +74E543 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo + New Taipei City Taipei 23585 + TW + +00-15-CF (hex) ARRIS Group, Inc. +0015CF (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +6C-FA-A7 (hex) AMPAK Technology, Inc. +6CFAA7 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road + Hsinchu 30352 + TW + +00-23-F1 (hex) Sony Mobile Communications Inc +0023F1 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +54-E4-BD (hex) FN-LINK TECHNOLOGY LIMITED +54E4BD (base 16) FN-LINK TECHNOLOGY LIMITED + 5th Floor, A Building, Haoye Logistics Park, Shugang Channel, Bao'an District, + SHENZHEN GUANGDONG 518000 + CN + +54-14-FD (hex) Orbbec 3D Technology International +5414FD (base 16) Orbbec 3D Technology International + 950 Stephenson Hwy Suite 208 + Troy MI 48083 + US + +90-0B-C1 (hex) Sprocomm Technologies CO.,Ltd +900BC1 (base 16) Sprocomm Technologies CO.,Ltd + 5D-506 F1.6 Block,Tianfa Building,Tianan Chegongmiao Industrial Park,Futian Dist,Shenzhen China + Shenzhen Guangdong 518000 + CN + +00-1C-A8 (hex) AirTies Wireless Networks +001CA8 (base 16) AirTies Wireless Networks + Gulbahar Mahallesi, Avni Diligil Sokak + ISTANBUL ISTANBUL 34394 + TR + +48-5D-60 (hex) AzureWave Technology Inc. +485D60 (base 16) AzureWave Technology Inc. + 8F ., No.94, Baozhong Rd. + Xindian City Taipei County 231 + TW + +DC-85-DE (hex) AzureWave Technology Inc. +DC85DE (base 16) AzureWave Technology Inc. + 8F ., No.94, Baozhong RD, Sindian, + New Taipei City 231 + TW + +B0-EE-45 (hex) AzureWave Technology Inc. +B0EE45 (base 16) AzureWave Technology Inc. + 8F ., No.94, Baozhong Rd. , Xindian Dist., + New Taipei City 231 + US + +00-23-8E (hex) ADB Broadband Italia +00238E (base 16) ADB Broadband Italia + VIALE SARCA 222 + MILANO 20126 + IT + +00-1D-8B (hex) ADB Broadband Italia +001D8B (base 16) ADB Broadband Italia + VIALE SARCA 222 + MILANO 20126 + IT + +00-13-C8 (hex) ADB Broadband Italia +0013C8 (base 16) ADB Broadband Italia + VIALE SARCA 222 + MILANO 20126 + IT + +DC-0B-1A (hex) ADB Broadband Italia +DC0B1A (base 16) ADB Broadband Italia + via Sarca 222 + Milano 20126 + IT + +0C-6A-E6 (hex) Stanley Security Solutions +0C6AE6 (base 16) Stanley Security Solutions + 6161 East 75th Street + Indianapolis IN 46250 + US + +84-26-15 (hex) ADB Broadband Italia +842615 (base 16) ADB Broadband Italia + VIALE SARCA 336 + MILANO 20126 + IT + +F0-84-2F (hex) ADB Broadband Italia +F0842F (base 16) ADB Broadband Italia + VIALE SARCA 336 + MILANO 20126 + IT + +54-27-1E (hex) AzureWave Technology Inc. +54271E (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City 231 + TW + +28-C2-DD (hex) AzureWave Technology Inc. +28C2DD (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd., + New Taipei City Taiwan 231 + TW + +80-A5-89 (hex) AzureWave Technology Inc. +80A589 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd., + New Taipei City Taiwan 231 + TW + +C4-09-38 (hex) FUJIAN STAR-NET COMMUNICATION CO.,LTD +C40938 (base 16) FUJIAN STAR-NET COMMUNICATION CO.,LTD + 19-22# Building,,Star-net Science Plaza + Fuzhou Fujian 350002 + CN + +00-1C-50 (hex) TCL Technoly Electronics (Huizhou) Co., Ltd. +001C50 (base 16) TCL Technoly Electronics (Huizhou) Co., Ltd. + 10/F, Block A , TCL Tower + Shenzhen Guangdong 518057 + CN + +00-AA-02 (hex) Intel Corporation +00AA02 (base 16) Intel Corporation + 445 + piscataway NJ 08554 + US + +AC-E5-F0 (hex) Doppler Labs +ACE5F0 (base 16) Doppler Labs + 611 Broadway Suite 523 + New York NY 10012 + US + +F4-8E-38 (hex) Dell Inc. +F48E38 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +74-C6-3B (hex) AzureWave Technology Inc. +74C63B (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +7C-7A-91 (hex) Intel Corporate +7C7A91 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +AC-7B-A1 (hex) Intel Corporate +AC7BA1 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +6C-29-95 (hex) Intel Corporate +6C2995 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +98-4F-EE (hex) Intel Corporate +984FEE (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +E8-2A-EA (hex) Intel Corporate +E82AEA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +60-57-18 (hex) Intel Corporate +605718 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C4-D9-87 (hex) Intel Corporate +C4D987 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +FC-F8-AE (hex) Intel Corporate +FCF8AE (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +60-36-DD (hex) Intel Corporate +6036DD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +10-0B-A9 (hex) Intel Corporate +100BA9 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +8C-70-5A (hex) Intel Corporate +8C705A (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +60-67-20 (hex) Intel Corporate +606720 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +7C-5C-F8 (hex) Intel Corporate +7C5CF8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B4-E1-C4 (hex) Microsoft Mobile Oy +B4E1C4 (base 16) Microsoft Mobile Oy + Keilalahdentie 4 + Espoo 02150 + FI + +E0-75-7D (hex) Motorola Mobility LLC, a Lenovo Company +E0757D (base 16) Motorola Mobility LLC, a Lenovo Company + 600 North US Highway 45 + Libertyville IL 60048 + US + +34-BB-26 (hex) Motorola Mobility LLC, a Lenovo Company +34BB26 (base 16) Motorola Mobility LLC, a Lenovo Company + 600 North US Highway 45 + Libertyville IL 60048 + US + +80-6C-1B (hex) Motorola Mobility LLC, a Lenovo Company +806C1B (base 16) Motorola Mobility LLC, a Lenovo Company + 222 Merchandise Mart Plaza, Suite 1800 + Chicago IL 60654 + US + +00-16-EB (hex) Intel Corporate +0016EB (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-18-DE (hex) Intel Corporate +0018DE (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +5C-E0-C5 (hex) Intel Corporate +5CE0C5 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +58-A8-39 (hex) Intel Corporate +58A839 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1E-67 (hex) Intel Corporate +001E67 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-22-FA (hex) Intel Corporate +0022FA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-15-00 (hex) Intel Corporate +001500 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A0-88-B4 (hex) Intel Corporate +A088B4 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +64-80-99 (hex) Intel Corporate +648099 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +D0-7E-35 (hex) Intel Corporate +D07E35 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1E-65 (hex) Intel Corporate +001E65 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +34-84-46 (hex) Ericsson AB +348446 (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +04-4E-06 (hex) Ericsson AB +044E06 (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +00-27-0E (hex) Intel Corporate +00270E (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-26-B9 (hex) Dell Inc. +0026B9 (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +64-00-6A (hex) Dell Inc. +64006A (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-D0-9E (hex) 2Wire Inc +00D09E (base 16) 2Wire Inc + 694 TASMAN DRIVE + MILPITAS CA 95035 + US + +00-19-E4 (hex) 2Wire Inc +0019E4 (base 16) 2Wire Inc + 1704 Automation Parkway + San Jose CA 94538 + US + +00-1A-C4 (hex) 2Wire Inc +001AC4 (base 16) 2Wire Inc + 1704 Automation Parkway + San Jose CA 94538 + US + +00-1B-5B (hex) 2Wire Inc +001B5B (base 16) 2Wire Inc + 1704 Automation Parkway + San Jose CA 95131 + US + +3C-EA-4F (hex) 2Wire Inc +3CEA4F (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose 95131 + US + +DC-7F-A4 (hex) 2Wire Inc +DC7FA4 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose 95131 + US + +B0-D5-CC (hex) Texas Instruments +B0D5CC (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +38-29-DD (hex) ONvocal Inc +3829DD (base 16) ONvocal Inc + 104 Otis Street, Ste 28 + Northborough MA 01532 + US + +00-1E-C7 (hex) 2Wire Inc +001EC7 (base 16) 2Wire Inc + 1704 Automation Prkwy + San Jose 95131 + US + +00-26-50 (hex) 2Wire Inc +002650 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +00-23-51 (hex) 2Wire Inc +002351 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +00-1E-4F (hex) Dell Inc. +001E4F (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +5C-26-0A (hex) Dell Inc. +5C260A (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +78-45-C4 (hex) Dell Inc. +7845C4 (base 16) Dell Inc. + One Dell way + Round Rock 78682 + US + +C8-1F-66 (hex) Dell Inc. +C81F66 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-15-C5 (hex) Dell Inc. +0015C5 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-14-22 (hex) Dell Inc. +001422 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +10-98-36 (hex) Dell Inc. +109836 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +80-0A-80 (hex) IEEE Registration Authority +800A80 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F8-DB-88 (hex) Dell Inc. +F8DB88 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +3C-A3-48 (hex) vivo Mobile Communication Co., Ltd. +3CA348 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +E4-5A-A2 (hex) vivo Mobile Communication Co., Ltd. +E45AA2 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +CC-3B-3E (hex) Lester Electrical +CC3B3E (base 16) Lester Electrical + 625 W A Street + Lincoln NE 68522 + US + +20-82-C0 (hex) Xiaomi Communications Co Ltd +2082C0 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +DC-6D-CD (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +DC6DCD (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +C4-28-2D (hex) Embedded Intellect Pty Ltd +C4282D (base 16) Embedded Intellect Pty Ltd + Level 32, 101 Miller Street + North Sydney NSW 2060 + AU + +58-46-E1 (hex) Baxter International Inc +5846E1 (base 16) Baxter International Inc + One Baxter Parkway + Deerfield IL 60015 + US + +00-17-3F (hex) Belkin International Inc. +00173F (base 16) Belkin International Inc. + 501 West Walnut Street + Compton CA 90220-5221 + US + +00-1C-DF (hex) Belkin International Inc. +001CDF (base 16) Belkin International Inc. + 12045 E. Waterfront Drive + Playa Vista CA 90094 + US + +C0-56-27 (hex) Belkin International Inc. +C05627 (base 16) Belkin International Inc. + 12045 E. Waterfront Drive + Playa Vista CA 90094 + US + +4C-17-EB (hex) Sagemcom Broadband SAS +4C17EB (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison Cedex Hauts de Seine 92848 + FR + +CC-33-BB (hex) Sagemcom Broadband SAS +CC33BB (base 16) Sagemcom Broadband SAS + 250 ROUTE DE L'EMPEREUR + RUEIL MALMAISON CEDEX Choisissez l'état / la province 92848 + FR + +D8-6C-E9 (hex) Sagemcom Broadband SAS +D86CE9 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + RUEIL MALMAISON CEDEX Hauts de Seine 92848 + FR + +E8-F1-B0 (hex) Sagemcom Broadband SAS +E8F1B0 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + RUEIL MALMAISON CEDEX Hauts de Seine 92848 + FR + +5C-6B-32 (hex) Texas Instruments +5C6B32 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +84-DD-20 (hex) Texas Instruments +84DD20 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-18-31 (hex) Texas Instruments +001831 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +24-FD-5B (hex) SmartThings, Inc. +24FD5B (base 16) SmartThings, Inc. + 456 University Avenue + Palo Alto CA 94301 + US + +28-76-CD (hex) Funshion Online Technologies Co.,Ltd +2876CD (base 16) Funshion Online Technologies Co.,Ltd + Tower B 1201, Jinqiu International Building, No.6, Zhichun Road, Haidian District + Beijing 100088 + CN + +20-55-32 (hex) Gotech International Technology Limited +205532 (base 16) Gotech International Technology Limited + Unit 2506, 25/F, Prosperity Place,6 Shing Yip Street, Kwun Tong, Kowloon + Hong Kong 00000 + CN + +2C-FF-65 (hex) Oki Electric Industry Co., Ltd. +2CFF65 (base 16) Oki Electric Industry Co., Ltd. + 1-7-12 Toranomon + Tokyo 105-8460 + JP + +2C-27-D7 (hex) Hewlett Packard +2C27D7 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +98-4B-E1 (hex) Hewlett Packard +984BE1 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +00-29-26 (hex) Applied Optoelectronics, Inc Taiwan Branch +002926 (base 16) Applied Optoelectronics, Inc Taiwan Branch + No.18,Gong 4th Rd + New Taipei City Linkou District 24452 + TW + +24-BA-13 (hex) RISO KAGAKU CORPORATION +24BA13 (base 16) RISO KAGAKU CORPORATION + 2-8-1 Gakuen-minami + Thukuba-shi Ibaraki 305-0818 + JP + +00-17-E5 (hex) Texas Instruments +0017E5 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-17-EC (hex) Texas Instruments +0017EC (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-17-E7 (hex) Texas Instruments +0017E7 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-17-E9 (hex) Texas Instruments +0017E9 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +1C-BA-8C (hex) Texas Instruments +1CBA8C (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-15-E9 (hex) D-Link Corporation +0015E9 (base 16) D-Link Corporation + 2F, No.233-2, Pao-Chiao Road + Hsin-Tien, Taipei 231 + TW + +00-1B-11 (hex) D-Link Corporation +001B11 (base 16) D-Link Corporation + NO.289, Sinhu 3rd Rd., + Neihu District, Taipei City 114 + TW + +00-26-5A (hex) D-Link Corporation +00265A (base 16) D-Link Corporation + No.289, Sinhu 3rd Rd., + Neihu District 114 + TW + +C8-BE-19 (hex) D-Link International +C8BE19 (base 16) D-Link International + 1 International Business Park, #03-12, The Synergy + SINGAPORE 609917 + SG + +A4-BA-76 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A4BA76 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan Guangdong 523808 + CN + +00-50-C2 (hex) IEEE Registration Authority +0050C2 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +44-00-10 (hex) Apple, Inc. +440010 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-56-CD (hex) Apple, Inc. +0056CD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-60-37 (hex) NXP Semiconductors +006037 (base 16) NXP Semiconductors + High Tech Campus 32, Office 1.21 + SAF AD 13456 + NL + +DC-C0-EB (hex) ASSA ABLOY CÔTE PICARDE +DCC0EB (base 16) ASSA ABLOY CÔTE PICARDE + rue Alexandre Fichet + Oust-Marest 80460 + FR + +28-BC-56 (hex) EMAC, Inc. +28BC56 (base 16) EMAC, Inc. + 2390 EMAC Way + Carbondale IL 62902 + US + +00-CD-FE (hex) Apple, Inc. +00CDFE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-F8-95 (hex) Shenzhen TINNO Mobile Technology Corp. +A0F895 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F.,H-3 Building,OCT Eastern lndustrial Park. + Nanshan District, Shenzhen GUANGDONG 518053 + CN + +00-78-CD (hex) Ignition Design Labs +0078CD (base 16) Ignition Design Labs + 1550 Technology Drive + San Jose 95110 + US + +B4-36-A9 (hex) Fibocom Wireless Inc. +B436A9 (base 16) Fibocom Wireless Inc. + 5/F,Tower A,Technology Building II,1057# Nanhai Blvd + Shenzhen GuangDong 518000 + CN + +70-CA-4D (hex) Shenzhen lnovance Technology Co.,Ltd. +70CA4D (base 16) Shenzhen lnovance Technology Co.,Ltd. + LiuXian 2 Road + Shenzhen Guangdong 518000 + CN + +00-1A-11 (hex) Google, Inc. +001A11 (base 16) Google, Inc. + 1600 Amphitheater Parkway + Mountain View CA 94043 + US + +48-DB-50 (hex) HUAWEI TECHNOLOGIES CO.,LTD +48DB50 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan Guangdong 523808 + CN + +C8-47-8C (hex) Beken Corporation +C8478C (base 16) Beken Corporation + Building 41, Capital of Tech Leaders, 1387 Zhangdong Road, Zhangjiang High-Tech Park, Pudong New District + Shanghai 201203 + CN + +9C-EF-D5 (hex) Panda Wireless, Inc. +9CEFD5 (base 16) Panda Wireless, Inc. + 15559 Union Ave, Suite 300 + Los Gatos CA 95032 + US + +9C-34-26 (hex) ARRIS Group, Inc. +9C3426 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +2C-6E-85 (hex) Intel Corporate +2C6E85 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1D-D1 (hex) ARRIS Group, Inc. +001DD1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-CF (hex) ARRIS Group, Inc. +001DCF (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-D5 (hex) ARRIS Group, Inc. +001DD5 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-D4 (hex) ARRIS Group, Inc. +001DD4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E4-98-D6 (hex) Apple, Inc. +E498D6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-22-83 (hex) Juniper Networks +002283 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-10-DB (hex) Juniper Networks +0010DB (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-12-1E (hex) Juniper Networks +00121E (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +CC-A4-62 (hex) ARRIS Group, Inc. +CCA462 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +48-45-20 (hex) Intel Corporate +484520 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C8-0E-77 (hex) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited +C80E77 (base 16) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited + No.201-427,2F,Tthe Animation Building B1 District£¬No. 126£¬Tianjin eco-city animation Road + Tianjin 300467 + CN + +10-6F-3F (hex) BUFFALO.INC +106F3F (base 16) BUFFALO.INC + AKAMONDORI Bldg., 30-20,Ohsu 3-chome + Naka-ku,Nagoya Aichi Pref. 460-8315 + JP + +90-49-FA (hex) Intel Corporate +9049FA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +BC-0F-64 (hex) Intel Corporate +BC0F64 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-00-C5 (hex) ARRIS Group, Inc. +0000C5 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +64-55-B1 (hex) ARRIS Group, Inc. +6455B1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-02-B3 (hex) Intel Corporation +0002B3 (base 16) Intel Corporation + M/S: JF3-420 + Hillsboro OR 97124 + US + +00-03-47 (hex) Intel Corporation +000347 (base 16) Intel Corporation + M/S: JF3-420 + Hillsboro OR 97124 + US + +00-0E-0C (hex) Intel Corporation +000E0C (base 16) Intel Corporation + 2111 NE 25th Avenue + Hillsboro OR 97124 + US + +D8-D3-85 (hex) Hewlett Packard +D8D385 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +18-A9-05 (hex) Hewlett Packard +18A905 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +00-1B-78 (hex) Hewlett Packard +001B78 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +E4-FA-FD (hex) Intel Corporate +E4FAFD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +94-65-9C (hex) Intel Corporate +94659C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B0-C7-45 (hex) BUFFALO.INC +B0C745 (base 16) BUFFALO.INC + AKAMONDORI Bldg.,30-20,Ohsu 3-chome + Naka-ku,Nagoya Aichi Pref 460-8315 + JP + +14-CF-E2 (hex) ARRIS Group, Inc. +14CFE2 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +44-E1-37 (hex) ARRIS Group, Inc. +44E137 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-13-20 (hex) Intel Corporate +001320 (base 16) Intel Corporate + Lot 8, Jalan Hi-tech 2/3 + Kulim Kedah 09000 + MY + +00-80-E1 (hex) STMicroelectronics SRL +0080E1 (base 16) STMicroelectronics SRL + 1000 AZTEC WEST + london 12345 + GB + +F8-DB-7F (hex) HTC Corporation +F8DB7F (base 16) HTC Corporation + No.23 Xinghua Road + Taoyuan County 330 + TW + +64-A7-69 (hex) HTC Corporation +64A769 (base 16) HTC Corporation + No.23 Xinghua Road + Taoyuan County 330 + TW + +E8-99-C4 (hex) HTC Corporation +E899C4 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +BC-CF-CC (hex) HTC Corporation +BCCFCC (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County 330 + TW + +00-04-EA (hex) Hewlett Packard +0004EA (base 16) Hewlett Packard + MAIL STOP 42LE + CUPERTINO CA 95014 + US + +00-12-79 (hex) Hewlett Packard +001279 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-13-21 (hex) Hewlett Packard +001321 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-08-02 (hex) Hewlett Packard +000802 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-02-A5 (hex) Hewlett Packard +0002A5 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-18-71 (hex) Hewlett Packard +001871 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-0E-7F (hex) Hewlett Packard +000E7F (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-11-85 (hex) Hewlett Packard +001185 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +10-60-4B (hex) Hewlett Packard +10604B (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +C8-CB-B8 (hex) Hewlett Packard +C8CBB8 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +84-34-97 (hex) Hewlett Packard +843497 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +6C-C2-17 (hex) Hewlett Packard +6CC217 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +14-58-D0 (hex) Hewlett Packard +1458D0 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +5C-8A-38 (hex) Hewlett Packard +5C8A38 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +EC-9A-74 (hex) Hewlett Packard +EC9A74 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +2C-59-E5 (hex) Hewlett Packard +2C59E5 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +D8-FC-38 (hex) Giantec Semiconductor Inc +D8FC38 (base 16) Giantec Semiconductor Inc + No12, Lane647, Songtao Rd, Zhangjiang Hi-Tech Park + Shanghai Shanghai 201203 + CN + +AC-2A-0C (hex) CSR ZHUZHOU INSTITUTE CO.,LTD. +AC2A0C (base 16) CSR ZHUZHOU INSTITUTE CO.,LTD. + Times Ave.,Zhuzhou,hunan,China + zhuzhou Hunan 412001 + CN + +2C-67-98 (hex) InTalTech Ltd. +2C6798 (base 16) InTalTech Ltd. + Shlomo Ben David 5 + Rishon LeZion 7536215 + IL + +00-23-4D (hex) Hon Hai Precision Ind. Co.,Ltd. +00234D (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-25-56 (hex) Hon Hai Precision Ind. Co.,Ltd. +002556 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +60-18-88 (hex) zte corporation +601888 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +D8-60-B0 (hex) bioMérieux Italia S.p.A. +D860B0 (base 16) bioMérieux Italia S.p.A. + Via di Campigliano, 58 + Bagno a Ripoli Firenze 50012 + IT + +54-E6-FC (hex) TP-LINK TECHNOLOGIES CO.,LTD. +54E6FC (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + 1-6F, Building 2, Pingshandayuan Industrial, South Zone, + Shenzhen Guangdong 518000 + CN + +74-EA-3A (hex) TP-LINK TECHNOLOGIES CO.,LTD. +74EA3A (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 7, Second Part, Honghualing Industrial Zone + Shenzhen Guangdong 518000 + CN + +F8-1A-67 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +F81A67 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan + shenzhen guangdong Province 518057 + CN + +EC-17-2F (hex) TP-LINK TECHNOLOGIES CO.,LTD. +EC172F (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan + shenzhen guangdong Province 518057 + CN + +84-77-78 (hex) Cochlear Limited +847778 (base 16) Cochlear Limited + 1 University Avenue + Sydney New South Wales 2109 + AU + +88-7F-03 (hex) Comper Technology Investment Limited +887F03 (base 16) Comper Technology Investment Limited + Room 710, Wangjing SOHO Tower 1-B + Beijing Beijing 100102 + CN + +00-19-E0 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +0019E0 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + South Building, No.5 Keyuan Road + Nanshan Shenzhen 518057 + CN + +00-25-86 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +002586 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 7, Second Part, Honghualing Industrial Zone + Shenzhen Guangdong 518057 + CN + +D8-1F-CC (hex) Brocade Communications Systems, Inc. +D81FCC (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +F4-31-C3 (hex) Apple, Inc. +F431C3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-A5-C3 (hex) Apple, Inc. +64A5C3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-56-5A (hex) Hon Hai Precision Ind. Co.,Ltd. +28565A (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +6C-B5-6B (hex) HUMAX Co., Ltd. +6CB56B (base 16) HUMAX Co., Ltd. + HUMAX Village,216,Hwangsaeul-ro,Bundang-gu + Seongnam-si Gyeonggi-do 463-875 + KR + +BC-3A-EA (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +BC3AEA (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD,WUSHA,CHANG'AN,DONGGUAN,GUANGDONG,CHINA + DONGGUAN GUANGDONG 523860 + CN + +E4-22-A5 (hex) PLANTRONICS, INC. +E422A5 (base 16) PLANTRONICS, INC. + 345 ENCINAL STREET + SANTA CRUZ CA 95060 + US + +D4-C9-B2 (hex) Quanergy Systems Inc +D4C9B2 (base 16) Quanergy Systems Inc + 482 Mercury Drive + Sunnyvale California 94085 + US + +60-21-C0 (hex) Murata Manufacturing Co., Ltd. +6021C0 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1 Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +88-30-8A (hex) Murata Manufacturing Co., Ltd. +88308A (base 16) Murata Manufacturing Co., Ltd. + 1-10-1 Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +5C-DA-D4 (hex) Murata Manufacturing Co., Ltd. +5CDAD4 (base 16) Murata Manufacturing Co., Ltd. + 2288, Oaza-Ohshinohara, Yasu-cho, + Yasu-gun Shiga 520-2393 + JP + +00-26-E8 (hex) Murata Manufacturing Co., Ltd. +0026E8 (base 16) Murata Manufacturing Co., Ltd. + 2288, Oaza-Ohshinohara, Yasu-cho, + Yasu-gun Shiga 520-2393 + JP + +00-25-12 (hex) zte corporation +002512 (base 16) zte corporation + 12/F ZTE Plaza,Keji Road South,Hi-Tech Industrial Park,Nanshan District, + Shenzhen GUANGDONG 518057 + CN + +00-1C-26 (hex) Hon Hai Precision Ind. Co.,Ltd. +001C26 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-27-F8 (hex) Brocade Communications Systems, Inc. +0027F8 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +74-8E-F8 (hex) Brocade Communications Systems, Inc. +748EF8 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-24-38 (hex) Brocade Communications Systems, Inc. +002438 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-14-C9 (hex) Brocade Communications Systems, Inc. +0014C9 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +14-E6-E4 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +14E6E4 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan, + Shenzhen Guangdong Province, 518057 + CN + +34-4B-50 (hex) zte corporation +344B50 (base 16) zte corporation + 12/F,ZTE R&D Building,Kejinan Road, + Shenzhen Guangdong 518057 + CN + +FC-C8-97 (hex) zte corporation +FCC897 (base 16) zte corporation + 12/F.,zte R&D building,kejinan Road, + shenzhen guangdong 518057 + CN + +00-16-CE (hex) Hon Hai Precision Ind. Co.,Ltd. +0016CE (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-22-68 (hex) Hon Hai Precision Ind. Co.,Ltd. +002268 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +50-EB-1A (hex) Brocade Communications Systems, Inc. +50EB1A (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-18-82 (hex) HUAWEI TECHNOLOGIES CO.,LTD +001882 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + F1-20,Section F,Huawei Base,Bantian, Longgang District + ShenZhen GuangDong 518129 + CN + +D4-EA-0E (hex) Avaya Inc +D4EA0E (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +6C-FA-58 (hex) Avaya Inc +6CFA58 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +20-F3-A3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +20F3A3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District + Shenzhen Guangdong 518057 + CN + +0C-37-DC (hex) HUAWEI TECHNOLOGIES CO.,LTD +0C37DC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District + Shenzhen Guangdong 518057 + CN + +BC-76-70 (hex) HUAWEI TECHNOLOGIES CO.,LTD +BC7670 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +24-DB-AC (hex) HUAWEI TECHNOLOGIES CO.,LTD +24DBAC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +1C-1D-67 (hex) HUAWEI TECHNOLOGIES CO.,LTD +1C1D67 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +30-0E-D5 (hex) Hon Hai Precision Ind. Co.,Ltd. +300ED5 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +48-5A-B6 (hex) Hon Hai Precision Ind. Co.,Ltd. +485AB6 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +54-35-30 (hex) Hon Hai Precision Ind. Co.,Ltd. +543530 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +F8-66-D1 (hex) Hon Hai Precision Ind. Co.,Ltd. +F866D1 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +24-69-A5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +2469A5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park + Shenzhen Guangdong 518057 + CN + +EC-23-3D (hex) HUAWEI TECHNOLOGIES CO.,LTD +EC233D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, + Shenzhen Guangdong 518057 + CN + +78-F5-FD (hex) HUAWEI TECHNOLOGIES CO.,LTD +78F5FD (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, + Shenzhen Guangdong 518057 + CN + +5C-7D-5E (hex) HUAWEI TECHNOLOGIES CO.,LTD +5C7D5E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, + Shenzhen Guangdong 518057 + CN + +90-67-1C (hex) HUAWEI TECHNOLOGIES CO.,LTD +90671C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +BC-25-E0 (hex) HUAWEI TECHNOLOGIES CO.,LTD +BC25E0 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-E3-FB (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4E3FB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D0-2D-B3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D02DB3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate + Shenzhen GuangDong 518057 + CN + +E8-CD-2D (hex) HUAWEI TECHNOLOGIES CO.,LTD +E8CD2D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate + Shenzhen GuangDong 518057 + CN + +84-A8-E4 (hex) HUAWEI TECHNOLOGIES CO.,LTD +84A8E4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +0C-96-BF (hex) HUAWEI TECHNOLOGIES CO.,LTD +0C96BF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +60-E7-01 (hex) HUAWEI TECHNOLOGIES CO.,LTD +60E701 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E8-08-8B (hex) HUAWEI TECHNOLOGIES CO.,LTD +E8088B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A0-51-C6 (hex) Avaya Inc +A051C6 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +F0-EB-D0 (hex) Shanghai Feixun Communication Co.,Ltd. +F0EBD0 (base 16) Shanghai Feixun Communication Co.,Ltd. + Building 90,No,4855,Guangfulin Road + shanghai Shanghai 201616 + CN + +64-3E-8C (hex) HUAWEI TECHNOLOGIES CO.,LTD +643E8C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base + Shenzhen Guangdong 518129 + CN + +00-12-D2 (hex) Texas Instruments +0012D2 (base 16) Texas Instruments + 12500 TI Boulevard + Dallas 75243 + US + +A8-63-F2 (hex) Texas Instruments +A863F2 (base 16) Texas Instruments + 12203 S.W.Freeway, MS728 + Stafford 77477 + US + +7C-60-97 (hex) HUAWEI TECHNOLOGIES CO.,LTD +7C6097 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +CC-53-B5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +CC53B5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +60-DE-44 (hex) HUAWEI TECHNOLOGIES CO.,LTD +60DE44 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +10-51-72 (hex) HUAWEI TECHNOLOGIES CO.,LTD +105172 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base + Shenzhen Guangdong 518129 + CN + +08-E8-4F (hex) HUAWEI TECHNOLOGIES CO.,LTD +08E84F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base + Shenzhen Guangdong 518129 + CN + +88-86-03 (hex) HUAWEI TECHNOLOGIES CO.,LTD +888603 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen 518129 + CN + +04-F9-38 (hex) HUAWEI TECHNOLOGIES CO.,LTD +04F938 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen Guangdong 518129 + CN + +AC-85-3D (hex) HUAWEI TECHNOLOGIES CO.,LTD +AC853D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen Guangdong 518129 + CN + +48-46-FB (hex) HUAWEI TECHNOLOGIES CO.,LTD +4846FB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen Guangdong 518129 + CN + +D0-FF-50 (hex) Texas Instruments +D0FF50 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +20-C3-8F (hex) Texas Instruments +20C38F (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +7C-66-9D (hex) Texas Instruments +7C669D (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +D8-DD-FD (hex) Texas Instruments +D8DDFD (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +D0-5F-B8 (hex) Texas Instruments +D05FB8 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +E0-24-7F (hex) HUAWEI TECHNOLOGIES CO.,LTD +E0247F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +00-46-4B (hex) HUAWEI TECHNOLOGIES CO.,LTD +00464B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +80-FB-06 (hex) HUAWEI TECHNOLOGIES CO.,LTD +80FB06 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +6C-A8-49 (hex) Avaya Inc +6CA849 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +64-C3-54 (hex) Avaya Inc +64C354 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +50-CD-22 (hex) Avaya Inc +50CD22 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +B4-A9-5A (hex) Avaya Inc +B4A95A (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +84-EB-18 (hex) Texas Instruments +84EB18 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +EC-11-27 (hex) Texas Instruments +EC1127 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +58-16-26 (hex) Avaya Inc +581626 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +70-E4-22 (hex) Cisco Systems, Inc +70E422 (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +00-50-0F (hex) Cisco Systems, Inc +00500F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +7C-1D-D9 (hex) Xiaomi Communications Co Ltd +7C1DD9 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +A0-86-C6 (hex) Xiaomi Communications Co Ltd +A086C6 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +9C-99-A0 (hex) Xiaomi Communications Co Ltd +9C99A0 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +58-44-98 (hex) Xiaomi Communications Co Ltd +584498 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +00-E0-B0 (hex) Cisco Systems, Inc +00E0B0 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-E0-FE (hex) Cisco Systems, Inc +00E0FE (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-E0-34 (hex) Cisco Systems, Inc +00E034 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-E0-F9 (hex) Cisco Systems, Inc +00E0F9 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +C8-D7-19 (hex) Cisco-Linksys, LLC +C8D719 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine 92612 + US + +00-10-79 (hex) Cisco Systems, Inc +001079 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-10-29 (hex) Cisco Systems, Inc +001029 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-0E-08 (hex) Cisco-Linksys, LLC +000E08 (base 16) Cisco-Linksys, LLC + 170 West Tasman Dr. + San Jose CA 95134 + US + +44-03-A7 (hex) Cisco Systems, Inc +4403A7 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +B0-FA-EB (hex) Cisco Systems, Inc +B0FAEB (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +7C-AD-74 (hex) Cisco Systems, Inc +7CAD74 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-60-3E (hex) Cisco Systems, Inc +00603E (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-60-2F (hex) Cisco Systems, Inc +00602F (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-60-47 (hex) Cisco Systems, Inc +006047 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-50-A2 (hex) Cisco Systems, Inc +0050A2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-02-3D (hex) Cisco Systems, Inc +00023D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +20-3A-07 (hex) Cisco Systems, Inc +203A07 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-50-2A (hex) Cisco Systems, Inc +00502A (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +BC-16-F5 (hex) Cisco Systems, Inc +BC16F5 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +FC-5B-39 (hex) Cisco Systems, Inc +FC5B39 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +34-6F-90 (hex) Cisco Systems, Inc +346F90 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +5C-FC-66 (hex) Cisco Systems, Inc +5CFC66 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +D4-6D-50 (hex) Cisco Systems, Inc +D46D50 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +74-A0-2F (hex) Cisco Systems, Inc +74A02F (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +88-90-8D (hex) Cisco Systems, Inc +88908D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +F0-78-16 (hex) Cisco Systems, Inc +F07816 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-22-3A (hex) Cisco SPVTG +00223A (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +00-21-BE (hex) Cisco SPVTG +0021BE (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +14-DA-E9 (hex) ASUSTek COMPUTER INC. +14DAE9 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou, + Taipei 112 + TW + +F4-CF-E2 (hex) Cisco Systems, Inc +F4CFE2 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +A8-0C-0D (hex) Cisco Systems, Inc +A80C0D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +C0-7B-BC (hex) Cisco Systems, Inc +C07BBC (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +24-E9-B3 (hex) Cisco Systems, Inc +24E9B3 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-11-D8 (hex) ASUSTek COMPUTER INC. +0011D8 (base 16) ASUSTek COMPUTER INC. + No.150, Li-Te Rd., Peitou + Taipei 112 + TW + +C0-8C-60 (hex) Cisco Systems, Inc +C08C60 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +E8-ED-F3 (hex) Cisco Systems, Inc +E8EDF3 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +E4-C7-22 (hex) Cisco Systems, Inc +E4C722 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +64-E9-50 (hex) Cisco Systems, Inc +64E950 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +F4-1F-C2 (hex) Cisco Systems, Inc +F41FC2 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +44-AD-D9 (hex) Cisco Systems, Inc +44ADD9 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +0C-68-03 (hex) Cisco Systems, Inc +0C6803 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +1C-DE-A7 (hex) Cisco Systems, Inc +1CDEA7 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +F0-7F-06 (hex) Cisco Systems, Inc +F07F06 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +88-F0-31 (hex) Cisco Systems, Inc +88F031 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-18-F3 (hex) ASUSTek COMPUTER INC. +0018F3 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou + Taipei 112 + TW + +00-1A-92 (hex) ASUSTek COMPUTER INC. +001A92 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou + Taipei 112 + TW + +00-0C-41 (hex) Cisco-Linksys, LLC +000C41 (base 16) Cisco-Linksys, LLC + 121 Theory Dr. + Irvine CA 92612 + US + +00-16-B6 (hex) Cisco-Linksys, LLC +0016B6 (base 16) Cisco-Linksys, LLC + 121 Theory Dr. + Irvine CA 92612 + US + +00-18-F8 (hex) Cisco-Linksys, LLC +0018F8 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine CA 92612 + US + +00-25-2E (hex) Cisco SPVTG +00252E (base 16) Cisco SPVTG + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +54-D4-6F (hex) Cisco SPVTG +54D46F (base 16) Cisco SPVTG + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +A4-A2-4A (hex) Cisco SPVTG +A4A24A (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +44-E0-8E (hex) Cisco SPVTG +44E08E (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +00-E0-36 (hex) PIONEER CORPORATION +00E036 (base 16) PIONEER CORPORATION + 2610 Hanazono 4-Chome + Saitama Prefecture, 359-8 34567 + JP + +00-E0-4F (hex) Cisco Systems, Inc +00E04F (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-10-FF (hex) Cisco Systems, Inc +0010FF (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-10-54 (hex) Cisco Systems, Inc +001054 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-10-F6 (hex) Cisco Systems, Inc +0010F6 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-10-A6 (hex) Cisco Systems, Inc +0010A6 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +BC-C8-10 (hex) Cisco SPVTG +BCC810 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +7C-B2-1B (hex) Cisco SPVTG +7CB21B (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville 30044 + US + +24-76-7D (hex) Cisco SPVTG +24767D (base 16) Cisco SPVTG + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +48-1D-70 (hex) Cisco SPVTG +481D70 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +F0-B2-E5 (hex) Cisco Systems, Inc +F0B2E5 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-23-32 (hex) Apple, Inc. +002332 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-23-6C (hex) Apple, Inc. +00236C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-23-DF (hex) Apple, Inc. +0023DF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-25-00 (hex) Apple, Inc. +002500 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-25-BC (hex) Apple, Inc. +0025BC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +58-97-BD (hex) Cisco Systems, Inc +5897BD (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +5C-83-8F (hex) Cisco Systems, Inc +5C838F (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +EC-BD-1D (hex) Cisco Systems, Inc +ECBD1D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-19-E3 (hex) Apple, Inc. +0019E3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-1B-63 (hex) Apple, Inc. +001B63 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-1E-C2 (hex) Apple, Inc. +001EC2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-1F-F3 (hex) Apple, Inc. +001FF3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-10-FA (hex) Apple, Inc. +0010FA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-50-E4 (hex) Apple, Inc. +0050E4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-0D-93 (hex) Apple, Inc. +000D93 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +7C-FA-DF (hex) Apple, Inc. +7CFADF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-A3-E4 (hex) Apple, Inc. +78A3E4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-8F-C6 (hex) Apple, Inc. +148FC6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-6A-B8 (hex) Apple, Inc. +286AB8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-E0-2C (hex) Apple, Inc. +28E02C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-B9-BA (hex) Apple, Inc. +E0B9BA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-C6-10 (hex) Apple, Inc. +00C610 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B8-F6-B1 (hex) Apple, Inc. +B8F6B1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +8C-FA-BA (hex) Apple, Inc. +8CFABA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +7C-D1-C3 (hex) Apple, Inc. +7CD1C3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-DC-E2 (hex) Apple, Inc. +F0DCE2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +24-AB-81 (hex) Apple, Inc. +24AB81 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-F8-47 (hex) Apple, Inc. +E0F847 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-E7-CF (hex) Apple, Inc. +28E7CF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-CE-8F (hex) Apple, Inc. +E4CE8F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-20-66 (hex) Apple, Inc. +A82066 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-52-B7 (hex) Apple, Inc. +BC52B7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-59-48 (hex) Apple, Inc. +5C5948 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-BC-C8 (hex) Apple, Inc. +C8BCC8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E8-04-0B (hex) Apple, Inc. +E8040B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-5A-05 (hex) Apple, Inc. +145A05 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +1C-AB-A7 (hex) Apple, Inc. +1CABA7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-84-7A (hex) Apple, Inc. +C0847A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-15-9E (hex) Apple, Inc. +34159E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +58-B0-35 (hex) Apple, Inc. +58B035 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +DC-86-D8 (hex) Apple, Inc. +DC86D8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-B9-31 (hex) Apple, Inc. +90B931 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-E1-40 (hex) Apple, Inc. +D0E140 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +24-A2-E1 (hex) Apple, Inc. +24A2E1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-21-4C (hex) Insight Energy Ventures LLC +04214C (base 16) Insight Energy Ventures LLC + 123 W. Fifth St + Royal Oak MI 48067 + US + +F8-32-E4 (hex) ASUSTek COMPUTER INC. +F832E4 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +80-EA-96 (hex) Apple, Inc. +80EA96 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-03-08 (hex) Apple, Inc. +600308 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-F1-3E (hex) Apple, Inc. +04F13E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-F0-AB (hex) Apple, Inc. +98F0AB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-31-C1 (hex) Apple, Inc. +7831C1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-3A-84 (hex) Apple, Inc. +783A84 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-8D-4E (hex) Apple, Inc. +5C8D4E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-63-DF (hex) Apple, Inc. +8863DF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-1F-A1 (hex) Apple, Inc. +881FA1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-E0-EB (hex) Apple, Inc. +C8E0EB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-B8-E3 (hex) Apple, Inc. +98B8E3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-53-95 (hex) Apple, Inc. +885395 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-6C-1C (hex) Apple, Inc. +786C1C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +4C-8D-79 (hex) Apple, Inc. +4C8D79 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +1C-E6-2B (hex) Apple, Inc. +1CE62B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +0C-30-21 (hex) Apple, Inc. +0C3021 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +0C-3E-9F (hex) Apple, Inc. +0C3E9F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-FC-48 (hex) Apple, Inc. +FCFC48 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-29-3F (hex) Apple, Inc. +9C293F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +80-A1-AB (hex) Intellisis +80A1AB (base 16) Intellisis + 10350 Science Center Dr + San Diego CA 92121 + US + +84-28-5A (hex) Saffron Solutions Inc +84285A (base 16) Saffron Solutions Inc + 1337 Mass Ave #273 + Arlington MA 02476 + US + +D4-B8-FF (hex) Home Control Singapore Pte Ltd +D4B8FF (base 16) Home Control Singapore Pte Ltd + 620A Lorong 1 Toa Payoh + Singapore Singapore 217909 + SG + +08-74-02 (hex) Apple, Inc. +087402 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +94-F6-A3 (hex) Apple, Inc. +94F6A3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-E0-D9 (hex) Apple, Inc. +98E0D9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +CC-29-F5 (hex) Apple, Inc. +CC29F5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-5A-EB (hex) Apple, Inc. +285AEB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-24-75 (hex) Apple, Inc. +F02475 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-1F-23 (hex) Apple, Inc. +2C1F23 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-9F-13 (hex) Apple, Inc. +549F13 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-DB-E2 (hex) Apple, Inc. +F0DBE2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +74-81-14 (hex) Apple, Inc. +748114 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-F6-43 (hex) Apple, Inc. +18F643 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A4-5E-60 (hex) Apple, Inc. +A45E60 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-18-28 (hex) Apple, Inc. +A01828 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-03-4B (hex) Apple, Inc. +D0034B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +10-41-7F (hex) Apple, Inc. +10417F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-66-7F (hex) Apple, Inc. +A8667F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-25-98 (hex) Apple, Inc. +D02598 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +80-BE-05 (hex) Apple, Inc. +80BE05 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +24-A0-74 (hex) Apple, Inc. +24A074 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-78-8B (hex) Apple, Inc. +84788B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-A4-23 (hex) Sagemcom Broadband SAS +84A423 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +3C-78-73 (hex) Airsonics +3C7873 (base 16) Airsonics + 1289 Fordham Blvd. + Chapel Hill NC 27514 + US + +9C-88-AD (hex) Fiberhome Telecommunication Technologies Co.,LTD +9C88AD (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +88-94-7E (hex) Fiberhome Telecommunication Technologies Co.,LTD +88947E (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +C8-A2-CE (hex) Oasis Media Systems LLC +C8A2CE (base 16) Oasis Media Systems LLC + 1073 Barley Sheaf Rd + Flemington NJ 08822 + US + +58-F4-96 (hex) Source Chain +58F496 (base 16) Source Chain + #407-4 eBIZ.Center + Seoul seoul ASI|KR|KS013|SEOUL + KR + +58-7F-57 (hex) Apple, Inc. +587F57 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-7C-2D (hex) Leie IOT technology Co., Ltd +D07C2D (base 16) Leie IOT technology Co., Ltd + 9th floor,Hongchengxintai building,No.105,Yaojiayuan Road,Chaoyang District,Beijing + Beijing Beijing 100026 + CN + +EC-64-E7 (hex) MOCACARE Corporation +EC64E7 (base 16) MOCACARE Corporation + 887 Federation Way + Palo Alto CA 94303 + US + +40-86-2E (hex) JDM MOBILE INTERNET SOLUTION CO., LTD. +40862E (base 16) JDM MOBILE INTERNET SOLUTION CO., LTD. + + Jiashan Zhejiang 314100 + CN + +C4-BB-EA (hex) Pakedge Device and Software Inc +C4BBEA (base 16) Pakedge Device and Software Inc + 3847 Breakwater Ave + Hayward CA 94545 + US + +98-87-44 (hex) Wuxi Hongda Science and Technology Co.,LTD +988744 (base 16) Wuxi Hongda Science and Technology Co.,LTD + No.10 An Nan Road, Nan Quan Town, Bin Hu District + WUXI Jiangsu 214128 + CN + +E8-34-3E (hex) Beijing Infosec Technologies Co., LTD. +E8343E (base 16) Beijing Infosec Technologies Co., LTD. + Floor 4, Tower C, Global Finance and News Center + Beijing Beijing 100052 + CN + +34-69-87 (hex) zte corporation +346987 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +98-F4-28 (hex) zte corporation +98F428 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +A4-CC-32 (hex) Inficomm Co., Ltd +A4CC32 (base 16) Inficomm Co., Ltd + 3F, B-31 Building, Tanglang Industry Park, Taoyuan Str, Nanshan District + Shenzhen Guangdong 518055 + CN + +00-6D-52 (hex) Apple, Inc. +006D52 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-32-99 (hex) Lenovo (Beijing) Co., Ltd. +A03299 (base 16) Lenovo (Beijing) Co., Ltd. + No.6, ChuangYe Road, + Haidian District Beijing 100085 + CN + +40-54-E4 (hex) Wearsafe Labs Inc +4054E4 (base 16) Wearsafe Labs Inc + 1429 Park Street + Hartford CT 06106 + US + +DC-9A-8E (hex) Nanjing Cocomm electronics co., LTD +DC9A8E (base 16) Nanjing Cocomm electronics co., LTD + Room 201,the Qinheng technology park building + Nanjing Jiangsu 210012 + CN + +AC-EE-9E (hex) Samsung Electronics Co.,Ltd +ACEE9E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B8-57-D8 (hex) Samsung Electronics Co.,Ltd +B857D8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +70-BF-3E (hex) Charles River Laboratories +70BF3E (base 16) Charles River Laboratories + 1023 Wappoo Road Suite 43B + Charleston SC 29407 + US + +A8-C8-7F (hex) Roqos, Inc. +A8C87F (base 16) Roqos, Inc. + 1775 Greensboro Station Place + Mclean Virginia 22102 + US + +3C-83-1E (hex) CKD Corporation +3C831E (base 16) CKD Corporation + 250, Ouji 2-Chome + Komaki Aichi 485-8551 + JP + +90-DF-FB (hex) HOMERIDER SYSTEMS +90DFFB (base 16) HOMERIDER SYSTEMS + 12 RUE REMORA + GRADIGNAN GIRONDE 33170 + FR + +30-5A-3A (hex) ASUSTek COMPUTER INC. +305A3A (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +2C-08-1C (hex) OVH +2C081C (base 16) OVH + 2, rue Kellermann + Roubaix Nord 59100 + FR + +C0-84-88 (hex) Finis Inc +C08488 (base 16) Finis Inc + 7085-E Las Positas Rd + Livermore CA 94551 + US + +38-F5-57 (hex) JOLATA, INC. +38F557 (base 16) JOLATA, INC. + 2262 N. FIRST ST. + SAN JOSE CA 95134 + US + +54-A3-FA (hex) BQT Solutions (Australia)Pty Ltd +54A3FA (base 16) BQT Solutions (Australia)Pty Ltd + Unit 29, 1 Talavera Road + North Ryde NSW 2113 + AU + +24-6C-8A (hex) YUKAI Engineering +246C8A (base 16) YUKAI Engineering + 16-11-101, Tomihisa, Shinjuku + Tokyo - 162-0067 + + +AC-C5-1B (hex) Zhuhai Pantum Electronics Co., Ltd. +ACC51B (base 16) Zhuhai Pantum Electronics Co., Ltd. + Area A, 3rd floor, Building No.1, No.3883, Zhuhai Avenue, Zhuhai, Guangdong, China + Zhuhai Guangdong 519000 + CN + +38-5F-66 (hex) Cisco SPVTG +385F66 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +B8-44-D9 (hex) Apple, Inc. +B844D9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-7A-03 (hex) Ciena Corporation +9C7A03 (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +5C-CF-7F (hex) Espressif Inc. +5CCF7F (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +68-12-95 (hex) Lupine Lighting Systems GmbH +681295 (base 16) Lupine Lighting Systems GmbH + Winnberger Weg 11 + Neumarkt Bavaria 92318 + DE + +70-11-AE (hex) Music Life LTD +7011AE (base 16) Music Life LTD + Unit E, 31/F, Billion Centre Tower A + Kowloon N/A 00000 + HK + +04-1E-7A (hex) DSPWorks +041E7A (base 16) DSPWorks + 12/947, MHB Colony, Gorai Road + Mumbai 400091 + IN + +84-A7-88 (hex) Perples +84A788 (base 16) Perples + 8F, 209 Dosan-daero, + Seoul 135-892 + KR + +AC-60-B6 (hex) Ericsson AB +AC60B6 (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +14-B3-70 (hex) Gigaset Digital Technology (Shenzhen) Co., Ltd. +14B370 (base 16) Gigaset Digital Technology (Shenzhen) Co., Ltd. + 11/F, Matsunichi Building, No.9996 Shen Nan Boulevard, Nan Shan District, Shenzhen, China + ShenZhen Guangdong 518000 + CN + +68-89-C1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +6889C1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +1C-49-7B (hex) Gemtek Technology Co., Ltd. +1C497B (base 16) Gemtek Technology Co., Ltd. + No. 1 Jen Ai Road Hsinchu Industrial Park Hukou, Hsinchu 30352 TAIWAN, REPUBLIC OF CHINA + Hsinchu TAIWAN 30352 + TW + +2C-CF-58 (hex) HUAWEI TECHNOLOGIES CO.,LTD +2CCF58 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D0-93-80 (hex) Ducere Technologies Pvt. Ltd. +D09380 (base 16) Ducere Technologies Pvt. Ltd. + 222B West Marredpally + Secunderabad Telangana 500026 + IN + +68-F9-56 (hex) Objetivos y Servicio de Valor Añadido +68F956 (base 16) Objetivos y Servicio de Valor Añadido + c/Monte Esquinza, 28 1ºD + MADRID MADRID 28010 + ES + +C8-A9-FC (hex) Goyoo Networks Inc. +C8A9FC (base 16) Goyoo Networks Inc. + Building D, Kelin Blocks, No.107, Dongsi North St, + Beijing Beijing 100007 + CN + +FC-FE-C2 (hex) Invensys Controls UK Limited +FCFEC2 (base 16) Invensys Controls UK Limited + 401 Southway Drive + Plymouth Devon Pl6 6QT + GB + +68-9A-B7 (hex) Atelier Vision Corporation +689AB7 (base 16) Atelier Vision Corporation + 888-340 Nakagawa + Hamamatsu Shizuoka 431-1304 + JP + +44-4C-A8 (hex) Arista Networks +444CA8 (base 16) Arista Networks + 5453 Great America Parkway + Santa Clara CA 95054 + US + +7C-2B-E1 (hex) Shenzhen Ferex Electrical Co.,Ltd +7C2BE1 (base 16) Shenzhen Ferex Electrical Co.,Ltd + Block 2,Jiuzhou Industrial Park,Gongming + Shenzhen Guangdong 518107 + CN + +50-31-AD (hex) ABB Global Industries and Services Private Limited +5031AD (base 16) ABB Global Industries and Services Private Limited + 21st floor, World Trade Center + Bangalore Karnataka 560055 + IN + +14-3E-BF (hex) zte corporation +143EBF (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +FC-2F-EF (hex) UTT Technologies Co., Ltd. +FC2FEF (base 16) UTT Technologies Co., Ltd. + Room 301, Building 9, No. 518 Xinzhuan + Shanghai Shanghai 201612 + CN + +A4-C1-38 (hex) Telink Semiconductor (Taipei) Co. Ltd. +A4C138 (base 16) Telink Semiconductor (Taipei) Co. Ltd. + Room 1050. 10F. Buld. H, No. 3-2 YuanQu St., + Taipei Taipei 11503 + TW + +20-F5-10 (hex) Codex Digital Limited +20F510 (base 16) Codex Digital Limited + 60 Poland Street + London Greater London W1F 7NT + GB + +A8-74-1D (hex) PHOENIX CONTACT Electronics GmbH +A8741D (base 16) PHOENIX CONTACT Electronics GmbH + Dringenauer Str. 30 + Bad Pyrmont - D-31812 + DE + +F0-9A-51 (hex) Shanghai Viroyal Electronic Technology Company Limited +F09A51 (base 16) Shanghai Viroyal Electronic Technology Company Limited + LevelB,Building#3,401 Caobao Road,Shanghai,China + Shanghai Shanghai 200233 + CN + +4C-B8-2C (hex) Cambridge Mobile Telematics, Inc. +4CB82C (base 16) Cambridge Mobile Telematics, Inc. + One Broadway, 14th Floor + Cambridge MA 02142 + US + +E4-A3-2F (hex) Shanghai Artimen Technology Co., Ltd. +E4A32F (base 16) Shanghai Artimen Technology Co., Ltd. + Room 4462, Third Building, No. 505, Xinge Road, Xinqiao Town, SongJiang District, Shanghai City, China + Shanghai Shanghai 201206 + CN + +F4-67-2D (hex) ShenZhen Topstar Technology Company +F4672D (base 16) ShenZhen Topstar Technology Company + 5/F Buliding 204,Tai Ran ShenZhen Science&Industry Park + ShenZhen GuangZhou 518042 + CN + +A8-D8-28 (hex) Ascensia Diabetes Care +A8D828 (base 16) Ascensia Diabetes Care + 5 Wood Hollow Rd, + Parsippany NJ 07054 + US + +B8-69-C2 (hex) Sunitec Enterprise Co., Ltd. +B869C2 (base 16) Sunitec Enterprise Co., Ltd. + 1F., No.35, Dayong St., Zhonghe Dist., + New Taipei City Taiwan 235 + TW + +88-CB-A5 (hex) Suzhou Torchstar Intelligent Technology Co.,Ltd +88CBA5 (base 16) Suzhou Torchstar Intelligent Technology Co.,Ltd + Rm1704B,Business Building, No.181, Cuiyuan Rd.,SIP + Suzhou Jiangsu Province 215000 + CN + +7C-A2-3E (hex) HUAWEI TECHNOLOGIES CO.,LTD +7CA23E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +50-1A-A5 (hex) GN Netcom A/S +501AA5 (base 16) GN Netcom A/S + Lautrupbjerg 7 + Ballerup Ballerup DK-2750 + DK + +A4-8D-3B (hex) Vizio, Inc +A48D3B (base 16) Vizio, Inc + 39 Tesla + Irvine CA 92618 + US + +1C-56-FE (hex) Motorola Mobility LLC, a Lenovo Company +1C56FE (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +B8-99-B0 (hex) Cohere Technologies +B899B0 (base 16) Cohere Technologies + 404 Saratoga Avenue + Santa Clara CA 95050 + US + +D8-5D-EF (hex) Busch-Jaeger Elektro GmbH +D85DEF (base 16) Busch-Jaeger Elektro GmbH + Freisenbergstrasse 2 + Luedenscheid NRW 58513 + DE + +88-A2-D7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +88A2D7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-32-3A (hex) so-logic +00323A (base 16) so-logic + Lustkandlgasse 52 + Vienna Vienna 1090 + AT + +80-9F-AB (hex) Fiberhome Telecommunication Technologies Co.,LTD +809FAB (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +E0-03-70 (hex) ShenZhen Continental Wireless Technology Co., Ltd. +E00370 (base 16) ShenZhen Continental Wireless Technology Co., Ltd. + North 23F, Dongfang Technology Building, + Shenzhen Guangdong 518057 + CN + +04-61-69 (hex) MEDIA GLOBAL LINKS CO., LTD. +046169 (base 16) MEDIA GLOBAL LINKS CO., LTD. + 580-16, Horikawa-cho + Kawasaki Kanagawa 212-0013 + JP + +BC-EB-5F (hex) Fujian Beifeng Telecom Technology Co., Ltd. +BCEB5F (base 16) Fujian Beifeng Telecom Technology Co., Ltd. + A-15, Huaqiao Economic Development Zone, Shuangyang, Luojiang, + quanzhou fujian 362000 + CN + +AC-5A-14 (hex) Samsung Electronics Co.,Ltd +AC5A14 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F0-AB-54 (hex) MITSUMI ELECTRIC CO.,LTD. +F0AB54 (base 16) MITSUMI ELECTRIC CO.,LTD. + 2-11-2, Tsurumaki + Tama-shi Tokyo 206-8567 + JP + +3C-31-78 (hex) Qolsys Inc. +3C3178 (base 16) Qolsys Inc. + 1900 The Alameda + San Jose Ca 95126 + US + +08-EC-A9 (hex) Samsung Electronics Co.,Ltd +08ECA9 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E0-4B-45 (hex) Hi-P Electronics Pte Ltd +E04B45 (base 16) Hi-P Electronics Pte Ltd + 12 Ang Mo Kio Street 64 + Singapore Singapore 569088 + SG + +F4-6A-92 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +F46A92 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +F0-D6-57 (hex) ECHOSENS +F0D657 (base 16) ECHOSENS + 30 Place d'Italie + PARIS 13 Ile de France 75013 + FR + +9C-37-F4 (hex) HUAWEI TECHNOLOGIES CO.,LTD +9C37F4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +3C-47-11 (hex) HUAWEI TECHNOLOGIES CO.,LTD +3C4711 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +5C-EB-68 (hex) Cheerstar Technology Co., Ltd +5CEB68 (base 16) Cheerstar Technology Co., Ltd + 5th Floor,Hongye Industrial Park, + ShenZhen GuangDong 518006 + CN + +AC-56-2C (hex) LAVA INTERNATIONAL(H.K) LIMITED +AC562C (base 16) LAVA INTERNATIONAL(H.K) LIMITED + UNIT L 1/F MAU LAM COMM BLDG 16-18 + Hong Kong + CN + +FC-9A-FA (hex) Motus Global Inc. +FC9AFA (base 16) Motus Global Inc. + 5394 Merrick Road + Massapequa NY 11758 + US + +14-15-7C (hex) TOKYO COSMOS ELECTRIC CO.,LTD. +14157C (base 16) TOKYO COSMOS ELECTRIC CO.,LTD. + 2-268 Sobudai + Zama Kanagawa 252-8550 + JP + +20-E4-07 (hex) Spark srl +20E407 (base 16) Spark srl + Via A. Gramsci 86/A + Reggio Emilia 42124 + IT + +D0-9D-AB (hex) TCT mobile ltd +D09DAB (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +88-73-84 (hex) Toshiba +887384 (base 16) Toshiba + 2-9,Suehiro-Cho + Ome Tokyo 1988710 + JP + +24-69-3E (hex) innodisk Corporation +24693E (base 16) innodisk Corporation + 5F., No. 237, Sec. 1, Datong Rd., Xizhi Dist. + New Taipei City Taiwan 221 + TW + +C0-DC-6A (hex) Qingdao Eastsoft Communication Technology Co.,LTD +C0DC6A (base 16) Qingdao Eastsoft Communication Technology Co.,LTD + Shandong QINGDAO, No. 16A, Shangqing Road, Shibei District + QINGDAO Shandong 266023 + CN + +24-B0-A9 (hex) Shanghai Mobiletek Communication Ltd. +24B0A9 (base 16) Shanghai Mobiletek Communication Ltd. + RM201, Building 9, No 99 Tianzhou RD, Shanghai China + Shanghai Shanghai 200233 + CN + +1C-C5-86 (hex) Absolute Acoustics +1CC586 (base 16) Absolute Acoustics + Av. Corifeu de Azevedo Marques, 1703 + Sao Paulo 05581-001 + BR + +40-7F-E0 (hex) Glory Star Technics (ShenZhen) Limited +407FE0 (base 16) Glory Star Technics (ShenZhen) Limited + 4/f, West Block, Xi Li Village, Xin Wu Industry Bldg., Nan Shan District, ShenZhen, China + Shenzhen China + CN + +C8-E1-30 (hex) Milkyway Group Ltd +C8E130 (base 16) Milkyway Group Ltd + RM 405 Tung Ming Building + Hong Kong Hong Kong 999077 + HK + +48-6E-FB (hex) Davit System Technology Co., Ltd. +486EFB (base 16) Davit System Technology Co., Ltd. + #304 Hanlim Human Tower, LS-Ro 172 + Gunpo-si Gyeonggi-Do 435-824 + KR + +B0-96-6C (hex) Lanbowan Technology Ltd. +B0966C (base 16) Lanbowan Technology Ltd. + No. 60 Langbao Xi Road + Foshan Guangdong 528051 + CN + +1C-F0-3E (hex) Wearhaus Inc. +1CF03E (base 16) Wearhaus Inc. + 2041 Bancroft Way + Berkeley CA 94704 + US + +C4-3A-BE (hex) Sony Mobile Communications Inc +C43ABE (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +88-3B-8B (hex) Cheering Connection Co. Ltd. +883B8B (base 16) Cheering Connection Co. Ltd. + Room 602, Shenzhen Software Park T2-B + Shenzhen Guangdong 518057 + CN + +E4-F9-39 (hex) Minxon Hotel Technology INC. +E4F939 (base 16) Minxon Hotel Technology INC. + 3F, No.37, Dongxing Rd., Xinyi Dist. + Taipei Taiwan 11070 + TW + +14-6B-72 (hex) Shenzhen Fortune Ship Technology Co., Ltd. +146B72 (base 16) Shenzhen Fortune Ship Technology Co., Ltd. + Room 701-716, 7th Floor, + Nanshan District, Shenzhen Guangdong 518000 + CN + +B8-F0-80 (hex) SPS, INC. +B8F080 (base 16) SPS, INC. + 70, Techno8-ro + Yuseong-gu Daejeon 305-500 + KR + +80-50-67 (hex) W & D TECHNOLOGY CORPORATION +805067 (base 16) W & D TECHNOLOGY CORPORATION + 1F., NO.22, GONGYEQU 31TH RD + TAICHUNG CITY TAIWAN 40768 + TW + +78-F9-44 (hex) Private +78F944 (base 16) Private + +24-76-56 (hex) Shanghai Net Miles Fiber Optics Technology Co., LTD. +247656 (base 16) Shanghai Net Miles Fiber Optics Technology Co., LTD. + Flat F, 17th Floor, Southern International Mansion + Shanghai Shanghai 201401 + CN + +F8-CF-C5 (hex) Motorola Mobility LLC, a Lenovo Company +F8CFC5 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +A4-7B-85 (hex) ULTIMEDIA Co Ltd, +A47B85 (base 16) ULTIMEDIA Co Ltd, + Guro-Gu Saeaml-ro 102 + Seoul 152770 + KR + +5C-5B-35 (hex) Mist Systems, Inc. +5C5B35 (base 16) Mist Systems, Inc. + 1601 South De Anza Blvd, Suite 248 + Cupertino CA 95014 + US + +EC-BA-FE (hex) GIROPTIC +ECBAFE (base 16) GIROPTIC + 165 avenue de Bretagne + Lille Nord 59000 + FR + +3C-2C-94 (hex) 杭州德澜科技有限公司(HangZhou Delan Technology Co.,Ltd) +3C2C94 (base 16) 杭州德澜科技有限公司(HangZhou Delan Technology Co.,Ltd) + tianmushan road no.398,Xihu District, hangzhou city, zhejiang province, China + Hangzhou ZheJiang 310013 + CN + +24-1B-44 (hex) Hangzhou Tuners Electronics Co., Ltd +241B44 (base 16) Hangzhou Tuners Electronics Co., Ltd + 5/F,Building No.1,No.619 + BinJiang District, Hangzhou ZheJiang 310053 + CN + +80-A8-5D (hex) Osterhout Design Group +80A85D (base 16) Osterhout Design Group + 153 Townsend Suite 570 + San Francisco CA 94107 + US + +AC-CA-AB (hex) Virtual Electric Inc +ACCAAB (base 16) Virtual Electric Inc + 1314 Vanna Ct + San Jose CA 95131 + US + +48-54-15 (hex) NET RULES TECNOLOGIA EIRELI +485415 (base 16) NET RULES TECNOLOGIA EIRELI + Rua Madre Cabrini, 240 - 7°andar + São Paulo São Paulo 04020000 + BR + +78-40-E4 (hex) Samsung Electronics Co.,Ltd +7840E4 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E0-99-71 (hex) Samsung Electronics Co.,Ltd +E09971 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +70-DA-9C (hex) TECSEN +70DA9C (base 16) TECSEN + $401, Jeongsu Bd, 94-70, + SEOUL NA 150-037 + KR + +2C-A2-B4 (hex) Fortify Technologies, LLC +2CA2B4 (base 16) Fortify Technologies, LLC + 6200 Shingle Creek Pkwy, Suite 400 + Minneapolis Minnesota 55430 + US + +10-D3-8A (hex) Samsung Electronics Co.,Ltd +10D38A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E4-85-01 (hex) Geberit International AG +E48501 (base 16) Geberit International AG + Schachenstrasse 77 + Jona SG 8645 + CH + +20-62-74 (hex) Microsoft Corporation +206274 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +E8-16-2B (hex) IDEO Security Co., Ltd. +E8162B (base 16) IDEO Security Co., Ltd. + 1404, Seoul Forest IT Valley, 77, Seongsuil-ro + Seongdong-gu, SEOUL 133-822 + KR + +B4-73-56 (hex) Hangzhou Treebear Networking Co., Ltd. +B47356 (base 16) Hangzhou Treebear Networking Co., Ltd. + 2F,Block A, Lianhe Building, 2#, Zijinghua RD, Xihu District + Hangzhou Zhejiang 310012 + CN + +34-68-95 (hex) Hon Hai Precision Ind. Co.,Ltd. +346895 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +84-73-03 (hex) Letv Mobile and Intelligent Information Technology (Beijing) Corporation Ltd. +847303 (base 16) Letv Mobile and Intelligent Information Technology (Beijing) Corporation Ltd. + 5th floor,Hongchengxintai building,No.105,Yaojiayuan Road,Chaoyang District,Beijing + Beijing Chaoyang 100025 + CN + +3C-C2-E1 (hex) XINHUA CONTROL ENGINEERING CO.,LTD +3CC2E1 (base 16) XINHUA CONTROL ENGINEERING CO.,LTD + 160 Wenjing Road, Minhang + Shanghai Shanghai 200245 + CN + +8C-87-3B (hex) Leica Camera AG +8C873B (base 16) Leica Camera AG + Am Leitz-Park 5 + Wetzlar Hessen 35578 + DE + +44-F4-77 (hex) Juniper Networks +44F477 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +14-29-71 (hex) NEMOA ELECTRONICS (HK) CO. LTD +142971 (base 16) NEMOA ELECTRONICS (HK) CO. LTD + ROOM 610, MINGYOU PURCHASING & DISPLAYING CENTER, + SHENZHEN GUANGDONG 518000 + CN + +78-E9-80 (hex) RainUs Co.,Ltd +78E980 (base 16) RainUs Co.,Ltd + E-703, Digital Empire, 16, Deogyeong-daero + Suwon-si Gyeonggi-do 443-702 + KR + +E0-FF-F7 (hex) Softiron Inc. +E0FFF7 (base 16) Softiron Inc. + 6540 Central Avenue + Newark California 94560 + US + +3C-6A-9D (hex) Dexatek Technology LTD. +3C6A9D (base 16) Dexatek Technology LTD. + 15F, NO.81, Sec.1, Xizhi Dist., + New Taipei City 221 + TW + +34-9E-34 (hex) Evervictory Electronic Co.Ltd +349E34 (base 16) Evervictory Electronic Co.Ltd + Chu-Chi management district Humen Town, DongGuan GuangDong Province, China + DongGuan GuangDong 523000 + CN + +70-0F-C7 (hex) SHENZHEN IKINLOOP TECHNOLOGY CO.,LTD. +700FC7 (base 16) SHENZHEN IKINLOOP TECHNOLOGY CO.,LTD. + Room 8B,Building C, Tongfang Information Port, Langshan Road, Science + Shenzhen Guangdong 518057 + CN + +BC-74-D7 (hex) HangZhou JuRu Technology CO.,LTD +BC74D7 (base 16) HangZhou JuRu Technology CO.,LTD + No.803 Room,Shuyu Building,No.98 Wenyi West Road,Hangzhou,Zhejiang,China + hangzhou zhejiang 310053 + CN + +78-EB-14 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +78EB14 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +3C-49-37 (hex) ASSMANN Electronic GmbH +3C4937 (base 16) ASSMANN Electronic GmbH + Auf dem Schueffel 3 + Luedenscheid Germany 58513 + DE + +84-44-64 (hex) ServerU Inc +844464 (base 16) ServerU Inc + 8100 NW 64th Street + Miami FL 33166 + US + +00-35-60 (hex) Rosen Aviation +003560 (base 16) Rosen Aviation + 1020 Owen Loop South + Eugene Oregon 97402 + US + +F8-BC-41 (hex) Rosslare Enterprises Limited +F8BC41 (base 16) Rosslare Enterprises Limited + Flat 912 Wing Fat Industrial Building + Kowloon Bay Kowloon + HK + +3C-B7-92 (hex) Hitachi Maxell, Ltd., Optronics Division +3CB792 (base 16) Hitachi Maxell, Ltd., Optronics Division + 5030 Totsuka-cho, Totsuka-ku + Yokohama Kanagawa 244-0003 + JP + +F8-B2-F3 (hex) GUANGZHOU BOSMA TECHNOLOGY CO.,LTD +F8B2F3 (base 16) GUANGZHOU BOSMA TECHNOLOGY CO.,LTD + FL.3,A5,No.11 Kaiyuan Ave., Scienc City,Guangzhou,CHINA + Guangzhou GuangDong 510530 + CN + +28-D9-8A (hex) Hangzhou Konke Technology Co.,Ltd. +28D98A (base 16) Hangzhou Konke Technology Co.,Ltd. + Hangzhou cuibai road 7, ROOM 422 + Hangzhou Zhejiang 310012 + CN + +D8-93-41 (hex) General Electric Global Research +D89341 (base 16) General Electric Global Research + 2623 Camino Ramon + San Ramon CA 94583 + US + +1C-9E-CB (hex) Beijing Nari Smartchip Microelectronics Company Limited +1C9ECB (base 16) Beijing Nari Smartchip Microelectronics Company Limited + Northern Territory Xixiaokou Rd,Haidian district,Beijing 100192,China + beijing beijing 100192 + CN + +D4-8D-D9 (hex) Meld Technology, Inc +D48DD9 (base 16) Meld Technology, Inc + 725 San Aleso Ave + Sunnyvale CA 94085 + US + +DC-C6-22 (hex) BUHEUNG SYSTEM +DCC622 (base 16) BUHEUNG SYSTEM + 302, 45, Jeonpa-ro, 24 Beongil + Anyang-si Gyeonggi-do 430-857 + KR + +90-2C-C7 (hex) C-MAX Asia Limited +902CC7 (base 16) C-MAX Asia Limited + Unit 117, 1/F, Liven House + Kwun Tong Kowloon 852 + HK + +88-70-EF (hex) SC Professional Trading Co., Ltd. +8870EF (base 16) SC Professional Trading Co., Ltd. + 2 Soi Krungthepkreetar 21 + Sapansoong Bangkok 10250 + TH + +94-C0-38 (hex) Tallac Networks +94C038 (base 16) Tallac Networks + 6528 Lonetree Blvd. + Rocklin CA 95765 + US + +68-36-B5 (hex) DriveScale, Inc. +6836B5 (base 16) DriveScale, Inc. + 530 Lakeside Dr. #190 + Sunnyvale CALIFORNIA 94085 + US + +C4-08-80 (hex) Shenzhen UTEPO Tech Co., Ltd. +C40880 (base 16) Shenzhen UTEPO Tech Co., Ltd. + 5/F Western Block, M-8 Building, + Shenzhen Guangdong 518057 + CN + +D8-80-39 (hex) Microchip Technology Inc. +D88039 (base 16) Microchip Technology Inc. + 2355 W. Chandler Blvd. + Chandler AZ 85224 + US + +5C-96-6A (hex) RTNET +5C966A (base 16) RTNET + 827-64, Yeoksam-dong, Kangnam-Gu + Seoul - 135-080 + KR + +BC-BC-46 (hex) SKS Welding Systems GmbH +BCBC46 (base 16) SKS Welding Systems GmbH + Marie-Curie-Str. 14 + Kaiserslautern Rheinlandpfalz 67661 + DE + +98-16-EC (hex) IC Intracom +9816EC (base 16) IC Intracom + 550 Commerce Blvd + Oldsmar Florida 34677 + US + +D0-62-A0 (hex) China Essence Technology (Zhumadian) Co., Ltd. +D062A0 (base 16) China Essence Technology (Zhumadian) Co., Ltd. + 4th Floor, Administrative Service Center Office of Yicheng District + Zhumadian Henan Province 463000 + CN + +90-17-9B (hex) Nanomegas +90179B (base 16) Nanomegas + BD Ed.Machtens 79/22 + BXL Molenbeek 1080 + BE + +14-F8-93 (hex) Wuhan FiberHome Digital Technology Co.,Ltd. +14F893 (base 16) Wuhan FiberHome Digital Technology Co.,Ltd. + No.88 YouKeyuan Road + Wuhan Hubei 430074 + CN + +58-21-36 (hex) KMB systems, s.r.o. +582136 (base 16) KMB systems, s.r.o. + Dr. M. Horakove 559 + Liberec Czech Republic 46006 + CZ + +80-09-02 (hex) Keysight Technologies, Inc. +800902 (base 16) Keysight Technologies, Inc. + 1400 Fountaingrove Pkwy. + Santa Rosa CA 95403 + US + +04-99-E6 (hex) Shenzhen Yoostar Technology Co., Ltd +0499E6 (base 16) Shenzhen Yoostar Technology Co., Ltd + #503,Tower D, HUA HAN Innovation Park, + Shenzhen Guangdong 518000 + CN + +70-FF-5C (hex) Cheerzing Communication(Xiamen)Technology Co.,Ltd +70FF5C (base 16) Cheerzing Communication(Xiamen)Technology Co.,Ltd + Room N514,North Torch Building,5 Torch Road + Xiamen Fujian 361005 + CN + +4C-48-DA (hex) Beijing Autelan Technology Co.,Ltd +4C48DA (base 16) Beijing Autelan Technology Co.,Ltd + 1-4F, 3rd Area, 9#Building Zhongguancun Software Park + Beijing 100193 + CN + +20-5C-FA (hex) Yangzhou ChangLian Network Technology Co,ltd. +205CFA (base 16) Yangzhou ChangLian Network Technology Co,ltd. + No.60, Shangfang Temple Road + Yangzhou City Jiangsu 225000 + CN + +84-93-0C (hex) InCoax Networks Europe AB +84930C (base 16) InCoax Networks Europe AB + Strommavagen 2 + Gavle Sweden 80309 + SE + +1C-A2-B1 (hex) ruwido austria gmbh +1CA2B1 (base 16) ruwido austria gmbh + Koestendorferstrasse 8 + Neumarkt a.W. Salzburg 5202 + AT + +38-4B-76 (hex) AIRTAME ApS +384B76 (base 16) AIRTAME ApS + Vestergade 20C + Copenhagen C Copenhagen 1456 + DK + +38-B1-DB (hex) Hon Hai Precision Ind. Co.,Ltd. +38B1DB (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +34-F6-D2 (hex) Panasonic Taiwan Co.,Ltd. +34F6D2 (base 16) Panasonic Taiwan Co.,Ltd. + 579,Yuan Shan Road + New Taipei Taiwan 235 + + +30-75-12 (hex) Sony Mobile Communications Inc +307512 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +64-00-2D (hex) Powerlinq Co., LTD +64002D (base 16) Powerlinq Co., LTD + 13 PingDong Road 4 , + Zhuhai GD 519060 + + +B4-7C-29 (hex) Shenzhen Guzidi Technology Co.,Ltd +B47C29 (base 16) Shenzhen Guzidi Technology Co.,Ltd + South 6/F,Yingtang Building,No.5 Kejiyuan Road,Nanshan District,Shenzhen City,Guangdong Province,P.R. China + Shenzhen Guangdong 518000 + CN + +D4-8F-33 (hex) Microsoft Corporation +D48F33 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +54-F8-76 (hex) ABB AG +54F876 (base 16) ABB AG + Trafoweg 4 + Halle / Saale Saxony-Anhalt 06112 + DE + +34-B7-FD (hex) Guangzhou Younghead Electronic Technology Co.,Ltd +34B7FD (base 16) Guangzhou Younghead Electronic Technology Co.,Ltd + Room 206,Wenzhenxin Building,Block 3, No.2 Kefa RD,Hi-Tech Park, Nanshan District, Shenzhen,China + Shenzhen Guangdong 518052 + CN + +B4-17-80 (hex) DTI Group Ltd +B41780 (base 16) DTI Group Ltd + 50 Affleck Rd + Perth Airport Western Australia 6105 + AU + +48-9D-18 (hex) Flashbay Limited +489D18 (base 16) Flashbay Limited + 6 The Fountain Centre + London London SW6 2TW + GB + +90-20-3A (hex) BYD Precision Manufacture Co.,Ltd +90203A (base 16) BYD Precision Manufacture Co.,Ltd + Building 23#,NO.3009 BYD Road,Pingshan + Shenzhen Guangdong 518118 + CN + +80-EA-CA (hex) Dialog Semiconductor Hellas SA +80EACA (base 16) Dialog Semiconductor Hellas SA + Leoforos Syggrou 143 + Athens Attiki 17121 + GR + +20-A9-9B (hex) Microsoft Corporation +20A99B (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +60-48-26 (hex) Newbridge Technologies Int. Ltd. +604826 (base 16) Newbridge Technologies Int. Ltd. + 35/F Central Plaza + Hong Kong + CN + +38-F3-3F (hex) TATSUNO CORPORATION +38F33F (base 16) TATSUNO CORPORATION + 2-6,Mita 3-Chome,Minato-ku + Tokyo 108-8520 + JP + +D8-0C-CF (hex) C.G.V. S.A.S. +D80CCF (base 16) C.G.V. S.A.S. + 18, RUE THEODORE MONOD + OSTWALD CEDEX BAS-RHIN 67541 + FR + +4C-BB-58 (hex) Chicony Electronics Co., Ltd. +4CBB58 (base 16) Chicony Electronics Co., Ltd. + No.25, Wugong 6th Rd., Wugu Dist., + New Taipei City 248, TAIWAN, REPUBLIC OF CHINA 248 + TW + +A4-12-42 (hex) NEC Platforms, Ltd. +A41242 (base 16) NEC Platforms, Ltd. + 800 Shimomata + Kakegawa Shizuoka 436-8501 + JP + +D0-0A-AB (hex) Yokogawa Digital Computer Corporation +D00AAB (base 16) Yokogawa Digital Computer Corporation + Shinjuku MIDWEST Bldg.4-30-3 + Yoyogi Shibuya-ku, Tokyo 151-0053 + JP + +C4-00-06 (hex) Lipi Data Systems Ltd. +C40006 (base 16) Lipi Data Systems Ltd. + Mewar Industrial Area (M.I.A) + UDAIPUR RAJASTHAN 313003 + IN + +38-26-2B (hex) UTran Technology +38262B (base 16) UTran Technology + No.130, Guoji Rd., Tucheng Dist., + New Taipei City 23650 + TW + +48-0C-49 (hex) NAKAYO Inc +480C49 (base 16) NAKAYO Inc + Development Support Center 165 Higashiomuro-machi + Maebashi-shi Gunma 379-2105 + JP + +3C-D9-CE (hex) Eclipse WiFi +3CD9CE (base 16) Eclipse WiFi + 68 S Service Rd + Melville NY 11747 + US + +60-77-E2 (hex) Samsung Electronics Co.,Ltd +6077E2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-19-10 (hex) Samsung Electronics Co.,Ltd +FC1910 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-79-0B (hex) Hitachi High Technologies America, Inc. +FC790B (base 16) Hitachi High Technologies America, Inc. + 208 Fairforest Way + Greenville SC 29607 + US + +60-81-F9 (hex) Helium Systems, Inc +6081F9 (base 16) Helium Systems, Inc + 717 Market Street + San Francisco CA 94102 + US + +84-01-A7 (hex) Greyware Automation Products, Inc +8401A7 (base 16) Greyware Automation Products, Inc + 308 Oriole Ct + Murphy TX 75094 + US + +98-F1-70 (hex) Murata Manufacturing Co., Ltd. +98F170 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +68-6E-48 (hex) Prophet Electronic Technology Corp.,Ltd +686E48 (base 16) Prophet Electronic Technology Corp.,Ltd + 9F ,3 Building,No 1535,Hongmei Road ,Xuhui District + Shanghai Shanghai 200233 + CN + +04-C9-91 (hex) Phistek INC. +04C991 (base 16) Phistek INC. + 5 Floor, No.188, Section 3, Datong Road + New Taipei City 221 + TW + +3C-A1-0D (hex) Samsung Electronics Co.,Ltd +3CA10D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +64-6C-B2 (hex) Samsung Electronics Co.,Ltd +646CB2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +68-05-71 (hex) Samsung Electronics Co.,Ltd +680571 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-B4-84 (hex) Samsung Electronics Co.,Ltd +14B484 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F4-C4-47 (hex) Coagent International Enterprise Limited +F4C447 (base 16) Coagent International Enterprise Limited + FLAT/RM 2 6F CROWN TND BLDG 106 HOW MING ST KWUN TONG + Hong Kong Hong Kong 528133 + CN + +C8-E4-2F (hex) Technical Research Design and Development +C8E42F (base 16) Technical Research Design and Development + 186 Lincoln street + Boston MA 02111 + US + +C4-C9-EC (hex) Gugaoo HK Limited +C4C9EC (base 16) Gugaoo HK Limited + Unit 04, 7/F BRIGHT WAY TOWER + Kowloon, Hongkong + HK + +34-E4-2A (hex) Automatic Bar Controls Inc. +34E42A (base 16) Automatic Bar Controls Inc. + 790 Eubanks Dr + Vacaville CA 95688 + US + +30-59-B7 (hex) Microsoft +3059B7 (base 16) Microsoft + 1 Microsoft Way + Redmond Washington 98052 + US + +20-A7-87 (hex) Bointec Taiwan Corporation Limited +20A787 (base 16) Bointec Taiwan Corporation Limited + 1F, A20, L790, SEC.5, + TAIPEI TAIWAN 11082 + TW + +A0-FC-6E (hex) Telegrafia a.s. +A0FC6E (base 16) Telegrafia a.s. + Lomena 7 + Kosice Slovakia 040 01 + + +20-53-CA (hex) Risk Technology Ltd +2053CA (base 16) Risk Technology Ltd + Matrix House, Merlin Court + Altrincham Cheshire WA14 5NL + GB + +A4-3D-78 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +A43D78 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +04-57-2F (hex) Sertel Electronics UK Ltd +04572F (base 16) Sertel Electronics UK Ltd + Rutland House, 148 Edmund Street, + Birmingham B3 2FD + GB + +D8-97-7C (hex) Grey Innovation +D8977C (base 16) Grey Innovation + 255 Mary St + Richmond Victoria 3121 + AU + +BC-8D-0E (hex) Nokia +BC8D0E (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +A4-9F-85 (hex) Lyve Minds, Inc +A49F85 (base 16) Lyve Minds, Inc + 10001 N. De Anza Blvd, Ste 300 + Cupertino CA 95014 + US + +78-92-3E (hex) Nokia Corporation +78923E (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +AC-A9-A0 (hex) Audioengine, Ltd. +ACA9A0 (base 16) Audioengine, Ltd. + 1535 Dido Mt Salem Rd + Ackerman Ms 39735 + US + +A4-81-EE (hex) Nokia Corporation +A481EE (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +78-D6-6F (hex) Aristocrat Technologies Australia Pty. Ltd. +78D66F (base 16) Aristocrat Technologies Australia Pty. Ltd. + Building A, Pinnacle Office Park + North Ryde N.S.W. 2113 + AU + +44-1E-91 (hex) ARVIDA Intelligent Electronics Technology Co.,Ltd. +441E91 (base 16) ARVIDA Intelligent Electronics Technology Co.,Ltd. + No.3 Qiliang Road., + Danyang Jiangsu 212300 + CN + +C4-62-6B (hex) ZPT Vigantice +C4626B (base 16) ZPT Vigantice + Vigantice 266 + Roznov pod Radhostem 75661 + CZ + +EC-17-66 (hex) Research Centre Module +EC1766 (base 16) Research Centre Module + 3 Eight March 4Th Street + Moscow Moscow 125190 + RU + +A0-D1-2A (hex) AXPRO Technology Inc. +A0D12A (base 16) AXPRO Technology Inc. + 8F, No.128, sec. 4 Chung Hsiao E. RD., + Taipei city 10866 + TW + +20-9A-E9 (hex) Volacomm Co., Ltd +209AE9 (base 16) Volacomm Co., Ltd + 15F-6., No.7, Sec.3, New Taipei Blvd., Xinzhuang Dist., New Taipei City 242., Taiwan (R.O.C) + Xinzhuang Dist. New Taipei City 242 + TW + +34-5D-10 (hex) Wytek +345D10 (base 16) Wytek + 10 rue jean jaures + Poitiers 86000 + FR + +6C-14-F7 (hex) Erhardt+Leimer GmbH +6C14F7 (base 16) Erhardt+Leimer GmbH + Albert-Leimer-Platz 1 + Stadtbergen 86391 + DE + +B0-D5-9D (hex) Shenzhen Zowee Technology Co., Ltd +B0D59D (base 16) Shenzhen Zowee Technology Co., Ltd + Block 5 (ZOWEE Technology Building), + Pingshan, Xili Town, Nanshan District Shenzhen, Guangdong 518055 + CN + +68-28-BA (hex) Dejai +6828BA (base 16) Dejai + PO Box 101 + Toorak Vic 3142 + AU + +B0-57-06 (hex) Vallox Oy +B05706 (base 16) Vallox Oy + Myllykylantie 9-11 + Loimaa 32200 + FI + +48-EE-07 (hex) Silver Palm Technologies LLC +48EE07 (base 16) Silver Palm Technologies LLC + 9639 DOCTOR PERRY RD STE 123N + IJAMSVILLE Maryland 21754 + US + +50-C7-BF (hex) TP-LINK TECHNOLOGIES CO.,LTD. +50C7BF (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +20-5A-00 (hex) Coval +205A00 (base 16) Coval + ZA Les Petits Champs + MONTELIER Drome 26120 + FR + +A8-A6-68 (hex) zte corporation +A8A668 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-EE-BD (hex) HTC Corporation +00EEBD (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +38-F7-08 (hex) National Resource Management, Inc. +38F708 (base 16) National Resource Management, Inc. + 480 Neponset St. Bldg. #2 + Canton MA 02021 + US + +E0-DB-88 (hex) Open Standard Digital-IF Interface for SATCOM Systems +E0DB88 (base 16) Open Standard Digital-IF Interface for SATCOM Systems + 3090 Raritan Ave + Aberdeen Proving Ground MD 21001 + US + +A8-BD-3A (hex) UNIONMAN TECHNOLOGY CO.,LTD +A8BD3A (base 16) UNIONMAN TECHNOLOGY CO.,LTD + 18F, HUAYANG TOWER,YANDAYI ROAD + Huizhou Guangdong 516007 + CN + +A8-24-EB (hex) ZAO NPO Introtest +A824EB (base 16) ZAO NPO Introtest + Studencheskaya st. 55 + Ekaterinburg Sverdlovsk region 620078 + RU + +C4-0E-45 (hex) ACK Networks,Inc. +C40E45 (base 16) ACK Networks,Inc. + Floor3,Building B.,No.1 ShangDi XinXi Rd. + Beijing 100085 + CN + +3C-89-A6 (hex) KAPELSE +3C89A6 (base 16) KAPELSE + 5 Allee De Saint-Cloud + 54600 Villers Les Nancy + FR + +A4-6C-C1 (hex) LTi REEnergy GmbH +A46CC1 (base 16) LTi REEnergy GmbH + Heinrich-Hertz-Straße 18 + Unna North Rhine-Westfalia 59423 + DE + +A8-B9-B3 (hex) ESSYS +A8B9B3 (base 16) ESSYS + Daerung Post Tower 5 15F + Seoul Gasan-Dong, Geumchen-gu 153-702 + KR + +6C-09-D6 (hex) Digiquest Electronics LTD +6C09D6 (base 16) Digiquest Electronics LTD + 26 Park House + London NW11 7PT + GB + +48-18-42 (hex) Shanghai Winaas Co. Equipment Co. Ltd. +481842 (base 16) Shanghai Winaas Co. Equipment Co. Ltd. + 8F Building A, WanDa Square + Shanghai 200433 + CN + +44-70-98 (hex) MING HONG TECHNOLOGY (SHEN ZHEN) LIMITED +447098 (base 16) MING HONG TECHNOLOGY (SHEN ZHEN) LIMITED + Unit 906,South Block,Resources Tech Building, + Shenzhen Guangdong province 518000 + CN + +9C-BD-9D (hex) SkyDisk, Inc. +9CBD9D (base 16) SkyDisk, Inc. + 2F Tenjin central place, + Fukuoka-shi Fukuoka 810-0001 + JP + +74-C6-21 (hex) Zhejiang Hite Renewable Energy Co.,LTD +74C621 (base 16) Zhejiang Hite Renewable Energy Co.,LTD + NO1320,2th Ring Road(South) + Tongxiang City Zhejiang Province 314500 + CN + +D4-31-9D (hex) Sinwatec +D4319D (base 16) Sinwatec + 76 Rikhard Zorge st. + Ufa Bashkortostan 450075 + RU + +B0-68-B6 (hex) Hangzhou OYE Technology Co. Ltd +B068B6 (base 16) Hangzhou OYE Technology Co. Ltd + Room 202 Building 12 Wenxinrenjia, + Hangzhou Zhejiang 310051 + CN + +9C-65-F9 (hex) AcSiP Technology Corp. +9C65F9 (base 16) AcSiP Technology Corp. + 3F-1, No. 207, Fusing Rd. + Taoyuan Taiwan 33066 + TW + +48-76-04 (hex) Private +487604 (base 16) Private + +2C-53-4A (hex) Shenzhen Winyao Electronic Limited +2C534A (base 16) Shenzhen Winyao Electronic Limited + 7B Block A Fuqiao Building Fuhua Road + Shen Zhen Guangdong 518000 + CN + +A4-BB-AF (hex) Lime Instruments +A4BBAF (base 16) Lime Instruments + 1187 Brittmoore Road + Houston TX 77043 + US + +F4-90-CA (hex) Tensorcom +F490CA (base 16) Tensorcom + 5900 Pastuer Ct., Suite 105 + Carlsbad CA 92008 + US + +E4-4C-6C (hex) Shenzhen Guo Wei Electronic Co,. Ltd. +E44C6C (base 16) Shenzhen Guo Wei Electronic Co,. Ltd. + No 3038, Lo Sha Road, Liantang + Shenzhen Guangdong 518004 + CN + +A8-57-4E (hex) TP-LINK TECHNOLOGIES CO.,LTD. +A8574E (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +B8-43-E4 (hex) Vlatacom +B843E4 (base 16) Vlatacom + Milutina Milankovica 5 + Belgrade Serbia 11080 + RS + +28-22-46 (hex) Beijing Sinoix Communication Co., LTD +282246 (base 16) Beijing Sinoix Communication Co., LTD + Gehua Tower Room 603 + Beijing 100000 + CN + +48-B9-77 (hex) PulseOn Oy +48B977 (base 16) PulseOn Oy + Tekniikantie 12 + ESPOO Uusimaa 02150 + FI + +70-71-B3 (hex) Brain Corporation +7071B3 (base 16) Brain Corporation + 5665 Morehouse Dr. + San Diego CA 92121 + US + +64-E6-25 (hex) Woxu Wireless Co., Ltd +64E625 (base 16) Woxu Wireless Co., Ltd + B103 Building1 No.6 Changjianghoujie + Nanjing 210000 + US + +10-B7-13 (hex) Private +10B713 (base 16) Private + +10-0E-7E (hex) Juniper Networks +100E7E (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +20-89-86 (hex) zte corporation +208986 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +44-C5-6F (hex) NGN Easy Satfinder (Tianjin) Electronic Co., Ltd +44C56F (base 16) NGN Easy Satfinder (Tianjin) Electronic Co., Ltd + A4, Sifang Hi-tech Building, Nankai Hi-tech Industry Area, Ya'an Road, Nankai District + Tianjin 300113 + US + +B8-98-F7 (hex) Gionee Communication Equipment Co,Ltd.ShenZhen +B898F7 (base 16) Gionee Communication Equipment Co,Ltd.ShenZhen + 21/F Times Technology Building, 7028 Shennan Road, + Shenzhen Guangdong 518040 + CN + +84-83-36 (hex) Newrun +848336 (base 16) Newrun + #803 IT Convergence Industry Bldg., Kyungpook National Univ. + Daegu N/A 702-010 + KR + +18-20-12 (hex) Aztech Associates Inc. +182012 (base 16) Aztech Associates Inc. + 805 Bayridge Dr. + Kingston Ontario K7P1T5 + CA + +B8-26-6C (hex) ANOV France +B8266C (base 16) ANOV France + Chemin de Baillot + Montauban Tarn & Garonne 82000 + FR + +3C-30-0C (hex) Dewar Electronics Pty Ltd +3C300C (base 16) Dewar Electronics Pty Ltd + 32 Taylors Road + Croydon Victoria 3136 + AU + +98-FF-D0 (hex) Lenovo Mobile Communication Technology Ltd. +98FFD0 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999,Qishan North 2nd Road + Xiamen Fujian 361006 + CN + +A8-75-E2 (hex) Aventura Technologies, Inc. +A875E2 (base 16) Aventura Technologies, Inc. + 48 Mall Drive + Commack NY 11725 + US + +B8-7A-C9 (hex) Siemens Ltd. +B87AC9 (base 16) Siemens Ltd. + 885 Mountain Hwy + Bayswater Victoria 3153 + AU + +F0-61-30 (hex) Advantage Pharmacy Services, LLC +F06130 (base 16) Advantage Pharmacy Services, LLC + PO Box 7 + Madison MO 39130-0007 + US + +6C-3C-53 (hex) SoundHawk Corp +6C3C53 (base 16) SoundHawk Corp + 20380 Town Center Lane + Cupertino Ca 95014 + US + +08-40-27 (hex) Gridstore Inc. +084027 (base 16) Gridstore Inc. + 1975 Landings Dr. + Mountain View CA 94043 + US + +38-BF-2F (hex) Espec Corp. +38BF2F (base 16) Espec Corp. + 5-2-5 Kanokodai Minamimachi + Kobe City Hyogo 561-1514 + JP + +44-C4-A9 (hex) Opticom Communication, LLC +44C4A9 (base 16) Opticom Communication, LLC + 1050 Connecticut Avenue, NW + Washington DC 20036 + US + +C4-82-4E (hex) Changzhou Uchip Electronics Co., LTD. +C4824E (base 16) Changzhou Uchip Electronics Co., LTD. + Room1801~1802, + Shanghai 201206 + CN + +A4-77-60 (hex) Nokia Corporation +A47760 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +C8-56-63 (hex) Sunflex Europe GmbH +C85663 (base 16) Sunflex Europe GmbH + Konrad-Zuse-Str. 13 + Schwerte NRW 58239 + DE + +88-FE-D6 (hex) ShangHai WangYong Software Co., Ltd. +88FED6 (base 16) ShangHai WangYong Software Co., Ltd. + Shanghai Pudong Zhangjiang Hi-Tech Park, + Pudong Software Park 22301-283 ShangHai 201203 + CN + +7C-72-E4 (hex) Unikey Technologies +7C72E4 (base 16) Unikey Technologies + 2250 Lee Rd + Winter Park FL 32789 + US + +7C-20-48 (hex) KoamTac +7C2048 (base 16) KoamTac + 116 Village Boulevard + Princeton New Jersey 08540 + US + +8C-B7-F7 (hex) Shenzhen UniStrong Science & Technology Co., Ltd +8CB7F7 (base 16) Shenzhen UniStrong Science & Technology Co., Ltd + 17/F, Global Digital Bldg, Hi-tech Park + Shen zhen Guang dong 518000 + CN + +38-B7-4D (hex) Fijowave Limited +38B74D (base 16) Fijowave Limited + Synergy Centre + Dublin 24 + IE + +18-0C-14 (hex) iSonea Limited +180C14 (base 16) iSonea Limited + 125 South Tremont Street + Oceanside CA 92054 + US + +9C-A9-E4 (hex) zte corporation +9CA9E4 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +90-F3-B7 (hex) Kirisun Communications Co., Ltd. +90F3B7 (base 16) Kirisun Communications Co., Ltd. + 3-6Flrs, ROBETA Building, 1 QiMin Road, Songping Shan Area, Science & Industry Park, Nanshan District + Shenzhen GuangDong 518057 + US + +C4-E9-2F (hex) AB Sciex +C4E92F (base 16) AB Sciex + 71 Four Valley Drive + Concord Ontario L4K 4V8 + US + +A8-8D-7B (hex) SunDroid Global limited. +A88D7B (base 16) SunDroid Global limited. + Room 1305B, Fiyta Science Building, + Shenzhen Guang Dong 518057 + CN + +3C-F7-48 (hex) Shenzhen Linsn Technology Development Co.,Ltd +3CF748 (base 16) Shenzhen Linsn Technology Development Co.,Ltd + Floor 4,Block 7,Zone 2,Baiwangxin Industrial Park + Shenzhen Guangdong 518055 + CN + +B0-79-08 (hex) Cummings Engineering +B07908 (base 16) Cummings Engineering + 145 S. 79th St., Ste. 26 + Chandler AZ 85226 + US + +E4-77-23 (hex) zte corporation +E47723 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +1C-63-B7 (hex) OpenProducts 237 AB +1C63B7 (base 16) OpenProducts 237 AB + Barsebäcksvägen 27 + Löddeköpinge 24630 + SE + +B4-52-7E (hex) Sony Mobile Communications Inc +B4527E (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +94-B9-B4 (hex) Aptos Technology +94B9B4 (base 16) Aptos Technology + 5F., No.65, Guangfu N. Rd., Zhongxing Vil., + Hsinchu 303 + TW + +6C-15-F9 (hex) Nautronix Limited +6C15F9 (base 16) Nautronix Limited + Blackwood House + Aberdeen AB10 6XU + GB + +18-AA-45 (hex) Fon Technology +18AA45 (base 16) Fon Technology + C/Quintanavides, 15 Edificio 2 Planta 1 + + ES + +90-20-83 (hex) General Engine Management Systems Ltd. +902083 (base 16) General Engine Management Systems Ltd. + GEMS + Egham Surrey TW208RN + GB + +14-B1-26 (hex) Industrial Software Co +14B126 (base 16) Industrial Software Co + 85, Aleksandyr Malinov Blvd. Office 6 + Sofia 1715 + BG + +D8-50-E6 (hex) ASUSTek COMPUTER INC. +D850E6 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +DC-3E-F8 (hex) Nokia Corporation +DC3EF8 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +A4-9F-89 (hex) Shanghai Rui Rui Communication Technology Co.Ltd. +A49F89 (base 16) Shanghai Rui Rui Communication Technology Co.Ltd. + Room 1130,Building No.1 + ShangHai 201199 + CN + +70-60-DE (hex) LaVision GmbH +7060DE (base 16) LaVision GmbH + Anna-Vandenhoeck-Ring 19 + Goettingen Niedersachsen 37081 + DE + +50-2E-5C (hex) HTC Corporation +502E5C (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +FC-FE-77 (hex) Hitachi Reftechno, Inc. +FCFE77 (base 16) Hitachi Reftechno, Inc. + 709-2 Tomita + Tochigi-shi Tochigi-ken 329-4404 + JP + +70-53-3F (hex) Alfa Instrumentos Eletronicos Ltda. +70533F (base 16) Alfa Instrumentos Eletronicos Ltda. + Rua Coronel Mario de Azevedo, 138 + Sao Paulo SP 02710-020 + BR + +40-7A-80 (hex) Nokia Corporation +407A80 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +64-42-14 (hex) Swisscom Energy Solutions AG +644214 (base 16) Swisscom Energy Solutions AG + Solothurnerstrasse 19 + Olten 4600 + CH + +0C-A6-94 (hex) Sunitec Enterprise Co.,Ltd +0CA694 (base 16) Sunitec Enterprise Co.,Ltd + 3F.,No.98-1,Mincyuan Rd.Sindian City + Taipei County 231 231141 + CN + +18-44-62 (hex) Riava Networks, Inc. +184462 (base 16) Riava Networks, Inc. + Kato Bldg. 1F, 6-12-4 Soto-Kanda + Chiyoda-ku Tokyo 1010021 + JP + +C0-35-80 (hex) A&R TECH +C03580 (base 16) A&R TECH + Marksteinergasse 13 + Vienna 1210 + AT + +D0-8A-55 (hex) Skullcandy +D08A55 (base 16) Skullcandy + 1441 Ute blvd. + Park City Utah 84098 + US + +34-4F-3F (hex) IO-Power Technology Co., Ltd. +344F3F (base 16) IO-Power Technology Co., Ltd. + 1F., No.100, + Hsinchu City 30055 + TW + +14-60-80 (hex) zte corporation +146080 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +9C-BB-98 (hex) Shen Zhen RND Electronic Co.,LTD +9CBB98 (base 16) Shen Zhen RND Electronic Co.,LTD + G315,Hua Chuang Da business Certer + Shen Zhen Guang Dong 518000 + CN + +50-C2-71 (hex) SECURETECH INC +50C271 (base 16) SECURETECH INC + #304, 799 Kwanyang-dong, Dongan-gu, + Anyang-ci Gyunggi-do 431-767 + KR + +CC-72-0F (hex) Viscount Systems Inc. +CC720F (base 16) Viscount Systems Inc. + 4585 Tillicum Street + Burnaby British Columbia V5J 5K9 + CA + +74-2B-62 (hex) FUJITSU LIMITED +742B62 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +64-3F-5F (hex) Exablaze +643F5F (base 16) Exablaze + Level 6 + Sydney NSW 2000 + AU + +8C-2F-39 (hex) IBA Dosimetry GmbH +8C2F39 (base 16) IBA Dosimetry GmbH + Bahnhofstrasse 5 + Schwarzenbruck 90592 + DE + +C0-A0-BB (hex) D-Link International +C0A0BB (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +2C-CD-69 (hex) Aqavi.com +2CCD69 (base 16) Aqavi.com + 3 Riverway + Houston TX 77056 + US + +F4-5F-69 (hex) Matsufu Electronics distribution Company +F45F69 (base 16) Matsufu Electronics distribution Company + Suites 1601~3, Kinwick Centre, 32 Hollywood Road, Hong Kong + Hong Kong + HK + +28-A1-EB (hex) ETEK TECHNOLOGY (SHENZHEN) CO.,LTD +28A1EB (base 16) ETEK TECHNOLOGY (SHENZHEN) CO.,LTD + A505-506、A509 Room,A5 Floor, Academy Of International Technology Innovation, Keji Nan 10th Road, Hi-Tech Industrial Park, Shenzhen, P.R.C. + SHENZHEN GUANGDONG 518057 + CN + +B8-F8-28 (hex) Changshu Gaoshida Optoelectronic Technology Co. Ltd. +B8F828 (base 16) Changshu Gaoshida Optoelectronic Technology Co. Ltd. + Baimao Industrail Park Changshu Jiangsu + Changshu Jiangsu 215500 + CN + +3C-1A-57 (hex) Cardiopulmonary Corp +3C1A57 (base 16) Cardiopulmonary Corp + 200 Cascade Blvd + Milford CT 06460 + US + +54-1B-5D (hex) Techno-Innov +541B5D (base 16) Techno-Innov + 35 rue du champ Blanc + Meyzieu Rhône 69330 + FR + +9C-E7-BD (hex) Winduskorea co., Ltd +9CE7BD (base 16) Winduskorea co., Ltd + RM313, Seoul-Garden Bldg, + Seoul 152-828 + KR + +38-42-A6 (hex) Ingenieurbuero Stahlkopf +3842A6 (base 16) Ingenieurbuero Stahlkopf + Ingenieurbuero Stahlkopf + Glockengießerweg 2 Bielefeld 33659 + DE + +2C-55-3C (hex) Gainspeed, Inc. +2C553C (base 16) Gainspeed, Inc. + 295 Santa Ana Court + Sunnyvale CA 94085 + US + +24-80-00 (hex) Westcontrol AS +248000 (base 16) Westcontrol AS + Breivikvg 7 + Joerpeland - 4100 + US + +1C-4B-B9 (hex) SMG ENTERPRISE, LLC +1C4BB9 (base 16) SMG ENTERPRISE, LLC + 865 LOVE ST + ELK GROVE VILLAGE IL 60007 + US + +34-61-78 (hex) The Boeing Company +346178 (base 16) The Boeing Company + 325 James S. McDonnell Blvd + Hazelwood MO 63042-2513 + US + +14-46-E4 (hex) AVISTEL +1446E4 (base 16) AVISTEL + 15 rue Auguste Bartholdi + Carrieres sur Seine 78420 + FR + +D0-95-C7 (hex) Pantech Co., Ltd. +D095C7 (base 16) Pantech Co., Ltd. + 110-1 Ongjeong-Ri, Tongjin-Eup + Gimpo-Si Gyounggi-Do 415-865 + KR + +D0-2C-45 (hex) littleBits Electronics, Inc. +D02C45 (base 16) littleBits Electronics, Inc. + 60 E. 11th Street + New York NY 10003 + US + +04-4F-8B (hex) Adapteva, Inc. +044F8B (base 16) Adapteva, Inc. + 1666 Massachusetts Ave + Lexington MA 02420 + US + +B4-A8-2B (hex) Histar Digital Electronics Co., Ltd. +B4A82B (base 16) Histar Digital Electronics Co., Ltd. + Room 616,Block A, + Shenzhen Baoan 518133 + CN + +28-4D-92 (hex) Luminator +284D92 (base 16) Luminator + 900 Klein Road + Plano Texas 75074 + US + +54-FB-58 (hex) WISEWARE, Lda +54FB58 (base 16) WISEWARE, Lda + Centro Social e Administrativo da ZIV + Zona Industrial de Vagos Portugal 3840-385 + PT + +94-0B-D5 (hex) Himax Technologies, Inc +940BD5 (base 16) Himax Technologies, Inc + No.26, Zilian Rd., Xinshi Dist. + Tainan City 741 + TW + +E0-D1-E6 (hex) Aliph dba Jawbone +E0D1E6 (base 16) Aliph dba Jawbone + 99 Rhode Island Street + San Francisco California 94103 + US + +D8-2D-9B (hex) Shenzhen G.Credit Communication Technology Co., Ltd +D82D9B (base 16) Shenzhen G.Credit Communication Technology Co., Ltd + 4/F, Suite A, XinNengYuan Building, 2239 Nanhai Rd., Nanshan Dist., Shenzhen, Guangdong,China + Shenzhen Guangdong 518054 + CN + +70-9B-FC (hex) Bryton Inc. +709BFC (base 16) Bryton Inc. + 6F., No. 100, Zhouzi St., Neihu Dist. + Taipei City 11493 + US + +AC-E4-2E (hex) SK hynix +ACE42E (base 16) SK hynix + SK u-Tower, 25-1, Jeongja-dong, Bundang-gu + Seongnam-si Gyeonggi-do 463-844 + KR + +78-FE-41 (hex) Socus networks +78FE41 (base 16) Socus networks + 2F.-2, No.215, Sec. 2, Chengde Rd., Datong Dist., + Taipei City 103 + TW + +20-57-21 (hex) Salix Technology CO., Ltd. +205721 (base 16) Salix Technology CO., Ltd. + 5F., No. 16, Lane 77, Hsing Ai Road + Taipei 114 + TW + +88-36-12 (hex) SRC Computers, LLC +883612 (base 16) SRC Computers, LLC + 4240 N. Nevada Avenue + Colorado Springs CO 80907 + US + +08-35-71 (hex) CASwell INC. +083571 (base 16) CASwell INC. + 8F,No.242,Bo-Ai St., Shu-Lin Dist.,New Taipei City ,Taiwan. + New Taipei City Taiwan 23845 + TW + +98-76-B6 (hex) Adafruit +9876B6 (base 16) Adafruit + 150 Varick st + New York NY 10013 + US + +50-3C-C4 (hex) Lenovo Mobile Communication Technology Ltd. +503CC4 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999,Qishan North 2nd Road,Information&Optoelectronics Park, + Xiamen Fujian 361006 + US + +2C-7B-84 (hex) OOO Petr Telegin +2C7B84 (base 16) OOO Petr Telegin + Gagarin avenue, 37, build P1 + Nizhny Novgorod 603009 + RU + +A4-C0-C7 (hex) ShenZhen Hitom Communication Technology Co..LTD +A4C0C7 (base 16) ShenZhen Hitom Communication Technology Co..LTD + Room 110,Unit A,No.1 Chuangye Building,43# YanShan Road,Shekou Area + ShenZhen GuangDong 518052 + CN + +30-61-12 (hex) PAV GmbH +306112 (base 16) PAV GmbH + Georg-Kaindl-Straße 11 + Otterfing 83624 + DE + +78-9F-4C (hex) HOERBIGER Elektronik GmbH +789F4C (base 16) HOERBIGER Elektronik GmbH + Justinus-Kernerstr. 7 + Ammerbuch Baden-Wuerttemberg D-72119 + DE + +18-10-4E (hex) CEDINT-UPM +18104E (base 16) CEDINT-UPM + Campus de Montegancedo + Madrid + ES + +9C-14-65 (hex) Edata Elektronik San. ve Tic. A.Ş. +9C1465 (base 16) Edata Elektronik San. ve Tic. A.Ş. + Tantavi Mahallesi Menteşoğlu Cad. + İstanbul - 34764 + TR + +4C-55-CC (hex) Zentri Pty Ltd +4C55CC (base 16) Zentri Pty Ltd + Level 9, 191 Clarence St, + Sydney NSW 2000 + AU + +00-C5-DB (hex) Datatech Sistemas Digitales Avanzados SL +00C5DB (base 16) Datatech Sistemas Digitales Avanzados SL + Cardenal Herrera Oria 165 + Madrid 28034 + ES + +8C-F9-45 (hex) Power Automation pte Ltd +8CF945 (base 16) Power Automation pte Ltd + 28 Ayer Rajah Crescent + 139959 + SG + +F8-42-FB (hex) Yasuda Joho Co.,ltd. +F842FB (base 16) Yasuda Joho Co.,ltd. + 1-11-1 + Minato-ku Tokyo 105-0022 + JP + +88-73-98 (hex) K2E Tekpoint +887398 (base 16) K2E Tekpoint + 201,Winstower,278-51,Sungsoo2ga 3dong,Sungdong-gu,Seoul,S.Korea,133-123 + Seoul Sungdong-gu 133-123 + KR + +2C-92-2C (hex) Kishu Giken Kogyou Company Ltd,. +2C922C (base 16) Kishu Giken Kogyou Company Ltd,. + 466 Nunohiki + Wakayama city Wakayama prefecture 6410015 + JP + +D8-FE-E3 (hex) D-Link International +D8FEE3 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +58-F3-87 (hex) HCCP +58F387 (base 16) HCCP + Gabriel Metsulaan 4a + EINDHOVEN 5611SP + NL + +3C-97-7E (hex) IPS Technology Limited +3C977E (base 16) IPS Technology Limited + 7 Floor,E block,Dong Hai Wang Building + Shenzhen Guangodng 518000 + CN + +A4-FB-8D (hex) Hangzhou Dunchong Technology Co.Ltd +A4FB8D (base 16) Hangzhou Dunchong Technology Co.Ltd + Yitian Square 1#401A + hangzhou zhejiang 310051 + US + +F4-CD-90 (hex) Vispiron Rotec GmbH +F4CD90 (base 16) Vispiron Rotec GmbH + Frankfurter Ring 224 + München Bayern 80807 + DE + +80-6C-8B (hex) KAESER KOMPRESSOREN AG +806C8B (base 16) KAESER KOMPRESSOREN AG + Carl-Kaeser-Strasse 26 + Coburg Bavaria 96450 + DE + +04-3D-98 (hex) ChongQing QingJia Electronics CO.,LTD +043D98 (base 16) ChongQing QingJia Electronics CO.,LTD + No.1,DianCe Village JiangBei District + Chongqing city 400020 + CN + +E0-3E-4A (hex) Cavanagh Group International +E03E4A (base 16) Cavanagh Group International + 9180 Four Mile Creek Rd. + Gainesville GA 30506 + US + +04-1B-94 (hex) Host Mobility AB +041B94 (base 16) Host Mobility AB + Anders Personsgatan 12 + Gothenburg Vastra Gotaland 41664 + SE + +A0-CE-C8 (hex) CE LINK LIMITED +A0CEC8 (base 16) CE LINK LIMITED + 2/F, Building G, Licheng Tech. Ind. Zone + Shenzhen Guangdong 518104 + CN + +90-7A-28 (hex) Beijing Morncloud Information And Technology Co. Ltd. +907A28 (base 16) Beijing Morncloud Information And Technology Co. Ltd. + A#1107, XiaoYun center + Chaoyang District Beijing 100125 + CN + +10-01-CA (hex) Ashley Butterworth +1001CA (base 16) Ashley Butterworth + P.O. Box 3410 + Santa Clara CA 95055 + US + +24-6A-AB (hex) IT-IS International +246AAB (base 16) IT-IS International + 1 Wainstones Court + Middlesbrough Cleveland TS9 5JY + GB + +FC-4B-BC (hex) Sunplus Technology Co., Ltd. +FC4BBC (base 16) Sunplus Technology Co., Ltd. + No.19, Innovation First Road + Hsinchu City 300 + TW + +50-A0-BF (hex) Alba Fiber Systems Inc. +50A0BF (base 16) Alba Fiber Systems Inc. + 265 E. Merrick Rd + Valley Stream NY 11580 + US + +B8-36-D8 (hex) Videoswitch +B836D8 (base 16) Videoswitch + Uspallata 3579 + Buenos Aires Capital Federal C1437JCS + AR + +DC-6F-00 (hex) Livescribe, Inc. +DC6F00 (base 16) Livescribe, Inc. + 7677 Oakport Street + Oakland California 94621 + US + +54-E3-B0 (hex) JVL Industri Elektronik +54E3B0 (base 16) JVL Industri Elektronik + Blokken 42 + Birkeroed Sjaelland DK-3460 + DK + +80-4B-20 (hex) Ventilation Control +804B20 (base 16) Ventilation Control + Kronenstrasse 34 + Villingen-Schwenningen Baden-Wuerttemberg 78054 + DE + +28-79-94 (hex) Realplay Digital Technology(Shenzhen) Co.,Ltd +287994 (base 16) Realplay Digital Technology(Shenzhen) Co.,Ltd + 7/F,Building E,SDG Information Port ,Kefeng Rd.,Hi-tech + Shenzhen Guangdong 518057 + CN + +10-7A-86 (hex) U&U ENGINEERING INC. +107A86 (base 16) U&U ENGINEERING INC. + No.15, Gaoyang S. Rd + Taoyuan County 325-44 + TW + +40-BD-9E (hex) Physio-Control, Inc +40BD9E (base 16) Physio-Control, Inc + 11811 Willows Rd NE + Redmond WA 98052 + US + +6C-57-79 (hex) Aclima, Inc. +6C5779 (base 16) Aclima, Inc. + 10 Lombard Street + San Francisco California 94111 + US + +C0-DA-74 (hex) Hangzhou Sunyard Technology Co., Ltd. +C0DA74 (base 16) Hangzhou Sunyard Technology Co., Ltd. + No.3888 Jiangnan Ave, Binjiang District, + Hangzhou Zhejiang 310053 + CN + +18-D6-CF (hex) Kurth Electronic GmbH +18D6CF (base 16) Kurth Electronic GmbH + Mühleweg 11 + Eningen 72800 + DE + +F4-81-39 (hex) CANON INC. +F48139 (base 16) CANON INC. + 30-2 Shimomaruko 3-chome, + Ohta-ku Tokyo 146-8501 + JP + +18-36-FC (hex) Elecsys International Corporation +1836FC (base 16) Elecsys International Corporation + 846 N Mart-Way Court + Olathe KS 66061 + US + +A4-D0-94 (hex) Erwin Peters Systemtechnik GmbH +A4D094 (base 16) Erwin Peters Systemtechnik GmbH + Josef Baumann Strasse 37 + Bochum D44805 + DE + +88-23-64 (hex) Watchnet DVR Inc +882364 (base 16) Watchnet DVR Inc + Unit 5 - 351 Ferrier St. + Markham Ontario L3R 5Z2 + CA + +58-1C-BD (hex) Affinegy +581CBD (base 16) Affinegy + 1705 S. Capital of Texas Hwy. Ste 310 + Austin Texas 78746 + US + +28-4F-CE (hex) Liaoning Wontel Science and Technology Development Co.,Ltd. +284FCE (base 16) Liaoning Wontel Science and Technology Development Co.,Ltd. + A704 Floor TaiHe building + Shenyang Liaoning 110000 + CN + +04-8D-38 (hex) Netcore Technology Inc. +048D38 (base 16) Netcore Technology Inc. + 9F,B block,Tsinghua Information Guard + Shenzhen Guangdong 518057 + CN + +2C-94-64 (hex) Cincoze Co., Ltd. +2C9464 (base 16) Cincoze Co., Ltd. + 7F., No. 4 Aly. 1 Ln. 235, Baociao Rd., + New Taipei City 23145 + US + +30-65-EC (hex) Wistron (ChongQing) +3065EC (base 16) Wistron (ChongQing) + No.F08/F09,D zone,Konggang Functional Zone + ChongQing 401120 + CN + +54-2C-EA (hex) PROTECTRON +542CEA (base 16) PROTECTRON + 140 zone industriel + CASABLANCA 18600 + MA + +94-B8-C5 (hex) RuggedCom Inc. +94B8C5 (base 16) RuggedCom Inc. + 300 Applewood Crescent + Concord Ontario L4K 5C7 + CA + +DC-82-5B (hex) JANUS, spol. s r.o. +DC825B (base 16) JANUS, spol. s r.o. + Sarajevska 8 + Prague Czech Republic 12000 + CZ + +9C-A5-77 (hex) Osorno Enterprises Inc. +9CA577 (base 16) Osorno Enterprises Inc. + 976 Elgin Ave + Winnipeg MB R3E 1B4 + CA + +C0-43-01 (hex) Epec Oy +C04301 (base 16) Epec Oy + P.O. Box 194 + Seinäjoki 60101 + FI + +E0-7C-62 (hex) Whistle Labs, Inc. +E07C62 (base 16) Whistle Labs, Inc. + 251 Rhode Island Street, Suite 211 + San Francisco CA 94013 + US + +F0-7F-0C (hex) Leopold Kostal GmbH &Co. KG +F07F0C (base 16) Leopold Kostal GmbH &Co. KG + An der Bellmerei 10 + Luedenscheid NRW D-58513 + DE + +4C-62-55 (hex) SANMINA-SCI SYSTEM DE MEXICO S.A. DE C.V. +4C6255 (base 16) SANMINA-SCI SYSTEM DE MEXICO S.A. DE C.V. + Carretera Guadalajara-chapala km 15.5 #45 + TLAJOMULCO JALISCO 45640 + MX + +08-27-19 (hex) APS systems/electronic AG +082719 (base 16) APS systems/electronic AG + Neumatt 4 + Niederbuchsiten SO 4626 + CH + +50-5A-C6 (hex) GUANGDONG SUPER TELECOM CO.,LTD. +505AC6 (base 16) GUANGDONG SUPER TELECOM CO.,LTD. + 4/F,NO.1025-1027 Gaopu Rd + Guangzhou Guangdong 510663 + CN + +9C-79-AC (hex) Suntec Software(Shanghai) Co., Ltd. +9C79AC (base 16) Suntec Software(Shanghai) Co., Ltd. + 17F New Hualian Mansion + Shanghai 200020 + CN + +4C-96-14 (hex) Juniper Networks +4C9614 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +B8-63-BC (hex) ROBOTIS, Co, Ltd +B863BC (base 16) ROBOTIS, Co, Ltd + #1506 Ace high End Tower 3, 371-50 + Seoul 153-787 + KR + +98-0D-2E (hex) HTC Corporation +980D2E (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +C4-19-EC (hex) Qualisys AB +C419EC (base 16) Qualisys AB + Packhusgatan 6 + Gothenburg 41113 + SE + +60-4A-1C (hex) SUYIN Corporation +604A1C (base 16) SUYIN Corporation + No.377,Fude 1st Rd + Taipei 221 + TW + +D4-64-F7 (hex) CHENGDU USEE DIGITAL TECHNOLOGY CO., LTD +D464F7 (base 16) CHENGDU USEE DIGITAL TECHNOLOGY CO., LTD + NO.6 CHUANGYE ROAD + CHENGDU SICHUAN 610041 + CN + +74-D0-2B (hex) ASUSTek COMPUTER INC. +74D02B (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +60-1E-02 (hex) EltexAlatau +601E02 (base 16) EltexAlatau + Ibragimova 9 + Almaty Province 050032 + KZ + +E0-C6-B3 (hex) MilDef AB +E0C6B3 (base 16) MilDef AB + Box 22079 + Helsingborg Skane 25022 + SE + +64-72-D8 (hex) GooWi Technology Co.,Limited +6472D8 (base 16) GooWi Technology Co.,Limited + Unit C8.,9/F,Hongming Fatoty Building + 99 How Ming Street Kwun Tong 999077 + HK + +60-60-1F (hex) SZ DJI TECHNOLOGY CO.,LTD +60601F (base 16) SZ DJI TECHNOLOGY CO.,LTD + 6/F,HKUST SZ IER Bldg,9 Yuexing 1st Rd + shenzhen guangdong 518057 + CN + +5C-84-86 (hex) Brightsource Industries Israel LTD +5C8486 (base 16) Brightsource Industries Israel LTD + 11 Kiryat Mada st + Jerusalem 91450 + IL + +50-CD-32 (hex) NanJing Chaoran Science & Technology Co.,Ltd. +50CD32 (base 16) NanJing Chaoran Science & Technology Co.,Ltd. + Block C,Floor 5,Tianzexingwang Building + NanJing City JiangSu Province 210019 + CN + +BC-BA-E1 (hex) AREC Inc. +BCBAE1 (base 16) AREC Inc. + 3F, No.367, Sec.2, Wenhua Rd + Banqiao Dist New Taipei City 220 + TW + +18-FA-6F (hex) ISC applied systems corp +18FA6F (base 16) ISC applied systems corp + 295 Labrosse + Pointe-claire QC H9R-1A3 + CA + +A0-1C-05 (hex) NIMAX TELECOM CO.,LTD. +A01C05 (base 16) NIMAX TELECOM CO.,LTD. + 1F. NO.308-7,SEC.1,DATONG RD + NEW TAIPEI CITY 221 + TW + +60-E0-0E (hex) SHINSEI ELECTRONICS CO LTD +60E00E (base 16) SHINSEI ELECTRONICS CO LTD + 2-6-25 + Amagasaki Hyogo 660-0805 + JP + +54-54-14 (hex) Digital RF Corea, Inc +545414 (base 16) Digital RF Corea, Inc + 2 Floor, SeMin B/D, 201, Jangdari-ro + Suwon-si Gyeonggi-do 442-833 + KR + +24-EB-65 (hex) SAET I.S. S.r.l. +24EB65 (base 16) SAET I.S. S.r.l. + Via Leinì 1/B + San Maurizio C.se TO 10077 + IT + +D0-F2-7F (hex) SteadyServ Technoligies, LLC +D0F27F (base 16) SteadyServ Technoligies, LLC + 12895 Brighton Avenue + Carmel IN 46032 + US + +E8-94-F6 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +E894F6 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +18-84-10 (hex) CoreTrust Inc. +188410 (base 16) CoreTrust Inc. + 14F Saman Bldg. 945 Daechi-dong + Seoul Republic of Korea 135-280 + KR + +FC-22-9C (hex) Han Kyung I Net Co.,Ltd. +FC229C (base 16) Han Kyung I Net Co.,Ltd. + 3F,Seung Eun Bldg + Yu Seong-Gu Dae Jeon 305-335 + KR + +18-32-A2 (hex) LAON TECHNOLOGY CO., LTD. +1832A2 (base 16) LAON TECHNOLOGY CO., LTD. + #1212 HO, BIZ CENTER, SKn TECHNOPARK + SEONGNAM KYOUNGGI DO 462-721 + KR + +D4-A4-99 (hex) InView Technology Corporation +D4A499 (base 16) InView Technology Corporation + 8900 Shoal Creek Blvd + Austin TX 78757 + US + +08-48-2C (hex) Raycore Taiwan Co., LTD. +08482C (base 16) Raycore Taiwan Co., LTD. + 3F-5, No.351, Sec.2, Zongshan Rd + New Taipei city 23504 + TW + +DC-2B-CA (hex) Zera GmbH +DC2BCA (base 16) Zera GmbH + Hauptstrasse 392 + Koenigswinter NRW 53639 + DE + +94-98-A2 (hex) Shanghai LISTEN TECH.LTD +9498A2 (base 16) Shanghai LISTEN TECH.LTD + 7F,A#,NO.3699,Gonghexin Road + SHANGHAI SHANGHAI 200435 + CN + +E0-ED-C7 (hex) Shenzhen Friendcom Technology Development Co., Ltd +E0EDC7 (base 16) Shenzhen Friendcom Technology Development Co., Ltd + 6/F,17 Building, Guangqian Industrial Park, + Nanshan District, Shen Zhen CIty Guang Dong 518055 + CN + +B4-DD-15 (hex) ControlThings Oy Ab +B4DD15 (base 16) ControlThings Oy Ab + Werner Söderströmin katu 24 + Porvoo Finland 06100 + FI + +DC-1D-D4 (hex) Microstep-MIS spol. s r.o. +DC1DD4 (base 16) Microstep-MIS spol. s r.o. + Cavojskeho 1 + Bratislava 84104 + SK + +FC-DD-55 (hex) Shenzhen WeWins wireless Co.,Ltd +FCDD55 (base 16) Shenzhen WeWins wireless Co.,Ltd + 6/F.,B Wing,Yuehai Piaza,Nanhai Road + Shenzhen Guangdong 518000 + CN + +B0-17-43 (hex) EDISON GLOBAL CIRCUITS LLC +B01743 (base 16) EDISON GLOBAL CIRCUITS LLC + 1475 Sawdust Rd + Spring TX 77380-2974 + US + +D0-BE-2C (hex) CNSLink Co., Ltd. +D0BE2C (base 16) CNSLink Co., Ltd. + room 807, Jungang Induspia 5 + Seongnam Gyeonggi 462-807 + US + +40-51-6C (hex) Grandex International Corporation +40516C (base 16) Grandex International Corporation + 4F, 525 Chung Cheng Road + Hsin Tien Dist. New Taipei City 231 + TW + +C0-88-5B (hex) SnD Tech Co., Ltd. +C0885B (base 16) SnD Tech Co., Ltd. + 1140-4 Triple Tower C-406 + Bucheon Si Gyeonggi-Do 420-852 + KR + +3C-FB-96 (hex) Emcraft Systems LLC +3CFB96 (base 16) Emcraft Systems LLC + 2191 S. El Camino Real + Oceanside CA 92054 + US + +84-62-23 (hex) Shenzhen Coship Electronics Co., Ltd. +846223 (base 16) Shenzhen Coship Electronics Co., Ltd. + Rainbow Bldg., North, Hi-Tech Industrial Park + Shenzhen Guangdong 518057 + CN + +1C-FA-68 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +1CFA68 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +08-1F-3F (hex) WondaLink Inc. +081F3F (base 16) WondaLink Inc. + 2F, No. 23, R&D Road 2 + Hsinchu 300 + TW + +18-53-E0 (hex) Hanyang Digitech Co.Ltd +1853E0 (base 16) Hanyang Digitech Co.Ltd + 103, BANWOL-DONG, HWASEONG-SI, KYUNGGI-DO, KOREA + HWASEONG KYUNGGI 445-330 + KR + +00-C1-4F (hex) DDL Co,.ltd. +00C14F (base 16) DDL Co,.ltd. + 6F AFT BLDG. + SAPPORO HOKKAIDO 060-0035 + JP + +2C-26-C5 (hex) zte corporation +2C26C5 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +10-5F-06 (hex) Actiontec Electronics, Inc +105F06 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +08-79-99 (hex) AIM GmbH +087999 (base 16) AIM GmbH + Sasbacherstraße 2 + Freiburg BW 79111 + US + +C0-11-A6 (hex) Fort-Telecom ltd. +C011A6 (base 16) Fort-Telecom ltd. + Hrustalnaya 8a + Perm 614107 + RU + +C0-4A-00 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +C04A00 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +04-5F-A7 (hex) Shenzhen Yichen Technology Development Co.,LTD +045FA7 (base 16) Shenzhen Yichen Technology Development Co.,LTD + 5/F Honghualing 2nd Industry Zone,Xili Town + Shenzhen Guangdong 518055 + CN + +94-C9-62 (hex) Teseq AG +94C962 (base 16) Teseq AG + Nordstrasse 11F + Luterbach Solothurn 4542 + CH + +DC-2A-14 (hex) Shanghai Longjing Technology Co. +DC2A14 (base 16) Shanghai Longjing Technology Co. + 689 Chundong Road, Minhang District + Shanghai 201108 + CN + +68-86-E7 (hex) Orbotix, Inc. +6886E7 (base 16) Orbotix, Inc. + 1155 Canyon Blvd. + Boulder CO 80302 + US + +C0-5E-6F (hex) V. Stonkaus firma Kodinis Raktas +C05E6F (base 16) V. Stonkaus firma Kodinis Raktas + Ateities 10 + Vilnius 08303 + LT + +C0-B8-B1 (hex) BitBox Ltd +C0B8B1 (base 16) BitBox Ltd + Whitney Road + Basingstoke Hampshire RG24 8NS + GB + +F8-2E-DB (hex) RTW GmbH & Co. KG +F82EDB (base 16) RTW GmbH & Co. KG + Am Wassermann 25 + Cologne NRW 50829 + DE + +80-8B-5C (hex) Shenzhen Runhuicheng Technology Co., Ltd +808B5C (base 16) Shenzhen Runhuicheng Technology Co., Ltd + 315.3rd Floor Taoyuan Commercial Building A2 ridgepole Guang Qian Industrial Estate XiLi + Shenzhen Guangdong 518052 + CN + +D8-19-CE (hex) Telesquare +D819CE (base 16) Telesquare + 670, Sampyeong-dong, Bundang-gu + Seongnam-si Gyeonggi-do 463-400 + KR + +E0-CE-C3 (hex) ASKEY COMPUTER CORP +E0CEC3 (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +38-F5-97 (hex) home2net GmbH +38F597 (base 16) home2net GmbH + Im Haslet 42 + Woerth/Donau Bayern 93086 + DE + +80-7B-1E (hex) Corsair Memory, Inc. +807B1E (base 16) Corsair Memory, Inc. + 47100 Bayside Parkway + Fremont CA 94538 + US + +B4-AB-2C (hex) MtM Technology Corporation +B4AB2C (base 16) MtM Technology Corporation + 12F, No. 186, Fuxing Road + Taoyuan City Taoyuan County 33066 + TW + +74-37-2F (hex) Tongfang Shenzhen Cloudcomputing Technology Co.,Ltd +74372F (base 16) Tongfang Shenzhen Cloudcomputing Technology Co.,Ltd + 4,1 Building,FinanceBase,NO.8KeFaRoad,Science park + ShenZhen City GuangDong 518057 + US + +F0-21-9D (hex) Cal-Comp Electronics & Communications Company Ltd. +F0219D (base 16) Cal-Comp Electronics & Communications Company Ltd. + No.147, Sec. 3, Beishen Rd + Shenkeng Dist New Taipei City --- + TW + +18-17-25 (hex) Cameo Communications, Inc. +181725 (base 16) Cameo Communications, Inc. + No. 276, Sinhu 1st Rd., Neihu District, + Taipei 114 + TW + +84-62-A6 (hex) EuroCB (Phils), Inc. +8462A6 (base 16) EuroCB (Phils), Inc. + SFB No.2 + Lapulapu CIty Cebu 6015 + PH + +E4-F3-65 (hex) Time-O-Matic, Inc. +E4F365 (base 16) Time-O-Matic, Inc. + 1015 Maple St. + Danville IL 61832 + US + +DC-C0-DB (hex) Shenzhen Kaiboer Technology Co., Ltd. +DCC0DB (base 16) Shenzhen Kaiboer Technology Co., Ltd. + 4/F, No. 11 Bldg., Yusheng Industrial Park, No. 467, Xixiang Sec., + Shenzhen Guangdong 518126 + CN + +AC-5D-10 (hex) Pace Americas +AC5D10 (base 16) Pace Americas + 1764 Automation Parkway + San Jose Ca 95131 + US + +FC-62-6E (hex) Beijing MDC Telecom +FC626E (base 16) Beijing MDC Telecom + 26 Xiaoyun Road #B2808, Chaoyang + Beijing 100016 + CN + +84-C8-B1 (hex) Incognito Software Systems Inc. +84C8B1 (base 16) Incognito Software Systems Inc. + #500 - 375 Water St + Vancouver BC - British Columbia V6B 5C6 + CA + +E8-A3-64 (hex) Signal Path International / Peachtree Audio +E8A364 (base 16) Signal Path International / Peachtree Audio + 2045 120th Ave NE + Bellevue Washington 98005 + US + +BC-51-FE (hex) Swann communications Pty Ltd +BC51FE (base 16) Swann communications Pty Ltd + Unit 13 + Port Melbourne Victoria 3207 + AU + +88-F4-90 (hex) Jetmobile Pte Ltd +88F490 (base 16) Jetmobile Pte Ltd + 541 Orchard Road + Singapore 238881 + SG + +1C-91-79 (hex) Integrated System Technologies Ltd +1C9179 (base 16) Integrated System Technologies Ltd + Suite 5 Birch House + Aldridge West Midlands WS9 0NF + GB + +A0-BA-B8 (hex) Pixon Imaging +A0BAB8 (base 16) Pixon Imaging + 9530 Towne Center Dr. + San Diego CA 92121 + US + +74-E4-24 (hex) APISTE CORPORATION +74E424 (base 16) APISTE CORPORATION + 1-4-16 Dojimahama, Kita-ku + Osaka Japan 530-0004 + JP + +24-11-D0 (hex) Chongqing Ehs Science and Technology Development Co.,Ltd. +2411D0 (base 16) Chongqing Ehs Science and Technology Development Co.,Ltd. + Saturn Business Center C3-15-7,Starlight No.5 Street + Chongqing 400060 + CN + +B4-61-FF (hex) Lumigon A/S +B461FF (base 16) Lumigon A/S + Baadehavnsgade 2A + Copenhagen SV Denmark 2450 + DK + +A0-A1-30 (hex) DLI Taiwan Branch office +A0A130 (base 16) DLI Taiwan Branch office + No.18-5, No.738. Zhong Zheng Rd + Taipei New City 23511 + TW + +30-21-5B (hex) Shenzhen Ostar Display Electronic Co.,Ltd +30215B (base 16) Shenzhen Ostar Display Electronic Co.,Ltd + Room218, CASTD Incubator Building, High-tech South Street No.1, + Shenzhen Guangdong 518057 + CN + +34-FA-40 (hex) Guangzhou Robustel Technologies Co., Limited +34FA40 (base 16) Guangzhou Robustel Technologies Co., Limited + B301, Tianchang Shangmaoyuan + Guangzhou Guangdong 510660 + CN + +1C-5A-6B (hex) Philips Electronics Nederland BV +1C5A6B (base 16) Philips Electronics Nederland BV + PO BOX 80045 + Eindhoven 5600 JZ + NL + +A8-75-D6 (hex) FreeTek International Co., Ltd. +A875D6 (base 16) FreeTek International Co., Ltd. + Unit D, 15/F, Tai Ping Ind.Ctr., Blk 2, 55 Ting Kok Rd., + Hong Kong Hong KOng 1111 + HK + +EC-E9-15 (hex) STI Ltd +ECE915 (base 16) STI Ltd + Osborn Way + Hook Hampshire RG27 9HX + GB + +80-D7-33 (hex) QSR Automations, Inc. +80D733 (base 16) QSR Automations, Inc. + 2301 Stanley Gault Pkwy + Louisville KY 40223 + US + +30-3D-08 (hex) GLINTT TES S.A. +303D08 (base 16) GLINTT TES S.A. + Beloura Office Park, Ed.10 + Sintra 2710-693 + PT + +A8-1F-AF (hex) KRYPTON POLSKA +A81FAF (base 16) KRYPTON POLSKA + AL. JEROZOLIMSKIE 131 + WARSZAWA MAZOWIECKIE 02-304 + PL + +30-D3-57 (hex) Logosol, Inc. +30D357 (base 16) Logosol, Inc. + 5041 ROBERT J. MATHEWS PARKWAY + EL DORADO HILLS California 95762 + US + +BC-39-A6 (hex) CSUN System Technology Co.,LTD +BC39A6 (base 16) CSUN System Technology Co.,LTD + 4-16-22,Chiyogaoka + Kawasaki-shi Kanagawa Ken 2150005 + JP + +EC-B5-41 (hex) SHINANO E and E Co.Ltd. +ECB541 (base 16) SHINANO E and E Co.Ltd. + 5511-6 Wada + Matsumoto City Nagano 390-1242 + JP + +D4-10-CF (hex) Huanshun Network Science and Technology Co., Ltd. +D410CF (base 16) Huanshun Network Science and Technology Co., Ltd. + No. 218-1, North Binjiang Road + yuyao zhejiang 315400 + CN + +6C-B3-11 (hex) Shenzhen Lianrui Electronics Co.,Ltd +6CB311 (base 16) Shenzhen Lianrui Electronics Co.,Ltd + Block C4 XinTang Industrial Park + Shenzhen Guangdong 518000 + CN + +10-A7-43 (hex) SK Mtek Limited +10A743 (base 16) SK Mtek Limited + Flat/Rm 1808, 18F Tower II, Admirality + Hong Kong + HK + +54-7F-A8 (hex) TELCO systems, s.r.o. +547FA8 (base 16) TELCO systems, s.r.o. + Zvolenska cesta 20 + Banska Bystrica Slovak republic 974 05 + SK + +54-74-E6 (hex) Webtech Wireless +5474E6 (base 16) Webtech Wireless + 215-4299 Canada Way + Burnaby BC V5G 1H3 + CA + +C4-6D-F1 (hex) DataGravity +C46DF1 (base 16) DataGravity + 10 Tara Blvd + Nashua NH 03062 + US + +30-44-49 (hex) PLATH GmbH +304449 (base 16) PLATH GmbH + Gotenstrasse 18 + Hamburg 20097 + DE + +94-FD-2E (hex) Shanghai Uniscope Technologies Co.,Ltd +94FD2E (base 16) Shanghai Uniscope Technologies Co.,Ltd + 5th Floor, Building 10, + Shanghai 200233 + CN + +E4-C1-46 (hex) Objetivos y Servicios de Valor A +E4C146 (base 16) Objetivos y Servicios de Valor A + C/ Monte Esquinza, 28, 1D + Madrid 28017 + ES + +D4-00-57 (hex) MC Technologies GmbH +D40057 (base 16) MC Technologies GmbH + Kabelkamp 2 + Hannover Germany 30179 + DE + +5C-E0-F6 (hex) NIC.br- Nucleo de Informacao e Coordenacao do Ponto BR +5CE0F6 (base 16) NIC.br- Nucleo de Informacao e Coordenacao do Ponto BR + Av. das Nacoes Unidas, 11541, 7o andar + São Paulo SP 04578-000 + BR + +C8-3D-97 (hex) Nokia Corporation +C83D97 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +0C-F3-61 (hex) Java Information +0CF361 (base 16) Java Information + Woolim Lions Valley 2nd B-1305 + Seongnam-Si Gyounggi-Do 462-120 + KR + +60-0F-77 (hex) SilverPlus, Inc +600F77 (base 16) SilverPlus, Inc + 18 Technology Dr, #143 + Irvine CA 92618 + US + +B0-35-8D (hex) Nokia Corporation +B0358D (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +F8-E4-FB (hex) Actiontec Electronics, Inc +F8E4FB (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +8C-4A-EE (hex) GIGA TMS INC +8C4AEE (base 16) GIGA TMS INC + 9F-2 NO.31 Lane 169 Kang-ning Street, Hsi-Chih + Taipei County 221 221 + TW + +34-C9-9D (hex) EIDOLON COMMUNICATIONS TECHNOLOGY CO. LTD. +34C99D (base 16) EIDOLON COMMUNICATIONS TECHNOLOGY CO. LTD. + Room 603, 6/F., Wanchai Central Building, 89 Lockhart Road, Wanchai, + + HK + +AC-E6-4B (hex) Shenzhen Baojia Battery Technology Co., Ltd. +ACE64B (base 16) Shenzhen Baojia Battery Technology Co., Ltd. + Block A, Tongfuyu Industrial Zone + Shenzhen Guangdong 518013 + CN + +78-9F-87 (hex) Siemens AG I IA PP PRM +789F87 (base 16) Siemens AG I IA PP PRM + Gleiwitzer Strasse 555 + Nuremberg Bavaria 90475 + DE + +08-E5-DA (hex) NANJING FUJITSU COMPUTER PRODUCTS CO.,LTD. +08E5DA (base 16) NANJING FUJITSU COMPUTER PRODUCTS CO.,LTD. + NO.1,XIANXIN MID-ROAD + NANJING JIANGSU 210046 + CN + +58-84-E4 (hex) IP500 Alliance e.V. +5884E4 (base 16) IP500 Alliance e.V. + Scharnhorststraße 16 + Berlin 10115 + DE + +04-4B-FF (hex) GuangZhou Hedy Digital Technology Co., Ltd +044BFF (base 16) GuangZhou Hedy Digital Technology Co., Ltd + B 701, Gaoke Building, TianHe Bei Road, + GuangZhou GuangDong 510630 + CN + +E8-71-8D (hex) Elsys Equipamentos Eletronicos Ltda +E8718D (base 16) Elsys Equipamentos Eletronicos Ltda + Av. Torquato Tapajós, n. 1052 - B. Flores + Manaus Amazonas 69.058-830 + BR + +D0-73-8E (hex) DONG OH PRECISION CO., LTD. +D0738E (base 16) DONG OH PRECISION CO., LTD. + #282 SHINGAL-RI, JICSAN-EUP + CHEONAN-SI CHUNGCHEONGNAM-DO 331-814 + KR + +64-C9-44 (hex) LARK Technologies, Inc +64C944 (base 16) LARK Technologies, Inc + 2570 W El Camino Real + Mountain View CA 94040 + US + +0C-93-FB (hex) BNS Solutions +0C93FB (base 16) BNS Solutions + PO Box 508 + Walpole MA 02081 + US + +E4-4F-5F (hex) EDS Elektronik Destek San.Tic.Ltd.Sti +E44F5F (base 16) EDS Elektronik Destek San.Tic.Ltd.Sti + Meclis Mah. Hayran Sok. No:4 + istanbul 34785 + TR + +E8-6D-54 (hex) Digit Mobile Inc +E86D54 (base 16) Digit Mobile Inc + 5F.,No.550,Ruiguang Rd., Neihu Dist.,Taipei City 11492, Taiwan + Taipei Taiwan 11492 + TW + +90-B1-1C (hex) Dell Inc. +90B11C (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-5D-03 (hex) Xilinx, Inc +005D03 (base 16) Xilinx, Inc + 2100 Logic drive + San Jose CA 95124 + US + +80-2F-DE (hex) Zurich Instruments AG +802FDE (base 16) Zurich Instruments AG + Technoparkstrasse 1 + Zurich 8005 + CH + +5C-38-E0 (hex) Shanghai Super Electronics Technology Co.,LTD +5C38E0 (base 16) Shanghai Super Electronics Technology Co.,LTD + 1/F Building A 39 Hongcao Road + Shanghai 200233 + CN + +08-AF-78 (hex) Totus Solutions, Inc. +08AF78 (base 16) Totus Solutions, Inc. + 1505 Wallace Drive, Suite 102 + Carrollton TX 75006 + US + +C8-C7-91 (hex) Zero1.tv GmbH +C8C791 (base 16) Zero1.tv GmbH + Heinrich-Roller-Str. 16 B + Berlin 10405 + DE + +EC-D9-25 (hex) RAMI +ECD925 (base 16) RAMI + 7 RUE RAOUL FOLLEREAU + BUSSY ST GEORGES 77600 + FR + +1C-94-92 (hex) RUAG Schweiz AG +1C9492 (base 16) RUAG Schweiz AG + RUAG Defence + Hombrechtikon ZH 8634 + CH + +B8-89-CA (hex) ILJIN ELECTRIC Co., Ltd. +B889CA (base 16) ILJIN ELECTRIC Co., Ltd. + 112-83, Annyeong-dong + Hwaseong Gyeonggi-do 445-380 + KR + +64-F5-0E (hex) Kinion Technology Company Limited +64F50E (base 16) Kinion Technology Company Limited + ng Kon107A, 1/F, Enterprise Place, + + HK + +D0-4C-C1 (hex) SINTRONES Technology Corp. +D04CC1 (base 16) SINTRONES Technology Corp. + 14F.-3, No.736, Zhongzheng Rd., Zhonghe Dist., New Taipei City 235, Taiwan (R.O.C.) + Taipei N/A 235 + TW + +50-3F-56 (hex) Syncmold Enterprise Corp +503F56 (base 16) Syncmold Enterprise Corp + 9F., No.168, Jiankang Rd., Zhonghe Dist. + Xinbei City 235 + US + +8C-EE-C6 (hex) Precepscion Pty. Ltd. +8CEEC6 (base 16) Precepscion Pty. Ltd. + Level 10 + Melbourne Victoria 3000 + AU + +10-12-48 (hex) ITG, Inc. +101248 (base 16) ITG, Inc. + YASUHARA BLDG 302, 1-42-6, ITABASHI, + ITABASHI-KU TOKYO 173-0004 + US + +18-48-D8 (hex) Fastback Networks +1848D8 (base 16) Fastback Networks + 2480 N 1st Street + San Jose California 95131 + US + +F0-D3-E7 (hex) Sensometrix SA +F0D3E7 (base 16) Sensometrix SA + Rue Albert Richard 2 + Geneva GE 1201 + CH + +B0-12-66 (hex) Futaba-Kikaku +B01266 (base 16) Futaba-Kikaku + 2-17-20-302 Yanaka + Taito-ku Tokyo 110-0001 + JP + +7C-C8-D0 (hex) TIANJIN YAAN TECHNOLOGY CO., LTD. +7CC8D0 (base 16) TIANJIN YAAN TECHNOLOGY CO., LTD. + No.8 Ziyuan Road,Huayuan Industrial Zone + Tianjin 300384 + CN + +88-E9-17 (hex) Tamaggo +88E917 (base 16) Tamaggo + 2001 McGill College + Montreal Quebec H3A 3L3 + CA + +88-61-5A (hex) Siano Mobile Silicon Ltd. +88615A (base 16) Siano Mobile Silicon Ltd. + P.O. Box 8684 + Netanya 42504 + IL + +70-E2-4C (hex) SAE IT-systems GmbH & Co. KG +70E24C (base 16) SAE IT-systems GmbH & Co. KG + Im Gewerbegebiet Pesch 14 + Köln NRW 50767 + DE + +00-FD-4C (hex) NEVATEC +00FD4C (base 16) NEVATEC + Lindaraja 2 + Granada 18009 + ES + +14-43-19 (hex) Creative&Link Technology Limited +144319 (base 16) Creative&Link Technology Limited + ROOM 704 HONG JIN GE BLD. NO.3018,YANHE SOUTH ROAD + Shenzhen Guangdong 518002 + US + +D8-AF-3B (hex) Hangzhou Bigbright Integrated communications system Co.,Ltd +D8AF3B (base 16) Hangzhou Bigbright Integrated communications system Co.,Ltd + The 6floor ,Building1,No.1418-41,Moganshan Road + Hangzhou Zhejiang 310015 + CN + +60-32-F0 (hex) Mplus technology +6032F0 (base 16) Mplus technology + #201 Gayang Dong, Gangsea Gu + Seoul 157-793 + KR + +28-29-D9 (hex) GlobalBeiMing technology (Beijing)Co. Ltd +2829D9 (base 16) GlobalBeiMing technology (Beijing)Co. Ltd + Beijing Chaoyang District 8 Guanghua Road A seat 320 rooms + Beijing 100026 + CN + +1C-C3-16 (hex) MileSight Technology Co., Ltd. +1CC316 (base 16) MileSight Technology Co., Ltd. + 202-2,No.21 Wanghai Road, 2nd Software Park + Xiamen Fujian 361006 + CN + +68-15-D3 (hex) Zaklady Elektroniki i Mechaniki Precyzyjnej R&G S.A. +6815D3 (base 16) Zaklady Elektroniki i Mechaniki Precyzyjnej R&G S.A. + ul. Traugutta 7 + Mielec 39-300 + PL + +10-F3-DB (hex) Gridco Systems, Inc. +10F3DB (base 16) Gridco Systems, Inc. + 10-L Commerice Way + Woburn MA 01801 + US + +30-5D-38 (hex) Beissbarth +305D38 (base 16) Beissbarth + Hanauer Str. 101 + Muenchen 80993 + DE + +60-D2-B9 (hex) REALAND BIO CO., LTD. +60D2B9 (base 16) REALAND BIO CO., LTD. + Room 201A, N.set, Jinshan Bd., No.248 Wushan Rd., Tianhe District + Guangzhou Guangdong 510630 + CN + +30-FD-11 (hex) MACROTECH (USA) INC. +30FD11 (base 16) MACROTECH (USA) INC. + 1799 BAYSHORE HIGHWAY + BURLINGAME CA 94010 + US + +C4-DA-26 (hex) NOBLEX SA +C4DA26 (base 16) NOBLEX SA + Vicente Padín Moreira 97 + Ushuaia Tierra del fuego 9410 + AR + +7C-C8-AB (hex) Acro Associates, Inc. +7CC8AB (base 16) Acro Associates, Inc. + 1990 Olivera Rd. + Concord CA 94520 + US + +60-19-29 (hex) VOLTRONIC POWER TECHNOLOGY(SHENZHEN) CORP. +601929 (base 16) VOLTRONIC POWER TECHNOLOGY(SHENZHEN) CORP. + 1-4F,Building 5,YuSheng Industrial Park,No.467,Section Xixiang,National Highway 107,Xixiang,Bao An District,Shenzhen,China + Shenzhen Shenzhen 518000 + CN + +48-B2-53 (hex) Marketaxess Corporation +48B253 (base 16) Marketaxess Corporation + 299 Park Avenue + New York NY 10171 + US + +74-94-3D (hex) AgJunction +74943D (base 16) AgJunction + 8444 N. 90th St + Scottsdale AZ 85258 + US + +58-CF-4B (hex) Lufkin Industries +58CF4B (base 16) Lufkin Industries + 811 Willow Oak Drive + Missouri City Texas 77489 + US + +68-B4-3A (hex) WaterFurnace International, Inc. +68B43A (base 16) WaterFurnace International, Inc. + 9000 Conservation Way + Fort Wayne IN 46809 + US + +4C-78-97 (hex) Arrowhead Alarm Products Ltd +4C7897 (base 16) Arrowhead Alarm Products Ltd + 344B Rosedale Road + Auckland Auckland 0751 + NZ + +44-E8-A5 (hex) Myreka Technologies Sdn. Bhd. +44E8A5 (base 16) Myreka Technologies Sdn. Bhd. + 2-13, JALAN MAYANG PASIR 1, + Bayan Baru Penang 11950 + MY + +D8-AF-F1 (hex) Panasonic Appliances Company +D8AFF1 (base 16) Panasonic Appliances Company + 2-3-1-2 Noji-higashi + Kusatsu City Shiga 525-8555 + JP + +2C-62-89 (hex) Regenersis (Glenrothes) Ltd +2C6289 (base 16) Regenersis (Glenrothes) Ltd + 1 James Watt Avenue + Glenrothes Fife KY7 4UA + GB + +58-EC-E1 (hex) Newport Corporation +58ECE1 (base 16) Newport Corporation + 1791 Deere Ave. + Irvine California 92606 + US + +4C-09-B4 (hex) zte corporation +4C09B4 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +60-D1-AA (hex) Vishal Telecommunications Pvt Ltd +60D1AA (base 16) Vishal Telecommunications Pvt Ltd + 25 Sitaram Building Dr D N Road + Mumbai Maharastra 400001 + IN + +70-9B-A5 (hex) Shenzhen Y&D Electronics Co.,LTD. +709BA5 (base 16) Shenzhen Y&D Electronics Co.,LTD. + D zone3F,Shenzhen Academy of Aerospace Technology,Hi-Tech Park,south 10th Road,Nanshan + Shenzhen Guangdong 518057 + CN + +F4-54-33 (hex) Rockwell Automation +F45433 (base 16) Rockwell Automation + 1 Allen-Bradley Dr. + Mayfield Heights OH 44124-6118 + US + +B4-89-10 (hex) Coster T.E. S.P.A. +B48910 (base 16) Coster T.E. S.P.A. + Via San Giovanni Battista De La Salle 4/a + Milano MI 20132 + IT + +B0-C8-3F (hex) Jiangsu Cynray IOT Co., Ltd. +B0C83F (base 16) Jiangsu Cynray IOT Co., Ltd. + Building D1, 1 Zidong road, Qixia district + Nanjing Jiangsu 210000 + CN + +3C-F3-92 (hex) Virtualtek. Co. Ltd +3CF392 (base 16) Virtualtek. Co. Ltd + 12F, ShinhanDm Bldg., + Seoul 121-708 + KR + +B4-82-C5 (hex) Relay2, Inc. +B482C5 (base 16) Relay2, Inc. + 1525 McCarthy Blvd., + Milpitas CA 95035 + US + +98-5E-1B (hex) ConversDigital Co., Ltd. +985E1B (base 16) ConversDigital Co., Ltd. + 5308 5th Bldg., Dong Seoul Univ. + Seongnam Gyeonggi 461714 + KR + +D4-8C-B5 (hex) Cisco Systems, Inc +D48CB5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +90-9D-E0 (hex) Newland Design + Assoc. Inc. +909DE0 (base 16) Newland Design + Assoc. Inc. + 3186-G Airway Ave. + Costa Mesa CA 92626 + US + +14-9F-E8 (hex) Lenovo Mobile Communication Technology Ltd. +149FE8 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999,Qishan North 2nd Road,Information&Optoelectronics Park,Torch Hi-tech Industry Development Zone + Xiamen Fujian 361006 + CN + +BC-D9-40 (hex) ASR Co,.Ltd. +BCD940 (base 16) ASR Co,.Ltd. + 1-3-1 Sotokanda Chiyoda-ku + Tokyo 101-0021 + JP + +04-9C-62 (hex) BMT Medical Technology s.r.o. +049C62 (base 16) BMT Medical Technology s.r.o. + Cejl 50 + Brno 65660 + CZ + +0C-2A-69 (hex) electric imp, incorporated +0C2A69 (base 16) electric imp, incorporated + 5050 El Camino Real, Ste 221 + Los Altos California 94022 + US + +C4-55-C2 (hex) Bach-Simpson +C455C2 (base 16) Bach-Simpson + 109 Meg Drive + London Ontario N6E3Z7 + CA + +00-E8-AB (hex) Meggitt Training Systems, Inc. +00E8AB (base 16) Meggitt Training Systems, Inc. + 296 Brogdon Rd + Suwanee GA 30024 + US + +B4-21-8A (hex) Dog Hunter LLC +B4218A (base 16) Dog Hunter LLC + 8 Faneuil Hall SQ + Boston MA 02109 + US + +B4-A4-B5 (hex) Zen Eye Co.,Ltd +B4A4B5 (base 16) Zen Eye Co.,Ltd + #401, 157-5 Chunui-dong + Bucheon-si Gyeonggi-do 420-859 + KR + +DC-37-D2 (hex) Hunan HKT Electronic Technology Co., Ltd +DC37D2 (base 16) Hunan HKT Electronic Technology Co., Ltd + Room 428,4F,Hunan Environmental Science and Technology Committee Building,No 18 South of Wanjiali Road,Yuhua District,Changsha + Changsha Hunan 410007 + CN + +40-70-74 (hex) Life Technology (China) Co., Ltd +407074 (base 16) Life Technology (China) Co., Ltd + No.1, 2F, Nanshan Digital Culture Industrial base (East Tower Podium) 10128 Shennan Blvd, Nanshan Dist. + Shenzhen Guangdong 518000 + CN + +20-F0-02 (hex) MTData Developments Pty. Ltd. +20F002 (base 16) MTData Developments Pty. Ltd. + 20 Miles Street + Mulgrave Victoria 3170 + AU + +38-8A-B7 (hex) ITC Networks +388AB7 (base 16) ITC Networks + 3F Daiwa Shibaura Bldg + Tokyo 105-0023 + JP + +BC-C2-3A (hex) Thomson Video Networks +BCC23A (base 16) Thomson Video Networks + 6, rue du Clos Courtel + Cesson Sevigne 35510 + FR + +1C-F4-CA (hex) Private +1CF4CA (base 16) Private + +AC-C2-EC (hex) CLT INT'L IND. CORP. +ACC2EC (base 16) CLT INT'L IND. CORP. + 11F-2, NO.1, ZHANQIAN + MIAOLI 36043 + TW + +A8-65-B2 (hex) DONGGUAN YISHANG ELECTRONIC TECHNOLOGY CO., LIMITED +A865B2 (base 16) DONGGUAN YISHANG ELECTRONIC TECHNOLOGY CO., LIMITED + 3rd floor, B# Building ,Houdefu Logistics Park,Qingshuiao, + Dongguan Guangdong 523062 + CN + +E8-D0-FA (hex) MKS Instruments Deutschland GmbH +E8D0FA (base 16) MKS Instruments Deutschland GmbH + Schatzbogen 43 + Munich 81829 + DE + +98-26-2A (hex) Applied Research Associates, Inc +98262A (base 16) Applied Research Associates, Inc + 4300 San Mateo Boulevard NE + Albuquerque NM 87110 + US + +3C-91-74 (hex) ALONG COMMUNICATION TECHNOLOGY +3C9174 (base 16) ALONG COMMUNICATION TECHNOLOGY + 1301, Zhenye International Business Center, + Shenzhen Guandong 518000 + CN + +AC-EE-3B (hex) 6harmonics Inc +ACEE3B (base 16) 6harmonics Inc + 21 Concourse Gate - Suite 10 + Ottawa Ontario K2E 7S4 + CA + +1C-6B-CA (hex) Mitsunami Co., Ltd. +1C6BCA (base 16) Mitsunami Co., Ltd. + 2-30-11, Nishi-gotanda, Shinagawa-ku + Tokyo 141-0031 + JP + +64-24-00 (hex) Xorcom Ltd. +642400 (base 16) Xorcom Ltd. + Teradyon Industrial Park + D.N Misgav 20179 + IL + +E8-3E-FB (hex) GEODESIC LTD. +E83EFB (base 16) GEODESIC LTD. + 18,10TH CROSS, MAYURA STREET + BANGALORE KARNATAKA 560094 + IN + +EC-D1-9A (hex) Zhuhai Liming Industries Co., Ltd +ECD19A (base 16) Zhuhai Liming Industries Co., Ltd + No.6 Xinqing Rd,Xinqing Hi-Tech Industrial Park + Zhuhai Guangdong 519100 + CN + +34-81-37 (hex) UNICARD SA +348137 (base 16) UNICARD SA + UL.WADOWICKA 12 + KRAKOW woj. malopolskie 30-415 + PL + +38-B1-2D (hex) Sonotronic Nagel GmbH +38B12D (base 16) Sonotronic Nagel GmbH + Becker-Goering-Str. 17-25 + Karlsbad 76307 + DE + +54-9D-85 (hex) EnerAccess inc +549D85 (base 16) EnerAccess inc + 3154 Le Corbusier Blvd + Laval Quebec H7L 4S8 + CA + +B0-75-0C (hex) QA Cafe +B0750C (base 16) QA Cafe + 33 Jewell Court + Portsmouth NH 03801 + US + +B4-E1-EB (hex) Private +B4E1EB (base 16) Private + +3C-36-3D (hex) Nokia Corporation +3C363D (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +80-86-98 (hex) Netronics Technologies Inc. +808698 (base 16) Netronics Technologies Inc. + 600-15 Allstate Parkway + Markham Ontario L3R 5B4 + CA + +9C-E1-0E (hex) NCTech Ltd +9CE10E (base 16) NCTech Ltd + 20-22 Braid Road + Edinburgh EH10 6AD + GB + +A0-6D-09 (hex) Intelcan Technosystems Inc. +A06D09 (base 16) Intelcan Technosystems Inc. + 5490 Boul Thimens + Saint-Laurent Quebec H4R2K9 + CA + +60-F3-DA (hex) Logic Way GmbH +60F3DA (base 16) Logic Way GmbH + Hagenower Str. 73 + Schwerin Mecklenburg-West Pomerania 19061 + DE + +FC-50-90 (hex) SIMEX Sp. z o.o. +FC5090 (base 16) SIMEX Sp. z o.o. + ul. Wielopole 7 + Gdañsk pomorskie 80-556 + PL + +60-B9-82 (hex) RO.VE.R. Laboratories S.p.A. +60B982 (base 16) RO.VE.R. Laboratories S.p.A. + Via Parini, 2 + Sirmione Brescia 25019 + IT + +B4-62-38 (hex) Exablox +B46238 (base 16) Exablox + 365 San Antonio Road + Mountain View CA 94040 + US + +C8-BB-D3 (hex) Embrane +C8BBD3 (base 16) Embrane + 2350 Mission College Blvd., Ste 703 + Santa Clara CA 95054 + US + +8C-60-4F (hex) Cisco Systems, Inc +8C604F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A4-B9-80 (hex) Parking BOXX Inc. +A4B980 (base 16) Parking BOXX Inc. + 382 NE 191st St. #93984 + Miami FL 33179-3899 + US + +A4-7C-14 (hex) ChargeStorm AB +A47C14 (base 16) ChargeStorm AB + Laxholmstorget 3 + Norrköping 60221 + SE + +80-20-AF (hex) Trade FIDES, a.s. +8020AF (base 16) Trade FIDES, a.s. + Dornych 57 + Brno 61700 + CZ + +2C-75-0F (hex) Shanghai Dongzhou-Lawton Communication Technology Co. Ltd. +2C750F (base 16) Shanghai Dongzhou-Lawton Communication Technology Co. Ltd. + NO.188,FengyeRoad,BaoshanDistrict + shanghai 200949 + CN + +5C-50-15 (hex) Cisco Systems, Inc +5C5015 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +98-02-84 (hex) Theobroma Systems GmbH +980284 (base 16) Theobroma Systems GmbH + Gutheil-Schoder Gasse 17 + Wien 1230 + US + +1C-D4-0C (hex) Kriwan Industrie-Elektronik GmbH +1CD40C (base 16) Kriwan Industrie-Elektronik GmbH + Allmand 11 + Forchtenberg Baden-Würtemberg D-74670 + DE + +00-2D-76 (hex) TITECH GmbH +002D76 (base 16) TITECH GmbH + Otto-Hahn-Str. 6 + Muelheim-Kaerlich 56218 + DE + +F8-DB-4C (hex) PNY Technologies, INC. +F8DB4C (base 16) PNY Technologies, INC. + 100 Jefferson Road + Parsippany New Jersey 07054 + US + +0C-9D-56 (hex) Consort Controls Ltd +0C9D56 (base 16) Consort Controls Ltd + 13 Campion Terrace + Leamington Spa CV32 4SU + GB + +3C-B8-7A (hex) Private +3CB87A (base 16) Private + +AC-14-61 (hex) ATAW Co., Ltd. +AC1461 (base 16) ATAW Co., Ltd. + Dongan-gu Pyeongchon-dong 126-1 + Anyang-si Gyeonggi-do 431-755 + KR + +E4-C6-E6 (hex) Mophie, LLC +E4C6E6 (base 16) Mophie, LLC + 2850 Red Hill Ave. + Santa Ana CA 92705 + US + +50-2D-1D (hex) Nokia Corporation +502D1D (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +F4-8E-09 (hex) Nokia Corporation +F48E09 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +58-48-C0 (hex) COFLEC +5848C0 (base 16) COFLEC + Parc d'activités du moulin de Massy + MASSY 91300 + FR + +8C-57-FD (hex) LVX Western +8C57FD (base 16) LVX Western + 700 54th ave North + St. Cloud MN 56303 + US + +54-E6-3F (hex) ShenZhen LingKeWeiEr Technology Co., Ltd. +54E63F (base 16) ShenZhen LingKeWeiEr Technology Co., Ltd. + Room 625, YiJing Building, MeiLin Rd., FuTian District + ShenZhen GuandDong 518000 + CN + +20-FA-BB (hex) Cambridge Executive Limited +20FABB (base 16) Cambridge Executive Limited + St John's Innovation Centre + Cambridge Cambridgeshire CB40WS + GB + +14-1A-51 (hex) Treetech Sistemas Digitais +141A51 (base 16) Treetech Sistemas Digitais + Praca Claudino Alves, 141 + Atibaia São Paulo 12940-800 + BR + +58-7F-C8 (hex) S2M +587FC8 (base 16) S2M + 2 rue des champs + Saint Marcel 27950 + FR + +20-05-05 (hex) RADMAX COMMUNICATION PRIVATE LIMITED +200505 (base 16) RADMAX COMMUNICATION PRIVATE LIMITED + F-24/34, IIND FLOOR, SECTOR-7 + DELHI DELHI 110085 + IN + +C0-35-BD (hex) Velocytech Aps +C035BD (base 16) Velocytech Aps + Automatikvej 1, 3rd floor + SOEBORG 2860 + DK + +28-71-84 (hex) Spire Payments +287184 (base 16) Spire Payments + Units 3 & 6 Milford Trading Estate + Salisbury Wiltshire SP1 2UD + GB + +7C-B0-3E (hex) OSRAM GmbH +7CB03E (base 16) OSRAM GmbH + Berliner Allee 65 + Augsburg Bayern 86136 + DE + +3C-9F-81 (hex) Shenzhen CATIC Bit Communications Technology Co.,Ltd +3C9F81 (base 16) Shenzhen CATIC Bit Communications Technology Co.,Ltd + in Nanshan District,Shenzhen Software park Road 10 in Room 202 + Shenzhen Guangdong 518057 + CN + +44-5F-7A (hex) Shihlin Electric & Engineering Corp. +445F7A (base 16) Shihlin Electric & Engineering Corp. + 16F NO.88, SEC, 6, CHUNG SHAN N. RD., TAIPEI + HsinChu HsinFun Shiang 304 + TW + +08-8F-2C (hex) Hills Sound Vision & Lighting +088F2C (base 16) Hills Sound Vision & Lighting + 1 Clyde Street + Silverwater New South Wales 2128 + AU + +44-13-19 (hex) WKK TECHNOLOGY LTD. +441319 (base 16) WKK TECHNOLOGY LTD. + 23/F., One Kowloon, No.1, Wang Yuen Street, + 852 + HK + +18-B5-91 (hex) I-Storm +18B591 (base 16) I-Storm + Hogye-dong, Dongan-gu + Anyang-si Gyeonggi-do 431-080 + KR + +BC-8B-55 (hex) NPP ELIKS America Inc. DBA T&M Atlantic +BC8B55 (base 16) NPP ELIKS America Inc. DBA T&M Atlantic + 175 SW 7th St Suite 1812 + Miami FL 33130 + US + +C0-49-3D (hex) MAITRISE TECHNOLOGIQUE +C0493D (base 16) MAITRISE TECHNOLOGIQUE + 224 RUE DE LA SAINTE BAUME + SAINT MAXIMIN LA SAINTE BAUME VAR 83470 + FR + +C8-45-44 (hex) Asia Pacific CIS (Wuxi) Co, Ltd +C84544 (base 16) Asia Pacific CIS (Wuxi) Co, Ltd + No 11, Xikun Road, Wuxi New District + Wuxi Jiangsu 214028 + CN + +E0-EF-25 (hex) Lintes Technology Co., Ltd. +E0EF25 (base 16) Lintes Technology Co., Ltd. + 9F-1., No.150, Jian 1st Rd., Zhonghe Dist., + New Taipei City 23511 + TW + +50-ED-94 (hex) EGATEL SL +50ED94 (base 16) EGATEL SL + Parque Tecnologico de Galicia + Ourense 32901 + ES + +48-A2-2D (hex) Shenzhen Huaxuchang Telecom Technology Co.,Ltd +48A22D (base 16) Shenzhen Huaxuchang Telecom Technology Co.,Ltd + Room 501 Block B, Cyber Time Plaza + Shenzhen Guangdong 518040 + CN + +C8-60-00 (hex) ASUSTek COMPUTER INC. +C86000 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +AC-0D-FE (hex) Ekon GmbH - myGEKKO +AC0DFE (base 16) Ekon GmbH - myGEKKO + Rienzfeldstraße 30 + Bruneck Südtirol (BZ) 39031 + IT + +FC-5B-26 (hex) MikroBits +FC5B26 (base 16) MikroBits + Jalan Petung 31 Papringan + Yogyakarta DIY 55281 + ID + +40-F4-07 (hex) Nintendo Co., Ltd. +40F407 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +B0-1C-91 (hex) Elim Co +B01C91 (base 16) Elim Co + 4F Gagu Plaza B/D 81-9, jeongja-dong, Jangan-gu, + Suwon city Gyeonggi-Do 440-300 + KR + +04-F1-7D (hex) Tarana Wireless +04F17D (base 16) Tarana Wireless + 2105 Martin Luther King Jr Way + Berkeley CA 94704 + US + +84-49-15 (hex) vArmour Networks, Inc. +844915 (base 16) vArmour Networks, Inc. + 4633 OLD IRONSIDES DR + SANTA CLARA CA 95054-1807 + US + +2C-BE-97 (hex) Ingenieurbuero Bickele und Buehler GmbH +2CBE97 (base 16) Ingenieurbuero Bickele und Buehler GmbH + St.Poeltener Str. 70 + Stuttgart BW 70469 + DE + +70-A6-6A (hex) Prox Dynamics AS +70A66A (base 16) Prox Dynamics AS + Smedsvingen 4 + Hvalstad Akershus 1395 + NO + +DC-3E-51 (hex) Solberg & Andersen AS +DC3E51 (base 16) Solberg & Andersen AS + Litleaasvegen 61 + Bergen 5132 + NO + +90-0A-3A (hex) PSG Plastic Service GmbH +900A3A (base 16) PSG Plastic Service GmbH + Pinaer Str. 12-16 + Mannheim BW 68309 + DE + +28-CD-1C (hex) Espotel Oy +28CD1C (base 16) Espotel Oy + Kappelitie 6 + Espoo Espoo FI-02200 + FI + +D4-43-A8 (hex) Changzhou Haojie Electric Co., Ltd. +D443A8 (base 16) Changzhou Haojie Electric Co., Ltd. + No. 158, + Changzhou Jiangsu 213022 + CN + +BC-E5-9F (hex) WATERWORLD Technology Co.,LTD +BCE59F (base 16) WATERWORLD Technology Co.,LTD + 6 Floor,Block B,Digital Building,Garden City,No.1079,Nanhai Road,Nanshan District, + Shenzhen Guangdong 518067 + US + +70-41-B7 (hex) Edwards Lifesciences LLC +7041B7 (base 16) Edwards Lifesciences LLC + One Edwards Way + Irvine CA 92614 + US + +DC-A8-CF (hex) New Spin Golf, LLC. +DCA8CF (base 16) New Spin Golf, LLC. + 1637 Burr Oak Drive + Libertyville IL 60048 + US + +A8-49-A5 (hex) Lisantech Co., Ltd. +A849A5 (base 16) Lisantech Co., Ltd. + 1108, STX V-Tower Gasan-dong + Seoul 153-803 + KR + +A0-5E-6B (hex) MELPER Co., Ltd. +A05E6B (base 16) MELPER Co., Ltd. + 207, 2nd FL.,Wonhyo Bldg.,1365-22 + SEOUL 137-863 + KR + +D8-78-E5 (hex) KUHN SA +D878E5 (base 16) KUHN SA + 4, impasse des fabriques + SAVERNE 67700 + FR + +D8-24-BD (hex) Cisco Systems, Inc +D824BD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +34-97-FB (hex) ADVANCED RF TECHNOLOGIES INC +3497FB (base 16) ADVANCED RF TECHNOLOGIES INC + 3116 W Vanowen St + Burbank California 91505 + US + +F0-3A-55 (hex) Omega Elektronik AS +F03A55 (base 16) Omega Elektronik AS + Ege Serbest Bolgesi + Izmir 35410 + TR + +98-BC-57 (hex) SVA TECHNOLOGIES CO.LTD +98BC57 (base 16) SVA TECHNOLOGIES CO.LTD + 5F No.192 Tinglin Road, + SHANGHAI 200233 + CN + +DC-3C-2E (hex) Manufacturing System Insights, Inc. +DC3C2E (base 16) Manufacturing System Insights, Inc. + 2550 Ninth St. + Berkely CA 94710 + US + +F8-35-53 (hex) Magenta Research Ltd. +F83553 (base 16) Magenta Research Ltd. + 128 Litchfield Road + New Milford CT 06776 + US + +F4-04-4C (hex) ValenceTech Limited +F4044C (base 16) ValenceTech Limited + Unit 1, 20/F., APEC Plaza + HONG KONG NIL + CN + +C4-67-B5 (hex) Libratone A/S +C467B5 (base 16) Libratone A/S + Marielundvej 43 A + 2730 HERLEV + DK + +4C-39-10 (hex) Newtek Electronics co., Ltd. +4C3910 (base 16) Newtek Electronics co., Ltd. + Byucksan-Sunyoung Technopia 1004, + Uiwang-City Kyunggi-Do 437-821 + KR + +90-3A-A0 (hex) Nokia +903AA0 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +B0-6C-BF (hex) 3ality Digital Systems GmbH +B06CBF (base 16) 3ality Digital Systems GmbH + Gut Mergenthau 1 + Kissing Bayern 86438 + DE + +54-D0-ED (hex) AXIM Communications +54D0ED (base 16) AXIM Communications + 1F., No. 5, Aly. 12, Ln. 15, Sec. 6, Sinyi Rd., Sinyi Dist., + Taipei 110 + TW + +84-36-11 (hex) hyungseul publishing networks +843611 (base 16) hyungseul publishing networks + 526-4, paju bookcity, munbal-li, gyoha-eup + paju-si Gyeonggi-do 413-832 + KR + +34-40-B5 (hex) IBM +3440B5 (base 16) IBM + 3039 E Cornwallis Rd + Research Triangle Park NC 27709 + US + +D4-D7-48 (hex) Cisco Systems, Inc +D4D748 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +34-4F-69 (hex) EKINOPS SAS +344F69 (base 16) EKINOPS SAS + 3, Rue Blaise Pascal + LANNION FRANCE 22300 + FR + +F8-31-3E (hex) endeavour GmbH +F8313E (base 16) endeavour GmbH + Max-Planck-Str. 04 + Vreden NRW 48691 + DE + +14-36-05 (hex) Nokia Corporation +143605 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +C8-1A-FE (hex) DLOGIC GmbH +C81AFE (base 16) DLOGIC GmbH + Rathausstrasse 14 + Baar ZG 6341 + CH + +EC-63-E5 (hex) ePBoard Design LLC +EC63E5 (base 16) ePBoard Design LLC + 4065 E. La Palma Ave. + Anaheim California 92807 + US + +94-DB-49 (hex) SITCORP +94DB49 (base 16) SITCORP + 7 RUE CADET + PARIS 75015 + FR + +F0-62-0D (hex) Shenzhen Egreat Tech Corp.,Ltd +F0620D (base 16) Shenzhen Egreat Tech Corp.,Ltd + 4F,1Building,Chuangye Industrial park + Shenzhen Guangdong 518104 + CN + +2C-67-FB (hex) ShenZhen Zhengjili Electronics Co., LTD +2C67FB (base 16) ShenZhen Zhengjili Electronics Co., LTD + The Longhua Town Shenzhen City Streets huaning three house Science Park Road Chiayi Source fifth floor + Shenzhen Guangdong 518000 + CN + +3C-E5-B4 (hex) KIDASEN INDUSTRIA E COMERCIO DE ANTENAS LTDA +3CE5B4 (base 16) KIDASEN INDUSTRIA E COMERCIO DE ANTENAS LTDA + AV SINCLER SAMBATTI, 1945 + MARINGA PARANA 87055-020 + BR + +08-D0-9F (hex) Cisco Systems, Inc +08D09F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +64-4B-F0 (hex) CalDigit, Inc +644BF0 (base 16) CalDigit, Inc + 1941 Miraloma Ave #B + Placentia CA 92870 + US + +64-ED-62 (hex) WOORI SYSTEMS Co., Ltd +64ED62 (base 16) WOORI SYSTEMS Co., Ltd + 101Ho #42-9, Jeongja-dong, Pundang-gu + Sungnam-si Kyunggi-do 463-848 + KR + +2C-00-2C (hex) UNOWHY +2C002C (base 16) UNOWHY + 11, rue Tronchet + Paris 75008 + US + +5C-C9-D3 (hex) PALLADIUM ENERGY ELETRONICA DA AMAZONIA LTDA +5CC9D3 (base 16) PALLADIUM ENERGY ELETRONICA DA AMAZONIA LTDA + AVENIDA BURITI, 4285 + MANAUS AMAZONAS 69075-000 + BR + +C8-7C-BC (hex) Valink Co., Ltd. +C87CBC (base 16) Valink Co., Ltd. + 1F Dongwon Bldg. 90, Dangsan-Dong 3-Ga Youngdungpo-Gu + Seoul 150-803 + KR + +B8-14-13 (hex) Keen High Holding(HK) Ltd. +B81413 (base 16) Keen High Holding(HK) Ltd. + 25th Floor, In-long Development Centre, No.6025 Shennan Ave + Shenzhen Guangdong 518040 + CN + +B4-94-4E (hex) WeTelecom Co., Ltd. +B4944E (base 16) WeTelecom Co., Ltd. + The'O Plus #915 + Gunpo-si Kyunggi-do 435-805 + KR + +E0-0B-28 (hex) Inovonics +E00B28 (base 16) Inovonics + 315 CTC Blvd + Louisville CO 80027 + US + +48-02-2A (hex) B-Link Electronic Limited +48022A (base 16) B-Link Electronic Limited + NO 268,FuQian Rd, JuTang Community,GuanLan town BaoAn district,ShenZhen, 518110,China + Shen Zhen Guang Dong 518110 + CN + +18-E8-0F (hex) Viking Electronics Inc. +18E80F (base 16) Viking Electronics Inc. + 1531 Industrial St + Hudson WI 54016 + US + +CC-6B-F1 (hex) Sound Masking Inc. +CC6BF1 (base 16) Sound Masking Inc. + 47 - 23 - Glamis Drive Sw + Calgary Alberta T3E 6S3 + CA + +2C-97-17 (hex) I.C.Y. B.V. +2C9717 (base 16) I.C.Y. B.V. + Houtsaachmole 35 + Lemmer Friesland 8531 WC + NL + +2C-3F-38 (hex) Cisco Systems, Inc +2C3F38 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +40-50-E0 (hex) Milton Security Group LLC +4050E0 (base 16) Milton Security Group LLC + 111 North Harbor Blvd + Fullerton CA 92832 + US + +70-CA-9B (hex) Cisco Systems, Inc +70CA9B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A0-78-BA (hex) Pantech Co., Ltd. +A078BA (base 16) Pantech Co., Ltd. + 110-1 Ongjeong-Ri, Tongjin-Eup + Gimpo-Si Gyounggi-Do 415-865 + KR + +68-BC-0C (hex) Cisco Systems, Inc +68BC0C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +34-5B-11 (hex) EVI HEAT AB +345B11 (base 16) EVI HEAT AB + Box 55 + Kungsaengen 196 22 + SE + +78-BA-D0 (hex) Shinybow Technology Co. Ltd. +78BAD0 (base 16) Shinybow Technology Co. Ltd. + 9Fl.,No.63,Ju Guang Rd.,Chung Ho Dist. + New Taipei 235 + TW + +24-E6-BA (hex) JSC Zavod im. Kozitsky +24E6BA (base 16) JSC Zavod im. Kozitsky + Bld. 70, 5th line, V.O, + St.-Petersburg 199048 + RU + +CC-A3-74 (hex) Guangdong Guanglian Electronic Technology Co.Ltd +CCA374 (base 16) Guangdong Guanglian Electronic Technology Co.Ltd + B338,Block13,No.232 Waihuandonglu Road,High Education Mega Center + Guangzhou Guangdong 510006 + CN + +58-67-7F (hex) Clare Controls Inc. +58677F (base 16) Clare Controls Inc. + 7519 Pennsylvania Ave + Sarasota FL 34243 + US + +0C-5A-19 (hex) Axtion Sdn Bhd +0C5A19 (base 16) Axtion Sdn Bhd + A13-07, Subang Avenue Serviced Suites + Subang Jaya Selangor 47500 + MY + +A8-BD-1A (hex) Honey Bee (Hong Kong) Limited +A8BD1A (base 16) Honey Bee (Hong Kong) Limited + Flat L, 12/F., Phase 4, Kwun Tong Industrial Ctr., + + HK + +24-87-07 (hex) SEnergy Corporation +248707 (base 16) SEnergy Corporation + Koizumi Bldg. 3F, 1-38-18 + Yokohama city Kanagawa Pref. 224-0003 + JP + +C4-C1-9F (hex) National Oilwell Varco Instrumentation, Monitoring, and Optimization (NOV IMO) +C4C19F (base 16) National Oilwell Varco Instrumentation, Monitoring, and Optimization (NOV IMO) + 1200 Cypress Creek Rd. + Cedar Park TX 78613 + US + +00-08-30 (hex) Cisco Systems, Inc +000830 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C4-EE-AE (hex) VSS Monitoring +C4EEAE (base 16) VSS Monitoring + 1850 Gateway Dr, Suite 500 + San Mateo CA 94404 + US + +F8-D3-A9 (hex) AXAN Networks +F8D3A9 (base 16) AXAN Networks + 2F Myungjin-Bldg Daechi-Dong Gangnam-Gu + Seoul 135-845 + KR + +BC-77-9F (hex) SBM Co., Ltd. +BC779F (base 16) SBM Co., Ltd. + Hyunwoo Bldg 206, Anyang7-Dong + Anyang Gyeonggi-Do 430-817 + KR + +40-6A-AB (hex) RIM +406AAB (base 16) RIM + Phillip Street + Waterloo Ontario N2L 3W8 + CA + +9C-A3-BA (hex) SAKURA Internet Inc. +9CA3BA (base 16) SAKURA Internet Inc. + 7-20-1 Nishi-shinjuku + Shinjuku-ku Tokyo 1600023 + JP + +8C-8A-6E (hex) ESTUN AUTOMATION TECHNOLOY CO., LTD +8C8A6E (base 16) ESTUN AUTOMATION TECHNOLOY CO., LTD + 16,Shuige Road + Nanjing Jiangsu 211106 + CN + +98-82-17 (hex) Disruptive Ltd +988217 (base 16) Disruptive Ltd + Windsor House + High Wycombe Buckinghamshire HP12 3NR + GB + +9C-5C-8D (hex) FIREMAX INDÚSTRIA E COMÉRCIO DE PRODUTOS ELETRÔNICOS LTDA +9C5C8D (base 16) FIREMAX INDÚSTRIA E COMÉRCIO DE PRODUTOS ELETRÔNICOS LTDA + R: Vicente de Felice, 589 - Jd.Ouro Verde + Limeira São Paulo 13482-075 + BR + +D4-20-6D (hex) HTC Corporation +D4206D (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +7C-1E-52 (hex) Microsoft +7C1E52 (base 16) Microsoft + 1 Microsoft Way + Redmond Washington 98052 + US + +DC-B4-C4 (hex) Microsoft XCG +DCB4C4 (base 16) Microsoft XCG + 1 Microsoft Way + Redmond WA 98052 + US + +AC-CB-09 (hex) Hefcom Metering (Pty) Ltd +ACCB09 (base 16) Hefcom Metering (Pty) Ltd + PO Box 10770 + Centurion Gauteng 0046 + ZA + +18-66-E3 (hex) Veros Systems, Inc. +1866E3 (base 16) Veros Systems, Inc. + PO Box 10534 + College Station Texas 77842 + US + +74-FD-A0 (hex) Compupal (Group) Corporation +74FDA0 (base 16) Compupal (Group) Corporation + No.1555 Jiashan Avenue + Jiashan Zhejiang 314113 + CN + +CC-B8-F1 (hex) EAGLE KINGDOM TECHNOLOGIES LIMITED +CCB8F1 (base 16) EAGLE KINGDOM TECHNOLOGIES LIMITED + FLAT/ RM B 26/F TWO CHINACHEM PLAZA 68 CONNAUGHT ROAD CENTRAL HK + + HK + +A4-29-B7 (hex) bluesky +A429B7 (base 16) bluesky + Rm1410 Tower A,Chengjian plaza,NO.18 beitaipingzhuang Road,Haidian district, + Beijing 100088 + CN + +48-F3-17 (hex) Private +48F317 (base 16) Private + +CC-F8-F0 (hex) Xi'an HISU Multimedia Technology Co.,Ltd. +CCF8F0 (base 16) Xi'an HISU Multimedia Technology Co.,Ltd. + 3 Floor , NO.1 Building , Modern Business Enterprise Centre (East) , NO.69, Jinye road , Xi¡¯an + Xi'an City Shanxi Province 710075 + CN + +04-88-8C (hex) Eifelwerk Butler Systeme GmbH +04888C (base 16) Eifelwerk Butler Systeme GmbH + Eifelwerkstrasse 1 + Malbergweich 54655 + DE + +D4-5A-B2 (hex) Galleon Systems +D45AB2 (base 16) Galleon Systems + Unit 9, Fortnum Close + Birmingham West Midlands B33 0LG + GB + +30-DE-86 (hex) Cedac Software S.r.l. +30DE86 (base 16) Cedac Software S.r.l. + Via Toscana, 3 + Castiglione dei Pepoli Bologna 40035 + IT + +18-C4-51 (hex) Tucson Embedded Systems +18C451 (base 16) Tucson Embedded Systems + 5620 North Kolb Road + Tucson AZ 85750 + US + +70-46-42 (hex) CHYNG HONG ELECTRONIC CO., LTD. +704642 (base 16) CHYNG HONG ELECTRONIC CO., LTD. + No.80, Lane 258, Sec. 3, Hansi W. Rd., + Taichung 40647 + TW + +D4-1C-1C (hex) RCF S.P.A. +D41C1C (base 16) RCF S.P.A. + Via Raffaello Sanzio 13 + Reggio Emilia Italy 42124 + IT + +58-92-0D (hex) Kinetic Avionics Limited +58920D (base 16) Kinetic Avionics Limited + Elstree Aerodrome + Hertfordshire WD6 3AW + GB + +AC-02-EF (hex) Comsis +AC02EF (base 16) Comsis + 3 rue Broussais + Paris 75014 + FR + +B8-B4-2E (hex) Gionee Communication Equipment Co,Ltd.ShenZhen +B8B42E (base 16) Gionee Communication Equipment Co,Ltd.ShenZhen + 21/F Times Technology Building, 7028 Shennan Road, Futian District, + Shenzhen Guangdong 518040 + CN + +44-3E-B2 (hex) DEOTRON Co., LTD. +443EB2 (base 16) DEOTRON Co., LTD. + 506, Dain Bldg + Ansan Kyonggi-do 425-856 + KR + +D0-59-C3 (hex) CeraMicro Technology Corporation +D059C3 (base 16) CeraMicro Technology Corporation + 4F, No. 16-1, Sec. 6, Mingcyuan East Road + Taipei 114 + TW + +18-2C-91 (hex) Concept Development, Inc. +182C91 (base 16) Concept Development, Inc. + 1881 Langley Avenue + Irvine CA 92614-5623 + US + +FC-17-94 (hex) InterCreative Co., Ltd +FC1794 (base 16) InterCreative Co., Ltd + 897-6, HoGye-Dong, DongAn-Gu, + AnYang-Si, GyeongGi-Do, 431-836 + KR + +B4-0B-7A (hex) Brusa Elektronik AG +B40B7A (base 16) Brusa Elektronik AG + Neudorf 14 + Sennwald St. Gallen 9466 + CH + +28-0C-B8 (hex) Mikrosay Yazilim ve Elektronik A.S. +280CB8 (base 16) Mikrosay Yazilim ve Elektronik A.S. + Cevizli Mah. Tansel Cad. + Istanbul 34846 + TR + +3C-C9-9E (hex) Huiyang Technology Co., Ltd +3CC99E (base 16) Huiyang Technology Co., Ltd + 22D 7 Block ZhonghuiNewcity + Dongguan Guangdong 523849 + CN + +2C-1E-EA (hex) AERODEV +2C1EEA (base 16) AERODEV + No.59,1985 Lane,Chunshen Road, + Shanghai 200237 + CN + +1C-8E-8E (hex) DB Communication & Systems Co., ltd. +1C8E8E (base 16) DB Communication & Systems Co., ltd. + 3-3 Yeongdeok-dong, Giheung-gu + Yongin-si Gyeonggi-do 449-908 + KR + +24-EC-99 (hex) ASKEY COMPUTER CORP +24EC99 (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +A4-4B-15 (hex) Sun Cupid Technology (HK) LTD +A44B15 (base 16) Sun Cupid Technology (HK) LTD + Room 1201-3, 12/F., Tower 6 + Tsim Sha Tsui + HK + +48-C8-62 (hex) Simo Wireless,Inc. +48C862 (base 16) Simo Wireless,Inc. + 326#,Building 4,Zhongxing Industrial Park,Chuangye + Shenzhen Guangdong 518054 + CN + +78-BE-B6 (hex) Enhanced Vision +78BEB6 (base 16) Enhanced Vision + 5882 MACHINE DR. + Huntington Beach California 92649 + US + +44-9C-B5 (hex) Alcomp, Inc +449CB5 (base 16) Alcomp, Inc + 11537 Walnut Lane + Fort Atkinson WI 53538 + US + +B4-FC-75 (hex) SEMA Electronics(HK) CO.,LTD +B4FC75 (base 16) SEMA Electronics(HK) CO.,LTD + Xialingbei Industrial Zone Liaobu, + Dongguan Guangdong 523411 + CN + +B0-BF-99 (hex) WIZITDONGDO +B0BF99 (base 16) WIZITDONGDO + 2F, 299-1, 3-DONG, SUNGSU 2-GA + SEOUL 133-833 + KR + +B8-2A-DC (hex) EFR Europäische Funk-Rundsteuerung GmbH +B82ADC (base 16) EFR Europäische Funk-Rundsteuerung GmbH + Nymphenburger Straße 20b + Munich 80335 + DE + +40-F1-4C (hex) ISE Europe SPRL +40F14C (base 16) ISE Europe SPRL + Fauvette 1 + Uccle 1180 + BE + +E8-94-4C (hex) Cogent Healthcare Systems Ltd +E8944C (base 16) Cogent Healthcare Systems Ltd + 69 Alma Road + Berkshire SL4 3HT + GB + +90-67-F3 (hex) Alcatel Lucent +9067F3 (base 16) Alcatel Lucent + Via Energy Park, 14 + Vimercate MB 20871 + IT + +D4-F0-B4 (hex) Napco Security Technologies +D4F0B4 (base 16) Napco Security Technologies + 333 Bayview Ave + Amityville NY 11701 + US + +68-F8-95 (hex) Redflow Limited +68F895 (base 16) Redflow Limited + 1/27 Counihan Rd + Brisbane Queensland 4073 + AU + +70-B9-21 (hex) Fiberhome Telecommunication Technologies Co.,LTD +70B921 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +A0-E2-95 (hex) DAT System Co.,Ltd +A0E295 (base 16) DAT System Co.,Ltd + Gun San Free Trade Area 511-1 , + 573-540 + KR + +A0-16-5C (hex) Triteka LTD +A0165C (base 16) Triteka LTD + Malha Technology Park + Jerusalem 96951 + IL + +9C-41-7C (hex) Hame Technology Co., Limited +9C417C (base 16) Hame Technology Co., Limited + 5F, No. 18 High Tech Middle Avenue One, High Tech Industrial Park, Nanshan District, + Shenzhen Guangdong 518057 + CN + +9C-6A-BE (hex) QEES ApS. +9C6ABE (base 16) QEES ApS. + Naverland 31, 2.tv + Glostrup Hovedstaden 2600 + DK + +9C-93-4E (hex) Xerox Corporation +9C934E (base 16) Xerox Corporation + Mail Stop 0214 - 7E + Webster NY 14580 + US + +04-46-65 (hex) Murata Manufacturing Co., Ltd. +044665 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +2C-21-72 (hex) Juniper Networks +2C2172 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +90-09-17 (hex) Far-sighted mobile +900917 (base 16) Far-sighted mobile + Technology Park Desay Building 6th-Floor + Shenzhen Guangdong Province 518000 + CN + +2C-8B-F2 (hex) Hitachi Metals America Ltd +2C8BF2 (base 16) Hitachi Metals America Ltd + 1920 Zanker Road + San Jose CA 95112 + US + +D8-97-3B (hex) Artesyn Embedded Technologies +D8973B (base 16) Artesyn Embedded Technologies + 16/F Lu Plaza Building + Kwun Tong Kowloon 00000 + HK + +38-26-CD (hex) ANDTEK +3826CD (base 16) ANDTEK + Am Soeldnermoos 17 + Hallbergmoos Bavaria 85399 + DE + +88-BF-D5 (hex) Simple Audio Ltd +88BFD5 (base 16) Simple Audio Ltd + Unit 59 Elderpark Workspace + Glasgow G51 3TR + GB + +24-CB-E7 (hex) MYK, Inc. +24CBE7 (base 16) MYK, Inc. + 4-60-30-108, Kamoi, + Yokohama Kanagawa 226-0003 + JP + +B0-A1-0A (hex) Pivotal Systems Corporation +B0A10A (base 16) Pivotal Systems Corporation + 4683 Chabot Drive + Pleasanton CA 94588 + US + +80-2D-E1 (hex) Solarbridge Technologies +802DE1 (base 16) Solarbridge Technologies + 9229 Waterford Centre Blvd + Austin TX 78758 + US + +F4-A5-2A (hex) Hawa Technologies Inc +F4A52A (base 16) Hawa Technologies Inc + 336 Hayes St + San Francisco California 94102 + US + +0C-6E-4F (hex) PrimeVOLT Co., Ltd. +0C6E4F (base 16) PrimeVOLT Co., Ltd. + 2F-3, No. 9, Lane 3, Jihu Rd, Neihu + Taipei 11492 + TW + +E8-B7-48 (hex) Cisco Systems, Inc +E8B748 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +BC-99-BC (hex) FonSee Technology Inc. +BC99BC (base 16) FonSee Technology Inc. + 14F-2, No.32, Gaotie 2nd Rd., + Zhubei City Hsinchu County 302 + TW + +78-3F-15 (hex) EasySYNC Ltd. +783F15 (base 16) EasySYNC Ltd. + Unit 1, 2 Seaward Place + Glasgow Scotland G41 1HH + GB + +18-D0-71 (hex) DASAN CO., LTD. +18D071 (base 16) DASAN CO., LTD. + DASAN Tower 7F, 49 Daewangpangyo-ro644beon-gil + Seongnam-si Gyeonggi-do 463-760 + KR + +58-E4-76 (hex) CENTRON COMMUNICATIONS TECHNOLOGIES FUJIAN CO.,LTD +58E476 (base 16) CENTRON COMMUNICATIONS TECHNOLOGIES FUJIAN CO.,LTD + 4th Floor,Jiaodajiepu Building,72# Kejierlu Road, + Xi'an Shaanxi Province 710100 + CN + +44-7E-95 (hex) Alpha and Omega, Inc +447E95 (base 16) Alpha and Omega, Inc + 4735 Montview Blvd + Denver CO 80207 + US + +98-60-22 (hex) EMW Co., Ltd. +986022 (base 16) EMW Co., Ltd. + 80B-4L, 680-3 Gojan-Dong + Incheon 405-819 + KR + +B8-D4-9D (hex) M Seven System Ltd. +B8D49D (base 16) M Seven System Ltd. + 24F, Trust Tower Bldg, 275-7, Yangjae2-Dong, Seocho-Gu + Seoul 137-739 + KR + +3C-67-2C (hex) Sciovid Inc. +3C672C (base 16) Sciovid Inc. + 387 S Silverbrook Dr + Anaheim CA 92807 + US + +DC-9B-1E (hex) Intercom, Inc. +DC9B1E (base 16) Intercom, Inc. + Sorimachi Bldg., 3-5, Taito 1-chome, + Taito-ku Tokyo 110-8654 + JP + +BC-5F-F4 (hex) ASRock Incorporation +BC5FF4 (base 16) ASRock Incorporation + 2F.,No.37, Sec.2, Jhongyang S.Rd., Beitou Distric, + Taipei 112 + TW + +E8-B4-AE (hex) Shenzhen C&D Electronics Co.,Ltd +E8B4AE (base 16) Shenzhen C&D Electronics Co.,Ltd + Building 2, Xia You Song Mountain Top Industrial District, You Song Village + Shenzhen Guang Dong 518000 + CN + +50-FA-AB (hex) L-tek d.o.o. +50FAAB (base 16) L-tek d.o.o. + Obrtna cesta 18 + Sentjernej 8310 + SI + +38-91-FB (hex) Xenox Holding BV +3891FB (base 16) Xenox Holding BV + Lingedijk 80 + Tricht Gelderland 4196 HC + NL + +A8-E0-18 (hex) Nokia Corporation +A8E018 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +78-1D-FD (hex) Jabil Inc +781DFD (base 16) Jabil Inc + 10500 Dr. Martin Luther King Jr. St. N. + St. Petersburg Florida 33716 + US + +18-AE-BB (hex) Siemens Convergence Creators GmbH&Co.KG +18AEBB (base 16) Siemens Convergence Creators GmbH&Co.KG + Communications, Media and Technology + Hamburg D-21079 + DE + +B0-BD-A1 (hex) ZAKLAD ELEKTRONICZNY SIMS +B0BDA1 (base 16) ZAKLAD ELEKTRONICZNY SIMS + POD SKARPA 51A + BYDGOSZCZ KUJAWSKO-POMORSKIE 85-796 + PL + +70-B2-65 (hex) Hiltron s.r.l. +70B265 (base 16) Hiltron s.r.l. + Strada Provinciale di Caserta, 218 + Naples 80144 + IT + +CC-C6-2B (hex) Tri-Systems Corporation +CCC62B (base 16) Tri-Systems Corporation + 3-27-8 TRS Building 3F + Hachioji Tokyo 192-0904 + JP + +D8-C0-68 (hex) Netgenetech.co.,ltd. +D8C068 (base 16) Netgenetech.co.,ltd. + 704, Hanlim Venture Town., #689-6, + Gunpo-si 435-862 + KR + +60-11-99 (hex) Siama Systems Inc +601199 (base 16) Siama Systems Inc + 410 Saint-Nicolas Street + Montreal Quebec H2Y 2P5 + CA + +6C-81-FE (hex) Mitsuba Corporation +6C81FE (base 16) Mitsuba Corporation + 1-2681 + Kiryu Gunma 376-8555 + JP + +C0-27-B9 (hex) Beijing National Railway Research & Design Institute of Signal & Communication Co., Ltd. +C027B9 (base 16) Beijing National Railway Research & Design Institute of Signal & Communication Co., Ltd. + Building No.18, Huayuan YiLi,Fengtai District, + Beijing 100073 + CN + +14-74-11 (hex) RIM +147411 (base 16) RIM + Phillip Street + Waterloo Ontario N2L 3W8 + CA + +F8-A9-DE (hex) PUISSANCE PLUS +F8A9DE (base 16) PUISSANCE PLUS + 222 Impasse Louis Lépine + Montauban 82000 + FR + +A8-8C-EE (hex) MicroMade Galka i Drozdz sp.j. +A88CEE (base 16) MicroMade Galka i Drozdz sp.j. + ul. Wieniawskiego 16 + Pila Wielkopolskie 64-920 + PL + +DC-2B-66 (hex) InfoBLOCK S.A. de C.V. +DC2B66 (base 16) InfoBLOCK S.A. de C.V. + Hegel 229 - 10 + Mexico City Distrito Federal 11570 + MX + +B8-87-1E (hex) Good Mind Industries Co., Ltd. +B8871E (base 16) Good Mind Industries Co., Ltd. + 22, Ta Yeou 2nd St, + Kaohsiung 831 + TW + +D4-F0-27 (hex) Trust Power Ltd. +D4F027 (base 16) Trust Power Ltd. + 13 Berkley Street + London W1J 8DU + GB + +04-55-CA (hex) BriView (Xiamen) Corp. +0455CA (base 16) BriView (Xiamen) Corp. + NO.1998 West of Fangshan Road,Xiang An Branch,Torch Hi-tech lndustrial Development Zone, + Xiamen city Fujian Province 361102 + CN + +14-35-B3 (hex) Future Designs, Inc. +1435B3 (base 16) Future Designs, Inc. + 2702 Triana Blvd + Huntsville AL 35805 + US + +AC-93-2F (hex) Nokia Corporation +AC932F (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +00-54-AF (hex) Continental Automotive Systems Inc. +0054AF (base 16) Continental Automotive Systems Inc. + 21440 W. Lake Cook Rd. + Deer Park IL 60010 + US + +AC-CA-BA (hex) Midokura Co., Ltd. +ACCABA (base 16) Midokura Co., Ltd. + 7th Floor Azabudai Hinoki building + Tokyo 106-0041 + JP + +0C-81-12 (hex) Private +0C8112 (base 16) Private + +9C-95-F8 (hex) SmartDoor Systems, LLC +9C95F8 (base 16) SmartDoor Systems, LLC + 5711-A Center Lane + Falls Church Virginia 22041 + US + +78-19-F7 (hex) Juniper Networks +7819F7 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +64-09-4C (hex) Beijing Superbee Wireless Technology Co.,Ltd +64094C (base 16) Beijing Superbee Wireless Technology Co.,Ltd + B7,Science-Tech Fortune Center, + Beijing 100192 + CN + +7C-7D-41 (hex) Jinmuyu Electronics Co., Ltd. +7C7D41 (base 16) Jinmuyu Electronics Co., Ltd. + Room 132, Building 16, Tianqiaowan + Beijing 101101 + CN + +4C-14-80 (hex) NOREGON SYSTEMS, INC +4C1480 (base 16) NOREGON SYSTEMS, INC + 100 N. MAIN ST. SUITE 2200 + WINSTON - SALEM NC 27101 + US + +A4-85-6B (hex) Q Electronics Ltd +A4856B (base 16) Q Electronics Ltd + Beck House, Hawksworth Road + Leeds West Yorkshire LS18 4JP + GB + +20-D5-AB (hex) Korea Infocom Co.,Ltd. +20D5AB (base 16) Korea Infocom Co.,Ltd. + 5F Wintek B/D 511 + Uiwang Kyunggi-Do 437-830 + KR + +0C-F3-EE (hex) EM Microelectronic +0CF3EE (base 16) EM Microelectronic + Rue des Sors 3 + Marin-Epagnier Neuchatel 2074 + CH + +64-D1-A3 (hex) Sitecom Europe BV +64D1A3 (base 16) Sitecom Europe BV + Linatebaan 101 + Rotterdam Zuid Holland 3045 AH + NL + +F4-3E-9D (hex) Benu Networks, Inc. +F43E9D (base 16) Benu Networks, Inc. + 300 Rd., Suite 110 + Billerica MA 01821 + US + +04-E2-F8 (hex) AEP Ticketing solutions srl +04E2F8 (base 16) AEP Ticketing solutions srl + Via dei Colli, 240 + Signa Firenze 50058 + IT + +EC-9E-CD (hex) Artesyn Embedded Technologies +EC9ECD (base 16) Artesyn Embedded Technologies + 2900 S. Diablo Way Suite 190 + Tempe Arizona 85282 + US + +8C-51-05 (hex) Shenzhen ireadygo Information Technology CO.,LTD. +8C5105 (base 16) Shenzhen ireadygo Information Technology CO.,LTD. + Room 02,11F,DESAY Building,No.1 Hi-Tech South Road + Shenzhen 518057 + CN + +C8-20-8E (hex) Storagedata +C8208E (base 16) Storagedata + Randstad 22117 + Almere Flevoland 1316BW + NL + +5C-5E-AB (hex) Juniper Networks +5C5EAB (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +9C-80-7D (hex) SYSCABLE Korea Inc. +9C807D (base 16) SYSCABLE Korea Inc. + 2F KAMA Bldg 1461-15 Secho-3dong Seocho-Gu + Seoul 137-720 + KR + +28-E2-97 (hex) Shanghai InfoTM Microelectronics Co.,Ltd. +28E297 (base 16) Shanghai InfoTM Microelectronics Co.,Ltd. + building 11,NO.115,lane 572,BiBo Road, + ShangHai 201203 + CN + +34-B5-71 (hex) PLDS +34B571 (base 16) PLDS + Schanzenfeldstrasse 2 + Wetzlar Hessen 35578 + DE + +3C-74-37 (hex) RIM +3C7437 (base 16) RIM + Phillip Street + Waterloo Ontario N2L 3W8 + CA + +EC-92-33 (hex) Eddyfi NDT Inc +EC9233 (base 16) Eddyfi NDT Inc + 2800, Louis-Lumiere street + Quebec Quebec G1P 0A4 + CA + +74-38-89 (hex) ANNAX Anzeigesysteme GmbH +743889 (base 16) ANNAX Anzeigesysteme GmbH + Wettersteinstrasse 18 + Taufkirchen Bavaria 82024 + DE + +44-D2-CA (hex) Anvia TV Oy +44D2CA (base 16) Anvia TV Oy + PO Box 29 + SEINAJOKI FIN60101 + FI + +38-6E-21 (hex) Wasion Group Ltd. +386E21 (base 16) Wasion Group Ltd. + No.468 West Tongzipo Road High-Tech Industrial Development Zone + Changsha City Hunan Province, 410205 + CN + +28-72-F0 (hex) ATHENA +2872F0 (base 16) ATHENA + 42 RUE MONGE + PARIS 75005 + FR + +1C-19-DE (hex) eyevis GmbH +1C19DE (base 16) eyevis GmbH + Hundsschleestrasse 23 + Reutlingen BW 72766 + DE + +60-9E-64 (hex) Vivonic GmbH +609E64 (base 16) Vivonic GmbH + Kurfuerst-Eppstein-Ring 4 + Sailauf Bayern 63877 + DE + +BC-15-A6 (hex) Taiwan Jantek Electronics,Ltd. +BC15A6 (base 16) Taiwan Jantek Electronics,Ltd. + 6F-1,No.1 Wu-Chuan 1St. Rd,Wu-Ku Industrial Park, + Sinchwang City Taipei Hsien 24892 + TW + +DC-DE-CA (hex) Akyllor +DCDECA (base 16) Akyllor + Britannia House, 22, 2F, Cator Road + Bandar Seri Begawan BS 8811 + BN + +A0-AA-FD (hex) EraThink Technologies Corp. +A0AAFD (base 16) EraThink Technologies Corp. + 289 Bisheng Road Building 4,Floor 4 + Shanghai 201204 + CN + +6C-A9-06 (hex) Telefield Ltd +6CA906 (base 16) Telefield Ltd + Flat D,2/F., Valiant Industrial Centre,2-12 Au Pui Wan Street, + Hongkong 852 + CN + +78-22-3D (hex) Affirmed Networks +78223D (base 16) Affirmed Networks + 35 Nagog Park + Acton MA 01720 + US + +3C-02-B1 (hex) Creation Technologies LP +3C02B1 (base 16) Creation Technologies LP + 3939 North Fraser Way + Burnaby BC V5J 5J2 + CA + +E4-41-E6 (hex) Ottec Technology GmbH +E441E6 (base 16) Ottec Technology GmbH + Bünteweg 33 + Gehrden Lower Saxony 30989 + DE + +BC-71-C1 (hex) XTrillion, Inc. +BC71C1 (base 16) XTrillion, Inc. + 1-12-3-4F + Chiyoda-ku Tokyo 101-0041 + JP + +E0-E8-E8 (hex) Olive Telecommunication Pvt. Ltd +E0E8E8 (base 16) Olive Telecommunication Pvt. Ltd + 862, Udyog Vihar + Gurgaon Haryana 122016 + IN + +60-52-D0 (hex) FACTS Engineering +6052D0 (base 16) FACTS Engineering + 8049 Photonics Drive + New Port Richey FL 34655 + US + +B0-89-91 (hex) LGE +B08991 (base 16) LGE + 60-39 , Kasan -dong , Gumcheon-gu. + Seoul 153-801 + KR + +30-14-2D (hex) Piciorgros GmbH +30142D (base 16) Piciorgros GmbH + Claudiastrasse 5 + Cologne NRW 51149 + DE + +50-AF-73 (hex) Shenzhen Bitland Information Technology Co., Ltd. +50AF73 (base 16) Shenzhen Bitland Information Technology Co., Ltd. + 1-4F,44 Building,Tanglang Industrial Park and 1-6F,#7 Building,XiLi Tongfuyu Industrial Town,Nanshan District + Shenzhen Guangdong 518055 + CN + +5C-9A-D8 (hex) FUJITSU LIMITED +5C9AD8 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +A4-C0-E1 (hex) Nintendo Co., Ltd. +A4C0E1 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +4C-3B-74 (hex) VOGTEC(H.K.) Co., Ltd +4C3B74 (base 16) VOGTEC(H.K.) Co., Ltd + Flat 01, 2/F, On Ning Building, + Hong Kong 999077 + CN + +68-43-52 (hex) Bhuu Limited +684352 (base 16) Bhuu Limited + Office 1, 465 Mt Eden Road + Auckland 1023 + NZ + +EC-E9-0B (hex) SISTEMA SOLUCOES ELETRONICAS LTDA - EASYTECH +ECE90B (base 16) SISTEMA SOLUCOES ELETRONICAS LTDA - EASYTECH + RUA GUERRA DE AGUIAR, 220 + São Paulo SP 08275-260 + BR + +A0-8C-9B (hex) Xtreme Technologies Corp +A08C9B (base 16) Xtreme Technologies Corp + 200 4616 Valiant Dr NW + Calgary AB T3A0X9 + CA + +A8-39-44 (hex) Actiontec Electronics, Inc +A83944 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +74-E0-6E (hex) Ergophone GmbH +74E06E (base 16) Ergophone GmbH + Temmlerstrasse 5 + Marburg Hessen 35039 + DE + +0C-F0-B4 (hex) Globalsat International Technology Ltd +0CF0B4 (base 16) Globalsat International Technology Ltd + 17th floor,China Youse Building,No.6013 Shennan Avenue,Futian District, + Shenzhen Guangdong 518040 + CN + +48-DF-1C (hex) Wuhan NEC Fibre Optic Communications industry Co. Ltd +48DF1C (base 16) Wuhan NEC Fibre Optic Communications industry Co. Ltd + 3rd Road Guanshan, + Wuhan Hubei 430074 + CN + +D4-9C-8E (hex) University of FUKUI +D49C8E (base 16) University of FUKUI + 3-9-1 Bunkyo + Fukui City 910-8507 + JP + +F8-F0-14 (hex) RackWare Inc. +F8F014 (base 16) RackWare Inc. + 44053 Fremont Blvd. + Fremont CA 94538 + US + +28-26-A6 (hex) PBR electronics GmbH +2826A6 (base 16) PBR electronics GmbH + Berliner Strasse 5 + Sandhausen Baden Wuertemmberg 69207 + DE + +B4-28-F1 (hex) E-Prime Co., Ltd. +B428F1 (base 16) E-Prime Co., Ltd. + Rm1207, Kolon Science Valley, 811, + Seoul 152050 + KR + +C0-12-42 (hex) Alpha Security Products +C01242 (base 16) Alpha Security Products + 10715 Sikes Place, Ste. 200 + Charlotte NC 28277 + US + +BC-20-BA (hex) Inspur (Shandong) Electronic Information Co., Ltd +BC20BA (base 16) Inspur (Shandong) Electronic Information Co., Ltd + No.1036 Shunya Rd. + Jinan Shandong 250101 + CN + +1C-FE-A7 (hex) IDentytech Solutins Ltd. +1CFEA7 (base 16) IDentytech Solutins Ltd. + 14 Hadaya Street + Ramat- Hasharon 47226 + IL + +30-4E-C3 (hex) Tianjin Techua Technology Co., Ltd. +304EC3 (base 16) Tianjin Techua Technology Co., Ltd. + 12-1-1401 Tianlinyuan Fulicheng Gulouxi Road,Nankai District + Tianjin 300101 + CN + +B4-CF-DB (hex) Shenzhen Jiuzhou Electric Co.,LTD +B4CFDB (base 16) Shenzhen Jiuzhou Electric Co.,LTD + 6F,Jiuzhou Electric Building,Southern No.12RD.,Hi-Tech Industrial Park,Nanshan District, + Shenzhen Guangdong 518057 + CN + +FC-D4-F2 (hex) The Coca Cola Company +FCD4F2 (base 16) The Coca Cola Company + One Coca Cola Plaza + Atlanta GA 30313 + US + +5C-6A-7D (hex) KENTKART EGE ELEKTRONIK SAN. VE TIC. LTD. STI. +5C6A7D (base 16) KENTKART EGE ELEKTRONIK SAN. VE TIC. LTD. STI. + 1370 SK, NO:42/304, + MONTRO IZMIR 35230 + TR + +44-59-9F (hex) Criticare Systems, Inc +44599F (base 16) Criticare Systems, Inc + 20925 Crossroads Circle + Waukasha WI 53186 + US + +3C-2F-3A (hex) SFORZATO Corp. +3C2F3A (base 16) SFORZATO Corp. + 863 + HINO-SHI TOKYO 191-0022 + JP + +74-CE-56 (hex) Packet Force Technology Limited Company +74CE56 (base 16) Packet Force Technology Limited Company + 2F., No.25, Sec. 1, Shuangshi Rd., Central Dist., + Taichung 40046 + TW + +AC-2F-A8 (hex) Humannix Co.,Ltd. +AC2FA8 (base 16) Humannix Co.,Ltd. + #402, 98-4, Songpa-Dong, Songpa-Gu + Seoul 138-170 + KR + +10-64-E2 (hex) ADFweb.com s.r.l. +1064E2 (base 16) ADFweb.com s.r.l. + Strada Nuova, 17 + Mareno di Piave Treviso 31010 + IT + +CC-34-D7 (hex) GEWISS S.P.A. +CC34D7 (base 16) GEWISS S.P.A. + VIA ALESSANDRO VOLTA 1 + CENATE SOTTO 24069 + IT + +F0-2A-61 (hex) Waldo Networks, Inc. +F02A61 (base 16) Waldo Networks, Inc. + 4505 Spicewood Springs Rd + Austin Texas 78759 + US + +C8-A7-0A (hex) Verizon Business +C8A70A (base 16) Verizon Business + One Digex Plaza + Beltsville MD 20705 + US + +60-DA-23 (hex) Estech Co.,Ltd +60DA23 (base 16) Estech Co.,Ltd + #717,133-1,Sangdaewon-Dong + Seongnam-Si Gyeonggi-Do 462-120 + KR + +44-DC-CB (hex) SEMINDIA SYSTEMS PVT LTD +44DCCB (base 16) SEMINDIA SYSTEMS PVT LTD + 1006/13, Sy No.49/1&3, 7th Mile, A.M Indl Estate, + Bangalore Karnataka 560068 + IN + +A0-DE-05 (hex) JSC Irbis-T +A0DE05 (base 16) JSC Irbis-T + 39, Gorodskoy lane + Tula 300012 + RU + +08-17-F4 (hex) IBM Corp +0817F4 (base 16) IBM Corp + 2051 Mission College Blvd + Santa Clara CA 95054 + US + +CC-D8-11 (hex) Aiconn Technology Corporation +CCD811 (base 16) Aiconn Technology Corporation + 5F, NO. 9, Alley 2, Lane 35, Ji-Hu Rd., Nei-Hu, + Taipei City 11494 + TW + +F4-38-14 (hex) Shanghai Howell Electronic Co.,Ltd +F43814 (base 16) Shanghai Howell Electronic Co.,Ltd + 5-5/F, Bldg.1, No.788 Fengzhen Rd., + Shanghai 200434 + CN + +90-61-0C (hex) Fida International (S) Pte Ltd +90610C (base 16) Fida International (S) Pte Ltd + Blk 16, Kallang Place + 339156 + SG + +3C-5F-01 (hex) Synerchip Co., Ltd. +3C5F01 (base 16) Synerchip Co., Ltd. + c/o Synerchip USA Corp. + Sunnyvale CA 94085 + US + +EC-BB-AE (hex) Digivoice Tecnologia em Eletronica Ltda +ECBBAE (base 16) Digivoice Tecnologia em Eletronica Ltda + Alameda Juru, 159 - Torreo + Barueri São Paulo 06455-010 + BR + +34-A1-83 (hex) AWare, Inc +34A183 (base 16) AWare, Inc + 614 Massachusetts Ave. + Cambridge MA 02139 + US + +98-73-C4 (hex) Sage Electronic Engineering LLC +9873C4 (base 16) Sage Electronic Engineering LLC + 201 Terry St. + Longmont CO 80501 + US + +B4-01-42 (hex) GCI Science & Technology Co.,LTD +B40142 (base 16) GCI Science & Technology Co.,LTD + No.381,xingangzhong road , + GuangZhou GuangDong 510310 + CN + +74-0A-BC (hex) LightwaveRF Technology Ltd +740ABC (base 16) LightwaveRF Technology Ltd + Innovation Campus Birmingham + Faraday Wharf, Holt Street Birmingham B4 4BB + GB + +10-A1-3B (hex) FUJIKURA RUBBER LTD. +10A13B (base 16) FUJIKURA RUBBER LTD. + 1-840,Mihashi,Omiya + Saitama 330-0856 + JP + +F4-E1-42 (hex) Delta Elektronika BV +F4E142 (base 16) Delta Elektronika BV + Vissersdijk 4 + Zierikzee 4301 ND + NL + +AC-81-12 (hex) Gemtek Technology Co., Ltd. +AC8112 (base 16) Gemtek Technology Co., Ltd. + No. 1 Jen Ai Road Hsinchu Industrial Park Hukou, Hsinchu 30352 TAIWAN, REPUBLIC OF CHINA + Hsinchu TAIWAN 30352 + TW + +68-63-59 (hex) Advanced Digital Broadcast SA +686359 (base 16) Advanced Digital Broadcast SA + Avenue de Tournay 7 + Pregny-Chambesy 1292 + CH + +28-06-1E (hex) NINGBO GLOBAL USEFUL ELECTRIC CO.,LTD +28061E (base 16) NINGBO GLOBAL USEFUL ELECTRIC CO.,LTD + No.88,Kechuang South Road, + Ningbo Zhejiang 315000 + CN + +64-E8-E6 (hex) global moisture management system +64E8E6 (base 16) global moisture management system + 11132 broad river road + irmo sc 29063 + US + +E0-D1-0A (hex) Katoudenkikougyousyo co ltd +E0D10A (base 16) Katoudenkikougyousyo co ltd + oujihontyou1-4-13 + kita-ku tokyo-to 114-0022 + JP + +C4-4B-44 (hex) Omniprint Inc. +C44B44 (base 16) Omniprint Inc. + 1923 East Deere Ave. + Santa Ana CA 92705 + US + +18-92-2C (hex) Virtual Instruments +18922C (base 16) Virtual Instruments + 100 Enterprise Way + Scotts Valley CA 95066 + US + +A4-9B-13 (hex) Digital Check +A49B13 (base 16) Digital Check + 630 Dundee Rd. Suite 210 + Northbrook IL 60062 + US + +C8-EE-08 (hex) TANGTOP TECHNOLOGY CO.,LTD +C8EE08 (base 16) TANGTOP TECHNOLOGY CO.,LTD + 1F,NO.153,Ligon St.,Beitou District + Taipei City 112 + TW + +74-72-F2 (hex) Chipsip Technology Co., Ltd. +7472F2 (base 16) Chipsip Technology Co., Ltd. + 8F-1, No.186, Jian-Yi Road, ChungHo City, + Taipei 235 + TW + +48-C8-B6 (hex) SysTec GmbH +48C8B6 (base 16) SysTec GmbH + Ludwig-Erhard-Strasse 6 + Bergheim-Glessen NRW 50129 + DE + +3C-62-78 (hex) SHENZHEN JETNET TECHNOLOGY CO.,LTD. +3C6278 (base 16) SHENZHEN JETNET TECHNOLOGY CO.,LTD. + Room 403,4th floor,Qinghua Information Building,Keyuan Road,North District of Tech-Park,Nanshan District + Shenzhen Guangdong 518057 + CN + +C8-D5-FE (hex) Shenzhen Zowee Technology Co., Ltd +C8D5FE (base 16) Shenzhen Zowee Technology Co., Ltd + Block 5, Science and Technology Industrial Park of + Shenzhen GuangDong 518055 + CN + +2C-30-68 (hex) Pantech Co.,Ltd +2C3068 (base 16) Pantech Co.,Ltd + 110-1 Ongjeong-Ri, Tongjin-Eup + Gimpo-Si Gyounggi-Do 415-865 + KR + +00-BD-27 (hex) Exar Corp. +00BD27 (base 16) Exar Corp. + 48720 Kato Rd. + Fremont CA 94538 + US + +5C-40-58 (hex) Jefferson Audio Video Systems, Inc. +5C4058 (base 16) Jefferson Audio Video Systems, Inc. + 13020 Middletown Industrial Blvd. + Louisville Kentucky 40223 + US + +58-D0-8F (hex) IEEE 1904.1 Working Group +58D08F (base 16) IEEE 1904.1 Working Group + 1351 Redwood Way, + Petaluma CA 94954 + US + +6C-9C-E9 (hex) Nimble Storage +6C9CE9 (base 16) Nimble Storage + 2645 Zanker Road + San Jose CA 95134 + US + +CC-09-C8 (hex) IMAQLIQ LTD +CC09C8 (base 16) IMAQLIQ LTD + Obvodny Canal 93A + St.Petersburg 191119 + RU + +9C-45-63 (hex) DIMEP Sistemas +9C4563 (base 16) DIMEP Sistemas + Av. Mofarrej, 840 + São Paulo 05311000 + BR + +D4-3D-67 (hex) Carma Industries Inc. +D43D67 (base 16) Carma Industries Inc. + 132 Walsh Road + Lindsay Ontario K9V 4R3 + CA + +E0-A6-70 (hex) Nokia Corporation +E0A670 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +58-DB-8D (hex) Fast Co., Ltd. +58DB8D (base 16) Fast Co., Ltd. + 2-11-1 Iwamotocho + Chiyoda-ku Tokyo 101-0032 + JP + +E4-46-BD (hex) C&C TECHNIC TAIWAN CO., LTD. +E446BD (base 16) C&C TECHNIC TAIWAN CO., LTD. + ROOM6 13F, NO.2,Jian 8th ROAD + Taipei Chungho City, 23511 + TW + +8C-DD-8D (hex) Wifly-City System Inc. +8CDD8D (base 16) Wifly-City System Inc. + 4F.,-1,NO 106,RUEIGUANG Rd.Neihu District, + Taipei City 114 + TW + +20-A2-E7 (hex) Lee-Dickens Ltd +20A2E7 (base 16) Lee-Dickens Ltd + Rushton Rd + Kettering Northamptonshire NN14 2QW + GB + +FC-ED-B9 (hex) Arrayent +FCEDB9 (base 16) Arrayent + 570 El Camino Real #150-419 + Redwood City CA 94063 + US + +44-ED-57 (hex) Longicorn, inc. +44ED57 (base 16) Longicorn, inc. + Rm1001-2, 10F, Byuksan Digital Valley1 + Seoul 152-775 + KR + +EC-98-C1 (hex) Beijing Risbo Network Technology Co.,Ltd +EC98C1 (base 16) Beijing Risbo Network Technology Co.,Ltd + 1/F Yinyan Building 2A,No.23 Anningzhuangdonglu Haidian District + Beijing 100085 + CN + +38-A9-5F (hex) Actifio Inc +38A95F (base 16) Actifio Inc + 225 Wyman Street + Waltham MA 02451 + IN + +F4-DC-DA (hex) Zhuhai Jiahe Communication Technology Co., limited +F4DCDA (base 16) Zhuhai Jiahe Communication Technology Co., limited + 4/F,East Of B5,Sourth Software Park,Tangjia, + Zhuhai Guangdong 519085 + CN + +E8-04-62 (hex) Cisco Systems, Inc +E80462 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +DC-D0-F7 (hex) Bentek Systems Ltd. +DCD0F7 (base 16) Bentek Systems Ltd. + 315 - 3750 46th Ave. SE + Calgary AB T2B 0L1 + CA + +D4-A9-28 (hex) GreenWave Reality Inc +D4A928 (base 16) GreenWave Reality Inc + 39 Parker + Irvine California 92618 + US + +E0-62-90 (hex) Jinan Jovision Science & Technology Co., Ltd. +E06290 (base 16) Jinan Jovision Science & Technology Co., Ltd. + Room 407, Tower C, Cyber Port Building, + Jinan Shandong 250013 + CN + +10-0E-2B (hex) NEC CASIO Mobile Communications +100E2B (base 16) NEC CASIO Mobile Communications + 1753,Shimonumabe + Kawasaki-shi Kanagawa 211-8666 + JP + +70-E1-39 (hex) 3view Ltd +70E139 (base 16) 3view Ltd + 168-172 Old Street + London EC1V 9BP + GB + +18-42-2F (hex) Alcatel Lucent +18422F (base 16) Alcatel Lucent + Via Energy Park, 14 + Vimercate MB 20871 + IT + +C4-63-54 (hex) U-Raku, Inc. +C46354 (base 16) U-Raku, Inc. + 401-1 Deba + Ritto-shi Shiga 520-3041 + JP + +40-5F-BE (hex) RIM +405FBE (base 16) RIM + 295 Phillip Street + Waterloo Ontario N2L 3W8 + CA + +68-54-F5 (hex) enLighted Inc +6854F5 (base 16) enLighted Inc + 1451 Grant Rd + Mountain View CA 94040 + US + +7C-B5-42 (hex) ACES Technology +7CB542 (base 16) ACES Technology + #928, Hyundai Venture Ville + Seoul 135-539 + KR + +90-54-46 (hex) TES ELECTRONIC SOLUTIONS +905446 (base 16) TES ELECTRONIC SOLUTIONS + Immeuble Odyssee + BRUZ 35170 + FR + +54-4A-05 (hex) wenglor sensoric gmbh +544A05 (base 16) wenglor sensoric gmbh + wenglor Str. 3 + Tettnang 88069 + DE + +98-E1-65 (hex) Accutome +98E165 (base 16) Accutome + 3222 Phoenixville Pike + Malvern PA 19355 + US + +78-57-12 (hex) Mobile Integration Workgroup +785712 (base 16) Mobile Integration Workgroup + 4580 Klahanie DR SE STE 106 + Issaquah WA 98029 + US + +38-0A-0A (hex) Sky-City Communication and Electronics Limited Company +380A0A (base 16) Sky-City Communication and Electronics Limited Company + 1109, Building A, Kefa Industrial park, Huanguan south road, Guanlan, + Shenzhen Guangdong 518110 + CN + +0C-D6-96 (hex) Amimon Ltd +0CD696 (base 16) Amimon Ltd + 2 Maskit st + Herzlia 46733 + IL + +F4-DC-4D (hex) Beijing CCD Digital Technology Co., Ltd +F4DC4D (base 16) Beijing CCD Digital Technology Co., Ltd + 107 Dongsi North Street, Dongcheng District, + Beijing 100007 + CN + +40-13-D9 (hex) Global ES +4013D9 (base 16) Global ES + Sinimäentie 8 b + Espoo 02631 + FI + +AC-4F-FC (hex) SVS-VISTEK GmbH +AC4FFC (base 16) SVS-VISTEK GmbH + Muehlbachstraße 20 + Seefeld BY 82229 + DE + +B4-37-41 (hex) Consert, Inc. +B43741 (base 16) Consert, Inc. + 4700 Falls of Neuse Rd. + Raleigh NC 27609 + US + +94-85-7A (hex) Evantage Industries Corp +94857A (base 16) Evantage Industries Corp + 815 Bridge St. W. + Waterloo Ontario N2V 2M7 + CA + +40-83-DE (hex) Zebra Technologies Inc +4083DE (base 16) Zebra Technologies Inc + 475 Half Day Road + Lincolnshire IL 60069 + US + +88-97-DF (hex) Entrypass Corporation Sdn. Bhd. +8897DF (base 16) Entrypass Corporation Sdn. Bhd. + No.40, Jalan TPP 1/10, + Puchong Selangor Darul Ehsan 47100 + MY + +24-AF-54 (hex) NEXGEN Mediatech Inc. +24AF54 (base 16) NEXGEN Mediatech Inc. + 8F No. 150, Jianyi Rd., + Chung Ho Taipei Hsien 235 + TW + +F0-F8-42 (hex) KEEBOX, Inc. +F0F842 (base 16) KEEBOX, Inc. + 10 Poppy Trail + Rolling Hills California 90274 + US + +DC-4E-DE (hex) SHINYEI TECHNOLOGY CO., LTD. +DC4EDE (base 16) SHINYEI TECHNOLOGY CO., LTD. + 6-5-2, MINATOJIMA-MINAMIMACHI, CHUO-KU + KOBE HYOGO 650-0047 + JP + +E0-87-B1 (hex) Nata-Info Ltd. +E087B1 (base 16) Nata-Info Ltd. + 28, Prokhorova str. + Yoshkar-Ola Republic Mari-El 424007 + RU + +44-7C-7F (hex) Innolight Technology Corporation +447C7F (base 16) Innolight Technology Corporation + 3 Results Way + Cupertino CA 95014 + US + +D4-96-DF (hex) SUNGJIN C&T CO.,LTD +D496DF (base 16) SUNGJIN C&T CO.,LTD + Daeya + Sheung Gyeonggi 429-809 + KR + +5C-86-4A (hex) Secret Labs LLC +5C864A (base 16) Secret Labs LLC + 315 Bleecker St #308 + New York NY 10014 + US + +F0-AD-4E (hex) Globalscale Technologies, Inc. +F0AD4E (base 16) Globalscale Technologies, Inc. + 5F, No. 2 Building, Minxing Industrial Park + Shenzhen Guangdong 518109 + CN + +90-3D-5A (hex) Shenzhen Wision Technology Holding Limited +903D5A (base 16) Shenzhen Wision Technology Holding Limited + Room 26A, Jinrun Building, N0.6019, Shennan Rd., Futian District + Shenzhen Guangdong 518040 + CN + +7C-A2-9B (hex) D.SignT GmbH & Co. KG +7CA29B (base 16) D.SignT GmbH & Co. KG + Marktstraße 10 + Kerken 47647 + DE + +A0-40-41 (hex) SAMWONFA Co.,Ltd. +A04041 (base 16) SAMWONFA Co.,Ltd. + 470-5, Moonhyun2-Dong + Busan 608-042 + KR + +40-40-6B (hex) Icomera +40406B (base 16) Icomera + Vikingsgatan 3 + Göteborg 41104 + SE + +6C-22-AB (hex) Ainsworth Game Technology +6C22AB (base 16) Ainsworth Game Technology + 10 Holker Street + Newington New South Wales 2127 + AU + +30-18-CF (hex) DEOS control systems GmbH +3018CF (base 16) DEOS control systems GmbH + Birkenallee 113 + Rheine NRW 48432 + DE + +08-FA-E0 (hex) Fohhn Audio AG +08FAE0 (base 16) Fohhn Audio AG + Hohes Gestade 3-7 + Nuertingen BW 72622 + DE + +58-B9-E1 (hex) Crystalfontz America, Inc. +58B9E1 (base 16) Crystalfontz America, Inc. + 12412 E. Saltese Ave. + Spokane Valley WA 99216 + US + +20-D9-06 (hex) Iota, Inc. +20D906 (base 16) Iota, Inc. + 2212 Queen Anne Ave. N., #348 + Seattle WA 98109 + US + +F4-55-95 (hex) HENGBAO Corporation LTD. +F45595 (base 16) HENGBAO Corporation LTD. + 8th Floor,Tower B,Xinsheng Mansion No.5 Financial Street, + Beijing 100140 + CN + +1C-3A-4F (hex) AccuSpec Electronics, LLC +1C3A4F (base 16) AccuSpec Electronics, LLC + 8140 Hawthorne Drive + Erie Pennsylvania 16509 + US + +9C-4E-20 (hex) Cisco Systems, Inc +9C4E20 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D8-75-33 (hex) Nokia Corporation +D87533 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +98-35-B8 (hex) Assembled Products Corporation +9835B8 (base 16) Assembled Products Corporation + 115 E. Linden + Rogers Arkansas 72756 + US + +28-89-15 (hex) CashGuard Sverige AB +288915 (base 16) CashGuard Sverige AB + Finlandsgatan 16 + Kista 16474 + SE + +4C-5D-CD (hex) Oy Finnish Electric Vehicle Technologies Ltd +4C5DCD (base 16) Oy Finnish Electric Vehicle Technologies Ltd + Majavantie 10 + TUUSULA FI-04320 + FI + +70-D5-7E (hex) Scalar Corporation +70D57E (base 16) Scalar Corporation + 1F San-Ei Bldg + Shinjuku-ku Tokyo 160-0023 + JP + +B0-E3-9D (hex) CAT SYSTEM CO.,LTD. +B0E39D (base 16) CAT SYSTEM CO.,LTD. + 3-147-27 Higasi-sinmachi Hirohata-ku + Himeji Hyogo 671-1121 + JP + +7C-2E-0D (hex) Blackmagic Design +7C2E0D (base 16) Blackmagic Design + 11 Gateway Court + Melbourne Victoria 3207 + AU + +18-0C-77 (hex) Westinghouse Electric Company, LLC +180C77 (base 16) Westinghouse Electric Company, LLC + 1000 Westinghouse Drive + Cranberry Township PA 16066 + US + +68-CA-00 (hex) Octopus Systems Limited +68CA00 (base 16) Octopus Systems Limited + 36/F, 148 Electric Road + + HK + +E0-58-9E (hex) Laerdal Medical +E0589E (base 16) Laerdal Medical + Tanke Svilandsgate 30 + Stavanger 4002 + NO + +0C-1D-C2 (hex) SeAH Networks +0C1DC2 (base 16) SeAH Networks + 9F, IT Venture Tower East Wing 78 Garak-Dong, + Seoul Songpa-gu 138-950 + KR + +54-75-D0 (hex) Cisco Systems, Inc +5475D0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +60-89-B7 (hex) KAEL MÜHENDİSLİK ELEKTRONİK TİCARET SANAYİ LİMİTED ŞİRKETİ +6089B7 (base 16) KAEL MÜHENDİSLİK ELEKTRONİK TİCARET SANAYİ LİMİTED ŞİRKETİ + Atatürk Mah. 78 sokak ,No:10, Büyükalan Mevkii + Izmir Aegean 35175 + TR + +30-52-5A (hex) NST Co., LTD +30525A (base 16) NST Co., LTD + RM301,Daeryung Techno Town 2, 569-21 + Seoul 153-771 + KR + +2C-A7-80 (hex) True Technologies Inc. +2CA780 (base 16) True Technologies Inc. + R476, AngelCity 1st, + Seongnam, Kyungki 463-862 + KR + +7C-6F-06 (hex) Caterpillar Trimble Control Technologies +7C6F06 (base 16) Caterpillar Trimble Control Technologies + 5475 Kellenburger Rd. + Dayton OH 45424 + US + +60-12-83 (hex) TSB REAL TIME LOCATION SYSTEMS S.L. +601283 (base 16) TSB REAL TIME LOCATION SYSTEMS S.L. + Ronda Auguste y Louis Lumière 23, Nave 13 + Parque Tecnológico de Valencia Paterna (Valencia) 46980 + ES + +98-DC-D9 (hex) UNITEC Co., Ltd. +98DCD9 (base 16) UNITEC Co., Ltd. + 1-2-1-Shinyokohama + Yokohama-shi Kanagawa 222-0033 + JP + +C0-CF-A3 (hex) Creative Electronics & Software, Inc. +C0CFA3 (base 16) Creative Electronics & Software, Inc. + 650 Sundown Road + South Elgin IL 60177 + US + +94-23-6E (hex) Shenzhen Junlan Electronic Ltd +94236E (base 16) Shenzhen Junlan Electronic Ltd + Block C,No.2 Industrial District, Fuyuan, Tangwei,Fuyong, Bao'an + Shenzhen Guangdong 518103 + CN + +10-E6-AE (hex) Source Technologies, LLC +10E6AE (base 16) Source Technologies, LLC + 2910 Whitehall Park Drive + Charlotte NC 28273 + US + +FC-E1-92 (hex) Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd +FCE192 (base 16) Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd + No.28,Xinchuang Rd.,West Gaoxin District + Chengdu Sichuan 611731 + CN + +40-8A-9A (hex) TITENG CO., Ltd. +408A9A (base 16) TITENG CO., Ltd. + 7Fl. Shindo B/D 10 Garak-dong + Seoul 138-160 + KR + +F4-45-ED (hex) Portable Innovation Technology Ltd. +F445ED (base 16) Portable Innovation Technology Ltd. + 601-602, 6/F Park Building, + Kowloon + HK + +5C-E2-86 (hex) Nortel Networks +5CE286 (base 16) Nortel Networks + CARRETERA BASE AEREA # 5850 + Zapopan Jalisco 44130 + MX + +8C-64-0B (hex) Beyond Devices d.o.o. +8C640B (base 16) Beyond Devices d.o.o. + Trzaska cesta 515 + Brezovica pri Ljubljani SI-1351 + SI + +94-9C-55 (hex) Alta Data Technologies +949C55 (base 16) Alta Data Technologies + 4901 Rockaway Blvd, Building A + Rio Rancho NM 87124 + US + +D4-79-C3 (hex) Cameronet GmbH & Co. KG +D479C3 (base 16) Cameronet GmbH & Co. KG + Elberfelder Strasse 96 + Remscheid NRW 42853 + DE + +70-D5-E7 (hex) Wellcore Corporation +70D5E7 (base 16) Wellcore Corporation + 2870 Zanker Road + San Jose CA 95134 + US + +3C-F7-2A (hex) Nokia Corporation +3CF72A (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +54-5F-A9 (hex) Teracom Limited +545FA9 (base 16) Teracom Limited + B-84, Sector - 60, + Noida Uttar Pradesh 201 301 + IN + +6C-32-DE (hex) Indieon Technologies Pvt. Ltd. +6C32DE (base 16) Indieon Technologies Pvt. Ltd. + 601, Alpha 2, Gigaspace IT Park + Pune Maharastra 411014 + IN + +14-A6-2C (hex) S.M. Dezac S.A. +14A62C (base 16) S.M. Dezac S.A. + Vial Sant jordi S/N + Viladecavalls Barcelona 08232 + ES + +54-7F-EE (hex) Cisco Systems, Inc +547FEE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +AC-EA-6A (hex) GENIX INFOCOMM CO., LTD. +ACEA6A (base 16) GENIX INFOCOMM CO., LTD. + 2F, Daebo Bldg. #1009-34 + Seoul 153-829 + KR + +E0-BC-43 (hex) C2 Microsystems, Inc. +E0BC43 (base 16) C2 Microsystems, Inc. + 2833 Junction Avenue + San Jose California 95134 + US + +2C-A8-35 (hex) RIM +2CA835 (base 16) RIM + 295 Phillip Street + Waterloo Ontario N2L 3W8 + CA + +C4-1E-CE (hex) HMI Sources Ltd. +C41ECE (base 16) HMI Sources Ltd. + 5 Floor, Suite 2, 233 Hsin Yi Road, Section 4 + Taipei 10681 + TW + +A8-F4-70 (hex) Fujian Newland Communication Science Technologies Co.,Ltd. +A8F470 (base 16) Fujian Newland Communication Science Technologies Co.,Ltd. + Newland Science & Technology Park No.1 Rujiang West Rd., Mawei, + Fuzhou Fujian 350015 + CN + +8C-73-6E (hex) FUJITSU LIMITED +8C736E (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +B8-64-91 (hex) CK Telecom Ltd +B86491 (base 16) CK Telecom Ltd + Keji Avenue,Heyuan Hi-tech Development Zone + Heyuan Guangdong Province 517000 + CN + +50-F0-03 (hex) Open Stack, Inc. +50F003 (base 16) Open Stack, Inc. + Advanced Research Center #411 + Bun-Dang, Seong-Nam Gyung-Gi 463-816 + KR + +DC-49-C9 (hex) CASCO SIGNAL LTD +DC49C9 (base 16) CASCO SIGNAL LTD + No.489 Xizang Bei Road + Shanghai 200071 + CN + +70-D8-80 (hex) Upos System sp. z o.o. +70D880 (base 16) Upos System sp. z o.o. + Sienkiewicza 13 + Knurow Slaskie 44-190 + PL + +A0-5D-C1 (hex) TMCT Co., LTD. +A05DC1 (base 16) TMCT Co., LTD. + 5F-561, #19-11 SanChong Rd. + Taipei 115 + TW + +58-3C-C6 (hex) Omneality Ltd. +583CC6 (base 16) Omneality Ltd. + 10B Glossop Road + South Croydon Surrey CR2 0PU + GB + +B0-C8-AD (hex) People Power Company +B0C8AD (base 16) People Power Company + 620 Lowell Ave + Palo Alto CA 94301 + US + +18-17-14 (hex) DAEWOOIS +181714 (base 16) DAEWOOIS + 7F Namkwang Centlex Bldg. 440-4 Cheongcheon2-dong + Incheon Pupyeong-gu 82 + KR + +F0-EC-39 (hex) Essec +F0EC39 (base 16) Essec + Schoebroekstraat 48 + Paal Limburg 3583 + BE + +44-6C-24 (hex) Reallin Electronic Co.,Ltd +446C24 (base 16) Reallin Electronic Co.,Ltd + 2/F, Building 3, No.202 Zhengzhong Rd, XiHu industry Park + Hang Zhou Zhe Jiang 310030 + CN + +20-46-F9 (hex) Advanced Network Devices (dba:AND) +2046F9 (base 16) Advanced Network Devices (dba:AND) + 3820 Ventura Drive + Arlington Heights IL 60004 + US + +48-71-19 (hex) SGB GROUP LTD. +487119 (base 16) SGB GROUP LTD. + 13F,No.192,Sec.2,Chung Hsin Rd.,Hsin Tien City + Taipei 231 + TW + +04-FE-7F (hex) Cisco Systems, Inc +04FE7F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A4-B1-EE (hex) H. ZANDER GmbH & Co. KG +A4B1EE (base 16) H. ZANDER GmbH & Co. KG + Am Gut Wolf 15 + Aachen 52070 + DE + +84-21-41 (hex) Shenzhen Ginwave Technologies Ltd. +842141 (base 16) Shenzhen Ginwave Technologies Ltd. + 4/F,R2-A,High-Tech Industrial Park + Shenzhen Guangdong 518057 + CN + +A0-23-1B (hex) TeleComp R&D Corp. +A0231B (base 16) TeleComp R&D Corp. + 102 SW Orange Blossom + Lake City Florida 32025 + US + +B8-A3-E0 (hex) BenRui Technology Co.,Ltd +B8A3E0 (base 16) BenRui Technology Co.,Ltd + No.3A room A Unit Hongsong Building + ShenZhen GuangDong 518000 + CN + +3C-F5-2C (hex) DSPECIALISTS GmbH +3CF52C (base 16) DSPECIALISTS GmbH + Helmholtzstr. 2-9 L + Berlin 10587 + DE + +EC-44-76 (hex) Cisco Systems, Inc +EC4476 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +6C-18-11 (hex) Decatur Electronics +6C1811 (base 16) Decatur Electronics + 715 Bright Street + Decatur IL 62522 + US + +F8-E9-68 (hex) Egker Kft. +F8E968 (base 16) Egker Kft. + Szuglo u. 49. + Budapest 1145 + HU + +A8-99-5C (hex) aizo ag +A8995C (base 16) aizo ag + Brandstrasse 33 + Schlieren 8952 + CH + +40-12-E4 (hex) Compass-EOS +4012E4 (base 16) Compass-EOS + 7 Giborei Israel + Natanya 42504 + IL + +54-03-F5 (hex) EBN Technology Corp. +5403F5 (base 16) EBN Technology Corp. + 10F, No.90, Sec. 1, Sintai 5th Rd. + Sijhih City Taipei County 22102 + US + +04-C0-5B (hex) Tigo Energy +04C05B (base 16) Tigo Energy + 170 Knowles Dr + Los Gatos CA 95032 + US + +80-38-FD (hex) LeapFrog Enterprises, Inc. +8038FD (base 16) LeapFrog Enterprises, Inc. + 6401 Holis Street + Emeryville CA 94608 + US + +AC-BE-B6 (hex) Visualedge Technology Co., Ltd. +ACBEB6 (base 16) Visualedge Technology Co., Ltd. + 13FL.-1 No. 716, Zhongzheng Road, Zhonghe City, + Taipei County, 23511 + TW + +2C-91-27 (hex) Eintechno Corporation +2C9127 (base 16) Eintechno Corporation + 3359-1, kako, Inami-cho + kako-gun hyogo 675-1105 + JP + +AC-58-3B (hex) Human Assembler, Inc. +AC583B (base 16) Human Assembler, Inc. + 2-1-11-6F + Shibuya-ku Tokyo 150-0002 + JP + +E8-E7-76 (hex) Shenzhen Kootion Technology Co., Ltd +E8E776 (base 16) Shenzhen Kootion Technology Co., Ltd + 3/F, Building #4, XinJianXing Industrial Park + Shenzhen Guangdong Province 518108 + CN + +68-1F-D8 (hex) Siemens Industry, Inc. +681FD8 (base 16) Siemens Industry, Inc. + 10670 Treena Street + San Diego CA 92131 + US + +40-01-C6 (hex) 3COM EUROPE LTD +4001C6 (base 16) 3COM EUROPE LTD + Peoplebuilding 2 + Hemel Hempstead HERTS. HP2 4NW + GB + +9C-5E-73 (hex) Calibre UK LTD +9C5E73 (base 16) Calibre UK LTD + Cornwall House + Bradford West Yorkshire BD8 7JS + GB + +5C-14-37 (hex) Thyssenkrupp Aufzugswerke GmbH +5C1437 (base 16) Thyssenkrupp Aufzugswerke GmbH + Bernhaeuser Str.45 + Neuhausen a.d.F 73765 + DE + +9C-55-B4 (hex) I.S.E. S.r.l. +9C55B4 (base 16) I.S.E. S.r.l. + Via della Canapiglia 5 + Migliarino Pisano PISA 56010 + IT + +4C-63-EB (hex) Application Solutions (Electronics and Vision) Ltd +4C63EB (base 16) Application Solutions (Electronics and Vision) Ltd + The Riverside Centre + Lewes East Sussex BN7 2AQ + GB + +70-2F-97 (hex) Aava Mobile Oy +702F97 (base 16) Aava Mobile Oy + Nahkatehtaankatu 2 + Oulu 90100 + FI + +10-CA-81 (hex) PRECIA +10CA81 (base 16) PRECIA + Le ruissol VEYRAS + PRIVAS 07001 + FR + +40-A6-A4 (hex) PassivSystems Ltd +40A6A4 (base 16) PassivSystems Ltd + Medway House + Newbury Berks RG14 2PZ + GB + +94-BA-31 (hex) Visiontec da Amazônia Ltda. +94BA31 (base 16) Visiontec da Amazônia Ltda. + Rod. Geraldo Scavone, 2300 - Galpao 27 + Jacareí SP 12305-490 + BR + +B8-94-D2 (hex) Retail Innovation HTT AB +B894D2 (base 16) Retail Innovation HTT AB + Sjöängsvägen 2 + Sollentuna S-192 72 + SE + +B0-E9-7E (hex) Advanced Micro Peripherals +B0E97E (base 16) Advanced Micro Peripherals + Unit 1 Harrier House + Witchford Cambridgeshire CB6 2HY + GB + +F0-C2-4C (hex) Zhejiang FeiYue Digital Technology Co., Ltd +F0C24C (base 16) Zhejiang FeiYue Digital Technology Co., Ltd + Baoting Industrial Park, 531 Jiaogong Road + Hangzhou City Zhejiang Province 310012 + CN + +E4-75-1E (hex) Getinge Sterilization AB +E4751E (base 16) Getinge Sterilization AB + Box 69 + Getinge 31044 + SE + +10-65-A3 (hex) Core Brands LLC +1065A3 (base 16) Core Brands LLC + 1880 South McDowell Blvd + Petaluma CA 94954 + US + +9C-5B-96 (hex) NMR Corporation +9C5B96 (base 16) NMR Corporation + 3F Esprit Build.,1-3-6 Nishi-Nippori + Arakawa-Ku Tokyo 116-0013 + JP + +60-F1-3D (hex) JABLOCOM s.r.o. +60F13D (base 16) JABLOCOM s.r.o. + V Nivach 12 + Jablonec nad Nisou 466 01 + CZ + +50-25-2B (hex) Nethra Imaging Incorporated +50252B (base 16) Nethra Imaging Incorporated + 2855 Bowers Ave + Santa Clara CA 95051 + US + +F8-81-1A (hex) OVERKIZ +F8811A (base 16) OVERKIZ + EUROPA 3 + Archamps 74160 + FR + +38-63-F6 (hex) 3NOD MULTIMEDIA(SHENZHEN)CO.,LTD +3863F6 (base 16) 3NOD MULTIMEDIA(SHENZHEN)CO.,LTD + F6,Building11,Shenzhen Software Park + Shenzhen Guangdong 518057 + CN + +78-B8-1A (hex) INTER SALES A/S +78B81A (base 16) INTER SALES A/S + Stavneagervej 22 + Egaa 8250 + DK + +CC-00-80 (hex) BETTINI SRL +CC0080 (base 16) BETTINI SRL + VIA CESARE BATTISTI 22 + CESANO MADERNO MILAN 20031 + IT + +64-4B-C3 (hex) Shanghai WOASiS Telecommunications Ltd., Co. +644BC3 (base 16) Shanghai WOASiS Telecommunications Ltd., Co. + 15F, Software Building, + Shanghai 200233 + CN + +94-2E-63 (hex) Finsécur +942E63 (base 16) Finsécur + 52 rue Paul Lescop + Nanterre 92000 + FR + +AC-83-17 (hex) Shenzhen Furtunetel Communication Co., Ltd +AC8317 (base 16) Shenzhen Furtunetel Communication Co., Ltd + F19 building A zhongke plaza Nan yi street high-tech zone, Nanshan District, + Shenzhen Guangdong 518057 + CN + +AC-D1-80 (hex) Crexendo Business Solutions, Inc. +ACD180 (base 16) Crexendo Business Solutions, Inc. + 10201 S. 5st St. + Phoenix AZ 85044 + US + +CC-CC-4E (hex) Sun Fountainhead USA. Corp +CCCC4E (base 16) Sun Fountainhead USA. Corp + 801 S. Garfiled AVE # 236 + Los Angeles California 91801 + US + +68-85-40 (hex) IGI Mobile, Inc. +688540 (base 16) IGI Mobile, Inc. + 4F Kyongnam Bldg., + Seoul 135-080 + KR + +A0-9A-5A (hex) Time Domain +A09A5A (base 16) Time Domain + 330 Wynn Drive + Huntsville AL 35805 + US + +64-A8-37 (hex) Juni Korea Co., Ltd +64A837 (base 16) Juni Korea Co., Ltd + E603 Bundang Techno-Park 151 + Seongnam Gyeonggi 463-760 + KR + +20-2C-B7 (hex) Kong Yue Electronics & Information Industry (Xinhui) Ltd. +202CB7 (base 16) Kong Yue Electronics & Information Industry (Xinhui) Ltd. + Kong Yue Industrial Park, 18 Kongyue Road, Jinguzhou + Jiangmen Guangdong 529141 + CN + +60-9F-9D (hex) CloudSwitch +609F9D (base 16) CloudSwitch + 200 Wheeler Rd + Burlington MA 01803 + US + +48-34-3D (hex) IEP GmbH +48343D (base 16) IEP GmbH + Am Pferdemarkt 9c + Langenhagen Niedersachsen 30853 + DE + +D4-AA-FF (hex) MICRO WORLD +D4AAFF (base 16) MICRO WORLD + 19370 VAN NESS AVE + TORRANCE CA 90501 + US + +74-E5-37 (hex) RADSPIN +74E537 (base 16) RADSPIN + Songpa-gu Garak-dong 78 + Seoul 138-950 + KR + +00-26-E9 (hex) SP Corp +0026E9 (base 16) SP Corp + Guro 3-dong ,Guro-gu + Seoul 152-780 + KR + +00-26-EB (hex) Advanced Spectrum Technology Co., Ltd. +0026EB (base 16) Advanced Spectrum Technology Co., Ltd. + 1F., No.67 Jhongjheng Rd. + Sinjhuang Taiwan 242 + TW + +00-26-E1 (hex) Stanford University, OpenFlow Group +0026E1 (base 16) Stanford University, OpenFlow Group + 353 Serra Mall + Stanford CA 94305-9030 + US + +00-27-17 (hex) CE Digital(Zhenjiang)Co.,Ltd +002717 (base 16) CE Digital(Zhenjiang)Co.,Ltd + Wei 3 Road, Dingmao, Eco.Dev.Zone, + Zhenjiang 212009 + CN + +00-27-16 (hex) Adachi-Syokai Co., Ltd. +002716 (base 16) Adachi-Syokai Co., Ltd. + 228-2 Hazama Maki + Fukuchiyama-shi Kyoto 620-0913 + JP + +00-26-DC (hex) Optical Systems Design +0026DC (base 16) Optical Systems Design + 7/1 Vuko Place + Warriewood NSW 2102 + AU + +00-27-00 (hex) Shenzhen Siglent Technology Co., Ltd. +002700 (base 16) Shenzhen Siglent Technology Co., Ltd. + BUILDING A8,TANGLANG INDUSTRIAL ZONE,XILI,NANSHAN + Shenzhen Guangdong 518000 + CN + +00-26-EC (hex) Legrand Home Systems, Inc +0026EC (base 16) Legrand Home Systems, Inc + 301 Fulling Mill Rd + Middletown PA 17057 + US + +00-26-D4 (hex) IRCA SpA +0026D4 (base 16) IRCA SpA + Viale Venezia 31 - C.P. 248 + San Vendemiano (Treviso) Italy 31020 + IT + +00-26-63 (hex) Shenzhen Huitaiwei Tech. Ltd, co. +002663 (base 16) Shenzhen Huitaiwei Tech. Ltd, co. + JianDa Building,501-502 + Shenzhen Guangdong 518000 + CN + +00-26-61 (hex) Irumtek Co., Ltd. +002661 (base 16) Irumtek Co., Ltd. + Apt 708 513-22 Joongil Eines Platz + Seongnam-City Gyunggi-do 462-120 + KR + +00-26-5B (hex) Hitron Technologies. Inc +00265B (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +00-26-56 (hex) Sansonic Electronics USA +002656 (base 16) Sansonic Electronics USA + 9950 Baldwin Place + El Monte Cailfornia 91731 + US + +00-26-7D (hex) A-Max Technology Macao Commercial Offshore Company Limited +00267D (base 16) A-Max Technology Macao Commercial Offshore Company Limited + Avenida Da Praia Grande No. 409 + Macau + CN + +00-26-7C (hex) Metz-Werke GmbH & Co KG +00267C (base 16) Metz-Werke GmbH & Co KG + Ohmstrasse 55 + Zirndorf 90513 + DE + +00-26-73 (hex) RICOH COMPANY,LTD. +002673 (base 16) RICOH COMPANY,LTD. + 810 Shimoimaizumi + Ebina-City Kanagawa-Pref 243-0460 + JP + +00-26-6D (hex) MobileAccess Networks +00266D (base 16) MobileAccess Networks + 8391 Old Courthouse Rd. + Vienna VA 22182 + US + +00-26-C0 (hex) EnergyHub +0026C0 (base 16) EnergyHub + 232 3rd St C201 + Brooklyn NY 11215 + US + +00-26-C1 (hex) ARTRAY CO., LTD. +0026C1 (base 16) ARTRAY CO., LTD. + 5F Ueno Bldg, 1-17-5 Kouenjikita, + Tokyo 166-0002 + JP + +00-26-BE (hex) Schoonderbeek Elektronica Systemen B.V. +0026BE (base 16) Schoonderbeek Elektronica Systemen B.V. + Roggestraat 3-5 + Nieuw Vennep Noord Holland 2153GC + NL + +00-26-B5 (hex) ICOMM Tele Ltd +0026B5 (base 16) ICOMM Tele Ltd + 304, Trendset Towers, + Hyderabad AP 500034 + IN + +00-26-8C (hex) StarLeaf Ltd. +00268C (base 16) StarLeaf Ltd. + Chaston House, Mill Court + Cambridge CB22 5LD + GB + +00-26-8B (hex) Guangzhou Escene Computer Technology Limited +00268B (base 16) Guangzhou Escene Computer Technology Limited + Room 209, No.54-56 Yuehe Building, Huacui Street, Tianhe Industrial Park + Guangzhou Guangdong Province 510065 + CN + +00-26-6F (hex) Coordiwise Technology Corp. +00266F (base 16) Coordiwise Technology Corp. + 2F., No.123, Sec. 1, Lioujia 5th Rd. + Jhubei City, Hsinchu County 30272 + TW + +00-26-6E (hex) Nissho-denki Co.,LTD. +00266E (base 16) Nissho-denki Co.,LTD. + 3-7-6,chidori + ohta Tokyo 146-0083 + JP + +00-26-C3 (hex) Insightek Corp. +0026C3 (base 16) Insightek Corp. + 5F,NO.755,Chung Cheng Rd., + Chung Ho City Taipei Hsien 235 + TW + +00-26-81 (hex) Interspiro AB +002681 (base 16) Interspiro AB + Box 2853 + Täby 18728 + SE + +00-26-83 (hex) Ajoho Enterprise Co., Ltd. +002683 (base 16) Ajoho Enterprise Co., Ltd. + 7F., No.101, Ruihu St. + Taipei 114 + TW + +00-26-7F (hex) Zenterio AB +00267F (base 16) Zenterio AB + Diskettgatan 11B + Linköping 58335 + SE + +00-26-98 (hex) Cisco Systems, Inc +002698 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-26-9B (hex) SOKRAT Ltd. +00269B (base 16) SOKRAT Ltd. + Volkonskogo 2 + Irkutsk 664007 + RU + +00-26-A1 (hex) Megger +0026A1 (base 16) Megger + 4271 Bronze Way + Dallas Texas 75237 + US + +00-26-44 (hex) Thomson Telecom Belgium +002644 (base 16) Thomson Telecom Belgium + Prins Boudewijnlaan 47 + Edegem Antwerp B-2650 + BE + +00-26-46 (hex) SHENYANG TONGFANG MULTIMEDIA TECHNOLOGY COMPANY LIMITED +002646 (base 16) SHENYANG TONGFANG MULTIMEDIA TECHNOLOGY COMPANY LIMITED + No.10 Ping Nan East Road + Shenyang Liao Ning 110014 + CN + +00-26-3F (hex) LIOS Technology GmbH +00263F (base 16) LIOS Technology GmbH + Schanzenstraße 39 + Köln Germany D-51063 + DE + +00-26-3B (hex) Onbnetech +00263B (base 16) Onbnetech + 506, Samsung IT Valley, 197-5 + Guro-Gu Seoul 152-848 + KR + +00-26-58 (hex) T-Platforms (Cyprus) Limited +002658 (base 16) T-Platforms (Cyprus) Limited + Themistokli Dervi 3, Julia House + Nicosia P.C.-1066 + CY + +00-26-4C (hex) Shanghai DigiVision Technology Co., Ltd. +00264C (base 16) Shanghai DigiVision Technology Co., Ltd. + No. 333 Guangji Rd. + Shanghai 200083 + CN + +00-26-2F (hex) HAMAMATSU TOA ELECTRONICS +00262F (base 16) HAMAMATSU TOA ELECTRONICS + 9162-1 + HAMAMATSU SIZUOKA 431-2102 + JP + +00-26-31 (hex) COMMTACT LTD +002631 (base 16) COMMTACT LTD + Nahal Snir 10 + Yazne 81101 + IL + +00-25-FB (hex) Tunstall Healthcare A/S +0025FB (base 16) Tunstall Healthcare A/S + Stroemmen 6 + Noerresundby 9400 + DK + +00-25-F4 (hex) KoCo Connector AG +0025F4 (base 16) KoCo Connector AG + Marienstraße 12 + Berlin 10117 + DE + +00-26-06 (hex) RAUMFELD GmbH +002606 (base 16) RAUMFELD GmbH + Reichenberger Str. 124 + Berlin 10999 + DE + +00-26-07 (hex) Enabling Technology Pty Ltd +002607 (base 16) Enabling Technology Pty Ltd + 23/44 Kings Park Road + West Perth Western Australia 6005 + AU + +00-26-24 (hex) Thomson Inc. +002624 (base 16) Thomson Inc. + 101 West 103rd Street + Indianapolis IN 46290 + US + +00-26-05 (hex) CC Systems AB +002605 (base 16) CC Systems AB + Box 83 + Alfta 822 22 + SE + +00-26-02 (hex) SMART Temps LLC +002602 (base 16) SMART Temps LLC + 435 PARK PL CIRCLE SUITE 100 + Mishawaka IN 46545 + US + +00-26-1A (hex) Femtocomm System Technology Corp. +00261A (base 16) Femtocomm System Technology Corp. + 2F.-2,No.28, Taiyuan St., + Jhubei City, Hsinchu Country, 30288 + TW + +00-26-34 (hex) Infineta Systems, Inc +002634 (base 16) Infineta Systems, Inc + 2870 Zanker Rd + San Jose CA 95134 + US + +00-25-99 (hex) Hedon e.d. B.V. +002599 (base 16) Hedon e.d. B.V. + Elektronicaweg 15 + Delft Zuid Holland 2628 XG + NL + +00-25-97 (hex) Kalki Communication Technologies +002597 (base 16) Kalki Communication Technologies + 4th Floor, Survey. No. 17/1, Outer Ring Road + Opp. Prestige Cessna Park Bangalore 560 103 + IN + +00-25-92 (hex) Guangzhou Shirui Electronic Co., Ltd +002592 (base 16) Guangzhou Shirui Electronic Co., Ltd + 301D, No.9, Caipin Road, + Guangzhou Guangdong 510663 + CN + +00-25-94 (hex) Eurodesign BG LTD +002594 (base 16) Eurodesign BG LTD + Business Park Sofia, Building 4, Floor 2 + Sofia 1113 + BG + +00-25-9F (hex) TechnoDigital Technologies GmbH +00259F (base 16) TechnoDigital Technologies GmbH + Haesslerstraße 8 + Erfurt Thuringia 99096 + DE + +00-25-9D (hex) Private +00259D (base 16) Private + +00-25-98 (hex) Zhong Shan City Litai Electronic Industrial Co. Ltd +002598 (base 16) Zhong Shan City Litai Electronic Industrial Co. Ltd + No.3 Industrial District, Wuguishan, Cheng gui Road + Zhong shan City Guang dong Province 528458 + CN + +00-25-E3 (hex) Hanshinit Inc. +0025E3 (base 16) Hanshinit Inc. + Dong-Won Bld 3F, 395-13, Gal-Ma 2, Seo-Gu + Daejeon 302-809 + KR + +00-25-DC (hex) Sumitomo Electric Industries,Ltd +0025DC (base 16) Sumitomo Electric Industries,Ltd + 1-1-3, Shimaya, Konohana-ku + Osaka 554-0024 + JP + +00-25-D4 (hex) General Dynamics Mission Systems +0025D4 (base 16) General Dynamics Mission Systems + 150 Rustcraft Road + Dedham MA 02026 + US + +00-25-C2 (hex) RingBell Co.,Ltd. +0025C2 (base 16) RingBell Co.,Ltd. + 10586 KingGeorge Hwy + Surrey B.C V3T 2X3 + CA + +00-25-A7 (hex) itron +0025A7 (base 16) itron + 5390 Triangle Parkway + Norcross GA 30092 + US + +00-25-A9 (hex) Shanghai Embedway Information Technologies Co.,Ltd +0025A9 (base 16) Shanghai Embedway Information Technologies Co.,Ltd + 2F,Building 9,Lujiazui Software Park, No.20,Lane 91,E'Shan Road + Shanghai 200127 + CN + +00-25-CA (hex) LS Research, LLC +0025CA (base 16) LS Research, LLC + W66 N220 Commerce Court + Cedarburg WI 53012 + US + +00-25-B4 (hex) Cisco Systems, Inc +0025B4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-25-B2 (hex) MBDA Deutschland GmbH +0025B2 (base 16) MBDA Deutschland GmbH + Hagenauer Forst 27 + Schrobenhausen Bavaria 86529 + DE + +00-25-EF (hex) I-TEC Co., Ltd. +0025EF (base 16) I-TEC Co., Ltd. + 7/F,KAWARAMACHI KOYO BLDG.3-4-3,KAWARAMCHI,CHUO-KU, + OSAKA 541-0048 + JP + +00-25-28 (hex) Daido Signal Co., Ltd. +002528 (base 16) Daido Signal Co., Ltd. + 6-17-19 + Minato-ku TOKYO 105-8650 + JP + +00-25-26 (hex) Genuine Technologies Co., Ltd. +002526 (base 16) Genuine Technologies Co., Ltd. + Klingelnberg Bldg. + Yokohama Kanagawa 222-0033 + JP + +00-25-6B (hex) ATENIX E.E. s.r.l. +00256B (base 16) ATENIX E.E. s.r.l. + Via Torricelli, 15/b + VERONA VR 37135 + IT + +00-25-6E (hex) Van Breda B.V. +00256E (base 16) Van Breda B.V. + Mercuriusweg 21 + Brummen Gelderland 6971 GV + NL + +00-25-65 (hex) Vizimax Inc. +002565 (base 16) Vizimax Inc. + 2284, rue de la Province + Longueuil Québec J4G 1G1 + CA + +00-25-5E (hex) Shanghai Dare Technologies Co.,Ltd. +00255E (base 16) Shanghai Dare Technologies Co.,Ltd. + 22F,Info Tech Building, No.1555,Kongjiang Road, + Shanghai 200092 + CN + +00-25-3B (hex) din Dietmar Nocker Facilitymanagement GmbH +00253B (base 16) din Dietmar Nocker Facilitymanagement GmbH + Kotzinastrasse 5 + Linz Upper Austria 4030 + AT + +00-25-3D (hex) DRS Consolidated Controls +00253D (base 16) DRS Consolidated Controls + 21 South Street + Danbury CT 06810-8147 + US + +00-25-35 (hex) Minimax GmbH & Co KG +002535 (base 16) Minimax GmbH & Co KG + Industriestrasse 10/12 + Bad Oldesloe SH 23840 + DE + +00-25-84 (hex) Cisco Systems, Inc +002584 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-25-79 (hex) J & F Labs +002579 (base 16) J & F Labs + 1214 W. Boston Post Road + Mamaroneck NY 10543 + US + +00-25-7F (hex) CallTechSolution Co.,Ltd +00257F (base 16) CallTechSolution Co.,Ltd + #123,Daewooprugio B/D,344-1, Seogyo-Dong,Mapo-gu + Seoul 121-837 + KR + +00-25-77 (hex) D-BOX Technologies +002577 (base 16) D-BOX Technologies + 2172 de la Province + Longueuil Quebec J4G 1R7 + CA + +00-25-72 (hex) Nemo-Q International AB +002572 (base 16) Nemo-Q International AB + Box 210 + Sollentuna 19123 + SE + +00-25-29 (hex) COMELIT GROUP S.P.A +002529 (base 16) COMELIT GROUP S.P.A + DON ARRIGONI N. 5 + SAN LORENZO, ROVETTA BERGAMO 24020 + IT + +00-25-2A (hex) Chengdu GeeYa Technology Co.,LTD +00252A (base 16) Chengdu GeeYa Technology Co.,LTD + 50 Shuxi Road, + Chengdu SiChuan 610091 + CN + +00-25-8A (hex) Pole/Zero Corporation +00258A (base 16) Pole/Zero Corporation + 5530 Union Centre Drive + West Chester OH 45069 + US + +00-25-5F (hex) SenTec AG +00255F (base 16) SenTec AG + Ringstrasse 39 + Therwil 4106 + CH + +00-24-EC (hex) United Information Technology Co.,Ltd. +0024EC (base 16) United Information Technology Co.,Ltd. + 5/F,9th Building,Software Park,2nd Keji-zhong Road,High-Tech Industrial Park + Shenzhen Guangdong 518057 + CN + +00-24-E6 (hex) In Motion Technology Inc. +0024E6 (base 16) In Motion Technology Inc. + #350, 625 Agnes Street + New Westminster BC V3M 5Y4 + CA + +00-24-E7 (hex) Plaster Networks +0024E7 (base 16) Plaster Networks + 935 Hamilton Avenue + Menlo Park CA 94025-1431 + US + +00-24-E4 (hex) Withings +0024E4 (base 16) Withings + 37bis rue du General Leclerc + Issy les Moulineaux 92442 + FR + +00-24-DE (hex) GLOBAL Technology Inc. +0024DE (base 16) GLOBAL Technology Inc. + No.168,Shanshan Rd., Wangchun Industrial Park, + Ningbo 315176 + CN + +00-24-DC (hex) Juniper Networks +0024DC (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-24-DB (hex) Alcohol Monitoring Systems +0024DB (base 16) Alcohol Monitoring Systems + 1241 W. Mineral Avenue + Littleton CO 80120 + US + +00-25-21 (hex) Logitek Electronic Systems, Inc. +002521 (base 16) Logitek Electronic Systems, Inc. + 5622 Edgemoor Drive + Houston Texas 77081 + US + +00-25-1F (hex) ZYNUS VISION INC. +00251F (base 16) ZYNUS VISION INC. + 1-1-7-1A + SAGAMIHARA KANAGAWA 229-0039 + JP + +00-25-1E (hex) ROTEL TECHNOLOGIES +00251E (base 16) ROTEL TECHNOLOGIES + CEVIZLIDERE 14.CD NO:2/19 BALGAT + ANKARA 06520 + TR + +00-25-19 (hex) Viaas Inc +002519 (base 16) Viaas Inc + 3175 South Winchester Blvd + Campbell CA 95008 + US + +00-24-D5 (hex) Winward Industrial Limited +0024D5 (base 16) Winward Industrial Limited + Rm.7, P Floor, Tower A, + HongKong 852 + CN + +00-24-DD (hex) Centrak, Inc. +0024DD (base 16) Centrak, Inc. + 207 Penns Trail + Newtown PA 18940 + US + +00-24-EA (hex) iris-GmbH infrared & intelligent sensors +0024EA (base 16) iris-GmbH infrared & intelligent sensors + Ostendstraße 1-14 + Berlin 12459 + DE + +00-24-ED (hex) YT Elec. Co,.Ltd. +0024ED (base 16) YT Elec. Co,.Ltd. + Block B,2 Floor ,Bao Ying Industrial District, + Wu Lian Lu Shenzhen 518116 + CN + +00-25-03 (hex) IBM Corp +002503 (base 16) IBM Corp + 2051 Mission College Blvd + Santa Clara CA 95054 + US + +00-25-04 (hex) Valiant Communications Limited +002504 (base 16) Valiant Communications Limited + 71-1 Shivaji Marg + New Delhi Delhi 110015 + IN + +00-25-13 (hex) CXP DIGITAL BV +002513 (base 16) CXP DIGITAL BV + De Reulver 97A + Enschede 7544RT + NL + +00-24-A4 (hex) Siklu Communication +0024A4 (base 16) Siklu Communication + 7 Shoham St., , 3rd Floor + Petah Tikva 49517 + IL + +00-24-9A (hex) Beijing Zhongchuang Telecommunication Test Co., Ltd. +00249A (base 16) Beijing Zhongchuang Telecommunication Test Co., Ltd. + 12-14,Block C,Beijing International Building,#18,Zhong Guan Cun Nan Road, + Beijing 100081 + CN + +00-24-9E (hex) ADC-Elektronik GmbH +00249E (base 16) ADC-Elektronik GmbH + Östingstraße 13b + Hamm NRW D-59063 + DE + +00-24-9F (hex) RIM Testing Services +00249F (base 16) RIM Testing Services + 440 Phillip Street + Waterloo Ontario N2L 5R9 + CA + +00-24-C2 (hex) Asumo Co.,Ltd. +0024C2 (base 16) Asumo Co.,Ltd. + Oya-Kita 1-3-1 + EBINA-CITY KANAGAWA-PREF. 243-0419 + JP + +00-24-BF (hex) CIAT +0024BF (base 16) CIAT + 30, Avenue Jean Falconnier + Culoz 01350 + FR + +00-24-C0 (hex) NTI COMODO INC +0024C0 (base 16) NTI COMODO INC + Rm#502, Kangyong Bldg, Sungnam-dong + Sungnam-si Kyunggi-do 462-827 + KR + +00-24-BB (hex) CENTRAL Corporation +0024BB (base 16) CENTRAL Corporation + NISSO 17 Bldg.7F 2-14-30 + Yokohama Kanagawa 222-0033 + JP + +00-24-BC (hex) HuRob Co.,Ltd +0024BC (base 16) HuRob Co.,Ltd + 2121, Jeongwang-Dong + Siheung-Si Gyeonggi-Do 429-793 + KR + +00-24-AD (hex) Adolf Thies Gmbh & Co. KG +0024AD (base 16) Adolf Thies Gmbh & Co. KG + Hauptstraße 76 + Göttingen 37083 + DE + +00-24-A7 (hex) Advanced Video Communications Inc. +0024A7 (base 16) Advanced Video Communications Inc. + 633 W 5th Street + Los Angeles CA 90017 + US + +00-24-AB (hex) A7 Engineering, Inc. +0024AB (base 16) A7 Engineering, Inc. + 12127 Kirkham Road Suite 101 + Poway CA 92064 + US + +00-24-66 (hex) Unitron nv +002466 (base 16) Unitron nv + Franrkijklaan 27 + Poperinge W-vl 8970 + BE + +00-24-5F (hex) Vine Telecom CO.,Ltd. +00245F (base 16) Vine Telecom CO.,Ltd. + 191-4, 4F, Anyang-dong, Manan-gu + Anyang-si Gyeonggi-do 430-010 + KR + +00-24-55 (hex) MuLogic BV +002455 (base 16) MuLogic BV + Olivier van Noortstraat 4 + Schiedam ZH 3124LA + NL + +00-24-88 (hex) Centre For Development Of Telematics +002488 (base 16) Centre For Development Of Telematics + B01, Electronic City, Phase 1 + Bangalore Karnataka 560100 + IN + +00-24-8F (hex) DO-MONIX +00248F (base 16) DO-MONIX + #501, Koreana B/D + Seongnam-si Gyeonggi-do 82 + KP + +00-24-79 (hex) Optec Displays, Inc. +002479 (base 16) Optec Displays, Inc. + 528 S. 6th Avenue + City of Industry California 91746 + US + +00-24-B7 (hex) GridPoint, Inc. +0024B7 (base 16) GridPoint, Inc. + 2801 Clarendon Blvd. + Arlington VA 22201 + US + +00-24-AE (hex) IDEMIA +0024AE (base 16) IDEMIA + 18 chaussee Jules Cesar + OSNY 95520 + FR + +00-24-68 (hex) Sumavision Technologies Co.,Ltd +002468 (base 16) Sumavision Technologies Co.,Ltd + 6F, Block A2, Power Creative Building,No.1 Shangdi East Road, Haidian District + Beijing 100085 + CN + +00-24-3A (hex) Ludl Electronic Products +00243A (base 16) Ludl Electronic Products + 171 Brady Ave + Hawthorne NY 10532 + US + +00-24-39 (hex) Digital Barriers Advanced Technologies +002439 (base 16) Digital Barriers Advanced Technologies + 4th Floor + Glasgow Lanarkshire G1 2QQ + GB + +00-24-34 (hex) Lectrosonics, Inc. +002434 (base 16) Lectrosonics, Inc. + 581 Laser Rd. + Rio Rancho NM 87124 + US + +00-24-5A (hex) Nanjing Panda Electronics Company Limited +00245A (base 16) Nanjing Panda Electronics Company Limited + Zhongshan EastRoad 301, + NANJING JIANGSU 210016 + CN + +00-24-5B (hex) RAIDON TECHNOLOGY, INC. +00245B (base 16) RAIDON TECHNOLOGY, INC. + 4F-8, NO.16, Lane 609, Sec.5, Chung-Hsin Rd., + San-Chung City Taipei county, 24159 + TW + +00-24-59 (hex) ABB Automation products GmbH +002459 (base 16) ABB Automation products GmbH + Eppelheimer Strasse 82 + Heidelberg 69123 + DE + +00-24-4E (hex) RadChips, Inc. +00244E (base 16) RadChips, Inc. + 422 East Vermijo Ave. + Colorado Springs CO 80903 + US + +00-24-0D (hex) OnePath Networks LTD. +00240D (base 16) OnePath Networks LTD. + 8 Hartom St + Jerusalem 91450 + IL + +00-24-0B (hex) Virtual Computer Inc. +00240B (base 16) Virtual Computer Inc. + 3 LAN Drive + Westford MA 01886 + US + +00-24-02 (hex) Op-Tection GmbH +002402 (base 16) Op-Tection GmbH + Borsigstraße 80 + Heinsberg Germany 52525 + DE + +00-24-2F (hex) Micron +00242F (base 16) Micron + 8000 S Federal Way + Boise ID 83716 + US + +00-24-26 (hex) NOHMI BOSAI LTD. +002426 (base 16) NOHMI BOSAI LTD. + 7-3,Kudan-Minami 4-Chome, + Tokyo 102-8277 + JP + +00-24-18 (hex) Nextwave Semiconductor +002418 (base 16) Nextwave Semiconductor + 3610 Valley Centre Dr + San Diego CA 92130 + US + +00-24-12 (hex) Benign Technologies Co, Ltd. +002412 (base 16) Benign Technologies Co, Ltd. + 504 room, 5F, South building, Forsafe Tower, + Shenzhen Guangdong 518057 + CN + +00-24-29 (hex) MK MASTER INC. +002429 (base 16) MK MASTER INC. + 6F, -1, NO. 110,SEC. 3, JHONGSHAN RD., + JHONG-HE CITY, TAIPEI COUNTY 235 + TW + +00-23-DB (hex) saxnet gmbh +0023DB (base 16) saxnet gmbh + Willy-Brandt-Ring 1 + Oelsnitz Sachsen 08606 + DE + +00-23-C8 (hex) TEAM-R +0023C8 (base 16) TEAM-R + Gragdanski str.111, A, 9-N + St. Petersburg 195265 + RU + +00-23-EB (hex) Cisco Systems, Inc +0023EB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-23-EC (hex) Algorithmix GmbH +0023EC (base 16) Algorithmix GmbH + Klettgaustrasse 21 + Waldshut-Tiengen BW 79761 + US + +00-23-C1 (hex) Securitas Direct AB +0023C1 (base 16) Securitas Direct AB + Angbatsbron 1 + Malmö 21120 + SE + +00-23-AA (hex) HFR, Inc. +0023AA (base 16) HFR, Inc. + 5F, Hana EZ Tower + Sungnam-si Kyunggi-do 463-870 + KR + +00-23-A5 (hex) SageTV, LLC +0023A5 (base 16) SageTV, LLC + 9800 S. La Cienega Blvd + Inglewood CA 90301 + US + +00-23-9E (hex) Jiangsu Lemote Technology Corporation Limited +00239E (base 16) Jiangsu Lemote Technology Corporation Limited + Menglan Industrial Park,Yushan + Changshu Jiangsu 215500 + CN + +00-23-FC (hex) Ultra Stereo Labs, Inc +0023FC (base 16) Ultra Stereo Labs, Inc + 181 Bonetti Drive + San Luis Obispo CA 93401 + US + +00-23-BB (hex) Schmitt Industries +0023BB (base 16) Schmitt Industries + 2765 NW Nicolai St + Portland Oregon 97210 + US + +00-23-8D (hex) Techno Design Co., Ltd. +00238D (base 16) Techno Design Co., Ltd. + 312-2 + Aso-gun Kumamoto-ken 861-2401 + JP + +00-23-87 (hex) ThinkFlood, Inc. +002387 (base 16) ThinkFlood, Inc. + 138 Claflin St + Belmont MA 02478 + US + +00-23-84 (hex) GGH Engineering s.r.l. +002384 (base 16) GGH Engineering s.r.l. + Via Agucchi 84/2 + Bologna 40133 + IT + +00-23-91 (hex) Maxian +002391 (base 16) Maxian + 21th Fl. KINS tower, 25-1 + Seongnam-city Gyeonggi-do 463-847 + KR + +00-23-92 (hex) Proteus Industries Inc. +002392 (base 16) Proteus Industries Inc. + 340 Pioneer Way + Mountain View CA 94041 + US + +00-23-93 (hex) AJINEXTEK +002393 (base 16) AJINEXTEK + 9-3, Holimdong, Dalseogu + Daegu 704-240 + KR + +00-23-7F (hex) PLANTRONICS, INC. +00237F (base 16) PLANTRONICS, INC. + 345 ENCINAL STREET + SANTA CRUZ CA 95060 + US + +00-23-6F (hex) DAQ System +00236F (base 16) DAQ System + Rm 913, SungNam Woolim Lions VAlley I, 311-3 + Sungnam-Si Kyunggi-Do, 462-806 + KR + +00-23-30 (hex) DIZIPIA, INC. +002330 (base 16) DIZIPIA, INC. + 15th Floor, East Wing, IT Venture Tower + Seoul 138160 + KR + +00-23-69 (hex) Cisco-Linksys, LLC +002369 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +00-22-F8 (hex) PIMA Electronic Systems Ltd. +0022F8 (base 16) PIMA Electronic Systems Ltd. + 5 Hatzoref St. + Holon 58856 + IL + +00-23-1C (hex) Fourier Systems Ltd. +00231C (base 16) Fourier Systems Ltd. + 16 Hamelacha St + Rosh Haayin 48091 + IL + +00-23-1D (hex) Deltacom Electronics Ltd +00231D (base 16) Deltacom Electronics Ltd + 2F,ZIT,7km Tzarigradsko Shose + Sofia Sofia-grad 1784 + BG + +00-22-D7 (hex) Nintendo Co., Ltd. +0022D7 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-22-D6 (hex) Cypak AB +0022D6 (base 16) Cypak AB + P.O. BOX 2332 + Stockholm 103 18 + SE + +00-22-D0 (hex) Polar Electro Oy +0022D0 (base 16) Polar Electro Oy + Professorintie 5 + Kempele Oulu 90440 + FI + +00-23-0A (hex) ARBURG GmbH & Co KG +00230A (base 16) ARBURG GmbH & Co KG + Arthur Hehl Straße + Lossburg D-72290 + DE + +00-22-C3 (hex) Zeeport Technology Inc. +0022C3 (base 16) Zeeport Technology Inc. + 1F,No231,Xianzheng 2nd Rd. + HsinChu Taiwan 300 + TW + +00-23-16 (hex) KISAN ELECTRONICS CO +002316 (base 16) KISAN ELECTRONICS CO + 317-15 + SEOUNG-DONG GU SEOUL 133-123 + KR + +00-23-0F (hex) Hirsch Electronics Corporation +00230F (base 16) Hirsch Electronics Corporation + 1900 Carnegie, Bldg. B + Santa Ana CA 92705 + US + +00-23-2D (hex) SandForce +00232D (base 16) SandForce + 12950 Saratoga Ave. + Saratoga California 95070-4658 + US + +00-23-23 (hex) Zylin AS +002323 (base 16) Zylin AS + Auglendsdalen 78 + Stavanger 4017 + NO + +00-22-DE (hex) OPPO Digital, Inc. +0022DE (base 16) OPPO Digital, Inc. + 2629B Terminal Blvd + Mountain View CA 94043 + US + +00-22-F1 (hex) Private +0022F1 (base 16) Private + +00-22-A2 (hex) Xtramus Technologies +0022A2 (base 16) Xtramus Technologies + 5th Fl., No. 102, Lide St., + Zhonghe City Taipei County 235 + TW + +00-22-9E (hex) Social Aid Research Co., Ltd. +00229E (base 16) Social Aid Research Co., Ltd. + South 3, West 10, Chuo-ku + Sapporo Hokkaido 060-0063 + JP + +00-22-85 (hex) NOMUS COMM SYSTEMS +002285 (base 16) NOMUS COMM SYSTEMS + 601, Gunjan Tower, + Baroda Gujarat 390023 + IN + +00-22-81 (hex) Daintree Networks Pty +002281 (base 16) Daintree Networks Pty + 1 Dalmore Drive + Scoresby Victoria 3179 + AU + +00-22-55 (hex) Cisco Systems, Inc +002255 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-22-4E (hex) SEEnergy Corp. +00224E (base 16) SEEnergy Corp. + 4F, No.61, Dongsing RD. + Taipei 110 + TW + +00-22-87 (hex) Titan Wireless LLC +002287 (base 16) Titan Wireless LLC + 3914 Gattis School Rd + Round Rock Texas 78664 + US + +00-22-88 (hex) Sagrad, Inc. +002288 (base 16) Sagrad, Inc. + 751 North Drive + Melbourne FL 32934 + US + +00-22-73 (hex) Techway +002273 (base 16) Techway + Rm 1002, Daehyun Techno World Bd, + Uiwang-Si, Kyungki-Do 437-820 + KR + +00-22-6B (hex) Cisco-Linksys, LLC +00226B (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +00-22-67 (hex) Nortel Networks +002267 (base 16) Nortel Networks + 2221 Lakeside Blvd + Richardson TX 75081 + US + +00-22-95 (hex) SGM Technology for lighting spa +002295 (base 16) SGM Technology for lighting spa + Via Pio La Torre 1 + Tavullia PU 61010 + IT + +00-22-5A (hex) Garde Security AB +00225A (base 16) Garde Security AB + Box 78 + Soderhamn S-826 22 + SE + +00-22-42 (hex) Alacron Inc. +002242 (base 16) Alacron Inc. + 71 Spit Brook Rd. + Nashua NH 03060 + US + +00-22-34 (hex) Corventis Inc. +002234 (base 16) Corventis Inc. + 1410 Energy Park Dr. Suite #1 + St. Paul Minnesota 55108 + US + +00-21-F7 (hex) HPN Supply Chain +0021F7 (base 16) HPN Supply Chain + 8000 Foothills Blvd + Roseville CA 95747 + US + +00-21-F4 (hex) INRange Systems, Inc +0021F4 (base 16) INRange Systems, Inc + 3316 5th Avenue, Suite 100 + Altoona PA 16602 + US + +00-21-F5 (hex) Western Engravers Supply, Inc. +0021F5 (base 16) Western Engravers Supply, Inc. + 17621 N Black Canyon Highway + Phoenix AZ 85023 + US + +00-22-32 (hex) Design Design Technology Ltd +002232 (base 16) Design Design Technology Ltd + Unit 9, Ash Road South + Wrexham North Wales LL13 9UG + GB + +00-22-2B (hex) Nucomm, Inc. +00222B (base 16) Nucomm, Inc. + 101 Bilby Road + Hackettstown NJ 07840 + US + +00-22-26 (hex) Avaak, Inc. +002226 (base 16) Avaak, Inc. + 9645 Scranton Rd., Suitie 110 + San Diego CA 92121 + US + +00-22-21 (hex) ITOH DENKI CO,LTD. +002221 (base 16) ITOH DENKI CO,LTD. + 1146-2, Asazuma-cho + Kasai Hyogo 679-0180 + JP + +00-22-1D (hex) Freegene Technology LTD +00221D (base 16) Freegene Technology LTD + 3/F ,C BLDG,Weipengda Industrial Park + Shenzhen Gongdong 518109 + CN + +00-22-24 (hex) Good Will Instrument Co., Ltd. +002224 (base 16) Good Will Instrument Co., Ltd. + No. 7-1 Jhongsing Road, + Taipei 236 + TW + +00-22-45 (hex) Leine & Linde AB +002245 (base 16) Leine & Linde AB + Box 8 + Strängnäs Södermanland SE-645 21 + SE + +00-22-49 (hex) HOME MULTIENERGY SL +002249 (base 16) HOME MULTIENERGY SL + Capitán HAYA 1 + MADRID 28020 + ES + +00-22-40 (hex) Universal Telecom S/A +002240 (base 16) Universal Telecom S/A + Avenida Paulista, 2444 - 17 andar + São Paulo 01310-300 + BR + +00-22-0F (hex) MoCA (Multimedia over Coax Alliance) +00220F (base 16) MoCA (Multimedia over Coax Alliance) + 90 Inverness Circle East + Englewood CA 94583 + US + +00-22-0A (hex) OnLive, Inc +00220A (base 16) OnLive, Inc + 1091 N Shoreline Blvd + Mountainview California 94043 + US + +00-22-03 (hex) Glensound Electronics Ltd +002203 (base 16) Glensound Electronics Ltd + 1 - 6 Brooks Place + Maidstone Kent ME17 1UN + GB + +00-22-04 (hex) KORATEK +002204 (base 16) KORATEK + Geumjeong-dong + Gunpo-si Gyeonggi-do 435-825 + KR + +00-21-FF (hex) Cyfrowy Polsat SA +0021FF (base 16) Cyfrowy Polsat SA + Łubinowa + Warsaw Mazowieckie 03-878 + PL + +00-21-E4 (hex) I-WIN +0021E4 (base 16) I-WIN + 27 Rue des Econdeaux + EPINAY SUR SEINE Seine Saint Denis 93800 + FR + +00-21-E5 (hex) Display Solution AG +0021E5 (base 16) Display Solution AG + Talhofstraße 32a + Gilching D 82205 + DE + +00-22-1B (hex) Morega Systems +00221B (base 16) Morega Systems + 5770 Hurontario Street + Mississauga Ontario L5R 3G5 + CA + +00-21-B2 (hex) Fiberblaze A/S +0021B2 (base 16) Fiberblaze A/S + Kildevangsvej 9 + Roskilde 4000 + DK + +00-21-AC (hex) Infrared Integrated Systems Ltd +0021AC (base 16) Infrared Integrated Systems Ltd + Park Circle, Tithe Barn Way + Northampton Northants NN4 9BG + GB + +00-21-8E (hex) MEKICS CO., LTD. +00218E (base 16) MEKICS CO., LTD. + Industrial Zone 861-10, Taegye-Dong + Chunchon Kangwon 200-944 + KR + +00-21-8F (hex) Avantgarde Acoustic Lautsprechersysteme GmbH +00218F (base 16) Avantgarde Acoustic Lautsprechersysteme GmbH + Nibelungenstraße 349 + Lautertal - Reichenbach Hessen D-64686 + DE + +00-21-7E (hex) Telit Communication s.p.a +00217E (base 16) Telit Communication s.p.a + Via stazione di prosecco 5B + SGONICO Trieste 34010 + IT + +00-21-87 (hex) Imacs GmbH +002187 (base 16) Imacs GmbH + Mittelfeldstrasse 25 + Kornwestheim Germany D-70806 + DE + +00-21-81 (hex) Si2 Microsystems Limited +002181 (base 16) Si2 Microsystems Limited + No 84, Sy No 150, EPIP, Whitefield Industrial Area + Bangalore Karnataka 560066 + IN + +00-21-C2 (hex) GL Communications Inc +0021C2 (base 16) GL Communications Inc + 818 West Diamond Ave + Gaithersburg MD 20878 + US + +00-21-E2 (hex) visago Systems & Controls GmbH & Co. KG +0021E2 (base 16) visago Systems & Controls GmbH & Co. KG + Neuwiesenstraße 20 + Weilheim an der Teck D-73235 + DE + +00-21-DD (hex) Northstar Systems Corp +0021DD (base 16) Northstar Systems Corp + 5F, No.200 Gang Qian Rd + Taipei 114 + TW + +00-21-D5 (hex) X2E GmbH +0021D5 (base 16) X2E GmbH + Raiffeisenstrasse 9 + Winden Rheinland-Pfalz 76872 + DE + +00-21-A2 (hex) EKE-Electronics Ltd. +0021A2 (base 16) EKE-Electronics Ltd. + Piispanportti 7 + ESPOO 02240 + FI + +00-21-C9 (hex) Wavecom Asia Pacific Limited +0021C9 (base 16) Wavecom Asia Pacific Limited + 201 Bio-Informatics Centre, No.2 Science Park West Ave + + HK + +00-21-4A (hex) Pixel Velocity, Inc +00214A (base 16) Pixel Velocity, Inc + 3917 Research Park Dr. + Ann Arbor MI 48108 + US + +00-21-46 (hex) Sanmina-SCI +002146 (base 16) Sanmina-SCI + 13000 South Memorial Parkway + Huntsville AL 35803 + US + +00-21-6E (hex) Function ATI (Huizhou) Telecommunications Co., Ltd. +00216E (base 16) Function ATI (Huizhou) Telecommunications Co., Ltd. + No. 8, Huitai Road, Huitai Industrial Zone + Huizhou City Guangdong Province 516006 + CN + +00-21-6D (hex) Soltech Co., Ltd. +00216D (base 16) Soltech Co., Ltd. + #30-3,3F + Yongsan Ku Seoul 140837 + KR + +00-21-65 (hex) Presstek Inc. +002165 (base 16) Presstek Inc. + 55 Executive Drive + Hudson New Hampshire 03051 + US + +00-21-1F (hex) SHINSUNG DELTATECH CO.,LTD. +00211F (base 16) SHINSUNG DELTATECH CO.,LTD. + 44-10 + CHANGWON-CITY KYUNGNAM-DO 641-290 + KR + +00-21-24 (hex) Optos Plc +002124 (base 16) Optos Plc + Queensferry House + Dunfermline Fife KY11 8GR + GB + +00-21-33 (hex) Building B, Inc +002133 (base 16) Building B, Inc + 1000 NW 65th Street, Suite 300 + Ft. Lauderdale FL 33309 + US + +00-21-34 (hex) Brandywine Communications +002134 (base 16) Brandywine Communications + 1153 Warner Ave + Tustin CA 92780 + US + +00-21-3A (hex) Winchester Systems Inc. +00213A (base 16) Winchester Systems Inc. + 101 Billerica Avenue + Billerica, MA 01862 + US + +00-21-2E (hex) dresden-elektronik +00212E (base 16) dresden-elektronik + Enno-Heidebroek-Str. 12 + Dresden Saxony D-01237 + DE + +00-21-30 (hex) Keico Hightech Inc. +002130 (base 16) Keico Hightech Inc. + Ace twin tower I, 12th Fl. + Seoul 152-050 + KR + +00-21-5B (hex) SenseAnywhere +00215B (base 16) SenseAnywhere + Lisztlaan 2 + Roosendaal 4702 KJ + NL + +00-21-4E (hex) GS Yuasa Power Supply Ltd. +00214E (base 16) GS Yuasa Power Supply Ltd. + 1, Inobanba-cho, Nishinosho, Kisshoin, Minami-ku, + Kyoto 601-8520 + JP + +00-21-42 (hex) Advanced Control Systems doo +002142 (base 16) Advanced Control Systems doo + Bulevar Zorana Djindjica 8a + Belgrade Serbia 11070 + YU + +00-1F-FA (hex) Coretree, Co, Ltd +001FFA (base 16) Coretree, Co, Ltd + #502 IT Venture Town, 694 + Daejeon 305-510 + KR + +00-1F-F5 (hex) Kongsberg Defence & Aerospace +001FF5 (base 16) Kongsberg Defence & Aerospace + Olav Brunborgs vei 6 + Billingstad 1396 + NO + +00-1F-F2 (hex) VIA Technologies, Inc. +001FF2 (base 16) VIA Technologies, Inc. + 1F, 531, Chung-Cheng Road + Hsin-Tien Taipei 231 + TW + +00-21-01 (hex) Aplicaciones Electronicas Quasar (AEQ) +002101 (base 16) Aplicaciones Electronicas Quasar (AEQ) + C/Rey Pastor 40 + Leganes Madrid 28914 + ES + +00-21-03 (hex) GHI Electronics, LLC +002103 (base 16) GHI Electronics, LLC + 35555 Garfield Rd. + Clinton Township MI 48035 + US + +00-1F-F8 (hex) Siemens AG, Sector Industry, Drive Technologies, Motion Control Systems +001FF8 (base 16) Siemens AG, Sector Industry, Drive Technologies, Motion Control Systems + Frauenauracherstraße 80 + Erlangen Bavaria 91056 + DE + +00-1F-D0 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +001FD0 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + + Pin-Jen Taoyuan 324 + TW + +00-1F-D1 (hex) OPTEX CO.,LTD. +001FD1 (base 16) OPTEX CO.,LTD. + 5-8-12 + Otsu Shiga 520-0101 + JP + +00-1F-C9 (hex) Cisco Systems, Inc +001FC9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1F-DC (hex) Mobile Safe Track Ltd +001FDC (base 16) Mobile Safe Track Ltd + Niemenkatu 73 + 15149 Lahti + FI + +00-1F-D6 (hex) Shenzhen Allywll +001FD6 (base 16) Shenzhen Allywll + Kejiyuan Nanshan + Shenzhen Guangdong 518057 + CN + +00-21-17 (hex) Tellord +002117 (base 16) Tellord + Gurogu Gurodong 170-5 Woolim e-Biz Center 709 + Seoul 152-050 + KR + +00-21-0F (hex) Cernium Corp +00210F (base 16) Cernium Corp + 1943 Isaac Newton Sq + Reston VA 20190 + US + +00-1F-F1 (hex) Paradox Hellas S.A. +001FF1 (base 16) Paradox Hellas S.A. + 3 Korinthoy St + Athens Attiki 14451 + GR + +00-1F-E6 (hex) Alphion Corporation +001FE6 (base 16) Alphion Corporation + 196 Princeton Hightstown Rd. + Princeton Junction NJ 08550 + US + +00-1F-CF (hex) MSI Technology GmbH +001FCF (base 16) MSI Technology GmbH + Hanauer Landstraße 328-330 + Frankfurt am Main Hessen 60314 + DE + +00-1F-9C (hex) LEDCO +001F9C (base 16) LEDCO + 47801 W Anchor Court + Plymouth MI 48170 + US + +00-1F-90 (hex) Actiontec Electronics, Inc +001F90 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +00-1F-91 (hex) DBS Lodging Technologies, LLC +001F91 (base 16) DBS Lodging Technologies, LLC + 21196 Limber + Mission Viejo CA 92692 + US + +00-1F-98 (hex) DAIICHI-DENTSU LTD. +001F98 (base 16) DAIICHI-DENTSU LTD. + OOMORI 690-1 + KANI GIFU 509-0238 + JP + +00-1F-93 (hex) Xiotech Corporation +001F93 (base 16) Xiotech Corporation + 6455 Flying Cloud Drive + Eden Prairie MN 55344 + US + +00-1F-51 (hex) HD Communications Corp +001F51 (base 16) HD Communications Corp + 2180 Fifth Ave + Ronkonkoma NY 11779 + US + +00-1F-53 (hex) GEMAC Chemnitz GmbH +001F53 (base 16) GEMAC Chemnitz GmbH + Zwickauer Straße 227 + Chemnitz Sachsen 09116 + DE + +00-1F-50 (hex) Swissdis AG +001F50 (base 16) Swissdis AG + Grasweg 7 + Schwarzhaeusern BE 4911 + CH + +00-1F-4C (hex) Roseman Engineering Ltd +001F4C (base 16) Roseman Engineering Ltd + 65 Weizman Street + Givataim Israel 53468 + IL + +00-1F-A9 (hex) Atlanta DTH, Inc. +001FA9 (base 16) Atlanta DTH, Inc. + 5388 New Peachtree Rd + Chamblee GA 30341 + US + +00-1F-A3 (hex) T&W Electronics(Shenzhen)Co.,Ltd. +001FA3 (base 16) T&W Electronics(Shenzhen)Co.,Ltd. + 2F,Baiying Building, No.1019, + ShenZhen GuangDong 518067 + CN + +00-1F-A2 (hex) Datron World Communications, Inc. +001FA2 (base 16) Datron World Communications, Inc. + 3030 Enterprise Court + Vista California 92081 + US + +00-1F-70 (hex) Botik Technologies LTD +001F70 (base 16) Botik Technologies LTD + Trudovaya, 1 + Pereslavl-Zalessky Yaroslavskaya 152020 + RU + +00-1F-64 (hex) Beijing Autelan Technology Inc. +001F64 (base 16) Beijing Autelan Technology Inc. + Room B-12B01, Keshi Plaza, Xinxi road, + Beijing 100085 + CN + +00-1F-6D (hex) Cisco Systems, Inc +001F6D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1F-24 (hex) DIGITVIEW TECHNOLOGY CO., LTD. +001F24 (base 16) DIGITVIEW TECHNOLOGY CO., LTD. + NO. 14-22, TIAN-FU , + TAIPEI COUNTY 237 + TW + +00-1F-21 (hex) Inner Mongolia Yin An Science & Technology Development Co.,L +001F21 (base 16) Inner Mongolia Yin An Science & Technology Development Co.,L + YinAn Building Yiwei Road.RuYi + Beijing 010010 + CN + +00-1F-22 (hex) Source Photonics, Inc. +001F22 (base 16) Source Photonics, Inc. + 20550 Nordhoff Street + Chatsworth CA 91311 + US + +00-1F-1D (hex) Atlas Material Testing Technology LLC +001F1D (base 16) Atlas Material Testing Technology LLC + 4114 N. Ravenswood Ave. + Chicago IL 60613 + US + +00-1F-15 (hex) Bioscrypt Inc +001F15 (base 16) Bioscrypt Inc + 505 Cochrane Drive + Markham Ontario L3R 8E3 + CA + +00-1F-2B (hex) Orange Logic +001F2B (base 16) Orange Logic + #706 AceTechnoTower 10-cha,470-5 + SEOUL 153-789 + KR + +00-1F-2A (hex) ACCM +001F2A (base 16) ACCM + Obour Industrial City, Industrial zone A, lot14, block 12006. + Cairo + EG + +00-1F-30 (hex) Travelping +001F30 (base 16) Travelping + + Chemnitz Saxony 09113 + DE + +00-1F-48 (hex) Mojix Inc. +001F48 (base 16) Mojix Inc. + 11075 Santa Monica Blvd. + Los Angeles Ca 90025 + US + +00-1F-3E (hex) RP-Technik e.K. +001F3E (base 16) RP-Technik e.K. + Hermann-Staudinger-Str. 10-16 + Rodgau Hessen 63110 + DE + +00-1E-F0 (hex) Gigafin Networks +001EF0 (base 16) Gigafin Networks + 19050 Pruneridge + Cupertino CA 95014 + US + +00-1E-F2 (hex) Micro Motion Inc +001EF2 (base 16) Micro Motion Inc + 7070 Winchester Circle + Boulder CO 80301 + US + +00-1F-37 (hex) Genesis I&C +001F37 (base 16) Genesis I&C + #515 lisantekeunotaun + Goyang Gyeonggi 410-722 + KR + +00-1F-2C (hex) Starbridge Networks +001F2C (base 16) Starbridge Networks + 3265 Meridian Parkway + Weston FL 33331 + US + +00-1F-31 (hex) Radiocomp +001F31 (base 16) Radiocomp + Krakesvej 17 + Hilleroed Copenhagen 3400 + DK + +00-1F-12 (hex) Juniper Networks +001F12 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-1E-EA (hex) Sensor Switch, Inc. +001EEA (base 16) Sensor Switch, Inc. + 900 Northrop Road + Wallingford CT 06492 + US + +00-1F-04 (hex) Granch Ltd. +001F04 (base 16) Granch Ltd. + 40 Koroleva str. + Novosibirsk NSO 630015 + RU + +00-1E-94 (hex) SUPERCOM TECHNOLOGY CORPORATION +001E94 (base 16) SUPERCOM TECHNOLOGY CORPORATION + 8F, NO 100-1, Ming-Chuan Rd. + Shing Tien Taipei 231 + TW + +00-1E-8F (hex) CANON INC. +001E8F (base 16) CANON INC. + 3-30-2 + Ohta-Ku Tokyo 146-8501 + JP + +00-1E-A5 (hex) ROBOTOUS, Inc. +001EA5 (base 16) ROBOTOUS, Inc. + Nex Center-201(Lab.), SK n Technopark + Seongnam-si Gyeonggi-do 462-120 + KR + +00-1E-A7 (hex) Actiontec Electronics, Inc +001EA7 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +00-1E-A0 (hex) XLN-t +001EA0 (base 16) XLN-t + Hoogstraat 52 + Putte Antwerp B2580 + BE + +00-1E-98 (hex) GreenLine Communications +001E98 (base 16) GreenLine Communications + Alrabiah - Alrabeea Street + Amman Central Region 11953 + JO + +00-1E-9A (hex) HAMILTON Bonaduz AG +001E9A (base 16) HAMILTON Bonaduz AG + Via Crusch 8 + Bonaduz Graubuenden 7402 + CH + +00-1E-DF (hex) Master Industrialization Center Kista +001EDF (base 16) Master Industrialization Center Kista + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +00-1E-E3 (hex) T&W Electronics (ShenZhen) Co.,Ltd +001EE3 (base 16) T&W Electronics (ShenZhen) Co.,Ltd + 2F Baiying Building, No.19, NanhaiRd., Nanshan Dist + ShenZhen GuangDong 518052 + CN + +00-1E-D9 (hex) Mitsubishi Precision Co.,LTd. +001ED9 (base 16) Mitsubishi Precision Co.,LTd. + 345 KAMIMACHIYA + KAMAKURA-City KANAGAWA-Prefecture 247-8505 + JP + +00-1E-D3 (hex) Dot Technology Int'l Co., Ltd. +001ED3 (base 16) Dot Technology Int'l Co., Ltd. + Unit 1001, Fourseas Building 208-212, Nathan Road + Kowloon + HK + +00-1E-A6 (hex) Best IT World (India) Pvt. Ltd. +001EA6 (base 16) Best IT World (India) Pvt. Ltd. + 87/70/93 Mistry Industrial Complex, + Mumbai Maharashtra 400093 + IN + +00-1E-83 (hex) LAN/MAN Standards Association (LMSC) +001E83 (base 16) LAN/MAN Standards Association (LMSC) + C/O IEEE Standards Association + Piscataway NJ 08855-1331 + US + +00-1E-7C (hex) Taiwick Limited +001E7C (base 16) Taiwick Limited + 5/F., Block E, Hing Yip Factory Bldg., + Hong Kong China 852 + HK + +00-1E-CF (hex) PHILIPS ELECTRONICS UK LTD +001ECF (base 16) PHILIPS ELECTRONICS UK LTD + PHILIPS CENTRE + GUILDFORD SURREY GU2 8XH + GB + +00-1E-22 (hex) ARVOO Imaging Products BV +001E22 (base 16) ARVOO Imaging Products BV + Tasveld 13 + Montfoort UT 3417 XS + NL + +00-1E-1A (hex) Best Source Taiwan Inc. +001E1A (base 16) Best Source Taiwan Inc. + 2F, No.16, Lane 56, Jhongjheng W. Rd., + Jhubei City, Hsinchu County 302 + TW + +00-1E-19 (hex) GTRI +001E19 (base 16) GTRI + M/S 0821 + Atlanta GA 30332 + US + +00-1E-14 (hex) Cisco Systems, Inc +001E14 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-44 (hex) SANTEC +001E44 (base 16) SANTEC + An der Strusbek 31 + Ahrensburg Schleswig Holstein 22926 + DE + +00-1E-62 (hex) Siemon +001E62 (base 16) Siemon + 27 Siemon Company Drive + Watertown CT 06795 + US + +00-1E-5C (hex) RB GeneralEkonomik +001E5C (base 16) RB GeneralEkonomik + Bulevar despota stefana 59a + Beograd Serbia 11000 + YU + +00-1E-5D (hex) Holosys d.o.o. +001E5D (base 16) Holosys d.o.o. + Kovinska 4 + Zagreb 10090 + HR + +00-1E-78 (hex) Owitek Technology Ltd., +001E78 (base 16) Owitek Technology Ltd., + No.2, Lane 78, Cingshan 6th St., + Taoyuan County 32657 + TW + +00-1E-7A (hex) Cisco Systems, Inc +001E7A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-27 (hex) SBN TECH Co.,Ltd. +001E27 (base 16) SBN TECH Co.,Ltd. + #706 Industrial Academic Center, Konkuk University, Hwayang-dong, Gwangjin-gu + Seoul 143-701 + KR + +00-1E-60 (hex) Digital Lighting Systems, Inc +001E60 (base 16) Digital Lighting Systems, Inc + 12302 Sw 128th ct, #105 + Miami FL 33186 + US + +00-1E-6C (hex) Opaque Systems +001E6C (base 16) Opaque Systems + 4820 Fisher Road + Athens OH 45701 + US + +00-1E-2F (hex) DiMoto Pty Ltd +001E2F (base 16) DiMoto Pty Ltd + 7 Meljaren Place + Buderim Queensland 4556 + AU + +00-1E-36 (hex) IPTE +001E36 (base 16) IPTE + Geleenlaan 5 + Genk Limburg 3600 + BE + +00-1D-A7 (hex) Seamless Internet +001DA7 (base 16) Seamless Internet + 2050 Russett Way Suite 338 + Carson City Nevada 89703 + US + +00-1D-A5 (hex) WB Electronics +001DA5 (base 16) WB Electronics + Langelandsvej 1A + Herning Herning 7400 + DK + +00-1D-A8 (hex) Takahata Electronics Co.,Ltd +001DA8 (base 16) Takahata Electronics Co.,Ltd + 1188,Kubota,Kubota-machi + Yonezawa-shi Yamagata-Pref. 992-0003 + JP + +00-1D-A9 (hex) Castles Technology, Co., LTD +001DA9 (base 16) Castles Technology, Co., LTD + 2F, No.205, Sec 3 Beishin Rd., + Hsin-Tien City Taipei 231 + TW + +00-1D-CB (hex) Exéns Development Oy +001DCB (base 16) Exéns Development Oy + Kauppakatu 36 + Kajaani Kainuu 87100 + FI + +00-1D-CA (hex) PAV Electronics Limited +001DCA (base 16) PAV Electronics Limited + 7 Laverock Road + Airdrie Lanarkshire ML6 7UD + GB + +00-1D-C2 (hex) XORTEC OY +001DC2 (base 16) XORTEC OY + Höytämöntie 6 + Lempäälä Pirkanmaa 33880 + FI + +00-1E-0E (hex) MAXI VIEW HOLDINGS LIMITED +001E0E (base 16) MAXI VIEW HOLDINGS LIMITED + Suite 2302,23/F Great Eagle Centre, 23 Harbour Road, Wanchai + Hong Kong + CN + +00-1E-0F (hex) Briot International +001E0F (base 16) Briot International + 2 rue roger Bonnet + Pont de l'Arche Eure 27340 + FR + +00-1D-E3 (hex) Intuicom +001DE3 (base 16) Intuicom + 4900 Nautilus CT N + Boulder CO 80301 + US + +00-1D-DE (hex) Zhejiang Broadcast&Television Technology Co.,Ltd. +001DDE (base 16) Zhejiang Broadcast&Television Technology Co.,Ltd. + Building No.16,Xidoumen Industry Park,Wenyi Road, + Hangzhou Zhejiang 310012 + CN + +00-1D-E5 (hex) Cisco Systems, Inc +001DE5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1D-EC (hex) Marusys +001DEC (base 16) Marusys + Eunsung Bldg. 5F + Seoul 135-763 + KR + +00-1D-E8 (hex) Nikko Denki Tsushin Corporation(NDTC) +001DE8 (base 16) Nikko Denki Tsushin Corporation(NDTC) + 440 Kamoshida-town, Aoba-ku + Yokohama 227-0033 + JP + +00-1D-DA (hex) Mikroelektronika spol. s r. o. +001DDA (base 16) Mikroelektronika spol. s r. o. + Dráby 849 + Vysoké Mýto CZ 566 01 + CZ + +00-1D-B0 (hex) FuJian HengTong Information Technology Co.,Ltd +001DB0 (base 16) FuJian HengTong Information Technology Co.,Ltd + No.14-804,Building 2,JinXiuFuCheng,No.338,HuaLin Road + FuZhou City FuJian Province 350001 + CN + +00-1D-B8 (hex) Intoto Inc. +001DB8 (base 16) Intoto Inc. + 3100 De La Cruz Blvd. #300 + Santa Clara CA 95054 + US + +00-1D-F5 (hex) Sunshine Co,LTD +001DF5 (base 16) Sunshine Co,LTD + 1-3-5 Kojimachi + TOKYO Kanto region 102-0083 + JP + +00-1D-F0 (hex) Vidient Systems, Inc. +001DF0 (base 16) Vidient Systems, Inc. + 4000 Burton Drive + Santa Clara CA 94054 + US + +00-1D-FE (hex) Palm, Inc +001DFE (base 16) Palm, Inc + 950 West Maude Ave + Sunnyvale CA 94085 + US + +00-1D-52 (hex) Defzone B.V. +001D52 (base 16) Defzone B.V. + Transportcentrum 10 + Enschede Overijssel 7547 RW + NL + +00-1D-4A (hex) Carestream Health, Inc. +001D4A (base 16) Carestream Health, Inc. + 150 Verona Street + Rochestser NY 14608 + US + +00-1D-96 (hex) WatchGuard Video +001D96 (base 16) WatchGuard Video + 3001 Summit Ave. + Plano TX 75074 + US + +00-1D-8F (hex) PureWave Networks +001D8F (base 16) PureWave Networks + 2660-C Marine Way + Mountain View CA 94043 + US + +00-1D-8C (hex) La Crosse Technology LTD +001D8C (base 16) La Crosse Technology LTD + 2809 Losey Blvd. So. + La Crosse WI 54601 + US + +00-1D-64 (hex) Adam Communications Systems Int Ltd +001D64 (base 16) Adam Communications Systems Int Ltd + The Mission + Stockport Cheshire SK1 3AH + GB + +00-1D-5E (hex) COMING MEDIA CORP. +001D5E (base 16) COMING MEDIA CORP. + BONA Bld. 4th Fl., 548-18 + Seoul 135-158 + KR + +00-1D-55 (hex) ZANTAZ, Inc +001D55 (base 16) ZANTAZ, Inc + 5758 W. Las Positas Avenue + Pleasanton CA 94588 + US + +00-1D-A1 (hex) Cisco Systems, Inc +001DA1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1D-71 (hex) Cisco Systems, Inc +001D71 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1D-65 (hex) Microwave Radio Communications +001D65 (base 16) Microwave Radio Communications + 101 Billerica Avemue, Bldg 6 + N. Billerica MA 01862 + US + +00-1D-50 (hex) SPINETIX SA +001D50 (base 16) SPINETIX SA + Parc Scientifique de l'EPFL, Bâtiment C + Lausanne VD 1015 + CH + +00-1D-45 (hex) Cisco Systems, Inc +001D45 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1D-69 (hex) Knorr-Bremse IT-Services GmbH +001D69 (base 16) Knorr-Bremse IT-Services GmbH + Moosacher Str. 80 + Muenchen BY 80809 + DE + +00-1C-F8 (hex) Parade Technologies, Ltd. +001CF8 (base 16) Parade Technologies, Ltd. + C/O Parade Technologies, Inc. + Sunnyvale CA 94085 + US + +00-1C-F7 (hex) AudioScience +001CF7 (base 16) AudioScience + 729 west 16th st + Costa Mesa California 92627 + US + +00-1C-F6 (hex) Cisco Systems, Inc +001CF6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1C-F5 (hex) Wiseblue Technology Limited +001CF5 (base 16) Wiseblue Technology Limited + Rm G5, 5/F, Kingsford Industrial Building Phase II, 26-32 Kwai Hei Street, + Kwai Chung N.T. + HK + +00-1C-EE (hex) SHARP Corporation +001CEE (base 16) SHARP Corporation + 22-22,Nagaike-cho + Osaka city Osaka prefecture 545-8522 + JP + +00-1D-07 (hex) Shenzhen Sang Fei Consumer Communications Co.,Ltd +001D07 (base 16) Shenzhen Sang Fei Consumer Communications Co.,Ltd + 11 Science and Technology Road, + Shenzhen Guangdong 518057 + CN + +00-1D-06 (hex) HM Electronics, Inc. +001D06 (base 16) HM Electronics, Inc. + 14110 Stowe Drive + Poway CA 92064 + US + +00-1D-01 (hex) Neptune Digital +001D01 (base 16) Neptune Digital + Mednarodni mejni prehod 6 + Vrtojba Nova Gorica 5290 + SI + +00-1D-33 (hex) Maverick Systems Inc. +001D33 (base 16) Maverick Systems Inc. + 908, Daerungposttower 2-cha, 182-13 + Seoul 152-790 + KR + +00-1D-2C (hex) Wavetrend Technologies (Pty) Limited +001D2C (base 16) Wavetrend Technologies (Pty) Limited + Wavetrend House, Building 816/3 + Gauteng 2021 + ZA + +00-1C-CF (hex) LIMETEK +001CCF (base 16) LIMETEK + #213-1, Byucksan Digital Valley II, 480-10, Gasan-dong, + Seoul 153-783 + KR + +00-1D-24 (hex) Aclara Power-Line Systems Inc. +001D24 (base 16) Aclara Power-Line Systems Inc. + 945 Hornet Drive + Hazelwood MO 63042 + US + +00-1D-18 (hex) Power Innovation GmbH +001D18 (base 16) Power Innovation GmbH + Rehland 2 + Achim Niedersachsen 28832 + DE + +00-1D-1B (hex) Sangean Electronics Inc. +001D1B (base 16) Sangean Electronics Inc. + No. 18, Lane 7, Li-De street + Chung Ho City Taipei Hsien 235 + TW + +00-1D-17 (hex) Digital Sky Corporation +001D17 (base 16) Digital Sky Corporation + 5-5-15 Sotokanda, + Chiyoda-ku Tokyo 101-0021 + JP + +00-1D-27 (hex) NAC-INTERCOM +001D27 (base 16) NAC-INTERCOM + AVDA. RICARDO MELLA 123-B + VIGO PONTEVEDRA 36330 + ES + +00-1C-E3 (hex) Optimedical Systems +001CE3 (base 16) Optimedical Systems + 235 Hembree Park Drive + Roswell GA 30076 + US + +00-1C-DE (hex) Interactive Multimedia eXchange Inc. +001CDE (base 16) Interactive Multimedia eXchange Inc. + NO. 165 Wenlin Road. + Taipei Taiwan 111 + TW + +00-1D-36 (hex) ELECTRONICS CORPORATION OF INDIA LIMITED +001D36 (base 16) ELECTRONICS CORPORATION OF INDIA LIMITED + CONTROL AND AUTOMATION DIVISION-3 + HYDERABAD ANDHRA PRADESH 500 062 + IN + +00-1C-80 (hex) New Business Division/Rhea-Information CO., LTD. +001C80 (base 16) New Business Division/Rhea-Information CO., LTD. + 4F 594 Yeong Pung Bldg, Gueui-Dong + Seoul Gwangjin-Gu 143-200 + KR + +00-1C-83 (hex) New Level Telecom Co., Ltd. +001C83 (base 16) New Level Telecom Co., Ltd. + INNOPLEX 1-703 + Seoul 153-803 + KR + +00-1C-76 (hex) The Wandsworth Group Ltd +001C76 (base 16) The Wandsworth Group Ltd + Albert Drive + Woking Surrey GU21 5SE + GB + +00-1C-72 (hex) Mayer & Cie GmbH & Co KG +001C72 (base 16) Mayer & Cie GmbH & Co KG + Emil Mayer Strasse 10 + Albstadt Baden-Württemberg 72461 + DE + +00-1C-AD (hex) Wuhan Telecommunication Devices Co.,Ltd +001CAD (base 16) Wuhan Telecommunication Devices Co.,Ltd + 88 Youkeyuan Road,Hongshan District + Wuhan Hubei 430074 + CN + +00-1C-A7 (hex) International Quartz Limited +001CA7 (base 16) International Quartz Limited + 2nd Floor, 2, Dai Wang Street, + Hong Kong 852 + CN + +00-1C-AB (hex) Meyer Sound Laboratories, Inc. +001CAB (base 16) Meyer Sound Laboratories, Inc. + 2832 San Pablo Ave. + Berkeley CA 94702 + US + +00-1C-9E (hex) Dualtech IT AB +001C9E (base 16) Dualtech IT AB + Banehagsgatan 1F + GOTHENBURG Västra Götaland 41451 + SE + +00-1C-C8 (hex) INDUSTRONIC Industrie-Electronic GmbH & Co. KG +001CC8 (base 16) INDUSTRONIC Industrie-Electronic GmbH & Co. KG + Carl-Jacob-Kolb-Weg 1 + Wertheim Baden-Württemberg 97877 + DE + +00-1C-C6 (hex) ProStor Systems +001CC6 (base 16) ProStor Systems + 5555 Central Avenue + Boulder Colorado 80301 + US + +00-1C-BE (hex) Nintendo Co., Ltd. +001CBE (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-1C-94 (hex) LI-COR Biosciences +001C94 (base 16) LI-COR Biosciences + 4647 Superior Street + Lincoln NE 68504 + US + +00-1C-8C (hex) DIAL TECHNOLOGY LTD. +001C8C (base 16) DIAL TECHNOLOGY LTD. + 6F-4, NO.18, LANE.609, SEC.5, CHONGSIN RD., + SANCHONG CITY TAIPEI COUNTY 241 + TW + +00-1C-CA (hex) Shanghai Gaozhi Science & Technology Development Co. +001CCA (base 16) Shanghai Gaozhi Science & Technology Development Co. + No.283 Qin Jiang Rd. Shanghai,China + Shanghai 200233 + CN + +00-1C-C9 (hex) Kaise Electronic Technology Co., Ltd. +001CC9 (base 16) Kaise Electronic Technology Co., Ltd. + No.678, Wunsyue Rd., Zuoying District, + Kaohsiung 813 + TW + +00-1C-93 (hex) ExaDigm Inc +001C93 (base 16) ExaDigm Inc + 2871 Pullman St + Santa Ana CA 92705 + US + +00-1C-85 (hex) Eunicorn +001C85 (base 16) Eunicorn + 226-16 unbo b/d suckchon-dong songpa-gu + seoul 138845 + KR + +00-1C-67 (hex) Pumpkin Networks, Inc. +001C67 (base 16) Pumpkin Networks, Inc. + 3FL JungHo Bldg, 108-4 Sangdo-Dong, Dongjak-Gu + SEOUL 156-030 + KR + +00-1C-60 (hex) CSP Frontier Technologies,Inc. +001C60 (base 16) CSP Frontier Technologies,Inc. + 3-2-3,Sasazuka + Shibuya-ku Tokyo 151-0073 + JP + +00-1C-6A (hex) Weiss Engineering Ltd. +001C6A (base 16) Weiss Engineering Ltd. + Florastrasse 42 + Uster ZH 8610 + CH + +00-1C-0A (hex) Shenzhen AEE Technology Co.,Ltd. +001C0A (base 16) Shenzhen AEE Technology Co.,Ltd. + 1st Floor B Building, Shenzhen, + Shenzhen Guangdong 518057 + CN + +00-1C-0D (hex) G-Technology, Inc. +001C0D (base 16) G-Technology, Inc. + 1653 Stanford Street + Santa Monica CA 90404 + US + +00-1C-03 (hex) Betty TV Technology AG +001C03 (base 16) Betty TV Technology AG + Hardturmstrasse 2 + Zurich 80005 + CH + +00-1C-46 (hex) QTUM +001C46 (base 16) QTUM + #507 Byucksan/Kyungin Digital Valley 2 481-10 + Seoul 153-783 + KR + +00-1C-42 (hex) Parallels, Inc. +001C42 (base 16) Parallels, Inc. + 660 SW 39h Street + Renton WA 98057 + US + +00-1C-3E (hex) ECKey Corporation +001C3E (base 16) ECKey Corporation + 206A W James St + Lancaster PA 17603 + US + +00-1C-51 (hex) Celeno Communications +001C51 (base 16) Celeno Communications + 22 Zarhin Street + Ra'anana 43665 + IL + +00-1C-54 (hex) Hillstone Networks Inc +001C54 (base 16) Hillstone Networks Inc + A-1905 e-Wing Center + Beijing 100086 + CN + +00-1C-59 (hex) DEVON IT +001C59 (base 16) DEVON IT + 1100 FIRST AVENUE + KING OF PRUSSIA PA 19406 + US + +00-1C-22 (hex) Aeris Elettronica s.r.l. +001C22 (base 16) Aeris Elettronica s.r.l. + Zona Ind.le Vallecupa + Colonnella Teramo 64010 + IT + +00-1C-1D (hex) CHENZHOU GOSPELL DIGITAL TECHNOLOGY CO.,LTD +001C1D (base 16) CHENZHOU GOSPELL DIGITAL TECHNOLOGY CO.,LTD + BAILUTANG,SUXIAN DISTRICT, + CHENZHOU HUNAN 423025 + CN + +00-1C-39 (hex) S Netsystems Inc. +001C39 (base 16) S Netsystems Inc. + 10F Sungwon Bldg., 141 Samsung-Dong + Seoul 135-716 + KR + +00-1C-37 (hex) Callpod, Inc. +001C37 (base 16) Callpod, Inc. + 850 W. Jackson + Chicago IL 60607 + US + +00-1C-33 (hex) Sutron +001C33 (base 16) Sutron + 21300 Ridgetop Cir + Sterling VA 20166 + US + +00-1B-F6 (hex) CONWISE Technology Corporation Ltd. +001BF6 (base 16) CONWISE Technology Corporation Ltd. + 2F No.44, Park Ave. 2, Hsinchu Science Park + Hsinchu City 30075 + TW + +00-1B-F8 (hex) Digitrax Inc. +001BF8 (base 16) Digitrax Inc. + 2443 Transmitter Rd, + Panama City FL 32404 + US + +00-1C-2F (hex) Pfister GmbH +001C2F (base 16) Pfister GmbH + Stätzlinger SStraße 70 + Augsburg Bavaria 86165 + DE + +00-1C-27 (hex) Sunell Electronics Co. +001C27 (base 16) Sunell Electronics Co. + 3rd Floor,Bldg.514,BaGua Rd + ShenZhen Guangdong 518029 + CN + +00-1C-0F (hex) Cisco Systems, Inc +001C0F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1C-48 (hex) WiDeFi, Inc. +001C48 (base 16) WiDeFi, Inc. + 1333 Gateway Blvd + Melbourne FL 32901 + US + +00-1B-AD (hex) iControl Incorporated +001BAD (base 16) iControl Incorporated + 3235 Kifer Road + Santa Clara California 95051 + US + +00-1B-A7 (hex) Lorica Solutions +001BA7 (base 16) Lorica Solutions + 275 Northpointe Parkway + Amherst NY 14228 + US + +00-1B-A5 (hex) MyungMin Systems, Inc. +001BA5 (base 16) MyungMin Systems, Inc. + #410,Doosan Venture Dime 2-cha,1307-37 + Kyungki-do 431-060 + KR + +00-1B-F1 (hex) Nanjing SilverNet Software Co., Ltd. +001BF1 (base 16) Nanjing SilverNet Software Co., Ltd. + 3/F, 10 building, Nanjing World Window Technology & Software Park + Nanjing Jiangsu 210013 + CN + +00-1B-EF (hex) Blossoms Digital Technology Co.,Ltd. +001BEF (base 16) Blossoms Digital Technology Co.,Ltd. + BLK25,Hengfeng Ind.City,Hezhou + Shenzhen Guangdong 518126 + CN + +00-1B-EB (hex) DMP Electronics INC. +001BEB (base 16) DMP Electronics INC. + 8F., No.12, Wucyuan 7th Rd., + Taipei County 248 + TW + +00-1B-A2 (hex) IDS Imaging Development Systems GmbH +001BA2 (base 16) IDS Imaging Development Systems GmbH + Dimbacher Str. 6 + Obersulm BW 74182 + DE + +00-1B-9D (hex) Novus Security Sp. z o.o. +001B9D (base 16) Novus Security Sp. z o.o. + ul. Puławska 431 + Warsaw woj. mazowieckie 02-801 + PL + +00-1B-C9 (hex) FSN DISPLAY INC +001BC9 (base 16) FSN DISPLAY INC + Baeksuk-Dong 1141-1, Ilsan Techno Town 1009 + Koyang-si Kyeonggi-Do 410722 + KR + +00-1B-C3 (hex) Mobisolution Co.,Ltd +001BC3 (base 16) Mobisolution Co.,Ltd + 848-16 + Gumi Gyeongbuk 730-300 + KR + +00-1B-CE (hex) Measurement Devices Ltd +001BCE (base 16) Measurement Devices Ltd + Redwood House + York Yorkshire YO266QR + GB + +00-1B-B8 (hex) BLUEWAY ELECTRONIC CO;LTD +001BB8 (base 16) BLUEWAY ELECTRONIC CO;LTD + Workshop B,Dong Feng Village, + HuiZhou GuangDong 516008 + CN + +00-1B-B2 (hex) Intellect International NV +001BB2 (base 16) Intellect International NV + Kleine Kloosterstraat 23 + Zaventem Vlaamse brabant 1932 + BE + +00-1B-E7 (hex) Postek Electronics Co., Ltd. +001BE7 (base 16) Postek Electronics Co., Ltd. + Suite 510, Shanghang Building + Shen Zhen Guang Dong 518028 + CN + +00-1B-E3 (hex) Health Hero Network, Inc. +001BE3 (base 16) Health Hero Network, Inc. + 2000 Seaport Blvd. + Redwood City CA 94063 + US + +00-1B-DC (hex) Vencer Co., Ltd. +001BDC (base 16) Vencer Co., Ltd. + 20F-1, No.77, Sec.1, Hsin Tai Wu Rd., + Hsi Chih Taipei 221 + TW + +00-1B-D5 (hex) Cisco Systems, Inc +001BD5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1B-95 (hex) VIDEO SYSTEMS SRL +001B95 (base 16) VIDEO SYSTEMS SRL + Loc. Gorizzo, 16 + CAMINO AL TAGLIAMENTO UD + IT + +00-1B-90 (hex) Cisco Systems, Inc +001B90 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1B-7F (hex) TMN Technologies Telecomunicacoes Ltda +001B7F (base 16) TMN Technologies Telecomunicacoes Ltda + Rua Nilza, 422 + São Paulo SP 03651-120 + BR + +00-1B-7E (hex) Beckmann GmbH +001B7E (base 16) Beckmann GmbH + Brandtstraße 1 + Hoevelhof NRW 33161 + DE + +00-1B-7A (hex) Nintendo Co., Ltd. +001B7A (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-1B-34 (hex) Focus System Inc. +001B34 (base 16) Focus System Inc. + 19F-1, No. 266 Wen Hwa 2nd Rd., Sec. 1 + Linkou Taipei County + TW + +00-1B-3A (hex) SIMS Corp. +001B3A (base 16) SIMS Corp. + RAON Bldg, 9F, 92-8, Wonhyoro-2ga, Yongsan-gu + Seoul 140-847 + KR + +00-1B-2E (hex) Sinkyo Electron Inc +001B2E (base 16) Sinkyo Electron Inc + 3-3-21 asahigaoka + hino-city Tokyo 191-0065 + JP + +00-1B-5F (hex) Alien Technology +001B5F (base 16) Alien Technology + 18220 Butterfield Blvd. + Morgan Hill CA 95037 + US + +00-1B-61 (hex) Digital Acoustics, LLC +001B61 (base 16) Digital Acoustics, LLC + 37 Sherwood Terrace + Lake Bluff IL 60044 + US + +00-1B-5E (hex) BPL Limited +001B5E (base 16) BPL Limited + BPL Towers + Bangalore Karnataka 560001 + IN + +00-1B-5C (hex) Azuretec Co., Ltd. +001B5C (base 16) Azuretec Co., Ltd. + 3F, No.8, Alley 8, Lane 45, Baoxing Rd., Xindian Dist., + New Taipei City Taiwan 231 + TW + +00-1B-72 (hex) Sicep s.p.a. +001B72 (base 16) Sicep s.p.a. + Via calabria, 14 + Certaldo 50052 + IT + +00-1B-74 (hex) MiraLink Corporation +001B74 (base 16) MiraLink Corporation + 111 SW 5th Ave. + Portland OR 97204 + US + +00-1B-6D (hex) Midtronics, Inc. +001B6D (base 16) Midtronics, Inc. + 7000 Monroe St. + Willowbrook IL 60527 + US + +00-1B-6F (hex) Teletrak Ltd +001B6F (base 16) Teletrak Ltd + 214 Kepa Road + Auckland 1071 + NZ + +00-1B-4B (hex) SANION Co., Ltd. +001B4B (base 16) SANION Co., Ltd. + #208 ACETECHNO TOWER, 55-7, MULLAE-DONG 3GA, + YEONGDEUNGPO-GU SEOUL 150-992 + KR + +00-1B-2D (hex) Med-Eng Systems Inc. +001B2D (base 16) Med-Eng Systems Inc. + 2400 St. Laurent Blvd. + Ottawa Ontario K1G 6C4 + CA + +00-1B-87 (hex) Deepsound Tech. Co., Ltd +001B87 (base 16) Deepsound Tech. Co., Ltd + 3F No. 576 Sec. 1, Minsheng N. Rd., Gueishan Township, + Taoyuan 333 + TW + +00-1B-4D (hex) Areca Technology Corporation +001B4D (base 16) Areca Technology Corporation + 8F., No. 22, Lane 35, Ji-Hu Rd. + Taipei 114 + TW + +00-1A-E3 (hex) Cisco Systems, Inc +001AE3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1A-DF (hex) Interactivetv Pty Limited +001ADF (base 16) Interactivetv Pty Limited + Suite 10 Level 3 + Pyrmont, Sydney NSW 2009 + US + +00-1A-E1 (hex) EDGE ACCESS INC +001AE1 (base 16) EDGE ACCESS INC + 5440 BEAUMONT CENTER BLVD + TAMPA FL 33634 + US + +00-1A-E8 (hex) Unify Software and Solutions GmbH & Co. KG +001AE8 (base 16) Unify Software and Solutions GmbH & Co. KG + Mies-van-der-Rohe-Strasse 6 + Munich 80807 + DE + +00-1A-E9 (hex) Nintendo Co., Ltd. +001AE9 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-1A-E5 (hex) Mvox Technologies Inc. +001AE5 (base 16) Mvox Technologies Inc. + 19050 Pruneridge Ave + Cupertino CA 95014 + US + +00-1A-E4 (hex) Medicis Technologies Corporation +001AE4 (base 16) Medicis Technologies Corporation + 11818 North Creek Parkway N. + Bothell WA 98011 + US + +00-1A-F8 (hex) Copley Controls Corporation +001AF8 (base 16) Copley Controls Corporation + 20 Dan Road + Canton MA 02021 + US + +00-1A-F5 (hex) PENTAONE. CO., LTD. +001AF5 (base 16) PENTAONE. CO., LTD. + Hyo Chang Bldg, 3F, 1013-6, Inkye-dong Paldal-Gu, + Suwon City Gyunggi-Do 422-833 + KR + +00-1A-ED (hex) INCOTEC GmbH +001AED (base 16) INCOTEC GmbH + Blomestrasse 25 - 27 + Bielefeld NRW 33609 + DE + +00-1A-EE (hex) Shenztech Ltd +001AEE (base 16) Shenztech Ltd + 813, 8F, HOLLYWOOD PLAZA, 610 NATHAN ROAD, + KOWLOON 852 + HK + +00-1A-CE (hex) YUPITERU CORPORATION +001ACE (base 16) YUPITERU CORPORATION + 3, Dannoue, Iwazu-cho, Okazaki-city, Aichi + Okazaki Aichi 444-2144 + JP + +00-1A-CC (hex) Celestial Semiconductor, Ltd +001ACC (base 16) Celestial Semiconductor, Ltd + Ugland House, South Church Street, + George Town, Cayman Islands 00000 + KY + +00-1A-D2 (hex) Eletronica Nitron Ltda +001AD2 (base 16) Eletronica Nitron Ltda + Rua Dr. Ulisses Escobar 415 + Camanducaia Minas Gerais 37650-000 + BR + +00-1B-1D (hex) Phoenix International Co., Ltd +001B1D (base 16) Phoenix International Co., Ltd + 11F. No.42-1, Sec.1, Zhongyang N. Rd. Beitou + Taipei 112 + TW + +00-1B-1A (hex) e-trees Japan, Inc. +001B1A (base 16) e-trees Japan, Inc. + Oowada-cho 2-9-2 + Hachioji-city Tokyo 150-0001 + JP + +00-1B-12 (hex) Apprion +001B12 (base 16) Apprion + Nasa Ames Rerearch Center + Moffett Field California 94035 + US + +00-1A-FE (hex) SOFACREAL +001AFE (base 16) SOFACREAL + 149 avenue du MAINE + PARIS Region Parisienne 75014 + FR + +00-1A-F1 (hex) Embedded Artists AB +001AF1 (base 16) Embedded Artists AB + Davidshallsgatan 16 + Malmoe 21145 + SE + +00-1B-0D (hex) Cisco Systems, Inc +001B0D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1B-0A (hex) Intelligent Distributed Controls Ltd +001B0A (base 16) Intelligent Distributed Controls Ltd + Keynes House, Chester Park + Derby Derbyshire DE21 4AS + GB + +00-1A-B1 (hex) Asia Pacific Satellite Industries Co., Ltd. +001AB1 (base 16) Asia Pacific Satellite Industries Co., Ltd. + 9th FL, IT Castle 2-Dong, #550-1, Gasan-Dong, GeumCheon-Gu, + Seoul 153-768 + KR + +00-1A-B7 (hex) Ethos Networks LTD. +001AB7 (base 16) Ethos Networks LTD. + 2 Maskit St. + Herzlia 46766 + IL + +00-1A-B2 (hex) Cyber Solutions Inc. +001AB2 (base 16) Cyber Solutions Inc. + 6-6-3, Minami Yoshinari + Sendai Miyagi-ken 989-3204 + JP + +00-1A-97 (hex) fitivision technology Inc. +001A97 (base 16) fitivision technology Inc. + 8F, No. 356, Sec. 1, Neihu Rd + Taipei 114 + TW + +00-1A-90 (hex) Trópico Sistemas e Telecomunicações da Amazônia LTDA. +001A90 (base 16) Trópico Sistemas e Telecomunicações da Amazônia LTDA. + Rod. Campinas-Mogi-Mirim (SP 340) Km 118,5 + Campinas São Paulo 13.086-902 + BR + +00-1A-94 (hex) Votronic GmbH +001A94 (base 16) Votronic GmbH + Saarbruecker Str. 8 + St. Ingbert Saarland 66386 + DE + +00-1A-86 (hex) AdvancedIO Systems Inc +001A86 (base 16) AdvancedIO Systems Inc + 595 Howe Street, Suite 502 + Vancouver BC V6C 2T5 + CA + +00-1A-C7 (hex) UNIPOINT +001AC7 (base 16) UNIPOINT + 7F Gwangsung Bld 831-47 YeokSam-Dong + Seoul 135-936 + KR + +00-1A-C0 (hex) JOYBIEN TECHNOLOGIES CO., LTD. +001AC0 (base 16) JOYBIEN TECHNOLOGIES CO., LTD. + 14F-7, NO.2, JIAN 8TH RD., + NEW TAIPEI CITY TAIWAN 23511 + TW + +00-1A-9E (hex) ICON Digital International Limited +001A9E (base 16) ICON Digital International Limited + Suite2209, 22/F., SkyLine Tower, + + CN + +00-1A-98 (hex) Asotel Communication Limited Taiwan Branch +001A98 (base 16) Asotel Communication Limited Taiwan Branch + 3G17, No5, Hsin Yi Road, Sec. 5 + Taipei 110 + TW + +00-1A-72 (hex) Mosart Semiconductor Corp. +001A72 (base 16) Mosart Semiconductor Corp. + 23F., No.33, Sec.1, + Taipei 220 + TW + +00-1A-68 (hex) Weltec Enterprise Co., Ltd. +001A68 (base 16) Weltec Enterprise Co., Ltd. + 2F, No. 351 Yung Ho Rd. + Chung Ho 235 + TW + +00-1A-C2 (hex) YEC Co.,Ltd. +001AC2 (base 16) YEC Co.,Ltd. + 543-9 Tsuruma + Machida Tokyo 194-0004 + JP + +00-1A-A5 (hex) BRN Phoenix +001AA5 (base 16) BRN Phoenix + 2500 Augustine Drive, Suite 200 + Santa Clara CA 95054 + US + +00-1A-A2 (hex) Cisco Systems, Inc +001AA2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1A-9C (hex) RightHand Technologies, Inc. +001A9C (base 16) RightHand Technologies, Inc. + 7450 W Wilson Avenue + Chicago IL 60706 + US + +00-1A-7E (hex) LN Srithai Comm Ltd. +001A7E (base 16) LN Srithai Comm Ltd. + 71/12 M.5, Bangna-Trad Rd, KM.52, Thakam + Bangpakong Chachoengsao 24130 + TH + +00-1A-5A (hex) Korea Electric Power Data Network (KDN) Co., Ltd +001A5A (base 16) Korea Electric Power Data Network (KDN) Co., Ltd + 665 NAESON-DONG, + GYEONGGI-DO UIWANG-SI, NAESON-DONG 437-082 + KR + +00-1A-5F (hex) KitWorks.fi Ltd. +001A5F (base 16) KitWorks.fi Ltd. + Snowpolis + Vuokatti Kainuu 88610 + FI + +00-1A-35 (hex) BARTEC GmbH +001A35 (base 16) BARTEC GmbH + Schulstraße 30 + Gotteszell Bavaria 94239 + DE + +00-1A-37 (hex) Lear Corporation +001A37 (base 16) Lear Corporation + Industriestrasse 48 + Kronach Bayern 96317 + DE + +00-1A-38 (hex) Sanmina-SCI +001A38 (base 16) Sanmina-SCI + 13000 South Memorial Parkway + Huntsville AL 35803 + US + +00-1A-2B (hex) Ayecom Technology Co., Ltd. +001A2B (base 16) Ayecom Technology Co., Ltd. + No. 25, R&D Road 2, Science-Based Industrial Park + Hsinchu 300 + TW + +00-1A-28 (hex) ASWT Co., LTD. Taiwan Branch H.K. +001A28 (base 16) ASWT Co., LTD. Taiwan Branch H.K. + 7F., No.3 Lane 91, Dongmei Rd. + Hsinchu 30070 + TW + +00-1A-2C (hex) SATEC Co.,LTD +001A2C (base 16) SATEC Co.,LTD + 358-4, Palgok2-Dong, Sangnok-Gu + Ansan-Si Kyungki-Do 426-190 + KR + +00-1A-27 (hex) Ubistar +001A27 (base 16) Ubistar + 8F, Seongo Building, 587-23 + Seoul 135-747 + KR + +00-1A-21 (hex) Brookhuis Applied Technologies BV +001A21 (base 16) Brookhuis Applied Technologies BV + PO Box 79 + Enschede NL-7500 + NL + +00-19-FF (hex) Finnzymes +0019FF (base 16) Finnzymes + 800 West Cummings Park + Woburn MA 01801 + US + +00-19-FA (hex) Cable Vision Electronics CO., LTD. +0019FA (base 16) Cable Vision Electronics CO., LTD. + 12F-3, No.16, Chien Pa Rd. + Chung Ho City Taipei Hsien 235 + TW + +00-1A-5D (hex) Mobinnova Corp. +001A5D (base 16) Mobinnova Corp. + 11F, 845, CHUNG SHAN RD + TAOYUAN 33059 + TW + +00-1A-4D (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +001A4D (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + + Pin-Jen Taoyuan 324 + TW + +00-1A-48 (hex) Takacom Corporation +001A48 (base 16) Takacom Corporation + 304-709 Aza-Nishiyanma + Toki-shi Gifu-ken 509-5202 + JP + +00-1A-0B (hex) BONA TECHNOLOGY INC. +001A0B (base 16) BONA TECHNOLOGY INC. + 4F, E-Place Bldg., 719-24 + Seoul 135-080 + KR + +00-1A-06 (hex) OpVista, Inc. +001A06 (base 16) OpVista, Inc. + 870 North McCarthy Blvd. + Milpitas California 95035 + US + +00-1A-2E (hex) Ziova Coporation +001A2E (base 16) Ziova Coporation + Unit 3, 7-9 Sherriffs road + Lonsdale S.A. 5160 + AU + +00-1A-32 (hex) ACTIVA MULTIMEDIA +001A32 (base 16) ACTIVA MULTIMEDIA + SICP CSE + SANT JOAN DESPI BARCELONA 08970 + ES + +00-1A-00 (hex) MATRIX INC. +001A00 (base 16) MATRIX INC. + AS bld.3-13-20 + Osaka 530-0047 + JP + +00-19-AD (hex) BOBST SA +0019AD (base 16) BOBST SA + rte des flumeaux 50 + PRILLY VD 1008 + CH + +00-19-A2 (hex) ORDYN TECHNOLOGIES +0019A2 (base 16) ORDYN TECHNOLOGIES + Ozone Manay Tech Park, + Bangalore 560 068 + IN + +00-19-A5 (hex) RadarFind Corporation +0019A5 (base 16) RadarFind Corporation + 2100 Gateway Centre Blvd., Suite 150 + Morrisville NC 27560 + US + +00-19-93 (hex) Changshu Switchgear MFG. Co.,Ltd. (Former Changshu Switchgea +001993 (base 16) Changshu Switchgear MFG. Co.,Ltd. (Former Changshu Switchgea + No. 8 Jianye Road + Changshu Jiangsu 215500 + CN + +00-19-F1 (hex) Star Communication Network Technology Co.,Ltd +0019F1 (base 16) Star Communication Network Technology Co.,Ltd + 10/F,Tower B,SOHO New Town,No.88 jianguoRoad,Chaoyang District + Beijing 100022 + CN + +00-19-EC (hex) Sagamore Systems, Inc. +0019EC (base 16) Sagamore Systems, Inc. + 55 Middlesex Street + North Chelmsford MA 01863 + US + +00-19-CC (hex) RCG (HK) Ltd +0019CC (base 16) RCG (HK) Ltd + 9/F., Core C, Cyberport 3 + + HK + +00-19-C8 (hex) AnyDATA Corporation +0019C8 (base 16) AnyDATA Corporation + 18902 Bardeen Ave. + Irvine CA 91612 + US + +00-19-C4 (hex) Infocrypt Inc. +0019C4 (base 16) Infocrypt Inc. + 711, BYUCKSAN DIGITAL VALLEY 1 212-16, + Seoul 152-050 + KR + +00-19-BC (hex) ELECTRO CHANCE SRL +0019BC (base 16) ELECTRO CHANCE SRL + CARHUE 3179 + CAPITAL FEDERAL BUENOS AIRES 1440 + AR + +00-19-9B (hex) Diversified Technical Systems, Inc. +00199B (base 16) Diversified Technical Systems, Inc. + 909 Electric Avenue + Seal Beach California 90740 + US + +00-19-90 (hex) ELM DATA Co., Ltd. +001990 (base 16) ELM DATA Co., Ltd. + 2-15 TECHNO-PARK 1-CHOME + SAPPORO HOKKAIDO 004-0015 + JP + +00-19-8F (hex) Nokia Bell N.V. +00198F (base 16) Nokia Bell N.V. + Copernicuslaan 50 + Antwerp B-2018 + BE + +00-19-D8 (hex) MAXFOR +0019D8 (base 16) MAXFOR + #E 809, Bundang, Techno-Park + Seongnam-City Gyeonggi-Do 463-760 + KR + +00-19-D5 (hex) IP Innovations, Inc. +0019D5 (base 16) IP Innovations, Inc. + 1517 146th Ave + Dorr MI 49323 + US + +00-19-A3 (hex) asteel electronique atlantique +0019A3 (base 16) asteel electronique atlantique + za de la lande de saint jean + sainte marie de redon 35600 + FR + +00-19-EA (hex) TeraMage Technologies Co., Ltd. +0019EA (base 16) TeraMage Technologies Co., Ltd. + Golden Land Building Suite 907 + Beijing 100016 + CN + +00-19-6E (hex) Metacom (Pty) Ltd. +00196E (base 16) Metacom (Pty) Ltd. + 6 Ndabeni Business Park + Cape Town Western Cape 7405 + ZA + +00-19-65 (hex) YuHua TelTech (ShangHai) Co., Ltd. +001965 (base 16) YuHua TelTech (ShangHai) Co., Ltd. + YuHua R&D Building,27 xin jin qiao road, + SHANGHAI 201206 + CN + +00-19-66 (hex) Asiarock Technology Limited +001966 (base 16) Asiarock Technology Limited + P.O. Box957, Offshore Incorporations Centre + Road Town Tortola + VG + +00-19-7B (hex) Picotest Corp. +00197B (base 16) Picotest Corp. + 8F-1, 286-9, Hsin-Ya Rd., 80673 + Kaohsiung 80673 + TW + +00-19-73 (hex) Zeugma Systems +001973 (base 16) Zeugma Systems + Suite 250 + Richmond BC V6V 2R2 + CA + +00-19-75 (hex) Beijing Huisen networks technology Inc +001975 (base 16) Beijing Huisen networks technology Inc + Jia#2 of Xili of Baiyun road,Xicheng district + Beijing 100045 + CN + +00-19-40 (hex) Rackable Systems +001940 (base 16) Rackable Systems + 1933 Milmont Drive + Milpitas CA 95035 + US + +00-19-3C (hex) HighPoint Technologies Incorporated +00193C (base 16) HighPoint Technologies Incorporated + 1161 Cadillac Court + Milpitas CA 95035 + US + +00-19-5C (hex) Innotech Corporation +00195C (base 16) Innotech Corporation + 3-17-6 + Yokohama Kanagawa 222-8580 + JP + +00-19-5F (hex) Valemount Networks Corporation +00195F (base 16) Valemount Networks Corporation + 1201- 5th Ave + Valemount BC V0E2Z0 + CA + +00-19-48 (hex) AireSpider Networks +001948 (base 16) AireSpider Networks + 1171 Montague Express Way + Milpitas CA 95035 + US + +00-19-43 (hex) Belden +001943 (base 16) Belden + 793 Fort Mill Highway + Fort Mill South Carolina 29715 + US + +00-19-2E (hex) Spectral Instruments, Inc. +00192E (base 16) Spectral Instruments, Inc. + 420 N Bonita Ave + Tucson AZ 85745 + US + +00-19-2B (hex) Aclara RF Systems Inc. +00192B (base 16) Aclara RF Systems Inc. + 30400 Solon Road + Solon OH 44139 + US + +00-19-1E (hex) Beyondwiz Co., Ltd. +00191E (base 16) Beyondwiz Co., Ltd. + 3F, Daechang Bldg., + Sungnam Kyungki-do 463-825 + KR + +00-19-81 (hex) Vivox Inc +001981 (base 16) Vivox Inc + 40 Speen Street + Framingham MA 01701 + US + +00-19-45 (hex) RF COncepts, LLC +001945 (base 16) RF COncepts, LLC + 1148 Wagner Drive + Sevierville TN 37862 + US + +00-19-1F (hex) Microlink communications Inc. +00191F (base 16) Microlink communications Inc. + 8F , 31 , Hsintai Road , Chupei City , Hsinchu + Chupei Taiwan 302 + TW + +00-19-20 (hex) KUME electric Co.,Ltd. +001920 (base 16) KUME electric Co.,Ltd. + 4-2-24 Kitakawara + Itami-city Hyougo + JP + +00-19-26 (hex) BitsGen Co., Ltd. +001926 (base 16) BitsGen Co., Ltd. + #502, Owner's Tower, #16-5, Sunea-dong + Bundang-gu Seongnam-si 463-825 + KR + +00-19-29 (hex) 2M2B Montadora de Maquinas Bahia Brasil LTDA +001929 (base 16) 2M2B Montadora de Maquinas Bahia Brasil LTDA + Rua Djalma dutra, 668, Sete Portas + Salvador Bahia 40240080 + BR + +00-18-F1 (hex) Chunichi Denshi Co.,LTD. +0018F1 (base 16) Chunichi Denshi Co.,LTD. + 1 Denjiyama + Nagoya Aichi 458-8525 + JP + +00-18-F2 (hex) Beijing Tianyu Communication Equipment Co., Ltd +0018F2 (base 16) Beijing Tianyu Communication Equipment Co., Ltd + 27th Floor, Tengda Plaza + Beijing 100044 + CN + +00-18-EC (hex) Welding Technology Corporation +0018EC (base 16) Welding Technology Corporation + 24775 Crestview Court + Farmington Hills MI 48335 + US + +00-18-ED (hex) Accutech Ultrasystems Co., Ltd. +0018ED (base 16) Accutech Ultrasystems Co., Ltd. + 11F-4, No. 150, + CHUNG-HO CITY, TAIPEI HSIEN, 235 + TW + +00-19-0B (hex) Southern Vision Systems, Inc. +00190B (base 16) Southern Vision Systems, Inc. + 8215 Madison Blvd, Suite 150 + Madison AL 35758 + US + +00-19-03 (hex) Bigfoot Networks Inc +001903 (base 16) Bigfoot Networks Inc + 3925 West Braker Lane + Austin TX 78759 + US + +00-19-00 (hex) Intelliverese - DBA Voicecom +001900 (base 16) Intelliverese - DBA Voicecom + 5900 Windward Parkway + Alpharetta Georgia 30005 + US + +00-19-02 (hex) Cambridge Consultants Ltd +001902 (base 16) Cambridge Consultants Ltd + Science Park + Cambridge Cambs CB4 0DW + GB + +00-19-2A (hex) Antiope Associates +00192A (base 16) Antiope Associates + 18 Clay Street + Fair Haven New Jersey 07704 + US + +00-19-0F (hex) Advansus Corp. +00190F (base 16) Advansus Corp. + No.5 Shing Yeh Street, Kwei Hsiang + Taoyuan 333 + TW + +00-19-11 (hex) Just In Mobile Information Technologies (Shanghai) Co., Ltd. +001911 (base 16) Just In Mobile Information Technologies (Shanghai) Co., Ltd. + 5th Floor, 2nd Area, Haiwangxing Building, 62 Xingguang Ave., N.High-Tech Park + Chongqing 401121 + CN + +00-18-E0 (hex) ANAVEO +0018E0 (base 16) ANAVEO + Les Carrés du parc + CHAMPAGNE au MONT D'OR Rhône F-69410 + FR + +00-19-17 (hex) Posiflex Inc. +001917 (base 16) Posiflex Inc. + 6, Wu-Chuan Road + Taipei Hsien 248 + TW + +00-19-18 (hex) Interactive Wear AG +001918 (base 16) Interactive Wear AG + Petersbrunner Strasse 3 + Starnberg Bayern 82319 + DE + +00-18-CB (hex) Tecobest Technology Limited +0018CB (base 16) Tecobest Technology Limited + 53/F.,Block A,United Plaza, + Shenzhen Guangdong 518026 + CN + +00-18-CE (hex) Dreamtech Co., Ltd +0018CE (base 16) Dreamtech Co., Ltd + #340-5, Yang-dang Ri, Jik-san Myeon + Cheon-an si Chung-Nam 330810 + KR + +00-18-94 (hex) NPCore, Inc. +001894 (base 16) NPCore, Inc. + 1001, ISBIZ Tower + Youngdungpo Gu Seoul 150-105 + KR + +00-18-98 (hex) KINGSTATE ELECTRONICS CORPORATION +001898 (base 16) KINGSTATE ELECTRONICS CORPORATION + 10F, No.69-11, Sec.2, Chung Cheng E. Rd., + Taipei County 251 + TW + +00-18-92 (hex) ads-tec GmbH +001892 (base 16) ads-tec GmbH + Raiffeisenstrasse 14 + Leinfelden-Echterdingen BW 70771 + DE + +00-18-91 (hex) Zhongshan General K-mate Electronics Co., Ltd +001891 (base 16) Zhongshan General K-mate Electronics Co., Ltd + 3/F B1 Building, Fuwan Ind. Zone Sun Wen East Road + Zhongshan Guangdong 528403 + CN + +00-18-AD (hex) NIDEC SANKYO CORPORATION +0018AD (base 16) NIDEC SANKYO CORPORATION + 5329, Shimosuwa-machi, Suwa-gun + Nagano 393-8511 + JP + +00-18-AC (hex) Shanghai Jiao Da HISYS Technology Co. Ltd. +0018AC (base 16) Shanghai Jiao Da HISYS Technology Co. Ltd. + 7F Haoran HiTech Bldg., No.1954 Huashan Road + shanghai xuhui 200030 + US + +00-18-AB (hex) BEIJING LHWT MICROELECTRONICS INC. +0018AB (base 16) BEIJING LHWT MICROELECTRONICS INC. + 18/F,QUANTUM PLAZA,NO.27 ZHI CHUN RD.,HAI DIAN DISTRICT,BEIJING + + CN + +00-18-A5 (hex) ADigit Technologies Corp. +0018A5 (base 16) ADigit Technologies Corp. + Rm D302E,No.185 3F-2,Kur-Wong Road, + Tao-yuan, 325 + TW + +00-18-78 (hex) Mackware GmbH +001878 (base 16) Mackware GmbH + Schänzle 13 + Waiblingen Baden-Württemberg 71332 + DE + +00-18-6A (hex) Global Link Digital Technology Co,.LTD +00186A (base 16) Global Link Digital Technology Co,.LTD + Qibaoyiding Ind.Area + Dongguan Guangdong 523051 + CN + +00-18-6B (hex) Sambu Communics CO., LTD. +00186B (base 16) Sambu Communics CO., LTD. + 38B-1L Namdong Industrial Complex + Incheon 405-100 + KR + +00-18-6E (hex) 3Com Ltd +00186E (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +00-18-A6 (hex) Persistent Systems, LLC +0018A6 (base 16) Persistent Systems, LLC + 118 N. Howard St. #72 + Baltimore MD 21201 + US + +00-18-9B (hex) Thomson Inc. +00189B (base 16) Thomson Inc. + 101 West 103rd Street + Indianapolis IN 46290-1102 + US + +00-18-B2 (hex) ADEUNIS RF +0018B2 (base 16) ADEUNIS RF + 283 Rue NEEL + CROLLES ISERE 38920 + FR + +00-18-B3 (hex) TEC WizHome Co., Ltd. +0018B3 (base 16) TEC WizHome Co., Ltd. + 18fl., In-Song bldg., 194-15, + Seoul 100-952 + KR + +00-18-BD (hex) SHENZHEN DVBWORLD TECHNOLOGY CO., LTD. +0018BD (base 16) SHENZHEN DVBWORLD TECHNOLOGY CO., LTD. + 2ND FLOOR, BUILDING A, QINGHU XINQIAO INDUSTRY AREA, + SHENZHEN GUANGDONG 518000 + CN + +00-18-67 (hex) Datalogic ADC +001867 (base 16) Datalogic ADC + 433 N. Fair Oaks Ave + Pasadena CA 91103 + US + +00-18-65 (hex) Siemens Healthcare Diagnostics Manufacturing Ltd +001865 (base 16) Siemens Healthcare Diagnostics Manufacturing Ltd + Northern Road + Sudbury Suffolk C010 2XQ + GB + +00-18-77 (hex) Amplex A/S +001877 (base 16) Amplex A/S + Silkeborgvej 2 + Aarhus C 8000 + DK + +00-18-89 (hex) WinNet Solutions Limited +001889 (base 16) WinNet Solutions Limited + Rm804, Kornhill Metro Tower, Quarry Bay + HK 852 + HK + +00-17-F9 (hex) Forcom Sp. z o.o. +0017F9 (base 16) Forcom Sp. z o.o. + Gajowa 6 + Poznan WLKP 60-815 + PL + +00-17-F4 (hex) ZERON ALLIANCE +0017F4 (base 16) ZERON ALLIANCE + 3F DOORI BUILD. 244-14 bunji, Poi-dong, Gangnam-gu + SEOUL 135-965 + KR + +00-17-F7 (hex) CEM Solutions Pvt Ltd +0017F7 (base 16) CEM Solutions Pvt Ltd + 49,Kanija Bhavan + Bangalore Karnataka 560 001 + IN + +00-17-ED (hex) WooJooIT Ltd. +0017ED (base 16) WooJooIT Ltd. + Hankooktire B/D 4th floor, 501-19, + Yangcheon-gu, Seoul 158-839 + KR + +00-18-43 (hex) Dawevision Ltd +001843 (base 16) Dawevision Ltd + 197 High Street + Cottenham Cambridge CB4 8RX + GB + +00-18-2C (hex) Ascend Networks, Inc. +00182C (base 16) Ascend Networks, Inc. + No. 4 - 4, Lane 413, ChungChan Road, + BenQuao City Taipei 220 + TW + +00-18-1D (hex) ASIA ELECTRONICS CO.,LTD +00181D (base 16) ASIA ELECTRONICS CO.,LTD + 620-3 DOCHEON-DONG + GWANGJU 506-301 + KR + +00-18-1F (hex) Palmmicro Communications +00181F (base 16) Palmmicro Communications + Room 0611, Bldg.B Tsinghua Tongfang Technology Plaza + Beijing 100083 + CN + +00-18-1B (hex) TaiJin Metal Co., Ltd. +00181B (base 16) TaiJin Metal Co., Ltd. + #95-9, Hangdong7-Ga, Joong-Gu + In Cheon 400-037 + KR + +00-18-05 (hex) Beijing InHand Networking Technology Co.,Ltd. +001805 (base 16) Beijing InHand Networking Technology Co.,Ltd. + West Wing 11th Floor of Qiming International Mansion + Beijing 100085 + CN + +00-18-0D (hex) Terabytes Server Storage Tech Corp +00180D (base 16) Terabytes Server Storage Tech Corp + 14257 E Don Julian Rd + City of Industry CA 91746 + US + +00-18-54 (hex) Argard Co., Ltd +001854 (base 16) Argard Co., Ltd + 2571 Lardprao Rd. + wangthonglang Bangkok 10310 + TH + +00-18-47 (hex) AceNet Technology Inc. +001847 (base 16) AceNet Technology Inc. + 133 Vienna Dr. + Milpitas CA 95035 + US + +00-18-36 (hex) REJ Co.,Ltd +001836 (base 16) REJ Co.,Ltd + 2-3-2 Fukuura, Kanazawa-ku + Yokohama Kanagawa 236-8641 + JP + +00-17-CC (hex) Alcatel-Lucent +0017CC (base 16) Alcatel-Lucent + 601 Data Dr. + Plano TX 75075 + US + +00-17-C4 (hex) Quanta Microsystems, INC. +0017C4 (base 16) Quanta Microsystems, INC. + 188 Wenhwa 2nd RD., Kueishan Hsiang + Taoyuan Shien 333 + TW + +00-17-9E (hex) Sirit Inc +00179E (base 16) Sirit Inc + 2525 Meridian Parkway + Durham NC 27713 + US + +00-17-A7 (hex) Mobile Computing Promotion Consortium +0017A7 (base 16) Mobile Computing Promotion Consortium + 3-5-12 Shiba-Koen + Tokyo 105-0011 + JP + +00-17-9F (hex) Apricorn +00179F (base 16) Apricorn + 12191 Kirkham RD + Poway California 92064 + US + +00-17-B4 (hex) Remote Security Systems, LLC +0017B4 (base 16) Remote Security Systems, LLC + 4806 Upper Brandon Place + Marietta Georgia 30068 + US + +00-17-AC (hex) O'Neil Product Development Inc. +0017AC (base 16) O'Neil Product Development Inc. + 8 Mason + Irvine CA 92618 + US + +00-17-AD (hex) AceNet Corporation +0017AD (base 16) AceNet Corporation + 7F-4, No.146, Wen-Shin Road + Gueishan TAOYUAN + TW + +00-17-DD (hex) Clipsal Australia +0017DD (base 16) Clipsal Australia + 33-37 Port Wakefield Rd + Gepps Cross South Australia 5094 + AU + +00-17-D9 (hex) AAI Corporation +0017D9 (base 16) AAI Corporation + P.O. Box 126 + Hunt Valley Maryland 21030 + US + +00-17-DC (hex) DAEMYUNG ZERO1 +0017DC (base 16) DAEMYUNG ZERO1 + #809,Hyosung Intellian + Anyang-si Gyeonggi-do 431-060 + KR + +00-17-BF (hex) Coherent Research Limited +0017BF (base 16) Coherent Research Limited + 8 Princess Mews + Kingston upon Thames Surrey KT1 2SZ + GB + +00-17-BD (hex) Tibetsystem +0017BD (base 16) Tibetsystem + 6F IT Castle II 550-1 Gasan-dong + Seoul Geumcheon-gu 153-803 + KR + +00-17-A1 (hex) 3soft inc. +0017A1 (base 16) 3soft inc. + shinyoung bldg 4f, chungdam-dong, gangnam-gu + seoul 135-100 + KR + +00-17-92 (hex) Falcom Wireless Comunications Gmbh +001792 (base 16) Falcom Wireless Comunications Gmbh + Gewerbering 6 + Langewiesen Thuringia 98704 + DE + +00-17-97 (hex) Telsy Elettronica S.p.A. +001797 (base 16) Telsy Elettronica S.p.A. + Corso Svizzera 185 + Torino 10149 + IT + +00-17-8C (hex) Independent Witness, Inc +00178C (base 16) Independent Witness, Inc + 1515 West 2200 South + Salt Lake City UT 84119 + US + +00-17-CB (hex) Juniper Networks +0017CB (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-17-D3 (hex) Etymotic Research, Inc. +0017D3 (base 16) Etymotic Research, Inc. + 61 Martin Lane + Elk Grove Village IL 60061 + US + +00-17-88 (hex) Philips Lighting BV +001788 (base 16) Philips Lighting BV + High Tech Campus 45 + Eindhoven Noord Brabant 5656 AE + NL + +00-17-3C (hex) Extreme Engineering Solutions +00173C (base 16) Extreme Engineering Solutions + 7878 Big Sky Drive + Madison WI 53719 + US + +00-17-36 (hex) iiTron Inc. +001736 (base 16) iiTron Inc. + 88 Mercy St. + Mountain View CA 94041 + US + +00-17-37 (hex) Industrie Dial Face S.p.A. +001737 (base 16) Industrie Dial Face S.p.A. + via Canzo, 4 + Peschiera Borromeo Milano 20068 + IT + +00-17-33 (hex) SFR +001733 (base 16) SFR + 42 Quai du point du jour + Boulogne Billancourt Hauts de Seine 92659 + FR + +00-17-58 (hex) ThruVision Ltd +001758 (base 16) ThruVision Ltd + Central 127, No.18 + Abingdon Oxfordshire OX14 4SA + GB + +00-17-4F (hex) iCatch Inc. +00174F (base 16) iCatch Inc. + 10F-2, No. 109, Sec. 6, Mincyuan E. Rd., + Taipei 114 + TW + +00-17-4A (hex) SOCOMEC +00174A (base 16) SOCOMEC + rue de Westhouse + BENFELD CEDEX 67235 + FR + +00-17-4E (hex) Parama-tech Co.,Ltd. +00174E (base 16) Parama-tech Co.,Ltd. + 2-19-8, Sharyo, Higashi-ku + Fukuoka 812-0068 + JP + +00-17-6F (hex) PAX Computer Technology(Shenzhen) Ltd. +00176F (base 16) PAX Computer Technology(Shenzhen) Ltd. + 4/F, No.3 Building, Software Park, Second Central Science-Tech Road, High-Tech + Shenzhen GuangDong 518057 + CN + +00-17-71 (hex) APD Communications Ltd +001771 (base 16) APD Communications Ltd + Newlands Centre + HULL HU6 7TQ + GB + +00-17-5B (hex) ACS Solutions Switzerland Ltd. +00175B (base 16) ACS Solutions Switzerland Ltd. + Frankenstrasse 70 + Bern- Buempliz 3018 + CH + +00-17-29 (hex) Ubicod Co.LTD +001729 (base 16) Ubicod Co.LTD + 7F Chun-gin Bldg, 53-5 Wonhyo-ro + Seoul 140-719 + KR + +00-17-27 (hex) Thermo Ramsey Italia s.r.l. +001727 (base 16) Thermo Ramsey Italia s.r.l. + Strada Rivoltana km 6/7 + Rodano Milano 20090 + IT + +00-17-2A (hex) Proware Technology Corp.(By Unifosa) +00172A (base 16) Proware Technology Corp.(By Unifosa) + 6Fl., No. 4, Alley 1, Lane 235, PaoChao Rd., Sindian Dist., + New Taipei City 231 + TW + +00-17-25 (hex) Liquid Computing +001725 (base 16) Liquid Computing + 340 Terry Fox Drive + Ottawa Ontario K2K 3A2 + CA + +00-17-64 (hex) ATMedia GmbH +001764 (base 16) ATMedia GmbH + Stuhlsatzenhausweg 69 + Saarbruecken Saarland 66123 + DE + +00-17-5E (hex) Zed-3 +00175E (base 16) Zed-3 + 501 Valley Way + Milpitas CA 95035 + US + +00-17-66 (hex) Accense Technology, Inc. +001766 (base 16) Accense Technology, Inc. + 35 Tansumachi + Shinjyuku-ku Tokyo 1620833 + JP + +00-16-D0 (hex) ATech elektronika d.o.o. +0016D0 (base 16) ATech elektronika d.o.o. + Bac pri Materiji 30 + Materija SI 6242 + SI + +00-16-C3 (hex) BA Systems Inc +0016C3 (base 16) BA Systems Inc + 6895 Via Del Oro + San Jose CA 95119 + US + +00-16-F0 (hex) Dell +0016F0 (base 16) Dell + 909 Hermosa Ct + Sunnyvale CA 94085 + US + +00-16-F8 (hex) AVIQTECH TECHNOLOGY CO., LTD. +0016F8 (base 16) AVIQTECH TECHNOLOGY CO., LTD. + 6F 12, Li-hsin Road, SBIP + Hsin-chu 300 + TW + +00-16-E8 (hex) Sigma Designs, Inc. +0016E8 (base 16) Sigma Designs, Inc. + 1778 McCarthy Blvd. + Milpitas CA 95035 + US + +00-17-03 (hex) MOSDAN Internation Co.,Ltd +001703 (base 16) MOSDAN Internation Co.,Ltd + No.216 Xiwei,Shanhua Dist, + Tainan 741 + TW + +00-16-FC (hex) TOHKEN CO.,LTD. +0016FC (base 16) TOHKEN CO.,LTD. + 2-16-20 Tamagawa + Chofu Tokyo 182-0025 + JP + +00-16-E9 (hex) Tiba Medical Inc +0016E9 (base 16) Tiba Medical Inc + 5024 Lakewood Drive + Plano TX 75093 + US + +00-16-DC (hex) ARCHOS +0016DC (base 16) ARCHOS + 12 rue AMPERE + IGNY ESSONNES 91430 + FR + +00-17-14 (hex) BR Controls Nederland bv +001714 (base 16) BR Controls Nederland bv + Branderweg 1 + Zwolle Overijssel 8042 PD + NL + +00-17-1B (hex) Innovation Lab Corp. +00171B (base 16) Innovation Lab Corp. + 12FL., No. 285, Sec. 2, TiDing Blvd., + Taipei 11493 + TW + +00-17-09 (hex) Exalt Communications +001709 (base 16) Exalt Communications + 580 Division Street + Campbell CA 95008 + US + +00-16-C1 (hex) Eleksen Ltd +0016C1 (base 16) Eleksen Ltd + Pinewood Studios + Iver Bucks SL0 0NH + US + +00-16-A9 (hex) 2EI +0016A9 (base 16) 2EI + Rua dos Rubis, 77 - Assumpcao + Aguas de Lindoia São Paulo 13940-000 + BR + +00-16-B0 (hex) VK Corporation +0016B0 (base 16) VK Corporation + VK B/D, 548-6, Anyang 8dong, Manan-gu + Anyang Kyounggi 430-8903 + KR + +00-16-B1 (hex) KBS +0016B1 (base 16) KBS + 88 rue Pierre Sémard + Moissy cedex Ile de France 77552 + FR + +00-16-AE (hex) INVENTEL +0016AE (base 16) INVENTEL + 35 rue Tournefort + PARIS 75005 + FR + +00-16-AC (hex) Toho Technology Corp. +0016AC (base 16) Toho Technology Corp. + HIGASHI 5-1 + INAZAWA-CITY AICHI 492-8501 + JP + +00-16-83 (hex) WEBIO International Co.,.Ltd. +001683 (base 16) WEBIO International Co.,.Ltd. + 21F.,No.171 Songde Rd.,Sinyi District + Taipei 11085 + TW + +00-16-84 (hex) Donjin Co.,Ltd. +001684 (base 16) Donjin Co.,Ltd. + 21F,Cangsong Building,Tairan,Futian + Shenzhen Guangdong 518040 + CN + +00-16-87 (hex) Chubb CSC-Vendor AP +001687 (base 16) Chubb CSC-Vendor AP + Ottawa STN + Ottawa K1G 6W6 + CA + +00-16-7F (hex) Bluebird Soft Inc. +00167F (base 16) Bluebird Soft Inc. + 562-21 Gangnam-gu, + Seoul 135-890 + KR + +00-16-4C (hex) PLANET INT Co., Ltd +00164C (base 16) PLANET INT Co., Ltd + 8th Floor, Saeum B/D, 1361-5 + Seoul 137-070 + KR + +00-16-49 (hex) SetOne GmbH +001649 (base 16) SetOne GmbH + Hegenheimer Str. 2 + Weil am Rhein D-79576 + DE + +00-16-47 (hex) Cisco Systems, Inc +001647 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-16-65 (hex) Cellon France +001665 (base 16) Cellon France + Route d'Angers Le Mans cedex 9 + Le Mans Sarthe 72081 + FR + +00-16-5F (hex) Fairmount Automation +00165F (base 16) Fairmount Automation + 4621 West Chester Pike + Newtown Square PA 19073 + US + +00-16-7C (hex) iRex Technologies BV +00167C (base 16) iRex Technologies BV + HighTech Campus + Eindhoven Brabant 5656AE + NL + +00-16-73 (hex) Bury GmbH & Co. KG +001673 (base 16) Bury GmbH & Co. KG + Robert-Koch-Str. 1-7 + Loehne Germany 32584 + DE + +00-16-94 (hex) Sennheiser Communications A/S +001694 (base 16) Sennheiser Communications A/S + Langager 6 + Solrød Strand Copenhagen 2680 + DK + +00-16-9C (hex) Cisco Systems, Inc +00169C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-16-57 (hex) Aegate Ltd +001657 (base 16) Aegate Ltd + Technology Centre + Melbourn Hertfordshire SG8 6DP + GB + +00-16-8C (hex) DSL Partner AS +00168C (base 16) DSL Partner AS + Havreveien 49 + Oslo 0680 + NO + +00-16-1B (hex) Micronet Corporation +00161B (base 16) Micronet Corporation + 1788-388 Nomura Hirooka + Shiojiri-shi Nagano-ken 399-0702 + JP + +00-16-18 (hex) HIVION Co., Ltd. +001618 (base 16) HIVION Co., Ltd. + 2F., Akyung Bldg., 54-10, Munjeong-dong, + Songpa-Gu Seoul + KR + +00-16-1E (hex) Woojinnet +00161E (base 16) Woojinnet + 292 osan dongtan + hwaseong kyonggi 445-813 + KR + +00-16-1F (hex) SUNWAVETEC Co., Ltd. +00161F (base 16) SUNWAVETEC Co., Ltd. + #823, Kwanyang-dong, Dongan-ku + Anyang-si Kyungki-do 431-060 + US + +00-16-14 (hex) Picosecond Pulse Labs +001614 (base 16) Picosecond Pulse Labs + 2500 55th Street + Boulder CO 80301 + US + +00-16-0E (hex) Optica Technologies Inc. +00160E (base 16) Optica Technologies Inc. + 2051 Dogwood Street + Louisville CO 80027 + US + +00-16-43 (hex) Sunhillo Corporation +001643 (base 16) Sunhillo Corporation + 444 Kelley Drive + West Berlin New Jersey 08091 + US + +00-16-44 (hex) LITE-ON Technology Corp. +001644 (base 16) LITE-ON Technology Corp. + 18F, No.392, Ruey Kuang Road, Niehu, + Taipei 114 + TW + +00-16-3E (hex) Xensource, Inc. +00163E (base 16) Xensource, Inc. + 2300 Geng Rd. + Palo Alto CA 94303 + US + +00-15-FD (hex) Complete Media Systems +0015FD (base 16) Complete Media Systems + Grove Place + Warninglid West sussex RH17 5SN + GB + +00-15-F6 (hex) SCIENCE AND ENGINEERING SERVICES, INC. +0015F6 (base 16) SCIENCE AND ENGINEERING SERVICES, INC. + 4015 PULASKI PIKE NW + HUNTSVILLE AL 35810 + US + +00-16-34 (hex) Mathtech, Inc. +001634 (base 16) Mathtech, Inc. + 6402 Arlington Blvd., + Falls Church Virginia 22042-2356 + US + +00-16-2C (hex) Xanboo +00162C (base 16) Xanboo + 115 West 30th, 6th Fl + New York NY 10001 + US + +00-16-05 (hex) YORKVILLE SOUND INC. +001605 (base 16) YORKVILLE SOUND INC. + 4625 WITMER INDUSTRIAL ESTATE + NIAGARA FALLS NY 14305 + US + +00-15-F9 (hex) Cisco Systems, Inc +0015F9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-15-E3 (hex) Dream Technologies Corporation +0015E3 (base 16) Dream Technologies Corporation + Ebisu Prime Square, 1-1-39 Hiroo + Tokyo 150-0012 + JP + +00-15-E0 (hex) Ericsson +0015E0 (base 16) Ericsson + Nya Vattentornet + Lund SE-221 83 + NO + +00-15-F3 (hex) PELTOR AB +0015F3 (base 16) PELTOR AB + Box 2341 + SE-331 02 Värnamo SE-331 02 + SE + +00-15-E7 (hex) Quantec Tontechnik +0015E7 (base 16) Quantec Tontechnik + Mittenwalderstr.63 + München D-81377 + DE + +00-15-D3 (hex) Pantech&Curitel Communications, Inc. +0015D3 (base 16) Pantech&Curitel Communications, Inc. + 1451-34, Seocho-dong, Seocho-Gu + Seoul 137-070 + KR + +00-15-AD (hex) Accedian Networks +0015AD (base 16) Accedian Networks + 4878 Levy, suite 202 + St-Laurent Quebec H9P 2V4 + CA + +00-15-AC (hex) Capelon AB +0015AC (base 16) Capelon AB + Jägerhorns väg 1 + Kungens Kurva Stockholm S-141 75 + SE + +00-15-A9 (hex) KWANG WOO I&C CO.,LTD +0015A9 (base 16) KWANG WOO I&C CO.,LTD + 898-23, Hogye-dong,Dongan-gu + 431-080 + KR + +00-E0-A8 (hex) SAT GmbH & Co. +00E0A8 (base 16) SAT GmbH & Co. + RUTHNERGASSE 1 + VIENNA A-1210 + AT + +00-15-74 (hex) Horizon Semiconductors Ltd. +001574 (base 16) Horizon Semiconductors Ltd. + 9 Hamenofim St. + Herzliya 46120 + IL + +00-15-8A (hex) SURECOM Technology Corp. +00158A (base 16) SURECOM Technology Corp. + 6F, No. 125, Sec. 2, Datung Rd. + Shijr City, Taipei County 221 + TW + +00-15-8E (hex) Plustek.INC +00158E (base 16) Plustek.INC + 13F-1,No3(Building F) Yuan Qu Street + Taipei Yuan Qu 115 + TW + +00-15-89 (hex) D-MAX Technology Co.,Ltd +001589 (base 16) D-MAX Technology Co.,Ltd + 7F-6,NO.26,Lian Cheng RD.,Chung-Ho City + Taipei Hsien 235 + US + +00-15-B4 (hex) Polymap Wireless LLC +0015B4 (base 16) Polymap Wireless LLC + 310 S. Williams Blvd. Ste. 350 + Tucson AZ 85711 + US + +00-15-CA (hex) TeraRecon, Inc. +0015CA (base 16) TeraRecon, Inc. + 2955 Campus Drive, Suite 325 + San Mateo CA 94403 + US + +00-15-98 (hex) Kolektor group +001598 (base 16) Kolektor group + Vojkova 10 + Idrija 5280 + SI + +00-15-12 (hex) Zurich University of Applied Sciences +001512 (base 16) Zurich University of Applied Sciences + Technikumstrasse 9 + Winterthur ZH CH-8401 + CH + +00-15-0A (hex) Sonoa Systems, Inc +00150A (base 16) Sonoa Systems, Inc + 3900 Freedom Circle + Santa Clara CA 95054 + US + +00-15-70 (hex) Zebra Technologies Inc +001570 (base 16) Zebra Technologies Inc + 475 Half Day Road + Lincolnshire IL 60069 + US + +00-15-6E (hex) A. W. Communication Systems Ltd +00156E (base 16) A. W. Communication Systems Ltd + Crook Barn + Carlisle Cumbria CA6 6LH + GB + +00-15-68 (hex) Dilithium Networks +001568 (base 16) Dilithium Networks + 5401 Old Redwood Hwy + Petaluma CA 94954 + US + +00-15-4B (hex) Wonde Proud Technology Co., Ltd +00154B (base 16) Wonde Proud Technology Co., Ltd + 21F., No.100, Sec.1, Shintai 5th Rd + Sijhih city Taipei County 221 + TW + +00-15-48 (hex) CUBE TECHNOLOGIES +001548 (base 16) CUBE TECHNOLOGIES + 46 A CHEMIN DU MOULIN CARRON + 69570 DARDILLY FRANCE + FR + +00-15-5F (hex) GreenPeak Technologies +00155F (base 16) GreenPeak Technologies + Spinnerijstraat 14 + Zele 9240 + BE + +00-15-5A (hex) DAINIPPON PHARMACEUTICAL CO., LTD. +00155A (base 16) DAINIPPON PHARMACEUTICAL CO., LTD. + 2-6-8, DOSHOMACHI, CHUO-KU + OSAKA CITY OSAKA PREF. 541-8524 + JP + +00-15-1D (hex) M2I CORPORATION +00151D (base 16) M2I CORPORATION + Kyonggi Venture Anyang technical center, 13th Floor, 572-5, Anyang 8-Dong, Manan-Gu + Anyang-Shi Kyonggi-Do 430-731 + KR + +00-15-3C (hex) Kprotech Co., Ltd. +00153C (base 16) Kprotech Co., Ltd. + 2nd Floor, # 202, Myoung-ji e-Space II + An-yang City Gyeong-gi Do 430-817 + KR + +00-15-3A (hex) Shenzhen Syscan Technology Co.,Ltd. +00153A (base 16) Shenzhen Syscan Technology Co.,Ltd. + 13F, Olympic Plaza, + Shenzhen Guangdong 518034 + CN + +00-15-32 (hex) Consumer Technologies Group, LLC +001532 (base 16) Consumer Technologies Group, LLC + 801 Brookhollow + Efland NC 27243 + US + +00-14-9B (hex) Nokota Communications, LLC +00149B (base 16) Nokota Communications, LLC + 200 Galleria Parkway + Atlanta Georgia 30339 + US + +00-14-A1 (hex) Synchronous Communication Corp +0014A1 (base 16) Synchronous Communication Corp + 9 floor, No168, Rueiguang Road, Neihu District + Taipei 114 + TW + +00-14-9E (hex) UbONE Co., Ltd +00149E (base 16) UbONE Co., Ltd + Shinyoung B.D. 602, SeoHyeon2-Dong + Seongnam-si Gyeongg-do 463-824 + KR + +00-14-A2 (hex) Core Micro Systems Inc. +0014A2 (base 16) Core Micro Systems Inc. + Wacore Kaname-cho Bldg. 9F, 11-2, Nakamaru-cho + Itabashi-ku Tokyo 173-0026 + JP + +00-14-AD (hex) Gassner Wiege- und Meßtechnik GmbH +0014AD (base 16) Gassner Wiege- und Meßtechnik GmbH + Münchner Bundesstraße + Salzburg A-5020 + AT + +00-14-AF (hex) Datasym POS Inc. +0014AF (base 16) Datasym POS Inc. + 45 Dalkeith Drive + Brantford Ontario N3P1M1 + CA + +00-14-A9 (hex) Cisco Systems, Inc +0014A9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-14-FF (hex) Precise Automation, Inc. +0014FF (base 16) Precise Automation, Inc. + 1402 Alexandra Blvd + Crystal Lake IL 60014 + US + +00-14-FA (hex) AsGa S.A. +0014FA (base 16) AsGa S.A. + Rod Roberto Moreira Km 04 + Paulinia São Paulo 13140-000 + BR + +00-14-FB (hex) Technical Solutions Inc. +0014FB (base 16) Technical Solutions Inc. + 101-7188 Progress Way + Delta BC V4G 1M6 + CA + +00-14-D2 (hex) Kyuden Technosystems Corporation +0014D2 (base 16) Kyuden Technosystems Corporation + 4-19-18 SHIMIZU,MINAMI-KU + FUKUOKA 815-0031 + JP + +00-14-DC (hex) Communication System Design & Manufacturing (CSDM) +0014DC (base 16) Communication System Design & Manufacturing (CSDM) + Postbus 181 + Bussum NH 1400 AD + NL + +00-14-CD (hex) DigitalZone Co., Ltd. +0014CD (base 16) DigitalZone Co., Ltd. + No. 1001 E&C VentureDreamTower2 + Seoul 152-848 + KR + +00-14-C0 (hex) Symstream Technology Group Ltd +0014C0 (base 16) Symstream Technology Group Ltd + Level 1, 3 Chester Street + Oakleigh Victoria 3166 + AU + +00-14-C1 (hex) U.S. Robotics Corporation +0014C1 (base 16) U.S. Robotics Corporation + 935 National Parkway + Schaumburg IL 60173-5157 + US + +00-14-C4 (hex) Vitelcom Mobile Technology +0014C4 (base 16) Vitelcom Mobile Technology + PTA, Avda, Juan López Peñalver, nº 7 + Campanillas. Malaga. + ES + +00-14-EC (hex) Acro Telecom +0014EC (base 16) Acro Telecom + 714 Woolim e-Biz Center 170-5 Guro-dong + Guro-Gu Seoul 152-769 + KR + +00-14-EB (hex) AwarePoint Corporation +0014EB (base 16) AwarePoint Corporation + 8899 University Center Lane + San Diego CA 92122 + US + +00-14-AB (hex) Senhai Electronic Technology Co., Ltd. +0014AB (base 16) Senhai Electronic Technology Co., Ltd. + Rm.10A. 28/F.SEGPlaza Huaqiangbei Road + Shengzhen Guangdong 518031 + CN + +00-14-B0 (hex) Naeil Community +0014B0 (base 16) Naeil Community + #506 AceTwin Tower 1, Guro-Dong + Seoul Guro-Gu 152779 + KR + +00-14-F4 (hex) DekTec Digital Video B.V. +0014F4 (base 16) DekTec Digital Video B.V. + Van Riebeeckweg 43A + Hilversum NH 1212AE + NL + +00-14-F5 (hex) OSI Security Devices +0014F5 (base 16) OSI Security Devices + 1580 Jayken Way + Chula Vista California 91911 + US + +00-14-8E (hex) Tele Power Inc. +00148E (base 16) Tele Power Inc. + 1-46-15#B1F + Nerima-ku Tokyo 176-0005 + JP + +00-14-8F (hex) Protronic (Far East) Ltd. +00148F (base 16) Protronic (Far East) Ltd. + Rm. 2504, Nanyang Plaza, + Kwun Tong Kowloon + HK + +00-14-8C (hex) General Dynamics Mission Systems +00148C (base 16) General Dynamics Mission Systems + 150 Rustcraft Road + Dedham MA 02026 + US + +00-14-87 (hex) American Technology Integrators +001487 (base 16) American Technology Integrators + 1358 Rosalia Ave + San Jose CA 95130 + US + +00-14-44 (hex) Grundfos Holding +001444 (base 16) Grundfos Holding + Poul Due Jensensvej 7 + Bjerringbro DK8850 + DK + +00-14-37 (hex) GSTeletech Co.,Ltd. +001437 (base 16) GSTeletech Co.,Ltd. + 1385-14, Juan-Dong, Nam-gu + Incheon 402-200 + KR + +00-14-31 (hex) PDL Electronics Ltd +001431 (base 16) PDL Electronics Ltd + 81 Austin Street + Napier Hawkes Bay + NZ + +00-14-4D (hex) Intelligent Systems +00144D (base 16) Intelligent Systems + 11101 Johns Hopkins Road + Laurel MD 20723 + US + +00-14-4A (hex) Taiwan Thick-Film Ind. Corp. +00144A (base 16) Taiwan Thick-Film Ind. Corp. + NO.126,Wuu Gong 2nd RD, + Taipei Hsien 248 + TW + +00-14-45 (hex) Telefon-Gradnja d.o.o. +001445 (base 16) Telefon-Gradnja d.o.o. + Plesivicka 3 + Sveta Nedelja Zupanija Zagrebacka 10431 + HR + +00-14-68 (hex) CelPlan International, Inc. +001468 (base 16) CelPlan International, Inc. + 1920 Association Drive + Reston VA 20191 + US + +00-14-7C (hex) 3Com Ltd +00147C (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +00-14-81 (hex) Multilink Inc +001481 (base 16) Multilink Inc + 580 Ternes Ave + Elyria OH 44035 + US + +00-14-64 (hex) Cryptosoft +001464 (base 16) Cryptosoft + Lermontova str, 3 + Penza region 440026 + RU + +00-14-5E (hex) IBM Corp +00145E (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-14-58 (hex) HS Automatic ApS +001458 (base 16) HS Automatic ApS + Bjerringbrovej 70 + Rodovre 2610 + DK + +00-14-21 (hex) Total Wireless Technologies Pte. Ltd. +001421 (base 16) Total Wireless Technologies Pte. Ltd. + Blk 1003, Bukit Merah Central, #04-18 + 159836 + SG + +00-14-20 (hex) G-Links networking company +001420 (base 16) G-Links networking company + 1FL. NO.15-49, MING DER SECOND ROAD, + Keelung 206 + TW + +00-14-18 (hex) C4Line +001418 (base 16) C4Line + 1001 Hyundai Parisian, + Yangchun-Gu Seoul 158-050 + KR + +00-14-1B (hex) Cisco Systems, Inc +00141B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-13-F0 (hex) Wavefront Semiconductor +0013F0 (base 16) Wavefront Semiconductor + 4746 44th Ave SW + Seattle WA 98116 + US + +00-13-EF (hex) Kingjon Digital Technology Co.,Ltd +0013EF (base 16) Kingjon Digital Technology Co.,Ltd + Room 827,Huanan Dianli Bulding,No.2050 + Shenzhen GuangDong 518031 + CN + +00-13-EB (hex) Sysmaster Corporation +0013EB (base 16) Sysmaster Corporation + 5801 Christie Ave. + Emeryville CA 94608 + US + +00-13-EC (hex) Netsnapper Technologies SARL +0013EC (base 16) Netsnapper Technologies SARL + 2160 Century Park East 1806 + Los Angeles CA 90067-2236 + US + +00-14-2B (hex) Edata Communication Inc. +00142B (base 16) Edata Communication Inc. + 2F-1, No. 872, Chung-Cheng Rd + Taipei Hsien 235 + TW + +00-14-2C (hex) Koncept International, Inc. +00142C (base 16) Koncept International, Inc. + 2500 E Foothill Blvd. #407 + Pasadena CA 91107 + US + +00-14-24 (hex) Merry Electrics CO., LTD. +001424 (base 16) Merry Electrics CO., LTD. + NO.22,23rd ROAD + TAICHUNG CITY 40850 + TW + +00-13-D0 (hex) t+ Medical Ltd +0013D0 (base 16) t+ Medical Ltd + 174E Milton Park + Abingdon OX14 4SE + GB + +00-13-D2 (hex) PAGE IBERICA, S.A. +0013D2 (base 16) PAGE IBERICA, S.A. + AV. DE LA INDUSTRIA, 24 + TRES CANTOS MADRID 28760 + ES + +00-13-D1 (hex) KIRK telecom A/S +0013D1 (base 16) KIRK telecom A/S + Langmarksvej 34 + Horsens 8700 + DK + +00-14-0F (hex) Federal State Unitary Enterprise Leningrad R&D Institute of +00140F (base 16) Federal State Unitary Enterprise Leningrad R&D Institute of + 11 Warshawskaya St. + St. Petersburg 196128 + RU + +00-14-07 (hex) Sperian Protection Instrumentation +001407 (base 16) Sperian Protection Instrumentation + 651 South Main Street + Middletown CT 06457 + US + +00-14-06 (hex) Go Networks +001406 (base 16) Go Networks + 126 Yigal Alon st. + Tel Aviv 67443 + IL + +00-14-0A (hex) WEPIO Co., Ltd. +00140A (base 16) WEPIO Co., Ltd. + #1125, Opus1, Gurodongcomplex building + Seoul 152-050 + KR + +00-13-FA (hex) LifeSize Communications, Inc +0013FA (base 16) LifeSize Communications, Inc + 901 S. Mopac + Austin TX 78746 + US + +00-13-FB (hex) RKC INSTRUMENT INC. +0013FB (base 16) RKC INSTRUMENT INC. + 16-6, Kugahara 5-chome, + Ohta-ku Tokyo 146-8515 + JP + +00-13-DC (hex) IBTEK INC. +0013DC (base 16) IBTEK INC. + 16F, 30, Pei-Ping East Rd., + Taipei 100 + TW + +00-13-BA (hex) ReadyLinks Inc +0013BA (base 16) ReadyLinks Inc + 6595 Edenvale Boulevard + Eden Prairie MN 55346 + US + +00-13-B8 (hex) RyCo Electronic Systems Limited +0013B8 (base 16) RyCo Electronic Systems Limited + Unit E, Cartel Business Estate + Harlow Essex CM20 2TT + GB + +00-13-B6 (hex) Sling Media, Inc. +0013B6 (base 16) Sling Media, Inc. + 1840 Gateway Center + San Mateo CA 94404 + US + +00-13-7D (hex) Dynalab, Inc. +00137D (base 16) Dynalab, Inc. + 555 Lancaster Ave. + Reynoldsburg OH 43068 + US + +00-13-83 (hex) Application Technologies and Engineering Research Laboratory +001383 (base 16) Application Technologies and Engineering Research Laboratory + Shinjuku 1-chome Bldg. + Shinjuku-ku Tokyo 160-0022 + JP + +00-13-87 (hex) 27M Technologies AB +001387 (base 16) 27M Technologies AB + Diskettgatan 11 + Linköping S-583 35 + SE + +00-13-73 (hex) BLwave Electronics Co., Ltd +001373 (base 16) BLwave Electronics Co., Ltd + 23FGH, Block A,ZhenYe Building , BaoAn Nan Road , LuoHu , Shenzhen , China + ShenZhen GuangDong 518000 + CN + +00-13-66 (hex) Neturity Technologies Inc. +001366 (base 16) Neturity Technologies Inc. + 830 Stewart Drive + Sunnyvale CA 94085 + US + +00-13-5B (hex) PanelLink Cinema, LLC +00135B (base 16) PanelLink Cinema, LLC + 1070 E Arques Ave + Sunnyvale CA 94085 + US + +00-13-6F (hex) PacketMotion, Inc. +00136F (base 16) PacketMotion, Inc. + 2121 El Camino Real + San Mateo CA 94403 + US + +00-13-68 (hex) Saab Danmark A/S +001368 (base 16) Saab Danmark A/S + Alsion 2 + Soenderborg DK 6400 + DK + +00-13-B4 (hex) Appear TV +0013B4 (base 16) Appear TV + P.O. Box 8 Lilleaker + Oslo NO-0216 + NO + +00-13-AE (hex) Radiance Technologies, Inc. +0013AE (base 16) Radiance Technologies, Inc. + 350 Wynn Dr. + Huntsville Alabama 35805 + US + +00-13-97 (hex) Oracle Corporation +001397 (base 16) Oracle Corporation + 500 Oracle Parkway + Redwood Shores CA 94065 + US + +00-13-C3 (hex) Cisco Systems, Inc +0013C3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-13-BD (hex) HYMATOM SA +0013BD (base 16) HYMATOM SA + Zone Industrielle + VENDARGUES HERAULT 34740 + FR + +00-13-91 (hex) OUEN CO.,LTD. +001391 (base 16) OUEN CO.,LTD. + Gotanda NT Bldg.7F, + Shinagawa-ku Tokyo 141-0022 + JP + +00-13-23 (hex) Cap Co., Ltd. +001323 (base 16) Cap Co., Ltd. + 11F,684-2,deungchon 3-dong,gangseo-gu + Seoul 157-754 + KR + +00-13-14 (hex) Asiamajor Inc. +001314 (base 16) Asiamajor Inc. + 6F-9, No. 268, Lian-Cheng Rd., Junghe City, + Taipei 235 + TW + +00-13-16 (hex) L-S-B Broadcast Technologies GmbH +001316 (base 16) L-S-B Broadcast Technologies GmbH + Gustav-Stresemann-Str. 8 + Bingen Rheinland-Pfalz 55411 + DE + +00-13-12 (hex) Amedia Networks Inc. +001312 (base 16) Amedia Networks Inc. + 101 Crawfords Corner Rd + Holmdel NJ 07733 + US + +00-13-36 (hex) Tianjin 712 Communication Broadcasting co., ltd. +001336 (base 16) Tianjin 712 Communication Broadcasting co., ltd. + No.185, Xinda Road, Hebei District + Tianjin 300140 + CN + +00-13-5E (hex) EAB/RWI/K +00135E (base 16) EAB/RWI/K + Färögatan 6 + Stockholm Kista 164 80 + SE + +00-13-4E (hex) Valox Systems, Inc. +00134E (base 16) Valox Systems, Inc. + #704, Ace Twin tower 2, 212-30, Guro-3dong, Guro-gu + Seoul 152-779 + KR + +00-13-44 (hex) Fargo Electronics Inc. +001344 (base 16) Fargo Electronics Inc. + 6533 Flying Cloud Drive + Eden Prairie MN 55344 + US + +00-13-48 (hex) Artila Electronics Co., Ltd. +001348 (base 16) Artila Electronics Co., Ltd. + 2F., No.1, Alley 8, Siwei Lane, Zhongzheng Rd., + Xindian City Taipei County 231 + TW + +00-12-EF (hex) OneAccess SA +0012EF (base 16) OneAccess SA + 28 rue de la Redoute + Fontenay aux Roses 92260 + FR + +00-12-E9 (hex) Abbey Systems Ltd +0012E9 (base 16) Abbey Systems Ltd + Level 4, 220 Willis St + Wellington 6030 + NZ + +00-13-00 (hex) IT-FACTORY, INC. +001300 (base 16) IT-FACTORY, INC. + 1-16-26 TAKAGI MINAMI-KU + FUKUOKA-SHI FUKUOKA-KEN 815-0004 + JP + +00-13-22 (hex) DAQ Electronics, Inc. +001322 (base 16) DAQ Electronics, Inc. + 262B Old New Brunswick Road + Piscataway NJ 08854 + US + +00-12-D5 (hex) Motion Reality Inc. +0012D5 (base 16) Motion Reality Inc. + 200 North Cobb Parkway + Marietta GA 30062 + US + +00-12-D8 (hex) International Games System Co., Ltd. +0012D8 (base 16) International Games System Co., Ltd. + No.130, Wu-Gung Rd., Wu-Gu Industrial Park, + Taipei 248 + TW + +00-12-9A (hex) IRT Electronics Pty Ltd +00129A (base 16) IRT Electronics Pty Ltd + 26 Hotham Parade + Artarmon NSW 2064 + AU + +00-12-8D (hex) STB Datenservice GmbH +00128D (base 16) STB Datenservice GmbH + Weinsbergstraße 190 + Köln NRW 50825 + DE + +00-12-DB (hex) ZIEHL industrie-elektronik GmbH + Co KG +0012DB (base 16) ZIEHL industrie-elektronik GmbH + Co KG + Daimlerstraße 13 + Schwäbisch Hall 74523 + DE + +00-12-D6 (hex) Jiangsu Yitong High-Tech Co.,Ltd +0012D6 (base 16) Jiangsu Yitong High-Tech Co.,Ltd + No 216 Huanghe Road + Changshu Jiangsu 215500 + CN + +00-12-DA (hex) Cisco Systems, Inc +0012DA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-12-D3 (hex) Zetta Systems, Inc. +0012D3 (base 16) Zetta Systems, Inc. + 17311 135th AVE NE + Woodinville WA 98072 + US + +00-12-A2 (hex) VITA +0012A2 (base 16) VITA + PO Box 19658 + Fountain Hills AZ 85269 + US + +00-12-A5 (hex) Dolphin Interconnect Solutions AS +0012A5 (base 16) Dolphin Interconnect Solutions AS + NILS Hansens Vei 13 + Oslo 0667 + NO + +00-12-A8 (hex) intec GmbH +0012A8 (base 16) intec GmbH + Rahmedestraße 90 + Luedenscheid NRW 58507 + DE + +00-12-9E (hex) Surf Communications Inc. +00129E (base 16) Surf Communications Inc. + Room 313, 3F, Bldg.52, No. 195, Chung Hsing Rd., Sec 4, Chutung, HsinChu, Taiwan + HsinChu 310 + TW + +00-12-BA (hex) FSI Systems, Inc. +0012BA (base 16) FSI Systems, Inc. + 5847 County Road 41 + Farmington NY 14425 + US + +00-12-B2 (hex) AVOLITES LTD. +0012B2 (base 16) AVOLITES LTD. + 184 PARK AVENUE + LONDON NW10 7XL + GB + +00-12-AE (hex) HLS HARD-LINE Solutions Inc. +0012AE (base 16) HLS HARD-LINE Solutions Inc. + 53 Main Street + Dowling Ontario P0M 1R0 + CA + +00-12-AF (hex) ELPRO Technologies +0012AF (base 16) ELPRO Technologies + 9 / 12 Billabong St. + Stafford Queensland 4053 + AU + +00-12-E6 (hex) SPECTEC COMPUTER CO., LTD. +0012E6 (base 16) SPECTEC COMPUTER CO., LTD. + 6F., No. 92, Nanking E. Rd. Sec. 5, + Taipei 105 + TW + +00-12-E3 (hex) Agat-RT, Ltd. +0012E3 (base 16) Agat-RT, Ltd. + 101 pr. Mira #1220, + Moscow 129085 + RU + +00-12-36 (hex) ConSentry Networks +001236 (base 16) ConSentry Networks + 1690 McCandless Dr + Milipitas CA 95035 + US + +00-12-35 (hex) Andrew Corporation +001235 (base 16) Andrew Corporation + 2601 Telecom Pkwy + Richardson TX 75082 + US + +00-12-45 (hex) Zellweger Analytics, Inc. +001245 (base 16) Zellweger Analytics, Inc. + 405 Barclay Blvd. + Lincolnshire Illinois 60069 + US + +00-12-42 (hex) Millennial Net +001242 (base 16) Millennial Net + 285 Billerica Road + Chelmsford MA 01803 + US + +00-12-41 (hex) a2i marketing center +001241 (base 16) a2i marketing center + 1024-4 Duksan Bldg Bangbaedong Seochogu Seoul Korea + SEOUL 137-060 + KR + +00-12-3B (hex) KeRo Systems ApS +00123B (base 16) KeRo Systems ApS + Allikevej 3 + Hørsholm 2970 + DK + +00-12-87 (hex) Digital Everywhere Unterhaltungselektronik GmbH +001287 (base 16) Digital Everywhere Unterhaltungselektronik GmbH + Maria Gailer Strasse 16 + Villach Kärnten 9500 + AT + +00-12-82 (hex) Qovia +001282 (base 16) Qovia + 7470 New Technology Way + Frederick MD 21703 + US + +00-12-85 (hex) Gizmondo Europe Ltd +001285 (base 16) Gizmondo Europe Ltd + 1 Meadow Gate Avenue + Farnborough Hampshire GU14 6FG + GB + +00-12-77 (hex) Korenix Technologies Co., Ltd. +001277 (base 16) Korenix Technologies Co., Ltd. + 11F-1, No. 108, MinQuan Rd. + Xindian City Taipei 231 + TW + +00-12-6D (hex) University of California, Berkeley +00126D (base 16) University of California, Berkeley + EECS Department + Berkeley CA 94720-1776 + US + +00-12-67 (hex) Panasonic Corporation +001267 (base 16) Panasonic Corporation + 2460-1, Uegawa-Cho + Matsusaka-City Mie 571-8506 + JP + +00-12-65 (hex) Enerdyne Technologies, Inc. +001265 (base 16) Enerdyne Technologies, Inc. + 1935 Cordell Court + El Cajon CA 92020 + US + +00-12-57 (hex) LeapComm Communication Technologies Inc. +001257 (base 16) LeapComm Communication Technologies Inc. + RM1804-05 South Tower Hong Kong Plaza, No.283 Huaihai Zhong Road + Shanghai 200021 + CN + +00-12-51 (hex) SILINK +001251 (base 16) SILINK + 13 RUE POMEYS + LE TAILLAN 33320 + FR + +00-12-8E (hex) Q-Free ASA +00128E (base 16) Q-Free ASA + Th. Owesensgt. 35c + Trondheim 7443 + NO + +00-12-92 (hex) Griffin Technology +001292 (base 16) Griffin Technology + 1930 Air Lane Drive + Nashville TN 37210 + US + +00-11-F3 (hex) NeoMedia Europe AG +0011F3 (base 16) NeoMedia Europe AG + Jens-Otto-Krag-Straße 11 + Würselen 52146 + DE + +00-11-E9 (hex) STARNEX CO., LTD. +0011E9 (base 16) STARNEX CO., LTD. + 4th Floor, C&C Bldg, 228-2 + Kwangjin-gu Seoul 143-200 + KR + +00-11-EC (hex) AVIX INC. +0011EC (base 16) AVIX INC. + 1-1, Fukuura, Kanazawa-ku + Yokohama-shi Kanagawa 236-0004 + JP + +00-11-E7 (hex) WORLDSAT - Texas de France +0011E7 (base 16) WORLDSAT - Texas de France + 220, rue Gustave Eiffel + Aix en Provence Bouches du Rhone 13854 + FR + +00-12-02 (hex) Decrane Aerospace - Audio International Inc. +001202 (base 16) Decrane Aerospace - Audio International Inc. + 7300 Industry Drive + North Little Rock AR 72117 + US + +00-11-FE (hex) Keiyo System Research, Inc. +0011FE (base 16) Keiyo System Research, Inc. + Hamada park Bldg. 6F + Chiba-city Chiba-pref 260-0028 + JP + +00-11-FD (hex) KORG INC. +0011FD (base 16) KORG INC. + 4015-2, Yanokuchi + Inagi-City TOKYO 206-0812 + JP + +00-11-FA (hex) Rane Corporation +0011FA (base 16) Rane Corporation + 10802 47th Avenue West + Mukilteo WA 98275-5098 + US + +00-11-CE (hex) Ubisense Limited +0011CE (base 16) Ubisense Limited + St. Andrews House + Chesterton Cambridge CB4 1DL + GB + +00-11-D0 (hex) Tandberg Data ASA +0011D0 (base 16) Tandberg Data ASA + Kjelsåsveien 161 + Oslo 0411 + NO + +00-11-C3 (hex) Transceiving System Technology Corporation +0011C3 (base 16) Transceiving System Technology Corporation + NO.85,Sec.2,Gongdaowu Rd., + Hsinchu 300 + TW + +00-11-C2 (hex) United Fiber Optic Communication +0011C2 (base 16) United Fiber Optic Communication + 13-1,NO.700,Jungjeng RD,Junghe City + Junghe City Taipei 235 + TW + +00-12-28 (hex) Data Ltd. +001228 (base 16) Data Ltd. + J. Hagaru 9 + Bratislava 830 05 + SK + +00-12-1F (hex) Harding Instruments +00121F (base 16) Harding Instruments + 9431-41Ave + Edmonton AB T6E 5X7 + CA + +00-12-20 (hex) Cadco Systems +001220 (base 16) Cadco Systems + 2363 Merritt Dr + Garland Texas 75041 + US + +00-12-29 (hex) BroadEasy Technologies Co.,Ltd +001229 (base 16) BroadEasy Technologies Co.,Ltd + 24th Floor,Tower A,JinShan Mansion, + Nanjing Jiangsu 210009 + CN + +00-12-26 (hex) Japan Direx Corporation +001226 (base 16) Japan Direx Corporation + Kyocera Harajuku Bldg. + Shibuya-ku Tokyo 150-0001 + JP + +00-12-22 (hex) Skardin (UK) Ltd +001222 (base 16) Skardin (UK) Ltd + No. 5 Greenway (RO24) + Harlow Essex CM19 5QB + GB + +00-11-E8 (hex) Tixi.Com +0011E8 (base 16) Tixi.Com + Karmeliterweg 114 + Berlin 13465 + DE + +00-11-E0 (hex) U-MEDIA Communications, Inc. +0011E0 (base 16) U-MEDIA Communications, Inc. + 9F, No.1 Jin-Shan St. + Hsinchu 300 + TW + +00-12-0D (hex) Advanced Telecommunication Technologies, Inc. +00120D (base 16) Advanced Telecommunication Technologies, Inc. + 10390 Wilshire Boulevard + Los Angeles California 90024 + US + +00-12-0E (hex) AboCom +00120E (base 16) AboCom + 1F , No. 21, Yanfa 2nd Rd., SBIP + Hsinchu City 300 + TW + +00-11-F2 (hex) Institute of Network Technologies +0011F2 (base 16) Institute of Network Technologies + 17-th Line Vasilevsky Ostrov, 54-1 + St.Petersburg 199178 + RU + +00-12-10 (hex) WideRay Corp +001210 (base 16) WideRay Corp + 25 Kearny Street + San Francisco CA 94108 + US + +00-11-A4 (hex) JStream Technologies Inc. +0011A4 (base 16) JStream Technologies Inc. + Bldg.53, R405, 195 Sec.4, Chung Hsing Rd. + Chutung, Hsinchu 310 + TW + +00-11-98 (hex) Prism Media Products Limited +001198 (base 16) Prism Media Products Limited + William James House + Cambridge Cambridgeshire CB4 0WX + GB + +00-11-97 (hex) Monitoring Technologies Limited +001197 (base 16) Monitoring Technologies Limited + 14 Attenburys Park Estate + Timperley Cheshire WA14 5QE + GB + +00-11-99 (hex) 2wcom Systems GmbH +001199 (base 16) 2wcom Systems GmbH + Am Sophienhof 8 + Flensburg 24941 + DE + +00-11-A7 (hex) Infilco Degremont Inc. +0011A7 (base 16) Infilco Degremont Inc. + 8007 Discovery Dr. + Richmond Virginia 23255-1390 + US + +00-11-A9 (hex) MOIMSTONE Co., LTD +0011A9 (base 16) MOIMSTONE Co., LTD + 7th Floor JoongPyung Building 64-1 + Seoul 137-900 + KR + +00-11-A3 (hex) LanReady Technologies Inc. +0011A3 (base 16) LanReady Technologies Inc. + 4F, No. 337, SinHu 2nd Road., NeiHu District + Taipei 114 + TW + +00-11-76 (hex) Intellambda Systems, Inc. +001176 (base 16) Intellambda Systems, Inc. + 48501 Warm Springs Blvd, #107 + Fremont California 94539 + US + +00-11-77 (hex) Coaxial Networks, Inc. +001177 (base 16) Coaxial Networks, Inc. + 4633 Old Ironsides Dr + Santa Clara CA 95054 + US + +00-11-70 (hex) GSC SRL +001170 (base 16) GSC SRL + VIA PER VIMERCATE + USMATE VELATE MILANO 20040 + IT + +00-11-6B (hex) Digital Data Communications Asia Co.,Ltd +00116B (base 16) Digital Data Communications Asia Co.,Ltd + 8F,No.41,Lane 221,Kang-Chien RD.,Nei-Hu Dis., + Taipei City 114 + TW + +00-11-69 (hex) EMS Satcom +001169 (base 16) EMS Satcom + Green Lane + Tewkesbury Gloucestershire GL20 8HD + GB + +00-11-62 (hex) STAR MICRONICS CO.,LTD. +001162 (base 16) STAR MICRONICS CO.,LTD. + 536 Shimizunanatsushinya + Shizuoka 424-0066 + JP + +00-11-81 (hex) InterEnergy Co.Ltd, +001181 (base 16) InterEnergy Co.Ltd, + 3F Shinyokohama Bosei Bldg. + Yokohama city Kanagawa 222-0033 + JP + +00-11-94 (hex) Chi Mei Communication Systems, Inc. +001194 (base 16) Chi Mei Communication Systems, Inc. + 11F, No.39, Chung Hua RD. Sec 1 + Taipei 100 + TW + +00-11-BF (hex) AESYS S.p.A. +0011BF (base 16) AESYS S.p.A. + Via Artigiani, 41 + Brusaporto Bergamo 24060 + IT + +00-11-B7 (hex) Octalix B.V. +0011B7 (base 16) Octalix B.V. + Molensteijn 60 + De Meern NL-3454 PT + NL + +00-11-B9 (hex) Inner Range Pty. Ltd. +0011B9 (base 16) Inner Range Pty. Ltd. + 1 Millenium Court + Knoxfield Victoria 3180 + AU + +00-11-09 (hex) Micro-Star International +001109 (base 16) Micro-Star International + No 69, Li-De Street, Jung-He City, + Taipei + TW + +00-11-04 (hex) TELEXY +001104 (base 16) TELEXY + 1116, HYUNDAI 41 TOWER, 917-9 + SEOUL 158-723 + KR + +00-11-61 (hex) NetStreams, LLC +001161 (base 16) NetStreams, LLC + 3600 W. Parmer Lane + Austin TX 78727 + US + +00-11-56 (hex) Pharos Systems NZ +001156 (base 16) Pharos Systems NZ + Level 3, 123 Carlton Gore Road + Auckland NZ 1001 + NZ + +00-11-59 (hex) MATISSE NETWORKS INC +001159 (base 16) MATISSE NETWORKS INC + 339 N BERNARDO AVE + MOUNTAIN VIEW CA 94043 + US + +00-11-5C (hex) Cisco Systems, Inc +00115C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-5D (hex) Cisco Systems, Inc +00115D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-26 (hex) Venstar Inc. +001126 (base 16) Venstar Inc. + 9250 Owensmouth Ave. + Chatsworth CA 91311 + US + +00-11-2E (hex) CEICOM +00112E (base 16) CEICOM + 17 rue Gaston Evrard + Toulouse Cedex 1 31094 + FR + +00-11-22 (hex) CIMSYS Inc +001122 (base 16) CIMSYS Inc + #301,Sinsung-clean BLDG,140, Nongseo-Ri,Kiheung-Eup + Yongin-City Kyunggi-Do 449-711 + KR + +00-11-17 (hex) CESNET +001117 (base 16) CESNET + Zikova 4 + Praha 6 160 00 + CZ + +00-11-16 (hex) COTEAU VERT CO., LTD. +001116 (base 16) COTEAU VERT CO., LTD. + 3-3-19 KACHIDOKI + CHUO-KU TOKYO 104-0054 + JP + +00-11-10 (hex) Maxanna Technology Co., Ltd. +001110 (base 16) Maxanna Technology Co., Ltd. + Room201, No.42-3, Luyuan Road + Guangzhou 510095 + CN + +00-11-3B (hex) Micronet Communications Inc. +00113B (base 16) Micronet Communications Inc. + 12F-1, No. 100, Min-Chuan Road + Hsin-Tien Taipei 231 + TW + +00-11-3D (hex) KN SOLTEC CO.,LTD. +00113D (base 16) KN SOLTEC CO.,LTD. + 98B-5L NAMDONG INDUSTRIAL COMPLEX #662-4 GOJAN-DONG + NAMDONG-GU INCHEON 405-818 + KR + +00-11-34 (hex) MediaCell, Inc. +001134 (base 16) MediaCell, Inc. + 600 17th St + Denver CO 80202 + US + +00-11-35 (hex) Grandeye Ltd +001135 (base 16) Grandeye Ltd + 6 Huxley Road + Guildford Surrey GU2 7RE + GB + +00-11-21 (hex) Cisco Systems, Inc +001121 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-49 (hex) Proliphix Inc. +001149 (base 16) Proliphix Inc. + 3 Lan Drive + Westford MA 01886 + US + +00-0F-C0 (hex) DELCOMp +000FC0 (base 16) DELCOMp + Technologielaan 3 + Leuven B-3000 + BE + +00-0F-BA (hex) Tevebox AB +000FBA (base 16) Tevebox AB + Berglinds vag 13 + warmdo S-13900 + SE + +00-0F-B8 (hex) CallURL Inc. +000FB8 (base 16) CallURL Inc. + 3F-11, No. 508 Sec. 5, Chung-Hsiao E. Rd. + Taipei 110 + TW + +00-0F-B7 (hex) Cavium +000FB7 (base 16) Cavium + 2315 N First Street + San Jose CA 95131 + US + +00-0F-D3 (hex) Digium +000FD3 (base 16) Digium + 445 Jan Davis Drive NW + Huntsville AL 35806 + US + +00-0F-D1 (hex) Applied Wireless Identifications Group, Inc. +000FD1 (base 16) Applied Wireless Identifications Group, Inc. + 382 Route 59, Section 292 + Monsey New York 10952 + US + +00-0F-C1 (hex) WAVE Corporation +000FC1 (base 16) WAVE Corporation + 3-25-5 Chidori + Ohta-ku Tokyo 146-0083 + JP + +00-11-00 (hex) Schneider Electric +001100 (base 16) Schneider Electric + 5460 Pottsville Pike + Leesport PA 19533 + US + +00-0F-FA (hex) Optinel Systems, Inc. +000FFA (base 16) Optinel Systems, Inc. + 6835 Deerpath Rd. + Elkridge MD 21075 + US + +00-0F-FD (hex) Glorytek Network Inc. +000FFD (base 16) Glorytek Network Inc. + 5F.-3, No.16, Sec. 1, Dongda Rd., + Hsinchu 300 + TW + +00-0F-F9 (hex) Valcretec, Inc. +000FF9 (base 16) Valcretec, Inc. + Byucksan Digital Valley II 15F + Seoul 153-803 + KR + +00-0F-C4 (hex) NST co.,LTD. +000FC4 (base 16) NST co.,LTD. + 4-3-1 SHINMIYAKODA + HAMAMATSU SHIZUOKA 431-2103 + JP + +00-0F-C9 (hex) Allnet GmbH +000FC9 (base 16) Allnet GmbH + Maistraße 2 + Germering Bavaria 82110 + DE + +00-0F-C6 (hex) Eurocom Industries A/S +000FC6 (base 16) Eurocom Industries A/S + porsvej 2 + Aalborg NV DK-9200 + DK + +00-0F-BE (hex) e-w/you Inc. +000FBE (base 16) e-w/you Inc. + 3F FINE Bldg. 6-17-17 + Shinagawa-ku, Tokyo 140-0013 + JP + +00-0F-A9 (hex) PC Fabrik +000FA9 (base 16) PC Fabrik + Buchenstrasse 13-15 + Dresden Sachsen 01097 + DE + +00-0F-A0 (hex) CANON KOREA BUSINESS SOLUTIONS INC. +000FA0 (base 16) CANON KOREA BUSINESS SOLUTIONS INC. + 736 Wonsi-Dong + Ansan-si Kyunggi-do 425-090 + KR + +00-0F-9A (hex) Synchrony, Inc. +000F9A (base 16) Synchrony, Inc. + 6410 Commonwealth Drive + Roanoke VA 24018 + US + +00-0F-EA (hex) Giga-Byte Technology Co.,LTD. +000FEA (base 16) Giga-Byte Technology Co.,LTD. + No.215,Nan-Ping Road,Ping-Jen City, + Ping-Jen Taoyuan 324 + TW + +00-0F-F7 (hex) Cisco Systems, Inc +000FF7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0F-D8 (hex) Force, Inc. +000FD8 (base 16) Force, Inc. + 825 Park Street + Christiansburg Va 24073 + US + +00-0F-8D (hex) FAST TV-Server AG +000F8D (base 16) FAST TV-Server AG + Ruedesheimerstraße 11-13 + Munich Germany 80686 + DE + +00-0F-85 (hex) ADDO-Japan Corporation +000F85 (base 16) ADDO-Japan Corporation + Shin Edobashi Bldg. 4F, 8-6 Nihombashi Kobuna-cho + Chuo-ku Tokyo 103-0024 + JP + +00-0F-82 (hex) Mortara Instrument, Inc. +000F82 (base 16) Mortara Instrument, Inc. + 7865 N. 86th St. + Milwaukee WI 53224 + US + +00-0F-49 (hex) Northover Solutions Limited +000F49 (base 16) Northover Solutions Limited + Heath Cottage + Larling Norfolk NR16 2RB + GB + +00-0F-4B (hex) Oracle Corporation +000F4B (base 16) Oracle Corporation + 900 Chelmsford Street + Lowell MA 01851 + US + +00-0F-44 (hex) Tivella Inc. +000F44 (base 16) Tivella Inc. + 795 Main Street + Half Moon Bay CA 94019 + US + +00-0F-4A (hex) Kyushu-kyohan co.,ltd +000F4A (base 16) Kyushu-kyohan co.,ltd + 2-6-3,Koganemachi + Kitakyushu-city Fukuoka 802-0071 + JP + +00-0F-81 (hex) PAL Pacific Inc. +000F81 (base 16) PAL Pacific Inc. + 79405 Highway 111 + La Quinta CA 92253 + US + +00-0F-7F (hex) UBSTORAGE Co.,Ltd. +000F7F (base 16) UBSTORAGE Co.,Ltd. + #A-108, Seoul_Sanup_Jiwon_Center + Ganseo-gu Seoul 157-840 + KR + +00-0F-95 (hex) ELECOM Co.,LTD Laneed Division +000F95 (base 16) ELECOM Co.,LTD Laneed Division + 8F Kanda-Muromachi Bldg. + Chiyoda-Ku, Tokyo. 101-0052 + JP + +00-0F-55 (hex) Datawire Communication Networks Inc. +000F55 (base 16) Datawire Communication Networks Inc. + 10 Carlson Court, Suite 300 + Toronto Ontario M9W 6L2 + CA + +00-0F-56 (hex) Continuum Photonics Inc +000F56 (base 16) Continuum Photonics Inc + 5 Fortune Drive + Billerica MA 01821 + US + +00-0F-60 (hex) Lifetron Co.,Ltd +000F60 (base 16) Lifetron Co.,Ltd + 6-7,Tenjinnishimachi + Osaka Osaka Prefecture 530-0045 + JP + +00-0F-5B (hex) Delta Information Systems, Inc. +000F5B (base 16) Delta Information Systems, Inc. + 300 Welsh Road, Bldg. 3 + Horsham PA 19044-2273 + US + +00-0F-8A (hex) WideView +000F8A (base 16) WideView + F. 6, No. 8, Wu-chuan 2 Rd, Hsin-Chuang City + Taipei Country 242 + TW + +00-0F-90 (hex) Cisco Systems, Inc +000F90 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0F-77 (hex) DENTUM CO.,LTD +000F77 (base 16) DENTUM CO.,LTD + Wookyung B/D 602 #678-6 + Seoul 157-030 + KR + +00-0F-7B (hex) Arce Sistemas, S.A. +000F7B (base 16) Arce Sistemas, S.A. + C/Padre Larramendi, 3 - 2º + Bilbao Vizcaya 48012 + ES + +00-0F-68 (hex) Vavic Network Technology, Inc. +000F68 (base 16) Vavic Network Technology, Inc. + 1st Floor, 15 Jiangong Road + Guangzhou Guangdong 510665 + CN + +00-0E-E2 (hex) Custom Engineering +000EE2 (base 16) Custom Engineering + Via Beretttine 2/b + Fontevivo Parma 43010 + IT + +00-0E-E3 (hex) Chiyu Technology Co.,Ltd +000EE3 (base 16) Chiyu Technology Co.,Ltd + No. 28, Renai Road, Chiayi, 600 + Chiayi 600 + TW + +00-0E-E5 (hex) bitWallet, Inc. +000EE5 (base 16) bitWallet, Inc. + Gate City Ohsaki West Tower 18F, 1-11-1 Osaki, Shinagawa-ku + Tokyo 1410032 + JP + +00-0E-DA (hex) C-TECH UNITED CORP. +000EDA (base 16) C-TECH UNITED CORP. + 5F, No 665, CHUNG CHEN RD. + HSIN CHUANG CITT of TAIPEI HSIEN 242 + TW + +00-0E-CF (hex) PROFIBUS Nutzerorganisation e.V. +000ECF (base 16) PROFIBUS Nutzerorganisation e.V. + Haid-und-Neu-Straße 7 + Karlsruhe Baden-Württemberg 76131 + DE + +00-0E-EB (hex) Sandmartin(zhong shan)Electronics Co.,Ltd +000EEB (base 16) Sandmartin(zhong shan)Electronics Co.,Ltd + 3st Industrial Area,Tan Zhou, + Zhongshan Guangdong 528467 + CN + +00-0E-EC (hex) Orban +000EEC (base 16) Orban + 1525 Alvarado St. + San Leandro CA 94577 + US + +00-0E-EF (hex) Private +000EEF (base 16) Private + +00-0E-F1 (hex) EZQUEST INC. +000EF1 (base 16) EZQUEST INC. + 23311 E. LA PALMA AVE. + YORBA LINDA CA 92887 + US + +00-0E-E7 (hex) AAC ELECTRONICS CORP. +000EE7 (base 16) AAC ELECTRONICS CORP. + FLOOR 7,SIXTH BUILDING OF NAIANYOU TNAN INDUSTRIAL AREA,NANSHAN DISTRICT + SHENZHEN PROVINCE GUANGDONG 518054 + CN + +00-0F-1C (hex) DigitAll World Co., Ltd +000F1C (base 16) DigitAll World Co., Ltd + Sejin Bld 2F, 689 ilwon2-dong, + gangnam-gu Seoul 135-946 + KR + +00-0F-1A (hex) Gaming Support B.V. +000F1A (base 16) Gaming Support B.V. + Industrie weg 29 + Rotterdam 3044 AS + NL + +00-0F-0A (hex) Clear Edge Networks +000F0A (base 16) Clear Edge Networks + 11250 El Camino Real + San Diego CA 92130 + US + +00-0F-02 (hex) Digicube Technology Co., Ltd +000F02 (base 16) Digicube Technology Co., Ltd + 8F,No. 51, Lane 35, Jihu Rd., + Taipei 114 + TW + +00-0F-2F (hex) W-LINX TECHNOLOGY CO., LTD. +000F2F (base 16) W-LINX TECHNOLOGY CO., LTD. + 2F,ELLEN L. SKELTON BUILDING,FISHER LANE ROAD + TORTOLA + VG + +00-0F-2D (hex) CHUNG-HSIN ELECTRIC & MACHINERY MFG.CORP. +000F2D (base 16) CHUNG-HSIN ELECTRIC & MACHINERY MFG.CORP. + NO. 25, Wen-Te Rd., Lo-Shan Village + Kwei Shan Hsiang Taoyuan Hsien 330 + TW + +00-0E-F7 (hex) Vulcan Portals Inc +000EF7 (base 16) Vulcan Portals Inc + 505 5th Ave South, Suite 900 + Seattle WA 98104 + US + +00-0E-F0 (hex) Festo AG & Co. KG +000EF0 (base 16) Festo AG & Co. KG + Ruiterstraße 82 + Esslingen 73734 + DE + +00-0E-E9 (hex) WayTech Development, Inc. +000EE9 (base 16) WayTech Development, Inc. + 11Floor, 253 Min-Sheng Road + HsinChu 300 + TW + +00-0F-40 (hex) Optical Internetworking Forum +000F40 (base 16) Optical Internetworking Forum + 48377 Fremont Blvd + Fremont CA 94538 + US + +00-0F-33 (hex) DUALi Inc. +000F33 (base 16) DUALi Inc. + #505 Samsung Techno Park Bldg 471 + Suwon Gyeonggi-do 442-824 + KR + +00-0F-05 (hex) 3B SYSTEM INC. +000F05 (base 16) 3B SYSTEM INC. + 1727, SANKYUK2-DONG, BUK-GU + DAEGU 702-845 + KR + +00-0E-C9 (hex) YOKO Technology Corp. +000EC9 (base 16) YOKO Technology Corp. + 6F, No.10, Lane16, Sec2, Sze-Chuan Rd., Pan- + Taipei 886 + TW + +00-0E-BD (hex) Burdick, a Quinton Compny +000EBD (base 16) Burdick, a Quinton Compny + 500 Burdick Parkway + Deerfield WI 53531 + US + +00-0E-B9 (hex) HASHIMOTO Electronics Industry Co.,Ltd. +000EB9 (base 16) HASHIMOTO Electronics Industry Co.,Ltd. + 3866-12 Takasu-cho + Matsusaka Mie 515-0104 + JP + +00-0E-B2 (hex) Micro-Research Finland Oy +000EB2 (base 16) Micro-Research Finland Oy + Välitalontie 83 C + Helsinki FIN-00660 + FI + +00-0E-D0 (hex) Privaris, Inc. +000ED0 (base 16) Privaris, Inc. + 675 Peter Jefferson Pkwy, Ste 150 + Charlottesville Virginia 22911 + US + +00-0E-C3 (hex) Logic Controls, Inc. +000EC3 (base 16) Logic Controls, Inc. + 355 Denton Avenue + New Hyde Park NY 11040 + US + +00-0E-C4 (hex) Iskra Transmission d.d. +000EC4 (base 16) Iskra Transmission d.d. + Stegne 11 + Ljubljana 1000 + SI + +00-0E-C1 (hex) MYNAH Technologies +000EC1 (base 16) MYNAH Technologies + 504 Trade Center Blvd + Chesterfield MO 63005 + US + +00-0E-82 (hex) Commtech Wireless +000E82 (base 16) Commtech Wireless + 115/396 Scarborough Beach Rd + Perth WA 6017 + AU + +00-0E-89 (hex) CLEMATIC +000E89 (base 16) CLEMATIC + 101 rue Pierre SEMARD + CHATILLON R.P. 92320 + US + +00-0E-79 (hex) Ample Communications Inc. +000E79 (base 16) Ample Communications Inc. + 4034 Clipper Ct. + Fremont CA 94538 + US + +00-0E-A1 (hex) Formosa Teletek Corporation +000EA1 (base 16) Formosa Teletek Corporation + 358,Huaya 2nd Rd. + Taoyuan 333 + TW + +00-0E-98 (hex) HME Clear-Com LTD. +000E98 (base 16) HME Clear-Com LTD. + 7400 Beach Drive + Cambridgeshire CB25 9TP + GB + +00-0E-99 (hex) Spectrum Digital, Inc +000E99 (base 16) Spectrum Digital, Inc + 12502 Exchange Drive, Suite 440 + Stafford TX 77477 + US + +00-0E-95 (hex) Fujiya Denki Seisakusho Co.,Ltd. +000E95 (base 16) Fujiya Denki Seisakusho Co.,Ltd. + 8F Fukushima BLDG. 6-25-11,Nishi-Gotanda + Shinagawa-Ku Tokyo 141-0031 + JP + +00-0E-97 (hex) Ultracker Technology CO., Inc +000E97 (base 16) Ultracker Technology CO., Inc + 14F-1, No. 888, Jingguo Road, Taoyuan City, + Taoyuan 330 + TW + +00-0E-A7 (hex) Endace Technology +000EA7 (base 16) Endace Technology + 85 Alexandra Street + Hamilton 3204 + NZ + +00-0E-6F (hex) IRIS Corporation Berhad +000E6F (base 16) IRIS Corporation Berhad + IRIS Smart Technology Complex + Kuala Lumpur WP 57000 + MY + +00-0E-B5 (hex) Ecastle Electronics Co., Ltd. +000EB5 (base 16) Ecastle Electronics Co., Ltd. + #502, Namjang B/D, Bangbae-dong, + Seoul 137-818 + KR + +00-0E-50 (hex) Thomson Telecom Belgium +000E50 (base 16) Thomson Telecom Belgium + Prins Boudewijnlaan 47 + Edegem Antwerp B-2650 + BE + +00-0E-4B (hex) atrium c and i +000E4B (base 16) atrium c and i + 124-4, Ojeon-dong, + Uiwang-city Kyunggi-Do 437-819 + KR + +00-0E-2B (hex) Safari Technologies +000E2B (base 16) Safari Technologies + 63855 M40 Hwy + Lawton MI 49065 + US + +00-0E-28 (hex) Dynamic Ratings P/L +000E28 (base 16) Dynamic Ratings P/L + C/O Wilson Transformer Co. + Glen Waverley Victoria 3150 + AU + +00-0E-24 (hex) Huwell Technology Inc. +000E24 (base 16) Huwell Technology Inc. + 1F 82-21, Majin Building + Seoul 135-010 + KR + +00-0E-3F (hex) Soronti, Inc. +000E3F (base 16) Soronti, Inc. + 12159 Business Park Dr, Suite 140 + Draper Utah 84020 + US + +00-0E-45 (hex) Beijing Newtry Electronic Technology Ltd +000E45 (base 16) Beijing Newtry Electronic Technology Ltd + PO Box 95, No. 1 Bei Sha Tan, + Beijing 10083 + CN + +00-0E-1D (hex) ARION Technology Inc. +000E1D (base 16) ARION Technology Inc. + 3F, Pica Bldg, 894-2, Hogye 2 Dong + An-Yang City Gyeonggi-Do + KR + +00-0E-12 (hex) Adaptive Micro Systems Inc. +000E12 (base 16) Adaptive Micro Systems Inc. + 7840 North 86th St. + Milwaukee WI 53224 + US + +00-0E-4F (hex) Trajet GmbH +000E4F (base 16) Trajet GmbH + Rebenring 33 + Braunschweig Nds. 38106 + DE + +00-0E-38 (hex) Cisco Systems, Inc +000E38 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0E-36 (hex) HEINESYS, Inc. +000E36 (base 16) HEINESYS, Inc. + 3F, Sungkwang Bldg. 456-13, Sungnae-dong + Seoul 134-848 + KR + +00-0E-17 (hex) Private +000E17 (base 16) Private + +00-0E-15 (hex) Tadlys LTD +000E15 (base 16) Tadlys LTD + ISRAELI SHIMON 3 + RISHON lEZYYON ISRAEL 75654 + US + +00-0E-01 (hex) ASIP Technologies Inc. +000E01 (base 16) ASIP Technologies Inc. + 10F-2, NO.322, Sec.1, Guangfu Rd., + Hsinchu 300 + TW + +00-0D-CB (hex) Petcomkorea Co., Ltd. +000DCB (base 16) Petcomkorea Co., Ltd. + 5F,689-47,Geumjeong-dong,Gunpo-si,Kyungg + Kyunggi-do gunpo-si 435-050 + KR + +00-0D-CC (hex) NEOSMART Corp. +000DCC (base 16) NEOSMART Corp. + Yoon-B/D 4F, 475-31, Bangbae 2-dong + Seoul Seocho-gu 147-819 + KR + +00-0D-CE (hex) Dynavac Technology Pte Ltd +000DCE (base 16) Dynavac Technology Pte Ltd + 30 Tuas Avenue 9 + 639183 + SG + +00-0D-E8 (hex) Nasaco Electronics Pte. Ltd +000DE8 (base 16) Nasaco Electronics Pte. Ltd + Level 4, Nasaco Tech Centre + 486056 + SG + +00-0D-E9 (hex) Napatech Aps +000DE9 (base 16) Napatech Aps + Rundofrbivej 271, 1 + Naerum 2850 + DK + +00-0D-E6 (hex) YOUNGBO ENGINEERING CO.,LTD +000DE6 (base 16) YOUNGBO ENGINEERING CO.,LTD + Mt.22, Jaeunga-ri, Jigsan-Eup, + Cheonan-shi Chungcheongnam-do #330-810 + KR + +00-0D-C3 (hex) First Communication, Inc. +000DC3 (base 16) First Communication, Inc. + 1F, No.36, Industry E. Rd. IV., + Hsinchu + TW + +00-0D-B9 (hex) PC Engines GmbH +000DB9 (base 16) PC Engines GmbH + Flughofstrasse 58 + 8152 Glattbrugg + CH + +00-0D-B7 (hex) SANKO ELECTRIC CO,.LTD +000DB7 (base 16) SANKO ELECTRIC CO,.LTD + 7-23 Tamanoi-cho Atsuta-ku + Nagoya-shi Aichi 456-0025 + JP + +00-0D-AC (hex) Japan CBM Corporation +000DAC (base 16) Japan CBM Corporation + 5-68-10 Nakano, + Nakano-Ku Tokyo 164-0001 + JP + +00-0D-DF (hex) Japan Image & Network Inc. +000DDF (base 16) Japan Image & Network Inc. + 5-29-12 Shiba + Minato-ku Tokyo 108-0014 + JP + +00-0D-DB (hex) AIRWAVE TECHNOLOGIES INC. +000DDB (base 16) AIRWAVE TECHNOLOGIES INC. + 3F,No.9,Industry E. 9th Road + Hsinchu 300 + TW + +00-0E-04 (hex) CMA/Microdialysis AB +000E04 (base 16) CMA/Microdialysis AB + Dalvägen 10 / Box 2 + Solna 171 18 + SE + +00-0D-2A (hex) Scanmatic AS +000D2A (base 16) Scanmatic AS + Kilsund + Staubø 4920 + NO + +00-0D-29 (hex) Cisco Systems, Inc +000D29 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0D-26 (hex) Primagraphics Limited +000D26 (base 16) Primagraphics Limited + Cambridge House, No.2 Focus Four + Letchworth Garden City Hertfordshire SG6 2TU + GB + +00-0D-46 (hex) Parker SSD Drives +000D46 (base 16) Parker SSD Drives + 9225 Forsyth Park Drive + Charlotte NC 28273-3884 + US + +00-0D-41 (hex) Siemens AG ICM MP UC RD IT KLF1 +000D41 (base 16) Siemens AG ICM MP UC RD IT KLF1 + Suedstrasse 9 + Kamp-Lintfort NRW 47475 + DE + +00-0D-42 (hex) Newbest Development Limited +000D42 (base 16) Newbest Development Limited + 3/F Unit 311-312 + Shatin NT + HK + +00-0D-3C (hex) i.Tech Dynamic Ltd +000D3C (base 16) i.Tech Dynamic Ltd + Room 1112, Metroplaza Tower 2, 223 Hing + 852 + HK + +00-0D-55 (hex) SANYCOM Technology Co.,Ltd +000D55 (base 16) SANYCOM Technology Co.,Ltd + 6F,Beijing Capital Times Square,88# Xich + Beijing 100031 + CN + +00-0D-57 (hex) Fujitsu I-Network Systems Limited. +000D57 (base 16) Fujitsu I-Network Systems Limited. + 1-403 kosugi-cho nakahara-ku + kawasaki kanagawa 211-0063 + JP + +00-0D-58 (hex) Private +000D58 (base 16) Private + +00-0D-51 (hex) DIVR Systems, Inc. +000D51 (base 16) DIVR Systems, Inc. + 2161 Saturn Ct. + Bakersfield CA 93308 + US + +00-0D-39 (hex) Network Electronics +000D39 (base 16) Network Electronics + Box 1020 + Sandefjord Sandefjord N3204 + NO + +00-0D-35 (hex) PAC International Ltd +000D35 (base 16) PAC International Ltd + 1 Park Gate Close + Stockport Cheshire SK6 2SZ + GB + +00-0D-95 (hex) Opti-cell, Inc. +000D95 (base 16) Opti-cell, Inc. + 100 High Tower Blvd., Suite 301 + Pittsburgh PA 15205 + US + +00-0D-91 (hex) Eclipse (HQ Espana) S.L. +000D91 (base 16) Eclipse (HQ Espana) S.L. + CC de Negocios + Puerto de Banus Marbella 29660 + ES + +00-0D-62 (hex) Funkwerk Dabendorf GmbH +000D62 (base 16) Funkwerk Dabendorf GmbH + Maerkische Strasse + Dabendorf Brandenburg 15806 + DE + +00-0D-65 (hex) Cisco Systems, Inc +000D65 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0D-45 (hex) Tottori SANYO Electric Co., Ltd. +000D45 (base 16) Tottori SANYO Electric Co., Ltd. + 3-201, Minami Yoshikata + Tottori City Tottori 680-8634 + JP + +00-0D-A1 (hex) MIRAE ITS Co.,LTD. +000DA1 (base 16) MIRAE ITS Co.,LTD. + 7F, ChangHyun B/D,960-1,HoGye1Dong + AnYang KyongiGiDo 431-840 + KR + +00-0D-80 (hex) Online Development Inc +000D80 (base 16) Online Development Inc + 7209 Chapman Hwy + Knoxville Tn 37920 + US + +00-0D-13 (hex) Wilhelm Rutenbeck GmbH&Co.KG +000D13 (base 16) Wilhelm Rutenbeck GmbH&Co.KG + Niederworth 1-10 + Schalksmühle NRW 58579 + DE + +00-0D-19 (hex) ROBE Show lighting +000D19 (base 16) ROBE Show lighting + Hazovice 2090 + Roznov pod Radhostem 756 61 + US + +00-0D-1C (hex) Amesys Defense +000D1C (base 16) Amesys Defense + 1030 Av de la LAUZIERE + AIX en PROVENCE Cedex 03 13794 + FR + +00-0C-ED (hex) Real Digital Media +000CED (base 16) Real Digital Media + 485 North Keller Road + Maitland FL 32751 + US + +00-0C-F0 (hex) M & N GmbH +000CF0 (base 16) M & N GmbH + Dieselstr 18 + Rosbach v.d.H. 61191 + DE + +00-0C-F4 (hex) AKATSUKI ELECTRIC MFG.CO.,LTD. +000CF4 (base 16) AKATSUKI ELECTRIC MFG.CO.,LTD. + 593-1,aoji­ cho + kusatsu shi shiga 525-0041 + JP + +00-0C-F3 (hex) CALL IMAGE SA +000CF3 (base 16) CALL IMAGE SA + 867 Route Imperiale + BAILLARGUES 34670 + FR + +00-0C-CF (hex) Cisco Systems, Inc +000CCF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0C-D8 (hex) M. K. Juchheim GmbH & Co +000CD8 (base 16) M. K. Juchheim GmbH & Co + Moltkestraße 13 - 31 + Fulda Hessen 36039 + DE + +00-0C-C6 (hex) Ka-Ro electronics GmbH +000CC6 (base 16) Ka-Ro electronics GmbH + Pascalstraße 22 + Aachen NW 52076 + DE + +00-0D-01 (hex) P&E Microcomputer Systems, Inc. +000D01 (base 16) P&E Microcomputer Systems, Inc. + 710 Commonwealth Ave + Boston Ma 02215 + US + +00-0D-00 (hex) Seaway Networks Inc. +000D00 (base 16) Seaway Networks Inc. + 1 Chrysalis Way + Ottawa Ontario K2G 6P9 + CA + +00-0C-F9 (hex) Xylem Water Solutions +000CF9 (base 16) Xylem Water Solutions + Gesallvagen + + SE + +00-0C-C4 (hex) Tiptel AG +000CC4 (base 16) Tiptel AG + Halskestrasse 1 + Ratingen NRW 40880 + DE + +00-0C-BA (hex) Jamex, Inc. +000CBA (base 16) Jamex, Inc. + 2415 N Triphammer Rd + Ithaca NY 14850 + US + +00-0C-D1 (hex) SFOM Technology Corp. +000CD1 (base 16) SFOM Technology Corp. + No.18, Lane 32, Wufu 1st Rd., Luju shian + Luju Shiang Tauyuan County 338 + TW + +00-0C-CE (hex) Cisco Systems, Inc +000CCE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0C-E0 (hex) Trek Diagnostics Inc. +000CE0 (base 16) Trek Diagnostics Inc. + 982 Keynote Circle + Cleveland Ohio 44131 + US + +00-0C-E2 (hex) Rolls-Royce +000CE2 (base 16) Rolls-Royce + 105 N. Sandusky St. + Mt. Vernon Ohio 43050 + US + +00-0D-0C (hex) MDI Security Systems +000D0C (base 16) MDI Security Systems + 9518 Ninth Street + Rancho Cucamonga CA 91730 + US + +00-0D-16 (hex) UHS Systems Pty Ltd +000D16 (base 16) UHS Systems Pty Ltd + PO Box 6264 + Alexandria NSW 2015 + AU + +00-0D-1F (hex) AV Digital +000D1F (base 16) AV Digital + Pottendorfer Strasse 25-27/4/1/1 + Wien 1120 + AT + +00-0C-AD (hex) BTU International +000CAD (base 16) BTU International + 23 Esquire Rd + North Billerica MA 01862 + US + +00-0C-AA (hex) Cubic Transportation Systems Inc +000CAA (base 16) Cubic Transportation Systems Inc + 1308 S. Washington Street + Tullahoma TN 37388 + US + +00-0C-AC (hex) Citizen Watch Co., Ltd. +000CAC (base 16) Citizen Watch Co., Ltd. + 6-1-12, Tanashi-cho + Nishi-Tokyo-shi Tokyo 188-8511 + JP + +00-0C-AE (hex) Ailocom Oy +000CAE (base 16) Ailocom Oy + Hatanpaan valtatie 24 + TAMPERE FIN 33950 + FI + +00-0C-A3 (hex) Rancho Technology, Inc. +000CA3 (base 16) Rancho Technology, Inc. + 10783 Bell Court + Rancho Cucamonga CA 19730 + US + +00-0C-9C (hex) Chongho information & communications +000C9C (base 16) Chongho information & communications + Chongho Bldg, #7-61 Yangjae-dong, Seocho + Seoul 137-130 + KR + +00-0C-97 (hex) NV ADB TTV Technologies SA +000C97 (base 16) NV ADB TTV Technologies SA + LEUVENSESTEENWEG,585 + ZAVENTEM Vlaamse brabant 1930 + BE + +00-0C-8F (hex) Nergal s.r.l. +000C8F (base 16) Nergal s.r.l. + Viale Bardanzellu,8 + Roma 00155 + IT + +00-0C-92 (hex) WolfVision Gmbh +000C92 (base 16) WolfVision Gmbh + VWP + Goetzis Vorarlberg A-6840 + AT + +00-0C-93 (hex) Xeline Co., Ltd. +000C93 (base 16) Xeline Co., Ltd. + 7F. Chungjin Bldg., 475-22 + Seoul 137-819 + KR + +00-0C-7F (hex) synertronixx GmbH +000C7F (base 16) synertronixx GmbH + Lange Laube 22 + Hannover Niedersachsen 30159 + DE + +00-0C-81 (hex) Schneider Electric (Australia) +000C81 (base 16) Schneider Electric (Australia) + 80 Schneider Road + Eagle Farm Qld 4009 + AU + +00-0C-9E (hex) MemoryLink Corp. +000C9E (base 16) MemoryLink Corp. + 36 Jewelers Park Drive + Neenah Wisconsin 54957 + US + +00-0C-95 (hex) PrimeNet +000C95 (base 16) PrimeNet + Hongik University, 72-1, Sangsu-Dong, Ma + Seoul 121-791 + KR + +00-0C-76 (hex) MICRO-STAR INTERNATIONAL CO., LTD. +000C76 (base 16) MICRO-STAR INTERNATIONAL CO., LTD. + No 69, Li-De Street, Jung-He City, Taipe + Taipei + TW + +00-0C-80 (hex) Opelcomm Inc. +000C80 (base 16) Opelcomm Inc. + 46750 Fremont Blvd. Ste 210 + Fremont CA 94538 + US + +00-0C-7D (hex) TEIKOKU ELECTRIC MFG. CO., LTD +000C7D (base 16) TEIKOKU ELECTRIC MFG. CO., LTD + 60,HIRANO + IBO-GUN HYOGO 679-4395 + JP + +00-0C-B7 (hex) Nanjing Huazhuo Electronics Co., Ltd. +000CB7 (base 16) Nanjing Huazhuo Electronics Co., Ltd. + No.77 Gaohu Road + Nanjing Jiangsu 211100 + CN + +00-0C-68 (hex) SigmaTel, Inc. +000C68 (base 16) SigmaTel, Inc. + 201 Jones Road + Waltham MA 02451 + US + +00-0C-07 (hex) Iftest AG +000C07 (base 16) Iftest AG + Schwimmbadstrasse 43 + Wettingen AG 5430 + CH + +00-0C-0C (hex) APPRO TECHNOLOGY INC. +000C0C (base 16) APPRO TECHNOLOGY INC. + 13F, No. 66 Chung-Cheng Rd, + Hsin-Chuang Taipei 242 + TW + +00-0C-0E (hex) XtremeSpectrum, Inc. +000C0E (base 16) XtremeSpectrum, Inc. + 8133 Leesburg Pike + Vienna VA 22182 + US + +00-0C-12 (hex) Micro-Optronic-Messtechnik GmbH +000C12 (base 16) Micro-Optronic-Messtechnik GmbH + Lessingstrasse 14 + Langebrück Saxony D-01465 + DE + +00-0C-10 (hex) PNI Corporation +000C10 (base 16) PNI Corporation + 5464 Skylane Blvd #A + Santa Rosa CA 95403 + US + +00-0C-40 (hex) Altech Controls +000C40 (base 16) Altech Controls + 1545 Industial Drive + Missouri City Texas 77489 + US + +00-0C-3E (hex) Crest Audio +000C3E (base 16) Crest Audio + 16-00 Pollitt Drive + Fair Lawn NJ 07410 + US + +00-0C-3A (hex) Oxance +000C3A (base 16) Oxance + 75-85 rue Richelieu + les Lucs sur Boulogne 85170 + FR + +00-0C-35 (hex) KaVo Dental GmbH & Co. KG +000C35 (base 16) KaVo Dental GmbH & Co. KG + Bismarkring 39 + Biberach/Riss Baden-Württemberg 88400 + DE + +00-0C-56 (hex) Megatel Computer (1986) Corp. +000C56 (base 16) Megatel Computer (1986) Corp. + 586 Main Street + Glen Williams Ontario L7G 3T6 + CA + +00-0C-57 (hex) MACKIE Engineering Services Belgium BVBA +000C57 (base 16) MACKIE Engineering Services Belgium BVBA + Industriepark Noord 10 + Sint Niklaas B-9100 + BE + +00-0C-23 (hex) Beijing Lanchuan Tech. Co., Ltd. +000C23 (base 16) Beijing Lanchuan Tech. Co., Ltd. + Rm220,No.30 Shangyuancun,Gaoliangqiaolu, + Beijing 100044 + CN + +00-0C-25 (hex) Allied Telesis Labs, Inc. +000C25 (base 16) Allied Telesis Labs, Inc. + Suite 450 + Raleigh NC 27606 + US + +00-0C-18 (hex) Zenisu Keisoku Inc. +000C18 (base 16) Zenisu Keisoku Inc. + 2-13-37 + Fuchu-shi Tokyo 183-0027 + JP + +00-0C-0A (hex) Guangdong Province Electronic Technology Research Institute +000C0A (base 16) Guangdong Province Electronic Technology Research Institute + Electronic Technology Building,NO.61-65, + Guangzhou Guangdong 510630 + CN + +00-0C-0B (hex) Broadbus Technologies +000C0B (base 16) Broadbus Technologies + 80 Central Street + Boxborough Massachusetts 01719 + US + +00-0C-4A (hex) Cygnus Microsystems (P) Limited +000C4A (base 16) Cygnus Microsystems (P) Limited + 93, Phase II, + Hyderabad Andhra Pradesh 500051 + IN + +00-0C-54 (hex) Pedestal Networks, Inc +000C54 (base 16) Pedestal Networks, Inc + 6503 Dumbarton Circle + Fremont CA 94555 + US + +00-0C-37 (hex) Geomation, Inc. +000C37 (base 16) Geomation, Inc. + 25188 Genesee Trail Road + Golden CO 80401 + US + +00-0B-E8 (hex) AOIP +000BE8 (base 16) AOIP + 6 rue Maryse BASTIE + COURCOURONNES Idf 91080 + FR + +00-0B-DC (hex) AKCP +000BDC (base 16) AKCP + 67/285 Muangake Village #8 + Amphur Muang Patomthanee 12000 + TH + +00-0B-D8 (hex) Industrial Scientific Corp. +000BD8 (base 16) Industrial Scientific Corp. + 1001 Oakdale Road + Oakdale PA 15071 + US + +00-0B-D7 (hex) DORMA Time + Access GmbH +000BD7 (base 16) DORMA Time + Access GmbH + Mainzer Straße 36-52 + Bonn Nordrheinwestfalen 53179 + DE + +00-0B-DD (hex) TOHOKU RICOH Co., LTD. +000BDD (base 16) TOHOKU RICOH Co., LTD. + 3-1 Shinmeido + Shibata Miyagi pref. 989-1695 + JP + +00-0B-E5 (hex) HIMS International Corporation +000BE5 (base 16) HIMS International Corporation + 139-9 + Daejeon Daejeon 305-806 + KR + +00-0B-E9 (hex) Actel Corporation +000BE9 (base 16) Actel Corporation + 200 Valley Road + Mt. Arlington NJ 07856 + US + +00-0B-E3 (hex) Key Stream Co., Ltd. +000BE3 (base 16) Key Stream Co., Ltd. + No. 2 Nagaoka Bldg. 4F, 2-8-5 Hatchobor + Chuo-ku Tokyo 104-0032 + JP + +00-0B-D3 (hex) cd3o +000BD3 (base 16) cd3o + 402 W Broadway + San Deigo CA 92101 + US + +00-0B-D5 (hex) Nvergence, Inc. +000BD5 (base 16) Nvergence, Inc. + Jeil Bldg. 4th, Samsung-dong 168-26, Kan + Seoul 135-090 + KR + +00-0B-D1 (hex) Aeronix, Inc. +000BD1 (base 16) Aeronix, Inc. + 1775 W. Hibiscus Blvd, + Melbourne FL 32901 + US + +00-0B-D2 (hex) Remopro Technology Inc. +000BD2 (base 16) Remopro Technology Inc. + No. 443, Huannan RD., + Pingjen City Taoyuan 324 + TW + +00-0B-C7 (hex) ICET S.p.A. +000BC7 (base 16) ICET S.p.A. + Via Quarto Negroni, 63 + Cecchina di Ariccia Roma 00040 + IT + +00-0B-B8 (hex) Kihoku Electronic Co. +000BB8 (base 16) Kihoku Electronic Co. + Marukatubiru 3F 4-9-6 + Osakashi Osaka-hu 556-0005 + JP + +00-0B-C0 (hex) China IWNComm Co., Ltd. +000BC0 (base 16) China IWNComm Co., Ltd. + 4F.C Xietong Building,No.12 Gaoxin 2nd r + Xi'an shaanxi 710075 + CN + +00-0B-B0 (hex) Sysnet Telematica srl +000BB0 (base 16) Sysnet Telematica srl + Viale Berbera, 49 + Milan 20162 + IT + +00-0B-B4 (hex) RDC Semiconductor Inc., +000BB4 (base 16) RDC Semiconductor Inc., + 6F-1 , No.2-1, Lihsin Rd, Science-Based + Hsin Chu 300 + TW + +00-0B-CC (hex) JUSAN, S.A. +000BCC (base 16) JUSAN, S.A. + Vivero, 5 + MADRID 28040 + ES + +00-0B-AC (hex) 3Com Ltd +000BAC (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +00-0B-F9 (hex) Gemstone Communications, Inc. +000BF9 (base 16) Gemstone Communications, Inc. + 6Fl., No. 102, Hengyang Rd. + Taipei 100 + TW + +00-0B-FC (hex) Cisco Systems, Inc +000BFC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-EA (hex) Zultys Technologies +000BEA (base 16) Zultys Technologies + 785 Lucern Drive + Sunnyvale CA 94085 + US + +00-0B-9F (hex) Neue ELSA GmbH +000B9F (base 16) Neue ELSA GmbH + Sonnenweg 11 + Aachen 52070 + DE + +00-0B-98 (hex) NiceTechVision +000B98 (base 16) NiceTechVision + IntelZone 703 + YongIn Gugal-ri Ki Heung KyoungKiDo 354-2 + KR + +00-0B-95 (hex) eBet Gaming Systems Pty Ltd +000B95 (base 16) eBet Gaming Systems Pty Ltd + Suite D, 255 Rawson Street + Auburn NSW 2144 + AU + +00-0B-9E (hex) Yasing Technology Corp. +000B9E (base 16) Yasing Technology Corp. + No. 50, Ta Hsueh Road, HsinChu, Taiwan + HsinChu 300 + TW + +00-0B-88 (hex) Vidisco ltd. +000B88 (base 16) Vidisco ltd. + 17 Yechiel Dresner + Petach-Tikva 49277 + IL + +00-0B-54 (hex) BiTMICRO Networks, Inc. +000B54 (base 16) BiTMICRO Networks, Inc. + 47929 Fremont Blvd + Fremont CA 94538 + US + +00-0B-8C (hex) Flextronics +000B8C (base 16) Flextronics + Migdal HaEmek + 23108 Hataasia 1 + IL + +00-0B-8A (hex) MITEQ Inc. +000B8A (base 16) MITEQ Inc. + 100 Davids Drive + Hauppauge NY 11788-2034 + US + +00-0B-90 (hex) ADVA Optical Networking Ltd. +000B90 (base 16) ADVA Optical Networking Ltd. + ADVAntage House + York YO30 4RY + GB + +00-0B-79 (hex) X-COM, Inc. +000B79 (base 16) X-COM, Inc. + 8809 Sudley Road + Manassas VA 20110 + US + +00-0B-4B (hex) VISIOWAVE SA +000B4B (base 16) VISIOWAVE SA + Route de la Pierre 22 + ECUBLENS VAUD CH-1024 + CH + +00-0B-36 (hex) Productivity Systems, Inc. +000B36 (base 16) Productivity Systems, Inc. + 1711 Analog Drive + Richardson TX 75081-1944 + US + +00-0B-35 (hex) Quad Bit System co., Ltd. +000B35 (base 16) Quad Bit System co., Ltd. + 402 Gayang Technotown + Seoul Kangseogu 157-810 + KR + +00-0B-75 (hex) Iosoft Ltd. +000B75 (base 16) Iosoft Ltd. + 5 Woodlark Road + Cambridge Cambs. CB3 0HT + GB + +00-0B-70 (hex) Load Technology, Inc. +000B70 (base 16) Load Technology, Inc. + 4225 Production Court + Las Vegas NV 89115 + US + +00-0B-6F (hex) Media Streaming Networks Inc +000B6F (base 16) Media Streaming Networks Inc + 1905 Anam Tower, 702-10, Yeoksam dong, K + Seoul 135-080 + KR + +00-0B-43 (hex) Microscan Systems, Inc. +000B43 (base 16) Microscan Systems, Inc. + 700 SW 39th St + Renton WA 98057 + US + +00-0B-45 (hex) Cisco Systems, Inc +000B45 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-4C (hex) Clarion (M) Sdn Bhd +000B4C (base 16) Clarion (M) Sdn Bhd + Phase 3 + Bayan Lepas Penang 11900 + MY + +00-0B-63 (hex) Kaleidescape +000B63 (base 16) Kaleidescape + One First Street, Suite Sixteen + Los Altos CA 94022 + US + +00-0B-68 (hex) Addvalue Communications Pte Ltd +000B68 (base 16) Addvalue Communications Pte Ltd + 28,TAI SENG STREET #06-02 + Singapore 534106 + SG + +00-0B-58 (hex) Astronautics C.A LTD +000B58 (base 16) Astronautics C.A LTD + 23 hayarkon street + Bnei Brak 51261 + IL + +00-0B-55 (hex) ADInstruments +000B55 (base 16) ADInstruments + P. O. Box 587 + Dunedin Otago 9001 + NZ + +00-0B-87 (hex) American Reliance Inc. +000B87 (base 16) American Reliance Inc. + 11801 Goldring Rd + Arcadia CA 91006 + US + +00-0B-0D (hex) Air2U, Inc. +000B0D (base 16) Air2U, Inc. + No. 5-1 Innovation Rd 1, Science-based P + Hsin-Chu Taiwan 300 + TW + +00-0B-0B (hex) Corrent Corporation +000B0B (base 16) Corrent Corporation + 1711 W. Greentree Dr. + Tempe AZ 85284-2717 + US + +00-0B-08 (hex) Pillar Data Systems +000B08 (base 16) Pillar Data Systems + 1371 McCarthy Blvd. + Milpitas CA 95035 + US + +00-0B-27 (hex) Scion Corporation +000B27 (base 16) Scion Corporation + 82 Worman's Mill Court + Frederick MD 21701 + US + +00-0B-21 (hex) G-Star Communications Inc. +000B21 (base 16) G-Star Communications Inc. + 5F, 69-10, Sec. 2, Chung Cheng East Road + Taipei Hsien 251 + TW + +00-0A-DA (hex) Vindicator Technologies +000ADA (base 16) Vindicator Technologies + 5307 Industrial Oaks Blvd. + Austin Texas 78735 + US + +00-0A-C9 (hex) Zambeel Inc +000AC9 (base 16) Zambeel Inc + 45700 Northport Loop East + Fremont CA 94538 + US + +00-0B-25 (hex) Aeluros +000B25 (base 16) Aeluros + 201 San Antonio Circle #172 + Mountain View CA 94040 + US + +00-0B-1A (hex) Industrial Defender, Inc. +000B1A (base 16) Industrial Defender, Inc. + 16 Chestnut Street + Foxborough MA 02035 + US + +00-0B-18 (hex) Private +000B18 (base 16) Private + +00-0B-15 (hex) Platypus Technology +000B15 (base 16) Platypus Technology + 4/1 Atchison St + St Leonards NSW 2065 + AU + +00-0A-FA (hex) Traverse Technologies Australia +000AFA (base 16) Traverse Technologies Australia + Unit 13, 240 Sydney Rd + Coburg Victoria 3058 + AU + +00-0A-FC (hex) Core Tec Communications, LLC +000AFC (base 16) Core Tec Communications, LLC + 49 Leavenworth Street + Waterbury CT 06702 + US + +00-0A-EC (hex) Koatsu Gas Kogyo Co., Ltd. +000AEC (base 16) Koatsu Gas Kogyo Co., Ltd. + 1-5, Doyama-cho, Kita-ku, Osaka + Osaka 530-8411 + JP + +00-0A-E7 (hex) ELIOP S.A. +000AE7 (base 16) ELIOP S.A. + Avenida de Manoteras, 30 + Madrid E-28050 + ES + +00-0A-E8 (hex) Cathay Roxus Information Technology Co. LTD +000AE8 (base 16) Cathay Roxus Information Technology Co. LTD + Fuhua mansion building A/B 4F + Beijing 100027 + CN + +00-0A-DD (hex) Allworx Corp. +000ADD (base 16) Allworx Corp. + 245 East Main Street + East Rochester NY 14604 + US + +00-0A-E1 (hex) EG Technology +000AE1 (base 16) EG Technology + 250 15th Street + Atlanta GA 30318 + US + +00-0A-DF (hex) Gennum Corporation +000ADF (base 16) Gennum Corporation + P.O Box 489 + Burlington Ontario L7R 3Y3 + CA + +00-0B-3F (hex) Anthology Solutions Inc. +000B3F (base 16) Anthology Solutions Inc. + 1722 Ringwood Ave. + San Jose CA 95131 + US + +00-0B-3C (hex) Cygnal Integrated Products, Inc. +000B3C (base 16) Cygnal Integrated Products, Inc. + 4301 Westbank Drive + Austin TX 78746 + US + +00-0A-F1 (hex) Clarity Design, Inc. +000AF1 (base 16) Clarity Design, Inc. + 13029 Danielson Street + Poway CA 92064-8810 + US + +00-0A-F3 (hex) Cisco Systems, Inc +000AF3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0A-8D (hex) EUROTHERM LIMITED +000A8D (base 16) EUROTHERM LIMITED + FARADAY CLOSE + WORTHING WEST SUSSEX BN13 3PL + GB + +00-0A-9F (hex) Pannaway Technologies, Inc. +000A9F (base 16) Pannaway Technologies, Inc. + 215 Commerce Way + Portsmouth NH 03801 + US + +00-0A-8F (hex) Aska International Inc. +000A8F (base 16) Aska International Inc. + 306 Riverseven + Kochi 780-8088 + JP + +00-0A-A0 (hex) Cedar Point Communications +000AA0 (base 16) Cedar Point Communications + 16 Route 111, Bldg 3 + Derry NH 03038 + US + +00-0A-8E (hex) Invacom Ltd +000A8E (base 16) Invacom Ltd + Business and Technology Centre + Stevenage Hertfordshire SG1 2DX + GB + +00-0A-C1 (hex) Futuretel +000AC1 (base 16) Futuretel + 21580 Stevens Creek Blvd, Suite 208 + Cupertino CA 95014 + US + +00-0A-BE (hex) OPNET Technologies CO., LTD. +000ABE (base 16) OPNET Technologies CO., LTD. + 3F, NO.5, Industry E. Rd. IX, Science-Ba + Hsinchu 300 + TW + +00-0A-C3 (hex) eM Technics Co., Ltd. +000AC3 (base 16) eM Technics Co., Ltd. + 7F., IT Venture Tower., 78, + Seoul 138-803 + KR + +00-0A-C4 (hex) Daewoo Teletech Co., Ltd +000AC4 (base 16) Daewoo Teletech Co., Ltd + 265-3, Seohyeon, Bundang + Seongnam Gyeonggi + KR + +00-0A-C0 (hex) Fuyoh Video Industry CO., LTD. +000AC0 (base 16) Fuyoh Video Industry CO., LTD. + 7-25 Higashi Kibogaoka + Yokohama-shi Kanagawa-ken 246-0008 + JP + +00-0A-AE (hex) Rosemount Process Analytical +000AAE (base 16) Rosemount Process Analytical + 6573A Cochran Rd. + Solon Ohio 44139-3922 + US + +00-0A-B3 (hex) Fa. GIRA +000AB3 (base 16) Fa. GIRA + Dahlienstraße + Radevormwald Nordrhein-Westfalen 42477 + DE + +00-0A-BA (hex) Arcon Technology Limited +000ABA (base 16) Arcon Technology Limited + Rm. 3711-12, 37/F., Cable TV Tower , + Hong Kong + CN + +00-0A-B6 (hex) COMPUNETIX, INC +000AB6 (base 16) COMPUNETIX, INC + 2420 MOSSIDE BLVD. + MONROEVILLE PA 15146 + US + +00-0A-AF (hex) Pipal Systems +000AAF (base 16) Pipal Systems + 2903 Bunker Hill Lane + Santa Clara CA 95054 + US + +00-0A-76 (hex) Beida Jade Bird Huaguang Technology Co.,Ltd +000A76 (base 16) Beida Jade Bird Huaguang Technology Co.,Ltd + No.207 Chengfu Road, Haidian District + Beijing 100871 + CN + +00-0A-B2 (hex) Fresnel Wireless Systems +000AB2 (base 16) Fresnel Wireless Systems + 1333 Gateway Drive + Melbourne FL 32901 + US + +00-0A-AA (hex) AltiGen Communications Inc. +000AAA (base 16) AltiGen Communications Inc. + 47427 Fremont Blvd. + Fremont CA 94538 + US + +00-0A-99 (hex) Calamp Wireless Networks Inc +000A99 (base 16) Calamp Wireless Networks Inc + 101-5540 Ferrier Street + Town of Mount-Royal Quebec H4P 1M2 + CA + +00-0A-93 (hex) W2 Networks, Inc. +000A93 (base 16) W2 Networks, Inc. + 5808 NW Lac Leman Drive + Issaquah Washington 98027 + US + +00-0A-89 (hex) Creval Systems, Inc. +000A89 (base 16) Creval Systems, Inc. + 2F,24-4,Sanwolgok-Dong,Sungbuk-Ku,Seoul, + Seoul 136-120 + KR + +00-0A-80 (hex) Telkonet Inc. +000A80 (base 16) Telkonet Inc. + 20374 Seneca Meadows Pkwy + Germantown MD 21401 + US + +00-0A-79 (hex) corega K.K +000A79 (base 16) corega K.K + 1-19-20, Shinyokohama + Yokohama-city Kanagawa-ken 222-0033 + JP + +00-0A-5C (hex) Carel s.p.a. +000A5C (base 16) Carel s.p.a. + Via dell' Industria, 11 + Brugine Padova 35020 + IT + +00-0A-5A (hex) GreenNET Technologies Co.,Ltd. +000A5A (base 16) GreenNET Technologies Co.,Ltd. + No.10, Qiongyu Road,Sciences-based Indus + Shenzhen Guangdong 518057 + CN + +00-0A-56 (hex) HITACHI Maxell Ltd. +000A56 (base 16) HITACHI Maxell Ltd. + 6-20-1 Kinunodai + Yawara-mura, Tsukuba-gun IBARAKI 300-2496 + JP + +00-0A-51 (hex) GyroSignal Technology Co., Ltd. +000A51 (base 16) GyroSignal Technology Co., Ltd. + 5F,No. 77,Lide St. + Zhonghe City Taipei County 23556 + TW + +00-0A-2C (hex) Active Tchnology Corporation +000A2C (base 16) Active Tchnology Corporation + 16-23, Shibaura 2-Chome, + Tokyo Tokyo 108-0023 + JP + +00-0A-2A (hex) QSI Systems Inc. +000A2A (base 16) QSI Systems Inc. + 7 Raymond Avenue + Salem NH 03079 + US + +00-0A-23 (hex) Parama Networks Inc +000A23 (base 16) Parama Networks Inc + 1955 The Alameda + San Jose CA 95126 + US + +00-0A-1F (hex) ART WARE Telecommunication Co., Ltd. +000A1F (base 16) ART WARE Telecommunication Co., Ltd. + 806 Ace Techno Tower #1, 197-17 + Seoul 152-050 + KR + +00-0A-0A (hex) SUNIX Co., Ltd. +000A0A (base 16) SUNIX Co., Ltd. + 3Fl., No. 76, Baugau Rd., + Shindian Taipei 231 + TW + +00-0A-05 (hex) Widax Corp. +000A05 (base 16) Widax Corp. + 269 Stevens Street + Hyannis MA 02668 + US + +00-0A-34 (hex) Identicard Systems Incorporated +000A34 (base 16) Identicard Systems Incorporated + 40 Citation Lane + Lancaster Pennsylvania 17606 + US + +00-0A-30 (hex) Visteon Corporation +000A30 (base 16) Visteon Corporation + One Village Center Drive + Van Buren Twp MI 48111 + US + +00-0A-2F (hex) Artnix Inc. +000A2F (base 16) Artnix Inc. + Chungjin B/D, 475-22 Bangbae, Seocho + Seoul 137-819 + KR + +00-0A-15 (hex) Silicon Data, Inc +000A15 (base 16) Silicon Data, Inc + 4699 Old Ironsides Dr., #150 + Santa Clara CA 95054 + US + +00-0A-1B (hex) Stream Labs +000A1B (base 16) Stream Labs + Leninskie gori 1, bild 77 + Moskow 119992 + RU + +00-0A-1A (hex) Imerge Ltd +000A1A (base 16) Imerge Ltd + Unit 6, Bar Hill Business Park + Bar Hill Cambridge CB3 8SL + GB + +00-0A-60 (hex) Autostar Technology Pte Ltd +000A60 (base 16) Autostar Technology Pte Ltd + Unit 04-10 TECHplace II + Singapore Singapore 569876 + SG + +00-0A-5D (hex) FingerTec Worldwide Sdn Bhd +000A5D (base 16) FingerTec Worldwide Sdn Bhd + No 6, 8 & 10 + Bandar Kinrara 47100 PUchong Selangor + MY + +00-0A-39 (hex) LoPA Information Technology +000A39 (base 16) LoPA Information Technology + 710-9, Dae Lim 3-Dong + Young Deung po-gu Seoul, Korea 150-814 + KR + +00-0A-37 (hex) Procera Networks, Inc. +000A37 (base 16) Procera Networks, Inc. + 1299 Orleans Drive + Sunnyvale CA 94089 + US + +00-0A-53 (hex) Intronics, Incorporated +000A53 (base 16) Intronics, Incorporated + 2020 Lafayette Blvd. + Fredericksburg Virginia 22401 + US + +00-0A-4A (hex) Targa Systems Ltd. +000A4A (base 16) Targa Systems Ltd. + 1905 Grandtech Centre, + Shatin N.T. + HK + +00-09-D6 (hex) KNC One GmbH +0009D6 (base 16) KNC One GmbH + Hohe Welle 10 B + Evessen 38173 + DE + +00-09-C7 (hex) Movistec +0009C7 (base 16) Movistec + 110-5 Maryoung -ri Seosu-myun + Kunsan Chonbuk 573-940 + KR + +00-09-C9 (hex) BlueWINC Co., Ltd. +0009C9 (base 16) BlueWINC Co., Ltd. + 401 Korea Design Center + Seongnam City Kyonggi杁o 463-828 + KR + +00-09-D4 (hex) Transtech Networks +0009D4 (base 16) Transtech Networks + 100 Wood Avenue + Iselin NJ 08830 + US + +00-09-CB (hex) HBrain +0009CB (base 16) HBrain + #705 Kwanglim Bldg 179 KumiDong + Seongnam GyeonggiDo 463-810 + KR + +00-09-F1 (hex) Yamaki Electric Corporation +0009F1 (base 16) Yamaki Electric Corporation + 3-7-22 Shimomeguro + Meguro-ku Tokyo 153-0064 + JP + +00-09-F4 (hex) Alcon Laboratories, Inc. +0009F4 (base 16) Alcon Laboratories, Inc. + 6201 South Freeway + Fort Worth Tx 76134 + US + +00-09-F5 (hex) Emerson Network Power Co.,Ltd +0009F5 (base 16) Emerson Network Power Co.,Ltd + 1/F,3/F Electric Building Huawei Base,Ba + ShenZhen GuangDong 518029 + CN + +00-09-EA (hex) YEM Inc. +0009EA (base 16) YEM Inc. + 1-3-33 + Atsugi-shi Kanagawa 243-0021 + JP + +00-09-C5 (hex) KINGENE Technology Corporation +0009C5 (base 16) KINGENE Technology Corporation + 7F, No. 144, Minchuan E. Rd. Sec. 3 + Taipei 105 + TW + +00-09-CD (hex) HUDSON SOFT CO.,LTD. +0009CD (base 16) HUDSON SOFT CO.,LTD. + C62,Geijutsu-no-mori + Sapporo Hokkaido 005-0864 + JP + +00-09-C0 (hex) 6WIND +0009C0 (base 16) 6WIND + 1, place Charles de Gaulle + Montigny-le-Bretonneux 78180 + FR + +00-09-BF (hex) Nintendo Co., Ltd. +0009BF (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-09-E3 (hex) Angel Iglesias S.A. +0009E3 (base 16) Angel Iglesias S.A. + Polígono 27 Martutene + San Sebastián Guipúzcoa 20014 + ES + +00-09-B4 (hex) KISAN TELECOM CO., LTD. +0009B4 (base 16) KISAN TELECOM CO., LTD. + 9F, Teawon Bldg., 65 Bangyi-Dong + Songpa-Gu Seoul 138-828 + KR + +00-09-AE (hex) OKANO ELECTRIC CO.,LTD +0009AE (base 16) OKANO ELECTRIC CO.,LTD + 2-8-18 KANAYAMA-CHO + HIGASHIKURUME TOKYO 203-0003 + JP + +00-09-BA (hex) MAKU Informationstechik GmbH +0009BA (base 16) MAKU Informationstechik GmbH + Gewerbehofstraße 7 + Essen NRW 45145 + DE + +00-0A-04 (hex) 3Com Ltd +000A04 (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +00-09-71 (hex) Time Management, Inc. +000971 (base 16) Time Management, Inc. + 11 Lake Gatlin Road + Orlando Florida 32806 + US + +00-09-74 (hex) Innopia Technologies, Inc. +000974 (base 16) Innopia Technologies, Inc. + 5F., Institute of Technology + Seoul 133-791 + KR + +00-09-8B (hex) Entropic Communications, Inc. +00098B (base 16) Entropic Communications, Inc. + 9276 Scranton Rd #200 + San Diego CA 92121 + US + +00-09-7E (hex) IMI TECHNOLOGY CO., LTD +00097E (base 16) IMI TECHNOLOGY CO., LTD + 2nd floor, Eun Seok Building, 729-1 + Gangnam-gu Seoul 135-080 + KR + +00-09-6A (hex) Cloverleaf Communications Inc. +00096A (base 16) Cloverleaf Communications Inc. + 2 Willow St. + Southborough MA 01745-1027 + US + +00-09-5A (hex) RACEWOOD TECHNOLOGY +00095A (base 16) RACEWOOD TECHNOLOGY + 5F-2,NO.6,CHUNG-HSING RD.,SEC.1,WU-GU + TAIPEI 248 + TW + +00-09-4E (hex) BARTECH SYSTEMS INTERNATIONAL, INC +00094E (base 16) BARTECH SYSTEMS INTERNATIONAL, INC + 251 Najoles Rd Suite A + Millersville Maryland 21108 + US + +00-09-47 (hex) Aztek, Inc. +000947 (base 16) Aztek, Inc. + 23 Spectrum Pointe #209 + Lake Forest California 92630 + US + +00-09-51 (hex) Apogee Imaging Systems +000951 (base 16) Apogee Imaging Systems + 151 Sunrise Avenue + Roseville CA 95661 + US + +00-09-3D (hex) Newisys,Inc. +00093D (base 16) Newisys,Inc. + 6200 Bridgepoint Parkway + Austin TX 78730 + US + +00-09-67 (hex) Tachyon, Inc +000967 (base 16) Tachyon, Inc + 9339 Carroll Park Drive + San Diego CA 92121 + US + +00-09-96 (hex) RDI +000996 (base 16) RDI + 20406 Earl St. + Torrance CA 90503 + US + +00-09-0C (hex) Mayekawa Mfg. Co. Ltd. +00090C (base 16) Mayekawa Mfg. Co. Ltd. + 16825 IH 35 North + Selma Texas 78154 + US + +00-09-0D (hex) LEADER ELECTRONICS CORP. +00090D (base 16) LEADER ELECTRONICS CORP. + 2-6-33, TSUNASHIMA-HIGASHI + YOKOHAMA KANAGAWA 223-8505 + JP + +00-08-FE (hex) UNIK C&C Co.,Ltd. +0008FE (base 16) UNIK C&C Co.,Ltd. + 706-13 UNIK BLDG 17F + SEOUL 135-080 + KR + +00-08-FF (hex) Trilogy Communications Ltd +0008FF (base 16) Trilogy Communications Ltd + 26 Focus Way + Andover Hampshire SP10 5NY + GB + +00-09-04 (hex) MONDIAL electronic +000904 (base 16) MONDIAL electronic + Eggelsberg 73 + Eggelsberg Oberoesterreich 5142 + AT + +00-09-1F (hex) A&D Co., Ltd. +00091F (base 16) A&D Co., Ltd. + 1-243 Asahi + Kitamoto-shi Saitama 364-8585 + JP + +00-09-24 (hex) Telebau GmbH +000924 (base 16) Telebau GmbH + Am Kraehenberg 1 + Waldeck-Sachsenhausen Germany 34513 + DE + +00-09-21 (hex) Planmeca Oy +000921 (base 16) Planmeca Oy + Asentajankatu 6 + HELSINKI 00810 HELSIN + FI + +00-09-19 (hex) MDS Gateways +000919 (base 16) MDS Gateways + Clonshaugh Industrial Estate + Dublin 17 + IE + +00-09-18 (hex) SAMSUNG TECHWIN CO.,LTD +000918 (base 16) SAMSUNG TECHWIN CO.,LTD + 42 + CHANGWON KYONGNAM 641-716 + KR + +00-09-2F (hex) Akom Technology Corporation +00092F (base 16) Akom Technology Corporation + 5F, No. 323, Yang-Guang St. + Taipei 114 + TW + +00-08-EF (hex) DIBAL,S.A. +0008EF (base 16) DIBAL,S.A. + Astintze Kalea 24 + Derio Vizcaya 48160 + ES + +00-08-F0 (hex) Next Generation Systems, Inc. +0008F0 (base 16) Next Generation Systems, Inc. + PO BOX 31205 + Dayton OH 45437-0205 + US + +00-08-E9 (hex) NextGig +0008E9 (base 16) NextGig + 9820-B Towne Centre Drive + San Diego CA 92121 + US + +00-09-10 (hex) Simple Access Inc. +000910 (base 16) Simple Access Inc. + 600 McCaffrey Street + St-Laurent Quebec H4T1N1 + CA + +00-09-14 (hex) COMPUTROLS INC. +000914 (base 16) COMPUTROLS INC. + 221 Bark Drive + Harvey LA 70058 + US + +00-08-E7 (hex) SHI ControlSystems,Ltd. +0008E7 (base 16) SHI ControlSystems,Ltd. + 19,Natusima + Yokosuka Kanagawa 237-8555 + JP + +00-08-D7 (hex) HOW CORPORATION +0008D7 (base 16) HOW CORPORATION + 1-11-17 Chiyoda + Sagamihara Kanagawa 229-0037 + JP + +00-08-FC (hex) Gigaphoton Inc. +0008FC (base 16) Gigaphoton Inc. + YOKOKURA SHINDEN400 + OYAMA TOTIGI 323-8558 + JP + +00-09-38 (hex) Allot Communications +000938 (base 16) Allot Communications + Hanagar 22 st' + Hod-Hasharon 45800 + IL + +00-08-BF (hex) Aptus Elektronik AB +0008BF (base 16) Aptus Elektronik AB + FO Petersons G 6 + + SE + +00-08-B8 (hex) E.F. Johnson +0008B8 (base 16) E.F. Johnson + 299 Johnson Ave. + Waseca MN 56093 + US + +00-08-BB (hex) NetExcell +0008BB (base 16) NetExcell + 15375 Barranca Pkwy, #E-106 + Irvine CA 92679 + US + +00-08-BE (hex) XENPAK MSA Group +0008BE (base 16) XENPAK MSA Group + Care of: Agilent Technologies + Ipswich Suffolk Ip1 5PB + GB + +00-08-C1 (hex) Avistar Communications Corporation +0008C1 (base 16) Avistar Communications Corporation + 15851 Dallas Pkwy. + Addison TX 75001 + US + +00-08-C6 (hex) Philips Consumer Communications +0008C6 (base 16) Philips Consumer Communications + Route d'Angers + Cedex 9 + FR + +00-08-65 (hex) JASCOM CO., LTD +000865 (base 16) JASCOM CO., LTD + JUAN INDUSTRIAL COMPLEX 330, 17-1, + JUAN-DONG NAM-GU INCHEON 402-200 + KR + +00-08-64 (hex) Fasy S.p.A. +000864 (base 16) Fasy S.p.A. + Via Tognasca 7 + Gallarate Varese 21013 + US + +00-08-60 (hex) LodgeNet Entertainment Corp. +000860 (base 16) LodgeNet Entertainment Corp. + 3900 W. Innovation Street + Sioux Falls SD 57107 + US + +00-08-97 (hex) Quake Technologies +000897 (base 16) Quake Technologies + 2880 Zanker Road + San Jose CA 95134 + US + +00-08-90 (hex) AVILINKS SA +000890 (base 16) AVILINKS SA + Etic Center - CS 77 729 + Cesson Sevigne Cedex 35577 + FR + +00-08-8D (hex) Sigma-Links Inc. +00088D (base 16) Sigma-Links Inc. + 550-1 Higashiasakawa-cho, + Tokyo 193-8550 + JP + +00-08-A8 (hex) Systec Co., Ltd. +0008A8 (base 16) Systec Co., Ltd. + 19 Nochidori, Nawa + Tokai Aichi 476-0002 + JP + +00-08-A4 (hex) Cisco Systems, Inc +0008A4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +08-00-6B (hex) ACCEL TECHNOLOGIES INC. +08006B (base 16) ACCEL TECHNOLOGIES INC. + 7358 TRADE STREET + SAN DIEGO CA 92121 + US + +00-08-84 (hex) Index Braille AB +000884 (base 16) Index Braille AB + Box 155 + + SE + +00-07-E8 (hex) EdgeWave +0007E8 (base 16) EdgeWave + 15333 Avenue of Science + San Diego CA 92128 + US + +00-07-EB (hex) Cisco Systems, Inc +0007EB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-07-EC (hex) Cisco Systems, Inc +0007EC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-08-51 (hex) Canadian Bank Note Company, Ltd. +000851 (base 16) Canadian Bank Note Company, Ltd. + 18 Auriga Dr. + K2E 7T9 + CA + +00-08-59 (hex) ShenZhen Unitone Electronics Co., Ltd. +000859 (base 16) ShenZhen Unitone Electronics Co., Ltd. + 2 Southern Floor 702 Building + + CN + +00-08-4E (hex) DivergeNet, Inc. +00084E (base 16) DivergeNet, Inc. + 2142 Bering Dr. + San Jose CA 95131 + US + +00-08-19 (hex) Banksys +000819 (base 16) Banksys + Haachtsesteenweg 1442 + + BE + +00-08-1A (hex) Sanrad Intelligence Storage Communications (2000) Ltd. +00081A (base 16) Sanrad Intelligence Storage Communications (2000) Ltd. + 32 Habarzel St., Entrace B + + IL + +00-08-10 (hex) Key Technology, Inc. +000810 (base 16) Key Technology, Inc. + 150 Avery St. + Walla Walla WA 99362 + US + +00-08-07 (hex) Access Devices Limited +000807 (base 16) Access Devices Limited + Sixth Floor, 58 Oxbridge Road + + GB + +00-07-FC (hex) Adept Systems Inc. +0007FC (base 16) Adept Systems Inc. + 2100 Boca Rio Rd. + Boca Raton FL 33433 + US + +00-08-25 (hex) Acme Packet +000825 (base 16) Acme Packet + 71 Third Avenue + Woburn MA 01803 + US + +00-07-DC (hex) Atek Co, Ltd. +0007DC (base 16) Atek Co, Ltd. + B dong #205 hanyang venture park + Seoul + KR + +00-08-1F (hex) Pou Yuen Tech Corp. Ltd. +00081F (base 16) Pou Yuen Tech Corp. Ltd. + 16F, No. 107, Sect. 3, Taichung Keng Rd. + + TW + +00-07-C6 (hex) VDS Vosskuhler GmbH +0007C6 (base 16) VDS Vosskuhler GmbH + Weibe Breite 7 + + DE + +00-07-F5 (hex) Bridgeco Co AG +0007F5 (base 16) Bridgeco Co AG + Ringstr. 14 + + CH + +00-07-94 (hex) Simple Devices, Inc. +000794 (base 16) Simple Devices, Inc. + 111 Anza Blvd., Suite 120 + Burlingame CA 94010 + US + +00-07-97 (hex) Netpower Co., Ltd. +000797 (base 16) Netpower Co., Ltd. + Baekam Bldg., 6F + Seoul 138-162 + KR + +00-07-8C (hex) Elektronikspecialisten i Borlange AB +00078C (base 16) Elektronikspecialisten i Borlange AB + Box 50 + SE 780 + SE + +00-07-CC (hex) Kaba Benzing GmbH +0007CC (base 16) Kaba Benzing GmbH + Albertistrabe 3 + + DE + +00-07-C0 (hex) NetZerver Inc. +0007C0 (base 16) NetZerver Inc. + 26 West Lone Cactus Drive + Phoenix AZ 85027 + US + +00-04-7E (hex) Siqura B.V. +00047E (base 16) Siqura B.V. + Zuidelijk Halfrond 4 + + NL + +00-07-BC (hex) Identix Inc. +0007BC (base 16) Identix Inc. + 6591 Sierra Lane + Dublin CA 94568 + US + +00-07-A9 (hex) Novasonics +0007A9 (base 16) Novasonics + 1390 Willow Road + Menlo Park CA 94025 + US + +00-07-A1 (hex) VIASYS Healthcare GmbH +0007A1 (base 16) VIASYS Healthcare GmbH + Leibnizstraße 7 + Hoechberg Bavaria 97204 + DE + +00-07-9E (hex) Ilinx Co., Ltd. +00079E (base 16) Ilinx Co., Ltd. + 4th Floor Korea Telecom, Yangjae Branch + Seoul + KR + +00-07-A0 (hex) e-Watch Inc. +0007A0 (base 16) e-Watch Inc. + 7800 IH 10 West + San Antonio TX 78229 + US + +00-07-88 (hex) Clipcomm, Inc. +000788 (base 16) Clipcomm, Inc. + 5th Fl, Ssangyang Bldg. + Seoul 151-827 + KR + +00-07-81 (hex) Itron Inc. +000781 (base 16) Itron Inc. + 2818 N. Sullivan Road + Spokane WA 99216 + US + +00-07-6B (hex) Stralfors AB +00076B (base 16) Stralfors AB + Langgatan 21 + + SE + +00-07-68 (hex) Danfoss A/S +000768 (base 16) Danfoss A/S + E16-N12, DK-6430 Nordborg + + + +00-07-5F (hex) VCS Video Communication Systems AG +00075F (base 16) VCS Video Communication Systems AG + Forchheimer Str. 4 + + DE + +00-07-B8 (hex) Corvalent Corporation +0007B8 (base 16) Corvalent Corporation + 1101 Arrow Point Dr #501 + Cedar Park TX 78613 + US + +00-07-7B (hex) Millimetrix Broadband Networks +00077B (base 16) Millimetrix Broadband Networks + Kibutz Givat Hashelosha 48800 + + IL + +00-07-69 (hex) Italiana Macchi SpA +000769 (base 16) Italiana Macchi SpA + Via Matteotti 1 + + IT + +00-07-1A (hex) Finedigital Inc. +00071A (base 16) Finedigital Inc. + 4th Fl. Bomi Bldg., 661 Deungchon 3 Dong + Seoul 157-033 + KR + +00-07-1E (hex) Tri-M Engineering / Nupak Dev. Corp. +00071E (base 16) Tri-M Engineering / Nupak Dev. Corp. + 6-1301 Ketch Court + V3K 6X7 + CA + +00-07-17 (hex) Wieland Electric GmbH +000717 (base 16) Wieland Electric GmbH + Brennerstraße 10-14 + + DE + +00-07-11 (hex) Acterna +000711 (base 16) Acterna + 6620 Network Way + Indianapolis IN 46278 + US + +00-07-02 (hex) Varex Imaging +000702 (base 16) Varex Imaging + 1678 South Pioneer Road + Salt Lake City UT 84104 + US + +00-07-05 (hex) Endress & Hauser GmbH & Co +000705 (base 16) Endress & Hauser GmbH & Co + Hauptstrabe 1 - Postfach 1261 + + DE + +00-06-FF (hex) Sheba Systems Co., Ltd. +0006FF (base 16) Sheba Systems Co., Ltd. + 5th Fl. Hyundai Jad B/D + Seoul 134-030 + KR + +00-07-41 (hex) Sierra Automated Systems +000741 (base 16) Sierra Automated Systems + 2821 Burton Ave. + Burbank CA 91504 + US + +00-07-45 (hex) Radlan Computer Communications Ltd. +000745 (base 16) Radlan Computer Communications Ltd. + Atidim Technology Park + Tel Aviv 61131 + IL + +00-07-3E (hex) China Great-Wall Computer Shenzhen Co., Ltd. +00073E (base 16) China Great-Wall Computer Shenzhen Co., Ltd. + Research & Development Center, Kefa Road + Shenzhen 518057 + CN + +00-07-33 (hex) DANCONTROL Engineering +000733 (base 16) DANCONTROL Engineering + Italiensvej 1-5 + + DK + +00-07-2B (hex) Jung Myung Telecom Co., Ltd. +00072B (base 16) Jung Myung Telecom Co., Ltd. + 5Fl Silla Technovil., 39-3 Dang-Dong + + KR + +00-07-18 (hex) iCanTek Co., Ltd. +000718 (base 16) iCanTek Co., Ltd. + 2nd Fl. DK Plaza II, 376-5, + Sungman-si, Kyonggi-do 463-805 + KR + +00-07-16 (hex) J & S Marine Ltd. +000716 (base 16) J & S Marine Ltd. + Pottington Business Park + Devon EX31 1LY + GB + +00-07-5C (hex) Eastman Kodak Company +00075C (base 16) Eastman Kodak Company + 343 State Street + Rochester NY 146501245 + US + +00-07-56 (hex) Juyoung Telecom +000756 (base 16) Juyoung Telecom + #201, Dunsan Building + Taejon 302-846 + KR + +00-07-5A (hex) Air Products and Chemicals, Inc. +00075A (base 16) Air Products and Chemicals, Inc. + 7201 Hamilton Blvd. + Allentown PA 18195-1501 + US + +00-07-48 (hex) The Imaging Source Europe +000748 (base 16) The Imaging Source Europe + Sommerstraße 34-36 + + DE + +00-07-46 (hex) TURCK, Inc. +000746 (base 16) TURCK, Inc. + 3000 Campus Drive + Plymouth MN 55441 + US + +00-07-3B (hex) Tenovis GmbH & Co KG +00073B (base 16) Tenovis GmbH & Co KG + Kleyerstraße 94 + + DE + +00-07-31 (hex) Ophir-Spiricon LLC +000731 (base 16) Ophir-Spiricon LLC + 3050 N 300 W + North Logan UT 84341 + US + +00-07-0A (hex) Unicom Automation Co., Ltd. +00070A (base 16) Unicom Automation Co., Ltd. + Silk Bldg 3-31-11 + Tokyo 164-0012 + JP + +00-07-09 (hex) Westerstrand Urfabrik AB +000709 (base 16) Westerstrand Urfabrik AB + Box 133 + + SE + +00-06-EB (hex) Global Data +0006EB (base 16) Global Data + 2250 Obispo Ave #105 + Signal Hill CA 90806 + US + +00-06-D3 (hex) Alpha Telecom, Inc. U.S.A. +0006D3 (base 16) Alpha Telecom, Inc. U.S.A. + 1394 Borregor Ave. + Sunnyvale CA 94089 + US + +00-06-47 (hex) Etrali S.A. +000647 (base 16) Etrali S.A. + 221, Rue La Fontaine + + FR + +00-06-A4 (hex) INNOWELL Corp. +0006A4 (base 16) INNOWELL Corp. + #717 ChongGu Bluevill + 463-825 + KR + +00-06-D6 (hex) Cisco Systems, Inc +0006D6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-06-CB (hex) Jotron Electronics A/S +0006CB (base 16) Jotron Electronics A/S + Pob 54 + + NO + +00-06-CD (hex) Leaf Imaging Ltd. +0006CD (base 16) Leaf Imaging Ltd. + 7th Hatnufa st + Petach-Tikva 49002 + IL + +00-06-95 (hex) Ensure Technologies, Inc. +000695 (base 16) Ensure Technologies, Inc. + 3526 West Liberty + Ann Arbor MI 48103 + US + +00-06-91 (hex) PT Inovacao +000691 (base 16) PT Inovacao + Rua Eng. Jose F. Pinto Basto + + PT + +00-06-92 (hex) Intruvert Networks, Inc. +000692 (base 16) Intruvert Networks, Inc. + Suite 102 + San Jose CA 95131 + US + +00-06-8B (hex) AirRunner Technologies, Inc. +00068B (base 16) AirRunner Technologies, Inc. + 2401 Lupine Trail + South Lake Tahoe CA 96150 + US + +00-06-88 (hex) Telways Communication Co., Ltd. +000688 (base 16) Telways Communication Co., Ltd. + 3F, No. 53, Lane 258 + Taipei 114 + TW + +00-06-AB (hex) W-Link Systems, Inc. +0006AB (base 16) W-Link Systems, Inc. + No. 20, Park Ave. II, + Hsinchu 300 + TW + +00-06-AC (hex) Intersoft Co. +0006AC (base 16) Intersoft Co. + #1803 sun-kyoung Officetel + Seoul + KR + +00-06-94 (hex) Mobillian Corporation +000694 (base 16) Mobillian Corporation + 11031 Via Frontera + San Diego CA 92127 + US + +00-06-C7 (hex) RFNET Technologies Pte Ltd (S) +0006C7 (base 16) RFNET Technologies Pte Ltd (S) + Unit 233 Innovation Centre Blk 2 + 637722 + SG + +00-06-B9 (hex) A5TEK Corp. +0006B9 (base 16) A5TEK Corp. + 1233 Alderwood Ave. + Sunnyvale CA 94089 + US + +00-06-B3 (hex) Diagraph Corporation +0006B3 (base 16) Diagraph Corporation + 3401 Rider Trail South + Earth City MO 63045-1110 + US + +00-06-E3 (hex) Quantitative Imaging Corporation +0006E3 (base 16) Quantitative Imaging Corporation + 8081 Lougheed Highway + + CA + +00-06-E4 (hex) Citel Technologies Ltd. +0006E4 (base 16) Citel Technologies Ltd. + Wheatcroft Business Park + Nottigham NG12 4DG + GB + +00-06-A1 (hex) Celsian Technologies, Inc. +0006A1 (base 16) Celsian Technologies, Inc. + 3002 Dow Ave., Unit 138 + Tustin CA 92780 + US + +00-06-D9 (hex) IPM-Net S.p.A. +0006D9 (base 16) IPM-Net S.p.A. + Via Remo De Feo + + IT + +00-06-63 (hex) Human Technology Co., Ltd. +000663 (base 16) Human Technology Co., Ltd. + 3rd Fl, Hyungok Bldg., + Kangnam-ku Seoul + KR + +00-06-65 (hex) Sunny Giken, Inc. +000665 (base 16) Sunny Giken, Inc. + 3-1-9 Nishidai Itami-shi + Hyogo-pref. 664-0858 + JP + +00-06-69 (hex) Datasound Laboratories Ltd +000669 (base 16) Datasound Laboratories Ltd + 5 Business Park West, Avenue One + ENGLAND + GB + +00-06-6E (hex) Delta Electronics, Inc. +00066E (base 16) Delta Electronics, Inc. + 11F, 266 Wen-Hwa 2nd Road, + + TW + +00-06-1B (hex) Notebook Development Lab. Lenovo Japan Ltd. +00061B (base 16) Notebook Development Lab. Lenovo Japan Ltd. + 1623-14 Shimotsuruma + 242-8502 + JP + +00-06-0F (hex) Narad Networks Inc +00060F (base 16) Narad Networks Inc + 515 Groton Road + Westford MA 01886 + US + +00-06-10 (hex) Abeona Networks Inc +000610 (base 16) Abeona Networks Inc + 46117 Landing Parkway + Fremont CA 94539 + US + +00-06-11 (hex) Zeus Wireless, Inc. +000611 (base 16) Zeus Wireless, Inc. + 8325 Guilford Road + Columbia MD 21046 + US + +00-05-EC (hex) Mosaic Systems Inc. +0005EC (base 16) Mosaic Systems Inc. + 7 Campbell Park + Somerville MA 02144 + US + +00-06-62 (hex) MBM Technology Ltd. +000662 (base 16) MBM Technology Ltd. + Victoria Rd. + + GB + +00-06-5A (hex) Strix Systems +00065A (base 16) Strix Systems + 310 N. Westlake Blvd. + Westlake Village CA 91362 + US + +00-06-52 (hex) Cisco Systems, Inc +000652 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-06-56 (hex) Tactel AB +000656 (base 16) Tactel AB + Norra Vallgatan 64 + + SE + +00-06-41 (hex) ITCN +000641 (base 16) ITCN + 8571 Gander Creek Drive + Miamisburg OH 45342 + US + +00-06-48 (hex) Seedsware, Inc. +000648 (base 16) Seedsware, Inc. + 3-7-16 Technostage, + Izumi, Osaka 594-1144 + JP + +00-06-4C (hex) Invicta Networks, Inc. +00064C (base 16) Invicta Networks, Inc. + 13873 Park Center Road + Herndon VA 20171 + US + +00-06-74 (hex) Spectrum Control, Inc. +000674 (base 16) Spectrum Control, Inc. + 8061 Avonia Road + Fairview PA 16415 + US + +00-06-38 (hex) Sungjin C&C Co., Ltd. +000638 (base 16) Sungjin C&C Co., Ltd. + 1543-6, Seocho-dong, Seocho-gu, + Seoul 137-073 + KR + +00-06-35 (hex) PacketAir Networks, Inc. +000635 (base 16) PacketAir Networks, Inc. + 11545 W. Bernardo Ct. + San Diego CA 92127 + US + +00-06-1A (hex) Zetari Inc. +00061A (base 16) Zetari Inc. + 411 Waverly Oaks Rd. + Waltham MA 02452-8401 + US + +00-06-1F (hex) Vision Components GmbH +00061F (base 16) Vision Components GmbH + Ottostraße 2 + + DE + +00-06-87 (hex) Omnitron Systems Technology, Inc. +000687 (base 16) Omnitron Systems Technology, Inc. + 140 Technology + Irvine CA 92618 + US + +00-06-02 (hex) Cirkitech Electronics Co. +000602 (base 16) Cirkitech Electronics Co. + B1-2, No. 361, Fu-Xing First Road + Tao-Yuan + TW + +00-05-C0 (hex) Digital Network Alacarte Co., Ltd. +0005C0 (base 16) Digital Network Alacarte Co., Ltd. + A104, Seoul Business Incubator + Seoul 157-030, + KR + +00-05-B8 (hex) Electronic Design Associates, Inc. +0005B8 (base 16) Electronic Design Associates, Inc. + 331 Arcado Rd. NW + Lilburn GA 30047-2841 + US + +00-05-BA (hex) Area Netwoeks, Inc. +0005BA (base 16) Area Netwoeks, Inc. + 1148 Euclid Ave., Suite 400 + Cleveland OH 4415 + US + +00-05-BF (hex) JustEzy Technology, Inc. +0005BF (base 16) JustEzy Technology, Inc. + 5F, No. 324, Sec. 1, Junghua Rd. + Hsinchu + TW + +00-05-D5 (hex) Speedcom Wireless +0005D5 (base 16) Speedcom Wireless + 7020 Professional Pkwy East + Sarasota FL 34240-8514 + US + +00-05-C5 (hex) Flaga HF +0005C5 (base 16) Flaga HF + Vesturhlid 7 + + IS + +00-05-CA (hex) Hitron Technology, Inc. +0005CA (base 16) Hitron Technology, Inc. + HSINCHU SBIP SUBSIDIARY + Hsin-chu + TW + +00-05-D2 (hex) DAP Technologies +0005D2 (base 16) DAP Technologies + 955 Fernand Dufour, + G1M 3B2 + CA + +00-05-B1 (hex) ASB Technology BV +0005B1 (base 16) ASB Technology BV + De Ronde 15A + + NL + +00-05-99 (hex) DRS Test and Energy Management or DRS-TEM +000599 (base 16) DRS Test and Energy Management or DRS-TEM + 110 Wynn Drive + Huntsville AL 35805 + US + +00-05-9A (hex) Cisco Systems, Inc +00059A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-AB (hex) Cyber Fone, Inc. +0005AB (base 16) Cyber Fone, Inc. + 989 Old Eagle School Road + Wayne PA 19087 + US + +00-05-92 (hex) Pultek Corp. +000592 (base 16) Pultek Corp. + 74-1, Yamashita-cho, + 231-0023 + JP + +00-05-8B (hex) IPmental, Inc. +00058B (base 16) IPmental, Inc. + 8F-9, No. 35, Hsin Tai Rd. + + TW + +00-05-AC (hex) Northern Digital, Inc. +0005AC (base 16) Northern Digital, Inc. + 103 Randall Drive + Waterloo Ontario N2V 1C5 + CA + +00-05-AD (hex) Topspin Communications, Inc. +0005AD (base 16) Topspin Communications, Inc. + 515 Ellis Street + Mountain View CA 94043 + US + +00-05-D1 (hex) Metavector Technologies +0005D1 (base 16) Metavector Technologies + Steenweg Op Gierle, 100 + + BE + +00-05-C9 (hex) LG Innotek Co., Ltd. +0005C9 (base 16) LG Innotek Co., Ltd. + LG Component R&D Center + Ansan-si Gyeonggi-do 426-791 + KR + +00-05-FB (hex) ShareGate, Inc. +0005FB (base 16) ShareGate, Inc. + 9805 Double R Blvd. + Reno NV 89511-5917 + US + +00-05-FE (hex) Traficon N.V. +0005FE (base 16) Traficon N.V. + Bissegemsestraat 45 + + BE + +00-05-F0 (hex) SATEC +0005F0 (base 16) SATEC + P.O. Box 45022 + 91450 + IL + +00-05-30 (hex) Andiamo Systems, Inc. +000530 (base 16) Andiamo Systems, Inc. + 375 E. Tasman Dr. + San Jose CA 95134 + US + +00-05-38 (hex) Merilus, Inc. +000538 (base 16) Merilus, Inc. + #307-46165 Yale Road + V2P 2P2 + CA + +00-05-2B (hex) HORIBA, Ltd. +00052B (base 16) HORIBA, Ltd. + 2 Miyanohigashi, Kisshoin, + 601-8510 + JP + +00-05-1D (hex) Airocon, Inc. +00051D (base 16) Airocon, Inc. + 116 Houghton Lane + Boxboro MA 01719 + US + +00-05-15 (hex) Nuark Co., Ltd. +000515 (base 16) Nuark Co., Ltd. + 12F, Anyang K center, 1591-9, Burim-dong + Gunggi-do 431-065 + KR + +00-05-16 (hex) SMART Modular Technologies +000516 (base 16) SMART Modular Technologies + 4305 Cushing Pkwy + Fremont CA 94538 + US + +00-05-77 (hex) SM Information & Communication +000577 (base 16) SM Information & Communication + 330-1 Yangjaedong + 137-130 + KR + +00-05-70 (hex) Baydel Ltd. +000570 (base 16) Baydel Ltd. + Baydel House + + GB + +00-05-6E (hex) National Enhance Technology, Inc. +00056E (base 16) National Enhance Technology, Inc. + 2F, No. 196-3, Tatung Rd., Sec. 3, + + TW + +00-05-6D (hex) Pacific Corporation +00056D (base 16) Pacific Corporation + 2-23-3 Ebisu-Minami Shibuya + + JP + +00-05-81 (hex) Snell +000581 (base 16) Snell + Southleigh Park House + Hampshire P09 2PE + GB + +00-05-7D (hex) Sun Communications, Inc. +00057D (base 16) Sun Communications, Inc. + Gloria Bldg 6th + Tokyo 162-082 + JP + +00-05-86 (hex) Lucent Technologies +000586 (base 16) Lucent Technologies + 1701 Harbor Bay Parkway + Alameda CA 94502 + US + +00-05-7B (hex) Chung Nam Electronic Co., Ltd. +00057B (base 16) Chung Nam Electronic Co., Ltd. + Unit 3, 1/F, Festigood Centre + Tsuen Fanling, + HK + +00-05-71 (hex) Seiwa Electronics Co. +000571 (base 16) Seiwa Electronics Co. + 757 Amabouki, Kukizaki-Machi + 300-1253 + JP + +00-05-49 (hex) Salira Optical Network Systems +000549 (base 16) Salira Optical Network Systems + 2694 Orchard Parkway + San Jose CA 95134 + US + +00-05-4C (hex) RF Innovations Pty Ltd +00054C (base 16) RF Innovations Pty Ltd + 22 Boulder Road + Malaga WA 6090 + AU + +00-05-43 (hex) IQ Wireless GmbH +000543 (base 16) IQ Wireless GmbH + Carl-Scheele-Str. 14 + + DE + +00-05-5C (hex) Kowa Company, Ltd. +00055C (base 16) Kowa Company, Ltd. + Chofugaoka 3-3-1, + 182-0021 + JP + +00-05-10 (hex) Infinite Shanghai Communication Terminals Ltd. +000510 (base 16) Infinite Shanghai Communication Terminals Ltd. + 777 Chungiao Road, Pudong + + CN + +00-04-FF (hex) Acronet Co., Ltd. +0004FF (base 16) Acronet Co., Ltd. + Saman B/D 2Fl + 137-064 + KR + +00-05-01 (hex) Cisco Systems, Inc +000501 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-08 (hex) Inetcam, Inc. +000508 (base 16) Inetcam, Inc. + 10171 Pacific Mesa Blvd. + San Diego CA 92121 + US + +00-05-1B (hex) Magic Control Technology Corporation +00051B (base 16) Magic Control Technology Corporation + 6F, No. 120-11 Chung Shan Rd. + + TW + +00-05-13 (hex) VTLinx Multimedia Systems, Inc. +000513 (base 16) VTLinx Multimedia Systems, Inc. + 8401 Colesville Road, + Silver Spring MD 20910 + US + +00-05-0E (hex) 3ware, Inc. +00050E (base 16) 3ware, Inc. + 701 E. Middlefield Rd. + Mt. View CA 94043 + US + +00-04-D7 (hex) Omitec Instrumentation Ltd. +0004D7 (base 16) Omitec Instrumentation Ltd. + Hopton Industrial Est. + ENGLAND + GB + +00-04-D4 (hex) Proview Electronics Co., Ltd. +0004D4 (base 16) Proview Electronics Co., Ltd. + 6F, No. 1, Pau-Sheng Road + + TW + +00-04-DB (hex) Tellus Group Corp. +0004DB (base 16) Tellus Group Corp. + 4F, No. 15 Industry E. Rd., IX + Hsinchu Hsinchu Taiwan + TW + +00-04-E0 (hex) Procket Networks +0004E0 (base 16) Procket Networks + 1100 Cadillac Court + Milpitas CA 95035 + US + +00-04-DD (hex) Cisco Systems, Inc +0004DD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-80-86 (hex) COMPUTER GENERATION INC. +008086 (base 16) COMPUTER GENERATION INC. + 3855 PRESIDENTIAL PARKWAY + ATLANTA GA 30340 + US + +00-05-04 (hex) Naray Information & Communication Enterprise +000504 (base 16) Naray Information & Communication Enterprise + 3F San Woo Bldg., 1543-11 + Seoul 137-070 + KR + +00-05-09 (hex) AVOC Nishimura Ltd. +000509 (base 16) AVOC Nishimura Ltd. + Jogasaki 4-16-14 + + JP + +00-04-FB (hex) Commtech, Inc. +0004FB (base 16) Commtech, Inc. + 9011 E. 37th Street + Wichita KS 67226-2006 + US + +00-04-C0 (hex) Cisco Systems, Inc +0004C0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-04-BA (hex) KDD Media Will Corporation +0004BA (base 16) KDD Media Will Corporation + 2-1-23 Nakameguro + 153-0061 + JP + +00-04-B6 (hex) Stratex Networks, Inc. +0004B6 (base 16) Stratex Networks, Inc. + 64 White Road + Cape Town 7945 + ZA + +00-04-CD (hex) Extenway Solutions Inc +0004CD (base 16) Extenway Solutions Inc + 500 boul. Morgan + Baie-d'Urfe Quebec H9X 3V1 + CA + +00-04-E9 (hex) Infiniswitch Corporation +0004E9 (base 16) Infiniswitch Corporation + 134 Flanders Road + Westborough MA 01581 + US + +00-04-E8 (hex) IER, Inc. +0004E8 (base 16) IER, Inc. + 4501 So. General Bruce Dr + Temple TX 76502 + US + +00-04-B3 (hex) Videotek, Inc. +0004B3 (base 16) Videotek, Inc. + 243 Shoemaker Rd. + Pottstown PA 19464 + US + +00-04-4C (hex) JENOPTIK +00044C (base 16) JENOPTIK + Laser, Optik, Systeme GmbH + + DE + +00-04-44 (hex) Western Multiplex Corporation +000444 (base 16) Western Multiplex Corporation + 1196 Borregas Avenue + Sunnyvale CA 94089 + US + +00-04-39 (hex) Rosco Entertainment Technology, Inc. +000439 (base 16) Rosco Entertainment Technology, Inc. + 2181 NW Front Ave. + Portland OR 97209 + US + +00-04-3A (hex) Intelligent Telecommunications, Inc. +00043A (base 16) Intelligent Telecommunications, Inc. + 1687-2, Sinil-dong + SOUTH KOREA 306-230 + KR + +00-04-92 (hex) Hive Internet, Ltd. +000492 (base 16) Hive Internet, Ltd. + Unit 2, Church View Business Centre + Binbrook Market Rasen, Lincolnshire LN8 6BY + GB + +00-04-8C (hex) Nayna Networks, Inc. +00048C (base 16) Nayna Networks, Inc. + 157 Topaz St. + Milpitas CA 95035 + US + +00-04-91 (hex) Technovision, Inc. +000491 (base 16) Technovision, Inc. + 5155 Spectrum Way, Unit #31 + L4W 5A1 + CA + +00-04-93 (hex) Tsinghua Unisplendour Co., Ltd. +000493 (base 16) Tsinghua Unisplendour Co., Ltd. + Th-Unis Building Tsinghua + P.R. + CN + +00-04-94 (hex) Breezecom, Ltd. +000494 (base 16) Breezecom, Ltd. + Atidim Technology Park + + IL + +00-04-89 (hex) YAFO Networks, Inc. +000489 (base 16) YAFO Networks, Inc. + 1340F Charwood Rd. + Hanover MD 21076 + US + +00-04-8A (hex) Temia Vertriebs GmbH +00048A (base 16) Temia Vertriebs GmbH + Landsbergerstraße 320 + + DE + +00-04-81 (hex) Econolite Control Products, Inc. +000481 (base 16) Econolite Control Products, Inc. + 3360 E. La Palma Ave. + Anaheim CA 92806 + US + +00-04-6C (hex) Cyber Technology Co., Ltd. +00046C (base 16) Cyber Technology Co., Ltd. + 1-45 Yeo Wol-Dong + Kyeong Gi-Do Kyeong Gi-Do KOREA + KR + +00-04-71 (hex) IPrad +000471 (base 16) IPrad + 24 Raoul Wallenberg St. + + IL + +00-04-6E (hex) Cisco Systems, Inc +00046E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-04-74 (hex) LEGRAND +000474 (base 16) LEGRAND + 145 Avenue De Lattre + + FR + +00-04-2D (hex) Sarian Systems, Ltd. +00042D (base 16) Sarian Systems, Ltd. + Beacon House + West Yorkshire ENGLAND LS29 8JZ + GB + +00-04-2E (hex) Netous Technologies, Ltd. +00042E (base 16) Netous Technologies, Ltd. + 1006, Block A, + HONG KONG + HK + +00-04-25 (hex) Atmel Corporation +000425 (base 16) Atmel Corporation + Multimedia & Communications Group + Morrisville NC 27560 + US + +00-04-3F (hex) ESTeem Wireless Modems, Inc +00043F (base 16) ESTeem Wireless Modems, Inc + 415 N. Quay St., Suite 4 + Kennewick WA 99336 + US + +00-04-33 (hex) Cyberboard A/S +000433 (base 16) Cyberboard A/S + Kloevermarken 120 + + DK + +00-04-34 (hex) Accelent Systems, Inc. +000434 (base 16) Accelent Systems, Inc. + 2620 Ridgewood Rd., + Akron OH 44313 + US + +00-04-77 (hex) Scalant Systems, Inc. +000477 (base 16) Scalant Systems, Inc. + 2040 Martin Avenue + Santa Clara CA 95050 + US + +00-04-73 (hex) Photonex Corporation +000473 (base 16) Photonex Corporation + 8C Preston Court + Bedford MA 01730 + US + +00-04-70 (hex) ipUnplugged AB +000470 (base 16) ipUnplugged AB + Box 10160 + + SE + +00-04-5D (hex) BEKA Elektronik +00045D (base 16) BEKA Elektronik + Siemenstraße 29 + Erftstadt 50374 + DE + +00-04-59 (hex) Veristar Corporation +000459 (base 16) Veristar Corporation + 727 Allston Way + Berkeley CA 94710 + US + +00-04-A4 (hex) NetEnabled, Inc. +0004A4 (base 16) NetEnabled, Inc. + 1275 Kinnear Rd. + Columbus OH 43212 + US + +00-04-16 (hex) Parks S/A Comunicacoes Digitais +000416 (base 16) Parks S/A Comunicacoes Digitais + Av. Pernambuco, 1001 + + BR + +00-04-0F (hex) Asus Network Technologies, Inc. +00040F (base 16) Asus Network Technologies, Inc. + 11-1, No. 675, Sec. 1, King-kuo Rd., + TAIWAN TAIWAN R.O.C. + TW + +00-04-0A (hex) Sage Systems +00040A (base 16) Sage Systems + 1420 Harbor Bay Parkway + Alameda CA 94502 + US + +00-04-04 (hex) Makino Milling Machine Co., Ltd. +000404 (base 16) Makino Milling Machine Co., Ltd. + 4023 Nakatsu, Aikawa-machi + Aiko-gun Kanagawa 243-0303 + JP + +00-03-D0 (hex) KOANKEISO Co., Ltd. +0003D0 (base 16) KOANKEISO Co., Ltd. + Zip Code 791-8042 + + JP + +00-03-CF (hex) Muxcom, Inc. +0003CF (base 16) Muxcom, Inc. + D 602, Bundang Technopark #151 + Kyungki Do KOREA 463-070 + KR + +00-03-D1 (hex) Takaya Corporation +0003D1 (base 16) Takaya Corporation + Development Division + + JP + +00-03-AD (hex) Emerson Energy Systems AB +0003AD (base 16) Emerson Energy Systems AB + PO Box 92113 + + SE + +00-03-A7 (hex) Unixtar Technology, Inc. +0003A7 (base 16) Unixtar Technology, Inc. + 13F No. 100 Ming Chuan Road + TAIWAN + TW + +00-03-AE (hex) Allied Advanced Manufacturing Pte, Ltd. +0003AE (base 16) Allied Advanced Manufacturing Pte, Ltd. + 7 International Business Park + Singapore 609919 + SG + +00-03-A3 (hex) MAVIX, Ltd. +0003A3 (base 16) MAVIX, Ltd. + POB 217, Yokneam Illit, + 20692 + IL + +00-03-B6 (hex) QSI Corporation +0003B6 (base 16) QSI Corporation + 2212 South West Temple #50 + Salt Lake City UT 84115 + US + +00-03-B1 (hex) Hospira Inc. +0003B1 (base 16) Hospira Inc. + 755 Jarvis Drive + Morgan Hill CA 95037 + US + +00-03-B3 (hex) IA Link Systems Co., Ltd. +0003B3 (base 16) IA Link Systems Co., Ltd. + 6F-4, No. 81 Hsin Tai + TAIWAN TAIWAN R.O.C. + TW + +00-03-EB (hex) Atrica +0003EB (base 16) Atrica + 5 Shenkar St. P.O.B. 12231 + 46733 46733 + IL + +00-03-E7 (hex) Logostek Co. Ltd. +0003E7 (base 16) Logostek Co. Ltd. + 19th 15 Sunusu-Academy Tower + Seoul KOREA 133-123 + KR + +00-03-E3 (hex) Cisco Systems, Inc +0003E3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-F4 (hex) NetBurner +0003F4 (base 16) NetBurner + 5405 Morehouse Drive + San Diego CA 92121 + US + +00-03-F2 (hex) Seneca Networks +0003F2 (base 16) Seneca Networks + 30 West Gude Dr. + Rockville MD 20850 + US + +00-03-F0 (hex) Redfern Broadband Networks +0003F0 (base 16) Redfern Broadband Networks + Level 1, 1 Central Ave., + + AU + +00-03-DB (hex) Apogee Electronics Corp. +0003DB (base 16) Apogee Electronics Corp. + 1715 Berkeley St. + Santa Monica CA 90405-3210 + US + +00-03-D2 (hex) Crossbeam Systems, Inc. +0003D2 (base 16) Crossbeam Systems, Inc. + 80 Central Street + Boxborough MA 01719 + US + +00-04-05 (hex) ACN Technologies +000405 (base 16) ACN Technologies + 9F, HeyKang B/D, 157-36 + Seoul KOREA #135-090 + KR + +00-04-01 (hex) Osaki Electric Co., Ltd. +000401 (base 16) Osaki Electric Co., Ltd. + 1131, Fujikubo, Miyoshimachi, + + JP + +00-04-1B (hex) Bridgeworks Ltd. +00041B (base 16) Bridgeworks Ltd. + 135 Somerford Road + Christchurch DORSET BH23 3PY + GB + +00-03-A1 (hex) HIPER Information & Communication, Inc. +0003A1 (base 16) HIPER Information & Communication, Inc. + 1675-7, Sinil-dong, + 306-230 South Korea + KR + +00-03-96 (hex) EZ Cast Co., Ltd. +000396 (base 16) EZ Cast Co., Ltd. + 6th Floor, JungAng Building, + KOREA + KR + +00-03-9A (hex) SiConnect +00039A (base 16) SiConnect + Delta 100 + Swindon SN5 7XP + GB + +00-03-63 (hex) Miraesys Co., Ltd. +000363 (base 16) Miraesys Co., Ltd. + 650-2 4 Fl. Daemyung Bldg. + 135-080 + KR + +00-03-5F (hex) Prüftechnik Condition Monitoring GmbH & Co. KG +00035F (base 16) Prüftechnik Condition Monitoring GmbH & Co. KG + Franz-Bayer-Straße 14 + + DE + +00-03-60 (hex) PAC Interactive Technology, Inc. +000360 (base 16) PAC Interactive Technology, Inc. + 6F, No. 30, Alley 18, Lane 478 + Taipei + TW + +00-03-61 (hex) Widcomm, Inc. +000361 (base 16) Widcomm, Inc. + 9645 Scranton Road + San Diego CA 92121 + US + +00-03-94 (hex) Connect One +000394 (base 16) Connect One + 2 Hanagar Street + + IL + +00-03-8A (hex) America Online, Inc. +00038A (base 16) America Online, Inc. + 44900 Prentice Drive + Dulles VA 20166 + US + +00-03-8D (hex) PCS Revenue Control Systems, Inc. +00038D (base 16) PCS Revenue Control Systems, Inc. + 560 Sylvan Ave. + Englewood Cliffs NJ 07632 + US + +00-03-88 (hex) Fastfame Technology Co., Ltd. +000388 (base 16) Fastfame Technology Co., Ltd. + 7F, No. 111, Hsing De Rd., + TAIWAN TAIWAN R.O.C. + TW + +00-03-59 (hex) DigitalSis +000359 (base 16) DigitalSis + B-1405 Samho Bldg. + Seocho Seoul, + KR + +00-03-52 (hex) Colubris Networks +000352 (base 16) Colubris Networks + 440 Armand-Frappier + H7V 4B4 + CA + +00-03-4C (hex) Shanghai DigiVision Technology Co., Ltd. +00034C (base 16) Shanghai DigiVision Technology Co., Ltd. + 11F, Heng Tong + Shanghai 200050 + CN + +00-03-78 (hex) HUMAX Co., Ltd. +000378 (base 16) HUMAX Co., Ltd. + 271-2, Suh-hyun-Dong, + + KR + +00-03-74 (hex) Control Microsystems +000374 (base 16) Control Microsystems + 48 Steacie Drive + Ottawa Ontario K2K 2A9 + CA + +00-03-76 (hex) Graphtec Technology, Inc. +000376 (base 16) Graphtec Technology, Inc. + 45 Parker, Suite A + Irvine CA 92618 + US + +00-03-7E (hex) PORTech Communications, Inc. +00037E (base 16) PORTech Communications, Inc. + 150, Shiang-Shung N. Rd., + Taichung Taiwan 403, R.O.C. + TW + +00-03-6D (hex) Runtop, Inc. +00036D (base 16) Runtop, Inc. + 1, Lane 21, Hsin Hua Road, Kueishan + + TW + +00-03-6E (hex) Nicon Systems (Pty) Limited +00036E (base 16) Nicon Systems (Pty) Limited + 11 Termo Street + + ZA + +00-03-71 (hex) Acomz Networks Corp. +000371 (base 16) Acomz Networks Corp. + 7th Fl., Wooseok Bldg., 1007-37 + Seoul 156-09 + KR + +00-03-49 (hex) Vidicode Datacommunicatie B.V. +000349 (base 16) Vidicode Datacommunicatie B.V. + Postbus 7164 + + NL + +00-03-3E (hex) Tateyama System Laboratory Co., Ltd. +00033E (base 16) Tateyama System Laboratory Co., Ltd. + 30 Shimonoban Oyama-cho + 930-1305 + JP + +00-03-3C (hex) Daiden Co., Ltd. +00033C (base 16) Daiden Co., Ltd. + 2100-19 Tutumi, Kamimine-machi + + JP + +00-03-25 (hex) Arima Computer Corp. +000325 (base 16) Arima Computer Corp. + 6th Fl., No. 327, + + TW + +00-03-1F (hex) Condev Ltd. +00031F (base 16) Condev Ltd. + 200-1626 West 2nd Ave. + + CA + +00-02-9F (hex) L-3 Communication Aviation Recorders +00029F (base 16) L-3 Communication Aviation Recorders + P.O. Box 3041 + Sarasota FL 34230 + US + +00-03-1B (hex) Cellvision Systems, Inc. +00031B (base 16) Cellvision Systems, Inc. + 3F-1, 75, Hsin Taiwu Road, Sec. 1 + + TW + +00-03-1C (hex) Svenska Hardvarufabriken AB +00031C (base 16) Svenska Hardvarufabriken AB + Ole Romersvag 16, Ideon + + SE + +00-01-A8 (hex) Welltech Computer Co., Ltd. +0001A8 (base 16) Welltech Computer Co., Ltd. + 13F-4, no. 150, Jian Yi Road + TAIWAN TAIWAN R.O.C. + TW + +00-03-0C (hex) Telesoft Technologies Ltd. +00030C (base 16) Telesoft Technologies Ltd. + Observatory House, Stour Park, + + GB + +00-03-08 (hex) AM Communications, Inc. +000308 (base 16) AM Communications, Inc. + 100 Commerce Blvd. + Quakertown PA 18951 + US + +00-03-07 (hex) Secure Works, Inc. +000307 (base 16) Secure Works, Inc. + 11 Executive Drive + Atlanta GA 30329 + US + +00-03-06 (hex) Fusion In Tech Co., Ltd. +000306 (base 16) Fusion In Tech Co., Ltd. + 6Fl, Daeyoon Bldg. 1688-5, Seocho-dong + Seoul, + KR + +00-02-FC (hex) Cisco Systems, Inc +0002FC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-02-FA (hex) DX Antenna Co., Ltd. +0002FA (base 16) DX Antenna Co., Ltd. + 2-15 Hamazaki-Dori, + + JP + +00-02-FB (hex) Baumuller Aulugen-Systemtechnik GmbH +0002FB (base 16) Baumuller Aulugen-Systemtechnik GmbH + Ostendsts. 84 + + DE + +00-02-F6 (hex) Equipe Communications +0002F6 (base 16) Equipe Communications + 100 Nagog Park + Acton MA 01720 + US + +00-02-23 (hex) ClickTV +000223 (base 16) ClickTV + Kemong Bldg., 4th Fl., + Seoul Korea 135-010 + KR + +00-02-CB (hex) TriState Ltd. +0002CB (base 16) TriState Ltd. + Shinonaga Blg. 4-11-19 Hokko-cho + 053-0852 053-0852 + JP + +00-02-CA (hex) EndPoints, Inc. +0002CA (base 16) EndPoints, Inc. + 4 Preston Court + Bedford MA 01730 + US + +00-03-2A (hex) UniData Communication Systems, Inc. +00032A (base 16) UniData Communication Systems, Inc. + 2F, OhSung-Bldg, 82-15, + + KR + +00-03-24 (hex) SANYO Consumer Electronics Co., Ltd. +000324 (base 16) SANYO Consumer Electronics Co., Ltd. + 7-101 Tachikawa-cho + Tottori City 680-8634 + JP + +00-02-C4 (hex) Vector International BVBA +0002C4 (base 16) Vector International BVBA + Technologielaan 4 + 3001 Leuven + BE + +00-02-BF (hex) dotRocket, Inc. +0002BF (base 16) dotRocket, Inc. + 1901 S. Bascom, Suite 300 + Campbell CA 95008 + US + +00-03-17 (hex) Merlin Systems, Inc. +000317 (base 16) Merlin Systems, Inc. + 3900 New Park Mall Rd. + Newark CA 94560 + US + +00-03-18 (hex) Cyras Systems, Inc. +000318 (base 16) Cyras Systems, Inc. + 47100 Bayside Parkway + Fremont CA 94538 + US + +00-02-E3 (hex) LITE-ON Communications, Inc. +0002E3 (base 16) LITE-ON Communications, Inc. + 736 S. Hillview Drive + Milpitas CA 95035 + US + +00-02-DD (hex) Bromax Communications, Ltd. +0002DD (base 16) Bromax Communications, Ltd. + No. 20 Kuang Fu Road, + Hsin Chu 303 + TW + +00-02-47 (hex) Great Dragon Information Technology (Group) Co., Ltd. +000247 (base 16) Great Dragon Information Technology (Group) Co., Ltd. + 169 Beiyuan Rd., + Beijing 100101, + CN + +00-02-43 (hex) Raysis Co., Ltd. +000243 (base 16) Raysis Co., Ltd. + 997-10, Daechi-Dong, Kangnam-Ku, + Seoul 135-280, South Korea + KR + +00-02-31 (hex) Ingersoll-Rand +000231 (base 16) Ingersoll-Rand + 1467 Route 31 South + Annandale NJ 08801 + US + +00-02-66 (hex) Thermalogic Corporation +000266 (base 16) Thermalogic Corporation + 22 Kane Industrial Drive + Hudson MA 01749 + US + +00-02-68 (hex) Harris Government Communications +000268 (base 16) Harris Government Communications + Systems Division + Melbourne FL 32902 + US + +00-02-5E (hex) High Technology Ltd +00025E (base 16) High Technology Ltd + Chongqing Jinghong + People's Republic of + CN + +00-02-60 (hex) Accordion Networks, Inc. +000260 (base 16) Accordion Networks, Inc. + 39899 Balentine Drive, #335 + Newark CA 94560 + US + +00-02-83 (hex) Spectrum Controls, Inc. +000283 (base 16) Spectrum Controls, Inc. + PO Box 5533 + Bellevue WA 98006 + US + +00-02-84 (hex) UK Grid Solutions Limited +000284 (base 16) UK Grid Solutions Limited + St Leonards Building Redhill Business Park + Stafford ST16 1TW + GB + +00-02-80 (hex) Mu Net, Inc. +000280 (base 16) Mu Net, Inc. + 442 Marrett Road + Lexington MA 02421 + US + +00-90-64 (hex) Thomson Inc. +009064 (base 16) Thomson Inc. + 101 West 103rd Street + Indianapolis IN 46290-1102 + US + +00-02-7A (hex) IOI Technology Corporation +00027A (base 16) IOI Technology Corporation + 4F-3 No. 125 Lane 235, + Taipei TAIWAN, R.O.C. + TW + +00-02-74 (hex) Tommy Technologies Corp. +000274 (base 16) Tommy Technologies Corp. + #407 Heehoon Bld + Seoul Seoul KOREA + KR + +00-02-9E (hex) Information Equipment Co., Ltd. +00029E (base 16) Information Equipment Co., Ltd. + 740-1 Eaho Bldg., Yeok Sam-Dong + Seoul Korea #135-080 + KR + +00-02-9B (hex) Kreatel Communications AB +00029B (base 16) Kreatel Communications AB + Teknikringen 4C + + SE + +00-02-95 (hex) IP.Access Limited +000295 (base 16) IP.Access Limited + Melbourn Science Park + SG8 6EE SG8 6EE U.K. + GB + +00-02-72 (hex) CC&C Technologies, Inc. +000272 (base 16) CC&C Technologies, Inc. + 8F, 150, Chien I Rd., Chung Ho City, + Taipei County 235 Taiwan R.O.C. + TW + +00-02-6D (hex) Adept Telecom +00026D (base 16) Adept Telecom + Avenue de l'Europe + + FR + +00-02-6B (hex) BCM Computers Co., Ltd. +00026B (base 16) BCM Computers Co., Ltd. + 6F-6, No. 66, Sec 2, + TAIWAN TAIWAN R.O.C. + TW + +00-02-93 (hex) Solid Data Systems +000293 (base 16) Solid Data Systems + 2945 Oakmead Village Court + Santa Clara CA 95051 + US + +00-02-89 (hex) DNE Technologies +000289 (base 16) DNE Technologies + 50 Barnes Park N + Wallingford CT 06492 + US + +00-01-2F (hex) Twinhead International Corp +00012F (base 16) Twinhead International Corp + 2FL, 2, Lane 235, Bao-Chiao Road + TAIWAN TAIWAN R.O.C. + TW + +00-02-A7 (hex) Vivace Networks +0002A7 (base 16) Vivace Networks + 2730 Orchard Parkway + San Jose CA 95134 + US + +00-01-B2 (hex) Digital Processing Systems, Inc. +0001B2 (base 16) Digital Processing Systems, Inc. + 70 Valleywood Drive + L3R 4T5 + CA + +00-01-B8 (hex) Netsensity, Inc. +0001B8 (base 16) Netsensity, Inc. + PO Box 1060 + Lake Forest CA 92630 + US + +00-01-B9 (hex) SKF (U.K.) Limited +0001B9 (base 16) SKF (U.K.) Limited + 2 Michaelson Square Kirkton Campus + Livingston West Lothian EH54 7DP + GB + +00-01-B3 (hex) Precision Electronic Manufacturing +0001B3 (base 16) Precision Electronic Manufacturing + P0187, P.O. 527948 + Miami FL 33152-7948 + US + +00-01-BD (hex) Peterson Electro-Musical Products, Inc. +0001BD (base 16) Peterson Electro-Musical Products, Inc. + 11601 S. Mayfield Avenue + Alsip IL 60803-2476 + US + +00-02-09 (hex) Shenzhen SED Information Technology Co., Ltd. +000209 (base 16) Shenzhen SED Information Technology Co., Ltd. + 4/F., West Block, Block 414, Zhenhua Rd. + + CN + +00-02-02 (hex) Amino Communications, Ltd. +000202 (base 16) Amino Communications, Ltd. + Times House + UK CB4 5LH + GB + +00-02-01 (hex) IFM Electronic gmbh +000201 (base 16) IFM Electronic gmbh + Bechlingen 34 + + DE + +00-02-34 (hex) Imperial Technology, Inc. +000234 (base 16) Imperial Technology, Inc. + 2305 Utah Avenue + El Segundo CA 90245 + US + +00-02-36 (hex) INIT GmbH +000236 (base 16) INIT GmbH + Kaeppelestraße 6 + + DE + +00-02-2B (hex) SAXA, Inc. +00022B (base 16) SAXA, Inc. + NBF Platinum Tower 1-17-3 Shirokane + Minato-ku Tokyo 108-8050 + JP + +00-02-24 (hex) C-COR +000224 (base 16) C-COR + 15 Sterling Drive + Wallingford CT 06492 + US + +00-02-1F (hex) Aculab PLC +00021F (base 16) Aculab PLC + Lakeside, Bramley Road + Milton Keynes MK1 1PT + GB + +00-02-1A (hex) Zuma Networks +00021A (base 16) Zuma Networks + 8403 Fallbrook Ave. + West Hills CA 91304 + US + +00-01-CA (hex) Geocast Network Systems, Inc. +0001CA (base 16) Geocast Network Systems, Inc. + 190 Independence Drive + Menlo Park CA 94025 + US + +00-01-D1 (hex) CoNet Communications, Inc. +0001D1 (base 16) CoNet Communications, Inc. + 25 Mauchly, #320 + Irvine CA 92618 + US + +00-02-22 (hex) Chromisys, Inc. +000222 (base 16) Chromisys, Inc. + 1012 Stewart Drive + Sunnyvale CA 94086 + US + +00-02-13 (hex) S.D.E.L. +000213 (base 16) S.D.E.L. + Aeropole D2A + + FR + +00-01-DB (hex) Freecom Technologies GmbH +0001DB (base 16) Freecom Technologies GmbH + Obentrautstraße 72 + + DE + +00-01-DF (hex) ISDN Communications, Ltd. +0001DF (base 16) ISDN Communications, Ltd. + The Stable Block, Ronans + ENGLAND + GB + +00-01-EF (hex) Camtel Technology Corp. +0001EF (base 16) Camtel Technology Corp. + No. 2, Wu-Kung 5 Rd., Wu-Ku + Taiwan Taiwan R.O.C. + TW + +00-02-0A (hex) Gefran Spa +00020A (base 16) Gefran Spa + Via Sebina, 74 + + IT + +00-02-06 (hex) Telital R&D Denmark A/S +000206 (base 16) Telital R&D Denmark A/S + 9530 Stouring + + DK + +00-01-79 (hex) WIRELESS TECHNOLOGY, INC. +000179 (base 16) WIRELESS TECHNOLOGY, INC. + Anam Bldg. 2Fl, 154-17 + KOREA + KR + +00-01-60 (hex) ELMEX Co., LTD. +000160 (base 16) ELMEX Co., LTD. + 16-30 Kimachi + + JP + +00-01-4E (hex) WIN Enterprises, Inc. +00014E (base 16) WIN Enterprises, Inc. + 300 Willow Street South + North Andover MA 01845 + US + +00-30-73 (hex) International Microsystems, In +003073 (base 16) International Microsystems, In + 521 Valley Way + Milpitas CA 95035 + US + +00-30-3F (hex) TurboComm Tech Inc. +00303F (base 16) TurboComm Tech Inc. + 4F-2, No 171, Sung-Tch Road + Taipei + TW + +00-01-84 (hex) SIEB & MEYER AG +000184 (base 16) SIEB & MEYER AG + Auf dem Schmaarkamp 21 + + DE + +00-01-95 (hex) Sena Technologies, Inc. +000195 (base 16) Sena Technologies, Inc. + 116-23 Shinlim-dong + KOREA + KR + +00-01-A4 (hex) Microlink Corporation +0001A4 (base 16) Microlink Corporation + 11110 Ohio Ave., - Ste. #108 + Los Angeles CA 90034 + US + +00-01-8E (hex) Logitec Corporation +00018E (base 16) Logitec Corporation + 8268 Rokudouhara, Misuzu + + JP + +00-01-6D (hex) CarrierComm Inc. +00016D (base 16) CarrierComm Inc. + 2231 Rutherford, Suite 110 + Carlsbad CA 92008 + US + +00-01-6F (hex) Inkel Corp. +00016F (base 16) Inkel Corp. + CheongCheon-Dong, BuPyeong-Gu, + Incheon-Si + KR + +00-01-70 (hex) ESE Embedded System Engineer'g +000170 (base 16) ESE Embedded System Engineer'g + Mühlbachstraße 20 + + DE + +00-01-6A (hex) ALITEC +00016A (base 16) ALITEC + Laval Technopole B.P. 102 + + FR + +00-01-53 (hex) ARCHTEK TELECOM CORPORATION +000153 (base 16) ARCHTEK TELECOM CORPORATION + 4F, No.9 Lane 130, Min-Chyuan Rd. + 231 TAIWAN + TW + +00-01-35 (hex) KDC Corp. +000135 (base 16) KDC Corp. + 200-11 AnYang 7 dong + KOREA + KR + +00-01-41 (hex) CABLE PRINT +000141 (base 16) CABLE PRINT + Jozef Cardynstraat 16 + + BE + +00-01-65 (hex) AirSwitch Corporation +000165 (base 16) AirSwitch Corporation + 37East 200South + Springville UT 84663 + US + +00-01-56 (hex) FIREWIREDIRECT.COM, INC. +000156 (base 16) FIREWIREDIRECT.COM, INC. + 4132 Spicewood Springs Rd - #I-4 + Austin TX 78759 + US + +00-01-B7 (hex) Centos, Inc. +0001B7 (base 16) Centos, Inc. + 6F-1, NO. 15, LANE 360 + TAIWAN TAIWAN R.O.C. + TW + +00-01-B5 (hex) Turin Networks, Inc. +0001B5 (base 16) Turin Networks, Inc. + 1415 North McDowell Blvd. + Petaluma CA 94954 + US + +00-01-83 (hex) ANITE TELECOMS +000183 (base 16) ANITE TELECOMS + 127 Fleet Road, Fleet + UNITED KINGDOM + GB + +00-01-7E (hex) ADTEK System Science Co., Ltd. +00017E (base 16) ADTEK System Science Co., Ltd. + YBP West Tower + Hodogaya Yokohama + JP + +00-01-0C (hex) System Talks Inc. +00010C (base 16) System Talks Inc. + 4F, PrimeNihonbashi Bld. + Chuo-ku Tokyo + JP + +00-01-11 (hex) iDigm Inc. +000111 (base 16) iDigm Inc. + 7FL Sindo B/D 1604-22 Seocho-Dong + Seoul 137-070 + KR + +00-01-07 (hex) Leiser GmbH +000107 (base 16) Leiser GmbH + Ilmstr. 7 + 85579 Neubiberg + DE + +00-01-14 (hex) KANDA TSUSHIN KOGYO CO., LTD. +000114 (base 16) KANDA TSUSHIN KOGYO CO., LTD. + 23-2, Nishi-Gotanda 2-chome, + Tokyo 141-8533 + JP + +00-B0-F5 (hex) NetWorth Technologies, Inc. +00B0F5 (base 16) NetWorth Technologies, Inc. + 1000 Germantown Pike + Plymouth Metting PA 19462 + US + +00-B0-DB (hex) Nextcell, Inc. +00B0DB (base 16) Nextcell, Inc. + 651 East 18th Street + Plano TX 75074 + US + +00-B0-AE (hex) Symmetricom +00B0AE (base 16) Symmetricom + 2300 Orchard Parkway + San Jose CA 95131 + US + +00-B0-E7 (hex) British Federal Ltd. +00B0E7 (base 16) British Federal Ltd. + Castle Mill Works + Dudley DY1 4DA England + GB + +00-B0-8E (hex) Cisco Systems, Inc +00B08E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-5C (hex) SMAR Laboratories Corp. +00305C (base 16) SMAR Laboratories Corp. + 10960 Millridge North - Ste. #107 + Houston TX 77070 + US + +00-30-04 (hex) LEADTEK RESEARCH INC. +003004 (base 16) LEADTEK RESEARCH INC. + 18F, No.166, Chien-Yi Road + Hsien + TW + +00-30-F9 (hex) Sollae Systems Co., Ltd. +0030F9 (base 16) Sollae Systems Co., Ltd. + 607 Incheo IT Tower + Nam-gu Incheon + KR + +00-01-18 (hex) EZ Digital Co., Ltd. +000118 (base 16) EZ Digital Co., Ltd. + Bitville Bldg. Room 703 + Seoul + KR + +00-01-1C (hex) Universal Talkware Corporation +00011C (base 16) Universal Talkware Corporation + 10 Second St. NE + Minneapolis MN 55413 + US + +00-01-28 (hex) EnjoyWeb, Inc. +000128 (base 16) EnjoyWeb, Inc. + 3000 Scott Blvd. #107 + Santa Clara CA 95054 + US + +00-01-46 (hex) Tesco Controls, Inc. +000146 (base 16) Tesco Controls, Inc. + P.O. Box 239012 + Sacramento CA 95823-9012 + US + +00-01-49 (hex) TDT AG +000149 (base 16) TDT AG + Siemensstraße 18 + Essenbach 84051 + DE + +00-01-31 (hex) Bosch Security Systems, Inc. +000131 (base 16) Bosch Security Systems, Inc. + 130 Perinton Parkway + Fairport NY 14450 + US + +00-30-BE (hex) City-Net Technology, Inc. +0030BE (base 16) City-Net Technology, Inc. + 135 E. Chesnut Ave., Ste. + Monrovia CA 91016 + US + +00-30-02 (hex) Expand Networks +003002 (base 16) Expand Networks + Atidim Tech Park, Bldg. 4 + Tel-Aviv 61580 + IL + +00-30-78 (hex) Cisco Systems, Inc +003078 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-B0-EC (hex) EACEM +00B0EC (base 16) EACEM + Avenue Louise 140, Bte 6 + B-1050 BRUSSELS + BE + +00-B0-DF (hex) Starboard Storage Systems +00B0DF (base 16) Starboard Storage Systems + 12303 Airport Way + Broomfield Co 80021 + US + +00-01-0B (hex) Space CyberLink, Inc. +00010B (base 16) Space CyberLink, Inc. + 5th Fl. Guppyung Town B + Seoul + KR + +00-30-9C (hex) Timing Applications, Inc. +00309C (base 16) Timing Applications, Inc. + 4775 Walnut St. + Boulder CO 80301 + US + +00-30-7E (hex) Redflex Communication Systems +00307E (base 16) Redflex Communication Systems + 11-29 Eastern Road + South Melbourne Victoria 3205 + AU + +00-30-4F (hex) PLANET Technology Corporation +00304F (base 16) PLANET Technology Corporation + 11F, No. 96, Min-Chuan Road + Hsin-Tien Dist., New Taipei City + TW + +00-30-22 (hex) Fong Kai Industrial Co., Ltd. +003022 (base 16) Fong Kai Industrial Co., Ltd. + 4F-3, No. 13, Wu Chuan 1st Road + Hsin Chuang City, Taipei Hsien + TW + +00-30-70 (hex) 1Net Corporation +003070 (base 16) 1Net Corporation + 347 Elizabeth Avenue - Ste. #100 + Somerset NJ 08873 + US + +00-30-F8 (hex) Dynapro Systems, Inc. +0030F8 (base 16) Dynapro Systems, Inc. + 800 Carleton Court + New Westminster British Columbia V3M 6L3 + CA + +00-30-B7 (hex) Teletrol Systems, Inc. +0030B7 (base 16) Teletrol Systems, Inc. + Technology Center + Manchester NH 03101 + US + +00-30-B3 (hex) San Valley Systems, Inc. +0030B3 (base 16) San Valley Systems, Inc. + 2105 S. Bascom Ave. - Ste. #390 + Campbell CA 95008 + US + +00-30-09 (hex) Tachion Networks, Inc. +003009 (base 16) Tachion Networks, Inc. + 2 Meridian Road + Eatontown NJ 07724 + US + +00-30-7A (hex) Advanced Technology & Systems +00307A (base 16) Advanced Technology & Systems + Yokohama Business Park East Tower 9F, + 240-0005 + JP + +00-30-61 (hex) MobyTEL +003061 (base 16) MobyTEL + 4301 Connecticut Ave. NW + Washington DC 20008 + US + +00-30-54 (hex) CASTLENET TECHNOLOGY, INC. +003054 (base 16) CASTLENET TECHNOLOGY, INC. + NO. 130 WU-KUNG RD., + TAIWAN TAIWAN R.O.C. + TW + +00-30-0B (hex) mPHASE Technologies, Inc. +00300B (base 16) mPHASE Technologies, Inc. + 250 14th Street + Atlanta GA 30318 + US + +00-30-8F (hex) MICRILOR, Inc. +00308F (base 16) MICRILOR, Inc. + 17 Lakeside Office Park + Wakefield MA 01880 + US + +00-30-50 (hex) Versa Technology +003050 (base 16) Versa Technology + 4430 E. Miraloma Ave., - Ste. + Anaheim CA 92807 + US + +00-30-C0 (hex) Lara Technology, Inc. +0030C0 (base 16) Lara Technology, Inc. + 2345 North First Street + San Jose CA 95131 + US + +00-30-05 (hex) Fujitsu Siemens Computers +003005 (base 16) Fujitsu Siemens Computers + Buergermeister ulrich 100 + 86199 Augsburg + DE + +00-30-E0 (hex) OXFORD SEMICONDUCTOR LTD. +0030E0 (base 16) OXFORD SEMICONDUCTOR LTD. + 25 MILTON PARK + Abingdon Oxon OX14 4SH + GB + +00-30-64 (hex) ADLINK TECHNOLOGY, INC. +003064 (base 16) ADLINK TECHNOLOGY, INC. + 9F, NO. 166, JIEN-YI R.D. + CHUNG-HO CITY TAIPEI + TW + +00-30-DB (hex) Mindready Solutions, Inc. +0030DB (base 16) Mindready Solutions, Inc. + 2800 Marie-Curie Avenue + Quebec H4S 2C2 + CA + +00-30-E7 (hex) CNF MOBILE SOLUTIONS, INC. +0030E7 (base 16) CNF MOBILE SOLUTIONS, INC. + 7722 E. GRAY ROAD + SCOTTSDALE AZ 85260 + US + +00-30-B4 (hex) INTERSIL CORP. +0030B4 (base 16) INTERSIL CORP. + P.O. BOX 883 + MELBOURNE FL 32902 + US + +00-30-B1 (hex) TrunkNet +0030B1 (base 16) TrunkNet + Aubergenviller Allee 51 + Dieburg D-64807 + DE + +00-30-60 (hex) Powerfile, Inc. +003060 (base 16) Powerfile, Inc. + 3350 Thomas Road + Santa Clara CA 95054-2062 + US + +00-30-A0 (hex) TYCO SUBMARINE SYSTEMS, LTD. +0030A0 (base 16) TYCO SUBMARINE SYSTEMS, LTD. + 250 INDUSTRIAL WAY WEST + EATONTOWN NJ 07724 + US + +00-30-15 (hex) CP CLARE CORP. +003015 (base 16) CP CLARE CORP. + 78 CHERRY HILL DRIVE + BEVERLY MA 01915 + US + +00-30-1F (hex) OPTICAL NETWORKS, INC. +00301F (base 16) OPTICAL NETWORKS, INC. + 166 BAYPOINTE PARKWAY + SAN JOSE CA 95134 + US + +00-30-FA (hex) TELICA, INC. +0030FA (base 16) TELICA, INC. + 734 FOREST STREET, BLDG. + MARLBORO MA 01752 + US + +00-30-4B (hex) ORBACOM SYSTEMS, INC. +00304B (base 16) ORBACOM SYSTEMS, INC. + 1704 TAYLORS LANE + CINNAMINSON NJ 08077 + US + +00-30-E9 (hex) GMA COMMUNICATION MANUFACT'G +0030E9 (base 16) GMA COMMUNICATION MANUFACT'G + MARKETING, (1991) LTD. + ISRAEL ISRAEL 49130 + IL + +00-30-A5 (hex) ACTIVE POWER +0030A5 (base 16) ACTIVE POWER + 11525 STONEHOLLOW - STE.#255 + AUSTIN TX 78758 + US + +00-30-84 (hex) ALLIED TELESYN INTERNAIONAL +003084 (base 16) ALLIED TELESYN INTERNAIONAL + CORPORATION + SUNNYVALE CA 94086 + US + +00-30-43 (hex) IDREAM TECHNOLOGIES, PTE. LTD. +003043 (base 16) IDREAM TECHNOLOGIES, PTE. LTD. + 54 KALLANG BAHRU, #02-14 + + SG + +00-30-00 (hex) ALLWELL TECHNOLOGY CORP. +003000 (base 16) ALLWELL TECHNOLOGY CORP. + 4F, #15, LANE3, SEC.2 + TAIWAN TAIWAN R.O.C. + TW + +00-30-11 (hex) HMS Industrial Networks +003011 (base 16) HMS Industrial Networks + P O Box 4126 + SE-300 04 + SE + +00-30-68 (hex) CYBERNETICS TECH. CO., LTD. +003068 (base 16) CYBERNETICS TECH. CO., LTD. + DAITOH BLDG. 4F 3-32-1 + JAPAN 171-0033 + JP + +00-30-91 (hex) TAIWAN FIRST LINE ELEC. CORP. +003091 (base 16) TAIWAN FIRST LINE ELEC. CORP. + 40 Chung-Shan Road + Taipei County + TW + +00-30-CD (hex) CONEXANT SYSTEMS, INC. +0030CD (base 16) CONEXANT SYSTEMS, INC. + 4311 JAMBOREE ROAD + NEWPORT BEACH CA 92660 + US + +00-30-1A (hex) SMARTBRIDGES PTE. LTD. +00301A (base 16) SMARTBRIDGES PTE. LTD. + 745 Toa Payoh Lorong 5 + 319455 + SG + +00-30-29 (hex) OPICOM +003029 (base 16) OPICOM + ROOM #302, STYLE FACTORY 151 + KOREA + KR + +00-30-83 (hex) Ivron Systems +003083 (base 16) Ivron Systems + 19-20 YORK ROAD + + IE + +00-30-B6 (hex) Cisco Systems, Inc +0030B6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-C7 (hex) Macromate Corp. +0030C7 (base 16) Macromate Corp. + 8F,Universal Center,Number 179 + Taipei Hsien + TW + +00-30-E4 (hex) CHIYODA SYSTEM RIKEN +0030E4 (base 16) CHIYODA SYSTEM RIKEN + 2-7, KANDA-NISHIKI-CHO + + JP + +00-30-66 (hex) RFM +003066 (base 16) RFM + 3079 Premiere Pkwy + Duluth GA 30097 + US + +00-30-31 (hex) LIGHTWAVE COMMUNICATIONS, INC. +003031 (base 16) LIGHTWAVE COMMUNICATIONS, INC. + 261 PEPE'S FARM ROAD + MILFORD CT 06460 + US + +00-D0-07 (hex) MIC ASSOCIATES, INC. +00D007 (base 16) MIC ASSOCIATES, INC. + 1510-1, KAIDOKI + JAPAN JAPAN 206-0012 + JP + +00-D0-FF (hex) Cisco Systems, Inc +00D0FF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-28 (hex) Harmonic, Inc +00D028 (base 16) Harmonic, Inc + 965 Stewart Drive + Sunnyvale CA 94086-3913 + US + +00-D0-25 (hex) XROSSTECH, INC. +00D025 (base 16) XROSSTECH, INC. + HABDONG B/D 5F 210-2 + KOREA + KR + +00-D0-44 (hex) ALIDIAN NETWORKS, INC. +00D044 (base 16) ALIDIAN NETWORKS, INC. + 1330 W. MIDDLEFIELD ROAD + MOUNTAIN VIEW CA 94043 + US + +00-30-5B (hex) Toko Inc. +00305B (base 16) Toko Inc. + 18 COMIGAYA, TSURUGASHIMA-SHI + JAPAN 350-2281 + JP + +00-D0-49 (hex) IMPRESSTEK CO., LTD. +00D049 (base 16) IMPRESSTEK CO., LTD. + 6F, SPECIALTY CONSTRUCTION CTR + 302-120 KOREA (REP.) + KR + +00-D0-5B (hex) ACROLOOP MOTION CONTROL +00D05B (base 16) ACROLOOP MOTION CONTROL + SYSTEMS + CHASKA MN 55318 + US + +00-D0-42 (hex) MAHLO GMBH & CO. UG +00D042 (base 16) MAHLO GMBH & CO. UG + DONAUSTRASSE 12 + + DE + +00-D0-31 (hex) INDUSTRIAL LOGIC CORPORATION +00D031 (base 16) INDUSTRIAL LOGIC CORPORATION + 15 PIEDMONT CENTER-STE #700 + ATLANTA GA 30305 + US + +00-D0-38 (hex) FIVEMERE, LTD. +00D038 (base 16) FIVEMERE, LTD. + UNIT 1-HERON INDUSTRIAL ESTATE + RG7 1PJ ENGLAND + GB + +00-D0-C6 (hex) THOMAS & BETTS CORP. +00D0C6 (base 16) THOMAS & BETTS CORP. + Thomas & Betts Aust. Pty. Ltd. + Lidcombe New South Wales + AU + +00-D0-77 (hex) LUCENT TECHNOLOGIES +00D077 (base 16) LUCENT TECHNOLOGIES + CLIENT ACCESS BUSINESS UNIT + HOLMDEL NJ 07733 + US + +00-D0-3E (hex) ROCKETCHIPS, INC. +00D03E (base 16) ROCKETCHIPS, INC. + 7901 XERXES AVE. S. + MINNEAPOLIS MN 55431 + US + +00-D0-93 (hex) TQ - COMPONENTS GMBH +00D093 (base 16) TQ - COMPONENTS GMBH + GUT DELLING - MUHLSTR 2 + + DE + +00-D0-3F (hex) AMERICAN COMMUNICATION +00D03F (base 16) AMERICAN COMMUNICATION + TECHNOLIGIES INTERNATIONAL INC + ROHNERT PARK CA 94928 + US + +00-D0-F7 (hex) NEXT NETS CORPORATION +00D0F7 (base 16) NEXT NETS CORPORATION + MITA KOKUSAI BLDG. 17F + + JP + +00-D0-6F (hex) KMC CONTROLS +00D06F (base 16) KMC CONTROLS + P.O. BOX 497 + NEW PARIS IN 46553 + US + +00-D0-FC (hex) GRANITE MICROSYSTEMS +00D0FC (base 16) GRANITE MICROSYSTEMS + 10202 N. ENTERPRISE DRIVE + MEQUON WI 53092 + US + +00-D0-A6 (hex) LANBIRD TECHNOLOGY CO., LTD. +00D0A6 (base 16) LANBIRD TECHNOLOGY CO., LTD. + ROOM A-211, S.B.I. + KOREA 157-030 + KR + +00-D0-03 (hex) COMDA ENTERPRISES CORP. +00D003 (base 16) COMDA ENTERPRISES CORP. + 2F, NO. 501-18, CHUNGCHEN ROAD + TAIWAN TAIWAN ROC + TW + +00-D0-D2 (hex) EPILOG CORPORATION +00D0D2 (base 16) EPILOG CORPORATION + 500 CORPORATE CIRCLE - STE. + GOLDEN CO 80401 + US + +00-D0-F9 (hex) ACUTE COMMUNICATIONS CORP. +00D0F9 (base 16) ACUTE COMMUNICATIONS CORP. + NO. 1, CREATION ROAD III + TAIWAN + TW + +00-D0-CE (hex) iSystem Labs +00D0CE (base 16) iSystem Labs + BRODISCE 7, 10C + Trzin 1236 + SI + +00-D0-18 (hex) QWES. COM, INC. +00D018 (base 16) QWES. COM, INC. + 14742 NEWPORT AVE. - STE. #203 + TUSTIN CA 92780 + US + +00-01-A7 (hex) UNEX TECHNOLOGY CORPORATION +0001A7 (base 16) UNEX TECHNOLOGY CORPORATION + 8F-5, #130, SZE WEI RD., + HSINCHU + TW + +00-D0-8C (hex) GENOA TECHNOLOGY, INC. +00D08C (base 16) GENOA TECHNOLOGY, INC. + 5401 TECH CIRCLE + MOORPARK CA 93021 + US + +00-D0-59 (hex) AMBIT MICROSYSTEMS CORP. +00D059 (base 16) AMBIT MICROSYSTEMS CORP. + 5F-1, 5 HSIN-AN ROAD + TAIWAN TAIWAN R.O.C. + TW + +00-D0-FD (hex) OPTIMA TELE.COM, INC. +00D0FD (base 16) OPTIMA TELE.COM, INC. + 4-20 Cachet Woods Court + Markham ON L6C 3G1 + CA + +00-D0-A9 (hex) SHINANO KENSHI CO., LTD. +00D0A9 (base 16) SHINANO KENSHI CO., LTD. + ELECTRONIC EQUIPMENT DIVISION + + JP + +00-D0-DD (hex) SUNRISE TELECOM, INC. +00D0DD (base 16) SUNRISE TELECOM, INC. + 22 GREAT OAKS BLVD. + SAN JOSE CA 95119 + US + +00-D0-E6 (hex) IBOND INC. +00D0E6 (base 16) IBOND INC. + 3160, DE LA CRUZ BLVD. + SANTA CLARA CA 95054 + US + +00-D0-D1 (hex) Sycamore Networks +00D0D1 (base 16) Sycamore Networks + 220 Mill Rd + Chelmsford MA 01824 + US + +00-D0-87 (hex) MICROFIRST INC. +00D087 (base 16) MICROFIRST INC. + 11 EAST OAK STREET + OAKLAND NJ 07436 + US + +00-D0-80 (hex) EXABYTE CORPORATION +00D080 (base 16) EXABYTE CORPORATION + 1685 38TH STREET + BOULDER CO 80301 + US + +00-D0-91 (hex) SMARTSAN SYSTEMS, INC. +00D091 (base 16) SMARTSAN SYSTEMS, INC. + 4655 OLD IRONSIDES DR. #480 + SANTA CLARA CA 95054 + US + +00-D0-4E (hex) LOGIBAG +00D04E (base 16) LOGIBAG + 2, Rue de la Mandinière + + FR + +00-D0-27 (hex) APPLIED AUTOMATION, INC. +00D027 (base 16) APPLIED AUTOMATION, INC. + P.O. BOX 9999 + BARTLESVILLE OK 74005-9999 + US + +00-D0-72 (hex) BROADLOGIC +00D072 (base 16) BROADLOGIC + 463 S. MILPITAS BLVD. + MILPITAS CA 95035 + US + +00-D0-E2 (hex) MRT MICRO, INC. +00D0E2 (base 16) MRT MICRO, INC. + 14000 S. MILITARY TRAIL + DELRAY BEACH FL 33484 + US + +00-D0-6A (hex) LINKUP SYSTEMS CORPORATION +00D06A (base 16) LINKUP SYSTEMS CORPORATION + 1190 COLEMAN AVE.- STE #2C + SAN JOSE CA 95110 + US + +00-D0-89 (hex) DYNACOLOR, INC. +00D089 (base 16) DYNACOLOR, INC. + No.116, Zhouzi St., Neihu Dist. + Taipei City 114 + TW + +00-D0-2C (hex) CAMPBELL SCIENTIFIC, INC. +00D02C (base 16) CAMPBELL SCIENTIFIC, INC. + 815 W. 1800 N. + LOGAN UT 84321-1784 + US + +00-D0-CD (hex) ATAN TECHNOLOGY INC. +00D0CD (base 16) ATAN TECHNOLOGY INC. + #5, ALLEY 18, LANE 81, + TAIWAN TAIWAN R.O.C. + TW + +00-D0-40 (hex) SYSMATE CO., LTD. +00D040 (base 16) SYSMATE CO., LTD. + 1091 WOLPYONG-DONG + SOUTH KOREA + KR + +00-D0-1A (hex) URMET TLC S.P.A. +00D01A (base 16) URMET TLC S.P.A. + VIA DI CASTEL ROMANO 167 + + IT + +00-50-FF (hex) HAKKO ELECTRONICS CO., LTD. +0050FF (base 16) HAKKO ELECTRONICS CO., LTD. + 238, KAMIKASHIWANO-MACHI + MATTO-SHI, ISHIKAWA 924-0035 + JP + +00-50-D2 (hex) CMC Electronics Inc +0050D2 (base 16) CMC Electronics Inc + 600 Dr.Frederik-Philips Blvd + Montreal QC H4M 2S9 + CA + +00-50-F9 (hex) Sensormatic Electronics LLC +0050F9 (base 16) Sensormatic Electronics LLC + 1501 Yamato Rd + Boca Raton FL 33431 + US + +00-50-48 (hex) INFOLIBRIA +005048 (base 16) INFOLIBRIA + 411 WAVERLY OAKS RD-STE #323 + WALTHAM MA 02154-8414 + US + +00-50-4E (hex) SIERRA MONITOR CORP. +00504E (base 16) SIERRA MONITOR CORP. + 1991 TAROB COURT + MILPITAS CA 95035 + US + +00-50-F6 (hex) PAN-INTERNATIONAL INDUSTRIAL CORP. +0050F6 (base 16) PAN-INTERNATIONAL INDUSTRIAL CORP. + GF, NO. 176, CHANG CHUN RD. + TAIPEI + TW + +00-50-6C (hex) Beijer Electronics Products AB +00506C (base 16) Beijer Electronics Products AB + Box 426 + SE-201 24 Malmoe + SE + +00-50-D7 (hex) TELSTRAT +0050D7 (base 16) TELSTRAT + 3600 AVENUE + PLANO TX 75074 + US + +00-50-44 (hex) ASACA CORPORATION +005044 (base 16) ASACA CORPORATION + 420 CORPORATE CIRCLE, Unit H + GOLDEN CO 80401 + US + +00-50-E6 (hex) HAKUSAN CORPORATION +0050E6 (base 16) HAKUSAN CORPORATION + J TOWER, 1-1, NIKKOU-CHO + + JP + +00-50-3C (hex) TSINGHUA NOVEL ELECTRONICS +00503C (base 16) TSINGHUA NOVEL ELECTRONICS + CO., LTD. + 100084 100084 + CN + +00-50-60 (hex) TANDBERG TELECOM AS +005060 (base 16) TANDBERG TELECOM AS + Philip Pedersens vei 20 + 1361 Lysaker + NO + +00-50-EE (hex) TEK DIGITEL CORPORATION +0050EE (base 16) TEK DIGITEL CORPORATION + 20010 CENTURY BLVD. #300 + GERMANTOWN MD 20874 + US + +00-50-45 (hex) RIOWORKS SOLUTIONS, INC. +005045 (base 16) RIOWORKS SOLUTIONS, INC. + 4F, NO.28, LANE 583 + TAIWAN TAIWAN R.O.C. + TW + +00-50-2B (hex) GENRAD LTD. +00502B (base 16) GENRAD LTD. + ORION BUSINESS PARK + UNITED KINGDOM SK3 OXG + GB + +00-50-2E (hex) CAMBEX CORPORATION +00502E (base 16) CAMBEX CORPORATION + 115 Flanders Road + Westborough MA 01581 + US + +00-50-6E (hex) CORDER ENGINEERING CORPORATION +00506E (base 16) CORDER ENGINEERING CORPORATION + 151 KALMUS DRIVE - STE #A103 + COSTA MESA CA 92626 + US + +00-50-2C (hex) SOYO COMPUTER, INC. +00502C (base 16) SOYO COMPUTER, INC. + NO. 21 WU-KUNG 5 RD. + TAIWAN TAIWAN R.O.C. + TW + +00-50-77 (hex) PROLIFIC TECHNOLOGY, INC. +005077 (base 16) PROLIFIC TECHNOLOGY, INC. + 6F 1, LANE 51, SEC 1 + 100 + TW + +00-50-33 (hex) MAYAN NETWORKS +005033 (base 16) MAYAN NETWORKS + 3350 SCOTT BLVD. - BLDG. #9 + SANTA CLARA CA 95054 + US + +00-50-0E (hex) CHROMATIS NETWORKS, INC. +00500E (base 16) CHROMATIS NETWORKS, INC. + 3 BETHESDA METRO CENTER + BETHESDA MD 20814 + US + +00-D0-CC (hex) TECHNOLOGIES LYRE INC. +00D0CC (base 16) TECHNOLOGIES LYRE INC. + 1200 ST-JEAN-BAPTISTE, + CANADA G2E 5E8 + CA + +00-50-EC (hex) OLICOM A/S +0050EC (base 16) OLICOM A/S + NYBROVEJ 114 + + DK + +00-50-C9 (hex) MASPRO DENKOH CORP. +0050C9 (base 16) MASPRO DENKOH CORP. + ASADA NISSHIN AICHI + + JP + +00-50-BB (hex) CMS TECHNOLOGIES +0050BB (base 16) CMS TECHNOLOGIES + 13955 FARMINGTON RAOD + LIVONIA MI 48154 + US + +00-50-62 (hex) KOUWELL ELECTRONICS CORP. ** +005062 (base 16) KOUWELL ELECTRONICS CORP. ** + 7F, NO.99, NAN-KANG ROAD + + TW + +00-50-D5 (hex) AD SYSTEMS CORP. +0050D5 (base 16) AD SYSTEMS CORP. + 1-4-1, NAKACHO, MUSASHINO CITY + TOKYO 180-0006 + JP + +00-50-F3 (hex) GLOBAL NET INFORMATION CO., Ltd. +0050F3 (base 16) GLOBAL NET INFORMATION CO., Ltd. + NORTH TOWER- RM 1305 + GUANG ZHOU 510095 + CN + +00-50-BE (hex) FAST MULTIMEDIA AG +0050BE (base 16) FAST MULTIMEDIA AG + RUEDESHEIMERSTR. 11-13 + 80686 MUNICH + DE + +00-50-6F (hex) G-CONNECT +00506F (base 16) G-CONNECT + P.O. BOX 2200 + HERZLIYA 46120 + IL + +00-50-F8 (hex) ENTREGA TECHNOLOGIES, INC. +0050F8 (base 16) ENTREGA TECHNOLOGIES, INC. + 25691 ATLANTIC OCEAN DRIVE + LAKE FOREST CA 92630 + US + +00-50-42 (hex) SCI MANUFACTURING SINGAPORE PTE, LTD. +005042 (base 16) SCI MANUFACTURING SINGAPORE PTE, LTD. + 3 DEPOT CLOSE + SINGAPORE 109840 + SG + +00-50-C0 (hex) GATAN, INC. +0050C0 (base 16) GATAN, INC. + 5933 CORONADO LANE + PLEASANTON CA 94588 + US + +00-50-51 (hex) IWATSU ELECTRIC CO., LTD. +005051 (base 16) IWATSU ELECTRIC CO., LTD. + 7-41, KUGAYAMA 1-CHOME + SUGINAMI-KU, TOKYO 168-8501 + JP + +00-50-7D (hex) IFP +00507D (base 16) IFP + LESSINGSTR. 4 + D-78315 RADOLFZELL + DE + +00-50-97 (hex) MMC-EMBEDDED COMPUTERTECHNIK GmbH +005097 (base 16) MMC-EMBEDDED COMPUTERTECHNIK GmbH + ULRICHSBERGERSTR. 17 + D-94469 DEGGENDORF + DE + +00-50-10 (hex) NovaNET Learning, Inc. +005010 (base 16) NovaNET Learning, Inc. + 125 W. CHURCH STREET-STE. #300 + CHAMPAIGN IL 61820 + US + +00-50-9A (hex) TAG ELECTRONIC SYSTEMS +00509A (base 16) TAG ELECTRONIC SYSTEMS + GENESIS BUSINESS PARK + WOKING, SURREY GU21 5RW + GB + +00-50-22 (hex) ZONET TECHNOLOGY, INC. +005022 (base 16) ZONET TECHNOLOGY, INC. + 830 ROOM, BLDG. 53, 195, SEC.4 + HSINCHA + TW + +00-50-07 (hex) SIEMENS TELECOMMUNICATION SYSTEMS LIMITED +005007 (base 16) SIEMENS TELECOMMUNICATION SYSTEMS LIMITED + NO. 90, SEC. 1, CHIEN KUO NORTH ROAD + TAIPEI + TW + +00-50-40 (hex) Panasonic Electric Works Co., Ltd. +005040 (base 16) Panasonic Electric Works Co., Ltd. + Tsu-Factory, 1668, Fujikata + Tsu-shi Mie-ken 514-8555 + JP + +00-50-1C (hex) JATOM SYSTEMS, INC. +00501C (base 16) JATOM SYSTEMS, INC. + 99 MICHAEL COWPLAND DRIVE + ONTARIO, K2M 1X3 + CA + +00-50-92 (hex) Rigaku Corporation Osaka Plant +005092 (base 16) Rigaku Corporation Osaka Plant + 14-8 AKAOJI-CHO + TAKATSUKI-SHI, OSAKA 569-1146 + JP + +00-50-7A (hex) XPEED, INC. +00507A (base 16) XPEED, INC. + 4699 OLD IRONSIDES DRIVE + SANTA CLARA CA 95054 + US + +00-50-69 (hex) PixStream Incorporated +005069 (base 16) PixStream Incorporated + 180 COLUMBIA ST. W. + Ontario N2L 3L3 + CA + +00-50-68 (hex) ELECTRONIC INDUSTRIES ASSOCIATION +005068 (base 16) ELECTRONIC INDUSTRIES ASSOCIATION + 2500 WILSON BLVD. + ARLINGTON VA 22201 + US + +00-50-BC (hex) HAMMER STORAGE SOLUTIONS +0050BC (base 16) HAMMER STORAGE SOLUTIONS + 8450 CENTRAL AVENUE + NEWARK CA 94560 + US + +00-90-71 (hex) Applied Innovation Inc. +009071 (base 16) Applied Innovation Inc. + 5800 Innovation Drive + Dublin OH 43016-3271 + US + +00-50-EB (hex) ALPHA-TOP CORPORATION +0050EB (base 16) ALPHA-TOP CORPORATION + 19F., NO. 2, LANE 150 + TAIPEI + TW + +00-50-EF (hex) SPE Systemhaus GmbH +0050EF (base 16) SPE Systemhaus GmbH + WALDSTRASSE 7 + 63150 HEUSENSTAMM + DE + +00-50-98 (hex) GLOBALOOP, LTD. +005098 (base 16) GLOBALOOP, LTD. + 12 HASHARON ROAD + KFAR SABA 44269 + IL + +00-50-4F (hex) OLENCOM ELECTRONICS +00504F (base 16) OLENCOM ELECTRONICS + SOLTAM INDUSTRIAL PARK + YOKNEAM 20692 + IL + +00-90-FF (hex) TELLUS TECHNOLOGY INC. +0090FF (base 16) TELLUS TECHNOLOGY INC. + 40990 ENCYCLOPEDIA CIR. + FREMONT CA 94538-2470 + US + +00-90-3E (hex) N.V. PHILIPS INDUSTRIAL ACTIVITIES +00903E (base 16) N.V. PHILIPS INDUSTRIAL ACTIVITIES + + B-3001 LEUVEN + BE + +00-90-BA (hex) VALID NETWORKS, INC. +0090BA (base 16) VALID NETWORKS, INC. + 6 CROMWELL #102 + IRVINE CA 92618 + US + +00-90-18 (hex) ITO ELECTRIC INDUSTRY CO, LTD. +009018 (base 16) ITO ELECTRIC INDUSTRY CO, LTD. + 4-26-12 MEIEKI NAKAMURA-KU + NAGOYA-CITY AICHI 450-0002 + JP + +00-90-CD (hex) ENT-EMPRESA NACIONAL DE TELECOMMUNICACOES, S.A. +0090CD (base 16) ENT-EMPRESA NACIONAL DE TELECOMMUNICACOES, S.A. + R. ENG FREDERICO ULRICH - APARTADO 3081 + Guardeiras - 4470 Moreira Maia + PT + +00-90-FB (hex) PORTWELL, INC. +0090FB (base 16) PORTWELL, INC. + 7F-4, NO. 160, SEC. 6 + TAIPEI + TW + +00-90-94 (hex) OSPREY TECHNOLOGIES, INC. +009094 (base 16) OSPREY TECHNOLOGIES, INC. + 600 AIRPORT BLVD. - STE. #900 + MORRISVILLE NC 27560 + US + +00-90-B3 (hex) AGRANAT SYSTEMS +0090B3 (base 16) AGRANAT SYSTEMS + 1345 MAIN STREET + WALTHAM MA 02154 + US + +00-90-3C (hex) ATLANTIC NETWORK SYSTEMS +00903C (base 16) ATLANTIC NETWORK SYSTEMS + IMMEUBLE Kennedy + 33700 MERIGNAC + FR + +00-90-5D (hex) NETCOM SICHERHEITSTECHNIK GMBH +00905D (base 16) NETCOM SICHERHEITSTECHNIK GMBH + BOPPSTRASSE 38 + + DE + +00-90-D1 (hex) LEICHU ENTERPRISE CO., LTD. +0090D1 (base 16) LEICHU ENTERPRISE CO., LTD. + 8F, NO. 203, PA-TEH ROAD, SEC.2 + + TW + +00-90-46 (hex) DEXDYNE, LTD. +009046 (base 16) DEXDYNE, LTD. + 15 MARKET PL. + GLOCESTERSHIRE GL7 2PB + GB + +00-90-DA (hex) DYNARC, INC. +0090DA (base 16) DYNARC, INC. + 1887 LANDINGS DRIVE + MOUNTAIN VIEW CA 94043 + US + +00-90-E0 (hex) SYSTRAN CORP. +0090E0 (base 16) SYSTRAN CORP. + 4126 LINDEN AVENUE + DAYTON OH 45432 + US + +00-90-D0 (hex) Thomson Telecom Belgium +0090D0 (base 16) Thomson Telecom Belgium + Prins Boudewijnlaan 47 + B-2650 EDEGEM + BE + +00-90-9B (hex) MARKEM-IMAJE +00909B (base 16) MARKEM-IMAJE + Frihamnen 16A + Gothenburg 417 55 + SE + +00-90-22 (hex) IVEX +009022 (base 16) IVEX + 4295 INTERNATIONAL BLVD. + NORCROSS GA 30093 + US + +00-90-16 (hex) ZAC +009016 (base 16) ZAC + Stüvestraße 9 + D-31141 Hildesheim + DE + +00-90-A7 (hex) CLIENTEC CORPORATION +0090A7 (base 16) CLIENTEC CORPORATION + 8175 S. VIRGINIA ST. + RENO NV 89511 + US + +00-90-53 (hex) DAEWOO ELECTRONICS CO., LTD. +009053 (base 16) DAEWOO ELECTRONICS CO., LTD. + DIT RESEARCH CENTER + CHUNG-GU SEOUL 100-714 + KR + +00-90-DC (hex) TECO INFORMATION SYSTEMS +0090DC (base 16) TECO INFORMATION SYSTEMS + CO., LTD. + SAN JOSE CA 95134 + US + +00-90-E2 (hex) DISTRIBUTED PROCESSING TECHNOLOGY +0090E2 (base 16) DISTRIBUTED PROCESSING TECHNOLOGY + 140 CANDACE DRIVE + ORLANDO FL 32751 + US + +00-90-85 (hex) GOLDEN ENTERPRISES, INC. +009085 (base 16) GOLDEN ENTERPRISES, INC. + 4450 WEST EAU GALLIE BLVD. + MELBOURNE FL 32934 + US + +00-90-C7 (hex) ICOM INC. +0090C7 (base 16) ICOM INC. + 6-9-16 KAMIHIGASHI + HIRANO-KU, OSAKA + JP + +00-90-35 (hex) ALPHA TELECOM, INC. +009035 (base 16) ALPHA TELECOM, INC. + 2F, NO.2, LI HSIN ROAD + HSIN-CHU + TW + +00-90-0F (hex) KAWASAKI HEAVY INDUSTRIES, LTD +00900F (base 16) KAWASAKI HEAVY INDUSTRIES, LTD + ELEC. & CONTROL TECH CENTER + + JP + +00-90-EA (hex) ALPHA TECHNOLOGIES, INC. +0090EA (base 16) ALPHA TECHNOLOGIES, INC. + 3767 ALPHA WAY + BELLINGHAM WA 98226 + US + +00-90-77 (hex) ADVANCED FIBRE COMMUNICATIONS +009077 (base 16) ADVANCED FIBRE COMMUNICATIONS + PO BOX #751239 + PETALUMA CA 94975 + US + +00-90-99 (hex) ALLIED TELESIS, K.K. +009099 (base 16) ALLIED TELESIS, K.K. + NO. 2 TOC BUILDING, 7-21-11Nishi-Gotand + Shinagawa-Ku Tokyo 141 + JP + +00-10-AD (hex) SOFTRONICS USB, INC. +0010AD (base 16) SOFTRONICS USB, INC. + 5085 LIST DRIVE + COLORADO SPRINGS CO 80919 + US + +00-10-A7 (hex) UNEX TECHNOLOGY CORPORATION +0010A7 (base 16) UNEX TECHNOLOGY CORPORATION + 8F-5, #130, SZE WEI RD., + HSINCHU + TW + +00-10-D5 (hex) IMASDE CANARIAS, S.A. +0010D5 (base 16) IMASDE CANARIAS, S.A. + URB. EL CEBADAL + 35008 LAS PALMAS G.C. + ES + +00-10-55 (hex) FUJITSU MICROELECTRONICS, INC. +001055 (base 16) FUJITSU MICROELECTRONICS, INC. + 3545 NORTH FIRST STREET + SAN JOSE CA 95134-1806 + US + +00-90-7A (hex) Spectralink, Inc +00907A (base 16) Spectralink, Inc + 2560 55th Street + BOULDER CO 80301 + US + +00-90-F0 (hex) Harmonic Video Systems Ltd. +0090F0 (base 16) Harmonic Video Systems Ltd. + 19 ALON HATAVOR STREET + CAESAREA Industrial Park 38900 + IL + +00-90-20 (hex) PHILIPS ANALYTICAL X-RAY B.V. +009020 (base 16) PHILIPS ANALYTICAL X-RAY B.V. + LELYWEG 1 + 7602 EA ALMELO + NL + +00-10-A3 (hex) OMNITRONIX, INC. +0010A3 (base 16) OMNITRONIX, INC. + 760 HARRISON STREET + SEATTLE WA 98109 + US + +00-90-5C (hex) EDMI +00905C (base 16) EDMI + 626 OLD GYMPIE ROAD + NARANGBA QLD 4504 + AU + +00-90-E3 (hex) AVEX ELECTRONICS INC. +0090E3 (base 16) AVEX ELECTRONICS INC. + 4807 BRADFORD DRIVE + HUNTSVILLE AL 35805 + US + +00-90-A9 (hex) WESTERN DIGITAL +0090A9 (base 16) WESTERN DIGITAL + 1599 NORTH BROADWAY + ROCHESTER MN 55906 + US + +00-90-F3 (hex) ASPECT COMMUNICATIONS +0090F3 (base 16) ASPECT COMMUNICATIONS + 1310 Ridder Park Drive + San Jose CA 95131-2313 + US + +00-90-4F (hex) ABB POWER T&D COMPANY, INC. +00904F (base 16) ABB POWER T&D COMPANY, INC. + 7036 SNOWDRIFT ROAD + ALLENTOWN PA 18106 + US + +00-90-60 (hex) SYSTEM CREATE CORP. +009060 (base 16) SYSTEM CREATE CORP. + 3-13-6 YOSHIKAWA BLD. + TOKYO + JP + +00-90-13 (hex) SAMSAN CORP. +009013 (base 16) SAMSAN CORP. + ELECTRONICS & COMM DIVISION + Kangdong-Gu Seoul 134-050 + KR + +00-10-52 (hex) METTLER-TOLEDO (ALBSTADT) GMBH +001052 (base 16) METTLER-TOLEDO (ALBSTADT) GMBH + P.O. BOX 2 50 + D-72423 ALBSTADT + DE + +00-10-6B (hex) SONUS NETWORKS, INC. +00106B (base 16) SONUS NETWORKS, INC. + 5 CARLISLE ROAD + WESTFORD MA 01886 + US + +00-10-C3 (hex) CSI-CONTROL SYSTEMS +0010C3 (base 16) CSI-CONTROL SYSTEMS + INTERNATIONAL + DALLAS TX 75229 + US + +00-90-55 (hex) PARKER HANNIFIN CORPORATION COMPUMOTOR DIVISION +009055 (base 16) PARKER HANNIFIN CORPORATION COMPUMOTOR DIVISION + 5500 BUSINESS PARK DRIVE + ROHNERT PARK CA 94928 + US + +00-10-DD (hex) ENABLE SEMICONDUCTOR, INC. +0010DD (base 16) ENABLE SEMICONDUCTOR, INC. + 1740 TECHNOLOGY DRIVE + SAN JOSE CA 95110 + US + +00-10-2D (hex) HITACHI SOFTWARE ENGINEERING +00102D (base 16) HITACHI SOFTWARE ENGINEERING + 5-79, ONOECHO, NAKA-KU + YOKOHAMA 231 + JP + +00-10-33 (hex) ACCESSLAN COMMUNICATIONS, INC. +001033 (base 16) ACCESSLAN COMMUNICATIONS, INC. + 44 AIRPORT PARKWAY + SAN JOSE CA 95110 + US + +00-10-12 (hex) PROCESSOR SYSTEMS (I) PVT LTD +001012 (base 16) PROCESSOR SYSTEMS (I) PVT LTD + 24 RICHMOND ROAD + BANGALORE 560 025 + IN + +00-10-15 (hex) OOmon Inc. +001015 (base 16) OOmon Inc. + PO BOX 8241 + COBURG OR 97408 + US + +00-10-78 (hex) NUERA COMMUNICATIONS, INC. +001078 (base 16) NUERA COMMUNICATIONS, INC. + 10445 PACIFIC CENTER COURT + SAN DIEGO CA 92121 + US + +00-10-4F (hex) Oracle Corporation +00104F (base 16) Oracle Corporation + 500 Oracle Parkway + Redwood Shores CA 94065 + US + +00-10-7A (hex) AmbiCom, Inc. +00107A (base 16) AmbiCom, Inc. + 2450 SCOTT BLVD., #305 + SANTA CLARA CA 95050 + US + +00-10-B9 (hex) MAXTOR CORP. +0010B9 (base 16) MAXTOR CORP. + 2190 MILLER DRIVE + LONGMONT CO 80501-6744 + US + +00-10-5D (hex) Draeger Medical +00105D (base 16) Draeger Medical + Moislinger Allee 53-55 + Luebeck D-23542 + DE + +00-10-91 (hex) NO WIRES NEEDED BV +001091 (base 16) NO WIRES NEEDED BV + P.O. BOX 343 + 3720 AH BILTHOVEN + NL + +00-10-1B (hex) CORNET TECHNOLOGY, INC. +00101B (base 16) CORNET TECHNOLOGY, INC. + 7F-4, NO. 46 CHUNG SHAN N.ROAD + SEC. 2, TAIPEI + TJ + +00-10-DC (hex) MICRO-STAR INTERNATIONAL CO., LTD. +0010DC (base 16) MICRO-STAR INTERNATIONAL CO., LTD. + NO. 69, LI-DE ST., JUNG-HE CITY + Taipei Hsien + TW + +00-10-0A (hex) WILLIAMS COMMUNICATIONS GROUP +00100A (base 16) WILLIAMS COMMUNICATIONS GROUP + ADVANCED TECHNOLOGIES + TULSA OK 74103 + US + +00-10-32 (hex) ALTA TECHNOLOGY +001032 (base 16) ALTA TECHNOLOGY + 9500 SOUTH 500 WEST - STE #212 + SANDY UT 84070 + US + +00-10-80 (hex) METAWAVE COMMUNICATIONS +001080 (base 16) METAWAVE COMMUNICATIONS + 8700 148TH AVENUE N.E. + REDMOND WA 98052 + US + +00-10-F4 (hex) Vertical Communications +0010F4 (base 16) Vertical Communications + 3979 Freedom Circle #400 + Santa Clara CA 95054-1247 + US + +00-10-77 (hex) SAF DRIVE SYSTEMS, LTD. +001077 (base 16) SAF DRIVE SYSTEMS, LTD. + 88 ARDELT AVE. + KITCHENER, ONTARIO N2C 2C9 + CA + +00-10-B3 (hex) NOKIA MULTIMEDIA TERMINALS +0010B3 (base 16) NOKIA MULTIMEDIA TERMINALS + NOKIA HOME COMMUNICATIONS + SE-583 35 LINKOPING + SE + +00-10-1E (hex) MATSUSHITA ELECTRONIC INSTRUMENTS CORP. +00101E (base 16) MATSUSHITA ELECTRONIC INSTRUMENTS CORP. + 23-9 KIYOHARA INDUSTRIAL PARK + UTSUNOMIYA Tochigi 321-32 + JP + +00-10-4D (hex) SURTEC INDUSTRIES, INC. +00104D (base 16) SURTEC INDUSTRIES, INC. + NO.11, ALLEY 16, LANE 337 + TAIPEI + TW + +00-10-51 (hex) CMICRO CORPORATION +001051 (base 16) CMICRO CORPORATION + 17-20-2 KAMINO-CHO + TAKAMATSU-SHI, KAGAWA 761 + JP + +00-10-37 (hex) CYQ've Technology Co., Ltd. +001037 (base 16) CYQ've Technology Co., Ltd. + COSMO BLDG. 10F, NO.1-7 + SHINJUKU-KU, TOKYO 160 + JP + +00-E0-BB (hex) NBX CORPORATION +00E0BB (base 16) NBX CORPORATION + 100 BRICKSTONE SQUARE + ANDOVER MA 01810 + US + +00-E0-8A (hex) GEC AVERY, LTD. +00E08A (base 16) GEC AVERY, LTD. + FOUNDRY LANE + WEST MIDLANDS, B66 2LP England + GB + +00-E0-86 (hex) Emerson Network Power, Avocent Division +00E086 (base 16) Emerson Network Power, Avocent Division + 4991 Corporate Drive + HUNTSVILLE AL 35805 + US + +00-E0-1B (hex) SPHERE COMMUNICATIONS, INC. +00E01B (base 16) SPHERE COMMUNICATIONS, INC. + 2 ENERGY DRIVE + LAKE BLUFF IL 60044 + US + +00-E0-59 (hex) CONTROLLED ENVIRONMENTS, LTD. +00E059 (base 16) CONTROLLED ENVIRONMENTS, LTD. + 590 BERRY STREET + WINNEPEG R3H OR9 + CA + +00-E0-C5 (hex) BCOM ELECTRONICS INC. +00E0C5 (base 16) BCOM ELECTRONICS INC. + 8 FL, NO. 64, AN HO ROAD, SEC. 2 + TAIPEI + TW + +00-E0-EE (hex) MAREL HF +00E0EE (base 16) MAREL HF + Austurhraun 9 + Gardabaer 210 + IS + +00-E0-8E (hex) UTSTARCOM +00E08E (base 16) UTSTARCOM + 33 WOOD AVE. SOUTH + ISELIN NJ 08830 + US + +00-E0-3F (hex) JATON CORPORATION +00E03F (base 16) JATON CORPORATION + 556 SOUTH MILPITAS BLVD. + MILPITAS CA 95035 + US + +00-E0-D4 (hex) EXCELLENT COMPUTER +00E0D4 (base 16) EXCELLENT COMPUTER + 551, M.K.N. ROAD + ALANDUR, CHENNAI 600016 + IN + +00-E0-7F (hex) LOGISTISTEM s.r.l. +00E07F (base 16) LOGISTISTEM s.r.l. + VIA PANCIATICHI 94/18 + 50127 FIRENZE + IT + +00-E0-13 (hex) EASTERN ELECTRONIC CO., LTD. +00E013 (base 16) EASTERN ELECTRONIC CO., LTD. + NO. 4, SHIN-LONG ROAD, + TAO-YUAN + TW + +00-E0-FD (hex) A-TREND TECHNOLOGY CO., LTD. +00E0FD (base 16) A-TREND TECHNOLOGY CO., LTD. + 10F, NO. 75, HSIN TAI WU RD., + TAIPEI HSIEN 221 + TJ + +00-E0-BD (hex) INTERFACE SYSTEMS, INC. +00E0BD (base 16) INTERFACE SYSTEMS, INC. + 5855 INTERFACE DRIVE + ANN ARBOR MI 48103-9515 + US + +00-E0-6E (hex) FAR SYSTEMS S.p.A. +00E06E (base 16) FAR SYSTEMS S.p.A. + VIA F. ZENI 8 + 3868 ROVERETO (TN) + IT + +00-E0-6D (hex) COMPUWARE CORPORATION +00E06D (base 16) COMPUWARE CORPORATION + One Campus Martius + Detroit MI 48226 + US + +00-E0-EA (hex) INNOVAT COMMUNICATIONS, INC. +00E0EA (base 16) INNOVAT COMMUNICATIONS, INC. + 1257 N. PLANO ROAD + RICHARDSON TX 75081 + US + +00-E0-64 (hex) SAMSUNG ELECTRONICS +00E064 (base 16) SAMSUNG ELECTRONICS + 99 W. TASMAN DRIVE + SAN JOSE CA 95134 + US + +00-E0-C9 (hex) AutomatedLogic Corporation +00E0C9 (base 16) AutomatedLogic Corporation + 1150 ROBERTS BOULEVARD + KENNESAW GA 30144-3618 + US + +00-E0-38 (hex) PROXIMA CORPORATION +00E038 (base 16) PROXIMA CORPORATION + 9440 CARROLL PARK DRIVE + SAN DIEGO CA 92121-2298 + US + +00-E0-9C (hex) MII +00E09C (base 16) MII + LE parc du MOULIN + F95650 PUISEUX-POTOISE + FR + +00-E0-E9 (hex) DATA LABS, INC. +00E0E9 (base 16) DATA LABS, INC. + 444 NORTH FREDERICK AVE. + GAITHERSBURG MD 20877 + US + +00-E0-0C (hex) MOTOROLA +00E00C (base 16) MOTOROLA + 5401 N. BEACH ST. S243 + FT. WORTH TX 76137 + US + +00-E0-0A (hex) DIBA, INC. +00E00A (base 16) DIBA, INC. + 3355 EDISON WAY + MENLO PARK CA 94025 + US + +00-E0-C4 (hex) HORNER ELECTRIC, INC. +00E0C4 (base 16) HORNER ELECTRIC, INC. + 1521 E. WASHINGTON ST. + INDIANAPOLIS IN 46201 + US + +00-E0-69 (hex) JAYCOR +00E069 (base 16) JAYCOR + 9775 TOWNE CENTRE DRIVE + SAN DIEGO CA 92121 + US + +00-E0-A4 (hex) ESAOTE S.p.A. +00E0A4 (base 16) ESAOTE S.p.A. + via di CACIOLLE, 15 + 50127 FLORENCE + IT + +00-E0-DE (hex) DATAX NV +00E0DE (base 16) DATAX NV + RINGLAAN 51 + B-2600 BERCHEM + BE + +00-E0-A5 (hex) ComCore Semiconductor, Inc. +00E0A5 (base 16) ComCore Semiconductor, Inc. + 4505 LAS VIRGENES, Suite 202 + CALABASAS CA 91302 + US + +00-E0-15 (hex) HEIWA CORPORATION +00E015 (base 16) HEIWA CORPORATION + 2-3014-8, HIROSAWA-CHO + GUNMA PREF. 376 + JP + +00-E0-E8 (hex) GRETACODER Data Systems AG +00E0E8 (base 16) GRETACODER Data Systems AG + ALTHARDSTRASSE 150 + CH-8105 REGENSDORF + CH + +00-E0-16 (hex) RAPID CITY COMMUNICATIONS +00E016 (base 16) RAPID CITY COMMUNICATIONS + 555 CLYDE AVE. + MOUNTAIN VIEW CA 94043 + US + +00-E0-05 (hex) TECHNICAL CORP. +00E005 (base 16) TECHNICAL CORP. + 22-6 MINAMI SENGENCHO + KANAGAWA + JP + +00-E0-C1 (hex) MEMOREX TELEX JAPAN, LTD. +00E0C1 (base 16) MEMOREX TELEX JAPAN, LTD. + YAESUGUCHI KAIKAN, 1-7-20 + TOKYO 103 + JP + +00-E0-A9 (hex) FUNAI ELECTRIC CO., LTD. +00E0A9 (base 16) FUNAI ELECTRIC CO., LTD. + 7-1, NAKAGAITO 7-CHOME, DAITO + OSAKA 574 + JP + +00-E0-84 (hex) COMPULITE R&D +00E084 (base 16) COMPULITE R&D + 3 HAROSHET STR. NEW IND. ZONE + RAMAT-HASHARON 47279 + IL + +00-E0-96 (hex) SHIMADZU CORPORATION +00E096 (base 16) SHIMADZU CORPORATION + 1, NISHINOKYO-KUWABARACHO + NAKAGYO-KU, KYOTO 604 + US + +00-E0-17 (hex) EXXACT GmbH +00E017 (base 16) EXXACT GmbH + RHEINSTRASE 7 + D-41836 HUCKELHOVEN + DE + +00-60-7F (hex) AURORA TECHNOLOGIES, INC. +00607F (base 16) AURORA TECHNOLOGIES, INC. + 176 SECOND AVENUE + WALTHAM MA 02154 + US + +00-E0-29 (hex) STANDARD MICROSYSTEMS CORP. +00E029 (base 16) STANDARD MICROSYSTEMS CORP. + 6 HUGHES + IRVINE CA 92718 + US + +00-60-74 (hex) QSC LLC +006074 (base 16) QSC LLC + 1675 MACARTHUR BLVD + COSTA MESA CA 92626 + US + +00-60-76 (hex) SCHLUMBERGER TECHNOLOGIES RETAIL PETROLEUM SYSTEMS +006076 (base 16) SCHLUMBERGER TECHNOLOGIES RETAIL PETROLEUM SYSTEMS + 825-M GREENBRIER CIRCLE + CHESAPEAKE VA 23320 + US + +00-60-A1 (hex) VPNet, Inc. +0060A1 (base 16) VPNet, Inc. + 555 N. MATHILDA AVE.,-STE #110 + SUNNYVALE CA 94086 + US + +00-60-27 (hex) Superior Modular Products +006027 (base 16) Superior Modular Products + General Technology Division + MELBOURNE FL 32940 + US + +00-60-BC (hex) KeunYoung Electronics & Communication Co., Ltd. +0060BC (base 16) KeunYoung Electronics & Communication Co., Ltd. + 325-76, DAEHEUNG-DONG, MAPO-GU, + SEOUL + KR + +00-60-A5 (hex) PERFORMANCE TELECOM CORP. +0060A5 (base 16) PERFORMANCE TELECOM CORP. + 10 CARLSON ROAD + ROCHESTER NY 14610-1021 + US + +00-60-05 (hex) FEEDBACK DATA LTD. +006005 (base 16) FEEDBACK DATA LTD. + PARK ROAD + EAST SUSSEX, TN6 2QR + GB + +00-60-2E (hex) CYCLADES CORPORATION +00602E (base 16) CYCLADES CORPORATION + 41934 CHRISTY STREET + FREMONT CA 94538 + US + +00-60-B6 (hex) LAND COMPUTER CO., LTD. +0060B6 (base 16) LAND COMPUTER CO., LTD. + 7-4-17 NISHINAKAJIMA + YODOGAWAKU 532 + JP + +00-60-6C (hex) ARESCOM +00606C (base 16) ARESCOM + 2833 JUNCTION AVE. - STE #206 + SAN JOSE CA 95134 + US + +00-60-E3 (hex) ARBIN INSTRUMENTS +0060E3 (base 16) ARBIN INSTRUMENTS + 3206 LONGMIRE DRIVE + COLLEGE STATION TX 77845 + US + +00-60-71 (hex) MIDAS LAB, INC. +006071 (base 16) MIDAS LAB, INC. + 4 KATAMACHI, + TOKYO 160 + JP + +00-60-61 (hex) WHISTLE COMMUNICATIONS CORP. +006061 (base 16) WHISTLE COMMUNICATIONS CORP. + 110 MARSH DRIVE-STE #100 + FOSTER CITY CA 94404 + US + +00-60-1B (hex) MESA ELECTRONICS +00601B (base 16) MESA ELECTRONICS + 1323 61ST STREET + EMERYVILLE CA 94608-2117 + US + +00-60-C5 (hex) ANCOT CORP. +0060C5 (base 16) ANCOT CORP. + 115 CONSTITUTION DR. + MENLO PARK CA 94025 + US + +00-60-A9 (hex) GESYTEC MBH +0060A9 (base 16) GESYTEC MBH + PASCALSTRASSE 6 + D 52076 AACHEN + DE + +00-60-F2 (hex) LASERGRAPHICS, INC. +0060F2 (base 16) LASERGRAPHICS, INC. + 20 ADA + IRVINE CA 92718 + US + +00-60-C3 (hex) NETVISION CORPORATION +0060C3 (base 16) NETVISION CORPORATION + MS# 1A + RONKONKOMA NY 11779 + US + +00-60-29 (hex) CARY PERIPHERALS INC. +006029 (base 16) CARY PERIPHERALS INC. + 190 COLONNADE ROAD S, UNIT 9 + NEPEAN, ONTARIO K2E 7J5 + CA + +00-60-A8 (hex) TIDOMAT AB +0060A8 (base 16) TIDOMAT AB + + S-12089 STOCKHOLM + SE + +00-60-FC (hex) CONSERVATION THROUGH INNOVATION LTD. +0060FC (base 16) CONSERVATION THROUGH INNOVATION LTD. + 1040 WHIPPLE ST.- STE. #225 + PRESCOTT AZ 86301 + US + +00-60-18 (hex) STELLAR ONE CORPORATION +006018 (base 16) STELLAR ONE CORPORATION + 500 108TH AVE. NE--STE. #2200 + BELLEVUE WA 98004 + US + +00-60-0A (hex) SORD COMPUTER CORPORATION +00600A (base 16) SORD COMPUTER CORPORATION + 20-7, MASAGO 5-CHOME + CHIBA 261 + JP + +00-60-A4 (hex) GEW Technologies (PTY)Ltd +0060A4 (base 16) GEW Technologies (PTY)Ltd + BOX 912-561 + SILVERTON 0127 + ZA + +00-60-64 (hex) NETCOMM LIMITED +006064 (base 16) NETCOMM LIMITED + PO BOX 379 + NORTH RYDE, NSW, 2113 + AU + +00-60-F9 (hex) DIAMOND LANE COMMUNICATIONS +0060F9 (base 16) DIAMOND LANE COMMUNICATIONS + 1310 REDWOOD WAY - STE. + PETALUMA CA 94954 + US + +00-60-EA (hex) StreamLogic +0060EA (base 16) StreamLogic + 21329 NORDHOFF STREET + CHATSWORTH CA 91311 + US + +00-60-82 (hex) NOVALINK TECHNOLOGIES, INC. +006082 (base 16) NOVALINK TECHNOLOGIES, INC. + 48511 WARM SPRINGS BLVD. #208 + FREMONT CA 94539 + US + +00-60-E7 (hex) RANDATA +0060E7 (base 16) RANDATA + PO BOX 209 + HAWTHORN VIC 3122 + AU + +00-60-D9 (hex) TRANSYS NETWORKS INC. +0060D9 (base 16) TRANSYS NETWORKS INC. + 3403 GRIFFITH + ST. LAURENT, QUEBEC H4T 1W5 + CA + +00-60-1F (hex) STALLION TECHNOLOGIES +00601F (base 16) STALLION TECHNOLOGIES + 33 WOODSTOCK ROAD + TOOWONG Q-L-D- 4066 + AU + +00-60-54 (hex) CONTROLWARE GMBH +006054 (base 16) CONTROLWARE GMBH + WALDSTRASSE 92 + 63128 DIETZENBACH + DE + +00-60-C2 (hex) MPL AG +0060C2 (base 16) MPL AG + Taefernstrasse 20 + CH-5405 Daettwil + CH + +00-60-D4 (hex) ELDAT COMMUNICATION LTD. +0060D4 (base 16) ELDAT COMMUNICATION LTD. + 10 HAKISHON STREET + BNEI-BRAK 51203 + IL + +00-A0-4E (hex) VOELKER TECHNOLOGIES, INC. +00A04E (base 16) VOELKER TECHNOLOGIES, INC. + 22 NEW BOSTON COURT + DANVILLE CA 94526 + US + +00-A0-5A (hex) KOFAX IMAGE PRODUCTS +00A05A (base 16) KOFAX IMAGE PRODUCTS + 3 JENNER STREET + IRVINE CA 92718-3807 + US + +00-A0-52 (hex) STANILITE ELECTRONICS PTY. LTD +00A052 (base 16) STANILITE ELECTRONICS PTY. LTD + 424, LANE COVE ROAD + NORTH RYDE NSW 2113 + AU + +00-A0-5E (hex) MYRIAD LOGIC INC. +00A05E (base 16) MYRIAD LOGIC INC. + 1109 SPRING STREET + SILVER SPRING MD 20910 + US + +00-A0-95 (hex) ACACIA NETWORKS, INC. +00A095 (base 16) ACACIA NETWORKS, INC. + 831 WOBURN STREET + WILMINGTON MA 01887 + US + +00-A0-53 (hex) COMPACT DEVICES, INC. +00A053 (base 16) COMPACT DEVICES, INC. + 16795 LARK AVENUE + LOS GATOS CA 95030 + US + +00-A0-69 (hex) Symmetricom, Inc. +00A069 (base 16) Symmetricom, Inc. + 3750 Westwind Blvd. + Santa Rosa CA 95403 + US + +00-A0-7A (hex) ADVANCED PERIPHERALS TECHNOLOGIES, INC. +00A07A (base 16) ADVANCED PERIPHERALS TECHNOLOGIES, INC. + + FUJISAWA-SHI, KANAGAWA-KEN 251 + JP + +00-60-9B (hex) AstroNova, Inc +00609B (base 16) AstroNova, Inc + 600 EAST GREENWICH AVE. + WEST WARWICK RI 02893 + US + +00-60-DB (hex) NTP ELEKTRONIK A/S +0060DB (base 16) NTP ELEKTRONIK A/S + KNAPHOLM 7 + DK-2730 HERLEV + DK + +00-60-52 (hex) PERIPHERALS ENTERPRISE CO., Ltd. +006052 (base 16) PERIPHERALS ENTERPRISE CO., Ltd. + 3F, NO.10, ALLEY 6, LANE 45 + TAIPEI + TW + +00-60-B2 (hex) PROCESS CONTROL CORP. +0060B2 (base 16) PROCESS CONTROL CORP. + 6875 MIMMS DRIVE + ATLANTA GA 30340 + US + +00-60-81 (hex) TV/COM INTERNATIONAL +006081 (base 16) TV/COM INTERNATIONAL + 16516 VIA ESPRILLO + SAN DIEGO CA 92127 + US + +00-A0-05 (hex) DANIEL INSTRUMENTS, LTD. +00A005 (base 16) DANIEL INSTRUMENTS, LTD. + TROLLSTRASSE 33 + CH-8400 WINTERTHUR + CH + +00-A0-F2 (hex) INFOTEK COMMUNICATIONS, INC. +00A0F2 (base 16) INFOTEK COMMUNICATIONS, INC. + 111 ANZA BLVD., #203 + BURLINGAME CA 94010 + US + +00-A0-DF (hex) STS TECHNOLOGIES, INC. +00A0DF (base 16) STS TECHNOLOGIES, INC. + 13765 ST. CHARLES ROCK RD. + BRIDGETON MO 63044 + US + +00-A0-94 (hex) COMSAT CORPORATION +00A094 (base 16) COMSAT CORPORATION + 22300 COMSAT DRIVE + CLARKSBURG MD 20871-9475 + US + +00-A0-EF (hex) LUCIDATA LTD. +00A0EF (base 16) LUCIDATA LTD. + LUCIDATA HOUSE + GREAT SHELFORD CAMBBRIDGE CB2 5HA + GB + +00-A0-20 (hex) CITICORP/TTI +00A020 (base 16) CITICORP/TTI + 3100 OCEAN PARK BLVD. + SANTA MONICA CA 90405 + US + +00-A0-CE (hex) Ecessa +00A0CE (base 16) Ecessa + 2800 Campus Drive + Plymouth MN 55441 + US + +00-A0-28 (hex) CONNER PERIPHERALS +00A028 (base 16) CONNER PERIPHERALS + 3061 ZANKER ROAD + SAN JOSE CA 95134-2128 + US + +00-A0-9E (hex) ICTV +00A09E (base 16) ICTV + 14600 WINCHESTER BLVD. + LOS GATOS CA 95030 + US + +00-A0-99 (hex) K-NET LTD. +00A099 (base 16) K-NET LTD. + SADDLERS HOUSE + YATELEY, SURREY GU17 7RX + GB + +00-A0-EC (hex) TRANSMITTON LTD. +00A0EC (base 16) TRANSMITTON LTD. + SMISBY ROAD + LEICESTERSHIRE LE65 2UG + GB + +00-A0-67 (hex) NETWORK SERVICES GROUP +00A067 (base 16) NETWORK SERVICES GROUP + 3421 COMMISSION COURT-STE #202 + WOODBRIDGE VA 22192 + US + +00-A0-E0 (hex) TENNYSON TECHNOLOGIES PTY LTD +00A0E0 (base 16) TENNYSON TECHNOLOGIES PTY LTD + 14 BUSINESS PARK DRIVE + VICTORIA - 3168 + AU + +00-A0-FD (hex) SCITEX DIGITAL PRINTING, INC. +00A0FD (base 16) SCITEX DIGITAL PRINTING, INC. + 3100 RESEARCH BLVD. + DAYTON OH 45420 + US + +00-A0-0F (hex) Broadband Technologies +00A00F (base 16) Broadband Technologies + P.O. Box 13737 + Research Triangle Park, NC 27709-3737 + US + +00-A0-02 (hex) LEEDS & NORTHRUP AUSTRALIA PTY LTD +00A002 (base 16) LEEDS & NORTHRUP AUSTRALIA PTY LTD + PO BOX 4009 + EIGHT MILE PLAINS QLD 4113 + AU + +00-A0-E4 (hex) OPTIQUEST +00A0E4 (base 16) OPTIQUEST + 20490 BUSINESS PARKWAY + WALNUT CA 91789 + US + +00-A0-EE (hex) NASHOBA NETWORKS +00A0EE (base 16) NASHOBA NETWORKS + 9-11 GOLDSMITH ST. + LITTLETON MA 01460 + US + +00-A0-C3 (hex) UNICOMPUTER GMBH +00A0C3 (base 16) UNICOMPUTER GMBH + LIMBURGER STRASSE 48 + + DE + +00-A0-0A (hex) Airspan +00A00A (base 16) Airspan + Unitronics Building, Arava Street, Airport City + 70100 + IL + +00-A0-E7 (hex) CENTRAL DATA CORPORATION +00A0E7 (base 16) CENTRAL DATA CORPORATION + 1602 NEWTON DRIVE + CHAMPAIGN IL 61821 + US + +00-A0-80 (hex) Tattile SRL +00A080 (base 16) Tattile SRL + 4000 Executive Parkway + San Ramon CA 94583 + US + +00-A0-2B (hex) TRANSITIONS RESEARCH CORP. +00A02B (base 16) TRANSITIONS RESEARCH CORP. + SHELTER ROCK LANE + DANBURY CT 06810 + US + +00-A0-E8 (hex) REUTERS HOLDINGS PLC +00A0E8 (base 16) REUTERS HOLDINGS PLC + 85, FLEET STREET + ENGLAND + GB + +00-A0-08 (hex) NETCORP +00A008 (base 16) NETCORP + 8 PLACE OF COMMERCE--STE #200 + CANADA J4W 3H2 + CA + +00-A0-50 (hex) CYPRESS SEMICONDUCTOR +00A050 (base 16) CYPRESS SEMICONDUCTOR + 198 Champion Ct + SAN JOSE CA 95134 + US + +00-A0-DD (hex) AZONIX CORPORATION +00A0DD (base 16) AZONIX CORPORATION + 900 MIDDLESEX TURNPIKE + BILLERICA MA 01821 + US + +00-A0-75 (hex) MICRON TECHNOLOGY, INC. +00A075 (base 16) MICRON TECHNOLOGY, INC. + 8000 S. Federal Way + Boise ID 83707-0006 + US + +00-A0-09 (hex) WHITETREE NETWORK +00A009 (base 16) WHITETREE NETWORK + TECHNOLOGIES, INC. + PALO ALTO CA 94306 + US + +00-A0-0C (hex) KINGMAX TECHNOLOGY, INC. +00A00C (base 16) KINGMAX TECHNOLOGY, INC. + 2FL., NO. 4, LANE 902, SEC.2 + + TW + +00-A0-66 (hex) ISA CO., LTD. +00A066 (base 16) ISA CO., LTD. + SHINJUKU LAMBDAX BLDG. 5F., + + JP + +00-A0-AB (hex) NETCS INFORMATIONSTECHNIK GMBH +00A0AB (base 16) NETCS INFORMATIONSTECHNIK GMBH + KATHARINENSTRASSE 17-18 + + DE + +00-A0-D8 (hex) SPECTRA - TEK +00A0D8 (base 16) SPECTRA - TEK + OUTGANG LANE + ENGLAND Y018 FJA + GB + +00-A0-FA (hex) Marconi Communication GmbH +00A0FA (base 16) Marconi Communication GmbH + Gerberstrasse 33 + + DE + +00-A0-CB (hex) ARK TELECOMMUNICATIONS, INC. +00A0CB (base 16) ARK TELECOMMUNICATIONS, INC. + 124 CARMEN LANE--SUITE + SANTA MARIA CA 93454 + US + +00-A0-34 (hex) AXEL +00A034 (base 16) AXEL + 16, AVENUE DU QUEBEC + + FR + +00-A0-01 (hex) DRS Signal Solutions +00A001 (base 16) DRS Signal Solutions + 700 Quince Orchard Road + Gaithersburg MD 20878-1794 + US + +00-20-B2 (hex) GKD Gesellschaft Fur Kommunikation Und Datentechnik +0020B2 (base 16) GKD Gesellschaft Fur Kommunikation Und Datentechnik + SAARBURGER RING 10-12 + 68229 MANNHEIM + DE + +00-20-52 (hex) RAGULA SYSTEMS +002052 (base 16) RAGULA SYSTEMS + 4540 S. JUPITER DRIVE + SALT LAKE CITY UT 84124 + US + +00-20-FC (hex) MATROX +0020FC (base 16) MATROX + 1055 ST. REGIS, + DORVAL, QUEBEC H9P-2T4 + CA + +00-20-FE (hex) TOPWARE INC. / GRAND COMPUTER +0020FE (base 16) TOPWARE INC. / GRAND COMPUTER + CORPORATION + TAIPEI R.O.C. + TW + +00-20-73 (hex) FUSION SYSTEMS CORPORATION +002073 (base 16) FUSION SYSTEMS CORPORATION + 7600 STANDISH PLACE + ROCKVILLE MD 20855 + US + +00-20-35 (hex) IBM Corp +002035 (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-A0-17 (hex) J B M CORPORATION +00A017 (base 16) J B M CORPORATION + 10-1, ARAMOTOSHIN MACHI + 577 + JP + +00-A0-25 (hex) REDCOM LABS INC. +00A025 (base 16) REDCOM LABS INC. + ONE REDCOM CENTER + VICTOR NY 14564-0995 + US + +00-A0-BB (hex) HILAN GMBH +00A0BB (base 16) HILAN GMBH + HAID-UND-NEU-STRASSE 7 + + DE + +00-A0-91 (hex) APPLICOM INTERNATIONAL +00A091 (base 16) APPLICOM INTERNATIONAL + 43, RUE MAZAGRAN + + FR + +00-A0-A5 (hex) TEKNOR MICROSYSTEME, INC. +00A0A5 (base 16) TEKNOR MICROSYSTEME, INC. + 616 CURE BOIVIN + J7G 2A7 + CA + +00-20-B7 (hex) NAMAQUA COMPUTERWARE +0020B7 (base 16) NAMAQUA COMPUTERWARE + P.O. BOX 7155 + + ZA + +00-20-E3 (hex) MCD KENCOM CORPORATION +0020E3 (base 16) MCD KENCOM CORPORATION + 20950 CASTLE ROCK ROAD + LAGUNA BEACH CA 92651-1115 + US + +00-20-13 (hex) DIVERSIFIED TECHNOLOGY, INC. +002013 (base 16) DIVERSIFIED TECHNOLOGY, INC. + 112 E. STATE STREET + RIDGELAND MS 39157 + US + +00-20-AB (hex) MICRO INDUSTRIES CORP. +0020AB (base 16) MICRO INDUSTRIES CORP. + 8399 GREEN MEADOWS DR. N. + WESTERVILLE OH 43081 + US + +00-20-8D (hex) CMD TECHNOLOGY +00208D (base 16) CMD TECHNOLOGY + 1 VANDERBILT + IRVINE CA 92718 + US + +00-20-DD (hex) Cybertec Pty Ltd +0020DD (base 16) Cybertec Pty Ltd + Unit 11, 41 Higginbotham Road + Gladesville NSW 2111 + AU + +00-20-E6 (hex) LIDKOPING MACHINE TOOLS AB +0020E6 (base 16) LIDKOPING MACHINE TOOLS AB + BOX 910 + + SE + +00-A0-A2 (hex) DIGICOM S.P.A. +00A0A2 (base 16) DIGICOM S.P.A. + VIA VOLTA 39 + + IT + +00-20-86 (hex) MICROTECH ELECTRONICS LIMITED +002086 (base 16) MICROTECH ELECTRONICS LIMITED + LANCASTER ROAD + KINGDOM + GB + +00-20-23 (hex) T.C. TECHNOLOGIES PTY. LTD +002023 (base 16) T.C. TECHNOLOGIES PTY. LTD + 6/60 FAIRFORD RD. + + AU + +00-A0-54 (hex) Private +00A054 (base 16) Private + +00-20-5A (hex) COMPUTER IDENTICS +00205A (base 16) COMPUTER IDENTICS + 5 SHAWMUT ROAD + CANTON MA 02021 + US + +00-20-00 (hex) LEXMARK INTERNATIONAL, INC. +002000 (base 16) LEXMARK INTERNATIONAL, INC. + 740 NEW CIRCLE ROAD + LEXINGTON KY 40550 + US + +00-20-1D (hex) KATANA PRODUCTS +00201D (base 16) KATANA PRODUCTS + THE STUDIO, QUARRY HILL BOX, + WILTSHIRE SN14 9HT + GB + +00-20-03 (hex) PIXEL POWER LTD. +002003 (base 16) PIXEL POWER LTD. + Unit 5 College Business Park + CAMBRIDGE CB1 3HD + GB + +00-20-46 (hex) CIPRICO, INC. +002046 (base 16) CIPRICO, INC. + 2800 CAMPUS DRIVE--SUITE #60 + PLYMOUTH MN 55441 + US + +00-20-9B (hex) ERSAT ELECTRONIC GMBH +00209B (base 16) ERSAT ELECTRONIC GMBH + HAARBERGSTR. 61 + + DE + +00-20-1C (hex) EXCEL, INC. +00201C (base 16) EXCEL, INC. + 355 OLD PLYMOUTH ROAD + SAGAMORE BEACH MA 02562 + US + +00-20-7F (hex) KYOEI SANGYO CO., LTD. +00207F (base 16) KYOEI SANGYO CO., LTD. + DIR. & GEN'L MGR.IND. SYSTEMS + TOKYO + JP + +00-20-C9 (hex) VICTRON BV +0020C9 (base 16) VICTRON BV + POB 31 + THE + NL + +00-20-77 (hex) KARDIOS SYSTEMS CORP. +002077 (base 16) KARDIOS SYSTEMS CORP. + 26 N SUMMIT AVE. + GAITHERSBURG MD 20877 + US + +00-20-7A (hex) WiSE Communications, Inc. +00207A (base 16) WiSE Communications, Inc. + 130 KNOWLES DRIVE + LOS GATOS CA 95030 + US + +00-20-3E (hex) LogiCan Technologies, Inc. +00203E (base 16) LogiCan Technologies, Inc. + 150 KARL CLARK ROAD + EDMONTON, ALBERTA T6N 1E2 + CA + +00-20-58 (hex) ALLIED SIGNAL INC. +002058 (base 16) ALLIED SIGNAL INC. + ROUTE 46 + TETERBORO NJ 07608 + US + +00-20-E1 (hex) ALAMAR ELECTRONICS +0020E1 (base 16) ALAMAR ELECTRONICS + 489 DIVISION STREET + CAMPBELL CA 95008 + US + +00-20-26 (hex) AMKLY SYSTEMS, INC. +002026 (base 16) AMKLY SYSTEMS, INC. + 15801 ROCKFIELD BLVD., #P + IRVINE CA 92718 + US + +00-20-65 (hex) SUPERNET NETWORKING INC. +002065 (base 16) SUPERNET NETWORKING INC. + 16 TOZERET HA'ARETZ ST. + TEL-AVIV 67891 + IL + +00-20-2A (hex) N.V. DZINE +00202A (base 16) N.V. DZINE + KONING LEOPOLD III LAAN 2 + + BE + +00-20-83 (hex) PRESTICOM INCORPORATED +002083 (base 16) PRESTICOM INCORPORATED + 3275, 1ST STREET, STE. #1 + CANADA J3Y 8Y6 + CA + +00-20-19 (hex) OHLER GMBH +002019 (base 16) OHLER GMBH + MAYBACHSTRASE 30 + 71332 WAIBLINGEN + DE + +00-20-9E (hex) BROWN'S OPERATING SYSTEM SERVICES, LTD. +00209E (base 16) BROWN'S OPERATING SYSTEM SERVICES, LTD. + ST. AGNES HOUSE, CRESSWELL PK, + BLACKHEATH, London SE3 9RD + GB + +00-20-8E (hex) CHEVIN SOFTWARE ENG. LTD. +00208E (base 16) CHEVIN SOFTWARE ENG. LTD. + 2 BOROUGHGATE, OTLEY, + LS21 3AL UNITED KINGDOM + GB + +00-20-97 (hex) APPLIED SIGNAL TECHNOLOGY +002097 (base 16) APPLIED SIGNAL TECHNOLOGY + 160 SOBRANTE WAY + SUNNYVALE CA 94086 + US + +00-C0-0B (hex) NORCONTROL A.S. +00C00B (base 16) NORCONTROL A.S. + P.O. BOX 1024 + + NO + +00-20-B0 (hex) GATEWAY DEVICES, INC. +0020B0 (base 16) GATEWAY DEVICES, INC. + 2440 STANWELL DRIVE + CONCORD CA 94520 + US + +00-20-5B (hex) Kentrox, LLC +00205B (base 16) Kentrox, LLC + 20010 NW Tanasbourne Dr. + Hillsboro OR 97124 + US + +00-20-F6 (hex) NET TEK AND KARLNET, INC. +0020F6 (base 16) NET TEK AND KARLNET, INC. + LITTLE STREAMS + UNITED KINGDOM + GB + +00-20-C6 (hex) NECTEC +0020C6 (base 16) NECTEC + RAMA VI ROAD + + TH + +00-20-08 (hex) CABLE & COMPUTER TECHNOLOGY +002008 (base 16) CABLE & COMPUTER TECHNOLOGY + 1555 SO. SINCLAIR STREET + ANAHEIM CA 92806 + US + +00-20-D3 (hex) OST (OUEST STANDARD TELEMATIQU +0020D3 (base 16) OST (OUEST STANDARD TELEMATIQU + RUE DU BAS VILLAGE + + FR + +00-C0-0E (hex) PSITECH, INC. +00C00E (base 16) PSITECH, INC. + 18368 BANDILIER CIRCLE + FOUNTAIN VALLEY CA 92708 + US + +00-C0-31 (hex) DESIGN RESEARCH SYSTEMS, INC. +00C031 (base 16) DESIGN RESEARCH SYSTEMS, INC. + 925 E. EXECUTIVE PARK DR. + SALT LAKE CITY UT 84117 + US + +00-07-01 (hex) RACAL-DATACOM +000701 (base 16) RACAL-DATACOM + LAN INTERNETWORKING DIVISION + BOXBOROUGH MA 01719 + US + +00-C0-9C (hex) HIOKI E.E. CORPORATION +00C09C (base 16) HIOKI E.E. CORPORATION + 81 Koizumi, Ueda, Nagano + Tokyo 386-1192 + JP + +00-C0-AA (hex) SILICON VALLEY COMPUTER +00C0AA (base 16) SILICON VALLEY COMPUTER + 441 N. WHISMAN RD., BLDG.#13 + MT. VIEW CA 94043 + US + +00-C0-66 (hex) DOCUPOINT, INC. +00C066 (base 16) DOCUPOINT, INC. + 2701 BAYVIEW DRIVE + FREMONT CA 94538 + US + +00-C0-2D (hex) FUJI PHOTO FILM CO., LTD. +00C02D (base 16) FUJI PHOTO FILM CO., LTD. + 798 MIYANODAI KAISEI-MACHI + + JP + +00-C0-F2 (hex) TRANSITION NETWORKS +00C0F2 (base 16) TRANSITION NETWORKS + 10900 Red Circle Dr. + MInnetonka MN 55343 + US + +00-C0-BD (hex) INEX TECHNOLOGIES, INC. +00C0BD (base 16) INEX TECHNOLOGIES, INC. + 3350 SCOTT BLVD. + SANTA CLARA CA 95054 + US + +00-C0-88 (hex) EKF ELEKTRONIK GMBH +00C088 (base 16) EKF ELEKTRONIK GMBH + PHILIPP-REIS-STR. 4 + + DE + +00-C0-11 (hex) INTERACTIVE COMPUTING DEVICES +00C011 (base 16) INTERACTIVE COMPUTING DEVICES + 1735 TECHNOLOGY DRIVE-STE #720 + SAN JOSE CA 95110 + US + +00-C0-3E (hex) FA. GEBR. HELLER GMBH +00C03E (base 16) FA. GEBR. HELLER GMBH + P.O. BOX 1428, DEP. EE7 + + DE + +00-C0-FD (hex) PROSUM +00C0FD (base 16) PROSUM + 12 RUE SADI-CARNOT + + FR + +00-C0-14 (hex) TELEMATICS CALABASAS INT'L,INC +00C014 (base 16) TELEMATICS CALABASAS INT'L,INC + 26630 AGOURA ROAD + CALABASAS CA 91302-1988 + US + +00-AA-3C (hex) OLIVETTI TELECOM SPA (OLTECO) +00AA3C (base 16) OLIVETTI TELECOM SPA (OLTECO) + 10062 MILLER AVE.-STE.#204 + CUPERTINO CA 95014 + US + +00-C0-C9 (hex) ELSAG BAILEY PROCESS +00C0C9 (base 16) ELSAG BAILEY PROCESS + AUTOMATION + WICKLIFFE OH 44092 + US + +00-C0-48 (hex) BAY TECHNICAL ASSOCIATES +00C048 (base 16) BAY TECHNICAL ASSOCIATES + 200 N. SECOND STREET + BAY ST. LOUIS MS 39520 + US + +00-C0-76 (hex) I-DATA INTERNATIONAL A-S +00C076 (base 16) I-DATA INTERNATIONAL A-S + 35-43 VADSTRUPVEJ + + DK + +00-C0-46 (hex) Blue Chip Technology Ltd +00C046 (base 16) Blue Chip Technology Ltd + Chowley Oak Lane + Chester Cheshire CH3 9EX + GB + +00-C0-97 (hex) ARCHIPEL SA +00C097 (base 16) ARCHIPEL SA + 1 RUE DU BULLOZ + + FR + +00-C0-04 (hex) JAPAN BUSINESS COMPUTER CO.LTD +00C004 (base 16) JAPAN BUSINESS COMPUTER CO.LTD + 1368 FUTOO-CHO, KOHOKU-KU + 222 + JP + +00-C0-60 (hex) ID SCANDINAVIA AS +00C060 (base 16) ID SCANDINAVIA AS + P.O. BOX 4227 + + NO + +00-40-CC (hex) SILCOM MANUF'G TECHNOLOGY INC. +0040CC (base 16) SILCOM MANUF'G TECHNOLOGY INC. + 5620 TIMBERLEA BOULEVARD + CANADA L4W 4M6 + CA + +00-C0-9E (hex) CACHE COMPUTERS, INC. +00C09E (base 16) CACHE COMPUTERS, INC. + 46600 LANDING PARKWAY + FREMONT CA 94538 + US + +00-C0-AC (hex) GAMBIT COMPUTER COMMUNICATIONS +00C0AC (base 16) GAMBIT COMPUTER COMMUNICATIONS + SOLTAM INDUSTRIAL PARK + + IL + +00-C0-34 (hex) TRANSACTION NETWORK +00C034 (base 16) TRANSACTION NETWORK + SERVICES, INC. + LANSING MI 48910-8356 + US + +00-C0-93 (hex) ALTA RESEARCH CORP. +00C093 (base 16) ALTA RESEARCH CORP. + 614 SOUTH FEDERAL HIGHWAY + DEERFIELD BEACH FL 33441 + US + +00-40-E7 (hex) ARNOS INSTRUMENTS & COMPUTER +0040E7 (base 16) ARNOS INSTRUMENTS & COMPUTER + SYSTEMS (GROUP) CO., LTD. + TSUEN WAN N.T. + HK + +00-40-87 (hex) UBITREX CORPORATION +004087 (base 16) UBITREX CORPORATION + 19TH FLOOR, 155 CARLTON STREET + CANADA R3C 3H8 + CA + +00-40-07 (hex) TELMAT INFORMATIQUE +004007 (base 16) TELMAT INFORMATIQUE + 6 RUE DE L'INDUSTRIE + + FR + +00-40-7B (hex) SCIENTIFIC ATLANTA +00407B (base 16) SCIENTIFIC ATLANTA + Information Technology + Norcross GA 30091-6850 + US + +00-40-2C (hex) ISIS DISTRIBUTED SYSTEMS, INC. +00402C (base 16) ISIS DISTRIBUTED SYSTEMS, INC. + 111 SOUTH CAYUGA STREET + ITHACA NY 14850 + US + +00-C0-DF (hex) KYE Systems Corp. +00C0DF (base 16) KYE Systems Corp. + No. 492 Sec 5, Chung Hsin Road + Taipei Hsien 241 + TW + +00-C0-F5 (hex) METACOMP, INC. +00C0F5 (base 16) METACOMP, INC. + 10989 VIA FRONTERA + SAN DIEGO CA 92127 + US + +00-C0-91 (hex) JABIL CIRCUIT, INC. +00C091 (base 16) JABIL CIRCUIT, INC. + 32275 MALLY ROAD + MADISON HEIGHTS MI 48071 + US + +00-C0-49 (hex) U.S. ROBOTICS, INC. +00C049 (base 16) U.S. ROBOTICS, INC. + 8100 NORTH MCCORMICK BLVD. + SKOKIE IL 60076-2999 + US + +00-C0-9D (hex) DISTRIBUTED SYSTEMS INT'L, INC +00C09D (base 16) DISTRIBUTED SYSTEMS INT'L, INC + 531 WEST ROOSEVLET RD, STE #2 + WHEATON IL 60187 + US + +00-C0-E9 (hex) OAK SOLUTIONS, LTD. +00C0E9 (base 16) OAK SOLUTIONS, LTD. + BROADWAY HOUSE + ENGLAND + GB + +00-C0-C5 (hex) SID INFORMATICA +00C0C5 (base 16) SID INFORMATICA + RUA DR. GERALDO CAMPOS MOREIRA + + BR + +00-C0-51 (hex) ADVANCED INTEGRATION RESEARCH +00C051 (base 16) ADVANCED INTEGRATION RESEARCH + 2188 DEL FRANCO STREET + SAN JOSE CA 95131 + US + +00-C0-85 (hex) ELECTRONICS FOR IMAGING, INC. +00C085 (base 16) ELECTRONICS FOR IMAGING, INC. + 2855 CAMPUS DRIVE + SAN MATEO CA 94403 + US + +00-C0-B2 (hex) NORAND CORPORATION +00C0B2 (base 16) NORAND CORPORATION + 550 2ND STREET SE + CEDAR RAPIDS IA 52401 + US + +00-C0-54 (hex) NETWORK PERIPHERALS, LTD. +00C054 (base 16) NETWORK PERIPHERALS, LTD. + 4TH FLOOR, 17 BOWATER RD. + ENGLAND + GB + +00-C0-22 (hex) LASERMASTER TECHNOLOGIES, INC. +00C022 (base 16) LASERMASTER TECHNOLOGIES, INC. + 7156 SHADY OAK ROAD + EDEN PRAIRIE MN 55344 + US + +00-C0-25 (hex) DATAPRODUCTS CORPORATION +00C025 (base 16) DATAPRODUCTS CORPORATION + 6219 DESOTO AVENUE + WOODLAND HILLS CA 91365-0746 + US + +00-40-CF (hex) STRAWBERRY TREE, INC. +0040CF (base 16) STRAWBERRY TREE, INC. + 160 SOUTH WOLFE ROAD + SUNNYVALE CA 94086 + US + +00-40-77 (hex) MAXTON TECHNOLOGY CORPORATION +004077 (base 16) MAXTON TECHNOLOGY CORPORATION + 4FK, 249, SEC. 3, + TAIWAN + TW + +00-C0-2C (hex) CENTRUM COMMUNICATIONS, INC. +00C02C (base 16) CENTRUM COMMUNICATIONS, INC. + 2880 ZANKER ROAD-STE #108 + SAN JOSE CA 95134 + US + +00-C0-FB (hex) ADVANCED TECHNOLOGY LABS +00C0FB (base 16) ADVANCED TECHNOLOGY LABS + 22100 BOTHELL HIGHWAY S.E. + BOTHELL WA 98041-3003 + US + +00-C0-2B (hex) GERLOFF GESELLSCHAFT FUR +00C02B (base 16) GERLOFF GESELLSCHAFT FUR + ELEKRONISCHE SYSTEMENTWICKLUNG + + DE + +00-40-74 (hex) CABLE AND WIRELESS +004074 (base 16) CABLE AND WIRELESS + COMMUNICATIONS, INC. + VIENNA VA 22182-3964 + US + +00-40-B8 (hex) IDEA ASSOCIATES +0040B8 (base 16) IDEA ASSOCIATES + 29 DUNHAM ROAD + BILLERICA MA 01821 + US + +00-40-E8 (hex) CHARLES RIVER DATA SYSTEMS,INC +0040E8 (base 16) CHARLES RIVER DATA SYSTEMS,INC + 983 CONCORD STREET + FRAMINGHAM MA 01701 + US + +00-40-C0 (hex) VISTA CONTROLS CORPORATION +0040C0 (base 16) VISTA CONTROLS CORPORATION + 27825 FREMONT COURT + VALENCIA CA 91355 + US + +00-C0-A0 (hex) ADVANCE MICRO RESEARCH, INC. +00C0A0 (base 16) ADVANCE MICRO RESEARCH, INC. + 2045 CORPORATE COURT + SAN JOSE CA 95131 + US + +00-C0-10 (hex) HIRAKAWA HEWTECH CORP. +00C010 (base 16) HIRAKAWA HEWTECH CORP. + 7F, BLDG.B, OMORI BELLPORT + + JP + +00-C0-37 (hex) DYNATEM +00C037 (base 16) DYNATEM + 15795 ROCKFIELD BLVD. + IRVINE CA 92718 + US + +00-40-83 (hex) TDA INDUSTRIA DE PRODUTOS +004083 (base 16) TDA INDUSTRIA DE PRODUTOS + ELETRONICOS S.A. + + BR + +00-40-5B (hex) FUNASSET LIMITED +00405B (base 16) FUNASSET LIMITED + ORCHARDS, 14 TOWNSEND + UNITED KINGDOM + GB + +00-40-73 (hex) BASS ASSOCIATES +004073 (base 16) BASS ASSOCIATES + 435 TASSO STREET, STE. #325 + PALO ALTO CA 94301 + US + +00-40-7D (hex) EXTENSION TECHNOLOGY CORP. +00407D (base 16) EXTENSION TECHNOLOGY CORP. + 30 HOLLIS STREET + FRAMINGHAM MA 01701 + US + +00-80-D7 (hex) Fantum Engineering +0080D7 (base 16) Fantum Engineering + + Rockwall TX 75087 + US + +00-80-7A (hex) AITECH SYSTEMS LTD. +00807A (base 16) AITECH SYSTEMS LTD. + 3080 OLCOTT STREET + SANTA CLARA CA 95054 + US + +00-80-DC (hex) PICKER INTERNATIONAL +0080DC (base 16) PICKER INTERNATIONAL + 595 MINER ROAD + CLEVELAND OH 44143 + US + +00-40-4D (hex) TELECOMMUNICATIONS TECHNIQUES +00404D (base 16) TELECOMMUNICATIONS TECHNIQUES + M/S + GERMANTOWN MD 20876 + US + +00-40-0D (hex) LANNET DATA COMMUNICATIONS,LTD +00400D (base 16) LANNET DATA COMMUNICATIONS,LTD + ATIDIM TECHNOLOG'L PARK, BG.#3 + + IL + +00-40-19 (hex) AEON SYSTEMS, INC. +004019 (base 16) AEON SYSTEMS, INC. + 8401 WASHINGTON PLACE NE + ALBUQUERQUE NM 87113 + US + +00-40-BE (hex) BOEING DEFENSE & SPACE +0040BE (base 16) BOEING DEFENSE & SPACE + P.O. BOX 3999 + SEATTLE WA 98124-2499 + US + +00-40-6E (hex) COROLLARY, INC. +00406E (base 16) COROLLARY, INC. + 2802 KELVIN + IRVINE CA 92714 + US + +00-40-76 (hex) Sun Conversion Technologies +004076 (base 16) Sun Conversion Technologies + 100 Commerce Boulevard + Quakertown PA 78951-2237 + US + +00-40-22 (hex) KLEVER COMPUTERS, INC. +004022 (base 16) KLEVER COMPUTERS, INC. + 1028 W. MAUDE AVENUE + SUNNYVALE CA 94086 + US + +00-40-BF (hex) CHANNEL SYSTEMS INTERN'L INC. +0040BF (base 16) CHANNEL SYSTEMS INTERN'L INC. + 93 SO. LA PATERA LANE + SANTA BARBARA CA 93117 + US + +00-40-1E (hex) ICC +00401E (base 16) ICC + 8230 MONTGOMERY ROAD + CINCINNATI OH 45236 + US + +00-40-9A (hex) NETWORK EXPRESS, INC. +00409A (base 16) NETWORK EXPRESS, INC. + 2200 GREEN ROAD - STE + ANN ARBOR MI 48170 + US + +00-40-94 (hex) SHOGRAPHICS, INC. +004094 (base 16) SHOGRAPHICS, INC. + 1890 N. SHORELINE BLVD. + MOUNTAIN VIEW CA 94043 + US + +00-40-55 (hex) METRONIX GMBH +004055 (base 16) METRONIX GMBH + NEUE KNOCHENHAUERSTRAßE 5 + WEST + DE + +00-40-27 (hex) SMC MASSACHUSETTS, INC. +004027 (base 16) SMC MASSACHUSETTS, INC. + 25 WALKERS BROOK DRIVE + READING MA 01867 + US + +00-40-8B (hex) RAYLAN CORPORATION +00408B (base 16) RAYLAN CORPORATION + 120 INDEPENDENCE DRIVE + MENLO PARK CA 94025 + US + +00-40-EF (hex) HYPERCOM, INC. +0040EF (base 16) HYPERCOM, INC. + 2851 WEST KATHLEEN ROAD + PHOENIX AZ 85023 + US + +00-40-93 (hex) PAXDATA NETWORKS LTD. +004093 (base 16) PAXDATA NETWORKS LTD. + COMMUNICATIONS HOUSE, + ENGLAND + GB + +00-40-85 (hex) SAAB INSTRUMENTS AB +004085 (base 16) SAAB INSTRUMENTS AB + P.O. BOX 1017 + + SE + +00-40-23 (hex) LOGIC CORPORATION +004023 (base 16) LOGIC CORPORATION + 3-14-10 MEIJI-SEIMEI BUILDING + + JP + +00-40-A4 (hex) ROSE ELECTRONICS +0040A4 (base 16) ROSE ELECTRONICS + P.O. BOX 742571 + HOUSTON TX 77274-2571 + US + +00-40-08 (hex) A PLUS INFO CORPORATION +004008 (base 16) A PLUS INFO CORPORATION + 5F, NO.2, LANE 235 + TAIWAN TAIWAN R.O.C. + TW + +00-40-B5 (hex) VIDEO TECHNOLOGY COMPUTERS LTD +0040B5 (base 16) VIDEO TECHNOLOGY COMPUTERS LTD + 33/F., BLOCK #1, + N.T. HONG KONG + HK + +00-40-12 (hex) WINDATA, INC. +004012 (base 16) WINDATA, INC. + 10 BEARFOOT ROAD + NORTHBORO MA 01532 + US + +00-40-D5 (hex) Sartorius Mechatronics T&H GmbH +0040D5 (base 16) Sartorius Mechatronics T&H GmbH + WEENDER LANDSTR: 94 - 108 + + DE + +00-40-10 (hex) SONIC SYSTEMS, INC. +004010 (base 16) SONIC SYSTEMS, INC. + 575 PASTORIA NORTH AVENUE + SUNNYVALE CA 940867 + US + +00-40-CA (hex) FIRST INTERNAT'L COMPUTER, INC +0040CA (base 16) FIRST INTERNAT'L COMPUTER, INC + FIC Building + Neihu Taipei 114 Taipei 114 + TW + +00-40-C4 (hex) KINKEI SYSTEM CORPORATION +0040C4 (base 16) KINKEI SYSTEM CORPORATION + 1-22-17, KAMIKITA, HIRANOKU + + JP + +00-40-5D (hex) STAR-TEK, INC. +00405D (base 16) STAR-TEK, INC. + 71 LYMAN STREET + NORTHBORO MA 01532 + US + +00-40-E2 (hex) MESA RIDGE TECHNOLOGIES, INC. +0040E2 (base 16) MESA RIDGE TECHNOLOGIES, INC. + 6725 MESA RIDGE ROAD-STE#100 + SAN DIEGO CA 92121 + US + +00-40-8C (hex) AXIS COMMUNICATIONS AB +00408C (base 16) AXIS COMMUNICATIONS AB + SCHEELEVAGEN 16 + + SE + +00-40-45 (hex) TWINHEAD CORPORATION +004045 (base 16) TWINHEAD CORPORATION + 1537 CENTRE POINTE DRIVE + MILPITAS CA 95035 + US + +00-40-28 (hex) NETCOMM LIMITED +004028 (base 16) NETCOMM LIMITED + 3 OLYMPIC BUSINESS CENTRE + UNITED KINGDOM + GB + +00-40-DD (hex) HONG TECHNOLOGIES +0040DD (base 16) HONG TECHNOLOGIES + 532 WEDDELL DRIVE + SUNNYVALE CA 94089 + US + +00-40-CB (hex) LANWAN TECHNOLOGIES +0040CB (base 16) LANWAN TECHNOLOGIES + 1566 LA PRADERA DRIVE + CAMPBELL CA 95008 + US + +00-40-B2 (hex) SYSTEMFORSCHUNG +0040B2 (base 16) SYSTEMFORSCHUNG + KONIGSTRASSE 33A + + DE + +00-40-E6 (hex) C.A.E.N. +0040E6 (base 16) C.A.E.N. + 2, CHEMIN LATERAL + + FR + +00-40-F0 (hex) MicroBrain,Inc. +0040F0 (base 16) MicroBrain,Inc. + Yuzan Bldg. 4F, + Aichi-gun AICHI 480-1117 + JP + +00-40-89 (hex) MEIDENSHA CORPORATION +004089 (base 16) MEIDENSHA CORPORATION + FACTORY NO.4, 515 KAMINAKAMIZO + + JP + +00-40-15 (hex) ASCOM INFRASYS AG +004015 (base 16) ASCOM INFRASYS AG + DPT. EASO 3726 + + CH + +00-80-95 (hex) BASIC MERTON HANDELSGES.M.B.H. +008095 (base 16) BASIC MERTON HANDELSGES.M.B.H. + DURCHLASS-STRASSE 42 + + AT + +00-80-AE (hex) HUGHES NETWORK SYSTEMS +0080AE (base 16) HUGHES NETWORK SYSTEMS + 11717 EXPLORATION LANE + GERMANTOWN MD 20876 + US + +00-80-3A (hex) VARITYPER, INC. +00803A (base 16) VARITYPER, INC. + 900 MIDDLESEX TURNPIKE + BILLERICA MA 01821 + US + +00-80-1C (hex) NEWPORT SYSTEMS SOLUTIONS +00801C (base 16) NEWPORT SYSTEMS SOLUTIONS + 4019 WESTERLY AVENUE + NEWPORT BEACH CA 92660 + US + +00-80-56 (hex) SPHINX Electronics GmbH & Co KG +008056 (base 16) SPHINX Electronics GmbH & Co KG + Tullastr. 3 + + DE + +00-80-31 (hex) BASYS, CORP. +008031 (base 16) BASYS, CORP. + 501 MACARA AVENUE + SUNNYVALE CA 94086 + US + +00-80-DB (hex) GRAPHON CORPORATION +0080DB (base 16) GRAPHON CORPORATION + 1506 DELL AVE - # + CAMPBELL CA 95008-6911 + VE + +00-80-82 (hex) PEP MODULAR COMPUTERS GMBH +008082 (base 16) PEP MODULAR COMPUTERS GMBH + APFELSTRANGER STR. 16 + WEST + DE + +00-80-39 (hex) ALCATEL STC AUSTRALIA +008039 (base 16) ALCATEL STC AUSTRALIA + 252-280 BOTANY ROAD + + AU + +00-80-23 (hex) INTEGRATED BUSINESS NETWORKS +008023 (base 16) INTEGRATED BUSINESS NETWORKS + 1BN THE SYSTEMS CENTRE + BUCKS HP19 3XN - ENGLAND + GB + +00-80-6B (hex) SCHMID TELECOMMUNICATION +00806B (base 16) SCHMID TELECOMMUNICATION + BINZSTRASSE 35, + + CH + +00-80-59 (hex) STANLEY ELECTRIC CO., LTD +008059 (base 16) STANLEY ELECTRIC CO., LTD + R&D LABORATORY + + JP + +00-80-41 (hex) VEB KOMBINAT ROBOTRON +008041 (base 16) VEB KOMBINAT ROBOTRON + GRUNAER STRAßE 2, DRESDEN 8010 + GDR EAST + DE + +00-80-80 (hex) DATAMEDIA CORPORATION +008080 (base 16) DATAMEDIA CORPORATION + 7401 CENTRAL HIGHWAY + PENNSAUKEN NJ 08109 + US + +00-80-3F (hex) TATUNG COMPANY +00803F (base 16) TATUNG COMPANY + 22 CHUNGSHANG N. RD. 3RD SEC. + TAIPEI TAIWAN R.O.C. + TW + +00-80-E6 (hex) PEER NETWORKS, INC. +0080E6 (base 16) PEER NETWORKS, INC. + 3350 SCOTT BLVD. BLDG. 14 + SANTA CLARA CA 95054 + US + +00-80-E0 (hex) XTP SYSTEMS, INC. +0080E0 (base 16) XTP SYSTEMS, INC. + 1900 STATE STREET , STE + SANTA BARBARA CA 93101 + US + +00-80-88 (hex) VICTOR COMPANY OF JAPAN, LTD. +008088 (base 16) VICTOR COMPANY OF JAPAN, LTD. + 58-7 SHINMEI-CHO, YOKOSUKA + + JP + +00-80-D8 (hex) NETWORK PERIPHERALS INC. +0080D8 (base 16) NETWORK PERIPHERALS INC. + 2890 ZONKER ROAD SUITE 209 + SAN JOSE CA 95134 + US + +00-80-9E (hex) DATUS GMBH +00809E (base 16) DATUS GMBH + INDUSTRIESTR. 2 + WEST + DE + +00-80-2B (hex) INTEGRATED MARKETING CO +00802B (base 16) INTEGRATED MARKETING CO + 1360 BORDEAUX DRIVE + SUNNYVALE CA 94089 + US + +00-80-01 (hex) PERIPHONICS CORPORATION +008001 (base 16) PERIPHONICS CORPORATION + 4000 VETERANS MEMORIAL HIGHWAY + BOHEMIA NEW YORK 11716 + US + +00-80-97 (hex) CENTRALP AUTOMATISMES +008097 (base 16) CENTRALP AUTOMATISMES + 21, RUE MARCEL PAGNOL 69694 + + FR + +00-80-71 (hex) SAI TECHNOLOGY +008071 (base 16) SAI TECHNOLOGY + 4224 CAMPUS POINT COURT + SAN DIEGO CA 92121-1513 + US + +00-80-98 (hex) TDK CORPORATION +008098 (base 16) TDK CORPORATION + CORP. R&D DEPT. TECH. HDQTERS. + CHIBA-KEN 272, + JP + +00-80-CA (hex) NETCOM RESEARCH INCORPORATED +0080CA (base 16) NETCOM RESEARCH INCORPORATED + 201 TECHNOLOGY DRIVE + IRVINE CA 92718 + US + +00-80-D5 (hex) CADRE TECHNOLOGIES +0080D5 (base 16) CADRE TECHNOLOGIES + 19545 NW VON NEUMANN DRIVE + BEAVERTON OR 97006 + VU + +00-80-1B (hex) KODIAK TECHNOLOGY +00801B (base 16) KODIAK TECHNOLOGY + 2340 HARRIS WAY + SAN JOSE CA 95131 + US + +00-80-D3 (hex) SHIVA CORP. +0080D3 (base 16) SHIVA CORP. + 205 BURLINGTON ROAD + BEDFORD MA 01730 + US + +00-80-B3 (hex) AVAL DATA CORPORATION +0080B3 (base 16) AVAL DATA CORPORATION + MACHIDA ENGINEERING CENTER + + JP + +00-80-E7 (hex) Leonardo Tactical Systems. +0080E7 (base 16) Leonardo Tactical Systems. + Silvertree, Coxbridge Business Park + Alton Road, Farnham GU10 5EH + GB + +00-80-20 (hex) NETWORK PRODUCTS +008020 (base 16) NETWORK PRODUCTS + DIVISION OF ANDREW CORPORATION + TORRANCE CA 90503 + US + +00-80-70 (hex) COMPUTADORAS MICRON +008070 (base 16) COMPUTADORAS MICRON + GUERRERO 2001 - 19 + + MX + +00-80-08 (hex) DYNATECH COMPUTER SYSTEMS +008008 (base 16) DYNATECH COMPUTER SYSTEMS + 280 BERNARDO AVENUE + MOUNTAIN VIEW CA 94039-7400 + US + +00-00-E4 (hex) IN2 GROUPE INTERTECHNIQUE +0000E4 (base 16) IN2 GROUPE INTERTECHNIQUE + IN2 - B.P.63 + + FR + +00-80-13 (hex) THOMAS-CONRAD CORPORATION +008013 (base 16) THOMAS-CONRAD CORPORATION + 1908-R KRAMER LANE + AUSTIN TX 78758 + US + +00-80-6E (hex) NIPPON STEEL CORPORATION +00806E (base 16) NIPPON STEEL CORPORATION + 31-1 SHINKAWA 2-CHOUME + + JP + +00-80-10 (hex) COMMODORE INTERNATIONAL +008010 (base 16) COMMODORE INTERNATIONAL + 1200 WILSON DRIVE + WEST CHESTER PA 19380 + US + +00-80-47 (hex) IN-NET CORP. +008047 (base 16) IN-NET CORP. + 16720 WEST BERNARDO DRIVE + SAN DIEGO CA 92127-1904 + US + +00-80-67 (hex) SQUARE D COMPANY +008067 (base 16) SQUARE D COMPANY + 4041 NORTH RICHARD STREET + MILWAUKEE WI 53201 + US + +00-80-45 (hex) MATSUSHITA ELECTRIC IND. CO +008045 (base 16) MATSUSHITA ELECTRIC IND. CO + COMPUTER DIVISION + OSAKA 571 + JP + +00-80-BF (hex) TAKAOKA ELECTRIC MFG. CO. LTD. +0080BF (base 16) TAKAOKA ELECTRIC MFG. CO. LTD. + KANDA BRANCH OFFICE TONEN + + JP + +00-80-F9 (hex) HEURIKON CORPORATION +0080F9 (base 16) HEURIKON CORPORATION + 8310 EXCELSIOR DRIVE + MADISON WI 53717 + US + +00-80-A1 (hex) MICROTEST, INC. +0080A1 (base 16) MICROTEST, INC. + 4747 N. 22ND STREET + PHOENIX AZ 85016-4708 + US + +00-80-A9 (hex) CLEARPOINT RESEARCH +0080A9 (base 16) CLEARPOINT RESEARCH + 190 NORTH MAIN STREET + NATICK MA + US + +00-80-17 (hex) PFU LIMITED +008017 (base 16) PFU LIMITED + Nu 98-2 Unoke + Kahoku-shi, Ishikawa 929-1192 + JP + +00-80-F8 (hex) MIZAR, INC. +0080F8 (base 16) MIZAR, INC. + 1419 DUNN DRIVE + CARROLLTON TX 75006 + US + +00-00-14 (hex) NETRONIX +000014 (base 16) NETRONIX + 1372 MCDOWELL BLVD. + PETULAMA CA 94952 + US + +00-00-72 (hex) MINIWARE TECHNOLOGY +000072 (base 16) MINIWARE TECHNOLOGY + BEEMDENSTRAAT 38 + THE + NL + +00-00-A1 (hex) MARQUETTE ELECTRIC CO. +0000A1 (base 16) MARQUETTE ELECTRIC CO. + 8200 WEST TOWER AVENUE + MILWAUKEE WI 53223 + US + +00-00-F5 (hex) DIAMOND SALES LIMITED +0000F5 (base 16) DIAMOND SALES LIMITED + 17, CHARTERHOUSE STREET + UNITED KINGDOM + GB + +00-00-5C (hex) TELEMATICS INTERNATIONAL INC. +00005C (base 16) TELEMATICS INTERNATIONAL INC. + 1201 CYPRESS CREEK RD + FT. LAUDERDALE FL 33309 + US + +00-00-AC (hex) CONWARE COMPUTER CONSULTING +0000AC (base 16) CONWARE COMPUTER CONSULTING + KILLISFELDSTRAßE 64 + + DE + +00-00-94 (hex) ASANTE TECHNOLOGIES +000094 (base 16) ASANTE TECHNOLOGIES + 821 FOX LANE + SAN JOSE CA 95131 + US + +00-00-90 (hex) MICROCOM +000090 (base 16) MICROCOM + 500 RIVER RIDGE DRIVE + NORWOOD MA 02062-5028 + US + +00-00-47 (hex) NICOLET INSTRUMENTS CORP. +000047 (base 16) NICOLET INSTRUMENTS CORP. + 5225 VERONA ROAD + MADISON WI 53711 + US + +00-00-21 (hex) SUREMAN COMP. & COMMUN. CORP. +000021 (base 16) SUREMAN COMP. & COMMUN. CORP. + 10F-5 NO. 7, SEC. 3 + TAIPEI TAIWAN, R.O.C. + TW + +00-00-30 (hex) VG LABORATORY SYSTEMS LTD +000030 (base 16) VG LABORATORY SYSTEMS LTD + TRIBUNE AVENUE + ENGLAND + GB + +00-00-35 (hex) SPECTRAGRAPHICS CORPORATION +000035 (base 16) SPECTRAGRAPHICS CORPORATION + OR + SAN DIEGO CA 92121 + US + +00-00-26 (hex) SHA-KEN CO., LTD. +000026 (base 16) SHA-KEN CO., LTD. + MINAMI-OTSUKA + TOKYO + JP + +00-00-B6 (hex) MICRO-MATIC RESEARCH +0000B6 (base 16) MICRO-MATIC RESEARCH + AMBACHTENLAAN 21 B5 + + BE + +00-00-82 (hex) LECTRA SYSTEMES SA +000082 (base 16) LECTRA SYSTEMES SA + CHEMIN DE MARTICOT + + FR + +00-00-2B (hex) CRISP AUTOMATION, INC +00002B (base 16) CRISP AUTOMATION, INC + 5160 BLAZER PARKWAY + DUBLIN OH 43017 + US + +00-00-51 (hex) HOB ELECTRONIC GMBH & CO. KG +000051 (base 16) HOB ELECTRONIC GMBH & CO. KG + BRANDSSTATTER-STR.2-10 + + DE + +00-00-A7 (hex) NETWORK COMPUTING DEVICES INC. +0000A7 (base 16) NETWORK COMPUTING DEVICES INC. + 350 NORTH BERNARDO + MOUNTAIN VIEW CA 94043 + US + +00-00-98 (hex) CROSSCOMM CORPORATION +000098 (base 16) CROSSCOMM CORPORATION + 450 DONALD LYNCH BOULEVARD + MARLBOROUGH MA 01752 + US + +00-00-C6 (hex) EON SYSTEMS +0000C6 (base 16) EON SYSTEMS + 10601 SOUTH DEANZA BLVD. + CUPERTINO CA 95014 + US + +00-00-70 (hex) HCL LIMITED +000070 (base 16) HCL LIMITED + RESEARCH & DEVELOPMENT UNIT + + IN + +00-00-8F (hex) Raytheon +00008F (base 16) Raytheon + M/S 1-1-1119 + Marlboro MA 01752 + US + +00-00-F1 (hex) MAGNA COMPUTER CORPORATION +0000F1 (base 16) MAGNA COMPUTER CORPORATION + 22 KEEWAYDIN DRIVE + SALEM NH 03079 + US + +00-00-54 (hex) Schneider Electric +000054 (base 16) Schneider Electric + 35 rue Joseph Monier + + FR + +00-00-20 (hex) DATAINDUSTRIER DIAB AB +000020 (base 16) DATAINDUSTRIER DIAB AB + BOX 2029 + + SE + +00-00-7A (hex) DANA COMPUTER INC. +00007A (base 16) DANA COMPUTER INC. + 550 DEL REY AVENUE + SUNNYVALE CA 94086 + US + +00-00-45 (hex) FORD AEROSPACE & COMM. CORP. +000045 (base 16) FORD AEROSPACE & COMM. CORP. + COLORADO SPRINGS OPERATION + COLORADO SPRINGS CO 80908 + US + +00-00-9C (hex) ROLM MIL-SPEC COMPUTERS +00009C (base 16) ROLM MIL-SPEC COMPUTERS + 3151 ZANKER ROAD + SAN JOSE CA 95148 + US + +00-00-7C (hex) AMPERE INCORPORATED +00007C (base 16) AMPERE INCORPORATED + SHINJUKU ASAHI BLDG. + TOKYO + JP + +00-00-68 (hex) ROSEMOUNT CONTROLS +000068 (base 16) ROSEMOUNT CONTROLS + 1300 E. LAMBERT ROAD + LA HABRA CA 90632 + US + +00-00-E9 (hex) ISICAD, INC. +0000E9 (base 16) ISICAD, INC. + 1920 WEST CORPORATE WAY + ANAHEIM CA 92803-6122 + US + +00-00-9F (hex) AMERISTAR TECHNOLOGIES INC. +00009F (base 16) AMERISTAR TECHNOLOGIES INC. + 47 WHITTIER AVE. + MEDFORD NY 11763 + US + +00-00-E3 (hex) INTEGRATED MICRO PRODUCTS LTD +0000E3 (base 16) INTEGRATED MICRO PRODUCTS LTD + IMP, NO. 1 INDUSTRIAL ESTATE + ENGLAND ENGLAND DH86TJ + GB + +00-00-AD (hex) BRUKER INSTRUMENTS INC. +0000AD (base 16) BRUKER INSTRUMENTS INC. + MANNING PARK + BILLERICA MA 01821 + US + +00-00-74 (hex) RICOH COMPANY LTD. +000074 (base 16) RICOH COMPANY LTD. + 2446 TODA, ATSUGI CITY + 243 + JP + +00-00-46 (hex) OLIVETTI NORTH AMERICA +000046 (base 16) OLIVETTI NORTH AMERICA + E 22425 APPLEWAY + LIBERTY LAKE WA 99019 + US + +00-00-8D (hex) Cryptek Inc. +00008D (base 16) Cryptek Inc. + 1501 Moran Road + Sterling VA 20166 + US + +00-00-3B (hex) i Controls, Inc. +00003B (base 16) i Controls, Inc. + 12F Doonsan building, 105-7 + KOREA 135-714 + KR + +00-00-B3 (hex) CIMLINC INCORPORATED +0000B3 (base 16) CIMLINC INCORPORATED + 1957 CROOKS ROAD + TROY MI 48084 + US + +00-00-D3 (hex) WANG LABORATORIES INC. +0000D3 (base 16) WANG LABORATORIES INC. + + + + +00-00-D0 (hex) DEVELCON ELECTRONICS LTD. +0000D0 (base 16) DEVELCON ELECTRONICS LTD. + 856-51ST STREET EAST + + CA + +00-00-93 (hex) PROTEON INC. +000093 (base 16) PROTEON INC. + 4 TECH CIRCLE + NATICK MA 01760 + US + +00-00-8B (hex) INFOTRON +00008B (base 16) INFOTRON + 9 NORTH OLNEY + CHERRY HILL NJ 08003 + US + +08-00-57 (hex) Evans & Sutherland +080057 (base 16) Evans & Sutherland + + Salt Lake City UT + US + +08-00-5D (hex) GOULD INC. +08005D (base 16) GOULD INC. + 6901 WEST SUNRISE BLVD. + FT. LAUDERDALE FL 33310-9148 + US + +08-00-5B (hex) VTA TECHNOLOGIES INC. +08005B (base 16) VTA TECHNOLOGIES INC. + 2040 SHERMAN STREET + HOLLYWOOD FL 33020 + US + +08-00-71 (hex) MATRA (DSIE) +080071 (base 16) MATRA (DSIE) + PARC D'AFFAIRES - B.P. 262 + + FR + +08-00-6C (hex) SUNTEK TECHNOLOGY INT'L +08006C (base 16) SUNTEK TECHNOLOGY INT'L + 586 NO. FIRST STREET + SAN JOSE CA 95112 + US + +08-00-67 (hex) ComDesign +080067 (base 16) ComDesign + + Goleta CA + US + +08-00-8C (hex) NETWORK RESEARCH CORPORATION +08008C (base 16) NETWORK RESEARCH CORPORATION + 2380 N. ROSE AVENUE + OXNARD CA 93010 + US + +08-00-81 (hex) ASTECH INC. +080081 (base 16) ASTECH INC. + 670 NORTH COMMERCIAL STREET + MANCHESTER NH 03101 + US + +08-00-2D (hex) LAN-TEC INC. +08002D (base 16) LAN-TEC INC. + 2131 UNIVERSITY AVENUE + BERKELEY CA 94704 + US + +00-DD-00 (hex) UNGERMANN-BASS INC. +00DD00 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +00-00-AA (hex) XEROX CORPORATION +0000AA (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +04-0A-E0 (hex) XMIT AG COMPUTER NETWORKS +040AE0 (base 16) XMIT AG COMPUTER NETWORKS + 11 AVENUE DE BAUMETTES + + CH + +08-00-11 (hex) TEKTRONIX INC. +080011 (base 16) TEKTRONIX INC. + TECHNICAL STANDARDS + BEAVERTON OR 97077 + US + +08-00-26 (hex) NORSK DATA A.S. +080026 (base 16) NORSK DATA A.S. + P.O. BOX 25 BOGERUD + + NO + +08-00-25 (hex) CONTROL DATA +080025 (base 16) CONTROL DATA + 4201 LEXINGTON AVE NORTH + ARDEN HILLS MN 55112 + US + +10-00-00 (hex) Private +100000 (base 16) Private + +00-00-D7 (hex) DARTMOUTH COLLEGE +0000D7 (base 16) DARTMOUTH COLLEGE + KIEWIT COMPUTER CENTER + HANOVER NH 03755 + US + +AA-00-04 (hex) DIGITAL EQUIPMENT CORPORATION +AA0004 (base 16) DIGITAL EQUIPMENT CORPORATION + LKG 1-2/A19 + LITTLETON MA 01460-1289 + US + +08-00-0C (hex) MIKLYN DEVELOPMENT CO. +08000C (base 16) MIKLYN DEVELOPMENT CO. + 3613 ANDOVER DIVE + BEDFORD TX 76021 + US + +00-DD-05 (hex) UNGERMANN-BASS INC. +00DD05 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +08-00-1D (hex) ABLE COMMUNICATIONS INC. +08001D (base 16) ABLE COMMUNICATIONS INC. + 17891 CARTWRIGHT ROAD + IRVINE CA 92714-6216 + US + +00-DD-0B (hex) UNGERMANN-BASS INC. +00DD0B (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +08-00-03 (hex) ADVANCED COMPUTER COMM. +080003 (base 16) ADVANCED COMPUTER COMM. + 720 SANTA BARBARA ST. + SANTA BARBARA CA 93101 + US + +00-DD-03 (hex) UNGERMANN-BASS INC. +00DD03 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +00-DD-0F (hex) UNGERMANN-BASS INC. +00DD0F (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +00-00-01 (hex) XEROX CORPORATION +000001 (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +08-00-17 (hex) NATIONAL SEMICONDUCTOR +080017 (base 16) NATIONAL SEMICONDUCTOR + 2900 SEMICONDUCTOR DRIVE + SANTA CLARA CA 95051 + US + +54-21-60 (hex) Alula +542160 (base 16) Alula + 2340 Energy Park Drive + St. Paul MN 55108 + US + +10-B3-C6 (hex) Cisco Systems, Inc +10B3C6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +10-B3-D6 (hex) Cisco Systems, Inc +10B3D6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +58-96-30 (hex) Technicolor CH USA Inc. +589630 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +F8-54-B8 (hex) Amazon Technologies Inc. +F854B8 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +78-17-35 (hex) Nokia Shanghai Bell Co., Ltd. +781735 (base 16) Nokia Shanghai Bell Co., Ltd. + No.388 Ning Qiao Road,Jin Qiao Pudong Shanghai + Shanghai 201206 + CN + +3C-89-4D (hex) Dr. Ing. h.c. F. Porsche AG +3C894D (base 16) Dr. Ing. h.c. F. Porsche AG + Porscheplatz 1 + Stuttgart 70435 + DE + +84-C8-07 (hex) ADVA Optical Networking Ltd. +84C807 (base 16) ADVA Optical Networking Ltd. + ADVAntage House + York YO30 4RY + GB + +B4-39-39 (hex) Shenzhen TINNO Mobile Technology Corp. +B43939 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F, H-3 Building, Qiao Cheng Eastern Industrial Park, Overseas Chinese Town, Shenzhen + Shenzhen guangdong 518053 + CN + +5C-CD-5B (hex) Intel Corporate +5CCD5B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A0-AB-51 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +A0AB51 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Gaoxin 2 Road, Free Trade Zone,Weifang,Shandong,261205,P.R.China + Weifang Shandong 261205 + CN + +64-C9-01 (hex) INVENTEC Corporation +64C901 (base 16) INVENTEC Corporation + No.66, Hougang St., Shilin Dist., Taipei City 111, Taiwan (R.O.C.) + Taipei 111 + TW + +74-9E-F5 (hex) Samsung Electronics Co.,Ltd +749EF5 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +68-BF-C4 (hex) Samsung Electronics Co.,Ltd +68BFC4 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A8-5E-45 (hex) ASUSTek COMPUTER INC. +A85E45 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +84-9A-40 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +849A40 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +04-B1-A1 (hex) Samsung Electronics Co.,Ltd +04B1A1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +CC-46-4E (hex) Samsung Electronics Co.,Ltd +CC464E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F8-89-3C (hex) Inventec Appliances Corp. +F8893C (base 16) Inventec Appliances Corp. + 37 Wugong 5th road, New Taipei Industrial Park, + New Taipei City Wugu District 24890 + TW + +A0-DF-15 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A0DF15 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-AD-34 (hex) Routerboard.com +C4AD34 (base 16) Routerboard.com + Mikrotikls SIA + Riga Riga LV1009 + LV + +30-6F-07 (hex) Nations Technologies Inc. +306F07 (base 16) Nations Technologies Inc. + 18F, Nations Tower, Nanshan District + Shenzhen 518057 + CN + +24-74-F7 (hex) GoPro +2474F7 (base 16) GoPro + 3000 Clearview Way + San Mateo CA 94402 + US + +7C-D5-66 (hex) Amazon Technologies Inc. +7CD566 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +68-63-50 (hex) Hella India Automotive Pvt Ltd +686350 (base 16) Hella India Automotive Pvt Ltd + Unit no 201A to 201B Nano Space Surveyno.5/1B/2 BanerBaner Pashan Link road + Pune Maharastra 411045 + IN + +5C-E5-0C (hex) Beijing Xiaomi Mobile Software Co., Ltd +5CE50C (base 16) Beijing Xiaomi Mobile Software Co., Ltd + The Rainbow City Office Building, 68 Qinghe Middle Street Haidian District + Beijing Beijing 100085 + CN + +18-70-3B (hex) Huawei Device Co., Ltd. +18703B (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +D8-9E-61 (hex) Huawei Device Co., Ltd. +D89E61 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +34-7E-00 (hex) Huawei Device Co., Ltd. +347E00 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +00-30-92 (hex) Kontron Electronics AG +003092 (base 16) Kontron Electronics AG + Riedstrasse 1 + Rotkreuz CH-6343 + CH + +80-75-1F (hex) BSkyB Ltd +80751F (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +E8-5A-8B (hex) Xiaomi Communications Co Ltd +E85A8B (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +44-22-95 (hex) China Mobile Iot Limited company +442295 (base 16) China Mobile Iot Limited company + No. 8 Yangliu North Road, Yubei District, Chongqing, China + Chong Qing Chong Qing 401120 + CN + +98-AF-65 (hex) Intel Corporate +98AF65 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +5C-71-0D (hex) Cisco Systems, Inc +5C710D (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +00-AB-48 (hex) eero inc. +00AB48 (base 16) eero inc. + 660 3rd Street + San Francisco CA 94107 + US + +F8-55-CD (hex) Visteon Corporation +F855CD (base 16) Visteon Corporation + One Village Center Drive + Van Buren Twp MI 48111 + US + +44-18-47 (hex) HUNAN SCROWN ELECTRONIC INFORMATION TECH.CO.,LTD +441847 (base 16) HUNAN SCROWN ELECTRONIC INFORMATION TECH.CO.,LTD + Building No.4,Changsha Zhongdian Software Park No.39,Jianshan Road + Changsha Hunan 410006 + CN + +1C-C1-BC (hex) Yichip Microelectronics (Hangzhou) Co.,Ltd +1CC1BC (base 16) Yichip Microelectronics (Hangzhou) Co.,Ltd + Room 401, Building 15, No.498 Guoshoujing Road, Pudong Software Park + Shanghai 200120 + CN + +AC-61-B9 (hex) WAMA Technology Limited +AC61B9 (base 16) WAMA Technology Limited + Room 2205, Westley Square, 48 Hoi Yuen Road, Kwun Tong, Kowloon + Hong Kong 00000 + HK + +C4-D8-F3 (hex) iZotope +C4D8F3 (base 16) iZotope + 60 Hampshire St + Cambridge MA 02139 + US + +00-30-56 (hex) HMS Industrial Networks +003056 (base 16) HMS Industrial Networks + P O Box 4126 + Halmstad Halland 300 04 + SE + +68-0A-E2 (hex) Silicon Laboratories +680AE2 (base 16) Silicon Laboratories + 7000 W. William Cannon Dr. + Austin TX 78735 + US + +AC-8B-9C (hex) Primera Technology, Inc. +AC8B9C (base 16) Primera Technology, Inc. + 2 Carlson Parkway N, Ste 375 + Plymouth MN 55447 + US + +2C-3A-FD (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +2C3AFD (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +34-49-5B (hex) Sagemcom Broadband SAS +34495B (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +C8-F3-19 (hex) LG Electronics (Mobile Communications) +C8F319 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +80-16-09 (hex) Sleep Number +801609 (base 16) Sleep Number + 1001 Third Avenue South + Minneapolis MN 55404 + US + +04-5E-A4 (hex) SHENZHEN NETIS TECHNOLOGY CO.,LTD +045EA4 (base 16) SHENZHEN NETIS TECHNOLOGY CO.,LTD + Building 6, Baolong Plant, Able Technology Park, Longgang District + SHENZHEN 518116 + CN + +1C-BF-C0 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +1CBFC0 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +78-B4-6A (hex) HUAWEI TECHNOLOGIES CO.,LTD +78B46A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +6C-EB-B6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +6CEBB6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +4C-F5-5B (hex) HUAWEI TECHNOLOGIES CO.,LTD +4CF55B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E8-3F-67 (hex) Huawei Device Co., Ltd. +E83F67 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +34-46-EC (hex) Huawei Device Co., Ltd. +3446EC (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +64-31-39 (hex) IEEE Registration Authority +643139 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +A4-4B-D5 (hex) Xiaomi Communications Co Ltd +A44BD5 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +64-95-6C (hex) LG Electronics +64956C (base 16) LG Electronics + 222 LG-ro, JINWI-MYEON + Pyeongtaek-si Gyeonggi-do 451-713 + KR + +14-87-6A (hex) Apple, Inc. +14876A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-B5-5F (hex) Apple, Inc. +E0B55F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-FF-C2 (hex) Apple, Inc. +F8FFC2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-EB-40 (hex) Apple, Inc. +E0EB40 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-A6-B7 (hex) Intel Corporate +40A6B7 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +64-69-4E (hex) Texas Instruments +64694E (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +0C-7A-15 (hex) Intel Corporate +0C7A15 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +94-D6-DB (hex) NexFi +94D6DB (base 16) NexFi + Room 417, Building 14, No. 498, Guoshoujing Road, Pudong New Area + Shanghai 201203 + CN + +B4-EC-F2 (hex) Shanghai Listent Medical Tech Co., Ltd. +B4ECF2 (base 16) Shanghai Listent Medical Tech Co., Ltd. + No. 668 Qingdai Road Pudong District + Shanghai Shanghai 201318 + CN + +18-E7-77 (hex) vivo Mobile Communication Co., Ltd. +18E777 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +40-77-A9 (hex) New H3C Technologies Co., Ltd +4077A9 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +F8-33-31 (hex) Texas Instruments +F83331 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +C4-95-4D (hex) IEEE Registration Authority +C4954D (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +C4-98-78 (hex) SHANGHAI MOAAN INTELLIGENT TECHNOLOGY CO.,LTD +C49878 (base 16) SHANGHAI MOAAN INTELLIGENT TECHNOLOGY CO.,LTD + BLOCK B, 4TH FLOOR, BUILDING 2, NO. 401 CAOBAO ROAD, XUHUI DISTRICT, SHANGHAI + SHANGHAI 200030 + CN + +6C-63-9C (hex) ARRIS Group, Inc. +6C639C (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +5C-2A-EF (hex) r2p Asia-Pacific Pty Ltd +5C2AEF (base 16) r2p Asia-Pacific Pty Ltd + 65 Epping Road + Sydney NSW 2113 + AU + +A4-BB-6D (hex) Dell Inc. +A4BB6D (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +6C-06-D6 (hex) Huawei Device Co., Ltd. +6C06D6 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +0C-8E-29 (hex) Arcadyan Corporation +0C8E29 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +A0-22-4E (hex) IEEE Registration Authority +A0224E (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +30-27-CF (hex) Private +3027CF (base 16) Private + +54-8D-5A (hex) Intel Corporate +548D5A (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +38-43-E5 (hex) Grotech Inc +3843E5 (base 16) Grotech Inc + 19, Ojeongongeop-gil + Uiwang-si Gyeonggi-do 16072 + KR + +CC-59-3E (hex) Sensium Healthcare Limited +CC593E (base 16) Sensium Healthcare Limited + 115 MILTON PARK + ABINGDON OXFORDSHIRE OX14 4SA + GB + +5C-68-D0 (hex) Aurora Innovation Inc. +5C68D0 (base 16) Aurora Innovation Inc. + 1880 Embarcadero Rd. + Palo Alto CA 94303 + US + +10-36-4A (hex) Boston Dynamics +10364A (base 16) Boston Dynamics + 78 4TH AVE + Waltham MA 02451 + US + +00-B8-10 (hex) Yichip Microelectronics (Hangzhou) Co.,Ltd +00B810 (base 16) Yichip Microelectronics (Hangzhou) Co.,Ltd + Room 401, Building 15, No.498 Guoshoujing Road, Pudong Software Park + Shanghai 200120 + CN + +A4-B2-39 (hex) Cisco Systems, Inc +A4B239 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D8-D5-B9 (hex) Rainforest Automation, Inc. +D8D5B9 (base 16) Rainforest Automation, Inc. + 827 Cambie St. + Vancouver British Columbia V6B 2P4 + CA + +00-1B-B0 (hex) Bharat Electronics Limited +001BB0 (base 16) Bharat Electronics Limited + JALAHALLI POST + BANGALORE KARNATAKA 560013 + IN + +58-96-1D (hex) Intel Corporate +58961D (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +68-AF-FF (hex) Shanghai Cambricon Information Technology Co., Ltd. +68AFFF (base 16) Shanghai Cambricon Information Technology Co., Ltd. + 888 West Huanhu Road No.2, Nanhui New Town, Pudong New Area + Shanghai Shanghai 200000 + CN + +DC-21-E2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +DC21E2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +FC-1B-D1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +FC1BD1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +58-25-75 (hex) HUAWEI TECHNOLOGIES CO.,LTD +582575 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +28-DE-E5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +28DEE5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D0-1C-3C (hex) TECNO MOBILE LIMITED +D01C3C (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +18-C0-4D (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +18C04D (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + Pin-Jen City, Taoyuan, Taiwan, R.O.C. + Pin-Jen Taoyuan 324 + TW + +8C-AA-B5 (hex) Espressif Inc. +8CAAB5 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +B8-9A-2A (hex) Intel Corporate +B89A2A (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +40-2C-76 (hex) IEEE Registration Authority +402C76 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +44-C7-FC (hex) Huawei Device Co., Ltd. +44C7FC (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +78-85-F4 (hex) Huawei Device Co., Ltd. +7885F4 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +F4-49-55 (hex) MIMO TECH Co., Ltd. +F44955 (base 16) MIMO TECH Co., Ltd. + 21F.-6, No. 7, Sec. 3, New Taipei Blvd., Xinzhuang Dist., + New Taipei City Taiwan 24250 + TW + +08-09-C7 (hex) Zhuhai Unitech Power Technology Co., Ltd. +0809C7 (base 16) Zhuhai Unitech Power Technology Co., Ltd. + 102, Yinhua Road + Zhuhai Guangdong 519000 + CN + +88-54-1F (hex) Google, Inc. +88541F (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +90-0C-C8 (hex) Google, Inc. +900CC8 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +04-1D-C7 (hex) zte corporation +041DC7 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +68-21-5F (hex) Edgecore Networks Corporation +68215F (base 16) Edgecore Networks Corporation + 1 Creation RD 3. + Hsinchu 30077 + TW + +3C-28-A6 (hex) Alcatel-Lucent Enterprise (China) +3C28A6 (base 16) Alcatel-Lucent Enterprise (China) + 2/F, Building 1, No.60 Naxian Road,Pudong + Shanghai Shanghai 201210 + CN + +50-50-A4 (hex) Samsung Electronics Co.,Ltd +5050A4 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +80-86-D9 (hex) Samsung Electronics Co.,Ltd +8086D9 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F4-17-B8 (hex) AirTies Wireless Networks +F417B8 (base 16) AirTies Wireless Networks + Esentepe Mah., Kore Şehitleri Cad. + Istanbul Şişli 34360 + TR + +3C-BF-60 (hex) Apple, Inc. +3CBF60 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-15-F4 (hex) Apple, Inc. +AC15F4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-6A-77 (hex) Samsung Electronics Co.,Ltd +386A77 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-14-59 (hex) Vodafone Italia S.p.A. +141459 (base 16) Vodafone Italia S.p.A. + Via Lorenteggio nr. 240 + Milan Italy 20147 + IT + +50-43-B9 (hex) OktoInform RUS +5043B9 (base 16) OktoInform RUS + Bolshoy Tishinskiy pereulok, d. 26, korp.13-14, ofis 4R + Moscow 123557 + RU + +5C-27-D4 (hex) Shenzhen Qihu Intelligent Technology Company Limited +5C27D4 (base 16) Shenzhen Qihu Intelligent Technology Company Limited + Room 201, Block A, No.1, Qianwan Road 1,Qianhai Shenzhen HongKong Modern Service Industry Cooperation Zone + Shenzhen Guangdong 518057 + CN + +74-D8-3E (hex) Intel Corporate +74D83E (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +08-D2-3E (hex) Intel Corporate +08D23E (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +88-A4-79 (hex) Apple, Inc. +88A479 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-72-95 (hex) Apple, Inc. +047295 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D4-46-E1 (hex) Apple, Inc. +D446E1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-D1-62 (hex) Apple, Inc. +78D162 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +08-F8-BC (hex) Apple, Inc. +08F8BC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-A2-5B (hex) Apple, Inc. +90A25B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-30-0C (hex) Hisense Electric Co.,Ltd +18300C (base 16) Hisense Electric Co.,Ltd + Qianwangang Roard 218 + Qingdao Shandong 266510 + CN + +44-A5-6E (hex) NETGEAR +44A56E (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +1C-91-9D (hex) Dongguan Liesheng Electronic Co., Ltd. +1C919D (base 16) Dongguan Liesheng Electronic Co., Ltd. + F5, Building B, North Block, Gaosheng Tech Park, No. 84 Zhongli Road, Nancheng District, Dongguan Ci + dongguan guangdong 523000 + CN + +FC-F2-9F (hex) China Mobile Iot Limited company +FCF29F (base 16) China Mobile Iot Limited company + No. 8 Yangliu North Road, Yubei District, Chongqing, China + Chong Qing Chong Qing 401120 + CN + +F8-1F-32 (hex) Motorola Mobility LLC, a Lenovo Company +F81F32 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +B0-0A-D5 (hex) zte corporation +B00AD5 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +A8-7E-EA (hex) Intel Corporate +A87EEA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +20-11-4E (hex) MeteRSit S.R.L. +20114E (base 16) MeteRSit S.R.L. + Viale dell'Industria 31 + Padova 35129 + IT + +2C-57-41 (hex) Cisco Systems, Inc +2C5741 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A8-4D-4A (hex) Audiowise Technology Inc. +A84D4A (base 16) Audiowise Technology Inc. + 2F, No 1-1, Innovation RD I, Hsinchu Science Park + Hsincu Taiwan 30076 + TW + +78-94-E8 (hex) Radio Bridge +7894E8 (base 16) Radio Bridge + 8601 73rd Ave N, Suite 38 + Brooklyn Park MN 55428 + US + +48-4E-FC (hex) ARRIS Group, Inc. +484EFC (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +B0-B3-53 (hex) IEEE Registration Authority +B0B353 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +54-7F-BC (hex) iodyne +547FBC (base 16) iodyne + 35 Miller Ave #175 + Mill Valley CA 94941 + US + +7C-DF-A1 (hex) Espressif Inc. +7CDFA1 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +98-00-6A (hex) zte corporation +98006A (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-26-74 (hex) Hunter Douglas +002674 (base 16) Hunter Douglas + One Duette Way + Broomfield CO 80020 + US + +1C-97-C5 (hex) Ynomia Pty Ltd +1C97C5 (base 16) Ynomia Pty Ltd + 153 Tooronga Rd + Glen Iris 3146 + AU + +5C-C1-D7 (hex) Samsung Electronics Co.,Ltd +5CC1D7 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +38-01-46 (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD +380146 (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD + NO.268? Fuqian Rd, Jutang community, Guanlan Town, Longhua New district + shenzhen guangdong 518000 + CN + +88-96-55 (hex) Zitte corporation +889655 (base 16) Zitte corporation + 4F Yokohama Kusunoki-cho Building,4-7 Kusunoki-cho,Nishi-ku + Yokohama Kanagawa 2200003 + JP + +F4-A4-D6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4A4D6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +FC-E1-4F (hex) BRK Brands, Inc. +FCE14F (base 16) BRK Brands, Inc. + 3901 Liberty Street + Aurora IL 60504 + US + +74-B6-B6 (hex) eero inc. +74B6B6 (base 16) eero inc. + 660 3rd Street + San Francisco CA 94107 + US + +EC-97-B2 (hex) SUMEC Machinery & Electric Co.,Ltd. +EC97B2 (base 16) SUMEC Machinery & Electric Co.,Ltd. + 198# ChangJiang Road, XuanWu District, 17F, SUMEC Building + Nanjing JiangSu 210018 + CN + +28-FA-7A (hex) Zhejiang Tmall Technology Co., Ltd. +28FA7A (base 16) Zhejiang Tmall Technology Co., Ltd. + Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District, Shenzhen Guangdong province + Shenzhen GuangDong 518000 + CN + +84-2E-14 (hex) Silicon Laboratories +842E14 (base 16) Silicon Laboratories + 7000 W. William Cannon Dr. + Austin TX 78735 + US + +10-05-E1 (hex) Nokia +1005E1 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +08-F4-58 (hex) Huawei Device Co., Ltd. +08F458 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +5C-BA-2C (hex) Hewlett Packard Enterprise +5CBA2C (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +34-37-94 (hex) Hamee Corp. +343794 (base 16) Hamee Corp. + Square O2 2-12-10 Sakae-cho + Odawara Kanagawa 250-0011 + JP + +40-EC-99 (hex) Intel Corporate +40EC99 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +6C-D9-4C (hex) vivo Mobile Communication Co., Ltd. +6CD94C (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +EC-31-6D (hex) Hansgrohe +EC316D (base 16) Hansgrohe + Auestraße 5-9 + Schiltach 77761 + DE + +BC-54-2F (hex) Intel Corporate +BC542F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +44-10-FE (hex) Huizhou Foryou General Electronics Co., Ltd. +4410FE (base 16) Huizhou Foryou General Electronics Co., Ltd. + North Shangxia Road, Dongjiang Hi-tech Industry Park + Huizhou Guangdong 516000 + CN + +7C-AB-60 (hex) Apple, Inc. +7CAB60 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +44-C6-5D (hex) Apple, Inc. +44C65D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-7E-B9 (hex) Apple, Inc. +187EB9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +4C-A6-4D (hex) Cisco Systems, Inc +4CA64D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +CC-7F-75 (hex) Cisco Systems, Inc +CC7F75 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +20-E8-74 (hex) Apple, Inc. +20E874 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-3F-AA (hex) Apple, Inc. +D03FAA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +0C-B9-37 (hex) Ubee Interactive Co., Limited +0CB937 (base 16) Ubee Interactive Co., Limited + Flat/RM 1202, 12/F, AT Tower + North Point Hong Kong 180 + HK + +D4-DC-09 (hex) Mist Systems, Inc. +D4DC09 (base 16) Mist Systems, Inc. + 1601 South De Anza Blvd, Suite 248 + Cupertino CA 95014 + US + +00-88-BA (hex) NC&C +0088BA (base 16) NC&C + Gurogu + Seoul 08390 + KR + +F4-73-35 (hex) Logitech Far East +F47335 (base 16) Logitech Far East + #2 Creation Rd. 4, + Hsinchu 300 + TW + +90-AD-FC (hex) Telechips, Inc. +90ADFC (base 16) Telechips, Inc. + 19F~23F,Luther Bldg.42, Olympic-ro 35da-gil, Songpa-gu, + Seoul Seoul 05510 + KR + +5C-A6-2D (hex) Cisco Systems, Inc +5CA62D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +40-2B-69 (hex) Kumho Electric Inc. +402B69 (base 16) Kumho Electric Inc. + 309, Bongmu-ro, Namsa-myeon, Cheoin-gu + Yongin-si Gyeonggi-do 17118 + KR + +E8-E9-8E (hex) SOLAR controls s.r.o. +E8E98E (base 16) SOLAR controls s.r.o. + Brojova 25 + Plzen 32600 + CZ + +64-F6-BB (hex) Fibocom Wireless Inc. +64F6BB (base 16) Fibocom Wireless Inc. + 5/F,TowerA,Technology Building 2,1057 Nanhai Blvd, Nanshan + Shenzhen 518000 Guangdong + CN + +BC-16-95 (hex) zte corporation +BC1695 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +DC-35-F1 (hex) Positivo Tecnologia S.A. +DC35F1 (base 16) Positivo Tecnologia S.A. + João Bettega, 5200 + Curitiba Paraná 81350-000 + BR + +A4-08-01 (hex) Amazon Technologies Inc. +A40801 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +AC-1E-D0 (hex) Temic Automotive Philippines Inc. +AC1ED0 (base 16) Temic Automotive Philippines Inc. + Bagsakan Road, FTI estate + Taguig 1630 + PH + +2C-EA-7F (hex) Dell Inc. +2CEA7F (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +34-51-80 (hex) TCL King Electrical Appliances (Huizhou) Co., Ltd +345180 (base 16) TCL King Electrical Appliances (Huizhou) Co., Ltd + 10F, TCL Multimedia Building, TCL International E City, No.1001 Zhongshanyuan Rd., Nanshan District + Shenzhen Guangdong 518052 + CN + +A4-CF-D2 (hex) Ubee Interactive Co., Limited +A4CFD2 (base 16) Ubee Interactive Co., Limited + Flat/RM 1202, 12/F, AT Tower, 180 Electric Road + North Point 00000 + HK + +A8-A0-97 (hex) ScioTeq bvba +A8A097 (base 16) ScioTeq bvba + President Kennedypark 35A + Kortrijk 8500 + BE + +08-6B-D1 (hex) Shenzhen SuperElectron Technology Co.,Ltd. +086BD1 (base 16) Shenzhen SuperElectron Technology Co.,Ltd. + 1213-1214, haosheng business center, dongbin road, nanshan street, nanshan district, shenzhen city + Shenzhen Guangdong 518000 + CN + +AC-3A-67 (hex) Cisco Systems, Inc +AC3A67 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +3C-B5-3D (hex) HUNAN GOKE MICROELECTRONICS CO.,LTD +3CB53D (base 16) HUNAN GOKE MICROELECTRONICS CO.,LTD + No.9, East 10th Road(South), Xingsha, Changsha + Changsha HUNAN 410131 + CN + +98-0D-51 (hex) Huawei Device Co., Ltd. +980D51 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +00-AD-D5 (hex) Huawei Device Co., Ltd. +00ADD5 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +90-5D-7C (hex) New H3C Technologies Co., Ltd +905D7C (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +98-FA-A7 (hex) INNONET +98FAA7 (base 16) INNONET + C-417, Munjeong Hyundai Knowledge Industry Center, Beobwon-ro 11-gil-7 + Songpa-gu Seoul 05836 + KR + +48-7B-5E (hex) SMT TELECOMM HK +487B5E (base 16) SMT TELECOMM HK + Unit C 8/F Charmhill Centre 50 Hillwood RD. + Tsim Sha Tsui Kowloon 999077 + HK + +B8-E3-B1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B8E3B1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-B7-A8 (hex) Heinzinger electronic GmbH +00B7A8 (base 16) Heinzinger electronic GmbH + Anton Jakob Str.4 + Rosenheim BY 83026 + DE + +34-CF-F6 (hex) Intel Corporate +34CFF6 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +EC-79-49 (hex) FUJITSU LIMITED +EC7949 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +D4-D2-D6 (hex) FN-LINK TECHNOLOGY LIMITED +D4D2D6 (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +10-50-72 (hex) Sercomm Corporation. +105072 (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +90-0A-84 (hex) Mellanox Technologies, Inc. +900A84 (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +AC-4A-67 (hex) Cisco Systems, Inc +AC4A67 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +70-CA-97 (hex) Ruckus Wireless +70CA97 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +30-B2-16 (hex) ABB Power Grids Germany AG – Grid Automation +30B216 (base 16) ABB Power Grids Germany AG – Grid Automation + Kallstadter Strasse 1 + Mannheim 68309 + DE + +00-09-91 (hex) Intelligent Platforms, LLC. +000991 (base 16) Intelligent Platforms, LLC. + 2500 Austin Drive + Charlottesville VA 22911 + US + +DC-33-3D (hex) Huawei Device Co., Ltd. +DC333D (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +28-54-71 (hex) Huawei Device Co., Ltd. +285471 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +B8-8E-82 (hex) Huawei Device Co., Ltd. +B88E82 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +08-87-C6 (hex) INGRAM MICRO SERVICES +0887C6 (base 16) INGRAM MICRO SERVICES + 100 CHEMIN DE BAILLOT + MONTAUBAN 82000 + FR + +D4-1D-71 (hex) Palo Alto Networks +D41D71 (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +08-66-1F (hex) Palo Alto Networks +08661F (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +BC-F3-10 (hex) Extreme Networks, Inc. +BCF310 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +C8-66-5D (hex) Extreme Networks, Inc. +C8665D (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +E0-1C-41 (hex) Extreme Networks, Inc. +E01C41 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +D8-54-A2 (hex) Extreme Networks, Inc. +D854A2 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +84-80-94 (hex) Meter, Inc. +848094 (base 16) Meter, Inc. + 148 Townsend St + San Francisco CA 94107 + US + +10-B3-D5 (hex) Cisco Systems, Inc +10B3D5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +30-A2-C2 (hex) Huawei Device Co., Ltd. +30A2C2 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +DC-DF-D6 (hex) zte corporation +DCDFD6 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +AC-A8-8E (hex) SHARP Corporation +ACA88E (base 16) SHARP Corporation + 1 Takumi-cho, Sakai-ku + Sakai City Osaka 590-8522 + JP + +98-41-5C (hex) Nintendo Co.,Ltd +98415C (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +F0-4F-7C (hex) Private +F04F7C (base 16) Private + +70-54-25 (hex) ARRIS Group, Inc. +705425 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +5C-0B-CA (hex) Tunstall Nordic AB +5C0BCA (base 16) Tunstall Nordic AB + Agnesfridsvagen 113A + Malmo 21237 + SE + +28-33-34 (hex) Huawei Device Co., Ltd. +283334 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +F0-A2-25 (hex) Private +F0A225 (base 16) Private + +50-A1-32 (hex) Shenzhen MiaoMing Intelligent Technology Co.,Ltd +50A132 (base 16) Shenzhen MiaoMing Intelligent Technology Co.,Ltd + Chudong science and technology park, 111 shaxin road, tangxia town, + dongguan city guangdong province 523710 + CN + +80-78-71 (hex) ASKEY COMPUTER CORP +807871 (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +4C-B1-CD (hex) Ruckus Wireless +4CB1CD (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +F4-9C-12 (hex) Structab AB +F49C12 (base 16) Structab AB + Slotsmöllan 14B + HALMSTAD 30231 + SE + +88-51-7A (hex) HMD Global Oy +88517A (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +AC-B3-B5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +ACB3B5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +08-3A-88 (hex) Universal Global Scientific Industrial Co., Ltd. +083A88 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, Lane 351, Taiping Road, Sec.1,Tsao Tuen + Nan-Tou Taiwan 54261 + TW + +08-31-8B (hex) HUAWEI TECHNOLOGIES CO.,LTD +08318B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-B6-88 (hex) PLANTRONICS, INC. +F4B688 (base 16) PLANTRONICS, INC. + 345 ENCINAL STREET + SANTA CRUZ CA 95060 + US + +4C-7A-48 (hex) Nippon Seiki (Europe) B.V. +4C7A48 (base 16) Nippon Seiki (Europe) B.V. + Antareslaan 27 + Hoofddorp 2132 + NL + +84-D1-5A (hex) TCT mobile ltd +84D15A (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +04-7F-0E (hex) Barrot Technology Limited +047F0E (base 16) Barrot Technology Limited + C7-1-1,East Area, No.2,Shangdi Xinxi Road, Haidian District + Beijing 100085 + CN + +B8-F6-53 (hex) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd +B8F653 (base 16) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + 3/F,A5 Building Zhiyuan Community No.1001,Xueyuan Road Nanshan District + Shenzhen Guangdong 518055 + CN + +60-AB-14 (hex) LG Innotek +60AB14 (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +BC-62-D2 (hex) Genexis International B.V. +BC62D2 (base 16) Genexis International B.V. + Waldfeuchterbaan 124 + Maria Hoop Maria Hoop 6105 BP + NL + +6C-9E-7C (hex) Fiberhome Telecommunication Technologies Co.,LTD +6C9E7C (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +BC-BA-C2 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +BCBAC2 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +44-D5-F2 (hex) IEEE Registration Authority +44D5F2 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +0C-DD-24 (hex) Intel Corporate +0CDD24 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-0C-86 (hex) Cisco Systems, Inc +000C86 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F8-3C-BF (hex) BOTATO ELECTRONICS SDN BHD +F83CBF (base 16) BOTATO ELECTRONICS SDN BHD + c-1-2, JALAN BK5A/2B 47180,BANDAR KINRARA + PUCHONG SELANGOR 47180 + MY + +FC-58-9A (hex) Cisco Systems, Inc +FC589A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F0-86-20 (hex) Arcadyan Corporation +F08620 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +DC-CC-8D (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +DCCC8D (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +F0-5C-77 (hex) Google, Inc. +F05C77 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +11-11-11 (hex) Private +111111 (base 16) Private + +6C-D7-1F (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +6CD71F (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +F0-68-65 (hex) Taicang T&W Electronics +F06865 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +A4-63-A1 (hex) Inventus Power Eletronica do Brasil LTDA +A463A1 (base 16) Inventus Power Eletronica do Brasil LTDA + Av Buriti, 4285 Distrito Industrial + Manaus Amazonas 69075000 + BR + +3C-9D-56 (hex) HUAWEI TECHNOLOGIES CO.,LTD +3C9D56 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +70-FD-45 (hex) HUAWEI TECHNOLOGIES CO.,LTD +70FD45 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +44-67-47 (hex) HUAWEI TECHNOLOGIES CO.,LTD +446747 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-4A-70 (hex) Wacom Co.,Ltd. +884A70 (base 16) Wacom Co.,Ltd. + Sumitomo Fudosan Shinjuku Grand Tower 31F,8-17-1 + Nishi-shinjuku,Shinjuku-ku Tokyo 160-6131 + JP + +F4-B5-BB (hex) CERAGON NETWORKS +F4B5BB (base 16) CERAGON NETWORKS + 24 RAUEL WALLENBERG STREET + TEL-AVIV 96719 + IL + +50-7A-C5 (hex) Apple, Inc. +507AC5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +4C-6B-E8 (hex) Apple, Inc. +4C6BE8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +8C-86-1E (hex) Apple, Inc. +8C861E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-2B-8D (hex) Apple, Inc. +542B8D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-1D-29 (hex) Doro AB +001D29 (base 16) Doro AB + Magistratsvägen 10 + Lund 226 43 + SE + +EC-A5-DE (hex) ONYX WIFI Inc +ECA5DE (base 16) ONYX WIFI Inc + 9891 Irvine Center Drive, Suite 200 + Irvine 92618 + US + +8C-49-62 (hex) Roku, Inc +8C4962 (base 16) Roku, Inc + 150 Winchester Circle + Los Gatos CA 95032 + US + +10-33-BF (hex) Technicolor CH USA Inc. +1033BF (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +34-75-63 (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +347563 (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District, + Shenzhen Guangdong 518000 + CN + +14-2E-5E (hex) Sercomm Corporation. +142E5E (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +00-25-CB (hex) Reiner SCT +0025CB (base 16) Reiner SCT + Reiner Kartengeräte GmbH & Co. KG. + Furtwangen 78120 + DE + +44-23-7C (hex) Beijing Xiaomi Mobile Software Co., Ltd +44237C (base 16) Beijing Xiaomi Mobile Software Co., Ltd + The Rainbow City Office Building, 68 Qinghe Middle Street Haidian District + Beijing Beijing 100085 + CN + +50-EB-71 (hex) Intel Corporate +50EB71 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C0-64-E4 (hex) Cisco Systems, Inc +C064E4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +50-80-4A (hex) Quectel Wireless Solutions Co., Ltd. +50804A (base 16) Quectel Wireless Solutions Co., Ltd. + 7th Floor, Hongye Building, No.1801 Hongmei Road, Xuhui District + Shanghai 200233 + CN + +30-94-35 (hex) vivo Mobile Communication Co., Ltd. +309435 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +D4-4B-B6 (hex) Zhejiang Tmall Technology Co., Ltd. +D44BB6 (base 16) Zhejiang Tmall Technology Co., Ltd. + Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District, Shenzhen Guangdong province + Shenzhen GuangDong 518000 + CN + +38-18-4C (hex) Sony Home Entertainment&Sound Products Inc +38184C (base 16) Sony Home Entertainment&Sound Products Inc + Sony City Osaki 2-10-1 Osaki Shinagawa-ku + Tokyo Japan 141-8610 + JP + +D8-2F-E6 (hex) Zhejiang Tmall Technology Co., Ltd. +D82FE6 (base 16) Zhejiang Tmall Technology Co., Ltd. + Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District, Shenzhen Guangdong province + Shenzhen GuangDong 518000 + CN + +14-0F-42 (hex) Nokia +140F42 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +00-6D-61 (hex) Guangzhou V-SOLUTION Electronic Technology Co., Ltd. +006D61 (base 16) Guangzhou V-SOLUTION Electronic Technology Co., Ltd. + Room 601,Originality Building B2, NO.162 Science Avenue,Science Town + Guangzhou Guangdong 510663 + CN + +C4-AC-59 (hex) Murata Manufacturing Co., Ltd. +C4AC59 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +58-16-D7 (hex) ALPS ELECTRIC CO., LTD. +5816D7 (base 16) ALPS ELECTRIC CO., LTD. + nishida 6-1 + Kakuda-City Miyagi-Pref 981-1595 + JP + +FC-A4-7A (hex) IEEE Registration Authority +FCA47A (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E4-19-C1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E419C1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B8-66-85 (hex) Sagemcom Broadband SAS +B86685 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +38-1A-52 (hex) Seiko Epson Corporation +381A52 (base 16) Seiko Epson Corporation + 2070 Kotobuki Koaka + Matsumoto-shi Nagano-ken 399-8702 + JP + +00-0A-17 (hex) NESTAR COMMUNICATIONS, INC +000A17 (base 16) NESTAR COMMUNICATIONS, INC + No.6,19 Lane Bade Road + HSINCHU 300 + TW + +D8-AF-81 (hex) ZAO NPK Rotek +D8AF81 (base 16) ZAO NPK Rotek + Filippovskiy per., 8/1 + Moscow 119019 + RU + +E4-FD-A1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E4FDA1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B4-52-A9 (hex) Texas Instruments +B452A9 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +54-EF-44 (hex) Lumi United Technology Co., Ltd +54EF44 (base 16) Lumi United Technology Co., Ltd + 8th Floor, JinQi Wisdom Valley, No.1 TangLing Road, LinXian Ave, Taoyuan Residential District,Nanshan District + ShenZhen GuangDong 518055 + CN + +40-2B-50 (hex) ARRIS Group, Inc. +402B50 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +78-CC-2B (hex) SINEWY TECHNOLOGY CO., LTD +78CC2B (base 16) SINEWY TECHNOLOGY CO., LTD + 2F., No.179, Dongmin Rd. + Toufen City, Miaoli County 351 + TW + +B8-07-56 (hex) Cisco Meraki +B80756 (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco null 94158 + US + +D0-C8-57 (hex) IEEE Registration Authority +D0C857 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +FC-BC-D1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +FCBCD1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +74-60-FA (hex) HUAWEI TECHNOLOGIES CO.,LTD +7460FA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +CC-3A-DF (hex) Private +CC3ADF (base 16) Private + +38-EF-E3 (hex) INGENICO TERMINALS SAS +38EFE3 (base 16) INGENICO TERMINALS SAS + 28-32 BOULEVARD DE GRENELLE + PARIS 75015 + FR + +50-D4-F7 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +50D4F7 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +5C-87-9C (hex) Intel Corporate +5C879C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +24-EE-9A (hex) Intel Corporate +24EE9A (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1F-47 (hex) MCS Logic Inc. +001F47 (base 16) MCS Logic Inc. + 6F. Samho Center B Bldg., 275-6 + Seoul 137-941 + KR + +8C-FD-18 (hex) HUAWEI TECHNOLOGIES CO.,LTD +8CFD18 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B4-54-59 (hex) China Mobile (Hangzhou) Information Technology Co., Ltd. +B45459 (base 16) China Mobile (Hangzhou) Information Technology Co., Ltd. + No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District + Hangzhou Zhejiang 310000 + CN + +00-09-70 (hex) Vibration Research Corporation +000970 (base 16) Vibration Research Corporation + 2385 Wilshere Drive + Jenison MI 49428 + US + +14-A2-A0 (hex) Cisco Systems, Inc +14A2A0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E4-AB-89 (hex) MitraStar Technology Corp. +E4AB89 (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +78-C3-13 (hex) China Mobile Group Device Co.,Ltd. +78C313 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +74-34-AE (hex) this is engineering Inc. +7434AE (base 16) this is engineering Inc. + 352, 815 Daewangpangyo-ro, Sujeong-gu + Seongnam-si Gyeonggi-do 13449 + KR + +74-AD-B7 (hex) China Mobile Group Device Co.,Ltd. +74ADB7 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street + Beijing 100053 + CN + +60-95-CE (hex) IEEE Registration Authority +6095CE (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +8C-E5-C0 (hex) Samsung Electronics Co.,Ltd +8CE5C0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F0-8A-76 (hex) Samsung Electronics Co.,Ltd +F08A76 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +EC-AA-25 (hex) Samsung Electronics Co.,Ltd +ECAA25 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +68-7D-6B (hex) Samsung Electronics Co.,Ltd +687D6B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +48-51-69 (hex) Samsung Electronics Co.,Ltd +485169 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C4-06-83 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C40683 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-D0-0D (hex) HUAWEI TECHNOLOGIES CO.,LTD +94D00D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-8A-5A (hex) JFCONTROL +C48A5A (base 16) JFCONTROL + 1449-37 Seoburo + Suwon Gyunggi-do 16643 + KR + +B4-9A-95 (hex) Shenzhen Boomtech Industrial Corporation +B49A95 (base 16) Shenzhen Boomtech Industrial Corporation + 2F, Block E, Bao'an Intelligent Valley, Yingtian Road No.4 Xixiang Sub-District Office, Bao'an District + Shenzhen Guangdong 518102 + CN + +AC-83-E9 (hex) Beijing Zile Technology Co., Ltd +AC83E9 (base 16) Beijing Zile Technology Co., Ltd + Tecent WeWork, Huilongguan East Avenue, Changping District + Beijing Beijing 100096 + CN + +D8-CA-06 (hex) Titan DataCenters France +D8CA06 (base 16) Titan DataCenters France + E.SpacePark 45 Allee des ormes + mougins 06250 + FR + +1C-20-DB (hex) HUAWEI TECHNOLOGIES CO.,LTD +1C20DB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D0-C6-5B (hex) HUAWEI TECHNOLOGIES CO.,LTD +D0C65B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +90-78-B2 (hex) Xiaomi Communications Co Ltd +9078B2 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +B4-CF-E0 (hex) Sichuan tianyi kanghe communications co., LTD +B4CFE0 (base 16) Sichuan tianyi kanghe communications co., LTD + No.198, section 1, xueshan avenue, jinyuan town, dayi county + chengdu sichuan 611330 + CN + +BC-7F-A4 (hex) Xiaomi Communications Co Ltd +BC7FA4 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +FC-49-2D (hex) Amazon Technologies Inc. +FC492D (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +74-EE-2A (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD +74EE2A (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD + NO.268, Fuqian Rd, Jutang community, Guanlan Town, Longhua New district + shenzhen guangdong 518000 + CN + +08-7E-64 (hex) Technicolor CH USA Inc. +087E64 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +08-00-39 (hex) SPIDER SYSTEMS LIMITED +080039 (base 16) SPIDER SYSTEMS LIMITED + SPIDER PARK + SCOTLAND + GB + +90-47-3C (hex) China Mobile Group Device Co.,Ltd. +90473C (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +88-9E-33 (hex) TCT mobile ltd +889E33 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +6C-8A-EC (hex) Nantong Coship Electronics Co., Ltd. +6C8AEC (base 16) Nantong Coship Electronics Co., Ltd. + No.188 Xinsheng Road + Nantong Jiangsu 226001 + CN + +84-C2-E4 (hex) Jiangsu Qinheng Co., Ltd. +84C2E4 (base 16) Jiangsu Qinheng Co., Ltd. + No. 18, Ningshuang Road + Nanjing Jiangsu 210012 + CN + +7C-21-D8 (hex) Shenzhen Think Will Communication Technology co., LTD. +7C21D8 (base 16) Shenzhen Think Will Communication Technology co., LTD. + 16F,Block A,Central Plaza,No.2002,Baoyuan Rd.,Baoan District + Shenzhen 518101 + CN + +FC-EA-50 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +FCEA50 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +00-E0-6B (hex) W&G SPECIAL PRODUCTS +00E06B (base 16) W&G SPECIAL PRODUCTS + SCEINCE PARK EINDHOVIN 5049 + + NL + +04-5C-6C (hex) Juniper Networks +045C6C (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +D8-F1-5B (hex) Espressif Inc. +D8F15B (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +D4-F0-57 (hex) Nintendo Co.,Ltd +D4F057 (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +6C-F1-7E (hex) Zhejiang Uniview Technologies Co.,Ltd. +6CF17E (base 16) Zhejiang Uniview Technologies Co.,Ltd. + No.88,Jiangling Road + Hangzhou Zhejiang,P.R.China 310051 + CN + +08-3A-2F (hex) Guangzhou Juan Intelligent Tech Joint Stock Co.,Ltd +083A2F (base 16) Guangzhou Juan Intelligent Tech Joint Stock Co.,Ltd + NO.9, street 3, HengLing industrial zone, Tangdong, tianhe district + Guangzhou Guangdong CN 510000 + CN + +1C-3A-60 (hex) Ruckus Wireless +1C3A60 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +D4-35-1D (hex) Technicolor +D4351D (base 16) Technicolor + Prins Boudewijnlaan 47 + Edegem - Belgium B-2650 + BE + +60-09-C3 (hex) u-blox AG +6009C3 (base 16) u-blox AG + Zuercherstrasse 68 + Thalwil 8800 + CH + +48-87-64 (hex) vivo Mobile Communication Co., Ltd. +488764 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +5C-1C-B9 (hex) vivo Mobile Communication Co., Ltd. +5C1CB9 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +C0-FD-84 (hex) zte corporation +C0FD84 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +44-4B-7E (hex) Fiberhome Telecommunication Technologies Co.,LTD +444B7E (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +DC-8C-37 (hex) Cisco Systems, Inc +DC8C37 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E8-D0-FC (hex) Liteon Technology Corporation +E8D0FC (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +E8-E8-B7 (hex) Murata Manufacturing Co., Ltd. +E8E8B7 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +10-3D-3E (hex) China Mobile Group Device Co.,Ltd. +103D3E (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +7C-50-DA (hex) Private +7C50DA (base 16) Private + +64-CC-22 (hex) Arcadyan Corporation +64CC22 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +4C-91-57 (hex) Fujian LANDI Commercial Equipment Co.,Ltd +4C9157 (base 16) Fujian LANDI Commercial Equipment Co.,Ltd + Building 17,the 1st Section ,Fuzhou Software Park + No.89 Software Road Fuzhou ,Fujian 350003 + CN + +9C-25-BE (hex) Wildlife Acoustics, Inc. +9C25BE (base 16) Wildlife Acoustics, Inc. + 3 Mill and Main Place, Suite 210 + MAYNARD MA 01754 + US + +D0-39-EA (hex) NetApp +D039EA (base 16) NetApp + 1395 Crossman Ave + Sunnyvale, CA 94089 + US + +F8-DF-E1 (hex) MyLight Systems +F8DFE1 (base 16) MyLight Systems + 290 rue Ferdinand Perrier + Saint Priest 69800 + FR + +60-D2-DD (hex) Shenzhen Baitong Putian Technology Co.,Ltd. +60D2DD (base 16) Shenzhen Baitong Putian Technology Co.,Ltd. + 501,5/F,Building 1,No.2,Lianwei Street,Hualian Community,Longhua Street Longhua District + Shenzhen Guangdong 518109 + CN + +78-8C-77 (hex) LEXMARK INTERNATIONAL, INC. +788C77 (base 16) LEXMARK INTERNATIONAL, INC. + 740 NEW CIRCLE ROAD + LEXINGTON KY 40550 + US + +3C-0C-7D (hex) Tiny Mesh AS +3C0C7D (base 16) Tiny Mesh AS + Elisabeth von Hübschs gate 6 + MOSS 1534 + NO + +34-76-C5 (hex) I-O DATA DEVICE,INC. +3476C5 (base 16) I-O DATA DEVICE,INC. + 3-10, SAKURADA-MACHI + KANAZAWA ISHIKAWA 920-8512 + JP + +24-DA-33 (hex) HUAWEI TECHNOLOGIES CO.,LTD +24DA33 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +FC-AB-90 (hex) HUAWEI TECHNOLOGIES CO.,LTD +FCAB90 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +58-93-D8 (hex) Texas Instruments +5893D8 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +50-51-A9 (hex) Texas Instruments +5051A9 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +98-8B-0A (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +988B0A (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +A4-97-5C (hex) VTech Telecommunications Ltd. +A4975C (base 16) VTech Telecommunications Ltd. + 23/F,Tai Ping Industrial Centre ,Block 1 + Hong Kong 000000 + CN + +B0-2A-1F (hex) Wingtech Group (HongKong)Limited +B02A1F (base 16) Wingtech Group (HongKong)Limited + FLAT/RM 1903 19/F PODIUM PLAZA 5HANOI ROAD TSIM SHA TSUI + Hong Kong Hong Kong 999077 + HK + +DC-68-0C (hex) Hewlett Packard Enterprise +DC680C (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +F4-02-70 (hex) Dell Inc. +F40270 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +1C-27-04 (hex) zte corporation +1C2704 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +50-78-B3 (hex) zte corporation +5078B3 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +F0-D4-F7 (hex) varram system +F0D4F7 (base 16) varram system + 57, TECHNO 11-RO,YUSEONG-GU, DAEJEON, KOREA + DAEJEON 34036 + KR + +E0-CC-7A (hex) HUAWEI TECHNOLOGIES CO.,LTD +E0CC7A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +6C-23-CB (hex) Wattty Corporation +6C23CB (base 16) Wattty Corporation + 2-15-31 takaokanishi nakaku + hamamatsushi shizuokaken 4338118 + JP + +60-AB-67 (hex) Xiaomi Communications Co Ltd +60AB67 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +AC-71-0C (hex) China Mobile Group Device Co.,Ltd. +AC710C (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +A8-DB-03 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +A8DB03 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +30-89-44 (hex) DEVA Broadcast Ltd. +308944 (base 16) DEVA Broadcast Ltd. + Alexander Stamboliyski 65 + Burgas Burgas 8000 + BG + +F4-79-60 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F47960 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +14-52-90 (hex) KNS Group LLC (YADRO Company) +145290 (base 16) KNS Group LLC (YADRO Company) + Spartakovskaya sq., 14, bl. 1 + Moscow 105082 + RU + +5C-32-C5 (hex) Teracom Ltd. +5C32C5 (base 16) Teracom Ltd. + 11 Vasil Levski blvd. + Ruse 7019 + BG + +AC-EE-70 (hex) Fontem Ventures BV +ACEE70 (base 16) Fontem Ventures BV + Motion Building 8F, Radarweg 60 + Amsterdam Noord-Holland 1043NT + NL + +AC-E2-D3 (hex) Hewlett Packard +ACE2D3 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +00-FD-22 (hex) Cisco Systems, Inc +00FD22 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +44-18-FD (hex) Apple, Inc. +4418FD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-B6-00 (hex) VOIM Co., Ltd. +00B600 (base 16) VOIM Co., Ltd. + 70, Seotan-ro, Jinwi-myeon + Pyeongtaek-si Gyeonggi-do 17706 + KR + +98-FA-9B (hex) LCFC(HeFei) Electronics Technology co., ltd +98FA9B (base 16) LCFC(HeFei) Electronics Technology co., ltd + YunGu Road 3188-1 + Hefei Anhui 230000 + CN + +00-5B-94 (hex) Apple, Inc. +005B94 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-89-7E (hex) Apple, Inc. +E0897E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B0-0C-D1 (hex) Hewlett Packard +B00CD1 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +48-46-C1 (hex) FN-LINK TECHNOLOGY LIMITED +4846C1 (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +B4-D0-A9 (hex) China Mobile Group Device Co.,Ltd. +B4D0A9 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +FC-29-F3 (hex) McPay Co.,LTD. +FC29F3 (base 16) McPay Co.,LTD. + No.801, 61, Digital-ro 31-gil, Guro-gu + Seoul 08375 + KR + +F8-AF-DB (hex) Fiberhome Telecommunication Technologies Co.,LTD +F8AFDB (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +48-89-E7 (hex) Intel Corporate +4889E7 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A0-BD-1D (hex) Zhejiang Dahua Technology Co., Ltd. +A0BD1D (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199,Waterfront Road + Hangzhou Zhejiang 310053 + CN + +E4-9F-1E (hex) ARRIS Group, Inc. +E49F1E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-26-15 (hex) Teracom Limited +002615 (base 16) Teracom Limited + B-84 + Noida Uttar Pradesh 201301 + IN + +9C-8E-DC (hex) Teracom Limited +9C8EDC (base 16) Teracom Limited + 123456 + Noida Uttar Pradesh 201301 + IN + +00-01-91 (hex) SYRED Data Systems +000191 (base 16) SYRED Data Systems + 272 Lanes Mill Road + Howell NJ 07731 + US + +AC-D5-64 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +ACD564 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +94-D0-75 (hex) CIS Crypto +94D075 (base 16) CIS Crypto + Nauchnyy proezd 6 + Moscow 117246 + RU + +28-B4-FB (hex) Sprocomm Technologies CO.,LTD. +28B4FB (base 16) Sprocomm Technologies CO.,LTD. + 5D F1.6 Block,Tianfa Building,Tianan Chegongmiao Industrial park,Futian Dist + shenzhen guangdong 518000 + CN + +40-F9-D5 (hex) Tecore Networks +40F9D5 (base 16) Tecore Networks + 7030 Hi Tech Drive + Hanover MD 21076 + US + +CC-2C-83 (hex) DarkMatter L.L.C +CC2C83 (base 16) DarkMatter L.L.C + Level 15, Aldar HQ + Abu Dhabi 27655 + AE + +DC-ED-84 (hex) Haverford Systems Inc +DCED84 (base 16) Haverford Systems Inc + 152 Robbins Road + Downingtown PA 19335 + US + +64-4C-36 (hex) Intel Corporate +644C36 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +7C-57-3C (hex) Aruba, a Hewlett Packard Enterprise Company +7C573C (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +2C-01-B5 (hex) Cisco Systems, Inc +2C01B5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +28-EF-01 (hex) Private +28EF01 (base 16) Private + +C0-53-36 (hex) Beijing National Railway Research & Design Institute of Signal & Communication Group Co..Ltd. +C05336 (base 16) Beijing National Railway Research & Design Institute of Signal & Communication Group Co..Ltd. + 7 floor, No.1 Automobile Museum South Road, Fengtai Science and Technology Park, + Beijing Beijing 100070 + CN + +60-6E-D0 (hex) SEAL AG +606ED0 (base 16) SEAL AG + Landstrasse 176 + Wettingen 5430 + CH + +2C-CC-E6 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +2CCCE6 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +E4-4C-C7 (hex) IEEE Registration Authority +E44CC7 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D4-E8-80 (hex) Cisco Systems, Inc +D4E880 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A8-34-6A (hex) Samsung Electronics Co.,Ltd +A8346A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +3C-20-F6 (hex) Samsung Electronics Co.,Ltd +3C20F6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +7C-38-AD (hex) Samsung Electronics Co.,Ltd +7C38AD (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D4-9C-DD (hex) AMPAK Technology,Inc. +D49CDD (base 16) AMPAK Technology,Inc. + 3F, No.15-1 Zhonghua Road, Hsinchu Industrail Park, Hukou, + Hsinchu Hsinchu,Taiwan R.O.C. 30352 + TW + +50-F7-22 (hex) Cisco Systems, Inc +50F722 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +98-49-E1 (hex) Boeing Defence Australia +9849E1 (base 16) Boeing Defence Australia + GPO Box 767 + Brisbane Queensland 4001 + AU + +04-D7-A5 (hex) New H3C Technologies Co., Ltd +04D7A5 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +4C-4D-66 (hex) Nanjing Jiahao Technology Co., Ltd. +4C4D66 (base 16) Nanjing Jiahao Technology Co., Ltd. + Moling Industrial Park, Development Zone, Jiangning, Nanjing + Nanjing Jiangsu 211111 + CN + +A4-81-7A (hex) CIG SHANGHAI CO LTD +A4817A (base 16) CIG SHANGHAI CO LTD + 5th Floor, Building 8 No 2388 Chenhang Road + SHANGHAI 201114 + CN + +90-58-51 (hex) Technicolor CH USA Inc. +905851 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +98-09-CF (hex) OnePlus Technology (Shenzhen) Co., Ltd +9809CF (base 16) OnePlus Technology (Shenzhen) Co., Ltd + 18C02, 18C03, 18C04 ,18C05,TAIRAN BUILDING, + Shenzhen Guangdong 518000 + CN + +B8-DE-5E (hex) LONGCHEER TELECOMMUNICATION LIMITED +B8DE5E (base 16) LONGCHEER TELECOMMUNICATION LIMITED + Building 1,No.401,Caobao Rd + Shanghai Xuhui District 200233 + CN + +88-5A-06 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +885A06 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +54-47-D3 (hex) TSAT AS +5447D3 (base 16) TSAT AS + Martin Linges v 25 + Fornebu 1364 + NO + +CC-ED-DC (hex) MitraStar Technology Corp. +CCEDDC (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +3C-F0-11 (hex) Intel Corporate +3CF011 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +CC-D8-1F (hex) Maipu Communication Technology Co.,Ltd. +CCD81F (base 16) Maipu Communication Technology Co.,Ltd. + Maipu Mansion, No.288 Tianfu 3rd Street, High-tech Zone + Chengdu Sichuan 610094 + CN + +68-8B-0F (hex) China Mobile IOT Company Limited +688B0F (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +F8-2F-6A (hex) ITEL MOBILE LIMITED +F82F6A (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +B0-68-E6 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +B068E6 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +A4-E7-E4 (hex) Connex GmbH +A4E7E4 (base 16) Connex GmbH + Elbestrasse 12 + Oldenburg 26135 + DE + +B8-EF-8B (hex) SHENZHEN CANNICE TECHNOLOGY CO.,LTD +B8EF8B (base 16) SHENZHEN CANNICE TECHNOLOGY CO.,LTD + F-20,7A,Baoneng Technology Park + Shenzhen Guangdong 518109 + CN + +B8-18-6F (hex) ORIENTAL MOTOR CO., LTD. +B8186F (base 16) ORIENTAL MOTOR CO., LTD. + 5-8-3 Tokodai + Tsukuba Ibaraki 300-2635 + JP + +00-1A-3F (hex) Intelbras +001A3F (base 16) Intelbras + BR 101, km 210, S/N° + São José Santa Catarina 88104800 + BR + +C0-D8-34 (hex) xvtec ltd +C0D834 (base 16) xvtec ltd + Ha'nagar 24 + Hod Hasharon Israel 4527713 + IL + +B8-C2-53 (hex) Juniper Networks +B8C253 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +F0-5C-19 (hex) Aruba, a Hewlett Packard Enterprise Company +F05C19 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +04-BD-88 (hex) Aruba, a Hewlett Packard Enterprise Company +04BD88 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +9C-1C-12 (hex) Aruba, a Hewlett Packard Enterprise Company +9C1C12 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +18-DF-B4 (hex) BOSUNG POWERTEC CO.,LTD. +18DFB4 (base 16) BOSUNG POWERTEC CO.,LTD. + 70, Daechang-gil, Judeok-eup + Chungju-si Chungcheongbuk-do 27463 + KR + +00-01-47 (hex) Zhone Technologies +000147 (base 16) Zhone Technologies + 7001 Oakport Street + Oakland CA 94621 + US + +20-B7-80 (hex) Toshiba Visual Solutions Corporation Co.,Ltd +20B780 (base 16) Toshiba Visual Solutions Corporation Co.,Ltd + Shinkawasaki Mitsui Builing West Tower 19F, 1-1-2 Kashimada + Saiwai-ku, Kawasaki-shi Kanagawa 212-0058 + JP + +E0-37-17 (hex) Technicolor CH USA Inc. +E03717 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +14-D4-FE (hex) ARRIS Group, Inc. +14D4FE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +30-4F-75 (hex) DASAN Network Solutions +304F75 (base 16) DASAN Network Solutions + DASAN Tower 8F, 49 Daewangpangyo-ro644beon-gil Bundang-gu + Seongnam-si Gyeonggi-do 13493 + KR + +EC-A9-FA (hex) GUANGDONG GENIUS TECHNOLOGY CO., LTD. +ECA9FA (base 16) GUANGDONG GENIUS TECHNOLOGY CO., LTD. + #126,BBK Road,Wusha,Chang'An + Dong Guan Guang Dong 523860 + CN + +00-03-A5 (hex) Medea Corporation +0003A5 (base 16) Medea Corporation + 5701 Lindero Canyon Rd. + Wetlake Village CA 91362 + US + +BC-E6-7C (hex) Cambium Networks Limited +BCE67C (base 16) Cambium Networks Limited + Unit B2, Linhay Business Park, + Ashburton Devon TQ13 7UP + GB + +7C-1E-06 (hex) New H3C Technologies Co., Ltd +7C1E06 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +F0-B3-1E (hex) Universal Electronics, Inc. +F0B31E (base 16) Universal Electronics, Inc. + 201 E. Sandpointe Ave + Santa Ana CA 92707 + US + +F8-91-73 (hex) AEDLE SAS +F89173 (base 16) AEDLE SAS + 11 Rue Campagne Première, Cour Intérieure, Entresol, CODE 13B80 + Paris IDF 75014 + FR + +C8-4F-86 (hex) Sophos Ltd +C84F86 (base 16) Sophos Ltd + The Pentagon + Abingdon Oxfordshire OX14 3YP + GB + +64-29-ED (hex) AO PKK Milandr +6429ED (base 16) AO PKK Milandr + Gergievsky prospekt, 5 + Zelenograd Moscow 124498 + RU + +44-3C-88 (hex) FICOSA MAROC INTERNATIONAL +443C88 (base 16) FICOSA MAROC INTERNATIONAL + Zone Franche Technopolis Rocade Rabat-Salé 11103 Sala Al Jadida - Salé + Salé 11103 + MA + +84-1C-70 (hex) zte corporation +841C70 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +54-47-41 (hex) XCHENG HOLDING +544741 (base 16) XCHENG HOLDING + ROOM 401F, Building 5, No.3000 LONG DONG Avenue, Pudong New District + Shanghai 201203 + CN + +CC-F7-35 (hex) Amazon Technologies Inc. +CCF735 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +C4-F8-39 (hex) Actia Automotive +C4F839 (base 16) Actia Automotive + 5 rue Jorge Semprun + TOULOUSE 31400 + FR + +C8-F7-42 (hex) HangZhou Gubei Electronics Technology Co.,Ltd +C8F742 (base 16) HangZhou Gubei Electronics Technology Co.,Ltd + Room 106, No.611 Jianghong Road, Binjiang District, Hangzhou, Zhejiang, China + Hangzhou ZheJiang 310052 + CN + +00-6F-F2 (hex) MITSUMI ELECTRIC CO.,LTD. +006FF2 (base 16) MITSUMI ELECTRIC CO.,LTD. + 2-11-2, Tsurumaki + Tama-shi Tokyo 206-8567 + JP + +30-DF-8D (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +30DF8D (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +D4-C9-3C (hex) Cisco Systems, Inc +D4C93C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +78-DD-12 (hex) Arcadyan Corporation +78DD12 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +2C-5D-34 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +2C5D34 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +9C-14-63 (hex) Zhejiang Dahua Technology Co., Ltd. +9C1463 (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199,Waterfront Road + Hangzhou Zhejiang 310053 + CN + +00-24-33 (hex) ALPS ELECTRIC CO., LTD. +002433 (base 16) ALPS ELECTRIC CO., LTD. + 1-2-1, Okinouchi, + Soma-city, Fukushima-pref., 976-8501 + JP + +00-23-06 (hex) ALPS ELECTRIC CO., LTD. +002306 (base 16) ALPS ELECTRIC CO., LTD. + 1-2-1, Okinouchi, + Soma-city, Fukushima-pref., 976-8501 + JP + +B4-EC-02 (hex) ALPS ELECTRIC CO., LTD. +B4EC02 (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + Kakuda Miyagi-Pref 981-1595 + JP + +64-60-38 (hex) Hirschmann Automation and Control GmbH +646038 (base 16) Hirschmann Automation and Control GmbH + Stuttgarter Straße 45-51 + Neckartenzlingen D-72654 + DE + +70-18-A7 (hex) Cisco Systems, Inc +7018A7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +CC-D3-9D (hex) IEEE Registration Authority +CCD39D (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E0-75-0A (hex) ALPS ELECTRIC CO., LTD. +E0750A (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + kakuda-City 981-1595 + US + +00-19-C1 (hex) ALPS ELECTRIC CO., LTD. +0019C1 (base 16) ALPS ELECTRIC CO., LTD. + 1-2-1, Okinouchi, + Soma-city, Fukushima-pref., 976-8501 + JP + +00-16-FE (hex) ALPS ELECTRIC CO., LTD. +0016FE (base 16) ALPS ELECTRIC CO., LTD. + 1-2-1, Okinouchi, + Soma-city, Fukushima-pref., 976-8501 + JP + +9C-8D-7C (hex) ALPS ELECTRIC CO., LTD. +9C8D7C (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + Kakuda Miyagi-Pref 981-1595 + JP + +D4-25-CC (hex) IEEE Registration Authority +D425CC (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +8C-6D-C4 (hex) Megapixel VR +8C6DC4 (base 16) Megapixel VR + 340 S. Lemon Ave + Walnut CA 91789 + US + +BC-75-36 (hex) ALPS ELECTRIC CO., LTD. +BC7536 (base 16) ALPS ELECTRIC CO., LTD. + nishida 6-1 + Kakuda-City Miyagi-Pref 981-1595 + JP + +E0-AE-5E (hex) ALPS ELECTRIC CO., LTD. +E0AE5E (base 16) ALPS ELECTRIC CO., LTD. + 6-3-36 Furukawanakazato, + Osaki Miyagi-pref 989-6181 + JP + +D4-B7-61 (hex) Sichuan AI-Link Technology Co., Ltd. +D4B761 (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou,Industrial Park + Anzhou,Industrial Park Sichuan 621000 + CN + +7C-03-5E (hex) Xiaomi Communications Co Ltd +7C035E (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +44-FE-3B (hex) Arcadyan Corporation +44FE3B (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +D8-3A-F5 (hex) Wideband Labs LLC +D83AF5 (base 16) Wideband Labs LLC + 1027 S Main Street, STE 330 + Joplin MO 64801 + US + +38-D9-A5 (hex) Mikotek Information Inc. +38D9A5 (base 16) Mikotek Information Inc. + 3F, No. 20, Aly. 18, Ln. 478, Ruiguang Rd. + Taipei 114 + TW + +4C-87-5D (hex) Bose Corporation +4C875D (base 16) Bose Corporation + The Mountain + Framingham MA 01701-9168 + US + +98-2C-BC (hex) Intel Corporate +982CBC (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B0-E7-DE (hex) Homa Technologies JSC +B0E7DE (base 16) Homa Technologies JSC + Building 5, Quang Trung Software City, District 12 + Ho Chi Minh 729226 + VN + +64-9D-99 (hex) FS COM INC +649D99 (base 16) FS COM INC + 380 Centerpoint Blvd New Castle + New Castle DE 19720 + US + +00-16-9D (hex) Cisco Systems, Inc +00169D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +4C-96-2D (hex) Fresh AB +4C962D (base 16) Fresh AB + Gransholmsvägen 136 + Gemla 35599 + SE + +00-D2-79 (hex) VINGROUP JOINT STOCK COMPANY +00D279 (base 16) VINGROUP JOINT STOCK COMPANY + Number 7, Bang Lang 1 street, Long Bien district + Ha Noi Ha Noi 100000 + VN + +48-4A-30 (hex) George Robotics Limited +484A30 (base 16) George Robotics Limited + Salisbury House, Station Road + Cambridge CB1 2LA + GB + +48-61-A3 (hex) Concern Axion JSC +4861A3 (base 16) Concern Axion JSC + 90, M. Gorkogo St. + Izhevsk Udmurt Republic 426000 + RU + +30-4A-26 (hex) Shenzhen Trolink Technology CO, LTD +304A26 (base 16) Shenzhen Trolink Technology CO, LTD + 201 B building 4 shijie, Chashu industry 505 block, Baoan airport Sanwei community, Hangcheng street Baoan area. + Shenzhen GuangDong 518000 + CN + +4C-E5-AE (hex) Tianjin Beebox Intelligent Technology Co.,Ltd. +4CE5AE (base 16) Tianjin Beebox Intelligent Technology Co.,Ltd. + Room 103,NO.1 of the 2nd Street + Tianjin Pilot Free Trade Zone Airport EconomicArea Airport International Logistics Zone, Tianjin 300300 + CN + +E4-D3-AA (hex) FUJITSU CONNECTED TECHNOLOGIES LIMITED +E4D3AA (base 16) FUJITSU CONNECTED TECHNOLOGIES LIMITED + 4-1-1, Kamikodanaka, Nakahara-ku + Kawasaki Kanagawa 2118588 + JP + +D4-67-D3 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +D467D3 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +A4-12-32 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +A41232 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +48-E3-C3 (hex) JENOPTIK Advanced Systems GmbH +48E3C3 (base 16) JENOPTIK Advanced Systems GmbH + Feldstrasse 155 + Wedel Schleswig-Holstein 22880 + DE + +CC-35-5A (hex) SecuGen Corporation +CC355A (base 16) SecuGen Corporation + 2065 Martin Ave, Suite 108 + Santa Clara CA 95050 + US + +80-54-6A (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +80546A (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +B4-47-F5 (hex) Earda Technologies co Ltd +B447F5 (base 16) Earda Technologies co Ltd + Block A,Lianfeng Creative Park, #2 Jisheng Rd., Nansha District + Guangzhou Guangdong 511455 + CN + +F4-C7-C8 (hex) Kelvin Inc. +F4C7C8 (base 16) Kelvin Inc. + 400 Centennial Parkway, Suite 190 + Louisville CO 80027 + US + +A8-9C-A4 (hex) Furrion Limited +A89CA4 (base 16) Furrion Limited + Units 503C & 505-508, Level 5, Core D, Cyberport 3, 100 Cyberport Road + Hong Kong 00000 + HK + +00-00-4C (hex) NEC Corporation +00004C (base 16) NEC Corporation + 7-1 SHIBA 5-CHOME + TOKYO 108-01 0000 + JP + +8C-CF-8F (hex) ITC Systems +8CCF8F (base 16) ITC Systems + 800 Fee Fee Road + St Louis MO 63043 + US + +28-75-D8 (hex) FUJIAN STAR-NET COMMUNICATION CO.,LTD +2875D8 (base 16) FUJIAN STAR-NET COMMUNICATION CO.,LTD + 19-22# Building, Star-net Science Plaza, Juyuanzhou, + FUZHOU FUJIAN 350002 + CN + +90-E2-02 (hex) Texas Instruments +90E202 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +30-24-78 (hex) Sagemcom Broadband SAS +302478 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +7C-89-C1 (hex) Palo Alto Networks +7C89C1 (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +84-A9-3E (hex) Hewlett Packard +84A93E (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +B0-C3-87 (hex) GOEFER, Inc. +B0C387 (base 16) GOEFER, Inc. + 118 N. Market St. + Frederick MD 21701 + US + +08-6B-D7 (hex) Silicon Laboratories +086BD7 (base 16) Silicon Laboratories + 7000 W. William Cannon Dr. + Austin TX 78735 + US + +34-93-42 (hex) TTE Corporation +349342 (base 16) TTE Corporation + 7/F, Building 22E 22 Science Park East Avenue Hong Kong Science Park Shatin, N.T. + Hong Kong 999077 + HK + +58-9E-C6 (hex) Gigaset Communications GmbH +589EC6 (base 16) Gigaset Communications GmbH + Frankenstrasse 2 + Bocholt NRW 46395 + DE + +64-C7-53 (hex) Apple, Inc. +64C753 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-58-AD (hex) China Mobile IOT Company Limited +6458AD (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +1C-F2-9A (hex) Google, Inc. +1CF29A (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +74-8A-0D (hex) ARRIS Group, Inc. +748A0D (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +CC-75-E2 (hex) ARRIS Group, Inc. +CC75E2 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +A0-A3-B8 (hex) WISCLOUD +A0A3B8 (base 16) WISCLOUD + Tech Park Xia Sha + Hangzhou Zhejiang 310000 + CN + +38-F9-D3 (hex) Apple, Inc. +38F9D3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-18-3C (hex) Apple, Inc. +FC183C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A4-0C-66 (hex) Shenzhen Colorful Yugong Technology and Development Co., Ltd. +A40C66 (base 16) Shenzhen Colorful Yugong Technology and Development Co., Ltd. + 13F, Central Business Tower, No.88 Fuhua First Rd., Futian District, Shenzhen, Guangdong, China + Shenzhen Guangdong 518000 + CN + +44-55-B1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +4455B1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +98-F9-C7 (hex) IEEE Registration Authority +98F9C7 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +FC-77-74 (hex) Intel Corporate +FC7774 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +70-0B-4F (hex) Cisco Systems, Inc +700B4F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E4-38-8C (hex) Digital Products Limited +E4388C (base 16) Digital Products Limited + 53 Clark Road + Rothesay New Brunswick E2E 2K9 + CA + +18-4B-DF (hex) Caavo Inc +184BDF (base 16) Caavo Inc + 1525 McCarthy Blvd., #1182 + Milpitas 95035 + US + +B8-9A-9A (hex) Xin Shi Jia Technology (Beijing) Co.,Ltd +B89A9A (base 16) Xin Shi Jia Technology (Beijing) Co.,Ltd + Room 1002, A Tower, Zhongguancun E World Wealth Center, No.11, Zhongguancun Street, Haidian District, Beijing City + Beijing Beijing 100190 + CN + +8C-7B-F0 (hex) Xufeng Development Limited +8C7BF0 (base 16) Xufeng Development Limited + FLAT/RM1616 16F INTERATIONAL TRADE CENTRE 11-19 SHA TSUI RD TSUEN WAN + HongKong HongKong 999077 + HK + +E0-A5-09 (hex) Bitmain Technologies Inc +E0A509 (base 16) Bitmain Technologies Inc + Building 25, North Olympic Science & Technology Park, Baosheng South Road, Haidian District, Beijing, China + Beijing BEIJING CHINA + CN + +3C-5C-C4 (hex) Amazon Technologies Inc. +3C5CC4 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +D8-A7-56 (hex) Sagemcom Broadband SAS +D8A756 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +D8-D6-F3 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +D8D6F3 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +6C-2C-DC (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +6C2CDC (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +78-35-A0 (hex) Zurn Industries LLC +7835A0 (base 16) Zurn Industries LLC + 1747 Commerce Way + Paso Robles CA 93446 + US + +F4-39-09 (hex) Hewlett Packard +F43909 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +20-1F-31 (hex) Inteno Broadband Technology AB +201F31 (base 16) Inteno Broadband Technology AB + Stensätravägen 13 + Skärholmen SE 127 39 + SE + +2C-CC-44 (hex) Sony Interactive Entertainment Inc. +2CCC44 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +F4-7D-EF (hex) Samsung Electronics Co.,Ltd +F47DEF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +7C-8B-B5 (hex) Samsung Electronics Co.,Ltd +7C8BB5 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-83-3A (hex) Zyxel Communications Corporation +54833A (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +78-70-52 (hex) Welotec GmbH +787052 (base 16) Welotec GmbH + zum Hagenbach 7 + Laer NRW 48366 + DE + +D8-A9-8B (hex) Texas Instruments +D8A98B (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +00-11-6C (hex) Nanwang Multimedia Inc.,Ltd +00116C (base 16) Nanwang Multimedia Inc.,Ltd + Floor 12,Tianyuan Bldg,Wensan Rd#508 + Hangzhou Zhejiang 310013 + CN + +10-B9-F7 (hex) Niko-Servodan +10B9F7 (base 16) Niko-Servodan + Stenager 5 + Sønderborg 6400 + DK + +14-EF-CF (hex) SCHREDER +14EFCF (base 16) SCHREDER + Rue Lusambo 67 + Brussels 1190 + BE + +38-30-F9 (hex) LG Electronics (Mobile Communications) +3830F9 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +A8-3F-A1 (hex) IEEE Registration Authority +A83FA1 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +78-47-E3 (hex) SICHUAN TIANYI COMHEART TELECOM CO.,LTD +7847E3 (base 16) SICHUAN TIANYI COMHEART TELECOM CO.,LTD + NO.198 FIRST SECTION,SNOW MOUNTAIN AVENUE, JINYUAN TOWN, DAYI COUNTY, + CHENGDU SICHUAN 611330 + CN + +6C-9B-C0 (hex) Chemoptics Inc. +6C9BC0 (base 16) Chemoptics Inc. + 261, Techno 2-ro, Yuseong-gu + Daejeon 34026 + KR + +F4-DB-E6 (hex) Cisco Systems, Inc +F4DBE6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +24-84-98 (hex) Beijing Jiaoda Microunion Tech.Co.,Ltd. +248498 (base 16) Beijing Jiaoda Microunion Tech.Co.,Ltd. + 4-5/F,89 Building, First Section No.44 Gaoliangqiao Xie Street, Haidian District, Beijing, China + Beijing Beijing 100044 + CN + +C0-74-AD (hex) Grandstream Networks, Inc. +C074AD (base 16) Grandstream Networks, Inc. + 1297 Beacon Street + Brookline MA 02446 + US + +F0-95-F1 (hex) Carl Zeiss AG +F095F1 (base 16) Carl Zeiss AG + Carl-Zeiss-Straße 22 + Oberkochen 73447 + DE + +00-F4-8D (hex) Liteon Technology Corporation +00F48D (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +70-2E-D9 (hex) Guangzhou Shiyuan Electronics Co., Ltd. +702ED9 (base 16) Guangzhou Shiyuan Electronics Co., Ltd. + No.6, 4th Yunpu Road, Yunpu industry District + Gunagzhou Guangdong 510530 + CN + +70-19-2F (hex) HUAWEI TECHNOLOGIES CO.,LTD +70192F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +10-C2-2F (hex) China Entropy Co., Ltd. +10C22F (base 16) China Entropy Co., Ltd. + Haidian District + Beijing 100085 + CN + +BC-38-65 (hex) JWCNETWORKS +BC3865 (base 16) JWCNETWORKS + 114, Gasan digital 2-ro, Geumcheon-gu, + Seoul 08506 + KR + +04-EB-40 (hex) Cisco Systems, Inc +04EB40 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +18-A7-F1 (hex) Qingdao Haier Technology Co.,Ltd +18A7F1 (base 16) Qingdao Haier Technology Co.,Ltd + Building A01,Haier Information Park, No.1 Haier Road, + Qingdao Shandong 266101 + CN + +90-E1-7B (hex) Apple, Inc. +90E17B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D8-1C-79 (hex) Apple, Inc. +D81C79 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +58-E6-BA (hex) Apple, Inc. +58E6BA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +44-E4-EE (hex) Wistron Neweb Corporation +44E4EE (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +DC-41-E5 (hex) Shenzhen Zhixin Data Service Co., Ltd. +DC41E5 (base 16) Shenzhen Zhixin Data Service Co., Ltd. + Baoyuan Road F518 Fashion Creative Park F3 Blg208 + Baoan District, Shenzhen Guangdong 518101 + CN + +00-A5-BF (hex) Cisco Systems, Inc +00A5BF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C8-BA-E9 (hex) QDIS +C8BAE9 (base 16) QDIS + #512, Buliding B, 168 GaSanDigital 1st, GeumChun-Gu + SEOUL 08507 + KR + +18-01-F1 (hex) Xiaomi Communications Co Ltd +1801F1 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +C4-4F-33 (hex) Espressif Inc. +C44F33 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +54-6A-D8 (hex) Elster Water Metering +546AD8 (base 16) Elster Water Metering + Mas des Cavaliers II, 471 Rue Charles Nungesser + Mauguio 34130 + FR + +C0-84-7D (hex) AMPAK Technology, Inc. +C0847D (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +04-09-A5 (hex) HFR, Inc. +0409A5 (base 16) HFR, Inc. + 5F, Hana EZ Tower + Sungnam-si Kyunggi-do 463-870 + KR + +94-91-7F (hex) ASKEY COMPUTER CORP +94917F (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +9C-0C-DF (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +9C0CDF (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +24-21-24 (hex) Nokia +242124 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +94-9B-2C (hex) Extreme Networks, Inc. +949B2C (base 16) Extreme Networks, Inc. + 6480 Via Del Oro + San Jose 95119 + US + +7C-D3-0A (hex) INVENTEC CORPORATION +7CD30A (base 16) INVENTEC CORPORATION + Inventec Building, 66 Hou-Kang Street + Taipei 111 + TW + +00-1E-33 (hex) INVENTEC CORPORATION +001E33 (base 16) INVENTEC CORPORATION + Inventec Building, 66 Hou-Kang Street + Taipei 111 + TW + +FC-1D-84 (hex) Autobase +FC1D84 (base 16) Autobase + 1201, Biz Center, SKnTechno Park, 124, Sagimakgol-ro, Jungwon-gu, Seongnam-si, Gyeonggi-do + Seongnam Gyeonggi 462-721 + KR + +18-AC-9E (hex) ITEL MOBILE LIMITED +18AC9E (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +EC-84-B4 (hex) CIG SHANGHAI CO LTD +EC84B4 (base 16) CIG SHANGHAI CO LTD + 5th Floor, Building 8 No 2388 Chenhang Road + SHANGHAI 201114 + CN + +00-D0-96 (hex) 3COM EUROPE LTD +00D096 (base 16) 3COM EUROPE LTD + BOUNDARY WAY + vvvvv UNITED KINGDOM + GB + +00-26-54 (hex) 3COM +002654 (base 16) 3COM + 5353 Betsy Ross Drive + Santa Clara 95054-1162 + US + +00-50-DA (hex) 3COM +0050DA (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +00-04-76 (hex) 3COM +000476 (base 16) 3COM + 5400 Bayfront Plaza + Santa Clara CA 95052 + US + +00-04-75 (hex) 3COM +000475 (base 16) 3COM + 5400 Bayfront Plaza + Santa Clara CA 95052 + US + +44-22-F1 (hex) S.FAC, INC +4422F1 (base 16) S.FAC, INC + Bldg A203 Techno2 ro 187 + Yuseong-Gu Daejeon 34025 + KR + +30-09-F9 (hex) IEEE Registration Authority +3009F9 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +B4-DD-D0 (hex) Continental Automotive Hungary Kft +B4DDD0 (base 16) Continental Automotive Hungary Kft + Napmátka u. 6. + Budapest Pest H-1106 + HU + +48-F0-27 (hex) Chengdu newifi Co.,Ltd +48F027 (base 16) Chengdu newifi Co.,Ltd + C11 Building 2001,No.219 ,2nd Tianhua Road,Hi-tech zone + Chengdu Sichuan 610000 + CN + +14-C6-97 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +14C697 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +7C-03-AB (hex) Xiaomi Communications Co Ltd +7C03AB (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +DC-16-B2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +DC16B2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-FB-65 (hex) HUAWEI TECHNOLOGIES CO.,LTD +24FB65 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +0C-B5-27 (hex) HUAWEI TECHNOLOGIES CO.,LTD +0CB527 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B4-2E-99 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +B42E99 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + Pin-Jen City, Taoyuan, Taiwan, R.O.C. + Pin-Jen Taoyuan 324 + TW + +34-2C-C4 (hex) Compal Broadband Networks, Inc. +342CC4 (base 16) Compal Broadband Networks, Inc. + 13F., No.1, Taiyuan 1st St. + Zhubei City Hsinchu County 30265 + TW + +14-E9-B2 (hex) Fiberhome Telecommunication Technologies Co.,LTD +14E9B2 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +C8-54-4B (hex) Zyxel Communications Corporation +C8544B (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +D0-7F-A0 (hex) Samsung Electronics Co.,Ltd +D07FA0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-90-93 (hex) EIZO Corporation +009093 (base 16) EIZO Corporation + 153 Shimokashiwano + Hakusan Ishikawa 924-8856 + JP + +4C-11-59 (hex) Vision Information & Communications +4C1159 (base 16) Vision Information & Communications + 151, Ulseong-gil + Pyeongtaek-si Gyeonggi-do 17823 + KR + +00-04-9F (hex) Freescale Semiconductor +00049F (base 16) Freescale Semiconductor + 2100 East Elliot + Tempe AZ 85284 + US + +00-D0-7B (hex) COMCAM INTERNATIONAL INC +00D07B (base 16) COMCAM INTERNATIONAL INC + 1140 McDermott Drive Suite 200 + WEST CHESTER PA 19380 + US + +78-52-4A (hex) Ensenso GmbH +78524A (base 16) Ensenso GmbH + Gundelfingerstr. 2 + Freiburg 79108 + DE + +E4-FC-82 (hex) Juniper Networks +E4FC82 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-B5-D0 (hex) Samsung Electronics Co.,Ltd +00B5D0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-96-E5 (hex) Samsung Electronics Co.,Ltd +1496E5 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C4-6E-7B (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +C46E7B (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District, + Shenzhen Guangdong 518000 + CN + +C0-48-FB (hex) Shenzhen JingHanDa Electronics Co.Ltd +C048FB (base 16) Shenzhen JingHanDa Electronics Co.Ltd + 5th Floor,No 4 ,Road 1,ShangXue Technology industrial Park,LongGang district,ShenZhen,GuangDong,China + ShenZhen GuangDong 518129 + CN + +20-E8-82 (hex) zte corporation +20E882 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +F0-9F-FC (hex) SHARP Corporation +F09FFC (base 16) SHARP Corporation + 1 Takumi-cho, Sakai-ku + Sakai City Osaka 590-8522 + JP + +0C-B5-DE (hex) Alcatel Lucent +0CB5DE (base 16) Alcatel Lucent + Via Energy Park, 14 + Vimercate MB 20871 + IT + +00-0B-3B (hex) devolo AG +000B3B (base 16) devolo AG + Charlottenburger Allee 67 + Aachen NRW 52068 + DE + +24-05-88 (hex) Google, Inc. +240588 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +50-DC-FC (hex) ECOCOM +50DCFC (base 16) ECOCOM + 15ST,Block A,Fortune Plaza, No.7002 ShenNan Avenue, Futian District + Shenzhen Guangdong 518040 + CN + +70-0B-01 (hex) Sagemcom Broadband SAS +700B01 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +5C-26-23 (hex) WaveLynx Technologies Corporation +5C2623 (base 16) WaveLynx Technologies Corporation + 100 Technology Drive, Building B, Ste 150 + Broomfield CO 80021 + US + +30-38-55 (hex) Nokia Corporation +303855 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu Ou 90590 + FI + +00-B6-70 (hex) Cisco Systems, Inc +00B670 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +AC-64-17 (hex) Siemens AG +AC6417 (base 16) Siemens AG + Werner-von-Siemens Strasse 50 + Amberg 92224 + DE + +34-79-16 (hex) HUAWEI TECHNOLOGIES CO.,LTD +347916 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +34-66-EA (hex) VERTU INTERNATIONAL CORPORATION LIMITED +3466EA (base 16) VERTU INTERNATIONAL CORPORATION LIMITED + 25 St Thomas Street, Winchester, Hampshire, United Kingdom + Winchester Hampshire SO23 9HJ + GB + +28-38-5C (hex) FLEXTRONICS +28385C (base 16) FLEXTRONICS + Carretera Base Aerea 5850 int 4 + Zapopan Jalisco 45136 + MX + +0C-1C-57 (hex) Texas Instruments +0C1C57 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +80-6F-B0 (hex) Texas Instruments +806FB0 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +88-3F-99 (hex) Siemens AG +883F99 (base 16) Siemens AG + Werner-von-Siemens-Str. 48 + Amberg 92224 + DE + +EC-6F-0B (hex) FADU, Inc. +EC6F0B (base 16) FADU, Inc. + 4th FL, 8, Bongeunsa-ro 68-gil, Gangnam-gu + Seoul 06153 + KR + +00-06-EC (hex) Harris Corporation +0006EC (base 16) Harris Corporation + 1025 West NASA Blvd + Melbourne FL 32919 + US + +00-BB-60 (hex) Intel Corporate +00BB60 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +7C-6D-A6 (hex) Superwave Group LLC +7C6DA6 (base 16) Superwave Group LLC + poselok Krasnaya Zarya, dom 15 + Vsevolozhskiy raiyon Leningradskaya oblast 193149 + RU + +D0-16-B4 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D016B4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +20-A8-B9 (hex) SIEMENS AG +20A8B9 (base 16) SIEMENS AG + Oestliche Rheinbrueckenstrasse 50 + Karlsruhe Baden Wuerttemberg 76187 + DE + +F0-F0-8F (hex) Nextek Solutions Pte Ltd +F0F08F (base 16) Nextek Solutions Pte Ltd + 105 Cecil Street, #06-01 The Octagon + Singapore Singapore 069534 + SG + +8C-B0-E9 (hex) Samsung Electronics.,LTD +8CB0E9 (base 16) Samsung Electronics.,LTD + 129, Samsung-ro, Yeongtong-gu + Suwon Gyeonggi-Do 443-742 + KR + +1C-39-47 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +1C3947 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +34-27-92 (hex) FREEBOX SAS +342792 (base 16) FREEBOX SAS + 16 rue de la Ville l'Eveque + PARIS IdF 75008 + FR + +40-A1-08 (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +40A108 (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan + Wuhan Hubei 430000 + CN + +70-5A-B6 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +705AB6 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +20-1A-06 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +201A06 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +F8-A9-63 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +F8A963 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +DC-0E-A1 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +DC0EA1 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone,, Jiangsu, + KUNSHAN SUZHOU 215300 + CN + +B8-70-F4 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +B870F4 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +00-9D-6B (hex) Murata Manufacturing Co., Ltd. +009D6B (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +74-59-33 (hex) Danal Entertainment +745933 (base 16) Danal Entertainment + 9th Fl. Bundang First Tower, 55 Bundang-ro, Bundang-gu + Seongnam-si Gyeonggi-do 13591 + KR + +EC-58-EA (hex) Ruckus Wireless +EC58EA (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +7C-9A-54 (hex) Technicolor CH USA Inc. +7C9A54 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +38-8B-59 (hex) Google, Inc. +388B59 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +88-01-18 (hex) BLT Co +880118 (base 16) BLT Co + Dongan-gu Burim-ro 170beon-gil 44 + Anyangsi Kyunggido 14055 + KR + +A4-26-18 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +A42618 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +34-E1-2D (hex) Intel Corporate +34E12D (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A4-61-91 (hex) NamJunSa +A46191 (base 16) NamJunSa + 12, Gimhae-daero 2635 beon-gil + Gimhae-si Gyeongsangnam-do 50932 + KR + +84-A2-4D (hex) Birds Eye Systems Private Limited +84A24D (base 16) Birds Eye Systems Private Limited + 123-126, B Wing First Floor, Chintanmani Plaza, Mohan Studio Compound, Andheri-Kurla Road, Andheri East + Mumbai Maharashtra 400099 + IN + +7C-6B-9C (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +7C6B9C (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +00-17-B6 (hex) Aquantia Corporation +0017B6 (base 16) Aquantia Corporation + 700 Tasman Drive + Milpitas CA 95035 + US + +10-59-17 (hex) Tonal +105917 (base 16) Tonal + 1074 Folsom St + San Francisco 94103 + US + +D0-EF-C1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D0EFC1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D4-52-51 (hex) IBT Ingenieurbureau Broennimann Thun +D45251 (base 16) IBT Ingenieurbureau Broennimann Thun + Kasernenstrasse 5 + Thun Bern 3600 + CH + +00-18-B5 (hex) Magna Carta +0018B5 (base 16) Magna Carta + Naritaweg 126 + Amsterdam Noord Holland 1043 CA + NL + +D8-7E-B1 (hex) x.o.ware, inc. +D87EB1 (base 16) x.o.ware, inc. + 114 E. Haley St., Ste N + Santa Barbara California 93101 + US + +48-57-02 (hex) HUAWEI TECHNOLOGIES CO.,LTD +485702 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +64-4F-42 (hex) JETTER CO., Ltd. +644F42 (base 16) JETTER CO., Ltd. + 265-40 Emukaecho Tanomoto + Sasebo-shi Nagasaki 859-6134 + JP + +DC-AF-68 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +DCAF68 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Gaoxin 2 Road, Free Trade Zone,Weifang,Shandong,261205,P.R.China + Weifang Shandong 261205 + CN + +24-EC-51 (hex) ADF Technologies Sdn Bhd +24EC51 (base 16) ADF Technologies Sdn Bhd + Plot 88F, Lintang Bayan Lepas 10, Bayan Lepas Industrial Park Phase IV + Bayan Lepas Pulau Pinang 11900 + MY + +70-89-CC (hex) China Mobile Group Device Co.,Ltd. +7089CC (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +2C-5B-E1 (hex) Centripetal Networks, Inc +2C5BE1 (base 16) Centripetal Networks, Inc + 2251 Corporate Park Drive, Suite 150 + Herndon VA 201715806 + US + +DC-EF-CA (hex) Murata Manufacturing Co., Ltd. +DCEFCA (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +00-BC-60 (hex) Cisco Systems, Inc +00BC60 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +CC-7B-61 (hex) NIKKISO CO., LTD. +CC7B61 (base 16) NIKKISO CO., LTD. + Yebisu Garden Place Tower 22nd Floor, 20-3, Ebisu 4-Chome + Shibuya-ku Tokyo 150-6022 + JP + +9C-71-3A (hex) HUAWEI TECHNOLOGIES CO.,LTD +9C713A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +2C-97-B1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +2C97B1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A8-99-69 (hex) Dell Inc. +A89969 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +A4-EA-8E (hex) Extreme Networks, Inc. +A4EA8E (base 16) Extreme Networks, Inc. + 6480 Via Del Oro + San Jose CA 95119 + US + +88-2D-53 (hex) Baidu Online Network Technology (Beijing) Co., Ltd. +882D53 (base 16) Baidu Online Network Technology (Beijing) Co., Ltd. + Baidu Campus, No.10 Shangdi 10th Street, Haidian District Beijing 100085 CN + Beijing 100085 + CN + +00-D0-B5 (hex) IPricot formerly DotCom +00D0B5 (base 16) IPricot formerly DotCom + 10-12, avenue de Verdun + La-Garenne-Colombes F-92250 + FR + +74-6B-AB (hex) GUANGDONG ENOK COMMUNICATION CO., LTD +746BAB (base 16) GUANGDONG ENOK COMMUNICATION CO., LTD + NO.139 Lixiang road, Songmushan Dalang Town + Dongguan, Guangdong 523770 + CN + +0C-B6-D2 (hex) D-Link International +0CB6D2 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +78-29-ED (hex) ASKEY COMPUTER CORP +7829ED (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +50-61-BF (hex) Cisco Systems, Inc +5061BF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-DF (hex) Vestel Elektronik San ve Tic. A.Ş. +0009DF (base 16) Vestel Elektronik San ve Tic. A.Ş. + Organize san + Manisa Turket 45030 + TR + +F4-03-2F (hex) Reduxio Systems +F4032F (base 16) Reduxio Systems + 2 Granit St + Petach Tikvah 4951446 + IL + +94-4A-0C (hex) Sercomm Corporation. +944A0C (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +00-0F-A2 (hex) 2xWireless +000FA2 (base 16) 2xWireless + 1065 Maurader st + Chico CA 95973 + US + +10-8E-E0 (hex) Samsung Electronics Co.,Ltd +108EE0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-A6-21 (hex) Samsung Electronics Co.,Ltd +FCA621 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +8C-F2-28 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +8CF228 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan + Shenzhen Guangdong 518057 + CN + +70-0F-6A (hex) Cisco Systems, Inc +700F6A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-B2 (hex) SMALLBIG TECHNOLOGY +000BB2 (base 16) SMALLBIG TECHNOLOGY + 3F Dongsung Bldg. 720-9 Yoksamdong + Gangnamgu Seoul 135-080 + KR + +00-30-5E (hex) Abelko Innovation +00305E (base 16) Abelko Innovation + Box 808 + Lulea 97125 + SE + +FC-6B-F0 (hex) TOPWELL INTERNATIONAL HOLDINDS LIMITED +FC6BF0 (base 16) TOPWELL INTERNATIONAL HOLDINDS LIMITED + Room 1301-5,Buliding China Youshe,NO.6013,ShenNan Road,CheGong Temple,FuTian District,ShenZhen,GuangDong province,China + SHENZHEN GUANGDONG 518000 + CN + +00-14-77 (hex) Trilliant +001477 (base 16) Trilliant + 950 Cowie st. + Granby Quebec J2J 1P2 + CA + +00-07-9B (hex) Aurora Networks +00079B (base 16) Aurora Networks + 2803 Mission College Blvd. + Santa Clara CA 95054 + US + +54-48-10 (hex) Dell Inc. +544810 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +54-B2-03 (hex) PEGATRON CORPORATION +54B203 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +38-68-DD (hex) INVENTEC CORPORATION +3868DD (base 16) INVENTEC CORPORATION + NO.88, DAZHI RD. + TAOYUAN 33068 + TW + +3C-6A-A7 (hex) Intel Corporate +3C6AA7 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B8-B7-F1 (hex) Wistron Neweb Corporation +B8B7F1 (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +80-50-F6 (hex) ITEL MOBILE LIMITED +8050F6 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +A8-CA-B9 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +A8CAB9 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Maetan3-Dong, Yeongtong-Gu + SUWON KYUNGGI-DO 443-743 + KR + +20-39-56 (hex) HMD Global Oy +203956 (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +78-AF-E4 (hex) Comau S.p.A +78AFE4 (base 16) Comau S.p.A + via Rivalta 30 + Grugliasco (TO) 10095 + IT + +90-A1-37 (hex) Beijing Splendidtel Communication Technology Co,. Ltd +90A137 (base 16) Beijing Splendidtel Communication Technology Co,. Ltd + 4 Floor,Taixing Tower,No.11 Huayuan East Road. Haidian District + Beijing Beijing 100191 + CN + +80-02-9C (hex) Gemtek Technology Co., Ltd. +80029C (base 16) Gemtek Technology Co., Ltd. + No.15-1 Zhonghua Road + Hukou Hsinchu 30352 + TW + +D0-C5-D3 (hex) AzureWave Technology Inc. +D0C5D3 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +14-16-9E (hex) Wingtech Group (HongKong)Limited +14169E (base 16) Wingtech Group (HongKong)Limited + FLAT/RM 1903 19/F PODIUM PLAZA 5HANOI ROAD TSIM SHA TSUI + Hong Kong Hong Kong 999077 + HK + +F8-C3-9E (hex) HUAWEI TECHNOLOGIES CO.,LTD +F8C39E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E8-D0-99 (hex) Fiberhome Telecommunication Technologies Co.,LTD +E8D099 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +10-7B-A4 (hex) Olive & Dove Co.,Ltd. +107BA4 (base 16) Olive & Dove Co.,Ltd. + 803 Polaris bldg., 381, Seongnam-daero, Bundang-gu + Gyeonggi-do Seongnam-si 13555 + KR + +7C-41-A2 (hex) Nokia +7C41A2 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +BC-32-5F (hex) Zhejiang Dahua Technology Co., Ltd. +BC325F (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199,Waterfront Road + Hangzhou Zhejiang 310053 + CN + +50-5B-C2 (hex) Liteon Technology Corporation +505BC2 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +6C-21-A2 (hex) AMPAK Technology, Inc. +6C21A2 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +9C-2F-73 (hex) Universal Tiancheng Technology (Beijing) Co., Ltd. +9C2F73 (base 16) Universal Tiancheng Technology (Beijing) Co., Ltd. + 13 floor,Changxin Building,Anding Road No.39,Chaoyang District,Beijing + Beijing Beijing 100029 + CN + +D8-32-E3 (hex) Xiaomi Communications Co Ltd +D832E3 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +94-87-E0 (hex) Xiaomi Communications Co Ltd +9487E0 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +38-AF-29 (hex) Zhejiang Dahua Technology Co., Ltd. +38AF29 (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199,Waterfront Road + Hangzhou Zhejiang 310053 + CN + +C8-86-29 (hex) Shenzhen Duubee Intelligent Technologies Co.,LTD. +C88629 (base 16) Shenzhen Duubee Intelligent Technologies Co.,LTD. + 9F, Block B, Unicenter, Xin’an Sub district, Bao’an District + Shenzhen GuangDong 518000 + CN + +CC-C2-E0 (hex) Raisecom Technology CO., LTD +CCC2E0 (base 16) Raisecom Technology CO., LTD + No. 11, East Area, No. 10 Block, East Xibeiwang Road + Beijing 100094 + CN + +30-0A-C5 (hex) Ruio telecommunication technologies Co., Limited +300AC5 (base 16) Ruio telecommunication technologies Co., Limited + Room 2501, Broadegate Software Building, No,1003 Keyuan Road, + Shenzhen guangdong 518000 + CN + +00-E0-65 (hex) OPTICAL ACCESS INTERNATIONAL +00E065 (base 16) OPTICAL ACCESS INTERNATIONAL + 500 WEST CUMMINGS PL. #3400 + WOBURN MA 01801 + US + +44-66-FC (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +4466FC (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +A0-28-ED (hex) HMD Global Oy +A028ED (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +AC-54-74 (hex) China Mobile IOT Company Limited +AC5474 (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +8C-1C-DA (hex) IEEE Registration Authority +8C1CDA (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-07-A8 (hex) Haier Group Technologies Ltd +0007A8 (base 16) Haier Group Technologies Ltd + No. 1 Haier Road, Hi-tech Zone + 00000 00000 + CN + +98-14-D2 (hex) Avonic +9814D2 (base 16) Avonic + Distributieweg 60 + Delfgauw 2645EJ + NL + +14-09-DC (hex) HUAWEI TECHNOLOGIES CO.,LTD +1409DC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +EC-93-65 (hex) Mapper.ai, Inc. +EC9365 (base 16) Mapper.ai, Inc. + 400 Treat Ave, Suite G + San Francisco CA 94110 + US + +38-BA-F8 (hex) Intel Corporate +38BAF8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C4-BA-A3 (hex) Beijing Winicssec Technologies Co., Ltd. +C4BAA3 (base 16) Beijing Winicssec Technologies Co., Ltd. + F block 9th floor 907 of Jiahua Building, No.9 Shangdi 3rd Street + Haidian District Beijing 100085 + CN + +9C-FE-A1 (hex) Fiberhome Telecommunication Technologies Co.,LTD +9CFEA1 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +D8-8A-3B (hex) UNIT-EM +D88A3B (base 16) UNIT-EM + 167 Merchants Street + Valletta VLT 1174 + MT + +EC-5A-86 (hex) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd +EC5A86 (base 16) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + Road NO2, West of Industrial Park,North of Science & Technology Park + Dongguan Guangdong 518057 + CN + +C0-EE-B5 (hex) Enice Network. +C0EEB5 (base 16) Enice Network. + NO.30, Shuige Rd, JiangNing Economic Development Zone, Nanjing + Nanjing 211106 + CN + +60-DE-F3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +60DEF3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +50-A0-09 (hex) Xiaomi Communications Co Ltd +50A009 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +88-96-4E (hex) ARRIS Group, Inc. +88964E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +88-3F-4A (hex) Texas Instruments +883F4A (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +9C-A6-15 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +9CA615 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +E4-4E-76 (hex) CHAMPIONTECH ENTERPRISE (SHENZHEN) INC +E44E76 (base 16) CHAMPIONTECH ENTERPRISE (SHENZHEN) INC + Against Office of Dong-Zhou Residential Committee Guang Ming + Shenzhen 518000 + CN + +00-40-98 (hex) DRESSLER GMBH & CO. +004098 (base 16) DRESSLER GMBH & CO. + KACKERTSTRASSE 10 + + DE + +00-1D-FA (hex) Fujian LANDI Commercial Equipment Co.,Ltd +001DFA (base 16) Fujian LANDI Commercial Equipment Co.,Ltd + Building 17,the 1st Section ,Fuzhou Software Park + No.89 Software Road Fuzhou ,Fujian 350003 + CN + +9C-E6-5E (hex) Apple, Inc. +9CE65E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C4-98-80 (hex) Apple, Inc. +C49880 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-33-8E (hex) Apple, Inc. +E0338E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +08-F6-9C (hex) Apple, Inc. +08F69C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-FA-83 (hex) Qingdao Haier Technology Co.,Ltd +04FA83 (base 16) Qingdao Haier Technology Co.,Ltd + Building A01,Haier Information Park, No.1 Haier Road, + Qingdao Shandong 266101 + CN + +78-F9-B4 (hex) Nokia +78F9B4 (base 16) Nokia + Karaportti 3 + Espoo Finland 02610 + FI + +20-16-B9 (hex) Intel Corporate +2016B9 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +D0-76-E7 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +D076E7 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +50-A6-7F (hex) Apple, Inc. +50A67F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D4-61-DA (hex) Apple, Inc. +D461DA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-18-98 (hex) Apple, Inc. +F01898 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-19-08 (hex) Apple, Inc. +881908 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-09-47 (hex) Apple, Inc. +5C0947 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-20-5E (hex) Apple, Inc. +14205E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B8-41-A4 (hex) Apple, Inc. +B841A4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-16-5C (hex) Trackflow Ltd. +00165C (base 16) Trackflow Ltd. + 167-169 Kensington High Street + London England W86SH + GB + +64-1C-AE (hex) Samsung Electronics Co.,Ltd +641CAE (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +F8-E4-4E (hex) MCOT INC. +F8E44E (base 16) MCOT INC. + Yogohigashi 1-5-12 + Matsuyama Ehime 790-0044 + JP + +40-CD-7A (hex) Qingdao Hisense Communications Co.,Ltd. +40CD7A (base 16) Qingdao Hisense Communications Co.,Ltd. + Qianwangang Road 218 + Qingdao Shandong 266510 + CN + +DC-4E-F4 (hex) Shenzhen MTN Electronics CO., Ltd +DC4EF4 (base 16) Shenzhen MTN Electronics CO., Ltd + MTN Industrial Park, No. 5, 9 South Futai Road, Pingxi Community, Pingdi Street, Longgang District + Shenzhen Guangdong 518117 + CN + +F0-81-73 (hex) Amazon Technologies Inc. +F08173 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno 89507 + US + +EC-65-CC (hex) Panasonic Automotive Systems Company of America +EC65CC (base 16) Panasonic Automotive Systems Company of America + 776 Highway 74 South + Peachtree City null 30269 + US + +94-99-90 (hex) VTC Telecommunications +949990 (base 16) VTC Telecommunications + 750 (3rd Floor) Dien Bien Phu, District 10 + Ho Chi Minh Ho Chi Minh 70000 + VN + +F4-BC-97 (hex) Shenzhen Crave Communication Co., LTD +F4BC97 (base 16) Shenzhen Crave Communication Co., LTD + F3,8Building, DongFangMing IndustryZone, No.83 DabaoRD., 33 District BaoAn + Shenzhen 518000 + CN + +28-FE-DE (hex) COMESTA, Inc. +28FEDE (base 16) COMESTA, Inc. + Techno1-ro 61-7, Yuseong-gu, + Daejeon 34014 + KR + +90-79-10 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +907910 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +00-3D-E8 (hex) LG Electronics (Mobile Communications) +003DE8 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +68-FE-DA (hex) Fiberhome Telecommunication Technologies Co.,LTD +68FEDA (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +E8-98-6D (hex) Palo Alto Networks +E8986D (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +14-4E-34 (hex) Remote Solution +144E34 (base 16) Remote Solution + 92, Chogokri, Nammyun + Kimcheon city Kyungbuk 740-871 + KR + +00-50-8B (hex) Hewlett Packard +00508B (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +14-6B-9C (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD +146B9C (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD + NO.268, Fuqian Rd, Jutang community, Guanlan Town, Longhua New district + shenzhen guangdong 518000 + CN + +94-8D-EF (hex) Oetiker Schweiz AG +948DEF (base 16) Oetiker Schweiz AG + Spätzstrasse 11 + Horgen 8810 + CH + +2C-D9-74 (hex) Hui Zhou Gaoshengda Technology Co.,LTD +2CD974 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +D4-F7-86 (hex) Fiberhome Telecommunication Technologies Co.,LTD +D4F786 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +34-03-DE (hex) Texas Instruments +3403DE (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +94-B8-6D (hex) Intel Corporate +94B86D (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +24-0A-63 (hex) ARRIS Group, Inc. +240A63 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F8-8B-37 (hex) ARRIS Group, Inc. +F88B37 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +20-67-7C (hex) Hewlett Packard Enterprise +20677C (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +34-D7-12 (hex) Smartisan Digital Co., Ltd +34D712 (base 16) Smartisan Digital Co., Ltd + 4F, China Digital Kingdom, No.1 Wangjing North Road, Chaoyang District + Beijing Beijing 100012 + CN + +A0-66-10 (hex) FUJITSU LIMITED +A06610 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +44-FF-BA (hex) zte corporation +44FFBA (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +E0-E6-2E (hex) TCT mobile ltd +E0E62E (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +38-78-62 (hex) Sony Mobile Communications Inc +387862 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +E4-2D-7B (hex) China Mobile IOT Company Limited +E42D7B (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +C4-64-E3 (hex) Texas Instruments +C464E3 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +88-17-A3 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +8817A3 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +88-A9-A7 (hex) IEEE Registration Authority +88A9A7 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +EC-89-14 (hex) HUAWEI TECHNOLOGIES CO.,LTD +EC8914 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B8-94-36 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B89436 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +50-14-79 (hex) iRobot Corporation +501479 (base 16) iRobot Corporation + 8 Crosby Drive + Bedford MA 01730 + US + +60-84-BD (hex) BUFFALO.INC +6084BD (base 16) BUFFALO.INC + AKAMONDORI Bld.,30-20,Ohsu 3-chome,Naka-ku + Nagoya Aichi Pref. 460-8315 + JP + +34-7E-CA (hex) NEXTWILL +347ECA (base 16) NEXTWILL + JJ-Building, 20, Deongmyeong-ro 71beon-gil1, Yuseong-gu + Daejeon 34155 + KR + +B4-2E-F8 (hex) Eline Technology co.Ltd +B42EF8 (base 16) Eline Technology co.Ltd + kangcheng Road, Pharmaceutical Industrical Park, Yuanzhou District + Yichun Jiangxi 336000 + CN + +A4-D4-B2 (hex) Shenzhen MeiG Smart Technology Co.,Ltd +A4D4B2 (base 16) Shenzhen MeiG Smart Technology Co.,Ltd + #88 Qinjiang Road, Xuhui District + Shanghai 200233 + CN + +8C-F7-73 (hex) Nokia +8CF773 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +DC-DD-24 (hex) Energica Motor Company SpA +DCDD24 (base 16) Energica Motor Company SpA + Via Cesare della Chiesa, 150 + MODENA (MO) Mo 41126 + IT + +64-1C-B0 (hex) Samsung Electronics Co.,Ltd +641CB0 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +90-3A-72 (hex) Ruckus Wireless +903A72 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +CC-3B-58 (hex) Curiouser Products Inc +CC3B58 (base 16) Curiouser Products Inc + 712 Broadway #4 + New York NY 10003 + US + +4C-EF-C0 (hex) Amazon Technologies Inc. +4CEFC0 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +8C-59-73 (hex) Zyxel Communications Corporation +8C5973 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +24-18-1D (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +24181D (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +58-D7-59 (hex) HUAWEI TECHNOLOGIES CO.,LTD +58D759 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F8-90-66 (hex) Nain Inc. +F89066 (base 16) Nain Inc. + Aoyamadai building 902, Shibuya 2-9-10, Shibuya-ku + Tokyo 150-0002 + JP + +70-06-AC (hex) Eastcompeace Technology Co., Ltd +7006AC (base 16) Eastcompeace Technology Co., Ltd + Number 8 Pinggong Zhong Road,Nanping S&T Industry Community,Zhuhai,Guangdong,519060 China + Zhuhai Guangdong 519060 + CN + +28-02-D8 (hex) Samsung Electronics Co.,Ltd +2802D8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +DC-E5-33 (hex) IEEE Registration Authority +DCE533 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D8-44-5C (hex) DEV Tecnologia Ind Com Man Eq LTDA +D8445C (base 16) DEV Tecnologia Ind Com Man Eq LTDA + Av Prof Lineu Prestes 2242 SL 23 + Sao Paulo SP 05508000 + BR + +50-95-51 (hex) ARRIS Group, Inc. +509551 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +80-41-26 (hex) HUAWEI TECHNOLOGIES CO.,LTD +804126 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +AC-F9-70 (hex) HUAWEI TECHNOLOGIES CO.,LTD +ACF970 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-39-53 (hex) zte corporation +7C3953 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +38-E1-AA (hex) zte corporation +38E1AA (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +48-C7-96 (hex) Samsung Electronics Co.,Ltd +48C796 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F4-C2-48 (hex) Samsung Electronics Co.,Ltd +F4C248 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F4-71-90 (hex) Samsung Electronics Co.,Ltd +F47190 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C4-FF-BC (hex) IEEE Registration Authority +C4FFBC (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +0C-23-69 (hex) Honeywell SPS +0C2369 (base 16) Honeywell SPS + 700 Visions Dr. + Skaneateles Falls NY 13153 + US + +04-C9-D9 (hex) Dish Technologies Corp +04C9D9 (base 16) Dish Technologies Corp + 94 Inverness Terrace E + Englewood CO 80112 + US + +70-55-F8 (hex) Cerebras Systems Inc +7055F8 (base 16) Cerebras Systems Inc + 175 S San Antonio Rd #100 + Los Altos CA 94022 + US + +6C-54-CD (hex) LAMPEX ELECTRONICS LIMITED +6C54CD (base 16) LAMPEX ELECTRONICS LIMITED + 6-2/231/B, Kukatpally, + Hyderabad Telangana 500072 + IN + +00-08-89 (hex) Dish Technologies Corp +000889 (base 16) Dish Technologies Corp + 94 Inverness Terrace E + Englewood CO 80112 + US + +F0-B5-B7 (hex) Disruptive Technologies Research AS +F0B5B7 (base 16) Disruptive Technologies Research AS + Ytrebygdsvegen 215 + Blomsterdalen Hordaland 5258 + NO + +B4-DE-DF (hex) zte corporation +B4DEDF (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +28-3B-82 (hex) D-Link International +283B82 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +D4-90-9C (hex) Apple, Inc. +D4909C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-E0-A6 (hex) Apple, Inc. +E4E0A6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +58-04-54 (hex) ICOMM HK LIMITED +580454 (base 16) ICOMM HK LIMITED + SUITES 2302-6, 23/F GREAT EAGLE CTR 23 HARBOUR RD + WANCHAI NA + HK + +3C-9A-77 (hex) Technicolor CH USA Inc. +3C9A77 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +C4-77-AF (hex) Advanced Digital Broadcast SA +C477AF (base 16) Advanced Digital Broadcast SA + Route de Crassier 21, B2 + Eysins CH-1262 + CH + +A4-86-AE (hex) Quectel Wireless Solutions +A486AE (base 16) Quectel Wireless Solutions + No.1801 Hongmei Road, Xuhui District + Shanghai 200233 + CN + +94-29-0C (hex) Shenyang wisdom Foundation Technology Development Co., Ltd. +94290C (base 16) Shenyang wisdom Foundation Technology Development Co., Ltd. + No. 262 North Main Street, Huanggu District, the Yellow River + shenyang 110000 + CN + +9C-32-CE (hex) CANON INC. +9C32CE (base 16) CANON INC. + 30-2 Shimomaruko 3-chome, + Ohta-ku Tokyo 146-8501 + JP + +20-E0-9C (hex) Nokia +20E09C (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +2C-FD-A1 (hex) ASUSTek COMPUTER INC. +2CFDA1 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +38-07-D4 (hex) Zeppelin Systems GmbH +3807D4 (base 16) Zeppelin Systems GmbH + Messenhäuser Str. 37-45 + Rödermark Hessen 63322 + DE + +04-19-7F (hex) Grasphere Japan +04197F (base 16) Grasphere Japan + 3-1-11 NNT build. + Tokyo 1030013 + JP + +5C-00-38 (hex) Viasat Group S.p.A. +5C0038 (base 16) Viasat Group S.p.A. + Via Aosta 23 + Venaria Reale Torino 10078 + IT + +8C-EC-4B (hex) Dell Inc. +8CEC4B (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +34-41-5D (hex) Intel Corporate +34415D (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-50-91 (hex) NETACCESS, INC. +005091 (base 16) NETACCESS, INC. + 18 KEEWAYDIN DRIVE + SALEM NH 03079 + US + +B8-50-01 (hex) Extreme Networks, Inc. +B85001 (base 16) Extreme Networks, Inc. + ONE ZEBRA PLAZA + HOLTSVILLE NY 11742 + US + +80-2B-F9 (hex) Hon Hai Precision Ind. Co.,Ltd. +802BF9 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +54-B8-02 (hex) Samsung Electronics Co.,Ltd +54B802 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +10-CE-A9 (hex) Texas Instruments +10CEA9 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +80-5E-0C (hex) YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD. +805E0C (base 16) YEALINK(XIAMEN) NETWORK TECHNOLOGY CO.,LTD. + 309, 3th Floor, No.16, Yun Ding North Road, Huli District + xiamen Fujian 361015 + CN + +6C-49-C1 (hex) o2ones Co., Ltd. +6C49C1 (base 16) o2ones Co., Ltd. + 503 Glory Tower, 3-10, Gumi-ro 9beon-gil, Bundang-gu + Seongnam-si Gyeonggi-do 13637 + KR + +70-EE-A3 (hex) Eoptolink Technology Inc. Ltd, +70EEA3 (base 16) Eoptolink Technology Inc. Ltd, + No.127 West Wulian Street + Chengdu China/Sichuan 610213 + CN + +70-47-E9 (hex) vivo Mobile Communication Co., Ltd. +7047E9 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +5C-52-1E (hex) Nintendo Co.,Ltd +5C521E (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +14-44-4A (hex) Apollo Seiko Ltd. +14444A (base 16) Apollo Seiko Ltd. + 2271-7 Jinba + Gotenba Shizuoka 412-0047 + JP + +3C-2C-99 (hex) Edgecore Networks Corporation +3C2C99 (base 16) Edgecore Networks Corporation + 1 Creation RD 3. + Hsinchu 30077 + TW + +88-D0-39 (hex) TCL Technoly Electronics(Huizhou).,Ltd +88D039 (base 16) TCL Technoly Electronics(Huizhou).,Ltd + Section 37, Zhongkai Hi-Tech Development Zone + Huizhou Guangdong 516006 + CN + +68-3E-02 (hex) SIEMENS AG, Digital Factory, Motion Control System +683E02 (base 16) SIEMENS AG, Digital Factory, Motion Control System + Varey Road + Congleton Cheshire CW12 1PH + GB + +00-02-61 (hex) Tilgin AB +000261 (base 16) Tilgin AB + Finlandsgatan 40 + kista 12345 + SE + +00-14-C3 (hex) Seagate Technology +0014C3 (base 16) Seagate Technology + M/S NW1F01 + Longmont CO 80503 + US + +00-04-CF (hex) Seagate Technology +0004CF (base 16) Seagate Technology + M/S NW1F01 + Longmont CO 80503 + US + +00-20-37 (hex) Seagate Technology +002037 (base 16) Seagate Technology + 8001 E. BLOOMINGTON FWY + BLOOMINGTON MN 55420 + US + +5C-81-A7 (hex) Network Devices Pty Ltd +5C81A7 (base 16) Network Devices Pty Ltd + 16 Dickson Ave + Artarmon NSW 2064 + AU + +5C-0C-0E (hex) Guizhou Huaxintong Semiconductor Technology Co Ltd +5C0C0E (base 16) Guizhou Huaxintong Semiconductor Technology Co Ltd + Sitelin Park + Intersection between Jin ma Ave and Qianzhong Ave Gui An New Area, Guizhou Prov 550003 + CN + +50-3C-EA (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +503CEA (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +D0-96-FB (hex) DASAN Network Solutions +D096FB (base 16) DASAN Network Solutions + DASAN Tower 8F, 49 Daewangpangyo-ro644beon-gil Bundang-gu + Seongnam-si Gyeonggi-do 13493 + KR + +00-E0-91 (hex) LG Electronics +00E091 (base 16) LG Electronics + 16, Woomyeon-dong, Seocho-gu + Seoul 137-724 + KR + +38-43-7D (hex) Compal Broadband Networks, Inc. +38437D (base 16) Compal Broadband Networks, Inc. + 13F., No.1, Taiyuan 1st St. + Zhubei City Hsinchu County 30265 + TW + +50-6F-98 (hex) Sehaj Synergy Technologies Private Limited +506F98 (base 16) Sehaj Synergy Technologies Private Limited + E-112A, Kataria Colony, Ramanagar Extension, New Sanganer Road, Sodala, Jaipur-302019 + Jaipur Rajasthan 302019 + IN + +4C-AE-1C (hex) SaiNXT Technologies LLP +4CAE1C (base 16) SaiNXT Technologies LLP + Shop No. 7, Sonawala Building, 1st Floor, Proctor Road, Grant Road (E) + Mumbai Maharashtra 400007 + IN + +14-28-82 (hex) MIDICOM ELECTRONICS CO.LTD +142882 (base 16) MIDICOM ELECTRONICS CO.LTD + Bucheon Techno Park 303-404,345 + Seokcheon-ro,Bucheon-si Gyeonggi-do 1501 + KR + +EC-81-93 (hex) Logitech, Inc +EC8193 (base 16) Logitech, Inc + 4700 NW Camas Meadows Drive + Camas WA 98607 + US + +6C-DD-30 (hex) Cisco Systems, Inc +6CDD30 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +6C-4E-86 (hex) Third Millennium Systems Ltd. +6C4E86 (base 16) Third Millennium Systems Ltd. + 18/19 Torfaen Business Centre, Panteg Way + New Inn, Pontypool Torfaen NP4 0LS + GB + +5C-86-C1 (hex) DONGGUAN SOLUM ELECTRONICS CO.,LTD +5C86C1 (base 16) DONGGUAN SOLUM ELECTRONICS CO.,LTD + NO.157,13 Coastal Way TPFTZ + TIANJIN 300461 + CN + +5C-77-76 (hex) TCT mobile ltd +5C7776 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +70-E5-6E (hex) Texas Instruments +70E56E (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +54-7D-CD (hex) Texas Instruments +547DCD (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +00-AE-CD (hex) Pensando Systems +00AECD (base 16) Pensando Systems + 1730 Technology Drive, Suite 202 + San Jose CA 95110 + US + +FC-9D-D8 (hex) Beijing TongTongYiLian Science and Technology Ltd. +FC9DD8 (base 16) Beijing TongTongYiLian Science and Technology Ltd. + Room 301,Zone 3,Building 9,No.8 Dongbeiwang West Road,Haidian District,Beijing + BEIJING BEIJING 100193 + CN + +DC-28-34 (hex) HAKKO Corporation +DC2834 (base 16) HAKKO Corporation + 4-5, Shiokusa 2-chome, Naniwaku + Osaka Osaka 556-0024 + JP + +84-50-9A (hex) Easy Soft TV Co., Ltd +84509A (base 16) Easy Soft TV Co., Ltd + #1613, Heungduk U-Tower, Heungduk Jung ang-ro 120 + Yongin-si Gyeounggi-do 16950 + KR + +00-17-30 (hex) Automation Electronics +001730 (base 16) Automation Electronics + 111 Big Horn Rd. + Casper Wy 82601 + US + +30-E4-8E (hex) Vodafone UK +30E48E (base 16) Vodafone UK + Vodafone House + Newbury Berkshire RG142FN + GB + +44-91-60 (hex) Murata Manufacturing Co., Ltd. +449160 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +B4-F1-DA (hex) LG Electronics (Mobile Communications) +B4F1DA (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +C8-63-F1 (hex) Sony Interactive Entertainment Inc. +C863F1 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +DC-E1-AD (hex) Shenzhen Wintop Photoelectric Technology Co., Ltd +DCE1AD (base 16) Shenzhen Wintop Photoelectric Technology Co., Ltd + 6th Floor, 1st Building, Zone 3, South Area, Zhongguan& Honghualing Industrial Zone, No. 1213, Liuxian Avenue, Taoyuan Street, Nanshan District, Shenzhen, China + Shenzhen Guangdong 518054 + CN + +94-88-54 (hex) Texas Instruments +948854 (base 16) Texas Instruments + 12500 TI Boulevard + Dallas TX 75243 + US + +00-1D-0D (hex) Sony Interactive Entertainment Inc. +001D0D (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +B0-FC-36 (hex) CyberTAN Technology Inc. +B0FC36 (base 16) CyberTAN Technology Inc. + 99 Park Ave III, Hsinchu Science Park + Hsinchu 308 + TW + +00-1D-F4 (hex) Magellan Technology Pty Limited +001DF4 (base 16) Magellan Technology Pty Limited + 65 Johnston Street + Annandale NSW 2000 + AU + +6C-05-D5 (hex) Ethertronics Inc +6C05D5 (base 16) Ethertronics Inc + 5501 Oberlin Drive, Suite 100 + SAN DIEGO CA 92121 + US + +00-19-C2 (hex) Equustek Solutions, Inc. +0019C2 (base 16) Equustek Solutions, Inc. + #286 - 5489 Byrne Road, + Burnaby BC V5J 3J1 + CA + +80-00-0B (hex) Intel Corporate +80000B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +EC-B0-E1 (hex) Ciena Corporation +ECB0E1 (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +78-DD-D9 (hex) Guangzhou Shiyuan Electronics Co., Ltd. +78DDD9 (base 16) Guangzhou Shiyuan Electronics Co., Ltd. + No.6, 4th Yunpu Road, Yunpu Industry District + Guangzhou Guangdong 510530 + CN + +F8-B7-E2 (hex) Cisco Systems, Inc +F8B7E2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F8-20-55 (hex) Green Information System +F82055 (base 16) Green Information System + #202(Shopping center), Woldong-ro 28, Buk-gu + Gwangju 61153 + KR + +74-E1-9A (hex) Fiberhome Telecommunication Technologies Co.,LTD +74E19A (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +00-00-97 (hex) Dell EMC +000097 (base 16) Dell EMC + 176 South Street + Hopkinton MA 01748 + US + +8C-CF-09 (hex) Dell EMC +8CCF09 (base 16) Dell EMC + 228 South St + Hopkinton MA 01748 + US + +8C-83-9D (hex) SHENZHEN XINYUPENG ELECTRONIC TECHNOLOGY CO., LTD +8C839D (base 16) SHENZHEN XINYUPENG ELECTRONIC TECHNOLOGY CO., LTD + ROOM 1505,BIT INNOVATION BUILDING,SCIENCE AND TECHNOLOGY PARK,NANSHAN DISTRICT + Shenzhen 518057 + CN + +B0-C1-9E (hex) zte corporation +B0C19E (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +0C-37-47 (hex) zte corporation +0C3747 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +AC-A6-67 (hex) Electronic Systems Protection, Inc. +ACA667 (base 16) Electronic Systems Protection, Inc. + 8001 Knightdale Blvd. + Knightdale NC 27545 + US + +00-81-F9 (hex) Texas Instruments +0081F9 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +EC-B5-FA (hex) Philips Lighting BV +ECB5FA (base 16) Philips Lighting BV + High Tech Campus 45 + Eindhoven Noord Brabant 5656 AE + NL + +44-CD-0E (hex) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. +44CD0E (base 16) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + Xin Qing Science & Technology Industrial Park,Jin An Town,Doumen ,Zhuhai,Guangdong,PRC + Zhuhai Guangdong 519180 + CN + +E8-82-5B (hex) ARRIS Group, Inc. +E8825B (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +70-99-1C (hex) Shenzhen Honesty Electronics Co.,Ltd +70991C (base 16) Shenzhen Honesty Electronics Co.,Ltd + 5/F,Zone B,Chitat Industrial Park,West Longping Road + Shenzhen City Longgang District, Guangdong 518172 + CN + +80-B0-3D (hex) Apple, Inc. +80B03D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-9A-DC (hex) Apple, Inc. +E49ADC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-E4-B5 (hex) Apple, Inc. +ACE4B5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-D2-B0 (hex) Apple, Inc. +D0D2B0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-1C-AE (hex) WiChorus, Inc. +001CAE (base 16) WiChorus, Inc. + 3590 N 1st Street, Suite 300 + San Jose CA 95134 + US + +7C-DD-76 (hex) Suzhou Hanming Technologies Co., Ltd. +7CDD76 (base 16) Suzhou Hanming Technologies Co., Ltd. + Suite 407, No. 166, Ren Ai Road + Suzhou Jiangsu 215123 + CN + +24-68-80 (hex) Braveridge.co.,ltd. +246880 (base 16) Braveridge.co.,ltd. + 3-27-2, Susenji + Nishi-ku, Fukuoka-shi Fukuoka 819-0373 + JP + +F0-92-B4 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +F092B4 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +E8-DF-70 (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +E8DF70 (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +28-AD-3E (hex) Shenzhen TONG BO WEI Technology CO.,LTD +28AD3E (base 16) Shenzhen TONG BO WEI Technology CO.,LTD + Longhua District, Dalang street Langkou community Huarong Road Peng Tengda Industrial Park 4 5 floor + SHENZHEN guangdong 518109 + CN + +00-1C-56 (hex) Pado Systems, Inc. +001C56 (base 16) Pado Systems, Inc. + #706 Loadland EZ Tower 153 + SungNam Gyung gi-Do 463-810 + KR + +F0-6D-78 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +F06D78 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +78-44-FD (hex) TP-LINK TECHNOLOGIES CO.,LTD. +7844FD (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +EC-F8-EB (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +ECF8EB (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +70-7D-95 (hex) Shenzhen City LinwlanTechnology Co. Ltd. +707D95 (base 16) Shenzhen City LinwlanTechnology Co. Ltd. + 106 village road , manhole street Baoan district . + Shenzhen Guangdong 518125 + CN + +2C-43-1A (hex) Shenzhen YOUHUA Technology Co., Ltd +2C431A (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +A8-D3-C8 (hex) Topcon Electronics GmbH & Co. KG +A8D3C8 (base 16) Topcon Electronics GmbH & Co. KG + Industriestraße 7 + Geisenheim 65366 + DE + +D0-59-95 (hex) Fiberhome Telecommunication Technologies Co.,LTD +D05995 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +18-CC-88 (hex) Hitachi Johnson Controls Air +18CC88 (base 16) Hitachi Johnson Controls Air + 390 Number + Shimizu Village Village Shizuoka Prefecture 424-0926 + JP + +80-C7-55 (hex) Panasonic Appliances Company +80C755 (base 16) Panasonic Appliances Company + 2-3-1-2 Noji-higashi + Kusatsu City Shiga 525-8555 + JP + +F0-BD-2E (hex) H+S Polatis Ltd +F0BD2E (base 16) H+S Polatis Ltd + 332/2 Cambridge Science Park + Cambridge CB4 0WN + GB + +74-6E-E4 (hex) Asia Vital Components Co.,Ltd. +746EE4 (base 16) Asia Vital Components Co.,Ltd. + Rm. 3, 7F., No.24, Wuquan 2nd Rd., Xinzhuang Dist., + New Taipei Taiwan 24892 + TW + +00-40-E4 (hex) E-M TECHNOLOGY, INC. +0040E4 (base 16) E-M TECHNOLOGY, INC. + 9245 SOUTHWEST NIMBUS AVE. + BEAVERTON OR 97005 + US + +98-4B-4A (hex) ARRIS Group, Inc. +984B4A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E0-84-F3 (hex) High Grade Controls Corporation +E084F3 (base 16) High Grade Controls Corporation + 87 Magill Street + Sudbury Ontario P3Y1K6 + CA + +38-A6-CE (hex) BSkyB Ltd +38A6CE (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +34-56-FE (hex) Cisco Meraki +3456FE (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco null 94158 + US + +70-70-8B (hex) Cisco Systems, Inc +70708B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +38-9F-5A (hex) C-Kur TV Inc. +389F5A (base 16) C-Kur TV Inc. + A-1902, 583, Yangcheon-ro, Gangseo-gu + Seoul 07547 + KR + +D8-43-ED (hex) Suzuken +D843ED (base 16) Suzuken + 8, Higashikatahamachi, Higashiku + Nagoya Aich 4610015 + JP + +BC-41-01 (hex) Shenzhen TINNO Mobile Technology Corp. +BC4101 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F, H-3 Building, Qiao Cheng Eastern Industrial Park, Overseas Chinese Town, Shenzhen + Shenzhen guangdong 518053 + CN + +04-3A-0D (hex) SM Optics S.r.l. +043A0D (base 16) SM Optics S.r.l. + via Michelangelo Buonarroti, 1 + Cologno Monzese Milan I-20093 + IT + +44-8F-17 (hex) Samsung Electronics Co., Ltd. ARTIK +448F17 (base 16) Samsung Electronics Co., Ltd. ARTIK + 1-1, Samsungjeonja-ro + Hwaseong-si Gyeonggi-do 18448 + KR + +00-FC-8B (hex) Amazon Technologies Inc. +00FC8B (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +00-76-B1 (hex) Somfy-Protect By Myfox SAS +0076B1 (base 16) Somfy-Protect By Myfox SAS + Regent Park II, Bât I, 2460 l'Occitane + Labège 31670 + FR + +6C-C1-47 (hex) Xiamen Hanin Electronic Technology Co., Ltd +6CC147 (base 16) Xiamen Hanin Electronic Technology Co., Ltd + #8 building, Gaoqi Nan Shi'er Road, Huli Distric + Xiamen Fujian 361000 + CN + +A0-72-E4 (hex) NJ SYSTEM CO.,LTD +A072E4 (base 16) NJ SYSTEM CO.,LTD + Urim lions valley 5cha, A-1701, 144-3, Sangdaewon-dong, Jungwon-gu + Seongnam Gyeonggido 13201 + KR + +4C-13-65 (hex) Emplus Technologies +4C1365 (base 16) Emplus Technologies + Bld B, 10F, No.209, Sec.1, Nangang Rd + Taipei 115 + TW + +CC-F9-57 (hex) u-blox AG +CCF957 (base 16) u-blox AG + Zuercherstrasse 68 + Thalwil 8800 + CH + +0C-62-A6 (hex) Hui Zhou Gaoshengda Technology Co.,LTD +0C62A6 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +18-13-2D (hex) zte corporation +18132D (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +74-D2-1D (hex) HUAWEI TECHNOLOGIES CO.,LTD +74D21D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-78-D4 (hex) Verizon +1878D4 (base 16) Verizon + One Verizon Way + Basking Ridge NJ 07920 + US + +B8-D9-4D (hex) Sagemcom Broadband SAS +B8D94D (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +38-90-A5 (hex) Cisco Systems, Inc +3890A5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C0-74-2B (hex) SHENZHEN XUNLONG SOFTWARE CO.,LIMITED +C0742B (base 16) SHENZHEN XUNLONG SOFTWARE CO.,LIMITED + Room 532, Block A, Huameiju Business Center, Xinhu Road, Baoan 82 Area + Shenzhen Guangdong 518133 + CN + +5C-67-76 (hex) IDS Imaging Development Systems GmbH +5C6776 (base 16) IDS Imaging Development Systems GmbH + Dimbacher Str. 6 + Obersulm BW 74182 + DE + +44-EA-D8 (hex) Texas Instruments +44EAD8 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +18-9B-A5 (hex) IEEE Registration Authority +189BA5 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +A4-91-B1 (hex) Technicolor +A491B1 (base 16) Technicolor + Prins Boudewijnlaan 47 + Edegem - Belgium B-2650 + BE + +1C-70-22 (hex) Murata Manufacturing Co., Ltd. +1C7022 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +CC-98-91 (hex) Cisco Systems, Inc +CC9891 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +28-BF-89 (hex) Fiberhome Telecommunication Technologies Co.,LTD +28BF89 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +90-3D-BD (hex) SECURE METERS LIMITED +903DBD (base 16) SECURE METERS LIMITED + E CLASS, PRATAP NAGAR INDUSTRIAL AREA + UDAIPUR RAJASTHAN 313003 + IN + +00-22-94 (hex) KYOCERA CORPORATION +002294 (base 16) KYOCERA CORPORATION + 2-1-1,Kagahara + Yokohama-shi Kanagawa 224-8502 + JP + +38-89-DC (hex) Opticon Sensors Europe B.V. +3889DC (base 16) Opticon Sensors Europe B.V. + Opaallaan 35 + Hoofddorp Noord Holland 2132 XV + NL + +8C-45-00 (hex) Murata Manufacturing Co., Ltd. +8C4500 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +1C-DD-EA (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +1CDDEA (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +94-00-06 (hex) jinyoung +940006 (base 16) jinyoung + 1000 Dongil-ro Nowon-gu Seoul + Seoul 01849 + KR + +74-E5-F9 (hex) Intel Corporate +74E5F9 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +20-04-0F (hex) Dell Inc. +20040F (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +A4-34-12 (hex) Thales Alenia Space +A43412 (base 16) Thales Alenia Space + 26 av JF Champollion + Toulouse 31037 + FR + +8C-85-90 (hex) Apple, Inc. +8C8590 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-88-C3 (hex) Ningbo Dooya Mechanic & Electronic Technology Co., Ltd +BC88C3 (base 16) Ningbo Dooya Mechanic & Electronic Technology Co., Ltd + No.168 Shengguang road Luotuo street Zhenhai district + Ningbo Zhejiang 315202 + CN + +38-CD-07 (hex) Beijing FaceCam Technology Co., Ltd. +38CD07 (base 16) Beijing FaceCam Technology Co., Ltd. + Room C115, DongSheng Building, No 8, East Road, Zhongguan Town, Haidian District + Beijing 100083 + CN + +00-D0-60 (hex) Panasonic Europe Ltd. +00D060 (base 16) Panasonic Europe Ltd. + LABORATORIES GMBH + + DE + +EC-FA-03 (hex) FCA +ECFA03 (base 16) FCA + 800 Chrylser Dr + Auburn Hills MI 48326 + US + +6C-96-CF (hex) Apple, Inc. +6C96CF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-1F-40 (hex) Blu Wireless Technology Ltd +681F40 (base 16) Blu Wireless Technology Ltd + Bluwireless Technology, 5th Floor, 1 Temple Way + Bristol Bristol, City of BS2 0BY + GB + +90-AD-F7 (hex) vivo Mobile Communication Co., Ltd. +90ADF7 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +40-CE-24 (hex) Cisco Systems, Inc +40CE24 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +34-32-E6 (hex) Panasonic Industrial Devices Europe GmbH +3432E6 (base 16) Panasonic Industrial Devices Europe GmbH + Zeppelinstraße 19 + Lüneburg 21337 + DE + +40-01-7A (hex) Cisco Systems, Inc +40017A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +78-88-6D (hex) Apple, Inc. +78886D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-EE-28 (hex) Apple, Inc. +20EE28 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B4-F6-1C (hex) Apple, Inc. +B4F61C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +08-F4-AB (hex) Apple, Inc. +08F4AB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-01-7C (hex) Hon Hai Precision Ind. Co.,Ltd. +FC017C (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +90-32-4B (hex) Hon Hai Precision Ind. Co.,Ltd. +90324B (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +60-2E-20 (hex) HUAWEI TECHNOLOGIES CO.,LTD +602E20 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E4-72-E2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E472E2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-12-7D (hex) MobileAria +00127D (base 16) MobileAria + 800 W El Camino Real #240 + Mountain View CA 94040 + US + +F8-64-65 (hex) Anova Applied Electronics, Inc. +F86465 (base 16) Anova Applied Electronics, Inc. + 580 Howard Street, #403 + san francisco CA 94105 + US + +00-20-60 (hex) ALCATEL ITALIA S.p.A. +002060 (base 16) ALCATEL ITALIA S.p.A. + VIA TRENTO, 30 + 20059 VIMERCATE (MI) + IT + +A0-88-69 (hex) Intel Corporate +A08869 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +50-8F-4C (hex) Xiaomi Communications Co Ltd +508F4C (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +A4-77-58 (hex) Ningbo Freewings Technologies Co.,Ltd +A47758 (base 16) Ningbo Freewings Technologies Co.,Ltd + No.502 Wenshui Road, Shounan Street, Yinzhou District + Ningbo Zhejiang 315192 + CN + +58-A0-CB (hex) TrackNet, Inc +58A0CB (base 16) TrackNet, Inc + 900 Lafayette Street #329 + Santa Clara CA 95050 + US + +00-0C-EC (hex) Spectracom Corp. +000CEC (base 16) Spectracom Corp. + 95 Methodist Hill Drive + Rochester NY 14623 + US + +E0-60-89 (hex) Cloudleaf, Inc. +E06089 (base 16) Cloudleaf, Inc. + 860 Hillview Court, Suite 350 + Milpitas CA 95035 + US + +78-36-90 (hex) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd +783690 (base 16) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + Road NO2, West of Industrial Park,North of Science & Technology Park + Dongguan Guangdong 518057 + CN + +BC-54-FC (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +BC54FC (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + 3/F, Building R1-B, High-Tech Industrial Park, Nanshan District + Shenzhen Guangdong 518057 + CN + +0C-4B-54 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +0C4B54 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +E4-F0-04 (hex) Dell Inc. +E4F004 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +94-E3-6D (hex) Texas Instruments +94E36D (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +F0-F8-F2 (hex) Texas Instruments +F0F8F2 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +34-15-13 (hex) Texas Instruments +341513 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +74-81-9A (hex) PT. Hartono Istana Teknologi +74819A (base 16) PT. Hartono Istana Teknologi + KHR Asnawi + Kudus Jawa Tengah 59332 + ID + +28-35-45 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD +283545 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + Unit East Block22-24/F,Skyworth semiconductor design Bldg., Gaoxin Ave.4.S.,Nanshan District,Shenzhen,China + SHENZHEN GUANGDONG 518057 + CN + +04-4F-4C (hex) HUAWEI TECHNOLOGIES CO.,LTD +044F4C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-B8-1F (hex) ARRIS Group, Inc. +18B81F (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +1C-15-1F (hex) HUAWEI TECHNOLOGIES CO.,LTD +1C151F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-8B-FC (hex) mixi,Inc. +008BFC (base 16) mixi,Inc. + Sumitomo Shibuya First Tower 7F, 1-2-20 Higashi + Shibuya-ku Tokyo 150-0011 + JP + +A8-2B-B5 (hex) Edgecore Networks Corporation +A82BB5 (base 16) Edgecore Networks Corporation + 1 Creation RD 3. + Hsinchu 30077 + TW + +60-F6-77 (hex) Intel Corporate +60F677 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +E8-E1-E2 (hex) Energotest +E8E1E2 (base 16) Energotest + Chorzowska 44B + Gliwice Slask 44-100 + PL + +78-11-DC (hex) XIAOMI Electronics,CO.,LTD +7811DC (base 16) XIAOMI Electronics,CO.,LTD + Xiaomi Building, No.68 Qinghe Middle Street + Haidian District Beijing 100085 + CN + +D4-63-C6 (hex) Motorola Mobility LLC, a Lenovo Company +D463C6 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +F8-44-E3 (hex) Taicang T&W Electronics +F844E3 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +24-A5-34 (hex) SynTrust Tech International Ltd. +24A534 (base 16) SynTrust Tech International Ltd. + 10F-1, No. 125, Songde Road, + Taipei Taiwan 110 + TW + +C4-44-A0 (hex) Cisco Systems, Inc +C444A0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +18-74-2E (hex) Amazon Technologies Inc. +18742E (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno 89507 + US + +90-A3-65 (hex) HMD Global Oy +90A365 (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +DC-44-B6 (hex) Samsung Electronics Co.,Ltd +DC44B6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +10-07-B6 (hex) Samsung Electronics Co.,Ltd +1007B6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +34-2D-0D (hex) Samsung Electronics Co.,Ltd +342D0D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A4-4C-C8 (hex) Dell Inc. +A44CC8 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +D8-37-BE (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +D837BE (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + #1905 Mei Hong Road + Shanghai Shanghai 200000 + CN + +D4-68-4D (hex) Ruckus Wireless +D4684D (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +8C-0C-90 (hex) Ruckus Wireless +8C0C90 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +6C-AA-B3 (hex) Ruckus Wireless +6CAAB3 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +00-13-92 (hex) Ruckus Wireless +001392 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +08-51-14 (hex) QINGDAO TOPSCOMM COMMUNICATION CO., LTD +085114 (base 16) QINGDAO TOPSCOMM COMMUNICATION CO., LTD + 7/F, Building 6, NO.288, Ningxia Road + Qingdao Shandong 266024 + CN + +D0-5A-00 (hex) Technicolor CH USA Inc. +D05A00 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +70-78-8B (hex) vivo Mobile Communication Co., Ltd. +70788B (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +48-59-A4 (hex) zte corporation +4859A4 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +54-BD-79 (hex) Samsung Electronics Co.,Ltd +54BD79 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +A0-42-3F (hex) Tyan Computer Corp +A0423F (base 16) Tyan Computer Corp + 3288 Larurelview Court + Fremont CA 94538 + US + +70-F1-1C (hex) Shenzhen Ogemray Technology Co.,Ltd +70F11C (base 16) Shenzhen Ogemray Technology Co.,Ltd + 4/F,5Bldg,Dongwu Industrial Park, Donghuan 1st Rd, Longhua District. + Shenzhen 518059 + CN + +70-65-A3 (hex) Kandao lightforge Co., Ltd. +7065A3 (base 16) Kandao lightforge Co., Ltd. + 5th Floor, M7 Steel Building, the second way in Technology Road , Nanshan District, + Shenzhen Guangdong 518057 + CN + +14-14-4B (hex) Ruijie Networks Co.,LTD +14144B (base 16) Ruijie Networks Co.,LTD + 19-22# Building,Star-net Science Plaza,Juyuanzhou, + FUZHOU FUJIAN 350002 + CN + +74-D0-DC (hex) Ericsson AB +74D0DC (base 16) Ericsson AB + Torshamnsgatan 48 + STOCKHOLM 164 83 + SE + +C0-8A-DE (hex) Ruckus Wireless +C08ADE (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +00-1D-2E (hex) Ruckus Wireless +001D2E (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +B4-E6-2A (hex) LG Innotek +B4E62A (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +A0-C5-F2 (hex) IEEE Registration Authority +A0C5F2 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +A8-6B-7C (hex) SHENZHEN FENGLIAN TECHNOLOGY CO., LTD. +A86B7C (base 16) SHENZHEN FENGLIAN TECHNOLOGY CO., LTD. + ORIENTAL CYBERPORT, HIGHTECH 6 ROAD + SHENZHEN GUANGDONG 518057 + CN + +B0-39-56 (hex) NETGEAR +B03956 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +3C-0C-DB (hex) UNIONMAN TECHNOLOGY CO.,LTD +3C0CDB (base 16) UNIONMAN TECHNOLOGY CO.,LTD + 18F, HUAYANG TOWER,YANDAYI ROAD + Huizhou Guangdong 516007 + CN + +EC-42-B4 (hex) ADC Corporation +EC42B4 (base 16) ADC Corporation + 77-1, Miyako + Namegawa-machi, Hiki-gun Saitama Pref. 355-0812 + JP + +60-DA-83 (hex) Hangzhou H3C Technologies Co., Limited +60DA83 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +2C-57-31 (hex) Wingtech Group (HongKong)Limited +2C5731 (base 16) Wingtech Group (HongKong)Limited + FLAT/RM 1903 19/F PODIUM PLAZA 5HANOI ROAD TSIM SHA TSUI + Hong Kong Hong Kong 999077 + HK + +CC-46-39 (hex) WAAV, Inc. +CC4639 (base 16) WAAV, Inc. + 151 PEARL ST FL 4 + BOSTON MA 02110 + US + +AC-9E-17 (hex) ASUSTek COMPUTER INC. +AC9E17 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +64-16-66 (hex) Nest Labs Inc. +641666 (base 16) Nest Labs Inc. + 3400 Hillview Ave. + Palo Alto CA 94304 + US + +D8-DF-7A (hex) Quest Software, Inc. +D8DF7A (base 16) Quest Software, Inc. + 4 Polaris Way + Aliso Viejo CA 92656 + US + +14-5B-E1 (hex) nyantec GmbH +145BE1 (base 16) nyantec GmbH + Europaplatz 2 + Berlin 10557 + DE + +A0-23-9F (hex) Cisco Systems, Inc +A0239F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +70-F3-5A (hex) Cisco Systems, Inc +70F35A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A0-34-1B (hex) Adero Inc +A0341B (base 16) Adero Inc + 7410 HOllister Ave + Goleta CA 93117 + US + +A0-AF-BD (hex) Intel Corporate +A0AFBD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +7C-8B-CA (hex) TP-LINK TECHNOLOGIES CO.,LTD. +7C8BCA (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +B0-4E-26 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +B04E26 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +B0-89-C2 (hex) Zyptonite +B089C2 (base 16) Zyptonite + 1460 Broadway, 12 fl. + New York NY 10036 + US + +F0-23-B9 (hex) IEEE Registration Authority +F023B9 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +FC-4D-D4 (hex) Universal Global Scientific Industrial Co., Ltd. +FC4DD4 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, Lane 351, Taiping Rd. Sec. 1, Tsao Tuen, + Nan-Tou Hsien, 542 + TW + +A4-F4-C2 (hex) VNPT TECHNOLOGY +A4F4C2 (base 16) VNPT TECHNOLOGY + HoaLac Hi-Tech Park + HANOI HANOI 10000 + VN + +8C-14-7D (hex) IEEE Registration Authority +8C147D (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +30-07-4D (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +30074D (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +1C-1F-D4 (hex) LifeBEAM Technologies LTD +1C1FD4 (base 16) LifeBEAM Technologies LTD + 150 Greenwich st 4WTC - 29th floor + New York NY 10007 + US + +00-9A-D2 (hex) Cisco Systems, Inc +009AD2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +44-7F-77 (hex) Connected Home +447F77 (base 16) Connected Home + 19-22, Rathbone Place + London W1T 1HY + GB + +E8-B6-C2 (hex) Juniper Networks +E8B6C2 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +94-7B-E7 (hex) Samsung Electronics Co.,Ltd +947BE7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +50-92-B9 (hex) Samsung Electronics Co.,Ltd +5092B9 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +DC-74-A8 (hex) Samsung Electronics Co.,Ltd +DC74A8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E8-39-35 (hex) Hewlett Packard +E83935 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +00-18-0A (hex) Cisco Meraki +00180A (base 16) Cisco Meraki + 99 Rhode Island St. + San Francisco, CA 94103 + US + +5C-6A-80 (hex) Zyxel Communications Corporation +5C6A80 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +D8-60-B3 (hex) Guangdong Global Electronic Technology CO.,LTD +D860B3 (base 16) Guangdong Global Electronic Technology CO.,LTD + Floor4 East side,build#6,Huangzhou industry Park, chebei Road, Tianhe District + GuangZhou GuangDong 510660 + CN + +64-35-1C (hex) e-CON SYSTEMS INDIA PVT LTD +64351C (base 16) e-CON SYSTEMS INDIA PVT LTD + RR Tower 4, 7th Floor, TVK IND Estate, Guindy + Chennai Other 600032 + IN + +60-BA-18 (hex) nextLAP GmbH +60BA18 (base 16) nextLAP GmbH + Hofmannstr. 61 + München 81379 + DE + +44-AA-50 (hex) Juniper Networks +44AA50 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +84-CD-62 (hex) ShenZhen IDWELL Technology CO.,Ltd +84CD62 (base 16) ShenZhen IDWELL Technology CO.,Ltd + 4F,Building 20 Changxing Industrial Park,Shayi,Shajing,BaoAn + ShenZhen 518000 + CN + +A8-D5-79 (hex) Beijing Chushang Science and Technology Co.,Ltd +A8D579 (base 16) Beijing Chushang Science and Technology Co.,Ltd + 3A285 room,3 layer,1 building,No 11 of yongwai song zhuang road,Fengtai district,Beijing + Beijing Beijing 518000 + CN + +44-48-C1 (hex) Hewlett Packard Enterprise +4448C1 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +48-10-63 (hex) NTT Innovation Institute, Inc. +481063 (base 16) NTT Innovation Institute, Inc. + 1950 University Avenue, Suite 600 + East Palo Alto CA 94303 + US + +A0-8E-78 (hex) Sagemcom Broadband SAS +A08E78 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +88-D5-0C (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +88D50C (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +D4-28-D5 (hex) TCT mobile ltd +D428D5 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +9C-AF-6F (hex) ITEL MOBILE LIMITED +9CAF6F (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +FC-53-9E (hex) Shanghai Wind Technologies Co.,Ltd +FC539E (base 16) Shanghai Wind Technologies Co.,Ltd + Floor 8,East Building,Guilin Technology Mansion,No.650,Caobao Road,XuHui District,Shanghai,P.R.China + Shanghai Shanghai 200233 + CN + +60-53-17 (hex) Sandstone Technologies +605317 (base 16) Sandstone Technologies + 1920 lyell ave + Rochester NY 14606 + US + +90-70-65 (hex) Texas Instruments +907065 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +18-A9-58 (hex) PROVISION THAI CO., LTD. +18A958 (base 16) PROVISION THAI CO., LTD. + 155/7-10 Rachadapisek Rd., + Thonburi Bangkok 10600 + TH + +74-C9-A3 (hex) Fiberhome Telecommunication Technologies Co.,LTD +74C9A3 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +EC-8A-4C (hex) zte corporation +EC8A4C (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +D4-5F-25 (hex) Shenzhen YOUHUA Technology Co., Ltd +D45F25 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +40-C8-CB (hex) AM Telecom co., Ltd. +40C8CB (base 16) AM Telecom co., Ltd. + #608,YatapLeaders B/D, Jangmi-ro 42, Bundang-gu + Seongnam-si Gyeonggi-do 463-828 + KR + +2C-AB-EB (hex) Cisco Systems, Inc +2CABEB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C8-3A-6B (hex) Roku, Inc +C83A6B (base 16) Roku, Inc + 150 Winchester Circle + Los Gatos CA 95032 + US + +B4-C6-F8 (hex) Axilspot Communication +B4C6F8 (base 16) Axilspot Communication + A302 Han's Innovation Building, No.9018 Beihuan Ave., Nanshan District + Shenzhen 518000 + CN + +9C-E9-51 (hex) Shenzhen Sang Fei Consumer Communications Ltd., Co. +9CE951 (base 16) Shenzhen Sang Fei Consumer Communications Ltd., Co. + 11,Science And Technology Road, Shenzhen Hi-tech Industrial Park, Nanshan District + Shenzhen City Guangdong 518057 + CN + +B8-D5-0B (hex) Sunitec Enterprise Co.,Ltd +B8D50B (base 16) Sunitec Enterprise Co.,Ltd + 3F.,No.98-1,Mincyuan Rd.Sindian City + Taipei County 231 231141 + CN + +BC-66-DE (hex) Shadow Creator Information Technology Co.,Ltd. +BC66DE (base 16) Shadow Creator Information Technology Co.,Ltd. + Shanghai City, Pudong New Area Zhangjiang road 368, Building 29, room 611 + Shanghai Shanghai 200120 + CN + +18-68-CB (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +1868CB (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.469,Jianghui Road + Hangzhou Zhejiang 310052 + CN + +C4-AE-12 (hex) Samsung Electronics Co.,Ltd +C4AE12 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +00-1F-A4 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +001FA4 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + 4F,Baiying Building, No.1019,Nanhai RD,Shekou, + ShenZhen GuangDong 518067 + CN + +D4-DC-CD (hex) Apple, Inc. +D4DCCD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-4B-AA (hex) Apple, Inc. +484BAA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +DC-A9-04 (hex) Apple, Inc. +DCA904 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-AB-31 (hex) Apple, Inc. +6CAB31 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +4C-74-BF (hex) Apple, Inc. +4C74BF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-94-6B (hex) TECNO MOBILE LIMITED +04946B (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +A0-4C-5B (hex) Shenzhen TINNO Mobile Technology Corp. +A04C5B (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F, H-3 Building, Qiao Cheng Eastern Industrial Park, Overseas Chinese Town, Shenzhen + Shenzhen guangdong 518053 + CN + +48-88-03 (hex) ManTechnology Inc. +488803 (base 16) ManTechnology Inc. + 12th Fl, 308-4 Seongsoodong 2ga, Seongdonggu + Seoul 04781 + KR + +B4-36-E3 (hex) KBVISION GROUP +B436E3 (base 16) KBVISION GROUP + 337 N. Vineyard Avenue, 4th Floor, San Jose, CA 91764 + San Jose CA 90847 + US + +94-D2-99 (hex) Techmation Co.,Ltd. +94D299 (base 16) Techmation Co.,Ltd. + 9F., No.529, Zhongzheng Rd., Xindian Dist., New Taipei City 231, Taiwan + New Taipei City 231 + TW + +34-1A-35 (hex) Fiberhome Telecommunication Technologies Co.,LTD +341A35 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +2C-02-9F (hex) 3ALogics +2C029F (base 16) 3ALogics + #704, Hyundai office B'd, Sunae-dong, Bundang-gu + Seongnam-si 13601 + KR + +64-D1-54 (hex) Routerboard.com +64D154 (base 16) Routerboard.com + Mikrotikls SIA + Riga Riga LV1009 + LV + +58-D9-D5 (hex) Tenda Technology Co.,Ltd.Dongguan branch +58D9D5 (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +6C-4B-90 (hex) LiteON +6C4B90 (base 16) LiteON + 5F, No.90, Rd. Chien 1, ChungHo + New Taipei Taiwan 23505 + TW + +00-05-0F (hex) Tanaka S/S Ltd. +00050F (base 16) Tanaka S/S Ltd. + 1942 Nomura Hirooka + Nagano 399-0702 + JP + +98-9E-63 (hex) Apple, Inc. +989E63 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-6B-6E (hex) Apple, Inc. +886B6E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-E4-AD (hex) zte corporation +F4E4AD (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +28-FF-3E (hex) zte corporation +28FF3E (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +B8-D7-AF (hex) Murata Manufacturing Co., Ltd. +B8D7AF (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +D4-AE-05 (hex) Samsung Electronics Co.,Ltd +D4AE05 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E0-48-AF (hex) Premietech Limited +E048AF (base 16) Premietech Limited + Unit 805, Tower 3, Enterprise Square I + No. 9 Sheung Yuet Road Kowloon Bay HongKong 00000 + HK + +2C-33-11 (hex) Cisco Systems, Inc +2C3311 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +50-82-D5 (hex) Apple, Inc. +5082D5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-EE-10 (hex) Samsung Electronics Co.,Ltd +F0EE10 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C4-70-0B (hex) GUANGZHOU CHIP TECHNOLOGIES CO.,LTD +C4700B (base 16) GUANGZHOU CHIP TECHNOLOGIES CO.,LTD + 4th floor, Building J of JiTang Industrial Zone, No. 8 NanYun fifth road, HuangPu District + Guangzhou Guangdong 510700 + CN + +3C-A0-67 (hex) Liteon Technology Corporation +3CA067 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +BC-02-4A (hex) HMD Global Oy +BC024A (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +94-99-01 (hex) Shenzhen YITOA Digital Appliance CO.,LTD +949901 (base 16) Shenzhen YITOA Digital Appliance CO.,LTD + 5/F,Yitoa Building,Keji South Road 5th,Hi-tech Industrial Park,Nanshan District, + shenzhen Guangdong 518000 + CN + +F8-59-71 (hex) Intel Corporate +F85971 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +10-05-CA (hex) Cisco Systems, Inc +1005CA (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +78-94-B4 (hex) Sercomm Corporation. +7894B4 (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +44-37-08 (hex) MRV Comunications +443708 (base 16) MRV Comunications + Hayetzira + Yokneam 614 + IL + +28-5F-2F (hex) RNware Co.,Ltd. +285F2F (base 16) RNware Co.,Ltd. + #202 ICT Park Bldg, 205, Songhyun-ro, Dalseo-gu + Daegu 42734 + KR + +50-0F-F5 (hex) Tenda Technology Co.,Ltd.Dongguan branch +500FF5 (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +BC-45-2E (hex) Knowledge Development for POF S.L. +BC452E (base 16) Knowledge Development for POF S.L. + Ronda de Poniente 14, 2-C,D + Tres Cantos Madrid 28760 + ES + +DC-C6-4B (hex) HUAWEI TECHNOLOGIES CO.,LTD +DCC64B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +04-33-89 (hex) HUAWEI TECHNOLOGIES CO.,LTD +043389 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-A0-68 (hex) BHP LIMITED +00A068 (base 16) BHP LIMITED + 1500 Post Oak Boulevard #11.08 B + Houston TX 77056-3030 + US + +70-3A-CB (hex) Google, Inc. +703ACB (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +70-6D-EC (hex) Wifi-soft LLC +706DEC (base 16) Wifi-soft LLC + 616, West Monroe + Austin TX 78704 + US + +B0-C2-05 (hex) BIONIME +B0C205 (base 16) BIONIME + No.100, Sec.2, Daqing St., South Dist., + Taichung Taiwan 40242 + TW + +94-F5-51 (hex) Cadi Scientific Pte Ltd +94F551 (base 16) Cadi Scientific Pte Ltd + 31 Ubi Road 1, Aztech Building, #07-01A + Singapore 408694 + SG + +10-5A-F7 (hex) ADB Italia +105AF7 (base 16) ADB Italia + Viale Sarca 222 + Milan Italy 20126 + IT + +B8-1D-AA (hex) LG Electronics (Mobile Communications) +B81DAA (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-E4-00 (hex) Sichuan Changhong Electric Ltd. +00E400 (base 16) Sichuan Changhong Electric Ltd. + No.35,East MianXin Road,MianYang,Sichaun,China. + MianYang SiChuan PRC 621000 + CN + +2C-55-D3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +2C55D3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-C0-24 (hex) EDEN SISTEMAS DE COMPUTACAO SA +00C024 (base 16) EDEN SISTEMAS DE COMPUTACAO SA + RUA DO OUVIDOR 121 5 ANDAR + + BR + +7C-46-85 (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +7C4685 (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan + Wuhan Hubei 430000 + CN + +1C-1E-E3 (hex) Hui Zhou Gaoshengda Technology Co.,LTD +1C1EE3 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +44-03-2C (hex) Intel Corporate +44032C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +78-68-F7 (hex) YSTen Technology Co.,Ltd +7868F7 (base 16) YSTen Technology Co.,Ltd + Room 1715,17/F North Star Times Tower,Chaoyang District,Beijing. + Beijing 100101 + CN + +00-4B-F3 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +004BF3 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + 3/F, Building R1-B, High-Tech Industrial Park, Nanshan District + Shenzhen Guangdong 518057 + CN + +08-CC-A7 (hex) Cisco Systems, Inc +08CCA7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +08-96-AD (hex) Cisco Systems, Inc +0896AD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +08-23-B2 (hex) vivo Mobile Communication Co., Ltd. +0823B2 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +88-C3-B3 (hex) SOVICO +88C3B3 (base 16) SOVICO + 2271-5 Nambusunhwan-ro, Seocho-gu + Seoul 06703 + KR + +E0-51-24 (hex) NXP Semiconductors +E05124 (base 16) NXP Semiconductors + 411 E. Plumeria Drive + San Jose CA 95134 + US + +00-1D-A3 (hex) SabiOso +001DA3 (base 16) SabiOso + 189 S State Suite #250 + Clearfield Utah 84015 + US + +54-2F-8A (hex) TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO +542F8A (base 16) TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO + Av. Buriti, 1900 – Setor B – Distrito Industrial + Manaus Amazonas 69075-000 + BR + +60-14-B3 (hex) CyberTAN Technology Inc. +6014B3 (base 16) CyberTAN Technology Inc. + 99 Park Ave III, Hsinchu Science Park + Hsinchu 308 + TW + +10-56-11 (hex) ARRIS Group, Inc. +105611 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +34-78-77 (hex) O-Net Communications (Shenzhen) Limited +347877 (base 16) O-Net Communications (Shenzhen) Limited + #10-1 South,Maqueling Industrial Park,Nanshan District + Shenzhen Guangdong 518057 + CN + +00-20-CC (hex) DIGITAL SERVICES, LTD. +0020CC (base 16) DIGITAL SERVICES, LTD. + 9 WAYTE STREET + ENGLAND PO6 3BS + GB + +68-9F-F0 (hex) zte corporation +689FF0 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +5C-AF-06 (hex) LG Electronics (Mobile Communications) +5CAF06 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-17-9B (hex) CHANT SINCERE CO.,LTD +00179B (base 16) CHANT SINCERE CO.,LTD + 7F-2,NO.188,Sec 3,Ta Tung Rood, + Hsi Chih City Taipei Hsien 221 + TW + +1C-39-8A (hex) Fiberhome Telecommunication Technologies Co.,LTD +1C398A (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +E8-65-D4 (hex) Tenda Technology Co.,Ltd.Dongguan branch +E865D4 (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +24-D5-1C (hex) Zhongtian broadband technology co., LTD +24D51C (base 16) Zhongtian broadband technology co., LTD + Rudong hekou town Zhongtian industrial park + Nantong jiangsu Province 226463 + CN + +EC-43-F6 (hex) Zyxel Communications Corporation +EC43F6 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +60-C6-58 (hex) PHYTRONIX Co.,Ltd. +60C658 (base 16) PHYTRONIX Co.,Ltd. + 1877-3 Ootashimo-machi + Takamatsu Kagawa 761-8073 + JP + +FC-B5-8A (hex) Wapice Ltd. +FCB58A (base 16) Wapice Ltd. + Yliopistonranta 5 + Vaasa 65200 + FI + +A4-62-DF (hex) DS Global. Co., LTD +A462DF (base 16) DS Global. Co., LTD + 3F, 107, Gasan digital 2-ro, Geumcheon-gu + Seoul 08505 + KR + +4C-16-94 (hex) shenzhen sibituo Technology Co., Ltd +4C1694 (base 16) shenzhen sibituo Technology Co., Ltd + 15C Yuehua Park Nanshan Road Nanshan District + SHENZHEN guangdong 518000 + CN + +C8-14-51 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C81451 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +44-D4-37 (hex) Inteno Broadband Technology AB +44D437 (base 16) Inteno Broadband Technology AB + Stensätravägen 13 + Skärholmen SE 127 39 + SE + +EC-E1-54 (hex) Beijing Unisound Information Technology Co.,Ltd. +ECE154 (base 16) Beijing Unisound Information Technology Co.,Ltd. + Rm406,keyan Building,Tsinghua Hi-tech Park,High-tech Industrial Park North Area,Nanshan + Shenzhen 518057 + CN + +6C-16-0E (hex) ShotTracker +6C160E (base 16) ShotTracker + 7220 W Frontage Rd + Merriam KS 66203 + US + +80-3A-0A (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +803A0A (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +0C-73-BE (hex) Dongguan Haimai Electronie Technology Co.,Ltd +0C73BE (base 16) Dongguan Haimai Electronie Technology Co.,Ltd + Room 701,Yifeng Building7, No.8 Industrial Zone, Xianbian Road, Changan Town Xiaobian edge + Dongguan Guangdong 518000 + CN + +28-6F-7F (hex) Cisco Systems, Inc +286F7F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F0-C8-50 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F0C850 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-01-4F (hex) Adtran Inc +00014F (base 16) Adtran Inc + 901 Explorer Blvd. + Huntsville AL 35806-2807 + US + +28-52-61 (hex) Cisco Systems, Inc +285261 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C8-AA-55 (hex) Hunan Comtom Electronic Incorporated Co.,Ltd +C8AA55 (base 16) Hunan Comtom Electronic Incorporated Co.,Ltd + 6 -7 Floor, Jindan Building B,Xiongtian Road, Furong District + changsha Hunan 410126 + CN + +20-78-0B (hex) Delta Faucet Company +20780B (base 16) Delta Faucet Company + 55 East 111th Street + Indianapolis IN 46280 + US + +88-09-AF (hex) Masimo Corporation +8809AF (base 16) Masimo Corporation + 40 Parker + Irvine 92618 + US + +2C-D0-2D (hex) Cisco Systems, Inc +2CD02D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +9C-CC-83 (hex) Juniper Networks +9CCC83 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +2C-63-73 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +2C6373 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +24-A7-DC (hex) BSkyB Ltd +24A7DC (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +64-DB-A0 (hex) Select Comfort +64DBA0 (base 16) Select Comfort + 9800 59th Ave N + Minneapolis MN 55442 + US + +F8-98-3A (hex) Leeman International (HongKong) Limited +F8983A (base 16) Leeman International (HongKong) Limited + Number 13 first floor Y1 cultural creative park bantian + shen zhen 51800 + CN + +4C-EC-EF (hex) Soraa, Inc. +4CECEF (base 16) Soraa, Inc. + 6500 Kaiser Dr Suite 110 + Fremont CA 94555 + US + +1C-EF-CE (hex) bebro electronic GmbH +1CEFCE (base 16) bebro electronic GmbH + MAx-Planck-Str. 6-8 + Frickenhausen 72636 + DE + +98-B6-E9 (hex) Nintendo Co.,Ltd +98B6E9 (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +F0-15-B9 (hex) PlayFusion Limited +F015B9 (base 16) PlayFusion Limited + St Johns Innovation Centre + Cambridge CB4 0WS + GB + +64-B0-A6 (hex) Apple, Inc. +64B0A6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +7C-04-D0 (hex) Apple, Inc. +7C04D0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-FC-AC (hex) Apple, Inc. +84FCAC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +DC-0C-5C (hex) Apple, Inc. +DC0C5C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-70-0D (hex) Apple, Inc. +70700D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +30-E1-71 (hex) Hewlett Packard +30E171 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +18-65-90 (hex) Apple, Inc. +186590 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-62-14 (hex) Apple, Inc. +F86214 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-4F-43 (hex) Apple, Inc. +784F43 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-4D-7F (hex) Apple, Inc. +404D7F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-1D-72 (hex) Wistron Corporation +001D72 (base 16) Wistron Corporation + 21F, 88, Sec.1, Hsin Tai Wu Rd., Hsichih, + Taipei Hsien 221 + TW + +D8-19-7A (hex) Nuheara Ltd +D8197A (base 16) Nuheara Ltd + Unit 5, 28 John St + Northbridge WA 6003 + AU + +4C-38-D5 (hex) MITAC COMPUTING TECHNOLOGY CORPORATION +4C38D5 (base 16) MITAC COMPUTING TECHNOLOGY CORPORATION + 3F., NO.1, R&D ROAD 2, HSINCHU SCIENCE PARK + HSINCHU 30076 + TW + +54-B5-6C (hex) Xi'an NovaStar Tech Co., Ltd +54B56C (base 16) Xi'an NovaStar Tech Co., Ltd + 4F, Block D, Qinfeng Pavilion, Xi'an Software Park, No.68 Keji 2nd Rd., + Xi'an Shanxi 710075 + CN + +34-4C-C8 (hex) Echodyne Corp +344CC8 (base 16) Echodyne Corp + 2380 116th Ave NE + Bellevue WA 98004 + US + +64-13-6C (hex) zte corporation +64136C (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +04-B6-48 (hex) ZENNER +04B648 (base 16) ZENNER + Roemerstadt 6 + Saarbruecken 66121 + DE + +98-F1-99 (hex) NEC Platforms, Ltd. +98F199 (base 16) NEC Platforms, Ltd. + 2-3 Kandatsukasamachi + Chiyodaku Tokyo 101-8532 + JP + +18-40-A4 (hex) Shenzhen Trylong Smart Science and Technology Co., Ltd. +1840A4 (base 16) Shenzhen Trylong Smart Science and Technology Co., Ltd. + 15E, qingdian building, No#6007, Binhe road, futian district + Shenzhen city Guangdong Province 518100 + CN + +1C-48-CE (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +1C48CE (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +C8-0C-C8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C80CC8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +04-25-C5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +0425C5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +60-3E-7B (hex) Gafachi, Inc. +603E7B (base 16) Gafachi, Inc. + 1 W Main St., STE 650 + Rochester NY 14614 + US + +4C-74-87 (hex) Leader Phone Communication Technology Co., Ltd. +4C7487 (base 16) Leader Phone Communication Technology Co., Ltd. + 121 Room (Park) No.1 Building, No.10 Xinghuo Road Science City Feng-tai District, Beijing, China + Beijing 100070 + CN + +AC-83-F3 (hex) AMPAK Technology, Inc. +AC83F3 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +CC-8C-DA (hex) Shenzhen Wei Da Intelligent Technology Go.,Ltd +CC8CDA (base 16) Shenzhen Wei Da Intelligent Technology Go.,Ltd + 5K, Block B,Yueshang Center Cultural Square Jianshe East Rd Longhua New District + Shenzhen 518109 + CN + +D4-36-DB (hex) Jiangsu Toppower Automotive Electronics Co., Ltd +D436DB (base 16) Jiangsu Toppower Automotive Electronics Co., Ltd + No. 2 Tuolanshan Road + Xuzhou Jiangsu 221004 + CN + +2C-DC-AD (hex) Wistron Neweb Corporation +2CDCAD (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +6C-5C-14 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +6C5C14 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +E8-09-45 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +E80945 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +B0-A2-E7 (hex) Shenzhen TINNO Mobile Technology Corp. +B0A2E7 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F, H-3 Building, Qiao Cheng Eastern Industrial Park, Overseas Chinese Town, Shenzhen + Shenzhen guangdong 518053 + CN + +7C-25-87 (hex) chaowifi.com +7C2587 (base 16) chaowifi.com + No. 502 1th Building TaiHe Square + HangZhou QianJiangRoad 310002 + CN + +2C-21-31 (hex) Juniper Networks +2C2131 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-50-1E (hex) Grass Valley, A Belden Brand +00501E (base 16) Grass Valley, A Belden Brand + 3499, Douglas B. Floreani + Montreal Quebec H4S 2C6 + CA + +EC-0D-9A (hex) Mellanox Technologies, Inc. +EC0D9A (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +90-D7-BE (hex) Wavelab Global Inc. +90D7BE (base 16) Wavelab Global Inc. + 12007 Sunrise Valley Drive, Suite 450 + Reston VA 20191 + US + +24-4E-7B (hex) IEEE Registration Authority +244E7B (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +30-AE-A4 (hex) Espressif Inc. +30AEA4 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +3C-FA-43 (hex) HUAWEI TECHNOLOGIES CO.,LTD +3CFA43 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +14-5F-94 (hex) HUAWEI TECHNOLOGIES CO.,LTD +145F94 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-1F-82 (hex) Cal-Comp Electronics & Communications Company Ltd. +001F82 (base 16) Cal-Comp Electronics & Communications Company Ltd. + No.147, Sec. 3, Beishen Rd + Shenkeng Dist New Taipei City --- + TW + +88-3C-1C (hex) MERCURY CORPORATION +883C1C (base 16) MERCURY CORPORATION + 90, Gajaeul-ro, Seo-gu + INCHEON 22830 + KR + +00-21-44 (hex) SS Telecoms +002144 (base 16) SS Telecoms + 23 Botha Avenue + Centurion Gauteng 0140 + ZA + +00-6B-F1 (hex) Cisco Systems, Inc +006BF1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +28-34-A2 (hex) Cisco Systems, Inc +2834A2 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +78-23-AE (hex) ARRIS Group, Inc. +7823AE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +20-71-9E (hex) SF Technology Co.,Ltd +20719E (base 16) SF Technology Co.,Ltd + 1/F,Block B,Building 1,ShenzhenSoftware Industry Base,Hi-Tech Industrial Park South + Shenzhen Guangdong Province 518054 + CN + +2C-C2-60 (hex) Oracle Corporation +2CC260 (base 16) Oracle Corporation + Zarhin 13 + Raanana 4366241 + IL + +3C-3F-51 (hex) 2CRSI +3C3F51 (base 16) 2CRSI + 32 rue Jacobi-Netter + STRASBOURG France 67200 + FR + +3C-2A-F4 (hex) Brother Industries, LTD. +3C2AF4 (base 16) Brother Industries, LTD. + 15-1, Naeshirocho, Mizuho-ku + NAGOYA 4678561 + JP + +C0-85-4C (hex) Ragentek Technology Group +C0854C (base 16) Ragentek Technology Group + D10/D11,No.3188, Xiupu Road, PuDong District, Shanghai + Shanghai 201315 + CN + +00-24-AC (hex) Hangzhou DPtech Technologies Co., Ltd. +0024AC (base 16) Hangzhou DPtech Technologies Co., Ltd. + Huarong Shidai Bld., NO.3880,Jiang-Nan Avenue, Binjiang District + Hangzhou Zhejiang 310051 + CN + +50-58-4F (hex) waytotec,Inc. +50584F (base 16) waytotec,Inc. + #604-4,B-Dong,Bundang Technopark,148,Yatap-dong,Bundang-gu, + Seongnam-si Gyeonggi-do 13511 + KR + +08-5D-DD (hex) MERCURY CORPORATION +085DDD (base 16) MERCURY CORPORATION + 90, Gajaeul-ro, Seo-gu + INCHEON 22830 + KR + +8C-60-E7 (hex) MPGIO CO.,LTD +8C60E7 (base 16) MPGIO CO.,LTD + MPGIO Bldg., 98 Uijeong St., + Uijeongbu Korea / Gyeonggi 11623 + KR + +CC-94-70 (hex) Kinestral Technologies, Inc. +CC9470 (base 16) Kinestral Technologies, Inc. + 400 E Jamie Ct., Ste. 201 + South San Francisco CA 94080 + US + +B4-39-D6 (hex) ProCurve Networking by HP +B439D6 (base 16) ProCurve Networking by HP + 60 Alexandra Terrace + 0000 118502 + SG + +34-F3-9A (hex) Intel Corporate +34F39A (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +D8-16-C1 (hex) DEWAV (HK) ELECTRONICS LIMITED +D816C1 (base 16) DEWAV (HK) ELECTRONICS LIMITED + UNIT NO.1-2, 06/F., PERFECT INDUSTRIAL BUILDING,NO. 31 TAI YAU STREET, SAN PO KONG + KOWLOON, HONG KONG 510610 + CN + +CC-61-E5 (hex) Motorola Mobility LLC, a Lenovo Company +CC61E5 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +8C-8A-BB (hex) Beijing Orient View Technology Co., Ltd. +8C8ABB (base 16) Beijing Orient View Technology Co., Ltd. + Building NO.1, LiYe Road 7 + Huilongguan Town Changping District, Beijing 102206 + CN + +00-03-9B (hex) NetChip Technology, Inc. +00039B (base 16) NetChip Technology, Inc. + 335 Pioneer Way + Mountain View CA 94041 + US + +44-D9-E7 (hex) Ubiquiti Networks Inc. +44D9E7 (base 16) Ubiquiti Networks Inc. + 2580 Orchard Parkway + San Jose CA 95131 + US + +24-A4-3C (hex) Ubiquiti Networks Inc. +24A43C (base 16) Ubiquiti Networks Inc. + 91 E. Tasman Dr. + San Jose 95134 + US + +9C-8B-A0 (hex) Apple, Inc. +9C8BA0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +CC-08-8D (hex) Apple, Inc. +CC088D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-A4-ED (hex) Xiaomi Communications Co Ltd +38A4ED (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +B8-99-19 (hex) 7signal Solutions, Inc +B89919 (base 16) 7signal Solutions, Inc + 526 S. Main Street + Akron OH 44311 + US + +40-FE-0D (hex) MAXIO +40FE0D (base 16) MAXIO + 1101-1 digital empire A, 387 simin-daero dongan-gu + anyang-si kyunggi-do 14057 + KR + +AC-64-DD (hex) IEEE Registration Authority +AC64DD (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +94-B8-19 (hex) Nokia +94B819 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +78-7D-48 (hex) ITEL MOBILE LIMITED +787D48 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +88-71-E5 (hex) Amazon Technologies Inc. +8871E5 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +BC-39-D9 (hex) Z-TEC +BC39D9 (base 16) Z-TEC + Donyu 1 Ro + Paju Kyeongkido 10832 + KR + +60-9A-C1 (hex) Apple, Inc. +609AC1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +74-8D-08 (hex) Apple, Inc. +748D08 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-B0-EE (hex) Ajile Systems, Inc. +00B0EE (base 16) Ajile Systems, Inc. + 920 Saratoga Ave. + San Jose CA 95129 + US + +04-18-D6 (hex) Ubiquiti Networks Inc. +0418D6 (base 16) Ubiquiti Networks Inc. + 91 E. Tasman Dr. + San Jose 95134 + US + +20-DB-AB (hex) Samsung Electronics Co., Ltd. +20DBAB (base 16) Samsung Electronics Co., Ltd. + 416, Maetan-3Dong, Yeongtong-Gu + Suwon Geyonggi-Do 443-742 + KR + +38-3A-21 (hex) IEEE Registration Authority +383A21 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D8-38-0D (hex) SHENZHEN IP-COM Network Co.,Ltd +D8380D (base 16) SHENZHEN IP-COM Network Co.,Ltd + No.1001,Zhongshangyuan Road,Nanshan District + Shenzhen Guangdong 518000 + CN + +88-AD-43 (hex) PEGATRON CORPORATION +88AD43 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +B4-EF-FA (hex) Lemobile Information Technology (Beijing) Co., Ltd. +B4EFFA (base 16) Lemobile Information Technology (Beijing) Co., Ltd. + 5/F LeEco Building, 105 Yaojiayuan Road, Chaoyang District + Beijing Beijing 100025 + CN + +6C-71-BD (hex) EZELINK TELECOM +6C71BD (base 16) EZELINK TELECOM + Bay Square Building 06 - Office No 105 + Dubai Dubai 111581 + AE + +60-EF-C6 (hex) Shenzhen Chima Technologies Co Limited +60EFC6 (base 16) Shenzhen Chima Technologies Co Limited + 5F, TongXin Technology Park,HengGang,LongGang,Shenzhen,China + Shenzhen GuangDong 518115 + CN + +00-1F-C6 (hex) ASUSTek COMPUTER INC. +001FC6 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou,Taipei 112 ,Taiwan + Taipei Taiwan 112 + TW + +B0-C1-28 (hex) Adler ELREHA GmbH +B0C128 (base 16) Adler ELREHA GmbH + Schwetzinger Str. 103 + Hockenheim Baden-Württemberg D-68766 + DE + +30-87-D9 (hex) Ruckus Wireless +3087D9 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +FC-CA-C4 (hex) LifeHealth, LLC +FCCAC4 (base 16) LifeHealth, LLC + 2656 Patton Rd + Roseville MN 55113 + US + +F0-D9-B2 (hex) EXO S.A. +F0D9B2 (base 16) EXO S.A. + Av. Chiclana 3444 + Buenos Aires 1260 + AR + +E4-C8-01 (hex) BLU Products Inc +E4C801 (base 16) BLU Products Inc + 10814 NW 33rd Street + Miami FL 33172 + US + +F0-98-38 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F09838 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C8-0E-14 (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +C80E14 (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +AC-63-BE (hex) Amazon Technologies Inc. +AC63BE (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +F8-1D-78 (hex) IEEE Registration Authority +F81D78 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +38-F7-B2 (hex) SEOJUN ELECTRIC +38F7B2 (base 16) SEOJUN ELECTRIC + 468 Gangseo-ro, 07573, SEOJUN ELECTRIC Ace Techno Tower 805 + Seoul 07573 + KR + +10-12-50 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +101250 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +78-02-B7 (hex) ShenZhen Ultra Easy Technology CO.,LTD +7802B7 (base 16) ShenZhen Ultra Easy Technology CO.,LTD + 608,Building 2,Guangxingyuan Industrial Park A District, + Baoyuan Rd ShenZhen,Guangdong 518102 + CN + +64-61-84 (hex) VELUX +646184 (base 16) VELUX + Baekgaardsvej 40 + Skjern 6900 + DK + +E8-E5-D6 (hex) Samsung Electronics Co.,Ltd +E8E5D6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C8-7E-75 (hex) Samsung Electronics Co.,Ltd +C87E75 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-26-5F (hex) Samsung Electronics Co.,Ltd +00265F (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-23-3A (hex) Samsung Electronics Co.,Ltd +00233A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +08-6A-0A (hex) ASKEY COMPUTER CORP +086A0A (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +98-E7-F4 (hex) Hewlett Packard +98E7F4 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +00-07-AB (hex) Samsung Electronics Co.,Ltd +0007AB (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-24-86 (hex) DesignArt Networks +002486 (base 16) DesignArt Networks + 4 Ha'haroshet St + Ra'anana 43101 + IL + +00-24-78 (hex) Mag Tech Electronics Co Limited +002478 (base 16) Mag Tech Electronics Co Limited + Flat / Room T78 GOF Bangkok Building + Sheung Wan HK + HK + +38-2D-D1 (hex) Samsung Electronics Co.,Ltd +382DD1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-1B-2C (hex) ATRON electronic GmbH +001B2C (base 16) ATRON electronic GmbH + Am Ziegelstadel 12 + 14 + Markt Schwaben 85570 + DE + +90-34-FC (hex) Hon Hai Precision Ind. Co.,Ltd. +9034FC (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-14-27 (hex) JazzMutant +001427 (base 16) JazzMutant + 2 allee du Doyen Georges Brus + Pessac 33600 + FR + +00-1E-84 (hex) Pika Technologies Inc. +001E84 (base 16) Pika Technologies Inc. + 535 Legget Drive + Ottawa Ontario K2K 3B8 + CA + +10-DD-B1 (hex) Apple, Inc. +10DDB1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-23-29 (hex) DDRdrive LLC +002329 (base 16) DDRdrive LLC + 384 Madeline CT + Palo Alto CA 94306 + US + +00-26-AD (hex) Arada Systems, Inc. +0026AD (base 16) Arada Systems, Inc. + 1024 Morse Avenue + Sunnyvale CA 94089 + US + +FC-1F-19 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +FC1F19 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Maetan3-Dong, Yeongtong-Gu + Suwon 443-743 + US + +84-0B-2D (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +840B2D (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Maetan3-Dong, Yeongtong-Gu + SUWON KYUNGGI-DO 443-743 + KR + +20-64-32 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +206432 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Maetan3-Dong, Yeongtong-Gu + Suwon Gyunggi-Do 443-743 + KR + +B4-07-F9 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +B407F9 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + Suwon-Si, Gyeonggi_Do, Korea + Suwon Gyeonggi_Do 443-743 + KR + +88-9F-FA (hex) Hon Hai Precision Ind. Co.,Ltd. +889FFA (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +8C-7C-B5 (hex) Hon Hai Precision Ind. Co.,Ltd. +8C7CB5 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +C4-46-19 (hex) Hon Hai Precision Ind. Co.,Ltd. +C44619 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +50-63-13 (hex) Hon Hai Precision Ind. Co.,Ltd. +506313 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +60-D8-19 (hex) Hon Hai Precision Ind. Co.,Ltd. +60D819 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +F8-2F-A8 (hex) Hon Hai Precision Ind. Co.,Ltd. +F82FA8 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +0C-84-DC (hex) Hon Hai Precision Ind. Co.,Ltd. +0C84DC (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-16-6C (hex) Samsung Electronics Co.,Ltd +00166C (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3Dong,Yeongtong-Gu + Suwon Gyeonggi-Do 443-742 + KR + +18-1E-B0 (hex) Samsung Electronics Co.,Ltd +181EB0 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +24-7F-20 (hex) Sagemcom Broadband SAS +247F20 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +E8-03-9A (hex) Samsung Electronics Co.,Ltd +E8039A (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3Dong, Yeongtong-Gu + Suwon Geyonggi 443742 + KR + +30-CD-A7 (hex) Samsung Electronics Co.,Ltd +30CDA7 (base 16) Samsung Electronics Co.,Ltd + 416 MAETAN 3-DONG + SUWON- SI 443-742 + US + +00-12-47 (hex) Samsung Electronics Co.,Ltd +001247 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi-City Gyeong-Buk 730-350 + KR + +00-15-99 (hex) Samsung Electronics Co.,Ltd +001599 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3Dong, Yeongtong-Gu + Suwon AL 443-742 + US + +00-12-FB (hex) Samsung Electronics Co.,Ltd +0012FB (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3Dong, Yeongtong-Gu + Suwon-City Gyeonggi-Do 443-742 + KR + +D0-66-7B (hex) Samsung Electronics Co.,Ltd +D0667B (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3dong, Yeongtong-gu + Suwon Gyeonggi-do 443742 + KR + +B8-5E-7B (hex) Samsung Electronics Co.,Ltd +B85E7B (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E4-92-FB (hex) Samsung Electronics Co.,Ltd +E492FB (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +6C-B7-F4 (hex) Samsung Electronics Co.,Ltd +6CB7F4 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +2C-44-01 (hex) Samsung Electronics Co.,Ltd +2C4401 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B8-D9-CE (hex) Samsung Electronics Co.,Ltd +B8D9CE (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +1C-66-AA (hex) Samsung Electronics Co.,Ltd +1C66AA (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +3C-8B-FE (hex) Samsung Electronics Co.,Ltd +3C8BFE (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D4-E8-B2 (hex) Samsung Electronics Co.,Ltd +D4E8B2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-89-FD (hex) Samsung Electronics Co.,Ltd +1489FD (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +BC-85-1F (hex) Samsung Electronics Co.,Ltd +BC851F (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-15-B9 (hex) Samsung Electronics Co.,Ltd +0015B9 (base 16) Samsung Electronics Co.,Ltd + #94-1 + Gumi-City Gyeong-Buk 730-350 + KR + +00-24-91 (hex) Samsung Electronics Co.,Ltd +002491 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-23-39 (hex) Samsung Electronics Co.,Ltd +002339 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +50-01-BB (hex) Samsung Electronics Co.,Ltd +5001BB (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C4-01-42 (hex) MaxMedia Technology Limited +C40142 (base 16) MaxMedia Technology Limited + 5F, No. 113, Jian 2nd Rd. Jhonghe District. + New Taipei City 23585 + TW + +84-30-E5 (hex) SkyHawke Technologies, LLC +8430E5 (base 16) SkyHawke Technologies, LLC + 274 Commerce Park Dr, Ste M + Ridgeland MS 39157 + US + +1C-77-F6 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +1C77F6 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +58-E3-26 (hex) Compass Technologies Inc. +58E326 (base 16) Compass Technologies Inc. + Unit 1012 C-dong, Woolim Lion's Valley + Seoul Seoul 153-786 + KR + +00-1B-2A (hex) Cisco Systems, Inc +001B2A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +74-9D-DC (hex) 2Wire Inc +749DDC (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose 95131 + US + +14-DD-E5 (hex) MPMKVVCL +14DDE5 (base 16) MPMKVVCL + NISHTHA PARISAR, GOVINDPURA + BHOPAL MADHYA PRADESH 462023 + IN + +00-1A-09 (hex) Wayfarer Transit Systems Ltd +001A09 (base 16) Wayfarer Transit Systems Ltd + 10 Willis Way + Poole Dorset BH15 3SS + GB + +74-23-44 (hex) Xiaomi Communications Co Ltd +742344 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +54-88-0E (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +54880E (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +F0-25-B7 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +F025B7 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +F0-43-47 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F04347 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +9C-B2-B2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +9CB2B2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A8-C8-3A (hex) HUAWEI TECHNOLOGIES CO.,LTD +A8C83A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +BC-72-B1 (hex) Samsung Electronics Co.,Ltd +BC72B1 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +78-F7-BE (hex) Samsung Electronics Co.,Ltd +78F7BE (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +68-48-98 (hex) Samsung Electronics Co.,Ltd +684898 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +34-23-BA (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +3423BA (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong 24180 + US + +00-36-76 (hex) ARRIS Group, Inc. +003676 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +FC-8E-7E (hex) ARRIS Group, Inc. +FC8E7E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +FC-6F-B7 (hex) ARRIS Group, Inc. +FC6FB7 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D4-2C-0F (hex) ARRIS Group, Inc. +D42C0F (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +40-0E-85 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +400E85 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong 24180 + US + +C8-BA-94 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +C8BA94 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +84-38-38 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +843838 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +A0-55-DE (hex) ARRIS Group, Inc. +A055DE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +80-F5-03 (hex) ARRIS Group, Inc. +80F503 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +44-AA-F5 (hex) ARRIS Group, Inc. +44AAF5 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E0-9D-FA (hex) Wanan Hongsheng Electronic Co.Ltd +E09DFA (base 16) Wanan Hongsheng Electronic Co.Ltd + 1st section of industrial pack,Wan'An County,Ji'An City,jiangxi province + Wanan China/jiangxi 343800 + CN + +5C-3C-27 (hex) Samsung Electronics Co.,Ltd +5C3C27 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +70-A8-4C (hex) MONAD., Inc. +70A84C (base 16) MONAD., Inc. + 702, Hanlla Sigma Vally, 545, Dunchon-daero, Jungwon-gu + Seongnam-Shi 13215 + KR + +84-C7-EA (hex) Sony Mobile Communications Inc +84C7EA (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +24-E4-3F (hex) Wenzhou Kunmei Communication Technology Co.,Ltd. +24E43F (base 16) Wenzhou Kunmei Communication Technology Co.,Ltd. + Baitawang industrial zone,Yueqing,Zhejiang + Yueqing Zhejiang 310025 + CN + +28-7A-EE (hex) ARRIS Group, Inc. +287AEE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +88-79-7E (hex) Motorola Mobility LLC, a Lenovo Company +88797E (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +30-58-90 (hex) Frontier Silicon Ltd +305890 (base 16) Frontier Silicon Ltd + 137 Euston Road + London NW12AA + GB + +70-8B-CD (hex) ASUSTek COMPUTER INC. +708BCD (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +00-25-8B (hex) Mellanox Technologies, Inc. +00258B (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +00-56-2B (hex) Cisco Systems, Inc +00562B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E8-FD-90 (hex) Turbostor +E8FD90 (base 16) Turbostor + 47800 Westinghouse Drive + Fremont CA 94539 + US + +2C-AC-44 (hex) CONEXTOP +2CAC44 (base 16) CONEXTOP + Room 608, 6/F, Electric Building , High-tech Park , Nanshan + Shenzhen 51800 + CN + +D0-13-FD (hex) LG Electronics (Mobile Communications) +D013FD (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +BC-64-4B (hex) ARRIS Group, Inc. +BC644B (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +60-64-05 (hex) Texas Instruments +606405 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +18-99-F5 (hex) Sichuan Changhong Electric Ltd. +1899F5 (base 16) Sichuan Changhong Electric Ltd. + No.35,East MianXin Road,MianYang,Sichaun,China. + MianYang SiChuan PRC 621000 + CN + +00-25-C3 (hex) 21168 +0025C3 (base 16) 21168 + CARRETERA BASE AEREA # 5850 + Zapopan Jalisco 44130 + MX + +00-0F-57 (hex) CABLELOGIC Co., Ltd. +000F57 (base 16) CABLELOGIC Co., Ltd. + 3F., Hwain Bldg., 1559-12 Seocho 3-dong, + Seoul 137-873 + KR + +00-03-42 (hex) Nortel Networks +000342 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +A4-82-69 (hex) Datrium, Inc. +A48269 (base 16) Datrium, Inc. + 385 Moffett Park Drive + Sunnyvale CA 94089 + US + +10-E6-8F (hex) KWANGSUNG ELECTRONICS KOREA CO.,LTD. +10E68F (base 16) KWANGSUNG ELECTRONICS KOREA CO.,LTD. + 356-3, Gongdan-ro + Gunpo-si Gyeonggi-do 15808 + KR + +4C-FA-CA (hex) Cambridge Industries(Group) Co.,Ltd. +4CFACA (base 16) Cambridge Industries(Group) Co.,Ltd. + 5/F,Building 8, 2388 ChenHang Road, MinHang District + shanghai 201114 + CN + +18-AB-F5 (hex) Ultra Electronics Electrics +18ABF5 (base 16) Ultra Electronics Electrics + Kingsditch Lane + Cheltenham Gloucestershire GL51 9PG + GB + +B0-3E-B0 (hex) MICRODIA Ltd. +B03EB0 (base 16) MICRODIA Ltd. + Suites 1608-1610, 16/F., Prosperity Centre, 25 Chong Yip Street, + Kwun Tong Kowloon, 000000 + HK + +00-15-91 (hex) RLW Inc. +001591 (base 16) RLW Inc. + 2029 Cato Ave. + State College PA 16801 + US + +00-18-2E (hex) XStreamHD +00182E (base 16) XStreamHD + 7900B Westpark Drive + McLean VA 22102 + US + +00-12-83 (hex) Nortel Networks +001283 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-11-F9 (hex) Nortel Networks +0011F9 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-11-58 (hex) Nortel Networks +001158 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-0F-6A (hex) Nortel Networks +000F6A (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-0E-62 (hex) Nortel Networks +000E62 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-0C-F8 (hex) Nortel Networks +000CF8 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-26-F1 (hex) ProCurve Networking by HP +0026F1 (base 16) ProCurve Networking by HP + 60 Alexandra Terrace + 0000 118502 + SG + +38-0D-D4 (hex) Primax Electronics Ltd. +380DD4 (base 16) Primax Electronics Ltd. + 8F,No. 669, Ruey Kuang Road, Neihu + Taipei 114 + TW + +98-FD-B4 (hex) Primax Electronics Ltd. +98FDB4 (base 16) Primax Electronics Ltd. + No. 669, Ruey Kuang Road, Neihu + Taipei Taiwan, R.O.C. + TW + +D8-C4-6A (hex) Murata Manufacturing Co., Ltd. +D8C46A (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +D8-FB-68 (hex) Cloud Corner Ltd. +D8FB68 (base 16) Cloud Corner Ltd. + Cloud Corner Smart Bldg, Mei Ju Center NO.39 Dongcheng South Road + Dong Guan Guang Dong 523129 + CN + +68-53-88 (hex) P&S Technology +685388 (base 16) P&S Technology + 216 Deajiro + Yongin-si Gyeonggi-do 448-813 + KR + +98-2F-3C (hex) Sichuan Changhong Electric Ltd. +982F3C (base 16) Sichuan Changhong Electric Ltd. + 35 East Mianxing Road,High-Tech Park, + MianYang SiChuan 621000 + CN + +14-C1-FF (hex) ShenZhen QianHai Comlan communication Co.,LTD +14C1FF (base 16) ShenZhen QianHai Comlan communication Co.,LTD + Shenzhen Nanshan district keyuan road Dongfang science and technology building, room 2407. + ShenZhen GuangDong 518000 + CN + +00-04-17 (hex) ELAU AG +000417 (base 16) ELAU AG + Dillberg 12 + + DE + +EC-FA-AA (hex) The IMS Company +ECFAAA (base 16) The IMS Company + 2929 E. Imperial Highway + Brea CA 92821 + US + +F0-07-86 (hex) Shandong Bittel Electronics Co., Ltd +F00786 (base 16) Shandong Bittel Electronics Co., Ltd + No.1 Rizhao North Road + Rizhao Shandong 276800 + CN + +00-D0-F6 (hex) Nokia +00D0F6 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +54-A6-19 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +54A619 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +00-09-97 (hex) Nortel Networks +000997 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1C-EB (hex) Nortel Networks +001CEB (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1C-17 (hex) Nortel Networks +001C17 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1A-8F (hex) Nortel Networks +001A8F (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-17-D1 (hex) Nortel Networks +0017D1 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +88-83-22 (hex) Samsung Electronics Co.,Ltd +888322 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E8-93-09 (hex) Samsung Electronics Co.,Ltd +E89309 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-14-C7 (hex) Nortel Networks +0014C7 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1D-AF (hex) Nortel Networks +001DAF (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +88-A6-C6 (hex) Sagemcom Broadband SAS +88A6C6 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +94-D4-69 (hex) Cisco Systems, Inc +94D469 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +88-2B-D7 (hex) ADDÉNERGIE TECHNOLOGIES +882BD7 (base 16) ADDÉNERGIE TECHNOLOGIES + 533 avenue de la montagne LOCAL 121 + Shawinigan Quebec G9N 0A3 + CA + +00-90-CC (hex) PLANEX COMMUNICATIONS INC. +0090CC (base 16) PLANEX COMMUNICATIONS INC. + 2F FENISSAY Ebisu Bldg + Shibuya-ku, Tokyo 150-0011 + JP + +20-57-AF (hex) Shenzhen FH-NET OPTOELECTRONICS CO.,LTD +2057AF (base 16) Shenzhen FH-NET OPTOELECTRONICS CO.,LTD + 5/F Building D1 TCL International E City NO.1001 Zhong shan yuan Rd, Nanshan District Shenzhen china + Shenzhen GuangDong 518055 + CN + +54-DC-1D (hex) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd +54DC1D (base 16) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + Road NO2, West of Industrial Park,North of Science & Technology Park + Dongguan Guangdong 518057 + CN + +AC-A2-13 (hex) Shenzhen Bilian electronic CO.,LTD +ACA213 (base 16) Shenzhen Bilian electronic CO.,LTD + NO 268,Fuqian Rd,Jutang Community + shenzhen guangdong 518110 + CN + +3C-33-00 (hex) Shenzhen Bilian electronic CO.,LTD +3C3300 (base 16) Shenzhen Bilian electronic CO.,LTD + NO 268,Fuqian Rd,Jutang Community,Guanlan town , LongHua new district + Shenzhen Guangdong 518110 + CN + +6C-D0-32 (hex) LG Electronics +6CD032 (base 16) LG Electronics + 16, Woomyeon-dong, Seocho-gu + Seoul 137-724 + KR + +3C-BD-D8 (hex) LG ELECTRONICS INC +3CBDD8 (base 16) LG ELECTRONICS INC + 19-1, CHEONGHO-RI, JINWI-MYEON + PYEONGTAEK GYEONGGI-DO 451-713 + KR + +34-4D-F7 (hex) LG Electronics (Mobile Communications) +344DF7 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +58-3F-54 (hex) LG Electronics (Mobile Communications) +583F54 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-22-CF (hex) PLANEX COMMUNICATIONS INC. +0022CF (base 16) PLANEX COMMUNICATIONS INC. + 2F F ・ NISSAY Ebisu Bldg3-16-3 + Shibuya-ku Tokyo 150-0011 + JP + +E4-17-D8 (hex) 8BITDO TECHNOLOGY HK LIMITED +E417D8 (base 16) 8BITDO TECHNOLOGY HK LIMITED + Rooms 1318-19, 13/F, Hollywood Plaza, 610 Nathan Road, Mongkok, Kowloon, Hong Kong + Hong Kong Hong Kong 000000 + CN + +9C-D3-32 (hex) PLC Technology Ltd +9CD332 (base 16) PLC Technology Ltd + Nauchny proezd, 17 + Moscow Select State 117246 + RU + +38-F8-CA (hex) OWIN Inc. +38F8CA (base 16) OWIN Inc. + Chosunref 5fl,577,Seolleung-ro,Gangnam-gu + Seoul 682-20 + KR + +44-33-4C (hex) Shenzhen Bilian electronic CO.,LTD +44334C (base 16) Shenzhen Bilian electronic CO.,LTD + NO 268 + Shenzhen Guangdong 518110 + CN + +64-89-9A (hex) LG Electronics (Mobile Communications) +64899A (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-21-05 (hex) Alcatel-Lucent IPD +002105 (base 16) Alcatel-Lucent IPD + 701 E. Middlefield Rd. + Mountain View CA 94043 + US + +00-1B-C5 (hex) IEEE Registration Authority +001BC5 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +48-DF-37 (hex) Hewlett Packard Enterprise +48DF37 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +C0-E4-2D (hex) TP-LINK TECHNOLOGIES CO.,LTD. +C0E42D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +8C-A6-DF (hex) TP-LINK TECHNOLOGIES CO.,LTD. +8CA6DF (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +84-16-F9 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +8416F9 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +18-D6-C7 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +18D6C7 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +78-C3-E9 (hex) Samsung Electronics Co.,Ltd +78C3E9 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +8C-1A-BF (hex) Samsung Electronics Co.,Ltd +8C1ABF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +30-CB-F8 (hex) Samsung Electronics Co.,Ltd +30CBF8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A0-CB-FD (hex) Samsung Electronics Co.,Ltd +A0CBFD (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E4-5D-75 (hex) Samsung Electronics Co.,Ltd +E45D75 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-E0-4D (hex) INTERNET INITIATIVE JAPAN, INC +00E04D (base 16) INTERNET INITIATIVE JAPAN, INC + 1-4, SANBAN-CHO, CHIYODA-KU + TOKYO 102 + JP + +F8-A9-D0 (hex) LG Electronics (Mobile Communications) +F8A9D0 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +CC-FA-00 (hex) LG Electronics (Mobile Communications) +CCFA00 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +74-A7-22 (hex) LG Electronics (Mobile Communications) +74A722 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +F0-1C-13 (hex) LG Electronics (Mobile Communications) +F01C13 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +58-FC-DB (hex) IEEE Registration Authority +58FCDB (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +B0-C5-CA (hex) IEEE Registration Authority +B0C5CA (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +74-19-F8 (hex) IEEE Registration Authority +7419F8 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +A8-16-B2 (hex) LG Electronics (Mobile Communications) +A816B2 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +64-BC-0C (hex) LG Electronics (Mobile Communications) +64BC0C (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +90-C6-82 (hex) IEEE Registration Authority +90C682 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +C0-1A-DA (hex) Apple, Inc. +C01ADA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-60-0C (hex) QUANTA COMPUTER INC. +2C600C (base 16) QUANTA COMPUTER INC. + No.211, Wen Hwa 2nd Rd + Taoyuan Taiwan 33377 + TW + +00-00-31 (hex) QPSX COMMUNICATIONS, LTD. +000031 (base 16) QPSX COMMUNICATIONS, LTD. + 33 RICHARDSON STREET + Western 00000 + AU + +00-0E-1E (hex) QLogic Corporation +000E1E (base 16) QLogic Corporation + 26650 Aliso Viejo Parkway + Aliso Viejo CA 92656 + US + +00-14-D1 (hex) TRENDnet, Inc. +0014D1 (base 16) TRENDnet, Inc. + 20675 Manhattan Place + Torrance CA 90501 + US + +00-23-8B (hex) QUANTA COMPUTER INC. +00238B (base 16) QUANTA COMPUTER INC. + NO. 211, WEN HWA 2RD.,KUEI SHAN HSIANG, TAO YUAN SHIEN, + TAIPEI TAIWAN 333 + TW + +00-1E-68 (hex) QUANTA COMPUTER INC. +001E68 (base 16) QUANTA COMPUTER INC. + NO. 211, WEN HWA 2RD., KUEI SHAN HSIANG + TAIPEI TAO YUAN SHIEN 333 + TW + +CC-52-AF (hex) Universal Global Scientific Industrial Co., Ltd. +CC52AF (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, LANE 351, TAIPING RD. + nan tou NAN-TOU 542 + TW + +00-1C-14 (hex) VMware, Inc. +001C14 (base 16) VMware, Inc. + 3401 Hillview Avenue + Palo Alto CA 94304 + US + +00-50-56 (hex) VMware, Inc. +005056 (base 16) VMware, Inc. + 3401 Hillview Avenue + PALO ALTO CA 94304 + US + +00-12-1C (hex) PARROT SA +00121C (base 16) PARROT SA + 174 Quai de Jemmapes + Paris 75010 + FR + +90-03-B7 (hex) PARROT SA +9003B7 (base 16) PARROT SA + 174 Quai de Jemmapes + Paris 75010 + FR + +20-87-56 (hex) SIEMENS AG +208756 (base 16) SIEMENS AG + Oestliche Rheinbrueckenstrasse 50 + Karlsruhe Baden-Württemberg 76187 + DE + +74-B4-72 (hex) CIESSE +74B472 (base 16) CIESSE + Via G. di Vittorio, 66 + Rignano Sull'Arno Florence 50067 + IT + +FC-F1-52 (hex) Sony Corporation +FCF152 (base 16) Sony Corporation + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +48-3C-0C (hex) HUAWEI TECHNOLOGIES CO.,LTD +483C0C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +30-9B-AD (hex) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. +309BAD (base 16) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + LiWu INDUSTRIAL PARK,Wusha,Chang'an + Dong Guan Guang Dong 523860 + CN + +00-1B-B1 (hex) Wistron Neweb Corporation +001BB1 (base 16) Wistron Neweb Corporation + No. 10-1, Li-hsin Road I, Hsinchu Science Park, + Hsinchu 300 + TW + +00-80-F7 (hex) Zenith Electronics Corporation +0080F7 (base 16) Zenith Electronics Corporation + 1000 MILWAUKEE AVENUE + GLENVIEW IL 60025 + US + +BC-30-7D (hex) Wistron Neweb Corporation +BC307D (base 16) Wistron Neweb Corporation + 20 Park Avenue II, Hsin Science Park, Hsinchu 308, Taiwan + HsinChu Taiwan 308 + TW + +48-A9-D2 (hex) Wistron Neweb Corporation +48A9D2 (base 16) Wistron Neweb Corporation + 20 Park Avenue II, Hsin Science Park, Hsinchu 308, Taiwan + HsinChu Taiwan 308 + TW + +80-EA-23 (hex) Wistron Neweb Corporation +80EA23 (base 16) Wistron Neweb Corporation + 20 Park Avenue II, Hsin Science Park, Hsinchu 308, Taiwan + HsinChu Taiwan 308 + TW + +00-27-13 (hex) Universal Global Scientific Industrial Co., Ltd. +002713 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, LANE 351,SEC.1, TAIPING RD. + TSAOTUEN, NANTOU 54261 + TW + +BC-30-7E (hex) Wistron Neweb Corporation +BC307E (base 16) Wistron Neweb Corporation + 20 Park Avenue II. + Hsinchu 30808854 + TW + +08-95-2A (hex) Technicolor CH USA Inc. +08952A (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +44-32-C8 (hex) Technicolor CH USA Inc. +4432C8 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +38-A2-8C (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +38A28C (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District, + Shenzhen Guangdong 518000 + CN + +B4-A5-EF (hex) Sercomm Corporation. +B4A5EF (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +84-9D-64 (hex) SMC Corporation +849D64 (base 16) SMC Corporation + 4-2-2, Kinunodai + Tsukuba Mirai-shi Ibaraki-ken 300-2493 + JP + +00-10-C1 (hex) OI ELECTRIC CO.,LTD +0010C1 (base 16) OI ELECTRIC CO.,LTD + 7-3-16 KIKUNA + YOKOHAMA KANAGAWA-KEN 222-0011 + JP + +28-BE-9B (hex) Technicolor CH USA Inc. +28BE9B (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +FC-52-8D (hex) Technicolor CH USA Inc. +FC528D (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +50-65-83 (hex) Texas Instruments +506583 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +B0-91-22 (hex) Texas Instruments +B09122 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +FC-51-A4 (hex) ARRIS Group, Inc. +FC51A4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +98-57-D3 (hex) HON HAI-CCPBG PRECISION IND.CO.,LTD. +9857D3 (base 16) HON HAI-CCPBG PRECISION IND.CO.,LTD. + 5F, No.9,Li-Hsin Road V,Science Park + Hsinchu 300 + TW + +FC-F5-28 (hex) Zyxel Communications Corporation +FCF528 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +00-A0-C5 (hex) Zyxel Communications Corporation +00A0C5 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +A0-9E-1A (hex) Polar Electro Oy +A09E1A (base 16) Polar Electro Oy + Professorintie 5 + Kempele Oulu 90440 + FI + +1C-D6-BD (hex) LEEDARSON LIGHTING CO., LTD. +1CD6BD (base 16) LEEDARSON LIGHTING CO., LTD. + No. 1511, 2nd Fanghu North Rd., Huli District + Xiamen Fugian 361010 + CN + +D0-D9-4F (hex) IEEE Registration Authority +D0D94F (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-1E-04 (hex) Hanson Research Corporation +001E04 (base 16) Hanson Research Corporation + 9810 Variel Ave. + Chatsworth CA 91311 + US + +60-C0-BF (hex) ON Semiconductor +60C0BF (base 16) ON Semiconductor + 5005 East McDowell Road + Phoenix AZ 85008 + US + +AC-04-81 (hex) Jiangsu Huaxing Electronics Co., Ltd. +AC0481 (base 16) Jiangsu Huaxing Electronics Co., Ltd. + the Industrial concentration zone, Zhiqian town,Jintan distric + Changzhou City Jiangsu Province 213234 + CN + +68-B3-5E (hex) Shenzhen Neostra Technology Co.Ltd +68B35E (base 16) Shenzhen Neostra Technology Co.Ltd + 7th Building,Huaide Cuihai Industrial Park,Fuyong,Shenzhen China + shenzhen 518100 + CN + +40-88-05 (hex) Motorola Mobility LLC, a Lenovo Company +408805 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +24-E2-71 (hex) Qingdao Hisense Communications Co.,Ltd. +24E271 (base 16) Qingdao Hisense Communications Co.,Ltd. + Qianwangang Road 218 + Qingdao Shandong 266510 + CN + +BC-60-10 (hex) Qingdao Hisense Communications Co.,Ltd. +BC6010 (base 16) Qingdao Hisense Communications Co.,Ltd. + Qianwangang Road 218 + Qingdao Shandong 266510 + CN + +D0-FC-CC (hex) Samsung Electronics Co.,Ltd +D0FCCC (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +98-39-8E (hex) Samsung Electronics Co.,Ltd +98398E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +44-D1-FA (hex) Shenzhen Yunlink Technology Co., Ltd +44D1FA (base 16) Shenzhen Yunlink Technology Co., Ltd + Gushu, Xixiang Town, Bao'an District, + Shenzhen City Guangdong Province 518100 + CN + +F0-F6-44 (hex) Whitesky Science & Technology Co.,Ltd. +F0F644 (base 16) Whitesky Science & Technology Co.,Ltd. + Room301,Building7,NO.6,Lane365 + Shanghai 200052 + CN + +20-F1-7C (hex) HUAWEI TECHNOLOGIES CO.,LTD +20F17C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +34-6A-C2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +346AC2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-1C-FF (hex) Vizio, Inc +C41CFF (base 16) Vizio, Inc + 39 Tesla + Irvine CA 92618 + US + +C0-97-27 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +C09727 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +DC-29-3A (hex) Shenzhen Nuoshi Technology Co., LTD. +DC293A (base 16) Shenzhen Nuoshi Technology Co., LTD. + Room 7020 of Tian Xia IC Industry Park, Majialong Industrial Zone, YiYuan Road + Nanshan District, Shenzhen Guangdong 518052 + CN + +7C-6A-F3 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +7C6AF3 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +E4-62-51 (hex) HAO CHENG GROUP LIMITED +E46251 (base 16) HAO CHENG GROUP LIMITED + FLAT/RM C, 06/F, BEST-TO-BEST COMMERCIAL CENTRE 32-36 FERRY STREET JORDAN KL + Hong KOng 999077 + HK + +40-56-2D (hex) Smartron India Pvt ltd +40562D (base 16) Smartron India Pvt ltd + 1st Floor, Kapil Tower, Gachibowli + Hyderabad Telangana 500032 + IN + +38-76-D1 (hex) Euronda SpA +3876D1 (base 16) Euronda SpA + Via dell'artigianato, 7 + Montecchio Precalcino Italia/Vicenza 36030 + IT + +C4-69-3E (hex) Turbulence Design Inc. +C4693E (base 16) Turbulence Design Inc. + 1-3-14 + Koshigaya-City Saitama 343-0813 + JP + +00-95-69 (hex) LSD Science and Technology Co.,Ltd. +009569 (base 16) LSD Science and Technology Co.,Ltd. + Lierda Building,No.425 Dengyun Rd. + Hangzhou Zhijiang 310011 + CN + +B0-CF-4D (hex) MI-Zone Technology Ireland +B0CF4D (base 16) MI-Zone Technology Ireland + 2nd floor,block 10 unit 3 + dublin Blanchardstown 15 + IE + +28-9A-FA (hex) TCT mobile ltd +289AFA (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +00-1A-34 (hex) Konka Group Co., Ltd. +001A34 (base 16) Konka Group Co., Ltd. + Shenzhen Konka R & D Building, 28th floor 15-24 + Nanshan District Guangdong 00000 + CN + +00-11-FC (hex) HARTING Electronics GmbH +0011FC (base 16) HARTING Electronics GmbH + Wilhelm Harting Str. 1 + Espelkamp Nordrhein Westfalen D-32339 + DE + +00-23-89 (hex) Hangzhou H3C Technologies Co., Limited +002389 (base 16) Hangzhou H3C Technologies Co., Limited + Oriental Electronics Bldg., #2, Chuangye Road£¬Shangdi Information Industry Base, + Beijing 100085 + US + +3C-E5-A6 (hex) Hangzhou H3C Technologies Co., Limited +3CE5A6 (base 16) Hangzhou H3C Technologies Co., Limited + Oriental Electronic Bld., NO.2,Chuangye Road + Beijing 100085 + CN + +5C-DD-70 (hex) Hangzhou H3C Technologies Co., Limited +5CDD70 (base 16) Hangzhou H3C Technologies Co., Limited + 310 Liuhe Road, Zhijiang Science Park + Hangzhou Zhejiang, 310053 + CN + +3C-8C-40 (hex) Hangzhou H3C Technologies Co., Limited +3C8C40 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District, + Hangzhou Zhejiang, P.R.China 310052 + CN + +A0-67-BE (hex) Sicon srl +A067BE (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +D8-20-9F (hex) Cubro Acronet GesmbH +D8209F (base 16) Cubro Acronet GesmbH + Geiselberstraße 17 / 6 Floor + Vienna Vienna 1110 + AT + +8C-77-16 (hex) LONGCHEER TELECOMMUNICATION LIMITED +8C7716 (base 16) LONGCHEER TELECOMMUNICATION LIMITED + Building 1,No.401,Caobao Rd + Shanghai Xuhui District 200233 + CN + +68-FB-7E (hex) Apple, Inc. +68FB7E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-A1-34 (hex) Apple, Inc. +84A134 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-D3-85 (hex) AUMA Riester GmbH & Co. KG +A0D385 (base 16) AUMA Riester GmbH & Co. KG + Aumastr. 1 + Muellheim Baden-Württemberg 79379 + DE + +14-14-E6 (hex) Ningbo Sanhe Digital Co.,Ltd +1414E6 (base 16) Ningbo Sanhe Digital Co.,Ltd + No.1177 Lingyun Road + ningbo zhejiang 315048 + CN + +00-25-82 (hex) Maksat Technologies (P) Ltd +002582 (base 16) Maksat Technologies (P) Ltd + D-10/6, Okhla, Phase-I + New Delhi 110020 + IN + +0C-51-01 (hex) Apple, Inc. +0C5101 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-F0-A2 (hex) Apple, Inc. +2CF0A2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-C0-49 (hex) Broad Telecom SA +48C049 (base 16) Broad Telecom SA + c/ Margarita Salas, 22 + Leganes Madrid 28918 + ES + +AC-6F-BB (hex) TATUNG Technology Inc. +AC6FBB (base 16) TATUNG Technology Inc. + 22, Chungshan N. Rd., 3rd Sec., + Taipei 104 + TW + +00-1C-41 (hex) scemtec Transponder Technology GmbH +001C41 (base 16) scemtec Transponder Technology GmbH + Wehrstr. 1 + Gummersbach NRW 51645 + DE + +14-63-08 (hex) JABIL CIRCUIT (SHANGHAI) LTD. +146308 (base 16) JABIL CIRCUIT (SHANGHAI) LTD. + FL5-UNIT A2 NO. 1528 GUMEI ROAD + SHANGHAI 200233 + CN + +00-1E-25 (hex) INTEK DIGITAL +001E25 (base 16) INTEK DIGITAL + 1101, 11th Fl., Anyang K-center building, 1591-9 + Anyang Gyeonggi-do 431-815 + KR + +00-E0-CF (hex) INTEGRATED DEVICE +00E0CF (base 16) INTEGRATED DEVICE + 6024 Silver Creek Valley Road + San Jose CA 95138 + US + +90-4D-4A (hex) Sagemcom Broadband SAS +904D4A (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +04-4E-5A (hex) ARRIS Group, Inc. +044E5A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-60-B1 (hex) Input/Output, Inc. +0060B1 (base 16) Input/Output, Inc. + 12300 PARC CREST DRIVE + STAFFORD TX 77477-2416 + US + +54-7F-54 (hex) INGENICO +547F54 (base 16) INGENICO + 9, avenue de la gare - BP 25156 + Valence cedex 9 26958 + FR + +6C-24-83 (hex) Microsoft Mobile Oy +6C2483 (base 16) Microsoft Mobile Oy + Keilalahdentie 4 + Espoo 02150 + FI + +68-91-D0 (hex) IEEE Registration Authority +6891D0 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E0-4F-43 (hex) Universal Global Scientific Industrial Co., Ltd. +E04F43 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, Lane 351, Taiping Road, Sec.1,Tsao Tuen + Nan-Tou Taiwan 54261 + TW + +38-70-0C (hex) ARRIS Group, Inc. +38700C (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-0E-2E (hex) Edimax Technology Co. Ltd. +000E2E (base 16) Edimax Technology Co. Ltd. + No. 278, Xinhu 1st Road + Taipei City Neihu Dist 248 + TW + +00-06-5F (hex) ECI Telecom Ltd. +00065F (base 16) ECI Telecom Ltd. + 30 Hasivim St. + hasivivm 53188 + IL + +00-20-8F (hex) ECI Telecom Ltd. +00208F (base 16) ECI Telecom Ltd. + HASIVIM ST. 30, + PETACH-TIKVA 49133 49133 + IL + +84-40-76 (hex) Drivenets +844076 (base 16) Drivenets + 4 ashizaf + Raanana 4366411 + IL + +00-1C-D7 (hex) Harman/Becker Automotive Systems GmbH +001CD7 (base 16) Harman/Becker Automotive Systems GmbH + Becker-Göring-Straße 16 + Karlsbad Baden-Württemberg 76307 + DE + +00-3A-7D (hex) Cisco Systems, Inc +003A7D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +90-C7-D8 (hex) zte corporation +90C7D8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-18-5C (hex) EDSLAB Technologies +00185C (base 16) EDSLAB Technologies + 20 Ayer Rajah Crescent + Crescent 139964 + SG + +00-1A-45 (hex) GN Netcom A/S +001A45 (base 16) GN Netcom A/S + Metalbuen 66 + Ballerup Skovlunde DK - 2750 + DK + +00-20-88 (hex) GLOBAL VILLAGE COMMUNICATION +002088 (base 16) GLOBAL VILLAGE COMMUNICATION + 1144 EAST ARQUES AVENUE + SUNNYVALE CA 94086 + US + +54-13-79 (hex) Hon Hai Precision Ind. Co.,Ltd. +541379 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-19-21 (hex) Elitegroup Computer Systems Co.,Ltd. +001921 (base 16) Elitegroup Computer Systems Co.,Ltd. + No.22,Alley 38,Lane 91, Sec. 1,Nei Hu Road. + Taipei 114 + TW + +00-16-EC (hex) Elitegroup Computer Systems Co.,Ltd. +0016EC (base 16) Elitegroup Computer Systems Co.,Ltd. + No. 22, Alley 38, Lane 91, Sec. 1, Nei Hu Road, + Taipei 11441 + TW + +00-07-95 (hex) Elitegroup Computer Systems Co.,Ltd. +000795 (base 16) Elitegroup Computer Systems Co.,Ltd. + No. 22, Alley 38, Lane 91, + Taipei 114 + TW + +FC-0F-4B (hex) Texas Instruments +FC0F4B (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +D4-88-3F (hex) HDPRO CO., LTD. +D4883F (base 16) HDPRO CO., LTD. + HDPRO Bldg. 23, 362 Beon-gil, Shinheung-ro, Ojeong-gu + Bucheon-City Gyunggi-Do 14491 + KR + +10-88-CE (hex) Fiberhome Telecommunication Technologies Co.,LTD +1088CE (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +60-B6-17 (hex) Fiberhome Telecommunication Technologies Co.,LTD +60B617 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +DC-9C-9F (hex) Shenzhen YOUHUA Technology Co., Ltd +DC9C9F (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +74-DF-BF (hex) Liteon Technology Corporation +74DFBF (base 16) Liteon Technology Corporation + 7F, Bldg, C, 90, Chien 1 Road + Taipei Taiwan 23585 + TW + +F0-3E-90 (hex) Ruckus Wireless +F03E90 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +D8-D7-23 (hex) IDS, Inc +D8D723 (base 16) IDS, Inc + 6801 15 Mile Rd. + Sterling Heights MI 48312 + US + +84-AD-58 (hex) HUAWEI TECHNOLOGIES CO.,LTD +84AD58 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +58-60-5F (hex) HUAWEI TECHNOLOGIES CO.,LTD +58605F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-A0-F4 (hex) GE +00A0F4 (base 16) GE + W-657 + WAUKESHA WI 53188 + US + +AC-0D-1B (hex) LG Electronics (Mobile Communications) +AC0D1B (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +F0-D1-B8 (hex) LEDVANCE +F0D1B8 (base 16) LEDVANCE + 200 Ballardvale St + Wilmington MA 01887 + US + +98-6D-35 (hex) IEEE Registration Authority +986D35 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +88-79-5B (hex) Konka Group Co., Ltd. +88795B (base 16) Konka Group Co., Ltd. + Shenzhen Konka R & D Building, 28th floor 15-24 + Nanshan District Guangdong 00000 + CN + +08-1F-71 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +081F71 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +5C-CA-1A (hex) Microsoft Mobile Oy +5CCA1A (base 16) Microsoft Mobile Oy + Keilalahdentie 4 + Espoo 02150 + FI + +FC-2F-AA (hex) Nokia +FC2FAA (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +B0-7E-70 (hex) Zadara Storage Ltd. +B07E70 (base 16) Zadara Storage Ltd. + 6 Venture, Suite 140 + Irvine CA 92618 + US + +00-80-B1 (hex) SOFTCOM A/S +0080B1 (base 16) SOFTCOM A/S + STUDIESTRAEDE 21 + + DK + +20-2D-F8 (hex) Digital Media Cartridge Ltd. +202DF8 (base 16) Digital Media Cartridge Ltd. + 5F-3, No. 9, Ln 3, Jihu Rd, Neihu + Taipei 11492 + TW + +10-D0-AB (hex) zte corporation +10D0AB (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-04-C6 (hex) YAMAHA MOTOR CO.,LTD +0004C6 (base 16) YAMAHA MOTOR CO.,LTD + Information System Division + Japan Zip: 438-8501 + JP + +18-A3-E8 (hex) Fiberhome Telecommunication Technologies Co.,LTD +18A3E8 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +74-1E-93 (hex) Fiberhome Telecommunication Technologies Co.,LTD +741E93 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +20-2D-07 (hex) Samsung Electronics Co.,Ltd +202D07 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D8-80-3C (hex) Anhui Huami Information Technology Company Limited +D8803C (base 16) Anhui Huami Information Technology Company Limited + Building A4, 12th Floor, No. 800, Wangjiang Road + Hefei Anhui 230088 + CN + +00-34-DA (hex) LG Electronics (Mobile Communications) +0034DA (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +38-10-D5 (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +3810D5 (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +18-C5-01 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +18C501 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +00-A0-B8 (hex) NetApp +00A0B8 (base 16) NetApp + 1395 Crossman Ave + Sunnyvale, CA 94089 + US + +00-C8-8B (hex) Cisco Systems, Inc +00C88B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +24-C3-F9 (hex) Securitas Direct AB +24C3F9 (base 16) Securitas Direct AB + Angbatsbron 1 + Malmö 21120 + SE + +2C-21-D7 (hex) IMAX Corporation +2C21D7 (base 16) IMAX Corporation + 2525 Speakman Drive + Mississauga Ontario L5K 1B1 + CA + +00-09-D2 (hex) Mai Logic Inc. +0009D2 (base 16) Mai Logic Inc. + 47697 Westinghouse Dr., Suite 200 + Fremont CA 94539 + US + +00-60-16 (hex) CLARIION +006016 (base 16) CLARIION + COSLIN DRIVE + SOUTHBORO MA 01772 + US + +98-1F-B1 (hex) Shenzhen Lemon Network Technology Co.,Ltd +981FB1 (base 16) Shenzhen Lemon Network Technology Co.,Ltd + Changhong Technology Building 1710-11,South NO.12 Road,Nanshan Technology Park,Nanshan District,Shenzhen,China. + shenzhen 518100 + CN + +0C-5A-9E (hex) Wi-SUN Alliance +0C5A9E (base 16) Wi-SUN Alliance + 275 Tennant Avenue, Suite 202 + Morgan Hill CA 95037 + US + +B4-4B-D2 (hex) Apple, Inc. +B44BD2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +DC-41-5F (hex) Apple, Inc. +DC415F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-12-25 (hex) Cisco Systems, Inc +641225 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +78-64-E6 (hex) Green Motive Technology Limited +7864E6 (base 16) Green Motive Technology Limited + Room 1106,11 Floor,The XinYuan Square, No 418 Gui ping Road + shanghai shanghai 20233 + CN + +3C-BE-E1 (hex) NIKON CORPORATION +3CBEE1 (base 16) NIKON CORPORATION + Shinagawa Intercity Tower C, 2-15-3, Konan + Minato-ku Tokyo 108-6290 + JP + +10-2A-B3 (hex) Xiaomi Communications Co Ltd +102AB3 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +40-D3-57 (hex) Ison Technology Co., Ltd. +40D357 (base 16) Ison Technology Co., Ltd. + Room 6, 20F, No. 77, section 1, Xintai 5th Rd. Xizhi District + New Taipei City Taiwan 22101 + TW + +A4-15-88 (hex) ARRIS Group, Inc. +A41588 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F4-5C-89 (hex) Apple, Inc. +F45C89 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-76-8F (hex) Apple, Inc. +20768F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-5C-F9 (hex) Sony Mobile Communications Inc +9C5CF9 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-11-D1 (hex) Soft Imaging System GmbH +0011D1 (base 16) Soft Imaging System GmbH + Johann-Krane-Weg 39 + Muenster 48149 + DE + +98-D6-86 (hex) Chyi Lee industry Co., ltd. +98D686 (base 16) Chyi Lee industry Co., ltd. + No.25, Wufu Rd., Xinying Dist. + Tainan city 73054 + TW + +8C-C6-61 (hex) Current, powered by GE +8CC661 (base 16) Current, powered by GE + 1975 Noble Road B335C + East Cleveland OH 44112 + US + +88-A0-84 (hex) Formation Data Systems +88A084 (base 16) Formation Data Systems + 39141 Civic Center Drive, Suite 410 + Fremont CA 94538 + US + +E8-B2-AC (hex) Apple, Inc. +E8B2AC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-9A-79 (hex) Apple, Inc. +E49A79 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +30-A9-DE (hex) LG Innotek +30A9DE (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +F0-1B-6C (hex) vivo Mobile Communication Co., Ltd. +F01B6C (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +A0-B9-ED (hex) Skytap +A0B9ED (base 16) Skytap + 710 2nd Ave Suite 1130 + Seattle WA 98104 + US + +94-C9-60 (hex) Zhongshan B&T technology.co.,ltd +94C960 (base 16) Zhongshan B&T technology.co.,ltd + Floor3-4,Block A,Dong Fang Industrial park,Da che country,Nan Lang District + Zhong Shan City Guang Dong Province 528451 + CN + +74-C3-30 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +74C330 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +40-3F-8C (hex) TP-LINK TECHNOLOGIES CO.,LTD. +403F8C (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +DC-B3-B4 (hex) Honeywell Environmental & Combustion Controls (Tianjin) Co., Ltd. +DCB3B4 (base 16) Honeywell Environmental & Combustion Controls (Tianjin) Co., Ltd. + 158 Nan Hai Road, TEDA + Tianjin 300457 + CN + +00-1D-3B (hex) Nokia Danmark A/S +001D3B (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1D-FD (hex) Nokia Danmark A/S +001DFD (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1E-3B (hex) Nokia Danmark A/S +001E3B (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1E-A4 (hex) Nokia Danmark A/S +001EA4 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-26-CC (hex) Nokia Danmark A/S +0026CC (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-0E-ED (hex) Nokia Danmark A/S +000EED (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +4C-25-78 (hex) Nokia Corporation +4C2578 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo NA 24101 + FI + +BC-C6-DB (hex) Nokia Corporation +BCC6DB (base 16) Nokia Corporation + Joensuunkatu 7 + Salo NA 24101 + FI + +60-A8-FE (hex) Nokia +60A8FE (base 16) Nokia + Karaportti 3 + Espoo 02610 + FI + +00-11-9F (hex) Nokia Danmark A/S +00119F (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1A-16 (hex) Nokia Danmark A/S +001A16 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1A-89 (hex) Nokia Danmark A/S +001A89 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1A-DC (hex) Nokia Danmark A/S +001ADC (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-25-CF (hex) Nokia Danmark A/S +0025CF (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-21-AB (hex) Nokia Danmark A/S +0021AB (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1F-DE (hex) Nokia Danmark A/S +001FDE (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1F-DF (hex) Nokia Danmark A/S +001FDF (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +54-79-75 (hex) Nokia Corporation +547975 (base 16) Nokia Corporation + Joensuunkatu 7E + Salo 24101 + FI + +A8-7B-39 (hex) Nokia Corporation +A87B39 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo Varsinais-Suomi 24101 + FI + +00-24-7C (hex) Nokia Danmark A/S +00247C (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-22-66 (hex) Nokia Danmark A/S +002266 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-21-FE (hex) Nokia Danmark A/S +0021FE (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790V + DK + +C4-77-AB (hex) Beijing ASU Tech Co.,Ltd +C477AB (base 16) Beijing ASU Tech Co.,Ltd + 15/F, Global Trade Center Tower, No.36, North 3rd Ring Road, Dongcheng District, Beijing, 100013, China + BEI JING BEI JING 100013 + CN + +00-0B-CA (hex) DATAVAN TC +000BCA (base 16) DATAVAN TC + 4FL,#120-12,Chung Shan Rd, Sec.3 + Chung Ho City, Taipei Hsien 235 + TW + +70-25-59 (hex) CyberTAN Technology Inc. +702559 (base 16) CyberTAN Technology Inc. + 99, Park Avenue III, Science-Based Industrial Park + Hsinchu 308 + TW + +60-7E-DD (hex) Microsoft Mobile Oy +607EDD (base 16) Microsoft Mobile Oy + Keilalahdentie 4 + ESPOO 02150 + FI + +A8-A0-89 (hex) Tactical Communications +A8A089 (base 16) Tactical Communications + 473 Post Street + Camarillo CA 93010 + US + +48-36-5F (hex) Wintecronics Ltd. +48365F (base 16) Wintecronics Ltd. + Rm. 3, 11F., No.716, Zhongzheng Rd., Zhonghe Dist., New Taipei City 23552, Taiwan (R.O.C.) + New Taipei City 23552 + TW + +00-1D-20 (hex) Comtrend Corporation +001D20 (base 16) Comtrend Corporation + 3F-1, 10 Lane 609, Chongxin Road, Section 5, + New Taipei City, Taiwan 24159 + TW + +08-37-3D (hex) Samsung Electronics Co.,Ltd +08373D (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +0C-75-BD (hex) Cisco Systems, Inc +0C75BD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +30-0D-43 (hex) Microsoft Mobile Oy +300D43 (base 16) Microsoft Mobile Oy + Keilalahdentie 2-4 + Espoo N.A. 02150 + FI + +00-00-0E (hex) FUJITSU LIMITED +00000E (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +00-0B-5D (hex) FUJITSU LIMITED +000B5D (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +C4-88-E5 (hex) Samsung Electronics Co.,Ltd +C488E5 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +08-05-81 (hex) Roku, Inc. +080581 (base 16) Roku, Inc. + 12980 Saratoga Ave + Saratoga CA 95070 + US + +00-0D-F3 (hex) Asmax Solutions +000DF3 (base 16) Asmax Solutions + Tatarska 5 + Cracow 30-103 + PL + +80-AC-AC (hex) Juniper Networks +80ACAC (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-0D-B6 (hex) Broadcom +000DB6 (base 16) Broadcom + 1363 Redwood Way + Petaluma CA 94954 + US + +00-0A-F7 (hex) Broadcom +000AF7 (base 16) Broadcom + 16215 Alton Parkway + Irvine CA 92618 + US + +D4-01-29 (hex) Broadcom +D40129 (base 16) Broadcom + 5300 California Ave. + Irvine CA 92617 + US + +00-1D-00 (hex) Brivo Systems, LLC +001D00 (base 16) Brivo Systems, LLC + 4330 East West Highway + Bethesda MD 20814 + US + +00-20-D6 (hex) Breezecom, Ltd. +0020D6 (base 16) Breezecom, Ltd. + ATIDIM TECHNOLOGICAL PK-BLDG.3 + Tel-aviv 12345 + IL + +00-E0-63 (hex) Cabletron Systems, Inc. +00E063 (base 16) Cabletron Systems, Inc. + 35 INDUSTRIAL WAY + ROCHESTER NH 03866-5005 + US + +FC-C7-34 (hex) Samsung Electronics Co.,Ltd +FCC734 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +84-25-DB (hex) Samsung Electronics Co.,Ltd +8425DB (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-EC-71 (hex) Samsung Electronics Co.,Ltd +B0EC71 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E4-58-B8 (hex) Samsung Electronics Co.,Ltd +E458B8 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +08-8C-2C (hex) Samsung Electronics Co.,Ltd +088C2C (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +64-B8-53 (hex) Samsung Electronics Co.,Ltd +64B853 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +38-94-96 (hex) Samsung Electronics Co.,Ltd +389496 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +50-56-BF (hex) Samsung Electronics Co.,Ltd +5056BF (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +90-F1-AA (hex) Samsung Electronics Co.,Ltd +90F1AA (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +10-77-B1 (hex) Samsung Electronics Co.,Ltd +1077B1 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +00-1F-C7 (hex) Casio Hitachi Mobile Communications Co., Ltd. +001FC7 (base 16) Casio Hitachi Mobile Communications Co., Ltd. + 2-229-1, Sakuragaoka + Higashiyamato-shi Tokyo 207-8501 + JP + +A4-9A-58 (hex) Samsung Electronics Co.,Ltd +A49A58 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +08-EE-8B (hex) Samsung Electronics Co.,Ltd +08EE8B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +0C-A4-2A (hex) OB Telecom Electronic Technology Co., Ltd +0CA42A (base 16) OB Telecom Electronic Technology Co., Ltd + 17/F, Jiangong Building + Hangzhou ZheJiang 310012 + CN + +74-45-8A (hex) Samsung Electronics Co.,Ltd +74458A (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +5C-DC-96 (hex) Arcadyan Technology Corporation +5CDC96 (base 16) Arcadyan Technology Corporation + No.8, Sec.2, Guangfu Rd., + Hsinchu City 30071, 12345 + TW + +74-31-70 (hex) Arcadyan Technology Corporation +743170 (base 16) Arcadyan Technology Corporation + 4F. , No. 9 , Park Avenue II, + Hsinchu 300 + TW + +00-1A-2A (hex) Arcadyan Technology Corporation +001A2A (base 16) Arcadyan Technology Corporation + 4F., No. 9 , Park Avenue II, + Hsinchu 300 + TW + +88-25-2C (hex) Arcadyan Technology Corporation +88252C (base 16) Arcadyan Technology Corporation + 4F., NO.9, Park Avenue II , + Hsinchu 300 + TW + +40-BA-61 (hex) ARIMA Communications Corp. +40BA61 (base 16) ARIMA Communications Corp. + 6F., No.866, Jhongjheng Rd., Jhonghe Dist. + New Taipei City 23586 + TW + +00-11-F5 (hex) ASKEY COMPUTER CORP +0011F5 (base 16) ASKEY COMPUTER CORP + 10F, NO.119, CHIENKANG RD., + CHUNG-HO, TAIPEI 235 + TW + +00-16-E3 (hex) ASKEY COMPUTER CORP +0016E3 (base 16) ASKEY COMPUTER CORP + 10F, NO.119, CHIENKANG RD., + CHUNG-HO, TAIPEI 235 + TW + +E8-39-DF (hex) ASKEY COMPUTER CORP +E839DF (base 16) ASKEY COMPUTER CORP + 10F,NO.119,CHIENKANG RD,CHUNG-HO,TAIPEI, + TAIWAN TAIPEI 235 + TW + +1C-C6-3C (hex) Arcadyan Technology Corporation +1CC63C (base 16) Arcadyan Technology Corporation + 4F, No. 9, Park Avenue II , + Hsinchu 300 + TW + +18-83-BF (hex) Arcadyan Technology Corporation +1883BF (base 16) Arcadyan Technology Corporation + 4F, No. 9, Park Avenue II , + Hsinchu 300 + TW + +68-ED-43 (hex) BlackBerry RTS +68ED43 (base 16) BlackBerry RTS + 451 Phillip Street + Waterloo ON N2L 3X2 + CA + +70-AA-B2 (hex) BlackBerry RTS +70AAB2 (base 16) BlackBerry RTS + 451 Phillip Street + Waterloo ON N2L 3X2 + CA + +00-14-6C (hex) NETGEAR +00146C (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-1E-2A (hex) NETGEAR +001E2A (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-18-4D (hex) NETGEAR +00184D (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-04-0E (hex) AVM GmbH +00040E (base 16) AVM GmbH + Alt-Moabit 95 + berlin 12345 + DE + +9C-C7-A6 (hex) AVM GmbH +9CC7A6 (base 16) AVM GmbH + Alt-Moabit 95 + berlin Berlin 10559 + DE + +A0-63-91 (hex) NETGEAR +A06391 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +20-E5-2A (hex) NETGEAR +20E52A (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +44-94-FC (hex) NETGEAR +4494FC (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +20-0C-C8 (hex) NETGEAR +200CC8 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +C4-47-3F (hex) HUAWEI TECHNOLOGIES CO.,LTD +C4473F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +74-44-01 (hex) NETGEAR +744401 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +E0-91-F5 (hex) NETGEAR +E091F5 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-0F-86 (hex) BlackBerry RTS +000F86 (base 16) BlackBerry RTS + 295 Phillip Street + Waterloo Ontario N2L 3W8 + CA + +00-24-D2 (hex) ASKEY COMPUTER CORP +0024D2 (base 16) ASKEY COMPUTER CORP + 10F,NO.119,CHIENKANG RD,CHUNG-HO,TAIPEI, + TAIWAN TAIPEI 235 + TW + +B4-EE-B4 (hex) ASKEY COMPUTER CORP +B4EEB4 (base 16) ASKEY COMPUTER CORP + 10F,NO.119,CHIENKANG RD,ZHONGHE DIST NEW TAIPEI CITY + TAIWAN TAIPEI 23585 + TW + +E4-64-49 (hex) ARRIS Group, Inc. +E46449 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +40-FC-89 (hex) ARRIS Group, Inc. +40FC89 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +2C-9E-5F (hex) ARRIS Group, Inc. +2C9E5F (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-26-36 (hex) ARRIS Group, Inc. +002636 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1C-C1 (hex) ARRIS Group, Inc. +001CC1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1E-5A (hex) ARRIS Group, Inc. +001E5A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-13-71 (hex) ARRIS Group, Inc. +001371 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-23-EE (hex) ARRIS Group, Inc. +0023EE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1A-DE (hex) ARRIS Group, Inc. +001ADE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +74-56-12 (hex) ARRIS Group, Inc. +745612 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-50-E3 (hex) ARRIS Group, Inc. +0050E3 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-21-36 (hex) ARRIS Group, Inc. +002136 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-16-26 (hex) ARRIS Group, Inc. +001626 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-19-A6 (hex) ARRIS Group, Inc. +0019A6 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E8-C7-4F (hex) Liteon Technology Corporation +E8C74F (base 16) Liteon Technology Corporation + 4F, No. 90, Chien 1 Road, + New Taipei City Taiwan 23585 + TW + +D0-53-49 (hex) Liteon Technology Corporation +D05349 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road ChungHo + New Taipei City Taiwan 23585 + TW + +00-0B-A2 (hex) Sumitomo Electric Industries,Ltd +000BA2 (base 16) Sumitomo Electric Industries,Ltd + 1-1-3, Shimaya, Konohana-ku + Osaka 554-0024 + JP + +00-08-F6 (hex) Sumitomo Electric Industries,Ltd +0008F6 (base 16) Sumitomo Electric Industries,Ltd + 1-1-3, Shimaya, Konohana-ku + Osaka 554-0024 + JP + +00-00-5F (hex) Sumitomo Electric Industries,Ltd +00005F (base 16) Sumitomo Electric Industries,Ltd + 1-1-3, Shimaya, Konohana-ku + Osaka 554-0024 + JP + +E8-F7-24 (hex) Hewlett Packard Enterprise +E8F724 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +5C-B5-24 (hex) Sony Mobile Communications Inc +5CB524 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +90-C1-15 (hex) Sony Mobile Communications Inc +90C115 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +D0-51-62 (hex) Sony Mobile Communications Inc +D05162 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +18-00-2D (hex) Sony Mobile Communications Inc +18002D (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +28-0D-FC (hex) Sony Interactive Entertainment Inc. +280DFC (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +00-13-11 (hex) ARRIS Group, Inc. +001311 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D0-DF-9A (hex) Liteon Technology Corporation +D0DF9A (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +1C-65-9D (hex) Liteon Technology Corporation +1C659D (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +30-10-B3 (hex) Liteon Technology Corporation +3010B3 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road, ChungHo, TaiPei Hsien + TaiPei TaiWan 23585 + TW + +70-1A-04 (hex) Liteon Technology Corporation +701A04 (base 16) Liteon Technology Corporation + 4F 90 Chien 1 Rd.ChungHo + Taipei 23585 + TW + +48-D2-24 (hex) Liteon Technology Corporation +48D224 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo + New Taipei City Taipei 23585 + TW + +20-68-9D (hex) Liteon Technology Corporation +20689D (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo + New Taipei City Taipei 23585 + TW + +00-24-EF (hex) Sony Mobile Communications Inc +0024EF (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-25-E7 (hex) Sony Mobile Communications Inc +0025E7 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +58-17-0C (hex) Sony Mobile Communications Inc +58170C (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-16-B8 (hex) Sony Mobile Communications Inc +0016B8 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +7C-BF-B1 (hex) ARRIS Group, Inc. +7CBFB1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +08-00-46 (hex) Sony Corporation +080046 (base 16) Sony Corporation + Gotenyama Tec, 5-1-2 Kitashinagawa + Tokyo 141-0001 + JP + +EC-F0-0E (hex) AboCom +ECF00E (base 16) AboCom + 1F , No. 21, Yanfa 2nd Rd., SBIP + Hsinchu City 300 886 + TW + +00-E0-98 (hex) AboCom +00E098 (base 16) AboCom + 12F-3, NO. 333, SEC. 1 + HSIN-CHU 12345 + TW + +74-DA-EA (hex) Texas Instruments +74DAEA (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +94-88-15 (hex) Infinique Worldwide Inc +948815 (base 16) Infinique Worldwide Inc + 513, 4185 Shipp Drive + Mississauga Ontario L4Z2Y8 + CA + +D0-E4-4A (hex) Murata Manufacturing Co., Ltd. +D0E44A (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +38-4F-F0 (hex) AzureWave Technology Inc. +384FF0 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd + . New Taipei City Taiwan 231 + TW + +E8-74-E6 (hex) ADB Broadband Italia +E874E6 (base 16) ADB Broadband Italia + VIALE SARCA 336 + MILANO 20126 + IT + +00-20-E0 (hex) Actiontec Electronics, Inc +0020E0 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +00-26-62 (hex) Actiontec Electronics, Inc +002662 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +00-25-53 (hex) ADB Broadband Italia +002553 (base 16) ADB Broadband Italia + VIALE SARCA 222 + MILANO 20126 + IT + +00-19-3E (hex) ADB Broadband Italia +00193E (base 16) ADB Broadband Italia + VIALE SARCA 222 + MILANO 20126 + IT + +00-08-27 (hex) ADB Broadband Italia +000827 (base 16) ADB Broadband Italia + Viale Sarca 222 + pisacataway Milano 20126 + IT + +74-2F-68 (hex) AzureWave Technology Inc. +742F68 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd., Xindian + Taipei 231 + TW + +4C-14-A3 (hex) TCL Technoly Electronics (Huizhou) Co., Ltd. +4C14A3 (base 16) TCL Technoly Electronics (Huizhou) Co., Ltd. + 19th Zhongkai Hi-tech Development Zone + Huizhou Guangdong 516006 + CN + +4C-B0-E8 (hex) Beijing RongZhi xinghua technology co., LTD +4CB0E8 (base 16) Beijing RongZhi xinghua technology co., LTD + Beijing haidian district zhongguancun east road No. 18 smartfortune international building, room 909 + beijing beijing 100000 + CN + +D8-87-D5 (hex) Leadcore Technology CO.,LTD +D887D5 (base 16) Leadcore Technology CO.,LTD + 1258 Mingyue Road,Shanghai.China + shanghai shanghai 201206 + CN + +00-F2-8B (hex) Cisco Systems, Inc +00F28B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +34-E6-AD (hex) Intel Corporate +34E6AD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +08-11-96 (hex) Intel Corporate +081196 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +18-3D-A2 (hex) Intel Corporate +183DA2 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +80-9B-20 (hex) Intel Corporate +809B20 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-23-14 (hex) Intel Corporate +002314 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +34-02-86 (hex) Intel Corporate +340286 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1C-BF (hex) Intel Corporate +001CBF (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B4-B6-76 (hex) Intel Corporate +B4B676 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +3C-A9-F4 (hex) Intel Corporate +3CA9F4 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B8-8A-60 (hex) Intel Corporate +B88A60 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +78-FF-57 (hex) Intel Corporate +78FF57 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +9C-4E-36 (hex) Intel Corporate +9C4E36 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +34-13-E8 (hex) Intel Corporate +3413E8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-27-10 (hex) Intel Corporate +002710 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A4-8E-0A (hex) DeLaval International AB +A48E0A (base 16) DeLaval International AB + Gustaf De Lavals väg 15 + TUMBA 14721 + SE + +AC-2B-6E (hex) Intel Corporate +AC2B6E (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +9C-35-83 (hex) Nipro Diagnostics, Inc +9C3583 (base 16) Nipro Diagnostics, Inc + 2400 N.W. 55th Court. + Ft. Lauderdale FL 33309 + US + +C0-61-18 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +C06118 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +B8-2A-72 (hex) Dell Inc. +B82A72 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +F8-E0-79 (hex) Motorola Mobility LLC, a Lenovo Company +F8E079 (base 16) Motorola Mobility LLC, a Lenovo Company + 600 North US Highway 45 + Libertyville IL 60048 + US + +CC-C3-EA (hex) Motorola Mobility LLC, a Lenovo Company +CCC3EA (base 16) Motorola Mobility LLC, a Lenovo Company + 600 North US Highway 45 + Libertyville IL 60048 + US + +40-78-6A (hex) Motorola Mobility LLC, a Lenovo Company +40786A (base 16) Motorola Mobility LLC, a Lenovo Company + 222 Merchandise Mart Plaza, Suite 1800 + Chicago IL 60654 + US + +00-19-D1 (hex) Intel Corporate +0019D1 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-19-D2 (hex) Intel Corporate +0019D2 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1B-21 (hex) Intel Corporate +001B21 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +18-FF-0F (hex) Intel Corporate +18FF0F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +34-DE-1A (hex) Intel Corporate +34DE1A (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +E8-B1-FC (hex) Intel Corporate +E8B1FC (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +CC-3D-82 (hex) Intel Corporate +CC3D82 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1F-3C (hex) Intel Corporate +001F3C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-23-15 (hex) Intel Corporate +002315 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-16-6F (hex) Intel Corporate +00166F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-0A-8A (hex) Cisco Systems, Inc +000A8A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1D-09 (hex) Dell Inc. +001D09 (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +00-23-AE (hex) Dell Inc. +0023AE (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +BC-30-5B (hex) Dell Inc. +BC305B (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +38-86-02 (hex) Flexoptix GmbH +388602 (base 16) Flexoptix GmbH + Muehltalstr. 153 + Darmstadt 64297 + DE + +40-65-A3 (hex) Sagemcom Broadband SAS +4065A3 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +D0-22-12 (hex) IEEE Registration Authority +D02212 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +10-07-23 (hex) IEEE Registration Authority +100723 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +A4-4F-29 (hex) IEEE Registration Authority +A44F29 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +74-F8-DB (hex) IEEE Registration Authority +74F8DB (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +A4-3B-FA (hex) IEEE Registration Authority +A43BFA (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +B8-CA-3A (hex) Dell Inc. +B8CA3A (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +EC-F4-BB (hex) Dell Inc. +ECF4BB (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +D4-BE-D9 (hex) Dell Inc. +D4BED9 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-19-4B (hex) Sagemcom Broadband SAS +00194B (base 16) Sagemcom Broadband SAS + Le Ponnant de Paris + CEDEX Paris 75512 + FR + +00-1E-74 (hex) Sagemcom Broadband SAS +001E74 (base 16) Sagemcom Broadband SAS + Le Ponnant de Paris + CEDEX Paris 75512 + FR + +38-3B-C8 (hex) 2Wire Inc +383BC8 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose 95131 + US + +60-FE-20 (hex) 2Wire Inc +60FE20 (base 16) 2Wire Inc + 1764 Automation ParkWay + San Jose CA 95131 + US + +00-24-56 (hex) 2Wire Inc +002456 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +C0-83-0A (hex) 2Wire Inc +C0830A (base 16) 2Wire Inc + 1764 Automation Pkwy + San Jose CA 95131 + US + +00-18-3F (hex) 2Wire Inc +00183F (base 16) 2Wire Inc + 1704 Automation Parkway + San Jose CA 94538 + US + +00-0D-56 (hex) Dell Inc. +000D56 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +18-1E-78 (hex) Sagemcom Broadband SAS +181E78 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison HAUTS DE SEINE 92848 + FR + +00-37-B7 (hex) Sagemcom Broadband SAS +0037B7 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison HAUTS DE SEINE 92848 + FR + +00-54-BD (hex) Swelaser AB +0054BD (base 16) Swelaser AB + Tullgårdsgatan 8 + Stockholm 11668 + SE + +00-1E-4C (hex) Hon Hai Precision Ind. Co.,Ltd. +001E4C (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +20-BB-76 (hex) COL GIOVANNI PAOLO SpA +20BB76 (base 16) COL GIOVANNI PAOLO SpA + Via F.lli Ceirano n. 20 + Moncalieri TORINO 10024 + IT + +3C-DD-89 (hex) SOMO HOLDINGS & TECH. CO.,LTD. +3CDD89 (base 16) SOMO HOLDINGS & TECH. CO.,LTD. + 6, Mujeonggonddan-Gil + Damyang-Gun Jellanam-Do 57360 + KR + +18-01-E3 (hex) Bittium Wireless Ltd +1801E3 (base 16) Bittium Wireless Ltd + Tutkijantie 8 + Oulu 50590 + FI + +14-91-82 (hex) Belkin International Inc. +149182 (base 16) Belkin International Inc. + 12045 E. Waterfront Drive + Playa Vista CA 90094 + US + +18-62-2C (hex) Sagemcom Broadband SAS +18622C (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + RUEIL MALMAISON CEDEX Hauts de Seine 92848 + FR + +3C-81-D8 (hex) Sagemcom Broadband SAS +3C81D8 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + RUEIL MALMAISON CEDEX Hauts de Seine 92848 + FR + +40-F2-01 (hex) Sagemcom Broadband SAS +40F201 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison HAUTS DE SEINE 92848 + FR + +D0-84-B0 (hex) Sagemcom Broadband SAS +D084B0 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison HAUTS DE SEINE 92848 + FR + +D8-54-3A (hex) Texas Instruments +D8543A (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +64-9C-8E (hex) Texas Instruments +649C8E (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +10-2E-AF (hex) Texas Instruments +102EAF (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +7C-8E-E4 (hex) Texas Instruments +7C8EE4 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +B4-EE-D4 (hex) Texas Instruments +B4EED4 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +D0-37-61 (hex) Texas Instruments +D03761 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +C8-3E-99 (hex) Texas Instruments +C83E99 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +40-98-4E (hex) Texas Instruments +40984E (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-17-EB (hex) Texas Instruments +0017EB (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-17-E6 (hex) Texas Instruments +0017E6 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +C4-ED-BA (hex) Texas Instruments +C4EDBA (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-18-32 (hex) Texas Instruments +001832 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +3C-2D-B7 (hex) Texas Instruments +3C2DB7 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +54-64-D9 (hex) Sagemcom Broadband SAS +5464D9 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + RUEIL MALMAISON CEDEX Hauts de Seine 92848 + FR + +00-19-5B (hex) D-Link Corporation +00195B (base 16) D-Link Corporation + NO.289, Sinhu 3rd Rd., + Neihu District, Taipei City 114 + TW + +00-0F-3D (hex) D-Link Corporation +000F3D (base 16) D-Link Corporation + No.8,Li-shing Seventh Road,Science-based Industrial Park,Hsimchu, + Hsimchu 300 + TW + +24-DA-11 (hex) NO NDA Inc +24DA11 (base 16) NO NDA Inc + 828 Bryant St + Palo Alto IA 94301 + US + +EC-22-80 (hex) D-Link International +EC2280 (base 16) D-Link International + 1 Internal Business Park, #03-12, + SINGAPORE Singapore 609917 + SG + +9C-8E-99 (hex) Hewlett Packard +9C8E99 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +90-59-AF (hex) Texas Instruments +9059AF (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +BC-6A-29 (hex) Texas Instruments +BC6A29 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +84-7E-40 (hex) Texas Instruments +847E40 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-17-35 (hex) Intel Wireless Network Group +001735 (base 16) Intel Wireless Network Group + 2111 NE 25th Ave + Hillsboro OR 97124 + US + +74-AC-5F (hex) Qiku Internet Network Scientific (Shenzhen) Co., Ltd. +74AC5F (base 16) Qiku Internet Network Scientific (Shenzhen) Co., Ltd. + Cyber Harbor, 2nd Mengxi Road, Hi-Tech Industrial Park (North), NanShan District + ShenZhen GuangDong 518000 + CN + +38-CA-DA (hex) Apple, Inc. +38CADA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-B3-3F (hex) Shenzhen TINNO Mobile Technology Corp. +D0B33F (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F.,H-3 Building,OCT Eastern lndustrial Park. NO.1 XiangShan East Road., + GUANGDONG SHENZHEN 518053 + CN + +BC-D1-D3 (hex) Shenzhen TINNO Mobile Technology Corp. +BCD1D3 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F.,H-3 Building,OCT Eastern lndustrial Park. + Nanshan, Shenzhen GUANGDONG 518053 + CN + +D8-3C-69 (hex) Shenzhen TINNO Mobile Technology Corp. +D83C69 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F.,H-3 Building,OCT Eastern lndustrial Park. NO.1 XiangShan East Road + SHENZHEN GUANGDONG 518053 + CN + +F4-F5-D8 (hex) Google, Inc. +F4F5D8 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +8C-57-9B (hex) Wistron Neweb Corporation +8C579B (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +00-59-AC (hex) KPN. B.V. +0059AC (base 16) KPN. B.V. + Maanplein 55 + Den Haag Zuid holland 2516 CK + NL + +40-D8-55 (hex) IEEE Registration Authority +40D855 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +34-AB-37 (hex) Apple, Inc. +34AB37 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +24-00-BA (hex) HUAWEI TECHNOLOGIES CO.,LTD +2400BA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan Guangdong 523808 + CN + +24-DF-6A (hex) HUAWEI TECHNOLOGIES CO.,LTD +24DF6A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan Guangdong 523808 + CN + +78-8B-77 (hex) Standar Telecom +788B77 (base 16) Standar Telecom + Sadovnicheskaya 44 s.4 + Moscow 115035 + RU + +B0-C0-90 (hex) Chicony Electronics Co., Ltd. +B0C090 (base 16) Chicony Electronics Co., Ltd. + No.25, Wugong 6th Rd., Wugu Dist., + New Taipei City 248, TAIWAN, REPUBLIC OF CHINA 248 + TW + +90-7F-61 (hex) Chicony Electronics Co., Ltd. +907F61 (base 16) Chicony Electronics Co., Ltd. + No.25, Wu-Gong 6th Rd., Wu Ku Industrial Park, + New Taipei City, 248 + TW + +0C-05-35 (hex) Juniper Systems +0C0535 (base 16) Juniper Systems + 1132 W. 1700 N. + Logan UT 84321 + US + +BC-83-A7 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD +BC83A7 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + Unit A 13-16/F,Skyworth Bldg., Gaoxin Ave.1.S.,Nanshan District + Shenzhen GuangDong 518057 + CN + +BC-EC-23 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD +BCEC23 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + Unit A13-16/F,Skyworth Bldg., Gaoxin Ave.1.S.,Nanshan District,Shenzhen,China + ShenZhen GuangDong 518057 + CN + +18-AF-61 (hex) Apple, Inc. +18AF61 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-F9-38 (hex) Apple, Inc. +5CF938 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-90-69 (hex) Juniper Networks +009069 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +64-64-9B (hex) Juniper Networks +64649B (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +F0-1C-2D (hex) Juniper Networks +F01C2D (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +30-7C-5E (hex) Juniper Networks +307C5E (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +AC-06-C7 (hex) ServerNet S.r.l. +AC06C7 (base 16) ServerNet S.r.l. + Località Padriciano 99 + Trieste Trieste 34149 + IT + +E8-3E-FC (hex) ARRIS Group, Inc. +E83EFC (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +90-0D-CB (hex) ARRIS Group, Inc. +900DCB (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-CD (hex) ARRIS Group, Inc. +001DCD (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-D2 (hex) ARRIS Group, Inc. +001DD2 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +8C-09-F4 (hex) ARRIS Group, Inc. +8C09F4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +88-57-EE (hex) BUFFALO.INC +8857EE (base 16) BUFFALO.INC + AKAMONDORI Bld.,30-20,Ohsu 3-chome,Naka-ku + Nagoya Aichi Pref. 460-8315 + JP + +10-1F-74 (hex) Hewlett Packard +101F74 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +00-9C-02 (hex) Hewlett Packard +009C02 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +F4-CE-46 (hex) Hewlett Packard +F4CE46 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +DC-FB-02 (hex) BUFFALO.INC +DCFB02 (base 16) BUFFALO.INC + AKAMONDORI Bldg.,30-20,Ohsu 3-chome + Naka-ku,Nagoya Aichi Pref 460-8315 + JP + +00-16-35 (hex) Hewlett Packard +001635 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-08-C7 (hex) Hewlett Packard +0008C7 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-10-E3 (hex) Hewlett Packard +0010E3 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-08-83 (hex) Hewlett Packard +000883 (base 16) Hewlett Packard + MAIL STOP 42LE + CUPERTINO CA 95014 + US + +A0-2B-B8 (hex) Hewlett Packard +A02BB8 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +00-19-BB (hex) Hewlett Packard +0019BB (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-1F-29 (hex) Hewlett Packard +001F29 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-21-5A (hex) Hewlett Packard +00215A (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-23-7D (hex) Hewlett Packard +00237D (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +E8-ED-05 (hex) ARRIS Group, Inc. +E8ED05 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +78-96-84 (hex) ARRIS Group, Inc. +789684 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +CC-65-AD (hex) ARRIS Group, Inc. +CC65AD (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-26-55 (hex) Hewlett Packard +002655 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-0D-9D (hex) Hewlett Packard +000D9D (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-15-60 (hex) Hewlett Packard +001560 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-20-7B (hex) Intel Corporation +00207B (base 16) Intel Corporation + 2111 NE 25th Avenue + Hillsboro OR 97124 + US + +00-11-75 (hex) Intel Corporation +001175 (base 16) Intel Corporation + 5200 NE ELAM YOUNG PARKWAY + HIllsboro OR 97124 + US + +78-0C-B8 (hex) Intel Corporate +780CB8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +18-5E-0F (hex) Intel Corporate +185E0F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +2C-81-58 (hex) Hon Hai Precision Ind. Co.,Ltd. +2C8158 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +80-02-DF (hex) ORA Inc. +8002DF (base 16) ORA Inc. + No.1 Anjialou, Xiaoliangmaqiao Ave., Chaoyang Dist. + BeiJing 100125 + CN + +00-30-6E (hex) Hewlett Packard +00306E (base 16) Hewlett Packard + ENTERPRISE SYSTEMS TECH.CENTER + CUPERTINO CA 95014 + US + +3C-4A-92 (hex) Hewlett Packard +3C4A92 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +7C-7D-3D (hex) HUAWEI TECHNOLOGIES CO.,LTD +7C7D3D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan Guangdong 523808 + CN + +44-82-E5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +4482E5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-23-4E (hex) Hon Hai Precision Ind. Co.,Ltd. +00234E (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +2C-23-3A (hex) Hewlett Packard +2C233A (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +00-0A-57 (hex) Hewlett Packard +000A57 (base 16) Hewlett Packard + 10955 Tantau Avenue + Cupertino CA 95014 + US + +00-01-E7 (hex) Hewlett Packard +0001E7 (base 16) Hewlett Packard + 11000 Wolfe Road, Mailstop 42LE + Cupertino CA 95014 + US + +00-01-E6 (hex) Hewlett Packard +0001E6 (base 16) Hewlett Packard + 11000 Wolfe Road, Mailstop 42LE + Cupertino CA 95014 + US + +00-23-76 (hex) HTC Corporation +002376 (base 16) HTC Corporation + No.23 Xinghua Road + Taoyuan County 330 + TW + +38-E7-D8 (hex) HTC Corporation +38E7D8 (base 16) HTC Corporation + No.23 Xinghua Road + Taoyuan County 330 + TW + +18-87-96 (hex) HTC Corporation +188796 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +B4-CE-F6 (hex) HTC Corporation +B4CEF6 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +8C-DC-D4 (hex) Hewlett Packard +8CDCD4 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +D4-C9-EF (hex) Hewlett Packard +D4C9EF (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +FC-15-B4 (hex) Hewlett Packard +FC15B4 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +3C-A8-2A (hex) Hewlett Packard +3CA82A (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +EC-5F-23 (hex) Qinghai Kimascend Electronics Technology Co. Ltd. +EC5F23 (base 16) Qinghai Kimascend Electronics Technology Co. Ltd. + 2F,Building 6,J6 Science&Tech Park, No.6 Jiangjun Rd., Jiangning District + Nanjing Jiangsu 211100 + CN + +04-7D-50 (hex) Shenzhen Kang Ying Technology Co.Ltd. +047D50 (base 16) Shenzhen Kang Ying Technology Co.Ltd. + Units 608,Saiba Electronic tower,NO.6, Langshan 2 Rd., Hi-Tech Industrial Park North , Nanshan, Shenzhen City + Shenzhen Guangdong 518057 + CN + +54-EF-FE (hex) Fullpower Technologies, Inc. +54EFFE (base 16) Fullpower Technologies, Inc. + 1200 Pacific Avenue + Santa Cruz CA 95060 + US + +94-09-37 (hex) HUMAX Co., Ltd. +940937 (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bundang-gu, + Seongnam-si Gyeonggi-do 463-875 + KR + +E8-4D-D0 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E84DD0 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +0C-45-BA (hex) HUAWEI TECHNOLOGIES CO.,LTD +0C45BA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +20-90-6F (hex) Shenzhen Tencent Computer System Co., Ltd. +20906F (base 16) Shenzhen Tencent Computer System Co., Ltd. + 5-10 Building High-tech Zone, Nanshan District, + Shenzhen Guangdong Province 518057 + CN + +6C-E3-B6 (hex) Nera Telecommunications Ltd. +6CE3B6 (base 16) Nera Telecommunications Ltd. + 109 Defu Lane 10 + Singapore Singapore 539225 + SG + +DC-D3-21 (hex) HUMAX Co., Ltd. +DCD321 (base 16) HUMAX Co., Ltd. + HUMAX Village, 11-4, Sunae-dong, Bundang-gu + Seongnam-si Gyeonggi-do 463-825 + KR + +6C-72-E7 (hex) Apple, Inc. +6C72E7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +74-1B-B2 (hex) Apple, Inc. +741BB2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-E8-73 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +6CE873 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park + Shenzhen Guangdong 518057 + CN + +C4-6E-1F (hex) TP-LINK TECHNOLOGIES CO.,LTD. +C46E1F (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +50-FA-84 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +50FA84 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4)  + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +44-B3-2D (hex) TP-LINK TECHNOLOGIES CO.,LTD. +44B32D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4)  + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +CC-44-63 (hex) Apple, Inc. +CC4463 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-25-93 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +882593 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4)  + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +00-1F-E1 (hex) Hon Hai Precision Ind. Co.,Ltd. +001FE1 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +D8-5D-4C (hex) TP-LINK TECHNOLOGIES CO.,LTD. +D85D4C (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 7, Second Part, Honghualing Industrial Zone + Shenzhen Guangdong 518000 + CN + +A0-F3-C1 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +A0F3C1 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan + shenzhen guangdong Province 518057 + CN + +00-1D-0F (hex) TP-LINK TECHNOLOGIES CO.,LTD. +001D0F (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + 3/F, Bldg. R1-B, + Shenzhen Guangdong 518057 + CN + +00-23-CD (hex) TP-LINK TECHNOLOGIES CO.,LTD. +0023CD (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + South Building, No.5 Keyuan Road, Central Zone, + Shenzhen Guangdong 518000 + CN + +90-48-9A (hex) Hon Hai Precision Ind. Co.,Ltd. +90489A (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-71-CC (hex) Hon Hai Precision Ind. Co.,Ltd. +0071CC (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +B0-5B-67 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B05B67 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +CC-A2-23 (hex) HUAWEI TECHNOLOGIES CO.,LTD +CCA223 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +78-6A-89 (hex) HUAWEI TECHNOLOGIES CO.,LTD +786A89 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +38-46-08 (hex) zte corporation +384608 (base 16) zte corporation + 12/F,ZTE R&D Building,Kejinan Road, + Shenzhen Guangdong 518057 + CN + +4C-AC-0A (hex) zte corporation +4CAC0A (base 16) zte corporation + 12/F,ZTE R&D Building,Kejinan Road, + Shenzhen Guangdong 518057 + CN + +B4-B3-62 (hex) zte corporation +B4B362 (base 16) zte corporation + 12/F,ZTE R&D Building,Kejinan Road, + Shenzhen Guangdong 518057 + CN + +B0-75-D5 (hex) zte corporation +B075D5 (base 16) zte corporation + 12/F,ZTE R&D Building,Kejinan Road, + Shenzhen Guangdong 518057 + CN + +D0-15-4A (hex) zte corporation +D0154A (base 16) zte corporation + 12/F.,zte R&D building,kejinan Road, + shenzhen guangdong 518057 + CN + +00-26-ED (hex) zte corporation +0026ED (base 16) zte corporation + 12/F ZTE Plaza,Keji Road South,Hi-Tech Industrial Park,Nanshan District, + Shenzhen GUANGDONG 518057 + CN + +00-60-57 (hex) Murata Manufacturing Co., Ltd. +006057 (base 16) Murata Manufacturing Co., Ltd. + 1-18-1 HAKUSAN MIDORI-KU + YOKOHAMA 226 12345 + JP + +78-3E-53 (hex) BSkyB Ltd +783E53 (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +00-19-FB (hex) BSkyB Ltd +0019FB (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +C4-F5-7C (hex) Brocade Communications Systems, Inc. +C4F57C (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +14-B9-68 (hex) HUAWEI TECHNOLOGIES CO.,LTD +14B968 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +5C-F9-6A (hex) HUAWEI TECHNOLOGIES CO.,LTD +5CF96A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-12-F2 (hex) Brocade Communications Systems, Inc. +0012F2 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-05-1E (hex) Brocade Communications Systems, Inc. +00051E (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +08-3E-8E (hex) Hon Hai Precision Ind. Co.,Ltd. +083E8E (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-22-93 (hex) zte corporation +002293 (base 16) zte corporation + 12/F ZTE Plaza,Keji Road South,Hi-Tech Industrial Park,Nanshan District, + Shenzhen GUANGDONG 518057 + CN + +10-A5-D0 (hex) Murata Manufacturing Co., Ltd. +10A5D0 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1,Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +50-A7-2B (hex) HUAWEI TECHNOLOGIES CO.,LTD +50A72B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +0C-D6-BD (hex) HUAWEI TECHNOLOGIES CO.,LTD +0CD6BD (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-F8-1C (hex) HUAWEI TECHNOLOGIES CO.,LTD +00F81C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +08-7A-4C (hex) HUAWEI TECHNOLOGIES CO.,LTD +087A4C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate + Shenzhen GuangDong 518057 + CN + +AC-E2-15 (hex) HUAWEI TECHNOLOGIES CO.,LTD +ACE215 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, + Shenzhen Guangdong 518057 + CN + +34-6B-D3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +346BD3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, + Shenzhen Guangdong 518057 + CN + +70-72-3C (hex) HUAWEI TECHNOLOGIES CO.,LTD +70723C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, + Shenzhen Guangdong 518057 + CN + +AC-E8-7B (hex) HUAWEI TECHNOLOGIES CO.,LTD +ACE87B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District + Shenzhen Guangdong 518057 + CN + +F8-3D-FF (hex) HUAWEI TECHNOLOGIES CO.,LTD +F83DFF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District + Shenzhen Guangdong 518057 + CN + +28-5F-DB (hex) HUAWEI TECHNOLOGIES CO.,LTD +285FDB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +40-4D-8E (hex) HUAWEI TECHNOLOGIES CO.,LTD +404D8E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +4C-54-99 (hex) HUAWEI TECHNOLOGIES CO.,LTD +4C5499 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +F4-9F-F3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F49FF3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-09-95 (hex) HUAWEI TECHNOLOGIES CO.,LTD +240995 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +84-DB-AC (hex) HUAWEI TECHNOLOGIES CO.,LTD +84DBAC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-77-2B (hex) HUAWEI TECHNOLOGIES CO.,LTD +94772B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D4-40-F0 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D440F0 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +04-02-1F (hex) HUAWEI TECHNOLOGIES CO.,LTD +04021F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +10-CD-AE (hex) Avaya Inc +10CDAE (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +04-8A-15 (hex) Avaya Inc +048A15 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +B4-B0-17 (hex) Avaya Inc +B4B017 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +90-FB-5B (hex) Avaya Inc +90FB5B (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +C8-F4-06 (hex) Avaya Inc +C8F406 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +70-52-C5 (hex) Avaya Inc +7052C5 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +F8-15-47 (hex) Avaya Inc +F81547 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +50-61-84 (hex) Avaya Inc +506184 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +18-59-36 (hex) Xiaomi Communications Co Ltd +185936 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +20-A7-83 (hex) miControl GmbH +20A783 (base 16) miControl GmbH + Blankenfelder Chaussee 1 + Großbeeren Brandenburg 15831 + DE + +20-0B-C7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +200BC7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen Guangdong 518129 + CN + +F8-4A-BF (hex) HUAWEI TECHNOLOGIES CO.,LTD +F84ABF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen Guangdong 518129 + CN + +78-D7-52 (hex) HUAWEI TECHNOLOGIES CO.,LTD +78D752 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +10-47-80 (hex) HUAWEI TECHNOLOGIES CO.,LTD +104780 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +54-89-98 (hex) HUAWEI TECHNOLOGIES CO.,LTD +548998 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +00-04-0D (hex) Avaya Inc +00040D (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +70-A8-E3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +70A8E3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen 518129 + CN + +F8-E8-11 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F8E811 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen Guangdong 518129 + CN + +F8-A4-5F (hex) Xiaomi Communications Co Ltd +F8A45F (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +64-09-80 (hex) Xiaomi Communications Co Ltd +640980 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +94-04-9C (hex) HUAWEI TECHNOLOGIES CO.,LTD +94049C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base + Shenzhen Guangdong 518129 + CN + +68-8F-84 (hex) HUAWEI TECHNOLOGIES CO.,LTD +688F84 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base + SHENZHEN GUANGDONG 518129 + CN + +30-D1-7E (hex) HUAWEI TECHNOLOGIES CO.,LTD +30D17E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +00-50-BD (hex) Cisco Systems, Inc +0050BD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-90-6F (hex) Cisco Systems, Inc +00906F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +74-D6-EA (hex) Texas Instruments +74D6EA (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +20-91-48 (hex) Texas Instruments +209148 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +54-4A-16 (hex) Texas Instruments +544A16 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +E0-2F-6D (hex) Cisco Systems, Inc +E02F6D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +58-97-1E (hex) Cisco Systems, Inc +58971E (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +B4-E9-B0 (hex) Cisco Systems, Inc +B4E9B0 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-08-32 (hex) Cisco Systems, Inc +000832 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +18-9C-5D (hex) Cisco Systems, Inc +189C5D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +5C-A4-8A (hex) Cisco Systems, Inc +5CA48A (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +1C-1D-86 (hex) Cisco Systems, Inc +1C1D86 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +60-73-5C (hex) Cisco Systems, Inc +60735C (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +34-A8-4E (hex) Cisco Systems, Inc +34A84E (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +54-78-1A (hex) Cisco Systems, Inc +54781A (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-60-5C (hex) Cisco Systems, Inc +00605C (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-06-C1 (hex) Cisco Systems, Inc +0006C1 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-E0-14 (hex) Cisco Systems, Inc +00E014 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +DC-A5-F4 (hex) Cisco Systems, Inc +DCA5F4 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +50-17-FF (hex) Cisco Systems, Inc +5017FF (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +70-10-5C (hex) Cisco Systems, Inc +70105C (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +10-F3-11 (hex) Cisco Systems, Inc +10F311 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-50-F0 (hex) Cisco Systems, Inc +0050F0 (base 16) Cisco Systems, Inc + 170 W. TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-50-14 (hex) Cisco Systems, Inc +005014 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-90-F2 (hex) Cisco Systems, Inc +0090F2 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +0C-E0-E4 (hex) PLANTRONICS, INC. +0CE0E4 (base 16) PLANTRONICS, INC. + 345 ENCINAL STREET + SANTA CRUZ CA 95060 + US + +74-A2-E6 (hex) Cisco Systems, Inc +74A2E6 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +BC-F1-F2 (hex) Cisco Systems, Inc +BCF1F2 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +C8-00-84 (hex) Cisco Systems, Inc +C80084 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +40-A6-E8 (hex) Cisco Systems, Inc +40A6E8 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +30-85-A9 (hex) ASUSTek COMPUTER INC. +3085A9 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou + Taipei 112 + US + +B8-38-61 (hex) Cisco Systems, Inc +B83861 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +58-0A-20 (hex) Cisco Systems, Inc +580A20 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +2C-3E-CF (hex) Cisco Systems, Inc +2C3ECF (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +B0-59-47 (hex) Shenzhen Qihu Intelligent Technology Company Limited +B05947 (base 16) Shenzhen Qihu Intelligent Technology Company Limited + Room 201, Block A, No.1, Qianwan Road 1,Qianhai Shenzhen HongKong Modern Service Industry Cooperation Zone + Shenzhen Guangdong 518057 + CN + +34-62-88 (hex) Cisco Systems, Inc +346288 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +CC-D8-C1 (hex) Cisco Systems, Inc +CCD8C1 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +7C-0E-CE (hex) Cisco Systems, Inc +7C0ECE (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +A0-EC-F9 (hex) Cisco Systems, Inc +A0ECF9 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +50-87-89 (hex) Cisco Systems, Inc +508789 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +38-1C-1A (hex) Cisco Systems, Inc +381C1A (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +BC-67-1C (hex) Cisco Systems, Inc +BC671C (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-19-47 (hex) Cisco SPVTG +001947 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +00-18-39 (hex) Cisco-Linksys, LLC +001839 (base 16) Cisco-Linksys, LLC + 121 Theory Dr. + Irvine CA 92612 + US + +00-22-15 (hex) ASUSTek COMPUTER INC. +002215 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou, + Taipei 112 + TW + +E0-CB-4E (hex) ASUSTek COMPUTER INC. +E0CB4E (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou,Taipei 112 ,Taiwan + Taipei Taiwan 112 + TW + +54-7C-69 (hex) Cisco Systems, Inc +547C69 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-17-31 (hex) ASUSTek COMPUTER INC. +001731 (base 16) ASUSTek COMPUTER INC. + No.5 Shing Yeh Street,Kwei Shan Hsiang,Taoyuan + Taipei 333 + TW + +DC-CE-C1 (hex) Cisco Systems, Inc +DCCEC1 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +9C-57-AD (hex) Cisco Systems, Inc +9C57AD (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +60-FE-C5 (hex) Apple, Inc. +60FEC5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-25-E7 (hex) Apple, Inc. +E425E7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-92-6B (hex) Apple, Inc. +BC926B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +10-1C-0C (hex) Apple, Inc. +101C0C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +08-00-07 (hex) Apple, Inc. +080007 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-40-96 (hex) Cisco Systems, Inc +004096 (base 16) Cisco Systems, Inc + 170 W. Tasman Drive + San Jose CA 95134 + US + +30-F7-0D (hex) Cisco Systems, Inc +30F70D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +E8-65-49 (hex) Cisco Systems, Inc +E86549 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +B0-7D-47 (hex) Cisco Systems, Inc +B07D47 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +38-ED-18 (hex) Cisco Systems, Inc +38ED18 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +38-20-56 (hex) Cisco Systems, Inc +382056 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +40-D3-2D (hex) Apple, Inc. +40D32D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C4-2C-03 (hex) Apple, Inc. +C42C03 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-27-E4 (hex) Apple, Inc. +9027E4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +10-9A-DD (hex) Apple, Inc. +109ADD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +58-1F-AA (hex) Apple, Inc. +581FAA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-C6-63 (hex) Apple, Inc. +88C663 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-1F-5B (hex) Apple, Inc. +001F5B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-24-36 (hex) Apple, Inc. +002436 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-25-4B (hex) Apple, Inc. +00254B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-16-CB (hex) Apple, Inc. +0016CB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-17-F2 (hex) Apple, Inc. +0017F2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +7C-6D-62 (hex) Apple, Inc. +7C6D62 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-C9-D0 (hex) Apple, Inc. +20C9D0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-96-7B (hex) Apple, Inc. +68967B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-FC-FE (hex) Apple, Inc. +84FCFE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-8B-7F (hex) Apple, Inc. +E48B7F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-88-65 (hex) Apple, Inc. +008865 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-3B-AF (hex) Apple, Inc. +BC3BAF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-E0-72 (hex) Apple, Inc. +3CE072 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-48-4C (hex) Apple, Inc. +38484C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A4-67-06 (hex) Apple, Inc. +A46706 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +8C-58-77 (hex) Apple, Inc. +8C5877 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +7C-F0-5F (hex) Apple, Inc. +7CF05F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +80-49-71 (hex) Apple, Inc. +804971 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-3E-6D (hex) Apple, Inc. +6C3E6D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-67-78 (hex) Apple, Inc. +BC6778 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D8-D1-CB (hex) Apple, Inc. +D8D1CB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-FA-D8 (hex) Apple, Inc. +A8FAD8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B8-17-C2 (hex) Apple, Inc. +B817C2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +7C-11-BE (hex) Apple, Inc. +7C11BE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-37-37 (hex) Apple, Inc. +283737 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +50-EA-D6 (hex) Apple, Inc. +50EAD6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-D6-BB (hex) Apple, Inc. +98D6BB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-9E-FC (hex) Apple, Inc. +189EFC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-CF-5C (hex) Apple, Inc. +ACCF5C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +80-00-6E (hex) Apple, Inc. +80006E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-8E-0C (hex) Apple, Inc. +848E0C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-15-C2 (hex) Apple, Inc. +3C15C2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-70-9F (hex) Apple, Inc. +6C709F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-F2-FB (hex) Apple, Inc. +C0F2FB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +24-E3-14 (hex) Apple, Inc. +24E314 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +80-E6-50 (hex) Apple, Inc. +80E650 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-FD-61 (hex) Apple, Inc. +90FD61 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +08-70-45 (hex) Apple, Inc. +087045 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-88-08 (hex) Apple, Inc. +A88808 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A4-C3-61 (hex) Apple, Inc. +A4C361 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-F0-EE (hex) Apple, Inc. +2CF0EE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-97-F3 (hex) Apple, Inc. +5C97F3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D4-F4-6F (hex) Apple, Inc. +D4F46F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-76-BA (hex) Apple, Inc. +6476BA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-E2-FD (hex) Apple, Inc. +34E2FD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-48-9A (hex) Apple, Inc. +04489A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-F6-1C (hex) Apple, Inc. +F0F61C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +8C-29-37 (hex) Apple, Inc. +8C2937 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B0-9F-BA (hex) Apple, Inc. +B09FBA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +0C-4D-E9 (hex) Apple, Inc. +0C4DE9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-F5-C6 (hex) Apple, Inc. +E0F5C6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-ED-CD (hex) Apple, Inc. +A0EDCD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-F2-49 (hex) Hitron Technologies. Inc +F0F249 (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +28-57-BE (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +2857BE (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.469,Jianghui Road + Hangzhou Zhejiang 310052 + CN + +5C-F5-DA (hex) Apple, Inc. +5CF5DA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-EE-69 (hex) Apple, Inc. +18EE69 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-9A-BE (hex) Apple, Inc. +649ABE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-99-BF (hex) Apple, Inc. +F099BF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +94-E9-6A (hex) Apple, Inc. +94E96A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-29-3A (hex) Apple, Inc. +AC293A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-FC-01 (hex) Apple, Inc. +9CFC01 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-35-EB (hex) Apple, Inc. +9C35EB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-43-7C (hex) Apple, Inc. +48437C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-A3-95 (hex) Apple, Inc. +34A395 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-7E-61 (hex) Apple, Inc. +787E61 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-F8-1D (hex) Apple, Inc. +60F81D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-C9-86 (hex) Apple, Inc. +38C986 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-33-11 (hex) Apple, Inc. +D03311 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +50-7A-55 (hex) Apple, Inc. +507A55 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-C2-C6 (hex) Shanghai Airm2m Communication Technology Co., Ltd +C8C2C6 (base 16) Shanghai Airm2m Communication Technology Co., Ltd + Rm.816,Building C,No.668,East Beijing Road,Huangpu District,Shanghai,China + Shang hai Shang hai 200001 + CN + +78-9C-85 (hex) August Home, Inc. +789C85 (base 16) August Home, Inc. + 657 Bryant Street + San Francisco California 94107 + US + +74-D7-CA (hex) Panasonic Corporation Automotive +74D7CA (base 16) Panasonic Corporation Automotive + 5652 + Matsumoto City Nagano 399-8730 + JP + +58-82-A8 (hex) Microsoft +5882A8 (base 16) Microsoft + 1 Microsoft Way + Redmond Washington 98052 + US + +58-68-5D (hex) Tempo Australia Pty Ltd +58685D (base 16) Tempo Australia Pty Ltd + 8/14 Rodborough Rd + Frenchs Forest NSW 2086 + AU + +54-4B-8C (hex) Juniper Networks +544B8C (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +DC-FE-07 (hex) PEGATRON CORPORATION +DCFE07 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +70-79-38 (hex) Wuxi Zhanrui Electronic Technology Co.,LTD +707938 (base 16) Wuxi Zhanrui Electronic Technology Co.,LTD + Wuxi,Taihu West Road No.1188 Runhua International Building 1604 + Wuxi Jiangsu 214072 + CN + +24-31-84 (hex) SHARP Corporation +243184 (base 16) SHARP Corporation + 22-22,Nagaike-Cho + Osaka-City Osaka-Prefecture 545-8522 + JP + +58-2B-DB (hex) Pax AB +582BDB (base 16) Pax AB + Box 72 + Hälleforsnäs 64806 + SE + +E0-36-76 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E03676 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +EC-38-8F (hex) HUAWEI TECHNOLOGIES CO.,LTD +EC388F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D0-3E-5C (hex) HUAWEI TECHNOLOGIES CO.,LTD +D03E5C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-9E-41 (hex) G24 Power Limited +C49E41 (base 16) G24 Power Limited + South Lake Drive + Newport Gwent NP10 8AS + GB + +B8-13-E9 (hex) Trace Live Network +B813E9 (base 16) Trace Live Network + #200, 5970 Centre St SE + Calgary Alberta T2H0C1 + CA + +80-B7-09 (hex) Viptela, Inc +80B709 (base 16) Viptela, Inc + 1740 Technology Drive, Ste#500 + San Jose California 95110 + US + +F0-0D-5C (hex) JinQianMao Technology Co.,Ltd. +F00D5C (base 16) JinQianMao Technology Co.,Ltd. + 58#,Jiangbin Road,Taijiang District + Fuzhou Fujian 350009 + CN + +54-BE-53 (hex) zte corporation +54BE53 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +28-0E-8B (hex) Beijing Spirit Technology Development Co., Ltd. +280E8B (base 16) Beijing Spirit Technology Development Co., Ltd. + No. 26 Ave. 4 Chuangye Middle Road + Beijing 100085 + CN + +F4-4D-30 (hex) Elitegroup Computer Systems Co.,Ltd. +F44D30 (base 16) Elitegroup Computer Systems Co.,Ltd. + No.239,Sec.2,Ti Ding Blvd., + Taipei Taipei + TW + +0C-86-10 (hex) Juniper Networks +0C8610 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +38-D4-0B (hex) Samsung Electronics Co.,Ltd +38D40B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E8-3A-12 (hex) Samsung Electronics Co.,Ltd +E83A12 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +24-DA-9B (hex) Motorola Mobility LLC, a Lenovo Company +24DA9B (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +30-E0-90 (hex) Linctronix Ltd, +30E090 (base 16) Linctronix Ltd, + ​9F-1, No.66, Chongqing Rd., + Banqiao Dist., China 22063 + TW + +A4-DC-BE (hex) HUAWEI TECHNOLOGIES CO.,LTD +A4DCBE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +EC-B8-70 (hex) Beijing Heweinet Technology Co.,Ltd. +ECB870 (base 16) Beijing Heweinet Technology Co.,Ltd. + 1514 Room,15F,No.2 Building + Haidian District Beijing 100085 + CN + +94-BB-AE (hex) Husqvarna AB +94BBAE (base 16) Husqvarna AB + Drottninggatan 2 + Huskvarna Sweden 56131 + SE + +D4-0A-A9 (hex) ARRIS Group, Inc. +D40AA9 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +20-3D-66 (hex) ARRIS Group, Inc. +203D66 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D4-94-E8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D494E8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B0-78-F0 (hex) Beijing HuaqinWorld Technology Co.,Ltd. +B078F0 (base 16) Beijing HuaqinWorld Technology Co.,Ltd. + Beijing City, Chaoyang District Wangjing Garden Department Youle A District No. 3 building 308 room + Bejjing Bejjing 100102 + CN + +20-9B-CD (hex) Apple, Inc. +209BCD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +30-95-E3 (hex) SHANGHAI SIMCOM LIMITED +3095E3 (base 16) SHANGHAI SIMCOM LIMITED + Building A,SIM Technology Building,No.633, Jinzhong Road,Changning District , Shanghai, P.R.China + Shanghai / 200355 + CN + +80-65-6D (hex) Samsung Electronics Co.,Ltd +80656D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-F1-36 (hex) Samsung Electronics Co.,Ltd +FCF136 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +B8-86-87 (hex) Liteon Technology Corporation +B88687 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +18-89-5B (hex) Samsung Electronics Co.,Ltd +18895B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +58-49-25 (hex) E3 Enterprise +584925 (base 16) E3 Enterprise + 32F, Shinjuku Nomura Building + Tokyo 163-0532 + JP + +94-F2-78 (hex) Elma Electronic +94F278 (base 16) Elma Electronic + 44350 S. Grimmer Blvd + Fremont CA 94538 + US + +28-37-13 (hex) Shenzhen 3Nod Digital Technology Co., Ltd. +283713 (base 16) Shenzhen 3Nod Digital Technology Co., Ltd. + Building D, No.8 Langhui Road, Tangxiayong Community, Songgang Street, Baoan District, Shenzhen City, Guangdong Province, P.R. China + Shenzhen Guangdong 518105 + CN + +08-94-EF (hex) Wistron Infocomm (Zhongshan) Corporation +0894EF (base 16) Wistron Infocomm (Zhongshan) Corporation + No.38,East Keji Road,Zhongshan Torch Development Zone,Zhongshan City,Guangdong,China + Zhongshan Guangdong 528437 + CN + +E0-31-9E (hex) Valve Corporation +E0319E (base 16) Valve Corporation + 10900 NE 4th ST + Bellevue Washington 98004 + US + +3C-5C-C3 (hex) Shenzhen First Blue Chip Technology Ltd +3C5CC3 (base 16) Shenzhen First Blue Chip Technology Ltd + 3Nod Smart Building,11Floor,No.3012,Binhai Avenue, Nanshan District + Shenzhen Guangdong 518000 + CN + +C4-9F-F3 (hex) Mciao Technologies, Inc. +C49FF3 (base 16) Mciao Technologies, Inc. + Room304, Building 1, No.288 Qiuyi Rd., Binjiang District + Hangzhou Zhejiang 310052 + CN + +78-8E-33 (hex) Jiangsu SEUIC Technology Co.,Ltd +788E33 (base 16) Jiangsu SEUIC Technology Co.,Ltd + NO23.Wenzhu Road.Yuhuatai Distrct. + Nanjing Jiangsu Province 210012 + CN + +EC-EE-D8 (hex) ZTLX Network Technology Co.,Ltd +ECEED8 (base 16) ZTLX Network Technology Co.,Ltd + Unit 703,No 77,CuShaHuan + ZhuHai GuangDong 519000 + CN + +80-EB-77 (hex) Wistron Corporation +80EB77 (base 16) Wistron Corporation + No. 158, SingShan Rd., Neihu, Taipei 11469, Taiwan, R.O.C. + Neihu Taipei 11469 + + +48-39-74 (hex) Proware Technologies Co., Ltd. +483974 (base 16) Proware Technologies Co., Ltd. + 2nd F1 East Wing,South Section,Factory Building 24,Science&Technology Park, Shennan Rd, Nanshan District + Shenzhen Guangdong 518057 + CN + +30-FF-F6 (hex) HangZhou KuoHeng Technology Co.,ltd +30FFF6 (base 16) HangZhou KuoHeng Technology Co.,ltd + No.368,Wangjiali,Chang'ancun Industrial Park,Wenyan Town, Xiaoshan District, Hangzhou, CHina + HangZhou ZheJiang 311258 + CN + +D8-EF-CD (hex) Nokia +D8EFCD (base 16) Nokia + Karaportti 3 + Espoo Finland 02610 + FI + +4C-C6-81 (hex) Shenzhen Aisat Electronic Co., Ltd. +4CC681 (base 16) Shenzhen Aisat Electronic Co., Ltd. + Golden Building 419#, Design Park, + Shenzhen Guangdong 518056 + CN + +48-E2-44 (hex) Hon Hai Precision Ind. Co.,Ltd. +48E244 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +7C-AB-25 (hex) MESMO TECHNOLOGY INC. +7CAB25 (base 16) MESMO TECHNOLOGY INC. + 3F., No.181, ZHOUZI ST., NEIHU DIST., + TAIPEI TAIPEI 11493 + TW + +B0-41-1D (hex) ITTIM Technologies +B0411D (base 16) ITTIM Technologies + B1606, No.6, Zhongguancun South Street, + Beijing Beijing 100086 + CN + +F8-BF-09 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F8BF09 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-B2-5C (hex) Acacia Communications +7CB25C (base 16) Acacia Communications + 3 Clock Tower Place + Maynard MA 01754 + US + +DC-DB-70 (hex) Tonfunk Systementwicklung und Service GmbH +DCDB70 (base 16) Tonfunk Systementwicklung und Service GmbH + Anger20 + Falkenstein / Harz OT Ermsleben Sachsen-Anhalt 06463 + DE + +80-0B-51 (hex) Chengdu XGimi Technology Co.,Ltd +800B51 (base 16) Chengdu XGimi Technology Co.,Ltd + 5F Building A7,Tianfu Software Park,Tianfu + Chengdu Sichuan 610041 + CN + +F8-0D-60 (hex) CANON INC. +F80D60 (base 16) CANON INC. + 30-2 Shimomaruko 3-chome, + Ohta-ku Tokyo 146-8501 + JP + +F0-18-2B (hex) LG Chem +F0182B (base 16) LG Chem + 128, Yeoui-daero, Yeongdeungpo-gu, + Seoul Seoul 150-721 + KR + +34-81-F4 (hex) SST Taiwan Ltd. +3481F4 (base 16) SST Taiwan Ltd. + 5F, No. 5, Industry E Rd. VII, + Hsin Chu, Taiwan 30077 + TW + +7C-A2-37 (hex) King Slide Technology CO., LTD. +7CA237 (base 16) King Slide Technology CO., LTD. + No. 6, Luke 9th Rd., + Kaohsiung Taiwan 82151 + TW + +D4-04-CD (hex) ARRIS Group, Inc. +D404CD (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +58-48-22 (hex) Sony Mobile Communications Inc +584822 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +74-73-36 (hex) MICRODIGTAL Inc +747336 (base 16) MICRODIGTAL Inc + 10F, Ace High-End Tower 9th, + Seoul 153-803 + KR + +38-2B-78 (hex) ECO PLUGS ENTERPRISE CO., LTD +382B78 (base 16) ECO PLUGS ENTERPRISE CO., LTD + 10F,-6, No.117, Sec.2, Zhongbei Rd., Zhongli Dist., + Taoyuan Taiwan 32097 + TW + +A4-7B-2C (hex) Nokia +A47B2C (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +24-E5-AA (hex) Philips Oral Healthcare, Inc. +24E5AA (base 16) Philips Oral Healthcare, Inc. + 22100 Bothell Everett Hwy + Bothell WA 98021 + US + +78-BD-BC (hex) Samsung Electronics Co.,Ltd +78BDBC (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +34-9B-5B (hex) Maquet GmbH +349B5B (base 16) Maquet GmbH + Kehler Strasse 31 + Rastatt Baden-Württemberg 76437 + DE + +88-41-57 (hex) Shenzhen Atsmart Technology Co.,Ltd. +884157 (base 16) Shenzhen Atsmart Technology Co.,Ltd. + East 3F ,2 Building, Meijing Industry Park, Qiaoxiang Road, Nanshan District + Shenzhen Guangdong 518000 + CN + +D8-9A-34 (hex) Beijing SHENQI Technology Co., Ltd. +D89A34 (base 16) Beijing SHENQI Technology Co., Ltd. + No.6 Shang Di West Road + Haidian District Beijing 100085 + CN + +A0-A6-5C (hex) Supercomputing Systems AG +A0A65C (base 16) Supercomputing Systems AG + Technoparkstrasse 1 + Zurich ZH 8005 + CH + +48-50-73 (hex) Microsoft Corporation +485073 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +E8-37-7A (hex) Zyxel Communications Corporation +E8377A (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +80-3B-2A (hex) ABB Xiamen Low Voltage Equipment Co.,Ltd. +803B2A (base 16) ABB Xiamen Low Voltage Equipment Co.,Ltd. + No.12-20,3rd Chuang Xin Road + Xiamen SEZ Fujian 361006 + CN + +C4-EA-1D (hex) Technicolor +C4EA1D (base 16) Technicolor + Prins Boudewijnlaan 47 + Edegem - Belgium B-2650 + BE + +7C-F9-0E (hex) Samsung Electronics Co.,Ltd +7CF90E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +50-F0-D3 (hex) Samsung Electronics Co.,Ltd +50F0D3 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-A7-84 (hex) ITX security +00A784 (base 16) ITX security + 9F Kolon Digital Tower Aston Bldg + SEOUL (Outside US/Canada/China) 441-813 + KR + +84-11-9E (hex) Samsung Electronics Co.,Ltd +84119E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-9A-10 (hex) Microsoft Corporation +149A10 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +38-FA-CA (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +38FACA (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +5C-B4-3E (hex) HUAWEI TECHNOLOGIES CO.,LTD +5CB43E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +70-77-81 (hex) Hon Hai Precision Ind. Co.,Ltd. +707781 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +54-E1-40 (hex) INGENICO +54E140 (base 16) INGENICO + 9 AVENUE DE LA GARE + VALENCE DROME 26958 + FR + +E4-90-7E (hex) Motorola Mobility LLC, a Lenovo Company +E4907E (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +74-6A-3A (hex) Aperi Corporation +746A3A (base 16) Aperi Corporation + 360 Mobil Avenue + Camarillo CA 93010 + US + +94-A7-B7 (hex) zte corporation +94A7B7 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +18-44-E6 (hex) zte corporation +1844E6 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +3C-CE-15 (hex) Mercedes-Benz USA, LLC +3CCE15 (base 16) Mercedes-Benz USA, LLC + One Mercedes Drive + Montvale NJ 07645 + US + +28-76-10 (hex) IgniteNet +287610 (base 16) IgniteNet + 1, Creation 3rd Rd. + Hsinchu 300 + TW + +20-D7-5A (hex) Posh Mobile Limited +20D75A (base 16) Posh Mobile Limited + 1011A 10/F Harbour Centre Tower 1, 1 Hok Cheung Street + HungHom Kowloon 00000 + HK + +F4-15-63 (hex) F5 Networks, Inc. +F41563 (base 16) F5 Networks, Inc. + 1322 North Whitman Lane + Liberty Lake WA 99019 + US + +8C-8B-83 (hex) Texas Instruments +8C8B83 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +40-11-DC (hex) Sonance +4011DC (base 16) Sonance + 212 Avenida Fabricante + San Clemente California 92672 + US + +1C-83-41 (hex) Hefei Bitland Information Technology Co.Ltd +1C8341 (base 16) Hefei Bitland Information Technology Co.Ltd + C1# Building, Bitland Industrial Park, No#4088, Jinxiu RD,Economic Development Zone, Hefei, Anhui, China + Hefei Anhui 230061 + CN + +08-1F-EB (hex) BinCube +081FEB (base 16) BinCube + Si Ming Shan Road 116, Beilun + Ningbo Zhejiang 315800 + CN + +78-5F-4C (hex) Argox Information Co., Ltd. +785F4C (base 16) Argox Information Co., Ltd. + 7F, No.126, Lane 235, Baoqiao Rd., Xindian Dist. + New Taipei City Taipei 231 + TW + +34-CC-28 (hex) Nexpring Co. LTD., +34CC28 (base 16) Nexpring Co. LTD., + 3rd Floor, Building C, PDC Tower + Sungnam City Kyungki-do 463400 + KR + +54-E2-C8 (hex) Dongguan Aoyuan Electronics Technology Co., Ltd +54E2C8 (base 16) Dongguan Aoyuan Electronics Technology Co., Ltd + Factory A7 Zhen'an Sci-Tech Industrial Park, Chang'an Town, Dongguan City, Guangdong Province, China + Dongguan City Guangdong Province 523863 + CN + +6C-1E-70 (hex) Guangzhou YBDS IT Co.,Ltd +6C1E70 (base 16) Guangzhou YBDS IT Co.,Ltd + Room 318,3/F,970 Kang Wang Bei Lu,Liwan District,Guangzhou,PRC + Guangzhou City Guangdong Province 510170 + CN + +54-B8-0A (hex) D-Link International +54B80A (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +D8-AD-DD (hex) Sonavation, Inc. +D8ADDD (base 16) Sonavation, Inc. + 3970 RCA Blvd. + Palm Beach Gardens Florida 33410 + US + +88-33-BE (hex) Ivenix, Inc. +8833BE (base 16) Ivenix, Inc. + 21 Water Street + Amesbury MA 01913 + US + +E4-8D-8C (hex) Routerboard.com +E48D8C (base 16) Routerboard.com + Mikrotikls SIA + Riga Riga LV1009 + LV + +70-68-79 (hex) Saijo Denki International Co., Ltd. +706879 (base 16) Saijo Denki International Co., Ltd. + 39/9 Moo 9 Soi Duangmanee + Muang Nonthaburi 11000 + TH + +10-AF-78 (hex) Shenzhen ATUE Technology Co., Ltd +10AF78 (base 16) Shenzhen ATUE Technology Co., Ltd + 3/F,Building 2nd, Xintang Industry Zone,Fuyong Town,Bao'an District + Shenzhen Guangdong 518103 + CN + +CC-19-A8 (hex) PT Inovação e Sistemas SA +CC19A8 (base 16) PT Inovação e Sistemas SA + Rua Eng. José Ferreira Pinto Basto + Aveiro Aveiro 3810-106 + PT + +B4-B2-65 (hex) DAEHO I&T +B4B265 (base 16) DAEHO I&T + 211, Jayumuyeok 3-gil, MasanHoewon-gu + Changwon-si Gyeongsangnam-do 630-812 + KR + +E0-35-60 (hex) Challenger Supply Holdings, LLC +E03560 (base 16) Challenger Supply Holdings, LLC + 4500 Mercantile Plaza Dr. + Fort Worth TX 76137 + US + +3C-CB-7C (hex) TCT mobile ltd +3CCB7C (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +24-9E-AB (hex) HUAWEI TECHNOLOGIES CO.,LTD +249EAB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-4B-03 (hex) Samsung Electronics Co.,Ltd +244B03 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +E4-CE-70 (hex) Health & Life co., Ltd. +E4CE70 (base 16) Health & Life co., Ltd. + 9F, No. 186, Jian Yi Road + New Taipei City Taiwan 23553 + TW + +7C-11-CD (hex) QianTang Technology +7C11CD (base 16) QianTang Technology + 36 Landmark Palace + Beijing Beijing 100125 + + +CC-A4-AF (hex) Shenzhen Sowell Technology Co., LTD +CCA4AF (base 16) Shenzhen Sowell Technology Co., LTD + 7F, Yizhe Building. Yuquan Road. + Shen Zhen Guang Dong 518052 + CN + +10-2C-83 (hex) XIMEA +102C83 (base 16) XIMEA + Lesna 52 + Marianka SK 90033 + SK + +6C-A7-5F (hex) zte corporation +6CA75F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +8C-79-67 (hex) zte corporation +8C7967 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +78-58-F3 (hex) Vachen Co.,Ltd +7858F3 (base 16) Vachen Co.,Ltd + Rm1206, Hanyang Bldg, 18, Gukhoe-daero 70-gil, Yeongdeungpo-gu + Seoul Seoul 150-748 + KR + +70-9C-8F (hex) Nero AG +709C8F (base 16) Nero AG + Rueppurrer Str. 1A + Karlsruhe BW 76137 + DE + +00-7E-56 (hex) China Dragon Technology Limited +007E56 (base 16) China Dragon Technology Limited + B4 Bldg.Haoshan 1st Industry Park, + Shenzhen Guangdong 518104 + CN + +74-E2-8C (hex) Microsoft Corporation +74E28C (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +00-71-C2 (hex) PEGATRON CORPORATION +0071C2 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +7C-82-74 (hex) Shenzhen Hikeen Technology CO.,LTD +7C8274 (base 16) Shenzhen Hikeen Technology CO.,LTD + 15rd floor,unit1,Building A of Kexing Science Park + Shenzhen GuangDong 518057 + CN + +94-D4-17 (hex) GPI KOREA INC. +94D417 (base 16) GPI KOREA INC. + Daebang Triplaon B-Dong 201 + Goyang-Si Kyeonggi-Do 410-704 + KR + +24-4B-81 (hex) Samsung Electronics Co.,Ltd +244B81 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +70-4E-66 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +704E66 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +D8-55-A3 (hex) zte corporation +D855A3 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +38-D8-2F (hex) zte corporation +38D82F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +F0-79-59 (hex) ASUSTek COMPUTER INC. +F07959 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +E0-8E-3C (hex) Aztech Electronics Pte Ltd +E08E3C (base 16) Aztech Electronics Pte Ltd + 31, Ubi Road 1 + Singapore Singapore 408694 + SG + +84-4B-B7 (hex) Beijing Sankuai Online Technology Co.,Ltd +844BB7 (base 16) Beijing Sankuai Online Technology Co.,Ltd + Block F&G, Wangjing International R & D Park, + Chaoyang District BEIJING 100102 + CN + +68-F0-BC (hex) Shenzhen LiWiFi Technology Co., Ltd +68F0BC (base 16) Shenzhen LiWiFi Technology Co., Ltd + No.7, Xinxi Road, Hi-Tech Park (North Zone) + Shenzhen Guangdong 518057 + CN + +30-0E-E3 (hex) Aquantia Corporation +300EE3 (base 16) Aquantia Corporation + 700 Tasman Drive + Milpitas CA 95035 + US + +18-F1-45 (hex) NetComm Wireless Limited +18F145 (base 16) NetComm Wireless Limited + Level 2, 18-20 Orion Road + Lane Cove Sydney 2066 + AU + +AC-AB-BF (hex) AthenTek Inc. +ACABBF (base 16) AthenTek Inc. + 8F., No.356, Sec. 1, Neihu Rd., Neihu Dist., + Taipei City Taiwan 114 + TW + +28-84-FA (hex) SHARP Corporation +2884FA (base 16) SHARP Corporation + 1 Takumi-cho, Sakai-ku + Sakai City Osaka 590-8522 + JP + +60-AF-6D (hex) Samsung Electronics Co.,Ltd +60AF6D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B8-5A-73 (hex) Samsung Electronics Co.,Ltd +B85A73 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +3C-1E-04 (hex) D-Link International +3C1E04 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +60-D9-A0 (hex) Lenovo Mobile Communication Technology Ltd. +60D9A0 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999, Qishan North 2nd Road, Information & Optoelectronics Park, + Xiamen Fujian 361006 + + +68-B9-83 (hex) b-plus GmbH +68B983 (base 16) b-plus GmbH + Ulrichsberger Str. 17 + Deggendorf Bavaria 94469 + DE + +78-B3-B9 (hex) ShangHai sunup lighting CO.,LTD +78B3B9 (base 16) ShangHai sunup lighting CO.,LTD + RM2508,Building 2,1077# Zu Chong Zhi Rd,Zhang Jiang Hi-Tech Park,Pudong New Area,ShangHai,China + shanghai shanghai 201203 + CN + +04-C0-9C (hex) Tellabs Inc. +04C09C (base 16) Tellabs Inc. + 1415 W. Diehl Road + Naperville Illinois 60563 + US + +98-1D-FA (hex) Samsung Electronics Co.,Ltd +981DFA (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +18-68-82 (hex) Beward R&D Co., Ltd. +186882 (base 16) Beward R&D Co., Ltd. + Molokova street 16, apt.355 + Krasnoyarsk Krasnoyarsk region 660118 + RU + +EC-80-09 (hex) NovaSparks +EC8009 (base 16) NovaSparks + 12 rue de Chatillon + Paris Ile de France 75014 + FR + +50-AD-D5 (hex) Dynalec Corporation +50ADD5 (base 16) Dynalec Corporation + 87 West Main Street + Sodus NY 14551 + US + +B0-45-19 (hex) TCT mobile ltd +B04519 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +D8-8D-5C (hex) Elentec +D88D5C (base 16) Elentec + Dongtangiheung-ro 64-3 + Gyeonggi-do Hwaseong-si/Dongtan-myeon 445-812 + KR + +74-29-AF (hex) Hon Hai Precision Ind. Co.,Ltd. +7429AF (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +3C-1A-0F (hex) ClearSky Data +3C1A0F (base 16) ClearSky Data + 99 Summer Street + Boston MA 02110 + US + +E8-CC-18 (hex) D-Link International +E8CC18 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +B0-91-37 (hex) ISis ImageStream Internet Solutions, Inc +B09137 (base 16) ISis ImageStream Internet Solutions, Inc + 4374 FM 1518 + Selma TX 78154 + US + +8C-05-51 (hex) Koubachi AG +8C0551 (base 16) Koubachi AG + Technoparkstrasse 1 + Zurich Zurich 8005 + CH + +D8-97-BA (hex) PEGATRON CORPORATION +D897BA (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +A8-D8-8A (hex) Wyconn +A8D88A (base 16) Wyconn + Rennweg 97-99 + Vienna 1030 + AT + +40-EA-CE (hex) FOUNDER BROADBAND NETWORK SERVICE CO.,LTD +40EACE (base 16) FOUNDER BROADBAND NETWORK SERVICE CO.,LTD + 5F,Tower B,Beifa Plaza,No.16 Building + Haisdian District Beijing 100088 + CN + +84-8E-DF (hex) Sony Mobile Communications Inc +848EDF (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +A4-9D-49 (hex) Ketra, Inc. +A49D49 (base 16) Ketra, Inc. + 3815 S. Capital of Texas Hwy + Austin TX 78704 + US + +C0-38-96 (hex) Hon Hai Precision Ind. Co.,Ltd. +C03896 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +2C-50-89 (hex) Shenzhen Kaixuan Visual Technology Co.,Limited +2C5089 (base 16) Shenzhen Kaixuan Visual Technology Co.,Limited + No.19th Xifu Road, Hongxing Community + Shenzhen Guangdong 518000 + CN + +94-8E-89 (hex) INDUSTRIAS UNIDAS SA DE CV +948E89 (base 16) INDUSTRIAS UNIDAS SA DE CV + CARRETERA PANAMERICANA + PASTEJE JOCOTITLAN ESTADO DE MEXICO 50700 + MX + +00-AE-FA (hex) Murata Manufacturing Co., Ltd. +00AEFA (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +84-18-26 (hex) Osram GmbH +841826 (base 16) Osram GmbH + Marcel Breuer Str. 6 + Munich Bavaria 80807 + DE + +F8-E9-03 (hex) D-Link International +F8E903 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +E8-96-06 (hex) testo Instruments (Shenzhen) Co., Ltd. +E89606 (base 16) testo Instruments (Shenzhen) Co., Ltd. + China Merchants Guangming Science & Technology Park, + Guangming New District, Shenzhen Guangdong 518107 + CN + +1C-7E-51 (hex) 3bumen.com +1C7E51 (base 16) 3bumen.com + 11/F FRONT BLK HANG LOK BLDG + HONG KONG KONG KONG N/A + HK + +68-72-DC (hex) CETORY.TV Company Limited +6872DC (base 16) CETORY.TV Company Limited + Building C-1601, Tiley Central Plaza + Shenzhen Guangdong 518054 + CN + +30-77-CB (hex) Maike Industry(Shenzhen)CO.,LTD +3077CB (base 16) Maike Industry(Shenzhen)CO.,LTD + Maike Industrial Garden, Sanwei village, + Shenzhen Guangdong 518100 + CN + +24-97-ED (hex) Techvision Intelligent Technology Limited +2497ED (base 16) Techvision Intelligent Technology Limited + Room 7006B, Tianxia IC Industry Building, + Shenzhen Guangdong 518052 + CN + +90-9F-33 (hex) EFM Networks +909F33 (base 16) EFM Networks + 6F, Benposra II 1197-1 Bojeong Giheung Gu + Yong In Kyunggi do 446913 + KR + +60-04-17 (hex) POSBANK CO.,LTD +600417 (base 16) POSBANK CO.,LTD + Room 805-808, New T Castle B/D, 429-1 + Seoul 153-803 + KR + +20-76-93 (hex) Lenovo (Beijing) Limited. +207693 (base 16) Lenovo (Beijing) Limited. + No.6 Chuang Ye Road Shangdi Information Industry Base, + Beijing 100085 + CN + +08-46-56 (hex) VEO-LABS +084656 (base 16) VEO-LABS + 14 rue du Patis Tatelin + RENNES Bretagne 35700 + FR + +EC-3C-5A (hex) SHEN ZHEN HENG SHENG HUI DIGITAL TECHNOLOGY CO.,LTD +EC3C5A (base 16) SHEN ZHEN HENG SHENG HUI DIGITAL TECHNOLOGY CO.,LTD + 5A 6FLOOR, BLOCK C12, FUYUAN INDUSTRIAL AREA, ZHOU SHI ROAD, + SHENZHEN GUANGDONG 518102 + CN + +44-88-CB (hex) Camco Technologies NV +4488CB (base 16) Camco Technologies NV + Technologielaan 13 + Heverlee VB 3001 + BE + +6C-BF-B5 (hex) Noon Technology Co., Ltd +6CBFB5 (base 16) Noon Technology Co., Ltd + Building C, Zhangkeng Industrial Park, Minzhi + Shenzhen GuangDong 518131 + CN + +50-29-4D (hex) NANJING IOT SENSOR TECHNOLOGY CO,LTD +50294D (base 16) NANJING IOT SENSOR TECHNOLOGY CO,LTD + ROOM 422 NO.420 ZHONGHUA ROAD QINHUAI DISTRICT NANJING CITY + Nangjing jiangsu 210000 + CN + +0C-CF-D1 (hex) SPRINGWAVE Co., Ltd +0CCFD1 (base 16) SPRINGWAVE Co., Ltd + #B-703,U-space 1-danji,670 Sampyeong-dong Bundang-gu + Seongnam-si Gyeonggi-do 463-400 + KR + +74-BA-DB (hex) Longconn Electornics(shenzhen)Co.,Ltd +74BADB (base 16) Longconn Electornics(shenzhen)Co.,Ltd + Building D12,n 30,Xingye One Road,Fenghuang First Industrial Zone,Fuyong Street,Bao an District,Shenzhen,Guangdong Province. + shenzhen guangdong 518000 + CN + +B8-F3-17 (hex) iSun Smasher Communications Private Limited +B8F317 (base 16) iSun Smasher Communications Private Limited + No. 826, Ferns Paradise, 2nd Street, + Bangalore Karnataka 560037 + IN + +8C-F8-13 (hex) ORANGE POLSKA +8CF813 (base 16) ORANGE POLSKA + AL.JEROZOLIMSKIE 160 + WARSAW MASOVIA 02-326 + PL + +54-9F-35 (hex) Dell Inc. +549F35 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +24-42-BC (hex) Alinco,incorporated +2442BC (base 16) Alinco,incorporated + Yodoyabashi Dai-Bldg 13F, + Osaka Osaka pref. 541-0043 + JP + +F8-24-41 (hex) Yeelink +F82441 (base 16) Yeelink + F10-B4, Bldg. B, International Innovation Park + Qingdao Shandong 266101 + CN + +10-8A-1B (hex) RAONIX Inc. +108A1B (base 16) RAONIX Inc. + Changeop-Center 710, Shin-Gu Univ. Gwangmyeong-ro 377, Jungwon-gu + Seongnam-si Gyeonggi-do 462-743 + KR + +10-2F-6B (hex) Microsoft Corporation +102F6B (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +8C-B0-94 (hex) Airtech I&C Co., Ltd +8CB094 (base 16) Airtech I&C Co., Ltd + 33B-9L #613-9, Namchon-dong + Namdong-gu Incheon 405-846 + KR + +94-54-93 (hex) Rigado, LLC +945493 (base 16) Rigado, LLC + 2601 25th ST SE, STE 200 + Salem OR 97302 + US + +68-F0-6D (hex) ALONG INDUSTRIAL CO., LIMITED +68F06D (base 16) ALONG INDUSTRIAL CO., LIMITED + FLAT/RM,3 11/F, HUNG TO INDUSTRIAL BUILDING + HONG KONG + HK + +F4-28-53 (hex) Zioncom Electronics (Shenzhen) Ltd. +F42853 (base 16) Zioncom Electronics (Shenzhen) Ltd. + A1&A2 Building,Lantian Technology Park, Xinyu Road, Xingqiao Henggang Block, Shajing Street, Baoan District + Shenzhen Guangdong 518000 + CN + +D4-EC-86 (hex) LinkedHope Intelligent Technologies Co., Ltd +D4EC86 (base 16) LinkedHope Intelligent Technologies Co., Ltd + 2nd Floor,Building 1, Science Park, + Beijing Beijing 100070 + CN + +1C-9C-26 (hex) Zoovel Technologies +1C9C26 (base 16) Zoovel Technologies + Paseo de la Castellana 259C + Madrid 28046 + ES + +04-67-85 (hex) scemtec Hard- und Software fuer Mess- und Steuerungstechnik GmbH +046785 (base 16) scemtec Hard- und Software fuer Mess- und Steuerungstechnik GmbH + Gewerbeparkstr. 20 + Reichshof-Wehnrath NRW 51580 + + +D0-FA-1D (hex) Qihoo 360 Technology Co.,Ltd +D0FA1D (base 16) Qihoo 360 Technology Co.,Ltd + Building 2,6 Haoyuan + Chaoyang District Beijing 100015 + CN + +AC-11-D3 (hex) Suzhou HOTEK Video Technology Co. Ltd +AC11D3 (base 16) Suzhou HOTEK Video Technology Co. Ltd + No.78,Keling Road,Suzhou National new and hi-tech industrial Development zone + Suzhou Jiangsu 215200 + CN + +84-32-EA (hex) ANHUI WANZTEN P&T CO., LTD +8432EA (base 16) ANHUI WANZTEN P&T CO., LTD + 9F Building B1 HUAYI science Park + Hefei Anhui Province 230088 + CN + +E0-1D-38 (hex) Beijing HuaqinWorld Technology Co.,Ltd +E01D38 (base 16) Beijing HuaqinWorld Technology Co.,Ltd + 30F,Beijing Silver Tower + Chao Yang Dist Beijing 100027 + CN + +E4-7F-B2 (hex) FUJITSU LIMITED +E47FB2 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +FC-6D-C0 (hex) BME CORPORATION +FC6DC0 (base 16) BME CORPORATION + 147-2 + Kawagoe-shi Saitama 350-0845 + JP + +24-D1-3F (hex) MEXUS CO.,LTD +24D13F (base 16) MEXUS CO.,LTD + 1512, Seoulsup IT Valley, + Seoul Seoul 133-822 + KR + +78-24-AF (hex) ASUSTek COMPUTER INC. +7824AF (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +FC-9F-E1 (hex) CONWIN.Tech. Ltd +FC9FE1 (base 16) CONWIN.Tech. Ltd + 4D,Tianxia IC Bldg,115 Yiyuan road, Nanshan District,Shenzhen,Guangdong,P.P.China + Shenzhen Guangdong 518000 + CN + +B8-9B-E4 (hex) ABB Power Systems Power Generation +B89BE4 (base 16) ABB Power Systems Power Generation + 29801 Euclid Ave + Wickliffe Ohio 44092 + US + +A8-1B-5D (hex) Foxtel Management Pty Ltd +A81B5D (base 16) Foxtel Management Pty Ltd + Building 3, Level 3 + NORTH RYDE NSW 2113 + AU + +50-50-65 (hex) TAKT Corporation +505065 (base 16) TAKT Corporation + 2762-8 + Chino-City Nagano-Pref. 391-0001 + JP + +40-C6-2A (hex) Shanghai Jing Ren Electronic Technology Co., Ltd. +40C62A (base 16) Shanghai Jing Ren Electronic Technology Co., Ltd. + GUI Qing Road 7 No. 3 building G7 software base A District 208 room + Xuhui District Shanghai City 200233 + CN + +E8-15-0E (hex) Nokia Corporation +E8150E (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +C4-42-02 (hex) Samsung Electronics Co.,Ltd +C44202 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B4-AE-6F (hex) Circle Reliance, Inc DBA Cranberry Networks +B4AE6F (base 16) Circle Reliance, Inc DBA Cranberry Networks + 921 Rose Avenue + Menlo Park CA 94025 + US + +90-DA-6A (hex) FOCUS H&S Co., Ltd. +90DA6A (base 16) FOCUS H&S Co., Ltd. + #113, Doosan Venture Digm, 126-1 + Anyang Gyeonggi-Do 431-755 + KR + +DC-53-7C (hex) Compal Broadband Networks, Inc. +DC537C (base 16) Compal Broadband Networks, Inc. + 13F., No.1, Taiyuan 1st St. + Zhubei City Hsinchu County 30265 + TW + +44-A6-E5 (hex) THINKING TECHNOLOGY CO.,LTD +44A6E5 (base 16) THINKING TECHNOLOGY CO.,LTD + The 6th Floor,Gate No. 3 of Huaqiang Logistics Building + Nanshan, Shenzhen Guangdong 518055 + CN + +A4-5D-A1 (hex) ADB Broadband Italia +A45DA1 (base 16) ADB Broadband Italia + VIALE SARCA 336 + MILANO ITALY 20126 + + +0C-AC-05 (hex) Unitend Technologies Inc. +0CAC05 (base 16) Unitend Technologies Inc. + No.6 Nanda'an Hutong, Xizhimeng st + Zicheng District Beijing 100035 + CN + +4C-6E-6E (hex) Comnect Technology CO.,LTD +4C6E6E (base 16) Comnect Technology CO.,LTD + 7-402, Xinyuan Industrial Park, No.61 + Shenzhen Guangdong 518055 + CN + +8C-33-57 (hex) HiteVision Digital Media Technology Co.,Ltd. +8C3357 (base 16) HiteVision Digital Media Technology Co.,Ltd. + 1st building,Honghui Industrial Park,LiuXian + Shenzhen Guangdong 510008 + CN + +3C-AA-3F (hex) iKey, Ltd. +3CAA3F (base 16) iKey, Ltd. + 2621 Ridgepoint Drive + Austin Texas 78754 + US + +0C-38-3E (hex) Fanvil Technology Co., Ltd. +0C383E (base 16) Fanvil Technology Co., Ltd. + 3F, Block A, Gaoxinqi Building, Anhua Industrial Park + Shenzhen Guangdong 518101 + CN + +60-CD-A9 (hex) Abloomy +60CDA9 (base 16) Abloomy + Room 501 ,CTS Building,No 1 Beishatan Chaoyang District + BeiJing 100083 + CN + +B8-AD-3E (hex) BLUECOM +B8AD3E (base 16) BLUECOM + 116, Venture-ro, Yeonsu-gu, + Incheon 406-840 + KR + +18-30-09 (hex) Woojin Industrial Systems Co., Ltd. +183009 (base 16) Woojin Industrial Systems Co., Ltd. + 95, Sari-ro, Sari-myeon + Goesan-gun Chungcheongbuk-do 367-822 + KR + +74-DB-D1 (hex) Ebay Inc +74DBD1 (base 16) Ebay Inc + 2211 N. First St + San Jose Ca 95131 + US + +30-B5-F1 (hex) Aitexin Technology Co., Ltd +30B5F1 (base 16) Aitexin Technology Co., Ltd + 1210 PDAY research center streer 2 + Peiking 100190 + CN + +B0-10-41 (hex) Hon Hai Precision Ind. Co.,Ltd. +B01041 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +80-AD-67 (hex) Kasda Networks Inc +80AD67 (base 16) Kasda Networks Inc + B-31 Building, Tanglang Industry Zone, Xili, Nanshan District + Shenzhen Guangdong 518055 + CN + +18-D5-B6 (hex) SMG Holdings LLC +18D5B6 (base 16) SMG Holdings LLC + 205 N Michigan Ave + Chicago IL 60601 + US + +5C-2E-59 (hex) Samsung Electronics Co.,Ltd +5C2E59 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A8-E5-39 (hex) Moimstone Co.,Ltd +A8E539 (base 16) Moimstone Co.,Ltd + 4F, 954-9 Gwanyang-dong + Anyang-Si Gyeonggi-do 431-060 + KR + +54-B7-53 (hex) Hunan Fenghui Yinjia Science And Technology Co.,Ltd +54B753 (base 16) Hunan Fenghui Yinjia Science And Technology Co.,Ltd + No.15 Lutian Road + Changsha Hunan 410205 + CN + +10-30-47 (hex) Samsung Electronics Co.,Ltd +103047 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F8-84-F2 (hex) Samsung Electronics Co.,Ltd +F884F2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-75-4D (hex) Nokia +B0754D (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +E0-CB-EE (hex) Samsung Electronics Co.,Ltd +E0CBEE (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +4C-39-09 (hex) HPL Electric & Power Private Limited +4C3909 (base 16) HPL Electric & Power Private Limited + 133, Pace City-1, Sec-37 + Gurgaon Haryana 122001 + IN + +90-7E-BA (hex) UTEK TECHNOLOGY (SHENZHEN) CO.,LTD +907EBA (base 16) UTEK TECHNOLOGY (SHENZHEN) CO.,LTD + 6F, C Building JiaAn Industrial Zone, 72# district of Baoan, ShenZhen, China + SHENZHEN Guangdong Province 518101 + CN + +A0-02-DC (hex) Amazon Technologies Inc. +A002DC (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +54-2A-A2 (hex) Alpha Networks Inc. +542AA2 (base 16) Alpha Networks Inc. + No.8 Li-shing 7th Rd., Science-based Industrial Park, Hsinchu, Taiwan, R.O.C + Hsinchu Taiwan 300 + TW + +84-94-8C (hex) Hitron Technologies. Inc +84948C (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +A8-F7-E0 (hex) PLANET Technology Corporation +A8F7E0 (base 16) PLANET Technology Corporation + 11F, No. 96, Min Quan Road, + New Taipei City 22341 + TW + +44-86-C1 (hex) Siemens Low Voltage & Products +4486C1 (base 16) Siemens Low Voltage & Products + 5400 Triangle Parkway + Norcross GA 30092 + US + +40-45-DA (hex) Spreadtrum Communications (Shanghai) Co., Ltd. +4045DA (base 16) Spreadtrum Communications (Shanghai) Co., Ltd. + Building 1, Spreadtrum Center, No.2288, Zuchongzhi Rd + Shanghai 201203 + + +34-51-AA (hex) JID GLOBAL +3451AA (base 16) JID GLOBAL + 211, Biz Plus Suwon 2F Chungho Bldg, 17 363Road, Susung-ro + SUWON Gyeonggi-do 440-846 + KR + +98-BE-94 (hex) IBM +98BE94 (base 16) IBM + 3039 E Cornwallis Rd + Research Triangle Park NC 27709 + US + +6C-19-8F (hex) D-Link International +6C198F (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +C8-FF-77 (hex) Dyson Limited +C8FF77 (base 16) Dyson Limited + Tetbury Hill + Malmesbury Wiltshire SN16 0RP + GB + +B4-9E-AC (hex) Imagik Int'l Corp +B49EAC (base 16) Imagik Int'l Corp + 2299 SW 37 th Ave + Miami Florida 33145 + US + +CC-07-E4 (hex) Lenovo Mobile Communication Technology Ltd. +CC07E4 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999, Qishan North 2nd Road, Information & Optoelectronics Park, Torch Hi-tech Industry Development Zone, Xiamen, P.R.China + Xiamen Fujian 361006 + US + +C4-6B-B4 (hex) myIDkey +C46BB4 (base 16) myIDkey + 65 Enterprise + Aliso Viejo CA 92656 + US + +0C-63-FC (hex) Nanjing Signway Technology Co., Ltd +0C63FC (base 16) Nanjing Signway Technology Co., Ltd + Rm 1001,10/F,28 Ningshuang Rd, + Nanjing Jiangsu 210012 + CN + +D4-E0-8E (hex) ValueHD Corporation +D4E08E (base 16) ValueHD Corporation + Xinwei Xili, Nanshan District, Shenzhen City Industrial Zone, Shiling 8, 3rd Floor, North + Shenzhen Guangdong 518055 + CN + +C8-9F-1D (hex) SHENZHEN COMMUNICATION TECHNOLOGIES CO.,LTD +C89F1D (base 16) SHENZHEN COMMUNICATION TECHNOLOGIES CO.,LTD + NO.6 QINGNING ROAD,CAIHUANG INDUSTRY PARK, + SHENZHEN GUANGDONG 518109 + CN + +14-3D-F2 (hex) Beijing Shidai Hongyuan Network Communication Co.,Ltd +143DF2 (base 16) Beijing Shidai Hongyuan Network Communication Co.,Ltd + #505, 5F, Tower 3 + Beijing 100000 + CN + +2C-39-C1 (hex) Ciena Corporation +2C39C1 (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +54-EE-75 (hex) Wistron InfoComm(Kunshan)Co.,Ltd. +54EE75 (base 16) Wistron InfoComm(Kunshan)Co.,Ltd. + 168# First Avenue,Kunshan Integrated Free Trade Zone,Kunshan,Jiangsu,China + Kunshan Jiangsu 215300 + CN + +08-74-F6 (hex) Winterhalter Gastronom GmbH +0874F6 (base 16) Winterhalter Gastronom GmbH + Tettnanger Straße 72 + Meckenbeuren Baden-Württemberg 88074 + DE + +D8-49-2F (hex) CANON INC. +D8492F (base 16) CANON INC. + 30-2 Shimomaruko 3-chome, + Ohta-ku Tokyo 146-8501 + JP + +80-0E-24 (hex) ForgetBox +800E24 (base 16) ForgetBox + 61 rue de Sèvres + Ville d'Avray IDF 92140 + FR + +3C-25-D7 (hex) Nokia Corporation +3C25D7 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +30-A8-DB (hex) Sony Mobile Communications Inc +30A8DB (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +18-FF-2E (hex) Shenzhen Rui Ying Da Technology Co., Ltd +18FF2E (base 16) Shenzhen Rui Ying Da Technology Co., Ltd + KaiXinda Electronic Science and Technology Park, Zhoushi Road 49,Shiyan Street,Baoan District,ShenZhen,China + shenzhen guangdong 518108 + CN + +84-72-07 (hex) I&C Technology +847207 (base 16) I&C Technology + 24,Pangyo-ro 255beon-gil, Bundang-gu, Seongnam-si, Gyeonggi-do, 463-400,Korea + Seongnam-si Gyeonggi-do 463-400,Korea + US + +CC-A6-14 (hex) AIFA TECHNOLOGY CORP. +CCA614 (base 16) AIFA TECHNOLOGY CORP. + 1F., No.230, Sec. 2, Bade Rd., Fongshan Dist. + Kaohsiung City Taiwan 83053 + TW + +90-F1-B0 (hex) Hangzhou Anheng Info&Tech CO.,LTD +90F1B0 (base 16) Hangzhou Anheng Info&Tech CO.,LTD + 15F Zhongcai Bldg,#68 Tonghe Rd + Hangzhou Zhejiang 310051 + CN + +4C-8B-30 (hex) Actiontec Electronics, Inc +4C8B30 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +08-05-CD (hex) DongGuang EnMai Electronic Product Co.Ltd. +0805CD (base 16) DongGuang EnMai Electronic Product Co.Ltd. + 701 7th Floor,YiFeng Building, + DongGuang GuangDong Province 523843 + CN + +54-D1-63 (hex) MAX-TECH,INC +54D163 (base 16) MAX-TECH,INC + 2F, 26, 2gil, Dujeonggongdan + Cheonan Chungnam 331957 + KR + +48-B5-A7 (hex) Glory Horse Industries Ltd. +48B5A7 (base 16) Glory Horse Industries Ltd. + Woekshop 8, 4/F., World Wide Industrial Centre, + Shatin, N.T. HKG + HK + +0C-4F-5A (hex) ASA-RT s.r.l. +0C4F5A (base 16) ASA-RT s.r.l. + Strada del Lionetto 16/a + Torino To 10146 + IT + +D4-22-4E (hex) Alcatel Lucent +D4224E (base 16) Alcatel Lucent + Via Energy Park, 14 + Vimercate MB 20871 + IT + +9C-86-DA (hex) Phoenix Geophysics Ltd. +9C86DA (base 16) Phoenix Geophysics Ltd. + 3781 Victoria Park Ave. + Toronto ON M1W 3K5 + CA + +2C-07-3C (hex) DEVLINE LIMITED +2C073C (base 16) DEVLINE LIMITED + FLAT/RM A9,9/F SILVERCORP INT TOWER + HONGKONG 999077 + CN + +7C-1A-03 (hex) 8Locations Co., Ltd. +7C1A03 (base 16) 8Locations Co., Ltd. + 1F, No. 123, Chenggong 2rd Street + Zhube City Hsinchu 302 + TW + +AC-B8-59 (hex) Uniband Electronic Corp, +ACB859 (base 16) Uniband Electronic Corp, + 6F-1 No. Dongguang Rd., + Hsinchu 300 300 + TW + +2C-9A-A4 (hex) Eolo SpA +2C9AA4 (base 16) Eolo SpA + via Gran San Bernardo 12 + Busto Arsizio VA 21052 + IT + +88-B1-E1 (hex) Mojo Networks, Inc. +88B1E1 (base 16) Mojo Networks, Inc. + 339 N.Bernardo Ave + Mountain View CA 94043 + US + +90-DB-46 (hex) E-LEAD ELECTRONIC CO., LTD +90DB46 (base 16) E-LEAD ELECTRONIC CO., LTD + NO.37, GUNGDUNG 1ST RD. + SHENGANG SHIANG CHANGHUA 50971 + TW + +34-4F-5C (hex) R&M AG +344F5C (base 16) R&M AG + Binzstrasse 32 + Wetzikon Zurich 8620 + CH + +60-47-D4 (hex) FORICS Electronic Technology Co., Ltd. +6047D4 (base 16) FORICS Electronic Technology Co., Ltd. + BLD 2A, No 1588, Lianhang Rd + Shanghai 201112 + CN + +FC-F8-B7 (hex) TRONTEQ Electronic +FCF8B7 (base 16) TRONTEQ Electronic + Siemensstrasse 22 + Reutlingen Baden Wuerttemberg 72766 + DE + +30-F4-2F (hex) ESP +30F42F (base 16) ESP + 126-1 Pyeongchon-dong, Dongan-gu + Anyang-si Gyeonggi-do 431-755 + KR + +70-4E-01 (hex) KWANGWON TECH CO., LTD. +704E01 (base 16) KWANGWON TECH CO., LTD. + D-401, Digital-Empire Bldg., 980-3 + Suwon Gyeonggi-Do 443-702 + KR + +74-6A-8F (hex) VS Vision Systems GmbH +746A8F (base 16) VS Vision Systems GmbH + Aspelohe 27A + Norderstedt Schleswig-Holstein 22848 + DE + +54-A3-1B (hex) Shenzhen Linkworld Technology Co,.LTD +54A31B (base 16) Shenzhen Linkworld Technology Co,.LTD + Room 667-675 , sixth floor , + Shenzhen Guangdong 518055 + CN + +CC-39-8C (hex) Shiningtek +CC398C (base 16) Shiningtek + No. 53, Nankeng 3 St + Hsinchu 30841 + TW + +18-20-A6 (hex) Sage Co., Ltd. +1820A6 (base 16) Sage Co., Ltd. + 2-24 Sumiyoshicho, Naka-ku + Yokohama-shi Kanagawa 231-0013 + JP + +20-EA-C7 (hex) SHENZHEN RIOPINE ELECTRONICS CO., LTD +20EAC7 (base 16) SHENZHEN RIOPINE ELECTRONICS CO., LTD + ROOM1002~1004, BaoYuan HuaFeng Headquarters' Business Building, Xixiang Avenue (west) , Bao'an District + Shenzhen Guangdong 518000 + CN + +64-B3-70 (hex) PowerComm Solutions LLC +64B370 (base 16) PowerComm Solutions LLC + 15 Minneakoning Rd. Suite 311 + Flemington NJ 08822 + US + +5C-F5-0D (hex) Institute of microelectronic applications +5CF50D (base 16) Institute of microelectronic applications + Na Valentince 1003/1 + Praha 15000 + CZ + +74-9C-52 (hex) Huizhou Desay SV Automotive Co., Ltd. +749C52 (base 16) Huizhou Desay SV Automotive Co., Ltd. + 103, Hechang 5th Road West, + Huizhou Guangdong 516006 + CN + +C4-29-1D (hex) KLEMSAN ELEKTRIK ELEKTRONIK SAN.VE TIC.AS. +C4291D (base 16) KLEMSAN ELEKTRIK ELEKTRONIK SAN.VE TIC.AS. + kemalpaşa yolu 3.km KEMALPASA 35170 + izmir TÜRKİYE -- 35170 + TR + +6C-5F-1C (hex) Lenovo Mobile Communication Technology Ltd. +6C5F1C (base 16) Lenovo Mobile Communication Technology Ltd. + No.999, Qishan North 2nd Road, + Xiamen 361000 Fujian + US + +7C-E4-AA (hex) Private +7CE4AA (base 16) Private + +08-3F-3E (hex) WSH GmbH +083F3E (base 16) WSH GmbH + Koelner Str. 58a + Gummersbach NRW 51645 + DE + +2C-95-7F (hex) zte corporation +2C957F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +3C-0C-48 (hex) Servergy, Inc. +3C0C48 (base 16) Servergy, Inc. + 1700 N. Redbud + McKinney TEXAS 75069 + US + +10-DE-E4 (hex) automationNEXT GmbH +10DEE4 (base 16) automationNEXT GmbH + Millennium Park 4 + Lustenau Vorarlberg 6890 + AT + +F0-3A-4B (hex) Bloombase, Inc. +F03A4B (base 16) Bloombase, Inc. + 955 Benecia Ave + Sunnyvale California 94085 + US + +A0-E4-53 (hex) Sony Mobile Communications Inc +A0E453 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +40-4A-18 (hex) Addrek Smart Solutions +404A18 (base 16) Addrek Smart Solutions + Al Gharrafa Thani Bin Jassim St + Doha + QA + +C0-C5-69 (hex) SHANGHAI LYNUC CNC TECHNOLOGY CO.,LTD +C0C569 (base 16) SHANGHAI LYNUC CNC TECHNOLOGY CO.,LTD + Building 3,No.25 Cangwu Rd + Shanghai 200233 + CN + +C4-C0-AE (hex) MIDORI ELECTRONIC CO., LTD. +C4C0AE (base 16) MIDORI ELECTRONIC CO., LTD. + 397 + Chikuma Nagano 389-0804 + JP + +AC-C5-95 (hex) Graphite Systems +ACC595 (base 16) Graphite Systems + 2037 Landings Drive + Mountain View California 94043 + US + +7C-E1-FF (hex) Computer Performance, Inc. DBA Digital Loggers, Inc. +7CE1FF (base 16) Computer Performance, Inc. DBA Digital Loggers, Inc. + 2695 Walsh Avenue + Santa Clara CA 95051 + US + +D8-15-0D (hex) TP-LINK TECHNOLOGIES CO.,LTD. +D8150D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +58-50-AB (hex) TLS Corporation +5850AB (base 16) TLS Corporation + 1241 Superior Ave. + Cleveland OH 44114 + US + +7C-CD-11 (hex) MS-Magnet +7CCD11 (base 16) MS-Magnet + Parchevich 42 + Sofia 1000 + BG + +98-FF-6A (hex) OTEC(Shanghai)Technology Co.,Ltd. +98FF6A (base 16) OTEC(Shanghai)Technology Co.,Ltd. + 13th Floor,Building 2 + Shanghai 200235 + CN + +BC-1A-67 (hex) YF Technology Co., Ltd +BC1A67 (base 16) YF Technology Co., Ltd + No.62,South Fumin Road, + Dongguang Guangdong 523773 + CN + +4C-D7-B6 (hex) Helmer Scientific +4CD7B6 (base 16) Helmer Scientific + 14400 Bergen Boulevard + Noblesville Indiana 46060 + US + +84-25-A4 (hex) Tariox Limited +8425A4 (base 16) Tariox Limited + 173 Highway 53 + Cathcart Ontario N0E 1B0 + CA + +48-3D-32 (hex) Syscor Controls & Automation +483D32 (base 16) Syscor Controls & Automation + 201-60 Bastion Sq + Victoria BC V8W 1J2 + CA + +CC-85-6C (hex) SHENZHEN MDK DIGITAL TECHNOLOGY CO.,LTD +CC856C (base 16) SHENZHEN MDK DIGITAL TECHNOLOGY CO.,LTD + Xin fengze industrial park,shangnan east road + SHENZHEN GUANGDONG 518101 + CN + +AC-6B-AC (hex) Jenny Science AG +AC6BAC (base 16) Jenny Science AG + Sandblatte 7a + Rain Luzern 6026 + CH + +D8-EE-78 (hex) Moog Protokraft +D8EE78 (base 16) Moog Protokraft + 4545 W Stone Dr Bldg 135 + Kingsport TN 37660 + US + +24-11-48 (hex) Entropix, LLC +241148 (base 16) Entropix, LLC + 100 Rawson Road + Victor New York 14564 + US + +C4-45-EC (hex) Shanghai Yali Electron Co.,LTD +C445EC (base 16) Shanghai Yali Electron Co.,LTD + Room 1-607 + Shanghai Shanghai 201100 + US + +E0-E6-31 (hex) SNB TECHNOLOGIES LIMITED +E0E631 (base 16) SNB TECHNOLOGIES LIMITED + Rm 303, Building #13, + Long Gang district, ShenZhen GuangDong 518000 + CN + +78-B5-D2 (hex) Ever Treasure Industrial Limited +78B5D2 (base 16) Ever Treasure Industrial Limited + 15A Tung Lee Commercial Building + Sheung Wan 852 + HK + +F8-57-2E (hex) Core Brands, LLC +F8572E (base 16) Core Brands, LLC + 1800 South McDowell Blvd. + Petaluma CA 94954 + US + +50-ED-78 (hex) Changzhou Yongse Infotech Co.,Ltd +50ED78 (base 16) Changzhou Yongse Infotech Co.,Ltd + No.128 Zhengzhong Rd, Xixiashua Town + Changzhou Jiangsu 213135 + CN + +90-02-8A (hex) Shenzhen Shidean Legrand Electronic Products Co.,Ltd +90028A (base 16) Shenzhen Shidean Legrand Electronic Products Co.,Ltd + Block39,Shahe Industrial Zone Baishizhou + Guangdong 518053 + CN + +1C-C1-1A (hex) Wavetronix +1CC11A (base 16) Wavetronix + 78 East 1700 South + Provo UT 84606 + US + +FC-09-D8 (hex) ACTEON Group +FC09D8 (base 16) ACTEON Group + ZAC Athelia IV + La Ciotat France 13705 + FR + +74-3E-CB (hex) Gentrice tech +743ECB (base 16) Gentrice tech + 15F No.738-5 JhengJhong Rd + New Taipei city 235 + TW + +7C-44-4C (hex) Entertainment Solutions, S.L. +7C444C (base 16) Entertainment Solutions, S.L. + Parque Empresarial Miraflores, nave 3 + Zaragoza 50720 + ES + +04-44-A1 (hex) TELECON GALICIA,S.A. +0444A1 (base 16) TELECON GALICIA,S.A. + AVENIDA DE NOSTIAN + A CORUNA 15008 + ES + +20-C6-0D (hex) Shanghai annijie Information technology Co.,LTD +20C60D (base 16) Shanghai annijie Information technology Co.,LTD + Room605,NO.9,Lane 777 + Shanghai 200070 + CN + +38-CA-97 (hex) Contour Design LLC +38CA97 (base 16) Contour Design LLC + 10 Industrial Drive + Windham NH 03087 + US + +BC-2D-98 (hex) ThinGlobal LLC +BC2D98 (base 16) ThinGlobal LLC + 703 wildflower RD + Davenport FL 33837 + US + +18-79-A2 (hex) GMJ ELECTRIC LIMITED +1879A2 (base 16) GMJ ELECTRIC LIMITED + RM 1405, 14/F, C C WU BUILDING + 999077 + HK + +E0-C8-6A (hex) SHENZHEN TW-SCIE Co., Ltd +E0C86A (base 16) SHENZHEN TW-SCIE Co., Ltd + 816# DongMing Building MinKang Road + Shenzhen Guangdong 518000 + CN + +BC-EE-7B (hex) ASUSTek COMPUTER INC. +BCEE7B (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +34-13-A8 (hex) Mediplan Limited +3413A8 (base 16) Mediplan Limited + 245 Sheffield Road + Sheffield South Yorkshire S13 9ZD + GB + +7C-97-63 (hex) Openmatics s.r.o. +7C9763 (base 16) Openmatics s.r.o. + Poděbradova 2842/1 + Pilsen Tschechien 30100 + CZ + +48-A2-B7 (hex) Kodofon JSC +48A2B7 (base 16) Kodofon JSC + 97 Moskovskyi pr. + Voronezh 394077 + RU + +CC-74-98 (hex) Filmetrics Inc. +CC7498 (base 16) Filmetrics Inc. + 3560 Dunhill Street, #100 + San Diego CA 92121 + US + +08-5A-E0 (hex) Recovision Technology Co., Ltd. +085AE0 (base 16) Recovision Technology Co., Ltd. + 1709,No.5 Wanghai Road, + Xiamen Fujian 361006 + CN + +20-E7-91 (hex) Siemens Healthcare Diagnostics, Inc +20E791 (base 16) Siemens Healthcare Diagnostics, Inc + 2 Edgewater Drive + Norwood MA 02062 + US + +08-97-58 (hex) Shenzhen Strong Rising Electronics Co.,Ltd DongGuan Subsidiary +089758 (base 16) Shenzhen Strong Rising Electronics Co.,Ltd DongGuan Subsidiary + QingPing Road 2,Qinghutou village + DongGuan GuangDong 523711 + CN + +FC-19-D0 (hex) Cloud Vision Networks Technology Co.,Ltd. +FC19D0 (base 16) Cloud Vision Networks Technology Co.,Ltd. + F/9,Hechuan Building 2016 + Shanghai 201103 + CN + +94-86-D4 (hex) Surveillance Pro Corporation +9486D4 (base 16) Surveillance Pro Corporation + 12F., No.4, Ln. 609, Sec. 5, Chongxin Rd., Sanchong Dist. + New Taipei City 241 + US + +9C-D6-43 (hex) D-Link International +9CD643 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +3C-18-A0 (hex) Luxshare Precision Industry Company Limited +3C18A0 (base 16) Luxshare Precision Industry Company Limited + Floor 2, Block A, Sanyo New Industrial Area + West Haoyi Community, Shajing Subdistrict Office Bao'an District, Shenzhen, Guangdong 523000 + CN + +8C-AE-89 (hex) Y-cam Solutions Ltd +8CAE89 (base 16) Y-cam Solutions Ltd + 3 dee road + Richmond Surrey TW9 2JN + GB + +94-E9-8C (hex) Nokia +94E98C (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +FC-E1-D9 (hex) Stable Imaging Solutions LLC +FCE1D9 (base 16) Stable Imaging Solutions LLC + 3709 Old Conejo Rd + Newbury Park CA 91320 + US + +50-20-6B (hex) Emerson Climate Technologies Transportation Solutions +50206B (base 16) Emerson Climate Technologies Transportation Solutions + Axel Kiers Vej 5A + Hoejbjerg 8270 + DK + +7C-BF-88 (hex) Mobilicom LTD +7CBF88 (base 16) Mobilicom LTD + Hametzoda 31 + Azor 5800174 + IL + +60-DB-2A (hex) HNS +60DB2A (base 16) HNS + 345-50, Gasan-dong, Geumcheon-gu, Seoul, Korea[153-707] + Seoul The Seoul Metropolis 82 + KR + +B0-45-45 (hex) YACOUB Automation GmbH +B04545 (base 16) YACOUB Automation GmbH + Gustav Meyer Allee 25 + Berlin 13355 + DE + +C8-EE-75 (hex) Pishion International Co. Ltd +C8EE75 (base 16) Pishion International Co. Ltd + 3F,NO,15-2,Beihuan Rd + Taichung City 42760 + TW + +CC-34-29 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +CC3429 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +64-BA-BD (hex) SDJ Technologies, Inc. +64BABD (base 16) SDJ Technologies, Inc. + 2125-B Madera Road + Simi Valley CA 93065 + US + +24-C8-48 (hex) mywerk Portal GmbH +24C848 (base 16) mywerk Portal GmbH + Fabrikstr. 3 + Gronau 48599 + DE + +CC-FB-65 (hex) Nintendo Co., Ltd. +CCFB65 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +A0-A2-3C (hex) GPMS +A0A23C (base 16) GPMS + 40 Ridge Rd + Cornwall VT 05753 + US + +68-FC-B3 (hex) Next Level Security Systems, Inc. +68FCB3 (base 16) Next Level Security Systems, Inc. + 6353 Corte Del Abeto + Carlsbad CA 92011 + US + +94-C3-E4 (hex) Atlas Copco IAS GmbH +94C3E4 (base 16) Atlas Copco IAS GmbH + Gewerbestr. 52 + Bretten-Goelshausen 75015 + DE + +34-88-5D (hex) Logitech Far East +34885D (base 16) Logitech Far East + #2 Creation Rd. 4, + Hsinchu 300 + TW + +88-57-6D (hex) XTA Electronics Ltd +88576D (base 16) XTA Electronics Ltd + The Design House + Stourport-on-Severn Worcestershire DY13 9BZ + GB + +BC-41-00 (hex) CODACO ELECTRONIC s.r.o. +BC4100 (base 16) CODACO ELECTRONIC s.r.o. + Hemy 825 + Valasske Mezirici 75701 + CZ + +FC-D8-17 (hex) Beijing Hesun Technologies Co.Ltd. +FCD817 (base 16) Beijing Hesun Technologies Co.Ltd. + Room 1811, 18th floor, Building No. 4, Courtyard 1, Shangdi tenth Street + Beijing 100085 + CN + +68-2D-DC (hex) Wuhan Changjiang Electro-Communication Equipment CO.,LTD +682DDC (base 16) Wuhan Changjiang Electro-Communication Equipment CO.,LTD + No.8,Yinghu Sience&Technology industrial park + Wuhan Hubei 430040 + CN + +E8-61-1F (hex) Dawning Information Industry Co.,Ltd +E8611F (base 16) Dawning Information Industry Co.,Ltd + NO.15 Huake Street,Hi-Tech Zone + Tianjin 300384 + CN + +28-47-AA (hex) Nokia Corporation +2847AA (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +5C-D6-1F (hex) Qardio, Inc +5CD61F (base 16) Qardio, Inc + 340 S Lemon Ave #1104F + Walnut California 91789 + US + +70-59-57 (hex) Medallion Instrumentation Systems +705957 (base 16) Medallion Instrumentation Systems + 17150 Hickory St + Spring Lake MI 49456 + US + +9C-44-3D (hex) CHENGDU XUGUANG TECHNOLOGY CO, LTD +9C443D (base 16) CHENGDU XUGUANG TECHNOLOGY CO, LTD + 2ND SECTION,PARK ROAD + CHENGDU SICHUAN 610100 + CN + +B4-24-E7 (hex) Codetek Technology Co.,Ltd +B424E7 (base 16) Codetek Technology Co.,Ltd + 4F.-1, No.55, Dongguang Rd., East Dist., + Hsinchu City 300 + TW + +54-2F-89 (hex) Euclid Laboratories, Inc. +542F89 (base 16) Euclid Laboratories, Inc. + 9151 Arvida Ln + Coral Gables Florida 33156 + US + +90-99-16 (hex) ELVEES NeoTek OJSC +909916 (base 16) ELVEES NeoTek OJSC + Proezd 4922, dom 4, stroenie 2 + Moscow Zelenograd 124498 + RU + +00-A2-FF (hex) abatec group AG +00A2FF (base 16) abatec group AG + Oberregauerstraße 48 + Regau 4844 + AT + +60-24-C1 (hex) Jiangsu Zhongxun Electronic Technology Co., Ltd +6024C1 (base 16) Jiangsu Zhongxun Electronic Technology Co., Ltd + tangshu road #8 + yixing jiangsu 214221 + CN + +A0-14-3D (hex) PARROT SA +A0143D (base 16) PARROT SA + 174 Quai de Jemmapes + Paris 75010 + FR + +FC-1B-FF (hex) V-ZUG AG +FC1BFF (base 16) V-ZUG AG + Industriestrasse 66 + Zug 6301 + CH + +F4-28-96 (hex) SPECTO PAINEIS ELETRONICOS LTDA +F42896 (base 16) SPECTO PAINEIS ELETRONICOS LTDA + RUA WALTER JOSE CORREA, AREA 12 + SAO JOSE SANTA CATARINA 88122-035 + BR + +78-CB-33 (hex) DHC Software Co.,Ltd +78CB33 (base 16) DHC Software Co.,Ltd + 16/F,DHC Mansion No.3 Zijin + Beijing 100190 + CN + +60-A9-B0 (hex) Merchandising Technologies, Inc +60A9B0 (base 16) Merchandising Technologies, Inc + 1050 NW 229th Avenue + HIllsboro OR 97124 + US + +50-27-C7 (hex) TECHNART Co.,Ltd +5027C7 (base 16) TECHNART Co.,Ltd + 2-21 Nishiohjicho + Kusatsu Shiga 525-0037 + JP + +6C-5A-B5 (hex) TCL Technoly Electronics (Huizhou) Co., Ltd. +6C5AB5 (base 16) TCL Technoly Electronics (Huizhou) Co., Ltd. + 19th Zhongkai Hi-tech Development Zone + Huizhou Guangdong 516006 + CN + +38-5A-A8 (hex) Beijing Zhongdun Security Technology Development Co. +385AA8 (base 16) Beijing Zhongdun Security Technology Development Co. + No.1 Capital Gymnasium South Road + Beijing 100048 + CN + +F4-A2-94 (hex) EAGLE WORLD DEVELOPMENT CO., LIMITED +F4A294 (base 16) EAGLE WORLD DEVELOPMENT CO., LIMITED + 1F, CMA Bldg., 64 Connaught Road Central + Hong Kong 00852 + HK + +EC-3E-09 (hex) PERFORMANCE DESIGNED PRODUCTS, LLC +EC3E09 (base 16) PERFORMANCE DESIGNED PRODUCTS, LLC + 14144 Ventura Blvd + Sherman Oaks California 91423 + US + +94-7C-3E (hex) Polewall Norge AS +947C3E (base 16) Polewall Norge AS + Vige Havnevei 78 + Kristiansand Vest-Agder 4633 + NO + +34-A3-BF (hex) Terewave. Inc. +34A3BF (base 16) Terewave. Inc. + Room 217, Ssangyong Research Center + Yuseong-gu Daejeon-city 305804 + KR + +8C-08-8B (hex) Remote Solution +8C088B (base 16) Remote Solution + 92, Chogokri, Nammyun + Kimcheon city Kyungbuk 740-871 + KR + +B4-3E-3B (hex) Viableware, Inc +B43E3B (base 16) Viableware, Inc + 12220 113th Ave NE + Kirkland WA 98034 + US + +0C-5C-D8 (hex) DOLI Elektronik GmbH +0C5CD8 (base 16) DOLI Elektronik GmbH + Adi-Maislinger-Str. 7 + Munich 81373 + DE + +3C-15-EA (hex) TESCOM CO., LTD. +3C15EA (base 16) TESCOM CO., LTD. + #928 UTV, 1141-2 Baeksuk Ilsandong + Goyang Gyeonggi 410-722 + KR + +E8-04-10 (hex) Private +E80410 (base 16) Private + +F4-BD-7C (hex) Chengdu jinshi communication Co., LTD +F4BD7C (base 16) Chengdu jinshi communication Co., LTD + No. 108 #1-2-505, Eastern 5 Section, First Ring Road, JinJiang District, + Chengdu Chongqing 610000 + CN + +DC-C4-22 (hex) Systembase Limited +DCC422 (base 16) Systembase Limited + Jupes Field House, Pettridge Lane + Warminster Wiltshire BA12 6DG + GB + +C8-F3-6B (hex) Yamato Scale Co.,Ltd. +C8F36B (base 16) Yamato Scale Co.,Ltd. + 5-22 + Akashi Hyogo 673-8688 + JP + +98-F8-C1 (hex) IDT Technology Limited +98F8C1 (base 16) IDT Technology Limited + Block C, 9/F.,Kaiser Estate, Phase 1, + Kowloon Hong Kong + HK + +6C-D1-B0 (hex) WING SING ELECTRONICS HONG KONG LIMITED +6CD1B0 (base 16) WING SING ELECTRONICS HONG KONG LIMITED + No. 1, Guoyuan Industrial Zone + Guangzhou Guang Dong 510385 + CN + +A4-F5-22 (hex) CHOFU SEISAKUSHO CO.,LTD +A4F522 (base 16) CHOFU SEISAKUSHO CO.,LTD + 2-1 + Shimonoseki-shi Yamaguchi 752-8555 + JP + +84-5C-93 (hex) Chabrier Services +845C93 (base 16) Chabrier Services + 354 Chemin de la Pinatte + Saint-Peray 07130 + FR + +68-E1-66 (hex) Private +68E166 (base 16) Private + +BC-2B-D7 (hex) Revogi Innovation Co., Ltd. +BC2BD7 (base 16) Revogi Innovation Co., Ltd. + 2018, Anhui Building, No. 6007, + Shenzhen, Guangdong 518113 + CN + +28-6D-97 (hex) SAMJIN Co., Ltd. +286D97 (base 16) SAMJIN Co., Ltd. + 199-6, Anyang 7-dong, Manan-gu + Anyang-si Gyeonggi-do 430-817 + KR + +24-EC-D6 (hex) CSG Science & Technology Co.,Ltd.Hefei +24ECD6 (base 16) CSG Science & Technology Co.,Ltd.Hefei + No.612-1,Huangshan Road,Gaoxin District + Hefei Anhui Province 230088 + CN + +CC-2A-80 (hex) Micro-Biz intelligence solutions Co.,Ltd +CC2A80 (base 16) Micro-Biz intelligence solutions Co.,Ltd + Room 611,Sunshine Building + Zhuhai City Guangdong Province 519000 + CN + +60-FE-F9 (hex) Thomas & Betts +60FEF9 (base 16) Thomas & Betts + 5900 Eastport Blvd + Richmond VA 23231 + US + +B8-DC-87 (hex) IAI Corporation +B8DC87 (base 16) IAI Corporation + 577-1 Obane + Shizuoka-City Shizuoka 424-0103 + JP + +7C-6F-F8 (hex) ShenZhen ACTO Digital Video Technology Co.,Ltd. +7C6FF8 (base 16) ShenZhen ACTO Digital Video Technology Co.,Ltd. + 3/F,Building 7,Software Park + ShenZhen GuangDong 518055 + CN + +DC-F7-55 (hex) SITRONIK +DCF755 (base 16) SITRONIK + 22 MARISCHAL GARDENS + ABERDEEN ABERDEENSHIRE AB21 9BY + GB + +5C-02-6A (hex) Applied Vision Corporation +5C026A (base 16) Applied Vision Corporation + 2020 Vision Lane + Cuyahoga Falls OH 44223 + US + +0C-93-01 (hex) PT. Prasimax Inovasi Teknologi +0C9301 (base 16) PT. Prasimax Inovasi Teknologi + Jl. Margonda Raya 494D + Depok Jawa Barat 16424 + ID + +74-66-30 (hex) T:mi Ytti +746630 (base 16) T:mi Ytti + Messitytonkatu 8 C 39 + Helsinki n/a 00180 + FI + +6C-B3-50 (hex) Anhui comhigher tech co.,ltd +6CB350 (base 16) Anhui comhigher tech co.,ltd + B6,717 Zhongshan South Road + Wuhu Anhui 241000 + CN + +38-59-F8 (hex) MindMade Sp. z o.o. +3859F8 (base 16) MindMade Sp. z o.o. + Sniadeckich 10 + Warsaw 00-656 + PL + +4C-DF-3D (hex) TEAM ENGINEERS ADVANCE TECHNOLOGIES INDIA PVT LTD +4CDF3D (base 16) TEAM ENGINEERS ADVANCE TECHNOLOGIES INDIA PVT LTD + A-1/2/A,IDA UPPAL, + HYDERABAD AP 500039 + IN + +E8-92-18 (hex) Arcontia International AB +E89218 (base 16) Arcontia International AB + Gruvgatan 35A + Vastra Frolunda 421 30 + SE + +00-75-E1 (hex) Ampt, LLC +0075E1 (base 16) Ampt, LLC + 4850 Innovation Drive + Fort Collins Colorado 80525 + US + +D4-6A-91 (hex) Snap AV +D46A91 (base 16) Snap AV + 1800 Continental Blvd + Charlotte North Carolina 28273 + US + +98-CD-B4 (hex) Virident Systems, Inc. +98CDB4 (base 16) Virident Systems, Inc. + 500 Yosemite Dr. + Milpitas CA 95035 + US + +A4-23-05 (hex) Open Networking Laboratory +A42305 (base 16) Open Networking Laboratory + 1000 El Camino Real + Menlo Park CA 94025 + US + +1C-48-F9 (hex) GN Netcom A/S +1C48F9 (base 16) GN Netcom A/S + Lautrupbjerg 7 + Ballerup Ballerup DK-2750 + DK + +B0-FE-BD (hex) Private +B0FEBD (base 16) Private + +60-69-9B (hex) isepos GmbH +60699B (base 16) isepos GmbH + Wannweiler Str. 12 + Kirchentellinsfurt 72138 + US + +D4-D5-0D (hex) Southwest Microwave, Inc +D4D50D (base 16) Southwest Microwave, Inc + 9055 S McKemy St + Tempe AZ 85284 + US + +34-CD-6D (hex) CommSky Technologies +34CD6D (base 16) CommSky Technologies + 4655 Old Ironsides Dr + Santa Clara CA 95054 + US + +E4-F3-E3 (hex) Shanghai iComhome Co.,Ltd. +E4F3E3 (base 16) Shanghai iComhome Co.,Ltd. + Small second floor of No.773 Siping Road + Shanghai 200092 + CN + +90-46-B7 (hex) Vadaro Pte Ltd +9046B7 (base 16) Vadaro Pte Ltd + 71 Ayer Rajah Crescent + 139951 + SG + +04-CF-25 (hex) MANYCOLORS, INC. +04CF25 (base 16) MANYCOLORS, INC. + 3F, 4-1-18 Jinnoharu + Kitakyushu Fukuoka 8070821 + JP + +80-BB-EB (hex) Satmap Systems Ltd +80BBEB (base 16) Satmap Systems Ltd + 4 Fountain House + Leatherhead Surrey KT22 7LX + GB + +00-B7-8D (hex) Nanjing Shining Electric Automation Co., Ltd +00B78D (base 16) Nanjing Shining Electric Automation Co., Ltd + NO.699,Laiyinda Road + Nanjing Jiangsu 211100 + CN + +60-FE-1E (hex) China Palms Telecom.Ltd +60FE1E (base 16) China Palms Telecom.Ltd + 2nd Floor of Building 1 + PuDong District Shanghai 201203 + US + +B0-50-BC (hex) SHENZHEN BASICOM ELECTRONIC CO.,LTD. +B050BC (base 16) SHENZHEN BASICOM ELECTRONIC CO.,LTD. + Basicom industry park, Baolong Avenue 3rd Road, Baolong industry town + Shenzhen Guangdong 518116 + CN + +84-1E-26 (hex) KERNEL-I Co.,LTD +841E26 (base 16) KERNEL-I Co.,LTD + #606,ACE Techno Tower 10,470-5 + Gasan-Dong, Geumcheon-gu, Seoul Korea 153-789 + KR + +B4-34-6C (hex) MATSUNICHI DIGITAL TECHNOLOGY (HONG KONG) LIMITED +B4346C (base 16) MATSUNICHI DIGITAL TECHNOLOGY (HONG KONG) LIMITED + 22/F. TWO INTERNATIONAL FINANCE CTR + Hong Kong Hong Kong 999077 + HK + +00-86-A0 (hex) Private +0086A0 (base 16) Private + +A0-5B-21 (hex) ENVINET GmbH +A05B21 (base 16) ENVINET GmbH + Hans-Pinsel-Str. 4 + Haar 85540 + DE + +50-B8-A2 (hex) ImTech Technologies LLC, +50B8A2 (base 16) ImTech Technologies LLC, + 2101 NE Jack London St + Corvallis Oregon 97330 + US + +B0-4C-05 (hex) Fresenius Medical Care Deutschland GmbH +B04C05 (base 16) Fresenius Medical Care Deutschland GmbH + Hafenstr. 9 + Schweinfurt 97424 + DE + +B0-79-3C (hex) Revolv Inc +B0793C (base 16) Revolv Inc + 2060 Broadway #380 + Boulder CO 80302 + US + +9C-4E-BF (hex) BoxCast +9C4EBF (base 16) BoxCast + 14538 Grapeland Ave + Cleveland Ohio 44111 + US + +34-A8-43 (hex) KYOCERA Display Corporation +34A843 (base 16) KYOCERA Display Corporation + 5-7-18 Higashinippori + Arakawa-ku Tokyo 116-0014 + JP + +74-CA-25 (hex) Calxeda, Inc. +74CA25 (base 16) Calxeda, Inc. + 7000 North Mopac Expressway + Austin TX 78731 + US + +5C-A3-EB (hex) Lokel s.r.o. +5CA3EB (base 16) Lokel s.r.o. + Moravska 797/85 + Ostrava Moravskoslezsky 700 30 + CZ + +C8-B3-73 (hex) Cisco-Linksys, LLC +C8B373 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +0C-2A-E7 (hex) Beijing General Research Institute of Mining and Metallurgy +0C2AE7 (base 16) Beijing General Research Institute of Mining and Metallurgy + Building 23, Zone 18 of ABP, No. 188 + Beijing 100160 + CN + +98-30-71 (hex) DAIKYUNG VASCOM +983071 (base 16) DAIKYUNG VASCOM + DAIKYUNG Bldg.#1164-15,Gaepo-dong + Gangnam-gu Seoul 135-960 + KR + +D4-95-24 (hex) Clover Network, Inc. +D49524 (base 16) Clover Network, Inc. + 415 N Mathilda Ave + Sunnyvale CA 94085 + US + +94-50-47 (hex) Rechnerbetriebsgruppe +945047 (base 16) Rechnerbetriebsgruppe + Werner von Siemens Str. 64 + Würzburg Bayern 97076 + DE + +E0-31-D0 (hex) SZ Telstar CO., LTD +E031D0 (base 16) SZ Telstar CO., LTD + Telstar Technology Park No.12&14, Longtong Industrial Zone + Shenzhen Guangdong 518172 + CN + +54-11-2F (hex) Sulzer Pump Solutions Finland Oy +54112F (base 16) Sulzer Pump Solutions Finland Oy + Lentokentaentie 44 + Lappeenranta FI-53600 + FI + +4C-55-B8 (hex) Turkcell Teknoloji +4C55B8 (base 16) Turkcell Teknoloji + TUBITAK MAM Teknoloji Serbest Bolgesi Gebze + Kocaeli 41470 + TR + +08-80-39 (hex) Cisco SPVTG +088039 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +E4-38-F2 (hex) Advantage Controls +E438F2 (base 16) Advantage Controls + 4700 Harold Abitz Dr. + Muskogee OK 74403 + US + +C4-C7-55 (hex) Beijing HuaqinWorld Technology Co.,Ltd +C4C755 (base 16) Beijing HuaqinWorld Technology Co.,Ltd + 30F,Beijing Silver Tower,No.2 North Road, + Beijing 100027 + CN + +0C-2D-89 (hex) QiiQ Communications Inc. +0C2D89 (base 16) QiiQ Communications Inc. + 30 East Beaver Creek Road + Richmond Hill Ontario L4B 1J2 + CA + +A8-D2-36 (hex) Lightware Visual Engineering +A8D236 (base 16) Lightware Visual Engineering + Peterdy utca 15. + Budapest H-1071 + HU + +98-10-94 (hex) Shenzhen Vsun communication technology Co.,ltd +981094 (base 16) Shenzhen Vsun communication technology Co.,ltd + Room 1903, Block A, + Shenzhen Guangdong 518000 + CN + +A4-F3-C1 (hex) Open Source Robotics Foundation, Inc. +A4F3C1 (base 16) Open Source Robotics Foundation, Inc. + 419 N Shoreline Blvd + Mountain View CA 94043 + US + +14-13-30 (hex) Anakreon UK LLP +141330 (base 16) Anakreon UK LLP + 5-th Floor + London EC3V 0EH + GB + +0C-F4-05 (hex) Beijing Signalway Technologies Co.,Ltd +0CF405 (base 16) Beijing Signalway Technologies Co.,Ltd + Room B 1905,Tri-tower + Haidian District Beijing 100190 + CN + +50-61-D6 (hex) Indu-Sol GmbH +5061D6 (base 16) Indu-Sol GmbH + Blumenstr. 3 + Schmölln Thüringen 04626 + DE + +DC-70-14 (hex) Private +DC7014 (base 16) Private + +78-8D-F7 (hex) Hitron Technologies. Inc +788DF7 (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +2C-24-5F (hex) Babolat VS +2C245F (base 16) Babolat VS + 93 rue Andre Bollier + Lyon 69007 + FR + +90-56-92 (hex) Autotalks Ltd. +905692 (base 16) Autotalks Ltd. + Kfar Netter + Israel 40593 + IL + +04-BF-A8 (hex) ISB Corporation +04BFA8 (base 16) ISB Corporation + 1-2-1 Shinyokohama, Kohoku-ku + Yokohama Kanagawa 222-0033 + JP + +8C-C7-D0 (hex) zhejiang ebang communication co.,ltd +8CC7D0 (base 16) zhejiang ebang communication co.,ltd + 1418-36#,Moganshan Road + hangzhou zhejiang 310013 + CN + +B8-AE-6E (hex) Nintendo Co., Ltd. +B8AE6E (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +D0-EB-03 (hex) Zhehua technology limited +D0EB03 (base 16) Zhehua technology limited + Room 2206,No 1079,A,ZhanTao Technology Building, MinZhi Street, Longhua District + Tortoal British Virgin Island,Hong Kong Shenzhen,Guang Dong 518131 + CN + +68-3E-EC (hex) ERECA +683EEC (base 16) ERECA + 75, Rue d'Orgemont + Saint GRATIEN 95210 + FR + +C4-26-28 (hex) Airo Wireless +C42628 (base 16) Airo Wireless + 12 Piedmont Center + Atlanta GA 30305 + US + +30-AA-BD (hex) Shanghai Reallytek Information Technology Co.,Ltd +30AABD (base 16) Shanghai Reallytek Information Technology Co.,Ltd + Building No.1-906, No.3000 Long Dong Avenue + Shanghai 201203 + CN + +A4-B8-18 (hex) PENTA Gesellschaft für elektronische Industriedatenverarbeitung mbH +A4B818 (base 16) PENTA Gesellschaft für elektronische Industriedatenverarbeitung mbH + Ulrichsberger Str. 17 + Deggendorf 94469 + DE + +C0-4D-F7 (hex) SERELEC +C04DF7 (base 16) SERELEC + 2, Chemin du Génie + VENISSIEUX CEDEX 69633 + FR + +0C-84-84 (hex) Zenovia Electronics Inc. +0C8484 (base 16) Zenovia Electronics Inc. + #206, 506B St. Albert Rd. + St. Albert AB T8N 5Z1 + CA + +00-59-07 (hex) LenovoEMC Products USA, LLC +005907 (base 16) LenovoEMC Products USA, LLC + 22 South St + Hopinkton MA 01748 + US + +50-A7-15 (hex) Aboundi, Inc. +50A715 (base 16) Aboundi, Inc. + 4 Bud Way, Unit 10 + Nashua NH 03063 + US + +0C-04-00 (hex) Jantar d.o.o. +0C0400 (base 16) Jantar d.o.o. + Kranjska cesta 24 + Naklo Slovenia 4202 + SI + +68-7C-D5 (hex) Y Soft Corporation, a.s. +687CD5 (base 16) Y Soft Corporation, a.s. + Technicka 2948/13 + Brno Czech Republic 616 00 + CZ + +90-7A-F1 (hex) Wally +907AF1 (base 16) Wally + 1415 NE 45th St + Seattle WA 98105 + US + +2C-B6-93 (hex) Radware +2CB693 (base 16) Radware + 22 Raoul Wallenberg St. + Tel-Aviv 69710 + IL + +A8-61-AA (hex) Cloudview Limited +A861AA (base 16) Cloudview Limited + Kingsway House + St Peter Port Guernsey GY1 2QE + GB + +FC-11-86 (hex) Logic3 plc +FC1186 (base 16) Logic3 plc + Rhodes Way + Watford Hertfordshire WD24 4YW + GB + +E0-18-77 (hex) FUJITSU LIMITED +E01877 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +E4-57-A8 (hex) Stuart Manufacturing, Inc. +E457A8 (base 16) Stuart Manufacturing, Inc. + 1615 East Wallace Street + Fort Wayne Indiana 46803 + US + +78-99-66 (hex) Musilab Electronics (DongGuan)Co.,Ltd. +789966 (base 16) Musilab Electronics (DongGuan)Co.,Ltd. + A2, LinDong 3 Road, LinCun + DongGuan Guangdong 523710 + CN + +28-CB-EB (hex) One +28CBEB (base 16) One + Mechelsesteenweg 326 + Edegem Antwerpen 2650 + BE + +7C-A1-5D (hex) GN ReSound A/S +7CA15D (base 16) GN ReSound A/S + Lautrupbjerg 7 + Ballerup DK-CPH 2750 + DK + +3C-08-1E (hex) Beijing Yupont Electric Power Technology Co.,Ltd +3C081E (base 16) Beijing Yupont Electric Power Technology Co.,Ltd + No.1,Dizang-an Nanxiang + Beijing 100045 + CN + +FC-58-FA (hex) Shen Zhen Shi Xin Zhong Xin Technology Co.,Ltd. +FC58FA (base 16) Shen Zhen Shi Xin Zhong Xin Technology Co.,Ltd. + Block 3, Dong Huan Industrial Zone, Sha Jing Town + Shen Zhen Guang Dong 518000 + CN + +4C-CC-34 (hex) Motorola Solutions Inc. +4CCC34 (base 16) Motorola Solutions Inc. + One Motorola Plaza + Holtsville NY 11742 + US + +D0-D4-71 (hex) MVTECH co., Ltd +D0D471 (base 16) MVTECH co., Ltd + #1004, Hanshin IT Tower, 235, Guro 3-dong, Guro-Gu + SEOUL 152-768 + KR + +08-68-D0 (hex) Japan System Design +0868D0 (base 16) Japan System Design + Skyhills Deshio 3F + Hiroshima 734-0001 + JP + +D4-22-3F (hex) Lenovo Mobile Communication Technology Ltd. +D4223F (base 16) Lenovo Mobile Communication Technology Ltd. + No.999,Qishan North 2nd Road,Information&Optoelectronics Park,Torch Hi-tech Industry Development Zone, + Xiamen Fujian 361006 + US + +C8-EE-A6 (hex) Shenzhen SHX Technology Co., Ltd +C8EEA6 (base 16) Shenzhen SHX Technology Co., Ltd + 6F,No.10 buliding,JiuXiangling Industial Zone,Xili, + Shenzhen Guangdong 518055 + CN + +24-81-AA (hex) KSH International Co., Ltd. +2481AA (base 16) KSH International Co., Ltd. + 2F, No.17 Minsheng Rd, Xindian Dist., + New Taipei City 23150 + US + +AC-41-22 (hex) Eclipse Electronic Systems Inc. +AC4122 (base 16) Eclipse Electronic Systems Inc. + 17111 Waterview Parkway + Dallas TX 75252 + US + +68-97-E8 (hex) Society of Motion Picture & Television Engineers +6897E8 (base 16) Society of Motion Picture & Television Engineers + 3 Barker Ave. FL5 + White Plains NY 10601 + US + +E8-E8-75 (hex) iS5 Communications Inc. +E8E875 (base 16) iS5 Communications Inc. + #1-1815 Meyerside Drive + Mississauga Ontario L5T 1G3 + CA + +C8-0E-95 (hex) OmniLync Inc. +C80E95 (base 16) OmniLync Inc. + 51a Bennington St. + Newton MA 02458 + US + +30-05-5C (hex) Brother industries, LTD. +30055C (base 16) Brother industries, LTD. + 1-1-1, Kawagishi, Mizuho-ku, + Nagoya Aichi 467-8562 + JP + +08-0E-A8 (hex) Velex s.r.l. +080EA8 (base 16) Velex s.r.l. + Via Dell'Artigianato 56 + Vigodarzere Padova 35010 + IT + +B8-C4-6F (hex) PRIMMCON INDUSTRIES INC +B8C46F (base 16) PRIMMCON INDUSTRIES INC + 137 MinQuan Rd, 5th Floor, + New Taipei 23141 + TW + +D8-B0-2E (hex) Guangzhou Zonerich Business Machine Co., LTD. +D8B02E (base 16) Guangzhou Zonerich Business Machine Co., LTD. + North Gate, No.17 Yunjun Road, Luogang District + Guangzhou Guangdong 510530 + CN + +C4-E0-32 (hex) IEEE 1904.1 Working Group +C4E032 (base 16) IEEE 1904.1 Working Group + 1351 Redwood Way, + Petaluma CA 94954 + US + +58-EB-14 (hex) Proteus Digital Health +58EB14 (base 16) Proteus Digital Health + 2600 Bridge Parkway, Ste 101 + Redwood City California 94065 + US + +C4-58-C2 (hex) Shenzhen TATFOOK Technology Co., Ltd. +C458C2 (base 16) Shenzhen TATFOOK Technology Co., Ltd. + 3rd Industrial Area of Shajing Industrial Company, Haoxiang Road + Shenzhen Guangdong 518104 + CN + +D0-CD-E1 (hex) Scientech Electronics +D0CDE1 (base 16) Scientech Electronics + 4F, No.501-17, Zhong Zheng Rd, + New Taipei City 23148 + TW + +5C-E0-CA (hex) FeiTian United (Beijing) System Technology Co., Ltd. +5CE0CA (base 16) FeiTian United (Beijing) System Technology Co., Ltd. + 3 Floor, Tower B, Huizhi Tower + Haidian District Beijing 100085 + CN + +E0-81-77 (hex) GreenBytes, Inc. +E08177 (base 16) GreenBytes, Inc. + 15 Gray Lane, Suite 301 + Ashaway RI 02804 + US + +9C-98-11 (hex) Guangzhou Sunrise Electronics Development Co., Ltd +9C9811 (base 16) Guangzhou Sunrise Electronics Development Co., Ltd + 12th Floor,368 GuangZhou Avenue South + Guangzhou Guangdong 510300 + CN + +B8-60-91 (hex) Onnet Technologies and Innovations LLC +B86091 (base 16) Onnet Technologies and Innovations LLC + 1, 82/83 Street, New Industrial Area -II + Ajman Ajman 52141 + AE + +8C-76-C1 (hex) Goden Tech Limited +8C76C1 (base 16) Goden Tech Limited + ROOM 510-511C2 NAN FUNG TOWER., + 999077 + HK + +8C-07-8C (hex) FLOW DATA INC +8C078C (base 16) FLOW DATA INC + 2309 GRAND PARK DRIVE + GRAND JUNCTION CO 81505 + US + +F8-DF-A8 (hex) zte corporation +F8DFA8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +A8-95-B0 (hex) Aker Subsea Ltd +A895B0 (base 16) Aker Subsea Ltd + Kiekhill Industrial Estate + Aberdeen AB51 3XA + GB + +10-4D-77 (hex) Innovative Computer Engineering +104D77 (base 16) Innovative Computer Engineering + 10302 Eaton Place STE 100 + Fairfax VA 22030 + US + +C4-5D-D8 (hex) HDMI Forum +C45DD8 (base 16) HDMI Forum + 1140 East Arques Avenue, Suite 900 + Sunnyvale CA 94085 + US + +C4-EB-E3 (hex) RRCN SAS +C4EBE3 (base 16) RRCN SAS + 23 chemin du vieux chene + Meylan Isere 38246 + FR + +94-75-6E (hex) QinetiQ North America +94756E (base 16) QinetiQ North America + 137 Delta Drive + Pittsburgh PA 15238 + US + +4C-1A-95 (hex) Novakon Co., Ltd. +4C1A95 (base 16) Novakon Co., Ltd. + 6F., No. 120, Lane 235, Pao Chiao Road + New Taipei City 23145 + TW + +60-BB-0C (hex) Beijing HuaqinWorld Technology Co,Ltd +60BB0C (base 16) Beijing HuaqinWorld Technology Co,Ltd + 30F,Beijing Silver Tower,No.2 North Road + Chao Yang District Beijing 100027 + CN + +A4-2C-08 (hex) Masterwork Automodules +A42C08 (base 16) Masterwork Automodules + 11F-3, 3,PARK ST., NAN GANG + TAIPEI 11503 + TW + +10-B9-FE (hex) Lika srl +10B9FE (base 16) Lika srl + Via San Lorenzo 25 + Carrè Vicenza 36010 + IT + +30-15-18 (hex) Ubiquitous Communication Co. ltd. +301518 (base 16) Ubiquitous Communication Co. ltd. + JEI Platz RM No.410-1 + Seoul 153-792 + KR + +84-17-15 (hex) GP Electronics (HK) Ltd. +841715 (base 16) GP Electronics (HK) Ltd. + Gold Peak Industrial Building, 6F + Kwai Chung NT + HK + +84-8E-96 (hex) Embertec Pty Ltd +848E96 (base 16) Embertec Pty Ltd + 182 Fullarton Road + Dulwich, Adelaide South Australia 5065 + AU + +64-99-A0 (hex) AG Elektronik AB +6499A0 (base 16) AG Elektronik AB + Smidesv 12 + Staffanstorp 24534 + SE + +08-F1-B7 (hex) Towerstream Corpration +08F1B7 (base 16) Towerstream Corpration + 55 Hammerlund Way + Middletown RI 02842 + US + +C0-44-E3 (hex) Shenzhen Sinkna Electronics Co., LTD +C044E3 (base 16) Shenzhen Sinkna Electronics Co., LTD + 9 Building, XinXin Tian Industry Area, + Shenzhen Guangdong 5180000 + CN + +18-55-0F (hex) Cisco SPVTG +18550F (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +18-7A-93 (hex) AMICCOM Electronics Corporation +187A93 (base 16) AMICCOM Electronics Corporation + Room A3, 1F., No.1, Lixing 1st Rd + Hsinchu 30078 + TW + +88-87-DD (hex) DarbeeVision Inc. +8887DD (base 16) DarbeeVision Inc. + 401 N. Cotswolds Lane #C + Orange California 92869 + US + +30-C8-2A (hex) WI-BIZ srl +30C82A (base 16) WI-BIZ srl + Via Carlo Ferrero 10 + Cascine Vica Rivoli Torino 10098 + IT + +88-A3-CC (hex) Amatis Controls +88A3CC (base 16) Amatis Controls + 210 Aspen Airport Business Center, Suite A + Aspen CO 81611 + US + +C0-A0-C7 (hex) FAIRFIELD INDUSTRIES +C0A0C7 (base 16) FAIRFIELD INDUSTRIES + 1111 GILLINGHAM LANE + SUGAR LAND TEXAS 77478 + US + +DC-A9-89 (hex) MACANDC +DCA989 (base 16) MACANDC + 2-nd Filevskaya str.7/6 + Moscow 121096 + RU + +A0-03-63 (hex) Robert Bosch Healthcare GmbH +A00363 (base 16) Robert Bosch Healthcare GmbH + Stuttgarter Stra + Waiblingen Baden-Württemberg 71332 + DE + +D0-B4-98 (hex) Robert Bosch LLC Automotive Electronics +D0B498 (base 16) Robert Bosch LLC Automotive Electronics + 15000 N Haggerty + Plymouth Michigan 48170 + US + +E0-55-97 (hex) Emergent Vision Technologies Inc. +E05597 (base 16) Emergent Vision Technologies Inc. + SUITE# 239 - 552A CLARKE ROAD + COQUITLAM British Columbia V3J 0A3 + CA + +7C-43-8F (hex) E-Band Communications Corp. +7C438F (base 16) E-Band Communications Corp. + 10095 Scripps Ranch Ct. Ste A + San Diego CA 92131 + US + +A0-E2-5A (hex) Amicus SK, s.r.o. +A0E25A (base 16) Amicus SK, s.r.o. + Koreszkova 9 + Skalica Trnavsky kraj 90901 + SK + +D4-0F-B2 (hex) Applied Micro Electronics AME bv +D40FB2 (base 16) Applied Micro Electronics AME bv + Esp 100 + Eindhoven NB 5633 AA + NL + +44-9B-78 (hex) The Now Factory +449B78 (base 16) The Now Factory + Arkle Road + Dublin 18 + IE + +F0-F6-69 (hex) Motion Analysis Corporation +F0F669 (base 16) Motion Analysis Corporation + 3617 Westwind Blvd. + Santa Rosa CA 95403 + US + +78-99-5C (hex) Nationz Technologies Inc +78995C (base 16) Nationz Technologies Inc + 12F,Tower Building #3,China Academy of Science and Technology Development,Gaoxin South Ave.1 + Shen Zhen GuangDong 518057 + CN + +84-9D-C5 (hex) Centera Photonics Inc. +849DC5 (base 16) Centera Photonics Inc. + 3F, No 6-3 Dusing Rd. + Hsinchu Taiwan 30078 + TW + +58-09-43 (hex) Private +580943 (base 16) Private + +EC-FC-55 (hex) A. Eberle GmbH & Co. KG +ECFC55 (base 16) A. Eberle GmbH & Co. KG + Frankenstrasse 160 + Nuernberg Bavaria 90461 + DE + +18-2A-7B (hex) Nintendo Co., Ltd. +182A7B (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +68-FB-95 (hex) Generalplus Technology Inc. +68FB95 (base 16) Generalplus Technology Inc. + 3F, No.8, Dusing Rd., Hsinchu Science Park + Hsinchu City 30077 + TW + +F8-F0-82 (hex) NAG LLC +F8F082 (base 16) NAG LLC + Predelnaya st 57/2 + Ekaterinburg Sverdlovskaya oblast 620161 + RU + +5C-89-D4 (hex) Beijing Banner Electric Co.,Ltd +5C89D4 (base 16) Beijing Banner Electric Co.,Ltd + Mail Box 1033,Long cheng Garden + Chang Ping District beijing 102208 + CN + +54-11-5F (hex) Atamo Pty Ltd +54115F (base 16) Atamo Pty Ltd + 21 River Road + Bayswater WA 6156 + AU + +8C-AE-4C (hex) Plugable Technologies +8CAE4C (base 16) Plugable Technologies + 40 Lake Bellevue Dr. + Bellevue WA 98005 + US + +0C-C6-55 (hex) Wuxi YSTen Technology Co.,Ltd. +0CC655 (base 16) Wuxi YSTen Technology Co.,Ltd. + Room 1801,18F, North Star Times Tower, + Chaoyang District Beijing 100101 + CN + +24-2F-FA (hex) Toshiba Global Commerce Solutions +242FFA (base 16) Toshiba Global Commerce Solutions + B307/D121F + RTP NC 27709 + US + +E4-96-AE (hex) ALTOGRAPHICS Inc. +E496AE (base 16) ALTOGRAPHICS Inc. + Daegu Venture Center 13F + Daegu 701-020 + KR + +4C-22-58 (hex) cozybit, Inc. +4C2258 (base 16) cozybit, Inc. + 605 Market Street + San Francisco CA 94105 + US + +F4-94-66 (hex) CountMax, ltd +F49466 (base 16) CountMax, ltd + 11 Titova str. + poselok Lesnoy Moscowskaya oblast 141231 + RU + +F4-52-14 (hex) Mellanox Technologies, Inc. +F45214 (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +1C-95-9F (hex) Veethree Electronics And Marine LLC +1C959F (base 16) Veethree Electronics And Marine LLC + 2050 47th Terrace East + Bradenton Florida 34203 + US + +08-81-F4 (hex) Juniper Networks +0881F4 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +10-F4-9A (hex) T3 Innovation +10F49A (base 16) T3 Innovation + 808 Calle Plano + Camarillo CA 93012 + US + +3C-57-BD (hex) Kessler Crane Inc. +3C57BD (base 16) Kessler Crane Inc. + 602 East Jefferson St + Plymouth Indidana 46563 + US + +04-E9-E5 (hex) PJRC.COM, LLC +04E9E5 (base 16) PJRC.COM, LLC + 14723 SW Brooke Ct + Sherwood Oregon 97140 + US + +60-BD-91 (hex) Move Innovation +60BD91 (base 16) Move Innovation + Generatorvej 8B,st + Herlev DK 2730 + DK + +CC-4B-FB (hex) Hellberg Safety AB +CC4BFB (base 16) Hellberg Safety AB + Stakebergsvagen 2 + Stenkullen 44361 + SE + +6C-AD-EF (hex) KZ Broadband Technologies, Ltd. +6CADEF (base 16) KZ Broadband Technologies, Ltd. + 1601 Tower C + Shenzhen Guangdong 518057 + CN + +74-5F-AE (hex) TSL PPL +745FAE (base 16) TSL PPL + Units 1-2, First Avenue + Marlow Buckinghamshire SL7 1YA + GB + +68-51-B7 (hex) PowerCloud Systems, Inc. +6851B7 (base 16) PowerCloud Systems, Inc. + 3333 Coyote Hill Rd + Palo Alto CA 94304 + US + +74-2D-0A (hex) Norfolk Elektronik AG +742D0A (base 16) Norfolk Elektronik AG + Luzernstrasse 12 + Eschenbach LU 6274 + CH + +70-F1-E5 (hex) Xetawave LLC +70F1E5 (base 16) Xetawave LLC + 1668 Valtec Lane + Boulder CO 80301 + US + +C0-AA-68 (hex) OSASI Technos Inc. +C0AA68 (base 16) OSASI Technos Inc. + 65-3, Hongu-cho, + Kochi-shi, Kochi-ken 780-0945 + JP + +88-D7-BC (hex) DEP Company +88D7BC (base 16) DEP Company + Poryadkovy pereulok,21 + Moscow 127055 + RU + +48-5A-3F (hex) WISOL +485A3F (base 16) WISOL + 373-7, Gajang-dong + Osan-si Gyeonggi-do 447-210 + KR + +60-BC-4C (hex) EWM Hightec Welding GmbH +60BC4C (base 16) EWM Hightec Welding GmbH + Dr.Günter-Henle-Str. 8 + Mündersbach Rheinland Pfalz 56271 + DE + +1C-11-E1 (hex) Wartsila Finland Oy +1C11E1 (base 16) Wartsila Finland Oy + Jarvikatu 2-4 + Vaasa Western Finland 65101 + FI + +50-46-5D (hex) ASUSTek COMPUTER INC. +50465D (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +74-BF-A1 (hex) HYUNTECK +74BFA1 (base 16) HYUNTECK + #603 107-Dong, Jugong Apt., Changhyeon-ri, Hwado-eup + Namyangju-si Gyeonggi-do 472-779 + KR + +CC-26-2D (hex) Verifi, LLC +CC262D (base 16) Verifi, LLC + 9466 Meridian Way + West Chester OH 45069 + US + +3C-8A-E5 (hex) Tensun Information Technology(Hangzhou) Co.,LTD +3C8AE5 (base 16) Tensun Information Technology(Hangzhou) Co.,LTD + Room 207,Building 5,Wensan Road + Hangzhou Zhejiang 310013 + CN + +2C-5A-A3 (hex) PROMATE ELECTRONIC CO.LTD +2C5AA3 (base 16) PROMATE ELECTRONIC CO.LTD + 4F 32,SEC.1 HUAN SHAN RD.,NEI HU, + TAIPEI 114 + TW + +34-E0-CF (hex) zte corporation +34E0CF (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +08-B7-38 (hex) Lite-On Technogy Corp. +08B738 (base 16) Lite-On Technogy Corp. + 18F, 392, RueyKuang Road, Neihu, + Taipei 11492 + TW + +F8-AA-8A (hex) Axview Technology (Shenzhen) Co.,Ltd +F8AA8A (base 16) Axview Technology (Shenzhen) Co.,Ltd + NO 1, Mei Zhong Road, Futian District + SHENZHEN GUANGDONG 518049 + CN + +7C-01-87 (hex) Curtis Instruments, Inc. +7C0187 (base 16) Curtis Instruments, Inc. + 200 Kisco Avenue + Mt Kisco NY 10549 + US + +54-F6-66 (hex) Berthold Technologies GmbH and Co.KG +54F666 (base 16) Berthold Technologies GmbH and Co.KG + Calmbacher Strasse 22 + Bad Wildbad 75323 + DE + +34-C8-03 (hex) Nokia Corporation +34C803 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +F0-5F-5A (hex) Getriebebau NORD GmbH and Co. KG +F05F5A (base 16) Getriebebau NORD GmbH and Co. KG + Rudolf-Diesel-Strasse 1 + Bargteheide Schleswig-Holstein 22941 + DE + +80-1D-AA (hex) Avaya Inc +801DAA (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +7C-09-2B (hex) Bekey A/S +7C092B (base 16) Bekey A/S + Bredebjergvej 6 + Taastrup 2630 + DK + +84-2B-BC (hex) Modelleisenbahn GmbH +842BBC (base 16) Modelleisenbahn GmbH + Plainbachstrasse 4 + Bergheim 5101 + AT + +B4-00-9C (hex) CableWorld Ltd. +B4009C (base 16) CableWorld Ltd. + Kondorfa u. 6/B + Budapest 1112 + HU + +28-9E-DF (hex) Danfoss Turbocor Compressors, Inc +289EDF (base 16) Danfoss Turbocor Compressors, Inc + 1769 E. Paul Dirac Ave. + Tallahassee Florida 32310 + US + +80-3F-D6 (hex) bytes at work AG +803FD6 (base 16) bytes at work AG + Konradstrasse 15 + Winterthur ZH 8400 + CH + +78-44-05 (hex) FUJITU(HONG KONG) ELECTRONIC Co.,LTD. +784405 (base 16) FUJITU(HONG KONG) ELECTRONIC Co.,LTD. + 8/F,QingHai Building,Xiang Mei Road,Futian District + SHENZHEN GUANGDONG 518000 + CN + +04-4A-50 (hex) Ramaxel Technology (Shenzhen) limited company +044A50 (base 16) Ramaxel Technology (Shenzhen) limited company + 2-5/F,North Block Southeast Industrial and Commercial Building Houhai Road,Shekou Shenzhen + shenzhen guangdong 518067 + CN + +0C-D9-C1 (hex) Visteon Corporation +0CD9C1 (base 16) Visteon Corporation + One Village Center Drive + Van Buren Twp MI 48111 + US + +38-A5-B6 (hex) SHENZHEN MEGMEET ELECTRICAL CO.,LTD +38A5B6 (base 16) SHENZHEN MEGMEET ELECTRICAL CO.,LTD + 5th Floor,Building B, Ziguang Information Harbor + Shenzhen Guangdong 518057 + CN + +68-AB-8A (hex) RF IDeas +68AB8A (base 16) RF IDeas + 4020 Winnetka Ave + Rolling Meadows IL 60008 + US + +24-EE-3A (hex) Chengdu Yingji Electronic Hi-tech Co Ltd +24EE3A (base 16) Chengdu Yingji Electronic Hi-tech Co Ltd + No.3 South Herui Road Hi-tech Zone + Chengdu City Sichuan 611731 + CN + +0C-C6-6A (hex) Nokia Corporation +0CC66A (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +74-27-3C (hex) ChangYang Technology (Nanjing) Co., LTD +74273C (base 16) ChangYang Technology (Nanjing) Co., LTD + NO.9 KaiCheng Road,QiLinTown + NanJing JiangSu 211100 + CN + +08-7C-BE (hex) Quintic Corp. +087CBE (base 16) Quintic Corp. + 1600 Wyatt Dr., #8 + Santa Clara CA 95054 + US + +E8-04-F3 (hex) Throughtek Co., Ltd. +E804F3 (base 16) Throughtek Co., Ltd. + 4F, no. 221, Chong-yang Rd. + Taipei 11573 + TW + +08-68-EA (hex) EITO ELECTRONICS CO., LTD. +0868EA (base 16) EITO ELECTRONICS CO., LTD. + 1-34-1 Shinmeidai + Hamura-shi Tokyo 205-0023 + JP + +F8-22-85 (hex) Cypress Technology CO., LTD. +F82285 (base 16) Cypress Technology CO., LTD. + 6F-5, NO., 130 Jiankang Rd., + Zhonghe Dist. New Taipei City 23585 + TW + +C4-AD-21 (hex) MEDIAEDGE Corporation +C4AD21 (base 16) MEDIAEDGE Corporation + 23F Kobe Commerce, Industry and Trade Center Bldg. + Kobe Hyogo 651-0083 + JP + +E8-5B-F0 (hex) Imaging Diagnostics +E85BF0 (base 16) Imaging Diagnostics + POB 698 + Nes Ziona N/A 74106 + IL + +A4-0B-ED (hex) Carry Technology Co.,Ltd +A40BED (base 16) Carry Technology Co.,Ltd + 4F, No.119, JianKang Road + Jhonghe Dist. New Taipei City 23585 + TW + +70-23-93 (hex) fos4X GmbH +702393 (base 16) fos4X GmbH + Thalkirchner Str. 210, Geb. 6 + 81371 München + DE + +64-D8-14 (hex) Cisco Systems, Inc +64D814 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F8-5F-2A (hex) Nokia Corporation +F85F2A (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +C4-38-D3 (hex) TAGATEC CO.,LTD +C438D3 (base 16) TAGATEC CO.,LTD + #604, Dongmoon Goodmorning Tower 2, + Goyang-si Kyunggi-do 410-704 + KR + +50-2E-CE (hex) Asahi Electronics Co.,Ltd +502ECE (base 16) Asahi Electronics Co.,Ltd + 29-25 Kariyado + Kanagawa-ken 211-0022 + JP + +AC-14-D2 (hex) wi-daq, inc. +AC14D2 (base 16) wi-daq, inc. + 850 NW Federal Hwy + Stuart Florida 34994 + US + +9C-4C-AE (hex) Mesa Labs +9C4CAE (base 16) Mesa Labs + 10 Evergreen Dr + Bozeman MT 59715 + US + +20-C1-AF (hex) i Wit Digital Co., Limited +20C1AF (base 16) i Wit Digital Co., Limited + 303,Buiding1,Nanhai Ecool Innovation Park, + Shenzhen GuangDong 518000 + US + +80-AA-A4 (hex) USAG +80AAA4 (base 16) USAG + 301 Goolsby Blvd + Deerfield Beach FL 33442 + US + +30-AE-F6 (hex) Radio Mobile Access +30AEF6 (base 16) Radio Mobile Access + 1 Elm Sq + Andover MA 01870 + US + +08-5B-0E (hex) Fortinet, Inc. +085B0E (base 16) Fortinet, Inc. + 899 Kifer Road + Sunnyvale California 94086 + US + +EC-42-F0 (hex) ADL Embedded Solutions, Inc. +EC42F0 (base 16) ADL Embedded Solutions, Inc. + 4411 Morena Blvd. + San Diego CA 92117 + US + +E8-CB-A1 (hex) Nokia Corporation +E8CBA1 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +6C-E4-CE (hex) Villiger Security Solutions AG +6CE4CE (base 16) Villiger Security Solutions AG + Giessenmatt 2 + Sins 5643 + CH + +64-9F-F7 (hex) Kone OYj +649FF7 (base 16) Kone OYj + Myllykatu 3 + Hyvinkaa Hyvinkaa 05830 + FI + +CC-91-2B (hex) TE Connectivity Touch Solutions +CC912B (base 16) TE Connectivity Touch Solutions + 2245 Brighton Henrietta Town Line Road + Rochester New York 14623 + US + +C0-5E-79 (hex) SHENZHEN HUAXUN ARK TECHNOLOGIES CO.,LTD +C05E79 (base 16) SHENZHEN HUAXUN ARK TECHNOLOGIES CO.,LTD + 3F,C4 Building,Yintian Industrial Zone,Xixiang,Baoan District + shenzhen guangdong 518102 + CN + +58-BF-EA (hex) Cisco Systems, Inc +58BFEA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C4-01-B1 (hex) SeekTech INC +C401B1 (base 16) SeekTech INC + 3855 Ruffin Road + San Diego California 92123 + US + +C0-C9-46 (hex) MITSUYA LABORATORIES INC. +C0C946 (base 16) MITSUYA LABORATORIES INC. + 6-31-18 + KAWASAKI-CITY KANAGAWA 215-0021 + JP + +F4-60-0D (hex) Panoptic Technology, Inc +F4600D (base 16) Panoptic Technology, Inc + 587 W Eau Gallie Blvd + Melbourne FL 32935 + US + +A8-2B-D6 (hex) Shina System Co., Ltd +A82BD6 (base 16) Shina System Co., Ltd + 3305, O'BizTower, 126, Beolmal-ro, + Anyang-Si Gyeounggi-Do 431-763 + KR + +AC-CF-23 (hex) Hi-flying electronics technology Co.,Ltd +ACCF23 (base 16) Hi-flying electronics technology Co.,Ltd + Room B101,456 BiBo Raod,PuDong + Shanghai 201200 + CN + +60-90-84 (hex) DSSD Inc +609084 (base 16) DSSD Inc + 4025 Bohannon Dr + Menlo Park CA 94025 + US + +FC-1D-59 (hex) I Smart Cities HK Ltd +FC1D59 (base 16) I Smart Cities HK Ltd + Unit G,10/F,Phase 2,Yip Fat IND + 73-75 + HK + +78-C4-AB (hex) Shenzhen Runsil Technology Co.,Ltd +78C4AB (base 16) Shenzhen Runsil Technology Co.,Ltd + 4/F., Yuhua Building A, Yangmen Industrial Park, + Shenzhen GuangDong 518055 + CN + +B0-A8-6E (hex) Juniper Networks +B0A86E (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +80-2A-FA (hex) Germaneers GmbH +802AFA (base 16) Germaneers GmbH + Dr.-Kurt-Schumacher-Ring 3 + Wettstetten Bayern 85139 + DE + +18-42-1D (hex) Private +18421D (base 16) Private + +28-C9-14 (hex) Taimag Corporation +28C914 (base 16) Taimag Corporation + NO. 1, West 2nd St. N.E.P.Z + Kaohsiung 811 + TW + +74-93-A4 (hex) Zebra Technologies Corp. +7493A4 (base 16) Zebra Technologies Corp. + 20314 Seneca Meadows Parkway + Germantown Maryland 21771 + US + +E4-71-85 (hex) Securifi Ltd +E47185 (base 16) Securifi Ltd + 16F-3, #482 Zhongxiao E Rd, Sec 5 + Taipei 11083 + TW + +08-0C-C9 (hex) Mission Technology Group, dba Magma +080CC9 (base 16) Mission Technology Group, dba Magma + 9918 Via Pasar + San Diego CA 92126 + US + +64-0E-94 (hex) Pluribus Networks, Inc. +640E94 (base 16) Pluribus Networks, Inc. + 1808 Embarcadero Rd Suite B + Palo Alto CA 94303 + US + +0C-B4-EF (hex) Digience Co.,Ltd. +0CB4EF (base 16) Digience Co.,Ltd. + 204 Building for Growth, Gumi Electronics&Information Technology Research Institute, 17 Cheomdangieop-1ro, + Gumi Gyeongbuk + KR + +14-6A-0B (hex) Cypress Electronics Limited +146A0B (base 16) Cypress Electronics Limited + 11/F., Block G, East Sun Industrial Centre, 16 Shing Yip Street, + Hong Kong nil nil + HK + +F4-90-EA (hex) Deciso B.V. +F490EA (base 16) Deciso B.V. + Burgemeester Mijslaan 2 + Middelharnis Zuid Holland 3241 XA + NL + +5C-EE-79 (hex) Global Digitech Co LTD +5CEE79 (base 16) Global Digitech Co LTD + 1F., No.25, Aly.56, Ln. 245, Sec. 4, Bade Rd., + Taipei Taiwan 105 + TW + +4C-AA-16 (hex) AzureWave Technologies (Shanghai) Inc. +4CAA16 (base 16) AzureWave Technologies (Shanghai) Inc. + No.8 Lane 66, Chenbao Road, Malu Town Jiading District + Shanghai 201801 + CN + +AC-40-EA (hex) C&T Solution Inc. +AC40EA (base 16) C&T Solution Inc. + 12F-1, No.700, Zhongzheng Rd., Zhonghe Dist. + New Taipei City Taiwan 235 + TW + +00-2A-AF (hex) LARsys-Automation GmbH +002AAF (base 16) LARsys-Automation GmbH + Sinzinger Str. 3 + Hochburg-Ach 5122 + AT + +1C-E1-65 (hex) Marshal Corporation +1CE165 (base 16) Marshal Corporation + Field Three Sotokanda Bldg. + 5-3-6, Sotokanda, Chiyodaku Tokyo 101-0021 + JP + +40-16-FA (hex) EKM Metering +4016FA (base 16) EKM Metering + 363 Berkeley Way + Santa Cruz CA 95062 + US + +0C-13-0B (hex) Uniqoteq Ltd. +0C130B (base 16) Uniqoteq Ltd. + Lemminkaisenkatu 14-18 A + Turku 20520 + FI + +2C-54-2D (hex) Cisco Systems, Inc +2C542D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +BC-14-01 (hex) Hitron Technologies. Inc +BC1401 (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +94-CA-0F (hex) Honeywell Analytics +94CA0F (base 16) Honeywell Analytics + 2840 2nd Ave SE + Calgary Alberta T2A7X9 + CA + +78-25-44 (hex) Omnima Limited +782544 (base 16) Omnima Limited + Oxford Science Park + Oxford Oxfordshire OX4 4GP + GB + +A4-18-75 (hex) Cisco Systems, Inc +A41875 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C8-AE-9C (hex) Shanghai TYD Elecronic Technology Co. Ltd +C8AE9C (base 16) Shanghai TYD Elecronic Technology Co. Ltd + 21F, BLKB, NO.391 GuiPing Rd, + Shanghai 200233 + CN + +AC-3F-A4 (hex) TAIYO YUDEN CO.,LTD +AC3FA4 (base 16) TAIYO YUDEN CO.,LTD + 8-1, Sakae-cho + Takasaki-shi Gunma 370-8522 + JP + +6C-AE-8B (hex) IBM Corporation +6CAE8B (base 16) IBM Corporation + 4400 North First Street + San Jose CA 95134 + US + +40-AC-8D (hex) Data Management, Inc. +40AC8D (base 16) Data Management, Inc. + 3322 Loop 306 + San Angelo Texas 76904 + US + +80-CE-B1 (hex) Theissen Training Systems GmbH +80CEB1 (base 16) Theissen Training Systems GmbH + Schuchardstrasse 3 + Duesseldorf NRW 40595 + DE + +FC-2A-54 (hex) Connected Data, Inc. +FC2A54 (base 16) Connected Data, Inc. + 2905 Stender Way + Santa Clara CA 95054 + US + +04-5C-06 (hex) Zmodo Technology Corporation +045C06 (base 16) Zmodo Technology Corporation + 1401 Interstate Dr + Champaign IL 61822 + US + +74-7B-7A (hex) ETH Inc. +747B7A (base 16) ETH Inc. + #202 Mazium BLG, 545-6, Dangjung-dong, + Gunpo-si Gyeonggi-do 435-833 + KR + +48-EA-63 (hex) Zhejiang Uniview Technologies Co., Ltd. +48EA63 (base 16) Zhejiang Uniview Technologies Co., Ltd. + Eastcom Building C,Eastcom Avenue + Hangzhou Zhejiang 310053 + CN + +E8-8D-F5 (hex) ZNYX Networks, Inc. +E88DF5 (base 16) ZNYX Networks, Inc. + 48421 Milmont Drive + Fremont CA 94538 + US + +90-F7-2F (hex) Phillips Machine & Welding Co., Inc. +90F72F (base 16) Phillips Machine & Welding Co., Inc. + 16125 E. Gale Ave. + Industry CA 91745 + US + +D0-57-85 (hex) Pantech Co., Ltd. +D05785 (base 16) Pantech Co., Ltd. + 110-1 Ongjeong-Ri, Tongjin-Eup + Gimpo-Si Gyounggi-Do 415-865 + KR + +40-8B-07 (hex) Actiontec Electronics, Inc +408B07 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +28-41-21 (hex) OptiSense Network, LLC +284121 (base 16) OptiSense Network, LLC + 1308 10th Street + Bridgeport TX 76426 + US + +38-45-8C (hex) MyCloud Technology corporation +38458C (base 16) MyCloud Technology corporation + Room 705£¬Building F, Jiahua Building£¬ + Beijing 100085 + CN + +10-E4-AF (hex) APR, LLC +10E4AF (base 16) APR, LLC + 4800 US HWY 280 West + Opelika AL 36801 + US + +F4-EA-67 (hex) Cisco Systems, Inc +F4EA67 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +2C-2D-48 (hex) bct electronic GesmbH +2C2D48 (base 16) bct electronic GesmbH + Saalachstraße 86a + Salzburg 5020 + AT + +28-BA-18 (hex) NextNav, LLC +28BA18 (base 16) NextNav, LLC + 484 Oakmead Parkway + Sunnyvale CA 94085 + US + +AC-3D-75 (hex) HANGZHOU ZHIWAY TECHNOLOGIES CO.,LTD. +AC3D75 (base 16) HANGZHOU ZHIWAY TECHNOLOGIES CO.,LTD. + FLOOR12B,BUILDING E,PARADISE SOFTWARE PARK,NO.3 XIDOUMEN ROAD, + HANGZHOU ZHEJIANG 310012 + CN + +A0-90-DE (hex) VEEDIMS,LLC +A090DE (base 16) VEEDIMS,LLC + 49 N. Federal Highway #397 + Pompano Beach Florida 33062 + US + +64-2D-B7 (hex) SEUNGIL ELECTRONICS +642DB7 (base 16) SEUNGIL ELECTRONICS + #16-8, Dodang-dong + Buchon Gyuonggi-do 420-801 + KR + +00-2A-6A (hex) Cisco Systems, Inc +002A6A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F4-36-E1 (hex) Abilis Systems SARL +F436E1 (base 16) Abilis Systems SARL + 3, chemin Pré Fleuri + Plan-Les-Ouates Geneva 1228 + CH + +78-1C-5A (hex) SHARP Corporation +781C5A (base 16) SHARP Corporation + 22-22,Nagaike-cho + Osaka city Osaka prefecture 545-8522 + JP + +E8-0C-75 (hex) Syncbak, Inc. +E80C75 (base 16) Syncbak, Inc. + 5 Research Center + Marion IA 52302 + US + +80-0A-06 (hex) COMTEC co.,ltd +800A06 (base 16) COMTEC co.,ltd + 60 shimoishida,azabu-cho, + Miyoshi-shi Aichi-ken 470-0206 + JP + +60-8C-2B (hex) Hanson Technology +608C2B (base 16) Hanson Technology + Room 1503, Zhao Jia Bang Road + Shanghai 200030 + CN + +94-00-70 (hex) Nokia Corporation +940070 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +BC-2C-55 (hex) Bear Flag Design, Inc. +BC2C55 (base 16) Bear Flag Design, Inc. + 1 Thayer Road + Santa Cruz CA 95060 + US + +0C-75-23 (hex) BEIJING GEHUA CATV NETWORK CO.,LTD +0C7523 (base 16) BEIJING GEHUA CATV NETWORK CO.,LTD + No.35,N.Huayuan RD.,Haidian District + BEIJING 100083 + CN + +04-F0-21 (hex) Compex Systems Pte Ltd +04F021 (base 16) Compex Systems Pte Ltd + 135 Joo Seng Road, + 368363 + SG + +28-18-FD (hex) Aditya Infotech Ltd. +2818FD (base 16) Aditya Infotech Ltd. + Khemka Square, A-12, Sector-4, + Noida Uttar Pradesh 201301 + IN + +D8-B9-0E (hex) Triple Domain Vision Co.,Ltd. +D8B90E (base 16) Triple Domain Vision Co.,Ltd. + No.9, Aly. 1, Ln. 585, Sec.3, Fulin Rd., + Hsinchu Conuty 307 + TW + +34-2F-6E (hex) Anywire corporation +342F6E (base 16) Anywire corporation + 1 Zusyo, Baba + Nagaokakyo Kyoto pref. 617-8550 + JP + +CC-EE-D9 (hex) VAHLE Automation GmbH +CCEED9 (base 16) VAHLE Automation GmbH + Egerbach 12a + Kufstein Schwoich Tirol 6334 + AT + +00-5C-B1 (hex) Gospell DIGITAL TECHNOLOGY CO., LTD +005CB1 (base 16) Gospell DIGITAL TECHNOLOGY CO., LTD + Block F10-F13¡¢F518 Idea land ¡¢Bao Yuan Road + Shenzhen Guangdong 518102 + CN + +B0-8E-1A (hex) URadio Systems Co., Ltd +B08E1A (base 16) URadio Systems Co., Ltd + Phase II D202-2, 1355 JinJiHu Blvd + Suzhou Jiangsu 215021 + CN + +D8-E9-52 (hex) KEOPSYS +D8E952 (base 16) KEOPSYS + 21 RUE LOUIS DE BROGLIE + LANNION BRITANY 22300 + FR + +BC-A4-E1 (hex) Nabto +BCA4E1 (base 16) Nabto + Aabogade 15 + Aarhus Jutland 8200 + DK + +90-8F-CF (hex) UNO System Co., Ltd +908FCF (base 16) UNO System Co., Ltd + #402 Kolon Science Valley °., 187-10, Guro-dong, Guro-gu + Seoul 152-848 + KR + +40-E7-93 (hex) Shenzhen Siviton Technology Co.,Ltd +40E793 (base 16) Shenzhen Siviton Technology Co.,Ltd + 4F,Block6,Coolpad Business Centre,North of Keyuan Road,Hi-technology Zone,Nanshan District + Shenzhen Guangdong 518057 + CN + +00-08-31 (hex) Cisco Systems, Inc +000831 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +34-D0-9B (hex) MobilMAX Technology Inc. +34D09B (base 16) MobilMAX Technology Inc. + 2F-5, No.28, Tai-Yuan St. + Chupei City, Hsinchu Country 302 + TW + +F0-00-7F (hex) Janz - Contadores de Energia, SA +F0007F (base 16) Janz - Contadores de Energia, SA + Avenida Infante D. Henrique + Lisbon 1800-223 + PT + +30-B3-A2 (hex) Shenzhen Heguang Measurement & Control Technology Co.,Ltd +30B3A2 (base 16) Shenzhen Heguang Measurement & Control Technology Co.,Ltd + 3/F, Tower A, Xiangnian Plaza, 6060 Qiaoxiang Road, + Shenzhen Guangdong 518053 + CN + +50-60-28 (hex) Xirrus Inc. +506028 (base 16) Xirrus Inc. + 2101 CORPORATE CENTER DR + Thousand Oaks CALIFORNIA 91320 + US + +00-91-FA (hex) Synapse Product Development +0091FA (base 16) Synapse Product Development + 1511 6th Ave + Seattle WA 98101 + US + +A0-5A-A4 (hex) Grand Products Nevada, Inc. +A05AA4 (base 16) Grand Products Nevada, Inc. + 751 Pilot Rd. + Las Vegas Nevada 89119 + US + +F0-EE-BB (hex) VIPAR GmbH +F0EEBB (base 16) VIPAR GmbH + Lichtenbergstrasse 8 + Garching bei Muenchen Bavaria 85748 + DE + +6C-E9-07 (hex) Nokia Corporation +6CE907 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +E4-FA-1D (hex) PAD Peripheral Advanced Design Inc. +E4FA1D (base 16) PAD Peripheral Advanced Design Inc. + 1400 Hocquart + Saint-Bruno QC J3V 6E1 + CA + +1C-5C-55 (hex) PRIMA Cinema, Inc +1C5C55 (base 16) PRIMA Cinema, Inc + 1903 Wright Place, Suite 320 + Carlsbad CA 92008 + US + +34-BA-9A (hex) Asiatelco Technologies Co. +34BA9A (base 16) Asiatelco Technologies Co. + 301,#8 Building,#289 Bisheng Road + Shanghai 201204 + CN + +50-64-41 (hex) Greenlee +506441 (base 16) Greenlee + 219 S Main St + Dallas TX 76104 + US + +9C-1F-DD (hex) Accupix Inc. +9C1FDD (base 16) Accupix Inc. + 3F Gaeyang BLDG, 548-1, + Anyang Kyeonggi-Do 430-730 + KR + +7C-DD-11 (hex) Chongqing MAS SCI&TECH.Co.,Ltd +7CDD11 (base 16) Chongqing MAS SCI&TECH.Co.,Ltd + 6th Floor, Zone C2,Hi-tech Venture Park, No.105 Erlang Venture Road + Chongqing City 400039 + CN + +B8-FD-32 (hex) Zhejiang ROICX Microelectronics +B8FD32 (base 16) Zhejiang ROICX Microelectronics + 22 Floor, 1888 Jianghui Road, Binjiang District + Hangzhou Zhejiang 310051 + CN + +70-EE-50 (hex) Netatmo +70EE50 (base 16) Netatmo + 17 route de la reine + Boulogne-Billancourt 92100 + FR + +98-4A-47 (hex) CHG Hospital Beds +984A47 (base 16) CHG Hospital Beds + 1020 Adelaide St S + London ON N6E 1R6 + CA + +14-49-78 (hex) Digital Control Incorporated +144978 (base 16) Digital Control Incorporated + 19625 62nd Ave S + Kent WA 98032 + US + +2C-10-C1 (hex) Nintendo Co., Ltd. +2C10C1 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +8C-D1-7B (hex) CG Mobile +8CD17B (base 16) CG Mobile + 3F Caohejing Software Building, No.461 Hongcao Rd.,XuHui District + Shanghai 200233 + CN + +50-22-67 (hex) PixeLINK +502267 (base 16) PixeLINK + 3030 Conroy Road + Ottawa Ontario K1G 6C2 + CA + +3C-6A-7D (hex) Niigata Power Systems Co., Ltd. +3C6A7D (base 16) Niigata Power Systems Co., Ltd. + 7-26,Tatsumi 3-Chome + Koto-ku TOKYO 135-0053 + JP + +3C-70-59 (hex) MakerBot Industries +3C7059 (base 16) MakerBot Industries + 87 3rd Avenue + Brooklyn NY 11217 + US + +50-26-90 (hex) FUJITSU LIMITED +502690 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +24-B6-57 (hex) Cisco Systems, Inc +24B657 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C8-AF-40 (hex) marco Systemanalyse und Entwicklung GmbH +C8AF40 (base 16) marco Systemanalyse und Entwicklung GmbH + Hans-Böckler-Straße 2 + Dachau Bavaria 85221 + DE + +40-98-4C (hex) Casacom Solutions AG +40984C (base 16) Casacom Solutions AG + Badenerstarsse 551 + Zuerich 8046 + CH + +5C-18-B5 (hex) Talon Communications +5C18B5 (base 16) Talon Communications + 10636 Scripps Summit Ct. + San Diego CA 92131 + US + +64-E1-61 (hex) DEP Corp. +64E161 (base 16) DEP Corp. + Nishi-shinjuku 6-12-7 + Shinjuku Tokyo 160-0023 + JP + +88-23-FE (hex) TTTech Computertechnik AG +8823FE (base 16) TTTech Computertechnik AG + Schoenbrunnerstrasse 7 + Vienna 1040 + AT + +B8-9A-ED (hex) OceanServer Technology, Inc +B89AED (base 16) OceanServer Technology, Inc + 151 Martine St + Fall River MA 02723 + US + +C8-7D-77 (hex) Shenzhen Kingtech Communication Equipment Co.,Ltd +C87D77 (base 16) Shenzhen Kingtech Communication Equipment Co.,Ltd + Floor3.Building A,NO.3,Road 1 of shangxue Dengxinkeng Industry Park,Bantian Street, + Shenzhen City Guangdong 518112 + CN + +94-AE-61 (hex) Alcatel Lucent +94AE61 (base 16) Alcatel Lucent + Via Energy Park, 14 + Vimercate MB 20871 + IT + +5C-CE-AD (hex) CDYNE Corporation +5CCEAD (base 16) CDYNE Corporation + 505 Independence Pkwy Ste 300 + Chesapeake VA 23320 + US + +AC-54-EC (hex) IEEE P1823 Standards Working Group +AC54EC (base 16) IEEE P1823 Standards Working Group + 445 Hoes Lane + Piscataway NJ 08854 + US + +70-97-56 (hex) Happyelectronics Co.,Ltd +709756 (base 16) Happyelectronics Co.,Ltd + #A-805, Bundang Technopark, + Seongnam-Si 463-816 + KR + +B8-20-E7 (hex) Guangzhou Horizontal Information & Network Integration Co. Ltd +B820E7 (base 16) Guangzhou Horizontal Information & Network Integration Co. Ltd + Floor 10¬Golden Star Building¬Wushan Hanjing Road¬Tianhe District¬Guangzhou City + Guangzhou Guangdong Province 510630 + CN + +00-CD-90 (hex) MAS Elektronik AG +00CD90 (base 16) MAS Elektronik AG + Pollhornbogen 19 + Hamburg 21107 + DE + +7C-6B-52 (hex) Tigaro Wireless +7C6B52 (base 16) Tigaro Wireless + Shen A'ari 7 + Even Yehuda 40500 + IL + +00-64-A6 (hex) Maquet CardioVascular +0064A6 (base 16) Maquet CardioVascular + 1300 MacArthur Blvd + Mahwah NJ 07430 + US + +98-8B-AD (hex) Corintech Ltd. +988BAD (base 16) Corintech Ltd. + Ashford Mill + Fordingbridge Hampshire SP6 1DZ + GB + +D4-4B-5E (hex) TAIYO YUDEN CO., LTD. +D44B5E (base 16) TAIYO YUDEN CO., LTD. + 8-1, Sakae-cho + Takasaki-shi Gunma 370-8522 + JP + +64-0E-36 (hex) TAZTAG +640E36 (base 16) TAZTAG + Cicea 1 + Bruz 35170 + FR + +94-1D-1C (hex) TLab West Systems AB +941D1C (base 16) TLab West Systems AB + Ebbe Lieberathsgatan 23B + Gothenburg 41265 + SE + +E4-55-EA (hex) Dedicated Computing +E455EA (base 16) Dedicated Computing + N26 W23880 Commerce Circle + Waukesha Wisconsin 53188 + US + +B0-5C-E5 (hex) Nokia Corporation +B05CE5 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +34-82-DE (hex) Kiio Inc +3482DE (base 16) Kiio Inc + 404 Holtzman Rd + Madison WI 53713 + US + +4C-5F-D2 (hex) Alcatel-Lucent +4C5FD2 (base 16) Alcatel-Lucent + 777 East Middlefield Road + Mountain View CA 94043 + US + +28-C7-18 (hex) Altierre +28C718 (base 16) Altierre + 1980 Concourse Drive + San Jose United States 95131 + US + +7C-4C-58 (hex) Scale Computing, Inc. +7C4C58 (base 16) Scale Computing, Inc. + 2121 El Camino Real + San Mateo UNITED STATES 94403 + US + +10-13-EE (hex) Justec International Technology INC. +1013EE (base 16) Justec International Technology INC. + 7F-2 No 113 Zihyou Road + Hsinchu City 30041 + TW + +8C-27-1D (hex) QuantHouse +8C271D (base 16) QuantHouse + 52 Rue de la Victoire + Paris 75009 + FR + +38-60-77 (hex) PEGATRON CORPORATION +386077 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +70-81-05 (hex) Cisco Systems, Inc +708105 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E0-ED-1A (hex) vastriver Technology Co., Ltd +E0ED1A (base 16) vastriver Technology Co., Ltd + A-6A Keshi Building,No.28,Xinxi Road,Haidian, + Beijing 100085 + CN + +D4-F6-3F (hex) IEA S.R.L. +D4F63F (base 16) IEA S.R.L. + Eva Peron 4468 + Rosario Santa Fe S2002LBQ + AR + +58-B0-D4 (hex) ZuniData Systems Inc. +58B0D4 (base 16) ZuniData Systems Inc. + 4F-7, No.65, Gaotia 7th Rd, Zhubei City + Hsinchu 302 + TW + +64-55-7F (hex) NSFOCUS Information Technology Co., Ltd. +64557F (base 16) NSFOCUS Information Technology Co., Ltd. + 3/F,Ether Building, No.4 Beiwa Rd.,Haidian District + Beijing 100089 + CN + +00-08-2F (hex) Cisco Systems, Inc +00082F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +9C-C7-D1 (hex) SHARP Corporation +9CC7D1 (base 16) SHARP Corporation + 22-22,Nagaike-cho + Osaka city Osaka prefecture 545-8522 + JP + +14-90-90 (hex) KongTop industrial(shen zhen)CO.,LTD +149090 (base 16) KongTop industrial(shen zhen)CO.,LTD + xinwuyuan,gushu,Xixiang,Baoan, + Shenzhen Guangdong 518000 + CN + +38-DE-60 (hex) Mohlenhoff GmbH +38DE60 (base 16) Mohlenhoff GmbH + Museumstraße 54a + Salzgitter Niedersachsen 38229 + DE + +28-39-E7 (hex) Preceno Technology Pte.Ltd. +2839E7 (base 16) Preceno Technology Pte.Ltd. + 11F, No.207-2, Sec. 3, Beixin Rd., Xindian Dist. + New Taipei City 23143 + TW + +68-5E-6B (hex) PowerRay Co., Ltd. +685E6B (base 16) PowerRay Co., Ltd. + 7F-1, No 190, Sec 2, Chung Hsing Road, Sindian District + New Taipei City 231 + TW + +20-C8-B3 (hex) SHENZHEN BUL-TECH CO.,LTD. +20C8B3 (base 16) SHENZHEN BUL-TECH CO.,LTD. + Area C,4/F,NO.59,Longjing 2nd Road, + SHENZHEN GuangDong 518101 + CN + +F8-E7-B5 (hex) µTech Tecnologia LTDA +F8E7B5 (base 16) µTech Tecnologia LTDA + Rua Lauro Linhares, 598 + Florianopolis Santa Catarina 88036-200 + BR + +D4-CE-B8 (hex) Enatel LTD +D4CEB8 (base 16) Enatel LTD + 66 Treffers Road + Christchurch Canterbury 8042 + NZ + +80-7A-7F (hex) ABB Genway Xiamen Electrical Equipment CO., LTD +807A7F (base 16) ABB Genway Xiamen Electrical Equipment CO., LTD + 7F,No.23 Wanghai Road,Software Park 2, Lvling Road, + Xiamen Fujian Province 361008 + CN + +24-DA-B6 (hex) Sistemas de Gestión Energética S.A. de C.V +24DAB6 (base 16) Sistemas de Gestión Energética S.A. de C.V + Calzada de los Fresnos 70-A + Zapopan Jalisoc 45010 + MX + +B0-7D-62 (hex) Dipl.-Ing. H. Horstmann GmbH +B07D62 (base 16) Dipl.-Ing. H. Horstmann GmbH + Humboldtstraße 2 + Heiligenhaus 42579 + DE + +B8-F5-E7 (hex) WayTools, LLC +B8F5E7 (base 16) WayTools, LLC + 401 Wilshire Blvd. + Santa Monica CA 90401 + US + +B8-19-99 (hex) Nesys +B81999 (base 16) Nesys + Energeticheskaya, 1 + Moscow 111116 + RU + +34-25-5D (hex) Shenzhen Loadcom Technology Co.,Ltd +34255D (base 16) Shenzhen Loadcom Technology Co.,Ltd + Yuehai Building A-13CD,Nanhai Road,Nanshan Area + Shenzhen Guangdong 518054 + CN + +4C-A7-4B (hex) Alcatel Lucent +4CA74B (base 16) Alcatel Lucent + Via Energy Park, 14 + Vimercate MB 20871 + IT + +D0-31-10 (hex) Ingenic Semiconductor Co.,Ltd +D03110 (base 16) Ingenic Semiconductor Co.,Ltd + Room 108,Building A,Information Center Zhongguancun Software Park 8 Dongbeiwang West Road,Haidain District + Beijing 100193 + CN + +1C-E1-92 (hex) Qisda Corporation +1CE192 (base 16) Qisda Corporation + 157 Shan-Ying Road + Gueishan Taoyuan 333 + TW + +70-6F-81 (hex) Private +706F81 (base 16) Private + +FC-00-12 (hex) Toshiba Samsung Storage Technolgoy Korea Corporation +FC0012 (base 16) Toshiba Samsung Storage Technolgoy Korea Corporation + 14 Floor, Bldg. No. 102, Digital Empire2, 486, Sin-dong, Yeongtong-gu, Suwon-si, + Su-won Gyeonggi 443-734 + KR + +18-14-20 (hex) TEB SAS +181420 (base 16) TEB SAS + RD294 - Corpeau + Meursault Burgundy 21190 + FR + +AC-81-F3 (hex) Nokia Corporation +AC81F3 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +30-68-8C (hex) Reach Technology Inc. +30688C (base 16) Reach Technology Inc. + 4575 Cushing Parkway + Fremont California 94538 + US + +10-EE-D9 (hex) Canoga Perkins Corporation +10EED9 (base 16) Canoga Perkins Corporation + 20600 Prairie Street + Chatsworth CA 91311 + US + +94-DE-0E (hex) SmartOptics AS +94DE0E (base 16) SmartOptics AS + Stalfjaera 9 + Oslo N-0975 + NO + +C0-29-F3 (hex) XySystem +C029F3 (base 16) XySystem + #1304 Daerung Post Tower 5 + Seoul 153-801 + KR + +AC-4A-FE (hex) Hisense Broadband Multimedia Technology Co.,Ltd. +AC4AFE (base 16) Hisense Broadband Multimedia Technology Co.,Ltd. + No.11 Jiangxi Road,Shinan District + Qingdao City Shandong Province 266071 + CN + +54-F5-B6 (hex) ORIENTAL PACIFIC INTERNATIONAL LIMITED +54F5B6 (base 16) ORIENTAL PACIFIC INTERNATIONAL LIMITED + 5 ARGUS PLACE + NORTH SHORE CITY AUCKLAND 0627 + NZ + +90-34-2B (hex) Gatekeeper Systems, Inc. +90342B (base 16) Gatekeeper Systems, Inc. + 8 Studebaker + Irvine CA 92618 + US + +8C-B8-2C (hex) IPitomy Communications +8CB82C (base 16) IPitomy Communications + 1940 Northgate Boulevard + Sarasota Florida 34234 + US + +80-7D-E3 (hex) Chongqing Sichuan Instrument Microcircuit Co.LTD. +807DE3 (base 16) Chongqing Sichuan Instrument Microcircuit Co.LTD. + Jinhua Road No.309, Beibei, + Chongqing 400700 + CN + +DC-17-5A (hex) Hitachi High-Technologies Corporation +DC175A (base 16) Hitachi High-Technologies Corporation + 794, Higashitoyoi, + Kudamatsu City, Yamaguchi Pref., 744-0002, + JP + +C8-A1-BA (hex) Neul Ltd +C8A1BA (base 16) Neul Ltd + Suite 42 Innovation Centre + Cambridge Cambs CB4 0EY + GB + +C4-3A-9F (hex) Siconix Inc. +C43A9F (base 16) Siconix Inc. + #28, 2333 18th Ave NE + Calgary Alberta T2E 8T6 + CA + +68-6E-23 (hex) Wi3 Inc. +686E23 (base 16) Wi3 Inc. + P.O. Box 1123 + Pittsford NY 14534 + US + +DC-F0-5D (hex) Letta Teknoloji +DCF05D (base 16) Letta Teknoloji + TUBITAK Teknoloji Gelistirme Bolgesi + KOCAELI 41455 + TR + +5C-16-C7 (hex) Big Switch Networks +5C16C7 (base 16) Big Switch Networks + 100 W Evelyn + Mountain View CA 94041 + US + +84-8F-69 (hex) Dell Inc. +848F69 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +3C-09-6D (hex) Powerhouse Dynamics +3C096D (base 16) Powerhouse Dynamics + 1 Bridge Street + Newton MA 02458 + US + +90-0D-66 (hex) Digimore Electronics Co., Ltd +900D66 (base 16) Digimore Electronics Co., Ltd + 10 FL., No. 61, Yan-Ping South Road + Taipei 100 + TW + +0C-92-4E (hex) Rice Lake Weighing Systems +0C924E (base 16) Rice Lake Weighing Systems + 230 West Coleman St + Rice Lake WI 54868 + US + +F4-94-61 (hex) NexGen Storage +F49461 (base 16) NexGen Storage + 400 Centennial Blvd. + Louisville CO 80027 + US + +B8-CD-A7 (hex) Maxeler Technologies Ltd. +B8CDA7 (base 16) Maxeler Technologies Ltd. + 1 Down Place + London UK W6 9JH + GB + +54-35-DF (hex) Symeo GmbH +5435DF (base 16) Symeo GmbH + Prof.-Messerschmitt-Str. 3 + Neubiberg Bavaria 85579 + DE + +F4-3D-80 (hex) FAG Industrial Services GmbH +F43D80 (base 16) FAG Industrial Services GmbH + Kaiserstrasse 100 + Herzogenrath NRW 52134 + DE + +F0-DB-30 (hex) Yottabyte +F0DB30 (base 16) Yottabyte + 1750 S. Telegraph Road + Bloomfield Twp. MI 48302 + US + +9C-31-B6 (hex) Kulite Semiconductor Products Inc +9C31B6 (base 16) Kulite Semiconductor Products Inc + 1 Willow Tree Rd + Leonia NJ 07605 + US + +A4-B3-6A (hex) JSC SDO Chromatec +A4B36A (base 16) JSC SDO Chromatec + 94, Stroiteley street + Yoshkar-Ola Mari El republic 424000 + RU + +E4-DD-79 (hex) En-Vision America, Inc. +E4DD79 (base 16) En-Vision America, Inc. + 1845 Hovey Ave + Normal IL 61761 + US + +E8-CC-32 (hex) Micronet LTD +E8CC32 (base 16) Micronet LTD + Hametzuda 27 + Azor 58001 + IL + +D4-3A-E9 (hex) DONGGUAN ipt INDUSTRIAL CO., LTD +D43AE9 (base 16) DONGGUAN ipt INDUSTRIAL CO., LTD + No.66-1.Ist New Area, Nanshe Dist., Chigang,Humen, + Dongguan Guangdong 52390 + CN + +58-98-35 (hex) Technicolor +589835 (base 16) Technicolor + Prins Boudewijnlaan 47 + Edegem - Belgium B-2650 + BE + +8C-5C-A1 (hex) d-broad,INC +8C5CA1 (base 16) d-broad,INC + 3-17-5 ShinYokohama Kouhoku-Ku + Yokohama Kanagawa 222-0033 + JP + +18-F6-50 (hex) Multimedia Pacific Limited +18F650 (base 16) Multimedia Pacific Limited + 1 Matheson Street, Shell Tower 29F/12 + 000000 + HK + +68-84-70 (hex) eSSys Co.,Ltd +688470 (base 16) eSSys Co.,Ltd + Daerung Post Tower 5 15F, 60-3 + Seoul Geumcheon-gu 153-702 + KR + +48-DC-FB (hex) Nokia Corporation +48DCFB (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +20-B7-C0 (hex) OMICRON electronics GmbH +20B7C0 (base 16) OMICRON electronics GmbH + Oberes Ried 1 + Klaus 6833 + AT + +80-58-C5 (hex) NovaTec Kommunikationstechnik GmbH +8058C5 (base 16) NovaTec Kommunikationstechnik GmbH + Technologiepark 9 + Paderborn NRW 33100 + DE + +B8-C7-16 (hex) Fiberhome Telecommunication Technologies Co.,LTD +B8C716 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +D4-2C-3D (hex) Sky Light Digital Limited +D42C3D (base 16) Sky Light Digital Limited + Rm. 1009 Kwong Sang Hong Centre, 151-153 Hoi Bun Road, Kwun Tong, Kowloon, + Hong Kong 999077 + CN + +A4-5A-1C (hex) smart-electronic GmbH +A45A1C (base 16) smart-electronic GmbH + Industriestrasse 29 + St. Georgen Baden-Württemberg 78122 + DE + +80-64-59 (hex) Nimbus Inc. +806459 (base 16) Nimbus Inc. + 1359 Gwanpyeong-dong, Yuseong-gu + Daejeon 305-509 + KR + +8C-89-A5 (hex) Micro-Star INT'L CO., LTD +8C89A5 (base 16) Micro-Star INT'L CO., LTD + No.69, Lide st. + Taipei County 235 + TW + +B4-A5-A9 (hex) MODI GmbH +B4A5A9 (base 16) MODI GmbH + Kapellenweg 21 + REICHSHOF-Sinspert 51580 + DE + +E8-C3-20 (hex) Austco Communication Systems Pty Ltd +E8C320 (base 16) Austco Communication Systems Pty Ltd + 40 O'Malley Street + Osborne Park Western Australia 6017 + AU + +C4-36-DA (hex) Rusteletech Ltd. +C436DA (base 16) Rusteletech Ltd. + Ordzhonikidze Str. 11, Bldg. 40, Off. 15 + Moscow 115419 + RU + +04-32-F4 (hex) Partron +0432F4 (base 16) Partron + 22-6, Seokwoo-dong + Hwaseong-si Gyeonggi-do 445-170 + KR + +1C-18-4A (hex) ShenZhen RicherLink Technologies Co.,LTD +1C184A (base 16) ShenZhen RicherLink Technologies Co.,LTD + 703,Building W1-A,High-Tech Industrial Park,KeJiNan 1st Road,NanShan, + ShenZhen GuangDong 518057 + CN + +0C-39-56 (hex) Observator instruments +0C3956 (base 16) Observator instruments + Rietdekkerstraat 6 + Ridderkerk Zuid Holland 2984 BM + NL + +DC-A6-BD (hex) Beijing Lanbo Technology Co., Ltd. +DCA6BD (base 16) Beijing Lanbo Technology Co., Ltd. + Room.301.Bidg.4NO.8 Shangdi West Road, Haidian District, + Beijing City 100085 + CN + +10-C5-86 (hex) BIO SOUND LAB CO., LTD. +10C586 (base 16) BIO SOUND LAB CO., LTD. + Suite 311, 312 SKn Techno Park + Seongnam-si Gyeonggi-do, 462-721 + KR + +10-76-8A (hex) EoCell +10768A (base 16) EoCell + 149 Beaconsfield Street + Silverwater NSW 2128 + AU + +F4-4E-FD (hex) Actions Semiconductor Co.,Ltd.(Cayman Islands) +F44EFD (base 16) Actions Semiconductor Co.,Ltd.(Cayman Islands) + Po Box 309GT,Ugland House,South Church Street, + George Town Grand Cayman + KY + +24-B8-D2 (hex) Opzoon Technology Co.,Ltd. +24B8D2 (base 16) Opzoon Technology Co.,Ltd. + 11th floor, Tower B£¬Yintai Center 2 Jianguomenwai St,. + Beijing Asia 100022 + CN + +A4-99-81 (hex) FuJian Elite Power Tech CO.,LTD. +A49981 (base 16) FuJian Elite Power Tech CO.,LTD. + 8th Floor£¬56 GuanRi Road + Xiamen Fujian 361009 + CN + +B8-3A-7B (hex) Worldplay (Canada) Inc. +B83A7B (base 16) Worldplay (Canada) Inc. + 803 - 24th Ave SE, Unit 200 + Calgary Alberta T2G 1P5 + CA + +14-07-E0 (hex) Abrantix AG +1407E0 (base 16) Abrantix AG + Foerrlibuckstrasse 66 + Zuerich ZH 8005 + CH + +DC-CF-94 (hex) Beijing Rongcheng Hutong Technology Co., Ltd. +DCCF94 (base 16) Beijing Rongcheng Hutong Technology Co., Ltd. + Room 401A,Building No.4,Yard No.5, + Beijing 100024 + CN + +A4-DB-2E (hex) Kingspan Environmental Ltd +A4DB2E (base 16) Kingspan Environmental Ltd + 180 Gilford Road + Portadown Armagh BT63 5LF + GB + +60-54-64 (hex) Eyedro Green Solutions Inc. +605464 (base 16) Eyedro Green Solutions Inc. + 151 Charles St W + Kitchener Ontario N2G1H6 + CA + +C8-FE-30 (hex) Bejing DAYO Mobile Communication Technology Ltd. +C8FE30 (base 16) Bejing DAYO Mobile Communication Technology Ltd. + Room 712, ULO Park Building No. 601E + Beijing 100102 + CN + +E4-D7-1D (hex) Oraya Therapeutics +E4D71D (base 16) Oraya Therapeutics + 8000 Jarvis Avenue Ste. 200 + Newark CA 94560 + US + +24-C9-DE (hex) Genoray +24C9DE (base 16) Genoray + #812 Byucksan Technopia 434-6 Sangdaewon 1-Dong + Seongnam-City Gyeonggi-Do 462-716 + KR + +54-05-5F (hex) Alcatel Lucent +54055F (base 16) Alcatel Lucent + Via Energy Park, 14 + Vimercate MB 20871 + IT + +6C-5D-63 (hex) ShenZhen Rapoo Technology Co., Ltd. +6C5D63 (base 16) ShenZhen Rapoo Technology Co., Ltd. + Block A1,B1,B2,1st second stage, 1st Industrial Park, 3rd Industrial Zone ,Fenghuang Fuyong, BaoAn + ShenZhen 518103 + CN + +94-16-73 (hex) Point Core SARL +941673 (base 16) Point Core SARL + 29/31 Rue du Bois Galon + FONTENAY SOUS BOIS Ile de France 94120 + FR + +5C-56-ED (hex) 3pleplay Electronics Private Limited +5C56ED (base 16) 3pleplay Electronics Private Limited + Plot No 54, Eshwarapuri Colony + Hyderabad Andhra Pradesh 500083 + IN + +78-02-8F (hex) Adaptive Spectrum and Signal Alignment (ASSIA), Inc. +78028F (base 16) Adaptive Spectrum and Signal Alignment (ASSIA), Inc. + 333 Twin Dolphin Drive + Redwood City CA 94065 + US + +DC-16-A2 (hex) Medtronic Diabetes +DC16A2 (base 16) Medtronic Diabetes + 18000 Devonshire St + Northridge CA 91325 + US + +30-8C-FB (hex) Dropcam +308CFB (base 16) Dropcam + 160 Spear Street + San Francisco CA 94105 + US + +D0-EB-9E (hex) Seowoo Inc. +D0EB9E (base 16) Seowoo Inc. + #B101 Seojung B/D, 590-9 Guui-dong, Gwangjin-gu, + Seoul 143-831 + KR + +BC-CD-45 (hex) VOISMART +BCCD45 (base 16) VOISMART + VIA BENIGNO CRESPI 12 + MILANO 20159 + IT + +14-3E-60 (hex) Nokia +143E60 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +70-32-D5 (hex) Athena Wireless Communications Inc +7032D5 (base 16) Athena Wireless Communications Inc + 12425 W Bell Rd + Surprise AZ 85378 + US + +78-51-0C (hex) LiveU Ltd. +78510C (base 16) LiveU Ltd. + 5 Hagavish St. + Kfar-Saba 44641 + IL + +44-AA-E8 (hex) Nanotec Electronic GmbH & Co. KG +44AAE8 (base 16) Nanotec Electronic GmbH & Co. KG + Gewerbestrasse 11 + Landsham Bavaria 85652 + DE + +D4-28-B2 (hex) ioBridge, Inc. +D428B2 (base 16) ioBridge, Inc. + 225 Cedar Hill Street + Marlborough MA 01752 + US + +84-27-CE (hex) Corporation of the Presiding Bishop of The Church of Jesus Christ of Latter-day Saints +8427CE (base 16) Corporation of the Presiding Bishop of The Church of Jesus Christ of Latter-day Saints + Audiovisual Engineering - 2LL + Salt Lake City UT 84150 + US + +48-D8-FE (hex) ClarIDy Solutions, Inc. +48D8FE (base 16) ClarIDy Solutions, Inc. + 7F, No.9, ParkAvenue II Rd., Hsinchu Science Park, + Hsinchu 300 + TW + +D4-94-5A (hex) COSMO CO., LTD +D4945A (base 16) COSMO CO., LTD + 1-12, Higashi-Gotanda 2-chome + Shinagawa-ku Tokyo 141-0022 + JP + +30-4C-7E (hex) Panasonic Electric Works Automation Controls Techno Co.,Ltd. +304C7E (base 16) Panasonic Electric Works Automation Controls Techno Co.,Ltd. + 2-9-18 Chidori + Oota-ku Tokyo 146-8540 + JP + +5C-F2-07 (hex) Speco Technologies +5CF207 (base 16) Speco Technologies + 200 New Highway + Amityville New York 11701 + US + +B4-2A-39 (hex) ORBIT MERRET, spol. s r. o. +B42A39 (base 16) ORBIT MERRET, spol. s r. o. + Vodnanska 675/30 + Praha 198 00 + CZ + +70-E8-43 (hex) Beijing C&W Optical Communication Technology Co.,Ltd. +70E843 (base 16) Beijing C&W Optical Communication Technology Co.,Ltd. + 2/F Yufa Plaza, No.19 Xiaoying Beilu, Chaoyang District, + Beijing 100101 + CN + +2C-7E-CF (hex) Onzo Ltd +2C7ECF (base 16) Onzo Ltd + 6 Great Newport Street + London WC2H 7JB + GB + +10-37-11 (hex) Simlink AS +103711 (base 16) Simlink AS + Otto Nielsens Veg 12 + Trondheim N-7004 + NO + +50-E5-49 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +50E549 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + + Pin-Jen Taoyuan 324 + TW + +B4-B8-8D (hex) Thuh Company +B4B88D (base 16) Thuh Company + 605 Territorial Dr + Bolingbrook IL 60440 + US + +4C-73-A5 (hex) KOVE +4C73A5 (base 16) KOVE + 14 N. Peoria Street + Chicago IL 60607 + US + +70-A4-1C (hex) Advanced Wireless Dynamics S.L. +70A41C (base 16) Advanced Wireless Dynamics S.L. + Centro de Empresas UPM oficina 3 + Pozuelo de Alarcon Madrid 28223 + ES + +BC-BB-C9 (hex) Kellendonk Elektronik GmbH +BCBBC9 (base 16) Kellendonk Elektronik GmbH + Butzweilerhof Allee 4 + Cologne NRW 50829 + DE + +E4-2A-D3 (hex) Magneti Marelli S.p.A. Powertrain +E42AD3 (base 16) Magneti Marelli S.p.A. Powertrain + Via del Timavo 33 + Bologna 40128 + IT + +E8-3E-B6 (hex) RIM +E83EB6 (base 16) RIM + Phillip Street + Waterloo Ontario N2L 3W8 + CA + +BC-35-E5 (hex) Hydro Systems Company +BC35E5 (base 16) Hydro Systems Company + 3798 Round Bottom Road + Cincinnati Ohio 45244 + US + +9C-5D-95 (hex) VTC Electronics Corp. +9C5D95 (base 16) VTC Electronics Corp. + 5F,No.21,Sec.6,Zhongxiao E.Rd.,Nangang District + Taipei 11575 + TW + +B8-A8-AF (hex) Logic S.p.A. +B8A8AF (base 16) Logic S.p.A. + Via Galilei 5 + Cassina de' Pecchi MI 20060 + IT + +60-F6-73 (hex) TERUMO CORPORATION +60F673 (base 16) TERUMO CORPORATION + 1500,Inokuchi,Nakai-machi + Ashigarakami-gun Kanagawa 259-0151 + JP + +28-CC-FF (hex) Corporacion Empresarial Altra SL +28CCFF (base 16) Corporacion Empresarial Altra SL + Marie Curie 21 + Malaga 29590 + ES + +94-FD-1D (hex) WhereWhen Corp +94FD1D (base 16) WhereWhen Corp + 96A Flynn Avenue + Mountain View California 94043 + US + +4C-07-C9 (hex) COMPUTER OFFICE Co.,Ltd. +4C07C9 (base 16) COMPUTER OFFICE Co.,Ltd. + 1368-10 Muramatsu-cho + Ise-shi Mie-ken 515-0507 + JP + +F8-76-9B (hex) Neopis Co., Ltd. +F8769B (base 16) Neopis Co., Ltd. + #401 Neo bd., 196-44 Anyang7-Dong + Anyang Kyonggi-Do 430-857 + KR + +74-B0-0C (hex) Network Video Technologies, Inc +74B00C (base 16) Network Video Technologies, Inc + 4005 Bohannon Drive + Menlo Park CA 94025 + US + +E8-40-40 (hex) Cisco Systems, Inc +E84040 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D8-9D-B9 (hex) eMegatech International Corp. +D89DB9 (base 16) eMegatech International Corp. + Room 403, No.24 Wucyuan 2nd Rd., + Sinjhuang City, Taipei County, 238 + TW + +40-5A-9B (hex) ANOVO +405A9B (base 16) ANOVO + ZI de Bracheux + BEAUVAIS 60000 + FR + +E0-69-95 (hex) PEGATRON CORPORATION +E06995 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +84-DE-3D (hex) Crystal Vision Ltd +84DE3D (base 16) Crystal Vision Ltd + Lion Technology park + Whittlesford/ Cambridge Cambs CB22 4WL + GB + +D0-75-BE (hex) Reno A&E +D075BE (base 16) Reno A&E + 4655 Aircenter Circle + Reno Nevada 89502 + US + +BC-6E-76 (hex) Green Energy Options Ltd +BC6E76 (base 16) Green Energy Options Ltd + 3 St. Mary's Court, Main Street + Cambridge Cambridgeshire CB23 7QS + GB + +E8-28-D5 (hex) Cots Technology +E828D5 (base 16) Cots Technology + C-702, Bundang Techno Park, 145, + Sungnam-City Kyounggi-do 463-760 + KR + +F8-DA-F4 (hex) Taishan Online Technology Co., Ltd. +F8DAF4 (base 16) Taishan Online Technology Co., Ltd. + 4/F Fangda Building, South Area, Hi-tech Industial Park, + Shenzhen Guangdong 518057 + CN + +08-D5-C0 (hex) Seers Technology Co., Ltd +08D5C0 (base 16) Seers Technology Co., Ltd + 1210 Techcenter, SKnTechnopark, 190-1 + Seongnam-si Gyeonggi-do 462-721 + KR + +6C-33-A9 (hex) Magicjack LP +6C33A9 (base 16) Magicjack LP + 5700 Georgia Avenue + West Palm Beach FL 33405 + US + +10-8C-CF (hex) Cisco Systems, Inc +108CCF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D8-E3-AE (hex) CIRTEC MEDICAL SYSTEMS +D8E3AE (base 16) CIRTEC MEDICAL SYSTEMS + 101B Cooper Court + Los Gatos CA 95032 + US + +08-B7-EC (hex) Wireless Seismic +08B7EC (base 16) Wireless Seismic + 13100 SW Freeway + Sugar Land TX 77478 + US + +18-AF-9F (hex) DIGITRONIC Automationsanlagen GmbH +18AF9F (base 16) DIGITRONIC Automationsanlagen GmbH + Auf der Langwies 1 + Wallbach Hessen 65510 + DE + +00-B3-42 (hex) MacroSAN Technologies Co., Ltd. +00B342 (base 16) MacroSAN Technologies Co., Ltd. + Room 102, No.2 Building + Hangzhou Zhejiang 310052 + CN + +1C-F5-E7 (hex) Turtle Industry Co., Ltd. +1CF5E7 (base 16) Turtle Industry Co., Ltd. + 1-12-4 Nishineminami + Tsutiura Ibaraki 300-0842 + JP + +98-0E-E4 (hex) Private +980EE4 (base 16) Private + +44-7D-A5 (hex) VTION INFORMATION TECHNOLOGY (FUJIAN) CO.,LTD +447DA5 (base 16) VTION INFORMATION TECHNOLOGY (FUJIAN) CO.,LTD + Room 502, Wing A, World Trade Center + Beijing, + CN + +0C-CD-D3 (hex) EASTRIVER TECHNOLOGY CO., LTD. +0CCDD3 (base 16) EASTRIVER TECHNOLOGY CO., LTD. + 30 JINNIU XINCUN + DONGGUAN GUANGDONG 523010 + CN + +E4-6C-21 (hex) messMa GmbH +E46C21 (base 16) messMa GmbH + Am Stadtfeld 8 + Ixleben Sachsen-Anhalt 39167 + DE + +00-B0-33 (hex) OAO Izhevskiy radiozavod +00B033 (base 16) OAO Izhevskiy radiozavod + 19 Bazisnaya street + Izhevsk Udmurt Republic 426034 + RU + +08-17-35 (hex) Cisco Systems, Inc +081735 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C8-9C-1D (hex) Cisco Systems, Inc +C89C1D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E4-37-D7 (hex) HENRI DEPAEPE S.A.S. +E437D7 (base 16) HENRI DEPAEPE S.A.S. + 75/77 RUE DU PRE BROCHET + SANNOIS 95112 + FR + +E0-A1-D7 (hex) SFR +E0A1D7 (base 16) SFR + 40/42 Quai du point du jour + Boulogne Billancourt Hauts de Seine 92659 + FR + +94-81-A4 (hex) Azuray Technologies +9481A4 (base 16) Azuray Technologies + 7470 SW Bridgeport Rd + Durham OR 97224 + US + +BC-E0-9D (hex) Eoslink +BCE09D (base 16) Eoslink + #602, 900-1 + Anyang-City Kyonggi-Do 431-060 + KR + +9C-22-0E (hex) TASCAN Systems GmbH +9C220E (base 16) TASCAN Systems GmbH + Max-Planck-Str. 38 + Cologne Köln 50858 + DE + +7C-DD-90 (hex) Shenzhen Ogemray Technology Co., Ltd. +7CDD90 (base 16) Shenzhen Ogemray Technology Co., Ltd. + 3 Floor, 9 Building, Minxing Industrial Zone, + Shenzhen Guangdong 518131 + CN + +0C-3C-65 (hex) Dome Imaging Inc +0C3C65 (base 16) Dome Imaging Inc + 400 Fifth Av + Waltham MA 02451 + US + +C8-DF-7C (hex) Nokia Corporation +C8DF7C (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +B4-4C-C2 (hex) NR ELECTRIC CO., LTD +B44CC2 (base 16) NR ELECTRIC CO., LTD + 69,Suyuan Avenue + Nanjing Jiangsu 211102 + CN + +48-CB-6E (hex) Cello Electronics (UK) Ltd +48CB6E (base 16) Cello Electronics (UK) Ltd + Cliff Lodge + Leyburn North Yorkshire DL8 5NS + GB + +BC-43-77 (hex) Hang Zhou Huite Technology Co.,ltd. +BC4377 (base 16) Hang Zhou Huite Technology Co.,ltd. + Rm1338,Block A¬FuLi Technology Building ,No.328,WenEr Rd + Hang Zhou Zhe Jiang 310012 + CN + +CC-76-69 (hex) SEETECH +CC7669 (base 16) SEETECH + 19-15, Seoku-dong + Hwasung-si Gyeonggi-do 445-170 + KR + +AC-20-AA (hex) DMATEK Co., Ltd. +AC20AA (base 16) DMATEK Co., Ltd. + 11F.-2, No.386, Shizheng Rd., Xitun Dist., + Taichung 40757 + TW + +FC-AF-6A (hex) Qulsar Inc +FCAF6A (base 16) Qulsar Inc + Torshamnsgatan 35 + Kista SE-16440 + SE + +34-6F-92 (hex) White Rodgers Division +346F92 (base 16) White Rodgers Division + 8100 West Florissant + St. Louis MO 63136 + US + +34-BD-F9 (hex) Shanghai WDK Industrial Co.,Ltd. +34BDF9 (base 16) Shanghai WDK Industrial Co.,Ltd. + No.2100,Songzhen Road,Songjiang District + Shanghai 201606 + CN + +CC-BE-71 (hex) OptiLogix BV +CCBE71 (base 16) OptiLogix BV + Joop Geesinkweg 999 + Amsterdam NH 1096AZ + NL + +0C-46-9D (hex) MS Sedco +0C469D (base 16) MS Sedco + 8701 Castle Park Drive + Indianapolis 46256 + US + +B0-9A-E2 (hex) STEMMER IMAGING GmbH +B09AE2 (base 16) STEMMER IMAGING GmbH + Gutenbergstraße 11 + Puchheim By 82178 + DE + +14-EE-9D (hex) AirNav Systems LLC +14EE9D (base 16) AirNav Systems LLC + 4660 La Jolla Village Dr. - Suite 500 + San Diego California CA 92122 + US + +78-D0-04 (hex) Neousys Technology Inc. +78D004 (base 16) Neousys Technology Inc. + 13F.-1, NO.1, BAOSHENG RD., + YONGHE CITY TAIPEI COUNTY 23444 + TW + +88-95-B9 (hex) Unified Packet Systems Crop +8895B9 (base 16) Unified Packet Systems Crop + 1F., No32,Lane 15,SEC 6, MinQuan E Rd., + Taipei Neihu 114 + TW + +D8-FE-8F (hex) IDFone Co., Ltd. +D8FE8F (base 16) IDFone Co., Ltd. + 7F Ace techno tower 5th B/D, 197-22 + Guro-dong, Guro-gu Seoul 152-766 + KR + +88-8C-19 (hex) Brady Corp Asia Pacific Ltd +888C19 (base 16) Brady Corp Asia Pacific Ltd + 1, Kaki Bukit Crescent + 416236 + SG + +44-8C-52 (hex) KTIS CO., Ltd +448C52 (base 16) KTIS CO., Ltd + 1208ho-103dong + Ojung-Gu, Bucheon-si Gyeonggi-do 421-808 + KR + +00-6D-FB (hex) Vutrix Technologies Ltd +006DFB (base 16) Vutrix Technologies Ltd + Unit 1 Red Lodge Business Park + Weston-super-mare North Somerset BS24 7TN + GB + +84-18-88 (hex) Juniper Networks +841888 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +90-67-B5 (hex) Alcatel-Lucent +9067B5 (base 16) Alcatel-Lucent + 600-700 Mountain Ave. + Murray Hiill NJ 07974-0636 + US + +E0-F3-79 (hex) Vaddio +E0F379 (base 16) Vaddio + 9433 Science Center Drive + New Hope MN 55428 + US + +78-B6-C1 (hex) AOBO Telecom Co.,Ltd +78B6C1 (base 16) AOBO Telecom Co.,Ltd + Room1508,Jiangong Building + Hangzhou ZheJiang 310012 + CN + +08-D2-9A (hex) Proformatique +08D29A (base 16) Proformatique + 10 bis rue Lucien Voilin + Puteaux 92800 + FR + +C8-93-83 (hex) Embedded Automation, Inc. +C89383 (base 16) Embedded Automation, Inc. + 17345 Abbey Drive + Surrey BC V4N 4M3 + CA + +78-A0-51 (hex) iiNet Labs Pty Ltd +78A051 (base 16) iiNet Labs Pty Ltd + Level 1 + Subiaco WA 6008 + AU + +80-4F-58 (hex) ThinkEco, Inc. +804F58 (base 16) ThinkEco, Inc. + 303 Fifth Avenue + New York NY 10016 + US + +04-75-F5 (hex) CSST +0475F5 (base 16) CSST + Building 6, CSST industrial park, Tong fuyu Industrial zone + Shenzhen Guangdong 518107 + CN + +8C-4D-EA (hex) Cerio Corporation +8C4DEA (base 16) Cerio Corporation + 5F., No.88, Mincyuan Rd., Sindian City + Taipei County 23141 + TW + +24-BA-30 (hex) Technical Consumer Products, Inc. +24BA30 (base 16) Technical Consumer Products, Inc. + 325 Campus Drive + Aurora OH 44202 + US + +18-8E-D5 (hex) TP Vision Belgium N.V. - innovation site Brugge +188ED5 (base 16) TP Vision Belgium N.V. - innovation site Brugge + Pathoekeweg 11 + Bruges West Flanders 8000 + BE + +E8-0C-38 (hex) DAEYOUNG INFORMATION SYSTEM CO., LTD +E80C38 (base 16) DAEYOUNG INFORMATION SYSTEM CO., LTD + #826 TAMNIP-DONG, YUSEONG-GO, + DAEJON 305-510 + KR + +E0-8A-7E (hex) Exponent +E08A7E (base 16) Exponent + 149 Commonwealth Drive + Menlo Park CA 94025 + US + +A8-B0-AE (hex) LEONI +A8B0AE (base 16) LEONI + 3945 Freedom Circle + Santa Clara California 95054 + US + +E4-27-71 (hex) Smartlabs +E42771 (base 16) Smartlabs + 72, Oktyabrskaya Street + Moscow 127521 + RU + +34-DF-2A (hex) Fujikon Industrial Co.,Limited +34DF2A (base 16) Fujikon Industrial Co.,Limited + 16/F., Tower 1, Grand Central Plaza,138 Shatin Rural + 523930 + HK + +2C-DD-0C (hex) Discovergy GmbH +2CDD0C (base 16) Discovergy GmbH + Pascalstraße 15 + Aachen NRW 52076 + DE + +40-B2-C8 (hex) Nortel Networks +40B2C8 (base 16) Nortel Networks + CARRETERA BASE AEREA # 5850 + Zapopan Jalisco 44130 + MX + +70-A1-91 (hex) Trendsetter Medical, LLC +70A191 (base 16) Trendsetter Medical, LLC + 2030 Ardmore BLVD + Pittsburgh PA 15221 + US + +70-8B-78 (hex) citygrow technology co., ltd +708B78 (base 16) citygrow technology co., ltd + rm1404, blk A, ,5 - 21 Pak Tin Par Street + Tsuen Wan + HK + +64-31-7E (hex) Dexin Corporation +64317E (base 16) Dexin Corporation + 14F-8, No. 258, Lian Cheng Rd. + Chung Ho City, Taipei Hsien 235 + TW + +3C-99-F7 (hex) Lansentechnology AB +3C99F7 (base 16) Lansentechnology AB + Rörkullsvägen 4 + Halmstad 30241 + SE + +50-7D-02 (hex) BIODIT +507D02 (base 16) BIODIT + Calle Gustave Eiffel 3 + Paterna Valencia 46980 + ES + +B4-A4-E3 (hex) Cisco Systems, Inc +B4A4E3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +8C-1F-94 (hex) RF Surgical System Inc. +8C1F94 (base 16) RF Surgical System Inc. + 9740 Appaloosa Road + San Diego CA 92131 + US + +44-91-DB (hex) Shanghai Huaqin Telecom Technology Co.,Ltd +4491DB (base 16) Shanghai Huaqin Telecom Technology Co.,Ltd + No.1 Building,399 Keyuan Road, Zhangjian Hi-Tech Park, + shanghai shanghai 201203 + CN + +14-D7-6E (hex) CONCH ELECTRONIC Co.,Ltd +14D76E (base 16) CONCH ELECTRONIC Co.,Ltd + No.3 Keji 1st Load. + Tainan 70955 + TW + +AC-83-F0 (hex) ImmediaTV Corporation +AC83F0 (base 16) ImmediaTV Corporation + 2005 De La Cruz Blvd + Santa Clara California 95050 + US + +CC-6B-98 (hex) Minetec Wireless Technologies +CC6B98 (base 16) Minetec Wireless Technologies + 10 Kembla Way + Willetton WA 6155 + AU + +3C-04-BF (hex) PRAVIS SYSTEMS Co.Ltd., +3C04BF (base 16) PRAVIS SYSTEMS Co.Ltd., + 4F, 5F Jaeyoon Bld, 75-3 Yangjae-Dong, + Seoul Seocho-Gu 137-889 + KR + +94-DD-3F (hex) A+V Link Technologies, Corp. +94DD3F (base 16) A+V Link Technologies, Corp. + 5F., No.550, Xianzheng 2nd Rd. + Zhubei City Hsinchu Country 30268 + TW + +F4-42-27 (hex) S & S Research Inc. +F44227 (base 16) S & S Research Inc. + 89 Access Rd #10 + Norwood MA 02062 + US + +C8-A7-29 (hex) SYStronics Co., Ltd. +C8A729 (base 16) SYStronics Co., Ltd. + #301-1404, Buchun Techno-Park II + Buchun City Kyung gi-do 421-741 + KR + +44-54-C0 (hex) Thompson Aerospace +4454C0 (base 16) Thompson Aerospace + 18 Technology + Irvine CA 92618 + US + +C4-F4-64 (hex) Spica international +C4F464 (base 16) Spica international + Pot k sejmiscu 33 + Ljubljana 1000 + SI + +60-2A-54 (hex) CardioTek B.V. +602A54 (base 16) CardioTek B.V. + Amerikalaan 70 + Maastricht Airport Limburg 6199AE + NL + +BC-FF-AC (hex) TOPCON CORPORATION +BCFFAC (base 16) TOPCON CORPORATION + 75-1, Hasunuma-cho + Itabashi-ku TOKYO 174-8580 + JP + +44-5E-F3 (hex) Tonalite Holding B.V. +445EF3 (base 16) Tonalite Holding B.V. + Nieuw Amsterdamsestraat 40 + Emmen Drenthe 7814 VA + NL + +68-DB-96 (hex) OPWILL Technologies CO .,LTD +68DB96 (base 16) OPWILL Technologies CO .,LTD + Room 415,Digital Media Building,NO.7 Shangdi Information Road,HaiDian District, + Beijing 100085 + CN + +7C-55-E7 (hex) YSI, Inc. +7C55E7 (base 16) YSI, Inc. + 1725 Brannum Lane + Yellow Springs Ohio 45387 + US + +70-B0-8C (hex) Shenou Communication Equipment Co.,Ltd +70B08C (base 16) Shenou Communication Equipment Co.,Ltd + No.118 Middle Juguang Road, High & New Industrial Zone + Wenzhou Zhejiang 325029 + CN + +C0-3B-8F (hex) Minicom Digital Signage +C03B8F (base 16) Minicom Digital Signage + 24 Hebron Road + Jerusalem 93542 + IL + +20-FE-DB (hex) M2M Solution S.A.S. +20FEDB (base 16) M2M Solution S.A.S. + Centre d'Affaires Regus Bat.D + Mougins 06254 + FR + +0C-8D-98 (hex) TOP EIGHT IND CORP +0C8D98 (base 16) TOP EIGHT IND CORP + 8F.,No79-1 Zhouzi St., Neihu District, Taipei City (Neihu Technology Park) + Taipei 11493 + TW + +40-C7-C9 (hex) Naviit Inc. +40C7C9 (base 16) Naviit Inc. + 3058A Scott Blvd. + Santa Clara CA 95054 + US + +7C-BB-6F (hex) Cosco Electronics Co., Ltd. +7CBB6F (base 16) Cosco Electronics Co., Ltd. + #1101, ENC Dream tower, 327-27 + Seoul 153-793 + KR + +94-A7-BC (hex) BodyMedia, Inc. +94A7BC (base 16) BodyMedia, Inc. + 420 Fort Duquesne Blvd + Pittsburgh PA 15222 + US + +C8-A1-B6 (hex) Shenzhen Longway Technologies Co., Ltd +C8A1B6 (base 16) Shenzhen Longway Technologies Co., Ltd + Suite 707,Incubation Building, China Academy of Science&Tech Development, South area + Shenzhen Guangdong 518057 + CN + +A8-55-6A (hex) Pocketnet Technology Inc. +A8556A (base 16) Pocketnet Technology Inc. + Suite B, 7F., No. 550, Ruie Kwang Rd., Neihu District, + Taipei 11429 + TW + +B4-C8-10 (hex) UMPI Elettronica +B4C810 (base 16) UMPI Elettronica + Via Respighi, 15 + Cattolica 47841 + IT + +64-A2-32 (hex) OOO Samlight +64A232 (base 16) OOO Samlight + 44A, Dubninskaya str., + Moscow 127591 + RU + +64-FC-8C (hex) Zonar Systems +64FC8C (base 16) Zonar Systems + 18200 Cascade Ave South + Seattle WA 98118 + US + +D0-57-4C (hex) Cisco Systems, Inc +D0574C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F8-DA-E2 (hex) NDC Technologies +F8DAE2 (base 16) NDC Technologies + 8001 Technology Blvd + Dayton OH 45424 + US + +70-5E-AA (hex) Action Target, Inc. +705EAA (base 16) Action Target, Inc. + PO Box 636 + Provo UT 84603 + US + +34-F9-68 (hex) ATEK Products, LLC +34F968 (base 16) ATEK Products, LLC + 210 NE 10th Avenue + Brainerd MN 56401 + US + +20-B0-F7 (hex) Enclustra GmbH +20B0F7 (base 16) Enclustra GmbH + Technoparkstrasse 1 + Zurich ZH CH-8005 + CH + +54-31-31 (hex) Raster Vision Ltd +543131 (base 16) Raster Vision Ltd + Unit 1, Crundalls + Tonbridge Kent TN12 7EA + GB + +D0-E3-47 (hex) Yoga +D0E347 (base 16) Yoga + Tammsaare tee 47 + Tallinn Harjumaa 11316 + EE + +F0-ED-1E (hex) Bilkon Bilgisayar Kontrollu Cih. Im.Ltd. +F0ED1E (base 16) Bilkon Bilgisayar Kontrollu Cih. Im.Ltd. + Gersan Sanayi Sitesi 658.Sokak No:16 + ANKARA 06370 + TR + +C4-16-FA (hex) Prysm Inc +C416FA (base 16) Prysm Inc + 180 Baytech Drive + San Jose California 95134 + US + +50-6F-9A (hex) Wi-Fi Alliance +506F9A (base 16) Wi-Fi Alliance + 3925 W. Braker Lane + Austin TX 78759 + US + +84-29-14 (hex) EMPORIA TELECOM Produktions- und VertriebsgesmbH & Co KG +842914 (base 16) EMPORIA TELECOM Produktions- und VertriebsgesmbH & Co KG + Industriezeile 36, + Linz 4020 + AT + +BC-7D-D1 (hex) Radio Data Comms +BC7DD1 (base 16) Radio Data Comms + 5/20-30 Stubbs Street + Silverwater New South Wales (NSW) 2128 + AU + +58-50-76 (hex) Linear Equipamentos Eletronicos SA +585076 (base 16) Linear Equipamentos Eletronicos SA + Praca Linear 100 + Santa Rita do Sapucai MG 37540000 + BR + +F0-F9-F7 (hex) IES GmbH & Co. KG +F0F9F7 (base 16) IES GmbH & Co. KG + Darmcher Grund 22 + Meinerzhagen 58540 + DE + +38-58-0C (hex) Panaccess Systems GmbH +38580C (base 16) Panaccess Systems GmbH + Gutenbergstr. 8 + Ismaning BY 85737 + DE + +44-51-DB (hex) Raytheon BBN Technologies +4451DB (base 16) Raytheon BBN Technologies + 10 Moulton Street + Cambridge MA 02138 + US + +DC-FA-D5 (hex) STRONG Ges.m.b.H. +DCFAD5 (base 16) STRONG Ges.m.b.H. + Franz-Josefs-Kai 1 + Vienna 1010 + AT + +6C-8D-65 (hex) Wireless Glue Networks, Inc. +6C8D65 (base 16) Wireless Glue Networks, Inc. + 1601 N. Main Street, Suite 202 + Walnut Creek CA 94596 + US + +98-03-A0 (hex) ABB n.v. Power Quality Products +9803A0 (base 16) ABB n.v. Power Quality Products + 10 allée centrale + Jumet 6040 + BE + +CC-43-E3 (hex) Trump s.a. +CC43E3 (base 16) Trump s.a. + rue de la Maitrise 9 + Nivelles 1400 + BE + +F8-C0-91 (hex) Highgates Technology +F8C091 (base 16) Highgates Technology + 1415 Highgates Ave + Los Angeles CA 90042 + US + +AC-9B-84 (hex) Smak Tecnologia e Automacao +AC9B84 (base 16) Smak Tecnologia e Automacao + Av. Sto. Antonio, 201 - Bela Vista + Osasco São Paulo CEP 06086-075 + BR + +90-F2-78 (hex) Radius Gateway +90F278 (base 16) Radius Gateway + 520 E. Montford Ave + Ada OH 45810 + US + +80-66-29 (hex) Prescope Technologies CO.,LTD. +806629 (base 16) Prescope Technologies CO.,LTD. + 12F-1,No.192,Sec 2,Chung Hsin Road + Hsin Tien City Taipei County 23146 + TW + +24-1F-2C (hex) Calsys, Inc. +241F2C (base 16) Calsys, Inc. + 2700 Augustine drive, Ste145 + Santa Clara California 95054 + US + +F0-BD-F1 (hex) Sipod Inc. +F0BDF1 (base 16) Sipod Inc. + 4633 Old Ironsides Drive, #400 + Santa Clara CA 95054 + US + +64-67-07 (hex) Beijing Omnific Technology, Ltd. +646707 (base 16) Beijing Omnific Technology, Ltd. + Rm. 402, Building 1, Shui Mu Qing Hua Community + Beijing 100190 + CN + +58-FD-20 (hex) Bravida Sakerhet AB +58FD20 (base 16) Bravida Sakerhet AB + Mikrofonvagen 28 + STOCKHOLM 126 81 + SE + +AC-A0-16 (hex) Cisco Systems, Inc +ACA016 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +58-E7-47 (hex) Deltanet AG +58E747 (base 16) Deltanet AG + Riedstrasse 8 + Dietikon Zurich 8953 + CH + +40-40-22 (hex) ZIV +404022 (base 16) ZIV + Polígono Parque Tecnológico, 210 + ZAMUDIO VIZCAYA 48170 + ES + +A8-5B-B0 (hex) Shenzhen Dehoo Technology Co.,Ltd +A85BB0 (base 16) Shenzhen Dehoo Technology Co.,Ltd + 5C,Tianzhan Building Tianan Cyberpark, + ShenZhen Guang Dong 518040 + CN + +44-A6-89 (hex) PROMAX ELECTRONICA SA +44A689 (base 16) PROMAX ELECTRONICA SA + FRANCESC MORAGAS 71-75 + HOSPITALET DE LLOBREGAT BARCELONA 08907 + ES + +40-61-8E (hex) Stella-Green Co +40618E (base 16) Stella-Green Co + 1-5-16 Edobori, Nishi-ku + Osaka 550-0002 + JP + +68-E4-1F (hex) Unglaube Identech GmbH +68E41F (base 16) Unglaube Identech GmbH + An der Moosach 3a + Massenhausen Bayern 85376 + DE + +4C-60-D5 (hex) airPointe of New Hampshire +4C60D5 (base 16) airPointe of New Hampshire + 35E Industrial Way + Rochester NH 03867 + US + +88-87-17 (hex) CANON INC. +888717 (base 16) CANON INC. + 3-30-2 + Ohta-Ku Tokyo 146-8501 + JP + +6C-DC-6A (hex) Promethean Limited +6CDC6A (base 16) Promethean Limited + Activlab + Blackburn Lancashire BB1 5SN + GB + +90-55-AE (hex) Ericsson, EAB/RWI/K +9055AE (base 16) Ericsson, EAB/RWI/K + Skolgången 17 + Gävle SE-800 06 + SE + +10-10-B6 (hex) McCain Inc +1010B6 (base 16) McCain Inc + 2365 Oak Ridge Way + Vista CA 92081 + US + +00-93-63 (hex) Uni-Link Technology Co., Ltd. +009363 (base 16) Uni-Link Technology Co., Ltd. + 7-5, No.66, Sec.2, Nan-Kan Rd., Lu-Chu Hsiang,Taoyuan,Taiwan + Taoyuan Taiwan 338 + TW + +D4-82-3E (hex) Argosy Technologies, Ltd. +D4823E (base 16) Argosy Technologies, Ltd. + 73-221 Haystack Road + Palm Desert CA 92260 + US + +00-35-32 (hex) Electro-Metrics Corporation +003532 (base 16) Electro-Metrics Corporation + 231 Enterprise Road + Johnstown New York 12095 + US + +08-1F-F3 (hex) Cisco Systems, Inc +081FF3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +44-37-6F (hex) Young Electric Sign Co +44376F (base 16) Young Electric Sign Co + 1651 N 1000 W + Logan UT 84321 + US + +38-9F-83 (hex) OTN Systems N.V. +389F83 (base 16) OTN Systems N.V. + Industrielaan 17b + Olen 2250 + BE + +BC-6A-16 (hex) tdvine +BC6A16 (base 16) tdvine + 301 Maison Maru Building + Seoul 135-010 + KR + +00-3A-9D (hex) NEC Platforms, Ltd. +003A9D (base 16) NEC Platforms, Ltd. + 800 Shimomata + Kakegawa Shizuoka 436-8501 + JP + +28-CD-4C (hex) Individual Computers GmbH +28CD4C (base 16) Individual Computers GmbH + Im Zemmer 6 + Woffelsbach NRW 52152 + DE + +8C-53-F7 (hex) A&D ENGINEERING CO., LTD. +8C53F7 (base 16) A&D ENGINEERING CO., LTD. + 336-6 Dangsandong 6-ga, Yeongdeungpo-gu + Seoul 150-810 + KR + +7C-76-73 (hex) ENMAS GmbH +7C7673 (base 16) ENMAS GmbH + Holzkoppelweg 23 + Kiel Schleswig-Holstein 24251 + DE + +6C-6F-18 (hex) Stereotaxis, Inc. +6C6F18 (base 16) Stereotaxis, Inc. + 4320 Forest Park Ave + St. Louis MO 63108 + US + +84-C7-27 (hex) Gnodal Ltd +84C727 (base 16) Gnodal Ltd + 178 - 180 Hotwell Road + Bristol BS8 4RP + GB + +08-76-95 (hex) Auto Industrial Co., Ltd. +087695 (base 16) Auto Industrial Co., Ltd. + 14Floor, #235 Hanshin IT Tower, + Seoul 152-768 + KR + +AC-CE-8F (hex) HWA YAO TECHNOLOGIES CO., LTD +ACCE8F (base 16) HWA YAO TECHNOLOGIES CO., LTD + NO. 6, LN. 48, NANSING RD., + YONGKANG CITY, TAINAN COUNTY 710 + TW + +8C-92-36 (hex) Aus.Linx Technology Co., Ltd. +8C9236 (base 16) Aus.Linx Technology Co., Ltd. + 6F-2, No. 190, Sec. 2, Zhongxing Rd., Xindian Dist., + New Taipei City 23146 + TW + +10-C7-3F (hex) Midas Klark Teknik Ltd +10C73F (base 16) Midas Klark Teknik Ltd + Klark Teknik Building + Kidderminster Worcestershire DY11 7HJ + GB + +F8-91-2A (hex) GLP German Light Products GmbH +F8912A (base 16) GLP German Light Products GmbH + Im Stöckmädle 13 + Karlsbad BW 76307 + DE + +44-E4-9A (hex) OMNITRONICS PTY LTD +44E49A (base 16) OMNITRONICS PTY LTD + 27 SARICH CRT + OSBORNE PARK WA 6017 + AU + +08-F2-F4 (hex) Net One Partners Co.,Ltd. +08F2F4 (base 16) Net One Partners Co.,Ltd. + 2-8 Higashi Shinagawa 2-chome, + Tokyo 1400002 + JP + +0C-7D-7C (hex) Kexiang Information Technology Co, Ltd. +0C7D7C (base 16) Kexiang Information Technology Co, Ltd. + Room 1502, Longxi Hotel No.3788 Jiangnan Avenue. + Hangzhou Zhejiang 310053 + CN + +30-37-A6 (hex) Cisco Systems, Inc +3037A6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +DC-1D-9F (hex) U & B tech +DC1D9F (base 16) U & B tech + 2F, Daeyoung buliding, 1423-6, Kwanyang-1Dong, + Anyang-Si Gyeonggi-Do 431-061 + KR + +D8-E7-2B (hex) NetAlly +D8E72B (base 16) NetAlly + 310 Littleton Road + Westford MA 01886 + US + +78-5C-72 (hex) Hioso Technology Co., Ltd. +785C72 (base 16) Hioso Technology Co., Ltd. + 6th Floor, 12th Building, Wangtang Industrial Zone, + Shenzhen Guangdong 518055 + CN + +58-05-56 (hex) Elettronica GF S.r.L. +580556 (base 16) Elettronica GF S.r.L. + Via Vittori, 63 + FAENZA RA 48018 + IT + +B0-90-74 (hex) Fulan Electronics Limited +B09074 (base 16) Fulan Electronics Limited + Flat B&C,3/F,A1 Block, Gaoxin Cyber-Tech Zone,Nanshan + Shenzhen Guangdong 518057 + CN + +94-F6-92 (hex) Geminico co.,Ltd. +94F692 (base 16) Geminico co.,Ltd. + #102-1112, Chunui-Technopark, 200-1, + Bucheon-city Kyunggi-do 420-857 + KR + +68-EF-BD (hex) Cisco Systems, Inc +68EFBD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F0-24-08 (hex) Talaris (Sweden) AB +F02408 (base 16) Talaris (Sweden) AB + Taljs Sodra Industriomrade + Flen 64284 + SE + +80-81-A5 (hex) TONGQING COMMUNICATION EQUIPMENT (SHENZHEN) Co.,Ltd +8081A5 (base 16) TONGQING COMMUNICATION EQUIPMENT (SHENZHEN) Co.,Ltd + Tongqing Industry Park,jiuwei,xixiang Town,Baoan District, + Shenzhen Guangdong 518126 + CN + +B4-82-FE (hex) ASKEY COMPUTER CORP +B482FE (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +30-7C-30 (hex) RIM +307C30 (base 16) RIM + 295 Phillip Street + Waterloo Ontario N2L 3W8 + CA + +BC-4E-3C (hex) CORE STAFF CO., LTD. +BC4E3C (base 16) CORE STAFF CO., LTD. + Shin-osaka Oriental Bldg. 14F, 7-1-26 Nishinakajima + Yodogawa-ku Osaka 532-0011 + JP + +50-2A-8B (hex) Telekom Research and Development Sdn Bhd +502A8B (base 16) Telekom Research and Development Sdn Bhd + TMRND Innovation Centre + Cyberjaya Selangor 63000 + MY + +EC-43-E6 (hex) AWCER Ltd. +EC43E6 (base 16) AWCER Ltd. + 100-413 Bucheon Technopark + Bucheon-city Gyeonggi-do 421-741 + KR + +78-12-B8 (hex) ORANTEK LIMITED +7812B8 (base 16) ORANTEK LIMITED + 5/F, Building E, Dakan Tech Park, Dakan village, Xili Town, Nanshan District, Shenzhen, China + Shenzhen Guangdong 518000 + CN + +98-BC-99 (hex) Edeltech Co.,Ltd. +98BC99 (base 16) Edeltech Co.,Ltd. + #302 Jamae Bldg, 1010-28, Sadang-dong, Dongjak=gu + Seoul 156-824 + KR + +F0-2F-D8 (hex) Bi2-Vision +F02FD8 (base 16) Bi2-Vision + 16-504, 21-ban, Shimomaruko 4-chome, Oota-ku + Tokyo 146-0092 + JP + +54-42-49 (hex) Sony Corporation +544249 (base 16) Sony Corporation + Gotenyama Tec 5-1-2 + Tokyo Shinagawa-ku 141-0001 + JP + +90-47-16 (hex) RORZE CORPORATION +904716 (base 16) RORZE CORPORATION + 1588-2 Michinoue, Kannabe-cho + Fukuyama Hiroshima 720-2104 + JP + +10-44-5A (hex) Shaanxi Hitech Electronic Co., LTD +10445A (base 16) Shaanxi Hitech Electronic Co., LTD + 35 Tuanjienan Rode, + Xian Shaanxi 710075 + CN + +F4-76-26 (hex) Viltechmeda UAB +F47626 (base 16) Viltechmeda UAB + Kalvariju 125 + Vilnius LT-08221 + LT + +0C-17-F1 (hex) TELECSYS +0C17F1 (base 16) TELECSYS + 31 chemin du fief aux pretres + L'ORBRIE 85200 + FR + +00-3A-9B (hex) Cisco Systems, Inc +003A9B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +2C-34-27 (hex) ERCO & GENER +2C3427 (base 16) ERCO & GENER + ZI de SAINT LAMBERT DES LEVEES + SAUMUR 49412 + FR + +80-91-2A (hex) Lih Rong electronic Enterprise Co., Ltd. +80912A (base 16) Lih Rong electronic Enterprise Co., Ltd. + 2F, No. 2, Lane 387, Hsin Shu Road + Hsin Chuang Taipei 242 + TW + +7C-2F-80 (hex) Gigaset Communications GmbH +7C2F80 (base 16) Gigaset Communications GmbH + SCM PE 2 + Bocholt 46395 + DE + +10-B7-F6 (hex) Plastoform Industries Ltd. +10B7F6 (base 16) Plastoform Industries Ltd. + Units 1506A - 1512, Mita Centre, + Kwai Chung, + HK + +44-8E-81 (hex) VIG +448E81 (base 16) VIG + 705 Hanshin IT Tower, 60-18, Kasan-dong, Geumcheon-gu + Seoul KSXX0022 + KR + +88-94-F9 (hex) Gemicom Technology, Inc. +8894F9 (base 16) Gemicom Technology, Inc. + 16F, Building B, No. 98, Sec 1, Hsin-Tai-Wu Rd. + Hsi-Chih city Taipei 22102 + TW + +50-2A-7E (hex) Smart electronic GmbH +502A7E (base 16) Smart electronic GmbH + Industrie Str. 29 + St. Georgen 78112 + DE + +5C-87-78 (hex) Cybertelbridge co.,ltd +5C8778 (base 16) Cybertelbridge co.,ltd + #901 Acehighend tower 2 + Seoul 152-050 + KR + +38-BB-23 (hex) OzVision America LLC +38BB23 (base 16) OzVision America LLC + 400 West Cummings Park + Woburn MA 01801 + US + +0C-84-11 (hex) A.O. Smith Water Products +0C8411 (base 16) A.O. Smith Water Products + 25589 Hwy 1 + McBee SC 29101 + US + +E0-AB-FE (hex) Orb Networks, Inc. +E0ABFE (base 16) Orb Networks, Inc. + 428 13th Street + Oakland CA 94612 + US + +44-83-12 (hex) Star-Net +448312 (base 16) Star-Net + Egoz 64 + Kiryat Byalik Israel 27000 + IL + +A0-5D-E7 (hex) DIRECTV, Inc. +A05DE7 (base 16) DIRECTV, Inc. + 2230 E. Imperial Hwy + El Segundo CA 90245 + US + +08-76-18 (hex) ViE Technologies Sdn. Bhd. +087618 (base 16) ViE Technologies Sdn. Bhd. + no. 85-A, Lintang Bayan Lepas 11, + Bayan Lepas Penang 11900 + MY + +D0-E4-0B (hex) Wearable Inc. +D0E40B (base 16) Wearable Inc. + 3825 Charles Dr. + Northbrook IL 60062 + US + +74-7E-1A (hex) Red Embedded Design Limited +747E1A (base 16) Red Embedded Design Limited + The Wave + Shipley West Yorkshire BD17 7Du + GB + +14-A8-6B (hex) ShenZhen Telacom Science&Technology Co., Ltd +14A86B (base 16) ShenZhen Telacom Science&Technology Co., Ltd + B1701/1705 Pavilion, Hua Qiang Bei RD4002, Futian District + ShenZhen GuangDong 518028 + CN + +0C-C3-A7 (hex) Meritec +0CC3A7 (base 16) Meritec + P.O. Box 8003 + Painesville Ohio 44077 + US + +DC-E2-AC (hex) Lumens Digital Optics Inc. +DCE2AC (base 16) Lumens Digital Optics Inc. + 5F, No.35, Sintai Rd., Jhubei City + Jhubei HsinChu 302 + TW + +98-D8-8C (hex) Nortel Networks +98D88C (base 16) Nortel Networks + CARRETERA BASE AEREA # 5850 + Zapopan Jalisco 44130 + MX + +78-19-2E (hex) NASCENT Technology +78192E (base 16) NASCENT Technology + 2744 Yorkmont RD + Charlotte NC 28208 + US + +48-EB-30 (hex) ETERNA TECHNOLOGY, INC. +48EB30 (base 16) ETERNA TECHNOLOGY, INC. + 3939 veselich ave + los angeles california 90039 + US + +4C-32-2D (hex) TELEDATA NETWORKS +4C322D (base 16) TELEDATA NETWORKS + 10 Hasadnaot Street + HERZLIYA 46120 + IL + +AC-86-7E (hex) Create New Technology (HK) Limited Company +AC867E (base 16) Create New Technology (HK) Limited Company + Rm B 10/F JinFeng Building,1001 ShangBu South Road,FuTian District + Shen Zhen Guang Dong 518031 + CN + +8C-59-8B (hex) C Technologies AB +8C598B (base 16) C Technologies AB + Traktorvägen 11 + Lund Skåne 226 60 + SE + +D4-4C-A7 (hex) Informtekhnika & Communication, LLC +D44CA7 (base 16) Informtekhnika & Communication, LLC + 1, build. 2/1, Verhnaya + Moscow 107140 + RU + +A8-C2-22 (hex) TM-Research Inc. +A8C222 (base 16) TM-Research Inc. + Hiyoshi Honcho 1-15-4 + Yokohama Kanagawa 223-0062 + JP + +00-3D-41 (hex) Hatteland Computer AS +003D41 (base 16) Hatteland Computer AS + Aamsosen + Nedre Vats Rogaland 5578 + NO + +CC-50-76 (hex) Ocom Communications, Inc. +CC5076 (base 16) Ocom Communications, Inc. + 13F-6, No. 1, Bao Sheng Rd., + Yong Ho City 234 + TW + +4C-C4-52 (hex) Shang Hai Tyd. Electon Technology Ltd. +4CC452 (base 16) Shang Hai Tyd. Electon Technology Ltd. + Room No.5,N0.396,GuiLin Road, + Shang Hai 200233 + US + +7C-CB-0D (hex) Antaira Technologies, LLC +7CCB0D (base 16) Antaira Technologies, LLC + 445 Capricorn St. + Brea California 92821 + US + +C0-1E-9B (hex) Pixavi AS +C01E9B (base 16) Pixavi AS + Dusavikveien 39 + Stavanger 4003 + NO + +80-3B-9A (hex) ghe-ces electronic ag +803B9A (base 16) ghe-ces electronic ag + Hoemelstraße 17 + Wald ZH 8636 + CH + +74-32-56 (hex) NT-ware Systemprg GmbH +743256 (base 16) NT-ware Systemprg GmbH + Niedersachsenstrasse 6 + Bad Iburg NDS 49186 + DE + +C4-E1-7C (hex) U2S co. +C4E17C (base 16) U2S co. + 104-706, SK Ventium Building, 522, Dangjeong-Dong + Gunpo-si Geonggi-do 435-776 + KR + +20-BF-DB (hex) DVL +20BFDB (base 16) DVL + 21 Gradinilor Str + Chisinau MD2001 + MD + +20-41-5A (hex) Smarteh d.o.o. +20415A (base 16) Smarteh d.o.o. + Trg tigrovcev 1 + Tolmin 5220 + SI + +A4-DA-3F (hex) Bionics Corp. +A4DA3F (base 16) Bionics Corp. + 1406 Masters Tower + Seoul 121-748 + KR + +A0-40-25 (hex) Actioncable, Inc. +A04025 (base 16) Actioncable, Inc. + 998 Westlynn Way + Cupertino CA 95014 + US + +4C-4B-68 (hex) Mobile Device, Inc. +4C4B68 (base 16) Mobile Device, Inc. + 8F-1, No. 145, Sianjheng 9th Rd., + Jhubei City, Hsinchu County 30251 + TW + +20-12-57 (hex) Most Lucky Trading Ltd +201257 (base 16) Most Lucky Trading Ltd + Room403 No.506 Zhongshan South 2nd Road,Xuhui District + Shanghai 200032 + CN + +E8-DA-AA (hex) VideoHome Technology Corp. +E8DAAA (base 16) VideoHome Technology Corp. + 4F-1, No. 192, Da Tung Rd., Sec. 3, Hsichih, + Taipei Hsien 221 + TW + +64-7D-81 (hex) YOKOTA INDUSTRIAL CO,.LTD +647D81 (base 16) YOKOTA INDUSTRIAL CO,.LTD + 5-55 NISHIIWATA + HIGASHI OSAKA-CITY OSAKA 578-0947 + JP + +7C-CF-CF (hex) Shanghai SEARI Intelligent System Co., Ltd +7CCFCF (base 16) Shanghai SEARI Intelligent System Co., Ltd + No.505 Wuning Road, Putuo District + Shanghai 200063 + CN + +68-AA-D2 (hex) DATECS LTD., +68AAD2 (base 16) DATECS LTD., + BUL. TSARIGRADSKO SHOSSE 115A + SOFIA 1784 + BG + +A4-DE-50 (hex) Total Walther GmbH +A4DE50 (base 16) Total Walther GmbH + Frankfurter Ring 17 + Munich 80807 + DE + +1C-F0-61 (hex) SCAPS GmbH +1CF061 (base 16) SCAPS GmbH + Bahnhofstraße 17 + Deisenhofen Bavaria 82041 + DE + +A8-93-E6 (hex) JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LTD +A893E6 (base 16) JIANGXI JINGGANGSHAN CKING COMMUNICATION TECHNOLOGY CO.,LTD + 5F,301building,Tairan High-tech park, Chegongmiao,Futian zone, + SHENZHEN GUANGDONG 518000 + CN + +C4-AA-A1 (hex) SUMMIT DEVELOPMENT, spol.s r.o. +C4AAA1 (base 16) SUMMIT DEVELOPMENT, spol.s r.o. + K Vodoteci 197 + Orech Praha-zapad 252 25 + CZ + +30-32-D4 (hex) Hanilstm Co., Ltd. +3032D4 (base 16) Hanilstm Co., Ltd. + 138-6, Sangdaewon-dong Jungwon-gu + Seongnam Kyonggi-do 462-120 + KR + +E0-64-BB (hex) DigiView S.r.l. +E064BB (base 16) DigiView S.r.l. + Via Senigallia 18/2 + Milano 20161 + IT + +DC-33-50 (hex) TechSAT GmbH +DC3350 (base 16) TechSAT GmbH + Gruber Str. 46c + Poing BY 85586 + DE + +F0-BC-C8 (hex) MaxID (Pty) Ltd +F0BCC8 (base 16) MaxID (Pty) Ltd + 43 Homestead Road + Johannesburg Gauteng 2128 + ZA + +24-82-8A (hex) Prowave Technologies Ltd. +24828A (base 16) Prowave Technologies Ltd. + 2F,No.879-16,Zhongjiang Road + Shanghai 200333 + CN + +68-CC-9C (hex) Mine Site Technologies +68CC9C (base 16) Mine Site Technologies + 113 Wicks Road + North Ryde NSW 2113 + AU + +14-6E-0A (hex) Private +146E0A (base 16) Private + +0C-E7-09 (hex) Fox Crypto B.V. +0CE709 (base 16) Fox Crypto B.V. + P.O. box 638 + Delft ZH 2600 AP + NL + +B4-B5-AF (hex) Minsung Electronics +B4B5AF (base 16) Minsung Electronics + Mega-valley #620 + Anyang-si Kyeonggi-do 431-767 + KR + +04-B3-B6 (hex) Seamap (UK) Ltd +04B3B6 (base 16) Seamap (UK) Ltd + Unit 34, The Maltings + Shepton Mallet Somerset BA4 5QE + GB + +00-27-0B (hex) Adura Technologies +00270B (base 16) Adura Technologies + 28 Second Street + San Francisco CA 94105 + US + +00-27-0D (hex) Cisco Systems, Inc +00270D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-27-1B (hex) Alec Sicherheitssysteme GmbH +00271B (base 16) Alec Sicherheitssysteme GmbH + Friedrich-Hoelscher-Strasse 367 + Dortmund 44328 + DE + +00-27-18 (hex) Suzhou NEW SEAUNION Video Technology Co.,Ltd +002718 (base 16) Suzhou NEW SEAUNION Video Technology Co.,Ltd + 383 Jingmao Road, Industry Park + Suzhou Jiangsu 215021 + CN + +6C-0F-6A (hex) JDC Tech Co., Ltd. +6C0F6A (base 16) JDC Tech Co., Ltd. + 370-12 Daemyung-ri Daegot-myun + Kimpo-si Kyunggi-do 410-853 + KR + +04-B4-66 (hex) BSP Co., Ltd. +04B466 (base 16) BSP Co., Ltd. + 162-10 + Gumi Gyeungsangbuk Do 730-902 + KR + +D8-D6-7E (hex) GSK CNC EQUIPMENT CO.,LTD +D8D67E (base 16) GSK CNC EQUIPMENT CO.,LTD + No.7,1st Street,Luochong North Road,Luochongwei,No.7,1st Street,Luochong North Road,Luochongwei,No.7,1st Street,Luochong North Road,Luochongwei, + Guangzhou Guangdong 510165 + CN + +00-26-AE (hex) Wireless Measurement Ltd +0026AE (base 16) Wireless Measurement Ltd + The Crescent + EMSWORTH PO10 8JS + GB + +00-26-B1 (hex) Navis Auto Motive Systems, Inc. +0026B1 (base 16) Navis Auto Motive Systems, Inc. + Busan, Centumjungang-ro 78, Centum Greentower 8th floor + BUSAN 612-822 + KR + +00-26-AA (hex) Kenmec Mechanical Engineering Co., Ltd. +0026AA (base 16) Kenmec Mechanical Engineering Co., Ltd. + 3F, No. 97, Sec.2 Nan-Kang Rd., + Taipei 11578 + TW + +00-26-D2 (hex) Pcube Systems, Inc. +0026D2 (base 16) Pcube Systems, Inc. + 1857 O'Toole Lane + San Jose CA 95131 + US + +00-26-CD (hex) PurpleComm, Inc. +0026CD (base 16) PurpleComm, Inc. + 2620 Augustine Dr., Ste. 100 + Santa Clara CA 95054 + US + +00-27-07 (hex) Lift Complex DS, JSC +002707 (base 16) Lift Complex DS, JSC + mikrorayon Gorsky, 6 + Novosibirsk 630073 + RU + +00-26-D7 (hex) KM Electornic Technology Co., Ltd. +0026D7 (base 16) KM Electornic Technology Co., Ltd. + 5F, NO.3 Building, NO.118 Rd. Baoan District, Shenzhen China + Shenzhen Guangdong 518101 + CN + +00-26-D0 (hex) Semihalf +0026D0 (base 16) Semihalf + ul. Wadowicka 8A + Krakow ... 30-415 + PL + +00-26-FE (hex) MKD Technology Inc. +0026FE (base 16) MKD Technology Inc. + R.B8, No.1 Lising 1st Rd., + Hsinchu 30078 + TW + +00-26-A0 (hex) moblic +0026A0 (base 16) moblic + 7F, 271-1, Seohyeon-dong, Bundang-gu + Seongnam-si Kyeonggi-do 463-824 + KR + +00-26-E5 (hex) AEG Power Solutions +0026E5 (base 16) AEG Power Solutions + Emil Siepmannstraße 32 + Warstein NRW 59581 + DE + +00-26-E3 (hex) DTI +0026E3 (base 16) DTI + Rue de la gare, 35 + NANINNE NAMUR 5100 + BE + +00-26-BC (hex) General Jack Technology Ltd. +0026BC (base 16) General Jack Technology Ltd. + The Area of Administration of Lian Bei, + Dong Guan Guang Dong 523580 + CN + +00-26-96 (hex) NOOLIX Co., Ltd +002696 (base 16) NOOLIX Co., Ltd + DAECHANG B/D 3F, 8-2 SUNAE-DONG + SUNGNAM-SI KYUNGGI-DO 463-825 + KR + +00-26-9A (hex) Carina System Co., Ltd. +00269A (base 16) Carina System Co., Ltd. + 2-2-11 Kotonoo-cho + Kobe Hyogo 651-0094 + JP + +00-26-95 (hex) ZT Group Int'l Inc +002695 (base 16) ZT Group Int'l Inc + 350 Meadowlands Parkway + Secaucus NJ 07094 + US + +00-26-93 (hex) QVidium Technologies, Inc. +002693 (base 16) QVidium Technologies, Inc. + 12989 Chaparral Ridge Rd + San Diego CA 92130 + US + +00-26-65 (hex) ProtectedLogic Corporation +002665 (base 16) ProtectedLogic Corporation + PO Box 67707 + Albuquerque NM 87193 + US + +00-26-60 (hex) Logiways +002660 (base 16) Logiways + 24/26 rue Louis ARMAND + PARIS 75015 + FR + +00-26-70 (hex) Cinch Connectors +002670 (base 16) Cinch Connectors + 1700 Finley Road + Lombard IL 60148 + US + +00-26-71 (hex) AUTOVISION Co., Ltd +002671 (base 16) AUTOVISION Co., Ltd + Shinsegae YBS Bldg. 102 + Seongdong-gu Seoul 133-847 + KR + +00-26-48 (hex) Emitech Corp. +002648 (base 16) Emitech Corp. + No. 156-5A, ChengGong 1st St., + Jhubei City Hsinchu County 302 + TW + +00-26-45 (hex) Circontrol S.A. +002645 (base 16) Circontrol S.A. + Lepant 43 + Terrassa Barcelona 08223 + ES + +00-26-3E (hex) Trapeze Networks +00263E (base 16) Trapeze Networks + 5753 West Las Positas Blvd. + Pleasanton California 94588 + US + +00-26-3C (hex) Bachmann Technology GmbH & Co. KG +00263C (base 16) Bachmann Technology GmbH & Co. KG + Ernsthaldenstrasse 33 + Stuttgart BW 70565 + DE + +00-26-3D (hex) MIA Corporation +00263D (base 16) MIA Corporation + 1-3-15 Yoshino-cho, Minami-ku + Yokohama Kanagawa 232-0014 + JP + +00-26-78 (hex) Logic Instrument SA +002678 (base 16) Logic Instrument SA + 43, Avenue de l'Europe + Domont 95330 + FR + +00-26-77 (hex) DEIF A/S +002677 (base 16) DEIF A/S + Frisenborgvej 33 + Skive 7800 + DK + +00-26-8E (hex) Alta Solutions, Inc. +00268E (base 16) Alta Solutions, Inc. + 11305 Rancho Bernardo Road + San Diego CA 92127 + US + +00-26-88 (hex) Juniper Networks +002688 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-25-DA (hex) Secura Key +0025DA (base 16) Secura Key + 20301 Nordhoff St. + Chatsworth CA 91311 + US + +00-25-DB (hex) ATI Electronics(Shenzhen) Co., LTD +0025DB (base 16) ATI Electronics(Shenzhen) Co., LTD + 2F,1st Buliding,Tangyanshan Industrial Park, + Shenzhen Guangdong 518108 + CN + +00-25-D5 (hex) Robonica (Pty) Ltd +0025D5 (base 16) Robonica (Pty) Ltd + 41 Park Avenue North + Centurion Gauteng 0046 + ZA + +00-25-E2 (hex) Everspring Industry Co., Ltd. +0025E2 (base 16) Everspring Industry Co., Ltd. + 7F., No. 609, Sec 1, Wanshou Rd., + Gueishan Township Taoyuan County 333 + TW + +00-25-E1 (hex) SHANGHAI SEEYOO ELECTRONIC & TECHNOLOGY CO., LTD +0025E1 (base 16) SHANGHAI SEEYOO ELECTRONIC & TECHNOLOGY CO., LTD + RM701,XIN'AN BUILDING,99 TIANZHOU RD,XUHUI DISTRICT,SHANGHAI + SHANGHAI 200233 + CN + +00-26-0E (hex) Ablaze Systems, LLC +00260E (base 16) Ablaze Systems, LLC + 523 West Valley Road + Wayne Pennsylvania 19087 + US + +00-26-10 (hex) Apacewave Technologies +002610 (base 16) Apacewave Technologies + 48389 Fremont Blvd, STE#100 + Fremont CA 94538 + US + +00-26-0D (hex) Mercury Systems, Inc. +00260D (base 16) Mercury Systems, Inc. + 26 Hampshire Dr + Hudson NH 03051 + US + +00-26-0A (hex) Cisco Systems, Inc +00260A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-26-32 (hex) Instrumentation Technologies d.d. +002632 (base 16) Instrumentation Technologies d.d. + Velika pot 22 + Solkan Nova Gorica 5250 + SI + +00-26-2E (hex) Chengdu Jiuzhou Electronic Technology Inc +00262E (base 16) Chengdu Jiuzhou Electronic Technology Inc + A2 Building,Tianfu Software Park + Chengdu Sichuan 610041 + CN + +00-26-2C (hex) IKT Advanced Technologies s.r.o. +00262C (base 16) IKT Advanced Technologies s.r.o. + Piseckeho 334/19 + Praha 5 15000 + CZ + +00-26-29 (hex) Juphoon System Software Inc. +002629 (base 16) Juphoon System Software Inc. + Room 910,Building 2 + Ningbo Zhejiang 315041 + CN + +00-26-25 (hex) MediaSputnik +002625 (base 16) MediaSputnik + Yaroslavskoe shosse, 19, + Moscow 129337 + RU + +00-26-26 (hex) Geophysical Survey Systems, Inc. +002626 (base 16) Geophysical Survey Systems, Inc. + 12 Industrial Way + Salem NH 03079 + US + +00-25-CC (hex) Mobile Communications Korea Incorporated +0025CC (base 16) Mobile Communications Korea Incorporated + 1011-1012, Suwon High Venture Valley, + Suwon-si, Gyeonggi-do, 441-360 + KR + +00-25-F9 (hex) GMK electronic design GmbH +0025F9 (base 16) GMK electronic design GmbH + Daimlerstraße 8 + Wernberg-Koeblitz Bavaria D-92533 + DE + +00-25-F7 (hex) Ansaldo STS USA +0025F7 (base 16) Ansaldo STS USA + 1000 Technology Drive + Pittsburgh PA 15219 + US + +00-26-1B (hex) LAUREL BANK MACHINES CO., LTD. +00261B (base 16) LAUREL BANK MACHINES CO., LTD. + 12-6 + Kita-Ku Tokyo 114-0013 + JP + +00-26-14 (hex) KTNF +002614 (base 16) KTNF + 204,Daeryungtechnotown1,327,Gasan-Dong, + Seoul 153-771 + KR + +00-26-03 (hex) Shenzhen Wistar Technology Co., Ltd +002603 (base 16) Shenzhen Wistar Technology Co., Ltd + Rm919, Science &Technology Service Center + Shenzhen Guangdong 518000 + CN + +00-25-A6 (hex) Central Network Solution Co., Ltd. +0025A6 (base 16) Central Network Solution Co., Ltd. + 584-1, Pajang-Dong, JangAn-Gu + Suwon-Si, Kyunggi-Do 440-854 + KR + +00-25-AA (hex) Beijing Soul Technology Co.,Ltd. +0025AA (base 16) Beijing Soul Technology Co.,Ltd. + Room 606,Xinzheng Office Building + BEIJING 100089 + CN + +00-25-88 (hex) Genie Industries, Inc. +002588 (base 16) Genie Industries, Inc. + 18620 NE 67th Ct + Redmond WA 98052 + US + +00-25-80 (hex) Equipson S.A. +002580 (base 16) Equipson S.A. + Poligono Ind. L´Alteró + Silla Valencia 46460 + ES + +00-25-BD (hex) Italdata Ingegneria dell'Idea S.p.A. +0025BD (base 16) Italdata Ingegneria dell'Idea S.p.A. + viale Eroi di Cefalonia 123 + Roma 00128 + IT + +00-25-B7 (hex) Costar electronics, inc., +0025B7 (base 16) Costar electronics, inc., + 3fl,-1 no 13,lane 120,nei-hu road sec.1, + Taipei 114 + TW + +00-25-7D (hex) PointRed Telecom Private Ltd. +00257D (base 16) PointRed Telecom Private Ltd. + 15F - 5., No. 1071, Zhongzheng Road, + Taoyuan City 330 330 + TW + +00-25-A2 (hex) Alta Definicion LINCEO S.L. +0025A2 (base 16) Alta Definicion LINCEO S.L. + Maria de Luna 11, nave 4 + Zaragoza Es-50018 + ES + +00-25-6D (hex) Broadband Forum +00256D (base 16) Broadband Forum + 48377 Fremont Boulevard + Fremont CA 94538 + US + +00-25-6C (hex) Azimut Production Association JSC +00256C (base 16) Azimut Production Association JSC + 2-B Ataeva Street + Makhachkala Dagestan 367005 + RU + +00-25-63 (hex) Luxtera Inc +002563 (base 16) Luxtera Inc + 2320. Camino Vida Roble + Carlsbad CA 92011 + US + +00-25-93 (hex) DatNet Informatikai Kft. +002593 (base 16) DatNet Informatikai Kft. + Hétvezér u. 5. + Szigetszentmiklós Pest megye 2310 + HU + +00-25-8E (hex) The Weather Channel +00258E (base 16) The Weather Channel + Mail Stop 500 + Atlanta GA 30339 + US + +00-25-A3 (hex) Trimax Wireless, Inc. +0025A3 (base 16) Trimax Wireless, Inc. + 2675 S Horseshoe Dr + Naples FL 34104 + US + +00-25-9C (hex) Cisco-Linksys, LLC +00259C (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +00-25-C8 (hex) S-Access GmbH +0025C8 (base 16) S-Access GmbH + Oberhausenstrasse 47 + Wettswil a/A Zuerich 8907 + CH + +00-25-C0 (hex) ZillionTV Corporation +0025C0 (base 16) ZillionTV Corporation + 1170 Kifer Road + Sunnyvale CA 94086 + US + +00-25-1B (hex) Philips CareServant +00251B (base 16) Philips CareServant + High Tech Campus 27 + Eindhoven Noord-Brabant 5656 AE + NL + +00-25-18 (hex) Power PLUS Communications AG +002518 (base 16) Power PLUS Communications AG + Am Exerzierplatz 2 + Mannheim Baden Wuerttemberg 68167 + DE + +00-25-15 (hex) SFR +002515 (base 16) SFR + 42 Quai du point du jour + Boulogne billancourt . 92659 + FR + +00-25-0D (hex) GZT Telkom-Telmor sp. z o.o. +00250D (base 16) GZT Telkom-Telmor sp. z o.o. + Mickiewicza 5/7 + Gdansk pomorskie 80-425 + PL + +00-25-0E (hex) gt german telematics gmbh +00250E (base 16) gt german telematics gmbh + Rankestrasse 26 + Berlin D-10789 + DE + +00-25-31 (hex) Cloud Engines, Inc. +002531 (base 16) Cloud Engines, Inc. + 857 Montgomery Street + San Francisco CA 94133 + US + +00-25-2D (hex) Kiryung Electronics +00252D (base 16) Kiryung Electronics + Kiryung Bldg. 686-70, Sindaebang-dong + Seoul 156-010 + KR + +00-25-45 (hex) Cisco Systems, Inc +002545 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-25-42 (hex) Pittasoft +002542 (base 16) Pittasoft + #913 Daeryung Techno Town 8th 481-11ga + Geumcheon-gu Seoul 153-775 + KR + +00-25-36 (hex) Oki Electric Industry Co., Ltd. +002536 (base 16) Oki Electric Industry Co., Ltd. + 1-16-8 Chuou + Warabi-shi Saitama 335-8510 + JP + +00-25-41 (hex) Maquet Critical Care AB +002541 (base 16) Maquet Critical Care AB + Röntgenvägen 2 + Solna SE-171 95 + SE + +00-25-2B (hex) Stirling Energy Systems +00252B (base 16) Stirling Energy Systems + Sandia National Labs - NSTTF + Albuquerque NM 87185-1127 + US + +00-25-24 (hex) Lightcomm Technology Co., Ltd +002524 (base 16) Lightcomm Technology Co., Ltd + 9/F.,Hi-Tech Venture Park Tower A, + ShenZhen GuangDong 518040 + CN + +00-25-4E (hex) Vertex Wireless Co., Ltd. +00254E (base 16) Vertex Wireless Co., Ltd. + 5F, Seohyeon Plaza, 254-5, Seohyeon-dong, Bundang-gu + Seongnam-si Gyeonggi-do 463-824 + KR + +00-25-46 (hex) Cisco Systems, Inc +002546 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-25-22 (hex) ASRock Incorporation +002522 (base 16) ASRock Incorporation + 2F., No. 37, Sec. 2, Jhongyang S. Rd., Beitou District, + Taipei 112 + TW + +00-25-60 (hex) Ibridge Networks & Communications Ltd. +002560 (base 16) Ibridge Networks & Communications Ltd. + 28,Bedford Road East Ham + London E6 2NN + GB + +00-24-B8 (hex) free alliance sdn bhd +0024B8 (base 16) free alliance sdn bhd + B-3-2 Plaza Damas + Kuala Lumpur WP 50480 + MY + +00-24-B3 (hex) Graf-Syteco GmbH & Co. KG +0024B3 (base 16) Graf-Syteco GmbH & Co. KG + Kaiserstraße 18 + Tuningen Baden-Württemberg 78609 + DE + +00-24-F6 (hex) MIYOSHI ELECTRONICS CORPORATION +0024F6 (base 16) MIYOSHI ELECTRONICS CORPORATION + 3-13-21 KUSHIRO + KAWANISHI-CITY HYOGO-PREF. 666-0024 + JP + +00-24-F0 (hex) Seanodes +0024F0 (base 16) Seanodes + Batiment Platon + Colomiers 31770 + FR + +00-24-CB (hex) Autonet Mobile +0024CB (base 16) Autonet Mobile + 2235 Mercury Way Ste. 145 + Santa Rosa CA 95407 + US + +00-24-D1 (hex) Thomson Inc. +0024D1 (base 16) Thomson Inc. + 101 West 103rd Street + Indianapolis IN 46290 + US + +00-24-C9 (hex) Broadband Solutions Group +0024C9 (base 16) Broadband Solutions Group + 1101 Marina Village Parkway + Alameda CA 94501 + US + +00-24-CA (hex) Tobii Technology AB +0024CA (base 16) Tobii Technology AB + Karlsrovägen 2D + Danderyd 18253 + SE + +00-25-08 (hex) Maquet Cardiopulmonary AG +002508 (base 16) Maquet Cardiopulmonary AG + Hechinger Strasse 38 + Hirrlingen 72145 + DE + +00-24-FC (hex) QuoPin Co., Ltd. +0024FC (base 16) QuoPin Co., Ltd. + #109, R&D Center for Advanced Technology 68 Yatap-dong Bundang-gu + Seongnam Kyungki-do 463-816 + KR + +00-24-FB (hex) Private +0024FB (base 16) Private + +00-24-FA (hex) Hilger u. Kern GMBH +0024FA (base 16) Hilger u. Kern GMBH + Kaefertaler Strasse 253-255 + Mannheim Baden-Württemberg 68167 + DE + +00-24-D0 (hex) Shenzhen SOGOOD Industry CO.,LTD. +0024D0 (base 16) Shenzhen SOGOOD Industry CO.,LTD. + SOGOOD Science Park,Aviation Road,XiXiang Town,Bao'an District, + Shenzhen Guangzhou 518102 + CN + +00-24-CC (hex) Fascinations Toys and Gifts, Inc. +0024CC (base 16) Fascinations Toys and Gifts, Inc. + 19224 Des Moines Way S + Seattle Washington 98148 + US + +00-24-C7 (hex) Mobilarm Ltd +0024C7 (base 16) Mobilarm Ltd + 768 Canning Highway + Western Australia 6153 + AU + +00-24-DF (hex) Digitalbox Europe GmbH +0024DF (base 16) Digitalbox Europe GmbH + Sandstraße 65 + Ratingen 40878 + DE + +00-24-45 (hex) Adtran Inc +002445 (base 16) Adtran Inc + 901 Explorer Blvd. + Huntsville AL 35806-2807 + US + +00-24-3F (hex) Storwize, Inc. +00243F (base 16) Storwize, Inc. + 11 Alatlef St. + Yehud 56216 + IL + +00-24-97 (hex) Cisco Systems, Inc +002497 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-A3 (hex) Sonim Technologies Inc +0024A3 (base 16) Sonim Technologies Inc + 1875 S.Grant Street + Sanmateo CA 94402 + US + +00-24-AA (hex) Dycor Technologies Ltd. +0024AA (base 16) Dycor Technologies Ltd. + 1851 94 Street + Edmonton Alberta T6N 1E6 + CA + +00-24-A9 (hex) Ag Leader Technology +0024A9 (base 16) Ag Leader Technology + 2202 S Riverside Dr. + Ames IA 50010 + US + +00-24-A6 (hex) TELESTAR DIGITAL GmbH +0024A6 (base 16) TELESTAR DIGITAL GmbH + Vulkanhöhe / B410 + Dreis-Brück 54552 + DE + +00-24-9B (hex) Action Star Enterprise Co., Ltd. +00249B (base 16) Action Star Enterprise Co., Ltd. + 10F, No.159, Sec.2, Datong Rd. + Xizhi Dist. New Taipei City 221 + TW + +00-24-71 (hex) Fusion MultiSystems dba Fusion-io +002471 (base 16) Fusion MultiSystems dba Fusion-io + 6350 S. 3000 E., 6th floor + Salt lake City UT 84121 + US + +00-24-74 (hex) Autronica Fire And Securirty +002474 (base 16) Autronica Fire And Securirty + Haakon VII's g.4 + Trondheim N-7483 + NO + +00-24-46 (hex) MMB Research Inc. +002446 (base 16) MMB Research Inc. + 35 Prince Arthur Ave. + Toronto Ontario M5R 1B2 + CA + +00-24-63 (hex) Phybridge Inc +002463 (base 16) Phybridge Inc + 3495 Laird Rd + Mississauga Ontario L5L5S5 + CA + +00-24-72 (hex) ReDriven Power Inc. +002472 (base 16) ReDriven Power Inc. + 24A Bath Rd. + Iroquois Ontario K0E 1K0 + CA + +00-24-1C (hex) FuGang Electronic (DG) Co.,Ltd +00241C (base 16) FuGang Electronic (DG) Co.,Ltd + Industry Street, Dong-Keng + Dong Guan City 523448 + CN + +00-24-19 (hex) Private +002419 (base 16) Private + +00-24-15 (hex) Magnetic Autocontrol GmbH +002415 (base 16) Magnetic Autocontrol GmbH + Grienmatt 20 + Schopfheim D-79650 + DE + +00-23-E7 (hex) Hinke A/S +0023E7 (base 16) Hinke A/S + Tingbjergvej 2 + Bjaeverskov DK-4632 + DK + +00-23-E2 (hex) SEA Signalisation +0023E2 (base 16) SEA Signalisation + 20-22 Rue Pierre Mendès France + Vaulx en Velin CEDEX 69515 + FR + +00-24-25 (hex) Shenzhenshi chuangzhicheng Technology Co.,Ltd +002425 (base 16) Shenzhenshi chuangzhicheng Technology Co.,Ltd + 5th Floor,Block2,25th Building,Industrial Zone West Keyuan Sci-tech Garden Nanshan Districh,Shenzhen + Shenzhen Guangdong 518057 + CN + +00-24-27 (hex) SSI COMPUTER CORP +002427 (base 16) SSI COMPUTER CORP + 4F, NO4, LANE 235, BAO CHIAO ROAD + HSIN TIEN TAIPEI 231 + TW + +00-24-11 (hex) PharmaSmart LLC +002411 (base 16) PharmaSmart LLC + 3495 Winton Place + Rochester NY 14623 + US + +00-24-0F (hex) Ishii Tool & Engineering Corporation +00240F (base 16) Ishii Tool & Engineering Corporation + 2-5-60 Higashi-Omichi + Oita 870-0823 + JP + +00-23-FA (hex) RG Nets, Inc. +0023FA (base 16) RG Nets, Inc. + 316 California Ave. + Reno NV 89501 + US + +00-23-F2 (hex) TVLogic +0023F2 (base 16) TVLogic + suite 914 ACE Techno Tower-9th + Geumcheon-gu SEOUL 153-782 + KR + +00-24-0A (hex) US Beverage Net +00240A (base 16) US Beverage Net + 1001 W. Fayette Street + Syracuse NY 13204 + US + +00-24-07 (hex) TELEM SAS +002407 (base 16) TELEM SAS + 16, RUE DE L'ETANG + GIERES RHONE ALPES 38610 + FR + +00-24-40 (hex) Halo Monitoring, Inc. +002440 (base 16) Halo Monitoring, Inc. + 515 Sparkman Dr. + Huntsville AL 35816 + US + +00-23-CF (hex) CUMMINS-ALLISON CORP. +0023CF (base 16) CUMMINS-ALLISON CORP. + 891 FEEHANVILLE DRIVE + MT. PROSPECT IL 60056 + US + +00-23-C2 (hex) SAMSUNG Electronics. Co. LTD +0023C2 (base 16) SAMSUNG Electronics. Co. LTD + 19th Fl., Korea Life Bldg. 1338-12 + Seoul 137-860 + KR + +00-23-C4 (hex) Lux Lumen +0023C4 (base 16) Lux Lumen + Kernenergiestraat 53A + Wilrijk Antwerp 2610 + BE + +00-23-C5 (hex) Radiation Safety and Control Services Inc +0023C5 (base 16) Radiation Safety and Control Services Inc + 91 Portsmouth Ave + Stratham New Hampshire 03885 + US + +00-23-C6 (hex) SMC Corporation +0023C6 (base 16) SMC Corporation + 4-2-2, Kinunodai + Tsukuba Mirai-shi Ibaraki-ken 300-2493 + JP + +00-23-88 (hex) V.T. Telematica S.p.a. +002388 (base 16) V.T. Telematica S.p.a. + Via Gorky, 21 + San Giuliano Milanese Milano 20098 + IT + +00-23-86 (hex) Tour & Andersson AB +002386 (base 16) Tour & Andersson AB + Annelund + Ljung 524 80 + US + +00-23-83 (hex) InMage Systems Inc +002383 (base 16) InMage Systems Inc + 3255-1 Scott Blvd, #104 + Santa Clara CA 95054 + US + +00-23-81 (hex) Lengda Technology(Xiamen) Co.,Ltd. +002381 (base 16) Lengda Technology(Xiamen) Co.,Ltd. + 5/F, 47 Haijing South 2nd Road,Xiamen Export Processing Zone, Haicang District, + Xiamen Fujian 361026 + CN + +00-23-BF (hex) Mainpine, Inc. +0023BF (base 16) Mainpine, Inc. + PO Box 241 + Wilsonville Oregon 97070-0241 + US + +00-23-B2 (hex) Intelligent Mechatronic Systems Inc +0023B2 (base 16) Intelligent Mechatronic Systems Inc + 161 Roger Street + Waterloo Ontario N2J 1B1 + CA + +00-23-B5 (hex) ORTANA LTD +0023B5 (base 16) ORTANA LTD + OSTIM KOCASINAN SANAYI SITESI + ANKARA 06370 + TR + +00-23-B9 (hex) Airbus Defence and Space Deutschland GmbH +0023B9 (base 16) Airbus Defence and Space Deutschland GmbH + Willy-Messerschmitt-Strasse 1, + Taufkirchen 82024 + DE + +00-23-BD (hex) Digital Ally, Inc. +0023BD (base 16) Digital Ally, Inc. + 1218 Valley Ridge Drive + Grain Valley MO 64029 + US + +00-23-D5 (hex) WAREMA electronic GmbH +0023D5 (base 16) WAREMA electronic GmbH + Dillberg 33 + Marktheidenfeld Bavaria 97828 + DE + +00-23-C9 (hex) Sichuan Tianyi Information Science & Technology Stock CO.,LTD +0023C9 (base 16) Sichuan Tianyi Information Science & Technology Stock CO.,LTD + No.1,Hot Spring Highway,Dayi County + Chengdu Sichuan 611330 + US + +00-23-CE (hex) KITA DENSHI CORPORATION +0023CE (base 16) KITA DENSHI CORPORATION + 12F TOKYO-NISHIIKEBUKURO Bilg., + Toshima-ku, Tokyo 171-0021 + JP + +00-23-A9 (hex) Beijing Detianquan Electromechanical Equipment Co., Ltd +0023A9 (base 16) Beijing Detianquan Electromechanical Equipment Co., Ltd + No. 2 Chapeng Road, Haidian District, + Beijing 100091 + CN + +00-23-A7 (hex) Redpine Signals, Inc. +0023A7 (base 16) Redpine Signals, Inc. + Plot 87, Sagar Society + Hyderabad AP 500034 + IN + +00-23-9B (hex) Elster Solutions, LLC +00239B (base 16) Elster Solutions, LLC + 208 South Rogers Lane + Raleigh North Carolina 27610 + US + +00-23-7B (hex) WHDI LLC +00237B (base 16) WHDI LLC + 2350 Mission College Blvd. + Santa Clara CA 95054 + US + +00-23-24 (hex) G-PRO COMPUTER +002324 (base 16) G-PRO COMPUTER + first arrange C, YingHu industrial estate + DongGuan City GuangDong Province 523648 + CN + +00-23-E0 (hex) INO Therapeutics LLC +0023E0 (base 16) INO Therapeutics LLC + 2902 Dairy Drive + Madison WI 53718 + US + +00-23-90 (hex) Algolware Corporation +002390 (base 16) Algolware Corporation + 13F-5, No. 77, Sec. 1, Sintai 5th Rd., + Taipei County Taiwan 221 + TW + +00-23-11 (hex) Gloscom Co., Ltd. +002311 (base 16) Gloscom Co., Ltd. + #507 Changhyun Bldg. + Anyang City Kyunggo-do 431-080 + KR + +00-23-09 (hex) Janam Technologies LLC +002309 (base 16) Janam Technologies LLC + 100 Crossways Park West + Woodbury NY 11797 + US + +00-23-04 (hex) Cisco Systems, Inc +002304 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-23-5D (hex) Cisco Systems, Inc +00235D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-23-5C (hex) Aprius, Inc. +00235C (base 16) Aprius, Inc. + 440 N. Wolfe Rd + Sunnyvale CA 94085 + US + +00-23-52 (hex) DATASENSOR S.p.A. +002352 (base 16) DATASENSOR S.p.A. + Via Lavino, 265 + Monte San Pietro (BO) 40050 + IT + +00-23-2F (hex) Advanced Card Systems Ltd. +00232F (base 16) Advanced Card Systems Ltd. + Unit 2010-13, Chevalier Commercial Centre, + Kowloon Bay, SAR + HK + +00-23-53 (hex) F E T Elettronica snc +002353 (base 16) F E T Elettronica snc + Via Alessandro Manzoni 14/a + Poggibonsi Siena 53036 + IT + +00-23-42 (hex) Coffee Equipment Company +002342 (base 16) Coffee Equipment Company + 4216 6th Ave NW + Seattle WA 98107 + US + +00-23-37 (hex) Global Star Solutions ULC +002337 (base 16) Global Star Solutions ULC + 4600 Jacombs Road + Richmond BC V6V 3B1 + CA + +00-23-19 (hex) Sielox LLC +002319 (base 16) Sielox LLC + 170 East Ninth Ave. + Runnemede NJ 08078 + US + +00-23-6A (hex) SmartRG Inc +00236A (base 16) SmartRG Inc + 501 SE Columbia Shores Blvd + Vancouver WA 98661 + US + +00-23-31 (hex) Nintendo Co., Ltd. +002331 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-23-35 (hex) Linkflex Co.,Ltd +002335 (base 16) Linkflex Co.,Ltd + 5F. Min Young Bldg. 175-2 + Seoul 135-010 + KR + +00-23-25 (hex) IOLAN Holding +002325 (base 16) IOLAN Holding + Mon Plaisir 26 + Etten Leur 4879AN + NL + +00-23-21 (hex) Avitech International Corp +002321 (base 16) Avitech International Corp + 15333 NE 90th Street + Redmond WA 98052 + US + +00-23-70 (hex) Snell +002370 (base 16) Snell + Hartman House + Reading Berks RG6 4PB + GB + +00-22-B9 (hex) Analogix Seminconductor, Inc +0022B9 (base 16) Analogix Seminconductor, Inc + 3211 Scott Blvd., Suite 100 + Santa Clara CA 95054 + US + +00-22-B8 (hex) Norcott +0022B8 (base 16) Norcott + Brookfield House, Grimsditch Lane off Tarporley Road + Cheshire WA4 4EA + GB + +00-22-B7 (hex) GSS Grundig SAT-Systems GmbH +0022B7 (base 16) GSS Grundig SAT-Systems GmbH + Beutherner Strasse 43 + Nuernberg Bayern 90471 + DE + +00-22-B3 (hex) Sei S.p.A. +0022B3 (base 16) Sei S.p.A. + Via Ruffilli, 1 + Curno Bergamo 24035 + IT + +00-22-9C (hex) Verismo Networks Inc +00229C (base 16) Verismo Networks Inc + 295 Bernando Avenue + Mountain View CA 94043 + US + +00-22-9A (hex) Lastar, Inc. +00229A (base 16) Lastar, Inc. + 3555 Kettering BLVD. + Moraine Ohio 45439 + US + +00-22-EE (hex) Algo Communication Products Ltd +0022EE (base 16) Algo Communication Products Ltd + 4500 Beedie Street + Burnaby BC V5J 5L2 + CA + +00-22-EA (hex) Rustelcom Inc. +0022EA (base 16) Rustelcom Inc. + Garagniy proezd, 1 + St.-Petersburg 192288 + RU + +00-22-F0 (hex) 3 Greens Aviation Limited +0022F0 (base 16) 3 Greens Aviation Limited + 10 Hedingham Close + Macclesfield SK10 3LZ + GB + +00-22-EC (hex) IDEALBT TECHNOLOGY CORPORATION +0022EC (base 16) IDEALBT TECHNOLOGY CORPORATION + 6F., NO.8, LANE 345, YANGGUANG ST., NEIHU DISTRICT + Taipei 114 + TW + +00-22-DD (hex) Protecta Electronics Ltd +0022DD (base 16) Protecta Electronics Ltd + Kesmark str 7/A + Budapest Hungary 1158 + HU + +00-22-AB (hex) Shenzhen Turbosight Technology Ltd +0022AB (base 16) Shenzhen Turbosight Technology Ltd + Unit C-8A,Shennan Garden Bldg,Hightech Park,Nanshan District + Shenzhen Guangdong 518057 + CN + +00-22-9B (hex) AverLogic Technologies, Inc. +00229B (base 16) AverLogic Technologies, Inc. + 7F-2, No.2, Lane 258, Rui Guang Rd., Nei-Hu Dist., + Taipei Taiwan 114 + TW + +00-22-BE (hex) Cisco Systems, Inc +0022BE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-22-BF (hex) SieAmp Group of Companies +0022BF (base 16) SieAmp Group of Companies + 2 Ang Mo Kio Street 64 + Singapore 569084 + US + +00-22-DB (hex) Translogic Corporation +0022DB (base 16) Translogic Corporation + 10825 E. 47th Avenue + Denver Colorado 80239 + US + +00-22-DA (hex) ANATEK, LLC +0022DA (base 16) ANATEK, LLC + 3219 East Camelback Road + Phoenix AZ 85018 + US + +00-22-F9 (hex) Pollin Electronic GmbH +0022F9 (base 16) Pollin Electronic GmbH + Max-Pollin-Str. 1 + Pfoerring 85104 + DE + +00-22-C5 (hex) INFORSON Co,Ltd. +0022C5 (base 16) INFORSON Co,Ltd. + Room 704,Tower B1, ChangYuanTianDi Plaza + BeiJing City 100080 + CN + +00-22-62 (hex) BEP Marine +002262 (base 16) BEP Marine + 13 Tarndale Grove Albany + Auckland 0632 + NZ + +00-22-6A (hex) Honeywell +00226A (base 16) Honeywell + 8840 Evergreen Blvd. + Minneapolis MN 55433-6040 + US + +00-22-63 (hex) Koos Technical Services, Inc. +002263 (base 16) Koos Technical Services, Inc. + 1025 Greenwood Blvd. + Lake Mary FL 32746 + US + +00-22-6C (hex) LinkSprite Technologies, Inc. +00226C (base 16) LinkSprite Technologies, Inc. + 1410 Cannon Mountain Dr + Longmont CO 80503 + US + +00-22-5C (hex) Multimedia & Communication Technology +00225C (base 16) Multimedia & Communication Technology + Digital Empire D-801 #980-3 + Suwon-City KyeongGi-Do 443-813 + KR + +00-22-84 (hex) DESAY A&V SCIENCE AND TECHNOLOGY CO.,LTD +002284 (base 16) DESAY A&V SCIENCE AND TECHNOLOGY CO.,LTD + DESAY 3rd Zone,Chenjiang, + Huizhou Guangdong 516229 + CN + +00-22-86 (hex) ASTRON +002286 (base 16) ASTRON + Oudehoogeveensedijk 4 + Dwingeloo Drenthe 7991PD + NL + +00-22-82 (hex) 8086 Consultancy +002282 (base 16) 8086 Consultancy + 17 Lowfield Lane + Newark Notts NG24 3HJ + GB + +00-22-46 (hex) Evoc Intelligent Technology Co.,Ltd. +002246 (base 16) Evoc Intelligent Technology Co.,Ltd. + No.31 Gaoxin Centeral Avenue 4th Road,Nanshan District Shenzhen City + Shenzhen Guangdong 518057 + CN + +00-22-48 (hex) Microsoft Corporation +002248 (base 16) Microsoft Corporation + One Microsoft Way + Redmond Washington 98052-6399 + US + +00-22-90 (hex) Cisco Systems, Inc +002290 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-22-8A (hex) Teratronik elektronische systeme gmbh +00228A (base 16) Teratronik elektronische systeme gmbh + Karl-Ulrich-Strasse 1 + Gross-Umstadt D-64823 + DE + +00-22-8E (hex) TV-NUMERIC +00228E (base 16) TV-NUMERIC + 24-26 rue Louis Armand + Paris 75015 + FR + +00-22-54 (hex) Bigelow Aerospace +002254 (base 16) Bigelow Aerospace + 1899 W. Brooks Ave + North Las Vegas NV 89032 + US + +00-22-57 (hex) 3COM EUROPE LTD +002257 (base 16) 3COM EUROPE LTD + Peoplebuilding 2 + Hemel Hempstead HERTS. HP2 4NW + GB + +00-22-76 (hex) Triple EYE B.V. +002276 (base 16) Triple EYE B.V. + Vaassenseweg 71 + Emst 8166 AT + NL + +00-22-74 (hex) FamilyPhone AB +002274 (base 16) FamilyPhone AB + Anckargripsgatan 3 + Malmö 21119 + SE + +00-22-36 (hex) VECTOR SP. Z O.O. +002236 (base 16) VECTOR SP. Z O.O. + KRZEMOWA 6 + GDYNIA 81-577 + PL + +00-22-30 (hex) FutureLogic Inc. +002230 (base 16) FutureLogic Inc. + 425 E. Colorado St., Ste. 100 + Glendale CA 91205 + US + +00-22-2E (hex) maintech GmbH +00222E (base 16) maintech GmbH + Seeweg 60 + Höchberg Bavaria 97204 + DE + +00-22-14 (hex) RINNAI KOREA +002214 (base 16) RINNAI KOREA + 560-2, Shibjong-1dong, Pupyoung-gu + Pupyoung-gu Incheon 403-847 + KR + +00-22-0B (hex) National Source Coding Center +00220B (base 16) National Source Coding Center + Suite 701,Power Creative A,No.1 + Beijing 100085 + CN + +00-22-0C (hex) Cisco Systems, Inc +00220C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-21-EA (hex) Bystronic Laser AG +0021EA (base 16) Bystronic Laser AG + Industriestrasse 21 + 3362 Niederönz + CH + +00-21-FD (hex) LACROIX TRAFFIC S.A.U +0021FD (base 16) LACROIX TRAFFIC S.A.U + Majada 4 + Tres Cantos Madrid 28760 + ES + +00-21-CD (hex) LiveTV +0021CD (base 16) LiveTV + 1333 Gateway Drive, Suite 1007 + Melbourne Florida 32901 + US + +00-21-D0 (hex) Global Display Solutions Spa +0021D0 (base 16) Global Display Solutions Spa + Via Tezze, 20/A + Cornedo Vicentino Vicenza 36073 + IT + +00-22-28 (hex) Breeze Innovations Ltd. +002228 (base 16) Breeze Innovations Ltd. + Har Hotzvim, P.O. Box 45397 + Jerusalem Israel 91451 + IL + +00-22-29 (hex) Compumedics Ltd +002229 (base 16) Compumedics Ltd + 30 - 40 Flockhart Street + Abbotsford Victoria 3067 + AU + +00-22-16 (hex) SHIBAURA VENDING MACHINE CORPORATION +002216 (base 16) SHIBAURA VENDING MACHINE CORPORATION + Ekimae-cho13-10 + Obama-shi Fukui-ken 917-0077 + JP + +00-21-E1 (hex) Nortel Networks +0021E1 (base 16) Nortel Networks + 2221 Lakeside Blvd + Richardson TX 75081 + US + +00-22-00 (hex) IBM Corp +002200 (base 16) IBM Corp + 2051 Mission College Blvd + Santa Clara CA 95054 + US + +00-21-C6 (hex) CSJ Global, Inc. +0021C6 (base 16) CSJ Global, Inc. + 9th Fl. Samwhan Bldg. Annex, 17-26 Yeouido-dong, + Seoul 150-874 + KR + +00-21-C3 (hex) CORNELL Communications, Inc. +0021C3 (base 16) CORNELL Communications, Inc. + 7915 N. 81st Street + Milwaukee Wisconsin 53223 + US + +00-21-C7 (hex) Russound +0021C7 (base 16) Russound + 5 Forbes Road + Newmarket NH 03857 + US + +00-21-C1 (hex) ABB Oy / Medium Voltage Products +0021C1 (base 16) ABB Oy / Medium Voltage Products + PO Box 699 + Vaasa FI-65101 + FI + +00-21-C0 (hex) Mobile Appliance, Inc. +0021C0 (base 16) Mobile Appliance, Inc. + #819 Kranz Techno, + Seong nam Gyeonggi-Do 462-729 + KR + +00-21-BB (hex) Riken Keiki Co., Ltd. +0021BB (base 16) Riken Keiki Co., Ltd. + 2-7-6 Azusawa + Itabashi-Ku Tokyo 174-8744 + JP + +00-21-66 (hex) NovAtel Inc. +002166 (base 16) NovAtel Inc. + 1120 - 68 Ave NE + Calgary Alberta T2E 8S5 + CA + +00-21-64 (hex) Special Design Bureau for Seismic Instrumentation +002164 (base 16) Special Design Bureau for Seismic Instrumentation + 129, Krainyaya Str. + Saratov Saratov region 410019 + RU + +00-21-60 (hex) Hidea Solutions Co. Ltd. +002160 (base 16) Hidea Solutions Co. Ltd. + 4F, Do&Can house Dldg., #656-1683, Seongsu 1-ga 2-dong, Seongdong-gu + Seoul 656-1683 + KR + +00-21-B1 (hex) DIGITAL SOLUTIONS LTD +0021B1 (base 16) DIGITAL SOLUTIONS LTD + Tsarigradsko Shose 7km BLVD + Sofia Sofia 1784 + BG + +00-21-B0 (hex) Tyco Telecommunications +0021B0 (base 16) Tyco Telecommunications + 1011 Pawtucket Blvd + Lowell Massachusetts 01853 + US + +00-21-AD (hex) Nordic ID Oy +0021AD (base 16) Nordic ID Oy + Myllyojankatu 2A + SALO FIN-24100 + FI + +00-21-7F (hex) Intraco Technology Pte Ltd +00217F (base 16) Intraco Technology Pte Ltd + 750e Chai Chee Road #05-01 + Singapore 4690005 + SG + +00-21-7D (hex) PYXIS S.R.L. +00217D (base 16) PYXIS S.R.L. + C/O DIP. INFORMATICA E SISTEMISTICA - UNIVERSITY OF PAVIA + PAVIA 27100 + IT + +00-21-6F (hex) SymCom, Inc. +00216F (base 16) SymCom, Inc. + 2880 North Plaza Drive + Rapid City SD 57702 + US + +00-21-A3 (hex) Micromint +0021A3 (base 16) Micromint + 111 Commerce St + Lake Mary FL 32746 + US + +00-21-A5 (hex) ERLPhase Power Technologies Ltd. +0021A5 (base 16) ERLPhase Power Technologies Ltd. + 74 Scurfield Blvd. + Winnipeg Manitoba R3Y 1G4 + CA + +00-21-9D (hex) Adesys BV +00219D (base 16) Adesys BV + Molenweer 4 + Wateringen Zuid Holland 2291 NR + NL + +00-21-95 (hex) GWD Media Limited +002195 (base 16) GWD Media Limited + 10 Leeds Road + Sheffield South Yorkshire S9 3TY + GB + +00-21-88 (hex) EMC Corporation +002188 (base 16) EMC Corporation + 2421 Mission College Blvd + Santa Clara CA 95050 + US + +00-21-1A (hex) LInTech Corporation +00211A (base 16) LInTech Corporation + Krasnokazarmennaya st., 12 + Moscow 111250 + RU + +00-21-16 (hex) Transcon Electronic Systems, spol. s r. o. +002116 (base 16) Transcon Electronic Systems, spol. s r. o. + Kvapilova 2133 + Frydek-Mistek 73802 + CZ + +00-21-15 (hex) PHYWE Systeme GmbH & Co. KG +002115 (base 16) PHYWE Systeme GmbH & Co. KG + Robert-Bosch-Breite 10 + Goettingen Niedersachsen 37079 + DE + +00-21-41 (hex) RADLIVE +002141 (base 16) RADLIVE + 4 Hanechoshet St. + Tel Aviv 69710 + IL + +00-21-40 (hex) EN Technologies Inc. +002140 (base 16) EN Technologies Inc. + Geumbok Bldg. 9F, Band-yi-dong 45-2, Songpa-gu + Seoul 138-828 + KR + +00-21-3D (hex) Cermetek Microelectronics, Inc. +00213D (base 16) Cermetek Microelectronics, Inc. + 374 Turquoise Street + Milpitas CA 95035 + US + +00-21-11 (hex) Uniphone Inc. +002111 (base 16) Uniphone Inc. + 795 Main Street + Half Moon Bay CA 94019 + US + +00-21-14 (hex) Hylab Technology Inc. +002114 (base 16) Hylab Technology Inc. + 15F-2.,No.872,Jhongjheng Rd. + Jhonghe City, Taipei 235 + TW + +00-21-32 (hex) Masterclock, Inc. +002132 (base 16) Masterclock, Inc. + 2484 W. Clay St. + St. Charles MO 63301 + US + +00-21-31 (hex) Blynke Inc. +002131 (base 16) Blynke Inc. + 133 Richmond St. West + Toronto Ontario M5H 2L3 + CA + +00-21-29 (hex) Cisco-Linksys, LLC +002129 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +00-21-1D (hex) Dataline AB +00211D (base 16) Dataline AB + Katrinedalsgatan 53 + Borås S-50451 + SE + +00-21-20 (hex) Sequel Technologies +002120 (base 16) Sequel Technologies + 2951 Cleveland Ave N + Roseville MN 55113 + US + +00-21-52 (hex) General Satellite Research & Development Limited +002152 (base 16) General Satellite Research & Development Limited + Lit. E, building 2, 4 Novoladozhskaya str + Saint Petersburg 197110 + RU + +00-21-58 (hex) Style Flying Technology Co. +002158 (base 16) Style Flying Technology Co. + 22/F,Cyber Tower B,No.2 Zhong Guan Cun South Street,Haidian District, + Beijing 100086 + CN + +00-21-48 (hex) Kaco Solar Korea +002148 (base 16) Kaco Solar Korea + Chung-won-ku Sang-dea-won-dong 333-1 + Songnam Kyung-kido 462-806 + KR + +00-21-3C (hex) AliphCom +00213C (base 16) AliphCom + 150 Executive Park Blvd + San Francisco CA 94134 + US + +00-1F-B5 (hex) I/O Interconnect Inc. +001FB5 (base 16) I/O Interconnect Inc. + 1202 E Wakeham Ave + Santa Ana CA 92708 + US + +00-1F-E7 (hex) Simet +001FE7 (base 16) Simet + Strada del Portone 129 + Grugliasco Torino 10095 + IT + +00-1F-DB (hex) Network Supply Corp., +001FDB (base 16) Network Supply Corp., + 1938 NAKADAIRA KANAE + IIDA NAGANO 395-0801 + JP + +00-1F-BF (hex) Fulhua Microelectronics Corp. Taiwan Branch +001FBF (base 16) Fulhua Microelectronics Corp. Taiwan Branch + 1F, No.12, R&D Road, + Hsin-Chu, 300 886 + TW + +00-1F-BE (hex) Shenzhen Mopnet Industrial Co.,Ltd +001FBE (base 16) Shenzhen Mopnet Industrial Co.,Ltd + 3F.No.3 Keyuan Rd., + Shenzhen Guangdong 518057 + CN + +00-1F-C2 (hex) Jow Tong Technology Co Ltd +001FC2 (base 16) Jow Tong Technology Co Ltd + 46 Lane 337 Chung Cheng Rd + Yung Kang City Tainan County 71066 + TW + +00-1F-D2 (hex) COMMTECH TECHNOLOGY MACAO COMMERCIAL OFFSHORE LTD. +001FD2 (base 16) COMMTECH TECHNOLOGY MACAO COMMERCIAL OFFSHORE LTD. + 31,TAI YIP STREET, 7/F KWUN TONG, + KOWLOON, HONGKONG + CN + +00-1F-B8 (hex) Universal Remote Control, Inc. +001FB8 (base 16) Universal Remote Control, Inc. + 500 Mamaroneck Avenue + Harrison NY 10528 + US + +00-1F-D4 (hex) 4IPNET, INC. +001FD4 (base 16) 4IPNET, INC. + 38129 CAMBRIDGE COURT + FREMONT CA 94536 + US + +00-1F-CB (hex) NIW Solutions +001FCB (base 16) NIW Solutions + P.O. Box 62 + One Tree Hill South Australia 5114 + AU + +00-1F-F7 (hex) Nakajima All Precision Co., Ltd. +001FF7 (base 16) Nakajima All Precision Co., Ltd. + Kami-Gomyo1480 + Hanishina-Gun Nagano-Ken 389-0606 + JP + +00-1F-EB (hex) Trio Datacom Pty Ltd +001FEB (base 16) Trio Datacom Pty Ltd + 41 Aster Avenue + Carrum Downs Victoria 3201 + AU + +00-1F-69 (hex) Pingood Technology Co., Ltd. +001F69 (base 16) Pingood Technology Co., Ltd. + Rm1917, South Block, Cangsong Bldg., Tairan Industrial Zone, Futian District + Shenzhen Guangdong 518040 + CN + +00-1F-4D (hex) Segnetics LLC +001F4D (base 16) Segnetics LLC + Shkiperski protok 14 + Saint-Petersburg 199106 + RU + +00-1F-81 (hex) Accel Semiconductor Corp +001F81 (base 16) Accel Semiconductor Corp + 1F,Mainbldg,149 Chun Xiao Road, + Shanghai 201203 + CN + +00-1F-83 (hex) Teleplan Technology Services Sdn Bhd +001F83 (base 16) Teleplan Technology Services Sdn Bhd + 2580, Tingkat Perusahaan 4B + Perai Penang 13600 + MY + +00-1F-9B (hex) POSBRO +001F9B (base 16) POSBRO + ShinyoungGtower 6F, 271-1 + Seongnam-si Kyunggi-do 463-824 + KR + +00-1F-78 (hex) Blue Fox Porini Textile +001F78 (base 16) Blue Fox Porini Textile + 1208 Pointe Centre Drive + Chattanooga TN 37421 + US + +00-1F-68 (hex) Martinsson Elektronik AB +001F68 (base 16) Martinsson Elektronik AB + Box 9060 + Hägersten Stockholm 126 09 + SE + +00-1F-63 (hex) JSC Goodwin-Europa +001F63 (base 16) JSC Goodwin-Europa + 20/5 Marksistskaya st. + Moscow 109147 + RU + +00-1F-AD (hex) Brown Innovations, Inc +001FAD (base 16) Brown Innovations, Inc + 369 Congress Street + Boston MA 02210 + US + +00-1F-A6 (hex) Stilo srl +001FA6 (base 16) Stilo srl + Via Besana, 4 + 20122 Milano + IT + +00-1F-97 (hex) BERTANA srl +001F97 (base 16) BERTANA srl + Viale GALILEO FERRARIS 27 + BRUINO TORINO 10090 + IT + +00-1F-8C (hex) CCS Inc. +001F8C (base 16) CCS Inc. + Shimodachiuri-agaru + Kyoto Kyoto 602-8011 + JP + +00-1F-10 (hex) TOLEDO DO BRASIL INDUSTRIA DE BALANCAS LTDA +001F10 (base 16) TOLEDO DO BRASIL INDUSTRIA DE BALANCAS LTDA + RUA MANOEL CREMONESI, 1 + SAO BERNARDO DO CAMPO SP 09851-900 + BR + +00-1F-0F (hex) Select Engineered Systems +001F0F (base 16) Select Engineered Systems + 7991 W. 26 Ave + Hialeah Florida 33016 + US + +00-1F-02 (hex) Pixelmetrix Corporation Pte Ltd +001F02 (base 16) Pixelmetrix Corporation Pte Ltd + 31 Kaki Bukit Road 3 + 417818 + SG + +00-1E-FE (hex) LEVEL s.r.o. +001EFE (base 16) LEVEL s.r.o. + Plhovska 1997 + Nachod 547 01 + CZ + +00-1F-1A (hex) Prominvest +001F1A (base 16) Prominvest + 7, Bobruiskaya ulica + Saint-Petersburg North-West Federal District 195009 + RU + +00-1F-18 (hex) Hakusan.Mfg.Co,.Ltd +001F18 (base 16) Hakusan.Mfg.Co,.Ltd + Tomin-Kougyou-Ikebukuro BLD.5F + Tosima Ward Tokyo-Met. 171-0022 + JP + +00-1F-13 (hex) S.& A.S. Ltd. +001F13 (base 16) S.& A.S. Ltd. + Boutros Bldg. 1st bsmt + Beirut 2067 7808 + LB + +00-1F-25 (hex) MBS GmbH +001F25 (base 16) MBS GmbH + Römerstraße 15 + Krefeld Nordrhein-Westfalen 47809 + DE + +00-1F-27 (hex) Cisco Systems, Inc +001F27 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1F-26 (hex) Cisco Systems, Inc +001F26 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-EF (hex) Cantronic International Limited +001EEF (base 16) Cantronic International Limited + Unit 515-516, Building 15, East Wing, No 8 Science Park West Avenue, Hong Kong Science Park Phase II + Shatin New Territories 852 + HK + +00-1E-DE (hex) BYD COMPANY LIMITED +001EDE (base 16) BYD COMPANY LIMITED + NO.1,Baoping Road,Baolong Industrial Town,Longgang + SHEN ZHEN Guangdong 518116 + CN + +00-1E-DD (hex) WASKO S.A. +001EDD (base 16) WASKO S.A. + Berbeckiego 6 + Gliwice Silesia 44-100 + PL + +00-1E-DB (hex) Giken Trastem Co., Ltd. +001EDB (base 16) Giken Trastem Co., Ltd. + 4-1 Takeda Dankawaracho Fushimiku + Kyoto 612-8414 + JP + +00-1F-42 (hex) Etherstack plc +001F42 (base 16) Etherstack plc + 80 Abercrombie Street + Chippendale NSW 2008 + AU + +00-1F-35 (hex) AIR802 LLC +001F35 (base 16) AIR802 LLC + 1169 Banyon Court + Naperville IL 60540 + US + +00-1F-34 (hex) Lung Hwa Electronics Co., Ltd. +001F34 (base 16) Lung Hwa Electronics Co., Ltd. + 3F, 248, Pei Sheng Rd. Sec. 3, + Taipei Hsien 222 + TW + +00-1E-EB (hex) Talk-A-Phone Co. +001EEB (base 16) Talk-A-Phone Co. + 5013 N. Kedzie Ave. + Chicago IL 60625 + US + +00-1E-6A (hex) Beijing Bluexon Technology Co.,Ltd +001E6A (base 16) Beijing Bluexon Technology Co.,Ltd + Jinqiuzhichun 7-301,Zhichun Rd., + Beijing 100088 + CN + +00-1E-66 (hex) RESOL Elektronische Regelungen GmbH +001E66 (base 16) RESOL Elektronische Regelungen GmbH + Heiskampstraße 10 + Hattingen NRW 45527 + DE + +00-1E-63 (hex) Vibro-Meter SA +001E63 (base 16) Vibro-Meter SA + Route de Moncor 4 + Fribourg CH-1701 + CH + +00-1E-7F (hex) CBM of America +001E7F (base 16) CBM of America + 1455 West Newport Center Drive + Deerfield Beach Florida 33442 + US + +00-1E-82 (hex) SanDisk Corporation +001E82 (base 16) SanDisk Corporation + 630 Alder Drive, + Milpitas CA 95035 + US + +00-1E-B1 (hex) Cryptsoft Pty Ltd +001EB1 (base 16) Cryptsoft Pty Ltd + P.O. Box 6389 + Fairfield Gardens Queensland 4103 + AU + +00-1E-AF (hex) Ophir Optronics Ltd +001EAF (base 16) Ophir Optronics Ltd + POB 45021 + Jerusalem 91450 + IL + +00-1E-AD (hex) Wingtech Group Limited +001EAD (base 16) Wingtech Group Limited + 6th floor, Unit G, No.668, East Beijing Road, + Shanghai 200001 + CN + +00-1E-D1 (hex) Keyprocessor B.V. +001ED1 (base 16) Keyprocessor B.V. + Paasheuvelweg 20 + Amsterdam NH 1105 BJ + NL + +00-1E-D0 (hex) Ingespace +001ED0 (base 16) Ingespace + 6 rue de lourmede + Eurocentre 31621 + FR + +00-1E-8E (hex) Hunkeler AG +001E8E (base 16) Hunkeler AG + Bahnhofstrasse 31 + Wikon CH 4806 + CH + +00-1E-87 (hex) Realease Limited +001E87 (base 16) Realease Limited + 15/F, Morrison Commercial Building + WanChai + HK + +00-1E-CD (hex) KYLAND Technology Co. LTD +001ECD (base 16) KYLAND Technology Co. LTD + Building No.2,Shixing Avenue 30# + Shijingshan District Beijing 100044 + CN + +00-1E-BF (hex) Haas Automation Inc. +001EBF (base 16) Haas Automation Inc. + 2800 Sturgis Rd + Oxnard CA 93030 + US + +00-1E-BC (hex) WINTECH AUTOMATION CO.,LTD. +001EBC (base 16) WINTECH AUTOMATION CO.,LTD. + #1115, TAEKWANG BLVD. + SUWON-SI KYUNGGI 443-816 + KR + +00-1E-6F (hex) Magna-Power Electronics, Inc. +001E6F (base 16) Magna-Power Electronics, Inc. + 39 Royal Road + Flemington NJ 08822 + US + +00-1E-A1 (hex) Brunata a/s +001EA1 (base 16) Brunata a/s + Vesterlundvej 14 + Herlev 2730 + DK + +00-1E-53 (hex) Further Tech Co., LTD +001E53 (base 16) Further Tech Co., LTD + 8F,NO 421, Sungshan RD.,Taipei, Taiwn,R.O.C. + Taipei 110 + TW + +00-1E-4E (hex) DAKO EDV-Ingenieur- und Systemhaus GmbH +001E4E (base 16) DAKO EDV-Ingenieur- und Systemhaus GmbH + Ernst-Haeckel-Platz 5/6 + Jena Thuringia 07745 + DE + +00-1E-49 (hex) Cisco Systems, Inc +001E49 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-28 (hex) Lumexis Corporation +001E28 (base 16) Lumexis Corporation + 3184 Airway Ave Bldg D + Costa Mesa CA 92626 + US + +00-1E-24 (hex) Zhejiang Bell Technology Co.,ltd +001E24 (base 16) Zhejiang Bell Technology Co.,ltd + 6 Xidoumen Rd. West Lake district + Hangzhou Zhejiang 310012 + CN + +00-1E-20 (hex) Intertain Inc. +001E20 (base 16) Intertain Inc. + Suite 608 LG Eclat-2, 245-4 Seohyun-dong, Bundang-gu + Sungngm-shi Kyunggi-do 463-824 + KR + +00-1E-1C (hex) SWS Australia Pty Limited +001E1C (base 16) SWS Australia Pty Limited + 23 Scanlon Drive + Epping Victoria 3076 + AU + +00-1E-12 (hex) Ecolab +001E12 (base 16) Ecolab + 655 Lone Oak Drive + Eagan MN 55121 + US + +00-1E-16 (hex) Keytronix +001E16 (base 16) Keytronix + Ungargasse 64-66/1/109 + Vienna 1030 + AT + +00-1E-32 (hex) Zensys +001E32 (base 16) Zensys + Emdrupvej 26 + Copenhagen O DK-2100 + DK + +00-1E-35 (hex) Nintendo Co., Ltd. +001E35 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-1E-2B (hex) Radio Systems Design, Inc. +001E2B (base 16) Radio Systems Design, Inc. + 601 Heron Drive + Logan Twp New Jersey 08085 + US + +00-1E-42 (hex) Teltonika +001E42 (base 16) Teltonika + Zirmunu 27 + Vilnius LT - 09105 + LT + +00-1E-43 (hex) AISIN AW CO.,LTD. +001E43 (base 16) AISIN AW CO.,LTD. + 6-18 HARAYAMA + OKAZAKI AICHI 444-8564 + JP + +00-1E-08 (hex) Centec Networks Inc +001E08 (base 16) Centec Networks Inc + Suite 4F-13/16, Building B, No.5 Xing Han Street + Suzhou Jiangsu 215021 + CN + +00-1D-FB (hex) NETCLEUS Systems Corporation +001DFB (base 16) NETCLEUS Systems Corporation + 3F, Daiichi-maeda Bldg. + Yamato-shi 242-0017 + JP + +00-1D-B9 (hex) Wellspring Wireless +001DB9 (base 16) Wellspring Wireless + 107 Magella Court + North Wales Pa 19454 + US + +00-1D-BB (hex) Dynamic System Electronics Corp. +001DBB (base 16) Dynamic System Electronics Corp. + 5F,NO,9,LANE 130,SEC 1,KUANGG FU RD.SAN CHUNG CITY, + Taipei Hsien 24158 + TW + +00-1D-B3 (hex) HPN Supply Chain +001DB3 (base 16) HPN Supply Chain + 8000 Foothills Blvd + Roseville CA 95747 + US + +00-1D-B1 (hex) Crescendo Networks +001DB1 (base 16) Crescendo Networks + 6 Yoni Netanyahu St. + Or-Yehuda 60376 + IL + +00-1D-B4 (hex) KUMHO ENG CO.,LTD +001DB4 (base 16) KUMHO ENG CO.,LTD + 498-13, HYUNDAI B/D 5F + DAEGU 703-835 + KR + +00-1D-A4 (hex) Hangzhou System Technology CO., LTD +001DA4 (base 16) Hangzhou System Technology CO., LTD + ROOM A1505 HuaXing times plaza,NO 478 Wensan Road + Hangzhou Zhejiang 310012 + CN + +00-1D-9F (hex) MATT R.P.Traczynscy Sp.J. +001D9F (base 16) MATT R.P.Traczynscy Sp.J. + Polnocna 44 + Koscian wielkopolskie PL-64000 + PL + +00-1D-90 (hex) EMCO Flow Systems +001D90 (base 16) EMCO Flow Systems + 2150 Miller Drive + Longmont CO 80501 + US + +00-1D-93 (hex) Modacom +001D93 (base 16) Modacom + Jinsuk Building 1536-7 + Seoul 137-073 + KR + +00-1D-94 (hex) Climax Technology Co., Ltd +001D94 (base 16) Climax Technology Co., Ltd + No. 258, Hsin Hu 2nd Road + Taipei City Taipei 114 + TW + +00-1D-8E (hex) Alereon, Inc. +001D8E (base 16) Alereon, Inc. + 7600 N. Capital of Texas Hwy + Austin TX 78731 + US + +00-1D-DB (hex) C-BEL Corporation +001DDB (base 16) C-BEL Corporation + Futabacho 35-12 + Itabashi-ku Tokyo 173-0011 + JP + +00-1D-E6 (hex) Cisco Systems, Inc +001DE6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1D-E7 (hex) Marine Sonic Technology, Ltd. +001DE7 (base 16) Marine Sonic Technology, Ltd. + 5508 George Washington Memorial Highway + White Marsh Virginia 23183 + US + +00-1D-7B (hex) Ice Energy, Inc. +001D7B (base 16) Ice Energy, Inc. + 9351 Eastman Park Drive + Windsor Colorado 80550 + US + +00-1D-6C (hex) ClariPhy Communications, Inc. +001D6C (base 16) ClariPhy Communications, Inc. + 16 Technology Dr., Suite 165 + Irvine CA 92618 + US + +00-1D-C5 (hex) Beijing Jiaxun Feihong Electricial Co., Ltd. +001DC5 (base 16) Beijing Jiaxun Feihong Electricial Co., Ltd. + Electrical Building,No. 31 Jiaoda East Road, + Beijing Haidian District, 100044 + CN + +00-1D-C6 (hex) SNR Inc. +001DC6 (base 16) SNR Inc. + VBIC T223ho, ICU, 103-6 Munji-dong, Youseong-gu + Daejeon 305-732 + KR + +00-1D-84 (hex) Gateway, Inc. +001D84 (base 16) Gateway, Inc. + 610 Gateway Drive + North Sioux City South Dakota 57049 + US + +00-1D-85 (hex) Call Direct Cellular Solutions +001D85 (base 16) Call Direct Cellular Solutions + Suite 145, National Innovation Centre + Eveleigh NSW 1430 + AU + +00-1D-BF (hex) Radiient Technologies, Inc. +001DBF (base 16) Radiient Technologies, Inc. + 2084-A Walsh Ave + Santa Clara CA 95050 + US + +00-1D-34 (hex) SYRIS Technology Corp +001D34 (base 16) SYRIS Technology Corp + 21 F-2, NO. 12, SEC. 1, Taijunggang Rd. + Taichung 403 + US + +00-1D-32 (hex) Longkay Communication & Technology (Shanghai) Co. Ltd +001D32 (base 16) Longkay Communication & Technology (Shanghai) Co. Ltd + No.5 Building, Unit 2, Lane 299 Bisheng Rd, + Shanghai 201204 + CN + +00-1D-2A (hex) SHENZHEN BUL-TECH CO.,LTD. +001D2A (base 16) SHENZHEN BUL-TECH CO.,LTD. + 4/F, COFCO Bdlg , 3rd District,Baoan District, Shenzhen City, + shengzhen guangdong 518101 + CN + +00-1D-2D (hex) Pylone, Inc. +001D2D (base 16) Pylone, Inc. + 4F Nakano Bldg. 4-30-8 Kita-Shinjuku + Shinjuku-ku, Tokyo 169-0074 + JP + +00-1D-5B (hex) Tecvan Informática Ltda +001D5B (base 16) Tecvan Informática Ltda + Rua Guaicurus, 145 + Diadema São Paulo 09911-630 + BR + +00-1D-5D (hex) Control Dynamics Pty. Ltd. +001D5D (base 16) Control Dynamics Pty. Ltd. + PO Box 636 + MORLEY Western Australia 6943 + AU + +00-1D-59 (hex) Mitra Energy & Infrastructure +001D59 (base 16) Mitra Energy & Infrastructure + Boulevard de l'Europe 131 + 1301 Wavre + BE + +00-1D-2B (hex) Wuhan Pont Technology CO. , LTD +001D2B (base 16) Wuhan Pont Technology CO. , LTD + Building E, Guandong Science and Technology Industry Park, + Wuhan Hubei 430074 + CN + +00-1D-22 (hex) Foss Analytical A/S +001D22 (base 16) Foss Analytical A/S + Slangerupgade 69 + Hillerød Seeland 3400 + DK + +00-1D-23 (hex) SENSUS +001D23 (base 16) SENSUS + 44 CASTILIAN DRIVE + GOLETA CALIFORNIA 93117 + US + +00-1D-3E (hex) SAKA TECHNO SCIENCE CO.,LTD +001D3E (base 16) SAKA TECHNO SCIENCE CO.,LTD + Nishi 105-1 + Kanazawa Ishikawa 920-0367 + JP + +00-1D-40 (hex) Intel – GE Care Innovations LLC +001D40 (base 16) Intel – GE Care Innovations LLC + 3721 Douglas Blvd + Roseville CA 95661 + US + +00-1D-57 (hex) CAETEC Messtechnik +001D57 (base 16) CAETEC Messtechnik + Schlossstraße 95a + Olching Bayern 82140 + DE + +00-1D-51 (hex) Babcock & Wilcox Power Generation Group, Inc +001D51 (base 16) Babcock & Wilcox Power Generation Group, Inc + 11864 Canon Blvd, Suite 105 + Newport News VA 23606 + US + +00-1D-4C (hex) Alcatel-Lucent +001D4C (base 16) Alcatel-Lucent + 601 Data Dr. + Plano TX 75075 + US + +00-1D-1A (hex) OvisLink S.A. +001D1A (base 16) OvisLink S.A. + C/Andres Obispo, 37. Pl. 4. + Madrid 28043 + ES + +00-1C-B7 (hex) USC DigiArk Corporation +001CB7 (base 16) USC DigiArk Corporation + 6F Tennoz Central Tower 2-2-24 Higashishinagawa + Tokyo Shinagawa-ku 140-0002 + JP + +00-1C-AF (hex) Plato Networks Inc. +001CAF (base 16) Plato Networks Inc. + 2855 Kifer Road + Santa Clara CA 95051 + US + +00-1C-B1 (hex) Cisco Systems, Inc +001CB1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1C-FE (hex) Quartics Inc +001CFE (base 16) Quartics Inc + 15241 Laguna Canyon Road + Irvine CA 92618 + US + +00-1D-0B (hex) Power Standards Lab +001D0B (base 16) Power Standards Lab + 1201 Marina Village Parkway #101 + Alameda CA 94501 + US + +00-1D-02 (hex) Cybertech Telecom Development +001D02 (base 16) Cybertech Telecom Development + Hazenkoog 25 + Alkmaar Noord Holland 1822 BS + NL + +00-1C-E9 (hex) Galaxy Technology Limited +001CE9 (base 16) Galaxy Technology Limited + 9/F Win Full Commerical Building, 172-176 Wing Lok Street, + Sheung Wan, + HK + +00-1C-EA (hex) Scientific-Atlanta, Inc +001CEA (base 16) Scientific-Atlanta, Inc + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +00-1C-E7 (hex) Rocon PLC Research Centre +001CE7 (base 16) Rocon PLC Research Centre + 21 Vek 56A str. + Sofia 1700 + US + +00-1C-DB (hex) CARPOINT CO.,LTD +001CDB (base 16) CARPOINT CO.,LTD + 1340-6, Namgang Bld 7F, Seocho-Dong + SEOUL 137-070 + KR + +00-1C-D5 (hex) ZeeVee, Inc. +001CD5 (base 16) ZeeVee, Inc. + 1 Monarch Drive + Littleton MA 01460 + US + +00-1C-BC (hex) CastGrabber, LLC +001CBC (base 16) CastGrabber, LLC + 6507 Wilkins Avenue Ste. 212 + Pittsburgh PA 15217 + US + +00-1C-E4 (hex) EleSy JSC +001CE4 (base 16) EleSy JSC + Altayskaya street, 161a + Tomsk oblast 634021 + RU + +00-1C-E2 (hex) Attero Tech, LLC. +001CE2 (base 16) Attero Tech, LLC. + 1315 Directors Row - Suite 107 + Fort Wayne Indiana 46808 + US + +00-1C-AA (hex) Bellon Pty Ltd +001CAA (base 16) Bellon Pty Ltd + Unit 12/12-18 Victoria St East + Lidcombe NSW 2000 + AU + +00-1C-A0 (hex) Production Resource Group, LLC +001CA0 (base 16) Production Resource Group, LLC + 539 Temple Hill Road + New Windsor NY 12553 + US + +00-1C-D3 (hex) ZP Engineering SEL +001CD3 (base 16) ZP Engineering SEL + via Ardito Desio, 60 + ROME 00131 + IT + +00-1C-CB (hex) Forth Corporation Public Company Limited +001CCB (base 16) Forth Corporation Public Company Limited + 226/12,13,16 Paholyothin Road + Bangkok 10400 + TH + +00-1C-75 (hex) Segnet Ltd. +001C75 (base 16) Segnet Ltd. + 146 New London Road + Chelmsford Essex CM2 OAW + GB + +00-1C-74 (hex) Syswan Technologies Inc. +001C74 (base 16) Syswan Technologies Inc. + 2050 Beavercreek Road + Oregon City Oregon 97045 + US + +00-1C-68 (hex) Anhui Sun Create Electronics Co., Ltd +001C68 (base 16) Anhui Sun Create Electronics Co., Ltd + NO.199 Xiangzhang Road + Hefei Anhui 230088 + CN + +00-1C-66 (hex) UCAMP CO.,LTD +001C66 (base 16) UCAMP CO.,LTD + #1015, Kolon Science Valley ¥± + Seoul Guro-Dong,Guro-gu, 152-848 + KR + +00-1C-98 (hex) LUCKY TECHNOLOGY (HK) COMPANY LIMITED +001C98 (base 16) LUCKY TECHNOLOGY (HK) COMPANY LIMITED + FLAT/RM 1503 15/F ISLAND BEVERLEY NO 1 GREAT GEORGE STREET CAUSEWAY BAY + 999077 + HK + +00-1C-91 (hex) Gefen Inc. +001C91 (base 16) Gefen Inc. + 20600 Nordhoff Street + Chatsworth CA 91311 + US + +00-1C-81 (hex) NextGen Venturi LTD +001C81 (base 16) NextGen Venturi LTD + Technium 2 + Swansea West Glamorgan SA18PJ + GB + +00-1C-7A (hex) Perfectone Netware Company Ltd +001C7A (base 16) Perfectone Netware Company Ltd + Unit 815, Sun Fung Centre, + Kwai Chung + HK + +00-1C-7B (hex) Castlenet Technology Inc. +001C7B (base 16) Castlenet Technology Inc. + No.64, Chung-Shan Rd. + Tu-Cheng City Taipei 236 + TW + +00-1C-53 (hex) Synergy Lighting Controls +001C53 (base 16) Synergy Lighting Controls + One Lithonia Way + Conyers GA 30012 + US + +00-1C-4D (hex) Aplix IP Holdings Corporation +001C4D (base 16) Aplix IP Holdings Corporation + 2-20-9 Nishiwaseda + Shinjuku-ku Tokyo 169-0051 + JP + +00-1C-92 (hex) Tervela +001C92 (base 16) Tervela + 43 Nagog Park + Acton MA 01720 + US + +00-1C-8A (hex) Cirrascale Corporation +001C8A (base 16) Cirrascale Corporation + 9449 Carroll Park Drive + San Diego CA 92121 + US + +00-1C-38 (hex) Bio-Rad Laboratories, Inc. +001C38 (base 16) Bio-Rad Laboratories, Inc. + 245 Winter St. + Waltham MA 02451 + US + +00-1C-30 (hex) Mode Lighting (UK ) Ltd. +001C30 (base 16) Mode Lighting (UK ) Ltd. + The Maltings + Ware Hertfordshire SG12 9AD + GB + +00-1C-2E (hex) HPN Supply Chain +001C2E (base 16) HPN Supply Chain + 8000 Foothills Blvd + Roseville CA 95747 + US + +00-1C-2A (hex) Envisacor Technologies Inc. +001C2A (base 16) Envisacor Technologies Inc. + 237 Romina Drive + Concord Ontario L4K 4V3 + CA + +00-1C-02 (hex) Pano Logic +001C02 (base 16) Pano Logic + 2000 Seaport Drive, Suite 200 + Redwood City CA 94063 + US + +00-1C-05 (hex) Nonin Medical Inc. +001C05 (base 16) Nonin Medical Inc. + 13700 1st Avenue North + Plymouth MN 55441 + US + +00-1C-06 (hex) Siemens Numerical Control Ltd., Nanjing +001C06 (base 16) Siemens Numerical Control Ltd., Nanjing + No. 18 Siemens Road, Jiangning Development Zone + Nanjing JiangSu 211100 + CN + +00-1B-EA (hex) Nintendo Co., Ltd. +001BEA (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-1B-E5 (hex) 802automation Limited +001BE5 (base 16) 802automation Limited + 18 First Avenue + Worthing West Sussex BN14 9NJ + GB + +00-1B-E4 (hex) TOWNET SRL +001BE4 (base 16) TOWNET SRL + VIA DEI FINALE, 20 + 61043 CAGLI (PU) + IT + +00-1C-04 (hex) Airgain, Inc. +001C04 (base 16) Airgain, Inc. + 1930 Palomar Point Way + Carlsbad CA 92008 + US + +00-1C-01 (hex) ABB Oy Drives +001C01 (base 16) ABB Oy Drives + Hiomotie 13 + Helsinki FI-00380 + FI + +00-1B-FF (hex) Millennia Media inc. +001BFF (base 16) Millennia Media inc. + 4200 Day Spring CT + Placerville CA 95667 + US + +00-1B-F2 (hex) KWORLD COMPUTER CO., LTD +001BF2 (base 16) KWORLD COMPUTER CO., LTD + No. 113, Jian 2nd Rd., + Jhonghe Taipei county 235 + TW + +00-1B-F0 (hex) Value Platforms Limited +001BF0 (base 16) Value Platforms Limited + Rm 712-713, Building 9, 5, Science Park West Ave., + Shatin, + HK + +00-1C-1B (hex) Hyperstone GmbH +001C1B (base 16) Hyperstone GmbH + Line-Eid-Straße 3 + Konstanz Baden-Württemberg 78467 + DE + +00-1C-10 (hex) Cisco-Linksys, LLC +001C10 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +00-1B-D2 (hex) ULTRA-X ASIA PACIFIC Inc. +001BD2 (base 16) ULTRA-X ASIA PACIFIC Inc. + 5-1-15 Sotokanda + Tokyo Chiyoda-ku 101-0021 + JP + +00-1B-8D (hex) Electronic Computer Systems, Inc. +001B8D (base 16) Electronic Computer Systems, Inc. + 418 Donegal Drive + Towson MD 21286 + US + +00-1B-86 (hex) Bosch Access Systems GmbH +001B86 (base 16) Bosch Access Systems GmbH + Charlottenburger Allee 50 + AACHEN D-52068 + DE + +00-1B-C2 (hex) Integrated Control Technology Limitied +001BC2 (base 16) Integrated Control Technology Limitied + 11 Canaveral Drive + Auckland Auckland 0735 + NZ + +00-1B-BB (hex) RFTech Co.,Ltd +001BBB (base 16) RFTech Co.,Ltd + 339-17 Jwahang-Ri,Wonsam-Myun, + Yongin-Si Kyungki-Do 449-871 + KR + +00-1B-AA (hex) XenICs nv +001BAA (base 16) XenICs nv + Ambachtenlaan 44 + Leuven Vlaams-Brabant B-3001 + BE + +00-1B-7C (hex) A & R Cambridge +001B7C (base 16) A & R Cambridge + Pembroke Avenue + Cambridge CAMBS CB25 9QR + GB + +00-1B-5D (hex) Vololink Pty Ltd +001B5D (base 16) Vololink Pty Ltd + Level 2, 541 Blackburn Road + Mount Waverley Victoria 3149 + AU + +00-1B-5A (hex) Apollo Imaging Technologies, Inc. +001B5A (base 16) Apollo Imaging Technologies, Inc. + 18545 Rangeland Rd + Ramona CA 92065 + US + +00-1B-56 (hex) Tehuti Networks Ltd. +001B56 (base 16) Tehuti Networks Ltd. + 1, Shenkar St. + Hertzliya 46105 + IL + +00-1B-C6 (hex) Strato Rechenzentrum AG +001BC6 (base 16) Strato Rechenzentrum AG + Pascalstrasse 10 + D-10587 Berlin + DE + +00-1B-C4 (hex) Ultratec, Inc. +001BC4 (base 16) Ultratec, Inc. + 450 Science Drive + Madison WI 53711 + US + +00-1B-A1 (hex) Åmic AB +001BA1 (base 16) Åmic AB + Uppsala science park + Uppsala 75183 + SE + +00-1B-96 (hex) General Sensing +001B96 (base 16) General Sensing + Unit 716, Cyberport 1 + Pok Fu Lam + US + +00-1A-EA (hex) Radio Terminal Systems Pty Ltd +001AEA (base 16) Radio Terminal Systems Pty Ltd + 1st Floor + Laverton North Victoria 3026 + AU + +00-1A-DD (hex) PePWave Ltd +001ADD (base 16) PePWave Ltd + 17/F., Park Building, + Cheung Sha Wan Kowloon + HK + +00-1A-D6 (hex) JIAGNSU AETNA ELECTRIC CO.,LTD +001AD6 (base 16) JIAGNSU AETNA ELECTRIC CO.,LTD + NO.571 QIANHU ROAD,QIANQIAO INDUSTRY PARK,WUXI,JIANGSU,CHINA + WUXI JIANGSU 214151 + CN + +00-1A-D4 (hex) iPOX Technology Co., Ltd. +001AD4 (base 16) iPOX Technology Co., Ltd. + 15F-1, No.186, Jian-Yi Rd., Chung-Ho City, + Taipei 235 + TW + +00-1B-14 (hex) Carex Lighting Equipment Factory +001B14 (base 16) Carex Lighting Equipment Factory + 50 Chang Tang Rd., Yan Tian District, + Guangdong province + CN + +00-1B-15 (hex) Voxtel, Inc. +001B15 (base 16) Voxtel, Inc. + 12725 SW Millikan Way + Beaverton OR 97005 + US + +00-1B-09 (hex) Matrix Telecom Pvt. Ltd. +001B09 (base 16) Matrix Telecom Pvt. Ltd. + 394, GIDC, Makarpura, + Vadodara Gujarat 390010 + IN + +00-1B-03 (hex) Action Technology (SZ) Co., Ltd +001B03 (base 16) Action Technology (SZ) Co., Ltd + Action Technology Building Baoyuan Road, Xixiang, Bao'an District + Shenzhen Guangdong 518102 + CN + +00-1A-FB (hex) Joby Inc. +001AFB (base 16) Joby Inc. + 1535 Mission St. + San Francisco CA 94103 + US + +00-1A-FD (hex) EVOLIS +001AFD (base 16) EVOLIS + 29 avenue de la fontaine + Beaucouze 49070 + FR + +00-1B-1E (hex) HART Communication Foundation +001B1E (base 16) HART Communication Foundation + STE 1-350 + Austin TX 78759 + US + +00-1B-4C (hex) Signtech +001B4C (base 16) Signtech + 609 Seonil Technopia 609 + Sungnamsi Kyunggido 462-120 + KR + +00-1A-D5 (hex) KMC CHAIN INDUSTRIAL CO., LTD. +001AD5 (base 16) KMC CHAIN INDUSTRIAL CO., LTD. + 7F-8, No. 81, Sui-Lih Rd., Hsinchu + Hsinchu 300 + TW + +00-1A-D0 (hex) Albis Technologies AG +001AD0 (base 16) Albis Technologies AG + Albisriederstrasse 199 + CH 8047 Zuerich + CH + +00-1A-D3 (hex) Vamp Ltd. +001AD3 (base 16) Vamp Ltd. + PO Box 810 + Vaasa 65101 + FI + +00-1A-D8 (hex) AlsterAero GmbH +001AD8 (base 16) AlsterAero GmbH + Heidenkampsweg 45 + Hamburg 20097 + DE + +00-1A-DA (hex) Biz-2-Me Inc. +001ADA (base 16) Biz-2-Me Inc. + 1301 West Eau Gallie Blvd + Melbourne FL 32935 + US + +00-1A-6F (hex) MI.TEL s.r.l. +001A6F (base 16) MI.TEL s.r.l. + VIA GUIDO ROSSA, 22 + CORNATE D'ADDA MILANO 20040 + IT + +00-1A-71 (hex) Diostech Co., Ltd. +001A71 (base 16) Diostech Co., Ltd. + 151-21, Buk-ri, Namsa-myeon, + Yongin-city Gyeonggi-do 449 884 + KR + +00-1A-69 (hex) Wuhan Yangtze Optical Technology CO.,Ltd. +001A69 (base 16) Wuhan Yangtze Optical Technology CO.,Ltd. + 4#,Guanshan 2 Road + Wuhan Hubei 430073 + CN + +00-1A-67 (hex) Infinite QL Sdn Bhd +001A67 (base 16) Infinite QL Sdn Bhd + G.02, Block A, Dataran Hamodal + Petaling Jaya Selangor Darul Ehsan 46300 + MY + +00-1A-C3 (hex) Scientific-Atlanta, Inc +001AC3 (base 16) Scientific-Atlanta, Inc + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +00-1A-BF (hex) TRUMPF Laser Marking Systems AG +001ABF (base 16) TRUMPF Laser Marking Systems AG + Ausserfeld + Gruesch GR 7214 + CH + +00-1A-B8 (hex) Anseri Corporation +001AB8 (base 16) Anseri Corporation + 35E Industrial Way + Rochester NH 03867 + US + +00-1A-BC (hex) U4EA Technologies Ltd +001ABC (base 16) U4EA Technologies Ltd + City Point + Bristol BS1 6PL + GB + +00-1A-CB (hex) Autocom Products Ltd +001ACB (base 16) Autocom Products Ltd + Unit 4 Tachbrook Link, Tachbrook Park Drive + Warwick Warwickshire CV34 6RH + GB + +00-1A-CF (hex) C.T. ELETTRONICA +001ACF (base 16) C.T. ELETTRONICA + Via Caduti di Nassiriya 5 B + Barberino Val D'Elsa (FI) 50021 + IT + +00-1A-A3 (hex) DELORME +001AA3 (base 16) DELORME + 2 DELORME DRIVE + YARMOUTH MAINE 04096 + US + +00-1A-9B (hex) ADEC & Parter AG +001A9B (base 16) ADEC & Parter AG + Staldenbachstrasse 30 + Pfaeffikon ZH 8808 + CH + +00-1A-9D (hex) Skipper Wireless, Inc. +001A9D (base 16) Skipper Wireless, Inc. + Shinjuku-Sumitomo Bldg. 20F + Shinjuku Tokyo 163-0220 + JP + +00-1A-85 (hex) NV Michel Van de Wiele +001A85 (base 16) NV Michel Van de Wiele + M. Vandewielestraat 7 + Marke West-Vlaanderen 8510 + BE + +00-1A-8E (hex) 3Way Networks Ltd +001A8E (base 16) 3Way Networks Ltd + 7200 Cambridge Research Park + Cambridge Cambridgeshire CB5 9TL + GB + +00-1A-44 (hex) JWTrading Co., Ltd +001A44 (base 16) JWTrading Co., Ltd + 1590 Kwanyang-dong, Dongan-ku + Ahnyang Kyungki - do 431-060 + KR + +00-1A-49 (hex) Micro Vision Co.,LTD +001A49 (base 16) Micro Vision Co.,LTD + 1-9-15 + Niigata-city Niigata-ken 950-0986 + JP + +00-1A-3D (hex) Ajin Vision Co.,Ltd +001A3D (base 16) Ajin Vision Co.,Ltd + 1404, Mario-Tower, 222-12 + Seoul 152-050 + KR + +00-1A-41 (hex) INOCOVA Co.,Ltd +001A41 (base 16) INOCOVA Co.,Ltd + 5F SEOUL BD.736-17 + Yeoksam-Dong, Kangnam-Ku SEOUL 135-924 + KR + +00-1A-33 (hex) ASI Communications, Inc. +001A33 (base 16) ASI Communications, Inc. + 1042 E Guadalupe Rd + Tempe AZ 85283 + US + +00-1A-23 (hex) Ice Qube, Inc +001A23 (base 16) Ice Qube, Inc + 141 Wilson Ave + Greensburg Pa 15601 + US + +00-1A-1D (hex) PChome Online Inc. +001A1D (base 16) PChome Online Inc. + 11F, 105, Sec. 2, Tun-Hwa S. Rd. + Taipei 106 + TW + +00-1A-17 (hex) Teak Technologies, Inc. +001A17 (base 16) Teak Technologies, Inc. + 2901 Tasman Dr., Ste. #210 + Santa Clara CA 95054 + US + +00-1A-1C (hex) GT&T Engineering Pte Ltd +001A1C (base 16) GT&T Engineering Pte Ltd + 2 Ang Mo Kio St.64, Econ Building, #04-00 + Singapore 569084 + SG + +00-1A-1F (hex) Coastal Environmental Systems +001A1F (base 16) Coastal Environmental Systems + 820 First Avenue South + Seattle wa 98134 + US + +00-1A-64 (hex) IBM Corp +001A64 (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-1A-51 (hex) Alfred Mann Foundation +001A51 (base 16) Alfred Mann Foundation + P.O. Box 905 + Santa Clarita CA 91380-9005 + US + +00-1A-55 (hex) ACA-Digital Corporation +001A55 (base 16) ACA-Digital Corporation + 17 F, No. 866-7, Chung Cheng Rd., + Chung Ho City Taipei County 23586 + TW + +00-19-E6 (hex) TOYO MEDIC CO.,LTD. +0019E6 (base 16) TOYO MEDIC CO.,LTD. + 1-17-22 Kitahorie, Nishi-ku + Osaka 550-0014 + JP + +00-19-E2 (hex) Juniper Networks +0019E2 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-19-E8 (hex) Cisco Systems, Inc +0019E8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-DF (hex) Thomson Inc. +0019DF (base 16) Thomson Inc. + 101 West 103rd Street + Indianapolis IN 46290-1102 + US + +00-19-DD (hex) FEI-Zyfer, Inc. +0019DD (base 16) FEI-Zyfer, Inc. + 1515 S. Manchester + Anaheim CA 92802 + US + +00-19-B2 (hex) XYnetsoft Co.,Ltd +0019B2 (base 16) XYnetsoft Co.,Ltd + NO.158Zhenyu Street High Industries Development area + ChangChun JiLin 130000 + CN + +00-19-A4 (hex) Austar Technology (hang zhou) Co.,Ltd +0019A4 (base 16) Austar Technology (hang zhou) Co.,Ltd + 7-402,West Lake Software Part + Hang Zhou Zhe Jiang 310012 + CN + +00-19-AA (hex) Cisco Systems, Inc +0019AA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-B1 (hex) Arrow7 Corporation +0019B1 (base 16) Arrow7 Corporation + Kamijima 3-27-7 + Hamamatsu Shizuoka 433-8122 + JP + +00-19-B3 (hex) Stanford Research Systems +0019B3 (base 16) Stanford Research Systems + 1290-D Reamwood Ave + Sunnyvale CA 94089 + US + +00-1A-0A (hex) Adaptive Micro-Ware Inc. +001A0A (base 16) Adaptive Micro-Ware Inc. + 6917 Innovation Blvd + Fort Wayne IN 46818 + US + +00-1A-05 (hex) OPTIBASE LTD +001A05 (base 16) OPTIBASE LTD + 7 Shankar St. + Herzliya ISRAEL 46120 + IL + +00-19-D4 (hex) ICX Technologies +0019D4 (base 16) ICX Technologies + 3440 Francis-Hughes + Laval Quebec H7L 5A9 + CA + +00-19-CF (hex) SALICRU, S.A. +0019CF (base 16) SALICRU, S.A. + Av. Serra , 100 + Sta.Ma.Palautordera Barcelona 08460 + ES + +00-19-FC (hex) PT. Ufoakses Sukses Luarbiasa +0019FC (base 16) PT. Ufoakses Sukses Luarbiasa + Jl. Sultan Hasanudin No. 41 + Jakarta Selatan DKI Jakarta 12160 + ID + +00-19-F4 (hex) Convergens Oy Ltd +0019F4 (base 16) Convergens Oy Ltd + Westendintie 99 B + Espoo Uusimaa FIN-02160 + FI + +00-19-96 (hex) TurboChef Technologies Inc. +001996 (base 16) TurboChef Technologies Inc. + 4240 International Parkway + Carrollton Texas 75007 + US + +00-19-97 (hex) Soft Device Sdn Bhd +001997 (base 16) Soft Device Sdn Bhd + 67-2 Jalan 2/27F + Kuala Lumpur WP 53300 + MY + +00-19-98 (hex) SATO CORPORATION +001998 (base 16) SATO CORPORATION + 1-207,ONARI-CHO, + SAITAMA-SHI SAITAMA 330-0852 + JP + +00-19-9C (hex) CTRING +00199C (base 16) CTRING + #514, World Meridian Venture Center II + Keumcheon-gu Seoul 153-803 + KR + +00-19-46 (hex) Cianet Industria e Comercio S/A +001946 (base 16) Cianet Industria e Comercio S/A + rod SC401, km01 Tecnopolis/Alfama 4o. Andar + Florianopolis Santa Catarina 88030-902 + BR + +00-19-49 (hex) TENTEL COMTECH CO., LTD. +001949 (base 16) TENTEL COMTECH CO., LTD. + 3/F., NO. 42, LANE 80, SEC. 3, NAN-KANG RD., + TAIPEI 115 + TW + +00-19-44 (hex) Fossil Partners, L.P. +001944 (base 16) Fossil Partners, L.P. + 2280 N. Greenville Ave. + Richardson TX 75082 + US + +00-19-71 (hex) Guangzhou Unicomp Technology Co.,Ltd +001971 (base 16) Guangzhou Unicomp Technology Co.,Ltd + 7/F,North Tower,Jinshan Building.No.248 + Guangzhou Guangdong 510630 + CN + +00-19-64 (hex) Doorking Inc. +001964 (base 16) Doorking Inc. + 120 Glasgow St. + Inglewood CA. 90301 + US + +00-19-76 (hex) Xipher Technologies, LLC +001976 (base 16) Xipher Technologies, LLC + 156 River Road + Willington CT 06279 + US + +00-19-6C (hex) ETROVISION TECHNOLOGY +00196C (base 16) ETROVISION TECHNOLOGY + 2F, 19-5 San Chung Rd., + TAIPEI 115 + TW + +00-19-67 (hex) TELDAT Sp.J. +001967 (base 16) TELDAT Sp.J. + Kijowska 44 + Bydgoszcz woj. kujawsko-pomorskie 85-703 + PL + +00-19-52 (hex) ACOGITO Co., Ltd +001952 (base 16) ACOGITO Co., Ltd + #501 Shinyoung Palace Tower, 246-2, Seohyun + Sungnam Kyunggi 463-824 + KR + +00-19-8B (hex) Novera Optics Korea, Inc. +00198B (base 16) Novera Optics Korea, Inc. + 463-1 Jeon Min Dong Yuseong Gu + Deajeon 305-811 + KR + +00-19-61 (hex) Blaupunkt Embedded Systems GmbH +001961 (base 16) Blaupunkt Embedded Systems GmbH + Bahnhofsstrasse 16 + Schlitz 36110 + DE + +00-19-42 (hex) ON SOFTWARE INTERNATIONAL LIMITED +001942 (base 16) ON SOFTWARE INTERNATIONAL LIMITED + 9F, NO. 17, SEC. 1, CHENG-TE RD. + TAIPEI 103 + TW + +00-19-3F (hex) RDI technology(Shenzhen) Co.,LTD +00193F (base 16) RDI technology(Shenzhen) Co.,LTD + Building C1&C2, Xin Tang Industrial Zone,East BaiShiXia Village, Fuyong Town, Baoan District + SHENZHEN GUANGDONG province 518103 + CN + +00-19-41 (hex) Pitney Bowes, Inc +001941 (base 16) Pitney Bowes, Inc + 35 Waterview Drive + Shelton CT 06484 + US + +00-18-FD (hex) Optimal Technologies International Inc. +0018FD (base 16) Optimal Technologies International Inc. + 12 Spanish Main Drive + Freeport GBI + BS + +00-18-F0 (hex) JOYTOTO Co., Ltd. +0018F0 (base 16) JOYTOTO Co., Ltd. + 3F Sungwoo Bldg. 717-3, Sooseo-Dong + Seoul 135-220 + KR + +00-18-E9 (hex) Numata Corporation +0018E9 (base 16) Numata Corporation + 8-2-39 nanko-higashi + Osaka-shi Osaka-fu 559-0031 + JP + +00-19-08 (hex) Duaxes Corporation +001908 (base 16) Duaxes Corporation + 2-5, Kasumigaseki 3-chome, Chiyoda-ku. + Tokyo Foreign 100-6014 + JP + +00-19-0C (hex) Encore Electronics, Inc. +00190C (base 16) Encore Electronics, Inc. + 16483 Old Valley Blvd. + La Puente CA 91744 + US + +00-19-19 (hex) ASTEL Inc. +001919 (base 16) ASTEL Inc. + 59-7 Jang-dong Yusung-Gu + Daejeon Chungnam 305-343 + KR + +00-19-2D (hex) Nokia Corporation +00192D (base 16) Nokia Corporation + Rensingstraße 15 + Bochum NRW 44807 + DE + +00-18-EF (hex) Escape Communications, Inc. +0018EF (base 16) Escape Communications, Inc. + 2615 Pacific Coast Hwy + Hermosa Beach CA 90254 + US + +00-18-E6 (hex) Computer Hardware Design SIA +0018E6 (base 16) Computer Hardware Design SIA + Dzelzavas 120i + Riga LV-1021 + LV + +00-19-30 (hex) Cisco Systems, Inc +001930 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-27 (hex) ImCoSys Ltd +001927 (base 16) ImCoSys Ltd + Bundesstrasse 5 + Zug ZG 6300 + CH + +00-18-F7 (hex) Kameleon Technologies +0018F7 (base 16) Kameleon Technologies + 217, rue St Honoré + Paris 75001 + FR + +00-18-85 (hex) Avigilon Corporation +001885 (base 16) Avigilon Corporation + Box 378, 101 - 1001 West Broadway + Vancouver BC V6H 4E4 + CA + +00-18-88 (hex) GOTIVE a.s. +001888 (base 16) GOTIVE a.s. + Zámocká 34 + Bratislava 81101 + SK + +00-18-8A (hex) Infinova LLC +00188A (base 16) Infinova LLC + 51 Stouts Lane, Unit 1 & 2 + Monmouth Junction New Jersey 08852 + US + +00-18-86 (hex) EL-TECH, INC. +001886 (base 16) EL-TECH, INC. + A-711, WOOLIM LION'S VALLEY, 371-28 + SEOUL 150-834 + KR + +00-18-87 (hex) Metasystem SpA +001887 (base 16) Metasystem SpA + Via Oberdan 16 + Reggio Emilia RE 42100 + IT + +00-18-BE (hex) ANSA Corporation +0018BE (base 16) ANSA Corporation + 17F, No. 738, Chung Cheng Road + Chung Ho City Taipei County 235 + TW + +00-18-BA (hex) Cisco Systems, Inc +0018BA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-18-B4 (hex) Dawon Media Inc. +0018B4 (base 16) Dawon Media Inc. + Rm503. woolim e-biz center 170-5, Guro3dong Gurogu, + Seoul 152-769 + KR + +00-18-B6 (hex) S3C, Inc. +0018B6 (base 16) S3C, Inc. + 1010 Stewart Dr. + Sunnyvale California 94085 + US + +00-18-A3 (hex) ZIPPY TECHNOLOGY CORP. +0018A3 (base 16) ZIPPY TECHNOLOGY CORP. + 10F, No. 50, Mincyuan Rd., Sindian City + Taipei 231 + TW + +00-18-A0 (hex) Cierma Ascenseurs +0018A0 (base 16) Cierma Ascenseurs + 17 avenue guiglionda de saint agathe + Nice PACA 06300 + FR + +00-18-93 (hex) SHENZHEN PHOTON BROADBAND TECHNOLOGY CO.,LTD +001893 (base 16) SHENZHEN PHOTON BROADBAND TECHNOLOGY CO.,LTD + 2/F Hivac BLD,2th Langshan Rd,North Hi-Tech Industrial + Shenzhen Guangdong 518057 + CN + +00-18-B1 (hex) IBM Corp +0018B1 (base 16) IBM Corp + 2051 Mission College Blvd + Santa Clara CA 95054 + US + +00-18-7B (hex) 4NSYS Co. Ltd. +00187B (base 16) 4NSYS Co. Ltd. + 3F, Hana Bldg + Guro-Gu Seoul 152-100 + KR + +00-18-7F (hex) ZODIANET +00187F (base 16) ZODIANET + 23, rue des Fraisettes + PALAISEAU ESSONNE 91120 + FR + +00-18-7E (hex) RGB Spectrum +00187E (base 16) RGB Spectrum + 950 Marina Village Pkwy + Alameda CA 94501 + US + +00-18-9D (hex) Navcast Inc. +00189D (base 16) Navcast Inc. + Suite 612, 6711 Mississauga Road + Mississauga ON m2r 1a3 + CA + +00-18-D6 (hex) Swirlnet A/S +0018D6 (base 16) Swirlnet A/S + Diplomvej 381 + Lyngby DK-2800 + DK + +00-18-CD (hex) Erae Electronics Industry Co., Ltd +0018CD (base 16) Erae Electronics Industry Co., Ltd + #371-51, Gasan-dong + Geumchen-gu Seoul 153-803 + KR + +00-18-DB (hex) EPL Technology Ltd +0018DB (base 16) EPL Technology Ltd + LongDong,Longgang District + ShenZhen GuangDong 518116 + CN + +00-18-C8 (hex) ISONAS Inc. +0018C8 (base 16) ISONAS Inc. + 6325 Gunpark Drive + Boulder CO 80301 + US + +00-18-49 (hex) nVent, Schroff GmbH +001849 (base 16) nVent, Schroff GmbH + Langenalber Strasse 96-100 + Straubenhardt 75334 + DE + +00-18-46 (hex) Crypto S.A. +001846 (base 16) Crypto S.A. + V. Ipirou 45 + Marousi Athens 15125 + GR + +00-18-45 (hex) Pulsar-Telecom LLC. +001845 (base 16) Pulsar-Telecom LLC. + Zaharova, 18a + Penza 440044 + RU + +00-18-1E (hex) GDX Technologies Ltd. +00181E (base 16) GDX Technologies Ltd. + 61-63 Back Sneddon Street + Paisley Renfrewshire PA3 2DD + GB + +00-18-1C (hex) Exterity Limited +00181C (base 16) Exterity Limited + Ridge Way, Hillend Industrial Estate + Dunfermline Fife KY11 9JD + GB + +00-18-63 (hex) Veritech Electronics Limited +001863 (base 16) Veritech Electronics Limited + 8F, 67, Sec. 1, Zhongshan Road, Xinzhuang, + Taipei 242 + TW + +00-18-5A (hex) uControl, Inc. +00185A (base 16) uControl, Inc. + 5914 W. Courtyard Drive + Austin TX 78730 + US + +00-18-52 (hex) StorLink Semiconductors, Inc. +001852 (base 16) StorLink Semiconductors, Inc. + 1804 N. Shoreline Boulevard + Mountain View CA 94043 + US + +00-18-50 (hex) Secfone Kft +001850 (base 16) Secfone Kft + 51 Bercsenyi str + Jaszbereny 5100 + HU + +00-18-58 (hex) TagMaster AB +001858 (base 16) TagMaster AB + Kronborgsgréind 1 + Kista Stockholm S-16487 + SE + +00-18-24 (hex) Kimaldi Electronics, S.L. +001824 (base 16) Kimaldi Electronics, S.L. + Ctra. de Rubí, 292 B + Terrassa Barcelona 08228 + ES + +00-18-3D (hex) Vertex Link Corporation +00183D (base 16) Vertex Link Corporation + Meitetsu Fudosan Takebashi Bldg 6F + Chiyoda-ku Tokyo 101-0054 + JP + +00-18-25 (hex) Private +001825 (base 16) Private + +00-18-79 (hex) dSys +001879 (base 16) dSys + Soeflinger Str. 100 + Ulm BW 89077 + DE + +00-18-03 (hex) ArcSoft Shanghai Co. LTD +001803 (base 16) ArcSoft Shanghai Co. LTD + 20th Floor, Suite (EAST) 2008, China Merchants Plaza, 333 + Shanghai 200041 + CN + +00-17-EF (hex) IBM Corp +0017EF (base 16) IBM Corp + 2051 Mission College Blvd + Santa Clara CA 95054 + US + +00-17-F5 (hex) LIG NEOPTEK +0017F5 (base 16) LIG NEOPTEK + 926 Gosaek-dong + Suwon-si Gyeonggi-do 441-813 + KR + +00-17-CD (hex) CEC Wireless R&D Ltd. +0017CD (base 16) CEC Wireless R&D Ltd. + West M5 Building,No.1 East Road + Beijing 100016 + CN + +00-17-D0 (hex) Opticom Communications, LLC +0017D0 (base 16) Opticom Communications, LLC + 1050 Connecticut Avenue, NW + Washington DC 20036 + US + +00-17-C6 (hex) Cross Match Technologies Inc +0017C6 (base 16) Cross Match Technologies Inc + 400, boul. Jean-Lesage + Québec G1K 8W1 + CA + +00-17-FE (hex) TALOS SYSTEM INC. +0017FE (base 16) TALOS SYSTEM INC. + 6191 CORNERSTONE CT. STE #109 + SAN DIEGO CA 92121 + US + +00-17-F8 (hex) Motech Industries Inc. +0017F8 (base 16) Motech Industries Inc. + 6F, No. 248, Sec. 3, Pei-Shen Rd., + Taipei Hsien 222 + TW + +00-17-C3 (hex) KTF Technologies Inc. +0017C3 (base 16) KTF Technologies Inc. + 4th Fl., Central Tower, 265-3, Seohyun-Dong + Sungnam-City Kyunggi-Do 463-769 + KR + +00-17-B7 (hex) Tonze Technology Co. +0017B7 (base 16) Tonze Technology Co. + 5F-10, No.6, Lane 180, + Taipei 11490 + TW + +00-17-AB (hex) Nintendo Co., Ltd. +0017AB (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-18-07 (hex) Fanstel Corp. +001807 (base 16) Fanstel Corp. + 7466 E. Monte Cristo Ave. + Scottsdale Arizona 85260 + US + +00-18-08 (hex) SightLogix, Inc. +001808 (base 16) SightLogix, Inc. + 745 Alexander Road + Princeton NJ 08540 + US + +00-17-CE (hex) Screen Service Spa +0017CE (base 16) Screen Service Spa + Via G.Di Vittorio 17 + Brescia 25125 + IT + +00-17-DB (hex) CANKO TECHNOLOGIES INC. +0017DB (base 16) CANKO TECHNOLOGIES INC. + 5 FL. DONG SUNG BLDG. 17-8 + SEOUL 150-874 + KR + +00-17-D6 (hex) Bluechips Microhouse Co.,Ltd. +0017D6 (base 16) Bluechips Microhouse Co.,Ltd. + 212/2 M.10 Tambol Umong + Lamphun 51150 + TH + +00-17-87 (hex) Brother, Brother & Sons ApS +001787 (base 16) Brother, Brother & Sons ApS + Ved Amagerbanen 9 + Copenhagen S DK-2300 + DK + +00-17-89 (hex) Zenitron Corporation +001789 (base 16) Zenitron Corporation + No. 8, Lane 250, Sinhu 2nd Rd., Neihu District, + Taipei 11494 + TW + +00-17-60 (hex) Naito Densei Machida MFG.CO.,LTD +001760 (base 16) Naito Densei Machida MFG.CO.,LTD + 2-17-28 Fuchinobe + Sagamihara Kanagawa 229-0006 + JP + +00-17-61 (hex) Private +001761 (base 16) Private + +00-17-68 (hex) Zinwave Ltd +001768 (base 16) Zinwave Ltd + Zinwave Ltd, Harston Mill + Cambridge Cambridgeshire CB2 5GG + GB + +00-17-69 (hex) Cymphonix Corp +001769 (base 16) Cymphonix Corp + 8871 S. Sandy Parkway, Suite 150 + Sandy UT 84070 + US + +00-17-62 (hex) Solar Technology, Inc. +001762 (base 16) Solar Technology, Inc. + 7620 Cetronia Road + Allentown PA 18106 + US + +00-17-8F (hex) NINGBO YIDONG ELECTRONIC CO.,LTD. +00178F (base 16) NINGBO YIDONG ELECTRONIC CO.,LTD. + No.65 Siming East Rd + Yuyao City, Zhejiang Province Zhejiang Province China P.C 315400 + CN + +00-17-94 (hex) Cisco Systems, Inc +001794 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-17-8A (hex) DARTS TECHNOLOGIES CORP. +00178A (base 16) DARTS TECHNOLOGIES CORP. + 2F,No.119,Chien Kang Rd., + Chung-Ho Taipei Hsien 235 + TW + +00-17-34 (hex) ADC Telecommunications +001734 (base 16) ADC Telecommunications + 541 E Trimble Road + San Jose California 95134-1224 + US + +00-17-2E (hex) FXC Inc. +00172E (base 16) FXC Inc. + 10-16 6F, Nihonbashi Tomizawa-Chou, Chuo-ku + Tokyo 103-0006 + JP + +00-17-2B (hex) Global Technologies Inc. +00172B (base 16) Global Technologies Inc. + 4/F Kicox Bldg.,188-5,Guro-Dong,Guro-gu, + Seoul 152-848 + KR + +00-17-72 (hex) ASTRO Strobel Kommunikationssysteme GmbH +001772 (base 16) ASTRO Strobel Kommunikationssysteme GmbH + Olefant 1-3 + Bergisch Gladbach NRW 51427 + DE + +00-17-3E (hex) LeucotronEquipamentos Ltda. +00173E (base 16) LeucotronEquipamentos Ltda. + Rua Jorge Dionisio Barbosa, 312 + Santa Rita do Sapucai Minas Gerais 37.540-000 + BR + +00-17-98 (hex) Azonic Technology Co., LTD +001798 (base 16) Azonic Technology Co., LTD + 15F-3, No. 163, Sec., 1 Keelung Rd. + Taipei 110 + TW + +00-17-47 (hex) Trimble +001747 (base 16) Trimble + 345 SW Avery Ave + Corvallis OR 97333 + US + +00-17-7A (hex) ASSA ABLOY AB +00177A (base 16) ASSA ABLOY AB + Theres Svenssons gata 15 + Goteborg 41755 + SE + +00-16-F4 (hex) Eidicom Co., Ltd. +0016F4 (base 16) Eidicom Co., Ltd. + Polychem B/D 4th Floor, 900-1 + Anyang-si Kyeonggi-do 431-060 + KR + +00-16-E7 (hex) Dynamix Promotions Limited +0016E7 (base 16) Dynamix Promotions Limited + 788-790, Finchley Road + London NW11 7TJ + GB + +00-16-E5 (hex) FORDLEY DEVELOPMENT LIMITED +0016E5 (base 16) FORDLEY DEVELOPMENT LIMITED + ROOM 706, 7TH FLOOR, YU SUNG BOON BUILDING, 107-111 DES VOEUX ROAD, CENTRAL, + + HK + +00-16-E6 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +0016E6 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + Pin-Jen City, Taoyuan + 324 + TW + +00-17-20 (hex) Image Sensing Systems, Inc. +001720 (base 16) Image Sensing Systems, Inc. + 1600 University Ave. W. + St. Paul MN 55104 + US + +00-17-1A (hex) Winegard Company +00171A (base 16) Winegard Company + 3000 Kirkwood Street + Burlington IA 52601 + US + +00-16-C8 (hex) Cisco Systems, Inc +0016C8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-16-C4 (hex) SiRF Technology, Inc. +0016C4 (base 16) SiRF Technology, Inc. + 217 Devcon Dr. + San Jose CA 95112 + US + +00-16-F3 (hex) CAST Information Co., Ltd +0016F3 (base 16) CAST Information Co., Ltd + 5F MSA Bldg. 891-43 Dacchi-Dong, + SEOUL 135-280 + KR + +00-16-F5 (hex) Dalian Golden Hualu Digital Technology Co.,Ltd +0016F5 (base 16) Dalian Golden Hualu Digital Technology Co.,Ltd + No.1 Hua Road,Qixianling + Dalian LiaoNing 116023 + CN + +00-16-F1 (hex) OmniSense, LLC +0016F1 (base 16) OmniSense, LLC + 72 sams point road + Ladys Island SC 29907 + US + +00-16-DD (hex) Gigabeam Corporation +0016DD (base 16) Gigabeam Corporation + 407 Springpark Place + Herndon VA 20170 + US + +00-17-1C (hex) NT MicroSystems, Inc. +00171C (base 16) NT MicroSystems, Inc. + 1-5-3-2F Tamagawadai + Setagaya Tokyo 158-0096 + JP + +00-17-16 (hex) Qno Technology Inc. +001716 (base 16) Qno Technology Inc. + 6F-2, No.25, Puding Road + Hsinchu Taiwan 300 + TW + +00-17-26 (hex) m2c Electronic Technology Ltd. +001726 (base 16) m2c Electronic Technology Ltd. + 2403, 24/F, Nanyang Plaza + Kwuntong Hong Kong 999 999 + CN + +00-17-21 (hex) FITRE S.p.A. +001721 (base 16) FITRE S.p.A. + Via Valsolda, 15 + MILANO MI 20142 + IT + +00-16-F9 (hex) CETRTA POT, d.o.o., Kranj +0016F9 (base 16) CETRTA POT, d.o.o., Kranj + Planina 3 + Kranj SI 4000 + SI + +00-17-0A (hex) INEW DIGITAL COMPANY +00170A (base 16) INEW DIGITAL COMPANY + Supply Bureau 3th floor KT&G 203-1, + Daejeon 306-712 + KR + +00-16-BD (hex) ATI Industrial Automation +0016BD (base 16) ATI Industrial Automation + 1031 Goodworth Drive + Apex North Carolina 27539-3869 + US + +00-16-C0 (hex) Semtech Corporation +0016C0 (base 16) Semtech Corporation + 200 Flynn Rd + Camarillo California 93012 + US + +00-16-C2 (hex) Avtec Systems Inc +0016C2 (base 16) Avtec Systems Inc + 14432 Albemarle Point Place + Chantilly Virginia 20151 + US + +00-16-BA (hex) WEATHERNEWS INC. +0016BA (base 16) WEATHERNEWS INC. + NAKASE 1-3 MTG + CHIBA 262-0032 + US + +00-16-B2 (hex) DriveCam Inc +0016B2 (base 16) DriveCam Inc + 3954 Murphy Canyon Road + San Diego CA 92123 + US + +00-16-B3 (hex) Photonicbridges (China) Co., Ltd. +0016B3 (base 16) Photonicbridges (China) Co., Ltd. + No. 900, Yishan road, + Shanghai 200233 + US + +00-16-AD (hex) BT-Links Company Limited +0016AD (base 16) BT-Links Company Limited + Rm 802, Nan Fung Centre, 264-298 Castle Peak Rd + + HK + +00-16-6E (hex) Arbitron Inc. +00166E (base 16) Arbitron Inc. + 9705 Patuxent Woods Drive + Columbia MD 21046 + US + +00-16-AF (hex) Shenzhen Union Networks Equipment Co.,Ltd. +0016AF (base 16) Shenzhen Union Networks Equipment Co.,Ltd. + Yihai Square east building 2307, Chuangye road, Nanshan District + Shenzhen Guangdong 518054 + CN + +00-16-9E (hex) TV One Ltd +00169E (base 16) TV One Ltd + Unit V Continental Approach + Margate Kent CT9 4JG + GB + +00-16-6A (hex) TPS +00166A (base 16) TPS + 145 quai de Stalingrad + Issy Les Moulineaux Ile de France 92137 + FR + +00-16-63 (hex) KBT Mobile +001663 (base 16) KBT Mobile + 4F, Polaris I, 15-3, Jeongja-dong, Bundang-gu + Seongnam-si, Gyeonggi-do 463-811 + KR + +00-16-9F (hex) Vimtron Electronics Co., Ltd. +00169F (base 16) Vimtron Electronics Co., Ltd. + 7F., No.9, Alley 2, Lane 35 + Neihu District Taipei City 11492 + TW + +00-16-9A (hex) Quadrics Ltd +00169A (base 16) Quadrics Ltd + 1 Bridewell Street + Bristol BS1 2AA + GB + +00-16-92 (hex) Scientific-Atlanta, Inc. +001692 (base 16) Scientific-Atlanta, Inc. + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +00-16-91 (hex) Moser-Baer AG +001691 (base 16) Moser-Baer AG + Spitalstrasse 7 + Sumiswald BE 3454 + CH + +00-16-88 (hex) ServerEngines LLC +001688 (base 16) ServerEngines LLC + 209 N. Fair Oaks Avenue + Sunnyvale CA 94085 + US + +00-16-8B (hex) Paralan Corporation +00168B (base 16) Paralan Corporation + 455 Ruffner St. + San Diego CA 92111 + US + +00-16-82 (hex) Pro Dex, Inc +001682 (base 16) Pro Dex, Inc + 1800 NW 169th Place + Beaverton Oregon 97006 + US + +00-16-0A (hex) SWEEX Europe BV +00160A (base 16) SWEEX Europe BV + Ampereweg 3 + Delft Zuid-Holland 2627 BG + NL + +00-16-02 (hex) CEYON TECHNOLOGY CO.,LTD. +001602 (base 16) CEYON TECHNOLOGY CO.,LTD. + 13F Samsung Insurance B/D. #942-9 + Suwon-City Gyeonggi-Do 442-832 + KR + +00-16-00 (hex) CelleBrite Mobile Synchronization +001600 (base 16) CelleBrite Mobile Synchronization + 25 Basel St + Petach Tikva 49170 + IL + +00-15-F4 (hex) Eventide +0015F4 (base 16) Eventide + 1 Alsan Way + Little Ferry NJ 07643 + US + +00-16-29 (hex) Nivus GmbH +001629 (base 16) Nivus GmbH + Im Täle 2 + Eppingen Baden-Württemberg 75031 + DE + +00-16-21 (hex) Colorado Vnet +001621 (base 16) Colorado Vnet + 255 E. 6th St. + Loveland CO 80537 + US + +00-16-1A (hex) Dametric AB +00161A (base 16) Dametric AB + Box 120 + Skarholmen Stockholm SE-12723 + SE + +00-16-15 (hex) Nittan Company, Limited +001615 (base 16) Nittan Company, Limited + 11-6, 1-chome, Hatagaya + Shibuya-ku Tokyo 151-8535 + JP + +00-16-16 (hex) BROWAN COMMUNICATION INC. +001616 (base 16) BROWAN COMMUNICATION INC. + No.1 Jen-Ai Road, HsinChu Industrial Park, + HuKou Hsiang HsinChu Hsien 303 + TW + +00-16-17 (hex) MSI +001617 (base 16) MSI + No.69, Li-De St, Jung-Ho City + Taipei Hsien 235 + TW + +00-16-2E (hex) Space Shuttle Hi-Tech Co., Ltd. +00162E (base 16) Space Shuttle Hi-Tech Co., Ltd. + No. 226, Wu-Ho St., Wu-Lung Village, + Hsinchu Hsien 307 + TW + +00-16-2A (hex) Antik computers & communications s.r.o. +00162A (base 16) Antik computers & communications s.r.o. + Razusova 2 + Kosice SK SK-04001 + SK + +00-16-56 (hex) Nintendo Co., Ltd. +001656 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-16-51 (hex) Exeo Systems +001651 (base 16) Exeo Systems + 1650, rue Michelin, suite 201 + Laval Québec H7L 4R3 + CA + +00-16-10 (hex) Carina Technology +001610 (base 16) Carina Technology + 690A Discovery Drive + Huntsville AL 35806 + US + +00-16-06 (hex) Ideal Industries +001606 (base 16) Ideal Industries + 15070 Ave. of Science #200 + San Diego CA 92128 + US + +00-16-07 (hex) Curves International Inc. +001607 (base 16) Curves International Inc. + 100 Ritchie Road + Waco Texas 76712 + US + +00-16-54 (hex) Flex-P Industries Sdn. Bhd. +001654 (base 16) Flex-P Industries Sdn. Bhd. + No.128-12-2, Menara UMNO, + Georgetown Penang 10400 + US + +00-16-31 (hex) Xteam +001631 (base 16) Xteam + room 801, No.102 international Science & Techology Park + Beijing 8610 + CN + +00-16-4B (hex) Quorion Data Systems GmbH +00164B (base 16) Quorion Data Systems GmbH + An der Klinge 6 + Erfurt Thuringia 99095 + DE + +00-15-94 (hex) BIXOLON CO.,LTD +001594 (base 16) BIXOLON CO.,LTD + 502-508,Digital Empire Bldg. + Yeongtong-Gu,Suwon Gyeonggi-Do 443-813 + KR + +00-15-90 (hex) Hectronic GmbH +001590 (base 16) Hectronic GmbH + Allmendstraße 15 + Bonndorf Baden-Württemberg 79848 + DE + +00-15-8C (hex) Liab ApS +00158C (base 16) Liab ApS + Oestre Alle 6 + Stoevring DK-9530 + DK + +00-15-8F (hex) NTT Advanced Technology Corporation +00158F (base 16) NTT Advanced Technology Corporation + Shinjuku Mitsui Bldg. 2-1-1, Nishi-shinjuku, + Shinjuku-ku Tokyo 163-0431 + JP + +00-15-ED (hex) Fulcrum Microsystems, Inc. +0015ED (base 16) Fulcrum Microsystems, Inc. + 26630 Agoura Road + Calabasas CA 91302 + US + +00-15-F0 (hex) EGO BV +0015F0 (base 16) EGO BV + Parade 15 + 's-Hertogenbosch Noord-Brabant 5211KL + NL + +00-15-EE (hex) Omnex Control Systems +0015EE (base 16) Omnex Control Systems + #74 - 1833 Coast Meridian Rd. + Port Coquitlam BC V3C 6G5 + CA + +00-15-C8 (hex) FlexiPanel Ltd +0015C8 (base 16) FlexiPanel Ltd + 7 bis rue Lalo + Paris 75016 + FR + +00-15-C0 (hex) DIGITAL TELEMEDIA CO.,LTD. +0015C0 (base 16) DIGITAL TELEMEDIA CO.,LTD. + 17TH FLOOR, CHINA YUSE BUILDING, + SHENZHEN GUANGDONG 518040 + CN + +00-15-C2 (hex) 3M Germany +0015C2 (base 16) 3M Germany + Carl Schurz Str. 1 + Neuss NRW 41453 + US + +00-15-88 (hex) Salutica Allied Solutions Sdn Bhd +001588 (base 16) Salutica Allied Solutions Sdn Bhd + 3 Jalan Zarib 6 + Lahat, Ipoh Perak 31500 + MY + +00-15-83 (hex) IVT corporation +001583 (base 16) IVT corporation + Shangdi Xinxi road, Haidian District + Beijing 100085 + US + +00-15-85 (hex) Aonvision Technolopy Corp. +001585 (base 16) Aonvision Technolopy Corp. + 2F, No. 58, Park 2nd Ave. Science-Based Industrial Park, + Hsinchu 300 + TW + +00-15-A5 (hex) DCI Co., Ltd. +0015A5 (base 16) DCI Co., Ltd. + 4th Fl. Susung B/D, 893-4 + Daejeon 305-330 + KR + +00-15-B2 (hex) Advanced Industrial Computer, Inc. +0015B2 (base 16) Advanced Industrial Computer, Inc. + 17970 E. Ajax Circle + City of Industry CA 91748 + US + +00-15-DA (hex) IRITEL A.D. +0015DA (base 16) IRITEL A.D. + Batajnicki put 23 + Beograd Serbia 11080 + YU + +00-15-4A (hex) WANSHIH ELECTRONIC CO., LTD +00154A (base 16) WANSHIH ELECTRONIC CO., LTD + 3F 72, WU KONG 6th RD., + TAIPEI HSIEN TAIWAN 248 + TW + +00-15-4C (hex) Saunders Electronics +00154C (base 16) Saunders Electronics + 192 Gannett Drive + South Portland ME 04106 + US + +00-15-4D (hex) Netronome Systems, Inc. +00154D (base 16) Netronome Systems, Inc. + 3159 Unionville Road + Cranberry Twp. PA 16066 + US + +00-15-49 (hex) Dixtal Biomedica Ind. Com. Ltda +001549 (base 16) Dixtal Biomedica Ind. Com. Ltda + R. Eng. Francisco Pitta Brito, 703 + São Paulo SP 04753-080 + BR + +00-15-3D (hex) ELIM PRODUCT CO. +00153D (base 16) ELIM PRODUCT CO. + 602-2 GAYANG TECHNO TOWN, GAYANG, 3-DONG + SEOUL 157-793 + KR + +00-15-44 (hex) coM.s.a.t. AG +001544 (base 16) coM.s.a.t. AG + Besselstraße 3 + Mannheim D-68219 + US + +00-15-39 (hex) Technodrive srl +001539 (base 16) Technodrive srl + Via Leonardo da Vinci 162 + Trezzano S/N Milan 20090 + IT + +00-15-31 (hex) KOCOM +001531 (base 16) KOCOM + 5F, KOCOM Bldg., 260-7 + SEOUL 157-040 + KR + +00-15-35 (hex) OTE Spa +001535 (base 16) OTE Spa + via Barsanti 8 + Florence FI 50127 + IT + +00-15-36 (hex) Powertech co.,Ltd +001536 (base 16) Powertech co.,Ltd + #705, dongyoung Venturestel, 199-32 + Anyang City Kyoungki-do 430-010 + US + +00-15-2B (hex) Cisco Systems, Inc +00152B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-15-2C (hex) Cisco Systems, Inc +00152C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-15-28 (hex) Beacon Medical Products LLC d.b.a. BeaconMedaes +001528 (base 16) Beacon Medical Products LLC d.b.a. BeaconMedaes + 14408 W 105TH ST + LENEXA KS 66215 + US + +00-15-27 (hex) Balboa Instruments +001527 (base 16) Balboa Instruments + 1382 Bell Ave + Tustin CA 92780 + US + +00-15-21 (hex) Horoquartz +001521 (base 16) Horoquartz + BP 251 + FONTENAY LE COMTE VENDEE 85205 + FR + +00-15-20 (hex) Radiocrafts AS +001520 (base 16) Radiocrafts AS + Sandakerveien 64 + Oslo 0484 + NO + +00-15-66 (hex) A-First Technology Co., Ltd. +001566 (base 16) A-First Technology Co., Ltd. + 5F, No. 111-2, Shin-Teh Rd., + San-Chung City Taipei Shien 241 + TW + +00-15-6B (hex) Perfisans Networks Corp. +00156B (base 16) Perfisans Networks Corp. + 4118 14th Avenue + Markham Ontario L3R 0J3 + CA + +00-15-47 (hex) AiZen Solutions Inc. +001547 (base 16) AiZen Solutions Inc. + 10F-1, No.29, Puding Rd. + Hsinchu Hsinchu County 300 + TW + +00-15-79 (hex) Lunatone Industrielle Elektronik GmbH +001579 (base 16) Lunatone Industrielle Elektronik GmbH + Rennbahnweg 55 + Wien 1220 + AT + +00-14-D7 (hex) Datastore Technology Corp +0014D7 (base 16) Datastore Technology Corp + 9F, NO.10, SEC.1, Chung Hsing RD., Wu-Ku + Taipei Hsien, 248 + TW + +00-14-DD (hex) Covergence Inc. +0014DD (base 16) Covergence Inc. + One Clock Tower Place, Suite 200 + Maynard MA 01754 + US + +00-14-D4 (hex) K Technology Corporation +0014D4 (base 16) K Technology Corporation + 325 Ganbara + Kami-gun Miyagi-ken 981-4263 + JP + +00-14-CF (hex) INVISIO Communications +0014CF (base 16) INVISIO Communications + Stamholmen 157 + Hvidovre 2650 + DK + +00-14-BE (hex) Wink communication technology CO.LTD +0014BE (base 16) Wink communication technology CO.LTD + Huijiang Ind Blding Dashi Town + Guang zhou Guang dong 511430 + CN + +00-15-11 (hex) Data Center Systems +001511 (base 16) Data Center Systems + 14802 Venture Drive + Dallas TX 75234 + US + +00-15-0E (hex) OPENBRAIN TECHNOLOGIES CO., LTD. +00150E (base 16) OPENBRAIN TECHNOLOGIES CO., LTD. + #804,ANYANG K-CENTER,1591-9 , BURIM-DONG,DONGAN-GU, + ANYANG KYUNGGI-DO 431-815 + KR + +00-15-0D (hex) Hoana Medical, Inc. +00150D (base 16) Hoana Medical, Inc. + 828 Fort Street Mall + Honolulu HI 96813 + US + +00-15-1C (hex) LENECO +00151C (base 16) LENECO + 6th.,Dong Moon Good Morning Tower 1 + Kyeong Ki-Do GoYang-Si 411-817 + KR + +00-15-19 (hex) StoreAge Networking Technologies +001519 (base 16) StoreAge Networking Technologies + 63 Bar-Yehuda st. + Nesher 36651 + IL + +00-15-06 (hex) Neo Photonics +001506 (base 16) Neo Photonics + 910 E. California St. + Sunnyvale CA 94085 + US + +00-15-04 (hex) GAME PLUS CO., LTD. +001504 (base 16) GAME PLUS CO., LTD. + 164-57, Yeonghwa-dong, Jangan-gu + Suwon Gyeonggi-do 440-818 + KR + +00-15-05 (hex) Actiontec Electronics, Inc +001505 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +00-14-FE (hex) Artech Electronics +0014FE (base 16) Artech Electronics + #301, Yangjae Bldg., 276-2 + Seoul 137-895 + KR + +00-14-DE (hex) Sage Instruments Inc. +0014DE (base 16) Sage Instruments Inc. + 240 Airport Blvd. + Freedom CA 95019 + US + +00-14-DF (hex) HI-P Tech Corporation +0014DF (base 16) HI-P Tech Corporation + 1-27-23 Higashitokorozawa + Tokorozawa Saitama 359-0021 + JP + +00-14-E6 (hex) AIM Infrarotmodule GmbH +0014E6 (base 16) AIM Infrarotmodule GmbH + Soeflingerstraße 100 + Ulm BW 89077 + DE + +00-14-F3 (hex) ViXS Systems Inc +0014F3 (base 16) ViXS Systems Inc + 2235 Sheppard Ave East + TORONTO ONTARIO M2J 5B5 + CA + +00-14-7E (hex) InnerWireless +00147E (base 16) InnerWireless + 1155 Kas Drive, Suite 200 + Richardson TX 75081 + US + +00-14-7D (hex) Aeon Digital International +00147D (base 16) Aeon Digital International + 31-6, The Bund Center + Shanghai SH 200002 + CN + +00-14-76 (hex) MultiCom Industries Limited +001476 (base 16) MultiCom Industries Limited + Room 1206-7, Manhattan Center, + Kwai Chung, N.T. + HK + +00-14-73 (hex) Bookham Inc +001473 (base 16) Bookham Inc + 10 Brewer Hunt Way + Kanata ON K2K 2B5 + CA + +00-14-89 (hex) B15402100 - JANDEI, S.L. +001489 (base 16) B15402100 - JANDEI, S.L. + POL. IND. POCOMACO, E-28 + LA Coruña 15190 + ES + +00-14-80 (hex) Hitachi-LG Data Storage Korea, Inc +001480 (base 16) Hitachi-LG Data Storage Korea, Inc + 19-1,Cheongho-ri + Pyungtaik Kyunggi-Do 451-713 + KR + +00-14-B6 (hex) Enswer Technology Inc. +0014B6 (base 16) Enswer Technology Inc. + 1F No.70 Sec.2 Chung Shun St. + Taipei 116 + TW + +00-14-B2 (hex) mCubelogics Corporation +0014B2 (base 16) mCubelogics Corporation + 4F, Unibooks B/D, 514-1, Dogok-Dong, KangNam + Seoul 135-270 + KR + +00-14-AE (hex) Wizlogics Co., Ltd. +0014AE (base 16) Wizlogics Co., Ltd. + Rm#1321, Samchang Plaza, 173, + Seoul 121-745 + KR + +00-14-A6 (hex) Teranetics, Inc. +0014A6 (base 16) Teranetics, Inc. + 3965 Freedom Circle + Santa Clara CA 95054 + US + +00-14-69 (hex) Cisco Systems, Inc +001469 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-14-BA (hex) Carvers SA de CV +0014BA (base 16) Carvers SA de CV + Alvarez del Castillo 1550 + Guadalajara Jalisco 44620 + MX + +00-14-8A (hex) Elin Ebg Traction Gmbh +00148A (base 16) Elin Ebg Traction Gmbh + Cumberlandstrasse 32 + Vienna 1140 + AT + +00-14-91 (hex) Daniels Electronics Ltd. dbo Codan Rado Communications +001491 (base 16) Daniels Electronics Ltd. dbo Codan Rado Communications + 43 Erie St + Victoria BC V8V 1P8 + CA + +00-14-6E (hex) H. Stoll GmbH & Co. KG +00146E (base 16) H. Stoll GmbH & Co. KG + Stollweg + Reutlingen Deutschland 72760 + DE + +00-14-AA (hex) Ashly Audio, Inc. +0014AA (base 16) Ashly Audio, Inc. + 847 Holt Road + Webster NY 14580 + US + +00-14-09 (hex) MAGNETI MARELLI S.E. S.p.A. +001409 (base 16) MAGNETI MARELLI S.E. S.p.A. + ZI Nord, Allee d'Argenson + CHATELLERAULT 86100 + FR + +00-14-0B (hex) FIRST INTERNATIONAL COMPUTER, INC. +00140B (base 16) FIRST INTERNATIONAL COMPUTER, INC. + FIC BUILDING, NO.300, YANG GUANG ST., + TAIPEI COUNTY 114 + TW + +00-13-FD (hex) Nokia Danmark A/S +0013FD (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-14-00 (hex) MINERVA KOREA CO., LTD +001400 (base 16) MINERVA KOREA CO., LTD + #203, SH Sienne, Seohyeon-Dong + Seongnam-Si Gyeonggi-Do 463-821 + KR + +00-13-FC (hex) SiCortex, Inc +0013FC (base 16) SiCortex, Inc + One Clocktower Place + Maynard MA 01754 + US + +00-13-F6 (hex) Cintech +0013F6 (base 16) Cintech + 21a route de la wantzenau + Hoenheim 67800 + FR + +00-14-4F (hex) Oracle Corporation +00144F (base 16) Oracle Corporation + 500 Oracle Parkway + Redwood Shores CA 94065 + US + +00-14-56 (hex) Edge Products +001456 (base 16) Edge Products + 1080 South Depot Drive + Ogden Utah 84404 + US + +00-14-50 (hex) Heim Systems GmbH +001450 (base 16) Heim Systems GmbH + Friedrich Ebert Strasse + Bergisch Gladbach NRW 51429 + DE + +00-14-52 (hex) CALCULEX,INC. +001452 (base 16) CALCULEX,INC. + 132 W. LAS CRUCES AVE. + LAS CRUCES NEW MEXICO 88001 + US + +00-14-42 (hex) ATTO CORPORATION +001442 (base 16) ATTO CORPORATION + 1-25-23 Hongo, + Tokyo 113-8425 + JP + +00-14-47 (hex) BOAZ Inc. +001447 (base 16) BOAZ Inc. + 282 Pukok-ri SongSan-myon Dangzin-gun Chungcheongnam-do, 343-834 + Seoul SeoCho-gu 137-070 + KR + +00-14-3E (hex) AirLink Communications, Inc. +00143E (base 16) AirLink Communications, Inc. + 3159 Corporate Place + Hayward CA 94545 + US + +00-14-5D (hex) WJ Communications, Inc. +00145D (base 16) WJ Communications, Inc. + 401 River Oaks Parkway + San Jose CA 95134 + US + +00-14-3B (hex) Sensovation AG +00143B (base 16) Sensovation AG + Markhallen -Str + Radolfzell Baden-Württemberg 78315 + DE + +00-14-2D (hex) Toradex AG +00142D (base 16) Toradex AG + Altsagenstrasse 5 + Horw LU 6048 + CH + +00-14-29 (hex) V Center Technologies Co., Ltd. +001429 (base 16) V Center Technologies Co., Ltd. + 7F-7, NO.35, Hsintai Rd. + Jubei City Hsinchu 302 + TW + +00-14-14 (hex) Jumpnode Systems LLC. +001414 (base 16) Jumpnode Systems LLC. + 800 Washington Ave N. + Minneapolis MN 55041 + US + +00-14-1E (hex) P.A. Semi, Inc. +00141E (base 16) P.A. Semi, Inc. + 3965 Freedom Circle, Fl 8 + Santa Clara CA 95054 + US + +00-13-CB (hex) Zenitel Norway AS +0013CB (base 16) Zenitel Norway AS + Sandaker v 24 c + Oslo 0403 + NO + +00-13-CF (hex) 4Access Communications +0013CF (base 16) 4Access Communications + 1 N. LaSalle St. + Chicago IL 60602 + US + +00-13-BE (hex) Virtual Conexions +0013BE (base 16) Virtual Conexions + 410 rue St-Nicolas, suite 600 + Montréal QUÉBEC H2Y 2P5 + CA + +00-13-B9 (hex) BM SPA +0013B9 (base 16) BM SPA + VIA MILANO 54/56 + Rozzano 20089 + IT + +00-13-AB (hex) Telemotive AG +0013AB (base 16) Telemotive AG + Breitwiesen + Muehlhausen Baden Wuerttemberg 73347 + DE + +00-13-C9 (hex) Beyond Achieve Enterprises Ltd. +0013C9 (base 16) Beyond Achieve Enterprises Ltd. + XIN LIAN HI-TECH INDUSTRIAL AREA, HU-MEN + DONGGUAN GUANG DONG + CN + +00-13-C6 (hex) OpenGear, Inc +0013C6 (base 16) OpenGear, Inc + 7984 South Welby Park #101 + Salt Lake City UTAH 84088 + US + +00-13-F3 (hex) Giga-byte Communications Inc. +0013F3 (base 16) Giga-byte Communications Inc. + 8F, No.43, Fu-Hsin Road. Hsin-Tien + Taipei Hsien 231 + TW + +00-13-F4 (hex) Psitek (Pty) Ltd +0013F4 (base 16) Psitek (Pty) Ltd + The Vineyards Office Estate + Tyger Valley Cape Town 7530 + ZA + +00-13-AC (hex) Sunmyung Electronics Co., LTD +0013AC (base 16) Sunmyung Electronics Co., LTD + LARGO-PLAZA 8F, Janghang-Dong + Koyang Kyungki 411-837 + KR + +00-13-A8 (hex) Tanisys Technology +0013A8 (base 16) Tanisys Technology + 11001 Lakeline blvd + Austin TX 78717 + US + +00-13-DA (hex) Diskware Co., Ltd +0013DA (base 16) Diskware Co., Ltd + 1-4-12 Kiba + Koto-ku Tokyo 135-0042 + JP + +00-13-D8 (hex) Princeton Instruments +0013D8 (base 16) Princeton Instruments + 3660 Quakerbridge Road + Trenton NJ 08619 + US + +00-13-99 (hex) STAC Corporation. +001399 (base 16) STAC Corporation. + 2-16-37 fujimi + sayama-shi saitama 350-1306 + JP + +00-13-E9 (hex) VeriWave, Inc. +0013E9 (base 16) VeriWave, Inc. + 9600 SW Oak St. + Portland OR 97223 + US + +00-13-95 (hex) congatec AG +001395 (base 16) congatec AG + Auwiesenstrasse 5 + Deggendorf 94469 + DE + +00-13-56 (hex) FLIR Radiation Inc +001356 (base 16) FLIR Radiation Inc + 100 Midland Rd + Oak Ridge TN 37830 + US + +00-13-5A (hex) Project T&E Limited +00135A (base 16) Project T&E Limited + Room 3C, 2/F. Wah Shing Center, + Kwun Tong, Kowloon, 852 + HK + +00-13-61 (hex) Biospace Co., Ltd. +001361 (base 16) Biospace Co., Ltd. + 10th Floor, Poonglim Bldg, 823 Yeoksam 1-dong + Gangnam-gu Seoul 135-784 + KR + +00-13-62 (hex) ShinHeung Precision Co., Ltd. +001362 (base 16) ShinHeung Precision Co., Ltd. + DaeHa Bldg. 401 + YoungDungPoGu Seoul 150-050 + KR + +00-13-4F (hex) Rapidus Wireless Networks Inc. +00134F (base 16) Rapidus Wireless Networks Inc. + 47 - 14550 Morris Valley Road + Agassiz British Columbia V0M 1A1 + CA + +00-13-78 (hex) Qsan Technology, Inc. +001378 (base 16) Qsan Technology, Inc. + 4F., No.103, Ruihu St., Neihu Dist. + Taipei 114 + TW + +00-13-7A (hex) Netvox Technology Co., Ltd. +00137A (base 16) Netvox Technology Co., Ltd. + No.21-1 Sec. 1 Chung Hua West Road + Tainan 702 + TW + +00-13-81 (hex) CHIPS & Systems, Inc. +001381 (base 16) CHIPS & Systems, Inc. + 4750 Patrick Henry Drive + Santa Clara California 95054 + US + +00-13-79 (hex) PONDER INFORMATION INDUSTRIES LTD. +001379 (base 16) PONDER INFORMATION INDUSTRIES LTD. + 14F,No.77,lane700, Chung-Cheng Road + Hsin-Tien City Taipei Hsien 231 + TW + +00-13-2C (hex) MAZ Brandenburg GmbH +00132C (base 16) MAZ Brandenburg GmbH + Pascalstraße 10a + Berlin Berlin 10587 + DE + +00-13-24 (hex) Schneider Electric Ultra Terminal +001324 (base 16) Schneider Electric Ultra Terminal + Industriparken 32 + Copenhagen 2750 + DK + +00-13-26 (hex) ECM Systems Ltd +001326 (base 16) ECM Systems Ltd + Ellifoot Park + HULL East Yorkshire HU12 9DZ + GB + +00-13-27 (hex) Data Acquisitions limited +001327 (base 16) Data Acquisitions limited + 84 Gasson street + Christchurch + NZ + +00-13-67 (hex) Narayon. Co., Ltd. +001367 (base 16) Narayon. Co., Ltd. + #502 Hyochang T/W 181-3 + Seoul 138-220 + KR + +00-13-5C (hex) OnSite Systems, Inc. +00135C (base 16) OnSite Systems, Inc. + 3900 Freedom Circle + Santa Clara CA 95054-1222 + US + +00-13-5F (hex) Cisco Systems, Inc +00135F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-13-3B (hex) Speed Dragon Multimedia Limited +00133B (base 16) Speed Dragon Multimedia Limited + Room 1312, Vanta Industrial Centre, + Kwai Chung N.T. + HK + +00-13-38 (hex) FRESENIUS-VIAL +001338 (base 16) FRESENIUS-VIAL + Le Grand Chemin + BREZINS 38590 + FR + +00-13-2D (hex) iWise Communications +00132D (base 16) iWise Communications + Unit 3C, Arden Grove + Cape Town 7441 + ZA + +00-13-74 (hex) Atheros Communications, Inc. +001374 (base 16) Atheros Communications, Inc. + 529 Almanor Avenue + Sunnyvale CA 94085-3512 + US + +00-13-69 (hex) Honda Electron Co., LED. +001369 (base 16) Honda Electron Co., LED. + Kanematsu Building 3 Floor + Chuo-ku Tokyo 104-0031 + JP + +00-13-42 (hex) Vision Research, Inc. +001342 (base 16) Vision Research, Inc. + 190 Parish Drive + Wayne NJ 07470 + US + +00-13-40 (hex) AD.EL s.r.l. +001340 (base 16) AD.EL s.r.l. + via S. Pertini,5 + Martellago VENEZIA 30030 + IT + +00-13-0C (hex) HF System Corporation +00130C (base 16) HF System Corporation + 1520-1 Ayukai + Nishiokitama-Gun Yamagata-Ken 992-0771 + JP + +00-13-0F (hex) EGEMEN Bilgisayar Muh San ve Tic LTD STI +00130F (base 16) EGEMEN Bilgisayar Muh San ve Tic LTD STI + Fevzi Cakmak 2 Sok 31/A + ANKARA CANKAYA 06440 + TR + +00-13-13 (hex) GuangZhou Post & Telecom Equipment ltd +001313 (base 16) GuangZhou Post & Telecom Equipment ltd + 139# Zhongshan Ave + Guangzhou Guangdong 510630 + CN + +00-12-CB (hex) CSS Inc. +0012CB (base 16) CSS Inc. + 151 Superior Blvd. + Mississauga Ontario L5T2L1 + CA + +00-12-CE (hex) Advanced Cybernetics Group +0012CE (base 16) Advanced Cybernetics Group + 2953 Bunker Hill Lane + Santa Clara CA 95054 + US + +00-12-CA (hex) Mechatronic Brick Aps +0012CA (base 16) Mechatronic Brick Aps + Alsion 2 + 6400 Sonderborg + DK + +00-12-C7 (hex) SECURAY Technologies Ltd.Co. +0012C7 (base 16) SECURAY Technologies Ltd.Co. + Tianjin Haitai Industrial Base ErWei Road + Tianjin 300384 + CN + +00-12-CD (hex) ASEM SpA +0012CD (base 16) ASEM SpA + Via Buia, 4 + ARTEGNA Udine I-33011 + IT + +00-12-E8 (hex) Fraunhofer IMS +0012E8 (base 16) Fraunhofer IMS + Finkenstrasse 61 + Duisburg NRW 47057 + DE + +00-12-DD (hex) Shengqu Information Technology (Shanghai) Co., Ltd. +0012DD (base 16) Shengqu Information Technology (Shanghai) Co., Ltd. + No.1 Building,No. 690 Bibo Road,Pudong New Area + Shanghai 201203 + CN + +00-13-1D (hex) Scanvaegt International A/S +00131D (base 16) Scanvaegt International A/S + P.O.Pedersens vej 18 + Aarhus Jylland 8200 N + DK + +00-13-18 (hex) DGSTATION Co., Ltd. +001318 (base 16) DGSTATION Co., Ltd. + Rm.401, Bldg.A, Bundang Techno Park 150, Yatap-Dong, Bundang-Gu, Sungnam-Si, Gyunggi-Do, 463-760, Korea + Sungnam Gyunggi 463-760 + KR + +00-13-1A (hex) Cisco Systems, Inc +00131A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-12-F4 (hex) Belco International Co.,Ltd. +0012F4 (base 16) Belco International Co.,Ltd. + 212, Yeokok-Dong, Wonmi-gu + Puchun-Si Kyongki-Do 420-100 + KR + +00-12-F5 (hex) Imarda New Zealand Limited +0012F5 (base 16) Imarda New Zealand Limited + Suite G16, National Innovation Centre, + Eveleigh NSW 2015 + NZ + +00-12-E0 (hex) Codan Limited +0012E0 (base 16) Codan Limited + 81 Graves Street + Newton South 5074 + AU + +00-12-DE (hex) Radio Components Sweden AB +0012DE (base 16) Radio Components Sweden AB + Viderogatan 3B + Kista 16422 + SE + +00-13-01 (hex) IronGate S.L. +001301 (base 16) IronGate S.L. + C\Alcala 268, primera planta + Madrid 28027 + ES + +00-12-F6 (hex) MDK CO.,LTD. +0012F6 (base 16) MDK CO.,LTD. + 2-6-27 Ibarame + Kashiwazaki City Niigata 9451341 + JP + +00-12-F1 (hex) IFOTEC +0012F1 (base 16) IFOTEC + ZAC Champfeuillet + VOIRON 38507 + FR + +00-12-F8 (hex) WNI Resources, LLC +0012F8 (base 16) WNI Resources, LLC + 2146 Bering Drive + San Jose California 95131-2013 + US + +00-12-7C (hex) SWEGON AB +00127C (base 16) SWEGON AB + Box 300 + KVÄNUM VÄSTRA GÖTALAND SE 535 23 + SE + +00-12-78 (hex) International Bar Code +001278 (base 16) International Bar Code + 160 Oak Street + Glastonbury CT 06033 + US + +00-12-7A (hex) Sanyu Industry Co.,Ltd. +00127A (base 16) Sanyu Industry Co.,Ltd. + Midori-ku Hakusan1-11-11 + Yokohama-shi Kanagawa-ken 226-0006 + JP + +00-12-68 (hex) IPS d.o.o. +001268 (base 16) IPS d.o.o. + C. Ljubljanske brigade 17 + Ljubljana SI-1000 + SI + +00-12-AC (hex) ONTIMETEK INC. +0012AC (base 16) ONTIMETEK INC. + 9Fl.,Owner's Tower + Sungnam-Si Kyunggi-Do 463-825 + KR + +00-12-BC (hex) Echolab LLC +0012BC (base 16) Echolab LLC + 267 Boston Road + Billerica MA 01862 + US + +00-12-BD (hex) Avantec Manufacturing Limited +0012BD (base 16) Avantec Manufacturing Limited + Unit L, 7/F, Camelpaint Bldg, Block 3 + 852 + HK + +00-12-AB (hex) WiLife, Inc. +0012AB (base 16) WiLife, Inc. + 132 E. 13065 S., Suite 150 + Draper UT 84020 + US + +00-12-9B (hex) E2S Electronic Engineering Solutions, S.L. +00129B (base 16) E2S Electronic Engineering Solutions, S.L. + Sant Ferran 10 + Barcelona 08031 + ES + +00-12-98 (hex) MICO ELECTRIC(SHENZHEN) LIMITED +001298 (base 16) MICO ELECTRIC(SHENZHEN) LIMITED + + SHENZHEN GUANGDONG 518040 + CN + +00-12-72 (hex) Redux Communications Ltd. +001272 (base 16) Redux Communications Ltd. + POB 101 + Modiin 71700 + IL + +00-12-6A (hex) OPTOELECTRONICS Co., Ltd. +00126A (base 16) OPTOELECTRONICS Co., Ltd. + 3-1Kamiaokinishi 1-chome + Kawaguchi Saitama Pref. 333-0845 + JP + +00-12-C0 (hex) HotLava Systems, Inc. +0012C0 (base 16) HotLava Systems, Inc. + 6329 Chelton Drive + Oakland CA 94611 + US + +00-12-B7 (hex) PTW Freiburg +0012B7 (base 16) PTW Freiburg + Loerracher Strasse 7 + Freiburg 79115 + DE + +00-12-A1 (hex) BluePacket Communications Co., Ltd. +0012A1 (base 16) BluePacket Communications Co., Ltd. + 10F-1, No. 420, Sec. 1, Keelung Rd., 110, + Taipei 110 + TW + +00-12-06 (hex) iQuest (NZ) Ltd +001206 (base 16) iQuest (NZ) Ltd + P.O.Box 15169 + Hamilton Waikato 3243 + NZ + +00-12-07 (hex) Head Strong International Limited +001207 (base 16) Head Strong International Limited + Unit 9, 20/F, Metropole Square, + Guangdong + HK + +00-12-09 (hex) Fastrax Ltd +001209 (base 16) Fastrax Ltd + Valimotie 7 + Vantaa FI 01510 + FI + +00-12-0B (hex) Chinasys Technologies Limited +00120B (base 16) Chinasys Technologies Limited + 10/F,CAGW Building,No.30 Haidian South Road + Beijing 100080 + CN + +00-12-05 (hex) Terrasat Communications, Inc. +001205 (base 16) Terrasat Communications, Inc. + 235 Vineyard Court, suite 100 + Morgan Hill California 95037 + US + +00-12-38 (hex) SetaBox Technology Co., Ltd. +001238 (base 16) SetaBox Technology Co., Ltd. + 9F-1, No. 293-3, Sec2, Fu-Hsing S. Rd. + Taipei 106 + TW + +00-12-3C (hex) Second Rule LLC +00123C (base 16) Second Rule LLC + 4119 Walnut Street + Philadelphia PA 19104 + US + +00-12-3E (hex) ERUNE technology Co., Ltd. +00123E (base 16) ERUNE technology Co., Ltd. + No. 429, Chin-San 2nd street, + Tao Yuan 326 + TW + +00-12-54 (hex) Spectra Technologies Holdings Company Ltd +001254 (base 16) Spectra Technologies Holdings Company Ltd + Unit 1301-09, Tower II + 852 + HK + +00-12-4F (hex) nVent +00124F (base 16) nVent + 1665 Utica Avenue, Suite 700 + St Louis Park MN 55416 + US + +00-12-21 (hex) B.Braun Melsungen AG +001221 (base 16) B.Braun Melsungen AG + Schwarzenberger Weg 73-79 + Melsungen Hessen 34212 + DE + +00-12-12 (hex) PLUS Corporation +001212 (base 16) PLUS Corporation + 1033-1, Oshitate + Inagi-shi Tokyo 206-0811 + JP + +00-12-13 (hex) Metrohm AG +001213 (base 16) Metrohm AG + Oberdorfstrasse 68 + Herisau AR 9101 + CH + +00-12-18 (hex) ARUZE Corporation +001218 (base 16) ARUZE Corporation + Ariake Frontier Building A + Kohtoh-ku Tokyo 135-0063 + JP + +00-12-49 (hex) Delta Elettronica S.p.A. +001249 (base 16) Delta Elettronica S.p.A. + Via Astico 41 + Varese 21100 + IT + +00-12-4D (hex) Inducon BV +00124D (base 16) Inducon BV + Kerklaan 26 + Leimuiden ZH 2541 CG + NL + +00-12-66 (hex) Swisscom Hospitality Services SA +001266 (base 16) Swisscom Hospitality Services SA + Chemin de l'Etang 65 + 1211 Geneva + CH + +00-12-5E (hex) CAEN +00125E (base 16) CAEN + via Vetraia, 11 + Viareggio LUCCA 55049 + IT + +00-12-5D (hex) CyberNet Inc. +00125D (base 16) CyberNet Inc. + #205, Lotte Suntech City, 513-15 + Sungnam Kyunggi 462-806 + KR + +00-12-23 (hex) Pixim +001223 (base 16) Pixim + 915 Linda Vista Ave. + Mountain View CA 94043 + US + +00-12-3A (hex) Posystech Inc., Co. +00123A (base 16) Posystech Inc., Co. + Room 407, Daeryung Techno Town 6, + Seoul 153-771 + KR + +00-12-34 (hex) Camille Bauer +001234 (base 16) Camille Bauer + Aargauerstr. 7 + Wohlen AG 5610 + CH + +00-11-E3 (hex) Thomson, Inc. +0011E3 (base 16) Thomson, Inc. + 101 West 103rd Street + Indianapolis IN 46290 + US + +00-11-DC (hex) Glunz & Jensen +0011DC (base 16) Glunz & Jensen + Selandia Park 1 + Ringsted 4100 + DK + +00-11-96 (hex) Actuality Systems, Inc. +001196 (base 16) Actuality Systems, Inc. + 25 Corporate Drive + Burlington MA 01803 + US + +00-11-87 (hex) Category Solutions, Inc +001187 (base 16) Category Solutions, Inc + 1021 W. Adams St + Chicago IL 60607 + US + +00-11-90 (hex) Digital Design Corporation +001190 (base 16) Digital Design Corporation + 3820 Ventura Drive + Arlington Heights IL 60004 + US + +00-11-C4 (hex) Terminales de Telecomunicacion Terrestre, S.L. +0011C4 (base 16) Terminales de Telecomunicacion Terrestre, S.L. + Poligono Europolis, Calle C 26 + Las Rozas Madrid 28230 + ES + +00-11-CB (hex) Jacobsons AB +0011CB (base 16) Jacobsons AB + Nedralid s 32 + Motala 591 97 + SE + +00-11-F7 (hex) Shenzhen Forward Industry Co., Ltd +0011F7 (base 16) Shenzhen Forward Industry Co., Ltd + 4b1 F5.8, Tian An Cyber Park, Chengongmiao, + Shenzhen Guangdong 518040 + CN + +00-11-D3 (hex) NextGenTel Holding ASA +0011D3 (base 16) NextGenTel Holding ASA + Sandslimarka 31 + Bergen Hordaland 5861 + NO + +00-11-AB (hex) TRUSTABLE TECHNOLOGY CO.,LTD. +0011AB (base 16) TRUSTABLE TECHNOLOGY CO.,LTD. + 12FL.-1,NO.167,Fu-Shing N.Rd.,Sung-Shan area + Taipei 105 + TW + +00-11-A5 (hex) Fortuna Electronic Corp. +0011A5 (base 16) Fortuna Electronic Corp. + 3F, No.9, Sec.1, ChangAn East Rd., + Taipei 104 + TW + +00-11-3C (hex) Micronas GmbH +00113C (base 16) Micronas GmbH + Hans-Bunte-Strasse 19 + Freiburg D-79108 + DE + +00-11-31 (hex) UNATECH. CO.,LTD +001131 (base 16) UNATECH. CO.,LTD + A-727 ,GEOPYUNG TOWN,203-1 + KANGNAM-GU SEOUL 135-010 + US + +00-11-27 (hex) TASI, Inc +001127 (base 16) TASI, Inc + 5551 Dry Fork Road + Cleves OH 45002 + US + +00-11-2A (hex) Niko NV +00112A (base 16) Niko NV + Industriepark West 40 + Sint-Niklaas O/V 9100 + BE + +00-11-2B (hex) NetModule AG +00112B (base 16) NetModule AG + Meriedweg 11 + Niederwangen CH 3172 + CH + +00-11-6F (hex) Netforyou Co., LTD. +00116F (base 16) Netforyou Co., LTD. + 1121-4 3F, Kwanyang-dong, Dongan-gu + Anyang-si Kyunggi-do 431-804 + KR + +00-11-71 (hex) DEXTER Communications, Inc. +001171 (base 16) DEXTER Communications, Inc. + 2F Shinsung B/D 404-1 + Sungnam Gyunggi 463-420 + KR + +00-11-67 (hex) Integrated System Solution Corp. +001167 (base 16) Integrated System Solution Corp. + 3F, No. 2-1, industry East Rd., I + Hsinchu 300 + TW + +00-11-6D (hex) American Time and Signal +00116D (base 16) American Time and Signal + 140 Third St. South + Dassel MN 55325 + US + +00-11-60 (hex) ARTDIO Company Co., LTD +001160 (base 16) ARTDIO Company Co., LTD + 7th FL.., No.476, Min-Hu RD., Hsin-Chu, + Hsinchu 300 + TW + +00-11-54 (hex) Webpro Technologies Inc. +001154 (base 16) Webpro Technologies Inc. + 2F-1, No.81, Sec. 4, Chungching N. Rd., + Taipei 111 + TW + +00-11-45 (hex) ValuePoint Networks +001145 (base 16) ValuePoint Networks + 350 Townsend St Ste 320 + San Francisco, CA 94107 + US + +00-11-51 (hex) Mykotronx +001151 (base 16) Mykotronx + 359 Van Ness Way + Torrance CA 90501 + US + +00-11-4E (hex) 690885 Ontario Inc. +00114E (base 16) 690885 Ontario Inc. + 205 Annagem Blvd. + Mississauga Ontario L5T 2V1 + CA + +00-11-2D (hex) iPulse Systems +00112D (base 16) iPulse Systems + Unit 3, Riverside Industrial Park + Gauteng Johannesburg 1618 + ZA + +00-11-7B (hex) Büchi Labortechnik AG +00117B (base 16) Büchi Labortechnik AG + Meierseggstrasse 40 + Flawil 9230 SG + CH + +00-0F-EE (hex) XTec, Incorporated +000FEE (base 16) XTec, Incorporated + 5775 Blue Lagoon Drive + Miami Florida 33126 + US + +00-0F-E4 (hex) Pantech Co.,Ltd +000FE4 (base 16) Pantech Co.,Ltd + Shinsong B/D 3F, 25-12, + Youngdeungpo-GU Seoul 150-711 + KR + +00-0F-E7 (hex) Lutron Electronics Co., Inc. +000FE7 (base 16) Lutron Electronics Co., Inc. + 7200 Suter Rd. + Coopersburg PA 18036-1299 + US + +00-0F-E6 (hex) MBTech Systems, Inc. +000FE6 (base 16) MBTech Systems, Inc. + 412 1st Ave SE + Cullman Alabama 35055 + US + +00-0F-DA (hex) YAZAKI CORPORATION +000FDA (base 16) YAZAKI CORPORATION + 1500 MISHUKU + SUSONO-CITY SHIZUOKA-PREF 410-1194 + JP + +00-0F-EF (hex) Thales e-Transactions GmbH +000FEF (base 16) Thales e-Transactions GmbH + Konrad-Zuse-Straße 19-21 + Bad Hersfeld Hessen 36251 + DE + +00-0F-E9 (hex) GW TECHNOLOGIES CO.,LTD. +000FE9 (base 16) GW TECHNOLOGIES CO.,LTD. + No.38 Shangdi Xilu,Haidian District + Beijing 100085 + CN + +00-0F-E1 (hex) ID DIGITAL CORPORATION +000FE1 (base 16) ID DIGITAL CORPORATION + 6th Fl., Mirae Bldg., 271-1, Seohyun-dong, Bundang-ku, Sungnam-si, Keongki-do, South Korea + Sungnam-Si Keongki-do 463-050 + KR + +00-0F-DF (hex) SOLOMON Technology Corp. +000FDF (base 16) SOLOMON Technology Corp. + No.42,Sing Zhong Rd.,Nei Hu Dist., + Taipei 114 + TW + +00-0F-FE (hex) G-PRO COMPUTER +000FFE (base 16) G-PRO COMPUTER + first arrange C YingHu industrial estate QingXi country DongGuan city + DongGuan GuangDong 523648 + CN + +00-11-0B (hex) Franklin Technology Systems +00110B (base 16) Franklin Technology Systems + 20406 Earl St + Torrance CA 90503 + US + +00-11-05 (hex) Sunplus Technology Co., Ltd. +001105 (base 16) Sunplus Technology Co., Ltd. + 19, Innovation First Road, Hsinchu Science Park + Hsinchu 300 + TW + +00-11-02 (hex) Aurora Multimedia Corp. +001102 (base 16) Aurora Multimedia Corp. + 205 Commercial Court + Morganville New Jersey 07751-1070 + US + +00-11-23 (hex) Appointech, Inc. +001123 (base 16) Appointech, Inc. + 6F-2 No.192 Tung-Kuan Rd. + Hsinchu 300 + TW + +00-11-0F (hex) netplat,Inc. +00110F (base 16) netplat,Inc. + 2F Olympia Center, 828-10, Yeoksam-dong, Gangnam-gu + SEOUL 135-935 + KR + +00-0F-D6 (hex) Sarotech Co., Ltd +000FD6 (base 16) Sarotech Co., Ltd + HanGang Bldg, 1549-7, Seocho-Dong, + Seoul 137-070 + KR + +00-11-15 (hex) EPIN Technologies, Inc. +001115 (base 16) EPIN Technologies, Inc. + Acorn Campus + Cupertino CA 95014 + US + +00-0F-C7 (hex) Dionica R&D Ltd. +000FC7 (base 16) Dionica R&D Ltd. + Bologna Centre, F11 + Mosta MST13 + MT + +00-0F-64 (hex) D&R Electronica Weesp BV +000F64 (base 16) D&R Electronica Weesp BV + Rijnkade 15B + WEESP NH 1382GS + NL + +00-0F-75 (hex) First Silicon Solutions +000F75 (base 16) First Silicon Solutions + 13939 Forest Lane + Larkspur CO 80118 + US + +00-0F-7C (hex) ACTi Corporation +000F7C (base 16) ACTi Corporation + 7F., No. 1, Alley 20, Lane 407, Sec. 2, Tiding Blvd., + Taipei 114 + TW + +00-0F-7A (hex) BeiJing NuQX Technology CO.,LTD +000F7A (base 16) BeiJing NuQX Technology CO.,LTD + Room 812,8F Tower B,YinWang Center, No.113,Zhi Chun Road, + Beijing 100086 + CN + +00-0F-AD (hex) FMN communications GmbH +000FAD (base 16) FMN communications GmbH + Grimmelallee 4 + Nordhausen Thüringen 99734 + DE + +00-0F-AB (hex) Kyushu Electronics Systems Inc. +000FAB (base 16) Kyushu Electronics Systems Inc. + 3-3, Kongo 2-Chome, Yahatanishi Ward + Kitakyushu City Fukuoka Pref. 807-1263 + JP + +00-0F-AC (hex) IEEE 802.11 +000FAC (base 16) IEEE 802.11 + 4125 Highlander Parkway + Richfield Ohio 44286 + US + +00-0F-72 (hex) Sandburst +000F72 (base 16) Sandburst + 600 Federal St + Andover MA 01810 + US + +00-0F-B3 (hex) Actiontec Electronics, Inc +000FB3 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +00-0F-9C (hex) Panduit Corp +000F9C (base 16) Panduit Corp + 17301 Ridgeland Ave + Tinley Park Illinois 60477 + US + +00-0F-C8 (hex) Chantry Networks +000FC8 (base 16) Chantry Networks + 1900 Minnesota Court + Mississauga Ontario L5N 3C9 + CA + +00-0F-BB (hex) Nokia Siemens Networks GmbH & Co. KG. +000FBB (base 16) Nokia Siemens Networks GmbH & Co. KG. + Werner-von-Siemens Straße 2-6 + Bruchsal Baden-Württemberg 76646 + DE + +00-0F-BC (hex) Onkey Technologies, Inc. +000FBC (base 16) Onkey Technologies, Inc. + 780 Montague Expressway, Inc. + San Jose CA 95131 + US + +00-0F-B6 (hex) Europlex Technologies +000FB6 (base 16) Europlex Technologies + Clonshaugh Business & Tech. Park + Clonshaugh Dublin 17 + IE + +00-0F-B9 (hex) Adaptive Instruments +000FB9 (base 16) Adaptive Instruments + 577 Main Street + Hudson MA 01749 + US + +00-0F-98 (hex) Avamax Co. Ltd. +000F98 (base 16) Avamax Co. Ltd. + B1, No. 51, Section 2, ChongQing S. Rd. + Taipei + TW + +00-0F-97 (hex) Avanex Corporation +000F97 (base 16) Avanex Corporation + 40919 Encyclopedia Circle + Fremont CA 94538 + US + +00-0F-96 (hex) Telco Systems, Inc. +000F96 (base 16) Telco Systems, Inc. + 15 Berkshire Road + Mansfield MA 02048 + US + +00-0F-8B (hex) Orion MultiSystems Inc +000F8B (base 16) Orion MultiSystems Inc + 3375 Scott Blvd Suite 338 + Santa Clara CA 95054 + US + +00-0F-8C (hex) Gigawavetech Pte Ltd +000F8C (base 16) Gigawavetech Pte Ltd + 1 Jalan Kilang Timor + 159303 + SG + +00-0F-38 (hex) Netstar +000F38 (base 16) Netstar + 3F,No.347, Yang-kuang St.,Nei-Hu Dis., + Taipei 114 + TW + +00-0F-3A (hex) HISHARP +000F3A (base 16) HISHARP + NO.673,CHANG HSING ROAD PATE CITY,TAOYUAN, + TAIPEI 334 + TW + +00-0F-30 (hex) Raza Microelectronics Inc +000F30 (base 16) Raza Microelectronics Inc + 3080 North First Street + San Jose CA 95134 + US + +00-0F-53 (hex) Solarflare Communications Inc. +000F53 (base 16) Solarflare Communications Inc. + Suite 100, 7505 Irvine Center Drive + Irvine CA 92618 + US + +00-0F-51 (hex) Azul Systems, Inc. +000F51 (base 16) Azul Systems, Inc. + 1600 Plymouth Street + Mountain View California 94043 + US + +00-0F-07 (hex) Mangrove Systems, Inc. +000F07 (base 16) Mangrove Systems, Inc. + 10 Fairfield Blvd. + Wallingford CT 06492 + US + +00-0F-00 (hex) Legra Systems, Inc. +000F00 (base 16) Legra Systems, Inc. + 3 Burlington Woods Drive + Burlington MA 01803 + US + +00-0F-01 (hex) DIGITALKS INC +000F01 (base 16) DIGITALKS INC + 14 MARSHALL LANE + WESTON CT 06883 + US + +00-0F-03 (hex) COM&C CO., LTD +000F03 (base 16) COM&C CO., LTD + 2F Woojin BLD 1445-2 Secho-Dong + SEOUL 137-070 + KR + +00-0F-34 (hex) Cisco Systems, Inc +000F34 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0F-2E (hex) Megapower International Corp. +000F2E (base 16) Megapower International Corp. + Rm. 403, No 24 , Wu-Chuan 2nd Rd., + Taipei Hsien 242 + TW + +00-0F-26 (hex) WorldAccxx LLC +000F26 (base 16) WorldAccxx LLC + 4035 Tampa Rd. + Oldsmar FL 34667 + US + +00-0F-45 (hex) Stretch, Inc. +000F45 (base 16) Stretch, Inc. + 1322 Orleans Drive + Sunnyvale CA 94089 + US + +00-0F-3B (hex) Fuji System Machines Co., Ltd. +000F3B (base 16) Fuji System Machines Co., Ltd. + 5-8-10 + Zama-Shi Kanagawa-Ken 228-0003 + JP + +00-0F-37 (hex) Xambala Incorporated +000F37 (base 16) Xambala Incorporated + 2674 N. 1st Street + San Jose CA 95134 + US + +00-0F-54 (hex) Entrelogic Corporation +000F54 (base 16) Entrelogic Corporation + 33 Boston Post Rd. West. + Marlborough MA 01752 + US + +00-0F-25 (hex) AimValley B.V. +000F25 (base 16) AimValley B.V. + Utrechtseweg 38, + Hilversum NH 1223 TV + NL + +00-0F-19 (hex) Boston Scientific +000F19 (base 16) Boston Scientific + 4100 Hamline Ave N. + St. Paul MN 55112 + US + +00-0F-10 (hex) RDM Corporation +000F10 (base 16) RDM Corporation + 608 Weber St. N + Waterloo ON N2V 1K4 + CA + +00-0E-A8 (hex) United Technologists Europe Limited +000EA8 (base 16) United Technologists Europe Limited + UTEL Laboratories, Wolves Farm Lane + Hadleigh Suffolk IP7 6BH + GB + +00-0E-AA (hex) Scalent Systems, Inc. +000EAA (base 16) Scalent Systems, Inc. + 490 S. California Ave + Palo Alto CA 94306 + US + +00-0E-AC (hex) MINTRON ENTERPRISE CO., LTD. +000EAC (base 16) MINTRON ENTERPRISE CO., LTD. + NO.3,Wu-Kung 5Rd., Wu-Ku Ind Park + Taipei County 248 + TW + +00-0E-AE (hex) GAWELL TECHNOLOGIES CORP. +000EAE (base 16) GAWELL TECHNOLOGIES CORP. + 2F,NO.102,SEC.3,JUNG SHAN RD, + JUNG HO CITY, TAIPEI HSIEN 235 + TW + +00-0E-BA (hex) HANMI SEMICONDUCTOR CO., LTD. +000EBA (base 16) HANMI SEMICONDUCTOR CO., LTD. + #532-2, Gajwa-Dong, Seo-Ku, + Incheon, 404 250 + KR + +00-0E-BC (hex) Paragon Fidelity GmbH +000EBC (base 16) Paragon Fidelity GmbH + Schwadermühlstraße + Cadolzburg 90556 + DE + +00-0E-C5 (hex) Digital Multitools Inc +000EC5 (base 16) Digital Multitools Inc + 9005 Leslie Street Unit 205 + Richmond Hill Ontario L4B 1G7 + CA + +00-0E-C7 (hex) Motorola Korea +000EC7 (base 16) Motorola Korea + Hibrand B/D 17F SW Team Motorola Korea + Yangjaedong Seocho + KR + +00-0E-8B (hex) Astarte Technology Co, Ltd. +000E8B (base 16) Astarte Technology Co, Ltd. + 11F, No. 166 Dah-Yeh Rd. + Peitou, Taipei + TW + +00-0E-DF (hex) PLX Technology +000EDF (base 16) PLX Technology + 870 Maude Ave., + Sunnyvale CA 94085 + US + +00-0E-E1 (hex) ExtremeSpeed Inc. +000EE1 (base 16) ExtremeSpeed Inc. + PO Box 600 + Mannville Alberta T0B 2W0 + CA + +00-0E-D7 (hex) Cisco Systems, Inc +000ED7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0E-D3 (hex) Epicenter, Inc. +000ED3 (base 16) Epicenter, Inc. + 211 B Calle Pintoresco + San Clemente CA 92672 + US + +00-0E-9D (hex) Tiscali UK Ltd +000E9D (base 16) Tiscali UK Ltd + 20 Broadwick Street + London W1F 8HT + GB + +00-0E-47 (hex) NCI System Co.,Ltd. +000E47 (base 16) NCI System Co.,Ltd. + #206, Kayang Techno-Town, 1487, Kayang 3 dong, Kangseo-Ku, Seoul, Korea + Seoul 157-810 + KR + +00-0E-46 (hex) Niigata Seimitsu Co.,Ltd. +000E46 (base 16) Niigata Seimitsu Co.,Ltd. + 3335-2, Shimonaka, Sanwa-mura + Nakakubiki-gun Niigata 943-0222 + JP + +00-0E-1F (hex) TCL Networks Equipment Co., Ltd. +000E1F (base 16) TCL Networks Equipment Co., Ltd. + No.5 Industrial Road,Shekou + ShenZhen GuangDong 518067 + CN + +00-0E-26 (hex) Gincom Technology Corp. +000E26 (base 16) Gincom Technology Corp. + 15F., No. 284, Sec.3, Sanmin Rd., Taoyuan City, + Taoyuan, 330 + TW + +00-0E-6C (hex) Device Drivers Limited +000E6C (base 16) Device Drivers Limited + 1-5-1-103 + Fuchu-shi Tokyo 1830005 + JP + +00-0E-6B (hex) Janitza electronics GmbH +000E6B (base 16) Janitza electronics GmbH + Vor dem Polstück 1 + Lahnau Hessen 35633 + DE + +00-0E-5F (hex) activ-net GmbH & Co. KG +000E5F (base 16) activ-net GmbH & Co. KG + Konrad-Zuse-Str. 4 + Bochum 44801 + DE + +00-0E-57 (hex) Iworld Networking, Inc. +000E57 (base 16) Iworld Networking, Inc. + 125 Hanju Bldg, Nonhyun-Dong + Seoul 135010 + KR + +00-0E-51 (hex) tecna elettronica srl +000E51 (base 16) tecna elettronica srl + via miglioli 30 + castel san pietro terme bologna 40024 + IT + +00-0E-67 (hex) Eltis Microelectronics Ltd. +000E67 (base 16) Eltis Microelectronics Ltd. + Unit 902B, 9/F., Sunbeam Centre + Kwun Tong Kowloon + HK + +00-0E-65 (hex) TransCore +000E65 (base 16) TransCore + 8600 Jefferson St NE + Albuquerque NM 87113 + US + +00-0E-43 (hex) G-Tek Electronics Sdn. Bhd. +000E43 (base 16) G-Tek Electronics Sdn. Bhd. + 2493 Mukim 1, Lorong Perusahaan Lapan + Perai Penang 13600 + MY + +00-0E-44 (hex) Digital 5, Inc. +000E44 (base 16) Digital 5, Inc. + 101 Grovers Mill Rd. + Lawrenceville NJ 08648 + US + +00-0E-74 (hex) Solar Telecom. Tech +000E74 (base 16) Solar Telecom. Tech + B B/D, 4F, Samho Venture Tower + Seoul 137-941 + KR + +00-0E-7A (hex) GemWon Communications Co., Ltd. +000E7A (base 16) GemWon Communications Co., Ltd. + 3FL.,NO.32,Lane 135,Shianjeng 9th Rd.,Jubei City + Hsinchu 302 + TW + +00-0E-80 (hex) Thomson Technology Inc +000E80 (base 16) Thomson Technology Inc + 9087A 198th ST + Surrey BC V1M-3B1 + CA + +00-0E-85 (hex) Catalyst Enterprises, Inc. +000E85 (base 16) Catalyst Enterprises, Inc. + 3385 Scott Blvd + Santa Clara CA 95054 + US + +00-0E-32 (hex) Kontron Medical +000E32 (base 16) Kontron Medical + Reinacherstrasse 131 + Basel 4002 + CH + +00-0E-0B (hex) Netac Technology Co., Ltd. +000E0B (base 16) Netac Technology Co., Ltd. + 6F, Incubator Building, China Academy of Science &Tech Development, + ShenZhen GuangDong 518057 + CN + +00-0E-11 (hex) BDT Büro und Datentechnik GmbH & Co.KG +000E11 (base 16) BDT Büro und Datentechnik GmbH & Co.KG + Saline 29 + Rottweil Baden-Württemberg D-78628 + DE + +00-0D-F5 (hex) Teletronics International Inc. +000DF5 (base 16) Teletronics International Inc. + 2 Choke Cherry Road + Rockville MD 20850 + US + +00-0D-F7 (hex) Space Dynamics Lab +000DF7 (base 16) Space Dynamics Lab + 1695 N. Research Park Way + North Logan UT 84341 + US + +00-0D-EB (hex) CompXs Limited +000DEB (base 16) CompXs Limited + Robert Denholm House + Redhill Surrey RH1 4HW + GB + +00-0D-EE (hex) Andrew RF Power Amplifier Group +000DEE (base 16) Andrew RF Power Amplifier Group + 40 Technology Drive + Warren NJ 07059 + US + +00-0D-EF (hex) Soc. Coop. Bilanciai +000DEF (base 16) Soc. Coop. Bilanciai + via S.Ferrari 16 + Campogalliano Modena 41011 + IT + +00-0D-E7 (hex) Snap-on OEM Group +000DE7 (base 16) Snap-on OEM Group + 2333 East Walton Blvd. + Auburn Hills MI 48326 + US + +00-0D-C6 (hex) DigiRose Technology Co., Ltd. +000DC6 (base 16) DigiRose Technology Co., Ltd. + No. 1, Alley 20, Lane 26 Rueiguang Road, + Taipei 114 + TW + +00-0D-C1 (hex) SafeWeb Inc +000DC1 (base 16) SafeWeb Inc + 2200 Powell St. Ste 590 + Emeryville CA 94608 + US + +00-0D-F0 (hex) QCOM TECHNOLOGY INC. +000DF0 (base 16) QCOM TECHNOLOGY INC. + 4F., No.301, Sec. 2, Tiding Blvd. + Taipei City Neihu District 114 + TW + +00-0D-E5 (hex) Samsung Thales +000DE5 (base 16) Samsung Thales + 259 Gongdan-Dong + Gumi-City Gyeongsangbuk-do 730-904 + KR + +00-0D-C0 (hex) Spagat AS +000DC0 (base 16) Spagat AS + Tonne Hutifeldtpl. 2 + Halden Ostfold 1767 + NO + +00-0D-DD (hex) Profilo Telra Elektronik Sanayi ve Ticaret. A.Ş +000DDD (base 16) Profilo Telra Elektronik Sanayi ve Ticaret. A.Ş + Cemal Sahir Sokak NO:26-28 + İstanbul TURKEY 34255 + TR + +00-0D-F8 (hex) ORGA Kartensysteme GmbH +000DF8 (base 16) ORGA Kartensysteme GmbH + Konrad-Zuse-Ring 1 + Flintbek Schleswig-Holstein 24220 + DE + +00-0E-16 (hex) SouthWing S.L. +000E16 (base 16) SouthWing S.L. + C/Avila, 48-50 + Barcelona 08005 + ES + +00-0D-A7 (hex) Private +000DA7 (base 16) Private + +00-0D-AD (hex) Dataprobe, Inc. +000DAD (base 16) Dataprobe, Inc. + 1B Pearl Court + Allendale NJ 07401 + US + +00-0D-A9 (hex) T.E.A.M. S.L. +000DA9 (base 16) T.E.A.M. S.L. + Parque Tecnologico Edificio 108 + ZAMUDIO Bizkaia 48170 + ES + +00-0D-AB (hex) Parker Hannifin GmbH Electromechanical Division Europe +000DAB (base 16) Parker Hannifin GmbH Electromechanical Division Europe + Robert-Bosch-Straße 22 + Offenburg Baden-Württemberg 77656 + DE + +00-0D-A8 (hex) Teletronics Technology Corporation +000DA8 (base 16) Teletronics Technology Corporation + 2525 Pearl Buck Road + Bristol Pennsylvania 19007 + US + +00-0D-79 (hex) Dynamic Solutions Co,.Ltd. +000D79 (base 16) Dynamic Solutions Co,.Ltd. + 17-8 Nihonbashi Hakozaki-cho + Chuo-ku Tokyo 103-0015 + JP + +00-0D-6D (hex) K-Tech Devices Corp. +000D6D (base 16) K-Tech Devices Corp. + 14016-30 + nakaminowa minowamachi kamiina nagano 399-4601 + JP + +00-0D-AF (hex) Plexus Corp (UK) Ltd +000DAF (base 16) Plexus Corp (UK) Ltd + Pinnacle Hill + Kelso Roxburghshire TD5 8XX + GB + +00-0D-B1 (hex) Japan Network Service Co., Ltd. +000DB1 (base 16) Japan Network Service Co., Ltd. + Matoba Bldg. 6F, + Chuo-ku Tokyo 104-0042 + JP + +00-0D-83 (hex) Sanmina-SCI Hungary Ltd. +000D83 (base 16) Sanmina-SCI Hungary Ltd. + Kota Jozsef u. 2. + Tatabanya Komarom-Esztergom 2800 + HU + +00-0D-7F (hex) MIDAS COMMUNICATION TECHNOLOGIES PTE LTD ( Foreign Branch) +000D7F (base 16) MIDAS COMMUNICATION TECHNOLOGIES PTE LTD ( Foreign Branch) + 04-12, Phase Z.Ro Technoprenuer Park + Singapore 139 347 + SG + +00-0D-75 (hex) Kobian Pte Ltd - Taiwan Branch +000D75 (base 16) Kobian Pte Ltd - Taiwan Branch + 2F, No.580, Rueikuang Rd.,Nei Hu,Taipei, + Taipei Nei Hu 114 + TW + +00-0D-78 (hex) Engineering & Security +000D78 (base 16) Engineering & Security + Martiri della Libertà   32/4 + Genova 16155 + IT + +00-0D-9E (hex) TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd. +000D9E (base 16) TOKUDEN OHIZUMI SEISAKUSYO Co.,Ltd. + Yoshida 1221 + Ouragun Ohizumi Gunma 370-0523 + JP + +00-0D-A3 (hex) Emerging Technologies Limited +000DA3 (base 16) Emerging Technologies Limited + Wong's Industrial Centre, 180 Wai Yip St + Nil + HK + +00-0D-A4 (hex) DOSCH & AMAND SYSTEMS AG +000DA4 (base 16) DOSCH & AMAND SYSTEMS AG + Scheinerstrasse 9 + Munich Bavaria 81679 + DE + +00-0D-9A (hex) INFOTEC LTD +000D9A (base 16) INFOTEC LTD + The Maltings + Ashby-de-la-Zouch Leicestershire LE65 2PS + GB + +00-0D-6E (hex) K-Patents Oy +000D6E (base 16) K-Patents Oy + P.O. Box 77 + VANTAA FI 01511 + FI + +00-0D-6A (hex) Redwood Technologies LTD +000D6A (base 16) Redwood Technologies LTD + Amber House + Bracknell Berkshire RG12 1JB + GB + +00-0D-BA (hex) Océ Document Technologies GmbH +000DBA (base 16) Océ Document Technologies GmbH + Max-Stromeyer-Straße 116 + Konstanz 78467 + DE + +00-0D-BD (hex) Cisco Systems, Inc +000DBD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0D-B5 (hex) GLOBALSAT TECHNOLOGY CORPORATION +000DB5 (base 16) GLOBALSAT TECHNOLOGY CORPORATION + Far East Century Park + Taipei Hsien 235 + TW + +00-0D-97 (hex) ABB Inc./Tropos +000D97 (base 16) ABB Inc./Tropos + 1710 S. Amphlett Blvd, Suite 304 + San Mateo CA 94402 + US + +00-0D-96 (hex) Vtera Technology Inc. +000D96 (base 16) Vtera Technology Inc. + No 34, Industrial East. 4th Rd. + HsinChu 300 + TW + +00-0D-8B (hex) T&D Corporation +000D8B (base 16) T&D Corporation + 5652-169 Sasaga + Matsumoto Nagano 399-0033 + JP + +00-0D-90 (hex) Factum Electronics AB +000D90 (base 16) Factum Electronics AB + Teknikringen 1H + Linköping Östergötland 583 30 + SE + +00-0D-85 (hex) Tapwave, Inc. +000D85 (base 16) Tapwave, Inc. + 1901 Landings Drive + Mountain View CA 94043 + US + +00-0D-82 (hex) PHSNET +000D82 (base 16) PHSNET + Piazza Mariano Rumor, 18 + Arcugnano Vicenza 36057 + IT + +00-0D-23 (hex) Smart Solution, Inc +000D23 (base 16) Smart Solution, Inc + 465 West Lawndale #B + Salt Lake City UT 84115 + US + +00-0D-27 (hex) MICROPLEX Printware AG +000D27 (base 16) MICROPLEX Printware AG + Panzerstraße 5 + Varel Niedersachsen 26316 + DE + +00-0D-1B (hex) Kyoto Electronics Manufacturing Co., Ltd. +000D1B (base 16) Kyoto Electronics Manufacturing Co., Ltd. + 56-2, Ninodan-cho, Shinden, + Kyoto-City Kyoto Prefecture 601-8317 + JP + +00-0D-1D (hex) HIGH-TEK HARNESS ENT. CO., LTD. +000D1D (base 16) HIGH-TEK HARNESS ENT. CO., LTD. + 4F-6, No18, Pu-Ting Rd. Hsinchu, Taiwan + Hsinchu 300 + TW + +00-0D-02 (hex) NEC Platforms, Ltd. +000D02 (base 16) NEC Platforms, Ltd. + 800 Shimomata + Kakegawa Shizuoka 436-8501 + JP + +00-0D-07 (hex) Calrec Audio Ltd +000D07 (base 16) Calrec Audio Ltd + Nutclough Mill + Hebden Bridge West Yorkshire HX7 8EZ + GB + +00-0D-40 (hex) Verint Loronix Video Solutions +000D40 (base 16) Verint Loronix Video Solutions + 12526 High Bluff Dr. #170 + San DIego CA 92130 + US + +00-0D-21 (hex) WISCORE Inc. +000D21 (base 16) WISCORE Inc. + 6F, No. 180, Sec. 2, Duenhua S. Rd, + Taipei 106 + TW + +00-0D-09 (hex) Yuehua(Zhuhai) Electronic CO. LTD +000D09 (base 16) Yuehua(Zhuhai) Electronic CO. LTD + 4Rd Pingdong,Nanping Science & Technolog + Zhuhai Guangdong 519070 + CN + +00-0D-37 (hex) WIPLUG +000D37 (base 16) WIPLUG + RUA DR. AGOSTINHO GOULAO + PETROPOLIS RIO JANEIRO 25730050 + BR + +00-0D-33 (hex) Prediwave Corp. +000D33 (base 16) Prediwave Corp. + 48431 Milmont Drive + Fremont CA 94538 + US + +00-0D-2F (hex) AIN Comm.Tech.Co., LTD +000D2F (base 16) AIN Comm.Tech.Co., LTD + 4F, No.76, Sec2 Mintzu Rd + Jung-Li City 320 + TW + +00-0D-5D (hex) Raritan Computer, Inc +000D5D (base 16) Raritan Computer, Inc + 400 Cottontail Lane + Somerset NJ 08873 + US + +00-0D-63 (hex) DENT Instruments, Inc. +000D63 (base 16) DENT Instruments, Inc. + 64 NW Franklin Ave + Bend OR 97701 + US + +00-0D-66 (hex) Cisco Systems, Inc +000D66 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0C-CD (hex) IEC - TC57 +000CCD (base 16) IEC - TC57 + 3, rue de Varembé + Geneva GE 1211 + CH + +00-0C-CB (hex) Design Combus Ltd +000CCB (base 16) Design Combus Ltd + Hatanapaan valtatie 34A + Tampere FIN-33100 + FI + +00-0C-C9 (hex) ILWOO DATA & TECHNOLOGY CO.,LTD +000CC9 (base 16) ILWOO DATA & TECHNOLOGY CO.,LTD + 1475-10,HWA HYUN BLD. 2nd Floor, + SEOUL 137-071 + KR + +00-0C-E9 (hex) BLOOMBERG L.P. +000CE9 (base 16) BLOOMBERG L.P. + 731 Lexington Ave + NEW YORK NEW YORK 10022 + US + +00-0C-EA (hex) aphona Kommunikationssysteme +000CEA (base 16) aphona Kommunikationssysteme + Entwicklungs- und VertriebsgmbH + Wien 1230 + AT + +00-0C-DA (hex) FreeHand Systems, Inc. +000CDA (base 16) FreeHand Systems, Inc. + 95 First St. + Los Altos CA 94022 + US + +00-0C-F5 (hex) InfoExpress +000CF5 (base 16) InfoExpress + 170 S. Whisman Road, Suite B + Mountain View CA 94041 + US + +00-0C-EE (hex) jp-embedded +000CEE (base 16) jp-embedded + Buen 21, Nr. Dalby + Borup 4140 + DK + +00-0C-AF (hex) TRI TERM CO.,LTD. +000CAF (base 16) TRI TERM CO.,LTD. + 21-5 HIRAIDE KOUGIYO DANCHI + TOCHIGI 321-0905 + JP + +00-0C-B3 (hex) ROUND Co.,Ltd. +000CB3 (base 16) ROUND Co.,Ltd. + 3-9 Gokashou-Shibahigashi + uji kyoto 611-0011 + JP + +00-0C-DD (hex) AOS technologies AG +000CDD (base 16) AOS technologies AG + Taefernstrasse 20 + Baden - Daettwil AG CH-5405 + CH + +00-0C-A5 (hex) Naman NZ LTd +000CA5 (base 16) Naman NZ LTd + 13/17 Kawana St + Auckland + NZ + +00-0C-A9 (hex) Ebtron Inc. +000CA9 (base 16) Ebtron Inc. + 1663 Hwy 701 South + Loris SC 29569 + US + +00-0C-FB (hex) Korea Network Systems +000CFB (base 16) Korea Network Systems + 206 JangYoungSil Bldg, 1688-5 + Taejeon 306-230 + KR + +00-0C-7A (hex) DaTARIUS Technologies GmbH +000C7A (base 16) DaTARIUS Technologies GmbH + Anton Maria Schyrle Str. 7 + Reutte Tirol 6600 + AT + +00-0C-79 (hex) Extel Communications P/L +000C79 (base 16) Extel Communications P/L + 399 Ferntree Gully Road + Mt Waverley Victoria 3149 + AU + +00-0C-75 (hex) Oriental integrated electronics. LTD +000C75 (base 16) Oriental integrated electronics. LTD + 281-34 Dondang-dong Wonmi-Gu + Bucheon 420-808 + KR + +00-0C-5D (hex) CHIC TECHNOLOGY (CHINA) CORP. +000C5D (base 16) CHIC TECHNOLOGY (CHINA) CORP. + 7th Building,Shi'ao Ind.Zone,Longhua Tow + Shenzhen Guangdong 518109 + CN + +00-0C-4F (hex) UDTech Japan Corporation +000C4F (base 16) UDTech Japan Corporation + Hamacho Hanacho Bldg, 2F + Chuo-ku Tokyo 103-0007 + JP + +00-0C-62 (hex) ABB AB, Cewe-Control +000C62 (base 16) ABB AB, Cewe-Control + Dept. LPCC/RE + Vasteras 721 61 + SE + +00-0C-4C (hex) Arcor AG&Co. +000C4C (base 16) Arcor AG&Co. + Alfred-Herrhausen-Allee 1 + Eschborn Hessen 65760 + DE + +00-0C-47 (hex) SK Teletech(R&D Planning Team) +000C47 (base 16) SK Teletech(R&D Planning Team) + 21th FL Startower 737, Yeoksam-dong + Seoul 135-984 + KR + +00-0C-6D (hex) Edwards Ltd. +000C6D (base 16) Edwards Ltd. + Marshall Road + Eastbourne East Sussex BN22 9BA + GB + +00-0C-70 (hex) ACC GmbH +000C70 (base 16) ACC GmbH + Am Sandfeld 15 + Karlsruhe Baden 76149 + DE + +00-0C-6A (hex) MBARI +000C6A (base 16) MBARI + 7700 Sandholdt Road + Moss Landing CA 95039 + US + +00-0C-6B (hex) Kurz Industrie-Elektronik GmbH +000C6B (base 16) Kurz Industrie-Elektronik GmbH + Foehrenbachstraße 3 + Remshalden Baden-Württemberg 73630 + DE + +00-0C-9D (hex) UbeeAirWalk, Inc. +000C9D (base 16) UbeeAirWalk, Inc. + 1850 N. GreenVille Ave., Suite 164 + Richardson TX 75081 + US + +00-0C-9F (hex) NKE Corporation +000C9F (base 16) NKE Corporation + 366-1 Hishikawa-cho Hazukashi Fushimi-ku + Kyoto-shi Kyoto 612-8487 + JP + +00-0C-84 (hex) Eazix, Inc. +000C84 (base 16) Eazix, Inc. + Unit 301 Plaza Building B + Muntinlupa City Rizal 1770 + PH + +00-0C-85 (hex) Cisco Systems, Inc +000C85 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0C-3F (hex) Cogent Defence & Security Networks, +000C3F (base 16) Cogent Defence & Security Networks, + Meadows Road, + Newport, South Wales, NP19 4SS + GB + +00-0C-30 (hex) Cisco Systems, Inc +000C30 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0C-9A (hex) Hitech Electronics Corp. +000C9A (base 16) Hitech Electronics Corp. + 4f, No. 501-15 Chung-Cheng Rd. + Shin-tien Taipei Shien 231 + TW + +00-0C-91 (hex) Riverhead Networks Inc. +000C91 (base 16) Riverhead Networks Inc. + + Cupertino CA 95014 + US + +00-0B-DA (hex) EyeCross Co.,Inc. +000BDA (base 16) EyeCross Co.,Inc. + 3F Iioka-Building + Tokyo Ueno Taitoh-ku 3-4-1 110-0005 + JP + +00-0B-D6 (hex) Paxton Access Ltd +000BD6 (base 16) Paxton Access Ltd + Paxton House + Brighton East Sussex BN1 9HU + GB + +00-0B-D4 (hex) Beijing Wise Technology & Science Development Co.Ltd +000BD4 (base 16) Beijing Wise Technology & Science Development Co.Ltd + 3rd Floor Caihong Building, No.2,1st Wes + Beijing 100088 + CN + +00-0C-1F (hex) Glimmerglass Networks +000C1F (base 16) Glimmerglass Networks + 26142 Eden Landing Road + Hayward California 94545 + US + +00-0C-20 (hex) Fi WIn, Inc. +000C20 (base 16) Fi WIn, Inc. + 8F, No. 10, Prosperity Rd. 1, + Hsin Chu 300 + TW + +00-0C-15 (hex) CyberPower Systems, Inc. +000C15 (base 16) CyberPower Systems, Inc. + 6F, No. 32, Sec. 1, Chenggong Rd. + Taipei 115 + TW + +00-0B-F8 (hex) Infinera +000BF8 (base 16) Infinera + 1322 Bordeaux Drive + Sunnyvale CA 94089 + US + +00-0B-FF (hex) Berkeley Camera Engineering +000BFF (base 16) Berkeley Camera Engineering + 127 National Street + Santa Cruz CA 95060 + US + +00-0C-16 (hex) Concorde Microsystems Inc. +000C16 (base 16) Concorde Microsystems Inc. + 10427 Cogdill Road, Suite 500 + Knoxville TN 37932 + US + +00-0C-09 (hex) Hitachi IE Systems Co., Ltd +000C09 (base 16) Hitachi IE Systems Co., Ltd + Saiwai-cho 120-1,Inazawa-shi + Inazawa-shi Aichi 492-8622 + JP + +00-0B-E7 (hex) COMFLUX TECHNOLOGY INC. +000BE7 (base 16) COMFLUX TECHNOLOGY INC. + Room 131,Bldg. 53,195-58,Sec.4, + Hsinchu 310 + TW + +00-0B-EC (hex) NIPPON ELECTRIC INSTRUMENT, INC. +000BEC (base 16) NIPPON ELECTRIC INSTRUMENT, INC. + 3-56-21 Hirado + Totsuka-ku Yokohama-shi 244-0802 + JP + +00-0C-02 (hex) ABB Oy +000C02 (base 16) ABB Oy + P.O.Box 89 + Turku FIN-20521 + FI + +00-0B-71 (hex) Litchfield Communications Inc. +000B71 (base 16) Litchfield Communications Inc. + 27 Princeton Road + Watertown CT 06795 + US + +00-0B-74 (hex) Kingwave Technology Co., Ltd. +000B74 (base 16) Kingwave Technology Co., Ltd. + 18F-3, No. 186, Jian-Yi Rd. + Chung-Ho Taipei 235 + TW + +00-0B-73 (hex) Kodeos Communications +000B73 (base 16) Kodeos Communications + 111 Corporate Blvd + South Plainfield NJ 07080 + US + +00-0B-76 (hex) ET&T Technology Co. Ltd. +000B76 (base 16) ET&T Technology Co. Ltd. + 6F No.101, SongJiang Rd. + Taipei 104 + TW + +00-0B-5E (hex) Audio Engineering Society Inc. +000B5E (base 16) Audio Engineering Society Inc. + 60 East 42nd Street, Suite #2520 + New York NY 10165-2520 + US + +00-0B-60 (hex) Cisco Systems, Inc +000B60 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-65 (hex) Sy.A.C. srl +000B65 (base 16) Sy.A.C. srl + via Caboto 19/1 + Trieste 34147 + IT + +00-0B-5F (hex) Cisco Systems, Inc +000B5F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-61 (hex) Friedrich Lütze GmbH & Co. KG +000B61 (base 16) Friedrich Lütze GmbH & Co. KG + Bruckwiesenstraße 17 - 19 + Weinstadt (Großheppach) BW 71384 + DE + +00-0B-59 (hex) ScriptPro, LLC +000B59 (base 16) ScriptPro, LLC + 5828 Reeds Rd. + Mission Kansas 66202 + US + +00-0B-5C (hex) Newtech Co.,Ltd +000B5C (base 16) Newtech Co.,Ltd + K-Bldg 1-7-7 Shibadaimon Minato-ku + Tokyo 105-0012 + JP + +00-0B-7E (hex) SAGINOMIYA Seisakusho Inc. +000B7E (base 16) SAGINOMIYA Seisakusho Inc. + 535 Sasai + Sayamashi Saitamaken 350-1395 + JP + +00-0B-80 (hex) Lycium Networks +000B80 (base 16) Lycium Networks + 9 Hamenofim St. + Herzliya Israel 46733 + IL + +00-0B-A7 (hex) Maranti Networks +000BA7 (base 16) Maranti Networks + 3061-B Zanker Road + San Jose CA 95134 + US + +00-0B-AA (hex) Aiphone co.,Ltd +000BAA (base 16) Aiphone co.,Ltd + 2-18 Jinno-Cho + Nagoya Aichi-ken 456-8666 + JP + +00-0B-A4 (hex) Shiron Satellite Communications Ltd. (1996) +000BA4 (base 16) Shiron Satellite Communications Ltd. (1996) + 23 Hasivim St. + Petach Tikva 49170 + IL + +00-0B-D0 (hex) XiMeta Technology Americas Inc. +000BD0 (base 16) XiMeta Technology Americas Inc. + 54 Ray Street + New Brunswick NJ 08901 + US + +00-0B-C5 (hex) SMC Networks, Inc. +000BC5 (base 16) SMC Networks, Inc. + 38 Tesla + Irvine CA 92618 + US + +00-0B-C6 (hex) ISAC, Inc. +000BC6 (base 16) ISAC, Inc. + PO Box 7682 + Auburn CA 95604 + US + +00-0B-C1 (hex) Bay Microsystems, Inc. +000BC1 (base 16) Bay Microsystems, Inc. + 2055 Gateway Place + Santa Jose CA 95110 + US + +00-0B-8B (hex) KERAJET, S.A. +000B8B (base 16) KERAJET, S.A. + Avda. del Boverot, 24 + Almazora Castellon E-12550 + ES + +00-0B-89 (hex) Top Global Technology, Ltd. +000B89 (base 16) Top Global Technology, Ltd. + Room 3310, China World Tower No. 1 + Beijing Beijing 100004 + CN + +00-0B-99 (hex) SensAble Technologies, Inc. +000B99 (base 16) SensAble Technologies, Inc. + 15 Constitution Way + Woburn MA 01801 + US + +00-0B-9C (hex) TriBeam Technologies, Inc. +000B9C (base 16) TriBeam Technologies, Inc. + 116 W. Eastman St., suite 208 + Arlington Heights IL 60004 + US + +00-0B-7C (hex) Telex Communications +000B7C (base 16) Telex Communications + 8601 E. Cornhusker Hwy + Lincoln NE 68505 + US + +00-0B-83 (hex) DATAWATT B.V. +000B83 (base 16) DATAWATT B.V. + HOUTSTRAAT 5 + WOLVEGA NL-8471-ZX + NL + +00-0B-20 (hex) Hirata corporation +000B20 (base 16) Hirata corporation + 111 Hitotsugi, Ueki, Kamoto, + Kumamoto 861-0198 + JP + +00-0B-22 (hex) Environmental Systems and Services +000B22 (base 16) Environmental Systems and Services + 20 Council Street + Hawthorn East Victoria 3123 + AU + +00-0B-1B (hex) Systronix, Inc. +000B1B (base 16) Systronix, Inc. + 939 Edison St. + Salt Lake City Utah 84111 + US + +00-0B-03 (hex) Taekwang Industrial Co., Ltd +000B03 (base 16) Taekwang Industrial Co., Ltd + #191-1, Anyang-7Dong, Manan-Gu + Anyang-Si South Korea 430-017 + KR + +00-0B-01 (hex) DAIICHI ELECTRONICS CO., LTD. +000B01 (base 16) DAIICHI ELECTRONICS CO., LTD. + 1-11-13 + Hitotsuya Adachi-ku Tokyo 121-8639 + JP + +00-0B-3E (hex) BittWare, Inc +000B3E (base 16) BittWare, Inc + 31 B South Main St + Concord NH 03301 + US + +00-0B-29 (hex) LS(LG) Industrial Systems co.,Ltd +000B29 (base 16) LS(LG) Industrial Systems co.,Ltd + 533 Hogye-dong, Dongan-gu + Anyang-si Gyeonggi-do + KR + +00-0B-39 (hex) Keisoku Giken Co.,Ltd. +000B39 (base 16) Keisoku Giken Co.,Ltd. + Tsuzuki-ku + Yokohama Kanagawa 224-0037 + JP + +00-0B-3A (hex) QuStream Corporation +000B3A (base 16) QuStream Corporation + 3305 Breckinridge Blvd. + Duluth Georgia 30096 + US + +00-0B-33 (hex) Vivato Technologies +000B33 (base 16) Vivato Technologies + 444 Cedros Ave + Solana Beach CA 92027 + US + +00-0B-05 (hex) Pacific Broadband Networks +000B05 (base 16) Pacific Broadband Networks + Suite 15, Building 3, 195 Wellington Road + Clayton VIC 3168 + AU + +00-0B-00 (hex) FUJIAN START COMPUTER EQUIPMENT CO.,LTD +000B00 (base 16) FUJIAN START COMPUTER EQUIPMENT CO.,LTD + HONG SHAN YUAN ROAD NO.68 HONGSHAN,GULOU + FUZHOU FUJIAN 350002 + CN + +00-0B-5B (hex) Rincon Research Corporation +000B5B (base 16) Rincon Research Corporation + 101 N. Wilmot Rd. + Tucson AZ 85711 + US + +00-0A-F6 (hex) Emerson Climate Technologies Retail Solutions, Inc. +000AF6 (base 16) Emerson Climate Technologies Retail Solutions, Inc. + 1640 Airport Rd + Kennesaw GA 30144-7038 + US + +00-0B-11 (hex) HIMEJI ABC TRADING CO.,LTD. +000B11 (base 16) HIMEJI ABC TRADING CO.,LTD. + 1-8-22 + HJMEJI HYOGO 670-0883 + JP + +00-0B-41 (hex) Ing. Büro Dr. Beutlhauser +000B41 (base 16) Ing. Büro Dr. Beutlhauser + Roemerweg 4 + Grassau D-83224 + DE + +00-0A-EA (hex) ADAM ELEKTRONIK LTD. ŞTI +000AEA (base 16) ADAM ELEKTRONIK LTD. ŞTI + UZUNAYNA CAD. CELENK SOK. NO:1 Çakmak + İstanbul 81260 + TR + +00-0A-E3 (hex) YANG MEI TECHNOLOGY CO., LTD +000AE3 (base 16) YANG MEI TECHNOLOGY CO., LTD + 21, Alley 1, Lane 342 + Taipei 114 + TW + +00-0A-DC (hex) RuggedCom Inc. +000ADC (base 16) RuggedCom Inc. + 30 Whitmore Road + Woodbridge Ontario L4L 7Z4 + CA + +00-0A-B7 (hex) Cisco Systems, Inc +000AB7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0A-AD (hex) Stargames Corporation +000AAD (base 16) Stargames Corporation + 13 Sheridan Close + Milperra NSW 2031 + AU + +00-0A-B1 (hex) GENETEC Corporation +000AB1 (base 16) GENETEC Corporation + BYGS Shinjyuku Bldg. 5F + Shinjuku-ku Tokyo 162-0022 + JP + +00-0A-B9 (hex) Astera Technologies Corp. +000AB9 (base 16) Astera Technologies Corp. + 2380 Waverley Street + Palo Alto CA 94301 + US + +00-0A-90 (hex) Bayside Interactive, Inc. +000A90 (base 16) Bayside Interactive, Inc. + 330 Biscayne Blvd. + Miami FL 33132 + US + +00-0A-9D (hex) King Young Technology Co. Ltd. +000A9D (base 16) King Young Technology Co. Ltd. + 1Fl., No. 9, Lane 26, Gangchi Rd., Neihu + Taipei 114 + TW + +00-0A-A1 (hex) V V S Limited +000AA1 (base 16) V V S Limited + HPIC, 1. Ainslie Road , + Glasgow Scotland G52 4RU + GB + +00-0A-A4 (hex) SHANGHAI SURVEILLANCE TECHNOLOGY CO,LTD +000AA4 (base 16) SHANGHAI SURVEILLANCE TECHNOLOGY CO,LTD + FL.25A,NO.8 CHANGYANG ROAD + SHANGHAI 200082 + CN + +00-0A-9E (hex) BroadWeb Corportation +000A9E (base 16) BroadWeb Corportation + 3F, 24-1, Industry East Rd., IV, + Hsin-Chu 300 + TW + +00-0A-E0 (hex) Fujitsu Softek +000AE0 (base 16) Fujitsu Softek + 1250 East Arques Ave + Sunnyvale Ca 94085 + US + +00-0A-8B (hex) Cisco Systems, Inc +000A8B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0A-88 (hex) InCypher S.A. +000A88 (base 16) InCypher S.A. + 18 rue de l'Eau + Luxembourg 1449 + LU + +00-0A-BB (hex) Taiwan Secom Co,. Ltd +000ABB (base 16) Taiwan Secom Co,. Ltd + 13F, 108, Sec1, Shin-Tai 5th Road + Hsi-Chih Taipei County 221 + TW + +00-0A-7C (hex) Tecton Ltd +000A7C (base 16) Tecton Ltd + Fishers Court + Eastleigh Hampshire SO50 7HG + GB + +00-0A-6E (hex) Harmonic, Inc +000A6E (base 16) Harmonic, Inc + 4300 North First Street + San Jose CA 95134 + US + +00-0A-6D (hex) EKS Elektronikservice GmbH +000A6D (base 16) EKS Elektronikservice GmbH + Enzstr. 9 + Kornwestheim Baden-Württemberg 70806 + DE + +00-0A-43 (hex) Chunghwa Telecom Co., Ltd. +000A43 (base 16) Chunghwa Telecom Co., Ltd. + 12, Lane 551, Min-Tsu Road + Taoyuan 326 + TW + +00-0A-45 (hex) Audio-Technica Corp. +000A45 (base 16) Audio-Technica Corp. + Naruse 1,348 + Machida Tokyo 194-8566 + JP + +00-0A-35 (hex) Xilinx +000A35 (base 16) Xilinx + 2100 Logic Drive + San Jose CA 94110 + US + +00-0A-3B (hex) GCT Semiconductor, Inc +000A3B (base 16) GCT Semiconductor, Inc + 2121 Ringwood Avenue + San Jose CA 95131 + US + +00-0A-74 (hex) Manticom Networks Inc. +000A74 (base 16) Manticom Networks Inc. + 14016-C Sullyfield Circle + Chantilly VA 20151 + US + +00-0A-6F (hex) ZyFLEX Technologies Inc +000A6F (base 16) ZyFLEX Technologies Inc + 2Fl. No. 58 Park Ave. II + S.B.I.P., Hsinchu 30077 + TW + +00-0A-63 (hex) DHD GmbH +000A63 (base 16) DHD GmbH + Haferkornstrasse 5 + Leipzig Sachsen 04129 + DE + +00-0A-2E (hex) MAPLE NETWORKS CO., LTD +000A2E (base 16) MAPLE NETWORKS CO., LTD + 602, Dongwha + SEOUL 156-010 + KR + +00-0A-2D (hex) Cabot Communications Limited +000A2D (base 16) Cabot Communications Limited + Verona House + Bristol Gloucestershire BS16 3RY + US + +00-0A-25 (hex) CERAGON NETWORKS +000A25 (base 16) CERAGON NETWORKS + 24 RAUEL WALLENBERG STREET + TEL-AVIV 96719 + IL + +00-0A-21 (hex) Integra Telecom Co. Ltd +000A21 (base 16) Integra Telecom Co. Ltd + 7th floor Hwayoung Bld. 112-2 + Seoul + KR + +00-0A-1E (hex) Red-M Products Limited +000A1E (base 16) Red-M Products Limited + Neptune House + Wooburn Green Buckinghamshire HP10 0HH + GB + +00-0A-4B (hex) DataPower Technology, Inc. +000A4B (base 16) DataPower Technology, Inc. + One Alewife Center + Cambridge MA 02140 + US + +00-0A-33 (hex) Emulex Corporation +000A33 (base 16) Emulex Corporation + 2021 Opportunity Drive + Roseville CA 95678 + US + +00-0A-67 (hex) OngCorp +000A67 (base 16) OngCorp + 481 Hackensack Ave. + Hackensack NJ 07601 + US + +00-09-F9 (hex) ART JAPAN CO., LTD. +0009F9 (base 16) ART JAPAN CO., LTD. + 322-7, Ichinotsubo, + Kawasaki Kanagawa 211-0016 + JP + +00-09-FC (hex) IPFLEX Inc. +0009FC (base 16) IPFLEX Inc. + Mowa-Bldg 3F, 1-16-6 + Shibuya-ku Tokyo 150-0021 + JP + +00-09-FD (hex) Ubinetics Limited +0009FD (base 16) Ubinetics Limited + Cambridge Technology Centre + Melbourn Hertfordshire SG8 6DP + GB + +00-09-F7 (hex) SED, a division of Calian +0009F7 (base 16) SED, a division of Calian + 18 Innnovation Boulevard + Saskatoon Saskatchewan (SK) S7K 3P7 + CA + +00-09-E2 (hex) Sinbon Electronics Co., Ltd. +0009E2 (base 16) Sinbon Electronics Co., Ltd. + 4F-13, No. 79, Sec 1, Hsin Tai Wu Rd. + Hsi-Chih, Taipei 221 + TW + +00-09-DA (hex) Control Module Inc. +0009DA (base 16) Control Module Inc. + 227 Brainard Road + Enfield CT 06082 + US + +00-09-D7 (hex) DC Security Products +0009D7 (base 16) DC Security Products + One Lindsay Circle + San Francisco California 94124 + US + +00-09-D8 (hex) Fält Communications AB +0009D8 (base 16) Fält Communications AB + Kylgränd 6a + SE 906 20 Umeå + SE + +00-0A-14 (hex) TECO a.s. +000A14 (base 16) TECO a.s. + Havlickova 260 + KOLIN CZ 280 58 + CZ + +00-0A-0B (hex) Sealevel Systems, Inc. +000A0B (base 16) Sealevel Systems, Inc. + 155 Technology Place + Liberty SC 29657 + US + +00-0A-10 (hex) FAST media integrations AG +000A10 (base 16) FAST media integrations AG + Schöngrund 26 + Rotkreuz Canton of Zug 6343 + CH + +00-09-DB (hex) eSpace +0009DB (base 16) eSpace + 9623 Simsbury Ct. + Twinsburg OH 44087-3220 + US + +00-09-D5 (hex) Signal Communication, Inc. +0009D5 (base 16) Signal Communication, Inc. + 100 Wood Ave South + Iselin NJ 08830 + US + +00-09-D3 (hex) Western DataCom Co., Inc. +0009D3 (base 16) Western DataCom Co., Inc. + 925-D Bassett Rd. + Westlake OH 44145 + US + +00-09-BC (hex) Utility, Inc +0009BC (base 16) Utility, Inc + 250 E Ponce de Leon Ave Suite 700 + Decatur GA 30030 + US + +00-09-BE (hex) Mamiya-OP Co.,Ltd. +0009BE (base 16) Mamiya-OP Co.,Ltd. + 3-23-10, Negishi Minami-ku + Saitama-shi Saitama 336-8581 + JP + +00-09-E6 (hex) Cyber Switching Inc. +0009E6 (base 16) Cyber Switching Inc. + 1800 De La Cruz Blvd. + Santa Clara CA 95050 + US + +00-09-FB (hex) Philips Patient Monitoring +0009FB (base 16) Philips Patient Monitoring + Hewlett-Packard-Str.2 + Boeblingen 71034 + DE + +00-09-8F (hex) Cetacean Networks +00098F (base 16) Cetacean Networks + 110 Corporate Drive + Portsmouth NH 03801 + US + +00-09-87 (hex) NISHI NIPPON ELECTRIC WIRE & CABLE CO.,LTD. +000987 (base 16) NISHI NIPPON ELECTRIC WIRE & CABLE CO.,LTD. + Kasugaura + Oita-City OITA 870-8632 + JP + +00-09-89 (hex) VividLogic Inc. +000989 (base 16) VividLogic Inc. + 40994 Encyclopedia Circle + Fremont CA 94538 + US + +00-09-86 (hex) Metalink LTD. +000986 (base 16) Metalink LTD. + Yakum Business Park + Yakum HOF HASHARON 60972 + IL + +00-09-8C (hex) Option Wireless Sweden +00098C (base 16) Option Wireless Sweden + Sturegatan 2 + Sundbyberg SE-172 24 + SE + +00-09-85 (hex) Auto Telecom Company +000985 (base 16) Auto Telecom Company + 10F, No.3,Lane 16, Sec.2, Sichuan Rd. + Banqiao City Taipei County 22061 + TW + +00-09-8D (hex) Velocity Semiconductor +00098D (base 16) Velocity Semiconductor + Suite 32 Wey House + Weybridge Surrey KT13 8NA + GB + +00-09-81 (hex) Newport Networks +000981 (base 16) Newport Networks + Enterprise House + Chepstow Monmouthshire NP16 5PB + GB + +00-09-55 (hex) Young Generation International Corp. +000955 (base 16) Young Generation International Corp. + 4F.,No. 188, Minchuan Rd., Shindian City + Shindian 231 + TW + +00-09-4A (hex) Homenet Communications +00094A (base 16) Homenet Communications + Innovation Centre + Limerick + IE + +00-09-4B (hex) FillFactory NV +00094B (base 16) FillFactory NV + Schalienhoevedreef 20B + B-2800 Mechelen + BE + +00-09-4D (hex) Braintree Communications Pty Ltd +00094D (base 16) Braintree Communications Pty Ltd + Unit 3 + Slacks Creek QLD 4127 + AU + +00-09-50 (hex) Independent Storage Corporation +000950 (base 16) Independent Storage Corporation + 6273 Monarch Park Place + Niwot Colorado 80503 + US + +00-09-54 (hex) AMiT spol. s. r. o. +000954 (base 16) AMiT spol. s. r. o. + Naskove 3 + 150 00 Praha 5 + CZ + +00-09-92 (hex) InterEpoch Technology,INC. +000992 (base 16) InterEpoch Technology,INC. + 7F,No.3,Alley 6,Lane 235,Pao-Chiao Rd + Hsin-Tien Taipei Hsien 231 + TW + +00-09-95 (hex) Castle Technology Ltd +000995 (base 16) Castle Technology Ltd + Ore Trading Estate + Framlingham Suffolk IP13 9LL + GB + +00-09-98 (hex) Capinfo Company Limited +000998 (base 16) Capinfo Company Limited + 7th Floor A Corporate Square, NO. 35 Fin + Beijing 100032 + CN + +00-09-B6 (hex) Cisco Systems, Inc +0009B6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-B3 (hex) MCM Systems Ltd +0009B3 (base 16) MCM Systems Ltd + Kolomban 9F + Ankaran Slovenija 6280 + SI + +00-09-5C (hex) Philips Medical Systems - Cardiac and Monitoring Systems (CM +00095C (base 16) Philips Medical Systems - Cardiac and Monitoring Systems (CM + 3000 Minuteman Road + Andover Massachusetts 01810 + US + +00-09-58 (hex) INTELNET S.A. +000958 (base 16) INTELNET S.A. + FRANCISCO OLIVAN BAYLE, 4 + ZARAGOZA 50015 + ES + +00-09-A3 (hex) Leadfly Techologies Corp. Ltd. +0009A3 (base 16) Leadfly Techologies Corp. Ltd. + 9Fl, No.260, Bade Rd., + Taipei 104 + TW + +00-09-A5 (hex) HANSUNG ELETRONIC INDUSTRIES DEVELOPMENT CO., LTD +0009A5 (base 16) HANSUNG ELETRONIC INDUSTRIES DEVELOPMENT CO., LTD + HEUNGJIN BLDG 3F, #217-3 POI-DONG, KANGN + SEOUL 135-963 + KR + +00-09-62 (hex) Sonitor Technologies AS +000962 (base 16) Sonitor Technologies AS + Forskningsveien 1B + Oslo Blindern N-0134 + NO + +00-09-5D (hex) Dialogue Technology Corp. +00095D (base 16) Dialogue Technology Corp. + 10F, No. 196, Sec. 2, Jungshing Rd. + Shindian City Taipei 231 + TW + +00-09-9A (hex) ELMO COMPANY, LIMITED +00099A (base 16) ELMO COMPANY, LIMITED + 6-14, MEIZEN-CHO, MIZUHO-KU + NAGOYA AICHI-Pref. 467-8567 + JP + +00-09-9C (hex) Naval Research Laboratory +00099C (base 16) Naval Research Laboratory + Code 5592 + Washington DC 20375-5000 + US + +00-09-84 (hex) MyCasa Network Inc. +000984 (base 16) MyCasa Network Inc. + 200 Sheridan Ave #103 + Palo Alto CA 94306 + US + +00-09-2B (hex) iQstor Networks, Inc. +00092B (base 16) iQstor Networks, Inc. + 2001 Corporate Center Drive + Newbury Park CA 91320 + US + +00-09-26 (hex) YODA COMMUNICATIONS, INC. +000926 (base 16) YODA COMMUNICATIONS, INC. + 2F, No.3-1, Industry East Road IX, + Hsinchu 300 + TW + +00-09-27 (hex) TOYOKEIKI CO.,LTD. +000927 (base 16) TOYOKEIKI CO.,LTD. + 17-10-3,Shimosinjyo + Osaka 533-0021 + JP + +00-09-23 (hex) Heaman System Co., Ltd +000923 (base 16) Heaman System Co., Ltd + Building M6,National Hi-tech & Indus + Changsha Hunan Province 410013 + US + +00-09-1D (hex) Proteam Computer Corporation +00091D (base 16) Proteam Computer Corporation + 7F, No. 157. Section 2 Ta-Tung Rd + Hsi-Chih Taipei Hsien 221 + US + +00-08-EB (hex) ROMWin Co.,Ltd. +0008EB (base 16) ROMWin Co.,Ltd. + 406 OmiyaOhtaka Bldg. 1-103 + Saitama 330-0843 + US + +00-08-E8 (hex) Excel Master Ltd. +0008E8 (base 16) Excel Master Ltd. + Room D, 3/F., Yeung Yiu Chung (No. 8) Ind. Bldg. + Kowloon Bay + HK + +00-08-DC (hex) Wiznet +0008DC (base 16) Wiznet + 5F Simmtech bldg., 228-3, + Seoul 135-830 + KR + +00-08-DD (hex) Telena Communications, Inc. +0008DD (base 16) Telena Communications, Inc. + 6725 Mesa Ridge Road + San Diego CA 92121 + US + +00-08-E1 (hex) Barix AG +0008E1 (base 16) Barix AG + Seefeld Strasse 303 + Zürich ZH 8008 + US + +00-09-09 (hex) Telenor Connect A/S +000909 (base 16) Telenor Connect A/S + Ellegaardvej 25L + Sønderborg Als 6400 + DK + +00-09-0A (hex) SnedFar Technology Co., Ltd. +00090A (base 16) SnedFar Technology Co., Ltd. + 15FL., No.866-2, Jung Jeng Rd., + Junghe Taipei 235 + TW + +00-09-0F (hex) Fortinet Inc. +00090F (base 16) Fortinet Inc. + 1090 Kifer Road + Sunnyvale CA 94086 + US + +00-09-2C (hex) Hitpoint Inc. +00092C (base 16) Hitpoint Inc. + No.7, Fenliao, 2nd Industrial Park, Link + Taipei 244 + TW + +00-09-03 (hex) Panasas, Inc +000903 (base 16) Panasas, Inc + 15333 John F Kennedy Blvd, Suite 400 + Houston TX 77032-2351 + US + +00-09-07 (hex) Chrysalis Development +000907 (base 16) Chrysalis Development + 8125 River Dr. Suite 100 + Morton Grove IL 60053 + US + +00-09-06 (hex) Esteem Networks +000906 (base 16) Esteem Networks + 4F, No.900, Yishan Road + Shanghai 200233 + CN + +00-09-52 (hex) Auerswald GmbH & Co. KG +000952 (base 16) Auerswald GmbH & Co. KG + Vor den Grashoefen 1 + Cremlingen Niedersachsen 38162 + DE + +00-09-44 (hex) Cisco Systems, Inc +000944 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-08-FB (hex) SonoSite, Inc. +0008FB (base 16) SonoSite, Inc. + 21919 30th Drive SE + Bothell WA 98021 + US + +00-08-EE (hex) Logic Product Development +0008EE (base 16) Logic Product Development + 411 Washington Ave N. Suite 101 + Minneapolis Minnesota 55401 + US + +00-09-17 (hex) WEM Technology Inc +000917 (base 16) WEM Technology Inc + 8F-2, No 386, Sec 5 Nanjing East Road. + Taipei 105 + TW + +00-08-81 (hex) DIGITAL HANDS CO.,LTD. +000881 (base 16) DIGITAL HANDS CO.,LTD. + KAKiYA Building 2F + Yokohama Kanagawa 222-0033 + JP + +00-08-82 (hex) SIGMA CORPORATION +000882 (base 16) SIGMA CORPORATION + 2-3-15 Iwato-minami + Komae-shi Tokyo 201-8630 + JP + +00-08-73 (hex) DapTechnology B.V. +000873 (base 16) DapTechnology B.V. + Zutphenstraat 67 + EJ Oldenzaal 7575 + NL + +00-08-7A (hex) Wipotec GmbH +00087A (base 16) Wipotec GmbH + Adam-Hoffman Str. 26 + + DE + +00-08-71 (hex) NORTHDATA Co., Ltd. +000871 (base 16) NORTHDATA Co., Ltd. + #302 KayangTechno-Town 1487 + Kangseo-Gu Seoul 157-810 + KR + +00-08-B2 (hex) SHENZHEN COMPASS TECHNOLOGY DEVELOPMENT CO.,LTD +0008B2 (base 16) SHENZHEN COMPASS TECHNOLOGY DEVELOPMENT CO.,LTD + 4th Floor,Building 205,TaiRan Industry + Shenzhen GUANGDONG 518040 + CN + +00-08-B1 (hex) ProQuent Systems +0008B1 (base 16) ProQuent Systems + 67 Forest Street + Marlboro MA 01752 + US + +00-08-AF (hex) Novatec Corporation +0008AF (base 16) Novatec Corporation + 2-19-2 Nishi-Gotanda + Shinagawa-ku Tokyo 141-0031 + JP + +00-08-A6 (hex) Multiware & Image Co., Ltd. +0008A6 (base 16) Multiware & Image Co., Ltd. + Saedong Bldg. 65-25, + Pusan 606-032 + KR + +00-08-7E (hex) Bon Electro-Telecom Inc. +00087E (base 16) Bon Electro-Telecom Inc. + Gayang 1st Factory 701, 14-81 + Seoul 157-808 + KR + +00-08-80 (hex) BroadTel Canada Communications inc. +000880 (base 16) BroadTel Canada Communications inc. + 3700 Griffith, Suite 389 + Saint-Laurent Quebec H4T 2B3 + CA + +00-08-6D (hex) Missouri FreeNet +00086D (base 16) Missouri FreeNet + PO Box 771026 + St. Louis Missouri 63177-1026 + US + +00-08-D4 (hex) IneoQuest Technologies, Inc +0008D4 (base 16) IneoQuest Technologies, Inc + 1931 Washington St + Canton Massachusetts 02021 + US + +00-08-D6 (hex) HASSNET Inc. +0008D6 (base 16) HASSNET Inc. + 2F Missy2000 B/D 725, SooSeo-Dong, + Seoul 135-757 + KR + +00-08-CE (hex) IPMobileNet Inc. +0008CE (base 16) IPMobileNet Inc. + 11909 E Telegraph Rd. + Santa Fe Springs CA 90670 + US + +00-08-C2 (hex) Cisco Systems, Inc +0008C2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-08-C0 (hex) ASA SYSTEMS +0008C0 (base 16) ASA SYSTEMS + S245 Korea Maritime University, 1 Dongsa + Busan Busan Metropolitan City 606-791 + KR + +00-08-A3 (hex) Cisco Systems, Inc +0008A3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-08-9E (hex) Beijing Enter-Net co.LTD +00089E (base 16) Beijing Enter-Net co.LTD + NO 1 courtyard, + Beijing 100085 + US + +00-08-B4 (hex) SYSPOL +0008B4 (base 16) SYSPOL + 4th Fl,SYSPOL B/D, Bangbae 4 Dong, Seoch + Seoul 137-064 + US + +00-08-B3 (hex) Fastwel +0008B3 (base 16) Fastwel + Profsoyuznaya 108, + Moscow 117313 + RU + +00-08-8E (hex) Nihon Computer Co., Ltd. +00088E (base 16) Nihon Computer Co., Ltd. + 36-8 Higashitamachi + Hamamatsu Shizuoka 430-0915 + JP + +00-08-DA (hex) SofaWare Technologies Ltd. +0008DA (base 16) SofaWare Technologies Ltd. + 3 Hilazon St. + Ramat-Gan 52522 + IL + +00-07-D5 (hex) 3e Technologies Int;., Inc. +0007D5 (base 16) 3e Technologies Int;., Inc. + 15800 Crabbs Branch Way + Rockville MD 20855 + US + +00-07-DB (hex) Kirana Networks, Inc. +0007DB (base 16) Kirana Networks, Inc. + 331 Newman Springs Road + Red Bank NJ 07701 + US + +00-08-6A (hex) Securiton Gmbh +00086A (base 16) Securiton Gmbh + Von-Drais-Strasse 33 + Achern D-77855 + DE + +00-08-63 (hex) Entrisphere Inc. +000863 (base 16) Entrisphere Inc. + 1601 S. De Anza Blvd. + Cupertino CA 95014 + US + +00-08-66 (hex) DSX Access Systems, Inc. +000866 (base 16) DSX Access Systems, Inc. + 10731 Rockwall Rd. + Dallas TX 75238 + US + +00-07-EF (hex) Lockheed Martin Tactical Systems +0007EF (base 16) Lockheed Martin Tactical Systems + 3333 Pilot Knob Road + Eagan MN 55121 + US + +00-07-F4 (hex) Eletex Co., Ltd. +0007F4 (base 16) Eletex Co., Ltd. + 8-2-56 Nankou-Higashi Suminoe-ku + + JP + +00-07-DD (hex) Cradle Technologies +0007DD (base 16) Cradle Technologies + 3130 West Warren Ave. + Fremont CA 94538 + US + +00-08-1B (hex) Windigo Systems +00081B (base 16) Windigo Systems + 2210 O'Toole Ave. #200 + San Jose CA 95131 + US + +00-07-FF (hex) Gluon Networks +0007FF (base 16) Gluon Networks + 5401 Old Redwood Hwy. + Petaluma CA 94954 + US + +00-07-F7 (hex) Galtronics +0007F7 (base 16) Galtronics + 4645 East Cotton Center Blvd. + Phoenix AZ 85040 + US + +00-08-5F (hex) Picanol N.V. +00085F (base 16) Picanol N.V. + Polenlaan 3-7 + + BE + +00-08-52 (hex) Davolink Co. Inc. +000852 (base 16) Davolink Co. Inc. + Room-604, Kumhwa Plaza, + Kyunggi-Do 435-040 + KR + +00-08-0C (hex) VDA Elettronica spa +00080C (base 16) VDA Elettronica spa + Viale Lino Zanussi, 3 + 33170 Pordenone + IT + +00-08-04 (hex) ICA Inc. +000804 (base 16) ICA Inc. + 542-1 Noguki + + JP + +00-08-57 (hex) Polaris Networks, Inc. +000857 (base 16) Polaris Networks, Inc. + 6810 Santa Teresa Blvd. + San Jose CA 95119 + US + +00-07-8B (hex) Wegener Communications, Inc. +00078B (base 16) Wegener Communications, Inc. + 11350 Technology Circle + Duluth GA 30097 + US + +00-07-83 (hex) SynCom Network, Inc. +000783 (base 16) SynCom Network, Inc. + 4F, No. 31, Hsintai Road, Chupei City, + + TW + +00-07-87 (hex) Idea System Co., Ltd. +000787 (base 16) Idea System Co., Ltd. + 4-1-21 Shinmei-cho Okaya-shi + + JP + +00-07-89 (hex) Allradio Co., Ltd +000789 (base 16) Allradio Co., Ltd + 861-5, Gwanyang-Dong, Dongan-Gu, + Anyang-si, Gyeonggi-do, 430-803 + KR + +00-07-B9 (hex) Ginganet Corporation +0007B9 (base 16) Ginganet Corporation + Kintetsu Shin Namba Building + Osaka Shi 1556-0017 + JP + +00-04-7F (hex) Chr. Mayr GmbH & Co. KG +00047F (base 16) Chr. Mayr GmbH & Co. KG + Eichenstraße 1 + + DE + +00-04-7B (hex) Schlumberger +00047B (base 16) Schlumberger + Sugar Land Product Center + Sugar Land TX 77478 + US + +00-07-B4 (hex) Cisco Systems, Inc +0007B4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-07-B3 (hex) Cisco Systems, Inc +0007B3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-07-B5 (hex) Any One Wireless Ltd. +0007B5 (base 16) Any One Wireless Ltd. + Namseoul Bd., 8F, 1304-3 + Seoul + KR + +00-07-85 (hex) Cisco Systems, Inc +000785 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-07-75 (hex) Valence Semiconductor, Inc. +000775 (base 16) Valence Semiconductor, Inc. + 41 Discovery + Irvine CA 92618 + US + +00-07-93 (hex) Shin Satellite Public Company Limited +000793 (base 16) Shin Satellite Public Company Limited + 41/103 Rattanathibet Road, + + TH + +00-07-96 (hex) LSI Systems, Inc. +000796 (base 16) LSI Systems, Inc. + 10-1 Minami-kurokawa, + Kanagawa 215-0034 + JP + +00-07-7F (hex) J Communications Co., Ltd. +00077F (base 16) J Communications Co., Ltd. + 124-4 Ojeon-Dong, Ulwang-City + + KR + +00-07-71 (hex) Embedded System Corporation +000771 (base 16) Embedded System Corporation + 13-5, Takadanobaba 3-chome, + + JP + +00-07-70 (hex) Ubiquoss Inc +000770 (base 16) Ubiquoss Inc + Ubiquoss B/D, 68, Pangyo-ro 255beon-gil, + + KR + +00-07-D1 (hex) Spectrum Signal Processing Inc. +0007D1 (base 16) Spectrum Signal Processing Inc. + #200-2700 Production Way + + CA + +00-07-A2 (hex) Opteon Corporation +0007A2 (base 16) Opteon Corporation + 70 Hastings Street + Wellesley MA 02481 + US + +00-06-F8 (hex) The Boeing Company +0006F8 (base 16) The Boeing Company + 5731 W. Las Positas Blvd. + Pleasanton CA 94588 + US + +00-06-FB (hex) Hitachi Printing Solutions, Ltd. +0006FB (base 16) Hitachi Printing Solutions, Ltd. + 1060, Takeda Hitachinaka-City + 312-8502 + JP + +00-06-FC (hex) Fnet Co., Ltd. +0006FC (base 16) Fnet Co., Ltd. + KFSB Bldg. 10th F. 16-2 + Seoul + KR + +00-06-F4 (hex) Prime Electronics & Satellitics Inc. +0006F4 (base 16) Prime Electronics & Satellitics Inc. + 69,Tung-Yuan Rd + Chung-Li City Tao-Yuan County 32000 + TW + +00-07-38 (hex) Young Technology Co., Ltd. +000738 (base 16) Young Technology Co., Ltd. + D-604, Sigma-II Officetel, + Sungnam-si, Kyeonggi-do 763-741 + KR + +00-07-29 (hex) Kistler Instrumente AG +000729 (base 16) Kistler Instrumente AG + Eulachstrasse 22 + + CH + +00-07-2A (hex) Innovance Networks +00072A (base 16) Innovance Networks + 19 Fairmont Avenue + + CA + +00-07-4A (hex) Carl Valentin GmbH +00074A (base 16) Carl Valentin GmbH + Neckarstrabe 78-80 + + DE + +00-07-3C (hex) Telecom Design +00073C (base 16) Telecom Design + Voie Romaine, Zone de Remora + + FR + +00-07-36 (hex) Data Video Technologies Co., Ltd. +000736 (base 16) Data Video Technologies Co., Ltd. + 7F, No. 352, Sec. 2 + Taipei Hsien + TW + +00-07-50 (hex) Cisco Systems, Inc +000750 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-07-42 (hex) Ormazabal +000742 (base 16) Ormazabal + Parque Tecnologico 104 + 48170 Zamudio, Bizkaia + ES + +00-07-4B (hex) Daihen Corporation +00074B (base 16) Daihen Corporation + 2-1-11 Tagawa Yodogawa-ku + + JP + +00-07-64 (hex) YoungWoo Telecom Co. Ltd. +000764 (base 16) YoungWoo Telecom Co. Ltd. + 3F, Sehwa B/D, 355-1 + Sungnam-Si Kyungki-Do + KR + +00-07-66 (hex) Chou Chin Industrial Co., Ltd. +000766 (base 16) Chou Chin Industrial Co., Ltd. + 9F, #35, Chiau An St. Chung Ho City, + + TW + +00-07-61 (hex) 29530 +000761 (base 16) 29530 + EPFL - Quartier de l'Innovation + Lausanne CH 1015 + CH + +00-07-55 (hex) Lafon +000755 (base 16) Lafon + 44 Avenue Victor Meunier + Bassens 33530 + FR + +00-07-59 (hex) Boris Manufacturing Corp. +000759 (base 16) Boris Manufacturing Corp. + PO Box 601 + Castle Point NY 12511 + US + +00-07-51 (hex) m-u-t AG +000751 (base 16) m-u-t AG + Messgeräte für Medizin- und Umwelttechnik + Wedel 22880 + DE + +00-07-19 (hex) Mobiis Co., Ltd. +000719 (base 16) Mobiis Co., Ltd. + 277-1, Shinhwa Bldg. 4F + Seoul, + KR + +00-07-0D (hex) Cisco Systems, Inc +00070D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-07-0E (hex) Cisco Systems, Inc +00070E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-07-0B (hex) Novabase SGPS, SA +00070B (base 16) Novabase SGPS, SA + Av. D Joao II, Lote 1.03.2.3 + Lisboa 1998-031 + PT + +00-07-10 (hex) Adax, Inc. +000710 (base 16) Adax, Inc. + 614 Bancroft Way + Berkeley CA 94556 + US + +00-06-E8 (hex) Optical Network Testing, Inc. +0006E8 (base 16) Optical Network Testing, Inc. + 55 Merchant St. + Honolulu HI 96813 + US + +00-06-EE (hex) Shenyang Neu-era Information & Technology Stock Co., Ltd +0006EE (base 16) Shenyang Neu-era Information & Technology Stock Co., Ltd + 8/F, the 21st Century Building, + Dvlpmnt Zone Shenyang, + CN + +00-06-E2 (hex) Ceemax Technology Co., Ltd. +0006E2 (base 16) Ceemax Technology Co., Ltd. + 5f-7, 736, Chung Cheng Rd., + + TW + +00-06-A5 (hex) PINON Corp. +0006A5 (base 16) PINON Corp. + Axis Gotanda Bldg.7F-701 + Tokyo 141-0031 + JP + +00-06-9D (hex) Petards Ltd +00069D (base 16) Petards Ltd + 390 Princesway, Team Valley + Gateshead Tyne and Wear NE11 OTU + GB + +00-06-A8 (hex) KC Technology, Inc. +0006A8 (base 16) KC Technology, Inc. + 1900 McCarthy Blvd. + Milpitas CA 95035 + US + +00-06-A0 (hex) Mx Imaging +0006A0 (base 16) Mx Imaging + 2894 Columbia Street + Torrance CA 90503 + US + +00-06-BE (hex) Baumer Optronic GmbH +0006BE (base 16) Baumer Optronic GmbH + Badstraße 30 + + DE + +00-06-BA (hex) Westwave Communications +0006BA (base 16) Westwave Communications + 463 Aviation Blvd. + Santa Rosa CA 95403 + US + +00-06-C4 (hex) Piolink Inc. +0006C4 (base 16) Piolink Inc. + IT Castle 1-401, 550-1 Gasan-dong, + Seoul 153-803 + KR + +00-06-B5 (hex) Source Photonics, Inc. +0006B5 (base 16) Source Photonics, Inc. + 20550 Nordhoff St. + Chatsworth CA 91311 + US + +00-06-8F (hex) Telemonitor, Inc. +00068F (base 16) Telemonitor, Inc. + 9055F Guilford Road + Columbia MD 21046 + US + +00-06-DA (hex) ITRAN Communications Ltd. +0006DA (base 16) ITRAN Communications Ltd. + 1 Azrieli Center, + Tel Aviv 67021 67021 + IL + +00-06-D0 (hex) Elgar Electronics Corp. +0006D0 (base 16) Elgar Electronics Corp. + 9250 Brown Deer Rd. + San Diego CA 92121 + US + +00-06-CC (hex) JMI Electronics Co., Ltd. +0006CC (base 16) JMI Electronics Co., Ltd. + Nanyang B/D 3F, 25-4 + Seoul 140-080 + KR + +00-06-BF (hex) Accella Technologies Co., Ltd. +0006BF (base 16) Accella Technologies Co., Ltd. + Rm 512 No. 680 Gui Ping Rd. + Shanghai 200233 + CN + +00-06-90 (hex) Euracom Communication GmbH +000690 (base 16) Euracom Communication GmbH + Franklinstraße 14 + + DE + +00-06-E1 (hex) Techno Trade s.a +0006E1 (base 16) Techno Trade s.a + 732a Chaussee de Bruxelles + + BE + +00-06-2E (hex) Aristos Logic Corp. +00062E (base 16) Aristos Logic Corp. + 27051 Towne Centre Dr. + Foothill Ranch CA 92610 + US + +00-06-24 (hex) Gentner Communications Corp. +000624 (base 16) Gentner Communications Corp. + 1825 Research Way + Salt Lake City UT 84119 + US + +00-06-25 (hex) The Linksys Group, Inc. +000625 (base 16) The Linksys Group, Inc. + 17401 Armstrong Ave. + Irvine CA 92614 + US + +00-06-27 (hex) Uniwide Technologies, Inc. +000627 (base 16) Uniwide Technologies, Inc. + Korea Development Bank B/D 5th Flr + Taejon 302-122, + KR + +00-06-2A (hex) Cisco Systems, Inc +00062A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-06-2C (hex) Bivio Networks +00062C (base 16) Bivio Networks + 4457 Willow Road, + Pleasanton CA 94588 + US + +00-06-21 (hex) Hinox, Co., Ltd. +000621 (base 16) Hinox, Co., Ltd. + 15-7 3-chome, Sennin-cho, + 193-0835 + JP + +00-06-4E (hex) Broad Net Technology Inc. +00064E (base 16) Broad Net Technology Inc. + 5F, No.58, Lane 188, Rui Kuang Road + + TW + +00-06-2D (hex) TouchStar Technologies, L.L.C. +00062D (base 16) TouchStar Technologies, L.L.C. + 5147 South Garnett Road + Tulsa OK 74146 + US + +00-06-46 (hex) ShenZhen XunBao Network Technology Co Ltd +000646 (base 16) ShenZhen XunBao Network Technology Co Ltd + F3, R2-A Building, South District + Shen Zhen + CN + +00-06-4B (hex) Alexon Co., Ltd. +00064B (base 16) Alexon Co., Ltd. + 3-207-1 Teramoto, + + JP + +00-06-3C (hex) Intrinsyc Software International Inc. +00063C (base 16) Intrinsyc Software International Inc. + 885 Dunsmuir Street, Suite 380 + Vancouver B.C. V6C 1N5 + CA + +00-06-30 (hex) Adtranz Sweden +000630 (base 16) Adtranz Sweden + Dept. TCC/TH + + SE + +00-06-37 (hex) Toptrend-Meta Information (ShenZhen) Inc. +000637 (base 16) Toptrend-Meta Information (ShenZhen) Inc. + 2/F, Bldg. 3, Section A, Nor-East Zone + + CN + +00-06-1C (hex) Hoshino Metal Industries, Ltd. +00061C (base 16) Hoshino Metal Industries, Ltd. + 645 Yamanokami, Yabutsuka, + 379-2302 + JP + +00-06-23 (hex) MGE UPS Systems France +000623 (base 16) MGE UPS Systems France + 140 Avenue Jean Kuntzmann + + FR + +00-06-0B (hex) Artesyn Embedded Technologies +00060B (base 16) Artesyn Embedded Technologies + 2900 S. Diablo Way Suite 190 + Tempe AZ 85282 + US + +00-06-7E (hex) WinCom Systems, Inc. +00067E (base 16) WinCom Systems, Inc. + 10900 World Trade Blvd. + Morrisville NC 27560 + US + +00-06-77 (hex) SICK AG +000677 (base 16) SICK AG + Erwin-Sick Str.1 + Waldkirch D-79183 + DE + +00-06-66 (hex) Roving Networks +000666 (base 16) Roving Networks + 809 University Avenue + Los Gatos CA 95032 + US + +00-06-67 (hex) Tripp Lite +000667 (base 16) Tripp Lite + 1111 W. 35th Street + Chicago IL 60609 + US + +00-06-4D (hex) Sencore +00064D (base 16) Sencore + 3200 Sencore Dr. + Sioux Falls SD 57107 + US + +00-06-60 (hex) NADEX Co., Ltd. +000660 (base 16) NADEX Co., Ltd. + 1 Omiyamae, Tokushige, + Aichi 481-0038 + JP + +00-06-79 (hex) Konami Corporation +000679 (base 16) Konami Corporation + 11-14-5 Akasaka, Minato-ku, + + JP + +00-06-6C (hex) Robinson Corporation +00066C (base 16) Robinson Corporation + 12F, No. 278 Ho Ping E. Rd., + Taipei + TW + +00-06-15 (hex) Kimoto Electric Co., Ltd. +000615 (base 16) Kimoto Electric Co., Ltd. + 3-1 Funahashi-Cho, + 543-0024 + JP + +00-06-0A (hex) Blue2space +00060A (base 16) Blue2space + Arstaangsv. 9 + + SE + +00-05-CE (hex) Prolink Microsystems Corporation +0005CE (base 16) Prolink Microsystems Corporation + 6F, No. 349, Yang-Kuang St. + Nei-Hu Taipei, + TW + +00-05-C2 (hex) Soronti, Inc. +0005C2 (base 16) Soronti, Inc. + 12159 Business Park Dr, suite 140 + Draper Utah 84020 + US + +00-05-DF (hex) Electronic Innovation, Inc. +0005DF (base 16) Electronic Innovation, Inc. + 12731 Cannington Way SW + Calgary, AB T2W 1Z7 + CA + +00-05-DE (hex) Gi Fone Korea, Inc. +0005DE (base 16) Gi Fone Korea, Inc. + Twin Bldg. 4th Fl, + Seoul, + KR + +00-05-E0 (hex) Empirix Corp. +0005E0 (base 16) Empirix Corp. + 205 Lowell St. + Wilmington MA 01887 + US + +00-05-D8 (hex) Arescom, Inc. +0005D8 (base 16) Arescom, Inc. + 3541 Gateway Blvd. + Fremont CA 94538 + US + +00-05-E4 (hex) Red Lion Controls Inc. +0005E4 (base 16) Red Lion Controls Inc. + 20 Willow Springs Circle + York PA 17402 + US + +00-05-F2 (hex) Power R, Inc. +0005F2 (base 16) Power R, Inc. + 756 Aloha St. + Seattle WA 98109 + US + +00-05-F3 (hex) Webyn +0005F3 (base 16) Webyn + 26 Rue Oes Gaudines + + FR + +00-06-01 (hex) Otanikeiki Co., Ltd. +000601 (base 16) Otanikeiki Co., Ltd. + 2-10-23 Hikari-Machi + 732-0052 + JP + +00-06-05 (hex) Inncom International, Inc. +000605 (base 16) Inncom International, Inc. + P.O. Box 1060 + Old Lyme CT 06371 + US + +00-05-FA (hex) IPOptical, Inc. +0005FA (base 16) IPOptical, Inc. + 45940 Horseshoe Drive + Dulles VA 20166 + US + +00-05-E5 (hex) Renishaw PLC +0005E5 (base 16) Renishaw PLC + New Mills, Wotton-under-Edge + + GB + +00-05-F5 (hex) Geospace Technologies +0005F5 (base 16) Geospace Technologies + 7007 Pinemont + Houston TX 77040 + US + +00-05-FD (hex) PacketLight Networks Ltd. +0005FD (base 16) PacketLight Networks Ltd. + 27 Habarzel St. + Tel-Aviv 69710 + IL + +00-05-D4 (hex) FutureSmart Networks, Inc. +0005D4 (base 16) FutureSmart Networks, Inc. + 6155 Almaden Expressway + San Jose CA 95120 + US + +00-05-C4 (hex) Telect, Inc. +0005C4 (base 16) Telect, Inc. + 2111 N. Molter Road + Liberty Lake WA 99019 + US + +00-05-A3 (hex) QEI, Inc. +0005A3 (base 16) QEI, Inc. + 60 Fadem Road + Springfield NJ 07081 + US + +00-05-9E (hex) Zinwell Corporation +00059E (base 16) Zinwell Corporation + 7F, No.512, Yuan-Shan Road + + TW + +00-05-A5 (hex) KOTT +0005A5 (base 16) KOTT + Suite 305 Daeha B/D + 135-080 + KR + +00-05-B3 (hex) Asahi-Engineering Co., Ltd. +0005B3 (base 16) Asahi-Engineering Co., Ltd. + 3-6-12-2 Gakuenhigashi-cho + Tokyo 187-0043 + JP + +00-05-9D (hex) Daniel Computing Systems, Inc. +00059D (base 16) Daniel Computing Systems, Inc. + 3208 8th Avenue NE #118 + T2A 7V8 + CA + +00-05-A4 (hex) Lucid Voice Ltd. +0005A4 (base 16) Lucid Voice Ltd. + 5 Jabotinski Street + + IL + +00-05-63 (hex) J-Works, Inc. +000563 (base 16) J-Works, Inc. + 12328 Gladstone St. #1 + Sylmor CA 91342 + US + +00-05-57 (hex) Agile TV Corporation +000557 (base 16) Agile TV Corporation + 333 Ravenswood Ave., + Menlo Park CA 94025 + US + +00-05-5B (hex) Charles Industries, Ltd. +00055B (base 16) Charles Industries, Ltd. + 5600 Apollo Dr. + Rolling Meadows IL 60008 + US + +00-05-54 (hex) Rangestar Wireless +000554 (base 16) Rangestar Wireless + 9565 Soquel Drive, Suite 100 + Aptos CA 95003 + US + +00-05-53 (hex) DVC Company, Inc. +000553 (base 16) DVC Company, Inc. + 10200 Hwy 290 W. + Austin TX 78236 + US + +00-05-66 (hex) Secui.com Corporation +000566 (base 16) Secui.com Corporation + 17th Fl. Samsung Yeoksam Bldg. + Seoul 135-080 + KR + +00-05-6C (hex) Hung Chang Co., Ltd. +00056C (base 16) Hung Chang Co., Ltd. + 1385-14, Juan-Dong, + + KR + +00-05-5F (hex) Cisco Systems, Inc +00055F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-5D (hex) D-LINK SYSTEMS, INC. +00055D (base 16) D-LINK SYSTEMS, INC. + 53 Discover Dr. + Irvine CA 92618 + US + +00-05-61 (hex) nac Image Technology, Inc. +000561 (base 16) nac Image Technology, Inc. + 8-7 Sanban-cho, Chiyoda-ku, + + JP + +00-05-94 (hex) HMS Industrial Networks +000594 (base 16) HMS Industrial Networks + PO Box 4126 + SE30004 SE + SE + +00-05-6F (hex) Innomedia Technologies Pvt. Ltd. +00056F (base 16) Innomedia Technologies Pvt. Ltd. + #3278, 12th Main Road + + IN + +00-05-74 (hex) Cisco Systems, Inc +000574 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-67 (hex) Etymonic Design, Inc. +000567 (base 16) Etymonic Design, Inc. + 41 Byron Avenue + NOL 1GO + CA + +00-05-65 (hex) Tailyn Communication Company Ltd. +000565 (base 16) Tailyn Communication Company Ltd. + No. 62, Lane 205, Nan-San Road, + Taoyuan Hsien + TW + +00-05-8E (hex) Flextronics International GmbH & Co. Nfg. KG +00058E (base 16) Flextronics International GmbH & Co. Nfg. KG + Schrackgasse 9-15 + Kindberg 8650 + AT + +00-05-32 (hex) Cisco Systems, Inc +000532 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-36 (hex) Danam Communications, Inc. +000536 (base 16) Danam Communications, Inc. + 900-3, Hokye-dong, Dongan-gu, + + KR + +00-05-42 (hex) Otari, Inc. +000542 (base 16) Otari, Inc. + 4-33-3 Kokuryo-cho, + + JP + +00-05-37 (hex) Nets Technology Co., Ltd. +000537 (base 16) Nets Technology Co., Ltd. + #B1 YungJun Bldg. + Seoul 135-090 135-090 + KR + +00-05-7C (hex) RCO Security AB +00057C (base 16) RCO Security AB + Box 705 + + SE + +00-05-83 (hex) ImageCom Limited +000583 (base 16) ImageCom Limited + Cedars Park, Cedars Road, + SL6 1RZ + GB + +00-05-4B (hex) Eaton Automation AG +00054B (base 16) Eaton Automation AG + Spinnereistrasse 8 + St.Gallen 9008 + CH + +00-04-C8 (hex) LIBA Maschinenfabrik GmbH +0004C8 (base 16) LIBA Maschinenfabrik GmbH + PO Box 1120 + + DE + +00-04-CC (hex) Peek Traffic B.V. +0004CC (base 16) Peek Traffic B.V. + Postbus 2542 + The + NL + +00-04-BF (hex) VersaLogic Corp. +0004BF (base 16) VersaLogic Corp. + 12100 SW Tualatin Rd + Tualatin OR 97062 + US + +00-04-C3 (hex) CASTOR Informatique +0004C3 (base 16) CASTOR Informatique + 2, Rue Du Kefir + 94537 Orly Cedex + FR + +00-04-F6 (hex) Amphus +0004F6 (base 16) Amphus + 2372 Qume Drive, #F + San Jose CA 95131 + US + +00-04-F4 (hex) Infinite Electronics Inc. +0004F4 (base 16) Infinite Electronics Inc. + No.478-1, Sec 2 + + TW + +00-04-F1 (hex) WhereNet +0004F1 (base 16) WhereNet + 107 W. McKinney Avenue + Rogersville TN 37857 + US + +00-05-21 (hex) Control Microsystems +000521 (base 16) Control Microsystems + 48 Steacie Drive + Ottawa Ontario K2K 2A9 + CA + +00-05-23 (hex) AVL List GmbH +000523 (base 16) AVL List GmbH + Hans List Platz 1 + Graz 8020 + AT + +00-05-1F (hex) Taijin Media Co., Ltd. +00051F (base 16) Taijin Media Co., Ltd. + 640-8 Tungchon-Dong + Seoul 157-030 + KR + +00-05-0C (hex) Network Photonics, Inc. +00050C (base 16) Network Photonics, Inc. + 451 Aviation Boulevard + Santa Rosa CA 95403 + US + +00-04-EC (hex) Memobox SA +0004EC (base 16) Memobox SA + 1, Place Dame Suzanne + + FR + +00-04-E4 (hex) Daeryung Ind., Inc. +0004E4 (base 16) Daeryung Ind., Inc. + #219-6, Kasan Dong, + Seoul Seoul KOREA + KR + +00-05-0A (hex) ICS Spa +00050A (base 16) ICS Spa + Via Romano AL + + IT + +00-05-11 (hex) Complementary Technologies Ltd +000511 (base 16) Complementary Technologies Ltd + Comtech House, 28 Manchester Road + BL5 3QJ + GB + +00-05-06 (hex) Reddo Networks AB +000506 (base 16) Reddo Networks AB + Livdjursgatan 4 + + SE + +00-04-E2 (hex) SMC Networks, Inc. +0004E2 (base 16) SMC Networks, Inc. + 6 Hughes + Irvine CA 92618 + US + +00-04-CB (hex) Tdsoft Communication, Ltd. +0004CB (base 16) Tdsoft Communication, Ltd. + 60 Medinat Hayehudim St. + + IL + +00-05-26 (hex) IPAS GmbH +000526 (base 16) IPAS GmbH + Hölscherstr. 27 + + DE + +00-04-67 (hex) Wuhan Research Institute of MII +000467 (base 16) Wuhan Research Institute of MII + 88 Youkeyuan Road, + 430074 430074 P.R.CHINA + CN + +00-04-5A (hex) The Linksys Group, Inc. +00045A (base 16) The Linksys Group, Inc. + 17401 Armstrong Ave. + Irvine CA 92614 + US + +00-04-63 (hex) Bosch Security Systems +000463 (base 16) Bosch Security Systems + 850 Greenfield Road + Lancaster PA 17601-5874 + US + +00-04-5C (hex) Mobiwave Pte Ltd +00045C (base 16) Mobiwave Pte Ltd + Blk 16, Kallang Place + 339156 + SG + +00-04-53 (hex) YottaYotta, Inc. +000453 (base 16) YottaYotta, Inc. + 6020- 104 Street + Edmonton, AB T6H 5S4 + CA + +00-04-50 (hex) DMD Computers SRL +000450 (base 16) DMD Computers SRL + Via Monviso, 14 + + IT + +00-04-43 (hex) Agilent Technologies, Inc. +000443 (base 16) Agilent Technologies, Inc. + 5301 Stevens Creek Boulevard + Santa Clara CA 95051 + US + +00-04-49 (hex) Mapletree Networks +000449 (base 16) Mapletree Networks + 315 Norwood Park South + Norwood MA 02062 + US + +00-04-2F (hex) International Communications Products, Inc. +00042F (base 16) International Communications Products, Inc. + 4325 Woodland Park Drive + West Melbourne FL 32904 + US + +00-04-29 (hex) Pixord Corporation +000429 (base 16) Pixord Corporation + 6F, No. 12, Innovation 1st Rd., + TAIWAN TAIWAN R.O.C. + TW + +00-04-26 (hex) Autosys +000426 (base 16) Autosys + 202 Ilsinpastel, + Seoul Seoul KOREA + KR + +00-04-B8 (hex) Kumahira Co., Ltd. +0004B8 (base 16) Kumahira Co., Ltd. + 4-34 Ujinahigashi 2-Chome + JAPAN 734-8567 + JP + +00-04-B5 (hex) Equitrac Corporation +0004B5 (base 16) Equitrac Corporation + 1905 N.W. 82nd Avenue + Miami FL 33126 + US + +00-04-B1 (hex) Signal Technology, Inc. +0004B1 (base 16) Signal Technology, Inc. + 3rd. Fl. Dabo Bldg. + Seoul KOREA 138-110 + KR + +00-04-51 (hex) Medrad, Inc. +000451 (base 16) Medrad, Inc. + One Medrad Drive + Indianola PA 15051 + US + +00-04-83 (hex) Deltron Technology, Inc. +000483 (base 16) Deltron Technology, Inc. + 8F-3, No. 125, Lane 235 + Taipei TAIWAN, R.O.C. + TW + +00-04-41 (hex) Half Dome Systems, Inc. +000441 (base 16) Half Dome Systems, Inc. + 155 B-1 Moffet Park Drive + Sunnyvale CA 94089 + US + +00-04-A5 (hex) Barco Projection Systems NV +0004A5 (base 16) Barco Projection Systems NV + Noordlaan 5 + + BE + +00-04-82 (hex) Medialogic Corp. +000482 (base 16) Medialogic Corp. + 0-3, Toyamaken-Sangyou + + JP + +00-03-CA (hex) MTS Systems Corp. +0003CA (base 16) MTS Systems Corp. + 3001 Sheldon Drive + Cary, NC 27513 + US + +00-03-C7 (hex) hopf Elektronik GmbH +0003C7 (base 16) hopf Elektronik GmbH + Nottebohmstraße 41 + 58511 Lüdenscheid + DE + +00-03-C2 (hex) Solphone K.K. +0003C2 (base 16) Solphone K.K. + 2-11-1 Kandatsukasa-cho + 101-0048 + JP + +00-03-F3 (hex) Dazzle Multimedia, Inc. +0003F3 (base 16) Dazzle Multimedia, Inc. + 47211 Bayside Parkway + Fremont CA 94538 + US + +00-03-EC (hex) ICG Research, Inc. +0003EC (base 16) ICG Research, Inc. + 775 B The Queens Way + M8Z 1N1 + CA + +00-03-E9 (hex) Akara Canada, Inc. +0003E9 (base 16) Akara Canada, Inc. + 150 Katimavik Road + CANADA K2L 2N2 + CA + +00-03-E5 (hex) Hermstedt SG +0003E5 (base 16) Hermstedt SG + Carl-Reuther - Str. 3 + + DE + +00-03-E8 (hex) Wavelength Digital Limited +0003E8 (base 16) Wavelength Digital Limited + 12 Vincent Avenue + MK8 0AB MK8 0AB ENGLAND + GB + +00-04-21 (hex) Ocular Networks +000421 (base 16) Ocular Networks + 12700, Fair Lakes Circle + Fairfax VA 22033 + US + +00-04-24 (hex) TMC s.r.l. +000424 (base 16) TMC s.r.l. + 202 Via A. Costa + + IT + +00-04-1D (hex) Corega of America +00041D (base 16) Corega of America + P.O. Box 159 + Bothell WA 98041-0159 + US + +00-04-1A (hex) Ines Test and Measurement GmbH & CoKG +00041A (base 16) Ines Test and Measurement GmbH & CoKG + An der Mühlenaue 5 + Bad Nenndorf 31542 + DE + +00-04-1E (hex) Shikoku Instrumentation Co., Ltd. +00041E (base 16) Shikoku Instrumentation Co., Ltd. + 777, Oosachou, Zentsuujishi, + + JP + +00-04-13 (hex) snom technology GmbH +000413 (base 16) snom technology GmbH + Wittestr 30 G + Berlin 13509 + DE + +00-03-B4 (hex) Macrotek International Corp. +0003B4 (base 16) Macrotek International Corp. + 2F, No. 28, Lane 46 + Taipei Taipei TAIWAN + TW + +00-03-A6 (hex) Traxit Technology, Inc. +0003A6 (base 16) Traxit Technology, Inc. + 256 Great Road, + Littleton MA 01461 + US + +00-03-A4 (hex) Imation Corp. +0003A4 (base 16) Imation Corp. + 1 Imation Place + Oakdale MN 55128-3414 + US + +00-03-AB (hex) Bridge Information Systems +0003AB (base 16) Bridge Information Systems + 717 Office Parkway + St. Louis MO 63141 + US + +00-04-03 (hex) Nexsi Corporation +000403 (base 16) Nexsi Corporation + 1959 Concourse Drive + San Jose CA 95131 + US + +00-04-06 (hex) Fa. Metabox AG +000406 (base 16) Fa. Metabox AG + Daimlerring 37, + + DE + +00-03-F8 (hex) SanCastle Technologies, Inc. +0003F8 (base 16) SanCastle Technologies, Inc. + 2107 North First Street + San Jose CA 95131 + US + +00-03-FA (hex) TiMetra Networks +0003FA (base 16) TiMetra Networks + 500 Ellis St. + Mountain View CA 94043 + US + +00-03-C6 (hex) ICUE Systems, Inc. +0003C6 (base 16) ICUE Systems, Inc. + 17489 Gale Avenue + City of Industry CA 91748 + US + +00-03-BB (hex) Signal Communications Limited +0003BB (base 16) Signal Communications Limited + Unit 217, 2/F, HKITC, + HONG KONG + HK + +00-03-BE (hex) Netility +0003BE (base 16) Netility + 298 South Sunnyvale Ave. + Sunnyvale CA 94086 + US + +00-03-DF (hex) Desana Systems +0003DF (base 16) Desana Systems + 1805 McCandless Ave. + Milpitas CA 95035 + US + +00-03-DA (hex) Takamisawa Cybernetics Co., Ltd. +0003DA (base 16) Takamisawa Cybernetics Co., Ltd. + Nakano Heiwa Bldg. + + JP + +00-03-D9 (hex) Secheron SA +0003D9 (base 16) Secheron SA + Untermattweg 8 + + CH + +00-03-FB (hex) ENEGATE Co.,Ltd. +0003FB (base 16) ENEGATE Co.,Ltd. + 3-14-40 Senrioka, + Settsu-city Osaka 566-8686 + JP + +00-03-F6 (hex) Allegro Networks, Inc. +0003F6 (base 16) Allegro Networks, Inc. + 6399 San Ignacio Avenue + San Jose CA 95119 + US + +00-04-15 (hex) Rasteme Systems Co., Ltd. +000415 (base 16) Rasteme Systems Co., Ltd. + 886-2 Nihongi Nakagou-mura + + JP + +00-03-98 (hex) WISI +000398 (base 16) WISI + Wilhelm-Sihn-Str. 5-7 + D-75223 Niefern-Oeschelbronn + DE + +00-03-95 (hex) California Amplifier +000395 (base 16) California Amplifier + 460 Calle San Pablo + Camarillo CA 93012 + US + +00-03-92 (hex) Hyundai Teletek Co., Ltd. +000392 (base 16) Hyundai Teletek Co., Ltd. + B-501, Techno Park, 148 Yatap-dong, + KOREA Republic + KR + +00-03-8E (hex) Atoga Systems, Inc. +00038E (base 16) Atoga Systems, Inc. + 49026 Milmont Drive + Fremont CA 94538 + US + +00-03-1A (hex) Beijing Broad Telecom Ltd., China +00031A (base 16) Beijing Broad Telecom Ltd., China + P.O. Box #147 + Beijing 100876 + CN + +00-03-5B (hex) BridgeWave Communications +00035B (base 16) BridgeWave Communications + 3350 Thomad Road + Santa Clara CA 95054 + US + +00-03-57 (hex) Intervoice-Brite, Inc. +000357 (base 16) Intervoice-Brite, Inc. + 17811 Waterview Pkwy. + Dallas TX 75252 + US + +00-03-7F (hex) Atheros Communications, Inc. +00037F (base 16) Atheros Communications, Inc. + 5480 Great America Parkway + Santa Clara CA 95054 + US + +00-02-F0 (hex) AME Optimedia Technology Co., Ltd. +0002F0 (base 16) AME Optimedia Technology Co., Ltd. + 17F-2, 79 Hsin Tai Wu Road, Sec. 1, + + TW + +00-03-9E (hex) Tera System Co., Ltd. +00039E (base 16) Tera System Co., Ltd. + Doosung B/F Rm 302 + Republic of Korea + KR + +00-03-97 (hex) FireBrick Limited +000397 (base 16) FireBrick Limited + C/O Andrews & Arnold Ltd, + Enterprise Court, Downmill Road Bracknell, Berks RG12 1QS + GB + +00-03-3F (hex) BigBand Networks, Ltd. +00033F (base 16) BigBand Networks, Ltd. + 3 Azrieli Towers + + IL + +00-03-27 (hex) ACT'L +000327 (base 16) ACT'L + Avenue de Artisanat 10A + + BE + +00-03-2E (hex) Scope Information Management, Ltd. +00032E (base 16) Scope Information Management, Ltd. + 2F Chanwoo b/o 736 Youksang-dong, + Seoul 135-080 + KR + +00-03-7C (hex) Coax Media +00037C (base 16) Coax Media + 1220 Oak Industrial Lane + Cumming GA 30041 + US + +00-03-68 (hex) Embedone Co., Ltd. +000368 (base 16) Embedone Co., Ltd. + Fl. 9 Annex Samhwan B/D. 17-26 + Seoul 150-01 + KR + +00-03-45 (hex) Routrek Networks Corporation +000345 (base 16) Routrek Networks Corporation + Nilssei Shin Mizonokuchi Bldg. 1F + 23-0011 + JP + +00-02-C8 (hex) Technocom Communications Technology (pte) Ltd +0002C8 (base 16) Technocom Communications Technology (pte) Ltd + 189 Kaki Buckit Avenue 1 + Singapore 416029 + SG + +00-02-B8 (hex) WHI KONSULT AB +0002B8 (base 16) WHI KONSULT AB + Scheelegatan 11 + Stockholm SE-112 28 + SE + +00-02-A9 (hex) RACOM, s.r.o. +0002A9 (base 16) RACOM, s.r.o. + Mirova 1283, Nove Mesto na Morave + 592 31 Czech republic + CZ + +00-02-BB (hex) Continuous Computing Corp +0002BB (base 16) Continuous Computing Corp + 9380 Carroll Park Drive + San Diego CA 92121 + US + +00-02-BC (hex) LVL 7 Systems, Inc. +0002BC (base 16) LVL 7 Systems, Inc. + 13000 Weston Pkwy + Cary NC 27513 + US + +00-03-0F (hex) Digital China (Shanghai) Networks Ltd. +00030F (base 16) Digital China (Shanghai) Networks Ltd. + 602-23, Haitai Building, 351 Guo Shoujin + Shanghai + CN + +00-03-11 (hex) Micro Technology Co., Ltd. +000311 (base 16) Micro Technology Co., Ltd. + Suehiro Bldg. + 101-0021 + JP + +00-03-0D (hex) Uniwill Computer Corp. +00030D (base 16) Uniwill Computer Corp. + No. 24, Pei Yuan Rd., Chung + Li City + TW + +00-03-09 (hex) Texcel Technology PLC +000309 (base 16) Texcel Technology PLC + Thames Road + ENGLAND + GB + +00-03-03 (hex) JAMA Electronics Co., Ltd. +000303 (base 16) JAMA Electronics Co., Ltd. + 10F, No. 222-1, Sec. 3 + Taipei Hsien + TW + +00-03-05 (hex) MSC Vertriebs GmbH +000305 (base 16) MSC Vertriebs GmbH + Design Center Aachen + AACHEN D-52076 + DE + +00-02-FE (hex) Viditec, Inc. +0002FE (base 16) Viditec, Inc. + 520 Central Parkway E. + Plano TX 75074 + US + +00-01-9F (hex) ReadyNet +00019F (base 16) ReadyNet + 6952 High Tech Drive + Midvale UT 84047 + US + +00-02-FF (hex) Handan BroadInfoCom +0002FF (base 16) Handan BroadInfoCom + 5th Fl. Shinsung Plaza #697-11 + Seoul + KR + +00-02-F4 (hex) PCTEL, Inc. +0002F4 (base 16) PCTEL, Inc. + 1331 California Circle + Milpitas CA 95035 + US + +00-02-E9 (hex) CS Systemes De Securite - C3S +0002E9 (base 16) CS Systemes De Securite - C3S + 23, rue de Schwobsheim + + FR + +00-02-E5 (hex) Timeware Ltd. +0002E5 (base 16) Timeware Ltd. + Brookfield Grange + Lancs 042 GLB + GB + +00-02-E0 (hex) ETAS GmbH +0002E0 (base 16) ETAS GmbH + Borsigstraße 10 + + DE + +00-02-CE (hex) FoxJet, Inc. +0002CE (base 16) FoxJet, Inc. + 2016 E. Randal Mill Rd. #409 + Arlington TX 76011-8223 + US + +00-02-C3 (hex) Arelnet Ltd. +0002C3 (base 16) Arelnet Ltd. + 3 Hayarden St. + + IL + +00-03-16 (hex) Nobell Communications, Inc. +000316 (base 16) Nobell Communications, Inc. + 3410 Far West Blvd., Suite 240 + Austin TX 78731 + US + +00-03-29 (hex) F3, Inc. +000329 (base 16) F3, Inc. + 2F, No. 7, Industry E. Rd. 9, + Hsinchu + TW + +00-03-21 (hex) Reco Research Co., Ltd. +000321 (base 16) Reco Research Co., Ltd. + No. 47-1, Sec. 2, + + TW + +00-02-F5 (hex) VIVE Synergies, Inc. +0002F5 (base 16) VIVE Synergies, Inc. + 30 West Beaver Creek Road, Unit 101 + L4B 3K1 + CA + +00-02-D5 (hex) ACR +0002D5 (base 16) ACR + Cardoulines B2 + + FR + +00-02-AB (hex) CTC Union Technologies Co., Ltd. +0002AB (base 16) CTC Union Technologies Co., Ltd. + 8F No. 60 Zhouzi St. + Neihu Taipei 114 + TW + +00-02-A4 (hex) AddPac Technology Co., Ltd. +0002A4 (base 16) AddPac Technology Co., Ltd. + 3F Jeoung Am Bldg., 769-12 + Seoul Seoul Korea + KR + +00-02-A3 (hex) ABB Switzerland Ltd, Power Systems +0002A3 (base 16) ABB Switzerland Ltd, Power Systems + Bruggerstrasse 72 + Baden + CH + +00-02-A0 (hex) Flatstack Ltd. +0002A0 (base 16) Flatstack Ltd. + 1112 Budapest + + HU + +00-02-B2 (hex) Cablevision +0002B2 (base 16) Cablevision + 420 Crossways Park Drive West + Woodbury NY 11787 + US + +00-02-B7 (hex) Watanabe Electric Industry Co., Ltd. +0002B7 (base 16) Watanabe Electric Industry Co., Ltd. + 6-16-19, Jingumae, Shibuya-ku + + JP + +00-02-AF (hex) TeleCruz Technology, Inc. +0002AF (base 16) TeleCruz Technology, Inc. + 2391 Qume Dr. + San Jose CA 95131 + US + +00-02-A8 (hex) Air Link Technology +0002A8 (base 16) Air Link Technology + Bethel Bldg. 303 + Seoul KOREA 137-130 + KR + +00-02-6A (hex) Cocess Telecom Co., Ltd. +00026A (base 16) Cocess Telecom Co., Ltd. + Research & Development Dept. + Seoul Seoul KOREA + KR + +00-02-6C (hex) Philips CFT +00026C (base 16) Philips CFT + Building SAN 6 + The + NL + +00-02-62 (hex) Soyo Group Soyo Com Tech Co., Ltd +000262 (base 16) Soyo Group Soyo Com Tech Co., Ltd + 5H. No. 21 Wu-gong 5 Rd, + Taipei Hsien Taiwan R.O.C. + TW + +00-02-65 (hex) Virditech Co. Ltd. +000265 (base 16) Virditech Co. Ltd. + Hyundai Topics Blgd., 11th Fl + Seoul Seoul KOREA + KR + +00-02-5B (hex) Cambridge Silicon Radio +00025B (base 16) Cambridge Silicon Radio + Unit 400, Science Park, + United Kingdom + GB + +00-02-56 (hex) Alpha Processor, Inc. +000256 (base 16) Alpha Processor, Inc. + 130 C Baker Ave. Ext. + Concord MA 01742 + US + +00-02-59 (hex) Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group +000259 (base 16) Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group + 8F, #99, Huaihai Rd, East, + CHINA 200021 + CN + +00-02-94 (hex) Tokyo Sokushin Co., Ltd. +000294 (base 16) Tokyo Sokushin Co., Ltd. + 5-16-12 Nishi-Nippori + + JP + +00-02-96 (hex) Lectron Co,. Ltd. +000296 (base 16) Lectron Co,. Ltd. + 9F, No.171, Sec. 2, Tatung Rd., + Taiwan Taiwan R.O.C. + TW + +00-02-8E (hex) Rapid 5 Networks, Inc. +00028E (base 16) Rapid 5 Networks, Inc. + 180 Baytech Drive + San Jose CA 95134-2302 + US + +00-02-4F (hex) IPM Datacom S.R.L. +00024F (base 16) IPM Datacom S.R.L. + Via Roma, 231 + Naples + IT + +00-02-71 (hex) Zhone Technologies +000271 (base 16) Zhone Technologies + 7001 Oakport Street + Oakland CA 94621 + US + +00-02-8A (hex) Ambit Microsystems Corporation +00028A (base 16) Ambit Microsystems Corporation + 5F-1, 5 Hsin-An Road Hsinchu, + TAIWAN + TW + +00-01-FA (hex) HOROSCAS +0001FA (base 16) HOROSCAS + 26, LOUIS BLANC + + FR + +00-02-82 (hex) ViaClix, Inc. +000282 (base 16) ViaClix, Inc. + 1400 Dell Ave., Suite B + Campbell CA 95008 + US + +00-02-85 (hex) Riverstone Networks +000285 (base 16) Riverstone Networks + 5200 Great America Parkway + Santa Clara CA 95054 + US + +00-02-79 (hex) Control Applications, Ltd. +000279 (base 16) Control Applications, Ltd. + 3 Tevuot Haarets St. + + IL + +00-02-51 (hex) Soma Networks, Inc. +000251 (base 16) Soma Networks, Inc. + 650 Townsend St. + San Francisco CA 94103 + US + +00-01-F5 (hex) ERIM S.A. +0001F5 (base 16) ERIM S.A. + 11 Av Republique + + FR + +00-01-FF (hex) Data Direct Networks, Inc. +0001FF (base 16) Data Direct Networks, Inc. + 9320 Lurline Avenue + Chatsworth CA 91311 + US + +00-01-FC (hex) Keyence Corporation +0001FC (base 16) Keyence Corporation + 1-3-14, Higashi-Nakajima, + + JP + +00-01-FD (hex) Digital Voice Systems, Inc. +0001FD (base 16) Digital Voice Systems, Inc. + 234 Littleton Road + Westford MA 01886 + US + +00-02-10 (hex) Fenecom +000210 (base 16) Fenecom + 7/F Kon-kuk University Alumni + Seoul Seoul Korea + KR + +00-02-0B (hex) Native Networks, Inc. +00020B (base 16) Native Networks, Inc. + P.O. Box 7165 + + IL + +00-02-18 (hex) Advanced Scientific Corp +000218 (base 16) Advanced Scientific Corp + 1 Fl., No. 26, Industry East 9th Road + TAIWAN + TW + +00-01-EE (hex) Comtrol Europe, Ltd. +0001EE (base 16) Comtrol Europe, Ltd. + The Courtyard Studio + U.K. + GB + +00-01-F0 (hex) Tridium, Inc. +0001F0 (base 16) Tridium, Inc. + 3951 Westerre Parkway + Richmond VA 23233 + US + +00-01-F1 (hex) Innovative Concepts, Inc. +0001F1 (base 16) Innovative Concepts, Inc. + 8200 Greensboro Drive + McLean VA 22102 + US + +00-01-E2 (hex) Ando Electric Corporation +0001E2 (base 16) Ando Electric Corporation + 19-7, Kamata 4-Chrome, Ota-ku + + JP + +00-02-2F (hex) P-Cube, Ltd. +00022F (base 16) P-Cube, Ltd. + P.O. Box 12331 + + IL + +00-02-27 (hex) ESD Electronic System Design GmbH +000227 (base 16) ESD Electronic System Design GmbH + Vahrenwalder Str. 207 + 30 165 Hannover + DE + +00-02-1D (hex) Data General Communication Ltd. +00021D (base 16) Data General Communication Ltd. + Rm. 18C, Bldg. C, CEIEC Tower + + CN + +00-02-19 (hex) Paralon Technologies +000219 (base 16) Paralon Technologies + 700 Fifth Ave, Suite 6101 + Seattle WA 98104 + US + +00-02-03 (hex) Woonsang Telecom, Inc. +000203 (base 16) Woonsang Telecom, Inc. + 104-9, Munji-Dong, Yusong-Gu + KOREA + KR + +00-01-D3 (hex) PAXCOMM, Inc. +0001D3 (base 16) PAXCOMM, Inc. + 7th F The Corp. Center + KOREA + KR + +00-01-E1 (hex) Kinpo Electronics, Inc. +0001E1 (base 16) Kinpo Electronics, Inc. + No.147, Sec. 3, Beishen Rd + Shenkeng Dist. New Taipei City 222 + TW + +00-02-2C (hex) ABB Bomem, Inc. +00022C (base 16) ABB Bomem, Inc. + 585, boul. Charest Est + Canada G1K 9H4 + CA + +00-02-3C (hex) Creative Technology, Ltd. +00023C (base 16) Creative Technology, Ltd. + 31 International Business Park + Republic of + SG + +00-30-6C (hex) Hitex Holding GmbH +00306C (base 16) Hitex Holding GmbH + Greschbachstraße 12 + 76229 Karlsruhe + DE + +00-30-8B (hex) Brix Networks +00308B (base 16) Brix Networks + 300 Concord Road + Billerica MA 01821 + US + +00-01-77 (hex) EDSL +000177 (base 16) EDSL + Habarzel 1 st + ISRAEL 69710 + IL + +00-01-4D (hex) Shin Kin Enterprises Co., Ltd +00014D (base 16) Shin Kin Enterprises Co., Ltd + 7, FU Hsing St. Tue Cheng Ind. + TAIWAN TAIWAN R.O.C. + TW + +00-01-DA (hex) WINCOMM Corporation +0001DA (base 16) WINCOMM Corporation + 2F, No. 3, Prosperity Road 1, + Hsinchu Taiwan + TW + +00-01-D2 (hex) inXtron, Inc. +0001D2 (base 16) inXtron, Inc. + 8F, No.52, MinQuan Road, Xindian Dist. + New Taipei City 23141 + TW + +00-01-C6 (hex) Quarry Technologies +0001C6 (base 16) Quarry Technologies + 8 New England Executive Park + Burlington MA 01803 + US + +00-01-6E (hex) Conklin Corporation +00016E (base 16) Conklin Corporation + 6141 Crooked Creek Road + Norcross GA 30092-3193 + US + +00-01-74 (hex) CyberOptics Corporation +000174 (base 16) CyberOptics Corporation + 5900 Golden Hills Drive + Golden Valley MN 55416 + US + +00-01-5E (hex) BEST TECHNOLOGY CO., LTD. +00015E (base 16) BEST TECHNOLOGY CO., LTD. + 7F, Haesung B/D + KOREA + KR + +00-01-61 (hex) Meta Machine Technology +000161 (base 16) Meta Machine Technology + 400 Silver Cedar Court - ste. #220 + Chapel Hill NC 27514 + US + +00-01-A1 (hex) Mag-Tek, Inc. +0001A1 (base 16) Mag-Tek, Inc. + 1710 Apollo Court + Seal Beach CA 90740 + US + +00-01-86 (hex) Uwe Disch +000186 (base 16) Uwe Disch + Eichenhainstraße 14 + + DE + +00-01-A6 (hex) Scientific-Atlanta Arcodan A/S +0001A6 (base 16) Scientific-Atlanta Arcodan A/S + Avgustenborg Landevej 7 + + DK + +00-01-72 (hex) TechnoLand Co., LTD. +000172 (base 16) TechnoLand Co., LTD. + 3-17-11 Akebono-cho + + JP + +00-01-A0 (hex) Infinilink Corporation +0001A0 (base 16) Infinilink Corporation + 1740 E. Garry Ave. - Ste. #206 + Santa Ana CA 92705 + US + +00-01-96 (hex) Cisco Systems, Inc +000196 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-01-99 (hex) HeiSei Electronics +000199 (base 16) HeiSei Electronics + 5/7 Alley 8, Lane 45 + TAIWAN + TW + +00-01-8B (hex) NetLinks Co., Ltd. +00018B (base 16) NetLinks Co., Ltd. + 3F Dscom Bldg., 238-3 + KOREA + KR + +00-01-8D (hex) AudeSi Technologies +00018D (base 16) AudeSi Technologies + Suite 180, 6815 + AB + CA + +00-01-9D (hex) E-Control Systems, Inc. +00019D (base 16) E-Control Systems, Inc. + 9420 Lurline Ave., Unite + Chatsworth CA 91311 + US + +00-01-CE (hex) Custom Micro Products, Ltd. +0001CE (base 16) Custom Micro Products, Ltd. + 450 Blandford Road + UNITED KINGDOM + GB + +00-01-BB (hex) Frequentis +0001BB (base 16) Frequentis + SPITTELBREITENGASSE 34 + + AT + +00-01-BC (hex) Brains Corporation +0001BC (base 16) Brains Corporation + 2-27-8-4Fl TAMAGAWA + + JP + +00-01-C0 (hex) CompuLab, Ltd. +0001C0 (base 16) CompuLab, Ltd. + P.O. Box 66 + + IL + +00-01-7C (hex) AG-E GmbH +00017C (base 16) AG-E GmbH + Dennewartstraße 27 + + DE + +00-01-08 (hex) AVLAB Technology, Inc. +000108 (base 16) AVLAB Technology, Inc. + 3F-1, No. 134, Sec. 3 + Hsin Tien, Taipei + TW + +00-06-2B (hex) INTRASERVER TECHNOLOGY +00062B (base 16) INTRASERVER TECHNOLOGY + SEVEN OCTOBER HILL RD. + HOLLISTON MA 01746 + US + +00-01-00 (hex) EQUIP'TRANS +000100 (base 16) EQUIP'TRANS + 31 rue Paul Cezanne + LA ROCHETTE 77000 + FR + +00-B0-9D (hex) Point Grey Research Inc. +00B09D (base 16) Point Grey Research Inc. + 305-1847 West Broadway + Vancouver British Columbia V6J 1Y6 + CA + +00-01-10 (hex) Gotham Networks +000110 (base 16) Gotham Networks + 15 Discovery Way + Acton MA 01720 + US + +00-01-12 (hex) Shark Multimedia Inc. +000112 (base 16) Shark Multimedia Inc. + 48890 Milmont Drive #101-D + Fremont CA 94538 + US + +00-01-16 (hex) Netspect Technologies, Inc. +000116 (base 16) Netspect Technologies, Inc. + 3945 Freedom Circle - Ste. #360 + Santa Clara CA 95054 + US + +00-B0-6D (hex) Jones Futurex Inc. +00B06D (base 16) Jones Futurex Inc. + 3715 Atherton Road + Rocklin CA 95765 + US + +00-B0-94 (hex) Alaris, Inc. +00B094 (base 16) Alaris, Inc. + 47338 Fremont Boulevard + Fremont CA 94538 + US + +00-30-F0 (hex) Uniform Industrial Corp. +0030F0 (base 16) Uniform Industrial Corp. + 18F, 171, Shung Teh Road + Taipei + TW + +00-01-3B (hex) BNA SYSTEMS +00013B (base 16) BNA SYSTEMS + 1637 S. Main Street + Milpitas CA 95035 + US + +00-01-34 (hex) Selectron Systems AG +000134 (base 16) Selectron Systems AG + Bernstreasse 70 + + CH + +00-01-39 (hex) Point Multimedia Systems +000139 (base 16) Point Multimedia Systems + 4Ra 507, Shihwa Industrial Complex + Korea 425-110 + KR + +00-01-3E (hex) Ascom Tateco AB +00013E (base 16) Ascom Tateco AB + Box 8783 + + SE + +00-01-2E (hex) PC Partner Ltd. +00012E (base 16) PC Partner Ltd. + Rm 1901-1908, 19/F, Shatin Galleria + + CN + +00-01-32 (hex) Dranetz - BMI +000132 (base 16) Dranetz - BMI + 1000 New Durham Road + Edison NJ 08818 + US + +00-01-13 (hex) OLYMPUS CORPORATION +000113 (base 16) OLYMPUS CORPORATION + 2-3 Kuboyama-cho, Hachioji-shi + Tokyo 192-8512 j + JP + +00-01-1E (hex) Precidia Technologies, Inc. +00011E (base 16) Precidia Technologies, Inc. + 10A Hearst Way + Kanata Ontario K2M-2C4 + CA + +00-01-55 (hex) Promise Technology, Inc. +000155 (base 16) Promise Technology, Inc. + 4F, 1, Prosperity 1st Road + TAIWAN + TW + +00-30-94 (hex) Cisco Systems, Inc +003094 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-8A (hex) NICOTRA SISTEMI S.P.A +00308A (base 16) NICOTRA SISTEMI S.P.A + 41 Via Primo Maggio + Baranzate (MI) 20021 + IT + +00-30-72 (hex) Intellibyte Inc. +003072 (base 16) Intellibyte Inc. + Canada Trust Tower - BCE Place + Toronto Ontario M5J 2S1 + CA + +00-30-40 (hex) Cisco Systems, Inc +003040 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-32 (hex) MagicRam, Inc. +003032 (base 16) MagicRam, Inc. + 1850 Beverly Blvd. + Los Angeles CA 90057 + US + +00-30-EA (hex) TeraForce Technology Corporation +0030EA (base 16) TeraForce Technology Corporation + 1100 EXECUTIVE DRIVE + RICHARDSON TX 75081 + US + +00-30-9B (hex) Smartware +00309B (base 16) Smartware + 49 AV Aristide + 92160 Antony + FR + +00-30-45 (hex) Village Networks, Inc. (VNI) +003045 (base 16) Village Networks, Inc. (VNI) + 100 Village Court - Ste. #301 + Hazlet NJ 07730 + US + +00-30-E5 (hex) Amper Datos S.A. +0030E5 (base 16) Amper Datos S.A. + C/Marconi n*3 (PTM) + 28760 Madrid + ES + +00-30-06 (hex) SUPERPOWER COMPUTER +003006 (base 16) SUPERPOWER COMPUTER + ELECTRONICS CO., LTD. + Taipei 248 + TW + +00-30-38 (hex) XCP, INC. +003038 (base 16) XCP, INC. + 40 ELM STREET + DRYDEN NY 13053 + US + +00-30-79 (hex) CQOS, INC. +003079 (base 16) CQOS, INC. + 25 MAUCHLY - STE. #329 + IRVINE CA 92618 + US + +00-30-0C (hex) CONGRUENCY, LTD. +00300C (base 16) CONGRUENCY, LTD. + 23 HASIVIM STREET + PETAH-TIKVA 49170 + IL + +00-30-4C (hex) APPIAN COMMUNICATIONS, INC. +00304C (base 16) APPIAN COMMUNICATIONS, INC. + 80 CENTRAL STREET + BOXBOROUGH MA 01719 + US + +00-30-E8 (hex) ENSIM CORP. +0030E8 (base 16) ENSIM CORP. + 1215 Terra Bella Ave. + Mountainview CA 94043 + US + +00-30-C9 (hex) LuxN, N +0030C9 (base 16) LuxN, N + 570 Maude Court + Sunnyvale CA 94086 + US + +00-30-28 (hex) FASE Saldatura srl +003028 (base 16) FASE Saldatura srl + V.R. Bernardi 5 + TORINO + IT + +00-30-69 (hex) IMPACCT TECHNOLOGY CORP. +003069 (base 16) IMPACCT TECHNOLOGY CORP. + 2F, NO. 12, R&D RD. II + TAIWAN TAIWAN R.O.C. + TW + +00-30-C3 (hex) FLUECKIGER ELEKTRONIK AG +0030C3 (base 16) FLUECKIGER ELEKTRONIK AG + KIRCHBARGSTRASSE 201 + + CH + +00-30-5A (hex) TELGEN CORPORATION +00305A (base 16) TELGEN CORPORATION + 3101 SOVEREIGN DR. - STE. + LANSING MI 48911 + US + +00-30-10 (hex) VISIONETICS INTERNATIONAL +003010 (base 16) VISIONETICS INTERNATIONAL + 3F, NO. 3, PROSPERITY ROAD 1 + TAIWAN R.O.C. + TW + +00-30-D9 (hex) DATACORE SOFTWARE CORP. +0030D9 (base 16) DATACORE SOFTWARE CORP. + CORPORATE PARK + FORT LAUDERDALE FL 33309 + US + +00-30-26 (hex) HeiTel Digital Video GmbH +003026 (base 16) HeiTel Digital Video GmbH + Stuthagen 25 + + DE + +00-30-77 (hex) ONPREM NETWORKS +003077 (base 16) ONPREM NETWORKS + 42501 ALBRAE STREET + FREMONT CA 94538 + US + +00-30-47 (hex) NISSEI ELECTRIC CO., LTD. +003047 (base 16) NISSEI ELECTRIC CO., LTD. + 32 MIYAWAKE, SHIMONOISHIKI-CHO + + JP + +00-30-D4 (hex) AAE Systems, Inc. +0030D4 (base 16) AAE Systems, Inc. + 642 North Pastoria Avenue + Sunnyvale CA 94085 + US + +00-D0-D7 (hex) B2C2, INC. +00D0D7 (base 16) B2C2, INC. + 2020 CHALLENGER DRIVE- + ALAMEDA CA 94501 + US + +00-D0-73 (hex) ACN ADVANCED COMMUNICATIONS +00D073 (base 16) ACN ADVANCED COMMUNICATIONS + NETWORKS SA + + CH + +00-D0-57 (hex) ULTRAK, INC. +00D057 (base 16) ULTRAK, INC. + 1301 WATERS RIDGE DRIVE + LEWISVILLE TX 75057 + US + +00-30-AB (hex) DELTA NETWORKS, INC. +0030AB (base 16) DELTA NETWORKS, INC. + 8, KON JAN WEST ROAD + TAIWAN TAIWAN R.O.C. + TW + +00-30-49 (hex) BRYANT TECHNOLOGY, LTD. +003049 (base 16) BRYANT TECHNOLOGY, LTD. + P.O. BOX 69557 + SOUTH AFRICA + ZA + +00-30-6D (hex) LUCENT TECHNOLOGIES +00306D (base 16) LUCENT TECHNOLOGIES + 300 BAKER AVENUE - STE. #100 + CONCORD MA 01742-2168 + US + +00-30-17 (hex) BlueArc UK Ltd +003017 (base 16) BlueArc UK Ltd + Queensgate House + Bracknell RG12 1RB + GB + +00-30-1C (hex) ALTVATER AIRDATA SYSTEMS +00301C (base 16) ALTVATER AIRDATA SYSTEMS + GMBH & CO. KG + + DE + +00-30-80 (hex) Cisco Systems, Inc +003080 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-F7 (hex) RAMIX INC. +0030F7 (base 16) RAMIX INC. + 1672 DONLON STREET + VENTURA CA 93003 + US + +00-30-D0 (hex) Tellabs +0030D0 (base 16) Tellabs + 1750 Founder's Parkway + Alpharetta GA 30004 + US + +00-30-14 (hex) DIVIO, INC. +003014 (base 16) DIVIO, INC. + 997 E. ARQUES AVENUE + SUNNYVALE CA 94086 + US + +00-30-81 (hex) ALTOS C&C +003081 (base 16) ALTOS C&C + 150-010 RM. 1012, 44-1 + KOREA + KR + +00-D0-F0 (hex) CONVISION TECHNOLOGY GMBH +00D0F0 (base 16) CONVISION TECHNOLOGY GMBH + REBENRING 33 + + DE + +00-D0-10 (hex) CONVERGENT NETWORKS, INC. +00D010 (base 16) CONVERGENT NETWORKS, INC. + 2 HIGHWOOD DRIVE + TEWKSBURY MA 01876 + US + +00-D0-4B (hex) LA CIE GROUP S.A. +00D04B (base 16) LA CIE GROUP S.A. + 17 RUE AMPERE + + FR + +00-D0-0E (hex) PLURIS, INC. +00D00E (base 16) PLURIS, INC. + 10455 BANDLEY DRIVE + CUPERTINO CA 95014 + US + +00-D0-12 (hex) GATEWORKS CORP. +00D012 (base 16) GATEWORKS CORP. + 7631 MORRO ROAD + ATASCADERO CA 93422 + US + +00-D0-4D (hex) DIV OF RESEARCH & STATISTICS +00D04D (base 16) DIV OF RESEARCH & STATISTICS + BOG OF THE FEDERAL RESERVE SYS + WASHINGTON DC 20551 + US + +00-D0-2E (hex) COMMUNICATION AUTOMATION CORP. +00D02E (base 16) COMMUNICATION AUTOMATION CORP. + 1180 MCDERMOTT DRIVE + WEST CHESTER PA 19380 + US + +00-D0-C5 (hex) COMPUTATIONAL SYSTEMS, INC. +00D0C5 (base 16) COMPUTATIONAL SYSTEMS, INC. + 835 INNOVATION DRIVE + KNOXVILLE TN 37932 + US + +00-D0-46 (hex) DOLBY LABORATORIES, INC. +00D046 (base 16) DOLBY LABORATORIES, INC. + 100 Potrero Avenue + San Francisco CA 94103-4938 + US + +00-D0-DE (hex) PHILIPS MULTIMEDIA NETWORK +00D0DE (base 16) PHILIPS MULTIMEDIA NETWORK + SYSTEMS GMBH + + DE + +00-D0-0C (hex) SNIJDER MICRO SYSTEMS +00D00C (base 16) SNIJDER MICRO SYSTEMS + P.O. BOX 300 + THE + NL + +00-D0-17 (hex) SYNTECH INFORMATION CO., LTD. +00D017 (base 16) SYNTECH INFORMATION CO., LTD. + 8F, 210, TA-TUNG RD., SEC. 3 + TAIWAN TAIWAN ROC + TW + +00-D0-36 (hex) TECHNOLOGY ATLANTA CORP. +00D036 (base 16) TECHNOLOGY ATLANTA CORP. + 141 W. WIEUCA RD. N.E. + ATLANTA GA 30342 + US + +00-D0-E3 (hex) ELE-CHEM ENGINEERING CO., LTD. +00D0E3 (base 16) ELE-CHEM ENGINEERING CO., LTD. + WINDSTONE OFFICE + SEOUL 137-130 SEOUL 137-130 KOREA + KR + +00-D0-B6 (hex) CRESCENT NETWORKS, INC. +00D0B6 (base 16) CRESCENT NETWORKS, INC. + 201 RIVERNECK ROAD + CHELMSFORD MA 01842 + US + +00-D0-C4 (hex) TERATECH CORPORATION +00D0C4 (base 16) TERATECH CORPORATION + 223 MIDDLESEX TRPK. + BURLINGTON MA 01803-3308 + US + +00-D0-61 (hex) TREMON ENTERPRISES CO., LTD. +00D061 (base 16) TREMON ENTERPRISES CO., LTD. + 15F, NO. 116, SEC. 1 + TAIWAN TAIWAN ROC + TW + +00-D0-E5 (hex) SOLIDUM SYSTEMS CORP. +00D0E5 (base 16) SOLIDUM SYSTEMS CORP. + 940 BELFAST ROAD 1S.217 + + CA + +00-D0-45 (hex) KVASER AB +00D045 (base 16) KVASER AB + BOX 4076 + + SE + +00-D0-04 (hex) PENTACOM LTD. +00D004 (base 16) PENTACOM LTD. + 8 HASADNAOT STREET + + IL + +00-D0-05 (hex) ZHS ZEITMANAGEMENTSYSTEME +00D005 (base 16) ZHS ZEITMANAGEMENTSYSTEME + HARD-UND SOFTWARE GMBH + + DE + +00-D0-D3 (hex) Cisco Systems, Inc +00D0D3 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-26 (hex) HIRSCHMANN AUSTRIA GMBH +00D026 (base 16) HIRSCHMANN AUSTRIA GMBH + OBERER PASPELSWEG 6 - 8 + + AT + +00-D0-DA (hex) TAICOM DATA SYSTEMS CO., LTD. +00D0DA (base 16) TAICOM DATA SYSTEMS CO., LTD. + 45, WU-KUNG 5 ROAD + TAIWAN + TW + +00-D0-3C (hex) Vieo, Inc. +00D03C (base 16) Vieo, Inc. + 12416 Hymeadow Drive, + Austin TX 78750 + US + +00-D0-B4 (hex) KATSUJIMA CO., LTD. +00D0B4 (base 16) KATSUJIMA CO., LTD. + 1-6-1, SHIRATORI + + JP + +00-D0-86 (hex) FOVEON, INC. +00D086 (base 16) FOVEON, INC. + 2820 San Tomas Expressway + Santa Clara CA 95051 + US + +00-D0-A8 (hex) NETWORK ENGINES, INC. +00D0A8 (base 16) NETWORK ENGINES, INC. + 61 PLEASANT STREET + RANDOLPH MA 02368 + US + +00-D0-AB (hex) DELTAKABEL TELECOM CV +00D0AB (base 16) DELTAKABEL TELECOM CV + HANZEWEG 14 + THE + NL + +00-D0-E8 (hex) MAC SYSTEM CO., LTD. +00D0E8 (base 16) MAC SYSTEM CO., LTD. + R&D INSTITUTE + KYUNGKI-DO KOREA, 430-017 + KR + +00-D0-6B (hex) SR TELECOM INC. +00D06B (base 16) SR TELECOM INC. + 8150 Trans Canada Highway + Quebec H4S 1M5 + CA + +00-D0-DC (hex) MODULAR MINING SYSTEMS, INC. +00D0DC (base 16) MODULAR MINING SYSTEMS, INC. + 3289 E. HEMISPHERE LOOP + TUCSON AZ 85706 + US + +00-D0-1E (hex) PINGTEL CORP. +00D01E (base 16) PINGTEL CORP. + 773 WINTER STREET + N. ANDOVER MA 01845 + US + +00-D0-CA (hex) Intrinsyc Software International Inc. +00D0CA (base 16) Intrinsyc Software International Inc. + 885 Dunsmuir Street, Suite 380 + Vancouver B.C. V6C 1N5 + CA + +00-D0-65 (hex) TOKO ELECTRIC +00D065 (base 16) TOKO ELECTRIC + 4008 KUROHAMA, HASUDA-SHI + + JP + +00-D0-9A (hex) FILANET CORPORATION +00D09A (base 16) FILANET CORPORATION + 931 Benecia Avenue + Sunnyvale CA 94085 + US + +00-D0-AE (hex) ORESIS COMMUNICATIONS, INC. +00D0AE (base 16) ORESIS COMMUNICATIONS, INC. + 14670 NW GREENBRIER PKWY + BEAVERTON OR 97006 + US + +00-D0-F2 (hex) MONTEREY NETWORKS +00D0F2 (base 16) MONTEREY NETWORKS + 1909 N. GLENVILLE DRIVE + RICHARDSON TX 75081 + US + +00-D0-14 (hex) ROOT, INC. +00D014 (base 16) ROOT, INC. + 8F TOC2 Bldg, 7-21-11 Nishi-Gotanda + Tokyo 141-0031 + JP + +00-D0-23 (hex) INFORTREND TECHNOLOGY, INC. +00D023 (base 16) INFORTREND TECHNOLOGY, INC. + 10F, NO. 33 SAN-MIN RD. + TAIWAN + TW + +00-D0-A2 (hex) INTEGRATED DEVICE +00D0A2 (base 16) INTEGRATED DEVICE + TECHNOLOGY, INC. + SANTA CLARA CA 95054 + US + +00-D0-34 (hex) ORMEC SYSTEMS CORP. +00D034 (base 16) ORMEC SYSTEMS CORP. + 19 LINDEN PARK + ROCHESTER NY 14625 + US + +00-D0-8A (hex) PHOTRON USA +00D08A (base 16) PHOTRON USA + 1101 S. WINCHESTER BLVD. + SAN JOSE CA 95128 + US + +00-D0-A7 (hex) TOKYO SOKKI KENKYUJO CO., LTD. +00D0A7 (base 16) TOKYO SOKKI KENKYUJO CO., LTD. + 8-2, MINAMI-OHI 6-CHOME + JAPAN 140-8560 + JP + +00-D0-1D (hex) FURUNO ELECTRIC CO., LTD. +00D01D (base 16) FURUNO ELECTRIC CO., LTD. + NO. 9-52, ASHIHARA-CHO + 662-8580 + JP + +00-50-4C (hex) Galil Motion Control +00504C (base 16) Galil Motion Control + 270 Technology Way + Rocklin CA 95765 + US + +00-50-76 (hex) IBM Corp +005076 (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-50-D4 (hex) JOOHONG INFORMATION & +0050D4 (base 16) JOOHONG INFORMATION & + COMMUNICATIONS, LTD. + SEOUL SEOUL KOREA + KR + +00-50-A6 (hex) OPTRONICS +0050A6 (base 16) OPTRONICS + 175 CREMONA DRIVE + GOLETA CA 93117 + US + +00-50-A9 (hex) MOLDAT WIRELESS TECHNOLGIES +0050A9 (base 16) MOLDAT WIRELESS TECHNOLGIES + 3 SHIMON ISRAELI STREET + + IL + +00-50-9B (hex) SWITCHCORE AB +00509B (base 16) SWITCHCORE AB + POSITIONEN 153 + + SE + +00-50-7E (hex) NEWER TECHNOLOGY +00507E (base 16) NEWER TECHNOLOGY + 4848 WEST IRVING ST. + WICHITA KS 67209-2621 + US + +00-50-CE (hex) LG INTERNATIONAL CORP. +0050CE (base 16) LG INTERNATIONAL CORP. + LG TWIN TOWERS + SEOUL, 150-606 + KR + +00-50-F7 (hex) VENTURE MANUFACTURING (SINGAPORE) LTD. +0050F7 (base 16) VENTURE MANUFACTURING (SINGAPORE) LTD. + + #05-01 Techplace II 569873 + SG + +00-50-19 (hex) SPRING TIDE NETWORKS, INC. +005019 (base 16) SPRING TIDE NETWORKS, INC. + 85 SWANSON ROAD + BOXBOROUGH MA 01719 + US + +00-50-FD (hex) VISIONCOMM CO., LTD. +0050FD (base 16) VISIONCOMM CO., LTD. + 4, 5F, DAEWON B/D + YONGSAN-GU, SEOUL + KR + +00-50-BF (hex) Metalligence Technology Corp. +0050BF (base 16) Metalligence Technology Corp. + NO.9, PARK AVENUE II + HSIN-CHU + TW + +00-50-36 (hex) NETCAM, LTD. +005036 (base 16) NETCAM, LTD. + 6071 N. PASEO ZALDIVAR + TUCSON AZ 85750 + US + +00-50-DB (hex) CONTEMPORARY CONTROL +0050DB (base 16) CONTEMPORARY CONTROL + SYSTEMS, INC. + DOWNERS GROVE IL 60515 + US + +00-50-7C (hex) VIDEOCON AG +00507C (base 16) VIDEOCON AG + ALBERT-SCHWEITZER-STR. 64 + + DE + +00-50-47 (hex) Private +005047 (base 16) Private + +00-D0-6C (hex) SHAREWAVE, INC. +00D06C (base 16) SHAREWAVE, INC. + 5175 HILLSDALE CIRCLE + EL DORADO HILLS CA 95762 + US + +00-50-A7 (hex) Cisco Systems, Inc +0050A7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-50-55 (hex) DOMS A/S +005055 (base 16) DOMS A/S + FORMERVANGEN 28 + + DK + +00-50-72 (hex) CORVIS CORPORATION +005072 (base 16) CORVIS CORPORATION + 8320 GUILFORD ROAD + COLUMBIA MD 21046 + US + +00-D0-EE (hex) DICTAPHONE CORPORATION +00D0EE (base 16) DICTAPHONE CORPORATION + 3191 BROADBRIDGE AVE. + STRATFORD CT 06614-2559 + US + +00-50-1B (hex) ABL CANADA, INC. +00501B (base 16) ABL CANADA, INC. + 8550 COTE DE LIESSE + ST-LAURENT (QUEBEC) H4T 1H2 + CA + +00-90-57 (hex) AANetcom, Inc. +009057 (base 16) AANetcom, Inc. + 4949 LIBERTY LANE - STE. #200 + ALLENTOWN PA 18106-9015 + US + +00-90-83 (hex) TURBO COMMUNICATION, INC. +009083 (base 16) TURBO COMMUNICATION, INC. + 4F-2, NO. 171, SUNG-TEH ROAD + TAIPEI + TW + +00-90-3D (hex) BIOPAC SYSTEMS, INC. +00903D (base 16) BIOPAC SYSTEMS, INC. + 42 AERO CAMINO + SANTA BARBARA CA 93117 + US + +00-90-D7 (hex) NetBoost Corp. +0090D7 (base 16) NetBoost Corp. + 390 CAMBRIDGE AVENUE + PALO ALTO CA 94306-1506 + US + +00-50-83 (hex) GILBARCO, INC. +005083 (base 16) GILBARCO, INC. + POB 22087 + GREENSBORO NC 27420 + US + +00-50-DC (hex) TAS TELEFONBAU A. SCHWABE GMBH & CO. KG +0050DC (base 16) TAS TELEFONBAU A. SCHWABE GMBH & CO. KG + + D-41238 MONCHENGLADBACH + DE + +00-50-08 (hex) TIVA MICROCOMPUTER CORP. (TMC) +005008 (base 16) TIVA MICROCOMPUTER CORP. (TMC) + 48550 FREMONT BLVD. + FREMONT CA 94538 + US + +00-50-52 (hex) TIARA NETWORKS, INC. +005052 (base 16) TIARA NETWORKS, INC. + 113 FOORIER AVENUE + FREMONT CA 94539 + US + +00-50-27 (hex) GENICOM CORPORATION +005027 (base 16) GENICOM CORPORATION + 900 CLOPPER ROAD - STE. #110 + GAITHERSBURG MD 20878 + US + +00-50-5A (hex) NETWORK ALCHEMY, INC. +00505A (base 16) NETWORK ALCHEMY, INC. + 1521.5 PACIFIC AVENUE + SANTA CRUZ CA 95060 + US + +00-50-39 (hex) MARINER NETWORKS +005039 (base 16) MARINER NETWORKS + 1585 S. MANCHESTER AVE. + ANAHEIM CA 92802-2907 + US + +00-50-64 (hex) CAE ELECTRONICS +005064 (base 16) CAE ELECTRONICS + P.O. BOX 1800 + ST. LAURENT, QUEBEC H4L 4X4 + CA + +00-50-B8 (hex) INOVA COMPUTERS GMBH & CO. KG +0050B8 (base 16) INOVA COMPUTERS GMBH & CO. KG + SUDETENSTRASSE 5 + 87600 KAUFBEUREN + DE + +00-50-5B (hex) KAWASAKI LSI U.S.A., INC. +00505B (base 16) KAWASAKI LSI U.S.A., INC. + 2570 NORTHFIRST STREET + SAN JOSE CA 95131 + US + +00-50-CC (hex) Seagate Cloud Systems Inc +0050CC (base 16) Seagate Cloud Systems Inc + 1351 S Sunset Street + Longmont CO 80501 + US + +00-50-16 (hex) Molex Canada Ltd +005016 (base 16) Molex Canada Ltd + 216 Bathurst Drive + Waterloo Ontario N2V 2L7 + CA + +00-50-1F (hex) MRG SYSTEMS, LTD. +00501F (base 16) MRG SYSTEMS, LTD. + WILLOW HOUSE, SLAD ROAD + GLOS. GL5 1QG England + GB + +00-50-43 (hex) MARVELL SEMICONDUCTOR, INC. +005043 (base 16) MARVELL SEMICONDUCTOR, INC. + 645 ALMANOR AVENUE + SUNNYVALE CA 94086 + US + +00-50-95 (hex) PERACOM NETWORKS +005095 (base 16) PERACOM NETWORKS + 13000 WESTON PARKWAY + CARY NC 27513 + US + +00-50-FA (hex) OXTEL, LTD. +0050FA (base 16) OXTEL, LTD. + THE MARKET PLACE + 0X11 7LE England + GB + +00-90-38 (hex) FOUNTAIN TECHNOLOGIES, INC. +009038 (base 16) FOUNTAIN TECHNOLOGIES, INC. + 50 RANDOLPH ROAD + SOMERSET NJ 08873 + US + +00-90-B0 (hex) VADEM +0090B0 (base 16) VADEM + 1960 ZANKER RD + SAN JOSE CA 95112 + US + +00-90-EF (hex) INTEGRIX, INC. +0090EF (base 16) INTEGRIX, INC. + 2001 CORPORATE CENTER DRIVE + NEWBURY PARK CA 91320 + US + +00-90-C5 (hex) INTERNET MAGIC, INC. +0090C5 (base 16) INTERNET MAGIC, INC. + 6450 LUSK BLVD.-STE. #E-201 + SAN DIEGO CA 92121 + US + +00-90-8C (hex) ETREND ELECTRONICS, INC. +00908C (base 16) ETREND ELECTRONICS, INC. + 2F, 22 INDUSTRY E. 9TH ROAD + + TW + +00-90-48 (hex) ZEAL CORPORATION +009048 (base 16) ZEAL CORPORATION + 301, HIRAIKE + NAGAKUTE-CHO, AICHI-PREF. 480-1155 + JP + +00-90-B9 (hex) BERAN INSTRUMENTS LTD. +0090B9 (base 16) BERAN INSTRUMENTS LTD. + HATCHMOOR INDUSTRIAL ESTATE + N DEVON EX38 7HP + GB + +00-90-C4 (hex) JAVELIN SYSTEMS, INC. +0090C4 (base 16) JAVELIN SYSTEMS, INC. + 1881 LANGLEY AVE. + IRVINE CA 92614 + US + +00-90-A5 (hex) SPECTRA LOGIC +0090A5 (base 16) SPECTRA LOGIC + 1700 N. 55TH STREET + BOULDER CO 80301 + US + +00-90-A3 (hex) Corecess Inc. +0090A3 (base 16) Corecess Inc. + 135-726, Keopyung B-Town 1F, 203, Nonhyu + Seoul + KR + +00-90-82 (hex) FORCE INSTITUTE +009082 (base 16) FORCE INSTITUTE + PARK ALLE 345 + DK-2605 BROENDBY + DK + +00-90-00 (hex) DIAMOND MULTIMEDIA +009000 (base 16) DIAMOND MULTIMEDIA + 312 SE STONEMILL DRIVE + VANCOUVER WA 98684 + US + +00-90-6E (hex) PRAXON, INC. +00906E (base 16) PRAXON, INC. + 1700 DELL AVENUE + CAMPBELL CA 95008 + US + +00-90-54 (hex) INNOVATIVE SEMICONDUCTORS, INC +009054 (base 16) INNOVATIVE SEMICONDUCTORS, INC + 2570 W. EL CAMINO REAL + MOUNTAIN VIEW CA 94040 + US + +00-90-61 (hex) PACIFIC RESEARCH & ENGINEERING CORPORATION +009061 (base 16) PACIFIC RESEARCH & ENGINEERING CORPORATION + 2070 LAS PALMAS DRIVE + CARLSBAD CA 92009 + US + +00-90-0B (hex) LANNER ELECTRONICS, INC. +00900B (base 16) LANNER ELECTRONICS, INC. + 8F-4, NO. 77, SEC. 1 + TAIPEI HSIEN + TW + +00-90-CE (hex) avateramedical Mechatronics GmbH +0090CE (base 16) avateramedical Mechatronics GmbH + Gewerbepark „Am Wald“ 4 + ILMENAU D-98693 + DE + +00-90-07 (hex) DOMEX TECHNOLOGY CORP. +009007 (base 16) DOMEX TECHNOLOGY CORP. + NO. 2, TECHNOLOGY RD. 1 + HSINCHU + TW + +00-90-2D (hex) DATA ELECTRONICS (AUST.) PTY, LTD. +00902D (base 16) DATA ELECTRONICS (AUST.) PTY, LTD. + 7 SEISMIC COURT + VICTORIA 3178 + AU + +00-90-D4 (hex) BindView Development Corp. +0090D4 (base 16) BindView Development Corp. + 3355 WEST ALABAMA #1200 + HOUSTON TX 77098 + US + +00-90-29 (hex) CRYPTO AG +009029 (base 16) CRYPTO AG + P.O. BOX + CH-6301 Zug + CH + +00-90-DF (hex) MITSUBISHI CHEMICAL AMERICA, INC. +0090DF (base 16) MITSUBISHI CHEMICAL AMERICA, INC. + 445 INDIO WAY + SUNNYVALE CA 94086 + US + +00-90-C0 (hex) K.J. LAW ENGINEERS, INC. +0090C0 (base 16) K.J. LAW ENGINEERS, INC. + 42300 W. NINE MILE ROAD + NOVI MI 48375 + US + +00-90-1F (hex) ADTEC PRODUCTIONS, INC. +00901F (base 16) ADTEC PRODUCTIONS, INC. + 408 RUSSELL STREET + NASHVILLE TN 37206 + US + +00-90-24 (hex) PIPELINKS, INC. +009024 (base 16) PIPELINKS, INC. + 2710 WALSH AVE., STE #300 + SANTA CLARA CA 95051 + US + +00-90-3A (hex) NIHON MEDIA TOOL INC. +00903A (base 16) NIHON MEDIA TOOL INC. + 1875 OYAMA-CHO + MIE 512-1102 + JP + +00-90-B2 (hex) AVICI SYSTEMS INC. +0090B2 (base 16) AVICI SYSTEMS INC. + 12 ELIZABETH DRIVE + CHELMSFORD MA 01824 + US + +00-90-B6 (hex) FIBEX SYSTEMS +0090B6 (base 16) FIBEX SYSTEMS + 5350 OLD REDWOOD HIGHWAY + PETALUMA CA 94954 + US + +00-90-63 (hex) COHERENT COMMUNICATIONS SYSTEMS CORPORATION +009063 (base 16) COHERENT COMMUNICATIONS SYSTEMS CORPORATION + 45085 UNIVERSITY DRIVE + ASHBURN VA 20147 + US + +00-90-62 (hex) ICP VORTEX COMPUTERSYSTEME GmbH +009062 (base 16) ICP VORTEX COMPUTERSYSTEME GmbH + FALTERSTRASSE 51-53 + D 74223 FLEIN + DE + +00-10-D3 (hex) GRIPS ELECTRONIC GMBH +0010D3 (base 16) GRIPS ELECTRONIC GMBH + NIESENBERGERGASSE 37 + A-8020 GRAZ + AT + +00-10-FB (hex) ZIDA TECHNOLOGIES LIMITED +0010FB (base 16) ZIDA TECHNOLOGIES LIMITED + 8/F BLOCK A GOODVIEW INDUSTRIAL BUILDIN + TUEN MUN NT + HK + +00-10-53 (hex) COMPUTER TECHNOLOGY CORP. +001053 (base 16) COMPUTER TECHNOLOGY CORP. + 50 W. TECHNECENTER DRIVE + MILFORD OH 45150 + US + +00-10-ED (hex) SUNDANCE TECHNOLOGY, INC. +0010ED (base 16) SUNDANCE TECHNOLOGY, INC. + 20111 STEVENS CREEK BLVD. + CUPERTINO CA 95014 + US + +00-10-6C (hex) EDNT GmbH +00106C (base 16) EDNT GmbH + Werner-von-Siemens-Str. 7 + 64625 Bensheim + DE + +00-10-E9 (hex) RAIDTEC LTD. +0010E9 (base 16) RAIDTEC LTD. + CASTLE ROAD + Little Island County Cork + IE + +00-10-03 (hex) IMATRON, INC. +001003 (base 16) IMATRON, INC. + 389 OYSTER POINT BLVD. + SO. SAN FRANCISCO CA 94080 + US + +00-10-71 (hex) ADVANET INC. +001071 (base 16) ADVANET INC. + 3-20-8 NODA + OKAYAMI 700 + JP + +00-90-15 (hex) CENTIGRAM COMMUNICATIONS CORP. +009015 (base 16) CENTIGRAM COMMUNICATIONS CORP. + 91 EAST TASMAN DRIVE + SAN JOSE CA 95134 + US + +00-90-95 (hex) UNIVERSAL AVIONICS +009095 (base 16) UNIVERSAL AVIONICS + 11351 WILLOWS ROAD NE + REDMOND WA 98052-2552 + US + +00-90-41 (hex) APPLIED DIGITAL ACCESS +009041 (base 16) APPLIED DIGITAL ACCESS + 9855 SCRANTON ROAD + SAN DIEGO CA 92121 + US + +00-90-5A (hex) DEARBORN GROUP, INC. +00905A (base 16) DEARBORN GROUP, INC. + 33604 West 8 Mile Rd + Farmington Hills MI 48335 + US + +00-90-11 (hex) WAVTrace, Inc. +009011 (base 16) WAVTrace, Inc. + 1555 132ND AVE. NE + BELLEVUE WA 98005 + US + +00-90-65 (hex) FINISAR CORPORATION +009065 (base 16) FINISAR CORPORATION + 1389 Moffett Park Dr + Sunnyvale CA 94089 + US + +00-90-23 (hex) ZILOG INC. +009023 (base 16) ZILOG INC. + 910 East Hamilton Ave. + Campbell CA 95008 + US + +00-90-F6 (hex) ESCALATE NETWORKS, INC. +0090F6 (base 16) ESCALATE NETWORKS, INC. + 6 HUGHES + IRVINE CA 92617 + US + +00-90-A8 (hex) NineTiles Networks, Ltd. +0090A8 (base 16) NineTiles Networks, Ltd. + 9 Station Road + Waterbeach Cambridge CB5 9HT + GB + +00-10-2A (hex) ZF MICROSYSTEMS, INC. +00102A (base 16) ZF MICROSYSTEMS, INC. + 1052 ELWELL COURT + PALO ALTO CA 94303-4307 + US + +00-10-E5 (hex) SOLECTRON TEXAS +0010E5 (base 16) SOLECTRON TEXAS + 12455 RESEARCH BLVD. M/S 2205 + AUSTIN TX 78759 + US + +00-10-9D (hex) CLARINET SYSTEMS, INC. +00109D (base 16) CLARINET SYSTEMS, INC. + 1415 KOLL CIRCLE #101 + SAN JOSE CA 95112 + US + +00-10-0E (hex) MICRO LINEAR COPORATION +00100E (base 16) MICRO LINEAR COPORATION + 2092 CONCOURSE DRIVE + SAN JOSE CA 95131 + US + +00-90-EC (hex) PYRESCOM +0090EC (base 16) PYRESCOM + 3 ALLEE DU MOULIN + 66680 CANOHES + FR + +00-90-C3 (hex) TOPIC SEMICONDUCTOR CORP. +0090C3 (base 16) TOPIC SEMICONDUCTOR CORP. + 11F-1, NO. 2, WU-LIN RD. + HSIN-CHU + TW + +00-10-C8 (hex) COMMUNICATIONS ELECTRONICS SECURITY GROUP +0010C8 (base 16) COMMUNICATIONS ELECTRONICS SECURITY GROUP + 10/4W22 FIDDLERS GREEN LANE + Benhall, Cheltenham Glouster GL52 5AJ + GB + +00-10-F3 (hex) Nexcom International Co., Ltd. +0010F3 (base 16) Nexcom International Co., Ltd. + 18F, No. 716, Chung-Cheng Road, + Taipei Hsien 235, + TW + +00-10-86 (hex) ATTO Technology, Inc. +001086 (base 16) ATTO Technology, Inc. + 155 Crosspoint Pkwy. + Amherst NY 14068 + US + +00-10-DF (hex) RISE COMPUTER INC. +0010DF (base 16) RISE COMPUTER INC. + 9F, NO. 306-3, TATUNG RD. + TAIPEI HSIEN + TW + +00-10-72 (hex) GVN TECHNOLOGIES, INC. +001072 (base 16) GVN TECHNOLOGIES, INC. + 8200 BRYAN DAIRY ROAD + LARGO FL 33777 + US + +00-10-DA (hex) Kollmorgen Corp +0010DA (base 16) Kollmorgen Corp + 33 S.LA PATERA LN + SANTA BARBARA CA 93117 + US + +00-10-E4 (hex) NSI CORPORATION +0010E4 (base 16) NSI CORPORATION + P.O. BOX 635 + WILSONVILLE OR 97070 + US + +00-10-7E (hex) BACHMANN ELECTRONIC GmbH +00107E (base 16) BACHMANN ELECTRONIC GmbH + KREUZAECKERWEG 33 + A 6806 FELDKIRCH + AT + +00-10-A0 (hex) INNOVEX TECHNOLOGIES, INC. +0010A0 (base 16) INNOVEX TECHNOLOGIES, INC. + KEYSTONE COMMONS + TURTLE CREEK PA 15145 + US + +00-10-16 (hex) T.SQWARE +001016 (base 16) T.SQWARE + 6, PARC ARIANE + 78284 GUYANCOURT CEDEX + FR + +00-10-90 (hex) CIMETRICS, INC. +001090 (base 16) CIMETRICS, INC. + 55 TEMPLE PLACE + BOSTON MA 02111 + US + +00-10-F5 (hex) AMHERST SYSTEMS, INC. +0010F5 (base 16) AMHERST SYSTEMS, INC. + 30 WILSON ROAD + BUFFALO NY 14221 + US + +00-10-3D (hex) PHASECOM, LTD. +00103D (base 16) PHASECOM, LTD. + P.O. BOX 45017 + JERUSALEM 91450 + IL + +00-10-96 (hex) TRACEWELL SYSTEMS, INC. +001096 (base 16) TRACEWELL SYSTEMS, INC. + 567 ENTERPRISE DRIVE + WESTERVILLE OH 43081 + US + +00-10-82 (hex) JNA TELECOMMUNICATIONS LIMITED +001082 (base 16) JNA TELECOMMUNICATIONS LIMITED + 16 SMITH ST, CHATSWOOD + NSW 2067 + AU + +00-10-98 (hex) STARNET TECHNOLOGIES, INC. +001098 (base 16) STARNET TECHNOLOGIES, INC. + 2210 O'TOOLE AVE. + SAN JOSE CA 95131 + US + +00-10-42 (hex) Alacritech, Inc. +001042 (base 16) Alacritech, Inc. + 1995 N. First Street + San Jose CA 95112 + US + +00-10-68 (hex) COMOS TELECOM +001068 (base 16) COMOS TELECOM + SAEHAN B/D/, 27-1 SUPYO-DONG + CHUNG-GU, SEOUL (100-230) + KR + +00-10-EA (hex) ADEPT TECHNOLOGY +0010EA (base 16) ADEPT TECHNOLOGY + 150 ROSE ORCHARD WAY + SAN JOSE CA 95134 + US + +00-10-AE (hex) SHINKO ELECTRIC INDUSTRIES CO. +0010AE (base 16) SHINKO ELECTRIC INDUSTRIES CO. + 80 OSHIMADA-MACHI + NAGANO-SHI 381-22 + JP + +00-10-C4 (hex) MEDIA GLOBAL LINKS CO., LTD. +0010C4 (base 16) MEDIA GLOBAL LINKS CO., LTD. + 580-16, horikawa-cho,saiwai-ku + Kawasaki, Kanagawa 212-0013 + JP + +00-10-FE (hex) DIGITAL EQUIPMENT CORPORATION +0010FE (base 16) DIGITAL EQUIPMENT CORPORATION + 301 ROCKRIMMON BLVD, SOUTH + COLORADO SPRINGS CO 80919 + US + +00-10-56 (hex) SODICK CO., LTD. +001056 (base 16) SODICK CO., LTD. + 3-12-1 NAKAMACHIDAI + TSUZUKI-KU, YOKOHAMA KANAGAWA 224 + JP + +00-10-CD (hex) INTERFACE CONCEPT +0010CD (base 16) INTERFACE CONCEPT + 3 VENELLE de KERGOS + 29000 QUIMPER + FR + +00-10-61 (hex) HOSTLINK CORP. +001061 (base 16) HOSTLINK CORP. + 10F-1, NO. 181 + HSI-CHIH, TAIPEI + TW + +00-10-99 (hex) InnoMedia, Inc. +001099 (base 16) InnoMedia, Inc. + 4800 GREAT AMERICA PARKWAY + SANTA CLARA CA 95054 + US + +00-10-E1 (hex) S.I. TECH, INC. +0010E1 (base 16) S.I. TECH, INC. + P.O. BOX 609 + GENEVA IL 60134 + US + +00-10-BB (hex) DATA & INFORMATION TECHNOLOGY +0010BB (base 16) DATA & INFORMATION TECHNOLOGY + TECHNOLOGY HOUSE + BOTTESFORD, NOTTINGHAM NG13 OEL + GB + +00-10-20 (hex) Hand Held Products Inc +001020 (base 16) Hand Held Products Inc + 700 Visions Drive + Skaneateles Falls NY 13153-0208 + US + +00-10-3A (hex) DIAMOND NETWORK TECH +00103A (base 16) DIAMOND NETWORK TECH + P.O. BOX 84525 + GREENSIDE 2034 + ZA + +00-10-04 (hex) THE BRANTLEY COILE COMPANY,INC +001004 (base 16) THE BRANTLEY COILE COMPANY,INC + 545 RESEARCH DRIVE + ATHENS GA 30605 + US + +00-10-EF (hex) DBTEL INCORPORATED +0010EF (base 16) DBTEL INCORPORATED + NO.29 TZU-CHIANG ST., + TU-CHENG TAIPEI + TW + +00-10-88 (hex) AMERICAN NETWORKS INC. +001088 (base 16) AMERICAN NETWORKS INC. + 6800 ORANGETHORPE AVE. #A + BUENA PARK CA 90620 + US + +00-10-22 (hex) SatCom Media Corporation +001022 (base 16) SatCom Media Corporation + 3255-7 SCOTT BLVD. + SANTA CLARA CA 95054 + US + +00-10-76 (hex) EUREM GmbH +001076 (base 16) EUREM GmbH + JULICHER STR. 338B + D-52070 AACHEN + DE + +00-10-3F (hex) TOLLGRADE COMMUNICATIONS, INC. +00103F (base 16) TOLLGRADE COMMUNICATIONS, INC. + 493 NIXON ROAD + CHESWICK PA 15024 + US + +00-10-49 (hex) ShoreTel, Inc +001049 (base 16) ShoreTel, Inc + 960 Stewart Drive + Sunnyvale CA 94085 + US + +00-10-5E (hex) Spirent plc, Service Assurance Broadband +00105E (base 16) Spirent plc, Service Assurance Broadband + 5280 Corporate Dr + Ballenger Creek MD 21703 + US + +00-10-AF (hex) TAC SYSTEMS, INC. +0010AF (base 16) TAC SYSTEMS, INC. + 1035 PUTMAN DRIVE--STE. + HUNTSVILLE AL 35816-2271 + US + +00-10-8C (hex) Fujitsu Services Ltd +00108C (base 16) Fujitsu Services Ltd + SOLIHULL PARKWAY + BIRMINGHAM B37 7YU England 0000 + GB + +00-10-F7 (hex) IRIICHI TECHNOLOGIES Inc. +0010F7 (base 16) IRIICHI TECHNOLOGIES Inc. + 1-26-7 CHUO, NAKANA-KU + TOKYO 164 + JP + +00-10-AB (hex) KOITO ELECTRIC INDUSTRIES, LTD. +0010AB (base 16) KOITO ELECTRIC INDUSTRIES, LTD. + 100 MAEDA-CHO, TOTSUKA-KU + YOKOHAMA 244 KANAGAWA 244-8569 + JP + +00-10-10 (hex) INITIO CORPORATION +001010 (base 16) INITIO CORPORATION + 2188 B DEL FRANCO STREET + SAN JOSE CA 95118 + US + +00-10-F2 (hex) ANTEC +0010F2 (base 16) ANTEC + 4920 AVALON RIDGE PKWY + NORCROSS GA 30071 + US + +00-E0-07 (hex) Avaya ECS Ltd +00E007 (base 16) Avaya ECS Ltd + Unit 1 Sterling Court, Mundells + Welwyn Garden City Hert AL7 1LZ + GB + +00-10-BE (hex) MARCH NETWORKS CORPORATION +0010BE (base 16) MARCH NETWORKS CORPORATION + 303 Terry Fox Drive + OTTAWA, ONTARIO K2K 3J1 + CA + +00-10-58 (hex) ArrowPoint Communications +001058 (base 16) ArrowPoint Communications + 235 LITTLETON ROAD + WESTFORD MA 01886 + US + +00-10-0F (hex) INDUSTRIAL CPU SYSTEMS +00100F (base 16) INDUSTRIAL CPU SYSTEMS + 111-D W. DYER ROAD + SANTA ANA CA 92707 + US + +00-10-BC (hex) Aastra Telecom +0010BC (base 16) Aastra Telecom + 8 Federal Street + Billerica MA 01821-3570 + US + +00-E0-BF (hex) TORRENT NETWORKING TECHNOLOGIES CORP. +00E0BF (base 16) TORRENT NETWORKING TECHNOLOGIES CORP. + 8181 PROFESSIONAL PLACE + LANDOVER MD 20785 + US + +00-E0-E3 (hex) SK-ELEKTRONIK GMBH +00E0E3 (base 16) SK-ELEKTRONIK GMBH + HEMMELRATHERWEG 201 + 51377 LEVERKUSEN + DE + +00-E0-C6 (hex) LINK2IT, L.L.C. +00E0C6 (base 16) LINK2IT, L.L.C. + 4256 BECK AVENUE + STUDIO CITY CA 91604 + US + +00-E0-E5 (hex) CINCO NETWORKS, INC. +00E0E5 (base 16) CINCO NETWORKS, INC. + 6601 KOLL CENTER PARK WAY + PLEASANTON CA 94566 + US + +00-E0-61 (hex) EdgePoint Networks, Inc. +00E061 (base 16) EdgePoint Networks, Inc. + 2238 MARTIN AVENUE + SANTA CLARA CA 95050 + US + +00-E0-53 (hex) CELLPORT LABS, INC. +00E053 (base 16) CELLPORT LABS, INC. + 885 ARAPAHOE AVE., + BOULDER CO 80302 + US + +00-E0-D3 (hex) DATENTECHNIK GmbH +00E0D3 (base 16) DATENTECHNIK GmbH + THERESIANUMGASSE 11 + A-1040 WIEN + AT + +00-E0-43 (hex) VitalCom +00E043 (base 16) VitalCom + 15222 DEL AMO AVE. + TUSTIN CA 92780 + US + +00-E0-B3 (hex) EtherWAN Systems, Inc. +00E0B3 (base 16) EtherWAN Systems, Inc. + 14 HUGHES, STE.B-105 + IRVINE CA 92618 + US + +00-E0-ED (hex) SILICOM, LTD. +00E0ED (base 16) SILICOM, LTD. + 8 HANAGER ST. + KFAR-SAVA 44000 + IL + +00-E0-B8 (hex) GATEWAY 2000 +00E0B8 (base 16) GATEWAY 2000 + 610 GATEWAY DRIVE + N. SIOUX CITY SD 57049 + US + +00-E0-7C (hex) METTLER-TOLEDO, INC. +00E07C (base 16) METTLER-TOLEDO, INC. + 1150 DEARBORN DRIVE + WORTHINGTON OH 43085 + US + +00-E0-26 (hex) Redlake MASD LLC +00E026 (base 16) Redlake MASD LLC + 3440 E. Pritannia Dr. + Tuscon AZ 85706 + US + +00-E0-20 (hex) TECNOMEN OY +00E020 (base 16) TECNOMEN OY + P.O. BOX 93 + FIN-02271 ESPOO + FI + +00-E0-0D (hex) RADIANT SYSTEMS +00E00D (base 16) RADIANT SYSTEMS + 1000 ALDERMAN DR. + ALPHARETTA GA 30202 + US + +00-E0-DC (hex) NEXWARE CORP. +00E0DC (base 16) NEXWARE CORP. + 825 STEWART DR., STE #4 + SUNNYVALE CA 94086 + US + +00-E0-37 (hex) CENTURY CORPORATION +00E037 (base 16) CENTURY CORPORATION + 2-28-5, Taito + TAITO-KU, TOKYO 101 + JP + +00-E0-C2 (hex) NECSY S.p.A. +00E0C2 (base 16) NECSY S.p.A. + VIA LISBONA 28 + 35020 PADOVA + IT + +00-E0-FB (hex) LEIGHTRONIX, INC. +00E0FB (base 16) LEIGHTRONIX, INC. + 2330 JARCO DR. + HOLT MI 48842 + US + +00-E0-9B (hex) ENGAGE NETWORKS, INC. +00E09B (base 16) ENGAGE NETWORKS, INC. + 316 N. MILWAUKEE ST., STE.#214 + MILWAUKEE WI 53202 + US + +00-E0-45 (hex) TOUCHWAVE, INC. +00E045 (base 16) TOUCHWAVE, INC. + Maglebjergvej 5B + DK-2800 Lyngby + DK + +00-E0-40 (hex) DeskStation Technology, Inc. +00E040 (base 16) DeskStation Technology, Inc. + 15729 COLLEGE BLVD. + LENEXA KS 66219 + US + +00-E0-1A (hex) COMTEC SYSTEMS. CO., LTD. +00E01A (base 16) COMTEC SYSTEMS. CO., LTD. + 404-9 CHOUNGCHEN-DONG + BUPYOUNG-KU, INCHON + KR + +00-E0-78 (hex) BERKELEY NETWORKS +00E078 (base 16) BERKELEY NETWORKS + 683 RIVER OAKS PARKWAY + SAN JOSE CA 95134 + US + +00-E0-87 (hex) LeCroy - Networking Productions Division +00E087 (base 16) LeCroy - Networking Productions Division + 25 BURLINGTON MALL ROAD + BURLINGTON MA 01803 + US + +00-E0-41 (hex) CSPI +00E041 (base 16) CSPI + 43 Manning Rd. + Billerica MA 01821 + US + +00-E0-E2 (hex) INNOVA CORP. +00E0E2 (base 16) INNOVA CORP. + 3325 SOUTH 116TH STREET + SEATTLE WA 98168 + US + +00-E0-81 (hex) TYAN COMPUTER CORP. +00E081 (base 16) TYAN COMPUTER CORP. + 3288 LAUREVIEW CT + Fremont CA 95035 + US + +00-E0-57 (hex) HAN MICROTELECOM. CO., LTD. +00E057 (base 16) HAN MICROTELECOM. CO., LTD. + FASHION BD., 3RD FR, + DONG SEO-GU, TAEJON KOREA 302-173 + KR + +00-E0-BC (hex) SYMON COMMUNICATIONS, INC. +00E0BC (base 16) SYMON COMMUNICATIONS, INC. + 10701 CORPORATE DR.-STE. #290 + STAFFORD TX 77477 + US + +00-E0-82 (hex) ANERMA +00E082 (base 16) ANERMA + SCHAAPSDRIES 25 + 2260 WESTERLO + BE + +00-E0-77 (hex) WEBGEAR, INC. +00E077 (base 16) WEBGEAR, INC. + 1263 OAKMEAD PKWY + SUNNYVALE CA 94080 + US + +00-E0-56 (hex) HOLONTECH CORPORATION +00E056 (base 16) HOLONTECH CORPORATION + 2039 SAMARITAN DRIVE + SAN JOSE CA 95124 + US + +00-E0-31 (hex) HAGIWARA ELECTRIC CO., LTD. +00E031 (base 16) HAGIWARA ELECTRIC CO., LTD. + 7, SHIMOKOFUKADA, ASADA-CHO + NISSHIN-SHI, AICHI 470-01 + JP + +00-E0-0B (hex) ROOFTOP COMMUNICATIONS CORP. +00E00B (base 16) ROOFTOP COMMUNICATIONS CORP. + 468 PACO DRIVE + LOS ALTOS CA 94024 + US + +00-E0-B2 (hex) TELMAX COMMUNICATIONS CORP. +00E0B2 (base 16) TELMAX COMMUNICATIONS CORP. + 46515 LANDING PARKWAY + FREMONT CA 94538 + US + +00-E0-2F (hex) MCNS HOLDINGS, L.P. +00E02F (base 16) MCNS HOLDINGS, L.P. + TCI, INC.-TECHNOLOGY VENTURES + DENVER CO 80217-5630 + US + +00-E0-7E (hex) WALT DISNEY IMAGINEERING +00E07E (base 16) WALT DISNEY IMAGINEERING + 1401 FLOWER ST. + GLENDALE CA 91221 + US + +00-E0-99 (hex) SAMSON AG +00E099 (base 16) SAMSON AG + WEISMULLERSTR. 3 + D-60314 FRANKFURT + DE + +00-60-AE (hex) TRIO INFORMATION SYSTEMS AB +0060AE (base 16) TRIO INFORMATION SYSTEMS AB + FOGDEVAGEN 4B + S-183 64 TABY + SE + +00-60-53 (hex) TOYODA MACHINE WORKS, LTD. +006053 (base 16) TOYODA MACHINE WORKS, LTD. + 1-7 KITAJIZOYAMA NODACHOU + KARIYA CITY, AICHI + JO + +00-60-56 (hex) NETWORK TOOLS, INC. +006056 (base 16) NETWORK TOOLS, INC. + 2975 BOWERS AVENUE, #202 + SANTA CLARA CA 95051-0955 + US + +00-60-0C (hex) Eurotech Inc. +00600C (base 16) Eurotech Inc. + 10260 Old Columbia Road + COLUMBIA MD 21046 + US + +00-60-1C (hex) TELXON CORPORATION +00601C (base 16) TELXON CORPORATION + 3330 W. MARKET STREET + AKRON OH 44334-0582 + US + +00-60-5F (hex) NIPPON UNISOFT CORPORATION +00605F (base 16) NIPPON UNISOFT CORPORATION + BR NINGYOCHO 1,2-13-9 + TOKYO 103 + JP + +00-60-91 (hex) FIRST PACIFIC NETWORKS, INC. +006091 (base 16) FIRST PACIFIC NETWORKS, INC. + 871 FOX LANE + SAN JOSE CA 95131 + US + +00-60-1D (hex) LUCENT TECHNOLOGIES +00601D (base 16) LUCENT TECHNOLOGIES + 101 CRAWFORDS CORNER RD. + HOLMDEL NJ 07733 + US + +00-60-7B (hex) FORE SYSTEMS, INC. +00607B (base 16) FORE SYSTEMS, INC. + 1000 FORE DRIVE + WARRENDALE PA 15086 + US + +00-E0-6C (hex) Ultra Electronics Command & Control Systems +00E06C (base 16) Ultra Electronics Command & Control Systems + Knaves Beech Business Centre + Hemel Hemstead Herts England HP2 7BW + GB + +00-E0-4A (hex) ZX Technologies, Inc +00E04A (base 16) ZX Technologies, Inc + 760 Spanish Oak Trail + Dripping Springs TX 78620 + US + +00-60-C9 (hex) ControlNet, Inc. +0060C9 (base 16) ControlNet, Inc. + 747 CAMDEN, STE. A + CAMPBELL CA 95008 + US + +00-E0-7A (hex) MIKRODIDAKT AB +00E07A (base 16) MIKRODIDAKT AB + Skiffervägen 48 + LUND SE22478 + SE + +00-60-32 (hex) I-CUBE, INC. +006032 (base 16) I-CUBE, INC. + 2328-C WALSH AVENUE + SANTA CLARA CA 95014 + US + +00-60-33 (hex) ACUITY IMAGING, INC. +006033 (base 16) ACUITY IMAGING, INC. + 9 TOWNSEND WEST + NASHUA NH 03063 + US + +00-60-13 (hex) NETSTAL MASCHINEN AG +006013 (base 16) NETSTAL MASCHINEN AG + INDUSTRIESTRASSE + CH-8752 NAEFELS + CH + +00-60-22 (hex) VICOM SYSTEMS, INC. +006022 (base 16) VICOM SYSTEMS, INC. + 1961 LANDINGS DRIVE + MOUNTAIN VIEW CA 94043 + US + +00-60-EE (hex) APOLLO +0060EE (base 16) APOLLO + 3610 BIRCH STREET--STE #100 + NEWPORT BEACH CA 92660 + US + +00-60-D8 (hex) ELMIC SYSTEMS, INC. +0060D8 (base 16) ELMIC SYSTEMS, INC. + DAI-ICHI SEIMEI BLDG. + YOKOHAMA 231 + JP + +00-60-EF (hex) FLYTECH TECHNOLOGY CO., LTD. +0060EF (base 16) FLYTECH TECHNOLOGY CO., LTD. + No.168 Sing-ai Rd., Neihu District + TAIPEI CITY 114 + TW + +00-60-85 (hex) Storage Concepts +006085 (base 16) Storage Concepts + 14352 Chamber Road + Tustin CA 92780 + US + +00-60-11 (hex) CRYSTAL SEMICONDUCTOR CORP. +006011 (base 16) CRYSTAL SEMICONDUCTOR CORP. + P.O. BOX 17847 + AUSTIN TX 78760 + US + +00-60-F5 (hex) ICON WEST, INC. +0060F5 (base 16) ICON WEST, INC. + 3342 SOUTH 300 EAST + SALT LAKE CITY UT 84115 + US + +00-60-62 (hex) TELESYNC, INC. +006062 (base 16) TELESYNC, INC. + 5555 OAKBROOK PKWY-STE #110 + NORCROSS GA 30093 + US + +00-60-E9 (hex) ATOP TECHNOLOGIES, INC. +0060E9 (base 16) ATOP TECHNOLOGIES, INC. + SUITE 305, NO. 47, PARK AVENUE II, + HSINCHU 30047 + TW + +00-60-43 (hex) iDirect, INC. +006043 (base 16) iDirect, INC. + 13865 Sunrise Vally Drive + Herndon VA 20171 + US + +00-60-28 (hex) MACROVISION CORPORATION +006028 (base 16) MACROVISION CORPORATION + 2830 De La Cruz Boulevard + Santa Clara CA 95050 + US + +00-60-F0 (hex) JOHNSON & JOHNSON MEDICAL, INC +0060F0 (base 16) JOHNSON & JOHNSON MEDICAL, INC + 4110 GEORGE RD. + TAMPA FL 33634 + US + +00-60-E0 (hex) AXIOM TECHNOLOGY CO., LTD. +0060E0 (base 16) AXIOM TECHNOLOGY CO., LTD. + 3F, 14, LANE 235 + TAIPEI HSIEN + TW + +00-60-96 (hex) T.S. MICROTECH INC. +006096 (base 16) T.S. MICROTECH INC. + 20818 HIGGINS COURT + TORRANCE CA 90501 + US + +00-60-3A (hex) QUICK CONTROLS LTD. +00603A (base 16) QUICK CONTROLS LTD. + DURHAM HOUSE, WARWICK COURT + MANCHESTER M24 1AE + GB + +00-02-88 (hex) GLOBAL VILLAGE COMMUNICATION +000288 (base 16) GLOBAL VILLAGE COMMUNICATION + 1144 EAST ARQUES AVE. + SUNNYVALE CA 94086 + US + +00-60-34 (hex) ROBERT BOSCH GmbH +006034 (base 16) ROBERT BOSCH GmbH + POSTBOX 11 62 + D-64701 ERBACH + DE + +00-60-50 (hex) INTERNIX INC. +006050 (base 16) INTERNIX INC. + 59-10 TAKAKURA-CHO + TOKYO 192 + JP + +00-60-FA (hex) EDUCATIONAL TECHNOLOGY RESOURCES, INC. +0060FA (base 16) EDUCATIONAL TECHNOLOGY RESOURCES, INC. + 1742 CHURCH STREET + HOLBROOK NY 11741 + US + +00-60-DA (hex) Red Lion Controls, LP +0060DA (base 16) Red Lion Controls, LP + 20 Willow Springs Circle + York NY 17402 + US + +00-60-E4 (hex) COMPUSERVE, INC. +0060E4 (base 16) COMPUSERVE, INC. + 5000 ARLINGTON CENTRE BLVD. + COLUMBUS OH 43220 + US + +00-60-8F (hex) TEKRAM TECHNOLOGY CO., LTD. +00608F (base 16) TEKRAM TECHNOLOGY CO., LTD. + B1, NO. 17, LANE 159, SEC. 6 + TAIPEI + TW + +00-60-C4 (hex) SOLITON SYSTEMS K.K. +0060C4 (base 16) SOLITON SYSTEMS K.K. + 2-4-3 SHINJUKU, SHINJUKU-KU + TOKYO 160 + JP + +00-A0-3C (hex) EG&G NUCLEAR INSTRUMENTS +00A03C (base 16) EG&G NUCLEAR INSTRUMENTS + 100 MIDLAND ROAD + OAK RIDGE TN 37830 + US + +00-A0-C4 (hex) CRISTIE ELECTRONICS LTD. +00A0C4 (base 16) CRISTIE ELECTRONICS LTD. + BOND'S MILL + GLOUCESTERSHIRE GL10 3RG + GB + +00-A0-63 (hex) JRL SYSTEMS, INC. +00A063 (base 16) JRL SYSTEMS, INC. + 8305 HWY 71 WEST + AUSTIN TX 78735 + US + +00-A0-2C (hex) interWAVE Communications +00A02C (base 16) interWAVE Communications + 656 BAIR ISLAND BLVD.-STE.#108 + REDWOOD CITY CA 94063-2704 + US + +00-A0-F7 (hex) V.I COMPUTER CORP. +00A0F7 (base 16) V.I COMPUTER CORP. + 531 ENCINITAS BLVD--#114 + ENCINITAS CA 92024 + US + +00-A0-90 (hex) TimeStep Corporation +00A090 (base 16) TimeStep Corporation + 359 TERRY FOX DRIVE + KANATA, ONTARIO K2K 2E7 + CA + +00-A0-EA (hex) ETHERCOM CORP. +00A0EA (base 16) ETHERCOM CORP. + 45990 HOTCHKISS ST. + FREEMONT CA 94539 + US + +00-A0-DC (hex) O.N. ELECTRONIC CO., LTD. +00A0DC (base 16) O.N. ELECTRONIC CO., LTD. + 3-20-27, TARUMI + SUITA, OSAKA 564 + JP + +00-A0-0B (hex) COMPUTEX CO., LTD. +00A00B (base 16) COMPUTEX CO., LTD. + 432-13 GOJYOBASHI-HIGASHI 4-CHYOME + HIGASHIYAMAKU, KYOTO-CITY 605 + JP + +00-A0-E2 (hex) Keisokugiken Corporation +00A0E2 (base 16) Keisokugiken Corporation + 2021-5 Houshakuji + Shioya-gun Tochigi 329-1233 + JP + +00-A0-33 (hex) imc MeBsysteme GmbH +00A033 (base 16) imc MeBsysteme GmbH + VOLTASTRASSE 5 + D-13355 BERLIN + DE + +00-A0-A9 (hex) NAVTEL COMMUNICATIONS INC. +00A0A9 (base 16) NAVTEL COMMUNICATIONS INC. + 55 RENFREW DRIVE + MARKHAM, ONTARIO L3R 8H3 + CA + +00-A0-71 (hex) VIDEO LOTTERY TECHNOLOGIES,INC +00A071 (base 16) VIDEO LOTTERY TECHNOLOGIES,INC + 2311 SOUTH 7TH AVENUE + BOZEMAN MT 59715 + US + +00-60-00 (hex) XYCOM INC. +006000 (base 16) XYCOM INC. + 750 N. MAPLE + SALINE MI 48176 + US + +00-60-45 (hex) PATHLIGHT TECHNOLOGIES +006045 (base 16) PATHLIGHT TECHNOLOGIES + 767 WARREN ROAD + ITHACA NY 14850 + US + +00-A0-5D (hex) CS COMPUTER SYSTEME GmbH +00A05D (base 16) CS COMPUTER SYSTEME GmbH + ISARSTRASSE 3, + 82065 BAIERBRUNN + DE + +00-A0-61 (hex) PURITAN BENNETT +00A061 (base 16) PURITAN BENNETT + 2200 FARADAY AVENUE + CARLSBAD CA 92008 + US + +00-60-A6 (hex) PARTICLE MEASURING SYSTEMS +0060A6 (base 16) PARTICLE MEASURING SYSTEMS + 5475 AIRPORT BLVD. + BOULDER CO 80301 + US + +00-60-2A (hex) SYMICRON COMPUTER COMMUNICATIONS, LTD. +00602A (base 16) SYMICRON COMPUTER COMMUNICATIONS, LTD. + UNIT 4 GREEN LANE BUSINESS PARK + London SE9 3TL + US + +00-A0-6D (hex) MANNESMANN TALLY CORPORATION +00A06D (base 16) MANNESMANN TALLY CORPORATION + P.O. BOX 97018 + KENT WA 98064-9718 + US + +00-A0-F6 (hex) AutoGas Systems Inc. +00A0F6 (base 16) AutoGas Systems Inc. + P.O. BOX 6957 + ABIOLENE TX 79608 + US + +00-60-BE (hex) WEBTRONICS +0060BE (base 16) WEBTRONICS + 3B-1 8-2-12 + SHINAGAWA-KU TOKYO 141 + JP + +00-60-BF (hex) MACRAIGOR SYSTEMS, INC. +0060BF (base 16) MACRAIGOR SYSTEMS, INC. + PO BOX 1008 + BROOKLINE VILLAGE MA 02147 + US + +00-60-80 (hex) MICROTRONIX DATACOM LTD. +006080 (base 16) MICROTRONIX DATACOM LTD. + 4056 Meadowbrook Drive, Unit 126 + LONDON ONTARIO N6L 1E3 + CA + +00-A0-37 (hex) Mindray DS USA, Inc. +00A037 (base 16) Mindray DS USA, Inc. + 800 Macarthur Blvd. + Mahwah NJ 07430 + US + +00-A0-4C (hex) INNOVATIVE SYSTEMS & TECHNOLOGIES, INC. +00A04C (base 16) INNOVATIVE SYSTEMS & TECHNOLOGIES, INC. + 48511 WARM SPRINGS BLVD. + FREMONT CA 94539 + US + +00-A0-31 (hex) HAZELTINE CORPORATION, MS 1-17 +00A031 (base 16) HAZELTINE CORPORATION, MS 1-17 + 450 E. PULASKI ROAD + GREENLAWN NY 11740 + US + +00-A0-41 (hex) INFICON +00A041 (base 16) INFICON + 2 Technology Place + E. Syracuse NY 13057 + US + +00-A0-A7 (hex) VORAX CORPORATION +00A0A7 (base 16) VORAX CORPORATION + 1031 EAST DUANE AVENUE, STE H + SUNNYVALE CA 94086 + US + +00-A0-7E (hex) AVID TECHNOLOGY, INC. +00A07E (base 16) AVID TECHNOLOGY, INC. + METROPOLITAN TECHNOLOGY PARK + TEWKSBURY MA 01876 + US + +00-A0-6F (hex) Color Sentinel Systems, LLC +00A06F (base 16) Color Sentinel Systems, LLC + 97 Ridgeland Rd, Suite #2 + ROCHESTER NY 14623 + US + +00-A0-C7 (hex) TADIRAN TELECOMMUNICATIONS +00A0C7 (base 16) TADIRAN TELECOMMUNICATIONS + P.O. BOX 500 + PETAH-TIKVA 49104 + IL + +00-A0-1A (hex) BINAR ELEKTRONIK AB +00A01A (base 16) BINAR ELEKTRONIK AB + MAGNETUAGEN 18 + + SE + +00-A0-88 (hex) ESSENTIAL COMMUNICATIONS +00A088 (base 16) ESSENTIAL COMMUNICATIONS + 4374 ALEXANDER BLVD. NE-STE + ALBUQUERQUE NM 87107 + US + +00-A0-C2 (hex) R.A. SYSTEMS CO., LTD. +00A0C2 (base 16) R.A. SYSTEMS CO., LTD. + 1850-3 HIROOKANOMURA + + JP + +00-A0-98 (hex) NetApp +00A098 (base 16) NetApp + 1395 Crossman Ave + Sunnyvale, CA 94089 + US + +00-A0-4B (hex) TFL LAN INC. +00A04B (base 16) TFL LAN INC. + 9F, NO. 499 CHUNG CHENG ROAD + TAIWAN TAIWAN R.O.C. + TW + +00-A0-64 (hex) KVB/ANALECT +00A064 (base 16) KVB/ANALECT + 9420 JERONIMO ROAD + IRVINE CA 92718 + US + +00-A0-3E (hex) ATM FORUM +00A03E (base 16) ATM FORUM + WORLDWIDE HEADQUARTERS + FOSTER CITY CA 94404-1138 + US + +00-A0-1F (hex) TRICORD SYSTEMS, INC. +00A01F (base 16) TRICORD SYSTEMS, INC. + 2800 NORTHWEST BOULEVARD + PLYMOUTH MN 55441-2625 + US + +00-A0-FB (hex) TORAY ENGINEERING CO., LTD. +00A0FB (base 16) TORAY ENGINEERING CO., LTD. + 1-45, OE 1-CHOME, OTSU CITY + 520-21 + JP + +00-A0-6C (hex) SHINDENGEN ELECTRIC MFG. CO., LTD. +00A06C (base 16) SHINDENGEN ELECTRIC MFG. CO., LTD. + 10-13, MINAMI-CHO, HANNOU-CITY + SAITAMA 357 + JO + +00-A0-DB (hex) FISHER & PAYKEL PRODUCTION +00A0DB (base 16) FISHER & PAYKEL PRODUCTION + MACHINERY LIMITED + + NZ + +00-A0-81 (hex) ALCATEL DATA NETWORKS +00A081 (base 16) ALCATEL DATA NETWORKS + 12502 SUNRISE VALLEY DRIVE + RESTON VA 22096 + US + +00-A0-B1 (hex) FIRST VIRTUAL CORPORATION +00A0B1 (base 16) FIRST VIRTUAL CORPORATION + 3393 OCTAVIUS DR.-STE.# 102 + SANTA CLARA CA 95054 + US + +00-20-10 (hex) JEOL SYSTEM TECHNOLOGY CO. LTD +002010 (base 16) JEOL SYSTEM TECHNOLOGY CO. LTD + 3-1-2 Musashino + Akishima-shi Tokyo 196-8558 + JP + +00-20-9F (hex) MERCURY COMPUTER SYSTEMS, INC. +00209F (base 16) MERCURY COMPUTER SYSTEMS, INC. + 199 RIVERNECK ROAD + CHELMSFORD MA 01824 + US + +00-A0-73 (hex) COM21, INC. +00A073 (base 16) COM21, INC. + 2113 LANDINGS DRIVE + MOUNTAIN VIEW CA 94043 + US + +00-A0-3A (hex) KUBOTEK CORPORATION +00A03A (base 16) KUBOTEK CORPORATION + 56 NISHIAKETA-CHO, HIGASHIKUJO + + JP + +00-A0-B2 (hex) SHIMA SEIKI +00A0B2 (base 16) SHIMA SEIKI + 85, SAKATA WAKAYAMA-CITY + + JP + +00-A0-8B (hex) ASTON ELECTRONIC DESIGNS LTD. +00A08B (base 16) ASTON ELECTRONIC DESIGNS LTD. + 123/127 DEEPCUT BRIDGE ROAD + ENGLAND + GB + +00-A0-97 (hex) JC INFORMATION SYSTEMS +00A097 (base 16) JC INFORMATION SYSTEMS + 4487 TECHNOLOGY DRIVE + FREMONT CA 94538-6343 + US + +00-A0-27 (hex) FIREPOWER SYSTEMS, INC. +00A027 (base 16) FIREPOWER SYSTEMS, INC. + 190 INDEPENDENCE DRIVE + MENLO PARK CA 94025 + US + +00-A0-46 (hex) SCITEX CORP. LTD. +00A046 (base 16) SCITEX CORP. LTD. + P.O.BOX 330 + + IL + +00-A0-D4 (hex) RADIOLAN, INC. +00A0D4 (base 16) RADIOLAN, INC. + 454 DEGUIGNE DRIVE - STE + SUNNYVALE CA 94086 + US + +00-A0-92 (hex) H. BOLLMANN MANUFACTURERS, LTD +00A092 (base 16) H. BOLLMANN MANUFACTURERS, LTD + 26 VICTORIA WAY + ENGLAND + GB + +00-20-0D (hex) CARL ZEISS +00200D (base 16) CARL ZEISS + POSTFACH 1380 + + DE + +00-20-2D (hex) TAIYO CORPORATION +00202D (base 16) TAIYO CORPORATION + 1-2-6 SANNOH, OHTA-KU + 143 + JP + +00-20-91 (hex) J125, NATIONAL SECURITY AGENCY +002091 (base 16) J125, NATIONAL SECURITY AGENCY + 9800 SAVAGE ROAD + FT. MEADE MD 20755-6000 + US + +00-20-BD (hex) NIOBRARA R & D CORPORATION +0020BD (base 16) NIOBRARA R & D CORPORATION + PO BOX 3418 + JOPLIN MO 64803-3418 + US + +00-20-54 (hex) Sycamore Networks +002054 (base 16) Sycamore Networks + 220 Mill Rd + Chelmsford MA 01824 + US + +00-20-A7 (hex) PAIRGAIN TECHNOLOGIES, INC. +0020A7 (base 16) PAIRGAIN TECHNOLOGIES, INC. + 14402 FRANKLIN AVENUE + TUSTIN CA 92680-7013 + US + +00-20-55 (hex) ALTECH CO., LTD. +002055 (base 16) ALTECH CO., LTD. + OHISHI BLDG., 2-23-11 + TOKYO 116 + JP + +00-20-0A (hex) SOURCE-COMM CORP. +00200A (base 16) SOURCE-COMM CORP. + 25020 W. AVENUE STANFORD + VALENCIA CA 91355 + US + +00-20-CF (hex) TEST & MEASUREMENT SYSTEMS INC +0020CF (base 16) TEST & MEASUREMENT SYSTEMS INC + 2045 SITKA COURT + LOVELAND CO 80538 + US + +00-20-B4 (hex) TERMA ELEKTRONIK AS +0020B4 (base 16) TERMA ELEKTRONIK AS + HOVMARKEN 4, + DK-8520 LYSTRUP + DK + +00-20-E4 (hex) HSING TECH ENTERPRISE CO., LTD +0020E4 (base 16) HSING TECH ENTERPRISE CO., LTD + NO. 2, LANE 128, SEC. 2 + TEIPEI, + TW + +00-20-6C (hex) EVERGREEN TECHNOLOGY CORP. +00206C (base 16) EVERGREEN TECHNOLOGY CORP. + 231 EMERSON STREET + PALO ALTO CA 94301 + US + +00-20-5E (hex) CASTLE ROCK, INC. +00205E (base 16) CASTLE ROCK, INC. + 20 SOUTH SANTA CRUZ AVE. + LOS GATOS CA 95030 + US + +00-20-12 (hex) CAMTRONICS MEDICAL SYSTEMS +002012 (base 16) CAMTRONICS MEDICAL SYSTEMS + P.O. BOX 950 + HARTLAND WI 53029 + US + +00-20-75 (hex) MOTOROLA COMMUNICATION ISRAEL +002075 (base 16) MOTOROLA COMMUNICATION ISRAEL + 3 KREMENETSKI STREET + TEL-AVIV 61250 + IL + +00-20-A5 (hex) API ENGINEERING +0020A5 (base 16) API ENGINEERING + 2689 POPLARWOOD WAY + SAN JOSE CA 95132 + US + +00-20-64 (hex) PROTEC MICROSYSTEMS, INC. +002064 (base 16) PROTEC MICROSYSTEMS, INC. + 297 LABROSSE + POINTE-CLAIRE, QUEBEC H9R 1A3 + CA + +00-20-33 (hex) SYNAPSE TECHNOLOGIES, INC. +002033 (base 16) SYNAPSE TECHNOLOGIES, INC. + 4822 ALBEMARLE ROAD, #104 + CHARLOTTE NC 28205 + US + +00-20-CB (hex) PRETEC ELECTRONICS CORP. +0020CB (base 16) PRETEC ELECTRONICS CORP. + 39899 BALENTINE DR. + NEWARK CA 94560 + US + +00-20-EB (hex) CINCINNATI MICROWAVE, INC. +0020EB (base 16) CINCINNATI MICROWAVE, INC. + ONE MICROWAVE PLAZA + CINCINNATI OH 45249 + US + +00-20-A0 (hex) OA LABORATORY CO., LTD. +0020A0 (base 16) OA LABORATORY CO., LTD. + 228 KAMIMACHIYA KAMAKURA + + JP + +00-20-E2 (hex) INFORMATION RESOURCE ENGINEERING +0020E2 (base 16) INFORMATION RESOURCE ENGINEERING + 8029 CORPORATE DRIVE + BALTIMORE MD 21236 + US + +00-20-07 (hex) SFA, INC. +002007 (base 16) SFA, INC. + 1401 MCCORMICK DRIVE + LANDOVER MD 20785 + US + +00-20-5C (hex) InterNet Systems of Florida, Inc. +00205C (base 16) InterNet Systems of Florida, Inc. + P.O. BOX 578 + CRESTVIEW FL 32536 + US + +00-20-A2 (hex) GALCOM NETWORKING LTD. +0020A2 (base 16) GALCOM NETWORKING LTD. + P.O. BOX 1568 + RAMAT HASHARON 47113 + IL + +00-20-31 (hex) Tattile SRL +002031 (base 16) Tattile SRL + AM PESTALOZZIRING 24 + D-91058 ERLANGEN + DE + +00-20-D0 (hex) VERSALYNX CORPORATION +0020D0 (base 16) VERSALYNX CORPORATION + 8950 CARLEY CIRCLE + SAN DIEGO CA 92126 + US + +00-20-B9 (hex) METRICOM, INC. +0020B9 (base 16) METRICOM, INC. + 980 UNIVERSITY AVENUE + LOS GATOS CA 95030 + US + +00-20-39 (hex) SCINETS +002039 (base 16) SCINETS + 1575 TENAKA - STE# N8 + SUNNYVALE CA 94087 + US + +00-20-72 (hex) WORKLINK INNOVATIONS +002072 (base 16) WORKLINK INNOVATIONS + 2452 ARMSTRONG STREET + LIVERMORE CA 9455O + US + +00-20-EC (hex) TECHWARE SYSTEMS CORP. +0020EC (base 16) TECHWARE SYSTEMS CORP. + #100 - 12051 HORSESHOE WAY + V7A 4V4 + CA + +00-20-6E (hex) XACT, INC. +00206E (base 16) XACT, INC. + P.O. BOX 55 + ARGYLE TX 76226 + US + +00-20-F1 (hex) ALTOS INDIA LIMITED +0020F1 (base 16) ALTOS INDIA LIMITED + D-60, OKLHLA INDUSTRIAL + + IN + +00-20-41 (hex) DATA NET +002041 (base 16) DATA NET + SUWON P.O. BOX 106, SUWON + KOREA 440-600 + KR + +00-20-76 (hex) REUDO CORPORATION +002076 (base 16) REUDO CORPORATION + 4-1-10 SHINSAN + + JP + +00-20-E8 (hex) DATATREK CORPORATION +0020E8 (base 16) DATATREK CORPORATION + 4505 WYLAND DRIVE + ELKHART IN 46516 + US + +00-20-C5 (hex) EAGLE TECHNOLOGY +0020C5 (base 16) EAGLE TECHNOLOGY + 2865 ZANKER ROAD + SAN JOSE CA 95134 + US + +00-20-09 (hex) PACKARD BELL ELEC., INC. +002009 (base 16) PACKARD BELL ELEC., INC. + 9425 CANOGA AVENUE + CHATSWORTH CA 913211 + US + +00-20-27 (hex) MING FORTUNE INDUSTRY CO., LTD +002027 (base 16) MING FORTUNE INDUSTRY CO., LTD + 4F, NO. 800 CHUNG CHENG RD, + TAIWAN TAIWAN R.O.C. + TW + +00-20-8A (hex) SONIX COMMUNICATIONS, LTD. +00208A (base 16) SONIX COMMUNICATIONS, LTD. + WILKINSON ROAD + ENGLAND + GB + +00-20-D2 (hex) RAD DATA COMMUNICATIONS, LTD. +0020D2 (base 16) RAD DATA COMMUNICATIONS, LTD. + 8 HANECHOSHET STREET + + KZ + +00-20-02 (hex) SERITECH ENTERPRISE CO., LTD. +002002 (base 16) SERITECH ENTERPRISE CO., LTD. + FL. 182, NO. 531-1 + TAIWAN TAIWAN R.O.C. + TW + +00-20-4B (hex) AUTOCOMPUTER CO., LTD. +00204B (base 16) AUTOCOMPUTER CO., LTD. + NO. 18, PEI YUAN ROAD + TAIWAN TAIWAN R.O.C. + TW + +00-20-EA (hex) EFFICIENT NETWORKS, INC. +0020EA (base 16) EFFICIENT NETWORKS, INC. + 4201 SPRING VALLEY ROAD + DALLAS TX 75244-3666 + US + +00-20-6A (hex) OSAKA COMPUTER CORP. +00206A (base 16) OSAKA COMPUTER CORP. + 2-8 KOYACHOU NEYAGAW-SHI + + JP + +00-20-DB (hex) XNET TECHNOLOGY, INC. +0020DB (base 16) XNET TECHNOLOGY, INC. + 426 S. HILLVIEW DRIVE + MILPITAS CA 95035 + US + +00-20-BB (hex) ZAX CORPORATION +0020BB (base 16) ZAX CORPORATION + 20-12 OGIKUBO 5-CHOME + 167 + JP + +00-20-A8 (hex) SAST TECHNOLOGY CORP. +0020A8 (base 16) SAST TECHNOLOGY CORP. + 225 OLD NEW BRUNSWICK RD. + PISCATAWAY NJ 08854 + US + +00-20-45 (hex) ION Networks, Inc. +002045 (base 16) ION Networks, Inc. + 1551 South Washington Ave. + Piscataway NJ 08854 + US + +00-20-49 (hex) COMTRON, INC. +002049 (base 16) COMTRON, INC. + SANCATHERINA BLDG. + TOKYO 160 + JP + +00-20-50 (hex) KOREA COMPUTER INC. +002050 (base 16) KOREA COMPUTER INC. + 469, DAEHEUNG-DONG + KOREA + KR + +00-20-84 (hex) OCE PRINTING SYSTEMS, GMBH +002084 (base 16) OCE PRINTING SYSTEMS, GMBH + SIEMENSALLEE 2 + + DE + +00-20-8C (hex) GALAXY NETWORKS, INC. +00208C (base 16) GALAXY NETWORKS, INC. + 9348 DE SOTO AVENUE + CHATSWORTH CA 91311 + US + +00-20-A6 (hex) Proxim Wireless +0020A6 (base 16) Proxim Wireless + 1561 Buckeye Drive + Milpitas CA 95035 + US + +00-20-2C (hex) WELLTRONIX CO., LTD. +00202C (base 16) WELLTRONIX CO., LTD. + 3F, NO. 36-1, HWANG HSI STREET + TAIWAN TAIWAN R.O.C. + TW + +00-20-21 (hex) ALGORITHMS SOFTWARE PVT. LTD. +002021 (base 16) ALGORITHMS SOFTWARE PVT. LTD. + 83 JOLLY MAKER CHAMBERS II + + IN + +00-C0-F9 (hex) Artesyn Embedded Technologies +00C0F9 (base 16) Artesyn Embedded Technologies + 2900 S. Diablo Way Suite 190 + Tempe AZ 85282 + US + +00-C0-75 (hex) XANTE CORPORATION +00C075 (base 16) XANTE CORPORATION + 2559 EMOGENE STREET + MOBILE AL 36606 + US + +00-1C-7C (hex) PERQ SYSTEMS CORPORATION +001C7C (base 16) PERQ SYSTEMS CORPORATION + 2600 LIBERTY AVENUE + PITTSBURGH PA 15230 + US + +00-C0-39 (hex) Teridian Semiconductor Corporation +00C039 (base 16) Teridian Semiconductor Corporation + 6440 Oak Canyon + Irvine CA 92618 + US + +00-C0-A9 (hex) BARRON MCCANN LTD. +00C0A9 (base 16) BARRON MCCANN LTD. + BEMAC HOUSE + UNITED KINGDOM + GB + +00-C0-4B (hex) CREATIVE MICROSYSTEMS +00C04B (base 16) CREATIVE MICROSYSTEMS + 9, AVENUE DU CANADA + 91966 LES ULIS---FRANC + FR + +00-C0-B9 (hex) FUNK SOFTWARE, INC. +00C0B9 (base 16) FUNK SOFTWARE, INC. + 222 THIRD STREET + CAMBRIDGE MA 02142 + US + +00-C0-15 (hex) NEW MEDIA CORPORATION +00C015 (base 16) NEW MEDIA CORPORATION + 15375 BARRANCA PARKWAY + IRVINE CA 92718 + US + +00-C0-83 (hex) TRACE MOUNTAIN PRODUCTS, INC. +00C083 (base 16) TRACE MOUNTAIN PRODUCTS, INC. + 1040 EAST BROKAW ROAD + SAN JOSE CA 95131 + US + +00-C0-94 (hex) VMX INC. +00C094 (base 16) VMX INC. + 2115 O'NEL DRIVE + SAN JOSE CA 95131 + US + +00-C0-19 (hex) LEAP TECHNOLOGY, INC. +00C019 (base 16) LEAP TECHNOLOGY, INC. + 20 + BURLINGTON MA 01803 + US + +00-C0-CF (hex) IMATRAN VOIMA OY +00C0CF (base 16) IMATRAN VOIMA OY + IVO + + FI + +00-C0-7D (hex) RISC DEVELOPMENTS LTD. +00C07D (base 16) RISC DEVELOPMENTS LTD. + 117 HATFIELD ROAD + ENGLAND + GB + +00-C0-43 (hex) STRATACOM +00C043 (base 16) STRATACOM + 1400 PARKMOOR AVENUE + SAN JOSE CA 95126 + US + +00-C0-B5 (hex) CORPORATE NETWORK SYSTEMS,INC. +00C0B5 (base 16) CORPORATE NETWORK SYSTEMS,INC. + 5711 SIX FORKS ROAD--STE #306 + RALEIGH NC 27609 + US + +00-C0-ED (hex) US ARMY ELECTRONIC +00C0ED (base 16) US ARMY ELECTRONIC + PROVING GROUND + SIERRA VISTA AZ 85635 + US + +00-C0-32 (hex) I-CUBED LIMITED +00C032 (base 16) I-CUBED LIMITED + UNIT J1, THE POADDOCKS + CB1 4DH CB1 4DH ENGLAND + GB + +00-C0-A5 (hex) DICKENS DATA SYSTEMS +00C0A5 (base 16) DICKENS DATA SYSTEMS + 1175 NORTHMEADOW PKWY-STE #150 + ROSWELL GA 30076 + US + +00-C0-EF (hex) ABIT CORPORATION +00C0EF (base 16) ABIT CORPORATION + 29-11 HIRAOKA-CHO + 192 + JP + +00-C0-61 (hex) SOLECTEK CORPORATION +00C061 (base 16) SOLECTEK CORPORATION + 6370 NANCY RIDGE DR.-STE.#109 + SAN DIEGO CA 92121 + US + +00-C0-AD (hex) MARBEN COMMUNICATION SYSTEMS +00C0AD (base 16) MARBEN COMMUNICATION SYSTEMS + 1 RUE DU BOIS CHALAND + + FR + +00-C0-7F (hex) NUPON COMPUTING CORP. +00C07F (base 16) NUPON COMPUTING CORP. + 1391 WARNER AVE., -SUITE + TUSTIN CA 92680 + US + +00-C0-57 (hex) MYCO ELECTRONICS +00C057 (base 16) MYCO ELECTRONICS + MUSSERONGRAND 1G + + SE + +00-C0-56 (hex) SOMELEC +00C056 (base 16) SOMELEC + BP 7010 - 95050 + + FR + +00-C0-27 (hex) CIPHER SYSTEMS, INC. +00C027 (base 16) CIPHER SYSTEMS, INC. + 22115 NW Imbrie Dr #285 + Hillsboro OR 97124 + US + +00-C0-5C (hex) ELONEX PLC +00C05C (base 16) ELONEX PLC + 2 APSLEY WAY + UNITED KINGDOM + GB + +00-C0-28 (hex) JASCO CORPORATION +00C028 (base 16) JASCO CORPORATION + 2967-5 ISHIKAWA-CHO, + + JP + +00-C0-8D (hex) TRONIX PRODUCT DEVELOPMENT +00C08D (base 16) TRONIX PRODUCT DEVELOPMENT + 4908 E. MCDOWELL RD. STE.#100 + PHOENIX AZ 85008 + US + +00-C0-2A (hex) OHKURA ELECTRIC CO., LTD. +00C02A (base 16) OHKURA ELECTRIC CO., LTD. + 2-90-20 SHIRAKO WAKO CITY + 351-01 + JP + +00-C0-FC (hex) ELASTIC REALITY, INC. +00C0FC (base 16) ELASTIC REALITY, INC. + 925 STEWART STREET + MADISON WI 53713 + US + +00-C0-BB (hex) FORVAL CREATIVE, INC. +00C0BB (base 16) FORVAL CREATIVE, INC. + 3-27-12 HONGO + + JP + +00-C0-E0 (hex) DSC COMMUNICATION CORP. +00C0E0 (base 16) DSC COMMUNICATION CORP. + 1000 COIT ROAD, MS#ADVP 3 + PLANO TX 75075 + US + +00-C0-5B (hex) NETWORKS NORTHWEST, INC. +00C05B (base 16) NETWORKS NORTHWEST, INC. + P.O. BOX 1188 + ISSAQUAH WA 98027 + US + +00-C0-08 (hex) SECO SRL +00C008 (base 16) SECO SRL + VIA CALAMANDREI 91 + + IT + +00-C0-B7 (hex) AMERICAN POWER CONVERSION CORP +00C0B7 (base 16) AMERICAN POWER CONVERSION CORP + 267 BOSTON ROAD #2 + NORTH BILLERICA MA 01862 + US + +00-C0-D3 (hex) OLYMPUS IMAGE SYSTEMS, INC. +00C0D3 (base 16) OLYMPUS IMAGE SYSTEMS, INC. + 15271 BARRANCA PARKWAY + IRVINE CA 92718-2201 + US + +00-C0-E8 (hex) PLEXCOM, INC. +00C0E8 (base 16) PLEXCOM, INC. + 65 MORELAND ROADENUYE + SIMI VALLEY CA 93065 + US + +00-C0-DA (hex) NICE SYSTEMS LTD. +00C0DA (base 16) NICE SYSTEMS LTD. + 3 TEVUOT HA'ARETZ ST + + IL + +00-C0-D1 (hex) COMTREE TECHNOLOGY CORPORATION +00C0D1 (base 16) COMTREE TECHNOLOGY CORPORATION + 5F-7, NO. 1, FU-HSING NORTH RD + TAIWAN R.O.C. + CN + +00-C0-38 (hex) RASTER IMAGE PROCESSING SYSTEM +00C038 (base 16) RASTER IMAGE PROCESSING SYSTEM + 4665 NAUTILUS COURT SOUTH + BOULDER CO 80301 + US + +00-40-9B (hex) HAL COMPUTER SYSTEMS INC. +00409B (base 16) HAL COMPUTER SYSTEMS INC. + 1315 DELL AVENUE + CAMPBELL CA 95008 + US + +00-40-EB (hex) MARTIN MARIETTA CORPORATION +0040EB (base 16) MARTIN MARIETTA CORPORATION + 12506 LAKE UNDERHILL + ORLANDO FL 32825 + US + +00-40-BD (hex) STARLIGHT NETWORKS, INC. +0040BD (base 16) STARLIGHT NETWORKS, INC. + 444 CASTRO STREET STE + MOUNTAIN VIEW CA 94041 + US + +00-40-ED (hex) NETWORK CONTROLS INT'NATL INC. +0040ED (base 16) NETWORK CONTROLS INT'NATL INC. + 9 WOODLAWN GREEN + CHARLOTTE NC 28217 + US + +00-40-21 (hex) RASTER GRAPHICS +004021 (base 16) RASTER GRAPHICS + 285 N. WOLFE ROAD + SUNNYVALE CA 94086 + US + +00-40-C1 (hex) BIZERBA-WERKE WILHEIM KRAUT +0040C1 (base 16) BIZERBA-WERKE WILHEIM KRAUT + GMBH & CO. KG, + D-7460 BALINGEN D-7460 BALINGEN + DE + +00-40-E1 (hex) MARNER INTERNATIONAL, INC. +0040E1 (base 16) MARNER INTERNATIONAL, INC. + 1617 93RD LANE NE + BLAINE MN 55449 + US + +00-40-FE (hex) SYMPLEX COMMUNICATIONS +0040FE (base 16) SYMPLEX COMMUNICATIONS + 5 RESEARCH DRIVE + ANN ARBOR MI 48103 + US + +00-40-E5 (hex) SYBUS CORPORATION +0040E5 (base 16) SYBUS CORPORATION + 2300 TALL PINE DRIVE-STE. #100 + LARGO FL 34641 + US + +00-40-A5 (hex) CLINICOMP INTL. +0040A5 (base 16) CLINICOMP INTL. + 4510 EXECCUTIVE DRIVE-STE.#200 + SAN DIEGO CA 92121 + US + +00-40-05 (hex) ANI COMMUNICATIONS INC. +004005 (base 16) ANI COMMUNICATIONS INC. + 8 ANZIO + IRVINE CA 92714 + US + +00-40-D9 (hex) AMERICAN MEGATRENDS INC. +0040D9 (base 16) AMERICAN MEGATRENDS INC. + 6145F N BELT PARKWAY + NORCROSS GA 30071 + US + +00-40-4C (hex) HYPERTEC PTY LTD. +00404C (base 16) HYPERTEC PTY LTD. + P.O. BOX 1782 + + AU + +00-C0-30 (hex) INTEGRATED ENGINEERING B. V. +00C030 (base 16) INTEGRATED ENGINEERING B. V. + ELLERMANSTRAAT 15 + THE + NL + +00-C0-A6 (hex) EXICOM AUSTRALIA PTY. LTD +00C0A6 (base 16) EXICOM AUSTRALIA PTY. LTD + 44-46 MANDARIN STREET + + AU + +00-C0-CB (hex) CONTROL TECHNOLOGY CORPORATION +00C0CB (base 16) CONTROL TECHNOLOGY CORPORATION + 25 SOUTH STREET + HOPKINTON MA 01748 + US + +00-C0-EB (hex) SEH COMPUTERTECHNIK GMBH +00C0EB (base 16) SEH COMPUTERTECHNIK GMBH + Suedring 11 + + DE + +00-40-DB (hex) ADVANCED TECHNICAL SOLUTIONS +0040DB (base 16) ADVANCED TECHNICAL SOLUTIONS + 8050 SEMINOLE OFFICE CENTER + SEMINOLE FL 34642 + US + +00-C0-92 (hex) MENNEN MEDICAL INC. +00C092 (base 16) MENNEN MEDICAL INC. + 10123 MAIN STREET + CLARENCE NY 14031-2095 + US + +00-C0-52 (hex) BURR-BROWN +00C052 (base 16) BURR-BROWN + P.O. BOX 11400 + TUCSON AZ 85734-1400 + US + +00-40-0E (hex) MEMOTEC, INC. +00400E (base 16) MEMOTEC, INC. + 7755 Henri-Bourassa + MONTREAL, QUEBEC H4S 1P7 + CA + +00-C0-3D (hex) WIESEMANN & THEIS GMBH +00C03D (base 16) WIESEMANN & THEIS GMBH + WITTENER STR. 312 + + DE + +00-40-C8 (hex) MILAN TECHNOLOGY CORPORATION +0040C8 (base 16) MILAN TECHNOLOGY CORPORATION + 894 ROSS DRIVE--STE #105 + SUNNYVALE CA 94089 + US + +00-40-BA (hex) ALLIANT COMPUTER SYSTEMS CORP. +0040BA (base 16) ALLIANT COMPUTER SYSTEMS CORP. + ONE MONARCH DRIVE + LITTLETON MA 01460 + US + +00-40-38 (hex) TALENT ELECTRIC INCORPORATED +004038 (base 16) TALENT ELECTRIC INCORPORATED + 3RD FL., NO. 260, PA TEH ROAD + TAIWAN TAIWAN R.O.C. + TW + +00-40-D8 (hex) OCEAN OFFICE AUTOMATION LTD. +0040D8 (base 16) OCEAN OFFICE AUTOMATION LTD. + 4TH & 5TH FLOOR, KADER BLDG. + HONG KONG + HK + +00-40-88 (hex) MOBIUS TECHNOLOGIES, INC. +004088 (base 16) MOBIUS TECHNOLOGIES, INC. + 5835 DOYLE STREET + EMERYVILLE CA 94608 + US + +00-40-32 (hex) DIGITAL COMMUNICATIONS +004032 (base 16) DIGITAL COMMUNICATIONS + ASSOCIATES, INC. + SAN JOSE CA 95131 + US + +00-40-C2 (hex) APPLIED COMPUTING DEVICES +0040C2 (base 16) APPLIED COMPUTING DEVICES + ALEPH PARK + TERRE HAUTE IN 47802 + US + +00-40-D4 (hex) GAGE TALKER CORP. +0040D4 (base 16) GAGE TALKER CORP. + 13680 NE 16TH STREET + BELLEVUE WA 98005 + US + +00-40-CE (hex) NET-SOURCE, INC. +0040CE (base 16) NET-SOURCE, INC. + 1265 EL CAMINO REAL + SANTA CLARA CA 95050 + US + +00-40-62 (hex) E-SYSTEMS, INC./GARLAND DIV. +004062 (base 16) E-SYSTEMS, INC./GARLAND DIV. + P.O. BOX 660023 + DALLAS TX 75266-0023 + US + +00-40-34 (hex) BUSTEK CORPORATION +004034 (base 16) BUSTEK CORPORATION + 4151 BURTON DRIVE + SANTA CLARA CA 95054 + US + +00-40-1C (hex) AST RESEARCH, INC. +00401C (base 16) AST RESEARCH, INC. + MS 2-78 + IRVINE CA 92618 + US + +00-40-0F (hex) DATACOM TECHNOLOGIES +00400F (base 16) DATACOM TECHNOLOGIES + 11001 31ST PLACE WEST + EVERETT WA 98204 + US + +00-40-06 (hex) SAMPO TECHNOLOGY CORPORATION +004006 (base 16) SAMPO TECHNOLOGY CORPORATION + 26-2 TING-HU, + 33334 TAIWAN 33334 TAIWAN R.O.C. + TW + +00-80-AA (hex) MAXPEED +0080AA (base 16) MAXPEED + 1120 CHESS DRIVE + FOSTER CITY CA 94404 + US + +00-C0-50 (hex) TOYO DENKI SEIZO K.K. +00C050 (base 16) TOYO DENKI SEIZO K.K. + 4-6-32 HIGASHIKASHIWAGAYA + KANAGAWA JAPAN 243-04 + JP + +00-40-C6 (hex) FIBERNET RESEARCH, INC. +0040C6 (base 16) FIBERNET RESEARCH, INC. + 1 TARA BOULEVARD-#405 + NASHUA NH 03062 + US + +00-40-47 (hex) WIND RIVER SYSTEMS +004047 (base 16) WIND RIVER SYSTEMS + 1010 ATLANTIC AVENUE + ALAMEDA CA 94501 + US + +00-40-50 (hex) IRONICS, INCORPORATED +004050 (base 16) IRONICS, INCORPORATED + 767 WARREN RD + ITHACA N.Y. 14850 + US + +00-80-92 (hex) Silex Technology, Inc. +008092 (base 16) Silex Technology, Inc. + 2-3-1 Hikaridai, + Kyoto 619-0237 + JP + +00-80-93 (hex) XYRON CORPORATION +008093 (base 16) XYRON CORPORATION + 7864 LILY COURT + CUPERTINO CA 95014 + US + +00-80-5A (hex) TULIP COMPUTERS INTERNAT'L B.V +00805A (base 16) TULIP COMPUTERS INTERNAT'L B.V + P.O. BOX 3333 + THE + NL + +00-40-41 (hex) FUJIKURA LTD. +004041 (base 16) FUJIKURA LTD. + 1-5-1, KIBA, KOTO-KU + + JP + +00-80-4E (hex) APEX COMPUTER COMPANY +00804E (base 16) APEX COMPUTER COMPANY + 4500 150TH AVENUE, NE + REDMOND WA 98052 + US + +00-80-55 (hex) FERMILAB +008055 (base 16) FERMILAB + P.O. BOX 500, MS-234 + BATAVIA IL 60510 + US + +00-80-2A (hex) TEST SYSTEMS & SIMULATIONS INC +00802A (base 16) TEST SYSTEMS & SIMULATIONS INC + 32429 INDUSTRIAL DRIVE + MADISON HEIGHTS MI 48071-1528 + US + +00-80-35 (hex) TECHNOLOGY WORKS, INC. +008035 (base 16) TECHNOLOGY WORKS, INC. + 4030 BRAKER LANE #350 + AUSTIN TX 78759 + US + +00-80-7E (hex) SOUTHERN PACIFIC LTD. +00807E (base 16) SOUTHERN PACIFIC LTD. + SANWA BLDG., 2-16-20 + JAPAN JAPAN 220 + JP + +00-80-EF (hex) RATIONAL +0080EF (base 16) RATIONAL + 3320 SCOTT BOULEVARD + SANTA CLARA CA 95054 + US + +00-80-F0 (hex) Panasonic Communications Co., Ltd. +0080F0 (base 16) Panasonic Communications Co., Ltd. + 4-1-62 Minoshima Hakata Fukuoka + 812-8531 + JP + +00-80-1D (hex) INTEGRATED INFERENCE MACHINES +00801D (base 16) INTEGRATED INFERENCE MACHINES + 1468 EAST KATELLA + ANAHEIM CA 92805 + US + +00-80-75 (hex) PARSYTEC GMBH +008075 (base 16) PARSYTEC GMBH + JUELICHER STR. 338 + F.R. + DE + +00-80-51 (hex) FIBERMUX +008051 (base 16) FIBERMUX + 9310 TOPANGA CANYON BLVD. + CHATSWORTH CA 91311 + US + +00-80-C6 (hex) NATIONAL DATACOMM CORPORATION +0080C6 (base 16) NATIONAL DATACOMM CORPORATION + 2F, 28, INDUSTRY EAST 9TH RD. + TAIWAN 30077 TAIWAN 30077 R.O.C. + TW + +00-80-C0 (hex) PENRIL DATACOMM +0080C0 (base 16) PENRIL DATACOMM + 1300 QUINCE ORCHARD BLVD. + GAITHERSBURG MD 20878 + US + +00-80-2E (hex) CASTLE ROCK COMPUTING +00802E (base 16) CASTLE ROCK COMPUTING + 20837 BOYCE LANE + SARATOGA CA 95070-4806 + US + +00-80-F2 (hex) RAYCOM SYSTEMS INC +0080F2 (base 16) RAYCOM SYSTEMS INC + 16525 SHERMAN WAY #C-8 + VAN NUYS CA 91406 + US + +00-80-BD (hex) THE FURUKAWA ELECTRIC CO., LTD +0080BD (base 16) THE FURUKAWA ELECTRIC CO., LTD + 6-1, MARUNOUCHI 2-CHOME + 100 + JP + +00-80-25 (hex) Telit Wireless Solutions GmbH +008025 (base 16) Telit Wireless Solutions GmbH + Mendelssohnstrasse15D + Hamburg 22761 + DE + +00-80-EA (hex) ADVA Optical Networking Ltd. +0080EA (base 16) ADVA Optical Networking Ltd. + ADVAntage House + York YO30 4RY + GB + +00-00-1E (hex) TELSIST INDUSTRIA ELECTRONICA +00001E (base 16) TELSIST INDUSTRIA ELECTRONICA + RUA VILHENA DE MORAES, 380 + + BR + +00-00-50 (hex) RADISYS CORPORATION +000050 (base 16) RADISYS CORPORATION + 15025 S.W. KOLL PARKWAY + BEAVERTON OR 97006-6056 + US + +00-80-04 (hex) ANTLOW COMMUNICATIONS, LTD. +008004 (base 16) ANTLOW COMMUNICATIONS, LTD. + 4 COLTHROP WAY + ENGLAND + GB + +00-80-D0 (hex) COMPUTER PERIPHERALS, INC. +0080D0 (base 16) COMPUTER PERIPHERALS, INC. + 667 RANCHO CONEJO BLVD. + NEWBURY PARK CA 91320 + US + +00-80-24 (hex) KALPANA, INC. +008024 (base 16) KALPANA, INC. + 1154 EAST ARQUES AVENUE + SUNNYVALE CA 94086 + US + +00-80-40 (hex) JOHN FLUKE MANUFACTURING CO. +008040 (base 16) JOHN FLUKE MANUFACTURING CO. + P.O. BOX C9090-M/S 244F + EVERETT WA 98206 + US + +00-80-21 (hex) Alcatel Canada Inc. +008021 (base 16) Alcatel Canada Inc. + 349 Terry Fox Drive + Kanata Ontario K2K 2V6 + CA + +00-80-E8 (hex) CUMULUS CORPORATIION +0080E8 (base 16) CUMULUS CORPORATIION + 23500 MERCANTILE ROAD + CLEVELAND OH 44122 + US + +00-80-69 (hex) COMPUTONE SYSTEMS +008069 (base 16) COMPUTONE SYSTEMS + 1100 NORTHMEADOW PARKWAY + ROSWELL GA 30076 + US + +00-80-0D (hex) VOSSWINKEL F.U. +00800D (base 16) VOSSWINKEL F.U. + AM JOSTENHOF 15 + + DE + +00-80-D1 (hex) KIMTRON CORPORATION +0080D1 (base 16) KIMTRON CORPORATION + 1709 JUNCTION COURT + SAN JOSE CA 95112 + US + +00-80-42 (hex) Artesyn Embedded Technologies +008042 (base 16) Artesyn Embedded Technologies + 2900 S. Diablo Way + Tempe AZ 85282 + US + +00-80-9A (hex) NOVUS NETWORKS LTD +00809A (base 16) NOVUS NETWORKS LTD + JOHN SCOTT HOUSE + ENGLAND + GB + +00-80-00 (hex) MULTITECH SYSTEMS, INC. +008000 (base 16) MULTITECH SYSTEMS, INC. + 2205 WOODALE DRIVE + MOUNDS VIEW MN 55112 + US + +00-80-ED (hex) IQ TECHNOLOGIES, INC. +0080ED (base 16) IQ TECHNOLOGIES, INC. + 11811 NE FIRST STREET + BELLEVUE WA 98005 + US + +00-80-4A (hex) PRO-LOG +00804A (base 16) PRO-LOG + 12 UPPER RAGSDALE DRIVE + MONTEREY CA 93940 + US + +00-00-66 (hex) TALARIS SYSTEMS, INC. +000066 (base 16) TALARIS SYSTEMS, INC. + 11339 SORRENTO VALLEY ROAD + SAN DIEGO CA 92121 + US + +00-00-49 (hex) APRICOT COMPUTERS, LTD +000049 (base 16) APRICOT COMPUTERS, LTD + 90 VINCENT DRIVE + ENGLAND + GB + +00-00-FA (hex) MICROSAGE COMPUTER SYSTEMS INC +0000FA (base 16) MICROSAGE COMPUTER SYSTEMS INC + 680 SOUTH ROCK BLVD + RENO NE 89502 + US + +00-00-D4 (hex) PURE DATA LTD. +0000D4 (base 16) PURE DATA LTD. + 200 WEST BEAVER CREEK ROAD + L4B 1B4 + CA + +00-00-19 (hex) APPLIED DYNAMICS INTERNATIONAL +000019 (base 16) APPLIED DYNAMICS INTERNATIONAL + 3800 STONE SCHOOL ROAD + ANN ARBOR MI 48104-2499 + US + +00-00-15 (hex) DATAPOINT CORPORATION +000015 (base 16) DATAPOINT CORPORATION + 9725 DATAPOINT DRIVE + SAN ANTONIO TX 78284 + US + +00-00-1C (hex) BELL TECHNOLOGIES +00001C (base 16) BELL TECHNOLOGIES + 330 WARREN AVENUE + FREMONT CA 94539 + US + +00-00-34 (hex) NETWORK RESOURCES CORPORATION +000034 (base 16) NETWORK RESOURCES CORPORATION + 61 EAST DAGGETT DRIVE + SAN JOSE CA 95134 + US + +00-00-22 (hex) VISUAL TECHNOLOGY INC. +000022 (base 16) VISUAL TECHNOLOGY INC. + 1703 MIDDLESEX STREET + LOWELL MA 01851 + US + +00-00-B5 (hex) DATABILITY SOFTWARE SYS. INC. +0000B5 (base 16) DATABILITY SOFTWARE SYS. INC. + ONE PALMER TERRACE + CARLSTADT NJ 07072 + US + +00-00-2F (hex) TIMEPLEX INC. +00002F (base 16) TIMEPLEX INC. + 530 CHESTNUT RIDGE ROAD + WOODCLIFF LAKE NJ 07675 + US + +00-00-B8 (hex) SEIKOSHA CO., LTD. +0000B8 (base 16) SEIKOSHA CO., LTD. + SYSTEM EQUIPMENT DIVISION + + JP + +00-00-E6 (hex) APTOR PRODUITS DE COMM INDUST +0000E6 (base 16) APTOR PRODUITS DE COMM INDUST + 61, CHEMIN DU VIEUX-CHENE + + FR + +00-00-84 (hex) SUPERNET +000084 (base 16) SUPERNET + 846 DEL REY AVENUE + SUNNYVALE CA 94086 + US + +00-00-9A (hex) RC COMPUTER A/S +00009A (base 16) RC COMPUTER A/S + LAUTRUPBJERG 1 + + DK + +00-00-27 (hex) JAPAN RADIO COMPANY +000027 (base 16) JAPAN RADIO COMPANY + LABORATORY + + JP + +00-00-E8 (hex) ACCTON TECHNOLOGY CORP. +0000E8 (base 16) ACCTON TECHNOLOGY CORP. + 46750 FREMONT BLVD. #104 + FREMONT CA 94538 + US + +00-00-4B (hex) ICL DATA OY +00004B (base 16) ICL DATA OY + KUTOMOTIE 16-18 + + FI + +00-00-E0 (hex) QUADRAM CORP. +0000E0 (base 16) QUADRAM CORP. + ONE QUAD WAY + NORCROSS GA 30093 + US + +00-00-AB (hex) LOGIC MODELING CORPORATION +0000AB (base 16) LOGIC MODELING CORPORATION + 1520 MCCANDLESS DRIVE + MILPITAS CA 95035 + US + +00-80-AC (hex) IMLOGIX, DIVISION OF GENESYS +0080AC (base 16) IMLOGIX, DIVISION OF GENESYS + 1900 SUMMIT TOWER BLVD.STE#770 + ORLANDO FL 32810 + US + +00-00-4F (hex) LOGICRAFT, INC. +00004F (base 16) LOGICRAFT, INC. + 22 COTTON ROAD + NASHUA NH 03063 + US + +00-00-6F (hex) Madge Ltd. +00006F (base 16) Madge Ltd. + Madge House + Maindenhead Berkshire SL6 2HP + GB + +00-00-78 (hex) LABTAM LIMITED +000078 (base 16) LABTAM LIMITED + 43 MALCOLM ROAD P.O. BOX297 + + AU + +00-00-5A (hex) SysKonnect GmbH +00005A (base 16) SysKonnect GmbH + SIEMENSSTRAßE 23 + + DE + +00-00-5B (hex) ELTEC ELEKTRONIK AG +00005B (base 16) ELTEC ELEKTRONIK AG + Galileo-Galilei-Strasse 11 + + DE + +00-00-71 (hex) ADRA SYSTEMS INC. +000071 (base 16) ADRA SYSTEMS INC. + 59 TECHNOLOGY DRIVE + LOWELL MA 01851 + US + +00-00-73 (hex) SIECOR CORPORATION +000073 (base 16) SIECOR CORPORATION + P.O. BOX 13625 + RESEARCH TRIANGLE PK NC 27709 + US + +00-00-B9 (hex) MCDONNELL DOUGLAS COMPUTER SYS +0000B9 (base 16) MCDONNELL DOUGLAS COMPUTER SYS + DIV MCDONNELL DOUGLAS INF SYS + ENGLAND + GB + +00-00-BF (hex) SYMMETRIC COMPUTER SYSTEMS +0000BF (base 16) SYMMETRIC COMPUTER SYSTEMS + 1620 OAKLAND ROAD SUITE D-200 + SAN JOSE CA 95131 + US + +00-00-2D (hex) CHROMATICS INC +00002D (base 16) CHROMATICS INC + 2558 MOUNTAIN INDUSTRIAL BLVD + TUCKER GA 30084 + US + +00-00-18 (hex) WEBSTER COMPUTER CORPORATION +000018 (base 16) WEBSTER COMPUTER CORPORATION + 16040 REDWOOD LODGE ROAD + LOS GATOS CA 95033-9260 + US + +00-00-C8 (hex) ALTOS COMPUTER SYSTEMS +0000C8 (base 16) ALTOS COMPUTER SYSTEMS + 2641 ORCHARD PARKWAY + SAN JOSE CA 95134 + US + +00-00-D5 (hex) MICROGNOSIS INTERNATIONAL +0000D5 (base 16) MICROGNOSIS INTERNATIONAL + 63 QUEEN VICTORIA STREET + UNITED KINGDOM + GB + +00-00-3A (hex) CHYRON CORPORATION +00003A (base 16) CHYRON CORPORATION + 265 SPAGNOLI ROAD + MELVILLE NY 11747 + US + +00-00-59 (hex) Hellige GMBH +000059 (base 16) Hellige GMBH + Heinrich-von-Stephan-Str. 4 + West Gernany + DE + +00-00-69 (hex) CONCORD COMMUNICATIONS INC +000069 (base 16) CONCORD COMMUNICATIONS INC + 753 FOREST STREET + MARLBOROUGH MA 01752 + US + +00-00-E7 (hex) Star Gate Technologies +0000E7 (base 16) Star Gate Technologies + 29300 Aurora Road + Solon OH 44139 + US + +00-00-4D (hex) DCI CORPORATION +00004D (base 16) DCI CORPORATION + 64J PRINCETON-HIGHTSTOWN RD + PRINCETON JUNCTION NJ 08550 + US + +00-00-23 (hex) ABB INDUSTRIAL SYSTEMS AB +000023 (base 16) ABB INDUSTRIAL SYSTEMS AB + DEPT. SEISY/LKSB + + SE + +00-00-BE (hex) THE NTI GROUP +0000BE (base 16) THE NTI GROUP + 4701 PATRICK HENRY DRIVE + SANTA CLARA CA 95054 + US + +00-00-D9 (hex) NIPPON TELEGRAPH & TELEPHONE +0000D9 (base 16) NIPPON TELEGRAPH & TELEPHONE + CORPORATION (NTT) + TOKYO 100-8116 + JP + +00-00-80 (hex) CRAY COMMUNICATIONS A/S +000080 (base 16) CRAY COMMUNICATIONS A/S + SMEDEHOLM 12-14 + + DK + +08-00-2A (hex) MOSAIC TECHNOLOGIES INC. +08002A (base 16) MOSAIC TECHNOLOGIES INC. + 47 MANNING ROAD + BILLERICA MA 01821-3970 + US + +08-00-89 (hex) Kinetics +080089 (base 16) Kinetics + + Walnut Creek CA + US + +08-00-86 (hex) KONICA MINOLTA HOLDINGS, INC. +080086 (base 16) KONICA MINOLTA HOLDINGS, INC. + 1-6-1, Marunouchi, + Tokyo 100-0005 + JP + +08-00-83 (hex) Seiko Instruments Inc. +080083 (base 16) Seiko Instruments Inc. + 8, Nakase 1-chome Mihama-ku + Chiba-shi Chiba 261-8507 + JP + +08-00-61 (hex) JAROGATE LTD. +080061 (base 16) JAROGATE LTD. + 197-213 LYHAM ROAD + UNITED KINGDOM + GB + +08-00-5F (hex) SABER TECHNOLOGY CORP. +08005F (base 16) SABER TECHNOLOGY CORP. + 2381 BERING DRIVE + SAN JOSE CA 95131-1125 + US + +08-00-58 (hex) SYSTEMS CONCEPTS +080058 (base 16) SYSTEMS CONCEPTS + 520 THIRD STREET + SAN FRANCISCO CA 94107 + US + +08-00-49 (hex) UNIVATION +080049 (base 16) UNIVATION + 1037 NORTH FAIR OAKS AVE. + SUNNYVALE CA 94089 + US + +08-00-24 (hex) 10NET COMMUNICATIONS/DCA +080024 (base 16) 10NET COMMUNICATIONS/DCA + 7777 WASHINGTON VILLAGE DR. + DAYTON OH 45459-3957 + US + +08-00-22 (hex) NBI INC. +080022 (base 16) NBI INC. + 3450 MITCHELL LANE + BOULDER CO 80301 + US + +08-00-20 (hex) Oracle Corporation +080020 (base 16) Oracle Corporation + 17 Network Circle + Menlo Park CA 95025 + US + +08-00-1F (hex) SHARP CORPORATION +08001F (base 16) SHARP CORPORATION + ENGINEERING DEPARTMENT 6 + NARA 639-11 + JP + +08-00-14 (hex) EXCELAN +080014 (base 16) EXCELAN + 1599 FLICKINGER AVENUE + SAN JOSE CA 95131 + US + +AA-00-00 (hex) DIGITAL EQUIPMENT CORPORATION +AA0000 (base 16) DIGITAL EQUIPMENT CORPORATION + LKG 1-2/A19 + LITTLETON MA 01460-1289 + US + +AA-00-01 (hex) DIGITAL EQUIPMENT CORPORATION +AA0001 (base 16) DIGITAL EQUIPMENT CORPORATION + LKG 1-2/A19 + LITTLETON MA 01460-1289 + US + +AA-00-02 (hex) DIGITAL EQUIPMENT CORPORATION +AA0002 (base 16) DIGITAL EQUIPMENT CORPORATION + LKG 1-2/A19 + LITTLETON MA 01460-1289 + US + +00-00-07 (hex) XEROX CORPORATION +000007 (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +00-80-1F (hex) KRUPP ATLAS ELECTRONIK GMBH +00801F (base 16) KRUPP ATLAS ELECTRONIK GMBH + P.O. BOX 448545 + + DE + +08-00-06 (hex) SIEMENS AG +080006 (base 16) SIEMENS AG + Siemens IT Solutions and Services, SIS GO QM O + POB 2353 Fuerth 90713 + DE + +04-E0-C4 (hex) TRIUMPH-ADLER AG +04E0C4 (base 16) TRIUMPH-ADLER AG + HUNDINGSTRAßE 11B + + DE + +02-07-01 (hex) RACAL-DATACOM +020701 (base 16) RACAL-DATACOM + LAN INTERNETWORKING DIVISION + BOXBOROUGH MA 01719 + US + +08-00-13 (hex) Exxon +080013 (base 16) Exxon + + + US + +00-DD-08 (hex) UNGERMANN-BASS INC. +00DD08 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +00-00-05 (hex) XEROX CORPORATION +000005 (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +02-1C-7C (hex) PERQ SYSTEMS CORPORATION +021C7C (base 16) PERQ SYSTEMS CORPORATION + 2600 LIBERTY AVENUE + PITTSBURGH PA 15230 + US + +08-00-65 (hex) GENRAD INC. +080065 (base 16) GENRAD INC. + 300 BAKER AVENUE + CONCORD MA 01742 + US + +84-A9-EA (hex) Career Technologies USA +84A9EA (base 16) Career Technologies USA + 9134 Independence Ave + Chatsworth CA 91311 + US + +E4-05-F8 (hex) Delta Innovation Technology Co., Ltd. +E405F8 (base 16) Delta Innovation Technology Co., Ltd. + China Digital Kingdom Building, Chaoyang District + Beijing Beijing 100102 + CN + +00-00-09 (hex) XEROX CORPORATION +000009 (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +00-80-E9 (hex) Madge Ltd. +0080E9 (base 16) Madge Ltd. + Madge House + Maindenhead Berkshire SL6 2HP + GB + +00-40-D6 (hex) LOCAMATION B.V. +0040D6 (base 16) LOCAMATION B.V. + POSTBOX 360 + HOLLAND + NL + +08-00-4B (hex) Planning Research Corp. +08004B (base 16) Planning Research Corp. + 1508 Kennedy Drive + Bellvue NE 68005 + US + +02-AA-3C (hex) OLIVETTI TELECOMM SPA (OLTECO) +02AA3C (base 16) OLIVETTI TELECOMM SPA (OLTECO) + 20300 STEVENS CREEK BLVD. + CUPERTINO CA 95014 + US + +08-00-59 (hex) A/S MYCRON +080059 (base 16) A/S MYCRON + PO BOX 6199 + + NO + +08-00-08 (hex) BOLT BERANEK AND NEWMAN INC. +080008 (base 16) BOLT BERANEK AND NEWMAN INC. + 70 FAWCETT STREET + CAMBRIDGE MA 02138 + US + +F4-74-88 (hex) New H3C Technologies Co., Ltd +F47488 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +FC-C2-33 (hex) ASUSTek COMPUTER INC. +FCC233 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +40-11-75 (hex) IEEE Registration Authority +401175 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +80-31-F0 (hex) Samsung Electronics Co.,Ltd +8031F0 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +28-7F-CF (hex) Intel Corporate +287FCF (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +58-35-26 (hex) DEEPLET TECHNOLOGY CORP +583526 (base 16) DEEPLET TECHNOLOGY CORP + 5F,No.9,Lane235,Pao-Chiao Rd., Hsin-Tien, + New Taipei City 23145 + TW + +34-B5-A3 (hex) CIG SHANGHAI CO LTD +34B5A3 (base 16) CIG SHANGHAI CO LTD + 5th Floor, Building 8 No 2388 Chenhang Road + SHANGHAI 201114 + CN + +6C-1D-EB (hex) u-blox AG +6C1DEB (base 16) u-blox AG + Zuercherstrasse 68 + Thalwil 8800 + CH + +28-52-F9 (hex) Zhongxin Intelligent Times (Shenzhen) Co., Ltd. +2852F9 (base 16) Zhongxin Intelligent Times (Shenzhen) Co., Ltd. + 3rd Floor,Building 46,Cuigang Industrial Zone 5,Fuyong Street,Baoan District + Shenzhen Guangdong 518103 + CN + +B8-F8-53 (hex) Arcadyan Corporation +B8F853 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +E0-D0-83 (hex) Samsung Electronics Co.,Ltd +E0D083 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +74-3C-18 (hex) Taicang T&W Electronics +743C18 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +4C-80-BA (hex) Wuhan Tianyu Information Industry Co., Ltd. +4C80BA (base 16) Wuhan Tianyu Information Industry Co., Ltd. + HUST Industry Park, East-Lake Development Zone + Wuhan Hubei 430223 + CN + +8C-02-FA (hex) COMMANDO Networks Limited +8C02FA (base 16) COMMANDO Networks Limited + Rm407, 4th floor, 3-2 HuaYuan Rd., DaLang Subdistrict, LongHua District + Shenzhen Guangdong 518109 + CN + +F0-26-4C (hex) Sigrist-Photometer AG +F0264C (base 16) Sigrist-Photometer AG + Hofurlistrasse 1 + Ennetbürgen 6373 + CH + +D0-3D-52 (hex) Vaion Limited +D03D52 (base 16) Vaion Limited + The Charter Building, Charter Place + Uxbridge UB8 1JG + GB + +D8-0B-9A (hex) Samsung Electronics Co.,Ltd +D80B9A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +AC-8D-34 (hex) HUAWEI TECHNOLOGIES CO.,LTD +AC8D34 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +64-52-99 (hex) The Chamberlain Group, Inc +645299 (base 16) The Chamberlain Group, Inc + 300 Windsor Drive + Oak Brook IL 60523 + US + +F8-75-A4 (hex) LCFC(HeFei) Electronics Technology co., ltd +F875A4 (base 16) LCFC(HeFei) Electronics Technology co., ltd + YunGu Road 3188-1 + Hefei Anhui 230000 + CN + +00-D2-B1 (hex) TPV Display Technology (Xiamen) Co.,Ltd. +00D2B1 (base 16) TPV Display Technology (Xiamen) Co.,Ltd. + No.1, Xianghai Road, Xiamen Torch Hi-Tech Industrial Development Zone + XM Fujian 361101 + CN + +C0-E4-34 (hex) AzureWave Technology Inc. +C0E434 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +6C-71-0D (hex) Cisco Systems, Inc +6C710D (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +24-6F-8C (hex) Huawei Device Co., Ltd. +246F8C (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +1C-13-86 (hex) Huawei Device Co., Ltd. +1C1386 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +BC-2E-F6 (hex) Huawei Device Co., Ltd. +BC2EF6 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +44-55-C4 (hex) Huawei Device Co., Ltd. +4455C4 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +00-08-29 (hex) TOKYO ELECTRON DEVICE NAGASAKI LIMITED +000829 (base 16) TOKYO ELECTRON DEVICE NAGASAKI LIMITED + 6-42 Tsukuba-machi, Isahaya-shi + Nagasaki Kyushu 854-0065 + JP + +1C-44-55 (hex) Sieb & Meyer AG +1C4455 (base 16) Sieb & Meyer AG + Auf dem Schmaarkamp 21 + Lueneburg 21339 + DE + +80-32-53 (hex) Intel Corporate +803253 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +F8-8A-5E (hex) Texas Instruments +F88A5E (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +5C-E7-A0 (hex) Nokia +5CE7A0 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +E0-1F-88 (hex) Xiaomi Communications Co Ltd +E01F88 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +8C-DC-02 (hex) zte corporation +8CDC02 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +B4-BC-7C (hex) Texas Instruments +B4BC7C (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +E0-AA-B0 (hex) SUNTAILI ENTERPRISE CO. LTD, +E0AAB0 (base 16) SUNTAILI ENTERPRISE CO. LTD, + No. 6 ALY 3,LN 64 XINGFU RD, XINZHUNAG DISTRICT + NEW TAIPEI CITY 242 + TW + +68-39-43 (hex) ittim +683943 (base 16) ittim + 1202, No.6, Zhongguancun South Street, Haidian District, + beijing 100080 + CN + +10-C6-5E (hex) Adapt-IP +10C65E (base 16) Adapt-IP + 1671 Dell Avenue, Suite 130 + Campbell CA 95008-6900 + US + +7C-A7-B0 (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD +7CA7B0 (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD + NO.268? Fuqian Rd, Jutang community, Guanlan Town, Longhua New district + shenzhen guangdong 518000 + CN + +20-31-1C (hex) vivo Mobile Communication Co., Ltd. +20311C (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +10-4F-58 (hex) Aruba, a Hewlett Packard Enterprise Company +104F58 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +B4-E8-42 (hex) Hong Kong Bouffalo Lab Limited +B4E842 (base 16) Hong Kong Bouffalo Lab Limited + RM 1903, 19/F Lee Garden One 33 Hysan Avenue, Causeway Bay + HongKong 999077 + HK + +00-03-CB (hex) SystemGear Co., Ltd. +0003CB (base 16) SystemGear Co., Ltd. + 1-9-14 Edobori + Osaka Nishi-ku 550-0002 + JP + +F0-A7-B2 (hex) FUTABA CORPORATION +F0A7B2 (base 16) FUTABA CORPORATION + 629 Oshiba + Mobara Chiba Prefecture 297-8588 + JP + +60-9B-2D (hex) JMACS Japan Co., Ltd. +609B2D (base 16) JMACS Japan Co., Ltd. + 11F, KM Nishi-Umeda bldg., 7-20-1 Fukushima, Fukushima-ku + Osaka-city Osaka 553-0003 + JP + +14-A3-2F (hex) Huawei Device Co., Ltd. +14A32F (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +04-D3-B5 (hex) Huawei Device Co., Ltd. +04D3B5 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +00-BB-1C (hex) Huawei Device Co., Ltd. +00BB1C (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +80-AC-7C (hex) Sichuan AI-Link Technology Co., Ltd. +80AC7C (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou,Industrial Park + Anzhou,Industrial Park Sichuan 621000 + CN + +DC-4B-FE (hex) Shenzhen Belon Technology CO.,LTD +DC4BFE (base 16) Shenzhen Belon Technology CO.,LTD + Tsinghua Information + Shenzhen Guangdong 518052 + CN + +50-62-55 (hex) IEEE Registration Authority +506255 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +58-D5-0A (hex) Murata Manufacturing Co., Ltd. +58D50A (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +88-A3-03 (hex) Samsung Electronics Co.,Ltd +88A303 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-DE-90 (hex) Samsung Electronics Co.,Ltd +FCDE90 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +18-54-CF (hex) Samsung Electronics Co.,Ltd +1854CF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +80-79-5D (hex) Infinix mobility limited +80795D (base 16) Infinix mobility limited + RMS 05-15, 13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG + HongKong HongKong 999077 + HK + +E8-84-C6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E884C6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +64-2C-AC (hex) HUAWEI TECHNOLOGIES CO.,LTD +642CAC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +08-CC-27 (hex) Motorola Mobility LLC, a Lenovo Company +08CC27 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +04-D3-95 (hex) Motorola Mobility LLC, a Lenovo Company +04D395 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +E0-98-06 (hex) Espressif Inc. +E09806 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +F4-CF-A2 (hex) Espressif Inc. +F4CFA2 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +F8-1E-6F (hex) EBG compleo GmbH +F81E6F (base 16) EBG compleo GmbH + Oberste-Wilms-Straße 15a + Dortmund Nordrhein-Westfalen 44309 + DE + +F0-A3-5A (hex) Apple, Inc. +F0A35A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-83-73 (hex) Apple, Inc. +608373 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-AD-8D (hex) Apple, Inc. +84AD8D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +74-42-8B (hex) Apple, Inc. +74428B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-91-38 (hex) Amazon Technologies Inc. +149138 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +6C-41-0E (hex) Cisco Systems, Inc +6C410E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +6C-31-0E (hex) Cisco Systems, Inc +6C310E (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +28-77-F1 (hex) Apple, Inc. +2877F1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-E7-7D (hex) Texas Instruments +A8E77D (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +DC-54-3D (hex) ITEL MOBILE LIMITED +DC543D (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +0C-84-47 (hex) Fiberhome Telecommunication Technologies Co.,LTD +0C8447 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +9C-6B-72 (hex) Realme Chongqing MobileTelecommunications Corp Ltd +9C6B72 (base 16) Realme Chongqing MobileTelecommunications Corp Ltd + No.24 Nichang Boulevard, Huixing Block, Yubei District, Chongqing. + Chongqing China 401120 + CN + +50-C6-AD (hex) Fiberhome Telecommunication Technologies Co.,LTD +50C6AD (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +74-8A-28 (hex) HMD Global Oy +748A28 (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +D4-24-93 (hex) GW Technologies Co.,Ltd +D42493 (base 16) GW Technologies Co.,Ltd + Building 16,No.8,Heying Road,Changping District + Beijing Beijing 102200 + CN + +00-23-E6 (hex) Innovation Farm, Inc. +0023E6 (base 16) Innovation Farm, Inc. + 47-8, Hasunuma-cho + Itabashi-ku Tokyo 174-8580 + JP + +EC-A9-40 (hex) ARRIS Group, Inc. +ECA940 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +FC-85-96 (hex) Axonne Inc. +FC8596 (base 16) Axonne Inc. + 1290 Kifer Rd. #301 + Sunnyvale CA 94086 + US + +5C-B4-E2 (hex) Inspur Software Group Ltd. +5CB4E2 (base 16) Inspur Software Group Ltd. + No. 1036, Langchao Road + Jinan Shandong 250101 + CN + +3C-51-0E (hex) Cisco Systems, Inc +3C510E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D8-AE-D0 (hex) Shanghai Engineering Science & Technology Co.,LTD CGNPC +D8AED0 (base 16) Shanghai Engineering Science & Technology Co.,LTD CGNPC + No.1588, Rd Zixing + Shanghai Shanghai 200241 + CN + +E0-85-9A (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +E0859A (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District, + Shenzhen Guangdong 518000 + CN + +0C-42-A1 (hex) Mellanox Technologies, Inc. +0C42A1 (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +B4-7A-F1 (hex) Hewlett Packard Enterprise +B47AF1 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +34-9F-7B (hex) CANON INC. +349F7B (base 16) CANON INC. + 30-2 Shimomaruko 3-chome, + Ohta-ku Tokyo 146-8501 + JP + +F4-D9-C6 (hex) UNIONMAN TECHNOLOGY CO.,LTD +F4D9C6 (base 16) UNIONMAN TECHNOLOGY CO.,LTD + No.5,Huitai Road,Huinan High-Tech Park,Huiao Highway + Huizhou Guangdong 516025 + CN + +34-F1-50 (hex) Hui Zhou Gaoshengda Technology Co.,LTD +34F150 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +CC-52-89 (hex) SHENZHEN OPTFOCUS TECHNOLOGY.,LTD +CC5289 (base 16) SHENZHEN OPTFOCUS TECHNOLOGY.,LTD + Floor 3, Building No.7,Tangtou 3rd Industrial Park,Shiyan Street of BaoAn District + ShenZhen 518000 + CN + +CC-5D-78 (hex) JTD Consulting +CC5D78 (base 16) JTD Consulting + 92 King Street South, Suite 200 + Waterloo Ontario N2J 1P5 + CA + +BC-F9-F2 (hex) TEKO +BCF9F2 (base 16) TEKO + Prospect Pobedy, 19 + Kazan Republic of Tatarstan 420138 + RU + +00-0E-A4 (hex) Quantum Corp. +000EA4 (base 16) Quantum Corp. + 8560 Upland Dr. + Englewood CA 80112 + US + +00-50-84 (hex) Quantum Corp. +005084 (base 16) Quantum Corp. + 8560 Upland Dr. + Englewood CO 80112 + US + +80-9F-9B (hex) Sichuan AI-Link Technology Co., Ltd. +809F9B (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou,Industrial Park + Anzhou,Industrial Park Sichuan 621000 + CN + +A8-2B-CD (hex) HUAWEI TECHNOLOGIES CO.,LTD +A82BCD (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +48-DC-2D (hex) HUAWEI TECHNOLOGIES CO.,LTD +48DC2D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +AC-EB-51 (hex) Universal Electronics, Inc. +ACEB51 (base 16) Universal Electronics, Inc. + 201 E. Sandpointe Ave + Santa Ana CA 92707 + US + +60-10-A2 (hex) Crompton Instruments +6010A2 (base 16) Crompton Instruments + 12 Freebournes Road + Witham Essex CM8 3AH + GB + +C4-B2-39 (hex) Cisco Systems, Inc +C4B239 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B0-A4-54 (hex) Tripwire Inc. +B0A454 (base 16) Tripwire Inc. + 308 SW 2nd Avenue Suite 400 + Portland OR 97204 + US + +64-90-C1 (hex) Beijing Xiaomi Mobile Software Co., Ltd +6490C1 (base 16) Beijing Xiaomi Mobile Software Co., Ltd + The Rainbow City Office Building, 68 Qinghe Middle Street Haidian District + Beijing Beijing 100085 + CN + +CC-5C-DE (hex) China Mobile Group Device Co.,Ltd. +CC5CDE (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +60-CE-86 (hex) Sercomm Corporation. +60CE86 (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +4C-4F-EE (hex) OnePlus Technology (Shenzhen) Co., Ltd +4C4FEE (base 16) OnePlus Technology (Shenzhen) Co., Ltd + 18C02, 18C03, 18C04 ,18C05,TAIRAN BUILDING, + Shenzhen Guangdong 518000 + CN + +4C-E1-75 (hex) Cisco Systems, Inc +4CE175 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A8-24-B8 (hex) Nokia +A824B8 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +00-0C-E6 (hex) Fortinet Inc. +000CE6 (base 16) Fortinet Inc. + 899 Kifer Road + Sunnyvale CA 94086 + US + +90-55-DE (hex) Fiberhome Telecommunication Technologies Co.,LTD +9055DE (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +E8-91-0F (hex) Fiberhome Telecommunication Technologies Co.,LTD +E8910F (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +D0-05-E4 (hex) Huawei Device Co., Ltd. +D005E4 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +30-AA-E4 (hex) Huawei Device Co., Ltd. +30AAE4 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +14-AB-56 (hex) WUXI FUNIDE DIGITAL CO.,LTD +14AB56 (base 16) WUXI FUNIDE DIGITAL CO.,LTD + No. 38 East Chunhui Road, Xishan Economic & Technology Development Zone + WUXI JIANGSU 214101 + CN + +E8-D8-D1 (hex) HP Inc. +E8D8D1 (base 16) HP Inc. + 10300 Energy Dr + Spring TX 77389 + US + +28-CD-C4 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +28CDC4 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +00-0C-DF (hex) JAI Manufacturing +000CDF (base 16) JAI Manufacturing + 2960-14 Uenojo Nishikata + Kushima Miyazaki 888-0004 + JP + +2C-91-AB (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +2C91AB (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +80-7B-3E (hex) Samsung Electronics Co.,Ltd +807B3E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F8-F1-E6 (hex) Samsung Electronics Co.,Ltd +F8F1E6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +88-A9-B7 (hex) Apple, Inc. +88A9B7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +EC-CE-D7 (hex) Apple, Inc. +ECCED7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-EB-62 (hex) Murata Manufacturing Co., Ltd. +48EB62 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +5C-E1-76 (hex) Cisco Systems, Inc +5CE176 (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +AC-90-85 (hex) Apple, Inc. +AC9085 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-48-ED (hex) Dell Inc. +3448ED (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +3C-57-31 (hex) Cisco Systems, Inc +3C5731 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +6C-55-E8 (hex) Technicolor CH USA Inc. +6C55E8 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +9C-FC-E8 (hex) Intel Corporate +9CFCE8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +34-2F-BD (hex) Nintendo Co.,Ltd +342FBD (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +A0-2D-13 (hex) AirTies Wireless Networks +A02D13 (base 16) AirTies Wireless Networks + Esentepe Mah., Kore ?ehitleri Cad. + Istanbul ?i?li 34360 + TR + +84-68-C8 (hex) TOTOLINK TECHNOLOGY INT‘L LIMITED +8468C8 (base 16) TOTOLINK TECHNOLOGY INT‘L LIMITED + ROOM 702,7/F SPA CENTER NO 53055 LOCKHART ROAD + WAN CHAI 999077 + HK + +9C-28-F7 (hex) Xiaomi Communications Co Ltd +9C28F7 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +10-52-1C (hex) Espressif Inc. +10521C (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +6C-42-AB (hex) Subscriber Networks, Inc. +6C42AB (base 16) Subscriber Networks, Inc. + 148 W. State Street + Kennett Square PA 19348 + US + +64-F6-F7 (hex) Anhui Dynamic Power Co., Ltd. +64F6F7 (base 16) Anhui Dynamic Power Co., Ltd. + NO.20 Jinniu Mid Road, + Xuancheng Anhui 242100 + CN + +94-1C-56 (hex) Actiontec Electronics, Inc +941C56 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +D8-0B-CB (hex) Telink Semiconductor (Shanghai) Co., Ltd. +D80BCB (base 16) Telink Semiconductor (Shanghai) Co., Ltd. + No. 1500 Zuchongzhi Rd, Building #3 + Shanghai 201203 + CN + +F0-F0-A4 (hex) Amazon Technologies Inc. +F0F0A4 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +C0-D6-82 (hex) Arista Networks +C0D682 (base 16) Arista Networks + 5453 Great America Parkway + Santa Clara CA 95054 + US + +CC-2D-1B (hex) SFR +CC2D1B (base 16) SFR + 12 rue jean-philippe Rameau CS 80001 + La plaine saint denis FRANCE 93634 + FR + +80-E5-40 (hex) ARRIS Group, Inc. +80E540 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-0D-B4 (hex) Stormshield +000DB4 (base 16) Stormshield + 2-10 rue Marceau + ISSY LES MOULINEAUX 92130 + FR + +2C-F0-5D (hex) Micro-Star INTL CO., LTD. +2CF05D (base 16) Micro-Star INTL CO., LTD. + No.69, Lide St., + New Taipei City Taiwan 235 + TW + +94-3B-B0 (hex) New H3C Technologies Co., Ltd +943BB0 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +90-43-E2 (hex) Cornami, Inc +9043E2 (base 16) Cornami, Inc + 300 Orchard City Dr, Suite 131 + Campbell CA 95008 + US + +80-30-49 (hex) Liteon Technology Corporation +803049 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +E8-49-43 (hex) YUGE Information technology Co. Ltd +E84943 (base 16) YUGE Information technology Co. Ltd + Room 303, Building No. 6, ShengRong Rd. 88, Pudong, Shanghai + Shanghai 201203 + CN + +50-14-08 (hex) AiNET +501408 (base 16) AiNET + 11700 MONTGOMERY RD + BELTSVILLE MD 20705-1159 + US + +28-9A-F7 (hex) ADVA Optical Networking Ltd. +289AF7 (base 16) ADVA Optical Networking Ltd. + ADVAntage House + York YO30 4RY + GB + +B0-B1-94 (hex) zte corporation +B0B194 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +10-C3-AB (hex) HUAWEI TECHNOLOGIES CO.,LTD +10C3AB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +28-11-EC (hex) HUAWEI TECHNOLOGIES CO.,LTD +2811EC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E4-26-86 (hex) DWnet Technologies(Suzhou) Corporation +E42686 (base 16) DWnet Technologies(Suzhou) Corporation + No.8,Tangzhuang Road, Suzhou Industrial Park, Jiangsu, China + Suzhou 21500 + CN + +00-69-2D (hex) Sunnovo International Limited +00692D (base 16) Sunnovo International Limited + 1717 Haitai Building + Beijing Beijing 100083 + CN + +38-EB-47 (hex) HUAWEI TECHNOLOGIES CO.,LTD +38EB47 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +0C-37-96 (hex) BIZLINK TECHNOLOGY, INC. +0C3796 (base 16) BIZLINK TECHNOLOGY, INC. + 47211 BAYSIDE PARKWAY + Fremont CA 94538 + US + +F4-03-2A (hex) Amazon Technologies Inc. +F4032A (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +14-77-40 (hex) Huawei Device Co., Ltd. +147740 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +B4-15-7E (hex) Celona Inc. +B4157E (base 16) Celona Inc. + 10061, Bubb Road Suite 300 + Cupertino CA 95014 + US + +AC-CB-51 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +ACCB51 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +18-D9-8F (hex) Huawei Device Co., Ltd. +18D98F (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +64-5E-2C (hex) IRay Technology Co., Ltd. +645E2C (base 16) IRay Technology Co., Ltd. + 11th Guiyang St., + Yantai Shandong 264000 + CN + +00-E0-EC (hex) CELESTICA INC. +00E0EC (base 16) CELESTICA INC. + 1900-5140 Yonge Street PO Box 42 + Toronto Ontario M2N 6L7 + CA + +70-38-11 (hex) Siemens Mobility Limited +703811 (base 16) Siemens Mobility Limited + 17 Langley Park Way + Chippenham Wiltshire SN15 1GG + GB + +64-62-66 (hex) IEEE Registration Authority +646266 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +48-7A-F6 (hex) NCS ELECTRICAL SDN BHD +487AF6 (base 16) NCS ELECTRICAL SDN BHD + NO. 20, 22, 24, 26, JALAN 1/3, RAWANG INTEGRATED INDUSTRIAL PARK, 48000 Rawang Selangor, MALAYSIA + RAWANG SELANGOR 48000 + MY + +48-6E-70 (hex) Zhejiang Tmall Technology Co., Ltd. +486E70 (base 16) Zhejiang Tmall Technology Co., Ltd. + Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District, Shenzhen Guangdong province + Shenzhen GuangDong 518000 + CN + +60-1D-9D (hex) Sichuan AI-Link Technology Co., Ltd. +601D9D (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou, Industrial Park + Mianyang Sichuan 622650 + CN + +D8-5F-77 (hex) Telink Semiconductor (Shanghai) Co., Ltd. +D85F77 (base 16) Telink Semiconductor (Shanghai) Co., Ltd. + No. 1500 Zuchongzhi Rd, Building #3 + Shanghai 201203 + CN + +2C-97-ED (hex) Sony Imaging Products & Solutions Inc. +2C97ED (base 16) Sony Imaging Products & Solutions Inc. + konan 1-7-1 + minato-ku Tokyo 108-0075 + JP + +20-82-6A (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +20826A (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +B8-90-47 (hex) Apple, Inc. +B89047 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-9C-4A (hex) Apple, Inc. +909C4A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-8C-43 (hex) Apple, Inc. +908C43 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-8A-6A (hex) AVPro Global Hldgs +188A6A (base 16) AVPro Global Hldgs + 2222 E 52nd Steeet N + Sioux Falls SD 57104 + US + +3C-7D-0A (hex) Apple, Inc. +3C7D0A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D4-8A-39 (hex) Samsung Electronics Co.,Ltd +D48A39 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E4-F3-C4 (hex) Samsung Electronics Co.,Ltd +E4F3C4 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +9C-2F-4E (hex) zte corporation +9C2F4E (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +F0-10-90 (hex) New H3C Technologies Co., Ltd +F01090 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +08-BF-A0 (hex) Samsung Electronics Co.,Ltd +08BFA0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +70-1F-3C (hex) Samsung Electronics Co.,Ltd +701F3C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +20-50-E7 (hex) AMPAK Technology,Inc. +2050E7 (base 16) AMPAK Technology,Inc. + 3F, No.15-1 Zhonghua Road, Hsinchu Industrail Park, Hukou, + Hsinchu Hsinchu,Taiwan R.O.C. 30352 + TW + +D8-A8-C8 (hex) zte corporation +D8A8C8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +38-22-E2 (hex) HP Inc. +3822E2 (base 16) HP Inc. + 10300 Energy Dr + Spring TX 77389 + US + +08-C0-EB (hex) Mellanox Technologies, Inc. +08C0EB (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +E4-E1-12 (hex) Texas Instruments +E4E112 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +34-14-B5 (hex) Texas Instruments +3414B5 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +D0-03-EB (hex) Texas Instruments +D003EB (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +94-DB-56 (hex) Sony Home Entertainment&Sound Products Inc +94DB56 (base 16) Sony Home Entertainment&Sound Products Inc + Sony City Osaki 2-10-1 Osaki Shinagawa-ku + Tokyo Japan 141-8610 + JP + +88-9E-68 (hex) Technicolor CH USA Inc. +889E68 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +64-09-AC (hex) TCT mobile ltd +6409AC (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +74-3A-EF (hex) Kaonmedia CO., LTD. +743AEF (base 16) Kaonmedia CO., LTD. + 884-3, Seongnam-daero, Bundang-gu + Seongnam-si Gyeonggi-do 13517 + KR + +54-48-E6 (hex) Beijing Xiaomi Mobile Software Co.,Ltd +5448E6 (base 16) Beijing Xiaomi Mobile Software Co.,Ltd + Xiaomi Campus, No. 33 Xi erqi Middle Road, Haidian District + Beijing Beijing 100085 + CN + +18-9E-2C (hex) Huawei Device Co., Ltd. +189E2C (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +5C-55-78 (hex) iryx corp +5C5578 (base 16) iryx corp + 14 Hughes + Irvine CA 92618 + US + +6C-F7-12 (hex) Nokia +6CF712 (base 16) Nokia + Karaportti 3 + Espoo Finland 02610 + FI + +4C-C5-3E (hex) Zyxel Communications Corporation +4CC53E (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +90-56-FC (hex) TECNO MOBILE LIMITED +9056FC (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +B8-63-92 (hex) GUANGDONG GENIUS TECHNOLOGY CO., LTD. +B86392 (base 16) GUANGDONG GENIUS TECHNOLOGY CO., LTD. + No.168, Middle Road Of East Gate + Xiaobian Community Chang'an Town 523851 + CN + +68-B9-D3 (hex) Shenzhen Trolink Technology CO, LTD +68B9D3 (base 16) Shenzhen Trolink Technology CO, LTD + 201 B building 4 shijie, Chashu industry 505 block, Baoan airport Sanwei community, Hangcheng street Baoan area. + Shenzhen GuangDong 518000 + CN + +B8-C6-AA (hex) Earda Technologies co Ltd +B8C6AA (base 16) Earda Technologies co Ltd + Block A,Lianfeng Creative Park, #2 Jisheng Rd., Nansha District + Guangzhou Guangdong 511455 + CN + +54-AE-D0 (hex) DASAN Networks, Inc. +54AED0 (base 16) DASAN Networks, Inc. + DASAN Tower, 49, Daewangpangyo-ro, 644 Beon-gil, Bundang-gu + Seongnam-si Gyeonggi-do 13493 + KR + +10-70-FD (hex) Mellanox Technologies, Inc. +1070FD (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +38-F6-01 (hex) Solid State Storage Technology Corporation +38F601 (base 16) Solid State Storage Technology Corporation + 21F, 392, Ruey Kuang Road, Neihu + Taipei 11492 + TW + +40-DE-AD (hex) Juniper Networks +40DEAD (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +40-F5-20 (hex) Espressif Inc. +40F520 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +78-AA-82 (hex) New H3C Technologies Co., Ltd +78AA82 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +20-6C-8A (hex) Extreme Networks, Inc. +206C8A (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +34-85-84 (hex) Extreme Networks, Inc. +348584 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +40-18-B1 (hex) Extreme Networks, Inc. +4018B1 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +88-5B-DD (hex) Extreme Networks, Inc. +885BDD (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +98-ED-5C (hex) Tesla,Inc. +98ED5C (base 16) Tesla,Inc. + 3500 Deer Creek Road + Palo Alto CA 94304 + US + +C4-42-68 (hex) CRESTRON ELECTRONICS, INC. +C44268 (base 16) CRESTRON ELECTRONICS, INC. + 15 Volvo Drive + Rockleigh NJ 07647 + US + +54-71-DD (hex) Huawei Device Co., Ltd. +5471DD (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +E4-A7-49 (hex) Palo Alto Networks +E4A749 (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +84-D6-C5 (hex) SolarEdge Technologies +84D6C5 (base 16) SolarEdge Technologies + 1 Abba Eban St. + Herzelia 46725 + IL + +F8-D0-27 (hex) Seiko Epson Corporation +F8D027 (base 16) Seiko Epson Corporation + 2070 Kotobuki Koaka + Matsumoto-shi Nagano-ken 399-8702 + JP + +5C-66-6C (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +5C666C (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +4C-4B-F9 (hex) IEEE Registration Authority +4C4BF9 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +1C-EA-0B (hex) Edgecore Networks Corporation +1CEA0B (base 16) Edgecore Networks Corporation + 1 Creation RD 3. + Hsinchu 30077 + TW + +24-41-8C (hex) Intel Corporate +24418C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +44-EF-BF (hex) China Dragon Technology Limited +44EFBF (base 16) China Dragon Technology Limited + B4 Bldg.Haoshan 1st Industry Park, + Shenzhen Guangdong 518104 + CN + +B8-1F-5E (hex) Apption Labs Limited +B81F5E (base 16) Apption Labs Limited + 7-8 Westbridge Close + Leicester LE3 5LW + GB + +D8-12-65 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +D81265 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +4C-B4-4A (hex) NANOWAVE Technologies Inc. +4CB44A (base 16) NANOWAVE Technologies Inc. + 425 Horner Avenue + Etobicoke Ontario M8W 4W3 + CA + +04-8C-9A (hex) Huawei Device Co., Ltd. +048C9A (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +60-F2-62 (hex) Intel Corporate +60F262 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +EC-3C-BB (hex) Huawei Device Co., Ltd. +EC3CBB (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +8C-3A-7E (hex) Universal Electronics, Inc. +8C3A7E (base 16) Universal Electronics, Inc. + 201 E. Sandpointe Ave + Santa Ana CA 92707 + US + +70-44-1C (hex) SHENZHEN KAIFA TECHNOLOGY CO.,LTD. +70441C (base 16) SHENZHEN KAIFA TECHNOLOGY CO.,LTD. + 7006 Caitian Rd., Futian Dist. + Shen Zhen Guang Dong 518035 + CN + +B4-7C-59 (hex) Jiangsu Hengxin Technology Co.,Ltd. +B47C59 (base 16) Jiangsu Hengxin Technology Co.,Ltd. + No.138 Taodu Road,Yixing city,Jiangsu Province,China + Yixing Jiangsu 214200 + CN + +30-0D-9E (hex) Ruijie Networks Co.,LTD +300D9E (base 16) Ruijie Networks Co.,LTD + 20# Building,Star-net Science Plaza,Juyuanzhou, 618 Jinshan Road + Fuzhou Fujian 350002 + CN + +EC-FA-5C (hex) Beijing Xiaomi Electronics Co., Ltd. +ECFA5C (base 16) Beijing Xiaomi Electronics Co., Ltd. + Building C, QingHe ShunShiJiaYe Technology Park, #66 ZhuFang Rd, HaiDian District + Beijing Beijing 10085 + CN + +F8-B4-6A (hex) Hewlett Packard +F8B46A (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +BC-B0-E7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +BCB0E7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +54-34-EF (hex) HUAWEI TECHNOLOGIES CO.,LTD +5434EF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-D5-A8 (hex) ITEL MOBILE LIMITED +88D5A8 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +20-85-93 (hex) IEEE Registration Authority +208593 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +AC-E3-42 (hex) HUAWEI TECHNOLOGIES CO.,LTD +ACE342 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +90-17-C8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +9017C8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E4-92-2A (hex) DBG HOLDINGS LIMITED +E4922A (base 16) DBG HOLDINGS LIMITED + UNIT D, 6/F., UNISON INDUSTRIAL CENTRE, 27-31 AUPUI WAN STREET, FOTAN, N.T. + Hong Kong 999077 + HK + +2C-64-1F (hex) Vizio, Inc +2C641F (base 16) Vizio, Inc + 39 Tesla + Irvine CA 92618 + US + +20-77-59 (hex) OPTICAL NETWORK VIDEO TECHNOLOGIES (SHENZHEN) CO., LTD. +207759 (base 16) OPTICAL NETWORK VIDEO TECHNOLOGIES (SHENZHEN) CO., LTD. + The 4-6th Floor, No. 59, HuaNing Road, Xinwei Community, Dalang Street, Longhua District + Shenzhen 518000 + CN + +54-E7-D5 (hex) Sun Cupid Technology (HK) LTD +54E7D5 (base 16) Sun Cupid Technology (HK) LTD + Room 1201-3, 12/F., Tower 6 + Tsim Sha Tsui + HK + +18-90-88 (hex) eero inc. +189088 (base 16) eero inc. + 660 3rd Street + San Francisco CA 94107 + US + +4C-56-DF (hex) Targus US LLC +4C56DF (base 16) Targus US LLC + 1211 North Miller Street + Anaheim CA 92806 + US + +24-15-10 (hex) IEEE Registration Authority +241510 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +6C-4D-51 (hex) Shenzhen Ceres Technology Co., Ltd. +6C4D51 (base 16) Shenzhen Ceres Technology Co., Ltd. + #601, Fl6, Bldg F, No.1008  Yangguang Community, Xili, Nanshan + Shenzhen Guangdong 518055 + CN + +88-9D-98 (hex) Allied-telesisK.K. +889D98 (base 16) Allied-telesisK.K. + 7-21-11 Nishi-Gotannda + Shinagawa-ku Tokyo 141-0031 + JP + +DC-F8-B9 (hex) zte corporation +DCF8B9 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +18-BF-1C (hex) Jiangsu Huitong Group Co.,Ltd. +18BF1C (base 16) Jiangsu Huitong Group Co.,Ltd. + No. 24, Block 2, Taohuawu New District + Zhenjiang Jiangsu 212003 + CN + +AC-DE-48 (hex) Private +ACDE48 (base 16) Private + +00-50-C7 (hex) Private +0050C7 (base 16) Private + +00-20-67 (hex) Private +002067 (base 16) Private + +48-01-C5 (hex) OnePlus Technology (Shenzhen) Co., Ltd +4801C5 (base 16) OnePlus Technology (Shenzhen) Co., Ltd + 18C02, 18C03, 18C04 ,18C05,TAIRAN BUILDING, + Shenzhen Guangdong 518000 + CN + +B4-EE-25 (hex) Shenzhen Belon Technology CO.,LTD +B4EE25 (base 16) Shenzhen Belon Technology CO.,LTD + Tsinghua Information + Shenzhen Guangdong 518052 + CN + +C8-2B-96 (hex) Espressif Inc. +C82B96 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +98-52-3D (hex) Sunitec Enterprise Co.,Ltd +98523D (base 16) Sunitec Enterprise Co.,Ltd + 3F.,No.98-1,Mincyuan Rd.Sindian City + Taipei County 231 231141 + CN + +D0-15-A6 (hex) Aruba, a Hewlett Packard Enterprise Company +D015A6 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +00-01-63 (hex) Cisco Systems, Inc +000163 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +60-63-4C (hex) D-Link International +60634C (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +20-5F-3D (hex) Cambridge Communication Systems Ltd +205F3D (base 16) Cambridge Communication Systems Ltd + Victory House, Vision Park, Chivers Way, Histon + Cambridge CB24 9ZR + GB + +04-81-9B (hex) BSkyB Ltd +04819B (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +E0-00-84 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E00084 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +2C-A8-9C (hex) Creatz inc. +2CA89C (base 16) Creatz inc. + 16, Deogyeong-daero 1556beon-gil, Yeongtong-gu + Suwon-si, Gyeonggi-do, 16690 + KR + +4C-DC-0D (hex) Coral Telecom Limited +4CDC0D (base 16) Coral Telecom Limited + E-2, Sector 63 + Noida Uttar Pradesh 201301 + IN + +00-4E-01 (hex) Dell Inc. +004E01 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +C4-E1-A1 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +C4E1A1 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +AC-C3-58 (hex) Continental Automotive Czech Republic s.r.o. +ACC358 (base 16) Continental Automotive Czech Republic s.r.o. + Průmyslová 1851 + Brandýs nad Labem 250 01 + CZ + +3C-EC-EF (hex) Super Micro Computer, Inc. +3CECEF (base 16) Super Micro Computer, Inc. + 980 Rock Ave + San Jose CA 95131 + US + +18-55-E3 (hex) Apple, Inc. +1855E3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-50-EB (hex) Apple, Inc. +E450EB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-64-40 (hex) Apple, Inc. +886440 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-70-C0 (hex) Apple, Inc. +6070C0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-C3-71 (hex) Apple, Inc. +F0C371 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-FF-0A (hex) Wistron Neweb Corporation +64FF0A (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +F0-99-19 (hex) Garmin International +F09919 (base 16) Garmin International + 1200 E. 151st St + Olathe KS 66062 + US + +00-00-DE (hex) CETIA +0000DE (base 16) CETIA + 150 RUE BERTHELOT + + FR + +F4-3E-66 (hex) Bee Computing (HK) Limited +F43E66 (base 16) Bee Computing (HK) Limited + Room 1902, 19/F, Lee Garden One 33 Hysan Avenue, Causeway Bay + Hong Kong 100043 + HK + +DC-39-6F (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +DC396F (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +B4-C4-76 (hex) Wuhan Maritime Communication Research Institute +B4C476 (base 16) Wuhan Maritime Communication Research Institute + No.312 Luoyu road, Hongshan District + Wuhan Hubei 430079 + CN + +68-34-89 (hex) LEA Professional +683489 (base 16) LEA Professional + 635 S. Lafayette Blvd + South Bend IN 46601 + US + +B4-6C-47 (hex) Panasonic Appliances Company +B46C47 (base 16) Panasonic Appliances Company + 2-3-1-2 Noji-higashi + Kusatsu City Shiga 525-8555 + JP + +44-42-2F (hex) TESTOP CO.,LTD. +44422F (base 16) TESTOP CO.,LTD. + 808RM Hanshin IT Tower ,272, Digital-ro + Guro-gu Seoul 08389 + KR + +54-9C-27 (hex) Plasma Cloud Limited +549C27 (base 16) Plasma Cloud Limited + 5/F, Yat Chau Building, 262 Des Voeux Road Central + Hong Kong NA + HK + +D0-4E-50 (hex) Mobiwire Mobiles (NingBo) Co., LTD +D04E50 (base 16) Mobiwire Mobiles (NingBo) Co., LTD + No.999 Dacheng East Road, Fenghua District, Ningbo City , Zhejiang Province, PRC + Ningbo Zhejiang 315500 + CN + +94-BF-80 (hex) zte corporation +94BF80 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +98-7A-14 (hex) Microsoft Corporation +987A14 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +C8-3D-DC (hex) Xiaomi Communications Co Ltd +C83DDC (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +9C-3A-9A (hex) Shenzhen Sundray Technologies Company Limited +9C3A9A (base 16) Shenzhen Sundray Technologies Company Limited + 5th Floor, Block A4, Nanshan ipark,NO.1001 Xue Yuan Road, Nanshan District, Shenzhen 518055, P.R. China + Shenzhen Guangdong 518057 + CN + +B0-B5-E8 (hex) Ruroc LTD +B0B5E8 (base 16) Ruroc LTD + Unit 2, Barnett Way, Barnwood Estate + Gloucester GL4 3RT + GB + +04-D5-90 (hex) Fortinet, Inc. +04D590 (base 16) Fortinet, Inc. + 899 Kifer Road + Sunnyvale null 94086 + US + +54-15-89 (hex) MCS Logic Inc. +541589 (base 16) MCS Logic Inc. + A-1701, Munjeong-dong, SK V1 GL Metro City, 128, Beobwon-ro, Songpa-gu, + seoul seoul 05854 + KR + +84-57-33 (hex) Microsoft Corporation +845733 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND 98052 + US + +00-24-23 (hex) AzureWave Technologies (Shanghai) Inc. +002423 (base 16) AzureWave Technologies (Shanghai) Inc. + NO. 8, LANE 66, CHENGBAO RD. + SHANGHAI 201801 + CN + +8C-59-3C (hex) IEEE Registration Authority +8C593C (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +60-29-D5 (hex) DAVOLINK Inc. +6029D5 (base 16) DAVOLINK Inc. + 112, Beolmal-ro + Dongan-gu, Anyang-si Gyeonggi-do 14057 + KR + +50-97-44 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +509744 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +58-F3-9C (hex) Cisco Systems, Inc +58F39C (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +C4-41-1E (hex) Belkin International Inc. +C4411E (base 16) Belkin International Inc. + 12045 East Waterfront Drive + Playa Vista null 90094 + US + +00-77-E4 (hex) Nokia +0077E4 (base 16) Nokia + Karaportti 3 + Espoo Finland 02610 + FI + +00-AD-63 (hex) Dedicated Micros Malta LTD +00AD63 (base 16) Dedicated Micros Malta LTD + Blb017, Qasam Industrijali Bulebel + ZEJTUN ZTN 3000 + MT + +E4-15-F6 (hex) Texas Instruments +E415F6 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +AC-42-28 (hex) Parta Networks +AC4228 (base 16) Parta Networks + Teknopark Izmir No:38 + URLA IZMIR 35433 + TR + +F4-1D-6B (hex) HUAWEI TECHNOLOGIES CO.,LTD +F41D6B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-EC-9B (hex) Fuzhou Teraway Information Technology Co.,Ltd +7CEC9B (base 16) Fuzhou Teraway Information Technology Co.,Ltd + 2F, Building 5#, No. 59, Yangqi Road, Cangshan District + Fuzhou Fujian 350000 + CN + +CC-90-70 (hex) Cisco Systems, Inc +CC9070 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +28-41-C6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +2841C6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +38-01-18 (hex) ULVAC,Inc. +380118 (base 16) ULVAC,Inc. + 2500 Hagizono + Chigasaki Kanagawa 253-8543 + JP + +14-AD-CA (hex) China Mobile Iot Limited company +14ADCA (base 16) China Mobile Iot Limited company + No. 8 Yangliu North Road, Yubei District, Chongqing, China + Chong Qing Chong Qing 401120 + CN + +80-91-33 (hex) AzureWave Technology Inc. +809133 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +B4-F5-8E (hex) HUAWEI TECHNOLOGIES CO.,LTD +B4F58E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-8F-C1 (hex) DEEPTRACK S.L.U. +C48FC1 (base 16) DEEPTRACK S.L.U. + Avenida de Barajas 32, Parque E. Omega, Edificio A + Alcobendas 28100 + ES + +F8-23-87 (hex) Shenzhen Horn Audio Co.,Ltd. +F82387 (base 16) Shenzhen Horn Audio Co.,Ltd. + NO.6 4th GuiHua road,PingShan, + Shenzhen Guangdong 518118 + CN + +E8-28-C1 (hex) Eltex Enterprise Ltd. +E828C1 (base 16) Eltex Enterprise Ltd. + Okruzhnaya st. 29v + Novosibirsk 630020 + RU + +78-D3-47 (hex) Ericsson AB +78D347 (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +A4-A1-79 (hex) Nanjing dianyan electric power automation co. LTD +A4A179 (base 16) Nanjing dianyan electric power automation co. LTD + No. 29, liuzhou north road, pukou district + Nanjing Jiangsu 210031 + CN + +68-DB-67 (hex) Nantong Coship Electronics Co., Ltd. +68DB67 (base 16) Nantong Coship Electronics Co., Ltd. + No.188 Xinsheng Road + Nantong 226000 + US + +18-19-D6 (hex) Samsung Electronics Co.,Ltd +1819D6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +BC-98-DF (hex) Motorola Mobility LLC, a Lenovo Company +BC98DF (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +70-FC-8F (hex) FREEBOX SAS +70FC8F (base 16) FREEBOX SAS + 16 rue de la Ville l'Eveque + PARIS IdF 75008 + FR + +50-1B-32 (hex) Taicang T&W Electronics +501B32 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +98-0D-67 (hex) Zyxel Communications Corporation +980D67 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +00-02-D8 (hex) BRECIS Communications Corporation +0002D8 (base 16) BRECIS Communications Corporation + 2025 Gateway Place, Suite 132 + San Jose CA 95110 + US + +B0-A6-F5 (hex) Xaptum, Inc. +B0A6F5 (base 16) Xaptum, Inc. + 350 W Ontario ST FL 4 + Chicago IL 60654 + US + +AC-F5-E6 (hex) Cisco Systems, Inc +ACF5E6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +58-A0-23 (hex) Intel Corporate +58A023 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +DC-B0-82 (hex) Nokia +DCB082 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +F8-C3-97 (hex) NZXT Corp. Ltd. +F8C397 (base 16) NZXT Corp. Ltd. + 13164 E. Temple Ave. + City of Industry California 91746 + US + +70-DD-A8 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +70DDA8 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +4C-6F-9C (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +4C6F9C (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +78-2C-29 (hex) New H3C Technologies Co., Ltd +782C29 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +BC-9F-E4 (hex) Aruba, a Hewlett Packard Enterprise Company +BC9FE4 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +70-2E-80 (hex) DIEHL Connectivity Solutions +702E80 (base 16) DIEHL Connectivity Solutions + Stephanstraße 49 + Nürnberg Bayern 90478 + DE + +D4-D2-52 (hex) Intel Corporate +D4D252 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +AC-A4-6E (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +ACA46E (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +C8-B4-22 (hex) ASKEY COMPUTER CORP +C8B422 (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +94-EE-9F (hex) HMD Global Oy +94EE9F (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +DC-2A-A1 (hex) MedHab LLC +DC2AA1 (base 16) MedHab LLC + 3501 North US Highway 67 + San Angelo TX 76905 + US + +E4-F3-E8 (hex) Shenzhen SuperElectron Technology Co.,Ltd. +E4F3E8 (base 16) Shenzhen SuperElectron Technology Co.,Ltd. + 1213-1214, haosheng business center, dongbin road, nanshan street, nanshan district, shenzhen city + Shenzhen Guangdong 518000 + CN + +F4-32-3D (hex) Sichuan tianyi kanghe communications co., LTD +F4323D (base 16) Sichuan tianyi kanghe communications co., LTD + No.198, section 1, xueshan avenue, jinyuan town, dayi county, sichuan province + chengdu sichuan 611330 + CN + +F8-B7-97 (hex) NEC Platforms, Ltd. +F8B797 (base 16) NEC Platforms, Ltd. + 2-3 Kandatsukasamachi + Chiyodaku Tokyo 101-8532 + JP + +B0-AA-D2 (hex) Sichuan tianyi kanghe communications co., LTD +B0AAD2 (base 16) Sichuan tianyi kanghe communications co., LTD + No.198, section 1, xueshan avenue, jinyuan town, dayi county, sichuan province + chengdu sichuan 611330 + CN + +10-93-97 (hex) ARRIS Group, Inc. +109397 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +50-75-F1 (hex) ARRIS Group, Inc. +5075F1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +C4-65-16 (hex) Hewlett Packard +C46516 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +E4-1E-0A (hex) IEEE Registration Authority +E41E0A (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +CC-A1-2B (hex) TCL King Electrical Appliances (Huizhou) Co., Ltd +CCA12B (base 16) TCL King Electrical Appliances (Huizhou) Co., Ltd + 10F, TCL Multimedia Building, TCL International E City, No.1001 Zhongshanyuan Rd., Nanshan District + Shenzhen Guangdong 518052 + CN + +AC-00-D0 (hex) zte corporation +AC00D0 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +E8-C4-17 (hex) Fiberhome Telecommunication Technologies Co.,LTD +E8C417 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +00-1E-A3 (hex) Nokia Danmark A/S +001EA3 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +38-F3-2E (hex) Skullcandy +38F32E (base 16) Skullcandy + 6301 N. LANDMARK DRIVE + Park City 84098 + US + +98-1E-19 (hex) Sagemcom Broadband SAS +981E19 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +84-B8-66 (hex) Beijing XiaoLu technology co. LTD +84B866 (base 16) Beijing XiaoLu technology co. LTD + Room 002, floor 2, building 1, yard 4, BeiTuCheng East Road, ChaoYang district, Beijing + Beijing 100102 + CN + +18-BC-5A (hex) Zhejiang Tmall Technology Co., Ltd. +18BC5A (base 16) Zhejiang Tmall Technology Co., Ltd. + Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District, + Shenzhen Guangdong 518000 + CN + +C4-C1-38 (hex) OWLink Technology Inc +C4C138 (base 16) OWLink Technology Inc + 760 Roosevelt + Irvine CA 92620 + US + +AC-37-C9 (hex) RAID Incorporated +AC37C9 (base 16) RAID Incorporated + 200 Brickstone Square + Andover MA 01810 + US + +20-58-69 (hex) Ruckus Wireless +205869 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +CC-37-AB (hex) Edgecore Networks Corporation +CC37AB (base 16) Edgecore Networks Corporation + 1 Creation Road 3. + Hsinchu Hsinchu 30077 + TW + +90-78-41 (hex) Intel Corporate +907841 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +14-22-DB (hex) eero inc. +1422DB (base 16) eero inc. + 230 9th St. + San Francisco CA 94103 + US + +C8-63-14 (hex) IEEE Registration Authority +C86314 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +24-31-54 (hex) HUAWEI TECHNOLOGIES CO.,LTD +243154 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +2C-58-E8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +2C58E8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +70-CD-91 (hex) TERACOM TELEMATICA S.A +70CD91 (base 16) TERACOM TELEMATICA S.A + RUA AMERICA,1000 + Eldorado do Sul Rio Grande do Sul 92990-000 + BR + +2C-18-75 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +2C1875 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +D0-6E-DE (hex) Sagemcom Broadband SAS +D06EDE (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +18-39-9C (hex) Skorpios Technologies +18399C (base 16) Skorpios Technologies + 7401 Snaproll St NE + Albuquerque NM 87109 + US + +94-C2-BD (hex) TECNOBIT +94C2BD (base 16) TECNOBIT + C/ FUDRE, 18 + VALDEPEÑAS CIUDAD REAL 13300 + ES + +48-83-B4 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +4883B4 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +84-B8-B8 (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +84B8B8 (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan + Wuhan Hubei 430000 + CN + +D0-41-C9 (hex) Fiberhome Telecommunication Technologies Co.,LTD +D041C9 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +E8-01-8D (hex) Fiberhome Telecommunication Technologies Co.,LTD +E8018D (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +10-A3-B8 (hex) Iskratel d.o.o. +10A3B8 (base 16) Iskratel d.o.o. + Ljubljanska cesta 24a + Kranj 4000 + SI + +E8-EC-A3 (hex) Dongguan Liesheng Electronic Co.Ltd +E8ECA3 (base 16) Dongguan Liesheng Electronic Co.Ltd + 13th Floor South Building, Gosun Science Park, Hongtu Rd + Dongguan Dongguan 523073 + CN + +08-A6-BC (hex) Amazon Technologies Inc. +08A6BC (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +70-1E-68 (hex) Hanna Instruments, Inc. +701E68 (base 16) Hanna Instruments, Inc. + 584 Park East Dr. + Woonsocket RI 02895 + US + +1C-B3-E9 (hex) Shenzhen Zhongke United Communication Technology +1CB3E9 (base 16) Shenzhen Zhongke United Communication Technology + 6C jiajiahao commercial building, Shennan avenue + Shenzhen Guangdong 518000 + CN + +8C-96-5F (hex) Shandong Zhongan Technology Co., Ltd. +8C965F (base 16) Shandong Zhongan Technology Co., Ltd. + North of Kejia Road, East District, Jinan High-tech Zone + Jinan Shandong 250100 + CN + +C0-07-4A (hex) Brita GmbH +C0074A (base 16) Brita GmbH + Heinrich-Hertz-Str. 4 + Taunusstein 65232 + DE + +E8-B2-FE (hex) HUMAX Co., Ltd. +E8B2FE (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +80-FD-7A (hex) BLU Products Inc +80FD7A (base 16) BLU Products Inc + 10814 NW 33rd Street + Miami FL 33172 + US + +00-17-FA (hex) Microsoft Corporation +0017FA (base 16) Microsoft Corporation + One Microsoft Way + Redmond Washington 98052-6399 + US + +94-16-25 (hex) Apple, Inc. +941625 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-3B-30 (hex) duagon AG +543B30 (base 16) duagon AG + Riedstrasse 12 + Zürich Dietikon 8953 + CH + +40-F2-1C (hex) DASAN Zhone Solutions +40F21C (base 16) DASAN Zhone Solutions + 7195 Oakport Street + Oakland CA 94621 + US + +B0-BB-8B (hex) WAVETEL TECHNOLOGY LIMITED +B0BB8B (base 16) WAVETEL TECHNOLOGY LIMITED + ROOM 1611B, 16/F, HO KING COMMERCIAL CENTRE, 2-16 FAYUEN STREET, MONGKOK, KOWLOON + HONGKONG 999077 + CN + +34-A8-EB (hex) Apple, Inc. +34A8EB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +94-BF-C4 (hex) Ruckus Wireless +94BFC4 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +A4-83-E7 (hex) Apple, Inc. +A483E7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-AF-E7 (hex) Apple, Inc. +F4AFE7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-88-FD (hex) Apple, Inc. +AC88FD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +50-3E-7C (hex) LeiShen Intelligent System Co.Ltd +503E7C (base 16) LeiShen Intelligent System Co.Ltd + 4th Floor,No.1 Commercial Building,Cultural Center,Tanggang Road,Tanggang Community,Shajing Street,Baoan District + Shenzhen Guangdong 518104 + CN + +24-58-6E (hex) zte corporation +24586E (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +B4-A3-05 (hex) XIAMEN YAXON NETWORK CO., LTD. +B4A305 (base 16) XIAMEN YAXON NETWORK CO., LTD. + 46#,Guanri Road, Software Park II + Xiamen Fujian 361008 + CN + +80-3E-48 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +803E48 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +24-3F-30 (hex) Oxygen Broadband s.a. +243F30 (base 16) Oxygen Broadband s.a. + 2 Messogeion ave., Athens Tower + Athens Attiki 11527 + GR + +3C-91-80 (hex) Liteon Technology Corporation +3C9180 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +20-32-6C (hex) Samsung Electronics Co.,Ltd +20326C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +64-89-F1 (hex) Samsung Electronics Co.,Ltd +6489F1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +20-34-FB (hex) Xiaomi Communications Co Ltd +2034FB (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +A8-9C-ED (hex) Xiaomi Communications Co Ltd +A89CED (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +6C-A6-04 (hex) ARRIS Group, Inc. +6CA604 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +5C-F9-DD (hex) Dell Inc. +5CF9DD (base 16) Dell Inc. + One Dell way + Round Rock 78682 + US + +D0-EC-35 (hex) Cisco Systems, Inc +D0EC35 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +10-AE-60 (hex) Private +10AE60 (base 16) Private + +00-25-DF (hex) Private +0025DF (base 16) Private + +BC-CF-4F (hex) Zyxel Communications Corporation +BCCF4F (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +C0-10-B1 (hex) HMD Global Oy +C010B1 (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +90-89-5F (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +90895F (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Gaoxin 2 Road, Free Trade Zone,Weifang,Shandong,261205,P.R.China + Weifang Shandong 261205 + CN + +48-D8-45 (hex) Shenzhen Mainuoke Electronics Co., Ltd +48D845 (base 16) Shenzhen Mainuoke Electronics Co., Ltd + 9th Floor, Hengtemei Building, Buji + Shenzhen Guangdong 518000 + CN + +0C-E0-41 (hex) iDruide +0CE041 (base 16) iDruide + 19 Rue de la Turbie + MONACO 98000 + MC + +B8-8F-B4 (hex) JABIL CIRCUIT ITALIA S.R.L +B88FB4 (base 16) JABIL CIRCUIT ITALIA S.R.L + via andrea appiani 12 + milano 20121 + IT + +00-52-C2 (hex) peiker acustic GmbH +0052C2 (base 16) peiker acustic GmbH + Max-Planck-Strasse 28-32 + Friedrichsdorf 61381 + DE + +8C-53-D2 (hex) China Mobile Group Device Co.,Ltd. +8C53D2 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +D4-53-83 (hex) Murata Manufacturing Co., Ltd. +D45383 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +A0-42-46 (hex) IT Telecom Co., Ltd. +A04246 (base 16) IT Telecom Co., Ltd. + 517 TheOvalley 555-9 Hogye-dong, Dong An-gu + Anyang-si Gyeonggi-do 14117 + KR + +0C-F4-75 (hex) Zliide Technologies ApS +0CF475 (base 16) Zliide Technologies ApS + Sverigesgade 6 + Aarhus 8000 + DK + +68-FF-7B (hex) TP-LINK TECHNOLOGIES CO.,LTD. +68FF7B (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +80-8F-1D (hex) TP-LINK TECHNOLOGIES CO.,LTD. +808F1D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +00-12-4E (hex) XAC AUTOMATION CORP. +00124E (base 16) XAC AUTOMATION CORP. + 4F, 30 Industry E. Road IX + Hsin-Chu 300 + US + +88-E0-34 (hex) Shinwa industries(China) ltd. +88E034 (base 16) Shinwa industries(China) ltd. + No.26,Huifeng West 2 Road,Zhongkai High-tech Zone + Huizhou Guangdong 516006 + CN + +48-BD-0E (hex) Quanta Storage Inc. +48BD0E (base 16) Quanta Storage Inc. + 3F. No.188, Wenhua 2nd Rd + Taoyuan City Guishan District 33383 + TW + +00-0F-69 (hex) SEW Eurodrive GmbH & Co. KG +000F69 (base 16) SEW Eurodrive GmbH & Co. KG + Ernst Blickle Str. 42 + Bruchsal 76646 + DE + +E4-58-E7 (hex) Samsung Electronics Co.,Ltd +E458E7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-10-4A (hex) The Parvus Corporation +00104A (base 16) The Parvus Corporation + 3222 S Washington St. + Salt Lake City UT 84115 + US + +38-00-25 (hex) Intel Corporate +380025 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +D0-58-C0 (hex) Qingdao Haier Multimedia Limited. +D058C0 (base 16) Qingdao Haier Multimedia Limited. + Pingban Building, Haier Industry Park, Laoshan District, + Qingdao Shandong 266103 + CN + +F8-D4-78 (hex) Flextronics Tech.(Ind) Pvt Ltd +F8D478 (base 16) Flextronics Tech.(Ind) Pvt Ltd + SURVEYNO.381, PADUR ROAD, KUTHAMBAKKAM VILLAGE, 602107 POONAMALLEE TALUK, THIRUVALLUR DISTRIC + Chennai 602107 + IN + +48-C3-B0 (hex) Pharos Co.Ltd +48C3B0 (base 16) Pharos Co.Ltd + 503 Ogong-ro 144 Deokjin-gu + Jeonju-si 54873 + KR + +DC-58-BC (hex) Thomas-Krenn.AG +DC58BC (base 16) Thomas-Krenn.AG + Speltenbach-Steinaecker 1 + Freyung 94078 + DE + +00-10-25 (hex) Grayhill, Inc +001025 (base 16) Grayhill, Inc + 561 Hillgrove Ave + LaGrange IL 60525 + US + +38-21-C7 (hex) Aruba, a Hewlett Packard Enterprise Company +3821C7 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +A4-5F-9B (hex) Nexell +A45F9B (base 16) Nexell + 12F, 31 Hwangsaeul-ro 258 beon-gil, Bundang-gu + Seongnam-si, Gyeonggi-do 13595 + KR + +70-EA-1A (hex) Cisco Systems, Inc +70EA1A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +80-8A-8B (hex) vivo Mobile Communication Co., Ltd. +808A8B (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +98-44-B6 (hex) INFRANOR SAS +9844B6 (base 16) INFRANOR SAS + Avenue Jean Moulin + LOURDES 65100 + FR + +38-83-9A (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +38839A (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District, + Shenzhen Guangdong 518000 + CN + +DC-67-23 (hex) barox Kommunikation GmbH +DC6723 (base 16) barox Kommunikation GmbH + Marie-Curie-Strasse 8 + Lörrach DE-79539 + DE + +44-B4-62 (hex) Flextronics Tech.(Ind) Pvt Ltd +44B462 (base 16) Flextronics Tech.(Ind) Pvt Ltd + SURVEYNO.381, PADUR ROAD, KUTHAMBAKKAM VILLAGE, 602107 POONAMALLEE TALUK, THIRUVALLUR DISTRIC + Chennai 602107 + IN + +94-B4-0F (hex) Aruba, a Hewlett Packard Enterprise Company +94B40F (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +00-1A-1E (hex) Aruba, a Hewlett Packard Enterprise Company +001A1E (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +00-24-6C (hex) Aruba, a Hewlett Packard Enterprise Company +00246C (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +20-1B-C9 (hex) Juniper Networks +201BC9 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +C8-F6-C8 (hex) Fiberhome Telecommunication Technologies Co.,LTD +C8F6C8 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +1C-3B-8F (hex) Selve GmbH & Co. KG +1C3B8F (base 16) Selve GmbH & Co. KG + Werdohler Landstraße 286 + Lüdenscheid 58513 + DE + +E4-E7-49 (hex) Hewlett Packard +E4E749 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +EC-C5-7F (hex) Suzhou Pairlink Network Technology +ECC57F (base 16) Suzhou Pairlink Network Technology + Room304, Building 4, No.209, Zhu Yuan Road, Suzhou new district + Suzhou Jiangsu 215011 + CN + +A8-6D-AA (hex) Intel Corporate +A86DAA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +38-C2-BA (hex) CCTV NEOTECH +38C2BA (base 16) CCTV NEOTECH + 68, Digital-ro 9-gil, Geumcheon-gu + Seoul ks013 + KR + +A0-F9-B7 (hex) Ademco Smart Homes Technology(Tianjin)Co.,Ltd. +A0F9B7 (base 16) Ademco Smart Homes Technology(Tianjin)Co.,Ltd. + No.156 Nanhai Road,TEDA, Jinbin Development Park , 21st Factory Building + Tianjin Tianjin 300457 + CN + +A8-3C-CB (hex) ROSSMA +A83CCB (base 16) ROSSMA + Malkova,12-108 + PERM 614087 + RU + +88-6F-D4 (hex) Dell Inc. +886FD4 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +CC-3F-EA (hex) BAE Systems, Inc +CC3FEA (base 16) BAE Systems, Inc + 1098 Clark St + Endicott NY 13760 + US + +4C-F2-BF (hex) Cambridge Industries(Group) Co.,Ltd. +4CF2BF (base 16) Cambridge Industries(Group) Co.,Ltd. + 22 Floor,Qilai Tower;889 Yishan Road + Shanghai 200233 + CN + +CC-9E-A2 (hex) Amazon Technologies Inc. +CC9EA2 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno 89507 + US + +AC-43-30 (hex) Versa Networks +AC4330 (base 16) Versa Networks + 6001 America center Drive, Suite 400 + San Jose CA 95070 + US + +E8-5B-B7 (hex) Ample Systems Inc. +E85BB7 (base 16) Ample Systems Inc. + 11F-2, No. 95 Minquan Rd. + New Taipei City 231 + TW + +94-67-7E (hex) Belden India Private Limited +94677E (base 16) Belden India Private Limited + Plot No. D-228, Chakan MIDC Phase 2, + Village Bhamboli, Taluka:Khed Pune, Maharashtra 410 507 + IN + +AC-57-75 (hex) HMD Global Oy +AC5775 (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +D4-3A-2E (hex) SHENZHEN MTC CO LTD +D43A2E (base 16) SHENZHEN MTC CO LTD + 5th Floor, 3rd Building, SHENZHEN MTC Industrial Park, XiaLilang Rd, Nanwan Street, Long’gang District + Shenzhen Guangdong 518100 + CN + +50-AD-92 (hex) NX Technologies +50AD92 (base 16) NX Technologies + 5F(OS Building), 57, Daeril-2gil, Beomseo-eup + Ulsan 44922 + KR + +30-C3-D9 (hex) ALPS ELECTRIC CO., LTD. +30C3D9 (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + Kakuda Miyagi-Pref 981-1595 + JP + +00-32-17 (hex) Cisco Systems, Inc +003217 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1B-FB (hex) ALPS ELECTRIC CO., LTD. +001BFB (base 16) ALPS ELECTRIC CO., LTD. + 1-2-1, Okinouchi, + Soma-city, Fukushima-pref., 976-8501 + JP + +94-E0-D6 (hex) China Dragon Technology Limited +94E0D6 (base 16) China Dragon Technology Limited + B4 Bldg.Haoshan 1st Industry Park, + Shenzhen Guangdong 518104 + CN + +B4-A9-FC (hex) Quanta Computer Inc. +B4A9FC (base 16) Quanta Computer Inc. + No. 211, Wen-Hwa 2nd Rd.,Kuei-Shan Dist. + Taoyuan City Taiwan 33377 + TW + +6C-A9-36 (hex) DisplayLink (UK) Ltd +6CA936 (base 16) DisplayLink (UK) Ltd + 140 Science Park, Milton road + Cambridge Cambridgeshire CB4 0GF + GB + +70-85-40 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +708540 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +08-F1-EA (hex) Hewlett Packard Enterprise +08F1EA (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +F0-0D-F5 (hex) ACOMA Medical Industry Co,. Ltd. +F00DF5 (base 16) ACOMA Medical Industry Co,. Ltd. + 2-14-14 hongo + bunkyo-ku Tokyo 113-0033 + JP + +68-45-F1 (hex) TOSHIBA CLIENT SOLUTIONS CO., LTD. +6845F1 (base 16) TOSHIBA CLIENT SOLUTIONS CO., LTD. + Tachihi Building No.2, 6-1-3, Sakae-Cho + Tachikawa-shi Tokyo 190-0003 + JP + +8C-AE-DB (hex) NAG LLC +8CAEDB (base 16) NAG LLC + Predelnaya st 57/2 + Ekaterinburg Sverdlovskaya oblast 620161 + RU + +78-B2-13 (hex) DWnet Technologies(Suzhou) Corporation +78B213 (base 16) DWnet Technologies(Suzhou) Corporation + No.8,Tangzhuang Road, Suzhou Industrial Park, Jiangsu, China + Suzhou 21500 + CN + +58-C2-32 (hex) NEC Corporation +58C232 (base 16) NEC Corporation + 1753, Shimonumabe, Nakahara-Ku, Kawasaki + Kanagawa 211-8666 + JP + +38-1D-14 (hex) Skydio Inc. +381D14 (base 16) Skydio Inc. + 114 Hazel Ave + Redwood City CA 94061 + US + +7C-DB-98 (hex) ASKEY COMPUTER CORP +7CDB98 (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +38-0B-3C (hex) Texas Instruments +380B3C (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +9C-8C-D8 (hex) Hewlett Packard Enterprise +9C8CD8 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +A4-8C-C0 (hex) JLG Industries, Inc. +A48CC0 (base 16) JLG Industries, Inc. + 13224 Fountainhead Plaza + Hagerstown MD 21742 + US + +3C-28-6D (hex) Google, Inc. +3C286D (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +00-09-3A (hex) Molex CMS +00093A (base 16) Molex CMS + 5224 Katrine Avenue + Downers Grove IL 60515 + US + +04-F9-D9 (hex) Speaker Electronic(Jiashan) Co.,Ltd +04F9D9 (base 16) Speaker Electronic(Jiashan) Co.,Ltd + No. 8 Development Zone Road, Huimin Sub-district + Jiashan Zhejiang 314112 + CN + +DC-08-0F (hex) Apple, Inc. +DC080F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-E9-4E (hex) Apple, Inc. +F8E94E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +EC-2C-E2 (hex) Apple, Inc. +EC2CE2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-BC-60 (hex) Apple, Inc. +40BC60 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E8-36-17 (hex) Apple, Inc. +E83617 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-64-8B (hex) Apple, Inc. +9C648B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-42-62 (hex) Apple, Inc. +344262 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-D0-0D (hex) Apple, Inc. +14D00D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-D2-11 (hex) Eko Devices, Inc. +88D211 (base 16) Eko Devices, Inc. + 2600 10th St Ste 260 + Berkeley CA 94710-2597 + US + +B8-C2-27 (hex) PSTec +B8C227 (base 16) PSTec + #80, Hwanggeum 3-ro 7beon-gil, Yangchon-eup + Gimpo-si Gyeonggi-do 10048 + KR + +74-F7-37 (hex) KCE +74F737 (base 16) KCE + 5F KCE B/D,34,Annam-ro 369beon-gil,Bupyoung-gu + Incheon 21312 + KR + +48-A4-93 (hex) TAIYO YUDEN CO.,LTD +48A493 (base 16) TAIYO YUDEN CO.,LTD + 8-1, Sakae-cho + Takasaki-shi Gunma 370-8522 + JP + +E8-2C-6D (hex) SmartRG, Inc. +E82C6D (base 16) SmartRG, Inc. + 501 SE Columbia Shores Blvd + Vancouver WA 98661 + US + +48-E6-95 (hex) Insigma Inc +48E695 (base 16) Insigma Inc + 43490, Yukon Drive, Suite 102 + Ashburn VA 20147 + US + +B4-79-C8 (hex) Ruckus Wireless +B479C8 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +B4-0B-78 (hex) Brusa Elektronik AG +B40B78 (base 16) Brusa Elektronik AG + Neudorf 14 + Sennwald St. Gallen 9466 + CH + +20-79-18 (hex) Intel Corporate +207918 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C0-3D-D9 (hex) MitraStar Technology Corp. +C03DD9 (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +2C-AA-8E (hex) Wyze Labs Inc +2CAA8E (base 16) Wyze Labs Inc + 4030 Lake Washington Boulevard NE + Kirkland WA 98033 + US + +70-3A-51 (hex) Xiaomi Communications Co Ltd +703A51 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +DC-48-B2 (hex) Baraja Pty. Ltd. +DC48B2 (base 16) Baraja Pty. Ltd. + 36 Bradfield Road + West Lindfield NSW 2070 + AU + +AC-AE-19 (hex) Roku, Inc +ACAE19 (base 16) Roku, Inc + 150 Winchester Circle + Los Gatos CA 95032 + US + +18-1E-95 (hex) AuVerte +181E95 (base 16) AuVerte + 14 Riverview Road + Niantic CT 06357 + US + +0C-95-41 (hex) CHIPSEA TECHNOLOGIES (SHENZHEN) CORP. +0C9541 (base 16) CHIPSEA TECHNOLOGIES (SHENZHEN) CORP. + 9F,BLOCK A,GARDEN CITY DIGITAL BUILDING,NO.1079 NANHAI ROAD,NANSHAN DISTRICT + SHEN ZHEN GUANG DONG 518000 + CN + +AC-F8-5C (hex) Private +ACF85C (base 16) Private + +9C-69-37 (hex) Qorvo Utrecht B.V. +9C6937 (base 16) Qorvo Utrecht B.V. + Leidseveer 10 + Utrecht Utrecht 3511SB + NL + +3C-37-86 (hex) NETGEAR +3C3786 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +48-35-2E (hex) Shenzhen Wolck Network Product Co.,LTD +48352E (base 16) Shenzhen Wolck Network Product Co.,LTD + 9# BuJi BanTian LongBi Industry Area + Shenzhen Guangdong 518129 + CN + +04-E5-98 (hex) Xiaomi Communications Co Ltd +04E598 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +10-12-B4 (hex) SICHUAN TIANYI COMHEART TELECOM CO.,LTD +1012B4 (base 16) SICHUAN TIANYI COMHEART TELECOM CO.,LTD + NO.198 FIRST SECTION,SNOW MOUNTAIN AVENUE, JINYUAN TOWN, DAYI COUNTY, + CHENGDU SICHUAN 611330 + CN + +B8-2C-A0 (hex) Resideo +B82CA0 (base 16) Resideo + 2 Corporate Center Dr. + Melville NY 11747 + US + +6C-C7-EC (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +6CC7EC (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +B0-33-A6 (hex) Juniper Networks +B033A6 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +D8-96-85 (hex) GoPro +D89685 (base 16) GoPro + 3000 Clearview Way + San Mateo CA 94402 + US + +3C-01-EF (hex) Sony Mobile Communications Inc +3C01EF (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +C0-BD-C8 (hex) Samsung Electronics Co.,Ltd +C0BDC8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +64-7B-CE (hex) Samsung Electronics Co.,Ltd +647BCE (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A8-87-B3 (hex) Samsung Electronics Co.,Ltd +A887B3 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +6C-00-6B (hex) Samsung Electronics Co.,Ltd +6C006B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-10-60 (hex) BILLIONTON SYSTEMS, INC. +001060 (base 16) BILLIONTON SYSTEMS, INC. + 3F-1, NO. 8, LANE 99 + HSIN-CHU + TW + +C4-D4-89 (hex) JiangSu Joyque Information Industry Co.,Ltd +C4D489 (base 16) JiangSu Joyque Information Industry Co.,Ltd + 10 Floor YaHua Building, Xi'anBei Road, + Xuzhou JiangSu 221006 + CN + +B4-F9-49 (hex) optilink networks pvt ltd +B4F949 (base 16) optilink networks pvt ltd + 501/502, sanjona complex, hemu kalani marg, chembur + mumbai maharashtra 400071 + IN + +E4-3C-80 (hex) University of Oklahoma +E43C80 (base 16) University of Oklahoma + Advanced Radar Research Center + Norman OK 73019 + US + +3C-2C-30 (hex) Dell Inc. +3C2C30 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +70-6D-15 (hex) Cisco Systems, Inc +706D15 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A4-A1-E4 (hex) Innotube, Inc. +A4A1E4 (base 16) Innotube, Inc. + #1212 MegaCenter SknTechnoPark 124 Sagimakgol-ro Jungwon-gu + Seongnam-si Gyeonggi-do 462-120 + KR + +94-EA-EA (hex) TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO +94EAEA (base 16) TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO + Av. Buriti, 1900 – Setor B – Distrito Industrial + Manaus Amazonas 69075-000 + BR + +1C-FD-08 (hex) IEEE Registration Authority +1CFD08 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +B8-59-9F (hex) Mellanox Technologies, Inc. +B8599F (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +A0-A4-C5 (hex) Intel Corporate +A0A4C5 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +F4-D1-08 (hex) Intel Corporate +F4D108 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +30-13-89 (hex) Siemens AG, Automations & Drives, +301389 (base 16) Siemens AG, Automations & Drives, + Systems Engineering + Fürth Deutschlang 90766 + DE + +04-6B-25 (hex) SICHUAN TIANYI COMHEART TELECOM CO.,LTD +046B25 (base 16) SICHUAN TIANYI COMHEART TELECOM CO.,LTD + NO.198 FIRST SECTION,SNOW MOUNTAIN AVENUE, JINYUAN TOWN, DAYI COUNTY, + CHENGDU SICHUAN 611330 + CN + +98-D3-E7 (hex) Netafim L +98D3E7 (base 16) Netafim L + Kibutz Magal + Kibutz Magal 38845 + IL + +F0-63-F9 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F063F9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-C3-85 (hex) HUAWEI TECHNOLOGIES CO.,LTD +7CC385 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +90-0E-B3 (hex) Shenzhen Amediatech Technology Co., Ltd. +900EB3 (base 16) Shenzhen Amediatech Technology Co., Ltd. + 2th floor, block A, building B, Minsheng Industrial Zone, Longhua District + Shenzhen Guangdong 518109 + CN + +54-9F-AE (hex) iBASE Gaming Inc +549FAE (base 16) iBASE Gaming Inc + 2F., No.542-17, Zhongzheng Rd + Xinzhuang Dist., New Taipei City 24255 + TW + +14-69-A2 (hex) SICHUAN TIANYI COMHEART TELECOM CO.,LTD +1469A2 (base 16) SICHUAN TIANYI COMHEART TELECOM CO.,LTD + NO.198 FIRST SECTION,SNOW MOUNTAIN AVENUE, JINYUAN TOWN, DAYI COUNTY, + CHENGDU SICHUAN 611330 + CN + +54-80-28 (hex) Hewlett Packard Enterprise +548028 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +00-AD-24 (hex) D-Link International +00AD24 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +54-06-8B (hex) Ningbo Deli Kebei Technology Co.LTD +54068B (base 16) Ningbo Deli Kebei Technology Co.LTD + zone 2nd , 301#, Road Xuxiake, Ninghai yuelong district + ningbo Zhejiang 315600 + CN + +60-CE-92 (hex) The Refined Industry Company Limited +60CE92 (base 16) The Refined Industry Company Limited + 7/F Sun King Factory Bldg,1 - 7 Shing Chuen Road, Shatin, NT + Hong Kong NT 000000 + HK + +10-5B-AD (hex) Mega Well Limited +105BAD (base 16) Mega Well Limited + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +74-BF-C0 (hex) CANON INC. +74BFC0 (base 16) CANON INC. + 30-2 Shimomaruko 3-chome, + Ohta-ku Tokyo 146-8501 + JP + +18-1D-EA (hex) Intel Corporate +181DEA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +18-56-80 (hex) Intel Corporate +185680 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C8-D9-D2 (hex) Hewlett Packard +C8D9D2 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +24-FC-E5 (hex) Samsung Electronics Co.,Ltd +24FCE5 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +80-96-21 (hex) Lenovo +809621 (base 16) Lenovo + 1009 Think Place + Morrisvilee NC 27560 + US + +78-05-5F (hex) Shenzhen WYC Technology Co., Ltd. +78055F (base 16) Shenzhen WYC Technology Co., Ltd. + No.618 Wenzhengxin Building,Hi-tech Park,Nanshan District + Shenzhen Guangdong 518000 + CN + +00-EA-BD (hex) Cisco Systems, Inc +00EABD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +48-87-2D (hex) SHEN ZHEN DA XIA LONG QUE TECHNOLOGY CO.,LTD +48872D (base 16) SHEN ZHEN DA XIA LONG QUE TECHNOLOGY CO.,LTD + Room 511, Building C, Yuxing Technology Park, Gushu Second Road, Bao’an District + SHEN ZHEN GUANG DONG 518000 + CN + +E8-1A-58 (hex) TECHNOLOGIC SYSTEMS +E81A58 (base 16) TECHNOLOGIC SYSTEMS + 16525 E Laser Dr + Fountain Hills AZ 85268-6534 + US + +20-B0-01 (hex) Technicolor +20B001 (base 16) Technicolor + Prins Boudewijnlaan 47 + Edegem - Belgium B-2650 + BE + +C0-BF-A7 (hex) Juniper Networks +C0BFA7 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +F0-54-94 (hex) Honeywell Connected Building +F05494 (base 16) Honeywell Connected Building + 1985 DOUGLAS DRIVE + Golden Valley MN 55422 + US + +5C-C9-99 (hex) New H3C Technologies Co., Ltd +5CC999 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +B0-2A-43 (hex) Google, Inc. +B02A43 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +C4-74-F8 (hex) Hot Pepper, Inc. +C474F8 (base 16) Hot Pepper, Inc. + 5151 California Ave., Suite 100, + Irvine 92617 + US + +14-22-33 (hex) Fiberhome Telecommunication Technologies Co.,LTD +142233 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +74-34-00 (hex) MTG Co., Ltd. +743400 (base 16) MTG Co., Ltd. + MTG No. 2 HIKARI Bldg., 4-13 Honjindori + Nakamura-ku, Nagoya Aichi 453-0041 + JP + +DC-37-57 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +DC3757 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +00-50-99 (hex) 3COM EUROPE LTD +005099 (base 16) 3COM EUROPE LTD + BOUNDARY WAY + HERTS. HP2 7YU vvvvvv + GB + +04-BC-87 (hex) Shenzhen JustLink Technology Co., LTD +04BC87 (base 16) Shenzhen JustLink Technology Co., LTD + Room 5002,The 2nd Unit of the Building East, Laobing Building, No.3012 Xingye Road,Baoan District + Shenzhen Guangdong Province 518101 + CN + +54-C3-3E (hex) Ciena Corporation +54C33E (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +EC-79-F2 (hex) Startel +EC79F2 (base 16) Startel + Xi Chuang Industrial Park,Second industrial district of Guan Long Village,Xili town ,Nanshan District + Shenzhen Guangdong 518055 + CN + +BC-B2-2B (hex) EM-Tech +BCB22B (base 16) EM-Tech + 40, Changwon-daero 1144beon-gil + Seongsan-gu Changwon Gyeongsangnam-do KR 642-120 + KR + +D4-AB-82 (hex) ARRIS Group, Inc. +D4AB82 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +70-4F-B8 (hex) ARRIS Group, Inc. +704FB8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-60-EB (hex) FOURTHTRACK SYSTEMS +0060EB (base 16) FOURTHTRACK SYSTEMS + UNIT 3 THE SYCAMORES + MARLOW - SL7 1QB + GB + +18-62-E4 (hex) Texas Instruments +1862E4 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +60-35-C0 (hex) SFR +6035C0 (base 16) SFR + 12 rue jean-philippe Rameau CS 80001 + La plaine saint denis FRANCE 93634 + FR + +C4-98-5C (hex) Hui Zhou Gaoshengda Technology Co.,LTD +C4985C (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +30-A1-FA (hex) HUAWEI TECHNOLOGIES CO.,LTD +30A1FA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-2E-90 (hex) PALIT MICROSYSTEMS, LTD +242E90 (base 16) PALIT MICROSYSTEMS, LTD + 21F.,No.88,Sec.2,Zhongxiao E.Rd.,Golden Tower, + TAIPEI 100 + TW + +9C-AA-1B (hex) Microsoft Corporation +9CAA1B (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +A8-9A-93 (hex) Sagemcom Broadband SAS +A89A93 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +00-1A-C5 (hex) Keysight Technologies, Inc. +001AC5 (base 16) Keysight Technologies, Inc. + 1400 Fountaingrove Pkwy. + Santa Rosa CA 95403 + US + +00-20-1E (hex) NETQUEST CORPORATION +00201E (base 16) NETQUEST CORPORATION + 523 FELLOWSHIP ROAD-STE.#205 + MT. LAUREL NJ 08054 + US + +64-62-8A (hex) evon GmbH +64628A (base 16) evon GmbH + Frank-Stronach-Straße 8 + Gleisdorf Styria 8200 + AT + +04-15-D9 (hex) Viwone +0415D9 (base 16) Viwone + 54 - 56 , Avenue Hoche + Paris 75008 + FR + +EC-B3-13 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +ECB313 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +B0-8B-CF (hex) Cisco Systems, Inc +B08BCF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-60-8C (hex) 3COM +00608C (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +00-A0-24 (hex) 3COM +00A024 (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +00-20-AF (hex) 3COM +0020AF (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +00-10-4B (hex) 3COM +00104B (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +A8-5A-F3 (hex) Shanghai Siflower Communication Technology Co., Ltd +A85AF3 (base 16) Shanghai Siflower Communication Technology Co., Ltd + Rm. 408, No. 84, Lane 887. Zhangjiang Hi-Tech Park. Zuchongzhi Rd. Shanghai, China + Shanghai Shanghai 201210 + CN + +70-FD-46 (hex) Samsung Electronics Co.,Ltd +70FD46 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +8C-83-E1 (hex) Samsung Electronics Co.,Ltd +8C83E1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +88-9F-6F (hex) Samsung Electronics Co.,Ltd +889F6F (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +5C-63-C9 (hex) Intellithings Ltd. +5C63C9 (base 16) Intellithings Ltd. + Hanehoshet 10 + Tel Aviv Israel 6971072 + IL + +64-5D-86 (hex) Intel Corporate +645D86 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +0C-96-E6 (hex) Cloud Network Technology (Samoa) Limited +0C96E6 (base 16) Cloud Network Technology (Samoa) Limited + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +3C-89-94 (hex) BSkyB Ltd +3C8994 (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +E0-0E-E1 (hex) We Corporation Inc. +E00EE1 (base 16) We Corporation Inc. + 201, 33, Deokcheon-ro, Manan-gu + Anyang-si Gyeonggi-do 14088 + KR + +00-0C-43 (hex) Ralink Technology, Corp. +000C43 (base 16) Ralink Technology, Corp. + 4F, No.2, Technology 5th Road, + Hsin-Chu 200 + TW + +8C-92-46 (hex) Oerlikon Textile Gmbh&Co.KG +8C9246 (base 16) Oerlikon Textile Gmbh&Co.KG + NO.9 Changyang Street + Suzhou Jiangsu 215000 + CN + +00-0E-94 (hex) Maas International BV +000E94 (base 16) Maas International BV + Science Park Eindhoven 5051 + Son Noord Brabant NL-5692 EB + NL + +48-98-CA (hex) Sichuan AI-Link Technology Co., Ltd. +4898CA (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou,Industrial Park + Anzhou,Industrial Park Sichuan 621000 + CN + +24-7E-51 (hex) zte corporation +247E51 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +E8-B5-41 (hex) zte corporation +E8B541 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +0C-9D-92 (hex) ASUSTek COMPUTER INC. +0C9D92 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +98-8E-D4 (hex) ITEL MOBILE LIMITED +988ED4 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +E8-A7-88 (hex) XIAMEN LEELEN TECHNOLOGY CO., LTD +E8A788 (base 16) XIAMEN LEELEN TECHNOLOGY CO., LTD + 65 Sunban South Rd., Jimei North Industrial Zone, + Xiamen Fujian 361021 + CN + +58-2D-34 (hex) Qingping Electronics (Suzhou) Co., Ltd +582D34 (base 16) Qingping Electronics (Suzhou) Co., Ltd + Room 304, A3 Building, NO.88 Dongchang Road, Suzhou Industrial Park + Suzhou Jiangsu Province 215028 + CN + +20-DE-88 (hex) IC Realtime LLC +20DE88 (base 16) IC Realtime LLC + 3050 N Andrews Ave Ext. + Pompano Beach FL 33064 + US + +F4-06-8D (hex) devolo AG +F4068D (base 16) devolo AG + Charlottenburger Allee 67 + Aachen NRW 52068 + DE + +00-1A-31 (hex) SCAN COIN AB +001A31 (base 16) SCAN COIN AB + Jagershillgatan 26 + Malmö Skåne 21375 + SE + +00-1B-84 (hex) Scan Engineering Telecom +001B84 (base 16) Scan Engineering Telecom + Svobody str. 75 + Voronezh 394030 + RU + +48-2C-A0 (hex) Xiaomi Communications Co Ltd +482CA0 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +34-12-F9 (hex) HUAWEI TECHNOLOGIES CO.,LTD +3412F9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +BC-E2-65 (hex) HUAWEI TECHNOLOGIES CO.,LTD +BCE265 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +4C-D1-A1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +4CD1A1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-BF-E4 (hex) HUAWEI TECHNOLOGIES CO.,LTD +88BFE4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +40-17-E2 (hex) INTAI TECHNOLOGY CORP. +4017E2 (base 16) INTAI TECHNOLOGY CORP. + No.9, JINGKE RD.,NANTUN DIST. + TAICHUNG CITY 40852 + TW + +0C-CB-85 (hex) Motorola Mobility LLC, a Lenovo Company +0CCB85 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +A4-E6-15 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD +A4E615 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + Unit East Block22-24/F,Skyworth semiconductor design Bldg., Gaoxin Ave.4.S.,Nanshan District,Shenzhen,China + SHENZHEN GUANGDONG 518057 + CN + +74-1F-79 (hex) YOUNGKOOK ELECTRONICS CO.,LTD +741F79 (base 16) YOUNGKOOK ELECTRONICS CO.,LTD + #810, Daewoo Frontier Valley 1,16-25, Dongbaekjungang-ro 16beon-gil, Giheung-gu + YONGIN Gyeonggi-do 17015 + KR + +A0-93-51 (hex) Cisco Systems, Inc +A09351 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +98-03-9B (hex) Mellanox Technologies, Inc. +98039B (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +20-89-84 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +208984 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone + KUNSHAN SUZHOU 215300 + CN + +B4-CE-FE (hex) James Czekaj +B4CEFE (base 16) James Czekaj + 41716 Waterfall Rd + Northville MI 48168 + US + +F8-CC-6E (hex) DEPO Electronics Ltd +F8CC6E (base 16) DEPO Electronics Ltd + 12, kommunalnaya zona Krasnogorsk-Mitino + Krasnogorsk Moscow region 143404 + RU + +F8-36-9B (hex) Texas Instruments +F8369B (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +88-AE-1D (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +88AE1D (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD STREET KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +B8-88-E3 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +B888E3 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + No.25, Third Avenue, A Zone, Kunshan Comprehensive Free Trade Zone,, Jiangsu, + KUNSHAN SUZHOU 215300 + CN + +28-9E-FC (hex) Sagemcom Broadband SAS +289EFC (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +00-C0-55 (hex) MODULAR COMPUTING TECHNOLOGIES +00C055 (base 16) MODULAR COMPUTING TECHNOLOGIES + 2352 MAIN STREET + CONCORD MA 01742 + US + +E4-1F-E9 (hex) Dunkermotoren GmbH +E41FE9 (base 16) Dunkermotoren GmbH + Allmendstr. 11 + Bonndorf Baden-Württemberg 79848 + DE + +C4-51-8D (hex) Shenzhen YOUHUA Technology Co., Ltd +C4518D (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +48-68-34 (hex) Silicon Motion, Inc. +486834 (base 16) Silicon Motion, Inc. + 8F, No. 36, Taiyuan St. + Zhubei City Hsinchu County 30265 + TW + +00-11-33 (hex) Siemens AG Austria +001133 (base 16) Siemens AG Austria + Siemensstrasse 90-92 + Vienna 1210 + AT + +00-0B-23 (hex) Siemens Home & Office Comm. Devices +000B23 (base 16) Siemens Home & Office Comm. Devices + 4849 Alpha Road + Dallas 74244 + US + +64-13-31 (hex) Bosch Car Multimedia (Wuhu) Co. Ltd. +641331 (base 16) Bosch Car Multimedia (Wuhu) Co. Ltd. + NO.48 North Yinhu Road + Wuhu city Anhui Province 241000 + CN + +18-3A-48 (hex) VostroNet +183A48 (base 16) VostroNet + GPO Box 3154 + Brisbane Queensland 4000 + AU + +78-2F-17 (hex) Xlab Co.,Ltd +782F17 (base 16) Xlab Co.,Ltd + #401 4F, Achasan-ro, Seongdong-gu + SEOUL 04793 + KR + +B0-02-7E (hex) MULLER SERVICES +B0027E (base 16) MULLER SERVICES + 107 Boulevard Ney + PARIS ILE DE FRANCE 75018 + FR + +24-FA-F3 (hex) Shanghai Flexem Technology Co.,Ltd. +24FAF3 (base 16) Shanghai Flexem Technology Co.,Ltd. + Room 804, C6 Building,No.52 Bay Valley Technology Park, Lane 1688 North Guoquan Road, Yangpu District. + Shanghai 200438 + CN + +88-D2-BF (hex) German Autolabs +88D2BF (base 16) German Autolabs + Köpenicker Str. 154 + Berlin Berlin 10997 + DE + +20-16-3D (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +20163D (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +E0-73-5F (hex) NUCOM +E0735F (base 16) NUCOM + Arte, 21,5B + Madrid Madrid 28033 + ES + +00-51-ED (hex) LG Innotek +0051ED (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +40-DC-9D (hex) HAJEN +40DC9D (base 16) HAJEN + 102-1302, Sinwon-ro 88, Yeongtong-gu + Suwon-Si Gyeonggi-do 16681 + KR + +34-0A-98 (hex) HUAWEI TECHNOLOGIES CO.,LTD +340A98 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +64-6D-6C (hex) HUAWEI TECHNOLOGIES CO.,LTD +646D6C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-B8-B4 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C4B8B4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F0-BC-C9 (hex) PFU LIMITED +F0BCC9 (base 16) PFU LIMITED + Nu 98-2 Unoke + Kahoku-shi, Ishikawa 929-1192 + JP + +48-75-83 (hex) Intellion AG +487583 (base 16) Intellion AG + Schuppisstrasse 10 + St. Gallen St. Gallen 9016 + CH + +90-4C-81 (hex) Hewlett Packard Enterprise +904C81 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +8C-35-79 (hex) QDIQO Sp. z o.o. +8C3579 (base 16) QDIQO Sp. z o.o. + Stanisława Wyspiańskiego 11 + Zielona Góra lubuskie 65-036 + PL + +38-C7-0A (hex) WiFiSong +38C70A (base 16) WiFiSong + Rm. 605, Building 3, No. 75 Wenyi West Road + Hangzhou Zhengjiang 310012 + CN + +D8-76-0A (hex) Escort, Inc. +D8760A (base 16) Escort, Inc. + 5440 West Chester Rd. + West Chester Ohio 45069 + US + +5C-2E-D2 (hex) ABC(XiSheng) Electronics Co.,Ltd +5C2ED2 (base 16) ABC(XiSheng) Electronics Co.,Ltd + No.2 Industrial building, FuRong 7 Road + ShenZhen GongDong 518100 + CN + +FC-FB-FB (hex) Cisco Systems, Inc +FCFBFB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-7E-95 (hex) Cisco Systems, Inc +007E95 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +9C-5A-44 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +9C5A44 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +14-CA-A0 (hex) Hu&Co +14CAA0 (base 16) Hu&Co + 105 Rue du Jardin + Bordeaux 33000 + FR + +08-D4-6A (hex) LG Electronics (Mobile Communications) +08D46A (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +68-3A-1E (hex) Cisco Meraki +683A1E (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco null 94158 + US + +00-10-17 (hex) Bosch Access Systems GmbH +001017 (base 16) Bosch Access Systems GmbH + Charlottenburger Allee 50 + AACHEN D-52068 + DE + +F4-EE-14 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +F4EE14 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan + Shenzhen Guangdong 518057 + CN + +6C-59-40 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +6C5940 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan + Shenzhen Guangdong 518057 + CN + +D0-25-16 (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +D02516 (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan + Shenzhen Guangdong 518057 + CN + +1C-60-DE (hex) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +1C60DE (base 16) MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + Mid-Fourth Flr.,Building 28,Cui Xi Fourth Road,Ke Yuan West,Nanshan + Shenzhen Guangdong 518057 + CN + +D8-24-77 (hex) Universal Electric Corporation +D82477 (base 16) Universal Electric Corporation + 168 Georgetown Road + Canonsburg PA 15317 + US + +00-90-7F (hex) WatchGuard Technologies, Inc. +00907F (base 16) WatchGuard Technologies, Inc. + 605 Fifth Ave. S + Seattle WA 98104-3892 + US + +4C-5E-0C (hex) Routerboard.com +4C5E0C (base 16) Routerboard.com + Mikrotikls SIA + Riga LV1009 + LV + +D4-CA-6D (hex) Routerboard.com +D4CA6D (base 16) Routerboard.com + Mikrotikls SIA + Riga LV-1009 + LV + +00-14-72 (hex) China Broadband Wireless IP Standard group(ChinaBWIPS) +001472 (base 16) China Broadband Wireless IP Standard group(ChinaBWIPS) + P.O.BOX 88,West High-tech + Xi'an Shaan Xi 710075 + CN + +80-B5-75 (hex) HUAWEI TECHNOLOGIES CO.,LTD +80B575 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-BE-2B (hex) HUAWEI TECHNOLOGIES CO.,LTD +A4BE2B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +68-E7-C2 (hex) Samsung Electronics Co.,Ltd +68E7C2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +58-B1-0F (hex) Samsung Electronics Co.,Ltd +58B10F (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +40-06-A0 (hex) Texas Instruments +4006A0 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +F8-2D-C0 (hex) ARRIS Group, Inc. +F82DC0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +18-9C-27 (hex) ARRIS Group, Inc. +189C27 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +3C-F5-CC (hex) New H3C Technologies Co., Ltd +3CF5CC (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +D0-8A-91 (hex) Technicolor CH USA Inc. +D08A91 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +28-11-A5 (hex) Bose Corporation +2811A5 (base 16) Bose Corporation + The Mountain + Framingham MA 01701-9168 + US + +D8-F3-DB (hex) Post CH AG +D8F3DB (base 16) Post CH AG + Wankdorfallee 4 + Bern 3030 + CH + +DC-B4-AC (hex) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. +DCB4AC (base 16) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + Xin Qing Science & Technology Industrial Park,Jin An Town,Doumen ,Zhuhai,Guangdong,PRC + Zhuhai Guangdong 519180 + CN + +A4-92-CB (hex) Nokia +A492CB (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +C0-D2-F3 (hex) Hui Zhou Gaoshengda Technology Co.,LTD +C0D2F3 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +B8-83-03 (hex) Hewlett Packard Enterprise +B88303 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +20-3D-BD (hex) LG Innotek +203DBD (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +A4-53-85 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +A45385 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China + Weifang Shandong 261205 + CN + +00-40-2F (hex) XLNT DESIGNS INC. +00402F (base 16) XLNT DESIGNS INC. + 15050 AVENUE OF SCIENCE + SAN DIEGO CA 92128 + US + +04-EC-BB (hex) Fiberhome Telecommunication Technologies Co.,LTD +04ECBB (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +64-A2-F9 (hex) OnePlus Technology (Shenzhen) Co., Ltd +64A2F9 (base 16) OnePlus Technology (Shenzhen) Co., Ltd + 18C02, 18C03, 18C04 ,18C05,TAIRAN BUILDING, + Shenzhen Guangdong 518000 + CN + +A8-7D-12 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A87D12 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D4-21-22 (hex) Sercomm Corporation. +D42122 (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +00-C0-02 (hex) Sercomm Corporation. +00C002 (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +BC-99-11 (hex) Zyxel Communications Corporation +BC9911 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +28-02-45 (hex) Konze System Technology Co.,Ltd. +280245 (base 16) Konze System Technology Co.,Ltd. + 4F., No.134, Ln. 235, Baoqiao Rd., Xindian Dist. + New Taipei City --- 231 + TW + +E4-8F-65 (hex) Yelatma Instrument Making Enterprise, JSC +E48F65 (base 16) Yelatma Instrument Making Enterprise, JSC + Yanina 25 + Yelatma Ryazan Region 391351 + RU + +00-00-A8 (hex) Stratus Technologies +0000A8 (base 16) Stratus Technologies + 5 Mill and Main Place, Suite 500 + Maynard MA 01754 + US + +00-04-FC (hex) Stratus Technologies +0004FC (base 16) Stratus Technologies + 5 Mill and Main Place, Suite 500 + Maynard MA 01754 + US + +3C-24-F0 (hex) IEEE Registration Authority +3C24F0 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-BB-3A (hex) Amazon Technologies Inc. +00BB3A (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +0C-B3-4F (hex) Shenzhen Xiaoqi Intelligent Technology Co., Ltd. +0CB34F (base 16) Shenzhen Xiaoqi Intelligent Technology Co., Ltd. + Room 1501, Block B4, Building 9, Section 2, Shenzhen Bay Science & Technology Ecological Park, West Shahe Road, Nanshan District, + Shenzhen Guangdong 518000 + CN + +3C-F4-F9 (hex) Moda-InnoChips +3CF4F9 (base 16) Moda-InnoChips + 42-7(Wonsi-Dong),Dongsan-ro 27beon-gil,Danwon-gu + Ansan-si Gyeonggi-Do 15433 + KR + +94-19-3A (hex) Elvaco AB +94193A (base 16) Elvaco AB + Kabelgatan 2T + Kungsbacka 43437 + SE + +C0-81-35 (hex) Ningbo Forfan technology Co., LTD +C08135 (base 16) Ningbo Forfan technology Co., LTD + Room B308,Tianjing Building,Tianan Cyber Park,Futian + Shenzhen Guangdong 518040 + CN + +84-0D-8E (hex) Espressif Inc. +840D8E (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +00-20-82 (hex) ONEAC CORPORATION +002082 (base 16) ONEAC CORPORATION + 27944 N. BRADLEY RD. + LIBERTYVILLE IL 60048 + US + +B4-C0-F5 (hex) Shenzhen TINNO Mobile Technology Corp. +B4C0F5 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F, H-3 Building, Qiao Cheng Eastern Industrial Park, Overseas Chinese Town, Shenzhen + Shenzhen guangdong 518053 + CN + +40-62-31 (hex) GIFA +406231 (base 16) GIFA + 11th Fl., Suojia Business Building , No.7 Hangkong Road , Baoan District + Shenzhen Guangdong 518000 + CN + +FC-B7-F0 (hex) Idaho National Laboratory +FCB7F0 (base 16) Idaho National Laboratory + 2525 N. Fremont Ave + Idaho Falls ID 83415 + US + +2C-28-B7 (hex) Hangzhou Ruiying technology co., LTD +2C28B7 (base 16) Hangzhou Ruiying technology co., LTD + No. 1, building 305, Yunqi Town Cloud Computing Industrial Park, Hangzhou City, Xihu District + Hangzhou Zhejiang 310000 + CN + +10-65-30 (hex) Dell Inc. +106530 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +04-6B-1B (hex) SYSDINE Co., Ltd. +046B1B (base 16) SYSDINE Co., Ltd. + 506 Convergence technology research commercialization center 218 Gajung-Ro, Yuseong-gu + Daejeon-City Daejeon-City 34129 + KR + +B0-A3-7E (hex) QING DAO HAIER TELECOM CO.,LTD. +B0A37E (base 16) QING DAO HAIER TELECOM CO.,LTD. + No.1,Haier Road,Qingdao 266101 P.R.China + Qingdao Shandong 266101 + CN + +3C-EA-F9 (hex) JUBIXCOLTD +3CEAF9 (base 16) JUBIXCOLTD + Rm 808, 809, B dong, Gunpo IT vally, 17, Gosan-ro 148beon-gil, Gunpo-si, Gyeonggi-do, Republic of Korea + GUNPOSI 15850 + KR + +58-DB-15 (hex) TECNO MOBILE LIMITED +58DB15 (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +50-50-CE (hex) Hangzhou Dianyixia Communication Technology Co. Ltd. +5050CE (base 16) Hangzhou Dianyixia Communication Technology Co. Ltd. + Room 207, Building 7, 1197 bin 'an road, Binjiang district, + Hangzhou Zhejiang 310011 + CN + +FC-69-47 (hex) Texas Instruments +FC6947 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +E0-7D-EA (hex) Texas Instruments +E07DEA (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +DC-DE-4F (hex) Gionee Communication Equipment Co Ltd +DCDE4F (base 16) Gionee Communication Equipment Co Ltd + 21/F Times Technology Building, 7028 Shennan Road + Shenzhen Futian District 518040 + CN + +4C-D0-CB (hex) HUAWEI TECHNOLOGIES CO.,LTD +4CD0CB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +50-5D-AC (hex) HUAWEI TECHNOLOGIES CO.,LTD +505DAC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E8-FA-F7 (hex) Guangdong Uniteddata Holding Group Co., Ltd. +E8FAF7 (base 16) Guangdong Uniteddata Holding Group Co., Ltd. + 39L, Pearl River Tower, No.15 Zhujiang West Road,Tianhe District + GUANGZHOU GUANGDONG 510623 + CN + +94-9D-57 (hex) Panasonic do Brasil Limitada +949D57 (base 16) Panasonic do Brasil Limitada + Rua Matrinxa + Manaus Amazonas 69075150 + BR + +88-D3-7B (hex) FirmTek, LLC +88D37B (base 16) FirmTek, LLC + 29300 Kohoutek Way + Union City CA 94587 + US + +1C-66-6D (hex) Hon Hai Precision Ind. Co.,Ltd. +1C666D (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +84-F3-EB (hex) Espressif Inc. +84F3EB (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +00-1B-48 (hex) Shenzhen Lantech Electronics Co., Ltd. +001B48 (base 16) Shenzhen Lantech Electronics Co., Ltd. + 306 Room, Nanshan Water Building, + Shenzhen Guangdong 518052 + CN + +00-25-0C (hex) Senet Inc +00250C (base 16) Senet Inc + 100 Market Street, Suite 302 + Portsmouth NH 03801 + US + +0C-80-63 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +0C8063 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +00-72-78 (hex) Cisco Systems, Inc +007278 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +04-D3-B0 (hex) Intel Corporate +04D3B0 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +64-5A-ED (hex) Apple, Inc. +645AED (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-B6-58 (hex) Apple, Inc. +C0B658 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-A9-1C (hex) Apple, Inc. +48A91C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +50-BC-96 (hex) Apple, Inc. +50BC96 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-2A-9C (hex) Apple, Inc. +FC2A9C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-2C-7B (hex) Cisco Systems, Inc +682C7B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +44-1E-98 (hex) Ruckus Wireless +441E98 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +A0-56-F3 (hex) Apple, Inc. +A056F3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-99-63 (hex) Apple, Inc. +549963 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-DD-5D (hex) Apple, Inc. +90DD5D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +DC-29-19 (hex) AltoBeam (Xiamen) Technology Ltd, Co. +DC2919 (base 16) AltoBeam (Xiamen) Technology Ltd, Co. + South Building 203-38,Huoju Square ,No.56-58,Huoju Road, Huoju Park, Huoju High-tech District + Xiamen 361000 + CN + +88-5F-E8 (hex) IEEE Registration Authority +885FE8 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-2F-D9 (hex) Fiberhome Telecommunication Technologies Co.,LTD +002FD9 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +B4-CD-27 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B4CD27 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C8-19-F7 (hex) Samsung Electronics Co.,Ltd +C819F7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +64-C3-D6 (hex) Juniper Networks +64C3D6 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-A0-21 (hex) General Dynamics Mission Systems +00A021 (base 16) General Dynamics Mission Systems + 150 Rustcraft Road + Dedham MA 02026 + US + +F0-AF-50 (hex) Phantom Intelligence +F0AF50 (base 16) Phantom Intelligence + 319 Rue Franquet Suite F + Quebec QC G1P 4R4 + CA + +C4-2C-4F (hex) Qingdao Hisense Mobile Communication Technology Co,Ltd +C42C4F (base 16) Qingdao Hisense Mobile Communication Technology Co,Ltd + No.399, Song Ling Road + Qingdao Shandong 266100 + CN + +24-CA-CB (hex) Fiberhome Telecommunication Technologies Co.,LTD +24CACB (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +54-3E-64 (hex) Fiberhome Telecommunication Technologies Co.,LTD +543E64 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +64-02-CB (hex) ARRIS Group, Inc. +6402CB (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F4-E1-1E (hex) Texas Instruments +F4E11E (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +38-80-DF (hex) Motorola Mobility LLC, a Lenovo Company +3880DF (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +BC-6A-2F (hex) Henge Docks LLC +BC6A2F (base 16) Henge Docks LLC + 455 10th St. + San Francisco California 94103 + US + +0C-08-B4 (hex) HUMAX Co., Ltd. +0C08B4 (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +00-27-05 (hex) Sectronic +002705 (base 16) Sectronic + Z.I. Les Saulniers + Sainte-Maure de Touraine 37800 + FR + +48-BD-3D (hex) New H3C Technologies Co., Ltd +48BD3D (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +18-4C-08 (hex) Rockwell Automation +184C08 (base 16) Rockwell Automation + 1 Allen-Bradley Dr. + Mayfield Heights OH 44124-6118 + US + +DC-02-65 (hex) Meditech Kft +DC0265 (base 16) Meditech Kft + Üllõi út 200. + Budapest 1191 + HU + +18-0F-76 (hex) D-Link International +180F76 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +14-A7-2B (hex) currentoptronics Pvt.Ltd +14A72B (base 16) currentoptronics Pvt.Ltd + CRT Building, Jupitor Jn , Near Time kids Koothattukulam - Piravom Rd + ERNAKULAM Time Kids day care 686662 + IN + +A4-DA-22 (hex) IEEE Registration Authority +A4DA22 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +3C-17-10 (hex) Sagemcom Broadband SAS +3C1710 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +DC-72-9B (hex) HUAWEI TECHNOLOGIES CO.,LTD +DC729B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +90-94-97 (hex) HUAWEI TECHNOLOGIES CO.,LTD +909497 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +34-02-9B (hex) Plexonics Technologies LImited +34029B (base 16) Plexonics Technologies LImited + 1st Floor, 181/23 Industrial Area Phase 1 + Chandigarh Punjab 160002 + IN + +90-03-72 (hex) Longnan Junya Digital Technology Co. Ltd. +900372 (base 16) Longnan Junya Digital Technology Co. Ltd. + Champion Asia Road, Xinzhen industrial Park, Longnan national economic and technological development zone, Ganzhou city, JiangXi Province , China + ganzhou jiangxi 341700 + CN + +84-DB-9E (hex) Aifloo AB +84DB9E (base 16) Aifloo AB + Postbox 2005 + Stockholm 10311 + SE + +0C-C6-CC (hex) HUAWEI TECHNOLOGIES CO.,LTD +0CC6CC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +78-58-60 (hex) HUAWEI TECHNOLOGIES CO.,LTD +785860 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E8-AB-F3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E8ABF3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +3C-DC-BC (hex) Samsung Electronics Co.,Ltd +3CDCBC (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +80-4E-70 (hex) Samsung Electronics Co.,Ltd +804E70 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D4-E6-B7 (hex) Samsung Electronics Co.,Ltd +D4E6B7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +8C-4C-AD (hex) Evoluzn Inc. +8C4CAD (base 16) Evoluzn Inc. + 34 Samoset Lane + Schaumburg IL 60193 + US + +8C-F9-57 (hex) RuiXingHengFang Network (Shenzhen) Co.,Ltd +8CF957 (base 16) RuiXingHengFang Network (Shenzhen) Co.,Ltd + Room 507, 2nd tower of KangTai biological building NO.6 KeFa Rd. NanShan District + Shenzhen Guangdong 518057 + CN + +4C-77-6D (hex) Cisco Systems, Inc +4C776D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +74-E1-82 (hex) Texas Instruments +74E182 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +44-9E-F9 (hex) vivo Mobile Communication Co., Ltd. +449EF9 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +6C-C4-D5 (hex) HMD Global Oy +6CC4D5 (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +80-C5-48 (hex) Shenzhen Zowee Technology Co.,Ltd +80C548 (base 16) Shenzhen Zowee Technology Co.,Ltd + NO.5 Zowee technology building, Science & Technology industrial park of privately Science & Technology industrial park of privately owned enterprises + Shenzhen GuangDong 518055 + CN + +10-C2-5A (hex) Technicolor CH USA Inc. +10C25A (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +E8-DE-FB (hex) MESOTIC SAS +E8DEFB (base 16) MESOTIC SAS + 11, Avenue de la Division Leclerc + Cachan 94230 + FR + +C4-00-AD (hex) Advantech Technology (CHINA) Co., Ltd. +C400AD (base 16) Advantech Technology (CHINA) Co., Ltd. + No.666, Han-Pu Rd. Yu-Shan + Kun-Shan Jiang Su 215316 + CN + +94-FE-9D (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +94FE9D (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + SONGGANG + SHENZHEN GUANGDONG 518105 + CN + +6C-B6-CA (hex) DIVUS GmbH +6CB6CA (base 16) DIVUS GmbH + Pillhof 51 + Eppan 39057 + IT + +04-D1-3A (hex) Xiaomi Communications Co Ltd +04D13A (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +4C-C2-06 (hex) Somfy +4CC206 (base 16) Somfy + 50 avenue du nouveau monde + Cluses 74300 + FR + +04-09-73 (hex) Hewlett Packard Enterprise +040973 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +34-99-D7 (hex) Universal Flow Monitors, Inc. +3499D7 (base 16) Universal Flow Monitors, Inc. + 1755 E. Nine Mile Rd. + Hazel Park MI 48030 + US + +0C-8B-D3 (hex) ITEL MOBILE LIMITED +0C8BD3 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +C0-A8-F0 (hex) Adamson Systems Engineering +C0A8F0 (base 16) Adamson Systems Engineering + 1401 Scugog Line 6 + Port Perry Ontario L9L 1B2 + CA + +9C-43-1E (hex) IEEE Registration Authority +9C431E (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-24-AF (hex) Dish Technologies Corp +0024AF (base 16) Dish Technologies Corp + 94 Inverness Terrace E + Englewood CO 80112 + US + +28-2C-02 (hex) IEEE Registration Authority +282C02 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +FC-A1-83 (hex) Amazon Technologies Inc. +FCA183 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno 89507 + US + +6C-2A-CB (hex) Paxton Access Ltd +6C2ACB (base 16) Paxton Access Ltd + Paxton House + Brighton East Sussex BN1 9HU + GB + +58-3B-D9 (hex) Fiberhome Telecommunication Technologies Co.,LTD +583BD9 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +DC-A2-66 (hex) Hon Hai Precision Ind. Co.,Ltd. +DCA266 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +C4-84-66 (hex) Apple, Inc. +C48466 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-7C-25 (hex) Apple, Inc. +347C25 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +CC-2D-B7 (hex) Apple, Inc. +CC2DB7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-BD-CD (hex) BSkyB Ltd +A0BDCD (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +BC-91-B5 (hex) Infinix mobility limited +BC91B5 (base 16) Infinix mobility limited + RMS 05-15, 13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG + HongKong HongKong 999077 + HK + +28-2F-C2 (hex) Automotive Data Solutions +282FC2 (base 16) Automotive Data Solutions + 8400 rue Bougainville + Montreal Quebec H4P2G1 + CA + +98-00-74 (hex) Raisecom Technology CO., LTD +980074 (base 16) Raisecom Technology CO., LTD + No. 11, East Area, No. 10 Block, East Xibeiwang Road + Beijing 100094 + CN + +18-C1-9D (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +18C19D (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +0C-98-38 (hex) Xiaomi Communications Co Ltd +0C9838 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +74-EA-CB (hex) New H3C Technologies Co., Ltd +74EACB (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +D4-1A-3F (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +D41A3F (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +D8-B1-22 (hex) Juniper Networks +D8B122 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +B4-C7-99 (hex) Extreme Networks, Inc. +B4C799 (base 16) Extreme Networks, Inc. + 475 Half Day Road + Lincolnshire IL 60069 + US + +64-6E-6C (hex) Radio Datacom LLC +646E6C (base 16) Radio Datacom LLC + 9601 N 35th St + Phoenix AZ 85028 + US + +E8-8E-60 (hex) NSD Corporation +E88E60 (base 16) NSD Corporation + Osu 3-31-28 + Nagoya Aichi 460-8302 + JP + +00-0F-9B (hex) Ross Video Limited +000F9B (base 16) Ross Video Limited + 8 John Street + Iroquois Ontario K0E 1K0 + CA + +00-24-BA (hex) Texas Instruments +0024BA (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +60-51-2C (hex) TCT mobile ltd +60512C (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +64-DB-81 (hex) Syszone Co., Ltd. +64DB81 (base 16) Syszone Co., Ltd. + 9F Garak, 310 Ogeum-ro + Seoul Seoul, Korea 138-716 + KR + +44-AD-19 (hex) XINGFEI (H.K)LIMITED +44AD19 (base 16) XINGFEI (H.K)LIMITED + 6/F North Tower Wandelai Building  No.29 Kejinan 6th Road, Nanshan District,Shenzhen,China + Shenzhen 518057 + CN + +38-AD-BE (hex) New H3C Technologies Co., Ltd +38ADBE (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +5C-AD-76 (hex) Shenzhen TCL New Technology Co., Ltd +5CAD76 (base 16) Shenzhen TCL New Technology Co., Ltd + B area,10 Floor, TCL Multimedia Building, TCL International E city, #1001 Zhongshan Park Road, Nanshan District + Shenzhen Guangdong 518052 + CN + +5C-86-5C (hex) Samsung Electronics Co.,Ltd +5C865C (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +04-F1-28 (hex) HMD Global Oy +04F128 (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +04-B1-67 (hex) Xiaomi Communications Co Ltd +04B167 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +EC-83-50 (hex) Microsoft Corporation +EC8350 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +D0-07-CA (hex) Juniper Networks +D007CA (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +1C-DF-52 (hex) Texas Instruments +1CDF52 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +30-C5-07 (hex) ECI Telecom Ltd. +30C507 (base 16) ECI Telecom Ltd. + 30 Hasivim St. + Petah Tikva 49133 + IL + +C8-45-8F (hex) Wyler AG +C8458F (base 16) Wyler AG + Im Hoelderli 13 + Winterthur ZH 8405 + CH + +00-1B-B9 (hex) Elitegroup Computer Systems Co.,Ltd. +001BB9 (base 16) Elitegroup Computer Systems Co.,Ltd. + No.22, Alley 38, Lane 91 , Sec. 1 , Nei Hu Road + Taipei 114 + TW + +00-24-61 (hex) Shin Wang Tech. +002461 (base 16) Shin Wang Tech. + 632-62, Guro-Dong, Guro-Gu + Seoul 152-866 + KR + +E4-A7-A0 (hex) Intel Corporate +E4A7A0 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +0C-52-03 (hex) AGM GROUP LIMITED +0C5203 (base 16) AGM GROUP LIMITED + 4F,Building B,HuaFeng Ind park,Gushu,Xixiang,BaoAn,ShenZhen,China + ShenZhen GuangDong 518100 + CN + +2C-54-91 (hex) Microsoft Corporation +2C5491 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +38-17-C3 (hex) Hewlett Packard Enterprise +3817C3 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +00-1E-1D (hex) East Coast Datacom, Inc. +001E1D (base 16) East Coast Datacom, Inc. + 245 Gus Hipp Blvd., STE 3 + Rockledge FL 32955 + US + +78-46-C4 (hex) DAEHAP HYPER-TECH +7846C4 (base 16) DAEHAP HYPER-TECH + #A-805, Woolim Lions Vally 5-cha, #144-3 Sangdaewon-dong, Jungwon-Gu + Seongnam 462-726 + US + +5C-E2-8C (hex) Zyxel Communications Corporation +5CE28C (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +E4-BD-4B (hex) zte corporation +E4BD4B (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +38-D7-CA (hex) 7HUGS LABS +38D7CA (base 16) 7HUGS LABS + 29 bd Romain Rolland + Montrouge 92120 + FR + +00-01-44 (hex) Dell EMC +000144 (base 16) Dell EMC + 228 South St. + Hopkinton MA 01748 + US + +08-00-1B (hex) Dell EMC +08001B (base 16) Dell EMC + 176 South Street + Hopkinton MA 01748 + US + +7C-01-0A (hex) Texas Instruments +7C010A (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +E4-2B-34 (hex) Apple, Inc. +E42B34 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-2E-F9 (hex) Apple, Inc. +3C2EF9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-4E-A7 (hex) Apple, Inc. +A04EA7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-98-9D (hex) Apple, Inc. +F0989D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-D6-BD (hex) Robert Bosch GmbH +FCD6BD (base 16) Robert Bosch GmbH + AE-BE/EKE + Leonberg BW 71206 + DE + +70-1F-53 (hex) Cisco Systems, Inc +701F53 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +18-39-6E (hex) SUNSEA TELECOMMUNICATIONS CO.,LTD. +18396E (base 16) SUNSEA TELECOMMUNICATIONS CO.,LTD. + High tech Industrial Park,Longhua District of Shenzhen City,South central concept + Shenzhen 518110 + CN + +EC-7D-11 (hex) vivo Mobile Communication Co., Ltd. +EC7D11 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +48-0E-EC (hex) TP-LINK TECHNOLOGIES CO.,LTD. +480EEC (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +50-3E-AA (hex) TP-LINK TECHNOLOGIES CO.,LTD. +503EAA (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +58-00-BB (hex) Juniper Networks +5800BB (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +48-BA-4E (hex) Hewlett Packard +48BA4E (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +D8-08-31 (hex) Samsung Electronics Co.,Ltd +D80831 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +94-41-C1 (hex) Mini-Cam Limited +9441C1 (base 16) Mini-Cam Limited + Unit 4 Yew Tree Way + Warrington Cheshire WA33JD + GB + +50-4E-DC (hex) Ping Communication +504EDC (base 16) Ping Communication + Brenden 18 + Appenzell Meistersrüte AI 9050 + CH + +08-67-4E (hex) Hisense broadband multimedia technology Co.,Ltd +08674E (base 16) Hisense broadband multimedia technology Co.,Ltd + Song ling Road 399 + Qingdao 266000 + CN + +50-0F-80 (hex) Cisco Systems, Inc +500F80 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +10-F1-F2 (hex) LG Electronics (Mobile Communications) +10F1F2 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +8C-68-C8 (hex) zte corporation +8C68C8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +EC-82-63 (hex) zte corporation +EC8263 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +68-3C-7D (hex) Magic Intelligence Technology Limited +683C7D (base 16) Magic Intelligence Technology Limited + B13/Flat 4,East block,Jinhui Blding.Nanhai Road + Nanshan District, Shenzhen guangdong 518000 + CN + +0C-1C-20 (hex) Kakao Corp +0C1C20 (base 16) Kakao Corp + 242, Cheomdan-ro + Jeju-si Jeju-do 63309 + KR + +24-F5-A2 (hex) Belkin International Inc. +24F5A2 (base 16) Belkin International Inc. + 12045 East Waterfront Drive + Playa Vista null 90094 + US + +74-BB-D3 (hex) Shenzhen xeme Communication Co., Ltd. +74BBD3 (base 16) Shenzhen xeme Communication Co., Ltd. + 303,Block D,Huayuan technology innovation park,Bao Yuen road,Xixiang street,Baoan District + Shenzhen Guangdong 518102 + CN + +94-28-2E (hex) New H3C Technologies Co., Ltd +94282E (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +98-F5-A9 (hex) OHSUNG +98F5A9 (base 16) OHSUNG + 181 + GUMI KYUNGBUK 730-030 + KR + +D8-9E-F3 (hex) Dell Inc. +D89EF3 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +38-4F-49 (hex) Juniper Networks +384F49 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +4C-BD-8F (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +4CBD8F (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road + Hangzhou Zhejiang 310052 + CN + +EC-EB-B8 (hex) Hewlett Packard Enterprise +ECEBB8 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +6C-B7-49 (hex) HUAWEI TECHNOLOGIES CO.,LTD +6CB749 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +98-9C-57 (hex) HUAWEI TECHNOLOGIES CO.,LTD +989C57 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-52-82 (hex) Fiberhome Telecommunication Technologies Co.,LTD +185282 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +8C-3C-4A (hex) NAKAYO Inc +8C3C4A (base 16) NAKAYO Inc + Development Support Center 165 Higashiomuro-machi + Maebashi-shi Gunma 379-2105 + JP + +70-86-C1 (hex) Texas Instruments +7086C1 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +F4-D7-B2 (hex) LGS Innovations, LLC +F4D7B2 (base 16) LGS Innovations, LLC + 13665 Dulles Technology Drive + Herndon VA 20171 + US + +00-15-2A (hex) Nokia Corporation +00152A (base 16) Nokia Corporation + Rensingstraße 15 + Bochum NRW 44807 + DE + +9C-4A-7B (hex) Nokia Corporation +9C4A7B (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu Ou 90590 + FI + +D8-61-62 (hex) Wistron Neweb Corporation +D86162 (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +28-84-0E (hex) silicon valley immigration service +28840E (base 16) silicon valley immigration service + 1410 Sharp Ave, + Campbell CA 95008 + US + +80-61-5F (hex) Beijing Sinead Technology Co., Ltd. +80615F (base 16) Beijing Sinead Technology Co., Ltd. + Room 504,Block A, New material Building, Yongfeng industrial, Haiding District, Beijing.China + Beijing Beijing 100000 + CN + +2C-D2-E7 (hex) Nokia Corporation +2CD2E7 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu Ou 90590 + FI + +38-6E-A2 (hex) vivo Mobile Communication Co., Ltd. +386EA2 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +98-2D-68 (hex) Samsung Electronics Co., Ltd +982D68 (base 16) Samsung Electronics Co., Ltd + Samsung 1-ro + Hwaseong-si Gyeonggi-do 445330 + KR + +BC-2E-48 (hex) ARRIS Group, Inc. +BC2E48 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +60-8C-E6 (hex) ARRIS Group, Inc. +608CE6 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +08-00-70 (hex) Mitsubishi Precision Co.,LTd. +080070 (base 16) Mitsubishi Precision Co.,LTd. + 325 KAMIMACHIYA + 000 00 + JP + +44-4A-B0 (hex) Zhejiang Moorgen Intelligence Technology Co., Ltd +444AB0 (base 16) Zhejiang Moorgen Intelligence Technology Co., Ltd + No.181 Changluo road Luotuo street Zhenhai district + Ningbo Zhejiang 315202 + CN + +DC-6A-EA (hex) Infinix mobility limited +DC6AEA (base 16) Infinix mobility limited + RMS 05-15, 13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG + HongKong HongKong 999077 + HK + +C4-21-C8 (hex) KYOCERA CORPORATION +C421C8 (base 16) KYOCERA CORPORATION + 2-1-1,Kagahara, + Yokohama-shi Kanagawa 224-8502 + JP + +80-73-9F (hex) KYOCERA CORPORATION +80739F (base 16) KYOCERA CORPORATION + 2-1-1 Kagahara + Yokohama-shi Kanagawa 224-8502 + JP + +48-EC-5B (hex) Nokia +48EC5B (base 16) Nokia + Karaportti 3 + Espoo Finland 02610 + FI + +70-58-12 (hex) Panasonic Corporation AVC Networks Company +705812 (base 16) Panasonic Corporation AVC Networks Company + 1-15 Matsuo-cho + Kadoma Osaka 571-8504 + JP + +04-20-9A (hex) Panasonic Corporation AVC Networks Company +04209A (base 16) Panasonic Corporation AVC Networks Company + 1-15 Matsuo-cho + Kadoma City Osaka 571-8504 + JP + +34-00-8A (hex) IEEE Registration Authority +34008A (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +A4-11-15 (hex) Robert Bosch Engineering and Business Solutions pvt. Ltd. +A41115 (base 16) Robert Bosch Engineering and Business Solutions pvt. Ltd. + 123, Industrial Layout, Hosur Road, Koramangala, + Bangalore Karnataka 560095 + IN + +40-D6-3C (hex) Equitech Industrial(DongGuan)Co.,Ltd +40D63C (base 16) Equitech Industrial(DongGuan)Co.,Ltd + 4F Building B No.2 ShiChang Road SongYuan Technology Park,DongCheng District + DongGuan GuangDong 523122 + CN + +F4-F3-AA (hex) JBL GmbH & Co. KG +F4F3AA (base 16) JBL GmbH & Co. KG + Dieselstrasse 3 + Neuhofen 67141 + DE + +40-A3-CC (hex) Intel Corporate +40A3CC (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +90-50-CA (hex) Hitron Technologies. Inc +9050CA (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +40-99-22 (hex) AzureWave Technology Inc. +409922 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +C0-6D-1A (hex) Tianjin Henxinhuifeng Technology Co.,Ltd. +C06D1A (base 16) Tianjin Henxinhuifeng Technology Co.,Ltd. + Rm 233, Tianjin Technology Innovation Service Center, 12 Keyan West Road, Nankai District, Tianjin, P.R.C. + Tianjin Tianjin 300192 + CN + +10-7B-44 (hex) ASUSTek COMPUTER INC. +107B44 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +84-25-3F (hex) silex technology, Inc. +84253F (base 16) silex technology, Inc. + 2-3-1 Hikaridai + Seika-cho Kyoto 619-0237 + JP + +00-08-C9 (hex) TechniSat Digital GmbH Daun +0008C9 (base 16) TechniSat Digital GmbH Daun + Gewerbepark Merbitz Nr. 5 + Dresden 01156 + US + +D8-B1-2A (hex) Panasonic Mobile Communications Co.,Ltd. +D8B12A (base 16) Panasonic Mobile Communications Co.,Ltd. + 600 Saedo-cho Tsuzuki-ku + Yokohama City Kanagawa 224-8539 + JP + +B0-19-C6 (hex) Apple, Inc. +B019C6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-66-F0 (hex) Apple, Inc. +3866F0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-80-09 (hex) JUPITER SYSTEMS, INC. +008009 (base 16) JUPITER SYSTEMS, INC. + 3073 TEAGARDEN STREET + SAN LEANDRO CA 94577-5720 + US + +00-C0-64 (hex) General Datacomm LLC +00C064 (base 16) General Datacomm LLC + 353 Christian Street, Suite 4 + Oxford CT 06478 + US + +E8-68-19 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E86819 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +1C-AB-34 (hex) New H3C Technologies Co., Ltd +1CAB34 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +3C-78-43 (hex) HUAWEI TECHNOLOGIES CO.,LTD +3C7843 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +5C-09-79 (hex) HUAWEI TECHNOLOGIES CO.,LTD +5C0979 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E4-FB-5D (hex) HUAWEI TECHNOLOGIES CO.,LTD +E4FB5D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-01-CC (hex) Japan Total Design Communication Co., Ltd. +0001CC (base 16) Japan Total Design Communication Co., Ltd. + Enesta Suginamihigashi Build., 3F, + + JP + +00-30-C8 (hex) GAD LINE, LTD. +0030C8 (base 16) GAD LINE, LTD. + BEIT ROKAR HAR HOTZVIM + + IL + +00-16-E0 (hex) 3Com Ltd +0016E0 (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +D8-DE-CE (hex) ISUNG CO.,LTD +D8DECE (base 16) ISUNG CO.,LTD + 92, Huimanggongwon-ro + Siheung-si Kyunggido 429-859 + KR + +80-19-34 (hex) Intel Corporate +801934 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +70-3E-AC (hex) Apple, Inc. +703EAC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-11-C0 (hex) Aday Technology Inc +0011C0 (base 16) Aday Technology Inc + 9F.-3, No. 247, Sec. 1, Taichung Port Rd., + Taichung City 403 + TW + +00-05-F1 (hex) Vrcom, Inc. +0005F1 (base 16) Vrcom, Inc. + 401, Songam Bldg, 479-1, + Seoul + KR + +AC-51-2C (hex) Infinix mobility limited +AC512C (base 16) Infinix mobility limited + RMS 05-15, 13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG + HongKong HongKong 999077 + HK + +30-99-35 (hex) zte corporation +309935 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +0C-72-D9 (hex) zte corporation +0C72D9 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +10-62-D0 (hex) Technicolor CH USA Inc. +1062D0 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +50-64-2B (hex) XIAOMI Electronics,CO.,LTD +50642B (base 16) XIAOMI Electronics,CO.,LTD + Xiaomi Building, No.68 Qinghe Middle Street + Haidian District Beijing 100085 + CN + +28-40-1A (hex) C8 MediSensors, Inc. +28401A (base 16) C8 MediSensors, Inc. + 727 University Ave + Los Gatos CA 95032 + US + +30-C0-1B (hex) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd +30C01B (base 16) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + 3/F,A5 Building Zhiyuan Community No.1001,Xueyuan Road Nanshan District + Shenzhen Guangdong 518055 + CN + +88-86-C2 (hex) STABILO International GmbH +8886C2 (base 16) STABILO International GmbH + Schwanweg 1 + Heroldsberg 90562 + DE + +08-A8-A1 (hex) Cyclotronics Power Concepts, Inc +08A8A1 (base 16) Cyclotronics Power Concepts, Inc + PO Box 37449 + Houston TX 77237-7449 + US + +F4-B5-20 (hex) Biostar Microtech international corp. +F4B520 (base 16) Biostar Microtech international corp. + 3F. No. 108-2 Min Chuan Road, Hsin Tien District + New Taipei City Taiwan 231 + TW + +CC-2F-71 (hex) Intel Corporate +CC2F71 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1C-C5 (hex) 3Com Ltd +001CC5 (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +88-7A-31 (hex) Velankani Electronics Pvt. Ltd. +887A31 (base 16) Velankani Electronics Pvt. Ltd. + 43, Electronics City, Phase 1, Hosur road + Bangalore Karnataka 560100 + IN + +8C-0F-6F (hex) PEGATRON CORPORATION +8C0F6F (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +8C-25-05 (hex) HUAWEI TECHNOLOGIES CO.,LTD +8C2505 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +8C-3B-AD (hex) NETGEAR +8C3BAD (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +64-CF-D9 (hex) Texas Instruments +64CFD9 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +64-32-A8 (hex) Intel Corporate +6432A8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +74-7D-24 (hex) Phicomm (Shanghai) Co., Ltd. +747D24 (base 16) Phicomm (Shanghai) Co., Ltd. + 3666 SiXian Rd.,Songjiang District + Shanghai Shanghai 201616 + CN + +D0-94-66 (hex) Dell Inc. +D09466 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +38-E5-95 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +38E595 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + B116,B118,A211-A213,B201-B213,A311-A313,B411-413,BF08-09 Nanshan Medical Instrument Industry Park, + Shenzhen Guangdong 518067 + CN + +BC-96-80 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +BC9680 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + B116,B118,A211-A213,B201-B213,A311-A313,B411-413,BF08-09 Nanshan Medical Instrument Industry Park, + Shenzhen Guangdong 518067 + CN + +A4-7B-9D (hex) Espressif Inc. +A47B9D (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +B8-F8-BE (hex) BLUECOM +B8F8BE (base 16) BLUECOM + 116, Venture-ro, Yeonsu-gu, + Incheon 406-840 + KR + +00-24-82 (hex) Ruckus Wireless +002482 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +68-92-34 (hex) Ruckus Wireless +689234 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +50-A7-33 (hex) Ruckus Wireless +50A733 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +2C-5D-93 (hex) Ruckus Wireless +2C5D93 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +38-FF-36 (hex) Ruckus Wireless +38FF36 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +84-18-3A (hex) Ruckus Wireless +84183A (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +24-C9-A1 (hex) Ruckus Wireless +24C9A1 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +7C-2E-DD (hex) Samsung Electronics Co.,Ltd +7C2EDD (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +3C-F7-A4 (hex) Samsung Electronics Co.,Ltd +3CF7A4 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +10-30-34 (hex) Cara Systems +103034 (base 16) Cara Systems + Ruzgarlibahce Mah. Kavak Sok. No: 31/1 Smart Plaza B Blok Kat: 4 + Istanbul Kavacik Beykoz 23805 + TR + +00-00-FE (hex) Annapolis Micro Systems, Inc. +0000FE (base 16) Annapolis Micro Systems, Inc. + 190 ADMIRAL COCHRANE DRIVE + ANNAPOLIS MD 21401 + US + +00-D0-1F (hex) Senetas Corporation Ltd +00D01F (base 16) Senetas Corporation Ltd + 1/11 Queens Road + consolidation consolidation + AU + +E0-CB-BC (hex) Cisco Meraki +E0CBBC (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco null 94158 + US + +64-47-E0 (hex) Feitian Technologies Co., Ltd +6447E0 (base 16) Feitian Technologies Co., Ltd + Floor 17, Tower B, Huizhi Mansion, No.9 Xueqing Rd, Haidian District + Beijing 100085 + CN + +B4-4F-96 (hex) Zhejiang Xinzailing Technology co., ltd +B44F96 (base 16) Zhejiang Xinzailing Technology co., ltd + No.1805, Dongliu Road, Binjiang District + Hangzhou Zhejiang 310051 + CN + +4C-65-A8 (hex) IEEE Registration Authority +4C65A8 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +B0-DF-C1 (hex) Tenda Technology Co.,Ltd.Dongguan branch +B0DFC1 (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +9C-6F-52 (hex) zte corporation +9C6F52 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +E8-6D-65 (hex) AUDIO MOBIL Elektronik GmbH +E86D65 (base 16) AUDIO MOBIL Elektronik GmbH + Audio-Mobil-Straße 5 - 7 + Braunau am Inn - Ranshofen 5282 + AT + +70-6E-6D (hex) Cisco Systems, Inc +706E6D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +60-47-62 (hex) Beijing Sensoro Technology Co.,Ltd. +604762 (base 16) Beijing Sensoro Technology Co.,Ltd. + Room 2807, Building 1B, Wangjing SOHO, No10 Wangjing Street, Chaoyang District, Beijing, China + Beijing Beijing 100102 PRC + CN + +BC-1C-81 (hex) Sichuan iLink Technology Co., Ltd. +BC1C81 (base 16) Sichuan iLink Technology Co., Ltd. + Anzhou,Industrial park,Mianyang,Sichuan + Mianyang 622651 + CN + +90-0A-1A (hex) Taicang T&W Electronics +900A1A (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +50-6E-92 (hex) Innocent Technology Co., Ltd. +506E92 (base 16) Innocent Technology Co., Ltd. + PROSIT AZUMA 3 #201, 1973, NIPPA-CHO, KOHOKU-KU, + YOKOHAMA-SHI KANAGAWA 2230057 + JP + +30-FE-31 (hex) Nokia +30FE31 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +98-F2-B3 (hex) Hewlett Packard Enterprise +98F2B3 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +C4-57-1F (hex) June Life Inc +C4571F (base 16) June Life Inc + 649 Front Street + San Francisco CA 94111 + US + +88-6A-E3 (hex) Alpha Networks Inc. +886AE3 (base 16) Alpha Networks Inc. + No.8 Li-shing 7th Rd., Science-based Industrial Park, Hsinchu, Taiwan, R.O.C + Hsinchu Taiwan 300 + TW + +1C-4D-70 (hex) Intel Corporate +1C4D70 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +D8-22-F4 (hex) Avnet Silica +D822F4 (base 16) Avnet Silica + 16 av carnot + Massy 91349 + FR + +34-8F-27 (hex) Ruckus Wireless +348F27 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +2C-9E-EC (hex) Jabil Circuit Penang +2C9EEC (base 16) Jabil Circuit Penang + Plot 56 , Hilir Sungai Keluang 1, Bayan Lepas Industrial Park, Phase 4 + George Town Penang 11900 + MY + +00-1C-FA (hex) Alarm.com +001CFA (base 16) Alarm.com + 8150 Leesburg Pike + Vienna VA 22182 + US + +60-31-3B (hex) Sunnovo International Limited +60313B (base 16) Sunnovo International Limited + 1717 Haitai Building + Beijing Beijing 100083 + CN + +6C-B2-27 (hex) Sony Video & Sound Products Inc. +6CB227 (base 16) Sony Video & Sound Products Inc. + Sony City Osaki, 2-10-1 Osaki + Shinagawa-ku Tokyo 141-8610 + JP + +98-6F-60 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +986F60 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +00-0C-AB (hex) Commend International GmbH +000CAB (base 16) Commend International GmbH + Hoelzlstrasse 561 + Wals Salzburg A-5071 + AT + +74-54-27 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +745427 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +60-72-0B (hex) BLU Products Inc +60720B (base 16) BLU Products Inc + 10814 NW 33rd Street + Miami FL 33172 + US + +30-89-76 (hex) DALIAN LAMBA TECHNOLOGY CO.,LTD +308976 (base 16) DALIAN LAMBA TECHNOLOGY CO.,LTD + Dalian Hi-tech Zone Keypark Room 1201 + Dalian Liaoning 116000 + CN + +2C-26-17 (hex) Oculus VR, LLC +2C2617 (base 16) Oculus VR, LLC + 1 Hacker Way + Menlo Park CA 94025 + US + +34-D9-54 (hex) WiBotic Inc. +34D954 (base 16) WiBotic Inc. + 4000 15th Ave NE Lab 225, Fluke Hall, Box 352141 + Seattle WA 98195 + US + +48-57-DD (hex) Facebook Inc +4857DD (base 16) Facebook Inc + 1 Hacker Way + Menlo Park 94025 + US + +48-7D-2E (hex) TP-LINK TECHNOLOGIES CO.,LTD. +487D2E (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +B0-DA-F9 (hex) ARRIS Group, Inc. +B0DAF9 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +18-35-D1 (hex) ARRIS Group, Inc. +1835D1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +C0-A5-DD (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +C0A5DD (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + 3/F, Building R1-B, High-Tech Industrial Park, Nanshan District + Shenzhen Guangdong 518057 + CN + +48-8D-36 (hex) Arcadyan Corporation +488D36 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +BC-D7-13 (hex) Owl Labs +BCD713 (base 16) Owl Labs + 33-1/2 Union Square + Somerville MA 02143 + US + +E8-E1-E1 (hex) Gemtek Technology Co., Ltd. +E8E1E1 (base 16) Gemtek Technology Co., Ltd. + No.15-1 Zhonghua Road + Hukou Hsinchu 30352 + TW + +28-07-0D (hex) GUANGZHOU WINSOUND INFORMATION TECHNOLOGY CO.,LTD. +28070D (base 16) GUANGZHOU WINSOUND INFORMATION TECHNOLOGY CO.,LTD. + Building1 NO.13 DABU ROAD HUADU DISTRICT + GUANGZHOU GUANGDONG 510800 + CN + +00-A3-D1 (hex) Cisco Systems, Inc +00A3D1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +FC-4D-8C (hex) SHENZHEN PANTE ELECTRONICS TECHNOLOGY CO., LTD +FC4D8C (base 16) SHENZHEN PANTE ELECTRONICS TECHNOLOGY CO., LTD + Building 5,Hui Mingsheng industrial park,Tongfu Rd,Fu Yong street + Shenzhen Guangdong 518042 + CN + +FC-06-ED (hex) M2Motive Technology Inc. +FC06ED (base 16) M2Motive Technology Inc. + Room 148, Lane 999, new two road, Baoshan District + Shanghai Shanghai 200439 + CN + +F0-D4-F6 (hex) Lars Thrane A/S +F0D4F6 (base 16) Lars Thrane A/S + Stubbeled 2 + Vedbæk 2950 + DK + +F4-A9-97 (hex) CANON INC. +F4A997 (base 16) CANON INC. + 30-2 Shimomaruko 3-chome, + Ohta-ku Tokyo 146-8501 + JP + +64-DF-E9 (hex) ATEME +64DFE9 (base 16) ATEME + 6 rue Dewoitine + Vélizy-Villacoublay 78140 + FR + +10-C6-FC (hex) Garmin International +10C6FC (base 16) Garmin International + 1200 East 151st Street + Olathe KS 66062 + US + +AC-22-05 (hex) Compal Broadband Networks, Inc. +AC2205 (base 16) Compal Broadband Networks, Inc. + 13F., No.1, Taiyuan 1st St. + Zhubei City Hsinchu County 30265 + TW + +80-A0-36 (hex) Shanghai MXCHIP Information Technology Co., Ltd. +80A036 (base 16) Shanghai MXCHIP Information Technology Co., Ltd. + 9th Floor, No. 5 Building, 2145 Jinshajiang Rd., Putuo District + Shanghai 200333 + CN + +F0-74-85 (hex) NGD Systems, Inc. +F07485 (base 16) NGD Systems, Inc. + 355 Goddard, Suite 200 + Irvine CA 92618 + US + +40-5C-FD (hex) Dell Inc. +405CFD (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +20-F4-52 (hex) Shanghai IUV Software Development Co. Ltd +20F452 (base 16) Shanghai IUV Software Development Co. Ltd + No.18, Lane 1387 Zhangdong Rd, Pudong, Shanghai, P.R.C + shanghai shanghai 201203 + CN + +50-9A-4C (hex) Dell Inc. +509A4C (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +A0-09-4C (hex) CenturyLink +A0094C (base 16) CenturyLink + 100 CenturyLink Drive + Monroe 71203 + US + +B4-39-34 (hex) Pen Generations, Inc. +B43934 (base 16) Pen Generations, Inc. + 8th FL., SOLiD Space, + Seongnam-si Gyeonggi-do 463-400 + KR + +74-26-AC (hex) Cisco Systems, Inc +7426AC (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +B0-26-28 (hex) Broadcom Limited +B02628 (base 16) Broadcom Limited + 5300 California Ave. + irvine CA 92617 + US + +98-74-DA (hex) Infinix mobility limited +9874DA (base 16) Infinix mobility limited + RMS 05-15, 13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG + HongKong HongKong 999077 + HK + +40-B4-F0 (hex) Juniper Networks +40B4F0 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +14-3F-27 (hex) Noccela Oy +143F27 (base 16) Noccela Oy + Kaarinantie 700 + Turku 20540 + FI + +10-58-87 (hex) Fiberhome Telecommunication Technologies Co.,LTD +105887 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +70-4C-A5 (hex) Fortinet, Inc. +704CA5 (base 16) Fortinet, Inc. + 899 Kifer Road + Sunnyvale null 94086 + US + +9C-06-1B (hex) Hangzhou H3C Technologies Co., Limited +9C061B (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +50-33-8B (hex) Texas Instruments +50338B (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +68-26-2A (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +68262A (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +E8-DE-8E (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +E8DE8E (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +D8-D8-66 (hex) SHENZHEN TOZED TECHNOLOGIES CO.,LTD. +D8D866 (base 16) SHENZHEN TOZED TECHNOLOGIES CO.,LTD. + 4F/A1,A2,TIANJI BUILDING,TIAN’AN CYBER PARK,FUTIAN + SHENZHEN GUANGDONG 518040 + CN + +D8-C0-6A (hex) Hunantv.com Interactive Entertainment Media Co.,Ltd. +D8C06A (base 16) Hunantv.com Interactive Entertainment Media Co.,Ltd. + Floor 2U, Hunan International Exhibition Center, Kaifu District, Changsha City, Hunan Province, P.R.C. + Changsha Hunan 410000 + CN + +AC-20-2E (hex) Hitron Technologies. Inc +AC202E (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +9C-32-A9 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +9C32A9 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +1C-5A-0B (hex) Tegile Systems +1C5A0B (base 16) Tegile Systems + 7999 Gateway Blvd Suite 120 + Newark CA 94560 + US + +04-6E-02 (hex) OpenRTLS Group +046E02 (base 16) OpenRTLS Group + De Nieuwe Ploeg 5 + Berlicum 5258 EX + NL + +90-0E-83 (hex) Monico Monitoring, Inc. +900E83 (base 16) Monico Monitoring, Inc. + 18530 Klein Church Rd + Spring TX 77379 + US + +60-14-66 (hex) zte corporation +601466 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +68-54-ED (hex) Alcatel-Lucent +6854ED (base 16) Alcatel-Lucent + 777 E. Middlefield Rd + Mountain View CA 94043 + US + +68-02-35 (hex) Konten Networks Inc. +680235 (base 16) Konten Networks Inc. + 7F-1, No.108, Minquan Rd., Xindian Dist., + New Taipei City Taiwan 231 + TW + +38-AC-3D (hex) Nephos Inc +38AC3D (base 16) Nephos Inc + 2840 Junction Ave. , + San Jose CA 95134 + US + +E0-37-BF (hex) Wistron Neweb Corporation +E037BF (base 16) Wistron Neweb Corporation + No.20,Park Avenue II,Hsinchu Science Park + Hsin-Chu R.O.C. 308 + TW + +E8-13-67 (hex) AIRSOUND Inc. +E81367 (base 16) AIRSOUND Inc. + 515-ho,75,Techno-1ro,Yuseoung-gu + Daejeon 34014 + KR + +00-11-92 (hex) Cisco Systems, Inc +001192 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +38-F1-35 (hex) SensorTec-Canada +38F135 (base 16) SensorTec-Canada + 1Yonge Street, Suite 1801 + Toronto ON M5E 1W7 + CA + +AC-74-09 (hex) Hangzhou H3C Technologies Co., Limited +AC7409 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +C4-9D-ED (hex) Microsoft Corporation +C49DED (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +98-A4-0E (hex) Snap, Inc. +98A40E (base 16) Snap, Inc. + 64 Market Street + Venice CA 90291 + US + +F4-03-43 (hex) Hewlett Packard Enterprise +F40343 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +F0-93-C5 (hex) Garland Technology +F093C5 (base 16) Garland Technology + 2130 Oak Bend Lane + Garland TX 75040 + US + +98-10-E8 (hex) Apple, Inc. +9810E8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-D0-12 (hex) Apple, Inc. +C0D012 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-A9-20 (hex) Apple, Inc. +BCA920 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-A1-95 (hex) Apple, Inc. +48A195 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-03-77 (hex) Apple, Inc. +F80377 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-96-34 (hex) Intel Corporate +F49634 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +10-7D-1A (hex) Dell Inc. +107D1A (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +70-AF-24 (hex) TP Vision Belgium NV +70AF24 (base 16) TP Vision Belgium NV + Technologiepark Zwijnaarde 19 + Gent 9052 + BE + +A4-11-63 (hex) IEEE Registration Authority +A41163 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +C4-D1-97 (hex) Ventia Utility Services +C4D197 (base 16) Ventia Utility Services + Level 4, Tower 1, 495 Victoria Avenue + Chatswood NSW 2067 + AU + +2C-86-D2 (hex) Cisco Systems, Inc +2C86D2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +7C-E9-7C (hex) ITEL MOBILE LIMITED +7CE97C (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +80-58-F8 (hex) Motorola Mobility LLC, a Lenovo Company +8058F8 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +DC-A4-CA (hex) Apple, Inc. +DCA4CA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +8C-8F-E9 (hex) Apple, Inc. +8C8FE9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-AF-25 (hex) Nishiyama Industry Co.,LTD. +70AF25 (base 16) Nishiyama Industry Co.,LTD. + 177-2 + Fuji Shizuoka 419-0205 + JP + +E8-D1-1B (hex) ASKEY COMPUTER CORP +E8D11B (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +B8-22-4F (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +B8224F (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +98-00-C1 (hex) GuangZhou CREATOR Technology Co.,Ltd.(CHINA) +9800C1 (base 16) GuangZhou CREATOR Technology Co.,Ltd.(CHINA) + Level 3,Blg 6,No 9 Keji Yuan,LanYusi St, + GuangZhou GuangDong 510730 + CN + +54-E1-AD (hex) LCFC(HeFei) Electronics Technology co., ltd +54E1AD (base 16) LCFC(HeFei) Electronics Technology co., ltd + YunGu Road 3188-1 + Hefei Anhui 230000 + CN + +98-D3-D2 (hex) MEKRA Lang GmbH & Co. KG +98D3D2 (base 16) MEKRA Lang GmbH & Co. KG + Buchheimerstr. 4 + Ergersheim 91465 + DE + +0C-5F-35 (hex) Niagara Video Corporation +0C5F35 (base 16) Niagara Video Corporation + 5627 Stoneridge Drive, Suite 316 + Pleasanton CA 94588 + US + +CC-BE-59 (hex) Calix Inc. +CCBE59 (base 16) Calix Inc. + 2777 Orchard Parkway + San Jose CA 95134 + US + +F8-A3-4F (hex) zte corporation +F8A34F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-19-12 (hex) Welcat Inc +001912 (base 16) Welcat Inc + East Tower 6F, Shinagawa Seaside, 4-12-8, Higashi Shinagawa, Shinagawa Section + Tokyo 140-0002 + JP + +8C-78-D7 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +8C78D7 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +B8-EA-AA (hex) ICG NETWORKS CO.,ltd +B8EAAA (base 16) ICG NETWORKS CO.,ltd + Room 2030,Block B,Yamei Park,Haidian District + BEIJING 100010 + CN + +B8-F8-83 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +B8F883 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +DC-FE-18 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +DCFE18 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +70-4F-57 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +704F57 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +B0-C4-6C (hex) Senseit +B0C46C (base 16) Senseit + Suschevsky val 16 str. 4 + Moscow Russian Federation 127018 + RU + +00-02-A1 (hex) World Wide Packets +0002A1 (base 16) World Wide Packets + PO Box 14645 + Spokane WA 99214 + US + +00-E0-22 (hex) Analog Devices, Inc. +00E022 (base 16) Analog Devices, Inc. + Three Technology Way + Norwood MA 02062-2666 + US + +14-B7-F8 (hex) Technicolor CH USA Inc. +14B7F8 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +90-3D-6B (hex) Zicon Technology Corp. +903D6B (base 16) Zicon Technology Corp. + 15F., No.688-2, Zhongzheng Rd., Zhonghe City, Taipei County 235 + Taipei 23586 + TW + +B0-40-89 (hex) Senient Systems LTD +B04089 (base 16) Senient Systems LTD + 152 Morrison St + Edinburgh Other (Non US) EH3 8EB + GB + +54-25-EA (hex) HUAWEI TECHNOLOGIES CO.,LTD +5425EA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +3C-7F-6F (hex) Telechips, Inc. +3C7F6F (base 16) Telechips, Inc. + 19F~23F,Luther Bldg.42, Olympic-ro 35da-gil, Songpa-gu, + Seoul Seoul 05510 + KR + +5C-BA-37 (hex) Microsoft Corporation +5CBA37 (base 16) Microsoft Corporation + 31807 - 25th Ave SW + Federal Way 98023 + US + +00-C0-C6 (hex) PERSONAL MEDIA CORP. +00C0C6 (base 16) PERSONAL MEDIA CORP. + 1-7-7 MY BLDG. HIRATSUKA + + JP + +28-FE-CD (hex) Lemobile Information Technology (Beijing) Co., Ltd. +28FECD (base 16) Lemobile Information Technology (Beijing) Co., Ltd. + 5/F LeEco Building, 105 Yaojiayuan Road, Chaoyang District + Beijing Beijing 100025 + CN + +C8-94-BB (hex) HUAWEI TECHNOLOGIES CO.,LTD +C894BB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +10-B1-F8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +10B1F8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +08-9E-08 (hex) Google, Inc. +089E08 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +00-21-0D (hex) SAMSIN INNOTEC +00210D (base 16) SAMSIN INNOTEC + SARIYUNDONG ILSANDONG-GU + GOYANG KYUNGGI 411530 + KR + +C8-73-24 (hex) Sow Cheng Technology Co. Ltd. +C87324 (base 16) Sow Cheng Technology Co. Ltd. + No.26, Ln. 181, Xinsheng W. Rd., Dali Dist + Taichung 412 + TW + +00-1F-16 (hex) Wistron Corporation +001F16 (base 16) Wistron Corporation + 21F, 88, Sec.1, Hsin Tai Wu Rd., Hsichih, + Taipei Hsien 221 + TW + +00-26-2D (hex) Wistron Corporation +00262D (base 16) Wistron Corporation + 21F, 88, Sec.1, Hsin Tai Wu Rd., Hsichih, + Taipei Hsien 221 + TW + +04-95-E6 (hex) Tenda Technology Co.,Ltd.Dongguan branch +0495E6 (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +50-E6-66 (hex) Shenzhen Techtion Electronics Co., Ltd. +50E666 (base 16) Shenzhen Techtion Electronics Co., Ltd. + Floor 2, C2 Building, Huafeng Industrial Park, Hangcheng Avenue, Gushu, Xixiang, Baoan + Shenzhen Guangdong 518102 + CN + +00-16-D3 (hex) Wistron Corporation +0016D3 (base 16) Wistron Corporation + 21F, 88, Sec.1, Hsin Tai Wu Rd., Hsichih, + Taipei Hsien 221 + TW + +4C-4E-03 (hex) TCT mobile ltd +4C4E03 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +90-86-74 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +908674 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +90-17-11 (hex) Hagenuk Marinekommunikation GmbH +901711 (base 16) Hagenuk Marinekommunikation GmbH + Hamburger Chaussee 25 + Flintbek 24220 + DE + +00-10-DE (hex) INTERNATIONAL DATACASTING CORPORATION +0010DE (base 16) INTERNATIONAL DATACASTING CORPORATION + 2680 QUEENSVIEW DRIVE + OTTAWA, ONTARIO K2B 8H6 + CA + +C0-D9-F7 (hex) ShanDong Domor Intelligent S&T CO.,Ltd +C0D9F7 (base 16) ShanDong Domor Intelligent S&T CO.,Ltd + Jining high-tech zone base of production,education & research + Jining Shandong 272000 + CN + +00-60-8B (hex) ConferTech International +00608B (base 16) ConferTech International + 12110 N. PECOS STREET + WESTMINSTER CO 80234-2074 + US + +70-2D-84 (hex) i4C Innovations +702D84 (base 16) i4C Innovations + 3800 Concorde Parkway, Suite 400 + Chantilly VA 20151 + US + +2C-20-0B (hex) Apple, Inc. +2C200B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-66-A5 (hex) Apple, Inc. +8866A5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-02-77 (hex) Cash Systemes Industrie +000277 (base 16) Cash Systemes Industrie + Technoparc Epsilon + + FR + +CC-A2-19 (hex) SHENZHEN ALONG INVESTMENT CO.,LTD +CCA219 (base 16) SHENZHEN ALONG INVESTMENT CO.,LTD + Room 1301,13F,Zhenye international Business Center,No.3101-90,Qianhai Road,Nanshan District + Shenzhen Guangdong Province 518052 + CN + +4C-1A-3A (hex) PRIMA Research And Production Enterprise Ltd. +4C1A3A (base 16) PRIMA Research And Production Enterprise Ltd. + 63, Svobody st. + Nizhny Novgorod 603003 + RU + +14-B3-1F (hex) Dell Inc. +14B31F (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +AC-C1-EE (hex) Xiaomi Communications Co Ltd +ACC1EE (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +54-19-C8 (hex) vivo Mobile Communication Co., Ltd. +5419C8 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +B0-B9-8A (hex) NETGEAR +B0B98A (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +80-5A-04 (hex) LG Electronics (Mobile Communications) +805A04 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +8C-A5-A1 (hex) Oregano Systems - Design & Consulting GmbH +8CA5A1 (base 16) Oregano Systems - Design & Consulting GmbH + Franzosengraben 8 + Vienna 1030 + AT + +B8-EC-A3 (hex) Zyxel Communications Corporation +B8ECA3 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +BC-83-85 (hex) Microsoft Corporation +BC8385 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +00-14-38 (hex) Hewlett Packard Enterprise +001438 (base 16) Hewlett Packard Enterprise + 20555 State Highway 249 + Houston TX 77070 + US + +E4-B0-05 (hex) Beijing IQIYI Science & Technology Co., Ltd. +E4B005 (base 16) Beijing IQIYI Science & Technology Co., Ltd. + Room 1101, Floor 11, Capital Development Tower, No.2 Haidian North 1st Street,Haidian District, + Beijing 100080 + CN + +00-00-48 (hex) Seiko Epson Corporation +000048 (base 16) Seiko Epson Corporation + 80 HIROOKA SHIOJIRI-CITY + japan JAPAN 399-07 + JP + +B0-E8-92 (hex) Seiko Epson Corporation +B0E892 (base 16) Seiko Epson Corporation + 3-3-5 OWA + SUWA-SHI NAGANO-KEN 392-8502 + JP + +AC-18-26 (hex) Seiko Epson Corporation +AC1826 (base 16) Seiko Epson Corporation + 3-3-5 OWA + SUWA-SHI NAGANO-KEN 392-8502 + JP + +A4-EE-57 (hex) Seiko Epson Corporation +A4EE57 (base 16) Seiko Epson Corporation + 3-3-5 OWA + SUWA-SHI NAGANO-KEN 392-8502 + JP + +9C-AE-D3 (hex) Seiko Epson Corporation +9CAED3 (base 16) Seiko Epson Corporation + 80 Harashinden + Shiojiri-shi Nagano-ken 399-0785 + JP + +70-7C-69 (hex) Avaya Inc +707C69 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +50-0B-91 (hex) IEEE Registration Authority +500B91 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F8-46-1C (hex) Sony Interactive Entertainment Inc. +F8461C (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +70-4D-7B (hex) ASUSTek COMPUTER INC. +704D7B (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +64-A6-8F (hex) Zhongshan Readboy Electronics Co.,Ltd +64A68F (base 16) Zhongshan Readboy Electronics Co.,Ltd + Changmingshui Industrial Park Wuguishan Zhongshan City,Guangdong Province + Zhongshan Guangdong 528400 + CN + +38-BC-01 (hex) HUAWEI TECHNOLOGIES CO.,LTD +38BC01 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +34-1E-6B (hex) HUAWEI TECHNOLOGIES CO.,LTD +341E6B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-66-39 (hex) HUAWEI TECHNOLOGIES CO.,LTD +886639 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-42-5A (hex) Cisco Systems, Inc +00425A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +18-DB-F2 (hex) Dell Inc. +18DBF2 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +18-F8-7A (hex) i3 International Inc. +18F87A (base 16) i3 International Inc. + 780 Birchmount Road + Scarborough Ontario M1K5H4 + CA + +4C-26-E7 (hex) Welgate Co., Ltd. +4C26E7 (base 16) Welgate Co., Ltd. + 19F, Geopyeong Bldg. 129 + Seoul Seoul 135726 + KR + +00-60-41 (hex) Yokogawa Digital Computer Corporation +006041 (base 16) Yokogawa Digital Computer Corporation + Shinjuku MIDWEST Bldg.4-30-3 + Yoyogi Shibuya-ku, Tokyo 151-0053 + JP + +C8-16-A5 (hex) Masimo Corporation +C816A5 (base 16) Masimo Corporation + 40 Parker + Irvine CA 92618 + US + +0C-02-27 (hex) Technicolor CH USA Inc. +0C0227 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +4C-11-BF (hex) Zhejiang Dahua Technology Co., Ltd. +4C11BF (base 16) Zhejiang Dahua Technology Co., Ltd. + NO.1199 Bin An Road,Binjiang District,HangZhou,P.R.China + HangZhou ZheJiang 310053 + CN + +2C-59-8A (hex) LG Electronics (Mobile Communications) +2C598A (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +B0-52-16 (hex) Hon Hai Precision Ind. Co.,Ltd. +B05216 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +A0-E4-CB (hex) Zyxel Communications Corporation +A0E4CB (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +28-4E-D7 (hex) OutSmart Power Systems, Inc. +284ED7 (base 16) OutSmart Power Systems, Inc. + 11 Mercer Rd + Natick 23 01760 + + +14-A7-8B (hex) Zhejiang Dahua Technology Co., Ltd. +14A78B (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199, Waterfront Road + Hangzhou Zhejiang 310053 + CN + +A0-B8-F8 (hex) Amgen U.S.A. Inc. +A0B8F8 (base 16) Amgen U.S.A. Inc. + 1 Amgen Center Drive + Thousand Oaks CA 91320 + US + +88-44-77 (hex) HUAWEI TECHNOLOGIES CO.,LTD +884477 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +14-9D-09 (hex) HUAWEI TECHNOLOGIES CO.,LTD +149D09 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +68-69-75 (hex) Angler Labs Inc +686975 (base 16) Angler Labs Inc + 940 Pearce Mill Rd. + Wexford PA 15090 + US + +20-D2-5F (hex) SmartCap Technologies +20D25F (base 16) SmartCap Technologies + L1 18 Finchley Street + Milton Queensland 4064 + AU + +E4-7D-BD (hex) Samsung Electronics Co.,Ltd +E47DBD (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +9C-FB-D5 (hex) vivo Mobile Communication Co., Ltd. +9CFBD5 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +18-F7-6B (hex) Zhejiang Winsight Technology CO.,LTD +18F76B (base 16) Zhejiang Winsight Technology CO.,LTD + No.3339 Linggongtang Road,NanHu District + Jiaxing Zhejiang 314000 + CN + +58-31-12 (hex) DRUST +583112 (base 16) DRUST + 8 rue fabre d'églantine + Paris 75012 + FR + +9C-83-BF (hex) PRO-VISION, Inc. +9C83BF (base 16) PRO-VISION, Inc. + 8625-B Byron Commerce Dr. SW + Byron Center MI 49315 + US + +78-EF-4C (hex) Unetconvergence Co., Ltd. +78EF4C (base 16) Unetconvergence Co., Ltd. + 101-511, Digital Empire2, 486, Shin-dong, Youngtong-gu + Suwon Kyonggi-do 443-390 + KR + +58-69-6C (hex) Ruijie Networks Co.,LTD +58696C (base 16) Ruijie Networks Co.,LTD + 19# Building,Star-net Science Plaza,Juyuanzhou, 618 Jinshan Road + Fuzhou Fujian 350002 + CN + +48-D3-43 (hex) ARRIS Group, Inc. +48D343 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-C0-5A (hex) SEMAPHORE COMMUNICATIONS CORP. +00C05A (base 16) SEMAPHORE COMMUNICATIONS CORP. + 217 HUMBOLDT COURT + SUNNYVALE CA 94089-1300 + US + +00-07-F9 (hex) Sensaphone +0007F9 (base 16) Sensaphone + 901 Tryens Road + Aston PA 19014 + US + +00-1C-B3 (hex) Apple, Inc. +001CB3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-71-83 (hex) Juniper Networks +407183 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +C8-1B-5C (hex) BCTech +C81B5C (base 16) BCTech + 14 Building, Tiandeng road 259# + shanghai xuhui district, shanghai 200237 + CN + +5C-E3-0E (hex) ARRIS Group, Inc. +5CE30E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +1C-C0-E1 (hex) IEEE Registration Authority +1CC0E1 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-1A-39 (hex) Merten GmbH&CoKG +001A39 (base 16) Merten GmbH&CoKG + Fritz-Kotz-Str. 8 + Wiehl NRW 51674 + DE + +FC-EC-DA (hex) Ubiquiti Networks Inc. +FCECDA (base 16) Ubiquiti Networks Inc. + 2580 Orchard Pkwy + San Jose CA 95131 + US + +00-B0-E1 (hex) Cisco Systems, Inc +00B0E1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-50-93 (hex) BOEING +005093 (base 16) BOEING + 3370 Miraloma Avenue + Anaheim CA 92803-3105 + US + +90-5C-44 (hex) Compal Broadband Networks, Inc. +905C44 (base 16) Compal Broadband Networks, Inc. + 13F., No.1, Taiyuan 1st St. + Zhubei City Hsinchu County 30265 + TW + +44-BA-46 (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +44BA46 (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +E0-7C-13 (hex) zte corporation +E07C13 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +F4-1F-88 (hex) zte corporation +F41F88 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +14-ED-BB (hex) 2Wire Inc +14EDBB (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +18-E2-9F (hex) vivo Mobile Communication Co., Ltd. +18E29F (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +28-EE-52 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +28EE52 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +68-72-51 (hex) Ubiquiti Networks Inc. +687251 (base 16) Ubiquiti Networks Inc. + 91 E. Tasman Dr. + San Jose 95134 + US + +B4-FB-E4 (hex) Ubiquiti Networks Inc. +B4FBE4 (base 16) Ubiquiti Networks Inc. + 2580 Orchard Pkwy + San Jose CA 95131 + US + +70-79-90 (hex) HUAWEI TECHNOLOGIES CO.,LTD +707990 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A0-4E-01 (hex) CENTRAL ENGINEERING co.,ltd. +A04E01 (base 16) CENTRAL ENGINEERING co.,ltd. + 2-3-19 shinyokohama kouhoku-ku + yokohama-shi kanagawa 222-0033 + JP + +28-CA-09 (hex) ThyssenKrupp Elevators (Shanghai) Co.,Ltd +28CA09 (base 16) ThyssenKrupp Elevators (Shanghai) Co.,Ltd + No. 2, Xunye Rd, Sheshan Subarea Songjiang Industrial Area + Shanghai Shanghai 201602 + CN + +84-25-19 (hex) Samsung Electronics +842519 (base 16) Samsung Electronics + 129, Samsung-rom Yeongtong-gu + Suwon-si Gyeonggi-do 16677 + KR + +5C-24-43 (hex) O-Sung Telecom Co., Ltd. +5C2443 (base 16) O-Sung Telecom Co., Ltd. + 43-9 Pyeongdongro 803-gil , Gwangsan-Gu + Gwangju 54611 + KR + +24-92-0E (hex) Samsung Electronics Co.,Ltd +24920E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-42-03 (hex) Samsung Electronics Co.,Ltd +FC4203 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A0-10-81 (hex) Samsung Electronics Co.,Ltd +A01081 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +3C-8B-CD (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +3C8BCD (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +4C-F9-5D (hex) HUAWEI TECHNOLOGIES CO.,LTD +4CF95D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +84-21-F1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +8421F1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-F2-2C (hex) Shanghai B-star Technology Co.,Ltd. +00F22C (base 16) Shanghai B-star Technology Co.,Ltd. + 4Floor NO.1158 Xiehe Road,Changning District ,shanghai ,China 200335 + Shanghai 200335 + CN + +00-05-EE (hex) Vanderbilt International (SWE) AB +0005EE (base 16) Vanderbilt International (SWE) AB + Englundavaegen 7 + Solna SE-171 41 + SE + +F0-79-60 (hex) Apple, Inc. +F07960 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-D7-95 (hex) Apple, Inc. +A0D795 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-90-E7 (hex) HORSCH ELEKTRONIK AG +0090E7 (base 16) HORSCH ELEKTRONIK AG + HAAGERSTRASSE + CH-9473 GAMS + CH + +E4-3E-D7 (hex) Arcadyan Corporation +E43ED7 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +54-54-CF (hex) PROBEDIGITAL CO.,LTD +5454CF (base 16) PROBEDIGITAL CO.,LTD + #107 Hyundai I-Valley, 31, Galmachi-ro 244beon-gil, Jungwon-gu + Seongnam-si Gyeonggi-do 13212 + KR + +F8-63-3F (hex) Intel Corporate +F8633F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +08-86-20 (hex) TECNO MOBILE LIMITED +088620 (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +F0-D5-BF (hex) Intel Corporate +F0D5BF (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +64-74-F6 (hex) Shooter Detection Systems +6474F6 (base 16) Shooter Detection Systems + 300 Newburyport Turnpike + Rowley MA 01969 + US + +98-13-33 (hex) zte corporation +981333 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +20-47-ED (hex) BSkyB Ltd +2047ED (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +74-8A-69 (hex) Korea Image Technology Co., Ltd +748A69 (base 16) Korea Image Technology Co., Ltd + 125, beolmal road, dongan gu, + anyang gyeonggi 14056 + KR + +BC-47-60 (hex) Samsung Electronics Co.,Ltd +BC4760 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +04-18-0F (hex) Samsung Electronics Co.,Ltd +04180F (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +20-13-E0 (hex) Samsung Electronics Co.,Ltd +2013E0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-25-66 (hex) Samsung Electronics Co.,Ltd +002566 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D0-DB-32 (hex) Nokia Corporation +D0DB32 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +E8-00-36 (hex) Befs co,. ltd +E80036 (base 16) Befs co,. ltd + C-#403, 242 Pangyo-ro, Bundang-gu + Seongnam-si Gyeonggi-do 13487 + KR + +C0-9F-05 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +C09F05 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +5C-49-79 (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +5C4979 (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +C0-F9-45 (hex) Toshiba Toko Meter Systems Co., LTD. +C0F945 (base 16) Toshiba Toko Meter Systems Co., LTD. + 3484, Sakuragaoka, Kurohama + Hasuda-shi Saitama 349-0192 + JP + +70-F8-E7 (hex) IEEE Registration Authority +70F8E7 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D4-2C-44 (hex) Cisco Systems, Inc +D42C44 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +84-3D-C6 (hex) Cisco Systems, Inc +843DC6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-85 (hex) ConteXtream Ltd +002485 (base 16) ConteXtream Ltd + 94 Em-HaMoshavot + Petach-Tikva 49527 + IL + +28-FC-F6 (hex) Shenzhen Xin KingBrand enterprises Co.,Ltd +28FCF6 (base 16) Shenzhen Xin KingBrand enterprises Co.,Ltd + Kingbrand Industrial Zone,Nanpu Road,Shang liao ling pi keng,Shajing Town + Shenzhen Guangdong 518000 + CN + +00-1F-58 (hex) EMH Energiemesstechnik GmbH +001F58 (base 16) EMH Energiemesstechnik GmbH + Vor dem Hassel 2 + Brackel 21438 + DE + +68-94-23 (hex) Hon Hai Precision Ind. Co.,Ltd. +689423 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +84-4B-F5 (hex) Hon Hai Precision Ind. Co.,Ltd. +844BF5 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +08-ED-B9 (hex) Hon Hai Precision Ind. Co.,Ltd. +08EDB9 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +3C-77-E6 (hex) Hon Hai Precision Ind. Co.,Ltd. +3C77E6 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +70-18-8B (hex) Hon Hai Precision Ind. Co.,Ltd. +70188B (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +5C-6D-20 (hex) Hon Hai Precision Ind. Co.,Ltd. +5C6D20 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +5C-AC-4C (hex) Hon Hai Precision Ind. Co.,Ltd. +5CAC4C (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-16-DF (hex) Lundinova AB +0016DF (base 16) Lundinova AB + Dalbyvägen 1 + Lund Skåne SE-224 60 + US + +00-1D-0C (hex) MobileCompia +001D0C (base 16) MobileCompia + Dongwon Bldg, 725-30, Yeoksam-dong, Gangnam-gu, + Seoul 135-080 + KR + +B8-8E-DF (hex) Zencheer Communication Technology Co., Ltd. +B88EDF (base 16) Zencheer Communication Technology Co., Ltd. + Room 2706, BLDG#7, Changjiang Building, NO.12, Changjiang Road, New District + Wuxi Jiangsu 214028 + CN + +DC-71-44 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +DC7144 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Maetan3-Dong, Yeongtong-Gu + Suwon 443-743 + US + +98-0C-82 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +980C82 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + Metan Dong 314, Youngtong Gu + Suwon Kyung-gi Do. 443-743 + KR + +A0-0B-BA (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +A00BBA (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + Suwon-Si, Gyeonggi_Do, Korea + Suwon Gyeonggi_Do 443-743 + KR + +60-6B-BD (hex) Samsung Electronics Co.,Ltd +606BBD (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3dong, Yeongtong-gu + Suwon-si Gyeonggi-do 443742 + KR + +00-21-4C (hex) Samsung Electronics Co.,Ltd +00214C (base 16) Samsung Electronics Co.,Ltd + 416, METAN-3DONG, + SUWON KYUNGKI-DO 442-742 + KR + +08-C6-B3 (hex) QTECH LLC +08C6B3 (base 16) QTECH LLC + Novozavodskaya st. 18 build. 1 + Moscow Moscow region 121309 + RU + +00-18-AF (hex) Samsung Electronics Co.,Ltd +0018AF (base 16) Samsung Electronics Co.,Ltd + #94-1 + Gumi-City Gyeong-Buk 730-350 + KR + +00-1E-E1 (hex) Samsung Electronics Co.,Ltd +001EE1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-16-6B (hex) Samsung Electronics Co.,Ltd +00166B (base 16) Samsung Electronics Co.,Ltd + 416,Maetan-3Dong,Yeongtong-Gu + Suwon-City Kyeonggi-Do 443-742 + KR + +00-00-F0 (hex) Samsung Electronics Co.,Ltd +0000F0 (base 16) Samsung Electronics Co.,Ltd + 416, MAETAN-3DONG, PALDAL-GU + kwon 442-742 + KR + +8C-C8-CD (hex) Samsung Electronics Co.,Ltd +8CC8CD (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3dong, Yeongtong-gu + Suwon Gyeonggi-do 443742 + KR + +A8-F2-74 (hex) Samsung Electronics Co.,Ltd +A8F274 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D4-87-D8 (hex) Samsung Electronics Co.,Ltd +D487D8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +18-46-17 (hex) Samsung Electronics Co.,Ltd +184617 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +38-0A-94 (hex) Samsung Electronics Co.,Ltd +380A94 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D0-DF-C7 (hex) Samsung Electronics Co.,Ltd +D0DFC7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D0-C1-B1 (hex) Samsung Electronics Co.,Ltd +D0C1B1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +80-18-A7 (hex) Samsung Electronics Co.,Ltd +8018A7 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3dong, Yeongtong-Gu + Suwon Gyeonggi-Do 443742 + KR + +F4-7B-5E (hex) Samsung Electronics Co.,Ltd +F47B5E (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3dong, Yeongtong-Gu + Suwon Gyeonggi-Do 443742 + KR + +70-F9-27 (hex) Samsung Electronics Co.,Ltd +70F927 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +34-E7-1C (hex) Shenzhen YOUHUA Technology Co., Ltd +34E71C (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +88-6A-B1 (hex) vivo Mobile Communication Co., Ltd. +886AB1 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +6C-1E-90 (hex) Hansol Technics Co., Ltd. +6C1E90 (base 16) Hansol Technics Co., Ltd. + 55, Hansam-ro, Deoksan-Myeon + Jincheon-Gun Chungbuk 27850 + KR + +00-5A-13 (hex) HUAWEI TECHNOLOGIES CO.,LTD +005A13 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-50-06 (hex) Samsung Electronics Co.,Ltd +C45006 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +88-32-9B (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +88329B (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong 24180 + US + +14-49-E0 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +1449E0 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong 24180 + US + +D0-25-44 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +D02544 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +BC-44-86 (hex) Samsung Electronics Co.,Ltd +BC4486 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +20-D3-90 (hex) Samsung Electronics Co.,Ltd +20D390 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +94-01-C2 (hex) Samsung Electronics Co.,Ltd +9401C2 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +50-FC-9F (hex) Samsung Electronics Co.,Ltd +50FC9F (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +38-0B-40 (hex) Samsung Electronics Co.,Ltd +380B40 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B8-FF-61 (hex) Apple, Inc. +B8FF61 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +94-61-24 (hex) Pason Systems +946124 (base 16) Pason Systems + 6130 - 3rd Street S.E. + Calgary Alberta T2H1K4 + CA + +F0-72-8C (hex) Samsung Electronics Co.,Ltd +F0728C (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +34-AA-8B (hex) Samsung Electronics Co.,Ltd +34AA8B (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +24-DB-ED (hex) Samsung Electronics Co.,Ltd +24DBED (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C8-DE-51 (hex) IntegraOptics +C8DE51 (base 16) IntegraOptics + 745 Albany Shaker Rd + Latham NY 12110 + US + +98-F0-58 (hex) Lynxspring, Incl. +98F058 (base 16) Lynxspring, Incl. + 1210 NE Windsor Drive + Lees Summit MO 64086 + US + +68-C4-4D (hex) Motorola Mobility LLC, a Lenovo Company +68C44D (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +40-0D-10 (hex) ARRIS Group, Inc. +400D10 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +94-3D-C9 (hex) Asahi Net, Inc. +943DC9 (base 16) Asahi Net, Inc. + Ginza 4-12-15 Chuo-ku + Tokyo 104-0061 + JP + +44-04-44 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +440444 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +00-17-7E (hex) Meshcom Technologies Inc. +00177E (base 16) Meshcom Technologies Inc. + Meritullinkatu 1 C + Helsinki 00170 + FI + +A0-04-60 (hex) NETGEAR +A00460 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +98-84-E3 (hex) Texas Instruments +9884E3 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +38-D2-69 (hex) Texas Instruments +38D269 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +C8-FD-19 (hex) Texas Instruments +C8FD19 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +50-8C-B1 (hex) Texas Instruments +508CB1 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +C4-F5-A5 (hex) Kumalift Co., Ltd. +C4F5A5 (base 16) Kumalift Co., Ltd. + 7-2-6 Saito-Asagi + Ibaraki Osaka 567-0085 + JP + +70-B1-4E (hex) ARRIS Group, Inc. +70B14E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +30-44-87 (hex) Hefei Radio Communication Technology Co., Ltd +304487 (base 16) Hefei Radio Communication Technology Co., Ltd + No.108, YinXing Road, High-tech Development Zone + Hefei Anhui 230088 + CN + +2C-9D-1E (hex) HUAWEI TECHNOLOGIES CO.,LTD +2C9D1E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-81-C4 (hex) Cisco Systems, Inc +0081C4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +58-E8-76 (hex) IEEE Registration Authority +58E876 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D0-37-42 (hex) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd +D03742 (base 16) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + Coolpad Information Harbor, 2nd Mengxi road, Hi-Tech Industrial Park(North), Nanshan District + Shenzhen Guangdong 518057 + CN + +00-17-65 (hex) Nortel Networks +001765 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-15-E8 (hex) Nortel Networks +0015E8 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-15-9B (hex) Nortel Networks +00159B (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-0F-06 (hex) Nortel Networks +000F06 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +84-B5-41 (hex) Samsung Electronics Co.,Ltd +84B541 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-6F-64 (hex) Samsung Electronics Co.,Ltd +006F64 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +DC-66-72 (hex) Samsung Electronics Co.,Ltd +DC6672 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +EC-8E-B5 (hex) Hewlett Packard +EC8EB5 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +70-AF-6A (hex) SHENZHEN FENGLIAN TECHNOLOGY CO., LTD. +70AF6A (base 16) SHENZHEN FENGLIAN TECHNOLOGY CO., LTD. + ORIENTAL CYBERPORT, HIGHTECH 6 ROAD + SHENZHEN GUANGDONG 518057 + CN + +20-F5-43 (hex) Hui Zhou Gaoshengda Technology Co.,LTD +20F543 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +E0-DD-C0 (hex) vivo Mobile Communication Co., Ltd. +E0DDC0 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +00-16-4D (hex) Alcatel-Lucent IPD +00164D (base 16) Alcatel-Lucent IPD + 701 E. Middlefield RD. + Mountain View CA 94043 + US + +00-1A-F0 (hex) Alcatel-Lucent IPD +001AF0 (base 16) Alcatel-Lucent IPD + 701 E. Middlefield Rd. + Mountain View CA 94943 + US + +38-52-1A (hex) Nokia +38521A (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +00-1E-40 (hex) Shanghai DareGlobal Technologies Co.,Ltd +001E40 (base 16) Shanghai DareGlobal Technologies Co.,Ltd + 22F, lnfo Tech Building, NO.1555 Kongjiang Road, + Shanghai 200092 + CN + +94-D7-23 (hex) Shanghai DareGlobal Technologies Co.,Ltd +94D723 (base 16) Shanghai DareGlobal Technologies Co.,Ltd + 22F Info-Tech Building + Shanghai 200092 + CN + +C4-04-7B (hex) Shenzhen YOUHUA Technology Co., Ltd +C4047B (base 16) Shenzhen YOUHUA Technology Co., Ltd + Shenzhen University-town Business Park,Lishan Road,Taoyuan Street + Shenzhen Guangdong 518055 + CN + +20-F4-1B (hex) Shenzhen Bilian electronic CO.,LTD +20F41B (base 16) Shenzhen Bilian electronic CO.,LTD + NO 268, Fuqian Rd,Jutang Community,Guanlan town, + ShenZhen Guangdong 518110 + CN + +FC-FA-F7 (hex) Shanghai Baud Data Communication Co.,Ltd. +FCFAF7 (base 16) Shanghai Baud Data Communication Co.,Ltd. + NO.123 JULI RD + SHANGHAI 201203 + CN + +D8-26-B9 (hex) Guangdong Coagent Electronics S&T Co.,Ltd. +D826B9 (base 16) Guangdong Coagent Electronics S&T Co.,Ltd. + Section C,Xi Nan Industrial Zone Sanshui + Foshan Guangdong 528133 + CN + +AC-9C-E4 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +AC9CE4 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +00-23-3E (hex) Alcatel-Lucent IPD +00233E (base 16) Alcatel-Lucent IPD + 701 E. Middlefield Rd. + Mountain View CA 94043 + US + +6C-BE-E9 (hex) Alcatel-Lucent IPD +6CBEE9 (base 16) Alcatel-Lucent IPD + 701 E. Middlefield Rd. + Mountain View CA 94043 + US + +00-15-40 (hex) Nortel Networks +001540 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1E-CA (hex) Nortel Networks +001ECA (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-13-0A (hex) Nortel Networks +00130A (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1F-0A (hex) Nortel Networks +001F0A (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +F8-E6-1A (hex) Samsung Electronics Co.,Ltd +F8E61A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A0-91-C8 (hex) zte corporation +A091C8 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +6C-A8-58 (hex) Fiberhome Telecommunication Technologies Co.,LTD +6CA858 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +CC-2D-8C (hex) LG ELECTRONICS INC +CC2D8C (base 16) LG ELECTRONICS INC + 19-1,Cheongho-Ri,Jinwi-Myeon + Pyeongtaek Gyeonggi-Do 451-713 + KR + +98-D6-F7 (hex) LG Electronics (Mobile Communications) +98D6F7 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +70-05-14 (hex) LG Electronics (Mobile Communications) +700514 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +E8-92-A4 (hex) LG Electronics (Mobile Communications) +E892A4 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +10-68-3F (hex) LG Electronics (Mobile Communications) +10683F (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +40-B0-FA (hex) LG Electronics (Mobile Communications) +40B0FA (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-25-E5 (hex) LG Electronics (Mobile Communications) +0025E5 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-21-FB (hex) LG Electronics (Mobile Communications) +0021FB (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +34-FC-EF (hex) LG Electronics (Mobile Communications) +34FCEF (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +BC-F5-AC (hex) LG Electronics (Mobile Communications) +BCF5AC (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +A8-4E-3F (hex) Hitron Technologies. Inc +A84E3F (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +0C-48-85 (hex) LG Electronics (Mobile Communications) +0C4885 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-22-A9 (hex) LG Electronics (Mobile Communications) +0022A9 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +2C-6A-6F (hex) IEEE Registration Authority +2C6A6F (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +08-D8-33 (hex) Shenzhen RF Technology Co., Ltd +08D833 (base 16) Shenzhen RF Technology Co., Ltd + 5/F,Building 4 ,Baokun science and Technology Industrial Park,Dalang Street,Baoan District,Shenzhen,China + Shenzhen Guangdong 518109 + CN + +A4-60-32 (hex) MRV Communications (Networks) LTD +A46032 (base 16) MRV Communications (Networks) LTD + Hayetzira 6 + Yokneam Yokneam 20692 + IL + +40-66-7A (hex) mediola - connected living AG +40667A (base 16) mediola - connected living AG + Nobelring 26 + Frankfurt am Main Hessen 60598 + DE + +68-A0-F6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +68A0F6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-0E-5C (hex) ARRIS Group, Inc. +000E5C (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +84-5D-D7 (hex) Shenzhen Netcom Electronics Co.,Ltd +845DD7 (base 16) Shenzhen Netcom Electronics Co.,Ltd + 8/F,1 Building,Finance Base,No.8,Kefa Road,High-Tech Park + Shenzhen Guangdong 518057 + CN + +00-B0-64 (hex) Cisco Systems, Inc +00B064 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +9C-2A-83 (hex) Samsung Electronics Co.,Ltd +9C2A83 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C8-02-10 (hex) LG Innotek +C80210 (base 16) LG Innotek + Jangduk-dong 978-1 + Gwang-ju Gwangsan-gu 506-731 + KR + +A0-39-F7 (hex) LG Electronics (Mobile Communications) +A039F7 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +1C-CA-E3 (hex) IEEE Registration Authority +1CCAE3 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E4-95-6E (hex) IEEE Registration Authority +E4956E (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +B4-37-D1 (hex) IEEE Registration Authority +B437D1 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-55-DA (hex) IEEE Registration Authority +0055DA (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +78-C2-C0 (hex) IEEE Registration Authority +78C2C0 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-0E-E8 (hex) Zioncom Electronics (Shenzhen) Ltd. +000EE8 (base 16) Zioncom Electronics (Shenzhen) Ltd. + West wing 5/F ., Block 1, GaoXin South Ring Rd/Keji South Rd, + Shenzhen Guangdong 518057 + CN + +00-C0-95 (hex) ZNYX Networks, Inc. +00C095 (base 16) ZNYX Networks, Inc. + 48421 Milmont Drive + Fremont CA 94538 + US + +00-20-25 (hex) CONTROL TECHNOLOGY, INC. +002025 (base 16) CONTROL TECHNOLOGY, INC. + 5734 MIDDLEBROOK PIKE + KNOXVILLE TN 37921 + US + +00-1A-6B (hex) Universal Global Scientific Industrial Co., Ltd. +001A6B (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, LANE 351,SEC.1, TAIPING RD. + TSAOTUEN, NANTOU 54261 + TW + +00-16-41 (hex) Universal Global Scientific Industrial Co., Ltd. +001641 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, LANE 351,SEC.1, TAIPING RD. + TSAOTUEN, NANTOU 54261 + TW + +00-10-C6 (hex) Universal Global Scientific Industrial Co., Ltd. +0010C6 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, LANE 351,SEC.1, TAIPING RD. + TSAOTUEN, NANTOU 54261 + TW + +00-24-7E (hex) Universal Global Scientific Industrial Co., Ltd. +00247E (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, LANE 351,SEC.1, TAIPING RD. + nantou NANTOU 54261 + TW + +00-DD-0A (hex) UNGERMANN-BASS INC. +00DD0A (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +54-AB-3A (hex) QUANTA COMPUTER INC. +54AB3A (base 16) QUANTA COMPUTER INC. + No.211, Wen Hwa 2nd Rd., Kuei Shan Hsiang, Tao Yuan Shien, Taiwan, R. O. C. + Taoyuan Taiwan 33377 + TW + +68-35-63 (hex) SHENZHEN LIOWN ELECTRONICS CO.,LTD. +683563 (base 16) SHENZHEN LIOWN ELECTRONICS CO.,LTD. + ROOM 301, NO.7, GONGYE 3RD ROAD + SHEKOU, NANSHAN DISTRICT SHENZHEN 518054 + CN + +00-40-72 (hex) Applied Innovation Inc. +004072 (base 16) Applied Innovation Inc. + 5800 Innovation Drive + Dublin OH 43016-3271 + US + +00-19-38 (hex) UMB Communications Co., Ltd. +001938 (base 16) UMB Communications Co., Ltd. + 1010, 5, ACE Techno Tower, 197-22, Guro-dong, Guro-gu + Seoul 151-766 + KR + +44-39-C4 (hex) Universal Global Scientific Industrial Co., Ltd. +4439C4 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141,Lane351,Taiping Rd.Sec.1 + nan tou 542 + TW + +40-2C-F4 (hex) Universal Global Scientific Industrial Co., Ltd. +402CF4 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, Lane 351, Taiping Rd. Sec. 1, Tsao Tuen, + Nan-Tou Hsien, 542 + TW + +00-1E-37 (hex) Universal Global Scientific Industrial Co., Ltd. +001E37 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, LANE 351,SEC.1, TAIPING RD. + TSAOTUEN, NANTOU 54261 + TW + +E8-9A-8F (hex) QUANTA COMPUTER INC. +E89A8F (base 16) QUANTA COMPUTER INC. + 211, Wen Hwa 2nd Rd.,Kuei Shan, Tao Yuan + TAIPEI 33377 + TW + +1C-57-D8 (hex) Kraftway Corporation PLC +1C57D8 (base 16) Kraftway Corporation PLC + 16, 3rd Mytischinskaya st. + Moscow 129626 + RU + +00-23-18 (hex) Toshiba +002318 (base 16) Toshiba + 2-9,Suehiro-Cho + Ome Tokyo 1988710 + JP + +B8-6B-23 (hex) Toshiba +B86B23 (base 16) Toshiba + 2-9,Suehiro-Cho + Ome Tokyo 1988710 + JP + +00-08-F1 (hex) Voltaire +0008F1 (base 16) Voltaire + 9 Hamenofim st. + Herzelia 46725 + IL + +00-19-9D (hex) Vizio, Inc +00199D (base 16) Vizio, Inc + 39 Tesla + Irvine CA 92618 + US + +00-E0-8B (hex) QLogic Corporation +00E08B (base 16) QLogic Corporation + 26600 Laguna Hills Dr. + Aliso Viejo CA 92656 + US + +D8-EB-97 (hex) TRENDnet, Inc. +D8EB97 (base 16) TRENDnet, Inc. + 20675 Manhattan Place + Torrance CA 90501 + US + +00-1C-7E (hex) Toshiba +001C7E (base 16) Toshiba + 2-9,Suehiro-Cho + Ome 1988710 + JP + +00-25-17 (hex) Venntis, LLC +002517 (base 16) Venntis, LLC + 11301 James Street + Holland MI 49424 + US + +00-60-0F (hex) Westell Technologies Inc. +00600F (base 16) Westell Technologies Inc. + 750 N Commons Dr + Aurora IL 60504 + US + +00-18-3A (hex) Westell Technologies Inc. +00183A (base 16) Westell Technologies Inc. + 750 N Commons Dr + Aurora IL 60504 + US + +60-02-B4 (hex) Wistron Neweb Corporation +6002B4 (base 16) Wistron Neweb Corporation + No.20 Park Avenue II + Hsinchu 308 + TW + +94-DF-4E (hex) Wistron InfoComm(Kunshan)Co.,Ltd. +94DF4E (base 16) Wistron InfoComm(Kunshan)Co.,Ltd. + 168# First Avence,Kunshan Export Processing Zone ,China + Kunsha JiangSu 215300 + CN + +98-EE-CB (hex) Wistron Infocomm (Zhongshan) Corporation +98EECB (base 16) Wistron Infocomm (Zhongshan) Corporation + No.38,East Keji Road,Zhongshan Torch Development Zone,Zhongshan City,Guangdong,China + Zhongshan Guangdong 528437 + CN + +64-3A-B1 (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +643AB1 (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, Chengdu, Sichuan + Chengdu Sichuan 610000 + CN + +00-1B-FE (hex) Zavio Inc. +001BFE (base 16) Zavio Inc. + No.1,Lising 1st Rd. Science Based Industrial Park, + Hsinchu 300 + TW + +54-10-EC (hex) Microchip Technology Inc. +5410EC (base 16) Microchip Technology Inc. + 2355 W. Chandler Blvd. + Chandler AZ 85224 + US + +00-04-A3 (hex) Microchip Technology Inc. +0004A3 (base 16) Microchip Technology Inc. + 2355 W. Chandler Blvd. + Chandler AZ 85224 + US + +78-9C-E7 (hex) Shenzhen Aikede Technology Co., Ltd +789CE7 (base 16) Shenzhen Aikede Technology Co., Ltd + Room 9B,Block B,Neptunus Mansion, + Shenzhen Guangdong 518000 + CN + +50-9F-3B (hex) OI ELECTRIC CO.,LTD +509F3B (base 16) OI ELECTRIC CO.,LTD + 7-3-16 KIKUNA + YOKOHAMA KANAGAWA-KEN 222-0011 + JP + +44-6E-E5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +446EE5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-F7-C7 (hex) Technicolor CH USA Inc. +88F7C7 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +80-48-A5 (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +8048A5 (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,TianYi International Hotel + Chengdu Sichuan 61000 + CN + +68-3E-34 (hex) MEIZU Technology Co., Ltd. +683E34 (base 16) MEIZU Technology Co., Ltd. + MEIZU Tech Bldg., Technology & Innovation Coast + Zhuhai Guangdong 519085 + CN + +C8-77-8B (hex) Mercury Systems – Trusted Mission Solutions, Inc. +C8778B (base 16) Mercury Systems – Trusted Mission Solutions, Inc. + 47200 Bayside Pkwy + Fremont CA 94538 + US + +00-04-4B (hex) NVIDIA +00044B (base 16) NVIDIA + 3535 Monroe St. + Santa Clara CA 95051 + US + +AC-9B-0A (hex) Sony Corporation +AC9B0A (base 16) Sony Corporation + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +10-4F-A8 (hex) Sony Corporation +104FA8 (base 16) Sony Corporation + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +00-0B-6B (hex) Wistron Neweb Corporation +000B6B (base 16) Wistron Neweb Corporation + No. 10-1, Li-Hsin Road I, Science-based + Hsinchu 300 + TW + +AC-04-0B (hex) Peloton Interactive, Inc +AC040B (base 16) Peloton Interactive, Inc + 158 W 27th St, 4th Fl + New York NY 10001 + US + +48-FC-B6 (hex) LAVA INTERNATIONAL(H.K) LIMITED +48FCB6 (base 16) LAVA INTERNATIONAL(H.K) LIMITED + UNIT L 1/F MAU LAM COMM BLDG 16-18 MAU LAM ST, JORDAN KL, HK + Hong kong 999077 + CN + +B0-E2-35 (hex) Xiaomi Communications Co Ltd +B0E235 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +40-C7-29 (hex) Sagemcom Broadband SAS +40C729 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +14-C9-13 (hex) LG Electronics +14C913 (base 16) LG Electronics + 222 LG-ro, JINWI-MYEON + Pyeongtaek-si Gyeonggi-do 451-713 + KR + +F8-A0-97 (hex) ARRIS Group, Inc. +F8A097 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +FC-23-25 (hex) EosTek (Shenzhen) Co., Ltd. +FC2325 (base 16) EosTek (Shenzhen) Co., Ltd. + Room 306, Complex Building Tsinghua High-Tech Park + Shenzhen Guangdong 518057 + CN + +FC-3D-93 (hex) LONGCHEER TELECOMMUNICATION LIMITED +FC3D93 (base 16) LONGCHEER TELECOMMUNICATION LIMITED + Building 1,No.401,Caobao Rd + Shanghai Xuhui District 200233 + CN + +D8-E0-B8 (hex) BULAT LLC +D8E0B8 (base 16) BULAT LLC + Zagorievsiy proezd 1, room 7 + Moscow 115547 + RU + +60-31-97 (hex) Zyxel Communications Corporation +603197 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +C0-C9-76 (hex) Shenzhen TINNO Mobile Technology Corp. +C0C976 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F, H-3 Building, Qiao Cheng Eastern Industrial Park, Overseas Chinese Town, Shenzhen + Shenzhen guangdong 518053 + CN + +58-8B-F3 (hex) Zyxel Communications Corporation +588BF3 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +50-67-F0 (hex) Zyxel Communications Corporation +5067F0 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +00-13-49 (hex) Zyxel Communications Corporation +001349 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +E0-98-61 (hex) Motorola Mobility LLC, a Lenovo Company +E09861 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +9C-8E-CD (hex) Amcrest Technologies +9C8ECD (base 16) Amcrest Technologies + 16727 Park Row + Houston TX 77084 + US + +A0-09-ED (hex) Avaya Inc +A009ED (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +00-14-B4 (hex) General Dynamics United Kingdom Ltd +0014B4 (base 16) General Dynamics United Kingdom Ltd + Castleham Road + St Leonards on Sea East Sussex TN38 9NJ + GB + +A0-B4-37 (hex) GD Mission Systems +A0B437 (base 16) GD Mission Systems + 8220 EAST ROOSEVELT ST R2121 + SCOTTSDALE AZ 85257 + US + +8C-6D-50 (hex) SHENZHEN MTC CO LTD +8C6D50 (base 16) SHENZHEN MTC CO LTD + 5th Floor, 3rd Building, SHENZHEN MTC Industrial Park, XiaLilang Rd, Nanwan Street, Long’gang District + Shenzhen Guangdong 518100 + CN + +00-F6-63 (hex) Cisco Systems, Inc +00F663 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A0-60-90 (hex) Samsung Electronics Co.,Ltd +A06090 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +BC-76-5E (hex) Samsung Electronics Co.,Ltd +BC765E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E0-A8-B8 (hex) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited +E0A8B8 (base 16) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited + ,Le Shi Building, No.105 Yaojiayuan Road,Chaoyang District,Beijing,China + beijing beijing 100025 + CN + +F4-5B-73 (hex) Wanjiaan Interconnected Technology Co., Ltd +F45B73 (base 16) Wanjiaan Interconnected Technology Co., Ltd + 2nd Floor,Incubation Building, Science Development Institute of China, High-tech South 1st Street, Nanshan District + Shenzhen Guangdong 518040 + CN + +B8-81-98 (hex) Intel Corporate +B88198 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B0-D7-CC (hex) Tridonic GmbH & Co KG +B0D7CC (base 16) Tridonic GmbH & Co KG + Färbergasse 15 + Dornbirn Vorarlberg 6851 + AT + +2C-DD-A3 (hex) Point Grey Research Inc. +2CDDA3 (base 16) Point Grey Research Inc. + 305-1847 West Broadway + Vancouver British Columbia V6J 1Y6 + CA + +00-80-9F (hex) ALE International +00809F (base 16) ALE International + 32 avenue Kléber + Colombes 92700 + FR + +48-C6-63 (hex) GTO Access Systems LLC +48C663 (base 16) GTO Access Systems LLC + 3121 Hartsfield Road + Tallahassee FL 32303 + US + +00-5F-86 (hex) Cisco Systems, Inc +005F86 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +38-1D-D9 (hex) FN-LINK TECHNOLOGY LIMITED +381DD9 (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +1C-B9-C4 (hex) Ruckus Wireless +1CB9C4 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +8C-59-C3 (hex) ADB Italia +8C59C3 (base 16) ADB Italia + Viale Sarca 222 + Milan Italy 20126 + IT + +B8-24-F0 (hex) SOYO Technology Development Co., Ltd. +B824F0 (base 16) SOYO Technology Development Co., Ltd. + 4F, 9Bldg, Longbi Industry Zone, Longgang Dist, Shenzhen City, Guangdong Pro, China + Shenzhen City Guangdong Pro 518129 + CN + +D8-5B-2A (hex) Samsung Electronics Co.,Ltd +D85B2A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-A8-9A (hex) Sunitec Enterprise Co.,Ltd +FCA89A (base 16) Sunitec Enterprise Co.,Ltd + 3F.,No.98-1,Mincyuan Rd.Sindian City + Taipei County 231 231141 + CN + +1C-7B-23 (hex) Qingdao Hisense Communications Co.,Ltd. +1C7B23 (base 16) Qingdao Hisense Communications Co.,Ltd. + Qianwangang Road 218 + Qingdao Shandong 266510 + CN + +00-0B-DE (hex) TELDIX GmbH +000BDE (base 16) TELDIX GmbH + Grenzhoefer Weg 36 + Heidelberg 69123 + DE + +C8-3D-FC (hex) Pioneer DJ Corporation +C83DFC (base 16) Pioneer DJ Corporation + 6F,Yokohama i-Mark Place, 4-4-5 Minatomirai, Nishi-ku + Yokohama Kanagawa 220-0012 + JP + +CC-D3-1E (hex) IEEE Registration Authority +CCD31E (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +34-B3-54 (hex) HUAWEI TECHNOLOGIES CO.,LTD +34B354 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +1C-6E-76 (hex) Quarion Technology Inc +1C6E76 (base 16) Quarion Technology Inc + 3248 Commerce Drive + Newburgh IN 47630 + US + +90-C1-C6 (hex) Apple, Inc. +90C1C6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-0E-E6 (hex) Chengdu Xiyida Electronic Technology Co,.Ltd +6C0EE6 (base 16) Chengdu Xiyida Electronic Technology Co,.Ltd + Room 408,Building A,No.33 Wuqing South Road,Wuhou District + Chengdu Sichuan 610000 + CN + +CC-50-0A (hex) Fiberhome Telecommunication Technologies Co.,LTD +CC500A (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +D0-46-DC (hex) Southwest Research Institute +D046DC (base 16) Southwest Research Institute + 6220 Culebra Road + San Antonio Texas 78238 + US + +70-A2-B3 (hex) Apple, Inc. +70A2B3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-0F-24 (hex) Apple, Inc. +F40F24 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +4C-57-CA (hex) Apple, Inc. +4C57CA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-07-63 (hex) Sunniwell Cyber Tech. Co., Ltd. +000763 (base 16) Sunniwell Cyber Tech. Co., Ltd. + 17th Floor Haitai Building #229 + Beijing 100083 + CN + +00-62-EC (hex) Cisco Systems, Inc +0062EC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +CC-16-7E (hex) Cisco Systems, Inc +CC167E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C4-6A-B7 (hex) Xiaomi Communications Co Ltd +C46AB7 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +00-0A-ED (hex) HARTING Electronics GmbH +000AED (base 16) HARTING Electronics GmbH + Wilhelm Harting Str.1 + Espelkamp NRW/OWL 32339 + DE + +24-0A-11 (hex) TCT mobile ltd +240A11 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +D8-E5-6D (hex) TCT mobile ltd +D8E56D (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +54-05-93 (hex) WOORI ELEC Co.,Ltd +540593 (base 16) WOORI ELEC Co.,Ltd + #1401~03, #1411~12, Bucheon Deawoo Techno Park, D-Dong, 261,Doyak-Ro, Wonmi-Gu,Bucheon-Si + Gyeonggi-Do 14523 + KR + +C0-2F-F1 (hex) Volta Networks +C02FF1 (base 16) Volta Networks + 109 Kingston St, 3rd Floor + Boston MA 02111 + US + +E8-A7-F2 (hex) sTraffic +E8A7F2 (base 16) sTraffic + 4th Fl., KTNET Building, 338 Pangyoro, Bundang-gu + Seongnam Gyeonggi-do 13493 + KR + +00-1F-20 (hex) Logitech Europe SA +001F20 (base 16) Logitech Europe SA + EPFL - Quartier de l'Innovation + Lausanne CH 1015 + CH + +74-1F-4A (hex) Hangzhou H3C Technologies Co., Limited +741F4A (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District, + Hangzhou Zhejiang, P.R.China 310052 + CN + +E4-1D-2D (hex) Mellanox Technologies, Inc. +E41D2D (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +0C-DA-41 (hex) Hangzhou H3C Technologies Co., Limited +0CDA41 (base 16) Hangzhou H3C Technologies Co., Limited + 310 Liuhe Road, Zhijiang Science Park + Hangzhou Zhejiang, 310053 + CN + +74-25-8A (hex) Hangzhou H3C Technologies Co., Limited +74258A (base 16) Hangzhou H3C Technologies Co., Limited + 310 Liuhe Road, Zhijiang Science Park + Hangzhou Zhejiang, 310053 + CN + +A0-B6-62 (hex) Acutvista Innovation Co., Ltd. +A0B662 (base 16) Acutvista Innovation Co., Ltd. + 2F-1, No. 20 Alley 1, Lane 768, Sec. 4 + Taipei City 11577 + TW + +E4-2F-56 (hex) OptoMET GmbH +E42F56 (base 16) OptoMET GmbH + Pfungstaedter Str. 92 + Darmstadt 64297 + DE + +F8-DA-0C (hex) Hon Hai Precision Ind. Co.,Ltd. +F8DA0C (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +1C-1B-0D (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +1C1B0D (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + Pin-Jen City, Taoyuan, Taiwan, R.O.C. + Pin-Jen Taoyuan 324 + TW + +48-E9-F1 (hex) Apple, Inc. +48E9F1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-38-09 (hex) Ericsson AB +903809 (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +00-A0-06 (hex) IMAGE DATA PROCESSING SYSTEM GROUP +00A006 (base 16) IMAGE DATA PROCESSING SYSTEM GROUP + SHINTOYOFUTA 2-1 + KASHIWA-CITY, CHIBA 277 + JP + +C8-3F-26 (hex) Microsoft Corporation +C83F26 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +34-97-F6 (hex) ASUSTek COMPUTER INC. +3497F6 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +50-68-0A (hex) HUAWEI TECHNOLOGIES CO.,LTD +50680A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-22-38 (hex) LOGIPLUS +002238 (base 16) LOGIPLUS + 1, RUE CLEMENT ADER + GOSSELIES HAINAUT B-6041 + BE + +00-0C-49 (hex) Dangaard Telecom Denmark A/S +000C49 (base 16) Dangaard Telecom Denmark A/S + Industrivej 1 + Padborg DK-6330 + DK + +00-08-B9 (hex) Kaonmedia CO., LTD. +0008B9 (base 16) Kaonmedia CO., LTD. + #113 Imae 1-Dong, Bundang-Gu + Sungnam-City Kyungki-Do 463-829 + KR + +60-B3-87 (hex) Synergics Technologies GmbH +60B387 (base 16) Synergics Technologies GmbH + Hummelgasse 74-76/19 + Vienna Austria 1130 + AT + +A4-D8-CA (hex) HONG KONG WATER WORLD TECHNOLOGY CO. LIMITED +A4D8CA (base 16) HONG KONG WATER WORLD TECHNOLOGY CO. LIMITED + RM B-C, 24/F, GOLDEN BEAR INDUSTRIAL CENTRE, 66-82 CHAI WAN KOK STREET,TSUEN WAN. N.T. + Hong Kong 999077 + HK + +80-19-FE (hex) JianLing Technology CO., LTD +8019FE (base 16) JianLing Technology CO., LTD + No. 383-1, Sec. 2, Jinling Rd., Pingzhen Dist., + Tao Yuan 324 + TW + +60-B4-F7 (hex) Plume Design Inc +60B4F7 (base 16) Plume Design Inc + 200 California Ave + Palo Alto CA 94306 + US + +48-7A-DA (hex) Hangzhou H3C Technologies Co., Limited +487ADA (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +00-1F-45 (hex) Enterasys +001F45 (base 16) Enterasys + 50 Minuteman Road + Andover MA 01810 + US + +00-1E-90 (hex) Elitegroup Computer Systems Co.,Ltd. +001E90 (base 16) Elitegroup Computer Systems Co.,Ltd. + No.239, Sec. 2, Ti Ding Blvd + Taipei 11493 + TW + +00-22-B1 (hex) Elbit Systems Ltd. +0022B1 (base 16) Elbit Systems Ltd. + p.o.b. 539 + Haifa 36925 + IL + +00-00-B4 (hex) Edimax Technology Co. Ltd. +0000B4 (base 16) Edimax Technology Co. Ltd. + No. 278, Xinhu 1st Road + Taipei City Neihu Dist 248 + TW + +00-16-8F (hex) GN Netcom A/S +00168F (base 16) GN Netcom A/S + Metalbuen 66 + Ballerup Skovlunde DK-2750 + DK + +00-0D-87 (hex) Elitegroup Computer Systems Co.,Ltd. +000D87 (base 16) Elitegroup Computer Systems Co.,Ltd. + No.22, Alley 38, Lane 91, Sec. 1, Nei Hu + Taipei 114 + TW + +10-78-D2 (hex) Elitegroup Computer Systems Co.,Ltd. +1078D2 (base 16) Elitegroup Computer Systems Co.,Ltd. + NO. 239, Sec. 2, Ti Ding Blvd. + Taipei Taiwan 11493 + TW + +00-21-97 (hex) Elitegroup Computer Systems Co.,Ltd. +002197 (base 16) Elitegroup Computer Systems Co.,Ltd. + NO.239, Sec. 2, Ti Ding Blvd., + Taipei 11493 + TW + +E4-F3-F5 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +E4F3F5 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + 3/F, Building R1-B, High-Tech Industrial Park, Nanshan District + Shenzhen Guangdong 518057 + CN + +A0-8C-FD (hex) Hewlett Packard +A08CFD (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +00-0E-03 (hex) Emulex Corporation +000E03 (base 16) Emulex Corporation + 3333 Susan Street + Costa Mesa CA 92626 + US + +00-CA-E5 (hex) Cisco Systems, Inc +00CAE5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-42-68 (hex) Cisco Systems, Inc +004268 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +48-83-C7 (hex) Sagemcom Broadband SAS +4883C7 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +40-16-3B (hex) Samsung Electronics Co.,Ltd +40163B (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +44-65-0D (hex) Amazon Technologies Inc. +44650D (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +D4-F2-07 (hex) DIAODIAO(Beijing)Technology CO.,Ltd +D4F207 (base 16) DIAODIAO(Beijing)Technology CO.,Ltd + 48D Image Base, No 3 Guangqu Road, Chaoyang District, Beijing, China + Beijing 100124 + CN + +D4-AD-2D (hex) Fiberhome Telecommunication Technologies Co.,LTD +D4AD2D (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +F0-8C-FB (hex) Fiberhome Telecommunication Technologies Co.,LTD +F08CFB (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +48-55-5F (hex) Fiberhome Telecommunication Technologies Co.,LTD +48555F (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +FC-3F-7C (hex) HUAWEI TECHNOLOGIES CO.,LTD +FC3F7C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +38-4C-4F (hex) HUAWEI TECHNOLOGIES CO.,LTD +384C4F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +0C-BF-3F (hex) Shenzhen Lencotion Technology Co.,Ltd +0CBF3F (base 16) Shenzhen Lencotion Technology Co.,Ltd + LongGang,Buji Xia Shuijing,Hubei Baofeng Lndustrial Area,2/F,TowerB + shenzhen Guangdong 518112 + CN + +50-FF-99 (hex) IEEE Registration Authority +50FF99 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +84-E3-23 (hex) Green Wave Telecommunication SDN BHD +84E323 (base 16) Green Wave Telecommunication SDN BHD + 8, 12, 9 - Menara Mutiara, Bangsar, Jalan Liku, Off Jalan Bangsar + Kuala Lumpur 59100 + MY + +70-5A-9E (hex) Technicolor CH USA Inc. +705A9E (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +04-A3-16 (hex) Texas Instruments +04A316 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +14-0C-5B (hex) PLNetworks +140C5B (base 16) PLNetworks + B-613, Tancheonsang-ro 164(Sigma 2) + Seongnam-si Bundang-gu, Gyeonggi-do 13631 + KR + +00-17-06 (hex) Techfaithwireless Communication Technology Limited. +001706 (base 16) Techfaithwireless Communication Technology Limited. + 2/F M8 West No.1 Jiu Xian Qiao Dong Road, + Beijing 100016 + CN + +FC-08-4A (hex) FUJITSU LIMITED +FC084A (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +BC-98-89 (hex) Fiberhome Telecommunication Technologies Co.,LTD +BC9889 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +24-61-5A (hex) China Mobile Group Device Co.,Ltd. +24615A (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +40-5E-E1 (hex) Shenzhen H&T Intelligent Control Co.,Ltd. +405EE1 (base 16) Shenzhen H&T Intelligent Control Co.,Ltd. + D-Zone,10/F,Shenzhen Academy of Aerospace Technology,Hi-Tech Park at Nanshan District,Shenzhen,China + Shenzhen 518000 + CN + +00-25-78 (hex) JSC Concern Sozvezdie +002578 (base 16) JSC Concern Sozvezdie + Plekhanovskaya st., 14 + Voronezh 394018 + RU + +30-B4-9E (hex) TP-LINK TECHNOLOGIES CO.,LTD. +30B49E (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +C8-38-70 (hex) Samsung Electronics Co.,Ltd +C83870 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +1C-55-3A (hex) QianGua Corp. +1C553A (base 16) QianGua Corp. + Room 1106, block B,No.391,Gui Ping Road + Xu Hui District ShangHai 200223 + CN + +34-E7-0B (hex) HAN Networks Co., Ltd +34E70B (base 16) HAN Networks Co., Ltd + 5F,#37 Building,#8 Dongbeiwang Eest Road + Haidian District Beijing 100193 + CN + +00-78-88 (hex) Cisco Systems, Inc +007888 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +90-03-25 (hex) HUAWEI TECHNOLOGIES CO.,LTD +900325 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +98-E7-F5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +98E7F5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +08-5B-DA (hex) CliniCare LTD +085BDA (base 16) CliniCare LTD + HaSadna 11 Suite 207 + Ra'anana 4365006 + IL + +1C-C0-35 (hex) PLANEX COMMUNICATIONS INC. +1CC035 (base 16) PLANEX COMMUNICATIONS INC. + Planex Volta Bldg., 2-11-9 Ebisu-Nishi,Shibuya-ku,Tokyo 150-0021,Japan + Tokyo Tokyo 150-0021 + JP + +34-54-3C (hex) TAKAOKA TOKO CO.,LTD. +34543C (base 16) TAKAOKA TOKO CO.,LTD. + 8F,SIA TOYOSU PRIME SQUARE,5-6-36,Toyosu + Koto-ku Tokyo 1350061 + JP + +18-66-DA (hex) Dell Inc. +1866DA (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +58-32-77 (hex) Reliance Communications LLC +583277 (base 16) Reliance Communications LLC + 555 Wireless Blvd + Hauppauge NY 11788 + US + +24-8A-07 (hex) Mellanox Technologies, Inc. +248A07 (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +9C-9D-5D (hex) Raden Inc +9C9D5D (base 16) Raden Inc + 15 Maiden Lane + New York NY 10038 + US + +DC-4D-23 (hex) MRV Comunications +DC4D23 (base 16) MRV Comunications + Hayetzira + Yokneam 614 + IL + +00-23-B3 (hex) Lyyn AB +0023B3 (base 16) Lyyn AB + IDEON Science Park + Lund 223 70 + SE + +40-2E-28 (hex) MiXTelematics +402E28 (base 16) MiXTelematics + Blaauwklip Office Park 2 + Stellenbosch Cape Province 7600 + ZA + +6C-8F-B5 (hex) Microsoft Mobile Oy +6C8FB5 (base 16) Microsoft Mobile Oy + Keilalahdentie 4 + Espoo 02150 + FI + +00-8E-73 (hex) Cisco Systems, Inc +008E73 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-15-C1 (hex) Sony Interactive Entertainment Inc. +0015C1 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +A0-9D-91 (hex) SoundBridge +A09D91 (base 16) SoundBridge + #810, IT Convergence Industrial Bldg. 47, Gyeongdae-ro 17-Gil, Buk-gu, + Daegu 41566 + KR + +40-B6-88 (hex) LEGIC Identsystems AG +40B688 (base 16) LEGIC Identsystems AG + Binzackerstrasse 41 + Wetzikon 8620 + CH + +9C-D4-8B (hex) Innolux Technology Europe BV +9CD48B (base 16) Innolux Technology Europe BV + Stationstraat 39G + Heerlen 6411NK + NL + +90-A6-2F (hex) NAVER +90A62F (base 16) NAVER + NAVER Green Factory, 6, Buljeong-ro, Bundang-gu + Seongnam-si Gyeonggi-do 463-867 + KR + +C0-C5-22 (hex) ARRIS Group, Inc. +C0C522 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +1C-9E-46 (hex) Apple, Inc. +1C9E46 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C4-E5-10 (hex) Mechatro, Inc. +C4E510 (base 16) Mechatro, Inc. + 169-28, Gasan Digital 2-ro, Geumcheon-Gu + Seoul 08500 + KR + +18-A6-F7 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +18A6F7 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +00-35-1A (hex) Cisco Systems, Inc +00351A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-AF-1F (hex) Cisco Systems, Inc +00AF1F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +80-38-96 (hex) SHARP Corporation +803896 (base 16) SHARP Corporation + 1 Takumi-cho, Sakai-ku + Sakai City Osaka 590-8522 + JP + +00-60-EC (hex) HERMARY OPTO ELECTRONICS INC. +0060EC (base 16) HERMARY OPTO ELECTRONICS INC. + 201-4050 GRAVELEY ST + BURNABY, BC V5C-3T6 + CA + +C0-CC-F8 (hex) Apple, Inc. +C0CCF8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-4F-DA (hex) Apple, Inc. +9C4FDA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-89-AD (hex) Apple, Inc. +8489AD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-3A-7A (hex) Roku, Inc. +AC3A7A (base 16) Roku, Inc. + 12980 Saratoga Ave + Saratoga 95070 + US + +B8-3E-59 (hex) Roku, Inc. +B83E59 (base 16) Roku, Inc. + 12980 Saratoga Ave. + Saratoga CA 95070 + US + +DC-3A-5E (hex) Roku, Inc. +DC3A5E (base 16) Roku, Inc. + 12980 Saratoga Ave. + Saratoga CA 95070 + US + +00-1A-73 (hex) Gemtek Technology Co., Ltd. +001A73 (base 16) Gemtek Technology Co., Ltd. + No. 1 Jen Ai Road, Hsinchu Industrial Park, Hukou, + Hsinchu 303 + TW + +00-90-4B (hex) Gemtek Technology Co., Ltd. +00904B (base 16) Gemtek Technology Co., Ltd. + No. 1 Jen Ai Road, + Hukou, Hsinchu, Taiwan 30352 + TW + +00-1A-7F (hex) GCI Science & Technology Co.,LTD +001A7F (base 16) GCI Science & Technology Co.,LTD + No.381, Xingangzhong Road, + guangzhou guangdong 510310 + CN + +00-18-0F (hex) Nokia Danmark A/S +00180F (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V Denmark 1790V + DK + +C8-97-9F (hex) Nokia Corporation +C8979F (base 16) Nokia Corporation + Joensuunkatu 7 + Salo Varsinais-Suomi 24101 + FI + +EC-F3-5B (hex) Nokia Corporation +ECF35B (base 16) Nokia Corporation + Joensuunkatu 7 + Salo Varsinais-Suomi 24101 + FI + +54-44-08 (hex) Nokia Corporation +544408 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo Varsinais-Suomi 24101 + FI + +3C-C2-43 (hex) Nokia Corporation +3CC243 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo NA 24101 + FI + +00-21-FC (hex) Nokia Danmark A/S +0021FC (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790V + DK + +00-1F-5D (hex) Nokia Danmark A/S +001F5D (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790V + DK + +00-1F-01 (hex) Nokia Danmark A/S +001F01 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790V + DK + +00-1B-EE (hex) Nokia Danmark A/S +001BEE (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-19-79 (hex) Nokia Danmark A/S +001979 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-25-D0 (hex) Nokia Danmark A/S +0025D0 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-24-D4 (hex) FREEBOX SAS +0024D4 (base 16) FREEBOX SAS + 8 rue de la Ville l'Eveque + PARIS IdF 75008 + FR + +34-7E-39 (hex) Nokia Danmark A/S +347E39 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-50-7F (hex) DrayTek Corp. +00507F (base 16) DrayTek Corp. + 26, Fushing Rd. + Hsinchu Hukou 303 + TW + +64-77-91 (hex) Samsung Electronics Co.,Ltd +647791 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +9C-E6-E7 (hex) Samsung Electronics Co.,Ltd +9CE6E7 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +9C-02-98 (hex) Samsung Electronics Co.,Ltd +9C0298 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +28-98-7B (hex) Samsung Electronics Co.,Ltd +28987B (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-FA-3E (hex) Samsung Electronics Co.,Ltd +54FA3E (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +0C-89-10 (hex) Samsung Electronics Co.,Ltd +0C8910 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +78-AB-BB (hex) Samsung Electronics Co.,Ltd +78ABBB (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +D8-C4-E9 (hex) Samsung Electronics Co.,Ltd +D8C4E9 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +BC-D1-1F (hex) Samsung Electronics Co.,Ltd +BCD11F (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F4-42-8F (hex) Samsung Electronics Co.,Ltd +F4428F (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-90-A2 (hex) CyberTAN Technology Inc. +0090A2 (base 16) CyberTAN Technology Inc. + 99, Park Avenue III + Hsinchu 12345 + TW + +00-90-D6 (hex) Crystal Group, Inc. +0090D6 (base 16) Crystal Group, Inc. + 850 KACENA RD. + HIAWATHA IA 52233 + US + +44-6D-6C (hex) Samsung Electronics Co.,Ltd +446D6C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-F4-6F (hex) Samsung Electronics Co.,Ltd +00F46F (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +0C-71-5D (hex) Samsung Electronics Co.,Ltd +0C715D (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +9C-80-DF (hex) Arcadyan Technology Corporation +9C80DF (base 16) Arcadyan Technology Corporation + 4F, No. 9, Park Avenue II , + Hsinchu 300 + TW + +00-23-08 (hex) Arcadyan Technology Corporation +002308 (base 16) Arcadyan Technology Corporation + 4F, No. 9, Park Avenue II , + Hsinchu 300 + TW + +88-03-55 (hex) Arcadyan Technology Corporation +880355 (base 16) Arcadyan Technology Corporation + 4F., No.9 , Park Avenue II + Hsinchu 300 + TW + +34-BB-1F (hex) BlackBerry RTS +34BB1F (base 16) BlackBerry RTS + 451 Phillip Street + Waterloo ON N2L 3X2 + CA + +40-6F-2A (hex) BlackBerry RTS +406F2A (base 16) BlackBerry RTS + 295 Phillip Street + Waterloo Ontario N2V 2S7 + CA + +7C-1C-F1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +7C1CF1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +78-F5-57 (hex) HUAWEI TECHNOLOGIES CO.,LTD +78F557 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E0-28-61 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E02861 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D0-D0-4B (hex) HUAWEI TECHNOLOGIES CO.,LTD +D0D04B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +48-00-31 (hex) HUAWEI TECHNOLOGIES CO.,LTD +480031 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D4-76-EA (hex) zte corporation +D476EA (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-17-5A (hex) Cisco Systems, Inc +00175A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +08-96-D7 (hex) AVM GmbH +0896D7 (base 16) AVM GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +50-6A-03 (hex) NETGEAR +506A03 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +10-0D-7F (hex) NETGEAR +100D7F (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +50-4A-6E (hex) NETGEAR +504A6E (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +4C-09-D4 (hex) Arcadyan Technology Corporation +4C09D4 (base 16) Arcadyan Technology Corporation + 4F, No. 9, Park Avenue II , + Hsinchu 300 + TW + +18-C0-86 (hex) Broadcom +18C086 (base 16) Broadcom + 5300 California Avenue + Irvine CA 92617 + US + +00-10-18 (hex) Broadcom +001018 (base 16) Broadcom + 16215 ALTON PARKWAY + IRVINE CA 92619-7013 + US + +C8-FF-28 (hex) Liteon Technology Corporation +C8FF28 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +B8-16-19 (hex) ARRIS Group, Inc. +B81619 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +B0-77-AC (hex) ARRIS Group, Inc. +B077AC (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +FC-B4-E6 (hex) ASKEY COMPUTER CORP +FCB4E6 (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + TAIWAN NEW TAIPEI 23585 + TW + +00-19-2C (hex) ARRIS Group, Inc. +00192C (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-19-5E (hex) ARRIS Group, Inc. +00195E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1A-1B (hex) ARRIS Group, Inc. +001A1B (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1A-66 (hex) ARRIS Group, Inc. +001A66 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1A-77 (hex) ARRIS Group, Inc. +001A77 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +64-ED-57 (hex) ARRIS Group, Inc. +64ED57 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +A4-ED-4E (hex) ARRIS Group, Inc. +A4ED4E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-21-1E (hex) ARRIS Group, Inc. +00211E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-21-80 (hex) ARRIS Group, Inc. +002180 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1B-DD (hex) ARRIS Group, Inc. +001BDD (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-6B (hex) ARRIS Group, Inc. +001D6B (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-BE (hex) ARRIS Group, Inc. +001DBE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-12-C9 (hex) ARRIS Group, Inc. +0012C9 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-23-A2 (hex) ARRIS Group, Inc. +0023A2 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-23-ED (hex) ARRIS Group, Inc. +0023ED (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1B-52 (hex) ARRIS Group, Inc. +001B52 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1E-8D (hex) ARRIS Group, Inc. +001E8D (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E0-46-9A (hex) NETGEAR +E0469A (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +30-46-9A (hex) NETGEAR +30469A (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-24-93 (hex) ARRIS Group, Inc. +002493 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-26-41 (hex) ARRIS Group, Inc. +002641 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-15-D0 (hex) ARRIS Group, Inc. +0015D0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-15-96 (hex) ARRIS Group, Inc. +001596 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +04-E6-76 (hex) AMPAK Technology, Inc. +04E676 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road + Hsinchu 30352 + TW + +00-22-F4 (hex) AMPAK Technology, Inc. +0022F4 (base 16) AMPAK Technology, Inc. + No. 8-1, Nanyuan 2nd Rd. + Jhongli Taoyuan 320 + TW + +00-1D-BA (hex) Sony Corporation +001DBA (base 16) Sony Corporation + Gotenyama Tec,5-1-12, + Shinagawa-ku Tokyo 141-0001 + JP + +00-24-BE (hex) Sony Corporation +0024BE (base 16) Sony Corporation + Gotenyama Tec. 5-1-12 + Shinagawa-ku Tokyo 141-0001 + JP + +00-0F-DE (hex) Sony Mobile Communications Inc +000FDE (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +0C-FE-45 (hex) Sony Interactive Entertainment Inc. +0CFE45 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +20-16-D8 (hex) Liteon Technology Corporation +2016D8 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo + New Taipei City Taipei 23585 + TW + +E0-63-E5 (hex) Sony Mobile Communications Inc +E063E5 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +F8-D0-AC (hex) Sony Interactive Entertainment Inc. +F8D0AC (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +24-21-AB (hex) Sony Mobile Communications Inc +2421AB (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +B8-F9-34 (hex) Sony Mobile Communications Inc +B8F934 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +8C-64-22 (hex) Sony Mobile Communications Inc +8C6422 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +20-E5-64 (hex) ARRIS Group, Inc. +20E564 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +90-B1-34 (hex) ARRIS Group, Inc. +90B134 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +40-B7-F3 (hex) ARRIS Group, Inc. +40B7F3 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1B-59 (hex) Sony Mobile Communications Inc +001B59 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-22-98 (hex) Sony Mobile Communications Inc +002298 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-17-E2 (hex) ARRIS Group, Inc. +0017E2 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-16-75 (hex) ARRIS Group, Inc. +001675 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-0C-E5 (hex) ARRIS Group, Inc. +000CE5 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-03-E0 (hex) ARRIS Group, Inc. +0003E0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-D0-C9 (hex) ADVANTECH CO., LTD. +00D0C9 (base 16) ADVANTECH CO., LTD. + FL. 4, NO. 108-3 + TAIPEI TAIPEI TAIWAN + TW + +64-87-D7 (hex) ADB Broadband Italia +6487D7 (base 16) ADB Broadband Italia + VIALE SARCA 222 + MILANO 20126 + IT + +E0-B2-F1 (hex) FN-LINK TECHNOLOGY LIMITED +E0B2F1 (base 16) FN-LINK TECHNOLOGY LIMITED + 5th Floor, A Building, Haoye Logistics Park, Shugang Channel, Bao'an District, + SHENZHEN GUANGDONG 518000 + CN + +0C-4C-39 (hex) MitraStar Technology Corp. +0C4C39 (base 16) MitraStar Technology Corp. + 4F No.6 Innovation Road II + Hsin-Chu 300 + TW + +74-88-8B (hex) ADB Broadband Italia +74888B (base 16) ADB Broadband Italia + via Sarca 222 + Milano 20126 + IT + +00-8C-54 (hex) ADB Broadband Italia +008C54 (base 16) ADB Broadband Italia + VIALE SARCA 336 + MILANO 20126 + US + +00-24-7B (hex) Actiontec Electronics, Inc +00247B (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +00-04-E3 (hex) Accton Technology Corp +0004E3 (base 16) Accton Technology Corp + No. 1 Creation Rd. III, + Hsinchu Hsinchu TAIWAN + TW + +00-10-B5 (hex) Accton Technology Corp +0010B5 (base 16) Accton Technology Corp + NO.1, CREATION RD. III + HSINCHU 300 12345 + TW + +00-19-74 (hex) 16063 +001974 (base 16) 16063 + 1F , No. 21, Yanfa 2nd Rd., SBIP + Hsinchu City Hsinchu 300 + TW + +E8-61-7E (hex) Liteon Technology Corporation +E8617E (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +18-CF-5E (hex) Liteon Technology Corporation +18CF5E (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +F0-27-2D (hex) Amazon Technologies Inc. +F0272D (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +84-D6-D0 (hex) Amazon Technologies Inc. +84D6D0 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +18-FE-34 (hex) Espressif Inc. +18FE34 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +38-22-9D (hex) ADB Broadband Italia +38229D (base 16) ADB Broadband Italia + VIALE SARCA 222 + MILANO 20126 + IT + +A4-52-6F (hex) ADB Broadband Italia +A4526F (base 16) ADB Broadband Italia + via Sarca 222 + Milano 20126 + IT + +60-5B-B4 (hex) AzureWave Technology Inc. +605BB4 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd., + New Taipei City Taiwan 231 + TW + +64-D9-54 (hex) Taicang T&W Electronics +64D954 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD, Lu Du, + Taicang Jiangsu 215412 + CN + +5C-36-B8 (hex) TCL King Electrical Appliances (Huizhou) Co., Ltd +5C36B8 (base 16) TCL King Electrical Appliances (Huizhou) Co., Ltd + 7/F,TCL Multimedia Building, TCL International E City, No.1001 Zhongshanyuan Road, Nanshan + Shenzhen Guangdong 518052 + CN + +00-AA-01 (hex) Intel Corporation +00AA01 (base 16) Intel Corporation + 445 + piscataway NJ 08554 + US + +98-5F-D3 (hex) Microsoft Corporation +985FD3 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +00-DA-55 (hex) Cisco Systems, Inc +00DA55 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +18-E3-BC (hex) TCT mobile ltd +18E3BC (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +CC-1F-C4 (hex) InVue +CC1FC4 (base 16) InVue + 15015 Lancaster Hwy + Charlotte NC 28277 + US + +00-AA-00 (hex) Intel Corporation +00AA00 (base 16) Intel Corporation + 5200 NE ELAM YOUNG PARKWAY + HILLSBORO OR 97124 + US + +00-C2-C6 (hex) Intel Corporate +00C2C6 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +5C-D2-E4 (hex) Intel Corporate +5CD2E4 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +28-B2-BD (hex) Intel Corporate +28B2BD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-22-43 (hex) AzureWave Technology Inc. +002243 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd., Xindian + Taipei 231 + TW + +00-00-6E (hex) Artisoft Inc. +00006E (base 16) Artisoft Inc. + 691 EAST RIVER ROAD + TUCSON AZ 85704 + US + +44-87-23 (hex) HOYA SERVICE CORPORATION +448723 (base 16) HOYA SERVICE CORPORATION + 4-10-2 Nakano + Nakano-ku Tokyo 164-8545 + JP + +D8-6C-02 (hex) Huaqin Telecom Technology Co.,Ltd +D86C02 (base 16) Huaqin Telecom Technology Co.,Ltd + No.1 Building,399 Keyuan Road, Zhangjian Hi-Tech Park, Pudong New Area + Shanghai 201203 + CN + +60-BE-B5 (hex) Motorola Mobility LLC, a Lenovo Company +60BEB5 (base 16) Motorola Mobility LLC, a Lenovo Company + 600 North US Highway 45 + Libertyville IL 60048 + US + +F8-F1-B6 (hex) Motorola Mobility LLC, a Lenovo Company +F8F1B6 (base 16) Motorola Mobility LLC, a Lenovo Company + 600 North US Highway 45 + Libertyville IL 60048 + US + +3C-FD-FE (hex) Intel Corporate +3CFDFE (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A4-C4-94 (hex) Intel Corporate +A4C494 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +90-2E-1C (hex) Intel Corporate +902E1C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A4-34-D9 (hex) Intel Corporate +A434D9 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +68-5D-43 (hex) Intel Corporate +685D43 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A0-36-9F (hex) Intel Corporate +A0369F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +64-D4-DA (hex) Intel Corporate +64D4DA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +40-25-C2 (hex) Intel Corporate +4025C2 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +50-2D-A2 (hex) Intel Corporate +502DA2 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +78-92-9C (hex) Intel Corporate +78929C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +84-3A-4B (hex) Intel Corporate +843A4B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +5C-51-4F (hex) Intel Corporate +5C514F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A4-4E-31 (hex) Intel Corporate +A44E31 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +4C-EB-42 (hex) Intel Corporate +4CEB42 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +F8-16-54 (hex) Intel Corporate +F81654 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +60-6C-66 (hex) Intel Corporate +606C66 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +4C-80-93 (hex) Intel Corporate +4C8093 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +AC-72-89 (hex) Intel Corporate +AC7289 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +44-85-00 (hex) Intel Corporate +448500 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +0C-D2-92 (hex) Intel Corporate +0CD292 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +DC-A9-71 (hex) Intel Corporate +DCA971 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +58-94-6B (hex) Intel Corporate +58946B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-24-D7 (hex) Intel Corporate +0024D7 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-24-D6 (hex) Intel Corporate +0024D6 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1D-E0 (hex) Intel Corporate +001DE0 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +4C-79-BA (hex) Intel Corporate +4C79BA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +84-A6-C8 (hex) Intel Corporate +84A6C8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +58-91-CF (hex) Intel Corporate +5891CF (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +0C-8B-FD (hex) Intel Corporate +0C8BFD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-21-5C (hex) Intel Corporate +00215C (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-21-6B (hex) Intel Corporate +00216B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-22-FB (hex) Intel Corporate +0022FB (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-15-17 (hex) Intel Corporate +001517 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +A0-A8-CD (hex) Intel Corporate +A0A8CD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +5C-C5-D4 (hex) Intel Corporate +5CC5D4 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1E-64 (hex) Intel Corporate +001E64 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +F4-F1-E1 (hex) Motorola Mobility LLC, a Lenovo Company +F4F1E1 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 Merchandise Mart Plaza, Suite 1800 + Chicago IL 60654 + US + +9C-D9-17 (hex) Motorola Mobility LLC, a Lenovo Company +9CD917 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 Merchandise Mart Plaza, Suite 1800 + Chicago IL 60654 + US + +90-68-C3 (hex) Motorola Mobility LLC, a Lenovo Company +9068C3 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 Merchandise Mart Plaza, Suite 1800 + Chicago IL 60654 + US + +3C-19-7D (hex) Ericsson AB +3C197D (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +B4-E1-0F (hex) Dell Inc. +B4E10F (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-22-19 (hex) Dell Inc. +002219 (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +00-24-E8 (hex) Dell Inc. +0024E8 (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +B0-83-FE (hex) Dell Inc. +B083FE (base 16) Dell Inc. + One Dell way + Round Rock 78682 + US + +34-17-EB (hex) Dell Inc. +3417EB (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +F8-BC-12 (hex) Dell Inc. +F8BC12 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +18-A9-9B (hex) Dell Inc. +18A99B (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-13-72 (hex) Dell Inc. +001372 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-11-43 (hex) Dell Inc. +001143 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +4C-76-25 (hex) Dell Inc. +4C7625 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +44-A8-42 (hex) Dell Inc. +44A842 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-25-3C (hex) 2Wire Inc +00253C (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +34-EF-44 (hex) 2Wire Inc +34EF44 (base 16) 2Wire Inc + 1764 Automation Pkwy + San Jose CA 95131 + US + +B0-E7-54 (hex) 2Wire Inc +B0E754 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose 95131 + US + +F0-1F-AF (hex) Dell Inc. +F01FAF (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-18-8B (hex) Dell Inc. +00188B (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-08-74 (hex) Dell Inc. +000874 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +B8-E6-25 (hex) 2Wire Inc +B8E625 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose 95131 + US + +00-1D-5A (hex) 2Wire Inc +001D5A (base 16) 2Wire Inc + 1704 Automation Parkway + San Jose 95131 + US + +1C-44-19 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +1C4419 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +5C-35-3B (hex) Compal Broadband Networks, Inc. +5C353B (base 16) Compal Broadband Networks, Inc. + 13F., No.1, Taiyuan 1st St. + Zhubei City Hsinchu County 30265 + TW + +28-FA-A0 (hex) vivo Mobile Communication Co., Ltd. +28FAA0 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +EC-DF-3A (hex) vivo Mobile Communication Co., Ltd. +ECDF3A (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +F4-29-81 (hex) vivo Mobile Communication Co., Ltd. +F42981 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +84-F6-FA (hex) Miovision Technologies Incorporated +84F6FA (base 16) Miovision Technologies Incorporated + 148 Manitou Drive + KITCHENER Ontario N2C1L4 + CA + +70-10-6F (hex) Hewlett Packard Enterprise +70106F (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +F8-E7-1E (hex) Ruckus Wireless +F8E71E (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +08-86-3B (hex) Belkin International Inc. +08863B (base 16) Belkin International Inc. + 12045 East Waterfront Drive + Playa Vista CA 90094 + US + +24-7C-4C (hex) Herman Miller +247C4C (base 16) Herman Miller + Unit 2, 2/F The Factory, 1 Yip Fat Street + Wong Chuk Hang - + HK + +E4-6F-13 (hex) D-Link International +E46F13 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +2C-56-DC (hex) ASUSTek COMPUTER INC. +2C56DC (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +00-31-46 (hex) Juniper Networks +003146 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-60-4C (hex) Sagemcom Broadband SAS +00604C (base 16) Sagemcom Broadband SAS + 27 RUE LEBLANC + CEDEX 15 PARIS 75512 + FR + +00-1F-95 (hex) Sagemcom Broadband SAS +001F95 (base 16) Sagemcom Broadband SAS + Le Ponnant de Paris + CEDEX Paris 75512 + FR + +00-23-48 (hex) Sagemcom Broadband SAS +002348 (base 16) Sagemcom Broadband SAS + Le Ponnant de Paris + CEDEX Paris 75512 + FR + +00-26-91 (hex) Sagemcom Broadband SAS +002691 (base 16) Sagemcom Broadband SAS + Le Ponnant de Paris + CEDEX Paris 75512 + FR + +98-8B-5D (hex) Sagemcom Broadband SAS +988B5D (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison 92848 + FR + +90-01-3B (hex) Sagemcom Broadband SAS +90013B (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison Cedex Hauts de Seine 92848 + FR + +7C-03-4C (hex) Sagemcom Broadband SAS +7C034C (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison Cedex Hauts de Seine 92848 + FR + +6C-2E-85 (hex) Sagemcom Broadband SAS +6C2E85 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison Cedex Hauts de Seine 92848 + FR + +94-FE-F4 (hex) Sagemcom Broadband SAS +94FEF4 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison Cedex Hauts de Seine 92848 + FR + +34-B1-F7 (hex) Texas Instruments +34B1F7 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +2C-FD-37 (hex) Blue Calypso, Inc. +2CFD37 (base 16) Blue Calypso, Inc. + 101 West Renner RD Suite 280 + Richardson TX 75082 + US + +0C-61-27 (hex) Actiontec Electronics, Inc +0C6127 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +3C-D9-2B (hex) Hewlett Packard +3CD92B (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +78-DE-E4 (hex) Texas Instruments +78DEE4 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-18-33 (hex) Texas Instruments +001833 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-18-34 (hex) Texas Instruments +001834 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-17-E3 (hex) Texas Instruments +0017E3 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-18-30 (hex) Texas Instruments +001830 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-23-D4 (hex) Texas Instruments +0023D4 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +BC-F6-85 (hex) D-Link International +BCF685 (base 16) D-Link International + 1 International Business Park, #03-12, The Synergy + SINGAPORE 609917 + SG + +78-54-2E (hex) D-Link International +78542E (base 16) D-Link International + 1 Internal Business Park, #03-12. + SINGAPORE Singapore 609917 + TW + +C4-A8-1D (hex) D-Link International +C4A81D (base 16) D-Link International + 1 Internal Business Park, #03-12, + SINGAPORE Singapore 609917 + SG + +00-21-91 (hex) D-Link Corporation +002191 (base 16) D-Link Corporation + NO.289, Sinhu 3rd Rd., + Neihu District, Taipei City 114 + TW + +AC-F1-DF (hex) D-Link International +ACF1DF (base 16) D-Link International + 1 International Business Park, #03-12, The Synergy + SINGAPORE 609917 + SG + +C0-E4-22 (hex) Texas Instruments +C0E422 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +D0-07-90 (hex) Texas Instruments +D00790 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +3C-7D-B1 (hex) Texas Instruments +3C7DB1 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +F4-FC-32 (hex) Texas Instruments +F4FC32 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +90-D7-EB (hex) Texas Instruments +90D7EB (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-17-E8 (hex) Texas Instruments +0017E8 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-17-83 (hex) Texas Instruments +001783 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-F8-71 (hex) DGS Denmark A/S +00F871 (base 16) DGS Denmark A/S + Kongebakken 9 + Smørum 2765 + DK + +24-35-CC (hex) Zhongshan Scinan Internet of Things Co.,Ltd. +2435CC (base 16) Zhongshan Scinan Internet of Things Co.,Ltd. + 15/F Bldg 1·Dezhong Plaza Torch Development Zone Zhongshan·Guangdong + ZhongShan GuangDong 528437 + CN + +2C-30-33 (hex) NETGEAR +2C3033 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +CC-46-D6 (hex) Cisco Systems, Inc +CC46D6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-41-D2 (hex) Cisco Systems, Inc +0041D2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +2C-AB-00 (hex) HUAWEI TECHNOLOGIES CO.,LTD +2CAB00 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A8-CA-7B (hex) HUAWEI TECHNOLOGIES CO.,LTD +A8CA7B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +BC-44-34 (hex) Shenzhen TINNO Mobile Technology Corp. +BC4434 (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F, H-3 Building, Qiao Cheng Eastern Industrial Park, Overseas Chinese Town, Shenzhen + Shenzhen guangdong 518053 + CN + +04-BF-6D (hex) Zyxel Communications Corporation +04BF6D (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +F8-8F-CA (hex) Google, Inc. +F88FCA (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View 94043 + US + +38-98-D8 (hex) MERITECH CO.,LTD +3898D8 (base 16) MERITECH CO.,LTD + 52-17 Sinjeon-Ro 41beon-gil + Giheung-gu, Yongin-City Kyungki-do 446-599 + KR + +94-86-CD (hex) SEOUL ELECTRONICS&TELECOM +9486CD (base 16) SEOUL ELECTRONICS&TELECOM + 709, Namkwangcentrex 440-4, Cheongcheon-dong, + Bupyeong-gu Incheon 403-030 + KR + +38-97-D6 (hex) Hangzhou H3C Technologies Co., Limited +3897D6 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +1C-A7-70 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD +1CA770 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + Unit A 13-16/F,Skyworth Bldg., Gaoxin Ave.1.S.,Nanshan District + ShenZhen GuangDong 518057 + CN + +44-19-B6 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +4419B6 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.469,Jianghui Road + Hangzhou Zhejiang 310052 + CN + +68-DB-CA (hex) Apple, Inc. +68DBCA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +08-66-98 (hex) Apple, Inc. +086698 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-54-36 (hex) Apple, Inc. +BC5436 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-4B-ED (hex) Apple, Inc. +044BED (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-8D-C1 (hex) Apple, Inc. +6C8DC1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-AC-FB (hex) Crouzet Automatismes +84ACFB (base 16) Crouzet Automatismes + 2 rue du docteur Abel + Valence France 26902 + FR + +7C-BB-8A (hex) Nintendo Co., Ltd. +7CBB8A (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +FC-FF-AA (hex) IEEE Registration Authority +FCFFAA (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +0C-D7-46 (hex) Apple, Inc. +0CD746 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-A3-7D (hex) Apple, Inc. +60A37D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-A2-5E (hex) Juniper Networks +88A25E (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +54-1E-56 (hex) Juniper Networks +541E56 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +88-96-B6 (hex) Global Fire Equipment S.A. +8896B6 (base 16) Global Fire Equipment S.A. + Sitio dos Barrabés, Armazém Nave Y, + São Brás de Alportel Faro 8150-016 + PT + +88-B8-D0 (hex) Dongguan Koppo Electronic Co.,Ltd +88B8D0 (base 16) Dongguan Koppo Electronic Co.,Ltd + No.2, Third Road, Buxinji Industrial Area, Guanjingtou Village, Fenggang Town, Dongguan City, Guangdong Province, China + Dongguan 523705 + CN + +60-19-71 (hex) ARRIS Group, Inc. +601971 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F8-CA-B8 (hex) Dell Inc. +F8CAB8 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-11-11 (hex) Intel Corporation +001111 (base 16) Intel Corporation + 2111 NE 25th Avenue + Hillsboro OR 97124 + US + +00-13-02 (hex) Intel Corporate +001302 (base 16) Intel Corporate + Lot 8, Jalan Hi-tech 2/3 + Kulim Kedah 09000 + MY + +6C-CA-08 (hex) ARRIS Group, Inc. +6CCA08 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +78-71-9C (hex) ARRIS Group, Inc. +78719C (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D4-05-98 (hex) ARRIS Group, Inc. +D40598 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E8-33-81 (hex) ARRIS Group, Inc. +E83381 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +8C-7F-3B (hex) ARRIS Group, Inc. +8C7F3B (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +5C-57-1A (hex) ARRIS Group, Inc. +5C571A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E8-89-2C (hex) ARRIS Group, Inc. +E8892C (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +94-87-7C (hex) ARRIS Group, Inc. +94877C (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +40-70-09 (hex) ARRIS Group, Inc. +407009 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +08-3E-0C (hex) ARRIS Group, Inc. +083E0C (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +3C-36-E4 (hex) ARRIS Group, Inc. +3C36E4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +1C-1B-68 (hex) ARRIS Group, Inc. +1C1B68 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-04-23 (hex) Intel Corporation +000423 (base 16) Intel Corporation + M/S: JF3-420 + Hillsboro OR 97124 + US + +20-73-55 (hex) ARRIS Group, Inc. +207355 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F8-ED-A5 (hex) ARRIS Group, Inc. +F8EDA5 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +54-65-DE (hex) ARRIS Group, Inc. +5465DE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +58-AC-78 (hex) Cisco Systems, Inc +58AC78 (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +78-0A-C7 (hex) Baofeng TV Co., Ltd. +780AC7 (base 16) Baofeng TV Co., Ltd. + Room 2D, Building 5D, Nanshan District Software Industry Base + ShenZhen GuangDong 518000 + CN + +00-0D-0B (hex) BUFFALO.INC +000D0B (base 16) BUFFALO.INC + MELCO HI-TECH CENTER, + NAGOYA 457-8520 + JP + +00-1D-73 (hex) BUFFALO.INC +001D73 (base 16) BUFFALO.INC + 15,Shibata Hondori 4-chome, + Nagoya Aichi Pref. 457-8520 + JP + +00-16-01 (hex) BUFFALO.INC +001601 (base 16) BUFFALO.INC + AKAMONDORI Bldg., 30-20,Ohsu 3-chome + Naka-ku,Nagoya Aichi Pref. 460-8315 + JP + +74-03-BD (hex) BUFFALO.INC +7403BD (base 16) BUFFALO.INC + AKAMONDORI Bldg, 30-20, Ohsu 3-chome, + Minami-ku, Nagoya Aichi Pref. 457-8520 + JP + +B8-FC-9A (hex) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited +B8FC9A (base 16) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited + ,Le Shi Building, No.105 Yaojiayuan Road,Chaoyang District,Beijing,China + beijing beijing 100025 + CN + +A4-5D-36 (hex) Hewlett Packard +A45D36 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +F0-92-1C (hex) Hewlett Packard +F0921C (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +A0-48-1C (hex) Hewlett Packard +A0481C (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +A0-1D-48 (hex) Hewlett Packard +A01D48 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +40-A8-F0 (hex) Hewlett Packard +40A8F0 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +88-51-FB (hex) Hewlett Packard +8851FB (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +08-2E-5F (hex) Hewlett Packard +082E5F (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +E4-11-5B (hex) Hewlett Packard +E4115B (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +28-92-4A (hex) Hewlett Packard +28924A (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +28-80-23 (hex) Hewlett Packard +288023 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +CC-3E-5F (hex) Hewlett Packard +CC3E5F (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +D8-9D-67 (hex) Hewlett Packard +D89D67 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +00-14-C2 (hex) Hewlett Packard +0014C2 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-80-5F (hex) Hewlett Packard +00805F (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-18-FE (hex) Hewlett Packard +0018FE (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-1A-4B (hex) Hewlett Packard +001A4B (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-24-81 (hex) Hewlett Packard +002481 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-0F-61 (hex) Hewlett Packard +000F61 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +48-0F-CF (hex) Hewlett Packard +480FCF (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +D4-0B-1A (hex) HTC Corporation +D40B1A (base 16) HTC Corporation + No. 23, Xinghua Rd. + Taoyuan County Taiwan 330 + TW + +94-53-30 (hex) Hon Hai Precision Ind. Co.,Ltd. +945330 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +A0-8D-16 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A08D16 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan Guangdong 523808 + CN + +4C-D0-8A (hex) HUMAX Co., Ltd. +4CD08A (base 16) HUMAX Co., Ltd. + HUMAX Village,216,Hwangsaeul-ro, + Seongnam-si Gyeonggi-do 463875 + KR + +CC-4E-EC (hex) HUMAX Co., Ltd. +CC4EEC (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bundang-gu, + Seongnam-si Gyeonggi-do 463-875 + KR + +40-3D-EC (hex) HUMAX Co., Ltd. +403DEC (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bundang-gu, + Seongnam-si Gyeonggi-do 463-875 + KR + +EC-4D-47 (hex) HUAWEI TECHNOLOGIES CO.,LTD +EC4D47 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-40-44 (hex) RackTop Systems Inc. +C44044 (base 16) RackTop Systems Inc. + 11840 W Market Pl Suite K + Fulton MD 20759 + US + +4C-A1-61 (hex) Rain Bird Corporation +4CA161 (base 16) Rain Bird Corporation + 970 West Sierra Madre Ave. + AZUSA CA 91702 + US + +8C-AB-8E (hex) Shanghai Feixun Communication Co.,Ltd. +8CAB8E (base 16) Shanghai Feixun Communication Co.,Ltd. + No.3666,Sixian Rd.,Songjiang District,Shanghai,P.R.China + Shanghai Shanghai 201616 + CN + +FC-64-BA (hex) Xiaomi Communications Co Ltd +FC64BA (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +90-60-F1 (hex) Apple, Inc. +9060F1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-D1-11 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +F8D111 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + 1-6F, Building 2, Pingshandayuan Industrial, South Zone, + Shenzhen Guangdong 518000 + CN + +B0-48-7A (hex) TP-LINK TECHNOLOGIES CO.,LTD. +B0487A (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + 1-6F, Building 2, Pingshandayuan Industrial, South Zone, + Shenzhen Guangdong 518000 + CN + +94-0C-6D (hex) TP-LINK TECHNOLOGIES CO.,LTD. +940C6D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 7, Second Part, Honghualing Industrial Zone + Shenzhen Guangdong 518000 + CN + +A4-51-6F (hex) Microsoft Mobile Oy +A4516F (base 16) Microsoft Mobile Oy + Keilalahdentie 4 + Espoo 02150 + FI + +54-27-58 (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +542758 (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan + Wuhan Hubei 430000 + CN + +00-24-2B (hex) Hon Hai Precision Ind. Co.,Ltd. +00242B (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-04-80 (hex) Brocade Communications Systems, Inc. +000480 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-0C-DB (hex) Brocade Communications Systems, Inc. +000CDB (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-1B-ED (hex) Brocade Communications Systems, Inc. +001BED (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-05-33 (hex) Brocade Communications Systems, Inc. +000533 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-60-69 (hex) Brocade Communications Systems, Inc. +006069 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +08-18-1A (hex) zte corporation +08181A (base 16) zte corporation + 12/F ZTE Plaza,Keji Road South,Hi-Tech Industrial Park,Nanshan District, + Shenzhen GUANGDONG 518057 + CN + +00-1E-73 (hex) zte corporation +001E73 (base 16) zte corporation + 12/F ZTE Plaza,Keji Road South,Hi-Tech Industrial Park,Nanshan District, + Shenzhen GUANGDONG 518057 + CN + +00-15-EB (hex) zte corporation +0015EB (base 16) zte corporation + 5/F,A Wing,ZTE Plaza,Keji Road South,Hi-Tech Industrial Park,Nanshan District + Shenzhen 518057 + US + +00-1C-25 (hex) Hon Hai Precision Ind. Co.,Ltd. +001C25 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-19-7E (hex) Hon Hai Precision Ind. Co.,Ltd. +00197E (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +90-FB-A6 (hex) Hon Hai Precision Ind. Co.,Ltd. +90FBA6 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +44-37-E6 (hex) Hon Hai Precision Ind. Co.,Ltd. +4437E6 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +CC-AF-78 (hex) Hon Hai Precision Ind. Co.,Ltd. +CCAF78 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +F4-B7-E2 (hex) Hon Hai Precision Ind. Co.,Ltd. +F4B7E2 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +64-70-02 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +647002 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan, + Shenzhen Guangdong Province, 518057 + CN + +10-FE-ED (hex) TP-LINK TECHNOLOGIES CO.,LTD. +10FEED (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park + Shenzhen Guangdong 518057 + CN + +64-56-01 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +645601 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +F0-27-65 (hex) Murata Manufacturing Co., Ltd. +F02765 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1 Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +5C-F8-A1 (hex) Murata Manufacturing Co., Ltd. +5CF8A1 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1 Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +44-A7-CF (hex) Murata Manufacturing Co., Ltd. +44A7CF (base 16) Murata Manufacturing Co., Ltd. + 2288, Oaza-Ohshinohara, Yasu-cho, + Yasu-gun Shiga 520-2393 + JP + +00-13-E0 (hex) Murata Manufacturing Co., Ltd. +0013E0 (base 16) Murata Manufacturing Co., Ltd. + 2288, Oaza-Ohshinohara, Yasu-cho, + Yasu-gun Shiga 520-2393 + JP + +EC-26-CA (hex) TP-LINK TECHNOLOGIES CO.,LTD. +EC26CA (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4)  + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +94-71-AC (hex) TCT mobile ltd +9471AC (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +2C-08-8C (hex) HUMAX Co., Ltd. +2C088C (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +1C-99-4C (hex) Murata Manufacturing Co., Ltd. +1C994C (base 16) Murata Manufacturing Co., Ltd. + 1-10-1 Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +00-60-DF (hex) Brocade Communications Systems, Inc. +0060DF (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +00-00-88 (hex) Brocade Communications Systems, Inc. +000088 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +F4-55-9C (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4559C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District + Shenzhen Guangdong 518057 + CN + +80-B6-86 (hex) HUAWEI TECHNOLOGIES CO.,LTD +80B686 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District + Shenzhen Guangdong 518057 + CN + +10-C6-1F (hex) HUAWEI TECHNOLOGIES CO.,LTD +10C61F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District + Shenzhen Guangdong 518057 + CN + +CC-96-A0 (hex) HUAWEI TECHNOLOGIES CO.,LTD +CC96A0 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +F8-01-13 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F80113 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park + Shenzhen Guangdong 518057 + CN + +A4-99-47 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A49947 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, + Shenzhen Guangdong 518057 + CN + +C8-D1-5E (hex) HUAWEI TECHNOLOGIES CO.,LTD +C8D15E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District + Shenzhen Guangdong 518057 + CN + +78-59-68 (hex) Hon Hai Precision Ind. Co.,Ltd. +785968 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +C0-70-09 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C07009 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +80-38-BC (hex) HUAWEI TECHNOLOGIES CO.,LTD +8038BC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-07-2F (hex) HUAWEI TECHNOLOGIES CO.,LTD +C4072F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-8E-92 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F48E92 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-66-4B (hex) HUAWEI TECHNOLOGIES CO.,LTD +00664B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +9C-C1-72 (hex) HUAWEI TECHNOLOGIES CO.,LTD +9CC172 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +24-7F-3C (hex) HUAWEI TECHNOLOGIES CO.,LTD +247F3C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +58-1F-28 (hex) HUAWEI TECHNOLOGIES CO.,LTD +581F28 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +EC-CB-30 (hex) HUAWEI TECHNOLOGIES CO.,LTD +ECCB30 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-DC-F9 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4DCF9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +30-87-30 (hex) HUAWEI TECHNOLOGIES CO.,LTD +308730 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +C0-57-BC (hex) Avaya Inc +C057BC (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +64-A7-DD (hex) Avaya Inc +64A7DD (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +24-1F-A0 (hex) HUAWEI TECHNOLOGIES CO.,LTD +241FA0 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-C5-8A (hex) HUAWEI TECHNOLOGIES CO.,LTD +18C58A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base + Shenzhen Guangdong 518129 + CN + +08-00-28 (hex) Texas Instruments +080028 (base 16) Texas Instruments + 12500 TI Boulevard + Dallas 75243 + US + +40-5F-C2 (hex) Texas Instruments +405FC2 (base 16) Texas Instruments + 12500 TI Boulevard + Dallas TX 75243 + US + +E0-E5-CF (hex) Texas Instruments +E0E5CF (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +68-DF-DD (hex) Xiaomi Communications Co Ltd +68DFDD (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +70-54-F5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +7054F5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +DC-D2-FC (hex) HUAWEI TECHNOLOGIES CO.,LTD +DCD2FC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +90-17-AC (hex) HUAWEI TECHNOLOGIES CO.,LTD +9017AC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base + Shenzhen Guangdong 518129 + CN + +34-CD-BE (hex) HUAWEI TECHNOLOGIES CO.,LTD +34CDBE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate + Shenzhen GuangDong 518057 + CN + +D8-49-0B (hex) HUAWEI TECHNOLOGIES CO.,LTD +D8490B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen 518129 + CN + +44-32-2A (hex) Avaya Inc +44322A (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +70-38-EE (hex) Avaya Inc +7038EE (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +70-30-18 (hex) Avaya Inc +703018 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +9C-28-EF (hex) HUAWEI TECHNOLOGIES CO.,LTD +9C28EF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +EC-24-B8 (hex) Texas Instruments +EC24B8 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +7C-EC-79 (hex) Texas Instruments +7CEC79 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +68-9E-19 (hex) Texas Instruments +689E19 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +20-CD-39 (hex) Texas Instruments +20CD39 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +B4-99-4C (hex) Texas Instruments +B4994C (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +A4-25-1B (hex) Avaya Inc +A4251B (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +64-6A-52 (hex) Avaya Inc +646A52 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +00-10-0B (hex) Cisco Systems, Inc +00100B (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-17-3B (hex) Cisco Systems, Inc +00173B (base 16) Cisco Systems, Inc + 170 West Tasman Dr. + San Jose CA 95134-1706 + US + +04-DA-D2 (hex) Cisco Systems, Inc +04DAD2 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +F0-29-29 (hex) Cisco Systems, Inc +F02929 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +20-BB-C0 (hex) Cisco Systems, Inc +20BBC0 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +4C-4E-35 (hex) Cisco Systems, Inc +4C4E35 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +98-FA-E3 (hex) Xiaomi Communications Co Ltd +98FAE3 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +F0-B4-29 (hex) Xiaomi Communications Co Ltd +F0B429 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +00-50-80 (hex) Cisco Systems, Inc +005080 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-50-73 (hex) Cisco Systems, Inc +005073 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-90-0C (hex) Cisco Systems, Inc +00900C (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-90-5F (hex) Cisco Systems, Inc +00905F (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-E0-F7 (hex) Cisco Systems, Inc +00E0F7 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-1B-D7 (hex) Cisco SPVTG +001BD7 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +00-60-83 (hex) Cisco Systems, Inc +006083 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-60-09 (hex) Cisco Systems, Inc +006009 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-06-7C (hex) Cisco Systems, Inc +00067C (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-10-7B (hex) Cisco Systems, Inc +00107B (base 16) Cisco Systems, Inc + 170 W.TASMAN DR.-SJA-2 + SAN JOSE CA 95134-1706 + US + +00-50-E2 (hex) Cisco Systems, Inc +0050E2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E4-D3-F1 (hex) Cisco Systems, Inc +E4D3F1 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +84-78-AC (hex) Cisco Systems, Inc +8478AC (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-90-A6 (hex) Cisco Systems, Inc +0090A6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-90-86 (hex) Cisco Systems, Inc +009086 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-8C (hex) ASUSTek COMPUTER INC. +00248C (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou,Taipei 112 ,Taiwan + Taipei Taiwan 112 + TW + +00-23-54 (hex) ASUSTek COMPUTER INC. +002354 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou,Taipei 112 ,Taiwan + Taipei Taiwan 112 + TW + +1C-87-2C (hex) ASUSTek COMPUTER INC. +1C872C (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.., Peitou, + Taipei 112 + TW + +60-18-2E (hex) ShenZhen Protruly Electronic Ltd co. +60182E (base 16) ShenZhen Protruly Electronic Ltd co. + ShenNan Road 1004 + Shen Zhen GuangDong 518000 + CN + +C4-14-3C (hex) Cisco Systems, Inc +C4143C (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +3C-08-F6 (hex) Cisco Systems, Inc +3C08F6 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-1E-8C (hex) ASUSTek COMPUTER INC. +001E8C (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou + Taipei 112 + TW + +00-13-D4 (hex) ASUSTek COMPUTER INC. +0013D4 (base 16) ASUSTek COMPUTER INC. + No.5 Shing Yeh Street + Tao Yuan Hsien 333 + TW + +20-CF-30 (hex) ASUSTek COMPUTER INC. +20CF30 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou,Taipei 112 ,Taiwan + Taipei Taiwan 112 + TW + +BC-16-65 (hex) Cisco Systems, Inc +BC1665 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +F8-72-EA (hex) Cisco Systems, Inc +F872EA (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +D0-C7-89 (hex) Cisco Systems, Inc +D0C789 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +F8-4F-57 (hex) Cisco Systems, Inc +F84F57 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +50-1C-BF (hex) Cisco Systems, Inc +501CBF (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +B0-00-B4 (hex) Cisco Systems, Inc +B000B4 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +54-4A-00 (hex) Cisco Systems, Inc +544A00 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-E1-6D (hex) Cisco Systems, Inc +00E16D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +78-BA-F9 (hex) Cisco Systems, Inc +78BAF9 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-22-CE (hex) Cisco SPVTG +0022CE (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30042 + US + +E0-D1-73 (hex) Cisco Systems, Inc +E0D173 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +E0-89-9D (hex) Cisco Systems, Inc +E0899D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +C4-72-95 (hex) Cisco Systems, Inc +C47295 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +7C-69-F6 (hex) Cisco Systems, Inc +7C69F6 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +78-DA-6E (hex) Cisco Systems, Inc +78DA6E (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +B8-78-2E (hex) Apple, Inc. +B8782E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-05-02 (hex) Apple, Inc. +000502 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-0A-95 (hex) Apple, Inc. +000A95 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-BD-C8 (hex) Cisco Systems, Inc +34BDC8 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +DC-EB-94 (hex) Cisco Systems, Inc +DCEB94 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +84-B5-17 (hex) Cisco Systems, Inc +84B517 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +1C-6E-4C (hex) Logistic Service & Engineering Co.,Ltd +1C6E4C (base 16) Logistic Service & Engineering Co.,Ltd + Unit N,9/F,Valiant Ind. Ctr.,2-12 Au Pui Wan St.,Fotan,Shatin,N.T.,Hong Kong + Hong Kong 00000 + HK + +00-0F-66 (hex) Cisco-Linksys, LLC +000F66 (base 16) Cisco-Linksys, LLC + 121 Theory Dr. + Irvine CA 92612 + US + +24-37-4C (hex) Cisco SPVTG +24374C (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +18-8B-9D (hex) Cisco Systems, Inc +188B9D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +E4-AA-5D (hex) Cisco Systems, Inc +E4AA5D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +F4-5F-D4 (hex) Cisco SPVTG +F45FD4 (base 16) Cisco SPVTG + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +2C-AB-A4 (hex) Cisco SPVTG +2CABA4 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +00-26-4A (hex) Apple, Inc. +00264A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-1E-64 (hex) Apple, Inc. +041E64 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-11-24 (hex) Apple, Inc. +001124 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-22-41 (hex) Apple, Inc. +002241 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +7C-C5-37 (hex) Apple, Inc. +7CC537 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-CA-39 (hex) Apple, Inc. +78CA39 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-E7-F4 (hex) Apple, Inc. +18E7F4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-CD-60 (hex) Apple, Inc. +70CD60 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +8C-7B-9D (hex) Apple, Inc. +8C7B9D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D8-9E-3F (hex) Apple, Inc. +D89E3F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B8-C7-5D (hex) Apple, Inc. +B8C75D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +0C-74-C2 (hex) Apple, Inc. +0C74C2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-30-04 (hex) Apple, Inc. +403004 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-29-99 (hex) Apple, Inc. +842999 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +74-E2-F5 (hex) Apple, Inc. +74E2F5 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-C9-7A (hex) Apple, Inc. +E0C97A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-A8-6D (hex) Apple, Inc. +68A86D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +7C-C3-A1 (hex) Apple, Inc. +7CC3A1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-73-CB (hex) Apple, Inc. +7073CB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-84-0D (hex) Apple, Inc. +90840D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E8-06-88 (hex) Apple, Inc. +E80688 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +EC-85-2F (hex) Apple, Inc. +EC852F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-F4-B9 (hex) Apple, Inc. +00F4B9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-95-AE (hex) Apple, Inc. +5C95AE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-03-D8 (hex) Apple, Inc. +9803D8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-C5-47 (hex) Apple, Inc. +60C547 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-5B-35 (hex) Apple, Inc. +685B35 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-B4-3A (hex) Apple, Inc. +2CB43A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-9C-70 (hex) Apple, Inc. +689C70 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-0F-4A (hex) Apple, Inc. +380F4A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +30-10-E4 (hex) Apple, Inc. +3010E4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-86-DD (hex) Apple, Inc. +A886DD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +44-4C-0C (hex) Apple, Inc. +444C0C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B4-F0-AB (hex) Apple, Inc. +B4F0AB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +80-92-9F (hex) Apple, Inc. +80929F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-04-EB (hex) Apple, Inc. +9C04EB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-96-9D (hex) Apple, Inc. +5C969D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-92-17 (hex) Apple, Inc. +609217 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-B1-53 (hex) Apple, Inc. +84B153 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-66-78 (hex) Apple, Inc. +E06678 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-D7-05 (hex) Apple, Inc. +48D705 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-15-52 (hex) Apple, Inc. +041552 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +CC-78-5F (hex) Apple, Inc. +CC785F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-CB-87 (hex) Apple, Inc. +88CB87 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-C1-F1 (hex) Apple, Inc. +F0C1F1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-38-35 (hex) Apple, Inc. +843835 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +8C-00-6D (hex) Apple, Inc. +8C006D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-96-8A (hex) Apple, Inc. +A8968A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-1B-A1 (hex) Apple, Inc. +F41BA1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-D9-C7 (hex) Apple, Inc. +60D9C7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-AB-8E (hex) Apple, Inc. +3CAB8E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-27-93 (hex) Apple, Inc. +F82793 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-72-40 (hex) Apple, Inc. +907240 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-8D-6C (hex) Apple, Inc. +908D6C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B8-09-8A (hex) Apple, Inc. +B8098A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +4C-7C-5F (hex) Apple, Inc. +4C7C5F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-64-4B (hex) Apple, Inc. +68644B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-1E-E7 (hex) Apple, Inc. +C81EE7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A4-31-35 (hex) Apple, Inc. +A43135 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-D9-3C (hex) Apple, Inc. +68D93C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-F7-6F (hex) Apple, Inc. +00F76F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C8-85-50 (hex) Apple, Inc. +C88550 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-14-A6 (hex) Apple, Inc. +7014A6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-5A-EB (hex) Apple, Inc. +985AEB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-D7-5F (hex) Apple, Inc. +78D75F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E0-B5-2D (hex) Apple, Inc. +E0B52D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-94-F8 (hex) Apple, Inc. +6C94F8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-CE-CD (hex) Apple, Inc. +C0CECD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-4B-2A (hex) Cisco SPVTG +F44B2A (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +74-6F-19 (hex) ICARVISIONS (SHENZHEN) TECHNOLOGY CO., LTD. +746F19 (base 16) ICARVISIONS (SHENZHEN) TECHNOLOGY CO., LTD. + 6F-1 ,Block D,Building 2#, Hongwan XinCun Ming JinHai Industry Area, Gushu Community, Xixiang Street, BaoAn District + Shenzhen Guangdong 518000 + CN + +2C-AE-2B (hex) Samsung Electronics Co.,Ltd +2CAE2B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C4-AD-F1 (hex) GOPEACE Inc. +C4ADF1 (base 16) GOPEACE Inc. + Woolim Bldg B-916, 14 Sagimakgol-ro 45beon-gil, Jungwon-gu + Seongnam Gyeonggi 13209 + KR + +58-FC-73 (hex) Arria Live Media, Inc. +58FC73 (base 16) Arria Live Media, Inc. + 2388 NE Lindsey Drive + Hillsboro OR 97124 + US + +0C-1A-10 (hex) Acoustic Stream +0C1A10 (base 16) Acoustic Stream + 3213 W Wheeler Street + Seattle WA 98199 + US + +C4-EF-70 (hex) Home Skinovations +C4EF70 (base 16) Home Skinovations + Tavor building POB 533 + Yokneam Israel 2069206 + IL + +5C-E3-B6 (hex) Fiberhome Telecommunication Technologies Co.,LTD +5CE3B6 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +7C-5A-67 (hex) JNC Systems, Inc. +7C5A67 (base 16) JNC Systems, Inc. + #611, Gyeonggi Venture Yeonsung University + Anyang-si Gyeonggi-do 430731 + KR + +A0-F9-E0 (hex) VIVATEL COMPANY LIMITED +A0F9E0 (base 16) VIVATEL COMPANY LIMITED + 36/F,Tower Two + Causeway Bay Causeway Bay 999077 + HK + +C8-69-CD (hex) Apple, Inc. +C869CD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A4-B8-05 (hex) Apple, Inc. +A4B805 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-C9-9B (hex) Tesorion Nederland B.V. +90C99B (base 16) Tesorion Nederland B.V. + Auke Vleerstraat 6-D + Enschede 7521 PG + NL + +5C-AD-CF (hex) Apple, Inc. +5CADCF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +08-0A-4E (hex) Planet Bingo® — 3rd Rock Gaming® +080A4E (base 16) Planet Bingo® — 3rd Rock Gaming® + 75190 Gerald Ford Dr. + Palm Desert CA 92211 + US + +B4-9D-0B (hex) BQ +B49D0B (base 16) BQ + Sofia, 10 + Las Rozas de Madrid Madrid 28230 + ES + +3C-8C-F8 (hex) TRENDnet, Inc. +3C8CF8 (base 16) TRENDnet, Inc. + 20675 Manhattan Place + Torrance CA 90501 + US + +E8-13-63 (hex) Comstock RD, Inc. +E81363 (base 16) Comstock RD, Inc. + 4415 Mason St + Ashton ID 83406 + US + +74-18-65 (hex) Shanghai DareGlobal Technologies Co.,Ltd +741865 (base 16) Shanghai DareGlobal Technologies Co.,Ltd + 22F NO.1555 Kongjiang RD + Shanghai 200092 + CN + +BC-6C-21 (hex) Apple, Inc. +BC6C21 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-C3-72 (hex) TSUZUKI DENKI +F8C372 (base 16) TSUZUKI DENKI + shinbashi 6-19-15 + mainato-ku tokyo-to 105-8665 + JP + +D4-72-08 (hex) Bragi GmbH +D47208 (base 16) Bragi GmbH + Herzog-Heinrich-Strasse 20 + Munich Bavaria 80336 + DE + +A8-72-85 (hex) IDT, INC. +A87285 (base 16) IDT, INC. + 6024 SILVER CREEK VALLEY RD + SAN JOSE CA 95138 + US + +78-05-41 (hex) Queclink Wireless Solutions Co., Ltd +780541 (base 16) Queclink Wireless Solutions Co., Ltd + Room 501, Building 9, No.99 Tianzhou Road + shanghai shanghai 200233 + CN + +04-41-69 (hex) GoPro +044169 (base 16) GoPro + 3000 Clearview Way + San Mateo CA 94402 + US + +C0-2D-EE (hex) Cuff +C02DEE (base 16) Cuff + 232 Townsend St + San Francisco CA 94107 + US + +6C-EB-B2 (hex) Dongguan Sen DongLv Electronics Co.,Ltd +6CEBB2 (base 16) Dongguan Sen DongLv Electronics Co.,Ltd + Nanjiang RD 111st,Daning + Dongguan Guangdong 523930 + + +3C-7A-8A (hex) ARRIS Group, Inc. +3C7A8A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F4-0E-22 (hex) Samsung Electronics Co.,Ltd +F40E22 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +88-1B-99 (hex) SHENZHEN XIN FEI JIA ELECTRONIC CO. LTD. +881B99 (base 16) SHENZHEN XIN FEI JIA ELECTRONIC CO. LTD. + #4 BULIDING, HIGH TECH INDUSTRIAL PARK, HE PING COMMUNITY + GUANGDONG N/A 518000 + CN + +54-4E-90 (hex) Apple, Inc. +544E90 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A4-A6-A9 (hex) Private +A4A6A9 (base 16) Private + +8C-10-D4 (hex) Sagemcom Broadband SAS +8C10D4 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +F8-98-B9 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F898B9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +5C-B5-59 (hex) CNEX Labs +5CB559 (base 16) CNEX Labs + 2880 Stevens Creek Blvd + San Jose CA 95128 + US + +B8-3A-9D (hex) Alarm.com +B83A9D (base 16) Alarm.com + 8281 Greensboro Dr., Suite 100 + Tysons VA 22102 + US + +68-58-C5 (hex) ZF TRW Automotive +6858C5 (base 16) ZF TRW Automotive + ​12001 Tech Center Drive + Livonia MI 48150 + US + +C0-11-73 (hex) Samsung Electronics Co.,Ltd +C01173 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +78-53-F2 (hex) ROXTON Ltd. +7853F2 (base 16) ROXTON Ltd. + 15 Ostapovsky proezd + Moscow Moscow 109316 + RU + +BC-E6-3F (hex) Samsung Electronics Co.,Ltd +BCE63F (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +7C-91-22 (hex) Samsung Electronics Co.,Ltd +7C9122 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +AC-BC-32 (hex) Apple, Inc. +ACBC32 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-23-EC (hex) Availink, Inc. +9023EC (base 16) Availink, Inc. + Scotia Centre P.O. Box 268GT,Grand Cayman, Cayman Islands + Grand Cayman Grand Cayman 999159 + KY + +44-1C-A8 (hex) Hon Hai Precision Ind. Co.,Ltd. +441CA8 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +B4-29-3D (hex) Shenzhen Urovo Technology Co.,Ltd. +B4293D (base 16) Shenzhen Urovo Technology Co.,Ltd. + A701-710, Zondy Cyber Building, Keyuan South Road, + Nanshan District, Shenzhen Guangzhou 518057 + CN + +54-FF-82 (hex) Davit Solution co. +54FF82 (base 16) Davit Solution co. + 103-301,Geudaegapremier,21 Deagyeong-Daero 1484beon-Gil + Suwon-Si Gyeonggi-Do KS002 + KR + +50-DF-95 (hex) Lytx +50DF95 (base 16) Lytx + 9785 Towne Centre Drive + San Diego CA 92121 + US + +9C-A6-9D (hex) Whaley Technology Co.Ltd +9CA69D (base 16) Whaley Technology Co.Ltd + Floor 3, Building E, No666 Shengxia Road + Shanghai 201203 + CN + +58-53-C0 (hex) Beijing Guang Runtong Technology Development Company co.,Ltd +5853C0 (base 16) Beijing Guang Runtong Technology Development Company co.,Ltd + Beijing city Haidian District North Third Ring Road 48, Beijing science and Technology Exhibition Center 1 building B block, room 18H + Beijing Bejing 100000 + CN + +2C-A5-39 (hex) Parallel Wireless, Inc +2CA539 (base 16) Parallel Wireless, Inc + 1 Tara Blvd + Nashua NH 03062 + US + +CC-79-4A (hex) BLU Products Inc. +CC794A (base 16) BLU Products Inc. + Tower 4, Excellence Century Center + Shenzhen Guangdong 518000 + CN + +F4-E9-26 (hex) Tianjin Zanpu Technology Inc. +F4E926 (base 16) Tianjin Zanpu Technology Inc. + 3F Haiyi International Center, Huayuan Industrial Park, Tianjin + Tianjin Tianjin 300384 + CN + +90-6F-18 (hex) Private +906F18 (base 16) Private + +98-CB-27 (hex) Galore Networks Pvt. Ltd. +98CB27 (base 16) Galore Networks Pvt. Ltd. + #D1104, Salarpuria Serenity, 41A, + Bangalore Karnataka 560068 + IN + +E8-F2-E2 (hex) LG Innotek +E8F2E2 (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +24-72-60 (hex) IOTTECH Corp +247260 (base 16) IOTTECH Corp + 4F.-1, No.55, Dongguang Rd., East Dist., Hsinchu City 300, TAIWAN ,REPUBLIC OF CHINA + Hsinchu TAIWAN 300 + TW + +24-5B-F0 (hex) Liteon, Inc. +245BF0 (base 16) Liteon, Inc. + 3001 Summit Avenue, Suite 400 + Plano Tx 75074 + US + +E8-55-B4 (hex) SAI Technology Inc. +E855B4 (base 16) SAI Technology Inc. + 2376 Walsh Avenue + Santa Clara California 95051 + US + +34-0C-ED (hex) Moduel AB +340CED (base 16) Moduel AB + Hudiksvallsgatan 8 + Stockholm Stockholm 11330 + SE + +28-27-BF (hex) Samsung Electronics Co.,Ltd +2827BF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +94-D8-59 (hex) TCT mobile ltd +94D859 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +2C-FC-E4 (hex) CTEK Sweden AB +2CFCE4 (base 16) CTEK Sweden AB + Rostugnsvägen 3 + Vikmanshyttan Dalarna SE-776 70 + SE + +C0-EE-40 (hex) Laird Technologies +C0EE40 (base 16) Laird Technologies + 50 South Main St + Akron Ohio 44308 + US + +F4-B8-A7 (hex) zte corporation +F4B8A7 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +30-0C-23 (hex) zte corporation +300C23 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +C0-B7-13 (hex) Beijing Xiaoyuer Technology Co. Ltd. +C0B713 (base 16) Beijing Xiaoyuer Technology Co. Ltd. + No.5 Guangshunbei Rd. Rm# B129 + Beijing Beijing 100102 + CN + +10-05-B1 (hex) ARRIS Group, Inc. +1005B1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +20-63-5F (hex) Abeeway +20635F (base 16) Abeeway + 29 chemin du vieux chêne + meylan Isere 38240 + FR + +08-3A-5C (hex) Junilab, Inc. +083A5C (base 16) Junilab, Inc. + #205 107 Gyounggyo-Ro, Yeongtong-Gu, Suwon + Suwon Gyeonggi-Do 443-766 + KR + +B8-B3-DC (hex) DEREK (SHAOGUAN) LIMITED +B8B3DC (base 16) DEREK (SHAOGUAN) LIMITED + Gaojiling, Taiping Town, + Shao Guan Guang Dong 512500 + CN + +70-2A-7D (hex) EpSpot AB +702A7D (base 16) EpSpot AB + Aluddsparken 7D + Stockholm 11265 + SE + +4C-AE-31 (hex) ShengHai Electronics (Shenzhen) Ltd +4CAE31 (base 16) ShengHai Electronics (Shenzhen) Ltd + Block 17&18,Hui Ming Ying Industry,YanChuan,SongGang + Shenzhen Guangdong 518105 + CN + +18-8E-F9 (hex) G2C Co. Ltd. +188EF9 (base 16) G2C Co. Ltd. + 1004,1591-9, K-Center Kwanyang Dong + Anyang Si Kyeonggido 431-815 + KR + +44-F4-36 (hex) zte corporation +44F436 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +C4-7D-46 (hex) FUJITSU LIMITED +C47D46 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +18-5D-9A (hex) BobjGear LLC +185D9A (base 16) BobjGear LLC + 4327 S Highway 27 # 504 + Clermont Florida 34711 + US + +F4-E9-D4 (hex) QLogic Corporation +F4E9D4 (base 16) QLogic Corporation + 26650 Aliso Viejo Parkway + Aliso Viejo California + US + +4C-B7-6D (hex) Novi Security +4CB76D (base 16) Novi Security + 1434 E 820 N + Orem UT 84097 + US + +6C-E0-1E (hex) Modcam AB +6CE01E (base 16) Modcam AB + Bredgatan 4 + Malmö Skåne 21130 + SE + +74-85-2A (hex) PEGATRON CORPORATION +74852A (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +9C-B6-D0 (hex) Rivet Networks +9CB6D0 (base 16) Rivet Networks + 11940 Jollyville Rd + Austin tx 78759 + US + +40-B8-9A (hex) Hon Hai Precision Ind. Co.,Ltd. +40B89A (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +1C-B7-2C (hex) ASUSTek COMPUTER INC. +1CB72C (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +40-B8-37 (hex) Sony Mobile Communications Inc +40B837 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +4C-EE-B0 (hex) SHC Netzwerktechnik GmbH +4CEEB0 (base 16) SHC Netzwerktechnik GmbH + Ludwigstrasse 33-37 + Frankfurt am Main Hessen 60327 + DE + +80-01-84 (hex) HTC Corporation +800184 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +44-C6-9B (hex) Wuhan Feng Tian Information Network CO.,LTD +44C69B (base 16) Wuhan Feng Tian Information Network CO.,LTD + Room 1002,10th Floor,Oversea talent Building A, + Wuhan City Hubei Province 430074 + CN + +FC-E3-3C (hex) HUAWEI TECHNOLOGIES CO.,LTD +FCE33C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C0-25-67 (hex) Nexxt Solutions +C02567 (base 16) Nexxt Solutions + 3505 NW 107TH AVENUE + MIAMI FLORIDA 33178 + US + +60-9C-9F (hex) Brocade Communications Systems, Inc. +609C9F (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +A8-82-7F (hex) CIBN Oriental Network(Beijing) CO.,Ltd +A8827F (base 16) CIBN Oriental Network(Beijing) CO.,Ltd + Floor 18B,Block B(International Resources Building),No.18B(Wanda Plaza),Shijingshan Road,Shijingshan,Beijing(100043) + Beijing Beijing 100043 + CN + +D0-48-F3 (hex) DATTUS Inc +D048F3 (base 16) DATTUS Inc + 3000 Kent Ave + W Lafayette IN 47906 + US + +B8-C3-BF (hex) Henan Chengshi NetWork Technology Co.,Ltd +B8C3BF (base 16) Henan Chengshi NetWork Technology Co.,Ltd + Ruhe Road South,Kunlun Road West,Zhongyuan District,Zhengzhou,Henan,P.R.China,450007 + Zhengzhou Henan 450007 + CN + +44-96-2B (hex) Aidon Oy +44962B (base 16) Aidon Oy + Piippukatu 11 + Jyvaskyla Jyvaskyla 40100 + FI + +E0-76-D0 (hex) AMPAK Technology, Inc. +E076D0 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road + Hsinchu Hsinchu 30352 + TW + +B0-08-BF (hex) Vital Connect, Inc. +B008BF (base 16) Vital Connect, Inc. + 900 E HAMILTON AVE STE 500 + CAMPBELL CA 95008-0667 + US + +D4-52-2A (hex) TangoWiFi.com +D4522A (base 16) TangoWiFi.com + TangoWiFi Team + Beijing Beijing 100022 + CN + +E8-07-BF (hex) SHENZHEN BOOMTECH INDUSTRY CO.,LTD +E807BF (base 16) SHENZHEN BOOMTECH INDUSTRY CO.,LTD + Floor 6 East, Bldg 6, Yusheng Industrial Area, Xixiang, Bao'an District + Shenzhen Guangdong 518000 + CN + +84-F1-29 (hex) Metrascale Inc. +84F129 (base 16) Metrascale Inc. + 400 Liberty Ave. + Brooklyn NY 11207 + US + +B8-9A-CD (hex) ELITE OPTOELECTRONIC(ASIA)CO.,LTD +B89ACD (base 16) ELITE OPTOELECTRONIC(ASIA)CO.,LTD + A9 jin Fu 1 Road,Tangchun lndustrial zone,Liaobu Town,Dongguan City,Guangdong Province + Liaobu dongguan /guangdong 523400 + CN + +D4-68-BA (hex) Shenzhen Sundray Technologies Company Limited +D468BA (base 16) Shenzhen Sundray Technologies Company Limited + 6th Floor,Block A1, Nanshan iPark, + Nanshan District, Shenzhen 518055 Guangdong + CN + +08-62-66 (hex) ASUSTek COMPUTER INC. +086266 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +9C-30-66 (hex) RWE Effizienz GmbH +9C3066 (base 16) RWE Effizienz GmbH + Flamingoweg 1 + Dortmund NRW 44139 + DE + +18-BD-AD (hex) L-TECH CORPORATION +18BDAD (base 16) L-TECH CORPORATION + 201, Moonbon-dong + Ilsandong-gu Gyeonggi-do 410-560 + KR + +60-E6-BC (hex) Sino-Telecom Technology Co.,Ltd. +60E6BC (base 16) Sino-Telecom Technology Co.,Ltd. + 6F, Building 2, No.115, Lane 1276 Nanle Rd + 201613 + CN + +C8-C5-0E (hex) Shenzhen Primestone Network Technologies.Co., Ltd. +C8C50E (base 16) Shenzhen Primestone Network Technologies.Co., Ltd. + Room 705,Complex Building, Tsinghua Hi-Tech Park + Shenzhen Guangdong 518057 + CN + +D0-6A-1F (hex) BSE CO.,LTD. +D06A1F (base 16) BSE CO.,LTD. + 626-3, Gozan-dong, Namdong-ku + Incheon, 405-817 + KR + +70-01-36 (hex) FATEK Automation Corporation +700136 (base 16) FATEK Automation Corporation + 5F., NO.300, SEC. 1, NEIHU RD + Taipei City 114 + TW + +FC-A2-2A (hex) PT. Callysta Multi Engineering +FCA22A (base 16) PT. Callysta Multi Engineering + Jl. Taman Cibeunying No. 2 + Bandung Jawa Barat 40114 + ID + +A4-56-02 (hex) fenglian Technology Co.,Ltd. +A45602 (base 16) fenglian Technology Co.,Ltd. + 302 R D Building Oriental Cyberport HighTech Industrial Park Nanshan Shenzhen China + Shenzhen,Guangdong Province 518057 + CN + +94-E2-FD (hex) Boge Kompressoren OTTO Boge GmbH & Co. KG +94E2FD (base 16) Boge Kompressoren OTTO Boge GmbH & Co. KG + Otto Boge Str. 1-7 + Bielefeld Westfalia 33739 + DE + +F0-1E-34 (hex) ORICO Technologies Co., Ltd +F01E34 (base 16) ORICO Technologies Co., Ltd + F-9, Block14A, Zhonghaixin Science &Technology Zone + ShenZhen Guangdong 518116 + CN + +DC-E0-26 (hex) Patrol Tag, Inc +DCE026 (base 16) Patrol Tag, Inc + 2800 Western Ave + Seattle WA 98121 + US + +B4-05-66 (hex) SP Best Corporation Co., LTD. +B40566 (base 16) SP Best Corporation Co., LTD. + 555/25 B-Avenue, Sukhaphibal 5 Road + Saimai Bangkok 10220 + TH + +1C-C7-2D (hex) Shenzhen Huapu Digital CO.,Ltd +1CC72D (base 16) Shenzhen Huapu Digital CO.,Ltd + R2305 Malata Technology Building,NO.9998 Shennan Boulevard, Shenzhen,P.R.China 518057 + Shenzhen Guangzhou 518057 + CN + +A8-90-08 (hex) Beijing Yuecheng Technology Co. Ltd. +A89008 (base 16) Beijing Yuecheng Technology Co. Ltd. + Room 1601, Floor 16 + Beijing Beijing 100000 + CN + +18-38-64 (hex) CAP-TECH INTERNATIONAL CO., LTD. +183864 (base 16) CAP-TECH INTERNATIONAL CO., LTD. + Rm. 6, 4F., No.120, Qiaohe Rd., Zhonghe Dist + New Taipei City Taiwan 235 + TW + +6C-F5-E8 (hex) Mooredoll Inc. +6CF5E8 (base 16) Mooredoll Inc. + 5F,No.50,Ln.316,Ruiguan Rd.,Neihu Dist.,Taipei 114, Taiwan + Taipei Neihu 114 + TW + +8C-BF-A6 (hex) Samsung Electronics Co.,Ltd +8CBFA6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C8-A8-23 (hex) Samsung Electronics Co.,Ltd +C8A823 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-C5-59 (hex) Samsung Electronics Co.,Ltd +B0C559 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F4-2C-56 (hex) SENOR TECH CO LTD +F42C56 (base 16) SENOR TECH CO LTD + No.165, Kangning St + New Taipei City Taiwan 221 + TW + +FC-DC-4A (hex) G-Wearables Corp. +FCDC4A (base 16) G-Wearables Corp. + 901, S&CTBuilding, No.9 Zhongguancun South Avenue + Beijing Beijing 100081 + CN + +1C-14-B3 (hex) Airwire Technologies +1C14B3 (base 16) Airwire Technologies + 9670 Gateway Drive, Suite 250 + Reno NV 89521 + US + +A4-8C-DB (hex) Lenovo +A48CDB (base 16) Lenovo + 1009 Think Place + Morrisvilee NC 27560 + US + +D8-5D-E2 (hex) Hon Hai Precision Ind. Co.,Ltd. +D85DE2 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +3C-91-2B (hex) Vexata Inc +3C912B (base 16) Vexata Inc + 1735 Technology Dr Suite 520 + San Jose CA 95110 + US + +34-6C-0F (hex) Pramod Telecom Pvt. Ltd +346C0F (base 16) Pramod Telecom Pvt. Ltd + Plot No. 6-B, Malviya Nagar, + Lucknow Uttar Pradesh 226004 + IN + +BC-14-85 (hex) Samsung Electronics Co.,Ltd +BC1485 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +9C-6C-15 (hex) Microsoft Corporation +9C6C15 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +44-5E-CD (hex) Razer Inc +445ECD (base 16) Razer Inc + 2035 Corte Del Nogal + Carlsbad CA 92011 + US + +4C-A9-28 (hex) Insensi +4CA928 (base 16) Insensi + 2025 Broadway, 2CD + New York City New York 10023 + US + +E8-44-7E (hex) Bitdefender SRL +E8447E (base 16) Bitdefender SRL + 24 Delea Veche St. + Bucharest Romania 024102 + RO + +C0-33-5E (hex) Microsoft +C0335E (base 16) Microsoft + 1 Microsoft Way + Redmond Washington 98052 + US + +B0-E0-3C (hex) TCT mobile ltd +B0E03C (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +B0-49-5F (hex) OMRON HEALTHCARE Co., Ltd. +B0495F (base 16) OMRON HEALTHCARE Co., Ltd. + 53, Kunotsubo, Terado-cho + Muko Kyoto 6170002 + JP + +60-F1-89 (hex) Murata Manufacturing Co., Ltd. +60F189 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +74-2E-FC (hex) DirectPacket Research, Inc, +742EFC (base 16) DirectPacket Research, Inc, + 909 Lake Carolyn Parkway + Irving Texas 75039 + US + +84-CF-BF (hex) Fairphone +84CFBF (base 16) Fairphone + Piet Heinkade 181A + Amsterdam North Holland 1019HC + NL + +AC-D1-B8 (hex) Hon Hai Precision Ind. Co.,Ltd. +ACD1B8 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +A0-C2-DE (hex) Costar Video Systems +A0C2DE (base 16) Costar Video Systems + 101 Wrangler, Suite 201 + Coppell Texas 75019 + US + +88-E1-61 (hex) Art Beijing Science and Technology Development Co., Ltd. +88E161 (base 16) Art Beijing Science and Technology Development Co., Ltd. + Room 210,Building 1#, No. 27 Qinghe Longgang Rd., Haidian District, Beijing,100192,China + Beijing Beijing 100192 + CN + +00-A5-09 (hex) WigWag Inc. +00A509 (base 16) WigWag Inc. + 4009 banister lane + austin texas 78704 + US + +74-91-BD (hex) Four systems Co.,Ltd. +7491BD (base 16) Four systems Co.,Ltd. + 608-608/7 Ramintra Road Kannayao + Bangkok Bangkok 10230 + TH + +F0-FE-6B (hex) Shanghai High-Flying Electronics Technology Co., Ltd +F0FE6B (base 16) Shanghai High-Flying Electronics Technology Co., Ltd + Room 1002 ,#1Building,No.3000 Longdong Avenue,Pudong District,Shanghai,China + shanghai shanghai 201203 + CN + +3C-AE-69 (hex) ESA Elektroschaltanlagen Grimma GmbH +3CAE69 (base 16) ESA Elektroschaltanlagen Grimma GmbH + Broner Ring 30 + Grimma Saxony 04668 + DE + +D4-32-66 (hex) Fike Corporation +D43266 (base 16) Fike Corporation + 704 SW 10th Street + Blue Springs MO 64015 + US + +90-0C-B4 (hex) Alinket Electronic Technology Co., Ltd +900CB4 (base 16) Alinket Electronic Technology Co., Ltd + 412 Guilin Rd. 3F, Xuhui District + Shanghai Shanghai 201235 + CN + +48-C0-93 (hex) Xirrus, Inc. +48C093 (base 16) Xirrus, Inc. + 2101 Corporate Center Dr. + Thousand Oaks CA 91320 + US + +DC-09-14 (hex) Talk-A-Phone Co. +DC0914 (base 16) Talk-A-Phone Co. + 7530 N. Natchez Ave. + Niles IL 60714 + US + +D0-92-9E (hex) Microsoft Corporation +D0929E (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +BC-52-B4 (hex) Nokia +BC52B4 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +94-05-B6 (hex) Liling FullRiver Electronics & Technology Ltd +9405B6 (base 16) Liling FullRiver Electronics & Technology Ltd + FullRiver Industrial Area Economic Development Zone + HuNan Province 412200 + CN + +00-F3-DB (hex) WOO Sports +00F3DB (base 16) WOO Sports + 11 Elkins St. + BOSTON Massachusetts 02127 + US + +78-31-2B (hex) zte corporation +78312B (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +C8-1B-6B (hex) Innova Security +C81B6B (base 16) Innova Security + Av. General Ataliba Leonel, 1205 + Sao Paulo Sao Paulo 02033000 + BR + +34-38-AF (hex) Inlab Software GmbH +3438AF (base 16) Inlab Software GmbH + Josef-Wuerth-Str. 3 + Gruenwald Bavaria 82031 + DE + +B4-A8-28 (hex) Shenzhen Concox Information Technology Co., Ltd +B4A828 (base 16) Shenzhen Concox Information Technology Co., Ltd + Floor 4th, Building B, Gaoxinqi Industrial Park, Liuxian 1st Road, district 67, Bao’an, Shenzhen, Guangdong,China + Shenzhen Guangdong 518102 + CN + +00-A2-F5 (hex) Guangzhou Yuanyun Network Technology Co.,Ltd +00A2F5 (base 16) Guangzhou Yuanyun Network Technology Co.,Ltd + 31/F,183 TianHe Bei Rd, Metro Plz + GuangZhou GuangDong 510630 + CN + +10-08-B1 (hex) Hon Hai Precision Ind. Co.,Ltd. +1008B1 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +E4-8C-0F (hex) Discovery Insure +E48C0F (base 16) Discovery Insure + 3 Alice lane + Sandton Gauteng 2196 + ZA + +E4-23-54 (hex) SHENZHEN FUZHI SOFTWARE TECHNOLOGY CO.,LTD +E42354 (base 16) SHENZHEN FUZHI SOFTWARE TECHNOLOGY CO.,LTD + 4/F,Fuxing Bldg,Binlang Road,Futian Free Trade Zone,SHENZHEN.CHINA + SHENZHEN Guang Dong 518038 + CN + +94-BF-95 (hex) Shenzhen Coship Electronics Co., Ltd +94BF95 (base 16) Shenzhen Coship Electronics Co., Ltd + Rainbow Bldg., North, Hi-Tech Industrial Park + Shenzhen Guangdong 518057 + CN + +44-CE-7D (hex) SFR +44CE7D (base 16) SFR + 5 RUE NOEL PONS + NANTERRE 92000 + FR + +34-4D-EA (hex) zte corporation +344DEA (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +4C-16-F1 (hex) zte corporation +4C16F1 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +10-FA-CE (hex) Reacheng Communication Technology Co.,Ltd +10FACE (base 16) Reacheng Communication Technology Co.,Ltd + Building No.5-401, + Pu Dong New District, Shanghai 201203 + CN + +94-70-D2 (hex) WINFIRM TECHNOLOGY +9470D2 (base 16) WINFIRM TECHNOLOGY + 2-1015 Lotte IT Castle + Seoul 153-768 + KR + +A4-4A-D3 (hex) ST Electronics(Shanghai) Co.,Ltd +A44AD3 (base 16) ST Electronics(Shanghai) Co.,Ltd + Floors 1&3, No.6 Building, No.1151 Lianxi Road + Shanghai Shanghai 201204 + CN + +7C-B1-77 (hex) Satelco AG +7CB177 (base 16) Satelco AG + Seestrasse 241 + Au / Waedenswil ZH 8804 + CH + +CC-30-80 (hex) VAIO Corporation +CC3080 (base 16) VAIO Corporation + 5432 Toyoshina + Azumino Nagano 399-8282 + JP + +58-7B-E9 (hex) AirPro Technology India Pvt. Ltd +587BE9 (base 16) AirPro Technology India Pvt. Ltd + D30, Gautam Marg, + Jaipur Rajasthan 302018 + IN + +8C-18-D9 (hex) Shenzhen RF Technology Co., Ltd +8C18D9 (base 16) Shenzhen RF Technology Co., Ltd + 5/F,Building 4,Baokun Science and Technology Industial Park + Baoan Guangdong 518100 + CN + +C4-BD-6A (hex) SKF GmbH +C4BD6A (base 16) SKF GmbH + Gunnar-Wester-Strasse 12 + Schweinfurt DE DE-97421 + DE + +C4-01-CE (hex) PRESITION (2000) CO., LTD. +C401CE (base 16) PRESITION (2000) CO., LTD. + 42/6 Moo6 + Muang Samutsakorn 74000 + TH + +18-71-17 (hex) eta plus electronic gmbh +187117 (base 16) eta plus electronic gmbh + Lauterstr. 29 + Nuertingen BW 72622 + DE + +EC-0E-C4 (hex) Hon Hai Precision Ind. Co.,Ltd. +EC0EC4 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +30-FA-B7 (hex) Tunai Creative +30FAB7 (base 16) Tunai Creative + 12F, No.221, Sec.4, Zongxiao E. Rd, Taipei 106, Taiwan + TAIPEI TAIPEI 10690 + TW + +08-09-B6 (hex) Masimo Corp +0809B6 (base 16) Masimo Corp + 40 Parker + Irvine CA 92618 + US + +4C-F5-A0 (hex) Scalable Network Technologies Inc +4CF5A0 (base 16) Scalable Network Technologies Inc + 600 Corporate Pointe + Culver City CA 90230 + US + +D8-FB-11 (hex) AXACORE +D8FB11 (base 16) AXACORE + 2468 HISTORIC DECATUR RD + SAN DIEGO CA 92106 + US + +4C-E9-33 (hex) RailComm, LLC +4CE933 (base 16) RailComm, LLC + 1387 Fairport Road + Fairport New York 14450 + US + +CC-E1-7F (hex) Juniper Networks +CCE17F (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +E4-C6-2B (hex) Airware +E4C62B (base 16) Airware + 1045 Bryant St. + San Francisco California 94103 + US + +EC-1D-7F (hex) zte corporation +EC1D7F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +AC-38-70 (hex) Lenovo Mobile Communication Technology Ltd. +AC3870 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999, Qishan North 2nd Road, Information & Optoelectronics Park, + Xiamen Fujian 361006 + + +4C-BC-42 (hex) Shenzhen Hangsheng Electronics Co.,Ltd. +4CBC42 (base 16) Shenzhen Hangsheng Electronics Co.,Ltd. + Hangsheng Industrial Area, Fuyuan 1st Road,Heping Village, Fuyong Town,Baoan District + Shenzhen City Guangdong 518103 + CN + +70-F1-96 (hex) Actiontec Electronics, Inc +70F196 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +18-82-19 (hex) Alibaba Cloud Computing Ltd. +188219 (base 16) Alibaba Cloud Computing Ltd. + Yuhang District of Hangzhou Wenyi Road, Building 1, No. 969 Xixi Park, Zhejiang Province + Hangzhou Zhejiang 310000 + CN + +28-A5-EE (hex) Shenzhen SDGI CATV Co., Ltd +28A5EE (base 16) Shenzhen SDGI CATV Co., Ltd + 2/F, NO, 3, QIONGYU ROAD, + shenzhen Guangdong province 518057 + CN + +D0-A0-D6 (hex) Chengdu TD Tech Ltd. +D0A0D6 (base 16) Chengdu TD Tech Ltd. + 3-5F,Building 3, No.219 Tian Hua Road 2, Software Park C,High-Tech Zone + Chengdu Sichuan 610041 + CN + +EC-B9-07 (hex) CloudGenix Inc +ECB907 (base 16) CloudGenix Inc + 2933 Bunker Hill Lane + Santa Clara CA 95054 + US + +F4-28-33 (hex) MMPC Inc. +F42833 (base 16) MMPC Inc. + #F313, KAIST-ICC, 193 Munjiro Yuseong-gu + Daejeon Daejeon 305-732 + KR + +0C-8C-8F (hex) Kamo Technology Limited +0C8C8F (base 16) Kamo Technology Limited + Room 1502, 15/F., Yue Xiu Building, + Wanchai Hong Kong 160-174 + CN + +A4-A4-D3 (hex) Bluebank Communication Technology Co.Ltd +A4A4D3 (base 16) Bluebank Communication Technology Co.Ltd + No.13-2.Jiang Ying Road, + Chongqing 401336 + CN + +A8-32-9A (hex) Digicom Futuristic Technologies Ltd. +A8329A (base 16) Digicom Futuristic Technologies Ltd. + 406 Mirror Tower, Modi Road, TST + 000086 + HK + +F4-D0-32 (hex) Yunnan Ideal Information&Technology.,Ltd +F4D032 (base 16) Yunnan Ideal Information&Technology.,Ltd + The 1st Floor, Building Four ,JingdianMingju,Haiyuanzhong road, High Tech Development Zone,Kunming,YunnanP.R.China + Kunming Yunnan 650106 + CN + +60-02-92 (hex) PEGATRON CORPORATION +600292 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +B4-B8-59 (hex) Texa Spa +B4B859 (base 16) Texa Spa + Via I Maggio, 9 + Monastier di Treviso Treviso 31050 + IT + +5C-F9-F0 (hex) Atomos Engineering P/L +5CF9F0 (base 16) Atomos Engineering P/L + 36 Park St + South Melbourne Victoria 3205 + AU + +70-2D-D1 (hex) Newings Communication CO., LTD. +702DD1 (base 16) Newings Communication CO., LTD. + 12F, Block 1, NO 7866, Humin Rd, Minhang District, Shanghai, China + Shanghai Shanghai 200000 + CN + +14-75-90 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +147590 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +50-BD-5F (hex) TP-LINK TECHNOLOGIES CO.,LTD. +50BD5F (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +98-7E-46 (hex) Emizon Networks Limited +987E46 (base 16) Emizon Networks Limited + 1 Allerton Road + Rugby Warwickshire CV23 0PA + GB + +3C-46-D8 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +3C46D8 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +4C-83-DE (hex) Cisco SPVTG +4C83DE (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +A8-13-74 (hex) Panasonic Corporation AVC Networks Company +A81374 (base 16) Panasonic Corporation AVC Networks Company + 1-15 Matsuo cho + Kadoma city Osaka 571-8504 + JP + +08-3D-88 (hex) Samsung Electronics Co.,Ltd +083D88 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +BC-4E-5D (hex) ZhongMiao Technology Co., Ltd. +BC4E5D (base 16) ZhongMiao Technology Co., Ltd. + NO.2009 Lihu Avenue, WuxiStudioA-A3 + Wuxi Jiangsu 214000 + CN + +3C-18-9F (hex) Nokia Corporation +3C189F (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +7C-6A-C3 (hex) GatesAir, Inc +7C6AC3 (base 16) GatesAir, Inc + 5300 Kings Island Drive + Mason Ohio 45040 + US + +5C-5B-C2 (hex) YIK Corporation +5C5BC2 (base 16) YIK Corporation + B-4F,Pangyo Silicon Park 613 + Seongnam-si Gyeonggi-do 463-400 + KR + +30-59-5B (hex) streamnow AG +30595B (base 16) streamnow AG + Brandstrasse 33 + Schlieren Zürich 8952 + CH + +84-85-0A (hex) Hella Sonnen- und Wetterschutztechnik GmbH +84850A (base 16) Hella Sonnen- und Wetterschutztechnik GmbH + Abfaltersbach 125 + Abfaltersbach Tirol 9913 + AT + +08-CD-9B (hex) samtec automotive electronics & software GmbH +08CD9B (base 16) samtec automotive electronics & software GmbH + Saarstrasse 27 + Filderstadt Baden-Wuerttemberg 70794 + DE + +28-E6-E9 (hex) SIS Sat Internet Services GmbH +28E6E9 (base 16) SIS Sat Internet Services GmbH + Justus-von-Liebig Str. 26 + Neustadt Niedersachsen 31535 + DE + +F4-FD-2B (hex) ZOYI Company +F4FD2B (base 16) ZOYI Company + 827-66 Yeoksam 1-dong, Second Floor + Seoul Korea 135-935 + KR + +F4-F6-46 (hex) Dediprog Technology Co. Ltd. +F4F646 (base 16) Dediprog Technology Co. Ltd. + 4F,No.7,Lane 143, Xinming Rd., + Taipei 114 + TW + +30-0D-2A (hex) Zhejiang Wellcom Technology Co.,Ltd. +300D2A (base 16) Zhejiang Wellcom Technology Co.,Ltd. + Liuhe Road,Binjiang District , Hangzhou + Hangzhou Zhejiang 310012 + + +04-5C-8E (hex) gosund GROUP CO.,LTD +045C8E (base 16) gosund GROUP CO.,LTD + 11/F., FRONT BLOCK, HANG LOK BUILDING + SHEUNG WAN, HK 999077 + HK + +7C-C4-EF (hex) Devialet +7CC4EF (base 16) Devialet + 126, rue Réaumur + Paris Paris 75002 + FR + +D8-5D-FB (hex) Private +D85DFB (base 16) Private + +DC-F1-10 (hex) Nokia Corporation +DCF110 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +60-8F-5C (hex) Samsung Electronics Co.,Ltd +608F5C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +DC-38-E1 (hex) Juniper Networks +DC38E1 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +90-8C-63 (hex) GZ Weedong Networks Technology Co. , Ltd +908C63 (base 16) GZ Weedong Networks Technology Co. , Ltd + 38th Floor,Ren Feng Building + Guangzhou Guangdong 510620 + CN + +E8-EF-89 (hex) OPMEX Tech. +E8EF89 (base 16) OPMEX Tech. + 18F GDC Building, 9 Gaoxin Central Avenue 3rd, Nanshan District + Shenzhen Guangdong 518000 + CN + +10-92-66 (hex) Samsung Electronics Co.,Ltd +109266 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +EC-2E-4E (hex) HITACHI-LG DATA STORAGE INC +EC2E4E (base 16) HITACHI-LG DATA STORAGE INC + 4F, MSC CENTER BLDG., 22-23 KAIGAN 3-CHOME, MINATO-KU, + TOKYO TOKYO 108-0022 + JP + +D4-67-61 (hex) United Gulf Gate Co. +D46761 (base 16) United Gulf Gate Co. + XonTel, Borj ALadel Tower, Fahad Al-Salem St Fl 21 + Kuwait 0000 + KW + +34-81-C4 (hex) AVM GmbH +3481C4 (base 16) AVM GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +98-37-13 (hex) PT.Navicom Indonesia +983713 (base 16) PT.Navicom Indonesia + Perkantoran Citragrand Blok CW7 no 10 + Bekasi Jawa Barat 17435 + ID + +A4-7E-39 (hex) zte corporation +A47E39 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +CC-B6-91 (hex) NECMagnusCommunications +CCB691 (base 16) NECMagnusCommunications + 4-28 MITA 1Chome + Minato-ku Tokyo 108-0073 + JP + +40-16-7E (hex) ASUSTek COMPUTER INC. +40167E (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +F8-4A-73 (hex) EUMTECH CO., LTD +F84A73 (base 16) EUMTECH CO., LTD + Room 1201, 115, Dongdeok-ro + Daegu Daegu 700-719 + KR + +14-2B-D6 (hex) Guangdong Appscomm Co.,Ltd +142BD6 (base 16) Guangdong Appscomm Co.,Ltd + Rm 903, Block C3, Chuangxin Building, No.182, + Guangzhou Guangdong 510663 + CN + +FC-C2-DE (hex) Murata Manufacturing Co., Ltd. +FCC2DE (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +98-34-9D (hex) Krauss Maffei Technologies GmbH +98349D (base 16) Krauss Maffei Technologies GmbH + Krauss-Mafffei-Str. 2 + Munich 80997 + DE + +88-0F-B6 (hex) Jabil Circuits India Pvt Ltd,-EHTP unit +880FB6 (base 16) Jabil Circuits India Pvt Ltd,-EHTP unit + B-26, MIDC, Ranjangaon, Tal.Shirur + Pune Maharashtra 412220 + IN + +B4-66-98 (hex) Zealabs srl +B46698 (base 16) Zealabs srl + via Monte Grappa, 25 + Lancenigo di Villorba Italy 31020 + IT + +68-7C-C8 (hex) Measurement Systems S. de R.L. +687CC8 (base 16) Measurement Systems S. de R.L. + 45999 Regal Plaza + Sterling VA 20165 + US + +74-F8-5D (hex) Berkeley Nucleonics Corp +74F85D (base 16) Berkeley Nucleonics Corp + 2955 Kerner Blvd #D + San Rafael California 94901 + US + +B0-61-C7 (hex) Ericsson-LG Enterprise +B061C7 (base 16) Ericsson-LG Enterprise + 77, Heungan-daro 81beon-gil, + Anyang Gyeonggi 431-749 + KR + +00-92-FA (hex) SHENZHEN WISKY TECHNOLOGY CO.,LTD +0092FA (base 16) SHENZHEN WISKY TECHNOLOGY CO.,LTD + 5/F W2-A,Hight-tech Park South 1 Road,Nanshan District,Shenzhen,Guangdong,China + Shenzhen Guangdong 518057 + CN + +4C-7F-62 (hex) Nokia Corporation +4C7F62 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +10-0F-18 (hex) Fu Gang Electronic(KunShan)CO.,LTD +100F18 (base 16) Fu Gang Electronic(KunShan)CO.,LTD + No.6 Zheng Wei West Road, Jin Xi Town, Kun Shan City, Jiang Su Province, China + Jiang Su 215324 + CN + +D0-C7-C0 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +D0C7C0 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +44-11-C2 (hex) Telegartner Karl Gartner GmbH +4411C2 (base 16) Telegartner Karl Gartner GmbH + Lerchenstr. 35 + Steinenbronn Baden-Wurttemberg 71144 + DE + +80-59-FD (hex) Noviga +8059FD (base 16) Noviga + Lefortovskaya nab., 1 + Moscow - 105005 + RU + +40-01-07 (hex) Arista Corp +400107 (base 16) Arista Corp + 40675 Encyclopedia Circle + Fremont CA 94538 + US + +30-C7-50 (hex) MIC Technology Group +30C750 (base 16) MIC Technology Group + No. 6 Gaoxin 3 road + Xi'an Shaanxi 710075 + CN + +18-CC-23 (hex) Philio Technology Corporation +18CC23 (base 16) Philio Technology Corporation + 8F., No.653-2, Zhongzheng Rd + New Taipei 242 + TW + +40-78-75 (hex) IMBEL - Industria de Material Belico do Brasil +407875 (base 16) IMBEL - Industria de Material Belico do Brasil + Rua Monsenhor Manoel Gomes, 520 + Rio de Janeiro RJ 20931-670 + BR + +D8-81-CE (hex) AHN INC. +D881CE (base 16) AHN INC. + 1006,Halla sigma valley, 53, Gasandigital 2-Ro + Seoul 153 706 + KR + +28-C8-25 (hex) DellKing Industrial Co., Ltd +28C825 (base 16) DellKing Industrial Co., Ltd + 2F,Building D,Zhongxing Science Park, No 3,Ganli 2nd Road,Gankeng Community + Shenzhen GuangDong 518112 + CN + +80-61-8F (hex) Shenzhen sangfei consumer communications co.,ltd +80618F (base 16) Shenzhen sangfei consumer communications co.,ltd + 11 science and technology road,shenzhen hi-tech industrial park nanshan district,shenzhen 518057,PRC + ShenZhen China/GuangDong 518057 + CN + +D8-2A-15 (hex) Leitner SpA +D82A15 (base 16) Leitner SpA + Via Brennero 34 + Vipiteno Bolzano 39049 + IT + +44-7E-76 (hex) Trek Technology (S) Pte Ltd +447E76 (base 16) Trek Technology (S) Pte Ltd + 30 Loyang Way #07-15 + Singapore Singapore 508769 + SG + +B0-EC-8F (hex) GMX SAS +B0EC8F (base 16) GMX SAS + 32 Rue Brancion + PARIS 75015 + FR + +28-DE-F6 (hex) bioMerieux Inc. +28DEF6 (base 16) bioMerieux Inc. + 595 Anglum Road + Hazelwood MO 63042 + US + +58-05-28 (hex) LABRIS NETWORKS +580528 (base 16) LABRIS NETWORKS + Silikon Blok 1 NK 24 Teknokent + ANKARA AN 06540 + TR + +E0-D3-1A (hex) EQUES Technology Co., Limited +E0D31A (base 16) EQUES Technology Co., Limited + Room 301, Building 1, No.168 Jixin Road, + Shanghai 201199 + CN + +98-77-70 (hex) Pep Digital Technology (Guangzhou) Co., Ltd +987770 (base 16) Pep Digital Technology (Guangzhou) Co., Ltd + 23F, Yinhui Building, No.117 Longyi Road, + Guangzhou Guangdong Province 510635 + CN + +68-D2-47 (hex) Portalis LC +68D247 (base 16) Portalis LC + 204 Fort Union Blvd. Ste. 202 + Midvale UT 84047 + US + +50-B6-95 (hex) Micropoint Biotechnologies,Inc. +50B695 (base 16) Micropoint Biotechnologies,Inc. + 6F, No.3, Industry 5 Road, Shekou + Shenzhen Guangdong 518067 + CN + +B4-43-0D (hex) Broadlink Pty Ltd +B4430D (base 16) Broadlink Pty Ltd + room 1201, No. 588 jiangnan Rd, + Hangzhou Zhejiang province 310052 + CN + +A0-65-18 (hex) VNPT TECHNOLOGY +A06518 (base 16) VNPT TECHNOLOGY + HoaLac Hi-Tech Park + HANOI 10000 + VN + +7C-8D-91 (hex) Shanghai Hongzhuo Information Technology co.,LTD +7C8D91 (base 16) Shanghai Hongzhuo Information Technology co.,LTD + Room.161,Building 5,No.311 Jingao RD + Pudong Shanghai 200136 + CN + +74-8F-1B (hex) MasterImage 3D +748F1B (base 16) MasterImage 3D + 131, Gasan Digital 1-ro, Geumcheon-gu + Seoul 153-803 + KR + +08-3F-76 (hex) Intellian Technologies, Inc. +083F76 (base 16) Intellian Technologies, Inc. + 348-5 Chungho-Ri Jinwi-Myeon + Gyeonggi-Do 451-862 + KR + +CC-89-FD (hex) Nokia Corporation +CC89FD (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +34-46-6F (hex) HiTEM Engineering +34466F (base 16) HiTEM Engineering + 7420 Carroll Road + San Diego CA 92121 + US + +38-6C-9B (hex) Ivy Biomedical +386C9B (base 16) Ivy Biomedical + 11 Business Park Drive + Branford Connecticut 06405 + US + +B4-2C-92 (hex) Zhejiang Weirong Electronic Co., Ltd +B42C92 (base 16) Zhejiang Weirong Electronic Co., Ltd + North of South Tanghe Road, Lingxi Town, + Wenzhou City Zhejiang Province 325800 + CN + +A0-77-71 (hex) Vialis BV +A07771 (base 16) Vialis BV + Loodsboot 15 + HOUTEN Utrecht 3991 CJ + US + +10-DD-F4 (hex) Maxway Electronics CO.,LTD +10DDF4 (base 16) Maxway Electronics CO.,LTD + 2F Building 4,A Section,3rd Industrial zone,Tangtou + Shenzhen Guangdong 518018 + CN + +5C-E7-BF (hex) New Singularity International Technical Development Co.,Ltd +5CE7BF (base 16) New Singularity International Technical Development Co.,Ltd + 8F,NorthStar-Ultrapower Tower, No.13 Beiyuan Road, Chaoyang District, Beijing, China + Beijing Beijing 100107 + CN + +6C-64-1A (hex) Penguin Computing +6C641A (base 16) Penguin Computing + 45800 Northport Loop West + Fremont CA 94538 + US + +50-A0-54 (hex) Actineon +50A054 (base 16) Actineon + 47751 Fremont Blvd + Fremont California 94538 + US + +B4-85-47 (hex) Amptown System Company GmbH +B48547 (base 16) Amptown System Company GmbH + Wandsbeker Strasse 26 + Hamburg Hamburg 22179 + DE + +50-56-A8 (hex) Jolla Ltd +5056A8 (base 16) Jolla Ltd + Itaemerenkatu 11-13 + Helsinki 00180 + US + +E8-E7-70 (hex) Warp9 Tech Design, Inc. +E8E770 (base 16) Warp9 Tech Design, Inc. + 3650 Pheasant Run N.E. + Blaine MN 55449 + US + +60-96-20 (hex) Private +609620 (base 16) Private + +C0-F9-91 (hex) GME Standard Communications P/L +C0F991 (base 16) GME Standard Communications P/L + 17 Gibbon Rd. + Winston Hills New South Wales 2153 + AU + +D8-7C-DD (hex) SANIX INCORPORATED +D87CDD (base 16) SANIX INCORPORATED + Creation Core Fukuoka 212, 3-2-16 Kamikoga, + Chikushino-shi Fukuoka 818-0041 + JP + +70-7C-18 (hex) ADATA Technology Co., Ltd +707C18 (base 16) ADATA Technology Co., Ltd + 2F, No.258, Lian Cheng Rd. + New Taipei City 23553 + TW + +14-F2-8E (hex) ShenYang ZhongKe-Allwin Technology Co.LTD +14F28E (base 16) ShenYang ZhongKe-Allwin Technology Co.LTD + No.6, Gaoge Road, + ShenYang Liaoning 110179 + CN + +BC-14-EF (hex) ITON Technology Limited +BC14EF (base 16) ITON Technology Limited + Room 1302,A ablock, Building 4 + ShenZhen GuangDong Pronvice 518000 + CN + +08-03-71 (hex) KRG CORPORATE +080371 (base 16) KRG CORPORATE + 41 rue Perier + Montrouge 92120 + FR + +20-0E-95 (hex) IEC – TC9 WG43 +200E95 (base 16) IEC – TC9 WG43 + 3, rue de Varembé + Geneva GE 1211 + CH + +C8-F6-8D (hex) S.E.TECHNOLOGIES LIMITED +C8F68D (base 16) S.E.TECHNOLOGIES LIMITED + #303 Shiodome building Level3 + Minato-ku Tokyo 105-0022 + JP + +3C-D4-D6 (hex) WirelessWERX, Inc +3CD4D6 (base 16) WirelessWERX, Inc + 22687 Old Canal Rd. + Yorba Linda California 92887 + US + +0C-12-62 (hex) zte corporation +0C1262 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +78-EC-74 (hex) Kyland-USA +78EC74 (base 16) Kyland-USA + 1107 SE Willow Pl + Blue Springs MO 64014 + US + +98-DA-92 (hex) Vuzix Corporation +98DA92 (base 16) Vuzix Corporation + 2166 Brighton Henrietta Town Line Road + Rochester NY 14623 + US + +38-7B-47 (hex) AKELA, Inc. +387B47 (base 16) AKELA, Inc. + 5551 Ekwill Street, Suite A + Santa Barbara California 93111 + US + +C0-64-C6 (hex) Nokia Corporation +C064C6 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +E4-04-39 (hex) TomTom Software Ltd +E40439 (base 16) TomTom Software Ltd + 20th Floor Euston Tower + London NW1 3AS + GB + +D0-C4-2F (hex) Tamagawa Seiki Co.,Ltd. +D0C42F (base 16) Tamagawa Seiki Co.,Ltd. + 1-3-47 Kitainter Kogyodanchi + Hachinohe city Aomori-Pref. 039-2245 + US + +54-93-59 (hex) SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. +549359 (base 16) SHENZHEN TWOWING TECHNOLOGIES CO.,LTD. + F 4th ,5th , 6th, No.6 Building, + Shenzhen Guangdong 518129 + US + +90-35-6E (hex) Vodafone Omnitel N.V. +90356E (base 16) Vodafone Omnitel N.V. + Via Guglielmo Jervis, 13 + Ivrea Italy / Tourin 10015 + IT + +28-44-30 (hex) GenesisTechnical Systems (UK) Ltd +284430 (base 16) GenesisTechnical Systems (UK) Ltd + Venture Centre + Coventry CV4 7EZ + GB + +5C-11-93 (hex) Seal One AG +5C1193 (base 16) Seal One AG + Berliner Str. 44 + Frankfurt am Main Hessen 60311 + DE + +78-3D-5B (hex) TELNET Redes Inteligentes S.A. +783D5B (base 16) TELNET Redes Inteligentes S.A. + Polígono Industrial Centrovía + La Muela Zaragoza 50198 + ES + +D0-B5-23 (hex) Bestcare Cloucal Corp. +D0B523 (base 16) Bestcare Cloucal Corp. + 4F.,No.106,Sec.1,Xintai 5th Rd., + New Taipei City 22102 + TW + +24-A4-95 (hex) Thales Canada Inc. +24A495 (base 16) Thales Canada Inc. + 105 Moatfield Road + Toronto Ontario M3B 0A4 + CA + +84-76-16 (hex) Addat s.r.o. +847616 (base 16) Addat s.r.o. + U krematoria 24 + Liberec Liberec 46001 + CZ + +DC-05-75 (hex) SIEMENS ENERGY AUTOMATION +DC0575 (base 16) SIEMENS ENERGY AUTOMATION + GOA WORKS ,L-6 , + VERNA GOA 403722 + IN + +E0-97-F2 (hex) Atomax Inc. +E097F2 (base 16) Atomax Inc. + 8F-1, No.300, Sec.1, Nei-hu Rd. + Taipei 114 + TW + +70-30-5E (hex) Nanjing Zhongke Menglian Information Technology Co.,LTD +70305E (base 16) Nanjing Zhongke Menglian Information Technology Co.,LTD + 3rd Floor,Building A,Area 3 + Nanjing Jiangsu 210042 + CN + +C0-98-E5 (hex) University of Michigan +C098E5 (base 16) University of Michigan + 4808 Beyster Bldg, + Ann Arbor Michigan 48109 + US + +50-E1-4A (hex) Private +50E14A (base 16) Private + +70-8D-09 (hex) Nokia Corporation +708D09 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +98-FB-12 (hex) Grand Electronics (HK) Ltd +98FB12 (base 16) Grand Electronics (HK) Ltd + Flat/Room 1120, 11/F Beverley Commercial Centre + 999077 + HK + +3C-10-40 (hex) daesung network +3C1040 (base 16) daesung network + #209 e-space Bldg,Guro-dong,Guro-gu + Seoul 152-789 + KR + +44-3C-9C (hex) Pintsch Tiefenbach GmbH +443C9C (base 16) Pintsch Tiefenbach GmbH + Beisenbruchstrasse 10 + Sprockhoevel 45549 + DE + +28-FC-51 (hex) The Electric Controller and Manufacturing Co., LLC +28FC51 (base 16) The Electric Controller and Manufacturing Co., LLC + PO Box 468 + Saint Matthews SC 29135 + US + +40-74-96 (hex) aFUN TECHNOLOGY INC. +407496 (base 16) aFUN TECHNOLOGY INC. + 2F.,No.3,Lane29,HuLu ST.,Shihlin District, + Taipei 11165 + TW + +70-1D-7F (hex) Comtech Technology Co., Ltd. +701D7F (base 16) Comtech Technology Co., Ltd. + 2F, No. 42, Sec. 3 Chung Yang Rd. + New Taipei City 23673 + TW + +70-59-86 (hex) OOO TTV +705986 (base 16) OOO TTV + No. 75, Okulov Street, Building 8 + Perm 614068 + RU + +84-4F-03 (hex) Ablelink Electronics Ltd +844F03 (base 16) Ablelink Electronics Ltd + Flat 1602,16/F Kodak House 2 39 Healthy Street East, + + CN + +90-67-17 (hex) Alphion India Private Limited +906717 (base 16) Alphion India Private Limited + 405 Windfall, Sahar Plaza + Mumbai Maharashtra 400059 + IN + +60-64-A1 (hex) RADiflow Ltd. +6064A1 (base 16) RADiflow Ltd. + 31 Habarzel St. + Tel Aviv 6971045 + IL + +58-B9-61 (hex) SOLEM Electronique +58B961 (base 16) SOLEM Electronique + ZAE La Plaine + CLAPIERS 34830 + FR + +0C-47-3D (hex) Hitron Technologies. Inc +0C473D (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +8C-CD-A2 (hex) ACTP, Inc. +8CCDA2 (base 16) ACTP, Inc. + 2400 Sand Lake Rd + Orlando FL 32809 + US + +84-26-2B (hex) Nokia +84262B (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +98-6C-F5 (hex) zte corporation +986CF5 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +44-7B-C4 (hex) DualShine Technology(SZ)Co.,Ltd +447BC4 (base 16) DualShine Technology(SZ)Co.,Ltd + No.334-1,LuoTian 3rd Industrial Park, + Shen Zhen Guang Dong 518000 + CN + +9C-03-9E (hex) Beijing Winchannel Software Technology Co., Ltd +9C039E (base 16) Beijing Winchannel Software Technology Co., Ltd + 8F, Block E, Dazhongsi Zhongkun Plaza No. A + Haidian District BEIJING 100089 + CN + +68-0A-D7 (hex) Yancheng Kecheng Optoelectronic Technology Co., Ltd +680AD7 (base 16) Yancheng Kecheng Optoelectronic Technology Co., Ltd + No.1 East Road, Kaifa Avenue, + Yancheng Jiangsu 224007 + CN + +BC-88-93 (hex) VILLBAU Ltd. +BC8893 (base 16) VILLBAU Ltd. + Üllöi ut 611. + Budapest - H-1182 + HU + +70-61-73 (hex) Calantec GmbH +706173 (base 16) Calantec GmbH + Doebelner Str. 4 + Berlin 12627 + DE + +7C-49-B9 (hex) Plexus Manufacturing Sdn Bhd +7C49B9 (base 16) Plexus Manufacturing Sdn Bhd + Plot 87 + Bayan Lepas Penang 11900 + MY + +9C-F8-DB (hex) shenzhen eyunmei technology co,.ltd +9CF8DB (base 16) shenzhen eyunmei technology co,.ltd + 8/F Yiben Building,No.1063 ChaGuang Road,XiLi Town, + Shenzhen Guangdong 518055 + CN + +20-D2-1F (hex) Wincal Technology Corp. +20D21F (base 16) Wincal Technology Corp. + 1028 South Greenwood Ave. + Montebello California 90640 + US + +F8-95-50 (hex) Proton Products Chengdu Ltd +F89550 (base 16) Proton Products Chengdu Ltd + 1st Ring + Chengdu Sichuan 610051 + CN + +58-63-9A (hex) TPL SYSTEMES +58639A (base 16) TPL SYSTEMES + ZAE DU PERIGORD NOIR + SARLAT 24200 + FR + +18-7E-D5 (hex) shenzhen kaism technology Co. Ltd +187ED5 (base 16) shenzhen kaism technology Co. Ltd + 37# chuanglong west road pinghu shenzhen + shenzhen 518111 + CN + +84-1B-38 (hex) Shenzhen Excelsecu Data Technology Co.,Ltd +841B38 (base 16) Shenzhen Excelsecu Data Technology Co.,Ltd + Unit 701-709,7/F,South Block,SDGI Building A, No.2, + Shenzhen Guangdong 518057 + CN + +4C-CB-F5 (hex) zte corporation +4CCBF5 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +44-70-0B (hex) IFFU +44700B (base 16) IFFU + 33, Annyeom-gil 112 beon-gil,jeongnam-myeon + Hwaseong-si Gyeonggi-do 445-968 + US + +54-A5-4B (hex) NSC Communications Siberia Ltd +54A54B (base 16) NSC Communications Siberia Ltd + Ordjonikidze 38 + Novosibirsk 630099 + RU + +BC-2B-6B (hex) Beijing Haier IC Design Co.,Ltd +BC2B6B (base 16) Beijing Haier IC Design Co.,Ltd + Room 205, Tongheng Building, No.4 Huayuan Road, Haidian District + Beijing Beijing 100088 + CN + +98-D3-31 (hex) Shenzhen Bolutek Technology Co.,Ltd. +98D331 (base 16) Shenzhen Bolutek Technology Co.,Ltd. + Building B, District A, Internet industry base, Baoan + Shenzhen Guangdong 518000 + CN + +38-EC-11 (hex) Novatek Microelectronics Corp. +38EC11 (base 16) Novatek Microelectronics Corp. + No.1-2 Innovation Rd I., + Hsinchu 300 + TW + +1C-41-58 (hex) Gemalto M2M GmbH +1C4158 (base 16) Gemalto M2M GmbH + Siemensdamm 50 + Berlin Berlin 13629 + DE + +9C-28-40 (hex) Discovery Technology,LTD.. +9C2840 (base 16) Discovery Technology,LTD.. + 5th floor Building 2,Block A,Internet industrial park, + Shenzhen Guangzhou 518100 + CN + +1C-7B-21 (hex) Sony Mobile Communications Inc +1C7B21 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +E0-AF-4B (hex) Pluribus Networks, Inc. +E0AF4B (base 16) Pluribus Networks, Inc. + 1808 Embarcadero Rd Suite B + Palo Alto CA 94303 + US + +84-0F-45 (hex) Shanghai GMT Digital Technologies Co., Ltd +840F45 (base 16) Shanghai GMT Digital Technologies Co., Ltd + Room 501-505 + Zhangjiang Hi-tech Park Shanghai 201204 + CN + +2C-5F-F3 (hex) Pertronic Industries +2C5FF3 (base 16) Pertronic Industries + 17 Eastern Hutt Road + Wingate 5019 + NZ + +78-49-1D (hex) The Will-Burt Company +78491D (base 16) The Will-Burt Company + 169 S. Main St. + Orrivlle Ohio 44667 + US + +F4-6A-BC (hex) Adonit Corp. Ltd. +F46ABC (base 16) Adonit Corp. Ltd. + 10689 Rm. A, 9F, No.107 Sec.4 Ren-Ai Rd., + Taipei Taipei 10689 + TW + +28-C6-71 (hex) Yota Devices OY +28C671 (base 16) Yota Devices OY + Elektronikkatie 13 + Oulu 90590 + FI + +D8-69-60 (hex) Steinsvik +D86960 (base 16) Steinsvik + Rundhaug 25 + FOERRESFJORDEN Rogaland 5563 + NO + +08-EF-3B (hex) MCS Logic Inc. +08EF3B (base 16) MCS Logic Inc. + 6F. Samho Center B Bldg., 275-6,Yangjae-Dong, Secho-Ku,Seoul + Seoul 137-941 + KR + +E8-EA-DA (hex) Denkovi Assembly Electronics LTD +E8EADA (base 16) Denkovi Assembly Electronics LTD + St. Stambolov str. 21 + Byala Rousse 7100 + BG + +F8-5B-C9 (hex) M-Cube Spa +F85BC9 (base 16) M-Cube Spa + Corso Cavour 2/2d + Trieste 34132 + IT + +7C-B7-7B (hex) Paradigm Electronics Inc +7CB77B (base 16) Paradigm Electronics Inc + 5340 Canotek Rd Unit#4 + Ottawa ON K1J 9C6 + CA + +B0-CE-18 (hex) Zhejiang shenghui lighting co.,Ltd +B0CE18 (base 16) Zhejiang shenghui lighting co.,Ltd + Rm801,1th Xinye Building + cao he jing Develop Zone Shanghai 200233 + CN + +6C-F9-7C (hex) Nanoptix Inc. +6CF97C (base 16) Nanoptix Inc. + 699 Champlain St + Dieppe NB E1A 1P6 + CA + +F8-FF-5F (hex) Shenzhen Communication Technology Co.,Ltd +F8FF5F (base 16) Shenzhen Communication Technology Co.,Ltd + 2F,6 Block, Kupai inforport,No.2 Mengxi Street,(North)High-tech Industrial Park, + Shenzhen Guangdong 518057 + CN + +10-22-79 (hex) ZeroDesktop, Inc. +102279 (base 16) ZeroDesktop, Inc. + 125 University Ave, Suite 150 + Palo Alto California 94301 + US + +7C-1A-FC (hex) Dalian Co-Edifice Video Technology Co., Ltd +7C1AFC (base 16) Dalian Co-Edifice Video Technology Co., Ltd + 23F , Block A , #32 Huoju Road , Hi-Tech Zone + Dalian Liaoning 116023 + CN + +F4-7A-4E (hex) Woojeon&Handan +F47A4E (base 16) Woojeon&Handan + 569-12, Gasan-dong, + Seoul 153-803 + KR + +04-84-8A (hex) 7INOVA TECHNOLOGY LIMITED +04848A (base 16) 7INOVA TECHNOLOGY LIMITED + 3F, A Building, QuanYuanFa Industrial Park, No. 72, GuanLan Rd + LongHua District Shenzhen 518000 + CN + +EC-22-57 (hex) JiangSu NanJing University Electronic Information Technology Co.,Ltd +EC2257 (base 16) JiangSu NanJing University Electronic Information Technology Co.,Ltd + F7,Block 06 + NanJing JiangSu 210000 + CN + +F0-37-A1 (hex) Huike Electronics (SHENZHEN) CO., LTD. +F037A1 (base 16) Huike Electronics (SHENZHEN) CO., LTD. + Huike industrial park,Minying industrial park,Shuitian country,Shiyan,Baoan District + SHENZHEN GUANGDONG 518108 + CN + +70-4C-ED (hex) TMRG, Inc. +704CED (base 16) TMRG, Inc. + 11950 Democracy Drive + Reston VA 20190 + US + +F0-8E-DB (hex) VeloCloud Networks +F08EDB (base 16) VeloCloud Networks + 720 University Ave. + Palo Alto CA 94301 + US + +C0-A3-9E (hex) EarthCam, Inc. +C0A39E (base 16) EarthCam, Inc. + 84 Kennedy Street + Hackensack New Jersey 07601 + US + +10-9A-B9 (hex) Tosibox Oy +109AB9 (base 16) Tosibox Oy + Elektroniikkatie 8 + Oulu 90590 + FI + +14-2D-8B (hex) Incipio Technologies, Inc +142D8B (base 16) Incipio Technologies, Inc + 6001 Oak Canyon + Irvine CA 92618 + US + +68-EE-96 (hex) Cisco SPVTG +68EE96 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +78-D3-8D (hex) HONGKONG YUNLINK TECHNOLOGY LIMITED +78D38D (base 16) HONGKONG YUNLINK TECHNOLOGY LIMITED + 15B 15/F CHEUK NANG PLAZA 250 HENNESSY RD HK + ShenzhenCity Guangdong Province 518103 + US + +DC-AE-04 (hex) CELOXICA Ltd +DCAE04 (base 16) CELOXICA Ltd + 34 Porchester Road + London W2 6ES + GB + +80-05-DF (hex) Montage Technology Group Limited +8005DF (base 16) Montage Technology Group Limited + Rm#A16F, Technolgy Blgd.,Yishan Rd. + Shanghai 200233 + CN + +68-1D-64 (hex) Sunwave Communications Co., Ltd +681D64 (base 16) Sunwave Communications Co., Ltd + 581,huoju Avenue,BinJiang District + Hangzhou Zhejiang Province 310053 + CN + +4C-21-D0 (hex) Sony Mobile Communications Inc +4C21D0 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +90-7A-0A (hex) Gebr. Bode GmbH & Co KG +907A0A (base 16) Gebr. Bode GmbH & Co KG + Ochshaeuser Str. 14 + Kassel 34266 + DE + +A0-C6-EC (hex) ShenZhen ANYK Technology Co.,LTD +A0C6EC (base 16) ShenZhen ANYK Technology Co.,LTD + 5F,12B,ZhongXing Industrial Zone, Venture Road + ShenZhen GuangDong 518054 + CN + +78-E8-B6 (hex) zte corporation +78E8B6 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +10-78-CE (hex) Hanvit SI, Inc. +1078CE (base 16) Hanvit SI, Inc. + #201 Daeheung Building, 265-18 Yangjae-dong + Seoul 137130 + KR + +D8-DA-52 (hex) APATOR S.A. +D8DA52 (base 16) APATOR S.A. + ul Gdanska 4A lok. C4 + Torun Kujawsko-Pomorskie 87-100 + PL + +58-7A-4D (hex) Stonesoft Corporation +587A4D (base 16) Stonesoft Corporation + Italahdenkatu 22A + Helsinki 00210 + FI + +84-E6-29 (hex) Bluwan SA +84E629 (base 16) Bluwan SA + Espace Lumiere, Bat 2 + Chatou 78400 + FR + +C4-7F-51 (hex) Inventek Systems +C47F51 (base 16) Inventek Systems + 2 Republic Road + Billerica Ma 01862 + US + +A8-97-DC (hex) IBM +A897DC (base 16) IBM + 4400 North First Street + San Jose CA 95134 + US + +CC-D2-9B (hex) Shenzhen Bopengfa Elec&Technology CO.,Ltd +CCD29B (base 16) Shenzhen Bopengfa Elec&Technology CO.,Ltd + Bldg56A,3/F,Baotian Rd3,Xixiang Town + shenzhen guangdong 518000 + CN + +A0-9B-BD (hex) Total Aviation Solutions Pty Ltd +A09BBD (base 16) Total Aviation Solutions Pty Ltd + Suite 816A / 3 PARKLAND BVDE + Brisbane QLD 4000 + AU + +D4-0B-B9 (hex) Solid Semecs bv. +D40BB9 (base 16) Solid Semecs bv. + Oostwijk 18 + Uden Noord Brabant 5406 XT + NL + +F4-15-FD (hex) Shanghai Pateo Electronic Equipment Manufacturing Co., Ltd. +F415FD (base 16) Shanghai Pateo Electronic Equipment Manufacturing Co., Ltd. + 20th Floor, Metro Tower + Xuhui District Shanghai 200030 + CN + +70-E0-27 (hex) HONGYU COMMUNICATION TECHNOLOGY LIMITED +70E027 (base 16) HONGYU COMMUNICATION TECHNOLOGY LIMITED + Room4B, East Building 210, + Shen Zhen Guang Dong Province 518040 + CN + +FC-35-E6 (hex) Visteon corp +FC35E6 (base 16) Visteon corp + One Village Center Dr + Belleville MI 48111 + US + +E8-48-1F (hex) Advanced Automotive Antennas +E8481F (base 16) Advanced Automotive Antennas + Pol.Ind Can Mitjans s/n + Viladecavalls Barcelona 08232 + ES + +34-95-DB (hex) Logitec Corporation +3495DB (base 16) Logitec Corporation + 8268 Rokudohara, Misuzu + Ina Nagano + JP + +9C-B7-93 (hex) Creatcomm Technology Inc. +9CB793 (base 16) Creatcomm Technology Inc. + Rm 619, Buld A, Modern Plaza + Kunshan Jiangsu 201203 + CN + +5C-33-5C (hex) Swissphone Telecom AG +5C335C (base 16) Swissphone Telecom AG + Faelmisstrasse 21 + Samstagern Zurich CH-8833 + CH + +04-DF-69 (hex) Car Connectivity Consortium +04DF69 (base 16) Car Connectivity Consortium + 3855 SW 153rd Drive + Beaverton Oregon 97006 + US + +78-DA-B3 (hex) GBO Technology +78DAB3 (base 16) GBO Technology + 1150 Bayhill Dr. Ste. 111 + San Bruno CA 94066 + US + +70-0F-EC (hex) Poindus Systems Corp. +700FEC (base 16) Poindus Systems Corp. + 5F., No. 59, Lane. 77, Xing-Ai Rd., Neihu Dist., + Taipei City 114 + TW + +F0-24-05 (hex) OPUS High Technology Corporation +F02405 (base 16) OPUS High Technology Corporation + 1st Floor, No. 367, Gaocui Road + Hsinchu City 30064 + TW + +D4-10-90 (hex) iNFORM Systems AG +D41090 (base 16) iNFORM Systems AG + Europastrasse 15 + Glattbrugg 8152 + CH + +78-D5-B5 (hex) NAVIELEKTRO KY +78D5B5 (base 16) NAVIELEKTRO KY + HALLIMESTARINKATU 11 + KAARINA FIN-20780 + FI + +E4-7D-5A (hex) Beijing Hanbang Technology Corp. +E47D5A (base 16) Beijing Hanbang Technology Corp. + 4/F,Skirt Building + Haidian District Beijing 100080 + CN + +E4-F7-A1 (hex) Datafox GmbH +E4F7A1 (base 16) Datafox GmbH + Dermbacher Str. 12 - 14 + Geisa Thüringen 36419 + DE + +10-5C-3B (hex) Perma-Pipe, Inc. +105C3B (base 16) Perma-Pipe, Inc. + 7720 Lehigh Ave + Niles IL 60714 + US + +34-9D-90 (hex) Heinzmann GmbH & CO. KG +349D90 (base 16) Heinzmann GmbH & CO. KG + Am Haselbach 1 + Schoenau Baden Wuertemberg 79677 + DE + +D8-62-DB (hex) Eno Inc. +D862DB (base 16) Eno Inc. + 2-3-18, Komagome, Toshima-ku + Tokyo 1700013 + JP + +C4-7D-FE (hex) A.N. Solutions GmbH +C47DFE (base 16) A.N. Solutions GmbH + Am Brauhaus 12 + Dresden Saxony 01099 + DE + +CC-BD-35 (hex) Steinel GmbH +CCBD35 (base 16) Steinel GmbH + Dieselstrasse 80-84 + Herzebrock-Clarholz 33442 + DE + +6C-EC-A1 (hex) SHENZHEN CLOU ELECTRONICS CO. LTD. +6CECA1 (base 16) SHENZHEN CLOU ELECTRONICS CO. LTD. + 5/F, building. T2, Hi-tech Industrial Park + SHENZ GUANGONG 518057 + CN + +B0-38-50 (hex) Nanjing CAS-ZDC IOT SYSTEM CO.,LTD +B03850 (base 16) Nanjing CAS-ZDC IOT SYSTEM CO.,LTD + 699-27 Xuanwu Avenue + Nanjing Jiangsu 210000 + CN + +74-8E-08 (hex) Bestek Corp. +748E08 (base 16) Bestek Corp. + No. 6, Lane 229, Sec. 3, Chang-Xing Rd. + Taoyuan 33852 + TW + +78-F5-E5 (hex) BEGA Gantenbrink-Leuchten KG +78F5E5 (base 16) BEGA Gantenbrink-Leuchten KG + Hennenbusch + Menden NRW 58708 + DE + +8C-3C-07 (hex) Skiva Technologies, Inc. +8C3C07 (base 16) Skiva Technologies, Inc. + 8330 Sterling St + Irving TX 75063 + US + +38-A8-6B (hex) Orga BV +38A86B (base 16) Orga BV + Strickledeweg 13 + Schiedam 3125 AT + NL + +F0-77-65 (hex) Sourcefire, Inc +F07765 (base 16) Sourcefire, Inc + 9780 Patuxent Woods Drive + Columbia Maryland 21046 + US + +14-41-E2 (hex) Monaco Enterprises, Inc. +1441E2 (base 16) Monaco Enterprises, Inc. + 14820 E. Sprague Ave. + Spokane WA 99216 + US + +EC-D0-40 (hex) GEA Farm Technologies GmbH +ECD040 (base 16) GEA Farm Technologies GmbH + Siemensstrasse 25-27 + Boenen Northrhine-Westfalia 59199 + DE + +F8-0D-EA (hex) ZyCast Technology Inc. +F80DEA (base 16) ZyCast Technology Inc. + No.33, Lane 181, Chung Hwa Road, + Hsin Chu 30060 + TW + +B0-88-07 (hex) Strata Worldwide +B08807 (base 16) Strata Worldwide + 8995 Roswell Road + Sandy Springs GA 30350 + US + +24-95-04 (hex) SFR +249504 (base 16) SFR + 40-42 QUAI DU POINT DU JOUR + BOULOGNE BILLANCOURT HAUT DE SEINE 92100 + FR + +F4-58-42 (hex) Boxx TV Ltd +F45842 (base 16) Boxx TV Ltd + Suite 17, Imperial Studios + London SW6 2AG + GB + +10-66-82 (hex) NEC Platforms, Ltd. +106682 (base 16) NEC Platforms, Ltd. + 800 Shimomata + Kakegawa Shizuoka 436-8501 + JP + +24-62-78 (hex) sysmocom - systems for mobile communications GmbH +246278 (base 16) sysmocom - systems for mobile communications GmbH + Alt-Moabit 93 + Berlin 10559 + DE + +F0-84-C9 (hex) zte corporation +F084C9 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +D4-01-6D (hex) TP-LINK TECHNOLOGIES CO.,LTD. +D4016D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +98-5C-93 (hex) SBG Systems SAS +985C93 (base 16) SBG Systems SAS + 3bis, chemin de la Jonchere + Rueil Malmaison Ile de France 92500 + FR + +A0-8A-87 (hex) HuiZhou KaiYue Electronic Co.,Ltd +A08A87 (base 16) HuiZhou KaiYue Electronic Co.,Ltd + 3#,Ruttang 2nd area,Tongcheng Avenue + Huizhou Guangdong 516005 + CN + +28-CD-9C (hex) Shenzhen Dynamax Software Development Co.,Ltd. +28CD9C (base 16) Shenzhen Dynamax Software Development Co.,Ltd. + Room 425-426,Block A,No.30,Hangkong Road + Shenzhen Guangdong 518000 + CN + +C0-C3-B6 (hex) Automatic Systems +C0C3B6 (base 16) Automatic Systems + avenue mercator,5 + Wavre Belgium 1300 + BE + +A0-EB-76 (hex) AirCUVE Inc. +A0EB76 (base 16) AirCUVE Inc. + Guro-gu Digital-ro + Seoul 152-719 + KR + +FC-44-99 (hex) Swarco LEA d.o.o. +FC4499 (base 16) Swarco LEA d.o.o. + Finzgarjeva 1A + Lesce 4248 + SI + +DC-64-7C (hex) C.R.S. iiMotion GmbH +DC647C (base 16) C.R.S. iiMotion GmbH + Hermann-Schwer-Str. 3 + Villingen-Schwenningen 78048 + DE + +14-86-92 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +148692 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +A8-15-4D (hex) TP-LINK TECHNOLOGIES CO.,LTD. +A8154D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +5C-F3-70 (hex) CC&C Technologies, Inc +5CF370 (base 16) CC&C Technologies, Inc + 8F, 150, Chien I Rd. + Chung Ho Taiwan 235 + TW + +A4-E0-E6 (hex) FILIZOLA S.A. PESAGEM E AUTOMACAO +A4E0E6 (base 16) FILIZOLA S.A. PESAGEM E AUTOMACAO + RUA JOAO VENTURA BATISTA, 450 + SAO PAULO 02054-100 + BR + +38-17-66 (hex) PROMZAKAZ LTD. +381766 (base 16) PROMZAKAZ LTD. + Noviy Arbat street, 21 + Moscow 119019 + RU + +18-E8-DD (hex) MODULETEK +18E8DD (base 16) MODULETEK + Unit 4A.4F.B Building. Shenfubao Science and Technology Industrial Park + Shenzhen Guangdong 518038 + CN + +D0-73-D5 (hex) LIFI LABS MANAGEMENT PTY LTD +D073D5 (base 16) LIFI LABS MANAGEMENT PTY LTD + 7 Cubitt St + Richmond Victoria 3121 + AU + +14-94-48 (hex) BLU CASTLE S.A. +149448 (base 16) BLU CASTLE S.A. + 5 RUE BONNEVOIE + LUXEMBOURG L-1260 + US + +48-F9-25 (hex) Maestronic +48F925 (base 16) Maestronic + Futura plaza 2103 + Kwun Tong 88 + HK + +38-67-93 (hex) Asia Optical Co., Inc. +386793 (base 16) Asia Optical Co., Inc. + No. 22-3 South 2nd Road, T.E.P.Z. + Taichung Taiwan 42754 + TW + +0C-82-68 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +0C8268 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +D8-1E-DE (hex) B&W Group Ltd +D81EDE (base 16) B&W Group Ltd + 5070 Francois Cusson + Lachine Quebec H8T1B3 + CA + +24-EA-40 (hex) Helmholz GmbH & Co. KG +24EA40 (base 16) Helmholz GmbH & Co. KG + Hannberger Weg 2 + Grossenseebach BAY 91091 + DE + +D4-29-EA (hex) Zimory GmbH +D429EA (base 16) Zimory GmbH + Revalerstrasse 100 + Berlin Brandenburg 10245 + DE + +34-AD-E4 (hex) Shanghai Chint Power Systems Co., Ltd. +34ADE4 (base 16) Shanghai Chint Power Systems Co., Ltd. + 855 Wenhe Road, Block 4 + 201614 + CN + +3C-94-D5 (hex) Juniper Networks +3C94D5 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +68-83-1A (hex) Pandora Mobility Corporation +68831A (base 16) Pandora Mobility Corporation + 1F., No.33, Fude St + Taoyuan Guishan 333 + TW + +FC-DB-96 (hex) ENERVALLEY CO., LTD +FCDB96 (base 16) ENERVALLEY CO., LTD + 907-101 DIGITAL EMPIRE II + SUWON SI GYEONGGI DO 443 734 + KR + +14-23-D7 (hex) EUTRONIX CO., LTD. +1423D7 (base 16) EUTRONIX CO., LTD. + EUTRONIX BLDG. 4TH FLOOR + ANYANG KYEONGGI 431-804 + US + +DC-6F-08 (hex) Bay Storage Technology +DC6F08 (base 16) Bay Storage Technology + 6200 Stoneridge Mall Road + Pleasanton CA 94588 + US + +90-DA-4E (hex) AVANU +90DA4E (base 16) AVANU + 5205 Prospect Rd + San Jose CA 95129-5034 + US + +28-18-78 (hex) Microsoft Corporation +281878 (base 16) Microsoft Corporation + One Microsoft Way + Redmond Washington 98052-6399 + US + +70-38-B4 (hex) Low Tech Solutions +7038B4 (base 16) Low Tech Solutions + 350 N. Orleans + Chicago IL 60654 + US + +74-5F-00 (hex) Samsung Semiconductor Inc. +745F00 (base 16) Samsung Semiconductor Inc. + 3566 N. 1St Street + San Jose CA 95134 + US + +E0-C3-F3 (hex) zte corporation +E0C3F3 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +5C-20-D0 (hex) Asoni Communication Co., Ltd. +5C20D0 (base 16) Asoni Communication Co., Ltd. + 21F-1, No.97, Sec. 4, Chongsin Rd., Sanchong District + New Taipei City Taiwan 24161 + TW + +AC-A4-30 (hex) Peerless AV +ACA430 (base 16) Peerless AV + 2300 White Oak Circle + Aurora illinios 60502 + US + +84-7A-88 (hex) HTC Corporation +847A88 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +A4-D8-56 (hex) Gimbal, Inc +A4D856 (base 16) Gimbal, Inc + 12526 High Bluff Drive + San Diego Ca 92130 + US + +78-55-17 (hex) SankyuElectronics +785517 (base 16) SankyuElectronics + 2-30-12 + Ohta-ku Tokyo 146-0091 + JP + +B4-7F-5E (hex) Foresight Manufacture (S) Pte Ltd +B47F5E (base 16) Foresight Manufacture (S) Pte Ltd + 1 Sims Lane #04-09 + Singapore 387355 + SG + +A0-FE-91 (hex) AVAT Automation GmbH +A0FE91 (base 16) AVAT Automation GmbH + Derendinger Strasse 40 + Tuebingen 72072 + DE + +74-EC-F1 (hex) Acumen +74ECF1 (base 16) Acumen + 6F, No.207-3, Sec 3, Beisin Rd + Sindian Dist New Taipei City 23143 + US + +58-09-E5 (hex) Kivic Inc. +5809E5 (base 16) Kivic Inc. + 670 Sampyeong-dong, Bundang-gu + Seongnam City 463-400 + KR + +50-4F-94 (hex) Loxone Electronics GmbH +504F94 (base 16) Loxone Electronics GmbH + Falkensteinstraße 6 + Kollerschlag Upper Austria 4154 + AT + +60-B1-85 (hex) ATH system +60B185 (base 16) ATH system + Osady Lezaku 498 + Chrast 53851 + CZ + +BC-62-9F (hex) Telenet Systems P. Ltd. +BC629F (base 16) Telenet Systems P. Ltd. + 2 Mani Bhuvan, Cama Road + Mumbai Maharashtra 400086 + IN + +38-0F-E4 (hex) Dedicated Network Partners Oy +380FE4 (base 16) Dedicated Network Partners Oy + Linnoitustie 6 + Espoo - 02600 + FI + +48-F2-30 (hex) Ubizcore Co.,LTD +48F230 (base 16) Ubizcore Co.,LTD + Kranz Techno #1420, Sangdaewon 1-dong + Seongnam-Si 462-729 + KR + +78-32-4F (hex) Millennium Group, Inc. +78324F (base 16) Millennium Group, Inc. + 16 Tech Circle + Natick MA 01760 + US + +38-43-69 (hex) Patrol Products Consortium LLC +384369 (base 16) Patrol Products Consortium LLC + 1128 Narragansett Blvd. + Cranston RI 02905 + US + +44-18-4F (hex) Fitview +44184F (base 16) Fitview + 5615 Scotts Valley Drive, Suite 110 + Scotts Valley CA 95066 + US + +84-AC-A4 (hex) Beijing Novel Super Digital TV Technology Co., Ltd +84ACA4 (base 16) Beijing Novel Super Digital TV Technology Co., Ltd + 4F Tower B Jingmeng Hightech building + Beijing 100085 + CN + +54-1F-D5 (hex) Advantage Electronics +541FD5 (base 16) Advantage Electronics + PO Box 407 + Greenwood IN 46143 + US + +AC-E9-7F (hex) IoT Tech Limited +ACE97F (base 16) IoT Tech Limited + 20b Lough Road + Lisburn Antrim BT28 2HA + GB + +E8-5A-A7 (hex) LLC Emzior +E85AA7 (base 16) LLC Emzior + Strelna, Svyazi street, 34, Lit A, of. 234 + Saint-Petersburg 198515 + RU + +9C-9C-1D (hex) Starkey Labs Inc. +9C9C1D (base 16) Starkey Labs Inc. + 6600 Washington Ave. S. + Eden Prairie MN 55344 + US + +D0-D6-CC (hex) Wintop +D0D6CC (base 16) Wintop + No. 1301,Xinfei Road + Songjiang District Shanghai 201612 + CN + +58-D0-71 (hex) BW Broadcast +58D071 (base 16) BW Broadcast + Unit 27 IO Centre + Croydon Surrey CR0 4WQ + GB + +1C-52-D6 (hex) FLAT DISPLAY TECHNOLOGY CORPORATION +1C52D6 (base 16) FLAT DISPLAY TECHNOLOGY CORPORATION + No.85, Sec. 1, Fuxing Rd., South Dist + Taichung 402 + TW + +D0-DF-B2 (hex) Genie Networks Limited +D0DFB2 (base 16) Genie Networks Limited + 5F, No.15, Lane 360, Sec., 1, Neihu Road, + Taipei 114 + TW + +38-66-45 (hex) OOSIC Technology CO.,Ltd +386645 (base 16) OOSIC Technology CO.,Ltd + 8F,No 1559, Zuchongzhi Road + Shanghai 201203 + CN + +B8-5A-F7 (hex) Ouya, Inc +B85AF7 (base 16) Ouya, Inc + 11693 San Vicente Blvd + Los Angeles CA 90049 + US + +34-F6-2D (hex) SHARP Corporation +34F62D (base 16) SHARP Corporation + 1 Takumi-cho, Sakai-ku + Sakai City Osaka 590-8522 + JP + +4C-8F-A5 (hex) Jastec +4C8FA5 (base 16) Jastec + Jastec B/D 2F, 92-7 Kumgok-dong, + Boondang-gu, 463-804 + KR + +84-ED-33 (hex) BBMC Co.,Ltd +84ED33 (base 16) BBMC Co.,Ltd + #301, DaerungPostTower 3, 182-4, + Seoul None 152-746 + KR + +E8-2E-24 (hex) Out of the Fog Research LLC +E82E24 (base 16) Out of the Fog Research LLC + 565 Clyde Avenue, Suite 620 + Mountain View CA 94043 + US + +80-FA-5B (hex) CLEVO CO. +80FA5B (base 16) CLEVO CO. + NO. 129, XINGDE ROAD + New TAIPEI CITY 241 + TW + +C0-B3-39 (hex) Comigo Ltd. +C0B339 (base 16) Comigo Ltd. + 15 HaPardes St. + Yarkona 45915 + IL + +20-85-8C (hex) Assa +20858C (base 16) Assa + Gurogu Guro3dong Ace Twintower 2cha 209 + Seoul 152-779 + KR + +60-CD-C5 (hex) Taiwan Carol Electronics., Ltd +60CDC5 (base 16) Taiwan Carol Electronics., Ltd + No.202, Tung Kuang Road + Taichung Taiwan 40151 + TW + +D8-18-2B (hex) Conti Temic Microelectronic GmbH +D8182B (base 16) Conti Temic Microelectronic GmbH + Sieboldstraße 19 + Nuremberg Bavaria 90411 + DE + +80-CF-41 (hex) Lenovo Mobile Communication Technology Ltd. +80CF41 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999,Qishan North 2nd Road,Information&Optoelectronics Park,Torch Hi-tech Industry Development Zone, + Xiamen Fujian 361006 + US + +9C-E1-D6 (hex) Junger Audio-Studiotechnik GmbH +9CE1D6 (base 16) Junger Audio-Studiotechnik GmbH + Justus-von-Liebig-Strasse 7 + 12489 Berlin + US + +48-B9-C2 (hex) Teletics Inc. +48B9C2 (base 16) Teletics Inc. + 103 Edgevalley Close NW + Calgary AB T3A 5E9 + CA + +58-D6-D3 (hex) Dairy Cheq Inc +58D6D3 (base 16) Dairy Cheq Inc + 60 Baffin Place, Unit 5 + Waterloo Ontario N2V 1Z7 + CA + +04-6E-49 (hex) TaiYear Electronic Technology (Suzhou) Co., Ltd +046E49 (base 16) TaiYear Electronic Technology (Suzhou) Co., Ltd + 12-B101 Creative Industrial Park ,No. 328,Xinghu Street ,Suzhou Industrial Park + SuZhou JiangSu 215000 + CN + +2C-3B-FD (hex) Netstor Technology Co., Ltd. +2C3BFD (base 16) Netstor Technology Co., Ltd. + 6F, No. 1, Alley 16, Lane 235, Baoqiao Rd., Xindian District + New Taipei City 23145 + US + +AC-3C-B4 (hex) Nilan A/S +AC3CB4 (base 16) Nilan A/S + Nilanvej 2 + Hedensted Vejle amt 8722 + DK + +B4-9D-B4 (hex) Axion Technologies Inc. +B49DB4 (base 16) Axion Technologies Inc. + 105-1203, 70, Jingeononam-ro + Namyangju Gyeonggi-do 472-859 + KR + +AC-E8-7E (hex) Bytemark Computer Consulting Ltd +ACE87E (base 16) Bytemark Computer Consulting Ltd + Unit 2 + Opus Avenue York YO26 6BL + GB + +80-07-A2 (hex) Esson Technology Inc. +8007A2 (base 16) Esson Technology Inc. + Room A2, 5F Longsheng Commericial Building, + Baoan District ShenZhen 518000 + CN + +C0-A0-E2 (hex) Eden Innovations +C0A0E2 (base 16) Eden Innovations + ZAC + Eguilles PACA 13510 + FR + +08-0F-FA (hex) KSP INC. +080FFA (base 16) KSP INC. + RM 501, 138 Kwangdeokdae-ro + Danwon-gu, Ansan-si Gyeonggi-do 425906 + KR + +E8-AB-FA (hex) Shenzhen Reecam Tech.Ltd. +E8ABFA (base 16) Shenzhen Reecam Tech.Ltd. + Room 03D-1 , North Wing Of 3 rd Floor, Block 1 , Vision Shenzhen Business Park + Nanshan District, Shenzhen Guangdong 518052 + CN + +DC-B0-58 (hex) Bürkert Werke GmbH +DCB058 (base 16) Bürkert Werke GmbH + Christian-Bürkert-Straße 13-17 + Ingelfingen Baden-Württemberg 74653 + DE + +6C-5A-34 (hex) Shenzhen Haitianxiong Electronic Co., Ltd. +6C5A34 (base 16) Shenzhen Haitianxiong Electronic Co., Ltd. + Rm.407, Block A, University-town Business Park, Taoyuan street, Lishan Road + Shenzhen Guangdong 518055 + CN + +90-38-DF (hex) Changzhou Tiannengbo System Co. Ltd. +9038DF (base 16) Changzhou Tiannengbo System Co. Ltd. + #9 East Hehai Road, RM 306 + Changzhou Jiangsu Province 213000 + CN + +18-52-53 (hex) Pixord Corporation +185253 (base 16) Pixord Corporation + 6F, No 12, Innovation 1st Road + Hsinchu 30076 + TW + +68-3B-1E (hex) Countwise LTD +683B1E (base 16) Countwise LTD + 1149 Sawgrass Corporate Parkway + Sunrise Florida 33323 + US + +AC-A2-2C (hex) Baycity Technologies Ltd +ACA22C (base 16) Baycity Technologies Ltd + 10 Nazareth Ave + Christchurch Canterbury 8024 + NZ + +30-32-94 (hex) W-IE-NE-R Plein & Baus GmbH +303294 (base 16) W-IE-NE-R Plein & Baus GmbH + Muellersbaum 20 + Burscheid NRW 51399 + US + +7C-82-2D (hex) Nortec +7C822D (base 16) Nortec + 2740 Fenton Rd + Ottawa ON K1T3T7 + US + +10-FB-F0 (hex) KangSheng LTD. +10FBF0 (base 16) KangSheng LTD. + 2F., No.11, + New Taipei City 24889 + TW + +6C-9A-C9 (hex) Valentine Research, Inc. +6C9AC9 (base 16) Valentine Research, Inc. + 10280 Alliance Rd + Cincinnati OH 45242 + US + +AC-8D-14 (hex) Smartrove Inc +AC8D14 (base 16) Smartrove Inc + 19630 Allendale Ave. + Saratoga CA 95070 + US + +20-91-D9 (hex) I'M SPA +2091D9 (base 16) I'M SPA + VIA BIRON 102/3 + MONTEVIALE VICENZA 36050 + IT + +AC-72-36 (hex) Lexking Technology Co., Ltd. +AC7236 (base 16) Lexking Technology Co., Ltd. + 2F, No. 3, Baoqiang Road, + New Taipei City Taiwan 231111 + TW + +3C-D7-DA (hex) SK Mtek microelectronics(shenzhen)limited +3CD7DA (base 16) SK Mtek microelectronics(shenzhen)limited + 12F, Micro-profit Building,South 6 road + Shenzhen Guangdong 518057 + CN + +04-F8-C2 (hex) Flaircomm Microelectronics, Inc. +04F8C2 (base 16) Flaircomm Microelectronics, Inc. + 7F,Guomai Building,116 East JiangBin Ave + Fuzhou Fujian 350015 + CN + +14-1B-F0 (hex) Intellimedia Systems Ltd +141BF0 (base 16) Intellimedia Systems Ltd + Sandhill Barn + Washington West Sussex RH204TD + GB + +58-87-E2 (hex) Shenzhen Coship Electronics Co., Ltd. +5887E2 (base 16) Shenzhen Coship Electronics Co., Ltd. + Rainbow Bldg., North, Hi-Tech Industrial Park + Shenzhen Guangdong 518057 + CN + +68-69-F2 (hex) ComAp s.r.o. +6869F2 (base 16) ComAp s.r.o. + Kundratka 17 + Prague 18000 + CZ + +B8-5A-FE (hex) Handaer Communication Technology (Beijing) Co., Ltd +B85AFE (base 16) Handaer Communication Technology (Beijing) Co., Ltd + Jiancaicheng West Rd.65,Xisanqi, + Beijing 100096 + CN + +F4-6D-E2 (hex) zte corporation +F46DE2 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +F0-AC-A4 (hex) HBC-radiomatic +F0ACA4 (base 16) HBC-radiomatic + Haller Str. 45-53 + Crailsheim Baden Wurttemberg 74564 + DE + +60-74-8D (hex) Atmaca Elektronik +60748D (base 16) Atmaca Elektronik + Namik Kemal Mahallesi 177, Sokak No:2 + Istanbul Esenyurt 34510 + TR + +B8-B7-D7 (hex) 2GIG Technologies +B8B7D7 (base 16) 2GIG Technologies + 2961 West Maple Loop Drive + Lehi Utah 84043 + US + +80-82-87 (hex) ATCOM Technology Co.Ltd. +808287 (base 16) ATCOM Technology Co.Ltd. + A-2F, #3 , Crown industry buildings + Shenzhen Guang Dong 518040 + US + +28-A1-86 (hex) enblink +28A186 (base 16) enblink + Room 212 Building 105-1 SNU + SEOUL 151-742 + KR + +50-39-55 (hex) Cisco SPVTG +503955 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +78-D1-29 (hex) Vicos +78D129 (base 16) Vicos + Eugenmuellerstrasse 14 + Salzburg Salzburg 5020 + AT + +84-DF-0C (hex) NET2GRID BV +84DF0C (base 16) NET2GRID BV + Krullelaan 28 + Zeist Utrecht 3701 TD + NL + +38-8E-E7 (hex) Fanhattan LLC +388EE7 (base 16) Fanhattan LLC + 489 S El Camino Real + San Mateo CA 94402 + US + +5C-D4-1B (hex) UCZOON Technology Co., LTD +5CD41B (base 16) UCZOON Technology Co., LTD + 9 th Floor,Pan Gu Plaza,No.27 North 4 th Ring, + Beijing Beijing 100029 + CN + +CC-E7-98 (hex) My Social Stuff +CCE798 (base 16) My Social Stuff + Sint-Hubertussyraat 65 + Berchem 2600 + BE + +A0-36-F0 (hex) Comprehensive Power +A036F0 (base 16) Comprehensive Power + 420 Northboro Road Central + Marlborough MA 01752 + US + +18-0C-AC (hex) CANON INC. +180CAC (base 16) CANON INC. + 3-30-2 + Ohta-Ku Tokyo 146-8501 + JP + +78-AB-60 (hex) ABB Australia +78AB60 (base 16) ABB Australia + PMB 88 + Berrimah NT 0828 + AU + +84-82-F4 (hex) Beijing Huasun Unicreate Technology Co., Ltd +8482F4 (base 16) Beijing Huasun Unicreate Technology Co., Ltd + North Region 6th Floor, Tower A, Huizhi Mansion, + Beijing 100085 + CN + +00-DB-1E (hex) Albedo Telecom SL +00DB1E (base 16) Albedo Telecom SL + Joan d'Austria 112 + Barcelona 08018 + ES + +18-86-3A (hex) DIGITAL ART SYSTEM +18863A (base 16) DIGITAL ART SYSTEM + 838 rue de l'Aiguelongue + Montpellier Etat 34090 + FR + +0C-DC-CC (hex) Inala Technologies +0CDCCC (base 16) Inala Technologies + Inala House, 557 15th Road + Midrand Gauteng 1685 + ZA + +98-29-1D (hex) Jaguar de Mexico, SA de CV +98291D (base 16) Jaguar de Mexico, SA de CV + Calle Tabla Grande No.2 + Jilotzongo Estado de Mexico 54570 + MX + +34-AF-2C (hex) Nintendo Co., Ltd. +34AF2C (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +7C-D9-FE (hex) New Cosmos Electric Co., Ltd. +7CD9FE (base 16) New Cosmos Electric Co., Ltd. + 2-5-4 Mitsuyanaka + Osaka Osaka-fu 532-0036 + JP + +E4-90-69 (hex) Rockwell Automation +E49069 (base 16) Rockwell Automation + 1 Allen-Bradley Dr. + Mayfield Heights OH 44124-6118 + US + +CC-C1-04 (hex) Applied Technical Systems +CCC104 (base 16) Applied Technical Systems + P.O. Box 5705 + Shreveport LA 71135 + US + +A4-B1-E9 (hex) Technicolor +A4B1E9 (base 16) Technicolor + Prins Boudewijnlaan 47 + Edegem - Belgium B-2650 + BE + +60-45-5E (hex) Liptel s.r.o. +60455E (base 16) Liptel s.r.o. + Hradna 338 + Liptovsky Hradok 03301 + SK + +D8-06-D1 (hex) Honeywell Fire System (Shanghai) Co,. Ltd. +D806D1 (base 16) Honeywell Fire System (Shanghai) Co,. Ltd. + No. 430, Li Bing Road, Pudong + Shanghai Shanghai 201203 + CN + +64-76-57 (hex) Innovative Security Designs +647657 (base 16) Innovative Security Designs + 18 Technology Drive + Irvine CA 92618 + US + +90-70-25 (hex) Garea Microsys Co.,Ltd. +907025 (base 16) Garea Microsys Co.,Ltd. + 4th Floor, Building 2, Software Park + Suzhou Jiangsu 215163 + CN + +10-D1-DC (hex) INSTAR Deutschland GmbH +10D1DC (base 16) INSTAR Deutschland GmbH + Auf der Hostert 17 + Huenstetten Bechtheim Hessen 65510 + DE + +34-99-6F (hex) VPI Engineering +34996F (base 16) VPI Engineering + 11814 S. Election Rd., Suite 200 + Draper UT 84020 + US + +94-4A-09 (hex) BitWise Controls +944A09 (base 16) BitWise Controls + 98 Inverness Dr East + Englewood CO 80112 + US + +BC-28-D6 (hex) Rowley Associates Limited +BC28D6 (base 16) Rowley Associates Limited + Suite 4B/4C Drake House + Dursley Gloucestershire GL11 4HH + GB + +10-BD-18 (hex) Cisco Systems, Inc +10BD18 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +58-69-F9 (hex) Fusion Transactive Ltd. +5869F9 (base 16) Fusion Transactive Ltd. + PO Box 68281 + Auckland 1145 + NZ + +D4-1E-35 (hex) TOHO Electronics INC. +D41E35 (base 16) TOHO Electronics INC. + 1-13-21 Tanashioda, Chuo-Ku + Sagamihara-City Kanagawa 252-0245 + JP + +4C-72-B9 (hex) PEGATRON CORPORATION +4C72B9 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +2C-ED-EB (hex) Alpheus Digital Company Limited +2CEDEB (base 16) Alpheus Digital Company Limited + Room 2, 23/F Tak King Industrial building + Hong Kong 852 + HK + +0C-D9-96 (hex) Cisco Systems, Inc +0CD996 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +30-F3-3A (hex) +plugg srl +30F33A (base 16) +plugg srl + via giovanni ventura, 5 + Milano MI 20134 + IT + +0C-57-EB (hex) Mueller Systems +0C57EB (base 16) Mueller Systems + 48 Leona Drive, Suite C + Middleboro MA 02346 + US + +74-53-27 (hex) COMMSEN CO., LIMITED +745327 (base 16) COMMSEN CO., LIMITED + 12/F., San Toi Building,139 Connaught Road Central + 999077 + HK + +D0-8C-FF (hex) UPWIS AB +D08CFF (base 16) UPWIS AB + Box 3000 + Uppsala Uppsala 75003 + SE + +68-CE-4E (hex) L-3 Communications Infrared Products +68CE4E (base 16) L-3 Communications Infrared Products + 3414 Herrmann Drive + Garland TX 75043 + US + +68-D1-FD (hex) Shenzhen Trimax Technology Co.,Ltd +68D1FD (base 16) Shenzhen Trimax Technology Co.,Ltd + Room 1016, 10F, Max Smart Commercial Center, + Shenzhen Guangdong 518133 + CN + +9C-06-6E (hex) Hytera Communications Corporation Limited +9C066E (base 16) Hytera Communications Corporation Limited + Hytera Tower, Hi-Tech Industrial Park North, Nanshan District + Shenzhen Guangdong 518057 + US + +3C-EA-FB (hex) NSE AG +3CEAFB (base 16) NSE AG + Bremgarterstrasse 54 + Wohlen AG 5610 + CH + +8C-C7-AA (hex) Radinet Communications Inc. +8CC7AA (base 16) Radinet Communications Inc. + 7F-2, No.229, Fuxing 2nd Rd, Zhubei, 30271 + Hsinchu Taiwan 30271 + US + +40-33-6C (hex) Godrej & Boyce Mfg. co. ltd +40336C (base 16) Godrej & Boyce Mfg. co. ltd + PSS TECH CELL, 2ND FLOOR, PLANT 17, SECURITY SOLUTIONS DIVISION + MUMBAI MAHARASHTRA 400079 + IN + +F8-A0-3D (hex) Dinstar Technologies Co., Ltd. +F8A03D (base 16) Dinstar Technologies Co., Ltd. + Floor 6, Guoxing Building + shenzhen Guangdong 518052 + US + +2C-D4-44 (hex) FUJITSU LIMITED +2CD444 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +BC-81-1F (hex) Ingate Systems +BC811F (base 16) Ingate Systems + Rissneleden 45 + Sundbyberg 17444 + SE + +D8-67-D9 (hex) Cisco Systems, Inc +D867D9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A4-E7-31 (hex) Nokia Corporation +A4E731 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +98-A7-B0 (hex) MCST ZAO +98A7B0 (base 16) MCST ZAO + 35/50, Nizhnyaya Krasnoselskaya St., + Moscow 105666 + RU + +4C-06-8A (hex) Basler Electric Company +4C068A (base 16) Basler Electric Company + 12570 State Route 143 + Highland Illinois 62249 + US + +E8-56-D6 (hex) NCTech Ltd +E856D6 (base 16) NCTech Ltd + 20-22 Braid Road + Edinburgh EH10 6AD + GB + +C0-81-70 (hex) Effigis GeoSolutions +C08170 (base 16) Effigis GeoSolutions + 4101, rue Molson + Montreal Quebec H1Y3L1 + CA + +64-22-16 (hex) Shandong Taixin Electronic co.,Ltd +642216 (base 16) Shandong Taixin Electronic co.,Ltd + FL.6,Haichen Building + Jinan Shandong 250010 + CN + +44-38-39 (hex) Cumulus Networks, inc +443839 (base 16) Cumulus Networks, inc + 650 Castro Street, suite 120-245 + Mountain View CA 94041 + US + +04-8B-42 (hex) Skspruce Technologies +048B42 (base 16) Skspruce Technologies + A1, Tianfu Software Park, 1129 Century City Road + High-tech Zone, Chengdu Sichuan 610041 + CN + +50-76-A6 (hex) Ecil Informatica Ind. Com. Ltda +5076A6 (base 16) Ecil Informatica Ind. Com. Ltda + Av. Araguacema, 388 + Barueri São Paulo 06460-070 + BR + +A4-4C-11 (hex) Cisco Systems, Inc +A44C11 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +60-84-3B (hex) Soladigm, Inc. +60843B (base 16) Soladigm, Inc. + 195. S Milpitas Blvd + Milpitas CA 95035 + US + +AC-4B-C8 (hex) Juniper Networks +AC4BC8 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +20-9B-A5 (hex) JIAXING GLEAD Electronics Co.,Ltd +209BA5 (base 16) JIAXING GLEAD Electronics Co.,Ltd + No.66 Zhengyuan Road in Tanghu Industrial Garden + Jiaxing Zhejiang 314003 + CN + +A0-F4-50 (hex) HTC Corporation +A0F450 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +60-89-B1 (hex) Key Digital Systems +6089B1 (base 16) Key Digital Systems + 521 E 3rd Street + Mount Vernon NY 10553 + US + +44-D1-5E (hex) Shanghai Kingto Information Technology Ltd +44D15E (base 16) Shanghai Kingto Information Technology Ltd + No.738 Guangji RD.3F shanghai.china + shanghai 200434 + CN + +00-36-FE (hex) SuperVision +0036FE (base 16) SuperVision + po box 3472 + palos verdes CA 90274 + US + +70-9E-86 (hex) X6D Limited +709E86 (base 16) X6D Limited + 199, Arch. Makariou III + Limassol 3030 + CY + +A0-F4-19 (hex) Nokia Corporation +A0F419 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +1C-97-3D (hex) PRICOM Design +1C973D (base 16) PRICOM Design + 2755 Slocum Rd + Peyton CO 80831 + US + +BC-02-00 (hex) Stewart Audio +BC0200 (base 16) Stewart Audio + 100 West El Camino Real + Mountain View CA 94041 + US + +48-91-53 (hex) Weinmann Geräte für Medizin GmbH + Co. KG +489153 (base 16) Weinmann Geräte für Medizin GmbH + Co. KG + Kronsaalsweg 40 + Hamburg D-22525 + DE + +AC-94-03 (hex) Envision Peripherals Inc +AC9403 (base 16) Envision Peripherals Inc + 47490 Seabridge Dr + Fremont California 94538 + US + +68-D9-25 (hex) ProSys Development Services +68D925 (base 16) ProSys Development Services + Mill House + Mitcham Surrey CR4 4HY + GB + +84-8D-84 (hex) Rajant Corporation +848D84 (base 16) Rajant Corporation + 400 East King Street + Malvern PA 19355 + US + +54-46-6B (hex) Shenzhen CZTIC Electronic Technology Co., Ltd +54466B (base 16) Shenzhen CZTIC Electronic Technology Co., Ltd + Xinghe Building, Zhongxin Road, Shajing Town, Baoan + SHENZHEN GUANGDONG 518104 + CN + +44-B3-82 (hex) Kuang-chi Institute of Advanced Technology +44B382 (base 16) Kuang-chi Institute of Advanced Technology + Software building, Gaoxingzhong 1st Road, + Shenzhen Guangdong 518057 + CN + +60-B9-33 (hex) Deutron Electronics Corp. +60B933 (base 16) Deutron Electronics Corp. + 8F, 68, Sec. 3, Nanking E. Rd. + Taipei Taiwan 104 + TW + +00-43-FF (hex) KETRON S.R.L. +0043FF (base 16) KETRON S.R.L. + Via Giuseppe Taliercio n. 7 + Ancona 60131 + IT + +7C-AC-B2 (hex) Bosch Software Innovations GmbH +7CACB2 (base 16) Bosch Software Innovations GmbH + Ziegelei 7 + Immenstaad BadenWuertemberg 88090 + DE + +18-D6-6A (hex) Inmarsat +18D66A (base 16) Inmarsat + 99 City Road + London EC1Y 1AX + GB + +1C-7C-45 (hex) Vitek Industrial Video Products, Inc. +1C7C45 (base 16) Vitek Industrial Video Products, Inc. + 28492 Constellation Rd + Valencia CA 91355 + US + +3C-38-88 (hex) ConnectQuest, llc +3C3888 (base 16) ConnectQuest, llc + P.O. Box 425 + West Simsbury Connecticut 06092 + US + +48-D7-FF (hex) BLANKOM Antennentechnik GmbH +48D7FF (base 16) BLANKOM Antennentechnik GmbH + Hermann-Petersilge Str. 1 + Bad Blankenburg TH 07422 + DE + +C4-71-30 (hex) Fon Technology S.L. +C47130 (base 16) Fon Technology S.L. + Avda. Bruselas, n. 7, Planta 3, Alcobendas + Madrid 28100 + ES + +D8-33-7F (hex) Office FA.com Co.,Ltd. +D8337F (base 16) Office FA.com Co.,Ltd. + 293-21 + Oyama-shi Tochigi 329-0216 + JP + +00-36-F8 (hex) Conti Temic microelectronic GmbH +0036F8 (base 16) Conti Temic microelectronic GmbH + Dornierstraße 1 + Markdorf 88677 + DE + +A4-F7-D0 (hex) LAN Accessories Co., Ltd. +A4F7D0 (base 16) LAN Accessories Co., Ltd. + 8F-1, No. 159, Sec. 1 Hsin Tai Wu Road, + New Taipei City, 221 + US + +C8-56-45 (hex) Intermas France +C85645 (base 16) Intermas France + Rue de l'industrie + Beauvais Oise 60000 + FR + +44-34-8F (hex) MXT INDUSTRIAL LTDA +44348F (base 16) MXT INDUSTRIAL LTDA + RODOVIA BR 381, KM 490, JARDIM DAS ALTEROSAS + BETIM MINAS GERAIS 32670790 + BR + +D4-EC-0C (hex) Harley-Davidson Motor Company +D4EC0C (base 16) Harley-Davidson Motor Company + 3700 W. Juneau Avenue + Milwaukee Wisconsin 53208 + US + +28-E6-08 (hex) Tokheim +28E608 (base 16) Tokheim + Industrieweg 5 + Bladel NBr 5531 AD + NL + +74-FF-7D (hex) Wren Sound Systems, LLC +74FF7D (base 16) Wren Sound Systems, LLC + 169 Gateshead Way + Phoenixville PA 19460 + US + +AC-F0-B2 (hex) Becker Electronics Taiwan Ltd. +ACF0B2 (base 16) Becker Electronics Taiwan Ltd. + No.32, Lane 30, Long Yuan Rd. + Long-Tan Taoyuan 32544 + TW + +54-2A-9C (hex) LSY Defense, LLC. +542A9C (base 16) LSY Defense, LLC. + 4175 Westport Rd. + Louisville Kentucky 40207 + US + +50-4A-5E (hex) Masimo Corporation +504A5E (base 16) Masimo Corporation + 40 Parker + Irvine California 92618 + US + +6C-A9-6F (hex) TransPacket AS +6CA96F (base 16) TransPacket AS + Drammensveien 134 + Oslo 0277 + NO + +AC-01-42 (hex) Uriel Technologies SIA +AC0142 (base 16) Uriel Technologies SIA + Dzerbenes iela 14 + Riga LV-1006 + LV + +C4-7B-A3 (hex) NAVIS Inc. +C47BA3 (base 16) NAVIS Inc. + Dmitrovskoe shosse 157 + Moscow 127411 + RU + +F4-48-48 (hex) Amscreen Group Ltd +F44848 (base 16) Amscreen Group Ltd + Paragon Business Park + Bolton Lancs BL6 6HG + GB + +50-D2-74 (hex) Steffes Corporation +50D274 (base 16) Steffes Corporation + 3050 Highway 22 North + Dickinson ND 58601 + US + +C8-F7-04 (hex) Building Block Video +C8F704 (base 16) Building Block Video + 17 APex Park + Hailsham East Sussex BN27 2JU + GB + +50-8A-42 (hex) Uptmate Technology Co., LTD +508A42 (base 16) Uptmate Technology Co., LTD + 6F., No.5, Jian 1st Rd.,Zhonghe Dist., + New Taipei City 23558 + TW + +BC-EA-2B (hex) CityCom GmbH +BCEA2B (base 16) CityCom GmbH + Am Kroit 25 + Amerang Bavaria 83123 + DE + +0C-A1-38 (hex) Blinq Wireless Inc. +0CA138 (base 16) Blinq Wireless Inc. + 400 MARCH RD UNIT 240 + KANATA ON K2K3H4 + CA + +5C-6F-4F (hex) S.A. SISTEL +5C6F4F (base 16) S.A. SISTEL + C/SOLSONES, 87 + CASTELLAR DEL VALLES BARCELONA 08211 + ES + +90-1B-0E (hex) Fujitsu Technology Solutions GmbH +901B0E (base 16) Fujitsu Technology Solutions GmbH + Buergermeister-Ulrich-Strasse 100 + Augsburg Bayern 86199 + DE + +F8-50-63 (hex) Verathon +F85063 (base 16) Verathon + 20001 N Creek Pkwy + Bothell WA 98011 + US + +F0-D1-4F (hex) LINEAR LLC +F0D14F (base 16) LINEAR LLC + 1950 CAMINO VIDA ROBLE #150 + CARLSBAD CA 92008-6517 + US + +2C-36-F8 (hex) Cisco Systems, Inc +2C36F8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +84-57-87 (hex) DVR C&C Co., Ltd. +845787 (base 16) DVR C&C Co., Ltd. + 7F 720 Namkwang Centlex Bldg, Cheongcheon-dong, Bupyeong-gu + Incheon 403-030 + KR + +58-08-FA (hex) Fiber Optic & telecommunication INC. +5808FA (base 16) Fiber Optic & telecommunication INC. + 161-4 Kumjeong-Dong, + Kunpo-city Gyeonggi-Do 435-824 + KR + +AC-3D-05 (hex) Instorescreen Aisa +AC3D05 (base 16) Instorescreen Aisa + Room 207, North Bldg,No 28 + Shanghai 200237 + CN + +28-60-94 (hex) CAPELEC +286094 (base 16) CAPELEC + 1130 rue des Marels + Montpellier Hérault 34000 + FR + +A4-56-30 (hex) Cisco Systems, Inc +A45630 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C4-3C-3C (hex) CYBELEC SA +C43C3C (base 16) CYBELEC SA + Rue des Uttins 27 + Yverdon-les-Bains 1401 + CH + +B8-26-D4 (hex) Furukawa Industrial S.A. Produtos Elétricos +B826D4 (base 16) Furukawa Industrial S.A. Produtos Elétricos + Rua Hasdrubal Bellegard, 820 + Parana 81460-120 + BR + +B8-74-47 (hex) Convergence Technologies +B87447 (base 16) Convergence Technologies + 16W215 83rd Street Suite D + Burr Ridge IL 60527 + US + +74-63-DF (hex) VTS GmbH +7463DF (base 16) VTS GmbH + Am Königholz Ost 4 + Eglhausen Bavaria 85411 + DE + +BC-12-5E (hex) Beijing WisVideo INC. +BC125E (base 16) Beijing WisVideo INC. + RM 3A08 Technology&Fortune Center A block No.8 Xue Qing Road,Haidian District , + Beijing 100192 + CN + +14-E4-EC (hex) mLogic LLC +14E4EC (base 16) mLogic LLC + 8440 Warner Drive + Culver City CA 90232 + US + +38-28-EA (hex) Fujian Netcom Technology Co., LTD +3828EA (base 16) Fujian Netcom Technology Co., LTD + Netcom Technology Building, B Zone:Tongpan Software Park, + Fuzhou Fujian 350003 + CN + +D0-1A-A7 (hex) UniPrint +D01AA7 (base 16) UniPrint + Unit 309, 1 Eva Road + Toronto Ontario M9C 4Z5 + CA + +84-6A-ED (hex) Wireless Tsukamoto.,co.LTD +846AED (base 16) Wireless Tsukamoto.,co.LTD + 16-21 1chome,Isoyama + Suzuka Mie-pref 5100256 + JP + +E0-5D-A6 (hex) Detlef Fink Elektronik & Softwareentwicklung +E05DA6 (base 16) Detlef Fink Elektronik & Softwareentwicklung + Brühlstraße 13 + Mössingen 72116 + DE + +04-5A-95 (hex) Nokia Corporation +045A95 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +04-F4-BC (hex) Xena Networks +04F4BC (base 16) Xena Networks + Graabroedretorv 6, 3. sal + København Danmark 1154 + DK + +80-DB-31 (hex) Power Quotient International Co., Ltd. +80DB31 (base 16) Power Quotient International Co., Ltd. + 8F., No. 49, Sec. 4, Jhongyang Rd., Tu Cheng Dist., + New Taipei City 23675 + TW + +1C-51-B5 (hex) Techaya LTD +1C51B5 (base 16) Techaya LTD + P.O.B 1500 + Pardes Hanna 3700 + IL + +6C-3A-84 (hex) Shenzhen Aero-Startech. Co.Ltd +6C3A84 (base 16) Shenzhen Aero-Startech. Co.Ltd + F3-4, Building3,Zhongyuntai Industrial Park.Shiyan Town., + Shenzhen Guangdong 518108 + CN + +00-D6-32 (hex) GE Energy +00D632 (base 16) GE Energy + Lissue Industrial Estate East + Lisburn Co Antrim BT28 2RE + GB + +0C-9E-91 (hex) Sankosha Corporation +0C9E91 (base 16) Sankosha Corporation + 1-12, Miyashimo + Sagamihara-shi Kanagawa-ken 252-0212 + JP + +38-3F-10 (hex) DBL Technology Ltd. +383F10 (base 16) DBL Technology Ltd. + Unit 42, 18/F., Block D, Wah Lok Industrial Center + + HK + +AC-D3-64 (hex) ABB SPA, ABB SACE DIV. +ACD364 (base 16) ABB SPA, ABB SACE DIV. + V.LE DELL'INDUSTRIA, 18 + VITTUONE MI 20010 + IT + +2C-EE-26 (hex) Petroleum Geo-Services +2CEE26 (base 16) Petroleum Geo-Services + 12555 Harris Branch Pkwy + Austin TX 78653 + US + +C8-F9-F9 (hex) Cisco Systems, Inc +C8F9F9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A4-EF-52 (hex) Telewave Co., Ltd. +A4EF52 (base 16) Telewave Co., Ltd. + A-203, SK Twintech Tower + Seoul 153-773 + KR + +A8-26-D9 (hex) HTC Corporation +A826D9 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +28-94-0F (hex) Cisco Systems, Inc +28940F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B8-DA-F7 (hex) Advanced Photonics, Inc. +B8DAF7 (base 16) Advanced Photonics, Inc. + the University of Tokyo, CCR507 + Meguro-ku Tokyo 153-8904 + JP + +14-3A-EA (hex) Dynapower Company LLC +143AEA (base 16) Dynapower Company LLC + 85 Meadowland Drive + South Burlington VT 05403 + US + +A0-86-EC (hex) SAEHAN HITEC Co., Ltd +A086EC (base 16) SAEHAN HITEC Co., Ltd + 16-3, Yongsu-ri, Chowol-eup + Gwangju-si, Gyeonggi-do 464-865 + KR + +94-2E-17 (hex) Schneider Electric Canada Inc +942E17 (base 16) Schneider Electric Canada Inc + 1400 industrielle street + La Prairie Quebec J5R 2E5 + CA + +C4-60-44 (hex) Everex Electronics Limited +C46044 (base 16) Everex Electronics Limited + Unit 3, Block A, 16/F + + HK + +98-FE-03 (hex) Ericsson - North America +98FE03 (base 16) Ericsson - North America + 6300 Legacy Drive + Plano TX 75024 + US + +E0-3C-5B (hex) SHENZHEN JIAXINJIE ELECTRON CO.,LTD +E03C5B (base 16) SHENZHEN JIAXINJIE ELECTRON CO.,LTD + Shenzhen Jiaxinjie Security Industrial park,No 6 Xin He Xin xing Industrial Park, Fuyong Town,Bao'an District + SHENZHEN GUANGDONG 518103 + CN + +CC-94-4A (hex) Pfeiffer Vacuum GmbH +CC944A (base 16) Pfeiffer Vacuum GmbH + Berliner Str. 43 + Asslar Hessen 35614 + DE + +0C-85-25 (hex) Cisco Systems, Inc +0C8525 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B4-D8-A9 (hex) BetterBots +B4D8A9 (base 16) BetterBots + 1600 Wilson Way SE, Ste. 9 + Smyrna GA 30082 + US + +7C-C8-D7 (hex) Damalisk +7CC8D7 (base 16) Damalisk + Coriolis 2 + ECUISSES 71210 + FR + +9C-B0-08 (hex) Ubiquitous Computing Technology Corporation +9CB008 (base 16) Ubiquitous Computing Technology Corporation + 2-20-1 Nishi-Gotanda + Shinagawa-ku Tokyo 1410031 + JP + +A8-77-6F (hex) Zonoff +A8776F (base 16) Zonoff + 70E Swedesford Rd + Malvern PA 19355 + US + +64-87-88 (hex) Juniper Networks +648788 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +00-FA-3B (hex) CLOOS ELECTRONIC GMBH +00FA3B (base 16) CLOOS ELECTRONIC GMBH + Jambe ducommun 8 + LE LOCLE 2400 + CH + +54-1D-FB (hex) Freestyle Energy Ltd +541DFB (base 16) Freestyle Energy Ltd + 18-24 Ricketts Road + Mount Waverley Victoria 3149 + AU + +60-B6-06 (hex) Phorus +60B606 (base 16) Phorus + 16255 Ventura Boulevard, Suite 310 + Encino CA 91436 + US + +90-92-B4 (hex) Diehl BGT Defence GmbH & Co. KG +9092B4 (base 16) Diehl BGT Defence GmbH & Co. KG + Alte Nussdorfer Strasse 13 + Ueberlingen 88662 + DE + +20-AA-4B (hex) Cisco-Linksys, LLC +20AA4B (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +CC-6D-EF (hex) TJK Tietolaite Oy +CC6DEF (base 16) TJK Tietolaite Oy + PL 443 + Vaasa 65101 + FI + +A8-5B-F3 (hex) Audivo GmbH +A85BF3 (base 16) Audivo GmbH + Irrenloher Damm 17 + Schwarzenfeld 92521 + DE + +B8-97-5A (hex) BIOSTAR Microtech Int'l Corp. +B8975A (base 16) BIOSTAR Microtech Int'l Corp. + 2Fl. No. 108-2, Min Chuan Road, Hsin Tien Dist., + New Taipei 231 + TW + +48-33-DD (hex) ZENNIO AVANCE Y TECNOLOGIA, S.L. +4833DD (base 16) ZENNIO AVANCE Y TECNOLOGIA, S.L. + RIO JARAMA 132 NAVE P8.11 + TOLEDO 45007 + ES + +08-75-72 (hex) Obelux Oy +087572 (base 16) Obelux Oy + Kutomotie 6 B + Helsinki 00380 + FI + +10-C2-BA (hex) UTT Co., Ltd. +10C2BA (base 16) UTT Co., Ltd. + + Seoul Korea 135-913 + KR + +90-D7-4F (hex) Bookeen +90D74F (base 16) Bookeen + 27, rue de la Vistule + Paris 75013 + FR + +64-C5-AA (hex) South African Broadcasting Corporation +64C5AA (base 16) South African Broadcasting Corporation + 77 Twickenham Avenue + Auckland Park Gauteng 2006 + ZA + +98-AA-D7 (hex) BLUE WAVE NETWORKING CO LTD +98AAD7 (base 16) BLUE WAVE NETWORKING CO LTD + No. 20, Lane 68, Da-feng RD, + NEW TAIPEI TAIPEI 23121 + TW + +9C-53-CD (hex) ENGICAM s.r.l. +9C53CD (base 16) ENGICAM s.r.l. + Via Dei Pratoni n.16 + Scandicci FIRENZE 50018 + IT + +60-86-45 (hex) Avery Weigh-Tronix, LLC +608645 (base 16) Avery Weigh-Tronix, LLC + 1000 Armstrong Drive + Fairmont MN 56031 + US + +FC-8F-C4 (hex) Intelligent Technology Inc. +FC8FC4 (base 16) Intelligent Technology Inc. + Yuanhe 3 Street,Tongsha Industrial Zone, + Dongguan Guangdong 523127 + CN + +10-FC-54 (hex) Shany Electronic Co., Ltd. +10FC54 (base 16) Shany Electronic Co., Ltd. + 4F, No. 92, Section 1, Nei-Hu Road + Taipei 114 + TW + +C0-29-73 (hex) Audyssey Laboratories Inc. +C02973 (base 16) Audyssey Laboratories Inc. + 110 E. 9th Street, Suite C700 + Los Angeles CA 90079 + US + +78-FE-3D (hex) Juniper Networks +78FE3D (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +28-38-CF (hex) Gen2wave +2838CF (base 16) Gen2wave + Gumi-dong, Bundang-gu + Seongnam-si Gyeonggi-do 463-741 + KR + +24-BC-82 (hex) Dali Wireless, Inc. +24BC82 (base 16) Dali Wireless, Inc. + 125 University Avenue, Suite 88 + Palo Alto CA 94301 + US + +B4-0C-25 (hex) Palo Alto Networks +B40C25 (base 16) Palo Alto Networks + 4401 Great America Parkway + Santa Clara CA 95054 + US + +F8-F7-D3 (hex) International Communications Corporation +F8F7D3 (base 16) International Communications Corporation + 11801 Pierce St. 2nd FL + Riverside CA 92505 + US + +28-D1-AF (hex) Nokia Corporation +28D1AF (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +24-C0-B3 (hex) RSF +24C0B3 (base 16) RSF + 45 Av Marcel Dassault + Toulouse Garonne, Haute (31) 31500 + FR + +FC-45-5F (hex) JIANGXI SHANSHUI OPTOELECTRONIC TECHNOLOGY CO.,LTD +FC455F (base 16) JIANGXI SHANSHUI OPTOELECTRONIC TECHNOLOGY CO.,LTD + No.1010,Anping Road,Eco-Industrial Park,Lushan District + Jiujiang Jiangxi 332000 + CN + +F0-4A-2B (hex) PYRAMID Computer GmbH +F04A2B (base 16) PYRAMID Computer GmbH + Boetzinger Strasse 60 + Freiburg BW 79111 + DE + +30-2D-E8 (hex) JDA, LLC (JDA Systems) +302DE8 (base 16) JDA, LLC (JDA Systems) + 4080 Pike Lane + Concord CA 94520 + US + +48-A6-D2 (hex) GJsun Optical Science and Tech Co.,Ltd. +48A6D2 (base 16) GJsun Optical Science and Tech Co.,Ltd. + First floor National Information Industry Park D-08 + Guilin Guangxi 541004 + CN + +50-0B-32 (hex) Foxda Technology Industrial(ShenZhen)Co.,LTD +500B32 (base 16) Foxda Technology Industrial(ShenZhen)Co.,LTD + 1F of 1st Building&1F-3F of 2nd Building, Foxda Industrial Zone,North of Lanzhu Road,Pingshan New District,Shenzhen City,Guangdong Province,P.R.China + Shenzhen Guangdong 518122 + CN + +60-35-53 (hex) Buwon Technology +603553 (base 16) Buwon Technology + (Cunuitechnopark 102-1507) 200-1,Chunui-dong + Buchon-si Gyeinggi-do 420-857 + KR + +E0-39-D7 (hex) Plexxi, Inc. +E039D7 (base 16) Plexxi, Inc. + 100 Innovative Way Suite 3322 + Nashua NH 03062 + US + +7C-33-6E (hex) MEG Electronics Inc. +7C336E (base 16) MEG Electronics Inc. + Bogazici Universitesi Kuzey Kampus + ISTANBUL 34342 + TR + +D4-E3-3F (hex) Nokia +D4E33F (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +68-CD-0F (hex) U Tek Company Limited +68CD0F (base 16) U Tek Company Limited + FL5, BLDG12, 3RD DISTRICT, TANGTOU INDUSTRIAL PARK + SHENZHEN GUANGDONG 518018 + CN + +60-3F-C5 (hex) COX CO., LTD +603FC5 (base 16) COX CO., LTD + 904HO, ACE TWIN TOWER 1-CHA + SEOUL 152-779 + KR + +A4-E3-91 (hex) DENY FONTAINE +A4E391 (base 16) DENY FONTAINE + ROUTE DE SAINT VALERY + SAINT BLIMONT 80960 + FR + +AC-6F-D9 (hex) Valueplus Inc. +AC6FD9 (base 16) Valueplus Inc. + #803, Sicox Tower, 513-14, + Seongnam-si Gyeonggi-do 462-806 + KR + +DC-1E-A3 (hex) Accensus LLC +DC1EA3 (base 16) Accensus LLC + 200 South Wacker Drive + Chicago IL 60606 + US + +A4-01-30 (hex) ABIsystems Co., LTD +A40130 (base 16) ABIsystems Co., LTD + 308 ACE Techno Tower8 191-7 Guro-dong + Seoul + KR + +90-A7-83 (hex) JSW PACIFIC CORPORATION +90A783 (base 16) JSW PACIFIC CORPORATION + 3F-3, No.700, Chung-Zheng Rd, Zhonghe District + New Taipei City 235 + TW + +F8-46-2D (hex) SYNTEC Incorporation +F8462D (base 16) SYNTEC Incorporation + 3F, NO.105, Shing-shyue St., + Hsinchu 300 + TW + +78-A5-DD (hex) Shenzhen Smarteye Digital Electronics Co., Ltd +78A5DD (base 16) Shenzhen Smarteye Digital Electronics Co., Ltd + #6 Northen Area + Shenzhen Guangdong 518129 + CN + +EC-E7-44 (hex) Omntec mfg. inc +ECE744 (base 16) Omntec mfg. inc + 1993 Pond Road. + Ronkonkoma NY 11779 + US + +28-AF-0A (hex) Sirius XM Radio Inc +28AF0A (base 16) Sirius XM Radio Inc + 1221 Avenue of the Americas + New York NY 10020 + US + +5C-D4-AB (hex) Zektor +5CD4AB (base 16) Zektor + 12675 Danielson Ct. Ste 401 + Poway CA 92064 + US + +08-FC-52 (hex) OpenXS BV +08FC52 (base 16) OpenXS BV + Koaibosk 3 + Terwispel Friesland 8407ED + NL + +4C-32-D9 (hex) M Rutty Holdings Pty. Ltd. +4C32D9 (base 16) M Rutty Holdings Pty. Ltd. + Unit 1, 4 Beaumont Road + Mount Kuring-Gai New South Wales 2080 + AU + +08-A1-2B (hex) ShenZhen EZL Technology Co., Ltd +08A12B (base 16) ShenZhen EZL Technology Co., Ltd + RM21B, Building 2, China Phoenix Building, + ShenZhen GuangDong 518026 + CN + +A0-0C-A1 (hex) SKTB SKiT +A00CA1 (base 16) SKTB SKiT + 239 B. Sadovaya Str. + Saratov Saratov region 410005 + RU + +64-E8-4F (hex) Serialway Communication Technology Co. Ltd +64E84F (base 16) Serialway Communication Technology Co. Ltd + Room 315, 706 Painting Room, + Beijing 100096 + CN + +2C-9E-FC (hex) CANON INC. +2C9EFC (base 16) CANON INC. + 3-30-2 + Ohta-Ku Tokyo 146-8501 + JP + +18-2B-05 (hex) 8D Technologies +182B05 (base 16) 8D Technologies + 416, de Maisonneuve West + Montreal, Quebec H3A 1L2 + CA + +24-0B-B1 (hex) KOSTAL Industrie Elektrik GmbH +240BB1 (base 16) KOSTAL Industrie Elektrik GmbH + Gewerbering 20 + Schalksmuehle North Rhine-Westphalia 58579 + DE + +20-EE-C6 (hex) Elefirst Science & Tech Co ., ltd +20EEC6 (base 16) Elefirst Science & Tech Co ., ltd + Floor 9, No 77 Zijinmingmen Building + Nanjing Jiangsu 210007 + CN + +E0-1E-07 (hex) Anite Telecoms US. Inc +E01E07 (base 16) Anite Telecoms US. Inc + 106 Vista Centre Dr + Forest VA 24551 + US + +7C-6B-33 (hex) Tenyu Tech Co. Ltd. +7C6B33 (base 16) Tenyu Tech Co. Ltd. + 1F., No.10, Ln. 36, Ganzhen 2nd St. + New Taipei City 251 + TW + +14-7D-C5 (hex) Murata Manufacturing Co., Ltd. +147DC5 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +00-B9-F6 (hex) Shenzhen Super Rich Electronics Co.,Ltd +00B9F6 (base 16) Shenzhen Super Rich Electronics Co.,Ltd + RM.102,Shibida Building,No.55,Zhenhua Road,Shenzhen Futian District, + Shenzhen Guangdong 518031 + CN + +FC-C2-3D (hex) Atmel Corporation +FCC23D (base 16) Atmel Corporation + 1150 E Cheyenne Mtn Blvd + Colorado Springs CO 80906 + US + +88-E7-A6 (hex) iKnowledge Integration Corp. +88E7A6 (base 16) iKnowledge Integration Corp. + 10F No.2, Sec. 3, Xinsheng S. Rd., + Taipei 10660 + TW + +A4-46-FA (hex) AmTRAN Video Corporation +A446FA (base 16) AmTRAN Video Corporation + 9 Goddard + Irvine CA 92618 + US + +CC-E7-DF (hex) American Magnetics, Inc. +CCE7DF (base 16) American Magnetics, Inc. + PO Box 2509 + Oak Ridge TN 37831-2509 + US + +28-04-E0 (hex) FERMAX ELECTRONICA S.A.U. +2804E0 (base 16) FERMAX ELECTRONICA S.A.U. + Tres Cruces 133 + Valencia 46017 + ES + +64-43-46 (hex) GuangDong Quick Network Computer CO.,LTD +644346 (base 16) GuangDong Quick Network Computer CO.,LTD + 12F,No.80 of Middle XianLie Road,YueXiu District + GuangZhou GuangDong 510070 + CN + +D4-02-4A (hex) Delphian Systems LLC +D4024A (base 16) Delphian Systems LLC + 720 Dartmouth Lane + Buffalo Grove IL 60089 + US + +00-41-B4 (hex) Wuxi Zhongxing Optoelectronics Technology Co.,Ltd. +0041B4 (base 16) Wuxi Zhongxing Optoelectronics Technology Co.,Ltd. + Block 93-C, Sci. & Tech. Industry park, + Wuxi Jiangsu 214028 + CN + +F4-44-50 (hex) BND Co., Ltd. +F44450 (base 16) BND Co., Ltd. + 573-13 Bokhyeon-dong, Buk-gu + Daegu 702-020 + KR + +04-62-D7 (hex) ALSTOM HYDRO FRANCE +0462D7 (base 16) ALSTOM HYDRO FRANCE + 82 Avenue Leon Blum + GRENOBLE 38041 + FR + +D4-50-7A (hex) CEIVA Logic, Inc +D4507A (base 16) CEIVA Logic, Inc + 214 E Magnolia Blvd + Burbank CA 91502 + US + +64-D9-89 (hex) Cisco Systems, Inc +64D989 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +64-5D-D7 (hex) Shenzhen Lifesense Medical Electronics Co., Ltd. +645DD7 (base 16) Shenzhen Lifesense Medical Electronics Co., Ltd. + China Academy of Science and Technology Development, Room 19A + Shenzhen Guangdong 518057 + CN + +EC-46-70 (hex) Meinberg Funkuhren GmbH & Co. KG +EC4670 (base 16) Meinberg Funkuhren GmbH & Co. KG + Lange Wand 9 + Bad Pyrmont NDS 31812 + DE + +D0-5A-0F (hex) I-BT DIGITAL CO.,LTD +D05A0F (base 16) I-BT DIGITAL CO.,LTD + 17F.-8, No.866, Zhongzheng Rd., Zhonghe Dist + New Taipei 235 + TW + +EC-96-81 (hex) 2276427 Ontario Inc +EC9681 (base 16) 2276427 Ontario Inc + 31-1275 Morningside Ave + Toronto ON M1B3W1 + CA + +5C-07-6F (hex) Thought Creator +5C076F (base 16) Thought Creator + Largo da Pirâmide, Nº 3, Sala D + Oeiras Lisboa 2795-156 Linda-a-Velha + PT + +3C-0F-C1 (hex) KBC Networks +3C0FC1 (base 16) KBC Networks + 25691 Atlantic Ocean Dr + Lake Forest CA 92630 + US + +58-E6-36 (hex) EVRsafe Technologies +58E636 (base 16) EVRsafe Technologies + 59 North Terrace + Adelaide South Australia 5069 + AU + +10-F9-EE (hex) Nokia Corporation +10F9EE (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +74-2B-0F (hex) Infinidat Ltd. +742B0F (base 16) Infinidat Ltd. + 11 Galgalei Haplada St. + Herzliya Pituach Center 46722 + IL + +C8-F9-81 (hex) Seneca s.r.l. +C8F981 (base 16) Seneca s.r.l. + Via Germania, 34 + PADOVA 35127 + IT + +24-49-7B (hex) Innovative Converged Devices Inc +24497B (base 16) Innovative Converged Devices Inc + 424 8th Avenue North + Seattle WA 98109 + US + +98-E7-9A (hex) Foxconn(NanJing) Communication Co.,Ltd. +98E79A (base 16) Foxconn(NanJing) Communication Co.,Ltd. + A-2FMinfang Building No.189 Guangzhou Rd + Nanjing Jiang su 210029 + CN + +A0-E9-DB (hex) Ningbo FreeWings Technologies Co.,Ltd +A0E9DB (base 16) Ningbo FreeWings Technologies Co.,Ltd + Room 1107-1108, No 298 XueShi Road Yinzhou District Ningbo, + Ningbo Zhejiang 315000 + CN + +78-89-73 (hex) CMC +788973 (base 16) CMC + Industriepark De Bruwaan 37B + Oudenaarde Oost-Vlaanderen 9700 + BE + +14-30-7A (hex) Avermetrics +14307A (base 16) Avermetrics + 2973 Glendale Blvd. + Los Angeles CA 90039 + US + +A0-6C-EC (hex) RIM +A06CEC (base 16) RIM + Phillip Street + Waterloo Ontario N2L 3W8 + CA + +20-37-06 (hex) Cisco Systems, Inc +203706 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F4-B1-64 (hex) Lightning Telecommunications Technology Co. Ltd +F4B164 (base 16) Lightning Telecommunications Technology Co. Ltd + Room 1302, Tian¡¯an Hi-Tech Plaza Tower A, Futian District, + ShenZhen GuangDong 518040 + CN + +70-B0-35 (hex) Shenzhen Zowee Technology Co., Ltd +70B035 (base 16) Shenzhen Zowee Technology Co., Ltd + Block 5, Science and Technology Industrial + Shenzhen Guangdong 518055 + CN + +88-21-E3 (hex) Nebusens, S.L. +8821E3 (base 16) Nebusens, S.L. + C/ Adaja S/N, Edificio M2 + Villamayor de la Armuña Salamanca 37185 + ES + +90-B9-7D (hex) Johnson Outdoors Marine Electronics d/b/a Minnkota +90B97D (base 16) Johnson Outdoors Marine Electronics d/b/a Minnkota + 1531 E Madison Ave + Mankato MN 56001 + US + +7C-F4-29 (hex) NUUO Inc. +7CF429 (base 16) NUUO Inc. + C block, 18 Sihyuan St. Jhongjheng District, + Taipei 100 + TW + +CC-B5-5A (hex) Fraunhofer ITWM +CCB55A (base 16) Fraunhofer ITWM + Fraunhoferplatz 1 + Kaiserslautern Rhineland-Palatinae 67663 + DE + +AC-8A-CD (hex) ROGER D.Wensker, G.Wensker sp.j. +AC8ACD (base 16) ROGER D.Wensker, G.Wensker sp.j. + Gosciszewo 59 + Sztum Pomorskie 82-400 + PL + +98-42-46 (hex) SOL INDUSTRY PTE., LTD +984246 (base 16) SOL INDUSTRY PTE., LTD + 1 NORTH BRIDGE RD., + 179094 + SG + +34-29-EA (hex) MCD ELECTRONICS SP. Z O.O. +3429EA (base 16) MCD ELECTRONICS SP. Z O.O. + Lelewela 26 + Zywiec slaskie 34-300 + PL + +8C-82-A8 (hex) Insigma Technology Co.,Ltd +8C82A8 (base 16) Insigma Technology Co.,Ltd + No.226 Tianmushan Road, + Hangzhou Zhejiang 310000 + CN + +60-19-0C (hex) RRAMAC +60190C (base 16) RRAMAC + 15400 Medina Rd + Plymouth MN 55447 + US + +D0-5F-CE (hex) Hitachi Data Systems +D05FCE (base 16) Hitachi Data Systems + 750 Central Expressway + Santa Clara CA 95050 + US + +F8-03-32 (hex) Khomp +F80332 (base 16) Khomp + Rua Joe Collaço, 253 + Florianópolis Santa Catarina 88037-010 + BR + +28-A5-74 (hex) Miller Electric Mfg. Co. +28A574 (base 16) Miller Electric Mfg. Co. + N676 Communication Drive + Appleton WI 54914 + US + +10-45-BE (hex) Norphonic AS +1045BE (base 16) Norphonic AS + Fabrikkgaten 10 + Bergen 5059 + NO + +90-B8-D0 (hex) Joyent, Inc. +90B8D0 (base 16) Joyent, Inc. + 345 California Street, + San Francisco CA 94104 + US + +AC-47-23 (hex) Genelec +AC4723 (base 16) Genelec + Olvitie 5 + Iisalmi 74100 + FI + +E8-BA-70 (hex) Cisco Systems, Inc +E8BA70 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D4-A4-25 (hex) SMAX Technology Co., Ltd. +D4A425 (base 16) SMAX Technology Co., Ltd. + 2F., No. 3, Wuquan 3rd, Wugu Dist. + New Taipei City 248 + TW + +28-14-71 (hex) Lantis co., LTD. +281471 (base 16) Lantis co., LTD. + busan innobiz center 401 + busan 616-829 + KR + +24-47-0E (hex) PentronicAB +24470E (base 16) PentronicAB + Bergsliden 1 + GUNNEBO 59093 + SE + +D0-9B-05 (hex) Emtronix +D09B05 (base 16) Emtronix + 5# Gaopeng Dadao + Chengdu 610041 + CN + +8C-11-CB (hex) ABUS Security-Center GmbH & Co. KG +8C11CB (base 16) ABUS Security-Center GmbH & Co. KG + Linker Kreuthweg 5 + Affing / Muehlhausen Bavaria 86444 + DE + +FC-83-29 (hex) Trei technics +FC8329 (base 16) Trei technics + 801 Northpoint Pkwy + West Palm Beach Florida 33407 + US + +14-EB-33 (hex) BSMediasoft Co., Ltd. +14EB33 (base 16) BSMediasoft Co., Ltd. + #603, Garden Bldg., 14-13, Yoido-Dong, Youngdeungpo-Gu + Seoul 150-871 + KR + +F4-B5-49 (hex) Xiamen Yeastar Information Technology Co., Ltd. +F4B549 (base 16) Xiamen Yeastar Information Technology Co., Ltd. + 3/F, No. 46 Guanri Road, 2nd Software Park + Xiamen Fujian 361006 + CN + +88-B1-68 (hex) Delta Control GmbH +88B168 (base 16) Delta Control GmbH + Rondorfer Hauptstraße 33 + Cologne NRW 50997 + DE + +68-87-6B (hex) INQ Mobile Limited +68876B (base 16) INQ Mobile Limited + 6 Hester Road + Battersea London SW11 4AN + GB + +1C-AA-07 (hex) Cisco Systems, Inc +1CAA07 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +68-5B-36 (hex) POWERTECH INDUSTRIAL CO., LTD. +685B36 (base 16) POWERTECH INDUSTRIAL CO., LTD. + 10F, No. 407, Chung Shan Rd., Sec 2, + Chung Ho Taipei County 23558 + TW + +28-EE-2C (hex) Frontline Test Equipment +28EE2C (base 16) Frontline Test Equipment + PO Box 7507 + Charlottesville Virginia 22906-7507 + US + +78-2E-EF (hex) Nokia Corporation +782EEF (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +7C-F0-BA (hex) Linkwell Telesystems Pvt Ltd +7CF0BA (base 16) Linkwell Telesystems Pvt Ltd + 1-11-252/1/A, Gowra Klassic + Hyderabad Andhra Pradesh 500016 + IN + +AC-86-74 (hex) Open Mesh, Inc. +AC8674 (base 16) Open Mesh, Inc. + 111 SW 5th Ave Ste1150 + Portland OR 97204 + US + +64-D2-41 (hex) Keith & Koep GmbH +64D241 (base 16) Keith & Koep GmbH + Uellendahler Str. 199 + Wuppertal NRW 42109 + DE + +18-B7-9E (hex) Invoxia +18B79E (base 16) Invoxia + 87 rue du Gouverneur Général Eboué + Issy-Les-Moulineaux 92130 + FR + +8C-44-35 (hex) Shanghai BroadMobi Communication Technology Co., Ltd. +8C4435 (base 16) Shanghai BroadMobi Communication Technology Co., Ltd. + Rm. 901, Bld. 9, No.1515 Gumei Rd, Xuhui District + Shanghai 200233 + CN + +F8-1D-93 (hex) Longdhua(Beijing) Controls Technology Co.,Ltd +F81D93 (base 16) Longdhua(Beijing) Controls Technology Co.,Ltd + Room 1203,Lixiang Building, No.111 Zhichun Road,Haidian District, + Beijing 10086 + CN + +94-D9-3C (hex) ENELPS +94D93C (base 16) ENELPS + Bul Arsenija Carnojevica 117 + Belgrade 11070 + RS + +B8-BE-BF (hex) Cisco Systems, Inc +B8BEBF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +64-B6-4A (hex) ViVOtech, Inc. +64B64A (base 16) ViVOtech, Inc. + 451 El Camino Real + Santa Clara CA 95050 + US + +38-D1-35 (hex) EasyIO Corporation Sdn. Bhd. +38D135 (base 16) EasyIO Corporation Sdn. Bhd. + No. 32-2 & 32-3, Jalan Puteri 2/4 + Puchong Selangor 47100 + MY + +CC-F8-41 (hex) Lumewave +CCF841 (base 16) Lumewave + 4803 B Street + Sacramento CA 95819 + US + +30-EB-25 (hex) INTEK DIGITAL +30EB25 (base 16) INTEK DIGITAL + 801, 8th Fl., Anyang K-center building, 1591-9 + Anyang 431-060 + KR + +44-E4-D9 (hex) Cisco Systems, Inc +44E4D9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +AC-CA-54 (hex) Telldus Technologies AB +ACCA54 (base 16) Telldus Technologies AB + Skiffervägen 102 + Lund 224 78 + SE + +90-19-00 (hex) SCS SA +901900 (base 16) SCS SA + Via Pini, 32 + Biasca 6710 + CH + +D4-5D-42 (hex) Nokia Corporation +D45D42 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +B0-38-29 (hex) Siliconware Precision Industries Co., Ltd. +B03829 (base 16) Siliconware Precision Industries Co., Ltd. + No. 123, Sec.3, Da Fong Rd, Tantzu, + Taichung 427 + TW + +7C-6C-39 (hex) PIXSYS SRL +7C6C39 (base 16) PIXSYS SRL + VIA DELLA CROCE ROSSA 42 + PADOVA PD 35129 + IT + +18-B3-BA (hex) Netlogic AB +18B3BA (base 16) Netlogic AB + Datavägen 14A + ASKIM Västra Götaland 43632 + SE + +8C-5F-DF (hex) Beijing Railway Signal Factory +8C5FDF (base 16) Beijing Railway Signal Factory + No.2 Sicun Xilu Langfa,Huangcun, + Beiijng 102613 + CN + +D4-7B-75 (hex) HARTING Electronics GmbH +D47B75 (base 16) HARTING Electronics GmbH + Marienwerderstraße. 3 + Espelkamp North Rhine Westphalia 32339 + DE + +D8-DF-0D (hex) beroNet GmbH +D8DF0D (base 16) beroNet GmbH + Friedrichstraße 231 + Berlin 10969 + DE + +AC-F9-7E (hex) ELESYS INC. +ACF97E (base 16) ELESYS INC. + Suit 623, 812-1, Hyomun-dong + Ulsan Buk-gu 683-360 + KR + +20-40-05 (hex) feno GmbH +204005 (base 16) feno GmbH + Kolpingring 22 + Oberhaching Bavaria 82041 + DE + +D4-6F-42 (hex) WAXESS USA Inc +D46F42 (base 16) WAXESS USA Inc + 1401 Dove Street + Newport Beach CA 92660 + US + +30-0B-9C (hex) Delta Mobile Systems, Inc. +300B9C (base 16) Delta Mobile Systems, Inc. + 700 Remington Road + Schaumburg Illinois 60173 + US + +6C-AD-3F (hex) Hubbell Building Automation, Inc. +6CAD3F (base 16) Hubbell Building Automation, Inc. + 9601 Dessau Rd + Austin Texas 78754 + US + +B0-1B-7C (hex) Ontrol A.S. +B01B7C (base 16) Ontrol A.S. + Turcan Cad No:19 Y.Dudullu + Umraniye Istanbul 34775 + TR + +04-C5-A4 (hex) Cisco Systems, Inc +04C5A4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +BC-28-46 (hex) NextBIT Computing Pvt. Ltd. +BC2846 (base 16) NextBIT Computing Pvt. Ltd. + 30/2, 2nd Floor, R.K. Plaza, + Bangalore Karnataka 560038 + IN + +BC-0F-2B (hex) FORTUNE TECHGROUP CO.,LTD +BC0F2B (base 16) FORTUNE TECHGROUP CO.,LTD + 7-8F,No.1198 North Qinzhou Road, + Shanghai 200233 + CN + +64-81-25 (hex) Alphatron Marine BV +648125 (base 16) Alphatron Marine BV + Schaardijk 23 + Rotterdam Zuid-Holland 3063NH + NL + +8C-F9-C9 (hex) MESADA Technology Co.,Ltd. +8CF9C9 (base 16) MESADA Technology Co.,Ltd. + TongFng Information Harbor,No.11 LangShan Road,HI-tech Park,Nanshan District, + Shenzhen GuangDong 518057 + CN + +C0-62-6B (hex) Cisco Systems, Inc +C0626B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +94-E2-26 (hex) D. ORtiz Consulting, LLC +94E226 (base 16) D. ORtiz Consulting, LLC + 22601 N. 17th Avenue Suite 270 + Phoenix AZ 85027 + US + +D8-C9-9D (hex) EA DISPLAY LIMITED +D8C99D (base 16) EA DISPLAY LIMITED + 22/F DELTA HOUSE 3 ON YIU ST + SHATIN NT + HK + +10-83-D2 (hex) Microseven Systems, LLC +1083D2 (base 16) Microseven Systems, LLC + 404 South Lemon Ave., #9 + Walnut California 91789 + US + +34-68-4A (hex) Teraworks Co., Ltd. +34684A (base 16) Teraworks Co., Ltd. + Room No. 201 , 515-30 , Mok-Dong + Seoul 158-808 + KR + +CC-FC-6D (hex) RIZ TRANSMITTERS +CCFC6D (base 16) RIZ TRANSMITTERS + BOZIDAREVICEVA 13 + ZAGREB 10000 + HR + +E0-3E-7D (hex) data-complex GmbH +E03E7D (base 16) data-complex GmbH + Düsterngraben 7 + Halberstadt Sachsen-Anhalt 38820 + DE + +0C-C6-AC (hex) DAGS +0CC6AC (base 16) DAGS + Ace High end Tower 7th 1802 + Seoul Geumcheon-gu 153-802 + KR + +04-26-05 (hex) GFR Gesellschaft für Regelungstechnik und Energieeinsparung mbH +042605 (base 16) GFR Gesellschaft für Regelungstechnik und Energieeinsparung mbH + Kapellenweg 42 + Verl 33415 + DE + +24-F0-FF (hex) GHT Co., Ltd. +24F0FF (base 16) GHT Co., Ltd. + #16 Nanyunyi Lu, Guangzhou Science City + Guangzhou Guangdong 510663 + CN + +9C-C0-D2 (hex) Conductix-Wampfler GmbH +9CC0D2 (base 16) Conductix-Wampfler GmbH + Rheinstrasse 27+33 + Baden-Württemberg + DE + +CC-F6-7A (hex) Ayecka Communication Systems LTD +CCF67A (base 16) Ayecka Communication Systems LTD + POB 3059 + Hod Hasharon 45130 + IL + +80-65-E9 (hex) BenQ Corporation +8065E9 (base 16) BenQ Corporation + 16 Jihu Road, Neihu + Taipei 114 + TW + +EC-98-6C (hex) Lufft Mess- und Regeltechnik GmbH +EC986C (base 16) Lufft Mess- und Regeltechnik GmbH + Gutenbergstraße 20 + Fellbach Baden-Württemberg 70736 + DE + +D0-93-F8 (hex) Stonestreet One LLC +D093F8 (base 16) Stonestreet One LLC + 9960 Corporate Campus Drive + Louisville KY 40223 + US + +9C-64-5E (hex) Harman Consumer Group +9C645E (base 16) Harman Consumer Group + 8500 Balboa Blvd + Northridge CA 91329 + US + +1C-33-4D (hex) ITS Telecom +1C334D (base 16) ITS Telecom + 29 Hametzuda st. + Azur Israel 580001 + IL + +DC-D8-7F (hex) Shenzhen JoinCyber Telecom Equipment Ltd +DCD87F (base 16) Shenzhen JoinCyber Telecom Equipment Ltd + 19CDE, Block A,JinFengBuilding,shangbu South Road,Futian District, + Shenzhen Guangdong 518031 + CN + +B4-E0-CD (hex) Fusion-io, Inc +B4E0CD (base 16) Fusion-io, Inc + 2880 Junction Avenue + San Jose CA 95134-1922 + US + +28-60-46 (hex) Lantech Communications Global, Inc. +286046 (base 16) Lantech Communications Global, Inc. + 7F, No. 45, Lane 188, Ruiguang Rd., Neihu District + Taipei City 11491 + TW + +10-E2-D5 (hex) Qi Hardware Inc. +10E2D5 (base 16) Qi Hardware Inc. + 555 4TH STREET #403 + San Francisco CA 94107 + US + +60-C9-80 (hex) Trymus +60C980 (base 16) Trymus + Bucheon Techno Park 303-902 + Bucheon-si 421-741 Gyunggi-do + KR + +A0-36-FA (hex) Ettus Research LLC +A036FA (base 16) Ettus Research LLC + 1043 N Shoreline Blvd + Mountain View CA 94043 + US + +EC-83-6C (hex) RM Tech Co., Ltd. +EC836C (base 16) RM Tech Co., Ltd. + C-801, Bupyeong Woolim Lions Valley + Incheon City 403-911 + KR + +30-39-55 (hex) Shenzhen Jinhengjia Electronic Co., Ltd. +303955 (base 16) Shenzhen Jinhengjia Electronic Co., Ltd. + 4-6 Floors, Factory Building, Jijia Industrial Park, + Shenzhen Guangdong 518112 + CN + +FC-5B-24 (hex) Weibel Scientific A/S +FC5B24 (base 16) Weibel Scientific A/S + Solvang 30 + Alleroed 3450 + DK + +78-59-3E (hex) RAFI GmbH & Co.KG +78593E (base 16) RAFI GmbH & Co.KG + Ravensburger Str. 128-134 + Berg Baden Wurttemberg 88276 + DE + +50-97-72 (hex) Westinghouse Digital +509772 (base 16) Westinghouse Digital + 500 N. State College Blvd. + Orange CA 92868 + US + +50-3D-E5 (hex) Cisco Systems, Inc +503DE5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +54-04-96 (hex) Gigawave LTD +540496 (base 16) Gigawave LTD + GIGAWAVE TECHNICAL CENTRE + Colchester ESSEX CO62NS + GB + +EC-46-44 (hex) TTK SAS +EC4644 (base 16) TTK SAS + 4, Rue du Chemin Vert + Clichy 92110 + FR + +4C-B9-C8 (hex) CONET CO., LTD. +4CB9C8 (base 16) CONET CO., LTD. + 2-8,HIGASHIJIMA-CHO + ICHINOMIYA AICHI 491-0074 + JP + +8C-B6-4F (hex) Cisco Systems, Inc +8CB64F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +20-4A-AA (hex) Hanscan Spain S.A. +204AAA (base 16) Hanscan Spain S.A. + Avda. de la Vega, 1 + Alcobendas Madrid 28108 + ES + +20-FE-CD (hex) System In Frontier Inc. +20FECD (base 16) System In Frontier Inc. + 4F Shinsuzuharu Bldg. 2-8-3 Akebonocyo + Tachikawa-shi Tokyo 190-0012 + JP + +F0-93-3A (hex) NxtConect +F0933A (base 16) NxtConect + Schillerstrasse 4 + Bad Kissingen 97688 + DE + +B8-41-5F (hex) ASP AG +B8415F (base 16) ASP AG + Max- Planck-Str. 15 a-c + Erkrath NRW 40699 + DE + +2C-B6-9D (hex) RED Digital Cinema +2CB69D (base 16) RED Digital Cinema + 20291 Valencia Circle + Lake Forest California 92630 + US + +58-2F-42 (hex) Universal Electric Corporation +582F42 (base 16) Universal Electric Corporation + 168 Georgetown Road + Canonsburg PA 15317 + US + +04-74-A1 (hex) Aligera Equipamentos Digitais Ltda +0474A1 (base 16) Aligera Equipamentos Digitais Ltda + Av. Para 330 / 302 + Porto Alegre RS 90240-590 + BR + +5C-69-84 (hex) NUVICO +5C6984 (base 16) NUVICO + 1 Enterprise Place Unit G + Hicksville NY 11801 + US + +70-DD-A1 (hex) Tellabs +70DDA1 (base 16) Tellabs + One Tellabs Center + Naperville Illinois 60563 + US + +94-D0-19 (hex) Cydle Corp. +94D019 (base 16) Cydle Corp. + 1203, KofomoTower, 16-3 , Sunae-Dong, Bundang-Gu + Seongnam-City Gyeonggi-Do 463825 + KR + +8C-27-8A (hex) Vocollect Inc +8C278A (base 16) Vocollect Inc + 703 Rodi Road + Pittsburgh Pa 15235 + US + +CC-0C-DA (hex) Miljovakt AS +CC0CDA (base 16) Miljovakt AS + Gannestadveien 2 + Borre Vestfold 3184 + NO + +E4-1C-4B (hex) V2 TECHNOLOGY, INC. +E41C4B (base 16) V2 TECHNOLOGY, INC. + 4450 Enterprise Street + Fremont California 94538 + US + +5C-F3-FC (hex) IBM Corp +5CF3FC (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +A8-6A-6F (hex) RIM +A86A6F (base 16) RIM + Phillip Street + Waterloo Ontario N2L 3W8 + CA + +68-12-2D (hex) Special Instrument Development Co., Ltd. +68122D (base 16) Special Instrument Development Co., Ltd. + 6F-1, No. 123, Lane 235 + Hsin Tien Taipei Hsien 231 + TW + +94-F7-20 (hex) Tianjin Deviser Electronics Instrument Co., Ltd +94F720 (base 16) Tianjin Deviser Electronics Instrument Co., Ltd + No.40 Yibin Road,Nankai district, + Tianjin 300113 + CN + +DC-9C-52 (hex) Sapphire Technology Limited. +DC9C52 (base 16) Sapphire Technology Limited. + Unit 1909-1919, 19/F., Tower 2, Grand Central Plaza, + + HK + +48-91-F6 (hex) Shenzhen Reach software technology CO.,LTD +4891F6 (base 16) Shenzhen Reach software technology CO.,LTD + 6/F,Block B, Kingdee Software park,#2,Keji 12th South Road,Hi-tech Industrial Park,Nanshan District + Shenzhen Guangdong 518057 + CN + +64-9B-24 (hex) V Technology Co., Ltd. +649B24 (base 16) V Technology Co., Ltd. + YBP East Tower 5F, + Yokohama city Kanagawa 240-0005 + JP + +84-6E-B1 (hex) Park Assist LLC +846EB1 (base 16) Park Assist LLC + 111 W28th Street + New York NY 10001 + US + +6C-50-4D (hex) Cisco Systems, Inc +6C504D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B8-D0-6F (hex) GUANGZHOU HKUST FOK YING TUNG RESEARCH INSTITUTE +B8D06F (base 16) GUANGZHOU HKUST FOK YING TUNG RESEARCH INSTITUTE + Rm 403, North of Software Building,Nansha IT Park, + Guangzhou Guangdong Privince 511458 + CN + +EC-14-F6 (hex) BioControl AS +EC14F6 (base 16) BioControl AS + Grimstad Gard + Rakkestad N-1890 + NO + +E8-99-5A (hex) PiiGAB, Processinformation i Goteborg AB +E8995A (base 16) PiiGAB, Processinformation i Goteborg AB + Anders Carlssons gata 1 + Gothenburg 417 55 + SE + +40-1D-59 (hex) Biometric Associates, LP +401D59 (base 16) Biometric Associates, LP + 9475 Deereco Rd. + Timonium MD 21093 + US + +B8-FF-6F (hex) Shanghai Typrotech Technology Co.Ltd +B8FF6F (base 16) Shanghai Typrotech Technology Co.Ltd + Design Building 903, NO.63, + Shanghai 200092 + CN + +1C-BD-0E (hex) Amplified Engineering Pty Ltd +1CBD0E (base 16) Amplified Engineering Pty Ltd + 5 Turner Avenue + Bentley WA 6102 + AU + +A0-F2-17 (hex) GE Medical System(China) Co., Ltd. +A0F217 (base 16) GE Medical System(China) Co., Ltd. + No.19, ChangJiang Road + Wuxi Jiangsu 214028 + CN + +F0-A7-64 (hex) GST Co., Ltd. +F0A764 (base 16) GST Co., Ltd. + #988-6, Gosaek-Dong, Gwonseon-Gu + Suwon-Si Gyeonggi-Do 441-813 + KR + +1C-06-56 (hex) IDY Corporation +1C0656 (base 16) IDY Corporation + IDEMITSU Korakuen Bld 9F + Bunkyo-ku Tokyo 112-0002 + JP + +50-0E-6D (hex) TrafficCast International +500E6D (base 16) TrafficCast International + 2801 Coho Street + Madison WI 53713 + US + +EC-3B-F0 (hex) NovelSat +EC3BF0 (base 16) NovelSat + Hataasia 21 + Raanana 2396 + IL + +4C-ED-DE (hex) ASKEY COMPUTER CORP +4CEDDE (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +E8-E0-8F (hex) GRAVOTECH MARKING SAS +E8E08F (base 16) GRAVOTECH MARKING SAS + 56 AVENUE JEAN JAURES + LA CHAPELLE SAINT LUC AUBE 10600 + FR + +AC-AB-8D (hex) Lyngso Marine A/S +ACAB8D (base 16) Lyngso Marine A/S + Lyngso Alle 2 + Horsholm DK-2970 + DK + +60-83-B2 (hex) GkWare e.K. +6083B2 (base 16) GkWare e.K. + Hatzper Str. 172B + Essen NRW 45149 + DE + +80-D0-19 (hex) Embed, Inc +80D019 (base 16) Embed, Inc + 410 Great Road + Littleton MA 01460 + US + +68-EB-C5 (hex) Angstrem Telecom +68EBC5 (base 16) Angstrem Telecom + Yuzhnaya promzona, passage 4806, 4, build 3 + Zelenograd Moscow 124460 + RU + +A0-B5-DA (hex) HongKong THTF Co., Ltd +A0B5DA (base 16) HongKong THTF Co., Ltd + 2F,Sector C of Tsinghua University Academy, + Shenzhen Guangdong 518057 + CN + +88-86-A0 (hex) Simton Technologies, Ltd. +8886A0 (base 16) Simton Technologies, Ltd. + 2 Taishan Road, Building C, 3rd Floor + Wuxi, Province of Jiangsu, 214028 + CN + +A4-50-55 (hex) BUSWARE.DE +A45055 (base 16) BUSWARE.DE + Lindenstrasse 18 + Scharbeutz 23684 + DE + +A8-9B-10 (hex) inMotion Ltd. +A89B10 (base 16) inMotion Ltd. + Unit 2709 Exchange Tower + KLN + HK + +B4-14-89 (hex) Cisco Systems, Inc +B41489 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A4-A8-0F (hex) Shenzhen Coship Electronics Co., Ltd. +A4A80F (base 16) Shenzhen Coship Electronics Co., Ltd. + Rainbow Bldg., North, Hi-Tech Industrial Park, Nanshan District, + Shenzhen Guangdong 518057 + CN + +F8-B5-99 (hex) Guangzhou CHNAVS Digital Technology Co.,Ltd +F8B599 (base 16) Guangzhou CHNAVS Digital Technology Co.,Ltd + Buliding C, industy base of digital home application and demonstration ,zhongyi road Guangzhou higher education mega center + Guangzhou Guangdong 510006 + CN + +B8-92-1D (hex) BG T&A +B8921D (base 16) BG T&A + 4F, L&C Tower + Gunpo-si Gyeonggi-do 435-845 + KR + +D0-89-99 (hex) APCON, Inc. +D08999 (base 16) APCON, Inc. + 9255 SW Pioneer Court + Wilsonville OR 97070 + US + +C8-84-47 (hex) Beautiful Enterprise Co., Ltd +C88447 (base 16) Beautiful Enterprise Co., Ltd + 26th Floor, Beautiful Group Tower + + HK + +54-FD-BF (hex) Scheidt & Bachmann GmbH +54FDBF (base 16) Scheidt & Bachmann GmbH + Breite Strasse 132 + Moenchengladbach NRW 41238 + DE + +D0-BB-80 (hex) SHL Telemedicine International Ltd. +D0BB80 (base 16) SHL Telemedicine International Ltd. + 90 Yigal Alon + Tel Aviv 67891 + IL + +5C-17-D3 (hex) LGE +5C17D3 (base 16) LGE + 60-39 , Kasan -dong , Gumcheon-gu. + Seoul 153-801 + KR + +1C-DF-0F (hex) Cisco Systems, Inc +1CDF0F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +68-BD-AB (hex) Cisco Systems, Inc +68BDAB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +9C-AD-EF (hex) Obihai Technology, Inc. +9CADEF (base 16) Obihai Technology, Inc. + 2105 S. Bascom Ave #285 + Campbell CA 95008 + US + +C8-8B-47 (hex) Nolangroup S.P.A con Socio Unico +C88B47 (base 16) Nolangroup S.P.A con Socio Unico + via Terzi di S.Agata 2 + Brembate di Sopra Bergamo 24030 + IT + +C4-CD-45 (hex) Beijing Boomsense Technology CO.,LTD. +C4CD45 (base 16) Beijing Boomsense Technology CO.,LTD. + 803 Building 4 INTERWEST Business Center,No.9 South Shouti Road ,HaidianDistrict, + Beijing 100048 + CN + +8C-E7-B3 (hex) Sonardyne International Ltd +8CE7B3 (base 16) Sonardyne International Ltd + Blackbushe Business Park + Yateley Hampshire GU46 6GD + GB + +08-8D-C8 (hex) Ryowa Electronics Co.,Ltd +088DC8 (base 16) Ryowa Electronics Co.,Ltd + 1483-1 Takahara-machi + Yamagata-shi Yamagata-pref. 9900002 + JP + +80-C6-CA (hex) Endian s.r.l. +80C6CA (base 16) Endian s.r.l. + Pillhof 47 + Frangarto Bolzano 39010 + IT + +70-76-F0 (hex) LevelOne Communications (India) Private Limited +7076F0 (base 16) LevelOne Communications (India) Private Limited + 2F, Lane 1, 45 Bharat Nagar + New Delhi DELHI 110025 + IN + +C0-2B-FC (hex) iNES. applied informatics GmbH +C02BFC (base 16) iNES. applied informatics GmbH + Ohmstrasse 9 + Ludwigsburg 71642 + DE + +94-C7-AF (hex) Raylios Technology +94C7AF (base 16) Raylios Technology + 12F., No.16, Jian 8th Rd + Zhonghe City Taipei County 23511 + TW + +D8-1C-14 (hex) Compacta International, Ltd. +D81C14 (base 16) Compacta International, Ltd. + 31342 Via Las Palmas + San Juan Capistrano CA 92675 + US + +00-8C-10 (hex) Black Box Corp. +008C10 (base 16) Black Box Corp. + 1000 Park Drive + Lawrence PA 15055 + US + +90-90-3C (hex) TRISON TECHNOLOGY CORPORATION +90903C (base 16) TRISON TECHNOLOGY CORPORATION + No.3, Kung-Yeh 12th Rd., Ping-Jen Industrial Park, + Ping-Jen City, TaoYuan County 32459 + TW + +E0-61-B2 (hex) HANGZHOU ZENOINTEL TECHNOLOGY CO., LTD +E061B2 (base 16) HANGZHOU ZENOINTEL TECHNOLOGY CO., LTD + Room 806, F#, Cambridge Combridge, Shenhua Road,District Xihu, + Hangzhou Zhejiang 310030 + CN + +94-11-DA (hex) ITF Fröschl GmbH +9411DA (base 16) ITF Fröschl GmbH + Hauserbachstraße 9 + Walderbach Bavaria 93194 + DE + +80-39-E5 (hex) PATLITE CORPORATION +8039E5 (base 16) PATLITE CORPORATION + 19-2 + SANDA HYOUGOKEN 669-1339 + JP + +DC-7B-94 (hex) Cisco Systems, Inc +DC7B94 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +5C-CA-32 (hex) Theben AG +5CCA32 (base 16) Theben AG + Hohenbergstraße 32 + Haigerloch Baden-Württemberg 72401 + DE + +74-15-E2 (hex) Tri-Sen Systems Corporation +7415E2 (base 16) Tri-Sen Systems Corporation + 17625 El Camino Real Suite 200 + Houston TX 77058 + US + +EC-C3-8A (hex) Accuenergy (CANADA) Inc +ECC38A (base 16) Accuenergy (CANADA) Inc + 2 Lansing Square, Suite 503 + Toronto Ontario M2J 4P8 + CA + +D4-8F-AA (hex) Sogecam Industrial, S.A. +D48FAA (base 16) Sogecam Industrial, S.A. + Rosalind Franklin, 22-24 + Malaga 29590 + ES + +B0-81-D8 (hex) I-sys Corp +B081D8 (base 16) I-sys Corp + 2457 Aviation Ave + N. Charleston South Carolina 29406 + US + +14-FE-AF (hex) SAGITTAR LIMITED +14FEAF (base 16) SAGITTAR LIMITED + 2-102, BLD34, BAIWANGMOLIYUAN + BEIJING 100094 + CN + +B0-B8-D5 (hex) Nanjing Nengrui Auto Equipment CO.,Ltd +B0B8D5 (base 16) Nanjing Nengrui Auto Equipment CO.,Ltd + No.108 Ganjiabian East Yaohua Town + Nanjing Jiangsu 210046 + CN + +94-E7-11 (hex) Xirka Dama Persada PT +94E711 (base 16) Xirka Dama Persada PT + Gdg CM + Jakarta 13150 + ID + +6C-9B-02 (hex) Nokia Corporation +6C9B02 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +64-1E-81 (hex) Dowslake Microsystems +641E81 (base 16) Dowslake Microsystems + 21 High Street, Suite 306 + North Andover MA 01845 + US + +EC-54-2E (hex) Shanghai XiMei Electronic Technology Co. Ltd +EC542E (base 16) Shanghai XiMei Electronic Technology Co. Ltd + Room 503, No.2623, GongHeXin Road + Shanghai 200072 + CN + +FC-D4-F6 (hex) Messana Air.Ray Conditioning s.r.l. +FCD4F6 (base 16) Messana Air.Ray Conditioning s.r.l. + Via Venezia 18 + Oderzo TV 31046 + IT + +D4-66-A8 (hex) Riedo Networks Ltd +D466A8 (base 16) Riedo Networks Ltd + Route de la Fonderie 6 + Fribourg 1700 + CH + +F0-E5-C3 (hex) Drägerwerk AG & Co. KG aA +F0E5C3 (base 16) Drägerwerk AG & Co. KG aA + Moislinger Allee 53-55 + Luebeck Germany 23452 + DE + +D8-29-86 (hex) Best Wish Technology LTD +D82986 (base 16) Best Wish Technology LTD + 7E,Hai Yi Business Building,No.310,Tianshan RD., + Shanghai 200336 + CN + +44-61-32 (hex) ecobee inc +446132 (base 16) ecobee inc + 333 Adelaide St W 6th Floor + Toronto Ontario M5V1R5 + CA + +F4-1F-0B (hex) YAMABISHI Corporation +F41F0B (base 16) YAMABISHI Corporation + 3-14-12 Kamigou + Ebina-city KANAGAWA 243-0434 + JP + +A0-82-C7 (hex) P.T.I Co.,LTD +A082C7 (base 16) P.T.I Co.,LTD + 1-5-1,Tsurumidan + Koriyama-shi Fukushima 963-8861 + JP + +04-36-04 (hex) Gyeyoung I&T +043604 (base 16) Gyeyoung I&T + 6F, Woosung Bldg. 1000-1, Daechi-dong + Seoul 135-502 + KR + +A4-B2-A7 (hex) Adaxys Solutions AG +A4B2A7 (base 16) Adaxys Solutions AG + Eichtalstrasse 55 + Hombrechtikon CH 8634 + CH + +D0-D0-FD (hex) Cisco Systems, Inc +D0D0FD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E0-5B-70 (hex) Innovid, Co., Ltd. +E05B70 (base 16) Innovid, Co., Ltd. + 5th Floor, Boga Building, 821-3, Bangbaedong, Seochogu + Seoul 137-060 + KR + +14-1B-BD (hex) Volex Inc. +141BBD (base 16) Volex Inc. + 915 Tate Blvd. SE + Hickory NC 28602 + US + +E8-7A-F3 (hex) S5 Tech S.r.l. +E87AF3 (base 16) S5 Tech S.r.l. + Via Tortona 72 + Milano 20144 + IT + +CC-5C-75 (hex) Weightech Com. Imp. Exp. Equip. Pesagem Ltda +CC5C75 (base 16) Weightech Com. Imp. Exp. Equip. Pesagem Ltda + Rodovia Virgílio Várzea, 3110 - Sala 01 + Florianópolis SC 88032-001 + BR + +1C-6F-65 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +1C6F65 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + + Pin-Jen Taoyuan 324 + TW + +90-E0-F0 (hex) IEEE 1722a Working Group +90E0F0 (base 16) IEEE 1722a Working Group + 8760 Sandy Parkway + Sandy Utah 84070 + US + +40-52-0D (hex) Pico Technology +40520D (base 16) Pico Technology + James House, Marlborough Road + St Neots Cambridgeshire PE19 8YP + GB + +80-7D-1B (hex) Neosystem Co. Ltd. +807D1B (base 16) Neosystem Co. Ltd. + 4-19-12 Takao + Dazaifu-shi Fukuoka 818-0122 + JP + +18-B2-09 (hex) Torrey Pines Logic, Inc +18B209 (base 16) Torrey Pines Logic, Inc + 12651 High Bluff Drive, #100 + San Diego CA 92130 + US + +D8-4B-2A (hex) Cognitas Technologies, Inc. +D84B2A (base 16) Cognitas Technologies, Inc. + 6406 Laurel Bush Ln. + Sugar Land Texas 77479 + US + +68-4B-88 (hex) Galtronics Telemetry Inc. +684B88 (base 16) Galtronics Telemetry Inc. + 31 Lupi Ct + Palm Coast Florida 32137 + US + +98-FC-11 (hex) Cisco-Linksys, LLC +98FC11 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +34-E0-D7 (hex) DONGGUAN QISHENG ELECTRONICS INDUSTRIAL CO., LTD +34E0D7 (base 16) DONGGUAN QISHENG ELECTRONICS INDUSTRIAL CO., LTD + XINJI INDUSTRIAL ZONE, MACHONG TOWN + DONGGUAN GUANGDONG 523123 + CN + +D8-46-06 (hex) Silicon Valley Global Marketing +D84606 (base 16) Silicon Valley Global Marketing + 830 Stewart Dr. #201 + Sunnyvale Ca 94085 + US + +F8-AC-6D (hex) Deltenna Ltd +F8AC6D (base 16) Deltenna Ltd + First Floor Unit 2 + Chippenham Wiltshire SN15 1BN + GB + +F4-50-EB (hex) Telechips Inc +F450EB (base 16) Telechips Inc + KORAD Bldg,1000-12, Daechi-Dong, Gangnam-Gu, + Seoul 135-280 + KR + +98-8E-DD (hex) TE Connectivity Limerick +988EDD (base 16) TE Connectivity Limerick + International Science Centre, Block 1 + Castletroy Co. Limerick + IE + +A4-AE-9A (hex) Maestro Wireless Solutions ltd. +A4AE9A (base 16) Maestro Wireless Solutions ltd. + 3603-9, 36/F + Sai Ying Pun + HK + +C8-48-F5 (hex) MEDISON Xray Co., Ltd +C848F5 (base 16) MEDISON Xray Co., Ltd + 3F Burim B/D 999 Daechi-dong + Seoul 135-280 + KR + +78-A7-14 (hex) Amphenol +78A714 (base 16) Amphenol + 20 Valley St. + Endicott New York 13760 + US + +F8-93-F3 (hex) VOLANS +F893F3 (base 16) VOLANS + 3F IJU BD 770-13 YEOKSAM-DONG + SEOUL 135-928 + KR + +78-66-AE (hex) ZTEC Instruments, Inc. +7866AE (base 16) ZTEC Instruments, Inc. + 7715 Tiburon St. NE + Albuquerque NM 87109 + US + +4C-02-2E (hex) CMR KOREA CO., LTD +4C022E (base 16) CMR KOREA CO., LTD + 6F, J-Tower, 24-5 Bangi-dong, Songpa-Gu + Seoul 138-050 + KR + +34-AA-EE (hex) Mikrovisatos Servisas UAB +34AAEE (base 16) Mikrovisatos Servisas UAB + Savanoriu pr. 125 + Kaunas LT44146 + LT + +44-D6-3D (hex) Talari Networks +44D63D (base 16) Talari Networks + 3200 Glen Royal Rd. + Raleigh NC 27617 + US + +78-A2-A0 (hex) Nintendo Co., Ltd. +78A2A0 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +48-FC-B8 (hex) Woodstream Corporation +48FCB8 (base 16) Woodstream Corporation + 69 N. Locust Street + Lititz PA 17543 + US + +D4-00-0D (hex) Phoenix Broadband Technologies, LLC. +D4000D (base 16) Phoenix Broadband Technologies, LLC. + 589 Bethlehem Pike + Montgomeryville PA 18936 + US + +AC-51-35 (hex) MPI TECH +AC5135 (base 16) MPI TECH + Vadstrupvej 35 + Bagsværd DK-2880 + DK + +74-B9-EB (hex) JinQianMao Technology Co.,Ltd. +74B9EB (base 16) JinQianMao Technology Co.,Ltd. + Room 506 YongHeng Building NO.58 JiangBing Raod + FuZhou FuJian 350005 + CN + +D4-52-97 (hex) nSTREAMS Technologies, Inc. +D45297 (base 16) nSTREAMS Technologies, Inc. + 10F-2, No. 302, Ruiguang Rd., Neihu District, + Taipei City 114 + TW + +18-80-CE (hex) Barberry Solutions Ltd +1880CE (base 16) Barberry Solutions Ltd + 2/13 Naviti Place + Auckland 0630 + NZ + +24-B6-B8 (hex) FRIEM SPA +24B6B8 (base 16) FRIEM SPA + Via Edison 1 + Segrate Milano 20090 + IT + +A4-56-1B (hex) MCOT Corporation +A4561B (base 16) MCOT Corporation + Yogohigashi 1-5-12 + Matsuyama city Ehime prefecture 790-0044 + JP + +80-C6-3F (hex) Remec Broadband Wireless , LLC +80C63F (base 16) Remec Broadband Wireless , LLC + 17034 Camino San Bernardo + San Diego CA 92127 + US + +40-D4-0E (hex) Biodata Ltd +40D40E (base 16) Biodata Ltd + 10 Stocks Street + Manchester M8 8QG + GB + +0C-82-6A (hex) Wuhan Huagong Genuine Optics Technology Co., Ltd +0C826A (base 16) Wuhan Huagong Genuine Optics Technology Co., Ltd + Science & Technology Region of HUST, Donghu High-Tech Zone + Wuhan Hubei 430223 + CN + +E0-27-1A (hex) TTC Next-generation Home Network System WG +E0271A (base 16) TTC Next-generation Home Network System WG + 1-1-12 Shiba Kouen + Minato-ku Tokyo 105-0011 + JP + +00-97-FF (hex) Heimann Sensor GmbH +0097FF (base 16) Heimann Sensor GmbH + Maria-Reiche-Str. 1 + Dresden Sachsen 01109 + DE + +E4-AB-46 (hex) UAB Selteka +E4AB46 (base 16) UAB Selteka + Draugystës g. 19 + Kaunas LT-51230 + LT + +94-5B-7E (hex) TRILOBIT LTDA. +945B7E (base 16) TRILOBIT LTDA. + R. ALVARENGA 1377 + São Paulo 05509002 + BR + +04-E5-48 (hex) Cohda Wireless Pty Ltd +04E548 (base 16) Cohda Wireless Pty Ltd + Suite 5 / 83 Fullarton Road + Kent Town South Australia 5067 + AU + +70-71-BC (hex) PEGATRON CORPORATION +7071BC (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +78-84-EE (hex) INDRA ESPACIO S.A. +7884EE (base 16) INDRA ESPACIO S.A. + C/ ROC BORONAT, 133 + BARCELONA 08018 + ES + +7C-05-1E (hex) RAFAEL LTD. +7C051E (base 16) RAFAEL LTD. + GUSH SEGEV POB 2250 + HAIFA 31008 + IL + +10-09-0C (hex) Janome Sewing Machine Co., Ltd. +10090C (base 16) Janome Sewing Machine Co., Ltd. + 1463 Hazama-Machi + Hachioji-Shi Tokyo 193-0941 + JP + +E0-1C-EE (hex) Bravo Tech, Inc. +E01CEE (base 16) Bravo Tech, Inc. + 6185 Phyllis Dr. Unit D. + Cypress CA 90630 + US + +28-93-FE (hex) Cisco Systems, Inc +2893FE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F4-C7-95 (hex) WEY Elektronik AG +F4C795 (base 16) WEY Elektronik AG + Dorfstrasse 57 + Unterengstringen Zurich 8103 + CH + +78-11-85 (hex) NBS Payment Solutions Inc. +781185 (base 16) NBS Payment Solutions Inc. + 703 Evans Ave + Toronto Ontario M9C 5E9 + CA + +D0-58-75 (hex) Active Control Technology Inc. +D05875 (base 16) Active Control Technology Inc. + 1800 Appleby Line + Burlington Ontario L7L 6A1 + CA + +C8-EF-2E (hex) Beijing Gefei Tech. Co., Ltd +C8EF2E (base 16) Beijing Gefei Tech. Co., Ltd + A-603 Power Creative Plaza, NO.1 Shangdi E. Rd.,Haidian District, + Beijing 100085 + CN + +08-F6-F8 (hex) GET Engineering +08F6F8 (base 16) GET Engineering + 9350 Bond Ave + El Cajon CA 92021 + US + +3C-4C-69 (hex) Infinity System S.L. +3C4C69 (base 16) Infinity System S.L. + Crtra. N-II, Km 48,5 Pol. Ind. Cabanillas del Campo, Parc. 12B + Guadalajara 19171 + US + +78-30-E1 (hex) UltraClenz, LLC +7830E1 (base 16) UltraClenz, LLC + 1440 W Indiantown Road + Jupiter FL 33458 + US + +B0-91-34 (hex) Taleo +B09134 (base 16) Taleo + 4140 Dublin Blvd + Dublin California 94568 + US + +A4-C2-AB (hex) Hangzhou LEAD-IT Information & Technology Co.,Ltd +A4C2AB (base 16) Hangzhou LEAD-IT Information & Technology Co.,Ltd + F2 Builder B,Xidomen Road NO.22 + Hangzhou Zhejiang 310012 + CN + +48-AA-5D (hex) Store Electronic Systems +48AA5D (base 16) Store Electronic Systems + 39 rue de montigny + Argenteuil 95100 + FR + +04-2F-56 (hex) ATOCS (Shenzhen) LTD +042F56 (base 16) ATOCS (Shenzhen) LTD + 4/F., Building 10, Tongfuyu Industry Zone, Xili Town, + Shenzhen + CN + +E8-5E-53 (hex) Infratec Datentechnik GmbH +E85E53 (base 16) Infratec Datentechnik GmbH + Gevener Weg 38 + Neuenrade NRW 58579 + DE + +88-BA-7F (hex) Qfiednet Co., Ltd. +88BA7F (base 16) Qfiednet Co., Ltd. + #204 KJ Bldg. DaeChi-Dong + Seoul 135-847 + KR + +64-DB-18 (hex) OpenPattern +64DB18 (base 16) OpenPattern + 109/111 rue des Côtes + Maisons Laffitte Yvelines 78600 + FR + +90-A2-DA (hex) GHEO SA +90A2DA (base 16) GHEO SA + Via Soldini, 22 + Chiasso CH-6830 + CH + +98-89-ED (hex) Anadem Information Inc. +9889ED (base 16) Anadem Information Inc. + 2nd F, 79 Zhouzi Street, Neihu District, + Taipei 114 + TW + +D8-1B-FE (hex) TWINLINX CORPORATION +D81BFE (base 16) TWINLINX CORPORATION + ESPACE DESCARTES BAT B + AIX EN PROVENCE PROVENCE 13857 + FR + +FC-44-63 (hex) Universal Audio, Inc +FC4463 (base 16) Universal Audio, Inc + 4585 Scotts Valley Dr. + Scotts Valley CA 95066 + US + +10-2D-96 (hex) Looxcie Inc. +102D96 (base 16) Looxcie Inc. + 1196 Borregas Ave. + Sunnyvale CA 94089 + US + +5C-35-DA (hex) There Corporation Oy +5C35DA (base 16) There Corporation Oy + Elimäenkatu 5 + Helsinki 00510 + FI + +A0-69-86 (hex) Wellav Technologies Ltd +A06986 (base 16) Wellav Technologies Ltd + 15F Desay Building + Huizhou Guangdong 516003 + CN + +EC-8E-AD (hex) DLX +EC8EAD (base 16) DLX + #401, Seoil B/D,1359-45 Seocho2-dong + Seoul 137-863 + KR + +34-C6-9A (hex) Enecsys Ltd +34C69A (base 16) Enecsys Ltd + Harston Mill + Cambridge Cambridgeshire CB22 7GG + GB + +D8-AE-90 (hex) Itibia Technologies +D8AE90 (base 16) Itibia Technologies + 5 Clausen Ct + West Windsor NJ 08550 + US + +B8-65-3B (hex) Bolymin, Inc. +B8653B (base 16) Bolymin, Inc. + 13F-1, No.20, Ta-Long Rd., + Taichung 40310 + TW + +38-E8-DF (hex) b gmbh medien + datenbanken +38E8DF (base 16) b gmbh medien + datenbanken + Kurfuerstenstrasse 22 + Ludwigsburg BW 71636 + DE + +1C-12-9D (hex) IEEE PES PSRC/SUB +1C129D (base 16) IEEE PES PSRC/SUB + Working Group H7/Sub C7 (IEEE PC37.238) + Piscataway NJ 08854 + US + +E0-CA-4D (hex) Shenzhen Unistar Communication Co.,LTD +E0CA4D (base 16) Shenzhen Unistar Communication Co.,LTD + 9/F,Qinghai Building,7043, Berhuan Road, Futian District, + Shenzhen Guangdong 518034 + CN + +0C-C9-C6 (hex) Samwin Hong Kong Limited +0CC9C6 (base 16) Samwin Hong Kong Limited + Rm 901-902, 9/F, Futura Plaza, + Hong Kong + CN + +10-62-C9 (hex) Adatis GmbH & Co. KG +1062C9 (base 16) Adatis GmbH & Co. KG + Forchheimer Straße 6 + Nürnberg Bavaria 90425 + DE + +60-B3-C4 (hex) Elber Srl +60B3C4 (base 16) Elber Srl + via Pontevecchio 42 W + Carasco Ge 16042 + IT + +04-C8-80 (hex) Samtec Inc +04C880 (base 16) Samtec Inc + 520 Park East Blvd + New Albany IN 47150 + US + +F8-8D-EF (hex) Tenebraex +F88DEF (base 16) Tenebraex + 27 Drydock Avenue + Boston MA 02210 + US + +04-22-34 (hex) Wireless Standard Extensions +042234 (base 16) Wireless Standard Extensions + 1322 Crossman avenue + Sunnyvale California 94089 + US + +F0-B6-EB (hex) Poslab Technology Co., Ltd. +F0B6EB (base 16) Poslab Technology Co., Ltd. + 5F-1, No.490 Bannan Rd. + Jhonghe City 235 + TW + +80-C8-62 (hex) Openpeak, Inc +80C862 (base 16) Openpeak, Inc + 1750 Clint Moore Rd + Boca Raton Florida 33487 + US + +1C-8F-8A (hex) Phase Motion Control SpA +1C8F8A (base 16) Phase Motion Control SpA + via Adamoli, 461 + Genova IT16141 + IT + +FC-CC-E4 (hex) Ascon Ltd. +FCCCE4 (base 16) Ascon Ltd. + 1-15-27 Minato-machi + Fukuyama –shi Hiroshima-ken 721-0964 + JP + +58-50-E6 (hex) Best Buy Corporation +5850E6 (base 16) Best Buy Corporation + 7601 Penn Ave South + Richfield MN 55423 + US + +3C-1C-BE (hex) JADAK LLC +3C1CBE (base 16) JADAK LLC + 7279 William Barry Blvd + North Syracuse NY 13212 + US + +BC-D5-B6 (hex) d2d technologies +BCD5B6 (base 16) d2d technologies + 10611 roundwood glen ct + Jacksonville Fl 32256 + US + +FC-68-3E (hex) Directed Perception, Inc +FC683E (base 16) Directed Perception, Inc + 890C Cowan Road + Burlingame California 94010 + US + +28-E7-94 (hex) Microtime Computer Inc. +28E794 (base 16) Microtime Computer Inc. + 4F, No. 222, Sec. 4, Cheng-Teh Rd., + Taipei 11167 + TW + +0C-D5-02 (hex) Westell Technologies Inc. +0CD502 (base 16) Westell Technologies Inc. + 750 N Commons Dr + Aurora IL 60504 + US + +70-82-8E (hex) OleumTech Corporation +70828E (base 16) OleumTech Corporation + 23 Hubble + Irvine CA 92618 + US + +A4-38-FC (hex) Plastic Logic +A438FC (base 16) Plastic Logic + 650 Castro St., Suite 500 + Mountain View CA 94041 + US + +18-FC-9F (hex) Changhe Electronics Co., Ltd. +18FC9F (base 16) Changhe Electronics Co., Ltd. + 6th Floor, Building B, Dajiahao Square, Yu¡¯an 1st Road, Bao¡¯an, + Shenzhen Guangdong 518101 + CN + +94-59-2D (hex) EKE Building Technology Systems Ltd +94592D (base 16) EKE Building Technology Systems Ltd + Piispanportti 7 + Espoo - 02240 + US + +CC-69-B0 (hex) Global Traffic Technologies, LLC +CC69B0 (base 16) Global Traffic Technologies, LLC + 7800 Third Street North + St. Paul Minnesota 55128 + US + +A0-59-3A (hex) V.D.S. Video Display Systems srl +A0593A (base 16) V.D.S. Video Display Systems srl + Via Del Pantano 71 + SCANDICCI FI 50018 + IT + +CC-EA-1C (hex) DCONWORKS Co., Ltd +CCEA1C (base 16) DCONWORKS Co., Ltd + 182-13 Daerung Post Tower 2nd 5F + Seoul 152-847 + KR + +7C-08-D9 (hex) Shanghai B-Star Technology Co +7C08D9 (base 16) Shanghai B-Star Technology Co + 1158 Xiehe Road + Shanghai 200335 + CN + +20-59-A0 (hex) Paragon Technologies Inc. +2059A0 (base 16) Paragon Technologies Inc. + 68 North 4th Ring Rd West, + Beijing 100080 + CN + +38-E9-8C (hex) Reco S.p.A. +38E98C (base 16) Reco S.p.A. + via dell'Industria, 8 + Montano Lucino CO 22070 + IT + +A0-BF-A5 (hex) CORESYS +A0BFA5 (base 16) CORESYS + 267-1 Nonhyundong Gangnamgu + Seoul 135-833 + KR + +B0-5B-1F (hex) THERMO FISHER SCIENTIFIC S.P.A. +B05B1F (base 16) THERMO FISHER SCIENTIFIC S.P.A. + STRADA RIVOLTANA KM 6/7 + RODANO MILAN 20090 + IT + +24-D2-CC (hex) SmartDrive Systems Inc. +24D2CC (base 16) SmartDrive Systems Inc. + 9276 Scranton Road + San Diego CA 92121 + US + +0C-EF-7C (hex) AnaCom Inc +0CEF7C (base 16) AnaCom Inc + 1996 Lundy Ave + San Jose CA 95131 + US + +EC-E9-F8 (hex) Guang Zhou TRI-SUN Electronics Technology Co., Ltd +ECE9F8 (base 16) Guang Zhou TRI-SUN Electronics Technology Co., Ltd + 9th floor Guangzhou info port building B, Keyun Road, Tianhe District, Guangzhou ,PRC + Guangzhou Guangdong 510665 + CN + +34-CE-94 (hex) Parsec (Pty) Ltd +34CE94 (base 16) Parsec (Pty) Ltd + Building 8-10 Manhattan Office Park + Centurion Gauteng 0157 + ZA + +34-EF-8B (hex) NTT Communications Corporation +34EF8B (base 16) NTT Communications Corporation + NTT Hibiya Bldg. 7F + Chiyoda-ku Tokyo 100-8019 + JP + +68-7F-74 (hex) Cisco-Linksys, LLC +687F74 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +D0-D2-86 (hex) Beckman Coulter K.K. +D0D286 (base 16) Beckman Coulter K.K. + 454-32 Higashino, + Nagaizumi-cho, Sunto-gun, Shizuoka-ken 411-0943 + JP + +C4-19-8B (hex) Dominion Voting Systems Corporation +C4198B (base 16) Dominion Voting Systems Corporation + 215 Spadina Avenue + Toronto Ontario M5T 2C7 + CA + +C8-3A-35 (hex) Tenda Technology Co., Ltd. +C83A35 (base 16) Tenda Technology Co., Ltd. + Room 601-602,R/D Building Complex,Tsinghua High-Tech Park,nanshan district + Shenzhen Guandong 518057 + CN + +6C-8C-DB (hex) Otus Technologies Ltd +6C8CDB (base 16) Otus Technologies Ltd + 26 Braid Road + Edinburgh Morningside EH10 6AD + GB + +40-F5-2E (hex) Leica Microsystems (Schweiz) AG +40F52E (base 16) Leica Microsystems (Schweiz) AG + Max Schmidheiny-Strasse 201 + Heerbrugg SG 9435 + CH + +E4-FF-DD (hex) ELECTRON INDIA +E4FFDD (base 16) ELECTRON INDIA + TYPE II, NO.9, DR. V.S.I. ESTATE + CHENNAI TAMIL NADU 600 041 + IN + +68-A1-B7 (hex) Honghao Mingchuan Technology (Beijing) CO.,Ltd. +68A1B7 (base 16) Honghao Mingchuan Technology (Beijing) CO.,Ltd. + Floor 8,Tower A, Wanliu Yicheng Building + Beijing 100089 + CN + +0C-D7-C2 (hex) Axium Technologies, Inc. +0CD7C2 (base 16) Axium Technologies, Inc. + 6625 N. Calle Eva Miranda + Irwindale CA 91702 + US + +E8-4E-CE (hex) Nintendo Co., Ltd. +E84ECE (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +10-45-F8 (hex) LNT-Automation GmbH +1045F8 (base 16) LNT-Automation GmbH + Hans-Paul-Kaysser-Straße 1 + Leutenbach-Nellmersbach BW D-71397 + DE + +DC-E7-1C (hex) AUG Elektronik GmbH +DCE71C (base 16) AUG Elektronik GmbH + Kleinwoellmiss 53 + St. Martin a. W. Styria A-8580 + AT + +A8-70-A5 (hex) UniComm Inc. +A870A5 (base 16) UniComm Inc. + 7F-7, No. 716, Chung-Cheng Road, + Chung-Ho City Taipei Hsien 23500 + TW + +F8-47-2D (hex) X2gen Digital Corp. Ltd +F8472D (base 16) X2gen Digital Corp. Ltd + # 89, Singlong Rd + Pin-Jhen City, 324 + TW + +84-90-00 (hex) Arnold & Richter Cine Technik +849000 (base 16) Arnold & Richter Cine Technik + Tuerkenstrasse 89 + Munich Bavaria 80799 + DE + +08-18-4C (hex) A. S. Thomas, Inc. +08184C (base 16) A. S. Thomas, Inc. + 355 Providence Hwy + Westwood MA 02090 + US + +10-88-0F (hex) Daruma Telecomunicações e Informática S.A. +10880F (base 16) Daruma Telecomunicações e Informática S.A. + AVENIDA INDEPENDENCIA, 3500, LOTEAMENTO INDUSTRIAL + Taubaté São Paulo 12032-000 + BR + +FC-61-98 (hex) NEC Personal Products, Ltd +FC6198 (base 16) NEC Personal Products, Ltd + 6-80, Shimohanazawa 2-chome, + Yonezawa-shi Yamagata 992-8520 + JP + +74-D8-50 (hex) Evrisko Systems +74D850 (base 16) Evrisko Systems + 2322 Alpine Rd, Ste 10 + Eau Claire WI 54703 + US + +54-B6-20 (hex) SUHDOL E&C Co.Ltd. +54B620 (base 16) SUHDOL E&C Co.Ltd. + 920, Ilsan TechnoTown 1141-1, Baekseok-dong, Ilsandong-gu + Goyang-si Gyunggi-do 410-722 + KR + +78-C4-0E (hex) H&D Wireless +78C40E (base 16) H&D Wireless + Sjövägen 17 + Solna 169 55 + SE + +2C-06-23 (hex) Win Leader Inc. +2C0623 (base 16) Win Leader Inc. + Level 3 ,Alexander House, + Ebene + MU + +0C-27-55 (hex) Valuable Techologies Limited +0C2755 (base 16) Valuable Techologies Limited + 602, Centre Point, J.B.Nagar, + Mumbai Maharashtra 400059 + IN + +78-99-8F (hex) MEDILINE ITALIA SRL +78998F (base 16) MEDILINE ITALIA SRL + VIA 8 MARZO, 4 + CORTE TEGGE REGGIO NELL'EMILIA 42025 + IT + +40-EC-F8 (hex) Siemens AG +40ECF8 (base 16) Siemens AG + I IS MS EDM + Munich Germany 85630 + DE + +BC-B1-81 (hex) SHARP CORPORATION +BCB181 (base 16) SHARP CORPORATION + 22-22,Nagaike-cho, + Osaka, 545-8522, + JP + +C8-87-3B (hex) Net Optics +C8873B (base 16) Net Optics + 5303 Betsy Ross Drive + Santa Clara CA 95054 + US + +A8-CE-90 (hex) CVC +A8CE90 (base 16) CVC + No.361,Renhua Rd., + Dali City Taichung 412 + TW + +E4-1F-13 (hex) IBM Corp +E41F13 (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +70-1A-ED (hex) ADVAS CO., LTD. +701AED (base 16) ADVAS CO., LTD. + 3-8-8 Shin-yokohama, Kohoku-ku + Yokohama-shi Kanagawa-ken 222-0033 + JP + +64-65-C0 (hex) Nuvon, Inc +6465C0 (base 16) Nuvon, Inc + 3130 Alpine Road + Portola Valley California 94028 + US + +7C-1E-B3 (hex) 2N TELEKOMUNIKACE a.s. +7C1EB3 (base 16) 2N TELEKOMUNIKACE a.s. + Modranska 621 + Prague 143 01 + CZ + +44-56-B7 (hex) Spawn Labs, Inc +4456B7 (base 16) Spawn Labs, Inc + 2209 Granger Lane + Austin TX 78613 + US + +44-C9-A2 (hex) Greenwald Industries +44C9A2 (base 16) Greenwald Industries + 212 Middlesex Avenue + Chester CT 06412 + US + +90-6D-C8 (hex) DLG Automação Industrial Ltda +906DC8 (base 16) DLG Automação Industrial Ltda + Rua José Batista Soares, 53 + Sertãozinho São Paulo 14176-119 + BR + +58-4C-EE (hex) Digital One Technologies, Limited +584CEE (base 16) Digital One Technologies, Limited + Room 2203, No.1 Shangdi Xinxi Road + Beijing 100085 + CN + +00-27-21 (hex) Shenzhen Baoan Fenda Industrial Co., Ltd +002721 (base 16) Shenzhen Baoan Fenda Industrial Co., Ltd + Fenda Hi-Tech Park + Baoan Shenzhen 518108 + CN + +A0-73-32 (hex) Cashmaster International Limited +A07332 (base 16) Cashmaster International Limited + Fairykirk Road + Rosyth Fife KY11 2QQ + GB + +64-C6-AF (hex) AXERRA Networks Ltd +64C6AF (base 16) AXERRA Networks Ltd + 24 Raoul Wallenberg St. , + Tel-Aviv ISRAEL 69719 + IL + +44-56-8D (hex) PNC Technologies Co., Ltd. +44568D (base 16) PNC Technologies Co., Ltd. + Development Center + Anyang Gyeonggi-Do 431-836 + KR + +40-61-86 (hex) MICRO-STAR INT'L CO.,LTD +406186 (base 16) MICRO-STAR INT'L CO.,LTD + No.69,Li-De St + Jung-Ho City Taipei Hsien 235 + TW + +00-26-F5 (hex) XRPLUS Inc. +0026F5 (base 16) XRPLUS Inc. + #805 Ace Techno Tower 2nd 197-17 + Seoul 152-766 + KR + +00-26-F8 (hex) Golden Highway Industry Development Co., Ltd. +0026F8 (base 16) Golden Highway Industry Development Co., Ltd. + Floor 7, Block 8, Vision Shenzhen Business Park, No.9 Gaoxin 9th South Road + Shenzhen City Guangdong Province 518057 + CN + +00-26-F4 (hex) Nesslab +0026F4 (base 16) Nesslab + 489-2 Maetan 3-dong, Yeong Tong-gu + Suwon-si Gyeonggi-do 443-803 + KR + +00-26-EE (hex) TKM GmbH +0026EE (base 16) TKM GmbH + Schlossstraße 123 + Mönchengladbach NRW 41238 + DE + +00-26-EF (hex) Technology Advancement Group, Inc. +0026EF (base 16) Technology Advancement Group, Inc. + 22355 Tag Way + Dulles VA 20166-9310 + US + +00-26-B2 (hex) Setrix GmbH +0026B2 (base 16) Setrix GmbH + Josephspitalstr. 15 + Muenchen Bayern 80331 + DE + +00-26-AF (hex) Duelco A/S +0026AF (base 16) Duelco A/S + Mommarkvej 5 + Soenderborg Soenderjylland DK6400 + DK + +00-26-B3 (hex) Thales Communications Inc +0026B3 (base 16) Thales Communications Inc + 22605 Gateway Center Drive + Clarksburg MD 20871 + US + +00-26-A7 (hex) CONNECT SRL +0026A7 (base 16) CONNECT SRL + Via Cernaia, 11 + Milan 20121 + IT + +00-26-A4 (hex) Novus Produtos Eletronicos Ltda +0026A4 (base 16) Novus Produtos Eletronicos Ltda + Rua Alvaro Chaves, 155 + Porto Alegre RS 90220-040 + BR + +00-26-D8 (hex) Magic Point Inc. +0026D8 (base 16) Magic Point Inc. + Suite 203, Building 17, No. 295 Lin Nan Road, Pudong Software Park Sanlin World Expo Block + Shanghai 2000126 + CN + +00-26-D6 (hex) Ningbo Andy Optoelectronic Co., Ltd. +0026D6 (base 16) Ningbo Andy Optoelectronic Co., Ltd. + Lanjiang Street Industrial Zone + Yuyao Zhejiang 315400 + CN + +00-27-0F (hex) Envisionnovation Inc +00270F (base 16) Envisionnovation Inc + 4 Wareham Drive + Mississauga Ontario L5M 1B6 + CA + +00-27-0A (hex) IEE S.A. +00270A (base 16) IEE S.A. + ZAE Weiergewan + Contern L-5326 + LU + +00-27-09 (hex) Nintendo Co., Ltd. +002709 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-26-D3 (hex) Zeno Information System +0026D3 (base 16) Zeno Information System + #1404 A-Dong Digital Empire Bldg, 980-3, Youngtong-dong, Youngtong-gu + Suwon City Gyeonggi-Do 443-702 + KR + +00-26-D1 (hex) S Squared Innovations Inc. +0026D1 (base 16) S Squared Innovations Inc. + 6807-104 Street + Edmonton AB T6H 2L5 + CA + +00-26-CB (hex) Cisco Systems, Inc +0026CB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-27-01 (hex) INCOstartec GmbH +002701 (base 16) INCOstartec GmbH + Rheinstraße 17 + Teltow Germany 14513 + DE + +00-26-FB (hex) AirDio Wireless, Inc. +0026FB (base 16) AirDio Wireless, Inc. + 13-5, No. 79, Sec. 1, Hsin Tai Wu Road + Hsichih City, Taipei County Taiwan 22101 + TW + +00-27-1A (hex) Geenovo Technology Ltd. +00271A (base 16) Geenovo Technology Ltd. + Unit 402, 4/F., Tower I,SHUI QING MU HUA YUAN, + Beijing 100080 + CN + +00-27-14 (hex) Grainmustards, Co,ltd. +002714 (base 16) Grainmustards, Co,ltd. + HEIWA MK Bldg,2-48-4,Nihonbashi-Hama-cho + Tokyo 103-0007 + JP + +00-27-15 (hex) Rebound Telecom. Co., Ltd +002715 (base 16) Rebound Telecom. Co., Ltd + 12F,Building No.82,No.1198,North Qinzhou Rd, + Shanghai 200233 + CN + +00-26-E6 (hex) Visionhitech Co., Ltd. +0026E6 (base 16) Visionhitech Co., Ltd. + Vision bldg. 150-3 + Buchon Kyunggi-Do 420-822 + KR + +00-26-DF (hex) TaiDoc Technology Corp. +0026DF (base 16) TaiDoc Technology Corp. + 7F, No. 127, Wugong 2nd Rd., 24888 Wugu Township + Taipei County Taiwan 24888 + TW + +00-26-6A (hex) ESSENSIUM NV +00266A (base 16) ESSENSIUM NV + Gaston Geenslaan 9 + LEUVEN VL BRABANT 3001 + BE + +00-26-6B (hex) SHINE UNION ENTERPRISE LIMITED +00266B (base 16) SHINE UNION ENTERPRISE LIMITED + UNIT 1211, 12FL., CHEVALIER COMMERCIAL CENTER, + KOWLOON NIL + HK + +00-26-67 (hex) CARECOM CO.,LTD. +002667 (base 16) CARECOM CO.,LTD. + 3-35-4 + Chofu Tokyo 182-0025 + JP + +00-26-A2 (hex) Instrumentation Technology Systems +0026A2 (base 16) Instrumentation Technology Systems + 19360 Business Center Drive + Northridge CA 91324 + US + +00-26-9F (hex) Private +00269F (base 16) Private + +00-26-99 (hex) Cisco Systems, Inc +002699 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-26-47 (hex) WFE TECHNOLOGY CORP. +002647 (base 16) WFE TECHNOLOGY CORP. + 17F NO.238,Chin-Hua N Rd, + Taichung 404 + TW + +00-26-40 (hex) Baustem Broadband Technologies, Ltd. +002640 (base 16) Baustem Broadband Technologies, Ltd. + 910 Quantum Plaza + Beijing 100191 + CN + +00-26-53 (hex) DaySequerra Corporation +002653 (base 16) DaySequerra Corporation + 154 Cooper Road + West Berlin NJ 08091 + US + +00-26-7B (hex) GSI Helmholtzzentrum für Schwerionenforschung GmbH +00267B (base 16) GSI Helmholtzzentrum für Schwerionenforschung GmbH + Planckstraße 1 + Darmstadt Hessen 64291 + DE + +00-26-87 (hex) corega K.K +002687 (base 16) corega K.K + 1-19-20, Shinyokohama + Yokohama-city Kanagawa-ken 222-0033 + JP + +00-26-8D (hex) CellTel S.p.A. +00268D (base 16) CellTel S.p.A. + Via Romano 72 + Scarmagno Torino 10010 + IT + +00-26-28 (hex) companytec automação e controle ltda. +002628 (base 16) companytec automação e controle ltda. + Rua Marcilio Dias 3005 + Pelotas Rio Grande do Sul 96020-480 + BR + +00-26-1F (hex) SAE Magnetics (H.K.) Ltd. +00261F (base 16) SAE Magnetics (H.K.) Ltd. + SAE Technology Centre + Hong Kong Science Park Shatin, New Territories + HK + +00-26-1E (hex) QINGBANG ELEC(SZ) CO., LTD +00261E (base 16) QINGBANG ELEC(SZ) CO., LTD + No. 2, qimin Rd. North District, High-tech Industrial Park, Nanshan, + Shenzhen Guangdong 518000 + CN + +00-26-19 (hex) FRC +002619 (base 16) FRC + 1511 South Benjamin Avenue + Mason City IA 50401 + US + +00-25-EA (hex) Iphion BV +0025EA (base 16) Iphion BV + Willemstraat 106 + Eindhoven 5616GE + NL + +00-25-F0 (hex) Suga Electronics Limited +0025F0 (base 16) Suga Electronics Limited + Units 1904-1907, Chevalier Commercial Centre, + Kowloon Bay Hong Kong + CN + +00-25-E8 (hex) Idaho Technology +0025E8 (base 16) Idaho Technology + 390 Wakara way + Salt Lake city UT 84108 + US + +00-25-E4 (hex) OMNI-WiFi, LLC +0025E4 (base 16) OMNI-WiFi, LLC + 70 Sullivan Street + Berwick Maine 03901 + US + +00-25-FC (hex) ENDA ENDUSTRIYEL ELEKTRONIK LTD. STI. +0025FC (base 16) ENDA ENDUSTRIYEL ELEKTRONIK LTD. STI. + Y. Dudullu Barbaros C. Kutup S. No. 20 + Istanbul 34775 + TR + +00-25-FA (hex) J&M Analytik AG +0025FA (base 16) J&M Analytik AG + Willy-Messerschmitt-Strasse 8 + Essingen BW 73457 + DE + +00-26-33 (hex) MIR - Medical International Research +002633 (base 16) MIR - Medical International Research + Via del Maggiolino 125 + Rome RM 00155 + IT + +00-25-D7 (hex) CEDO +0025D7 (base 16) CEDO + Videnska 127 + BRNO 61900 + CZ + +00-25-D8 (hex) KOREA MAINTENANCE +0025D8 (base 16) KOREA MAINTENANCE + 3F HAELIM BUIDING 103-7, GURO-5DONG + SEOUL 152-842 + KR + +00-25-D2 (hex) InpegVision Co., Ltd +0025D2 (base 16) InpegVision Co., Ltd + 226-3, Bugok-dong, Geumjeong-gu, + Busan 609-320 + KR + +00-26-30 (hex) ACOREL S.A.S +002630 (base 16) ACOREL S.A.S + 3, Rue Paul LANGEVIN + SAINT-PERAY F-07130 + FR + +00-26-2A (hex) Proxense, LLC +00262A (base 16) Proxense, LLC + 689 NW Stonepine Dr + Bend Oregon 97701 + US + +00-25-FE (hex) Pilot Electronics Corporation +0025FE (base 16) Pilot Electronics Corporation + No. 2, Tzu-Chiang 3rd Road, Chung-Li Industrial Zone, + Taoyuan Hsien 32063 + TW + +00-25-7B (hex) STJ ELECTRONICS PVT LTD +00257B (base 16) STJ ELECTRONICS PVT LTD + X-24 OKHLA INDUSTRIAL AREA + NEW DELHI DELHI 110 020 + IN + +00-25-7C (hex) Huachentel Technology Development Co., Ltd +00257C (base 16) Huachentel Technology Development Co., Ltd + 747 XinYu Rd. High-Tech Zone + Jinan Shandong Province 250101 + CN + +00-25-75 (hex) FiberPlex Technologies, LLC +002575 (base 16) FiberPlex Technologies, LLC + 10840-412 Guilford Rd + Annapolis Junction MD 20701 + US + +00-25-70 (hex) Eastern Communications Company Limited +002570 (base 16) Eastern Communications Company Limited + No.398 Wensan Road, + Hangzhou Zhejiang 310013 + CN + +00-25-9B (hex) Beijing PKUNITY Microsystems Technology Co., Ltd +00259B (base 16) Beijing PKUNITY Microsystems Technology Co., Ltd + 11th Floor, Resource Plaza, No.151 North Zhongguancun Street + Beijing 100080 + CN + +00-25-96 (hex) GIGAVISION srl +002596 (base 16) GIGAVISION srl + Via Figini, 16 + Muggiò Milano 20053 + IT + +00-25-95 (hex) Northwest Signal Supply, Inc +002595 (base 16) Northwest Signal Supply, Inc + 12965 SW Herman Rd + Tualatin OR 97062 + US + +00-25-C9 (hex) SHENZHEN HUAPU DIGITAL CO., LTD +0025C9 (base 16) SHENZHEN HUAPU DIGITAL CO., LTD + Futian District,Chegongmiao,TianAn Cyberpark + ShenZhen Guangdong Province 518040 + CN + +00-25-8F (hex) Trident Microsystems, Inc. +00258F (base 16) Trident Microsystems, Inc. + 3408 Garrett Drive + Santa Clara CA 95054 + US + +00-25-89 (hex) Hills Industries Limited +002589 (base 16) Hills Industries Limited + 5 Cambria Road + Melbourne VIC 3173 + AU + +00-25-85 (hex) KOKUYO S&T Co., Ltd. +002585 (base 16) KOKUYO S&T Co., Ltd. + 1-8-35 + Minato-ku Tokyo 108-8710 + JP + +00-25-81 (hex) x-star networks Inc. +002581 (base 16) x-star networks Inc. + 1F,NO1-2,Chungching S.Rd.Sec 3 + Taipei 10076 + TW + +00-25-B5 (hex) Cisco Systems, Inc +0025B5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-25-BE (hex) Tektrap Systems Inc. +0025BE (base 16) Tektrap Systems Inc. + 15 Buteau St. + Gatineau Quebec J8Z 1V4 + CA + +00-25-A0 (hex) Nintendo Co., Ltd. +0025A0 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-25-4D (hex) Singapore Technologies Electronics Limited +00254D (base 16) Singapore Technologies Electronics Limited + 24 Ang Mo Kio + 569061 + SG + +00-25-4C (hex) Videon Central, Inc. +00254C (base 16) Videon Central, Inc. + 2171 Sandy Drive + State College PA 16803 + US + +00-25-43 (hex) MONEYTECH +002543 (base 16) MONEYTECH + Rua Guiratinga 931 un. 103 + São Paulo SP 04141-001 + BR + +00-25-5B (hex) CoachComm, LLC +00255B (base 16) CoachComm, LLC + 205 Technology Parkway + Auburn AL 36830 + US + +00-25-16 (hex) Integrated Design Tools, Inc. +002516 (base 16) Integrated Design Tools, Inc. + 1202 E Park Avenue + Tallahassee FL 32301 + US + +00-25-10 (hex) Pico-Tesla Magnetic Therapies +002510 (base 16) Pico-Tesla Magnetic Therapies + 7852 South Elati + Littleton CO 80120 + US + +00-25-6A (hex) inIT - Institut Industrial IT +00256A (base 16) inIT - Institut Industrial IT + Liebigstrasse 87 + Lemgo Northrhine-Westfalia 32657 + DE + +00-25-62 (hex) interbro Co. Ltd. +002562 (base 16) interbro Co. Ltd. + 6F Joyang B/D, 113 Samseong-Dong, Gangnam-Gu + Seoul 135-090 + KR + +00-25-20 (hex) SMA Railway Technology GmbH +002520 (base 16) SMA Railway Technology GmbH + Miramstraße 87 + Kassel Hesse 34123 + DE + +00-25-27 (hex) Bitrode Corp. +002527 (base 16) Bitrode Corp. + 9787 Green Park Industrial Drive + St. Louis MO 63123 + US + +00-25-25 (hex) CTERA Networks Ltd. +002525 (base 16) CTERA Networks Ltd. + 24 Imber St. + Petach-Tikva 495111 + IL + +00-25-51 (hex) SE-Elektronic GmbH +002551 (base 16) SE-Elektronic GmbH + Eythstraße 16 + Göppingen 73037 + DE + +00-25-3A (hex) CEVA, Ltd. +00253A (base 16) CEVA, Ltd. + 2 Maskit Street. + Herzelia 46120 + IL + +00-24-A2 (hex) Hong Kong Middleware Technology Limited +0024A2 (base 16) Hong Kong Middleware Technology Limited + Room 1315 ,Leighton Centre,77 Leighton Road + Causeway Bay 852 + HK + +00-24-B9 (hex) Wuhan Higheasy Electronic Technology Development Co.Ltd +0024B9 (base 16) Wuhan Higheasy Electronic Technology Development Co.Ltd + Bldg A2 Optics Valley Software Park,Guanshan 1st Rd, + Wuhan Hubei 430033 + CN + +00-24-BD (hex) Hainzl Industriesysteme GmbH +0024BD (base 16) Hainzl Industriesysteme GmbH + Industriezeile 56 + Linz Upper Austria 4021 + AT + +00-24-B6 (hex) Seagate Technology +0024B6 (base 16) Seagate Technology + 1280 Disc Drive + Shakopee MN 55379 + US + +00-24-F7 (hex) Cisco Systems, Inc +0024F7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-E5 (hex) Seer Technology, Inc +0024E5 (base 16) Seer Technology, Inc + 2681 Parleys Way + Salt Lake City Utah 84109 + US + +00-24-E2 (hex) HASEGAWA ELECTRIC CO.,LTD. +0024E2 (base 16) HASEGAWA ELECTRIC CO.,LTD. + 5-6-20 SHIOE + AMAGASAKI HYOGO 661-0976 + JP + +00-24-E0 (hex) DS Tech, LLC +0024E0 (base 16) DS Tech, LLC + 2210 Hutton Drive + Carrollton TX 75006 + US + +00-24-F3 (hex) Nintendo Co., Ltd. +0024F3 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-25-01 (hex) JSC Supertel +002501 (base 16) JSC Supertel + 38A Petrogradskaya emb. + St.Petersburg 197101 + RU + +00-24-C8 (hex) Broadband Solutions Group +0024C8 (base 16) Broadband Solutions Group + 1101 Marina Village Parkway + Alameda CA 94501 + US + +00-24-C5 (hex) Meridian Audio Limited +0024C5 (base 16) Meridian Audio Limited + 11 Latham Road + Huntingdon Cambs PE29 6YE + GB + +00-24-96 (hex) Ginzinger electronic systems +002496 (base 16) Ginzinger electronic systems + Gewerbegebiet Pirath 16 + Weng Upper Austria 4952 + AT + +00-24-99 (hex) Aquila Technologies +002499 (base 16) Aquila Technologies + 8429A Washington Place NE + Albuquerque NM 87113 + US + +00-24-8A (hex) Kaga Electronics Co., Ltd. +00248A (base 16) Kaga Electronics Co., Ltd. + Hongo 2-2-9 + Tokyo 113-8503 + JP + +00-24-35 (hex) WIDE CORPORATION +002435 (base 16) WIDE CORPORATION + LEADERS TOWER 7TH FL., GOMAE-DONG, GIHEUNG-GU + YONGIN GYEONGGI 446-901 + KR + +00-24-31 (hex) Uni-v co.,ltd +002431 (base 16) Uni-v co.,ltd + 5/F,COFCO Property Tower, + Shenzhen Guangdong 518126 + CN + +00-24-32 (hex) Neostar Technology Co.,LTD +002432 (base 16) Neostar Technology Co.,LTD + 8F., No.102, Sec. 1, Sintai 5th Rd. + Sijhih City Taipei 22161 + TW + +00-24-43 (hex) Nortel Networks +002443 (base 16) Nortel Networks + 2221 Lakeside Blvd + Richardson TX 75081 + US + +00-24-41 (hex) Wanzl Metallwarenfabrik GmbH +002441 (base 16) Wanzl Metallwarenfabrik GmbH + Bubesheimer Straße 4 + Leipheim Bavaria 89340 + DE + +00-24-3B (hex) CSSI (S) Pte Ltd +00243B (base 16) CSSI (S) Pte Ltd + 70 Bendemeer Road Unit 04-04 + 339940 + SG + +00-24-51 (hex) Cisco Systems, Inc +002451 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-4A (hex) Voyant International +00244A (base 16) Voyant International + 444 Castro St + Mountain View CA 94041 + US + +00-24-47 (hex) Kaztek Systems +002447 (base 16) Kaztek Systems + 17 Bromfield Road + Acton MA 01720 + US + +00-24-77 (hex) Tibbo Technology +002477 (base 16) Tibbo Technology + 9F-3, No 31, Lane 169, Kang-Ning St., + Hsi-Chih Taipei Hsien 221 + TW + +00-24-6E (hex) Phihong USA Corp. +00246E (base 16) Phihong USA Corp. + 47800 Fremont Blvd. + Fremont CA 94538 + US + +00-24-5D (hex) Terberg besturingstechniek B.V. +00245D (base 16) Terberg besturingstechniek B.V. + Lage Dijk-Noord 3 + IJsselstein Utrecht 3401 VA + NL + +00-24-50 (hex) Cisco Systems, Inc +002450 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-58 (hex) PA Bastion CC +002458 (base 16) PA Bastion CC + 97, liter K, Buddyonnovsky ave. + Rostov-on-Don 344011 + RU + +00-24-73 (hex) 3COM EUROPE LTD +002473 (base 16) 3COM EUROPE LTD + Peoplebuilding 2 + Hemel Hempstead HERTS. HP2 4NW + GB + +00-24-6B (hex) Covia, Inc. +00246B (base 16) Covia, Inc. + Benex S-3 Bldg., 3-20-8, Shinyokohama,Kohoku-ku, + Yokohama-city Kanagawa-pref. 222-0033 + JP + +00-23-F5 (hex) WILO SE +0023F5 (base 16) WILO SE + Nortkirchenstraße 100 + D - 44263 Dortmund NRW 44263 + DE + +00-23-FF (hex) Beijing HTTC Technology Ltd. +0023FF (base 16) Beijing HTTC Technology Ltd. + B-13D-3 Keshi Building,Jia No.28 Xinxi Road,SHANGDI IT Industry Base + Beijing 100085 + CN + +00-23-F6 (hex) Softwell Technology Co., Ltd. +0023F6 (base 16) Softwell Technology Co., Ltd. + 4F, No. 419, Jhonghe Rd., Yonghe City, + Taipei County 234 + TW + +00-23-F3 (hex) Glocom, Inc. +0023F3 (base 16) Glocom, Inc. + 22 Firstfield Road + Gaithersburg Maryland 20878 + US + +00-23-F0 (hex) Shanghai Jinghan Weighing Apparatus Co. Ltd. +0023F0 (base 16) Shanghai Jinghan Weighing Apparatus Co. Ltd. + Building 58, No.99 Chunguang Road, Xinzhuang Industrial Zone,Minhang, + Shanghai 201108 + CN + +00-24-10 (hex) NUETEQ Technology,Inc. +002410 (base 16) NUETEQ Technology,Inc. + 11F, No. 112, Sec. 1, Zhong-Xiao E Rd. + Taipei 100 + TW + +00-24-08 (hex) Pacific Biosciences +002408 (base 16) Pacific Biosciences + 1505 Adams Drive + Menlo Park CA 94025 + US + +00-24-30 (hex) Ruby Tech Corp. +002430 (base 16) Ruby Tech Corp. + 3F, NO. 1, Lane 50, Nan Kang Road, Sec. 3, + Taipei 11510 + TW + +00-24-2E (hex) Datastrip Inc. +00242E (base 16) Datastrip Inc. + 1 Waterview Drive + Shelton CT 06484 + US + +00-24-1D (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +00241D (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + + Pin-Jen Taoyuan 324 + TW + +00-24-1A (hex) Red Beetle Inc. +00241A (base 16) Red Beetle Inc. + 898 Silas Deane Highway + Wethersfield CT 06109 + US + +00-24-14 (hex) Cisco Systems, Inc +002414 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-0C (hex) DELEC GmbH +00240C (base 16) DELEC GmbH + Ruheweg 17-21 + Göllheim Rheinland-Pfalz 67307 + DE + +00-23-F9 (hex) Double-Take Software, INC. +0023F9 (base 16) Double-Take Software, INC. + 8470 Allison Pointe Blvd + Indianapolis IN 46250 + US + +00-23-E9 (hex) F5 Networks, Inc. +0023E9 (base 16) F5 Networks, Inc. + 401 Elliott Ave. W. + Seattle WA 98119 + US + +00-23-EA (hex) Cisco Systems, Inc +0023EA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-23-E5 (hex) IPaXiom Networks +0023E5 (base 16) IPaXiom Networks + Aston Court + High Wycombe Buckinghamshire HP11 1LA + GB + +00-23-B6 (hex) SECURITE COMMUNICATIONS / HONEYWELL +0023B6 (base 16) SECURITE COMMUNICATIONS / HONEYWELL + FONT DE L'ORME + MOUGINS FRANCE 06250 + US + +00-23-B8 (hex) Sichuan Jiuzhou Electronic Technology Co.,Ltd +0023B8 (base 16) Sichuan Jiuzhou Electronic Technology Co.,Ltd + No.259 Jiuzhou Road, + Mianyang Sichuan 621000 + CN + +00-23-BA (hex) Chroma +0023BA (base 16) Chroma + 68, Hwa-Ya 1st Rd., Hwa-Ya Technical Park, + Taoyuan Hsien Taiwan 333 + TW + +00-23-BC (hex) EQ-SYS GmbH +0023BC (base 16) EQ-SYS GmbH + Hinter den Gärten 15b + Treuenbrietzen OT Feldheim Brandenburg 14929 + DE + +00-23-B1 (hex) Longcheer Technology (Singapore) Pte Ltd +0023B1 (base 16) Longcheer Technology (Singapore) Pte Ltd + 43 Kaki Bukit View, #04-01 , + 415970 + SG + +00-23-96 (hex) ANDES TECHNOLOGY CORPORATION +002396 (base 16) ANDES TECHNOLOGY CORPORATION + 2F,No. 1, Li-Hsin First Road, + Hsin-Chu Taiwan 300 + TW + +00-23-94 (hex) Samjeon +002394 (base 16) Samjeon + #1313-1 Joil-Ri, Samdong-Myeun,Ulju-Gun + Ulsan City South Korea 689-934 + KR + +00-23-77 (hex) Isotek Electronics Ltd +002377 (base 16) Isotek Electronics Ltd + 9 Clayton Wood Bank + Leeds LS16 6QZ + GB + +00-23-71 (hex) SOAM Systel +002371 (base 16) SOAM Systel + 182-13, Daerung Post Tower II, 1504 + Seoul Guro-dong, Guro-gu 152-847 + KR + +00-23-A1 (hex) Trend Electronics Ltd +0023A1 (base 16) Trend Electronics Ltd + Gut No. 350 + Auranagabad Maharashtra 431210 + IN + +00-23-A6 (hex) E-Mon +0023A6 (base 16) E-Mon + One Oxford Valley, Suite 418 + Langhorne PA 19047 + US + +00-23-A8 (hex) Marshall Electronics +0023A8 (base 16) Marshall Electronics + 20608 Madrona Ave + Torrance CA 90503 + US + +00-23-9A (hex) EasyData Hardware GmbH +00239A (base 16) EasyData Hardware GmbH + Breslauer Str. 24 + Wehrheim Hessen D-61273 + DE + +00-23-CC (hex) Nintendo Co., Ltd. +0023CC (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-23-79 (hex) Union Business Machines Co. Ltd. +002379 (base 16) Union Business Machines Co. Ltd. + Unit 2, 2/F, Block A, Hong Kong Industrial Centre, + Lai Chi Kok Kowloon + HK + +00-23-8C (hex) Private +00238C (base 16) Private + +00-23-C0 (hex) Broadway Networks +0023C0 (base 16) Broadway Networks + 1754 Technology Drive, Suite 208 + San Jose California 95110 + US + +00-23-58 (hex) SYSTEL SA +002358 (base 16) SYSTEL SA + ZI DE BELLE AIRE + AYTRE 17440 + FR + +00-23-56 (hex) Packet Forensics LLC +002356 (base 16) Packet Forensics LLC + 420 S Smith Rd + Tempe AZ 85281 + US + +00-23-50 (hex) RDC, Inc. dba LynTec +002350 (base 16) RDC, Inc. dba LynTec + 8385 Melrose Drive + Lenexa KS 66214 + US + +00-23-4F (hex) Luminous Power Technologies Pvt. Ltd. +00234F (base 16) Luminous Power Technologies Pvt. Ltd. + C8-C9, Community Center, + New Delhi 110058 + IN + +00-23-4B (hex) Inyuan Technology Inc. +00234B (base 16) Inyuan Technology Inc. + No. 3, Singye St., + Taoyuan County 33341 + TW + +00-23-49 (hex) Helmholtz Centre Berlin for Material and Energy +002349 (base 16) Helmholtz Centre Berlin for Material and Energy + Department FMD + Berlin 14109 + DE + +00-23-46 (hex) Vestac +002346 (base 16) Vestac + P.O. Box 7358 + Shrewsbury NJ 07702 + US + +00-23-07 (hex) FUTURE INNOVATION TECH CO.,LTD +002307 (base 16) FUTURE INNOVATION TECH CO.,LTD + 312 3-DONG, GWANGMYUNG INDUSTRIAL COMPLEX 201 + GWANGMYUNG GYUNGGI 423060 + KR + +00-23-05 (hex) Cisco Systems, Inc +002305 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-22-FF (hex) NIVIS LLC +0022FF (base 16) NIVIS LLC + 1000 CIRCLE 75 + ATLANTA GA 30339 + US + +00-23-44 (hex) Objective Interface Systems, Inc. +002344 (base 16) Objective Interface Systems, Inc. + 220 Spring Street, Suite 530 + Herndon VA 20170-6201 + US + +00-23-3C (hex) Alflex +00233C (base 16) Alflex + Blauw-roodlaan 300 + ZOETERMEER 2718 SK + NL + +00-23-33 (hex) Cisco Systems, Inc +002333 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-23-2E (hex) Kedah Electronics Engineering, LLC +00232E (base 16) Kedah Electronics Engineering, LLC + Zelenograd, 445 + Moscow 124498 + RU + +00-23-20 (hex) Nicira Networks +002320 (base 16) Nicira Networks + 3460 W. Bayshore Rd. + Palo Alto CA 94303 + US + +00-23-64 (hex) Power Instruments Pte Ltd +002364 (base 16) Power Instruments Pte Ltd + BLK 40 TOH GUAN RD EAST, #01-62 ENTERPRISE HUB + 608582 + SG + +00-23-17 (hex) Lasercraft Inc +002317 (base 16) Lasercraft Inc + 1450 Oakbrook Drive + Norcross GA 30093 + US + +00-23-0E (hex) Gorba AG +00230E (base 16) Gorba AG + Sandackerstrasse + Oberbüren SG CH - 9245 + CH + +00-23-62 (hex) Goldline Controls +002362 (base 16) Goldline Controls + 61 Whitecap Dr + North Kingstown RI 02852 + US + +00-23-5E (hex) Cisco Systems, Inc +00235E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-23-22 (hex) KISS Teknical Solutions, Inc. +002322 (base 16) KISS Teknical Solutions, Inc. + 1583 S. Navajo Way + Chandler Arizona 85286 + US + +00-22-B6 (hex) Superflow Technologies Group +0022B6 (base 16) Superflow Technologies Group + 4060 Dixon Street + Des Moines IA 50266 + US + +00-22-B5 (hex) NOVITA +0022B5 (base 16) NOVITA + 3F301,Namsung B/D 340-30 + Geumcheon-Gu Seoul 153-782 + KR + +00-22-B2 (hex) 4RF Communications Ltd +0022B2 (base 16) 4RF Communications Ltd + 26 Glover Street + Ngauranga Wellington 6031 + NZ + +00-22-AC (hex) Hangzhou Siyuan Tech. Co., Ltd +0022AC (base 16) Hangzhou Siyuan Tech. Co., Ltd + 5 F, Tower B, No. 37, Xiang Yuan Road + Hangzhou Zhejiang 310012 + CN + +00-22-AD (hex) TELESIS TECHNOLOGIES, INC. +0022AD (base 16) TELESIS TECHNOLOGIES, INC. + 28181 River Drive + Circleville Ohio 43113 + US + +00-22-AE (hex) Mattel Inc. +0022AE (base 16) Mattel Inc. + 333 Continental Blvd. + El Segundo CA 90245 + US + +00-22-D5 (hex) Eaton Corp. Electrical Group Data Center Solutions - Pulizzi +0022D5 (base 16) Eaton Corp. Electrical Group Data Center Solutions - Pulizzi + 3200 S. Susan St. + Santa Ana CA 92704 + US + +00-22-D1 (hex) Albrecht Jung GmbH & Co. KG +0022D1 (base 16) Albrecht Jung GmbH & Co. KG + Volmestraße 1 + Schalksmühle NRW 58579 + DE + +00-22-D2 (hex) All Earth Comércio de Eletrônicos LTDA. +0022D2 (base 16) All Earth Comércio de Eletrônicos LTDA. + Rua Leonida Reimman Trotti, 343 + Campinas São Paulo 13065-704 + BR + +00-22-C2 (hex) Proview Eletrônica do Brasil LTDA +0022C2 (base 16) Proview Eletrônica do Brasil LTDA + R. Acará 203 - Distrito Industrial + Manaus Amazonas 69075-030 + BR + +00-22-BD (hex) Cisco Systems, Inc +0022BD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-22-BA (hex) HUTH Elektronik Systeme GmbH +0022BA (base 16) HUTH Elektronik Systeme GmbH + Echternacher Str. 10 + Troisdorf-Spich NRW 53842 + DE + +00-22-BB (hex) beyerdynamic GmbH & Co. KG +0022BB (base 16) beyerdynamic GmbH & Co. KG + Theresienstraße 8 + Heilbronn 74072 + DE + +00-22-A3 (hex) California Eastern Laboratories +0022A3 (base 16) California Eastern Laboratories + 4590 Patrick Henry Dr. + Santa Clara CA 95054 + US + +00-23-02 (hex) Cobalt Digital, Inc. +002302 (base 16) Cobalt Digital, Inc. + 2406 East University Avenue + Urbana IL 61802 + US + +00-22-F5 (hex) Advanced Realtime Tracking GmbH +0022F5 (base 16) Advanced Realtime Tracking GmbH + Am Oeferl 6 + Weilheim Bayern D-82362 + DE + +00-22-CA (hex) Anviz Biometric Tech. Co., Ltd. +0022CA (base 16) Anviz Biometric Tech. Co., Ltd. + 5th Floor, 4299 Jindu Road, + Shanghai 201108 + CN + +00-22-C7 (hex) SEGGER Microcontroller GmbH & Co. KG +0022C7 (base 16) SEGGER Microcontroller GmbH & Co. KG + In den Weiden 11 + Hilden NRW 40721 + DE + +00-22-C1 (hex) Active Storage Inc. +0022C1 (base 16) Active Storage Inc. + 2295 Jefferson Street + Torrance CA 90501 + US + +00-22-8F (hex) CNRS +00228F (base 16) CNRS + MRCT + Meudon Ile de France 92195 + FR + +00-22-97 (hex) XMOS Semiconductor +002297 (base 16) XMOS Semiconductor + Venturers House + Bristol BS1 4PB + GB + +00-22-92 (hex) Cinetal +002292 (base 16) Cinetal + 8651 Castle Park + Indianapolis IN 46256 + US + +00-22-E5 (hex) Fisher-Rosemount Systems Inc. +0022E5 (base 16) Fisher-Rosemount Systems Inc. + 12301 Research Blvd + Austin Texas 78759 + US + +00-22-E4 (hex) APASS TECHNOLOGY CO., LTD. +0022E4 (base 16) APASS TECHNOLOGY CO., LTD. + 2F, No. 267, Sec. 3, Chengde Rd., + TEIPEI 113 + TW + +00-22-4F (hex) Byzoro Networks Ltd. +00224F (base 16) Byzoro Networks Ltd. + Room 5A1,Block A, Keshi Plaza,No. 28A Info. Road, + Beijing 100085 + CN + +00-22-51 (hex) Lumasense Technologies +002251 (base 16) Lumasense Technologies + 3033 Scott Blvd. + Santa Clara CA 95054 + US + +00-22-5E (hex) Uwin Technologies Co.,LTD +00225E (base 16) Uwin Technologies Co.,LTD + 2F,No.22.R&D RD II,SBIP + Hsinchu 300 + TW + +00-22-58 (hex) Taiyo Yuden Co., Ltd. +002258 (base 16) Taiyo Yuden Co., Ltd. + 8-1 Sakae-Cho + + JP + +00-22-5B (hex) Teradici Corporation +00225B (base 16) Teradici Corporation + 101 4621 Canada Way, + Burnaby BC V6G 4X8 + CA + +00-22-59 (hex) Guangzhou New Postcom Equipment Co.,Ltd. +002259 (base 16) Guangzhou New Postcom Equipment Co.,Ltd. + No.3¡¡Guangpuxi Road,Guangzhou Science City, + Guangzhou Guangdong 510663 + CN + +00-22-53 (hex) Entorian Technologies +002253 (base 16) Entorian Technologies + 8900 Shoal Creek Blvd + Austin TX 78757 + US + +00-22-2C (hex) Ceton Corp +00222C (base 16) Ceton Corp + 8259 122nd Ave NE, Suite 275 + Kirkland Washington 98033 + US + +00-22-2D (hex) SMC Networks Inc. +00222D (base 16) SMC Networks Inc. + 20 Mason + Irvine CA 92618 + US + +00-22-2A (hex) SoundEar A/S +00222A (base 16) SoundEar A/S + Rentemestervej 80 + Copenhagen NV Denmark DK-2400 + DK + +00-22-7E (hex) Chengdu 30Kaitian Communication Industry Co.Ltd +00227E (base 16) Chengdu 30Kaitian Communication Industry Co.Ltd + No.6 Chuangye Road + Chengdu Sichuan 610041 + CN + +00-22-7C (hex) Woori SMT Co.,ltd +00227C (base 16) Woori SMT Co.,ltd + 649-2,Suwolam-ri,Seotan-Myun + Pyongtaek Kyonggi-Do 451-852 + KR + +00-22-77 (hex) NEC Australia Pty Ltd +002277 (base 16) NEC Australia Pty Ltd + 649-655 Springvale Rd + Mulgrave Victoria 3170 + AU + +00-22-3D (hex) JumpGen Systems, LLC +00223D (base 16) JumpGen Systems, LLC + 2111 Palomar Airport Rd + Carlsbad CA 92011 + US + +00-22-39 (hex) Indiana Life Sciences Incorporated +002239 (base 16) Indiana Life Sciences Incorporated + 8875 Bash Street + Indianapolis Indiana 46256 + US + +00-22-35 (hex) Strukton Systems bv +002235 (base 16) Strukton Systems bv + Westkanaaldijk 2 + Utrecht 3542 DA + NL + +00-22-79 (hex) Nippon Conlux Co., Ltd. +002279 (base 16) Nippon Conlux Co., Ltd. + 5-3-8, Chiyoda + Sakado-shi Saitama 350-0214 + JP + +00-22-71 (hex) Jäger Computergesteuerte Meßtechnik GmbH. +002271 (base 16) Jäger Computergesteuerte Meßtechnik GmbH. + Rheinstraße 2-4 + Lorsch Hessen 64653 + DE + +00-22-47 (hex) DAC ENGINEERING CO., LTD. +002247 (base 16) DAC ENGINEERING CO., LTD. + 1-5 Oyanagi-cho + Kyoto 601-8128 + JP + +00-22-1F (hex) eSang Technologies Co., Ltd. +00221F (base 16) eSang Technologies Co., Ltd. + #1-817, IT Castle 550-1, Gasan-Dong, + Seoul 153-768 + KR + +00-21-E6 (hex) Starlight Video Limited +0021E6 (base 16) Starlight Video Limited + 5/F., Shing Dao Industrial Building, + + HK + +00-21-E0 (hex) CommAgility Ltd +0021E0 (base 16) CommAgility Ltd + Holywell Park + Loughborough Leics LE11 3AQ + GB + +00-21-DE (hex) Firepro Wireless +0021DE (base 16) Firepro Wireless + 27, Zamrudpur Community Center, + New Delhi Haryana 110020 + IN + +00-21-F9 (hex) WIRECOM Technologies +0021F9 (base 16) WIRECOM Technologies + 135, rue Jacques Charles + OLIVET Loiret 45166 + FR + +00-21-FA (hex) A4SP Technologies Ltd. +0021FA (base 16) A4SP Technologies Ltd. + Keilaranta 19 D + Espoo Uusimaa 02150 + FI + +00-21-F0 (hex) EW3 Technologies LLC +0021F0 (base 16) EW3 Technologies LLC + 114 E 11th St + Connersville IN 47331 + US + +00-21-D3 (hex) BOCOM SECURITY(ASIA PACIFIC) LIMITED +0021D3 (base 16) BOCOM SECURITY(ASIA PACIFIC) LIMITED + Flr.3,NO.29,#69 Guiqing RD + Shanghai 200233 + CN + +00-21-CC (hex) Flextronics International +0021CC (base 16) Flextronics International + Stretton Green Distribution Centre Langford Way + Warrington Cheshire WA4 4TQ + GB + +00-21-B9 (hex) Universal Devices Inc. +0021B9 (base 16) Universal Devices Inc. + 5353 Yarmouth Ave. #209 + Encino CA 91316 + US + +00-21-B3 (hex) Ross Controls +0021B3 (base 16) Ross Controls + One Ross Way + Lavonia GA 30553 + US + +00-21-B6 (hex) Triacta Power Technologies Inc. +0021B6 (base 16) Triacta Power Technologies Inc. + Box 582, 7 Mill Street + Almonte Ontario K0A 1A0 + CA + +00-22-17 (hex) Neat Electronics +002217 (base 16) Neat Electronics + Varuvägen 2 + Löddeköpinge Skåne SE-24642 + SE + +00-22-11 (hex) Rohati Systems +002211 (base 16) Rohati Systems + 1192 Borregas Ave + Sunnyvale CA 94089 + US + +00-21-CF (hex) The Crypto Group +0021CF (base 16) The Crypto Group + Zugerstrasse 42 + Steinhausen Zug 6312 + CH + +00-21-C5 (hex) 3DSP Corp +0021C5 (base 16) 3DSP Corp + 16271 Laguna Canyon Road + Irvine, CA 92618 + US + +00-22-12 (hex) CAI Networks, Inc. +002212 (base 16) CAI Networks, Inc. + 4790 Irvine Blvd + Irvine California 92620 + US + +00-22-0D (hex) Cisco Systems, Inc +00220D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-22-08 (hex) Certicom Corp +002208 (base 16) Certicom Corp + 5520 Explorer Drive, 4th Floor + Mississauga ON L4W 5L1 + CA + +00-21-EE (hex) Full Spectrum Inc. +0021EE (base 16) Full Spectrum Inc. + 1149 Chestnut Street, Suite 100 + Menlo Park California 94025 + US + +00-21-EC (hex) Solutronic GmbH +0021EC (base 16) Solutronic GmbH + Kueferstrasse 18 + Koengen 73257 + DE + +00-22-05 (hex) WeLink Solutions, Inc. +002205 (base 16) WeLink Solutions, Inc. + 3F, No. 88, Sec. 1, Nei-Hu Rd. + Taipei 114 + TW + +00-22-09 (hex) Omron Healthcare Co., Ltd +002209 (base 16) Omron Healthcare Co., Ltd + 24 Yamanoshita-cho Yamanouchi + Kyoto 6150084 + JP + +00-21-8C (hex) TopControl GMBH +00218C (base 16) TopControl GMBH + Enzenbergweg 24/A + Terlan (BZ) 39018 + IT + +00-21-8A (hex) Electronic Design and Manufacturing Company +00218A (base 16) Electronic Design and Manufacturing Company + 31 Millrace Dr + Lynchburg VA 24502 + US + +00-21-8B (hex) Wescon Technology, Inc. +00218B (base 16) Wescon Technology, Inc. + 4655-170 Old Ironsides Drive + Santa Clara California 95054 + US + +00-21-84 (hex) POWERSOFT SRL +002184 (base 16) POWERSOFT SRL + VIA ENRICO CONTI, 5 + SCANDICCI FI 50018 + IT + +00-21-78 (hex) Matuschek Messtechnik GmbH +002178 (base 16) Matuschek Messtechnik GmbH + Werner Heisenberg Straße 14 + Alsdorf NRW 52477 + DE + +00-21-73 (hex) Ion Torrent Systems, Inc. +002173 (base 16) Ion Torrent Systems, Inc. + 37 Soundview Rd + Guilford CT 06437 + US + +00-21-77 (hex) W. L. Gore & Associates +002177 (base 16) W. L. Gore & Associates + 402 Vieves Way + Elkton MD 21921 + US + +00-21-72 (hex) Seoultek Valley +002172 (base 16) Seoultek Valley + Bang-i Dong 51-5, Songpa + Seoul 138-050 + KR + +00-21-53 (hex) SeaMicro Inc. +002153 (base 16) SeaMicro Inc. + 3250 Jay Street + Santa Clara CA 95054 + US + +00-21-7A (hex) Sejin Electron, Inc. +00217A (base 16) Sejin Electron, Inc. + SJ Technoville + Seoul 153-801 + KR + +00-21-A4 (hex) Dbii Networks +0021A4 (base 16) Dbii Networks + 2217 Via Blanca + Oceanside CA 92054 + US + +00-21-99 (hex) Vacon Plc +002199 (base 16) Vacon Plc + P.O.Box 25 + Vaasa 65380 + FI + +00-21-A0 (hex) Cisco Systems, Inc +0021A0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-21-98 (hex) Thai Radio Co, LTD +002198 (base 16) Thai Radio Co, LTD + Hi-Tech Industrial Estate + Ayutthaya 13160 + TH + +00-21-AE (hex) ALCATEL-LUCENT FRANCE - WTD +0021AE (base 16) ALCATEL-LUCENT FRANCE - WTD + 7-9, Avenue Morane Saulnier + VELIZY 78141 + FR + +00-21-AF (hex) Radio Frequency Systems +0021AF (base 16) Radio Frequency Systems + Kabelkamp 20 + Hannover 30179 + DE + +00-21-54 (hex) D-TACQ Solutions Ltd +002154 (base 16) D-TACQ Solutions Ltd + James Watt Building + East Kilbride Lanarkshire G75 0QD + GB + +00-21-69 (hex) Prologix, LLC. +002169 (base 16) Prologix, LLC. + 17217 NE 133rd Place + Redmond Washington 98052-2153 + US + +00-21-4B (hex) Shenzhen HAMP Science & Technology Co.,Ltd +00214B (base 16) Shenzhen HAMP Science & Technology Co.,Ltd + No.302-303,3 Floor,District A,TCL Tower,Gaoxin Nan Yi Road,NanShan District + Shenzhen Guangdong 518057 + CN + +00-21-45 (hex) Semptian Technologies Ltd. +002145 (base 16) Semptian Technologies Ltd. + No. 809, Tower B, Shi Ji Ke Mao + Beijing 100190 + CN + +00-1F-FE (hex) HPN Supply Chain +001FFE (base 16) HPN Supply Chain + 8000 Foothills Blvd + Roseville CA 95747 + US + +00-1F-FF (hex) Respironics, Inc. +001FFF (base 16) Respironics, Inc. + 1740 Golden Mile Highway + Monroeville PA 15146 + US + +00-1F-FC (hex) Riccius+Sohn GmbH +001FFC (base 16) Riccius+Sohn GmbH + Haynauer Str. 49 + Berlin 12249 + DE + +00-1F-FD (hex) Indigo Mobile Technologies Corp. +001FFD (base 16) Indigo Mobile Technologies Corp. + 11F, No22, Lan407,TiDing Blvd Section2, Neihu Technology Park + Taipei City 114 + TW + +00-21-21 (hex) VRmagic GmbH +002121 (base 16) VRmagic GmbH + Augustaanlage 32 + Mannheim BW 68165 + DE + +00-21-23 (hex) Aerosat Avionics +002123 (base 16) Aerosat Avionics + 62 State Rd. + Amherst NH 03031 + US + +00-21-0A (hex) byd:sign Corporation +00210A (base 16) byd:sign Corporation + 2-10-6 Tsukiji + Chuo-ku Tokyo 104-0045 + JP + +00-21-07 (hex) Seowonintech Co Ltd. +002107 (base 16) Seowonintech Co Ltd. + 689-47 Geumjeongdong + Gunposi Kyoungkido 436-862 + KR + +00-21-3E (hex) TomTom +00213E (base 16) TomTom + Oosterdoksstraat 114 + Amsterdam North Holland 1011 DK + NL + +00-21-3F (hex) A-Team Technology Ltd. +00213F (base 16) A-Team Technology Ltd. + Rm. 1608, 16/F., Metropole Square, + New Territories, + HK + +00-21-1B (hex) Cisco Systems, Inc +00211B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-21-2D (hex) SCIMOLEX CORPORATION +00212D (base 16) SCIMOLEX CORPORATION + 2430, Saijou, Showa-cho + Nakakoma-gun, Yamanashi 409-3866 + JP + +00-1F-D5 (hex) MICRORISC s.r.o. +001FD5 (base 16) MICRORISC s.r.o. + Delnicka 222 + Jicin kralovehradecky kraj 50601 + CZ + +00-1F-B1 (hex) Cybertech Inc. +001FB1 (base 16) Cybertech Inc. + 935 Horsham Rd + Horsham PA 19044 + US + +00-1F-B2 (hex) Sontheim Industrie Elektronik GmbH +001FB2 (base 16) Sontheim Industrie Elektronik GmbH + Dieselstrasse 7 + Kempten Allgaeu Bavaria D-87437 + DE + +00-1F-EE (hex) ubisys technologies GmbH +001FEE (base 16) ubisys technologies GmbH + Am Wehrhahn 45 + Düsseldorf NRW 40211 + DE + +00-1F-EF (hex) SHINSEI INDUSTRIES CO.,LTD +001FEF (base 16) SHINSEI INDUSTRIES CO.,LTD + 4-12-15,HORIFUNE, KITA-KU, + TOKOYO 114-0004 + JP + +00-1F-EC (hex) Synapse Électronique +001FEC (base 16) Synapse Électronique + 1010, 7e Avenue + Grand-Mère Québec G9T 2B8 + CA + +00-1F-CA (hex) Cisco Systems, Inc +001FCA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1F-C3 (hex) SmartSynch, Inc +001FC3 (base 16) SmartSynch, Inc + 4400 Old Canton Rd + Jackson MS 39211 + US + +00-1F-E0 (hex) EdgeVelocity Corp +001FE0 (base 16) EdgeVelocity Corp + 68 Stiles Road + Hudson NH 03079 + US + +00-1F-D8 (hex) A-TRUST COMPUTER CORPORATION +001FD8 (base 16) A-TRUST COMPUTER CORPORATION + 3F., NO.361, FUSING 1ST RD., GUEISHAN TOWNSHIP, + TAOYUAN 33375 + TW + +00-1F-D7 (hex) TELERAD SA +001FD7 (base 16) TELERAD SA + 2, avenue de la butte aux cailles + ANGLET 64600 + FR + +00-1F-D3 (hex) RIVA Networks Inc. +001FD3 (base 16) RIVA Networks Inc. + 555 Riva Ave + East Brunswick NJ 08816 + US + +00-1F-C1 (hex) Hanlong Technology Co.,LTD +001FC1 (base 16) Hanlong Technology Co.,LTD + 2402 West Tower Building, Fuxin International Building, + Nanjing Jiangsu 210002 + CN + +00-1F-BB (hex) Xenatech Co.,LTD +001FBB (base 16) Xenatech Co.,LTD + 514-2 Ya Tab-Dong Bun Dang Gu + Seong namsi Gyong gi-do 463-839 + KR + +00-1F-E8 (hex) KURUSUGAWA Electronics Industry Inc,. +001FE8 (base 16) KURUSUGAWA Electronics Industry Inc,. + 2F, 52-5, Nogata 6chome + Nakano-Ku TOKYO 165-0027 + JP + +00-1F-AB (hex) I.S HIGH TECH.INC +001FAB (base 16) I.S HIGH TECH.INC + 603-1,Sungbon-ri,Daeso-myun + Eumsung-gun Chungcheongbuk-do 369-823 + KR + +00-1F-AC (hex) Goodmill Systems Ltd +001FAC (base 16) Goodmill Systems Ltd + Sinikalliontie 10 + Espoo Uusimaa 02630 + FI + +00-1F-36 (hex) Bellwin Information Co. Ltd., +001F36 (base 16) Bellwin Information Co. Ltd., + No.336, Beitun Rd., Beitun Dist., + Taichung 406 + TW + +00-1F-3D (hex) Qbit GmbH +001F3D (base 16) Qbit GmbH + Stegwiesenstrasse 32 + Bruchsal Germany 76646 + DE + +00-1F-38 (hex) POSITRON +001F38 (base 16) POSITRON + ESTRADA TELEBRAS-UNICAMP, KM0,97 - CJ.01 + CAMPINAS São Paulo 13084-971 + BR + +00-1F-2D (hex) Electro-Optical Imaging, Inc. +001F2D (base 16) Electro-Optical Imaging, Inc. + 4300 Fortune Place, Suite C + West Melbourne FL 32904 + US + +00-1F-89 (hex) Signalion GmbH +001F89 (base 16) Signalion GmbH + Sudhausweg 5 + Dresden Saxony 01099 + DE + +00-1F-8A (hex) Ellion Digital Inc. +001F8A (base 16) Ellion Digital Inc. + Suite 809, Sicox Tower, 513-14, Sangdaewon-dong, Jungwon-gu + Sungnam-city Kyonggi-do 426-726 + KR + +00-1F-7F (hex) Phabrix Limited +001F7F (base 16) Phabrix Limited + Blindmans Gate Cottage + Newbury Hampshire RG20 9XB + GB + +00-1F-76 (hex) AirLogic Systems Inc. +001F76 (base 16) AirLogic Systems Inc. + 3022 Peleke St.Suite 1 + Lihu'e HI 96766 + US + +00-1F-73 (hex) Teraview Technology Co., Ltd. +001F73 (base 16) Teraview Technology Co., Ltd. + 23F, No. 29-5, Sec. 2, Jhongjheng E. Road, + Taipei County 251 + TW + +00-1F-62 (hex) JSC Stilsoft +001F62 (base 16) JSC Stilsoft + Mayakovskogo 15 + Stavropol 355000 + RU + +00-1F-67 (hex) Hitachi,Ltd. +001F67 (base 16) Hitachi,Ltd. + Minamioi 6-27-18, Shinagawa-ku + Tokyo Tokyo 140-8572 + JP + +00-1F-56 (hex) DIGITAL FORECAST +001F56 (base 16) DIGITAL FORECAST + 5th Fl., 507, E&C Venture Dream Tower III, 197-33 + Seoul Gyunggi-do 152-719 + KR + +00-1F-52 (hex) UVT Unternehmensberatung fur Verkehr und Technik GmbH +001F52 (base 16) UVT Unternehmensberatung fur Verkehr und Technik GmbH + Josefsstraße 54-56 + Mainz RLP 55118 + DE + +00-1F-4F (hex) Thinkware Co. Ltd. +001F4F (base 16) Thinkware Co. Ltd. + 15FL, Hanmi Tower, 45, + Seoul 138-724 + KR + +00-1F-2F (hex) Berker GmbH & Co. KG +001F2F (base 16) Berker GmbH & Co. KG + Klagebach 38 + Schalksmuehle NRW 58579 + DE + +00-1F-32 (hex) Nintendo Co., Ltd. +001F32 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-1F-44 (hex) GE Transportation Systems +001F44 (base 16) GE Transportation Systems + 2901 East Lake Road + Erie PA 16501 + US + +00-1F-39 (hex) Construcciones y Auxiliar de Ferrocarriles, S.A. +001F39 (base 16) Construcciones y Auxiliar de Ferrocarriles, S.A. + C/ J.M. Iturrioz, 26 + Beasain Guipúzcoa E-20200 + ES + +00-1F-7C (hex) Witelcom AS +001F7C (base 16) Witelcom AS + Verftsgt 10 + Moss Ostfold 1511 + NO + +00-1F-7A (hex) WiWide Inc. +001F7A (base 16) WiWide Inc. + 10B10, Hua Jie Plaza + Beijing 100089 + CN + +00-1F-77 (hex) HEOL DESIGN +001F77 (base 16) HEOL DESIGN + 1 bd d'armor + LANNION BRETAGNE 22300 + FR + +00-1F-94 (hex) Lascar Electronics Ltd +001F94 (base 16) Lascar Electronics Ltd + Module House + Nr Salisbury Wiltshire SP5 2SJ + GB + +00-1F-8E (hex) Metris USA Inc. +001F8E (base 16) Metris USA Inc. + 44880 Falcon Place ste 100 + Sterling VA 20166 + US + +00-1F-61 (hex) Talent Communication Networks Inc. +001F61 (base 16) Talent Communication Networks Inc. + Rm. 910 R&F Plaza, #76, Huangpu Ave. West, + Guangzhou (Canton) Guangdong Province 510360 + CN + +00-1E-CE (hex) BISA Technologies (Hong Kong) Limited +001ECE (base 16) BISA Technologies (Hong Kong) Limited + 1102, Trans Asia Centre, + Kwai Chung, + HK + +00-1E-C8 (hex) Rapid Mobile (Pty) Ltd +001EC8 (base 16) Rapid Mobile (Pty) Ltd + Building C,D,E Apex Corporate Park + Pretoria Gauteng 0020 + ZA + +00-1E-CC (hex) CDVI +001ECC (base 16) CDVI + 31 Avenue du Général Leclerc + PANTIN Ile de France 93500 + FR + +00-1E-C5 (hex) Middle Atlantic Products Inc +001EC5 (base 16) Middle Atlantic Products Inc + 300 Fairfield Road + Fairfield NJ 07004 + US + +00-1F-03 (hex) NUM AG +001F03 (base 16) NUM AG + Battenhusstrasse 16 + Teufen AR 9053 + CH + +00-1E-FF (hex) Mueller-Elektronik GmbH & Co. KG +001EFF (base 16) Mueller-Elektronik GmbH & Co. KG + Franz-Kleine-Str. 18 + Salzkotten NRW 33154 + DE + +00-1F-05 (hex) iTAS Technology Corp. +001F05 (base 16) iTAS Technology Corp. + No. 75, Shuiyuan St. + Hsinchu City 30069 + TW + +00-1F-07 (hex) AZTEQ Mobile +001F07 (base 16) AZTEQ Mobile + Suite 210, 525 University Ave + Palo Alto CA 94301 + US + +00-1E-F6 (hex) Cisco Systems, Inc +001EF6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-F9 (hex) Pascom Kommunikations systeme GmbH. +001EF9 (base 16) Pascom Kommunikations systeme GmbH. + Technologiestr. 4 + Arbing Upper Austria 4332 + AT + +00-1E-F3 (hex) From2 +001EF3 (base 16) From2 + 2F, Mester inc + Daejeon 306-230 + KR + +00-1F-19 (hex) BEN-RI ELECTRONICA S.A. +001F19 (base 16) BEN-RI ELECTRONICA S.A. + POL. IND. VENTORRO DEL CANO + ALCORCON MADRID 28925 + ES + +00-1F-11 (hex) OPENMOKO, INC. +001F11 (base 16) OPENMOKO, INC. + 7F, No 300, Yang Guang Street + Taipei 11491 + TW + +00-1E-E4 (hex) ACS Solutions France +001EE4 (base 16) ACS Solutions France + Rue Claude Chappe + Guilherand Granges Ardeche 07503 + FR + +00-1E-ED (hex) Adventiq Ltd. +001EED (base 16) Adventiq Ltd. + Technology House + Bar Hill Cambs. CB3 8SQ + GB + +00-1E-D2 (hex) Ray Shine Video Technology Inc +001ED2 (base 16) Ray Shine Video Technology Inc + 6F,No.98,Sec.1,Xintai 5th Rd. + Xizhi City Taipei County 221 + TW + +00-1E-D4 (hex) Doble Engineering +001ED4 (base 16) Doble Engineering + 85 Walnut St + Watertown MA 02472 + US + +00-1E-FD (hex) Microbit 2.0 AB +001EFD (base 16) Microbit 2.0 AB + Nystaden 1 + KALIX 95261 + SE + +00-1E-E7 (hex) Epic Systems Inc +001EE7 (base 16) Epic Systems Inc + 390 S. Abbott Ave + Milpitas CA 95035 + US + +00-1E-E9 (hex) Stoneridge Electronics AB +001EE9 (base 16) Stoneridge Electronics AB + Gårdsfogdevägen 18A + Bromma Stockholm 168 66 + SE + +00-1F-1C (hex) KOBISHI ELECTRIC Co.,Ltd. +001F1C (base 16) KOBISHI ELECTRIC Co.,Ltd. + 1805-1 + Kounosu-shi Saitama-ken 365-0027 + JP + +00-1E-79 (hex) Cisco Systems, Inc +001E79 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-76 (hex) Thermo Fisher Scientific +001E76 (base 16) Thermo Fisher Scientific + 2215 Grand Avenue Parkway + Austin Texas 78728 + US + +00-1E-72 (hex) PCS +001E72 (base 16) PCS + 2 HENRI FARMAN + LESCAR PYRENEES ATLANTIQUES 64230 + FR + +00-1E-5F (hex) KwikByte, LLC +001E5F (base 16) KwikByte, LLC + 2430 W. 12th Street + Tempe AZ 85281 + US + +00-1E-5B (hex) Unitron Company, Inc. +001E5B (base 16) Unitron Company, Inc. + 10925 Miller Road + Dallas TX 75238 + US + +00-1E-5E (hex) COmputime Ltd. +001E5E (base 16) COmputime Ltd. + 17/F Great Eagle Centre + Wanchai + HK + +00-1E-9D (hex) Recall Technologies, Inc. +001E9D (base 16) Recall Technologies, Inc. + 130 Enterprise Ave. + Palm Bay FL 32909 + US + +00-1E-95 (hex) SIGMALINK +001E95 (base 16) SIGMALINK + DooSan VentureDigm 1028, + Anyang-City Kyunggi-do 431-070 + KR + +00-1E-93 (hex) CiriTech Systems Inc +001E93 (base 16) CiriTech Systems Inc + 920 Hillview Ct + Milpitas CA 95035 + US + +00-1E-A2 (hex) Symx Systems, Inc. +001EA2 (base 16) Symx Systems, Inc. + 6320 NW 84th Avenue + Miami Florida 33166 + US + +00-1E-A9 (hex) Nintendo Co., Ltd. +001EA9 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-1E-9E (hex) ddm hopt + schuler Gmbh + Co. KG +001E9E (base 16) ddm hopt + schuler Gmbh + Co. KG + Koenigsberger Strasse 12 + Rottweil Baden-Württemberg 78626 + DE + +00-1E-BE (hex) Cisco Systems, Inc +001EBE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-C3 (hex) Kozio, Inc. +001EC3 (base 16) Kozio, Inc. + 2015 Ionosphere Street + Longmont CO 80504 + US + +00-1E-BD (hex) Cisco Systems, Inc +001EBD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-B9 (hex) Sing Fai Technology Limited +001EB9 (base 16) Sing Fai Technology Limited + No.700, Kaohsiung University Rd., Nan-Tzu Dist. + Kaohsiung 811 + TW + +00-1E-B2 (hex) LG innotek +001EB2 (base 16) LG innotek + Hanyang Univ. 1271, Sa-dong, Sangrok-gu + Ansan-si Gyeonggi-do 426-791 + KR + +00-1E-B7 (hex) TBTech, Co., Ltd. +001EB7 (base 16) TBTech, Co., Ltd. + 1109, Hyundai Krim, 1330-18, Seocho-dong, + Seoul 137-070 + KR + +00-1E-69 (hex) Thomson Inc. +001E69 (base 16) Thomson Inc. + 101 West 103rd Street + Indianapolis IN 46290-1102 + US + +00-1E-92 (hex) JEULIN S.A. +001E92 (base 16) JEULIN S.A. + ZI N°1 + Evreux F27019 + FR + +00-1E-91 (hex) KIMIN Electronic Co., Ltd. +001E91 (base 16) KIMIN Electronic Co., Ltd. + 293-4, Dongdan-Dong + Gumi-city GyeongBuk 730-906 + KR + +00-1E-89 (hex) CRFS Limited +001E89 (base 16) CRFS Limited + Building 7200 + Waterbeach Cambridgeshire CB25 9TL + GB + +00-1E-86 (hex) MEL Co.,Ltd. +001E86 (base 16) MEL Co.,Ltd. + Tsukagoshi 5-5-1,Warabi-shi,Saitama,Japna + Warabi Saitama 335-0002 + JP + +00-1E-88 (hex) ANDOR SYSTEM SUPPORT CO., LTD. +001E88 (base 16) ANDOR SYSTEM SUPPORT CO., LTD. + Minami-Shinagawa 2-15-8 + Sinagawa Tokyo 140-0004 + JP + +00-1E-0C (hex) Sherwood Information Partners, Inc. +001E0C (base 16) Sherwood Information Partners, Inc. + 1120 W, 122nd Ave, Ste 300 + Westminster CO 80234 + US + +00-1E-02 (hex) Sougou Keikaku Kougyou Co.,Ltd. +001E02 (base 16) Sougou Keikaku Kougyou Co.,Ltd. + HK2 bld. 2-21-10 + Suginamiku Tokyo 167-0053 + JP + +00-1E-01 (hex) Renesas Technology Sales Co., Ltd. +001E01 (base 16) Renesas Technology Sales Co., Ltd. + 2-6-2 + Chiyoda-ku Tokyo 100-0004 + JP + +00-1D-FF (hex) Network Critical Solutions Ltd +001DFF (base 16) Network Critical Solutions Ltd + 12B Southview Park + Reading Berkshire RG45AF + GB + +00-1E-00 (hex) Shantou Institute of Ultrasonic Instruments +001E00 (base 16) Shantou Institute of Ultrasonic Instruments + No.77, Jinsha Road, + Shantou Guangdong 515041 + CN + +00-1E-54 (hex) TOYO ELECTRIC Corporation +001E54 (base 16) TOYO ELECTRIC Corporation + 1-39 HIKISAWA + KASUGAI AICHI 480-0393 + JP + +00-1E-3C (hex) Lyngbox Media AB +001E3C (base 16) Lyngbox Media AB + Diskettgatan 11B + Linkoping SE-58335 + SE + +00-1E-4D (hex) Welkin Sciences, LLC +001E4D (base 16) Welkin Sciences, LLC + 102 S. Tejon St, Suite 200 + Colorado Springs CO 80903 + US + +00-1E-4B (hex) City Theatrical +001E4B (base 16) City Theatrical + 475 Barell Ave + Carlstadt New Jersey 07072 + US + +00-1E-4A (hex) Cisco Systems, Inc +001E4A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-13 (hex) Cisco Systems, Inc +001E13 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-0D (hex) Micran Ltd. +001E0D (base 16) Micran Ltd. + Vershinina st. 47 + Tomsk Tomsk Region 634034 + RU + +00-1E-09 (hex) ZEFATEK Co.,LTD +001E09 (base 16) ZEFATEK Co.,LTD + 326-4 Gasandong, Geumcheongu + Seoul 153-802 + KR + +00-1E-06 (hex) WIBRAIN +001E06 (base 16) WIBRAIN + 306 JEI Plats B/D 459-11 Gasan-dong, Geumcheon-gu + SEOUL 153-803 + KR + +00-1E-31 (hex) INFOMARK CO.,LTD. +001E31 (base 16) INFOMARK CO.,LTD. + 5F.,Geown Bldg.,1360-53 + Seoul Seocho-dong,Seocho-gu 137-863 + KR + +00-1E-2C (hex) CyVerse Corporation +001E2C (base 16) CyVerse Corporation + Shoutou Roukubankan Bldg. 4F + Shibuya-ku Tokyo 150-0046 + JP + +00-1E-26 (hex) Digifriends Co. Ltd +001E26 (base 16) Digifriends Co. Ltd + Joyang B/D 6th Floor + Seoul 135-090 + KR + +00-1E-23 (hex) Electronic Educational Devices, Inc +001E23 (base 16) Electronic Educational Devices, Inc + 1903 S Grant St + Denver CO 80210 + US + +00-1D-F3 (hex) SBS Science & Technology Co., Ltd +001DF3 (base 16) SBS Science & Technology Co., Ltd + W2-B5/6 High-tech industrial park + ShenZhen GuangDong 518057 + CN + +00-1D-EE (hex) NEXTVISION SISTEMAS DIGITAIS DE TELEVISÃO LTDA. +001DEE (base 16) NEXTVISION SISTEMAS DIGITAIS DE TELEVISÃO LTDA. + Alameda Rio Negro, 1030 - 19o. andar conj. 1904 + Barueri São Paulo 06454-000 + BR + +00-1D-EA (hex) Commtest Instruments Ltd +001DEA (base 16) Commtest Instruments Ltd + Level 2, 22 Moorhouse Ave + Christchurch Canterbury 8243 + NZ + +00-1D-DD (hex) DAT H.K. LIMITED +001DDD (base 16) DAT H.K. LIMITED + Suite 1405 14/F., City Plaza 4, Tai Koo Wan Rd, + Tai Koo Shing Hong Kong Island 064828 + HK + +00-1D-E4 (hex) Visioneered Image Systems +001DE4 (base 16) Visioneered Image Systems + 10561 Garden Grove Blvd + Garden Grove California 92843 + US + +00-1D-E2 (hex) Radionor Communications +001DE2 (base 16) Radionor Communications + Ingvald Ystgaards veg 23 + Trondheim TRD 7046 + NO + +00-1D-D7 (hex) Algolith +001DD7 (base 16) Algolith + 400 Isabey + Saint-Laurent Qc H4T 1V3 + CA + +00-1D-C9 (hex) GainSpan Corp. +001DC9 (base 16) GainSpan Corp. + P.O. Box 223580 + Carmel CA 93922 + US + +00-1D-86 (hex) Shinwa Industries(China) Ltd. +001D86 (base 16) Shinwa Industries(China) Ltd. + 8 Pingnanzhong Road, Pingnan Industrial Park, Zhongkai No.4 Road, + Huizhou City Guangdong Province 516006 + CN + +00-1D-88 (hex) Clearwire +001D88 (base 16) Clearwire + 1475 120th Ave NE + Bellevue Washington 98005 + US + +00-1D-81 (hex) GUANGZHOU GATEWAY ELECTRONICS CO., LTD +001D81 (base 16) GUANGZHOU GATEWAY ELECTRONICS CO., LTD + B20#,4F,No.9 Jiangong Road,Tianhe Software Park,Tianhe District, + GUANGZHOU Guangdong 510665 + CN + +00-1D-7D (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +001D7D (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + + Pin-Jen Taoyuan 324 + TW + +00-1D-C7 (hex) L-3 Communications Geneva Aerospace +001DC7 (base 16) L-3 Communications Geneva Aerospace + 4240 International Parkway + Carrollton Texas 75007 + US + +00-1D-89 (hex) VaultStor Corporation +001D89 (base 16) VaultStor Corporation + 1010 Brioso Drive + Costa Mesa CA 92627 + US + +00-1D-66 (hex) Hyundai Telecom +001D66 (base 16) Hyundai Telecom + Hyundai Telecom Bldg., 4273-12, Shingil-Dong, Youngdungpo-Gu, + Seoul 150-859 + KR + +00-1D-77 (hex) NSGate +001D77 (base 16) NSGate + Rm 1304, 39 Kirpichnaya Street + Moscow 105187 + RU + +00-1D-A2 (hex) Cisco Systems, Inc +001DA2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1D-99 (hex) Cyan Optic, Inc. +001D99 (base 16) Cyan Optic, Inc. + 1390 N. McDowell Blvd + Petaluma CA 94954 + US + +00-1D-9B (hex) Hokuyo Automatic Co., Ltd. +001D9B (base 16) Hokuyo Automatic Co., Ltd. + Niitaka 1-10-9 + Osaka 532-0033 + JP + +00-1D-BC (hex) Nintendo Co., Ltd. +001DBC (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-1D-B6 (hex) BestComm Networks, Inc. +001DB6 (base 16) BestComm Networks, Inc. + 4400 E. Broadway Blvd. + Tucson AZ 85711 + US + +00-1D-AC (hex) Gigamon Systems LLC +001DAC (base 16) Gigamon Systems LLC + 598 Gibraltar Drive + Milpitas CA 95035 + US + +00-1D-15 (hex) Shenzhen Dolphin Electronic Co., Ltd +001D15 (base 16) Shenzhen Dolphin Electronic Co., Ltd + Building21,Baoyuan, No.1 Industrial Zone, + Shenzhen Guangdong 518103 + CN + +00-1D-16 (hex) SFR +001D16 (base 16) SFR + 40/42 Quai du point du jour + Boulongne Billancourt Hauts de Seine 92659 + FR + +00-1D-11 (hex) Analogue & Micro Ltd +001D11 (base 16) Analogue & Micro Ltd + Lakeside House + Llantarnam Industrial Park Cwmbran NP44 3XS + GB + +00-1D-12 (hex) ROHM CO., LTD. +001D12 (base 16) ROHM CO., LTD. + 21 Saiin-Mizosaki-cho, + Kyoto-shi KYOTO 615-8585 + JP + +00-1D-47 (hex) Covote GmbH & Co KG +001D47 (base 16) Covote GmbH & Co KG + Ritterhufen 30 + Berlin 14165 + DE + +00-1D-41 (hex) Hardy Instruments +001D41 (base 16) Hardy Instruments + 3860 Calle Fortunada + San Diego CA 92123 + US + +00-1D-3D (hex) Avidyne Corporation +001D3D (base 16) Avidyne Corporation + 202 West Dr + Melbourne FL 32904 + US + +00-1D-3C (hex) Muscle Corporation +001D3C (base 16) Muscle Corporation + 2-5-35, Kikawa-higashi + Osaka 532-0012 + JP + +00-1D-3A (hex) mh acoustics LLC +001D3A (base 16) mh acoustics LLC + 25A Summit Ave + Summit NJ 07901 + US + +00-1D-49 (hex) Innovation Wireless Inc. +001D49 (base 16) Innovation Wireless Inc. + 4F-1, NO.81, SHUEILI RD. + HSINCHU 30059 + TW + +00-1D-46 (hex) Cisco Systems, Inc +001D46 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1D-48 (hex) Sensor-Technik Wiedemann GmbH +001D48 (base 16) Sensor-Technik Wiedemann GmbH + Am Bärenwald 6 + Kaufbeuren Bayern 87600 + DE + +00-1D-76 (hex) Eyeheight Ltd. +001D76 (base 16) Eyeheight Ltd. + Unit 34, Park House + Watford Herts WD18 8PH + GB + +00-1D-7A (hex) Wideband Semiconductor, Inc. +001D7A (base 16) Wideband Semiconductor, Inc. + 1350 Pear Ave + Mountain View CA 94043 + US + +00-1D-68 (hex) Thomson Telecom Belgium +001D68 (base 16) Thomson Telecom Belgium + Prins Boudewijnlaan 47 + Edegem Antwerp B-2650 + BE + +00-1D-26 (hex) Rockridgesound Technology Co. +001D26 (base 16) Rockridgesound Technology Co. + Fumin Industrial Park, Houjie Town + Dong Guan Guang Dong 523956 + CN + +00-1D-35 (hex) Viconics Electronics Inc. +001D35 (base 16) Viconics Electronics Inc. + 9245 Langelier + Saint Leonard Quebec H1P3K9 + CA + +00-1D-31 (hex) HIGHPRO INTERNATIONAL R&D CO,.LTD. +001D31 (base 16) HIGHPRO INTERNATIONAL R&D CO,.LTD. + 3F,No.295,RuiGuang Rd,Nei Hu, + Taipei 114 + TW + +00-1D-61 (hex) BIJ Corporation +001D61 (base 16) BIJ Corporation + 7F Takamizawa Building,2-7-10, + Yokohama Kanagawa 220-0004 + JP + +00-1D-5C (hex) Tom Communication Industrial Co.,Ltd. +001D5C (base 16) Tom Communication Industrial Co.,Ltd. + 1173 Nippa-choh Kohoku-ku + Yokohama Kanagawa 223-0057 + JP + +00-1D-56 (hex) Kramer Electronics Ltd. +001D56 (base 16) Kramer Electronics Ltd. + 3 Am VeOlamo Street + Jerusalem 95463 + IL + +00-1D-4E (hex) TCM Mobile LLC +001D4E (base 16) TCM Mobile LLC + 9218 Metcalf, + Overland Park Kansas 66212 + US + +00-1D-21 (hex) Alcad SL +001D21 (base 16) Alcad SL + Pol. Ind. Arreche-Ugalde, 1 + Irún Guipúzcoa E-20305 + ES + +00-1D-1C (hex) Gennet s.a. +001D1C (base 16) Gennet s.a. + 2 Mesogeion ave. + Athens Attiki 11527 + GR + +00-1C-E1 (hex) INDRA SISTEMAS, S.A. +001CE1 (base 16) INDRA SISTEMAS, S.A. + Ctra. de Loeches, n.º 9 + Torrejón de Ardoz MADRID 28850 + ES + +00-1C-E0 (hex) DASAN TPS +001CE0 (base 16) DASAN TPS + HUMAX Village 6F, 11-4 Sunae-dong, Bundang-gu + Seongnam-si Gyeonggi-do 463-825 + KR + +00-1C-D9 (hex) GlobalTop Technology Inc. +001CD9 (base 16) GlobalTop Technology Inc. + 16 Nan-ke 9th Rd. Science-base Industrial Park, + ShanHua Tainan county 741 + TW + +00-1C-DA (hex) Exegin Technologies Limited +001CDA (base 16) Exegin Technologies Limited + 401 - 2071 Kingsway Avenue + Port Coquitlam BC V3C 6N2 + CA + +00-1C-D2 (hex) King Champion (Hong Kong) Limited +001CD2 (base 16) King Champion (Hong Kong) Limited + Unit 1520, 15/F, Phase 1, Metro Centre, + Kowloon + HK + +00-1C-A6 (hex) Win4NET +001CA6 (base 16) Win4NET + 1301 KOLON Digital Tower, + Kuro-gu Seoul 152-848 + KR + +00-1C-A9 (hex) Audiomatica Srl +001CA9 (base 16) Audiomatica Srl + Via Manfredi 12 + Florence Italy 50136 + IT + +00-1C-A1 (hex) AKAMAI TECHNOLOGIES, INC. +001CA1 (base 16) AKAMAI TECHNOLOGIES, INC. + 8 CAMBRIDGE CENTER + CAMBRIDGE MA 02142 + US + +00-1C-99 (hex) Shunra Software Ltd. +001C99 (base 16) Shunra Software Ltd. + 20 Hata'as St. + Kefar-Saba 44425 + IL + +00-1C-F9 (hex) Cisco Systems, Inc +001CF9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1C-F1 (hex) SUPoX Technology Co. , LTD. +001CF1 (base 16) SUPoX Technology Co. , LTD. + 7F, 419 , Chung San Rd. , Sec 2 + Chung Ho Taipei Hsien 235 + TW + +00-1C-CE (hex) By Techdesign +001CCE (base 16) By Techdesign + C/ Tomas Edison 5 + Arganda del Rey Madrid 28500 + ES + +00-1C-F3 (hex) EVS BROADCAST EQUIPMENT +001CF3 (base 16) EVS BROADCAST EQUIPMENT + Liege Science Park + Ougree Liege 4102 + BE + +00-1C-F4 (hex) Media Technology Systems Inc +001CF4 (base 16) Media Technology Systems Inc + 766 Lakefield Road + Westlake Village CA 91377 + US + +00-1C-E6 (hex) INNES +001CE6 (base 16) INNES + 80 avenue des Buttes de Coësmes + RENNES 35700 + FR + +00-1C-B9 (hex) KWANG SUNG ELECTRONICS CO., LTD. +001CB9 (base 16) KWANG SUNG ELECTRONICS CO., LTD. + 201, WORLD VENTURE TOWN 60-24, GASAN-DONG GEUMCHUN-GU, + SEOUL 153-801 + KR + +00-1D-03 (hex) Design Solutions Inc. +001D03 (base 16) Design Solutions Inc. + 81 David Love Place + Goleta Ca 93117 + US + +00-1C-A3 (hex) Terra +001CA3 (base 16) Terra + Draugystes str. 22 + Kaunas LT-51256 + LT + +00-1C-90 (hex) Empacket Corporation +001C90 (base 16) Empacket Corporation + 2-6-3 Nishi-Gotanda + Shinagawa Tokyo 141-0031 + JP + +00-1C-8E (hex) Alcatel-Lucent IPD +001C8E (base 16) Alcatel-Lucent IPD + 701 E. Middlefield Rd. + Mountain View CA 94043 + US + +00-1C-8F (hex) Advanced Electronic Design, Inc. +001C8F (base 16) Advanced Electronic Design, Inc. + 344 John L Dietsch Blvd., Unit #2 + North Attleboro MA 02763 + US + +00-1C-88 (hex) TRANSYSTEM INC. +001C88 (base 16) TRANSYSTEM INC. + No. 1-2, Li-Hsin Rd 1, Science-Based Industrial Park + Hsinchu 300 + TW + +00-1C-86 (hex) Cranite Systems, Inc. +001C86 (base 16) Cranite Systems, Inc. + 121 Albright Way + Los Gatos CA 95032 + US + +00-1C-4F (hex) MACAB AB +001C4F (base 16) MACAB AB + Vannhögsgatan 7 + Trelleborg 23166 + SE + +00-1C-4E (hex) TASA International Limited +001C4E (base 16) TASA International Limited + 5F£¬Building2£¬No.1295 ,Xin Jinqiao Road, + Shanghai 201206 + CN + +00-1C-4B (hex) Gener8, Inc. +001C4B (base 16) Gener8, Inc. + 897 Independence Ave + Mountain View CA 94043 + US + +00-1C-9B (hex) FEIG ELECTRONIC GmbH +001C9B (base 16) FEIG ELECTRONIC GmbH + Lange Straße 4 + Weilburg Hessen 35781 + DE + +00-1C-95 (hex) Opticomm Corporation +001C95 (base 16) Opticomm Corporation + 6827 Nancy Ridge Dr + San Diego CA 92121 + US + +00-1C-97 (hex) Enzytek Technology Inc., +001C97 (base 16) Enzytek Technology Inc., + 7F, No.35, Hsueh Fu Rd., + Hsinchu 300, + TW + +00-1C-70 (hex) NOVACOMM LTDA +001C70 (base 16) NOVACOMM LTDA + RUA BEIJUI, 70 + São Paulo 04689-000 + BR + +00-1C-6E (hex) Newbury Networks, Inc. +001C6E (base 16) Newbury Networks, Inc. + 419 Boylston Street + Boston MA 02116 + US + +00-1C-6B (hex) COVAX Co. Ltd +001C6B (base 16) COVAX Co. Ltd + 3-27-22 kitahanada-cho kitaku + sakai-shi oosaka 591-8002 + JP + +00-1C-69 (hex) Packet Vision Ltd +001C69 (base 16) Packet Vision Ltd + SC House + Maidenhead Berks SL6 4UB + GB + +00-1C-3D (hex) WaveStorm +001C3D (base 16) WaveStorm + Rue d'Oradour-sur-Glâne + Paris ÃŽle-de-France 75015 + FR + +00-1C-7F (hex) Check Point Software Technologies +001C7F (base 16) Check Point Software Technologies + 3A Jabotinsky St. + Ramat Gan 52520 + IL + +00-1C-78 (hex) WYPLAY SAS +001C78 (base 16) WYPLAY SAS + 200 avenue de Provence + ALLAUCH BdR 13190 + FR + +00-1C-58 (hex) Cisco Systems, Inc +001C58 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1C-5A (hex) Advanced Relay Corporation +001C5A (base 16) Advanced Relay Corporation + 1896 Columbia St + Eugene OR 97403 + US + +00-1C-65 (hex) JoeScan, Inc. +001C65 (base 16) JoeScan, Inc. + 4510 NE 68th Dr, Ste. 124 + Vancouver WA 98661 + US + +00-1C-5F (hex) Winland Electronics, Inc. +001C5F (base 16) Winland Electronics, Inc. + 1950 Excel Drive + Mankato MN 56001 + US + +00-1C-40 (hex) VDG-Security bv +001C40 (base 16) VDG-Security bv + Radonstraat 10-14 + Zoetermeer ZH 2718 TA + NL + +00-1C-3A (hex) Element Labs, Inc. +001C3A (base 16) Element Labs, Inc. + 3350 Scott Boulevard + Santa Clara CA 95054 + US + +00-1C-18 (hex) Sicert S.r.L. +001C18 (base 16) Sicert S.r.L. + Via Bernardino Alimena, 128 + Rome 00173 + IT + +00-1C-1A (hex) Thomas Instrumentation, Inc +001C1A (base 16) Thomas Instrumentation, Inc + 133 Landing Rd + Cape May Court House NJ 08210 + US + +00-1C-0E (hex) Cisco Systems, Inc +001C0E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1C-13 (hex) OPTSYS TECHNOLOGY CO., LTD. +001C13 (base 16) OPTSYS TECHNOLOGY CO., LTD. + SUITE B-802 BUNDANG TECHNO PARK + SEONGNAM-SI GYEONGGI-DO 463-760 + KR + +00-1C-0B (hex) SmartAnt Telecom +001C0B (base 16) SmartAnt Telecom + 2F, No. 669, Sec. 4, Chung Hsing Rd., Chutung + Hsinchu 310 + TW + +00-1B-D0 (hex) IDENTEC SOLUTIONS +001BD0 (base 16) IDENTEC SOLUTIONS + Hertzstraße 10 + Weinheim 69469 + DE + +00-1B-CD (hex) DAVISCOMMS (S) PTE LTD +001BCD (base 16) DAVISCOMMS (S) PTE LTD + Blk 70 Ubi Crescent #01-07 + 408570 + SG + +00-1B-CA (hex) Beijing Run Technology LTD. Company +001BCA (base 16) Beijing Run Technology LTD. Company + 4/F, Hangtian Technology Building + Beijing 100037 + CN + +00-1B-CC (hex) KINGTEK CCTV ALLIANCE CO., LTD. +001BCC (base 16) KINGTEK CCTV ALLIANCE CO., LTD. + 5F-3, NO. 106, SEC. 3, HSIN YI ROAD + TAIPEI 106 + TW + +00-1B-F4 (hex) KENWIN INDUSTRIAL(HK) LTD. +001BF4 (base 16) KENWIN INDUSTRIAL(HK) LTD. + RM.1512 15/F SHATIN GALLERIA + + HK + +00-1B-F9 (hex) Intellitect Water Ltd +001BF9 (base 16) Intellitect Water Ltd + Suite 19, Basepoint Business Centre + Christchurch Dorset BH23 ^NW + GB + +00-1B-FA (hex) G.i.N. mbH +001BFA (base 16) G.i.N. mbH + Raiffeisenstraße 15 + Griesheim Hessen 64347 + DE + +00-1B-F3 (hex) TRANSRADIO SenderSysteme Berlin AG +001BF3 (base 16) TRANSRADIO SenderSysteme Berlin AG + Mertensstrasse 63 + Berlin 13587 + DE + +00-1C-21 (hex) Nucsafe Inc. +001C21 (base 16) Nucsafe Inc. + 601 Oak Ridge Turnpike + Oak Ridge Tennessee 37830 + US + +00-1C-1E (hex) emtrion GmbH +001C1E (base 16) emtrion GmbH + Alter Schlachthof 45 + Karlsruhe Baden Wuerttemberg 76131 + DE + +00-1B-DE (hex) Renkus-Heinz, Inc. +001BDE (base 16) Renkus-Heinz, Inc. + 19201 Cook St. + Foothill Ranch CA 92610 + US + +00-1B-DB (hex) Valeo VECS +001BDB (base 16) Valeo VECS + 2 Avenue Fernand Pouillon + CRETEIL Ile de France 94042 + FR + +00-1B-D8 (hex) FLIR Systems Inc +001BD8 (base 16) FLIR Systems Inc + 65 Challenger Road + Ridgefield Park NJ 07660-2103 + US + +00-1B-D4 (hex) Cisco Systems, Inc +001BD4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1C-2D (hex) FlexRadio Systems +001C2D (base 16) FlexRadio Systems + 8900 Marybank Dr. + Austin TX 78750 + US + +00-1C-2C (hex) Synapse +001C2C (base 16) Synapse + 132 Export Circle + Huntsville AL 35806 + US + +00-1C-08 (hex) Echo360, Inc. +001C08 (base 16) Echo360, Inc. + 11955 Freedom Drive + Reston VA 20190 + US + +00-1B-C8 (hex) MIURA CO.,LTD +001BC8 (base 16) MIURA CO.,LTD + 620-1,Nakanishisoto + Matsuyama Ehime 799-2425 + JP + +00-1B-C1 (hex) HOLUX Technology, Inc. +001BC1 (base 16) HOLUX Technology, Inc. + 1F, No. 30, R&D Rd. II, + Hsinchu 300 + TW + +00-1B-BC (hex) Silver Peak Systems, Inc. +001BBC (base 16) Silver Peak Systems, Inc. + 471 El Camino Real + Santa Clara CA 95050 + US + +00-1B-73 (hex) DTL Broadcast Ltd +001B73 (base 16) DTL Broadcast Ltd + Johnson's Estate + HAYES Middlesex UB3 3BA + GB + +00-1B-71 (hex) Telular Corp. +001B71 (base 16) Telular Corp. + 311 South Wacker Drive + Chicago IL 60606 + US + +00-1B-97 (hex) Violin Technologies +001B97 (base 16) Violin Technologies + 33 Wood Ave South + Iselin NJ 08830 + US + +00-1B-A8 (hex) UBI&MOBI,.Inc +001BA8 (base 16) UBI&MOBI,.Inc + 3F, Duido Bldg, #288-5, Yangjae-Dong + Seocho-Gu Seoul 137-130 + KR + +00-1B-81 (hex) DATAQ Instruments, Inc. +001B81 (base 16) DATAQ Instruments, Inc. + 241 Springside Drive + Akron Ohio 44333 + US + +00-1B-7D (hex) CXR Anderson Jacobson +001B7D (base 16) CXR Anderson Jacobson + Rue de l'ornette + Abondant 28410 + FR + +00-1B-79 (hex) FAIVELEY TRANSPORT +001B79 (base 16) FAIVELEY TRANSPORT + ZI du bois de plante + LA VILLE AUX DAMES 37700 + FR + +00-1B-65 (hex) China Gridcom Co., Ltd +001B65 (base 16) China Gridcom Co., Ltd + 21/F, Huaneng Building, No. 2068 Shennan Main Road + Shenzhen Guangdong 0086 + CN + +00-1B-88 (hex) Divinet Access Technologies Ltd +001B88 (base 16) Divinet Access Technologies Ltd + 4th Floor, Media Center, + Pune Maharashtra 411007 + IN + +00-1B-83 (hex) Finsoft Ltd +001B83 (base 16) Finsoft Ltd + 16-18 Hatton Garden + London EC1N 8AT + GB + +00-1B-AB (hex) Telchemy, Incorporated +001BAB (base 16) Telchemy, Incorporated + 2905 Premiere Parkway + Duluth GA 30097 + US + +00-1B-AE (hex) Micro Control Systems, Inc +001BAE (base 16) Micro Control Systems, Inc + 5580 Enterprise Parkway + Fort Myers Florida 33905 + US + +00-1B-A0 (hex) Awox +001BA0 (base 16) Awox + 93, Place Pierre Duhem, + Montpellier Herault 34000 + FR + +00-1B-51 (hex) Vector Technology Corp. +001B51 (base 16) Vector Technology Corp. + No.7, Lane12, Yajou Road. + Tucheng Taipei 236 + TW + +00-1B-54 (hex) Cisco Systems, Inc +001B54 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1B-4A (hex) W&W Communications, Inc. +001B4A (base 16) W&W Communications, Inc. + 2903 Bunker Hill Lane + Santa Clara CA 95054 + US + +00-1A-FA (hex) Welch Allyn, Inc. +001AFA (base 16) Welch Allyn, Inc. + 4619 Jordan Road + Skaneateles Falls NY 13153-0187 + US + +00-1A-F7 (hex) dataschalt e+a GmbH +001AF7 (base 16) dataschalt e+a GmbH + An der Hülshorst 7-9 + Lübeck 23568 + DE + +00-1A-F3 (hex) Samyoung Electronics +001AF3 (base 16) Samyoung Electronics + 146-1, sangdaewon-dong, joongwon-gu + sungnam-shi Gyunggi-do 462-807 + KR + +00-1A-EF (hex) Loopcomm Technology, Inc. +001AEF (base 16) Loopcomm Technology, Inc. + 18F-1, No. 150, Jian Yi Rd., + Chung-Ho City Taipei Hsien 235 + TW + +00-1A-EC (hex) Keumbee Electronics Co.,Ltd. +001AEC (base 16) Keumbee Electronics Co.,Ltd. + 3-26, Jangsang-dong, Sangrok-gu + Ansan-si Kyungki-do 426-410 + KR + +00-1B-44 (hex) SanDisk Corporation +001B44 (base 16) SanDisk Corporation + 601 McCarthy Boulevard + Milpitas CA 95035 + US + +00-1B-46 (hex) Blueone Technology Co.,Ltd +001B46 (base 16) Blueone Technology Co.,Ltd + Room 309,3 Floor, 404 Building, ShangBu industrial + Shenzhen Guangdong 518028 + CN + +00-1B-40 (hex) Network Automation mxc AB +001B40 (base 16) Network Automation mxc AB + Box 7294 + Stockholm 10390 + SE + +00-1B-42 (hex) Wise & Blue +001B42 (base 16) Wise & Blue + #715-3 Anyang Megavalley + Anyang-Si Gyunggi-Do 431-767 + KR + +00-1B-35 (hex) ChongQing JINOU Science & Technology Development CO.,Ltd +001B35 (base 16) ChongQing JINOU Science & Technology Development CO.,Ltd + Chuangyeyuan 208# Keyuan 3rd Road 106# + Chongqing 400030 + CN + +00-1B-36 (hex) Tsubata Engineering Co.,Ltd. (Head Office) +001B36 (base 16) Tsubata Engineering Co.,Ltd. (Head Office) + Koyanagi 1-2 + Ibaraki Osaka 567-0852 + JP + +00-1B-39 (hex) Proxicast +001B39 (base 16) Proxicast + 312 Sunnyfield Drive + Glenshaw PA 15116 + US + +00-1B-3B (hex) Yi-Qing CO., LTD +001B3B (base 16) Yi-Qing CO., LTD + 310 ROOM,12F + TAIPEI 100 + TW + +00-1B-20 (hex) TPine Technology +001B20 (base 16) TPine Technology + 3F, No.1, AN-I Rd, + Keelung 111 + TW + +00-1B-22 (hex) Palit Microsystems ( H.K.) Ltd. +001B22 (base 16) Palit Microsystems ( H.K.) Ltd. + Room 4-6,11F,Nan Fung Commercial Center + Kowloon 111 + HK + +00-1B-1C (hex) Coherent +001B1C (base 16) Coherent + 1280 Blues Hills Ave. + Bloomfield CT 06002 + US + +00-1B-19 (hex) IEEE I&M Society TC9 +001B19 (base 16) IEEE I&M Society TC9 + 100 Bureau Dr., Mail Stop 8220 + Gaithersburg MD 20899-8220 + US + +00-1B-64 (hex) IsaacLandKorea Co., Ltd, +001B64 (base 16) IsaacLandKorea Co., Ltd, + Rm 608, Hangang-Hyundai-Hyel Bldg. 2-36, + Seoul 140-871 + KR + +00-1B-26 (hex) RON-Telecom ZAO +001B26 (base 16) RON-Telecom ZAO + 15 A, Zarechnaya st. + Trehgorny Chelyabinsk region 456080 + RU + +00-1B-13 (hex) Icron Technologies Corporation +001B13 (base 16) Icron Technologies Corporation + 221 - 4664 Lougheed Highway + Burnaby BC V5C 5T5 + CA + +00-1B-0F (hex) Petratec +001B0F (base 16) Petratec + 12 Derech HaSharon + Kfar Saba Sharon 44271 + IL + +00-1A-A9 (hex) FUJIAN STAR-NET COMMUNICATION CO.,LTD +001AA9 (base 16) FUJIAN STAR-NET COMMUNICATION CO.,LTD + 19-22# Building, Star-net Science Plaza, Juyuanzhou, + FUZHOU FUJIAN 350002 + CN + +00-1A-A8 (hex) Mamiya Digital Imaging Co., Ltd. +001AA8 (base 16) Mamiya Digital Imaging Co., Ltd. + 2-2, 1-chome, Koraku + Bunkyo-ku Tokyo 112-0004 + JP + +00-1A-99 (hex) Smarty (HZ) Information Electronics Co., Ltd +001A99 (base 16) Smarty (HZ) Information Electronics Co., Ltd + Yonghua Industrial District,Huishen Road,Zhenlong Town + HuiZhou GuangDong 516227 + CN + +00-1A-A6 (hex) Telefunken Radio Communication Systems GmbH &CO.KG +001AA6 (base 16) Telefunken Radio Communication Systems GmbH &CO.KG + Eberhard-Finckh-Strasse 55 + Ulm Baden-Wurttemberg 89075 + DE + +00-1A-96 (hex) ECLER S.A. +001A96 (base 16) ECLER S.A. + Motors 166-168 + Barcelona 08038 + ES + +00-1A-91 (hex) FusionDynamic Ltd. +001A91 (base 16) FusionDynamic Ltd. + 1 B.S.R. towers, 4-th floor + Ramat Gan 52573 + IL + +00-1A-8C (hex) Sophos Ltd +001A8C (base 16) Sophos Ltd + The Pentagon + Abingdon Oxfordshire OX14 3YP + GB + +00-1A-B3 (hex) VISIONITE INC. +001AB3 (base 16) VISIONITE INC. + #707 Daeryung Technotown-2 569-21 + Seoul 153-771 + KR + +00-1A-CA (hex) Tilera Corporation +001ACA (base 16) Tilera Corporation + 1900 West Park Drive + Westborough MA 01581 + US + +00-1A-84 (hex) V One Multimedia Pte Ltd +001A84 (base 16) V One Multimedia Pte Ltd + Blk 54, Kallang Bahru + 339336 + SG + +00-1A-B9 (hex) PMC +001AB9 (base 16) PMC + 56, avenue Raspail + Saint Maur 94100 + FR + +00-1A-BA (hex) Caton Overseas Limited +001ABA (base 16) Caton Overseas Limited + Room 102, No. 101, Lane 91 + Shanghai 200127 + CN + +00-1A-D1 (hex) FARGO CO., LTD. +001AD1 (base 16) FARGO CO., LTD. + 4F. KYEMYUNG B/D + SEOUL 135 885 + KR + +00-1A-3A (hex) Dongahelecomm +001A3A (base 16) Dongahelecomm + 678-3,Jeil-ri,Yanggi-myun,Cheoin-gu + Yongin-si Gyeonggi-do 449-821 + KR + +00-1A-3B (hex) Doah Elecom Inc. +001A3B (base 16) Doah Elecom Inc. + 8th fl. Century Plaza, 277-40 + Seoul 133-123 + KR + +00-1A-3C (hex) Technowave Ltd. +001A3C (base 16) Technowave Ltd. + Sakurai Bldg.1F, + Musashino-shi Tokyo 180-0006 + JP + +00-1A-40 (hex) A-FOUR TECH CO., LTD. +001A40 (base 16) A-FOUR TECH CO., LTD. + 6F, No. 108, Min-Chuan Rd., + Hsin-Tien Taipei 23141 + TW + +00-1A-30 (hex) Cisco Systems, Inc +001A30 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1A-7B (hex) Teleco, Inc. +001A7B (base 16) Teleco, Inc. + 430 Woodruff Rd. + Greenville SC 29607 + US + +00-1A-36 (hex) Aipermon GmbH & Co. KG +001A36 (base 16) Aipermon GmbH & Co. KG + Zamdorfer Str. 100 + Munich Bavaria D-81677 + DE + +00-1A-26 (hex) Deltanode Solutions AB +001A26 (base 16) Deltanode Solutions AB + Box 92 184 + Stockholm 120 09 + SE + +00-1A-6D (hex) Cisco Systems, Inc +001A6D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1A-6E (hex) Impro Technologies +001A6E (base 16) Impro Technologies + 47B Gillits Rd + Pinetown KwaZulu-Natal 3610 + ZA + +00-1A-6C (hex) Cisco Systems, Inc +001A6C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1A-4A (hex) Qumranet Inc. +001A4A (base 16) Qumranet Inc. + 530 Lakeside Drive + Sunnyvale California 94085 + US + +00-1A-3E (hex) Faster Technology LLC +001A3E (base 16) Faster Technology LLC + 1812 Avenue D + Katy Texas 77493 + US + +00-1A-63 (hex) Elster Solutions, LLC, +001A63 (base 16) Elster Solutions, LLC, + 208 South Rogers Lane + Raleigh NC 27610 + US + +00-1A-59 (hex) Ircona +001A59 (base 16) Ircona + Unit 4B-1, Corporate Park + Blanchardstown Dublin 15 + IE + +00-1A-46 (hex) Digital Multimedia Technology Co., Ltd +001A46 (base 16) Digital Multimedia Technology Co., Ltd + Doorim Bldg, 3rd Fl, 164-21 Poi-Dong, + Seoul Kangnam-Gu 135-960 + KR + +00-1A-25 (hex) DELTA DORE +001A25 (base 16) DELTA DORE + BONNEMAIN + COMBOURG BRETAGNE 35 35270 + FR + +00-19-FE (hex) SHENZHEN SEECOMM TECHNOLOGY CO.,LTD. +0019FE (base 16) SHENZHEN SEECOMM TECHNOLOGY CO.,LTD. + Room 609,404Yannan Road + ShenZhen Guangdong + CN + +00-19-FD (hex) Nintendo Co., Ltd. +0019FD (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-1A-0D (hex) HandHeld entertainment, Inc. +001A0D (base 16) HandHeld entertainment, Inc. + 539 Bryant Street, Suite 403 + San Francisco CA 94103 + US + +00-1A-0E (hex) Cheng Uei Precision Industry Co.,Ltd +001A0E (base 16) Cheng Uei Precision Industry Co.,Ltd + Junda Industry District, Dongkeng Town,Dongguan City + DongGuan Guang Dong 523455 + CN + +00-19-CD (hex) Chengdu ethercom information technology Ltd. +0019CD (base 16) Chengdu ethercom information technology Ltd. + South Extension of Tianfu Wide Road No.7 department room 201 + Chengdu Sichuan 610041 + CN + +00-19-D9 (hex) Zeutschel GmbH +0019D9 (base 16) Zeutschel GmbH + Heerweg 2 + Tübingen-Hirschau BW D-72070 + DE + +00-1A-01 (hex) Smiths Medical +001A01 (base 16) Smiths Medical + 4350 Rivergreen Parkway + Duluth GA 30096 + US + +00-19-CA (hex) Broadata Communications, Inc +0019CA (base 16) Broadata Communications, Inc + 2545 W 237th St Ste K + Torrance CA 90505 + US + +00-19-D3 (hex) TRAK Microwave +0019D3 (base 16) TRAK Microwave + 4726 Eisenhower Blvd + Tampa FL 33634 + US + +00-19-C3 (hex) Qualitrol +0019C3 (base 16) Qualitrol + Wildflower Way + Belfast Co. Antrim BT12 6TA + GB + +00-19-BE (hex) Altai Technologies Limited +0019BE (base 16) Altai Technologies Limited + 2/F, East Wing, Lakeside 2, 10 Science Park West Avenue, + Shatin New Territories + HK + +00-19-B4 (hex) Intellio Ltd +0019B4 (base 16) Intellio Ltd + Gyarmat u. 99/B + Budapest 1147 + HU + +00-19-BA (hex) Paradox Security Systems Ltd +0019BA (base 16) Paradox Security Systems Ltd + 780 Industrial Blvd + St-Eustache Quebec J7R 5V3 + CA + +00-19-A1 (hex) LG INFORMATION & COMM. +0019A1 (base 16) LG INFORMATION & COMM. + 60-39,Kasan-dong,Kumchon-ku + Seoul 153-023 + KR + +00-19-A8 (hex) WiQuest Communications +0019A8 (base 16) WiQuest Communications + 915 Enterprise Blvd. + Allen Texas 75013 + US + +00-19-ED (hex) Axesstel Inc. +0019ED (base 16) Axesstel Inc. + 6815 Flanders Sr. + San Diego CA 92121 + US + +00-19-F6 (hex) Acconet (PTE) Ltd +0019F6 (base 16) Acconet (PTE) Ltd + No. 16 Ayer Rajah Crescent + Singapore 139965 + SG + +00-1A-15 (hex) gemalto e-Payment +001A15 (base 16) gemalto e-Payment + 6 rue de la Verrerie + Meudon 92197 + FR + +00-19-68 (hex) Digital Video Networks(Shanghai) CO. LTD. +001968 (base 16) Digital Video Networks(Shanghai) CO. LTD. + 9th Floor,Hechuan Building, No.1026 YiShan Rd + Shanghai 201103 + CN + +00-19-7F (hex) PLANTRONICS, INC. +00197F (base 16) PLANTRONICS, INC. + 345 ENCINAL STREET + SANTA CRUZ CA 95060 + US + +00-19-7A (hex) MAZeT GmbH +00197A (base 16) MAZeT GmbH + Goeschwitzer Str. 32 + Jena D-07745 + DE + +00-19-78 (hex) Datum Systems, Inc. +001978 (base 16) Datum Systems, Inc. + 3666 Tiffani Ct. + Santa Cruz CA 95065 + US + +00-19-89 (hex) Sonitrol Corporation +001989 (base 16) Sonitrol Corporation + 1707 Orlando Central Pkwy. + Orlando FL 32809 + US + +00-19-8E (hex) Oticon A/S +00198E (base 16) Oticon A/S + Kongebakken 9 + Smørum 2765 + DK + +00-19-80 (hex) Gridpoint Systems +001980 (base 16) Gridpoint Systems + 4043 Carling Avenue, Suite 200 + Ottawa Ontario K2K 2A3 + CA + +00-19-83 (hex) CCT R&D Limited +001983 (base 16) CCT R&D Limited + 18/F CCT Telecom Building + Fotan, Shatin N.T. 000 + HK + +00-19-4C (hex) Fujian Stelcom information & Technology CO.,Ltd +00194C (base 16) Fujian Stelcom information & Technology CO.,Ltd + 4F,Building A,Start Science Park, No.68,Hongshanyuan Rd + Fuzhou Fujian 350002 + CN + +00-19-4A (hex) TESTO AG +00194A (base 16) TESTO AG + Testo Straße 1 + Lenzkirch Baden-Württemberg 79853 + DE + +00-19-8A (hex) Northrop Grumman Systems Corp. +00198A (base 16) Northrop Grumman Systems Corp. + 7055 Troy Hill Drive + Elkridge Maryland 21075 + US + +00-19-60 (hex) DoCoMo Systems, Inc. +001960 (base 16) DoCoMo Systems, Inc. + Meguro Techno Bldg. 2nd Floor + Shinagawa-ku Tokyo 141-0031 + JP + +00-19-5A (hex) Jenaer Antriebstechnik GmbH +00195A (base 16) Jenaer Antriebstechnik GmbH + Buchaer Strasse 1 + Jena Thueringen 07745 + DE + +00-19-6D (hex) Raybit Systems Korea, Inc +00196D (base 16) Raybit Systems Korea, Inc + Dream Tower 1221 + Seoul 158-718 + KR + +00-19-70 (hex) Z-Com, Inc. +001970 (base 16) Z-Com, Inc. + 7F-2, NO.9, PROSPERITY 1ST RD. + HSINCHU 300 + TW + +00-19-50 (hex) Harman Multimedia +001950 (base 16) Harman Multimedia + 8400 Balboa Blvd. + Northridge CA 91329 + US + +00-18-EE (hex) Videology Imaging Solutions, Inc. +0018EE (base 16) Videology Imaging Solutions, Inc. + 37 M Lark Industrial Parkway + Greenville RI 02828-3001 + US + +00-18-EB (hex) Blue Zen Enterprises Private Limited +0018EB (base 16) Blue Zen Enterprises Private Limited + No 2&3 (First Floor) Kurban Ali Street + Chennai Tamil Nadu 600002 + IN + +00-19-24 (hex) LBNL Engineering +001924 (base 16) LBNL Engineering + 1 Cyclotron Rd. + Berkeley CA 94720 + US + +00-19-1A (hex) IRLINK +00191A (base 16) IRLINK + HanYoung B/D 6F, 4-6 + SEOUL 138-824 + KR + +00-19-16 (hex) PayTec AG +001916 (base 16) PayTec AG + Rosengartenstrasse 3 + Zollikerberg ZH 8125 + CH + +00-19-0E (hex) Atech Technology Co., Ltd. +00190E (base 16) Atech Technology Co., Ltd. + 4 Fl., No. 103, Sec 2, Jiuzong Rd. + Taipei 114 + TW + +00-19-39 (hex) Gigamips +001939 (base 16) Gigamips + 5th Floor, Yangjae Building, 261, Yangjae-Dong + Seocho-Gu Seoul 137-130 + KR + +00-19-3A (hex) OESOLUTIONS +00193A (base 16) OESOLUTIONS + Technopark, 958-3 Daechon-Dong, Buk-Gu + Gwangju Buk-Gu 500-706 + KR + +00-18-E2 (hex) Topdata Sistemas de Automacao Ltda +0018E2 (base 16) Topdata Sistemas de Automacao Ltda + Rua Dr Carvalho Chaves, 662 + Curitiba PR 80.220-010 + BR + +00-19-22 (hex) CM Comandos Lineares +001922 (base 16) CM Comandos Lineares + Av Eng Alberto de Zagottis, 760 + São Paulo SP 04675-085 + BR + +00-19-1D (hex) Nintendo Co., Ltd. +00191D (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-19-2F (hex) Cisco Systems, Inc +00192F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-05 (hex) SCHRACK Seconet AG +001905 (base 16) SCHRACK Seconet AG + Eibesbrunnergasse 18 + Wien Österreich 1122 + AT + +00-19-07 (hex) Cisco Systems, Inc +001907 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-18-FB (hex) Compro Technology +0018FB (base 16) Compro Technology + 3/F No 12, Alley 6, Lane 45, Pao Shin Rd + Hsintien 231 + TW + +00-18-C3 (hex) CS Corporation +0018C3 (base 16) CS Corporation + CS-building, Pangyo seven venture valley 625 + Seongnam-si Gyeonggi-do 463-400 + KR + +00-18-CA (hex) Viprinet GmbH +0018CA (base 16) Viprinet GmbH + Basilikastraße 3 + Bingen am Rhein 55411 + DE + +00-18-C7 (hex) Real Time Automation +0018C7 (base 16) Real Time Automation + 2825 N Mayfair Rd Ste 11 + Wauwatosa WI 53222 + US + +00-18-BB (hex) Eliwell Controls srl +0018BB (base 16) Eliwell Controls srl + Via dell'Industria, 15 + Pieve d'Alpago Belluno 32010 + IT + +00-18-BF (hex) Essence Technology Solution, Inc. +0018BF (base 16) Essence Technology Solution, Inc. + B1, No. 207, Beisin Rd., Sec. 3 + Sindian, Taipei County 231 + TW + +00-18-8C (hex) Mobile Action Technology Inc. +00188C (base 16) Mobile Action Technology Inc. + 5F, No. 205-3, Sec. 3, Beishin Rd. + Shindian City, Taipei 231 + TW + +00-18-8F (hex) Montgomery Technology, Inc. +00188F (base 16) Montgomery Technology, Inc. + 800 East Commerce Street + Greenville AL 36037 + US + +00-18-84 (hex) Fon Technology S.L. +001884 (base 16) Fon Technology S.L. + Avda. Bruselas, n. 7, Planta 3, Alcobendas + Madrid 28100 + ES + +00-18-80 (hex) Maxim Integrated Products +001880 (base 16) Maxim Integrated Products + 160 Rio Robles + San Jose CA 95134 + US + +00-18-D0 (hex) AtRoad, A Trimble Company +0018D0 (base 16) AtRoad, A Trimble Company + 47071 Bayside Parkway + Fremont California 94538 + US + +00-18-D2 (hex) High-Gain Antennas LLC +0018D2 (base 16) High-Gain Antennas LLC + 11679 S. Cormorant Circle + Parker CO 80134 + US + +00-18-D3 (hex) TEAMCAST +0018D3 (base 16) TEAMCAST + Centre Espace Performance + Saint Gregoire 35769 + FR + +00-18-C6 (hex) OPW Fuel Management Systems +0018C6 (base 16) OPW Fuel Management Systems + 6900 Santa Fe Drive + Hodgkins Illinois 60525 + US + +00-18-7C (hex) INTERCROSS, LLC +00187C (base 16) INTERCROSS, LLC + Novoselov str., 58/7 + Ryazan 390049 + RU + +00-18-70 (hex) E28 Shanghai Limited +001870 (base 16) E28 Shanghai Limited + 2/F Eastern Tower + Shanghai 200001 + CN + +00-18-72 (hex) Expertise Engineering +001872 (base 16) Expertise Engineering + 4186 Sorrento Valley Blvd Suite -J + San Diego CA 92121 + US + +00-18-DC (hex) Prostar Co., Ltd. +0018DC (base 16) Prostar Co., Ltd. + A-703 Technotown, 250-3 Hagye-dong, Nowon-gu + Seoul 139-230 + KR + +00-18-D1 (hex) Siemens Home & Office Comm. Devices +0018D1 (base 16) Siemens Home & Office Comm. Devices + 4849 Alpha Rd. + Dallas Texas 75244 + US + +00-18-AA (hex) Protec Fire Detection plc +0018AA (base 16) Protec Fire Detection plc + Protec House + Nelson Lancashire BB9 6LQ + GB + +00-18-96 (hex) Great Well Electronic LTD +001896 (base 16) Great Well Electronic LTD + The Third Industrial Area + Shenzhen Guangdong 518110 + US + +00-18-90 (hex) RadioCOM, s.r.o. +001890 (base 16) RadioCOM, s.r.o. + Misikova 22 + Bratislava 811 06 + SK + +00-18-B9 (hex) Cisco Systems, Inc +0018B9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-18-B8 (hex) New Voice International AG +0018B8 (base 16) New Voice International AG + St. Gallerstrasse 8 + Lachen SZ 8853 + CH + +00-18-A1 (hex) Tiqit Computers, Inc. +0018A1 (base 16) Tiqit Computers, Inc. + 2215 Old Page Mill Rd + Palo Alto CA 94304 + US + +00-18-12 (hex) Beijing Xinwei Telecom Technology Co., Ltd. +001812 (base 16) Beijing Xinwei Telecom Technology Co., Ltd. + Xinwei Bldg., No. 7 Zhongguancun Software Park, + Haidian District Beijing 100094 + CN + +00-18-0B (hex) Brilliant Telecommunications +00180B (base 16) Brilliant Telecommunications + 307 Orchard City Dr. + Campbell CA 95008 + US + +00-18-61 (hex) Ooma, Inc. +001861 (base 16) Ooma, Inc. + 555 University Avenue + Palo Alto CA 94301 + US + +00-18-5B (hex) Network Chemistry, Inc +00185B (base 16) Network Chemistry, Inc + 1700 Seaport Blvd + Redwood City CA 94063 + US + +00-18-55 (hex) Aeromaritime Systembau GmbH +001855 (base 16) Aeromaritime Systembau GmbH + Ludwig-Erhard-Str. 16 + D-85375 Neufahrn + DE + +00-18-51 (hex) SWsoft +001851 (base 16) SWsoft + 13755 Sunrise Valley Drive, Suite 600 + Herndon VA 20171 + US + +00-18-74 (hex) Cisco Systems, Inc +001874 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-18-69 (hex) KINGJIM +001869 (base 16) KINGJIM + No.10-18,2-Chome + Chiyoda-ku Tokyo 101-0031 + JP + +00-18-56 (hex) EyeFi, Inc +001856 (base 16) EyeFi, Inc + 149 Commonwealth Drive + Menlo Park CA 94025 + US + +00-18-4E (hex) Lianhe Technologies, Inc. +00184E (base 16) Lianhe Technologies, Inc. + 3F, #119, DaHu ShanZhuang St. + Neihu District Taipei City 114 + TW + +00-18-4C (hex) Bogen Communications +00184C (base 16) Bogen Communications + 50 Spring St. + Ramsey NJ 07446 + US + +00-18-26 (hex) Cale Access AB +001826 (base 16) Cale Access AB + Box 1031 + Kista SE-164 21 + SE + +00-18-2D (hex) Artec Design +00182D (base 16) Artec Design + Teaduspargi 6/1 + Tallinn 12618 + EE + +00-18-2A (hex) Taiwan Video & Monitor +00182A (base 16) Taiwan Video & Monitor + 3F, 141 Jen Ai Rd Sec. 3 + Taipei City 106 + TW + +00-18-3B (hex) CENITS Co., Ltd. +00183B (base 16) CENITS Co., Ltd. + 3F, Yangjae Bldg., 264-3 + Seoul 137-130 + KR + +00-18-3C (hex) Encore Software Limited +00183C (base 16) Encore Software Limited + 6F Leo Complex + Bangalore Karnataka 560025 + IN + +00-18-41 (hex) High Tech Computer Corp +001841 (base 16) High Tech Computer Corp + 23 Hsin Hua Rd. + Taoyuan 330 + TW + +00-18-19 (hex) Cisco Systems, Inc +001819 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-18-0C (hex) Optelian Access Networks +00180C (base 16) Optelian Access Networks + 22A-1051 Baxter Road + Ottawa Ontario K2C 3P2 + CA + +00-18-10 (hex) IPTrade S.A. +001810 (base 16) IPTrade S.A. + Parc Scientifique + Sart-Tilman Wallonie 4031 + BE + +00-18-09 (hex) CRESYN +001809 (base 16) CRESYN + 8-22,Jamwon-dong + Seoul Seocho-Gu #137-902 + KR + +00-18-04 (hex) E-TEK DIGITAL TECHNOLOGY LIMITED +001804 (base 16) E-TEK DIGITAL TECHNOLOGY LIMITED + UNIT1520,15/F.,TOWER 2,GRAND CENTURY PLACE,193 PRINCE EDWARD ROAD WEST,KOWLOON, + + HK + +00-18-00 (hex) UNIGRAND LTD +001800 (base 16) UNIGRAND LTD + 7F-2, No.45, Jingde St., Jhonghe City, + 235 + TW + +00-17-FD (hex) Amulet Hotkey +0017FD (base 16) Amulet Hotkey + Cavalier Road + Heathfield Devon TQ12 6TQ + GB + +00-17-FC (hex) Suprema Inc. +0017FC (base 16) Suprema Inc. + 16F Parkview Office Tower, + Seongnam Gyeonggi 463-863 + KR + +00-17-FB (hex) FA +0017FB (base 16) FA + 628-7, Dungchon-Dong + Seoul Kangseo-Ku 157-838 + KR + +00-17-D8 (hex) Magnum Semiconductor, Inc. +0017D8 (base 16) Magnum Semiconductor, Inc. + 591 Yosemite Drive + Milpitas CA 95035 + US + +00-17-DA (hex) Spans Logic +0017DA (base 16) Spans Logic + 201 San Antonio Circle + Mountain View CA 94040 + US + +00-17-CF (hex) iMCA-GmbH +0017CF (base 16) iMCA-GmbH + Dorfstrasse 28b + Itzehoe Schleswig-Holstein 25524 + DE + +00-17-B9 (hex) Gambro Lundia AB +0017B9 (base 16) Gambro Lundia AB + BOX 10101 + LUND SkÃ¥ne 22010 + SE + +00-17-B3 (hex) Aftek Infosys Limited +0017B3 (base 16) Aftek Infosys Limited + Pawan Complex + Pune Maharashtra 411 038 + IN + +00-17-A2 (hex) Camrivox Ltd. +0017A2 (base 16) Camrivox Ltd. + The Jeffreys Building + Cambridge Cambridgeshire CB4 0WS + GB + +00-17-5F (hex) XENOLINK Communications Co., Ltd. +00175F (base 16) XENOLINK Communications Co., Ltd. + 2nd Fl., Jungyou B/D 797-22 + Seoul 135-930 + KR + +00-17-5C (hex) SHARP CORPORATION +00175C (base 16) SHARP CORPORATION + 1, Takumi-Cho, + Sakai city Osaka Prefecture 590-8522 + JP + +00-17-9D (hex) Kelman Limited +00179D (base 16) Kelman Limited + Rathdown Close + Lisburn Co. Antrim BT28 2RB + GB + +00-17-90 (hex) HYUNDAI DIGITECH Co, Ltd. +001790 (base 16) HYUNDAI DIGITECH Co, Ltd. + 13th Fl, Choung-Jin Bldg, 53-5 + Seoul 140-719 + KR + +00-17-91 (hex) LinTech GmbH +001791 (base 16) LinTech GmbH + Friedrich-Engels-Str. 35 + Berlin 13156 + DE + +00-17-95 (hex) Cisco Systems, Inc +001795 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-17-59 (hex) Cisco Systems, Inc +001759 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-17-54 (hex) Arkino HiTOP Corporation Limited +001754 (base 16) Arkino HiTOP Corporation Limited + 5F., No.437, Tao Ying Rd + Taoyuan City Taoyuan County 33068, + TW + +00-17-52 (hex) DAGS, Inc +001752 (base 16) DAGS, Inc + C-510, Woolim Lion's Valley, 371-28, Gasan Dong, Geumcheon Ku + Seoul 153-786 + KR + +00-17-56 (hex) Vinci Labs Oy +001756 (base 16) Vinci Labs Oy + Finlaysoninkuja 21 A + Tampere Länsi-Suomi 33210 + FI + +00-17-77 (hex) Obsidian Research Corporation +001777 (base 16) Obsidian Research Corporation + 120 - 4445 Calgary Trail NW + Edmonton Alberta T6H 5R7 + CA + +00-17-6A (hex) Avago Technologies +00176A (base 16) Avago Technologies + 350 West Trimble Rd + San Jose CA 95131 + US + +00-17-86 (hex) wisembed +001786 (base 16) wisembed + 808, hansin IT tower, 235 guro3-dong, guro-gu + Seoul 152-768 + KR + +00-17-82 (hex) LoBenn Inc. +001782 (base 16) LoBenn Inc. + 150 Katimavik Road + Ottawa Ontario K2L 2N2 + CA + +00-17-78 (hex) Central Music Co. +001778 (base 16) Central Music Co. + 0711-0712 Tower D, SOHO New Town + Beijing 100022 + CN + +00-17-6B (hex) Kiyon, Inc. +00176B (base 16) Kiyon, Inc. + 9381 Judicial Drive + San Diego CA 92121 + US + +00-17-99 (hex) SmarTire Systems Inc. +001799 (base 16) SmarTire Systems Inc. + Suite 150 + Richmond BC V6V 2J1 + CA + +00-17-7F (hex) Worldsmart Retech +00177F (base 16) Worldsmart Retech + 23 Hi-Tech Court + Eight Mile Plains QLD 4113 + AU + +00-17-6E (hex) DUCATI SISTEMI +00176E (base 16) DUCATI SISTEMI + VIA MARCO EMILIO LEPIDO, 182 + BOLOGNA 40132 + IT + +00-17-74 (hex) Elesta GmbH +001774 (base 16) Elesta GmbH + Gottlieb Daimler Strasse 1 + Konstanz 78467 + DE + +00-17-0C (hex) Twig Com Ltd. +00170C (base 16) Twig Com Ltd. + Meriniitynkatu 11 + Salo 2400 + FI + +00-17-0D (hex) Dust Networks Inc. +00170D (base 16) Dust Networks Inc. + 30695 Huntwood Ave. + Hayward Ca. 94544 + US + +00-17-0B (hex) Contela, Inc. +00170B (base 16) Contela, Inc. + 6-8 Soonae-dong, Bundang-gu, + Sungnam Kyunggi-do 463-825 + KR + +00-17-0F (hex) Cisco Systems, Inc +00170F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-17-04 (hex) Shinco Electronics Group Co.,Ltd +001704 (base 16) Shinco Electronics Group Co.,Ltd + No.5 Waihuan Road + Changzhou Jiangsu 213022 + CN + +00-17-07 (hex) InGrid, Inc +001707 (base 16) InGrid, Inc + 920 Cassatt Rd + Berwyn Pa 19312 + US + +00-17-12 (hex) ISCO International +001712 (base 16) ISCO International + 1001 Cambridge Drive + Elk Grove Village IL 60007 + US + +00-16-D8 (hex) Senea AB +0016D8 (base 16) Senea AB + Företagsallen 12 + Åkersberga 18484 + SE + +00-16-D6 (hex) TDA Tech Pty Ltd +0016D6 (base 16) TDA Tech Pty Ltd + 210 / 54 Currie Street + Adelaide South Australia 5000 + AU + +00-16-D5 (hex) Synccom Co., Ltd +0016D5 (base 16) Synccom Co., Ltd + #306 Myungi e-space 218-20 + Anyang-si Kyungki-do 430-817 + KR + +00-16-C9 (hex) NAT Seattle, Inc. +0016C9 (base 16) NAT Seattle, Inc. + 22125 17th Ave SE + Bothell WA 98021 + US + +00-16-C6 (hex) North Atlantic Industries +0016C6 (base 16) North Atlantic Industries + 170 Wilbur Place + Bohemia NY 11716 + US + +00-17-24 (hex) Studer Professional Audio GmbH +001724 (base 16) Studer Professional Audio GmbH + Althardstrasse 30 + Regensdorf Zürich CH-8105 + CH + +00-17-02 (hex) Osung Midicom Co., Ltd +001702 (base 16) Osung Midicom Co., Ltd + 231-18, Dorim2-dong, + Seoul, Youngdeungpo-gu 150-832 + KR + +00-16-F7 (hex) L-3 Communications, Aviation Recorders +0016F7 (base 16) L-3 Communications, Aviation Recorders + 100 Cattlemen Rd. + Sarasota FL 34232 + US + +00-17-2D (hex) Axcen Photonics Corporation +00172D (base 16) Axcen Photonics Corporation + 6F, No. 119, Baujung Rd., + Shindian City, Taipei 231 + TW + +00-17-41 (hex) DEFIDEV +001741 (base 16) DEFIDEV + 20 rue Raymond Marcheron + Vanves 92170 + FR + +00-17-38 (hex) International Business Machines +001738 (base 16) International Business Machines + 1 Azrieli Center + Tel Aviv 67021 + IL + +00-17-1E (hex) Theo Benning GmbH & Co. KG +00171E (base 16) Theo Benning GmbH & Co. KG + Muensterstraße 135-137 + Bocholt NRW 46397 + DE + +00-16-D2 (hex) Caspian +0016D2 (base 16) Caspian + 170 Baytech Drive + San Jose CA 95134 + US + +00-16-A4 (hex) Ezurio Ltd +0016A4 (base 16) Ezurio Ltd + Unit 2 + London NW9 5HD + GB + +00-16-99 (hex) Tonic DVB Marketing Ltd +001699 (base 16) Tonic DVB Marketing Ltd + Unit B, 10/F, Summit Building, + Hung Hom Kowloon + HK + +00-16-9B (hex) Alstom Transport +00169B (base 16) Alstom Transport + 11, 13 avenue de Bel Air + Villeurbanne Rhone 69100 + FR + +00-16-90 (hex) J-TEK INCORPORATION +001690 (base 16) J-TEK INCORPORATION + 2F-1, No. 83, Sec. 2, GongDaoWu Rd., + Hsinchu City 30070 + TW + +00-16-93 (hex) PowerLink Technology Inc. +001693 (base 16) PowerLink Technology Inc. + N0. 18, Alley 1, Lane 151, Sec. 1, Jhongsing Rd., Wugu Township + Taipei Hsien 248 + TW + +00-16-98 (hex) T&A Mobile Phones +001698 (base 16) T&A Mobile Phones + 4/F, South Building,No.2966, Jinke Road + Pudong Shanghai 201203 + CN + +00-16-62 (hex) Liyuh Technology Ltd. +001662 (base 16) Liyuh Technology Ltd. + 4F, No.19, Ln.221, Ganqian Rd., Neihu District + Taipei 114 + TW + +00-16-61 (hex) Novatium Solutions (P) Ltd +001661 (base 16) Novatium Solutions (P) Ltd + 3rd Floor, Temple Towers, #672 + Chennai Tamil Nadu 600035 + IN + +00-16-64 (hex) Prod-El SpA +001664 (base 16) Prod-El SpA + Via Palmanova 185 + Milano MI 20132 + IT + +00-16-5E (hex) Precision I/O +00165E (base 16) Precision I/O + 4005 Miranda Ave., Suite 210 + Palo Alto CA 94304-1232 + US + +00-16-58 (hex) Fusiontech Technologies Inc. +001658 (base 16) Fusiontech Technologies Inc. + 6F, No.78, Cheng Kung Rd., Sec. 1, + Taipei 115 + TW + +00-16-A5 (hex) Tandberg Storage ASA +0016A5 (base 16) Tandberg Storage ASA + Postboks 191 + + NO + +00-16-A1 (hex) 3Leaf Networks +0016A1 (base 16) 3Leaf Networks + 3255-1 Scott Blvd + Santa Clara CA 95054 + US + +00-16-66 (hex) Quantier Communication Inc. +001666 (base 16) Quantier Communication Inc. + 1F, No. 36, Industry E. Rd IV, + Hsin-Chu 300 + TW + +00-16-81 (hex) Vector Informatik GmbH +001681 (base 16) Vector Informatik GmbH + Ingersheimer Str. 24 + Stuttgart Baden-Württemberg 70499 + DE + +00-BA-C0 (hex) Biometric Access Company +00BAC0 (base 16) Biometric Access Company + 2555 North IH 35 + Round Rock Texas 78664 + US + +00-16-85 (hex) Elisa Oyj +001685 (base 16) Elisa Oyj + Elektroniikkatie 4 + 90570 Oulu + FI + +00-16-80 (hex) Bally Gaming + Systems +001680 (base 16) Bally Gaming + Systems + 950 Sandhill Road + Reno NV 89521 + US + +00-16-96 (hex) QDI Technology (H.K.) Limited +001696 (base 16) QDI Technology (H.K.) Limited + 16/F, Standard Chartered Bank Building 4-4A + Hong Kong + CN + +00-16-BE (hex) INFRANET, Inc. +0016BE (base 16) INFRANET, Inc. + 8th Floor, Cowell B/D, 66-1 + Seoul 137-040 + KR + +00-16-AB (hex) Dansensor A/S +0016AB (base 16) Dansensor A/S + Roennedevej 18 + Ringsted DK-4100 + DK + +00-16-53 (hex) LEGO System A/S IE Electronics Division +001653 (base 16) LEGO System A/S IE Electronics Division + Aastvej 1 + Billund Kommune 7190 + DK + +00-16-52 (hex) Hoatech Technologies, Inc. +001652 (base 16) Hoatech Technologies, Inc. + 1F., No.224, Guosheng St. + Zhubei HsinChu Hsien 30244 + TW + +00-16-50 (hex) Kratos EPD +001650 (base 16) Kratos EPD + Herley General Microwave Israel. + KIBBUTZ EYAL 45840 + IL + +00-15-FA (hex) Cisco Systems, Inc +0015FA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-15-FC (hex) Littelfuse Startco +0015FC (base 16) Littelfuse Startco + 3714 Kinnear Place + Saskatoon SK S7P 0A6 + CA + +00-15-F7 (hex) Wintecronics Ltd. +0015F7 (base 16) Wintecronics Ltd. + No. 716, 11F-3, Jung Jeng Rd. + Chung Ho City Taipei Hsien 235 + TW + +00-16-30 (hex) Vativ Technologies +001630 (base 16) Vativ Technologies + 9339 Genesee Avenue + San Diego CA 92121 + US + +00-16-2F (hex) Geutebrück GmbH +00162F (base 16) Geutebrück GmbH + Im Nassen 7-9 + Windhagen 53578 + DE + +00-16-2B (hex) Togami Electric Mfg.co.,Ltd. +00162B (base 16) Togami Electric Mfg.co.,Ltd. + 1-1 Ohtakara-Kitamachi + Saga.PRF 840-0802 + JP + +00-16-42 (hex) Pangolin +001642 (base 16) Pangolin + 9501 Satellite Boulevard, Suite 109 + Orlando FL 32837 + US + +00-16-3B (hex) VertexRSI/General Dynamics +00163B (base 16) VertexRSI/General Dynamics + 2120 Old Gatesburg Rd. + State college PA 16803 + US + +00-16-37 (hex) CITEL SpA +001637 (base 16) CITEL SpA + Via L. G. Columella, 36 + Milan MI 20128 + IT + +00-16-08 (hex) Sequans Communications +001608 (base 16) Sequans Communications + 19 Le Parvis de la Défense + PARIS LA DEFENSE CEDEX 92073 + FR + +00-16-24 (hex) Teneros, Inc. +001624 (base 16) Teneros, Inc. + 215 Castro St. + Mt. View CA 94041 + US + +00-15-F8 (hex) Kingtronics Industrial Co. Ltd. +0015F8 (base 16) Kingtronics Industrial Co. Ltd. + Penthouse, Century Centre, + Kowloon + HK + +00-16-1C (hex) e:cue +00161C (base 16) e:cue + Friedrich-List-Strasse 23 + Paderborn 33100 + DE + +00-15-B8 (hex) Tahoe +0015B8 (base 16) Tahoe + ul. Uniwersytecka 1 + Wroclaw 50951 + PL + +00-15-B6 (hex) ShinMaywa Industries, Ltd. +0015B6 (base 16) ShinMaywa Industries, Ltd. + 1-1 Shinmeiwa-cho + Takarazuka Hyogo 665-8550 + JP + +00-15-B0 (hex) AUTOTELENET CO.,LTD +0015B0 (base 16) AUTOTELENET CO.,LTD + 2F, 898-24, Hogye2-dong, Dongan-gu + Anyang-City Kyunggi-do 431-836 + KR + +00-15-B1 (hex) Ambient Corporation +0015B1 (base 16) Ambient Corporation + 79 Chapel St. + Newton MA 02458 + US + +00-15-9F (hex) Terascala, Inc. +00159F (base 16) Terascala, Inc. + 145 Bodwell Street + Avon MA 02322 + US + +00-15-9E (hex) Mad Catz Interactive Inc +00159E (base 16) Mad Catz Interactive Inc + Units 3+4 West Point Row + Bristol South Gloucestershire BS32 4QG + US + +00-15-A1 (hex) ECA-SINTERS +0015A1 (base 16) ECA-SINTERS + 5, rue Paul Mesplé + TOULOUSE Cedex 01 31106 + FR + +00-15-93 (hex) U4EA Technologies Inc. +001593 (base 16) U4EA Technologies Inc. + 48860 Milmont Drive + Fremont CA 94538 + US + +00-15-81 (hex) MAKUS Inc. +001581 (base 16) MAKUS Inc. + 4F Daedo Bldg. 748-14 Yeoksam-dong, Kangnam-gu + Seoul 135-080 + US + +00-15-7A (hex) Telefin S.p.A. +00157A (base 16) Telefin S.p.A. + Via Albere 87/A + Verona VR 37138 + IT + +00-15-C3 (hex) Ruf Telematik AG +0015C3 (base 16) Ruf Telematik AG + Ruetistrasse 13 + Schlieren ZH 8952 + CH + +00-15-E6 (hex) MOBILE TECHNIKA Inc. +0015E6 (base 16) MOBILE TECHNIKA Inc. + Sotobori Sky Bld. 5th Floor + Shinjuku-ku Tokyo 162-0845 + JP + +00-15-DB (hex) Canesta Inc. +0015DB (base 16) Canesta Inc. + 965 West Maude Avenue + Sunnyvale California 94085 + US + +00-15-8D (hex) Jennic Ltd +00158D (base 16) Jennic Ltd + Furnival Street + Sheffield Yorkshire S1 4QT + US + +00-15-84 (hex) Schenck Process GmbH +001584 (base 16) Schenck Process GmbH + Pallaswiesenstraße 100 + Darmstadt Hessen 64293 + DE + +00-15-CC (hex) UQUEST, LTD. +0015CC (base 16) UQUEST, LTD. + Sannomiya Intes Bldg. 8F + KOBE HYOGO 651-0086 + JP + +00-15-C6 (hex) Cisco Systems, Inc +0015C6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-15-D7 (hex) Reti Corporation +0015D7 (base 16) Reti Corporation + 6F,No 13, Lane 120, Sec 1, Neihu Rd., + Taipei City 114 + TW + +00-15-CB (hex) Surf Communication Solutions Ltd. +0015CB (base 16) Surf Communication Solutions Ltd. + P.O. Box 343 + Yokneam 20164 + IL + +00-15-A7 (hex) Robatech AG +0015A7 (base 16) Robatech AG + Pilatusring 10 + Muri AG 5630 + CH + +00-15-23 (hex) Meteor Communications Corporation +001523 (base 16) Meteor Communications Corporation + 22614 66th Avenue South + Kent WA 98032 + US + +00-15-24 (hex) Numatics, Inc. +001524 (base 16) Numatics, Inc. + 46280 Dylan Dr. + Novi Michigan 48377 + US + +00-15-1B (hex) Isilon Systems Inc. +00151B (base 16) Isilon Systems Inc. + 3101 Western Avenue + Seattle WA 98121 + US + +00-15-73 (hex) NewSoft Technology Corporation +001573 (base 16) NewSoft Technology Corporation + 3F, 19-3, SanChong RD, NanKang, + Taipei 115 + US + +00-15-75 (hex) Nevis Networks Inc. +001575 (base 16) Nevis Networks Inc. + 3945 Freedom Circle + Santa Clara CA 95054 + US + +00-15-6C (hex) SANE SYSTEM CO., LTD +00156C (base 16) SANE SYSTEM CO., LTD + 0-2 Heungan-daero 439 beon-gil Dongan-gu + Anyang-si Kyunggi-do 431-804 + KR + +00-15-6A (hex) DG2L Technologies Pvt. Ltd. +00156A (base 16) DG2L Technologies Pvt. Ltd. + AML Center 1, Gnd. Floor, 8 Mahal Indl. Est. + Mumbai Maharashtra 400093 + IN + +00-15-29 (hex) N3 Corporation +001529 (base 16) N3 Corporation + #402 GwangMyeong Techno Town + GyeongGi-Do 423-031 + KR + +00-15-2D (hex) TenX Networks, LLC +00152D (base 16) TenX Networks, LLC + 4855 Wiley Post Way + Salt Lake City UT 84116 + US + +00-15-6F (hex) Xiranet Communications GmbH +00156F (base 16) Xiranet Communications GmbH + Bertolt-Brecht-Allee 24 + Dresden Saxony 01309 + US + +00-15-72 (hex) Red-Lemon +001572 (base 16) Red-Lemon + Unit 4, 9/F, Paramount Building + Chai Wan + HK + +00-15-67 (hex) RADWIN Inc. +001567 (base 16) RADWIN Inc. + 900 Corporate Drive + Mahwah NJ 07430 + US + +00-15-5B (hex) Sampo Corporation +00155B (base 16) Sampo Corporation + 216 Chung Shan Road, + Taipei Hsien 220 + TW + +00-15-53 (hex) Cytyc Corporation +001553 (base 16) Cytyc Corporation + 250 Campus Dive + Marlborough MA 01752 + US + +00-15-51 (hex) RadioPulse Inc. +001551 (base 16) RadioPulse Inc. + 2nd fl. Hans B/D, 111-55 + Seoul 134-883 + KR + +00-15-52 (hex) Wi-Gear Inc. +001552 (base 16) Wi-Gear Inc. + 340 Church Street + San Francisco CA 94114 + US + +00-15-3E (hex) Q-Matic Sweden AB +00153E (base 16) Q-Matic Sweden AB + Neongatan 8 + Molndal 431 53 + SE + +00-15-42 (hex) MICROHARD S.R.L. +001542 (base 16) MICROHARD S.R.L. + Via Primo Maggio 36 + San Vittore Olona Milano 20028 + IT + +00-15-4E (hex) IEC +00154E (base 16) IEC + 3, rue de Varembé + CH - 1211 GENEVA 20 + DE + +00-15-50 (hex) Nits Technology Inc +001550 (base 16) Nits Technology Inc + 2FL. No. 8 Alley 16, Lane 235, Bauchiau Rd., + Shindian City Taipei Hsien 231 + TW + +00-15-46 (hex) ITG Worldwide Sdn Bhd +001546 (base 16) ITG Worldwide Sdn Bhd + 2, Jalan AstakaU8/83 + Shah Alam Selangor Darul Ehsan 40150 + MY + +00-15-5D (hex) Microsoft Corporation +00155D (base 16) Microsoft Corporation + One Microsoft Way + Redmond WA 98052-8300 + US + +00-15-62 (hex) Cisco Systems, Inc +001562 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-14-E1 (hex) Data Display AG +0014E1 (base 16) Data Display AG + Industriestraße 1 + Germering Bayern 82110 + DE + +00-14-E3 (hex) mm-lab GmbH +0014E3 (base 16) mm-lab GmbH + Stammheimer Strasse 10 + Kornwestheim + DE + +00-14-D9 (hex) IP Fabrics, Inc. +0014D9 (base 16) IP Fabrics, Inc. + 3720 SW 141st Avenue + Beaverton Oregon 97006 + US + +00-14-D6 (hex) Jeongmin Electronics Co.,Ltd. +0014D6 (base 16) Jeongmin Electronics Co.,Ltd. + #710, Byuksan Digital Valley 2, + Seoul 153 783 + KR + +00-14-F9 (hex) Vantage Controls +0014F9 (base 16) Vantage Controls + 1061 South 800 East + Orem UT 84097 + US + +00-14-E7 (hex) Stolinx,. Inc +0014E7 (base 16) Stolinx,. Inc + 3F Ohchang Bldg., 61 Yangjae-dong + Seoul 137-889 + KR + +00-14-E9 (hex) Nortech International +0014E9 (base 16) Nortech International + 32A Wiganthorpe Road + Pietermartizburg KwaZulu Natal 3201 + ZA + +00-14-ED (hex) Airak, Inc. +0014ED (base 16) Airak, Inc. + 21641 Beaumeade Circle + Ashburn Virginia 20147 + US + +00-14-CE (hex) NF CORPORATION +0014CE (base 16) NF CORPORATION + 6-3-20, Tsunashima-higashi + Yokohama Kanagawa 223-8508 + JP + +00-14-D0 (hex) BTI Systems Inc. +0014D0 (base 16) BTI Systems Inc. + 50 Northside Road + Ottawa Ontario K2H 5Z6 + CA + +00-15-03 (hex) PROFIcomms s.r.o. +001503 (base 16) PROFIcomms s.r.o. + Turgenevova 5 + Brno EU/Europe 618 00 + CZ + +00-15-09 (hex) Plus Technology Co., Ltd +001509 (base 16) Plus Technology Co., Ltd + Office #205, Gayang Techno-town, + Seoul 157-810 + KR + +00-14-F0 (hex) Business Security OL AB +0014F0 (base 16) Business Security OL AB + Box 110 65 + Lund 220 11 + SE + +00-14-F2 (hex) Cisco Systems, Inc +0014F2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-15-10 (hex) Techsphere Co., Ltd +001510 (base 16) Techsphere Co., Ltd + 4F, Wonil Bldg., 980-54, Bangbae-dong, SeoCho-gu + Seoul 137-060 + KR + +00-15-13 (hex) EFS sas +001513 (base 16) EFS sas + BP 34 + MILLERY F-69390 + US + +00-14-8B (hex) Globo Electronic GmbH & Co. KG +00148B (base 16) Globo Electronic GmbH & Co. KG + Industriestrasse 4a + Niederlauer Bayern 97618 + DE + +00-14-90 (hex) ASP Corporation +001490 (base 16) ASP Corporation + 465 Industrial Park Road + Hartwell GA 30643 + US + +00-14-84 (hex) Cermate Technologies Inc. +001484 (base 16) Cermate Technologies Inc. + 7F-1, No 168 Lien-Chen Rd. + Chung-Ho Dist New Taipei City + TW + +00-14-79 (hex) NEC Magnus Communications,Ltd. +001479 (base 16) NEC Magnus Communications,Ltd. + 22-23, Kaigan 3-chome + Minato-ku Tokyo 108-0022 + JP + +00-14-7B (hex) Iteris, Inc. +00147B (base 16) Iteris, Inc. + 1515 S. Manchester Ave. + Anaheim CA 92802 + US + +00-14-BB (hex) Open Interface North America +0014BB (base 16) Open Interface North America + 506 2nd Avenue, Suite 420 + Seattle WA 98104 + US + +00-14-70 (hex) Prokom Software SA +001470 (base 16) Prokom Software SA + Al. Jerozolimskie 65/79 + Warszawa Mazowieckie 00-697 + PL + +00-14-67 (hex) ArrowSpan Inc. +001467 (base 16) ArrowSpan Inc. + 4699 Old Ironsides Dr. Suite 100 + Santa Clara CA 95054 + US + +00-14-5F (hex) ADITEC CO. LTD +00145F (base 16) ADITEC CO. LTD + 4F Hyowon B/D, 99-5, + Seoul 138-805 + KR + +00-14-88 (hex) Akorri +001488 (base 16) Akorri + 11 Falcon Ridge Dr + Hopkinton MA 01748 + US + +00-14-7A (hex) Eubus GmbH +00147A (base 16) Eubus GmbH + Gollierstraße 70 Aufgang E 4.Stock + Munich Bavaria 80339 + DE + +00-14-6D (hex) RF Technologies +00146D (base 16) RF Technologies + 3125 N 126th Street + Brookfield WI 53005 + US + +00-14-AC (hex) Bountiful WiFi +0014AC (base 16) Bountiful WiFi + 707 West 700 South + Woods Cross Utah 84087 + US + +00-14-A8 (hex) Cisco Systems, Inc +0014A8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-14-A0 (hex) Accsense, Inc. +0014A0 (base 16) Accsense, Inc. + 460 Ward Drive + Santa Barbara California 93111 + US + +00-14-59 (hex) Moram Co., Ltd. +001459 (base 16) Moram Co., Ltd. + 3F, Manwol Bldg., 1022-4 + Suwon-shi Gyounggi-do 443-813 + KR + +00-14-57 (hex) T-VIPS AS +001457 (base 16) T-VIPS AS + Ostensjoveien 18 + Oslo NO-0661 + NO + +00-14-53 (hex) ADVANTECH TECHNOLOGIES CO.,LTD +001453 (base 16) ADVANTECH TECHNOLOGIES CO.,LTD + #1202 ACE TECHNO TOWER, 684-1 + Seoul 157-721 + KR + +00-14-54 (hex) Symwave +001454 (base 16) Symwave + 10251 Vista Sorrento Parkway + San Diego CA 92121 + US + +00-13-F8 (hex) Dex Security Solutions +0013F8 (base 16) Dex Security Solutions + 10 Junction Road Parktown + Johannesburg Guteng 2000 + ZA + +00-13-F9 (hex) Cavera Systems +0013F9 (base 16) Cavera Systems + 2355 Oakland Rd, Suite#33 + San Jose CA 95131 + US + +00-13-F2 (hex) Klas Ltd +0013F2 (base 16) Klas Ltd + Bracetown Business Park + Clonee Co Meath + IE + +00-13-F7 (hex) SMC Networks, Inc. +0013F7 (base 16) SMC Networks, Inc. + 38 Tesla + Irvine CA 92618 + US + +00-14-4B (hex) Hifn, Inc. +00144B (base 16) Hifn, Inc. + 750 University Ave + Los Gatos CA 95032 + US + +00-14-41 (hex) Innovation Sound Technology Co., LTD. +001441 (base 16) Innovation Sound Technology Co., LTD. + Building 2th.,Cuihai Industrial Area, + Shenzhen Guangdong 518103 + CN + +00-14-3C (hex) Rheinmetall Canada Inc. +00143C (base 16) Rheinmetall Canada Inc. + 225 boul du seminaire sud + St-Jean-sur-Richelieu Quebec J3B 8E9 + CA + +00-14-1A (hex) DEICY CORPORATION +00141A (base 16) DEICY CORPORATION + 3-3-6,Sakae-cho,Hamura-shi, + Tokyo 205-0002 + JP + +00-14-1C (hex) Cisco Systems, Inc +00141C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-14-0C (hex) GKB CCTV CO., LTD. +00140C (base 16) GKB CCTV CO., LTD. + 7F, No. 1, Lane 641, + Ta Ya Hsiang, TAICHUNG 428 + TW + +00-13-FE (hex) GRANDTEC ELECTRONIC CORP. +0013FE (base 16) GRANDTEC ELECTRONIC CORP. + 8F,NO.268,Lian Cheng Rd.,Chung Ho City, + Taipei 235 + TW + +00-14-35 (hex) CityCom Corp. +001435 (base 16) CityCom Corp. + 3F., No.532, Sec. 2, + Jhonghe City Taipei Hsien 23557 + TW + +00-14-48 (hex) Inventec Multimedia & Telecom Corporation +001448 (base 16) Inventec Multimedia & Telecom Corporation + 5F,NO.396,Sec.1 Nei-Hu Road + Taipei 114 + TW + +00-14-16 (hex) Scosche Industries, Inc. +001416 (base 16) Scosche Industries, Inc. + PO Box 2901 + Oxnard CA 93034 + US + +00-14-26 (hex) NL Technology +001426 (base 16) NL Technology + 800 Turnpike Street + North Andover MA 01845 + US + +00-13-C5 (hex) LIGHTRON FIBER-OPTIC DEVICES INC. +0013C5 (base 16) LIGHTRON FIBER-OPTIC DEVICES INC. + 51-1 Moonpyung-Dong, Taeduck-Gu + Taejon 306-220 + KR + +00-13-C4 (hex) Cisco Systems, Inc +0013C4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-13-C2 (hex) WACOM Co.,Ltd +0013C2 (base 16) WACOM Co.,Ltd + 2-510-1 Toyonodai Otone-machi + Kitasaitama-gun Saitama 349-1148 + JP + +00-13-BF (hex) Media System Planning Corp. +0013BF (base 16) Media System Planning Corp. + 4F Velco-Kuromon Bldg. + Taito-ku, Tokyo 110-0005 + JP + +00-13-BB (hex) Smartvue Corporation +0013BB (base 16) Smartvue Corporation + 102 Woodmont Boulevard + Nashville TN 37205 + US + +00-13-B5 (hex) Wavesat +0013B5 (base 16) Wavesat + 1375, Trans-Canada Highway + Dorval Quebec H9P 2W8 + CA + +00-13-AF (hex) NUMA Technology,Inc. +0013AF (base 16) NUMA Technology,Inc. + 4F,No778,Sec 4,Patch Rd. + Taipei 115 + TW + +00-13-B0 (hex) Jablotron +0013B0 (base 16) Jablotron + Pod Skalkou 33 + Jablonec nad Nisou 46601 + CZ + +00-13-9A (hex) K-ubique ID Corp. +00139A (base 16) K-ubique ID Corp. + Yamasan Bldg.8F, + Chuo-ku Tokyo 103-0023 + JP + +00-13-9E (hex) Ciara Technologies Inc. +00139E (base 16) Ciara Technologies Inc. + 9300 Trans Canada Highway + Saint-Laurent Quebec H4S 1K5 + CA + +00-13-9D (hex) MaxLinear Hispania S.L.U. +00139D (base 16) MaxLinear Hispania S.L.U. + Ronda Narcis Monturiol + Estarriol, 11D Paterna 46980 + ES + +00-13-D5 (hex) RuggedCom +0013D5 (base 16) RuggedCom + 300 Applewood Crescent (Unit 1) + Concord, Ontario L4K 5C7 + CA + +00-13-D6 (hex) TII NETWORK TECHNOLOGIES, INC. +0013D6 (base 16) TII NETWORK TECHNOLOGIES, INC. + 1385 AKRON STREET + COPIAGUE NY 11726 + US + +00-13-DB (hex) SHOEI Electric Co.,Ltd +0013DB (base 16) SHOEI Electric Co.,Ltd + 1-29-2,Wakabayashi + Setagaya-ku Tokyo 154-0023 + JP + +00-13-CD (hex) MTI co. LTD +0013CD (base 16) MTI co. LTD + 166-10 Karak-dong + Songpa-ku Seoul 138-810 + KR + +00-13-D3 (hex) MICRO-STAR INTERNATIONAL CO., LTD. +0013D3 (base 16) MICRO-STAR INTERNATIONAL CO., LTD. + NO. 69, LI-DE ST. + JUNG-HE CITY TAIPEI HSIEN 235 + TW + +00-13-CA (hex) Pico Digital +0013CA (base 16) Pico Digital + 6260 Sequence Drive + San Diego CA 92121 + US + +00-13-E6 (hex) Technolution +0013E6 (base 16) Technolution + Zuidelijkhalfrond 1 + GOUDA ZH 2801 DD + NL + +00-13-DF (hex) Ryvor Corp. +0013DF (base 16) Ryvor Corp. + 15145 Red Hill Ave. + Tustin CA 92780 + US + +00-13-8D (hex) Kinghold +00138D (base 16) Kinghold + 11F, No. 965, Jungjeng Rd. + Junghe Taipei 235 + TW + +00-13-ED (hex) PSIA +0013ED (base 16) PSIA + 517-13 Induspis 5th + SungNam KyungGi + KR + +00-13-B1 (hex) Intelligent Control Systems (Asia) Pte Ltd +0013B1 (base 16) Intelligent Control Systems (Asia) Pte Ltd + 70 Ubi Crescent #01-12 + 408570 + SG + +00-13-3C (hex) QUINTRON SYSTEMS INC. +00133C (base 16) QUINTRON SYSTEMS INC. + 2105 SO. BLOSSER ROAD + SANTA MARIA CALIFORNIA 93458 + US + +00-13-3D (hex) Micro Memory Curtiss Wright Co +00133D (base 16) Micro Memory Curtiss Wright Co + 9540 Vassar Avenue + Chatsworth CA 91311 + US + +00-13-3F (hex) Eppendorf Instrumente GmbH +00133F (base 16) Eppendorf Instrumente GmbH + Barkhausenweg 1 + Hamburg DE 22339 + DE + +00-13-41 (hex) Shandong New Beiyang Information Technology Co.,Ltd +001341 (base 16) Shandong New Beiyang Information Technology Co.,Ltd + NO.11 Xinwei Road + Weihai city Shandong 264200 + CN + +00-13-30 (hex) EURO PROTECTION SURVEILLANCE +001330 (base 16) EURO PROTECTION SURVEILLANCE + 30 Rue du Doubs + STRASBOURG 67100 + FR + +00-13-25 (hex) Cortina Systems Inc +001325 (base 16) Cortina Systems Inc + 840 W California Ave, Suite 100 + Sunnyvale CA 94086 + US + +00-13-31 (hex) CellPoint Connect +001331 (base 16) CellPoint Connect + Billedvej 4 + Copenhagen 2100 + DK + +00-13-35 (hex) VS Industry Berhad +001335 (base 16) VS Industry Berhad + Plo 47, Senai Ind. Est. II, + Senai Johor 81400 + MY + +00-13-2F (hex) Interactek +00132F (base 16) Interactek + Sigmal 2 BLDG #C-319, 18 Kumi-dong + Seongnam Kyung-gi 463-741 + KR + +00-13-4C (hex) YDT Technology International +00134C (base 16) YDT Technology International + 2F., No.218, Rueiguang Rd., + Taipei, 114 + TW + +00-13-59 (hex) ProTelevision Technologies A/S +001359 (base 16) ProTelevision Technologies A/S + Marielundvej 16,2 + Herlev Copenhagen 2730 + DK + +00-13-50 (hex) Silver Spring Networks, Inc +001350 (base 16) Silver Spring Networks, Inc + 575 Broadway Street + Redwood City CA 94063 + US + +00-13-7F (hex) Cisco Systems, Inc +00137F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-13-82 (hex) Cetacea Networks Corporation +001382 (base 16) Cetacea Networks Corporation + 3708 West 36th Avenue + Vancouver British Columbia V6N 2S4 + CA + +00-13-90 (hex) Termtek Computer Co., Ltd +001390 (base 16) Termtek Computer Co., Ltd + 2F, No. 100, Li De St., + Chung Ho City Taipei Hsien 235 + TW + +00-13-75 (hex) American Security Products Co. +001375 (base 16) American Security Products Co. + 11925 Pacific ave. + Fontana CA 92335 + US + +00-13-58 (hex) Realm Systems, Inc. +001358 (base 16) Realm Systems, Inc. + 9350 South 535 East + Sandy Utah 84070 + US + +00-12-C1 (hex) Check Point Software Technologies +0012C1 (base 16) Check Point Software Technologies + 5 Ha'solelim St. + Tel Aviv 67897 + IL + +00-12-BB (hex) Telecommunications Industry Association TR-41 Committee +0012BB (base 16) Telecommunications Industry Association TR-41 Committee + 2500 Wilson Blvd., Suite 300 + Arlington VA 22201 + US + +00-12-B6 (hex) Santa Barbara Infrared, Inc. +0012B6 (base 16) Santa Barbara Infrared, Inc. + 30 S. Calle Cesar Chavez + Santa Barbara CA 93103 + US + +00-12-B9 (hex) Fusion Digital Technology +0012B9 (base 16) Fusion Digital Technology + Victoria Mews, 23 Millfield Road + Bingley BD16 1PY + GB + +00-12-B4 (hex) Work Microwave GmbH +0012B4 (base 16) Work Microwave GmbH + Raiffeisenstrasse 12 + Holzkirchen 83607 + DE + +00-12-ED (hex) AVG Advanced Technologies +0012ED (base 16) AVG Advanced Technologies + 4140 Utica Ridge Road + Bettendorf IA 52722 + US + +00-12-EA (hex) Trane +0012EA (base 16) Trane + 4833 White Bear Parkway + St. Paul MN 55110 + US + +00-12-E7 (hex) Projectek Networking Electronics Corp. +0012E7 (base 16) Projectek Networking Electronics Corp. + 5F-9, No. 16, Lane 609, Sec. 5, Chungshin Rd., + Sanchung, Taipei 241 + TW + +00-12-C3 (hex) WIT S.A. +0012C3 (base 16) WIT S.A. + 138 avenue Léon Bérenger + Saint Laurent du Var PACA 06700 + FR + +00-12-C8 (hex) Perfect tech +0012C8 (base 16) Perfect tech + 3F,No.9,LANE175,NANKAN RD., + LUJHU TAOYUAN 338 + TW + +00-12-C6 (hex) TGC America, Inc +0012C6 (base 16) TGC America, Inc + 2901 Tasman Drive, Suite 111 + Santa Clara CA 95054 + US + +00-12-CC (hex) Bitatek CO., LTD +0012CC (base 16) Bitatek CO., LTD + 6F.,No 115,Wugong 3rd Rd + Wugu District New Taipei City 248 + TW + +00-12-FA (hex) THX LTD +0012FA (base 16) THX LTD + 5201 Great America Parkway + Santa Clara CA 95054 + US + +00-13-06 (hex) Always On Wireless +001306 (base 16) Always On Wireless + 3701 Kirby Dr + Houston TX 77098 + US + +00-12-FD (hex) OPTIMUS IC S.A. +0012FD (base 16) OPTIMUS IC S.A. + NAWOJOWSKA 118 + NOWY SACZ MALOPOLSKA 33-300 + PL + +00-13-05 (hex) Epicom, Inc. +001305 (base 16) Epicom, Inc. + PO Box 24839 + Oakland CA 94623-1839 + US + +00-12-E4 (hex) ZIEHL industrie-electronik GmbH + Co KG +0012E4 (base 16) ZIEHL industrie-electronik GmbH + Co KG + Daimlerstraße 13 + Schwaebisch Hall 74523 + DE + +00-12-97 (hex) O2Micro, Inc. +001297 (base 16) O2Micro, Inc. + 3118 Patrick Henry Drive + Santa Clara CA 95054 + US + +00-12-9D (hex) First International Computer do Brasil +00129D (base 16) First International Computer do Brasil + Rodovia BR 459 + Santa Rita do Sapucaí Minas Gerais + BR + +00-12-9C (hex) Yulinet +00129C (base 16) Yulinet + 11F, Samhomoolsan B/D 275-6, Yangjae-dong + Seocho Seoul 137-941 + KR + +00-12-90 (hex) KYOWA Electric & Machinery Corp. +001290 (base 16) KYOWA Electric & Machinery Corp. + 4-8-16,Masuizumi + Kanazawa Ishikawa 921-8025 + JP + +00-12-91 (hex) KWS Computersysteme GmbH +001291 (base 16) KWS Computersysteme GmbH + Carl Zeiss Str. 1 + Ettlingen BW 76275 + DE + +00-12-95 (hex) Aiware Inc. +001295 (base 16) Aiware Inc. + J-Tower 2F + Fuchu-shi Tokyo 183-0044 + JP + +00-12-8B (hex) Sensory Networks Inc +00128B (base 16) Sensory Networks Inc + Level 6, 140 William St + East Sydney NSW 2011 + AU + +00-12-8F (hex) Montilio +00128F (base 16) Montilio + 1 maskit st. + Hertzelia 46763 + IL + +00-12-A3 (hex) Trust International B.V. +0012A3 (base 16) Trust International B.V. + Laan van Barcelona 600 + Dordrecht Zuid holland 3317 DD + NL + +00-12-A7 (hex) ISR TECHNOLOGIES Inc +0012A7 (base 16) ISR TECHNOLOGIES Inc + 1100, rue Notre-Dame Ouest + Montreal Quebec H3C 1K3 + CA + +00-12-AA (hex) IEE, Inc. +0012AA (base 16) IEE, Inc. + 7740 Lemona Avenue + Van Nuys, CA 91405 + US + +00-12-9F (hex) RAE Systems +00129F (base 16) RAE Systems + 3775 North First Street + San Jose CA 95134 + US + +00-12-B5 (hex) Vialta, Inc. +0012B5 (base 16) Vialta, Inc. + 48461 Fremont Blvd. + Fremont CA 94538 + US + +00-12-B1 (hex) Dai Nippon Printing Co., Ltd +0012B1 (base 16) Dai Nippon Printing Co., Ltd + 2-8-21,Akabane-minami + Kita-ku Tokyo 115-0044 + JP + +00-12-89 (hex) Advance Sterilization Products +001289 (base 16) Advance Sterilization Products + 33 Technology Drive + Irvine California 92618 + US + +00-12-84 (hex) Lab33 Srl +001284 (base 16) Lab33 Srl + C.so F. Perrone 24 + Genoa GE 16152 + IT + +00-12-81 (hex) March Networks S.p.A. +001281 (base 16) March Networks S.p.A. + Via Dei Lavoratori Autobianchi n. 1, + Desio Milano 20033 + IT + +00-12-7E (hex) Digital Lifestyles Group, Inc. +00127E (base 16) Digital Lifestyles Group, Inc. + 801 South Sentous Ave. + City of Industry CA 91748 + US + +00-12-6B (hex) Ascalade Communications Limited +00126B (base 16) Ascalade Communications Limited + Unit 10-11, 35/F, Cable TV Tower, + + HK + +00-12-33 (hex) JRC TOKKI Co.,Ltd. +001233 (base 16) JRC TOKKI Co.,Ltd. + 3-2-1 Shinyoshidahigashi Kohoku-ku + Yokohama Kanagawa 223-8572 + JP + +00-12-5B (hex) KAIMEI ELECTRONI +00125B (base 16) KAIMEI ELECTRONI + 14-3F, NO.81,SEC. 1,HSIN-TAI-WU ROAD,HSICHIH, + TAIPEI HSIEN HSICHIH 221 + TW + +00-12-59 (hex) THERMO ELECTRON KARLSRUHE +001259 (base 16) THERMO ELECTRON KARLSRUHE + DIESELSTRAßE 4 + KARLSRUHE Baden-Württemberg 76227 + DE + +00-12-5A (hex) Microsoft Corporation +00125A (base 16) Microsoft Corporation + One Microsoft Way + Redmond Washington 98052-6399 + US + +00-12-3D (hex) GES Co, Ltd +00123D (base 16) GES Co, Ltd + Room 710, Bundang Technopark, 700 + Gyeonggi-Do 463-400 + KR + +00-12-39 (hex) S Net Systems Inc. +001239 (base 16) S Net Systems Inc. + 10F Sungwon Bldg. Samsung-dong + Seoul 135-090 + KR + +00-12-2F (hex) Sanei Electric Inc. +00122F (base 16) Sanei Electric Inc. + 5F Taisou-Ikebukuro Bldg. + Toshima-ku Tokyo 171-0014 + JP + +00-12-30 (hex) Picaso Infocommunication CO., LTD. +001230 (base 16) Picaso Infocommunication CO., LTD. + 3F, Suntechcity, Sangdaewon 1-dong, + Sungnam-city Kyunggi-do 462-725 + KR + +00-12-46 (hex) T.O.M TECHNOLOGY INC.. +001246 (base 16) T.O.M TECHNOLOGY INC.. + 906 Woolim E-biz Center 2, + Seoul Guro-Gu 184-1 + KR + +00-12-56 (hex) LG INFORMATION & COMM. +001256 (base 16) LG INFORMATION & COMM. + 459-9,KASAN-DONG,KUMCHON-GU, + SEOUL 153-023 + KR + +00-12-14 (hex) Koenig & Bauer AG +001214 (base 16) Koenig & Bauer AG + Friedrich-Koenig-Str. 4 + Wuerzburg Bavaria 97080 + DE + +00-12-0F (hex) IEEE 802.3 +00120F (base 16) IEEE 802.3 + + Oban PA34 5EJ + GB + +00-12-1D (hex) Netfabric Corporation +00121D (base 16) Netfabric Corporation + 67 Federal Road + Brookfield CT 06804 + US + +00-12-0C (hex) CE-Infosys Pte Ltd +00120C (base 16) CE-Infosys Pte Ltd + 390 Havelock Road + 169662 + SG + +00-11-B3 (hex) YOSHIMIYA CO.,LTD. +0011B3 (base 16) YOSHIMIYA CO.,LTD. + 2-3-24 Bainan + OSAKA OSAKA-Pref 557-0033 + JP + +00-11-B6 (hex) Open Systems International +0011B6 (base 16) Open Systems International + 4101 Arrowhead Drive + Medina MN 55340 + US + +00-11-B0 (hex) Fortelink Inc. +0011B0 (base 16) Fortelink Inc. + 42501 Albrae street suite 202 + Fremont CA 94538 + US + +00-11-AC (hex) Simtec Electronics +0011AC (base 16) Simtec Electronics + Avondale Drive + Tarleton Lancashire PR4 6AX + GB + +00-11-AD (hex) Shanghai Ruijie Technology +0011AD (base 16) Shanghai Ruijie Technology + 27F, 420 Jiangning Rd. + Shanghai 200041 + CN + +00-11-CD (hex) Axsun Technologies +0011CD (base 16) Axsun Technologies + 1 Fortune Drive + Billerica MA 02460 + US + +00-11-C5 (hex) TEN Technology +0011C5 (base 16) TEN Technology + 555 East Ocean Blvd. + Long Beach CA 90802 + US + +00-11-BE (hex) AGP Telecom Co. Ltd +0011BE (base 16) AGP Telecom Co. Ltd + 9F, 134 Chung-Hsiao E. RD + Taipei 106 + TW + +00-11-BA (hex) Elexol Pty Ltd +0011BA (base 16) Elexol Pty Ltd + Level 2 / 146 Bundall Road + Bundall Queensland 4217 + AU + +00-11-BC (hex) Cisco Systems, Inc +0011BC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-A8 (hex) Quest Technologies +0011A8 (base 16) Quest Technologies + 1060 Corporate Center Drive + Oconomowoc Wisconsin 53066 + US + +00-11-A1 (hex) VISION NETWARE CO.,LTD +0011A1 (base 16) VISION NETWARE CO.,LTD + Ace Twin Tower (2), #709 + Seoul Guro-Gu 152-050 + KR + +00-11-E2 (hex) Hua Jung Components Co., Ltd. +0011E2 (base 16) Hua Jung Components Co., Ltd. + 5F, No.13, Lane 120, Sec.1, Nei Hu Road + Taipei 114 + TW + +00-11-DA (hex) Vivaas Technology Inc. +0011DA (base 16) Vivaas Technology Inc. + 15F, No. 10, Sec 1, Pei-Hsin Rd., + Hsin-Tien city Taipei Hsien, 231 + TW + +00-11-DD (hex) FROMUS TEC. Co., Ltd. +0011DD (base 16) FROMUS TEC. Co., Ltd. + 2F 896-8 Hogye2-dong Dongan-Gu + 431-836 + KR + +00-11-EB (hex) Innovative Integration +0011EB (base 16) Innovative Integration + 2390A Ward Avenue + Simi Valley CA 93065 + US + +00-11-EA (hex) IWICS Inc. +0011EA (base 16) IWICS Inc. + 19125 North Creek Parkway + Bothell WA 98011 + US + +00-11-E4 (hex) Danelec Electronics A/S +0011E4 (base 16) Danelec Electronics A/S + Blokken 44 + Birkeroed Copenhagen 3460 + DK + +00-11-E1 (hex) Arcelik A.S +0011E1 (base 16) Arcelik A.S + Cumhuriyet Mah., E5 Yan Yol, No:1, + Istanbul 34520 + TR + +00-11-FB (hex) Heidelberg Engineering GmbH +0011FB (base 16) Heidelberg Engineering GmbH + Tiergartenstraße 15 + Heidelberg Baden-Württemberg 69121 + DE + +00-11-D6 (hex) HandEra, Inc. +0011D6 (base 16) HandEra, Inc. + 2859 104th St. + Des Moines IA 50322 + US + +00-11-CA (hex) Long Range Systems, Inc. +0011CA (base 16) Long Range Systems, Inc. + 4550 Excel Parkway + Addison Texas 75001 + US + +00-11-EF (hex) Conitec Datensysteme GmbH +0011EF (base 16) Conitec Datensysteme GmbH + Dieselstraße 11c + Dieburg Hessen 64807 + DE + +00-11-4F (hex) US Digital Television, Inc +00114F (base 16) US Digital Television, Inc + 5807 N. Andrews Way + Fort Lauderdale FL 33309 + US + +00-11-82 (hex) IMI Norgren Ltd +001182 (base 16) IMI Norgren Ltd + PO Box 22 + Lichfield Staffordshire WS13 6SB + GB + +00-11-7A (hex) Singim International Corp. +00117A (base 16) Singim International Corp. + 6F-2, No. 190, Sec. 2 Chung Hsin Road, + Hsin Tien City 231 + TW + +00-11-48 (hex) Prolon Control Systems +001148 (base 16) Prolon Control Systems + Herstedvesterstraede 56 + Albertslund DK-2620 + DK + +00-11-40 (hex) Nanometrics Inc. +001140 (base 16) Nanometrics Inc. + 250 Herzberg Rd. + Kanata Ontario K2K 2A1 + CA + +00-11-44 (hex) Assurance Technology Corp +001144 (base 16) Assurance Technology Corp + 6304 Potomac Avenue + Alexandria Virginia 22307 + US + +00-11-68 (hex) HomeLogic LLC +001168 (base 16) HomeLogic LLC + 100 Hoods Lane + Marblehead MA 01945 + US + +00-11-63 (hex) SYSTEM SPA DEPT. ELECTRONICS +001163 (base 16) SYSTEM SPA DEPT. ELECTRONICS + VIA GHIAROLA VECCHIA 73 + FIORANO MODENESE MODENA I-41042 + IT + +00-11-8F (hex) EUTECH INSTRUMENTS PTE. LTD. +00118F (base 16) EUTECH INSTRUMENTS PTE. LTD. + Blk 55,Ayer Rajah Crescent, #04-16/24. + 139949 + SG + +00-11-8D (hex) Hanchang System Corp. +00118D (base 16) Hanchang System Corp. + 1058-2, Shinkil-dong, Danwon-gu, + Ansan-si Gyeonggi-do 425-839 + KR + +00-11-5F (hex) ITX Security Co., Ltd. +00115F (base 16) ITX Security Co., Ltd. + 9F Kolon Digital Tower Aston Bldg. 505-14 + Gasan-dong Geumcheon-gu SEOUL 153-803 + KR + +00-11-53 (hex) Trident Tek, Inc. +001153 (base 16) Trident Tek, Inc. + 8041 Cessna Ave #200 + Gaithersburg MD 20879 + US + +00-11-72 (hex) COTRON CORPORATION +001172 (base 16) COTRON CORPORATION + 12FL,No.150,Sec.4,Cheng-De Rd + Taipei City 111 + TW + +00-11-A0 (hex) Vtech Engineering Canada Ltd +0011A0 (base 16) Vtech Engineering Canada Ltd + 200-7671 Alderbridge Way + Richmond BC V6X 1Z9 + CA + +00-11-9B (hex) Telesynergy Research Inc. +00119B (base 16) Telesynergy Research Inc. + 4F, No. 49, Tung Hsin Rd., + Taipei 110 + TW + +00-11-91 (hex) CTS-Clima Temperatur Systeme GmbH +001191 (base 16) CTS-Clima Temperatur Systeme GmbH + Lotzenäcker 21 + Hechingen Baden-Württemberg 72379 + DE + +00-11-89 (hex) Aerotech Inc +001189 (base 16) Aerotech Inc + 101 Zeta Drive + Pittsburgh PA 15238 + US + +00-0F-FB (hex) Nippon Denso Industry Co., Ltd. +000FFB (base 16) Nippon Denso Industry Co., Ltd. + 3-14-19 + Shibaura, Minato-ku Tokyo, 108-8560 + JP + +00-0F-F2 (hex) Loud Technologies Inc. +000FF2 (base 16) Loud Technologies Inc. + 16220 Wood-Red Rd. NE + Woodinville WA 98072 + US + +00-0F-F1 (hex) nex-G Systems Pte.Ltd +000FF1 (base 16) nex-G Systems Pte.Ltd + 25 Kallang Ave + 339416 + SG + +00-11-01 (hex) CET Technologies Pte Ltd +001101 (base 16) CET Technologies Pte Ltd + 100 Jurong East Street 21 + 609602 + SG + +00-0F-FF (hex) Control4 +000FFF (base 16) Control4 + 11734 S. Election Drive + Draper UT 84020 + US + +00-0F-FC (hex) Merit Li-Lin Ent. +000FFC (base 16) Merit Li-Lin Ent. + No. 20 Wu-Long 6 Rd. + Wu-Ku Taipei 242 + TW + +00-11-13 (hex) Fraunhofer FOKUS +001113 (base 16) Fraunhofer FOKUS + Kaiserin-Augusta-Allee 31 + Berlin 10589 + DE + +00-11-12 (hex) Honeywell CMSS +001112 (base 16) Honeywell CMSS + 8323 Lindbergh Ct + Sarasota FL 34243 + US + +00-0F-E0 (hex) NComputing Co.,Ltd. +000FE0 (base 16) NComputing Co.,Ltd. + 6th Fl, JEI-Platz B/D + Seoul Gasan-dong Geumcheon-Gu 459-11 + KR + +00-0F-E3 (hex) Damm Cellular Systems A/S +000FE3 (base 16) Damm Cellular Systems A/S + Moellegade 68 + Soenderborg DK-6400 + DK + +00-11-28 (hex) Streamit +001128 (base 16) Streamit + Flight Forum 3543 + Eindhoven 5657 DW + NL + +00-11-3F (hex) Alcatel DI +00113F (base 16) Alcatel DI + ZI lavoisier + EU Normandie 76260 + FR + +00-11-37 (hex) AICHI ELECTRIC CO., LTD. +001137 (base 16) AICHI ELECTRIC CO., LTD. + 1 + kasugai city aichi pref. 486-8666 + JP + +00-0F-F3 (hex) Jung Myoung Communications&Technology +000FF3 (base 16) Jung Myoung Communications&Technology + 1th FL., Dong IL Bldg.107 Yangjae-Dong + Seocho-Ku Seoul 137-130 + KR + +00-11-3A (hex) SHINBORAM +00113A (base 16) SHINBORAM + 4F DAHNWORLD BUILDING, 154-11 SAMSUNG-DONG + SEOUL 135-879 + KR + +00-0F-89 (hex) Winnertec System Co., Ltd. +000F89 (base 16) Winnertec System Co., Ltd. + #405, 4th Floor. Ace-Techno Tower III, 197-48, + Seoul 152-766 + KR + +00-0F-A4 (hex) Sprecher Automation GmbH +000FA4 (base 16) Sprecher Automation GmbH + Franckstrasse 51 + Linz Oberösterreich 4018 + AT + +00-0F-A6 (hex) S2 Security Corporation +000FA6 (base 16) S2 Security Corporation + 6 Abbott Road + Wellesley MA 02481 + US + +00-0F-AA (hex) Nexus Technologies +000FAA (base 16) Nexus Technologies + 10 National Ave. + Fletcher NC 28732 + US + +00-0F-A8 (hex) Photometrics, Inc. +000FA8 (base 16) Photometrics, Inc. + 3440 E Britannia Drive + Tucson AZ 85706-5006 + US + +00-0F-BD (hex) MRV Communications (Networks) LTD +000FBD (base 16) MRV Communications (Networks) LTD + P.O Box 614 + Yokneam 20692 + IL + +00-0F-B4 (hex) Timespace Technology +000FB4 (base 16) Timespace Technology + Blackstone Road + Huntingdon Cambridgeshire PE29 6TT + GB + +00-0F-9D (hex) DisplayLink (UK) Ltd +000F9D (base 16) DisplayLink (UK) Ltd + Mount Pleasant House + Cambridge Cambridgeshire CB3 0RN + GB + +00-0F-C5 (hex) KeyMed Ltd +000FC5 (base 16) KeyMed Ltd + KeyMed House + Southend on Sea Essex SS2 5QH + GB + +00-0F-BF (hex) DGT Sp. z o.o. +000FBF (base 16) DGT Sp. z o.o. + ul. Jaskowa Dolina 15 + Gdansk woj. pomorskie 80-252 + PL + +00-0F-92 (hex) Microhard Systems Inc. +000F92 (base 16) Microhard Systems Inc. + #17, 2135-32Ave NE + Calgary AB T2E6Z3 + CA + +00-0F-CB (hex) 3Com Ltd +000FCB (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +00-0F-D5 (hex) Schwechat - RISE +000FD5 (base 16) Schwechat - RISE + Am Concorde Park 2A + Schwechat 2320 + AT + +00-0F-67 (hex) West Instruments +000F67 (base 16) West Instruments + Unit 5, The Hyde, Lower Bevendean + Brighton East Sussex BN2 4JU + GB + +00-0F-6E (hex) BBox +000F6E (base 16) BBox + Gyar u. 2. (115) + Budaors H-2040 + HU + +00-0F-6F (hex) FTA Communication Technologies +000F6F (base 16) FTA Communication Technologies + 11, rue Pierre Werner + Betzdorf L-6832 + LU + +00-0F-63 (hex) Obzerv Technologies +000F63 (base 16) Obzerv Technologies + 400 Jean Lesage + Quebec QC G1K8W1 + CA + +00-0F-21 (hex) Scientific Atlanta, Inc +000F21 (base 16) Scientific Atlanta, Inc + 5030 Sugarloaf Parkway + Lawrenceville Ga 30042 + US + +00-0F-11 (hex) Prodrive B.V. +000F11 (base 16) Prodrive B.V. + P.O. 28030 + Eindhoven 5602 JA + NL + +00-0F-13 (hex) Nisca corporation +000F13 (base 16) Nisca corporation + 430-1 + Masuho-Cho Yamanashi-Ken 400-0593 + JP + +00-0F-14 (hex) Mindray Co., Ltd. +000F14 (base 16) Mindray Co., Ltd. + Mindray Building, Keji 12th Road South + Shenzhen Guangdong 518057 + CN + +00-0F-65 (hex) icube Corp. +000F65 (base 16) icube Corp. + Olympia Center 2F,828-10,Yeoksam-dong,Kangnam-ku + Seoul South 135-935 + KR + +00-0F-5D (hex) Genexis BV +000F5D (base 16) Genexis BV + Lodewijktraat 1A + 5652 AC Eindhoven + SE + +00-0F-58 (hex) Adder Technology Limited +000F58 (base 16) Adder Technology Limited + Technology House + Bar Hill Cambridgeshire CB3 8SQ + GB + +00-0F-12 (hex) Panasonic Europe Ltd. +000F12 (base 16) Panasonic Europe Ltd. + Hesebergweg 49-51 + Peine D-31228 + DE + +00-0F-0E (hex) WaveSplitter Technologies, Inc. +000F0E (base 16) WaveSplitter Technologies, Inc. + 2248 North First Street + San Jose CA 95131 + US + +00-0F-0C (hex) SYNCHRONIC ENGINEERING +000F0C (base 16) SYNCHRONIC ENGINEERING + 25 CAP DARNETAL + DARNETAL FRANCE 76160 + FR + +00-0F-0B (hex) Kentima Technologies AB +000F0B (base 16) Kentima Technologies AB + Box 174 + Staffanstorp Skåne 245 44 + SE + +00-0F-46 (hex) SINAR AG +000F46 (base 16) SINAR AG + Stadtweg 24 + Feuerthalen ZH CH-8245 + CH + +00-0F-41 (hex) Zipher Ltd +000F41 (base 16) Zipher Ltd + 7 Faraday Building + Nottingham Nottinghamshire NG7 2QP + GB + +00-0F-4D (hex) TalkSwitch +000F4D (base 16) TalkSwitch + 1545 Carling Ave + Ottawa Ontario K1Z 8P9 + CA + +00-0F-71 (hex) Sanmei Electronics Co.,Ltd +000F71 (base 16) Sanmei Electronics Co.,Ltd + 2-2-1,Seikai,Shimizu + Shizuoka 424-0924 + JP + +00-0F-6B (hex) GateWare Communications GmbH +000F6B (base 16) GateWare Communications GmbH + Allersberger Strasse 185 F + Nuernberg Bavaria D-90461 + DE + +00-0E-D5 (hex) COPAN Systems Inc. +000ED5 (base 16) COPAN Systems Inc. + 2605 Trade Centre Ave. + Longmont CO 80503 + US + +00-0E-CA (hex) WTSS Inc +000ECA (base 16) WTSS Inc + 5999 Avenida Encinas + Carlsbad CA 92008 + US + +00-0E-CC (hex) Tableau, LLC +000ECC (base 16) Tableau, LLC + N8 W22195 Johnson Drive, Suite 100 + Waukesha WI 53186 + US + +00-0E-CB (hex) VineSys Technology +000ECB (base 16) VineSys Technology + 3350 Scott Blvd. building 15-03 + Santa Clara CA 95054 + US + +00-0E-D2 (hex) Filtronic plc +000ED2 (base 16) Filtronic plc + The Waterfront + Saltaire W Yorks BD18 3TT + GB + +00-0E-C8 (hex) Zoran Corporation +000EC8 (base 16) Zoran Corporation + 1390 Kifer Rd. + Sunnyvale CA 94086 + US + +00-0E-D9 (hex) Aksys, Ltd. +000ED9 (base 16) Aksys, Ltd. + 2 Marriott Drive + Lincolnshire IL 60069 + US + +00-0E-B4 (hex) GUANGZHOU GAOKE COMMUNICATIONS TECHNOLOGY CO.LTD. +000EB4 (base 16) GUANGZHOU GAOKE COMMUNICATIONS TECHNOLOGY CO.LTD. + AVE. 398 ZHONGSHAN + GUANGZHOU GUANGDONG 510660 + CN + +00-0E-B1 (hex) Newcotech,Ltd +000EB1 (base 16) Newcotech,Ltd + Anyang Megavally 715-3 + Anyang City Gueonggi-Do 431-160 + KR + +00-0E-A9 (hex) Shanghai Xun Shi Communications Equipment Ltd. Co. +000EA9 (base 16) Shanghai Xun Shi Communications Equipment Ltd. Co. + Hi-Tech King World, Unit C603 + Shanghai 200001 + CN + +00-0E-B6 (hex) Riverbed Technology, Inc. +000EB6 (base 16) Riverbed Technology, Inc. + 680 Folsom St. + San Francisco CA 94107 + US + +00-0E-B7 (hex) Knovative, Inc. +000EB7 (base 16) Knovative, Inc. + 11245 West Bernardo Court + San Diego CA 92127 + US + +00-0E-FA (hex) Optoway Technology Incorporation +000EFA (base 16) Optoway Technology Incorporation + No. 38, Kuang Fu South Road + Hu Kou Hsin Chu 303 + TW + +00-0E-FD (hex) FUJINON CORPORATION +000EFD (base 16) FUJINON CORPORATION + 1-324 UETAKE, KITA-KU, + SAITAMA CITY SAITAMA 331-9624 + JP + +00-0E-F5 (hex) iPAC Technology Co., Ltd. +000EF5 (base 16) iPAC Technology Co., Ltd. + 6F, No. 30, Shingjung Road, Neihu + Taipei 114 + TW + +00-0E-FB (hex) Macey Enterprises +000EFB (base 16) Macey Enterprises + P.O. Box 7267 + Tempe AZ 85281 + US + +00-0F-09 (hex) Private +000F09 (base 16) Private + +00-0E-DC (hex) Tellion INC. +000EDC (base 16) Tellion INC. + 5th Fl. BONA Venture Town + Seoul Seocho-gu. 137-719 + KR + +00-0E-CD (hex) SKOV A/S +000ECD (base 16) SKOV A/S + Hedelund 4 + Roslev DK-7870 + DK + +00-0E-DB (hex) XiNCOM Corp. +000EDB (base 16) XiNCOM Corp. + 2840 Industrial Ave. + Hubbard OR 97032 + US + +00-0E-DD (hex) SHURE INCORPORATED +000EDD (base 16) SHURE INCORPORATED + 5800 W. TOUHY AVE. + NILES IL 60714 + US + +00-0E-C2 (hex) Lowrance Electronics, Inc. +000EC2 (base 16) Lowrance Electronics, Inc. + 12000 E. Skelly Drive + Tulsa OK 74128 + US + +00-0E-A3 (hex) CNCR-IT CO.,LTD,HangZhou P.R.CHINA +000EA3 (base 16) CNCR-IT CO.,LTD,HangZhou P.R.CHINA + Yinjiang mansion NO.5F Wenyi Road + HangZhou ZheJiang 310012 + CN + +00-0E-A2 (hex) McAfee, Inc +000EA2 (base 16) McAfee, Inc + 350 SW 12th Avenue + Deerfield Beach FL 33442 + US + +00-0E-9B (hex) Ambit Microsystems Corporation +000E9B (base 16) Ambit Microsystems Corporation + 5F-1, 5 Hsin-An Rd. Science-Based Industrial Park + Hsinchu 300 + TW + +00-0E-78 (hex) Amtelco +000E78 (base 16) Amtelco + 4800 Curtin Drive + McFarland WI 53558 + US + +00-0E-71 (hex) Gemstar Technology Development Ltd. +000E71 (base 16) Gemstar Technology Development Ltd. + Unit 201, Stulex house, 698 prince edward road east, san po kong, Kolwoon + Hong Kong 852 + HK + +00-0E-70 (hex) in2 Networks +000E70 (base 16) in2 Networks + 320 W 200 S + SLC UT 84101 + US + +00-0E-37 (hex) Harms & Wende GmbH & Co.KG +000E37 (base 16) Harms & Wende GmbH & Co.KG + Grossmoorkehre 9 + Hamburg D-21079 + DE + +00-0E-31 (hex) Olympus Soft Imaging Solutions GmbH +000E31 (base 16) Olympus Soft Imaging Solutions GmbH + Johann-Krane-Weg 39 + Münster 48149 + DE + +00-0E-2F (hex) Roche Diagnostics GmbH +000E2F (base 16) Roche Diagnostics GmbH + Roche Diabetes Care Insulin Delivery Systems + D-68305 Mannheim + DE + +00-0E-2A (hex) Private +000E2A (base 16) Private + +00-0E-9E (hex) Topfield Co., Ltd +000E9E (base 16) Topfield Co., Ltd + 4th floor, Deoksan Bldg 260-4, Seohyun-dong + Seongnam Bundang-Ku 463-824 + KR + +00-0E-41 (hex) NIHON MECHATRONICS CO.,LTD. +000E41 (base 16) NIHON MECHATRONICS CO.,LTD. + 9-6 SHIOMIDAI, MIYAMAE-KU + KAWASAKI-SHI KANAGAWA-KEN 216-0013 + JP + +00-0E-3C (hex) Transact Technologies Inc +000E3C (base 16) Transact Technologies Inc + 20 Bomax Drive + Ithaca New York 14850 + US + +00-0E-63 (hex) Lemke Diagnostics GmbH +000E63 (base 16) Lemke Diagnostics GmbH + Radeburger Str. 47 + Volkersdorf Saxony 01468 + DE + +00-0E-5B (hex) ParkerVision - Direct2Data +000E5B (base 16) ParkerVision - Direct2Data + 9432 Baymeadows Way + Jacksonville FL 32246 + US + +00-0E-60 (hex) 360SUN Digital Broadband Corporation +000E60 (base 16) 360SUN Digital Broadband Corporation + 2F-2, No.2, Jianba Rd., + Chung Ho Taipei 235 + TW + +00-0E-54 (hex) AlphaCell Wireless Ltd. +000E54 (base 16) AlphaCell Wireless Ltd. + 22 Zarhin street + Raanana 43662 + IL + +00-0E-4E (hex) Waveplus Technology Co., Ltd. +000E4E (base 16) Waveplus Technology Co., Ltd. + 347 HsinHu 2nd Rd., NeiHu + Taipei 114 + TW + +00-0E-4A (hex) Changchun Huayu WEBPAD Co.,LTD +000E4A (base 16) Changchun Huayu WEBPAD Co.,LTD + 4370 Gaoxin Road, High-Tech + Changchun Jilin 130012 + CN + +00-0E-93 (hex) Milénio 3 Sistemas Electrónicos, Lda. +000E93 (base 16) Milénio 3 Sistemas Electrónicos, Lda. + Edifício Via Norte, R. Espido 164C S403 + Maia Minho 4470-177 + PT + +00-0E-8D (hex) Systems in Progress Holding GmbH +000E8D (base 16) Systems in Progress Holding GmbH + Exerzierplatzstrasse 85 + Graz Styria 8051 + AT + +00-0E-76 (hex) GEMSOC INNOVISION INC. +000E76 (base 16) GEMSOC INNOVISION INC. + 9F,No.516,Sec,1Neihu Rd., + Taipei 114 + TW + +00-0E-7D (hex) Electronics Line 3000 Ltd. +000E7D (base 16) Electronics Line 3000 Ltd. + 2 Granit St. + Petah Tikva Kiryar Arie 449130 + IL + +00-0E-2C (hex) Netcodec co. +000E2C (base 16) Netcodec co. + 401 Daeion S/W Center, 48 Jangdong + Daejon 305-715 + KR + +00-0E-23 (hex) Incipient, Inc. +000E23 (base 16) Incipient, Inc. + 230 Third Ave. + Waltham MA 02451 + US + +00-0E-25 (hex) Hannae Technology Co., Ltd +000E25 (base 16) Hannae Technology Co., Ltd + 4F, Hyunjin Bldg., #798-30, Yeoksam-Dong + SEOUL 135-080 + KR + +00-0E-20 (hex) ACCESS Systems Americas, Inc. +000E20 (base 16) ACCESS Systems Americas, Inc. + 1188 East Arques Avenue + Sunnyvale CA 94085 + US + +00-0E-21 (hex) MTU Friedrichshafen GmbH +000E21 (base 16) MTU Friedrichshafen GmbH + Maybachplatz 1 + Friedrichshafen Baden Wuertemberg 88040 + DE + +00-0D-D4 (hex) Symantec Corporation +000DD4 (base 16) Symantec Corporation + 275 2nd Ave + Waltham MA 02541 + US + +00-0D-D2 (hex) Simrad Optronics ASA +000DD2 (base 16) Simrad Optronics ASA + Ensjøveienn 23B + PO Box 6114 Etterstad NO-0602 Oslo + NO + +00-0D-D1 (hex) Stryker Corporation +000DD1 (base 16) Stryker Corporation + 4100 E Milham + Kalamazoo MI 49001 + US + +00-0D-D7 (hex) Bright +000DD7 (base 16) Bright + 1-12-44 Aobadai + Kashiwa-shi Chiba-ken 277-0055 + JP + +00-0D-D9 (hex) Anton Paar GmbH +000DD9 (base 16) Anton Paar GmbH + Anton-Paar-Strasse 20 + Graz 8054 + AT + +00-0D-DC (hex) VAC +000DDC (base 16) VAC + 20F, N0. 456, Sec. 4, Hsin Yi Rd., + Taipei 110 + TW + +00-0D-E0 (hex) ICPDAS Co.,LTD +000DE0 (base 16) ICPDAS Co.,LTD + No. 111, Kuang-Fu N. Rd., Hsin-Chu Indu + HSINCHU 303 + TW + +00-0D-E3 (hex) AT Sweden AB +000DE3 (base 16) AT Sweden AB + P.O. Box 1166 + Kista Stockholm SE-164 26 + SE + +00-0D-EA (hex) Kingtel Telecommunication Corp. +000DEA (base 16) Kingtel Telecommunication Corp. + 147 Kang Ning St. + Hsi Chih City Taipei Hsien 221 + TW + +00-0D-ED (hex) Cisco Systems, Inc +000DED (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0D-E4 (hex) DIGINICS, Inc. +000DE4 (base 16) DIGINICS, Inc. + 178-7 Poi-dong + Kangnam-gu Seoul 135-961 + KR + +00-0E-09 (hex) Shenzhen Coship Software Co.,LTD. +000E09 (base 16) Shenzhen Coship Software Co.,LTD. + 7/F,Block A,W2 Bldg,Hi-Tech Industrial Park,Shenzhen,China + Shenzhen Guangdong 518057 + CN + +00-0E-05 (hex) WIRELESS MATRIX CORP. +000E05 (base 16) WIRELESS MATRIX CORP. + UNIT 1A-3751 NORTH FRASER WAY + BURNABY BC V5J 5G4 + CA + +00-0E-22 (hex) Private +000E22 (base 16) Private + +00-0E-1C (hex) Hach Company +000E1C (base 16) Hach Company + 5600 Lindbergh Drive + Loveland CO 80538 + US + +00-0E-02 (hex) Advantech AMT Inc. +000E02 (base 16) Advantech AMT Inc. + 657 Orly Ave. + Dorval Quebec H9P 1G1 + CA + +00-0D-C9 (hex) THALES Elektronik Systeme GmbH +000DC9 (base 16) THALES Elektronik Systeme GmbH + Fritz-Ludwig-Str. 1 + Koblenz 56070 + DE + +00-0D-81 (hex) Pepperl+Fuchs GmbH +000D81 (base 16) Pepperl+Fuchs GmbH + Lilienthalstraße 200 + Mannheim 68307 + DE + +00-0D-7A (hex) DiGATTO Asia Pacific Pte Ltd +000D7A (base 16) DiGATTO Asia Pacific Pte Ltd + 190 Mddle Road, #19-05 Fortune Center + 188979 + SG + +00-0D-77 (hex) FalconStor Software +000D77 (base 16) FalconStor Software + 125 Baylis Rd + Melville NY 11747 + US + +00-0D-76 (hex) Hokuto Denshi Co,. Ltd. +000D76 (base 16) Hokuto Denshi Co,. Ltd. + 3-7 Odori Nishi 16-Chome Chuoku + Sapporo Hokkaido 060-0042 + JP + +00-0D-7B (hex) Consensys Computers Inc. +000D7B (base 16) Consensys Computers Inc. + 215 Shields Ct. + Markham ON L3R 8V2 + CA + +00-0D-8F (hex) King Tsushin Kogyo Co., LTD. +000D8F (base 16) King Tsushin Kogyo Co., LTD. + 1-10-1 Edanishi Aobaku + Yokohama 225-0014 + JP + +00-0D-89 (hex) Bils Technology Inc +000D89 (base 16) Bils Technology Inc + 508 S River Oaks Drive + Indialantic FL 32903 + US + +00-0D-86 (hex) Huber + Suhner AG +000D86 (base 16) Huber + Suhner AG + Degersheimerstrasse 14 + 9100 Herisau + CH + +00-0D-C8 (hex) AirMagnet, Inc +000DC8 (base 16) AirMagnet, Inc + 830 E. Arques Avenue + Sunnyvale CA 94085 + US + +00-0D-BE (hex) Bel Fuse Europe Ltd.,UK +000DBE (base 16) Bel Fuse Europe Ltd.,UK + 45/46 Riverside 2 + Rochester Kent ME2 4DP + GB + +00-0D-BC (hex) Cisco Systems, Inc +000DBC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0D-9F (hex) RF Micro Devices +000D9F (base 16) RF Micro Devices + 2191 Zanker Road + San Jose CA 95131 + US + +00-0D-A5 (hex) Fabric7 Systems, Inc +000DA5 (base 16) Fabric7 Systems, Inc + 1300 Crittenden Lane + Mountain View CA 94043 + US + +00-0D-C5 (hex) EchoStar Global B.V. +000DC5 (base 16) EchoStar Global B.V. + Schuilenburglaan 5a + Almelo Overijssel 7604BJ + NL + +00-0D-99 (hex) Orbital Sciences Corp.; Launch Systems Group +000D99 (base 16) Orbital Sciences Corp.; Launch Systems Group + 3380 S. Price Rd. + Chandler, AZ 85248 + US + +00-0D-6C (hex) M-Audio +000D6C (base 16) M-Audio + 45 E ST Joseph St. + Arcadia CA 91006 + US + +00-0D-70 (hex) Datamax Corporation +000D70 (base 16) Datamax Corporation + 4501 Parkway Commerce Blvd + Orlando FL 32808 + US + +00-0D-59 (hex) Amity Systems, Inc. +000D59 (base 16) Amity Systems, Inc. + 888 Tasman Drive + Milpitas CA 95035 + US + +00-0D-4E (hex) NDR Co.,LTD. +000D4E (base 16) NDR Co.,LTD. + Sumitomo seimei minatomachi MT BLDG + Osak Kinki 550-0015 + JP + +00-0D-50 (hex) Galazar Networks +000D50 (base 16) Galazar Networks + 35 Fitzgerald Ave + Ottawa ON K2H 1E6 + CA + +00-0D-17 (hex) Turbo Networks Co.Ltd +000D17 (base 16) Turbo Networks Co.Ltd + 2F,No 1223, Chung Cheng Rd. + Tao Yuan 330 + TW + +00-0D-18 (hex) Mega-Trend Electronics CO., LTD. +000D18 (base 16) Mega-Trend Electronics CO., LTD. + Tong Fu Yu Ind., Ku Keng Village, Guan Lan + Shengzhen Guang Dong 518110 + CN + +00-0D-20 (hex) ASAHIKASEI TECHNOSYSTEM CO.,LTD. +000D20 (base 16) ASAHIKASEI TECHNOSYSTEM CO.,LTD. + Kanda Jinbocho 1-105 + Chiyoda-ku Tokyo 101-8101 + JP + +00-0D-49 (hex) Triton Systems of Delaware, Inc. +000D49 (base 16) Triton Systems of Delaware, Inc. + 522 E. Railroad St. + Long Beach MS 39560 + US + +00-0D-48 (hex) AEWIN Technologies Co., Ltd. +000D48 (base 16) AEWIN Technologies Co., Ltd. + 7F, No. 2, Lane 47, Sec. 3, Nan-Gang Rd. + TAIPEI 115 + TW + +00-0D-24 (hex) SENTEC E&E CO., LTD. +000D24 (base 16) SENTEC E&E CO., LTD. + No. 32. Gong5 Rd. + Lungtan Taoyuan 325 + TW + +00-0D-22 (hex) Unitronics LTD +000D22 (base 16) Unitronics LTD + Unitronics Building + Ben Gurion Airport 70100 + IL + +00-0D-14 (hex) Vtech Innovation LP dba Advanced American Telephones +000D14 (base 16) Vtech Innovation LP dba Advanced American Telephones + 203-600 Parsippany Rd + Parsippany NJ 07054 + US + +00-0D-5B (hex) Smart Empire Investments Limited +000D5B (base 16) Smart Empire Investments Limited + Suite 2001-2006,Level 20 Landmark North + Xin Jie Hong Kong 00852 + CN + +00-0D-3A (hex) Microsoft Corp. +000D3A (base 16) Microsoft Corp. + One Microsoft Way + Redmond Wa. 98052 + US + +00-0D-30 (hex) IceFyre Semiconductor +000D30 (base 16) IceFyre Semiconductor + Suite 300 + Kanata Ontario K2K 3C9 + CA + +00-0D-31 (hex) Compellent Technologies, Inc. +000D31 (base 16) Compellent Technologies, Inc. + 7625 Smetana Lane + Eden Prairie Minnesota 55344 + US + +00-0D-2C (hex) Net2Edge Limited +000D2C (base 16) Net2Edge Limited + Kulite House Stroudley Road + Basingstoke Hampshire RG24 8UG + GB + +00-0D-25 (hex) SANDEN CORPORATION +000D25 (base 16) SANDEN CORPORATION + 20 Kotobuki-cho + Isesaki-shi Gunma 372-8502 + JP + +00-0D-6F (hex) Ember Corporation +000D6F (base 16) Ember Corporation + 343 Congress St + Boston Ma 02210 + US + +00-0D-5E (hex) NEC Personal Products +000D5E (base 16) NEC Personal Products + 6-80, Shimohanazawa 2-Chome + Yonezawa-shi Yamagata 992-8520 + JP + +00-0D-3F (hex) VTI Instruments Corporation +000D3F (base 16) VTI Instruments Corporation + 5425 Warner Road, Suite 13 + Valley View OH 44125 + US + +00-0C-E3 (hex) Option International N.V. +000CE3 (base 16) Option International N.V. + Kolonel Begaultlaan 45 + Leuven Brabant 3012 + BE + +00-0C-E7 (hex) MediaTek Inc. +000CE7 (base 16) MediaTek Inc. + 1F, No. 13, Innovation Road 1, + Hsinchu 300 + TW + +00-0C-E8 (hex) GuangZhou AnJuBao Co., Ltd +000CE8 (base 16) GuangZhou AnJuBao Co., Ltd + HeiQiaoTang TangXia TianHe + GuangZhou GuangDong 510665 + CN + +00-0C-E4 (hex) NeuroCom International, Inc. +000CE4 (base 16) NeuroCom International, Inc. + 9570 SE Lawnfield Rd + Clackamas OR 97015 + US + +00-0C-B5 (hex) Premier Technolgies, Inc +000CB5 (base 16) Premier Technolgies, Inc + PO Box 159 + Long Lake MN 55356 + US + +00-0C-B6 (hex) NANJING SEU MOBILE & INTERNET TECHNOLOGY CO.,LTD +000CB6 (base 16) NANJING SEU MOBILE & INTERNET TECHNOLOGY CO.,LTD + 5th floor,Building 5,ChangJiangHou Street No.6 + Nanjing Jiangsu 210018 + CN + +00-0C-C3 (hex) BeWAN systems +000CC3 (base 16) BeWAN systems + 16 rue du Moulin des Bruyères Courbevoie + Courbevoie Hauts de Seine 92400 + FR + +00-0C-B4 (hex) AutoCell Laboratories, Inc. +000CB4 (base 16) AutoCell Laboratories, Inc. + 174 Concord Street + Peterborough, New Hampshire 03458 + US + +00-0C-B1 (hex) Salland Engineering (Europe) BV +000CB1 (base 16) Salland Engineering (Europe) BV + Bedrijvenpark Berkum + Zwolle OV 8024 HA + NL + +00-0C-BC (hex) Iscutum +000CBC (base 16) Iscutum + #899-6 Ho-Gye Dong, Dong-An Gu + An-Yang City Kyong-Gi Do 431-080 + KR + +00-0D-04 (hex) Foxboro Eckardt Development GmbH +000D04 (base 16) Foxboro Eckardt Development GmbH + Glockenstrasse 52 + Stuttgart Baden-Württemberg 70376 + DE + +00-0D-08 (hex) AboveCable, Inc. +000D08 (base 16) AboveCable, Inc. + 8403 Colesville Road, #825 + Silver Spring MD 20910 + US + +00-0D-05 (hex) cybernet manufacturing inc. +000D05 (base 16) cybernet manufacturing inc. + 5 holland + irvine ca 92618 + US + +00-0C-FE (hex) Grand Electronic Co., Ltd +000CFE (base 16) Grand Electronic Co., Ltd + Room 1710, Block B Lucky tower, No.3 Don + Beijing 100027 + CN + +00-0D-0E (hex) Inqnet Systems, Inc. +000D0E (base 16) Inqnet Systems, Inc. + 321 NKIC Center, + Seoul 120-100 + KR + +00-0D-11 (hex) DENTSPLY - Gendex +000D11 (base 16) DENTSPLY - Gendex + 901 West Oakton Street + Des Plaines IL 60018-1884 + US + +00-0C-C8 (hex) Xytronix Research & Design, Inc. +000CC8 (base 16) Xytronix Research & Design, Inc. + 1488 East 2300 North + North Logan UT 84341-1627 + US + +00-0C-CA (hex) HGST a Western Digital Company +000CCA (base 16) HGST a Western Digital Company + 3403 Yerba Buena Road + San Jose CA 95135 + US + +00-0C-D0 (hex) Symetrix +000CD0 (base 16) Symetrix + 6408 216th St SW + Mountlake Terrace WA 98043 + US + +00-0C-D9 (hex) Itcare Co., Ltd +000CD9 (base 16) Itcare Co., Ltd + 408 KT Seocho, 1001-1 Bangbae-dong, + Seoul 137-850 + KR + +00-0C-D5 (hex) Passave Inc. +000CD5 (base 16) Passave Inc. + 1557 Jasper Dr. + Sunnyvale CA 94087 + US + +00-0C-D2 (hex) Schaffner EMV AG +000CD2 (base 16) Schaffner EMV AG + Nordstrasse 1 + Luterbach CH-4542 + CH + +00-0A-07 (hex) WebWayOne Ltd +000A07 (base 16) WebWayOne Ltd + 11 Kingfisher Court, + Newbury Berkshire RG14 5SJ + GB + +00-0C-B0 (hex) Star Semiconductor Corporation +000CB0 (base 16) Star Semiconductor Corporation + 6F, No.17, Li-Hsin Rd + Hsinchu City 300 + TW + +00-0C-34 (hex) Vixen Co., Ltd. +000C34 (base 16) Vixen Co., Ltd. + 5-17-3 Higashitokorozawa + Tokorozawa Saitama 359-0021 + JP + +00-0C-58 (hex) M&S Systems +000C58 (base 16) M&S Systems + 2861 Congressman Lane + Dallas TX 75220 + US + +00-0C-51 (hex) Scientific Technologies Inc. +000C51 (base 16) Scientific Technologies Inc. + 6550 Dumbarton Circle + Fremont CA 94560 + US + +00-0C-73 (hex) TELSON ELECTRONICS CO., LTD +000C73 (base 16) TELSON ELECTRONICS CO., LTD + Telson Venture Tower., 949-3 Dogok-Dong + Seoul Kangnam-Ku 135-739 + KR + +00-0C-65 (hex) Sunin Telecom +000C65 (base 16) Sunin Telecom + 1025-5 Dokok-Ri, Wabu-Eub + Namyangju-City Kyunggi-Do 472-900 + KR + +00-0C-6C (hex) Eve Systems GmbH +000C6C (base 16) Eve Systems GmbH + Rotkreuzplatz 1 + Munich 80634 + DE + +00-0C-6F (hex) Amtek system co.,LTD. +000C6F (base 16) Amtek system co.,LTD. + 14F-11,No.79,Sec. 1 ,Hsin Tai Wu Rd., + Taipei 221 + TW + +00-0C-7E (hex) Tellium Incorporated +000C7E (base 16) Tellium Incorporated + 2 Crescent Place + Oceanport New Jersey 07757 + US + +00-0C-87 (hex) AMD +000C87 (base 16) AMD + 4555 Great America Pkwy + Santa Clara CA 95054 + US + +00-0C-98 (hex) LETEK Communications Inc. +000C98 (base 16) LETEK Communications Inc. + Taeyang Bd. 2nd Floor, 2486 + SongNam Kyunggi-do 462-824 + KR + +00-0C-8E (hex) Mentor Engineering Inc +000C8E (base 16) Mentor Engineering Inc + 2891 Sunridge Way NE + Calgary Alberta T1Y7K7 + CA + +00-0C-A2 (hex) Harmonic Video Network +000CA2 (base 16) Harmonic Video Network + 10 Ha'amal st. Park Afek + Rosh Ha'ayin 48092 + IL + +00-0C-A4 (hex) Prompttec Product Management GmbH +000CA4 (base 16) Prompttec Product Management GmbH + Mariatrosterstr. 41 + Graz AUSTRIA A-8043 + AT + +00-0C-5B (hex) HANWANG TECHNOLOGY CO.,LTD +000C5B (base 16) HANWANG TECHNOLOGY CO.,LTD + 8F,Automation Building,95 Zhongguancun, + Beijing 100080 + CN + +00-0C-60 (hex) ACM Systems +000C60 (base 16) ACM Systems + 3034 Gold Canal Drive + Rancho Cordova CA 95670 + US + +00-0C-83 (hex) Logical Solutions +000C83 (base 16) Logical Solutions + 100T Washington Street + Milford CT 06460 + US + +00-0C-96 (hex) OQO, Inc. +000C96 (base 16) OQO, Inc. + 1800 Illinois Street + San Francisco CA 94124 + US + +00-0C-08 (hex) HUMEX Technologies Corp. +000C08 (base 16) HUMEX Technologies Corp. + 5F, No.5, Lane 44, Szu Wei Rd. Taan Taip + Taipei 106 + TW + +00-0C-0D (hex) Communications & Power Industries / Satcom Division +000C0D (base 16) Communications & Power Industries / Satcom Division + 811 Hansen Way MS S-600 + Palo Alto CA 94303 + US + +00-0C-04 (hex) Tecnova +000C04 (base 16) Tecnova + 1486 St. Paul Ave. + Gurnee Illinois 60031 + US + +00-0C-01 (hex) Abatron AG +000C01 (base 16) Abatron AG + Lettenstrasse 9 + Rotkreuz CH-6343 + CH + +00-0C-39 (hex) Sentinel Wireless Inc. +000C39 (base 16) Sentinel Wireless Inc. + 439 S. Union St. + South Lawrence MA 01843 + US + +00-0C-32 (hex) Avionic Design Development GmbH +000C32 (base 16) Avionic Design Development GmbH + Sthamerstrasse 24a + Hamburg 22397 + DE + +00-0C-33 (hex) Compucase Enterprise Co. Ltd. +000C33 (base 16) Compucase Enterprise Co. Ltd. + 225 Lane 54, An Ho Road, Section 2nd. + Tainan City 70942 + TW + +00-0C-36 (hex) SHARP TAKAYA ELECTRONICS INDUSTRY CO.,LTD. +000C36 (base 16) SHARP TAKAYA ELECTRONICS INDUSTRY CO.,LTD. + 3121-1 Satomi Satosho-cho + Asakuchi-gun Okayama 719-0301 + JP + +00-0B-F6 (hex) Nitgen Co., Ltd +000BF6 (base 16) Nitgen Co., Ltd + 4th FL. 1337-31 Seocho-dong, Seocho-ku + Seoul 137-860 + KR + +00-0B-FD (hex) Cisco Systems, Inc +000BFD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-FA (hex) EXEMYS SRL +000BFA (base 16) EXEMYS SRL + LOYOLA 680 + CAPITAL FEDERAL BS AS C1414 + AR + +00-0B-F4 (hex) Private +000BF4 (base 16) Private + +00-0B-FB (hex) D-NET International Corporation +000BFB (base 16) D-NET International Corporation + 15, Wu-Chuan 5th Road, Wu-Ku Industrial + Taipei Hsieh 248 + US + +00-0C-1D (hex) Mettler & Fuchs AG +000C1D (base 16) Mettler & Fuchs AG + Querstrasse 17 + CH-8951 Fahrweid + CH + +00-0C-1E (hex) Global Cache +000C1E (base 16) Global Cache + 160 East California Street + Jacksonville OR 97530 + US + +00-0C-1A (hex) Quest Technical Solutions Inc. +000C1A (base 16) Quest Technical Solutions Inc. + 4110 Mourning Dove Crt. + Melbourne FL 32934 + US + +00-0C-24 (hex) ANATOR +000C24 (base 16) ANATOR + 44, rue d'Estienne d'Orves + sartrouville yvelines 78500 + FR + +00-0C-19 (hex) Telio Communications GmbH +000C19 (base 16) Telio Communications GmbH + Elbchaussee 1 + Hamburg 22765 + DE + +00-0C-13 (hex) MediaQ +000C13 (base 16) MediaQ + 2975 San Ysidro Way + Santa Clara CA 95051 + US + +00-0C-06 (hex) Nixvue Systems Pte Ltd +000C06 (base 16) Nixvue Systems Pte Ltd + 30 Loyang Way, #07-02 + Singapore Singapore S508769 + SG + +00-0C-2D (hex) FullWave Technology Co., Ltd. +000C2D (base 16) FullWave Technology Co., Ltd. + 7F-6, No.26, TaiYuan St., + JuBei Hsin Chu 302 + TW + +00-0C-26 (hex) Weintek Labs. Inc. +000C26 (base 16) Weintek Labs. Inc. + 3F, No.910, Chung Cheng Rd. + Chung Ho city Taipei Hsien 236 + TW + +00-0C-2B (hex) ELIAS Technology, Inc. +000C2B (base 16) ELIAS Technology, Inc. + 3F, 1015, Yung-An Road, + Taoyuan City Taoyuan 330 + TW + +00-0B-F0 (hex) MoTEX Products Co., Ltd. +000BF0 (base 16) MoTEX Products Co., Ltd. + C.P.O.Box 6912 + Chong-gu Seoul 82 + KR + +00-0B-F1 (hex) LAP Laser Applikations +000BF1 (base 16) LAP Laser Applikations + Zeppelinstraße 23 + Lüneburg Niedersachsen 21337 + DE + +00-0B-EE (hex) inc.jet, Incorporated +000BEE (base 16) inc.jet, Incorporated + One Winnenden Road + Norwich CT 06360 + US + +00-0B-8D (hex) Avvio Networks +000B8D (base 16) Avvio Networks + 11 Donovan Dr + Bedford MA 01730 + US + +00-0B-85 (hex) Cisco Systems, Inc +000B85 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-7F (hex) Align Engineering LLC +000B7F (base 16) Align Engineering LLC + 245 Highlands Drive + Friday Harbor WA 98250 + US + +00-0B-A6 (hex) Miyakawa Electric Works Ltd. +000BA6 (base 16) Miyakawa Electric Works Ltd. + 2-1-6, + Yokohama Kanagawa 222-0001 + JP + +00-0B-93 (hex) Ritter Elektronik +000B93 (base 16) Ritter Elektronik + Leverkuser Straße 65 + Remscheid NRW 42897 + DE + +00-0B-9B (hex) Sirius System Co, Ltd. +000B9B (base 16) Sirius System Co, Ltd. + 3-27 Funado-cho + Ashiya Hyogo 659-0093 + JP + +00-0B-E2 (hex) Lumenera Corporation +000BE2 (base 16) Lumenera Corporation + 2520B St. Laurent Blvd. + Ottawa Ontario K1B 4R8 + CA + +00-0B-E1 (hex) Nokia NET Product Operations +000BE1 (base 16) Nokia NET Product Operations + 313 Fairchild Drive + Mountain View California 94043 + US + +00-0B-A8 (hex) HANBACK ELECTRONICS CO., LTD. +000BA8 (base 16) HANBACK ELECTRONICS CO., LTD. + 306-7, Galma-dong, Seo-gu + Daejeon 302-171 + KR + +00-0B-A9 (hex) CloudShield Technologies, Inc. +000BA9 (base 16) CloudShield Technologies, Inc. + 212 Gilbraltar Drive + Sunnyvale CA 94089 + US + +00-0B-A1 (hex) Fujikura Solutions Ltd. +000BA1 (base 16) Fujikura Solutions Ltd. + 1565-6,Shirakusadai,Fukaya-shi + Saitama-ken 369-1106 + JP + +00-0B-8E (hex) Ascent Corporation +000B8E (base 16) Ascent Corporation + 2-16-19, Kawaraya-machi, Chuo-Ku, + Osaka-City Osaka-Pref 542-0066 + JP + +00-0B-8F (hex) AKITA ELECTRONICS SYSTEMS CO.,LTD. +000B8F (base 16) AKITA ELECTRONICS SYSTEMS CO.,LTD. + 85,AZA USHIRONO,AIKAWA,YUWA-MACHI + KAWABE-GUN AKITA-KEN 010-1231 + JP + +00-0B-CB (hex) Fagor Automation , S. Coop +000BCB (base 16) Fagor Automation , S. Coop + San Andres s/n + Guipuzcoa 20500 + ES + +00-0B-C8 (hex) AirFlow Networks +000BC8 (base 16) AirFlow Networks + 444 Castro St + Mountain View Ca 94041 + US + +00-0B-CE (hex) Free2move AB +000BCE (base 16) Free2move AB + Sperlingsgatan 7 + Halmstad Halland 30248 + SE + +00-0B-CF (hex) AGFA NDT INC. +000BCF (base 16) AGFA NDT INC. + 50 Industrial Park Road + Lewistown PA 17044 + US + +00-0B-C3 (hex) Multiplex, Inc. +000BC3 (base 16) Multiplex, Inc. + 5000 Hadley Rd. + S. Plainfield NJ 07040 + US + +00-0B-BE (hex) Cisco Systems, Inc +000BBE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-E0 (hex) SercoNet Ltd. +000BE0 (base 16) SercoNet Ltd. + 16 Ha'haroshet st. + Ra'anana 43657 + IL + +00-0B-BD (hex) Connexionz Limited +000BBD (base 16) Connexionz Limited + 1 Show Place + Christchurch + NZ + +00-0B-40 (hex) Cambridge Industries Group (CIG) +000B40 (base 16) Cambridge Industries Group (CIG) + 2560 Junction Avenue + San Jose 95134 + US + +00-0B-44 (hex) Concord IDea Corp. +000B44 (base 16) Concord IDea Corp. + 4118 14th Ave., Unit 4 + Markham Ontario L3R 0J3 + CA + +00-0B-42 (hex) commax Co., Ltd. +000B42 (base 16) commax Co., Ltd. + 513-11, Sangdaewon-Dong, Jungwon-Ku + Sungnam-City Kyunggi-Do 462-120 + KR + +00-0B-47 (hex) Advanced Energy +000B47 (base 16) Advanced Energy + 1625 Sharp Point Drive + Fort Collins Colorado 80525 + US + +00-0B-81 (hex) Kaparel Corporation +000B81 (base 16) Kaparel Corporation + 97 Randall Drive + Waterloo Ontario N2V-1C5 + CA + +00-0B-82 (hex) Grandstream Networks, Inc. +000B82 (base 16) Grandstream Networks, Inc. + 1297 Beacon Street + Brookline MA 02446 + US + +00-0B-6E (hex) Neff Instrument Corp. +000B6E (base 16) Neff Instrument Corp. + 700 South Myrtle Ave. + Monrovia CA 91016 + US + +00-0B-72 (hex) Lawo AG +000B72 (base 16) Lawo AG + Am Oberwald 8 + Rastatt Baden-Württemberg 76437 + DE + +00-0B-31 (hex) Yantai ZhiYang Scientific and technology industry CO., LTD +000B31 (base 16) Yantai ZhiYang Scientific and technology industry CO., LTD + 5F-4, NO. 64, Gong-Jian Rd. + Hsi-Chih City Taipei County 221 + CN + +00-0B-2F (hex) bplan GmbH +000B2F (base 16) bplan GmbH + Industriestrasse 23b + Steinbach Hessen 61449 + DE + +00-0B-3D (hex) CONTAL OK Ltd. +000B3D (base 16) CONTAL OK Ltd. + Frana Mraza 2/289 + Zilina 01124 + SK + +00-0B-4E (hex) VertexRSI, General Dynamics SatCOM Technologies, Inc. +000B4E (base 16) VertexRSI, General Dynamics SatCOM Technologies, Inc. + 3750 W. Loop 281 + Longview TX 75604 + US + +00-0B-4D (hex) Emuzed +000B4D (base 16) Emuzed + 46750 Lakeview Boulevard + Fremont California 94538 + US + +00-0B-24 (hex) AirLogic +000B24 (base 16) AirLogic + 807-1, Bundangtechnopark D, 151, + Sungnam-Si Kyungki-Do 463-760 + KR + +00-0B-78 (hex) TAIFATECH INC. +000B78 (base 16) TAIFATECH INC. + 8F-1 No.289, Sec.2 Guangfu Rd. + Hsinchu 300 + TW + +00-0B-6C (hex) Sychip Inc. +000B6C (base 16) Sychip Inc. + 2805 N. Dallas Parkway Suite 400 + Plano Texas 75093 + US + +00-91-D6 (hex) Crystal Group, Inc. +0091D6 (base 16) Crystal Group, Inc. + 850 Kacena Rd. + Hiawatha IA 52233 + US + +00-0B-5A (hex) HyperEdge +000B5A (base 16) HyperEdge + 333 Pierce Road Suite #200 + Itasca IL 60143 + US + +00-0B-0F (hex) Bosch Rexroth +000B0F (base 16) Bosch Rexroth + Luchthavenweg 20 + Eindhoven Noord Brabant NL5657 EB + NL + +00-0B-0C (hex) Agile Systems Inc. +000B0C (base 16) Agile Systems Inc. + 575 Kumpf Drive + Waterloo Ontario N2V 1K3 + CA + +00-0B-0A (hex) dBm Optics +000B0A (base 16) dBm Optics + 300 S. Public Road + Lafayette Colorado 80026 + US + +00-0B-09 (hex) Ifoundry Systems Singapore +000B09 (base 16) Ifoundry Systems Singapore + Block 1, Unit 101B, Innovation Centre, 1 + 637722 + SG + +00-0B-1D (hex) LayerZero Power Systems, Inc. +000B1D (base 16) LayerZero Power Systems, Inc. + 3559 Townley Road + Shaker Heights OH 44122-5156 + US + +00-0B-19 (hex) Vernier Networks, Inc. +000B19 (base 16) Vernier Networks, Inc. + 490 E. Middlefield Road + Mountain View CA 94043 + US + +00-0B-16 (hex) Communication Machinery Corporation +000B16 (base 16) Communication Machinery Corporation + 402 E. Gutierrez St. + Santa Barbara CA 93101 + US + +00-0B-12 (hex) NURI Telecom Co., Ltd. +000B12 (base 16) NURI Telecom Co., Ltd. + B-10F Woolim Lion's Valley 371-28 + Geuncheon-gu Seoul 153-803 + KR + +00-0A-C5 (hex) Color Kinetics +000AC5 (base 16) Color Kinetics + 10 Milk Street + Boston Masachusetts 02108 + US + +00-0A-BD (hex) Rupprecht & Patashnick Co. +000ABD (base 16) Rupprecht & Patashnick Co. + 25 Corporate Circle + Albany NY 12203 + US + +00-0A-CB (hex) XPAK MSA Group +000ACB (base 16) XPAK MSA Group + Care of: Molex Fiber Optics + Downers Grove IL 60515 + US + +00-0A-D5 (hex) Brainchild Electronic Co., Ltd. +000AD5 (base 16) Brainchild Electronic Co., Ltd. + No.209, Chung Yang Rd., + Taipei 115 + TW + +00-0A-D6 (hex) BeamReach Networks +000AD6 (base 16) BeamReach Networks + 755 North Mathilda Ave + Sunnyvale California 94086 + US + +00-0A-FE (hex) NovaPal Ltd +000AFE (base 16) NovaPal Ltd + Floor 6 + Ealing London W5 2ST + GB + +00-0A-FD (hex) Kentec Electronics +000AFD (base 16) Kentec Electronics + 620 Allendale Rd + King of Prussia PA 19406 + US + +00-0A-EF (hex) OTRUM ASA +000AEF (base 16) OTRUM ASA + Brattekleiv + Færvik N-4818 + NO + +00-0A-E5 (hex) ScottCare Corporation +000AE5 (base 16) ScottCare Corporation + 4791 West 150th Street + Cleveland Ohio 44135 + US + +00-0A-B0 (hex) LOYTEC electronics GmbH +000AB0 (base 16) LOYTEC electronics GmbH + Stolzenthalergasse 24/3 + Vienna 1080 + AT + +00-0A-B5 (hex) Digital Electronic Network +000AB5 (base 16) Digital Electronic Network + 8 rue du sacré coeur + Saint Laurent sur Sevre Vendee 85290 + FR + +00-0A-D2 (hex) JEPICO Corporation +000AD2 (base 16) JEPICO Corporation + Nishi-shinjyuku2-7-1 + Shinjyuku-ku Tokyo 163-0729 + JP + +00-0A-98 (hex) M+F Gwinner GmbH & Co +000A98 (base 16) M+F Gwinner GmbH & Co + Weidenbaumsweg 91 a + Hamburg 21029 + DE + +00-0A-9B (hex) TB Group Inc +000A9B (base 16) TB Group Inc + 4F NREG Hongo 3-chome Bldg., 3-26-6, Hngo, Bunkyo-ku, + Tokyo 113-003 + JP + +00-0A-6C (hex) Walchem Corporation +000A6C (base 16) Walchem Corporation + 5 Boynton Road + Holliston MA 01746 + US + +00-0A-5F (hex) almedio inc. +000A5F (base 16) almedio inc. + 32-13, sakae-cho 2 chome + higashimurayama-shi tokyo 189-0013 + JP + +00-0A-6B (hex) Tadiran Telecom Business Systems LTD +000A6B (base 16) Tadiran Telecom Business Systems LTD + 18 Hasivim St. + Petach Tikva 49105 + IL + +00-0A-61 (hex) Cellinx Systems Inc. +000A61 (base 16) Cellinx Systems Inc. + 408 Woosung Character199 officetel + Seoul 135-856 + KR + +00-0A-78 (hex) OLITEC +000A78 (base 16) OLITEC + B.P. 592 + NANCY cedex 54009 + FR + +00-0A-A9 (hex) Brooks Automation GmbH +000AA9 (base 16) Brooks Automation GmbH + Goeschwitzer Strasse 25 + Jena Thuringia 07745 + DE + +00-0A-A5 (hex) MAXLINK INDUSTRIES LIMITED +000AA5 (base 16) MAXLINK INDUSTRIES LIMITED + 29A SHENZHEN SPECIAL ZONE + SHENZHEN GUANGDONG 518009 + CN + +00-0A-A2 (hex) SYSTEK INC. +000AA2 (base 16) SYSTEK INC. + JCOM BUILDING 402, OJEON-DONG 124-4, + UIWANG-SI GYUNGGI-DO 437-070 + KR + +00-0A-5B (hex) Power-One as +000A5B (base 16) Power-One as + P.O. Box 1543 + Drammen 3007 + NO + +00-0A-55 (hex) MARKEM Corporation +000A55 (base 16) MARKEM Corporation + 150 Congress Street + Keene NH 03431 + US + +00-0A-73 (hex) Scientific Atlanta +000A73 (base 16) Scientific Atlanta + 5030 Sugarloaf Parkway + Lawrenceville Ga 30042 + US + +00-0A-69 (hex) SUNNY bell Technology Co., Ltd. +000A69 (base 16) SUNNY bell Technology Co., Ltd. + #502 BUWON B/D 107-45 BANPO-DONG + SEOUL 137-806 + KR + +00-0A-84 (hex) Rainsun Enterprise Co., Ltd. +000A84 (base 16) Rainsun Enterprise Co., Ltd. + No.14-3 , Lane 235, Ho-Chen Road + ShinDian City TAIPEI 231 + TW + +00-0A-7E (hex) The Advantage Group +000A7E (base 16) The Advantage Group + 1610 Des Peres Road + St. Louis MO 63131 + US + +00-0A-4C (hex) Molecular Devices Corporation +000A4C (base 16) Molecular Devices Corporation + 1311 Orleans Drive + Sunnyvale CA 94089 + US + +00-0A-4D (hex) Noritz Corporation +000A4D (base 16) Noritz Corporation + 5 Minami-Futami, + Akashi-shi Hyogo 674-0093 + JP + +00-0A-91 (hex) HemoCue AB +000A91 (base 16) HemoCue AB + Box 1204 + Ängelholm Skåne län 26223 + SE + +00-09-F2 (hex) Cohu, Inc., Electronics Division +0009F2 (base 16) Cohu, Inc., Electronics Division + 3912 Calle Fortunada + San Diego CA 92123 + US + +00-09-E9 (hex) Cisco Systems, Inc +0009E9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-DC (hex) Galaxis Technology AG +0009DC (base 16) Galaxis Technology AG + Steinmetzstraße 7 + Lübeck Schleswig-Holstein 23556 + DE + +00-0A-3A (hex) J-THREE INTERNATIONAL Holding Co., Ltd. +000A3A (base 16) J-THREE INTERNATIONAL Holding Co., Ltd. + No. 1, Yu-3 Rd., Youth Industrial Park + Yang-mei, Taoyuan Hsien 326 + TW + +00-0A-47 (hex) Allied Vision Technologies +000A47 (base 16) Allied Vision Technologies + Taschenweg 2a + Stadtroda Thüringen 07646 + DE + +00-0A-3C (hex) Enerpoint Ltd. +000A3C (base 16) Enerpoint Ltd. + Kaivopuistontie 33 + Rauma 26100 + FI + +00-0A-44 (hex) Avery Dennison Deutschland GmbH +000A44 (base 16) Avery Dennison Deutschland GmbH + Ohmstraße 3 + Eching 85386 + DE + +00-09-F8 (hex) UNIMO TECHNOLOGY CO., LTD. +0009F8 (base 16) UNIMO TECHNOLOGY CO., LTD. + BANGBAE DONG 479-12 + SEOUL 137-820 + KR + +00-09-FF (hex) X.net 2000 GmbH +0009FF (base 16) X.net 2000 GmbH + Koenigsberger Str. 2c + Reinheim 64354 + DE + +00-0A-03 (hex) ENDESA SERVICIOS, S.L. +000A03 (base 16) ENDESA SERVICIOS, S.L. + AVGDA PARAL.LEL, 51 + BARCELONA 08004 + ES + +00-09-FE (hex) Daisy Technologies, Inc. +0009FE (base 16) Daisy Technologies, Inc. + 1209 Orange Street + City of Wilmington DE 19801 + US + +00-0A-28 (hex) Motorola +000A28 (base 16) Motorola + 600 N. US Hwy 45 + Libertyville IL 60048 + US + +00-0A-29 (hex) Pan Dacom Networking AG +000A29 (base 16) Pan Dacom Networking AG + Dreieich Plaza 1B + Dreieich Hessen D-63303 + DE + +00-09-EB (hex) HuMANDATA LTD. +0009EB (base 16) HuMANDATA LTD. + 1-2-10 + Ibaraki Osaka 567-0034 + JP + +00-09-E8 (hex) Cisco Systems, Inc +0009E8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-ED (hex) CipherOptics +0009ED (base 16) CipherOptics + 701 Corporate Center Drive + Raleigh North Carolina 27607 + US + +00-0A-40 (hex) Crown Audio -- Harmanm International +000A40 (base 16) Crown Audio -- Harmanm International + 1718 W. Mishawaka Rd + Elkhart IN 46517 + US + +00-0A-26 (hex) CEIA S.p.A. +000A26 (base 16) CEIA S.p.A. + Zona Industriale di Viciomaggio 54 + Arezzo AR 52040 + IT + +00-0A-1D (hex) Optical Communications Products Inc. +000A1D (base 16) Optical Communications Products Inc. + 20961 Knapp St. + Chatsworth CA 91311 + US + +00-0A-16 (hex) Lassen Research +000A16 (base 16) Lassen Research + 31695 Forward Road + Manton CA 96059 + US + +00-0A-18 (hex) Vichel Inc. +000A18 (base 16) Vichel Inc. + 3F Jang Bldg. 92-6 Yangjae-dong, Secho-g + Seoul 137-130 + KR + +00-0A-06 (hex) Teledex LLC +000A06 (base 16) Teledex LLC + 6311 San Ignacio Avenue + San Jose CA 95119 + US + +00-09-A9 (hex) Ikanos Communications +0009A9 (base 16) Ikanos Communications + 47709 Fremont Blvd + Fremont CA 94538 + US + +00-09-9F (hex) VIDEX INC. +00099F (base 16) VIDEX INC. + 1105 NE Circle Blvd + Corvallis OR 97330 + US + +00-09-A2 (hex) Interface Co., Ltd. +0009A2 (base 16) Interface Co., Ltd. + 2-5-12-201 Kyonancho + Musashino-city Tokyo 180-0023 + JP + +00-09-A1 (hex) Telewise Communications, Inc. +0009A1 (base 16) Telewise Communications, Inc. + 2050 Ringwood Avenue + San Jose CA 95131 + US + +00-09-7D (hex) SecWell Networks Oy +00097D (base 16) SecWell Networks Oy + P.O.BOX 174 + Tampere 33101 + FI + +00-09-76 (hex) Datasoft ISDN Systems GmbH +000976 (base 16) Datasoft ISDN Systems GmbH + Schillerplatz 3 + St. Poelten Lower Austria 3100 + AT + +00-09-C6 (hex) Visionics Corporation +0009C6 (base 16) Visionics Corporation + 5600 Rowland Road + Minnetonka MN 55343 + US + +00-09-D1 (hex) SERANOA NETWORKS INC +0009D1 (base 16) SERANOA NETWORKS INC + CONCORD OFFICE CENTER + CONCORD MA 01742 + US + +00-09-CE (hex) SpaceBridge Semiconductor Corp. +0009CE (base 16) SpaceBridge Semiconductor Corp. + 115 rue Champlain + Hull Quebec J8X3R1 + CA + +00-09-B8 (hex) Entise Systems +0009B8 (base 16) Entise Systems + 10095 Judy Avenue + Cupertino CA 95014 + US + +00-09-AF (hex) e-generis +0009AF (base 16) e-generis + 13 rue du chene germain + cesson sevigne 35510 + FR + +00-09-AD (hex) HYUNDAI SYSCOMM, INC. +0009AD (base 16) HYUNDAI SYSCOMM, INC. + SAN 136-1, AMI-RI, BUBAL-EUB + ICHON KYOUNGKI-DO 467-701 + KR + +00-09-BD (hex) Epygi Technologies, Ltd. +0009BD (base 16) Epygi Technologies, Ltd. + 5040 Addison Circle + Addison Texas 75001 + US + +00-09-C2 (hex) Onity, Inc. +0009C2 (base 16) Onity, Inc. + 2232 Northmont Parkway + Duluth GA 30096 + US + +00-09-C3 (hex) NETAS +0009C3 (base 16) NETAS + Alemdag Cad. No 171 + ISTANBUL 81244 + TR + +00-09-B5 (hex) 3J Tech. Co., Ltd. +0009B5 (base 16) 3J Tech. Co., Ltd. + 342 Fushing N. Rd., 2F, Taipei, Taiwan + Taipei 104 + TW + +00-09-82 (hex) Loewe Opta GmbH +000982 (base 16) Loewe Opta GmbH + Industriestrasse 11 + Kronach 96317 + DE + +00-09-83 (hex) GlobalTop Technology, Inc. +000983 (base 16) GlobalTop Technology, Inc. + #16 Nan-Ke 9th Road + Tainan 741 + TW + +00-09-DD (hex) Mavin Technology Inc. +0009DD (base 16) Mavin Technology Inc. + Room 305, Bldg. 52 No. 195-28 + Chutung, Hsinchu 310 + TW + +00-09-7A (hex) Louis Design Labs. +00097A (base 16) Louis Design Labs. + 2F,NO 4, Lane 497, Chung-Cheng Rd.,Hsin- + Hsin-Tien Taipei Hsien 231 + TW + +00-09-6B (hex) IBM Corp +00096B (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-09-6D (hex) Powernet Technologies Corp. +00096D (base 16) Powernet Technologies Corp. + 371-51, Gasan-Dong Kumchon-Gu, + Seoul 153-803 + KR + +00-09-64 (hex) Hi-Techniques, Inc. +000964 (base 16) Hi-Techniques, Inc. + 2515 Frazier Ave. + Madison WI 53713-1505 + US + +00-09-65 (hex) HyunJu Computer Co., Ltd. +000965 (base 16) HyunJu Computer Co., Ltd. + 222-22, Hyunju B/D, Guro 3 Dong, Gurogu + Seoul 152-848 + KR + +00-09-39 (hex) ShibaSoku Co.,Ltd. +000939 (base 16) ShibaSoku Co.,Ltd. + 6-8 Shinbashi 4-chome + Minato-ku Tokyo 105-0004 + JP + +00-09-33 (hex) Ophit Co.Ltd. +000933 (base 16) Ophit Co.Ltd. + 3F. Suntechnovil, 5-27 Mangpo-Dong , + Kyungki-Do 137-070 + KR + +00-09-32 (hex) Omnilux +000932 (base 16) Omnilux + 130 W. Union St. + Pasadena CA 91103 + US + +00-09-1C (hex) CacheVision, Inc +00091C (base 16) CacheVision, Inc + 1990 Concourse Drive + San Jose CA 95131 + US + +00-09-1A (hex) Macat Optics & Electronics Co., Ltd. +00091A (base 16) Macat Optics & Electronics Co., Ltd. + 15/F., Macat Center, No. 63 Macat Road + Huizhou Guangdong 516001 + CN + +00-09-1B (hex) Digital Generation Inc. +00091B (base 16) Digital Generation Inc. + 5F, Ho-Sam B/D, #30-3, Bongchun6-Dong + Kwanak-Ku, Seoul 151-089 + KR + +00-09-29 (hex) Sanyo Industries (UK) Limited +000929 (base 16) Sanyo Industries (UK) Limited + School Road + Lowestoft Suffolk NR33 9NA + GB + +00-09-28 (hex) Telecore +000928 (base 16) Telecore + 1800 North Glenville + Richardson TX 75081 + US + +00-09-2E (hex) B&Tech System Inc. +00092E (base 16) B&Tech System Inc. + #601, Seo-Jung B/D, 830-24, Youksam-Dong + Seoul + KR + +00-09-6F (hex) Beijing Zhongqing Elegant Tech. Corp.,Limited +00096F (base 16) Beijing Zhongqing Elegant Tech. Corp.,Limited + Rm.508, A-Building, Shangdi Digital Scie + Beijing 100084 + CN + +00-09-5E (hex) Masstech Group Inc. +00095E (base 16) Masstech Group Inc. + 2 East Beaver Creek Rd. + Richmond Hill Ontario L4B 2N3 + CA + +00-09-4F (hex) elmegt GmbH & Co. KG +00094F (base 16) elmegt GmbH & Co. KG + Kommunikationstechnik + Peine Niedersachsen D-31228 + DE + +00-09-43 (hex) Cisco Systems, Inc +000943 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-02 (hex) Redline Communications Inc. +000902 (base 16) Redline Communications Inc. + 302 Town Centre Blvd + Markham ON L3R 0E8 + CA + +00-08-FA (hex) KEB Automation KG +0008FA (base 16) KEB Automation KG + Südstraße 38 + Barntrup NRW D-32683 + DE + +00-09-59 (hex) Sitecsoft +000959 (base 16) Sitecsoft + 7th Gugu BD. 145-18 Samsung-Dong + Seoul Seoul 135-090 + KR + +00-09-57 (hex) Supercaller, Inc. +000957 (base 16) Supercaller, Inc. + 101 Saginaw Drive + Redwood City CA 94063 + US + +00-08-D2 (hex) ZOOM Networks Inc. +0008D2 (base 16) ZOOM Networks Inc. + 13F,XinLuDao Building,No.1175,Nanshan Ro + Shen Zhen GuangDong Province 518052 + US + +00-08-C5 (hex) Liontech Co., Ltd. +0008C5 (base 16) Liontech Co., Ltd. + 306, Wooyoung Techno Center, 273-15, + Seoul 133-831 + KR + +00-08-AC (hex) Eltromat GmbH +0008AC (base 16) Eltromat GmbH + Herforder Straße 249-251 + Leopoldshöhe Nordrhein-Westfalen 33818 + DE + +00-08-AA (hex) KARAM +0008AA (base 16) KARAM + 98-3, Hankangro 2-KA, Yongsan + Seoul 140-012 + KR + +00-08-AB (hex) EnerLinx.com, Inc. +0008AB (base 16) EnerLinx.com, Inc. + 3965 South Woodhill Lane + New Berlin WI 53151 + US + +00-08-AD (hex) Toyo-Linx Co., Ltd. +0008AD (base 16) Toyo-Linx Co., Ltd. + Hirakawa-Cho, Chiyada-ku, + Tokyo 102-0093 + JP + +00-08-F2 (hex) C&S Technology +0008F2 (base 16) C&S Technology + C&S Venture Bldg., NonHyun-Dong, + SEOUL 135-829 + KR + +00-08-EA (hex) Motion Control Engineering, Inc +0008EA (base 16) Motion Control Engineering, Inc + 11380 White Rock Road + Rancho Cordova CA 95742 + US + +00-08-ED (hex) ST&T Instrument Corp. +0008ED (base 16) ST&T Instrument Corp. + 16 Shing-Gong Road, Yung-Kung Industrial + Yung-Kung Tainan 710 + TW + +00-08-88 (hex) OULLIM Information Technology Inc,. +000888 (base 16) OULLIM Information Technology Inc,. + a-10th FL,. IT Venture Tower, + Seoul 138-803 + KR + +00-08-85 (hex) EMS Dr. Thomas Wünsche +000885 (base 16) EMS Dr. Thomas Wünsche + Sonnenhang 3 + + DE + +00-08-72 (hex) Sorenson Communications +000872 (base 16) Sorenson Communications + 4192 South Riverboat Road + Salt Lake City UT 84123 + US + +00-08-9A (hex) Alcatel Microelectronics +00089A (base 16) Alcatel Microelectronics + Excelsiorlaan 44-46 + B-1930 Zavantem + BE + +00-08-A1 (hex) CNet Technology Inc. +0008A1 (base 16) CNet Technology Inc. + No.15, Park Avenue II, Science-Based Ind + Hsin-Chu 300 + TW + +00-08-93 (hex) LE INFORMATION COMMUNICATION INC. +000893 (base 16) LE INFORMATION COMMUNICATION INC. + Rm, 4501, DA-Dong Chungang Circulation C + Seoul 152-721 + KR + +00-08-B0 (hex) BKtel communications GmbH +0008B0 (base 16) BKtel communications GmbH + Benzstraße 4 + 41836 Hückelhoven-Baal NRW 41836 + DE + +00-08-CA (hex) TwinHan Technology Co.,Ltd +0008CA (base 16) TwinHan Technology Co.,Ltd + 13F-6,No 79,Sec 1,Hsin Tai Wu RD.,Hsi-Ch + Taipei Hsien 221 + TW + +00-08-B6 (hex) RouteFree, Inc. +0008B6 (base 16) RouteFree, Inc. + 3400 Hillview Ave., Building 5 + Palo Alto CA 94304 + US + +00-08-D8 (hex) Dowkey Microwave +0008D8 (base 16) Dowkey Microwave + 4822 McGrath Street + Ventura Ca 93003 + US + +00-08-DF (hex) Alistel Inc. +0008DF (base 16) Alistel Inc. + Midori Bldg. 2F + Yokohama Kanagawa 222-0001 + JP + +00-08-DB (hex) Corrigent Systems +0008DB (base 16) Corrigent Systems + 126 Yigal Alon + Tel Aviv 67443 + IL + +00-08-7C (hex) Cisco Systems, Inc +00087C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-08-79 (hex) CEM Corporation +000879 (base 16) CEM Corporation + P.O. Box 200 + Matthews NC 28106 + US + +00-08-7D (hex) Cisco Systems, Inc +00087D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-08-75 (hex) Acorp Electronics Corp. +000875 (base 16) Acorp Electronics Corp. + 8F, No.111-6,Shing Teh Rd, + San Chung Taipei Hsien 241 + TW + +00-08-16 (hex) Bluelon ApS +000816 (base 16) Bluelon ApS + Nattergalevej 6 + + DK + +00-08-11 (hex) VOIX Corporation +000811 (base 16) VOIX Corporation + 1991-3 4th Floor Top's Venture Tower + Seoul 138-090 + KR + +00-08-06 (hex) Raonet Systems, Inc. +000806 (base 16) Raonet Systems, Inc. + West Wing 14F, IT Venture Tower 78 + Seoul 138-803 + KR + +00-08-6F (hex) Resources Computer Network Ltd. +00086F (base 16) Resources Computer Network Ltd. + Rm 324, Tech Centre, 72 Tat Chee Ave., + + HK + +00-08-67 (hex) Uptime Devices +000867 (base 16) Uptime Devices + 11724 Dunfries Lane + Austin Texas 78754 + US + +00-07-F8 (hex) ITDevices, Inc. +0007F8 (base 16) ITDevices, Inc. + 606 110th Ave. NE + Bellevue WA 98004 + US + +00-07-F3 (hex) Thinkengine Networks +0007F3 (base 16) Thinkengine Networks + 100 Nickerson Road + Marlborough MA 01752 + US + +00-08-1C (hex) @pos.com +00081C (base 16) @pos.com + 3051 North First Street + San Jose CA 95134 + US + +00-08-1E (hex) Repeatit AB +00081E (base 16) Repeatit AB + Farogatan 7 + + SE + +00-08-56 (hex) Gamatronic Electronic Industries Ltd. +000856 (base 16) Gamatronic Electronic Industries Ltd. + Hartum Street 14 + + IL + +00-08-53 (hex) Schleicher GmbH & Co. Relaiswerke KG +000853 (base 16) Schleicher GmbH & Co. Relaiswerke KG + Pichelswerderstrasse 3-5 + + DE + +00-08-26 (hex) Colorado Med Tech +000826 (base 16) Colorado Med Tech + 6175 Longbow Dr. + Boulder CO 80301 + US + +00-08-5E (hex) PCO AG +00085E (base 16) PCO AG + Donaupark 11 + + DE + +00-07-9A (hex) Verint Systems Inc +00079A (base 16) Verint Systems Inc + 1800 Berlier, Suite 440 + Laval, Quebec H7L 4S4 + CA + +00-07-74 (hex) GuangZhou Thinker Technology Co. Ltd. +000774 (base 16) GuangZhou Thinker Technology Co. Ltd. + 109 Zhongshan Ave., Tianhe District + 510630 + CN + +00-07-98 (hex) Selea SRL +000798 (base 16) Selea SRL + Via A. Moro No. 69 + + IT + +00-07-91 (hex) International Data Communications, Inc. +000791 (base 16) International Data Communications, Inc. + 47873 Fremont Blvd. + Fremont CA 04538 + US + +00-07-EE (hex) telco Informationssysteme GmbH +0007EE (base 16) telco Informationssysteme GmbH + Schulstrasse 38 + + DE + +00-07-E2 (hex) Bitworks, Inc. +0007E2 (base 16) Bitworks, Inc. + #1 Bitworks Way + Prairie Grove AR 72753 + US + +00-07-E6 (hex) edgeflow Canada Inc. +0007E6 (base 16) edgeflow Canada Inc. + 329 March Road + K2K 2E1 + CA + +00-07-E5 (hex) Coup Corporation +0007E5 (base 16) Coup Corporation + 1-24-4 Marusen 2nd Bld. 4F, + Tokyo + JP + +00-07-DE (hex) eCopilt AB +0007DE (base 16) eCopilt AB + Veddestavagen 24 + + SE + +00-07-C8 (hex) Brain21, Inc. +0007C8 (base 16) Brain21, Inc. + 19F Mesa B/D, 204 Hoihyun-Dong + Seoul 100-051 + KR + +00-07-C5 (hex) Gcom, Inc. +0007C5 (base 16) Gcom, Inc. + 1800 Woodfield Dr. + Savoy IL 61874 + US + +00-07-C1 (hex) Overture Networks, Inc. +0007C1 (base 16) Overture Networks, Inc. + 637 Davis Drive + Morrisville NC 227560 + US + +00-07-A7 (hex) A-Z Inc. +0007A7 (base 16) A-Z Inc. + 5-5-17 Kamikoushien + + JP + +00-07-A6 (hex) Leviton Manufacturing Co., Inc. +0007A6 (base 16) Leviton Manufacturing Co., Inc. + 4330 Michoud Blvd + New Orleans LA 70129 + US + +00-07-A3 (hex) Ositis Software, Inc. +0007A3 (base 16) Ositis Software, Inc. + 6120 Stoneridge Mall Road + Pleasanton CA 94588 + US + +00-07-C2 (hex) Netsys Telecom +0007C2 (base 16) Netsys Telecom + 4F, KyungNam B/D, 830-48, YeokSam-Dong + Seoul 135-080 + KR + +00-07-8F (hex) Emkay Innovative Products +00078F (base 16) Emkay Innovative Products + 53, Pao Hsing Rd., Hsintien City + Taipei + TW + +00-07-82 (hex) Oracle Corporation +000782 (base 16) Oracle Corporation + 500 Oracle Parkway + Redwood Shores CA 94065 + US + +00-07-AE (hex) Britestream Networks, Inc. +0007AE (base 16) Britestream Networks, Inc. + 12401 Research Blvd. + Austin TX 78759 + US + +00-07-B1 (hex) Equator Technologies +0007B1 (base 16) Equator Technologies + 1300 White Oaks Rd. + Campbell CA 95008 + US + +00-05-F9 (hex) TOA Corporation +0005F9 (base 16) TOA Corporation + 2-1 Takamatsu-cho, + Hyogo 665-0043 + JP + +00-07-CA (hex) Creatix Polymedia Ges Fur Kommunikaitonssysteme +0007CA (base 16) Creatix Polymedia Ges Fur Kommunikaitonssysteme + Heinrich-Barth-Straße 3 + + DE + +00-07-DF (hex) Vbrick Systems Inc. +0007DF (base 16) Vbrick Systems Inc. + 12 Beaumont Road + Wallingford CT 06492 + US + +00-07-44 (hex) Unico, Inc. +000744 (base 16) Unico, Inc. + 3725 Nicholson Rd. + Franksville WI 53126 + US + +00-07-49 (hex) CENiX Inc. +000749 (base 16) CENiX Inc. + 5141 California Avenue + Irvine CA 92612 + US + +00-07-3D (hex) Nanjing Postel Telecommunications Co., Ltd. +00073D (base 16) Nanjing Postel Telecommunications Co., Ltd. + No. 187, ShengZhou Road, + 210004 + CN + +00-07-39 (hex) Scotty Group Austria Gmbh +000739 (base 16) Scotty Group Austria Gmbh + Teslastrasse 4 + 8074 Grambach 8074 + AT + +00-07-4E (hex) IPFRONT Inc +00074E (base 16) IPFRONT Inc + 4F ALT Bldg., + Tokyo 101-0021 + JP + +00-07-52 (hex) Rhythm Watch Co., Ltd. +000752 (base 16) Rhythm Watch Co., Ltd. + 321 Shinshukushinden, Showa-Machi, + 344-0196 + JP + +00-07-4F (hex) Cisco Systems, Inc +00074F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-07-43 (hex) Chelsio Communications +000743 (base 16) Chelsio Communications + 170 S. Whismon Rd. + Mountain View CA 94041-1512 + US + +00-07-47 (hex) Mecalc +000747 (base 16) Mecalc + PO Box 7958 + + ZA + +00-07-79 (hex) Sungil Telecom Co., Ltd. +000779 (base 16) Sungil Telecom Co., Ltd. + #321, Gongdan-Dong, + 730-030 + KR + +00-07-7E (hex) Elrest GmbH +00077E (base 16) Elrest GmbH + Leibnizstraße 10 + + DE + +00-07-78 (hex) GERSTEL GmbH & Co. KG +000778 (base 16) GERSTEL GmbH & Co. KG + Eberhard-Gerstel-Platz 1 + Mülheim an der Ruhr + DE + +00-07-6D (hex) Flexlight Networks +00076D (base 16) Flexlight Networks + 15 Atir Yeda St. + + IL + +00-07-30 (hex) Hutchison OPTEL Telecom Technology Co., Ltd. +000730 (base 16) Hutchison OPTEL Telecom Technology Co., Ltd. + No. 28 Xinwai Street + Beijing + CN + +00-07-22 (hex) The Nielsen Company +000722 (base 16) The Nielsen Company + 501 Brooker Creek Blvd. + Oldsmar FL 34677 + US + +00-07-60 (hex) TOMIS Information & Telecom Corp. +000760 (base 16) TOMIS Information & Telecom Corp. + Youngdeungpo telephone office - extensio + Seoul + KR + +00-07-35 (hex) Flarion Technologies, Inc. +000735 (base 16) Flarion Technologies, Inc. + 135 Route 202/206 South + Bedminster NJ 07921 + US + +00-07-5E (hex) Ametek Power Instruments +00075E (base 16) Ametek Power Instruments + 4050 NW 121 Avenue + Coral Springs FL 33065 + US + +00-07-1F (hex) European Systems Integration +00071F (base 16) European Systems Integration + 455 Promenade Des Anglas + + FR + +00-07-21 (hex) Formac Elektronik GmbH +000721 (base 16) Formac Elektronik GmbH + Dofstraße 33 + + DE + +00-07-86 (hex) Wireless Networks Inc. +000786 (base 16) Wireless Networks Inc. + #300, 3016 Fifth Ave. NE + T2A 6K4 + CA + +00-06-BC (hex) Macrolink, Inc. +0006BC (base 16) Macrolink, Inc. + 1500 N Kellogg Dr. + Anaheim CA 92807 + US + +00-06-C2 (hex) Smartmatic Corporation +0006C2 (base 16) Smartmatic Corporation + 6400 Congress Ave., Suite 1300 + Boca Raton FL 33487 + US + +00-06-54 (hex) Winpresa Building Automation Technologies GmbH +000654 (base 16) Winpresa Building Automation Technologies GmbH + Vivenotgasse 53/2 + + AT + +00-06-B4 (hex) Vorne Industries, Inc. +0006B4 (base 16) Vorne Industries, Inc. + 1445 Industrial Dr. + Itasca IL 60143-1849 + US + +00-06-AE (hex) Himachal Futuristic Communications Ltd +0006AE (base 16) Himachal Futuristic Communications Ltd + 8, Commercial Complex + New Dehli 110048 + IN + +00-06-E5 (hex) Fujian Newland Computer Ltd. Co. +0006E5 (base 16) Fujian Newland Computer Ltd. Co. + 141F Sunshine Holiday Hotel + Fuzhou Fujian 350005 + CN + +00-06-DE (hex) Flash Technology +0006DE (base 16) Flash Technology + P.O. Box 681509 + Franklin TN 37068 + US + +00-06-DF (hex) AIDONIC Corporation +0006DF (base 16) AIDONIC Corporation + 2-7-10 Otsuka, Bunkyo-ku, + Tokyo, 112-0012 + JP + +00-06-DD (hex) AT & T Laboratories - Cambridge Ltd +0006DD (base 16) AT & T Laboratories - Cambridge Ltd + 24a Trumpington Street + ENGLAND + GB + +00-06-F0 (hex) Digeo, Inc. +0006F0 (base 16) Digeo, Inc. + 8815 122nd Ave., NE + Kirkland WA 98033 + US + +00-07-00 (hex) Zettamedia Korea +000700 (base 16) Zettamedia Korea + Suite 1008, Kumkang Venturetel, 1108 + Kyounggido, + KR + +00-06-C5 (hex) INNOVI Technologies Limited +0006C5 (base 16) INNOVI Technologies Limited + 31st Floor, China Online Centre + Wanchai + HK + +00-06-C6 (hex) lesswire AG +0006C6 (base 16) lesswire AG + Im Technologiepark 25 + + DE + +00-06-B7 (hex) TELEM GmbH +0006B7 (base 16) TELEM GmbH + Lise-Meitner-Allee 31 + + DE + +00-06-EF (hex) Maxxan Systems, Inc. +0006EF (base 16) Maxxan Systems, Inc. + 107 Bonaventura Drive + San Jose CA 95134 + US + +00-06-E9 (hex) Intime Corp. +0006E9 (base 16) Intime Corp. + 324-4, Yangjae-dong, 2F + + KR + +00-06-EA (hex) ELZET80 Mikrocomputer GmbH&Co. KG +0006EA (base 16) ELZET80 Mikrocomputer GmbH&Co. KG + Theaterplatz 9 + + DE + +00-07-08 (hex) Bitrage Inc. +000708 (base 16) Bitrage Inc. + 100 Southpark Blvd. + Saint Augustine FL 32086 + US + +00-07-12 (hex) JAL Information Technology +000712 (base 16) JAL Information Technology + Network Solution Dep. JAL-Tamachi Bldg. + Tokyo + JP + +00-07-13 (hex) IP One, Inc. +000713 (base 16) IP One, Inc. + Sammi Bldg., 1004 + Seoul, 135-083 + KR + +00-07-07 (hex) Interalia Inc. +000707 (base 16) Interalia Inc. + 4110-79th Street N.W. + T3B 5C2 + CA + +00-06-F2 (hex) Platys Communications +0006F2 (base 16) Platys Communications + 3150A Coronado Dr. + Santa Clara CA 95054 + US + +00-06-FA (hex) IP SQUARE Co, Ltd. +0006FA (base 16) IP SQUARE Co, Ltd. + 1-9-11, Hakataekihigashi, + Fukuoka 812-0013 + JP + +00-07-03 (hex) CSEE Transport +000703 (base 16) CSEE Transport + 4, avenue du CANADA + + FR + +00-07-06 (hex) Sanritz Corporation +000706 (base 16) Sanritz Corporation + 1-30-13, Narimasu, + 175-0094 + JP + +00-06-D1 (hex) Tahoe Networks, Inc. +0006D1 (base 16) Tahoe Networks, Inc. + 3052 Orchard Drive + San Jose CA 95134 + US + +00-06-D4 (hex) Interactive Objects, Inc. +0006D4 (base 16) Interactive Objects, Inc. + 12600 SE 38th St. + Bellevue WA 98006 + US + +00-06-CA (hex) American Computer & Digital Components, Inc. (ACDC) +0006CA (base 16) American Computer & Digital Components, Inc. (ACDC) + 440 Cloverleaf Drive + Baldwin Park CA 91706 + US + +00-06-CE (hex) DATENO +0006CE (base 16) DATENO + Rue Amiral Berenger + + FR + +00-06-8E (hex) HID Corporation +00068E (base 16) HID Corporation + 9292 Jeronimo Road + Irvine CA 92618-1905 + US + +00-06-8A (hex) NeuronNet Co. Ltd. R&D Center +00068A (base 16) NeuronNet Co. Ltd. R&D Center + 735-34 Dasung Bldg., Yuksam-dong, + + KR + +00-06-85 (hex) NetNearU Corporation +000685 (base 16) NetNearU Corporation + 2908 Finfeather Road + Bryan TX 77801 + US + +00-06-50 (hex) Tiburon Networks, Inc. +000650 (base 16) Tiburon Networks, Inc. + 200 Minuteman Rd. + Andover MA 01810 + US + +00-06-5E (hex) Photuris, Inc. +00065E (base 16) Photuris, Inc. + 20 Corporate Place South + Piscataway NJ 08854 + US + +00-06-7F (hex) Digeo, Inc. +00067F (base 16) Digeo, Inc. + 8815 122nd Avenue NE + Kirkland WA 98033 + US + +00-06-83 (hex) Bravara Communications, Inc. +000683 (base 16) Bravara Communications, Inc. + 2650 East Bayshore Road + Palo Alto CA 94303 + US + +00-06-55 (hex) Yipee, Inc. +000655 (base 16) Yipee, Inc. + 555 International Drive + Williamsville NY 14221 + US + +00-06-76 (hex) Novra Technologies Inc. +000676 (base 16) Novra Technologies Inc. + 900-330 St. Mary Avenue + Winnipeg Manitoba R3C 3Z5 + CA + +00-06-64 (hex) Fostex Corporation +000664 (base 16) Fostex Corporation + 3-2-35, Musashino, Akishima, + Tokyo 196-0021 + JP + +00-06-7A (hex) JMP Systems +00067A (base 16) JMP Systems + 3rd Fl. Shinwha Bldg., + Seocho-ku Seoul, + KR + +00-06-73 (hex) TKH Security Solutions USA +000673 (base 16) TKH Security Solutions USA + 12920 Cloverleaf Center Drive + Germantown MD 20874 + US + +00-06-9B (hex) AVT Audio Video Technologies GmbH +00069B (base 16) AVT Audio Video Technologies GmbH + Rathsbergstraße 17 + + DE + +00-06-93 (hex) Flexus Computer Technology, Inc. +000693 (base 16) Flexus Computer Technology, Inc. + 8F-2, No.5, Alley22, Lane 513, + Taipei 114 + TW + +00-06-5D (hex) Heidelberg Web Systems +00065D (base 16) Heidelberg Web Systems + 121 Technology Dr. + Durham NH 03824 + US + +00-06-B0 (hex) Comtech EF Data Corp. +0006B0 (base 16) Comtech EF Data Corp. + 2114 W. 7th St. + Tempe AZ 85281 + US + +00-06-96 (hex) Advent Networks +000696 (base 16) Advent Networks + 9600 Great Hills Tr. + Austin TX 78759 + US + +00-05-D7 (hex) Vista Imaging, Inc. +0005D7 (base 16) Vista Imaging, Inc. + 521 Taylor Way + San Carlos CA 94070 + US + +00-05-DB (hex) PSI Nentec GmbH +0005DB (base 16) PSI Nentec GmbH + Greschbachstraße12 + Karlsruhe 76229 + DE + +00-05-DD (hex) Cisco Systems, Inc +0005DD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-06-28 (hex) Cisco Systems, Inc +000628 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-06-1D (hex) MIP Telecom, Inc. +00061D (base 16) MIP Telecom, Inc. + 3rd Floor, Sangil BLDG, + Seoul 151-069 + KR + +00-06-19 (hex) Connection Technology Systems +000619 (base 16) Connection Technology Systems + 18F-6, No. 79, Sec. 1, + Hsinchih Taipei, + TW + +00-06-40 (hex) White Rock Networks +000640 (base 16) White Rock Networks + Suite #900 + Dallas TX 75252 + US + +00-06-44 (hex) NextGen Business Solutions, Inc +000644 (base 16) NextGen Business Solutions, Inc + KKS Higashi-Sapporo Bldg.3-5-3-24, Higashi-Sapporo + Shiroishi-ku, Sapporo-city Hokkaido 003-0003 + JP + +00-06-45 (hex) Meisei Electric Co. Ltd. +000645 (base 16) Meisei Electric Co. Ltd. + 249-1, Moriya-kou, Moriya + 302-0192 + JP + +A0-6A-00 (hex) Verilink Corporation +A06A00 (base 16) Verilink Corporation + 127 Jetplex Circle + Madison AL 35758 + US + +00-05-F8 (hex) Real Time Access, Inc. +0005F8 (base 16) Real Time Access, Inc. + 455 N. Canyons Pkwy. + Livermore CA 94550 + US + +00-05-EB (hex) Blue Ridge Networks, Inc. +0005EB (base 16) Blue Ridge Networks, Inc. + 14120 Parke Long Court + Chantilly VA 20151 + US + +00-05-E8 (hex) TurboWave, Inc. +0005E8 (base 16) TurboWave, Inc. + 555 South State + Orem UT 84058 + US + +00-05-F6 (hex) Young Chang Co. Ltd. +0005F6 (base 16) Young Chang Co. Ltd. + 1432 Main Street + Waltham MA 02451 + US + +00-05-FC (hex) Schenck Pegasus Corp. +0005FC (base 16) Schenck Pegasus Corp. + 2890 John R Road + Troy MI 48083 + US + +00-06-3A (hex) Dura Micro, Inc. +00063A (base 16) Dura Micro, Inc. + 13580 Fifth Street + Chino CA 91710 + US + +00-06-32 (hex) Mesco Engineering GmbH +000632 (base 16) Mesco Engineering GmbH + Wiesentalstraße 74 + + DE + +00-06-34 (hex) GTE Airfone Inc. +000634 (base 16) GTE Airfone Inc. + 2809 Butterfield + Oakbrook IL 60522 + US + +00-06-0C (hex) Melco Industries, Inc. +00060C (base 16) Melco Industries, Inc. + 1575 W. 124th Ave. + Denver CO 80234 + US + +00-06-0E (hex) IGYS Systems, Inc. +00060E (base 16) IGYS Systems, Inc. + 7373 Lincoln Way + Garden Grove CA 92841 + US + +00-06-14 (hex) Prism Holdings +000614 (base 16) Prism Holdings + P.O. Box 901, + Gauteng + ZA + +00-06-08 (hex) At-Sky SAS +000608 (base 16) At-Sky SAS + ZI Athelia 3, Voi Atlas + + FR + +00-05-C3 (hex) Pacific Instruments, Inc. +0005C3 (base 16) Pacific Instruments, Inc. + 4080 Pike Lane + Concord CA 94520 + US + +00-05-B9 (hex) Airvana, Inc. +0005B9 (base 16) Airvana, Inc. + 25 Industrial Ave. + Chlemsford MA 01824 + US + +00-05-BC (hex) Resource Data Management Ltd +0005BC (base 16) Resource Data Management Ltd + 80 Johnstone Avenue, + Scotland G52 4NZ + GB + +00-05-BE (hex) Kongsberg Seatex AS +0005BE (base 16) Kongsberg Seatex AS + Pirsenteret + + NO + +00-05-BD (hex) ROAX BV +0005BD (base 16) ROAX BV + Sterrenbergweg 29 + + NL + +00-05-C1 (hex) A-Kyung Motion, Inc. +0005C1 (base 16) A-Kyung Motion, Inc. + 54-10, Munjung-Dong + Seoul + KR + +00-05-B4 (hex) Aceex Corporation +0005B4 (base 16) Aceex Corporation + 2F, No. 2, Alley 1, Sze-Wei Lane + 23138 + TW + +00-05-98 (hex) CRONOS S.r.l. +000598 (base 16) CRONOS S.r.l. + Via cavour 58/A + + IT + +00-05-B7 (hex) Arbor Technology Corp. +0005B7 (base 16) Arbor Technology Corp. + 5F, No. 738, Zhong Zheng Rd., + + TW + +00-05-9B (hex) Cisco Systems, Inc +00059B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-7E (hex) Eckelmann Steuerungstechnik GmbH +00057E (base 16) Eckelmann Steuerungstechnik GmbH + Berliner Strasse 161 + + DE + +00-05-80 (hex) FibroLAN Ltd. +000580 (base 16) FibroLAN Ltd. + 2 Hacarmel st., POB 544 + Yokneam Illit 20692 + IL + +00-05-82 (hex) ClearCube Technology +000582 (base 16) ClearCube Technology + 8834 Capital of Texas Hwy, + Austin TX 78759 + US + +00-05-D9 (hex) Techno Valley, Inc. +0005D9 (base 16) Techno Valley, Inc. + ASIC Venture Town 5F, + Seoul 135-072 + KR + +00-05-DC (hex) Cisco Systems, Inc +0005DC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-D0 (hex) Solinet Systems +0005D0 (base 16) Solinet Systems + 1200-180 Elgin St. + K2P 2K3 + CA + +00-05-9F (hex) Yotta Networks, Inc. +00059F (base 16) Yotta Networks, Inc. + 2201 Avenue K + Plano TX 75074 + US + +00-05-87 (hex) Locus, Incorporated +000587 (base 16) Locus, Incorporated + 5540 Research Park Drive + Madison WI 53711 + US + +00-05-90 (hex) Swissvoice Ltd. +000590 (base 16) Swissvoice Ltd. + Ziegelmattstrasse 1 + + CH + +00-05-95 (hex) Alesis Corporation +000595 (base 16) Alesis Corporation + 1633 26th Street + Santa Monica CA 90404 + US + +00-05-78 (hex) Private +000578 (base 16) Private + +00-05-72 (hex) Deonet Co., Ltd. +000572 (base 16) Deonet Co., Ltd. + #127-5 Jinyoung B/D 3th F, + Seoul + KR + +00-05-76 (hex) NSM Technology Ltd. +000576 (base 16) NSM Technology Ltd. + 22 Floor, Times Tower + Koloon + HK + +00-05-6A (hex) Heuft Systemtechnik GmbH +00056A (base 16) Heuft Systemtechnik GmbH + Brohltalstr 31-33 + Deutschland + DE + +00-05-68 (hex) Piltofish Networks AB +000568 (base 16) Piltofish Networks AB + Stora Badhusgatan 18-20 + + SE + +00-05-B6 (hex) INSYS Microelectronics GmbH +0005B6 (base 16) INSYS Microelectronics GmbH + Hermann-Köhl-Straße 22 + + DE + +00-05-55 (hex) Japan Cash Machine Co., Ltd. +000555 (base 16) Japan Cash Machine Co., Ltd. + No. 3-15, 2-chome, Nishiwaki, + 547-0035 + JP + +00-05-52 (hex) Xycotec Computer GmbH +000552 (base 16) Xycotec Computer GmbH + Karl-Heinz-Beckurts-Str. 4 + + DE + +00-05-4A (hex) Ario Data Networks, Inc. +00054A (base 16) Ario Data Networks, Inc. + 2890 Zanker Road, Suite 203 + San Jose CA 95134 + US + +00-05-48 (hex) Disco Corporation +000548 (base 16) Disco Corporation + 13-11 Omori-Kita 2-chome + Ota-ku Tokyo 143-8580 + JP + +00-04-F7 (hex) Omega Band, Inc. +0004F7 (base 16) Omega Band, Inc. + 9020-I Capital of Texas Hghwy N + Austin TX 78759 + US + +00-04-EE (hex) Lincoln Electric Company +0004EE (base 16) Lincoln Electric Company + 22801 St. Clair Avenue + Cleveland OH 44117-1199 + US + +00-04-F0 (hex) International Computers, Ltd +0004F0 (base 16) International Computers, Ltd + 1 Wenlock Way + UK + GB + +00-05-27 (hex) SJ Tek Co. Ltd +000527 (base 16) SJ Tek Co. Ltd + Ho gae Dong 976-5, Dong An Ku, + + KR + +00-05-29 (hex) Shanghai Broadan Communication Technology Co., Ltd +000529 (base 16) Shanghai Broadan Communication Technology Co., Ltd + 15F, Suntime International Mansion + 200122 + CN + +00-05-2C (hex) Supreme Magic Corporation +00052C (base 16) Supreme Magic Corporation + Sun Towers Center Bldg., 13F + 154-0024 + JP + +00-05-3E (hex) KID Systeme GmbH +00053E (base 16) KID Systeme GmbH + Luneburger Schanze 30 + + DE + +00-05-3F (hex) VisionTek, Inc. +00053F (base 16) VisionTek, Inc. + 1175 Lakeside Dr. + Gurnee IL 60031 + US + +00-05-3D (hex) Agere Systems +00053D (base 16) Agere Systems + 1371 McCarthy Blvd. + Milpitas CA 95035 + US + +00-05-00 (hex) Cisco Systems, Inc +000500 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-19 (hex) Siemens Building Technologies AG, +000519 (base 16) Siemens Building Technologies AG, + Cerberus Division + + CH + +00-05-0D (hex) Midstream Technologies, Inc. +00050D (base 16) Midstream Technologies, Inc. + 777 108th Ave. NE + Bellevue WA 98004-5140 + US + +00-05-34 (hex) Northstar Engineering Ltd. +000534 (base 16) Northstar Engineering Ltd. + P.O. Box 40 + + GB + +00-05-35 (hex) Chip PC Ltd. +000535 (base 16) Chip PC Ltd. + 20 A.L. Motzkin St. + Tirat Carmel 39100 + IL + +00-05-07 (hex) Fine Appliance Corp. +000507 (base 16) Fine Appliance Corp. + 7Fl., No. 499, + + TW + +00-04-FD (hex) Japan Control Engineering Co., Ltd. +0004FD (base 16) Japan Control Engineering Co., Ltd. + 1-5-1, Higashiamagawa, Takatsuki-shi + + JP + +00-05-62 (hex) Digital View Limited +000562 (base 16) Digital View Limited + 2201 Nan Yang Plaza, + Kowloon + HK + +00-04-E5 (hex) Glonet Systems, Inc. +0004E5 (base 16) Glonet Systems, Inc. + 11Fl., Jeil Bldg., 94-46, 7Ka + + KR + +00-04-D2 (hex) Adcon Telemetry GmbH +0004D2 (base 16) Adcon Telemetry GmbH + Inkustraße 24 + + AT + +00-04-D3 (hex) Toyokeiki Co., Ltd. +0004D3 (base 16) Toyokeiki Co., Ltd. + Wada 3967-10, Matsumoto-City + + JP + +00-04-AA (hex) Jetstream Communications +0004AA (base 16) Jetstream Communications + 5400 Hellyer Avenue + San Jose CA 95138-1005 + US + +00-04-A0 (hex) Verity Instruments, Inc. +0004A0 (base 16) Verity Instruments, Inc. + 2901 Eisenhower St. + Carrollton TX 75007 + US + +00-04-9E (hex) Wirelink Co., Ltd. +00049E (base 16) Wirelink Co., Ltd. + 11F, Geoseong B/D 541, Dowha-Dong, + KOREA + KR + +00-04-9A (hex) Cisco Systems, Inc +00049A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-04-79 (hex) Radius Co., Ltd. +000479 (base 16) Radius Co., Ltd. + 1-48-11, Itabashi + + JP + +00-04-B0 (hex) ELESIGN Co., Ltd. +0004B0 (base 16) ELESIGN Co., Ltd. + 9Fl. TaeKyoung Bldg., + R.O. KOREA + KR + +00-04-AB (hex) Mavenir Inc. +0004AB (base 16) Mavenir Inc. + 1700 International Parkway + Richardson TX 75081 + US + +00-04-A7 (hex) FabiaTech Corporation +0004A7 (base 16) FabiaTech Corporation + 4F-3, No. 18, Lane 609 + Taipei Hsien, TAIWAN R.O.C + TW + +00-04-98 (hex) Mahi Networks +000498 (base 16) Mahi Networks + 1039 N. McDowell Blvd. + Petaluma CA 94954 + US + +00-04-97 (hex) MacroSystem Digital Video AG +000497 (base 16) MacroSystem Digital Video AG + Schoellinger Feld 28 + + DE + +00-04-D5 (hex) Hitachi Information & Communication Engineering, Ltd. +0004D5 (base 16) Hitachi Information & Communication Engineering, Ltd. + Queen's Tower B21F, 2-3-3, Minatomirai, + Nishi-ku, Yokohama, 220-6121 + JP + +00-04-CA (hex) FreeMs Corp. +0004CA (base 16) FreeMs Corp. + Shinhan Bldg. 6F, + Seoul 150-736 KOREA + KR + +00-04-88 (hex) Eurotherm Controls +000488 (base 16) Eurotherm Controls + 741F Miller Drive + Lessburg VA 20175 + US + +00-04-85 (hex) PicoLight +000485 (base 16) PicoLight + 4665 Nautilus Court South + Boulder CO 80301 + US + +00-04-DA (hex) Relax Technology, Inc. +0004DA (base 16) Relax Technology, Inc. + DBA/ Granite Digital + Union City CA 94587 + US + +00-04-C5 (hex) ASE Technologies, USA +0004C5 (base 16) ASE Technologies, USA + 6721 Baum Dr. + Knoxville TN 37919 + US + +00-04-36 (hex) ELANsat Technologies, Inc. +000436 (base 16) ELANsat Technologies, Inc. + No. 11, Lane 19, Pateh Road, + Hsinchu TAIWAN, R.O.C. + TW + +00-04-32 (hex) Voyetra Turtle Beach, Inc. +000432 (base 16) Voyetra Turtle Beach, Inc. + 150 Clearbrook Road, Suite 162 + Elmsford NY 10523 + US + +00-04-35 (hex) InfiNet LLC +000435 (base 16) InfiNet LLC + Serafimy Deryabinoy str. 24 + Yekaterinburg 620149 + RU + +00-04-37 (hex) Powin Information Technology, Inc. +000437 (base 16) Powin Information Technology, Inc. + 8F, No. 70, Zhou-Z St. + TAIWAN TAIWAN R.O.C. + TW + +00-04-0C (hex) Kanno Works, Ltd. +00040C (base 16) Kanno Works, Ltd. + 1-5-25 Kamitomino, + + JP + +00-04-08 (hex) Sanko Electronics Co., Ltd. +000408 (base 16) Sanko Electronics Co., Ltd. + 3-802 ueda tenpaku-ku + nagoya + JP + +00-04-07 (hex) Topcon Positioning Systems, Inc. +000407 (base 16) Topcon Positioning Systems, Inc. + 5758 W. Las Positas Blvd. + Pleasanton CA 94588 + US + +00-04-09 (hex) Cratos Networks +000409 (base 16) Cratos Networks + 313 Littleton Road + Chelmsford MA 01824 + US + +00-04-55 (hex) ANTARA.net +000455 (base 16) ANTARA.net + 747 Camden Ave. + Campbell CA 95008 + US + +00-04-57 (hex) Universal Access Technology, Inc. +000457 (base 16) Universal Access Technology, Inc. + 2 Fl., No. 5, Alley 22, + Nei Hu Taipei, TAIWAN 114 + TW + +00-04-4D (hex) Cisco Systems, Inc +00044D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-04-54 (hex) Quadriga UK +000454 (base 16) Quadriga UK + Baird House + ENGLAND + GB + +00-04-48 (hex) Polaroid Corporation +000448 (base 16) Polaroid Corporation + 300 Baker Avenue + Concord MA 01742 + US + +00-04-47 (hex) Acrowave Systems Co., Ltd. +000447 (base 16) Acrowave Systems Co., Ltd. + Maru B/D 86-6, Nonhyun-Dong + KOREA zip: 135-818 + KR + +00-04-3E (hex) Telencomm +00043E (base 16) Telencomm + 2551 Walsh Avenue + Santa Clara CA 95051 + US + +00-04-6D (hex) Cisco Systems, Inc +00046D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-04-66 (hex) ARMITEL Co. +000466 (base 16) ARMITEL Co. + F5, Doman Plaza 353-4, + Republic of KOREA + KR + +00-03-E2 (hex) Comspace Corporation +0003E2 (base 16) Comspace Corporation + 955 Freeport Pkwy + Coppell TX 75019 + US + +00-03-FF (hex) Microsoft Corporation +0003FF (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond WA 98052 + US + +00-04-14 (hex) Umezawa Musen Denki Co., Ltd. +000414 (base 16) Umezawa Musen Denki Co., Ltd. + 14-3, Minami 1, Nishi 8, + Hokkaido JAPAN 060-0061 + JP + +00-04-28 (hex) Cisco Systems, Inc +000428 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-86 (hex) Ho Net, Inc. +000386 (base 16) Ho Net, Inc. + Venture Company Center + KOREA 442-760 + KR + +00-03-7D (hex) Stellcom +00037D (base 16) Stellcom + 10525 Vista Sorrento Parkway + San Diego CA 92121 + US + +00-03-83 (hex) Metera Networks, Inc. +000383 (base 16) Metera Networks, Inc. + 1202 Richardson Dr. + Richardson TX 75080 + US + +00-03-CC (hex) Momentum Computer, Inc. +0003CC (base 16) Momentum Computer, Inc. + 1815 Aston Avenue + Carlsbad CA 92008-7310 + US + +00-03-D7 (hex) NextNet Wireless, Inc. +0003D7 (base 16) NextNet Wireless, Inc. + 9555 James Ave. So. + Bloomington MN 55431 + US + +00-03-D3 (hex) Internet Energy Systems, Inc. +0003D3 (base 16) Internet Energy Systems, Inc. + 4218 Trumbo Ct. + Fairfax VA 22033 + US + +00-03-CD (hex) Clovertech, Inc. +0003CD (base 16) Clovertech, Inc. + 3-1-5 Naka-cho Musashino-shi + Tokyo 180-0006 + JP + +00-03-8B (hex) PLUS-ONE I&T, Inc. +00038B (base 16) PLUS-ONE I&T, Inc. + 7F, A-San Venture Tower, + KOREA + KR + +00-03-8C (hex) Total Impact +00038C (base 16) Total Impact + 295 Willis Ave. + Camarillo CA 93010 + US + +00-03-EE (hex) MKNet Corporation +0003EE (base 16) MKNet Corporation + 711-B Charcot Ave. + San Jose CA 95131 + US + +00-03-EA (hex) Mega System Technologies, Inc. +0003EA (base 16) Mega System Technologies, Inc. + 2F, No. 41, Lane 76, + Taipei Taipei TAIWAN + TW + +00-03-E6 (hex) Entone, Inc. +0003E6 (base 16) Entone, Inc. + 2755 Campus Dr Ste 235 + San Mateo CA 94403 + US + +00-03-A9 (hex) AXCENT Media AG +0003A9 (base 16) AXCENT Media AG + Technologiepark 13 + + DE + +00-03-9F (hex) Cisco Systems, Inc +00039F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-90 (hex) Digital Video Communications, Inc. +000390 (base 16) Digital Video Communications, Inc. + 500 W. Cummings Park + Woburn MA 07801 + US + +00-03-B5 (hex) Entra Technology Co. +0003B5 (base 16) Entra Technology Co. + Fl. 3, No. 5, Alley 2, + TAIWAN TAIWAN R.O.C. + TW + +00-03-64 (hex) Scenix Semiconductor, Inc. +000364 (base 16) Scenix Semiconductor, Inc. + 1330 Charleston Rd. + Mountainview CA 94043 + US + +00-03-5E (hex) Metropolitan Area Networks, Inc. +00035E (base 16) Metropolitan Area Networks, Inc. + 1299 Pennsylvania Avenue, NW + Washington DC 20004 + US + +00-03-5C (hex) Saint Song Corp. +00035C (base 16) Saint Song Corp. + 4F, No. 12, Lane 94, Tsao Ti Wzi + 222 + TW + +00-03-5D (hex) Bosung Hi-Net Co., Ltd. +00035D (base 16) Bosung Hi-Net Co., Ltd. + Youngil B/O 2F, + 137-130 + KR + +00-03-79 (hex) Proscend Communications, Inc. +000379 (base 16) Proscend Communications, Inc. + 2F, No.36, Industry E. Rd. IV, + Hsinchu 300 + TW + +00-03-6F (hex) Telsey SPA +00036F (base 16) Telsey SPA + Viale Dell Industria, 1 + DiTreviso- + IT + +00-03-72 (hex) ULAN +000372 (base 16) ULAN + 5F-3, No. 31-1, Lane 169, + TAIWAN TAIWAN R.O.C. + TW + +00-03-34 (hex) Newport Electronics +000334 (base 16) Newport Electronics + 2229 So. Yale St. + Santa Ana CA 92704 + US + +00-03-3A (hex) Silicon Wave, Inc. +00033A (base 16) Silicon Wave, Inc. + 6256 Greenwich Drive + San Diego CA 92122 + US + +00-03-32 (hex) Cisco Systems, Inc +000332 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-0E (hex) Core Communications Co., Ltd. +00030E (base 16) Core Communications Co., Ltd. + 3F Shopping Center Bd. of + Seoul (121-050) (121-050) + KR + +00-03-12 (hex) TRsystems GmbH +000312 (base 16) TRsystems GmbH + Eglishalde 16 + Trossingen Baden-Wuerttemberg D-78647 + DE + +00-03-41 (hex) Axon Digital Design +000341 (base 16) Axon Digital Design + Lange Wagenstraat 55 + + NL + +00-80-37 (hex) Ericsson Group +008037 (base 16) Ericsson Group + Telefonaktiebolaget + + SE + +00-03-3D (hex) ILSHin Lab +00033D (base 16) ILSHin Lab + KCS B/D 228-13 Young Dap-Dong + Seoul + KR + +00-03-66 (hex) ASM Pacific Technology +000366 (base 16) ASM Pacific Technology + 12/F Watson Centre + Kwai Chung + HK + +00-03-62 (hex) Vodtel Communications, Inc. +000362 (base 16) Vodtel Communications, Inc. + 12F, No 166 Chien-Yi Road + 235 + TW + +00-03-4D (hex) Chiaro Networks, Ltd. +00034D (base 16) Chiaro Networks, Ltd. + P.O. Box 832427 + Richardson TX 75083-2427 + US + +00-03-22 (hex) IDIS Co., Ltd. +000322 (base 16) IDIS Co., Ltd. + 7th Floor, 646-7 Yuksam-Dong, + + KR + +00-03-1D (hex) Taiwan Commate Computer, Inc. +00031D (base 16) Taiwan Commate Computer, Inc. + 8F, No. 94, Sec 1, + + TW + +00-03-26 (hex) Iwasaki Information Systems Co., Ltd. +000326 (base 16) Iwasaki Information Systems Co., Ltd. + 3361 Oshi + + JP + +00-02-90 (hex) Woorigisool, Inc. +000290 (base 16) Woorigisool, Inc. + Yoopoong Bldg. + Seoul Seoul KOREA + KR + +00-02-92 (hex) Logic Innovations, Inc. +000292 (base 16) Logic Innovations, Inc. + 6205 Lusk Blvd. + San Diego CA 92121-2731 + US + +00-02-86 (hex) Occam Networks +000286 (base 16) Occam Networks + 4183 State Street + Santa Barbara CA 93110 + US + +00-02-D2 (hex) Workstation AG +0002D2 (base 16) Workstation AG + Schaffhauserstrasse 55 + + CH + +00-02-CD (hex) TeleDream, Inc. +0002CD (base 16) TeleDream, Inc. + Shinhwa Bldg., 940-10 Daechi-Dong + + KR + +00-02-D0 (hex) Comdial Corporation +0002D0 (base 16) Comdial Corporation + 1180 Seminole Trail + Charlottesville VA 22901 + US + +00-02-CC (hex) M.C.C.I +0002CC (base 16) M.C.C.I + 3520 Krums Corners Rd. + Ithaca NY 14850 + US + +00-02-B0 (hex) Hokubu Communication & Industrial Co., Ltd. +0002B0 (base 16) Hokubu Communication & Industrial Co., Ltd. + Fushiogami-aza-oki 27-1 + Fukushima 960-8514 + JP + +00-02-AA (hex) PLcom Co., Ltd. +0002AA (base 16) PLcom Co., Ltd. + Hosung B/D, #1083-1, Hogye-Dong + South Korea + KR + +00-02-B5 (hex) Avnet, Inc. +0002B5 (base 16) Avnet, Inc. + 2211 S. 47th Street + Phoenix AZ 85034 + US + +00-02-B4 (hex) DAPHNE +0002B4 (base 16) DAPHNE + 101 Chaussee De Binche + + BE + +00-02-AC (hex) 3PAR data +0002AC (base 16) 3PAR data + 4209 Technology Drive + Fremont CA 94538 + US + +00-02-D9 (hex) Reliable Controls +0002D9 (base 16) Reliable Controls + 120 Hallowell Road + Victoria, B.C. V9A 7K2 + CA + +00-02-EF (hex) CCC Network Systems Group Ltd. +0002EF (base 16) CCC Network Systems Group Ltd. + 13 Farnborough Business Centre + ENGLAND + GB + +00-02-E8 (hex) E.D.&A. +0002E8 (base 16) E.D.&A. + Energielaan 16 + + BE + +00-02-F2 (hex) eDevice, Inc. +0002F2 (base 16) eDevice, Inc. + 420 Lexington Avenue + New York NY 10170 + US + +00-02-9D (hex) Merix Corp. +00029D (base 16) Merix Corp. + Jin-Su Building, 49-16 + Seoul Seoul KOREA + KR + +00-02-C5 (hex) Evertz Microsystems Ltd. +0002C5 (base 16) Evertz Microsystems Ltd. + 5292 John Lucas Drive + Ontario L7L 5Z9 + CA + +00-02-4A (hex) Cisco Systems, Inc +00024A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-02-49 (hex) Aviv Infocom Co, Ltd. +000249 (base 16) Aviv Infocom Co, Ltd. + 962-5, Kwanyang-Dong, Dongan-Gu, + Korea (ROK) + KR + +00-02-45 (hex) Lampus Co, Ltd. +000245 (base 16) Lampus Co, Ltd. + 6th Bldg., Samgong, + Korea Korea 137-044 + KR + +00-02-32 (hex) Avision, Inc. +000232 (base 16) Avision, Inc. + No. 20, Creation Rd. 1, + Hsinchu Taiwan, R.O.C. + TW + +00-02-35 (hex) Paragon Networks International +000235 (base 16) Paragon Networks International + 61 Commerce Drive + Brookfield CT 06804 + US + +00-02-37 (hex) Cosmo Research Corp. +000237 (base 16) Cosmo Research Corp. + Cosmo Bldg, 3-148-5 + + KW + +00-02-28 (hex) Necsom, Ltd. +000228 (base 16) Necsom, Ltd. + Necsom Ltd. c/o Koirsto + + FI + +00-02-46 (hex) All-Win Tech Co., Ltd. +000246 (base 16) All-Win Tech Co., Ltd. + 11F, No. 111-7, Hsing De Rd., + Taipei Hsien Taiwan, R.O.C. + TW + +00-02-3A (hex) ZSK Stickmaschinen GmbH +00023A (base 16) ZSK Stickmaschinen GmbH + Magdeburger Straße 38-40 + + DE + +00-02-7F (hex) ask-technologies.com +00027F (base 16) ask-technologies.com + 36 Wellington Business Park + + GB + +00-02-7E (hex) Cisco Systems, Inc +00027E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-10-95 (hex) Thomson Inc. +001095 (base 16) Thomson Inc. + 101 West 103rd Street + Indianapolis IN 46290-1102 + US + +00-02-5D (hex) Calix Networks +00025D (base 16) Calix Networks + 1035 North McDowell Blvd. + Petaluma CA 94954 + US + +00-02-7B (hex) Amplify Net, Inc. +00027B (base 16) Amplify Net, Inc. + 47381 Bayside Parkway + Fremont CA 94538 + US + +00-02-73 (hex) Coriolis Networks +000273 (base 16) Coriolis Networks + 330 Codmanhill Road + Boxborough MA 01719 + US + +00-02-57 (hex) Microcom Corp. +000257 (base 16) Microcom Corp. + 8333A Green Meadows Dr. N. + Westerville OH 43081 + US + +00-02-53 (hex) Televideo, Inc. +000253 (base 16) Televideo, Inc. + 2345 Harris Way + San Jose CA 95131 + US + +00-02-6F (hex) Senao International Co., Ltd. +00026F (base 16) Senao International Co., Ltd. + 2F, No. 531, Chung-Cheng Rd., + TAIWAN + TW + +00-02-30 (hex) Intersoft Electronics +000230 (base 16) Intersoft Electronics + Lammerdries 27 + + BE + +00-02-1C (hex) Network Elements, Inc. +00021C (base 16) Network Elements, Inc. + 9782 SW Nimbus Avenue + Beaverton OR 97008 + US + +00-02-0C (hex) Metro-Optix +00020C (base 16) Metro-Optix + 2201 Avenue K + Plano TX 75074 + US + +00-02-16 (hex) Cisco Systems, Inc +000216 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-02-14 (hex) DTVRO +000214 (base 16) DTVRO + 813 Daegong Bldg., + KOREA KOREA 135-080 + KR + +00-02-0F (hex) AATR +00020F (base 16) AATR + 306 Chemin des Miroirs + + FR + +00-01-C3 (hex) Acromag, Inc. +0001C3 (base 16) Acromag, Inc. + 30765 S. Wixom Road + Wixom MI 48393 + US + +00-01-C2 (hex) ARK Research Corp. +0001C2 (base 16) ARK Research Corp. + 1198 Saratoga Ave. #11D + San Jose CA 95129 + US + +00-01-EA (hex) Cirilium Corp. +0001EA (base 16) Cirilium Corp. + 1615 S. 52nd Street + Tempe AZ 85281 + US + +00-01-E0 (hex) Fast Systems, Inc. +0001E0 (base 16) Fast Systems, Inc. + 87-9 Yang-Jae, Seo-Cho, + KOREA + KR + +00-01-AC (hex) Sitara Networks, Inc. +0001AC (base 16) Sitara Networks, Inc. + 60 Hickory Drive + Waltham MA 02451 + US + +00-01-ED (hex) SETA Corp. +0001ED (base 16) SETA Corp. + Ariake Frontier Bldg. B + JAPAN 135-0063 + JP + +00-01-F6 (hex) Association of Musical Electronics Industry +0001F6 (base 16) Association of Musical Electronics Industry + Ito Bldg. 4th Floor 2-16-9 Misaki-cho, + + JP + +00-01-CB (hex) EVR +0001CB (base 16) EVR + 12 Raul Wallenberg St. + Tel Aviv 69719 + IL + +00-01-D6 (hex) manroland AG +0001D6 (base 16) manroland AG + Stadtbachstraße 1 + + DE + +00-01-AD (hex) Coach Master International d.b.a. CMI Worldwide, Inc. +0001AD (base 16) Coach Master International d.b.a. CMI Worldwide, Inc. + 600 Stewart Street + Seattle WA 98101 + US + +00-01-88 (hex) LXCO Technologies ag +000188 (base 16) LXCO Technologies ag + Gimmerstraße 69 + + DE + +00-01-9B (hex) Kyoto Microcomputer Co., Ltd. +00019B (base 16) Kyoto Microcomputer Co., Ltd. + 2-44 nakayama oe nishikyo-ku + kyoto + JP + +00-01-7F (hex) Experience Music Project +00017F (base 16) Experience Music Project + 110 -110th Avenue NE - Ste. #400 + Bellevue WA 98004 + US + +00-01-5A (hex) Digital Video Broadcasting +00015A (base 16) Digital Video Broadcasting + DVB, % European Broadcasting Union + + CH + +00-01-2A (hex) Telematica Sistems Inteligente +00012A (base 16) Telematica Sistems Inteligente + Rua Miguel Casagrande, 200 + São Paulo + BR + +00-01-66 (hex) TC GROUP A/S +000166 (base 16) TC GROUP A/S + Sindalsvej 34 + Risskov DK-8240 + DK + +00-01-76 (hex) Orient Silver Enterprises +000176 (base 16) Orient Silver Enterprises + 8740 White Oak Avenue + Rancho Cucamonga CA 91730 + US + +00-01-58 (hex) Electro Industries/Gauge Tech +000158 (base 16) Electro Industries/Gauge Tech + 1800 Shames Drive + Westbury NY 11590 + US + +00-01-2D (hex) Komodo Technology +00012D (base 16) Komodo Technology + 170 Knowles Drive + Los Gatos CA 95032 + US + +00-01-48 (hex) X-traWeb Inc. +000148 (base 16) X-traWeb Inc. + 6750 West 93rd Street - Ste. #210 + Overland Park KS 66212 + US + +00-01-87 (hex) I2SE GmbH +000187 (base 16) I2SE GmbH + Friedrich-Ebert-Str. 61 + Leipzig 04109 + DE + +00-01-80 (hex) AOpen, Inc. +000180 (base 16) AOpen, Inc. + 6F, 88, Sec.1, Hsin Tai + TAIWAN TAIWAN R.O.C. + TW + +00-01-97 (hex) Cisco Systems, Inc +000197 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-01-9A (hex) LEUNIG GmbH +00019A (base 16) LEUNIG GmbH + Wilhelm-Ostwald-Str. 17 + + DE + +00-01-59 (hex) S1 Corporation +000159 (base 16) S1 Corporation + R&D Center, S1 Bldg. + KOREA 135-010 + KR + +00-01-71 (hex) Allied Data Technologies +000171 (base 16) Allied Data Technologies + Pascalweg 1, + THE + NL + +00-30-AC (hex) Systeme Lauer GmbH & Co., Ltd. +0030AC (base 16) Systeme Lauer GmbH & Co., Ltd. + Kelterstrasse 59 + 72669 Unterensingen + DE + +00-30-FB (hex) AZS Technology AG +0030FB (base 16) AZS Technology AG + Steinbeisstrasse 2-4 + 72510 Stetten A.K.M. + DE + +00-30-AE (hex) Times N System, Inc. +0030AE (base 16) Times N System, Inc. + 1826 Kramer Lane - Ste. + Austin TX 78758 + US + +00-30-03 (hex) Phasys Ltd. +003003 (base 16) Phasys Ltd. + #100-9404 41st Avenue + Edmonton Alberta T6X 1R2 + CA + +00-30-E2 (hex) GARNET SYSTEMS CO., LTD. +0030E2 (base 16) GARNET SYSTEMS CO., LTD. + Sungwon Bldg. 545-7 + Seoul + KR + +00-01-3A (hex) SHELCAD COMMUNICATIONS, LTD. +00013A (base 16) SHELCAD COMMUNICATIONS, LTD. + P.O. Box 8513 + + IL + +00-01-40 (hex) Sendtek Corporation +000140 (base 16) Sendtek Corporation + 12F-3, 333, Sec.1 + TAIWAN + TW + +00-01-23 (hex) Schneider Electric Japan Holdings Ltd. +000123 (base 16) Schneider Electric Japan Holdings Ltd. + Schneider Electric Osaka Building + 4-4-9 Kitahama Chuo-ku, Osaka 541-0041 + JP + +00-01-25 (hex) YAESU MUSEN CO., LTD. +000125 (base 16) YAESU MUSEN CO., LTD. + Tennozu Parkside Building + Shinagawa-ku, Tokyo 140-0002 + JP + +00-01-26 (hex) PAC Labs +000126 (base 16) PAC Labs + 3079 Kilgore Road + Rancho Cordova CA 95670 + US + +00-01-1B (hex) Unizone Technologies, Inc. +00011B (base 16) Unizone Technologies, Inc. + 5Floor HaeSung Bldg. + SeoCho-Ku Seoul + KR + +00-01-1D (hex) Centillium Communications +00011D (base 16) Centillium Communications + 47211 Lakeview Blvd. + Fremont CA 94538 + US + +00-01-1F (hex) RC Networks, Inc. +00011F (base 16) RC Networks, Inc. + 6727 Flanders Drive - Ste. #212 + San Diego CA 92121 + US + +00-B0-80 (hex) Mannesmann Ipulsys B.V. +00B080 (base 16) Mannesmann Ipulsys B.V. + Bordewijklaan 18 + 2591 XR The Hague + NL + +00-B0-1E (hex) Rantic Labs, Inc. +00B01E (base 16) Rantic Labs, Inc. + 702 Brazos, Suite #500 + Austin TX 78701 + US + +00-B0-F0 (hex) CALY NETWORKS +00B0F0 (base 16) CALY NETWORKS + 295 Santa Anna Court + Sunnyvale CA 94086 + US + +00-B0-9A (hex) Morrow Technologies Corp. +00B09A (base 16) Morrow Technologies Corp. + 2300 Tall Pines Drive + Largo FL 33771-5342 + US + +00-30-2E (hex) Hoft & Wessel AG +00302E (base 16) Hoft & Wessel AG + Rotenburger Strasse 20 + 30659 Hannover + DE + +00-30-ED (hex) Expert Magnetics Corp. +0030ED (base 16) Expert Magnetics Corp. + 12/F., Unit D, MTG Bldg., 1-3, Nakase + Mihama-ku, Chiba-city, 261-8501 + JP + +00-30-0F (hex) IMT - Information Management T +00300F (base 16) IMT - Information Management T + Gewerbestrasse 8 + CH-9470 Buchs + CH + +00-30-82 (hex) TAIHAN ELECTRIC WIRE CO., LTD. +003082 (base 16) TAIHAN ELECTRIC WIRE CO., LTD. + Communication Engineering Team + Seoul + KR + +00-30-A9 (hex) Netiverse, Inc. +0030A9 (base 16) Netiverse, Inc. + 100 Century Center Court + San Jose CA 95112 + US + +00-30-FE (hex) DSA GmbH +0030FE (base 16) DSA GmbH + Pascalstraße 28 + 52076 Aachen + DE + +00-30-C4 (hex) Canon Imaging Systems Inc. +0030C4 (base 16) Canon Imaging Systems Inc. + 1-24 Yoneyama, Chuo-ku + Niigata-shi Niigata 950-0916 + JP + +00-30-4D (hex) ESI +00304D (base 16) ESI + 3701 E. Plano Parkway + Plano TX 75074 + US + +08-14-43 (hex) UNIBRAIN S.A. +081443 (base 16) UNIBRAIN S.A. + 84, ETHNIKIS ANTISTASEOS + + GR + +00-B0-09 (hex) Grass Valley, A Belden Brand +00B009 (base 16) Grass Valley, A Belden Brand + 3499, Douglas B. Floreani + Montreal Quebec H4S 2C6 + CA + +00-B0-AC (hex) SIAE-Microelettronica S.p.A. +00B0AC (base 16) SIAE-Microelettronica S.p.A. + Via Michelangelo Buonarroti, 21 + 20093 Cologno M. (Ml) + IT + +00-30-23 (hex) COGENT COMPUTER SYSTEMS, INC. +003023 (base 16) COGENT COMPUTER SYSTEMS, INC. + 10 RIVER ROAD - STE. #205 + UXBRIDGE MA 01569 + US + +00-30-90 (hex) CYRA TECHNOLOGIES, INC. +003090 (base 16) CYRA TECHNOLOGIES, INC. + 8000 CAPWELL DRIVE + OAKLAND CA 94621 + US + +00-30-A7 (hex) SCHWEITZER ENGINEERING +0030A7 (base 16) SCHWEITZER ENGINEERING + LABORATORIES, INC. + PULLMAN WA 99163 + US + +00-30-7C (hex) ADID SA +00307C (base 16) ADID SA + 70 RU ANATOLE FRANCE + 92 300 LEVALLOIS-PERRET CEDEX + FR + +00-30-55 (hex) Renesas Technology America, Inc. +003055 (base 16) Renesas Technology America, Inc. + 450 Holger Way + San Jose CA 95134 + US + +00-30-2F (hex) GE Aviation System +00302F (base 16) GE Aviation System + 3290 Patterson Ave., S.E. + Grand Rapids MI 49512 + US + +00-30-0E (hex) Klotz Digital AG +00300E (base 16) Klotz Digital AG + Hans-Stiessbergerstraße 2A + D-85540 Haar + DE + +00-30-D5 (hex) DResearch GmbH +0030D5 (base 16) DResearch GmbH + Otto-Schmirgal-Str.3 + 10319 Berlin + DE + +00-30-18 (hex) Jetway Information Co., Ltd. +003018 (base 16) Jetway Information Co., Ltd. + 4F, No. 168, LI THE ST. + Chung Ho City 235 Taipei + TW + +00-30-9F (hex) AMBER NETWORKS +00309F (base 16) AMBER NETWORKS + 2475 AUGUSTINE DR. + SANTA CLARA CA 95054 + US + +00-30-A8 (hex) OL'E COMMUNICATIONS, INC. +0030A8 (base 16) OL'E COMMUNICATIONS, INC. + 1962 ZANKER ROAD + SAN JOSE CA 95112 + US + +00-30-D1 (hex) INOVA CORPORATION +0030D1 (base 16) INOVA CORPORATION + 110 AVON STREET + CHARLOTTESVILE VA 22902 + US + +00-30-BB (hex) CacheFlow, Inc. +0030BB (base 16) CacheFlow, Inc. + 650 Almanor Drive + Sunnyvale CA 94086 + US + +00-30-AF (hex) Honeywell GmbH +0030AF (base 16) Honeywell GmbH + Boeblinger Str. 17 + D-71098 Schoenaich + DE + +00-30-AA (hex) AXUS MICROSYSTEMS, INC. +0030AA (base 16) AXUS MICROSYSTEMS, INC. + 2F-4, NO.18/N. 609, SEC. 5 + TAIWAN TAIWAN R.O.C. + TW + +00-30-89 (hex) Spectrapoint Wireless, LLC +003089 (base 16) Spectrapoint Wireless, LLC + 1125 E. Collins Blvd. + Richardson TX 75081 + US + +00-30-9A (hex) ASTRO TERRA CORP. +00309A (base 16) ASTRO TERRA CORP. + 11526 SORRENTO VALLEY ROAD + SAN DIEGO CA 92121 + US + +00-30-87 (hex) VEGA GRIESHABER KG +003087 (base 16) VEGA GRIESHABER KG + AM HOHENSTEIN 113 + + DE + +00-30-62 (hex) IP Video Networks Inc +003062 (base 16) IP Video Networks Inc + 6650 Lusk Blvd + SAN DIEGO CA 92121 + US + +00-30-2D (hex) QUANTUM BRIDGE COMMUNICATIONS +00302D (base 16) QUANTUM BRIDGE COMMUNICATIONS + ONE HIGH STREET + NORTH ANDOVER MA 01845 + US + +00-30-CB (hex) OMNI FLOW COMPUTERS, INC. +0030CB (base 16) OMNI FLOW COMPUTERS, INC. + 10701 CORPORATE DRIVE-STE.#300 + STAFFORD TX 77477 + US + +00-30-6B (hex) CMOS SYSTEMS, INC. +00306B (base 16) CMOS SYSTEMS, INC. + 23440 HAWTHORNE BLVD-STE #290 + TORRANCE CA 90505 + US + +00-30-AD (hex) SHANGHAI COMMUNICATION +0030AD (base 16) SHANGHAI COMMUNICATION + TECHNOLOGIES CENTER + P.R. + CN + +00-30-CF (hex) TWO TECHNOLOGIES, INC. +0030CF (base 16) TWO TECHNOLOGIES, INC. + 419 SARGON WAY + HORSHAM PA 19044 + US + +00-30-B2 (hex) L-3 Sonoma EO +0030B2 (base 16) L-3 Sonoma EO + 428 Aviation Blvd + Santa Rosa CA 95403 + US + +00-30-35 (hex) Corning Incorporated +003035 (base 16) Corning Incorporated + Data Center + Corning NY 14831 + US + +00-30-7F (hex) IRLAN LTD. +00307F (base 16) IRLAN LTD. + 1 HATAMAR STREET + + IL + +00-D0-15 (hex) UNIVEX MICROTECHNOLOGY CORP. +00D015 (base 16) UNIVEX MICROTECHNOLOGY CORP. + 2, TZE-CHIANG 3RD ROAD + TAIWAN + TW + +00-D0-48 (hex) ECTON, INC. +00D048 (base 16) ECTON, INC. + 5168 CAMPUS DRIVE + PLYMOUTH MEETING PA 19462 + US + +00-D0-A5 (hex) AMERICAN ARIUM +00D0A5 (base 16) AMERICAN ARIUM + 14281 CHAMBERS ROAD + TUSTIN CA 92780 + US + +00-30-5D (hex) DIGITRA SYSTEMS, INC. +00305D (base 16) DIGITRA SYSTEMS, INC. + 8-61, GAWOL-DONG + KOREA 140-150 + KR + +00-30-36 (hex) RMP ELEKTRONIKSYSTEME GMBH +003036 (base 16) RMP ELEKTRONIKSYSTEME GMBH + HANNS-MARTIN-SCHLE'R-STR.12-14 + + DE + +00-D0-CF (hex) MORETON BAY +00D0CF (base 16) MORETON BAY + 12/97 JIJAWS STREET + + AU + +00-D0-7F (hex) STRATEGY & TECHNOLOGY, LIMITED +00D07F (base 16) STRATEGY & TECHNOLOGY, LIMITED + Suite 4.2, Clifton Heights + Bristol BS8 1EJ + GB + +00-30-E6 (hex) Draeger Medical Systems, Inc. +0030E6 (base 16) Draeger Medical Systems, Inc. + 6 Tech Drive + Andover MA 01810 + US + +00-30-BD (hex) BELKIN COMPONENTS +0030BD (base 16) BELKIN COMPONENTS + 501 WEST WALNUT STREET + COMPTON CA 90220 + US + +00-30-07 (hex) OPTI, INC. +003007 (base 16) OPTI, INC. + 1440 MCCARTHY BLVD. + MILPITAS CA 95035 + US + +00-D0-C2 (hex) BALTHAZAR TECHNOLOGY AB +00D0C2 (base 16) BALTHAZAR TECHNOLOGY AB + ANKDAMMSGATAN 24 + + SE + +00-D0-22 (hex) INCREDIBLE TECHNOLOGIES, INC. +00D022 (base 16) INCREDIBLE TECHNOLOGIES, INC. + 1600 HICKS ROAD + ROLLING MEADOWS IL 60008 + US + +00-D0-71 (hex) ECHELON CORP. +00D071 (base 16) ECHELON CORP. + 2901 Patrick Henry Dr. + Santa Clara CA 95054 + US + +00-D0-4F (hex) BITRONICS, INC. +00D04F (base 16) BITRONICS, INC. + P.O. BOX 22290 + LEHIGH VALLEY PA 18002-2290 + US + +00-D0-69 (hex) TECHNOLOGIC SYSTEMS +00D069 (base 16) TECHNOLOGIC SYSTEMS + 16610 E. LASER DRIVE-STE. #10 + FOUNTAIN HILLS AZ 85268 + US + +00-D0-90 (hex) Cisco Systems, Inc +00D090 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-F5 (hex) ORANGE MICRO, INC. +00D0F5 (base 16) ORANGE MICRO, INC. + 1400 N. LAKEVIEW AVE. + ANAHEIM CA 92807 + US + +00-D0-E9 (hex) Advantage Century Telecommunication Corp. +00D0E9 (base 16) Advantage Century Telecommunication Corp. + 4F, 41, Tunghsin Rd. + Taipei + TW + +00-D0-94 (hex) Seeion Control LLC +00D094 (base 16) Seeion Control LLC + 117 Stephanie Lane + vista CA 92084-5316 + US + +00-D0-FB (hex) TEK MICROSYSTEMS, INCORPORATED +00D0FB (base 16) TEK MICROSYSTEMS, INCORPORATED + ONE NORTH AVENUE + BURLINGTON MA 01803 + US + +00-D0-66 (hex) WINTRISS ENGINEERING CORP. +00D066 (base 16) WINTRISS ENGINEERING CORP. + 6344 FERRIS SQUARE + SAN DIEGO CA 92121 + US + +00-D0-82 (hex) IOWAVE INC. +00D082 (base 16) IOWAVE INC. + 1010 WISCONSIN AVENUE + WASHINGTON DC 20007 + US + +00-D0-81 (hex) RTD Embedded Technologies, Inc. +00D081 (base 16) RTD Embedded Technologies, Inc. + 103 Innovation Blvd. + State College PA 16803 + US + +00-D0-02 (hex) DITECH CORPORATION +00D002 (base 16) DITECH CORPORATION + 825 EAST MIDDLEFIELD RD + MOUNTAIN VIEW CA 94043 + US + +00-D0-85 (hex) OTIS ELEVATOR COMPANY +00D085 (base 16) OTIS ELEVATOR COMPANY + 5 FARM SPRINGS RD. + FARMINGTON CT 06032 + US + +00-D0-11 (hex) PRISM VIDEO, INC. +00D011 (base 16) PRISM VIDEO, INC. + 15851 DALLAS PARKWAY-STE.#1060 + ADDISON TX 75001 + US + +00-D0-DF (hex) KUZUMI ELECTRONICS, INC. +00D0DF (base 16) KUZUMI ELECTRONICS, INC. + 28-6 IIJIMA-CHYO, SAKAE-KU + + JP + +00-D0-9B (hex) SPECTEL LTD. +00D09B (base 16) SPECTEL LTD. + 21 STILLORGAN INDUSTRIAL PARK + + IE + +00-D0-67 (hex) CAMPIO COMMUNICATIONS +00D067 (base 16) CAMPIO COMMUNICATIONS + 2033 GATEWAY PL, SUITE #600 + SAN JOSE CA 95110 + US + +00-D0-58 (hex) Cisco Systems, Inc +00D058 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-32 (hex) YANO ELECTRIC CO., LTD. +00D032 (base 16) YANO ELECTRIC CO., LTD. + 7-3-1 IBUKIDAIHIGASHIMACHI + + JP + +00-D0-F1 (hex) SEGA ENTERPRISES, LTD. +00D0F1 (base 16) SEGA ENTERPRISES, LTD. + 12-14 HIGASHIKOUJIYA 2-CHOME + + JP + +00-D0-3A (hex) ZONEWORX, INC. +00D03A (base 16) ZONEWORX, INC. + 40925 COUNTY CENTER DRIVE + TEMECULA CA 92592 + US + +00-D0-01 (hex) VST TECHNOLOGIES, INC. +00D001 (base 16) VST TECHNOLOGIES, INC. + 125 NAGOG PARK + ACTON MA 01720 + US + +00-50-3E (hex) Cisco Systems, Inc +00503E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-50-20 (hex) MEDIASTAR CO., LTD. +005020 (base 16) MEDIASTAR CO., LTD. + 3FL, SOHUN BLDG. + KOREA + KR + +00-D0-75 (hex) ALARIS MEDICAL SYSTEMS, INC. +00D075 (base 16) ALARIS MEDICAL SYSTEMS, INC. + P.O. BOX 85335 + SAN DIEGO CA 92121-2733 + US + +00-D0-4C (hex) EUROTEL TELECOM LTD. +00D04C (base 16) EUROTEL TELECOM LTD. + CANISTER HOUSE + UNITED KINGDOM + GB + +00-D0-E1 (hex) AVIONITEK ISRAEL INC. +00D0E1 (base 16) AVIONITEK ISRAEL INC. + 1 ETGAR STREET + + IL + +00-D0-08 (hex) MACTELL CORPORATION +00D008 (base 16) MACTELL CORPORATION + 7000 CAMERON ROAD + AUSTIN TX 78752 + US + +00-D0-D9 (hex) DEDICATED MICROCOMPUTERS +00D0D9 (base 16) DEDICATED MICROCOMPUTERS + 1 Thellow Heath Park + Northwich CW9 6JB + GB + +00-D0-0B (hex) RHK TECHNOLOGY, INC. +00D00B (base 16) RHK TECHNOLOGY, INC. + 1050 EAST MAPLE ROAD + TROY MI 48083 + US + +00-D0-9C (hex) KAPADIA COMMUNICATIONS +00D09C (base 16) KAPADIA COMMUNICATIONS + 3925 WEST BROKER LANE + AUSTIN TX 78759 + US + +00-D0-F3 (hex) SOLARI DI UDINE SPA +00D0F3 (base 16) SOLARI DI UDINE SPA + VIA GINO PIERI 29 + + IT + +00-D0-39 (hex) UTILICOM, INC. +00D039 (base 16) UTILICOM, INC. + 323 LOVE PLACE + SANTA BARBARA CA 93112-3289 + US + +00-D0-A0 (hex) MIPS DENMARK +00D0A0 (base 16) MIPS DENMARK + LAUTRUPVANG 2B + DK - + DK + +00-D0-0A (hex) LANACCESS TELECOM S.A. +00D00A (base 16) LANACCESS TELECOM S.A. + GRAN VIA 8-10 4 1 + + ES + +00-D0-1C (hex) SBS TECHNOLOGIES, +00D01C (base 16) SBS TECHNOLOGIES, + CONNECTIVITY PRODUCTS + ST. PAUL MN 55121-1245 + US + +00-D0-D5 (hex) GRUNDIG AG +00D0D5 (base 16) GRUNDIG AG + KURGARTENSGTREET 37 + + DE + +00-D0-41 (hex) AMIGO TECHNOLOGY CO., LTD. +00D041 (base 16) AMIGO TECHNOLOGY CO., LTD. + 4F-1B, NO.12, LANE 609, SEC.5, + TAIWAN TAIWAN R.O.C. + TW + +00-D0-9D (hex) VERIS INDUSTRIES +00D09D (base 16) VERIS INDUSTRIES + 10831 SW CASCADE + PORTLAND OR 97223 + US + +00-D0-6D (hex) ACRISON, INC. +00D06D (base 16) ACRISON, INC. + 20 EMPIRE BLVD. + MOONACHIE NJ 07074 + US + +00-D0-2B (hex) JETCELL, INC. +00D02B (base 16) JETCELL, INC. + 173 CONSTITUTION DRIVE + MENLO PARK CA 94025-1106 + US + +00-D0-62 (hex) DIGIGRAM +00D062 (base 16) DIGIGRAM + PARC DE PRE MILLIET + + FR + +00-D0-8D (hex) PHOENIX GROUP, INC. +00D08D (base 16) PHOENIX GROUP, INC. + 123 MARCUS BLVD. + HAUPPAUGE NY 11788 + US + +00-D0-3D (hex) GALILEO TECHNOLOGY, LTD. +00D03D (base 16) GALILEO TECHNOLOGY, LTD. + MOSHAV MANOF + + IL + +00-50-C6 (hex) LOOP TELECOMMUNICATION INTERNATIONAL, INC. +0050C6 (base 16) LOOP TELECOMMUNICATION INTERNATIONAL, INC. + 7F, No. 8, Hsin Ann Road + Hsinchu - + TW + +00-50-9F (hex) HORIZON COMPUTER +00509F (base 16) HORIZON COMPUTER + TRINITY BLDG. 4-22-7 + TOKYO 106 + JP + +00-50-A5 (hex) CAPITOL BUSINESS SYSTEMS, LTD. +0050A5 (base 16) CAPITOL BUSINESS SYSTEMS, LTD. + 43/44 RIVERSIDE + ROCHESTER, KENT England ME2 4DP + GB + +00-50-00 (hex) NEXO COMMUNICATIONS, INC. +005000 (base 16) NEXO COMMUNICATIONS, INC. + 2ND FL., 160, MINGCHU ROAD + HSINCHU CITY + TW + +00-50-90 (hex) DCTRI +005090 (base 16) DCTRI + NO.40 XUE YUAN RD + + CN + +00-50-3B (hex) MEDIAFIRE CORPORATION +00503B (base 16) MEDIAFIRE CORPORATION + 11317 FREDERICK AVENUE + BELTSVILLE MD 20705 + US + +00-50-46 (hex) MENICX INTERNATIONAL CO., LTD. +005046 (base 16) MENICX INTERNATIONAL CO., LTD. + NO.9, MING TSUN ROAD + TAIWAN 310 TAIWAN 310 R.O.C. + TW + +00-50-41 (hex) Coretronic Corporation +005041 (base 16) Coretronic Corporation + NO.11, LI HSIN RD. + + TW + +00-50-B0 (hex) TECHNOLOGY ATLANTA CORPORATION +0050B0 (base 16) TECHNOLOGY ATLANTA CORPORATION + 500 Sugar Mill Road + Atlanta GA 30350 + US + +00-50-DD (hex) SERRA SOLDADURA, S.A. +0050DD (base 16) SERRA SOLDADURA, S.A. + POL. IND. ZONA FRANCA, + + ES + +00-50-63 (hex) OY COMSEL SYSTEM AB +005063 (base 16) OY COMSEL SYSTEM AB + TEGELBRUKSGATAN 5-7 + FIN-65100 VASA + FI + +00-50-8D (hex) ABIT COMPUTER CORPORATION +00508D (base 16) ABIT COMPUTER CORPORATION + 3F-7, NO. 79, SEC.1 + TAIPEI HSIEN + TW + +00-50-A0 (hex) DELTA COMPUTER SYSTEMS, INC. +0050A0 (base 16) DELTA COMPUTER SYSTEMS, INC. + 11719 NE 95TH STREET - STE. + VANCOUVER WA 98682-2444 + US + +00-50-66 (hex) AtecoM GmbH advanced telecomunication modules +005066 (base 16) AtecoM GmbH advanced telecomunication modules + KAISERSTR. 100 + D-52134 HERZOGENRATH + DE + +00-50-59 (hex) iBAHN +005059 (base 16) iBAHN + 10757 S. River Front Parkway + South Jordan UT 84095 + US + +00-50-D9 (hex) ENGETRON-ENGENHARIA ELETRONICA IND. e COM. LTDA +0050D9 (base 16) ENGETRON-ENGENHARIA ELETRONICA IND. e COM. LTDA + VIA SOCRATES M. BITTENCOURT, 1099 + 32010-010 Contagem MG + BR + +00-50-01 (hex) YAMASHITA SYSTEMS CORP. +005001 (base 16) YAMASHITA SYSTEMS CORP. + 5-7-12 IKEGAMI + OTA-KU TOKYO + JP + +00-50-67 (hex) AEROCOMM, INC. +005067 (base 16) AEROCOMM, INC. + 13256 W. 98TH STREET + LENEXA KS 66215 + US + +00-50-B6 (hex) GOOD WAY IND. CO., LTD. +0050B6 (base 16) GOOD WAY IND. CO., LTD. + 5F, NO.8, ALLEY 6, + TAIWAN R.O.C. + TW + +00-50-4B (hex) BARCONET N.V. +00504B (base 16) BARCONET N.V. + LUIPAARDSTRAAT 12 + + BE + +00-50-EA (hex) XEL COMMUNICATIONS, INC. +0050EA (base 16) XEL COMMUNICATIONS, INC. + 17101 E. OHIO DRIVE + AURORA CO 80017 + US + +00-50-C8 (hex) Addonics Technologies, Inc. +0050C8 (base 16) Addonics Technologies, Inc. + 1918 Junction Ave., + San Jose CA 95131 + US + +00-50-C4 (hex) IMD +0050C4 (base 16) IMD + HERBSTRASSE 8 + D-82178 PUCHHEIM + DE + +00-50-89 (hex) SAFETY MANAGEMENT SYSTEMS +005089 (base 16) SAFETY MANAGEMENT SYSTEMS + Burgemeester Burgerslaan 40 + NH Rosmalen 5245 + NL + +00-50-F4 (hex) SIGMATEK GMBH & CO. KG +0050F4 (base 16) SIGMATEK GMBH & CO. KG + A-5112 LAMPRECHTSHAUSEN, + + AT + +00-50-21 (hex) EIS INTERNATIONAL, INC. +005021 (base 16) EIS INTERNATIONAL, INC. + 1351 WASHINGTON BLVD. + STAMFORD CT 06902 + US + +00-50-5E (hex) DIGITEK MICROLOGIC S.A. +00505E (base 16) DIGITEK MICROLOGIC S.A. + SANT JOAN DE LA SALLE 6 + + ES + +00-50-E8 (hex) NOMADIX INC. +0050E8 (base 16) NOMADIX INC. + 2701 OCEAN PARK BLVD.-STE.#231 + SANTA MONICA CA 90405 + US + +00-50-AE (hex) FDK Co., Ltd +0050AE (base 16) FDK Co., Ltd + 2281 Washizu + Shizuoka-ken 431-0495 + JP + +00-50-E7 (hex) PARADISE INNOVATIONS (ASIA) +0050E7 (base 16) PARADISE INNOVATIONS (ASIA) + PTE. LTD. + SINGAPORE 554914 + SG + +00-50-FB (hex) VSK ELECTRONICS +0050FB (base 16) VSK ELECTRONICS + VENETIELAAN 39 + + BE + +00-90-73 (hex) GAIO TECHNOLOGY +009073 (base 16) GAIO TECHNOLOGY + OAK-YOKOHAMA BLDG. + NISHI-KU YOKOHAMA-CITY Kanagawa + JP + +00-90-7B (hex) E-TECH, INC. +00907B (base 16) E-TECH, INC. + 30, R&D ROAD 2 + HSINCHU + TW + +00-90-81 (hex) ALOHA NETWORKS, INC. +009081 (base 16) ALOHA NETWORKS, INC. + 1001A O'REILLY AVENUE + SAN FRANCISCO CA 94129-0472 + US + +00-90-1C (hex) mps Software Gmbh +00901C (base 16) mps Software Gmbh + LUDWIGSTR 36 + 85551 KIRCHHEIM + DE + +00-50-86 (hex) TELKOM SA, LTD. +005086 (base 16) TELKOM SA, LTD. + TELKOM LABORATORY + PRETORIA + ZA + +00-50-1A (hex) IQinVision +00501A (base 16) IQinVision + 33122 Valle Road + San Juan Capistrano CA 92675-4853 + US + +00-50-8F (hex) ASITA TECHNOLOGIES INT'L LTD. +00508F (base 16) ASITA TECHNOLOGIES INT'L LTD. + UNIT 2 BALLYBRIT BUSINESS PARK + + IE + +00-50-15 (hex) BRIGHT STAR ENGINEERING +005015 (base 16) BRIGHT STAR ENGINEERING + 19 ENFIELD DRIVE + ANDOVER MA 01810 + US + +00-50-57 (hex) BROADBAND ACCESS SYSTEMS +005057 (base 16) BROADBAND ACCESS SYSTEMS + 48 South Park St #208 + Montclair NJ 01752 + US + +00-50-88 (hex) AMANO CORPORATION +005088 (base 16) AMANO CORPORATION + 275, MAMEDO-CHO + 222-8558 + JP + +00-50-31 (hex) AEROFLEX LABORATORIES, INC. +005031 (base 16) AEROFLEX LABORATORIES, INC. + 35 SOUTH SERVICE ROAD + PLAINVIEW NY 11803 + US + +00-90-DB (hex) NEXT LEVEL COMMUNICATIONS +0090DB (base 16) NEXT LEVEL COMMUNICATIONS + 6085 STATE FARM DRIVE + ROHNERT PARK CA 94928 + US + +00-90-56 (hex) TELESTREAM, INC. +009056 (base 16) TELESTREAM, INC. + 848 GOLD FLAT RD., SUITE 1 + NEVADA CITY CA 95959 + US + +00-90-68 (hex) DVT CORP. +009068 (base 16) DVT CORP. + 1670 OAKBROOK DR. - STE. #330 + NORCROSS GA 30093 + US + +00-90-5E (hex) RAULAND-BORG CORPORATION +00905E (base 16) RAULAND-BORG CORPORATION + 3450 W. OAKTON ST. + SKOKIE IL 60076 + US + +00-90-AF (hex) J. MORITA MFG. CORP. +0090AF (base 16) J. MORITA MFG. CORP. + 680 HIGASHIHAMA MINAMI-CHO + FUSHIMI-KU, KYOTO 612-8213 + JP + +00-50-03 (hex) Xrite Inc +005003 (base 16) Xrite Inc + 4300 44TH Street, S.E. + Grand Rapids MI 49512 + US + +00-50-D3 (hex) DIGITAL AUDIO PROCESSING PTY. LTD. +0050D3 (base 16) DIGITAL AUDIO PROCESSING PTY. LTD. + PO BOX 40 + NSW 2138 + AU + +00-50-AD (hex) CommUnique Wireless Corp. +0050AD (base 16) CommUnique Wireless Corp. + 1070 MARINA VILLAGE PARKWAY + ALAMEDA CA 94501 + US + +00-50-AF (hex) INTERGON, INC. +0050AF (base 16) INTERGON, INC. + 5800 RANCHESTER DRIVE + HOUSTON TX 77036 + US + +00-90-34 (hex) IMAGIC, INC. +009034 (base 16) IMAGIC, INC. + 235 West Road #7 + Portsmouth NH 03801 + US + +00-90-AA (hex) INDIGO ACTIVE VISION SYSTEMS LIMITED +0090AA (base 16) INDIGO ACTIVE VISION SYSTEMS LIMITED + THE EDINBURGH TECHNOPOLE + Edinburgh EH26 OPJ + GB + +00-90-5B (hex) RAYMOND AND LAE ENGINEERING +00905B (base 16) RAYMOND AND LAE ENGINEERING + 208 COMMERCE DR., UNIT #3C + FORT COLLINS CO 80524 + US + +00-90-BC (hex) TELEMANN CO., LTD. +0090BC (base 16) TELEMANN CO., LTD. + 6F DONGSIN BLDG. + SEOUL, 135-270 + KR + +00-90-0A (hex) PROTON ELECTRONIC INDUSTRIAL CO., LTD. +00900A (base 16) PROTON ELECTRONIC INDUSTRIAL CO., LTD. + + PANCHIAO, Taipei County + TW + +00-90-F8 (hex) MEDIATRIX TELECOM +0090F8 (base 16) MEDIATRIX TELECOM + 4229 GARLOCK + QUEBEC J1L 2C8 + CA + +00-90-10 (hex) SIMULATION LABORATORIES, INC. +009010 (base 16) SIMULATION LABORATORIES, INC. + 10078 TYLER PLACE #A + IJAMSVILLE MD 21754 + US + +00-90-C6 (hex) OPTIM SYSTEMS, INC. +0090C6 (base 16) OPTIM SYSTEMS, INC. + 8201 GREENSBORO DR.-STE. #1000 + MCLEAN VA 22102 + US + +00-90-2E (hex) NAMCO LIMITED +00902E (base 16) NAMCO LIMITED + 1-1-32 SHIN-URASHIMA-CHO + KANAGAWA 221-0031 + JP + +00-90-37 (hex) ACUCOMM, INC. +009037 (base 16) ACUCOMM, INC. + 4633 OLD IRONSIDES - STE #310 + SANTA CLARA CA 95054 + US + +00-90-78 (hex) MER TELEMANAGEMENT SOLUTIONS, LTD. +009078 (base 16) MER TELEMANAGEMENT SOLUTIONS, LTD. + 5 HATSOREF STR. + HOLON + IL + +00-90-B8 (hex) ROHDE & SCHWARZ GMBH & CO. KG +0090B8 (base 16) ROHDE & SCHWARZ GMBH & CO. KG + POSTFACH: 80 14 69/ABT.: 3CK + D-81614 MUNCHEN + DE + +00-90-1A (hex) UNISPHERE SOLUTIONS +00901A (base 16) UNISPHERE SOLUTIONS + 5 CARLISLE ROAD + WESTFORD MA 01886 + US + +00-90-B5 (hex) NIKON CORPORATION +0090B5 (base 16) NIKON CORPORATION + Electronic Imaging Division, Designing D + TOKYO 140-8601 + JP + +00-90-05 (hex) PROTECH SYSTEMS CO., LTD. +009005 (base 16) PROTECH SYSTEMS CO., LTD. + 5F, NO. 34, LANE 80, SEC. 3 + TAIPEI + TW + +00-90-59 (hex) TELECOM DEVICE K.K. +009059 (base 16) TELECOM DEVICE K.K. + SANMIYANAGA BLDG. 3F, 1-5-12 + TOKYO 107 + JP + +00-90-CA (hex) ACCORD VIDEO TELECOMMUNICATIONS, LTD. +0090CA (base 16) ACCORD VIDEO TELECOMMUNICATIONS, LTD. + 10, MARTIN GEHL STR, PO BOX 3564 + Petach-Tikva 49130 + IL + +00-90-E9 (hex) JANZ COMPUTER AG +0090E9 (base 16) JANZ COMPUTER AG + Im Dörener Feld 8 + D-33100 Paderborn + DE + +00-90-EB (hex) SENTRY TELECOM SYSTEMS +0090EB (base 16) SENTRY TELECOM SYSTEMS + 8664 COMMERCE COURT + BURNABY BC V5A 4N7 + CA + +00-90-FE (hex) ELECOM CO., LTD. (LANEED DIV.) +0090FE (base 16) ELECOM CO., LTD. (LANEED DIV.) + TOKYU BANCHO BLDG. + Chiyoda-ku TOKYO 102-0081 + JP + +00-90-BB (hex) TAINET COMMUNICATION SYSTEM Corp. +0090BB (base 16) TAINET COMMUNICATION SYSTEM Corp. + 3 FL, NO. 6, ALLEY 23, LANE 91 SEC. 1 + Taipei + TW + +00-90-90 (hex) I-BUS +009090 (base 16) I-BUS + 9174 SKY PARK COURT + SAN DIEGO CA 92123 + US + +00-90-D5 (hex) EUPHONIX, INC. +0090D5 (base 16) EUPHONIX, INC. + 220 PORTAGE AVE. + PALO ALTO CA 94306 + US + +00-90-4A (hex) CONCUR SYSTEM TECHNOLOGIES +00904A (base 16) CONCUR SYSTEM TECHNOLOGIES + 2525 WALLINGWOOD DR.-STE. #804 + AUSTIN TX 78746 + US + +00-90-8F (hex) AUDIO CODES LTD. +00908F (base 16) AUDIO CODES LTD. + 3A NETANYAHU STREET + OR YEHUDA 60256 + IL + +00-90-9E (hex) Critical IO, LLC +00909E (base 16) Critical IO, LLC + 485 E. 17th Street + Costa Mesa CA 92627 + US + +00-10-92 (hex) NETCORE INC. +001092 (base 16) NETCORE INC. + 12F-2, 537, SEC.2 + HSINCHU + TW + +00-10-1C (hex) OHM TECHNOLOGIES INTL, LLC +00101C (base 16) OHM TECHNOLOGIES INTL, LLC + 4 EXECUTIVE CIRCLE, Suite 185 + IRVINE CA 92614 + US + +00-10-46 (hex) ALCORN MCBRIDE INC. +001046 (base 16) ALCORN MCBRIDE INC. + 3300 S. HIAWASSEE #105 + ORLANDO FL 32835 + US + +00-10-28 (hex) COMPUTER TECHNICA, INC. +001028 (base 16) COMPUTER TECHNICA, INC. + 3-5-19 HIGASHINAKA HAKATA-KU + FUKUOKA 816 + JP + +00-10-B7 (hex) COYOTE TECHNOLOGIES, LLC +0010B7 (base 16) COYOTE TECHNOLOGIES, LLC + 4360 PARK TERRACE DRIVE + WESTLAKE VILLAGE CA 91361 + US + +00-90-E5 (hex) TEKNEMA, INC. +0090E5 (base 16) TEKNEMA, INC. + 2656 E. BAYSHORE ROAD + PALO ALTO CA 94303 + US + +00-90-F4 (hex) LIGHTNING INSTRUMENTATION +0090F4 (base 16) LIGHTNING INSTRUMENTATION + BOVERESSES 50 + 1010 LAUSANNE + CH + +00-90-74 (hex) ARGON NETWORKS, INC. +009074 (base 16) ARGON NETWORKS, INC. + 25 PORTER ROAD + LITTLETON MA 01460 + US + +00-90-9F (hex) DIGI-DATA CORPORATION +00909F (base 16) DIGI-DATA CORPORATION + 7165 Columbia Gateway Drive + Columbia MD 21045 + US + +00-90-3B (hex) TriEMS Research Lab, Inc. +00903B (base 16) TriEMS Research Lab, Inc. + 1275 N. TUSTIN AVENUE + ANAHEIM CA 92807 + US + +00-10-C9 (hex) MITSUBISHI ELECTRONICS LOGISTIC SUPPORT CO. +0010C9 (base 16) MITSUBISHI ELECTRONICS LOGISTIC SUPPORT CO. + + Kamakura-city, Kanagawa 247 + JP + +00-04-00 (hex) LEXMARK INTERNATIONAL, INC. +000400 (base 16) LEXMARK INTERNATIONAL, INC. + 740 NEW CIRCLE ROAD + LEXINGTON KY 40550 + US + +00-10-C5 (hex) PROTOCOL TECHNOLOGIES, INC. +0010C5 (base 16) PROTOCOL TECHNOLOGIES, INC. + 4 FIRST STREET + BRIDGEWATER MA 02324 + US + +00-10-1A (hex) PictureTel Corp. +00101A (base 16) PictureTel Corp. + 100 MINUTEMAN ROAD, MS641 + ANDOVER MA 01810 + US + +00-10-47 (hex) ECHO ELETRIC CO. LTD. +001047 (base 16) ECHO ELETRIC CO. LTD. + NO.6-17-1-602 Higashi Hongou + Yokohama City 226 + JP + +00-90-3F (hex) AZTEC RADIOMEDIA +00903F (base 16) AZTEC RADIOMEDIA + 31, RUE DU CHEMINDEFER + 67200 STRASBOURG + FR + +00-10-43 (hex) A2 CORPORATION +001043 (base 16) A2 CORPORATION + 6-14-11 YUTAKA-CHO + TOKYO + JP + +00-10-A5 (hex) OXFORD INSTRUMENTS +0010A5 (base 16) OXFORD INSTRUMENTS + Halifax Road + Buckinghamshire HP12 3SE + GB + +00-10-D7 (hex) ARGOSY RESEARCH INC. +0010D7 (base 16) ARGOSY RESEARCH INC. + NO. 44, LANE 411, CHUNG HUA RD + + TW + +00-10-2C (hex) Lasat Networks A/S +00102C (base 16) Lasat Networks A/S + Skalhuse 13 + SK-9240 Nibe + DK + +00-10-FD (hex) COCOM A/S +0010FD (base 16) COCOM A/S + TELETONVEJ 8 + DK 2860 SOBORG + DK + +00-90-19 (hex) HERMES ELECTRONICS CO., LTD. +009019 (base 16) HERMES ELECTRONICS CO., LTD. + 3-2-12 YUSHIMA, BUNKYO-KU + TOKYO, 113-0034 + JP + +00-90-D8 (hex) WHITECROSS SYSTEMS +0090D8 (base 16) WHITECROSS SYSTEMS + 3A WATERSIDE PARK, COOKHAM RD + BERKSHIRE RG12 1RB + GB + +00-10-4E (hex) CEOLOGIC +00104E (base 16) CEOLOGIC + ZA DE PISSALOOP + 78192 TRAPPES + FR + +00-10-C2 (hex) WILLNET, INC. +0010C2 (base 16) WILLNET, INC. + JOWA-TAKANAWA BLDG. 8F + TOKYO + JP + +00-10-40 (hex) INTERMEC CORPORATION +001040 (base 16) INTERMEC CORPORATION + 6001 36TH AVE WEST + EVERETT WA 98203-9280 + US + +00-10-2E (hex) NETWORK SYSTEMS & TECHNOLOGIES PVT. LTD. +00102E (base 16) NETWORK SYSTEMS & TECHNOLOGIES PVT. LTD. + PLOT NO. 2, COCHIN EXPORT PROCESSING ZO + KAKKANAD, COCHIN 682 030 + IN + +00-10-B0 (hex) MERIDIAN TECHNOLOGY CORP. +0010B0 (base 16) MERIDIAN TECHNOLOGY CORP. + 11 MCBRIDE CORP. CENTER DR. + CHESTERFIELD MD 63005 + US + +00-10-21 (hex) ENCANTO NETWORKS, INC. +001021 (base 16) ENCANTO NETWORKS, INC. + 2953 BUNKER HILL LANE + SANTA CLARA CA 95054 + US + +00-10-64 (hex) DNPG, LLC +001064 (base 16) DNPG, LLC + 20 North Wentworth Avenue + Londonderry NH 03053 + US + +00-10-74 (hex) ATEN INTERNATIONAL CO., LTD. +001074 (base 16) ATEN INTERNATIONAL CO., LTD. + 12F, NO.101, SUNG CHIANG RD. + TAIPEI, 10428 + TW + +00-10-9E (hex) AWARE, INC. +00109E (base 16) AWARE, INC. + ONE OAK PARK + BEDFORD MA 01730 + US + +00-10-05 (hex) UEC COMMERCIAL +001005 (base 16) UEC COMMERCIAL + P.O. BOX 54, + 4300 DURBAN + ZA + +00-10-B8 (hex) ISHIGAKI COMPUTER SYSTEM CO. +0010B8 (base 16) ISHIGAKI COMPUTER SYSTEM CO. + 1-1-1, KYOBASHI, + Tokyo + JP + +00-10-8B (hex) LASERANIMATION SOLLINGER GMBH +00108B (base 16) LASERANIMATION SOLLINGER GMBH + CRELLESTR. 19/20 + D 10827 BERLIN + DE + +00-10-C7 (hex) DATA TRANSMISSION NETWORK +0010C7 (base 16) DATA TRANSMISSION NETWORK + 9110 W. DODGE RD. - STE.#200 + OMAHA NE 68114 + US + +00-10-70 (hex) CARADON TREND LTD. +001070 (base 16) CARADON TREND LTD. + P.O. BOX 34, HORSHAM + WEST SUSSEX, RH12 2YF ENGLAND + GB + +00-10-BA (hex) MARTINHO-DAVIS SYSTEMS, INC. +0010BA (base 16) MARTINHO-DAVIS SYSTEMS, INC. + 1260 OLD INNES ROAD + OTTAWA, ONTARIO K1B 3V3 + CA + +00-10-B4 (hex) ATMOSPHERE NETWORKS +0010B4 (base 16) ATMOSPHERE NETWORKS + 10460 BANDLEY DRIVE + CUPERTINO CA 95014 + US + +00-04-AC (hex) IBM Corp +0004AC (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-10-67 (hex) Ericsson +001067 (base 16) Ericsson + 250 Holger Way + SAN JOSE CA 95134 + US + +00-E0-7D (hex) NETRONIX, INC. +00E07D (base 16) NETRONIX, INC. + 340 THOR PLACE + BREA CA 92821 + US + +00-E0-28 (hex) APTIX CORPORATION +00E028 (base 16) APTIX CORPORATION + 2880 N. FIRST STREET + SAN JOSE CA 95134 + US + +00-E0-8C (hex) NEOPARADIGM LABS, INC. +00E08C (base 16) NEOPARADIGM LABS, INC. + 1735 N. FIRST ST., STE #108 + SAN JOSE CA 95112 + US + +00-E0-A1 (hex) HIMA PAUL HILDEBRANDT GmbH Co. KG +00E0A1 (base 16) HIMA PAUL HILDEBRANDT GmbH Co. KG + POSTBOX 1261 + D-68777 BRUEHL NEAR MANNHEIM + DE + +00-E0-88 (hex) LTX-Credence CORPORATION +00E088 (base 16) LTX-Credence CORPORATION + 825 UNIVERSITY AVENUE + NORWOOD MA 02062-2643 + US + +00-E0-5D (hex) UNITEC CO., LTD. +00E05D (base 16) UNITEC CO., LTD. + KISOGAWA-CHO ICHINOTORI 24 + HAGURI-GUN AICHI 493 + JP + +00-E0-5E (hex) JAPAN AVIATION ELECTRONICS INDUSTRY, LTD. +00E05E (base 16) JAPAN AVIATION ELECTRONICS INDUSTRY, LTD. + + TOKYO 196 JAPAN + JP + +00-E0-9D (hex) SARNOFF CORPORATION +00E09D (base 16) SARNOFF CORPORATION + CN 5300 + PRINCETON NJ 08543-5300 + US + +00-E0-58 (hex) PHASE ONE DENMARK A/S +00E058 (base 16) PHASE ONE DENMARK A/S + ROSKILDEVEJ 39 + DK-2000 FREDERIKSBERG + DK + +00-E0-76 (hex) DEVELOPMENT CONCEPTS, INC. +00E076 (base 16) DEVELOPMENT CONCEPTS, INC. + 1000 N. BROAD STREET + LANSDALE PA 19446 + US + +00-E0-F8 (hex) DICNA CONTROL AB +00E0F8 (base 16) DICNA CONTROL AB + STENYXEGATAN 21 C + 213 76 MALMOE + SE + +00-E0-DF (hex) KEYMILE GmbH +00E0DF (base 16) KEYMILE GmbH + Wohlenbergstraße 3 + 30179 Hannover + DE + +00-E0-F2 (hex) ARLOTTO COMNET, INC. +00E0F2 (base 16) ARLOTTO COMNET, INC. + 7F-4,55,TUNG-KUANG ROAD + HSIN-CHU, 300 + TW + +00-E0-E1 (hex) G2 NETWORKS, INC. +00E0E1 (base 16) G2 NETWORKS, INC. + 142 SO. SANTA CRUZ AVE. + LOS GATOS CA 95030-6702 + US + +00-E0-3D (hex) FOCON ELECTRONIC SYSTEMS A/S +00E03D (base 16) FOCON ELECTRONIC SYSTEMS A/S + DAMVANG, PO BOX 269 + DK-6400 SONDERBORG + DK + +00-E0-46 (hex) BENTLY NEVADA CORP. +00E046 (base 16) BENTLY NEVADA CORP. + PO BOX 157 + MINDEN NV 89423 + US + +00-E0-7B (hex) BAY NETWORKS +00E07B (base 16) BAY NETWORKS + 125 NAGOG PARK + ACTON MA 01720 + US + +00-E0-1D (hex) WebTV NETWORKS, INC. +00E01D (base 16) WebTV NETWORKS, INC. + 305 LYTTON AVE. + PALO ALTO CA 94301 + US + +00-E0-CD (hex) SAAB SENSIS CORPORATION +00E0CD (base 16) SAAB SENSIS CORPORATION + 85 Collamer Crossings + East Syracuse NY 13057 + US + +00-E0-8D (hex) PRESSURE SYSTEMS, INC. +00E08D (base 16) PRESSURE SYSTEMS, INC. + 34 RESEARCH DRIVE + HAMPTON VA 23666 + US + +00-E0-19 (hex) ING. GIORDANO ELETTRONICA +00E019 (base 16) ING. GIORDANO ELETTRONICA + VIA PIETRO COSSA 115/12 + 10146-TORINO + IT + +00-E0-47 (hex) InFocus Corporation +00E047 (base 16) InFocus Corporation + 27500 SW Parkway Avenue + Wilsonville OR 97070-8238 + US + +00-E0-C3 (hex) SAKAI SYSTEM DEVELOPMENT CORP. +00E0C3 (base 16) SAKAI SYSTEM DEVELOPMENT CORP. + PORTUS CENTER BLD., 4-45-1 + OSAKA-FU, 590 + JP + +00-E0-92 (hex) ADMTEK INCORPORATED +00E092 (base 16) ADMTEK INCORPORATED + 1962 ZANKER ROAD + SAN JOSE CA 95112 + US + +00-E0-FF (hex) SECURITY DYNAMICS TECHNOLOGIES, Inc. +00E0FF (base 16) SECURITY DYNAMICS TECHNOLOGIES, Inc. + 20 CROSBY DRIVE + BEDFORD MA 01730 + US + +00-E0-AB (hex) DIMAT S.A. +00E0AB (base 16) DIMAT S.A. + C/BISCAIA 383 3 + 08023 BARCELONA + ES + +00-E0-30 (hex) MELITA INTERNATIONAL CORP. +00E030 (base 16) MELITA INTERNATIONAL CORP. + 5051 PEACHTREE CORNERS CIRCLE + NORCROSS GA 30092 + US + +00-E0-33 (hex) E.E.P.D. GmbH +00E033 (base 16) E.E.P.D. GmbH + ROEMER-STRASSE 4 + 85229 MARKT INDERSDORF + DE + +00-E0-A2 (hex) MICROSLATE INC. +00E0A2 (base 16) MICROSLATE INC. + 9625 IGNACE - STE. D + BROSSARD QC J4Y 2P3 + CA + +00-E0-79 (hex) A.T.N.R. +00E079 (base 16) A.T.N.R. + BP 966 + 91976 COURTABOEUF + FR + +00-E0-75 (hex) Verilink Corporation +00E075 (base 16) Verilink Corporation + 127 Jetplex Circle + Madison AL 35758 + US + +00-60-39 (hex) SanCom Technology, Inc. +006039 (base 16) SanCom Technology, Inc. + 7719 WOOD HOLLOW DRIVE + AUSTIN TX 78731 + US + +00-60-49 (hex) VINA TECHNOLOGIES +006049 (base 16) VINA TECHNOLOGIES + 6 UNION SQUARE - STE F + UNION CITY CA 94587 + US + +00-60-8D (hex) UNIPULSE CORP. +00608D (base 16) UNIPULSE CORP. + 2-7, SENGENDAI-NISHI + SAITAMA 343 + JO + +00-E0-2E (hex) SPC ELECTRONICS CORPORATION +00E02E (base 16) SPC ELECTRONICS CORPORATION + 2-1-3 SHIBASAKI, CHOFU-SHI + TOKYO, 182 + JP + +00-E0-9A (hex) Positron Inc. +00E09A (base 16) Positron Inc. + 5101 Buchan Street + Montreal, Québec H4P 2R9 + CA + +00-E0-3E (hex) ALFATECH, INC. +00E03E (base 16) ALFATECH, INC. + SHIN-OSAKA EITO BLDG. + OSAKA + JP + +00-60-99 (hex) SBE, Inc. +006099 (base 16) SBE, Inc. + 4000 Executive Parkway + San Ramon CA 94583 + US + +00-60-B3 (hex) Z-COM, INC. +0060B3 (base 16) Z-COM, INC. + 7F-2, NO.9, PROSPERITY 1ST RD. + HSINCHU + TW + +00-60-02 (hex) SCREEN SUBTITLING SYSTEMS, LTD +006002 (base 16) SCREEN SUBTITLING SYSTEMS, LTD + THE OLD RECTORY + CLAYDON IPSWICH IP6 OEQ + GB + +00-60-89 (hex) XATA +006089 (base 16) XATA + 151 EAST CLIFF ROAD-STE.#10 + BURNSVILLE MN 55337 + US + +00-60-21 (hex) DSC CORPORATION +006021 (base 16) DSC CORPORATION + RECRUIT-SHINOHTSUKA BLDG., + TOKYO 170 + JP + +00-60-B8 (hex) CORELIS Inc. +0060B8 (base 16) CORELIS Inc. + 12607 Hiddencreek Way + Cerritos CA 90703 + US + +00-E0-AA (hex) ELECTROSONIC LTD. +00E0AA (base 16) ELECTROSONIC LTD. + HAWLEY MILL, HAWLEY RD. + DARTFORD, KENT DA2 7SY + GB + +00-E0-10 (hex) HESS SB-AUTOMATENBAU GmbH +00E010 (base 16) HESS SB-AUTOMATENBAU GmbH + HINDENBURGSTRASSE 27-29 + D-71106 MAGSTADT + DE + +00-E0-D2 (hex) VERSANET COMMUNICATIONS, INC. +00E0D2 (base 16) VERSANET COMMUNICATIONS, INC. + 628 N. DIAMOND BAR BLVD. + DIAMOND BAR CA 91765 + US + +00-60-CE (hex) ACCLAIM COMMUNICATIONS +0060CE (base 16) ACCLAIM COMMUNICATIONS + 5000 OLD IRONSIDES DRIVE + SANTA CLARA CA 95054 + US + +00-60-36 (hex) AIT Austrian Institute of Technology GmbH +006036 (base 16) AIT Austrian Institute of Technology GmbH + Donau-City-Straße 1 + Vienna 1220 + AT + +00-60-8E (hex) HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH +00608E (base 16) HE ELECTRONICS, TECHNOLOGIE & SYSTEMTECHNIK GmbH + AM GNEISENAUFLOT 8 + D-66538 NEUNHIRCHEN + DE + +00-60-1A (hex) KEITHLEY INSTRUMENTS +00601A (base 16) KEITHLEY INSTRUMENTS + 30500 BAINBRIDGE RD. + SOLON OH 44139 + US + +00-60-6A (hex) MITSUBISHI WIRELESS COMMUNICATIONS. INC. +00606A (base 16) MITSUBISHI WIRELESS COMMUNICATIONS. INC. + 2001 CHERRY DRIVE + BRASELTON GA 30517 + US + +00-60-AD (hex) MegaChips Corporation +0060AD (base 16) MegaChips Corporation + 4-1-6,Miyahara + Osaka 532-0003 + JP + +00-60-55 (hex) CORNELL UNIVERSITY +006055 (base 16) CORNELL UNIVERSITY + 729 Rhodes Hall + ITHACA NY 14850-4902 + US + +00-60-6D (hex) DIGITAL EQUIPMENT CORP. +00606D (base 16) DIGITAL EQUIPMENT CORP. + 550 KING STREET + LITTLETON MA 01460 + US + +00-60-B9 (hex) NEC Platforms, Ltd +0060B9 (base 16) NEC Platforms, Ltd + 2-6-1,Kitamikata,Takatsu-ku + Kawasaki 213-8511 + JP + +00-60-9C (hex) Perkin-Elmer Incorporated +00609C (base 16) Perkin-Elmer Incorporated + 710 Bridgeport Ave. + Shelton CT 06484 + US + +00-60-CF (hex) ALTEON NETWORKS, INC. +0060CF (base 16) ALTEON NETWORKS, INC. + 50 GREAT OAKS BLVD. + SAN JOSE CA 95119 + US + +00-60-75 (hex) PENTEK, INC. +006075 (base 16) PENTEK, INC. + 1 PARK WAY + UPPER SADDLE RIVER NJ 07458 + US + +00-60-B7 (hex) CHANNELMATIC, INC. +0060B7 (base 16) CHANNELMATIC, INC. + 1700 GILLESPIE WAY + EL CAJON CA 92020-0901 + US + +00-60-06 (hex) SOTEC CO., LTD +006006 (base 16) SOTEC CO., LTD + YOKOHAMA BASHAMICHI BLDG., + YOKOHAMA 231 + JP + +00-60-BA (hex) SAHARA NETWORKS, INC. +0060BA (base 16) SAHARA NETWORKS, INC. + 335 HIGHLAND AVE. + CHESHIRE CT 06410 + US + +00-60-98 (hex) HT COMMUNICATIONS +006098 (base 16) HT COMMUNICATIONS + 4480 SHOPPING LANE + SIMI VALLEY CA 93063 + US + +00-60-DE (hex) Kayser-Threde GmbH +0060DE (base 16) Kayser-Threde GmbH + Wolfratshauser Str. 48 + D-81379 Munich + DE + +00-60-D0 (hex) SNMP RESEARCH INCORPORATED +0060D0 (base 16) SNMP RESEARCH INCORPORATED + 3001 KIMBERLIN HEIGHTS ROAD + KNOXVILLE TN 37920-9716 + US + +00-60-15 (hex) NET2NET CORPORATION +006015 (base 16) NET2NET CORPORATION + 131 COOLIDGE STREET + HUDSON MA 01749 + US + +00-60-9D (hex) PMI FOOD EQUIPMENT GROUP +00609D (base 16) PMI FOOD EQUIPMENT GROUP + 701 RIDGE AVENUE + TROY OH 45374 + US + +00-60-A2 (hex) NIHON UNISYS LIMITED CO. +0060A2 (base 16) NIHON UNISYS LIMITED CO. + P.O. BOX 135 + SHINONOME 1-10-9 + JP + +00-60-84 (hex) DIGITAL VIDEO +006084 (base 16) DIGITAL VIDEO + 4920 AVALON RIDGE PKWY + NORCROSS GA 30092 + US + +00-60-2D (hex) ALERTON TECHNOLOGIES, INC. +00602D (base 16) ALERTON TECHNOLOGIES, INC. + 6670 185TH AVE. N.E. + REDMOND WA 98052 + US + +00-60-F8 (hex) Loran International Technologies Inc. +0060F8 (base 16) Loran International Technologies Inc. + 955 GREEN VALLEY CRESCENT + OTTAWA, ONTARIO K2C 3V4 + CA + +00-60-78 (hex) POWER MEASUREMENT LTD. +006078 (base 16) POWER MEASUREMENT LTD. + 2195 KEATING CROSS ROAD + SAANICHTON, B.C. V8M 2A5 + CA + +00-60-E8 (hex) HITACHI COMPUTER PRODUCTS (AMERICA), INC. +0060E8 (base 16) HITACHI COMPUTER PRODUCTS (AMERICA), INC. + 3101 TASMAN DRIVE + SANTA CLARA CA 95054 + US + +00-60-F6 (hex) NEXTEST COMMUNICATIONS PRODUCTS, INC. +0060F6 (base 16) NEXTEST COMMUNICATIONS PRODUCTS, INC. + TWO MID AMERICA PLAZA, STE.500 + OAKBROOK TERRACE IL 60181 + US + +00-60-72 (hex) VXL INSTRUMENTS, LIMITED +006072 (base 16) VXL INSTRUMENTS, LIMITED + PLOT NO. 17, KONAPPANA AGRAHARA + BANGALORE - 561 229 + IN + +00-60-51 (hex) QUALITY SEMICONDUCTOR +006051 (base 16) QUALITY SEMICONDUCTOR + 851 MARTIN AVENUE + SANTA CLARA CA 95050 + US + +00-60-92 (hex) MICRO/SYS, INC. +006092 (base 16) MICRO/SYS, INC. + 3447 OCEAN VIEW BLVD. + GLENDALE CA 91208 + US + +00-60-9E (hex) ASC X3 - INFORMATION TECHNOLOGY STANDARDS SECRETARIATS +00609E (base 16) ASC X3 - INFORMATION TECHNOLOGY STANDARDS SECRETARIATS + 1250 EYE STREET NW - STE #200 + WASHINGTON DC 20005 + US + +00-60-10 (hex) NETWORK MACHINES, INC. +006010 (base 16) NETWORK MACHINES, INC. + 255 OLD NEW BRUNSWICK RD., # N320 + PISCATAWAY NJ 08854 + US + +00-60-44 (hex) LITTON/POLY-SCIENTIFIC +006044 (base 16) LITTON/POLY-SCIENTIFIC + 2200 SOUTH MAIN STREET + BLACKSBURG VA 24060 + US + +00-60-04 (hex) COMPUTADORES MODULARES SA +006004 (base 16) COMPUTADORES MODULARES SA + AVDA MONTESIERRA S/N + 41020-SEVILLA + ES + +00-60-E2 (hex) QUEST ENGINEERING & DEVELOPMENT +0060E2 (base 16) QUEST ENGINEERING & DEVELOPMENT + 1345 EAST ROCK WREN ROAD + PHOENIX AZ 85048 + US + +00-60-B4 (hex) GLENAYRE R&D INC. +0060B4 (base 16) GLENAYRE R&D INC. + 1570 KOOTENAY STREET + VANCOUVER, BC V5K 5B8 + CA + +00-A0-1D (hex) Red Lion Controls, LP +00A01D (base 16) Red Lion Controls, LP + 20 Willow Springs Circle + York NY 17402 + US + +00-A0-A6 (hex) M.I. SYSTEMS, K.K. +00A0A6 (base 16) M.I. SYSTEMS, K.K. + 2-7-12-308 Satsukigaoka + Ikeda-Shi Osaka 563-0029 + JP + +00-A0-51 (hex) ANGIA COMMUNICATIONS. INC. +00A051 (base 16) ANGIA COMMUNICATIONS. INC. + 441 EAST BAY BLVD. + PROVO UTAH 84606 + US + +00-A0-13 (hex) TELTREND LTD. +00A013 (base 16) TELTREND LTD. + RINGWAY HOUSE, BELL ROAD + BASINGSTOKE HAMPSHIRE RG24 8F + GB + +00-A0-B9 (hex) EAGLE TECHNOLOGY, INC. +00A0B9 (base 16) EAGLE TECHNOLOGY, INC. + 6800 ORANGETHORPE AVE.UNIT + BUENA PARK CA 90620 + US + +00-A0-19 (hex) NEBULA CONSULTANTS, INC. +00A019 (base 16) NEBULA CONSULTANTS, INC. + 1449 DUNCAN DRIVE + DELTA, BC V4L 1R5 + CA + +00-A0-ED (hex) Brooks Automation, Inc. +00A0ED (base 16) Brooks Automation, Inc. + 15 Elizabeth Drive + Chelmsford MA 01824 + US + +00-60-CA (hex) HARMONIC SYSTEMS INCORPORATED +0060CA (base 16) HARMONIC SYSTEMS INCORPORATED + 199 1ST STREET - STE #302 + LOS ALTOS CA 94022 + US + +00-60-24 (hex) GRADIENT TECHNOLOGIES, INC. +006024 (base 16) GRADIENT TECHNOLOGIES, INC. + 2 MOUNT ROYAL AVENUE + MARLBORO MA 01752 + US + +00-60-AF (hex) PACIFIC MICRO DATA, INC. +0060AF (base 16) PACIFIC MICRO DATA, INC. + 16751 MILLIKAN AVENUE + IRVINE CA 92714 + US + +00-60-38 (hex) Nortel Networks +006038 (base 16) Nortel Networks + Global Operations Engineering + Brampton ON l6T 5P6 Cana + CA + +00-60-4F (hex) Tattile SRL +00604F (base 16) Tattile SRL + 552-51 AJIGAURA + IBARAKI, 311-12 + JP + +00-A0-D0 (hex) TEN X TECHNOLOGY, INC. +00A0D0 (base 16) TEN X TECHNOLOGY, INC. + 13091 POND SPRINGS ROAD, Suite B-200 + AUSTIN TX 78729 + US + +00-A0-BC (hex) VIASAT, INCORPORATED +00A0BC (base 16) VIASAT, INCORPORATED + 6155 El Camino Real + Carlsbad Ca 92009 + US + +00-A0-5B (hex) MARQUIP, INC. +00A05B (base 16) MARQUIP, INC. + 1245 E. WASHINGTON AVE. + MADISON WI 53703 + US + +00-A0-8C (hex) MultiMedia LANs, Inc. +00A08C (base 16) MultiMedia LANs, Inc. + 5600 EXECUTIVE CENTER DRIVE + CHARLOTTE NC 28212 + US + +00-A0-58 (hex) GLORY, LTD. +00A058 (base 16) GLORY, LTD. + 1-3-1 SHIMOTENO, HIMEJI + HYOGO PREF. 670 + JP + +00-A0-77 (hex) FUJITSU NEXION, INC. +00A077 (base 16) FUJITSU NEXION, INC. + 289 GREAT ROAD + ACTON MA 01720-4739 + US + +00-A0-A0 (hex) COMPACT DATA, LTD. +00A0A0 (base 16) COMPACT DATA, LTD. + 58 DITTON WALK + CAMBRIDGE CB5 8QE + GB + +00-A0-38 (hex) EMAIL ELECTRONICS +00A038 (base 16) EMAIL ELECTRONICS + P.O. BOX 154 + MOOROOLBARK, 3138 + AU + +00-A0-65 (hex) Symantec Corporation +00A065 (base 16) Symantec Corporation + 20330 Stevens Creek Blvd. + Cupertino CA 95014 + US + +00-A0-A3 (hex) RELIABLE POWER METERS +00A0A3 (base 16) RELIABLE POWER METERS + 400 BLOSSOM HILL ROAD + LOS GATOS CA 95032-4511 + US + +00-A0-1B (hex) PREMISYS COMMUNICATIONS, INC. +00A01B (base 16) PREMISYS COMMUNICATIONS, INC. + 48664 MILMONT DRIVE + FREMONT CA 94538 + US + +00-A0-55 (hex) Data Device Corporation +00A055 (base 16) Data Device Corporation + 105 Wilbur Place + Bohemia NY 11716 + US + +00-A0-74 (hex) PERCEPTION TECHNOLOGY +00A074 (base 16) PERCEPTION TECHNOLOGY + 40 SHAWMUT ROAD + CANTON MA 02021-1409 + US + +00-A0-7F (hex) GSM-SYNTEL, LTD. +00A07F (base 16) GSM-SYNTEL, LTD. + VICTORIA WORKS, QUEENS MILL RD + HD1 3PG ENGLAND + GB + +00-A0-29 (hex) COULTER CORPORATION +00A029 (base 16) COULTER CORPORATION + 11800 S.W. 147TH AVE. + MIAMI FL 33196 + US + +00-A0-87 (hex) Microsemi Corporation +00A087 (base 16) Microsemi Corporation + 400 March Road + Ontario K2K 3H4 + CA + +00-A0-43 (hex) AMERICAN TECHNOLOGY LABS, INC. +00A043 (base 16) AMERICAN TECHNOLOGY LABS, INC. + 115 WEST 3RD STREET + STEVENSVILLE MT 59870 + US + +00-A0-42 (hex) SPUR PRODUCTS CORP. +00A042 (base 16) SPUR PRODUCTS CORP. + 9288 W. EMERALD STREET + BOISE ID 83704 + US + +00-A0-C1 (hex) ORTIVUS MEDICAL AB +00A0C1 (base 16) ORTIVUS MEDICAL AB + BOX 513 + + SE + +00-A0-4F (hex) AMERITEC CORP. +00A04F (base 16) AMERITEC CORP. + 760 ARROW GRAND CIRCLE + COVINA CA 91722 + US + +00-A0-CF (hex) SOTAS, INC. +00A0CF (base 16) SOTAS, INC. + 2 RESEARCH PLACE, STE. + ROCKVILLE MD 20850 + US + +00-A0-72 (hex) OVATION SYSTEMS LTD. +00A072 (base 16) OVATION SYSTEMS LTD. + GREAT HASELEY TRAD. EST. + ENGLAND + GB + +00-A0-82 (hex) NKT ELEKTRONIK A/S +00A082 (base 16) NKT ELEKTRONIK A/S + NKT ALLE 85 + + DK + +00-A0-F0 (hex) TORONTO MICROELECTRONICS INC. +00A0F0 (base 16) TORONTO MICROELECTRONICS INC. + 5149 BRADCO BOULEVARD + L4W 2A6 + CA + +00-A0-D7 (hex) KASTEN CHASE APPLIED RESEARCH +00A0D7 (base 16) KASTEN CHASE APPLIED RESEARCH + 5100 ORBITOR DRIVE + L4W 4Z4 + CA + +00-A0-F1 (hex) MTI +00A0F1 (base 16) MTI + 4905 E. LA PALMA AVENUE + ANAHEIM CA 92807 + US + +00-A0-B3 (hex) ZYKRONIX +00A0B3 (base 16) ZYKRONIX + 7248 SOUTH TUCSON WAY + ENGLEWOOD CO 80112 + US + +00-A0-FF (hex) TELLABS OPERATIONS, INC. +00A0FF (base 16) TELLABS OPERATIONS, INC. + 1000 REMINGTON BLVD. + 60440 + US + +00-A0-E5 (hex) NHC COMMUNICATIONS +00A0E5 (base 16) NHC COMMUNICATIONS + 5450 COTE DE LIESSE + MONTREAL, QUEBEC H4P 1A5 + CA + +00-A0-36 (hex) APPLIED NETWORK TECHNOLOGY +00A036 (base 16) APPLIED NETWORK TECHNOLOGY + 319 LITTLETON ROAD--STE #101 + WESTFORD MA 01886-4133 + US + +00-A0-D2 (hex) ALLIED TELESIS INTERNATIONAL CORPORATION +00A0D2 (base 16) ALLIED TELESIS INTERNATIONAL CORPORATION + 950 KIFER ROAD + SUNNYVALE CA 94086 + US + +00-A0-9B (hex) QPSX COMMUNICATIONS, LTD. +00A09B (base 16) QPSX COMMUNICATIONS, LTD. + 33 RICHARDSON STREET + Western 00000 + AU + +00-A0-00 (hex) CENTILLION NETWORKS, INC. +00A000 (base 16) CENTILLION NETWORKS, INC. + 359 RAVENDALE DRIVE + MOUNTAIN VIEW CA 94043 + US + +00-A0-8A (hex) BROOKTROUT TECHNOLOGY, INC. +00A08A (base 16) BROOKTROUT TECHNOLOGY, INC. + 144 GOULD STREET- SUITE #200 + NEEDHAM MA 02194 + US + +00-A0-7B (hex) DAWN COMPUTER INCORPORATION +00A07B (base 16) DAWN COMPUTER INCORPORATION + 6 KEXUEYUAN SOUTH ROAD + + CN + +00-A0-5C (hex) INVENTORY CONVERSION, INC./ +00A05C (base 16) INVENTORY CONVERSION, INC./ + NEKOTECH DIVISION + HAMPTON NH 03842 + US + +00-20-0F (hex) EBRAINS Inc +00200F (base 16) EBRAINS Inc + Tachibana Bldg + Taito-ku Tokyo 110-0003 + JP + +00-A0-D3 (hex) INSTEM COMPUTER SYSTEMS, LTD. +00A0D3 (base 16) INSTEM COMPUTER SYSTEMS, LTD. + WALTON INDUSTRIAL ESTATE + + GB + +00-A0-B4 (hex) TEXAS MICROSYSTEMS, INC. +00A0B4 (base 16) TEXAS MICROSYSTEMS, INC. + 5959 CORPORATE DRIVE + HOUSTON TX 77036 + US + +00-A0-60 (hex) ACER PERIPHERALS, INC. +00A060 (base 16) ACER PERIPHERALS, INC. + 9F, 135 CHIAN KUO N. RD. SEC 2 + + TW + +00-A0-83 (hex) ASIMMPHONY TURKEY +00A083 (base 16) ASIMMPHONY TURKEY + ELECTRONICS, LTD. + V7C 4N1 + CA + +00-A0-AA (hex) SPACELABS MEDICAL +00A0AA (base 16) SPACELABS MEDICAL + 5150 220 Ave SE + Issaquah WA 98027 + US + +00-A0-3B (hex) TOSHIN ELECTRIC CO., LTD. +00A03B (base 16) TOSHIN ELECTRIC CO., LTD. + 3FL. RIVER-STONE 3RD. BLG.234 + 213 + JP + +00-A0-F3 (hex) STAUBLI +00A0F3 (base 16) STAUBLI + 183 RUE DES USINES + + FR + +00-20-DF (hex) KYOSAN ELECTRIC MFG. CO., LTD. +0020DF (base 16) KYOSAN ELECTRIC MFG. CO., LTD. + 2-29, HEIAN-CHO, TSURUMI-KU + + JP + +00-20-C7 (hex) AKAI Professional M.I. Corp. +0020C7 (base 16) AKAI Professional M.I. Corp. + 1-3, Hiranuma 1-Chome, + 220-0023 + JP + +00-A0-04 (hex) NETPOWER, INC. +00A004 (base 16) NETPOWER, INC. + 545 OAKMEAD PARKWAY + SUNNYVALE CA 94086 + US + +00-20-29 (hex) TELEPROCESSING PRODUCTS, INC. +002029 (base 16) TELEPROCESSING PRODUCTS, INC. + 4565 E. INDUSTRIAL STREET + SIMI VALLEY CA 93063 + US + +00-20-69 (hex) ISDN SYSTEMS CORPORATION +002069 (base 16) ISDN SYSTEMS CORPORATION + 8320 OLD COURTHOUSE RD. + VIENNA VA 22182 + US + +00-20-8B (hex) LAPIS TECHNOLOGIES, INC. +00208B (base 16) LAPIS TECHNOLOGIES, INC. + 1100 MARINA VILLAGE PKWY + ALAMEDA CA 94501 + US + +00-20-2B (hex) ADVANCED TELECOMMUNICATIONS MODULES, LTD. +00202B (base 16) ADVANCED TELECOMMUNICATIONS MODULES, LTD. + + Cambridge CB3 OBL + GB + +00-20-6B (hex) KONICA MINOLTA HOLDINGS, INC. +00206B (base 16) KONICA MINOLTA HOLDINGS, INC. + 1-6-1, Marunouchi, + Tokyo 100-0005 + JP + +00-20-04 (hex) YAMATAKE-HONEYWELL CO., LTD. +002004 (base 16) YAMATAKE-HONEYWELL CO., LTD. + 54 SUZUKAWA, ISEHARA + KANAGAWA 259-11 + JP + +00-20-15 (hex) ACTIS COMPUTER SA +002015 (base 16) ACTIS COMPUTER SA + 16 CHEMIN DES AULX + + CH + +00-20-99 (hex) BON ELECTRIC CO., LTD. +002099 (base 16) BON ELECTRIC CO., LTD. + 4-4 28, MIZUDO-CHO + HYOGO HYOGO + JP + +00-20-F9 (hex) PARALINK NETWORKS, INC. +0020F9 (base 16) PARALINK NETWORKS, INC. + 4F, NO. 27, SEC.3, PATEH RD. + TAIPEI + TW + +00-20-92 (hex) CHESS ENGINEERING B.V. +002092 (base 16) CHESS ENGINEERING B.V. + NIEUWE GRACHT 74 + + NL + +00-20-43 (hex) NEURON COMPANY LIMITED +002043 (base 16) NEURON COMPANY LIMITED + 15 KWAI YI ROAD, BLOCK 2, + KWAI CHUNG, N.T. + HK + +00-20-71 (hex) IBR GMBH +002071 (base 16) IBR GMBH + KOHLERSTR. 45 + D-46286 DORSTEN + DE + +00-20-7C (hex) AUTEC GMBH +00207C (base 16) AUTEC GMBH + BAHNHOFSTR. 57 + 55234 FRAMERSHEIM + DE + +00-20-57 (hex) TITZE DATENTECHNIK GmbH +002057 (base 16) TITZE DATENTECHNIK GmbH + DIESELSTRASSE 10 + DS-71272 RENNINGEN-2 + DE + +00-20-E5 (hex) APEX DATA, INC. +0020E5 (base 16) APEX DATA, INC. + 6624 OWENS DRIVE + PLEASANTON CA 94588 + US + +00-20-87 (hex) MEMOTEC, INC. +002087 (base 16) MEMOTEC, INC. + 7755 Henri-Bourassa + MONTREAL, QUEBEC H4S 1P7 + CA + +00-20-BC (hex) Long Reach Networks Pty Ltd +0020BC (base 16) Long Reach Networks Pty Ltd + Unit 3, 118-122 Bowden St + MEADOWBANK NSW 2114 + AU + +00-C0-C0 (hex) SHORE MICROSYSTEMS, INC. +00C0C0 (base 16) SHORE MICROSYSTEMS, INC. + 23 POCAHONTAS AVENUE + OCEANPORT NJ 07757 + US + +00-C0-0C (hex) RELIA TECHNOLGIES +00C00C (base 16) RELIA TECHNOLGIES + 1F., NO. 24, INDUSTRY E. 9TH + TAIWAN TAIWAN R.O.C. + TW + +00-C0-73 (hex) XEDIA CORPORATION +00C073 (base 16) XEDIA CORPORATION + 301 BALLARDVALE STREET + WILMINGTON MA 01887 + US + +00-C0-D4 (hex) AXON NETWORKS, INC. +00C0D4 (base 16) AXON NETWORKS, INC. + 104 SPRUCE STREET + WATERTOWN MA 02172 + US + +00-C0-CD (hex) COMELTA, S.A. +00C0CD (base 16) COMELTA, S.A. + AVDA. PARC TECNOLOGIC, 4 + + ES + +00-20-ED (hex) GIGA-BYTE TECHNOLOGY CO., LTD. +0020ED (base 16) GIGA-BYTE TECHNOLOGY CO., LTD. + 365 CLOVERLEAF + BALDWIN PARK CA 91706 + US + +00-20-85 (hex) Eaton Corporation +002085 (base 16) Eaton Corporation + 8380 Capital Blvd. + RALEIGH NC 27616 + US + +00-20-CD (hex) HYBRID NETWORKS, INC. +0020CD (base 16) HYBRID NETWORKS, INC. + 10201 BUBB ROAD + CUPERTINO CA 95014-4167 + US + +00-20-2E (hex) DAYSTAR DIGITAL +00202E (base 16) DAYSTAR DIGITAL + 5556 ATLANTA HIGHWAY + FLOWERY BRANCH GA 30542 + US + +00-20-B3 (hex) Tattile SRL +0020B3 (base 16) Tattile SRL + 3 APOLLO PLACE + + AU + +00-20-EE (hex) GTECH CORPORATION +0020EE (base 16) GTECH CORPORATION + 55 TECHNOLOGY WAY + WEST GREENWICH RI 02817 + US + +00-20-4C (hex) MITRON COMPUTER PTE LTD. +00204C (base 16) MITRON COMPUTER PTE LTD. + 1020 HOUGANG AVENUE 1 #03-3504 + SINGAPORE 1953 + SG + +00-20-17 (hex) ORBOTECH +002017 (base 16) ORBOTECH + INDUSTRIAL ZONE + + IL + +00-20-93 (hex) LANDINGS TECHNOLOGY CORP. +002093 (base 16) LANDINGS TECHNOLOGY CORP. + 163 WATER STREET + EXETER NH 03833 + US + +00-20-63 (hex) WIPRO INFOTECH LTD. +002063 (base 16) WIPRO INFOTECH LTD. + UNITS 47-48, SDF BLOCK VII + + + +00-20-16 (hex) SHOWA ELECTRIC WIRE & CABLE CO +002016 (base 16) SHOWA ELECTRIC WIRE & CABLE CO + NO. 20-25, SEISHIN 8-CHOME + 229 + JP + +00-20-4D (hex) INOVIS GMBH +00204D (base 16) INOVIS GMBH + HANNS-BRAUN STRASSE 50 + + DE + +00-20-5F (hex) GAMMADATA COMPUTER GMBH +00205F (base 16) GAMMADATA COMPUTER GMBH + GUTENBERGSTR. 13 + + DE + +00-20-1F (hex) BEST POWER TECHNOLOGY, INC. +00201F (base 16) BEST POWER TECHNOLOGY, INC. + P.O. BOX 280 + NECEDAH WI 54646 + US + +00-20-B6 (hex) AGILE NETWORKS, INC. +0020B6 (base 16) AGILE NETWORKS, INC. + 200 BAKER AVENUE + CONCORD MA 01742 + US + +00-20-D1 (hex) MICROCOMPUTER SYSTEMS (M) SDN. +0020D1 (base 16) MICROCOMPUTER SYSTEMS (M) SDN. + 23-25, JALAN JEJAKA TUJUH + + MY + +00-20-CE (hex) LOGICAL DESIGN GROUP, INC. +0020CE (base 16) LOGICAL DESIGN GROUP, INC. + 6301 CHAPEL HILL ROAD + RALEIGH NC 27607 + US + +00-20-14 (hex) GLOBAL VIEW CO., LTD. +002014 (base 16) GLOBAL VIEW CO., LTD. + 4F, NO. 23, LANE 306 + TAIWAN R.O.C. + TW + +00-20-C2 (hex) TEXAS MEMORY SYSTEMS, INC. +0020C2 (base 16) TEXAS MEMORY SYSTEMS, INC. + 11200 WESTHEIMER RD-STE#1000 + HOUSTON TX 77042 + US + +00-C0-F3 (hex) NETWORK COMMUNICATIONS CORP. +00C0F3 (base 16) NETWORK COMMUNICATIONS CORP. + 5501 GREEN VALLEY DRIVE + BLOOMINGTON MN 55437-1085 + US + +00-20-56 (hex) NEOPRODUCTS +002056 (base 16) NEOPRODUCTS + 25 CHAPMAN STREET + + AU + +00-20-42 (hex) DATAMETRICS CORP. +002042 (base 16) DATAMETRICS CORP. + 8966 COMANCHE AVE. + CHATSWORTH CA 91311 + US + +00-20-78 (hex) RUNTOP, INC. +002078 (base 16) RUNTOP, INC. + 5/F, NO. 10, ALLEY 8, LANE 45 + TAIWAN R.O.C. + TW + +00-20-06 (hex) GARRETT COMMUNICATIONS, INC. +002006 (base 16) GARRETT COMMUNICATIONS, INC. + 48531 WARMSPRINGS BLVD. + FREMONT CA 94539 + US + +00-20-24 (hex) PACIFIC COMMUNICATION SCIENCES +002024 (base 16) PACIFIC COMMUNICATION SCIENCES + 9645 SCRANTON ROAD + SAN DIEGO CA 92121 + US + +00-20-5D (hex) NANOMATIC OY +00205D (base 16) NANOMATIC OY + PUISTOLAN RAITTI 4 + + FI + +00-C0-05 (hex) LIVINGSTON ENTERPRISES, INC. +00C005 (base 16) LIVINGSTON ENTERPRISES, INC. + 6920 KOLL CENTER PARKWAY #220 + PLEASANTON CA 94566 + US + +00-C0-77 (hex) DAEWOO TELECOM LTD. +00C077 (base 16) DAEWOO TELECOM LTD. + PRODUCTS DESIGN DEPT. 1 + SEOUL SEOUL KOREA + KR + +00-C0-C8 (hex) MICRO BYTE PTY. LTD. +00C0C8 (base 16) MICRO BYTE PTY. LTD. + 197 SHERBOURNE RD. + AUSTRALIA 3094 + AU + +00-C0-69 (hex) Axxcelera Broadband Wireless +00C069 (base 16) Axxcelera Broadband Wireless + 111 Castilian Drive + Santa Barbara CA 93117 + US + +00-C0-67 (hex) UNITED BARCODE INDUSTRIES +00C067 (base 16) UNITED BARCODE INDUSTRIES + 12240 INDIAN CREEK COURT + BELTSVILLE MD 20705 + US + +00-C0-A3 (hex) DUAL ENTERPRISES CORPORATION +00C0A3 (base 16) DUAL ENTERPRISES CORPORATION + 9TH FLOOR 48 NAN-KANG ROAD + TAIWAN TAIWAN R.O.C. + TW + +00-C0-18 (hex) LANART CORPORATION +00C018 (base 16) LANART CORPORATION + 145 ROSEMARY STREET + NEEDHAM MA 02194 + US + +00-9D-8E (hex) CARDIAC RECORDERS, INC. +009D8E (base 16) CARDIAC RECORDERS, INC. + 34 SCARBORO ROAD + UNITED KINGDOM + GB + +00-BB-01 (hex) OCTOTHORPE CORP. +00BB01 (base 16) OCTOTHORPE CORP. + 285 WEST GREEN STREET + PASADENA CA 91105 + US + +00-C0-33 (hex) TELEBIT COMMUNICATIONS APS +00C033 (base 16) TELEBIT COMMUNICATIONS APS + SKANDERBORGVEJ 234 + + DK + +00-C0-90 (hex) PRAIM S.R.L. +00C090 (base 16) PRAIM S.R.L. + VIA MACCANI, 169 + ITALY + + +00-C0-DE (hex) ZCOMM, INC. +00C0DE (base 16) ZCOMM, INC. + 1050 C EAST DUANE AVENUE + SUNNYVALE CA 94086 + US + +00-C0-13 (hex) NETRIX +00C013 (base 16) NETRIX + 13595 DULLES TECHNOLOGY DRIVE + HERNDON VA 22071 + US + +00-C0-6B (hex) OSI PLUS CORPORATION +00C06B (base 16) OSI PLUS CORPORATION + 2-1-23 NAKAMEGURO + + JP + +00-C0-4C (hex) DEPARTMENT OF FOREIGN AFFAIRS +00C04C (base 16) DEPARTMENT OF FOREIGN AFFAIRS + & TRADE + + AU + +00-C0-7C (hex) HIGHTECH INFORMATION +00C07C (base 16) HIGHTECH INFORMATION + SYSTEM LTD. + HONG KONG + HK + +00-C0-B8 (hex) FRASER'S HILL LTD. +00C0B8 (base 16) FRASER'S HILL LTD. + 27502 W. GILL ROAD + MORRISTOWN AZ 85342 + US + +00-C0-62 (hex) IMPULSE TECHNOLOGY +00C062 (base 16) IMPULSE TECHNOLOGY + 210 DAHLONEGA ST.#204 + CUMMING GA 30130 + US + +00-C0-EC (hex) DAUPHIN TECHNOLOGY +00C0EC (base 16) DAUPHIN TECHNOLOGY + 450 EISENHOWER LANE NORTH + LOMBARD IL 60148 + US + +00-C0-86 (hex) THE LYNK CORPORATION +00C086 (base 16) THE LYNK CORPORATION + 101 QUEENS DRIVE + KING OF PRUSSIA PA 19406 + US + +00-C0-58 (hex) DATAEXPERT CORP. +00C058 (base 16) DATAEXPERT CORP. + 1156 SONOPRA COURTN-KANG RD. + SUNNYVALE CA 94086 + US + +00-C0-D0 (hex) RATOC SYSTEM INC. +00C0D0 (base 16) RATOC SYSTEM INC. + ASAHI NAMBA BLDG. + 556 + JP + +00-C0-BF (hex) TECHNOLOGY CONCEPTS, LTD. +00C0BF (base 16) TECHNOLOGY CONCEPTS, LTD. + GRANGE ESTATE + UNITED KINGDOM + GB + +00-C0-BA (hex) NETVANTAGE +00C0BA (base 16) NETVANTAGE + 201 CONTINENTAL BLVD.-STE.#201 + EL SECUNDO CA 90245 + US + +00-C0-5E (hex) VARI-LITE, INC. +00C05E (base 16) VARI-LITE, INC. + 201 REGAL ROW + DALLAS TX 75247 + US + +00-C0-D5 (hex) Werbeagentur Jürgen Siebert +00C0D5 (base 16) Werbeagentur Jürgen Siebert + Im Klostergarten 8 + D-50321 Brühl + DE + +00-C0-63 (hex) MORNING STAR TECHNOLOGIES, INC +00C063 (base 16) MORNING STAR TECHNOLOGIES, INC + 1760 ZOLLINGER ROAD + COLUMBUS OH 43221 + US + +00-C0-21 (hex) NETEXPRESS +00C021 (base 16) NETEXPRESS + 989 EAST HILLSDALE BLVD. + FOSTER CITY CA 94404-2113 + US + +00-C0-DB (hex) IPC CORPORATION (PTE) LTD. +00C0DB (base 16) IPC CORPORATION (PTE) LTD. + 122 EUNOS AVE., 7 #05-10 + SINGAPORE 1440 + SG + +00-C0-9B (hex) RELIANCE COMM/TEC, R-TEC +00C09B (base 16) RELIANCE COMM/TEC, R-TEC + SYSTEMS INC. + BEDFORD TX 76021 + US + +00-C0-6A (hex) ZAHNER-ELEKTRIK GMBH & CO. KG +00C06A (base 16) ZAHNER-ELEKTRIK GMBH & CO. KG + P.O. BOX 1846 + + DE + +00-C0-E3 (hex) OSITECH COMMUNICATIONS, INC. +00C0E3 (base 16) OSITECH COMMUNICATIONS, INC. + 679 SOUTHGATE DRIVE + CANADA N1G 4S2 + CA + +00-C0-FE (hex) APTEC COMPUTER SYSTEMS, INC. +00C0FE (base 16) APTEC COMPUTER SYSTEMS, INC. + P.O. BOX 6750 + PORTLAND OR 97228-6750 + US + +00-C0-16 (hex) ELECTRONIC THEATRE CONTROLS +00C016 (base 16) ELECTRONIC THEATRE CONTROLS + 3030 LAURA LANE + MIDDLETON WI 53562 + US + +00-C0-BC (hex) TELECOM AUSTRALIA/CSSC +00C0BC (base 16) TELECOM AUSTRALIA/CSSC + LOCKED BAG 8812 + + AU + +00-C0-C1 (hex) QUAD/GRAPHICS, INC. +00C0C1 (base 16) QUAD/GRAPHICS, INC. + N63 W23075 HWY 74 + SUSSEX WI 53089 + US + +00-C0-89 (hex) TELINDUS DISTRIBUTION +00C089 (base 16) TELINDUS DISTRIBUTION + GELDENAAKSEBAAN 335 + + BE + +00-C0-B0 (hex) GCC TECHNOLOGIES,INC. +00C0B0 (base 16) GCC TECHNOLOGIES,INC. + 580 WINTER STREET + WALTHAM MA 02154 + US + +00-C0-0A (hex) MICRO CRAFT +00C00A (base 16) MICRO CRAFT + 2-4-3 NISHIFURUMATSU + + JP + +00-C0-74 (hex) TOYODA AUTOMATIC LOOM +00C074 (base 16) TOYODA AUTOMATIC LOOM + WORKS, LTD. + 448 + JP + +00-40-4E (hex) FLUENT, INC. +00404E (base 16) FLUENT, INC. + 594 WORCESTER ROAD-STE.#308 + NATICK MA 01760 + US + +00-40-8D (hex) THE GOODYEAR TIRE & RUBBER CO. +00408D (base 16) THE GOODYEAR TIRE & RUBBER CO. + 1144 EAST MARKET STREET + AKRON OH 44316 + US + +00-40-1B (hex) PRINTER SYSTEMS CORP. +00401B (base 16) PRINTER SYSTEMS CORP. + 207 PERRY PARKWAY + GAITHERSBURG MD 20877-2142 + US + +00-40-A3 (hex) MICROUNITY SYSTEMS ENGINEERING +0040A3 (base 16) MICROUNITY SYSTEMS ENGINEERING + 255 CASPIAN DRIVE + SUNNYVALE CA 94089-1015 + US + +00-40-B3 (hex) ParTech Inc. +0040B3 (base 16) ParTech Inc. + 8383 Seneca Turnpike + NEW HARTFORD NY 13413 + US + +00-40-1D (hex) INVISIBLE SOFTWARE, INC. +00401D (base 16) INVISIBLE SOFTWARE, INC. + 1142 CHESS DRIVE + FOSTER CITY CA 94404 + US + +00-C0-CA (hex) ALFA, INC. +00C0CA (base 16) ALFA, INC. + 11-1, INDUSTRY EAST ROAD IV + TAIWAN + TW + +00-C0-6C (hex) SVEC COMPUTER CORP. +00C06C (base 16) SVEC COMPUTER CORP. + 3F, 531-1 CHUNG CHENG RD. + TAIWAN TAIWAN R.O.C. + TW + +00-40-FF (hex) TELEBIT CORPORATION +0040FF (base 16) TELEBIT CORPORATION + 1315 CHESAPEAKE TERRACE + SUNNYVALE CA 94089-1100 + US + +00-40-1F (hex) COLORGRAPH LTD +00401F (base 16) COLORGRAPH LTD + UNIT 2, MARS HOUSE + RG7 4QW - UNITED KINGDOM + GB + +00-40-AF (hex) DIGITAL PRODUCTS, INC. +0040AF (base 16) DIGITAL PRODUCTS, INC. + 411 WAVERLY OAKS ROAD + WALTHAM MA 02154 + US + +00-40-F7 (hex) Polaroid Corporation +0040F7 (base 16) Polaroid Corporation + 300 Baker Avenue + Concord MA 01742 + US + +00-40-37 (hex) SEA-ILAN, INC. +004037 (base 16) SEA-ILAN, INC. + 14602 NORTH US HIGHWAY #31 + CARMEL IN 46032 + US + +00-C0-26 (hex) LANS TECHNOLOGY CO., LTD. +00C026 (base 16) LANS TECHNOLOGY CO., LTD. + 153 MINTSU RD. 2F, TAOYUAN, + TAIWAN R. O. C. + TW + +00-40-7E (hex) EVERGREEN SYSTEMS, INC. +00407E (base 16) EVERGREEN SYSTEMS, INC. + 120 LANDING COURT-SUITE + NOVATO CA 94945 + US + +00-40-F9 (hex) COMBINET +0040F9 (base 16) COMBINET + 333 W. EL CAMINO REAL-STE#310 + SUNNYVALE CA 94087 + US + +00-C0-6F (hex) KOMATSU LTD. +00C06F (base 16) KOMATSU LTD. + 2597 SHINOMIYA HIRATSUKA-SHI + + JP + +00-C0-A7 (hex) SEEL LTD. +00C0A7 (base 16) SEEL LTD. + 3 YOUNG SQUARE + SCOTLAND + GB + +00-C0-4A (hex) GROUP 2000 AG +00C04A (base 16) GROUP 2000 AG + P.O. BOX 331 + + CH + +00-40-54 (hex) CONNECTION MACHINES SERVICES +004054 (base 16) CONNECTION MACHINES SERVICES + 12 HENSHAW STREET + WOBURN MA 01801-466664 + US + +00-40-04 (hex) ICM CO. LTD. +004004 (base 16) ICM CO. LTD. + 4-2-9 NIHONBASHI NANIWA-KU + + JP + +00-40-58 (hex) KRONOS, INC. +004058 (base 16) KRONOS, INC. + 400 FIFTH AVENUE + WALTHAM MA 02154 + US + +00-40-18 (hex) ADOBE SYSTEMS, INC. +004018 (base 16) ADOBE SYSTEMS, INC. + 1585 CHARLESTON ROAD + MOUNTAIN VIEW CA 94043 + US + +00-40-4A (hex) WEST AUSTRALIAN DEPARTMENT +00404A (base 16) WEST AUSTRALIAN DEPARTMENT + OF EMPLOYMENT (DEVET) + WESTERN + AU + +00-40-3C (hex) FORKS, INC. +00403C (base 16) FORKS, INC. + 1-27-4 IRIYA, + 110 + JP + +00-40-42 (hex) N.A.T. GMBH +004042 (base 16) N.A.T. GMBH + GOETHESTR. 2 + + DE + +00-40-F2 (hex) JANICH & KLASS COMPUTERTECHNIK +0040F2 (base 16) JANICH & KLASS COMPUTERTECHNIK + ZUM ALTEN ZOLLHAUS 20 + + DE + +00-40-A2 (hex) KINGSTAR TECHNOLOGY INC. +0040A2 (base 16) KINGSTAR TECHNOLOGY INC. + 1-3F, NO. 185, SEC. 3, + TAIPEI TAIWAN, R.O.C. + TW + +00-40-DC (hex) TRITEC ELECTRONIC GMBH +0040DC (base 16) TRITEC ELECTRONIC GMBH + ROBERT KOCH STR. 35 + + DE + +00-40-60 (hex) COMENDEC LTD +004060 (base 16) COMENDEC LTD + ENTERPRISE WAY, + BIRMINGHAM BIRMINGHAM ENGLAND + GB + +00-40-56 (hex) MCM JAPAN LTD. +004056 (base 16) MCM JAPAN LTD. + SYUUKAEN BLD. 2-11-1 + + JP + +00-40-30 (hex) GK COMPUTER +004030 (base 16) GK COMPUTER + BASLER STRASSE 103 + + DE + +00-40-40 (hex) RING ACCESS, INC. +004040 (base 16) RING ACCESS, INC. + 957-R INDUSTRIAL ROAD + SAN CARLOS CA 94070 + US + +00-80-57 (hex) ADSOFT, LTD. +008057 (base 16) ADSOFT, LTD. + Im Baumgarten 6 + MOHLIN CH-4313 + CH + +00-80-BB (hex) HUGHES LAN SYSTEMS +0080BB (base 16) HUGHES LAN SYSTEMS + 1225 CHARLESTON ROAD + MOUNTAIN VIEW CA 94043 + US + +00-40-3D (hex) Teradata Corporation +00403D (base 16) Teradata Corporation + 17095 Via Del Campo + San Diego CA 92127 + US + +00-40-D0 (hex) MITAC INTERNATIONAL CORP. +0040D0 (base 16) MITAC INTERNATIONAL CORP. + 8TH FL. 585 MING SHENG E. RD. + + TW + +00-40-AB (hex) ROLAND DG CORPORATION +0040AB (base 16) ROLAND DG CORPORATION + 1227 OKUBO-CHO, HAMAMATSU-SHI + 432 + JP + +00-40-B6 (hex) COMPUTERM CORPORATION +0040B6 (base 16) COMPUTERM CORPORATION + 111 WOOD STREET + PITTSBURGH PA 15222 + US + +00-40-A6 (hex) Cray, Inc. +0040A6 (base 16) Cray, Inc. + 655F LONE OAK DRIVE + EAGAN MN 55121 + US + +00-40-3E (hex) RASTER OPS CORPORATION +00403E (base 16) RASTER OPS CORPORATION + 2500 WALSH AVENUE + SANTA CLARA CA 95051 + US + +00-40-46 (hex) UDC RESEARCH LIMITED +004046 (base 16) UDC RESEARCH LIMITED + 8A KING WAN INDUSTRIAL BLDG. + HONG KONG + HK + +00-C0-D7 (hex) TAIWAN TRADING CENTER DBA +00C0D7 (base 16) TAIWAN TRADING CENTER DBA + TTC COMPUTER PRODUCTS + IRVING TX 75038 + US + +00-40-DA (hex) TELSPEC LTD +0040DA (base 16) TELSPEC LTD + LANCASTER PARKER ROAD + ENGLAND + GB + +00-40-C7 (hex) RUBY TECH CORPORATION +0040C7 (base 16) RUBY TECH CORPORATION + 6F-1, NO.3, LANE 250, + TAIPEI TAIWAN, R.O.C. + TW + +00-40-52 (hex) STAR TECHNOLOGIES, INC. +004052 (base 16) STAR TECHNOLOGIES, INC. + 515 SHAW ROAD + STERLING VA 22075 + US + +00-40-2E (hex) PRECISION SOFTWARE, INC. +00402E (base 16) PRECISION SOFTWARE, INC. + 600 S FEDERAL HWY STE + DEERFIELD BEACH FL 33441-4193 + US + +00-40-2B (hex) TRIGEM COMPUTER, INC. +00402B (base 16) TRIGEM COMPUTER, INC. + KISUNG B/D 4F, 784-6 + SEOUL KOREA 135-080 + KR + +00-40-1A (hex) FUJI ELECTRIC CO., LTD. +00401A (base 16) FUJI ELECTRIC CO., LTD. + NEW YURAKUCHO BLDG + + JP + +00-40-5F (hex) AFE COMPUTERS LTD. +00405F (base 16) AFE COMPUTERS LTD. + 62 ANCHORAGE ROAD + UNITED KINGDOM + GB + +00-40-80 (hex) ATHENIX CORPORATION +004080 (base 16) ATHENIX CORPORATION + 675 ALMANOR AVENUE + SUNNYVALE CA 94086 + US + +00-40-51 (hex) Garbee and Garbee +004051 (base 16) Garbee and Garbee + 4390 Darr Circle + Colorado Springs CO 80908 + US + +00-40-7A (hex) SOCIETE D'EXPLOITATION DU CNIT +00407A (base 16) SOCIETE D'EXPLOITATION DU CNIT + 2 GLACE DE LA DEFENSE 92053 + + FR + +00-40-31 (hex) KOKUSAI ELECTRIC CO., LTD +004031 (base 16) KOKUSAI ELECTRIC CO., LTD + 2-1 YASUUCHI + TOYAMA 939-23 + JP + +00-40-D3 (hex) KIMPSION INTERNATIONAL CORP. +0040D3 (base 16) KIMPSION INTERNATIONAL CORP. + 4701 PATRICK HENRY DRIVE + SANTA CLARA CA 95054 + US + +00-40-EE (hex) OPTIMEM +0040EE (base 16) OPTIMEM + 297 N. BERNARDO AVENUE + MOUNTAIN VIEW CA 94043-5205 + US + +00-40-25 (hex) MOLECULAR DYNAMICS +004025 (base 16) MOLECULAR DYNAMICS + 880 EAST ARQUES AVENUE + SUNNYVALE CA 94086-4536 + US + +00-40-67 (hex) OMNIBYTE CORPORATION +004067 (base 16) OMNIBYTE CORPORATION + 245 WEST ROOSEVELT ROAD + WEST CHICAGO IL 60185 + US + +00-40-C3 (hex) FISCHER AND PORTER CO. +0040C3 (base 16) FISCHER AND PORTER CO. + 125 E. COUNTY LINE ROAD + WARMINSTER PA 18974 + US + +00-40-EC (hex) MIKASA SYSTEM ENGINEERING +0040EC (base 16) MIKASA SYSTEM ENGINEERING + CO., LTD. + + JP + +00-80-2F (hex) NATIONAL INSTRUMENTS CORP. +00802F (base 16) NATIONAL INSTRUMENTS CORP. + 11500 North Mopac Expressway + AUSTIN TX 78759-3504 + US + +00-80-54 (hex) FRONTIER TECHNOLOGIES CORP. +008054 (base 16) FRONTIER TECHNOLOGIES CORP. + 10201 NO. PT. WASHINGTON ROAD + MEQUON WI 53092 + US + +00-80-53 (hex) INTELLICOM, INC. +008053 (base 16) INTELLICOM, INC. + 20415 NORDHOFF STREET + CHATSWORTH CA 91311 + US + +00-80-26 (hex) NETWORK PRODUCTS CORPORATION +008026 (base 16) NETWORK PRODUCTS CORPORATION + 1440 WEST COLORADO BLVD. + PASADENA CA 91105 + US + +00-80-B0 (hex) ADVANCED INFORMATION +0080B0 (base 16) ADVANCED INFORMATION + TECHNOLOGY, INC. + + JP + +00-80-FA (hex) RWT GMBH +0080FA (base 16) RWT GMBH + TALANGERSTR. 5-7 + WEST + DE + +00-80-FD (hex) EXSCEED CORPRATION +0080FD (base 16) EXSCEED CORPRATION + 1-15-12, KITAKASE, SAIWAI-KU + + JP + +00-80-FE (hex) AZURE TECHNOLOGIES, INC. +0080FE (base 16) AZURE TECHNOLOGIES, INC. + 63 SOUTH STREET + HOPKINTON MA 01748-2212 + US + +00-80-3C (hex) TVS ELECTRONICS LTD +00803C (base 16) TVS ELECTRONICS LTD + 44, MILLER ROAD + + IN + +00-80-46 (hex) Tattile SRL +008046 (base 16) Tattile SRL + DEPT. OF ELECTRICAL ENGIN'ING + + CA + +00-40-02 (hex) PERLE SYSTEMS LIMITED +004002 (base 16) PERLE SYSTEMS LIMITED + 60 RENFREW DRIVE + CANADA L3R 0E1 + CA + +00-40-49 (hex) Roche Diagnostics International Ltd. +004049 (base 16) Roche Diagnostics International Ltd. + FORRENSTRASSE + ROTKREUZ ZG 6343 + CH + +00-40-29 (hex) Compex +004029 (base 16) Compex + + + US + +00-40-9E (hex) CONCURRENT TECHNOLOGIES LTD. +00409E (base 16) CONCURRENT TECHNOLOGIES LTD. + 654 THE CRESCENT + UNITED KINGDOM + GB + +00-80-AD (hex) CNET TECHNOLOGY, INC. +0080AD (base 16) CNET TECHNOLOGY, INC. + 2199 ZANKER ROAD + SAN JOSE CA 95131 + US + +00-80-0E (hex) ATLANTIX CORPORATION +00800E (base 16) ATLANTIX CORPORATION + 5401 NW BROKENSOUND BLVD. + BOCA RATON FL 33431 + US + +00-80-AB (hex) DUKANE NETWORK INTEGRATION +0080AB (base 16) DUKANE NETWORK INTEGRATION + 2900 DUKANE DRIVE + ST. CHARLES IL 60174 + US + +00-80-F1 (hex) OPUS SYSTEMS +0080F1 (base 16) OPUS SYSTEMS + 3000 CORONADO DRIVE + SANTA CLARA CA 95054 + US + +00-80-29 (hex) EAGLE TECHNOLOGY, INC. +008029 (base 16) EAGLE TECHNOLOGY, INC. + 6800 ORANGETHORPE AVE.UNIT + BUENA PARK CA 90620 + US + +00-80-72 (hex) MICROPLEX SYSTEMS LTD. +008072 (base 16) MICROPLEX SYSTEMS LTD. + 301-2071 Kingsway + Port Coquitlam BC V3C6N2 + CA + +00-40-01 (hex) Zero One Technology Co. Ltd. +004001 (base 16) Zero One Technology Co. Ltd. + 10 Fl., No. 8, Lane 360, Sec 1, + Neihu Dist., Taipei City 114 + TW + +00-40-71 (hex) ATM COMPUTER GMBH +004071 (base 16) ATM COMPUTER GMBH + BUCKLESTR. 1-5,POSTFACH 101043 + + DE + +00-80-11 (hex) DIGITAL SYSTEMS INT'L. INC. +008011 (base 16) DIGITAL SYSTEMS INT'L. INC. + 7659 178TH PL. NE + REDMOND WA 98073-0908 + US + +00-80-34 (hex) SMT GOUPIL +008034 (base 16) SMT GOUPIL + 3 RUE DES ARCHIVES + + FR + +00-80-E4 (hex) NORTHWEST DIGITAL SYSTEMS, INC +0080E4 (base 16) NORTHWEST DIGITAL SYSTEMS, INC + P.O. BOX 15288 + SEATTLE WA 98115 + US + +00-80-EC (hex) SUPERCOMPUTING SOLUTIONS, INC. +0080EC (base 16) SUPERCOMPUTING SOLUTIONS, INC. + 6175 NANCY RIDGE BLVD. + SAN DIEGO CA 92121 + US + +00-80-2C (hex) THE SAGE GROUP PLC +00802C (base 16) THE SAGE GROUP PLC + SAGE HOUSE, BENTON PARK ROAD + UNITED KINGDOM + GB + +00-80-D6 (hex) NUVOTECH, INC. +0080D6 (base 16) NUVOTECH, INC. + 2015 BRIDGEWAY, SUITE 204 + SAUSALITO CA 94965 + US + +00-80-0A (hex) JAPAN COMPUTER CORP. +00800A (base 16) JAPAN COMPUTER CORP. + L. K. BLDG. HIGASHI KANDA + + JP + +00-80-4B (hex) EAGLE TECHNOLOGIES PTY.LTD. +00804B (base 16) EAGLE TECHNOLOGIES PTY.LTD. + 70 KEYS ROAD + + AU + +00-80-C8 (hex) D-LINK SYSTEMS, INC. +0080C8 (base 16) D-LINK SYSTEMS, INC. + 53 Discover Dr. + Irvine CA 92618 + US + +00-80-12 (hex) INTEGRATED MEASUREMENT SYSTEMS +008012 (base 16) INTEGRATED MEASUREMENT SYSTEMS + 9525 SW GEMINI DRIVE + BEAVERTON OR 97005 + US + +00-80-27 (hex) ADAPTIVE SYSTEMS, INC. +008027 (base 16) ADAPTIVE SYSTEMS, INC. + 1400 N.W. COMPTON DRIVE + BEAVERTON OR 97006 + US + +00-80-FC (hex) AVATAR CORPORATION +0080FC (base 16) AVATAR CORPORATION + 65 SOUTH STREET + HOPKINTON MA 01748 + US + +00-80-16 (hex) WANDEL AND GOLTERMANN +008016 (base 16) WANDEL AND GOLTERMANN + 1030 SWABIA COURT + NC 27709 + US + +00-80-A2 (hex) CREATIVE ELECTRONIC SYSTEMS +0080A2 (base 16) CREATIVE ELECTRONIC SYSTEMS + Avenue Eugène-Lance 38bis + + CH + +00-80-CC (hex) MICROWAVE BYPASS SYSTEMS +0080CC (base 16) MICROWAVE BYPASS SYSTEMS + 25 BRAINTREE HILL OFFICE PARK + BRAINTREE MA 02184 + US + +00-80-A5 (hex) SPEED INTERNATIONAL +0080A5 (base 16) SPEED INTERNATIONAL + 1320 ARBOLITA DR. + LA HABRA CA 90631 + US + +00-80-79 (hex) MICROBUS DESIGNS LTD. +008079 (base 16) MICROBUS DESIGNS LTD. + TREADAWAY HILL + UNITED KINGDOM + GB + +00-00-79 (hex) NETWORTH INCORPORATED +000079 (base 16) NETWORTH INCORPORATED + 8404 ESTERS BOULEVARD + IRVING TX 75063 + US + +00-00-91 (hex) ANRITSU CORPORATION +000091 (base 16) ANRITSU CORPORATION + 1800, ONNA + + JP + +00-00-75 (hex) Nortel Networks +000075 (base 16) Nortel Networks + Global Operations Engineering + Brampton ON l6T 5P6 Cana + CA + +00-00-A5 (hex) Tattile SRL +0000A5 (base 16) Tattile SRL + P.O. BOX 17220 + BOULDER CO 80308-7220 + US + +00-00-36 (hex) ATARI CORPORATION +000036 (base 16) ATARI CORPORATION + 1196 BORREGAS AVENUE + SUNNYVALE CA 94086 + US + +00-00-F8 (hex) DIGITAL EQUIPMENT CORPORATION +0000F8 (base 16) DIGITAL EQUIPMENT CORPORATION + LKG 1-2/A19 + LITTLETON MA 01460-1289 + US + +00-80-5C (hex) AGILIS CORPORATION +00805C (base 16) AGILIS CORPORATION + 1101 SAN ANTONIO ROAD + Mountain View CA 94043-1008 + US + +00-80-C5 (hex) NOVELLCO DE MEXICO +0080C5 (base 16) NOVELLCO DE MEXICO + CONSTITUYENTES NO. 907 + 11950 MEXICO 11950 MEXICO D.F. + MX + +00-80-78 (hex) PRACTICAL PERIPHERALS, INC. +008078 (base 16) PRACTICAL PERIPHERALS, INC. + 375 CONEJO RIDGE AVENUE + THOUSAND OAKS CA 91361 + US + +00-80-F6 (hex) SYNERGY MICROSYSTEMS +0080F6 (base 16) SYNERGY MICROSYSTEMS + 9605 SCRANTON ROAD-STE #700 + SAN DIEGO CA 92121-1773 + US + +00-80-7B (hex) ARTEL COMMUNICATIONS CORP. +00807B (base 16) ARTEL COMMUNICATIONS CORP. + 22 KANE INDUSTRIAL DRIVE + HUDSON MA 01749 + US + +00-80-14 (hex) ESPRIT SYSTEMS +008014 (base 16) ESPRIT SYSTEMS + 14F, NO. 1, SEC. 4 + TAIWAN TAIWAN R.O.C. + TW + +00-80-B7 (hex) STELLAR COMPUTER +0080B7 (base 16) STELLAR COMPUTER + 95 WELLS AVENUE + NEWTON MA 02159 + + +00-00-ED (hex) APRIL +0000ED (base 16) APRIL + 60, RUE DE CARTALE + + FR + +00-00-A3 (hex) NETWORK APPLICATION TECHNOLOGY +0000A3 (base 16) NETWORK APPLICATION TECHNOLOGY + 1686 DELL AVENUE + CAMPBELL CA 95008 + US + +00-00-39 (hex) TOSHIBA CORPORATION +000039 (base 16) TOSHIBA CORPORATION + COMPUTER DIVISION + TOKYO 105 + JP + +00-00-3C (hex) AUSPEX SYSTEMS INC. +00003C (base 16) AUSPEX SYSTEMS INC. + 5200 GREAT AMERICA PKWY + SANTA CLARA CA 95054 + US + +00-00-7E (hex) CLUSTRIX CORPORATION +00007E (base 16) CLUSTRIX CORPORATION + 960 HAMLIN COURT + SUNNYVALE CA 94089 + US + +00-00-CB (hex) COMPU-SHACK ELECTRONIC GMBH +0000CB (base 16) COMPU-SHACK ELECTRONIC GMBH + RINGSTR. 56 - 58, 5450 NEUWIED + WEST + DE + +00-00-13 (hex) CAMEX +000013 (base 16) CAMEX + 75 KNEELAND STREET + BOSTON MA 02111 + US + +00-00-95 (hex) SONY TEKTRONIX CORP. +000095 (base 16) SONY TEKTRONIX CORP. + P.O. BOX 5209 TOKYO INT'L + + JP + +00-00-57 (hex) SCITEX CORPORATION LTD. +000057 (base 16) SCITEX CORPORATION LTD. + P.O. BOX 330 + + IL + +00-00-D6 (hex) PUNCH LINE HOLDING +0000D6 (base 16) PUNCH LINE HOLDING + P.O. BOX 391708 + SOUTH AFRICA + ZA + +00-00-9E (hex) MARLI S.A. +00009E (base 16) MARLI S.A. + CHEMIN TAVERNEY 3 + + CH + +00-00-42 (hex) METIER MANAGEMENT SYSTEMS LTD. +000042 (base 16) METIER MANAGEMENT SYSTEMS LTD. + 3 FOUNDATION STREET + ENGLAND + GB + +00-00-7D (hex) Oracle Corporation +00007D (base 16) Oracle Corporation + 17 Network Circle + Menlo Park CA 95025 + US + +00-00-96 (hex) MARCONI ELECTRONICS LTD. +000096 (base 16) MARCONI ELECTRONICS LTD. + BROWNS LANE, THE AIRPORT + UNITED KINGDOM + GB + +00-00-5E (hex) ICANN, IANA Department +00005E (base 16) ICANN, IANA Department + INTERNET ASS'NED NOS.AUTHORITY + Los Angeles CA 90094-2536 + US + +00-00-38 (hex) CSS LABS +000038 (base 16) CSS LABS + 2134 SOUTH RIPCHEY + SANTA ANA CA 92705 + US + +00-00-44 (hex) CASTELLE CORPORATION +000044 (base 16) CASTELLE CORPORATION + 3255-3 SCOTT BOULEVARD + SANTA CLARA CA 95054 + US + +00-00-CE (hex) MEGADATA CORP. +0000CE (base 16) MEGADATA CORP. + 35 ORVILLE DRIVE + BOHEMIA NY 11716 + US + +00-00-7B (hex) RESEARCH MACHINES +00007B (base 16) RESEARCH MACHINES + P.O. BOX 75 + ENGLAND + GB + +00-00-0F (hex) NEXT, INC. +00000F (base 16) NEXT, INC. + 3475 DEER CREEK ROAD + PALO ALTO CA 94304 + US + +00-00-BB (hex) TRI-DATA +0000BB (base 16) TRI-DATA + 505 EAST MIDDLEFIELD ROAD + MOUNTAIN VIEW CA 94043-4082 + US + +00-00-1A (hex) ADVANCED MICRO DEVICES +00001A (base 16) ADVANCED MICRO DEVICES + P.O. BOX 3453 + SUNNYVALE CA 94088 + US + +00-00-7F (hex) LINOTYPE-HELL AG +00007F (base 16) LINOTYPE-HELL AG + POSTFACH 56 60 + + DE + +00-00-60 (hex) KONTRON ELEKTRONIK GMBH +000060 (base 16) KONTRON ELEKTRONIK GMBH + OSKAR-VON-MILLER-STR. 1 + + DE + +08-00-6F (hex) PHILIPS APELDOORN B.V. +08006F (base 16) PHILIPS APELDOORN B.V. + P.O. BOX 105 + THE + NL + +00-00-40 (hex) APPLICON, INC. +000040 (base 16) APPLICON, INC. + 4251 PLYMOUTH RD 48015 + ANN ARBOR MI 48106-0986 + US + +00-00-5D (hex) CS TELECOM +00005D (base 16) CS TELECOM + 4-16 AVENUE DU GENERAL LECLERC + + FR + +00-00-12 (hex) INFORMATION TECHNOLOGY LIMITED +000012 (base 16) INFORMATION TECHNOLOGY LIMITED + MAYLANDS AVE. HEMEL HEMPSTEAD + HERTS ENGLAND + GB + +00-00-8A (hex) DATAHOUSE INFORMATION SYSTEMS +00008A (base 16) DATAHOUSE INFORMATION SYSTEMS + DIRECTOR OF OPERATIONS + GU34 3QW ENGLAND + GB + +00-00-32 (hex) Marconi plc +000032 (base 16) Marconi plc + 28 ELSTREE WAY, BOREHAMWOOD + UNITED KINGDOM + GB + +00-00-85 (hex) CANON INC. +000085 (base 16) CANON INC. + DVTECH. DEV. CENTER DEPT.12 + + JP + +00-00-4A (hex) ADC CODENOLL TECHNOLOGY CORP. +00004A (base 16) ADC CODENOLL TECHNOLOGY CORP. + 200 CORPORATE BLVD. SO. + YONKERS NY 10701 + US + +08-00-8F (hex) CHIPCOM CORPORATION +08008F (base 16) CHIPCOM CORPORATION + SOUTHBOROUGH OFFICE + SOUTHBOROUGH MA 01772-1886 + US + +00-00-6A (hex) COMPUTER CONSOLES INC. +00006A (base 16) COMPUTER CONSOLES INC. + COMPUTER PRODUCTS DIVISION + IRVINE CA 92718 + US + +08-00-3E (hex) CODEX CORPORATION +08003E (base 16) CODEX CORPORATION + 50 EAST COMMERCE DRIVE + SCHAUMBURG IL 60173 + US + +08-00-40 (hex) FERRANTI COMPUTER SYS. LIMITED +080040 (base 16) FERRANTI COMPUTER SYS. LIMITED + WYTHENSHAWE DIVISION + UNITED KINGDOM + GB + +08-00-3A (hex) ORCATECH INC. +08003A (base 16) ORCATECH INC. + 2680 QUEENSVIEW DRIVE + CANADA K2B 8H6 + CA + +08-00-3D (hex) CADNETIX CORPORATIONS +08003D (base 16) CADNETIX CORPORATIONS + 5797 CENTRAL AVENUE + BOULDER CO 80301 + US + +08-00-38 (hex) BULL S.A.S. +080038 (base 16) BULL S.A.S. + rue Jean Jaures B.P.68 + Les Clayes sous Bois 78430 + FR + +08-00-73 (hex) TECMAR INC. +080073 (base 16) TECMAR INC. + 6225 COCHRAN ROAD + SOLON OH 44139 + US + +08-00-72 (hex) XEROX CORP UNIV GRANT PROGRAM +080072 (base 16) XEROX CORP UNIV GRANT PROGRAM + ZEROX SYSTEMS INSTITUTE + WEBSTER NY 14580 + US + +08-00-6A (hex) AT&T +08006A (base 16) AT&T + 3300 E Renner Road + Richardson TX 75082 + US + +08-00-7A (hex) INDATA +08007A (base 16) INDATA + GJERDRUMS VEI 12 C + + NO + +08-00-79 (hex) THE DROID WORKS +080079 (base 16) THE DROID WORKS + P.O. BOX CS 8180 + SAN RAFAEL CA 94912 + US + +08-00-4D (hex) CORVUS SYSTEMS INC. +08004D (base 16) CORVUS SYSTEMS INC. + 2100 CORVUS DRIVE + SAN JOSE CA 95124 + US + +08-00-2F (hex) PRIME COMPUTER INC. +08002F (base 16) PRIME COMPUTER INC. + 100 CROSBY DRIVE + BEDFORD MA 01730-1402 + US + +08-00-2C (hex) BRITTON LEE INC. +08002C (base 16) BRITTON LEE INC. + 14600 WINCHESTER BLVD + LOS GATOS CA 95030 + US + +08-00-62 (hex) General Dynamics +080062 (base 16) General Dynamics + + Fort Worth TX + US + +08-00-5C (hex) FOUR PHASE SYSTEMS +08005C (base 16) FOUR PHASE SYSTEMS + 2001 LOGIC DRIVE + SAN JOSE CA 95124-3452 + US + +08-00-5A (hex) IBM Corp +08005A (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +08-00-52 (hex) INSYSTEC +080052 (base 16) INSYSTEC + 450 LAKEMONT AVENUE + WINTER PARK FL 32792 + US + +08-00-1E (hex) APOLLO COMPUTER INC. +08001E (base 16) APOLLO COMPUTER INC. + 15 ELIZABETH DRIVE + CHELMSFORD MA 01824 + US + +08-00-19 (hex) GENERAL ELECTRIC CORPORATION +080019 (base 16) GENERAL ELECTRIC CORPORATION + 1285 BOSTON AVENUE + BRIDGEPORT CT 06602 + US + +02-70-01 (hex) RACAL-DATACOM +027001 (base 16) RACAL-DATACOM + LAN INTERNETWORKING DIVISION + BOXBOROUGH MA 01719 + US + +08-00-0E (hex) NCR CORPORATION +08000E (base 16) NCR CORPORATION + WORLD HEADQUARTERS + DAYTON OH 45479 + US + +00-DD-09 (hex) UNGERMANN-BASS INC. +00DD09 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +00-00-02 (hex) XEROX CORPORATION +000002 (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +00-00-03 (hex) XEROX CORPORATION +000003 (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +00-00-06 (hex) XEROX CORPORATION +000006 (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +08-00-01 (hex) COMPUTERVISION CORPORATION +080001 (base 16) COMPUTERVISION CORPORATION + 14 CROSBY DRIVE MS 5-1 + BEDFORD MA 01730 + US + +08-00-05 (hex) SYMBOLICS INC. +080005 (base 16) SYMBOLICS INC. + 257 VASSAR STREET + CAMBRIDGE MA 02139 + US + +00-DD-07 (hex) UNGERMANN-BASS INC. +00DD07 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +00-00-08 (hex) XEROX CORPORATION +000008 (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +00-00-3D (hex) UNISYS +00003D (base 16) UNISYS + MS8-010 + SAN JOSE CA 95150-6685 + US + +00-DD-0D (hex) UNGERMANN-BASS INC. +00DD0D (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +08-00-64 (hex) Sitasys AG +080064 (base 16) Sitasys AG + Freiburgstrasse 251 + + CH + +08-00-02 (hex) BRIDGE COMMUNICATIONS INC. +080002 (base 16) BRIDGE COMMUNICATIONS INC. + 2081 STIERLING ROAD + MOUNTAIN VIEW CA 94043 + US + +08-00-1A (hex) TIARA/ 10NET +08001A (base 16) TIARA/ 10NET + 7777 WASHINGTON VILLAGE DRIVE + DAYTON OHIO 45459-3957 + US + +08-00-8B (hex) PYRAMID TECHNOLOGY CORP. +08008B (base 16) PYRAMID TECHNOLOGY CORP. + 1295 CHARLESTON ROAD + MOUNTAIN VIEW CA 94043 + US + +08-00-12 (hex) BELL ATLANTIC INTEGRATED SYST. +080012 (base 16) BELL ATLANTIC INTEGRATED SYST. + 40 TALL PINE DRIVE + SUDBURY MA 01776 + US + +14-A1-BF (hex) ASSA ABLOY Korea Co., Ltd Unilock +14A1BF (base 16) ASSA ABLOY Korea Co., Ltd Unilock + 10f of JEI PLATZ Bldg., 186, Gasandigital 1-ro + Geumcheon-gu Seoul 08502 + KR + +94-83-C4 (hex) GL Technologies (Hong Kong) Limited +9483C4 (base 16) GL Technologies (Hong Kong) Limited + 103B Enterprise Place, 5W Science Park + NT 00000 + HK + +08-00-30 (hex) ROYAL MELBOURNE INST OF TECH +080030 (base 16) ROYAL MELBOURNE INST OF TECH + GPO BOX 2476V + MELBOURNE VIC 3001 + AU + +00-00-0B (hex) MATRIX CORPORATION +00000B (base 16) MATRIX CORPORATION + 1203 NEW HOPE ROAD + RALEIGH NORTH CAROLINA 276 + US + +00-00-9B (hex) INFORMATION INTERNATIONAL, INC +00009B (base 16) INFORMATION INTERNATIONAL, INC + 5F., THE 7TH INDUSTRY BLDG. + JAPAN 150 + JP + +9C-93-B0 (hex) Megatronix (Beijing) Technology Co., Ltd. +9C93B0 (base 16) Megatronix (Beijing) Technology Co., Ltd. + Floor11,Building C, Rongxin Center Chungyuan Road 34#, chaoyang distric, Beijing, P.R.China + Beijing Beijing 100012 + CN + +64-AE-F1 (hex) Qingdao Hisense Electronics Co.,Ltd. +64AEF1 (base 16) Qingdao Hisense Electronics Co.,Ltd. + Qianwangang Roard 218 + Qingdao Shandong 266510 + CN + +08-00-16 (hex) BARRISTER INFO SYS CORP +080016 (base 16) BARRISTER INFO SYS CORP + ONE TECHNOLOGY CENTER + BUFFALO NY 14203 + US + +44-CB-8B (hex) LG Innotek +44CB8B (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +B4-05-5D (hex) Inspur Electronic Information Industry Co.,Ltd. +B4055D (base 16) Inspur Electronic Information Industry Co.,Ltd. + No 224 Shanda Road + Jinan Shandong 250013 + CN + +98-48-27 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +984827 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +D4-F5-EF (hex) Hewlett Packard Enterprise +D4F5EF (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +28-BD-89 (hex) Google, Inc. +28BD89 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +EC-1B-BD (hex) Silicon Laboratories +EC1BBD (base 16) Silicon Laboratories + 7000 W. William Cannon Dr. + Austin 78735 + US + +D8-A3-15 (hex) vivo Mobile Communication Co., Ltd. +D8A315 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +80-64-7A (hex) Ola Sense Inc +80647A (base 16) Ola Sense Inc + 764 Avenue A + Redondo Beach 90277 + US + +C0-B8-83 (hex) Intel Corporate +C0B883 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +24-FD-0D (hex) INDÚSTRIA DE TELECOMUNICAÇÃO ELETRÔNICA +24FD0D (base 16) INDÚSTRIA DE TELECOMUNICAÇÃO ELETRÔNICA + BR 101, KM 210 + São Jose Santa Catarina 88104-800 + BR + +70-F8-2B (hex) DWnet Technologies(Suzhou) Corporation +70F82B (base 16) DWnet Technologies(Suzhou) Corporation + No.8,Tangzhuang Road, Suzhou Industrial Park, Jiangsu, China + Suzhou 21500 + CN + +14-24-75 (hex) 4DReplay, Inc +142475 (base 16) 4DReplay, Inc + 1286 Folsom Street + San Francisco CA 94103 + US + +10-DC-B6 (hex) IEEE Registration Authority +10DCB6 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F8-9E-28 (hex) Cisco Meraki +F89E28 (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco 94158 + US + +F8-C4-F3 (hex) Shanghai Infinity Wireless Technologies Co.,Ltd. +F8C4F3 (base 16) Shanghai Infinity Wireless Technologies Co.,Ltd. + Room 522, Building A, No.1687 Changyang Road, Yangpu District, Shanghai + Shanghai Shanghai 200082 + CN + +D4-77-2B (hex) Nanjing Ztlink Network Technology Co.,Ltd +D4772B (base 16) Nanjing Ztlink Network Technology Co.,Ltd + No.0 Mozhou East Road , Jiangning Economic & Technological Development Zone, Jiangning District + Nanjing Jiangsu 211111 + CN + +64-F9-C0 (hex) ANALOG DEVICES +64F9C0 (base 16) ANALOG DEVICES + 32990 ALVARADO NILES RD + UNION CITY CA 94587 + US + +18-D0-C5 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +18D0C5 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +34-ED-1B (hex) Cisco Systems, Inc +34ED1B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +BC-A5-11 (hex) NETGEAR +BCA511 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-0A-7B (hex) Cornelius Consult +000A7B (base 16) Cornelius Consult + Im Vogelsang 21 + Hattingen NRW 45527 + DE + +C4-E9-0A (hex) D-Link International +C4E90A (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +C4-44-7D (hex) HUAWEI TECHNOLOGIES CO.,LTD +C4447D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +30-E9-8E (hex) HUAWEI TECHNOLOGIES CO.,LTD +30E98E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +74-8B-34 (hex) Shanghai Smart System Technology Co., Ltd +748B34 (base 16) Shanghai Smart System Technology Co., Ltd + Room 902C-1, 560 Shengxia Road, Zhangjiang Hi-Tech Park, Shanghai 201203, China + Shanghai Shanghai 201210 + CN + +AC-BD-70 (hex) Huawei Device Co., Ltd. +ACBD70 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +C8-09-A8 (hex) Intel Corporate +C809A8 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C0-2E-26 (hex) Private +C02E26 (base 16) Private + +34-D2-62 (hex) SZ DJI TECHNOLOGY CO.,LTD +34D262 (base 16) SZ DJI TECHNOLOGY CO.,LTD + 6/F,HKUST SZ IER Bldg,9 Yuexing 1st Rd + shenzhen guangdong 518057 + CN + +08-12-A5 (hex) Amazon Technologies Inc. +0812A5 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +80-7F-F8 (hex) Juniper Networks +807FF8 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +44-03-77 (hex) IEEE Registration Authority +440377 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-24-87 (hex) Transact Campus, Inc. +002487 (base 16) Transact Campus, Inc. + 22601 North 19th Avenue + Phoenix AZ 85027 + US + +B4-E9-A3 (hex) port industrial automation GmbH +B4E9A3 (base 16) port industrial automation GmbH + Regensburger Str. 7b + Halle (S.) 06132 + DE + +38-E8-EE (hex) Nanjing Youkuo Electric Technology Co., Ltd +38E8EE (base 16) Nanjing Youkuo Electric Technology Co., Ltd + 100 Jiangjun Road,Jiangning + Nanjing Jiangsu 211100 + CN + +90-B8-E0 (hex) SHENZHEN YANRAY TECHNOLOGY CO.,LTD +90B8E0 (base 16) SHENZHEN YANRAY TECHNOLOGY CO.,LTD + 5A, 4th Building, Huafengzhenbao Industrial Park, Beihuan Road, Shiyan Street, Baoan District, + Shenzhen Guangdong 518000 + CN + +9C-F5-31 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +9CF531 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +80-E4-55 (hex) New H3C Technologies Co., Ltd +80E455 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +2C-4C-C6 (hex) Murata Manufacturing Co., Ltd. +2C4CC6 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +7C-21-0D (hex) Cisco Systems, Inc +7C210D (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +4C-BC-72 (hex) Primex Wireless +4CBC72 (base 16) Primex Wireless + 965 Wells Street + Lake Geneva WI 53147 + US + +68-02-B8 (hex) Compal Broadband Networks, Inc. +6802B8 (base 16) Compal Broadband Networks, Inc. + 13F., No.1, Taiyuan 1st St. + Zhubei City Hsinchu County 30265 + TW + +34-63-D4 (hex) BIONIX SUPPLYCHAIN TECHNOLOGIES SLU +3463D4 (base 16) BIONIX SUPPLYCHAIN TECHNOLOGIES SLU + Poligono Pocomaco Avenida Primera Parcela B3 Nave F + La Coruña La Coruña 15190 + ES + +08-F7-E9 (hex) HRCP Research and Development Partnership +08F7E9 (base 16) HRCP Research and Development Partnership + 1-24-2 Taito, Taito-ku + Tokyo 1100016 + JP + +8C-BA-25 (hex) UNIONMAN TECHNOLOGY CO.,LTD +8CBA25 (base 16) UNIONMAN TECHNOLOGY CO.,LTD + No.5,Huitai Road,Huinan High-Tech Park,Huiao Highway + Huizhou Guangdong 516025 + CN + +D4-9E-3B (hex) Guangzhou Shiyuan Electronic Technology Company Limited +D49E3B (base 16) Guangzhou Shiyuan Electronic Technology Company Limited + No.6, 4th Yunpu Road, Yunpu industry District + Guangzhou Guangdong 510530 + CN + +DC-DC-E2 (hex) Samsung Electronics Co.,Ltd +DCDCE2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A0-AC-69 (hex) Samsung Electronics Co.,Ltd +A0AC69 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +10-89-FB (hex) Samsung Electronics Co.,Ltd +1089FB (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +DC-4B-DD (hex) Shenzhen SuperElectron Technology Co.,Ltd. +DC4BDD (base 16) Shenzhen SuperElectron Technology Co.,Ltd. + 1213-1214, haosheng business center, dongbin road, nanshan street, nanshan district, shenzhen city + Shenzhen Guangdong 518000 + CN + +C0-B5-CD (hex) Huawei Device Co., Ltd. +C0B5CD (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +4C-50-77 (hex) Huawei Device Co., Ltd. +4C5077 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +50-2D-BB (hex) GD Midea Air-Conditioning Equipment Co.,Ltd. +502DBB (base 16) GD Midea Air-Conditioning Equipment Co.,Ltd. + Midea Global Innovation Center,Beijiao Town,Shunde + Foshan Guangdong 528311 + CN + +84-EA-97 (hex) Shenzhen iComm Semiconductor Co., Ltd. +84EA97 (base 16) Shenzhen iComm Semiconductor Co., Ltd. + Room 501A,Block B,Digital Building,Garden City,No.1079 Nanhai Road,Nanshan District + Shenzhen 518067 + CN + +5C-3A-3D (hex) zte corporation +5C3A3D (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +30-FD-65 (hex) HUAWEI TECHNOLOGIES CO.,LTD +30FD65 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-A1-AE (hex) Apple, Inc. +7CA1AE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-22-FB (hex) Apple, Inc. +3C22FB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +58-EA-FC (hex) ELL-IoT Inc +58EAFC (base 16) ELL-IoT Inc + 32 Journey + Aliso Viejo CA 92656 + US + +90-13-DA (hex) Athom B.V. +9013DA (base 16) Athom B.V. + Rigtersbleek-Zandvoort 10 + Enschede 7521BE + NL + +14-11-5D (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +14115D (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +E4-F3-27 (hex) ATOL LLC +E4F327 (base 16) ATOL LLC + Bolshaya Novodmitrovskaya str., 14, build 4 + Moscow 127015 + RU + +68-19-AC (hex) Guangzhou Xianyou Intelligent Technogoly CO., LTD +6819AC (base 16) Guangzhou Xianyou Intelligent Technogoly CO., LTD + No.32 Xixiu Road, Xiuquan Street,Huadu District + Guangzhou Guangdong 510800 + CN + +E8-2E-0C (hex) NETINT Technologies Inc. +E82E0C (base 16) NETINT Technologies Inc. + #306, 3500 Gilmore Way + Burnaby BC V5G0B8 + CA + +18-92-A4 (hex) Ciena Corporation +1892A4 (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +10-08-2C (hex) Texas Instruments +10082C (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +B0-73-5D (hex) Huawei Device Co., Ltd. +B0735D (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +F0-B4-D2 (hex) D-Link International +F0B4D2 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +5C-3A-45 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +5C3A45 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +A0-3C-31 (hex) Shenzhen Belon Technology CO.,LTD +A03C31 (base 16) Shenzhen Belon Technology CO.,LTD + Tsinghua Information + Shenzhen Guangdong 518052 + CN + +A8-97-CD (hex) ARRIS Group, Inc. +A897CD (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +40-4C-77 (hex) ARRIS Group, Inc. +404C77 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +2C-E3-10 (hex) Stratacache +2CE310 (base 16) Stratacache + 40 N Main St, Suite 2600 + Dayton OH 45423 + US + +00-22-A0 (hex) APTIV SERVICES US, LLC +0022A0 (base 16) APTIV SERVICES US, LLC + 5725 Innovation Drive + Troy MI 48098 + US + +A4-30-7A (hex) Samsung Electronics Co.,Ltd +A4307A (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +FC-8E-5B (hex) China Mobile Iot Limited company +FC8E5B (base 16) China Mobile Iot Limited company + No. 8 Yangliu North Road, Yubei District, Chongqing, China + Chong Qing Chong Qing 401120 + CN + +14-2A-14 (hex) ShenZhen Selenview Digital Technology Co.,Ltd +142A14 (base 16) ShenZhen Selenview Digital Technology Co.,Ltd + 615,Block A,Huafeng internet Creative Park,107 Gonghe Industrial Road,Baoan District,Shenzhen,China + Shenzhen Guangdong 518102 + CN + +D8-7E-76 (hex) ITEL MOBILE LIMITED +D87E76 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +38-4B-5B (hex) ZTRON TECHNOLOGY LIMITED +384B5B (base 16) ZTRON TECHNOLOGY LIMITED + 12/F,JunZi Plaza, Qiaoxiang Road, Futian District + Shenzhen Guangdong 518000 + CN + +B8-61-42 (hex) Beijing Tricolor Technology Co., Ltd +B86142 (base 16) Beijing Tricolor Technology Co., Ltd + Room 808, Building 1, Yard 39, Linfeng 2nd Road, Haidian + Beijing 102206 + CN + +20-0A-0D (hex) IEEE Registration Authority +200A0D (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E4-7C-65 (hex) Sunstar Communication Technology Co., Ltd +E47C65 (base 16) Sunstar Communication Technology Co., Ltd + 4F,Building D1, Mould Industrial Park, No.199 of Xiqu Ave,West High-tech Zone + Chengdu Sichuan 611731 + CN + +9C-54-DA (hex) SkyBell Technologies Inc. +9C54DA (base 16) SkyBell Technologies Inc. + 1 Jenner + Irvine CA 92618 + US + +4C-49-4F (hex) zte corporation +4C494F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +C4-74-1E (hex) zte corporation +C4741E (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-D0-78 (hex) Eltex of Sweden AB +00D078 (base 16) Eltex of Sweden AB + Södra Portgatan 19 + OSBY Skåne 283 50 + SE + +5C-78-F8 (hex) Huawei Device Co., Ltd. +5C78F8 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +B8-27-C5 (hex) Huawei Device Co., Ltd. +B827C5 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +DC-89-83 (hex) Samsung Electronics Co.,Ltd +DC8983 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +5C-CB-99 (hex) Samsung Electronics Co.,Ltd +5CCB99 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D4-60-75 (hex) Baidu Online Network Technology (Beijing) Co., Ltd +D46075 (base 16) Baidu Online Network Technology (Beijing) Co., Ltd + Baidu Campus, No.10 Shangdi 10th Street, Haidian District + Beijing 100085 + CN + +78-C5-F8 (hex) Huawei Device Co., Ltd. +78C5F8 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +D4-5D-64 (hex) ASUSTek COMPUTER INC. +D45D64 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +90-B1-44 (hex) Samsung Electronics Co.,Ltd +90B144 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +48-DD-0C (hex) eero inc. +48DD0C (base 16) eero inc. + 660 3rd Street + San Francisco CA 94107 + US + +94-0C-98 (hex) Apple, Inc. +940C98 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E8-FB-E9 (hex) Apple, Inc. +E8FBE9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-EC-0D (hex) Apple, Inc. +38EC0D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +58-27-8C (hex) BUFFALO.INC +58278C (base 16) BUFFALO.INC + AKAMONDORI Bld.,30-20,Ohsu 3-chome,Naka-ku + Nagoya Aichi Pref. 460-8315 + JP + +14-0A-C5 (hex) Amazon Technologies Inc. +140AC5 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +20-83-F8 (hex) Advanced Digital Broadcast SA +2083F8 (base 16) Advanced Digital Broadcast SA + Route de Lausanne 319 + Bellevue CH-1293 + SZ + +C8-C7-50 (hex) Motorola Mobility LLC, a Lenovo Company +C8C750 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +2C-DC-D7 (hex) AzureWave Technology Inc. +2CDCD7 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +8C-C6-81 (hex) Intel Corporate +8CC681 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +34-E3-DA (hex) Hoval Aktiengesellschaft +34E3DA (base 16) Hoval Aktiengesellschaft + Austrasse 70 + Vaduz 9490 + LI + +E0-BB-9E (hex) Seiko Epson Corporation +E0BB9E (base 16) Seiko Epson Corporation + 2070 Kotobuki Koaka + Matsumoto-shi Nagano-ken 399-8702 + JP + +48-D2-4F (hex) Sagemcom Broadband SAS +48D24F (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +E4-AA-EC (hex) Tianjin Hualai Technology Co., Ltd +E4AAEC (base 16) Tianjin Hualai Technology Co., Ltd + Overseas Chinese business building No. 10, Jinping Road, Nankai District, Tianjin + TIANJIN 300190 + CN + +94-BE-46 (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +94BE46 (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan + Wuhan Hubei 430000 + CN + +AC-F8-CC (hex) ARRIS Group, Inc. +ACF8CC (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +8C-5A-25 (hex) ARRIS Group, Inc. +8C5A25 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +48-3F-DA (hex) Espressif Inc. +483FDA (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +6C-5D-3A (hex) Microsoft Corporation +6C5D3A (base 16) Microsoft Corporation + One Microsoft Way + REDMOND 98052 + US + +CC-D4-2E (hex) Arcadyan Corporation +CCD42E (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +C8-53-E1 (hex) Beijing Bytedance Network Technology Co., Ltd +C853E1 (base 16) Beijing Bytedance Network Technology Co., Ltd + No.1 Building, Zhonghang Square, West Road of the Northern 3rd Circuit, Haidian Distrct + Beijing Beijing 100098 + CN + +14-16-9D (hex) Cisco Systems, Inc +14169D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +48-A2-E6 (hex) Resideo +48A2E6 (base 16) Resideo + 2 Corporate Center Dr. + Melville NY 11747 + US + +90-E2-FC (hex) IEEE Registration Authority +90E2FC (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F0-08-D1 (hex) Espressif Inc. +F008D1 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +58-94-B2 (hex) BrainCo +5894B2 (base 16) BrainCo + ????????????????1107? + ??? ??? 518000 + CN + +B0-95-75 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +B09575 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +B4-B0-55 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B4B055 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +04-8C-16 (hex) HUAWEI TECHNOLOGIES CO.,LTD +048C16 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +98-DD-5B (hex) TAKUMI JAPAN LTD +98DD5B (base 16) TAKUMI JAPAN LTD + 3-9-3 Uchiyama building 7F Nishishinbashi + Minato-ku Tokyo Tokyo 1050003 + JP + +3C-5C-F1 (hex) eero inc. +3C5CF1 (base 16) eero inc. + 660 3rd Street + San Francisco CA 94107 + US + +14-AE-85 (hex) IEEE Registration Authority +14AE85 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +90-74-9D (hex) IRay Technology Co., Ltd. +90749D (base 16) IRay Technology Co., Ltd. + 11th Guiyang St., + Yantai Shandong 264000 + CN + +8C-3B-32 (hex) Microfan B.V. +8C3B32 (base 16) Microfan B.V. + Industriestraat 23 + Horst Limburg 5961 PH + NL + +D0-D3-E0 (hex) Aruba, a Hewlett Packard Enterprise Company +D0D3E0 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +3C-58-C2 (hex) Intel Corporate +3C58C2 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +CC-F9-E4 (hex) Intel Corporate +CCF9E4 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +64-5C-F3 (hex) ParanTek Inc. +645CF3 (base 16) ParanTek Inc. + 3F, 40-15 Gilju-Ro, 411 Beon-Gil + Wonmi-Gu, Bucheon City Gyeonggi-Do 14488 + KR + +B0-CC-FE (hex) Huawei Device Co., Ltd. +B0CCFE (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +54-0D-F9 (hex) Huawei Device Co., Ltd. +540DF9 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +00-66-19 (hex) Huawei Device Co., Ltd. +006619 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +FC-39-64 (hex) ITEL MOBILE LIMITED +FC3964 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +E4-5E-37 (hex) Intel Corporate +E45E37 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +14-47-2D (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +14472D (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +E4-90-FD (hex) Apple, Inc. +E490FD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-AB-1A (hex) Apple, Inc. +84AB1A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-6D-31 (hex) FIREWALLA INC +206D31 (base 16) FIREWALLA INC + 75 E. Santa Clara St. STE 600 + San Jose CA 95113 + US + +D0-65-44 (hex) Apple, Inc. +D06544 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-6F-2D (hex) Shenzhen Sundray Technologies Company Limited +186F2D (base 16) Shenzhen Sundray Technologies Company Limited + 5th Floor, Block A4, Nanshan ipark,NO.1001 Xue Yuan Road, Nanshan District, Shenzhen 518055, P.R. China + Shenzhen Guangdong 518057 + CN + +F8-4F-AD (hex) Hui Zhou Gaoshengda Technology Co.,LTD +F84FAD (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +4C-0A-3D (hex) ADNACOM INC. +4C0A3D (base 16) ADNACOM INC. + 200-5050 Kingsway + Burnaby BC V5H 4H2 + CA + +3C-80-6B (hex) Hunan Voc Acoustics Technology Co., Ltd. +3C806B (base 16) Hunan Voc Acoustics Technology Co., Ltd. + State Industrialpark, Jiulong Development Zone, Yanling County + Zhuzhou Hunan 412500 + CN + +60-DE-35 (hex) GITSN, Inc. +60DE35 (base 16) GITSN, Inc. + #601~602, Daerung Post Tower 1, 288, Digital-ro + Guro-gu Seoul 08390 + KR + +28-31-7E (hex) Hongkong Nano IC Technologies Co., Ltd +28317E (base 16) Hongkong Nano IC Technologies Co., Ltd + Rm. 19C, Lockhart Ctr., 301-307 Lockhart Rd., Wan Chai, Hong Kong. + Hongkong 999077 + CN + +A8-41-22 (hex) China Mobile (Hangzhou) Information Technology Co.,Ltd. +A84122 (base 16) China Mobile (Hangzhou) Information Technology Co.,Ltd. + No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District + Hangzhou Zhejiang 310000 + CN + +6C-DD-BC (hex) Samsung Electronics Co.,Ltd +6CDDBC (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +CC-7F-76 (hex) Cisco Systems, Inc +CC7F76 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +40-BC-68 (hex) Wuhan Funshion Online Technologies Co.,Ltd +40BC68 (base 16) Wuhan Funshion Online Technologies Co.,Ltd + 5th Floor,Financial Port Building A9,No.77 Optical Valley Avenue, East Lake High-Tech Development Zone, Wuhan + Wuhan CN/Hubei 430000 + CN + +DC-98-40 (hex) Microsoft Corporation +DC9840 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND 98052 + US + +44-76-54 (hex) HUAWEI TECHNOLOGIES CO.,LTD +447654 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-D9-A0 (hex) HUAWEI TECHNOLOGIES CO.,LTD +7CD9A0 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F0-33-E5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F033E5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B4-F1-8C (hex) Huawei Device Co., Ltd. +B4F18C (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +B8-CE-F6 (hex) Mellanox Technologies, Inc. +B8CEF6 (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +B8-02-A4 (hex) Aeonsemi, Inc. +B802A4 (base 16) Aeonsemi, Inc. + Cassia Court, Suite 716, 10 Market Street + Camana Bay Grand Cayman KY1-9006 + KY + +E4-83-26 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E48326 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-05-BB (hex) IEEE Registration Authority +9405BB (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +8C-5F-AD (hex) Fiberhome Telecommunication Technologies Co.,LTD +8C5FAD (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +AC-C2-5D (hex) Fiberhome Telecommunication Technologies Co.,LTD +ACC25D (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +8C-0C-87 (hex) Nokia +8C0C87 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +18-69-D8 (hex) HANGZHOU AIXIANGJI TECHNOLOGY CO., LTD +1869D8 (base 16) HANGZHOU AIXIANGJI TECHNOLOGY CO., LTD + 7 Floor, 3 Blvd., More Centre, 87 Gudun Rd., Xihu District + Hangzhou Zhejiang 310012 + CN + +C4-32-D1 (hex) Farlink Technology Limited +C432D1 (base 16) Farlink Technology Limited + Flat A&B,9/F,Wing Cheong Factory Building,121 King Lam Street,Cheung Sha Wan,Hong Kong. + Hongkong 0000 + HK + +CC-41-8E (hex) MSA Innovation +CC418E (base 16) MSA Innovation + 1100 Cranberry Woods Road + Cranberry Township PA 16066 + US + +6C-6A-77 (hex) Intel Corporate +6C6A77 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +CC-A7-C1 (hex) Google, Inc. +CCA7C1 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +38-84-79 (hex) Cisco Meraki +388479 (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco 94158 + US + +7C-9E-BD (hex) Espressif Inc. +7C9EBD (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +1C-02-19 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +1C0219 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +C8-D7-78 (hex) BSH Hausgeraete GmbH +C8D778 (base 16) BSH Hausgeraete GmbH + Im Gewerbepark B10 + Regensburg 93059 + DE + +9C-61-1D (hex) Panasonic Corporation of North America +9C611D (base 16) Panasonic Corporation of North America + 1200 Ridgeway Ave + Rochester NY 14615 + US + +C0-95-DA (hex) NXP India Private Limited +C095DA (base 16) NXP India Private Limited + 1st Floor, Muttha Towers, Don Bosco Marg, Off Airport Road, Yerwada + Pune Maharashtra 411006 + IN + +B4-22-00 (hex) Brother Industries, LTD. +B42200 (base 16) Brother Industries, LTD. + 15-1, Naeshirocho, Mizuho-ku + NAGOYA 4678561 + JP + +68-49-B2 (hex) CARLO GAVAZZI LTD +6849B2 (base 16) CARLO GAVAZZI LTD + BLB042, Bulebel Industrial Estate + Zejtun ZTN 3000 + MT + +48-7A-FF (hex) ESSYS +487AFF (base 16) ESSYS + gaetbeol-ro + Incheon 21999 + KR + +40-B6-E7 (hex) Huawei Device Co., Ltd. +40B6E7 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +D0-B4-5D (hex) Huawei Device Co., Ltd. +D0B45D (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +88-36-CF (hex) Huawei Device Co., Ltd. +8836CF (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +A4-C5-4E (hex) Huawei Device Co., Ltd. +A4C54E (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +D4-BB-E6 (hex) Huawei Device Co., Ltd. +D4BBE6 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +00-9E-EE (hex) Positivo Tecnologia S.A. +009EEE (base 16) Positivo Tecnologia S.A. + João Bettega, 5200 + Curitiba Paraná 81350-000 + BR + +90-B8-32 (hex) Extreme Networks, Inc. +90B832 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +40-2F-86 (hex) LG Innotek +402F86 (base 16) LG Innotek + 26, Hanamsandan 5beon-ro + Gwangju Gwangsan-gu 506-731 + KR + +D4-22-CD (hex) Xsens Technologies B.V. +D422CD (base 16) Xsens Technologies B.V. + Pantheon 6-a + Enschede 7521 PR + NL + +C8-67-5E (hex) Extreme Networks, Inc. +C8675E (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +9C-5D-12 (hex) Extreme Networks, Inc. +9C5D12 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +F0-9C-E9 (hex) Extreme Networks, Inc. +F09CE9 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +C4-13-E2 (hex) Extreme Networks, Inc. +C413E2 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +00-0A-0D (hex) Amphenol +000A0D (base 16) Amphenol + Holzhauser Strasse 175 + Berlin 13509 + DE + +7C-8A-E1 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +7C8AE1 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +54-E4-A9 (hex) BHR Tech GmbH +54E4A9 (base 16) BHR Tech GmbH + Georg-Franz-Koller-Straße 18 + Bisamberg 2102 + AT + +20-80-58 (hex) Ciena Corporation +208058 (base 16) Ciena Corporation + 7035 Ridge Road + Hanover MD 21076 + US + +68-4A-AE (hex) HUAWEI TECHNOLOGIES CO.,LTD +684AAE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +60-D7-55 (hex) HUAWEI TECHNOLOGIES CO.,LTD +60D755 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-45-CD (hex) IoT Diagnostics +A445CD (base 16) IoT Diagnostics + 10052 Commerce Park Drive + Cincinnati OH 45246 + US + +94-62-69 (hex) ARRIS Group, Inc. +946269 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D0-DD-49 (hex) Juniper Networks +D0DD49 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +C8-63-FC (hex) ARRIS Group, Inc. +C863FC (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +1C-CC-D6 (hex) Xiaomi Communications Co Ltd +1CCCD6 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +A8-C2-52 (hex) Huawei Device Co., Ltd. +A8C252 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +A0-41-47 (hex) Huawei Device Co., Ltd. +A04147 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +1C-AE-CB (hex) HUAWEI TECHNOLOGIES CO.,LTD +1CAECB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +4C-F1-9E (hex) Groupe Atlantic +4CF19E (base 16) Groupe Atlantic + Ideal Boilers, National Ave + Hull East Yorkshire HU5 4JB + GB + +04-ED-33 (hex) Intel Corporate +04ED33 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +20-36-D7 (hex) Shanghai Reacheng Communication Technology Co.,Ltd +2036D7 (base 16) Shanghai Reacheng Communication Technology Co.,Ltd + No. 80, Lane 1505 Zuchongzhi Road + Shanghai Shanghai 201203 + CN + +68-07-0A (hex) TPVision Europe B.V +68070A (base 16) TPVision Europe B.V + Prins Bernhardplein 200 + Amsterdam Noord-Holland 1097 JB + NL + +4C-EB-BD (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +4CEBBD (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +7C-C9-26 (hex) Wuhan GreeNet Information Service Co.,Ltd. +7CC926 (base 16) Wuhan GreeNet Information Service Co.,Ltd. + 4-6F, Building 2, Phase 6, Optical Valley Software Park, East Lake High-Tech Development Zone + Wuhan 430000 + CN + +5C-75-AF (hex) Fitbit, Inc. +5C75AF (base 16) Fitbit, Inc. + 199 Fremont Street, 14th Fl + San Francisco CA 94105 + US + +38-BA-B0 (hex) Broadcom +38BAB0 (base 16) Broadcom + 1320 Ridder Park + San Jose CA 95131 + US + +70-87-9E (hex) Beken Corporation +70879E (base 16) Beken Corporation + Building 41, Capital of Tech Leaders, 1387 Zhangdong Road, Zhangjiang High-Tech Park, Pudong New District + Shanghai 201203 + CN + +B4-50-62 (hex) EmBestor Technology Inc. +B45062 (base 16) EmBestor Technology Inc. + 7F, No.1, Chin-Shan 8th St + Hsin-Chu, Taiwan 300 + TW + +04-4A-6C (hex) HUAWEI TECHNOLOGIES CO.,LTD +044A6C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +38-FB-14 (hex) HUAWEI TECHNOLOGIES CO.,LTD +38FB14 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F0-E4-A2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F0E4A2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-51-89 (hex) SG Wireless Limited +7C5189 (base 16) SG Wireless Limited + RM 504 5/F Sun Fung Industrial Building 8-12 Ma Kok Street + Tsuen Wan NA + HK + +7C-B2-7D (hex) Intel Corporate +7CB27D (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +10-63-C8 (hex) Liteon Technology Corporation +1063C8 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +58-20-59 (hex) Xiaomi Communications Co Ltd +582059 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +90-27-2B (hex) Algorab S.r.l. +90272B (base 16) Algorab S.r.l. + Via Luigi Negrelli, 21/13 + Lavis TN 38015 + IT + +4C-BC-B4 (hex) ABB SpA - DIN Rail +4CBCB4 (base 16) ABB SpA - DIN Rail + V.le dell'industria 18 + Vittuone Milan 20010 + IT + +94-D5-05 (hex) Fiberhome Telecommunication Technologies Co.,LTD +94D505 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +74-E1-B6 (hex) Apple, Inc. +74E1B6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +24-A5-2C (hex) HUAWEI TECHNOLOGIES CO.,LTD +24A52C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +48-27-59 (hex) Levven Electronics Ltd. +482759 (base 16) Levven Electronics Ltd. + 9741 54 Ave NW + Edmonton Alberta T6E 5J4 + CA + +AC-77-13 (hex) Honeywell Safety Products (Shanghai) Co.,Ltd +AC7713 (base 16) Honeywell Safety Products (Shanghai) Co.,Ltd + 430 Li Bing Road Zhang Jiang Hi-Tech ParkPudong New Area + Shanghai Shanghai 201203 + CN + +08-84-9D (hex) Amazon Technologies Inc. +08849D (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +90-BD-E6 (hex) Quectel Wireless Solutions Co., Ltd. +90BDE6 (base 16) Quectel Wireless Solutions Co., Ltd. + 7th Floor, Hongye Building, No.1801 Hongmei Road, Xuhui District + Shanghai 200233 + CN + +18-A4-A9 (hex) Vanu Inc. +18A4A9 (base 16) Vanu Inc. + 81 Hartwell Ave + Lexington MA 02421 + US + +80-E8-2C (hex) Hewlett Packard +80E82C (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +D4-AD-BD (hex) Cisco Systems, Inc +D4ADBD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +24-40-AE (hex) NIIC Technology Co., Ltd. +2440AE (base 16) NIIC Technology Co., Ltd. + Room 8218, Building 3#B, No. 268 Furong Road, Jingkai District + Hefei 230601 + CN + +F4-0E-01 (hex) Apple, Inc. +F40E01 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-95-CE (hex) Apple, Inc. +1495CE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +50-DE-06 (hex) Apple, Inc. +50DE06 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-D1-35 (hex) Xtreme Power Systems +5CD135 (base 16) Xtreme Power Systems + 2440 Kiowa Blvd. N. #102 + Lake Havasu City AZ 86403 + US + +78-69-D4 (hex) Shenyang Vibrotech Instruments Inc. +7869D4 (base 16) Shenyang Vibrotech Instruments Inc. + No 23-2 Yunfeng St. Tiexi Dist. + Shenyang Liaoning 110021 + CN + +08-26-97 (hex) Zyxel Communications Corporation +082697 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +CC-CC-CC (hex) Silicon Laboratories +CCCCCC (base 16) Silicon Laboratories + 7000 W. William Cannon Dr. + Austin TX 78735 + US + +CC-66-0A (hex) Apple, Inc. +CC660A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-1D-43 (hex) Apple, Inc. +FC1D43 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-CB-9F (hex) TECNO MOBILE LIMITED +64CB9F (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +4C-FB-FE (hex) Sercomm Japan Corporation +4CFBFE (base 16) Sercomm Japan Corporation + 8F, 3-1, YuanQu St., NanKang, Taipei 115, Taiwan + Taipei 115 + TW + +C0-CB-F1 (hex) Mobiwire Mobiles (NingBo) Co., LTD +C0CBF1 (base 16) Mobiwire Mobiles (NingBo) Co., LTD + No.999 Dacheng East Road, Fenghua District, Ningbo City , Zhejiang Province, PRC + Ningbo Zhejiang 315500 + CN + +FC-7D-6C (hex) HYESUNG TECHWIN Co., Ltd +FC7D6C (base 16) HYESUNG TECHWIN Co., Ltd + #1509,545,Dunchon-daero, Jungwon-gu + Seongnam Gyeonggi-do 13215 + KR + +E4-7E-9A (hex) zte corporation +E47E9A (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +2C-16-BD (hex) IEEE Registration Authority +2C16BD (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +30-A8-89 (hex) DECIMATOR DESIGN +30A889 (base 16) DECIMATOR DESIGN + UNIT 5 / 11 PRECISION PLACE + VINEYARD NSW 2765 + AU + +B4-A2-EB (hex) IEEE Registration Authority +B4A2EB (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +1C-D5-E2 (hex) Shenzhen YOUHUA Technology Co., Ltd +1CD5E2 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +00-24-E9 (hex) Samsung Electronics Co.,Ltd +0024E9 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3Dong, Yeongtong-Gu + Suwon City Geyonggi Do 443-742 + KR + +68-3B-78 (hex) Cisco Systems, Inc +683B78 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +F8-60-F0 (hex) Aruba, a Hewlett Packard Enterprise Company +F860F0 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +5C-A1-E0 (hex) EmbedWay Technologies +5CA1E0 (base 16) EmbedWay Technologies + 6F, Building 8, No 2388, Chenhang Rd, Shanghai + Shanghai 201114 + CN + +84-D4-12 (hex) Palo Alto Networks +84D412 (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +68-AB-09 (hex) Nokia +68AB09 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +F4-CE-36 (hex) Nordic Semiconductor ASA +F4CE36 (base 16) Nordic Semiconductor ASA + Otto Nielsens veg 12 + Trondheim NO-7052 + NO + +B4-60-77 (hex) Sichuan Changhong Electric Ltd. +B46077 (base 16) Sichuan Changhong Electric Ltd. + No.35,East MianXin Road,MianYang,Sichaun,China. + MianYang SiChuan PRC 621000 + CN + +00-F6-20 (hex) Google, Inc. +00F620 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +F4-33-28 (hex) CIMCON Lighting Inc. +F43328 (base 16) CIMCON Lighting Inc. + 35 Crosby Drive + Bedford MA 01730 + US + +7C-94-2A (hex) HUAWEI TECHNOLOGIES CO.,LTD +7C942A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +1C-B7-96 (hex) HUAWEI TECHNOLOGIES CO.,LTD +1CB796 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +38-47-BC (hex) HUAWEI TECHNOLOGIES CO.,LTD +3847BC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +54-92-09 (hex) HUAWEI TECHNOLOGIES CO.,LTD +549209 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +74-59-09 (hex) HUAWEI TECHNOLOGIES CO.,LTD +745909 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +5C-5A-C7 (hex) Cisco Systems, Inc +5C5AC7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +3C-B7-4B (hex) Technicolor CH USA Inc. +3CB74B (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +00-ED-B8 (hex) KYOCERA Corporation +00EDB8 (base 16) KYOCERA Corporation + 30 Hoji + Kitami, Hokkaido 099-1595 + JP + +9C-99-CD (hex) Voippartners +9C99CD (base 16) Voippartners + Via di Passolombardo 35 + Rome 00133 + IT + +C4-C6-03 (hex) Cisco Systems, Inc +C4C603 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +BC-A1-3A (hex) SES-imagotag +BCA13A (base 16) SES-imagotag + St.-Peter-Gürtel 10b + Graz 8010 + AT + +28-23-F5 (hex) China Mobile (Hangzhou) Information Technology Co., Ltd. +2823F5 (base 16) China Mobile (Hangzhou) Information Technology Co., Ltd. + No. 1600 Yuhangtang Road, Wuchang Street, Yuhang District + Hangzhou Zhejiang 310000 + CN + +F0-10-AB (hex) China Mobile (Hangzhou) Information Technology Co., Ltd. +F010AB (base 16) China Mobile (Hangzhou) Information Technology Co., Ltd. + No. 1600 Yuhang Tong Road, Wuchang Street, Yuhang District + Hangzhou Zhejiang 310000 + CN + +B4-DC-09 (hex) Guangzhou Dawei Communication Co.,Ltd +B4DC09 (base 16) Guangzhou Dawei Communication Co.,Ltd + Zone A 906#, International Business Incubator, No.3 Juquan Road, Huangpu District + Guangzhou Guangdong 510660 + CN + +98-86-5D (hex) Nokia Shanghai Bell Co., Ltd. +98865D (base 16) Nokia Shanghai Bell Co., Ltd. + No.388 Ning Qiao Road,Jin Qiao Pudong Shanghai + Shanghai 201206 + CN + +7C-B5-9B (hex) TP-LINK TECHNOLOGIES CO.,LTD. +7CB59B (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +2C-4F-52 (hex) Cisco Systems, Inc +2C4F52 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +68-A0-3E (hex) HUAWEI TECHNOLOGIES CO.,LTD +68A03E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B8-C3-85 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B8C385 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +4C-E9-E4 (hex) New H3C Technologies Co., Ltd +4CE9E4 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +AC-DB-48 (hex) ARRIS Group, Inc. +ACDB48 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +C8-0D-32 (hex) Holoplot GmbH +C80D32 (base 16) Holoplot GmbH + Ringbahnstr. 12, Hof A2 + Berlin 12099 + DE + +D0-57-94 (hex) Sagemcom Broadband SAS +D05794 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +04-D9-F5 (hex) ASUSTek COMPUTER INC. +04D9F5 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +B8-91-C9 (hex) Handreamnet +B891C9 (base 16) Handreamnet + #1203 Ace High-end Tower II, 61, Digital-ro 26-gil, Guro-Gu + Seoul 08389 + KR + +C8-A7-76 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C8A776 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-00-E2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A400E2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B4-C4-FC (hex) Xiaomi Communications Co Ltd +B4C4FC (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +C8-D6-9D (hex) Arab International Optronics +C8D69D (base 16) Arab International Optronics + El Salam St. + El Salam City Cairo 11371 + EG + +40-5B-D8 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +405BD8 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +54-EC-2F (hex) Ruckus Wireless +54EC2F (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +28-99-C7 (hex) LINDSAY BROADBAND INC +2899C7 (base 16) LINDSAY BROADBAND INC + 2035 2 FISHER DRIVE + PETERBOROUGH Ontario K9J 6X6 + CA + +FC-BD-67 (hex) Arista Networks +FCBD67 (base 16) Arista Networks + 5453 Great America Parkway + Santa Clara CA 95054 + US + +00-25-7E (hex) NEW POS TECHNOLOGY LIMITED +00257E (base 16) NEW POS TECHNOLOGY LIMITED + 6FRM, 6F, China Economic Trade Building + Shenzhen Guangdong 518000 + CN + +48-77-46 (hex) Calix Inc. +487746 (base 16) Calix Inc. + 2777 Orchard Parkway + San Jose CA 95134 + US + +F8-AE-27 (hex) John Deere Electronic Solutions +F8AE27 (base 16) John Deere Electronic Solutions + 1441 44th St N + Fargo ND 58102 + US + +74-45-CE (hex) CRESYN +7445CE (base 16) CRESYN + 8-22,Jamwon-dong + Seoul Seocho-Gu #137-902 + KR + +C4-F7-D5 (hex) Cisco Systems, Inc +C4F7D5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +1C-64-99 (hex) Comtrend Corporation +1C6499 (base 16) Comtrend Corporation + 3F-1, 10 Lane 609, Chongxin Road, Section 5, + New Taipei City, Taiwan 24159 + TW + +68-6D-BC (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +686DBC (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +10-DC-4A (hex) Fiberhome Telecommunication Technologies Co.,LTD +10DC4A (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +88-EF-16 (hex) ARRIS Group, Inc. +88EF16 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +8C-A9-6F (hex) D&M Holdings Inc. +8CA96F (base 16) D&M Holdings Inc. + D&M Building, 2-1 Nisshin-cho + Kawasaki-shi Kanagawa 210-8569 + JP + +7C-D6-61 (hex) Xiaomi Communications Co Ltd +7CD661 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +B0-FD-0B (hex) IEEE Registration Authority +B0FD0B (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +98-B8-BA (hex) LG Electronics (Mobile Communications) +98B8BA (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +0C-E9-9A (hex) ATLS ALTEC +0CE99A (base 16) ATLS ALTEC + 3 RUE DE LA GUIVERNONE ZI DU VERT GALANT + ST OUEN L AUMONE 95310 + FR + +4C-11-AE (hex) Espressif Inc. +4C11AE (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +8C-89-FA (hex) Zhejiang Hechuan Technology Co., Ltd. +8C89FA (base 16) Zhejiang Hechuan Technology Co., Ltd. + No. 9, Fucai Road, Longyou Industrial Zone + Quzhou Zhejiang 324000 + CN + +4C-BC-48 (hex) Cisco Systems, Inc +4CBC48 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +80-D0-4A (hex) Technicolor CH USA Inc. +80D04A (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +48-D8-75 (hex) China TransInfo Technology Co., Ltd +48D875 (base 16) China TransInfo Technology Co., Ltd + Qianfang Building, Phase I, Zhongguancun Software Park, 8 Wangxi Road, Haidian District + Beijing 100085 + CN + +D4-78-9B (hex) Cisco Systems, Inc +D4789B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +48-3F-E9 (hex) HUAWEI TECHNOLOGIES CO.,LTD +483FE9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +14-3C-C3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +143CC3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A8-E5-44 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A8E544 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +18-20-D5 (hex) ARRIS Group, Inc. +1820D5 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +30-50-FD (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +3050FD (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +00-40-BC (hex) ALGORITHMICS LTD. +0040BC (base 16) ALGORITHMICS LTD. + 3 DRAYTON PARK + ENGLAND + GB + +00-40-65 (hex) GTE SPACENET +004065 (base 16) GTE SPACENET + 1700 OLD MEADOW ROAD + MCLEAN VA 22102 + US + +88-E6-4B (hex) Juniper Networks +88E64B (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +D8-D0-90 (hex) Dell Inc. +D8D090 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +50-C4-DD (hex) BUFFALO.INC +50C4DD (base 16) BUFFALO.INC + AKAMONDORI Bld.,30-20,Ohsu 3-chome,Naka-ku + Nagoya Aichi Pref. 460-8315 + JP + +00-84-ED (hex) Private +0084ED (base 16) Private + +E0-02-A5 (hex) ABB Robotics +E002A5 (base 16) ABB Robotics + Hydrovägen 10 + Västerås 721 68 + SE + +F4-2E-7F (hex) Aruba, a Hewlett Packard Enterprise Company +F42E7F (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +B4-CC-04 (hex) Piranti +B4CC04 (base 16) Piranti + 126, Beolmal-ro + Dongan-gu, Anyang-si, Gyeonggi-do 14057 + KR + +B8-D5-26 (hex) Zyxel Communications Corporation +B8D526 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +F0-B9-68 (hex) ITEL MOBILE LIMITED +F0B968 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +04-E5-6E (hex) THUB Co., ltd. +04E56E (base 16) THUB Co., ltd. + #607 2, Busandaehak-ro 63beon-gil, Geumjeong-gu + Busan 46241 + KR + +1C-7F-2C (hex) HUAWEI TECHNOLOGIES CO.,LTD +1C7F2C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +88-BC-C1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +88BCC1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +1C-BF-CE (hex) Shenzhen Century Xinyang Technology Co., Ltd +1CBFCE (base 16) Shenzhen Century Xinyang Technology Co., Ltd + 3F, North Building, Bantian High-tech industrial Zone, No. 2 of Bell Road + Shenzhen Guangdong 518129 + CN + +F8-30-02 (hex) Texas Instruments +F83002 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +A8-A1-59 (hex) ASRock Incorporation +A8A159 (base 16) ASRock Incorporation + 2F., No. 37, Sec. 2, Jhongyang S. Rd., Beitou District, + Taipei 112 + TW + +EC-AD-E0 (hex) D-Link International +ECADE0 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +78-DA-07 (hex) Zhejiang Tmall Technology Co., Ltd. +78DA07 (base 16) Zhejiang Tmall Technology Co., Ltd. + Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District, + Shenzhen Guangdong 518000 + CN + +44-A6-1E (hex) INGRAM MICRO SERVICES +44A61E (base 16) INGRAM MICRO SERVICES + 100 CHEMIN DE BAILLOT + MONTAUBAN 82000 + FR + +38-D2-CA (hex) Zhejiang Tmall Technology Co., Ltd. +38D2CA (base 16) Zhejiang Tmall Technology Co., Ltd. + Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District, Shenzhen Guangdong province + Shenzhen GuangDong 518000 + CN + +10-9E-3A (hex) Zhejiang Tmall Technology Co., Ltd. +109E3A (base 16) Zhejiang Tmall Technology Co., Ltd. + Ali Center,No.3331 Keyuan South RD (Shenzhen bay), Nanshan District, + Shenzhen Guangdong 518000 + CN + +90-4D-C3 (hex) Flonidan A/S +904DC3 (base 16) Flonidan A/S + Islandsvej 29 + Horsens 8700 + DK + +00-0D-F1 (hex) IONIX INC. +000DF1 (base 16) IONIX INC. + Ssangyong IT Twin Tower 604, 442-17, Sangdaewon-dong, Jungwon-gu, + Seongnam-si Gyeonggi-do 462-120 + KR + +00-07-7C (hex) Westermo Network Technologies AB +00077C (base 16) Westermo Network Technologies AB + Stora Sundby + Sweden SE-640 40 + SE + +8C-42-6D (hex) HUAWEI TECHNOLOGIES CO.,LTD +8C426D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +90-F8-91 (hex) Kaonmedia CO., LTD. +90F891 (base 16) Kaonmedia CO., LTD. + 884-3, Seongnam-daero, Bundang-gu + Seongnam-si Gyeonggi-do 13517 + KR + +44-5D-5E (hex) SHENZHEN Coolkit Technology CO.,LTD +445D5E (base 16) SHENZHEN Coolkit Technology CO.,LTD + B09 2nd Floor, T6 ArtZone XiLi, Nanshan Dist + shenzhen guangdong 518110 + CN + +50-AD-71 (hex) Tessolve Semiconductor Private Limited +50AD71 (base 16) Tessolve Semiconductor Private Limited + Plot No: 31, P2, Electronic City Phase II, Electronic City + Bengaluru Karnataka 560100 + IN + +20-2A-C5 (hex) Petite-En +202AC5 (base 16) Petite-En + 1, Gwanak-ro, Gwanak-gu + Seoul 08826 + KR + +A8-BF-3C (hex) HDV Phoelectron Technology Limited +A8BF3C (base 16) HDV Phoelectron Technology Limited + Room 1103, Hang Seng Mongkok Building, 677 Nathan Road,Mongkok + Kowloon Hong Kong 518103 + CN + +D4-F5-27 (hex) SIEMENS AG +D4F527 (base 16) SIEMENS AG + Oestliche Rheinbrückenstraße 50 + Karlsruhe Baden-Württemberg 76181 + DE + +B8-B2-F8 (hex) Apple, Inc. +B8B2F8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-46-0A (hex) Apple, Inc. +98460A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B8-5D-0A (hex) Apple, Inc. +B85D0A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +7C-9A-1D (hex) Apple, Inc. +7C9A1D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +10-30-25 (hex) Apple, Inc. +103025 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-AC-D7 (hex) Shenzhen YOUHUA Technology Co., Ltd +70ACD7 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +54-62-E2 (hex) Apple, Inc. +5462E2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-9D-99 (hex) Apple, Inc. +149D99 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-7B-AC (hex) Nokia +147BAC (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +90-6D-05 (hex) BXB ELECTRONICS CO., LTD +906D05 (base 16) BXB ELECTRONICS CO., LTD + 6F.-1, NO.288-5, Xinya Rd., Qianzhen Dist. + Kaohsiung 80673 + TW + +D4-BB-C8 (hex) vivo Mobile Communication Co., Ltd. +D4BBC8 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +48-95-07 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +489507 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +24-BF-74 (hex) Private +24BF74 (base 16) Private + +CC-DC-55 (hex) Dragonchip Limited +CCDC55 (base 16) Dragonchip Limited + Room 601-2, 6/F, IC Development Centre, No. 6 Science Park West Avenue, Hong Kong Science Park, Shatin, N.T. + Hong Kong NA + HK + +A4-C3-F0 (hex) Intel Corporate +A4C3F0 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +28-FF-B2 (hex) Toshiba Corp. +28FFB2 (base 16) Toshiba Corp. + 1-1 Shibaura 1-Chome, Minato-Ku + Tokyo 105-8001 + JP + +1C-60-D2 (hex) Fiberhome Telecommunication Technologies Co.,LTD +1C60D2 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +F4-B5-AA (hex) zte corporation +F4B5AA (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +E8-AC-AD (hex) zte corporation +E8ACAD (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +08-36-C9 (hex) NETGEAR +0836C9 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +74-5B-C5 (hex) IEEE Registration Authority +745BC5 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +94-40-C9 (hex) Hewlett Packard Enterprise +9440C9 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +A0-41-A7 (hex) NL Ministry of Defense +A041A7 (base 16) NL Ministry of Defense + PO Box 10000 + Noord Holland 1780 CA Den Helder + NL + +E4-46-DA (hex) Xiaomi Communications Co Ltd +E446DA (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +1C-12-B0 (hex) Amazon Technologies Inc. +1C12B0 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +4C-C8-A1 (hex) Cisco Meraki +4CC8A1 (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco null 94158 + US + +4C-BC-98 (hex) IEEE Registration Authority +4CBC98 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +2C-F4-32 (hex) Espressif Inc. +2CF432 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +64-73-66 (hex) Shenzhen Siera Technology Ltd +647366 (base 16) Shenzhen Siera Technology Ltd + Room 2039, Shenhai Building, Wanzhong Village, Bulong Road, Minzhi, Longhua district, City: Shenzhen + Shenzhen Guangdong 518131 + CN + +04-1E-FA (hex) BISSELL Homecare, Inc. +041EFA (base 16) BISSELL Homecare, Inc. + 2345 Walker Ave NW + Grand Rapids MI 49544 + US + +D8-55-75 (hex) Samsung Electronics Co.,Ltd +D85575 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D4-11-A3 (hex) Samsung Electronics Co.,Ltd +D411A3 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +04-BA-8D (hex) Samsung Electronics Co.,Ltd +04BA8D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +74-4D-28 (hex) Routerboard.com +744D28 (base 16) Routerboard.com + Mikrotikls SIA + Riga Riga LV1009 + LV + +A4-11-62 (hex) Arlo Technology +A41162 (base 16) Arlo Technology + 350 East Plumeria Drive + san jose CA 95134 + US + +00-A0-85 (hex) Private +00A085 (base 16) Private + +E0-5A-9F (hex) IEEE Registration Authority +E05A9F (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +8C-5A-F8 (hex) Beijing Xiaomi Electronics Co., Ltd. +8C5AF8 (base 16) Beijing Xiaomi Electronics Co., Ltd. + Building C, QingHe ShunShiJiaYe Technology Park, #66 ZhuFang Rd, HaiDian District + Beijing Beijing 10085 + CN + +D4-58-00 (hex) Fiberhome Telecommunication Technologies Co.,LTD +D45800 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +90-84-2B (hex) LEGO System A/S +90842B (base 16) LEGO System A/S + Aastvej 1 + Billund DK-7190 + DK + +00-26-7E (hex) PARROT SA +00267E (base 16) PARROT SA + 174 Quai de Jemmapes + Paris 75010 + FR + +2C-55-7C (hex) Shenzhen YOUHUA Technology Co., Ltd +2C557C (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +F4-BC-DA (hex) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd +F4BCDA (base 16) Shenzhen Jingxun Software Telecommunication Technology Co.,Ltd + 3/F,A5 Building Zhiyuan Community No.1001,Xueyuan Road Nanshan District + Shenzhen Guangdong 518055 + CN + +00-09-15 (hex) CAS Corp. +000915 (base 16) CAS Corp. + #19, Ganap-Ri + Yangju-Gun Kyunggi-Do 482-841 + KR + +58-D9-C3 (hex) Motorola Mobility LLC, a Lenovo Company +58D9C3 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +2C-73-A0 (hex) Cisco Systems, Inc +2C73A0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +44-3E-07 (hex) Electrolux +443E07 (base 16) Electrolux + Corso Lino Zanussi 24 + Porcia PORDENONE 33080 + IT + +84-85-E6 (hex) Guangdong Asano Technology CO.,Ltd. +8485E6 (base 16) Guangdong Asano Technology CO.,Ltd. + Changsheng Road, Songxia Industrial Park, Songgang, Shishan Town, Nanhai + Foshan Guangdong, China. 528200 + CN + +3C-83-75 (hex) Microsoft Corporation +3C8375 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +00-0A-A8 (hex) ePipe Pty. Ltd. +000AA8 (base 16) ePipe Pty. Ltd. + P.O. Box 1428 + Brisbane Queensland 4066 + AU + +00-29-C2 (hex) Cisco Systems, Inc +0029C2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +18-7C-0B (hex) Ruckus Wireless +187C0B (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +D4-7B-35 (hex) NEO Monitors AS +D47B35 (base 16) NEO Monitors AS + PoBox 384 + Loerenskog Loerenskog 1471 + NO + +00-08-78 (hex) Benchmark Storage Innovations +000878 (base 16) Benchmark Storage Innovations + 3122 Sterling Circle + Boulder CO 80301 + US + +6C-F3-7F (hex) Aruba, a Hewlett Packard Enterprise Company +6CF37F (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +14-07-08 (hex) Private +140708 (base 16) Private + +78-A7-EB (hex) 1MORE +78A7EB (base 16) 1MORE + TianliaoBuilding F14 + New Materials Industrial Park,Xueyuan Blvd Shenzhen, Nanshan District 518005 + CN + +48-5D-36 (hex) Verizon +485D36 (base 16) Verizon + One Verizon Way + Basking Ridge NJ 07030 + US + +20-C0-47 (hex) Verizon +20C047 (base 16) Verizon + One Verizon Way + Basking Ridge 07030 + US + +34-6B-46 (hex) Sagemcom Broadband SAS +346B46 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +7C-60-4A (hex) Avelon +7C604A (base 16) Avelon + Bändliweg 20 + Zurich 8048 + CH + +18-64-72 (hex) Aruba, a Hewlett Packard Enterprise Company +186472 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +84-D4-7E (hex) Aruba, a Hewlett Packard Enterprise Company +84D47E (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +24-DE-C6 (hex) Aruba, a Hewlett Packard Enterprise Company +24DEC6 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +00-17-A0 (hex) RoboTech srl +0017A0 (base 16) RoboTech srl + Via Mazzini 82 + Sarzana (SP) I-19038 + IT + +10-3D-0A (hex) Hui Zhou Gaoshengda Technology Co.,LTD +103D0A (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +94-27-90 (hex) TCT mobile ltd +942790 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +A4-17-91 (hex) Shenzhen Decnta Technology Co.,LTD. +A41791 (base 16) Shenzhen Decnta Technology Co.,LTD. + F13,No.02,Building Shangqi,Nanhaidadao 4050 Nanshan District,Shenzhen,P.R.China + shenzhen Guangdong 518057 + CN + +34-DA-B7 (hex) zte corporation +34DAB7 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +10-9C-70 (hex) Prusa Research s.r.o. +109C70 (base 16) Prusa Research s.r.o. + Partyzanska 188/7a + Prague 17000 + CZ + +E8-4C-56 (hex) INTERCEPT SERVICES LIMITED +E84C56 (base 16) INTERCEPT SERVICES LIMITED + Bates Mill, Colne Road + Huddersfield North Yorkshire HD1 3AG + GB + +A4-19-08 (hex) Fiberhome Telecommunication Technologies Co.,LTD +A41908 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +38-AF-D0 (hex) Private +38AFD0 (base 16) Private + +80-D3-36 (hex) CERN +80D336 (base 16) CERN + CH-1211 + GENEVE SUISSE/SWITZ 023 + CH + +64-25-5E (hex) Observint Technologies, Inc. +64255E (base 16) Observint Technologies, Inc. + 11000 N Mopac Expressway Suite 300 + Austin TX 78759 + US + +90-94-0A (hex) Analog Devices, Inc +90940A (base 16) Analog Devices, Inc + Unit 2200, Airport Business Park, Kinsale Road + Cork T12 X36X + IE + +40-B0-76 (hex) ASUSTek COMPUTER INC. +40B076 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +D4-3D-39 (hex) Dialog Semiconductor +D43D39 (base 16) Dialog Semiconductor + B-7F, SiliconPark, 35, Pangyo-ro 255beon-gil, Bundang-gu + Seongnam-si Gyeonggi-do 13486 + KR + +00-14-A5 (hex) Gemtek Technology Co., Ltd. +0014A5 (base 16) Gemtek Technology Co., Ltd. + No. 1 Jen Ai Road + Hukou, Hsinchu 303 + TW + +C0-B5-D7 (hex) CHONGQING FUGUI ELECTRONICS CO.,LTD. +C0B5D7 (base 16) CHONGQING FUGUI ELECTRONICS CO.,LTD. + Building D21,No.1, East Zone 1st Road,Xiyong Town,Shapingba District + Chongqing Chongqing 401332 + CN + +D4-AD-71 (hex) Cisco Systems, Inc +D4AD71 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +70-2B-1D (hex) E-Domus International Limited +702B1D (base 16) E-Domus International Limited + 1st Floor + London W1W 7BL + GB + +F0-85-C1 (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +F085C1 (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A,6/F,Baotian Rd3,Xixiang Town,Baoan District, + Shenzhen Guangdong 518000 + CN + +60-38-0E (hex) ALPS ELECTRIC CO., LTD. +60380E (base 16) ALPS ELECTRIC CO., LTD. + 1-2-1, Okinouchi + Soma-city Fukushima 976-8501 + JP + +FC-62-B9 (hex) ALPS ELECTRIC CO., LTD. +FC62B9 (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + kakuda-city Miyagi-Pref 981-1595 + JP + +00-02-C7 (hex) ALPS ELECTRIC CO., LTD. +0002C7 (base 16) ALPS ELECTRIC CO., LTD. + 1-2-1, Okinouchi, Sama-City, + Sama 00000 + JP + +00-1E-3D (hex) ALPS ELECTRIC CO., LTD. +001E3D (base 16) ALPS ELECTRIC CO., LTD. + 1-2-1, Okinouchi, + Soma-city, Fukushima-pref., 976-8501 + JP + +28-A1-83 (hex) ALPS ELECTRIC CO., LTD. +28A183 (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + Kakuda Miyagi-Pref 981-1595 + JP + +4C-DD-7D (hex) LHP Telematics LLC +4CDD7D (base 16) LHP Telematics LLC + 17406 Tiller Ct. STE 100 + westfield IN 46074 + US + +48-F0-7B (hex) ALPS ELECTRIC CO., LTD. +48F07B (base 16) ALPS ELECTRIC CO., LTD. + 6-1 + Kakuda Miyagi-Pref 981-1595 + JP + +B8-BC-5B (hex) Samsung Electronics Co.,Ltd +B8BC5B (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +10-8E-BA (hex) Molekule +108EBA (base 16) Molekule + 1184 Harrison Street + San Francisco 94103 + US + +4C-21-8C (hex) Panasonic India Private limited +4C218C (base 16) Panasonic India Private limited + 12th floor, Ambience tower, Ambience Island + Gurgaon Haryana 122002 + IN + +2C-4E-7D (hex) Chunghua Intelligent Network Equipment Inc. +2C4E7D (base 16) Chunghua Intelligent Network Equipment Inc. + 2F-3, No.5, Sec. 3, New Taipei Blvd.,, XinZhung Dist, + New Taipei City 選擇州 242 + TW + +A4-F4-65 (hex) ITEL MOBILE LIMITED +A4F465 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +4C-91-7A (hex) IEEE Registration Authority +4C917A (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F4-8C-EB (hex) D-Link International +F48CEB (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +74-3A-65 (hex) NEC Corporation +743A65 (base 16) NEC Corporation + 7-1, Shiba 5-chome, Minato-ku + Tokyo 108-8001 + JP + +00-25-5C (hex) NEC Corporation +00255C (base 16) NEC Corporation + 1753, Shimonumabe, Nakahara-Ku, Kawasaki + Kanagawa 211-8666 + JP + +68-4F-64 (hex) Dell Inc. +684F64 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +CC-70-ED (hex) Cisco Systems, Inc +CC70ED (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +90-7E-30 (hex) LARS +907E30 (base 16) LARS + Swierkowa 14 + Niepruszewo 64-320 + PL + +84-EB-3E (hex) Vivint Smart Home +84EB3E (base 16) Vivint Smart Home + 4931 N. 300 W. + Provo UT 84604 + US + +00-A0-D5 (hex) Sierra Wireless +00A0D5 (base 16) Sierra Wireless + 13811 Wireless Way + Richmond RICHMOND B.C. V6V 3A4 + CA + +18-BB-26 (hex) FN-LINK TECHNOLOGY LIMITED +18BB26 (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +18-B9-05 (hex) Hong Kong Bouffalo Lab Limited +18B905 (base 16) Hong Kong Bouffalo Lab Limited + RM 1903, 19/F Lee Garden One 33 Hysan Avenue, Causeway Bay + HongKong 999077 + HK + +EC-F0-FE (hex) zte corporation +ECF0FE (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +94-A4-0C (hex) Diehl Metering GmbH +94A40C (base 16) Diehl Metering GmbH + Industriestrasse 13 + Ansbach 91522 + DE + +70-B3-17 (hex) Cisco Systems, Inc +70B317 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B0-02-47 (hex) AMPAK Technology, Inc. +B00247 (base 16) AMPAK Technology, Inc. + 3F.,No.15-1 Zhonghua Road,Hsinchu Industrial Park, Hukou,Hsinchu + Hsinchu Taiwan ROC. 30352 + TW + +BC-E7-96 (hex) Wireless CCTV Ltd +BCE796 (base 16) Wireless CCTV Ltd + charles Babbage house + Rochdale Greater Manchester ol164nw + GB + +94-8F-CF (hex) ARRIS Group, Inc. +948FCF (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +A8-F5-DD (hex) ARRIS Group, Inc. +A8F5DD (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +44-D3-AD (hex) Shenzhen TINNO Mobile Technology Corp. +44D3AD (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F, H-3 Building, Qiao Cheng Eastern Industrial Park, Overseas Chinese Town, Shenzhen + Shenzhen guangdong 518053 + CN + +9C-82-75 (hex) Yichip Microelectronics (Hangzhou) Co.,Ltd +9C8275 (base 16) Yichip Microelectronics (Hangzhou) Co.,Ltd + Room 401, Building 15, No.498 Guoshoujing Road, Pudong Software Park + Shanghai 200120 + CN + +5C-CB-CA (hex) FUJIAN STAR-NET COMMUNICATION CO.,LTD +5CCBCA (base 16) FUJIAN STAR-NET COMMUNICATION CO.,LTD + 19-22# Building, Star-net Science Plaza, Juyuanzhou, + FUZHOU FUJIAN 350002 + CN + +28-E9-8E (hex) Mitsubishi Electric Corporation +28E98E (base 16) Mitsubishi Electric Corporation + 2-7-3 Marunouchi Chiyoda-ku + Tokyo 100-8310 + JP + +34-F8-E7 (hex) Cisco Systems, Inc +34F8E7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B0-90-7E (hex) Cisco Systems, Inc +B0907E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +2C-73-60 (hex) Earda Technologies co Ltd +2C7360 (base 16) Earda Technologies co Ltd + Block A,Lianfeng Creative Park, #2 Jisheng Rd., Nansha District + Guangzhou Guangdong 511455 + CN + +50-8C-F5 (hex) China Mobile Group Device Co.,Ltd. +508CF5 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +1C-54-9E (hex) Universal Electronics, Inc. +1C549E (base 16) Universal Electronics, Inc. + 201 E. Sandpointe Ave + Santa Ana CA 92707 + US + +E4-CA-12 (hex) zte corporation +E4CA12 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +D4-9E-05 (hex) zte corporation +D49E05 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +58-5F-F6 (hex) zte corporation +585FF6 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +40-B3-0E (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +40B30E (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +04-CE-7E (hex) NXP France Semiconductors France +04CE7E (base 16) NXP France Semiconductors France + Parc les Algorithmes,Saint Aubin + Gif sur Yvette 91193 + FR + +C0-9A-D0 (hex) Apple, Inc. +C09AD0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +94-B0-1F (hex) Apple, Inc. +94B01F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-CC-4D (hex) Shenzhen mantunsci co., LTD +98CC4D (base 16) Shenzhen mantunsci co., LTD + 3 floor, 3 environmental protection industrial park, Nanshan District + Shenzhen Guangdong 518000 + CN + +C0-1B-23 (hex) SICHUAN TIANYI COMHEART TELECOM CO.,LTD +C01B23 (base 16) SICHUAN TIANYI COMHEART TELECOM CO.,LTD + NO.198 FIRST SECTION,SNOW MOUNTAIN AVENUE, JINYUAN TOWN, DAYI COUNTY, + CHENGDU SICHUAN 611330 + CN + +B8-C7-4A (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +B8C74A (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +D8-CE-3A (hex) Xiaomi Communications Co Ltd +D8CE3A (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +10-2C-6B (hex) AMPAK Technology, Inc. +102C6B (base 16) AMPAK Technology, Inc. + 3F.,No.15-1 Zhonghua Road,Hsinchu Industrial Park, Hukou,Hsinchu, Taiwan (R.O.C.) + Hsinchu Taiwan ROC. 30352 + TW + +74-85-C4 (hex) New H3C Technologies Co., Ltd +7485C4 (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +94-F6-D6 (hex) Apple, Inc. +94F6D6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-2D-7C (hex) Apple, Inc. +F82D7C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-BA-E4 (hex) Shanghai MXCHIP Information Technology Co., Ltd. +D0BAE4 (base 16) Shanghai MXCHIP Information Technology Co., Ltd. + Room 811,Tongpu Building + Shanghai Shanghai 200333 + CN + +48-D3-5D (hex) Private +48D35D (base 16) Private + +80-FB-F0 (hex) Quectel Wireless Solutions Co., Ltd. +80FBF0 (base 16) Quectel Wireless Solutions Co., Ltd. + 7th Floor, Hongye Building, No.1801 Hongmei Road, Xuhui District + Shanghai 200233 + CN + +C0-13-2B (hex) Sichuan Changhong Electric Ltd. +C0132B (base 16) Sichuan Changhong Electric Ltd. + No.35,East MianXin Road,MianYang,Sichaun,China. + MianYang SiChuan PRC 621000 + CN + +0C-B4-A4 (hex) Xintai Automobile Intelligent Network Technology +0CB4A4 (base 16) Xintai Automobile Intelligent Network Technology + Room3703E Changfu Jinmao Building,Shihua Road + Futian Duty Free Zone,Fubao Street,Futian District Shenzhen City 518000 + CN + +90-63-3B (hex) Samsung Electronics Co.,Ltd +90633B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +FC-AA-B6 (hex) Samsung Electronics Co.,Ltd +FCAAB6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C8-2E-47 (hex) Suzhou SmartChip Semiconductor Co., LTD +C82E47 (base 16) Suzhou SmartChip Semiconductor Co., LTD + 9A,Science Plaza,1355 JinJiHu Avenue, Suzhou Industrial Park, + Suzhou Jiangsu 215021 + CN + +C0-22-50 (hex) Koss Corporation +C02250 (base 16) Koss Corporation + 4129 N. Port Washington Ave. + Milwaukee WI 53212 + US + +A0-B5-49 (hex) Arcadyan Corporation +A0B549 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +00-1F-5A (hex) Beckwith Electric Co. +001F5A (base 16) Beckwith Electric Co. + 6190 118th Ave No + Largo Florida 33773 + US + +98-5D-82 (hex) Arista Networks +985D82 (base 16) Arista Networks + 5453 Great America Parkway + Santa Clara CA 95054 + US + +24-53-BF (hex) Enernet +2453BF (base 16) Enernet + 1007 B-dong, Hyundai Knowledge Industry Center, 70 Dusan-ro, Geumcheon-gu, Seoul, KOREA + SEOUL 08584 + KR + +04-33-85 (hex) Nanchang BlackShark Co.,Ltd. +043385 (base 16) Nanchang BlackShark Co.,Ltd. + Room 319, Jiaoqiao Town Office Building, Economic and Technical development zone, Nanchang City, Jiangxi Province. + Nanchang 330013 + CN + +84-E5-D8 (hex) Guangdong UNIPOE IoT Technology Co.,Ltd. +84E5D8 (base 16) Guangdong UNIPOE IoT Technology Co.,Ltd. + 11th Fl., BLDG. B1, Guangda WE Valley, Songshan Lake District + Dongguan Guangdong 523808 + CN + +A8-BC-9C (hex) Cloud Light Technology Limited +A8BC9C (base 16) Cloud Light Technology Limited + 3/F, 6 Science Park East Avenue Hong Kong Science Park Shatin, N.T., Hong Kong + Hong Kong 00000 + HK + +A8-90-42 (hex) Beijing Wanwei Intelligent Technology Co., Ltd. +A89042 (base 16) Beijing Wanwei Intelligent Technology Co., Ltd. + Room 616, Section 1, Cuicing, No. 1 Shanyuan Street, Haidian District + Beijing Beijing 100000 + CN + +18-BE-92 (hex) Delta Networks, Inc. +18BE92 (base 16) Delta Networks, Inc. + 256 Yang Guang Street, Neihu + Taipei Taiwan 11491 + TW + +90-C5-4A (hex) vivo Mobile Communication Co., Ltd. +90C54A (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +BC-75-96 (hex) Beijing Broadwit Technology Co., Ltd. +BC7596 (base 16) Beijing Broadwit Technology Co., Ltd. + Beijing Changping District Beijing International Information Industry Base Jizhida Building 3rd Floor Southeast + Beijing Beijing 10000 + CN + +1C-34-DA (hex) Mellanox Technologies, Inc. +1C34DA (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +2C-A0-2F (hex) Veroguard Systems Pty Ltd +2CA02F (base 16) Veroguard Systems Pty Ltd + PO Box 5003 + Clayton VIC 3168 + AU + +6C-5C-3D (hex) IEEE Registration Authority +6C5C3D (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +78-23-27 (hex) Samsung Electronics Co.,Ltd +782327 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +DC-F7-56 (hex) Samsung Electronics Co.,Ltd +DCF756 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +68-A4-7D (hex) Sun Cupid Technology (HK) LTD +68A47D (base 16) Sun Cupid Technology (HK) LTD + 16/F, CEO Tower, 77 Wing Hong Street, Kowloon + Hong Kong 00000 + HK + +18-4B-0D (hex) Ruckus Wireless +184B0D (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +D4-12-43 (hex) AMPAK Technology, Inc. +D41243 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +48-A6-B8 (hex) Sonos, Inc. +48A6B8 (base 16) Sonos, Inc. + 614 Chapala St + Santa Barbara CA 93101 + US + +B8-78-26 (hex) Nintendo Co.,Ltd +B87826 (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +50-76-AF (hex) Intel Corporate +5076AF (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +DC-CB-A8 (hex) Explora Technologies Inc +DCCBA8 (base 16) Explora Technologies Inc + 360, Franquet Street + Quebec G1P 4N3 + CA + +C0-78-78 (hex) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. +C07878 (base 16) FLEXTRONICS MANUFACTURING(ZHUHAI)CO.,LTD. + Xin Qing Science & Technology Industrial Park,Jin An Town,Doumen ,Zhuhai,Guangdong,PRC + Zhuhai Guangdong 519180 + CN + +E4-B9-7A (hex) Dell Inc. +E4B97A (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-16-36 (hex) QUANTA COMPUTER INC. +001636 (base 16) QUANTA COMPUTER INC. + No. 211, Wen Hwa 2Rd., Kuei Shan Hsiang + Tao Yuan Shien 0000 + TW + +34-DA-C1 (hex) SAE Technologies Development(Dongguan) Co., Ltd. +34DAC1 (base 16) SAE Technologies Development(Dongguan) Co., Ltd. + Winnerway Industrial Area,Nancheng + Dongguan City Guangdong Province 523087 + CN + +70-5D-CC (hex) EFM Networks +705DCC (base 16) EFM Networks + 6F, Benposra II 1197-1 Bojeong Giheung Gu + Yong In Kyunggi do 446913 + KR + +D0-92-FA (hex) Fiberhome Telecommunication Technologies Co.,LTD +D092FA (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +E8-5A-D1 (hex) Fiberhome Telecommunication Technologies Co.,LTD +E85AD1 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +A8-23-FE (hex) LG Electronics +A823FE (base 16) LG Electronics + 222 LG-ro, JINWI-MYEON + Pyeongtaek-si Gyeonggi-do 451-713 + KR + +E0-5D-5C (hex) Oy Everon Ab +E05D5C (base 16) Oy Everon Ab + Teräskatu 8 + Turku 20520 + FI + +68-8F-2E (hex) Hitron Technologies. Inc +688F2E (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +E0-46-E5 (hex) Gosuncn Technology Group Co., Ltd. +E046E5 (base 16) Gosuncn Technology Group Co., Ltd. + 6F, 2819 KaiChuang Blvd., Science Town, Huangpu District + Guangzhou City Guangdong 510530 + CN + +1C-59-9B (hex) HUAWEI TECHNOLOGIES CO.,LTD +1C599B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D4-BD-1E (hex) 5VT Technologies,Taiwan LTd. +D4BD1E (base 16) 5VT Technologies,Taiwan LTd. + 6F,No.19-9,SanChong Rd.,Nangang Dist, + Taipei 11501 + TW + +BC-9B-68 (hex) Technicolor CH USA Inc. +BC9B68 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +CC-D4-A1 (hex) MitraStar Technology Corp. +CCD4A1 (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +08-BA-5F (hex) Qingdao Hisense Electronics Co.,Ltd. +08BA5F (base 16) Qingdao Hisense Electronics Co.,Ltd. + Qianwangang Roard 218 + Qingdao Shandong 266510 + CN + +10-DF-FC (hex) Siemens AG +10DFFC (base 16) Siemens AG + Siemensstrasse 10 + Regensburg 93055 + DE + +84-7F-3D (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +847F3D (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +C4-FD-E6 (hex) DRTECH +C4FDE6 (base 16) DRTECH + 29, Dunchon-daero 541beon-gil, Jungwon-gu + Seongnam Gyeonggi-do 13216 + KR + +CC-98-8B (hex) SONY Visual Products Inc. +CC988B (base 16) SONY Visual Products Inc. + 2-10-1 Osaki + Shinagawa-ku Tokyo 141-8610 + JP + +30-E3-D6 (hex) Spotify USA Inc. +30E3D6 (base 16) Spotify USA Inc. + 45 West 18th Street + New York NY 10011 + US + +9C-A5-25 (hex) Shandong USR IOT Technology Limited +9CA525 (base 16) Shandong USR IOT Technology Limited + Floor 11,Building 1,No.1166 Xinluo Street,Gaoxin District,Jinan,Shandong,250101,China + Jinan Shandong 250101 + CN + +E0-45-6D (hex) China Mobile Group Device Co.,Ltd. +E0456D (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +28-39-26 (hex) CyberTAN Technology Inc. +283926 (base 16) CyberTAN Technology Inc. + 99 Park Ave III, Hsinchu Science Park + Hsinchu 308 + TW + +8C-FC-A0 (hex) Shenzhen Smart Device Technology Co., LTD. +8CFCA0 (base 16) Shenzhen Smart Device Technology Co., LTD. + SSMEC Building,Gao Xin Nan First Avenue Hi-Tech Park South,Nanshan + Shenzhen GuangDong 518057 + CN + +1C-42-7D (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +1C427D (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +80-69-33 (hex) HUAWEI TECHNOLOGIES CO.,LTD +806933 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +BC-26-C7 (hex) Cisco Systems, Inc +BC26C7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +BC-5E-A1 (hex) PsiKick, Inc. +BC5EA1 (base 16) PsiKick, Inc. + 2348 Walsh Ave + Santa Clara CA 95051 + US + +94-4F-4C (hex) Sound United LLC +944F4C (base 16) Sound United LLC + One Viper Way + Vista CA 92081 + US + +98-18-88 (hex) Cisco Meraki +981888 (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco null 94158 + US + +18-81-0E (hex) Apple, Inc. +18810E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-8C-4A (hex) Apple, Inc. +608C4A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +74-B5-87 (hex) Apple, Inc. +74B587 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-B6-D8 (hex) Apple, Inc. +FCB6D8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-6A-2C (hex) IEEE Registration Authority +3C6A2C (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +24-1B-7A (hex) Apple, Inc. +241B7A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +8C-FE-57 (hex) Apple, Inc. +8CFE57 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-A6-00 (hex) Apple, Inc. +C0A600 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-E8-29 (hex) Ubiquiti Networks Inc. +18E829 (base 16) Ubiquiti Networks Inc. + 2580 Orchard Pkwy + San Jose CA 95131 + US + +E0-C2-86 (hex) Aisai Communication Technology Co., Ltd. +E0C286 (base 16) Aisai Communication Technology Co., Ltd. + Room 2610 Asia Trade Centre, + Kwai Chung N.T. 852 + HK + +74-05-A5 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +7405A5 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +28-6D-CD (hex) Beijing Winner Microelectronics Co.,Ltd. +286DCD (base 16) Beijing Winner Microelectronics Co.,Ltd. + Floor 18, YinDu Building, No.67 FuCheng Road, HaiDian District + Beijing 100142 + CN + +54-10-31 (hex) SMARTO +541031 (base 16) SMARTO + 25 QUAI GALLIENI + SURESNES HAUT DE SEINE 92150 + FR + +44-A4-66 (hex) GROUPE LDLC +44A466 (base 16) GROUPE LDLC + Groupe LDLC - 2 rue des Erables + LIMONEST Rhone 69760 + FR + +D8-0D-17 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +D80D17 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +18-C2-BF (hex) BUFFALO.INC +18C2BF (base 16) BUFFALO.INC + AKAMONDORI Bld.,30-20,Ohsu 3-chome,Naka-ku + Nagoya Aichi Pref. 460-8315 + JP + +E8-1C-BA (hex) Fortinet, Inc. +E81CBA (base 16) Fortinet, Inc. + 899 Kifer Road + Sunnyvale null 94086 + US + +F0-B0-14 (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +F0B014 (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +18-89-A0 (hex) Wuhan Funshion Online Technologies Co.,Ltd +1889A0 (base 16) Wuhan Funshion Online Technologies Co.,Ltd + 5th Floor,Financial Port Building A9,No.77 Optical Valley Avenue, East Lake High-Tech Development Zone, Wuhan + Wuhan CN/Hubei 430000 + CN + +0C-2A-86 (hex) Fiberhome Telecommunication Technologies Co.,LTD +0C2A86 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +FC-61-E9 (hex) Fiberhome Telecommunication Technologies Co.,LTD +FC61E9 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +40-56-62 (hex) GuoTengShengHua Electronics LTD. +405662 (base 16) GuoTengShengHua Electronics LTD. + 1st floor,No. 15 of Tech North 2nd Road,Nanshan District, + Shenzhen Guangdong 518000 + CN + +E4-DB-6D (hex) Beijing Xiaomi Electronics Co., Ltd. +E4DB6D (base 16) Beijing Xiaomi Electronics Co., Ltd. + Building C, QingHe ShunShiJiaYe Technology Park, #66 ZhuFang Rd, HaiDian District + Beijing Beijing 10085 + CN + +00-A0-D1 (hex) INVENTEC CORPORATION +00A0D1 (base 16) INVENTEC CORPORATION + INVENTEC BUILDING + TAIWAN TAIWAN R.O.C. + TW + +00-18-CC (hex) AXIOHM SAS +0018CC (base 16) AXIOHM SAS + 1 RUE D'ARCUEIL + MONTROUGE 92120 + FR + +00-18-27 (hex) NEC UNIFIED SOLUTIONS NEDERLAND B.V. +001827 (base 16) NEC UNIFIED SOLUTIONS NEDERLAND B.V. + ANTON PHILIPSWEG 1 + HILVERSUM NH 1223KZ + NL + +00-90-04 (hex) 3COM EUROPE LTD +009004 (base 16) 3COM EUROPE LTD + 3COM CENTRE, BOUNDARY WAY + HERTS. HP2 7YU 00000 + GB + +00-06-8C (hex) 3COM +00068C (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +02-60-8C (hex) 3COM +02608C (base 16) 3COM + 5400 BAYFRONT PLAZA + SANTA CLARA CA 95052 + US + +00-D0-D8 (hex) 3COM +00D0D8 (base 16) 3COM + 2133 LEGHORN STREET + MOUNTAIN VIEW CA 94043 + US + +18-93-7F (hex) AMPAK Technology, Inc. +18937F (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +A4-35-23 (hex) Guangdong Donyan Network Technologies Co.,Ltd. +A43523 (base 16) Guangdong Donyan Network Technologies Co.,Ltd. + No.6,Kejizhong Road,Chuangye Building,Hi-tech Zone + Shantou Guangdong 515000 + CN + +B4-A9-4F (hex) MERCURY CORPORATION +B4A94F (base 16) MERCURY CORPORATION + 90, Gajaeul-ro, Seo-gu + INCHEON 22830 + KR + +80-3A-F4 (hex) Fiberhome Telecommunication Technologies Co.,LTD +803AF4 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +48-A0-F8 (hex) Fiberhome Telecommunication Technologies Co.,LTD +48A0F8 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +F8-5E-3C (hex) SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD +F85E3C (base 16) SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD + 4F,Bldg A2,Hedian Industrial Park,NO.8 Shijing Rd,Guanlan,Longhua District,ShenZhen,China + shengzhen 518110 + CN + +28-3E-76 (hex) Common Networks +283E76 (base 16) Common Networks + 1390 Market St. Suite 820 + San Francisco CA 94102 + US + +DC-39-79 (hex) Cisco Systems, Inc +DC3979 (base 16) Cisco Systems, Inc + 280 Hope Street + Mountain View CA 94041 + US + +58-D5-6E (hex) D-Link International +58D56E (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +0C-53-31 (hex) ETH Zurich +0C5331 (base 16) ETH Zurich + Dept. Computer Science, Universitätstr. 6 + Zurich ZH 8092 + CH + +DC-90-88 (hex) HUAWEI TECHNOLOGIES CO.,LTD +DC9088 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +54-81-2D (hex) PAX Computer Technology(Shenzhen) Ltd. +54812D (base 16) PAX Computer Technology(Shenzhen) Ltd. + 4/F, No.3 Building, Software Park, Second Central Science-Tech Road, High-Tech + Shenzhen GuangDong 518057 + CN + +0C-9A-42 (hex) FN-LINK TECHNOLOGY LIMITED +0C9A42 (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +00-08-09 (hex) Systemonic AG +000809 (base 16) Systemonic AG + Am Waldschloesschen 1 + + DE + +8C-41-F4 (hex) IPmotion GmbH +8C41F4 (base 16) IPmotion GmbH + Ludwig-Rinn-Straße 8-16 + Heuchelheim Hessen 35452 + DE + +70-4F-08 (hex) Shenzhen Huisheng Information Technology Co., Ltd. +704F08 (base 16) Shenzhen Huisheng Information Technology Co., Ltd. + Room 4A-205, Software Industry Base, Yuehai St + Nanshan District, Shenzhen Guangdong 518000 + CN + +88-35-C1 (hex) OI ELECTRIC CO.,LTD +8835C1 (base 16) OI ELECTRIC CO.,LTD + 7-3-16 KIKUNA + YOKOHAMA KANAGAWA-KEN 222-0011 + JP + +30-42-A1 (hex) ilumisys Inc. DBA Toggled +3042A1 (base 16) ilumisys Inc. DBA Toggled + 1820 E. Big Beaver Road + Troy MI 48083 + US + +00-26-B7 (hex) Kingston Technology Company, Inc. +0026B7 (base 16) Kingston Technology Company, Inc. + 17600 Newhope St. + Fountain Valley CA 92708 + US + +28-D0-CB (hex) Cambridge Communication Systems Ltd +28D0CB (base 16) Cambridge Communication Systems Ltd + Victory House, Vision Park, Chivers Way, Histon + Cambridge CB24 9ZR + GB + +44-65-7F (hex) Calix Inc. +44657F (base 16) Calix Inc. + 2777 Orchard Parkway + San Jose CA 95134 + US + +40-62-EA (hex) China Mobile Group Device Co.,Ltd. +4062EA (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +4C-0F-C7 (hex) Earda Technologies co Ltd +4C0FC7 (base 16) Earda Technologies co Ltd + 5/F,Block 2 East area,Haosheng Industrial Park, + Guangzhou Guangdong 511400 + CN + +80-A7-96 (hex) Neurotek LLC +80A796 (base 16) Neurotek LLC + 3180 18th St, Ste 200 + San Francisco CA 94110 + US + +CC-21-19 (hex) Samsung Electronics Co.,Ltd +CC2119 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +30-23-03 (hex) Belkin International Inc. +302303 (base 16) Belkin International Inc. + 12045 East Waterfront Drive + Playa Vista null 90094 + US + +9C-F6-DD (hex) IEEE Registration Authority +9CF6DD (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-1E-80 (hex) Icotera A/S +001E80 (base 16) Icotera A/S + Vibeholms Allé 16 + Brøndby 2605 + DK + +48-88-1E (hex) EthoSwitch LLC +48881E (base 16) EthoSwitch LLC + 1298 Evans Road + Wall Township NJ 07719 + US + +3C-71-BF (hex) Espressif Inc. +3C71BF (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +00-03-93 (hex) Apple, Inc. +000393 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-00-C3 (hex) Harris Corporation +0000C3 (base 16) Harris Corporation + 1025 West NASA Blvd + Melbourne FL 32919 + US + +30-4B-07 (hex) Motorola Mobility LLC, a Lenovo Company +304B07 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +34-5A-BA (hex) tcloud intelligence +345ABA (base 16) tcloud intelligence + Bao'an District, No. 400 Xiangshan Avenue + ShenZhen GuangDong 518105 + CN + +50-2F-A8 (hex) Cisco Systems, Inc +502FA8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B4-69-21 (hex) Intel Corporate +B46921 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +90-2B-D2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +902BD2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +08-D5-9D (hex) Sagemcom Broadband SAS +08D59D (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +C0-83-59 (hex) IEEE Registration Authority +C08359 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +EC-83-D5 (hex) GIRD Systems Inc +EC83D5 (base 16) GIRD Systems Inc + 11260 Chester Road, Ste. 600 + Cincinnati OH 45246 + US + +14-94-2F (hex) USYS CO.,LTD. +14942F (base 16) USYS CO.,LTD. + #911, SeoulTechnoPark, 232, Gongneung-ro, Nowon-gu + Seoul KS013 + KR + +FC-B1-0D (hex) Shenzhen Tian Kun Technology Co.,LTD. +FCB10D (base 16) Shenzhen Tian Kun Technology Co.,LTD. + Layer 8,Nanyuan Maple Building,No.1088 Nanshan Avenue,Nanshan Street,Nanshan District,Shenzhen + Shenzhen Guangdong 518048 + CN + +20-F7-7C (hex) vivo Mobile Communication Co., Ltd. +20F77C (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +00-1E-EC (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +001EEC (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street + KUNSHAN CITY SUZHOU PROVINCE 215300 + CN + +F0-76-1C (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +F0761C (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 15, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +00-04-AE (hex) Sullair Corporation +0004AE (base 16) Sullair Corporation + 3700 East Michigan Blvd + Michigan City IN 46360 + US + +00-45-1D (hex) Cisco Systems, Inc +00451D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A0-D6-35 (hex) WBS Technology +A0D635 (base 16) WBS Technology + Unit32, 2 Slough Ave, Slough Business Park + Silverwater New South Wales 2128 + AU + +34-80-0D (hex) Cavium Inc +34800D (base 16) Cavium Inc + 15485 Sand Canyon Ave + Irvine CA 92618 + US + +B4-4B-D6 (hex) IEEE Registration Authority +B44BD6 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D8-91-2A (hex) Zyxel Communications Corporation +D8912A (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +3C-42-7E (hex) IEEE Registration Authority +3C427E (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-0B-A3 (hex) Siemens AG +000BA3 (base 16) Siemens AG + Werner-von-Siemens-Straße 65 + Erlangen Bavaria 91052 + DE + +00-0C-8A (hex) Bose Corporation +000C8A (base 16) Bose Corporation + Automotive Systems Division (ASD) + Stow MA 01775-9102 + US + +24-3A-82 (hex) IRTS +243A82 (base 16) IRTS + 639 BD DES ARMARIS, IRTS + TOULON Provence Alpes Cotes d'Azur 83100 + FR + +88-09-07 (hex) MKT Systemtechnik GmbH & Co. KG +880907 (base 16) MKT Systemtechnik GmbH & Co. KG + Hasskampstraße 75-77 + Bünde NRW 32257 + DE + +58-A4-8E (hex) PixArt Imaging Inc. +58A48E (base 16) PixArt Imaging Inc. + No.5, Innovation Road 1, HsinChu Science Park, + Hsin-Chu 300 + TW + +30-D6-59 (hex) Merging Technologies SA +30D659 (base 16) Merging Technologies SA + Le Verney 4 + Puidoux Outside the U.S or Canada 1070 + CH + +70-2A-D5 (hex) Samsung Electronics Co.,Ltd +702AD5 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +88-97-65 (hex) exands +889765 (base 16) exands + RM2202 , No. 666 Gubei road + shanghai 200336 + CN + +38-6E-88 (hex) zte corporation +386E88 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +B8-85-84 (hex) Dell Inc. +B88584 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +40-EE-DD (hex) HUAWEI TECHNOLOGIES CO.,LTD +40EEDD (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B0-18-86 (hex) SmarDTV +B01886 (base 16) SmarDTV + Route de Genève 22 + Cheseaux CH-1033 + CH + +AC-75-1D (hex) HUAWEI TECHNOLOGIES CO.,LTD +AC751D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +28-9E-97 (hex) HUAWEI TECHNOLOGIES CO.,LTD +289E97 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-15-25 (hex) Chamberlain Access Solutions +001525 (base 16) Chamberlain Access Solutions + 8271 E. Gelding Drive + Scottsdale AZ 85260 + US + +00-1E-B0 (hex) ImesD Electronica S.L. +001EB0 (base 16) ImesD Electronica S.L. + d'Entença 81 + Barcelona 08015 + ES + +64-1C-67 (hex) DIGIBRAS INDUSTRIA DO BRASILS/A +641C67 (base 16) DIGIBRAS INDUSTRIA DO BRASILS/A + Rua Tambaqui, 180-B - MANAUS - AM ¨C BRAZIL + manaus MANAUS 69075-210 + BR + +60-05-8A (hex) Hitachi Metals, Ltd. +60058A (base 16) Hitachi Metals, Ltd. + Shinagawa Season Terrace, 2-70, Konan 1-chome + Minato-ku Tokyo 108-8224 + JP + +BC-22-FB (hex) RF Industries +BC22FB (base 16) RF Industries + PO Box 5 + Welland SA 5007 + AU + +00-80-B6 (hex) Mercury Systems – Trusted Mission Solutions, Inc. +0080B6 (base 16) Mercury Systems – Trusted Mission Solutions, Inc. + 6681 OWENS DRIVE + PLEASONTON CA 94588 + US + +08-51-2E (hex) Orion Diagnostica Oy +08512E (base 16) Orion Diagnostica Oy + Koivu-Mankkaan tie 6 + Espoo 02100 + FI + +98-A4-04 (hex) Ericsson AB +98A404 (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +00-CC-3F (hex) Universal Electronics, Inc. +00CC3F (base 16) Universal Electronics, Inc. + 201 E. Sandpointe Ave + Santa Ana CA 92707 + US + +74-B9-1E (hex) Nanjing Bestway Automation System Co., Ltd +74B91E (base 16) Nanjing Bestway Automation System Co., Ltd + #50 Baoxiang Road, Jiangning Bin Jiang Economic Development Zone + nanjing jiangsu 211161 + CN + +A0-19-B2 (hex) IEEE Registration Authority +A019B2 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +8C-15-C7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +8C15C7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +60-FA-9D (hex) HUAWEI TECHNOLOGIES CO.,LTD +60FA9D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +DC-99-14 (hex) HUAWEI TECHNOLOGIES CO.,LTD +DC9914 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +4C-3F-D3 (hex) Texas Instruments +4C3FD3 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +B0-53-65 (hex) China Mobile IOT Company Limited +B05365 (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +30-88-41 (hex) Sichuan AI-Link Technology Co., Ltd. +308841 (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou,Industrial Park + Anzhou,Industrial Park Sichuan 621000 + CN + +44-EF-CF (hex) UGENE SOLUTION inc. +44EFCF (base 16) UGENE SOLUTION inc. + A-1508, 1509, 583, Yangcheon-ro, Gangseo-gu + Seoul KS013 + KR + +30-45-96 (hex) HUAWEI TECHNOLOGIES CO.,LTD +304596 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C0-F4-E6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C0F4E6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +74-EB-80 (hex) Samsung Electronics Co.,Ltd +74EB80 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +0C-E0-DC (hex) Samsung Electronics Co.,Ltd +0CE0DC (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D8-68-C3 (hex) Samsung Electronics Co.,Ltd +D868C3 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C4-93-D9 (hex) Samsung Electronics Co.,Ltd +C493D9 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A8-2B-B9 (hex) Samsung Electronics Co.,Ltd +A82BB9 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +AC-FD-93 (hex) WEIFANG GOERTEK ELECTRONICS CO.,LTD +ACFD93 (base 16) WEIFANG GOERTEK ELECTRONICS CO.,LTD + Gaoxin 2 Road,Free Trade Zone,Weifang,Shandong,261205,P.R.China + Weifang Shandong 261205 + CN + +68-57-2D (hex) HANGZHOU AIXIANGJI TECHNOLOGY CO., LTD +68572D (base 16) HANGZHOU AIXIANGJI TECHNOLOGY CO., LTD + 7 Floor, 3 Blvd., More Centre, 87 Gudun Rd., Xihu District + Hangzhou Zhejiang 310012 + CN + +00-B8-C2 (hex) Heights Telecom T ltd +00B8C2 (base 16) Heights Telecom T ltd + Moshe Lerer 15 + Nes Ziona 7404996 + IL + +F4-BF-80 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4BF80 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-0E-8F (hex) Sercomm Corporation. +000E8F (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +A0-E6-17 (hex) MATIS +A0E617 (base 16) MATIS + 2/F,Hatchobori MIYATA Bldg.,1-8-2, + Shintomi,Chuo-Ku, Tokyo 104-0041 + JP + +70-01-B5 (hex) Cisco Systems, Inc +7001B5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1F-49 (hex) Manhattan TV Ltd +001F49 (base 16) Manhattan TV Ltd + 3 Phoenix Park, + London NW2 7LN + GB + +88-D6-52 (hex) AMERGINT Technologies +88D652 (base 16) AMERGINT Technologies + 2315 Briargate Pkwy, Suite 100 + Colorado Springs CO 80920 + US + +FC-90-FA (hex) Independent Technologies +FC90FA (base 16) Independent Technologies + 1960 Ridgeview Rd + Blair NE 68008 + US + +D0-B2-14 (hex) PoeWit Inc +D0B214 (base 16) PoeWit Inc + 2307 Sea Island Dr + Fort Lauderdale FL 33301 + US + +C4-24-56 (hex) Palo Alto Networks +C42456 (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +B4-B6-86 (hex) Hewlett Packard +B4B686 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +4C-ED-FB (hex) ASUSTek COMPUTER INC. +4CEDFB (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +7C-2E-BD (hex) Google, Inc. +7C2EBD (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +6C-AF-15 (hex) Webasto SE +6CAF15 (base 16) Webasto SE + Kraillinger Straße 5 + Stockdorf Bayern 82131 + DE + +E4-E1-30 (hex) TCT mobile ltd +E4E130 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +0C-21-38 (hex) Hengstler GmbH +0C2138 (base 16) Hengstler GmbH + Uhlandstrasse49 + Aldingen BW 78554 + DE + +E4-60-59 (hex) Pingtek Co., Ltd. +E46059 (base 16) Pingtek Co., Ltd. + 5F., No.786, Zhongzheng Rd., Zhonghe Dist. + New Taipei City 235 + TW + +E0-19-1D (hex) HUAWEI TECHNOLOGIES CO.,LTD +E0191D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +68-D1-BA (hex) Shenzhen YOUHUA Technology Co., Ltd +68D1BA (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +1C-1A-C0 (hex) Apple, Inc. +1C1AC0 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +30-78-C2 (hex) Innowireless / QUCELL Networks +3078C2 (base 16) Innowireless / QUCELL Networks + Innowireless Bldg. 190 Seohyeon-ro + Bundang-gu, Seongnam-si Gyeonggi-do 13590 + KR + +40-50-B5 (hex) Shenzhen New Species Technology Co., Ltd. +4050B5 (base 16) Shenzhen New Species Technology Co., Ltd. + Room 1827,Building R&D,EVOC intelligence valley,No 11,Gao xin west road,Guangming New District + Shenzhen 518107 + CN + +3C-15-FB (hex) HUAWEI TECHNOLOGIES CO.,LTD +3C15FB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +CC-93-4A (hex) Sierra Wireless +CC934A (base 16) Sierra Wireless + 1381 Wireless Way + Richmond BC CA V6V 3A4 + GB + +00-CF-C0 (hex) China Mobile Group Device Co.,Ltd. +00CFC0 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +DC-33-0D (hex) QING DAO HAIER TELECOM CO.,LTD. +DC330D (base 16) QING DAO HAIER TELECOM CO.,LTD. + No 1 Haier road,Hi-tech Zone,Qingdao,PR.China + Qingdao Shandong 266101 + CN + +68-89-75 (hex) nuoxc +688975 (base 16) nuoxc + 龙岗区横岗街道西坑社区西坑梧岗路9号2栋 + 深圳市 广东省 518173 + CN + +40-F0-4E (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +40F04E (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +00-21-F2 (hex) EASY3CALL Technology Limited +0021F2 (base 16) EASY3CALL Technology Limited + Room 1903-6, 19/F., HING YIP Commercial Centre + Hong Kong 999077 + CN + +00-15-C4 (hex) FLOVEL CO., LTD. +0015C4 (base 16) FLOVEL CO., LTD. + The Tachihi building No,3 hall, 6-1, Sakae-cho, + Tokyo 190-0003 + US + +00-11-E6 (hex) Scientific Atlanta +0011E6 (base 16) Scientific Atlanta + 5030 Sugarloaf Parkway + Lawrenceville Ga 30042 + US + +24-F1-28 (hex) Telstra +24F128 (base 16) Telstra + 231 Elisabeth St + SYDNEY NSW 2000 + AU + +E0-38-3F (hex) zte corporation +E0383F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +D4-72-26 (hex) zte corporation +D47226 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +40-83-1D (hex) Apple, Inc. +40831D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +DC-D3-A2 (hex) Apple, Inc. +DCD3A2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-1D-D9 (hex) Apple, Inc. +5C1DD9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +80-05-88 (hex) Ruijie Networks Co.,LTD +800588 (base 16) Ruijie Networks Co.,LTD + 20# Building,Star-net Science Plaza,Juyuanzhou, 618 Jinshan Road + Fuzhou Fujian 350002 + CN + +F0-0E-1D (hex) Megafone Limited +F00E1D (base 16) Megafone Limited + Unit 702,7/F,Bankok Bank Building,NO.18 Bonham Strand West + Hong Kong 999077 + HK + +88-AE-07 (hex) Apple, Inc. +88AE07 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +68-FE-F7 (hex) Apple, Inc. +68FEF7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-35-EE (hex) FN-LINK TECHNOLOGY LIMITED +AC35EE (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +88-11-96 (hex) HUAWEI TECHNOLOGIES CO.,LTD +881196 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E4-0E-EE (hex) HUAWEI TECHNOLOGIES CO.,LTD +E40EEE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +28-D9-97 (hex) Yuduan Mobile Co., Ltd. +28D997 (base 16) Yuduan Mobile Co., Ltd. + Room 401 No 84 Lane 887 Zuchongzhi Rd. + Shanghai 201203 + CN + +30-1F-9A (hex) IEEE Registration Authority +301F9A (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +0C-2C-54 (hex) HUAWEI TECHNOLOGIES CO.,LTD +0C2C54 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D4-C1-9E (hex) Ruckus Wireless +D4C19E (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +70-69-5A (hex) Cisco Systems, Inc +70695A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-BF-77 (hex) Cisco Systems, Inc +00BF77 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D0-77-14 (hex) Motorola Mobility LLC, a Lenovo Company +D07714 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +30-B7-D4 (hex) Hitron Technologies. Inc +30B7D4 (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +B4-81-BF (hex) Meta-Networks, LLC +B481BF (base 16) Meta-Networks, LLC + Office 106C, 5/2, Varshavskaya street + Saint-Petersburg Saint-Petersburg 196128 + RU + +94-6A-B0 (hex) Arcadyan Corporation +946AB0 (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +48-18-FA (hex) Nocsys +4818FA (base 16) Nocsys + 1F, No. 63 Building, No. 421 Hong Cao Road, Xuhui District + Shanghai Shanghai 200233 + CN + +58-7A-6A (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +587A6A (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +A0-38-F8 (hex) OURA Health Oy +A038F8 (base 16) OURA Health Oy + Elektroniikkatie 3 + Oulu 90590 + FI + +68-79-24 (hex) ELS-GmbH & Co. KG +687924 (base 16) ELS-GmbH & Co. KG + Dammstrasse 21 + Werther NRW 33824 + DE + +28-FD-80 (hex) IEEE Registration Authority +28FD80 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +0C-AE-7D (hex) Texas Instruments +0CAE7D (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +30-45-11 (hex) Texas Instruments +304511 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +E8-1A-AC (hex) ORFEO SOUNDWORKS Inc. +E81AAC (base 16) ORFEO SOUNDWORKS Inc. + 612, 11-41, Simin-daero 327beon-gil, Dongan-gu + Anyang 14055 + KR + +00-07-58 (hex) DragonWave Inc. +000758 (base 16) DragonWave Inc. + 600-411 Leggett Drive, + Kanata, Ontario K2K 3C9 + CA + +F0-FC-C8 (hex) ARRIS Group, Inc. +F0FCC8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F8-DF-15 (hex) Sunitec Enterprise Co.,Ltd +F8DF15 (base 16) Sunitec Enterprise Co.,Ltd + 3F.,No.98-1,Mincyuan Rd.Sindian City + Taipei County 231 231141 + CN + +00-1D-B5 (hex) Juniper Networks +001DB5 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +B0-26-80 (hex) Cisco Systems, Inc +B02680 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D4-93-98 (hex) Nokia Corporation +D49398 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo N.A. 24101 + FI + +00-19-37 (hex) CommerceGuard AB +001937 (base 16) CommerceGuard AB + Gustavslundsv 151A + BROMMA 16714 + SE + +FC-7C-02 (hex) Phicomm (Shanghai) Co., Ltd. +FC7C02 (base 16) Phicomm (Shanghai) Co., Ltd. + 3666 SiXian Rd.,Songjiang District + Shanghai Shanghai 201616 + CN + +A8-61-0A (hex) ARDUINO AG +A8610A (base 16) ARDUINO AG + Corso San Gottardo 6A + Chiasso 6830 + CH + +60-97-DD (hex) MicroSys Electronics GmbH +6097DD (base 16) MicroSys Electronics GmbH + Muehlweg 1 + Sauerlach 82054 + DE + +04-79-70 (hex) HUAWEI TECHNOLOGIES CO.,LTD +047970 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A0-57-E3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A057E3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +1C-B0-44 (hex) ASKEY COMPUTER CORP +1CB044 (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +AC-17-C8 (hex) Cisco Meraki +AC17C8 (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco null 94158 + US + +F4-84-4C (hex) Texas Instruments +F4844C (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +38-DE-AD (hex) Intel Corporate +38DEAD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +D4-6D-6D (hex) Intel Corporate +D46D6D (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B4-F2-E8 (hex) ARRIS Group, Inc. +B4F2E8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +3C-57-4F (hex) China Mobile Group Device Co.,Ltd. +3C574F (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +D4-9C-F4 (hex) Palo Alto Networks +D49CF4 (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +8C-16-45 (hex) LCFC(HeFei) Electronics Technology co., ltd +8C1645 (base 16) LCFC(HeFei) Electronics Technology co., ltd + YunGu Road 3188-1 + Hefei Anhui 230000 + CN + +68-98-61 (hex) Beacon Inc +689861 (base 16) Beacon Inc + 82-1, Anyangcheondong-ro, Dongan-gu + anyang Gyeonggi-do 14042 + KR + +60-98-13 (hex) Shanghai Visking Digital Technology Co. LTD +609813 (base 16) Shanghai Visking Digital Technology Co. LTD + Room 1301, Building A8, No.1688 Guoquan North Road, Yangpu District + Shanghai 200082 + CN + +50-6B-4B (hex) Mellanox Technologies, Inc. +506B4B (base 16) Mellanox Technologies, Inc. + 350 Oakmead Parkway, Suite 100 + Sunnyvale CA 94085 + US + +B4-1C-30 (hex) zte corporation +B41C30 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +70-5A-AC (hex) Samsung Electronics Co.,Ltd +705AAC (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +2C-95-69 (hex) ARRIS Group, Inc. +2C9569 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +A0-39-EE (hex) Sagemcom Broadband SAS +A039EE (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +E4-CB-59 (hex) Beijing Loveair Science and Technology Co. Ltd. +E4CB59 (base 16) Beijing Loveair Science and Technology Co. Ltd. + 103,Block B, Kelin Building, No.107, Dongsi North Street, Dongcheng District, + Beijing 100000 + CN + +B4-E6-2D (hex) Espressif Inc. +B4E62D (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +84-74-60 (hex) zte corporation +847460 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +4C-82-CF (hex) Dish Technologies Corp +4C82CF (base 16) Dish Technologies Corp + 94 Inverness Terrace E + Englewood CO 80112 + US + +28-57-67 (hex) Dish Technologies Corp +285767 (base 16) Dish Technologies Corp + 94 Inverness Terrace E + Englewood CO 80112 + US + +70-16-9F (hex) EtherCAT Technology Group +70169F (base 16) EtherCAT Technology Group + Ostendstr. 196 + NUremberg 90482 + DE + +68-EF-43 (hex) Apple, Inc. +68EF43 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-2B-20 (hex) Apple, Inc. +D02B20 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-61-F6 (hex) Apple, Inc. +2C61F6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D4-A3-3D (hex) Apple, Inc. +D4A33D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-76-6F (hex) Apple, Inc. +F0766F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-98-AD (hex) Apple, Inc. +4098AD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-4D-73 (hex) Apple, Inc. +6C4D73 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +1C-A0-B8 (hex) Hon Hai Precision Ind. Co., Ltd. +1CA0B8 (base 16) Hon Hai Precision Ind. Co., Ltd. + GuangDongShenZhen + ShenZhen GuangDong 518109 + CN + +D8-84-66 (hex) Extreme Networks, Inc. +D88466 (base 16) Extreme Networks, Inc. + 145 Rio Robles + San Jose CA 95134 + US + +00-04-96 (hex) Extreme Networks, Inc. +000496 (base 16) Extreme Networks, Inc. + 3585 Monroe Street + Santa Clara CA 95051 + US + +00-E0-2B (hex) Extreme Networks, Inc. +00E02B (base 16) Extreme Networks, Inc. + 10460 BANDLEY DRIVE + CUPERINT0 CA 95014 + US + +5C-0E-8B (hex) Extreme Networks, Inc. +5C0E8B (base 16) Extreme Networks, Inc. + 475 Half Day Road + Lincolnshire IL 60069 + US + +74-67-F7 (hex) Extreme Networks, Inc. +7467F7 (base 16) Extreme Networks, Inc. + 1 Zebra Plaza + Holtsville NY 11742 + US + +E4-30-22 (hex) Hanwha Techwin Security Vietnam +E43022 (base 16) Hanwha Techwin Security Vietnam + Plot O-2, Que Vo industrial park (Expanded area), + Nam Son Commune, Bac Ninh City Bac Ninh Province 000 + VN + +04-4F-17 (hex) HUMAX Co., Ltd. +044F17 (base 16) HUMAX Co., Ltd. + HUMAX Village, 216, Hwangsaeul-ro, Bu + Seongnam-si Gyeonggi-do 463-875 + KR + +5C-4A-1F (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +5C4A1F (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +E4-8F-34 (hex) Vodafone Italia S.p.A. +E48F34 (base 16) Vodafone Italia S.p.A. + Via Lorenteggio nr. 240 + Milan Italy 20147 + IT + +68-5A-CF (hex) Samsung Electronics Co.,Ltd +685ACF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +0C-A8-A7 (hex) Samsung Electronics Co.,Ltd +0CA8A7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-67-2F (hex) Bowers & Wilkins +B0672F (base 16) Bowers & Wilkins + 900 Middlefield Rd Floor 4 + Redwood City CA 94063 + US + +10-CD-6E (hex) FISYS +10CD6E (base 16) FISYS + 303 Expotel, 44, Dunsan-daero 117beon-gil, Seo-gu, Daejeon, Korea + Daejeon, Korea KS015 + KR + +D8-63-75 (hex) Xiaomi Communications Co Ltd +D86375 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +D8-9C-67 (hex) Hon Hai Precision Ind. Co.,Ltd. +D89C67 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +64-20-9F (hex) Tilgin AB +64209F (base 16) Tilgin AB + Finlandsgatan 40 + Kista 16474 + SE + +A4-3E-51 (hex) ANOV FRANCE +A43E51 (base 16) ANOV FRANCE + 100 CHEMIN DE BAILLOT + MONTAUBAN 82000 + FR + +70-26-05 (hex) SONY Visual Products Inc. +702605 (base 16) SONY Visual Products Inc. + 2-10-1 Osaki + Shinagawa-ku Tokyo 141-8610 + JP + +00-90-F1 (hex) Seagate Cloud Systems Inc +0090F1 (base 16) Seagate Cloud Systems Inc + 6305 El Camino Real + Carlsbad CA 92009 + US + +84-5A-81 (hex) ffly4u +845A81 (base 16) ffly4u + 3, avenue Didier Daurat + Toulouse 31400 + FR + +CC-81-DA (hex) Phicomm (Shanghai) Co., Ltd. +CC81DA (base 16) Phicomm (Shanghai) Co., Ltd. + 3666 SiXian Rd.,Songjiang District + Shanghai Shanghai 201616 + CN + +00-80-6C (hex) Secure Systems & Services +00806C (base 16) Secure Systems & Services + 24, Chemin de la Pouranque + F-13752 LES PENNES MIRABEAU CS30084 + FR + +00-72-63 (hex) Netcore Technology Inc. +007263 (base 16) Netcore Technology Inc. + ORIENTAL CYBERPORT,HIGHTECH 6 ROAD + Shenzhen 518057 + CN + +1C-27-DD (hex) Datang Gohighsec(zhejiang)Information Technology Co.,Ltd. +1C27DD (base 16) Datang Gohighsec(zhejiang)Information Technology Co.,Ltd. + Beiwu Innovation park, #23 Beiwu Villiage Road + Beijing Beijing 100000 + CN + +B8-C8-EB (hex) ITEL MOBILE LIMITED +B8C8EB (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +80-C5-F2 (hex) AzureWave Technology Inc. +80C5F2 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +64-F8-8A (hex) China Mobile IOT Company Limited +64F88A (base 16) China Mobile IOT Company Limited + NO.8 Yu Ma Road, NanAn Area + Chongqing Chongqing 401336 + CN + +68-DB-54 (hex) Phicomm (Shanghai) Co., Ltd. +68DB54 (base 16) Phicomm (Shanghai) Co., Ltd. + 3666 SiXian Rd.,Songjiang District + Shanghai Shanghai 201616 + CN + +B4-52-53 (hex) Seagate Technology +B45253 (base 16) Seagate Technology + 1280 Disc Drive + Shakopee MN 55379 + US + +00-11-C6 (hex) Seagate Technology +0011C6 (base 16) Seagate Technology + M/S NW1F01 + Longmont CO 80503 + US + +00-1D-38 (hex) Seagate Technology +001D38 (base 16) Seagate Technology + M/S NW1F01 + Longmont CO 80503 + US + +00-50-13 (hex) Seagate Cloud Systems Inc +005013 (base 16) Seagate Cloud Systems Inc + 7420 E. Dry Creek Parkway + Longmont CO 80503 + US + +C8-DF-84 (hex) Texas Instruments +C8DF84 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +24-0D-6C (hex) SMND +240D6C (base 16) SMND + 16-39, LS-ro 91 beon-gil, Dongan-gu + Anyang-si Gyeonggi-do 14119 + KR + +48-55-5C (hex) Wu Qi Technologies,Inc. +48555C (base 16) Wu Qi Technologies,Inc. + Xiantao street data on the 19th East Road + Chongqing City Yubei District 401120 + CN + +18-F0-E4 (hex) Xiaomi Communications Co Ltd +18F0E4 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources , No.68 Qinghe Middle Street , Haidian District + Beijing Beijing 100089 + CN + +58-8A-5A (hex) Dell Inc. +588A5A (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +9C-8C-6E (hex) Samsung Electronics Co.,Ltd +9C8C6E (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +DC-4F-22 (hex) Espressif Inc. +DC4F22 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +F8-6C-E1 (hex) Taicang T&W Electronics +F86CE1 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +1C-73-28 (hex) Connected Home +1C7328 (base 16) Connected Home + 19-22, Rathbone Place + London W1T 1HY + GB + +D8-E0-04 (hex) Vodia Networks Inc +D8E004 (base 16) Vodia Networks Inc + 33 Broad St + Boston MA 02109 + US + +2C-FD-AB (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +2CFDAB (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan + Wuhan Hubei 430000 + CN + +30-B4-B8 (hex) LG Electronics +30B4B8 (base 16) LG Electronics + 222 LG-ro, JINWI-MYEON + Pyeongtaek-si Gyeonggi-do 451-713 + KR + +38-0E-4D (hex) Cisco Systems, Inc +380E4D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +38-73-EA (hex) IEEE Registration Authority +3873EA (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +4C-52-62 (hex) Fujitsu Technology Solutions GmbH +4C5262 (base 16) Fujitsu Technology Solutions GmbH + Buergermeister-Ulrich-Strasse 100 + Augsburg Bayern 86199 + DE + +80-3B-F6 (hex) LOOK EASY INTERNATIONAL LIMITED +803BF6 (base 16) LOOK EASY INTERNATIONAL LIMITED + 4th Floor, No. 551, Guang-Fu South Road + Taipei Xinyi District 11074 + TW + +30-EB-1F (hex) Skylab M&C Technology Co.,Ltd +30EB1F (base 16) Skylab M&C Technology Co.,Ltd + 6 Floor,No.9 Building,Lijincheng Scientific&Technical park,Gongye East Road,Longhua District + Shenzhen Guangdong 518109 + CN + +54-9A-4C (hex) GUANGDONG HOMECARE TECHNOLOGY CO.,LTD. +549A4C (base 16) GUANGDONG HOMECARE TECHNOLOGY CO.,LTD. + 8F,12#, Taihua Industrial Park, Hangkong Rd., Gushu, Baoan District + Shenzhen Guangdong 518128 + CN + +EC-1D-8B (hex) Cisco Systems, Inc +EC1D8B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +EC-70-97 (hex) ARRIS Group, Inc. +EC7097 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +58-19-F8 (hex) ARRIS Group, Inc. +5819F8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D0-7F-C4 (hex) Ou Wei Technology Co.,Ltd. of Shenzhen City +D07FC4 (base 16) Ou Wei Technology Co.,Ltd. of Shenzhen City + Registered Address: Room 201, Block D, Huahan Innovation Park, Langshan Road, Xili Street, Nanshan District, + Shenzhen Guangdong 518057 + CN + +14-79-F3 (hex) China Mobile Group Device Co.,Ltd. +1479F3 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +0C-CE-F6 (hex) Guizhou Fortuneship Technology Co., Ltd +0CCEF6 (base 16) Guizhou Fortuneship Technology Co., Ltd + 2nd Floor, Factory Building 4, Hi-Tech Industrial Park, Xinpu Economic Development Zone, Xinpu New District + Zunyi City Guizhou Province 56300 + CN + +18-06-FF (hex) Acer Computer(Shanghai) Limited. +1806FF (base 16) Acer Computer(Shanghai) Limited. + Room1806-20, No.769, Jiujiang Road, Huangpu District + Shanghai 200000 + CN + +C4-CD-82 (hex) Hangzhou Lowan Information Technology Co., Ltd. +C4CD82 (base 16) Hangzhou Lowan Information Technology Co., Ltd. + 502 Building B, United Mansion, No.2 Zijinghua Road + Hangzhou Zhejiang 310023 + CN + +30-FB-94 (hex) Shanghai Fangzhiwei Information Technology CO.,Ltd. +30FB94 (base 16) Shanghai Fangzhiwei Information Technology CO.,Ltd. + The 17th Building A Unit,No. 1688 Lianhang Road,Minhang District,Shanghai City + Shanghai 201100 + CN + +00-23-A0 (hex) Hana CNS Co., LTD. +0023A0 (base 16) Hana CNS Co., LTD. + Taejang-dong 1720-52 Taejang-NongGong-Danji + Wonju Gangwon-do 220-962 + KR + +F4-06-A5 (hex) Hangzhou Bianfeng Networking Technology Co., Ltd. +F406A5 (base 16) Hangzhou Bianfeng Networking Technology Co., Ltd. + BlockC,2F,Building B,Paradise Software Park + Hangzhou Zhejiang 310012 + CN + +A4-B5-2E (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +A4B52E (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +3C-A5-81 (hex) vivo Mobile Communication Co., Ltd. +3CA581 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +34-E9-11 (hex) vivo Mobile Communication Co., Ltd. +34E911 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +64-CB-A3 (hex) Pointmobile +64CBA3 (base 16) Pointmobile + B-9F kabul Great Valley, 32, Digital-ro 9-gil, Geumcheon-gu + Seoul Seoul 08512 + KR + +EC-FA-BC (hex) Espressif Inc. +ECFABC (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +08-BA-22 (hex) Swaive Corporation +08BA22 (base 16) Swaive Corporation + 3565 Kettmann Road + San Jose CA 95121 + US + +28-C1-3C (hex) Hon Hai Precision Ind. Co., Ltd. +28C13C (base 16) Hon Hai Precision Ind. Co., Ltd. + GuangDongShenZhen + ShenZhen GuangDong 518109 + CN + +B0-EC-E1 (hex) Private +B0ECE1 (base 16) Private + +60-E7-8A (hex) UNISEM +60E78A (base 16) UNISEM + 10-7,Jangjinam-gil,Dongtan-meyeon + Hwaseong-si Gyeonggi-do 18510 + KR + +F8-F2-1E (hex) Intel Corporate +F8F21E (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +28-29-86 (hex) APC by Schneider Electric +282986 (base 16) APC by Schneider Electric + 800 Federal St. + Andover MA 01810 + US + +70-7D-B9 (hex) Cisco Systems, Inc +707DB9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +08-BE-AC (hex) Edimax Technology Co. Ltd. +08BEAC (base 16) Edimax Technology Co. Ltd. + No. 278, Xinhu 1st Road + Taipei City Neihu Dist 248 + TW + +24-8B-E0 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +248BE0 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +00-24-24 (hex) Ace Axis Limited +002424 (base 16) Ace Axis Limited + 602 Delta Business Park, Welton Road + Swindon SN5 7XP + GB + +50-C9-A0 (hex) SKIPPER AS +50C9A0 (base 16) SKIPPER AS + Enebakkvn 150 + Oslo 0612 + NO + +74-83-EF (hex) Arista Networks +7483EF (base 16) Arista Networks + 5453 Great America Parkway + Santa Clara CA 95054 + US + +00-E0-F6 (hex) DECISION EUROPE +00E0F6 (base 16) DECISION EUROPE + 3, rue de Lattre de Tassigny + 85170 SAINT DENIS LA CHEVASSE + FR + +CC-2D-E0 (hex) Routerboard.com +CC2DE0 (base 16) Routerboard.com + Mikrotikls SIA + Riga Riga LV1009 + LV + +00-BF-61 (hex) Samsung Electronics Co.,Ltd +00BF61 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +78-67-D7 (hex) Apple, Inc. +7867D7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B8-C1-11 (hex) Apple, Inc. +B8C111 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +10-46-B4 (hex) FormericaOE +1046B4 (base 16) FormericaOE + 5F-11, No.38, Taiyuan Street + Zhubei City Hsinchu County 302 + TW + +9C-E3-3F (hex) Apple, Inc. +9CE33F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-6B-1C (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +386B1C (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + 3/F, Building R1-B, High-Tech Industrial Park, Nanshan District + Shenzhen Guangdong 518057 + CN + +DC-55-83 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +DC5583 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +00-12-48 (hex) Dell EMC +001248 (base 16) Dell EMC + 176 South Street + Hopkinton MA 01748 + US + +00-60-48 (hex) Dell EMC +006048 (base 16) Dell EMC + 171 SOUTH ST., + HOPKINTON MA 01748 + US + +7C-C9-5A (hex) Dell EMC +7CC95A (base 16) Dell EMC + 176 South Street + Hopkinton MA 01748 + US + +D0-04-01 (hex) Motorola Mobility LLC, a Lenovo Company +D00401 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +74-28-57 (hex) Mayfield Robotics +742857 (base 16) Mayfield Robotics + 400 Convention Way + Redwood City CA 94063 + US + +58-90-43 (hex) Sagemcom Broadband SAS +589043 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +B4-A3-82 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +B4A382 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.555 Qianmo Road + Hangzhou Zhejiang 310052 + CN + +9C-9C-40 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +9C9C40 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +A4-07-B6 (hex) Samsung Electronics Co.,Ltd +A407B6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +40-49-8A (hex) Synapticon GmbH +40498A (base 16) Synapticon GmbH + Daimlerstr. 26 + Schönaich 71101 + DE + +38-9D-92 (hex) Seiko Epson Corporation +389D92 (base 16) Seiko Epson Corporation + 2070 Kotobuki Koaka + Matsumoto-shi Nagano-ken 399-8702 + JP + +24-E1-24 (hex) Xiamen Ursaconn Technology Co. , Ltd. +24E124 (base 16) Xiamen Ursaconn Technology Co. , Ltd. + 3/F, No. 46 Guanri Road, 2nd Software Park + Xiamen Fujian 361008 + CN + +8C-0F-83 (hex) Angie Hospitality LLC +8C0F83 (base 16) Angie Hospitality LLC + 12465 S Fort St, Ste 300 + Draper UT 84020-9021 + US + +DC-68-EB (hex) Nintendo Co.,Ltd +DC68EB (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +E8-36-1D (hex) Sense Labs, Inc. +E8361D (base 16) Sense Labs, Inc. + 485 Massachusetts Ave + Cambridge MA 02139 + US + +08-78-08 (hex) Samsung Electronics Co.,Ltd +087808 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +88-75-98 (hex) Samsung Electronics Co.,Ltd +887598 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C0-17-4D (hex) Samsung Electronics Co.,Ltd +C0174D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +20-F1-9E (hex) ARRIS Group, Inc. +20F19E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +C8-9F-42 (hex) VDII Innovation AB +C89F42 (base 16) VDII Innovation AB + Nedre Holländaregatan 5 + Helsingborg 25225 + SE + +70-91-F3 (hex) Universal Electronics, Inc. +7091F3 (base 16) Universal Electronics, Inc. + 201 E. Sandpointe Ave + Santa Ana CA 92707 + US + +08-00-69 (hex) Silicon Graphics +080069 (base 16) Silicon Graphics + 2011 N. SHORELINE BLVD. + MOUNTAIN VIEW CA 94039-7311 + US + +00-22-91 (hex) Cisco Systems, Inc +002291 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +10-FC-B6 (hex) mirusystems CO.,LTD +10FCB6 (base 16) mirusystems CO.,LTD + #1001, 2-dong, Pangoyo seven venture valley, 228-gil, Pangyo-ro + Bundang-gu, Seongnam-si, Gyeonggi-do 13487 + KR + +04-D6-AA (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +04D6AA (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +50-A8-3A (hex) S Mobile Devices Limited +50A83A (base 16) S Mobile Devices Limited + Unit B-303, 3rd Floor, Tower-B, Plot No-7,Advant IT Park Ltd , Sector-142 + NOIDA Uttar Pradesh 201301 + IN + +64-05-E9 (hex) Shenzhen WayOS Technology Crop., Ltd. +6405E9 (base 16) Shenzhen WayOS Technology Crop., Ltd. + F18, Yousong Business Building, Longhua New District, Shenzhen, China + Shenzhen Guangdong 518109 + CN + +A0-70-99 (hex) Beijing Huacan Electronics Co., Ltd +A07099 (base 16) Beijing Huacan Electronics Co., Ltd + NO.122, Room 2006, 20/F, Qingyun Contemporary Tower, Building 9, Manting Fangyuan Residential District, Qing Yun Li, Hai Dian District + Beijing 100036 + CN + +48-D6-D5 (hex) Google, Inc. +48D6D5 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +0C-58-42 (hex) DME Micro +0C5842 (base 16) DME Micro + unit 310 Lakeside 1, 8 Science Park West Ave, Shatin + Hong Kong Hong Kong + HK + +B8-10-D4 (hex) Masimo Corporation +B810D4 (base 16) Masimo Corporation + 40 Parker + Irvine CA 92618 + US + +BC-82-5D (hex) MITSUMI ELECTRIC CO.,LTD. +BC825D (base 16) MITSUMI ELECTRIC CO.,LTD. + 2-11-2, Tsurumaki + Tama-shi Tokyo 206-8567 + JP + +D0-66-6D (hex) Shenzhen Bus-Lan Technology Co., Ltd. +D0666D (base 16) Shenzhen Bus-Lan Technology Co., Ltd. + 928-931 Chuangke Building, 72-1 South Huanguan Rd, Guan Lan Jie Dao, Longhua District + Shenzhen Guangdong 518100 + CN + +08-15-2F (hex) Samsung Electronics Co., Ltd. ARTIK +08152F (base 16) Samsung Electronics Co., Ltd. ARTIK + 1-1, Samsungjeonja-ro + Hwaseong-si Gyeonggi-do 18448 + KR + +F4-F5-DB (hex) Xiaomi Communications Co Ltd +F4F5DB (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +F4-E2-04 (hex) Traqueur +F4E204 (base 16) Traqueur + 1, rue Royale + Saint-Cloud 92210 + FR + +CC-22-37 (hex) IEEE Registration Authority +CC2237 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +38-D6-20 (hex) Limidea Concept Pte. Ltd. +38D620 (base 16) Limidea Concept Pte. Ltd. + 101 Cecil Street #09-07, Tong Eng Building + Singapore Singapore 069533 + SG + +74-F9-1A (hex) Onface +74F91A (base 16) Onface + #1408, Mario Tower, 30Gil-28, Digital-ro, Guro-gu + Seoul 08389 + KR + +A4-34-F1 (hex) Texas Instruments +A434F1 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +18-60-24 (hex) Hewlett Packard +186024 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +BC-3D-85 (hex) HUAWEI TECHNOLOGIES CO.,LTD +BC3D85 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +20-54-FA (hex) HUAWEI TECHNOLOGIES CO.,LTD +2054FA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +38-37-8B (hex) HUAWEI TECHNOLOGIES CO.,LTD +38378B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +74-5C-4B (hex) GN Audio A/S +745C4B (base 16) GN Audio A/S + Lautrupbjerg 7 + Ballerup DK-2750 + DK + +00-14-9D (hex) Sound ID Inc. +00149D (base 16) Sound ID Inc. + 3430 West Bayshore Road + Palo Alto California 94303 + US + +A8-E8-24 (hex) INIM ELECTRONICS S.R.L. +A8E824 (base 16) INIM ELECTRONICS S.R.L. + VIA DEI LAVORATORI 10 - FRAZIONE CENTOBUCHI + MONTEPRANDONE ASCOLI PICENO 63076 + IT + +10-49-63 (hex) HARTING K.K. +104963 (base 16) HARTING K.K. + 1-7-9, Shin-Yokohama, Kohoku-ku + Yokohama-city Kanagawa 222-0033 + JP + +8C-D4-8E (hex) ITEL MOBILE LIMITED +8CD48E (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +64-2B-8A (hex) ALL BEST Industrial Co., Ltd. +642B8A (base 16) ALL BEST Industrial Co., Ltd. + 6F., No.210-20, Sec. 3, Zhongyang Rd., Tucheng Dist., + New Taipei City 23680 + TW + +B8-EE-0E (hex) Sagemcom Broadband SAS +B8EE0E (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +EC-D0-9F (hex) Xiaomi Communications Co Ltd +ECD09F (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +78-E1-03 (hex) Amazon Technologies Inc. +78E103 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +00-06-59 (hex) EAL (Apeldoorn) B.V. +000659 (base 16) EAL (Apeldoorn) B.V. + Molenmakershoek 14 + Apeldoorn 7328JK + NL + +78-A6-E1 (hex) Brocade Communications Systems, Inc. +78A6E1 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose 95134 + US + +E4-EC-10 (hex) Nokia Corporation +E4EC10 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu Ou 90590 + FI + +00-26-92 (hex) Mitsubishi Electric Corporation +002692 (base 16) Mitsubishi Electric Corporation + 2-7-3 Marunouchi + Chiyoda-ku Tokyo 100-8310 + JP + +8C-C1-21 (hex) Panasonic Corporation AVC Networks Company +8CC121 (base 16) Panasonic Corporation AVC Networks Company + 1-15 Matsuo-cho + Kadoma Osaka 571-8504 + JP + +EC-04-41 (hex) ShenZhen TIGO Semiconductor Co., Ltd. +EC0441 (base 16) ShenZhen TIGO Semiconductor Co., Ltd. + Room B6-709, Funian Plaza, No.3 Shihua Road, Futian Bonded Area + shenzhen China / Guangdong 518048 + CN + +AC-BE-75 (hex) Ufine Technologies Co.,Ltd. +ACBE75 (base 16) Ufine Technologies Co.,Ltd. + 46, Geumgok-dong, Bundang-gu + Seong-nam-si Gyeonggi-do 463-804 + KR + +00-C0-8F (hex) Panasonic Electric Works Co., Ltd. +00C08F (base 16) Panasonic Electric Works Co., Ltd. + Tsu-Factory + Mie-ken 514-8555 0000 + JP + +B0-35-0B (hex) MOBIWIRE MOBILES (NINGBO) CO.,LTD +B0350B (base 16) MOBIWIRE MOBILES (NINGBO) CO.,LTD + No.999,Dacheng East Road, + Fenghua Zhejiang 315500 + CN + +28-A6-AC (hex) seca gmbh & co. kg +28A6AC (base 16) seca gmbh & co. kg + Hammer Steindamm 3-25 + Hamburg Germany 22089 + DE + +A8-BE-27 (hex) Apple, Inc. +A8BE27 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-A5-3E (hex) Apple, Inc. +C0A53E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +44-4E-6D (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +444E6D (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +90-B1-E0 (hex) Beijing Nebula Link Technology Co., Ltd +90B1E0 (base 16) Beijing Nebula Link Technology Co., Ltd + Room 1201, Building C, Caizhi International Plaza, Haidian District + Beijing 100083 + CN + +6C-09-0A (hex) GEMATICA SRL +6C090A (base 16) GEMATICA SRL + Via Diocleziano, 107 + NAPOLI 80125 + IT + +70-E1-FD (hex) FLEXTRONICS +70E1FD (base 16) FLEXTRONICS + Carretera Base Aerea 5850 int 4 + Zapopan Jalisco 45136 + MX + +74-E6-0F (hex) TECNO MOBILE LIMITED +74E60F (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +00-1A-A7 (hex) Torian Wireless +001AA7 (base 16) Torian Wireless + 204 Johnston Street + Collingwood Victoria 3066 + AU + +0C-B4-59 (hex) Marketech International Corp. +0CB459 (base 16) Marketech International Corp. + 10F.,NO.3-2,Yuancyu St.,Nangang Dist. + Taipei 11503 + TW + +80-14-A8 (hex) Guangzhou V-SOLUTION Electronic Technology Co., Ltd. +8014A8 (base 16) Guangzhou V-SOLUTION Electronic Technology Co., Ltd. + Room 406,Originality Building B3, NO.162 Science Avenue,Science Town + Guangzhou Guangdong 510663 + CN + +40-9B-CD (hex) D-Link International +409BCD (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +00-2E-C7 (hex) HUAWEI TECHNOLOGIES CO.,LTD +002EC7 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +48-8E-EF (hex) HUAWEI TECHNOLOGIES CO.,LTD +488EEF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +54-75-95 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +547595 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +C4-71-54 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +C47154 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +58-61-63 (hex) Quantum Networks (SG) Pte. Ltd. +586163 (base 16) Quantum Networks (SG) Pte. Ltd. + 8, UBI ROAD, 2 ZERVEX #08-10, + Singapore 408538 + SG + +EC-3D-FD (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD +EC3DFD (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD + NO.268, Fuqian Rd, Jutang community, Guanlan Town, Longhua New district + shenzhen guangdong 518000 + CN + +94-D0-29 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +94D029 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +30-84-54 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +308454 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +5C-03-39 (hex) HUAWEI TECHNOLOGIES CO.,LTD +5C0339 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F8-28-19 (hex) Liteon Technology Corporation +F82819 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +00-15-E5 (hex) Cheertek Inc. +0015E5 (base 16) Cheertek Inc. + No.2, Du-Sing First Road, Science-Based Industrial Park, + Hsinchu 300 + TW + +50-E9-71 (hex) Jibo, Inc. +50E971 (base 16) Jibo, Inc. + 230 Congress Street + Boston MA 02110 + US + +30-F7-7F (hex) S Mobile Devices Limited +30F77F (base 16) S Mobile Devices Limited + Unit B-303, 3rd Floor, Tower-B, Plot No-7,Advant IT Park Ltd , Sector-142 + NOIDA Uttar Pradesh 201301 + IN + +D8-6C-63 (hex) Google, Inc. +D86C63 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +08-40-F3 (hex) Tenda Technology Co.,Ltd.Dongguan branch +0840F3 (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +94-FB-B2 (hex) SHENZHEN GONGJIN ELECTRONICS CO.,LT +94FBB2 (base 16) SHENZHEN GONGJIN ELECTRONICS CO.,LT + No.1, Songgang Avenue, Songgang Street, Bao’an District + Shenzhen Guangdong 518105 + CN + +00-1E-99 (hex) Vantanol Industrial Corporation +001E99 (base 16) Vantanol Industrial Corporation + 9F, NO 31 . Shin-Tai Road + Jubei City Shinchu 302 + TW + +58-B6-33 (hex) Ruckus Wireless +58B633 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +5C-51-81 (hex) Samsung Electronics Co.,Ltd +5C5181 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +60-8E-08 (hex) Samsung Electronics Co.,Ltd +608E08 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-3D-37 (hex) Ruckus Wireless +543D37 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +2C-E6-CC (hex) Ruckus Wireless +2CE6CC (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +00-22-7F (hex) Ruckus Wireless +00227F (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +74-91-1A (hex) Ruckus Wireless +74911A (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +00-C0-5D (hex) L&N TECHNOLOGIES +00C05D (base 16) L&N TECHNOLOGIES + 2899 AGOURA ROAD #196 + WESTLAKE VILLAGE CA 91361-3200 + US + +58-C5-83 (hex) ITEL MOBILE LIMITED +58C583 (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +18-20-4C (hex) Kummler+Matter AG +18204C (base 16) Kummler+Matter AG + Hohlstrasse 176 + Zürich 8004 + CH + +18-D2-25 (hex) Fiberhome Telecommunication Technologies Co.,LTD +18D225 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +18-B4-30 (hex) Nest Labs Inc. +18B430 (base 16) Nest Labs Inc. + 3400 Hillview Ave. + Palo Alto CA 94304 + US + +30-B1-64 (hex) Power Electronics International Inc. +30B164 (base 16) Power Electronics International Inc. + 561-8 Plate Drive + East Dundee 60118 + US + +F8-8A-3C (hex) IEEE Registration Authority +F88A3C (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +A4-04-50 (hex) nFore Technology Inc. +A40450 (base 16) nFore Technology Inc. + 5F, NO 31, Ln 258, Rulguang Rd + Taipei Neihu District 11491 + TW + +FC-5A-1D (hex) Hitron Technologies. Inc +FC5A1D (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +94-14-7A (hex) vivo Mobile Communication Co., Ltd. +94147A (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +38-17-E1 (hex) Technicolor CH USA Inc. +3817E1 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +98-28-A6 (hex) COMPAL INFORMATION (KUNSHAN) CO., LTD. +9828A6 (base 16) COMPAL INFORMATION (KUNSHAN) CO., LTD. + NO. 25, THE 3RD Street KUNSHAN EXPORT PROCESSING ZONE + KUNSHAN SUZHOU 215300 + CN + +94-3F-C2 (hex) Hewlett Packard Enterprise +943FC2 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +68-1D-EF (hex) Shenzhen CYX Technology Co., Ltd. +681DEF (base 16) Shenzhen CYX Technology Co., Ltd. + 2/F, Bldg. 6, Guangxi Industrial Park, Jianshe Rd., Longhua New Dist., Shenzhen + Shenzhen 518109 + CN + +B4-00-16 (hex) INGENICO TERMINALS SAS +B40016 (base 16) INGENICO TERMINALS SAS + 28-32 BOULEVARD DE GRENELLE + PARIS 75015 + FR + +AC-20-3E (hex) Wuhan Tianyu Information Industry Co., Ltd. +AC203E (base 16) Wuhan Tianyu Information Industry Co., Ltd. + HUST Industry Park, East-Lake Development Zone + Wuhan Hubei 430223 + CN + +B0-1F-29 (hex) Helvetia INC. +B01F29 (base 16) Helvetia INC. + 8-11 tokaichi-nishimachi, kitaku + Okayama okayama 7000856 + JP + +88-0F-10 (hex) Huami Information Technology Co.,Ltd. +880F10 (base 16) Huami Information Technology Co.,Ltd. + Room 1201 Building A4, National Animation Industry Base + Hefei Anhui 230088 + CN + +14-61-2F (hex) Avaya Inc +14612F (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +00-30-9D (hex) Nimble Microsystems, Inc. +00309D (base 16) Nimble Microsystems, Inc. + 50 Church Street - 5th Floor + Cambridge MA 02138 + US + +8C-21-0A (hex) TP-LINK TECHNOLOGIES CO.,LTD. +8C210A (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan + shenzhen guangdong Province 518057 + CN + +4C-18-9A (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +4C189A (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +CC-4B-73 (hex) AMPAK Technology, Inc. +CC4B73 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +00-15-DC (hex) KT&C Co., Ltd. +0015DC (base 16) KT&C Co., Ltd. + 487-4, KT&C Bldg. + GangSeo-Ku Seoul 157-849 + KR + +00-18-7D (hex) Armorlink Co .Ltd +00187D (base 16) Armorlink Co .Ltd + No. 515 of Xinzhuang Industry Park Shenfu Road + Shanghai Province Shanghai 201108 + CN + +F4-30-B9 (hex) Hewlett Packard +F430B9 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +00-19-F0 (hex) UNIONMAN TECHNOLOGY CO.,LTD +0019F0 (base 16) UNIONMAN TECHNOLOGY CO.,LTD + 18F, HUAYANG TOWER,YANDAYI ROAD + HUIZHOU GUANGDONG 516007 + CN + +C8-DB-26 (hex) Logitech +C8DB26 (base 16) Logitech + 7700 Gateway Blvd + Newark CA 94560 + US + +A4-0E-2B (hex) Facebook Inc +A40E2B (base 16) Facebook Inc + 1 Hacker Way + Menlo Park CA 94025 + US + +AC-4E-2E (hex) Shenzhen JingHanDa Electronics Co.Ltd +AC4E2E (base 16) Shenzhen JingHanDa Electronics Co.Ltd + 5th Floor,No 4 ,Road 1,ShangXue Technology industrial Park,LongGang district,ShenZhen,GuangDong,China + ShenZhen GuangDong 518129 + CN + +4C-91-0C (hex) Lanix Internacional, S.A. de C.V. +4C910C (base 16) Lanix Internacional, S.A. de C.V. + Carretera Nogales Km8.5 + Hermosillo Sonora 83160 + MX + +A4-78-86 (hex) Avaya Inc +A47886 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +04-03-D6 (hex) Nintendo Co.,Ltd +0403D6 (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +5C-1A-6F (hex) Cambridge Industries(Group) Co.,Ltd. +5C1A6F (base 16) Cambridge Industries(Group) Co.,Ltd. + 5/F,Building 8, 2388 ChenHang Road, MinHang District + shanghai 201114 + CN + +3C-4C-D0 (hex) CERAGON NETWORKS +3C4CD0 (base 16) CERAGON NETWORKS + 24 RAUEL WALLENBERG STREET + TEL-AVIV 96719 + IL + +F4-0E-83 (hex) ARRIS Group, Inc. +F40E83 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +98-F7-D7 (hex) ARRIS Group, Inc. +98F7D7 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +B4-BF-F6 (hex) Samsung Electronics Co.,Ltd +B4BFF6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +2C-3A-E8 (hex) Espressif Inc. +2C3AE8 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +88-BD-78 (hex) Flaircomm Microelectronics,Inc. +88BD78 (base 16) Flaircomm Microelectronics,Inc. + 7F, Guomai Building, Guomai Science and Technology Park, 116 East JiangBin Road, + Fuzhou Fujian 350015 + CN + +58-C5-CB (hex) Samsung Electronics Co.,Ltd +58C5CB (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +20-6B-E7 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +206BE7 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +18-2C-B4 (hex) Nectarsoft Co., Ltd. +182CB4 (base 16) Nectarsoft Co., Ltd. + 330, Seongam-ro, Mapo-gu + Seoul Seoul 03920 + KR + +54-C9-DF (hex) FN-LINK TECHNOLOGY LIMITED +54C9DF (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +74-F6-1C (hex) HTC Corporation +74F61C (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +B8-FF-B3 (hex) MitraStar Technology Corp. +B8FFB3 (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +EC-23-7B (hex) zte corporation +EC237B (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +A0-C9-A0 (hex) Murata Manufacturing Co., Ltd. +A0C9A0 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +98-2D-BA (hex) Fibergate Inc. +982DBA (base 16) Fibergate Inc. + KDX Shibadaimon.Bld 2F 2-10-12 Shibadaimon + Tokyo Minato-ku 1050012 + JP + +84-C0-EF (hex) Samsung Electronics Co.,Ltd +84C0EF (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +00-A3-8E (hex) Cisco Systems, Inc +00A38E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E0-D5-5E (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +E0D55E (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + Pin-Jen City, Taoyuan, Taiwan, R.O.C. + Pin-Jen Taoyuan 324 + TW + +A0-40-A0 (hex) NETGEAR +A040A0 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-0D-2B (hex) Racal Instruments +000D2B (base 16) Racal Instruments + 4 Goodyear Street + Irvine CA 92618 + US + +00-40-66 (hex) APRESIA Systems Ltd +004066 (base 16) APRESIA Systems Ltd + Tsukuba Network Technical Center, Tsukuba Network + Tsuchiura-shi Ibaraki-ken 300-0026 + JP + +48-A7-4E (hex) zte corporation +48A74E (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +BC-8A-E8 (hex) QING DAO HAIER TELECOM CO.,LTD. +BC8AE8 (base 16) QING DAO HAIER TELECOM CO.,LTD. + No 1 Haier Road Hi-tech Zone + Qingdao 266000 + CN + +F4-DE-0C (hex) ESPOD Ltd. +F4DE0C (base 16) ESPOD Ltd. + 6 Marjanishvili St. (Green Building) | 0102 Tbilisi | Georgia + Tbilisi Tbilisi 0102 + GE + +3C-52-82 (hex) Hewlett Packard +3C5282 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +08-ED-02 (hex) IEEE Registration Authority +08ED02 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E8-FD-E8 (hex) CeLa Link Corporation +E8FDE8 (base 16) CeLa Link Corporation + 401-1, Partners Tower1, Gasan digital 1-ro 83, Geumcheon-gu + Seoul 08589 + KR + +28-C6-3F (hex) Intel Corporate +28C63F (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +88-CC-45 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +88CC45 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +60-08-37 (hex) ivvi Scientific(Nanchang)Co.Ltd +600837 (base 16) ivvi Scientific(Nanchang)Co.Ltd + Coolpad Cyber Harbor,2nd Mengxi Road,Hi-TechIndustrial Park(North),NanShan District,ShenZhen,P.R.C. + shenzhen Guangdong 518057 + CN + +EC-36-3F (hex) Markov Corporation +EC363F (base 16) Markov Corporation + 650 Vaqueros Avenue, Suite A + Sunnyvale CA 94085 + US + +58-04-CB (hex) Tianjin Huisun Technology Co.,Ltd. +5804CB (base 16) Tianjin Huisun Technology Co.,Ltd. + 4/f, Building 3, No 1 Haitai Huake Street (outside Ring Road) + Tianjin 300384 + CN + +60-D7-E3 (hex) IEEE Registration Authority +60D7E3 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +18-93-D7 (hex) Texas Instruments +1893D7 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +A8-B8-6E (hex) LG Electronics (Mobile Communications) +A8B86E (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +CC-90-E8 (hex) Shenzhen YOUHUA Technology Co., Ltd +CC90E8 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +7C-4F-7D (hex) Sawwave +7C4F7D (base 16) Sawwave + SKn TechnoPark 1207 + SeongNam-Si Gyenggi-do 13207 + KR + +9C-AC-6D (hex) Universal Electronics, Inc. +9CAC6D (base 16) Universal Electronics, Inc. + 201 E. Sandpointe Ave + Santa Ana CA 92707 + US + +08-EA-40 (hex) SHENZHEN BILIAN ELECTRONIC CO.,LTD +08EA40 (base 16) SHENZHEN BILIAN ELECTRONIC CO.,LTD + NO.268, Fuqian Rd, Jutang community, Guanlan Town, Longhua New district + shenzhen guangdong 518000 + CN + +00-D0-95 (hex) Alcatel-Lucent Enterprise +00D095 (base 16) Alcatel-Lucent Enterprise + 26801 West Agoura Road + Calabasas CA 91301 + US + +00-20-DA (hex) Alcatel-Lucent Enterprise +0020DA (base 16) Alcatel-Lucent Enterprise + 26801 West Agoura Road + CALABASAS CA 91301 + US + +6C-59-76 (hex) Shanghai Tricheer Technology Co.,Ltd. +6C5976 (base 16) Shanghai Tricheer Technology Co.,Ltd. + Rm 907, Building 1, Lane 399, Shengxia Road,Zhangjiang Hi-Tech Park,Pudong District,Shanghai + Shanghai Shanghai 201203 + CN + +7C-7B-8B (hex) Control Concepts, Inc. +7C7B8B (base 16) Control Concepts, Inc. + 18760 Lake Dr. East + Chanhassen MN 55317 + US + +84-A9-C4 (hex) HUAWEI TECHNOLOGIES CO.,LTD +84A9C4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A0-08-6F (hex) HUAWEI TECHNOLOGIES CO.,LTD +A0086F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +34-CE-00 (hex) XIAOMI Electronics,CO.,LTD +34CE00 (base 16) XIAOMI Electronics,CO.,LTD + Xiaomi Building, No.68 Qinghe Middle Street + Haidian District Beijing 100085 + CN + +D0-6F-82 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D06F82 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A0-F4-79 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A0F479 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +84-47-65 (hex) HUAWEI TECHNOLOGIES CO.,LTD +844765 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-FF-1F (hex) HUAWEI TECHNOLOGIES CO.,LTD +C4FF1F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A0-C4-A5 (hex) SYGN HOUSE CO.,LTD +A0C4A5 (base 16) SYGN HOUSE CO.,LTD + 2-9-14 Tamagawa-denenchofu + Setagaya-ku Tokyo 1580085 + JP + +B8-37-65 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +B83765 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +34-5B-BB (hex) GD Midea Air-Conditioning Equipment Co.,Ltd. +345BBB (base 16) GD Midea Air-Conditioning Equipment Co.,Ltd. + Midea Global Innovation Center,Beijiao Town,Shunde + Foshan Guangdong 528311 + CN + +C4-0B-CB (hex) Xiaomi Communications Co Ltd +C40BCB (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +84-AF-EC (hex) BUFFALO.INC +84AFEC (base 16) BUFFALO.INC + AKAMONDORI Bld.,30-20,Ohsu 3-chome,Naka-ku + Nagoya Aichi Pref. 460-8315 + JP + +5C-C6-E9 (hex) Edifier International +5CC6E9 (base 16) Edifier International + Suit 2207, 22nd floor, Tower II, Lippo centre, 89 Queensway + Hong Kong 070 + CN + +98-DD-EA (hex) Infinix mobility limited +98DDEA (base 16) Infinix mobility limited + RMS 05-15, 13A/F SOUTH TOWER WORLD FINANCE CTR HARBOUR CITY 17 CANTON RD TST KLN HONG KONG + HongKong HongKong 999077 + HK + +00-1D-44 (hex) Krohne +001D44 (base 16) Krohne + Ludwig-Krohne-Str. 5 + Duisburg 47058 + DE + +A8-A1-98 (hex) TCT mobile ltd +A8A198 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +E0-C0-D1 (hex) CK Telecom (Shenzhen) Limited +E0C0D1 (base 16) CK Telecom (Shenzhen) Limited + Floor 9th, Building 4C,Software Industry Base, Xuefu Road, Hi-Tech Park, Nanshan Dist. + Shenzhen Guangdong 518057 + CN + +00-21-9E (hex) Sony Mobile Communications Inc +00219E (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +AC-B5-7D (hex) Liteon Technology Corporation +ACB57D (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +D4-61-9D (hex) Apple, Inc. +D4619D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-49-8B (hex) ZOOM SERVER +D0498B (base 16) ZOOM SERVER + North keyuan Road + Shenzhen 518057 + CN + +08-27-CE (hex) NAGANO KEIKI CO., LTD. +0827CE (base 16) NAGANO KEIKI CO., LTD. + 2150 IKUTA + UEDA NAGANO 386-0411 + JP + +C0-D3-C0 (hex) Samsung Electronics Co.,Ltd +C0D3C0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +94-8B-C1 (hex) Samsung Electronics Co.,Ltd +948BC1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-56-8E (hex) Samsung Electronics Co.,Ltd +14568E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-BD-61 (hex) Apple, Inc. +14BD61 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-E0-61 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +54E061 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +50-3A-7D (hex) AlphaTech PLC Int’l Co., Ltd. +503A7D (base 16) AlphaTech PLC Int’l Co., Ltd. + 13F., No.618, Sec. 7, New Taipei Blvd., Xinzhuang Dist., + New Taipei City 24260 + TW + +F4-C4-D6 (hex) Shenzhen Xinfa Electronic Co.,ltd +F4C4D6 (base 16) Shenzhen Xinfa Electronic Co.,ltd + No 57, Baoli Road, Buji Town + Longgang District Shenzhen, Guangdong 518112 + CN + +68-37-E9 (hex) Amazon Technologies Inc. +6837E9 (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +2C-A1-7D (hex) ARRIS Group, Inc. +2CA17D (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +D8-32-14 (hex) Tenda Technology Co.,Ltd.Dongguan branch +D83214 (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +10-95-4B (hex) Megabyte Ltd. +10954B (base 16) Megabyte Ltd. + Unit 507, 5/F, Building 12W, NO.12 Science Park Avenue, Hong Kong Science Park, Shatin, New Territories + Hong Kong NA + HK + +D8-32-5A (hex) Shenzhen YOUHUA Technology Co., Ltd +D8325A (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +9C-DA-3E (hex) Intel Corporate +9CDA3E (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +28-3F-69 (hex) Sony Mobile Communications Inc +283F69 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-2C-C8 (hex) Cisco Systems, Inc +002CC8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C0-02-8D (hex) WINSTAR Display CO.,Ltd +C0028D (base 16) WINSTAR Display CO.,Ltd + 1F., No.77, Ln. 188, Pinghe S. Rd., Daya Dist., Taichung City 428, Taiwan (R.O.C.) + Taichung City 428 + TW + +E8-9F-EC (hex) CHENGDU KT ELECTRONIC HI-TECH CO.,LTD +E89FEC (base 16) CHENGDU KT ELECTRONIC HI-TECH CO.,LTD + No.9, 3rd Wuke Road, Wuhou District + Chengdu Sichuan Province 610045 + CN + +80-26-89 (hex) D-Link International +802689 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +F8-AB-05 (hex) Sagemcom Broadband SAS +F8AB05 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +7C-50-49 (hex) Apple, Inc. +7C5049 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-7D-EB (hex) Shanghai Notion Information Technology CO.,LTD. +E47DEB (base 16) Shanghai Notion Information Technology CO.,LTD. + Room 201,Building 3,NO 289,Bisheng Rd,Pudong district,Shanghai,China + Shanghai Shanghai 201203 + CN + +C4-B9-CD (hex) Cisco Systems, Inc +C4B9CD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +EC-4F-82 (hex) Calix Inc. +EC4F82 (base 16) Calix Inc. + 2777 Orchard Parkway + San Jose CA 95134 + US + +D4-61-FE (hex) Hangzhou H3C Technologies Co., Limited +D461FE (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +2C-4D-54 (hex) ASUSTek COMPUTER INC. +2C4D54 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +34-96-72 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +349672 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +64-B4-73 (hex) Xiaomi Communications Co Ltd +64B473 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +74-51-BA (hex) Xiaomi Communications Co Ltd +7451BA (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +6C-B4-A7 (hex) Landauer, Inc. +6CB4A7 (base 16) Landauer, Inc. + 2 Science Road + Glenwood IL 60425 + US + +78-02-F8 (hex) Xiaomi Communications Co Ltd +7802F8 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +00-23-8A (hex) Ciena Corporation +00238A (base 16) Ciena Corporation + 920 Elkridge Landing + Linthicum MD 21090 + US + +00-10-81 (hex) DPS, INC. +001081 (base 16) DPS, INC. + 4922 EAST YALE AVENUE + FRESNO CA 93727 + US + +40-F3-85 (hex) IEEE Registration Authority +40F385 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +88-78-73 (hex) Intel Corporate +887873 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +F8-75-88 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F87588 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-4C-7F (hex) HUAWEI TECHNOLOGIES CO.,LTD +F44C7F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +28-A2-4B (hex) Juniper Networks +28A24B (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +08-00-27 (hex) PCS Systemtechnik GmbH +080027 (base 16) PCS Systemtechnik GmbH + 600 Suffold St + Lowell MA 01854 + US + +F8-A5-C5 (hex) Cisco Systems, Inc +F8A5C5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +7C-5A-1C (hex) Sophos Ltd +7C5A1C (base 16) Sophos Ltd + The Pentagon + Abingdon Oxfordshire OX14 3YP + GB + +B0-F1-EC (hex) AMPAK Technology, Inc. +B0F1EC (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road Hsinchu Industrial Park, Hukou + Hsinchu Taiwan ROC. 30352 + TW + +54-2B-57 (hex) Night Owl SP +542B57 (base 16) Night Owl SP + 4720 Radio Rd + Naples FL 34104 + US + +50-1E-2D (hex) StreamUnlimited Engineering GmbH +501E2D (base 16) StreamUnlimited Engineering GmbH + Gutheil-Schoder-Gasse 10 + Vienna 1100 + AT + +E4-5D-51 (hex) SFR +E45D51 (base 16) SFR + 12 rue jean-philippe Rameau CS 80001 + La plaine saint denis FRANCE 93634 + FR + +EC-01-EE (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +EC01EE (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +60-49-C1 (hex) Avaya Inc +6049C1 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +70-20-84 (hex) Hon Hai Precision Ind. Co., Ltd. +702084 (base 16) Hon Hai Precision Ind. Co., Ltd. + GuangDongShenZhen + ShenZhen GuangDong 518109 + CN + +9C-66-50 (hex) Glodio Technolies Co.,Ltd Tianjin Branch +9C6650 (base 16) Glodio Technolies Co.,Ltd Tianjin Branch + Room 904, No.1-2 LanYuan Road, HuaYuan Industrial Area + TianJin TianJin 300384 + CN + +A0-A3-3B (hex) HUAWEI TECHNOLOGIES CO.,LTD +A0A33B (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-67-A2 (hex) Intel Corporate +7C67A2 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-E0-5A (hex) GALEA NETWORK SECURITY +00E05A (base 16) GALEA NETWORK SECURITY + 2 PLACE du COMMERCE - STE #320 + BROSSARD, QUEBEC J4W 2T8 + CA + +48-A3-80 (hex) Gionee Communication Equipment Co.,Ltd. +48A380 (base 16) Gionee Communication Equipment Co.,Ltd. + 21/F,Times Technology Building,No. 7028,Shennan Avenue,Futian District + Shenzhen 518000 + CN + +94-65-2D (hex) OnePlus Technology (Shenzhen) Co., Ltd +94652D (base 16) OnePlus Technology (Shenzhen) Co., Ltd + 18C02, 18C03, 18C04 ,18C05,TAIRAN BUILDING, + Shenzhen Guangdong 518000 + CN + +1C-B8-57 (hex) Becon Technologies Co,.Ltd. +1CB857 (base 16) Becon Technologies Co,.Ltd. + Room C405-A Induckwon IT Vally, 40, Imiro + Uiwang city Kyunggi-do 16006 + KR + +68-27-37 (hex) Samsung Electronics Co.,Ltd +682737 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +F0-6E-32 (hex) MICROTEL INNOVATION S.R.L. +F06E32 (base 16) MICROTEL INNOVATION S.R.L. + Via Armentera 8 + BORGO VALSUGANA TN 38051 + IT + +54-C4-15 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +54C415 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.469,Jianghui Road + Hangzhou Zhejiang 310052 + CN + +3C-F8-62 (hex) Intel Corporate +3CF862 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +28-16-AD (hex) Intel Corporate +2816AD (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-60-D3 (hex) AT&T +0060D3 (base 16) AT&T + 3300 E Renner Road + Richardson TX 75082 + US + +84-8D-C7 (hex) Cisco SPVTG +848DC7 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +00-19-92 (hex) Adtran Inc +001992 (base 16) Adtran Inc + 901 Explorer Blvd. + Huntsville AL 35806-2807 + US + +04-5D-4B (hex) Sony Corporation +045D4B (base 16) Sony Corporation + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +78-AF-58 (hex) GIMASI SA +78AF58 (base 16) GIMASI SA + Via Luigi Lavizzari 18 + Mendrisio TI 6850 + CH + +90-50-5A (hex) unGlue, Inc +90505A (base 16) unGlue, Inc + 7150 Helmsdale Circle + West Hils CA 91307 + US + +8C-93-51 (hex) Jigowatts Inc. +8C9351 (base 16) Jigowatts Inc. + 5892-5 Endo + Fujisawa Kanagawa 252-0816 + JP + +D8-38-FC (hex) Ruckus Wireless +D838FC (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +34-78-D7 (hex) Gionee Communication Equipment Co.,Ltd. +3478D7 (base 16) Gionee Communication Equipment Co.,Ltd. + 21/F,Times Technology Building,No. 7028,Shennan Avenue,Futian District + Shenzhen 518000 + CN + +5C-CC-A0 (hex) Gridwiz Inc. +5CCCA0 (base 16) Gridwiz Inc. + 4F, 25 Sanun-ro 208beon-gil, Bundang-gu + Seongnam Gyeonggi 13460 + KR + +68-31-FE (hex) Teladin Co.,Ltd. +6831FE (base 16) Teladin Co.,Ltd. + Digital-ro 33 gil, Guro-gu + Seoul 08377 + KR + +58-00-E3 (hex) Liteon Technology Corporation +5800E3 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +2C-0B-E9 (hex) Cisco Systems, Inc +2C0BE9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C4-30-18 (hex) MCS Logic Inc. +C43018 (base 16) MCS Logic Inc. + 6F. Samho Center B Bldg., 275-6,Yangjae-Dong, Secho-Ku,Seoul + Seoul 137-941 + KR + +D0-FF-98 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D0FF98 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B0-E5-ED (hex) HUAWEI TECHNOLOGIES CO.,LTD +B0E5ED (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-86-E9 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C486E9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-0A-E4 (hex) Wistron Corporation +000AE4 (base 16) Wistron Corporation + 21F, No. 88, Section 1, Hsin Tai Wu Rd. + Taipei 221 + TW + +34-4B-3D (hex) Fiberhome Telecommunication Technologies Co.,LTD +344B3D (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +FC-3C-E9 (hex) Tsingtong Technologies Co, Ltd. +FC3CE9 (base 16) Tsingtong Technologies Co, Ltd. + Rm A03-72, Floor B1, Building 1, No.13 Dazhongsi, Haidian District + Beijing 100098 + CN + +A4-08-F5 (hex) Sagemcom Broadband SAS +A408F5 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +00-B0-91 (hex) Transmeta Corp. +00B091 (base 16) Transmeta Corp. + 3940 Freedom Circle + Santa Clara CA 95054 + US + +AC-C6-62 (hex) MitraStar Technology Corp. +ACC662 (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +88-6B-44 (hex) Sunnovo International Limited +886B44 (base 16) Sunnovo International Limited + 1717 Haitai Building + Beijing Beijing 100083 + CN + +A4-58-0F (hex) IEEE Registration Authority +A4580F (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +C8-F7-33 (hex) Intel Corporate +C8F733 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +E0-A7-00 (hex) Verkada Inc +E0A700 (base 16) Verkada Inc + 325 Sharon Park Drive, Suite 519 + Menlo Park 94025 + US + +58-40-4E (hex) Apple, Inc. +58404E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-C5-F3 (hex) Apple, Inc. +D0C5F3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-9F-EF (hex) Apple, Inc. +BC9FEF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-AB-37 (hex) Apple, Inc. +20AB37 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-F4-45 (hex) Apple, Inc. +60F445 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-F9-7C (hex) Fiberhome Telecommunication Technologies Co.,LTD +48F97C (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +40-B9-3C (hex) Hewlett Packard Enterprise +40B93C (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +C0-BF-C0 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C0BFC0 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +9C-D9-CB (hex) Lesira Manufacturing Pty Ltd +9CD9CB (base 16) Lesira Manufacturing Pty Ltd + 34 Gemsbok Street + Pretoria Gauteng 0186 + ZA + +94-E9-79 (hex) Liteon Technology Corporation +94E979 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +A0-3D-6F (hex) Cisco Systems, Inc +A03D6F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A0-E0-AF (hex) Cisco Systems, Inc +A0E0AF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +18-75-32 (hex) SICHUAN TIANYI COMHEART TELECOMCO., LTD +187532 (base 16) SICHUAN TIANYI COMHEART TELECOMCO., LTD + FL12, TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +4C-B8-1C (hex) SAM Electronics GmbH +4CB81C (base 16) SAM Electronics GmbH + Behringstr. 120 + Hamburg Hamburg 22763 + DE + +00-30-48 (hex) Super Micro Computer, Inc. +003048 (base 16) Super Micro Computer, Inc. + 2051 Junction Avenue + San Jose CA 95131 + US + +44-D2-44 (hex) Seiko Epson Corporation +44D244 (base 16) Seiko Epson Corporation + 80 Harashinden + Shiojiri-shi Nagano-ken 399-0785 + JP + +A0-8C-F8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A08CF8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-F9-5C (hex) U.I. Lapp GmbH +7CF95C (base 16) U.I. Lapp GmbH + Schulze-Delitzsch-Strasse 25 + Stuttgart 70565 + DE + +10-13-31 (hex) Technicolor +101331 (base 16) Technicolor + Prins Boudewijnlaan 47 + Edegem - Belgium B-2650 + BE + +A4-E6-B1 (hex) Shanghai Joindata Technology Co.,Ltd. +A4E6B1 (base 16) Shanghai Joindata Technology Co.,Ltd. + 26F,Building1,No428,South Yanggao Road,Pudong District + Shanghai Shanghai 200127 + CN + +C0-9C-04 (hex) Shaanxi GuoLian Digital TV Technology Co.,Ltd. +C09C04 (base 16) Shaanxi GuoLian Digital TV Technology Co.,Ltd. + No. 15, the first Gaoxin road Hi-tech development district + Xi'an Shaanxi 710075 + CN + +AC-D6-57 (hex) Shaanxi GuoLian Digital TV Technology Co.,Ltd. +ACD657 (base 16) Shaanxi GuoLian Digital TV Technology Co.,Ltd. + Chief Building, Fifth Yannan Road, Qujiang New District + xi'an shaanxi 71000 + CN + +00-76-86 (hex) Cisco Systems, Inc +007686 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +8C-2F-A6 (hex) Solid Optics B.V. +8C2FA6 (base 16) Solid Optics B.V. + Huchtstraat 35 + Almere 1327EC + NL + +8C-19-2D (hex) IEEE Registration Authority +8C192D (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-AC-E0 (hex) ARRIS Group, Inc. +00ACE0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-75-32 (hex) INID BV +007532 (base 16) INID BV + Mariettahof 27 + Haarlem NH 2033WS + NL + +64-73-E2 (hex) Arbiter Systems, Inc. +6473E2 (base 16) Arbiter Systems, Inc. + 1324 Vendels Circle + Paso Robles California 93446 + US + +88-C6-26 (hex) Logitech, Inc +88C626 (base 16) Logitech, Inc + 4700 NW Camas Meadows Dr + Camas WA 98607 + US + +D0-60-8C (hex) zte corporation +D0608C (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +AC-23-3F (hex) Shenzhen Minew Technologies Co., Ltd. +AC233F (base 16) Shenzhen Minew Technologies Co., Ltd. + H Building, Gangzhilong Science Park, QInglong Road + Shenzhen 518109 + CN + +7C-03-C9 (hex) Shenzhen YOUHUA Technology Co., Ltd +7C03C9 (base 16) Shenzhen YOUHUA Technology Co., Ltd + Room 407 Shenzhen University-town Business Park,Lishan Road,Taoyuan Street,Nanshan District + Shenzhen Guangdong 518055 + CN + +B8-E9-37 (hex) Sonos, Inc. +B8E937 (base 16) Sonos, Inc. + 614 Chapala St + Santa Barbara CA 93101 + US + +E4-5D-52 (hex) Avaya Inc +E45D52 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +00-23-F7 (hex) Private +0023F7 (base 16) Private + +3C-80-AA (hex) Ransnet Singapore Pte Ltd +3C80AA (base 16) Ransnet Singapore Pte Ltd + 114, Lavender Street, #08-83, CT Hub 2 + Singapore Singapore 338729 + SG + +B4-96-91 (hex) Intel Corporate +B49691 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C8-21-58 (hex) Intel Corporate +C82158 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +24-20-C7 (hex) Sagemcom Broadband SAS +2420C7 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +D4-C8-B0 (hex) Prime Electronics & Satellitics Inc. +D4C8B0 (base 16) Prime Electronics & Satellitics Inc. + 69,Tung-Yuan Rd + Chung-Li City Tao-Yuan County 32000 + TW + +44-6A-B7 (hex) ARRIS Group, Inc. +446AB7 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +70-1C-E7 (hex) Intel Corporate +701CE7 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +9C-2A-70 (hex) Hon Hai Precision Ind. Co.,Ltd. +9C2A70 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +70-3D-15 (hex) Hangzhou H3C Technologies Co., Limited +703D15 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +E4-9E-12 (hex) FREEBOX SAS +E49E12 (base 16) FREEBOX SAS + 16 rue de la Ville l'Eveque + PARIS IdF 75008 + FR + +04-81-AE (hex) Clack Corporation +0481AE (base 16) Clack Corporation + 4462 Duraform Lane + Windsor WI 53598 + US + +9C-13-AB (hex) Chanson Water Co., Ltd. +9C13AB (base 16) Chanson Water Co., Ltd. + 2F, No.88-11, Sec 1, Guangfu Rd, Sanchong Dist. + New Taipei City Taiwan 241 + TW + +98-E4-76 (hex) Zentan +98E476 (base 16) Zentan + 10F-3, No. 260, Sec.2 New Taipei Blvd., Sanchong District + New Taipei City 24158 + TW + +14-A5-1A (hex) HUAWEI TECHNOLOGIES CO.,LTD +14A51A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +04-75-03 (hex) HUAWEI TECHNOLOGIES CO.,LTD +047503 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +3C-EF-8C (hex) Zhejiang Dahua Technology Co., Ltd. +3CEF8C (base 16) Zhejiang Dahua Technology Co., Ltd. + NO.1199 Bin An Road,Binjiang District,HangZhou,P.R.China + HangZhou ZheJiang 310053 + CN + +FC-37-2B (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +FC372B (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +A4-D9-A4 (hex) neXus ID Solutions AB +A4D9A4 (base 16) neXus ID Solutions AB + Telefonvägen 26 + Stockholm 12626 + SE + +48-4D-7E (hex) Dell Inc. +484D7E (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +D4-E9-0B (hex) CVT CO.,LTD +D4E90B (base 16) CVT CO.,LTD + Secho gu BangBae 3 dong 1001-1 + seoul KangNam KS013 + KR + +CC-B0-DA (hex) Liteon Technology Corporation +CCB0DA (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +7C-CC-1F (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +7CCC1F (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +18-F2-92 (hex) Shannon Systems +18F292 (base 16) Shannon Systems + Suite 1801,Wentong Building,739 Kunming Road, Yangpu, Shanghai + Shanghai 200000 + CN + +8C-EA-1B (hex) Edgecore Networks Corporation +8CEA1B (base 16) Edgecore Networks Corporation + 1 Creation RD 3. + Hsinchu 30077 + TW + +E0-2C-F3 (hex) MRS Electronic GmbH +E02CF3 (base 16) MRS Electronic GmbH + Klaus-Gutsch-Str. 7 + Rottweil 78628 + DE + +50-B3-63 (hex) Digitron da Amazonia S/A +50B363 (base 16) Digitron da Amazonia S/A + Av. Eng. Luis Carlos Berrini , 1297 + São Paulo São Paulo 04571010 + BR + +2C-0E-3D (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +2C0E3D (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +58-E1-6C (hex) Ying Hua Information Technology (Shanghai)Co., LTD +58E16C (base 16) Ying Hua Information Technology (Shanghai)Co., LTD + Room 37 ,Building 13b, No. 4 , lane 600, Tianshan Road ,Changning District Shanghai + Shanghai 201210 + CN + +9C-7D-A3 (hex) HUAWEI TECHNOLOGIES CO.,LTD +9C7DA3 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-C6-4F (hex) HUAWEI TECHNOLOGIES CO.,LTD +A4C64F (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +CC-FD-17 (hex) TCT mobile ltd +CCFD17 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +DC-9F-DB (hex) Ubiquiti Networks Inc. +DC9FDB (base 16) Ubiquiti Networks Inc. + 2580 Orchard Parkway + San Jose CA 95131 + US + +00-27-22 (hex) Ubiquiti Networks Inc. +002722 (base 16) Ubiquiti Networks Inc. + 91 E Tasman Dr + San Jose CA 95134 + US + +00-15-6D (hex) Ubiquiti Networks Inc. +00156D (base 16) Ubiquiti Networks Inc. + 495 Montague Expwy. + Milpitas CA 95035 + US + +00-D7-8F (hex) Cisco Systems, Inc +00D78F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +2C-BA-BA (hex) Samsung Electronics Co.,Ltd +2CBABA (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +40-D3-AE (hex) Samsung Electronics Co.,Ltd +40D3AE (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +2C-DD-95 (hex) Taicang T&W Electronics +2CDD95 (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +88-E8-7F (hex) Apple, Inc. +88E87F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-F4-8E (hex) Apple, Inc. +9CF48E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +5C-F7-E6 (hex) Apple, Inc. +5CF7E6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B8-53-AC (hex) Apple, Inc. +B853AC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-3C-AE (hex) Apple, Inc. +203CAE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A0-3B-E3 (hex) Apple, Inc. +A03BE3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +4C-32-75 (hex) Apple, Inc. +4C3275 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-7A-55 (hex) ALE International +487A55 (base 16) ALE International + 32 avenue Kléber + Colombes 92700 + FR + +00-1E-AE (hex) Continental Automotive Systems Inc. +001EAE (base 16) Continental Automotive Systems Inc. + 21440 West Lake Cook Road + Deer Park IL 60010 + US + +50-2B-73 (hex) Tenda Technology Co.,Ltd.Dongguan branch +502B73 (base 16) Tenda Technology Co.,Ltd.Dongguan branch + Room 79,Yuanyi Road,Dalang Town,Dongguan Guangdong 523770 + Dongguan Guangdong 523770 + CN + +04-BA-36 (hex) Li Seng Technology Ltd +04BA36 (base 16) Li Seng Technology Ltd + Rm901, 9/F Shiu Fung Hong Building, 239-241 Wing Lok Street, Hong Kong + Hong Kong 0000 + HK + +10-72-23 (hex) TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO +107223 (base 16) TELLESCOM INDUSTRIA E COMERCIO EM TELECOMUNICACAO + Av. Buriti, 1900 – Setor B – Distrito Industrial + Manaus Amazonas 69075-000 + BR + +E0-68-6D (hex) Raybased AB +E0686D (base 16) Raybased AB + A Odhners Gata 41 + Västra Frölunda 42130 + SE + +18-61-C7 (hex) lemonbeat GmbH +1861C7 (base 16) lemonbeat GmbH + Deutsche Str. 5 + Dortmund 44339 + DE + +9C-DC-71 (hex) Hewlett Packard Enterprise +9CDC71 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +B4-F8-1E (hex) Kinova +B4F81E (base 16) Kinova + 6110, rue Doris-Lussier, + Boisbriand Qc J7H 0E8 + CA + +D0-3D-C3 (hex) AQ Corporation +D03DC3 (base 16) AQ Corporation + 205, Saneop-ro 155beon-gil, Gwonseon-gu + Suwon Gyeonggi-do 16648 + KR + +EC-01-E2 (hex) FOXCONN INTERCONNECT TECHNOLOGY +EC01E2 (base 16) FOXCONN INTERCONNECT TECHNOLOGY + 66-1, Chungshan Rd., Tucheng Dist. + New Taipei City Taiwan (R.O.C.) 23680 + TW + +B4-E7-82 (hex) Vivalnk +B4E782 (base 16) Vivalnk + 4655 Old Ironsides Dr, #390 + Santa Clara CA 95054 + US + +44-09-B8 (hex) Salcomp (Shenzhen) CO., LTD. +4409B8 (base 16) Salcomp (Shenzhen) CO., LTD. + Salcomp Road, Furong Industrial Area, Xinqiao, Shajing, Baoan District + Shenzhen Guangdong 518125 + CN + +38-16-D1 (hex) Samsung Electronics Co.,Ltd +3816D1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D0-17-6A (hex) Samsung Electronics Co.,Ltd +D0176A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D4-88-90 (hex) Samsung Electronics Co.,Ltd +D48890 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-92-BE (hex) Samsung Electronics Co.,Ltd +5492BE (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +20-5D-47 (hex) vivo Mobile Communication Co., Ltd. +205D47 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +10-C6-0C (hex) Domino UK Ltd +10C60C (base 16) Domino UK Ltd + Trafalgar Way + Cambridge Cambridgeshire CB23 8TU + GB + +04-31-10 (hex) Inspur Group Co., Ltd. +043110 (base 16) Inspur Group Co., Ltd. + No.1036 Langchao Rd. + Jinan Shandong 250101 + CN + +94-9A-A9 (hex) Microsoft Corporation +949AA9 (base 16) Microsoft Corporation + One Microsoft Way + REDMOND WA 98052 + US + +AC-AB-2E (hex) Beijing LasNubes Technology Co., Ltd. +ACAB2E (base 16) Beijing LasNubes Technology Co., Ltd. + Chao-Yang-Bei-Lu No. 103, Room 1109-1110 + Beijing 100025 + CN + +60-0B-03 (hex) Hangzhou H3C Technologies Co., Limited +600B03 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +A0-AB-1B (hex) D-Link International +A0AB1B (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +D8-42-E2 (hex) Canary Connect, Inc. +D842E2 (base 16) Canary Connect, Inc. + 132 East 43rd Street + New York 10017 + US + +C8-B2-1E (hex) CHIPSEA TECHNOLOGIES (SHENZHEN) CORP. +C8B21E (base 16) CHIPSEA TECHNOLOGIES (SHENZHEN) CORP. + 9F,BLOCK A,GARDEN CITY DIGITAL BUILDING,NO.1079 NANHAI ROAD,NANSHAN DISTRICT + SHEN ZHEN GUANG DONG 518000 + CN + +00-06-78 (hex) D&M Holdings Inc. +000678 (base 16) D&M Holdings Inc. + D&M Building, 2-1 Nisshin-cho + Kawasaki-shi Kanagawa 210-8569 + JP + +E0-28-6D (hex) AVM Audiovisuelles Marketing und Computersysteme GmbH +E0286D (base 16) AVM Audiovisuelles Marketing und Computersysteme GmbH + Alt-Moabit 95 + Berlin Berlin 10559 + DE + +88-4C-CF (hex) Pulzze Systems, Inc +884CCF (base 16) Pulzze Systems, Inc + 1290-B Reamwood Ave + Sunnyvale CA 94089 + US + +50-09-59 (hex) Technicolor CH USA Inc. +500959 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +E4-12-18 (hex) ShenZhen Rapoo Technology Co., Ltd. +E41218 (base 16) ShenZhen Rapoo Technology Co., Ltd. + 22,Jinxiu Road East,Pingshan District,Shenzhen,China + Shenzhen Guangdong 518122 + CN + +00-19-84 (hex) ESTIC Corporation +001984 (base 16) ESTIC Corporation + 2-5-9 Hashibahigashino-cho + Moriguchi Osaka 570-0031 + JP + +00-16-28 (hex) Magicard Ltd +001628 (base 16) Magicard Ltd + Hampshire Road + Weymouth Dorset DT4 9XD + GB + +70-2E-22 (hex) zte corporation +702E22 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +C8-E7-76 (hex) PTCOM Technology +C8E776 (base 16) PTCOM Technology + NO.189-8, SEC. 3, NANJING E. RD., ZHONGSHAN DIST. + Taipei 10488 + TW + +00-02-78 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +000278 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Mae-tan-dong, + Suwon Suwon KOREA + KR + +00-23-99 (hex) Samsung Electronics Co.,Ltd +002399 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3dong, yeongtong-gu, Suwon-city + suwon 443-742 + KR + +00-17-C9 (hex) Samsung Electronics Co.,Ltd +0017C9 (base 16) Samsung Electronics Co.,Ltd + 416, Maetan-3Dong, Yeongtong-Gu + Suwon Geyonggi-Do 443-742 + KR + +90-6E-BB (hex) Hon Hai Precision Ind. Co.,Ltd. +906EBB (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +18-F4-6A (hex) Hon Hai Precision Ind. Co.,Ltd. +18F46A (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +4C-0F-6E (hex) Hon Hai Precision Ind. Co.,Ltd. +4C0F6E (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +78-E4-00 (hex) Hon Hai Precision Ind. Co.,Ltd. +78E400 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-21-2F (hex) Phoebe Micro Inc. +00212F (base 16) Phoebe Micro Inc. + 47606 Kato Rd + Fremont CA 94538 + US + +38-59-F9 (hex) Hon Hai Precision Ind. Co.,Ltd. +3859F9 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +EC-55-F9 (hex) Hon Hai Precision Ind. Co.,Ltd. +EC55F9 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +C4-73-1E (hex) Samsung Electronics Co.,Ltd +C4731E (base 16) Samsung Electronics Co.,Ltd + 416, Maetan 3dong, Yeongtong-Gu + Suwon Gyeonggi-Do 443742 + KR + +5C-0A-5B (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +5C0A5B (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Maetan3-Dong, Yeongtong-Gu + Suwon 443-743 + US + +7C-E9-D3 (hex) Hon Hai Precision Ind. Co.,Ltd. +7CE9D3 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +1C-3E-84 (hex) Hon Hai Precision Ind. Co.,Ltd. +1C3E84 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +B8-76-3F (hex) Hon Hai Precision Ind. Co.,Ltd. +B8763F (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +60-F4-94 (hex) Hon Hai Precision Ind. Co.,Ltd. +60F494 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +80-56-F2 (hex) Hon Hai Precision Ind. Co.,Ltd. +8056F2 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +7C-F8-54 (hex) Samsung Electronics Co.,Ltd +7CF854 (base 16) Samsung Electronics Co.,Ltd + 415, Maetan-3dong, Yeongtong-gu, Suwon-City Gyeonggi-do 443-742 + Suwon 443-742 + KR + +00-1B-98 (hex) Samsung Electronics Co.,Ltd +001B98 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + GUMI Gyeong-Buk 730-350 + KR + +00-1A-8A (hex) Samsung Electronics Co.,Ltd +001A8A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi-City Gyeong-Buk 730-350 + KR + +3C-5A-37 (hex) Samsung Electronics Co.,Ltd +3C5A37 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F4-9F-54 (hex) Samsung Electronics Co.,Ltd +F49F54 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +34-C3-AC (hex) Samsung Electronics Co.,Ltd +34C3AC (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +44-F4-59 (hex) Samsung Electronics Co.,Ltd +44F459 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-26-5D (hex) Samsung Electronics Co.,Ltd +00265D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +CC-F9-E8 (hex) Samsung Electronics Co.,Ltd +CCF9E8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D8-57-EF (hex) Samsung Electronics Co.,Ltd +D857EF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +18-E2-C2 (hex) Samsung Electronics Co.,Ltd +18E2C2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +98-52-B1 (hex) Samsung Electronics Co.,Ltd +9852B1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E4-40-E2 (hex) Samsung Electronics Co.,Ltd +E440E2 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +10-3B-59 (hex) Samsung Electronics Co.,Ltd +103B59 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D8-90-E8 (hex) Samsung Electronics Co.,Ltd +D890E8 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C4-62-EA (hex) Samsung Electronics Co.,Ltd +C462EA (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +14-F4-2A (hex) Samsung Electronics Co.,Ltd +14F42A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +08-08-C2 (hex) Samsung Electronics Co.,Ltd +0808C2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +CC-FE-3C (hex) Samsung Electronics Co.,Ltd +CCFE3C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +28-BA-B5 (hex) Samsung Electronics Co.,Ltd +28BAB5 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +18-26-66 (hex) Samsung Electronics Co.,Ltd +182666 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +30-D6-C9 (hex) Samsung Electronics Co.,Ltd +30D6C9 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +CC-07-AB (hex) Samsung Electronics Co.,Ltd +CC07AB (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-25-67 (hex) Samsung Electronics Co.,Ltd +002567 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +BC-B1-F3 (hex) Samsung Electronics Co.,Ltd +BCB1F3 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +1C-62-B8 (hex) Samsung Electronics Co.,Ltd +1C62B8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B4-3A-28 (hex) Samsung Electronics Co.,Ltd +B43A28 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +78-A8-73 (hex) Samsung Electronics Co.,Ltd +78A873 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-1C-43 (hex) Samsung Electronics Co.,Ltd +001C43 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-23-D6 (hex) Samsung Electronics Co.,Ltd +0023D6 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +E4-12-1D (hex) Samsung Electronics Co.,Ltd +E4121D (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +44-D6-E1 (hex) Snuza International Pty. Ltd. +44D6E1 (base 16) Snuza International Pty. Ltd. + Unit 11, Roeland Square, Roeland Street + Cape Town Western Cape 8001 + ZA + +FC-91-14 (hex) Technicolor CH USA Inc. +FC9114 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +48-6D-BB (hex) Vestel Elektronik San ve Tic. A.Ş. +486DBB (base 16) Vestel Elektronik San ve Tic. A.Ş. + Organize san + Manisa Turket 45030 + TR + +00-2A-10 (hex) Cisco Systems, Inc +002A10 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-A2-89 (hex) Cisco Systems, Inc +00A289 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +44-E9-DD (hex) Sagemcom Broadband SAS +44E9DD (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + RUEIL MALMAISON CEDEX Hauts de Seine 92848 + FR + +00-0F-5E (hex) Veo +000F5E (base 16) Veo + 910 Rincon Circle + San Jose CA 95131 + US + +00-13-28 (hex) Westech Korea Inc., +001328 (base 16) Westech Korea Inc., + 548-9, Gajwa3-Dong,Seo-ku, + Incheon 404-817 + KR + +B8-BF-83 (hex) Intel Corporate +B8BF83 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +8C-61-02 (hex) Beijing Baofengmojing Technologies Co., Ltd +8C6102 (base 16) Beijing Baofengmojing Technologies Co., Ltd + 7/F, Tower C, Zhizhen Plaza, No.7 Zhichun Rd, Haidian District + Beijing 100191 + CN + +54-8C-A0 (hex) Liteon Technology Corporation +548CA0 (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +7C-79-E8 (hex) PayRange Inc. +7C79E8 (base 16) PayRange Inc. + 700 NE Multnomah St. Ste 1400 + Portland OR 97232 + US + +A4-31-11 (hex) ZIV +A43111 (base 16) ZIV + Polígono Parque Tecnológico, 210 + ZAMUDIO VIZCAYA 48170 + ES + +00-80-73 (hex) DWB ASSOCIATES +008073 (base 16) DWB ASSOCIATES + 9360 SW GEMINI DRIVE + BEAVERTON OR 97005-7151 + US + +80-A1-D7 (hex) Shanghai DareGlobal Technologies Co.,Ltd +80A1D7 (base 16) Shanghai DareGlobal Technologies Co.,Ltd + 22F,Info Tech Building,No.1555,Kongjiang Rd. + Shanghai 200092 + CN + +EC-1F-72 (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +EC1F72 (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93 Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +8C-0D-76 (hex) HUAWEI TECHNOLOGIES CO.,LTD +8C0D76 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +84-BE-52 (hex) HUAWEI TECHNOLOGIES CO.,LTD +84BE52 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +84-9F-B5 (hex) HUAWEI TECHNOLOGIES CO.,LTD +849FB5 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-CA-A0 (hex) HUAWEI TECHNOLOGIES CO.,LTD +A4CAA0 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +84-E0-F4 (hex) IEEE Registration Authority +84E0F4 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D8-30-62 (hex) Apple, Inc. +D83062 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-E5-4D (hex) ARRIS Group, Inc. +D0E54D (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +A0-C5-62 (hex) ARRIS Group, Inc. +A0C562 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +84-96-D8 (hex) ARRIS Group, Inc. +8496D8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-26-D9 (hex) ARRIS Group, Inc. +0026D9 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E8-50-8B (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +E8508B (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +F8-04-2E (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +F8042E (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak + Bangpakong Chachoengsao 24180 + TH + +00-D0-37 (hex) ARRIS Group, Inc. +00D037 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +84-E0-58 (hex) ARRIS Group, Inc. +84E058 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +70-76-30 (hex) ARRIS Group, Inc. +707630 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +04-BB-F9 (hex) Pavilion Data Systems Inc +04BBF9 (base 16) Pavilion Data Systems Inc + 2560 N 1st St, #220 + San Jose CA 95131 + US + +E4-BE-ED (hex) Netcore Technology Inc. +E4BEED (base 16) Netcore Technology Inc. + ORIENTAL CYBERPORT,HIGHTECH 6 ROAD + Shenzhen 518057 + CN + +58-FB-84 (hex) Intel Corporate +58FB84 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-A0-0E (hex) NetAlly +00A00E (base 16) NetAlly + 310 Littleton Road + Westford MA 01886 + US + +00-C0-17 (hex) NetAlly +00C017 (base 16) NetAlly + 2075 Research Parkway + Colorado Springs CO 80920 + US + +5C-B0-66 (hex) ARRIS Group, Inc. +5CB066 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +BC-8A-A3 (hex) NHN Entertainment +BC8AA3 (base 16) NHN Entertainment + Play Museum, 629 Sampyeong-dong, Bundang-gu + Seongnam-si, Gyeonggi-do 463-400 + KR + +A8-BD-27 (hex) Hewlett Packard Enterprise +A8BD27 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +34-57-60 (hex) MitraStar Technology Corp. +345760 (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +C0-D3-91 (hex) IEEE Registration Authority +C0D391 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D4-9B-5C (hex) Chongqing Miedu Technology Co., Ltd. +D49B5C (base 16) Chongqing Miedu Technology Co., Ltd. + 7-602 No.118 DaPing Main Street Yuzhong District + Chongqing 400000 + CN + +E8-EB-11 (hex) Texas Instruments +E8EB11 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +44-BF-E3 (hex) Shenzhen Longtech Electronics Co.,Ltd +44BFE3 (base 16) Shenzhen Longtech Electronics Co.,Ltd + No.148 Zhengfeng Industrial Area Donghuan RD Huangpu Village Shaijing Town Baoan District + Shenzhen Guangdong 518125 + CN + +3C-6F-EA (hex) Panasonic India Pvt. Ltd. +3C6FEA (base 16) Panasonic India Pvt. Ltd. + 12th Floor, Ambience Tower, Ambience Island, NH - 8 + Gurgaon Haryana 122002 + IN + +00-22-61 (hex) Frontier Silicon Ltd +002261 (base 16) Frontier Silicon Ltd + 137 Euston Road + London NW12AA + GB + +00-19-88 (hex) Wi2Wi, Inc +001988 (base 16) Wi2Wi, Inc + 2107 N. 1st Street + San Jose CA 95131 + US + +18-DC-56 (hex) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd +18DC56 (base 16) Yulong Computer Telecommunication Scientific (Shenzhen) Co.,Ltd + 8/F.high Tech Plaza,TianAn Cyberpark,Chegongmiao + Shenzhen Guangdong 518040 + CN + +00-16-F2 (hex) Dmobile System Co., Ltd. +0016F2 (base 16) Dmobile System Co., Ltd. + 2F, No.13-20, Sec.6, Mincyuan E.Rd, + Taipei 114 + TW + +34-07-4F (hex) AccelStor, Inc. +34074F (base 16) AccelStor, Inc. + 10F, No. 465, Sec. 6, Zhongxiao E. Rd., Nangang Dist. + Taipei City 11557 + TW + +B4-A9-84 (hex) Symantec Corporation +B4A984 (base 16) Symantec Corporation + 350 Ellis Street + Mountain View CA 94043 + US + +B0-B2-8F (hex) Sagemcom Broadband SAS +B0B28F (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +44-14-41 (hex) AudioControl Inc. +441441 (base 16) AudioControl Inc. + 22410 70Th Ave West, STE 1 + Mountlake Terrace WA 98043 + US + +C8-8D-83 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C88D83 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-E0-11 (hex) UNIDEN CORPORATION +00E011 (base 16) UNIDEN CORPORATION + 2-12-7 Hatchobori, + Chuo-ku Tokyo 104-8512 + JP + +00-25-55 (hex) Visonic Technologies 1993 Ltd. +002555 (base 16) Visonic Technologies 1993 Ltd. + 23 Habarzel st' + Tel - Aviv 69710 + IL + +58-98-6F (hex) Revolution Display +58986F (base 16) Revolution Display + 912 Ruberta Ave + Glendale CA 91201 + US + +C8-1F-BE (hex) HUAWEI TECHNOLOGIES CO.,LTD +C81FBE (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +20-3D-B2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +203DB2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +48-D5-39 (hex) HUAWEI TECHNOLOGIES CO.,LTD +48D539 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-1F-9A (hex) Nortel Networks +001F9A (base 16) Nortel Networks + 2221 Lakeside Blvd + Richardson TX 75082-4399 + US + +00-0A-0E (hex) Invivo Research Inc. +000A0E (base 16) Invivo Research Inc. + 12601 Research Parkway + Orlando Florida 32826 + US + +00-16-60 (hex) Nortel Networks +001660 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-1E-7E (hex) Nortel Networks +001E7E (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-13-65 (hex) Nortel Networks +001365 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-04-38 (hex) Nortel Networks +000438 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +00-0E-C0 (hex) Nortel Networks +000EC0 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +D8-4F-B8 (hex) LG ELECTRONICS +D84FB8 (base 16) LG ELECTRONICS + 84 Wanam-ro Seongsan-gu + Changwon-si Gyeongsangnam-do 642-713 + KR + +00-0A-EB (hex) TP-LINK TECHNOLOGIES CO.,LTD. +000AEB (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Hi-Tech Park R1-B3 + Shenzhen Guangdong 518057 + CN + +2C-37-31 (hex) SHENZHEN YIFANG DIGITAL TECHNOLOGY CO.,LTD. +2C3731 (base 16) SHENZHEN YIFANG DIGITAL TECHNOLOGY CO.,LTD. + Building # 22 and #23, Zone 5, Bai Wang Xin Industrial Park, Song Bai Road + ShenZhen GUANGDONG 518108 + CN + +60-EE-5C (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +60EE5C (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +64-88-FF (hex) Sichuan Changhong Electric Ltd. +6488FF (base 16) Sichuan Changhong Electric Ltd. + 35 East Mianxing Road,High-Tech Park, + MianYang SiChuan 621000 + CN + +00-21-62 (hex) Nortel Networks +002162 (base 16) Nortel Networks + 8200 Dixie Rd + Brampton Ontario 0000 + CA + +02-E6-D3 (hex) NIXDORF COMPUTER CORP. +02E6D3 (base 16) NIXDORF COMPUTER CORP. + NIXDORF TECHNOLOGY CENTER + SANTA CLARA CA 95054 + US + +00-16-B9 (hex) ProCurve Networking by HP +0016B9 (base 16) ProCurve Networking by HP + 8000 Foothills Blvd + Roseville CA 95747 + US + +C4-08-4A (hex) Nokia +C4084A (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +00-08-01 (hex) HighSpeed Surfing Inc. +000801 (base 16) HighSpeed Surfing Inc. + 44790 S. Grimmer Blvd. + Fremont CA 94538 + US + +00-07-72 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +000772 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +E0-30-05 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +E03005 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +3C-40-4F (hex) GUANGDONG PISEN ELECTRONICS CO.,LTD +3C404F (base 16) GUANGDONG PISEN ELECTRONICS CO.,LTD + Building C,Liuyue Jintang Industry Zone + Shenzhen Guangdong 518173 + CN + +0C-A4-02 (hex) Alcatel-Lucent IPD +0CA402 (base 16) Alcatel-Lucent IPD + 600 March Drive + Kanata Ontario K2K2E6 + CA + +A0-F3-E4 (hex) Alcatel-Lucent IPD +A0F3E4 (base 16) Alcatel-Lucent IPD + 600 March Drive + Kanata Ontario K2K2E6 + CA + +84-DB-FC (hex) Nokia +84DBFC (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +7C-FC-3C (hex) Visteon Corporation +7CFC3C (base 16) Visteon Corporation + One Village Center Drive + Van Buren Twp MI 48111 + US + +98-1E-0F (hex) Jeelan (Shanghai Jeelan Technology Information Inc +981E0F (base 16) Jeelan (Shanghai Jeelan Technology Information Inc + Room 302,Building 17, No.658, Jinzhong Road + shanghai 200052 + CN + +48-88-CA (hex) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. +4888CA (base 16) Motorola (Wuhan) Mobility Technologies Communication Co., Ltd. + No.19, Gaoxin 4th Road, Wuhan East Lake High-tech Zone, Wuhan + Wuhan Hubei 430000 + CN + +38-56-10 (hex) CANDY HOUSE, Inc. +385610 (base 16) CANDY HOUSE, Inc. + 119 University Ave. + Palo Alto CA 94301 + US + +00-A7-42 (hex) Cisco Systems, Inc +00A742 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-AA-70 (hex) LG Electronics (Mobile Communications) +00AA70 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +F8-95-C7 (hex) LG Electronics (Mobile Communications) +F895C7 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +84-D9-31 (hex) Hangzhou H3C Technologies Co., Limited +84D931 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang, P.R.China 310052 + CN + +00-11-6E (hex) Peplink International Ltd. +00116E (base 16) Peplink International Ltd. + 17/F., Park Building + Cheung Sha Wan Kowloon 0000 + HK + +54-09-55 (hex) zte corporation +540955 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-1E-75 (hex) LG Electronics (Mobile Communications) +001E75 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-1C-62 (hex) LG Electronics (Mobile Communications) +001C62 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +50-55-27 (hex) LG Electronics (Mobile Communications) +505527 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +88-C9-D0 (hex) LG Electronics (Mobile Communications) +88C9D0 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +C0-41-F6 (hex) LG ELECTRONICS INC +C041F6 (base 16) LG ELECTRONICS INC + 19-1,Cheongho-Ri,Jinwi-Myeon + Pyeongtaek Gyeonggi-Do 451-713 + KR + +8C-3A-E3 (hex) LG Electronics (Mobile Communications) +8C3AE3 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +90-A4-6A (hex) SISNET CO., LTD +90A46A (base 16) SISNET CO., LTD + 1409, SJ Technoville 60-19, Gasan-dong, Geumcheon-Gu + Seoul KS013 + KR + +14-E7-C8 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +14E7C8 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +EC-CD-6D (hex) Allied Telesis, Inc. +ECCD6D (base 16) Allied Telesis, Inc. + 3041 Orchard Parkway + San Jose 95134 + US + +18-33-9D (hex) Cisco Systems, Inc +18339D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +14-61-02 (hex) Alpine Electronics, Inc. +146102 (base 16) Alpine Electronics, Inc. + 20-1, Yoshima Industrial Park + Iwaki Fukushima 970-1192 + JP + +54-27-6C (hex) Jiangsu Houge Technology Corp. +54276C (base 16) Jiangsu Houge Technology Corp. + No.20 Xizhang North Road, Fenghuang Town + Zhangjiagang Jiangsu 215614 + CN + +9C-A3-A9 (hex) Guangzhou Juan Optical and Electronical Tech Joint Stock Co., Ltd +9CA3A9 (base 16) Guangzhou Juan Optical and Electronical Tech Joint Stock Co., Ltd + NO.9, street 3, HengLing industrial zone, Tangdong, tianhe district + Guangzhou Guangdong 510000 + CN + +7C-C7-09 (hex) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. +7CC709 (base 16) SHENZHEN RF-LINK TECHNOLOGY CO.,LTD. + Bldg56A, 6/F, Baotian Rd3, Baoan District, Shenzhen, P.R.C + Shenzhen Guangdong 518100 + CN + +A0-3E-6B (hex) IEEE Registration Authority +A03E6B (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +98-02-D8 (hex) IEEE Registration Authority +9802D8 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +64-FB-81 (hex) IEEE Registration Authority +64FB81 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +08-21-EF (hex) Samsung Electronics Co.,Ltd +0821EF (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +34-14-5F (hex) Samsung Electronics Co.,Ltd +34145F (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +2C-26-5F (hex) IEEE Registration Authority +2C265F (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +D0-05-2A (hex) Arcadyan Corporation +D0052A (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +E4-50-9A (hex) HW Communications Ltd +E4509A (base 16) HW Communications Ltd + Parkfield + Lancaster LA1 4TZ + GB + +70-29-00 (hex) Shenzhen ChipTrip Technology Co,Ltd +702900 (base 16) Shenzhen ChipTrip Technology Co,Ltd + The 8th floor of VIA Technology Building NO. 9966 Shennan road , Nanshan Distict Shenzhen + Shenzhen 518000 + CN + +EC-AA-A0 (hex) PEGATRON CORPORATION +ECAAA0 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +00-E0-DD (hex) Zenith Electronics Corporation +00E0DD (base 16) Zenith Electronics Corporation + 1000 MILWAUKEE AVENUE + GLENVIEW IL 60025 + US + +50-CE-75 (hex) Measy Electronics Co., Ltd. +50CE75 (base 16) Measy Electronics Co., Ltd. + #1506, Block B, Hai Song Bldg, Tairan 9th Road + Shenzhen Guang Dong 518040 + CN + +00-04-5B (hex) Techsan Electronics Co., Ltd. +00045B (base 16) Techsan Electronics Co., Ltd. + North Wing + UNITED KINGDOM + GB + +00-07-BA (hex) UTStarcom Inc +0007BA (base 16) UTStarcom Inc + 1275 Harbor Bay PKWY + Alameda CA 94502 + US + +90-A2-10 (hex) United Telecoms Ltd +90A210 (base 16) United Telecoms Ltd + 18A/19,Doddanekundi Industrial Area, + Bangalore Karanataka 560048 + IN + +6C-0B-84 (hex) Universal Global Scientific Industrial Co., Ltd. +6C0B84 (base 16) Universal Global Scientific Industrial Co., Ltd. + 141, Lane 351, TaiPing Road, Sec.1 + Tsao-Tuen Nan-Tou 54261 + TW + +00-15-97 (hex) AETA AUDIO SYSTEMS +001597 (base 16) AETA AUDIO SYSTEMS + 18-22, avenue Edouard Herriot + Le Plessis Robinson 92350 + FR + +00-23-97 (hex) Westell Technologies Inc. +002397 (base 16) Westell Technologies Inc. + 750 N Commons Dr + Aurora IL 60504 + US + +60-E3-AC (hex) LG Electronics (Mobile Communications) +60E3AC (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +90-F0-52 (hex) MEIZU Technology Co., Ltd. +90F052 (base 16) MEIZU Technology Co., Ltd. + MEIZU Tech Bldg., Technology & Innovation Coast + Zhuhai Guangdong 519085 + CN + +00-16-39 (hex) Ubiquam Co., Ltd. +001639 (base 16) Ubiquam Co., Ltd. + Technovill 4F,272-3 Yatap3 + Seongnam Kyeonggi 463-836 + KR + +00-0C-29 (hex) VMware, Inc. +000C29 (base 16) VMware, Inc. + 3401 Hillview Avenue + Palo Alto CA 94304 + US + +00-05-69 (hex) VMware, Inc. +000569 (base 16) VMware, Inc. + 3401 Hillview Avenue + Palo Alto CA 94304 + US + +00-0B-0E (hex) Trapeze Networks +000B0E (base 16) Trapeze Networks + 5753 W. Las Positas Blvd + Pleasanton CA 94588 + US + +8C-FD-F0 (hex) Qualcomm Inc. +8CFDF0 (base 16) Qualcomm Inc. + 5775 Morehouse Drive + San Diego CA 92121 + US + +C4-BB-4C (hex) Zebra Information Tech Co. Ltd +C4BB4C (base 16) Zebra Information Tech Co. Ltd + Room 415, No.569 Anchi Road, JiaDing District + Shanghai 201804 + CN + +98-CF-53 (hex) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. +98CF53 (base 16) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + LiWu INDUSTRIAL PARK,Wusha,Chang'an + Dong Guan Guang Dong 523860 + CN + +D4-A1-48 (hex) HUAWEI TECHNOLOGIES CO.,LTD +D4A148 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +D0-65-CA (hex) HUAWEI TECHNOLOGIES CO.,LTD +D065CA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +48-6B-2C (hex) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. +486B2C (base 16) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + LiWu INDUSTRIAL PARK,Wusha,Chang'an + Dong Guan Guang Dong 523860 + CN + +6C-25-B9 (hex) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. +6C25B9 (base 16) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + LiWu INDUSTRIAL PARK,Wusha,Chang'an + Dong Guan Guang Dong 523860 + CN + +2C-28-2D (hex) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. +2C282D (base 16) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + LiWu INDUSTRIAL PARK,Wusha,Chang'an + Dong Guan Guang Dong 523860 + CN + +48-13-F3 (hex) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. +4813F3 (base 16) BBK EDUCATIONAL ELECTRONICS CORP.,LTD. + LiWu INDUSTRIAL PARK,Wusha,Chang'an + Dong Guan Guang Dong 523860 + CN + +00-40-9F (hex) Telco Systems, Inc. +00409F (base 16) Telco Systems, Inc. + 15 Berkshire Road + Mansfield, MA 02048 + US + +00-00-1F (hex) Telco Systems, Inc. +00001F (base 16) Telco Systems, Inc. + 15 Berkshire Road + Mansfield MA 02048 + US + +00-A0-12 (hex) Telco Systems, Inc. +00A012 (base 16) Telco Systems, Inc. + 15 Berkshire Road + Mansfield MA 02048 + US + +8C-EB-C6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +8CEBC6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B0-89-00 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B08900 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +78-CB-68 (hex) DAEHAP HYPER-TECH +78CB68 (base 16) DAEHAP HYPER-TECH + 302,Galmachiro,Woolim Lions Valley 5-cha #A-810,Jungwon-Gu + Seongnam, Gyeonggido 445-918 + KR + +34-ED-0B (hex) Shanghai XZ-COM.CO.,Ltd. +34ED0B (base 16) Shanghai XZ-COM.CO.,Ltd. + 11th Floor,B Building ,No.100 Qinzhou Road ,Shanghai + shanghai shanghai 200235 + CN + +F0-DE-F1 (hex) Wistron Infocomm (Zhongshan) Corporation +F0DEF1 (base 16) Wistron Infocomm (Zhongshan) Corporation + 168KunShan, + JiangSu 215300 + CN + +F8-0F-41 (hex) Wistron Infocomm (Zhongshan) Corporation +F80F41 (base 16) Wistron Infocomm (Zhongshan) Corporation + Torch High-tech Industrial Development Zone, + ZhongShan Guangdong 528437 + CN + +3C-97-0E (hex) Wistron InfoComm(Kunshan)Co.,Ltd. +3C970E (base 16) Wistron InfoComm(Kunshan)Co.,Ltd. + 168# First Avence, + Kunshan JiangSu 215300 + CN + +30-14-4A (hex) Wistron Neweb Corporation +30144A (base 16) Wistron Neweb Corporation + 20 Park Avenue II, Hsin Science Park, Hsinchu 308, Taiwan + HsinChu Taiwan 308 + TW + +4C-0B-BE (hex) Microsoft +4C0BBE (base 16) Microsoft + 1 Microsoft Way + Redmond Washington 98052 + US + +0C-25-76 (hex) LONGCHEER TELECOMMUNICATION LIMITED +0C2576 (base 16) LONGCHEER TELECOMMUNICATION LIMITED + Building 1,No.401,Caobao Rd + Shanghai Xuhui District 200233 + CN + +D8-D4-3C (hex) Sony Corporation +D8D43C (base 16) Sony Corporation + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +D4-41-65 (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +D44165 (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +E4-02-9B (hex) Intel Corporate +E4029B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +DC-1A-C5 (hex) vivo Mobile Communication Co., Ltd. +DC1AC5 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong 523860 + CN + +F4-5E-AB (hex) Texas Instruments +F45EAB (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +A8-FC-B7 (hex) Consolidated Resource Imaging +A8FCB7 (base 16) Consolidated Resource Imaging + 2943 S Wilson CT NW + Grand Rapids MI 49534 + US + +00-C0-00 (hex) LANOPTICS, LTD. +00C000 (base 16) LANOPTICS, LTD. + P.O. BOX 184 + ISRAEL ISRAEL 10551 + IL + +84-51-81 (hex) Samsung Electronics Co.,Ltd +845181 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-C2-87 (hex) Technicolor CH USA Inc. +B0C287 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +CC-35-40 (hex) Technicolor CH USA Inc. +CC3540 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +8C-04-FF (hex) Technicolor CH USA Inc. +8C04FF (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +FC-94-E3 (hex) Technicolor CH USA Inc. +FC94E3 (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +B8-8D-12 (hex) Apple, Inc. +B88D12 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-EF-68 (hex) Zyxel Communications Corporation +90EF68 (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +C8-16-BD (hex) Qingdao Hisense Communications Co.,Ltd. +C816BD (base 16) Qingdao Hisense Communications Co.,Ltd. + Qianwangang Road 218 + Qingdao Shandong 266510 + CN + +00-EB-D5 (hex) Cisco Systems, Inc +00EBD5 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +C4-8F-07 (hex) Shenzhen Yihao Hulian Science and Technology Co., Ltd. +C48F07 (base 16) Shenzhen Yihao Hulian Science and Technology Co., Ltd. + Room A, Floor 6, Building 210, Tairan Industry and Trade Park, Che Kung Temple, Futian District, Shenzhen, Guangdong Province + ShenZhen Guangdong 518000 + CN + +DC-78-34 (hex) LOGICOM SA +DC7834 (base 16) LOGICOM SA + 55 Rue de Lisbonne + PARIS 75008 + FR + +CC-CC-81 (hex) HUAWEI TECHNOLOGIES CO.,LTD +CCCC81 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +6C-95-22 (hex) Scalys +6C9522 (base 16) Scalys + Lansinkesweg 4 + Hengelo 7553 AE + NL + +B4-56-B9 (hex) Teraspek Technologies Co.,Ltd +B456B9 (base 16) Teraspek Technologies Co.,Ltd + 14th floor,Block C,Beijing International Building, Zhongguancun South Street, Beijng, China, 100081 + Beijing 100081 + CN + +9C-DD-1F (hex) Intelligent Steward Co.,Ltd +9CDD1F (base 16) Intelligent Steward Co.,Ltd + Room 508-598 XiTianGeZhuang Town Government Office Building,8# XiTong Road ,Economic Development District ,MiYun County ,BeiJing City + BeiJing City 101509 + CN + +3C-68-16 (hex) VXi Corporation +3C6816 (base 16) VXi Corporation + 271 Locust Street + Dover NH 03820 + US + +E8-11-CA (hex) SHANDONG KAER ELECTRIC.CO.,LTD +E811CA (base 16) SHANDONG KAER ELECTRIC.CO.,LTD + No.58, Dalian Road, Weihai, 264209 Shandong Province, P.R.China + Weihai Shandong 264209 + CN + +70-28-8B (hex) Samsung Electronics Co.,Ltd +70288B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +34-8A-7B (hex) Samsung Electronics Co.,Ltd +348A7B (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D0-57-7B (hex) Intel Corporate +D0577B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +78-00-9E (hex) Samsung Electronics Co.,Ltd +78009E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +AC-C3-3A (hex) Samsung Electronics Co.,Ltd +ACC33A (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-F2-01 (hex) Samsung Electronics Co.,Ltd +54F201 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C4-A3-66 (hex) zte corporation +C4A366 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +60-73-BC (hex) zte corporation +6073BC (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +7C-35-48 (hex) Transcend Information +7C3548 (base 16) Transcend Information + No.70, XingZhong Rd., NeiHu Dist., + Taipei Taiwan 114 + TW + +18-B1-69 (hex) Sonicwall +18B169 (base 16) Sonicwall + 2001 Logic Drive + San Jose CA 95124-3452 + US + +44-44-50 (hex) OttoQ +444450 (base 16) OttoQ + 20370 Town Center Lane, Suite 205 + Cupertino CA 95014 + US + +50-F5-DA (hex) Amazon Technologies Inc. +50F5DA (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +10-12-12 (hex) Vivo International Corporation Pty Ltd +101212 (base 16) Vivo International Corporation Pty Ltd + 9-13 Bibby Street, + NSW Chiswick 2046 + AU + +C8-5B-76 (hex) LCFC(HeFei) Electronics Technology co., ltd +C85B76 (base 16) LCFC(HeFei) Electronics Technology co., ltd + YunGu Road 3188-1 + Hefei Anhui 230000 + CN + +78-FF-CA (hex) TECNO MOBILE LIMITED +78FFCA (base 16) TECNO MOBILE LIMITED + ROOMS 05-15, 13A/F., SOUTH TOWER, WORLD FINANCE CENTRE, HARBOUR CITY, 17 CANTON ROAD, TSIM SHA TSUI, KOWLOON, HONG KONG + Hong Kong Hong Kong 999077 + HK + +04-65-65 (hex) Testop +046565 (base 16) Testop + 808, Hanshin IT tower, 272 digital-ro + Guro-gu Seoul KS013 + KR + +A8-BB-50 (hex) WiZ IoT Company Limited +A8BB50 (base 16) WiZ IoT Company Limited + 148 Electric Road + Hong Kong 0000 + HK + +08-C0-21 (hex) HUAWEI TECHNOLOGIES CO.,LTD +08C021 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +60-08-10 (hex) HUAWEI TECHNOLOGIES CO.,LTD +600810 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +48-43-5A (hex) HUAWEI TECHNOLOGIES CO.,LTD +48435A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +8C-8E-F2 (hex) Apple, Inc. +8C8EF2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +90-B0-ED (hex) Apple, Inc. +90B0ED (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-3E-BF (hex) GOGORO TAIWAN LIMITED +F03EBF (base 16) GOGORO TAIWAN LIMITED + No.33 Dinghu Rd. + GuiShan Dist. Taoyuan 333 + TW + +3C-92-DC (hex) Octopod Technology Co. Ltd. +3C92DC (base 16) Octopod Technology Co. Ltd. + 822 Lane Zhennan Road + Shanghai 200331 + CN + +10-00-FD (hex) LaonPeople +1000FD (base 16) LaonPeople + 402-3, Bundang Techno Park B, 148 + Sungnam-si Gyeonggi-do 463-760 + KR + +C4-7C-8D (hex) IEEE Registration Authority +C47C8D (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +74-5C-9F (hex) TCT mobile ltd +745C9F (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +8C-99-E6 (hex) TCT mobile ltd +8C99E6 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +44-9F-7F (hex) DataCore Software Corporation +449F7F (base 16) DataCore Software Corporation + 6300 NW 5th Way + Fort Lauderdale FL 33309 + US + +84-83-19 (hex) Hangzhou Zero Zero Technology Co., Ltd. +848319 (base 16) Hangzhou Zero Zero Technology Co., Ltd. + Bldg 13&14, Dream Town, Hangzhou, Zhejiang + Hangzhou Zhejiang 310000 + CN + +A8-15-59 (hex) Breathometer, Inc. +A81559 (base 16) Breathometer, Inc. + 863 Mitten Road, Suite 104 + Burlingame CA 94010 + US + +70-BA-EF (hex) Hangzhou H3C Technologies Co., Limited +70BAEF (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District, + Hangzhou Zhejiang, P.R.China 310052 + CN + +58-6A-B1 (hex) Hangzhou H3C Technologies Co., Limited +586AB1 (base 16) Hangzhou H3C Technologies Co., Limited + 466 Changhe Road, Binjiang District, + Hangzhou Zhejiang, P.R.China 310052 + CN + +00-90-06 (hex) Hamamatsu Photonics K.K. +009006 (base 16) Hamamatsu Photonics K.K. + 812 JOKO-CHO + HAMAMATSU 431-3196 + JP + +00-1A-F4 (hex) Handreamnet +001AF4 (base 16) Handreamnet + #1209 MarioTower, 28 + Seoul 152-741 + KR + +04-D3-CF (hex) Apple, Inc. +04D3CF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-82-F2 (hex) Appel Elektronik GmbH +4882F2 (base 16) Appel Elektronik GmbH + Ludwig-Rinn-Str.10 + Heuchelheim Hessen 35452 + DE + +78-B8-4B (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +78B84B (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, + Chengdu Sichuan 610000 + CN + +7C-B0-C2 (hex) Intel Corporate +7CB0C2 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-17-93 (hex) Tigi Corporation +001793 (base 16) Tigi Corporation + 2070 Chain Bridge road + Vienna Va 22182 + US + +00-03-58 (hex) Hanyang Digitech Co.Ltd +000358 (base 16) Hanyang Digitech Co.Ltd + 13F, Acetwintower2, 212-30, Guro-Dong + Seoul 12304 + KR + +C4-CA-D9 (hex) Hangzhou H3C Technologies Co., Limited +C4CAD9 (base 16) Hangzhou H3C Technologies Co., Limited + 310 Liuhe Road, Zhijiang Science Park + Hangzhou Zhejiang, 310053 + CN + +58-66-BA (hex) Hangzhou H3C Technologies Co., Limited +5866BA (base 16) Hangzhou H3C Technologies Co., Limited + 310 Liuhe Road, Zhijiang Science Park + Hangzhou Zhejiang, 310053 + CN + +E0-C7-9D (hex) Texas Instruments +E0C79D (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +4C-0B-3A (hex) TCT mobile ltd +4C0B3A (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +E4-2D-02 (hex) TCT mobile ltd +E42D02 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +0C-BD-51 (hex) TCT mobile ltd +0CBD51 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +40-00-E0 (hex) Derek(Shaoguan)Limited +4000E0 (base 16) Derek(Shaoguan)Limited + Gaojiling,Taiping Town, Shixing County + Shaoguan Guangdong 512500 + CN + +FC-BC-9C (hex) Vimar Spa +FCBC9C (base 16) Vimar Spa + Viale Vicenza 14 + Marostica Vicenza 36063 + IT + +14-9E-CF (hex) Dell Inc. +149ECF (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +E8-09-59 (hex) Guoguang Electric Co.,Ltd +E80959 (base 16) Guoguang Electric Co.,Ltd + No.8 Jinghu Road, Xinhua Street, Huadu Reg + Guangzhou Guangdong 510800 + CN + +D8-94-03 (hex) Hewlett Packard Enterprise +D89403 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +E0-0E-DA (hex) Cisco Systems, Inc +E00EDA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +D0-A4-B1 (hex) Sonifex Ltd. +D0A4B1 (base 16) Sonifex Ltd. + 61 Station Road + Irthlingborough Northamptonshire NN9 5QE + GB + +F4-9E-EF (hex) Taicang T&W Electronics +F49EEF (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +C4-F0-81 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C4F081 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +80-13-82 (hex) HUAWEI TECHNOLOGIES CO.,LTD +801382 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-FE-22 (hex) HUAWEI TECHNOLOGIES CO.,LTD +94FE22 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-CC-55 (hex) Juniper Networks +F4CC55 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +50-DD-4F (hex) Automation Components, Inc +50DD4F (base 16) Automation Components, Inc + 2305 Pleasant View Rd + Middleton WI 53562 + US + +34-1F-E4 (hex) ARRIS Group, Inc. +341FE4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-24-F4 (hex) Kaminario, Ltd. +0024F4 (base 16) Kaminario, Ltd. + Yatam Industrial Park + Yokneam ISRAEL 20692 + IL + +00-1A-29 (hex) Johnson Outdoors Marine Electronics d/b/a Minnkota +001A29 (base 16) Johnson Outdoors Marine Electronics d/b/a Minnkota + 1220 Old Alpharetta Rd + Alpharetta GA 30041 + US + +00-90-AE (hex) ITALTEL S.p.A/RF-UP-I +0090AE (base 16) ITALTEL S.p.A/RF-UP-I + LOCALITA' BOSCHETTO + 67100 L'AQUILA na + IT + +00-17-7D (hex) IDT Technology Limited +00177D (base 16) IDT Technology Limited + Block C, 9/F, Kaiser Estate, Phase I + na na + HK + +00-A0-45 (hex) PHOENIX CONTACT Electronics GmbH +00A045 (base 16) PHOENIX CONTACT Electronics GmbH + POSTFACH 1341 + lower saxony D-31812 + DE + +00-23-78 (hex) GN Netcom A/S +002378 (base 16) GN Netcom A/S + Lautrupbjerg 7 + Ballerup DK - 2750 + DK + +50-C9-71 (hex) GN Netcom A/S +50C971 (base 16) GN Netcom A/S + Lautrupbjerg 7 + Ballerup DK - 2750 + DK + +F0-40-7B (hex) Fiberhome Telecommunication Technologies Co.,LTD +F0407B (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +94-88-5E (hex) Surfilter Network Technology Co., Ltd. +94885E (base 16) Surfilter Network Technology Co., Ltd. + 6/f,2 Building,Kejizhong Rd2,Software Park,High-Tech District,Nanshan,Shenzhen,China + Shenzhen Guangdong 518000 + CN + +C8-25-E1 (hex) Lemobile Information Technology (Beijing) Co., Ltd +C825E1 (base 16) Lemobile Information Technology (Beijing) Co., Ltd + WENHUAYING NORTH (No.1, LINKONG 2nd St), GAOLIYING, SHUNYI DISTRICT, BEIJING + Beijing Beijing 101300 + CN + +94-50-89 (hex) SimonsVoss Technologies GmbH +945089 (base 16) SimonsVoss Technologies GmbH + Feringastr. 4 + Unterfoehring Bavaria 85774 + DE + +04-2A-E2 (hex) Cisco Systems, Inc +042AE2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E0-B6-F5 (hex) IEEE Registration Authority +E0B6F5 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-90-FA (hex) Emulex Corporation +0090FA (base 16) Emulex Corporation + 3333 Susan Street + Costa Mesa CA 92626 + US + +00-E0-D5 (hex) Emulex Corporation +00E0D5 (base 16) Emulex Corporation + 3333 Susan Street + Costa Mesa CA 92626 + US + +00-10-35 (hex) Elitegroup Computer Systems Co.,Ltd. +001035 (base 16) Elitegroup Computer Systems Co.,Ltd. + 6F, NO. 88, SEC. 6 + Shih Lin TAIPEI 00000 + TW + +00-0A-E6 (hex) Elitegroup Computer Systems Co.,Ltd. +000AE6 (base 16) Elitegroup Computer Systems Co.,Ltd. + No.22, Alley 38, Lane 91, Sec. 1, Nei Hu + Taipei 114 + TW + +74-27-EA (hex) Elitegroup Computer Systems Co.,Ltd. +7427EA (base 16) Elitegroup Computer Systems Co.,Ltd. + No. 239, Sec. 2, Ti Ding Blvd., + Taipei 11493 + US + +64-99-68 (hex) Elentec +649968 (base 16) Elentec + 401-13 Chunggye-Ri + Dongtan-Myun Kyunggi 445-811 + KR + +00-40-9C (hex) TRANSWARE +00409C (base 16) TRANSWARE + 21, RUE DU 8 MAI 1945 + + FR + +B0-1B-D2 (hex) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited +B01BD2 (base 16) Le Shi Zhi Xin Electronic Technology (Tianjin) Limited + ,Le Shi Building, No.105 Yaojiayuan Road,Chaoyang District,Beijing,China + beijing beijing 100025 + CN + +54-48-9C (hex) CDOUBLES ELECTRONICS CO. LTD. +54489C (base 16) CDOUBLES ELECTRONICS CO. LTD. + 11F.-6, No. 7,Sec. 3, New Taipei Blvd., Xinzhuang Dist. + New Taipei City 24250 + TW + +E4-A1-E6 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +E4A1E6 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +84-00-2D (hex) PEGATRON CORPORATION +84002D (base 16) PEGATRON CORPORATION + No. 76, Ligong St., Beitou, + Taipei 112 + TW + +40-82-56 (hex) Continental Automotive GmbH +408256 (base 16) Continental Automotive GmbH + VD=-Strasse 1 + Babenhausen Garmany 64832 + DE + +5C-C7-D7 (hex) AZROAD TECHNOLOGY COMPANY LIMITED +5CC7D7 (base 16) AZROAD TECHNOLOGY COMPANY LIMITED + Block B2, No.14 Jian'an rd. Shajing, Bao'an District, + Shenzhen 518104 + CN + +98-6B-3D (hex) ARRIS Group, Inc. +986B3D (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E0-07-1B (hex) Hewlett Packard Enterprise +E0071B (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +1C-AB-C0 (hex) Hitron Technologies. Inc +1CABC0 (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +1C-3A-DE (hex) Samsung Electronics Co.,Ltd +1C3ADE (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +00-23-60 (hex) Lookit Technology Co., Ltd +002360 (base 16) Lookit Technology Co., Ltd + FL 8 Seashore Mansion + Shenzhen Guangdong 518100 + CN + +84-FE-DC (hex) Borqs Beijing Ltd. +84FEDC (base 16) Borqs Beijing Ltd. + Tower A, Building B23, Universal Business Park, No.10 Jiuxianqiao Road + Chaoyang District Beijing 100015 + CN + +60-83-34 (hex) HUAWEI TECHNOLOGIES CO.,LTD +608334 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E4-7E-66 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E47E66 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-DB-DA (hex) HUAWEI TECHNOLOGIES CO.,LTD +94DBDA (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +54-D9-E4 (hex) BRILLIANTTS CO., LTD +54D9E4 (base 16) BRILLIANTTS CO., LTD + Daewangpangyo-ro + Seongnam-si 13494 + KR + +F4-62-D0 (hex) Not for Radio, LLC +F462D0 (base 16) Not for Radio, LLC + 425 Front St + Lititz PA 17543 + US + +98-DE-D0 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +98DED0 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +50-89-65 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +508965 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + 3/F, Building R1-B, High-Tech Industrial Park, Nanshan District + Shenzhen Guangdong 518057 + CN + +00-5B-A1 (hex) shanghai huayuan chuangxin software CO., LTD. +005BA1 (base 16) shanghai huayuan chuangxin software CO., LTD. + Room D13 , Floor 13,Lane 1006, Jinshajiang road,putuo District + Shanghai Shanghai 200333 + CN + +58-D6-7A (hex) TCPlink +58D67A (base 16) TCPlink + Daerungpost tower 1-cha 1720, 288 digital-ro,Guro-gu + seoul 08390 + KR + +98-07-2D (hex) Texas Instruments +98072D (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +F0-C7-7F (hex) Texas Instruments +F0C77F (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +00-0A-C2 (hex) Wuhan FiberHome Digital Technology Co.,Ltd. +000AC2 (base 16) Wuhan FiberHome Digital Technology Co.,Ltd. + No.88 YouKeyuan Road,Hongshan District,W + Wuhan Hubei 430074 + CN + +10-DA-43 (hex) NETGEAR +10DA43 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +B8-05-AB (hex) zte corporation +B805AB (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +78-96-82 (hex) zte corporation +789682 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +D4-67-E7 (hex) Fiberhome Telecommunication Technologies Co.,LTD +D467E7 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +E4-2F-26 (hex) Fiberhome Telecommunication Technologies Co.,LTD +E42F26 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +04-C1-B9 (hex) Fiberhome Telecommunication Technologies Co.,LTD +04C1B9 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan City Hubei Province 430074 + CN + +C4-BE-D4 (hex) Avaya Inc +C4BED4 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +D0-17-C2 (hex) ASUSTek COMPUTER INC. +D017C2 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +34-99-71 (hex) Quanta Storage Inc. +349971 (base 16) Quanta Storage Inc. + 3F. No.188, Wenhua 2nd Rd + Taoyuan City Guishan District 33383 + TW + +9C-52-F8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +9C52F8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +EC-13-DB (hex) Juniper Networks +EC13DB (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +5C-F2-86 (hex) IEEE Registration Authority +5CF286 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +E8-FD-72 (hex) SHANGHAI LINGUO TECHNOLOGY CO., LTD. +E8FD72 (base 16) SHANGHAI LINGUO TECHNOLOGY CO., LTD. + No.2,277 Lane,Yongdeng Road,Putuo District,Shanghai,China + Shanghai Shanghai 200000 + CN + +98-BB-1E (hex) BYD Precision Manufacture Company Ltd. +98BB1E (base 16) BYD Precision Manufacture Company Ltd. + 7/Floor, Building 5#, No3000 LongDong Avenue, Pudong District + Shanghai Shanghai 201203 + CN + +AC-5F-3E (hex) SAMSUNG ELECTRO-MECHANICS(THAILAND) +AC5F3E (base 16) SAMSUNG ELECTRO-MECHANICS(THAILAND) + 93Moo5T. Bangsamak SEMTHAI, WELLGROW INDUSTRIAL ESTATE + Bangpakong Chachoengsao 24180 + TH + +54-6D-52 (hex) TOPVIEW OPTRONICS CORP. +546D52 (base 16) TOPVIEW OPTRONICS CORP. + No.8, Wuquan Rd., New Taipei Industrial Park, Wugu District + New Taipei City 24886 + TW + +04-C1-03 (hex) Clover Network, Inc. +04C103 (base 16) Clover Network, Inc. + 415 N Mathilda Ave + Sunnyvale CA 94085 + US + +28-0C-28 (hex) Unigen DataStorage Corporation +280C28 (base 16) Unigen DataStorage Corporation + 11F.-6, No.251, Fuxing 1st St., Zhubei City, Hsinchu County 302, Taiwan (R.O.C.) + Zhubei City 30271 + TW + +A4-BF-01 (hex) Intel Corporate +A4BF01 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +20-8B-37 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +208B37 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +08-BE-77 (hex) Green Electronics +08BE77 (base 16) Green Electronics + 47801 Fremont Blvd + Fremont CA 94538 + US + +50-9E-A7 (hex) Samsung Electronics Co.,Ltd +509EA7 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A8-81-95 (hex) Samsung Electronics Co.,Ltd +A88195 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +88-AD-D2 (hex) Samsung Electronics Co.,Ltd +88ADD2 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-CC-FC (hex) Cisco Systems, Inc +00CCFC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-C5 (hex) Sony Interactive Entertainment Inc. +0019C5 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +00-13-15 (hex) Sony Interactive Entertainment Inc. +001315 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +1C-23-4F (hex) EDMI Europe Ltd +1C234F (base 16) EDMI Europe Ltd + The Grainger Suite, Dobson House + Newcastle upon Tyne NE3 3PF + GB + +A4-44-D1 (hex) Wingtech Group (HongKong)Limited +A444D1 (base 16) Wingtech Group (HongKong)Limited + FLAT/RM 1903 19/F PODIUM PLAZA 5HANOI ROAD TSIM SHA TSUI + Hong Kong Hong Kong 999077 + HK + +00-6C-FD (hex) Sichuan Changhong Electric Ltd. +006CFD (base 16) Sichuan Changhong Electric Ltd. + No.35,East MianXin Road,MianYang,Sichaun,China. + MianYang SiChuan PRC 621000 + CN + +54-5A-A6 (hex) Espressif Inc. +545AA6 (base 16) Espressif Inc. + Room 204, Building 2, 690 Bibo Rd, Pudong New Area + Shanghai Shanghai 201203 + CN + +FC-1A-11 (hex) vivo Mobile Communication Co., Ltd. +FC1A11 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +00-1A-57 (hex) Matrix Design Group, LLC +001A57 (base 16) Matrix Design Group, LLC + 5741 Prospect Dr. + Newburgh IN 47630 + US + +A0-C5-89 (hex) Intel Corporate +A0C589 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-1E-1E (hex) Honeywell Life Safety +001E1E (base 16) Honeywell Life Safety + 12 Clintonville Road + Northford CT 0422 + US + +00-23-40 (hex) MiXTelematics +002340 (base 16) MiXTelematics + Blaauwklip Office Park 2 + Stellenbosch Western Cape 7600 + ZA + +B4-8B-19 (hex) Apple, Inc. +B48B19 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +38-FD-FE (hex) IEEE Registration Authority +38FDFE (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +2C-09-CB (hex) COBS AB +2C09CB (base 16) COBS AB + Box 9242 + Goteborg 40095 + SE + +BC-EC-5D (hex) Apple, Inc. +BCEC5D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-A0-2B (hex) Apple, Inc. +28A02B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-44-81 (hex) Nokia Corporation +A84481 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo NA 24101 + FI + +88-44-F6 (hex) Nokia Corporation +8844F6 (base 16) Nokia Corporation + Joensuunkatu 7 + Salo NA 24101 + FI + +F4-4D-17 (hex) GOLDCARD HIGH-TECH CO.,LTD. +F44D17 (base 16) GOLDCARD HIGH-TECH CO.,LTD. + No.158, Jinqiao Stree,Economic&Technological Development Area, + Hangzhou Zhejiang 310018 + CN + +38-B8-EB (hex) IEEE Registration Authority +38B8EB (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +98-97-D1 (hex) MitraStar Technology Corp. +9897D1 (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +B8-32-41 (hex) Wuhan Tianyu Information Industry Co., Ltd. +B83241 (base 16) Wuhan Tianyu Information Industry Co., Ltd. + HUST Industry Park, East-Lake Development Zone + Wuhan Hubei 430223 + CN + +00-60-DC (hex) NEC Magnus Communications,Ltd. +0060DC (base 16) NEC Magnus Communications,Ltd. + 18 Nihon-odori,Naka-ku + Yokohama, Kanagawa 231-0021 + JP + +90-72-82 (hex) Sagemcom Broadband SAS +907282 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +00-1C-35 (hex) Nokia Danmark A/S +001C35 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1C-9A (hex) Nokia Danmark A/S +001C9A (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1C-D6 (hex) Nokia Danmark A/S +001CD6 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1C-D4 (hex) Nokia Danmark A/S +001CD4 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1D-98 (hex) Nokia Danmark A/S +001D98 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1D-E9 (hex) Nokia Danmark A/S +001DE9 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1E-3A (hex) Nokia Danmark A/S +001E3A (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-25-48 (hex) Nokia Danmark A/S +002548 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-22-FC (hex) Nokia Danmark A/S +0022FC (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-22-FD (hex) Nokia Danmark A/S +0022FD (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-21-AA (hex) Nokia Danmark A/S +0021AA (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1D-6E (hex) Nokia Danmark A/S +001D6E (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-1C-FC (hex) Sumitomo Electric Industries,Ltd +001CFC (base 16) Sumitomo Electric Industries,Ltd + 1-1-3, Shimaya, Konohana-ku + Osaka 554-0024 + JP + +00-23-B4 (hex) Nokia Danmark A/S +0023B4 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-13-70 (hex) Nokia Danmark A/S +001370 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +9C-18-74 (hex) Nokia Danmark A/S +9C1874 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790V + DK + +00-1B-AF (hex) Nokia Danmark A/S +001BAF (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +C8-D1-0B (hex) Nokia Corporation +C8D10B (base 16) Nokia Corporation + Joensuunkatu 7 + Salo 24101 + FI + +5C-C6-D0 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +5CC6D0 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +00-1A-9A (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +001A9A (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +CC-6D-A0 (hex) Roku, Inc. +CC6DA0 (base 16) Roku, Inc. + 12980 Saratoga Ave. + Saratoga CA 95070 + US + +00-16-E4 (hex) VANGUARD SECURITY ENGINEERING CORP. +0016E4 (base 16) VANGUARD SECURITY ENGINEERING CORP. + 3, LANE 32, KSO CHING RD. + YANGMEI TAOYUAN 326 + US + +3C-89-70 (hex) Neosfar +3C8970 (base 16) Neosfar + 101 W. Broadway, Suite 300 + San Diego CA 92101 + US + +00-17-42 (hex) FUJITSU LIMITED +001742 (base 16) FUJITSU LIMITED + 403, Kosugi-cho 1-chome, Nakahara-ku + Kawasaki Kanagawa 211-0063 + JP + +00-19-99 (hex) Fujitsu Technology Solutions GmbH +001999 (base 16) Fujitsu Technology Solutions GmbH + Buergermeister-Ulrich-Strasse 100 + Augsburg 86199 + DE + +00-5A-39 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +005A39 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District + Shenzhen Guangdong 518057 + CN + +A0-89-E4 (hex) Skyworth Digital Technology(Shenzhen) Co.,Ltd +A089E4 (base 16) Skyworth Digital Technology(Shenzhen) Co.,Ltd + 7F,Block A,Skyworth Building, + Shenzhen Guangdong 518057 + CN + +78-CA-83 (hex) IEEE Registration Authority +78CA83 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +0C-11-67 (hex) Cisco Systems, Inc +0C1167 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +74-EA-E8 (hex) ARRIS Group, Inc. +74EAE8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +F8-8E-85 (hex) Comtrend Corporation +F88E85 (base 16) Comtrend Corporation + 3F-1, 10 Lane 609, Chongxin Road, Section 5, + New Taipei City, Taiwan 24159 + TW + +02-CF-1C (hex) Communication Machinery Corporation +02CF1C (base 16) Communication Machinery Corporation + 1226 ANACAPA + SANTA BARBARA CA 93101 + US + +00-90-F5 (hex) CLEVO CO. +0090F5 (base 16) CLEVO CO. + 35, WU-GON 6TH ROAD + TAIPEI HSIEN 12345 + TW + +00-30-FF (hex) DataFab Systems Inc. +0030FF (base 16) DataFab Systems Inc. + ROOM #1910, 19F, NO. 333 + TAIWAN TAIWAN R.O.C. + TW + +00-0F-F6 (hex) DARFON LIGHTING CORP +000FF6 (base 16) DARFON LIGHTING CORP + 31, Lane17, Zihciang N. Road + Taoyuan 333 + TW + +00-21-00 (hex) Gemtek Technology Co., Ltd. +002100 (base 16) Gemtek Technology Co., Ltd. + No.1 Jen Ai Road, Hsinchu Industrial Park, + Hukou, Hsinchu 303 + TW + +50-F5-20 (hex) Samsung Electronics Co.,Ltd +50F520 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +64-B3-10 (hex) Samsung Electronics Co.,Ltd +64B310 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A4-EB-D3 (hex) Samsung Electronics Co.,Ltd +A4EBD3 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C8-10-73 (hex) CENTURY OPTICOMM CO.,LTD +C81073 (base 16) CENTURY OPTICOMM CO.,LTD + WEITUO COMMUNITY,HECHUAN INDUSTRIAL PARK, HECHUAN DISTRICT,CHONGQING,CHINA + Chongqing 401121 + CN + +34-37-59 (hex) zte corporation +343759 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +FC-2F-40 (hex) Calxeda, Inc. +FC2F40 (base 16) Calxeda, Inc. + 7000 North Mopac Expressway + Austin TX 78731 + US + +BC-62-0E (hex) HUAWEI TECHNOLOGIES CO.,LTD +BC620E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +74-A5-28 (hex) HUAWEI TECHNOLOGIES CO.,LTD +74A528 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +5C-F6-DC (hex) Samsung Electronics Co.,Ltd +5CF6DC (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +00-26-E4 (hex) Canal + +0026E4 (base 16) Canal + + 48 quai du point du jour + Boulogne-Billancourt 92659 + FR + +00-01-17 (hex) Canal + +000117 (base 16) Canal + + 23 Rue LeBlanc + 75906 Paris Cedex 15 12345 + FR + +E0-1D-3B (hex) Cambridge Industries(Group) Co.,Ltd. +E01D3B (base 16) Cambridge Industries(Group) Co.,Ltd. + 22 Floor, Qilai Tower, #889 Yishan Road + Shanghai Shanghai 200233 + CN + +70-C7-6F (hex) INNO S +70C76F (base 16) INNO S + 215beon-gil, 119 + Guri-si Gyeonggi-do 471-060 + KR + +38-19-2F (hex) Nokia Corporation +38192F (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +B8-C6-8E (hex) Samsung Electronics Co.,Ltd +B8C68E (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +04-FE-31 (hex) Samsung Electronics Co.,Ltd +04FE31 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +4C-BC-A5 (hex) Samsung Electronics Co.,Ltd +4CBCA5 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +D8-31-CF (hex) Samsung Electronics Co.,Ltd +D831CF (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +18-83-31 (hex) Samsung Electronics Co.,Ltd +188331 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +9C-65-B0 (hex) Samsung Electronics Co.,Ltd +9C65B0 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +84-55-A5 (hex) Samsung Electronics Co.,Ltd +8455A5 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A8-7C-01 (hex) Samsung Electronics Co.,Ltd +A87C01 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-D0-9C (hex) Samsung Electronics Co.,Ltd +B0D09C (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +50-C8-E5 (hex) Samsung Electronics Co.,Ltd +50C8E5 (base 16) Samsung Electronics Co.,Ltd + #94-1,Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +00-20-D4 (hex) Cabletron Systems, Inc. +0020D4 (base 16) Cabletron Systems, Inc. + 35 INDUSTRIAL WAY + ROHESTER NH 03866-5005 + US + +00-E0-3A (hex) Cabletron Systems, Inc. +00E03A (base 16) Cabletron Systems, Inc. + 35 INDUSTRIAL WAY - BLDG. #36 + ROCHESTER NH 03867 + US + +00-10-E7 (hex) Breezecom, Ltd. +0010E7 (base 16) Breezecom, Ltd. + PO Box 13139 + Tel-Aviv 12345 + IL + +94-92-BC (hex) SYNTECH(HK) TECHNOLOGY LIMITED +9492BC (base 16) SYNTECH(HK) TECHNOLOGY LIMITED + Unit No.1,12/F.,Perfect Industrial Building,31 Tai Yau Street, San Po Kong, Kowloon, Hong Kong 999077 + Kowloon 999077 + HK + +00-1D-19 (hex) Arcadyan Technology Corporation +001D19 (base 16) Arcadyan Technology Corporation + 4F., No. 9 , Park Avenue II, + Hsinchu 300 + TW + +00-12-BF (hex) Arcadyan Technology Corporation +0012BF (base 16) Arcadyan Technology Corporation + 4F, No. 9, Park Avenue II + Hsinchu 300 + TW + +50-7E-5D (hex) Arcadyan Technology Corporation +507E5D (base 16) Arcadyan Technology Corporation + 4F, No. 9, Park Avenue II , + Hsinchu 300 + TW + +7C-4F-B5 (hex) Arcadyan Technology Corporation +7C4FB5 (base 16) Arcadyan Technology Corporation + 4F, No. 9, Park Avenue II , + Hsinchu 300 + TW + +00-22-3F (hex) NETGEAR +00223F (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-0F-B5 (hex) NETGEAR +000FB5 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-09-5B (hex) NETGEAR +00095B (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-1A-4F (hex) AVM GmbH +001A4F (base 16) AVM GmbH + Alt-Moabit 95 + Berlin 10559 + DE + +00-1C-4A (hex) AVM GmbH +001C4A (base 16) AVM GmbH + Alt-Moabit 95 + Berlin 10559 + DE + +00-15-0C (hex) AVM GmbH +00150C (base 16) AVM GmbH + Alt-Moabit 95 + Berlin 10559 + DE + +00-26-FF (hex) BlackBerry RTS +0026FF (base 16) BlackBerry RTS + 440 Phillip Street + Waterloo Ontario N2L 5W9 + CA + +A4-E4-B8 (hex) BlackBerry RTS +A4E4B8 (base 16) BlackBerry RTS + 295 Phillip Street + Waterloo Ontario N2L 3W8 + CA + +00-30-67 (hex) BIOSTAR Microtech Int'l Corp. +003067 (base 16) BIOSTAR Microtech Int'l Corp. + 2FL. NO. 108-2 MIN CHUAN ROAD + HSIN TIEN CITY, TAIPEI HSIEN 12345 + TW + +F4-0B-93 (hex) BlackBerry RTS +F40B93 (base 16) BlackBerry RTS + 451 Phillip Street + Waterloo ON N2L 3X2 + CA + +1C-69-A5 (hex) BlackBerry RTS +1C69A5 (base 16) BlackBerry RTS + 451 Phillip Street + Waterloo ON N2L 3X2 + CA + +94-EB-CD (hex) BlackBerry RTS +94EBCD (base 16) BlackBerry RTS + 295 Phillip Street + Waterloo Ontario N2L3W8 + CA + +28-C6-8E (hex) NETGEAR +28C68E (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +04-A1-51 (hex) NETGEAR +04A151 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +F8-73-94 (hex) NETGEAR +F87394 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +20-4E-7F (hex) NETGEAR +204E7F (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +C0-3F-0E (hex) NETGEAR +C03F0E (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-26-F2 (hex) NETGEAR +0026F2 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +00-13-8F (hex) Asiarock Technology Limited +00138F (base 16) Asiarock Technology Limited + P.O. Box957, Offshore Incorporations Centre + Road Town Tortola 12345 + VG + +80-37-73 (hex) NETGEAR +803773 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +A4-2B-8C (hex) NETGEAR +A42B8C (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +CC-7D-37 (hex) ARRIS Group, Inc. +CC7D37 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +A4-7A-A4 (hex) ARRIS Group, Inc. +A47AA4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-17-00 (hex) ARRIS Group, Inc. +001700 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-16-B5 (hex) ARRIS Group, Inc. +0016B5 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-15-A8 (hex) ARRIS Group, Inc. +0015A8 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-15-9A (hex) ARRIS Group, Inc. +00159A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-11-80 (hex) ARRIS Group, Inc. +001180 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-0B-06 (hex) ARRIS Group, Inc. +000B06 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-D0-88 (hex) ARRIS Group, Inc. +00D088 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-12-8A (hex) ARRIS Group, Inc. +00128A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-23-75 (hex) ARRIS Group, Inc. +002375 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-23-A3 (hex) ARRIS Group, Inc. +0023A3 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1A-DB (hex) ARRIS Group, Inc. +001ADB (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1F-7E (hex) ARRIS Group, Inc. +001F7E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-11-AE (hex) ARRIS Group, Inc. +0011AE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +94-CC-B9 (hex) ARRIS Group, Inc. +94CCB9 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +3C-43-8E (hex) ARRIS Group, Inc. +3C438E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-24-C1 (hex) ARRIS Group, Inc. +0024C1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-25-F2 (hex) ARRIS Group, Inc. +0025F2 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-25-F1 (hex) ARRIS Group, Inc. +0025F1 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-14-04 (hex) ARRIS Group, Inc. +001404 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1A-AD (hex) ARRIS Group, Inc. +001AAD (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-26-BA (hex) ARRIS Group, Inc. +0026BA (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-23-0B (hex) ARRIS Group, Inc. +00230B (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +74-E7-C6 (hex) ARRIS Group, Inc. +74E7C6 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1C-12 (hex) ARRIS Group, Inc. +001C12 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +5C-33-8E (hex) Alpha Networks Inc. +5C338E (base 16) Alpha Networks Inc. + No.8 Li-shing Seventh Road,Science-based + Hsinchu 300 + TW + +00-09-41 (hex) Allied Telesis R&D Center K.K. +000941 (base 16) Allied Telesis R&D Center K.K. + Technical Center/No.2 TOC Bldg. + Shinagawa-ku 141-0031 + US + +28-E3-47 (hex) Liteon Technology Corporation +28E347 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +44-6D-57 (hex) Liteon Technology Corporation +446D57 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +9C-B7-0D (hex) Liteon Technology Corporation +9CB70D (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +68-A3-C4 (hex) Liteon Technology Corporation +68A3C4 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +70-F1-A1 (hex) Liteon Technology Corporation +70F1A1 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo,Taipei Hsien,Taiwan, + TaiPei TaiWan 23585 + TW + +84-00-D2 (hex) Sony Mobile Communications Inc +8400D2 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +30-39-26 (hex) Sony Mobile Communications Inc +303926 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-EB-2D (hex) Sony Mobile Communications Inc +00EB2D (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +B4-52-7D (hex) Sony Mobile Communications Inc +B4527D (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-D9-D1 (hex) Sony Interactive Entertainment Inc. +00D9D1 (base 16) Sony Interactive Entertainment Inc. + 1-7-1 Konan + Minato-ku Tokyo 108-0075 + JP + +B0-05-94 (hex) Liteon Technology Corporation +B00594 (base 16) Liteon Technology Corporation + 4F,90,Chien 1 Road,ChungHo + New Taipei City Taipei 23585 + TW + +EC-08-6B (hex) TP-LINK TECHNOLOGIES CO.,LTD. +EC086B (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +94-A1-A2 (hex) AMPAK Technology, Inc. +94A1A2 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road + Hukou Hsinchu 30352 + TW + +00-01-4A (hex) Sony Corporation +00014A (base 16) Sony Corporation + Gotenyama Tec, 5-1-2 Kitashinagawa + Tokyo 141-0001 + JP + +00-1E-DC (hex) Sony Mobile Communications Inc +001EDC (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-1D-28 (hex) Sony Mobile Communications Inc +001D28 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +00-18-13 (hex) Sony Mobile Communications Inc +001813 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +40-2B-A1 (hex) Sony Mobile Communications Inc +402BA1 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +98-3B-16 (hex) AMPAK Technology, Inc. +983B16 (base 16) AMPAK Technology, Inc. + No.1,Jen Ai Road + Hsinchu 30352 + TW + +40-95-58 (hex) Aisino Corporation +409558 (base 16) Aisino Corporation + No.18A, Xingshikou Road, + Beijing 100195 + CN + +18-28-61 (hex) AirTies Wireless Networks +182861 (base 16) AirTies Wireless Networks + Gulbahar Mahallesi, Avni Diligil Sokak + ISTANBUL ISTANBUL 34394 + TR + +6C-71-D9 (hex) AzureWave Technology Inc. +6C71D9 (base 16) AzureWave Technology Inc. + 9F.,No.92,Baozhong Rd + Xindian District New Taipei City 231 + TW + +D0-E7-82 (hex) AzureWave Technology Inc. +D0E782 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd + . New Taipei City Taiwan 231 + TW + +6C-AD-F8 (hex) AzureWave Technology Inc. +6CADF8 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd + . New Taipei City Taiwan 231 + TW + +A8-1D-16 (hex) AzureWave Technology Inc. +A81D16 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +34-C3-D2 (hex) FN-LINK TECHNOLOGY LIMITED +34C3D2 (base 16) FN-LINK TECHNOLOGY LIMITED + A Building,HuiXin industial park,No 31, YongHe road, Fuyong town, Bao'an District + SHENZHEN GUANGDONG 518100 + CN + +54-F6-C5 (hex) FUJIAN STAR-NET COMMUNICATION CO.,LTD +54F6C5 (base 16) FUJIAN STAR-NET COMMUNICATION CO.,LTD + 19-22# Building, Star-net Science Plaza, Juyuanzhou, + FUZHOU FUJIAN 350002 + CN + +D0-D4-12 (hex) ADB Broadband Italia +D0D412 (base 16) ADB Broadband Italia + VIALE SARCA 336 + MILANO 20126 + IT + +00-26-B8 (hex) Actiontec Electronics, Inc +0026B8 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +00-26-FC (hex) AcSiP Technology Corp. +0026FC (base 16) AcSiP Technology Corp. + 3F., No.22, Dalin Rd., + Taoyuan City, Taoyuan County 330 + TW + +00-15-AF (hex) AzureWave Technology Inc. +0015AF (base 16) AzureWave Technology Inc. + 8F., No.94, Baozhong Rd., Xindian + Taipei 231 + TW + +74-F0-6D (hex) AzureWave Technology Inc. +74F06D (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd., Xindian + Taipei 231 + TW + +44-D8-32 (hex) AzureWave Technology Inc. +44D832 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd., Xindian + Taipei 231 + TW + +E0-B9-A5 (hex) AzureWave Technology Inc. +E0B9A5 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baoshong Rd. + Xindian City, Taipei County 231 + TW + +78-18-81 (hex) AzureWave Technology Inc. +781881 (base 16) AzureWave Technology Inc. + 8F., No.94 Baozhong Rd., + Xindian, Taipei 23144 + TW + +B0-46-FC (hex) MitraStar Technology Corp. +B046FC (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu 300 + TW + +E0-41-36 (hex) MitraStar Technology Corp. +E04136 (base 16) MitraStar Technology Corp. + No. 6, Innovation Road II, + Hsinchu Taiwan 300 + TW + +00-1C-A2 (hex) ADB Broadband Italia +001CA2 (base 16) ADB Broadband Italia + VIALE SARCA 222 + MILANO 20126 + IT + +00-22-33 (hex) ADB Broadband Italia +002233 (base 16) ADB Broadband Italia + VIALE SARCA 222 + MILANO 20126 + IT + +30-39-F2 (hex) ADB Broadband Italia +3039F2 (base 16) ADB Broadband Italia + VIALE SARCA 222 + MILANO 20126 + IT + +00-17-C2 (hex) ADB Broadband Italia +0017C2 (base 16) ADB Broadband Italia + v.Sarca 222 + Milano 20126 + IT + +68-9C-5E (hex) AcSiP Technology Corp. +689C5E (base 16) AcSiP Technology Corp. + 3F., No.22, Dalin Rd. + Taoyuan Taoyuan County 33067 + TW + +9C-0E-4A (hex) Shenzhen Vastking Electronic Co.,Ltd. +9C0E4A (base 16) Shenzhen Vastking Electronic Co.,Ltd. + 2/F Building 6,ZhengZhong Industrial Park,Qiaotou Community,Fuyong,Baoan,ShenZhen China + Shenzhen Guangdong 518103 + CN + +A8-58-40 (hex) Cambridge Industries(Group) Co.,Ltd. +A85840 (base 16) Cambridge Industries(Group) Co.,Ltd. + 5/F,Building 8, 2388 ChenHang Road, MinHang District + shanghai 201114 + CN + +A0-D3-7A (hex) Intel Corporate +A0D37A (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +88-96-F2 (hex) Valeo Schalter und Sensoren GmbH +8896F2 (base 16) Valeo Schalter und Sensoren GmbH + Laiernstrasse 12 + Bietigheim-Bissingen Germany 74321 + DE + +00-10-73 (hex) TECHNOBOX, INC. +001073 (base 16) TECHNOBOX, INC. + 140 Mount Holly Bypass + Lumberton NJ 08048-1114 + US + +20-93-4D (hex) FUJIAN STAR-NET COMMUNICATION CO.,LTD +20934D (base 16) FUJIAN STAR-NET COMMUNICATION CO.,LTD + 19-22# Building,,Star-net Science Plaza + Fuzhou Fujian 350002 + CN + +00-90-27 (hex) Intel Corporation +009027 (base 16) Intel Corporation + HF1-06 + HILLSBORO OR 97124 + US + +C4-85-08 (hex) Intel Corporate +C48508 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +68-05-CA (hex) Intel Corporate +6805CA (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +24-77-03 (hex) Intel Corporate +247703 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +74-E5-0B (hex) Intel Corporate +74E50B (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B8-03-05 (hex) Intel Corporate +B80305 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-A0-C9 (hex) Intel Corporation +00A0C9 (base 16) Intel Corporation + 5200 NE ELAM YOUNG PARKWAY + HILLSBORO OR 97124 + US + +14-18-77 (hex) Dell Inc. +141877 (base 16) Dell Inc. + One Dell way + Round Rock 78682 + US + +E0-97-96 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E09796 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen Guangdong 518129 + CN + +1C-40-24 (hex) Dell Inc. +1C4024 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +18-FB-7B (hex) Dell Inc. +18FB7B (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +F8-B1-56 (hex) Dell Inc. +F8B156 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +14-1A-A3 (hex) Motorola Mobility LLC, a Lenovo Company +141AA3 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 Merchandise Mart Plaza, Suite 1800 + Chicago IL 60654 + US + +34-07-FB (hex) Ericsson AB +3407FB (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +A4-A1-C2 (hex) Ericsson AB +A4A1C2 (base 16) Ericsson AB + Torshamnsgatan 36 + Stockholm SE-164 80 + SE + +00-06-5B (hex) Dell Inc. +00065B (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +84-2B-2B (hex) Dell Inc. +842B2B (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +F0-4D-A2 (hex) Dell Inc. +F04DA2 (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +E0-DB-55 (hex) Dell Inc. +E0DB55 (base 16) Dell Inc. + One Dell way + Round Rock 78682 + US + +00-0F-1F (hex) Dell Inc. +000F1F (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +24-B6-FD (hex) Dell Inc. +24B6FD (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +74-E6-E2 (hex) Dell Inc. +74E6E2 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +34-E6-D7 (hex) Dell Inc. +34E6D7 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +00-1E-C9 (hex) Dell Inc. +001EC9 (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +00-21-70 (hex) Dell Inc. +002170 (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +00-21-9B (hex) Dell Inc. +00219B (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +B8-AC-6F (hex) Dell Inc. +B8AC6F (base 16) Dell Inc. + One Dell Way, MS RR5-45 + Round Rock 78682 + US + +8C-A9-82 (hex) Intel Corporate +8CA982 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +BC-77-37 (hex) Intel Corporate +BC7737 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +14-30-C6 (hex) Motorola Mobility LLC, a Lenovo Company +1430C6 (base 16) Motorola Mobility LLC, a Lenovo Company + 600 North US Highway 45 + Libertyville IL 60048 + US + +D8-FC-93 (hex) Intel Corporate +D8FC93 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +D4-AE-52 (hex) Dell Inc. +D4AE52 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +28-16-2E (hex) 2Wire Inc +28162E (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose 95131 + US + +F8-18-97 (hex) 2Wire Inc +F81897 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose 95131 + US + +94-C1-50 (hex) 2Wire Inc +94C150 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +5C-F8-21 (hex) Texas Instruments +5CF821 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +88-07-4B (hex) LG Electronics (Mobile Communications) +88074B (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +00-0D-72 (hex) 2Wire Inc +000D72 (base 16) 2Wire Inc + 1704 Automation Parkway + San Jose CA 95131 + US + +00-12-88 (hex) 2Wire Inc +001288 (base 16) 2Wire Inc + 1704 Automation Parkway + San Jose CA 94538 + US + +00-78-9E (hex) Sagemcom Broadband SAS +00789E (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison Cedex Hauts de Seine 92848 + FR + +E8-BE-81 (hex) Sagemcom Broadband SAS +E8BE81 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + Rueil Malmaison Cedex Hauts de Seine 92848 + FR + +68-15-90 (hex) Sagemcom Broadband SAS +681590 (base 16) Sagemcom Broadband SAS + 250 ROUTE DE L'EMPEREUR + RUEIL MALMAISON CEDEX Choisissez l'état / la province 92848 + FR + +F4-EB-38 (hex) Sagemcom Broadband SAS +F4EB38 (base 16) Sagemcom Broadband SAS + 15 Avenue Ambroise Croizat + DOMERAT Allier 03410 + FR + +00-1B-BF (hex) Sagemcom Broadband SAS +001BBF (base 16) Sagemcom Broadband SAS + 14 Rue Paul Dautier + Vélizy 78457 + FR + +00-25-69 (hex) Sagemcom Broadband SAS +002569 (base 16) Sagemcom Broadband SAS + Le Ponnant de Paris + CEDEX Paris 75512 + FR + +14-1F-BA (hex) IEEE Registration Authority +141FBA (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +80-7B-85 (hex) IEEE Registration Authority +807B85 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +CC-1B-E0 (hex) IEEE Registration Authority +CC1BE0 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +F4-0E-11 (hex) IEEE Registration Authority +F40E11 (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +10-F6-81 (hex) vivo Mobile Communication Co., Ltd. +10F681 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +00-21-7C (hex) 2Wire Inc +00217C (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +00-1F-B3 (hex) 2Wire Inc +001FB3 (base 16) 2Wire Inc + 1764 Automation Parkway + San Jose CA 95131 + US + +00-22-75 (hex) Belkin International Inc. +002275 (base 16) Belkin International Inc. + 12045 E. Waterfront Drive + Playa Vista CA 90094 + US + +00-57-D2 (hex) Cisco Systems, Inc +0057D2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +3C-67-16 (hex) Lily Robotics +3C6716 (base 16) Lily Robotics + 75 Boardman Pl + San Francisco CA 94103 + US + +00-D0-BD (hex) Lattice Semiconductor Corp. (LPA) +00D0BD (base 16) Lattice Semiconductor Corp. (LPA) + 2115 O’Nel Drive + San Jose CA 95131 + US + +00-1F-3A (hex) Hon Hai Precision Ind. Co.,Ltd. +001F3A (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +C8-A0-30 (hex) Texas Instruments +C8A030 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +78-C5-E5 (hex) Texas Instruments +78C5E5 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +0C-FD-37 (hex) SUSE Linux GmbH +0CFD37 (base 16) SUSE Linux GmbH + Maxfeldstraße 5 + Nürnberg Bavaria 90409 + DE + +2C-22-8B (hex) CTR SRL +2C228B (base 16) CTR SRL + Via Lario 33 + Cantù Cantù (CO) 22063 + IT + +0C-6F-9C (hex) Shaw Communications Inc. +0C6F9C (base 16) Shaw Communications Inc. + Suite 900, 630 3rd Avenue S.W. + CALGARY ALBERTA T2P 4L4 + CA + +00-17-E4 (hex) Texas Instruments +0017E4 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +04-E4-51 (hex) Texas Instruments +04E451 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +50-56-63 (hex) Texas Instruments +505663 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +88-33-14 (hex) Texas Instruments +883314 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +64-7B-D4 (hex) Texas Instruments +647BD4 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +D8-95-2F (hex) Texas Instruments +D8952F (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +B8-FF-FE (hex) Texas Instruments +B8FFFE (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +2C-E4-12 (hex) Sagemcom Broadband SAS +2CE412 (base 16) Sagemcom Broadband SAS + 250 route de l'Empereur + RUEIL MALMAISON CEDEX Hauts de Seine 92848 + FR + +44-C1-5C (hex) Texas Instruments +44C15C (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +00-22-A5 (hex) Texas Instruments +0022A5 (base 16) Texas Instruments + 12500 TI Boulevard, MS 8723 + Dallas TX 75243 + US + +E0-43-DB (hex) Shenzhen ViewAt Technology Co.,Ltd. +E043DB (base 16) Shenzhen ViewAt Technology Co.,Ltd. + 9A,Microprofit,6th Gaoxin South Road, High-Tech Industrial Park, Nanshan, Shenzhen, CHINA. + shenzhen guangdong 518057 + CN + +3C-CF-5B (hex) ICOMM HK LIMITED +3CCF5B (base 16) ICOMM HK LIMITED + SUITES 2302-6, 23/F GREAT EAGLE CTR 23 HARBOUR RD + WANCHAI NA + HK + +24-05-F5 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +2405F5 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +3C-35-56 (hex) Cognitec Systems GmbH +3C3556 (base 16) Cognitec Systems GmbH + Großenhainer Str. 101 + Dresden Saxony 01127 + DE + +3C-90-66 (hex) SmartRG, Inc. +3C9066 (base 16) SmartRG, Inc. + 501 SE Columbia Shores Blvd + Vancouver WA 98661 + US + +00-0D-88 (hex) D-Link Corporation +000D88 (base 16) D-Link Corporation + No.8, Li-Hsing 7 Road, Science-Based Ind + Hsinchu 30077 + TW + +00-11-95 (hex) D-Link Corporation +001195 (base 16) D-Link Corporation + 2F No. 233-2, Pao-Chiao Road + Taipei Taiwan 0000 + TW + +00-13-46 (hex) D-Link Corporation +001346 (base 16) D-Link Corporation + 2F, No.233-2, Pao-Chiao Road + Hsin-Tien, Taipei 231 + TW + +78-E3-B5 (hex) Hewlett Packard +78E3B5 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +78-AC-C0 (hex) Hewlett Packard +78ACC0 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +68-B5-99 (hex) Hewlett Packard +68B599 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +1C-C1-DE (hex) Hewlett Packard +1CC1DE (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +B8-A3-86 (hex) D-Link International +B8A386 (base 16) D-Link International + 1 International Business Park, #03-12, The Synergy + SINGAPORE 609917 + SG + +1C-7E-E5 (hex) D-Link International +1C7EE5 (base 16) D-Link International + 1 International Business Park, #03-12, The Synergy + SINGAPORE 609917 + SG + +1C-BD-B9 (hex) D-Link International +1CBDB9 (base 16) D-Link International + 1 INTERNATIONAL BUSINESS PARK, + SINGAPORE 609917 + SG + +00-14-2F (hex) Savvius +00142F (base 16) Savvius + 1340 Treat Boulevard, Suite 500 + Walnut Creek CA 94597 + US + +28-BC-18 (hex) SourcingOverseas Co. Ltd +28BC18 (base 16) SourcingOverseas Co. Ltd + 2F., No.616, Sec.5, Zhongshan N. Rd., Shilin Dist., + Taipei City 111 + TW + +94-AB-DE (hex) OMX Technology - FZE +94ABDE (base 16) OMX Technology - FZE + Dubai Silicon Oasis - THUB - 1-D-OFF-124 + Dubai 65673 + AE + +9C-DF-B1 (hex) Shenzhen Crave Communication Co., LTD +9CDFB1 (base 16) Shenzhen Crave Communication Co., LTD + F3,8Building,DongFangMing IndustryZone,No.83 DabaoRD.,33 District BaoAn + Shenzhen Guangdong 518000 + CN + +AC-CF-85 (hex) HUAWEI TECHNOLOGIES CO.,LTD +ACCF85 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan Guangdong 523808 + CN + +38-71-DE (hex) Apple, Inc. +3871DE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-81-EB (hex) Apple, Inc. +7081EB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-73-8D (hex) Shenzhen TINNO Mobile Technology Corp. +00738D (base 16) Shenzhen TINNO Mobile Technology Corp. + 4/F.,H-3 Building,OCT Eastern lndustrial Park. NO.1 XiangShan East Road. + GuangDong 518053 + US + +34-BA-75 (hex) Everest Networks, Inc +34BA75 (base 16) Everest Networks, Inc + 2933 Bunker Hill Ln., Suite 100 + Santa Clara CA 95054 + US + +7C-18-CD (hex) E-TRON Co.,Ltd. +7C18CD (base 16) E-TRON Co.,Ltd. + 66-11, Nonhyeon 2-dong, Gangnam-gu + Seoul 06049 + KR + +00-E0-FC (hex) HUAWEI TECHNOLOGIES CO.,LTD +00E0FC (base 16) HUAWEI TECHNOLOGIES CO.,LTD + KEFA ROAD, SCIENCE-BASED INDUSTRIAL PARK + SHENZHEN 518057 12345 + CN + +64-16-F0 (hex) HUAWEI TECHNOLOGIES CO.,LTD +6416F0 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 2, Zone B,Huawei Industrial Park,Bantian, Longgang District + Shenzhen Guangdong 518129 + CN + +F4-03-04 (hex) Google, Inc. +F40304 (base 16) Google, Inc. + 1600 Amphitheatre Pkwy + Mt. View CA 94043 + US + +54-60-09 (hex) Google, Inc. +546009 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +A4-77-33 (hex) Google, Inc. +A47733 (base 16) Google, Inc. + 1600 Ampitheatre Parkway + Mountain View 94043 + US + +80-7A-BF (hex) HTC Corporation +807ABF (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +78-F8-82 (hex) LG Electronics (Mobile Communications) +78F882 (base 16) LG Electronics (Mobile Communications) + 60-39, Gasan-dong, Geumcheon-gu + Seoul 153-801 + KR + +C0-2C-7A (hex) Shenzhen Horn Audio Co.,Ltd. +C02C7A (base 16) Shenzhen Horn Audio Co.,Ltd. + Block17,Tongfuyu lnd.Zone,Dalang,Baoan + Shenzhen Guang Dong 518109 + CN + +1C-CB-99 (hex) TCT mobile ltd +1CCB99 (base 16) TCT mobile ltd + No.86 hechang 7th road, zhongkai, Hi-Tech District + Hui Zhou Guang Dong 516006 + CN + +A4-2B-B0 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +A42BB0 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +18-8B-45 (hex) Cisco Systems, Inc +188B45 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +60-69-44 (hex) Apple, Inc. +606944 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B0-C6-9A (hex) Juniper Networks +B0C69A (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +2C-6B-F5 (hex) Juniper Networks +2C6BF5 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +C4-2F-90 (hex) Hangzhou Hikvision Digital Technology Co.,Ltd. +C42F90 (base 16) Hangzhou Hikvision Digital Technology Co.,Ltd. + No.469,Jianghui Road + Hangzhou Zhejiang 310052 + CN + +F4-CA-24 (hex) FreeBit Co., Ltd. +F4CA24 (base 16) FreeBit Co., Ltd. + E.Space Tower 3-6 Maruyama-Cho + Shibuya-ku Tokyo 150-0044 + JP + +00-D0-B7 (hex) Intel Corporation +00D0B7 (base 16) Intel Corporation + 5200 NE ELAM YOUNG PARKWAY + HILLSBORO OR 97124 + US + +00-1D-D6 (hex) ARRIS Group, Inc. +001DD6 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +90-3E-AB (hex) ARRIS Group, Inc. +903EAB (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +30-60-23 (hex) ARRIS Group, Inc. +306023 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +14-AB-F0 (hex) ARRIS Group, Inc. +14ABF0 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-14-F6 (hex) Juniper Networks +0014F6 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +90-1A-CA (hex) ARRIS Group, Inc. +901ACA (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +C8-3F-B4 (hex) ARRIS Group, Inc. +C83FB4 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +E0-B7-0A (hex) ARRIS Group, Inc. +E0B70A (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-1D-CE (hex) ARRIS Group, Inc. +001DCE (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-13-E8 (hex) Intel Corporate +0013E8 (base 16) Intel Corporate + Lot 8, Jalan Hi-tech 2/3 + Kulim Kedah 09000 + MY + +00-13-CE (hex) Intel Corporate +0013CE (base 16) Intel Corporate + Lot 8, Jalan Hi-tech 2/3 + Kulim Kedah 09000 + MY + +2C-76-8A (hex) Hewlett Packard +2C768A (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +C8-34-8E (hex) Intel Corporate +C8348E (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +4C-34-88 (hex) Intel Corporate +4C3488 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +10-02-B5 (hex) Intel Corporate +1002B5 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-40-26 (hex) BUFFALO.INC +004026 (base 16) BUFFALO.INC + AKAMONDORI Bldg., 30-20,Ohsu 3-chome + Naka-ku,Nagoya Aichi Pref. 460-8315 + JP + +4C-E6-76 (hex) BUFFALO.INC +4CE676 (base 16) BUFFALO.INC + AKAMONDORI Bldg., 30-20,Ohsu 3-chome + Naka-ku,Nagoya Aichi Pref. 460-8315 + JP + +00-0B-CD (hex) Hewlett Packard +000BCD (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-0F-20 (hex) Hewlett Packard +000F20 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-11-0A (hex) Hewlett Packard +00110A (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +B8-B8-1E (hex) Intel Corporate +B8B81E (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +B4-6D-83 (hex) Intel Corporate +B46D83 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +00-0E-35 (hex) Intel Corporation +000E35 (base 16) Intel Corporation + 2111 NE 25th Ave + Hillsboro OR 97123 + US + +00-07-E9 (hex) Intel Corporation +0007E9 (base 16) Intel Corporation + 2111 NE 25th Avenue + Hillsboro OR 97124 + US + +00-17-08 (hex) Hewlett Packard +001708 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +00-17-A4 (hex) Hewlett Packard +0017A4 (base 16) Hewlett Packard + 20555 State Highway 249 + Houston TX 77070 + US + +C0-05-C2 (hex) ARRIS Group, Inc. +C005C2 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +00-30-C1 (hex) Hewlett Packard +0030C1 (base 16) Hewlett Packard + 11000 WOLFE ROAD + CUPERTINO CA 95014 + US + +00-80-A0 (hex) Hewlett Packard +0080A0 (base 16) Hewlett Packard + ALAMEDA RIO NEGRO, + houston tx 77070 + BR + +D4-85-64 (hex) Hewlett Packard +D48564 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +24-BE-05 (hex) Hewlett Packard +24BE05 (base 16) Hewlett Packard + 11445 Compaq Center Drive W + Houston 77070 + US + +FC-3F-DB (hex) Hewlett Packard +FC3FDB (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston TX 77070 + US + +30-8D-99 (hex) Hewlett Packard +308D99 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +58-20-B1 (hex) Hewlett Packard +5820B1 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +94-57-A5 (hex) Hewlett Packard +9457A5 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +00-0E-B3 (hex) Hewlett Packard +000EB3 (base 16) Hewlett Packard + 2580 55th Street + Boulder CO 80301 + US + +08-00-09 (hex) Hewlett Packard +080009 (base 16) Hewlett Packard + ENTERPRISE SYSTEMS TECH.CENTER + CUPERTINO CA 95014 + US + +90-CD-B6 (hex) Hon Hai Precision Ind. Co.,Ltd. +90CDB6 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +40-49-0F (hex) Hon Hai Precision Ind. Co.,Ltd. +40490F (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-26-5C (hex) Hon Hai Precision Ind. Co.,Ltd. +00265C (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-22-69 (hex) Hon Hai Precision Ind. Co.,Ltd. +002269 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +D8-79-88 (hex) Hon Hai Precision Ind. Co.,Ltd. +D87988 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +74-A7-8E (hex) zte corporation +74A78E (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +00-09-2D (hex) HTC Corporation +00092D (base 16) HTC Corporation + No.23 Xinghua Road, + Taoyuan County 330 + TW + +44-31-92 (hex) Hewlett Packard +443192 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +A0-D3-C1 (hex) Hewlett Packard +A0D3C1 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +38-EA-A7 (hex) Hewlett Packard +38EAA7 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +AC-16-2D (hex) Hewlett Packard +AC162D (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +80-C1-6E (hex) Hewlett Packard +80C16E (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +B4-B5-2F (hex) Hewlett Packard +B4B52F (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +D0-7E-28 (hex) Hewlett Packard +D07E28 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +D0-BF-9C (hex) Hewlett Packard +D0BF9C (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +7C-61-93 (hex) HTC Corporation +7C6193 (base 16) HTC Corporation + No. 23, Xinghua Rd., + Taoyuan County 330 + TW + +90-E7-C4 (hex) HTC Corporation +90E7C4 (base 16) HTC Corporation + No. 23, Xinghua Rd. + Taoyuan County Taiwan 330 + TW + +BC-EA-FA (hex) Hewlett Packard +BCEAFA (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +74-46-A0 (hex) Hewlett Packard +7446A0 (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +2C-44-FD (hex) Hewlett Packard +2C44FD (base 16) Hewlett Packard + 11445 Compaq Center Drive + Houston 77070 + US + +04-53-D5 (hex) Sysorex Global Holdings +0453D5 (base 16) Sysorex Global Holdings + Suite 195 2479 E. Bayshore Road + Palo Alto CA 94303 + US + +EC-52-DC (hex) WORLD MEDIA AND TECHNOLOGY Corp. +EC52DC (base 16) WORLD MEDIA AND TECHNOLOGY Corp. + 600 Brickell World Plaza, suite 1775 + Miami 33132 + US + +94-B2-CC (hex) PIONEER CORPORATION +94B2CC (base 16) PIONEER CORPORATION + 1-1 Shin-ogura + Kawasaki-shi Kanagawa Prefecture 2120031 + JP + +04-52-F3 (hex) Apple, Inc. +0452F3 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +88-C2-55 (hex) Texas Instruments +88C255 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +CC-78-AB (hex) Texas Instruments +CC78AB (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +1C-78-39 (hex) Shenzhen Tencent Computer System Co., Ltd. +1C7839 (base 16) Shenzhen Tencent Computer System Co., Ltd. + 36/F, Tencent Building, Kejizhongyi Avenue, Hi-Tech Park + Shenzhen Guangdong 518057 + CN + +FC-D7-33 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +FCD733 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4)  + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +5C-89-9A (hex) TP-LINK TECHNOLOGIES CO.,LTD. +5C899A (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4)  + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +A8-1B-5A (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +A81B5A (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD,WUSHA,CHANG'AN,DONGGUAN,GUANGDONG,CHINA + DONGGUAN GUANGDONG 523860 + CN + +2C-5B-B8 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +2C5BB8 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD,WUSHA,CHANG'AN,DONGGUAN,GUANGDONG,CHINA + DONGGUAN GUANGDONG 523860 + CN + +08-EB-74 (hex) HUMAX Co., Ltd. +08EB74 (base 16) HUMAX Co., Ltd. + HUMAX Village, 11-4, Sunae-dong, Bundang-gu + Seongnam-si Gyeonggi-do 463-825 + KR + +E0-05-C5 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +E005C5 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 7, Second Part, Honghualing Industrial Zone + Shenzhen Guangdong 518000 + CN + +38-83-45 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +388345 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park,Shennan Rd, Nanshan, + Shenzhen, Guangdong Province 518057 + CN + +EC-88-8F (hex) TP-LINK TECHNOLOGIES CO.,LTD. +EC888F (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park + Shenzhen Guangdong 518057 + CN + +64-66-B3 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +6466B3 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) Central Science and Technology Park + Shenzhen Guangdong 518057 + CN + +28-32-C5 (hex) HUMAX Co., Ltd. +2832C5 (base 16) HUMAX Co., Ltd. + HUMAX Village,216,Hwangsaeul-ro,Bundang-gu + Seongnam-si Gyeonggi-do 463-875 + KR + +F0-F3-36 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +F0F336 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +BC-46-99 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +BC4699 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4) + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +F4-83-CD (hex) TP-LINK TECHNOLOGIES CO.,LTD. +F483CD (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24 (floors 1,3,4,5) and 28 (floors1-4)  + Shennan Rd, Nanshan Shenzhen,Guangdong Province 518057 + CN + +00-21-27 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +002127 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + South Building, No.5 Keyuan Road, Central Zone, + Shenzhen Guangdong 518000 + CN + +5C-63-BF (hex) TP-LINK TECHNOLOGIES CO.,LTD. +5C63BF (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + 1-6F, Building 2, Pingshandayuan Industrial, South Zone, + Shenzhen Guangdong 518000 + CN + +88-94-71 (hex) Brocade Communications Systems, Inc. +889471 (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +8C-7C-FF (hex) Brocade Communications Systems, Inc. +8C7CFF (base 16) Brocade Communications Systems, Inc. + 130 Holger Way + San Jose CA 95134 + US + +14-2D-27 (hex) Hon Hai Precision Ind. Co.,Ltd. +142D27 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +88-E3-AB (hex) HUAWEI TECHNOLOGIES CO.,LTD +88E3AB (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +C4-05-28 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C40528 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +3C-DF-BD (hex) HUAWEI TECHNOLOGIES CO.,LTD +3CDFBD (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +50-9F-27 (hex) HUAWEI TECHNOLOGIES CO.,LTD +509F27 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +80-71-7A (hex) HUAWEI TECHNOLOGIES CO.,LTD +80717A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-21-E8 (hex) Murata Manufacturing Co., Ltd. +0021E8 (base 16) Murata Manufacturing Co., Ltd. + 2288, Oaza-Ohshinohara, Yasu-cho, + Yasu-gun Shiga 520-2393 + JP + +00-0E-6D (hex) Murata Manufacturing Co., Ltd. +000E6D (base 16) Murata Manufacturing Co., Ltd. + 2288, Oaza-Ohshinohara, Yasu-cho, + Yasu-gun Shiga 520-2393 + JP + +90-21-06 (hex) BSkyB Ltd +902106 (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +D0-27-88 (hex) Hon Hai Precision Ind. Co.,Ltd. +D02788 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +90-4C-E5 (hex) Hon Hai Precision Ind. Co.,Ltd. +904CE5 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-1F-E2 (hex) Hon Hai Precision Ind. Co.,Ltd. +001FE2 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +00-16-CF (hex) Hon Hai Precision Ind. Co.,Ltd. +0016CF (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +20-02-AF (hex) Murata Manufacturing Co., Ltd. +2002AF (base 16) Murata Manufacturing Co., Ltd. + 1-10-1 Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +98-F5-37 (hex) zte corporation +98F537 (base 16) zte corporation + 12/F.,zte R&D building,kejinan Road, + shenzhen guangdong 518057 + CN + +5C-4C-A9 (hex) HUAWEI TECHNOLOGIES CO.,LTD +5C4CA9 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +F4-C7-14 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4C714 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District, + Shenzhen Guangdong 518108 + CN + +28-6E-D4 (hex) HUAWEI TECHNOLOGIES CO.,LTD +286ED4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + HUAWEI Industrial Base Bantian,Longgang + Shenzhen guangdong 518129 + CN + +00-1E-10 (hex) HUAWEI TECHNOLOGIES CO.,LTD +001E10 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + HUAWEI INDUSTRIAL PK BANTIAN, LONGGANG DIST SHENZHEN + SHENZHEN GUANGDONG 518077 + CN + +D4-78-56 (hex) Avaya Inc +D47856 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +D8-42-AC (hex) Shanghai Feixun Communication Co.,Ltd. +D842AC (base 16) Shanghai Feixun Communication Co.,Ltd. + Building 90, No. 4855, Guangfulin Road, Songjiang District + Shanghai 201616 + CN + +54-39-DF (hex) HUAWEI TECHNOLOGIES CO.,LTD +5439DF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + Shenzhen Guangdong 518129 + CN + +28-3C-E4 (hex) HUAWEI TECHNOLOGIES CO.,LTD +283CE4 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate,Shiyan Baoan District + Shenzhen Guangdong 518057 + CN + +2C-F4-C5 (hex) Avaya Inc +2CF4C5 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +3C-3A-73 (hex) Avaya Inc +3C3A73 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +FC-83-99 (hex) Avaya Inc +FC8399 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +58-7F-66 (hex) HUAWEI TECHNOLOGIES CO.,LTD +587F66 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +64-A6-51 (hex) HUAWEI TECHNOLOGIES CO.,LTD +64A651 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +08-63-61 (hex) HUAWEI TECHNOLOGIES CO.,LTD +086361 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + Building 17,Nangang Industrial Park, Tangtou 3nd Industrial Estate + Shenzhen GuangDong 518057 + CN + +A0-12-90 (hex) Avaya Inc +A01290 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +38-BB-3C (hex) Avaya Inc +38BB3C (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +F8-73-A2 (hex) Avaya Inc +F873A2 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +CC-F9-54 (hex) Avaya Inc +CCF954 (base 16) Avaya Inc + 360 Mt Kemble Ave + Morristown NJ 07960 + US + +8C-34-FD (hex) HUAWEI TECHNOLOGIES CO.,LTD +8C34FD (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +AC-F7-F3 (hex) Xiaomi Communications Co Ltd +ACF7F3 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +D4-97-0B (hex) Xiaomi Communications Co Ltd +D4970B (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +8C-BE-BE (hex) Xiaomi Communications Co Ltd +8CBEBE (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +14-F6-5A (hex) Xiaomi Communications Co Ltd +14F65A (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +00-9E-C8 (hex) Xiaomi Communications Co Ltd +009EC8 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +0C-1D-AF (hex) Xiaomi Communications Co Ltd +0C1DAF (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +08-19-A6 (hex) HUAWEI TECHNOLOGIES CO.,LTD +0819A6 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +3C-F8-08 (hex) HUAWEI TECHNOLOGIES CO.,LTD +3CF808 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +48-62-76 (hex) HUAWEI TECHNOLOGIES CO.,LTD +486276 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +B4-15-13 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B41513 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +AC-4E-91 (hex) HUAWEI TECHNOLOGIES CO.,LTD +AC4E91 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +28-31-52 (hex) HUAWEI TECHNOLOGIES CO.,LTD +283152 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base,Bantian,Longgang,Shenzhen + ShenZhen GuangDong 518129 + CN + +34-80-B3 (hex) Xiaomi Communications Co Ltd +3480B3 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +F4-8B-32 (hex) Xiaomi Communications Co Ltd +F48B32 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +00-90-21 (hex) Cisco Systems, Inc +009021 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-90-B1 (hex) Cisco Systems, Inc +0090B1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1A-B6 (hex) Texas Instruments +001AB6 (base 16) Texas Instruments + 108 Wild Basin Ste 350 + Austin TX 78746 + US + +00-12-D1 (hex) Texas Instruments +0012D1 (base 16) Texas Instruments + 12500 TI Boulevard, + Dallas 75243 + US + +00-12-37 (hex) Texas Instruments +001237 (base 16) Texas Instruments + 12500 TI Boulevard, + Dallas 75243 + US + +A0-E6-F8 (hex) Texas Instruments +A0E6F8 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +70-FF-76 (hex) Texas Instruments +70FF76 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +D0-39-72 (hex) Texas Instruments +D03972 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +5C-31-3E (hex) Texas Instruments +5C313E (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +F4-B8-5E (hex) Texas Instruments +F4B85E (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +68-C9-0B (hex) Texas Instruments +68C90B (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +74-88-2A (hex) HUAWEI TECHNOLOGIES CO.,LTD +74882A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +4C-B1-6C (hex) HUAWEI TECHNOLOGIES CO.,LTD +4CB16C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1-4,Huawei Industrial Base,Bantian,Longgang + ShenZhen GuangDong 518129 + CN + +04-BD-70 (hex) HUAWEI TECHNOLOGIES CO.,LTD +04BD70 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + D1,Huawei Industrial Base + Shenzhen Guangdong 518129 + CN + +D4-F5-13 (hex) Texas Instruments +D4F513 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +50-72-24 (hex) Texas Instruments +507224 (base 16) Texas Instruments + 12500 TI BLVD + Dallas 75243 + US + +00-90-D9 (hex) Cisco Systems, Inc +0090D9 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-90-92 (hex) Cisco Systems, Inc +009092 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-10-2F (hex) Cisco Systems, Inc +00102F (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-10-0D (hex) Cisco Systems, Inc +00100D (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-10-07 (hex) Cisco Systems, Inc +001007 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-10-14 (hex) Cisco Systems, Inc +001014 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +00-90-BF (hex) Cisco Systems, Inc +0090BF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-50-D1 (hex) Cisco Systems, Inc +0050D1 (base 16) Cisco Systems, Inc + 170 W. TASMAN DR. + SAN JOSE CA 95134-1706 + US + +1C-E6-C7 (hex) Cisco Systems, Inc +1CE6C7 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +CC-D5-39 (hex) Cisco Systems, Inc +CCD539 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +4C-00-82 (hex) Cisco Systems, Inc +4C0082 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +7C-95-F3 (hex) Cisco Systems, Inc +7C95F3 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +34-DB-FD (hex) Cisco Systems, Inc +34DBFD (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +88-5A-92 (hex) Cisco Systems, Inc +885A92 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-40-0B (hex) Cisco Systems, Inc +00400B (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-60-70 (hex) Cisco Systems, Inc +006070 (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +50-06-04 (hex) Cisco Systems, Inc +500604 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-E0-1E (hex) Cisco Systems, Inc +00E01E (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +00-11-2F (hex) ASUSTek COMPUTER INC. +00112F (base 16) ASUSTek COMPUTER INC. + No.150, Li-Te Rd., Peitou + Taipei 112 + TW + +00-1B-FC (hex) ASUSTek COMPUTER INC. +001BFC (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou + Taipei 112 + TW + +A0-55-4F (hex) Cisco Systems, Inc +A0554F (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +20-4C-9E (hex) Cisco Systems, Inc +204C9E (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +84-B8-02 (hex) Cisco Systems, Inc +84B802 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +B0-AA-77 (hex) Cisco Systems, Inc +B0AA77 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +BC-C4-93 (hex) Cisco Systems, Inc +BCC493 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +A4-6C-2A (hex) Cisco Systems, Inc +A46C2A (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +D0-A5-A6 (hex) Cisco Systems, Inc +D0A5A6 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +3C-5E-C3 (hex) Cisco Systems, Inc +3C5EC3 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +64-F6-9D (hex) Cisco Systems, Inc +64F69D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-03-89 (hex) PLANTRONICS, INC. +000389 (base 16) PLANTRONICS, INC. + 345 ENCINAL STREET + SANTA CRUZ CA 95060 + US + +D0-72-DC (hex) Cisco Systems, Inc +D072DC (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +28-C7-CE (hex) Cisco Systems, Inc +28C7CE (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +F4-0F-1B (hex) Cisco Systems, Inc +F40F1B (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +F8-C2-88 (hex) Cisco Systems, Inc +F8C288 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +1C-6A-7A (hex) Cisco Systems, Inc +1C6A7A (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-1E-E5 (hex) Cisco-Linksys, LLC +001EE5 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine 92612 + US + +48-44-87 (hex) Cisco SPVTG +484487 (base 16) Cisco SPVTG + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +38-C8-5C (hex) Cisco SPVTG +38C85C (base 16) Cisco SPVTG + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +48-5B-39 (hex) ASUSTek COMPUTER INC. +485B39 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou,Taipei 112 ,Taiwan + Taipei Taiwan 112 + TW + +BC-AE-C5 (hex) ASUSTek COMPUTER INC. +BCAEC5 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou, + Taipei 112 + TW + +10-BF-48 (hex) ASUSTek COMPUTER INC. +10BF48 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd.,Peitou, + Taipei 112 + TW + +50-67-AE (hex) Cisco Systems, Inc +5067AE (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +F0-9E-63 (hex) Cisco Systems, Inc +F09E63 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +6C-99-89 (hex) Cisco Systems, Inc +6C9989 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +18-E7-28 (hex) Cisco Systems, Inc +18E728 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +00-12-17 (hex) Cisco-Linksys, LLC +001217 (base 16) Cisco-Linksys, LLC + 121 Theory Dr. + Irvine CA 92612 + US + +00-13-10 (hex) Cisco-Linksys, LLC +001310 (base 16) Cisco-Linksys, LLC + 121 Theory Dr. + Irvine CA 92612 + US + +04-6C-9D (hex) Cisco Systems, Inc +046C9D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +84-B2-61 (hex) Cisco Systems, Inc +84B261 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +E4-48-C7 (hex) Cisco SPVTG +E448C7 (base 16) Cisco SPVTG + 5030 Sugarloaf Pkwy + Lawrenceville GA 30044 + US + +00-10-1F (hex) Cisco Systems, Inc +00101F (base 16) Cisco Systems, Inc + 170 WEST TASMAN DRIVE + SAN JOSE CA 95134-1706 + US + +54-A2-74 (hex) Cisco Systems, Inc +54A274 (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +60-FB-42 (hex) Apple, Inc. +60FB42 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +64-B9-E8 (hex) Apple, Inc. +64B9E8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-1D-4F (hex) Apple, Inc. +001D4F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-23-12 (hex) Apple, Inc. +002312 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +80-E0-1D (hex) Cisco Systems, Inc +80E01D (base 16) Cisco Systems, Inc + 170 West Tasman Drive + San Jose CA 95134 + US + +D8-A2-5E (hex) Apple, Inc. +D8A25E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-0A-27 (hex) Apple, Inc. +000A27 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-34-51 (hex) Apple, Inc. +183451 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +0C-77-1A (hex) Apple, Inc. +0C771A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-6A-BA (hex) Apple, Inc. +286ABA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +4C-B1-99 (hex) Apple, Inc. +4CB199 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +C0-9F-42 (hex) Apple, Inc. +C09F42 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D0-23-DB (hex) Apple, Inc. +D023DB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-DE-E2 (hex) Apple, Inc. +70DEE2 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-CB-A1 (hex) Apple, Inc. +F0CBA1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-20-32 (hex) Apple, Inc. +182032 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-3C-FC (hex) Apple, Inc. +403CFC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +48-60-BC (hex) Apple, Inc. +4860BC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-51-C9 (hex) Apple, Inc. +3451C9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-6C-8F (hex) Apple, Inc. +406C8F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +58-55-CA (hex) Apple, Inc. +5855CA (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +DC-2B-61 (hex) Apple, Inc. +DC2B61 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +40-A6-D9 (hex) Apple, Inc. +40A6D9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +60-FA-CD (hex) Apple, Inc. +60FACD (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-3E-E1 (hex) Apple, Inc. +003EE1 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-25-3F (hex) Apple, Inc. +FC253F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-F7-E4 (hex) Apple, Inc. +04F7E4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +34-C0-59 (hex) Apple, Inc. +34C059 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F0-D1-A9 (hex) Apple, Inc. +F0D1A9 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-56-81 (hex) Apple, Inc. +705681 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-10-9F (hex) Apple, Inc. +14109F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-0C-CE (hex) Apple, Inc. +040CCE (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-EA-A8 (hex) Apple, Inc. +54EAA8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-E1-4C (hex) Apple, Inc. +28E14C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E4-C6-3D (hex) Apple, Inc. +E4C63D (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-E4-3A (hex) Apple, Inc. +54E43A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-DB-56 (hex) Apple, Inc. +04DB56 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-3C-0B (hex) Apple, Inc. +AC3C0B (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +70-11-24 (hex) Apple, Inc. +701124 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-26-65 (hex) Apple, Inc. +042665 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +EC-35-86 (hex) Apple, Inc. +EC3586 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +78-FD-94 (hex) Apple, Inc. +78FD94 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-BE-08 (hex) Apple, Inc. +2CBE08 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +E8-80-2E (hex) Apple, Inc. +E8802E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +00-61-71 (hex) Apple, Inc. +006171 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +8C-7C-92 (hex) Apple, Inc. +8C7C92 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B0-34-95 (hex) Apple, Inc. +B03495 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F4-37-B7 (hex) Apple, Inc. +F437B7 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-7F-3E (hex) Apple, Inc. +AC7F3E (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-0B-5C (hex) Apple, Inc. +280B5C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +AC-FD-EC (hex) Apple, Inc. +ACFDEC (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +DC-9B-9C (hex) Apple, Inc. +DC9B9C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +54-72-4F (hex) Apple, Inc. +54724F (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D8-CF-9C (hex) Apple, Inc. +D8CF9C (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +7C-6D-F8 (hex) Apple, Inc. +7C6DF8 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +04-E5-36 (hex) Apple, Inc. +04E536 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +A8-BB-CF (hex) Apple, Inc. +A8BBCF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-40-08 (hex) Apple, Inc. +6C4008 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +FC-A3-86 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD +FCA386 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + Unit East Block22-24/F,Skyworth semiconductor design Bldg., Gaoxin Ave.4.S.,Nanshan District,Shenzhen,China + SHENZHEN GUANGDONG 518057 + CN + +40-33-1A (hex) Apple, Inc. +40331A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +CC-C7-60 (hex) Apple, Inc. +CCC760 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +BC-4C-C4 (hex) Apple, Inc. +BC4CC4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +DC-37-14 (hex) Apple, Inc. +DC3714 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-A2-E4 (hex) Apple, Inc. +20A2E4 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-F0-76 (hex) Apple, Inc. +28F076 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +14-13-57 (hex) ATP Electronics, Inc. +141357 (base 16) ATP Electronics, Inc. + 2590 North First Street Suite 150 + San Jose CA 95131 + US + +B8-B2-EB (hex) Googol Technology (HK) Limited +B8B2EB (base 16) Googol Technology (HK) Limited + Unit 1008-09, 10/F C-Bons International Center + Kwun Tong Kowloon nil + HK + +FC-CF-43 (hex) HUIZHOU CITY HUIYANG DISTRICT MEISIQI INDUSTRY DEVELOPMENT CO,.LTD +FCCF43 (base 16) HUIZHOU CITY HUIYANG DISTRICT MEISIQI INDUSTRY DEVELOPMENT CO,.LTD + Meisiqi lndustrialPark,Yuechang, + Huizhou Guangdong 516000 + CN + +D8-48-EE (hex) Hangzhou Xueji Technology Co., Ltd. +D848EE (base 16) Hangzhou Xueji Technology Co., Ltd. + Room 1902, Tower D, West Intime City + Hangzhou Zhejiang 310012 + CN + +B4-EF-04 (hex) DAIHAN Scientific Co., Ltd. +B4EF04 (base 16) DAIHAN Scientific Co., Ltd. + 326, Sinpyoungsukhwaro + Wonju-si, Gangwon-do 26358 + KR + +A4-DE-C9 (hex) QLove Mobile Intelligence Information Technology (W.H.) Co. Ltd. +A4DEC9 (base 16) QLove Mobile Intelligence Information Technology (W.H.) Co. Ltd. + Sun Jia Tuan Township, Huan Cui District, Weihai, P.R.China + Weihai Shan Dong 264201 + CN + +CC-E0-C3 (hex) EXTEN Technologies, Inc. +CCE0C3 (base 16) EXTEN Technologies, Inc. + 4201 W Parmer Lane Bldg A, Ste 200 + Austin TX 78727 + US + +64-6A-74 (hex) AUTH-SERVERS, LLC +646A74 (base 16) AUTH-SERVERS, LLC + 43479 Stukely Dr + Sterling VA 20166 + US + +4C-8E-CC (hex) SILKAN SA +4C8ECC (base 16) SILKAN SA + Immeuble le Sirius + Meudon La Foret Ile de France 92360 + FR + +E4-35-C8 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E435C8 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +0C-54-B9 (hex) Nokia +0C54B9 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +84-10-0D (hex) Motorola Mobility LLC, a Lenovo Company +84100D (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +D0-0F-6D (hex) T&W Electronics Company +D00F6D (base 16) T&W Electronics Company + 89# Jiang Nan RD, Lu Du + Taicang Jiangsu 21500 + CN + +90-8D-78 (hex) D-Link International +908D78 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +7C-71-76 (hex) Wuxi iData Technology Company Ltd. +7C7176 (base 16) Wuxi iData Technology Company Ltd. + Floor 11, Building B1, Wuxi(Binhu) National Sensing Information Center, No. 999 Gaolang East Road, Wuxi City, Jiangsu Province, P.R.C. + Wuxi Jiangsu 214131 + CN + +7C-01-91 (hex) Apple, Inc. +7C0191 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +2C-1B-C8 (hex) Hunan Topview Network System CO.,LTD +2C1BC8 (base 16) Hunan Topview Network System CO.,LTD + RM 3002,3009,3010 Yuelu High-Tech Zone, Hanpu Couty, Yuelu District + Changsha Hunan 410208 + CN + +A8-47-4A (hex) Hon Hai Precision Ind. Co.,Ltd. +A8474A (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +C4-00-49 (hex) Kamama +C40049 (base 16) Kamama + 100 Enterprise Way + Scotts Valley CA 95066 + US + +80-D6-05 (hex) Apple, Inc. +80D605 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +98-E8-48 (hex) Axiim +98E848 (base 16) Axiim + 12126 NE 106th Pl + Kirkland WA 98033 + US + +40-40-A7 (hex) Sony Mobile Communications Inc +4040A7 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +C0-4A-09 (hex) Zhejiang Everbright Communication Equip. Co,. Ltd +C04A09 (base 16) Zhejiang Everbright Communication Equip. Co,. Ltd + 291# Wei 19th Rd. + Wenzhou Zhejiang 325600 + CN + +A0-1E-0B (hex) MINIX Technology Limited +A01E0B (base 16) MINIX Technology Limited + Unit 1501, Chevalier Commercial Center + Kowloon Bay Kowloon 000000 + HK + +68-E8-EB (hex) Linktel Technologies Co.,Ltd +68E8EB (base 16) Linktel Technologies Co.,Ltd + No.20 University Science Park Road, + Wuhan Hubei 430223 + CN + +A8-45-CD (hex) Siselectron Technology LTD. +A845CD (base 16) Siselectron Technology LTD. + 5F., No.232, Sec. 2, Sioulang Rd., Yonghe Dist., + New Taipei City Taiwan 23453 + TW + +D0-C1-93 (hex) SKYBELL, INC +D0C193 (base 16) SKYBELL, INC + 1 JENNER, SUITE 100 + IRVINE CA 92618 + US + +AC-64-62 (hex) zte corporation +AC6462 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +C0-25-A2 (hex) NEC Platforms, Ltd. +C025A2 (base 16) NEC Platforms, Ltd. + 2-3 Kandatsukasamachi + Chiyodaku Tokyo 101-8532 + JP + +48-13-7E (hex) Samsung Electronics Co.,Ltd +48137E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +30-F7-72 (hex) Hon Hai Precision Ind. Co.,Ltd. +30F772 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +DC-3C-F6 (hex) Atomic Rules LLC +DC3CF6 (base 16) Atomic Rules LLC + 287 Chester Rd + Auburn NH 03032 + US + +08-9B-4B (hex) iKuai Networks +089B4B (base 16) iKuai Networks + So Boss Tech Center 2 # 716 + Fengtai District Beijing 100068 + CN + +44-73-D6 (hex) Logitech +4473D6 (base 16) Logitech + 7700 Gateway Blvd + Newark CA 94560 + US + +10-CC-1B (hex) Liverock technologies,INC +10CC1B (base 16) Liverock technologies,INC + Shinjuku 5-13-10,Joshu-Bldg. 4F + Tokyo Shinjuku-ku 160-0022 + JP + +E8-07-34 (hex) Champion Optical Network Engineering, LLC +E80734 (base 16) Champion Optical Network Engineering, LLC + 23645 Mercantile Rd. + Beachwood OH 44122 + US + +A4-38-31 (hex) RF elements s.r.o. +A43831 (base 16) RF elements s.r.o. + Jasenovská 2528 + Humenne SK 06603 + SK + +38-05-46 (hex) Foctek Photonics, Inc. +380546 (base 16) Foctek Photonics, Inc. + No. 8, the 7th Road Phase II of Minhou Tieling Industrial District + Fuzhou Fujian 350100 + CN + +D4-83-04 (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +D48304 (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +DC-2B-2A (hex) Apple, Inc. +DC2B2A (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +9C-8D-D3 (hex) Leonton Technologies +9C8DD3 (base 16) Leonton Technologies + 3F, No.501-16, Zhongzheng Rd., Xindian Dist. + New Taipei City Taiwan 231 + TW + +E4-1A-2C (hex) ZPE Systems, Inc. +E41A2C (base 16) ZPE Systems, Inc. + 39420 Liberty Street, #253 + Fremont CA 94538 + US + +E8-BD-D1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +E8BDD1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +F4-15-35 (hex) SPON Communication Technology Co.,Ltd +F41535 (base 16) SPON Communication Technology Co.,Ltd + B Building, Lugu International Industrial Zone, NO.229, Tongzipo Road, Changsha, China + changsha hunan 410000 + CN + +38-0A-AB (hex) Formlabs +380AAB (base 16) Formlabs + 35 Medford St + Somerville MA 02143 + US + +38-2D-E8 (hex) Samsung Electronics Co.,Ltd +382DE8 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C0-89-97 (hex) Samsung Electronics Co.,Ltd +C08997 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +A8-15-D6 (hex) Shenzhen Meione Technology CO., LTD +A815D6 (base 16) Shenzhen Meione Technology CO., LTD + 12th FloorFutian Sports Park Cultural Industries Headquarters Building No. 3030 Fuqiang Road, Futian District + Shenzhen Guangdong 518000 + CN + +C0-7C-D1 (hex) PEGATRON CORPORATION +C07CD1 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +90-D8-F3 (hex) zte corporation +90D8F3 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +D4-45-E8 (hex) Jiangxi Hongpai Technology Co., Ltd. +D445E8 (base 16) Jiangxi Hongpai Technology Co., Ltd. + 5th Floor,C Region, Zhejiang University Science Park,No. 698, + Nanchang Jiangxi 330096 + CN + +34-26-06 (hex) CarePredict, Inc. +342606 (base 16) CarePredict, Inc. + PO Box 551686 + Fort Lauderdale Florida 33355 + US + +38-B7-25 (hex) Wistron Infocomm (Zhongshan) Corporation +38B725 (base 16) Wistron Infocomm (Zhongshan) Corporation + No.38,East Keji Road,Zhongshan Torch Development Zone,Zhongshan City,Guangdong,China + Zhongshan Guangdong 528437 + CN + +AC-EC-80 (hex) ARRIS Group, Inc. +ACEC80 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +50-7B-9D (hex) LCFC(HeFei) Electronics Technology co., ltd +507B9D (base 16) LCFC(HeFei) Electronics Technology co., ltd + YunGu Road 3188-1 + Hefei Anhui 230000 + CN + +6C-72-20 (hex) D-Link International +6C7220 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +30-A2-43 (hex) Shenzhen Prifox Innovation Technology Co., Ltd. +30A243 (base 16) Shenzhen Prifox Innovation Technology Co., Ltd. + Room B905, Bldg 4, Software Industry Park, + Shenzhen Guangdong Province 518057 + + +38-01-95 (hex) Samsung Electronics Co.,Ltd +380195 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +24-6E-96 (hex) Dell Inc. +246E96 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +44-97-5A (hex) SHENZHEN FAST TECHNOLOGIES CO.,LTD +44975A (base 16) SHENZHEN FAST TECHNOLOGIES CO.,LTD + Room 202,Building No.5,Section 30,No.2 of Kefa Road,Nanshan District,Shenzhen,P.R.China + Shenzhen Guangdong 518057 + CN + +50-45-F7 (hex) Liuhe Intelligence Technology Ltd. +5045F7 (base 16) Liuhe Intelligence Technology Ltd. + 7th Floor,Information Building, + Beijing Beijing 100085 + CN + +AC-67-6F (hex) Electrocompaniet A.S. +AC676F (base 16) Electrocompaniet A.S. + Breivikveien 7 + Tau Rogaland 4120 + NO + +64-0D-E6 (hex) Petra Systems +640DE6 (base 16) Petra Systems + One Cragwood Road + South Plainfield NJ 07080 + US + +E0-55-3D (hex) Cisco Meraki +E0553D (base 16) Cisco Meraki + 500 Terry A. Francois Blvd + San Francisco California 94158 + US + +FC-33-5F (hex) Polyera +FC335F (base 16) Polyera + 8045 Lamon Avenue + Skokie IL 60077 + US + +84-D4-C8 (hex) Widex A/S +84D4C8 (base 16) Widex A/S + Nymoellevej 6 + Lynge Alleroed DK3540 + DK + +EC-21-E5 (hex) Toshiba +EC21E5 (base 16) Toshiba + 2-9,Suehiro-Cho + Ome Tokyo 1988710 + JP + +04-C2-3E (hex) HTC Corporation +04C23E (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +E0-1A-EA (hex) Allied Telesis, Inc. +E01AEA (base 16) Allied Telesis, Inc. + 3041 Orchard Parkway + San Jose CALIFORNIA 95134 + US + +28-B9-D9 (hex) Radisys Corporation +28B9D9 (base 16) Radisys Corporation + 5435 NE Dawson Creek Drive + Hillsboro OR 97124 + US + +F4-C6-13 (hex) Alcatel-Lucent Shanghai Bell Co., Ltd +F4C613 (base 16) Alcatel-Lucent Shanghai Bell Co., Ltd + No. 389, Ningqiao Road, Pudong Jinqiao + Shanghai 201206 + CN + +44-5F-8C (hex) Intercel Group Limited +445F8C (base 16) Intercel Group Limited + Unit 6, 17/F, Vanta industrial Centre, + New Territories, Hong Kong + CN + +B8-89-81 (hex) Chengdu InnoThings Technology Co., Ltd. +B88981 (base 16) Chengdu InnoThings Technology Co., Ltd. + West Port Technology Enterprise Incubator Park + Chengdu Sichuan 610000 + CN + +F0-26-24 (hex) WAFA TECHNOLOGIES CO., LTD. +F02624 (base 16) WAFA TECHNOLOGIES CO., LTD. + Room302, Longtaili Building + Shenzhen Guangdong 518057 + CN + +F8-F4-64 (hex) Rawe Electonic GmbH +F8F464 (base 16) Rawe Electonic GmbH + Bregenzer Str. 67-69 + Weiler im Allgäu Bavaria 88171 + DE + +5C-51-88 (hex) Motorola Mobility LLC, a Lenovo Company +5C5188 (base 16) Motorola Mobility LLC, a Lenovo Company + 222 West Merchandise Mart Plaza + Chicago IL 60654 + US + +EC-01-33 (hex) TRINUS SYSTEMS INC. +EC0133 (base 16) TRINUS SYSTEMS INC. + UNITECH VENTURE TOWN SUITE 801 + GOYANG-SI GYEONGGI-DO 410-722 + KR + +2C-C5-48 (hex) IAdea Corporation +2CC548 (base 16) IAdea Corporation + 3F, No.33, Lane 77, Xing-ai Road + Taipei Taiwan 114 + TW + +14-DD-A9 (hex) ASUSTek COMPUTER INC. +14DDA9 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +18-4F-32 (hex) Hon Hai Precision Ind. Co.,Ltd. +184F32 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +DC-A3-AC (hex) RBcloudtech +DCA3AC (base 16) RBcloudtech + 5th Floor, Jiangnan Street NO.3900, Binjiang District, Hangzhou City. + Hangzhou Zhejiang 310052 + CN + +0C-E7-25 (hex) Microsoft Corporation +0CE725 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +58-F1-02 (hex) BLU Products Inc. +58F102 (base 16) BLU Products Inc. + Tower 4, Excellence Century Center + Shenzhen Guangdong 518000 + CN + +B4-AE-2B (hex) Microsoft +B4AE2B (base 16) Microsoft + 1 Microsoft Way + Redmond Washington 98052 + US + +94-9F-3E (hex) Sonos, Inc. +949F3E (base 16) Sonos, Inc. + 614 Chapala St + Santa Barbara CA 93101 + US + +30-89-D3 (hex) HONGKONG UCLOUDLINK NETWORK TECHNOLOGY LIMITED +3089D3 (base 16) HONGKONG UCLOUDLINK NETWORK TECHNOLOGY LIMITED + FLAT A-8 9/F DELYA INDUSTRIAL CENTRE 7 SHEK PAI TAU ROAD + Hong Kong + CN + +5C-B3-95 (hex) HUAWEI TECHNOLOGIES CO.,LTD +5CB395 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +90-6C-AC (hex) Fortinet, Inc. +906CAC (base 16) Fortinet, Inc. + 899 Kifer Road + Sunnyvale California 94086 + US + +3C-DA-2A (hex) zte corporation +3CDA2A (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +84-2E-27 (hex) Samsung Electronics Co.,Ltd +842E27 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +1C-AD-D1 (hex) Bosung Electronics Co., Ltd. +1CADD1 (base 16) Bosung Electronics Co., Ltd. + 74-12, Saemaeul-ro. + Gumi-si Gyeongsangbuk-do 730-930 + KR + +08-2C-B0 (hex) Network Instruments +082CB0 (base 16) Network Instruments + 10701 Red Circle Dr + Minnetonka Minnesota 55343 + US + +A0-13-CB (hex) Fiberhome Telecommunication Technologies Co.,LTD +A013CB (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +D0-04-92 (hex) Fiberhome Telecommunication Technologies Co.,LTD +D00492 (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +14-32-D1 (hex) Samsung Electronics Co.,Ltd +1432D1 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +18-16-C9 (hex) Samsung Electronics Co.,Ltd +1816C9 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +00-FC-8D (hex) Hitron Technologies. Inc +00FC8D (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +84-DF-19 (hex) Chuango Security Technology Corporation +84DF19 (base 16) Chuango Security Technology Corporation + 6-17, Overseas Students Pioneer Park, + Fuzhou Fujian 350015 + CN + +DC-15-DB (hex) Ge Ruili Intelligent Technology ( Beijing ) Co., Ltd. +DC15DB (base 16) Ge Ruili Intelligent Technology ( Beijing ) Co., Ltd. + Room 821, block E, No.6 Taiping Street, Xicheng District + Beijing 100005 + CN + +E0-DB-10 (hex) Samsung Electronics Co.,Ltd +E0DB10 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-61-72 (hex) ZODIAC AEROSPACE SAS +546172 (base 16) ZODIAC AEROSPACE SAS + 61 rue Pierre Curie + PLAISIR 78370 + FR + +EC-60-E0 (hex) AVI-ON LABS +EC60E0 (base 16) AVI-ON LABS + 2585 LARKSPUR DR + PARK CITY UT 84060 + US + +B4-6D-35 (hex) Dalian Seasky Automation Co;Ltd +B46D35 (base 16) Dalian Seasky Automation Co;Ltd + Room 408, DUT Science & Technology Park Building B, No.80 Software Park Road, High-Tech Industrial Zone, Dalian, Liaoning, China + Dalian Liao Ning 116023 + CN + +3C-A3-1A (hex) Oilfind International LLC +3CA31A (base 16) Oilfind International LLC + 12651 Briar Forest Dr, Suite 151 + Houston Texas 77077 + US + +30-F3-35 (hex) HUAWEI TECHNOLOGIES CO.,LTD +30F335 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +E8-F2-E3 (hex) Starcor Beijing Co.,Limited +E8F2E3 (base 16) Starcor Beijing Co.,Limited + NO.210 Block B, Building 2 + Beijing Berijing 100089 + CN + +64-59-F8 (hex) Vodafone Omnitel B.V. +6459F8 (base 16) Vodafone Omnitel B.V. + VIA JERVIS, 13 10015 IVREA (TO) + + IT + +6C-44-18 (hex) Zappware +6C4418 (base 16) Zappware + Ilgatlaan 19 + Hasselt Limburg 3500 + BE + +A8-D4-09 (hex) USA 111 Inc +A8D409 (base 16) USA 111 Inc + 5885 Green Pointe Dr. Suite B Groveport, OH 43125 + Groveport Ohio 43125 + US + +6C-45-98 (hex) Antex Electronic Corp. +6C4598 (base 16) Antex Electronic Corp. + 170 He Ping St., + Tainan City 73443 + TW + +68-A3-78 (hex) FREEBOX SAS +68A378 (base 16) FREEBOX SAS + 16 rue de la Ville l'Eveque + PARIS IdF 75008 + FR + +34-0A-22 (hex) TOP-ACCESS ELECTRONICS CO LTD +340A22 (base 16) TOP-ACCESS ELECTRONICS CO LTD + No. 2 Building + MingZhi Street BaoAn District,ShenzheN 518131 + CN + +E8-66-C4 (hex) Diamanti +E866C4 (base 16) Diamanti + 111 N. Market Street + San Jose CA 95113 + US + +D4-D7-A9 (hex) Shanghai Kaixiang Info Tech LTD +D4D7A9 (base 16) Shanghai Kaixiang Info Tech LTD + A401, NO.509 Caobao Road, Shanghai, PRC + Shanghai Shanghai 200233 + CN + +34-3D-98 (hex) JinQianMao Technology Co.,Ltd. +343D98 (base 16) JinQianMao Technology Co.,Ltd. + 58#,Jiangbin Road,Taijiang District + Fuzhou Fujian 350009 + CN + +F4-47-13 (hex) Leading Public Performance Co., Ltd. +F44713 (base 16) Leading Public Performance Co., Ltd. + 137/77-78 Moo 1 Nanthanagarden Soi 12 Pathum-Rangsit Road Banklang Muang Pathumthani 12000 Thailand + Pathumthani Pathumthani 12000 + TH + +5C-A1-78 (hex) TableTop Media (dba Ziosk) +5CA178 (base 16) TableTop Media (dba Ziosk) + 12404 Park Central Drive + Dallas TX 75251 + US + +9C-BE-E0 (hex) Biosoundlab Co., Ltd. +9CBEE0 (base 16) Biosoundlab Co., Ltd. + (Sangdaewon-dong, Sunil Technopia 907-908ho) + Jungwon-gu Seongnam-si Gyeonggi-do, 462726 + KR + +0C-41-3E (hex) Microsoft Corporation +0C413E (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +D0-6F-4A (hex) TOPWELL INTERNATIONAL HOLDINGS LIMITED +D06F4A (base 16) TOPWELL INTERNATIONAL HOLDINGS LIMITED + Unit 2506, 25/F, Prosperity Place, + Hong Kong N/A N/A + CN + +04-92-EE (hex) iway AG +0492EE (base 16) iway AG + Badenerstrasse 569 + Zurich ZH 8048 + CH + +80-74-59 (hex) K's Co.,Ltd. +807459 (base 16) K's Co.,Ltd. + 2864-16 Ryomitsuyanagi + Yonago Tottori 683-0853 + JP + +60-19-70 (hex) HUIZHOU QIAOXING ELECTRONICS TECHNOLOGY CO., LTD. +601970 (base 16) HUIZHOU QIAOXING ELECTRONICS TECHNOLOGY CO., LTD. + Room -611, TianAn High-Tech Plaza II , Futian District, Shenzhen, China + Shenzhen Guangdong 518040 + CN + +A4-08-EA (hex) Murata Manufacturing Co., Ltd. +A408EA (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +B8-78-79 (hex) Roche Diagnostics GmbH +B87879 (base 16) Roche Diagnostics GmbH + Sandhofer Strasse 116 + Mannheim Baden-Wuerttemberg 68305 + DE + +D0-83-D4 (hex) Xtel Wireless ApS +D083D4 (base 16) Xtel Wireless ApS + Alfred Nobels vej 21E + Aalborg Oest Nordjylland 9220 + DK + +08-D3-4B (hex) Techman Electronics (Changshu) Co., Ltd. +08D34B (base 16) Techman Electronics (Changshu) Co., Ltd. + No.66, Dalian Road, High-Tech Industrial Park + Changshu Jiangsu Province 215500 + CN + +78-A3-51 (hex) SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD +78A351 (base 16) SHENZHEN ZHIBOTONG ELECTRONICS CO.,LTD + 2F,Bldg. A,Kangmai Industrial Park,Renmin Rd + Shenzhen Guangdong 518110 + CN + +E4-69-5A (hex) Dictum Health, Inc. +E4695A (base 16) Dictum Health, Inc. + 255 3rd Street, Suite 102 + Oakland CA 94607 + US + +7C-7A-53 (hex) Phytrex Technology Corp. +7C7A53 (base 16) Phytrex Technology Corp. + 8F-16, No.81, Shuili Rd., + Hsinchu Taiwan 30059 + TW + +10-78-73 (hex) Shenzhen Jinkeyi Communication Co., Ltd. +107873 (base 16) Shenzhen Jinkeyi Communication Co., Ltd. + No. 10 Shun King Road, Zhen Ping Xi Cun, + Shenzhen Guangdong 518117 + CN + +48-EE-0C (hex) D-Link International +48EE0C (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +EC-3C-88 (hex) MCNEX Co.,Ltd. +EC3C88 (base 16) MCNEX Co.,Ltd. + Hanshin IT Tower2 11F, Digital lo 9 gil + Geumcheon-Gu Seoul 153-712 + KR + +70-AD-54 (hex) Malvern Instruments Ltd +70AD54 (base 16) Malvern Instruments Ltd + Grovewood Rd + Malvern Worcestershire WR14 1XZ + GB + +90-00-DB (hex) Samsung Electronics Co.,Ltd +9000DB (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B4-EF-39 (hex) Samsung Electronics Co.,Ltd +B4EF39 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +F0-2A-23 (hex) Creative Next Design +F02A23 (base 16) Creative Next Design + 6-6-15, Kaminopporo 3-jo, + Sapporo-shi Hokkaido 004-0033 + JP + +58-47-04 (hex) Shenzhen Webridge Technology Co.,Ltd +584704 (base 16) Shenzhen Webridge Technology Co.,Ltd + B2-22/F Chinese Technology Development Institute, High South Road, Nanshan District, Shenzhen, China + Shenzhen Guangdong 518000 + CN + +74-A0-63 (hex) HUAWEI TECHNOLOGIES CO.,LTD +74A063 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +EC-E2-FD (hex) SKG Electric Group(Thailand) Co., Ltd. +ECE2FD (base 16) SKG Electric Group(Thailand) Co., Ltd. + 3F,The Second Building,Sanhe village , Longhua Rd, Baoan Dist., Shenzhen, China + Shenzhen Guangdong 518301 + CN + +14-8F-21 (hex) Garmin International +148F21 (base 16) Garmin International + 1200 E. 151st St + Olathe KS 66062 + US + +9C-68-5B (hex) Octonion SA +9C685B (base 16) Octonion SA + EPFL Innovation Park, Bâtiment C + Lausanne Vaud 1015 + CH + +7C-53-4A (hex) Metamako +7C534A (base 16) Metamako + Suite 207 + Sydney Other 2000 + AU + +BC-6E-64 (hex) Sony Mobile Communications Inc +BC6E64 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +BC-B3-08 (hex) HONGKONG RAGENTEK COMMUNICATION TECHNOLOGY CO.,LIMITED +BCB308 (base 16) HONGKONG RAGENTEK COMMUNICATION TECHNOLOGY CO.,LIMITED + Building D10-D11 + PuDong District Shanghai 201315 + CN + +6C-2E-72 (hex) B&B EXPORTING LIMITED +6C2E72 (base 16) B&B EXPORTING LIMITED + Bldg.#D,Xinhe Industrial Park + Guangzhou Guangdong 510880 + CN + +5C-CC-FF (hex) Techroutes Network Pvt Ltd +5CCCFF (base 16) Techroutes Network Pvt Ltd + WW1-SF, Malibu Towne + Gurgaon Haryana 122002 + IN + +90-C3-5F (hex) Nanjing Jiahao Technology Co., Ltd. +90C35F (base 16) Nanjing Jiahao Technology Co., Ltd. + Moling Industrial Park, Development Zone, Jiangning, Nanjing + Nanjing Jiangsu 211111 + CN + +C8-08-E9 (hex) LG Electronics +C808E9 (base 16) LG Electronics + 222 LG-ro, JINWI-MYEON + Pyeongtaek-si Gyeonggi-do 451-713 + KR + +18-3A-2D (hex) Samsung Electronics Co.,Ltd +183A2D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +EC-74-BA (hex) Hirschmann Automation and Control GmbH +EC74BA (base 16) Hirschmann Automation and Control GmbH + Stuttgarter Strasse 45-51 + Neckartenzlingen Baden-Württemberg 72654 + DE + +FC-32-88 (hex) CELOT Wireless Co., Ltd +FC3288 (base 16) CELOT Wireless Co., Ltd + 4Fl.,NongHyup Bldg.,#1588-10 Gwanyang-Dong + Anyang City, Gyeonggi-Do 431-727 + KR + +D8-74-95 (hex) zte corporation +D87495 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +5C-3B-35 (hex) Gehirn Inc. +5C3B35 (base 16) Gehirn Inc. + 1-3-6 Kudan-kita + Chiyoda Tokyo 102-0073 + JP + +E4-FE-D9 (hex) EDMI Europe Ltd +E4FED9 (base 16) EDMI Europe Ltd + The Grainger Suite, Dobson House, Regent Centre + Newcastle upon Tyne Newcastle upon Tyne NE3 3PF + GB + +5C-F7-C3 (hex) SYNTECH (HK) TECHNOLOGY LIMITED +5CF7C3 (base 16) SYNTECH (HK) TECHNOLOGY LIMITED + Unit No. 1, 12/F., Perfect Industrial Building , + Kowloon, Hong Kong 999077 + HK + +9C-E2-30 (hex) JULONG CO,.LTD. +9CE230 (base 16) JULONG CO,.LTD. + 308,QianShanZhong Road,TieDong District,AnShan + AnShan City LiaoNing Province 114051 + CN + +5C-41-E7 (hex) Wiatec International Ltd. +5C41E7 (base 16) Wiatec International Ltd. + Unit 601-605,TaoJinDi Electronic Commercial + Shenzhen GuangDong 518131 + CN + +34-4C-A4 (hex) amazipoint technology Ltd. +344CA4 (base 16) amazipoint technology Ltd. + 1F,No. 14, Aly. 32, Ln. 133, Zhongyang Rd., + New Taipei City, 231 + TW + +A8-F0-38 (hex) SHEN ZHEN SHI JIN HUA TAI ELECTRONICS CO.,LTD +A8F038 (base 16) SHEN ZHEN SHI JIN HUA TAI ELECTRONICS CO.,LTD + Room A,Forth Floor,Building B,Hengmingzhu Industrial Park,Xixiang Forist and Fruit Bureau,Qianjin Road, Baoan District,Shenzhen city,Guangdong provice + 518126 + CN + +AC-C7-3F (hex) VITSMO CO., LTD. +ACC73F (base 16) VITSMO CO., LTD. + RM1418-1419, HansinIntervalley 24 Bldg. + SEOUL 135-918 + KR + +44-35-6F (hex) Neterix +44356F (base 16) Neterix + The Printworks + Chester Cheshire CH1 4RN + GB + +74-E2-77 (hex) Vizmonet Pte Ltd +74E277 (base 16) Vizmonet Pte Ltd + 32,Canberra drive,#05-28 + 76431 + SG + +14-89-3E (hex) VIXTEL TECHNOLOGIES LIMTED +14893E (base 16) VIXTEL TECHNOLOGIES LIMTED + ROOM 1409, 14/F, BLOCK B, KAILEY CENTER + CHAI WAN + HK + +BC-54-F9 (hex) Drogoo Technology Co., Ltd. +BC54F9 (base 16) Drogoo Technology Co., Ltd. + Shenzhen Dayun software town 17 2 floor + Shenzhen Guangdong 518172 + CN + +78-FC-14 (hex) Family Zone Cyber Safety Ltd +78FC14 (base 16) Family Zone Cyber Safety Ltd + 175 Heytesbury Rd + Subiaco WA 6008 + AU + +38-09-A4 (hex) Firefly Integrations +3809A4 (base 16) Firefly Integrations + 1013 Elroy Dr + Middlebury IN 46540 + US + +BC-E7-67 (hex) Quanzhou TDX Electronics Co., Ltd +BCE767 (base 16) Quanzhou TDX Electronics Co., Ltd + Hi-tech Park economic and tech development zone + Quanzhou Fujian province 362005 + CN + +FC-AF-AC (hex) Socionext Inc. +FCAFAC (base 16) Socionext Inc. + 19 Nishikujo-Kasuga-cho + Minaki-ku Kyoto 601-8413 + JP + +BC-4D-FB (hex) Hitron Technologies. Inc +BC4DFB (base 16) Hitron Technologies. Inc + No. 1-8, Lising 1st Rd. Hsinchu Science Park, Hsinchu, 300, Taiwan, R.O.C + Hsin-chu Taiwan 300 + TW + +2C-33-7A (hex) Hon Hai Precision Ind. Co.,Ltd. +2C337A (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +84-DD-B7 (hex) Cilag GmbH International +84DDB7 (base 16) Cilag GmbH International + Gubelstrasse 34 + Zug _ CH-6300 + CH + +08-EF-AB (hex) SAYME WIRELESS SENSOR NETWORK +08EFAB (base 16) SAYME WIRELESS SENSOR NETWORK + Calle Albert Einstein 18, 4a + Santander Cantabria 39011 + ES + +70-76-FF (hex) KERLINK +7076FF (base 16) KERLINK + 1 rue Jacqueline AURIOL + THORIGNE FOUILLARD 35235 + FR + +14-36-C6 (hex) Lenovo Mobile Communication Technology Ltd. +1436C6 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999, Qishan North 2nd Road, Information & Optoelectronics Park, + Xiamen Fujian 361006 + + +68-F7-28 (hex) LCFC(HeFei) Electronics Technology co., ltd +68F728 (base 16) LCFC(HeFei) Electronics Technology co., ltd + YunGu Road 3188-1 + Hefei Anhui 230000 + CN + +38-2C-4A (hex) ASUSTek COMPUTER INC. +382C4A (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +30-73-50 (hex) Inpeco SA +307350 (base 16) Inpeco SA + Via San Gottardo 10 + Lugano Ticino 6900 + CH + +DC-EC-06 (hex) Heimi Network Technology Co., Ltd. +DCEC06 (base 16) Heimi Network Technology Co., Ltd. + Room 12B12, Block A2, Long-Term World Building, + Beijing Beijing 100080 + CN + +CC-BD-D3 (hex) Ultimaker B.V. +CCBDD3 (base 16) Ultimaker B.V. + Burgemeester Rozeveld van de Venlaan 11 + Geldermalsen Gelderland 4191 PL + NL + +8C-E7-8C (hex) DK Networks +8CE78C (base 16) DK Networks + 20F-3, No.689, Zhong-Zheng Road, Zhong-He Dist. + New Taipei City Taiwan 235 + TW + +54-51-46 (hex) AMG Systems Ltd. +545146 (base 16) AMG Systems Ltd. + 3 The Omega Centre + Biggleswade Bedfordshire SG18 8QB + GB + +84-63-D6 (hex) Microsoft Corporation +8463D6 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +EC-13-B2 (hex) Netonix +EC13B2 (base 16) Netonix + 6 East Main St + Leola PA 17540 + US + +10-4E-07 (hex) Shanghai Genvision Industries Co.,Ltd +104E07 (base 16) Shanghai Genvision Industries Co.,Ltd + 2/F Building E,NO.55,Luo Jin Road,MinHang District,Shanghai + Shanghai Shanghai 200237 + CN + +04-9B-9C (hex) Eadingcore Intelligent Technology Co., Ltd. +049B9C (base 16) Eadingcore Intelligent Technology Co., Ltd. + No. 169 Lijia city C District comprehensive 3 layer C3-10 mall,Five-One road + Fuzhou Fujian 350000 + CN + +84-26-90 (hex) BEIJING THOUGHT SCIENCE CO.,LTD. +842690 (base 16) BEIJING THOUGHT SCIENCE CO.,LTD. + 1-1102,Intermational Business Park,No.1 ShangDi Xinxi Rd,Haidian District,Beijing + beijing beijing 100085 + CN + +80-19-67 (hex) Shanghai Reallytek Information Technology Co.,Ltd +801967 (base 16) Shanghai Reallytek Information Technology Co.,Ltd + 906 Room,No.1 Building,No.3000 Longdong Avenue + Shanghai 201203 + CN + +2C-F7-F1 (hex) Seeed Technology Inc. +2CF7F1 (base 16) Seeed Technology Inc. + 5th Floor, 8th Building, Shiling industrial Park, XiLi Town, NanShan dist. Shenzhen + ShenZhen GuangDong 518055 + CN + +3C-1E-13 (hex) HANGZHOU SUNRISE TECHNOLOGY CO., LTD +3C1E13 (base 16) HANGZHOU SUNRISE TECHNOLOGY CO., LTD + No.9, LongTan Road, CangQian Town, YuHang District, Hangzhou, China + HangZhou ZheJiang 311121 + CN + +08-11-5E (hex) Bitel Co., Ltd. +08115E (base 16) Bitel Co., Ltd. + 9F Yohyun B/D, 242-29, Nonhyun-dong + Seoul Gangnam-gu 135830 + KR + +08-81-BC (hex) HongKong Ipro Technology Co., Limited +0881BC (base 16) HongKong Ipro Technology Co., Limited + Flat/Rm A3 9/F Silvercorp Int Tower + HONGKONG 999077 + HK + +C0-98-79 (hex) Acer Inc. +C09879 (base 16) Acer Inc. + 8F, 88, Sec.1, Xintai 5th Rd. + New Taipei City N/A 221 + TW + +B8-4F-D5 (hex) Microsoft Corporation +B84FD5 (base 16) Microsoft Corporation + 1 Microsoft Way + Redmond Washington 98052 + FI + +D8-4A-87 (hex) OI ELECTRIC CO.,LTD +D84A87 (base 16) OI ELECTRIC CO.,LTD + 7-3-16 KIKUNA + YOKOHAMA KANAGAWA-KEN 222-0011 + JP + +F0-3D-29 (hex) Actility +F03D29 (base 16) Actility + 110 rue des Poissonniers + Paris Paris 75018 + FR + +88-70-8C (hex) Lenovo Mobile Communication Technology Ltd. +88708C (base 16) Lenovo Mobile Communication Technology Ltd. + No.999, Qishan North 2nd Road, Information & Optoelectronics Park, + Xiamen Fujian 361006 + + +50-14-B5 (hex) Richfit Information Technology Co., Ltd +5014B5 (base 16) Richfit Information Technology Co., Ltd + Room 1501, Gehua Tower, Suite N0.1, Qinglong lane, Dongcheng District + Beijing Beijing 100007 + CN + +CC-3F-1D (hex) Intesis Software SL +CC3F1D (base 16) Intesis Software SL + Mila i Fontanals 1bis 1 + Igualada Barcelona 08700 + ES + +DC-DA-4F (hex) GETCK TECHNOLOGY, INC +DCDA4F (base 16) GETCK TECHNOLOGY, INC + Room 508, NO .48 ZhengYi road + SHANGHAI 200082 + CN + +10-12-18 (hex) Korins Inc. +101218 (base 16) Korins Inc. + Rm. 608, Suntechcity Bldg. + Seongnam Gyeonggi 462-725 + KR + +34-28-F0 (hex) ATN International Limited +3428F0 (base 16) ATN International Limited + 4210, Office Tower, Convention Plaza + Hong Kong Hong Kong 00000 + HK + +CC-10-A3 (hex) Beijing Nan Bao Technology Co., Ltd. +CC10A3 (base 16) Beijing Nan Bao Technology Co., Ltd. + Room 8476,Floor 8,Building 3 + Shijingshan District Beijing 100041 + CN + +5C-AA-FD (hex) Sonos, Inc. +5CAAFD (base 16) Sonos, Inc. + 614 Chapala St + Santa Barbara CA 93101 + US + +14-ED-E4 (hex) Kaiam Corporation +14EDE4 (base 16) Kaiam Corporation + 39677 Eureka Drive + Newark California 94560 + US + +D0-12-42 (hex) BIOS Corporation +D01242 (base 16) BIOS Corporation + 2-43-15 Tomigaya + Shibuya-ku TOKYO 151-0063 + JP + +60-36-96 (hex) The Sapling Company +603696 (base 16) The Sapling Company + 1633 Republic Rd + Huntingdon Valley PA 19006 + US + +54-FF-CF (hex) Mopria Alliance +54FFCF (base 16) Mopria Alliance + 2400 Camino Ramon, Ste #375 + San Ramon CA 94583 + US + +F4-F2-6D (hex) TP-LINK TECHNOLOGIES CO.,LTD. +F4F26D (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +40-4E-EB (hex) Higher Way Electronic Co., Ltd. +404EEB (base 16) Higher Way Electronic Co., Ltd. + No.15 Jingke E. Rd., Nantun District + Taichung 408 + TW + +C4-56-FE (hex) Lava International Ltd. +C456FE (base 16) Lava International Ltd. + Room 705, Block A, HengYue Building + Shanghai 518054 + CN + +AC-B7-4F (hex) METEL s.r.o. +ACB74F (base 16) METEL s.r.o. + Zizkuv Kopec 617 + Ceska Skalice NA 55203 + CZ + +C0-EE-FB (hex) OnePlus Tech (Shenzhen) Ltd +C0EEFB (base 16) OnePlus Tech (Shenzhen) Ltd + 18F Tairan Building C, Tairan 8th Road Chegongmiao, Futian + Shenzhen Guangdong 518040 + CN + +30-42-25 (hex) BURG-WÄCHTER KG +304225 (base 16) BURG-WÄCHTER KG + Altenhofer Weg 15 + Wetter NRW 58300 + DE + +FC-DB-B3 (hex) Murata Manufacturing Co., Ltd. +FCDBB3 (base 16) Murata Manufacturing Co., Ltd. + 1-10-1, Higashikotari + Nagaokakyo-shi Kyoto 617-8555 + JP + +CC-F5-38 (hex) 3isysnetworks +CCF538 (base 16) 3isysnetworks + 11F-2 No1247 , Jung Jeng RD , + Taipei Taiwan 0000 + TW + +B8-BD-79 (hex) TrendPoint Systems +B8BD79 (base 16) TrendPoint Systems + 1595 East 6th Street + Corona CA 92879 + US + +74-F4-13 (hex) Maxwell Forest +74F413 (base 16) Maxwell Forest + Level 2, 51 Murray Street + Pyrmont NSW 2009 + AU + +A0-06-27 (hex) NEXPA System +A00627 (base 16) NEXPA System + #105, YBS bldg,227-1 Yongdap-Dong + Seoul ASI/KR/KS013/SEOUL + KR + +30-33-35 (hex) Boosty +303335 (base 16) Boosty + 40 Princes Street + Ipswich Suffolk IP11RJ + GB + +44-74-6C (hex) Sony Mobile Communications Inc +44746C (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +4C-9E-FF (hex) Zyxel Communications Corporation +4C9EFF (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +BC-9C-C5 (hex) Beijing Huafei Technology Co., Ltd. +BC9CC5 (base 16) Beijing Huafei Technology Co., Ltd. + 2 floor, Research building, Guanghua Pioneer Park, No.18, Anningzhuang East Rd, Haidian District, Beijing, China. + Beijing Beijing 100085 + CN + +5C-B8-CB (hex) Allis Communications +5CB8CB (base 16) Allis Communications + 10F.-3,No.31-1, Lane 169 Kangning St., + New Taipei City New Taipei City 221 + TW + +34-F0-CA (hex) Shenzhen Linghangyuan Digital Technology Co.,Ltd. +34F0CA (base 16) Shenzhen Linghangyuan Digital Technology Co.,Ltd. + Building R, Linghangyuan Industrial Park, No. 163 Banxuegang Road, Longgang Distrial, Shenzhen, China + Shenzhen Guangdong 518129 + CN + +70-72-0D (hex) Lenovo Mobile Communication Technology Ltd. +70720D (base 16) Lenovo Mobile Communication Technology Ltd. + No.999, Qishan North 2nd Road, Information & Optoelectronics Park, Torch Hi-tech Industry Development Zone, Xiamen, P.R.China + Xiamen Fujian 361000 + CN + +3C-CD-5A (hex) Technische Alternative GmbH +3CCD5A (base 16) Technische Alternative GmbH + Langestr. 124 + Amaliendorf Lower Austria A-3872 + AT + +FC-AA-14 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +FCAA14 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + Pin-Jen City, Taoyuan, Taiwan, R.O.C. + Pin-Jen Taoyuan 324 + TW + +94-D6-0E (hex) shenzhen yunmao information technologies co., ltd +94D60E (base 16) shenzhen yunmao information technologies co., ltd + H4-3A, Twelve Oaks Manor, bulong road + shenzhen guanggong 518127 + CN + +74-8F-4D (hex) MEN Mikro Elektronik GmbH +748F4D (base 16) MEN Mikro Elektronik GmbH + Neuwieder Str. 3 - 7 + Nuernberg Bavaria 90411 + DE + +50-67-87 (hex) Planet Networks +506787 (base 16) Planet Networks + 1 Ivy Crest Ln + Rockaway NJ 07866 + US + +8C-BF-9D (hex) Shanghai Xinyou Information Technology Ltd. Co. +8CBF9D (base 16) Shanghai Xinyou Information Technology Ltd. Co. + 905,418 Guiqing Road, Xuhui District, + Shanghai Shanghai 200233 + CN + +9C-AD-97 (hex) Hon Hai Precision Ind. Co.,Ltd. +9CAD97 (base 16) Hon Hai Precision Ind. Co.,Ltd. + Building D21,No.1, East Zone 1st Road + Chongqing Chongqing 401332 + CN + +88-29-50 (hex) Netmoon Technology Co., Ltd +882950 (base 16) Netmoon Technology Co., Ltd + 2nd Floor, Building No.1, NO.319, Qingpi Avenue + Wenjiang District Chengdu 611130 + CN + +7C-E5-24 (hex) Quirky, Inc. +7CE524 (base 16) Quirky, Inc. + 606 W 28th Street + New York NY 10001 + US + +F4-D2-61 (hex) SEMOCON Co., Ltd +F4D261 (base 16) SEMOCON Co., Ltd + B-19F, Gunpo IT Valley, Dangjeong-dong, 17, Gosan-ro 148beon-gil, + Gunpo-si Gyeonggi-do 435-833 + KR + +48-D8-55 (hex) Telvent +48D855 (base 16) Telvent + P.I. Alcobendas c/ Valgrande. 6 + Alcobendas Madrid 28108 + ES + +08-F7-28 (hex) GLOBO Multimedia Sp. z o.o. Sp.k. +08F728 (base 16) GLOBO Multimedia Sp. z o.o. Sp.k. + Gryfinska 104 + Szczecin Zachodniopomorskie 70-772 + PL + +20-6E-9C (hex) Samsung Electronics Co.,Ltd +206E9C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +6C-2F-2C (hex) Samsung Electronics Co.,Ltd +6C2F2C (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +B0-09-D3 (hex) Avizia +B009D3 (base 16) Avizia + 12018 Sunrise Valley Drive + Reston VA 20191 + US + +60-C1-CB (hex) Fujian Great Power PLC Equipment Co.,Ltd +60C1CB (base 16) Fujian Great Power PLC Equipment Co.,Ltd + 6/F.Bld.34.Zone C.Software Park + Fuzhou Fujian,China 350003 + CN + +BC-25-F0 (hex) 3D Display Technologies Co., Ltd. +BC25F0 (base 16) 3D Display Technologies Co., Ltd. + 4F., No.542-17, Zhongzheng Rd + New Taipei City 242 + TW + +C0-3D-46 (hex) Shanghai Sango Network Technology Co.,Ltd +C03D46 (base 16) Shanghai Sango Network Technology Co.,Ltd + No 666 Zhangheng Road + Pudong Shanghai 210203 + CN + +64-EA-C5 (hex) SiboTech Automation Co., Ltd. +64EAC5 (base 16) SiboTech Automation Co., Ltd. + 5th Floor, Bld 3 + Shanghai Shanghai 201612 + CN + +30-F7-D7 (hex) Thread Technology Co., Ltd +30F7D7 (base 16) Thread Technology Co., Ltd + 4F, A Block, CYG, No.2,Mid GaoXin + Shenzhen GuangDong 518055 + CN + +18-22-7E (hex) Samsung Electronics Co.,Ltd +18227E (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +30-C7-AE (hex) Samsung Electronics Co.,Ltd +30C7AE (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +44-D4-E0 (hex) Sony Mobile Communications Inc +44D4E0 (base 16) Sony Mobile Communications Inc + 4-12-3 Higashi – Shinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +FC-D5-D9 (hex) Shenzhen SDMC Technology Co., Ltd. +FCD5D9 (base 16) Shenzhen SDMC Technology Co., Ltd. + 7/F,Block A,Huahan Bldg., + Shenzhen GuangDong 518000 + CN + +74-DA-38 (hex) Edimax Technology Co. Ltd. +74DA38 (base 16) Edimax Technology Co. Ltd. + No. 278, Xinhu 1st Road + Taipei City Neihu Dist 248 + TW + +E4-F4-C6 (hex) NETGEAR +E4F4C6 (base 16) NETGEAR + 350 East Plumeria Drive + San Jose CA 95134 + US + +CC-A0-E5 (hex) DZG Metering GmbH +CCA0E5 (base 16) DZG Metering GmbH + Heidelberger Str. 32 + Oranienburg Brandenburg 16515 + DE + +60-81-2B (hex) Custom Control Concepts +60812B (base 16) Custom Control Concepts + 6020 S 190th ST + Kent Washington 98032 + US + +1C-1C-FD (hex) Dalian Hi-Think Computer Technology, Corp +1C1CFD (base 16) Dalian Hi-Think Computer Technology, Corp + Hi-Think Software Building,No.6 Hi-Tech Street, Qixianling Industrial Base, Hi-Tech Zone, Dalian, China + Dalian LiaoNing 116023 + CN + +90-AE-1B (hex) TP-LINK TECHNOLOGIES CO.,LTD. +90AE1B (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +60-E3-27 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +60E327 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +48-D1-8E (hex) Metis Communication Co.,Ltd +48D18E (base 16) Metis Communication Co.,Ltd + #102-805 Digital Empire2 + Suwon-Si GyeongGi-Do 443-734 + KR + +F8-66-01 (hex) Suzhou Chi-tek information technology Co., Ltd +F86601 (base 16) Suzhou Chi-tek information technology Co., Ltd + Rm204C、204D, Building A7, + SuZhou Jiangsu 215123 + CN + +14-56-45 (hex) Savitech Corp. +145645 (base 16) Savitech Corp. + 3F, No.309, Guangming 1st Rd., + Zhubei Hsinchu 30259 + TW + +70-62-B8 (hex) D-Link International +7062B8 (base 16) D-Link International + 1 Internal Business Park, #03-12,The Synergy, Singapore + Singapore Singapore 609917 + SG + +AC-A9-19 (hex) TrekStor GmbH +ACA919 (base 16) TrekStor GmbH + Kastanienallee 8-10 + Lorsch Hessen 64653 + DE + +B0-25-AA (hex) Private +B025AA (base 16) Private + +D4-B4-3E (hex) Messcomp Datentechnik GmbH +D4B43E (base 16) Messcomp Datentechnik GmbH + Neudecker Str. 11 + Wasserburg Bayern 83512 + DE + +94-C0-14 (hex) Sorter Sp. j. Konrad Grzeszczyk MichaA, Ziomek +94C014 (base 16) Sorter Sp. j. Konrad Grzeszczyk MichaA, Ziomek + ul. Gdynska 32 + PL9482565081 Mazowieckie 26-600 + PL + +9C-FB-F1 (hex) MESOMATIC GmbH & Co.KG +9CFBF1 (base 16) MESOMATIC GmbH & Co.KG + Siemensstr. 36 + Kernen i.R. 71394 + DE + +10-27-BE (hex) TVIP +1027BE (base 16) TVIP + 190000 ul. Decabristov, h.6 А, of.10-Н + Saint-Petersburg 197227 + RU + +20-87-AC (hex) AES motomation +2087AC (base 16) AES motomation + 48501 Warm Springs Blvd. + Fremont CA 94539 + US + +70-93-83 (hex) Intelligent Optical Network High Tech CO.,LTD. +709383 (base 16) Intelligent Optical Network High Tech CO.,LTD. + Room 205,Building 11,Jia + Changping District Beijing 102200 + CN + +80-D4-33 (hex) LzLabs GmbH +80D433 (base 16) LzLabs GmbH + Alte Winterthurerstrasse 14B + Wallisellen Zurich 8304 + CH + +B0-DA-00 (hex) CERA ELECTRONIQUE +B0DA00 (base 16) CERA ELECTRONIQUE + PARC D'ACTIVITES + VAL DE REUIL HAUTE NORMANDIE 27100 + FR + +1C-AB-01 (hex) Innovolt +1CAB01 (base 16) Innovolt + 14 Piedmont Center + Atlanta GA 30305 + US + +D8-B6-D6 (hex) Blu Tether Limited +D8B6D6 (base 16) Blu Tether Limited + 7600 Leesburg Pike + Falls Church VA 22043 + US + +6C-2C-06 (hex) OOO NPP Systemotechnika-NN +6C2C06 (base 16) OOO NPP Systemotechnika-NN + Nartova lane, 2v + Nizhny Novgorod Nizhegorodskaya oblast 603057 + RU + +C4-91-3A (hex) Shenzhen Sanland Electronic Co., ltd. +C4913A (base 16) Shenzhen Sanland Electronic Co., ltd. + 3 floor,Block D, Glory Technology Industrial Park, + ShenZhen Guangdong 518116 + CN + +68-85-6A (hex) OuterLink Corporation +68856A (base 16) OuterLink Corporation + 187 Ballardvale St., Ste. A260 + Wilmington MA 01887 + US + +94-51-BF (hex) Hyundai ESG +9451BF (base 16) Hyundai ESG + Gangnam-gu + Seoul KOREA, REPUBLIC OF 135-845 + KR + +F0-15-A0 (hex) KyungDong One Co., Ltd. +F015A0 (base 16) KyungDong One Co., Ltd. + 205-38, Gasan digital 1-ro, + Seoul 153-803 + KR + +C4-4E-1F (hex) BlueN +C44E1F (base 16) BlueN + 121-122 3F + Daegu Korea 700-809 + KR + +B0-86-9E (hex) Chloride S.r.L +B0869E (base 16) Chloride S.r.L + Via Fornace ,30 + CastelGuelfo (Bologna) Italy 40023 + IT + +D0-57-A1 (hex) Werma Signaltechnik GmbH & Co. KG +D057A1 (base 16) Werma Signaltechnik GmbH & Co. KG + Duerbheimer Strasse + Rietheim-Weilheim 78604 + DE + +B4-B5-42 (hex) Hubbell Power Systems, Inc. +B4B542 (base 16) Hubbell Power Systems, Inc. + 8100 Churchill Ave + Leeds AL 35094 + US + +54-CD-EE (hex) ShenZhen Apexis Electronic Co.,Ltd +54CDEE (base 16) ShenZhen Apexis Electronic Co.,Ltd + 12th floor,Keji BuildiHigng + ShenZhen GuangDong 518057 + CN + +88-E8-F8 (hex) YONG TAI ELECTRONIC (DONGGUAN) LTD. +88E8F8 (base 16) YONG TAI ELECTRONIC (DONGGUAN) LTD. + Yuan Shan Bei Managed Region + Dong Guan Guang Dong 523583 + CN + +90-98-64 (hex) Impex-Sat GmbH&Co KG +909864 (base 16) Impex-Sat GmbH&Co KG + Beim Giesshaus 7 + Glueckstadt 25348 + DE + +DC-E5-78 (hex) Experimental Factory of Scientific Engineering and Special Design Department +DCE578 (base 16) Experimental Factory of Scientific Engineering and Special Design Department + 9, Academician Semenov prospect + Chernogolovka Moscow region 142432 + RU + +D8-65-95 (hex) Toy's Myth Inc. +D86595 (base 16) Toy's Myth Inc. + 304, Yongsan-gu Changup-Jiwon center + Seoul 140-240 + KR + +F4-B5-2F (hex) Juniper Networks +F4B52F (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +C0-F7-9D (hex) Powercode +C0F79D (base 16) Powercode + 300 Industrial Dr + Random Lake Wisconsin 53075 + US + +C4-C9-19 (hex) Energy Imports Ltd +C4C919 (base 16) Energy Imports Ltd + 306a Broadway Ave + Palmerston North Manawatu 4414 + NZ + +38-F0-98 (hex) Vapor Stone Rail Systems +38F098 (base 16) Vapor Stone Rail Systems + 10000 Cavendish + Saint-Laurent Quebec H4M2V1 + CA + +64-E8-92 (hex) Morio Denki Co., Ltd. +64E892 (base 16) Morio Denki Co., Ltd. + 2, Nadooka + Ryugasaki Ibaraki 301-0845 + JP + +D8-DD-5F (hex) BALMUDA Inc. +D8DD5F (base 16) BALMUDA Inc. + 5-1-21 Kyonancho + Musashino Tokyo 180-0023 + JP + +D8-61-94 (hex) Objetivos y Sevicios de Valor Añadido +D86194 (base 16) Objetivos y Sevicios de Valor Añadido + Calle Monte Esquinza 28, 1ºD + Madrid 28010 + ES + +E8-FC-60 (hex) ELCOM Innovations Private Limited +E8FC60 (base 16) ELCOM Innovations Private Limited + 9TH FLOOR, MERIDIEN COMMERCIAL TOWER + New Delhi 110001 + US + +58-9C-FC (hex) FreeBSD Foundation +589CFC (base 16) FreeBSD Foundation + P.O. Box 20247 + Boulder CO 80308-3247 + US + +70-2C-1F (hex) Wisol +702C1F (base 16) Wisol + 377-3, Gajang-dong, Osan-si + 447-210 + KR + +C8-D4-29 (hex) Muehlbauer AG +C8D429 (base 16) Muehlbauer AG + Josef-Mühlbauer-Platz 1 + Roding Bavaria 93426 + DE + +F8-5C-45 (hex) IC Nexus Co. Ltd. +F85C45 (base 16) IC Nexus Co. Ltd. + 6F-1, No.3-2 Park Street + Taipei 115 + TW + +AC-E0-69 (hex) ISAAC Instruments +ACE069 (base 16) ISAAC Instruments + 240 Frechette + Chambly Quebec J3L2Z5 + CA + +30-B5-C2 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +30B5C2 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +E0-7F-53 (hex) TECHBOARD SRL +E07F53 (base 16) TECHBOARD SRL + Via Della Scienza, 50 + Modena 41122 + IT + +48-FE-EA (hex) HOMA B.V. +48FEEA (base 16) HOMA B.V. + P.O. Box 545 + Enschede 7500 AM + NL + +E8-EA-6A (hex) StarTech.com +E8EA6A (base 16) StarTech.com + 45 Artisans Cres + London Ontario N5V5E9 + CA + +04-DB-8A (hex) Suntech International Ltd. +04DB8A (base 16) Suntech International Ltd. + Room 605, IT Mirae Tower + Seoul 153-760 + KR + +90-DF-B7 (hex) s.m.s smart microwave sensors GmbH +90DFB7 (base 16) s.m.s smart microwave sensors GmbH + In den Waashainen 1 + Braunschweig NI 38108 + DE + +08-57-00 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +085700 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +FC-27-A2 (hex) TRANS ELECTRIC CO., LTD. +FC27A2 (base 16) TRANS ELECTRIC CO., LTD. + 771,Sec.2 Chungsan Rd,Huatang + Changhua Taiwan 503 + TW + +FC-BB-A1 (hex) Shenzhen Minicreate Technology Co.,Ltd +FCBBA1 (base 16) Shenzhen Minicreate Technology Co.,Ltd + 5/F.,5th,Building,Animation Park,Yuehai Road + Shenzhen Guangdong 518066 + CN + +F0-8A-28 (hex) JIANGSU HENGSION ELECTRONIC S and T CO.,LTD +F08A28 (base 16) JIANGSU HENGSION ELECTRONIC S and T CO.,LTD + 4F,Building 3 + ChangZhou Jiangsu 213125 + CN + +28-BB-59 (hex) RNET Technologies, Inc. +28BB59 (base 16) RNET Technologies, Inc. + 240. W. Elmwood Dr. + Dayton OHIO 45459-4248 + US + +24-26-42 (hex) SHARP Corporation. +242642 (base 16) SHARP Corporation. + 22-22,Abeno-ku + Osaka-City Osaka-Prefecture 545-8522 + JP + +34-DE-34 (hex) zte corporation +34DE34 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +FC-16-07 (hex) Taian Technology(Wuxi) Co.,Ltd. +FC1607 (base 16) Taian Technology(Wuxi) Co.,Ltd. + Gaolang East Road No.29 + Wuxi Jiangsu 214000 + CN + +AC-02-CA (hex) HI Solutions, Inc. +AC02CA (base 16) HI Solutions, Inc. + 4105 Royal Drive + Kennesaw GA 30144 + US + +74-6F-3D (hex) Contec GmbH +746F3D (base 16) Contec GmbH + Oberahrer Straße 9 + Sainerholz RP 56244 + DE + +4C-0D-EE (hex) JABIL CIRCUIT (SHANGHAI) LTD. +4C0DEE (base 16) JABIL CIRCUIT (SHANGHAI) LTD. + FL5-UNIT A2 NO 1528 GUMEI ROAD + SHANGHAI 200233 + CN + +D0-63-4D (hex) Meiko Maschinenbau GmbH & Co. KG +D0634D (base 16) Meiko Maschinenbau GmbH & Co. KG + Englerstraße 3 + Offenburg 77652 + DE + +00-8B-43 (hex) RFTECH +008B43 (base 16) RFTECH + Cheoin-gu + Yongin Gyeonggi 449-871 + KR + +8C-41-F2 (hex) RDA Technologies Ltd. +8C41F2 (base 16) RDA Technologies Ltd. + Suite 2203, CC Wu Building, + WanChai Hong Kong 00000 + HK + +E0-36-E3 (hex) Stage One International Co., Ltd. +E036E3 (base 16) Stage One International Co., Ltd. + Fl. 5., No. 10., Lane 321, Yangguang St., + Taipei City 11491 + TW + +DC-05-2F (hex) National Products Inc. +DC052F (base 16) National Products Inc. + 8410 Dallas Ave S. + Seattle WA 98108 + US + +D0-BD-01 (hex) DS International +D0BD01 (base 16) DS International + 806ho, ACE HITECH21 B/D + Busan Busan 612-020 + KR + +8C-DE-99 (hex) Comlab Inc. +8CDE99 (base 16) Comlab Inc. + 2300 Leon-Harmel, suite 220 + Quebec Quebec G1N 4L2 + CA + +4C-E1-BB (hex) Zhuhai HiFocus Technology Co., Ltd. +4CE1BB (base 16) Zhuhai HiFocus Technology Co., Ltd. + The second floor of the friend industrial park, + zhuhai guangdong 519080 + US + +24-A8-7D (hex) Panasonic Automotive Systems Asia Pacific(Thailand)Co.,Ltd. +24A87D (base 16) Panasonic Automotive Systems Asia Pacific(Thailand)Co.,Ltd. + 101 Moo 2 Teparak Road , + Bangsaothong Samutprakarn 10540 + TH + +EC-71-DB (hex) Shenzhen Baichuan Digital Technology Co., Ltd. +EC71DB (base 16) Shenzhen Baichuan Digital Technology Co., Ltd. + Room 602, Complex Building, Tsinghua High-Tech Park + Shenzhen Guangdong 518000 + CN + +A4-09-CB (hex) Alfred Kaercher GmbH & Co KG +A409CB (base 16) Alfred Kaercher GmbH & Co KG + Alfred Kaercher Gmbh & Co KG + Winnenden Baden-Wuerttemberg 71364 + DE + +8C-56-9D (hex) Imaging Solutions Group +8C569D (base 16) Imaging Solutions Group + 1387 Fairport Rd + Fairport NY 14450 + US + +40-B6-B1 (hex) SUNGSAM CO,.Ltd +40B6B1 (base 16) SUNGSAM CO,.Ltd + SUNGSAM Bldg, 7-1, BAnga-ro 23beon-gil, Bundang-gu + Seongnam-si Gyeonggi-do 463-829 + KR + +84-FE-9E (hex) RTC Industries, Inc. +84FE9E (base 16) RTC Industries, Inc. + 2800 Golf Road + Rolling Meadows IL 60008 + US + +FC-4B-1C (hex) INTERSENSOR S.R.L. +FC4B1C (base 16) INTERSENSOR S.R.L. + 101 Bd. Iuliu Maniu str., Bl. A2, Sc. 2, #47 + Bucharest 061094 + RO + +40-30-67 (hex) Conlog (Pty) Ltd +403067 (base 16) Conlog (Pty) Ltd + 270 Felix Dlamini Road + Durban Kwa-zulu Natal 4000 + ZA + +E8-61-83 (hex) Black Diamond Advanced Technology, LLC +E86183 (base 16) Black Diamond Advanced Technology, LLC + 7450 S. Priest Drive + Tempe AZ 85283 + US + +38-C9-A9 (hex) SMART High Reliability Solutions, Inc. +38C9A9 (base 16) SMART High Reliability Solutions, Inc. + 1325 N Fiesta Blvd., #101 + Gilbert AZ 85233 + US + +50-1A-C5 (hex) Microsoft +501AC5 (base 16) Microsoft + 1 Microsoft Way + Redmond Washington 98052 + US + +B0-98-9F (hex) LG CNS +B0989F (base 16) LG CNS + 53-94 Jinwisandan-ro, Jinwuy-Myun + Pyungtaek-City Kyunggi-Do 451-862 + KR + +C0-F1-C4 (hex) Pacidal Corporation Ltd. +C0F1C4 (base 16) Pacidal Corporation Ltd. + 3F., No. 11, Aly 3, Ln. 123, Sec. 3 Ren'ai Rd. + Taipei City 106 + TW + +60-03-47 (hex) Billion Electric Co. Ltd. +600347 (base 16) Billion Electric Co. Ltd. + 8F., No.192, Sec. 2, Zhongxing Rd., + New Taipei City, 231 + TW + +F0-D3-A7 (hex) CobaltRay Co., Ltd +F0D3A7 (base 16) CobaltRay Co., Ltd + Room 409,Humanteco Building,#281-16 + Seoul 133120 + KR + +38-A5-3C (hex) COMECER Netherlands +38A53C (base 16) COMECER Netherlands + Madame Curieweg 1 + Joure Friesland 8500 AC + NL + +5C-FF-FF (hex) Shenzhen Kezhonglong Optoelectronic Technology Co., Ltd +5CFFFF (base 16) Shenzhen Kezhonglong Optoelectronic Technology Co., Ltd + 3/F, B5 Building, Xinfu Industrial Park, Heping Village + Shenzhen, Guangdong 518101 + US + +08-52-40 (hex) EbV Elektronikbau- und Vertriebs GmbH +085240 (base 16) EbV Elektronikbau- und Vertriebs GmbH + Heisterner Weg 8 - 12 + Burbach Nordrhein-Westfalen 57299 + DE + +B8-C1-A2 (hex) Dragon Path Technologies Co., Limited +B8C1A2 (base 16) Dragon Path Technologies Co., Limited + 12/F., San Toi Building, + Central Hong Kong + HK + +80-F2-5E (hex) Kyynel +80F25E (base 16) Kyynel + Pirttikuja 3 + Oulu 90450 + FI + +68-69-2E (hex) Zycoo Co.,Ltd +68692E (base 16) Zycoo Co.,Ltd + F7,B7,Tianfu Software park + Chengdu Sichuan 610000 + CN + +D4-68-67 (hex) Neoventus Design Group +D46867 (base 16) Neoventus Design Group + 2350 Commonwealth Dr, Suite E + Charlottesville VA 22901 + US + +2C-18-AE (hex) Trend Electronics Co., Ltd. +2C18AE (base 16) Trend Electronics Co., Ltd. + 4F-3, No 17, Lane 77, Sec. 2 + Taipei Taiwan 10446 + TW + +F8-1C-E5 (hex) Telefonbau Behnke GmbH +F81CE5 (base 16) Telefonbau Behnke GmbH + Robert-Jungk-Str. 3 + Kirkel Saarland 66459 + DE + +88-91-66 (hex) Viewcooper Corp. +889166 (base 16) Viewcooper Corp. + Room 1061, A,Seven Block, No.128 Huayuan Rd + SHANGHAI 200083 + CN + +10-33-78 (hex) FLECTRON Co., LTD +103378 (base 16) FLECTRON Co., LTD + A-625, Sigma2, Tancheonsang-ro 164 + Seongnam-si Gyeonggi-do 463-741 + KR + +14-ED-A5 (hex) Wächter GmbH Sicherheitssysteme +14EDA5 (base 16) Wächter GmbH Sicherheitssysteme + Alte Ricklinger Str. 3 + Hannover Garbsen 30823 + DE + +50-C0-06 (hex) Carmanah Signs +50C006 (base 16) Carmanah Signs + #5 6025 12 Street SE + Calgary Alberta T2H2K1 + CA + +04-CB-1D (hex) Traka plc +04CB1D (base 16) Traka plc + 30 Stilebrook Road + Bucks Buckinghamshire MK46 5EA + GB + +A4-E9-A3 (hex) Honest Technology Co., Ltd +A4E9A3 (base 16) Honest Technology Co., Ltd + 5F, KyungDong Bldg. 906-5, + Daejeon 305-330 + KR + +A0-E5-E9 (hex) enimai Inc +A0E5E9 (base 16) enimai Inc + 701 Villa St + Mountain View California 94041 + US + +9C-21-6A (hex) TP-LINK TECHNOLOGIES CO.,LTD. +9C216A (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +F8-62-AA (hex) xn systems +F862AA (base 16) xn systems + #917, Worldmerdian 2nd + Seoul 153759 + KR + +10-7B-EF (hex) Zyxel Communications Corporation +107BEF (base 16) Zyxel Communications Corporation + No. 6 Innovation Road II, Science Park + Hsichu Taiwan 300 + TW + +B4-62-AD (hex) Elysia Germany GmbH +B462AD (base 16) Elysia Germany GmbH + Benzstr.4 + Straubenhardt Baden-Wuerttemberg 75334 + DE + +34-5C-40 (hex) Cargt Holdings LLC +345C40 (base 16) Cargt Holdings LLC + 8820 Hillside Dr + Lenexa KANSAS (KS) 66227 + US + +68-19-3F (hex) Digital Airways +68193F (base 16) Digital Airways + 5, Place Jean SIARD + ARGENTAN NORMANDY 61200 + FR + +B4-75-0E (hex) Belkin International Inc. +B4750E (base 16) Belkin International Inc. + 12045 East Waterfront Drive + Playa Vista Ca. 90094 + US + +94-10-3E (hex) Belkin International Inc. +94103E (base 16) Belkin International Inc. + 12045 East Waterfront Drive + Playa Vista Ca. 90094 + US + +7C-B7-33 (hex) ASKEY COMPUTER CORP +7CB733 (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +30-51-F8 (hex) BYK-Gardner GmbH +3051F8 (base 16) BYK-Gardner GmbH + Lausitzer Strasse 8 + Geretsried Bavarian 82538 + DE + +E8-F2-26 (hex) MILLSON CUSTOM SOLUTIONS INC. +E8F226 (base 16) MILLSON CUSTOM SOLUTIONS INC. + 2036 COLUMBIA STREET + VANCOUVER BRITISH COLUMBIA V5Y 3E1 + CA + +44-EE-30 (hex) Budelmann Elektronik GmbH +44EE30 (base 16) Budelmann Elektronik GmbH + Von-Renesse-Weg 60 + Muenster North Rhine-Westphalia 48163 + DE + +FC-1E-16 (hex) IPEVO corp +FC1E16 (base 16) IPEVO corp + 3F,No.53,Bo-ai Road,Taipei 100,Taiwan + Taipei 10044 + TW + +3C-6E-63 (hex) Mitron OY +3C6E63 (base 16) Mitron OY + Yrittäjankaari 19 + FORSSA Kanta-Hame 30420 + FI + +A4-05-9E (hex) STA Infinity LLP +A4059E (base 16) STA Infinity LLP + WINNINGTON HOUSE + London N12 0DR + GB + +A0-BF-50 (hex) S.C. ADD-PRODUCTION S.R.L. +A0BF50 (base 16) S.C. ADD-PRODUCTION S.R.L. + 36, Dragomirna str. + Chisinau MD-2008 + MD + +E8-D4-E0 (hex) Beijing BenyWave Technology Co., Ltd. +E8D4E0 (base 16) Beijing BenyWave Technology Co., Ltd. + No.55, Jiachuang Road, Taihu Town + Beijing 101111 + CN + +FC-01-9E (hex) VIEVU +FC019E (base 16) VIEVU + 105 W. John St + Seattle WA 98119 + US + +64-21-84 (hex) Nippon Denki Kagaku Co.,LTD +642184 (base 16) Nippon Denki Kagaku Co.,LTD + Nishino Gotochou 18 + Kyoto City Kyoto Pref 607-8356 + JP + +24-64-EF (hex) CYG SUNRI CO.,LTD. +2464EF (base 16) CYG SUNRI CO.,LTD. + No. 3, Langshan 1st Road, North Area of Hi-Tech Industrial Park + Shenzhen Guangdong 518057 + CN + +D8-27-0C (hex) MaxTronic International Co., Ltd. +D8270C (base 16) MaxTronic International Co., Ltd. + 4F., No.529, Zhongzheng Rd., Xindian Dist. + New Taipei City Taiwan 231 + TW + +B4-CC-E9 (hex) PROSYST +B4CCE9 (base 16) PROSYST + 2C Rue de l' EPINOY + TEMPLEMARS 59175 + FR + +C4-D6-55 (hex) Tercel technology co.,ltd +C4D655 (base 16) Tercel technology co.,ltd + Huafa South Road, Futian District, + SHENZHEN GUANGDONG 518000 + CN + +58-BD-F9 (hex) Sigrand +58BDF9 (base 16) Sigrand + UNIT 602 6/F, Causeway Bay Comm Bldg, + Hong Kong 999077 + HK + +C0-C6-87 (hex) Cisco SPVTG +C0C687 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +C4-93-80 (hex) Speedytel technology +C49380 (base 16) Speedytel technology + ROOM 1103,HANG SENG MONGKOK BUILDING,677 NATHAN ROAD,MONGKOK,KOWLOON + HONG KONG HONG KONG + HK + +00-7D-FA (hex) Volkswagen Group of America +007DFA (base 16) Volkswagen Group of America + 3800 Hamlin Rd + Auburn Hills MI 48326 + US + +2C-71-55 (hex) HiveMotion +2C7155 (base 16) HiveMotion + 1806, STX-V Tower + Seoul 153-803 + KR + +20-18-0E (hex) Shenzhen Sunchip Technology Co., Ltd +20180E (base 16) Shenzhen Sunchip Technology Co., Ltd + Room 818-831, Building B1, Mingyou Purchasing Center, Bao'an District, Shenzhen, China + Shenzhen Guangdong 518101 + CN + +80-B2-19 (hex) ELEKTRON TECHNOLOGY UK LIMITED +80B219 (base 16) ELEKTRON TECHNOLOGY UK LIMITED + BROERS BUILDING, + CAMBRIDGE CAMBS CB3 0FA + US + +E0-AE-B2 (hex) Bender GmbH & Co.KG +E0AEB2 (base 16) Bender GmbH & Co.KG + Londorfer Straße 65 + Grünberg Hessen 35305 + DE + +F8-4A-7F (hex) Innometriks Inc +F84A7F (base 16) Innometriks Inc + 3654 Ocean Ranch Blvd + Oceanside Ca 92056 + US + +74-A4-B5 (hex) Powerleader Science and Technology Co. Ltd. +74A4B5 (base 16) Powerleader Science and Technology Co. Ltd. + Powerleader Technology Park, #3 Guanyi Rd. + Shenzhen Guangdong 518110 + CN + +90-9F-43 (hex) Accutron Instruments Inc. +909F43 (base 16) Accutron Instruments Inc. + 11 Mary Street + Sudbury Ontario P3C1B4 + CA + +28-94-AF (hex) Samhwa Telecom +2894AF (base 16) Samhwa Telecom + 293-7, Doksan-dong + Seoul Seoul 153-813 + KR + +AC-50-36 (hex) Pi-Coral Inc +AC5036 (base 16) Pi-Coral Inc + 2130 Gold St + San Jose CA 95002-1177 + US + +0C-9B-13 (hex) Shanghai Magic Mobile Telecommunication Co.Ltd. +0C9B13 (base 16) Shanghai Magic Mobile Telecommunication Co.Ltd. + B7 parts, second floor + Waigaoqiao Free Trade Zone Shanghai 200131 + CN + +94-BF-1E (hex) eflow Inc. / Smart Device Planning and Development Division +94BF1E (base 16) eflow Inc. / Smart Device Planning and Development Division + Ryoka-Yoyogi building 3F + Shibuya-Ku TOKYO 151-0051 + JP + +E8-51-6E (hex) TSMART Inc. +E8516E (base 16) TSMART Inc. + The-O-valley 306, + Anyang-si Gyeonggi-do 431-080 + KR + +AC-22-0B (hex) ASUSTek COMPUTER INC. +AC220B (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +B8-87-A8 (hex) Step Ahead Innovations Inc. +B887A8 (base 16) Step Ahead Innovations Inc. + 20 Wintersport Ln. + Williston VT 05495 + US + +E0-A1-98 (hex) NOJA Power Switchgear Pty Ltd +E0A198 (base 16) NOJA Power Switchgear Pty Ltd + 16 Archimedes Place + Murarrie QLD 4172 + AU + +88-35-4C (hex) Transics +88354C (base 16) Transics + p/a Ter Waarde 91 + Ieper 8900 + BE + +3C-61-04 (hex) Juniper Networks +3C6104 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +CC-4A-E1 (hex) fourtec -Fourier Technologies +CC4AE1 (base 16) fourtec -Fourier Technologies + 16 Hamelacha St. POB 11681 + Rosh Ha’ayin 48091 + IL + +8C-4B-59 (hex) 3D Imaging & Simulations Corp +8C4B59 (base 16) 3D Imaging & Simulations Corp + 815, Timnip-Dong, Yuseong-Gu + Daejeon 305510 + KR + +5C-33-27 (hex) Spazio Italia srl +5C3327 (base 16) Spazio Italia srl + Via G.Galilei, 50 + Padenghe sul Garda BS 25080 + IT + +50-76-91 (hex) Tekpea, Inc. +507691 (base 16) Tekpea, Inc. + 2225 East Bayshore Road + Palo Alto California 94303 + US + +28-F5-32 (hex) ADD-Engineering BV +28F532 (base 16) ADD-Engineering BV + P.O. BOX 5893 + ROTTERDAM ZH 3008 AW + NL + +94-40-A2 (hex) Anywave Communication Technologies, Inc. +9440A2 (base 16) Anywave Communication Technologies, Inc. + 300 Knightsbridge Parkway, Suite 150 + Lincolnshire IL 60069 + US + +1C-86-AD (hex) MCT CO., LTD. +1C86AD (base 16) MCT CO., LTD. + C-815/816, Garden5 Works, 52 Chungmin-ro + Songpa-gu Seoul 138-961 + KR + +28-D9-3E (hex) Telecor Inc. +28D93E (base 16) Telecor Inc. + 6205 Kestrel Road + Mississauga Ontario L5T 2A1 + CA + +64-0B-4A (hex) Digital Telecom Technology Limited +640B4A (base 16) Digital Telecom Technology Limited + 1708 Nan Fung Tower, + 00852 + US + +38-42-33 (hex) Wildeboer Bauteile GmbH +384233 (base 16) Wildeboer Bauteile GmbH + Marker Weg 11 + Weener Niedersachsen 26826 + US + +3C-8A-B0 (hex) Juniper Networks +3C8AB0 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +C0-34-B4 (hex) Gigastone Corporation +C034B4 (base 16) Gigastone Corporation + 12F.NO 480. Rueiguang Rd. + Taipei 11492 + TW + +CC-E8-AC (hex) SOYEA Technology Co.,Ltd. +CCE8AC (base 16) SOYEA Technology Co.,Ltd. + STB department,Floor 4,Building 11 south + hangzhou zhejiang 310007 + CN + +70-F1-76 (hex) Data Modul AG +70F176 (base 16) Data Modul AG + Landsberger Str. 322 + Munich Bavaria 80687 + DE + +B8-47-C6 (hex) SanJet Technology Corp. +B847C6 (base 16) SanJet Technology Corp. + 4F,No2,Li-Hsin Rd., 6, + Hsinchu 30078 + TW + +B8-CD-93 (hex) Penetek, Inc +B8CD93 (base 16) Penetek, Inc + 6F, No.18, Wuqun 7th Rd, Wugu Dist + New Taipei City 248 + TW + +28-DB-81 (hex) Shanghai Guao Electronic Technology Co., Ltd +28DB81 (base 16) Shanghai Guao Electronic Technology Co., Ltd + No.6, Alley 1225 TongPu Road, + Shanghai 200333 + CN + +38-06-B4 (hex) A.D.C. GmbH +3806B4 (base 16) A.D.C. GmbH + Peter-Dornier-Str. 10 + Lindau 88131 + DE + +B8-24-1A (hex) SWEDA INFORMATICA LTDA +B8241A (base 16) SWEDA INFORMATICA LTDA + RUA DONA BRIGIDA, 713 + SAO PAULO SP 04111-081 + BR + +A0-B1-00 (hex) ShenZhen Cando Electronics Co.,Ltd +A0B100 (base 16) ShenZhen Cando Electronics Co.,Ltd + Building A, Dagang Industrial Zone, Changzhen Community + Shenzhen City Guangdong 518132 + CN + +20-1D-03 (hex) Elatec GmbH +201D03 (base 16) Elatec GmbH + Lilienthalstr. 3 + Puchheim Bayern 82178 + DE + +E0-67-B3 (hex) Shenzhen C-Data Technology Co., Ltd +E067B3 (base 16) Shenzhen C-Data Technology Co., Ltd + #601, Fl6, Bldg F, No.1008 Yangguang Community + Shenzhen Guangdong 518055 + CN + +1C-4A-F7 (hex) AMON INC +1C4AF7 (base 16) AMON INC + HANJUN BLDG 4/F, SHINGILDONG 110-4 + SEOUL 150839 + KR + +E4-77-6B (hex) AARTESYS AG +E4776B (base 16) AARTESYS AG + Bahnhofplatz 7 + Biel Bern CH-2501 + CH + +30-F3-1D (hex) zte corporation +30F31D (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +A0-EC-80 (hex) zte corporation +A0EC80 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +0C-C8-1F (hex) Summer Infant, Inc. +0CC81F (base 16) Summer Infant, Inc. + 1275 Park East Drive + Woonsocket Rhode Island 02895 + US + +A8-FB-70 (hex) WiseSec L.t.d +A8FB70 (base 16) WiseSec L.t.d + 145 yaffo ST. + Haifa Israel 37503 + IL + +E4-81-B3 (hex) Shenzhen ACT Industrial Co.,Ltd. +E481B3 (base 16) Shenzhen ACT Industrial Co.,Ltd. + NO.5 B/D,BEISHAN INDUSTRIAL PARK,BEISHAN R/D, + Shenzhen Guangdong 518083 + CN + +C0-6C-6D (hex) MagneMotion, Inc. +C06C6D (base 16) MagneMotion, Inc. + 139 Barnum Road + Devens Massachusetts 01434 + US + +E8-80-D8 (hex) GNTEK Electronics Co.,Ltd. +E880D8 (base 16) GNTEK Electronics Co.,Ltd. + Suzhou Industrial Park + Suzhou Jiangsu 215021 + CN + +30-3E-AD (hex) Sonavox Canada Inc +303EAD (base 16) Sonavox Canada Inc + 81 Zenway Blvd #25 + Woodbridge Ontario L4S0S5 + CA + +F8-35-DD (hex) Gemtek Technology Co., Ltd. +F835DD (base 16) Gemtek Technology Co., Ltd. + No. 1 Jen Ai Road Hsinchu Industrial Park Hukou, Hsinchu 30352 TAIWAN, REPUBLIC OF CHINA + Hsinchu TAIWAN 30352 + TW + +D8-B0-4C (hex) Jinan USR IOT Technology Co., Ltd. +D8B04C (base 16) Jinan USR IOT Technology Co., Ltd. + #1-523, Huizhan Guoji Cheng, Gaoxin Qu + JINAN SHANDONG 250101 + CN + +CC-04-B4 (hex) Select Comfort +CC04B4 (base 16) Select Comfort + 9800 59th Ave N + Minneapolis MN 55442 + US + +5C-15-E1 (hex) AIDC TECHNOLOGY (S) PTE LTD +5C15E1 (base 16) AIDC TECHNOLOGY (S) PTE LTD + NO.1 GOLDHILL PLAZA #03-21 + SINGAPORE 308899 + SG + +E8-51-9D (hex) Yeonhab Precision Co.,LTD +E8519D (base 16) Yeonhab Precision Co.,LTD + 219-27, Haksusosa-Gil, Mokcheon-Eup + Cheonan Chungcheongnamdo 330-844 + KR + +DC-57-26 (hex) Power-One +DC5726 (base 16) Power-One + Via San Girgio 642 + Terranuova Arezzo 52028 + IT + +F8-DA-DF (hex) EcoTech, Inc. +F8DADF (base 16) EcoTech, Inc. + 999 Postal Road + Allentown PA 18109 + US + +30-AE-7B (hex) Deqing Dusun Electron CO., LTD +30AE7B (base 16) Deqing Dusun Electron CO., LTD + No. 640 FengQing Street, Deqing + Huzhou Zhejiang 313200 + CN + +68-EC-62 (hex) YODO Technology Corp. Ltd. +68EC62 (base 16) YODO Technology Corp. Ltd. + 8F., No.168-1, Liancheng Rd + Taipei City 235 + TW + +18-88-57 (hex) Beijing Jinhong Xi-Dian Information Technology Corp. +188857 (base 16) Beijing Jinhong Xi-Dian Information Technology Corp. + 4th -5th Floor, 1# Building NO.1 Zhonghe Road + Beijing 100070 + CN + +B8-C8-55 (hex) Shanghai GBCOM Communication Technology Co.,Ltd. +B8C855 (base 16) Shanghai GBCOM Communication Technology Co.,Ltd. + Room 602, Building 6, No. + Shanghai 200241 + CN + +78-30-3B (hex) Stephen Technologies Co.,Limited +78303B (base 16) Stephen Technologies Co.,Limited + 5/F, Building NO.1, TongXin Industry Zone + Shenzhen Guangdong 518115 + CN + +CC-1A-FA (hex) zte corporation +CC1AFA (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +6C-8B-2F (hex) zte corporation +6C8B2F (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +8C-5A-F0 (hex) Exeltech Solar Products +8C5AF0 (base 16) Exeltech Solar Products + 3001 Northern Cross Blvd #361 + Fort Worth TX 76137 + US + +B0-80-8C (hex) Laser Light Engines +B0808C (base 16) Laser Light Engines + 8C Industrial Way + Salem New Hamshire 03079 + US + +D8-DC-E9 (hex) Kunshan Erlab ductless filtration system Co.,Ltd +D8DCE9 (base 16) Kunshan Erlab ductless filtration system Co.,Ltd + NO.100 Liu Shi Jin Road + Kunshan Jiangsu 215300 + CN + +DC-D5-2A (hex) Sunny Heart Limited +DCD52A (base 16) Sunny Heart Limited + Rm. 1516, 15/F, Hewlett Center + Kwun Tong Kowloon 852 + HK + +D8-66-C6 (hex) Shenzhen Daystar Technology Co.,ltd +D866C6 (base 16) Shenzhen Daystar Technology Co.,ltd + The 5th Floor,#4 Building, Minxing Industria Zone + Shenzhen Guangdong 518131 + CN + +D0-0E-A4 (hex) Porsche Cars North America +D00EA4 (base 16) Porsche Cars North America + 980 Hammond Drive + Atlanta GA 30328 + US + +78-4B-08 (hex) f.robotics acquisitions ltd +784B08 (base 16) f.robotics acquisitions ltd + Yevulim, Industrial Zone + Pardesia Hasharon 42815 + IL + +84-E4-D9 (hex) Shenzhen NEED technology Ltd. +84E4D9 (base 16) Shenzhen NEED technology Ltd. + Room 581 ,Jinda technology center,No.8, Kefeng road, + Shenzhen Guangdong 518057 + CN + +40-BC-73 (hex) Cronoplast S.L. +40BC73 (base 16) Cronoplast S.L. + Pol.Ind.S.Ermengol II - + ABRERA BARCELONA 08630 + ES + +40-07-C0 (hex) Railtec Systems GmbH +4007C0 (base 16) Railtec Systems GmbH + Sonnenbergstr. 19 + Hergiswil Nidwalden 6052 + CH + +A4-D3-B5 (hex) GLITEL Stropkov, s.r.o. +A4D3B5 (base 16) GLITEL Stropkov, s.r.o. + Cintorinska 557/73 + Stropkov 09101 + SK + +D4-3A-65 (hex) IGRS Engineering Lab Ltd. +D43A65 (base 16) IGRS Engineering Lab Ltd. + 8F,Taipeng Mansion + Haidian District Beijing 10000 + CN + +F4-99-AC (hex) WEBER Schraubautomaten GmbH +F499AC (base 16) WEBER Schraubautomaten GmbH + Hans-Urmiller-Ring 56 + Wolfratshausen Bayern 82515 + DE + +D0-50-99 (hex) ASRock Incorporation +D05099 (base 16) ASRock Incorporation + 2F., No.37, Sec. 2, Jhongyang S. Rd. + Taipei 112 + US + +A4-9E-DB (hex) AutoCrib, Inc. +A49EDB (base 16) AutoCrib, Inc. + 3011 S. Croddy Way + Santa Ana CA 92704 + US + +1C-76-CA (hex) Terasic Technologies Inc. +1C76CA (base 16) Terasic Technologies Inc. + 9F., No.176, Sec.2, Gongdao 5th Rd + Hsinchu City 30070 + TW + +88-89-64 (hex) GSI Electronics Inc. +888964 (base 16) GSI Electronics Inc. + 5200 Armand-Frappier + St-Hubert Quebec J3Z 1G5 + CA + +7C-D8-44 (hex) Enmotus Inc +7CD844 (base 16) Enmotus Inc + 65 Enterprise + Aliso Viejo CA 92656 + US + +44-61-9C (hex) FONsystem co. ltd. +44619C (base 16) FONsystem co. ltd. + 3F annex of Venture support center + GwangJu 500-706 + KR + +70-82-0E (hex) as electronics GmbH +70820E (base 16) as electronics GmbH + Kantstraße 10 + Großbettlingen Baden -Württemberg 72663 + DE + +0C-11-05 (hex) AKUVOX (XIAMEN) NETWORKS CO., LTD +0C1105 (base 16) AKUVOX (XIAMEN) NETWORKS CO., LTD + Suite 201-15, 31 WangHai Rd + Xiamen Fujian 361008 + CN + +5C-22-C4 (hex) DAE EUN ELETRONICS CO., LTD +5C22C4 (base 16) DAE EUN ELETRONICS CO., LTD + 1029 Hokye-Dong, Dongan-Goo + Anyang-Shi Kyongki-Do 431-080 + KR + +F8-FE-A8 (hex) Technico Japan Corporation +F8FEA8 (base 16) Technico Japan Corporation + AM Building 9F, 2-5-3, + Tokyo 160-0022 + JP + +18-00-DB (hex) Fitbit Inc. +1800DB (base 16) Fitbit Inc. + 150 Spear St Ste 200 + San Francisco CA 94105 + US + +78-A1-06 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +78A106 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +6C-61-26 (hex) Rinicom Holdings +6C6126 (base 16) Rinicom Holdings + Riverway House + Lancaster Lancashire LA1 2RX + GB + +88-68-5C (hex) Shenzhen ChuangDao & Perpetual Eternal Technology Co.,Ltd +88685C (base 16) Shenzhen ChuangDao & Perpetual Eternal Technology Co.,Ltd + Area c,2/F,Building 1, BaoAn foreign trade industrial zone + BaoAn District, Shenzhen Guangdong province 518100 + CN + +10-28-31 (hex) Morion Inc. +102831 (base 16) Morion Inc. + Shosse Kosmonavtov, 111 + Perm Permsky Krai 614990 + US + +EC-2C-49 (hex) University of Tokyo +EC2C49 (base 16) University of Tokyo + 4-6-1 Komaba + Meguro-ku Tokyo 153-8904 + US + +D8-29-16 (hex) Ascent Communication Technology +D82916 (base 16) Ascent Communication Technology + 13/F., Shum Tower + Hong Kong 9999 + HK + +2C-F2-03 (hex) EMKO ELEKTRONIK SAN VE TIC AS +2CF203 (base 16) EMKO ELEKTRONIK SAN VE TIC AS + DOSAB, KARANFIL SOK, NO:6 + BURSA 16369 + TR + +B4-FE-8C (hex) Centro Sicurezza Italia SpA +B4FE8C (base 16) Centro Sicurezza Italia SpA + Via Venaria 28-30 + Alpignano Torino 10091 + IT + +40-E7-30 (hex) DEY Storage Systems, Inc. +40E730 (base 16) DEY Storage Systems, Inc. + 215 South B Street + San Mateo CA 94401 + US + +68-B0-94 (hex) INESA ELECTRON CO.,LTD +68B094 (base 16) INESA ELECTRON CO.,LTD + 5F, NO.168, Tianlin Road + Shanghai 200233 + CN + +A0-73-FC (hex) Rancore Technologies Private Limited +A073FC (base 16) Rancore Technologies Private Limited + 5th Floor, Court House + Dhobi Talao Maharashtra 400 002 + IN + +44-F8-49 (hex) Union Pacific Railroad +44F849 (base 16) Union Pacific Railroad + 1400 Douglas St. STOP 0610 + Omaha NE 68179 + US + +CC-0D-EC (hex) Cisco SPVTG +CC0DEC (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +1C-37-BF (hex) Cloudium Systems Ltd. +1C37BF (base 16) Cloudium Systems Ltd. + Hartnett Centre + Limerick 00 + IE + +50-AB-BF (hex) Hoseo Telecom +50ABBF (base 16) Hoseo Telecom + 701 ACE Techno Tower 684-1 + Seoul 157-721 + KR + +0C-72-2C (hex) TP-LINK TECHNOLOGIES CO.,LTD. +0C722C (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +9C-E6-35 (hex) Nintendo Co., Ltd. +9CE635 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +60-A4-4C (hex) ASUSTek COMPUTER INC. +60A44C (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +18-5A-E8 (hex) Zenotech.Co.,Ltd +185AE8 (base 16) Zenotech.Co.,Ltd + E-503, BundangTechno Park, Yatap-dong + Seongnam 463-760 + KR + +C4-7D-CC (hex) Zebra Technologies Inc +C47DCC (base 16) Zebra Technologies Inc + 475 Half Day Road + Lincolnshire IL 60069 + US + +E0-AE-ED (hex) LOENK +E0AEED (base 16) LOENK + F9, Cheongdam Venture Plaza + SEOUL 135-951 + KR + +E4-92-E7 (hex) Gridlink Tech. Co.,Ltd. +E492E7 (base 16) Gridlink Tech. Co.,Ltd. + Room No. 619, No. 108 Jiang Bin Dong Road + Fuzhou Fujian 350015 + CN + +CC-04-7C (hex) G-WAY Microwave +CC047C (base 16) G-WAY Microwave + 38 Leuning Street + South Hackensack New Jersey 07078 + US + +64-53-5D (hex) Frauscher Sensortechnik +64535D (base 16) Frauscher Sensortechnik + Gewerbestraße 1 + St. Marienkirchen Upper Austria 4774 + US + +3C-6F-F7 (hex) EnTek Systems, Inc. +3C6FF7 (base 16) EnTek Systems, Inc. + 562 Starlight Dr. + Sautee Nacoochee GA 30571 + US + +2C-7B-5A (hex) Milper Ltd +2C7B5A (base 16) Milper Ltd + 32 Shaham St. + Petach Tikva 49250 + IL + +D4-BF-2D (hex) SE Controls Asia Pacific Ltd +D4BF2D (base 16) SE Controls Asia Pacific Ltd + Unit 301, 3/F, Hung To Centre, + Kwun Tong Kowloon + HK + +E0-D9-A2 (hex) Hippih aps +E0D9A2 (base 16) Hippih aps + Sceince Park Scion + Lyngby 2800 + DK + +FC-06-47 (hex) Cortland Research, LLC +FC0647 (base 16) Cortland Research, LLC + 12 S Main St., Ste 207 + Homer NY 13077 + US + +6C-D1-46 (hex) FRAMOS GmbH +6CD146 (base 16) FRAMOS GmbH + Mehlbeerenstr. 2 + Taufkirchen 82024 + DE + +54-E0-32 (hex) Juniper Networks +54E032 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +54-61-EA (hex) Zaplox AB +5461EA (base 16) Zaplox AB + Scheelev + Lund Sk 22370 + SE + +D0-8B-7E (hex) Passif Semiconductor +D08B7E (base 16) Passif Semiconductor + 400 S. El Camino Real Suite 250 + San Mateo California 94402 + US + +04-58-6F (hex) Sichuan Whayer information industry Co.,LTD +04586F (base 16) Sichuan Whayer information industry Co.,LTD + Layer 16,Building 10, C Area + Chengdu City 610041 + CN + +FC-9F-AE (hex) Fidus Systems Inc +FC9FAE (base 16) Fidus Systems Inc + 35 Fitzgerald Road + Ottawa Ontario K2H 1E6 + CA + +68-1E-8B (hex) InfoSight Corporation +681E8B (base 16) InfoSight Corporation + 20700 US Hwy 23 + Chillicothe Ohio 45601 + US + +D0-52-A8 (hex) Physical Graph Corporation +D052A8 (base 16) Physical Graph Corporation + 11654 Plaza America Drive + Reston VA 20190 + US + +CC-3A-61 (hex) SAMSUNG ELECTRO MECHANICS CO., LTD. +CC3A61 (base 16) SAMSUNG ELECTRO MECHANICS CO., LTD. + 314, Maetan3-Dong, Yeongtong-Gu + Suwon Gyunggi-Do 443-743 + US + +F8-D7-BF (hex) REV Ritter GmbH +F8D7BF (base 16) REV Ritter GmbH + Frankenstra + M Bavaria 63776 + DE + +48-BE-2D (hex) Symanitron +48BE2D (base 16) Symanitron + Ap.103, 17 Rudnevka str.,111674 + Moscow + RU + +F0-23-29 (hex) SHOWA DENKI CO.,LTD. +F02329 (base 16) SHOWA DENKI CO.,LTD. + 1-25 + Daito-city Osaka 574-0052 + JP + +F0-73-AE (hex) PEAK-System Technik +F073AE (base 16) PEAK-System Technik + Otto-Roehm-Str 69 + Darmstadt Hessen 64293 + DE + +48-B8-DE (hex) HOMEWINS TECHNOLOGY CO.,LTD. +48B8DE (base 16) HOMEWINS TECHNOLOGY CO.,LTD. + 10F-1, NO. 122, QIAOHE RD., + NEW TAIPEI CITY, 235 + TW + +10-EA-59 (hex) Cisco SPVTG +10EA59 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +0C-19-1F (hex) Inform Electronik +0C191F (base 16) Inform Electronik + Emek mah.Ordu cad.No-49-51-53 + Sarigazi-Sancaktepe Istanbul 34785 + US + +10-65-CF (hex) IQSIM +1065CF (base 16) IQSIM + 2000 Route des Lucioles + BIOT 06410 + FR + +68-4C-A8 (hex) Shenzhen Herotel Tech. Co., Ltd. +684CA8 (base 16) Shenzhen Herotel Tech. Co., Ltd. + Room W1402, West Tower, No.10128, Shennan Road, Nanshan District + Shenzhen Guangdong 518000 + CN + +98-20-8E (hex) Definium Technologies +98208E (base 16) Definium Technologies + 34 Fairthorne Road + Launceston Tasmania 7250 + AU + +70-4A-E4 (hex) Rinstrum Pty Ltd +704AE4 (base 16) Rinstrum Pty Ltd + 41 Success St + Acacia Ridge QLD 4110 + AU + +08-3A-B8 (hex) Shinoda Plasma Co., Ltd. +083AB8 (base 16) Shinoda Plasma Co., Ltd. + 4-6-7, Minatojima Minamimachi, Chuo-ku + Kobe Hyogo 6500047 + JP + +A0-DD-97 (hex) PolarLink Technologies, Ltd +A0DD97 (base 16) PolarLink Technologies, Ltd + 6FL 352, Zhonghua 1st Rd. Kaohsiung 804 Taiwan + Kaohsiung Taiwan 804 + TW + +EC-89-F5 (hex) Lenovo Mobile Communication Technology Ltd. +EC89F5 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999,Qishan North 2nd Road,Information&Optoelectronics Park,Torch Hi-tech Industry Development Zone, + Xiamen Fujian 361006 + US + +B4-98-42 (hex) zte corporation +B49842 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +70-54-D2 (hex) PEGATRON CORPORATION +7054D2 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +64-5A-04 (hex) Chicony Electronics Co., Ltd. +645A04 (base 16) Chicony Electronics Co., Ltd. + No.25, Wugong 6th Rd., Wugu Dist., + New Taipei City 248, TAIWAN, REPUBLIC OF CHINA 248 + TW + +AC-17-02 (hex) Fibar Group sp. z o.o. +AC1702 (base 16) Fibar Group sp. z o.o. + ul. Lotnicza 1 + Poznan 60-421 + PL + +98-4C-D3 (hex) Mantis Deposition +984CD3 (base 16) Mantis Deposition + 2 Goodson Industrial Mews + Thame Oxfordshire OX9 3BX + GB + +08-60-6E (hex) ASUSTek COMPUTER INC. +08606E (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +3C-57-D5 (hex) FiveCo +3C57D5 (base 16) FiveCo + Ch. de la Rueyre 116 + Renens VD 1020 + US + +F8-48-97 (hex) Hitachi, Ltd. +F84897 (base 16) Hitachi, Ltd. + 27-18, Minami Oi 6-chome, Shinagawa-ku + Tokyo 140-8572 + JP + +F8-0B-D0 (hex) Datang Telecom communication terminal (Tianjin) Co., Ltd. +F80BD0 (base 16) Datang Telecom communication terminal (Tianjin) Co., Ltd. + Garden East Roadon the 15th, + Haidian District Beijing 100191 + CN + +E8-9A-FF (hex) Fujian LANDI Commercial Equipment Co.,Ltd +E89AFF (base 16) Fujian LANDI Commercial Equipment Co.,Ltd + Building 17,the 1st Section ,Fuzhou Software Park + No.89 Software Road Fuzhou ,Fujian 350003 + CN + +0C-8C-DC (hex) Suunto Oy +0C8CDC (base 16) Suunto Oy + Valimotie 7 + Vantaa Uusimaa 02710 + FI + +60-C5-A8 (hex) Beijing LT Honway Technology Co.,Ltd +60C5A8 (base 16) Beijing LT Honway Technology Co.,Ltd + Room 1703,A1 Tower, Changyuan Tiandi, No.18,Suzhou Street + beijing beijing 100086 + CN + +28-D2-44 (hex) LCFC(HeFei) Electronics Technology Co., Ltd. +28D244 (base 16) LCFC(HeFei) Electronics Technology Co., Ltd. + 6 Cui Wei Road + Hefei Anhui 230000 + CN + +B4-DF-3B (hex) Chromlech +B4DF3B (base 16) Chromlech + 19 av. Gabriel Faure + THORIGNE FOUILLARD 35235 + FR + +7C-9A-9B (hex) VSE valencia smart energy +7C9A9B (base 16) VSE valencia smart energy + Sir Alexander Fleming n + Paterna Valencia 46980 + ES + +84-E7-14 (hex) Liang Herng Enterprise,Co.Ltd. +84E714 (base 16) Liang Herng Enterprise,Co.Ltd. + 1FL,No.27,KweiYang Street,Sanchung District,New Taipei City,Taiwan,R.O.C. + New Taipei City 241 + TW + +B8-29-F7 (hex) Blaster Tech +B829F7 (base 16) Blaster Tech + 13337 South Street + Cerritos CA 90703 + US + +E4-A7-FD (hex) Cellco Partnership +E4A7FD (base 16) Cellco Partnership + One Verizon Way + Baskin Ridge New Jersey 07920 + US + +2C-E2-A8 (hex) DeviceDesign +2CE2A8 (base 16) DeviceDesign + Yeongtong-dong, Yeongtong-gu + Suwon-si Gyeonggi-do 443-813 + KR + +00-B5-6D (hex) David Electronics Co., LTD. +00B56D (base 16) David Electronics Co., LTD. + 9F, -2, No. 188, Sec. 3, Ta-Tung Rd., + New Taipei City, 22103 + TW + +2C-35-57 (hex) ELLIY Power CO..Ltd +2C3557 (base 16) ELLIY Power CO..Ltd + 1-6-4, Osaki + Shinagawa-ku TOKYO 141-0032 + US + +B8-04-15 (hex) Bayan Audio +B80415 (base 16) Bayan Audio + 5 The Pavilions + Pease Pottage West Sussex RH11 9BJ + GB + +D4-13-6F (hex) Asia Pacific Brands +D4136F (base 16) Asia Pacific Brands + PO Box 113001 + Auckland Newmarket 1149 + NZ + +C8-E1-A7 (hex) Vertu Corporation Limited +C8E1A7 (base 16) Vertu Corporation Limited + Beacon Hill Road + Church Crookham Hampshire GU52 8DY + GB + +4C-AB-33 (hex) KST technology +4CAB33 (base 16) KST technology + Bangi-dong, songpa-gu + Seoul 138-050 + KR + +F4-47-2A (hex) Nanjing Rousing Sci. and Tech. Industrial Co., Ltd +F4472A (base 16) Nanjing Rousing Sci. and Tech. Industrial Co., Ltd + A630,F6,NO.58 Nanhu Road,Jianye District + Nanjing Jiangsu 210017 + CN + +DC-02-8E (hex) zte corporation +DC028E (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +A8-45-E9 (hex) Firich Enterprises CO., LTD. +A845E9 (base 16) Firich Enterprises CO., LTD. + 10F., No. 75, Sec. 1, Xintai 5th Rd., Xizhi Dist. + New Taipei City Taiwan (R.O.C.) 886 + TW + +48-52-61 (hex) SOREEL +485261 (base 16) SOREEL + 18 Rue de la Gâtine + CHOLET FRANCE 49304 + FR + +64-62-23 (hex) Cellient Co., Ltd. +646223 (base 16) Cellient Co., Ltd. + 6F Glass Tower, 366-4 Yatap-dong Bundang-gu + Seongnam-si Gyeonggi-do 463-827 + KR + +98-47-3C (hex) SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD +98473C (base 16) SHANGHAI SUNMON COMMUNICATION TECHNOGY CO.,LTD + Suite 604-605,Xing Yuan Technology Plaza 418 Gui Ping Road ShangHAI + Shanghai 200233 + CN + +54-81-AD (hex) Eagle Research Corporation +5481AD (base 16) Eagle Research Corporation + 4237 State Route 34 + Hurricane West Virginia 25526 + US + +54-A0-4F (hex) t-mac Technologies Ltd +54A04F (base 16) t-mac Technologies Ltd + Stand Park + Chesterfield Derbyshire S41 8JT + GB + +14-DB-85 (hex) S NET MEDIA +14DB85 (base 16) S NET MEDIA + 4F, SEHYUN BLDG, 1581-7 + SEOUL 137-875 + KR + +B8-DA-F1 (hex) Strahlenschutz- Entwicklungs- und Ausruestungsgesellschaft mbH +B8DAF1 (base 16) Strahlenschutz- Entwicklungs- und Ausruestungsgesellschaft mbH + Ostdamm 139 + Duelmen NRW 48249 + DE + +D4-5C-70 (hex) Wi-Fi Alliance +D45C70 (base 16) Wi-Fi Alliance + 10900-B Stonelake Boulevard + Austin TX 78759 + US + +EC-47-3C (hex) Redwire, LLC +EC473C (base 16) Redwire, LLC + 8 Thorndike St + Everett MA 02149 + US + +3C-C1-2C (hex) AES Corporation +3CC12C (base 16) AES Corporation + 285 Newbury St + Peabody MA 01960 + US + +94-9B-FD (hex) Trans New Technology, Inc. +949BFD (base 16) Trans New Technology, Inc. + KY Bldg. 8F, 5-14-4 Nishinippori + Arakawa Tokyo 116-0013 + JP + +A0-0A-BF (hex) Wieson Technologies Co., Ltd. +A00ABF (base 16) Wieson Technologies Co., Ltd. + 7F, No. 276, Sec. 1, Datong Rd + New Taipei City 221 + TW + +8C-CD-E8 (hex) Nintendo Co., Ltd. +8CCDE8 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +7C-B2-32 (hex) Hui Zhou Gaoshengda Technology Co.,LTD +7CB232 (base 16) Hui Zhou Gaoshengda Technology Co.,LTD + No.75,Zhongkai High-Tech Development District,Huizhou + Hui Zhou Guangdong 516006 + CN + +00-E6-66 (hex) ARIMA Communications Corp. +00E666 (base 16) ARIMA Communications Corp. + 6F.,No.866,Zhongzheng Rd.,Zhonghe Dist., + New Taipei City Taiwan 23586 + TW + +34-BD-FA (hex) Cisco SPVTG +34BDFA (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +F4-1E-26 (hex) Simon-Kaloi Engineering +F41E26 (base 16) Simon-Kaloi Engineering + 31192 La Baya Drive Unit G + Westlake Village CA 91362 + US + +70-25-26 (hex) Nokia +702526 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +18-D9-49 (hex) Qvis Labs, LLC +18D949 (base 16) Qvis Labs, LLC + 3204 Rustic River Cove + Austin TX 78746-2001 + US + +D8-08-F5 (hex) Arcadia Networks Co. Ltd. +D808F5 (base 16) Arcadia Networks Co. Ltd. + Cheung Sha Wan 5-B FL + Kowloon 0633 + HK + +0C-C4-7E (hex) EUCAST Co., Ltd. +0CC47E (base 16) EUCAST Co., Ltd. + Room 303, 1018-2 Unjung-dong, Bundang-Gu + Seongnam-si Kyunggi-do 463-440 + KR + +50-72-4D (hex) BEG Brueck Electronic GmbH +50724D (base 16) BEG Brueck Electronic GmbH + Schlosserstraße 30 + Lindlar Nordrhein-Westfalen 51789 + DE + +78-3C-E3 (hex) Kai-EE +783CE3 (base 16) Kai-EE + 3F.-12, No.79, Sec. 1, Xintai 5th Rd., + New Taipei City 22101 + TW + +B8-98-B0 (hex) Atlona Inc. +B898B0 (base 16) Atlona Inc. + 70 Daggett Dr. + San Jose CA 95134 + US + +24-69-4A (hex) Jasmine Systems Inc. +24694A (base 16) Jasmine Systems Inc. + 50 Charles Lindbergh Blvd. Suite 411 + Uniondale NY 11553 + US + +08-0C-0B (hex) SysMik GmbH Dresden +080C0B (base 16) SysMik GmbH Dresden + Bertolt-Brecht-Allee 24 + Dresden 01309 + DE + +DC-BF-90 (hex) HUIZHOU QIAOXING TELECOMMUNICATION INDUSTRY CO.,LTD. +DCBF90 (base 16) HUIZHOU QIAOXING TELECOMMUNICATION INDUSTRY CO.,LTD. + Qiaoxing Science Technological&Industrial Zone Tangquan + Huizhou Guangdong 516023 + CN + +04-9F-06 (hex) Smobile Co., Ltd. +049F06 (base 16) Smobile Co., Ltd. + T-1009, Poongrim i-won Plus, 255-1 + Seohyeon-dong, Bundang-gu Seongnam-si, Gyeonggi-do 463-862 + KR + +28-9A-4B (hex) SteelSeries ApS +289A4B (base 16) SteelSeries ApS + 656 West Randolph, Suite 2E + Chicago IL 60661 + US + +A0-8C-15 (hex) Gerhard D. Wempe KG +A08C15 (base 16) Gerhard D. Wempe KG + Steinstrasse 23 + Hamburg 20095 + DE + +90-CF-6F (hex) Dlogixs Co Ltd +90CF6F (base 16) Dlogixs Co Ltd + DLogixs Bldg, #351-1, Anyang-Dong + Anyang-si Gyeonggi-do 430-010 + KR + +C8-FB-26 (hex) Cisco SPVTG +C8FB26 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +B8-58-10 (hex) NUMERA, INC. +B85810 (base 16) NUMERA, INC. + 1511 3RD AVE + SEATTLE WA 98101 + US + +EC-D9-50 (hex) IRT SA +ECD950 (base 16) IRT SA + Puits-Godet 16 + NEUCHATEL NE 2000 + CH + +7C-02-BC (hex) Hansung Electronics Co. LTD +7C02BC (base 16) Hansung Electronics Co. LTD + 319, Bong san-ri, San dong-myun + Gumi 730-853 + KR + +B8-24-10 (hex) Magneti Marelli Slovakia s.r.o. +B82410 (base 16) Magneti Marelli Slovakia s.r.o. + Industrial Park Kechnec + Kechnec 04458 + SK + +10-5F-49 (hex) Cisco SPVTG +105F49 (base 16) Cisco SPVTG + 5030 Sugarloaf Parkway + Lawrenceville GA 30044 + US + +1C-5C-60 (hex) Shenzhen Belzon Technology Co.,LTD. +1C5C60 (base 16) Shenzhen Belzon Technology Co.,LTD. + 5F Block 1,Zhongxin Building,Chuangye Rd + Shenzhen Guangdong 518054 + CN + +B8-B9-4E (hex) Shenzhen iBaby Labs, Inc. +B8B94E (base 16) Shenzhen iBaby Labs, Inc. + Room 218, Building 17,Shangsha Innovation Science and Technology Park,Futian District + Shenzhen Guangdong 518047 + CN + +AC-C6-98 (hex) Kohzu Precision Co., Ltd. +ACC698 (base 16) Kohzu Precision Co., Ltd. + 2-6-15, Kurigi, Asao-ku + Kawasaki-shi Kanagawa 215-8521 + JP + +7C-38-6C (hex) Real Time Logic +7C386C (base 16) Real Time Logic + 12515 Academy Ridge View + Colorado Springs Colorado 80921 + US + +20-67-B1 (hex) Pluto inc. +2067B1 (base 16) Pluto inc. + Hongo5-21-1-303 + Bunkyo-ku Tokyo 113-0033 + JP + +18-9A-67 (hex) CSE-Servelec Limited +189A67 (base 16) CSE-Servelec Limited + Rotherside Road + Sheffield S21 4HL + GB + +08-7D-21 (hex) Altasec technology corporation +087D21 (base 16) Altasec technology corporation + 9F-1, No.75, Sec.1, Xintai 5th Rd., + New Taipei City Taiwan 221 + TW + +F8-05-1C (hex) DRS Imaging and Targeting Solutions +F8051C (base 16) DRS Imaging and Targeting Solutions + 100 N Babcock St + Melbourne FL 32935 + US + +78-D3-4F (hex) Pace-O-Matic, Inc. +78D34F (base 16) Pace-O-Matic, Inc. + 4150 Blue Ridge Industrial Parkway + Norcross GA 30071 + US + +A4-46-6B (hex) EOC Technology +A4466B (base 16) EOC Technology + #1601 Acro Palace, 1594 Gwanyang-dong, Dongan-gu + Anyang-si Gyeonggi-do 431-060 + KR + +90-1E-DD (hex) GREAT COMPUTER CORPORATION +901EDD (base 16) GREAT COMPUTER CORPORATION + 4F., No.236, Fude 2nd Rd., Xizhi Dist., + New Taipei City 22151 + TW + +34-D7-B4 (hex) Tributary Systems, Inc. +34D7B4 (base 16) Tributary Systems, Inc. + 3717 Commerce Place + Bedford Texas 76021 + US + +F4-0F-9B (hex) WAVELINK +F40F9B (base 16) WAVELINK + #701, Dongyoung Venture'stel 3rd, 202-4, + Anyang-si Kyungki-do 430-817 + KR + +64-5F-FF (hex) Nicolet Neuro +645FFF (base 16) Nicolet Neuro + 1850 Deming Way + Middleton WI 53562 + US + +AC-7A-42 (hex) iConnectivity +AC7A42 (base 16) iConnectivity + #21, 1725 30th Ave NE + Calgary Alberta T2E 7P6 + CA + +70-0B-C0 (hex) Dewav Technology Company +700BC0 (base 16) Dewav Technology Company + Room 1408, Real Estate Mansion + Shangahi 200120 + CN + +CC-14-A6 (hex) Yichun MyEnergy Domain, Inc +CC14A6 (base 16) Yichun MyEnergy Domain, Inc + 349W. Yuanshan Rd, Yichun + Yichun Jiangxi 336000 + CN + +10-9F-A9 (hex) Actiontec Electronics, Inc +109FA9 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +C0-A3-64 (hex) 3D Systems Massachusetts +C0A364 (base 16) 3D Systems Massachusetts + 19 Connector Road + Andover MA 01810 + US + +1C-5F-FF (hex) Beijing Ereneben Information Technology Co.,Ltd Shenzhen Branch +1C5FFF (base 16) Beijing Ereneben Information Technology Co.,Ltd Shenzhen Branch + Room 14A, Building A, Honglong Central Plaza, No.3001,Heping Road, Luohu District, Shenzhen City + Shenzhen Guangdong 518001 + CN + +60-45-BD (hex) Microsoft +6045BD (base 16) Microsoft + 1 Microsoft Way + Redmond Washington 98052 + US + +24-10-64 (hex) Shenzhen Ecsino Tecnical Co. Ltd +241064 (base 16) Shenzhen Ecsino Tecnical Co. Ltd + 7F Guoxin build ChangXin Road. Nan'shan District + Shenzhen Guangdong 518000 + CN + +7C-EB-EA (hex) ASCT +7CEBEA (base 16) ASCT + 4F., No.49, Wu-Gong 6th Rd. Wu-Gu Industrial Park, + New Taipei City 248 + TW + +9C-0D-AC (hex) Tymphany HK Limited +9C0DAC (base 16) Tymphany HK Limited + RM 1307-8 + 43-59, Queen's Road East Wanchai + HK + +70-B5-99 (hex) Embedded Technologies s.r.o. +70B599 (base 16) Embedded Technologies s.r.o. + Doubravice 134 + Turnov 51101 + CZ + +EC-4C-4D (hex) ZAO NPK RoTeK +EC4C4D (base 16) ZAO NPK RoTeK + Bild. 119-1, Prospekt Mira + Moscow Moscow 129223 + RU + +A4-D1-8F (hex) Shenzhen Skyee Optical Fiber Communication Technology Ltd. +A4D18F (base 16) Shenzhen Skyee Optical Fiber Communication Technology Ltd. + No.5 Bldg. Yimin Industrial Park, No.31, Makan South Road, Nanshan District + Shenzhen Guangdong 518000 + CN + +58-34-3B (hex) Glovast Technology Ltd. +58343B (base 16) Glovast Technology Ltd. + 6F., No.23, JianKang Rd., SongShan Dist., + Taipei 105 + TW + +88-96-76 (hex) TTC MARCONI s.r.o. +889676 (base 16) TTC MARCONI s.r.o. + Trebohosticka s.r.o. + Praha 10000 + CZ + +5C-17-37 (hex) I-View Now, LLC. +5C1737 (base 16) I-View Now, LLC. + 1421 E. Sunset + Las Vegas NV 89119 + US + +AC-0A-61 (hex) Labor S.r.L. +AC0A61 (base 16) Labor S.r.L. + Via della Scrofa 117 + Rome 00186 + IT + +1C-43-EC (hex) JAPAN CIRCUIT CO.,LTD +1C43EC (base 16) JAPAN CIRCUIT CO.,LTD + NKF-Kawasaki-Building 7F + Kawasaki Kanagawa 2100005 + JP + +54-D1-B0 (hex) Universal Laser Systems, Inc +54D1B0 (base 16) Universal Laser Systems, Inc + 16008 N 81st street + scottsdale az 85260 + US + +78-52-62 (hex) Shenzhen Hojy Software Co., Ltd. +785262 (base 16) Shenzhen Hojy Software Co., Ltd. + 3F,East of Building25,Keyuanxi,Number 5,Kezhixi Road, Science & Industry Park ,Nan Shan District ,Shenzhen + ShenZhen GuangDong 508057 + CN + +74-6A-89 (hex) Rezolt Corporation +746A89 (base 16) Rezolt Corporation + 2855 Bowers Avenue + Santa Clara CA 95051 + US + +70-2F-4B (hex) PolyVision Inc. +702F4B (base 16) PolyVision Inc. + 3970 Johns Creek Ct. + Suwanee Georgia 30024 + US + +74-14-89 (hex) SRT Wireless +741489 (base 16) SRT Wireless + 4101 SW 47th Avenue #102 + Davie Florida 33314 + US + +24-1B-13 (hex) Shanghai Nutshell Electronic Co., Ltd. +241B13 (base 16) Shanghai Nutshell Electronic Co., Ltd. + 365 Guoshoujing RD.,Zhangjiang Hi-Tech Park, Pudong District + Shanghai Shanghai 201203 + CN + +20-01-4F (hex) Linea Research Ltd +20014F (base 16) Linea Research Ltd + 1 Marquis Business Centre + Baldock Hertfordshire SG7 6XL + GB + +EC-0E-D6 (hex) ITECH INSTRUMENTS SAS +EC0ED6 (base 16) ITECH INSTRUMENTS SAS + 3 Avenue de la Maranne + Châteauneuf-Les-Martigues 13220 + FR + +24-09-17 (hex) Devlin Electronics Limited +240917 (base 16) Devlin Electronics Limited + Unit D1 + Basingstoke Hampshire RG226HZ + GB + +9C-54-CA (hex) Zhengzhou VCOM Science and Technology Co.,Ltd +9C54CA (base 16) Zhengzhou VCOM Science and Technology Co.,Ltd + National 863 Software Park£¬No.6 Cuizhu Street, Hi-tech Indusry Developing Park + ZhengZhou City Henan Province 450001 + CN + +B4-35-64 (hex) Fujian Tian Cheng Electron Science & Technical Development Co.,Ltd. +B43564 (base 16) Fujian Tian Cheng Electron Science & Technical Development Co.,Ltd. + 1801 unit,Tian an Cyber Times Tower A,Futian District + Shenzhen Guangdong 518000 + CN + +00-BF-15 (hex) Genetec Inc. +00BF15 (base 16) Genetec Inc. + 2280 boul. Alfred-Nobel + St,. Laurent Quebec H4S 2A4 + CA + +38-EE-9D (hex) Anedo Ltd. +38EE9D (base 16) Anedo Ltd. + Huelsmeyerstraße 35 + Eydelstedt 49406 + DE + +78-BE-BD (hex) STULZ GmbH +78BEBD (base 16) STULZ GmbH + Holsteiner Chausse 283 + Hamburg 22457 + DE + +D4-DF-57 (hex) Alpinion Medical Systems +D4DF57 (base 16) Alpinion Medical Systems + 1F Verdi Tower 222-22 + Seoul 181-848 + KR + +50-48-EB (hex) BEIJING HAIHEJINSHENG NETWORK TECHNOLOGY CO. LTD. +5048EB (base 16) BEIJING HAIHEJINSHENG NETWORK TECHNOLOGY CO. LTD. + RM 701 Unit 2 Huirong Bldg. No.106 Lianhuachi East RD. Xuanwu Dist. Beijing + BEIJING CHINA 100055 + CN + +B4-0E-96 (hex) HERAN +B40E96 (base 16) HERAN + No.88, Keji 3rd Rd., Guishan Township + Taoyuan R.O.C 333 + TW + +50-8C-77 (hex) DIRMEIER Schanktechnik GmbH &Co KG +508C77 (base 16) DIRMEIER Schanktechnik GmbH &Co KG + Alfons-Goppel-Straße 5 + 92526 Oberviechtach + DE + +40-70-4A (hex) Power Idea Technology Limited +40704A (base 16) Power Idea Technology Limited + 1401A, Mintai Building, WenXin 5 Road, ShenZhen, PRC + Guang Dong Shen Zhen 518054 + CN + +54-5E-BD (hex) NL Technologies +545EBD (base 16) NL Technologies + 33 Laird Drive + Toronto ON M4G3S8 + CA + +F4-7F-35 (hex) Cisco Systems, Inc +F47F35 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +BC-C1-68 (hex) DinBox Sverige AB +BCC168 (base 16) DinBox Sverige AB + Surbrunnsgatan 14 + Stockholm 11427 + SE + +DC-30-9C (hex) Heyrex Limited +DC309C (base 16) Heyrex Limited + Level 1, 236-256 Karori Road + Wellington 6147 + NZ + +2C-00-F7 (hex) XOS +2C00F7 (base 16) XOS + 15 Tech Valley Drive + East Greenbush NY 12061 + US + +28-F6-06 (hex) Syes srl +28F606 (base 16) Syes srl + Via Zanella 21 + Lissone (MB) Monza Brianza 20851 + IT + +0C-AF-5A (hex) GENUS POWER INFRASTRUCTURES LIMITED +0CAF5A (base 16) GENUS POWER INFRASTRUCTURES LIMITED + SPL-3 RIICO INDUSTRIAL AREA + JAIPUR RAJASTHAN 302022 + IN + +7C-EF-8A (hex) Inhon International Ltd. +7CEF8A (base 16) Inhon International Ltd. + 2F, No.552, Ruiguang Rd, Neihu Dist + Taipei Taiwan 114 + TW + +24-11-25 (hex) Hutek Co., Ltd. +241125 (base 16) Hutek Co., Ltd. + E-402 Bundang Technopark + Seongnam-city Gyeonggi-do 463-760 + KR + +B4-31-B8 (hex) Aviwest +B431B8 (base 16) Aviwest + 6 rue du Patis Tatelin + Rennes 35700 + FR + +CC-18-7B (hex) Manzanita Systems, Inc. +CC187B (base 16) Manzanita Systems, Inc. + 14269 Danielson Street + Poway CA 92064 + US + +08-BE-09 (hex) Astrol Electronic AG +08BE09 (base 16) Astrol Electronic AG + Vorderi Böde 3 + Oberrohrdorf AG 5452 + CH + +B4-1D-EF (hex) Internet Laboratories, Inc. +B41DEF (base 16) Internet Laboratories, Inc. + P.O. Box 7697 + Atlanta GA 30357 + US + +80-93-93 (hex) Xapt GmbH +809393 (base 16) Xapt GmbH + Neidenburger Str. 10 + Gelsenkirchen NRW 45897 + DE + +A0-07-B6 (hex) Advanced Technical Support, Inc. +A007B6 (base 16) Advanced Technical Support, Inc. + 10 Grassmere Ave + West Hartford CT 06110 + US + +0C-D2-B5 (hex) Binatone Telecommunication Pvt. Ltd +0CD2B5 (base 16) Binatone Telecommunication Pvt. Ltd + A36, G/F, Sector 4 + Uttar Pradesh 201301 + IN + +48-46-F1 (hex) Uros Oy +4846F1 (base 16) Uros Oy + Tutkijantie 4 + OULU 90590 + FI + +B8-27-EB (hex) Raspberry Pi Foundation +B827EB (base 16) Raspberry Pi Foundation + Mitchell Wood House + Caldecote Cambridgeshire CB23 7NU + US + +84-AF-1F (hex) Beat System Service Co,. Ltd. +84AF1F (base 16) Beat System Service Co,. Ltd. + 1-11-1-2F, Nodaya-cho + Okayama-city Okayama 700-0815 + JP + +B0-58-C4 (hex) Broadcast Microwave Services, Inc +B058C4 (base 16) Broadcast Microwave Services, Inc + 12367 Crosthwaite Circle + Poway CA 92064 + US + +74-57-98 (hex) TRUMPF Laser GmbH + Co. KG +745798 (base 16) TRUMPF Laser GmbH + Co. KG + Aichhalder Str. 39 + Schramberg BW 78713 + DE + +28-17-CE (hex) Omnisense Ltd +2817CE (base 16) Omnisense Ltd + 3rd Floor St Andrew's House + Cambridge Cambridgeshire CB2 3BZ + GB + +3C-CE-73 (hex) Cisco Systems, Inc +3CCE73 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B0-BD-6D (hex) Echostreams Innovative Solutions +B0BD6D (base 16) Echostreams Innovative Solutions + 1130 Coiner Ct. + City of Industry CA 91748 + US + +60-44-F5 (hex) Easy Digital Ltd. +6044F5 (base 16) Easy Digital Ltd. + Victoria Buildings, 1 Haddington Road + Dublin 4 + IE + +90-AC-3F (hex) BrightSign LLC +90AC3F (base 16) BrightSign LLC + 16795 Lark Ave. + Los Gatos CA 95032 + US + +AC-51-EE (hex) Cambridge Communication Systems Ltd +AC51EE (base 16) Cambridge Communication Systems Ltd + Sheraton House + Cambridge Cambridgeshire CB3 0AX + GB + +78-A1-83 (hex) Advidia +78A183 (base 16) Advidia + 3 Riverway + Houston TX 77056 + US + +A8-D0-E5 (hex) Juniper Networks +A8D0E5 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +F8-99-55 (hex) Fortress Technology Inc +F89955 (base 16) Fortress Technology Inc + 51 Grand Marshall Drive + Scarborough Ontario M1B 5N6 + CA + +4C-C9-4F (hex) Nokia +4CC94F (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +0C-E5-D3 (hex) DH electronics GmbH +0CE5D3 (base 16) DH electronics GmbH + Am Anger 8 + Bergen 83346 + DE + +E4-25-E9 (hex) Color-Chip +E425E9 (base 16) Color-Chip + Tavor Building 1 + New Industrial Park Yokneam 20692 + IL + +14-B1-C8 (hex) InfiniWing, Inc. +14B1C8 (base 16) InfiniWing, Inc. + 19925 Stevens Creek Blvd + Cupertino CA 95014 + US + +E8-40-F2 (hex) PEGATRON CORPORATION +E840F2 (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +50-05-3D (hex) CyWee Group Ltd +50053D (base 16) CyWee Group Ltd + 3F, No.28, Lane128 + Taipei 10462 + TW + +F8-8C-1C (hex) KAISHUN ELECTRONIC TECHNOLOGY CO., LTD. BEIJING +F88C1C (base 16) KAISHUN ELECTRONIC TECHNOLOGY CO., LTD. BEIJING + NO.1 FARM, HENGQIAO VILLAGE WEST, MACHIKOU TOWN, + BEIJING 102200 + CN + +1C-0B-52 (hex) EPICOM S.A +1C0B52 (base 16) EPICOM S.A + Autovia Andalucia Km 12.700 + Getafe Madrid 28905 + ES + +74-7E-2D (hex) Beijing Thomson CITIC Digital Technology Co. LTD. +747E2D (base 16) Beijing Thomson CITIC Digital Technology Co. LTD. + 8301, No.8 Workshop, 3 Yongchangbei Road + Beijing 100176 + CN + +88-5C-47 (hex) Alcatel Lucent +885C47 (base 16) Alcatel Lucent + Via Energy Park, 14 + Vimercate MB 20871 + IT + +3C-C1-F6 (hex) Melange Systems Pvt. Ltd. +3CC1F6 (base 16) Melange Systems Pvt. Ltd. + 4/1, 7th Cross, Kumarapark West + Bangalore Karnataka 560020 + IN + +94-FA-E8 (hex) Shenzhen Eycom Technology Co., Ltd +94FAE8 (base 16) Shenzhen Eycom Technology Co., Ltd + EYANG Building, No. 3 of Qimin Rd, Langshan 2nd Street, North Area of Hi-Tech Industrial Zone, Nanshan District + Shenzhen Guang Dong 518057 + CN + +B4-82-55 (hex) Research Products Corporation +B48255 (base 16) Research Products Corporation + 1015 E. Washington Ave + Madison WI 53703 + US + +80-16-B7 (hex) Brunel University +8016B7 (base 16) Brunel University + School of IS, Computing & Maths + Uxbridge Middlesex UB8 3PH + GB + +00-8D-DA (hex) Link One Co., Ltd. +008DDA (base 16) Link One Co., Ltd. + 601F Chungjuk tower 546-9 + Buchion Gyeonggi-do 420-864 + KR + +C4-98-05 (hex) Minieum Networks, Inc +C49805 (base 16) Minieum Networks, Inc + 6404 International Parkway + Plano Texas 75093 + US + +90-F4-C1 (hex) Rand McNally +90F4C1 (base 16) Rand McNally + 9855 Woods Drive + Skokie IL 60077 + US + +18-19-3F (hex) Tamtron Oy +18193F (base 16) Tamtron Oy + P.O.Box 15 (Vestonkatu 11) + Tampere 33561 + FI + +94-44-44 (hex) LG Innotek +944444 (base 16) LG Innotek + Jangduk-dong, Gwangsan-gu + Gwang-ju 506-731 + KR + +4C-64-D9 (hex) Guangdong Leawin Group Co., Ltd +4C64D9 (base 16) Guangdong Leawin Group Co., Ltd + 10/F, Domain Bldg,No.8 Keji Road(E),HiTech Development District, + Shantou Guangdong 515041 + CN + +94-01-49 (hex) AutoHotBox +940149 (base 16) AutoHotBox + 14090 SW Frwy, Ste. 300 + Sugar Land TX 77478 + US + +1C-B0-94 (hex) HTC Corporation +1CB094 (base 16) HTC Corporation + No. 23, Xinghua Rd., Taoyuan City + Taoyuan County Taiwan 330 + TW + +9C-01-11 (hex) Shenzhen Newabel Electronic Co., Ltd. +9C0111 (base 16) Shenzhen Newabel Electronic Co., Ltd. + 5Flr, South Tower of Sichuan Bld., + Shenzhen Guangdong 518028 + CN + +40-0E-67 (hex) Tremol Ltd. +400E67 (base 16) Tremol Ltd. + 6 Toledo str. + Veliko Turnovo 5000 + BG + +C0-DF-77 (hex) Conrad Electronic SE +C0DF77 (base 16) Conrad Electronic SE + Klaus Conrad Str. 1 + Hirschau Bavaria 92240 + DE + +30-55-ED (hex) Trex Network LLC +3055ED (base 16) Trex Network LLC + Room 505, Tower B Nongke Building, + Beijing 100097 + CN + +F0-F7-55 (hex) Cisco Systems, Inc +F0F755 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +1C-B2-43 (hex) TDC A/S +1CB243 (base 16) TDC A/S + Telehøjen 1 + Odense SØ 5220 + DK + +38-BF-33 (hex) NEC CASIO Mobile Communications +38BF33 (base 16) NEC CASIO Mobile Communications + 1753,Shimonumabe + Kawasaki-shi Kanagawa 211-8666 + JP + +B4-67-E9 (hex) Qingdao GoerTek Technology Co., Ltd. +B467E9 (base 16) Qingdao GoerTek Technology Co., Ltd. + 5F, No.3 Building, Fortune Center + Qingdao Shandong 266061 + CN + +18-67-51 (hex) KOMEG Industrielle Messtechnik GmbH +186751 (base 16) KOMEG Industrielle Messtechnik GmbH + Zum Wasserwerk 3 + Völklingen 66333 + DE + +64-5E-BE (hex) Yahoo! JAPAN +645EBE (base 16) Yahoo! JAPAN + Midtown Tower + Minato-ku Tokyo 107-6211 + JP + +CC-C5-0A (hex) SHENZHEN DAJIAHAO TECHNOLOGY CO.,LTD +CCC50A (base 16) SHENZHEN DAJIAHAO TECHNOLOGY CO.,LTD + 3F Buliding 1, 2th Park TaoHuaYuan Tech- Innovation, + Shenzhen Guangdong 518102 + CN + +1C-B1-7F (hex) NEC Platforms, Ltd. +1CB17F (base 16) NEC Platforms, Ltd. + 800 Shimomata + Kakegawa Shizuoka 436-8501 + JP + +E4-2C-56 (hex) Lilee Systems, Ltd. +E42C56 (base 16) Lilee Systems, Ltd. + 2905 Stender Way, Suite 78 + Santa Clara CA 95054 + US + +48-ED-80 (hex) daesung eltec +48ED80 (base 16) daesung eltec + #509 SJ Technoville, 60-19, Gasan-dong + Seoul 153-769 + KR + +C8-07-18 (hex) TDSi +C80718 (base 16) TDSi + Unit 10 Concept Park + Poole Dorset BH12 4QT + GB + +58-1D-91 (hex) Advanced Mobile Telecom co.,ltd. +581D91 (base 16) Advanced Mobile Telecom co.,ltd. + #608, Yatap Leaders Bldg. 342-1 + Seongnam-si Gyeonggi-do 463-828 + KR + +D8-BF-4C (hex) Victory Concept Electronics Limited +D8BF4C (base 16) Victory Concept Electronics Limited + 4/F., CAC Tower, + Kwun Tong Kowloon KLN + HK + +3C-B9-A6 (hex) Belden Deutschland GmbH +3CB9A6 (base 16) Belden Deutschland GmbH + Stuttgarter Straße 45-51 + Neckartenzlingen 72654 + DE + +8C-0C-A3 (hex) Amper +8C0CA3 (base 16) Amper + Marconi 3, PTM + Tres Cantos Madrid 28760 + US + +94-DF-58 (hex) IJ Electron CO.,Ltd. +94DF58 (base 16) IJ Electron CO.,Ltd. + 401 ACE HIGHEND8, 345-4 GASAN-DONG + SEOUL 153-802 + KR + +48-D5-4C (hex) Jeda Networks +48D54C (base 16) Jeda Networks + 2618 San Miguel Drive + Newport Beach Ca. 92660 + US + +8C-DE-52 (hex) ISSC Technologies Corp. +8CDE52 (base 16) ISSC Technologies Corp. + 4F, No.8, Dusing Rd., + Hsinchu City 30078 + TW + +08-25-22 (hex) ADVANSEE +082522 (base 16) ADVANSEE + 9 Rue Alfred Kastler + NANTES 44307 + FR + +4C-2F-9D (hex) ICM Controls +4C2F9D (base 16) ICM Controls + 7313 William Barry Blvd + North Syracuse NY 13212 + US + +E4-67-BA (hex) Danish Interpretation Systems A/S +E467BA (base 16) Danish Interpretation Systems A/S + Vestre Teglgade 12 + Copenhagen SV 2450 + DK + +BC-B8-52 (hex) Cybera, Inc. +BCB852 (base 16) Cybera, Inc. + 9009 Carothers Parkway + Franklin TN 37067 + US + +C4-93-00 (hex) 8Devices +C49300 (base 16) 8Devices + Gedimino st. 47 + Kaunas LT 44242 + LT + +6C-A6-82 (hex) EDAM information & communications +6CA682 (base 16) EDAM information & communications + 601, Hanlim Veture town, 689-6 + Gunpo Gyenggi-Do 435-862 + KR + +28-D5-76 (hex) Premier Wireless, Inc. +28D576 (base 16) Premier Wireless, Inc. + 4222 E. La Palma Ave. + Anaheim CA 92807 + US + +70-D6-B6 (hex) Metrum Technologies +70D6B6 (base 16) Metrum Technologies + 315 South University Parks Drive + Waco Texas 76701 + US + +C0-A0-DE (hex) Multi Touch Oy +C0A0DE (base 16) Multi Touch Oy + Henry Fordin katu 6 + Helsinki 00150 + FI + +40-BC-8B (hex) itelio GmbH +40BC8B (base 16) itelio GmbH + Franz-Larcher-Straße 4 + Kiefersfelden Bavaria 83088 + DE + +9C-A1-34 (hex) Nike, Inc. +9CA134 (base 16) Nike, Inc. + 1 Bowerman Drive + Beaverton OR 97005 + US + +50-FC-30 (hex) Treehouse Labs +50FC30 (base 16) Treehouse Labs + 601 Great Oaks Dr. + Round Rock TX 78681 + US + +B8-96-74 (hex) AllDSP GmbH & Co. KG +B89674 (base 16) AllDSP GmbH & Co. KG + Spenglerstrasse 6 + Hamm NRW 59067 + DE + +48-E1-AF (hex) Vity +48E1AF (base 16) Vity + 180 rue Pierre Landais + Caudan 56 56850 + FR + +1C-BB-A8 (hex) OJSC Ufimskiy Zavod Promsvyaz +1CBBA8 (base 16) OJSC Ufimskiy Zavod Promsvyaz + 39, 50 let SSSR + Ufa Bashkortostan 450071 + RU + +00-6B-A0 (hex) SHENZHEN UNIVERSAL INTELLISYS PTE LTD +006BA0 (base 16) SHENZHEN UNIVERSAL INTELLISYS PTE LTD + ROOM 1607-1608,XINGJI MANSION + SHENZHEN GUANGDONG 518104 + CN + +A8-98-C6 (hex) Shinbo Co., Ltd. +A898C6 (base 16) Shinbo Co., Ltd. + 203-14, Anyang 7-Dong, Manan-Gu + Anyang-Si Kyungki-Do 430-817 + KR + +B4-21-1D (hex) Beijing GuangXin Technology Co., Ltd +B4211D (base 16) Beijing GuangXin Technology Co., Ltd + Room 313,B Bld,Horizon International Tower,Zhichun Road,6,Haidian District,Beijing City,P.R.China + Beijing 100086 + CN + +90-3C-AE (hex) Yunnan KSEC Digital Technology Co.,Ltd. +903CAE (base 16) Yunnan KSEC Digital Technology Co.,Ltd. + 3F,NO.176 Keyi ROAD,High and New Technological Industrial Development Zone + Kunming Yunnan 650106 + CN + +70-70-4C (hex) Purple Communications, Inc +70704C (base 16) Purple Communications, Inc + 595 Menlo + Rocklin CA 95765 + US + +D8-97-60 (hex) C2 Development, Inc. +D89760 (base 16) C2 Development, Inc. + 127 S Bell Ave + Ames IA 50010 + US + +F4-7A-CC (hex) SolidFire, Inc. +F47ACC (base 16) SolidFire, Inc. + 1620 Pearl Street + Boulder Colorado 80302 + US + +90-56-82 (hex) Lenbrook Industries Limited +905682 (base 16) Lenbrook Industries Limited + 633 Granite Court + Pickering Ontario L1W 3K1 + CA + +F0-DA-7C (hex) RLH INDUSTRIES,INC. +F0DA7C (base 16) RLH INDUSTRIES,INC. + 936 N. MAIN ST. + ORANGE CA 92867 + US + +AC-31-9D (hex) Shenzhen TG-NET Botone Technology Co.,Ltd. +AC319D (base 16) Shenzhen TG-NET Botone Technology Co.,Ltd. + 2nd floor,Building No.6,Pengtengda industrial zone,Huarong road,Dalang Street Office, + Shenzhen Guangdong 518109 + CN + +20-10-7A (hex) Gemtek Technology Co., Ltd. +20107A (base 16) Gemtek Technology Co., Ltd. + No. 1 Jen Ai Road Hsinchu Industrial Park Hukou, Hsinchu 30352 TAIWAN, REPUBLIC OF CHINA + Hsinchu TAIWAN 30352 + TW + +78-DD-D6 (hex) c-scape +78DDD6 (base 16) c-scape + westerkade 22 + Gouda 2802 SL + NL + +C0-91-32 (hex) Patriot Memory +C09132 (base 16) Patriot Memory + 47027 Benicia + Fremont CA 94555 + US + +90-18-5E (hex) Apex Tool Group GmbH & Co OHG +90185E (base 16) Apex Tool Group GmbH & Co OHG + Industriestraße 1 + Westhausen 73463 + DE + +F8-FE-5C (hex) Reciprocal Labs Corp +F8FE5C (base 16) Reciprocal Labs Corp + 3 S. Pinckney St. + Madison WI 53703 + US + +6C-9C-ED (hex) Cisco Systems, Inc +6C9CED (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +24-86-F4 (hex) Ctek, Inc. +2486F4 (base 16) Ctek, Inc. + 34 Miraleste Plaza + Rancho Palos Verdes California 90275 + US + +C4-23-7A (hex) WhizNets Inc. +C4237A (base 16) WhizNets Inc. + 830 Stewart Drive + Sunnyvale California 94085 + US + +F4-E6-D7 (hex) Solar Power Technologies, Inc. +F4E6D7 (base 16) Solar Power Technologies, Inc. + 3006 Bee Caves Rd. + Austin Texas 78746 + US + +B8-74-24 (hex) Viessmann Elektronik GmbH +B87424 (base 16) Viessmann Elektronik GmbH + Beetwiese 2 + Allendorf (Eder) 35108 + DE + +B4-51-F9 (hex) NB Software +B451F9 (base 16) NB Software + Eichhalde 3 + Weissach i. T. Baden-Württemberg 71554 + DE + +30-16-8D (hex) ProLon +30168D (base 16) ProLon + 17510 rue Charles, Suite 100 + Mirabel Quebec J7J 1X9 + CA + +E4-AF-A1 (hex) HES-SO +E4AFA1 (base 16) HES-SO + Case postale 2134 + Sion 1950 + CH + +A8-87-ED (hex) ARC Wireless LLC +A887ED (base 16) ARC Wireless LLC + 6330 N. Washington St. + Denver CO 80216 + US + +D4-D2-49 (hex) Power Ethernet +D4D249 (base 16) Power Ethernet + 4th Floor, Holborn Gate + London WC2A 1AH + GB + +80-42-7C (hex) Adolf Tedsen GmbH & Co. KG +80427C (base 16) Adolf Tedsen GmbH & Co. KG + Otto-Hahn-Str. 13-15 + Trittau Schleswig-Holstein D-22946 + DE + +E0-DA-DC (hex) JVC KENWOOD Corporation +E0DADC (base 16) JVC KENWOOD Corporation + 3-12, Moriyacho, Kanagawa-ku + Yokohama-shi Kanagawa 221-0022 + JP + +E8-43-B6 (hex) QNAP Systems, Inc. +E843B6 (base 16) QNAP Systems, Inc. + 2F., No.22, Zhongxing Rd., Xizhi Dist. + New Taipei City 221 + TW + +B8-9B-C9 (hex) SMC Networks Inc +B89BC9 (base 16) SMC Networks Inc + 20 Mason + Irvine CA 92618 + US + +40-9F-C7 (hex) BAEKCHUN I&C Co., Ltd. +409FC7 (base 16) BAEKCHUN I&C Co., Ltd. + 67-5, Gyesu-dong + Bucheon-si Gyeonggi-do 422-070 + KR + +00-FC-58 (hex) WebSilicon Ltd. +00FC58 (base 16) WebSilicon Ltd. + 25, Habarzel St., + Tel-Aviv 69710 + IL + +98-35-71 (hex) Sub10 Systems Ltd +983571 (base 16) Sub10 Systems Ltd + Ash House + Kingsteignton Devon TQ12 3RZ + GB + +54-04-A6 (hex) ASUSTek COMPUTER INC. +5404A6 (base 16) ASUSTek COMPUTER INC. + 15,Li-Te Rd., Peitou, Taipei 112, Taiwan + Taipei Taiwan 112 + TW + +18-6D-99 (hex) Adanis Inc. +186D99 (base 16) Adanis Inc. + #2015-2016 Geumkang Penterium + Hakuro, Dongan-Gu, Anyang-Si Kyunggi-Do 431-060 + KR + +A0-E2-01 (hex) AVTrace Ltd.(China) +A0E201 (base 16) AVTrace Ltd.(China) + RM704, District B1, Originality Building, No.162 KeXue Avenue Science Town,GUANGZHOU,CHINA + GUANGZHOU GUANGDONG 510611 + US + +F0-DE-B9 (hex) ShangHai Y&Y Electronics Co., Ltd +F0DEB9 (base 16) ShangHai Y&Y Electronics Co., Ltd + No.3, 588 Tianxiong Road, Shanghai International Medical Zone(SIMZ), + Shanghai 201318 + CN + +7C-A6-1D (hex) MHL, LLC +7CA61D (base 16) MHL, LLC + 1140 East Arques Avenue + Sunnyvale CA 94085 + US + +9C-F6-7D (hex) Ricardo Prague, s.r.o. +9CF67D (base 16) Ricardo Prague, s.r.o. + Thamova 13 + Praha 8 186 00 + CZ + +F8-2F-5B (hex) eGauge Systems LLC +F82F5B (base 16) eGauge Systems LLC + 1510 28th St, Suite 205 + Boulder CO 80303 + US + +98-C8-45 (hex) PacketAccess +98C845 (base 16) PacketAccess + 611 North Main Street + Goldfield IA 50543 + US + +98-90-80 (hex) Linkpower Network System Inc Ltd. +989080 (base 16) Linkpower Network System Inc Ltd. + Room 202, Build 18, Shahe Industrial Zone + Shenzhen Guangdong 518053 + CN + +F8-33-76 (hex) Good Mind Innovation Co., Ltd. +F83376 (base 16) Good Mind Innovation Co., Ltd. + 20, Lane 200, Cheng Hu Rd. + Kaohsiung 833 + TW + +50-F6-1A (hex) Kunshan JADE Technologies co., Ltd. +50F61A (base 16) Kunshan JADE Technologies co., Ltd. + 12th Floor, Southern Building, Pudong Software Park,828 Xueyuan Road, Bacheng Town + Kunshan Jiangsu 215311 + CN + +54-20-18 (hex) Tely Labs +542018 (base 16) Tely Labs + 545 Middlefield Road + Menlo Park CA 94025 + US + +58-1F-EF (hex) Tuttnaer LTD +581FEF (base 16) Tuttnaer LTD + Har-Tuv B + Beith Shemesh 99000 + IL + +58-BD-A3 (hex) Nintendo Co., Ltd. +58BDA3 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +F8-F2-5A (hex) G-Lab GmbH +F8F25A (base 16) G-Lab GmbH + Schiffbaustrasse 10 + Zurich CH 8005 + CH + +30-7E-CB (hex) SFR +307ECB (base 16) SFR + 40/42 Quai du point du jour + Boulongne Billancourt Hauts de Seine 92659 + FR + +68-F1-25 (hex) Data Controls Inc. +68F125 (base 16) Data Controls Inc. + Fukashiro Bldg, 8F + Taito-ku Tokyo 111-0052 + JP + +BC-76-4E (hex) Rackspace US, Inc. +BC764E (base 16) Rackspace US, Inc. + 5000 Walzem Rd. + San Antonio TX 78218 + US + +CC-C8-D7 (hex) CIAS Elettronica srl +CCC8D7 (base 16) CIAS Elettronica srl + Via Giovanni Durando 38 + Milan 20158 + IT + +84-D3-2A (hex) IEEE 1905.1 +84D32A (base 16) IEEE 1905.1 + 445 Hoes Lane + Piscataway NJ 08855-1331 + US + +4C-02-89 (hex) LEX COMPUTECH CO., LTD +4C0289 (base 16) LEX COMPUTECH CO., LTD + 3F, No.77, LI DE St. Chung Ho Dist., + New Taipei City 23556 + TW + +C0-E5-4E (hex) ARIES Embedded GmbH +C0E54E (base 16) ARIES Embedded GmbH + Schöngeisinger Str. 84 + Fürstenfeldbruck D-82256 + DE + +F8-C0-01 (hex) Juniper Networks +F8C001 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +18-7C-81 (hex) Valeo Vision Systems +187C81 (base 16) Valeo Vision Systems + Dunmore Road + County Galway + IE + +AC-CC-8E (hex) Axis Communications AB +ACCC8E (base 16) Axis Communications AB + Emdalavägen 14 + LUND 22369 + SE + +8C-94-CF (hex) Encell Technology, Inc. +8C94CF (base 16) Encell Technology, Inc. + 1412 Sachem Place, Suite 204 + Charlottesville VA 22901 + US + +6C-A7-80 (hex) Nokia Corporation +6CA780 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +30-57-AC (hex) IRLAB LTD. +3057AC (base 16) IRLAB LTD. + 3rd Floor, 2A Biulding, Huihao Industrial Park + Shenzhen Guang Dong 518106 + CN + +84-2B-50 (hex) Huria Co.,Ltd. +842B50 (base 16) Huria Co.,Ltd. + #190-28 Chungchun-2Dong + Incheon 403-032 + KR + +48-F7-F1 (hex) Nokia +48F7F1 (base 16) Nokia + 600 March Road + Kanata Ontario K2K 2E6 + CA + +8C-8E-76 (hex) taskit GmbH +8C8E76 (base 16) taskit GmbH + Groß-Berliner Damm 37 + Berlin 12487 + DE + +A0-13-3B (hex) HiTi Digital, Inc. +A0133B (base 16) HiTi Digital, Inc. + 9F., No.225, Sec. 3, Beixin Rd., Xindian Dist., + Xindian Dist. New Taipei City 231 + TW + +9C-57-11 (hex) Feitian Xunda(Beijing) Aeronautical Information Technology Co., Ltd. +9C5711 (base 16) Feitian Xunda(Beijing) Aeronautical Information Technology Co., Ltd. + Building B,Horizon International Tower,No.6 Zhichun Rd,Haidian District, + Beijing 100088 + CN + +88-F4-88 (hex) cellon communications technology(shenzhen)Co.,Ltd. +88F488 (base 16) cellon communications technology(shenzhen)Co.,Ltd. + 13/F C Building,Gaoxin S.Ave.,Hi-Tech Industrial Park,Nanshan,shenzhen518057,PRC + shenzhen Guangdong 518057 + CN + +44-8E-12 (hex) DT Research, Inc. +448E12 (base 16) DT Research, Inc. + 2000 Concourse Drive + San Jose CA 95131 + US + +B8-BB-6D (hex) ENERES Co.,Ltd. +B8BB6D (base 16) ENERES Co.,Ltd. + 1907 Tokyo Art Center + Adahci-ku Tokyo 120-0034 + JP + +14-37-3B (hex) PROCOM Systems +14373B (base 16) PROCOM Systems + #1001, Kranz Techno, 5442-1 + Seongnam-si Gyunggi-do 462-729 + KR + +18-97-FF (hex) TechFaith Wireless Technology Limited +1897FF (base 16) TechFaith Wireless Technology Limited + Building C, Jia No.5, Rongchang East Street, BDA District, + Beijing 100176 + CN + +4C-55-85 (hex) Hamilton Systems +4C5585 (base 16) Hamilton Systems + 3143 Production Drive + Fairfield OH 45014 + US + +EC-EA-03 (hex) DARFON LIGHTING CORP +ECEA03 (base 16) DARFON LIGHTING CORP + 167, Shanying Road + Gueishan Taoyuan 33341 + TW + +30-F9-ED (hex) Sony Corporation +30F9ED (base 16) Sony Corporation + Gotenyama Tec 5-1-2 + Tokyo Shinagawa-ku 141-0001 + JP + +58-2E-FE (hex) Lighting Science Group +582EFE (base 16) Lighting Science Group + 1227 South Patrick Drive + Satellite Beach FL 32937 + US + +CC-60-BB (hex) Empower RF Systems +CC60BB (base 16) Empower RF Systems + 316 W. Florence Ave + Inglewood CA 90301 + US + +7C-DD-20 (hex) IOXOS Technologies S.A. +7CDD20 (base 16) IOXOS Technologies S.A. + 4 Chemin de Fontenailles + GLAND VAUD CH-1196 + CH + +EC-F2-36 (hex) NEOMONTANA ELECTRONICS +ECF236 (base 16) NEOMONTANA ELECTRONICS + Mladost-4, bl. 483, mag. 13 + Sofia 1715 + BG + +04-18-B6 (hex) Private +0418B6 (base 16) Private + +E4-A5-EF (hex) TRON LINK ELECTRONICS CO., LTD. +E4A5EF (base 16) TRON LINK ELECTRONICS CO., LTD. + FLAT A, 20/F., BLOCK 4,ON NING GARDEN, + KOWLOON 999077 + HK + +30-71-B2 (hex) Hangzhou Prevail Optoelectronic Equipment Co.,LTD. +3071B2 (base 16) Hangzhou Prevail Optoelectronic Equipment Co.,LTD. + Industrial Development Area, Guali Town, + Hangzhou City Zhe Jiang 311241 + CN + +DC-CE-41 (hex) FE GLOBAL HONG KONG LIMITED +DCCE41 (base 16) FE GLOBAL HONG KONG LIMITED + FLAT 204-205 2/F LAFORD CENTRE838 LAI CHI KOK RD CHEUNG SHA WAN KL + SHENZHEN 518057 + CN + +FC-6C-31 (hex) LXinstruments GmbH +FC6C31 (base 16) LXinstruments GmbH + Herrenberger Str. 130 + Boeblingen 71034 + DE + +70-5C-AD (hex) Konami Gaming Inc +705CAD (base 16) Konami Gaming Inc + 585 Trade Center Drive + Las Vegas Nevada 89119 + US + +3C-6F-45 (hex) Fiberpro Inc. +3C6F45 (base 16) Fiberpro Inc. + 59-4 Jang-dong, Yusong-gu + Deajeon 305-343 + KR + +70-31-87 (hex) ACX GmbH +703187 (base 16) ACX GmbH + Äußere Zwickauer Straße 8 + Zwickau 08064 + DE + +30-E4-DB (hex) Cisco Systems, Inc +30E4DB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +88-E0-F3 (hex) Juniper Networks +88E0F3 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +80-97-1B (hex) Altenergy Power System,Inc. +80971B (base 16) Altenergy Power System,Inc. + No.1 Yatai Road, + Jiaxing City, Zhejiang Province, 314050 + CN + +58-76-75 (hex) Beijing ECHO Technologies Co.,Ltd +587675 (base 16) Beijing ECHO Technologies Co.,Ltd + NO1 Street 4 Shangdi + BeiJing 100085 + CN + +0C-51-F7 (hex) CHAUVIN ARNOUX +0C51F7 (base 16) CHAUVIN ARNOUX + LA QUEUE DEVEE + REUX PONT L EVEQUE 14130 + FR + +0C-FC-83 (hex) Airoha Technology Corp., +0CFC83 (base 16) Airoha Technology Corp., + 5F, No.6-5, Dushing Road , Hsinchu Science Park + Hsinchu 300 + TW + +00-7F-28 (hex) Actiontec Electronics, Inc +007F28 (base 16) Actiontec Electronics, Inc + 3301 Olcott St. + Santa Clara CA 95054 + US + +80-47-31 (hex) Packet Design, Inc. +804731 (base 16) Packet Design, Inc. + 2455 Augustine Drive + Santa Clara CA 95054 + US + +B0-9B-D4 (hex) GNH Software India Private Limited +B09BD4 (base 16) GNH Software India Private Limited + 9/14 Sengani Amman Koil Street + Chennai Tamilnadu 600032 + IN + +F0-8B-FE (hex) COSTEL.,CO.LTD +F08BFE (base 16) COSTEL.,CO.LTD + 223-39, Sangdaewon-Dong, Jungwon-Gu + Seongnam-si Kyunggi-Do 462-807 + KR + +3C-26-D5 (hex) Sotera Wireless +3C26D5 (base 16) Sotera Wireless + 9444 Waples Street + San Diego CA 92121 + US + +E8-4E-06 (hex) EDUP INTERNATIONAL (HK) CO., LTD +E84E06 (base 16) EDUP INTERNATIONAL (HK) CO., LTD + 20D Room, Block B, Modern Windows Buidling, FuTian District, + Shenzhen Guangdong 518028 + CN + +00-07-7D (hex) Cisco Systems, Inc +00077D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +CC-D9-E9 (hex) SCR Engineers Ltd. +CCD9E9 (base 16) SCR Engineers Ltd. + 6 Haomanut St. + Netanya 42504 + IL + +34-A7-09 (hex) Trevil srl +34A709 (base 16) Trevil srl + Via Copernico 1 + Pozzo d'Adda MI 20060 + IT + +E0-C9-22 (hex) Jireh Energy Tech., Ltd. +E0C922 (base 16) Jireh Energy Tech., Ltd. + #606 Seoul Forest Hallasigmavalley, 325-2 + Seoul Seongdong-Gu 133-120 + KR + +90-5F-8D (hex) modas GmbH +905F8D (base 16) modas GmbH + Belziger Str. 69-71 + Berlin 10823 + DE + +98-29-3F (hex) Fujian Start Computer Equipment Co.,Ltd +98293F (base 16) Fujian Start Computer Equipment Co.,Ltd + No.68 Hongshangyuan Road, + Fuzhou City, Fujian Province, 350002 + CN + +B4-5C-A4 (hex) Thing-talk Wireless Communication Technologies Corporation Limited +B45CA4 (base 16) Thing-talk Wireless Communication Technologies Corporation Limited + 498 Guo Shou Jing Road, Suite 10402 + Shanghai 201203 + CN + +90-8D-1D (hex) GH Technologies +908D1D (base 16) GH Technologies + 5022 Binhe Road, Block B, United Plaza + Shenzhen 518026 + CN + +44-4F-5E (hex) Pan Studios Co.,Ltd. +444F5E (base 16) Pan Studios Co.,Ltd. + 1F., NO.402, SEC. 2, JHONGYANG N. RD., BEITOU DISTRICT, + TAIPEI CITY 11258 + TW + +D0-AF-B6 (hex) Linktop Technology Co., LTD +D0AFB6 (base 16) Linktop Technology Co., LTD + 2F Guangye Buliding, Torch Hi-Tech, + Xiamen Fujian 361006 + CN + +98-EC-65 (hex) Cosesy ApS +98EC65 (base 16) Cosesy ApS + Tyttebaervej 2 + Ans Jylland DK-8643 + DK + +AC-C9-35 (hex) Ness Corporation +ACC935 (base 16) Ness Corporation + 4/167 Prospect Highway + Sydney NSW 2147 + AU + +00-8D-4E (hex) CJSC NII STT +008D4E (base 16) CJSC NII STT + N.Leningradskaya str, 10 + Smolensk 214012 + RU + +98-F8-DB (hex) Marini Impianti Industriali s.r.l. +98F8DB (base 16) Marini Impianti Industriali s.r.l. + Via delle Province, 6A + Cisterna di Latina 04012 + IT + +E4-12-89 (hex) topsystem Systemhaus GmbH +E41289 (base 16) topsystem Systemhaus GmbH + Monnetstraße 24 + Würselen NRW 52146 + DE + +58-E8-08 (hex) AUTONICS CORPORATION +58E808 (base 16) AUTONICS CORPORATION + 41-5 YONGDANG-DONG + YANGSAN-SI KYEONGNAM 626-847 + KR + +DC-05-ED (hex) Nabtesco Corporation +DC05ED (base 16) Nabtesco Corporation + 9-18, Kaigan 1-chome + Minato-ku Tokyo 105-0022 + JP + +4C-98-EF (hex) Zeo +4C98EF (base 16) Zeo + 320 Nevada St + Newton MA 02460 + US + +00-A1-DE (hex) ShenZhen ShiHua Technology CO.,LTD +00A1DE (base 16) ShenZhen ShiHua Technology CO.,LTD + Room505,5/F TsingYi Building,LangShan 2ed Road,High-Tech Industrial Park, + ShenZhen GuangDong 518052 + CN + +80-6C-BC (hex) NET New Electronic Technology GmbH +806CBC (base 16) NET New Electronic Technology GmbH + Lerchenberg 7 + Finning Bavarian 86923 + DE + +90-90-60 (hex) RSI VIDEO TECHNOLOGIES +909060 (base 16) RSI VIDEO TECHNOLOGIES + 56, Rue Jean-Giraudoux - BAT 60 + STRASBOURG Bas-Rhin 67200 + FR + +BC-81-99 (hex) BASIC Co.,Ltd. +BC8199 (base 16) BASIC Co.,Ltd. + Keiefu-Building 9F + Minato-ku Tokyo 108-0014 + JP + +DC-A7-D9 (hex) Compressor Controls Corp +DCA7D9 (base 16) Compressor Controls Corp + 4725 121st Street + Des Moines Iowa 50323 + US + +38-FE-C5 (hex) Ellips B.V. +38FEC5 (base 16) Ellips B.V. + Esp 300 + Eindhoven Noord-Brabant 5633 AE + NL + +C4-55-A6 (hex) Cadac Holdings Ltd +C455A6 (base 16) Cadac Holdings Ltd + 1 New Street + Luton Bedfordshire LU1 5DX + GB + +5C-77-57 (hex) Haivision Network Video +5C7757 (base 16) Haivision Network Video + 4445 Garand + Montreal QC H4R 2H9 + CA + +D4-D8-98 (hex) Korea CNO Tech Co., Ltd +D4D898 (base 16) Korea CNO Tech Co., Ltd + #240-1,Uigok-Ri + Mungyeong-Si Gyeongsangbuk-do 745-853 + KR + +B4-AA-4D (hex) Ensequence, Inc. +B4AA4D (base 16) Ensequence, Inc. + 111 SW 5th Ave Suite 1400 + Portland OR 97204 + US + +B8-3D-4E (hex) Shenzhen Cultraview Digital Technology Co.,Ltd Shanghai Branch +B83D4E (base 16) Shenzhen Cultraview Digital Technology Co.,Ltd Shanghai Branch + 2/F,Building#5,1690Cailun Road,Zhangjiang Hi-tech Park, + Shanghai 201203 + CN + +50-87-B8 (hex) Nuvyyo Inc +5087B8 (base 16) Nuvyyo Inc + 1 Smythe Rd + Carleton Place Ontario K7C4J4 + CA + +C0-EA-E4 (hex) Sonicwall +C0EAE4 (base 16) Sonicwall + 2001 Logic Drive + San Jose CA 95124-3452 + US + +08-38-A5 (hex) Funkwerk plettac electronic GmbH +0838A5 (base 16) Funkwerk plettac electronic GmbH + Wuerzburger Str. 150 + Fuerth Bavaria 90766 + DE + +CC-1E-FF (hex) Metrological Group BV +CC1EFF (base 16) Metrological Group BV + Mariniersweg 151 + Rotterdam Zuid-Holland 3011NK + NL + +18-4E-94 (hex) MESSOA TECHNOLOGIES INC. +184E94 (base 16) MESSOA TECHNOLOGIES INC. + 13611 12th St., Unit B + Chino CA 91710 + US + +6C-39-1D (hex) Beijing ZhongHuaHun Network Information center +6C391D (base 16) Beijing ZhongHuaHun Network Information center + 6F BeiAo Mansion,HuiXin East Street A2, + Beijing 100029 + CN + +80-B3-2A (hex) UK Grid Solutions Ltd +80B32A (base 16) UK Grid Solutions Ltd + Harry Kerr Drive + Stafford Staffordshire ST17 4LX + GB + +40-55-39 (hex) Cisco Systems, Inc +405539 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +E0-F2-11 (hex) Digitalwatt +E0F211 (base 16) Digitalwatt + Via Dante, 18 + Renate Brianza MB 20055 + IT + +F8-69-71 (hex) Seibu Electric Co., +F86971 (base 16) Seibu Electric Co., + 1458-7 + Hachioji Tokyo 193-0941 + JP + +44-AA-27 (hex) udworks Co., Ltd. +44AA27 (base 16) udworks Co., Ltd. + #810, Byuksan3cha Digital Valley, 212-13, Guro-dong, Guro-gu + Seoul 152-775 + KR + +E8-F9-28 (hex) RFTECH SRL +E8F928 (base 16) RFTECH SRL + VIA VENETO, 22 + SCHIO VICENZA 36015 + IT + +1C-95-5D (hex) I-LAX ELECTRONICS INC. +1C955D (base 16) I-LAX ELECTRONICS INC. + 2283 ARGENTIA RD.- UNIT # 10 + MISSISSAUGA ON. L5N 5Z2 + CA + +60-F5-9C (hex) CRU-Dataport +60F59C (base 16) CRU-Dataport + 1000 SE Tech Center Drive + Vancouver WA 98683 + US + +B0-A7-2A (hex) Ensemble Designs, Inc. +B0A72A (base 16) Ensemble Designs, Inc. + 870 Gold Flat Road + Nevada City CA 95959 + US + +64-00-F1 (hex) Cisco Systems, Inc +6400F1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +B8-F4-D0 (hex) Herrmann Ultraschalltechnik GmbH & Co. Kg +B8F4D0 (base 16) Herrmann Ultraschalltechnik GmbH & Co. Kg + Descostraße 3-9 + Karlsbad Baden-Württemberg 76307 + DE + +08-AC-A5 (hex) Benu Video, Inc. +08ACA5 (base 16) Benu Video, Inc. + 300 Concord Rd., Suite #110 + Billerica MA 01821 + US + +58-6D-8F (hex) Cisco-Linksys, LLC +586D8F (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +10-E3-C7 (hex) Seohwa Telecom +10E3C7 (base 16) Seohwa Telecom + 678 Seohwa Bldg + Gasan-Dong, Gumcheon-Gu Seoul 153-803 + KR + +74-65-D1 (hex) Atlinks +7465D1 (base 16) Atlinks + 30 Avenue Geroge V + Paris 75008 + FR + +04-0A-83 (hex) Alcatel-Lucent +040A83 (base 16) Alcatel-Lucent + Via Trento, 30 + Vimenrcate MB 2059 + IT + +C4-56-00 (hex) Galleon Embedded Computing +C45600 (base 16) Galleon Embedded Computing + Grenseveien 97c + Oslo Oslo N-0602 + NO + +BC-3E-13 (hex) Accordance Systems Inc. +BC3E13 (base 16) Accordance Systems Inc. + 2F, No. 31, Sec. 6, Hsin Yi Road + Taipei 11085 + TW + +A8-1B-18 (hex) XTS CORP +A81B18 (base 16) XTS CORP + 10125 NW 116TH WAY, SUITE 5 + MEDLEY FLORIDA 33178 + US + +D0-A3-11 (hex) Neuberger Gebäudeautomation GmbH +D0A311 (base 16) Neuberger Gebäudeautomation GmbH + Oberer Kaiserweg 6 + Rothenburg o.d.T. Bayern 91541 + DE + +04-1D-10 (hex) Dream Ware Inc. +041D10 (base 16) Dream Ware Inc. + 5-23-7 Masugata, Tama-ku, + Kawasaki Kanagawa 214-0032 + JP + +80-14-40 (hex) Sunlit System Technology Corp +801440 (base 16) Sunlit System Technology Corp + 8F, No.19,Lane 120, Sec1, Neihu Rd. + Tapiei 114 + TW + +18-0B-52 (hex) Nanotron Technologies GmbH +180B52 (base 16) Nanotron Technologies GmbH + Alt-Moabit 60 + Berlin 10555 + DE + +DC-07-C1 (hex) HangZhou QiYang Technology Co.,Ltd. +DC07C1 (base 16) HangZhou QiYang Technology Co.,Ltd. + Floor 5, Building 2, Road XiYuanYi, WestLake Technology Park, + HangZhou ZheJiang 310028 + CN + +C0-A2-6D (hex) Abbott Point of Care +C0A26D (base 16) Abbott Point of Care + 400 College Road East + Princeton NJ 08540 + US + +00-BB-8E (hex) HME Co., Ltd. +00BB8E (base 16) HME Co., Ltd. + No.200 , Liao Bei Str.,San Min Dist., + Kaohsiung 807 + TW + +D8-2A-7E (hex) Nokia Corporation +D82A7E (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +80-1F-02 (hex) Edimax Technology Co. Ltd. +801F02 (base 16) Edimax Technology Co. Ltd. + No. 278, Xinhu 1st Road + Taipei City Neihu Dist 248 + TW + +58-EE-CE (hex) Icon Time Systems +58EECE (base 16) Icon Time Systems + 15201 NW Greenbrier Parkway + Beaverton OR 97006 + US + +64-7F-DA (hex) TEKTELIC Communications Inc. +647FDA (base 16) TEKTELIC Communications Inc. + 7657 10th Street NE + Calgary Alberta T2E 8X2 + CA + +AC-06-13 (hex) Senselogix Ltd +AC0613 (base 16) Senselogix Ltd + 56 Carlton Court, Ford William Morgan + St. Asaph Debighshire LL17 0JG + GB + +74-78-18 (hex) Jurumani Solutions +747818 (base 16) Jurumani Solutions + 321 14th Road + Midrand 1685 + ZA + +E0-1F-0A (hex) Xslent Energy Technologies. LLC +E01F0A (base 16) Xslent Energy Technologies. LLC + 7428 Redwood Blvd + Novato CA 94945 + US + +44-37-19 (hex) 2 Save Energy Ltd +443719 (base 16) 2 Save Energy Ltd + The Annexe, Field House Barn + Sherborne St John Hampshire RG24 9LR + GB + +84-EA-99 (hex) Vieworks +84EA99 (base 16) Vieworks + 6F Suntechcity 2,307-2 Sangdaewon-dong, Jungwon-gu + Seongnam Gyeonggi 462-806 + KR + +E0-0C-7F (hex) Nintendo Co., Ltd. +E00C7F (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +E4-8A-D5 (hex) RF WINDOW CO., LTD. +E48AD5 (base 16) RF WINDOW CO., LTD. + 14F, Daerung Posttower3 + Seoul 152-746 + KR + +FC-F1-CD (hex) OPTEX-FA CO.,LTD. +FCF1CD (base 16) OPTEX-FA CO.,LTD. + 91 Awata-cho + Kyoto 600-8815 + JP + +44-25-BB (hex) Bamboo Entertainment Corporation +4425BB (base 16) Bamboo Entertainment Corporation + 179 South Street + Boston MA 02111 + US + +7C-DA-84 (hex) Dongnian Networks Inc. +7CDA84 (base 16) Dongnian Networks Inc. + 90 Wensan Road, Building 8-A303 + Hangzhou Zhejiang 310012 + CN + +BC-C6-1A (hex) SPECTRA EMBEDDED SYSTEMS +BCC61A (base 16) SPECTRA EMBEDDED SYSTEMS + Khasra No. 24, Village Ghumman,1st Floor, Chawla Mansion, + Parwanoo Himachal Pradesh 173 220 + IN + +04-70-BC (hex) Globalstar Inc. +0470BC (base 16) Globalstar Inc. + 461 S Milpitas Blvd + Milpitas CA 95035 + US + +88-DD-79 (hex) Voltaire +88DD79 (base 16) Voltaire + 13, Zarchin St + Raanana 43662 + IL + +64-F9-87 (hex) Avvasi Inc. +64F987 (base 16) Avvasi Inc. + 103 Randall Dr. + Waterloo ON N2V 1C5 + CA + +D8-5D-84 (hex) CAx soft GmbH +D85D84 (base 16) CAx soft GmbH + Noettinger Strasse 3 + Karlsbad BW 76307 + DE + +D4-E3-2C (hex) S. Siedle & Sohne +D4E32C (base 16) S. Siedle & Sohne + Bregstrasse 1 + Furtwangen D-78120 + DE + +7C-6A-DB (hex) SafeTone Technology Co.,Ltd +7C6ADB (base 16) SafeTone Technology Co.,Ltd + Room 323,ZhuouJi Plaza,No.16 AnDe Road,East District, + Beijing 100011 + CN + +90-2E-87 (hex) LabJack +902E87 (base 16) LabJack + 3232 S Vance St STE 100 + Lakewood CO 80227 + US + +A4-24-B3 (hex) FlatFrog Laboratories AB +A424B3 (base 16) FlatFrog Laboratories AB + Magistratsvägen 10 + Lund Skåne 22643 + SE + +94-CD-AC (hex) Creowave Oy +94CDAC (base 16) Creowave Oy + Lentokatu 2 + Oulunsalo FIN-90460 + FI + +14-4C-1A (hex) Max Communication GmbH +144C1A (base 16) Max Communication GmbH + Siemensstrasse 47 + Rellingen 25462 + DE + +34-08-04 (hex) D-Link Corporation +340804 (base 16) D-Link Corporation + No.289, Sinhu 3rd Rd., Neihu District, + Taipei City 114 + TW + +F0-5D-89 (hex) Dycon Limited +F05D89 (base 16) Dycon Limited + Unit D + Mountain Ash Rhondda Cynon Taff CF45 4ER + GB + +AC-80-D6 (hex) Hexatronic AB +AC80D6 (base 16) Hexatronic AB + Exportgatan 47B + Gothenburg 42246 + SE + +9C-F9-38 (hex) AREVA NP GmbH +9CF938 (base 16) AREVA NP GmbH + Seligenstaedter Str. 100 + Karlstein Germany 63791 + DE + +8C-DB-25 (hex) ESG Solutions +8CDB25 (base 16) ESG Solutions + 20 Hyperion Court + Kingston Ontario K7K 7K2 + CA + +FC-35-98 (hex) Favite Inc. +FC3598 (base 16) Favite Inc. + No.19, Lane 78, Yanhe St., + Jhubei City Hsinchu County 302 + TW + +90-D9-2C (hex) HUG-WITSCHI AG +90D92C (base 16) HUG-WITSCHI AG + Auriedstrasse 10 + Boesingen Fribourg 3178 + CH + +98-8E-34 (hex) ZHEJIANG BOXSAM ELECTRONIC CO.,LTD +988E34 (base 16) ZHEJIANG BOXSAM ELECTRONIC CO.,LTD + No.288,LONGTAN ROAD, + JINHUA CITY ZHEJIANG PROVINCE, 321017 + CN + +C4-71-FE (hex) Cisco Systems, Inc +C471FE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +40-22-ED (hex) Digital Projection Ltd +4022ED (base 16) Digital Projection Ltd + Greenside Way + Manchester Lancs M24 1XX + GB + +98-94-49 (hex) Skyworth Wireless Technology Ltd. +989449 (base 16) Skyworth Wireless Technology Ltd. + Unit A Rm.3A01, Skyworth Bldg., Gaoxin Ave. 1.S., + Nanshan District Shenzhen 518057 + CN + +2C-A1-57 (hex) acromate, Inc. +2CA157 (base 16) acromate, Inc. + #1101, JnK Digital Tower, 111 + Seoul 152-848 + KR + +94-20-53 (hex) Nokia Corporation +942053 (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +28-85-2D (hex) Touch Networks +28852D (base 16) Touch Networks + 2515 152nd Ave NE + Redmond Washington 98052 + US + +B8-BA-68 (hex) Xi'an Jizhong Digital Communication Co.,Ltd +B8BA68 (base 16) Xi'an Jizhong Digital Communication Co.,Ltd + 10 Block NO.1 Enterprise Newly-typed Industrial Zone High-Tech Zone Xi¡¯an,China + Xi'an ShaanXi 710119 + CN + +B0-B3-2B (hex) Slican Sp. z o.o. +B0B32B (base 16) Slican Sp. z o.o. + M. Konopnickiej 18 + Bydgoszcz Kujawsko-Pomorskie 85-124 + PL + +58-42-E4 (hex) Baxter International Inc +5842E4 (base 16) Baxter International Inc + One Baxter Parkway + Deerfield IL 60015 + US + +B8-79-7E (hex) Secure Meters (UK) Limited +B8797E (base 16) Secure Meters (UK) Limited + Secure House + Winchester Hampshire SO23 7RX + GB + +CC-9E-00 (hex) Nintendo Co., Ltd. +CC9E00 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +58-A7-6F (hex) iD corporation +58A76F (base 16) iD corporation + goryokaku bld. 2F + hakodate hokkaido 040-0011 + JP + +00-06-F6 (hex) Cisco Systems, Inc +0006F6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +74-7D-B6 (hex) Aliwei Communications, Inc +747DB6 (base 16) Aliwei Communications, Inc + Keji 6 Road , Hi-tech Industrial Park + Shenzhen Guangdong 518057 + CN + +B0-65-63 (hex) Shanghai Railway Communication Factory +B06563 (base 16) Shanghai Railway Communication Factory + No.179 West Jiangchang road + Shanghai 200436 + CN + +40-18-D7 (hex) Smartronix, Inc. +4018D7 (base 16) Smartronix, Inc. + 44150 Smartronix Way + Hollywood MD 20636 + US + +4C-2C-80 (hex) Beijing Skyway Technologies Co.,Ltd +4C2C80 (base 16) Beijing Skyway Technologies Co.,Ltd + No.5 Jiangtai Road, + Beijing 100015 + CN + +D4-9E-6D (hex) Wuhan Zhongyuan Huadian Science & Technology Co., +D49E6D (base 16) Wuhan Zhongyuan Huadian Science & Technology Co., + NO.6, 6 Road, Sci. & Tech. region of HUST, East Lake Development Zone, + Wuhan Hubei 430223 + CN + +6C-2E-33 (hex) Accelink Technologies Co.,Ltd. +6C2E33 (base 16) Accelink Technologies Co.,Ltd. + 88 Youkeyuan Road, + Wuhan Hubei 430074 + CN + +40-98-7B (hex) Aisino Corporation +40987B (base 16) Aisino Corporation + No.18 A,Xingshikou Road,Haidian District, + Beijing 100195 + CN + +BC-38-D2 (hex) Pandachip Limited +BC38D2 (base 16) Pandachip Limited + Unit 210, 2/F (Lakeside 1), Building 15, No. 8 Science Park West Avenue + Shatin, N.T. + HK + +20-05-E8 (hex) OOO InProMedia +2005E8 (base 16) OOO InProMedia + pr.4806, d.6 + Zelenograd Moscow 124466 + RU + +F0-02-48 (hex) SmarteBuilding +F00248 (base 16) SmarteBuilding + 3267 Bee Cave Road + Austin TX 78746 + US + +AC-6F-4F (hex) Enspert Inc +AC6F4F (base 16) Enspert Inc + 2F., Daehwa B/D, + Seoul 135090 + KR + +E8-28-77 (hex) TMY Co., Ltd. +E82877 (base 16) TMY Co., Ltd. + Attic Bldg. 3F, 1-2-10 Ise-cho, + Ashikaga-shi Tochigi 326-0053 + JP + +F0-C8-8C (hex) LeddarTech Inc. +F0C88C (base 16) LeddarTech Inc. + 2740 Einstein Street + Quebec City G1P 4S4 + CA + +40-37-AD (hex) Macro Image Technology, Inc. +4037AD (base 16) Macro Image Technology, Inc. + East Bldg., 6th Floor, IT Venture Tower, + Seoul 138-950 + KR + +28-ED-58 (hex) JAG Jakob AG +28ED58 (base 16) JAG Jakob AG + Industriestrasse 20 + BRUEGG BE 2555 + CH + +48-6B-91 (hex) Fleetwood Group Inc. +486B91 (base 16) Fleetwood Group Inc. + 11832 James St + Holland Michigan 49424 + US + +64-34-09 (hex) BITwave Pte Ltd +643409 (base 16) BITwave Pte Ltd + 2 Serangoon North Ave 5 + 554911 + SG + +40-C2-45 (hex) Shenzhen Hexicom Technology Co., Ltd. +40C245 (base 16) Shenzhen Hexicom Technology Co., Ltd. + 1510 West Building,Nanshan Software Park, Nanshan Dist. + Shenzhen Guangdong 518053 + CN + +CC-55-AD (hex) RIM +CC55AD (base 16) RIM + Phillip Street + Waterloo Ontario N2L 3W8 + CA + +E8-75-7F (hex) FIRS Technologies(Shenzhen) Co., Ltd +E8757F (base 16) FIRS Technologies(Shenzhen) Co., Ltd + Rm 12A, Area A, Hongsong Business Building, Tairan 9th Rd, Chegongmiao, + Shenzhen Guangdong 518040 + CN + +F0-F7-B3 (hex) Phorm +F0F7B3 (base 16) Phorm + 222 Regent Street + London W1B 5TR + GB + +00-D3-8D (hex) Hotel Technology Next Generation +00D38D (base 16) Hotel Technology Next Generation + 650 E. Algonquin Road + Schaumburg IL 60173 + US + +C8-3E-A7 (hex) KUNBUS GmbH +C83EA7 (base 16) KUNBUS GmbH + Heerweg 15C + Denkendorf BW D-73770 + DE + +60-89-3C (hex) Thermo Fisher Scientific P.O.A. +60893C (base 16) Thermo Fisher Scientific P.O.A. + 46 Jonspin Rd. + Wilmington MA 01887 + US + +D8-6B-F7 (hex) Nintendo Co., Ltd. +D86BF7 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +74-CD-0C (hex) Smith Myers Communications Ltd. +74CD0C (base 16) Smith Myers Communications Ltd. + The Omega Centre + Biggleswade BEDS SG18 8QB + GB + +CC-CE-40 (hex) Janteq Corp +CCCE40 (base 16) Janteq Corp + 9272 Jeronimo Road + Irvine CA 92618 + US + +B8-EE-79 (hex) YWire Technologies, Inc. +B8EE79 (base 16) YWire Technologies, Inc. + 1372 Overdale + Montreal QC H3G 1V3 + CA + +74-D6-75 (hex) WYMA Tecnologia +74D675 (base 16) WYMA Tecnologia + Rua Clímaco Barbosa, 171-179 + São Paulo 01523-000 + BR + +B4-0E-DC (hex) LG-Ericsson Co.,Ltd. +B40EDC (base 16) LG-Ericsson Co.,Ltd. + 533,Hogye-1dong,Dongan-gu + Anyang-shi Kyungki-do 431-749 + KR + +E0-EE-1B (hex) Panasonic Automotive Systems Company of America +E0EE1B (base 16) Panasonic Automotive Systems Company of America + 776 Highway 74 South + Peachtree City Georgia 30269 + US + +74-BE-08 (hex) ATEK Products, LLC +74BE08 (base 16) ATEK Products, LLC + 210 NE 10th Avenue + Brainerd MN 56401 + US + +60-63-FD (hex) Transcend Communication Beijing Co.,Ltd. +6063FD (base 16) Transcend Communication Beijing Co.,Ltd. + A-6,Keshi plaza,28#,Information Road + Beijing 100085 + CN + +D8-B6-C1 (hex) NetworkAccountant, Inc. +D8B6C1 (base 16) NetworkAccountant, Inc. + 12101 Tukwila International Blvd. + Seattle Washington 98168 + US + +74-A4-A7 (hex) QRS Music Technologies, Inc. +74A4A7 (base 16) QRS Music Technologies, Inc. + 269 Quaker Drive + Seneca PA 16346 + US + +70-02-58 (hex) 01DB-METRAVIB +700258 (base 16) 01DB-METRAVIB + 200 CHEMIN DES ORMEAUX + LIMONEST CEDEX RHONE 69578 + FR + +F4-55-E0 (hex) Niceway CNC Technology Co.,Ltd.Hunan Province +F455E0 (base 16) Niceway CNC Technology Co.,Ltd.Hunan Province + 5/F,Innovation-Undertaking Center,HuanBao Industrial Park,199#,ZhenHua Road, + Changsha Hunan 410116 + CN + +20-FD-F1 (hex) 3COM EUROPE LTD +20FDF1 (base 16) 3COM EUROPE LTD + Peoplebuilding 2 + Hemel Hempstead HERTS. HP2 4NW + GB + +84-97-B8 (hex) Memjet Inc. +8497B8 (base 16) Memjet Inc. + 15920 Bernardo Center Drive + San Diego CA 92127 + US + +A0-DD-E5 (hex) SHARP Corporation +A0DDE5 (base 16) SHARP Corporation + 22-22,Nagaike-cho + Osaka city Osaka prefecture 545-8522 + JP + +20-6A-FF (hex) Atlas Elektronik UK Limited +206AFF (base 16) Atlas Elektronik UK Limited + A22 Buliding, Dorset Green Tech. Park + Dorchester Dorset DT2 8ZB + GB + +AC-34-CB (hex) Shanhai GBCOM Communication Technology Co. Ltd +AC34CB (base 16) Shanhai GBCOM Communication Technology Co. Ltd + Room 602, Building 6, No.555 Dongchuan Road + Shanghai 200241 + CN + +90-88-A2 (hex) IONICS TECHNOLOGY ME LTDA +9088A2 (base 16) IONICS TECHNOLOGY ME LTDA + RUA DEP. ANTONIO EDU VIEIRA + FLORIAN POLIS SANTA CATARINA 88040000 + BR + +40-CD-3A (hex) Z3 Technology +40CD3A (base 16) Z3 Technology + 2720 Harrison St + Evanston IL 60201 + US + +48-2C-EA (hex) Motorola Inc Business Light Radios +482CEA (base 16) Motorola Inc Business Light Radios + 8000 W Sunrise Boulevard + Plantation Florida 33324 + US + +00-33-6C (hex) SynapSense Corporation +00336C (base 16) SynapSense Corporation + 2365 Iron Point Road, Suite 100 + Folsom CA 95630 + US + +2C-D1-DA (hex) Sanjole, Inc. +2CD1DA (base 16) Sanjole, Inc. + 2800 Woodlawn Drive, #271 + Honolulu Hawaii 96822 + US + +F8-66-F2 (hex) Cisco Systems, Inc +F866F2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +AC-61-23 (hex) Drivven, Inc. +AC6123 (base 16) Drivven, Inc. + 12001 Network Boulevard + San Antonio TX 78249 + US + +10-0C-24 (hex) pomdevices, LLC +100C24 (base 16) pomdevices, LLC + 178 Colvard Park Dr + Durham NC 27713 + US + +58-F6-BF (hex) Kyoto University +58F6BF (base 16) Kyoto University + Yoshida-Hommachi + Kyoto 6068501 + JP + +78-EC-22 (hex) Shanghai Qihui Telecom Technology Co., LTD +78EC22 (base 16) Shanghai Qihui Telecom Technology Co., LTD + Room 501, No 2 BoYun Rd, PuDong New Area, + Shanghai 201203 + CN + +0C-15-C5 (hex) SDTEC Co., Ltd. +0C15C5 (base 16) SDTEC Co., Ltd. + 167, Churye-2Dong, Sasang-Gu, + Busan 617-716 + KR + +FC-75-E6 (hex) Handreamnet +FC75E6 (base 16) Handreamnet + #1209 MarioTower, 222-12, Guro-Dong, Guro-Gu + Seoul Guro-Gu 152-848 + KR + +A0-A7-63 (hex) Polytron Vertrieb GmbH +A0A763 (base 16) Polytron Vertrieb GmbH + Langwiesenweg 64-71 + Bad Wildbad Baden-Württemberg 75323 + DE + +EC-23-68 (hex) IntelliVoice Co.,Ltd. +EC2368 (base 16) IntelliVoice Co.,Ltd. + 3-6 Kioicho + Chiyoda Tokyo 102-0094 + JP + +74-90-50 (hex) Renesas Electronics Corporation +749050 (base 16) Renesas Electronics Corporation + 1753, Shimonumabe, Nakahara-Ku + Kawasaki Kanagawa 211-8668 + JP + +38-95-92 (hex) Beijing Tendyron Corporation +389592 (base 16) Beijing Tendyron Corporation + 1810,Tower B,Jin-ma,Building,17 East Qing Hua Road + Beijing 100083 + CN + +A4-21-8A (hex) Nortel Networks +A4218A (base 16) Nortel Networks + CARRETERA BASE AEREA # 5850 + Zapopan Jalisco 44130 + MX + +F8-FB-2F (hex) Santur Corporation +F8FB2F (base 16) Santur Corporation + 40931 Encyclopedia Circle + Fremont California 94538 + US + +2C-CD-43 (hex) Summit Technology Group +2CCD43 (base 16) Summit Technology Group + 145 Belmont Drive + Somerset NJ 08873 + US + +64-99-5D (hex) LGE +64995D (base 16) LGE + 60-39 , Kasan -dong , Gumcheon-gu. + Seoul 153-801 + KR + +7C-EF-18 (hex) Creative Product Design Pty. Ltd. +7CEF18 (base 16) Creative Product Design Pty. Ltd. + 82 Victoria Street + Sandringham Victoria 3191 + AU + +FC-7C-E7 (hex) FCI USA LLC +FC7CE7 (base 16) FCI USA LLC + 825 Old Trail Road + Etters PA 17319 + US + +14-54-12 (hex) Entis Co., Ltd. +145412 (base 16) Entis Co., Ltd. + 2-20-6, Hanaoka Bldg, 6F + Tokyo 1030007 + JP + +7C-3E-9D (hex) PATECH +7C3E9D (base 16) PATECH + #23-17. WonhyoRo-2Ga + YongSan-Gu Seoul 140112 + KR + +24-45-97 (hex) GEMUE Gebr. Mueller Apparatebau +244597 (base 16) GEMUE Gebr. Mueller Apparatebau + Fritz-Mueller-Strasse 6-8 + Ingelfingen Criesbach 74653 + DE + +78-81-8F (hex) Server Racks Australia Pty Ltd +78818F (base 16) Server Racks Australia Pty Ltd + 4 - 6 Endurance Ave + Queanbeyan NSW 2620 + AU + +28-48-46 (hex) GridCentric Inc. +284846 (base 16) GridCentric Inc. + 350 Bloor St. E + Toronto Ontario M4W 0A1 + CA + +30-69-4B (hex) RIM +30694B (base 16) RIM + 295 Phillip Street + Waterloo Ontario N2L 3W8 + CA + +6C-62-6D (hex) Micro-Star INT'L CO., LTD +6C626D (base 16) Micro-Star INT'L CO., LTD + No.69, Lide St., Jhonghe City + Taipei Conuty 235 + TW + +28-06-8D (hex) ITL, LLC +28068D (base 16) ITL, LLC + P.O. Box 41875 + Nashville TN 37204 + US + +C0-0D-7E (hex) Additech, Inc. +C00D7E (base 16) Additech, Inc. + 10925 Kinghurst + Houston TX 77099 + US + +84-C7-A9 (hex) C3PO S.A. +84C7A9 (base 16) C3PO S.A. + Alejandro Goicoechea 6 Local 9 + Sant Just Desvern Barcelona ES08960 + ES + +D8-71-57 (hex) Lenovo Mobile Communication Technology Ltd. +D87157 (base 16) Lenovo Mobile Communication Technology Ltd. + No.999,Qishan North 2nd Road,Information&Optoelectronics Park,Torch Hi-tech Industry Development Zone, + Xiamen Fujian 361006 + CN + +60-9A-A4 (hex) GVI SECURITY INC. +609AA4 (base 16) GVI SECURITY INC. + 2801 TRADE CENTER DR STE.120 + CARROLLTON TX 75007 + US + +64-10-84 (hex) HEXIUM Technical Development Co., Ltd. +641084 (base 16) HEXIUM Technical Development Co., Ltd. + Vaci ut 51b + BUDAPEST H-1134 + HU + +34-21-09 (hex) Jensen Scandinavia AS +342109 (base 16) Jensen Scandinavia AS + Balder Allé 3 + Jessheim 2050 + NO + +3C-10-6F (hex) ALBAHITH TECHNOLOGIES +3C106F (base 16) ALBAHITH TECHNOLOGIES + 165, King Abdullah Second Street + Amman 11953 + JO + +0C-DD-EF (hex) Nokia Corporation +0CDDEF (base 16) Nokia Corporation + Elektroniikkatie 10 + Oulu 90570 + FI + +EC-FE-7E (hex) BlueRadios, Inc. +ECFE7E (base 16) BlueRadios, Inc. + 7173 S. Havana Street, Suite 600 + Englewood Colorado 80112 + US + +E4-AD-7D (hex) SCL Elements +E4AD7D (base 16) SCL Elements + 5800 St-Denis, #222 + Montreal Quebec H2S3l5 + CA + +F0-9C-BB (hex) RaonThink Inc. +F09CBB (base 16) RaonThink Inc. + 916, Byucksan Digital Valley 2-Cha, 481-10, Kasan-Dong, Kumcheon-Gu, + Seoul 153-783 + KR + +10-CC-DB (hex) AXIMUM PRODUITS ELECTRONIQUES +10CCDB (base 16) AXIMUM PRODUITS ELECTRONIQUES + ZI DELTA INDUSTRIE + MARSEILLE CEDEX 11 13368 + FR + +38-C7-BA (hex) CS Services Co.,Ltd. +38C7BA (base 16) CS Services Co.,Ltd. + Imon BLDG 95 Edomachi + Kobe Hyogo 6500033 + JP + +EC-5C-69 (hex) MITSUBISHI HEAVY INDUSTRIES MECHATRONICS SYSTEMS,LTD. +EC5C69 (base 16) MITSUBISHI HEAVY INDUSTRIES MECHATRONICS SYSTEMS,LTD. + 1-16,5-CHOME,KOMATSU-DORI, + KOBE HYOGO 652-0865 + JP + +6C-92-BF (hex) Inspur Electronic Information Industry Co.,Ltd. +6C92BF (base 16) Inspur Electronic Information Industry Co.,Ltd. + No 224 Shanda Road + Jinan Shandong 250013 + CN + +44-A8-C2 (hex) SEWOO TECH CO., LTD +44A8C2 (base 16) SEWOO TECH CO., LTD + 689-20 GEUMJUNG-DONG + GUNPO-SI KYUNGGI-DO 435-862 + KR + +AC-9A-96 (hex) Lantiq Deutschland GmbH +AC9A96 (base 16) Lantiq Deutschland GmbH + Am Campeon 3 + Neubiberg Bavaria 85579 + DE + +80-EE-73 (hex) Shuttle Inc. +80EE73 (base 16) Shuttle Inc. + No. 30 Lane 76, Rei Kuang Rd + Taipei 114 + TW + +FC-E2-3F (hex) CLAY PAKY SPA +FCE23F (base 16) CLAY PAKY SPA + Via Pastrengo 3/b + Seriate Bergamo 24068 + IT + +58-57-0D (hex) Danfoss Solar Inverters +58570D (base 16) Danfoss Solar Inverters + Jyllandsgade 28 + Sønderborg DK-6400 + DK + +C4-82-3F (hex) Fujian Newland Auto-ID Tech. Co,.Ltd. +C4823F (base 16) Fujian Newland Auto-ID Tech. Co,.Ltd. + Newland Science & Technology Park, No.1 Rujiang West Rd., Mawei + Fuzhou Fujian 350015 + CN + +E8-5B-5B (hex) LG ELECTRONICS INC +E85B5B (base 16) LG ELECTRONICS INC + 19-1, CHEONGHO-RI, JINWI-MYEON + PYEONGTAEK GYEONGGI-DO 451-713 + KR + +BC-A9-D6 (hex) Cyber-Rain, Inc. +BCA9D6 (base 16) Cyber-Rain, Inc. + 5272 Evanwood Avenue + Oak Park California 91377-4809 + US + +6C-3E-9C (hex) KE Knestel Elektronik GmbH +6C3E9C (base 16) KE Knestel Elektronik GmbH + Osterwalder Str. 12 + Hopferbach Bavaria 87496 + DE + +8C-D6-28 (hex) Ikor Metering +8CD628 (base 16) Ikor Metering + Francisco Grandmontagne 4 + San Sebastian Guipuzcoa 20008 + ES + +24-3C-20 (hex) Dynamode Group +243C20 (base 16) Dynamode Group + Head Office, 132a St Albans Road + Watford Herts WD24 4AE + GB + +3C-39-C3 (hex) JW Electronics Co., Ltd. +3C39C3 (base 16) JW Electronics Co., Ltd. + 3A17, No. 5 Hsin-yi Rd., Sec. 5 + Taipei 110 + TW + +3C-05-AB (hex) Product Creation Studio +3C05AB (base 16) Product Creation Studio + 425 Westlake Ave N + Seattle WA 98109 + US + +F0-43-35 (hex) DVN(Shanghai)Ltd. +F04335 (base 16) DVN(Shanghai)Ltd. + 11F,Hechuan Building,2016 Yishan Rd, + Shanghai 201103 + CN + +A4-79-E4 (hex) KLINFO Corp +A479E4 (base 16) KLINFO Corp + 301 923 wolpyung-dong + Daejeon 302-852 + KR + +48-1B-D2 (hex) Intron Scientific co., ltd. +481BD2 (base 16) Intron Scientific co., ltd. + 6F., NO. 136,Sec 2,Keelung Rd., Da-an district + Taipei 106 + TW + +D0-F0-DB (hex) Ericsson +D0F0DB (base 16) Ericsson + 250 Holger Way + SAN JOSE CA 95134 + US + +7C-14-76 (hex) Damall Technologies SAS +7C1476 (base 16) Damall Technologies SAS + Corso della Repubblica 65 + Fabriano Ancona 60044 + IT + +8C-54-1D (hex) LGE +8C541D (base 16) LGE + 60-39 , Kasan -dong , Gumcheon-gu. + Seoul 153-801 + KR + +00-A2-DA (hex) INAT GmbH +00A2DA (base 16) INAT GmbH + Ostendstraße 50A + Nuremberg Bavaria 90482 + DE + +00-3C-C5 (hex) WONWOO Engineering Co., Ltd +003CC5 (base 16) WONWOO Engineering Co., Ltd + 7F 201, Techno-Park SsangYong III, + Bucheon City Gyeonggi-Do 421-808 + KR + +F0-77-D0 (hex) Xcellen +F077D0 (base 16) Xcellen + 15F KINS Tower 25-1,Jeongja-dong,Bungdang-gu, + Seongnam Gyeonggi 463811 + KR + +4C-C6-02 (hex) Radios, Inc. +4CC602 (base 16) Radios, Inc. + 31355 State Road 46 + Sorrenot Floriad 32776 + US + +80-71-1F (hex) Juniper Networks +80711F (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +88-FD-15 (hex) LINEEYE CO., LTD +88FD15 (base 16) LINEEYE CO., LTD + 5F Marufuku Bldg. 39-1 Karahashi + Kyoto 601-8468 + JP + +88-4B-39 (hex) Siemens AG, Healthcare Sector +884B39 (base 16) Siemens AG, Healthcare Sector + Henkestrasse 127 + Erlangen Bavaria 91052 + DE + +D8-28-C9 (hex) General Electric Consumer and Industrial +D828C9 (base 16) General Electric Consumer and Industrial + AP35-1405 + Louisville KY 40225 + US + +44-C2-33 (hex) Guangzhou Comet Technology Development Co.Ltd +44C233 (base 16) Guangzhou Comet Technology Development Co.Ltd + Rm 304,FL 3,Block G,Science and Technology Innovation Base, + Guangzhou Guangdong 510663 + CN + +30-EF-D1 (hex) Alstom Strongwish (Shenzhen) Co., Ltd. +30EFD1 (base 16) Alstom Strongwish (Shenzhen) Co., Ltd. + 5F,Building No.6, Keji Middle 2 Road High-Tech Industrial Park, + Shen Zhen Guangdong 518057 + CN + +7C-2C-F3 (hex) Secure Electrans Ltd +7C2CF3 (base 16) Secure Electrans Ltd + Pioneer House, Pioneer Business Park + Ellesmere Port CH65 1AD + GB + +08-16-51 (hex) SHENZHEN SEA STAR TECHNOLOGY CO.,LTD +081651 (base 16) SHENZHEN SEA STAR TECHNOLOGY CO.,LTD + Seastar industrial Park, BaoLong 6th Ave + ShenZhen GuangDong 518116 + CN + +A8-63-DF (hex) DISPLAIRE CORPORATION +A863DF (base 16) DISPLAIRE CORPORATION + 1300 Valley House Dr, Ste 100 + Rohnert Park CA 94928 + US + +18-3B-D2 (hex) BYD Precision Manufacture Company Ltd. +183BD2 (base 16) BYD Precision Manufacture Company Ltd. + No3000 LongDong Avenue, Pudong District + Shanghai 201203 + CN + +E4-35-93 (hex) Hangzhou GoTo technology Co.Ltd +E43593 (base 16) Hangzhou GoTo technology Co.Ltd + Room 1303,Boee buliding,3760 Nanhuan Road, Binjiang, + Hangzhou Zhejiang 310053 + CN + +2C-3A-28 (hex) Fagor Electrónica +2C3A28 (base 16) Fagor Electrónica + B. San Andres, s/n + Mondragón Guipuzcoa 20500 + ES + +B4-58-61 (hex) CRemote, LLC +B45861 (base 16) CRemote, LLC + 1195 Noel Drive + MENLO PARK CA 94025 + US + +B0-97-3A (hex) E-Fuel Corporation +B0973A (base 16) E-Fuel Corporation + 15466 Los Gatos Blvd. #37 + Los Gatos CA 95032 + US + +20-4E-6B (hex) Axxana(israel) ltd +204E6B (base 16) Axxana(israel) ltd + Habarzel 38 + Tel aviv 69710 + IL + +80-F5-93 (hex) IRCO Sistemas de Telecomunicación S.A. +80F593 (base 16) IRCO Sistemas de Telecomunicación S.A. + Via Sergia 98 + Mataró Barcelona 08302 + ES + +E4-97-F0 (hex) Shanghai VLC Technologies Ltd. Co. +E497F0 (base 16) Shanghai VLC Technologies Ltd. Co. + Room 901, B-Zone, East Beijing Road + Shanghai 200001 + CN + +B4-08-32 (hex) TC Communications +B40832 (base 16) TC Communications + 17575 Cartwright Road + Irvine CA 92614 + US + +EC-DE-3D (hex) Lamprey Networks, Inc. +ECDE3D (base 16) Lamprey Networks, Inc. + 58 Dover Road + Durham NH 03824 + US + +6C-FF-BE (hex) MPB Communications Inc. +6CFFBE (base 16) MPB Communications Inc. + 147 Hymus Blvd + Pointe-Claire Quebec H9R 1E9 + CA + +30-41-74 (hex) ALTEC LANSING LLC +304174 (base 16) ALTEC LANSING LLC + 535 ROUTES 6 & 209 + MILFORD PA 18337 + US + +80-B2-89 (hex) Forworld Electronics Ltd. +80B289 (base 16) Forworld Electronics Ltd. + No.16 Keyuan 2nd Rd., Situn District + Taichung City 886 + TW + +E8-3A-97 (hex) Toshiba Corporation +E83A97 (base 16) Toshiba Corporation + 1-1-1, Shibaura, Minato-ku + Tokyo 00000 + JP + +10-56-CA (hex) Peplink International Ltd. +1056CA (base 16) Peplink International Ltd. + 17/F, Park Building, + Cheung Sha Wan + HK + +48-6F-D2 (hex) StorSimple Inc +486FD2 (base 16) StorSimple Inc + 2350 Mission College Blvd + Santa Clara CA 95054 + US + +A0-3A-75 (hex) PSS Belgium N.V. +A03A75 (base 16) PSS Belgium N.V. + Hoogveld 50 + Dendermonde 9200 + BE + +24-DB-AD (hex) ShopperTrak RCT Corporation +24DBAD (base 16) ShopperTrak RCT Corporation + 200 W. Monroe Street + Chicago IL 60606 + US + +9C-EB-E8 (hex) BizLink (Kunshan) Co.,Ltd +9CEBE8 (base 16) BizLink (Kunshan) Co.,Ltd + No.168,Nanhe Road,Economic & Technological Development Zone, + Kunshan City Jiangsu Province 215300 + CN + +04-0E-C2 (hex) ViewSonic Mobile China Limited +040EC2 (base 16) ViewSonic Mobile China Limited + Room 601, The Gate Tower B, No.19, Zhongguancun Street, Haidian District + Beijing 100080 + CN + +C8-D1-D1 (hex) AGAiT Technology Corporation +C8D1D1 (base 16) AGAiT Technology Corporation + 5F,No.27-8, Sec. 2, Zhongzheng E. Rd., Danshui Township + Taipei County 25170 + TW + +00-DB-45 (hex) THAMWAY CO.,LTD. +00DB45 (base 16) THAMWAY CO.,LTD. + 3-9-2 + Fuji Shizuoka 417-0001 + JP + +D4-9C-28 (hex) JayBird LLC +D49C28 (base 16) JayBird LLC + 3676 California Ave + Salt Lake City UT 84104 + US + +74-F7-26 (hex) Neuron Robotics +74F726 (base 16) Neuron Robotics + 91 Pearson Ave + Somerville MA 02144 + US + +28-72-C5 (hex) Smartmatic Corp +2872C5 (base 16) Smartmatic Corp + 1001 Broken Sound Pkwy NW Suite D + Boca Raton Florida 33487 + US + +E0-8F-EC (hex) REPOTEC CO., LTD. +E08FEC (base 16) REPOTEC CO., LTD. + 3F, 258. + CHUNG HO CITY, TAIPEI COUNTY 235 + TW + +AC-E9-AA (hex) Hay Systems Ltd +ACE9AA (base 16) Hay Systems Ltd + Watermark + Livingston West Lothian EH54 7EG + GB + +08-2A-D0 (hex) SRD Innovations Inc. +082AD0 (base 16) SRD Innovations Inc. + 11525 Valley Ridge Dr. NW + Calgary AB T3B 5T4 + CA + +88-98-21 (hex) TERAON +889821 (base 16) TERAON + 2F Seohan Bldg., 1552-10, Seocho-Dong, Seocho-Gu, + Seoul 137-070 + KR + +E0-E7-51 (hex) Nintendo Co., Ltd. +E0E751 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-3A-AF (hex) BlueBit Ltd. +003AAF (base 16) BlueBit Ltd. + Unit B, 21/F., 78 Hung To Road, + Kowloon, + HK + +64-16-8D (hex) Cisco Systems, Inc +64168D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-3A-9C (hex) Cisco Systems, Inc +003A9C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +7C-6C-8F (hex) AMS NEVE LTD +7C6C8F (base 16) AMS NEVE LTD + BILLINGTON ROAD + BURNLEY LANCASHIRE BB11 5UB + GB + +9C-B2-06 (hex) PROCENTEC +9CB206 (base 16) PROCENTEC + Klopperman 16 + Wateringen Zuid Holland 2292JD + NL + +88-ED-1C (hex) Cudo Communication Co., Ltd. +88ED1C (base 16) Cudo Communication Co., Ltd. + 10F ArirangTV 1467-80, Seocho-3dong, Seocho-gu + Seoul 137-868 + KR + +9C-CD-82 (hex) CHENG UEI PRECISION INDUSTRY CO.,LTD +9CCD82 (base 16) CHENG UEI PRECISION INDUSTRY CO.,LTD + No.18, Chung Shan Rd., Tu-Cheng Industry Park + Tu Cheng City Taipei Hsien 23680 + TW + +F0-62-81 (hex) ProCurve Networking by HP +F06281 (base 16) ProCurve Networking by HP + 60 Alexandra Terrace + 118502 + SG + +C0-9C-92 (hex) COBY +C09C92 (base 16) COBY + COBY Electronics ShenZhen R&D Center + SHENZHEN GUANGDONG 518109 + CN + +C0-38-F9 (hex) Nokia Danmark A/S +C038F9 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +F4-63-49 (hex) Diffon Corporation +F46349 (base 16) Diffon Corporation + Digital Tower Aston 1505 + Seoul 153803 + KR + +74-F0-7D (hex) BnCOM Co.,Ltd +74F07D (base 16) BnCOM Co.,Ltd + Room1007, Daehyun Techno World, 174 + Uiwang-si Gyeonggi-do 437-753 + KR + +F8-52-DF (hex) VNL Europe AB +F852DF (base 16) VNL Europe AB + Finlandsgatan 10 + Kista 164 74 + SE + +A8-CB-95 (hex) EAST BEST CO., LTD. +A8CB95 (base 16) EAST BEST CO., LTD. + 4F,NO.98,SHING TEH ROAD + SAN CHUNG CITY TAIPEI 241 + TW + +F4-5F-F7 (hex) DQ Technology Inc. +F45FF7 (base 16) DQ Technology Inc. + 5111 Johnson Drive + Pleasanton CA 94588 + US + +7C-3B-D5 (hex) Imago Group +7C3BD5 (base 16) Imago Group + Ramon Marti Alsina 2-4-6 + Badalona Barcelona 08911 + ES + +5C-E2-23 (hex) Delphin Technology AG +5CE223 (base 16) Delphin Technology AG + Lustheide 81 + Bergisch-Gladbach 51427 + DE + +F8-71-FE (hex) The Goldman Sachs Group, Inc. +F871FE (base 16) The Goldman Sachs Group, Inc. + Christchurch Court | 10-15 Newgate Street + London London EC1A 7HD + GB + +2C-19-84 (hex) IDN Telecom, Inc. +2C1984 (base 16) IDN Telecom, Inc. + 2669 Great Arbor Way + Union City CA 94587 + US + +D8-C3-FB (hex) DETRACOM +D8C3FB (base 16) DETRACOM + 41 AVENUE DE L'EUROPE + CASTELNAU D'ESTRETEFONDS 31620 + FR + +58-F6-7B (hex) Xia Men UnionCore Technology LTD. +58F67B (base 16) Xia Men UnionCore Technology LTD. + (224)2F Chuangye Building,Xiamen Pioneering Park for Overseas Chinese Scholars + Xia Men Fu Jian 361009 + CN + +6C-F0-49 (hex) GIGA-BYTE TECHNOLOGY CO.,LTD. +6CF049 (base 16) GIGA-BYTE TECHNOLOGY CO.,LTD. + + Pin-Jen Taoyuan 324 + TW + +64-4F-74 (hex) LENUS Co., Ltd. +644F74 (base 16) LENUS Co., Ltd. + 18-5 Gwacheon-Dong + Gwacheon Gyeonggi-Do 427-060 + KR + +78-7F-62 (hex) GiK mbH +787F62 (base 16) GiK mbH + Goethestraße 5 + Aachen 52064 + DE + +40-15-97 (hex) Protect America, Inc. +401597 (base 16) Protect America, Inc. + 5100 N IH-35 + Round Rock TX 78681 + US + +C4-FC-E4 (hex) DishTV NZ Ltd +C4FCE4 (base 16) DishTV NZ Ltd + 10 Penney Ave + Auckland 1041 + NZ + +E8-0B-13 (hex) Akib Systems Taiwan, INC +E80B13 (base 16) Akib Systems Taiwan, INC + No.582-1, RuiGuang Rd + Taipei 114 + TW + +EC-6C-9F (hex) Chengdu Volans Technology CO.,LTD +EC6C9F (base 16) Chengdu Volans Technology CO.,LTD + 2nd Floor Building 4B Hi-Tech Incubation Park,Nanyan Xian,Tianfu Ave + Chengdu Sichuan 610041 + CN + +40-EF-4C (hex) Fihonest communication co.,Ltd +40EF4C (base 16) Fihonest communication co.,Ltd + Room902,Park road,Zhixing business-building + Dongguan Guangdong 523560 + CN + +00-27-1E (hex) Xagyl Communications +00271E (base 16) Xagyl Communications + 1667 Marronier Crt + Cumberland Ontario K4C 1C2 + CA + +00-27-1D (hex) Comba Telecom Systems (China) Ltd. +00271D (base 16) Comba Telecom Systems (China) Ltd. + 10 Shenzhou Road + Guangzhou Guangdong 510663 + CN + +00-27-20 (hex) NEW-SOL COM +002720 (base 16) NEW-SOL COM + Bucheon Tecnopark 403-602 + Bucheon city Kyoungki-do 420-734 + KR + +00-26-F0 (hex) cTrixs International GmbH. +0026F0 (base 16) cTrixs International GmbH. + Lieferinger Hauptstr. 140 + Salzburg Salzburg 5020 + AT + +00-26-EA (hex) Cheerchip Electronic Technology (ShangHai) Co., Ltd. +0026EA (base 16) Cheerchip Electronic Technology (ShangHai) Co., Ltd. + ROOM 1202, NO. 51, 7 Area, NO. 1467 CAOBAO ROAD; + SHANGHAI 201101 + CN + +00-27-08 (hex) Nordiag ASA +002708 (base 16) Nordiag ASA + Frysjaveien 40 + Oslo 0884 + NO + +00-27-02 (hex) SolarEdge Technologies +002702 (base 16) SolarEdge Technologies + 1 Abba Eban St. + Herzelia 46725 + IL + +00-27-04 (hex) Accelerated Concepts, Inc +002704 (base 16) Accelerated Concepts, Inc + 1208 E Kennedy Blvd + Tampa FL 33602 + US + +00-26-FA (hex) BandRich Inc. +0026FA (base 16) BandRich Inc. + 7F., No.188, Baociao Road + Sindian City Taipei 23145 + TW + +00-26-F9 (hex) S.E.M. srl +0026F9 (base 16) S.E.M. srl + via Lecco, 61 + Vimercate Monza Brianza 20059 + IT + +00-26-FD (hex) Interactive Intelligence +0026FD (base 16) Interactive Intelligence + 7601 Interactive Way + IN 46278 + US + +00-26-F7 (hex) Nivetti Systems Pvt. Ltd. +0026F7 (base 16) Nivetti Systems Pvt. Ltd. + #727,8th Main, JP Nagar 3rd Phase + Bangalore 560078 + IN + +00-26-F6 (hex) Military Communication Institute +0026F6 (base 16) Military Communication Institute + ul. Warszawska 22A + Zegrze 05-130 + PL + +00-26-DD (hex) Fival Science & Technology Co.,Ltd. +0026DD (base 16) Fival Science & Technology Co.,Ltd. + 1/F, Building 57, No.461 + Shanghai Shanghai 200233 + CN + +00-26-DE (hex) FDI MATELEC +0026DE (base 16) FDI MATELEC + Route de saint symphorien + Les landes Génusson 85130 + FR + +00-26-DA (hex) Universal Media Corporation /Slovakia/ s.r.o. +0026DA (base 16) Universal Media Corporation /Slovakia/ s.r.o. + Mickiewiczova 7104/14 + Bratislava 811 07 + SK + +00-26-DB (hex) Ionics EMS Inc. +0026DB (base 16) Ionics EMS Inc. + Carmelray Industrial Park 2, Brgy. Tulo + Calamba Laguna 4027 + PH + +00-26-D5 (hex) Ory Solucoes em Comercio de Informatica Ltda. +0026D5 (base 16) Ory Solucoes em Comercio de Informatica Ltda. + Av. Unisinos, 615 + Sao Leopoldo RS 93022000 + BR + +00-26-CE (hex) Kozumi USA Corp. +0026CE (base 16) Kozumi USA Corp. + 3005 Hartridge Terrace + Wellington FL 33414 + US + +00-27-11 (hex) LanPro Inc +002711 (base 16) LanPro Inc + 1880 NW 93Av + Miami Florida 33172 + US + +00-26-86 (hex) Quantenna Communcations, Inc. +002686 (base 16) Quantenna Communcations, Inc. + 3450 W. Warren Ave. + Fremont CA 94538 + US + +00-26-84 (hex) KISAN SYSTEM +002684 (base 16) KISAN SYSTEM + GWANGMYEONG TECHNOPARK B-403 + GWANGMYEONG GYEONGGI 423-050 + KR + +00-26-80 (hex) SIL3 Pty.Ltd +002680 (base 16) SIL3 Pty.Ltd + Factory 10 + DANDENONG VICTORIA 3175 + AU + +00-26-BF (hex) ShenZhen Temobi Science&Tech Development Co.,Ltd +0026BF (base 16) ShenZhen Temobi Science&Tech Development Co.,Ltd + 4FloorG, Jinrun Tower, 6019 Shennan Road + ShenZhen 518000 + CN + +00-26-B4 (hex) Ford Motor Company +0026B4 (base 16) Ford Motor Company + 20300 Rotunda Drive + Dearborn MI 48124 + US + +00-26-CA (hex) Cisco Systems, Inc +0026CA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-26-C9 (hex) Proventix Systems, Inc. +0026C9 (base 16) Proventix Systems, Inc. + 4518 Valleydale Road + Birmingham AL 35242 + US + +00-26-90 (hex) I DO IT +002690 (base 16) I DO IT + 1308, WoolimLions2nd Doksan Station + Seoul 153-787 + KR + +00-26-8F (hex) MTA SpA +00268F (base 16) MTA SpA + Viale dell Industria 12 + Codogno LODI 26845 + IT + +00-26-79 (hex) Euphonic Technologies, Inc. +002679 (base 16) Euphonic Technologies, Inc. + 2-5-10 Shin-yokohama, Kouhoku-ku + Yokohama 222-0033 + JP + +00-26-AC (hex) Shanghai LUSTER Teraband photonic Co., Ltd. +0026AC (base 16) Shanghai LUSTER Teraband photonic Co., Ltd. + F4, No.39 ChengZhong Rd. + Shanghai 201800 + CN + +00-26-A6 (hex) TRIXELL +0026A6 (base 16) TRIXELL + 460, Rue du pommarin + MOIRANS 38210 + FR + +00-26-9C (hex) ITUS JAPAN CO. LTD +00269C (base 16) ITUS JAPAN CO. LTD + 7F Shinkawa B/D + Chuoku Tokyo 1040033 + JP + +00-26-94 (hex) Senscient Ltd +002694 (base 16) Senscient Ltd + Unit 2, Block A, Arena Business Centre + Poole Dorset BH17 7FJ + GB + +00-26-76 (hex) COMMidt AS +002676 (base 16) COMMidt AS + Kikregata 57-59 + Levanger Nord-Troendelag 7600 + NO + +00-26-1D (hex) COP SECURITY SYSTEM CORP. +00261D (base 16) COP SECURITY SYSTEM CORP. + 4~7F, No.5, Lane 130, Min-Chung Rd., + Taipei 23141 + TW + +00-26-17 (hex) OEM Worldwide +002617 (base 16) OEM Worldwide + 2920 Kelly Ave + Watertown SD 57201 + US + +00-26-13 (hex) Engel Axil S.L. +002613 (base 16) Engel Axil S.L. + Puig dels Tudons, 6 + Barbera del Valles Barcelona 08210 + ES + +00-26-38 (hex) Xia Men Joyatech Co., Ltd. +002638 (base 16) Xia Men Joyatech Co., Ltd. + Room 304, 28th Building, Guanri Road, Xiamen Software Park + Xiamen Fujian Province 361008 + CN + +00-26-3A (hex) Digitec Systems +00263A (base 16) Digitec Systems + 7,1st Street, Kasturibai Nagar + Chennai Tamil Nadu 600054 + IN + +00-26-0F (hex) Linn Products Ltd +00260F (base 16) Linn Products Ltd + Glasgow Road + Glasgow Scotland G76 0EQ + GB + +00-26-0C (hex) Dataram +00260C (base 16) Dataram + 186 Princeton Rd. + West Windsor NJ 08550 + US + +00-26-2B (hex) Wongs Electronics Co. Ltd. +00262B (base 16) Wongs Electronics Co. Ltd. + Wanfeng Ind. Esata, Shajing, Baoan, + Shenzhen Guang Dong 518104 + CN + +00-26-20 (hex) ISGUS GmbH +002620 (base 16) ISGUS GmbH + Oberdorfstraße 18 - 22 + VS - Schwenningen BW 78054 + DE + +00-26-01 (hex) Cutera Inc +002601 (base 16) Cutera Inc + 3240 Bayshore Blvd + Brisbane CA 94405 + US + +00-26-35 (hex) Bluetechnix GmbH +002635 (base 16) Bluetechnix GmbH + Waidhausenstr. 3/19 + Vienna 1140 + AT + +00-26-57 (hex) OOO NPP EKRA +002657 (base 16) OOO NPP EKRA + I.Yakovleva St., 3 + Cheboksary Chuvash Republic 428003 + RU + +00-26-52 (hex) Cisco Systems, Inc +002652 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-26-66 (hex) EFM Networks +002666 (base 16) EFM Networks + 6F, Benposra II 1197-1 Bojeong Giheung Gu + Yong In Kyunggi do 446913 + KR + +00-25-F5 (hex) DVS Korea, Co., Ltd +0025F5 (base 16) DVS Korea, Co., Ltd + 497-3, SangHa-Dong, Giheung-gu + Yong-In city Gyeonggi-do 446-914 + KR + +00-25-EB (hex) Reutech Radar Systems (PTY) Ltd +0025EB (base 16) Reutech Radar Systems (PTY) Ltd + 35 Elektron Avenue + Stellenbosch Western Cape 7600 + ZA + +00-25-EE (hex) Avtex Ltd +0025EE (base 16) Avtex Ltd + Unit G5 Capital Business Park + Cardiff CF3 2PX + GB + +00-25-AE (hex) Microsoft Corporation +0025AE (base 16) Microsoft Corporation + One Microsoft Way + Redmond Washington 98052-6399 + US + +00-25-AF (hex) COMFILE Technology +0025AF (base 16) COMFILE Technology + Guro 5 dong, Guro-gu + Seoul 152-842 + KR + +00-25-A8 (hex) Kontron (BeiJing) Technology Co.,Ltd +0025A8 (base 16) Kontron (BeiJing) Technology Co.,Ltd + 17 Building, Block #1,ABP. 188 Western South 4th Ring Road + BeiJing 100070 + CN + +00-25-D9 (hex) DataFab Systems Inc. +0025D9 (base 16) DataFab Systems Inc. + 385-3 Hongzun Road + Pingzhen City Taoyuan County 32466 + TW + +00-25-D6 (hex) The Kroger Co. +0025D6 (base 16) The Kroger Co. + 11450 Grooms Road + Blue Ash OH 45242 + US + +00-25-D1 (hex) Eastern Asia Technology Limited +0025D1 (base 16) Eastern Asia Technology Limited + 8F-1, No. 188, Baoqiao Rd., Xindian Dist. + New Taipei City 23145 + TW + +00-25-CD (hex) Skylane Optics +0025CD (base 16) Skylane Optics + Rue d'Arlon, 6 + Windhof 8399 + LU + +00-25-BF (hex) Wireless Cables Inc. +0025BF (base 16) Wireless Cables Inc. + 1414 Soquel Ave, Ste 212 + Santa Cruz CA 95062 + US + +00-25-B9 (hex) Cypress Solutions Inc +0025B9 (base 16) Cypress Solutions Inc + 3066 Beta Ave + BC V5G 4K4 + CA + +00-25-B6 (hex) Telecom FM +0025B6 (base 16) Telecom FM + 895 Plymouth Road + Slough Berkshire SL1 4LP + GB + +00-25-A5 (hex) Walnut Media Network +0025A5 (base 16) Walnut Media Network + 440 N Wolfe Rd + Sunnyvale CA 94085 + US + +00-25-A4 (hex) EuroDesign embedded technologies GmbH +0025A4 (base 16) EuroDesign embedded technologies GmbH + Waldstratraße 4A + Kirchdorf a.d. Amper Bayern 85414 + DE + +00-25-C1 (hex) Nawoo Korea Corp. +0025C1 (base 16) Nawoo Korea Corp. + 4Fl., Hanwon Bldg., 6-1, Sunae-dong, Bundang-gu, + Seongnam-si Gyeonggi-do 463-825 + KR + +00-25-F6 (hex) netTALK.com, Inc. +0025F6 (base 16) netTALK.com, Inc. + 1100 NW 163RD DRIVE + NORTH MIAMI BEACH FL 33169 + US + +00-25-7A (hex) CAMCO Produktions- und Vertriebs-GmbH für Beschallungs- und Beleuchtungsanlagen +00257A (base 16) CAMCO Produktions- und Vertriebs-GmbH für Beschallungs- und Beleuchtungsanlagen + Fischpicke 5 + Wenden NRW 57482 + DE + +00-25-76 (hex) NELI TECHNOLOGIES +002576 (base 16) NELI TECHNOLOGIES + Route Nationale + LE RHEU 35650 + FR + +00-25-74 (hex) KUNIMI MEDIA DEVICE Co., Ltd. +002574 (base 16) KUNIMI MEDIA DEVICE Co., Ltd. + 3 KITAMACHIDA YAMAZAKI + KUNIMI, DATE FUKUSHIMA 969-1771 + JP + +00-25-59 (hex) Syphan Technologies Ltd +002559 (base 16) Syphan Technologies Ltd + The Watermill + Skipton North Yorkshire BD23 3AG + GB + +00-25-54 (hex) Pixel8 Networks +002554 (base 16) Pixel8 Networks + 22 Great Oaks Blvd, Suite 150 + San Jose CA 95119 + US + +00-25-40 (hex) Quasar Technologies, Inc. +002540 (base 16) Quasar Technologies, Inc. + 1701 Barrett Lakes Boulevard + Kennesaw GA 30144 + US + +00-25-33 (hex) WITTENSTEIN AG +002533 (base 16) WITTENSTEIN AG + Walter-Wittenstein-Straße 1 + Igersheim 97999 + DE + +00-25-30 (hex) Aetas Systems Inc. +002530 (base 16) Aetas Systems Inc. + 3A3, No. 1, LiHsin Road I + HsinChu Taiwan 30078 + TW + +00-25-2C (hex) Entourage Systems, Inc. +00252C (base 16) Entourage Systems, Inc. + 7901 Jones Branch Drive + McLean Virginia 22102 + US + +00-25-8C (hex) ESUS ELEKTRONIK SAN. VE DIS. TIC. LTD. STI. +00258C (base 16) ESUS ELEKTRONIK SAN. VE DIS. TIC. LTD. STI. + ESENSEHIR MAHALLESI KURKCULER CADDESI + ISTANBUL 34776 + TR + +00-25-5A (hex) Tantalus Systems Corp. +00255A (base 16) Tantalus Systems Corp. + 301-3480 Gilmore Way + Burnaby BC V5G 4Y1 + CA + +00-25-87 (hex) Vitality, Inc. +002587 (base 16) Vitality, Inc. + One Broadway + Cambridge MA 02142 + US + +00-25-73 (hex) ST Electronics (Info-Security) Pte Ltd +002573 (base 16) ST Electronics (Info-Security) Pte Ltd + 100, Jurong East Street 21, ST Electronics Jurong East Bldg + 609602 + SG + +00-25-6F (hex) Dantherm Power +00256F (base 16) Dantherm Power + Marienlystvej 65 + Skive 7800 + DK + +00-25-2F (hex) Energy, Inc. +00252F (base 16) Energy, Inc. + 3297 Pacific Street + Charleston SC 29418 + US + +00-25-0A (hex) Security Expert Co. Ltd +00250A (base 16) Security Expert Co. Ltd + 8F-3, No.2, Jian 8th Rd., + Jhonghe Taipei 235 + TW + +00-25-05 (hex) eks Engel GmbH & Co. KG +002505 (base 16) eks Engel GmbH & Co. KG + Schuetzenstrasse 2 + Wenden-Hillmicke NRW 57482 + DE + +00-25-09 (hex) SHARETRONIC Group LTD +002509 (base 16) SHARETRONIC Group LTD + ShaJing,Bao'an Zone, + ShenZhen Guangdong 518104 + CN + +00-24-DA (hex) Innovar Systems Limited +0024DA (base 16) Innovar Systems Limited + 12155 Commissioner Drive + North Jackson Ohio 44451 + US + +00-24-D8 (hex) IlSung Precision +0024D8 (base 16) IlSung Precision + 182-2, Jegi-ri, Jeongnam-myeon + Hwanseong-si Gyeonggi-do 445-964 + KR + +00-24-CD (hex) Willow Garage, Inc. +0024CD (base 16) Willow Garage, Inc. + 68 Willow Rd. + Menlo Park CA 94025 + US + +00-24-D3 (hex) QUALICA Inc. +0024D3 (base 16) QUALICA Inc. + 5-29-15,Toyo, + Tokyo 135-0016 + JP + +00-24-CE (hex) Exeltech Inc +0024CE (base 16) Exeltech Inc + 7317 Jack Newell Blvd North + Fort Worth TX 76118 + US + +00-24-CF (hex) Inscape Data Corporation +0024CF (base 16) Inscape Data Corporation + 1611 South Main Street + Milpitas CA 95035 + US + +00-24-C6 (hex) Hager Electro SAS +0024C6 (base 16) Hager Electro SAS + 132, boulevard d'Europe + Obernai Bas-Rhin 67215 + FR + +00-24-FD (hex) Accedian Networks Inc +0024FD (base 16) Accedian Networks Inc + 2351 Alfred Nobel Blvd + Saint Laurent QC h4s 2A9 + CA + +00-25-23 (hex) OCP Inc. +002523 (base 16) OCP Inc. + 18495 S Dixie Hwy PMB 107 + Miami Florida 33157 + US + +00-25-1D (hex) DSA Encore, LLC +00251D (base 16) DSA Encore, LLC + 50 Pocono Rd + Brookfield CT 06804 + US + +00-25-0F (hex) On-Ramp Wireless, Inc. +00250F (base 16) On-Ramp Wireless, Inc. + 16885 West Bernardo Drive + San Diego CA 92127 + US + +00-24-F5 (hex) NDS Surgical Imaging +0024F5 (base 16) NDS Surgical Imaging + 5750 Hellyer Ave. + San Jose CA. 95138 + US + +00-24-67 (hex) AOC International (Europe) GmbH +002467 (base 16) AOC International (Europe) GmbH + Lahnstrasse 86A + Berlin 12055 + DE + +00-24-6D (hex) Weinzierl Engineering GmbH +00246D (base 16) Weinzierl Engineering GmbH + Bahnhofstrasse 6 + Tyrlaching Bayern 84558 + DE + +00-24-70 (hex) AUROTECH ultrasound AS. +002470 (base 16) AUROTECH ultrasound AS. + Svingen 1 + Tydal Sr-Tr N-7590 + NO + +00-24-6A (hex) Solid Year Co., Ltd. +00246A (base 16) Solid Year Co., Ltd. + 2F-1, No. 94, Bao-chung Road, + Hsin-tien City Taipei Hsien 23147 + TW + +00-24-92 (hex) Motorola, Broadband Solutions Group +002492 (base 16) Motorola, Broadband Solutions Group + 1101 Marina Village Parkway + Alameda CA 94501 + US + +00-24-8B (hex) HYBUS CO., LTD. +00248B (base 16) HYBUS CO., LTD. + Rm# 701, Daerung Post Tower 1st + SEOUL 152-790 + KR + +00-24-84 (hex) Bang and Olufsen Medicom a/s +002484 (base 16) Bang and Olufsen Medicom a/s + Gimsinglundvej 20 + Struer DK DK7600 + DK + +00-24-80 (hex) Meteocontrol GmbH +002480 (base 16) Meteocontrol GmbH + Spichererstrasse 48 + Augsburg Bavaria 86152 + DE + +00-24-7A (hex) FU YI CHENG Technology Co., Ltd. +00247A (base 16) FU YI CHENG Technology Co., Ltd. + 13F, No. 105-1, Jilin Rd., Luju Shiang, + Taoyuan 338 + TW + +00-24-76 (hex) TAP.tv +002476 (base 16) TAP.tv + 16w361 South Frontage Road + Burr Ridge IL 60527 + US + +00-24-B4 (hex) ESCATRONIC GmbH +0024B4 (base 16) ESCATRONIC GmbH + Wuerzburger Str. 8 + Laatzen Lower Saxony 30880 + DE + +00-24-B1 (hex) Coulomb Technologies +0024B1 (base 16) Coulomb Technologies + 1692 Dell Ave + Campbell CA 95008 + US + +00-24-9C (hex) Bimeng Comunication System Co. Ltd +00249C (base 16) Bimeng Comunication System Co. Ltd + Level 16/f, Tower B,Sinotrans Plaza,No.43, Xi Zhi Men Northern Road,Hai dian District + Beijing 100044 + CN + +00-24-98 (hex) Cisco Systems, Inc +002498 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-24-52 (hex) Silicon Software GmbH +002452 (base 16) Silicon Software GmbH + Steubenstrasse 46 + Mannheim Baden-Wuerttemberg 68163 + DE + +00-24-53 (hex) Initra d.o.o. +002453 (base 16) Initra d.o.o. + Slomskova 33 + Ljubljana 1000 + SI + +00-24-4C (hex) Solartron Metrology Ltd +00244C (base 16) Solartron Metrology Ltd + Steyning Way + Bognor Regis West Sussex PO20 9ST + GB + +00-24-48 (hex) SpiderCloud Wireless, Inc +002448 (base 16) SpiderCloud Wireless, Inc + 475 Sycamore Drive + Milpitas CA 95035 + US + +00-24-4B (hex) PERCEPTRON INC +00244B (base 16) PERCEPTRON INC + 47827 HALYARD DR + PLYMOUTH MI 48170 + US + +00-24-28 (hex) EnergyICT +002428 (base 16) EnergyICT + Theodoor Sevenslaan 104a + Kortrijk 8500 + BE + +00-24-17 (hex) Thomson Telecom Belgium +002417 (base 16) Thomson Telecom Belgium + Prins Boudewijnlaan 47 + Edegem Antwerp B-2650 + BE + +00-24-16 (hex) Any Use +002416 (base 16) Any Use + LG APT 211-1805, + Yongin City Gyeong-Gi Province 448-150 + KR + +00-24-2A (hex) Hittite Microwave Corporation +00242A (base 16) Hittite Microwave Corporation + 20 Alpha Rd + Chelmsford MA 01824 + US + +00-24-22 (hex) Knapp Logistik Automation GmbH +002422 (base 16) Knapp Logistik Automation GmbH + Günter Knapp-Straße 5-7 + Hart bei Graz Styria 8075 + AT + +00-24-1B (hex) iWOW Communications Pte Ltd +00241B (base 16) iWOW Communications Pte Ltd + 1 Lorong 2 Toa Payoh #04-01 + 319637 + SG + +00-24-5E (hex) Hivision Co.,ltd +00245E (base 16) Hivision Co.,ltd + 2201-2202, COFCO Property Tower, + Shenzhen Guangdong 518101 + CN + +00-24-4D (hex) Hokkaido Electronics Corporation +00244D (base 16) Hokkaido Electronics Corporation + 1-1 East 10 North 10 + Sapporo Hokkaido 065-0010 + JP + +00-24-42 (hex) Axona Limited +002442 (base 16) Axona Limited + Unit 4U St. Albans Enterprise Centre + St. Albans Herts AL3 6EN + GB + +00-24-00 (hex) Nortel Networks +002400 (base 16) Nortel Networks + 2221 Lakeside Blvd + Richardson TX 75081 + US + +00-23-FB (hex) IP Datatel, LLC. +0023FB (base 16) IP Datatel, LLC. + 13110 Southwest Freeway + Sugar Land Texas 77478 + US + +00-24-09 (hex) The Toro Company +002409 (base 16) The Toro Company + 5825 Jasmine Street + Riverside CA 92504 + US + +00-24-06 (hex) Pointmobile +002406 (base 16) Pointmobile + 301,World Meridian Verture Center-1 60-24 + Seoul Geumcheon-gu 153781 + KR + +00-24-3C (hex) S.A.A.A. +00243C (base 16) S.A.A.A. + Z.A. Croix Saint Mathieu + GALLARDON Eure et Loir 28320 + FR + +00-23-D3 (hex) AirLink WiFi Networking Corp. +0023D3 (base 16) AirLink WiFi Networking Corp. + 19F-1 Room A , No.97, Sec 4, Chung Hsin Rd., + San Chung City, Taipei Hsien 241 + TW + +00-23-CA (hex) Behind The Set, LLC +0023CA (base 16) Behind The Set, LLC + 2185 Knollwood Dr. + Boulder CO 80302 + US + +00-23-CB (hex) Shenzhen Full-join Technology Co.,Ltd +0023CB (base 16) Shenzhen Full-join Technology Co.,Ltd + 9/F,No.1,Xinrui Road,Hourui ,Xixiang Town, Bao'an District + ShenZhen GuangDong 518000 + CN + +00-23-AD (hex) Xmark Corporation +0023AD (base 16) Xmark Corporation + 309 Legget Drive + Ottawa Ontario K2K 3A3 + CA + +00-23-AB (hex) Cisco Systems, Inc +0023AB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-23-A4 (hex) New Concepts Development Corp. +0023A4 (base 16) New Concepts Development Corp. + 2650 Bridge Lane + Woodstock IL 60098 + US + +00-23-DC (hex) Benein, Inc +0023DC (base 16) Benein, Inc + Hyojachonjesangga228 B9, 297, + Sengnam-si Kyunggi-do 463-818 + KR + +00-23-D1 (hex) TRG +0023D1 (base 16) TRG + Wisma Kosgoro 13th Floor + Jakarta Pusat 10350 + ID + +00-23-FE (hex) Biodevices, SA +0023FE (base 16) Biodevices, SA + Rua 5 de Outubro, 309 + Porto 4100-175 + PT + +00-23-F4 (hex) Masternaut +0023F4 (base 16) Masternaut + 4, rue Charles Cros + Louviers 27407 + FR + +00-23-D0 (hex) Uniloc USA Inc. +0023D0 (base 16) Uniloc USA Inc. + 3333 Michelson Drive + Irvine CA 92612 + US + +00-23-C7 (hex) AVSystem +0023C7 (base 16) AVSystem + ul. Friedleina 4 + Kraków małopolskie 30-009 + PL + +00-23-C3 (hex) LogMeIn, Inc. +0023C3 (base 16) LogMeIn, Inc. + 500 Unicorn Park Drive + Woburn Massachusetts 01801 + US + +00-23-B0 (hex) COMXION Technology Inc. +0023B0 (base 16) COMXION Technology Inc. + 11F, No. 111, Sec 2, Keelung Rd., Sinyi Distric + Taipei Taiwan 110 + TW + +00-23-E1 (hex) Cavena Image Products AB +0023E1 (base 16) Cavena Image Products AB + Nytorpsvägen 26 + Täby Stockholm se-183 53 + SE + +00-23-7E (hex) ELSTER GMBH +00237E (base 16) ELSTER GMBH + KUHLMANNSTRASSE 10 + HAMELN 31785 + DE + +00-23-7C (hex) NEOTION +00237C (base 16) NEOTION + ZI les Paluds + AUBAGNE F-13400 + FR + +00-23-7A (hex) RIM +00237A (base 16) RIM + 295 Phillip Street + Waterloo Ontario N2L 3W8 + CA + +00-23-6D (hex) ResMed Ltd +00236D (base 16) ResMed Ltd + 1, Elizabeth Macarthur Drive + Bella Vista NSW 2153 + AU + +00-23-6B (hex) Xembedded, Inc. +00236B (base 16) Xembedded, Inc. + 1050 Highland Dr + Ann Arbor MI 48108 + US + +00-23-61 (hex) Unigen Corporation +002361 (base 16) Unigen Corporation + 45388 Warm Springs Blvd + Fremont CA 94539 + US + +00-23-2C (hex) Senticare +00232C (base 16) Senticare + 161 Worcester Rd + Framingham MA 01701 + US + +00-23-2B (hex) IRD A/S +00232B (base 16) IRD A/S + Kullinggade 31 + Svendborg Fyn 5700 + DK + +00-23-36 (hex) METEL s.r.o. +002336 (base 16) METEL s.r.o. + Zizkuv Kopec 617 + Ceska Skalice Nachod 55203 + CZ + +00-23-38 (hex) OJ-Electronics A/S +002338 (base 16) OJ-Electronics A/S + Stenager 13B + Sønderborg 6400 + DK + +00-23-3B (hex) C-Matic Systems Ltd +00233B (base 16) C-Matic Systems Ltd + Warren Court + Crowborough East Sussex TN6 2QX + GB + +00-23-2A (hex) eonas IT-Beratung und -Entwicklung GmbH +00232A (base 16) eonas IT-Beratung und -Entwicklung GmbH + Greifenhagener Str. 54 + Berlin 10437 + DE + +00-23-27 (hex) Shouyo Electronics CO., LTD +002327 (base 16) Shouyo Electronics CO., LTD + 4F., No.8, Lane 345, Yang Kung St. + Taipei 11491 + TW + +00-23-28 (hex) ALCON TELECOMMUNICATIONS CO., LTD. +002328 (base 16) ALCON TELECOMMUNICATIONS CO., LTD. + 2nd FL, NO 480-5, SEC. 6, YEN-PING N. RD., + TAIPEI TAIWAN 111 + TW + +00-23-72 (hex) MORE STAR INDUSTRIAL GROUP LIMITED +002372 (base 16) MORE STAR INDUSTRIAL GROUP LIMITED + Rm1221-1225, F12 Sangda Science and Technology Building , + Shenzhen Guangdong 518057 + CN + +00-23-4C (hex) KTC AB +00234C (base 16) KTC AB + F O Petersons gata 6 + Vastra Frolunda Gothenburg SE-42131 + SE + +00-23-43 (hex) TEM AG +002343 (base 16) TEM AG + Triststrasse 8 + Chur 7007 + CH + +00-23-5F (hex) Silicon Micro Sensors GmbH +00235F (base 16) Silicon Micro Sensors GmbH + Grenzstrasse 28 / Gebäude 32 + Dresden Saxony 01109 + DE + +00-23-85 (hex) ANTIPODE +002385 (base 16) ANTIPODE + 5 RUE DE DOUAI + PARIS ILE DE FRANCE 75009 + FR + +00-22-D8 (hex) Shenzhen GST Security and Safety Technology Limited +0022D8 (base 16) Shenzhen GST Security and Safety Technology Limited + Room 502,Building 6 of Kupai Infomation Harbour, + Shenzhen Guangdong 518040 + CN + +00-22-DC (hex) Vigil Health Solutions Inc. +0022DC (base 16) Vigil Health Solutions Inc. + 2102-4464 Markham St + Victoria BC V8Z 7X8 + CA + +00-22-D9 (hex) Fortex Industrial Ltd. +0022D9 (base 16) Fortex Industrial Ltd. + Flat 16, 12 /F.,Pacific Trade Centre + Kowloon Hong Kong 852 + CN + +00-22-D3 (hex) Hub-Tech +0022D3 (base 16) Hub-Tech + 77, Imae-dong + Seongnam-si Gyeonggi-do 463-829 + KR + +00-22-D4 (hex) ComWorth Co., Ltd. +0022D4 (base 16) ComWorth Co., Ltd. + 2-35-7 Nishimagome + Ohta-ku Tokyo 143-0026 + JP + +00-22-FE (hex) Advanced Illumination +0022FE (base 16) Advanced Illumination + 440 State Garage Road + Rochester Vermont 05767 + US + +00-23-00 (hex) Cayee Computer Ltd. +002300 (base 16) Cayee Computer Ltd. + Units 1002-1003, 10/F, Join-In Hang Sing Centre + Kwai Chung N.T + HK + +00-22-F3 (hex) SHARP Corporation +0022F3 (base 16) SHARP Corporation + 22-22,Nagaike-cho + Osaka city Osaka prefecture 545-8522 + JP + +00-22-F6 (hex) Syracuse Research Corporation +0022F6 (base 16) Syracuse Research Corporation + 6225 Running Ridge Road + North Syracuse NY 13212 + US + +00-23-0D (hex) Nortel Networks +00230D (base 16) Nortel Networks + 2221 Lakeside Blvd + Richardson TX 75081 + US + +00-23-03 (hex) LITE-ON IT Corporation +002303 (base 16) LITE-ON IT Corporation + 14F, No. 392, Ruey Kuang Road, Neihu + Taipei City 114 + TW + +00-22-ED (hex) TSI Power Corporation +0022ED (base 16) TSI Power Corporation + 1103 West Pierce Avenue + Antigo WI 54409 + US + +00-22-E1 (hex) ZORT Labs, LLC. +0022E1 (base 16) ZORT Labs, LLC. + 44H Dover Point Road + Dover NH 03820 + US + +00-22-E0 (hex) Atlantic Software Technologies S.r.L. +0022E0 (base 16) Atlantic Software Technologies S.r.L. + Via Martino Bassi, 9 + Milano 20148 + IT + +00-22-DF (hex) TAMUZ Monitors +0022DF (base 16) TAMUZ Monitors + Tiedenkamp 16 + Henstedt-Ulzburg SH 24558 + DE + +00-23-1A (hex) ITF Co., Ltd. +00231A (base 16) ITF Co., Ltd. + 2-2-11 Nishiki-cho + Tachikawa-shi Tokyo 190-0022 + JP + +00-22-BC (hex) JDSU France SAS +0022BC (base 16) JDSU France SAS + 34 rue Necker + SAINT ETIENNE LOIRE 42000 + FR + +00-22-AA (hex) Nintendo Co., Ltd. +0022AA (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-22-C9 (hex) Lenord, Bauer & Co GmbH +0022C9 (base 16) Lenord, Bauer & Co GmbH + Dohlenstr 32 + Oberhausen NRW 46145 + DE + +00-22-8C (hex) Photon Europe GmbH +00228C (base 16) Photon Europe GmbH + Jülicher Straße 376 + Aachen Nordrhein-Westfalen 52070 + DE + +00-22-8B (hex) Kensington Computer Products Group +00228B (base 16) Kensington Computer Products Group + 333 Twin Dolphin Dr. + Redwood Shores CA 94065 + US + +00-22-8D (hex) GBS Laboratories LLC +00228D (base 16) GBS Laboratories LLC + 2325 Dulles Corner Blvd + Herndon VA 20171 + US + +00-22-4C (hex) Nintendo Co., Ltd. +00224C (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-22-4A (hex) RAYLASE AG +00224A (base 16) RAYLASE AG + Argelsrieder Feld 2-4 + Wessling Bavaria 82234 + DE + +00-22-4B (hex) AIRTECH TECHNOLOGIES, INC. +00224B (base 16) AIRTECH TECHNOLOGIES, INC. + 19fl-4, no.77, Hsin Tai Wu Rd., sec.1, Hsin-Chih + Taipei 221 + TW + +00-22-56 (hex) Cisco Systems, Inc +002256 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-22-52 (hex) ZOLL Lifecor Corporation +002252 (base 16) ZOLL Lifecor Corporation + 121 Freeport Road + Pittsburgh PA 15238 + US + +00-22-4D (hex) MITAC INTERNATIONAL CORP. +00224D (base 16) MITAC INTERNATIONAL CORP. + 6TH FL., NO187, TIDING BLVD., SEC. 2 + Taipei 114 + TW + +00-22-9F (hex) Sensys Traffic AB +00229F (base 16) Sensys Traffic AB + Slottsgatan 14 + Jonkoping Smaland 55322 + SE + +00-22-99 (hex) SeaMicro Inc. +002299 (base 16) SeaMicro Inc. + 4677 Old Ironsides Dr., + Santa Clara CA 95054 + US + +00-22-6D (hex) Shenzhen GIEC Electronics Co., Ltd. +00226D (base 16) Shenzhen GIEC Electronics Co., Ltd. + 24/F, XiNian Center, ShenNan Road 6021#, Futian District + Shenzhen Guangdong Province 518040 + CN + +00-22-6E (hex) Gowell Electronic Limited +00226E (base 16) Gowell Electronic Limited + Room 3601 ,36 Floor,Golden Central Tower,Jintian Road,Futian Central District, + Shenzhen GuangDong 518048 + CN + +00-22-5D (hex) Digicable Network India Pvt. Ltd. +00225D (base 16) Digicable Network India Pvt. Ltd. + 7B, Shah Industrial Estate + Andheri - West, Mumbai. Maharashtra 400 053 + IN + +00-22-7B (hex) Apogee Labs, Inc. +00227B (base 16) Apogee Labs, Inc. + 210 S. 3rd St. + North Wales PA 19454 + US + +00-22-89 (hex) Vandelrande APC inc. +002289 (base 16) Vandelrande APC inc. + 1280 Lebourgneuf Blvd. + Quebec G2K 0H1 + CA + +00-22-7D (hex) YE DATA INC. +00227D (base 16) YE DATA INC. + 182 Shinko + Iruma Saitama 358-0055 + JP + +00-22-A8 (hex) Ouman Oy +0022A8 (base 16) Ouman Oy + Voimatie 6 + Kempele FIN-90440 + FI + +00-22-23 (hex) TimeKeeping Systems, Inc. +002223 (base 16) TimeKeeping Systems, Inc. + 30700 Bainbridge Road + Solon OH 44139 + US + +00-22-1A (hex) Audio Precision +00221A (base 16) Audio Precision + 5750 SW Arctic Drive + Beaverton OR 97005 + US + +00-22-18 (hex) AKAMAI TECHNOLOGIES INC +002218 (base 16) AKAMAI TECHNOLOGIES INC + 150 BROADWAY + CAMBRIDGE MA 02142 + US + +00-22-3C (hex) RATIO Entwicklungen GmbH +00223C (base 16) RATIO Entwicklungen GmbH + Ludwig-Erhard-Strasse 22 + Hamburg 20459 + DE + +00-21-E7 (hex) Informatics Services Corporation +0021E7 (base 16) Informatics Services Corporation + 140, Negin Bldg., + Tehran 1549534511 + IR + +00-21-DC (hex) TECNOALARM S.r.l. +0021DC (base 16) TECNOALARM S.r.l. + Via Cirie' + San Mauro Torinese Torino 10099 + IT + +00-21-F1 (hex) Tutus Data AB +0021F1 (base 16) Tutus Data AB + Svardvagen 11 + Danderyd Stockholm 18233 + SE + +00-21-E3 (hex) SerialTek LLC +0021E3 (base 16) SerialTek LLC + 1570 Oakland Road + San Jose CA 95131 + US + +00-22-1C (hex) Private +00221C (base 16) Private + +00-22-22 (hex) Schaffner Deutschland GmbH +002222 (base 16) Schaffner Deutschland GmbH + Nürtingen Branch + Nürtingen BW D-72622 + DE + +00-21-F8 (hex) Enseo, Inc. +0021F8 (base 16) Enseo, Inc. + 401 International Parkway + Richardson TX 75081 + US + +00-21-F3 (hex) Si14 SpA +0021F3 (base 16) Si14 SpA + Via Tommaseo 77 + Padova PD 35131 + IT + +00-22-31 (hex) SMT&C Co., Ltd. +002231 (base 16) SMT&C Co., Ltd. + 2Fr. Haksan Bldg. 110, Gwangjang-dong, Gwangjin-gu + Seoul 143-802 + KR + +00-22-13 (hex) PCI CORPORATION +002213 (base 16) PCI CORPORATION + No.25, Lane 66, Hebei 1st St., Beitun District + Taichung 406 + TW + +00-22-01 (hex) Aksys Networks Inc +002201 (base 16) Aksys Networks Inc + 428, 3553 - 31 Street NW + Calgary T2L 2K7 + CA + +00-21-7B (hex) Bastec AB +00217B (base 16) Bastec AB + Hästvägen 4A + Malmö SE 212 35 + SE + +00-21-76 (hex) YMax Telecom Ltd. +002176 (base 16) YMax Telecom Ltd. + 11 Moshe Levi str. + Rishon Le Zion 75658 + IL + +00-21-71 (hex) Wesung TNC Co., Ltd. +002171 (base 16) Wesung TNC Co., Ltd. + 102-1409, Bucheon Chunui Technopark 1st, + Bucheon-City, Gyeongggi-Do 420-857 + KR + +00-21-93 (hex) Videofon MV +002193 (base 16) Videofon MV + 6 Blackoak Mews + Newtown PA 18940 + US + +00-21-92 (hex) Baoding Galaxy Electronic Technology Co.,Ltd +002192 (base 16) Baoding Galaxy Electronic Technology Co.,Ltd + NO.91 Fengfan Rd.,GaoKai District,Baoding City,Hebei Prov.China 071051 + Baoding City Hebei Prov. 071051 + CN + +00-21-A7 (hex) Hantle System Co., Ltd. +0021A7 (base 16) Hantle System Co., Ltd. + 481-10 Byucksan Digital Vally II, RM 1511 + Seoul City Seoul 153-783 + KR + +00-21-9C (hex) Honeywld Technology Corp. +00219C (base 16) Honeywld Technology Corp. + No.40,Hsueh-Fu Rd. + Hsinchu 300 + TW + +00-21-9A (hex) Cambridge Visual Networks Ltd +00219A (base 16) Cambridge Visual Networks Ltd + 61 Selwyn Road + Cambridge Cambridgeshire CB3 9EA + GB + +00-21-D8 (hex) Cisco Systems, Inc +0021D8 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-21-D7 (hex) Cisco Systems, Inc +0021D7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-21-D9 (hex) SEKONIC CORPORATION +0021D9 (base 16) SEKONIC CORPORATION + 7-24-14 + NERIMA-KU TOKYO 178-8686 + JP + +00-21-DA (hex) Automation Products Group Inc. +0021DA (base 16) Automation Products Group Inc. + 1025 West 1700 North + Logan Utah 84321 + US + +00-21-B5 (hex) Galvanic Ltd +0021B5 (base 16) Galvanic Ltd + 38 Nothumberland Road + Dublin 2 + IE + +00-21-BD (hex) Nintendo Co., Ltd. +0021BD (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-21-C4 (hex) Consilium AB +0021C4 (base 16) Consilium AB + Västra Finnbodavägen 2-4 + Nacka Stockholm 13131 + SE + +00-21-89 (hex) AppTech, Inc. +002189 (base 16) AppTech, Inc. + 363 E Greyhound Pass + Carmel Indiana 46032 + US + +00-21-22 (hex) Chip-pro Ltd. +002122 (base 16) Chip-pro Ltd. + 5F.-4, No.63, Siwei Rd., North District, + Hsinchu 300 + TW + +00-21-25 (hex) KUK JE TONG SHIN Co.,LTD +002125 (base 16) KUK JE TONG SHIN Co.,LTD + 476-3 + Incheon Kwangyouk-Si 407-060 + KR + +00-21-26 (hex) Shenzhen Torch Equipment Co., Ltd. +002126 (base 16) Shenzhen Torch Equipment Co., Ltd. + Floor 5, Block 3, Liming Industrial District, Zhongshanyuan Road, Nanshan, + Shenzhen Guangdong 518052 + CN + +00-21-13 (hex) Padtec S/A +002113 (base 16) Padtec S/A + Road Campinas Mogi-Mirim km 118,5 + Campinas São Paulo 13086-902 + BR + +00-21-12 (hex) WISCOM SYSTEM CO.,LTD +002112 (base 16) WISCOM SYSTEM CO.,LTD + 100 Jiangjun Road,Jiangning, + Nanjing 211100 + CN + +00-21-0E (hex) Orpak Systems L.T.D. +00210E (base 16) Orpak Systems L.T.D. + 31 Lechi St + Bnei - Brak 51114 + IL + +00-21-61 (hex) Yournet Inc. +002161 (base 16) Yournet Inc. + KT R&D Center + Seoul 137-792 + KR + +00-21-5F (hex) IHSE GmbH +00215F (base 16) IHSE GmbH + Maybachstraße 11 + Oberteuringen Baden-Württemberg 88094 + DE + +00-21-35 (hex) ALCATEL-LUCENT +002135 (base 16) ALCATEL-LUCENT + Ramirez de Prado 5 + Madrid 28045 + ES + +00-21-38 (hex) Cepheid +002138 (base 16) Cepheid + 904 Caribbean Drive + Sunnyvale CA 94089 + US + +00-21-47 (hex) Nintendo Co., Ltd. +002147 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-21-49 (hex) China Daheng Group ,Inc. +002149 (base 16) China Daheng Group ,Inc. + 12F Daheng Science & Technology Tower ,NO.3 Suzhou Str. + Beijing 100080 + CN + +00-21-56 (hex) Cisco Systems, Inc +002156 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-21-51 (hex) Millinet Co., Ltd. +002151 (base 16) Millinet Co., Ltd. + 2F, West Building, IT Venture Tower, 78, Garakbon-Dong + Songpa-gu Seoul 138-803 + US + +00-21-6C (hex) ODVA +00216C (base 16) ODVA + 4220 Varsity Drive + Ann Arbor MI 48108-5006 + US + +00-21-1C (hex) Cisco Systems, Inc +00211C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-21-18 (hex) Athena Tech, Inc. +002118 (base 16) Athena Tech, Inc. + 3721 Macintosh Dr + Warrenton VA 20187 + US + +00-1F-BD (hex) Kyocera Wireless Corp. +001FBD (base 16) Kyocera Wireless Corp. + 10300 Campus Point Drive + San Diego CA 92121 + US + +00-1F-B9 (hex) Paltronics +001FB9 (base 16) Paltronics + 1145 Paltronics Ct + Crystal Lake IL 60014 + US + +00-1F-B7 (hex) WiMate Technologies Corp. +001FB7 (base 16) WiMate Technologies Corp. + 14A Building 2, Guimiao Garden, Nanguanglu, Nanshan District + Shenzhen Guangdong 518054 + CN + +00-1F-B4 (hex) SmartShare Systems +001FB4 (base 16) SmartShare Systems + Tonsbakken 16-18 + Skovlunde DK-2740 + DK + +00-1F-B6 (hex) Chi Lin Technology Co., Ltd. +001FB6 (base 16) Chi Lin Technology Co., Ltd. + No.18, Sheng Li 1st St., Jen Te Hsiang, + Tainan Taiwan 71758 + CN + +00-1F-C8 (hex) Up-Today Industrial Co., Ltd. +001FC8 (base 16) Up-Today Industrial Co., Ltd. + 7/F., Unify Commercial & Industrial Building + Kowloon + HK + +00-1F-C5 (hex) Nintendo Co., Ltd. +001FC5 (base 16) Nintendo Co., Ltd. + 11-1 HOKOTATE-CHO KAMITOBA, MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +00-1F-C0 (hex) Control Express Finland Oy +001FC0 (base 16) Control Express Finland Oy + Laitaatsillantie 3 + Savonlinna 57170 + FI + +00-1F-BC (hex) EVGA Corporation +001FBC (base 16) EVGA Corporation + 2900 Saturn St. + Brea CA 92821 + US + +00-1F-F9 (hex) Advanced Knowledge Associates +001FF9 (base 16) Advanced Knowledge Associates + 3350 Scott Blvd, Suite 40 + Santa Clara CA 95054-3119 + US + +00-1F-ED (hex) Tecan Systems Inc. +001FED (base 16) Tecan Systems Inc. + 2450 Zanker Road + San Jose CA 95131 + US + +00-1F-E5 (hex) In-Circuit GmbH +001FE5 (base 16) In-Circuit GmbH + Königsbrücker Strasse 69 + Dresden 01099 + DE + +00-1F-F4 (hex) Power Monitors, Inc. +001FF4 (base 16) Power Monitors, Inc. + 800 North Main Street + Mt. Crawford Virginia 22841 + US + +00-1F-5F (hex) Blatand GmbH +001F5F (base 16) Blatand GmbH + Lichtenbergstrße 8 + Garching Bavaria 85748 + DE + +00-1F-57 (hex) Phonik Innovation Co.,LTD +001F57 (base 16) Phonik Innovation Co.,LTD + 29/167 Moo2, 345 Rd, Lampo, + Nonthaburi 11110 + TH + +00-1F-59 (hex) Kronback Tracers +001F59 (base 16) Kronback Tracers + c/o DTU, R254 + Ballerup Copenhagen 2750 + DK + +00-1F-4E (hex) ConMed Linvatec +001F4E (base 16) ConMed Linvatec + 11311 Concept Blvd. + Largo FL 33773 + US + +00-1F-AA (hex) Taseon, Inc. +001FAA (base 16) Taseon, Inc. + 3099 N. First Street + San Jose CA 95134 + US + +00-1F-7B (hex) TechNexion Ltd. +001F7B (base 16) TechNexion Ltd. + 17F-1, No. 16, Jian Ba Road, + Chung Ho Taipei 235 + TW + +00-1F-7D (hex) Embedded Wireless GmbH +001F7D (base 16) Embedded Wireless GmbH + Soeflinger Strasse 200 + Ulm BW 89077 + DE + +00-1F-8D (hex) Ingenieurbuero Stark GmbH und Ko. KG +001F8D (base 16) Ingenieurbuero Stark GmbH und Ko. KG + Rudolf-Diesel-Strasse 44 + Laichingen BW 89150 + DE + +00-1F-AF (hex) NextIO, Inc. +001FAF (base 16) NextIO, Inc. + 8303 N MoPac Expressway + Austin TX 78759 + US + +00-1F-74 (hex) Eigen Development +001F74 (base 16) Eigen Development + 1807 W10th Ave + Vancouver BC V6J 2A9 + CA + +00-1F-75 (hex) GiBahn Media +001F75 (base 16) GiBahn Media + 1816 Rosedale Suseo-dong + Seoul 135-885 + KR + +00-1F-8F (hex) Shanghai Bellmann Digital Source Co.,Ltd. +001F8F (base 16) Shanghai Bellmann Digital Source Co.,Ltd. + 404-408 Main Bd, FDUSP, No.11 Guotai Rd. + Shanghai 200433 + CN + +00-1F-84 (hex) Gigle Semiconductor +001F84 (base 16) Gigle Semiconductor + Barcelona Activa - Vivero Glorias + Barcelona 08018 + ES + +00-1F-6E (hex) Vtech Engineering Corporation +001F6E (base 16) Vtech Engineering Corporation + 20 New England Business Center + Andover MA 01810 + US + +00-1F-66 (hex) PLANAR LLC +001F66 (base 16) PLANAR LLC + 32, Elkina str + Chelyabinsk SU 454091 + RU + +00-1F-A0 (hex) A10 Networks +001FA0 (base 16) A10 Networks + 3 West Plumeria Drive + San Jose CA 95134 + US + +00-1F-9E (hex) Cisco Systems, Inc +001F9E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1E-E6 (hex) Shenzhen Advanced Video Info-Tech Co., Ltd. +001EE6 (base 16) Shenzhen Advanced Video Info-Tech Co., Ltd. + Tianxiang 11A, Tian'an Cyber Park , Futian + Shenzhen Guangdong 518048 + CN + +00-1E-F7 (hex) Cisco Systems, Inc +001EF7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1F-0B (hex) Federal State Unitary Enterprise Industrial UnionElectropribor +001F0B (base 16) Federal State Unitary Enterprise Industrial UnionElectropribor + + Penza 440011 + RU + +00-1F-0C (hex) Intelligent Digital Services GmbH +001F0C (base 16) Intelligent Digital Services GmbH + Grevesmuehlener Strasse 8 + Mallentin Mecklenburg-Vorpommern 23639 + DE + +00-1F-08 (hex) RISCO LTD +001F08 (base 16) RISCO LTD + 32 Hacharoshet St + Kiriat Malachi 83101 + IL + +00-1F-43 (hex) ENTES ELEKTRONIK +001F43 (base 16) ENTES ELEKTRONIK + Y. Dudullu Org. San. Bol. And Sanayi Sit. No.6 + Istanbul Dudullu 34775 + TR + +00-1F-14 (hex) NexG +001F14 (base 16) NexG + 5F Seoul Academy Bldg, Daechi-Dong, Gangnam-Gu, + Seoul 135-280 + KR + +00-1E-F1 (hex) Servimat +001EF1 (base 16) Servimat + ZAET Les Haies + St Maximin Oise 60740 + FR + +00-1E-F4 (hex) L-3 Communications Display Systems +001EF4 (base 16) L-3 Communications Display Systems + 1355 Bluegrass Lakes Parkway + Alpharetta GA 30004-8458 + US + +00-1E-F5 (hex) Hitek Automated Inc. +001EF5 (base 16) Hitek Automated Inc. + Room C3-901, No.383, Huamen Shijia + Hangzhou 310012 + CN + +00-1F-0E (hex) Japan Kyastem Co., Ltd +001F0E (base 16) Japan Kyastem Co., Ltd + 1-4-4 + Tachikawa Tokyo 190-0022 + JP + +00-1F-28 (hex) HPN Supply Chain +001F28 (base 16) HPN Supply Chain + 8000 Foothills Blvd + Roseville CA 95747 + US + +00-1F-1E (hex) Astec Technology Co., Ltd +001F1E (base 16) Astec Technology Co., Ltd + 12F, No.2, Jian Ba Rd. + Chung Ho Taipei Hsien 235 + TW + +00-1F-4A (hex) Albentia Systems S.A. +001F4A (base 16) Albentia Systems S.A. + Albala 13 + Madrid 28037 + ES + +00-1E-AA (hex) E-Senza Technologies GmbH +001EAA (base 16) E-Senza Technologies GmbH + Blarerstrasse 56 + Konstanz BW 78462 + DE + +00-1E-9C (hex) Fidustron INC +001E9C (base 16) Fidustron INC + NO.770-6, Jhongiheng Rd. + Jhonghe City Taipei County 235 + TW + +00-1E-97 (hex) Medium Link System Technology CO., LTD, +001E97 (base 16) Medium Link System Technology CO., LTD, + 11F.-2, No.7, Alley 92, Lane 77, Sec. 4, Sinhai Rd., + Wunshan District, Taipei 11693 + TW + +00-1E-8B (hex) Infra Access Korea Co., Ltd. +001E8B (base 16) Infra Access Korea Co., Ltd. + #902, Sambo Saving Bank B/D, + Kwanak-gu, Seoul 151-830 + KR + +00-1E-BB (hex) BLUELIGHT TECHNOLOGY INC. +001EBB (base 16) BLUELIGHT TECHNOLOGY INC. + 6472 CAMDEN AVE., SUITE 102B + SAN JOSE CA 95120 + US + +00-1E-B5 (hex) Ever Sparkle Technologies Ltd +001EB5 (base 16) Ever Sparkle Technologies Ltd + Unit 403, Nan Fung Commercial Centre + Kowloon Bay Kowloon + HK + +00-1E-B3 (hex) Primex Wireless +001EB3 (base 16) Primex Wireless + 965 Wells Street + Lake Geneva WI 53147 + US + +00-1E-85 (hex) Lagotek Corporation +001E85 (base 16) Lagotek Corporation + 11661 SE 1st St. #208 + Bellevue WA 98005 + US + +00-1E-D8 (hex) Digital United Inc. +001ED8 (base 16) Digital United Inc. + 9F, No.220, Gangcian Rd. + Taipei 11444 + TW + +00-1E-D6 (hex) Alentec & Orion AB +001ED6 (base 16) Alentec & Orion AB + Grustagsvägen 4 + 138 40 ÄLTA + SE + +00-1E-C6 (hex) Obvius Holdings LLC +001EC6 (base 16) Obvius Holdings LLC + 20811 NW Cornell Road + Hillsboro OR 97124 + US + +00-1E-C4 (hex) Celio Corp +001EC4 (base 16) Celio Corp + 265 E 100 S # 280 + Salt Lake City UT 84111 + US + +00-1E-C1 (hex) 3COM EUROPE LTD +001EC1 (base 16) 3COM EUROPE LTD + Peoplebuilding 2 + Hemel Hempstead HERTS. HP2 4NW + GB + +00-1E-B6 (hex) TAG Heuer SA +001EB6 (base 16) TAG Heuer SA + Rue Louis-Joseph Chevrolet 6A + la Chaux-de-Fonds NE 2300 + CH + +00-1E-AC (hex) Armadeus Systems +001EAC (base 16) Armadeus Systems + Business Campus + MULHOUSE cedex Haut-Rhin 68058 + FR + +00-1E-77 (hex) Air2App +001E77 (base 16) Air2App + 50 Old Forge Rd + Hanover MA 02339 + US + +00-1E-7B (hex) R.I.CO. S.r.l. +001E7B (base 16) R.I.CO. S.r.l. + via Adriatica, 17 + Castelfidardo AN 60022 + IT + +00-1E-6E (hex) Shenzhen First Mile Communications Ltd +001E6E (base 16) Shenzhen First Mile Communications Ltd + 5th Floor, Block R3-A + Shenzhen Guangdong 518057 + CN + +00-1E-6D (hex) IT R&D Center +001E6D (base 16) IT R&D Center + 461-25, Jeonmin-dong,Yuseong-Gu + Daejeon 305-811 + KR + +00-1E-34 (hex) CryptoMetrics +001E34 (base 16) CryptoMetrics + 160 Michael Cowpland Dr + Ottawa Ontario K2M 1P6 + CA + +00-1E-2D (hex) STIM +001E2D (base 16) STIM + ZAC les COUSTELLIERS + CASTRIES HERAULT 34160 + FR + +00-1E-41 (hex) Microwave Communication & Component, Inc. +001E41 (base 16) Microwave Communication & Component, Inc. + #204, WOOLIM LION`S VALLEY 2, 680 + Seoul 150-787 + KR + +00-1D-FC (hex) KSIC +001DFC (base 16) KSIC + #6F, Korea Federation of Teacher's Associations, 114-1, TaeBong-Ro, + Seoul Seocho-Ku 137-715 + KR + +00-1E-55 (hex) COWON SYSTEMS,Inc. +001E55 (base 16) COWON SYSTEMS,Inc. + 6th Fl. COWON TOWER,689-3, + Seoul 135-080 + KR + +00-1E-56 (hex) Bally Wulff Entertainment GmbH +001E56 (base 16) Bally Wulff Entertainment GmbH + Maybachufer 48-51 + Berlin 12045 + DE + +00-1E-3F (hex) TrellisWare Technologies, Inc. +001E3F (base 16) TrellisWare Technologies, Inc. + 16516 Via Esprillo, Suite 300 + San Diego CA 92127 + US + +00-1E-57 (hex) ALCOMA, spol. s r.o. +001E57 (base 16) ALCOMA, spol. s r.o. + Klukovice 313, Praha - 5 + Praha 152 00 + CZ + +00-1E-50 (hex) BATTISTONI RESEARCH +001E50 (base 16) BATTISTONI RESEARCH + PARCO DONICA 56 + FISCIANO SALERNO 84084 + IT + +00-1E-11 (hex) ELELUX INTERNATIONAL LTD +001E11 (base 16) ELELUX INTERNATIONAL LTD + 3F., NO.103 CHOW TZE STREET + TAIPEI 114 + TW + +00-1D-F2 (hex) Netflix, Inc. +001DF2 (base 16) Netflix, Inc. + 100 Winchester Circle + Los Gatos CA 95032 + US + +00-1D-EF (hex) TRIMM, INC. +001DEF (base 16) TRIMM, INC. + 407 RAILROAD STREET + BUTNER NC 27509 + US + +00-1D-F1 (hex) Intego Systems, Inc. +001DF1 (base 16) Intego Systems, Inc. + 5343 Bowden Road + Jacksonville FL 32216 + US + +00-1D-ED (hex) Grid Net, Inc. +001DED (base 16) Grid Net, Inc. + 340 Brannan Street + San Francisco CA 94107 + US + +00-1D-C3 (hex) RIKOR TV, Ltd +001DC3 (base 16) RIKOR TV, Ltd + Kostomarovsky per.,3 + Moscow 105120 + RU + +00-1D-C1 (hex) Audinate Pty L +001DC1 (base 16) Audinate Pty L + Level 1, 458 Wattle St + Ultimo NSW 2007 + AU + +00-1D-B2 (hex) HOKKAIDO ELECTRIC ENGINEERING CO.,LTD. +001DB2 (base 16) HOKKAIDO ELECTRIC ENGINEERING CO.,LTD. + Nishinopporo 120-8 + Ebetu-City Hokkaido 069-0832 + JP + +00-1D-AD (hex) Sinotech Engineering Consultants, Inc. Geotechnical Enginee +001DAD (base 16) Sinotech Engineering Consultants, Inc. Geotechnical Enginee + Basement No.7 Lane 26, Yat-Sen Rd. + Taipei 110 + TW + +00-1D-AB (hex) SwissQual License AG +001DAB (base 16) SwissQual License AG + Baarerstrasse 78 + Zug Postfach 117 + CH + +00-1D-9C (hex) Rockwell Automation +001D9C (base 16) Rockwell Automation + 1 Allen-Bradley Dr. + Mayfield Heights OH 44124-6118 + US + +00-1D-A0 (hex) Heng Yu Electronic Manufacturing Company Limited +001DA0 (base 16) Heng Yu Electronic Manufacturing Company Limited + Room 1503-5, Nan Fung Com'l Centre, + Kowloon + HK + +00-1D-D8 (hex) Microsoft Corporation +001DD8 (base 16) Microsoft Corporation + One Microsoft Way + Redmond Washington 98052-6399 + US + +00-1D-C8 (hex) Navionics Research Inc., dba SCADAmetrics +001DC8 (base 16) Navionics Research Inc., dba SCADAmetrics + 1133 Pond Road + Wildwood Missouri 63038 + US + +00-1D-CC (hex) Ayon Cyber Security, Inc +001DCC (base 16) Ayon Cyber Security, Inc + 2350 Commerce Park Dr. + Palm Bay FL 32905 + US + +00-1D-92 (hex) MICRO-STAR INT'L CO.,LTD. +001D92 (base 16) MICRO-STAR INT'L CO.,LTD. + No.69,Li-De St,Jung-Ho City + Taipei Hsien 235 + TW + +00-1D-8A (hex) TechTrex Inc +001D8A (base 16) TechTrex Inc + 6221 Highway 7, Unit 12 + Woodbridge Ontalio L4H 0K8 + CA + +00-1D-80 (hex) Beijing Huahuan Eletronics Co.,Ltd +001D80 (base 16) Beijing Huahuan Eletronics Co.,Ltd + No.26,Shangdi 6th St.Haidian District, + Beijing 100085 + CN + +00-1D-83 (hex) Emitech Corporation +001D83 (base 16) Emitech Corporation + 2F,No.7-1,Industry E,Rd.9 + Hsinchu 308 + TW + +00-1D-74 (hex) Tianjin China-Silicon Microelectronics Co., Ltd. +001D74 (base 16) Tianjin China-Silicon Microelectronics Co., Ltd. + 301,3F Building 211,No.214 Hongqi Road, Nankai District, Tianjin China + Tianjin 300190 + CN + +00-1D-4B (hex) Grid Connect Inc. +001D4B (base 16) Grid Connect Inc. + 1630 W. Diehl Rd + Naperville IL 60563 + US + +00-1D-4D (hex) Adaptive Recognition Hungary, Inc +001D4D (base 16) Adaptive Recognition Hungary, Inc + Kiralyhago ter 8-9 + Budapest Europe 1126 + HU + +00-1D-1E (hex) KYUSHU TEN CO.,LTD +001D1E (base 16) KYUSHU TEN CO.,LTD + 2360 YUNOKIMOTOMACHI + SASEBO-City NAGASAKI Prefecture 857-0115 + JP + +00-1D-1D (hex) Inter-M Corporation +001D1D (base 16) Inter-M Corporation + 653-5 Banghak-Dong, Dobong-Ku + Seoul 132-846 + KR + +00-1D-0E (hex) Agapha Technology co., Ltd. +001D0E (base 16) Agapha Technology co., Ltd. + 9F No.121, Shingde Rd., + Sanchung City Taipei County 241 + TW + +00-1D-0A (hex) Davis Instruments, Inc. +001D0A (base 16) Davis Instruments, Inc. + 3465 Diablo Ave. + Hayward CA 94545 + US + +00-1D-67 (hex) AMEC +001D67 (base 16) AMEC + 9F,No.360,Ruel Guang Rd,Neihu + Taipei 114 + TW + +00-1D-7C (hex) ABE Elettronica S.p.A. +001D7C (base 16) ABE Elettronica S.p.A. + Via Leonardo da Vinci, 92 + CARAVAGGIO BG 24043 + IT + +00-1D-6D (hex) Confidant International LLC +001D6D (base 16) Confidant International LLC + 2530 Meridian Pkwy + Durham North Carolina 27713 + US + +00-1D-75 (hex) Radioscape PLC +001D75 (base 16) Radioscape PLC + 1 Albany Terrace + Regent's Park London NW1 4DS + GB + +00-1D-53 (hex) S&O Electronics (Malaysia) Sdn. Bhd. +001D53 (base 16) S&O Electronics (Malaysia) Sdn. Bhd. + Lot 202, Bakar Arang + 08000 Sungai Petani Kedah + MY + +00-1D-54 (hex) Sunnic Technology & Merchandise INC. +001D54 (base 16) Sunnic Technology & Merchandise INC. + 6F, NO.74,ZHOU-Z ST., + Taipei 114 + TW + +00-1D-5F (hex) OverSpeed SARL +001D5F (base 16) OverSpeed SARL + 15, allee du Bois Cailley + Le Thuit-Signol Normandie 27370 + FR + +00-1D-58 (hex) CQ Inc +001D58 (base 16) CQ Inc + 5F, No. 43, Lane 76, Rui Guang Road + Taipei 114 + TW + +00-1D-87 (hex) VigTech Labs Sdn Bhd +001D87 (base 16) VigTech Labs Sdn Bhd + 45-11 The Boulevard Mid Valley City + Kuala Lumpur Selangor 59200 + MY + +00-1D-2F (hex) QuantumVision Corporation +001D2F (base 16) QuantumVision Corporation + 335 Plantation Way + Roswell Ga 30075 + US + +00-1C-E5 (hex) MBS Electronic Systems GmbH +001CE5 (base 16) MBS Electronic Systems GmbH + Ringstrasse 3 + 82319 Starnberg Bavaria 82319 + DE + +00-1C-DD (hex) COWBELL ENGINEERING CO., LTD. +001CDD (base 16) COWBELL ENGINEERING CO., LTD. + 1739-1 Nagatoro + SAKU Nagano 385-0021 + JP + +00-1D-05 (hex) Eaton Corporation +001D05 (base 16) Eaton Corporation + 203 Cooper Circle + Peachtree City GA 30269 + US + +00-1C-C2 (hex) Part II Research, Inc. +001CC2 (base 16) Part II Research, Inc. + 4601 E. Airport Dr. + Ontario CA 91761 + US + +00-1C-BD (hex) Ezze Mobile Tech., Inc. +001CBD (base 16) Ezze Mobile Tech., Inc. + 3F, Bubmusa Bldg., 151-31 + Seoul 135-824 + KR + +00-1C-B8 (hex) CBC Co., Ltd +001CB8 (base 16) CBC Co., Ltd + 2-15-13, Tsukishima, Chuo-ku + Tokyo 104-0052 + JP + +00-1C-AC (hex) Qniq Technology Corp. +001CAC (base 16) Qniq Technology Corp. + 5F, No.133, Sec.4, Minsheng E. Rd., + Taipei 105 + TW + +00-1C-A5 (hex) Zygo Corporation +001CA5 (base 16) Zygo Corporation + 21 Laurel Brook Rd. + Middlefield CT 06455 + US + +00-1C-9D (hex) Liecthi AG +001C9D (base 16) Liecthi AG + 10 Unterholz Street + Kriegstetten Solothurn 4566 + CH + +00-1C-FF (hex) Napera Networks Inc +001CFF (base 16) Napera Networks Inc + 7683 SE 27th + Mercer Island WA 98040 + US + +00-1C-DC (hex) Custom Computer Services, Inc. +001CDC (base 16) Custom Computer Services, Inc. + 1020 Spring City Drive + Waukesha WI 53186 + US + +00-1C-D1 (hex) Waves Audio LTD +001CD1 (base 16) Waves Audio LTD + Azrilei Center 3, Triangle tower + Tel Aviv Central 67023 + IL + +00-1C-ED (hex) ENVIRONNEMENT SA +001CED (base 16) ENVIRONNEMENT SA + 111 bd. Robespierre + POISSY Yvelines 78300 + FR + +00-1C-BA (hex) VerScient, Inc. +001CBA (base 16) VerScient, Inc. + 7700 Equitable Drive + Eden Prairie MN 55344 + US + +00-1C-B0 (hex) Cisco Systems, Inc +001CB0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1C-4C (hex) Petrotest Instruments +001C4C (base 16) Petrotest Instruments + Ludwig-Erhard-Ring 13 + Dahlewitz BBG 15827 + DE + +00-1C-45 (hex) Chenbro Micom Co., Ltd. +001C45 (base 16) Chenbro Micom Co., Ltd. + 15Fl., No. 150, Jian Yi Road + Chung Ho City Taipei Hsien 235 + TW + +00-1C-3C (hex) Seon Design Inc. +001C3C (base 16) Seon Design Inc. + 111-3B Burbidge Street + Coquitlam BC V3K 7B2 + CA + +00-1C-57 (hex) Cisco Systems, Inc +001C57 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1C-5D (hex) Leica Microsystems +001C5D (base 16) Leica Microsystems + Lothbury House Cambridge Technopark + Cambridge CB5 8PB + GB + +00-1C-5E (hex) ASTON France +001C5E (base 16) ASTON France + 151 Avenue Gallieni + BAGNOLET ile de france 93177 + FR + +00-1C-55 (hex) Shenzhen Kaifa Technology Co. +001C55 (base 16) Shenzhen Kaifa Technology Co. + 7006 Caitian Road, Futian District, + Shenzhen Guangdong 518035 + CN + +00-1C-5B (hex) Chubb Electronic Security Systems Ltd +001C5B (base 16) Chubb Electronic Security Systems Ltd + Shadsworth Road + Blackburn Lancashire BB1 2PR + GB + +00-1C-44 (hex) Bosch Security Systems BV +001C44 (base 16) Bosch Security Systems BV + Kapittelweg 10 + 4827 HG Breda Brabant 4827 + NL + +00-1C-82 (hex) Genew Technologies +001C82 (base 16) Genew Technologies + 3A3 Building B1, Cyber-tech Zone, + Shenzhen Guangdong 518057 + CN + +00-1C-84 (hex) STL Solution Co.,Ltd. +001C84 (base 16) STL Solution Co.,Ltd. + #710, World Meridian Venture Center I + Seoul 152781 + KR + +00-1C-79 (hex) Cohesive Financial Technologies LLC +001C79 (base 16) Cohesive Financial Technologies LLC + 200 South Wacker Dr. + Chicago IL 60606 + US + +00-1C-64 (hex) Landis+Gyr +001C64 (base 16) Landis+Gyr + 30000 Mill Creek Ave. Suite 100 + Alpharetta GA 30022 + US + +00-1C-31 (hex) Mobile XP Technology Co., LTD +001C31 (base 16) Mobile XP Technology Co., LTD + Room No.2506,Tri-tower C building,No.66 Zhongguancun East Road,Haidian District + Beijing 100080 + CN + +00-1C-8B (hex) MJ Innovations Ltd. +001C8B (base 16) MJ Innovations Ltd. + 333 Wyecroft Road + Oakville Ontario L6K 2H2 + CA + +00-1C-6D (hex) KYOHRITSU ELECTRONIC INDUSTRY CO., LTD. +001C6D (base 16) KYOHRITSU ELECTRONIC INDUSTRY CO., LTD. + 2-5-1, NIPPONBASHI-NISHI, + OSAKA 556-0004 + JP + +00-1C-96 (hex) Linkwise Technology Pte Ltd +001C96 (base 16) Linkwise Technology Pte Ltd + Blk 3, Ang Mo Kio Industrial Park 2A + 568050 + SG + +00-1C-29 (hex) CORE DIGITAL ELECTRONICS CO., LTD +001C29 (base 16) CORE DIGITAL ELECTRONICS CO., LTD + 1006# 102 CHUNUITECHNOPARK 200-1 + BUCHEON-CITY GYUNGGI-DO 420-857 + KR + +00-1C-24 (hex) Formosa Wireless Systems Corp. +001C24 (base 16) Formosa Wireless Systems Corp. + No. 408, Guandong Rd., + HsinChu City 300 + TW + +00-1C-20 (hex) CLB Benelux +001C20 (base 16) CLB Benelux + Ramgatseweg 17 + Raamsdonksveer NBR 4941 VN + NL + +00-1C-1C (hex) Center Communication Systems GmbH +001C1C (base 16) Center Communication Systems GmbH + Ignaz-Koeck-Strasse 19 + Vienna A-1210 + AT + +00-1B-DA (hex) UTStarcom Inc +001BDA (base 16) UTStarcom Inc + 1275 Harbor Bay PKWY + Alameda CA 94502 + US + +00-1B-D1 (hex) SOGESTMATIC +001BD1 (base 16) SOGESTMATIC + 409 Route de la Gare + CHATEAUNEUF DE GADAGNE PACA 84470 + FR + +00-1C-00 (hex) Entry Point, LLC +001C00 (base 16) Entry Point, LLC + 735 Robins + Idaho Falls Idaho 83401 + US + +00-1B-FD (hex) Dignsys Inc. +001BFD (base 16) Dignsys Inc. + 14F, Digital Empire Bldg., B-1408 + Suwon Gyeonggi-do 443-813 + KR + +00-1B-D6 (hex) Kelvin Hughes Ltd +001BD6 (base 16) Kelvin Hughes Ltd + New North Road + Ilford Essex IG6 2UR + GB + +00-1B-CF (hex) Dataupia Corporation +001BCF (base 16) Dataupia Corporation + One Alewife Center + Cambridge MA 02140 + US + +00-1B-CB (hex) PEMPEK SYSTEMS PTY LTD +001BCB (base 16) PEMPEK SYSTEMS PTY LTD + UNIT 3 / 13 HOYLE AVENUE + CASTLE HILL NSW 2154 + AU + +00-1B-F5 (hex) Tellink Sistemas de Telecomunicación S.L. +001BF5 (base 16) Tellink Sistemas de Telecomunicación S.L. + C/ María Tubau Nº 5 Bajo B + Madrid 28050 + ES + +00-1B-E6 (hex) VR AG +001BE6 (base 16) VR AG + Rütistrasse 18 + Schlieren CH-8952 + CH + +00-1B-E2 (hex) AhnLab,Inc. +001BE2 (base 16) AhnLab,Inc. + 6th Fl, CCMM Bldg, 12 Yeouido-dong + Seoul 150869 + KR + +00-1B-E0 (hex) TELENOT ELECTRONIC GmbH +001BE0 (base 16) TELENOT ELECTRONIC GmbH + Wiesentalstraße 42 + Aalen Baden-Württemberg 73434 + DE + +00-1C-34 (hex) HUEY CHIAO INTERNATIONAL CO., LTD. +001C34 (base 16) HUEY CHIAO INTERNATIONAL CO., LTD. + 5F, NO. 649-1, + HSIN CHUANG CITY TAIPEI 242 + TW + +00-1C-36 (hex) iNEWiT NV +001C36 (base 16) iNEWiT NV + Schaliënhoevedreef 20D + Mechelen Antwerp 2800 + BE + +00-1C-15 (hex) iPhotonix LLC +001C15 (base 16) iPhotonix LLC + 2600 N Central Expressway + Richardson Texas 75080 + US + +00-1C-07 (hex) Cwlinux Limited +001C07 (base 16) Cwlinux Limited + Unit 138, 13/F, Weswick Commercial Building, + Wan Chai + HK + +00-1B-A3 (hex) Flexit Group GmbH +001BA3 (base 16) Flexit Group GmbH + Bräuhausstraße 14 + Salzburg Salzburg 5020 + AT + +00-1B-9F (hex) Calyptech Pty Ltd +001B9F (base 16) Calyptech Pty Ltd + 5/486 Lower Heidelberg Road + Heidelberg Victoria 3084 + AU + +00-1B-9A (hex) Apollo Fire Detectors Ltd +001B9A (base 16) Apollo Fire Detectors Ltd + 36 Brookside Road + Havant Hampshire P09 1JR + GB + +00-1B-BD (hex) FMC Kongsberg Subsea AS +001BBD (base 16) FMC Kongsberg Subsea AS + Kirkegaardsveien 45 + Kongsberg Buskerud 3601 + NO + +00-1B-BE (hex) ICOP Digital +001BBE (base 16) ICOP Digital + 16801 W. 116th St. + Lenexa KS 66219 + US + +00-1B-B3 (hex) Condalo GmbH +001BB3 (base 16) Condalo GmbH + Kohlstatt 3 + Lichtenau Bavaria 86706 + DE + +00-1B-B7 (hex) Alta Heights Technology Corp. +001BB7 (base 16) Alta Heights Technology Corp. + 108 Alta Heights Court + Los Gatos California 95030 + US + +00-1B-99 (hex) KS System GmbH +001B99 (base 16) KS System GmbH + Alexanderstraße 37 + Muelheim NRW 45472 + DE + +00-1B-8F (hex) Cisco Systems, Inc +001B8F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1B-8C (hex) JMicron Technology Corp. +001B8C (base 16) JMicron Technology Corp. + 1F, No.13, Innovation Road 1 + Hsinchu 300 + TW + +00-1B-91 (hex) EFKON AG +001B91 (base 16) EFKON AG + Dietrich-Keller-Strasse 20 + 8074 Raaba + AT + +00-1B-82 (hex) Taiwan Semiconductor Co., Ltd. +001B82 (base 16) Taiwan Semiconductor Co., Ltd. + 11F, No. 205, Sec. 3, Beishin Rd, + Shindian Taipei 231 + TW + +00-1B-89 (hex) EMZA Visual Sense Ltd. +001B89 (base 16) EMZA Visual Sense Ltd. + 20 Ha'ta'as St., Beith Hapamon + Kfar Saba 44425 + IL + +00-1B-8B (hex) NEC Platforms, Ltd. +001B8B (base 16) NEC Platforms, Ltd. + 800 Shimomata + Kakegawa Shizuoka 436-8501 + JP + +00-1B-AC (hex) Curtiss Wright Controls Embedded Computing +001BAC (base 16) Curtiss Wright Controls Embedded Computing + 10201 Wateridge Circle + San Diego CA 92121 + US + +00-1B-6A (hex) Powerwave Technologies Sweden AB +001B6A (base 16) Powerwave Technologies Sweden AB + 164 26 + Knarrarnäsgatan 7, Kista + SE + +00-1B-67 (hex) Cisco Systems Inc +001B67 (base 16) Cisco Systems Inc + The Stella Building + Swindon Wiltshire SN5 6NX + GB + +00-1B-7B (hex) The Tintometer Ltd +001B7B (base 16) The Tintometer Ltd + Solar Way + Amesbury Wiltshire SP4 7SZ + GB + +00-1B-75 (hex) Hypermedia Systems +001B75 (base 16) Hypermedia Systems + 2B Bergman St. + Rehovot 76705 + IL + +00-1B-27 (hex) Merlin CSI +001B27 (base 16) Merlin CSI + 12625 Danielson Court + Poway CA 92064 + US + +00-1B-1B (hex) Siemens AG, +001B1B (base 16) Siemens AG, + I IA SC MF-K PE 3 + 76187 Karlsruhe Baden Wuerttemberg + DE + +00-1B-1F (hex) DELTA - Danish Electronics, Light & Acoustics +001B1F (base 16) DELTA - Danish Electronics, Light & Acoustics + Venlighedsvej 4 + Hørsholm DK-2970 + DK + +00-1B-57 (hex) SEMINDIA SYSTEMS PRIVATE LIMITED +001B57 (base 16) SEMINDIA SYSTEMS PRIVATE LIMITED + #1106/9,A.M.Industrial Estate,Garvebhai palya, + BANGALORE KARNATAKA 560068 + IN + +00-1B-55 (hex) Hurco Automation Ltd. +001B55 (base 16) Hurco Automation Ltd. + 6F, No. 31, Shintai Rd. + Jubei City, Hsinchu Hsien 30244 + TW + +00-1B-53 (hex) Cisco Systems, Inc +001B53 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1B-49 (hex) Roberts Radio limited +001B49 (base 16) Roberts Radio limited + Swinton Works + Mexborough South Yorkshire S64 8AJ + GB + +00-1B-0E (hex) InoTec GmbH Organisationssysteme +001B0E (base 16) InoTec GmbH Organisationssysteme + Biedrichstrasse 11 + Woelfersheim Hessen D-61200 + DE + +00-1B-04 (hex) Affinity International S.p.a +001B04 (base 16) Affinity International S.p.a + C.so Savona 51 + Villastellone I10029 + IT + +00-1B-06 (hex) Ateliers R. LAUMONIER +001B06 (base 16) Ateliers R. LAUMONIER + Ateliers R. LAUMONIER + Nesles-la-Vallée Val d'Oise 95690 + FR + +00-1B-31 (hex) Neural Image. Co. Ltd. +001B31 (base 16) Neural Image. Co. Ltd. + A307, CASI, Osaka Univ. + Suita city Osaka 565-0871 + JP + +00-1B-29 (hex) Avantis.Co.,Ltd +001B29 (base 16) Avantis.Co.,Ltd + 502 SEOIL BLDG. + SEOUL 132-872 + KR + +00-1B-2B (hex) Cisco Systems, Inc +001B2B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1B-28 (hex) POLYGON, JSC +001B28 (base 16) POLYGON, JSC + 37/1, Karl Marx str., floor 5 + Ufa Bashkortostan 450077 + RU + +00-1B-43 (hex) Beijing DG Telecommunications equipment Co.,Ltd +001B43 (base 16) Beijing DG Telecommunications equipment Co.,Ltd + No.5 Jiangtai Road, Chaoyang District + Beijing 100016 + CN + +00-1B-3C (hex) Software Technologies Group,Inc. +001B3C (base 16) Software Technologies Group,Inc. + 10330 W. Roosevelt Road + Weschester IL 60154 + US + +00-1B-3D (hex) EuroTel Spa +001B3D (base 16) EuroTel Spa + viale Martiri della Liberta,4 + Lissone Milan 20035 + IT + +00-1B-66 (hex) Sennheiser electronic GmbH & Co. KG +001B66 (base 16) Sennheiser electronic GmbH & Co. KG + Am Labor 1 + Wedemark Niedersachsen 30900 + DE + +00-1B-60 (hex) NAVIGON AG +001B60 (base 16) NAVIGON AG + Berliner Platz 11 + Wuerzburg Bavaria 97080 + DE + +00-1B-05 (hex) YMC AG +001B05 (base 16) YMC AG + Sonnenstrasse 4 + Kreuzlingen Thurgau 8280 + CH + +00-1A-FF (hex) Wizyoung Tech. +001AFF (base 16) Wizyoung Tech. + 9F, No. 25, Sec. 1, Nanjing E. Rd. + Taipei 104 + TW + +00-1B-00 (hex) Neopost Technologies +001B00 (base 16) Neopost Technologies + 113 rue Jean-Marin Naudin + Bagneux 92220 + FR + +00-1B-4E (hex) Navman New Zealand +001B4E (base 16) Navman New Zealand + 7-21 Kawana Street + Auckland 0627 + NZ + +00-1B-16 (hex) Celtro Ltd. +001B16 (base 16) Celtro Ltd. + Azorim Business Park + Petach Tikva 49527 + IL + +00-1A-E6 (hex) Atlanta Advanced Communications Holdings Limited +001AE6 (base 16) Atlanta Advanced Communications Holdings Limited + 1900 West Oak Circle, Marietta + Atlanta Georgia 30062 + US + +00-1A-D9 (hex) International Broadband Electric Communications, Inc. +001AD9 (base 16) International Broadband Electric Communications, Inc. + 285 Dunlop Blvd. SW + Huntsville AL 35824 + US + +00-1A-C8 (hex) ISL (Instrumentation Scientifique de Laboratoire) +001AC8 (base 16) ISL (Instrumentation Scientifique de Laboratoire) + Impasse des 4 vents + VERSON CALVADOS 14790 + FR + +00-1A-AB (hex) eWings s.r.l. +001AAB (base 16) eWings s.r.l. + via S. Quasimodo 46 + Castel Maggiore Bologna 40013 + IT + +00-1A-AC (hex) Corelatus AB +001AAC (base 16) Corelatus AB + Tegnergatan 37 + Stockholm 11161 + SE + +00-1A-AF (hex) BLUSENS TECHNOLOGY +001AAF (base 16) BLUSENS TECHNOLOGY + EDIFICIO CNL,- AV. + 15707 - SANTIAGO DE COMPOSTELA A Coruña + ES + +00-1A-B0 (hex) Signal Networks Pvt. Ltd., +001AB0 (base 16) Signal Networks Pvt. Ltd., + No.12, Kalpataru Apartments, + Bangalore Karnataka 560001 + IN + +00-1A-A1 (hex) Cisco Systems, Inc +001AA1 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-1A-C6 (hex) Micro Control Designs +001AC6 (base 16) Micro Control Designs + 17490 Caribou Dr + Monument Co. 80132 + US + +00-1A-F2 (hex) Dynavisions Schweiz AG +001AF2 (base 16) Dynavisions Schweiz AG + Freisinger Landstraße 21 + D-80939 Muenchen + DE + +00-1A-82 (hex) PROBA Building Automation Co.,LTD +001A82 (base 16) PROBA Building Automation Co.,LTD + Penghuan Building 501, Shangdi East Road #1, Haidian District, + Beijing 100085 + CN + +00-1A-7C (hex) Hirschmann Multimedia B.V. +001A7C (base 16) Hirschmann Multimedia B.V. + Pampuslaan 170 + Weesp Noord-Holland 1382 JS + NL + +00-1A-7A (hex) Lismore Instruments Limited +001A7A (base 16) Lismore Instruments Limited + Unit 2 Tristar Centre, Star Road + Horsham West Sussex RH13 8RA + GB + +00-1A-78 (hex) ubtos +001A78 (base 16) ubtos + Rn.213, Woolim Lions Valley, #680 + seoul Gasan-dong 153-803 + KR + +00-1A-76 (hex) SDT information Technology Co.,LTD. +001A76 (base 16) SDT information Technology Co.,LTD. + Samil B/B 2F, 5-63 Hyochang-dong + Seoul 140-896 + KR + +00-1A-70 (hex) Cisco-Linksys, LLC +001A70 (base 16) Cisco-Linksys, LLC + 121 Theory Drive + Irvine California 92612 + US + +00-1A-61 (hex) PacStar Corp. +001A61 (base 16) PacStar Corp. + 15055 SW Sequoia Pkwy, Suite 100 + Portland OR 97006 + US + +00-1A-62 (hex) Data Robotics, Incorporated +001A62 (base 16) Data Robotics, Incorporated + 1881 Landings Dr + Mountain View CA 94043 + US + +00-1A-65 (hex) Seluxit +001A65 (base 16) Seluxit + Nyhavnsgade 9, 2.sal + Aalborg Nord Jylland 9000 + DK + +00-1A-54 (hex) Hip Shing Electronics Ltd. +001A54 (base 16) Hip Shing Electronics Ltd. + Unit 1/2/3, 20/F, New Treasure Center + + HK + +00-1A-42 (hex) Techcity Technology co., Ltd. +001A42 (base 16) Techcity Technology co., Ltd. + 4F, No. 4, Alley 1, Szu Wei Lane, Chung Cheng Rd., + Hsin Tein City Taipei Hsien 231 + TW + +00-1A-50 (hex) PheeNet Technology Corp. +001A50 (base 16) PheeNet Technology Corp. + Rm. 3, 20F, No. 79, Sec. 1 Hsin Tai Wu Rd. + Hsi-Chih New-Taipei City 221 + TW + +00-1A-53 (hex) Zylaya +001A53 (base 16) Zylaya + 444 N. Frederick Ave. + Gaithersburg MD 20877 + US + +00-1A-4C (hex) Crossbow Technology, Inc +001A4C (base 16) Crossbow Technology, Inc + 4145 N. First Street + San Jose CA 95134 + US + +00-1A-1A (hex) Gentex Corporation/Electro-Acoustic Products +001A1A (base 16) Gentex Corporation/Electro-Acoustic Products + 2456 Brown Avenue + Manchester NH 03103 + US + +00-1A-12 (hex) Essilor +001A12 (base 16) Essilor + 64 Bis Avenue Aubert + 94300 Vincennes + FR + +00-1A-7D (hex) cyber-blue(HK)Ltd +001A7D (base 16) cyber-blue(HK)Ltd + Room 1408 block C stars Plaza HongLiRoad,FuTian District + Shenzhen GuangDong 518028 + CN + +00-1A-60 (hex) Wave Electronics Co.,Ltd. +001A60 (base 16) Wave Electronics Co.,Ltd. + 3th Fl.,DaeSan Plaza B/D,Guun-Dong, 12-1,Gwonseon-Gu + Suwon-si Kyeonggi-Do 441-814 + KR + +00-1A-56 (hex) ViewTel Co,. Ltd. +001A56 (base 16) ViewTel Co,. Ltd. + #B-502,Bundang Techno Park 148 + BunDang-Ku, SeongNam-Si GyeongGi-Do 463-760 + KR + +00-19-F3 (hex) Cetis, Inc +0019F3 (base 16) Cetis, Inc + 5025 Galley Rd + Colorado Springs CO 80915 + US + +00-19-F5 (hex) Imagination Technologies Ltd +0019F5 (base 16) Imagination Technologies Ltd + Zurich House + Leeds West Yorkshire LS11 5DB + GB + +00-19-EF (hex) SHENZHEN LINNKING ELECTRONICS CO.,LTD +0019EF (base 16) SHENZHEN LINNKING ELECTRONICS CO.,LTD + Room 901,B Block,Qinghua Information Center Hi-tec park North District,Nanshan District,Shenzhen + shenzhen guangdong 518057 + CN + +00-19-F7 (hex) Onset Computer Corporation +0019F7 (base 16) Onset Computer Corporation + P.O. Box 3450 + Pocasset MA 02559 + US + +00-19-EE (hex) CARLO GAVAZZI CONTROLS SPA-Controls Division +0019EE (base 16) CARLO GAVAZZI CONTROLS SPA-Controls Division + Via Safforze 8 + BELLUNO BL I-32100 + IT + +00-19-BF (hex) Citiway technology Co.,ltd +0019BF (base 16) Citiway technology Co.,ltd + No.2 Building,Jia 32,Beiheyan Avenue,East City + Peijing 100006 + CN + +00-19-B6 (hex) Euro Emme s.r.l. +0019B6 (base 16) Euro Emme s.r.l. + Via Belvedere, 24 + Galliate Lombardo Varese 21020 + IT + +00-19-EB (hex) Pyronix Ltd +0019EB (base 16) Pyronix Ltd + Braithwell Way + Rotherham South Yorkshire S66 8QY + GB + +00-19-E7 (hex) Cisco Systems, Inc +0019E7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-E9 (hex) S-Information Technolgy, Co., Ltd. +0019E9 (base 16) S-Information Technolgy, Co., Ltd. + Sungwoo Bldg, 717-3 Suseo-dong, + Seoul 135-884 + KR + +00-19-DA (hex) Welltrans O&E Technology Co. , Ltd. +0019DA (base 16) Welltrans O&E Technology Co. , Ltd. + the 3rd Floor, building C-D, Hi-tech Digital Harbor, Guandong Industrial Park + Wuhan Hubei 430074 + CN + +00-1A-14 (hex) Xin Hua Control Engineering Co.,Ltd. +001A14 (base 16) Xin Hua Control Engineering Co.,Ltd. + 160 Wenjing Rd., Minhang + Shanghai 2000245 + CN + +00-1A-10 (hex) LUCENT TRANS ELECTRONICS CO.,LTD +001A10 (base 16) LUCENT TRANS ELECTRONICS CO.,LTD + 9F-1,No.16,Chien Pah Rd. + Chung Ho Taipei 235 + TW + +00-1A-0C (hex) Swe-Dish Satellite Systems AB +001A0C (base 16) Swe-Dish Satellite Systems AB + Torggatan 15 + Solna Stockholm SE-171 06 + SE + +00-19-DC (hex) ENENSYS Technologies +0019DC (base 16) ENENSYS Technologies + Le Germanium + RENNES Brittany 35700 + FR + +00-19-D0 (hex) Cathexis +0019D0 (base 16) Cathexis + PO Box 1091 + Durban KwaZulu Natal 4320 + ZA + +00-19-D6 (hex) LS Cable and System Ltd. +0019D6 (base 16) LS Cable and System Ltd. + 12F LS Tower, 1026-6, Hogey-dong + Anyang-si Gyeonggi-do 431-080 + KR + +00-19-D7 (hex) FORTUNETEK CO., LTD +0019D7 (base 16) FORTUNETEK CO., LTD + 12F, No. 75, Sec 1, Chongqing S. Rd., + Taipei 100 + TW + +00-1A-02 (hex) SECURE CARE PRODUCTS, INC +001A02 (base 16) SECURE CARE PRODUCTS, INC + 39 CHENELL DRIVE + CONCORD NH 03301 + US + +00-19-F8 (hex) Embedded Systems Design, Inc. +0019F8 (base 16) Embedded Systems Design, Inc. + 6810 Deerpath Road + Elkridge MD 21075 + US + +00-1A-07 (hex) Arecont Vision +001A07 (base 16) Arecont Vision + 2400 N. Lincoln Ave + Altadena CA 91001 + US + +00-1A-08 (hex) Simoco Ltd. +001A08 (base 16) Simoco Ltd. + Field House + Derby DE1 1NH + GB + +00-1A-04 (hex) Interay Solutions BV +001A04 (base 16) Interay Solutions BV + Mr. W.M. Oppedijk van Veenweg 8 + BURGUM Friesland 9251 GA + NL + +00-19-C9 (hex) S&C ELECTRIC COMPANY +0019C9 (base 16) S&C ELECTRIC COMPANY + 1135 ATLANTIC AVE + ALAMEDA CA 94501 + US + +00-19-B5 (hex) Famar Fueguina S.A. +0019B5 (base 16) Famar Fueguina S.A. + Rodney 70 + Buenos Aires 1427 + AR + +00-19-B8 (hex) Boundary Devices +0019B8 (base 16) Boundary Devices + 7200 W. Oakland + Chandler AZ 85226 + US + +00-19-5D (hex) ShenZhen XinHuaTong Opto Electronics Co.,Ltd +00195D (base 16) ShenZhen XinHuaTong Opto Electronics Co.,Ltd + 5F,BaodaZhou,Shancheng Industrial Zone,BaoAn District + ShenZhen GuangDong 518108 + CN + +00-19-53 (hex) Chainleader Communications Corp. +001953 (base 16) Chainleader Communications Corp. + 5F, No. 400, Sec. 2 Bade Rd., + Taipei 105 + TW + +00-19-55 (hex) Cisco Systems, Inc +001955 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-19-59 (hex) Staccato Communications Inc. +001959 (base 16) Staccato Communications Inc. + 6195 Lusk Blvd. + San Diego CA 92121 + US + +00-19-4D (hex) Avago Technologies Sdn Bhd +00194D (base 16) Avago Technologies Sdn Bhd + Bayan Lepas Free Industrial Zone + Bayan Lepas Penang 11900 + MY + +00-19-4E (hex) Ultra Electronics - TCS (Tactical Communication Systems) +00194E (base 16) Ultra Electronics - TCS (Tactical Communication Systems) + 5990 Cote De Liesse + TMR Quebec H4T 1V7 + CA + +00-19-AC (hex) GSP SYSTEMS Inc. +0019AC (base 16) GSP SYSTEMS Inc. + 13FL, 101 Dong, Chunui Techno Park 1, + Bucheon-City Gyeonggi-Do 420-857 + KR + +00-19-B0 (hex) HanYang System +0019B0 (base 16) HanYang System + 701Ho, Kofomo Techno Center II, 1289-5 + Shihung-Shi Kyunggi-Do 429-850 + KR + +00-19-95 (hex) Jurong Hi-Tech (Suzhou)Co.ltd +001995 (base 16) Jurong Hi-Tech (Suzhou)Co.ltd + 275,Xing Long Street, Suzhou Indudtrial Park + Suzhou Jiang Su 215021 + CN + +00-19-9A (hex) EDO-EVI +00199A (base 16) EDO-EVI + 7065 Columbia Gateway Dr. + Columbia MD 21046 + US + +00-19-94 (hex) Jorjin Technologies Inc. +001994 (base 16) Jorjin Technologies Inc. + 5F, No.28, Lane141, Sing-ai Rd. + Taipei 114 + TW + +00-19-7C (hex) Riedel Communications GmbH +00197C (base 16) Riedel Communications GmbH + Uellendahler Str. 353 + Wuppertal NRW 42109 + DE + +00-19-A0 (hex) NIHON DATA SYSTENS, INC. +0019A0 (base 16) NIHON DATA SYSTENS, INC. + 6-9, Koyo-cho naka + Kobe-shi Hyogo 658-0032 + JP + +00-19-91 (hex) avinfo +001991 (base 16) avinfo + Jiahuiyuan 703,Huaao Center,31# Zizhuyuan Road, + Beijing 100089 + CN + +00-19-8C (hex) iXSea +00198C (base 16) iXSea + 55 av auguste Renoir + Marly le Roi 78160 + FR + +00-19-62 (hex) Commerciant, LP +001962 (base 16) Commerciant, LP + 2901 Wilcrest + Houston Texas 77042 + US + +00-19-6F (hex) SensoPart GmbH +00196F (base 16) SensoPart GmbH + Am Wiedenbach 1 + Wieden Baden-Württemberg D-79695 + DE + +00-18-DD (hex) Silicondust Engineering Ltd +0018DD (base 16) Silicondust Engineering Ltd + 38 Lillington Road + Auckland + NZ + +00-18-DF (hex) The Morey Corporation +0018DF (base 16) The Morey Corporation + 100 Morey Drive + Woodridge IL 60517 + US + +00-18-E1 (hex) Verkerk Service Systemen +0018E1 (base 16) Verkerk Service Systemen + Molenvliet 1 + Zwijndrecht Zuid-Holland NL-3335LH + NL + +00-18-DA (hex) Würth Elektronik eiSos GmbH & Co. KG +0018DA (base 16) Würth Elektronik eiSos GmbH & Co. KG + Max-Eyth-Straße 1 + Waldenburg 74638 + DE + +00-18-D5 (hex) REIGNCOM +0018D5 (base 16) REIGNCOM + 14F Kamco Yanjae Tower, 949-3 + Seoul 135-739 + KR + +00-18-E7 (hex) Cameo Communications, INC. +0018E7 (base 16) Cameo Communications, INC. + NO.42, Sec. 6, Mincyuan E. Rd. + Taipei 114 + TW + +00-18-E4 (hex) YIGUANG +0018E4 (base 16) YIGUANG + 3/FL.Industry zone,Fuxinlin,Hangcheng,Xixiang,Baoan + Shenzhen Guangdong 518126 + CN + +00-18-E5 (hex) Adhoco AG +0018E5 (base 16) Adhoco AG + Technopark + Winterthur ZH CH-8406 + CH + +00-19-0A (hex) HASWARE INC. +00190A (base 16) HASWARE INC. + 4-12-3 HIGASHI + KUNITACHI TOKYO 186-0002 + JP + +00-19-23 (hex) Phonex Korea Co., LTD. +001923 (base 16) Phonex Korea Co., LTD. + 33-3, Geoyeo-Dong + Seoul Songpa-Gu 138-814 + KR + +00-19-1C (hex) Sensicast Systems +00191C (base 16) Sensicast Systems + 200 Reservoir St + Needham MA 02494 + US + +00-19-28 (hex) Siemens AG, Transportation Systems +001928 (base 16) Siemens AG, Transportation Systems + Ackerstraße 22 + Braunschweig 38126 + DE + +00-19-15 (hex) TECOM Co., Ltd. +001915 (base 16) TECOM Co., Ltd. + 23 R&D Road 2 Science Based Industrial Park + Hsin-Chu 300 + TW + +00-19-1B (hex) Sputnik Engineering AG +00191B (base 16) Sputnik Engineering AG + Höheweg 85 + Biel-Bienne BE 2502 + CH + +00-19-09 (hex) DEVI - Danfoss A/S +001909 (base 16) DEVI - Danfoss A/S + Ulvehavevej 61 + Vejle 7100 + DK + +00-19-33 (hex) Strix Systems, Inc. +001933 (base 16) Strix Systems, Inc. + 26610 Agoura Road + Calabasas CA 91302 + US + +00-19-04 (hex) WB Electronics Sp. z o.o. +001904 (base 16) WB Electronics Sp. z o.o. + ul. Poznanska 129/133 + Ozarow Mazowiecki Mazowieckie 05-850 + PL + +00-19-34 (hex) TRENDON TOUCH TECHNOLOGY CORP. +001934 (base 16) TRENDON TOUCH TECHNOLOGY CORP. + 2F No.5, Alley 22, Lane 513, Rueiguang Rd., Neihu + Taipei City 114 + TW + +00-19-0D (hex) IEEE 1394c +00190D (base 16) IEEE 1394c + c/o 1394 Trade Association + Southlake TX 76092 + US + +00-18-81 (hex) Buyang Electronics Industrial Co., Ltd +001881 (base 16) Buyang Electronics Industrial Co., Ltd + 434-140, Oryu-Dong + Incheon 404-300 + KR + +00-18-76 (hex) WowWee Ltd. +001876 (base 16) WowWee Ltd. + 92 Granville Rd. Suite 301A-C + T.S.T. East Kowloon + HK + +00-18-7A (hex) Wiremold +00187A (base 16) Wiremold + 60 Woodlawn St. + West Hartford CT 06110 + US + +00-18-6C (hex) Neonode AB +00186C (base 16) Neonode AB + Biblioteksgatan 11, 1st floor + Stockholm S-111 46 + SE + +00-18-73 (hex) Cisco Systems, Inc +001873 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-18-5F (hex) TAC Inc. +00185F (base 16) TAC Inc. + 66 Nishiishigatsubocho Nishinanajyo Shimogyoku + Kyoto 600-8896 + JP + +00-18-D4 (hex) Unified Display Interface SIG +0018D4 (base 16) Unified Display Interface SIG + 15201 SW Greenbrier Road + Beaverton Oregon 97006 + US + +00-18-A7 (hex) Yoggie Security Systems LTD. +0018A7 (base 16) Yoggie Security Systems LTD. + P.P.Box 156 + Beth Halevy 42870 + IL + +00-18-A2 (hex) XIP Technology AB +0018A2 (base 16) XIP Technology AB + PO Box 437 + Jönköping Sweden SE- 551 16 + SE + +00-18-9C (hex) Weldex Corporation +00189C (base 16) Weldex Corporation + 6751 Katella Avenue + Cypress CA 90630 + US + +00-18-9A (hex) HANA Micron Inc. +00189A (base 16) HANA Micron Inc. + #95-1 Wonnam-Li, Umbong-Myeon + Asan-City Chung-Nam 336-864 + KR + +00-18-64 (hex) Eaton Corporation +001864 (base 16) Eaton Corporation + 730, rue Commerciale + St-Jean-Chrysostome QC G6Z 2C5 + CA + +00-18-66 (hex) Leutron Vision +001866 (base 16) Leutron Vision + Industriestrasse 57 + Glattbrugg ZH 8152 + CH + +00-18-60 (hex) SIM Technology Group Shanghai Simcom Ltd., +001860 (base 16) SIM Technology Group Shanghai Simcom Ltd., + SIM Technology building, + Shanghai 200233 + CN + +00-18-97 (hex) JESS-LINK PRODUCTS Co., LTD +001897 (base 16) JESS-LINK PRODUCTS Co., LTD + 9F, No. 176, Jian-Yi Rd., Chung Ho City + Taipei County 235 + TW + +00-18-9E (hex) OMNIKEY GmbH. +00189E (base 16) OMNIKEY GmbH. + Ferihumerstrasse 13 + Linz Upperaustria 4040 + AT + +00-18-A9 (hex) Ethernet Direct Corporation +0018A9 (base 16) Ethernet Direct Corporation + 19F,No.345 Chung Ho Road, Yung Ho City + Taipei 234 + TW + +00-18-A8 (hex) AnNeal Technology Inc. +0018A8 (base 16) AnNeal Technology Inc. + Room 106, No. 47, Science Park Rd. II + Hsinchu 300 + TW + +00-18-C2 (hex) Firetide, Inc +0018C2 (base 16) Firetide, Inc + 16795 Lark Av, Suite 200 + Los Gatos CA 95032 + US + +00-18-3E (hex) Digilent, Inc +00183E (base 16) Digilent, Inc + 215 E. Main St. + Pullman WA 99163 + US + +00-18-42 (hex) Nokia Danmark A/S +001842 (base 16) Nokia Danmark A/S + Frederikskaj + Copenhagen V DK-1790 + DK + +00-18-40 (hex) 3 Phoenix, Inc. +001840 (base 16) 3 Phoenix, Inc. + 14585 Avion Pkway + Chantilly Virginia 20151 + US + +00-18-44 (hex) Heads Up Technologies, Inc. +001844 (base 16) Heads Up Technologies, Inc. + 2033 Chennault Drive, Suite 100 + Carrollton Texas 75006-5119 + US + +00-18-21 (hex) SINDORICOH +001821 (base 16) SINDORICOH + 277-22, 2ga, Sungsu-dong, Sungdong-gu, + Seoul 133-120 + KR + +00-18-23 (hex) Delta Electronics, Inc. +001823 (base 16) Delta Electronics, Inc. + 186 Ruey Kuang Road, Neihu, + Taipei 114 + TW + +00-18-15 (hex) GZ Technologies, Inc. +001815 (base 16) GZ Technologies, Inc. + Room 1, 5F., No.94, Baojhong Rd. + Taipei 231 + TW + +00-18-57 (hex) Unilever R&D +001857 (base 16) Unilever R&D + Bldg. 50 + Bedford Bedfordshire MK44 1LQ + GB + +00-18-53 (hex) Atera Networks LTD. +001853 (base 16) Atera Networks LTD. + 31, Habarzel St. + Tel-Aviv 69710 + IL + +00-18-59 (hex) Strawberry Linux Co.,Ltd. +001859 (base 16) Strawberry Linux Co.,Ltd. + 1-28-8-204 Higashiayase + Adachiku Tokyo 120-0004 + JP + +00-18-4F (hex) 8 Ways Technology Corp. +00184F (base 16) 8 Ways Technology Corp. + 2F-1, No. 216, Sec. 3, Roosevelt Rd. + Taipei 231 + TW + +00-18-06 (hex) Hokkei Industries Co., Ltd. +001806 (base 16) Hokkei Industries Co., Ltd. + Imahira 432 + Hakusan Ishikawa 924-0827 + JP + +00-18-18 (hex) Cisco Systems, Inc +001818 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-18-1A (hex) AVerMedia Information Inc. +00181A (base 16) AVerMedia Information Inc. + 5F., No. 135, Jian 1st Rd., + New Taipei City 235 + TW + +00-18-16 (hex) Ubixon Co., Ltd. +001816 (base 16) Ubixon Co., Ltd. + Cheongdong Building 2F + Seoul 137-070 + KR + +00-18-2B (hex) Softier +00182B (base 16) Softier + Tidhar 3 + Ra'anana none 43665 + IL + +00-18-29 (hex) Gatsometer +001829 (base 16) Gatsometer + Claes Tillyweg 2 + Haarlem Noord-Holland 2031 CW + NL + +00-18-38 (hex) PanAccess Communications,Inc. +001838 (base 16) PanAccess Communications,Inc. + Floor 8,Tower B,Global Trade Center,36 Beisanhuandonglu,Dongcheng District + Beijing 100013 + CN + +00-17-F0 (hex) SZCOM Broadband Network Technology Co.,Ltd +0017F0 (base 16) SZCOM Broadband Network Technology Co.,Ltd + Room 602 No.8 Building ,Shenzhen Software Park, + Shenzhen Guangdong 518057 + CN + +00-17-F1 (hex) Renu Electronics Pvt Ltd +0017F1 (base 16) Renu Electronics Pvt Ltd + Sr No 2/6, Baner Road, + Pune Maharashtra 411045 + IN + +00-17-FF (hex) PLAYLINE Co.,Ltd. +0017FF (base 16) PLAYLINE Co.,Ltd. + 1-4-21 MOTOAKASAKA + TOKYO 107-0051 + JP + +00-17-F6 (hex) Pyramid Meriden Inc. +0017F6 (base 16) Pyramid Meriden Inc. + 45 Gracey Ave. + Meriden CT 06451 + US + +00-17-C5 (hex) SonicWALL +0017C5 (base 16) SonicWALL + 1143 Borregas Ave + Sunnyvale CA 95126 + US + +00-17-BE (hex) Tratec Telecom B.V. +0017BE (base 16) Tratec Telecom B.V. + De Smalle Zijde 12 + Veenendaal NL0-3903 LP + NL + +00-17-C0 (hex) PureTech Systems, Inc. +0017C0 (base 16) PureTech Systems, Inc. + 1950 W Rose Garden Lane + Phoenix AZ 85027 + US + +00-17-BA (hex) SEDO CO., LTD. +0017BA (base 16) SEDO CO., LTD. + 302, KT Bldg, 1ANNEX, 35-1 + Seoul 150-038 + KR + +00-17-D4 (hex) Monsoon Multimedia, Inc +0017D4 (base 16) Monsoon Multimedia, Inc + 1730 South Amphlett blvd. Suite 101 + San Mateo CA 94402 + US + +00-17-80 (hex) Applied Biosystems B.V. +001780 (base 16) Applied Biosystems B.V. + Blk 33, Marsiling Industrial Estate Road 3, + 739256 + SG + +00-17-A5 (hex) Ralink Technology Corp +0017A5 (base 16) Ralink Technology Corp + Suite 215, Bldg 53. 195-61 Sec.4, Chung Hsing Rd, + Chutung Hsinchu 310 + TW + +00-17-A8 (hex) EDM Corporation +0017A8 (base 16) EDM Corporation + 3-5-2 Itabashi + Itabashi-ku Tokyo 173-0004 + JP + +00-17-A9 (hex) Sentivision +0017A9 (base 16) Sentivision + Marynarska 19a + Warsaw Mazowieckie 02-674 + PL + +00-17-AF (hex) Enermet +0017AF (base 16) Enermet + Salvesenintie + Jyskä FIN-40420 + FI + +00-17-AA (hex) elab-experience inc. +0017AA (base 16) elab-experience inc. + 104 Anotsupia + Tsu-shi mie prefecture 514-0131 + JP + +00-17-AE (hex) GAI-Tronics +0017AE (base 16) GAI-Tronics + Brunel Drive + Burton Upon Trent Staffordshire DE13 0BZ + GB + +00-17-B5 (hex) Peerless Systems Corporation +0017B5 (base 16) Peerless Systems Corporation + 2381 Rosecrans Avenue, Suite 400 + El Segundo CA 90245 + US + +00-17-6C (hex) Pivot3, Inc. +00176C (base 16) Pivot3, Inc. + 6605 Cypresswood Drive, Ste 350 + Spring TX 77379-7741 + US + +00-17-70 (hex) Arti Industrial Electronics Ltd. +001770 (base 16) Arti Industrial Electronics Ltd. + Ger-San Sitesi, 657. Sokak + Ankara 06370 + TR + +00-17-8B (hex) Teledyne Technologies Incorporated +00178B (base 16) Teledyne Technologies Incorporated + 12333 West Olympic Blvd + Los Angeles CA 90064 + US + +00-17-DF (hex) Cisco Systems, Inc +0017DF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-17-46 (hex) Freedom9 Inc. +001746 (base 16) Freedom9 Inc. + 4140B SLADEVIEW CRE., + MISSISSAUGA, Ontario L5L6A1 + CA + +00-17-4D (hex) DYNAMIC NETWORK FACTORY, INC. +00174D (base 16) DYNAMIC NETWORK FACTORY, INC. + 26250 EDEN LANDING RD. + HAYWARD CA 94545 + US + +00-17-44 (hex) Araneo Ltd. +001744 (base 16) Araneo Ltd. + 103 Medinat Hayehudim + Herzliya 46733 + IL + +00-17-49 (hex) HYUNDAE YONG-O-SA CO.,LTD +001749 (base 16) HYUNDAE YONG-O-SA CO.,LTD + 448-10, Hyuckjae B/D Seongnae, Kangdong-gu + Seoul 134-847 + KR + +00-17-43 (hex) Deck Srl +001743 (base 16) Deck Srl + Via Fabio Filzi 2 + Milan 20124 + IT + +00-17-28 (hex) Selex Communications +001728 (base 16) Selex Communications + Via Pieragostini 80 + Genova 16151 + IT + +00-17-22 (hex) Hanazeder Electronic GmbH +001722 (base 16) Hanazeder Electronic GmbH + J.M. Dimmelstr 10 + Ried i. I. Oberösterreich 4910 + AT + +00-17-3D (hex) Neology +00173D (base 16) Neology + 13000 Gregg Street Suite A + Poway CA 92064 + US + +00-17-40 (hex) Bluberi Gaming Technologies Inc +001740 (base 16) Bluberi Gaming Technologies Inc + 2125, rue Letendre Suite 420 + Drummondville Quebec J2C 7G1 + CA + +00-17-32 (hex) Science-Technical Center RISSA +001732 (base 16) Science-Technical Center RISSA + st. Abramtsevskaja, h.9 + Moscow 128572 + RU + +00-17-6D (hex) CORE CORPORATION +00176D (base 16) CORE CORPORATION + 1-22-3, Sangenjaya, + Setagaya-ku Tokyo-to 154-8552 + JP + +00-17-73 (hex) Laketune Technologies Co. Ltd +001773 (base 16) Laketune Technologies Co. Ltd + No. 38 Zijinghua Rd. Westlake District + Hangzhou Zhejiang 310013 + CN + +00-17-3A (hex) Cloudastructure Inc +00173A (base 16) Cloudastructure Inc + 585 Broadway + Redwood City CA 94063 + US + +00-17-2F (hex) NeuLion Incorporated +00172F (base 16) NeuLion Incorporated + 1600 Old Country Road + Plainview NY 11803 + US + +00-17-23 (hex) Summit Data Communications +001723 (base 16) Summit Data Communications + 526 South Main Street + Akron Ohio 44311 + US + +00-17-1F (hex) IMV Corporation +00171F (base 16) IMV Corporation + 2-6-10 Takejima + Osaka 555-0011 + JP + +00-17-53 (hex) nFore Technology Inc. +001753 (base 16) nFore Technology Inc. + 5F, NO 31, Ln 258, Rulguang Rd + Taipei Neihu District 11491 + TW + +00-17-57 (hex) RIX TECHNOLOGY LIMITED +001757 (base 16) RIX TECHNOLOGY LIMITED + 17 DAI WANG STREET + TAI PO NEW TERRITORIES + HK + +00-16-BB (hex) Law-Chain Computer Technology Co Ltd +0016BB (base 16) Law-Chain Computer Technology Co Ltd + 7F-2, 286-4, hsin ya road, chien chen district + Kaohsiung 80673 + TW + +00-16-B4 (hex) Private +0016B4 (base 16) Private + +00-16-A7 (hex) AWETA G&P +0016A7 (base 16) AWETA G&P + Burg. Winkellaan 3 + Nootdorp 2631 HG + NL + +00-17-10 (hex) Casa Systems Inc. +001710 (base 16) Casa Systems Inc. + 10, New England Business Center Dr. + Andover MA 01810 + US + +00-16-BF (hex) PaloDEx Group Oy +0016BF (base 16) PaloDEx Group Oy + P.O. Box 64 + Tuusula 04301 + FI + +00-16-B7 (hex) Seoul Commtech +0016B7 (base 16) Seoul Commtech + 448-11, Seongnae 3dong. Gangdong gu, + Seoul 134033 + KR + +00-16-E1 (hex) SiliconStor, Inc. +0016E1 (base 16) SiliconStor, Inc. + 48430 Lakeview Blvd. + Fremont CA 94538 + US + +00-16-E2 (hex) American Fibertek, Inc. +0016E2 (base 16) American Fibertek, Inc. + 120 Belmont Drive + Somerset New Jersey 08873-1204 + US + +00-17-13 (hex) Tiger NetCom +001713 (base 16) Tiger NetCom + J-15 Mudan Cun, Yijing Huayuan, + Shenzhen Guangdong 518003 + CN + +00-16-CD (hex) HIJI HIGH-TECH CO., LTD. +0016CD (base 16) HIJI HIGH-TECH CO., LTD. + Ohga 8133 + Hayami Oita 879-1504 + JP + +00-16-EF (hex) Koko Fitness, Inc. +0016EF (base 16) Koko Fitness, Inc. + 136 Longwater Drive + Norwell MA 02061 + US + +00-16-FD (hex) Jaty Electronics +0016FD (base 16) Jaty Electronics + Jaty Bldg 10F, 1659-5 Bongchun11-Dong + Seoul 151-832 + KR + +00-16-78 (hex) SHENZHEN BAOAN GAOKE ELECTRONICS CO., LTD +001678 (base 16) SHENZHEN BAOAN GAOKE ELECTRONICS CO., LTD + GAOKE INDUSTRIAL PARK, NO.8 TANGKENG ROAD, SHIYAN TOWN + SHENZHEN GUANGDONG 518108 + CN + +00-16-74 (hex) EuroCB (Phils.), Inc. +001674 (base 16) EuroCB (Phils.), Inc. + SFB No.2 + Lapulapu City Cebu 6015 + PH + +00-16-70 (hex) SKNET Corporation +001670 (base 16) SKNET Corporation + Fontana Shinyokohama + Yokohama Kanagawa 222-0033 + JP + +00-16-89 (hex) Pilkor Electronics Co., Ltd +001689 (base 16) Pilkor Electronics Co., Ltd + 381,Wonchun-Dong,Yeoungtong-Gu + Suwon Kyung Ki-Do 442-380 + KR + +00-16-8A (hex) id-Confirm Inc +00168A (base 16) id-Confirm Inc + 1800 Boulder St + Denver CO 80211 + US + +00-16-86 (hex) Karl Storz Imaging +001686 (base 16) Karl Storz Imaging + 175 Cremona Dr. + Goleta CA 93117 + US + +00-16-8D (hex) KORWIN CO., Ltd. +00168D (base 16) KORWIN CO., Ltd. + 3rd Floor, Hana Bldg, 123-7 Nonhyun-dong + Seoul 135-010 + KR + +00-16-8E (hex) Vimicro corporation +00168E (base 16) Vimicro corporation + 15/F,Shining Tower,No.35,xueyuan + Beijing 100083 + CN + +00-16-4F (hex) World Ethnic Broadcastin Inc. +00164F (base 16) World Ethnic Broadcastin Inc. + 50 California Street, Suite 1500 + San Francisco California 94111 + US + +00-16-7E (hex) DIBOSS.CO.,LTD +00167E (base 16) DIBOSS.CO.,LTD + 126-1, Gongdan-dong + Gumi Gyeongbuk 730-902 + KR + +00-16-7B (hex) Haver&Boecker +00167B (base 16) Haver&Boecker + Carl-Haver-Platz 3 + Oelde NRW 59302 + DE + +00-16-79 (hex) eOn Communications +001679 (base 16) eOn Communications + 4105 Royal Drive, Suite 100 + Kennesaw Georgia 30144 + US + +00-16-A3 (hex) Ingeteam Transmission&Distribution, S.A. +0016A3 (base 16) Ingeteam Transmission&Distribution, S.A. + C/ Usausuaga, 7 + Basauri Bizkaia 48970 + ES + +00-16-A0 (hex) Auto-Maskin +0016A0 (base 16) Auto-Maskin + Sophie Radichs Vei 7 + LILLESTROM Akershus 2003 + NO + +00-16-5D (hex) AirDefense, Inc. +00165D (base 16) AirDefense, Inc. + 4800 North Point Pkwy + Alpharetta GA 30022 + US + +00-16-5B (hex) Grip Audio +00165B (base 16) Grip Audio + 6345 W. Louise Drive + Glendale Arizona 85310-4243 + US + +00-16-67 (hex) A-TEC Subsystem INC. +001667 (base 16) A-TEC Subsystem INC. + 4F, No. 86, Chung-Hsing Road, Shijr City, + 221 + TW + +00-16-4A (hex) Vibration Technology Limited +00164A (base 16) Vibration Technology Limited + Vibtech House, Central Boulevard + Larbert Scotland FK5 4RU + GB + +00-16-45 (hex) Power Distribution, Inc. +001645 (base 16) Power Distribution, Inc. + 4200 Oakleys Ct. + Richmond VA 23223 + US + +00-16-3F (hex) CReTE SYSTEMS Inc. +00163F (base 16) CReTE SYSTEMS Inc. + 7F,No.250,Sec.3,Pei Shen Rd.,Shen Keng Hsiang + Taipei County 22204 + TW + +00-16-3D (hex) Tsinghua Tongfang Legend Silicon Tech. Co., Ltd. +00163D (base 16) Tsinghua Tongfang Legend Silicon Tech. Co., Ltd. + 26F TSINGHUA TONGFANG HI-TECH PLAZA + BEIJING 100083 + CN + +00-16-2D (hex) STNet Co., Ltd. +00162D (base 16) STNet Co., Ltd. + Shin-wha Building 4F, 954-25 + Anyang-si Kyungki-do 431-060 + KR + +00-16-27 (hex) embedded-logic DESIGN AND MORE GmbH +001627 (base 16) embedded-logic DESIGN AND MORE GmbH + Hansestrasse 24 + Muenster NRW 48153 + DE + +00-16-3A (hex) YVES TECHNOLOGY CO., LTD. +00163A (base 16) YVES TECHNOLOGY CO., LTD. + No.74, Fusing 2nd Rd. + Gueishan Taoyuan 33377 + TW + +00-16-38 (hex) TECOM Co., Ltd. +001638 (base 16) TECOM Co., Ltd. + 23 R&D Road 2 Science Based Industrial Park + Hsin-Chu 300 + TW + +00-16-33 (hex) Oxford Diagnostics Ltd. +001633 (base 16) Oxford Diagnostics Ltd. + Sandybrae + Oxford Oxon. OX1 5HJ + GB + +00-15-EC (hex) Boca Devices LLC +0015EC (base 16) Boca Devices LLC + 7647 Sierra Ter + Boca Raton Florida 33433 + US + +00-15-EF (hex) NEC TOKIN Corporation +0015EF (base 16) NEC TOKIN Corporation + 1-1,Asahi-Cho 7-chome,Shiroishi, + Miyagi 989-0223 + JP + +00-15-E4 (hex) Zimmer Elektromedizin +0015E4 (base 16) Zimmer Elektromedizin + Junkersstrasse 9 + Neu-Ulm Bayern 89231 + DE + +00-16-22 (hex) BBH SYSTEMS GMBH +001622 (base 16) BBH SYSTEMS GMBH + Böttgerstraße 40 + Weiden i.d.OPf. Bayern 92637 + DE + +00-16-13 (hex) LibreStream Technologies Inc. +001613 (base 16) LibreStream Technologies Inc. + 895 Waverley Street + Winnipeg Manitoba R3T 5P4 + CA + +00-16-0F (hex) BADGER METER INC +00160F (base 16) BADGER METER INC + 4545 W BROWN DEER RD + MILWAUKEE WI 53223 + US + +00-16-04 (hex) Sigpro +001604 (base 16) Sigpro + 655 W Evelyn ST + Mountain View CA 94041 + US + +00-15-FB (hex) setex schermuly textile computer gmbh +0015FB (base 16) setex schermuly textile computer gmbh + Hauptstraße 25 + Mengerskirchen Hessen 35794 + DE + +00-15-FE (hex) SCHILLING ROBOTICS LLC +0015FE (base 16) SCHILLING ROBOTICS LLC + 260 COUSTEAU PL + DAVIS CA 95618 + US + +00-16-0D (hex) Be Here Corporation +00160D (base 16) Be Here Corporation + 39300 Civic Center Dr., Suite 180 + Fremont CA 94538 + US + +00-15-C9 (hex) Gumstix, Inc +0015C9 (base 16) Gumstix, Inc + 3130 Alpine Road + Portola Valley CA 94028 + US + +00-15-BA (hex) iba AG +0015BA (base 16) iba AG + Koenigswarterstrasse 44 + Fuerth Bavaria 90762 + DE + +00-15-BB (hex) SMA Solar Technology AG +0015BB (base 16) SMA Solar Technology AG + Sonnenallee 1 + Niestetal Hessen 34266 + DE + +00-15-BF (hex) technicob +0015BF (base 16) technicob + 4 Rue Camille Saint-Saens + LANESTER Morbihan 56602 + US + +00-15-82 (hex) Pulse Eight Limited +001582 (base 16) Pulse Eight Limited + 13 The Metro Centre + Peterbourugh PE2 7UH + GB + +00-15-7B (hex) Leuze electronic GmbH + Co. KG +00157B (base 16) Leuze electronic GmbH + Co. KG + In der Braike 1 + Owen Baden-Württemberg 73277 + DE + +00-15-78 (hex) Audio / Video Innovations +001578 (base 16) Audio / Video Innovations + A3-3375 North Service Road + Burlington ON L7N 3G2 + CA + +00-15-AE (hex) kyung il +0015AE (base 16) kyung il + woar rong-myn yougate-ri 101-2 + paju-city gyeong gi 413-813 + KR + +00-15-BC (hex) Develco +0015BC (base 16) Develco + Olof Palmes Allé 40 + Aarhus N 8200 + DK + +00-15-BD (hex) Group 4 Technology Ltd +0015BD (base 16) Group 4 Technology Ltd + Challenge House + Tewkesbury Gloucestershire GL20 8UQ + GB + +00-15-B5 (hex) CI Network Corp. +0015B5 (base 16) CI Network Corp. + 2F Daini Inoue Bldg + Tokyo 107-0052 + JP + +00-15-CD (hex) Exartech International Corp. +0015CD (base 16) Exartech International Corp. + 3/F, No.62, Lane 188, Ruei Guang Rd., Neihu + Taipei 114 + TW + +00-15-D9 (hex) PKC Electronics Oy +0015D9 (base 16) PKC Electronics Oy + Pajuniityntie 43 + RAAHE 92120 + FI + +00-15-DD (hex) IP Control Systems Ltd. +0015DD (base 16) IP Control Systems Ltd. + Unit 15, Hi-Tech Village, + Boldon Tyne & Wear NE35 9PE + GB + +00-15-9C (hex) B-KYUNG SYSTEM Co.,Ltd. +00159C (base 16) B-KYUNG SYSTEM Co.,Ltd. + #812,WOOLIM E-BIZ CENTER,170-5 + GURO-DONG GURO-GU 152-847 + KR + +00-15-95 (hex) Quester Tangent Corporation +001595 (base 16) Quester Tangent Corporation + 201 - 9865 West Saanich Road + Sidney BC V8L 5Y8 + CA + +00-15-87 (hex) Takenaka Seisakusho Co.,Ltd +001587 (base 16) Takenaka Seisakusho Co.,Ltd + 178 HISHIE + HIGASHI-OSAKA CITY OSAKA 578-0984 + JP + +00-15-1A (hex) Hunter Engineering Company +00151A (base 16) Hunter Engineering Company + 11250 Hunter Drive + Bridgeton Missouri 63044 + US + +00-15-14 (hex) Hu Zhou NAVA Networks&Electronics Ltd. +001514 (base 16) Hu Zhou NAVA Networks&Electronics Ltd. + 3/F,No.328-4,Guang Yuan Rd. + Hu Zhou Zhe Jiang 313000 + CN + +00-15-16 (hex) URIEL SYSTEMS INC. +001516 (base 16) URIEL SYSTEMS INC. + #204 Byucksan Digitalvalley 1st, 212-16, Guro-dong, Guro-gu + Seoul 152-050 + KR + +00-15-45 (hex) SEECODE Co., Ltd. +001545 (base 16) SEECODE Co., Ltd. + 4th Floor, Amin Bldg., 110-1, Yangjaedong, Seochogu + Seoul 137-891 + KR + +00-15-43 (hex) Aberdeen Test Center +001543 (base 16) Aberdeen Test Center + 400 Colleran Road + Aberdeen Proving Grounds MD 21005-5059 + US + +00-15-41 (hex) StrataLight Communications, Inc. +001541 (base 16) StrataLight Communications, Inc. + 2105 S. Bascom Avenue + Campbell CA 95008 + US + +00-15-69 (hex) PECO II, Inc. +001569 (base 16) PECO II, Inc. + 7060 Huntley Road + Columbus OH 43229 + US + +00-15-64 (hex) BEHRINGER Spezielle Studiotechnik GmbH +001564 (base 16) BEHRINGER Spezielle Studiotechnik GmbH + Hanns-Martin-Schleyer-Str. 36-38 + Willich + DE + +00-15-63 (hex) Cisco Systems, Inc +001563 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-15-61 (hex) JJPlus Corporation +001561 (base 16) JJPlus Corporation + 678 Massachusetts Ave + Cambridge MA 02139 + US + +00-15-71 (hex) Nolan Systems +001571 (base 16) Nolan Systems + 1595 Cleo Springs Dr. + San Jose Ca. 95131 + US + +00-15-65 (hex) XIAMEN YEALINK NETWORK TECHNOLOGY CO.,LTD +001565 (base 16) XIAMEN YEALINK NETWORK TECHNOLOGY CO.,LTD + 7F Hualian Electronic BLDG.580 Jiahe Road,Xiamen China + Xiamen Fujian 361006 + CN + +00-15-38 (hex) RFID, Inc. +001538 (base 16) RFID, Inc. + 14100 East Jewell Ave. + Aurora CO 80012 + US + +00-15-2E (hex) PacketHop, Inc. +00152E (base 16) PacketHop, Inc. + 1301 Shoreway Road + Belmont California 94002 + US + +00-15-58 (hex) FOXCONN +001558 (base 16) FOXCONN + No.2,2nd DongHuan Road,10th YouSong + ShenZhen GuangDong 518109 + US + +00-15-1F (hex) Multivision Intelligent Surveillance (Hong Kong) Ltd +00151F (base 16) Multivision Intelligent Surveillance (Hong Kong) Ltd + 26/F, Aitken Vanson Centre, + + HK + +00-15-22 (hex) Dea Security +001522 (base 16) Dea Security + Via Togliatti + Santo Stefano Magra SP 19037 + IT + +00-15-4F (hex) one RF Technology +00154F (base 16) one RF Technology + 1360 Route des Dolines + Valbonne Sophia-Antipolis PACA 06560 + FR + +00-15-01 (hex) LexBox +001501 (base 16) LexBox + 3, avenue Didier Daurat + TOULOUSE 31400 + FR + +00-14-A3 (hex) Vitelec BV +0014A3 (base 16) Vitelec BV + kapittelweg 18 + Breda NB NL 4827 HG + NL + +00-14-97 (hex) ZHIYUAN Eletronics co.,ltd. +001497 (base 16) ZHIYUAN Eletronics co.,ltd. + 2 Floor, NO.3 Building, Huangzhou Industrial Estate, Chebei Road, + Guangzhou Guangdong 510660 + CN + +00-14-99 (hex) Helicomm Inc +001499 (base 16) Helicomm Inc + 1947 Camino Vida Roble + Carlsbad CA 92008 + US + +00-14-92 (hex) Liteon, Mobile Media Solution SBU +001492 (base 16) Liteon, Mobile Media Solution SBU + 4F, 3, Lane 768, Sec. 4, + Taipei 115 + TW + +00-14-94 (hex) ESU AG +001494 (base 16) ESU AG + Lukasstrasse 29 + St. Gallen 9008 + CH + +00-14-EF (hex) TZero Technologies, Inc. +0014EF (base 16) TZero Technologies, Inc. + 455 W. Maude Avenue + Sunnyvale CA 94085 + US + +00-14-BC (hex) SYNECTIC TELECOM EXPORTS PVT. LTD. +0014BC (base 16) SYNECTIC TELECOM EXPORTS PVT. LTD. + 196, 1st Main, 3rd Stage, 4th Block + BANGALORE 560079 + IN + +00-14-B9 (hex) MSTAR SEMICONDUCTOR +0014B9 (base 16) MSTAR SEMICONDUCTOR + 11-13 rue René Jacques + Issy les Moulineaux 92130 + FR + +00-14-BD (hex) incNETWORKS, Inc +0014BD (base 16) incNETWORKS, Inc + 198 Brighton Ave + Long Branch NJ 07740 + US + +00-14-B7 (hex) AR Infotek Inc. +0014B7 (base 16) AR Infotek Inc. + 9F, No.185, GangQian Road + Taipei 11494 + TW + +00-14-CA (hex) Key Radio Systems Limited +0014CA (base 16) Key Radio Systems Limited + Venus House + Aldermaston Berkshire RG7 8DA + GB + +00-14-C8 (hex) Contemporary Research Corp +0014C8 (base 16) Contemporary Research Corp + 4355 Excel Pkwy + Addison TX 75001 + US + +00-14-C5 (hex) Alive Technologies Pty Ltd +0014C5 (base 16) Alive Technologies Pty Ltd + 11 Technology Drive + Arundel Queensland 4214 + AU + +00-14-DA (hex) Huntleigh Healthcare +0014DA (base 16) Huntleigh Healthcare + Huntleigh Healthcare - Diagnostic Products Division + Cardiff CF24 5HN + GB + +00-14-D5 (hex) Datang Telecom Technology CO. , LCD,Optical Communication Br +0014D5 (base 16) Datang Telecom Technology CO. , LCD,Optical Communication Br + 3rd Floor,Building 8,Hi-Tech Incubation Park, + ChengDu SiChuan 610041 + CN + +00-14-D3 (hex) SEPSA +0014D3 (base 16) SEPSA + calle Albatros, 7 y 9 + PINTO Madrid 28320 + ES + +00-14-D8 (hex) bio-logic SA +0014D8 (base 16) bio-logic SA + 1, rue de l'Europe + CLAIX 38640 + FR + +00-14-EE (hex) Western Digital Technologies, Inc. +0014EE (base 16) Western Digital Technologies, Inc. + 20511 Lake Forest Dr. + Lake Forest Ca 92630 + US + +00-14-B5 (hex) PHYSIOMETRIX,INC +0014B5 (base 16) PHYSIOMETRIX,INC + 101 BILLERICA AVE #5 + N. BILLERICA MA 01862 + US + +00-14-9C (hex) HF Company +00149C (base 16) HF Company + Node Park Touraine + BP1 Tauxigny 37310 + FR + +00-14-5C (hex) Intronics B.V. +00145C (base 16) Intronics B.V. + Koolhovenstraat 1E + Barneveld Gelderland 3772 MT + NL + +00-14-5A (hex) Neratec Solutions AG +00145A (base 16) Neratec Solutions AG + Rosswiesstrasse 29 + CH-8608 Bubikon ZH + CH + +00-14-5B (hex) SeekerNet Inc. +00145B (base 16) SeekerNet Inc. + 300 Satellite Blvd. + Suwanee Georgia 30024 + US + +00-14-49 (hex) Sichuan Changhong Electric Ltd. +001449 (base 16) Sichuan Changhong Electric Ltd. + No.35,East MianXin Road,MianYang,Sichaun,China. + MianYang SiChuan PRC 621000 + CN + +00-14-46 (hex) SuperVision Solutions LLC +001446 (base 16) SuperVision Solutions LLC + 762 Industrial Dr. + Elmhurst IL 60126 + US + +00-14-40 (hex) ATOMIC Corporation +001440 (base 16) ATOMIC Corporation + MAMPO BLDG + TAITO-KU TOKYO 111-0053 + JP + +00-14-2E (hex) 77 Elektronika Kft. +00142E (base 16) 77 Elektronika Kft. + Fehervari ut 98. + Budapest H-1163 + HU + +00-14-30 (hex) ViPowER, Inc +001430 (base 16) ViPowER, Inc + 9F., No.205-3, Sec. 3, Beisin Rd + Sindian Taipei County 231 + TW + +00-14-32 (hex) Tarallax Wireless, Inc. +001432 (base 16) Tarallax Wireless, Inc. + 10 West 100 South, + Salt Lake City UT 84101 + US + +00-14-85 (hex) Giga-Byte +001485 (base 16) Giga-Byte + No.215,Nan-Ping Road, + Pin-Jen Taoyuan 326 + TW + +00-14-83 (hex) eXS Inc. +001483 (base 16) eXS Inc. + 1900 Alameda de las Pulgas + San Mateo CA 94403 + US + +00-14-71 (hex) Eastern Asia Technology Limited +001471 (base 16) Eastern Asia Technology Limited + 8F-1, No. 188, Baoqiao Rd., Xindian Dist. + New Taipei City 23145 + TW + +00-14-6A (hex) Cisco Systems, Inc +00146A (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-14-4C (hex) General Meters Corp. +00144C (base 16) General Meters Corp. + 1935 Dominion Way + Colorado Springs Colorado 80918 + US + +00-14-43 (hex) Consultronics Europe Ltd +001443 (base 16) Consultronics Europe Ltd + Electron Way + Chandlers Ford Hants SO53 4SE + GB + +00-14-60 (hex) Kyocera Wireless Corp. +001460 (base 16) Kyocera Wireless Corp. + 10300 Campus Point Drive + San Diego CA 92121 + US + +00-13-F5 (hex) Akimbi Systems +0013F5 (base 16) Akimbi Systems + 1400 Fashion Island Blvd + San Mateo CA 94404 + US + +00-13-F1 (hex) AMOD Technology Co., Ltd. +0013F1 (base 16) AMOD Technology Co., Ltd. + 2F., No. 16, Prosperity Road II + Hsinchu, 30078 + TW + +00-13-E7 (hex) Halcro +0013E7 (base 16) Halcro + Suite 1, Level 1 + Wayville South Australia 5034 + AU + +00-13-EA (hex) Kamstrup A/S +0013EA (base 16) Kamstrup A/S + Industrivej 28 + Stilling 8660 + DK + +00-13-E1 (hex) Iprobe AB +0013E1 (base 16) Iprobe AB + Finlandsgatan 12 + Kista SE-16474 + SE + +00-13-E3 (hex) CoVi Technologies, Inc. +0013E3 (base 16) CoVi Technologies, Inc. + 6300 Bridgepoint Parkway + Austin Texas 78730 + US + +00-13-E4 (hex) YANGJAE SYSTEMS CORP. +0013E4 (base 16) YANGJAE SYSTEMS CORP. + 1202. HANSHIN IT TOWER Guro-3Dong, + Seoul 152-848 + KR + +00-13-C1 (hex) Asoka USA Corporation +0013C1 (base 16) Asoka USA Corporation + 558 Pilgrim Drive + Foster City CA 94404 + US + +00-13-C0 (hex) Trix Tecnologia Ltda. +0013C0 (base 16) Trix Tecnologia Ltda. + Rua da Paz, 1957 - Chácara Santo Antônio + São Paulo 04713-002 + BR + +00-14-1F (hex) SunKwang Electronics Co., Ltd +00141F (base 16) SunKwang Electronics Co., Ltd + #365(Techno-park, 301 dong, 901 ho,) Samjung-dong, Ohjung-ku, + Bucheon-shi Kyunggi-do 421-809 + KR + +00-14-1D (hex) LTI-Motion GmbH +00141D (base 16) LTI-Motion GmbH + Gewerbestrasse 5-9 + Lahnau Hessen 35633 + DE + +00-14-12 (hex) S-TEC electronics AG +001412 (base 16) S-TEC electronics AG + Industriestrasse 49 + Zug 6300 + CH + +00-14-11 (hex) Deutschmann Automation GmbH & Co. KG +001411 (base 16) Deutschmann Automation GmbH & Co. KG + Carl-Zeiss-Str. 8 + Bad Camberg D - 65520 + DE + +00-14-05 (hex) OpenIB, Inc. +001405 (base 16) OpenIB, Inc. + OpenFabrics, Inc., c/o QLogic Corporation + Mountain View CA 94043-4655 + US + +00-45-01 (hex) Midmark RTLS +004501 (base 16) Midmark RTLS + 2600 Miller Creek Road + Traverse City MI 49684 + US + +00-14-03 (hex) Renasis, LLC +001403 (base 16) Renasis, LLC + 1530 N. State St. + Lehi UT 84043 + US + +00-14-01 (hex) Rivertree Networks Corp. +001401 (base 16) Rivertree Networks Corp. + R#304, K-Center, 1591-9 + Anyang-si Kyunggi-do 431-815 + KR + +00-13-D9 (hex) Matrix Product Development, Inc. +0013D9 (base 16) Matrix Product Development, Inc. + 13 North Bird Street + Sun Prairie WI 53590 + US + +00-13-CC (hex) Tall Maple Systems +0013CC (base 16) Tall Maple Systems + 85 Saratoga Ave Suite 139 + Santa Clara CA 95051 + US + +00-13-94 (hex) Infohand Co.,Ltd +001394 (base 16) Infohand Co.,Ltd + Kranz-Techno #1207, 5442-1, Sangdaewon-dong, Jungwon-gu + Seongnam-si Gyeonggi-do 462-819 + KR + +00-13-89 (hex) Redes de Telefonía Móvil S.A. +001389 (base 16) Redes de Telefonía Móvil S.A. + C/Puerto de la Morcuera 14 B4 + Leganés Madrid 28918 + ES + +00-13-8C (hex) Kumyoung.Co.Ltd +00138C (base 16) Kumyoung.Co.Ltd + Seoul KY building, 40-17 Hangang Ro, 3Ga, Youngsan-Gu + Seoul 140-880 + KR + +00-13-A1 (hex) Crow Electronic Engeneering +0013A1 (base 16) Crow Electronic Engeneering + 12 Kinneret st. + Airport City + IL + +00-13-9C (hex) Exavera Technologies, Inc. +00139C (base 16) Exavera Technologies, Inc. + 195 New Hampshire Avenue + Portsmouth NH 03801 + US + +00-13-55 (hex) TOMEN Cyber-business Solutions, Inc. +001355 (base 16) TOMEN Cyber-business Solutions, Inc. + 2-11-19 Kohnan + TOKYO 108-0075 + JP + +00-13-57 (hex) Soyal Technology Co., Ltd. +001357 (base 16) Soyal Technology Co., Ltd. + 10F, No. 27, Lane 169, Kangning St., Shijr City, + Taipei 221 + TW + +00-13-60 (hex) Cisco Systems, Inc +001360 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-13-8E (hex) FOAB Elektronik AB +00138E (base 16) FOAB Elektronik AB + Sankt Jorgens Vag 8 + Gothenburg 422 49 + SE + +00-13-76 (hex) Tabor Electronics Ltd. +001376 (base 16) Tabor Electronics Ltd. + 9 Hatatsia St. + Tel Hanan 20302 + IL + +00-13-5D (hex) NTTPC Communications, Inc. +00135D (base 16) NTTPC Communications, Inc. + 3-25 Kanda Jinbo-cho + Chiyoda-ku Tokyo 101-0051 + JP + +00-13-52 (hex) Naztec, Inc. +001352 (base 16) Naztec, Inc. + 820 Park Two Dr. + Sugar Land TX 77478 + US + +00-13-6C (hex) TomTom +00136C (base 16) TomTom + Oosterdoksstraat 114 + 1011 DK Amsterdam + NL + +00-13-64 (hex) Paradigm Technology Inc.. +001364 (base 16) Paradigm Technology Inc.. + 3F, No. 285, Sec.2, Ti-Ding Blvd Nei-Hu, + Taipei 114 + TW + +00-13-6B (hex) E-TEC +00136B (base 16) E-TEC + 2-17-14-503 Hakataekimae + Fukuoka Fukuokaken 812-0011 + JP + +00-13-80 (hex) Cisco Systems, Inc +001380 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-13-85 (hex) Add-On Technology Co., LTD. +001385 (base 16) Add-On Technology Co., LTD. + 1F, No.11, Lane 206, Da-An Road Sec. 1, + Taipei 106 + TW + +00-13-B3 (hex) Ecom Communications Technology Co., Ltd. +0013B3 (base 16) Ecom Communications Technology Co., Ltd. + Floor 7, Machinery Industry Building, No.22, + Beijing + CN + +00-13-B7 (hex) Scantech ID +0013B7 (base 16) Scantech ID + Vanadiumweg 22 + Amersfoort Utrecht 3812 PZ + NL + +00-13-08 (hex) Nuvera Fuel Cells +001308 (base 16) Nuvera Fuel Cells + 129 Concord Road, #1 + Billerica MA 01821 + US + +00-13-07 (hex) Paravirtual Corporation +001307 (base 16) Paravirtual Corporation + 2953 Bunker Hill Lane + Santa Clara CA 95054 + US + +00-12-FC (hex) PLANET System Co.,LTD +0012FC (base 16) PLANET System Co.,LTD + 4th Floor, Daehan B/D, 873-29, + Seoul 137-064 + KR + +00-12-FE (hex) Lenovo Mobile Communication Technology Ltd. +0012FE (base 16) Lenovo Mobile Communication Technology Ltd. + Xiamen Overseas Chinese Electronic Science Park,Huoju High Technology Development Zone + XIA MEN FU JIAN 361009 + CN + +00-12-EC (hex) Movacolor b.v. +0012EC (base 16) Movacolor b.v. + Koperslagersstraat 31 + Sneek Friesland 8601 WL + NL + +00-12-EB (hex) PDH Solutions, LLC +0012EB (base 16) PDH Solutions, LLC + 34154 Bennett Rd + Warren OR 97053 + US + +00-13-43 (hex) Matsushita Electronic Components (Europe) GmbH +001343 (base 16) Matsushita Electronic Components (Europe) GmbH + Zeppelinstraße 19 + Lueneburg Niedersachsen 21337 + DE + +00-13-3E (hex) MetaSwitch +00133E (base 16) MetaSwitch + 1411 Harbor Bay Parkway + Alameda CA 94502 + US + +00-13-45 (hex) Eaton Corporation +001345 (base 16) Eaton Corporation + 4201 North 27th Street + Milwaukee Wisconsin 53216 + US + +00-13-47 (hex) Red Lion Controls, LP +001347 (base 16) Red Lion Controls, LP + 20 Willow Springs Circle + York NY 17402 + US + +00-13-2E (hex) ITian Coporation +00132E (base 16) ITian Coporation + 4F Youngho Bd.1605-1 Seocho-dong + Seoul 137-070 + KR + +00-13-39 (hex) CCV Deutschland GmbH +001339 (base 16) CCV Deutschland GmbH + Gewerbering 1 + Au i. d. Hallertau Bayern 84072 + DE + +00-13-29 (hex) VSST Co., LTD +001329 (base 16) VSST Co., LTD + suit 3202, Korea World Trade Center 159-1 + Seoul 135-729 + KR + +00-13-2B (hex) Phoenix Digital +00132B (base 16) Phoenix Digital + 7650 East Evans Rd. Bldg. A + Scottsdale Az 85260 + US + +00-13-0B (hex) Mextal B.V. +00130B (base 16) Mextal B.V. + De Tienden 48 + Nuenen Noord Brabant 5674TB + NL + +00-13-0D (hex) GALILEO AVIONICA +00130D (base 16) GALILEO AVIONICA + VIALE EUROPA + NERVIANO MILANO 20014 + IT + +00-12-F7 (hex) Xiamen Xinglian Electronics Co., Ltd. +0012F7 (base 16) Xiamen Xinglian Electronics Co., Ltd. + Xinglian Electronics (Xingtel) Building,Chuangxin Road, + Xiamen Fujian 361006 + CN + +00-13-1B (hex) BeCell Innovations Corp. +00131B (base 16) BeCell Innovations Corp. + 12F-9, No. 79, Shin-Tai 5th Rd Sec 1, + Shih-chih, Taipei 221 + TW + +00-12-E2 (hex) ALAXALA Networks Corporation +0012E2 (base 16) ALAXALA Networks Corporation + 890 Kashimada, Saiwai-ku + Kawasaki-shi Kanagawa-ken 212-0058 + JP + +00-12-DF (hex) Novomatic AG +0012DF (base 16) Novomatic AG + Wiener Strasse 158 + Gumpoldskirchen Niederösterreich A-2352 + AT + +00-12-D4 (hex) Princeton Technology, Ltd +0012D4 (base 16) Princeton Technology, Ltd + K.A.I. Bldg. 3F + Chiyodaku Tokyo 101-0032 + JP + +00-12-D9 (hex) Cisco Systems, Inc +0012D9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-12-C2 (hex) Apex Electronics Factory +0012C2 (base 16) Apex Electronics Factory + No.3 Industrial Zone, No.4 Block, + Shen Zhen Guang Dong 518103 + CN + +00-12-BE (hex) Astek Corporation +0012BE (base 16) Astek Corporation + 5055 Corporate Plaza Drive + Colorado Springs Colorado 80919 + US + +00-12-E1 (hex) Alliant Networks, Inc +0012E1 (base 16) Alliant Networks, Inc + 1259 Birchwood Dr. + Sunnyvale CA 94089 + US + +00-12-C5 (hex) V-Show Technology (China) Co.,Ltd +0012C5 (base 16) V-Show Technology (China) Co.,Ltd + 7F, Tengda Plaza, No.168 + HaiDian District, Beijing 100089 + CN + +00-12-AD (hex) IDS GmbH +0012AD (base 16) IDS GmbH + Nobelstraße, 18 + Ettlingen Baden-Württemberg 76275 + DE + +00-12-A0 (hex) NeoMeridian Sdn Bhd +0012A0 (base 16) NeoMeridian Sdn Bhd + 3A-1, Perdana The Place + Bandar Damansara Perdana Selangor 47820 + MY + +00-12-86 (hex) ENDEVCO CORP +001286 (base 16) ENDEVCO CORP + 30700 RANCHO VIEJO ROAD + SAN JUAN CAPISTRANO CA 92675 + US + +00-12-63 (hex) Data Voice Technologies GmbH +001263 (base 16) Data Voice Technologies GmbH + Stockholmer Allee 32b + Dortmund NRW D-44269 + DE + +00-12-70 (hex) NGES Denro Systems +001270 (base 16) NGES Denro Systems + 7055 Troy Hill Dr + Elkridge MD 21075 + US + +00-12-6E (hex) Seidel Elektronik GmbH Nfg.KG +00126E (base 16) Seidel Elektronik GmbH Nfg.KG + Frauentalerstrasse 100 + Deutschlandsberg Steiermark 8530 + AT + +00-12-6F (hex) Rayson Technology Co., Ltd. +00126F (base 16) Rayson Technology Co., Ltd. + 1F No.9 R&D Rd.II, Science-Based Industrial Park + Hsin-Chu 300 + TW + +00-12-5C (hex) Green Hills Software, Inc. +00125C (base 16) Green Hills Software, Inc. + 30 West Sola Street + Santa Barbara CA 93101 + US + +00-12-5F (hex) AWIND Inc. +00125F (base 16) AWIND Inc. + 17F., No. 886-5, Jungjeng Rd + Taipei County 235 + TW + +00-12-2D (hex) SiNett Corporation +00122D (base 16) SiNett Corporation + 640 W. California Avenue + Sunnyvale CA 94086 + US + +00-12-74 (hex) NIT lab +001274 (base 16) NIT lab + Skoriny str., 65-3 + Minsk Minskaya obl. 220013 + BY + +00-12-53 (hex) AudioDev AB +001253 (base 16) AudioDev AB + Kabingatan 9 + Malmö SE-212 39 + SE + +00-12-4C (hex) BBWM Corporation +00124C (base 16) BBWM Corporation + 6F, No. 578, Rui Guang Road, Nei Hu + Taipei 114 + TW + +00-12-55 (hex) NetEffect Incorporated +001255 (base 16) NetEffect Incorporated + 9211 Waterford Centre Blvd + Austin Texas 78758 + US + +00-12-44 (hex) Cisco Systems, Inc +001244 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-12-2C (hex) Soenen Controls N.V. +00122C (base 16) Soenen Controls N.V. + Wijnedalestraat 190 + Roeselare W-VL 8800 + BE + +00-12-2B (hex) Virbiage Pty Ltd +00122B (base 16) Virbiage Pty Ltd + Level 4 + Melbourne Victoria 3000 + AU + +00-12-32 (hex) LeWiz Communications Inc. +001232 (base 16) LeWiz Communications Inc. + 1376 N. 4th St. #300 + San Jose CA 95112 + US + +00-12-27 (hex) Franklin Electric Co., Inc. +001227 (base 16) Franklin Electric Co., Inc. + 400 E. Spring Street + Bluffton Indiana 46714 + US + +00-12-1A (hex) Techno Soft Systemnics Inc. +00121A (base 16) Techno Soft Systemnics Inc. + 2-5-17, Ebisu-nishi, Naniwa-ku, + Osaka 556-0003 + JP + +00-12-1B (hex) Sound Devices, LLC +00121B (base 16) Sound Devices, LLC + 300 Wengel Drive + Reedsburg WI 53959 + US + +00-11-DF (hex) Current Energy +0011DF (base 16) Current Energy + 5440 Harvest Hill, Ste 100 + Dallas TX 75230 + US + +00-11-D7 (hex) eWerks Inc +0011D7 (base 16) eWerks Inc + 420-2166 Mountain Grove Ave + Burlington Ontario L7P4X4 + CA + +00-12-04 (hex) u10 Networks, Inc. +001204 (base 16) u10 Networks, Inc. + 2-2-14 Kakinokizaka + Meguro Tokyo 152-0022 + JP + +00-12-0A (hex) Emerson Climate Technologies GmbH +00120A (base 16) Emerson Climate Technologies GmbH + Heerstrasse 111 + Waiblingen BW 71332 + DE + +00-12-08 (hex) Gantner Instruments GmbH +001208 (base 16) Gantner Instruments GmbH + Montafonerstrasse 8 + Schruns Vorarlberg 6780 + AT + +00-12-01 (hex) Cisco Systems, Inc +001201 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-EE (hex) Estari, Inc. +0011EE (base 16) Estari, Inc. + 1800 Paxton St + Harrisburg PA 17104 + US + +00-12-00 (hex) Cisco Systems, Inc +001200 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-E5 (hex) KCodes Corporation +0011E5 (base 16) KCodes Corporation + Floor 2, Number 501, Section 2 + Neihu District Taipei City 114 + TW + +00-11-DE (hex) EURILOGIC +0011DE (base 16) EURILOGIC + Centrale Parc Bât 7 + Chatenay Malabry 92298 + FR + +00-11-C8 (hex) Powercom Co., Ltd. +0011C8 (base 16) Powercom Co., Ltd. + 8F, No. 246, Lien Chen Rd. + Chung Ho Taipei 235 + TW + +00-11-B8 (hex) Liebherr - Elektronik GmbH +0011B8 (base 16) Liebherr - Elektronik GmbH + Peter - Dornier - Strasse 11 + Lindau (Bodensee) Bavaria 88131 + DE + +00-11-B4 (hex) Westermo Network Technologies AB +0011B4 (base 16) Westermo Network Technologies AB + Stora Sundby + Sweden SE-640 40 + SE + +00-11-78 (hex) Chiron Technology Ltd +001178 (base 16) Chiron Technology Ltd + Wyvols Court + Reading Berkshire RG7 1WY + GB + +00-11-6A (hex) Domo Ltd +00116A (base 16) Domo Ltd + Wessex House + Eastleigh Hampshire SO50 9FD + GB + +00-11-93 (hex) Cisco Systems, Inc +001193 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-8C (hex) Missouri Department of Transportation +00118C (base 16) Missouri Department of Transportation + P.O. Box 270 + Jefferson City Missouri 65102 + US + +00-11-8E (hex) Halytech Mace +00118E (base 16) Halytech Mace + Unit 11, 22 Lexington Drive + Baulkham Hills NSW 2153 + AU + +00-11-86 (hex) Prime Systems, Inc. +001186 (base 16) Prime Systems, Inc. + 16267-333 + Suwa-gun Hara-mura Nagano 391-0100 + JP + +00-11-83 (hex) Datalogic ADC, Inc. +001183 (base 16) Datalogic ADC, Inc. + 959 Terry St + Eugene OR 97402 + US + +00-11-7D (hex) ZMD America, Inc. +00117D (base 16) ZMD America, Inc. + 15373 Innovation Drive + San Dieo CA 92128 + US + +00-11-7F (hex) Neotune Information Technology Corporation,.LTD +00117F (base 16) Neotune Information Technology Corporation,.LTD + 1703# No.737 North of Caoxi Rd. + Shanghai 200030 + CN + +00-11-9D (hex) Diginfo Technology Corporation +00119D (base 16) Diginfo Technology Corporation + 10Fl., No.82, Fu Hsing North Road + Taipei 106 + TW + +00-11-9C (hex) EP&T Energy +00119C (base 16) EP&T Energy + 358 Eastern Valley Way + Sydney NSW 2067 + AU + +00-11-9A (hex) Alkeria srl +00119A (base 16) Alkeria srl + 25 Via Giuntini + Navacchio (PI) I-56023 + IT + +00-11-C1 (hex) 4P MOBILE DATA PROCESSING +0011C1 (base 16) 4P MOBILE DATA PROCESSING + VIALE REGIONE VENETO 26 + PADOVA PD 35127 + IT + +00-11-B2 (hex) 2001 Technology Inc. +0011B2 (base 16) 2001 Technology Inc. + 7F-10, 79 Hsin Tai 5th. Rd. Sec.1 + Hsi Chih Taipei County 221 + TW + +00-11-AF (hex) Medialink-i,Inc +0011AF (base 16) Medialink-i,Inc + 1-9-10 Hamamatsu-Cho + Minato-Ku Tokyo 105-0013 + JP + +00-11-5E (hex) ProMinent Dosiertechnik GmbH +00115E (base 16) ProMinent Dosiertechnik GmbH + Im Schumachergewann 5-11 + Heidelberg BW 69123 + DE + +00-11-7C (hex) e-zy.net +00117C (base 16) e-zy.net + Smirnis 14 + Veria Imathia 59100 + GR + +00-11-39 (hex) STOEBER ANTRIEBSTECHNIK GmbH + Co. KG. +001139 (base 16) STOEBER ANTRIEBSTECHNIK GmbH + Co. KG. + Kieselbronner Str. 12 + Pforzheim 75177 + DE + +00-11-3E (hex) JL Corporation +00113E (base 16) JL Corporation + 4-4-17 SUGE + KAWASAKI-CITY KANAGAWA-KEN 214-0001 + JP + +00-11-38 (hex) TAISHIN CO., LTD. +001138 (base 16) TAISHIN CO., LTD. + 200-7 Nakano + Nakano Nagano 383-0013 + JP + +00-11-36 (hex) Goodrich Sensor Systems +001136 (base 16) Goodrich Sensor Systems + 14300 Judicial Road + Burnsville Minnesota 55306-4898 + US + +00-11-32 (hex) Synology Incorporated +001132 (base 16) Synology Incorporated + 6F-2, No.106, Chang An W. Rd., + Taipei 103 + TW + +00-11-4B (hex) Francotyp-Postalia GmbH +00114B (base 16) Francotyp-Postalia GmbH + Triftweg 21-26 + Birkenwerder Brandenburg 16547 + DE + +00-11-47 (hex) Secom-Industry co.LTD. +001147 (base 16) Secom-Industry co.LTD. + Fukuoka Kuramoto Ichihonki 3-3 + Shiroishi Miyagi 989-0295 + JP + +00-11-4A (hex) KAYABA INDUSTRY Co,.Ltd. +00114A (base 16) KAYABA INDUSTRY Co,.Ltd. + World Trade Center Bldg., 4-1 + Minato-ku, Tokyo Meto. 105-6111 + JP + +00-11-42 (hex) e-SMARTCOM INC. +001142 (base 16) e-SMARTCOM INC. + 3F, 216, Imok-Dong + Suwon Kyoungki-Do 440-310 + KR + +00-11-20 (hex) Cisco Systems, Inc +001120 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-11-18 (hex) BLX IC Design Corp., Ltd. +001118 (base 16) BLX IC Design Corp., Ltd. + Rm 1006, Quantum Plaza + Beijing 100083 + CN + +00-11-07 (hex) RGB Networks Inc. +001107 (base 16) RGB Networks Inc. + 2929 Campus Drive + San Mateo CA 94403 + US + +00-11-08 (hex) Orbital Data Corporation +001108 (base 16) Orbital Data Corporation + 1900 S. Norfolk St. Ste 320 + San Mateo CA 94403 + US + +00-11-0C (hex) Atmark Techno, Inc. +00110C (base 16) Atmark Techno, Inc. + 2F SD BLDG, 2-2-3-14 Atsubetsu-nishi, Atsubetsu-ku + Sapporo Hokkaido 004-0062 + JP + +00-11-4D (hex) Atsumi Electric Co.,LTD. +00114D (base 16) Atsumi Electric Co.,LTD. + 4-2-2 Shin-Miyakoda, Kita-ku + Hamamatsu Shizuoka 431-2103 + JP + +00-11-30 (hex) Allied Telesis (Hong Kong) Ltd. +001130 (base 16) Allied Telesis (Hong Kong) Ltd. + Room F, 3/F, Yeung Yiu Chong (no. 8) Industrial building, + + HK + +00-11-29 (hex) Paradise Datacom Ltd. +001129 (base 16) Paradise Datacom Ltd. + 1 Wheaton Road + Witham Essex UK CM8 1UJ + GB + +00-11-57 (hex) Oki Electric Industry Co., Ltd. +001157 (base 16) Oki Electric Industry Co., Ltd. + 1-7-12 Toranomon + Tokyo 105-8460 + JP + +00-0F-D9 (hex) FlexDSL Telecommunications AG +000FD9 (base 16) FlexDSL Telecommunications AG + Haus zum Engel + Altendorf Schwyz 8852 + CH + +00-0F-D0 (hex) ASTRI +000FD0 (base 16) ASTRI + 18/F Tower 6, Gateway, 9 Canton Rd + + HK + +00-0F-CA (hex) A-JIN TECHLINE CO, LTD +000FCA (base 16) A-JIN TECHLINE CO, LTD + 327-35 + Kumchun-Ku Seoul 153-802 + KR + +00-0F-EC (hex) ARKUS Inc. +000FEC (base 16) ARKUS Inc. + 3-8 Chuo-cho + 3-8 Noda, Kitaa-Ku 700-0971 + JP + +00-0F-ED (hex) Anam Electronics Co., Ltd +000FED (base 16) Anam Electronics Co., Ltd + 645 Sungkok-dong + Ansan-city Kyungki-do 425-834 + KR + +00-0F-E5 (hex) MERCURY SECURITY CORPORATION +000FE5 (base 16) MERCURY SECURITY CORPORATION + 2355 MIRA MAR AVE. + LONG BEACH CA 90815 + US + +00-0F-AE (hex) E2O Communications +000FAE (base 16) E2O Communications + 52 Serangoon North Ave 4 + 555853 + SG + +00-0F-B1 (hex) Cognio Inc. +000FB1 (base 16) Cognio Inc. + 101 Orchard Ridge Drive + Gaithersburg MD 20878 + US + +00-0F-A7 (hex) Raptor Networks Technology +000FA7 (base 16) Raptor Networks Technology + 65 Enterprise Road + Aliso Viejo CA 92656 + US + +00-0F-F0 (hex) Sunray Co. Ltd. +000FF0 (base 16) Sunray Co. Ltd. + Osawa2-5-5 Mitaka + Tokyo 181-0015 + JP + +00-11-03 (hex) kawamura electric inc. +001103 (base 16) kawamura electric inc. + 3-86 akatsuki-cho + seto aichi 489-0071 + JP + +00-0F-DD (hex) SORDIN AB +000FDD (base 16) SORDIN AB + Rorlaggarvagen 8 + Varnamo Smaland S-331 34 + SE + +00-0F-C3 (hex) PalmPalm Technology, Inc. +000FC3 (base 16) PalmPalm Technology, Inc. + Samsung-dong 156-3, Gangnam-gu + Seoul 135-091 + KR + +00-0F-88 (hex) AMETEK, Inc. +000F88 (base 16) AMETEK, Inc. + 150 Freeport Road + Pittsburgh PA 15238 + US + +00-0F-7E (hex) Ablerex Electronics Co., LTD +000F7E (base 16) Ablerex Electronics Co., LTD + 1F, No.3 Lane 7, Paokao Rd. + Hsintien Taipei Hsien 23114 + TW + +00-0F-83 (hex) Brainium Technologies Inc. +000F83 (base 16) Brainium Technologies Inc. + #201 - 11491 Kingston Street + Maple Ridge BC V2X 0Y6 + CA + +00-0F-84 (hex) Astute Networks, Inc. +000F84 (base 16) Astute Networks, Inc. + 15015 Ave of Science + San Diego CA 92128 + US + +00-0F-5C (hex) Day One Digital Media Limited +000F5C (base 16) Day One Digital Media Limited + 197 Archers Rd + Auckland North Island 1310 + NZ + +00-0F-52 (hex) YORK Refrigeration, Marine & Controls +000F52 (base 16) YORK Refrigeration, Marine & Controls + Jens Juulsvej 28 + Viby J DK 8362 + DK + +00-0F-4C (hex) Elextech INC +000F4C (base 16) Elextech INC + 554-2, Gasan-Dong, Gumcheon-Gu + Seoul 153-023 + KR + +00-0F-93 (hex) Landis+Gyr Ltd. +000F93 (base 16) Landis+Gyr Ltd. + Feldstrasse 1 + Zug CH-6301 + CH + +00-0F-94 (hex) Genexis BV +000F94 (base 16) Genexis BV + Lodewijktraat 1A + 5652 AC Eindhoven + SE + +00-0F-6C (hex) ADDI-DATA GmbH +000F6C (base 16) ADDI-DATA GmbH + Airport Boulevard B210 + RHEINMUENSTER BW 77836 + DE + +00-0F-8F (hex) Cisco Systems, Inc +000F8F (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0F-7D (hex) Xirrus +000F7D (base 16) Xirrus + 310 North Westlake Blvd. + Westlake Village CA 91362 + US + +00-0F-76 (hex) Digital Keystone, Inc. +000F76 (base 16) Digital Keystone, Inc. + 1975 El Camino Real + Mountain View CA 94040 + US + +00-0F-9E (hex) Murrelektronik GmbH +000F9E (base 16) Murrelektronik GmbH + Falkenstraße 3 + Oppenweiler Baden-Württemberg 71570 + DE + +00-0F-79 (hex) Bluetooth Interest Group Inc. +000F79 (base 16) Bluetooth Interest Group Inc. + 4F, No. 9, Alley 2, Lane 35, Ji-Hu Rd. + Taipei 114 + TW + +00-0F-17 (hex) Insta Elektro GmbH +000F17 (base 16) Insta Elektro GmbH + Hohe Steinert 10 + Luedenscheid NRW 58509 + DE + +00-0F-1E (hex) Chengdu KT Electric Co.of High & New Technology +000F1E (base 16) Chengdu KT Electric Co.of High & New Technology + No.2 Gaopeng Dong Road,High & New Development Zone + Chengdu Sichuan 610041 + CN + +00-0F-15 (hex) Icotera A/S +000F15 (base 16) Icotera A/S + Vibeholms Allé 16 + Brøndby 2605 + DK + +00-0F-39 (hex) IRIS SENSORS +000F39 (base 16) IRIS SENSORS + ZA les Ufernets + TOULAUD Ardeche F07130 + FR + +00-0F-3E (hex) CardioNet, Inc +000F3E (base 16) CardioNet, Inc + 1010 Second Avenue + San Diego CA 92101 + US + +00-0F-3F (hex) Big Bear Networks +000F3F (base 16) Big Bear Networks + 345 Potrero Ave + Sunny Vale California 94085 + US + +00-0F-35 (hex) Cisco Systems, Inc +000F35 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0F-36 (hex) Accurate Techhnologies, Inc. +000F36 (base 16) Accurate Techhnologies, Inc. + 47199 Cartier Dr. + Wixom Michigan 48393 + US + +00-0F-28 (hex) Itronix Corporation +000F28 (base 16) Itronix Corporation + South 801 Stevens Street + Spokane WA 99204 + US + +00-0F-23 (hex) Cisco Systems, Inc +000F23 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0F-22 (hex) Helius, Inc. +000F22 (base 16) Helius, Inc. + 333 South 520 West + Lindon UT 84042 + US + +00-0F-24 (hex) Cisco Systems, Inc +000F24 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0E-FC (hex) JTAG Technologies B.V. +000EFC (base 16) JTAG Technologies B.V. + Boschdijk 50 + Eindhoven NB 5612 AN + NL + +00-0E-FE (hex) EndRun Technologies LLC +000EFE (base 16) EndRun Technologies LLC + 2270 Northpoint Parkway + Santa Rosa CA 95407 + US + +00-0F-2C (hex) Uplogix, Inc. +000F2C (base 16) Uplogix, Inc. + Bldg 1, Suite 235 + Austin TX 78730 + US + +00-0F-2B (hex) GREENBELL SYSTEMS +000F2B (base 16) GREENBELL SYSTEMS + 2TH Floor, Doonam Bldg, 236-11 Nonhyun-Dong, Kangnam-Ku + Seoul 135-010 + KR + +00-0E-F2 (hex) Infinico Corporation +000EF2 (base 16) Infinico Corporation + 4F, F-1 Bldg., 1-2-12, + Tokyo 105-0013 + JP + +00-0F-0D (hex) Hunt Electronic Co., Ltd. +000F0D (base 16) Hunt Electronic Co., Ltd. + 6FI, NO. 57-59, Jiun H Sien Rd., Chi Tu District + Keelung Taiwan 206 + TW + +00-0F-08 (hex) Indagon Oy +000F08 (base 16) Indagon Oy + Nuijamiestentie 5 A + Helsinki - 00400 + FI + +00-0F-04 (hex) cim-usa inc +000F04 (base 16) cim-usa inc + 10813 nw 30th street + miami florida 33172 + US + +00-0F-42 (hex) Xalyo Systems +000F42 (base 16) Xalyo Systems + Grenier 9 + Commugny VD 1291 + CH + +00-0E-A5 (hex) BLIP Systems +000EA5 (base 16) BLIP Systems + Haekken 2 + Vodskov Vester Hassing 9310 + DK + +00-0E-A0 (hex) NetKlass Technology Inc. +000EA0 (base 16) NetKlass Technology Inc. + 2F-1, No.30,Tai Yuen Street, + Chupei City, Hsinchu, 302 + TW + +00-0E-E4 (hex) BOE TECHNOLOGY GROUP CO.,LTD +000EE4 (base 16) BOE TECHNOLOGY GROUP CO.,LTD + No.10 Jiuxianqiao Road,Chaoyang District,Beijing,PRC + Beijing 100016 + CN + +00-0E-DE (hex) REMEC, Inc. +000EDE (base 16) REMEC, Inc. + 2144 Franklin Drive NE + Palm Bay Florida 32905-4021 + US + +00-0E-9C (hex) Benchmark Electronics +000E9C (base 16) Benchmark Electronics + 3535 Technology Drive + Rochester MN 55901 + US + +00-0E-9A (hex) BOE TECHNOLOGY GROUP CO.,LTD +000E9A (base 16) BOE TECHNOLOGY GROUP CO.,LTD + No.10 Jiuxianqiao Road,Chaoyang District,Beijing,PRC + Beijing 100016 + CN + +00-0E-90 (hex) PONICO CORP. +000E90 (base 16) PONICO CORP. + 602, Ace Twin Tower 1, 212-1 Guro-dong + Gurogu Seoul 152-766 + KR + +00-0E-8A (hex) Avara Technologies Pty. Ltd. +000E8A (base 16) Avara Technologies Pty. Ltd. + 9 Business Park Drive + Notting Hill Victoria 3168 + AU + +00-0E-B8 (hex) Iiga co.,Ltd +000EB8 (base 16) Iiga co.,Ltd + 3F TKBldg. 3-5-2 Sotokanda + Chiyoda-Ku Tokyo 101-0021 + JP + +00-0E-BE (hex) B&B Electronics Manufacturing Co. +000EBE (base 16) B&B Electronics Manufacturing Co. + 707 Dayton Road + Ottawa Ilinois 61350 + US + +00-0E-BB (hex) Everbee Networks +000EBB (base 16) Everbee Networks + 41, Boulevard des Capucines + Paris 75002 + FR + +00-0E-CE (hex) S.I.T.T.I. S.p.A. +000ECE (base 16) S.I.T.T.I. S.p.A. + Via Cadorna 69 + Vimodrone Milan I-20090 + IT + +00-0E-D4 (hex) CRESITT INDUSTRIE +000ED4 (base 16) CRESITT INDUSTRIE + 12 rue de Blois + Orleans BP 6744 45067 cedex + FR + +00-0E-D6 (hex) Cisco Systems, Inc +000ED6 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0E-D8 (hex) Positron Access Solutions Corp +000ED8 (base 16) Positron Access Solutions Corp + 5101 Buchan Street + Montreal, Quebec H4P 2R9 + CA + +00-0E-D1 (hex) Osaka Micro Computer. +000ED1 (base 16) Osaka Micro Computer. + Isonokamicyo 3-11-7 + Kishiwada Osaka 5960001 + JP + +00-0E-B0 (hex) Solutions Radio BV +000EB0 (base 16) Solutions Radio BV + Prinsegracht 82 + The Hague ZH 2512 GC + NL + +00-0E-83 (hex) Cisco Systems, Inc +000E83 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0E-81 (hex) Devicescape Software, Inc. +000E81 (base 16) Devicescape Software, Inc. + 1000 Marina Blvd + Brisbane CA 94005 + US + +00-0E-88 (hex) VIDEOTRON CORP. +000E88 (base 16) VIDEOTRON CORP. + 17-16,2-CHOME + HACHIOJI TOKYO 193-0835 + JP + +00-0E-86 (hex) Alcatel North America +000E86 (base 16) Alcatel North America + 2301 Sugar Bush Road + Raleigh NC 27612 + US + +00-0E-69 (hex) China Electric Power Research Institute +000E69 (base 16) China Electric Power Research Institute + No.15 Xiaoying East Road,Qinghe,Beijing,China + Beijing 100085 + CN + +00-0E-61 (hex) MICROTROL LIMITED +000E61 (base 16) MICROTROL LIMITED + 16 ELGAR BUSINESS CENTRE + HALLOW WORCESTER WR2 6NJ + GB + +00-0E-64 (hex) Elphel, Inc +000E64 (base 16) Elphel, Inc + 3200 S. Elpmer St. + Magna UT 84044 + US + +00-0E-49 (hex) Forsway Scandinavia AB +000E49 (base 16) Forsway Scandinavia AB + Kanikegränd 3B + 541 34 Skövde + SE + +00-0E-42 (hex) Motic Incoporation Ltd. +000E42 (base 16) Motic Incoporation Ltd. + Room 2907-8, Windsor House + Hong Kong + CN + +00-0E-3D (hex) Televic N.V. +000E3D (base 16) Televic N.V. + Leo Bekaertlaan 1 + Izegem 8870 + BE + +00-0E-39 (hex) Cisco Systems, Inc +000E39 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0E-34 (hex) NexGen City, LP +000E34 (base 16) NexGen City, LP + 1680 Glenville + Richardson Texas 75081 + US + +00-0E-6A (hex) 3Com Ltd +000E6A (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +00-0E-5A (hex) TELEFIELD inc. +000E5A (base 16) TELEFIELD inc. + 3F, Kumbo Bldg, 2-9, Seokchon-Dong + Seoul 138-190 + KR + +00-0E-5D (hex) Triple Play Technologies A/S +000E5D (base 16) Triple Play Technologies A/S + Herstedvang 8 + Albertslund DK-2620 + DK + +00-0E-52 (hex) Optium Corporation +000E52 (base 16) Optium Corporation + 500 Horizon Dr + Chalfont PA 18914 + US + +00-0E-7E (hex) ionSign Oy +000E7E (base 16) ionSign Oy + P.O.BOX 246 + Rauma + FI + +00-0E-77 (hex) Decru, Inc. +000E77 (base 16) Decru, Inc. + 275 Shoreline Dr + Redwood City CA 94065 + US + +00-0E-4D (hex) Numesa Inc. +000E4D (base 16) Numesa Inc. + 4444 Westgrove Suite 300 + Addison TX 75001 + US + +00-0E-4C (hex) Bermai Inc. +000E4C (base 16) Bermai Inc. + 410 Cambridge Ave + Palo Alto CA 94306 + US + +00-0E-2D (hex) Hyundai Digital Technology Co.,Ltd. +000E2D (base 16) Hyundai Digital Technology Co.,Ltd. + 223-22, Sangdaewon-1dong, Jungwon-gu + Seongnam-si Kyoungki-do 462-807 + KR + +00-0E-30 (hex) AERAS Networks, Inc. +000E30 (base 16) AERAS Networks, Inc. + P.O. Box 7330 + Laguna Niguel CA 92607-7330 + US + +00-0E-29 (hex) Shester Communications Inc +000E29 (base 16) Shester Communications Inc + 159 S. Lincoln + Spokane WA 99201 + US + +00-0D-E1 (hex) Control Products, Inc. +000DE1 (base 16) Control Products, Inc. + 1724 Lake Drive West + Chanhassen MN 55317 + US + +00-0D-D0 (hex) TetraTec Instruments GmbH +000DD0 (base 16) TetraTec Instruments GmbH + Gewerbestrasse 8 + Steinenbronn BW 71144 + DE + +00-0D-D3 (hex) SAMWOO Telecommunication Co.,Ltd. +000DD3 (base 16) SAMWOO Telecommunication Co.,Ltd. + + Gunpo Kyoung-Gi 435-831 + KR + +00-0D-D8 (hex) BBN +000DD8 (base 16) BBN + 7F-3,NO.186, Jian Yi Rd ., Chung Ho City + Taipei 235 + TW + +00-0D-B3 (hex) SDO Communication Corperation +000DB3 (base 16) SDO Communication Corperation + 6F, No.112, Shin Min Street + Chung Ho City Taipei Hsien 235 + TW + +00-0D-AE (hex) SAMSUNG HEAVY INDUSTRIES CO., LTD. +000DAE (base 16) SAMSUNG HEAVY INDUSTRIES CO., LTD. + 493, Banweol-Ri, Taean-Eup + Hwaseong-City Kyeonggi-Do 445-973 + KR + +00-0D-B2 (hex) Ammasso, Inc. +000DB2 (base 16) Ammasso, Inc. + 345 Summer Street + Boston MA 02210 + US + +00-0E-0D (hex) Hesch Schröder GmbH +000E0D (base 16) Hesch Schröder GmbH + Boschstraße 8 + Neustadt Niedersachsen 31535 + DE + +00-0D-F6 (hex) Technology Thesaurus Corp. +000DF6 (base 16) Technology Thesaurus Corp. + NO. 6, East 4th St. KEPZ + KAOHSIUNG 806 + TW + +00-0D-FF (hex) CHENMING MOLD INDUSTRY CORP. +000DFF (base 16) CHENMING MOLD INDUSTRY CORP. + 2F No. 26, Lane 513, Rei Kuang Rd. + Taipei 114 + TW + +00-0D-C7 (hex) COSMIC ENGINEERING INC. +000DC7 (base 16) COSMIC ENGINEERING INC. + 1-3-5, Nishihirayama + Hino-shi TOKYO 191-0055 + JP + +00-0D-C2 (hex) Private +000DC2 (base 16) Private + +00-0D-BF (hex) TekTone Sound & Signal Mfg., Inc. +000DBF (base 16) TekTone Sound & Signal Mfg., Inc. + 277 Industrial Park Rd. + Franklin NC 28734 + US + +00-0E-19 (hex) LogicaCMG Pty Ltd +000E19 (base 16) LogicaCMG Pty Ltd + 17-19 Orion Road + Lane Cove NSW 2066 + AU + +00-0E-1A (hex) JPS Communications +000E1A (base 16) JPS Communications + 5800 Departure Drive + Raleigh NC 27616 + US + +00-0E-06 (hex) Team Simoco Ltd +000E06 (base 16) Team Simoco Ltd + Field House + Derby Derbyshire DE1 1NH + GB + +00-0D-5C (hex) Robert Bosch GmbH, VT-ATMO +000D5C (base 16) Robert Bosch GmbH, VT-ATMO + Wernerstrasse 51 + Stuttgart BW 70469 + DE + +00-0D-60 (hex) IBM Corp +000D60 (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-0D-67 (hex) Ericsson +000D67 (base 16) Ericsson + 349 Terry Fox Drive + Kanata Ottawa K2K 2V6 + CA + +00-0D-5F (hex) Minds Inc +000D5F (base 16) Minds Inc + 1919 boul lionel bertrand + Boisbriand Quebec J7H 1N8 + CA + +00-0D-9C (hex) Elan GmbH & Co KG +000D9C (base 16) Elan GmbH & Co KG + Im Ostpark 2 + Wettenberg Hessen 35435 + DE + +00-0D-98 (hex) S.W.A.C. Schmitt-Walter Automation Consult GmbH +000D98 (base 16) S.W.A.C. Schmitt-Walter Automation Consult GmbH + Oedenpullach 1 + Oberhaching Bavaria 82041 + DE + +00-0D-8C (hex) Shanghai Wedone Digital Ltd. CO. +000D8C (base 16) Shanghai Wedone Digital Ltd. CO. + 893-899 Huashan Road, + Shanghai 200031 + CN + +00-0D-94 (hex) AFAR Communications,Inc +000D94 (base 16) AFAR Communications,Inc + 81 David Love Place + Santa Barbara CA 93117 + US + +00-0D-AA (hex) S.A.Tehnology co.,Ltd. +000DAA (base 16) S.A.Tehnology co.,Ltd. + 80-12 Yangjae 1 Dong + Seoul South Korea 137-890 + KR + +00-0D-A6 (hex) Universal Switching Corporation +000DA6 (base 16) Universal Switching Corporation + 7671 San Fernando Rd + Burbank CA 91505-1073 + US + +00-0D-8D (hex) Prosoft Technology, Inc +000D8D (base 16) Prosoft Technology, Inc + 5201 Truxtun Ave + Bakersfield CA 93300 + US + +00-0D-84 (hex) Makus Inc. +000D84 (base 16) Makus Inc. + 4F Daedo Bldg., 748-14 Yeoksam-dong + Kangnam-gu Seoul 135-080 + KR + +00-0D-73 (hex) Technical Support, Inc. +000D73 (base 16) Technical Support, Inc. + 11253 John Galt Blvd + Omaha Nebraska 68137 + US + +00-0D-69 (hex) TMT&D Corporation +000D69 (base 16) TMT&D Corporation + 2-24-1 + Fuchu-si Tokyo 183-0057 + JP + +00-0D-A2 (hex) Infrant Technologies, Inc. +000DA2 (base 16) Infrant Technologies, Inc. + 48820 Kato Road + Fremont CA 94538 + US + +00-0D-68 (hex) Vinci Systems, Inc. +000D68 (base 16) Vinci Systems, Inc. + 8330 Boone Boulevard + Vienna VA 22182 + US + +00-0D-64 (hex) COMAG Handels AG +000D64 (base 16) COMAG Handels AG + Zillenhardtstraße 41 + Goeppingen Baden-Württemberg 73037 + DE + +00-0D-74 (hex) Sand Network Systems, Inc. +000D74 (base 16) Sand Network Systems, Inc. + 434 Payran Street, Suite B + Petaluma CA 94952 + US + +00-0D-7D (hex) Afco Systems +000D7D (base 16) Afco Systems + 200 Finn Court + Farmingdale NY 11735 + US + +00-0D-54 (hex) 3Com Ltd +000D54 (base 16) 3Com Ltd + Peoplebuilding 2 + Hemel Hempstead Herts HP2 4NW + GB + +00-0D-4C (hex) Outline Electronics Ltd. +000D4C (base 16) Outline Electronics Ltd. + 7/F Benson Tower + Kwun Tong Kowloon + HK + +00-0D-0F (hex) Finlux Ltd +000D0F (base 16) Finlux Ltd + Radiomiehenkatu 3 + Turku FIN-20321 + FI + +00-0D-12 (hex) AXELL Corporation +000D12 (base 16) AXELL Corporation + Akihabara UDX South Wing 10F + Chiyoda-ku Tokyo 101-8973 + JP + +00-0D-34 (hex) Shell International Exploration and Production, Inc. +000D34 (base 16) Shell International Exploration and Production, Inc. + BTC-Gasmer + Houston TX 77001 + US + +00-0D-32 (hex) DispenseSource, Inc. +000D32 (base 16) DispenseSource, Inc. + 29801 Santa Margarita Parkway + Rancho Santa Margarita CA 92688 + US + +00-0C-F6 (hex) Sitecom Europe BV +000CF6 (base 16) Sitecom Europe BV + Sevillaweg 122 + Rotterdam ZH 3047 AL + NL + +00-0C-F2 (hex) GAMESA Eólica +000CF2 (base 16) GAMESA Eólica + Polígono Agustinos. C/ A s/n. + Pamplona NAVARRA 31013 + ES + +00-0D-2E (hex) Matsushita Avionics Systems Corporation +000D2E (base 16) Matsushita Avionics Systems Corporation + 26200 Enterprise Way + Lake Forest CA 92630 + US + +00-0D-28 (hex) Cisco Systems, Inc +000D28 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0D-4D (hex) Ninelanes +000D4D (base 16) Ninelanes + #405 4F Diplomatic Center + Seoul 1376-1 + KR + +00-0D-53 (hex) Beijing 5w Communication Corp. +000D53 (base 16) Beijing 5w Communication Corp. + NO.4,Zhong-Guan-Cun South 4 street, + Beijing 100080 + CN + +00-0C-FC (hex) S2io Technologies Corp +000CFC (base 16) S2io Technologies Corp + 505 March Rd + Ottawa Ontario K2K 2M5 + CA + +00-0D-38 (hex) NISSIN INC. +000D38 (base 16) NISSIN INC. + 10-7 KAMEI-CHO + TAKARAZUKA HYOGO 665-0047 + JP + +00-0D-15 (hex) Voipac s.r.o. +000D15 (base 16) Voipac s.r.o. + Ul. Janka Krala 3 + Trencin 911 01 + SK + +00-0C-A1 (hex) SIGMACOM Co., LTD. +000CA1 (base 16) SIGMACOM Co., LTD. + DacomBldg 7F 200-12 Anyang-dong + 430-817 + KR + +00-0C-A6 (hex) Mintera Corporation +000CA6 (base 16) Mintera Corporation + 847 Rogers Street + Lowell MA 01852 + US + +00-0C-C1 (hex) Eaton Corporation +000CC1 (base 16) Eaton Corporation + 2300 Badger Drive + Waukesha WI 53188 + US + +00-0C-8B (hex) Connect Tech Inc +000C8B (base 16) Connect Tech Inc + 42 Arrow Road + Guelph Ontario N1K 1S6 + CA + +00-0C-90 (hex) Octasic Inc. +000C90 (base 16) Octasic Inc. + 4101 Molson St. + Montreal Quebec H1Y 3L1 + CA + +00-0C-8C (hex) KODICOM CO.,LTD. +000C8C (base 16) KODICOM CO.,LTD. + A-Dong 5FI.,SK Twin Tower 345-9, + Seoul 153-023 + KR + +00-0C-C2 (hex) ControlNet (India) Private Limited +000CC2 (base 16) ControlNet (India) Private Limited + L-44, Unit - I + Verna, Salcete Goa 403 722 + IN + +00-0C-94 (hex) United Electronic Industries, Inc. (EUI) +000C94 (base 16) United Electronic Industries, Inc. (EUI) + 27 Renmar Ave + Walpole MA 02081 + US + +00-0C-9B (hex) EE Solutions, Inc +000C9B (base 16) EE Solutions, Inc + 8F, No. 9, Park II Ave., Science-Based I + Hsin Chu 300 + TW + +00-0C-E1 (hex) The Open Group +000CE1 (base 16) The Open Group + Apex Plaza + Reading Berks RG1 1AX + GB + +00-0C-DC (hex) BECS Technology, Inc +000CDC (base 16) BECS Technology, Inc + 9487 Dielman Rock Island Industrial Driv + St. Louis MO 63132 + US + +00-0C-C5 (hex) Nextlink Co., Ltd. +000CC5 (base 16) Nextlink Co., Ltd. + C 605, Technopark #145 Yatop-dong, + Seongnam-si Bundang-gu, Gyeonggi 463-760 + KR + +00-0C-DE (hex) ABB STOTZ-KONTAKT GmbH +000CDE (base 16) ABB STOTZ-KONTAKT GmbH + Eppelheimer Straße 82 + Heidelberg Baden-Württemberg 69123 + DE + +00-0C-BF (hex) Holy Stone Ent. Co., Ltd. +000CBF (base 16) Holy Stone Ent. Co., Ltd. + 1F, No.62, Sec.2, Huang Shan Rd., + Taipei 114 + US + +00-0C-4D (hex) Curtiss-Wright Controls Avionics & Electronics +000C4D (base 16) Curtiss-Wright Controls Avionics & Electronics + Landscape House, + Churchtown, Dublin 14 + IE + +00-0C-44 (hex) Automated Interfaces, Inc. +000C44 (base 16) Automated Interfaces, Inc. + 120 Confederate Lane + Greer South Carolina 29651 + US + +00-0C-3B (hex) Orion Electric Co., Ltd. +000C3B (base 16) Orion Electric Co., Ltd. + 41-1, Iehisa-cho + Takefu-shi Fukui 915-8555 + JP + +00-0C-71 (hex) Wybron, Inc +000C71 (base 16) Wybron, Inc + 4830 LIst Dr + Colorado Springs Colorado 80919 + US + +00-0C-72 (hex) Tempearl Industrial Co., Ltd. +000C72 (base 16) Tempearl Industrial Co., Ltd. + 3-1-42 Ohzu + Hiroshima-shi Hiroshima 732-0802 + JP + +00-0C-78 (hex) In-Tech Electronics Limited +000C78 (base 16) In-Tech Electronics Limited + Unit A, 13th Floor., Wing Tai Centre + Kwun Tong Kowloon + HK + +00-0C-59 (hex) Indyme Electronics, Inc. +000C59 (base 16) Indyme Electronics, Inc. + 9085 Aero Dr. + San Diego CA 92123 + US + +00-0C-5C (hex) GTN Systems B.V. +000C5C (base 16) GTN Systems B.V. + Postbus 12236 + Amsterdam + NL + +00-0C-55 (hex) Microlink Communications Inc. +000C55 (base 16) Microlink Communications Inc. + 8F, 31, Hsintai Road + Hsinchu 302 + TW + +00-0C-52 (hex) Roll Systems Inc. +000C52 (base 16) Roll Systems Inc. + 53 Third Avenue + Burlington MA 01803 + US + +00-0C-74 (hex) RIVERTEC CORPORATION +000C74 (base 16) RIVERTEC CORPORATION + 882-5 MIYAGASAKI + IMABARI EHIME 799-1537 + JP + +00-0C-67 (hex) OYO ELECTRIC CO.,LTD +000C67 (base 16) OYO ELECTRIC CO.,LTD + 63-1 Nakamichi Omote + Joyo Kyoto 610-0101 + JP + +00-0C-2E (hex) Openet information technology(shenzhen) Co., Ltd. +000C2E (base 16) Openet information technology(shenzhen) Co., Ltd. + 2/F,A tower,international tech-innovatio + shenzhen guangdong 518057 + CN + +00-0C-2C (hex) Enwiser Inc. +000C2C (base 16) Enwiser Inc. + 4F, Cheongseok B/D + Seoul Seoul 135-010 + KR + +00-0C-28 (hex) RIFATRON +000C28 (base 16) RIFATRON + 9th FL, SHINTAEYANG BLDG + SEOUL SEOCHO-GU 137-041 + KR + +00-0C-3D (hex) Glsystech Co., Ltd. +000C3D (base 16) Glsystech Co., Ltd. + Song Bo B/D 3F + Seoul + KR + +00-0C-2F (hex) SeorimTechnology Co.,Ltd. +000C2F (base 16) SeorimTechnology Co.,Ltd. + 2F DIPLOMATIC CENTER B/D 1376-1 SEOCHO2- + SEOUL 137-072 + US + +00-0C-31 (hex) Cisco Systems, Inc +000C31 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0C-53 (hex) Private +000C53 (base 16) Private + +00-0C-48 (hex) QoStek Corporation +000C48 (base 16) QoStek Corporation + 7F, 22, Taiyuen Street + Chupei Hsinchu Hsien 302 + TW + +00-0C-63 (hex) Zenith Electronics Corporation +000C63 (base 16) Zenith Electronics Corporation + 2000 Millbrook Drive + Lincolnshire Illinois 60069 + US + +00-0B-BB (hex) Etin Systems Co., Ltd +000BBB (base 16) Etin Systems Co., Ltd + 12F, IT Venture Tower, + Seoul 138-803 + KR + +00-0B-BC (hex) En Garde Systems, Inc. +000BBC (base 16) En Garde Systems, Inc. + 2101 White Cloud St. NE + Albuquerque NM 87112 + US + +00-0B-B1 (hex) Super Star Technology Co., Ltd. +000BB1 (base 16) Super Star Technology Co., Ltd. + No. 7 Lane 306,Sec. 2,Tai-Lin Rd. + Taipei Hsien 243 + US + +00-0B-BF (hex) Cisco Systems, Inc +000BBF (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-AD (hex) PC-PoS Inc. +000BAD (base 16) PC-PoS Inc. + 309 Commissioners Road West + London Ontario N6J 1Y4 + CA + +00-0B-A0 (hex) T&L Information Inc. +000BA0 (base 16) T&L Information Inc. + 898-44 Hokye-Dong, Dongan-Gu + Anyang Kyungki-Do 431-836 + KR + +00-0C-17 (hex) AJA Video Systems Inc +000C17 (base 16) AJA Video Systems Inc + 180 Litton Drive + Grass Valley CA 95945 + US + +00-0C-11 (hex) NIPPON DEMPA CO.,LTD. +000C11 (base 16) NIPPON DEMPA CO.,LTD. + 1-4-8 + kakegawa city shizuoka pref. 436-0028 + JP + +00-0C-14 (hex) Diagnostic Instruments, Inc. +000C14 (base 16) Diagnostic Instruments, Inc. + 6540 Burroughs + Sterling Heights MI 48314 + US + +00-0B-B5 (hex) nStor Technologies, Inc. +000BB5 (base 16) nStor Technologies, Inc. + 100 Technology Park + Lake Mary FL 32746 + US + +00-0B-B9 (hex) Imsys AB +000BB9 (base 16) Imsys AB + Johanneslundsvagen 3 + Upplands Vasby SE-19461 + SE + +00-0C-21 (hex) Faculty of Science and Technology, Keio University +000C21 (base 16) Faculty of Science and Technology, Keio University + 3-14-1 Hiyoshi, Kohoku-ku + Yokohama Kanagawa 223-8522 + JP + +00-0C-1B (hex) ORACOM Co, Ltd. +000C1B (base 16) ORACOM Co, Ltd. + 3rd Fl, A-Sung Bldg, 999-3 + Seoul 135-280 + KR + +00-0B-C9 (hex) Electroline Equipment +000BC9 (base 16) Electroline Equipment + 8265 boul. St-Michel + Montreal Quebec H1Z 3E4 + CA + +00-0B-C2 (hex) Corinex Communication Corp. +000BC2 (base 16) Corinex Communication Corp. + #308 1168 Hamilton Street + Vancouver B.C. V6B 2S2 + US + +00-0B-F7 (hex) NIDEK CO.,LTD +000BF7 (base 16) NIDEK CO.,LTD + 34-14 Maehama + Gamagori Aich 443-0038 + JP + +00-0C-00 (hex) BEB Industrie-Elektronik AG +000C00 (base 16) BEB Industrie-Elektronik AG + Progressastrasse 31 + Oberburg BE 3414 + CH + +00-0B-F3 (hex) BAE SYSTEMS +000BF3 (base 16) BAE SYSTEMS + 6500 Tracor Lane + Austin Texas 78725 + US + +00-0B-ED (hex) ELM Inc. +000BED (base 16) ELM Inc. + 2398 Kasedamiyahara + Minamisatsuma Kagoshima 897-1124 + JP + +00-0B-91 (hex) Aglaia Gesellschaft für Bildverarbeitung und Kommunikation mbH +000B91 (base 16) Aglaia Gesellschaft für Bildverarbeitung und Kommunikation mbH + Tiniusstraße 12-15 + Berlin D-13089 + DE + +00-0B-97 (hex) Matsushita Electric Industrial Co.,Ltd. +000B97 (base 16) Matsushita Electric Industrial Co.,Ltd. + 3-1-1 Yagumo-Naka-Machi + Moriguchi City Osaka 570-8501 + JP + +00-0B-92 (hex) Ascom Danmark A/S +000B92 (base 16) Ascom Danmark A/S + Fabriksparken 42 + Glostrup Denmark 2600 + DK + +00-0B-9A (hex) Shanghai Ulink Telecom Equipment Co. Ltd. +000B9A (base 16) Shanghai Ulink Telecom Equipment Co. Ltd. + 6 Floor, Building 3 + Shanghai 200083 + CN + +00-0B-9D (hex) TwinMOS Technologies Inc. +000B9D (base 16) TwinMOS Technologies Inc. + 303 No.3, Tzu Chiang Rd., Hu Kou Xiang, + Hsin Chu 303 + TW + +00-0B-96 (hex) Innotrac Diagnostics Oy +000B96 (base 16) Innotrac Diagnostics Oy + Kalevantie 25 + Turku Åbo 20520 + FI + +00-0B-56 (hex) Cybernetics +000B56 (base 16) Cybernetics + 111 Cybernetics Way STE 300 + Yorktown VA 23693 + US + +00-0B-50 (hex) Oxygnet +000B50 (base 16) Oxygnet + 402 E. Carrillo St. + Santa Barbara CA 93101 + US + +00-0B-52 (hex) JOYMAX ELECTRONICS CO. LTD. +000B52 (base 16) JOYMAX ELECTRONICS CO. LTD. + No.5 Dong-Yuan Road 2, Jhong-Li Industrial Park, + Tao-Yuan 32063 + TW + +00-0B-69 (hex) Franke Finland Oy +000B69 (base 16) Franke Finland Oy + Vartiokuja 1 + NAARAJARVI FIN-76850 + FI + +00-0B-A5 (hex) Quasar Cipta Mandiri, PT +000BA5 (base 16) Quasar Cipta Mandiri, PT + Jl. Palasari 9A + Bandung West Java 40262 + ID + +00-0B-49 (hex) RF-Link System Inc. +000B49 (base 16) RF-Link System Inc. + No.6, Nan-Ke 5th Rd., Hsin-Shi, + Tainan County 744 + TW + +00-0B-46 (hex) Cisco Systems, Inc +000B46 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0B-7A (hex) L-3 Linkabit +000B7A (base 16) L-3 Linkabit + 9890 Town Center Drive + San Diego CA 92121 + US + +00-0B-84 (hex) BODET +000B84 (base 16) BODET + Route de la Tourlandry + TREMENTINES FRANCE 49340 + FR + +00-0B-77 (hex) Cogent Systems, Inc. +000B77 (base 16) Cogent Systems, Inc. + 209 Fair Oaks Ave. + South Pasadena CA 91030 + US + +00-0B-66 (hex) Teralink Communications +000B66 (base 16) Teralink Communications + Capital Tower 15F, + Daejeon 302120 + KR + +00-0B-2C (hex) Eiki Industrial Co. Ltd. +000B2C (base 16) Eiki Industrial Co. Ltd. + 4-12 Manzai-cho, Kita-ku + Osaka 530 + JP + +00-0B-26 (hex) Wetek Corporation +000B26 (base 16) Wetek Corporation + 4F, NO.17, Kuanfu N. Road + Hsin Chu Industrial Park 303 + TW + +00-0B-28 (hex) Quatech Inc. +000B28 (base 16) Quatech Inc. + 662 Wolf Ledges Pkwy. + Akron OH 44311 + US + +00-0B-2A (hex) HOWTEL Co., Ltd. +000B2A (base 16) HOWTEL Co., Ltd. + J-COM Bd. 4F, 124-4 OJEON-DONG + UIWANG-SHI KYOUNGGI-DO 437-070 + KR + +00-0B-30 (hex) Beijing Gongye Science & Technology Co.,Ltd +000B30 (base 16) Beijing Gongye Science & Technology Co.,Ltd + Unit D.17/E,Shenlanhuating mid Road No.6 + Beijing 100029 + CN + +00-0A-F2 (hex) NeoAxiom Corp. +000AF2 (base 16) NeoAxiom Corp. + 1520 Montague Expressway + San Jose CA 95131 + US + +00-0A-F5 (hex) Airgo Networks, Inc. +000AF5 (base 16) Airgo Networks, Inc. + 900 Arastradero Rd + Palo Alto CA 94304 + US + +00-0A-F0 (hex) SHIN-OH ELECTRONICS CO., LTD. R&D +000AF0 (base 16) SHIN-OH ELECTRONICS CO., LTD. R&D + #729-5, Bonoh-Dong, Ansan-City, Kyunggi- + Ansan-City Kyunggi-Do 425-180 + KR + +00-0A-F4 (hex) Cisco Systems, Inc +000AF4 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0A-EE (hex) GCD Hard- & Software GmbH +000AEE (base 16) GCD Hard- & Software GmbH + Henkestraße 79 + Erlangen Bayern 91052 + DE + +00-0A-D8 (hex) IPCserv Technology Corp. +000AD8 (base 16) IPCserv Technology Corp. + 6f,No.107,Pan-Hsin Rd + Pan-Chiao Taipei 22046 + TW + +00-0A-D7 (hex) Origin ELECTRIC CO.,LTD. +000AD7 (base 16) Origin ELECTRIC CO.,LTD. + 1-18-1 + TOSHIMA WARD TOKYO MET. 171-8555 + JP + +00-0B-38 (hex) Knürr GmbH +000B38 (base 16) Knürr GmbH + Mariakirchener Straße 38 + Arnstorf Bavaria 94424 + DE + +00-0B-32 (hex) VORMETRIC, INC. +000B32 (base 16) VORMETRIC, INC. + 2060 CORPORATE CT + SAN JOSE CA 95131 + US + +00-0B-07 (hex) Voxpath Networks +000B07 (base 16) Voxpath Networks + 7600B Capital of Texas Highway - North + Austin Texas 78731 + US + +00-0B-04 (hex) Volktek Corporation +000B04 (base 16) Volktek Corporation + 4F., No.192, Lian-Chang Road, Chang-Ho + Taipei + TW + +00-0A-F9 (hex) HiConnect, Inc. +000AF9 (base 16) HiConnect, Inc. + Rm #906, Haksan Cosmostel, 110 + Kwangjin-Gu Seoul 143-802 + KR + +00-0B-1F (hex) I CON Computer Co. +000B1F (base 16) I CON Computer Co. + 3F, No. 142 , Hsin Ming Road + Neihu Taipei 114 + TW + +00-0B-13 (hex) ZETRON INC +000B13 (base 16) ZETRON INC + PO Box 97004 + REDMOND WA 98073 + US + +00-0B-10 (hex) 11wave Technonlogy Co.,Ltd +000B10 (base 16) 11wave Technonlogy Co.,Ltd + 10F,no.285 sec.2 ,Ti-Ding Ave,NaiHu.Taip + Taipei 114 + TW + +00-0A-E9 (hex) AirVast Technology Inc. +000AE9 (base 16) AirVast Technology Inc. + 3F.-5, No.6, Lane 609, Sec. 5, Chongsin Rd. + Sanchong City Taipei 241 + TW + +00-0B-2B (hex) HOSTNET CORPORATION +000B2B (base 16) HOSTNET CORPORATION + 10F-12,No. 12 Lane 609, Sec.5,Chunghsin + Sanchung Taipei Hsien 241 + TW + +00-0B-02 (hex) Dallmeier electronic +000B02 (base 16) Dallmeier electronic + Würzburgerstraße 5 + Regensburg Bavaria 93059 + DE + +00-0A-CD (hex) Sunrich Technology Limited +000ACD (base 16) Sunrich Technology Limited + Unit 1301, Eastern Centre, 1065 King's R + Quarry Bay + HK + +00-0A-CC (hex) Winnow Networks, Inc. +000ACC (base 16) Winnow Networks, Inc. + 701 Emerson Road + St. Louis MO 63141 + US + +00-0A-CF (hex) PROVIDEO Multimedia Co. Ltd. +000ACF (base 16) PROVIDEO Multimedia Co. Ltd. + 5F, NO.8, ALLEY 2, TZU-WEI LANE, + HSIN TIEN CITY TAIPEI HSIEN, 231 + TW + +00-0A-D1 (hex) MWS +000AD1 (base 16) MWS + 12, quai Papacino + NICE 06300 + FR + +00-0A-7D (hex) Valo, Inc. +000A7D (base 16) Valo, Inc. + 1351 Redwood Way + Petaluma CA 94954 + US + +00-0A-7F (hex) Teradon Industries, Inc +000A7F (base 16) Teradon Industries, Inc + 7500 2nd ST NW + Albuquerque NM 87120 + US + +00-0A-81 (hex) TEIMA Audiotex S.L. +000A81 (base 16) TEIMA Audiotex S.L. + C/ Tirvia, 6, local B + Madrid 28040 + ES + +00-0A-87 (hex) Integrated Micromachines Inc. +000A87 (base 16) Integrated Micromachines Inc. + 1400 S. Shamrock Ave. + Monrovia CA 91016 + US + +00-0A-77 (hex) Bluewire Technologies LLC +000A77 (base 16) Bluewire Technologies LLC + 420 N. O St. + Tulare Ca 93274 + US + +00-0A-8C (hex) Guardware Systems Ltd. +000A8C (base 16) Guardware Systems Ltd. + Ulloi ut 102. + Budapest H-1089 + HU + +00-0A-96 (hex) MEWTEL TECHNOLOGY INC. +000A96 (base 16) MEWTEL TECHNOLOGY INC. + E15FL. IT VENTURE TOWER + SEOUL 138-803 + KR + +00-0A-82 (hex) TATSUTA SYSTEM ELECTRONICS CO.,LTD. +000A82 (base 16) TATSUTA SYSTEM ELECTRONICS CO.,LTD. + IWATATYOU2-3-1 + HIGASHIOOSAKA-SHI OOSAKA-FU 578-8585 + JP + +00-0A-D3 (hex) INITECH Co., Ltd +000AD3 (base 16) INITECH Co., Ltd + 3F, INITECH Bldg, 559-5, + Seoul Songpa 138-816 + KR + +00-0A-C8 (hex) ZPSYS CO.,LTD. (Planning&Management) +000AC8 (base 16) ZPSYS CO.,LTD. (Planning&Management) + 106 Ace Techno Tower1 + Seoul 152-050 + KR + +00-0A-C6 (hex) Overture Networks. +000AC6 (base 16) Overture Networks. + 637 Davis Drive + Morrisville NC 27560 + US + +00-0A-AB (hex) Toyota Technical Development Corporation +000AAB (base 16) Toyota Technical Development Corporation + 1-9, Imae, Hanamoto-cho + Toyota Aichi 470-0334 + JP + +00-0A-B4 (hex) ETIC Telecommunications +000AB4 (base 16) ETIC Telecommunications + 13, chemin du vieux-chene ZIRST + MEYLAN Isere 38240 + FR + +00-0A-7A (hex) Kyoritsu Electric Co., Ltd. +000A7A (base 16) Kyoritsu Electric Co., Ltd. + 2-3-17 + Komae-shi Tokyo 201-0005 + JP + +00-0A-9C (hex) Server Technology, Inc. +000A9C (base 16) Server Technology, Inc. + 1040 Sandhill Drive + Reno Nevada 89521 + US + +00-0A-75 (hex) Caterpillar, Inc +000A75 (base 16) Caterpillar, Inc + Mailstop Location AC6130 + Mossville IL 61552-0610 + US + +00-0A-12 (hex) Azylex Technology, Inc +000A12 (base 16) Azylex Technology, Inc + 7-2Fl., No. 738 Chung Cheng Road, + Chung Ho City Taipei 235 + TW + +00-0A-13 (hex) Honeywell Video Systems +000A13 (base 16) Honeywell Video Systems + 6554 176 Street + Surrey BC V3S 4G5 + CA + +00-0A-09 (hex) TaraCom Integrated Products, Inc. +000A09 (base 16) TaraCom Integrated Products, Inc. + 830 Stewart Dr. + Sunnyvale CA 94085 + US + +00-0A-41 (hex) Cisco Systems, Inc +000A41 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0A-36 (hex) Synelec Telecom Multimedia +000A36 (base 16) Synelec Telecom Multimedia + Zone Industrielle + Saint Sernin sur Rance Aveyron F-12380 + FR + +00-0A-48 (hex) Albatron Technology +000A48 (base 16) Albatron Technology + 6F, No 716, Chung Cheng, + Chung-Ho City Taipei Hsien + TW + +00-0A-3E (hex) EADS Telecom +000A3E (base 16) EADS Telecom + Landshuter Strasse 26 + Munich Bavaria 85716 + DE + +00-0A-59 (hex) HW server +000A59 (base 16) HW server + Italska 15 + Prague 2 Czech Republic 120 00 + KM + +00-0A-54 (hex) Laguna Hills, Inc. +000A54 (base 16) Laguna Hills, Inc. + 3-5-2 + Chiyoda-ku Tokyo 102-0083 + JP + +00-0A-4F (hex) Brain Boxes Limited +000A4F (base 16) Brain Boxes Limited + Unit 3c, Wavertree Boulevard South + Liverpool Merseyside L7 9PF + GB + +00-0A-52 (hex) AsiaRF Ltd. +000A52 (base 16) AsiaRF Ltd. + 3F, No.176, Yongzhen Road + New Taipei City Taipei 234 + TW + +00-0A-02 (hex) ANNSO CO., LTD. +000A02 (base 16) ANNSO CO., LTD. + 5F, No. 100, Min-Chuan Road, Shing-Tien + Shing-Tien City Taipei Hsien Taiwan 221 + TW + +00-0A-65 (hex) GentechMedia.co.,ltd. +000A65 (base 16) GentechMedia.co.,ltd. + solvit bldg 2f, 402-8, yangjae-don, + seocho-gu, seoul 137-899 + KR + +00-0A-22 (hex) Amperion Inc +000A22 (base 16) Amperion Inc + 250 Apollo Drive + Chelmsford MA 01824 + US + +00-0A-1C (hex) Bridge Information Co., Ltd. +000A1C (base 16) Bridge Information Co., Ltd. + No.3, Lane 106, Wu-Kung 2 Rd., + Taipei 248 + TW + +00-0A-32 (hex) Xsido Corporation +000A32 (base 16) Xsido Corporation + 3F,2-8-13,Shiba-Daimon, + Tokyo 105-0012 + JP + +00-0A-2B (hex) Etherstuff +000A2B (base 16) Etherstuff + 208 W. Mimosa Circle + San Marcos TX 78666 + US + +00-0A-42 (hex) Cisco Systems, Inc +000A42 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-0A-38 (hex) Apani Networks +000A38 (base 16) Apani Networks + 1800 E. Imperial Hwy + Brea CA 92821 + US + +00-09-A8 (hex) Eastmode Pte Ltd +0009A8 (base 16) Eastmode Pte Ltd + 30 Loyang Way #07-06 + 508769 + SG + +00-09-AA (hex) Data Comm for Business, Inc. +0009AA (base 16) Data Comm for Business, Inc. + 2949 County Road 1000 East + Dewey IL 61853 + US + +00-09-A4 (hex) HARTEC Corporation +0009A4 (base 16) HARTEC Corporation + KOUHOKUKU SHIN-YOKOHAMA + YOKOHAMA-SHI KANAGAWA-KEN 222-0033 + JP + +00-09-A6 (hex) Ignis Optics, Inc. +0009A6 (base 16) Ignis Optics, Inc. + 482 W. San Carlos + San Jose California 95110 + US + +00-09-A7 (hex) Bang & Olufsen A/S +0009A7 (base 16) Bang & Olufsen A/S + Peter Bangs Vej 15 + Struer 7600 + DK + +00-09-C8 (hex) SINAGAWA TSUSHIN KEISOU SERVICE +0009C8 (base 16) SINAGAWA TSUSHIN KEISOU SERVICE + 13-5 Fuke , Sumiyoshi , Onahama + Iwaki City Fukushima Prefecture 971-8124 + JP + +00-09-B7 (hex) Cisco Systems, Inc +0009B7 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-B2 (hex) L&F Inc. +0009B2 (base 16) L&F Inc. + 4-2-9 + ITABASHI-KU Tokyo 175-0083 + JP + +00-09-F3 (hex) WELL Communication Corp. +0009F3 (base 16) WELL Communication Corp. + 11F, No.778, Chung Cheng Rd., Chung Ho C + Chung Ho 235 + TW + +00-09-EF (hex) Vocera Communications +0009EF (base 16) Vocera Communications + 525 Race St. + San Jose California 95126 + US + +00-09-C4 (hex) Medicore Co., Ltd +0009C4 (base 16) Medicore Co., Ltd + 72-3 5th Fl., Luna Bldg, Chungdam-dong + Seoul 135-080 + KR + +00-09-D9 (hex) Neoscale Systems, Inc +0009D9 (base 16) Neoscale Systems, Inc + 1500 Mc Candless Drive + Milpitas CA 95035 + US + +00-09-D0 (hex) Solacom Technologies Inc. +0009D0 (base 16) Solacom Technologies Inc. + 80 Jean-Proulx + Gatineau Quebec J8Z 1W1 + CA + +00-09-CC (hex) Moog GmbH +0009CC (base 16) Moog GmbH + Hanns-Klemm-Str. 28 + Boeblingen D-71034 + DE + +00-0A-00 (hex) Mediatek Corp. +000A00 (base 16) Mediatek Corp. + 8F, No 69-5, Sec.2, Chung Cheng East Rd. + Taipei 251 + TW + +00-09-F0 (hex) Shimizu Technology Inc. +0009F0 (base 16) Shimizu Technology Inc. + 15-6, No.107, Chung Shan Rd., Sec.1 + Hsin Chuan, Taipei 242 + US + +00-09-E4 (hex) K Tech Infosystem Inc. +0009E4 (base 16) K Tech Infosystem Inc. + B-405, Bundang Techno-Park 148, Yatap-do + Seongnam Kyonggi-Do 464-070 + KR + +00-09-72 (hex) Securebase,Inc +000972 (base 16) Securebase,Inc + 2nd Fl,Seungseung-Bldg,Dokok 2-Dong,Kang + Seoul 135-854 + KR + +00-09-78 (hex) AIJI System Co., Ltd. +000978 (base 16) AIJI System Co., Ltd. + #208 Samho-Park-Tower Bldg. 1122-10, Ing + Suwon Gyeonggi-do 442-835 + KR + +00-09-73 (hex) Lenten Technology Co., Ltd. +000973 (base 16) Lenten Technology Co., Ltd. + 16F, No.51, Sec.2, Gungyi Road, + Taichung City 408 + TW + +00-09-75 (hex) fSONA Communications Corporation +000975 (base 16) fSONA Communications Corporation + #140-11120 Horseshoe Way + Richmond BC V7A 5H7 + CA + +00-09-77 (hex) Brunner Elektronik AG +000977 (base 16) Brunner Elektronik AG + Müllerwis 1 + Hittnau Zurich 8335 + CH + +00-09-69 (hex) Meret Optical Communications +000969 (base 16) Meret Optical Communications + 10070 Mesa Rim Road + San Diego California 92121 + US + +00-09-42 (hex) Wireless Technologies, Inc +000942 (base 16) Wireless Technologies, Inc + Ohmori Mitsubishi Bldg., 7F, Sannoh 2-chome + Tokyo 143-0023 + JP + +00-09-45 (hex) Palmmicro Communications Inc +000945 (base 16) Palmmicro Communications Inc + 630 Alder Dr + Milpitas CA 95035 + US + +00-09-3E (hex) C&I Technologies +00093E (base 16) C&I Technologies + #303 Kwanbo Plaza B/D, 1467-2 + Anyang-Shi Kyunggi-Do 431-808 + KR + +00-09-40 (hex) AGFEO GmbH & Co. KG +000940 (base 16) AGFEO GmbH & Co. KG + Postfach 140107 + Bielefeld Rhine Westfalia 33621 + DE + +00-09-7F (hex) Vsecure 2000 LTD. +00097F (base 16) Vsecure 2000 LTD. + 11 Moshe Levi St. + Rishon LeZion 75658 + IL + +00-09-80 (hex) Power Zenith Inc. +000980 (base 16) Power Zenith Inc. + Tsujido Nishikaigan 1-10-7 + Fujisawa Kanagawa 251-0046 + JP + +00-09-A0 (hex) Microtechno Corporation +0009A0 (base 16) Microtechno Corporation + 2-33-36 Shimoodanaka + Kawasaki Kanagawa 211-0041 + JP + +00-09-9B (hex) Western Telematic Inc. +00099B (base 16) Western Telematic Inc. + 5 Sterling + Irvine CA 92618 + US + +00-09-90 (hex) ACKSYS Communications & systems +000990 (base 16) ACKSYS Communications & systems + ZA du Val Joyeux + VILLEPREUX F-78450 + FR + +00-09-53 (hex) Linkage System Integration Co.Ltd. +000953 (base 16) Linkage System Integration Co.Ltd. + 40 Gongjianfang + Nanjing Jiangsu 210006 + CN + +00-09-4C (hex) Communication Weaver Co.,Ltd. +00094C (base 16) Communication Weaver Co.,Ltd. + 1~3 COWEAVER B/D 446-19, + SEOUL 121-841 + KR + +00-09-6E (hex) GIANT ELECTRONICS LTD. +00096E (base 16) GIANT ELECTRONICS LTD. + 7/F., ELITE INDUSTRIAL BUILDING, + KWUN TONG KOWLOON + HK + +00-09-6C (hex) Imedia Semiconductor Corp. +00096C (base 16) Imedia Semiconductor Corp. + 4988 Great America Pkwy. + Santa Clara CA 95054 + US + +00-09-5F (hex) Telebyte, Inc. +00095F (base 16) Telebyte, Inc. + 270 Pulaski Road + Greenlawn NY 11740-1616 + US + +00-09-8A (hex) EqualLogic Inc +00098A (base 16) EqualLogic Inc + 9 Townsend West + Nashua NH 03062 + US + +00-08-F9 (hex) Artesyn Embedded Technologies +0008F9 (base 16) Artesyn Embedded Technologies + 2900 S. Diablo Way Suite 190 + Tempe AZ 85282 + US + +00-08-F4 (hex) Bluetake Technology Co., Ltd. +0008F4 (base 16) Bluetake Technology Co., Ltd. + 6F, No. 33, Lane 155, Sec. 3, Pei Shen R + Taipei Taiwan 222 + TW + +00-08-F7 (hex) Hitachi Ltd, Semiconductor & Integrated Circuits Gr +0008F7 (base 16) Hitachi Ltd, Semiconductor & Integrated Circuits Gr + 20-1 Josuihon-chou 5chome + Kodaira-shi Tokyo 187-8588 + JP + +00-09-20 (hex) EpoX COMPUTER CO.,LTD. +000920 (base 16) EpoX COMPUTER CO.,LTD. + 10th Floor, No.346,Chung San Rd.,Sec.2, + Chung Ho City,Taipei Hsien 235 + TW + +00-09-22 (hex) TST Biometrics GmbH +000922 (base 16) TST Biometrics GmbH + Moehlstraße 39 + 81675 Munich + DE + +00-09-16 (hex) Listman Home Technologies, Inc. +000916 (base 16) Listman Home Technologies, Inc. + 1100 Northmeadow Parkway + Roswell Georgia 30076 + US + +00-09-11 (hex) Cisco Systems, Inc +000911 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-12 (hex) Cisco Systems, Inc +000912 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-08 (hex) VTech Technology Corp. +000908 (base 16) VTech Technology Corp. + 2F-2, No. 124, Chung Cheng Rd., Shihlin + Taipei 11141 + TW + +00-09-0B (hex) MTL Instruments PLC +00090B (base 16) MTL Instruments PLC + Power Court + Luton Bedfordshire LU1 3JJ + GB + +00-09-3B (hex) HYUNDAI NETWORKS INC. +00093B (base 16) HYUNDAI NETWORKS INC. + SAN 136-1 AMI-RI BUBAL_EUP + ICHON KYUNGKI-DO 467-701 + KR + +00-09-34 (hex) Dream-Multimedia-Tv GmbH +000934 (base 16) Dream-Multimedia-Tv GmbH + Brückstraße 29 + Menden Sauerland 58706 + DE + +00-09-31 (hex) Future Internet, Inc. +000931 (base 16) Future Internet, Inc. + 11'th Floor Samhomoolsan Bldg, B/Bldg, 2 + Seoul Kyung-Ki 137-130 + KP + +00-08-F5 (hex) YESTECHNOLOGY Co.,Ltd. +0008F5 (base 16) YESTECHNOLOGY Co.,Ltd. + 4th FL Kyung-Am B/D 157-27 Samsung-Dong, + Seoul 135-090 + KR + +00-08-EC (hex) Optical Zonu Corporation +0008EC (base 16) Optical Zonu Corporation + 15028 Delano Street + Van Nuys CA 91411-2016 + US + +00-08-E6 (hex) Littlefeet +0008E6 (base 16) Littlefeet + 13000 Gregg Street + Poway California 92064 + US + +00-09-30 (hex) AeroConcierge Inc. +000930 (base 16) AeroConcierge Inc. + 10256 Yonge St. + Richmond Hill Ont. L4C 3B7 + CA + +00-09-1E (hex) Firstech Technology Corp. +00091E (base 16) Firstech Technology Corp. + 8fl.,No.267,section 4,Hsin-Yi Rd. ,Da-An + Taipei 106 + TW + +00-08-E2 (hex) Cisco Systems, Inc +0008E2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-09-05 (hex) iTEC Technologies Ltd. +000905 (base 16) iTEC Technologies Ltd. + 160-1, Karak-Dong, Songpa-Gu + Seoul 138-809 + KR + +00-08-A5 (hex) Peninsula Systems Inc. +0008A5 (base 16) Peninsula Systems Inc. + 6902 Verde Ridge Rd. + Rancho Palos Verdes CA 90275 + US + +00-08-A2 (hex) ADI Engineering, Inc. +0008A2 (base 16) ADI Engineering, Inc. + 1769A Worth Park + Charlottesville VA 22911 + US + +00-08-98 (hex) Gigabit Optics Corporation +000898 (base 16) Gigabit Optics Corporation + 1156 Aster Ave. + Sunnyvale CA 94086-6810 + US + +00-08-9B (hex) ICP Electronics Inc. +00089B (base 16) ICP Electronics Inc. + 4F, No. 22, Chung-Hsing Rd. Shi-Chi City + Taipei 221 + TW + +00-08-9C (hex) Elecs Industry Co., Ltd. +00089C (base 16) Elecs Industry Co., Ltd. + 1-22-23,Shinsaku,Takatsu-Ku + Kawasaki Kanagawa 213-0014 + JP + +00-08-9D (hex) UHD-Elektronik +00089D (base 16) UHD-Elektronik + Zuercherstrasse 12 + Baden AG 5400 + CH + +00-08-CF (hex) Nippon Koei Power Systems Co., Ltd. +0008CF (base 16) Nippon Koei Power Systems Co., Ltd. + 2940 Shinyoshida-cho + Kohoku-ku Yokohama 223-8506 + JP + +00-08-CB (hex) Zeta Broadband Inc. +0008CB (base 16) Zeta Broadband Inc. + 660 Vista Way, Suite B + Milpitas CA 95035 + US + +00-08-D3 (hex) Hercules Technologies S.A.S. +0008D3 (base 16) Hercules Technologies S.A.S. + 6,place des colombes + Rennes Bretagne 35000 + FR + +00-08-D0 (hex) Musashi Engineering Co., LTD. +0008D0 (base 16) Musashi Engineering Co., LTD. + 3-11-7, Nishi-shimbashi + Minato-ku Tokyo 105-0003 + JP + +00-08-BA (hex) Erskine Systems Ltd +0008BA (base 16) Erskine Systems Ltd + Salter Road + Scarborough North Yorkshire YO11 3DU + GB + +00-08-B5 (hex) TAI GUEN ENTERPRISE CO., LTD +0008B5 (base 16) TAI GUEN ENTERPRISE CO., LTD + N0.400, 10F-7 HUANPEI RD., + CHUNG LI 320-61 + TW + +00-08-B7 (hex) HIT Incorporated +0008B7 (base 16) HIT Incorporated + 4F, 8, Lane 235, Pao-Chiao Road, + Shin Tien Taipei 231 + TW + +00-08-A9 (hex) SangSang Technology, Inc. +0008A9 (base 16) SangSang Technology, Inc. + 64-8, Nogok-ri, Docheok-myun, + Gwangju Kyonggi-do 464-882 + KR + +00-08-C8 (hex) Soneticom, Inc. +0008C8 (base 16) Soneticom, Inc. + 4325 Woodland Park Drive, Suite 102 + West Melbourne Florida 32904 + US + +00-08-C4 (hex) Hikari Co.,Ltd. +0008C4 (base 16) Hikari Co.,Ltd. + 418-4 Minaminoda Chigenobu-cho + Onsen-gun Ehime 791-0297 + JP + +00-08-8F (hex) ADVANCED DIGITAL TECHNOLOGY +00088F (base 16) ADVANCED DIGITAL TECHNOLOGY + ADT BLDG.,3-3, YANGJAE-DONG, + SEOUL + KR + +00-08-8B (hex) Tropic Networks Inc. +00088B (base 16) Tropic Networks Inc. + 135 Micheal Cowpland Drive + Ottawa Ontario K2M2E9 + CA + +00-08-6B (hex) MIPSYS +00086B (base 16) MIPSYS + 19C, Avenue des Indes + LES ULIS Cedex FR-91969 + FR + +00-08-7F (hex) SPAUN electronic GmbH & Co. KG +00087F (base 16) SPAUN electronic GmbH & Co. KG + Byk-Gulden - Str. 22 + + DE + +00-08-86 (hex) Hansung Teliann, Inc. +000886 (base 16) Hansung Teliann, Inc. + 195-1, Neungpyung-ri, Opo-eub + + KR + +00-08-58 (hex) Novatechnology Inc. +000858 (base 16) Novatechnology Inc. + Nova Bldg. 4F 641 03 + Seoul 135-080 + KR + +00-08-50 (hex) Arizona Instrument Corp. +000850 (base 16) Arizona Instrument Corp. + 1912 W. 4th Street + Tempe AZ 85281 + US + +00-08-5B (hex) Hanbit Electronics Co., Ltd. +00085B (base 16) Hanbit Electronics Co., Ltd. + 414-5, Woncheon-Dong, Paldal-Gu + + KR + +00-08-2B (hex) Wooksung Electronics, Inc. +00082B (base 16) Wooksung Electronics, Inc. + Jaho-Bldg. 6F, Tanbang-Dong, + + KR + +00-08-2E (hex) Multitone Electronics PLC +00082E (base 16) Multitone Electronics PLC + Multitone House, Beggarwood Lane + + GB + +00-07-ED (hex) Altera Corporation +0007ED (base 16) Altera Corporation + 101 Innovation Drive + San Jose CA 95134 + US + +00-07-F1 (hex) TeraBurst Networks Inc. +0007F1 (base 16) TeraBurst Networks Inc. + 985 Stewart Drive + Sunnyvale CA 94086 + US + +00-07-F2 (hex) IOA Corporation +0007F2 (base 16) IOA Corporation + 350 Potrero Ave. + Sunnyvale CA 94085 + US + +00-07-EA (hex) Massana, Inc. +0007EA (base 16) Massana, Inc. + 2901 Tasman Drive + Santa Clara CA 95054 + US + +00-07-F0 (hex) LogiSync LLC +0007F0 (base 16) LogiSync LLC + 1313 Lear Industrial Parkway + Avon OH 44011 + US + +00-07-E7 (hex) FreeWave Technologies +0007E7 (base 16) FreeWave Technologies + 1880 S. Flaitron Ct. + Boulder CO 80301 + US + +00-07-D6 (hex) Commil Ltd. +0007D6 (base 16) Commil Ltd. + P.O. Box 10050 + + IL + +00-07-D7 (hex) Caporis Networks AG +0007D7 (base 16) Caporis Networks AG + Süggelstraße 31 + + DE + +00-07-D4 (hex) Zhejiang Yutong Network Communication Co Ltd. +0007D4 (base 16) Zhejiang Yutong Network Communication Co Ltd. + 805 HuaXing Technical Building + Zhejiang + CN + +00-07-CE (hex) Cabletime Limited +0007CE (base 16) Cabletime Limited + 64 Greenham Road + Newbury Berkshire RG14 7HX + GB + +00-07-D3 (hex) SPGPrints B.V. +0007D3 (base 16) SPGPrints B.V. + Raamstraat 1-3, 5831 AT Boxmeer + Boxmeer + NL + +00-08-13 (hex) Diskbank, Inc. +000813 (base 16) Diskbank, Inc. + 3F Focus Building, 725-25 + Seoul 135-080 + KR + +00-08-0F (hex) Proximion Fiber Optics AB +00080F (base 16) Proximion Fiber Optics AB + Isafjordsgatan 9 + + SE + +00-08-12 (hex) GM-2 Corporation +000812 (base 16) GM-2 Corporation + Shiba-Matushira-Bldg. + Tokyo Minato-ku 105-0014 + JP + +00-08-0B (hex) Birka BPA Informationssystem AB +00080B (base 16) Birka BPA Informationssystem AB + Box 20100 + + SE + +00-08-0A (hex) Espera-Werke GmbH +00080A (base 16) Espera-Werke GmbH + Moltkestrasse 17- 33 + + DE + +00-07-E3 (hex) Navcom Technology, Inc. +0007E3 (base 16) Navcom Technology, Inc. + 123 West Torrance Blvd., + Redondo Beach CA 90277 + US + +00-07-E1 (hex) WIS Communications Co. Ltd. +0007E1 (base 16) WIS Communications Co. Ltd. + 4/F Building 533 + Shenzhen Guangdong Providence + CN + +00-07-E0 (hex) Palm Inc. +0007E0 (base 16) Palm Inc. + 950 West Maude Ave + Sunnyvale CA 94085-2801 + US + +00-07-FA (hex) ITT Co., Ltd. +0007FA (base 16) ITT Co., Ltd. + 1-14-7, Mukohjyuku, + + JP + +00-07-F6 (hex) Qqest Software Systems +0007F6 (base 16) Qqest Software Systems + 860 East 4500 South #200 + Murray UT 84107 + US + +00-07-FB (hex) Giga Stream UMTS Technologies GmbH +0007FB (base 16) Giga Stream UMTS Technologies GmbH + Konrad-Zuse-Strabe 7 + + DE + +00-08-5D (hex) Mitel Corporation +00085D (base 16) Mitel Corporation + 350 Legget Drive + - K2K 2W7 + CA + +00-08-55 (hex) NASA-Goddard Space Flight Center +000855 (base 16) NASA-Goddard Space Flight Center + Code 561 + Greenbelt MD 20771 + US + +00-08-5A (hex) IntiGate Inc. +00085A (base 16) IntiGate Inc. + 309E IT Venture Tower + Seoul 138-803 + KR + +00-08-17 (hex) EmergeCore Networks LLC +000817 (base 16) EmergeCore Networks LLC + 10542 S. Jordan Gateway + South Jordan UT 84095 + US + +00-08-15 (hex) CATS Co., Ltd. +000815 (base 16) CATS Co., Ltd. + 751-2 Kachida-cho, + 224-0034 + JP + +00-08-18 (hex) Pixelworks, Inc. +000818 (base 16) Pixelworks, Inc. + 7700 SW Mohawk Street + Tualatin OR 97062 + US + +00-08-2A (hex) Powerwallz Network Security +00082A (base 16) Powerwallz Network Security + 120-13160 Vanier Place, + V6V 2J2 + CA + +00-07-AC (hex) Eolring +0007AC (base 16) Eolring + 10 Rue Alfred Kastler + + FR + +00-07-AA (hex) Quantum Data Inc. +0007AA (base 16) Quantum Data Inc. + 2111 Big Timber Rd. + Elgin IL 60123-1100 + US + +00-07-A4 (hex) GN Netcom Ltd. +0007A4 (base 16) GN Netcom Ltd. + 12-13 Sedling Road, Wear Est., District + England NE38 9BZ + GB + +00-07-9D (hex) Musashi Co., Ltd. +00079D (base 16) Musashi Co., Ltd. + 3-21-1, Shimo-ochiai, + Tokyo 161-0033 + JP + +00-07-9F (hex) Action Digital Inc. +00079F (base 16) Action Digital Inc. + 10650 Main St. + Fairfax VA 22030 + US + +00-04-7C (hex) Skidata AG +00047C (base 16) Skidata AG + T-697553 Untersbergstr. 40 + + AT + +00-07-BE (hex) DataLogic SpA +0007BE (base 16) DataLogic SpA + Via Candini, 2 + Bologna + IT + +00-07-AF (hex) Red Lion Controls, LP +0007AF (base 16) Red Lion Controls, LP + 20 Willow Springs Circle + York NY 17402 + US + +00-07-67 (hex) Yuxing Electronics Company Limited +000767 (base 16) Yuxing Electronics Company Limited + Unit 1808, 18/F Tower 3, + Kowloon Bay, Kowloon + HK + +00-07-5B (hex) Gibson Guitars +00075B (base 16) Gibson Guitars + 309 Park Plus Blvd. + Nashville TN 37217 + US + +00-07-62 (hex) Group Sense Limited +000762 (base 16) Group Sense Limited + 27/F, Wu Chung House, + Wanchai + HK + +00-07-84 (hex) Cisco Systems, Inc +000784 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-07-76 (hex) Federal APD +000776 (base 16) Federal APD + 42775 Nine Mile Rd. + Novi MI 48375 + US + +00-07-7A (hex) Infoware System Co., Ltd. +00077A (base 16) Infoware System Co., Ltd. + Mizorogi Daiichi Bldg 4 F + Tokyo + JP + +00-07-90 (hex) Tri-M Technologies (s) Limited +000790 (base 16) Tri-M Technologies (s) Limited + Blk 25, Kallang Avenue #07-01/04 + 339416 + SG + +00-07-8D (hex) NetEngines Ltd. +00078D (base 16) NetEngines Ltd. + 146 Walnut Tree Close + GUI 4UB + GB + +00-07-8A (hex) Mentor Data System Inc. +00078A (base 16) Mentor Data System Inc. + No. 24-1, Industry East 4 Rd., + Hsin-Chu, + TW + +00-07-92 (hex) Sütron Electronic GmbH +000792 (base 16) Sütron Electronic GmbH + Kurze Straße 29 + + DE + +00-07-B2 (hex) Transaccess S.A. +0007B2 (base 16) Transaccess S.A. + R. Galeno De Castro, 1445 + São Paulo SP + BR + +00-07-AD (hex) Pentacon GmbH Foto-und Feinwerktechnik +0007AD (base 16) Pentacon GmbH Foto-und Feinwerktechnik + Enderstrabe 94 + + DE + +00-07-D0 (hex) Automat Engenharia de Automação Ltda. +0007D0 (base 16) Automat Engenharia de Automação Ltda. + Rua Santo Antonio, 917 - Reboucas + 80230-120 + BR + +00-07-6A (hex) NEXTEYE Co., Ltd. +00076A (base 16) NEXTEYE Co., Ltd. + Shinsegi Plaza 4F, 900-9, + Kyunggi 431-070 + KR + +00-06-E6 (hex) DongYang Telecom Co., Ltd. +0006E6 (base 16) DongYang Telecom Co., Ltd. + 642-7 Deung Chon-Dong, KangSeo-Gu + Seoul 157-841 + KR + +00-06-DC (hex) Syabas Technology (Amquest) +0006DC (base 16) Syabas Technology (Amquest) + 4727 Paseo Padre Parkway + Fremont CA 94555 + US + +00-07-0C (hex) SVA-Intrusion.com Co. Ltd. +00070C (base 16) SVA-Intrusion.com Co. Ltd. + The 4th Floor, No. 28 Building + Shanghai 20233 + CN + +00-07-0F (hex) Fujant, Inc. +00070F (base 16) Fujant, Inc. + 6305 Carpinteria Avenue + Carpinteria CA 93013-2901 + US + +00-07-14 (hex) Brightcom +000714 (base 16) Brightcom + 6 Hanechoshet St., + + IL + +00-06-F3 (hex) AcceLight Networks +0006F3 (base 16) AcceLight Networks + 70 Abele Road, Building 1200 + Pittsburgh PA 15017 + US + +00-06-D2 (hex) Tundra Semiconductor Corp. +0006D2 (base 16) Tundra Semiconductor Corp. + 603 March Road + K2K-2M5 + CA + +00-06-D8 (hex) Maple Optical Systems +0006D8 (base 16) Maple Optical Systems + 3200 North First St. + San Jose CA 95134 + US + +00-06-CF (hex) Thales Avionics In-Flight Systems, LLC +0006CF (base 16) Thales Avionics In-Flight Systems, LLC + 17481 Red Hill Avenue + Irvine CA 92614-5630 + US + +00-06-FE (hex) Ambrado, Inc +0006FE (base 16) Ambrado, Inc + 11301 W. President George Bush Fwy. + Richardson TX 75080 + US + +00-06-E7 (hex) Bit Blitz Communications Inc. +0006E7 (base 16) Bit Blitz Communications Inc. + 830 Hillview Ct., #290 + Milpitas CA 95035 + US + +00-06-ED (hex) Inara Networks +0006ED (base 16) Inara Networks + 3031 Tisch Way, + San Jose CA 95128 + US + +00-06-DB (hex) ICHIPS Co., Ltd. +0006DB (base 16) ICHIPS Co., Ltd. + 3F, Samjeon Bldg., 236-3 + Seoul-City 135-01 + KR + +00-07-27 (hex) Zi Corporation (HK) Ltd. +000727 (base 16) Zi Corporation (HK) Ltd. + 30/F, China Resources Building + + HK + +00-07-2E (hex) North Node AB +00072E (base 16) North Node AB + Skeppsloron 42 + + SE + +00-06-99 (hex) Vida Design Co. +000699 (base 16) Vida Design Co. + 10F, No. 278 Ho Ping E. Rd., + + TW + +00-06-8D (hex) SEPATON, Inc. +00068D (base 16) SEPATON, Inc. + 400 Nickerson Rd. + Marlborough MA 01752 + US + +00-06-A3 (hex) Bitran Corporation +0006A3 (base 16) Bitran Corporation + 2213 Mochida + + JP + +00-06-9F (hex) Kuokoa Networks +00069F (base 16) Kuokoa Networks + 2901 Tasman Dr. + Santa Clara CA 95054 + US + +00-06-A2 (hex) Microtune, Inc. +0006A2 (base 16) Microtune, Inc. + 6440 Lusk Blvd., Suite D205 + San Diego CA 92121 + US + +00-06-A6 (hex) Artistic Licence Engineering Ltd +0006A6 (base 16) Artistic Licence Engineering Ltd + 24 Forward Drive + Harrow Middlesex HA3 8NT + GB + +00-06-B8 (hex) Bandspeed Pty Ltd +0006B8 (base 16) Bandspeed Pty Ltd + Level 9, 5000 Collins Street + + AU + +00-06-BB (hex) ATI Technologies Inc. +0006BB (base 16) ATI Technologies Inc. + 75 Tiverton Court + + CA + +00-06-BD (hex) BNTECHNOLOGY Co., Ltd. +0006BD (base 16) BNTECHNOLOGY Co., Ltd. + 602 Youngshin Bldg. 238-8 + Seoul + KR + +00-06-C3 (hex) Schindler Elevator Ltd. +0006C3 (base 16) Schindler Elevator Ltd. + R&D-CO + Ebikon CH-6030 + CH + +00-06-AA (hex) VT Miltope +0006AA (base 16) VT Miltope + 4900 Pearl East Circle + Boulder CO 80301 + US + +00-06-57 (hex) Market Central, Inc. +000657 (base 16) Market Central, Inc. + 500 Business Center Drive + Pittsburgh PA 15205-1333 + US + +00-06-97 (hex) R & D Center +000697 (base 16) R & D Center + 5F, Seungwon B/D, 810-9 + Seoul + KR + +00-06-9A (hex) e & Tel +00069A (base 16) e & Tel + 100 Sejong-no Chongno-gu, + + KR + +00-06-7D (hex) Takasago Ltd. +00067D (base 16) Takasago Ltd. + 1-24-16 Mizonokuchi Takatsu-ku + + JP + +00-06-71 (hex) Softing AG +000671 (base 16) Softing AG + Richard-Reitzner-Allee 6 + + DE + +00-06-72 (hex) Netezza +000672 (base 16) Netezza + 1671 Worcester Road + Framingham MA 01701 + US + +00-06-6A (hex) InfiniCon Systems, Inc. +00066A (base 16) InfiniCon Systems, Inc. + 700 American Ave. + King of Prussia PA 19406 + US + +00-06-61 (hex) NIA Home Technologies Corp. +000661 (base 16) NIA Home Technologies Corp. + Innovation Incubator, NTHU, + Hsinchu 30013, + TW + +00-06-B2 (hex) Linxtek Co. +0006B2 (base 16) Linxtek Co. + 2F Kum-a B/D 31-3 Karak-dong, + 138-160 + KR + +00-06-B6 (hex) Nir-Or Israel Ltd. +0006B6 (base 16) Nir-Or Israel Ltd. + 11 Amal St. + + IL + +00-06-84 (hex) Biacore AB +000684 (base 16) Biacore AB + Software, Electronics and Optics + + SE + +00-06-82 (hex) Convedia +000682 (base 16) Convedia + 4190 Still Creek Dr. + V5C 6C6 + CA + +00-05-E3 (hex) LightSand Communications, Inc. +0005E3 (base 16) LightSand Communications, Inc. + 375 Los Coches St. + Milpitas CA 94539 + US + +00-05-ED (hex) Technikum Joanneum GmbH +0005ED (base 16) Technikum Joanneum GmbH + Alte Poststrasse 149 + + AT + +00-05-EF (hex) ADOIR Digital Technology +0005EF (base 16) ADOIR Digital Technology + 28 Fl, ZhaoFeng World Trade Bldg. + Shanghai 200050, + CN + +00-06-00 (hex) Toshiba Teli Corporation +000600 (base 16) Toshiba Teli Corporation + 4-7-1 Asahigaoka, Hino-Shi, + Tokyo 191-0065 + JP + +00-06-6B (hex) Sysmex Corporation +00066B (base 16) Sysmex Corporation + 4-4-4 Takatsukadai, + 651-2271 + JP + +00-05-5A (hex) Power Dsine Ltd. +00055A (base 16) Power Dsine Ltd. + 1 Hanagar St., P.O. Box 7220 + + IL + +00-06-53 (hex) Cisco Systems, Inc +000653 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-06-4F (hex) PRO-NETS Technology Corporation +00064F (base 16) PRO-NETS Technology Corporation + Pao-Chung Road, + Hsin Tien Taipei, + TW + +00-06-12 (hex) Accusys, Inc. +000612 (base 16) Accusys, Inc. + 5F, No. 38, Taiyuan St + Hsinchu County 30265 + TW + +00-06-09 (hex) Crossport Systems +000609 (base 16) Crossport Systems + 10940 NE 33rd Place + Bellevue WA 98005 + US + +00-06-16 (hex) Tel Net Co., Ltd. +000616 (base 16) Tel Net Co., Ltd. + 3F BOF Bldg 730-15 Goje Song + + KR + +00-06-0D (hex) Wave7 Optics +00060D (base 16) Wave7 Optics + 1075 Windward Ridge Pkwy. + Alpharetta GA 30005 + US + +00-06-4A (hex) Honeywell Co., Ltd. (KOREA) +00064A (base 16) Honeywell Co., Ltd. (KOREA) + 56, Chaam-dong, Chonan-city + + KR + +00-06-3F (hex) Everex Communications Inc. +00063F (base 16) Everex Communications Inc. + 5020A Brandin Ct. + Fremont CA 94538 + US + +00-06-3D (hex) Microwave Data Systems Inc. +00063D (base 16) Microwave Data Systems Inc. + 175 Science Parkway + Rochester NY 14620 + US + +00-06-39 (hex) Newtec +000639 (base 16) Newtec + Laarstraat 5 + + BE + +00-06-2F (hex) Pivotech Systems Inc. +00062F (base 16) Pivotech Systems Inc. + 200 Centennial Ave., + Piscataway NJ 08854 + US + +00-06-36 (hex) Jedai Broadband Networks +000636 (base 16) Jedai Broadband Networks + 331 Newman Springs Rd. + Red Bank NJ 07701 + US + +00-06-51 (hex) Aspen Networks Inc. +000651 (base 16) Aspen Networks Inc. + 3777 Stevens Creek Blvd + Santa Clara CA 95051 + US + +00-06-5C (hex) Malachite Technologies, Inc. +00065C (base 16) Malachite Technologies, Inc. + 195 New Hampshire Avenue + Portsmouth NH 03801 + US + +00-06-42 (hex) Genetel Systems Inc. +000642 (base 16) Genetel Systems Inc. + Mockwoo B/D, 912 Walpyoung-Dong + 302-852 + KR + +00-05-E9 (hex) Unicess Network, Inc. +0005E9 (base 16) Unicess Network, Inc. + 870 Dorothy Dr. #708 + Richardson TX 75081 + US + +00-05-E6 (hex) Egenera, Inc. +0005E6 (base 16) Egenera, Inc. + 165 Forest St. + Marlboro MA 01752 + US + +00-06-1E (hex) Maxan Systems +00061E (base 16) Maxan Systems + 1-84, Woulam-dong + + KR + +00-06-22 (hex) Chung Fu Chen Yeh Enterprise Corp. +000622 (base 16) Chung Fu Chen Yeh Enterprise Corp. + 2F No. 666 Jing Ping Road, + Taipei Hsien + TW + +00-CB-BD (hex) Cambridge Broadband Networks Ltd. +00CBBD (base 16) Cambridge Broadband Networks Ltd. + Selwyn House Cambridge Business Park + Cambridge CB4 0WZ + GB + +00-05-88 (hex) Sensoria Corp. +000588 (base 16) Sensoria Corp. + 15950 Bernardo Ctr. Dr. + San Diego CA 92127 + US + +00-05-8D (hex) Lynx Photonic Networks, Inc. +00058D (base 16) Lynx Photonic Networks, Inc. + 13 Hamelaha St. + + IL + +00-05-8A (hex) Netcom Co., Ltd. +00058A (base 16) Netcom Co., Ltd. + 1F, No. 7, Lane 242, + Taipei + TW + +00-05-91 (hex) Active Silicon Ltd +000591 (base 16) Active Silicon Ltd + Pinewood Mews + Iver SL0 0NA + GB + +00-05-93 (hex) Grammar Engine Inc. +000593 (base 16) Grammar Engine Inc. + 921 Eastwind Drive + Westerville OH 43081 + US + +00-05-C7 (hex) I/F-COM A/S +0005C7 (base 16) I/F-COM A/S + Ellegaardvej 36 + + DK + +00-05-CC (hex) Sumtel Communications, Inc. +0005CC (base 16) Sumtel Communications, Inc. + 1F, No. 173, Gung Yuan Road, + Hsinchu City 30054 + TW + +00-05-CF (hex) Thunder River Technologies, Inc. +0005CF (base 16) Thunder River Technologies, Inc. + 23 Corporate Plaza Ste. 250 + Newport Beach CA 92660 + US + +00-05-C6 (hex) Triz Communications +0005C6 (base 16) Triz Communications + Anwon Bldg. 7th Fl. + Seoul 150-010 + KR + +00-05-D6 (hex) L-3 Linkabit +0005D6 (base 16) L-3 Linkabit + 9890 Town Center Drive + San Diego CA 92121 + US + +00-05-DA (hex) Apex Automationstechnik +0005DA (base 16) Apex Automationstechnik + Vossenkamp 4 + + DE + +00-05-A1 (hex) Zenocom +0005A1 (base 16) Zenocom + No.402, 4th floor, Wongok Bldg. + Seoul + KR + +00-05-A9 (hex) Princeton Networks, Inc. +0005A9 (base 16) Princeton Networks, Inc. + 100 Century Center Ct. #100 + San Jose CA 95112 + US + +00-05-AF (hex) InnoScan Computing A/S +0005AF (base 16) InnoScan Computing A/S + Soren Frichsvej 42R + + DK + +00-05-A6 (hex) Extron Electronics +0005A6 (base 16) Extron Electronics + 1230 S. Lewis + Anahiem CA 92805 + US + +00-05-A0 (hex) MOBILINE Kft. +0005A0 (base 16) MOBILINE Kft. + Lehel Utca 14 + H-1134 + HU + +00-05-84 (hex) AbsoluteValue Systems, Inc. +000584 (base 16) AbsoluteValue Systems, Inc. + 715-D North Dr. + Melbourne FL 32934 + US + +00-05-8F (hex) CLCsoft co. +00058F (base 16) CLCsoft co. + Dept. of Electrical Engineering + + KR + +00-05-BB (hex) Myspace AB +0005BB (base 16) Myspace AB + Sveavagen 33 + + SE + +00-05-17 (hex) Shellcomm, Inc. +000517 (base 16) Shellcomm, Inc. + Rm #6122 ETRI TBI Center, 1, + + KR + +00-05-1C (hex) Xnet Technology Corp. +00051C (base 16) Xnet Technology Corp. + 9F-16, No. 12, Lane 609, + + TW + +00-04-F9 (hex) Xtera Communications, Inc. +0004F9 (base 16) Xtera Communications, Inc. + 500 W Bethany Drive + Allen TX 75013 + US + +00-04-FA (hex) NBS Technologies Inc. +0004FA (base 16) NBS Technologies Inc. + 703 Evans Avenue, Suite 400 + Ontario M9C 5E9 + CA + +00-05-41 (hex) Advanced Systems Co., Ltd. +000541 (base 16) Advanced Systems Co., Ltd. + 2-9-7 Nishikicho, + 190-0022 + JP + +00-05-45 (hex) Internet Photonics +000545 (base 16) Internet Photonics + 1030 Broad St., 2nd Floor + Shrewsbury NJ 07702 + US + +00-05-3A (hex) Willowglen Services Pte Ltd +00053A (base 16) Willowglen Services Pte Ltd + 151 Lorong Chuan, + 556741 + SG + +00-05-31 (hex) Cisco Systems, Inc +000531 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-05-39 (hex) A Brand New World in Sweden AB +000539 (base 16) A Brand New World in Sweden AB + Box 1223 + + SE + +00-05-2A (hex) Ikegami Tsushinki Co., Ltd. +00052A (base 16) Ikegami Tsushinki Co., Ltd. + 5-6-16 Ikegami Ohta-ku, + 146-8567 + JP + +00-05-2D (hex) Zoltrix International Limited +00052D (base 16) Zoltrix International Limited + Room 701 Po Hing Centre, + + HK + +00-05-25 (hex) Puretek Industrial Co., Ltd. +000525 (base 16) Puretek Industrial Co., Ltd. + No. 14, 4 Flr. Lane 235 + + TW + +00-05-58 (hex) Synchronous, Inc. +000558 (base 16) Synchronous, Inc. + 77 Las Colinas Lane + San Jose CA 95119 + US + +00-05-50 (hex) Vcomms Connect Limited +000550 (base 16) Vcomms Connect Limited + 75 The Esplanade, Level 3 + Wellington Mail Centre 5045 Wellington + NZ + +00-05-12 (hex) Zebra Technologies Inc +000512 (base 16) Zebra Technologies Inc + 475 Half Day Road + Lincolnshire IL 60069 + US + +00-05-03 (hex) ICONAG +000503 (base 16) ICONAG + AM Bahnhof 2 + + DE + +00-05-7A (hex) Overture Networks +00057A (base 16) Overture Networks + 637 Davis Drive + Morrisville NC 27560 + US + +00-05-64 (hex) Tsinghua Bitway Co., Ltd. +000564 (base 16) Tsinghua Bitway Co., Ltd. + 12 Floor, Tower C, Corporate + + CN + +00-04-F8 (hex) QUALICABLE TV Industria E Com., Ltda +0004F8 (base 16) QUALICABLE TV Industria E Com., Ltda + Av. Joao Paulo Ablas, 308 + + BR + +00-04-F5 (hex) SnowShore Networks, Inc. +0004F5 (base 16) SnowShore Networks, Inc. + 285 Billerica Road + Chelmsford MA 01824 + US + +00-04-F2 (hex) Polycom +0004F2 (base 16) Polycom + 1000 West 14th Street + Canada V7P3P3 + CA + +00-04-F3 (hex) FS FORTH-SYSTEME GmbH +0004F3 (base 16) FS FORTH-SYSTEME GmbH + Küferstraße 8 + + DE + +00-04-ED (hex) Billion Electric Co., Ltd. +0004ED (base 16) Billion Electric Co., Ltd. + 8F, No.192, Sec.2, Chung Hsing Rd., + Taiwan Taiwan ROC + TW + +00-04-E7 (hex) Lightpointe Communications, Inc +0004E7 (base 16) Lightpointe Communications, Inc + 10140 Barnes Canyon Road + San Diego CA 92121 + US + +00-04-E6 (hex) Banyan Network Private Limited +0004E6 (base 16) Banyan Network Private Limited + 443, 8th Floor, Guna Complex + + IN + +00-04-DE (hex) Cisco Systems, Inc +0004DE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-04-A2 (hex) L.S.I. Japan Co., Ltd. +0004A2 (base 16) L.S.I. Japan Co., Ltd. + 1-8-14 Sendagaya Shibuya-Ku + Tokyo 151-0051 + JP + +00-04-9B (hex) Cisco Systems, Inc +00049B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-04-99 (hex) Chino Corporation +000499 (base 16) Chino Corporation + 1 Mori, Fujioka City, + Zip: 375-8505 + JP + +00-04-8E (hex) Ohm Tech Labs, Inc. +00048E (base 16) Ohm Tech Labs, Inc. + 141 Lanza Ave., B-12 + Garfield NJ 07026 + US + +00-04-A6 (hex) SAF Tehnika Ltd. +0004A6 (base 16) SAF Tehnika Ltd. + 91 Dzirnavu Str., + + LV + +00-04-A8 (hex) Broadmax Technologies, Inc. +0004A8 (base 16) Broadmax Technologies, Inc. + 180, Wai Yip Street, + HONG KONG + HK + +00-04-A1 (hex) Pathway Connectivity +0004A1 (base 16) Pathway Connectivity + 1439-17 Avenue SE + Calgary Alberta T2G 1J9 + CA + +00-04-CE (hex) Patria Ailon +0004CE (base 16) Patria Ailon + Naulakatu 3 + + FI + +00-04-C7 (hex) NetMount +0004C7 (base 16) NetMount + P.O.B. 2325 + + IL + +00-04-8D (hex) Teo Technologies, Inc +00048D (base 16) Teo Technologies, Inc + 11609 49th Place West + Mukilteo WA 98275 + US + +00-04-90 (hex) Optical Access +000490 (base 16) Optical Access + P.O. Box 114 + + IL + +00-04-E1 (hex) Infinior Microsystems +0004E1 (base 16) Infinior Microsystems + 2F, Accufar Bldg, 234-10, + Seoul KOREA 138-220 + KR + +00-04-C2 (hex) Magnipix, Inc. +0004C2 (base 16) Magnipix, Inc. + 3539 St-Charles Blvd., Suite 212 + CANADA H9H3C4 + CA + +00-04-86 (hex) ITTC, University of Kansas +000486 (base 16) ITTC, University of Kansas + 2335 Irving Hill Rd. + Lawrence KS 66045 + US + +00-04-8B (hex) Poscon Corporation +00048B (base 16) Poscon Corporation + #606 Ho-Dong, Nam Gu, + SOUTH KOREA + KR + +00-04-84 (hex) Amann GmbH +000484 (base 16) Amann GmbH + Unteranger 6 + + DE + +00-04-78 (hex) G. Star Technology Corporation +000478 (base 16) G. Star Technology Corporation + 4th Floor, No. 118, Sector 2 + Taipei City Taipei City TAIWAN + TW + +00-04-7A (hex) AXXESSIT ASA +00047A (base 16) AXXESSIT ASA + AXXESSIT ASA HALDEN + + NO + +00-04-6A (hex) Navini Networks +00046A (base 16) Navini Networks + 3605 E. Plano Pkwy, + Plano TX 75074 + US + +00-04-6B (hex) Palm Wireless, Inc. +00046B (base 16) Palm Wireless, Inc. + 48933 Warm Springs Blvd. + Fremont CA 94539 + US + +00-04-72 (hex) Telelynx, Inc. +000472 (base 16) Telelynx, Inc. + 3F-1, 66 Nankan Rd., + TAIWAN + TW + +00-04-64 (hex) Pulse-Link Inc +000464 (base 16) Pulse-Link Inc + 1934 Kellogg Avenue + Carlsbad CA 92008 + US + +00-04-65 (hex) i.s.t isdn-support technik GmbH +000465 (base 16) i.s.t isdn-support technik GmbH + Rhein Strasse 7E + + DE + +00-04-5E (hex) PolyTrax Information Technology AG +00045E (base 16) PolyTrax Information Technology AG + Martin-Kollar - Str. 5 + + DE + +00-04-11 (hex) Inkra Networks, Inc. +000411 (base 16) Inkra Networks, Inc. + 40971 Encyclopedia Circle + Fremont CA 94538 + US + +00-04-10 (hex) Spinnaker Networks, Inc. +000410 (base 16) Spinnaker Networks, Inc. + 107 Gamma Drive + Pittsburgh PA 15238 + US + +00-04-12 (hex) WaveSmith Networks, Inc. +000412 (base 16) WaveSmith Networks, Inc. + 40 Nagog Park + Acton MA 01720-3425 + US + +00-04-42 (hex) NACT +000442 (base 16) NACT + 191 W. 5200 N. + Provo UT 84604 + US + +00-04-45 (hex) LMS Skalar Instruments GmbH +000445 (base 16) LMS Skalar Instruments GmbH + Willi-Eichler-Str 11 + + DE + +00-04-4E (hex) Cisco Systems, Inc +00044E (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-04-52 (hex) RocketLogix, Inc. +000452 (base 16) RocketLogix, Inc. + 6504 International Parkway + Plano TX 75093 + US + +00-04-27 (hex) Cisco Systems, Inc +000427 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-04-20 (hex) Slim Devices, Inc. +000420 (base 16) Slim Devices, Inc. + 12 South First St. + San Jose CA 95113 + US + +00-04-3D (hex) INDEL AG +00043D (base 16) INDEL AG + Tufiwis 26 + + CH + +00-04-3B (hex) Lava Computer Mfg., Inc. +00043B (base 16) Lava Computer Mfg., Inc. + 2 Vulcan St. + CANADA M9W-1L2 + CA + +00-04-31 (hex) GlobalStreams, Inc. +000431 (base 16) GlobalStreams, Inc. + 2882 Prospect Park Drive + Rancho Cordova CA 95670 + US + +00-03-C4 (hex) Tomra Systems ASA +0003C4 (base 16) Tomra Systems ASA + Drengsrudhagen 2 + + NO + +00-03-C5 (hex) Mobotix AG +0003C5 (base 16) Mobotix AG + Wingertsweilerhof 6 + + DE + +00-03-BF (hex) Centerpoint Broadband Technologies, Inc. +0003BF (base 16) Centerpoint Broadband Technologies, Inc. + 1741 Technology Drive, + San Jose CA 95110-1310 + US + +00-03-B9 (hex) Hualong Telecom Co., Ltd. +0003B9 (base 16) Hualong Telecom Co., Ltd. + 9 Guanghua St. + P.R. + CN + +00-03-F9 (hex) Pleiades Communications, Inc. +0003F9 (base 16) Pleiades Communications, Inc. + 2830 Market Loop #104 + South Lake TX 76092 + US + +00-03-FE (hex) Cisco Systems, Inc +0003FE (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-F5 (hex) Chip2Chip +0003F5 (base 16) Chip2Chip + 2249 Zanker Rd. + San Jose CA 95131 + US + +00-03-91 (hex) Advanced Digital Broadcast, Ltd. +000391 (base 16) Advanced Digital Broadcast, Ltd. + 8F, 145 Chung Shan N. Rd. Sec. 2, + TAIWAN TAIWAN R.O.C. + TW + +00-03-AC (hex) Fronius Schweissmaschinen +0003AC (base 16) Fronius Schweissmaschinen + Günter Fronius-Straße 1 + + AT + +00-03-99 (hex) Dongju Informations & Communications Co., Ltd. +000399 (base 16) Dongju Informations & Communications Co., Ltd. + #305, Eunsuk Bldg. Samsung-dong + Republic of KOREA + KR + +00-03-FD (hex) Cisco Systems, Inc +0003FD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-BA (hex) Oracle Corporation +0003BA (base 16) Oracle Corporation + 17 Network Circle + Menlo Park CA 95025 + US + +00-03-AF (hex) Paragea Communications +0003AF (base 16) Paragea Communications + 207 Perry Parkway + Gaithersburg MD 20877 + US + +00-03-0B (hex) Hunter Technology, Inc. +00030B (base 16) Hunter Technology, Inc. + 1408, Woolim e-biz Center, + Seoul 135-270 + KR + +00-03-C9 (hex) TECOM Co., Ltd. +0003C9 (base 16) TECOM Co., Ltd. + 23, R&D Road 2 + Hsin-Chu + TW + +00-03-C1 (hex) Packet Dynamics Ltd +0003C1 (base 16) Packet Dynamics Ltd + 2 Buckstane Park + UK EH10 GPA + GB + +00-03-DE (hex) OTC Wireless +0003DE (base 16) OTC Wireless + 602 Charlot Ave. + San Jose CA 95131 + US + +00-03-28 (hex) Mace Group, Inc. +000328 (base 16) Mace Group, Inc. + 5101 Commerce Dr. + Baldwin Park CA 91706 + US + +00-03-2B (hex) GAI Datenfunksysteme GmbH +00032B (base 16) GAI Datenfunksysteme GmbH + Riedleparkstraße 28 + Friedrichshafen 88045 + DE + +00-03-2C (hex) ABB Switzerland Ltd +00032C (base 16) ABB Switzerland Ltd + Dept. ATEP + Austrasse + CH + +00-03-23 (hex) Cornet Technology, Inc. +000323 (base 16) Cornet Technology, Inc. + 6800 Versar Center, Suite 216 + Springfield VA 22151-4147 + US + +00-03-80 (hex) SSH Communications Security Corp. +000380 (base 16) SSH Communications Security Corp. + Fredrikinkatu 42 + + FI + +00-03-82 (hex) A-One Co., Ltd. +000382 (base 16) A-One Co., Ltd. + 6-9-20, Shimoichiba-cho, + + JP + +00-03-7A (hex) Taiyo Yuden Co., Ltd. +00037A (base 16) Taiyo Yuden Co., Ltd. + 8-1 Sakae-Cho + + JP + +00-03-75 (hex) NetMedia, Inc. +000375 (base 16) NetMedia, Inc. + 10940 N. Stallard Place + Tuscon AZ 85737 + US + +00-03-5A (hex) Photron Limited +00035A (base 16) Photron Limited + 1-1-8, Fujimi, + Chiyoda-ku 102-0071 + JP + +00-03-53 (hex) Mitac, Inc. +000353 (base 16) Mitac, Inc. + No. 2, Chung-Hsiao Street + Chitu Keelung, + TW + +00-03-56 (hex) Wincor Nixdorf International GmbH +000356 (base 16) Wincor Nixdorf International GmbH + Heinz-Nixdorf Ring 1 + D-33106 Paderborn + DE + +00-03-4F (hex) Sur-Gard Security +00034F (base 16) Sur-Gard Security + 401 Magnetic Drive + Ontario M3J 3H9 + CA + +00-03-7B (hex) IDEC IZUMI Corporation +00037B (base 16) IDEC IZUMI Corporation + 7-31, Nishimiyahara + + JP + +00-03-67 (hex) Jasmine Networks, Inc. +000367 (base 16) Jasmine Networks, Inc. + 1940 Zanker Road + San Jose CA 95112 + US + +00-03-6A (hex) Mainnet, Ltd. +00036A (base 16) Mainnet, Ltd. + P.O. Box 2324 + + IL + +00-03-6B (hex) Cisco Systems, Inc +00036B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-6C (hex) Cisco Systems, Inc +00036C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-8F (hex) Weinschel Corporation +00038F (base 16) Weinschel Corporation + 5305 Spectrum Drive + Frederick MD 21703 + US + +00-03-84 (hex) AETA +000384 (base 16) AETA + Kepler 6 + Le Plessis Robinson 92350 + FR + +00-03-87 (hex) Blaze Network Products +000387 (base 16) Blaze Network Products + 5180 Hacienda Drive + Dublin CA 94568 + US + +00-03-81 (hex) Ingenico International +000381 (base 16) Ingenico International + 1/9 Apollo Street + + AU + +00-03-40 (hex) Floware Wireless Systems, Ltd. +000340 (base 16) Floware Wireless Systems, Ltd. + 28 Hacharoshet Steet + 60250 + IL + +00-01-EC (hex) Ericsson Group +0001EC (base 16) Ericsson Group + Telefonaktiebolaget + + SE + +00-03-33 (hex) Digitel Co., Ltd. +000333 (base 16) Digitel Co., Ltd. + 835-6, Yoksam-dong + + KR + +00-03-38 (hex) Oak Technology +000338 (base 16) Oak Technology + 139 Kifer Court + Sunnyvale CA 94086-5160 + US + +00-03-39 (hex) Eurologic Systems, Ltd. +000339 (base 16) Eurologic Systems, Ltd. + Clonshaugh Industrial Estate + Clonshaugh Dublin 17 + IE + +00-03-31 (hex) Cisco Systems, Inc +000331 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-30 (hex) Imagenics, Co., Ltd. +000330 (base 16) Imagenics, Co., Ltd. + 1-31-5 Kokuryo-Cho + 182-0022 + JP + +00-03-4A (hex) RIAS Corporation +00034A (base 16) RIAS Corporation + 46600 Fremont Blvd. + Fremont CA 94538 + US + +00-02-CF (hex) ZyGate Communications, Inc. +0002CF (base 16) ZyGate Communications, Inc. + 2F, No.48, Lung-Chin Road + + TW + +00-02-D1 (hex) Vivotek, Inc. +0002D1 (base 16) Vivotek, Inc. + 5F-1, 168-1, Lien-Chen Rd, + + TW + +00-02-C2 (hex) Net Vision Telecom +0002C2 (base 16) Net Vision Telecom + #206 Software Support Center + 305-343 Rep. of Korea + KR + +00-02-B6 (hex) Acrosser Technology Co., Ltd. +0002B6 (base 16) Acrosser Technology Co., Ltd. + No. 116-2 Guang-Fu Rd. + Taipei Taipei R.O.C. + TW + +00-02-B1 (hex) Anritsu, Ltd. +0002B1 (base 16) Anritsu, Ltd. + Rutherford Close + UNITED KINGDOM + GB + +00-02-AD (hex) HOYA Corporation +0002AD (base 16) HOYA Corporation + 2-7-5 Naka-Ochiai, Shinjuku-ku, + Tokyo 161-8525 + JP + +00-02-AE (hex) Scannex Electronics Ltd. +0002AE (base 16) Scannex Electronics Ltd. + Unit 8 English Business Park + Hove BN3 7ET + GB + +00-03-04 (hex) Pacific Broadband Communications +000304 (base 16) Pacific Broadband Communications + 3103 North First St. + San Jose CA 95134 + US + +00-03-01 (hex) EXFO +000301 (base 16) EXFO + 400 Godin Avenue + Quebec G1M 2K2 + CA + +00-02-FD (hex) Cisco Systems, Inc +0002FD (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-03-00 (hex) Barracuda Networks, Inc. +000300 (base 16) Barracuda Networks, Inc. + 3175 S. Winchester Blvd + Campbell CA 95008 + US + +00-02-BD (hex) Bionet Co., Ltd. +0002BD (base 16) Bionet Co., Ltd. + 3F, Medison Venture Tower, + KOREA + KR + +00-02-BE (hex) Totsu Engineering, Inc. +0002BE (base 16) Totsu Engineering, Inc. + 5-16-20 Roppongi Minato-ku + Tokyo 106-8551 + JP + +00-02-B9 (hex) Cisco Systems, Inc +0002B9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-02-BA (hex) Cisco Systems, Inc +0002BA (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-02-F9 (hex) MIMOS Berhad +0002F9 (base 16) MIMOS Berhad + Technology Park Malaysia + Kuala Lumpur 57000 + MY + +00-02-F3 (hex) Media Serve Co., Ltd. +0002F3 (base 16) Media Serve Co., Ltd. + Dongsung Bldg. #17-8, Youido-dong, + Seoul + KR + +00-02-EA (hex) Focus Enhancements +0002EA (base 16) Focus Enhancements + 1370 Dell Ave. + Campbell CA 95008 + US + +00-03-13 (hex) Access Media SPA +000313 (base 16) Access Media SPA + Via delle Industrie, 4/g + 24035 LALLIO (BG) + IT + +00-03-10 (hex) E-Globaledge Corporation +000310 (base 16) E-Globaledge Corporation + 7F Nakameguro GT Tower + Meduro-ku, Tokyo 153-0051 + JP + +00-03-0A (hex) Argus Technologies +00030A (base 16) Argus Technologies + 8F, No. 183, Kang Chien Rd. + 114 + TW + +00-03-1E (hex) Optranet, Inc. +00031E (base 16) Optranet, Inc. + 7041 Koll Center Pkwy + Pleasanton CA 94566 + US + +00-03-15 (hex) Cidco Incorporated +000315 (base 16) Cidco Incorporated + 220 Cochrane Circle + Morgan Hill CA 95037 + US + +00-03-19 (hex) Infineon AG +000319 (base 16) Infineon AG + P.O. Box 800949 + + DE + +00-02-E7 (hex) CAB GmbH & Co KG +0002E7 (base 16) CAB GmbH & Co KG + Wilhelm-Schickard-Str 14 + + DE + +00-02-DF (hex) Net Com Systems, Inc. +0002DF (base 16) Net Com Systems, Inc. + 15-3, Yoido-Dong, + Seoul + KR + +00-02-DB (hex) NETSEC +0002DB (base 16) NETSEC + 13505 Dulles Technology Dr., Ste. 1 + Herdon VA 20171 + US + +00-02-4B (hex) Cisco Systems, Inc +00024B (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-02-4D (hex) Mannesman Dematic Colby Pty. Ltd. +00024D (base 16) Mannesman Dematic Colby Pty. Ltd. + 24 Narabang Way + + AU + +00-02-50 (hex) Geyser Networks, Inc. +000250 (base 16) Geyser Networks, Inc. + 535 Del Rey Avenue + Sunnyvale CA 94086 + US + +00-02-48 (hex) Pilz GmbH & Co. +000248 (base 16) Pilz GmbH & Co. + Felix-Wankel-Straße 2 + + DE + +00-02-4C (hex) SiByte, Inc. +00024C (base 16) SiByte, Inc. + 2805 Bowers Avenue + Santa Clara CA 95051-0917 + US + +00-02-5A (hex) Catena Networks +00025A (base 16) Catena Networks + 307 Legget Drive + Canada K2K 3C8 + CA + +00-02-6E (hex) NeGeN Access, Inc. +00026E (base 16) NeGeN Access, Inc. + 33 Boston Post Rd. West + Marlborough MA 01752 + US + +00-02-70 (hex) Crewave Co., Ltd. +000270 (base 16) Crewave Co., Ltd. + F7, Pureun Bldg., 28-1 + Seoul KOREA 137-030 + KR + +00-02-3B (hex) Ericsson +00023B (base 16) Ericsson + 250 Holger Way + SAN JOSE CA 95134 + US + +00-02-39 (hex) Visicom +000239 (base 16) Visicom + 10052 Mesa Ridge Ct. + San Diego CA 92121 + US + +00-02-33 (hex) Mantra Communications, Inc. +000233 (base 16) Mantra Communications, Inc. + 12850 Middlebrook Road + Germantown MD 20874 + US + +00-02-A2 (hex) Hilscher GmbH +0002A2 (base 16) Hilscher GmbH + Rheinstraße 15 + + DE + +00-02-54 (hex) WorldGate +000254 (base 16) WorldGate + 3190 Tremont Avenue + Trevose PA 19053 + US + +00-02-9A (hex) Storage Apps +00029A (base 16) Storage Apps + 3 Princess Road + Lawrenceville NJ 08648 + US + +00-02-8F (hex) Globetek, Inc. +00028F (base 16) Globetek, Inc. + 1607 Akron Peninsula Rd. + Akron OH 44313-5190 + US + +00-02-87 (hex) Adapcom +000287 (base 16) Adapcom + 172-A Component Drive + San Jose CA 95131 + US + +00-02-81 (hex) Madge Ltd. +000281 (base 16) Madge Ltd. + Madge House + Maindenhead Berkshire SL6 2HP + GB + +00-02-63 (hex) UPS Manufacturing SRL +000263 (base 16) UPS Manufacturing SRL + Via Giordano, 54 + Verona + IT + +00-02-40 (hex) Seedek Co., Ltd. +000240 (base 16) Seedek Co., Ltd. + #709, 1638-32, Sammo + KOREA + KR + +00-01-F3 (hex) QPS, Inc. +0001F3 (base 16) QPS, Inc. + 8015 E. Crystal Drive + Anaheim CA 92807 + US + +00-01-E4 (hex) Sitera, Inc. +0001E4 (base 16) Sitera, Inc. + 1820 Lefthand Circle + Longmont CO 80501 + US + +00-01-E3 (hex) Siemens AG +0001E3 (base 16) Siemens AG + Schlavenhorst 88 + + DE + +00-01-EB (hex) C-COM Corporation +0001EB (base 16) C-COM Corporation + 3F, No. 48, Park Ave. II SBIP + Hsinchu Taiwan Hsinchu Taiwan R.O.C. + TW + +00-01-F2 (hex) Mark of the Unicorn, Inc. +0001F2 (base 16) Mark of the Unicorn, Inc. + 1280 Massachusetts Ave. + Cambridge MA 02138 + US + +00-01-D9 (hex) Sigma, Inc. +0001D9 (base 16) Sigma, Inc. + 32-3 Seijyo 9 Chome + + JP + +00-01-C5 (hex) Simpler Networks +0001C5 (base 16) Simpler Networks + 555 Dr Frederick Philips + H4M 2X4 + CA + +00-01-C9 (hex) Cisco Systems, Inc +0001C9 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-02-1B (hex) Kollmorgen-Servotronix +00021B (base 16) Kollmorgen-Servotronix + POB 3919, Petach Tikya + 49130 + IL + +00-02-1E (hex) SIMTEL S.R.L. +00021E (base 16) SIMTEL S.R.L. + Via Bonifacio Lupi, 25 + + IT + +00-02-21 (hex) DSP Application, Ltd. +000221 (base 16) DSP Application, Ltd. + 12F-12, No. 79, Sec. 1 Hsin Tai Wu Rd. + TAIWAN + TW + +00-01-F7 (hex) Image Display Systems, Inc. +0001F7 (base 16) Image Display Systems, Inc. + 46560 Fremont Blvd. + Fremont CA 94538 + US + +00-02-00 (hex) Net & Sys Co., Ltd. +000200 (base 16) Net & Sys Co., Ltd. + Kuro Hitech Industrial Complex 304, + KOREA + KR + +00-01-C4 (hex) NeoWave, Inc. +0001C4 (base 16) NeoWave, Inc. + 10th KRIHS Bldg. 1591-6 + SOUTH KOREA + KR + +00-01-C1 (hex) Vitesse Semiconductor Corporation +0001C1 (base 16) Vitesse Semiconductor Corporation + Hoerkaer 18 + + DK + +00-01-D8 (hex) Teltronics, Inc. +0001D8 (base 16) Teltronics, Inc. + 4125 Keller Springs Road + Addison TX 25001 + US + +00-02-05 (hex) Hitachi Denshi, Ltd. +000205 (base 16) Hitachi Denshi, Ltd. + 32 Miyaki-cho Kodaira-shi + JAPAN 187-8511 + JP + +00-02-15 (hex) Cotas Computer Technology A/B +000215 (base 16) Cotas Computer Technology A/B + Paludan-Mullers Vej 82 + + DK + +00-02-2A (hex) Asound Electronic +00022A (base 16) Asound Electronic + Xianxi Industries Zone Changan Town + + CN + +00-01-8C (hex) Mega Vision +00018C (base 16) Mega Vision + 5765 Thornwood Drive + Goleta CA 93117 + US + +00-01-8F (hex) Kenetec, Inc. +00018F (base 16) Kenetec, Inc. + 115 Hurley Road + Oxford CT 06748 + US + +00-01-7B (hex) Heidelberger Druckmaschinen AG +00017B (base 16) Heidelberger Druckmaschinen AG + Kurfürsten-Anlage 52-60 + + DE + +00-01-9C (hex) JDS Uniphase Inc. +00019C (base 16) JDS Uniphase Inc. + 570 West Hunt Club Road + + CA + +00-01-A3 (hex) GENESYS LOGIC, INC. +0001A3 (base 16) GENESYS LOGIC, INC. + 10F, No. 11, Ln.3., + + TW + +00-01-82 (hex) DICA TECHNOLOGIES AG +000182 (base 16) DICA TECHNOLOGIES AG + Rotherstr, 19 + + DE + +00-01-89 (hex) Refraction Technology, Inc. +000189 (base 16) Refraction Technology, Inc. + 2626 Lombardy Lane - Ste. #105 + Dallas TX 75220 + US + +00-01-93 (hex) Hanbyul Telecom Co., Ltd. +000193 (base 16) Hanbyul Telecom Co., Ltd. + 5th Fl. Oksan Bldg. + KOREA + KR + +00-30-F5 (hex) Wild Lab. Ltd. +0030F5 (base 16) Wild Lab. Ltd. + 1-33-17-604 Harayama + Urawa City Saitama prif. 336-0931 + JP + +00-01-5D (hex) Oracle Corporation +00015D (base 16) Oracle Corporation + 500 Oracle Parkway + Redwood Shores CA 94065 + US + +00-01-73 (hex) AMCC +000173 (base 16) AMCC + 6290 Sequence Drive + San Diego CA 92121 + US + +00-01-6C (hex) FOXCONN +00016C (base 16) FOXCONN + 105 S Puente St. + Brea CA 92821 + US + +00-01-75 (hex) Radiant Communications Corp. +000175 (base 16) Radiant Communications Corp. + 5001 Hadley Road + South Plainfield NJ 07080 + US + +00-01-AF (hex) Artesyn Embedded Technologies +0001AF (base 16) Artesyn Embedded Technologies + 2900 S. Diablo Way + Tempe AZ 85282 + US + +00-01-8A (hex) ROI COMPUTER AG +00018A (base 16) ROI COMPUTER AG + Werner-von-Siemens-Str. 1 + + DE + +00-01-92 (hex) Texas Digital Systems +000192 (base 16) Texas Digital Systems + 400 Technology Parkway + College Station TX 77845 + US + +00-01-5C (hex) CADANT INC. +00015C (base 16) CADANT INC. + 4343 Commerce Court - Ste. #207 + Lisle IL 60532 + US + +00-01-69 (hex) Celestix Networks Pte Ltd. +000169 (base 16) Celestix Networks Pte Ltd. + 18 Tannery Lane #05-03 + SINGAPORE 347780 + SG + +00-01-6B (hex) LightChip, Inc. +00016B (base 16) LightChip, Inc. + 5 Industrial Way + Salem NH 03079 + US + +00-01-B6 (hex) SAEJIN T&M Co., Ltd. +0001B6 (base 16) SAEJIN T&M Co., Ltd. + 2nd Fl., Saejin Bldg., 689 + KOREA + KR + +00-01-AB (hex) Main Street Networks +0001AB (base 16) Main Street Networks + 4030 Moorpark Ave. + San Jose CA 95117-1849 + US + +00-01-45 (hex) WINSYSTEMS, INC. +000145 (base 16) WINSYSTEMS, INC. + 715 Stadium Drive + Arlington TX 76011 + US + +00-01-37 (hex) IT Farm Corporation +000137 (base 16) IT Farm Corporation + Asashiseimei Fuchu Bldg. 11F + 183-0055 + JP + +00-01-3C (hex) TIW SYSTEMS +00013C (base 16) TIW SYSTEMS + 2211 Lawson Lane + Santa Clara CA 95054 + US + +00-01-33 (hex) KYOWA Electronic Instruments C +000133 (base 16) KYOWA Electronic Instruments C + 3-5-1, Cyofugaoka + Cyofu Tokyo + JP + +00-01-A5 (hex) Nextcomm, Inc. +0001A5 (base 16) Nextcomm, Inc. + 12413 Willows Road NE - Ste. #210 + Kirkland WA 98034 + US + +00-01-90 (hex) SMK-M +000190 (base 16) SMK-M + 1055 Tierra Del Rey + Chula Vista CA 91910 + US + +00-01-4C (hex) Berkeley Process Control +00014C (base 16) Berkeley Process Control + 4124 Lakeside Dr + Richmond CA 94806 + US + +00-01-43 (hex) Cisco Systems, Inc +000143 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-01-4B (hex) Ennovate Networks, Inc. +00014B (base 16) Ennovate Networks, Inc. + 60 Codman Hill Road + Boxborough MA 01719 + US + +00-01-3D (hex) RiscStation Ltd. +00013D (base 16) RiscStation Ltd. + 168 Elliott Street + UNITED KINGDOM + GB + +00-01-20 (hex) OSCILLOQUARTZ S.A. +000120 (base 16) OSCILLOQUARTZ S.A. + Rue Des Brevards 16 + 2002 Neuchatel + CH + +00-30-46 (hex) Controlled Electronic Manageme +003046 (base 16) Controlled Electronic Manageme + Unit 4 Ravenhill Business Park + Belfast + IE + +00-30-98 (hex) Global Converging Technologies +003098 (base 16) Global Converging Technologies + 1800 Preston Park Blvd. + Plano TX 75093 + US + +00-30-0D (hex) MMC Technology, Inc. +00300D (base 16) MMC Technology, Inc. + #1502, Seoul Venture Town, Aju Bldg + Seoul 135-080 + KR + +00-30-75 (hex) ADTECH +003075 (base 16) ADTECH + RUE DU VAL ST LAMBERT 191 / i + SERAING 4100 + BE + +00-B0-69 (hex) Honewell Oy +00B069 (base 16) Honewell Oy + P.O. Box 168, FIN-78201 + + FI + +00-B0-C2 (hex) Cisco Systems, Inc +00B0C2 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-B0-3B (hex) HiQ Networks +00B03B (base 16) HiQ Networks + 2475 Augustine Drive + Santa Clara CA 95054 + US + +00-01-27 (hex) OPEN Networks Pty Ltd +000127 (base 16) OPEN Networks Pty Ltd + Level 5, 342 Flinders Street + Melbourne VIC 3000 + AU + +00-01-0E (hex) Bri-Link Technologies Co., Ltd +00010E (base 16) Bri-Link Technologies Co., Ltd + 2F, No. 63, Chow-Tze Street + Taipei 114 + TW + +00-30-37 (hex) Packard Bell Nec Services +003037 (base 16) Packard Bell Nec Services + 299 avenue Patton, BP 645 + 49006 Angers Cedex 01 + FR + +00-30-57 (hex) QTelNet, Inc. +003057 (base 16) QTelNet, Inc. + 400 - 3115 12th Street NE + Calgary Alberta T2E 7J2 + CA + +00-30-FC (hex) Terawave Communications, Inc. +0030FC (base 16) Terawave Communications, Inc. + 30695 Huntwood Avenue + Hayward CA 94544 + US + +00-B0-86 (hex) LocSoft Limited +00B086 (base 16) LocSoft Limited + 7 Bright Street + Clitheroe Lancashire BB7 1NW + GB + +00-30-A2 (hex) Lightner Engineering +0030A2 (base 16) Lightner Engineering + 8551 La Jolla Shores Dr + La Jolla CA 92037 + US + +00-30-42 (hex) DeTeWe-Deutsche Telephonwerke +003042 (base 16) DeTeWe-Deutsche Telephonwerke + Zeughofstrasse 1 + D-10997 Berlin + DE + +00-B0-C7 (hex) Tellabs Operations, Inc. +00B0C7 (base 16) Tellabs Operations, Inc. + One Tellabs Center + Naperville IL 60563 + US + +00-B0-2A (hex) ORSYS GmbH +00B02A (base 16) ORSYS GmbH + Am Stadtgraben 25 + D-88677 Markdorf + DE + +00-01-04 (hex) DVICO Co., Ltd. +000104 (base 16) DVICO Co., Ltd. + Kookmin Card B/D 6F 267-2 + Sungnam-si Kyungki-do 463-050 + KR + +00-01-06 (hex) Tews Datentechnik GmbH +000106 (base 16) Tews Datentechnik GmbH + Am Bahnhof 7 + 25469 Halstenbek + DE + +00-01-09 (hex) Nagano Japan Radio Co., Ltd. +000109 (base 16) Nagano Japan Radio Co., Ltd. + Shimohigano 1163, Inasato-machi + Nagano 381-2288 + JP + +00-02-9C (hex) 3COM +00029C (base 16) 3COM + 405 SPRING HILL ROAD + SHARON NH 03458 + US + +00-B0-19 (hex) UTC CCS +00B019 (base 16) UTC CCS + 791 Commerce Blvd + Boca Raton FL 33497 + US + +00-30-6F (hex) SEYEON TECH. CO., LTD. +00306F (base 16) SEYEON TECH. CO., LTD. + NAMCHEON BLDG. 6F, + KOREA 135-280 + KR + +00-30-3D (hex) IVA CORPORATION +00303D (base 16) IVA CORPORATION + 142 NORTH RD STE R + SUDBURY MA 01776 + US + +00-30-F4 (hex) STARDOT TECHNOLOGIES +0030F4 (base 16) STARDOT TECHNOLOGIES + 6820-H ORANGE THORPE AVE. + BUENA PARK CA 90620 + US + +00-30-52 (hex) ELASTIC NETWORKS +003052 (base 16) ELASTIC NETWORKS + 6120 WINDWARD PARKWAY -STE#100 + ALPHARETTA GA 30005 + US + +00-30-19 (hex) Cisco Systems, Inc +003019 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-76 (hex) Akamba Corporation +003076 (base 16) Akamba Corporation + 15595 Los Gatos Blvd. + Los Gatos CA 95032 + US + +00-30-EC (hex) BORGARDT +0030EC (base 16) BORGARDT + DIESELSTR. 15 + + DE + +00-30-F3 (hex) At Work Computers +0030F3 (base 16) At Work Computers + P.O. Box 947 + Corvallis OR 97339 + US + +00-30-CC (hex) Tenor Networks, Inc. +0030CC (base 16) Tenor Networks, Inc. + 100 Nagog Park + Acton MA 01720-3409 + US + +00-30-B0 (hex) Convergenet Technologies +0030B0 (base 16) Convergenet Technologies + 2222 Trade Zone Boulevard + San Jose CA 95131 + US + +00-30-EB (hex) TURBONET COMMUNICATIONS, INC. +0030EB (base 16) TURBONET COMMUNICATIONS, INC. + 19F-1, NO. 171, SUNG-TEH ROAD + TAIPEI + TW + +00-30-A1 (hex) WEBGATE Inc. +0030A1 (base 16) WEBGATE Inc. + 4F, Pika Bldg., 894-20, Hoyke 2-dong + Anyang-Si Kyunggi-Do + KR + +00-30-6A (hex) PENTA MEDIA CO., LTD. +00306A (base 16) PENTA MEDIA CO., LTD. + E-504 Bundang Technopark,151 + Seongnam Gyeonggi-do + KR + +00-30-86 (hex) Transistor Devices, Inc. +003086 (base 16) Transistor Devices, Inc. + 36A Newburgh Road + Hackettstown NJ 07840 + US + +00-30-44 (hex) CradlePoint, Inc +003044 (base 16) CradlePoint, Inc + 805 W. Franklin St. + Boise ID 83702 + US + +00-30-C2 (hex) COMONE +0030C2 (base 16) COMONE + Parc De Marticot + 33610 Cestas + FR + +00-30-53 (hex) Basler AG +003053 (base 16) Basler AG + An Der Strusbek 60-62 + 22926 Ahrensburg + DE + +00-30-D2 (hex) WIN TECHNOLOGIES, CO., LTD. +0030D2 (base 16) WIN TECHNOLOGIES, CO., LTD. + 4F-6, No. 81, Sec. 1 + Taipei + TW + +00-30-59 (hex) KONTRON COMPACT COMPUTERS AG +003059 (base 16) KONTRON COMPACT COMPUTERS AG + Nordstrasse 11/F + LUTERBACH 4542 + CH + +00-30-97 (hex) AB Regin +003097 (base 16) AB Regin + Box 366 + SE-26123 Landskrona + SE + +00-30-5F (hex) Hasselblad +00305F (base 16) Hasselblad + Hejrevej 30 + Copenhagen NV DK-2400 + DK + +00-30-DC (hex) RIGHTECH CORPORATION +0030DC (base 16) RIGHTECH CORPORATION + 4F, NO. 351, CHUNG-SHUN RD. + TAIWAN TAIWAN R.O.C. + TW + +00-30-25 (hex) CHECKOUT COMPUTER SYSTEMS, LTD +003025 (base 16) CHECKOUT COMPUTER SYSTEMS, LTD + TOWNSEND FARM ROAD + UNITED KINGDOM + GB + +00-30-12 (hex) DIGITAL ENGINEERING LTD. +003012 (base 16) DIGITAL ENGINEERING LTD. + 2 TRENCH ROAD, MALLUSK + NORTHERN + IE + +00-30-C6 (hex) CONTROL SOLUTIONS, INC. +0030C6 (base 16) CONTROL SOLUTIONS, INC. + 201 85TH AVENUE NW + MINNEAPOLIS MN 55433 + US + +00-30-D6 (hex) MSC VERTRIEBS GMBH +0030D6 (base 16) MSC VERTRIEBS GMBH + INDUSTRIESTR. 16 + + DE + +00-30-41 (hex) SAEJIN T & M CO., LTD. +003041 (base 16) SAEJIN T & M CO., LTD. + 2ND FL., SAEJIN BLDG. 689 + 135-230 KOREA + KR + +00-30-8C (hex) Quantum Corporation +00308C (base 16) Quantum Corporation + 10125 Federal Drive + Colorado Springs CO 80908 + US + +00-30-E3 (hex) SEDONA NETWORKS CORP. +0030E3 (base 16) SEDONA NETWORKS CORP. + 10A HEARST WAY + CANADA K2L 2P4 + CA + +00-30-BF (hex) MULTIDATA GMBH +0030BF (base 16) MULTIDATA GMBH + Dieburger Str. 96a + + DE + +00-D0-0F (hex) SPEECH DESIGN GMBH +00D00F (base 16) SPEECH DESIGN GMBH + INDUSTRIESTR. 1 + + DE + +00-30-58 (hex) API MOTION +003058 (base 16) API MOTION + 45 HAZELWOOD DRIVE + AMHERST NY 14228 + US + +00-30-34 (hex) SET ENGINEERING +003034 (base 16) SET ENGINEERING + 15750 VINEYARD BLVD. STE. #100 + MORGAN HILL CA 95037 + US + +00-30-4A (hex) Fraunhofer IPMS +00304A (base 16) Fraunhofer IPMS + Maria-Reiche-Strasse 2 + Dresden 01109 + DE + +00-30-8D (hex) Pinnacle Systems, Inc. +00308D (base 16) Pinnacle Systems, Inc. + Frankfurter Str. 3c + D-38122 Braunschweig + DE + +00-30-A6 (hex) VIANET TECHNOLOGIES, LTD. +0030A6 (base 16) VIANET TECHNOLOGIES, LTD. + 8 HACHARASH STREET + + IL + +00-D0-BF (hex) PIVOTAL TECHNOLOGIES +00D0BF (base 16) PIVOTAL TECHNOLOGIES + 70 S. LAKE AVENUE - STE. #900 + PASADENA CA 91101 + US + +00-30-3C (hex) ONNTO CORP. +00303C (base 16) ONNTO CORP. + 12F-2, NO. 161 + TAIWAN TAIWAN R.O.C. + TW + +00-30-24 (hex) Cisco Systems, Inc +003024 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-30-F6 (hex) SECURELOGIX CORPORATION +0030F6 (base 16) SECURELOGIX CORPORATION + 13750 SAN PEDRO + SAN ANTONIO TX 78232 + US + +00-D0-2F (hex) VLSI TECHNOLOGY INC. +00D02F (base 16) VLSI TECHNOLOGY INC. + 8375 S. RIVER PARKWAY + TEMPE AZ 85284 + US + +00-30-D8 (hex) SITEK +0030D8 (base 16) SITEK + VIA MONTE FIORINO 9 + + IT + +00-30-16 (hex) ISHIDA CO., LTD. +003016 (base 16) ISHIDA CO., LTD. + 959-1 SHIMOMAGARI + + JP + +00-D0-B1 (hex) OMEGA ELECTRONICS SA +00D0B1 (base 16) OMEGA ELECTRONICS SA + ROUTE DE SOLEURE 68 + + CH + +00-D0-16 (hex) SCM MICROSYSTEMS, INC. +00D016 (base 16) SCM MICROSYSTEMS, INC. + 160 KNOWLES DRIVE + LOS GATOS CA 95032 + US + +00-D0-43 (hex) ZONAL RETAIL DATA SYSTEMS +00D043 (base 16) ZONAL RETAIL DATA SYSTEMS + 24 FORTH STREET + SCOTLAND + GB + +00-D0-C1 (hex) HARMONIC DATA SYSTEMS, LTD. +00D0C1 (base 16) HARMONIC DATA SYSTEMS, LTD. + 10 BEIT SHAMAI STREET + ISRAEL 67018 + IL + +00-D0-AC (hex) Commscope, Inc +00D0AC (base 16) Commscope, Inc + 140 Vista Centre Drive + Forest VA 24551 + US + +00-D0-7C (hex) KOYO ELECTRONICS INC. CO.,LTD. +00D07C (base 16) KOYO ELECTRONICS INC. CO.,LTD. + 1-171 TENJIN-CHO KODAIRA + + JP + +00-D0-BC (hex) Cisco Systems, Inc +00D0BC (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-CB (hex) DASAN CO., LTD. +00D0CB (base 16) DASAN CO., LTD. + DASAN Tower 7F, 49 Daewangpangyo-ro644beon-gil + Seonggnam-Si Gyeoenggi-do 463-4000 + KR + +00-D0-19 (hex) DAINIPPON SCREEN CORPORATE +00D019 (base 16) DAINIPPON SCREEN CORPORATE + REPRESENTATIVES OF AMERICA,INC + IRVINE CA 92614 + US + +00-D0-35 (hex) BEHAVIOR TECH. COMPUTER CORP. +00D035 (base 16) BEHAVIOR TECH. COMPUTER CORP. + 20F-B, No.98, Sec. 1, + Sijhih City Taipei County 22102 + TW + +00-D0-DB (hex) MCQUAY INTERNATIONAL +00D0DB (base 16) MCQUAY INTERNATIONAL + 13600 INDUSTRIAL PARK BLVD. + MINNEAPOLIS MN 55441 + US + +00-D0-70 (hex) LONG WELL ELECTRONICS CORP. +00D070 (base 16) LONG WELL ELECTRONICS CORP. + 4F, NO. 59-1, TSAO DI WEI + TAIWAN 222 TAIWAN 222 R.O.C. + TW + +00-D0-29 (hex) WAKEFERN FOOD CORPORATION +00D029 (base 16) WAKEFERN FOOD CORPORATION + 230 RARITAN CENTER PARKWAY + EDISON NJ 08837 + US + +00-D0-C3 (hex) VIVID TECHNOLOGY PTE, LTD. +00D0C3 (base 16) VIVID TECHNOLOGY PTE, LTD. + 1003 BUKIT MERAH CENTRAL + + SG + +00-D0-13 (hex) PRIMEX AEROSPACE COMPANY +00D013 (base 16) PRIMEX AEROSPACE COMPANY + P.O. BOX 97009 + REDMOND WA 98073-9709 + US + +00-D0-A3 (hex) VOCAL DATA, INC. +00D0A3 (base 16) VOCAL DATA, INC. + 1701 N GREENVILLE #304 + RICHARDSON TX 75081 + US + +00-D0-7E (hex) KEYCORP LTD. +00D07E (base 16) KEYCORP LTD. + P.O. BOX 199 + + AU + +00-D0-20 (hex) AIM SYSTEM, INC. +00D020 (base 16) AIM SYSTEM, INC. + 4TH FLOOR CHUNGWOO B/D 219-1 + KOREA + KR + +00-D0-C8 (hex) Prevas A/S +00D0C8 (base 16) Prevas A/S + Lyskær 3EF + DK-2730 Herlev + DK + +00-50-17 (hex) RSR S.R.L. +005017 (base 16) RSR S.R.L. + VIA SINIGAGLIA, 38 + 22075 + IT + +00-50-65 (hex) TDK-Lambda Corporation +005065 (base 16) TDK-Lambda Corporation + 36-1 Kasuminosato + Ami-Machi Inashiki-Gun Ibaraki, 300-0396 + JP + +00-50-B9 (hex) XITRON TECHNOLOGIES, INC. +0050B9 (base 16) XITRON TECHNOLOGIES, INC. + 6295-D FERRIS SQUARE + SAN DIEGO CA 92121 + US + +00-50-6B (hex) SPX-ATEG +00506B (base 16) SPX-ATEG + 802 S. MAIN STREET + WAYLAND MI 49348 + US + +00-D0-76 (hex) Bank of America +00D076 (base 16) Bank of America + 1100 Merrill Drive + Pennington NJ 08534 + US + +00-D0-51 (hex) O2 MICRO, INC. +00D051 (base 16) O2 MICRO, INC. + 2901 TASMAN DRIVE, STE.#205 + SANTA CLARA CA 95054 + US + +00-D0-BB (hex) Cisco Systems, Inc +00D0BB (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-6E (hex) TRENDVIEW RECORDERS LTD. +00D06E (base 16) TRENDVIEW RECORDERS LTD. + 4 AIRFIELD WAY + UNITED KINGDOM + GB + +00-D0-5C (hex) KATHREIN TechnoTrend GmbH +00D05C (base 16) KATHREIN TechnoTrend GmbH + Ing.- Anton-Kathrein Str. 2 + + DE + +00-D0-EA (hex) NEXTONE COMMUNICATIONS, INC. +00D0EA (base 16) NEXTONE COMMUNICATIONS, INC. + 9700 GREAT SENECA HGHWY + ROCKVILLE MD 20850 + US + +00-D0-64 (hex) MULTITEL +00D064 (base 16) MULTITEL + 2905 RUE DE CELLES + CANADA CANADA G2C-1W7 + CA + +00-D0-5E (hex) STRATABEAM TECHNOLOGY, INC. +00D05E (base 16) STRATABEAM TECHNOLOGY, INC. + 1943 LANDINGS DRIVE + MOUNTAIN VIEW CA 94043 + US + +00-D0-AA (hex) CHASE COMMUNICATIONS +00D0AA (base 16) CHASE COMMUNICATIONS + ST. LEONARDS ROAD + UNITED KINGDOM + GB + +00-D0-5D (hex) INTELLIWORXX, INC. +00D05D (base 16) INTELLIWORXX, INC. + 1819 MAIN STREET, STE #1101 + SARASOTA FL 34236 + US + +00-D0-A1 (hex) OSKAR VIERLING GMBH + CO. KG +00D0A1 (base 16) OSKAR VIERLING GMBH + CO. KG + PRETZFELDER STR. 21 + + DE + +00-D0-06 (hex) Cisco Systems, Inc +00D006 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-2A (hex) Voxent Systems Ltd. +00D02A (base 16) Voxent Systems Ltd. + Unit 2, Rowan House + Chippenham Wiltshire SN14 0SQ + GB + +00-D0-8F (hex) ARDENT TECHNOLOGIES, INC. +00D08F (base 16) ARDENT TECHNOLOGIES, INC. + 250 N. WOLFE ROAD + SUNNYVALE CA 94086 + US + +00-D0-FA (hex) Thales e-Security Ltd. +00D0FA (base 16) Thales e-Security Ltd. + Meadow View House, Crendon Industrial Estate + Aylesbury Buckinghamshire HP18 9EQ + GB + +00-D0-EB (hex) LIGHTERA NETWORKS, INC. +00D0EB (base 16) LIGHTERA NETWORKS, INC. + 10201 BUBB ROAD + CUPERTINO CA 95014 + US + +00-50-A1 (hex) CARLO GAVAZZI, INC. +0050A1 (base 16) CARLO GAVAZZI, INC. + 222 PENNBRIGHT DR. - STE.#210 + HOUSTON TX 77090 + US + +00-D0-C0 (hex) Cisco Systems, Inc +00D0C0 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-D0-68 (hex) IWILL CORPORATION +00D068 (base 16) IWILL CORPORATION + NO.10, WU-CHUAN 3 RD, + TAIWAN + TW + +00-50-29 (hex) 1394 PRINTER WORKING GROUP +005029 (base 16) 1394 PRINTER WORKING GROUP + P.O. BOX 23158 + SAN JOSE CA 95153 + US + +00-50-81 (hex) MURATA MACHINERY, LTD. +005081 (base 16) MURATA MACHINERY, LTD. + 136, TAKEDA-MUKAISHIRO-CHO + FUSHIMI-KU, KYOTO 612-8686 + JP + +00-50-AC (hex) MAPLE COMPUTER CORPORATION +0050AC (base 16) MAPLE COMPUTER CORPORATION + 2F, NO. 184, SEC. 2 + Taipei + TJ + +00-50-49 (hex) Arbor Networks Inc +005049 (base 16) Arbor Networks Inc + 6 Omni Way + Chelmsford MA 01824 + US + +00-50-0D (hex) SATORI ELECTORIC CO., LTD. +00500D (base 16) SATORI ELECTORIC CO., LTD. + TIGUSADAI 38-8 MIDORI-KU + YOKOHAMA, KANAGAWA + JP + +00-50-A3 (hex) TransMedia Communications, Inc. +0050A3 (base 16) TransMedia Communications, Inc. + 20 GREAT OAKS BLVD., #210 + SAN JOSE CA 95119 + US + +00-50-A4 (hex) IO TECH, INC. +0050A4 (base 16) IO TECH, INC. + 25971 CANNON ROAD + CLEVELAND OH 44146 + US + +00-50-5C (hex) TUNDO CORPORATION +00505C (base 16) TUNDO CORPORATION + 7 GIBOREI ISRAEL STREET + + IL + +00-50-B3 (hex) VOICEBOARD CORPORATION +0050B3 (base 16) VOICEBOARD CORPORATION + 3151 WEST FIFTH STREET + OXNARD CA 93030 + US + +00-50-8C (hex) RSI SYSTEMS +00508C (base 16) RSI SYSTEMS + 5555 W. 78TH STREET, Suite F + EDINA MN 55439 + US + +00-50-E1 (hex) NS TECH ELECTRONICS SDN BHD +0050E1 (base 16) NS TECH ELECTRONICS SDN BHD + No. 37, Lorong 23, Geylang + Singapore 388371 + SG + +00-50-DE (hex) SIGNUM SYSTEMS CORP. +0050DE (base 16) SIGNUM SYSTEMS CORP. + 1211 Flynn Rd, + Camarillo CA 93021 + US + +00-50-75 (hex) KESTREL SOLUTIONS +005075 (base 16) KESTREL SOLUTIONS + 2370 CHARLESTON ROAD + MT. VIEW CA 94043 + US + +00-50-ED (hex) ANDA NETWORKS +0050ED (base 16) ANDA NETWORKS + 2921 COPPER ROAD + SANTA CLARA CA 95051 + US + +00-50-96 (hex) SALIX TECHNOLOGIES, INC. +005096 (base 16) SALIX TECHNOLOGIES, INC. + 904 WIND RIVER LANE- STE. #101 + GAITHERSBURG MD 20878 + US + +00-50-12 (hex) CBL - GMBH +005012 (base 16) CBL - GMBH + DARMSTAEDTER STR. 81 + D-64839 MUENSTER + DE + +00-50-F2 (hex) MICROSOFT CORP. +0050F2 (base 16) MICROSOFT CORP. + ONE MICROSOFT WAY + REDMOND WA 98052-6399 + US + +00-50-4A (hex) ELTECO A.S. +00504A (base 16) ELTECO A.S. + ROSINSKA CESTA P.O. BOX C-9 + + SK + +00-50-C1 (hex) GEMFLEX NETWORKS, LTD. +0050C1 (base 16) GEMFLEX NETWORKS, LTD. + 230-6651 FRASERWOOD PL. + CANADA V6W 1J3 + CA + +00-50-CF (hex) VANLINK COMMUNICATION TECHNOLOGY RESEARCH INSTITUTE +0050CF (base 16) VANLINK COMMUNICATION TECHNOLOGY RESEARCH INSTITUTE + 210 YADI OFFICE BUILDING + BEIJING 100088 + CN + +00-50-24 (hex) NAVIC SYSTEMS, INC. +005024 (base 16) NAVIC SYSTEMS, INC. + 74 CRESCENT STREET + NEEDHAM MA + US + +00-90-BD (hex) OMNIA COMMUNICATIONS, INC. +0090BD (base 16) OMNIA COMMUNICATIONS, INC. + 100 NICKERSON ROAD + MARLBOROUGH MA 01752 + US + +00-90-B4 (hex) WILLOWBROOK TECHNOLOGIES +0090B4 (base 16) WILLOWBROOK TECHNOLOGIES + 7120 HAYVENHURST AVE.-STE.#401 + VAN NUYS CA 91406 + US + +00-90-03 (hex) APLIO +009003 (base 16) APLIO + 18 Avenue Du 8 Mai 1945 + + FR + +00-90-31 (hex) MYSTICOM, LTD. +009031 (base 16) MYSTICOM, LTD. + P.O. 8364 + NATANIA 42504 + IL + +00-90-9D (hex) NovaTech Process Solutions, LLC +00909D (base 16) NovaTech Process Solutions, LLC + 11500 Cronridge Drive + Owings Mills MD 21117 + US + +00-90-DD (hex) MIHARU COMMUNICATIONS Inc +0090DD (base 16) MIHARU COMMUNICATIONS Inc + + KANAGAWA + JP + +00-90-28 (hex) NIPPON SIGNAL CO., LTD. +009028 (base 16) NIPPON SIGNAL CO., LTD. + 11 HIRAIDE-KOGIO-DANCHI + UISUNOMIYA TOCHIGI 321-8651 + JP + +00-90-7D (hex) Lake Communications +00907D (base 16) Lake Communications + 1 Westbrook, Milton Road + + IE + +00-90-C9 (hex) DPAC Technologies +0090C9 (base 16) DPAC Technologies + 7321 Lincoln Way + Garden Grove CA 92841 + US + +00-50-7B (hex) MERLOT COMMUNICATIONS +00507B (base 16) MERLOT COMMUNICATIONS + BERKSHIRE CORPORATE PARK + BETHEL CT 06801 + US + +00-50-CD (hex) DIGIANSWER A/S +0050CD (base 16) DIGIANSWER A/S + SKALHUSE 5 + + DK + +00-50-2D (hex) ACCEL, INC. +00502D (base 16) ACCEL, INC. + 1F, NO. 7, R&D 1ST ROAD + HSINCHU + TW + +00-50-3A (hex) DATONG ELECTRONICS LTD. +00503A (base 16) DATONG ELECTRONICS LTD. + CLAYTON WOOD CLOSE + Leeds LS16 6QE + GB + +00-50-87 (hex) TERASAKI ELECTRIC CO., LTD. +005087 (base 16) TERASAKI ELECTRIC CO., LTD. + 7-2-10 HANNAN-CHO ABENO-KU + OSAKA, 545-0021 + JP + +00-50-26 (hex) COSYSTEMS, INC. +005026 (base 16) COSYSTEMS, INC. + 1263 OAKMEAD PARKWAY + SUNNYVALE CA 94086 + US + +00-90-2C (hex) DATA & CONTROL EQUIPMENT LTD. +00902C (base 16) DATA & CONTROL EQUIPMENT LTD. + COUNTY FARM, WENDOVER RD. + BUCKS. HP22 STA + GB + +00-90-1D (hex) PEC (NZ) LTD. +00901D (base 16) PEC (NZ) LTD. + 2 STATION ROAD + MARTON + NZ + +00-90-97 (hex) Sycamore Networks +009097 (base 16) Sycamore Networks + 220 Mill Rd + Chelmsford MA 01824 + US + +00-90-25 (hex) BAE Systems Australia (Electronic Systems) Pty Ltd +009025 (base 16) BAE Systems Australia (Electronic Systems) Pty Ltd + 2 Second Ave + Mawson Lakes South Australia 5095 + AU + +00-90-4C (hex) Epigram, Inc. +00904C (base 16) Epigram, Inc. + 870 West Maude Ave. + Sunnyvale CA 94086 + US + +00-90-84 (hex) ATECH SYSTEM +009084 (base 16) ATECH SYSTEM + 4F DAEBOONG BLDG. 1451-78 + SEOUL 137-070 + KR + +00-90-6A (hex) TURNSTONE SYSTEMS, INC. +00906A (base 16) TURNSTONE SYSTEMS, INC. + 274 Ferguson Drive + MOUNTAIN VIEW CA 94043 + US + +00-90-87 (hex) ITIS +009087 (base 16) ITIS + CENTRE ESPACE PERFORMANCE + 35769 SAINT-GREGOIRE CEDEX + FR + +00-90-51 (hex) ULTIMATE TECHNOLOGY CORP. +009051 (base 16) ULTIMATE TECHNOLOGY CORP. + 100 RAWSON ROAD + VICTOR NY 14564 + US + +00-90-26 (hex) ADVANCED SWITCHING COMMUNICATIONS, INC. +009026 (base 16) ADVANCED SWITCHING COMMUNICATIONS, INC. + 8330 BOONE BOULEVARD--5TH FL. + VIENNA VA 22182 + US + +00-90-D3 (hex) GIESECKE & DEVRIENT GmbH +0090D3 (base 16) GIESECKE & DEVRIENT GmbH + PRINZREGENTENSTRASSE 159 + D-81677 MUNCHEN + DE + +00-90-67 (hex) WalkAbout Computers, Inc. +009067 (base 16) WalkAbout Computers, Inc. + 2655 N. OCEAN DRIVE--STE. #510 + SINGER ISLAND FL 33404 + US + +00-90-2A (hex) COMMUNICATION DEVICES, INC. +00902A (base 16) COMMUNICATION DEVICES, INC. + 85 Fulton Street + Boonton NJ 07005-1912 + US + +00-90-0D (hex) Overland Storage Inc. +00900D (base 16) Overland Storage Inc. + 9112 Spectrum Center Blvd + SAN DIEGO CA 92123 + US + +00-90-CF (hex) NORTEL +0090CF (base 16) NORTEL + 250 SIDNEY STREET + Belleville Ontario K8N 5B7 + CA + +00-90-72 (hex) SIMRAD AS +009072 (base 16) SIMRAD AS + P.O. BOX 111 + 3191 HORTEN + NO + +00-90-2F (hex) NETCORE SYSTEMS, INC. +00902F (base 16) NETCORE SYSTEMS, INC. + 187 BALLARDVALE STREET + WILMINGTON MA 01887 + US + +00-90-98 (hex) SBC DESIGNS, INC. +009098 (base 16) SBC DESIGNS, INC. + 3077-H LEEMAN FERRY ROAD + HUNTSVILLE AL 35801 + US + +00-90-45 (hex) Marconi Communications +009045 (base 16) Marconi Communications + 1000 Fore Drive + Warrendale PA 15086-7502 + US + +00-90-36 (hex) ens, inc. +009036 (base 16) ens, inc. + P.O. BOX 19207 + RALEIGH NC 27619 + US + +00-90-8B (hex) Tattile SRL +00908B (base 16) Tattile SRL + 2600 Fernbrook Lane + Plymouth MN 55447 + US + +00-90-44 (hex) ASSURED DIGITAL, INC. +009044 (base 16) ASSURED DIGITAL, INC. + 9-11 GOLDSMITH ST. + LITTLETON MA 01460 + US + +00-90-91 (hex) DigitalScape, Inc. +009091 (base 16) DigitalScape, Inc. + 6 MORGAN - STE.#100 + IRVINE CA 92618 + US + +00-90-7E (hex) VETRONIX CORP. +00907E (base 16) VETRONIX CORP. + 2030 ALAMEDE PADRE SERRA + SANTA BARBARA CA 93103 + US + +00-90-50 (hex) Teleste Corporation +009050 (base 16) Teleste Corporation + Telestenkatu 1 + LITTOINEN FI-20660 + FI + +00-90-4D (hex) SPEC S.A. +00904D (base 16) SPEC S.A. + CASP 172 3-B + 08013 BARCELONA + ES + +00-90-FD (hex) CopperCom, Inc. +0090FD (base 16) CopperCom, Inc. + 3255-1 SCOTT BLVD.,--STE.#103 + SANTA CLARA CA 95054 + US + +00-90-39 (hex) SHASTA NETWORKS +009039 (base 16) SHASTA NETWORKS + 249 HUMBOLDT COURT + SUNNYVALE CA 94089-1300 + US + +00-90-FC (hex) NETWORK COMPUTING DEVICES +0090FC (base 16) NETWORK COMPUTING DEVICES + 301 RAVENDALE DRIVE + MOUNTAIN VIEW CA 94043 + US + +00-90-14 (hex) ROTORK INSTRUMENTS, LTD. +009014 (base 16) ROTORK INSTRUMENTS, LTD. + CHAUL END LANE + LU4 8EZ England + GB + +00-90-8D (hex) VICKERS ELECTRONICS SYSTEMS +00908D (base 16) VICKERS ELECTRONICS SYSTEMS + 1151 W. MASON-MORROW RD. + LEBANON OH 45036 + US + +00-90-42 (hex) ECCS, Inc. +009042 (base 16) ECCS, Inc. + ONE SHEILA DRIVE + TINTON FALLS NJ 07724 + US + +00-90-33 (hex) INNOVAPHONE AG +009033 (base 16) INNOVAPHONE AG + Boeblinger Str. 76 + SINDELFINGEN D71065 + DE + +00-90-02 (hex) ALLGON AB +009002 (base 16) ALLGON AB + GARDATORGET 1 + 412 50 GOTEBORG + SE + +00-10-D4 (hex) STORAGE COMPUTER CORPORATION +0010D4 (base 16) STORAGE COMPUTER CORPORATION + 11 RIVERSIDE STREET + NASHUA NH 03062 + US + +00-06-29 (hex) IBM Corp +000629 (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-10-A9 (hex) ADHOC TECHNOLOGIES +0010A9 (base 16) ADHOC TECHNOLOGIES + 1150 FIRST STREET + SAN JOSE CA 95112 + US + +00-10-8A (hex) TeraLogic, Inc. +00108A (base 16) TeraLogic, Inc. + 707 CALIFORNIA STREET + MOUNTAIN VIEW CA 94041 + US + +00-10-24 (hex) NAGOYA ELECTRIC WORKS CO., LTD +001024 (base 16) NAGOYA ELECTRIC WORKS CO., LTD + 29-1 SHINODA, MIWA-CHO + AMA-GUN, AICHI 490-12 + JP + +00-10-D6 (hex) Exelis +0010D6 (base 16) Exelis + 7310 Innovation Blvd., M/S 536 + Ft Wayne IN 46818 + US + +00-10-48 (hex) HTRC AUTOMATION, INC. +001048 (base 16) HTRC AUTOMATION, INC. + 285 LAVAL STREET + QUEBEC J0B 1H0 + CA + +00-10-97 (hex) WinNet Metropolitan Communications Systems, Inc. +001097 (base 16) WinNet Metropolitan Communications Systems, Inc. + 661 EAST ARQUES AVE. + SUNNYVALE CA 94086 + US + +00-10-85 (hex) POLARIS COMMUNICATIONS, INC. +001085 (base 16) POLARIS COMMUNICATIONS, INC. + 10200 SW ALLEN BLVD. + BEAVERTON OR 97005 + US + +00-10-0C (hex) ITO CO., LTD. +00100C (base 16) ITO CO., LTD. + 8-2 MIYANOSHITA-CHO + HIRAKATA-CITY, OSAKA + JP + +00-10-06 (hex) Thales Contact Solutions Ltd. +001006 (base 16) Thales Contact Solutions Ltd. + Tolbar Way + Southampton, SO30 2ZP + GB + +00-90-09 (hex) I Controls, Inc. +009009 (base 16) I Controls, Inc. + 2nd Fl, I'Park 302, 11 Jeongja-Dong, + Seongnam Gyeonggi-Do 463-859 + KR + +00-90-8E (hex) Nortel Networks Broadband Access +00908E (base 16) Nortel Networks Broadband Access + 39660 Eureka Drive + Newark CA 94560 + US + +00-90-7C (hex) DIGITALCAST, INC. +00907C (base 16) DIGITALCAST, INC. + 503, ILKWANG BLDG., 1656-2 + SEOCHO-KU SEOUL + KR + +00-90-D2 (hex) ARTEL VIDEO SYSTEMS +0090D2 (base 16) ARTEL VIDEO SYSTEMS + 237 CEDAR HILL ST. + MARLBORO MA 01752 + US + +00-01-FE (hex) DIGITAL EQUIPMENT CORPORATION +0001FE (base 16) DIGITAL EQUIPMENT CORPORATION + 301 ROCKRIMMON BLVD, SOUTH + COLORADO SPRINGS CO 80919 + US + +00-90-BE (hex) IBC/INTEGRATED BUSINESS COMPUTERS +0090BE (base 16) IBC/INTEGRATED BUSINESS COMPUTERS + 2685 C PARK CENTER DRIVE + SIMI VALLEY CA 93065 + US + +00-10-3C (hex) IC ENSEMBLE, INC. +00103C (base 16) IC ENSEMBLE, INC. + 3255-2 SCOTT BLVD.--STE.#105 + SANTA CLARA CA 95054 + US + +00-10-19 (hex) SIRONA DENTAL SYSTEMS GmbH & Co. KG +001019 (base 16) SIRONA DENTAL SYSTEMS GmbH & Co. KG + FABRIKSTRASSE 31 + 64625 BENSHEIM + DE + +00-90-DE (hex) CARDKEY SYSTEMS, INC. +0090DE (base 16) CARDKEY SYSTEMS, INC. + 1757 TAPO CANYON ROAD + SIMI VALLEY CA 93063 + US + +00-90-6B (hex) APPLIED RESOURCES, INC. +00906B (base 16) APPLIED RESOURCES, INC. + 9821 WIDMER ROAD + LENEXA KS 66215-1239 + US + +00-10-E2 (hex) ArrayComm, Inc. +0010E2 (base 16) ArrayComm, Inc. + 3141 ZANKER ROAD + SAN JOSE CA 95134 + US + +00-10-D2 (hex) NITTO TSUSHINKI CO., LTD +0010D2 (base 16) NITTO TSUSHINKI CO., LTD + 7-27-11, TODOROKI, SETAGAYA-KU + TOKYO 151 + JP + +00-10-D9 (hex) IBM JAPAN, FUJISAWA MT+D +0010D9 (base 16) IBM JAPAN, FUJISAWA MT+D + KIRIHARA-CHO 1, FUJISAWA CITY + KANAGAWA 252 + JP + +00-90-66 (hex) Troika Networks, Inc. +009066 (base 16) Troika Networks, Inc. + 2829 Townsgate Road, + Westlake Village CA 91361 + US + +00-10-94 (hex) Performance Analysis Broadband, Spirent plc +001094 (base 16) Performance Analysis Broadband, Spirent plc + 27349 Agoura Road + Calabasas Hills CA 91301 + US + +00-10-50 (hex) RION CO., LTD. +001050 (base 16) RION CO., LTD. + 3-20-41 HIGASHIMOTOMACHI + KOKUBUNJI, TOKYO 185 + JP + +00-10-9C (hex) M-SYSTEM CO., LTD. +00109C (base 16) M-SYSTEM CO., LTD. + 1-1-25 SHIN URASHIMA CHOU + YOKOHAMA 221 + JP + +00-10-CE (hex) VOLAMP, LTD. +0010CE (base 16) VOLAMP, LTD. + UNIT 3 RIVERSIDE BUSINESS PARK + FARNHAM, SURREY ENGLAND + GB + +00-10-B2 (hex) COACTIVE AESTHETICS +0010B2 (base 16) COACTIVE AESTHETICS + 4000 BRIDGEWAY - STE. #303 + SAUSALITA CA 94965 + US + +00-10-5F (hex) ZODIAC DATA SYSTEMS +00105F (base 16) ZODIAC DATA SYSTEMS + 5 Av Des Andes + Les Ulis 91940 + FR + +00-10-3E (hex) NETSCHOOLS CORPORATION +00103E (base 16) NETSCHOOLS CORPORATION + 2003 LANDINGS DRIVE + MOUNTAIN VIEW CA 94043 + US + +00-10-CB (hex) FACIT K.K. +0010CB (base 16) FACIT K.K. + HIMEI NIHOMBASHI BLDG. 3F + CHUO-KU, TOKYO 103 + JP + +00-10-E0 (hex) Oracle Corporation +0010E0 (base 16) Oracle Corporation + 500 Oracle Parkway + Redwood Shores CA 94065 + US + +00-10-7C (hex) P-COM, INC. +00107C (base 16) P-COM, INC. + 3175 S. WINCHESTER BLVD. + CAMPBELL CA 95008 + US + +00-10-BD (hex) THE TELECOMMUNICATION TECHNOLOGY COMMITTEE (TTC) +0010BD (base 16) THE TELECOMMUNICATION TECHNOLOGY COMMITTEE (TTC) + 1-1-12 Shiba Kouen, Minato-ku + MINATO-KU, TOKYO 105-0011 + JP + +00-10-08 (hex) VIENNA SYSTEMS CORPORATION +001008 (base 16) VIENNA SYSTEMS CORPORATION + 6651 FRASERWOOD PLACE + RICHMOND, B.C. V6W 1J3 + CA + +00-10-D1 (hex) Top Layer Networks, Inc. +0010D1 (base 16) Top Layer Networks, Inc. + 4 MECHANIC ST.- STE#212 + NATICK MA 01760 + US + +00-10-6A (hex) DIGITAL MICROWAVE CORPORATION +00106A (base 16) DIGITAL MICROWAVE CORPORATION + 170 ROSE ORCHARD WAY + SAN JOSE CA 95134 + US + +00-10-6F (hex) TRENTON TECHNOLOGY INC. +00106F (base 16) TRENTON TECHNOLOGY INC. + 2350 CENTENNIAL DRIVE + GAINESVILLE GA 30504 + US + +00-10-34 (hex) GNP Computers +001034 (base 16) GNP Computers + 555 E.Huntington Drive + Monrovia CA 91016 + US + +00-10-44 (hex) InnoLabs Corporation +001044 (base 16) InnoLabs Corporation + 2F-4, NO. 16, LANE 609, CHUNG-HSIN RD. + Taipei Hsien + TW + +00-10-A1 (hex) KENDIN SEMICONDUCTOR, INC. +0010A1 (base 16) KENDIN SEMICONDUCTOR, INC. + 1550 S. BASCOM AVE., STE. #250 + CAMPBELL CA 95008 + US + +00-10-A8 (hex) RELIANCE COMPUTER CORP. +0010A8 (base 16) RELIANCE COMPUTER CORP. + 3032 BUNKER HILL LANE + SANTA CLARA CA 95054 + US + +00-10-6E (hex) TADIRAN COM. LTD. +00106E (base 16) TADIRAN COM. LTD. + 26 HASHOFTIM ST. + HOLON 58102 + IL + +00-10-9A (hex) NETLINE +00109A (base 16) NETLINE + 7, Rue de Bievres + 92140 CLAMART + FR + +00-10-89 (hex) WebSonic +001089 (base 16) WebSonic + 3466 EDWARD AVE. + SANTA CLARA CA 95054 + US + +00-10-E6 (hex) APPLIED INTELLIGENT SYSTEMS, INC. +0010E6 (base 16) APPLIED INTELLIGENT SYSTEMS, INC. + 3923 RANCHERO DRIVE + ANN ARBOR MI 48108 + US + +00-10-3B (hex) HIPPI NETWORKING FORUM +00103B (base 16) HIPPI NETWORKING FORUM + PO BOX 10173 + ALBUQUERQUE NM 87184-0173 + US + +00-E0-B7 (hex) PI GROUP, LTD. +00E0B7 (base 16) PI GROUP, LTD. + MILTON HALL, CHURCH LANE + MILTON, CAMBRIDGE CBA 6AB + GB + +00-E0-83 (hex) JATO TECHNOLOGIES, INC. +00E083 (base 16) JATO TECHNOLOGIES, INC. + 505 EAST HUNTLAND DR. STE #550 + AUSTIN TX 78752 + US + +00-E0-72 (hex) LYNK +00E072 (base 16) LYNK + RABIN BUILDING + D.N. MISGAV 201 + IL + +00-E0-AD (hex) EES TECHNOLOGY, LTD. +00E0AD (base 16) EES TECHNOLOGY, LTD. + 25 EASTWAYS + WITHAM, ESSEX, CM8 3AL + GB + +00-E0-94 (hex) OSAI SRL +00E094 (base 16) OSAI SRL + VIA TORINO + 603-IVREA (TO) + IT + +00-E0-32 (hex) MISYS FINANCIAL SYSTEMS, LTD. +00E032 (base 16) MISYS FINANCIAL SYSTEMS, LTD. + BUCKHOLT DRIVE, + WARNDON, WORCESTER WR49SR + GB + +00-E0-C0 (hex) SEIWA ELECTRIC MFG. CO., LTD. +00E0C0 (base 16) SEIWA ELECTRIC MFG. CO., LTD. + 86 TARADA SHIN-IKE, + KYOTO PREFECTURE + JP + +00-E0-D1 (hex) TELSIS LIMITED +00E0D1 (base 16) TELSIS LIMITED + 16 BARNES WALLACE ROAD + FAREHAM, HAMPSHIRE PO15 5TT ENGLAND + GB + +00-E0-F0 (hex) ABLER TECHNOLOGY, INC. +00E0F0 (base 16) ABLER TECHNOLOGY, INC. + 4F, NO. 54 SEC. 4 + TAIPEI + TW + +00-E0-02 (hex) CROSSROADS SYSTEMS, INC. +00E002 (base 16) CROSSROADS SYSTEMS, INC. + 9390 RESEARCH BLVD. + AUSTIN TX 78759 + US + +00-E0-D6 (hex) COMPUTER & COMMUNICATION RESEARCH LAB. +00E0D6 (base 16) COMPUTER & COMMUNICATION RESEARCH LAB. + + CHUTUNG, HSINCHU + TW + +00-E0-74 (hex) TIERNAN COMMUNICATIONS, INC. +00E074 (base 16) TIERNAN COMMUNICATIONS, INC. + 11025 ROSELLE ST. + SAN DIEGO CA 92121 + US + +00-E0-D9 (hex) TAZMO CO., LTD. +00E0D9 (base 16) TAZMO CO., LTD. + 6186 KINOKO, IBARA-SHI + OKAYAMA 715 + JP + +00-E0-55 (hex) INGENIERIA ELECTRONICA COMERCIAL INELCOM S.A. +00E055 (base 16) INGENIERIA ELECTRONICA COMERCIAL INELCOM S.A. + CL. PIQUER NO.3 + 28033 MADRID + ES + +00-E0-B4 (hex) TECHNO SCOPE CO., LTD. +00E0B4 (base 16) TECHNO SCOPE CO., LTD. + 13-6-7 KISHIMATI URAWASI + SAITAMA 336 + JP + +00-E0-71 (hex) EPIS MICROCOMPUTER +00E071 (base 16) EPIS MICROCOMPUTER + LAUTLINGER STRASSE 147 + 72458 ALBSTADT + DE + +00-E0-66 (hex) ProMax Systems, Inc. +00E066 (base 16) ProMax Systems, Inc. + 16 TECHNOLOGY DRIVE--BLDG.#106 + IRVINE CA 92656 + US + +00-E0-93 (hex) ACKFIN NETWORKS +00E093 (base 16) ACKFIN NETWORKS + 575 N. PASTORIA AVE. + SUNNYVALE CA 94086 + US + +00-E0-42 (hex) Pacom Systems Ltd. +00E042 (base 16) Pacom Systems Ltd. + UNIT 22 38/46 SOUTH ST. + RYDALMERE 2116 NSW + AU + +00-E0-EB (hex) DIGICOM SYSTEMS, INCORPORATED +00E0EB (base 16) DIGICOM SYSTEMS, INCORPORATED + 188 TOPAZ STREET + MILPITAS CA 95035 + US + +00-E0-1C (hex) Cradlepoint, Inc +00E01C (base 16) Cradlepoint, Inc + 1199 Shoreline Lane + Boise ID 83702 + US + +00-E0-27 (hex) DUX, INC. +00E027 (base 16) DUX, INC. + 5-18-19, NISHIKAMATA, OTA-KU + TOKYO-TO, 144 + JP + +00-E0-4B (hex) JUMP INDUSTRIELLE COMPUTERTECHNIK GmbH +00E04B (base 16) JUMP INDUSTRIELLE COMPUTERTECHNIK GmbH + + D94469 DEGGENDORF + DE + +00-E0-97 (hex) CARRIER ACCESS CORPORATION +00E097 (base 16) CARRIER ACCESS CORPORATION + 5395 PEARL PARKWAY + BOULDER CO 80301 + US + +00-E0-89 (hex) ION Networks, Inc. +00E089 (base 16) ION Networks, Inc. + 1551 South Washington Ave. + Piscataway NJ 08854 + US + +00-E0-70 (hex) DH TECHNOLOGY +00E070 (base 16) DH TECHNOLOGY + 3003 ROLLIE GATES DRIVE + PASO ROBLES CA 93446 + US + +00-E0-5C (hex) PHC Corporation +00E05C (base 16) PHC Corporation + 2-38-5 Nishishimbashi + Minato-ku Tokyo 105-8433 + JP + +00-E0-24 (hex) GADZOOX NETWORKS +00E024 (base 16) GADZOOX NETWORKS + 5850 HELLYER AVENUE + SAN JOSE CA 95138 + US + +00-60-5B (hex) IntraServer Technology, Inc. +00605B (base 16) IntraServer Technology, Inc. + 125 HOPPING BROOK PARK + HOLLISTON MA 01746 + US + +00-60-D7 (hex) ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE (EPFL) +0060D7 (base 16) ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE (EPFL) + ECUBLENS + CH-1015 LAUSANNE + CH + +00-E0-BA (hex) BERGHOF AUTOMATIONSTECHNIK GmbH +00E0BA (base 16) BERGHOF AUTOMATIONSTECHNIK GmbH + HARRET STRASSE 1 + D 72800 ENINGEN + DE + +00-E0-21 (hex) FREEGATE CORP. +00E021 (base 16) FREEGATE CORP. + 710 LAKEWAY STE.#230 + SUNNYVALE CA 94086 + US + +00-E0-5B (hex) WEST END SYSTEMS CORP. +00E05B (base 16) WEST END SYSTEMS CORP. + 39 WINNER'S CIRCLE DR., + ARNPRIOR, ONTARIO K7S 3G9 + CA + +00-E0-44 (hex) LSICS CORPORATION +00E044 (base 16) LSICS CORPORATION + 3-8-3 NINOMIYA, TSKUKUBA SHI + IBARAGI-KEN, 305 + JP + +00-E0-CA (hex) BEST DATA PRODUCTS +00E0CA (base 16) BEST DATA PRODUCTS + 21800 NORDHOFF STREET + CHATSWORTH CA 91311 + US + +00-E0-A7 (hex) IPC INFORMATION SYSTEMS, INC. +00E0A7 (base 16) IPC INFORMATION SYSTEMS, INC. + METRO CENTER + STAMFORD CT 06907 + US + +00-E0-62 (hex) HOST ENGINEERING +00E062 (base 16) HOST ENGINEERING + 200 EAST MAIN STREET -STE.#700 + JOHNSON CITY TN 37604 + US + +00-E0-CE (hex) ARN +00E0CE (base 16) ARN + 51, RUE GASTON LAURIAU + F-93512 MONTREUIL CEDEX + FR + +00-E0-5F (hex) e-Net, Inc. +00E05F (base 16) e-Net, Inc. + 12325 HYMEADOW DRIVE + AUSTIN TX 78750 + US + +00-E0-1F (hex) AVIDIA Systems, Inc. +00E01F (base 16) AVIDIA Systems, Inc. + 135 NORTH PLAINS INDUSTRIAL RD + WALLINGFORD CT 06492 + US + +00-E0-D0 (hex) NETSPEED, INC. +00E0D0 (base 16) NETSPEED, INC. + 12303 TECHNOLOGY BLVD. + AUSTIN TX 78727 + US + +00-E0-60 (hex) SHERWOOD +00E060 (base 16) SHERWOOD + 21056 FORBES STREET + HAYWARD CA 94545 + US + +00-E0-6A (hex) KAPSCH AG +00E06A (base 16) KAPSCH AG + WAGENSEILGASSE 1 + 1120-VIENNA + AT + +00-E0-01 (hex) STRAND LIGHTING LIMITED +00E001 (base 16) STRAND LIGHTING LIMITED + GRANT WAY + MIDDLESEX England TW7 5QD + GB + +00-E0-D8 (hex) LANBit Computer, Inc. +00E0D8 (base 16) LANBit Computer, Inc. + 12F, 552 CHUNG HSIAO E., RD. + + TW + +00-E0-E7 (hex) RAYTHEON E-SYSTEMS, INC. +00E0E7 (base 16) RAYTHEON E-SYSTEMS, INC. + 1301 E. COLLINS + RICHARDSON TX 75081 + US + +00-E0-3C (hex) AdvanSys +00E03C (base 16) AdvanSys + 1150 RINGWOOD COURT + SAN JOSE CA 95131 + US + +00-E0-73 (hex) NATIONAL AMUSEMENT NETWORK, INC. +00E073 (base 16) NATIONAL AMUSEMENT NETWORK, INC. + 401 N. MICHIGAN AVENUE + CHICAGO IL 60611 + US + +00-60-66 (hex) LACROIX Trafic +006066 (base 16) LACROIX Trafic + 1 ere Avenue, 11 eme rue + 06516 CARROS + FR + +00-60-F4 (hex) ADVANCED COMPUTER SOLUTIONS, Inc. +0060F4 (base 16) ADVANCED COMPUTER SOLUTIONS, Inc. + 12675 DANIELSON COURT + POWAY CA 92064 + US + +00-60-60 (hex) Data Innovations North America +006060 (base 16) Data Innovations North America + 120 Kimball Avenue Suite 100 + South Burlington VT 05403 + US + +00-60-35 (hex) DALLAS SEMICONDUCTOR, INC. +006035 (base 16) DALLAS SEMICONDUCTOR, INC. + 4401 SOUTH BELTWOOD PARKWAY + DALLAS TX 75244-3292 + US + +00-60-07 (hex) ACRES GAMING, INC. +006007 (base 16) ACRES GAMING, INC. + 815 NW 9TH STREET + CORVALLIS OR 97330 + US + +00-60-58 (hex) COPPER MOUNTAIN COMMUNICATIONS, INC. +006058 (base 16) COPPER MOUNTAIN COMMUNICATIONS, INC. + 6650 LUSK BLVD.-STE #B103 + SAN DIEGO CA 92121 + US + +00-60-FB (hex) PACKETEER, INC. +0060FB (base 16) PACKETEER, INC. + 10201 N. DE ANZA BOULEVARD + CUPERTINO CA 95014 + US + +00-60-C1 (hex) WaveSpan Corporation +0060C1 (base 16) WaveSpan Corporation + 500 N. BERNARDO AVE. + MOUNTAIN VIEW CA 94043 + US + +00-60-3C (hex) HAGIWARA SYS-COM CO., LTD. +00603C (base 16) HAGIWARA SYS-COM CO., LTD. + 2-4-3 NISHIKI NAKA-KU + AICHI 460 + JP + +00-60-7D (hex) SENTIENT NETWORKS INC. +00607D (base 16) SENTIENT NETWORKS INC. + 2201 CANTU COURT-STE #205 + SARASOTA FL 34232 + US + +00-60-19 (hex) Roche Diagnostics +006019 (base 16) Roche Diagnostics + 9115 Hague Road + Indianapolis IN 46250-0457 + US + +00-60-59 (hex) TECHNICAL COMMUNICATIONS CORP. +006059 (base 16) TECHNICAL COMMUNICATIONS CORP. + 100 DOMINO DRIVE + CONCORD MA 01742 + US + +00-60-03 (hex) TERAOKA WEIGH SYSTEM PTE, LTD. +006003 (base 16) TERAOKA WEIGH SYSTEM PTE, LTD. + 3A TUAS AVENUE 8 + SINGAPORE 639128 + SG + +00-60-7A (hex) DVS GMBH +00607A (base 16) DVS GMBH + KREPENSTRASSE 8 + D-30165 HANNOVER + DE + +00-60-F3 (hex) Performance Analysis Broadband, Spirent plc +0060F3 (base 16) Performance Analysis Broadband, Spirent plc + 27349 Agoura Road + Calabasas Hills CA 91301 + US + +00-60-7C (hex) WaveAccess, Ltd. +00607C (base 16) WaveAccess, Ltd. + P.O. BOX 2473 + RA'ANANA 43663 + IL + +00-60-A0 (hex) SWITCHED NETWORK TECHNOLOGIES, INC. +0060A0 (base 16) SWITCHED NETWORK TECHNOLOGIES, INC. + 13805 1ST AVENUE NORTH + PLYMOUTH MN 55441-5455 + US + +00-60-17 (hex) TOKIMEC INC. +006017 (base 16) TOKIMEC INC. + 2-16, MINAMI-KAMATA, OHTA-KU + TOKYO 144 + JP + +00-60-26 (hex) VIKING Modular Solutions +006026 (base 16) VIKING Modular Solutions + 11 COLUMBIA + LAGUNA HILLS CA 92656 + US + +00-60-6E (hex) DAVICOM SEMICONDUCTOR, INC. +00606E (base 16) DAVICOM SEMICONDUCTOR, INC. + 2457 AUGUSTINE DRIVE + SANTA CLARA CA 95054 + US + +00-60-C7 (hex) AMATI COMMUNICATIONS CORP. +0060C7 (base 16) AMATI COMMUNICATIONS CORP. + 2043 SAMARITAN DRIVE + SAN JOSE CA 95124 + US + +10-00-E8 (hex) NATIONAL SEMICONDUCTOR +1000E8 (base 16) NATIONAL SEMICONDUCTOR + 2900 SEMICONDUCTOR DRIVE + SANTA CLARA CA 95051 + US + +00-60-73 (hex) REDCREEK COMMUNICATIONS, INC. +006073 (base 16) REDCREEK COMMUNICATIONS, INC. + 3900 NEWPARK MALL ROAD + NEWARK CA 94560 + US + +00-60-FD (hex) NetICs, Inc. +0060FD (base 16) NetICs, Inc. + 42 NAGOG PARK + ACTON MA 01720 + US + +00-60-CB (hex) HITACHI ZOSEN CORPORATION +0060CB (base 16) HITACHI ZOSEN CORPORATION + 3-4, SAKURAJIMA 1-CHOME + KONOHANA-KU, OSAKA 554 + JP + +00-60-C8 (hex) KUKA WELDING SYSTEMS & ROBOTS +0060C8 (base 16) KUKA WELDING SYSTEMS & ROBOTS + BLUECHERSTRASSE 144 + D-86165 AUGSBURG + DE + +00-60-23 (hex) PERICOM SEMICONDUCTOR CORP. +006023 (base 16) PERICOM SEMICONDUCTOR CORP. + 2380 BERING DRIVE + SAN JOSE CA 95131 + US + +00-60-63 (hex) PSION DACOM PLC. +006063 (base 16) PSION DACOM PLC. + PSION DACOM HOUSE + CROWNHILL MILTON KEYNES MK8 0EF + GB + +00-60-31 (hex) HRK SYSTEMS +006031 (base 16) HRK SYSTEMS + P.O. BOX 514 + WESTVILLE 3630 + ZA + +00-60-0E (hex) WAVENET INTERNATIONAL, INC. +00600E (base 16) WAVENET INTERNATIONAL, INC. + 5825 KENNEDY ROAD + MISSISSAUGA, ONTARIO L4Z 2G3 + CA + +00-60-A3 (hex) CONTINUUM TECHNOLOGY CORP. +0060A3 (base 16) CONTINUUM TECHNOLOGY CORP. + 220 CONTINUUM DRIVE + FLETCHER NC 28732 + US + +00-60-3D (hex) 3CX +00603D (base 16) 3CX + 2085 HAMILTON AVE., -STE.#220 + SAN JOSE CA 95125 + US + +00-60-ED (hex) RICARDO TEST AUTOMATION LTD. +0060ED (base 16) RICARDO TEST AUTOMATION LTD. + LOWESMOOR WHARF + WORCESTER, WR12RS + GB + +00-60-12 (hex) POWER COMPUTING CORPORATION +006012 (base 16) POWER COMPUTING CORPORATION + 10261 BUBB ROAD + CUPERTINO CA 95014 + US + +00-60-4D (hex) MMC NETWORKS, INC. +00604D (base 16) MMC NETWORKS, INC. + 1134 EAST ARQUES AVENUE + SUNNYVALE CA 94086-4602 + US + +00-60-F7 (hex) DATAFUSION SYSTEMS +0060F7 (base 16) DATAFUSION SYSTEMS + P.O. BOX 582 + STELLENBOSCH, 7599 + ZA + +00-60-20 (hex) PIVOTAL NETWORKING, INC. +006020 (base 16) PIVOTAL NETWORKING, INC. + 7246 SHARON DR., STE + SAN JOSE CA 95129 + US + +00-60-C0 (hex) Nera Networks AS +0060C0 (base 16) Nera Networks AS + Kokstadveien 23 + Bergen 5020 + NO + +00-60-77 (hex) PRISA NETWORKS +006077 (base 16) PRISA NETWORKS + 6620 Mesa Ridge Road, + San Diego CA 92121 + US + +00-60-94 (hex) IBM Corp +006094 (base 16) IBM Corp + 3039 E Cornwallis Road + Research Triangle Park NC 27709-2195 + US + +00-60-AB (hex) LARSCOM INCORPORATED +0060AB (base 16) LARSCOM INCORPORATED + 1845 MCCANDLESS DRIVE + MILPITAS CA 95035 + US + +00-60-DD (hex) MYRICOM, INC. +0060DD (base 16) MYRICOM, INC. + 325B N. SANTA ANITA AVE. + ARCADIA CA 91006 + US + +00-60-46 (hex) VMETRO, INC. +006046 (base 16) VMETRO, INC. + 1880 DAIRY ASHFORD- STE #535 + HOUSTON TX 77077 + US + +00-60-68 (hex) Dialogic Corporation +006068 (base 16) Dialogic Corporation + 9800 Cavendish Blvd, 5th Floor + Montreal Quebec H4M 2V9 + CA + +00-60-5A (hex) CELCORE, INC. +00605A (base 16) CELCORE, INC. + 8001 CENTERVIEW PARKWAY + MEMPHIS TN 38018 + US + +00-60-95 (hex) ACCU-TIME SYSTEMS, INC. +006095 (base 16) ACCU-TIME SYSTEMS, INC. + 420 SOMERS ROAD + ELLINGTON CT 06029 + US + +00-60-8A (hex) CITADEL COMPUTER +00608A (base 16) CITADEL COMPUTER + 29 ARMORY RD + MILFORD MA 03055 + US + +00-60-93 (hex) VARIAN +006093 (base 16) VARIAN + 2700 MITCHELL DR. + WALNUT GREEK CA 94598 + US + +00-A0-3F (hex) COMPUTER SOCIETY MICROPROCESSOR & MICROPROCESSOR STANDARDS C +00A03F (base 16) COMPUTER SOCIETY MICROPROCESSOR & MICROPROCESSOR STANDARDS C + % APPLE COMPUTER, INC. + CUPERTINO CA 95014 + US + +00-A0-2D (hex) 1394 Trade Association +00A02D (base 16) 1394 Trade Association + 3925 WEST BRAKER LANE + AUSTIN TX 78759 + US + +00-A0-7C (hex) TONYANG NYLON CO., LTD. +00A07C (base 16) TONYANG NYLON CO., LTD. + ELECTRONIC RESEARCH LAB + ANYANG-CITY, KYUNGKI-DO 430-080 + KR + +00-A0-9A (hex) NIHON KOHDEN AMERICA +00A09A (base 16) NIHON KOHDEN AMERICA + 2446 DUPONT DRIVE + IRVINE CA 92715 + US + +00-A0-93 (hex) B/E AEROSPACE, Inc. +00A093 (base 16) B/E AEROSPACE, Inc. + 17481 RED HILL + IRVINE CA 92714-5630 + US + +00-A0-78 (hex) Marconi Communications +00A078 (base 16) Marconi Communications + 1000 Fore Drive + Warrendale PA 15086-7502 + US + +00-A0-BF (hex) WIRELESS DATA GROUP MOTOROLA +00A0BF (base 16) WIRELESS DATA GROUP MOTOROLA + 1201 E. WILEY ROAD + SCHAUMBURG IL 60173 + US + +00-A0-5F (hex) BTG Electronics Design BV +00A05F (base 16) BTG Electronics Design BV + P.O. Box 1543 + BA Oud Beijerland + NL + +00-A0-CD (hex) DR. JOHANNES HEIDENHAIN GmbH +00A0CD (base 16) DR. JOHANNES HEIDENHAIN GmbH + DR.-JOHANNES-HEIDENHAIN STR. + 83301 TRAUNREUT + DE + +00-A0-DA (hex) INTEGRATED SYSTEMS Technology, Inc. +00A0DA (base 16) INTEGRATED SYSTEMS Technology, Inc. + 4601 PRESIDENTS DRIVE + LANHAM MD 20706 + US + +00-A0-2A (hex) TRANCELL SYSTEMS +00A02A (base 16) TRANCELL SYSTEMS + 3180 DE LA CRUZ BLVD.-STE#200 + SANTA CLARA CA 95054-2402 + US + +00-A0-1C (hex) NASCENT NETWORKS CORPORATION +00A01C (base 16) NASCENT NETWORKS CORPORATION + 277 MAIN STREET, 3RD FLR. + MARLBORO MA 01752 + US + +00-A0-8F (hex) DESKNET SYSTEMS, INC. +00A08F (base 16) DESKNET SYSTEMS, INC. + 80 BUSINESS PARK DRIVE + ARMONK NY 10504 + US + +00-A0-CC (hex) LITE-ON COMMUNICATIONS, INC. +00A0CC (base 16) LITE-ON COMMUNICATIONS, INC. + 720 S. HILLVIEW DRIVE + MILPITAS CA 95035 + US + +00-A0-E6 (hex) DIALOGIC CORPORATION +00A0E6 (base 16) DIALOGIC CORPORATION + 1515 ROUTE 10 + PARSIPPANY NJ 07054 + US + +00-A0-4A (hex) NISSHIN ELECTRIC CO., LTD. +00A04A (base 16) NISSHIN ELECTRIC CO., LTD. + 5, MEOTOGOSHI, MUTSUSHI, + AICHI 481 + JP + +00-A0-35 (hex) CYLINK CORPORATION +00A035 (base 16) CYLINK CORPORATION + 3131 JAY STREET + SANTA CLARA CA 95054 + US + +00-A0-3D (hex) OPTO-22 +00A03D (base 16) OPTO-22 + 43044 BUSINESS PARK DR. + TEMECULA CA 92590 + US + +00-A0-56 (hex) MICROPROSS +00A056 (base 16) MICROPROSS + 33, RUE GANTOIS + 59000 LILLE + FR + +00-A0-E1 (hex) WESTPORT RESEARCH ASSOCIATES, INC. +00A0E1 (base 16) WESTPORT RESEARCH ASSOCIATES, INC. + 6102 ARLINGTON + RAYTOWN MO 64133 + US + +00-A0-B7 (hex) CORDANT, INC. +00A0B7 (base 16) CORDANT, INC. + 11400 COMMERCE PARK DR. + RESTON VA 22091-1506 + US + +00-A0-26 (hex) TELDAT, S.A. +00A026 (base 16) TELDAT, S.A. + PARQUE TECNOLOGICO MADRID + 28760 TACS CAN TOS (MADRID) + ES + +00-A0-23 (hex) APPLIED CREATIVE TECHNOLOGY, INC. +00A023 (base 16) APPLIED CREATIVE TECHNOLOGY, INC. + 2626 LOMBARDY LANE--STE.#107 + DALLAS TX 75220 + US + +00-A0-89 (hex) XPOINT TECHNOLOGIES, INC. +00A089 (base 16) XPOINT TECHNOLOGIES, INC. + 902 CLINT MOORE RD.-STE#132 + BOCA RATON FL 33487 + US + +00-A0-07 (hex) APEXX TECHNOLOGY, INC. +00A007 (base 16) APEXX TECHNOLOGY, INC. + 506 S. 11TH + BOISE ID 83707 + US + +00-A0-47 (hex) INTEGRATED FITNESS CORP. +00A047 (base 16) INTEGRATED FITNESS CORP. + 26 6TH STREET + STAMFORD CT 06905 + US + +00-A0-32 (hex) GES SINGAPORE PTE. LTD. +00A032 (base 16) GES SINGAPORE PTE. LTD. + 14 SUNGEI KADUT AVENUE + SINGAPORE 2572 + SG + +00-A0-E3 (hex) XKL SYSTEMS CORP. +00A0E3 (base 16) XKL SYSTEMS CORP. + 8420 154TH AVE. NE + REDMOND WA 98052 + US + +00-A0-14 (hex) CSIR +00A014 (base 16) CSIR + P.O. BOX 395 + SOUTH AFRICA + ZA + +00-A0-15 (hex) WYLE +00A015 (base 16) WYLE + 3000 BOWERS AVENUE + SANTA CLARA CA 95051 + US + +00-A0-6A (hex) Verilink Corporation +00A06A (base 16) Verilink Corporation + 127 Jetplex Circle + Madison AL 35758 + US + +00-A0-18 (hex) CREATIVE CONTROLLERS, INC. +00A018 (base 16) CREATIVE CONTROLLERS, INC. + 128 KENDRICK LANE + PICAYUNE MS 39466 + US + +00-A0-FE (hex) BOSTON TECHNOLOGY, INC. +00A0FE (base 16) BOSTON TECHNOLOGY, INC. + 100 QUANNAPOWITT PARKWAY + WAKEFIELD MA 01880 + US + +00-A0-EB (hex) Encore Networks, Inc. +00A0EB (base 16) Encore Networks, Inc. + 3800 Concorde Parkway, + Chantilly, VA 20151 + US + +00-A0-7D (hex) SEEQ TECHNOLOGY, INC. +00A07D (base 16) SEEQ TECHNOLOGY, INC. + 47131 BAYSIDE PARKWAY + FREMONT CA 94538 + US + +00-A0-D9 (hex) CONVEX COMPUTER CORPORATION +00A0D9 (base 16) CONVEX COMPUTER CORPORATION + 3000 WATERVIEW PARKWAY + RICHARDSON TX 75083-3851 + US + +00-A0-70 (hex) COASTCOM +00A070 (base 16) COASTCOM + 1151 HARBOR BAY PARKWAY + ALAMEDA CA 94502-6511 + US + +00-20-DE (hex) JAPAN DIGITAL LABORAT'Y CO.LTD +0020DE (base 16) JAPAN DIGITAL LABORAT'Y CO.LTD + JDL KAWASAKI R & D CENTER + KANAGAWA-KEN 215 + JP + +00-20-0B (hex) OCTAGON SYSTEMS CORP. +00200B (base 16) OCTAGON SYSTEMS CORP. + 7403 Church Ranch Blvd + Westminster CO 80021 + US + +00-20-94 (hex) CUBIX CORPORATION +002094 (base 16) CUBIX CORPORATION + 2800 LOCKHEED WAY + CARSON CITY NV 89706 + US + +00-20-F7 (hex) CYBERDATA CORPORATION +0020F7 (base 16) CYBERDATA CORPORATION + 3 Justin Court + MONTEREY CA 93940 + US + +00-20-D7 (hex) JAPAN MINICOMPUTER SYSTEMS CO., Ltd. +0020D7 (base 16) JAPAN MINICOMPUTER SYSTEMS CO., Ltd. + 3-33-18 TAKAIDOHIGASHI + TOKYO 168 + JP + +00-20-C3 (hex) COUNTER SOLUTIONS LTD. +0020C3 (base 16) COUNTER SOLUTIONS LTD. + 263 HEAGE ROAD + RIPLEY, DERBYS DE5 3GH + GB + +00-20-47 (hex) STEINBRECHER CORP. +002047 (base 16) STEINBRECHER CORP. + 30 NORTH AVENUE + BURLINGTON MA 01803 + US + +00-20-D5 (hex) VIPA GMBH +0020D5 (base 16) VIPA GMBH + WETTERKREUZ 27 + + DE + +00-20-1A (hex) MRV Communications, Inc. +00201A (base 16) MRV Communications, Inc. + 20415 Nordhoff St. + Chatsworth CA 91311 + US + +00-20-F2 (hex) Oracle Corporation +0020F2 (base 16) Oracle Corporation + 500 Oracle Parkway + Redwood Shores CA 94065 + US + +00-20-B8 (hex) PRIME OPTION, INC. +0020B8 (base 16) PRIME OPTION, INC. + 2341 W. 205TH STREET #116 + TORRANCE CA 90501 + US + +00-20-AD (hex) LINQ SYSTEMS +0020AD (base 16) LINQ SYSTEMS + P.O. BOX 11040 + TUCSON AZ 85734 + US + +00-20-7D (hex) ADVANCED COMPUTER APPLICATIONS +00207D (base 16) ADVANCED COMPUTER APPLICATIONS + 107 PENNS TRAIL + NEWTOWN PA 18940 + US + +00-20-2F (hex) ZETA COMMUNICATIONS, LTD. +00202F (base 16) ZETA COMMUNICATIONS, LTD. + ZENITH HOUSE + WREXHAM, CLWYD, LL12 8LX + GB + +00-20-9A (hex) THE 3DO COMPANY +00209A (base 16) THE 3DO COMPANY + 600 GALVESTON DRIVE + REDWOOD CITY CA 94063 + US + +00-20-62 (hex) SCORPION LOGIC, LTD. +002062 (base 16) SCORPION LOGIC, LTD. + 19 BROOKSIDE ROAD + HERTS WD1 4BW + GB + +00-20-81 (hex) TITAN ELECTRONICS +002081 (base 16) TITAN ELECTRONICS + 3033 SCIENCE PARK ROAD + SAN DIEGO CA 92121 + US + +00-20-D9 (hex) PANASONIC TECHNOLOGIES, INC./MIECO-US +0020D9 (base 16) PANASONIC TECHNOLOGIES, INC./MIECO-US + 1703 N. RANDALL RD. + ELGIN IL 60123 + US + +00-20-6F (hex) FLOWPOINT CORPORATION +00206F (base 16) FLOWPOINT CORPORATION + 7291 CORONADO DRIVE, STE# 4 + SAN JOSE CA 95129 + US + +00-20-20 (hex) MEGATRON COMPUTER INDUSTRIES PTY, LTD. +002020 (base 16) MEGATRON COMPUTER INDUSTRIES PTY, LTD. + + + AU + +00-20-1B (hex) NORTHERN TELECOM/NETWORK +00201B (base 16) NORTHERN TELECOM/NETWORK + SYSTEMS CORPORATION + CANADA K8N 5B7 + CA + +00-20-F3 (hex) RAYNET CORPORATION +0020F3 (base 16) RAYNET CORPORATION + 155 CONSTITUTION DRIVE + MENLO PARK CA 94025 + US + +00-20-90 (hex) ADVANCED COMPRESSION TECHNOLOGY, INC. +002090 (base 16) ADVANCED COMPRESSION TECHNOLOGY, INC. + 820 FLYNN ROAD + CAMARILLO CA 93012 + US + +00-20-C0 (hex) PULSE ELECTRONICS, INC. +0020C0 (base 16) PULSE ELECTRONICS, INC. + 5706 FREDERICK AVENUE + ROCKVILLE MD 20852 + US + +00-20-7E (hex) FINECOM CO., LTD. +00207E (base 16) FINECOM CO., LTD. + 1108 HWAKOK-DONG, KANGSEO-KU + SEOUL + KR + +00-20-4E (hex) NETWORK SECURITY SYSTEMS, INC. +00204E (base 16) NETWORK SECURITY SYSTEMS, INC. + 9401 WAPLES STREET,STE. #100 + SAN DIEGO CA 92121 + US + +00-20-CA (hex) DIGITAL OCEAN +0020CA (base 16) DIGITAL OCEAN + 11206 THOMPSON AVENUE + LENEXA KS 66219-2303 + US + +00-20-95 (hex) RIVA ELECTRONICS +002095 (base 16) RIVA ELECTRONICS + UNIT 17, BARRSFOLD RD. + LANCASHIRE ENGLAND BL5 3XW + GB + +00-20-FB (hex) OCTEL COMMUNICATIONS CORP. +0020FB (base 16) OCTEL COMMUNICATIONS CORP. + 1001 MURPHY RANCH RD + MILPITAS CA 95035 + US + +00-20-70 (hex) HYNET, LTD. +002070 (base 16) HYNET, LTD. + 102 JABOTINSKY ST. + PETACH TIKVA 49130 + IL + +00-20-BE (hex) LAN ACCESS CORP. +0020BE (base 16) LAN ACCESS CORP. + 2730 MONTEREY STREET, STE.#102 + TORRANCE CA 90503 + US + +00-20-3F (hex) JUKI CORPORATION +00203F (base 16) JUKI CORPORATION + 8-2-1 KOKURYO-CHO + + JP + +00-20-A9 (hex) WHITE HORSE INDUSTRIAL +0020A9 (base 16) WHITE HORSE INDUSTRIAL + 4F. NO.16, ALLEY 56, LANE 181 + + TW + +00-20-96 (hex) Invensys +002096 (base 16) Invensys + Robershaw Industrial Products + Marysville TN 37801 + US + +00-20-4A (hex) PRONET GMBH +00204A (base 16) PRONET GMBH + KARLSTRASSE 49 + + DE + +00-20-FF (hex) SYMMETRICAL TECHNOLOGIES +0020FF (base 16) SYMMETRICAL TECHNOLOGIES + 500 HUNTMAR PARK DRIVE + HERNDON VA 22070 + US + +00-20-44 (hex) GENITECH PTY LTD +002044 (base 16) GENITECH PTY LTD + P.O. BOX 196 + + AU + +00-20-EF (hex) USC CORPORATION +0020EF (base 16) USC CORPORATION + 6-4, OSAKI 1-CHOME + 141 + JP + +00-20-30 (hex) ANALOG & DIGITAL SYSTEMS +002030 (base 16) ANALOG & DIGITAL SYSTEMS + 1/2 LAVELLE ROAD + + IN + +00-20-AC (hex) INTERFLEX DATENSYSTEME GMBH +0020AC (base 16) INTERFLEX DATENSYSTEME GMBH + GROBWIESENSTRASE 24 + WESTGERMANY + DE + +00-20-D8 (hex) Nortel Networks +0020D8 (base 16) Nortel Networks + 4401 Great America Pkwy. + Santa Clara CA 94588 + US + +00-20-66 (hex) GENERAL MAGIC, INC. +002066 (base 16) GENERAL MAGIC, INC. + 2465 LATHAM STREET + MOUNTAIN VIEW CA 94040 + US + +00-20-01 (hex) DSP SOLUTIONS, INC. +002001 (base 16) DSP SOLUTIONS, INC. + 2464 EMBARCADERO WAY + PALO ALTO CA 94303 + US + +00-20-BF (hex) AEHR TEST SYSTEMS +0020BF (base 16) AEHR TEST SYSTEMS + 1667 PLYMOUTH STREET + MOUNTAIN VIEW CA 94043 + US + +00-20-53 (hex) HUNTSVILLE MICROSYSTEMS, INC. +002053 (base 16) HUNTSVILLE MICROSYSTEMS, INC. + P.O. BOX 12415 + HUNTSVILLE AL 35815 + US + +00-20-A1 (hex) DOVATRON +0020A1 (base 16) DOVATRON + PRODUCTS DIVISION + LONGMONT CO 80501 + US + +00-C0-2F (hex) OKUMA CORPORATION +00C02F (base 16) OKUMA CORPORATION + OGUCHI-CHO, NIWA-GUN + + JP + +00-C0-1E (hex) LA FRANCAISE DES JEUX +00C01E (base 16) LA FRANCAISE DES JEUX + CENTRE DE ROUSSY/DTI + + FR + +00-C0-E1 (hex) SONIC SOLUTIONS +00C0E1 (base 16) SONIC SOLUTIONS + 1891 E. FRANCISCO BLVD. + SAN RAFAEL CA 94901 + US + +00-20-36 (hex) BMC SOFTWARE +002036 (base 16) BMC SOFTWARE + 1600 CITY WEST BLVD., #1600 + HOUSTON TX 77042 + US + +00-20-F8 (hex) CARRERA COMPUTERS, INC. +0020F8 (base 16) CARRERA COMPUTERS, INC. + 23181 VERDUGO DRIVE-STE.#105A + LAGUNA HILLS CA 92653 + US + +00-C0-65 (hex) SCOPE COMMUNICATIONS, INC. +00C065 (base 16) SCOPE COMMUNICATIONS, INC. + 100 OTIS STREET + NORTHBORO MA 01532 + US + +00-C0-79 (hex) FONSYS CO.,LTD. +00C079 (base 16) FONSYS CO.,LTD. + 209-5, YANGJAE, SEOCHO + KOREA + KR + +00-C0-0F (hex) QUANTUM SOFTWARE SYSTEMS LTD. +00C00F (base 16) QUANTUM SOFTWARE SYSTEMS LTD. + 175 TERRENCE MATTHEWS CRESCENT + K2L 3T5 + CA + +00-C0-87 (hex) UUNET TECHNOLOGIES, INC. +00C087 (base 16) UUNET TECHNOLOGIES, INC. + 3110 FAIRVIEW PARK DR. #570 + FALLS CHURCH VA 22042 + US + +00-C0-06 (hex) NIPPON AVIONICS CO., LTD. +00C006 (base 16) NIPPON AVIONICS CO., LTD. + INDUSTRIAL SYSTEM DIVISION + + JP + +00-C0-A4 (hex) UNIGRAF OY +00C0A4 (base 16) UNIGRAF OY + RUUKINTIE 18 + + FI + +00-C0-29 (hex) Nexans Deutschland GmbH - ANS +00C029 (base 16) Nexans Deutschland GmbH - ANS + Bonnenbroicher Str. 100 + + DE + +00-C0-FA (hex) CANARY COMMUNICATIONS, INC. +00C0FA (base 16) CANARY COMMUNICATIONS, INC. + 1851 ZANKER ROAD + SAN JOSE CA 95112-4213 + US + +00-C0-3A (hex) MEN-MIKRO ELEKTRONIK GMBH +00C03A (base 16) MEN-MIKRO ELEKTRONIK GMBH + WIESENTALSTRASSE 40 + + DE + +00-C0-40 (hex) ECCI +00C040 (base 16) ECCI + 15070-B AVENUE OF SCIENCE + SAN DIEGO CA 92128 + US + +00-C0-1C (hex) INTERLINK COMMUNICATIONS LTD. +00C01C (base 16) INTERLINK COMMUNICATIONS LTD. + BRUNEL ROAD, + ENGLAND + GB + +00-C0-42 (hex) DATALUX CORP. +00C042 (base 16) DATALUX CORP. + 2836 CESSNA DRIVE + WINCHESTER VA 22601 + US + +00-C0-71 (hex) AREANEX COMMUNICATIONS, INC. +00C071 (base 16) AREANEX COMMUNICATIONS, INC. + 3333 OCTAVIUS DRIVE UNIT C + SANTA CLARA CA 95051 + US + +00-C0-44 (hex) EMCOM CORPORATION +00C044 (base 16) EMCOM CORPORATION + 840 AVENUE + PLANO TX 75074 + US + +00-C0-E6 (hex) Verilink Corporation +00C0E6 (base 16) Verilink Corporation + 127 Jetplex Circle + Madison AL 35758 + US + +00-C0-96 (hex) TAMURA CORPORATION +00C096 (base 16) TAMURA CORPORATION + COMMUNICATION SYSTEMS DIV. + + JP + +00-C0-4E (hex) COMTROL CORPORATION +00C04E (base 16) COMTROL CORPORATION + 2675 PATTON ROAD + ST. PAUL MN 55113 + US + +00-C0-3F (hex) STORES AUTOMATED SYSTEMS, INC. +00C03F (base 16) STORES AUTOMATED SYSTEMS, INC. + 1360 ADAMS ROAD + BENSALEM PA 19020 + US + +00-C0-36 (hex) RAYTECH ELECTRONIC CORP. +00C036 (base 16) RAYTECH ELECTRONIC CORP. + 2F, NO.6, LANE 497 + TAIWAN R.O.C. + TW + +00-C0-A2 (hex) INTERMEDIUM A/S +00C0A2 (base 16) INTERMEDIUM A/S + ODINSVEJ 19 + + DK + +00-C0-53 (hex) Aspect Software Inc. +00C053 (base 16) Aspect Software Inc. + 6 Technology Park Drive + Westford MA 01886 + US + +00-C0-CC (hex) TELESCIENCES CO SYSTEMS, INC. +00C0CC (base 16) TELESCIENCES CO SYSTEMS, INC. + 351 NEW ALBANY RD. + MOORESTOWN NJ 08057-1177 + US + +00-C0-CE (hex) CEI SYSTEMS & ENGINEERING PTE +00C0CE (base 16) CEI SYSTEMS & ENGINEERING PTE + BLK 73 #02-18 AYER RAJAH CRESC + SINGAPORE 0513 + SG + +00-40-4F (hex) SPACE & NAVAL WARFARE SYSTEMS +00404F (base 16) SPACE & NAVAL WARFARE SYSTEMS + NUWC + NEWPORT RI 02841-5047 + US + +00-40-8F (hex) WM-DATA MINFO AB +00408F (base 16) WM-DATA MINFO AB + OLOF ASKLUNDS GATA 14 + + SE + +00-40-D7 (hex) STUDIO GEN INC. +0040D7 (base 16) STUDIO GEN INC. + 3-12-8 TAKANAWA #202 + + JP + +00-40-57 (hex) LOCKHEED - SANDERS +004057 (base 16) LOCKHEED - SANDERS + DANIEL WEBSTER HIGHWAY SOUTH + NASHUA NH 03061-0868 + US + +00-40-17 (hex) Silex Technology America +004017 (base 16) Silex Technology America + 157 West 7065 South + Salt Lake City UT 84047 + US + +00-C0-D9 (hex) QUINTE NETWORK CONFIDENTIALITY +00C0D9 (base 16) QUINTE NETWORK CONFIDENTIALITY + EQUIPMENT INC. + CANADA K8N 1C3 + CA + +00-C0-B1 (hex) GENIUS NET CO. +00C0B1 (base 16) GENIUS NET CO. + 4F, HANSOO B/D 210-5 + SOUTH KOREA + KR + +00-C0-D2 (hex) SYNTELLECT, INC. +00C0D2 (base 16) SYNTELLECT, INC. + 15810 N. 28TH AVENUE + PHOENIX AZ 85023 + US + +00-C0-7E (hex) KUBOTA CORPORATION ELECTRONIC +00C07E (base 16) KUBOTA CORPORATION ELECTRONIC + DEVICE DEPT. + JAPAN #581 + JP + +00-C0-DD (hex) QLogic Corporation +00C0DD (base 16) QLogic Corporation + 6321 Bury Dr. + Eden Prarie MN 55346 + US + +00-C0-1B (hex) SOCKET COMMUNICATIONS, INC. +00C01B (base 16) SOCKET COMMUNICATIONS, INC. + 2823 WHIPPLE RD. + UNION CITY CA 94587 + US + +00-40-6F (hex) SYNC RESEARCH INC. +00406F (base 16) SYNC RESEARCH INC. + 7 STUDEBAKER + IRVINE CA 92718 + US + +00-40-F3 (hex) NETCOR +0040F3 (base 16) NETCOR + 850 AUBURN COURT + FREMONT CA 94538 + US + +00-40-4B (hex) MAPLE COMPUTER SYSTEMS +00404B (base 16) MAPLE COMPUTER SYSTEMS + P.O. BOX 10050 + CANADA ALA 4L5 + CA + +00-40-33 (hex) ADDTRON TECHNOLOGY CO., LTD. +004033 (base 16) ADDTRON TECHNOLOGY CO., LTD. + 46560 FREMONT BLVD. #303 + FREMONT CA 94538 + US + +00-C0-8E (hex) NETWORK INFORMATION TECHNOLOGY +00C08E (base 16) NETWORK INFORMATION TECHNOLOGY + 10430 S. DE ANZA BLVD. + CUPERTINO CA 95014 + US + +00-C0-C7 (hex) SPARKTRUM MICROSYSTEMS, INC. +00C0C7 (base 16) SPARKTRUM MICROSYSTEMS, INC. + 2860 ZANKER ROAD, STE.#210 + SAN JOSE CA 95134 + US + +00-C0-C4 (hex) COMPUTER OPERATIONAL +00C0C4 (base 16) COMPUTER OPERATIONAL + REQUIREMENT ANALYSTS LTD + GU12 4LZ GU12 4LZ ENGLAND + GB + +00-C0-12 (hex) NETSPAN CORPORATION +00C012 (base 16) NETSPAN CORPORATION + 1411 E. CAMPBELL RD + RICHARDSON TX 75081 + US + +00-40-AD (hex) SMA REGELSYSTEME GMBH +0040AD (base 16) SMA REGELSYSTEME GMBH + HANNOVERSCHE STR. 1-5 + + DE + +00-40-6D (hex) LANCO, INC. +00406D (base 16) LANCO, INC. + 800 WEST AIRPORT FREEWAY + IRVING TX 75062 + US + +00-40-CD (hex) TERA MICROSYSTEMS, INC. +0040CD (base 16) TERA MICROSYSTEMS, INC. + 2500 GREAT AMERICA PARKWAY + SANTA CLARA CA 95054 + US + +00-40-F5 (hex) OEM ENGINES +0040F5 (base 16) OEM ENGINES + 1190 DELL AVENUE, STE. + CAMPBELL CA 95008 + US + +00-40-39 (hex) OPTEC DAIICHI DENKO CO., LTD. +004039 (base 16) OPTEC DAIICHI DENKO CO., LTD. + FIBER OPTICS & TELECOM. DIV. + JAPAN + + +00-40-79 (hex) JUKO MANUFACTURE COMPANY, LTD. +004079 (base 16) JUKO MANUFACTURE COMPANY, LTD. + FLAT C, 3RD FLOOR, CDW BLDG. + HONG KONG + HK + +00-C0-20 (hex) ARCO ELECTRONIC, CONTROL LTD. +00C020 (base 16) ARCO ELECTRONIC, CONTROL LTD. + 2750 NORTH 29TH AVE.-STE.#316 + HOLLYWOOD FL 33020 + US + +00-C0-E7 (hex) FIBERDATA AB +00C0E7 (base 16) FIBERDATA AB + P.O. BOX 20095 + + SE + +00-C0-5F (hex) FINE-PAL COMPANY LIMITED +00C05F (base 16) FINE-PAL COMPANY LIMITED + RM. 9, 11F, KINGSFORD IND. CTR + HONG KONG + HK + +00-40-AE (hex) DELTA CONTROLS, INC. +0040AE (base 16) DELTA CONTROLS, INC. + 13520 78TH AVENUE + CANADA V3W 8J6 + CA + +00-40-F6 (hex) KATRON COMPUTERS INC. +0040F6 (base 16) KATRON COMPUTERS INC. + 4 FL. NO. 2, ALLEY 23 + TAIPEI TAIPEI TAIWAN + TW + +00-40-86 (hex) MICHELS & KLEBERHOFF COMPUTER +004086 (base 16) MICHELS & KLEBERHOFF COMPUTER + GATHE 117 + + DE + +00-40-92 (hex) ASP COMPUTER PRODUCTS, INC. +004092 (base 16) ASP COMPUTER PRODUCTS, INC. + 160 SAN GABRIEL DRIVE + SUNNYVALE CA 94086 + US + +00-40-68 (hex) EXTENDED SYSTEMS +004068 (base 16) EXTENDED SYSTEMS + 6123 NORTH MEEKER AVENUE + BOISE ID 83704 + US + +00-40-78 (hex) WEARNES AUTOMATION PTE LTD +004078 (base 16) WEARNES AUTOMATION PTE LTD + 801 LORONG 7, TOA PAYOH + SINGAPORE 1231 + SG + +00-40-F4 (hex) CAMEO COMMUNICATIONS, INC. +0040F4 (base 16) CAMEO COMMUNICATIONS, INC. + 71 SPITBROOK ROAD, STE #410 + NASHUA NH 030603 + US + +00-40-B4 (hex) NEXTCOM K.K. +0040B4 (base 16) NEXTCOM K.K. + 1-12-1 SHIBUYA + + JP + +00-40-B0 (hex) BYTEX CORPORATION, ENGINEERING +0040B0 (base 16) BYTEX CORPORATION, ENGINEERING + 13873 PARK CENTER ROAD + HERNDON VA 22071 + US + +00-80-D9 (hex) EMK Elektronik GmbH & Co. KG +0080D9 (base 16) EMK Elektronik GmbH & Co. KG + Obere Bergstrasse 28 + 75335 Dobel + DE + +00-40-59 (hex) YOSHIDA KOGYO K. K. +004059 (base 16) YOSHIDA KOGYO K. K. + TECHNICAL RESEARCH DEPT. + 939 + JP + +00-40-95 (hex) R.P.T. INTERGROUPS INT'L LTD. +004095 (base 16) R.P.T. INTERGROUPS INT'L LTD. + 9F, 50 MIN CHUAN RD + TAIWAN TAIWAN R.O.C. + TW + +00-40-35 (hex) OPCOM +004035 (base 16) OPCOM + 1215 W. CROSBY RD. + CARROLLTON TX 75006 + US + +00-40-5C (hex) FUTURE SYSTEMS, INC. +00405C (base 16) FUTURE SYSTEMS, INC. + ROOM 102 DONG BANG B/D, + SEOUL 130-080 SEOUL 130-080 KOREA + KR + +00-40-61 (hex) DATATECH ENTERPRISES CO., LTD. +004061 (base 16) DATATECH ENTERPRISES CO., LTD. + (LIN KOU INDUSTRIAL ZONE SEC,4 + TAOYUAN COUNTY TAIWAN R.O.C. + TW + +00-00-8C (hex) Alloy Computer Products (Australia) Pty Ltd +00008C (base 16) Alloy Computer Products (Australia) Pty Ltd + Unit 4/585 Blackburn Road + Notting Hill Victoria 3168 + AU + +00-40-B9 (hex) MACQ ELECTRONIQUE SA +0040B9 (base 16) MACQ ELECTRONIQUE SA + RUE DE L'AERONEF 2 + + BE + +00-40-BB (hex) GOLDSTAR CABLE CO., LTD. +0040BB (base 16) GOLDSTAR CABLE CO., LTD. + 555, HOGYE-DONG, ANYANG-SHI + KOREA + KR + +00-40-B1 (hex) CODONICS INC. +0040B1 (base 16) CODONICS INC. + 17991 ENGLEWOOD DRIVE + MIDDLEBURG HTS OH 44130 + US + +00-40-F8 (hex) SYSTEMHAUS DISCOM +0040F8 (base 16) SYSTEMHAUS DISCOM + DISTRIBUTED COMPUTING GMBH + + DE + +00-40-D2 (hex) PAGINE CORPORATION +0040D2 (base 16) PAGINE CORPORATION + 1961-A CONCOURSE DRIVE + SAN JOSE CA 95131 + US + +00-40-24 (hex) COMPAC INC. +004024 (base 16) COMPAC INC. + 16-7 NIHONBASI HAMACHO 3-CHO + + JP + +00-40-E9 (hex) ACCORD SYSTEMS, INC. +0040E9 (base 16) ACCORD SYSTEMS, INC. + 572 VALLEY WAY + MILPITAS CA 95035 + US + +00-40-03 (hex) Emerson Process Management Power & Water Solutions, Inc. +004003 (base 16) Emerson Process Management Power & Water Solutions, Inc. + 200 Beta Drive + PITTSBURGH PA 15238 + US + +00-40-90 (hex) ANSEL COMMUNICATIONS +004090 (base 16) ANSEL COMMUNICATIONS + 1701 JUNCTION COURT + SAN JOSE CA 95112 + US + +00-40-C5 (hex) MICOM COMMUNICATIONS INC. +0040C5 (base 16) MICOM COMMUNICATIONS INC. + 4100 LOS ANGELES AVENUE + SIMI VALLEY CA 93063 + US + +00-40-20 (hex) CommScope Inc +004020 (base 16) CommScope Inc + Unit 1, Kinmel Park + Bodelwyddan RHYL LL18 5TZ + GB + +00-40-48 (hex) SMD INFORMATICA S.A. +004048 (base 16) SMD INFORMATICA S.A. + LARGO MOVIMENTO DAS FORCAS + + PT + +00-40-7C (hex) QUME CORPORATION +00407C (base 16) QUME CORPORATION + 500 YOSEMITE DRIVE, M/S-29 + MILPITAS CA 95035-5426 + US + +00-40-7F (hex) FLIR Systems +00407F (base 16) FLIR Systems + BOX 3 + + SE + +00-40-2D (hex) HARRIS ADACOM CORPORATION +00402D (base 16) HARRIS ADACOM CORPORATION + 1100 VENTURE COURT + CARROLLTON TX 75006-5412 + US + +00-80-A6 (hex) REPUBLIC TECHNOLOGY, INC. +0080A6 (base 16) REPUBLIC TECHNOLOGY, INC. + P.O. BOX 141006 + AUSTIN TX 78714 + US + +00-40-DE (hex) Elsag Datamat spa +0040DE (base 16) Elsag Datamat spa + ELSAG S.P.A. + GENOVA 16154 + IT + +00-40-C9 (hex) NCUBE +0040C9 (base 16) NCUBE + 919 EAST HILLSDALE BLVD. + FOSTER CITY CA 94404 + US + +00-80-32 (hex) ACCESS CO., LTD. +008032 (base 16) ACCESS CO., LTD. + HIEI-KUDAN BLDG. B1 + + JP + +00-80-CF (hex) EMBEDDED PERFORMANCE INC. +0080CF (base 16) EMBEDDED PERFORMANCE INC. + 3385 SCOTT BLVD. + SANTA CLARA CA 95054-3115 + US + +00-80-90 (hex) MICROTEK INTERNATIONAL, INC. +008090 (base 16) MICROTEK INTERNATIONAL, INC. + 3300 NW 211TH TERRACE + HILLSBOR OR 97124-7136 + US + +00-40-44 (hex) QNIX COMPUTER CO., LTD. +004044 (base 16) QNIX COMPUTER CO., LTD. + 8,9F KOREAN TEACHER'S MUT.BLDG + SEOUL KOREA 150-010 + KR + +00-80-C4 (hex) DOCUMENT TECHNOLOGIES, INC. +0080C4 (base 16) DOCUMENT TECHNOLOGIES, INC. + 1300 CHARLESTON ROAD + MOUNTAIN VIEW CA 94043 + US + +00-80-5B (hex) CONDOR SYSTEMS, INC. +00805B (base 16) CONDOR SYSTEMS, INC. + 2133 SAMARILTAN DRIVE + SAN JOSE CA 95124 + US + +00-80-43 (hex) NETWORLD, INC. +008043 (base 16) NETWORLD, INC. + KANDA 3 AMEREX BLDG. + + JP + +00-40-DF (hex) DIGALOG SYSTEMS, INC. +0040DF (base 16) DIGALOG SYSTEMS, INC. + 3180 SOUTH 166TH STREET + NEW BERLIN WI 53151 + US + +00-40-09 (hex) TACHIBANA TECTRON CO., LTD. +004009 (base 16) TACHIBANA TECTRON CO., LTD. + SYSTEMATIC EQUIPMENT DIVISION + + JP + +00-40-A0 (hex) GOLDSTAR CO., LTD. +0040A0 (base 16) GOLDSTAR CO., LTD. + 6 GA 3B MUNLAE YEONGDEUNGPO + KOREA + KR + +00-40-FC (hex) IBR COMPUTER TECHNIK GMBH +0040FC (base 16) IBR COMPUTER TECHNIK GMBH + FRANKFURTER STR. 114 + WEST + DE + +00-80-AF (hex) ALLUMER CO., LTD. +0080AF (base 16) ALLUMER CO., LTD. + 2-8-8 CHUO-CHO, MEGURO-KU + + JP + +00-80-84 (hex) THE CLOUD INC. +008084 (base 16) THE CLOUD INC. + CLOUD BLDG. + KOREA + KR + +00-80-F3 (hex) SUN ELECTRONICS CORP. +0080F3 (base 16) SUN ELECTRONICS CORP. + 250 ASAHI KOCHINO-CHO + 483 + JP + +00-80-99 (hex) Eaton Industries GmbH +008099 (base 16) Eaton Industries GmbH + Hein-Moeller - Straße 7-11 + + DE + +00-80-8D (hex) WESTCOAST TECHNOLOGY B.V. +00808D (base 16) WESTCOAST TECHNOLOGY B.V. + P.O. BOX 3317 + + NL + +00-80-BE (hex) ARIES RESEARCH +0080BE (base 16) ARIES RESEARCH + 46791 FREMOND BLVD. + FREMONT CA 94538 + US + +00-80-15 (hex) SEIKO SYSTEMS, INC. +008015 (base 16) SEIKO SYSTEMS, INC. + 8,Nakase 1-chome,Mihama-ku + + JP + +00-80-D2 (hex) SHINNIHONDENKO CO., LTD. +0080D2 (base 16) SHINNIHONDENKO CO., LTD. + 6-8 NISHITENMA 2 CHOME + + JP + +00-80-89 (hex) TECNETICS (PTY) LTD. +008089 (base 16) TECNETICS (PTY) LTD. + P.O. BOX/POSBUS 56412 + SOUTH AFRICA + ZA + +00-80-6F (hex) ONELAN LTD. +00806F (base 16) ONELAN LTD. + P.O. BOX 107 + UNITED KINGDOM + GB + +00-80-81 (hex) KENDALL SQUARE RESEARCH CORP. +008081 (base 16) KENDALL SQUARE RESEARCH CORP. + 170 TRACER LANE + WALTHAM MA 02154-1379 + US + +00-80-9C (hex) LUXCOM, INC. +00809C (base 16) LUXCOM, INC. + 3249 LAURELVIEW COURT + FREMONT CA 94538 + US + +00-80-65 (hex) CYBERGRAPHIC SYSTEMS PTY LTD. +008065 (base 16) CYBERGRAPHIC SYSTEMS PTY LTD. + 290 BURWOOD ROAD + + AU + +00-80-19 (hex) DAYNA COMMUNICATIONS, INC. +008019 (base 16) DAYNA COMMUNICATIONS, INC. + 50 SOUTH MAIN STREET-#530 + SALT LAKE CITY UTAH 84144 + US + +00-80-50 (hex) ZIATECH CORPORATION +008050 (base 16) ZIATECH CORPORATION + 3433 ROBERTO COURT + SAN LUIS OBISPO CA 93401 + US + +00-80-A4 (hex) LIBERTY ELECTRONICS +0080A4 (base 16) LIBERTY ELECTRONICS + 332 HARBOR WAY + SOUTH SAN FRANCISCO CA 94080 + US + +00-80-CD (hex) MICRONICS COMPUTER, INC. +0080CD (base 16) MICRONICS COMPUTER, INC. + 45365 NORTHPORT LOOP WEST + FREMONT CA 94538 + US + +00-80-03 (hex) HYTEC ELECTRONICS LTD. +008003 (base 16) HYTEC ELECTRONICS LTD. + 5 CRADOCK ROAD + ENGLAND + GB + +00-80-52 (hex) TECHNICALLY ELITE CONCEPTS +008052 (base 16) TECHNICALLY ELITE CONCEPTS + 2615 PACIFIC COAST HIGHWAY + HERMOSA BEACH CA 90250 + US + +00-80-5D (hex) CANSTAR +00805D (base 16) CANSTAR + 3900 VICTORIA PARK AVENUE + M2H 3H7 + CA + +00-80-4F (hex) DAIKIN INDUSTRIES, LTD. +00804F (base 16) DAIKIN INDUSTRIES, LTD. + ELECTRONICS DIVISION + JAPAN 525 + JP + +00-80-05 (hex) CACTUS COMPUTER INC. +008005 (base 16) CACTUS COMPUTER INC. + 1120 METROCREST DRIVE + CARROLLTON TX 75006 + US + +00-80-6D (hex) CENTURY SYSTEMS CORP. +00806D (base 16) CENTURY SYSTEMS CORP. + 2-8-12 MINAMI-CHO + 185 + JP + +00-80-94 (hex) ALFA LAVAL AUTOMATION AB +008094 (base 16) ALFA LAVAL AUTOMATION AB + ADN + + SE + +00-00-41 (hex) ICE CORPORATION +000041 (base 16) ICE CORPORATION + 17945 SKYPARK CIRCLE + IRVINE CA 92714 + US + +00-00-86 (hex) MEGAHERTZ CORPORATION +000086 (base 16) MEGAHERTZ CORPORATION + 605 NORTH--5600 WEST + SALT LAKE CITY UT 84116-3738 + US + +00-00-92 (hex) COGENT DATA TECHNOLOGIES +000092 (base 16) COGENT DATA TECHNOLOGIES + 640 MULLIS STREET + FRIDAY HARBOR WA 98250 + US + +00-00-58 (hex) RACORE COMPUTER PRODUCTS INC. +000058 (base 16) RACORE COMPUTER PRODUCTS INC. + 2355 SOUTH 1070 WEST + SALT LAKE CITY UT 84119 + US + +00-80-74 (hex) FISHER CONTROLS +008074 (base 16) FISHER CONTROLS + 1712 CENTRE CREEK DRIVE + AUSTIN TX 78754 + US + +00-80-30 (hex) NEXUS ELECTRONICS +008030 (base 16) NEXUS ELECTRONICS + 39 SPRINGFIELD ROAD + UNITED KINGDOM + GB + +00-00-55 (hex) COMMISSARIAT A L`ENERGIE ATOM. +000055 (base 16) COMMISSARIAT A L`ENERGIE ATOM. + 31, RUE DE LA FEDERATION + + FR + +00-80-C9 (hex) ALBERTA MICROELECTRONIC CENTRE +0080C9 (base 16) ALBERTA MICROELECTRONIC CENTRE + 318, 11315 - 87 AVENUE + + CA + +00-80-0C (hex) VIDECOM LIMITED +00800C (base 16) VIDECOM LIMITED + NEWTOWN ESTATE + ENGLAND + GB + +00-80-7D (hex) EQUINOX SYSTEMS INC. +00807D (base 16) EQUINOX SYSTEMS INC. + 14260 SW 119TH AVENUE + MIAMI FL 33186 + US + +00-80-63 (hex) Hirschmann Automation and Control GmbH +008063 (base 16) Hirschmann Automation and Control GmbH + Stuttgarter Straße 45-51 + Neckartenzlingen D-72654 + DE + +00-80-EE (hex) THOMSON CSF +0080EE (base 16) THOMSON CSF + 51 ESPLANADE DU GENERAL + + FR + +00-80-8E (hex) RADSTONE TECHNOLOGY +00808E (base 16) RADSTONE TECHNOLOGY + WATER LANE, TOWCESTER + ENGLAND + GB + +00-80-96 (hex) HUMAN DESIGNED SYSTEMS, INC. +008096 (base 16) HUMAN DESIGNED SYSTEMS, INC. + 421 FEHELEY DRIVE + KING OF PRUSSIA PA 19406 + US + +00-80-DA (hex) Bruel & Kjaer Sound & Vibration Measurement A/S +0080DA (base 16) Bruel & Kjaer Sound & Vibration Measurement A/S + Skodsborgvej 307 + + DK + +00-80-3E (hex) SYNERNETICS +00803E (base 16) SYNERNETICS + 85 RANGEWAY ROAD + NORTH BILLERICA MA 01862 + US + +00-80-CE (hex) BROADCAST TELEVISION SYSTEMS +0080CE (base 16) BROADCAST TELEVISION SYSTEMS + P.O. BOX 30816 + Utah 84130-0816 + US + +00-80-1A (hex) BELL ATLANTIC +00801A (base 16) BELL ATLANTIC + N92 W14612 ANTHONY AVENUE + MENOMONEE FALLS WI 53051 + US + +00-80-DE (hex) GIPSI S.A. +0080DE (base 16) GIPSI S.A. + 2,BD VAUBAN - B.P. 268 + + FR + +00-80-02 (hex) SATELCOM (UK) LTD +008002 (base 16) SATELCOM (UK) LTD + TECHNOLOGY TRANSFER CENTRE + ENGLAND + GB + +00-80-64 (hex) WYSE TECHNOLOGY LLC +008064 (base 16) WYSE TECHNOLOGY LLC + 3471 NORTH FIRST STREET M/S + SAN JOSE CA 95134 + US + +00-80-48 (hex) COMPEX INCORPORATED +008048 (base 16) COMPEX INCORPORATED + 4055 EAST LA PALMA + ANAHEIM CA 92807 + US + +00-80-85 (hex) H-THREE SYSTEMS CORPORATION +008085 (base 16) H-THREE SYSTEMS CORPORATION + 100 PARK DRIVE, SUITE 204 + NC 27709 + US + +00-80-4C (hex) CONTEC CO., LTD. +00804C (base 16) CONTEC CO., LTD. + 3-9-31, HIMESATO + + JP + +00-80-8F (hex) C. ITOH ELECTRONICS, INC. +00808F (base 16) C. ITOH ELECTRONICS, INC. + 2505 MCCABE WAY + IRVINE CA 92714 + US + +00-00-52 (hex) Intrusion.com, Inc. +000052 (base 16) Intrusion.com, Inc. + 1101 E. ARAPAHO ROAD + RICHARDSON TX 75081 + + +00-80-FF (hex) SOC. DE TELEINFORMATIQUE RTC +0080FF (base 16) SOC. DE TELEINFORMATIQUE RTC + P.O. BOX 955 PLACE DU PARC + CANADA H2W 2N1 + + +00-00-F7 (hex) YOUTH KEEP ENTERPRISE CO LTD +0000F7 (base 16) YOUTH KEEP ENTERPRISE CO LTD + 3/F NO. 712 MINTSU E. ROAD + ROC + TW + +00-00-C7 (hex) ARIX CORPORATION +0000C7 (base 16) ARIX CORPORATION + ENGINEERING MAIL STOP + SUNNYVALE CA 94089 + US + +00-00-D1 (hex) ADAPTEC INCORPORATED +0000D1 (base 16) ADAPTEC INCORPORATED + M/S 180 + MILPITAS CA 95035 + US + +00-00-16 (hex) DU PONT PIXEL SYSTEMS . +000016 (base 16) DU PONT PIXEL SYSTEMS . + MEADLAKE PLACE + ENGLAND + GB + +00-00-E1 (hex) GRID SYSTEMS +0000E1 (base 16) GRID SYSTEMS + 47211 LAKEVIEW BOULEVARD + FREMONT CA 94537-5003 + US + +00-00-81 (hex) Bay Networks +000081 (base 16) Bay Networks + PO Box 58185 + Santa Clara CA 95052-8185 + US + +00-00-29 (hex) IMC NETWORKS CORP. +000029 (base 16) IMC NETWORKS CORP. + 16931 MILLIKEN AVE. + IRVINE CA 92714-5013 + US + +00-00-0A (hex) OMRON TATEISI ELECTRONICS CO. +00000A (base 16) OMRON TATEISI ELECTRONICS CO. + SECTION NFF, SYSTEM R&D LABS. + KYOTO 617 + JP + +00-00-0D (hex) FIBRONICS LTD. +00000D (base 16) FIBRONICS LTD. + MATAM TECHNOLOGY CENTER + + IL + +00-00-24 (hex) CONNECT AS +000024 (base 16) CONNECT AS + HOERKAER 7-9 + + DK + +00-00-67 (hex) SOFT * RITE, INC. +000067 (base 16) SOFT * RITE, INC. + 15392 ASSEMBLY LANE, UNIT A + HUNTINGTON BEACH CA 92649 + US + +00-00-D2 (hex) SBE, INC. +0000D2 (base 16) SBE, INC. + 4550 NORTH CANYON ROAD + SAN RAMON CA 94583 + US + +00-00-37 (hex) OXFORD METRICS LIMITED +000037 (base 16) OXFORD METRICS LIMITED + UNIT 8, 7 WEST WAY, + UNITED KINGDOM + GB + +00-00-FB (hex) RECHNER ZUR KOMMUNIKATION +0000FB (base 16) RECHNER ZUR KOMMUNIKATION + BITZENSTR. 11 + + DE + +00-00-E2 (hex) ACER TECHNOLOGIES CORP. +0000E2 (base 16) ACER TECHNOLOGIES CORP. + 401 CHARCOT AVE. + SAN JOSE CA 95131 + US + +00-00-BA (hex) SIIG, INC. +0000BA (base 16) SIIG, INC. + 6078 STEWART AVENUE + FREMONT CA 94538 + US + +00-00-2A (hex) TRW - SEDD/INP +00002A (base 16) TRW - SEDD/INP + 1800 GLENN CURTISS STREET + CARSON CA 90746 + US + +00-00-2C (hex) AUTOTOTE LIMITED +00002C (base 16) AUTOTOTE LIMITED + 100 BELLEVUE ROAD + NEWARK DELAWARE 19714 + US + +00-00-83 (hex) TADPOLE TECHNOLOGY PLC +000083 (base 16) TADPOLE TECHNOLOGY PLC + 137 DITTON WALK + ENGLAND + GB + +00-00-F3 (hex) GANDALF DATA LIMITED +0000F3 (base 16) GANDALF DATA LIMITED + 130 COLONNADE ROAD SOUTH + + CA + +00-00-B0 (hex) RND-RAD NETWORK DEVICES +0000B0 (base 16) RND-RAD NETWORK DEVICES + ATIDIM TECHNOL'CL BLDG. 1 + + IL + +00-00-CF (hex) HAYES MICROCOMPUTER PRODUCTS +0000CF (base 16) HAYES MICROCOMPUTER PRODUCTS + (CANADA) LTD. + + CA + +00-00-56 (hex) DR. B. STRUCK +000056 (base 16) DR. B. STRUCK + POB 1147 BAECKERBARG 6 + W-GERMANY + DE + +00-00-6C (hex) Private +00006C (base 16) Private + +00-00-A9 (hex) NETWORK SYSTEMS CORP. +0000A9 (base 16) NETWORK SYSTEMS CORP. + 7600 BOONE AVENUE NORTH + MINNEAPOLIS MN 55428-1099 + US + +00-00-EF (hex) KTI +0000EF (base 16) KTI + 2157 O'TOOLE AVENUE + SAN JOSE CA 95131 + US + +00-00-25 (hex) RAMTEK CORP. +000025 (base 16) RAMTEK CORP. + 810 W. MAUDE AVENUE + SUNNYVALE CA 94086 + US + +00-00-AF (hex) Canberra Industries, Inc. +0000AF (base 16) Canberra Industries, Inc. + 800 Research Parkway + Meriden CT 06450 + US + +00-00-76 (hex) ABEKAS VIDEO SYSTEM +000076 (base 16) ABEKAS VIDEO SYSTEM + 101 GALVESTON DRIVE + REDWOOD CITY CA 94063 + US + +08-00-55 (hex) STANFORD TELECOMM. INC. +080055 (base 16) STANFORD TELECOMM. INC. + 1221 CROSSMAN + SUNNYVALE CA 94089 + US + +08-00-53 (hex) MIDDLE EAST TECH. UNIVERSITY +080053 (base 16) MIDDLE EAST TECH. UNIVERSITY + DEPARTMENT OF + ANKARA + TR + +08-00-8E (hex) Tandem Computers +08008E (base 16) Tandem Computers + 14231 Tendem Blvd. + Austin TX 78728 - 6610 + US + +08-00-84 (hex) TOMEN ELECTRONICS CORP. +080084 (base 16) TOMEN ELECTRONICS CORP. + 1-1 UCHISAIWAI-CHO 2CHOME + + JP + +08-00-85 (hex) ELXSI +080085 (base 16) ELXSI + 2334 LUNDY PLACE + SAN JOSE CA 95131 + US + +08-00-82 (hex) VERITAS SOFTWARE +080082 (base 16) VERITAS SOFTWARE + 4800 GREAT AMERICA PARKWAY + SANTA CLARA CA 95054 + US + +08-00-80 (hex) AES DATA INC. +080080 (base 16) AES DATA INC. + 1900 MINNESOTA COURT + CANADA L5N L5N 3C9 + CA + +08-00-77 (hex) TSL COMMUNICATIONS LTD. +080077 (base 16) TSL COMMUNICATIONS LTD. + THE LANDSBURY ESTATE + ENGLAND + GB + +08-00-74 (hex) CASIO COMPUTER CO. LTD. +080074 (base 16) CASIO COMPUTER CO. LTD. + 3-2-1 SAKAE-CHO + 190-11 + JP + +08-00-6E (hex) MASSCOMP +08006E (base 16) MASSCOMP + ONE TECHNOLOGY PARK + WESTFORD MA 01886 + US + +08-00-68 (hex) RIDGE COMPUTERS +080068 (base 16) RIDGE COMPUTERS + 2451 MISSION COLLEGE BLVD. + SANTA CLARA CA 95054 + US + +08-00-63 (hex) PLESSEY +080063 (base 16) PLESSEY + PLESSEY - UK LIMITED + JAMAICA NY 11434 + US + +08-00-7B (hex) SANYO ELECTRIC CO. LTD. +08007B (base 16) SANYO ELECTRIC CO. LTD. + 1-18-13 HASHIRIDANI + OSAKA 573 + JP + +08-00-7C (hex) VITALINK COMMUNICATIONS CORP. +08007C (base 16) VITALINK COMMUNICATIONS CORP. + 48761 KATO ROAD + FREMONT CA 94538 + US + +00-00-DF (hex) BELL & HOWELL PUB SYS DIV +0000DF (base 16) BELL & HOWELL PUB SYS DIV + OLD MANSFIELD ROAD + WOOSTER OH 44691-9050 + US + +00-00-F9 (hex) QUOTRON SYSTEMS INC. +0000F9 (base 16) QUOTRON SYSTEMS INC. + 5454 BEETHOVEN ST. + LOS ANGELES CA 90066 + US + +08-00-60 (hex) INDUSTRIAL NETWORKING INC. +080060 (base 16) INDUSTRIAL NETWORKING INC. + 3990 FREEDOM CIRCLE + SANTA CLARA CA 95050 + US + +08-00-4C (hex) HYDRA COMPUTER SYSTEMS INC. +08004C (base 16) HYDRA COMPUTER SYSTEMS INC. + 12 MERCER ROAD + NATICK MA 01760 + US + +08-00-47 (hex) SEQUENT COMPUTER SYSTEMS INC. +080047 (base 16) SEQUENT COMPUTER SYSTEMS INC. + 15450 S.W. KOLL PARKWAY . + BEAVERTON OR 97006 + US + +08-00-4A (hex) BANYAN SYSTEMS INC. +08004A (base 16) BANYAN SYSTEMS INC. + 135 FLANDERS ROAD + WESTBORO MA 01581 + US + +08-00-44 (hex) DAVID SYSTEMS INC. +080044 (base 16) DAVID SYSTEMS INC. + 615 TASMAN DRIVE + SUNNYVALE CA 94088 + US + +08-00-41 (hex) RACAL-MILGO INFORMATION SYS.. +080041 (base 16) RACAL-MILGO INFORMATION SYS.. + 400 EMBASSY ROW + ATLANTA GA 30328 + US + +08-00-37 (hex) FUJI-XEROX CO. LTD. +080037 (base 16) FUJI-XEROX CO. LTD. + ADVANCED TECH & ENG'G CENTER + + JP + +08-00-35 (hex) MICROFIVE CORPORATION +080035 (base 16) MICROFIVE CORPORATION + 3560 HYLAND AVENUE + COSTA MESA CA 92626 + US + +08-00-32 (hex) TIGAN INCORPORATED +080032 (base 16) TIGAN INCORPORATED + 4020 FABIAN WAY + PALO ALTO CA 94303 + US + +08-00-8D (hex) XYVISION INC. +08008D (base 16) XYVISION INC. + 101 EDGEWATER DRIVE + WAKEFIELD MA 01880 + US + +08-00-15 (hex) STC BUSINESS SYSTEMS +080015 (base 16) STC BUSINESS SYSTEMS + HOLBROOK HOUSE + UNITED KINGDOM + GB + +08-00-42 (hex) JAPAN MACNICS CORP. +080042 (base 16) JAPAN MACNICS CORP. + + + JP + +08-00-66 (hex) AGFA CORPORATION +080066 (base 16) AGFA CORPORATION + 200 BALLARDVALE STREET + WILMINGTON MA 01887 + US + +08-00-04 (hex) CROMEMCO INCORPORATED +080004 (base 16) CROMEMCO INCORPORATED + 280 BERNARDO AVENUE + MOUNTAIN VIEW CA 94043 + US + +00-01-C8 (hex) CONRAD CORP. +0001C8 (base 16) CONRAD CORP. + + + + +08-00-3F (hex) FRED KOSCHARA ENTERPRISES +08003F (base 16) FRED KOSCHARA ENTERPRISES + + + + +08-00-0B (hex) UNISYS CORPORATION +08000B (base 16) UNISYS CORPORATION + TOWNSHIP LINE ROAD + BLUE BELL PA 19424 + US + +00-DD-01 (hex) UNGERMANN-BASS INC. +00DD01 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +00-DD-06 (hex) UNGERMANN-BASS INC. +00DD06 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +AA-00-03 (hex) DIGITAL EQUIPMENT CORPORATION +AA0003 (base 16) DIGITAL EQUIPMENT CORPORATION + LKG 1-2/A19 + LITTLETON MA 01460-1289 + US + +00-00-00 (hex) XEROX CORPORATION +000000 (base 16) XEROX CORPORATION + M/S 105-50C + WEBSTER NY 14580 + US + +08-00-21 (hex) 3M COMPANY +080021 (base 16) 3M COMPANY + Telecom Division + Austin TX 78726-9000 + US + +02-BB-01 (hex) OCTOTHORPE CORP. +02BB01 (base 16) OCTOTHORPE CORP. + 285 WEST GREEN STREET + PASADENA CA 91105 + US + +08-00-8A (hex) PerfTech, Inc. +08008A (base 16) PerfTech, Inc. + 613 NW Loop 410 + SAN ANTONIO TX 78216 + US + +00-00-3E (hex) SIMPACT +00003E (base 16) SIMPACT + 9210 SKY PARK COURT + SAN DIEGO CA 92123 + US + +00-DD-02 (hex) UNGERMANN-BASS INC. +00DD02 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +00-DD-04 (hex) UNGERMANN-BASS INC. +00DD04 (base 16) UNGERMANN-BASS INC. + 3900 FREEDOM CIRCLE + SANTA CLARA CA 95054 + US + +02-60-86 (hex) LOGIC REPLACEMENT TECH. LTD. +026086 (base 16) LOGIC REPLACEMENT TECH. LTD. + 14 ARKWRIGHT ROAD + UNITED KINGDOM + GB + +08-00-30 (hex) CERN +080030 (base 16) CERN + CH-1211 + GENEVE SUISSE/SWITZ 023 + CH + +74-DA-88 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +74DA88 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +CC-32-E5 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +CC32E5 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +1C-3B-F3 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +1C3BF3 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +3C-86-D1 (hex) vivo Mobile Communication Co., Ltd. +3C86D1 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +30-1B-97 (hex) Lierda Science & Technology Group Co.,Ltd +301B97 (base 16) Lierda Science & Technology Group Co.,Ltd + Lierda Science Park?No.1326 WenyiWestRoad + Hangzhou ZheJiang 311121 + CN + +2C-D2-E3 (hex) Guangzhou Aoshi Electronic Co.,Ltd +2CD2E3 (base 16) Guangzhou Aoshi Electronic Co.,Ltd + B1,Huachuang industrial park,Jinshan Avenue,Panyu District + Guangzhou Guangdong 511450 + CN + +14-59-C3 (hex) Creative Chips GmbH +1459C3 (base 16) Creative Chips GmbH + Im Bubenstück 1 + Bingen Rheinland-Pfalz 55411 + DE + +A0-D8-6F (hex) ARGO AI, LLC +A0D86F (base 16) ARGO AI, LLC + 40, 24th Street, Second Floor + Pittsburgh PA 15222 + US + +E4-67-1E (hex) SHEN ZHEN NUO XIN CHENG TECHNOLOGY co., Ltd. +E4671E (base 16) SHEN ZHEN NUO XIN CHENG TECHNOLOGY co., Ltd. + Building A2 and 1 F/L, Building A1, 9 Wugang Rd, Xikeng Village, Xikeng Community, Henggang Sub-district, Longgang District + Shenzhen 518100 + CN + +68-27-19 (hex) Microchip Technology Inc. +682719 (base 16) Microchip Technology Inc. + 2355 W. Chandler Blvd. + Chandler AZ 85224 + US + +24-C1-7A (hex) BEIJING IACTIVE NETWORK CO.,LTD +24C17A (base 16) BEIJING IACTIVE NETWORK CO.,LTD + Room 525, Yiquanhui Building, No. 35 Shangdi East Road, Haidian District + BEIJING 100085 + CN + +1C-9C-8C (hex) Juniper Networks +1C9C8C (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +A4-C9-39 (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +A4C939 (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +34-D7-72 (hex) Xiamen Yudian Automation Technology Co., Ltd +34D772 (base 16) Xiamen Yudian Automation Technology Co., Ltd + No. 17 North Huoju Rd., Huoju Park, Huoju Hi-Tech District + XIAMEN FUJIAN 361000 + CN + +C0-DC-DA (hex) Samsung Electronics Co.,Ltd +C0DCDA (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +04-B4-29 (hex) Samsung Electronics Co.,Ltd +04B429 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +48-79-4D (hex) Samsung Electronics Co.,Ltd +48794D (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +44-F9-71 (hex) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. +44F971 (base 16) SHENZHEN MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD. + 3/F, Building R1-B, High-Tech Industrial Park, Nanshan District + Shenzhen Guangdong 518057 + CN + +18-F9-C4 (hex) BAE Systems +18F9C4 (base 16) BAE Systems + 21 continental boulevard + Merrimack NH 03054 + US + +60-AB-D2 (hex) Bose Corporation +60ABD2 (base 16) Bose Corporation + The Mountain + Framingham MA 01701-9168 + US + +F0-EF-86 (hex) Google, Inc. +F0EF86 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +E4-C0-CC (hex) China Mobile Group Device Co.,Ltd. +E4C0CC (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +5C-B1-3E (hex) Sagemcom Broadband SAS +5CB13E (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +F4-E5-F2 (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4E5F2 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +54-13-10 (hex) HUAWEI TECHNOLOGIES CO.,LTD +541310 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +8C-E5-EF (hex) HUAWEI TECHNOLOGIES CO.,LTD +8CE5EF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +A4-CD-23 (hex) Shenzhenshi Xinzhongxin Co., Ltd +A4CD23 (base 16) Shenzhenshi Xinzhongxin Co., Ltd + Building A3, Donghuan Industrial Zone, Nanpu Road, Shajing Town, Baoan District + Shenzhen Guangdong 518125 + CN + +B8-3A-5A (hex) Aruba, a Hewlett Packard Enterprise Company +B83A5A (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +E4-AA-EA (hex) Liteon Technology Corporation +E4AAEA (base 16) Liteon Technology Corporation + 4F, 90, Chien 1 Road + New Taipei City Taiwan 23585 + TW + +A0-94-6A (hex) Shenzhen XGTEC Technology Co,.Ltd. +A0946A (base 16) Shenzhen XGTEC Technology Co,.Ltd. + Room 312, Changhong Science and Technology Building, No.18, South 12 Rd., High-tech Community, Yuehai Street, Nanshan District, Shenzhen + Shenzhen Guangdong 518057 + CN + +1C-2A-A3 (hex) Shenzhen HongRui Optical Technology Co., Ltd. +1C2AA3 (base 16) Shenzhen HongRui Optical Technology Co., Ltd. + B#2F Shuangjinhui Industrial Park, Yonghe Road, Heping Village, Fuyong Town, Bao'an Dis + Shenzhen Guangdong 518000 + CN + +38-8E-7A (hex) AUTOIT +388E7A (base 16) AUTOIT + 212, Gasan digital 1-ro + Seoul Geumcheon-gu 08502 + KR + +4C-71-0C (hex) Cisco Systems, Inc +4C710C (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +4C-71-0D (hex) Cisco Systems, Inc +4C710D (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +9C-31-C3 (hex) BSkyB Ltd +9C31C3 (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +6C-24-A6 (hex) vivo Mobile Communication Co., Ltd. +6C24A6 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +9C-5F-5A (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +9C5F5A (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +E4-47-B3 (hex) zte corporation +E447B3 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +FC-DB-21 (hex) SAMSARA NETWORKS INC +FCDB21 (base 16) SAMSARA NETWORKS INC + 525 York St + San Francisco CA 94110 + US + +60-77-71 (hex) Texas Instruments +607771 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +D8-CF-89 (hex) Beijing DoSee Science and Technology Co., Ltd. +D8CF89 (base 16) Beijing DoSee Science and Technology Co., Ltd. + Room 819-158,Floor 8,XinCaiLiao Chuangye Building,No.7 FengHuiZhong Road, Haidian District + Beijing 100094 + CN + +04-AA-E1 (hex) BEIJING MICROVISION TECHNOLOGY CO.,LTD +04AAE1 (base 16) BEIJING MICROVISION TECHNOLOGY CO.,LTD + ROOM 207-208,2/F,TAIXIANG COMMERCIAL BUILDING,NO.1A,LONGXIANG ROAD,HAIDIAN DISTRICT,BEIJING,P.R.C + BEIJING BEIJING 100191 + CN + +44-DC-4E (hex) ITEL MOBILE LIMITED +44DC4E (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +38-2A-19 (hex) Technica Engineering GmbH +382A19 (base 16) Technica Engineering GmbH + Leopoldstraße 236 + Munich 80807 + DE + +74-D6-54 (hex) GINT +74D654 (base 16) GINT + 9F, 47, Daehak-ro, Youngtong-gu + Suwon-si Gyeonggi-do 16225 + KR + +B4-E8-C9 (hex) XADA Technologies +B4E8C9 (base 16) XADA Technologies + No. 2-2, Xinyi Road Section 5, Lane 150, 1st Floor + Taipei City Taipei City 110 + TW + +7C-21-0E (hex) Cisco Systems, Inc +7C210E (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +94-2D-DC (hex) Samsung Electronics Co.,Ltd +942DDC (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +54-F2-94 (hex) Huawei Device Co., Ltd. +54F294 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +24-5A-B5 (hex) Samsung Electronics Co.,Ltd +245AB5 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +C0-D2-DD (hex) Samsung Electronics Co.,Ltd +C0D2DD (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +AC-1E-92 (hex) Samsung Electronics Co.,LTD +AC1E92 (base 16) Samsung Electronics Co.,LTD + 129, Samsung-ro, Youngtongl-Gu + Suwon 16677 + KR + +00-68-EB (hex) HP Inc. +0068EB (base 16) HP Inc. + 10300 Energy Dr + Spring TX 77389 + US + +7C-B3-7B (hex) Qingdao Intelligent&Precise Electronics Co.,Ltd. +7CB37B (base 16) Qingdao Intelligent&Precise Electronics Co.,Ltd. + No.218 Qianwangang Road + Qingdao Shangdong 266510 + CN + +48-4C-86 (hex) Huawei Device Co., Ltd. +484C86 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +88-12-3D (hex) Suzhou Aquila Solutions Inc. +88123D (base 16) Suzhou Aquila Solutions Inc. + Room 201, Building 3, 18 Dongchang Road, Suzhou Industry Park, Suzhou, PRC. Zip Code: 215000 + Suzhou 215000 + CN + +48-21-0B (hex) PEGATRON CORPORATION +48210B (base 16) PEGATRON CORPORATION + 5F No. 76, Ligong St., Beitou District + Taipei City Taiwan 112 + TW + +A0-1C-8D (hex) HUAWEI TECHNOLOGIES CO.,LTD +A01C8D (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +7C-31-0E (hex) Cisco Systems, Inc +7C310E (base 16) Cisco Systems, Inc + 80 West Tasman Dr. + San Jose CA 94568 + US + +F4-DE-AF (hex) HUAWEI TECHNOLOGIES CO.,LTD +F4DEAF (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +60-12-3C (hex) HUAWEI TECHNOLOGIES CO.,LTD +60123C (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +48-A5-E7 (hex) Nintendo Co.,Ltd +48A5E7 (base 16) Nintendo Co.,Ltd + 11-1 HOKOTATE-CHO KAMITOBA,MINAMI-KU + KYOTO KYOTO 601-8501 + JP + +08-2C-B6 (hex) Apple, Inc. +082CB6 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +F8-4E-73 (hex) Apple, Inc. +F84E73 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +B4-26-5D (hex) Taicang T&W Electronics +B4265D (base 16) Taicang T&W Electronics + 89# Jiang Nan RD + Suzhou Jiangsu 215412 + CN + +F0-78-07 (hex) Apple, Inc. +F07807 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +3C-CD-36 (hex) Apple, Inc. +3CCD36 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D4-B7-09 (hex) zte corporation +D4B709 (base 16) zte corporation + 12/F.,zte R&D building ,kejinan Road,Shenzhen,P.R.China + shenzhen guangdong 518057 + CN + +38-14-4E (hex) Fiberhome Telecommunication Technologies Co.,LTD +38144E (base 16) Fiberhome Telecommunication Technologies Co.,LTD + No.5 DongXin Road + Wuhan Hubei 430074 + CN + +5C-80-B6 (hex) Intel Corporate +5C80B6 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +F8-E4-E3 (hex) Intel Corporate +F8E4E3 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +AC-BD-0B (hex) Leimac Ltd. +ACBD0B (base 16) Leimac Ltd. + 1551, Sazukawa-chou + Moriyama-shi Shiga-ken 524-0215 + JP + +E0-CC-F8 (hex) Xiaomi Communications Co Ltd +E0CCF8 (base 16) Xiaomi Communications Co Ltd + The Rainbow City of China Resources + NO.68, Qinghe Middle Street Haidian District, Beijing 100085 + CN + +98-52-4A (hex) Technicolor CH USA Inc. +98524A (base 16) Technicolor CH USA Inc. + 5030 Sugarloaf Parkway Bldg 6 + Lawrenceville GA 30044 + US + +84-C5-A6 (hex) Intel Corporate +84C5A6 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +38-68-A4 (hex) Samsung Electronics Co.,LTD +3868A4 (base 16) Samsung Electronics Co.,LTD + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +B4-A5-AC (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +B4A5AC (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +1C-78-4E (hex) China Mobile Iot Limited company +1C784E (base 16) China Mobile Iot Limited company + No. 8 Yangliu North Road, Yubei District, Chongqing, China + Chong Qing Chong Qing 401120 + CN + +84-3E-79 (hex) Shenzhen Belon Technology CO.,LTD +843E79 (base 16) Shenzhen Belon Technology CO.,LTD + Tsinghua Information + Shenzhen Guangdong 518052 + CN + +B8-19-04 (hex) Nokia Shanghai Bell Co., Ltd. +B81904 (base 16) Nokia Shanghai Bell Co., Ltd. + No.388 Ning Qiao Road,Jin Qiao Pudong Shanghai + Shanghai 201206 + CN + +F4-A5-9D (hex) Huawei Device Co., Ltd. +F4A59D (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +E0-F4-42 (hex) Huawei Device Co., Ltd. +E0F442 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +F0-C4-2F (hex) Huawei Device Co., Ltd. +F0C42F (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +C0-B4-7D (hex) Huawei Device Co., Ltd. +C0B47D (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +44-46-87 (hex) Realme Chongqing MobileTelecommunications Corp Ltd +444687 (base 16) Realme Chongqing MobileTelecommunications Corp Ltd + No.24 Nichang Boulevard, Huixing Block, Yubei District, Chongqing. + Chongqing China 401120 + CN + +E8-26-89 (hex) Aruba, a Hewlett Packard Enterprise Company +E82689 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +20-F3-75 (hex) ARRIS Group, Inc. +20F375 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +84-BB-69 (hex) ARRIS Group, Inc. +84BB69 (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +10-5F-D4 (hex) Tendyron Corporation +105FD4 (base 16) Tendyron Corporation + Tendyron Building,Zhongguancun NO.1 Park,Beiqing Road,Haidian District,Beijing,China + Beijing 100000 + CN + +8C-E3-8E (hex) Kioxia Corporation +8CE38E (base 16) Kioxia Corporation + 1-21, Shibaura 3-chome + Minato-ku Tokyo 108-0023 + JP + +A0-B4-39 (hex) Cisco Systems, Inc +A0B439 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +A4-B4-39 (hex) Cisco Systems, Inc +A4B439 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +00-10-38 (hex) Micro Research Ltd. +001038 (base 16) Micro Research Ltd. + 2F Minami-Shinagawa N Bldg., 2-2-10 Minami-Shinagawa + Tokyo Shinagawa-Ku 140-0004 + JP + +E8-1B-4B (hex) amnimo Inc. +E81B4B (base 16) amnimo Inc. + M21-4, 2-9-32 Nakacho + Musashino-shi Tokyo 180-8750 + JP + +CC-F4-11 (hex) Google, Inc. +CCF411 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +9C-2D-CF (hex) Shishi Tongyun Technology(Chengdu)Co.,Ltd. +9C2DCF (base 16) Shishi Tongyun Technology(Chengdu)Co.,Ltd. + No. 1268 Middle Section of Tianfu Avenue, Chengdu High-tech Zone, China (Sichuan) Pilot Free Trade Zone + Chengdu Sichuan 610017 + CN + +94-24-B8 (hex) GREE ELECTRIC APPLIANCES, INC. OF ZHUHAI +9424B8 (base 16) GREE ELECTRIC APPLIANCES, INC. OF ZHUHAI + Jinji West Road, Qianshan, + Zhuhai Guangdong 519070 + CN + +04-33-C2 (hex) Intel Corporate +0433C2 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +C8-03-F5 (hex) Ruckus Wireless +C803F5 (base 16) Ruckus Wireless + 350 West Java Drive + Sunnyvale CA 94089 + US + +00-0D-0A (hex) Barco Projection Systems NV +000D0A (base 16) Barco Projection Systems NV + Beneluxpark 21 + Kortrijk West Flanders 8500 + BE + +C4-67-D1 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C467D1 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +9C-8A-CB (hex) Juniper Networks +9C8ACB (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +C8-C4-65 (hex) HUAWEI TECHNOLOGIES CO.,LTD +C8C465 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +1C-43-63 (hex) HUAWEI TECHNOLOGIES CO.,LTD +1C4363 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +94-29-2F (hex) New H3C Technologies Co., Ltd +94292F (base 16) New H3C Technologies Co., Ltd + 466 Changhe Road, Binjiang District + Hangzhou Zhejiang 310052 + CN + +D4-9A-A0 (hex) VNPT TECHNOLOGY +D49AA0 (base 16) VNPT TECHNOLOGY + HoaLac Hi-Tech Park + HANOI HANOI 10000 + VN + +F8-0F-F9 (hex) Google, Inc. +F80FF9 (base 16) Google, Inc. + 1600 Amphitheatre Parkway + Mountain View CA 94043 + US + +8C-5A-C1 (hex) Huawei Device Co., Ltd. +8C5AC1 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +A8-5A-E0 (hex) Huawei Device Co., Ltd. +A85AE0 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +A4-B6-1E (hex) Huawei Device Co., Ltd. +A4B61E (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +C4-FE-5B (hex) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD +C4FE5B (base 16) GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD + NO.18 HAIBIN ROAD, + DONG GUAN GUANG DONG 523860 + CN + +C0-39-37 (hex) GREE ELECTRIC APPLIANCES, INC. OF ZHUHAI +C03937 (base 16) GREE ELECTRIC APPLIANCES, INC. OF ZHUHAI + Jinji West Road, Qianshan, + Zhuhai Guangdong 519070 + CN + +B4-4C-3B (hex) Zhejiang Dahua Technology Co., Ltd. +B44C3B (base 16) Zhejiang Dahua Technology Co., Ltd. + No.1199,Waterfront Road + Hangzhou Zhejiang 310053 + CN + +40-A2-DB (hex) Amazon Technologies Inc. +40A2DB (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +4C-6C-13 (hex) IoT Company Solucoes Tecnologicas Ltda +4C6C13 (base 16) IoT Company Solucoes Tecnologicas Ltda + Rua Jordao Schiavetto, 436 - Sala 6 + Hortolandia Sao Paulo 13184-080 + BR + +A8-85-D7 (hex) Sangfor Technologies Inc. +A885D7 (base 16) Sangfor Technologies Inc. + block A1 ?nanshan ipark, No 1001, xueyuan road + Shenzhen 518100 + CN + +44-4A-DB (hex) Apple, Inc. +444ADB (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +84-F8-83 (hex) Luminar Technologies +84F883 (base 16) Luminar Technologies + 12601 Research Pkwy + Orlando FL 32828-7335 + US + +9C-A5-13 (hex) Samsung Electronics Co.,Ltd +9CA513 (base 16) Samsung Electronics Co.,Ltd + #94-1, Imsoo-Dong + Gumi Gyeongbuk 730-350 + KR + +10-39-E9 (hex) Juniper Networks +1039E9 (base 16) Juniper Networks + 1133 Innovation Way + Sunnyvale CA 94089 + US + +30-90-48 (hex) Apple, Inc. +309048 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +D4-1F-0C (hex) JAI Manufacturing +D41F0C (base 16) JAI Manufacturing + 2960-14 Uenojo Nishikata + Kushima Miyazaki 888-0004 + JP + +C8-FA-84 (hex) Trusonus corp. +C8FA84 (base 16) Trusonus corp. + 6F., No.42, Songjiang Rd., Zhongshan Dist + Taipei 10455 + TW + +C4-02-E1 (hex) Khwahish Technologies Private Limited +C402E1 (base 16) Khwahish Technologies Private Limited + Plot # 42, Thirugnana Sambandhar Street, Srinivasa Nagar, Madipakkam + Chennai TamilNadu 600091 + IN + +F8-5B-3B (hex) ASKEY COMPUTER CORP +F85B3B (base 16) ASKEY COMPUTER CORP + 10F,No.119,JIANKANG RD,ZHONGHE DIST + NEW TAIPEI TAIWAN 23585 + TW + +78-6D-EB (hex) GE Lighting +786DEB (base 16) GE Lighting + 1975 Noble Rd + East Cleveland OH 44112 + US + +88-E9-A4 (hex) Hewlett Packard Enterprise +88E9A4 (base 16) Hewlett Packard Enterprise + 8000 Foothills Blvd. + Roseville CA 95747 + US + +28-63-BD (hex) APTIV SERVICES US, LLC +2863BD (base 16) APTIV SERVICES US, LLC + 5725 Innovation Drive + Troy MI 48098 + US + +1C-72-1D (hex) Dell Inc. +1C721D (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +F4-1C-95 (hex) BEIJING YUNYI TIMES TECHNOLOGY CO,.LTD +F41C95 (base 16) BEIJING YUNYI TIMES TECHNOLOGY CO,.LTD + Room 2005, 2f, building B, No.1 Kaituo Road, Shangdi Information Industry base, Haidian District + BEIJING 100085 + CN + +A0-68-7E (hex) ARRIS Group, Inc. +A0687E (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +A8-70-5D (hex) ARRIS Group, Inc. +A8705D (base 16) ARRIS Group, Inc. + 6450 Sequence Drive + San Diego CA 92121 + US + +54-65-03 (hex) Quectel Wireless Solutions Co., Ltd. +546503 (base 16) Quectel Wireless Solutions Co., Ltd. + 7th Floor, Hongye Building, No.1801 Hongmei Road, Xuhui District + Shanghai 200233 + CN + +9C-97-89 (hex) 1MORE +9C9789 (base 16) 1MORE + TianliaoBuilding F14, New Materials Industrial Park, Xueyuan Blvd?Nanshan + Shenzhen Guangdong 518055 + CN + +1C-05-B7 (hex) Chongqing Trantor Technology Co., Ltd. +1C05B7 (base 16) Chongqing Trantor Technology Co., Ltd. + No.69,Huoju Avenue,Jiulongpo District. + Chongqing Chongqing 400050 + CN + +00-0E-F3 (hex) Smartlabs, Inc. +000EF3 (base 16) Smartlabs, Inc. + 1621 Alton Parkway, Suite 100 + Irvine CA 92606 + US + +A0-43-B0 (hex) Hangzhou BroadLink Technology Co.,Ltd +A043B0 (base 16) Hangzhou BroadLink Technology Co.,Ltd + Room 101,1/F,Unit C,Building 1,No.57 Jiang'er Road,Changhe Street,Binjiang District,Hangzhou,Zhejiang,P.R.China + Hangzhou Zhejiang 310052 + CN + +74-AC-B9 (hex) Ubiquiti Networks Inc. +74ACB9 (base 16) Ubiquiti Networks Inc. + 2580 Orchard Pkwy + San Jose CA 95131 + US + +F4-92-BF (hex) Ubiquiti Networks Inc. +F492BF (base 16) Ubiquiti Networks Inc. + 2580 Orchard Pkwy + San Jose CA 95131 + US + +D8-C5-61 (hex) CommFront Communications Pte Ltd +D8C561 (base 16) CommFront Communications Pte Ltd + No. 1 Yishun Industrial ST 1, #05-31 A'Posh BizHub + SG SG 768160 + SG + +0C-29-EF (hex) Dell Inc. +0C29EF (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +60-D8-9C (hex) HMD Global Oy +60D89C (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +F8-2E-8E (hex) Nanjing Kechen Electric Co., Ltd. +F82E8E (base 16) Nanjing Kechen Electric Co., Ltd. + Room 202, Building 12, No. 50 Daguang road + Nanjing 210001 + CN + +B4-C9-B9 (hex) Sichuan AI-Link Technology Co., Ltd. +B4C9B9 (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou, Industrial Park + Mianyang Sichuan 622650 + CN + +F0-46-3B (hex) Comcast Cable Corporation +F0463B (base 16) Comcast Cable Corporation + 1800 Arch Street + Philadelphia PA 19103 + US + +68-D7-9A (hex) Ubiquiti Networks Inc. +68D79A (base 16) Ubiquiti Networks Inc. + 2580 Orchard Pkwy + San Jose CA 95131 + US + +1C-63-BF (hex) SHENZHEN BROADTEL TELECOM CO.,LTD +1C63BF (base 16) SHENZHEN BROADTEL TELECOM CO.,LTD + No.14-1, Tongqing Road, Baolong street, Longgang District + ShenZhen GuangDong 518116 + CN + +AC-36-51 (hex) Jiangsu Hengtong Terahertz Technology Co., Ltd. +AC3651 (base 16) Jiangsu Hengtong Terahertz Technology Co., Ltd. + Room 1312, Beiyou Technology Building, Haidian District + Beijing Beijing 100876 + CN + +68-4A-76 (hex) eero inc. +684A76 (base 16) eero inc. + 660 3rd Street + San Francisco CA 94107 + US + +68-8F-C9 (hex) Zhuolian (Shenzhen) Communication Co., Ltd +688FC9 (base 16) Zhuolian (Shenzhen) Communication Co., Ltd + Shengli electromechanical Co., Ltd. 201, No.19, Xixiang section, Guangshen Road, Jingbei community, Xixiang street, Bao'an District + Shenzhen Shenzhen 518101 + CN + +F0-81-75 (hex) Sagemcom Broadband SAS +F08175 (base 16) Sagemcom Broadband SAS + 250, route de l'Empereur + Rueil Malmaison Cedex hauts de seine 92848 + FR + +D8-47-32 (hex) TP-LINK TECHNOLOGIES CO.,LTD. +D84732 (base 16) TP-LINK TECHNOLOGIES CO.,LTD. + Building 24(floors 1,3,4,5)and 28(floors 1-4)Central Science and Technology Park,Shennan Road,Nanshan + Shenzhen Guangdong 518057 + CN + +28-64-B0 (hex) Huawei Device Co., Ltd. +2864B0 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +04-F1-69 (hex) Huawei Device Co., Ltd. +04F169 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +50-21-EC (hex) Huawei Device Co., Ltd. +5021EC (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +8C-68-3A (hex) HUAWEI TECHNOLOGIES CO.,LTD +8C683A (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +B4-6E-08 (hex) HUAWEI TECHNOLOGIES CO.,LTD +B46E08 (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +00-5E-0C (hex) HMD Global Oy +005E0C (base 16) HMD Global Oy + Bertel Jungin aukio 9 + Espoo 02600 + FI + +B4-81-07 (hex) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD +B48107 (base 16) SHENZHEN CHUANGWEI-RGB ELECTRONICS CO.,LTD + Unit East Block22-24/F,Skyworth semiconductor design Bldg., Gaoxin Ave.4.S.,Nanshan District,Shenzhen,China + SHENZHEN GUANGDONG 518057 + CN + +70-66-55 (hex) AzureWave Technology Inc. +706655 (base 16) AzureWave Technology Inc. + 8F., No. 94, Baozhong Rd. + New Taipei City Taiwan 231 + TW + +C8-58-C0 (hex) Intel Corporate +C858C0 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +64-7C-34 (hex) Ubee Interactive Co., Limited +647C34 (base 16) Ubee Interactive Co., Limited + Flat/RM 1202, 12/F, AT Tower + North Point Hong Kong 180 + HK + +6C-38-A1 (hex) Ubee Interactive Co., Limited +6C38A1 (base 16) Ubee Interactive Co., Limited + Flat/RM 1202, 12/F, AT Tower + North Point Hong Kong 180 + HK + +78-53-0D (hex) Shenzhen Skyworth Digital Technology CO., Ltd +78530D (base 16) Shenzhen Skyworth Digital Technology CO., Ltd + 4F,Block A, Skyworth?Building, + Shenzhen Guangdong 518057 + CN + +0C-48-C6 (hex) CELESTICA INC. +0C48C6 (base 16) CELESTICA INC. + 1900-5140 Yonge Street PO Box 42 + Toronto Ontario M2N 6L7 + CA + +A4-29-85 (hex) Sichuan AI-Link Technology Co., Ltd. +A42985 (base 16) Sichuan AI-Link Technology Co., Ltd. + Anzhou, Industrial Park + Mianyang Sichuan 622650 + CN + +78-AC-44 (hex) Dell Inc. +78AC44 (base 16) Dell Inc. + One Dell Way + Round Rock TX 78682 + US + +98-C8-B8 (hex) vivo Mobile Communication Co., Ltd. +98C8B8 (base 16) vivo Mobile Communication Co., Ltd. + #283,BBK Road + Wusha,Chang'An DongGuan City,Guangdong, 523860 + CN + +B8-D4-E7 (hex) Aruba, a Hewlett Packard Enterprise Company +B8D4E7 (base 16) Aruba, a Hewlett Packard Enterprise Company + 3333 Scott Blvd + Santa Clara CA 95054 + US + +D8-4C-90 (hex) Apple, Inc. +D84C90 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +24-D0-DF (hex) Apple, Inc. +24D0DF (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +6C-4A-85 (hex) Apple, Inc. +6C4A85 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +28-F0-33 (hex) Apple, Inc. +28F033 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +20-9E-F7 (hex) Extreme Networks, Inc. +209EF7 (base 16) Extreme Networks, Inc. + 6480 Via Del Oro + San Jose CA 95119 + US + +BC-09-63 (hex) Apple, Inc. +BC0963 (base 16) Apple, Inc. + 1 Infinite Loop + Cupertino CA 95014 + US + +18-58-69 (hex) Sailer Electronic Co., Ltd +185869 (base 16) Sailer Electronic Co., Ltd + No. 6, Sanxi Road, Ximagou Industrial Park, Jianxi District + Luoyang Henan 471000 + CN + +BC-2D-EF (hex) Realme Chongqing Mobile Telecommunications Corp.,Ltd. +BC2DEF (base 16) Realme Chongqing Mobile Telecommunications Corp.,Ltd. + No.178 Yulong Avenue, Yufengshan, Yubei District, Chongqing. + Chongqing China 401120 + CN + +78-81-CE (hex) China Mobile Iot Limited company +7881CE (base 16) China Mobile Iot Limited company + No. 8 Yangliu North Road, Yubei District, Chongqing, China + Chong Qing Chong Qing 401120 + CN + +BC-FF-21 (hex) Smart Code(shenzhen)Technology Co.,Ltd +BCFF21 (base 16) Smart Code(shenzhen)Technology Co.,Ltd + Room 1206, Satellite Building,2002 Keyuan Road, Nanshan + Shenzhen Guangdong (Province) 518000 + CN + +44-5C-E9 (hex) Samsung Electronics Co.,Ltd +445CE9 (base 16) Samsung Electronics Co.,Ltd + 129, Samsung-ro, Youngtongl-Gu + Suwon Gyeonggi-Do 16677 + KR + +C0-16-92 (hex) China Mobile Group Device Co.,Ltd. +C01692 (base 16) China Mobile Group Device Co.,Ltd. + 32 Xuanwumen West Street,Xicheng District + Beijing 100053 + CN + +38-17-30 (hex) Ulrich Lippert GmbH & Co KG +381730 (base 16) Ulrich Lippert GmbH & Co KG + Christian-Henkel-Str. 12 + Berlin 12349 + DE + +40-2E-71 (hex) Texas Instruments +402E71 (base 16) Texas Instruments + 12500 TI Blvd + Dallas TX 75243 + US + +70-76-DD (hex) OxyGuard Internation A/S +7076DD (base 16) OxyGuard Internation A/S + Farum Gydevej 64 + Farum DK-3520 + DK + +94-E9-EE (hex) Huawei Device Co., Ltd. +94E9EE (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +28-E3-4E (hex) HUAWEI TECHNOLOGIES CO.,LTD +28E34E (base 16) HUAWEI TECHNOLOGIES CO.,LTD + No.2 Xin Cheng Road, Room R6,Songshan Lake Technology Park + Dongguan 523808 + CN + +AC-12-03 (hex) Intel Corporate +AC1203 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +64-BC-58 (hex) Intel Corporate +64BC58 (base 16) Intel Corporate + Lot 8, Jalan Hi-Tech 2/3 + Kulim Kedah 09000 + MY + +D4-52-EE (hex) BSkyB Ltd +D452EE (base 16) BSkyB Ltd + 130 Kings Road + Brentwood Essex 08854 + GB + +E0-23-FF (hex) Fortinet, Inc. +E023FF (base 16) Fortinet, Inc. + 899 Kifer Road + Sunnyvale 94086 + US + +8C-59-DC (hex) ASR Microelectronics (Shanghai) Co., Ltd. +8C59DC (base 16) ASR Microelectronics (Shanghai) Co., Ltd. + Building 2, NO.399 Keyuan Road,Pudong District + Shanghai Shanghai 201210 + CN + +18-82-8C (hex) Arcadyan Corporation +18828C (base 16) Arcadyan Corporation + No.8, Sec.2, Guangfu Rd. + Hsinchu City Hsinchu 30071 + TW + +9C-F0-29 (hex) Integrated Device Technology (Malaysia) Sdn. Bhd. +9CF029 (base 16) Integrated Device Technology (Malaysia) Sdn. Bhd. + Phase 3, Bayan Lepas FIZ + Bayan Lepas Penang 11900 + MY + +28-56-C1 (hex) Harman/Becker Automotive Systems GmbH +2856C1 (base 16) Harman/Becker Automotive Systems GmbH + 15th Fl, 400 Atlantic Street + Stamford CT 06901 + US + +78-B8-D6 (hex) Zebra Technologies Inc. +78B8D6 (base 16) Zebra Technologies Inc. + ONE ZEBRA PLAZA + HOLTSVILLE NY 11742 + US + +BC-4A-56 (hex) Cisco Systems, Inc +BC4A56 (base 16) Cisco Systems, Inc + 80 West Tasman Drive + San Jose CA 94568 + US + +6C-61-F4 (hex) SFR +6C61F4 (base 16) SFR + 12 rue jean-philippe Rameau CS 80001 + La plaine saint denis FRANCE 93634 + FR + +F4-90-CB (hex) IEEE Registration Authority +F490CB (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +00-10-7F (hex) CRESTRON ELECTRONICS, INC. +00107F (base 16) CRESTRON ELECTRONICS, INC. + 15 Volvo Drive + Rockleigh NJ 07647 + US + +00-1B-85 (hex) MAN Energy Solutions +001B85 (base 16) MAN Energy Solutions + Teglholmsgade 41 + Copenhagen 2450 + DK + +58-49-3B (hex) Palo Alto Networks +58493B (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +00-1B-17 (hex) Palo Alto Networks +001B17 (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +58-59-C2 (hex) Extreme Networks, Inc. +5859C2 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +B8-2F-CB (hex) CMS Electracom +B82FCB (base 16) CMS Electracom + 24 Binney Road + Kings Park NSW 2148 + AU + +10-CE-45 (hex) Miromico AG +10CE45 (base 16) Miromico AG + Gallusstrasse 4 + Zurich Zurich CH-8006 + CH + +78-7D-53 (hex) Extreme Networks, Inc. +787D53 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +7C-95-B1 (hex) Extreme Networks, Inc. +7C95B1 (base 16) Extreme Networks, Inc. + 1011 McCarthy Blvd + Milpitas CA 95035 + US + +EC-68-81 (hex) Palo Alto Networks +EC6881 (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +78-6D-94 (hex) Palo Alto Networks +786D94 (base 16) Palo Alto Networks + 3000 Tannery Way + Santa Clara CA 95054 + US + +F8-AF-05 (hex) Huawei Device Co., Ltd. +F8AF05 (base 16) Huawei Device Co., Ltd. + No.2 of Xincheng Road, Songshan Lake Zone + Dongguan Guangdong 523808 + CN + +4C-FC-AA (hex) Tesla,Inc. +4CFCAA (base 16) Tesla,Inc. + 3500 Deer Creek Rd. + PALO ALTO CA 94304 + US diff --git a/hwdb.d/ma-medium.txt b/hwdb.d/ma-medium.txt new file mode 100644 index 00000000..b2cb19a8 --- /dev/null +++ b/hwdb.d/ma-medium.txt @@ -0,0 +1,17784 @@ +OUI Organization +OUI-28/MA-M Range Organization + Address + +74-1A-E0 (hex) Private +900000-9FFFFF (base 16) Private + +20-85-93 (hex) IOG Products LLC +B00000-BFFFFF (base 16) IOG Products LLC + 9737 LURLINE AVENUE + CHATSWORTH CA 91311 + US + +B0-C5-CA (hex) Private +F00000-FFFFFF (base 16) Private + +B0-1F-81 (hex) Private +F00000-FFFFFF (base 16) Private + +20-85-93 (hex) Shanghai Kenmyond Industrial Network Equipment Co.,Ltd +D00000-DFFFFF (base 16) Shanghai Kenmyond Industrial Network Equipment Co.,Ltd + 15/F,NO3003,Baoyang Road,Baoshan District + Shanghai Shanghai 201201 + CN + +20-85-93 (hex) H3 Industries, Inc. +A00000-AFFFFF (base 16) H3 Industries, Inc. + 12758 W Deep Canyon Dr. + Star ID 83669 + US + +24-15-10 (hex) Teknic, Inc. +B00000-BFFFFF (base 16) Teknic, Inc. + 115 Victor Heights Pkwy + 14564,Victor NY 14564 + US + +98-06-37 (hex) GS GLOBAL SECURITY INC +500000-5FFFFF (base 16) GS GLOBAL SECURITY INC + 30 Pennsylvania Ave, Unit 16, + CONCORD ONTARIO L4K 4A5 + CA + +B4-A2-EB (hex) Shanghai Shenou Communication Equipment Co., Ltd. +C00000-CFFFFF (base 16) Shanghai Shenou Communication Equipment Co., Ltd. + No. 1188, Kungang Road, Songjiang District + Shanghai Shanghai 200000 + CN + +24-15-10 (hex) GANZHOU DEHUIDA TECHNOLOGY CO., LTD +500000-5FFFFF (base 16) GANZHOU DEHUIDA TECHNOLOGY CO., LTD + Dehuida Science and Technology Park, Huoyanshan Road, Anyuan District + Ganzhou Jiangxi 342100 + CN + +24-15-10 (hex) Nile Global Inc +200000-2FFFFF (base 16) Nile Global Inc + 10915 Miramonte Rd + Cupertino CA 95014 + US + +24-15-10 (hex) Helen of Troy +D00000-DFFFFF (base 16) Helen of Troy + 1 Helen of Troy Plaza + El Paso TX 79912 + US + +98-06-37 (hex) Zoleo Inc. +000000-0FFFFF (base 16) Zoleo Inc. + 7a Taymall Avenue + Toronto ON M8Z 3Y8 + CA + +98-06-37 (hex) E. P. Schlumberger +100000-1FFFFF (base 16) E. P. Schlumberger + 1 rue Henri Becquerel + Clamart 92140 + FR + +B4-37-D1 (hex) Private +F00000-FFFFFF (base 16) Private + +44-D5-F2 (hex) SYS TEC electronic GmbH +A00000-AFFFFF (base 16) SYS TEC electronic GmbH + Am Windrad 2 + Heinsdorfergrund Sachsen D-08468 + DE + +44-D5-F2 (hex) Shenzhen Nation RFID Technology Co.,Ltd. +D00000-DFFFFF (base 16) Shenzhen Nation RFID Technology Co.,Ltd. + Room 816, Building A, Yuanzheng Venture Building, No. 19 Langshan Road, Xili Street, Nanshan District + ShenZhen Guangdong 518000 + CN + +D0-5F-64 (hex) TytoCare LTD. +800000-8FFFFF (base 16) TytoCare LTD. + 12 Haomanut st., 2nd floor + Netanya Merkaz 4250445 + IL + +D0-5F-64 (hex) Cyrus Technology GmbH +600000-6FFFFF (base 16) Cyrus Technology GmbH + Hergelsbendenstraße 49 + Aachen 52080 + DE + +D0-5F-64 (hex) Montblanc-Simplo GmbH +E00000-EFFFFF (base 16) Montblanc-Simplo GmbH + Hellgrundweg 100 + Hamburg Hamburg 22525 + DE + +44-D5-F2 (hex) Beam Communications Pty Ltd +600000-6FFFFF (base 16) Beam Communications Pty Ltd + U5/8 Anzed Court + Mulgrave Victoria 3170 + AU + +FC-A4-7A (hex) Innovative Advantage +700000-7FFFFF (base 16) Innovative Advantage + 15353 NE 90th Street + Redmond WA 98052 + US + +FC-A4-7A (hex) Shenzhen Elebao Technology Co., Ltd +A00000-AFFFFF (base 16) Shenzhen Elebao Technology Co., Ltd + F/6, Tower A, Zhihuichuangxin Center Bldg,Qianjin Road, XixiangTown, Bao’an District + shenzhen GUANGDONG 518126 + CN + +FC-A4-7A (hex) Shenzhen ALFEYE Technology CO.,Ltd +C00000-CFFFFF (base 16) Shenzhen ALFEYE Technology CO.,Ltd + Dingye Business Center321, Building A, Jingbei Industrial Park, No. 82, Intersection of Baoan Avenue and Xin'an 6th Road, Haiyu Community, Xin'an Street, Bao'an District + Shenzhen Guangdong 518000 + CN + +2C-16-BD (hex) LINGDONG TECHNOLOGY (BEIJING) CO. LTD +B00000-BFFFFF (base 16) LINGDONG TECHNOLOGY (BEIJING) CO. LTD + 2603-01, Floor 22, building 2, No.66 Zhongguancun East Road, Haidian District, Beijing + Beijing 100080 + CN + +2C-16-BD (hex) Beijing CHJ Automotive Co., Ltd. +C00000-CFFFFF (base 16) Beijing CHJ Automotive Co., Ltd. + Room 101, Building 1, No. 4 Hengxing Road, Gaoliying, Shunyi District + Beijing Beijing 101303 + CN + +B4-A2-EB (hex) Quantitec GmbH +B00000-BFFFFF (base 16) Quantitec GmbH + Elisabethenstr. 3a + Hofheim am Taunus Hessen 65719 + DE + +B4-A2-EB (hex) CURRENT WAYS, INC. +900000-9FFFFF (base 16) CURRENT WAYS, INC. + 10221 BUENA VISTA AVE + SANTEE CA 92071 + US + +B4-A2-EB (hex) Annapurna labs +500000-5FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +B4-A2-EB (hex) Hengkang(Hangzhou)Co.,Ltd +A00000-AFFFFF (base 16) Hengkang(Hangzhou)Co.,Ltd + Industrial Area,Huanghu Town,Yuhang District + Hangzhou Zhejiang 311118 + CN + +8C-59-3C (hex) Guralp Systems Limited +400000-4FFFFF (base 16) Guralp Systems Limited + 3 Midas House + Reading Berkshire RG7 8EA + GB + +8C-59-3C (hex) Beida Jade Bird Universal Fire Alarm Device CO.,LTD. +200000-2FFFFF (base 16) Beida Jade Bird Universal Fire Alarm Device CO.,LTD. + Jade Bird Building C, 207 Chengfu RD, Haidian District + Beijing Beijing 100871 + CN + +8C-59-3C (hex) OBO Pro.2 Inc. +700000-7FFFFF (base 16) OBO Pro.2 Inc. + 2148 Bering Dr. + San Jose CA 95131 + US + +8C-59-3C (hex) GENIS +900000-9FFFFF (base 16) GENIS + 1111, 11F RACREUM, 26 Wiryeseoil-ro + Seongnam-si Gyeonggi-do 13647 + KR + +D0-C8-57 (hex) Beijing Inspiry Technology Co., Ltd. +500000-5FFFFF (base 16) Beijing Inspiry Technology Co., Ltd. + Building No. 5, East Zone, No. 10, Xibeiwang East Road, Haidian District + Beijing Beijing 100092 + CN + +BC-97-40 (hex) Shanghai Laisi Information Technology Co.,Ltd +500000-5FFFFF (base 16) Shanghai Laisi Information Technology Co.,Ltd + 1001,21#,No.1158 Zhongxin RD,Songjiang district Shanghai + shanghai 201614 + CN + +F4-0E-11 (hex) Private +F00000-FFFFFF (base 16) Private + +D0-C8-57 (hex) E-T-A Elektrotechnische Apparate GmbH +E00000-EFFFFF (base 16) E-T-A Elektrotechnische Apparate GmbH + Industriestr. 2-8 + Altdorf 90518 + DE + +BC-97-40 (hex) Airfi Oy AB +700000-7FFFFF (base 16) Airfi Oy AB + Piilipuunkatu 11 + RAISIO 21200 + FI + +BC-97-40 (hex) comtac AG +100000-1FFFFF (base 16) comtac AG + Allenwindenstrasse 1 + Flurlingen 8247 + CH + +BC-97-40 (hex) Precision Galaxy Pvt. Ltd +300000-3FFFFF (base 16) Precision Galaxy Pvt. Ltd + 3rd Floor, No.22 Habibullah Road, T Nagar + CHENNAI,Tamil Nadu Tamilnadu 600017 + IN + +60-95-CE (hex) Xiamen Sigmastar Technology Ltd. +600000-6FFFFF (base 16) Xiamen Sigmastar Technology Ltd. + 15th Floor ,Unit A,Chuangxin Building, Software Park, Xiamen Torch Hi-Tech Industrial Development Zone, Xiamen,China + Xiamen Fujian 361005 + CN + +1C-82-59 (hex) KeyWest Networks, Inc +B00000-BFFFFF (base 16) KeyWest Networks, Inc + 2200 N Glassell St + Orange CA 92865 + US + +88-5D-90 (hex) Private +F00000-FFFFFF (base 16) Private + +60-95-CE (hex) Beijing Sinomedisite Bio-tech Co.,Ltd +B00000-BFFFFF (base 16) Beijing Sinomedisite Bio-tech Co.,Ltd + No.9 Kangding Street,Economic-Technological Development Area + Beijing Beijing 100176 + CN + +60-95-CE (hex) Siema Applications +000000-0FFFFF (base 16) Siema Applications + 35 rue Alfred Brinon + Villeurbanne 69100 + FR + +60-95-CE (hex) Trophy SAS +800000-8FFFFF (base 16) Trophy SAS + 4 rue F. Pelloutier + Croissy-Beaubourg 77435 + FR + +60-95-CE (hex) VNS Inc. +E00000-EFFFFF (base 16) VNS Inc. + 3F, No. 27, Lane 66, Ruiguang Rd. + Taipei Taiwan 11466 + TW + +84-8B-CD (hex) exodraft a/s +500000-5FFFFF (base 16) exodraft a/s + C. F. Teiegens Boulevard 41 + Odense SØ 5220 + DK + +1C-82-59 (hex) 3xLOGIC Inc. +100000-1FFFFF (base 16) 3xLOGIC Inc. + 9882 E. 121st Street + Fishers IN 46037 + US + +84-8B-CD (hex) CCX Technologies Inc. +200000-2FFFFF (base 16) CCX Technologies Inc. + 408 - 11 Rosemount Ave. + Ottawa Ontario K1Y 4R8 + CA + +84-8B-CD (hex) TWTG R&D B.V. +600000-6FFFFF (base 16) TWTG R&D B.V. + Schaardijk 386 + Capelle aan den IJssel 2909LA + NL + +B0-FD-0B (hex) DMAC Security LLC +300000-3FFFFF (base 16) DMAC Security LLC + 833 Shotgun Road + Sunrise FL 33326 + US + +B0-FD-0B (hex) eSenseLab Ltd. +800000-8FFFFF (base 16) eSenseLab Ltd. + 1 Chervena stena Str., Office 1 + Sofia Sofia-grad 1421 + BG + +B0-FD-0B (hex) TEMCO JAPAN CO., LTD. +A00000-AFFFFF (base 16) TEMCO JAPAN CO., LTD. + 2-21-4 HONAN + SUGINAMI KU Tokyo-to 168-0062 + JP + +C8-2C-2B (hex) Grav I.T. +600000-6FFFFF (base 16) Grav I.T. + 601 1st Ave NW + Gravette AR 72736 + US + +C8-2C-2B (hex) Galgus +100000-1FFFFF (base 16) Galgus + Italica 1, 1st floor + Camas Seville 41900 + ES + +C8-2C-2B (hex) Kunshan SVL Electric Co.,Ltd +B00000-BFFFFF (base 16) Kunshan SVL Electric Co.,Ltd + No. 568, JuJin Road, Zhangpu Town + SuZhou 215300 + CN + +C8-2C-2B (hex) Merpa Bilgi Islem Ltd.Sti +700000-7FFFFF (base 16) Merpa Bilgi Islem Ltd.Sti + Oztekin CD NO:26 + Istanbul Bayrampasa 34040 + TR + +E4-1E-0A (hex) SAGE Glass +800000-8FFFFF (base 16) SAGE Glass + Two Sage Way + Faribault MN 55021 + US + +C8-2C-2B (hex) UBITRON Co.,LTD +D00000-DFFFFF (base 16) UBITRON Co.,LTD + Sinbuk-Ro + Chuncheon City Gangwon 24206 + KR + +C8-63-14 (hex) Autonics Co., Ltd. +100000-1FFFFF (base 16) Autonics Co., Ltd. + 4-14-26, Shimo-Muneoka + Shiki Saitama 3530003 + JP + +C8-63-14 (hex) Thinci, Inc. +800000-8FFFFF (base 16) Thinci, Inc. + 2105 S. Bascom Avenue, Suite 318 + Campbell CA 95008 + US + +C8-63-14 (hex) Maxcom S.A. +900000-9FFFFF (base 16) Maxcom S.A. + Towarowa 23A + Tychy 43-100 + PL + +FC-D2-B6 (hex) Bee Smart(Changzhou) Information Technology Co., Ltd +D00000-DFFFFF (base 16) Bee Smart(Changzhou) Information Technology Co., Ltd + Changwu Middle Road + Changzhou Jiangsu 213100 + CN + +74-5B-C5 (hex) CELYSS SAS +D00000-DFFFFF (base 16) CELYSS SAS + 7 allee des ginkgos + Bron 69500 + FR + +FC-D2-B6 (hex) Coet Costruzioni Elettrotecniche +300000-3FFFFF (base 16) Coet Costruzioni Elettrotecniche + Via Civesio 12 + San Donato Milanese Mi 20097 + IT + +A8-3F-A1 (hex) MEDCAPTAIN MEDICAL TECHNOLOGY CO., LTD. +200000-2FFFFF (base 16) MEDCAPTAIN MEDICAL TECHNOLOGY CO., LTD. + 12th Floor, Baiwang Research Building, No.5158 Shahe West Road, Xili, Nanshan + Shenzhen 518055 + CN + +74-5B-C5 (hex) Fournie Grospaud Energie SASU +A00000-AFFFFF (base 16) Fournie Grospaud Energie SASU + 220 rue du chene vert + LABEGE 31670 + FR + +74-5B-C5 (hex) ComNot +C00000-CFFFFF (base 16) ComNot + 15 chemin des Hirondelles + DARDILLY 69570 + FR + +4C-BC-98 (hex) Wonder Workshop +E00000-EFFFFF (base 16) Wonder Workshop + 1500 Fashion Island, Suite #200 + San Mateo CA 94404 + US + +4C-BC-98 (hex) JSC NIC +100000-1FFFFF (base 16) JSC NIC + Nauchny proezd, 6 + Moscow 117246 + RU + +E4-4C-C7 (hex) EPS Bio +C00000-CFFFFF (base 16) EPS Bio + No. 8, R&D 3rd Rd, Science-Based Industrial Park + Hsinchu Taiwan 30077 + TW + +E4-4C-C7 (hex) Doowon Electronics & Telecom Co.,Ltd +200000-2FFFFF (base 16) Doowon Electronics & Telecom Co.,Ltd + IT 301-408, Ssangyong 3Cha, Bucheon Technopark, 397, Seokcheon-ro, Ojeong-gu + Bucheon-si Gyeonggi-do 14449 + KR + +E0-5A-9F (hex) Fibrain +600000-6FFFFF (base 16) Fibrain + Zaczernie 190F + Zaczernie Subcarpathia 36-062 + PL + +F8-02-78 (hex) Private +F00000-FFFFFF (base 16) Private + +4C-BC-98 (hex) Shenzhen Cogitation Technology Co.,Ltd. +A00000-AFFFFF (base 16) Shenzhen Cogitation Technology Co.,Ltd. + NO.509 LangShan Building,Nanshan Yungu Innovation Industrial Park,No.1183 Taoyuan Street,Nanshen District + Shenzhen Guangdong 518000 + CN + +E0-5A-9F (hex) Gemalto Document Readers +900000-9FFFFF (base 16) Gemalto Document Readers + 3300 Acorn Street + Williamsburg VA 23188 + US + +D8-86-0B (hex) Grünbeck Wasseraufbereitung GmbH +700000-7FFFFF (base 16) Grünbeck Wasseraufbereitung GmbH + Josef-Grünbeck-Str. 1 + Hoechstaedt a.d. Donau 89420 + DE + +D8-86-0B (hex) Inspur Group Co., Ltd. +000000-0FFFFF (base 16) Inspur Group Co., Ltd. + No.1036 Langchao Rd. + Jinan Shandong 250101 + CN + +D8-86-0B (hex) CAMTRACE +500000-5FFFFF (base 16) CAMTRACE + 26 BIS BOULEVARD HENRI SELLIER + SURESNES 92150 + FR + +38-B1-9E (hex) System Q Ltd +B00000-BFFFFF (base 16) System Q Ltd + Turnoaks Business Park, Hasland + Chesterfield Derbyshire S40 2WB + GB + +CC-D3-9D (hex) Ethernity Networks +D00000-DFFFFF (base 16) Ethernity Networks + Ha-Melacha 13 + Lod Israel 7152025 + IL + +CC-D3-9D (hex) SHENZHEN ROYOLE TECHNOLOGIES CO., LTD. +500000-5FFFFF (base 16) SHENZHEN ROYOLE TECHNOLOGIES CO., LTD. + Building #43, Dayun Software Town, No.8288 Longgang Road, Henggang Street, Longgang District, + Shenzhen Guangdong 518000 + CN + +D4-25-CC (hex) Barobo, Inc. +400000-4FFFFF (base 16) Barobo, Inc. + 221 G Street, #204 + Davis CA 95616 + US + +9C-69-B4 (hex) BEIJING PICOHOOD TECHNOLOGY CO.,LTD +A00000-AFFFFF (base 16) BEIJING PICOHOOD TECHNOLOGY CO.,LTD + Room 504A, Building E, Lize Middle Yard, Wangjing Science and Technology Venture Park, Chaoyang District + BEIJING BEIJING 100102 + CN + +9C-69-B4 (hex) Elesta GmbH +500000-5FFFFF (base 16) Elesta GmbH + Heuteilstrasse 18 + Bad Ragaz St. Gallen 7310 + CH + +9C-69-B4 (hex) Toughdog Security Systems +B00000-BFFFFF (base 16) Toughdog Security Systems + 1317 E Hackberry Ave + McAllen TX 78501 + US + +6C-DF-FB (hex) Chongqing Baoli Yota Technologies Limited +100000-1FFFFF (base 16) Chongqing Baoli Yota Technologies Limited + No.2,1 Floor,Kelly Building,No.115 Xingtong Avenue,Guilin Street office, Tongnan District + Chongqing Chongqing 402660 + CN + +A4-4F-29 (hex) Private +F00000-FFFFFF (base 16) Private + +4C-91-7A (hex) Chongqing Unisinsight Technology Co.,Ltd. +200000-2FFFFF (base 16) Chongqing Unisinsight Technology Co.,Ltd. + No.117-386, Yunhan Road + Beibei District Chongqing 400714 + CN + +4C-91-7A (hex) Shenzhen bankledger Technology Co, Ltd +D00000-DFFFFF (base 16) Shenzhen bankledger Technology Co, Ltd + Room 802, Tower A, Yuanzheng Venture Building, No. 19 Langshan Road, Nanshan District + Shenzhen 518000 + CN + +6C-DF-FB (hex) Beijing Fimi Technology Co., Ltd. +E00000-EFFFFF (base 16) Beijing Fimi Technology Co., Ltd. + Room 348, 3F, Complex building A1, Yongtai Park, Qinghe Street, Haidian District, Beijing + Beijing 100000 + CN + +6C-DF-FB (hex) Beijing Ainemo Co Ltd +300000-3FFFFF (base 16) Beijing Ainemo Co Ltd + Building K1, NO. 86 Beiyuan North road, Chaoyang district, Beijing China + Beijing Beijing 100012 + CN + +4C-91-7A (hex) Shenzhen Dangs Science & Technology CO.,LTD +000000-0FFFFF (base 16) Shenzhen Dangs Science & Technology CO.,LTD + 7D, 7th Floor, HSAE Building, Nanshan District, + Shenzhen GuangDong 518000 + CN + +7C-BC-84 (hex) Nanning auto digital technology co.,LTD +500000-5FFFFF (base 16) Nanning auto digital technology co.,LTD + 3/f, no.6 guichun road, qingxiu district + Nanning Guangxi 530021 + CN + +98-F9-C7 (hex) Koala Technology CO., LTD. +900000-9FFFFF (base 16) Koala Technology CO., LTD. + Room 2004, Building A3, Dayuan International Center, High Tech Zone + Chengdu Sichuan 610000 + CN + +6C-DF-FB (hex) Hashtrend AG +700000-7FFFFF (base 16) Hashtrend AG + Bahnhofstrasse + Zug 6300 + CH + +98-F9-C7 (hex) GoodBox +600000-6FFFFF (base 16) GoodBox + Ground Floor, Optimum House + Clippers Quay Salford Quays M50 3XP + GB + +98-F9-C7 (hex) Tonycore Technology Co.,Ltd. +500000-5FFFFF (base 16) Tonycore Technology Co.,Ltd. + 2/F,Building A,Dingxin Technology Park,Honglang North 2nd Road,Xin’an Street,Bao’an District, + Shenzhen Guangdong 518000 + CN + +98-F9-C7 (hex) hangzhou soar security technologies limited liability company +D00000-DFFFFF (base 16) hangzhou soar security technologies limited liability company + Zhebao Ideal Xiangyuan Creative industrial Park + Hangzhou Zhejiang Zhejiang + CN + +2C-48-35 (hex) IROOTECH TECHNOLOGY CO.,LTD +E00000-EFFFFF (base 16) IROOTECH TECHNOLOGY CO.,LTD + Room 606, Floor 6, Building 5, Eastern Yard 10, Xibeiwang East Road + Beijing 100092 + CN + +0C-FE-5D (hex) NEWGREEN TECH CO., LTD. +E00000-EFFFFF (base 16) NEWGREEN TECH CO., LTD. + 2F., No.200, Sec. 2, Gaotie N. Rd., Dayuan Dist., Taoyuan City 337, Taiwan (R.O.C.) + Taoyuan City 33743 + TW + +0C-FE-5D (hex) Bepal Technology Co.,Ltd. +C00000-CFFFFF (base 16) Bepal Technology Co.,Ltd. + Xihu Qu, Tianmushan Road, Qianjiang Xixi Xinzuo + HangZhou ZheJiang 310000 + CN + +3C-39-E7 (hex) Private +F00000-FFFFFF (base 16) Private + +0C-FE-5D (hex) Chengdu Ledong Information & Technology Co., Ltd. +000000-0FFFFF (base 16) Chengdu Ledong Information & Technology Co., Ltd. + D7-13F, Chengdu Tianfu Software Park, No. 599 Shijicheng South street, Gaoxin District, Chengdu, China + Chengdu sichaun 610041 + CN + +6C-5C-3D (hex) GUANGZHOU GUANGRI ELEVATOR INDUSTRY CO.,LTD +800000-8FFFFF (base 16) GUANGZHOU GUANGRI ELEVATOR INDUSTRY CO.,LTD + 636 South of Guomao Road,Shilou County,Panyu District + Guangzhou Guangdong 511047 + CN + +6C-5C-3D (hex) ShenZhen Hugsun Technology Co.,Ltd. +000000-0FFFFF (base 16) ShenZhen Hugsun Technology Co.,Ltd. + 413~415 Room, 4/F, No.6 Bldg., TongFuYu Industrial Park, Dalang Street, 518109, Longhua New District, + ShengZhen GuangDong 518109 + CN + +6C-5C-3D (hex) Unitel Engineering +500000-5FFFFF (base 16) Unitel Engineering + 2-я Кабельная д.2 стр.1 + Москва Россия 111024 + RU + +A8-3F-A1 (hex) BEGLEC +600000-6FFFFF (base 16) BEGLEC + hofveld 2c + Groot-Bijgaarden 1702 + BE + +1C-FD-08 (hex) ShenZhen DeLippo Technology Co., LTD +800000-8FFFFF (base 16) ShenZhen DeLippo Technology Co., LTD + District A of Fifth Floor,Building E,Guancheng Low Carbon Industrial Park, Shangcun Community,Gongming Street,Guangming District + Shenzhen 518106 + CN + +A8-3F-A1 (hex) Neos Ventures Limited +800000-8FFFFF (base 16) Neos Ventures Limited + 47 Bermondsey Street + London SE1 3XT + GB + +A8-3F-A1 (hex) GTDevice LLC +100000-1FFFFF (base 16) GTDevice LLC + PO BOX 86339 + Portland OR 97286 + US + +E8-18-63 (hex) Private +F00000-FFFFFF (base 16) Private + +3C-6A-2C (hex) TP Radio +800000-8FFFFF (base 16) TP Radio + Agenavej 37 + Greve . 2670 + DK + +3C-6A-2C (hex) Xiamen Smarttek CO., Ltd. +D00000-DFFFFF (base 16) Xiamen Smarttek CO., Ltd. + 5F, B Area, Chuangxin Plaza, SoftPark I, Siming District + Xiamen Fujian 361005 + CN + +3C-6A-2C (hex) Eltov System +C00000-CFFFFF (base 16) Eltov System + #1309 Gyeonggi Venture Yeonsung Univ Center. 111, Anyang-ro, Manan-gu, + Anyang-si 14093 + KR + +3C-6A-2C (hex) Metro +A00000-AFFFFF (base 16) Metro + 189 rue de la Jonchere + Boege 74420 + FR + +3C-6A-2C (hex) Olibra LLC +100000-1FFFFF (base 16) Olibra LLC + 45 legin dr + creskill NJ 07626 + US + +3C-6A-2C (hex) XI'AN YEP TELECOM TECHNOLOGY CO.,LTD +400000-4FFFFF (base 16) XI'AN YEP TELECOM TECHNOLOGY CO.,LTD + 5F,Building C,CLP Park,No.211, Tiangu 8 Road, High-tech Zone, Xi' an, Shanxi Province, China + Xi’an Shanxi 710001 + CN + +A4-ED-43 (hex) Wuxi Junction Infomation Technology Incorporated Company +700000-7FFFFF (base 16) Wuxi Junction Infomation Technology Incorporated Company + ROOM919,NO.401 XINGYUANBEILU ROAD, LIANGXI DISTRIC,WUXI CITY,JIANGSU PROVINCE + WuXi Jiangsu 214000 + CN + +30-0A-60 (hex) Ampetronic Ltd +A00000-AFFFFF (base 16) Ampetronic Ltd + Unit 2 Trentside Business Village, Farndon Road + Newark Nottinghamshire NG24 4XB + GB + +30-0A-60 (hex) WINTEK System Co., Ltd +900000-9FFFFF (base 16) WINTEK System Co., Ltd + Wintek Venture Bldg., 511, Poil-Dong + Uiwang-City Gyunggi-Do 16013 + KR + +30-0A-60 (hex) Giax GmbH +B00000-BFFFFF (base 16) Giax GmbH + Am Weichselgarten 7 + Erlangen 91058 + DE + +30-0A-60 (hex) Thermo Process Instruments, LP +C00000-CFFFFF (base 16) Thermo Process Instruments, LP + 27 Forge Parkway + Frankllin MA 02038 + US + +A0-28-33 (hex) Xiamen Caimore Communication Technology Co.,Ltd. +600000-6FFFFF (base 16) Xiamen Caimore Communication Technology Co.,Ltd. + #2 of 302 Unit, 23# Wanghai Road, Xiamen Software Park II + Xiamen Fujian 361009 + CN + +A0-28-33 (hex) GERSYS GmbH +000000-0FFFFF (base 16) GERSYS GmbH + Hans-Urmiller-Ring 12A + Wolfratshausen 82515 + DE + +A4-ED-43 (hex) Brand New Brand Nordic AB +D00000-DFFFFF (base 16) Brand New Brand Nordic AB + Nohrstedts väg 5 + Söderbärke 77794 + SE + +A4-ED-43 (hex) Linseis Messgeraete GmbH +800000-8FFFFF (base 16) Linseis Messgeraete GmbH + Vielitzer Str. 43 + Selb 95100 + DE + +A0-28-33 (hex) Audix +D00000-DFFFFF (base 16) Audix + 9400 SW Barber St. + Wilsonville OR 97070 + US + +A0-28-33 (hex) Shanghai Nohmi Secom Fire Protection Equipment Co.,Ltd. +200000-2FFFFF (base 16) Shanghai Nohmi Secom Fire Protection Equipment Co.,Ltd. + No.98,Lane 1971,(s)Lianhua Road,Minhang Area + Shanghai Shanghai 201108 + CN + +84-89-EC (hex) Shenzhen Intellifusion Technologies Co., Ltd. +E00000-EFFFFF (base 16) Shenzhen Intellifusion Technologies Co., Ltd. + Suite701, Science Museum, Shenzhen City + Shenzhen Guangdong 518000 + CN + +00-55-DA (hex) Victorsure Limited +E00000-EFFFFF (base 16) Victorsure Limited + 15/F Cambridge house, 26-28 Cameron Road + Hong Kong Hong Kong Hong Kong + HK + +84-89-EC (hex) Research Electronics International, LLC. +100000-1FFFFF (base 16) Research Electronics International, LLC. + 455 Secuity Drive + Cookeville TN 38506 + US + +30-09-F9 (hex) OOO Microlink-Svyaz +300000-3FFFFF (base 16) OOO Microlink-Svyaz + 1st veshnjakovsky proezd 7 + moscow moscow 109456 + RU + +84-89-EC (hex) Arts Digital Technology (HK) Ltd. +800000-8FFFFF (base 16) Arts Digital Technology (HK) Ltd. + 1704, 17/F, Fo Tan Industrial Centre, 26-28 Au Pui Wan Street, Fo Tan, Hong Kong + Hong Kong Nil + HK + +84-89-EC (hex) Vayyar Imaging Ltd. +400000-4FFFFF (base 16) Vayyar Imaging Ltd. + 3 Avraham Giron St + Yehud 5621717 + IL + +84-89-EC (hex) POCT biotechnology +600000-6FFFFF (base 16) POCT biotechnology + 6F, No. 185, GangQian Rd., Neihu dist., + Taipei 11494 + TW + +30-09-F9 (hex) Technology for Humankind +D00000-DFFFFF (base 16) Technology for Humankind + 3913 N. Rushwood St. + Wichita KS 67226 + US + +C0-83-59 (hex) SHANGHAI CHARMHOPE INFORMATION TECHNOLOGY CO.,LTD. +A00000-AFFFFF (base 16) SHANGHAI CHARMHOPE INFORMATION TECHNOLOGY CO.,LTD. + Building 11,No.230,Chuanhong Rd,Pudong Distrist + Shanghai Shanghai 201202 + CN + +9C-F6-DD (hex) Ithor IT Co.,Ltd. +100000-1FFFFF (base 16) Ithor IT Co.,Ltd. + No. 501, Building I, ZTE Park, Hi-Tech Industrial Zone + XI'AN ShanXi 710065 + CN + +9C-F6-DD (hex) Guangzhou LANGO Electronics Technology Co., Ltd. +B00000-BFFFFF (base 16) Guangzhou LANGO Electronics Technology Co., Ltd. + 136#, Gaopu Road, Tianhe District + Guangzhou Guangdong 510663 + CN + +9C-F6-DD (hex) CAMA(Luoyang)Electronics Co.,Ltd +900000-9FFFFF (base 16) CAMA(Luoyang)Electronics Co.,Ltd + Luoyang High-tech District, Chuncheng Road 16th. + Luoyang Henan 471003 + CN + +C0-83-59 (hex) Suzhou Siheng Science and Technology Ltd. +B00000-BFFFFF (base 16) Suzhou Siheng Science and Technology Ltd. + 8 floor of Jincheng star, Yunhe road NO.150, gaoxin Zone, Suzhou + Suzhou 215000 + CN + +C0-83-59 (hex) ista International GmbH +800000-8FFFFF (base 16) ista International GmbH + Luxemburger Strasse 1 + Essen NRW 45131 + DE + +C0-83-59 (hex) Fuzhou Fdlinker Technology Co.,LTD +700000-7FFFFF (base 16) Fuzhou Fdlinker Technology Co.,LTD + 28th floor, Building 1, area F, Fuzhou software park, 89 Ruanjian Avenue + Fuzhou Fujian 350001 + CN + +04-C3-E6 (hex) Teleepoch Ltd +E00000-EFFFFF (base 16) Teleepoch Ltd + No.13 Langshan Rd,HiTech Park,Nanshan District + Shenzhen Guangdong 518000 + CN + +04-C3-E6 (hex) Sealed Unit Parts Co., Inc. +A00000-AFFFFF (base 16) Sealed Unit Parts Co., Inc. + 2230 Landmark Place + ALLENWOOD NJ 08720 + US + +C0-83-59 (hex) PCH Engineering A/S +300000-3FFFFF (base 16) PCH Engineering A/S + Ved Klaedebo 4 + Horsholm 2970 + DK + +B4-4B-D6 (hex) DongYoung media +B00000-BFFFFF (base 16) DongYoung media + #18, Dangjeong-Ro, Gunpo-Si, + Gyeonggi-Do, 15849 + KR + +B4-4B-D6 (hex) Perspicace Intellegince Technology +600000-6FFFFF (base 16) Perspicace Intellegince Technology + 4F, 1326#, West YanAn road, Shanghai, P.R.China + ShangHai ShangHai 200052 + CN + +3C-42-7E (hex) Shenzhen VETAS Communication Technology Co , Ltd. +300000-3FFFFF (base 16) Shenzhen VETAS Communication Technology Co , Ltd. + Room 1301-1303,West Wing,Skyworth Semiconductor Design Building,No.18,Gaoxin South 4th road, Nanshan District + ShenZhen Guangdong 518063 + CN + +3C-42-7E (hex) Privacy Labs +C00000-CFFFFF (base 16) Privacy Labs + 10400 NE 4th Street, 7th Floor + Bellevue WA 98004 + US + +98-6D-35 (hex) Private +900000-9FFFFF (base 16) Private + +3C-42-7E (hex) Starloop Tech Co., Ltd. +200000-2FFFFF (base 16) Starloop Tech Co., Ltd. + #643, Meinian Plaza A + Chengdu 610000 + CN + +3C-42-7E (hex) Geoplan Korea +500000-5FFFFF (base 16) Geoplan Korea + Simin-ro 327-7 DaeMyung Bldg #614 + AnYang 15044 + KR + +B4-4B-D6 (hex) Huizhou Sunoda Technology Co. Ltd +300000-3FFFFF (base 16) Huizhou Sunoda Technology Co. Ltd + NO.4 XING JU WEST ROAD,DONG XING DISTRICT,ZHONG KAI DONG JIANG HIGH TECHNOLOGY INDUSTRIAL PARK, + HUI ZHOU guangdong 516000 + CN + +B4-4B-D6 (hex) Shenzhen Hi-Net Technology Co., Ltd. +400000-4FFFFF (base 16) Shenzhen Hi-Net Technology Co., Ltd. + 3F, 4Building, Anda Industrial Zone, Chongqing Road, Fuyong Town, Baoan District + ShenZhen GuangDong 518103 + CN + +B4-4B-D6 (hex) Taizhou convergence Information technology Co.,LTD +700000-7FFFFF (base 16) Taizhou convergence Information technology Co.,LTD + Room 1006,general chamber of commerce,159 henghu road + wenling zhejiang 317515 + CN + +B4-4B-D6 (hex) G4S Monitoring Technologies Ltd +000000-0FFFFF (base 16) G4S Monitoring Technologies Ltd + 3 Centurion Court, Meridian East + Leicester Leicestershire LE19 1TP + GB + +D0-D9-4F (hex) Private +700000-7FFFFF (base 16) Private + +D4-7C-44 (hex) SHENZHEN ANYSEC TECHNOLOGY CO. LTD +E00000-EFFFFF (base 16) SHENZHEN ANYSEC TECHNOLOGY CO. LTD + 601, 1 BUILDING,MeiLin Dolly Industrial Zone,Futian District + SHENZHEN GuangDong 518000 + CN + +D4-7C-44 (hex) Pongee Industries Co., Ltd. +700000-7FFFFF (base 16) Pongee Industries Co., Ltd. + 5F., No.738, Chung-Cheng Road, + Chung-Ho District, New Taipei City, 23511 + TW + +A0-19-B2 (hex) ARIMA Communications Corp. +700000-7FFFFF (base 16) ARIMA Communications Corp. + 6F.,No.866,Zhongzheng Rd.,Zhonghe Dist., + New Taipei City Taiwan 23586 + TW + +A0-19-B2 (hex) GfG mbH +600000-6FFFFF (base 16) GfG mbH + Kloennestrasse 99 + Dortmund 44143 + DE + +1C-A0-D3 (hex) Exicom Tele-Systems Ltd. +E00000-EFFFFF (base 16) Exicom Tele-Systems Ltd. + Plot Number 77A, IFFCO Road, Sector 18 + Gurgaon Haryana 122015 + IN + +A0-19-B2 (hex) HangZhou iMagic Technology Co., Ltd +B00000-BFFFFF (base 16) HangZhou iMagic Technology Co., Ltd + Block F, 11th Floor, Building A, Tiantang Software Park, 3# Xidoumen Road, + Hangzhou Zhejiang 310012 + CN + +A0-19-B2 (hex) RYD Electronic Technology Co.,Ltd. +D00000-DFFFFF (base 16) RYD Electronic Technology Co.,Ltd. + Room1602,No68 Taidong Road,Siming District,Xiamen City + Xiamen FuJian 361000 + CN + +D4-7C-44 (hex) STRIVE ORTHOPEDICS INC +C00000-CFFFFF (base 16) STRIVE ORTHOPEDICS INC + 505 PARK AVE FL 17 + NEW YORK NY 10022 + US + +D4-7C-44 (hex) OPTiM Corporation +B00000-BFFFFF (base 16) OPTiM Corporation + 1 Honjo-machi + Saga 840-8502 + JP + +34-04-9E (hex) Private +C00000-CFFFFF (base 16) Private + +2C-48-35 (hex) Phasor Solutions Ltd +D00000-DFFFFF (base 16) Phasor Solutions Ltd + The Record Hall, 16 Baldwin Gardens + London EC1N 7RJ + GB + +2C-48-35 (hex) FAST +700000-7FFFFF (base 16) FAST + 4740 44th Ave SW Suite #201 + Seattle WA 98116 + US + +3C-24-F0 (hex) Swissdotnet SA +700000-7FFFFF (base 16) Swissdotnet SA + Route Saint-Nicolas-de-Flüe 2 + Fribourg 1700 + CH + +0C-73-EB (hex) U-PASS.CO.,LTD +400000-4FFFFF (base 16) U-PASS.CO.,LTD + HANEULMAEUL-RO + GYEONGGI-DO GOYANG-SI,ILSANDONG-GU 410315 + KR + +48-0B-B2 (hex) Microprogram Information Co., Ltd +900000-9FFFFF (base 16) Microprogram Information Co., Ltd + 14F., No.262, Sec. 2, Henan Rd., Xitun Dist. + Taichung 407 + TW + +48-0B-B2 (hex) Hangzhou Freely Communication Co., Ltd. +400000-4FFFFF (base 16) Hangzhou Freely Communication Co., Ltd. + No. 90 Wensan, Hangzhou, Zhejiang + Hangzhou Zhejiang 310012 + CN + +48-0B-B2 (hex) BravoCom(xiamen)TechCo.Ltd +800000-8FFFFF (base 16) BravoCom(xiamen)TechCo.Ltd + Room 506, Chengye Building lnnovation park Xiamen Torch Hi-Tech Zone Xiamen fujian P.R.China + Xiamen fujian 361000 + CN + +48-0B-B2 (hex) SHENZHEN TOPWELL TECHNOLOGY CO..LTD +C00000-CFFFFF (base 16) SHENZHEN TOPWELL TECHNOLOGY CO..LTD + 5th Floor, Building 10 Changyuan New Material + Port,No.2,Middle Road 1, High Tech Park, Nanshan District,Shenzhen 518001 + CN + +88-5F-E8 (hex) Changsha Xiangji-Haidun Technology Co., Ltd +800000-8FFFFF (base 16) Changsha Xiangji-Haidun Technology Co., Ltd + NO.5 Dongsan Rd, Changsha Economic & Technical Zone + Changsha HuNan 410100 + CN + +30-1F-9A (hex) Smart Component Technologies LTD +B00000-BFFFFF (base 16) Smart Component Technologies LTD + Cooper Buildings, Arundel Street + Sheffield South Yorkshire S1 2NS + GB + +30-1F-9A (hex) CHISON Medical Technologies Co., Ltd. +200000-2FFFFF (base 16) CHISON Medical Technologies Co., Ltd. + No.9, Xinhuihuan Road, Xinwu District, Wuxi, Jiangsu, China 214028 + WUXI JIANGSU 214028 + CN + +88-5F-E8 (hex) Shenzhen ORVIBO Technology Co., Ltd +B00000-BFFFFF (base 16) Shenzhen ORVIBO Technology Co., Ltd + 7F, A7 Zhiyuan, No.1001, Xueyuan AV., Nanshan district, Shenzhen,518055,PRC + Shenzhen guangdong 518000 + CN + +88-5F-E8 (hex) Apoidea Technology Co., Ltd. +100000-1FFFFF (base 16) Apoidea Technology Co., Ltd. + No. 111, Boyun Road + Shanghai 201203 + CN + +F0-41-C8 (hex) ATN Media Group FZ LLC +D00000-DFFFFF (base 16) ATN Media Group FZ LLC + Business Bay-alabrj st Business Towar By Damac.office-807 + Dubai 25051 + AE + +F0-41-C8 (hex) Telstra +A00000-AFFFFF (base 16) Telstra + 231 Elisabeth St + SYDNEY NSW 2000 + AU + +88-A9-A7 (hex) Shenzhenshi kechuangzhixian technology Co.LTD +000000-0FFFFF (base 16) Shenzhenshi kechuangzhixian technology Co.LTD + Room 14G,14th Floor, Langshi Building , keji South Road 12 , High-tech Industrial Park , Nanshan District + Shenzhen 518000 + CN + +88-A9-A7 (hex) Volterman Inc. +500000-5FFFFF (base 16) Volterman Inc. + Suite B2, Sunset Lake Road + Newark DE 19702 + US + +88-A9-A7 (hex) AVLINK INDUSTRIAL CO., LTD +D00000-DFFFFF (base 16) AVLINK INDUSTRIAL CO., LTD + 7/F, A1 Bldg, 1st Shuichanjingwan Industrial Park, Nanchang Village, Gushu, Bao'an Dist + Shenzhen Guangdong 518126 + CN + +F0-41-C8 (hex) DongGuan Siyoto Electronics Co., Ltd +100000-1FFFFF (base 16) DongGuan Siyoto Electronics Co., Ltd + Hecheng Industrial District, QiaoTou Town + DongGuan City Guangdong 523520 + CN + +F0-41-C8 (hex) Candelic Limited +400000-4FFFFF (base 16) Candelic Limited + Unit 312, 3/F Solo Workshop, 131-132 Cannaught Road West + Hong Kong 111111 + HK + +A4-DA-22 (hex) Shen Zhen City YaKun Electronics Co., Ltd +D00000-DFFFFF (base 16) Shen Zhen City YaKun Electronics Co., Ltd + SOUTHERN BUILDING 5388 Shang Bu Industrial Zone Huaqiang North Road Futian District + shen zhen city Guang Dong Province 518000 + CN + +A4-DA-22 (hex) Klashwerks Inc. +B00000-BFFFFF (base 16) Klashwerks Inc. + 441 Maclaren Street, Suite 408 + Ottawa ON K2P2H3 + CA + +A4-DA-22 (hex) Hydro Electronic Devices, Inc. +700000-7FFFFF (base 16) Hydro Electronic Devices, Inc. + 2120 Constitution Ave + Hartford WI 53027 + US + +A4-DA-22 (hex) DURATECH Enterprise,LLC +300000-3FFFFF (base 16) DURATECH Enterprise,LLC + NO.1013,184,Gasan digital 2-ro,Geumcheon-gu,Seoul + Seoul 08501 + KR + +A4-DA-22 (hex) Abetechs GmbH +A00000-AFFFFF (base 16) Abetechs GmbH + Niermannsweg 11 + Erkrath North Rhine-Westphalia 40699 + DE + +A4-DA-22 (hex) LORIOT AG +400000-4FFFFF (base 16) LORIOT AG + Zuercherstrasse 68 + Thalwil Zürich 8800 + CH + +A4-DA-22 (hex) T2T System +100000-1FFFFF (base 16) T2T System + #316, HYUNDAI Knowledge Industry Center, 70, Dusan-ro + Geumcheon-gu Seoul 08584 + KR + +A4-DA-22 (hex) Original Products Pvt. Ltd. +500000-5FFFFF (base 16) Original Products Pvt. Ltd. + B-19, Shiv Park, School Road, Khanpur + New Delhi New Delhi 110062 + IN + +DC-E5-33 (hex) Tintel Hongkong Co.Ltd +B00000-BFFFFF (base 16) Tintel Hongkong Co.Ltd + FLAT C,23/F,LUCKY PLAZA,315-321 LOCKHART ROAD,WANCHAI,HONGKONG + HONGKONG GUANG DONG PROVINCE 999077 + HK + +DC-E5-33 (hex) JB-Lighting Lichtanlagen GmbH +800000-8FFFFF (base 16) JB-Lighting Lichtanlagen GmbH + Sallersteig 15 + 89134 89134 + DE + +C4-FF-BC (hex) GSM Innovations Pty Ltd +900000-9FFFFF (base 16) GSM Innovations Pty Ltd + 142-144 Fullarton Road + Rose Park SA 5067 + AU + +DC-E5-33 (hex) Remko GmbH & Co. KG +200000-2FFFFF (base 16) Remko GmbH & Co. KG + Im Seelenkamp 12 + Lage 32791 + DE + +DC-E5-33 (hex) Ambi Labs Limited +100000-1FFFFF (base 16) Ambi Labs Limited + 1903, 19/F, Loon Lee Building, 267-275 Des Voeux Road Central., Sheung Wan, Hong Kong + Hong Kong Hong Kong 00000 + HK + +C4-FF-BC (hex) comtime GmbH +500000-5FFFFF (base 16) comtime GmbH + Gutenbergring 22 + Norderstedt 22848 + US + +C4-FF-BC (hex) VISATECH C0., LTD. +100000-1FFFFF (base 16) VISATECH C0., LTD. + C-312 168, Gasan digital 1-ro + Geumcheon-gu Seoul 08507 + KR + +1C-21-D1 (hex) p2-plus inc. +E00000-EFFFFF (base 16) p2-plus inc. + 12F.-6,No.5,Sec.3,new taipei Blvd., Sinjhuang Dist., + new taipei taiwan 24250 + TW + +34-29-8F (hex) Albert Handtmann Maschinenfabrik GmbH&Co.KG +C00000-CFFFFF (base 16) Albert Handtmann Maschinenfabrik GmbH&Co.KG + Hubertus-Liebrecht-Str. 10-12 + Biberach 88400 + DE + +9C-43-1E (hex) HK ELEPHONE Communication Tech Co.,Limited +D00000-DFFFFF (base 16) HK ELEPHONE Communication Tech Co.,Limited + Unit 04, 7/F Bright Way Tower No.33 Mong Kok Rd KL + Hong Kong 999077 + HK + +28-2C-02 (hex) Tokin Limited +A00000-AFFFFF (base 16) Tokin Limited + Unit 513-4, Block A, Focal Industrial Centre, 21 Man Lok Street, Hung Hom + Kowloon 0000 + HK + +28-2C-02 (hex) LLC MICROTEH +500000-5FFFFF (base 16) LLC MICROTEH + pl.5 bldg.2/3 Akademika Anokhina str. + Moscow 119602 + RU + +28-2C-02 (hex) ThirdReality, Inc +B00000-BFFFFF (base 16) ThirdReality, Inc + 647 East Longhua Road, Huangpu District + Shanghai Shanghai 200023 + CN + +9C-43-1E (hex) Antailiye Technology Co.,Ltd +000000-0FFFFF (base 16) Antailiye Technology Co.,Ltd + 7/F,Zhengjiyuan Buiding,2 Road,Qianjing, Xixiang, Baoan District,Shenzhen + SHEN ZHEN GUANGDONG 518000 + CN + +9C-43-1E (hex) Midas Technology DBA Phoenix Audio Technologies +E00000-EFFFFF (base 16) Midas Technology DBA Phoenix Audio Technologies + 16 Goodyear #120 + Irvine CA 92618 + US + +F8-B5-68 (hex) Dongwoo Engineering Co.,Ltd +300000-3FFFFF (base 16) Dongwoo Engineering Co.,Ltd + #311, dREC Techno 9-ro, Yuseong-gu + Daegeon 34027 + KR + +F8-B5-68 (hex) LifePrint Products, Inc. +000000-0FFFFF (base 16) LifePrint Products, Inc. + 4667 Golden Foothill Parkway, Suite 102 + El Dorado Hills CA 95762 + US + +F8-B5-68 (hex) etectRx +500000-5FFFFF (base 16) etectRx + 107 SW 140th Terr., Ste. 1 + Newberry FL 32669 + US + +F8-B5-68 (hex) Combiwins Technology Co.,Limited +400000-4FFFFF (base 16) Combiwins Technology Co.,Limited + 2F Sever Star Mansion, West Qixing Road + Xiamen Fujian 361012 + CN + +28-2C-02 (hex) SAKATA DENKI Co., Ltd. +000000-0FFFFF (base 16) SAKATA DENKI Co., Ltd. + Yagisawa2-17-20 + NishiTokyo-city Tokyo 202-0022 + JP + +38-73-EA (hex) Annapurna labs +D00000-DFFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +38-73-EA (hex) Shenzhen Jixian Technology Co., Ltd. +E00000-EFFFFF (base 16) Shenzhen Jixian Technology Co., Ltd. + 4F, Building A, Tongfang Information Harbor, No.11, Langshan Road, North Area of High-tech Park, Nanshan District + Shenzhen Guangdong 518000 + CN + +40-48-FD (hex) Plus One Global Ltd. +900000-9FFFFF (base 16) Plus One Global Ltd. + 2-8-6,Nishishinbashi + Minato-ku Tokyo 105-0003 + JP + +38-73-EA (hex) PingGPS Inc +700000-7FFFFF (base 16) PingGPS Inc + 19825 North Cove Road, #173 + CORNELIUS NC 28031 + US + +38-73-EA (hex) SHENZHEN CSE TECHNOLOGY CO., LTD +A00000-AFFFFF (base 16) SHENZHEN CSE TECHNOLOGY CO., LTD + 2F,3Building,Xinlianhe Industrial Park,Jinxiu Road,Western Industrial Zone, Shajing Town,Baoan, + Shenzhen Guangdong 518000 + CN + +38-73-EA (hex) Proch plastic Co., Ltd. +300000-3FFFFF (base 16) Proch plastic Co., Ltd. + 7F No.189 Xinhu 3rd Rd. Neihu Dist. + Taipei city --- 114 + TW + +38-73-EA (hex) LG Electronics +C00000-CFFFFF (base 16) LG Electronics + 51, Gasan Digital1-ro, Geumcheon-gu + Seoul 08592 + KR + +34-D0-B8 (hex) Captec Ltd +000000-0FFFFF (base 16) Captec Ltd + 7 Whittle Avenue + Fareham Hampshire PO15 5SH + GB + +8C-14-7D (hex) Anyware Solutions ApS +900000-9FFFFF (base 16) Anyware Solutions ApS + Monrads Alle 9 + Valby Sjaelland 2500 + DK + +34-D0-B8 (hex) Meatest sro +A00000-AFFFFF (base 16) Meatest sro + Zelezna 509/3 + Brno 61900 + CZ + +EC-9F-0D (hex) WisIOE +400000-4FFFFF (base 16) WisIOE + Room 601, Hongyuan Building, Baoyuan Road, Xixiang Street, Baoan District + Shenzhen Guangdong 518000 + CN + +AC-1D-DF (hex) Fine Inc. +B00000-BFFFFF (base 16) Fine Inc. + Rm 2208, U-Tower, 120 HeungDeok JungAng-ro, GiHeung-Gu + YongIn-si Gyeonggi-do 16950 + KR + +AC-1D-DF (hex) Elekon AG +D00000-DFFFFF (base 16) Elekon AG + Cheerstrasse 16 + Luzern 6014 + CH + +AC-1D-DF (hex) HellaStorm, Inc. +100000-1FFFFF (base 16) HellaStorm, Inc. + 12655 Edison Drive, Suite 250 + Alpharetta GA 30005 + US + +AC-1D-DF (hex) WESCO INTEGRATED SUPPLY +A00000-AFFFFF (base 16) WESCO INTEGRATED SUPPLY + 36 HARBOR PARK DRIVE + PORT WASHINGTON NY 11050 + US + +74-1A-E0 (hex) FUJIAN TAILI COMMUNICATION TECHNOLOGY CO.,LTD +500000-5FFFFF (base 16) FUJIAN TAILI COMMUNICATION TECHNOLOGY CO.,LTD + Cangshan science and technology park, Baihuting,Cangshan District, Fuzhou + FUZHOU 350026 + CN + +74-1A-E0 (hex) NURA HOLDINGS PTY LTD +200000-2FFFFF (base 16) NURA HOLDINGS PTY LTD + 349 Brunswick Rd + Brunswick VIC 3056 + AU + +74-1A-E0 (hex) bistos.co.ltd +C00000-CFFFFF (base 16) bistos.co.ltd + 7floor, worim lions vally 5cha + sungnam kyeunggi-do 13201 + KR + +74-1A-E0 (hex) Huano International Technology Limited +000000-0FFFFF (base 16) Huano International Technology Limited + Room 402, Building A, ChuangXin Technology Plaza(Phase 1),Chegongmiao, Futian District, + Shenzhen 518000 + CN + +74-1A-E0 (hex) Revl Inc. +400000-4FFFFF (base 16) Revl Inc. + 325 9th St. + San Francisco CA 94103 + US + +CC-22-37 (hex) Terma Sp. z o.o. +100000-1FFFFF (base 16) Terma Sp. z o.o. + Czaple 100 + Gdańsk Pomorskie 80-298 + PL + +2C-27-9E (hex) Rutledge Omni Services Pte Ltd +600000-6FFFFF (base 16) Rutledge Omni Services Pte Ltd + 34 Toh Guan Road East, #01-12/13 Enterprise Hub + Singapore Singapore 608579 + SG + +2C-27-9E (hex) Forties Inc. +B00000-BFFFFF (base 16) Forties Inc. + 5-3-10-1F, Shiba + Minato Tokyo 1080014 + JP + +2C-27-9E (hex) Kunyi electronic technology (Shanghai) Co., Ltd. +200000-2FFFFF (base 16) Kunyi electronic technology (Shanghai) Co., Ltd. + 2F, 42th Building, No.1000 Jinhai Road,Pudong + Shanghai Shanghai 201206 + CN + +2C-27-9E (hex) Changzhou WEBO Weighing Device & System CO.,LTD +000000-0FFFFF (base 16) Changzhou WEBO Weighing Device & System CO.,LTD + Gaoyang Road No.1 + Changzhou Jiangsu 213000 + CN + +18-9B-A5 (hex) Christ Electronic System GmbH +C00000-CFFFFF (base 16) Christ Electronic System GmbH + Alpenstrasse 34 + Memmingen Bavaria 87700 + DE + +2C-27-9E (hex) Jiangsu JianHu Science & Technology Co., Ltd. +D00000-DFFFFF (base 16) Jiangsu JianHu Science & Technology Co., Ltd. + No.95 East Guangdian Road of Yaoguan County, Wujin District + Changzhou Jiangsu 213011 + CN + +90-4E-91 (hex) Apollo Video Technology +100000-1FFFFF (base 16) Apollo Video Technology + 24000 35th Ave SE + Bothell WA 98021 + US + +34-29-8F (hex) ISRA Vision AG +400000-4FFFFF (base 16) ISRA Vision AG + Industriestraße 14 + Darmstadt 64297 + DE + +34-00-8A (hex) Hibertek International Limited +A00000-AFFFFF (base 16) Hibertek International Limited + Rm. 6, 21F., NO.5, Sec.3, New Taipei Blvd., Xinzhuang Dist. + New Taipei City 24250 + TW + +34-29-8F (hex) Wiesheu GmbH +900000-9FFFFF (base 16) Wiesheu GmbH + Daimlerstr. 10 + Affalterbach 71563 + DE + +34-29-8F (hex) Highlite International B.V. +500000-5FFFFF (base 16) Highlite International B.V. + Vestastraat 2 + Kerkrade 6468 EX + NL + +28-F5-37 (hex) Honeywell Safety Products USA, Inc +A00000-AFFFFF (base 16) Honeywell Safety Products USA, Inc + 7828 Waterville Road + San Diego CA 92154 + US + +E8-18-63 (hex) AVCON Information Technology Co.,Ltd +200000-2FFFFF (base 16) AVCON Information Technology Co.,Ltd + Room 2408, No 2 Building, 335# Guoding Road + Shanghai Shanghai 200433 + CN + +34-00-8A (hex) Shenzhen Andakai Technologies Co., Ltd. +800000-8FFFFF (base 16) Shenzhen Andakai Technologies Co., Ltd. + Unit B, 10/F, Building 2, NO.10 Industial Park, Tianliao Community, Gongming Street, GuangMing District, Shenzhen,China + Shenzhen Guangdong 518107 + CN + +34-00-8A (hex) uberGARD Pte. Ltd. +700000-7FFFFF (base 16) uberGARD Pte. Ltd. + 39 Sungei Kadut Avenue + Singapore 729663 + SG + +78-D8-00 (hex) CL International +E00000-EFFFFF (base 16) CL International + 12th Floor, Woolim Lions Valley 1 Bldg 27, Dunchon-daero 457beongil, Jungwon-gu + Seongnam Kyeonggi-do 462-806 + KR + +78-D8-00 (hex) Korea Micro Wireless Co.,Ltd. +D00000-DFFFFF (base 16) Korea Micro Wireless Co.,Ltd. + #323, 3F, Kyoungin Center, 20, Baekbeom-ro 577beon-gil, Bupyeong-gu + Incheon 21449 + KR + +7C-BA-CC (hex) Fossil Power Systems Inc +600000-6FFFFF (base 16) Fossil Power Systems Inc + 10 Mosher Drive + Dartmouth Nova Scotia B3B1N5 + CA + +7C-BA-CC (hex) Fortem Technologies, Inc. +500000-5FFFFF (base 16) Fortem Technologies, Inc. + 1712 S East Bay Boulevard Suite 325 + Provo UT 84606 + US + +7C-BA-CC (hex) Izkare +300000-3FFFFF (base 16) Izkare + Suite 2812, 800 MinHe Rd + Hangzhou Zhejiang 311200 + CN + +7C-BA-CC (hex) Annapurna labs +A00000-AFFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +7C-BA-CC (hex) Yongguan Electronic Technology (D.G)LTD +900000-9FFFFF (base 16) Yongguan Electronic Technology (D.G)LTD + xinfeng west 3RD + Dongguan 523041 + CN + +F8-8A-3C (hex) Josh.ai +700000-7FFFFF (base 16) Josh.ai + 191 University Blvd #188 + Denver CO 80206 + US + +4C-65-A8 (hex) Fuse +C00000-CFFFFF (base 16) Fuse + 1425 E St. + San Diego 92110 + US + +4C-65-A8 (hex) Beijing Bluehalo Internet Inc. +100000-1FFFFF (base 16) Beijing Bluehalo Internet Inc. + 901B,Building A of Power Creative,NO.1 Shangdi East Road,Haidian District, + Beijing 100085 + CN + +4C-65-A8 (hex) WELT Corporation +000000-0FFFFF (base 16) WELT Corporation + Seocho, Bangbae, 481-5 + Seoul 06699 + KR + +A0-C5-F2 (hex) Serious Integrated, Inc. +A00000-AFFFFF (base 16) Serious Integrated, Inc. + 576 East Germann Road + Gilbert AZ 85296 + US + +A0-C5-F2 (hex) Oray.com co., LTD. +B00000-BFFFFF (base 16) Oray.com co., LTD. + 8008Rm, building No.1 GuoDing d. Yangpu District + Shanghai Shanghai 200433 + CN + +4C-65-A8 (hex) Wuhan MoreQuick Network Technology Co., Ltd. +700000-7FFFFF (base 16) Wuhan MoreQuick Network Technology Co., Ltd. + GuangGuDaDao 70#ShiMaoZhongXin C-2205 + WuHan HuBei 430019 + CN + +4C-65-A8 (hex) SHENZHEN LISAIER TRONICS CO.,LTD +900000-9FFFFF (base 16) SHENZHEN LISAIER TRONICS CO.,LTD + No.22 xihu industrial park ,xikeng henggang Town Longgang District + shenzhen Guang Dong 518115 + CN + +8C-14-7D (hex) Shenzhen Meidou Technology Co, Ltd. +600000-6FFFFF (base 16) Shenzhen Meidou Technology Co, Ltd. + Room 321,Building 4,Zhongxinggongyeyuan, Chuangye Road, Nanshan District + Shenzhen Guangdong 518054 + CN + +8C-14-7D (hex) Unwired Networks +500000-5FFFFF (base 16) Unwired Networks + Gonzagagasse 11/25 + Vienna 1010 + AT + +F0-23-B9 (hex) Domotz Ltd +E00000-EFFFFF (base 16) Domotz Ltd + 334 Ladbroke Grove + London W10 5AD + GB + +04-71-4B (hex) Apparatebau Gauting GmbH +400000-4FFFFF (base 16) Apparatebau Gauting GmbH + Friedrichshafener Strasse 5 + Gilching 82205 + DE + +04-71-4B (hex) uAvionix Corporation +100000-1FFFFF (base 16) uAvionix Corporation + 380 Portage Ave. + Palo Alto CA 94306 + US + +04-71-4B (hex) Energport Inc +800000-8FFFFF (base 16) Energport Inc + 48660 Kato Road + Fremont CA 94538 + US + +60-D7-E3 (hex) HuBDIC CO.,LTD +E00000-EFFFFF (base 16) HuBDIC CO.,LTD + #301, 53, Jeonpa-ro, Manan-gu, Anyang-si + Gyeonggi-do 14084 + KR + +04-71-4B (hex) Observables, Inc. +A00000-AFFFFF (base 16) Observables, Inc. + 117 N. MILPAS ST + SANTA BARBARA CA 93103 + US + +F0-23-B9 (hex) Shenzhen Lachesis Mhealth Co., Ltd. +C00000-CFFFFF (base 16) Shenzhen Lachesis Mhealth Co., Ltd. + Bldg. C, No.43 Yanshan Rd, Nanshan District + Shenzhen GuangDong 518067 + CN + +60-D7-E3 (hex) Nextivity +B00000-BFFFFF (base 16) Nextivity + 16550 West Bernardo Road, Bldg 5, Suite 550 + San Diego CA 92127 + US + +60-D7-E3 (hex) Zhejiang Send Intelligent Technology,Ltd +C00000-CFFFFF (base 16) Zhejiang Send Intelligent Technology,Ltd + 6-7F,E Building,Tiantang Software Park,Xidoumen Road,Xihu District + Hangzhou Zhejiang 310012 + CN + +60-D7-E3 (hex) HindlePower, Inc +800000-8FFFFF (base 16) HindlePower, Inc + 1075 Saint John St + Easton PA 18042 + US + +60-D7-E3 (hex) Quantronix, Inc. +D00000-DFFFFF (base 16) Quantronix, Inc. + 380 S. 200 W. + Farmington UT 84025 + US + +60-D7-E3 (hex) Hemisphere GNSS +400000-4FFFFF (base 16) Hemisphere GNSS + 8515 E. Anderson Dr. + Scottsdale AZ 85255 + US + +08-ED-02 (hex) Savox Communications +900000-9FFFFF (base 16) Savox Communications + Laitaatsillantie 3 + Savonlinna 57170 + FI + +08-ED-02 (hex) Szok Energy and Communication Co., Ltd. +B00000-BFFFFF (base 16) Szok Energy and Communication Co., Ltd. + Rm. 1, 17F., No.104, Sec. 1, Xintai 5th Rd., Xizhi Dist. + New Taipei City 22102 + TW + +08-ED-02 (hex) Guard RFID Solutions +C00000-CFFFFF (base 16) Guard RFID Solutions + #140-766 Cliveden Place + Delta BC V3M6C7 + CA + +98-AA-FC (hex) RPE RADICO +400000-4FFFFF (base 16) RPE RADICO + Marksa, 14 + Obninsk Kaluga reg. 249035 + RU + +98-AA-FC (hex) Nexus Electrical(Jiaxing) Limited +300000-3FFFFF (base 16) Nexus Electrical(Jiaxing) Limited + No 1438,Jiachuang Road,Xiuzhou Industrial Park, + Jiaxing Zhejiang 314031 + CN + +98-AA-FC (hex) Beijing Tiandi-Marco Electro-Hydraulic Control System Company Ltd. +800000-8FFFFF (base 16) Beijing Tiandi-Marco Electro-Hydraulic Control System Company Ltd. + No.5 Qing Nian Gou Road, Hepingli + Beijing 100013 + CN + +98-AA-FC (hex) Mekotronics Co., Ltd +600000-6FFFFF (base 16) Mekotronics Co., Ltd + Rm 19C Lockhart Ctr 301-307, Lockhart Rd Wan Chai + Hong Kong 999077 + HK + +98-AA-FC (hex) MCS Micronic Computer Systeme GmbH +D00000-DFFFFF (base 16) MCS Micronic Computer Systeme GmbH + Geneststr. 5 + Berlin 10829 + DE + +14-4F-D7 (hex) Arkus-ST Ltd +B00000-BFFFFF (base 16) Arkus-ST Ltd + Generala Antonova 3a + Moscow 117342 + RU + +14-4F-D7 (hex) i-SENS, Inc. +600000-6FFFFF (base 16) i-SENS, Inc. + 43, Banpo-daero 28-gil, Seocho-gu + Seoul 06646 + KR + +1C-A0-D3 (hex) Cirque Audio Technology Co., Ltd +900000-9FFFFF (base 16) Cirque Audio Technology Co., Ltd + No. 2, Road BeiYiHeng, HuangJiaBao Industrial Park, ShiPai Town, + DongGuan GuangDong 523347 + CN + +40-F3-85 (hex) PALAZZETTI LELIO SPA +700000-7FFFFF (base 16) PALAZZETTI LELIO SPA + VIA ROVEREDO 103 + PORCIA PORDENONE 33080 + IT + +A4-11-63 (hex) accesso Technology Group +900000-9FFFFF (base 16) accesso Technology Group + Unit 5, The Pavillions, Ruscombe Business Park + Twyford Wilts RG10 9NN + GB + +1C-A0-D3 (hex) Guang Dong He Zheng Network Technology Co.,Ltd +B00000-BFFFFF (base 16) Guang Dong He Zheng Network Technology Co.,Ltd + N0.3,Sanjiang industrial zone,Hengli Town + Dongguan Guangdong 523460 + CN + +8C-C8-F4 (hex) SHENZHEN D-light Technolgy Limited +600000-6FFFFF (base 16) SHENZHEN D-light Technolgy Limited + 2302F, Block B, Wisdom Building ,Qiao xiang Road,Shahe Street, Nanshan District, + Shenzhen Guangdong 518000 + CN + +8C-C8-F4 (hex) Trilux Group Management GmbH +A00000-AFFFFF (base 16) Trilux Group Management GmbH + Heidestrasse + Arnsberg 59759 + DE + +40-F3-85 (hex) IntelliDesign Pty Ltd +300000-3FFFFF (base 16) IntelliDesign Pty Ltd + 99 Bluestone Circuit + Seventeen Mile Rocks Qld 4073 + AU + +40-F3-85 (hex) Embedded IQ +400000-4FFFFF (base 16) Embedded IQ + Block C, HHK House; 22 Ethel Avenue + Johannesburg Gauteng 2195 + ZA + +8C-C8-F4 (hex) TOHO DENKI IND.CO.,LTD +300000-3FFFFF (base 16) TOHO DENKI IND.CO.,LTD + 1-6-30 Meguro + Meguro-ku Tokyo 153-0063 + JP + +50-A4-D0 (hex) XinLian'AnBao(Beijing)Technology Co.,LTD. +800000-8FFFFF (base 16) XinLian'AnBao(Beijing)Technology Co.,LTD. + (Room 501,Building 10, Area 2, Headquarters Base)NO.188,South 4th Ring West Road, Fengtai District + Beijing Beijing 100070 + CN + +8C-C8-F4 (hex) Lanhomex Technology(Shen Zhen)Co.,Ltd. +100000-1FFFFF (base 16) Lanhomex Technology(Shen Zhen)Co.,Ltd. + Room 409, Building 29,Zhi Heng Industrial Part, Guankou 2nd Road, Nanshan District + SHENZHEN 518000 + CN + +8C-C8-F4 (hex) Swift Navigation Inc +900000-9FFFFF (base 16) Swift Navigation Inc + 1543 Mission Street + San Francisco CA 94103 + US + +50-A4-D0 (hex) Shanghai Pujiang Smart Card Systems Co., Ltd. +700000-7FFFFF (base 16) Shanghai Pujiang Smart Card Systems Co., Ltd. + No.100, Lane 7488, Hutai Road + Shanghai 86-201809 + CN + +8C-C8-F4 (hex) Guardtec,Inc +000000-0FFFFF (base 16) Guardtec,Inc + Hanshin IT tower #1203 Digital-ro 272 GUROGU + SEOUL 08389 + KR + +50-A4-D0 (hex) OEM PRODUCTION INC. +900000-9FFFFF (base 16) OEM PRODUCTION INC. + 1461-3 San Mateo Ave. + South San Francisco CA 94080 + US + +34-04-9E (hex) Eginity, Inc. +B00000-BFFFFF (base 16) Eginity, Inc. + 37 N Orange Ave STE 770 + Orlando 32801 + US + +34-04-9E (hex) Eclipse Information Technologies +800000-8FFFFF (base 16) Eclipse Information Technologies + Gulsuyu Mah. Fevzi Cakmak Cad Lefke Sk 16/6 + Istanbul Turkey 34848 + TR + +50-A4-D0 (hex) TREXOM S.r.l. +500000-5FFFFF (base 16) TREXOM S.r.l. + viale dell'Unione Europea, 19 + TARCENTO Udine 33017 + IT + +40-ED-98 (hex) Siebert Industrieelektronik GmbH +B00000-BFFFFF (base 16) Siebert Industrieelektronik GmbH + Siebertstrasse 2 + Eppelborn 66571 + DE + +40-ED-98 (hex) Vaisala Oyj +700000-7FFFFF (base 16) Vaisala Oyj + Vanha Nurmijarventie 21 + VANTAA Fin-01670 + FI + +34-04-9E (hex) uikismart +D00000-DFFFFF (base 16) uikismart + Nanshan + Shenzhen Guangdong 518061 + CN + +40-ED-98 (hex) Shanghai Broadwan Communications Co.,Ltd +600000-6FFFFF (base 16) Shanghai Broadwan Communications Co.,Ltd + Building G, No.1015, Caobao Rd + Shanghai Shanghai 200233 + CN + +40-ED-98 (hex) Cape +500000-5FFFFF (base 16) Cape + 1040 Mariposa St + San Francisco CA 94107 + US + +40-ED-98 (hex) Tsinghua Tongfang Co., LTD +000000-0FFFFF (base 16) Tsinghua Tongfang Co., LTD + Wangzhuang Road No.1, Haidian District, Beijing, Tsinghua Tongfang Technology Plaza. D 21st Floor + Beijing Beijing 100083 + CN + +A4-58-0F (hex) EYE IO, LLC +D00000-DFFFFF (base 16) EYE IO, LLC + 2000 University Ave. Suite 610 + Palo Alto CA 94303 + US + +A4-58-0F (hex) Astro, Inc +600000-6FFFFF (base 16) Astro, Inc + 450 W. 33rd St + New York NY 10001 + US + +A4-58-0F (hex) GUANGZHOU OPTICAL BRIDGE COMMUNICATION EQUIPMENT CO.,LTD. +A00000-AFFFFF (base 16) GUANGZHOU OPTICAL BRIDGE COMMUNICATION EQUIPMENT CO.,LTD. + room b201,NO.263,middle of zhougshan avenue,tianhe + guangzhou 510660 + CN + +50-0B-91 (hex) Panasonic Enterprise Solutions Company +800000-8FFFFF (base 16) Panasonic Enterprise Solutions Company + 6144 N Panasonic Way + Denver CO 80249 + US + +24-4E-7B (hex) Leshi Internet Information & Technology (Beijing) Corp. +400000-4FFFFF (base 16) Leshi Internet Information & Technology (Beijing) Corp. + Fl 16, Letv Building, 105 Yaojiayuan Road, Chaoyang District, Beijing,China + Beijing 100025 + CN + +24-4E-7B (hex) WithWin Technology ShenZhen CO.,LTD +E00000-EFFFFF (base 16) WithWin Technology ShenZhen CO.,LTD + 29F, East Tower, NanShan Digital Technology & Cultural Industry Park, ShenNan Throughfare10128# + ShenZhen China 518000 + CN + +24-4E-7B (hex) Jiangsu Xuanbo Electronic Technologies Co.,Ltd +500000-5FFFFF (base 16) Jiangsu Xuanbo Electronic Technologies Co.,Ltd + Nearby the Bus stop of Hanzi Industrial Park,Danjin Road,Hengtang Town + Danyang Jiangsu 212300 + CN + +50-0B-91 (hex) Shenzhen Xinfa Electronic Co.,ltd +700000-7FFFFF (base 16) Shenzhen Xinfa Electronic Co.,ltd + No 57, Baoli Road, Buji Town + Longgang District Shenzhen, Guangdong 518112 + CN + +7C-CB-E2 (hex) mirakonta s.l. +C00000-CFFFFF (base 16) mirakonta s.l. + calle zuatzu nº1 (edif ulia) pabellon 7 (parque emp. zuatzu) + san sebastian guipuzcoa 20018 + ES + +7C-CB-E2 (hex) Polarteknik Oy +800000-8FFFFF (base 16) Polarteknik Oy + Klaavolantie 1 + Huittinen 32700 + FI + +24-4E-7B (hex) RCC TIME CO .,LIMITED +200000-2FFFFF (base 16) RCC TIME CO .,LIMITED + 6/F,C2Block,Guang Hao Feng Industrial Park,Hang Cheng Road,Gushu + Hong Kong 518000 + HK + +48-65-EE (hex) Mission Microwave Technologies, Inc +400000-4FFFFF (base 16) Mission Microwave Technologies, Inc + 10012 Norwalk Blvd, Suite 150 + Santa Fe Springs CA 90670 + US + +48-65-EE (hex) Venture Research Inc. +700000-7FFFFF (base 16) Venture Research Inc. + 3001 Summit Ave + Plano TX 75074 + US + +1C-C0-E1 (hex) LX Corporation Pty Ltd +800000-8FFFFF (base 16) LX Corporation Pty Ltd + Suite 101, Level 1, National Innovation Centre Building, 4 Cornwallis Street + Eveleigh New South Wales 2015 + AU + +4C-E1-73 (hex) outpaceIO +300000-3FFFFF (base 16) outpaceIO + 44 rue Armand Carrel + Montreuil 93100 + FR + +4C-E1-73 (hex) Plus One Japan Limited +E00000-EFFFFF (base 16) Plus One Japan Limited + 2-8-6,Nishishinbashi + Minato-ku Tokyo 105-0003 + JP + +1C-C0-E1 (hex) Shenzhen Highsharp Electronics Ltd. +000000-0FFFFF (base 16) Shenzhen Highsharp Electronics Ltd. + A8 Music Tower 2007-08, High-tech Park + Shenzhen Guangdong 518000 + CN + +4C-E1-73 (hex) REMONDE NETWORK +C00000-CFFFFF (base 16) REMONDE NETWORK + Room 504 Building A, 3 Juquan Road, Science Town + Guangzhou Guangdong 510170 + CN + +0C-EF-AF (hex) Kenmore +000000-0FFFFF (base 16) Kenmore + 3333 Beverly Rd. + Hoffman Estates IL 60179 + US + +38-3A-21 (hex) Shenzhen HS Fiber Communication Equipment CO., LTD +200000-2FFFFF (base 16) Shenzhen HS Fiber Communication Equipment CO., LTD + 6F, Bld#A, Dezhong Industrial Park, Yangmei Village, Bantian Town, Longgang District + Shenzhen Guangdong 518129 + CN + +AC-64-DD (hex) 8Cups +400000-4FFFFF (base 16) 8Cups + 29, Gonghang-daero 61-gil, Gangseo-gu + Seoul 07563 + KR + +AC-64-DD (hex) JSC InfoTeCS +100000-1FFFFF (base 16) JSC InfoTeCS + Staryy Petrovsko-Razumovsky proyezd, 1/23, bld.1 + Moscow 127287 + RU + +AC-64-DD (hex) Groupe Citypassenger Inc +B00000-BFFFFF (base 16) Groupe Citypassenger Inc + 1117 sainte catherine ouest + Montreal Quebec H3B1H9 + CA + +38-3A-21 (hex) Colooc AB +D00000-DFFFFF (base 16) Colooc AB + Nåsvägen 9 + Bromma Sverige 16775 + SE + +38-3A-21 (hex) Shenzhen Smart-core Technology co., Ltd. +600000-6FFFFF (base 16) Shenzhen Smart-core Technology co., Ltd. + 16/F., Finance & Technology Building, No. 11 Keyuan Road, Nanshan Dist. + Shenzhen Guangdong 518057 + CN + +F8-1D-78 (hex) Digital Imaging Technology +400000-4FFFFF (base 16) Digital Imaging Technology + 2275 Research Blvd Suite 500 + Rockville MD 20850 + US + +F8-1D-78 (hex) SHANGHAI SUN TELECOMMUNICATION CO., LTD. +300000-3FFFFF (base 16) SHANGHAI SUN TELECOMMUNICATION CO., LTD. + Building No.145, Lane 666 Xianing Road, Jinshan Industrial Zone + Shanghai Shanghai 201506 + CN + +F8-1D-78 (hex) Tofino +D00000-DFFFFF (base 16) Tofino + 255 Fourier Avenue + Fremont 94539 + US + +F8-1D-78 (hex) AVPro Global Holdings LLC +A00000-AFFFFF (base 16) AVPro Global Holdings LLC + 3518 N Casco Ave + Sioux Falls SD 57104 + US + +38-3A-21 (hex) Dongguan Innovation Technology Co Ltd +400000-4FFFFF (base 16) Dongguan Innovation Technology Co Ltd + Building B, No.3 Desheng Road, Longbeiling, Tangxia + Dongguan City Guangdong Province 523715 + CN + +70-F8-E7 (hex) Fixstars Corporation +C00000-CFFFFF (base 16) Fixstars Corporation + 1-11-1 Ohsaki + Shinagawa-ku TOKYO 141-0032 + JP + +70-F8-E7 (hex) VOXX International +200000-2FFFFF (base 16) VOXX International + 180 Marcus Blvd. + Hauppauge NY 11788 + US + +84-E0-F4 (hex) Scale-Tec Ltd. +E00000-EFFFFF (base 16) Scale-Tec Ltd. + 16027 Hwy 64 + Anamosa IA 52205 + US + +84-E0-F4 (hex) Hangzhou Uni-Ubi Co.,Ltd. +200000-2FFFFF (base 16) Hangzhou Uni-Ubi Co.,Ltd. + Room 605, Building No.5, HaiChuang Park, No.998, Wenyi Road(West), YuHang District + HangZhou ZheJiang 311121 + CN + +C0-D3-91 (hex) xxter bv +900000-9FFFFF (base 16) xxter bv + Elandsgracht 73 + Amsterdam 1016 TR + NL + +58-E8-76 (hex) Xiamen Cacamle Technology Co.,Ltd. +D00000-DFFFFF (base 16) Xiamen Cacamle Technology Co.,Ltd. + Room 1501,15th floor,Building C,DaTang YOHO Park,Huli district + Xiamen Fujian 361000 + CN + +58-E8-76 (hex) Broad Air Technology Co., LTD. +500000-5FFFFF (base 16) Broad Air Technology Co., LTD. + Broadtown + Changsha Hunan 410126 + CN + +C0-D3-91 (hex) ALNETz Co.,LTD +700000-7FFFFF (base 16) ALNETz Co.,LTD + 1-3 Honcho,Naka-ku + Yokohama Kanagawa 231-0005 + JP + +58-E8-76 (hex) Annapurna labs +B00000-BFFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +58-E8-76 (hex) McWong International Inc +300000-3FFFFF (base 16) McWong International Inc + 1921 Arena Blvd + Sacramento CA 95834 + US + +F0-AC-D7 (hex) Intenta GmbH +100000-1FFFFF (base 16) Intenta GmbH + Annabergerstraße 240 + Chemnitz Sachsen 09125 + DE + +F0-AC-D7 (hex) QUANTUM POWER SYSTEMS +200000-2FFFFF (base 16) QUANTUM POWER SYSTEMS + B11. 3RD CROSS. ITI IND. ESTATE. MAHADEVAPURA + BANGALORE KARNATAKA 560048 + IN + +F0-AC-D7 (hex) Med-Pat/Inn-Phone +300000-3FFFFF (base 16) Med-Pat/Inn-Phone + 31 Riordan Place + Shrewsbury NJ 07702 + US + +F0-AC-D7 (hex) Guilin glsun Science and Tech Co.,LTD +000000-0FFFFF (base 16) Guilin glsun Science and Tech Co.,LTD + Block D-08, National IT Industry Park, Chaoyang Rd + Guilin Guangxi 541000 + CN + +28-36-38 (hex) SCA Hygiene Products AB +E00000-EFFFFF (base 16) SCA Hygiene Products AB + Mölndals bro 2 + 405 03 Göteborg - + SE + +28-36-38 (hex) ShangHai Canall Information Technology Co.,Ltd +B00000-BFFFFF (base 16) ShangHai Canall Information Technology Co.,Ltd + 11F,TongLian Building,1565 Jiaotong Rd.,ShangHai 200065,P.R.C. + ShangHai ShangHai 200065 + CN + +28-36-38 (hex) Havells India Limited +800000-8FFFFF (base 16) Havells India Limited + Head Office, Havells India Ltd QRG Towers, 2D, Sector 126 + Noida UP 201304 + IN + +28-36-38 (hex) Innovative Technology Ltd +700000-7FFFFF (base 16) Innovative Technology Ltd + Innovative Business Park, Derker Street + Oldham OL1 4EQ + GB + +8C-19-2D (hex) TeleAlarm SA +A00000-AFFFFF (base 16) TeleAlarm SA + Rue du Pont 23 + La Chaux-de-Fonds 2300 + CH + +38-B8-EB (hex) ExaScaler Inc. +B00000-BFFFFF (base 16) ExaScaler Inc. + Kimura Bldg. 5F, Kanda Ogawamachi 2-1 + Chiyoda-ku Tokyo 101-0052 + JP + +8C-19-2D (hex) Shenzhen Huanuo Internet Technology Co.,Ltd +100000-1FFFFF (base 16) Shenzhen Huanuo Internet Technology Co.,Ltd + Room 10G, Tower 4C, Software Industry Base, Nanshan District, ShenZhen, China, 518000. + Shenzhen 518000 + CN + +8C-19-2D (hex) DataRemote Inc. +200000-2FFFFF (base 16) DataRemote Inc. + 19301 SW 106th Ave Suite 6 + Miami FL 33157 + US + +D0-D9-4F (hex) Perfant Technology Co., Ltd +000000-0FFFFF (base 16) Perfant Technology Co., Ltd + Guo Ren Tong Xin B317,Ke Ji Zhong San Lu,Nanshan,Shenzhen,Guangdong,China + Shenzhen 518000 + CN + +D0-D9-4F (hex) Apption Labs Limited +800000-8FFFFF (base 16) Apption Labs Limited + 7-8 Westbridge Close + Leicester LE3 5LW + GB + +D0-D9-4F (hex) Optigo Networks +500000-5FFFFF (base 16) Optigo Networks + #320 – 887 Great Northern Way + Vancouver BC V5T 4T5 + CA + +D0-D9-4F (hex) Beijing Yiwangxuntong Technology +300000-3FFFFF (base 16) Beijing Yiwangxuntong Technology + Room 1605, Unit 2, Building No.1, ShangAoShiJi Center, XiSanQi + Beijing Select State 100096 + CN + +D0-D9-4F (hex) peiker CEE +400000-4FFFFF (base 16) peiker CEE + Gartenstrasse 25 + Bad Homburg 61352 + DE + +CC-D3-1E (hex) Haishu Technology LIMITED +A00000-AFFFFF (base 16) Haishu Technology LIMITED + Jiulong Midun street No.89 + Hongkong 999077 + HK + +C4-7C-8D (hex) HHCC Plant Technology Co.,Ltd. +600000-6FFFFF (base 16) HHCC Plant Technology Co.,Ltd. + Floor 12,A build ,Shuguang Plaza, Jingshun road, Chaoyang district + Beijing Beijing 100028 + CN + +CC-D3-1E (hex) Elk Products +B00000-BFFFFF (base 16) Elk Products + 3266 Highway 70 West + Hildebran NC 28637 + US + +CC-D3-1E (hex) BBPOS International Limited +600000-6FFFFF (base 16) BBPOS International Limited + Suite 1602, Tower 2, Nina Tower, 8 Yeung Uk Road, Tsuen Wan, NT + Hong Kong China 00000 + HK + +68-91-D0 (hex) Altis Technology +B00000-BFFFFF (base 16) Altis Technology + 711 Lu Plaza, 2 Wing Yip Street, Kwun Tong + Hong Kong 0000 + HK + +C4-7C-8D (hex) Awiselink Co., Ltd. +700000-7FFFFF (base 16) Awiselink Co., Ltd. + 7F., No.98, Minquan Rd., Xindian Dist. + New Taipei City 23141 + TW + +C4-7C-8D (hex) INOTEC Sicherheitstechnik GmbH +C00000-CFFFFF (base 16) INOTEC Sicherheitstechnik GmbH + Am Buschgarten 17 + Ense NRW 59469 + DE + +68-91-D0 (hex) WiseCube +A00000-AFFFFF (base 16) WiseCube + 14F IT Castle-2, 137 Gasan Digital 1-ro, Geumcheon-gu + Seoul 08506 + KR + +C4-7C-8D (hex) Airbus DS - SLC +900000-9FFFFF (base 16) Airbus DS - SLC + 1, Bd Jean Moulin - Metapole + ELANCOURT Cedex 78996 + FR + +C4-7C-8D (hex) PASCAL Co., Ltd. +500000-5FFFFF (base 16) PASCAL Co., Ltd. + 1-8-31, Honjo-Nishi + Higashiosaka Osaka-hu 5780965 + JP + +68-91-D0 (hex) Omniimpex GmbH +700000-7FFFFF (base 16) Omniimpex GmbH + Waldhof 5 + Zug Zug 6300 + CH + +E0-B6-F5 (hex) Agora +400000-4FFFFF (base 16) Agora + 16, rue Alfred Nobel + POITIERS Poitou-Charentes 86000 + FR + +E0-B6-F5 (hex) Folksam AB +A00000-AFFFFF (base 16) Folksam AB + Bohusgatan 14 + Stockholm 10660 + SE + +E0-B6-F5 (hex) ITEL MOBILE LIMITED +D00000-DFFFFF (base 16) ITEL MOBILE LIMITED + RM B3 & B4 BLOCK B, KO FAI INDUSTRIAL BUILDING NO.7 KO FAI ROAD, YAU TONG, KLN, H.K + Hong Kong KOWLOON 999077 + HK + +50-FF-99 (hex) Goetting KG +C00000-CFFFFF (base 16) Goetting KG + Celler Str. 5 + Lehrte Select Your State or Province 31275 + DE + +50-FF-99 (hex) Coyote Sytem +100000-1FFFFF (base 16) Coyote Sytem + 24 quai Gallieni + Suresnes 92150 + FR + +50-FF-99 (hex) Shenzhen Haipengxin Electronic Co., Ltd. +D00000-DFFFFF (base 16) Shenzhen Haipengxin Electronic Co., Ltd. + Block C3,Mingzhuo Xingye Technology Park,Guangming Avenue + Shenzhen Guangdong 518107 + CN + +50-FF-99 (hex) Sichuan Dowlab Electronics Technology Co. Ltd +B00000-BFFFFF (base 16) Sichuan Dowlab Electronics Technology Co. Ltd + NO.198, Wenjia Street, Qingyang District + Chengdu Sichuan 610091 + CN + +98-6D-35 (hex) Shenzhen cositea electronics technology co.,LTD +100000-1FFFFF (base 16) Shenzhen cositea electronics technology co.,LTD + Nanshan District Xili academy Avenue Tong Long Industrial A District 7 Building 3 floor + shenzhen guandong 518000 + CN + +7C-47-7C (hex) EyeLock LLC +300000-3FFFFF (base 16) EyeLock LLC + 355 Lexington Ave., 12th Floor + New York NY 10017 + US + +98-6D-35 (hex) Beijing 3CAVI Tech Co.,Ltd +800000-8FFFFF (base 16) Beijing 3CAVI Tech Co.,Ltd + Unit 203,Block D Keshi Building, Shangdi Xinxi Road, Haidian District + Beijing 100085 + CN + +7C-47-7C (hex) Annapurna labs +C00000-CFFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +5C-F2-86 (hex) VPInstruments +600000-6FFFFF (base 16) VPInstruments + Buitenwatersloot 335 + Delft 2614GS + NL + +5C-F2-86 (hex) Shanghai Notion Information Technology CO.,LTD. +200000-2FFFFF (base 16) Shanghai Notion Information Technology CO.,LTD. + Room 201,Building 3,NO 289,Bisheng Rd,Pudong district,Shanghai,China + Shanghai Shanghai 201203 + CN + +5C-F2-86 (hex) Sunpet Industries Limited +C00000-CFFFFF (base 16) Sunpet Industries Limited + Unit 618, Lakeside 2, Hong Kong Science Park + Shatin N.T. - + HK + +5C-F2-86 (hex) beijing your wonderful control system technology co.,ltd +300000-3FFFFF (base 16) beijing your wonderful control system technology co.,ltd + NO.11 Fengxian Medium Road,Yongfeng Industry Base,Haidian District,Beijing + beijing beijing 100094 + CN + +5C-F2-86 (hex) EUROIMMUN Medizinische Labordiagnostika AG +500000-5FFFFF (base 16) EUROIMMUN Medizinische Labordiagnostika AG + Seekamp 31 + Lübeck Schleswig-Holstein 23560 + DE + +5C-F2-86 (hex) BrightSky, LLC +D00000-DFFFFF (base 16) BrightSky, LLC + 5121 Castello Drive + Naples null 34103-1927 + US + +38-FD-FE (hex) iSmart electronic technology co.,LTD +E00000-EFFFFF (base 16) iSmart electronic technology co.,LTD + Room2101,DeWei Building,4 YunShan West Road,JiangBei, + HuiZhou GuangDong 516000 + CN + +5C-F2-86 (hex) SHENZHEN HIVT TECHNOLOGY CO.,LTD +800000-8FFFFF (base 16) SHENZHEN HIVT TECHNOLOGY CO.,LTD + 7 F,3rd Zone,B Block,Mingyou purchasing Center,Baoyuan RD,Xixiang,Bao'an District,Shenzhen,China + Shenzhen Guangdong 518100 + CN + +38-FD-FE (hex) Rademacher Geraete-Elektronik GmbH +700000-7FFFFF (base 16) Rademacher Geraete-Elektronik GmbH + Buschkamp 7 + Rhede NRW 46414 + DE + +38-FD-FE (hex) Smart Solution Technology, Inc +200000-2FFFFF (base 16) Smart Solution Technology, Inc + 1-15 Kagurazaka,Shinjyukuku, + Tokyo 162-0825 + JP + +38-B8-EB (hex) Wyres SAS +E00000-EFFFFF (base 16) Wyres SAS + 24 rue henri barbusse + Echirolles Isere 38130 + FR + +78-CA-83 (hex) Excelocity Inc. +100000-1FFFFF (base 16) Excelocity Inc. + 200 Colonnade Road Suite #8 + Ottawa Ontario K2E 7M1 + CA + +78-CA-83 (hex) Louroe Electronics +900000-9FFFFF (base 16) Louroe Electronics + 6955 Valjean Avenue + Van Nuys CA 91406 + US + +38-B8-EB (hex) Dojo-Labs Ltd +500000-5FFFFF (base 16) Dojo-Labs Ltd + Hatidhar 17 + Raanana 346651 + IL + +78-CA-83 (hex) DAINCUBE +000000-0FFFFF (base 16) DAINCUBE + #401-701, 655, Pyeongcheon-ro + Bucheon-si 14502 + KR + +1C-88-79 (hex) Airsmart System Co.,Ltd +200000-2FFFFF (base 16) Airsmart System Co.,Ltd + Unit416 , Tudao Intelligent Technology Building, No.9 KeJi Road ,Science and Technology Park, Nanshan District , + Shenzhen Guangdong 518000 + CN + +1C-88-79 (hex) Eolos IT Corp +600000-6FFFFF (base 16) Eolos IT Corp + 3663 SW 8 th Street, STE 210 + Miami FL 33135 + US + +1C-88-79 (hex) Accriva +C00000-CFFFFF (base 16) Accriva + 6260 Sequence Dr + San Diego CA 92121 + US + +1C-87-79 (hex) BEIDIAN GROUP +500000-5FFFFF (base 16) BEIDIAN GROUP + A2 501 Jingang Road Pudong Jinqiao Shanghai + Shanghai Shanghai 200126 + CN + +1C-87-79 (hex) Shenzhen Innovaconn Systems Co.,Ltd +D00000-DFFFFF (base 16) Shenzhen Innovaconn Systems Co.,Ltd + 1F East of Building D,Science and Technology Park,NO.2 Kefeng Road, + Shenzhen Guangdong 518000 + CN + +1C-87-79 (hex) AllThingsTalk +C00000-CFFFFF (base 16) AllThingsTalk + Ajuinlei 1 + Gent 9000 + BE + +1C-87-76 (hex) EBS Sp. z o.o. +100000-1FFFFF (base 16) EBS Sp. z o.o. + ul. Bronisława Czecha 59 + Warszawa Mazowieckie 04-555 + PL + +1C-87-79 (hex) Shenzhen Shouxin Tongda Technology Co.,Ltd +600000-6FFFFF (base 16) Shenzhen Shouxin Tongda Technology Co.,Ltd + Rm.1301-1305A,Fujian Building, Caitian road, Futian District, + Shenzhen Guangdong China + CN + +84-39-BE (hex) Shenzhen Lidaxun Digital Technology Co.,Ltd +D00000-DFFFFF (base 16) Shenzhen Lidaxun Digital Technology Co.,Ltd + 4th Floor 3B03-3B05, Building 2,Internet Industries Park Area A, Baoan district + Shenzhen Guangdong 51800 + CN + +84-39-BE (hex) EDC Electronic Design Chemnitz GmbH +C00000-CFFFFF (base 16) EDC Electronic Design Chemnitz GmbH + Technologie-Campus 4 + Chemnitz Sachsen 09126 + DE + +84-39-BE (hex) Emotiq s.r.l. +A00000-AFFFFF (base 16) Emotiq s.r.l. + Via Cristoforo Baioni 9 + Bergamo BG 24123 + IT + +40-A3-6B (hex) PH Technical Labs +900000-9FFFFF (base 16) PH Technical Labs + 1200, commerce dr, ste 112 + plano tx 75093 + US + +80-0A-80 (hex) Beijing VControl Technology Co., Ltd. +300000-3FFFFF (base 16) Beijing VControl Technology Co., Ltd. + Qinghe Anning Road, Wuyougang building #22 + Beijing Haidian 100085 + CN + +80-0A-80 (hex) Sumitomo Wiring Systems, Ltd. +200000-2FFFFF (base 16) Sumitomo Wiring Systems, Ltd. + Nagoya Lucent Tower 25F + Nagoya Aichi 451-6025 + JP + +80-0A-80 (hex) LLVISION TECHNOLOGY CO.,LTD +400000-4FFFFF (base 16) LLVISION TECHNOLOGY CO.,LTD + Room302,Building A Fuxing,No.30 He Tao Yuan,Guan Dong Dian Bei Jie + Beijing Beijing 100026 + CN + +CC-1B-E0 (hex) IC RealTech +600000-6FFFFF (base 16) IC RealTech + 3050 North Andrews Avenue Extension + Pompano Beach Florida 33064 + US + +00-55-DA (hex) Beijing Connected Information Technology Co.,Ltd. +200000-2FFFFF (base 16) Beijing Connected Information Technology Co.,Ltd. + F15 Block 7(Jing Xi Financial Science and Technology Building)No.30 Shi Xing St,Shijingshan District Beijing, China,100041 + Beijing Beijing 100041 + CN + +CC-1B-E0 (hex) MobiStor Technology Inc. +900000-9FFFFF (base 16) MobiStor Technology Inc. + Rm. 209, 2F., No. 99-1, Anzhong Rd., Xindian Dist. + New Taipei City Taiwn 23154 + TW + +CC-1B-E0 (hex) MDT technologies GmbH +800000-8FFFFF (base 16) MDT technologies GmbH + Papiermühle 1 + Engelskirchen Engelskirchen 51766 + DE + +CC-1B-E0 (hex) NEWSTAR (HK) ELECTRONIC DEVELOPMENT LIMITED +D00000-DFFFFF (base 16) NEWSTAR (HK) ELECTRONIC DEVELOPMENT LIMITED + UNIT 1005,10/F PROSPEROUS BLDG 48-52 DES VOEUX ROAD GENTRAL HONG KONG + HONGKONG HONGKONG 999077 + CN + +00-55-DA (hex) Interaxon Inc +B00000-BFFFFF (base 16) Interaxon Inc + Suite 303 - 511 King St W + Toronto ON M5V 1K4 + CA + +00-55-DA (hex) Arrow Electronics,Inc. +D00000-DFFFFF (base 16) Arrow Electronics,Inc. + 665 Maestro Drive + Reno NV 89511 + US + +CC-1B-E0 (hex) Shenzhen Vanstor Technology Co.,Ltd +300000-3FFFFF (base 16) Shenzhen Vanstor Technology Co.,Ltd + nanshan District + shenzhen GuangDong 518057 + CN + +A0-3E-6B (hex) Qunar.com +C00000-CFFFFF (base 16) Qunar.com + xihaiguoji,1#8 + Beijing Beijing 100086 + CN + +A0-3E-6B (hex) 718th Research Institute of CSIC +800000-8FFFFF (base 16) 718th Research Institute of CSIC + No.17 Zhanlan Road + Handan City Hebei 056027 + CN + +A0-3E-6B (hex) Incogniteam Ltd. +900000-9FFFFF (base 16) Incogniteam Ltd. + ROTERMANI 8 + Tallin Estonia 10111 + EE + +A0-3E-6B (hex) Friday Lab, UAB +500000-5FFFFF (base 16) Friday Lab, UAB + Sauletekio ave 15 + Vilnius Vilnius 10224 + LT + +C8-8E-D1 (hex) AP Sensing GmbH +A00000-AFFFFF (base 16) AP Sensing GmbH + Herrenberger Str. 130 + Böblingen Baden-Würrtemberg 71034 + DE + +C8-8E-D1 (hex) Shenyang Machine Tool(Group) Research & Design Institute Co., Ltd, Shanghai Branch +600000-6FFFFF (base 16) Shenyang Machine Tool(Group) Research & Design Institute Co., Ltd, Shanghai Branch + 2nd Floor,1st Building, No. 128 Xiangyin Rd, Shanghai + Shanghai Shanghai 200433 + CN + +C8-8E-D1 (hex) ROTRONIC AG +200000-2FFFFF (base 16) ROTRONIC AG + Grindelstrasse 6 + Bassersdorf Zurich 8303 + CH + +A0-3E-6B (hex) Videx Electronics S.p.A. +200000-2FFFFF (base 16) Videx Electronics S.p.A. + Via del Lavoro, 1 + Monte Giberto FM 63846 + IT + +DC-44-27 (hex) Wharton Electronics Ltd +800000-8FFFFF (base 16) Wharton Electronics Ltd + Unit 15, Thame Park Business Centre + Thame Oxfordshire OX9 3XA + GB + +1C-21-D1 (hex) Dynojet Research +900000-9FFFFF (base 16) Dynojet Research + 2191 Mendenhall #105 + North Las Vegas NV 89081 + US + +1C-21-D1 (hex) Reliatronics Inc. +800000-8FFFFF (base 16) Reliatronics Inc. + 1858 Ranch Road 3232 + Johnson City TX 78636 + US + +B0-C5-CA (hex) Astyx GmbH +800000-8FFFFF (base 16) Astyx GmbH + Lise-Meitner-Str. 2a + Ottobrunn Bavaria 85521 + DE + +DC-44-27 (hex) General Microsystems Sdn Bhd +300000-3FFFFF (base 16) General Microsystems Sdn Bhd + 3-17, Jalan USJ 7/3B + UEP Subang Jaya Selangor D. E. 47610 + MY + +DC-44-27 (hex) Suritel +000000-0FFFFF (base 16) Suritel + 5, ul. Usievicha + Moscow Moscow 125319 + RU + +1C-21-D1 (hex) B-Scada Inc. +500000-5FFFFF (base 16) B-Scada Inc. + 9030 W Fort Island Trail + Crystal River FL 34429 + US + +B0-C5-CA (hex) IVK-SAYANY +100000-1FFFFF (base 16) IVK-SAYANY + Aviamotornaya str. 50 + Moscow Moscow 111024 + RU + +B0-C5-CA (hex) SYSTOVI +500000-5FFFFF (base 16) SYSTOVI + 5, rue du Chêne Lassé + SAINT-HERBLAIN Loire-Atlantique 44800 + FR + +78-C2-C0 (hex) Wan Chao An (Beijing) Technology Co., Ltd. +B00000-BFFFFF (base 16) Wan Chao An (Beijing) Technology Co., Ltd. + Room 1-1-1403, Shang Di Jia Yuan + Beijing Beijing 100085 + CN + +B4-37-D1 (hex) DIMTON CO.,LTD. +300000-3FFFFF (base 16) DIMTON CO.,LTD. + 1F.,No.137,Xingfu E.Rd., Xinzhuang Dist., New Taipei City 242, Taiwan (R.O.C) + New Taipei Taiwan 24252 + TW + +B4-37-D1 (hex) Alturna Networks +100000-1FFFFF (base 16) Alturna Networks + De Huchtstraat 35 + Almere Flevoland 1327 EC + NL + +B4-37-D1 (hex) Fibersystem AB +200000-2FFFFF (base 16) Fibersystem AB + Gårdsfogdevägen 18B + Bormma Stockholm 16866 + SE + +78-C2-C0 (hex) Shenzhen ELI Technology co.,ltd +000000-0FFFFF (base 16) Shenzhen ELI Technology co.,ltd + Room 201, Dawning Building, No.12 Keji South 12th Road, Hi-Tech Park , Shenzhen + Shenzhen Guangdong 518057 + CN + +88-5D-90 (hex) Wuhan Strong Electronics Co., Ltd +400000-4FFFFF (base 16) Wuhan Strong Electronics Co., Ltd + 2nd Floor, 6 Bldg, Guannan Fuxing Medical Park, + Wuhan Hubei 430074 + CN + +88-5D-90 (hex) Schmidt & Co.,(H.K.)Ltd. +700000-7FFFFF (base 16) Schmidt & Co.,(H.K.)Ltd. + 5F., No.139, Songjiang Rd., Zhongshan Dist., Taipei City 10485, Taiwan (R.O.C.) + Taipei Taiwan 10485 + TW + +88-5D-90 (hex) iRoom GmbH +C00000-CFFFFF (base 16) iRoom GmbH + Paracelsus Str. 4 + Oberndorf Salzburg 5110 + AT + +88-5D-90 (hex) Premier Merchandises Limited +B00000-BFFFFF (base 16) Premier Merchandises Limited + 23/F Metro Loft, 38 Kwai Hei Street, + Hong Kong + HK + +74-F8-DB (hex) Provision-ISR +500000-5FFFFF (base 16) Provision-ISR + 11 Atir Yeda St. + Kfar Saba Israel 4464310 + IL + +64-FB-81 (hex) Kay Schulze & Karsten Pohle GbR +500000-5FFFFF (base 16) Kay Schulze & Karsten Pohle GbR + Heinrich-Hertz-Strasse 121 + Hamburg Hamburg 22083 + DE + +64-FB-81 (hex) NPG Technology S.A. +800000-8FFFFF (base 16) NPG Technology S.A. + C/ Ecuador 14 (P.I. Las Monjas) + Torrejón de Ardoz Madrid 28850 + ES + +80-7B-85 (hex) Oliotalo Oy +B00000-BFFFFF (base 16) Oliotalo Oy + Sinikalliontie 18 B + Espoo Uusimaa 02630 + FI + +80-7B-85 (hex) SMART ELECTRONICS NZ LIMITED +900000-9FFFFF (base 16) SMART ELECTRONICS NZ LIMITED + 4d Palm Grove, Berhampore + Wellington 6023 + NZ + +54-9A-11 (hex) SpearX Inc. +100000-1FFFFF (base 16) SpearX Inc. + No.332., Sec. 1, Jianguo S. Rd., + Taipei City 10656 + TW + +80-7B-85 (hex) Ningbo Plus and Popscreens electronic Technology Co.,LTD +C00000-CFFFFF (base 16) Ningbo Plus and Popscreens electronic Technology Co.,LTD + 7 Hong Da Road, Hong Tang Industrial Park Zone A + Ningbo Zhejiang 315040 + CN + +64-FB-81 (hex) Bronkhorst High-Tech BV +A00000-AFFFFF (base 16) Bronkhorst High-Tech BV + Nijverheidsstraat 1a + Ruurlo Gelderland NL-7261AK + NL + +80-E4-DA (hex) Elcus +900000-9FFFFF (base 16) Elcus + Varshavskaya st. 5A lit L + St.-Petersburg St.-Petersburg 196128 + RU + +64-FB-81 (hex) Pricer AB +400000-4FFFFF (base 16) Pricer AB + Västra Järnvägsgatan 7 + Stockholm 11164 + SE + +1C-CA-E3 (hex) PGA ELECTRONIC +100000-1FFFFF (base 16) PGA ELECTRONIC + ZI LA MALTERIE + MONTIERCHAUME 36130 + FR + +64-FB-81 (hex) MOBILUS Inc. +300000-3FFFFF (base 16) MOBILUS Inc. + 2nd Fl. 18, + Seocho-gu Seoul 138-898 + KR + +1C-CA-E3 (hex) Private +000000-0FFFFF (base 16) Private + +90-C6-82 (hex) Shenzhen Lencotion Technology Co.,Ltd +000000-0FFFFF (base 16) Shenzhen Lencotion Technology Co.,Ltd + LongGang,Buji Xia Shuijing,Hubei + Shenzhen Guangdong 518112 + CN + +2C-D1-41 (hex) CITA SMART SOLUTIONS LTD +E00000-EFFFFF (base 16) CITA SMART SOLUTIONS LTD + 5th Floor, 52-54 Gracechurch Street, London EC3V 0EH, United Kingdom + London N/L EC3V 0EH + GB + +80-E4-DA (hex) Shortcut Labs +700000-7FFFFF (base 16) Shortcut Labs + Teknikringen 26 + Stockholm Stockholm 11428 + SE + +80-E4-DA (hex) Wheatstone Corporation +000000-0FFFFF (base 16) Wheatstone Corporation + 600 Industrial Drive + New Bern NC 28562 + US + +2C-D1-41 (hex) Fiberroad Technology Co., Ltd. +A00000-AFFFFF (base 16) Fiberroad Technology Co., Ltd. + 2F,5# Building,Minxing Industrial Park,MinKang Rd.Minzhi,Longhua District,ShenZhen China. + shenzhen GuangDong 518131 + CN + +2C-D1-41 (hex) ZENIC INC. +500000-5FFFFF (base 16) ZENIC INC. + 4-7-5 + Nionohama Otsu Shiga 520-0801 + JP + +2C-6A-6F (hex) Logic IO Aps +900000-9FFFFF (base 16) Logic IO Aps + Holmboes Alle 14 + Horsens DK 8700 + DK + +2C-6A-6F (hex) SM DSP CO.,LTD. +700000-7FFFFF (base 16) SM DSP CO.,LTD. + 6-Gil 13-14 + Gumi-si Gyeongsangbuk-Do 730-906 + KR + +A0-BB-3E (hex) ManTech International Corporation +500000-5FFFFF (base 16) ManTech International Corporation + 2250 Corporate Park Drive + Herndon Virginia 20171 + US + +A0-BB-3E (hex) Filo SRL +A00000-AFFFFF (base 16) Filo SRL + Via Giovanni Giolitti 34 + Roma rm 00185 + IT + +98-02-D8 (hex) Private +E00000-EFFFFF (base 16) Private + +2C-6A-6F (hex) ELKO EP, s.r.o. +100000-1FFFFF (base 16) ELKO EP, s.r.o. + Palackeho 493 + Holesov, Vsetuly Zlinsky kraj 76901 + CZ + +98-02-D8 (hex) Zedi, Inc. +400000-4FFFFF (base 16) Zedi, Inc. + 1855 - 94 ST NW + Edmonton AB T6N 1E6 + CA + +98-02-D8 (hex) Simplo Technology Co.,LTD +800000-8FFFFF (base 16) Simplo Technology Co.,LTD + No471., Sec.2, Pa The Rd., + Hu Kou 30348 Hsin Chu Hsien + TW + +28-FD-80 (hex) Airbus Defence and Space Oy +C00000-CFFFFF (base 16) Airbus Defence and Space Oy + Hiomotie 32 + Helsinki 00380 + FI + +A0-BB-3E (hex) IVision Electronics Co.,Ltd +100000-1FFFFF (base 16) IVision Electronics Co.,Ltd + Bldg.B,Yingkeli Industrial Park + Shenzhen GuangDong 518116 + CN + +A0-BB-3E (hex) WiteRiver Technology LLC +300000-3FFFFF (base 16) WiteRiver Technology LLC + 31 Mira str. + Ufa Republic of Bashkortostan 450112 + RU + +28-FD-80 (hex) Zhixiang Technology Co., Ltd. +200000-2FFFFF (base 16) Zhixiang Technology Co., Ltd. + 7-2604 Media Village, + Chaoyang District, Beijing 100107 + CN + +2C-26-5F (hex) Jiangsu JARI Technology Group Co., LTD +200000-2FFFFF (base 16) Jiangsu JARI Technology Group Co., LTD + NO.18, Shenghu Rd, + Lianyungang City Jiangsu 222061 + CN + +2C-26-5F (hex) Polara Engineering +A00000-AFFFFF (base 16) Polara Engineering + 9153 STELLAR COURT + CORONA California 92883 + US + +0C-EF-AF (hex) GainStrong Industry Co.,Ltd +C00000-CFFFFF (base 16) GainStrong Industry Co.,Ltd + 3rd Floor, 1st Building, Block E, Minzhu West Industrial Zone, Bao’an Dist. + Shenzhen Guangdong 518100 + CN + +0C-EF-AF (hex) chengdu joyotime Technology Co., Ltd. +A00000-AFFFFF (base 16) chengdu joyotime Technology Co., Ltd. + room 503, B7 , tianfu software park + chengdu sichuan 610000 + CN + +F8-02-78 (hex) CLARUS Korea Co., Ltd +400000-4FFFFF (base 16) CLARUS Korea Co., Ltd + 2F, Illutech Bldg, Myoenmok7-dong, + Seoul 131827 + KR + +F8-02-78 (hex) Rosemount Analytical +B00000-BFFFFF (base 16) Rosemount Analytical + 10241 West Little York, Suite 200 + Houston, TX 77040 Texas 77040 + US + +A4-4F-29 (hex) HTD +A00000-AFFFFF (base 16) HTD + 1000 Shiloh Rd, Suite 100 + Plano TX 75074 + US + +A4-4F-29 (hex) GUANGDONG REAL-DESIGN INTELLIGENT TECHNOLOGY CO.,LTD +B00000-BFFFFF (base 16) GUANGDONG REAL-DESIGN INTELLIGENT TECHNOLOGY CO.,LTD + No.1 Ruixiang Road,Fengxiang industrial Park,DaliangSub-district,Shunde district,Foshan City,Guangdong + Foshan Guangdong 528300 + CN + +3C-39-E7 (hex) VANSTONE ELECTRONIC (BEIJING)CO,. LTD. +C00000-CFFFFF (base 16) VANSTONE ELECTRONIC (BEIJING)CO,. LTD. + Room 805,8/F,Qinghua Information Port Development Building,North High-tech Industrial Park,Nanshan District,Shenzhen + shenzhen guangdong 518000 + CN + +A4-4F-29 (hex) Dermalog Identification Systems GmbH +000000-0FFFFF (base 16) Dermalog Identification Systems GmbH + Mittelweg 120 + Hamburg Hamburg 20148 + DE + +3C-39-E7 (hex) Attrackting AG +500000-5FFFFF (base 16) Attrackting AG + Falkenstrasse 44 + Biel/Bienne Berne 2502 + CH + +0C-EF-AF (hex) Goerlitz AG +100000-1FFFFF (base 16) Goerlitz AG + August-Thyssen-Strasse 32 + Koblenz Rheinland-Pfalz 56070 + DE + +3C-39-E7 (hex) Martem AS +800000-8FFFFF (base 16) Martem AS + Akadeemia tee 21/6 + Tallinn Harjumaa 12618 + EE + +3C-39-E7 (hex) HomeWizard B.V. +200000-2FFFFF (base 16) HomeWizard B.V. + Scheepmakerstraat 40 + Katwijk ZH 2222AC + NL + +10-07-23 (hex) BEIJING SOOALL INFORMATION TECHNOLOGY CO.,LTD +500000-5FFFFF (base 16) BEIJING SOOALL INFORMATION TECHNOLOGY CO.,LTD + Room 1028,Block B,No.11 XinghuoRoad,Science City,Fengtai District + Beijing Beijing 100070 + CN + +E8-18-63 (hex) Protek Electronics Group Co.,LTD +B00000-BFFFFF (base 16) Protek Electronics Group Co.,LTD + Homecare Technology Park,5/F,No.30,Langdong + Shenzhen Guangdong 518105 + CN + +D0-22-12 (hex) Spirit IT B.V. +000000-0FFFFF (base 16) Spirit IT B.V. + prof. dr. Dorgelolaan 20 + Eindhoven Noord-Brabant 5613 AM + NL + +D0-22-12 (hex) Viatron GmbH +400000-4FFFFF (base 16) Viatron GmbH + Carl-Metz-Str. 3 + Ettlingen Baden Würtemberg 76275 + DE + +B8-D8-12 (hex) V5 Technology Corporation +400000-4FFFFF (base 16) V5 Technology Corporation + 5F., No.7, Lixing 3rd Rd., East Dist., Hsinchu City 30078, Taiwan (R.O.C.) + HsinChu Taiwan 30078 + TW + +74-E1-4A (hex) Kanto Aircraft Instrument Co., Ltd. +900000-9FFFFF (base 16) Kanto Aircraft Instrument Co., Ltd. + 2-3-18 Honfujisawa + Fujisawa Kanagawa 251-0875 + JP + +74-E1-4A (hex) APM Technologies (DongGuan) Ltd +700000-7FFFFF (base 16) APM Technologies (DongGuan) Ltd + 109Gosun Science Building, NanCheng , DongGuan, GuangDong, China + DongGuan GuangDong 523000 + CN + +B8-D8-12 (hex) Kiwigrid GmbH +A00000-AFFFFF (base 16) Kiwigrid GmbH + Kleiststraße 10b + Dresden Saxony 01129 + DE + +E4-95-6E (hex) Shanghai Tieda Telecommunications Equipment Co.,LTD. +D00000-DFFFFF (base 16) Shanghai Tieda Telecommunications Equipment Co.,LTD. + 18F The Sapphire Tower 267 TianmuRd(M) + Shanghai Zhabei District 200070 + + +BC-66-41 (hex) UtilLighting Co.,Ltd. +D00000-DFFFFF (base 16) UtilLighting Co.,Ltd. + #102, 1F, 22, Samyang-ro, Seongbuk-gu, Seoul + Seongbuk-gu Seoul 136-717 + KR + +E4-95-6E (hex) PT.MLWTelecom +800000-8FFFFF (base 16) PT.MLWTelecom + Jalan Jembatan Dua Raya no.16/2 + Jakarta 14450 + ID + +E4-95-6E (hex) SMC Networks, Inc +000000-0FFFFF (base 16) SMC Networks, Inc + 20 Mason + Irvine CA 92618 + US + +BC-66-41 (hex) Global China Technology Limited +100000-1FFFFF (base 16) Global China Technology Limited + Ruyi Road 1-3,Ailian, Longcheng Street, longgang Town, + Shenzhen GuangDong 518172 + CN + +58-FC-DB (hex) Spang Power Electronics +000000-0FFFFF (base 16) Spang Power Electronics + 9305 Progress Parkway + Mentor Ohio 44060 + US + +B0-1F-81 (hex) Access Device Integrated Communications Corp. +C00000-CFFFFF (base 16) Access Device Integrated Communications Corp. + No. 839, Sec.3, ChungChing Road, + Taichung City Taichung 42862 + TW + +58-FC-DB (hex) Hi-Target Surveying Instrument Co., Ltd. +900000-9FFFFF (base 16) Hi-Target Surveying Instrument Co., Ltd. + Plant 202, BLDG 13, Tian'An HQ Center, No.555 North Panyu RD. Donghuan Block, + Guangzhou Guangdong 511400 + CN + +58-FC-DB (hex) Inforce Computing Inc. +400000-4FFFFF (base 16) Inforce Computing Inc. + 48820 Kato Road + Fremont CA 94538 + US + +BC-66-41 (hex) Intuitive Surgical, Inc +600000-6FFFFF (base 16) Intuitive Surgical, Inc + 1250 Kifer Rd + Sunnyvale California 94086 + US + +14-1F-BA (hex) POS Systema LLC +E00000-EFFFFF (base 16) POS Systema LLC + Varshavskoe shosse, 35, room №13 + Moscow Moscow 117105 + RU + +F4-0E-11 (hex) BEIJING DONGJIN AERO-TECH CO., LTD +100000-1FFFFF (base 16) BEIJING DONGJIN AERO-TECH CO., LTD + Building 7, 3th floor, Compound No. 33, Beiwaxili, Haidian District + Beijing Beijing 100089 + CN + +B0-1F-81 (hex) Aether Services, Inc. +700000-7FFFFF (base 16) Aether Services, Inc. + 1A2-A08, No.1, Lising 1st RD. + Hsinchu City Hsinchu 30078 + TW + +F4-0E-11 (hex) Kodpro Ltd. +A00000-AFFFFF (base 16) Kodpro Ltd. + Room 801, 8/F, Opulent Bldg., + Hong Kong Wan Chai 999077 + HK + +14-1F-BA (hex) Wisnetworks Technologies Co., Ltd. +700000-7FFFFF (base 16) Wisnetworks Technologies Co., Ltd. + No.77, FuTe West 3 Road, China + Shanghai 200000 + + +7C-70-BC (hex) K-Vision Technology (Shanghai), Ltd +400000-4FFFFF (base 16) K-Vision Technology (Shanghai), Ltd + Floor 4, No.9 Building, 879 Lane + Shanghai Shanghai 200333 + CN + +7C-70-BC (hex) Nomad Digital Ltd. +700000-7FFFFF (base 16) Nomad Digital Ltd. + 2nd Floor, Baltic Chambers, + Newcastle upon Tyne NE1 3DQ + GB + +7C-70-BC (hex) Shanghai magcomm communication technology co ltd +000000-0FFFFF (base 16) Shanghai magcomm communication technology co ltd + B Block,11F,Software Building, No 461 Hongcaolu + Shanghai Shanghai 200233 + CN + +14-1F-BA (hex) BYZERO +400000-4FFFFF (base 16) BYZERO + 1222 Doosan Venture Digm + Anyang-si Gyeonggi-do 431-755 + KR + +BC-34-00 (hex) Q-PRODUCTS a. s. +700000-7FFFFF (base 16) Q-PRODUCTS a. s. + Rybnicna 38/K + Bratislava SK 83106 + SK + +BC-34-00 (hex) Altronix Corporation +300000-3FFFFF (base 16) Altronix Corporation + 140 58th street + Brooklyn NY 11220 + US + +BC-34-00 (hex) Redvision CCTV +000000-0FFFFF (base 16) Redvision CCTV + 17 Highview + Bordon Hampshire GU35 0AX + GB + +A4-3B-FA (hex) Recognition Systems LLC +600000-6FFFFF (base 16) Recognition Systems LLC + 2380 Owen Street + Santa Clara CA 95054 + US + +A4-3B-FA (hex) Deatronic srl +700000-7FFFFF (base 16) Deatronic srl + Via Giulianello 1/7 + ROMA 00178 + IT + +D0-76-50 (hex) Private +400000-4FFFFF (base 16) Private + +D0-76-50 (hex) Accumulate AB +800000-8FFFFF (base 16) Accumulate AB + Lästmakargatan 20 + Stockholm 111 44 + SE + +74-19-F8 (hex) Starcor Beijing Co.,Limited +500000-5FFFFF (base 16) Starcor Beijing Co.,Limited + NO.210 Block B, Building 2 + Beijing Berijing 100089 + CN + +74-19-F8 (hex) Princip a.s. +900000-9FFFFF (base 16) Princip a.s. + Radlicka 204/503 + Praha 5 Praha 158 00 + CZ + +74-19-F8 (hex) Tanjarine +A00000-AFFFFF (base 16) Tanjarine + 188 S Whisman Rd, Bldg A + Mountain View CA 94041 + US + +74-19-F8 (hex) Quest Payment Systems +800000-8FFFFF (base 16) Quest Payment Systems + 227 Burwood Road + Hawthorn Victoria 3122 + AU + +74-19-F8 (hex) Symtop Instrument Co. +200000-2FFFFF (base 16) Symtop Instrument Co. + Haidianqu Xueqinglu Xuezhixuan 613 + Haidianqu Beijing 100083 + CN + +4C-4B-F9 (hex) Electrolux Professional AB +A00000-AFFFFF (base 16) Electrolux Professional AB + Ringvägen 14 + Ljungby 34180 + SE + +40-11-75 (hex) MIRC ELECTRONICS LTD +500000-5FFFFF (base 16) MIRC ELECTRONICS LTD + Onida House, G-1, MIDC, Mahakali Caves Road, Andheri East + Mumbai Maharashtra 400093 + IN + +40-11-75 (hex) Table Trac Inc +400000-4FFFFF (base 16) Table Trac Inc + 6101 Baker Rd STE 206 + Minnetonka MN 55345 + US + +40-11-75 (hex) Lexi Devices, Inc. +000000-0FFFFF (base 16) Lexi Devices, Inc. + 2342 Shattuck Ave, #260 + Berkeley 94704 + US + +40-11-75 (hex) NIBBLE +E00000-EFFFFF (base 16) NIBBLE + Rua Julio Dinis 265 1D + Trofa 4785-330 + PT + +40-11-75 (hex) Fujian Kuke3D Technology Co.,LTD +100000-1FFFFF (base 16) Fujian Kuke3D Technology Co.,LTD + No.33, R&D Building, No. 1, Donghu Road, Digital Fujian Industrial Park, Changle District + Fuzhou Fujian 350200 + CN + +10-DC-B6 (hex) Pickering Interfaces Ltd +A00000-AFFFFF (base 16) Pickering Interfaces Ltd + Stephenson Road + Clacton On Sea Essex CO154NL + GB + +10-DC-B6 (hex) Moya Commumication Technology (Shenzhen) Co.,Ltd. +700000-7FFFFF (base 16) Moya Commumication Technology (Shenzhen) Co.,Ltd. + Guang Hui Science Park, No.17 of Min Qing Road, Longhua District + Shenzhen 518000 + CN + +54-A4-93 (hex) Intelligent Surveillance Corp +000000-0FFFFF (base 16) Intelligent Surveillance Corp + PO Box 12168 + College Station TX 77842 + US + +54-A4-93 (hex) I-MOON TECHNOLOGY CO., LIMITED +300000-3FFFFF (base 16) I-MOON TECHNOLOGY CO., LIMITED + FLAT/RM 2253, BLK 1, 22/F, HOI TAI FACTORY, EST TSING YEUNG CIRCUIT, TUEN MUN + NT 999077 + HK + +04-D1-6E (hex) Dspread Technology (Beijing) Inc. +500000-5FFFFF (base 16) Dspread Technology (Beijing) Inc. + Jingxin Building, 2045 Suite , Chaoyang District + Beijing 100027 + CN + +04-D1-6E (hex) Evolute Systems Private Limited +E00000-EFFFFF (base 16) Evolute Systems Private Limited + #3794 ,Ground and First Floor, 7th Main, Indira Nagar + Bangalore Karnataka 560038 + IN + +44-03-77 (hex) Exsom Computers LLC +200000-2FFFFF (base 16) Exsom Computers LLC + Office 3206, The Citadel Tower, Business Bay + Dubai Dubai 72891 + AE + +44-03-77 (hex) SHEN ZHEN HUAWANG TECHNOLOGY CO; LTD +600000-6FFFFF (base 16) SHEN ZHEN HUAWANG TECHNOLOGY CO; LTD + Longhua New District Qing Xiang Road, Bao Neng Technology Park + SHEN ZHEN GUANG DONG 518109 + CN + +44-03-77 (hex) Atari, Inc. +100000-1FFFFF (base 16) Atari, Inc. + 286 Madison Ave, 8th floor + New York NY 10017 + US + +44-03-77 (hex) Lenovo Image(Tianjin) Technology Ltd. +400000-4FFFFF (base 16) Lenovo Image(Tianjin) Technology Ltd. + Tianjin Free Trade Test Zone (Airport Economic Zone) Room 310, No. 1, Second Avenue, Airport International Logistics Zone + Tianjin Tianjin 300000 + CN + +44-03-77 (hex) Bolin Technology Co., Ltd +E00000-EFFFFF (base 16) Bolin Technology Co., Ltd + 5/F, No 4 Block, Jinruizhonghe Industry Park,Huarong Road, Da Lang, Long Hua, Shenzhen, China. + shenzhen Guang Dong 518109 + CN + +50-62-55 (hex) COTT Electronics +D00000-DFFFFF (base 16) COTT Electronics + 71-75 Shelton Street + London WC2H 9JQ + GB + +50-62-55 (hex) SHINSOFT CO., LTD. +E00000-EFFFFF (base 16) SHINSOFT CO., LTD. + 3F., No. 128, Xinhu 2nd Rd., Neihu Dist. + Taipei City 114 + TW + +1C-FD-08 (hex) Cobham Slip Rings +900000-9FFFFF (base 16) Cobham Slip Rings + 18 Rue de Montréal + ANNEMASSE Ville-la-Grand 74108 + FR + +C4-95-4D (hex) BA International Electronics Co. Ltd. +000000-0FFFFF (base 16) BA International Electronics Co. Ltd. + 8F., No. 140, Nanhua 1st St., Luzhu Dist., + Taoyuan City 338 + TW + +C4-95-4D (hex) LLC TechnoEnergo +700000-7FFFFF (base 16) LLC TechnoEnergo + Kemerovskaya str., 3 + Nizhny Novgorod Nizhny Novgorod region 603152 + RU + +C4-95-4D (hex) Xinjiang Golden Calf Energy IOT Technology Co., Ltd +800000-8FFFFF (base 16) Xinjiang Golden Calf Energy IOT Technology Co., Ltd + A02 office building of Cloud Computing Industrial Park, Karamay District + Karamay Xinjiang 834000 + CN + +C4-95-4D (hex) Teletronik AG +100000-1FFFFF (base 16) Teletronik AG + Bahnhofstrasse 10. + Zug 6302 + CH + +C4-95-4D (hex) AKKA Germany GmbH +600000-6FFFFF (base 16) AKKA Germany GmbH + Riesstrasse 14 + München Bayern 80992 + DE + +64-31-39 (hex) Livongo Health +100000-1FFFFF (base 16) Livongo Health + 150 W. Evelyn Ave, Suite 150 + Mountain View CA 94041 + US + +C4-95-4D (hex) KAT Mekatronik Urunleri AS +A00000-AFFFFF (base 16) KAT Mekatronik Urunleri AS + Istanbul Trakya Serbest Bolgesi Ataturk Bulvari No:20 + Istanbul Catalca 34500 + TR + +C4-95-4D (hex) GL Solutions Inc. +400000-4FFFFF (base 16) GL Solutions Inc. + 16-3 Kuramae 4-chome + Taito-ku Tokyo 111-0051 + JP + +00-69-67 (hex) miliwave +100000-1FFFFF (base 16) miliwave + room 423,105 gwanggyo-ro, yengtong-gu + suwon-si Kyunggi-do 16229 + KR + +00-69-67 (hex) Comcast-SRL +600000-6FFFFF (base 16) Comcast-SRL + Alejo Martinez 17 + Sosua Puerto Plata 34443 + DO + +00-69-67 (hex) aversix +D00000-DFFFFF (base 16) aversix + ???????????351?4??7 (????) + ??? ??? 235 + TW + +00-69-67 (hex) Ningbo Shen Link Communication Technology Co.,Ltd +200000-2FFFFF (base 16) Ningbo Shen Link Communication Technology Co.,Ltd + No.87,Fengming Road,Lizhou Street + Yuyao City Zhejiang Province 315403 + CN + +00-69-67 (hex) Zhejiang Holip Electronic Technology Co.,Ltd +A00000-AFFFFF (base 16) Zhejiang Holip Electronic Technology Co.,Ltd + NO.339 XINQIAO NORTH ROAD + Haiyan Zhejiang 314300 + CN + +A0-22-4E (hex) Hunan Youmei Science&Technology Development Co.,Ltd. +E00000-EFFFFF (base 16) Hunan Youmei Science&Technology Development Co.,Ltd. + 3F, Building No.B8, Cultural Advertising Creative Industry Park, Economic Development Zone + Huaihua City Hunan Province 418000 + CN + +A0-22-4E (hex) MESIT asd, s.r.o. +600000-6FFFFF (base 16) MESIT asd, s.r.o. + Sokolovska 573 + Uherske Hradiste 686 01 + CZ + +A0-22-4E (hex) Standartoptic, Limited Liability Company +C00000-CFFFFF (base 16) Standartoptic, Limited Liability Company + Moskovsky p, 22nd kilometer Kievskoe highway, house 4, building 1 floor 9 Block B office 903? + Moscow 108811 + RU + +20-0A-0D (hex) Amazon Technologies Inc. +B00000-BFFFFF (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +20-0A-0D (hex) Clearly IP Inc +300000-3FFFFF (base 16) Clearly IP Inc + 2416 Industrial Dr Unit F + Neenah WI 54956 + US + +20-0A-0D (hex) Bently & EL Co. Ltd. +D00000-DFFFFF (base 16) Bently & EL Co. Ltd. + 7F-3, Fuxing North Road, Zhong Shan District + Taipei 104 + TW + +20-0A-0D (hex) Austin Hughes Electronics Ltd. +600000-6FFFFF (base 16) Austin Hughes Electronics Ltd. + Unit 3608-12, Cable TV Tower, 9 Hoi Shing Road, Tsuen Wan, Hong Kong + Hong Kong Kwai Tsing New Territories 00000 + HK + +20-0A-0D (hex) HANGZHOU DANGBEI NETWORK TECH.Co.,Ltd +E00000-EFFFFF (base 16) HANGZHOU DANGBEI NETWORK TECH.Co.,Ltd + Build C,Wanfu Center,Binkang Road No.228,Binjiang Area + China 210051 + CN + +40-2C-76 (hex) Beijing Smarot Technology Co., Ltd. +400000-4FFFFF (base 16) Beijing Smarot Technology Co., Ltd. + Room 505, unit 2, 5th floor, 12th building, 3rd yard , Kangze road, Fangshan district + Beijing Beijing 102488 + CN + +40-2C-76 (hex) Shanghai Dahua Scale Factory +100000-1FFFFF (base 16) Shanghai Dahua Scale Factory + No.1013 Wangqiao Road,Pudong New District + Shanghai Shanghai 201201 + CN + +50-DE-19 (hex) Tianjin Natianal Health Technology Co.,Ltd +700000-7FFFFF (base 16) Tianjin Natianal Health Technology Co.,Ltd + Room 2-6, No.8, Haitai development fifth Road, Huayuan industrial Zone , Binhai high-tech District + Tianjin Tianjin 300450 + CN + +50-DE-19 (hex) Clear Flow by Antiference +100000-1FFFFF (base 16) Clear Flow by Antiference + Fradley Distribution Park, Wood End Lane + Lichfield Staffordshire WS13 8NE + GB + +50-DE-19 (hex) AEG Identifikationssysteme GmbH +900000-9FFFFF (base 16) AEG Identifikationssysteme GmbH + Hörvelsinger Weg 47 + Ulm 89081 + DE + +50-DE-19 (hex) SPII SPA +200000-2FFFFF (base 16) SPII SPA + VIA D. VOLPI 37 - ANGOLO VIA MONTOLI + SARONNO VARESE 21047 + IT + +50-A4-D0 (hex) TRAXENS +000000-0FFFFF (base 16) TRAXENS + HELIOPOLIS III – 16 rue Louis Leprince Ringuet + Marseille Provence-Alpes-Côte d'Azur 13013 + FR + +50-DE-19 (hex) TRAXENS +300000-3FFFFF (base 16) TRAXENS + HELIOPOLIS III – 16 rue Louis Leprince Ringuet + Marseille Provence-Alpes-Côte d'Azur 13013 + FR + +3C-FA-D3 (hex) LIPS Corporation +700000-7FFFFF (base 16) LIPS Corporation + 2F., No. 100, Ruiguang Rd., Neihu Dist. + Taipei Taiwan 114 + TW + +50-DE-19 (hex) Tannak International AB +A00000-AFFFFF (base 16) Tannak International AB + Midgårdsvägen 13 + Luleå 973 34 + SE + +3C-FA-D3 (hex) Annapurna labs +100000-1FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +3C-FA-D3 (hex) Corelink Technology Co.,Ltd +B00000-BFFFFF (base 16) Corelink Technology Co.,Ltd + 2701, building D2, No.1, Keyuan Weiyi Road, Laoshan District + Qingdao Shandong China + CN + +3C-FA-D3 (hex) Shenzhen Vplus Communication Intelligent Co., Ltd. +900000-9FFFFF (base 16) Shenzhen Vplus Communication Intelligent Co., Ltd. + Bao'an + Shenzhen Guangdong 518000 + CN + +B0-B3-53 (hex) WUUK LABS CORP. +700000-7FFFFF (base 16) WUUK LABS CORP. + 16192 COASTAL HWY + LEWES DE 19958 + US + +B0-B3-53 (hex) Nanjing Yining Intelligent Technology Co., Ltd. +E00000-EFFFFF (base 16) Nanjing Yining Intelligent Technology Co., Ltd. + Room 209-114, 2 / F, Building 04, No. 18 Jialingjiang East Street, Jianye District, Nanjing + Nanjing Jiangsu 210019 + CN + +B0-B3-53 (hex) Beijing Geekplus Technology Co.,Ltd. +C00000-CFFFFF (base 16) Beijing Geekplus Technology Co.,Ltd. + 1st Floor, Building 1, Chaolai High-Tech industrial Part, Chaoyang District + Beijing Beijing 100012 + CN + +B0-B3-53 (hex) IPvideo Corporation +D00000-DFFFFF (base 16) IPvideo Corporation + 1490 North Clinton Ave + Bay Shore NY 11706 + US + +B0-B3-53 (hex) Blake UK +000000-0FFFFF (base 16) Blake UK + 177-187, Rutland Road + Sheffield --select-- S3 9PT + GB + +B0-B3-53 (hex) Zoox +B00000-BFFFFF (base 16) Zoox + 1149 Chess Drive + Foster City CA 94404 + US + +14-AE-85 (hex) Qingdao iTechene Technologies Co., Ltd. +200000-2FFFFF (base 16) Qingdao iTechene Technologies Co., Ltd. + UnitA3-A4,Level8,Block A ,International Innovation Park,No.1Keyuanwei Rd.,Laoshan District + Qingdao 266100 + CN + +14-AE-85 (hex) Henfred Technology Co., Ltd. +100000-1FFFFF (base 16) Henfred Technology Co., Ltd. + 3F.-7, No.77, Sec. 1, Xintai 5th Rd + New Taipei City Xizhi Dist 221 + TW + +14-AE-85 (hex) MTA Systems +A00000-AFFFFF (base 16) MTA Systems + Pemstraße 2 + Mauthausen 4310 + AT + +64-62-66 (hex) MiiVii Dynamics Technology CO.,LTD +000000-0FFFFF (base 16) MiiVii Dynamics Technology CO.,LTD + 1408-1415 Tower A BUGG Building,No.18 N. Taipingzhuang Rd,haidian District + Beijing Beijing 100000 + CN + +64-62-66 (hex) Annapurna labs +100000-1FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +64-62-66 (hex) Bühler AG +500000-5FFFFF (base 16) Bühler AG + Gupfenstrasse 5 + Uzwil 9240 + CH + +64-62-66 (hex) Shenzhen Jie Shi Lian Industrial Co., LTD +E00000-EFFFFF (base 16) Shenzhen Jie Shi Lian Industrial Co., LTD + 6F,C Building,Jinao Industrial Park,Juling Rd,Guanlan Town,Longhua + Shenzhen Guangdong 518000 + CN + +64-62-66 (hex) Leontech Limited +800000-8FFFFF (base 16) Leontech Limited + 1208 WorkingBerg Commercial Buildung, 41-47 Marble Road + Hong Kong Hong Kong 00000 + HK + +94-CC-04 (hex) Sam Nazarko Trading Ltd +600000-6FFFFF (base 16) Sam Nazarko Trading Ltd + 18 Watermill Way + London Surrey SW19 2RD + GB + +94-CC-04 (hex) Hanzhuo Information Technology(Shanghai) Ltd. +D00000-DFFFFF (base 16) Hanzhuo Information Technology(Shanghai) Ltd. + Room 2085, building 2, 622 Yingyuan middle Road, Jiading Strict + Shanghai 201200 + CN + +94-CC-04 (hex) hyBee Inc. +A00000-AFFFFF (base 16) hyBee Inc. + #1003, Innovalley B, 253, Pangyo-ro, Bundang-gu + Seongnam-si Gyeonggi-do 13486 + KR + +94-05-BB (hex) iungo +800000-8FFFFF (base 16) iungo + Vrouwenlaan 62 + Zwolle Overijssel 8017 HS + NL + +94-CC-04 (hex) Nanjing Yacer Communication Technology Co. Ltd. +200000-2FFFFF (base 16) Nanjing Yacer Communication Technology Co. Ltd. + 333 Taiping South Road Jinling Yujingyuan 19nd  floor Unit K Qin Huai District + nanjing jiangsu 210000 + CN + +90-E2-FC (hex) Pars Ertebat Afzar Co. +000000-0FFFFF (base 16) Pars Ertebat Afzar Co. + 1116 – Burlington Tower Business Bay + Dubai 90072 + AE + +94-05-BB (hex) Dongguan CXWE Technology Co.,Ltd. +200000-2FFFFF (base 16) Dongguan CXWE Technology Co.,Ltd. + Room 805, building 1, No. 16, Keji 4th Road, Songshanhu + Dongguan Guangdong 523000 + CN + +94-05-BB (hex) Zimmer GmbH +900000-9FFFFF (base 16) Zimmer GmbH + Im Salmenkopf 5 + Rheinau Baden-Württemberg 77866 + DE + +94-05-BB (hex) Qingdao Maotran Electronics co., ltd +000000-0FFFFF (base 16) Qingdao Maotran Electronics co., ltd + Room2907, Building 2 of Minghui International, No.39 of Shiling Road, Laoshan District + Qingdao Shandong 266000 + CN + +94-05-BB (hex) LTE-X, Inc +700000-7FFFFF (base 16) LTE-X, Inc + 2-2-20 Higashi-Shinagawa + Shinagawa Tokyo 1400002 + JP + +94-05-BB (hex) BAE Systems +E00000-EFFFFF (base 16) BAE Systems + 21 continental boulevard + Merrimack NH 03054 + US + +F4-90-CB (hex) Cheetah Medical +C00000-CFFFFF (base 16) Cheetah Medical + 2A Hashlosha st. + Tel Aviv 6706055 + IL + +F4-90-CB (hex) A-dec Inc. +B00000-BFFFFF (base 16) A-dec Inc. + 2601 Crestview Drive + Newberg OR 97132 + US + +F4-90-CB (hex) TEQ SA +700000-7FFFFF (base 16) TEQ SA + Via al Municipio 16 + Barbengo Ticino 6917 + CH + +4C-4B-F9 (hex) Shenzhen dingsheng technology co., LTD +400000-4FFFFF (base 16) Shenzhen dingsheng technology co., LTD + Floor 3, building 5, kaijeda industrial zone, no.97, huaxing road, langkou community, dalang street, longhua district + Shenzhen Guangdong 518000 + CN + +4C-4B-F9 (hex) Connected IO +C00000-CFFFFF (base 16) Connected IO + 8304 Esters Boulevard, Suite 850 + Irving TX 75063 + US + +4C-4B-F9 (hex) Zivid AS +800000-8FFFFF (base 16) Zivid AS + Gjerdrums vei 10A + Oslo 0484 + NO + +20-85-93 (hex) Hemina Spa +000000-0FFFFF (base 16) Hemina Spa + Hemina SPA, via Piemonte 2 + Montangnana Padova 35044 + IT + +20-85-93 (hex) Regloplas AG +C00000-CFFFFF (base 16) Regloplas AG + Flurhofstrasse 158c + St. Gallen 9006 + CH + +4C-4B-F9 (hex) Jiangsu acrel Co., Ltd. +100000-1FFFFF (base 16) Jiangsu acrel Co., Ltd. + No. 5, Dongmeng Road, Nanzha Street + Jiangyin City Jiangsu Province 214400 + CN + +4C-4B-F9 (hex) GLONEXS +700000-7FFFFF (base 16) GLONEXS + 3F, 19-14, Doyak-ro 252beon-gil + Bucheon Gyeonggi-do 14531 + KR + +4C-4B-F9 (hex) Remedee Labs +500000-5FFFFF (base 16) Remedee Labs + 35 chemin du vieux chene + Meylan France 38240 + FR + +20-85-93 (hex) Dynaudio +E00000-EFFFFF (base 16) Dynaudio + Sverigesvej 15 + Skanderborg DK-8660 + DK + +84-39-BE (hex) Cheng Du virtual world Technology Limited. +200000-2FFFFF (base 16) Cheng Du virtual world Technology Limited. + 7F, Fang Da building, Ave 12 High-tech Industrial Park, Nanshan Dist + Shenzhen Guangdong 518057 + CN + +24-15-10 (hex) Satellite Link Technology CO.,LTD +E00000-EFFFFF (base 16) Satellite Link Technology CO.,LTD + 1305 ,SED science and technology Building,No.1 science and technology road,Nanshan District + Shenzhen Guangdong 518057 + CN + +20-85-93 (hex) Kloudspot Inc +400000-4FFFFF (base 16) Kloudspot Inc + 1285 Oakmead Parkway + Sunnyvale 94085 + US + +24-15-10 (hex) Shenzhen Xtooltech Co., Ltd +C00000-CFFFFF (base 16) Shenzhen Xtooltech Co., Ltd + 10574 Acacia St, Suite D4 + Rancho Cucamonga CA 91730 + US + +24-15-10 (hex) Safetrust Inc +000000-0FFFFF (base 16) Safetrust Inc + 8112 Mill Creek Rd + Fremont CA 94539 + US + +20-85-93 (hex) Networking Services Corp +100000-1FFFFF (base 16) Networking Services Corp + Bella Vista, Obarrio, Edificio Magna Corp, Mezanine + Panama Panama 33131 + PA + +24-15-10 (hex) Private +800000-8FFFFF (base 16) Private + +24-15-10 (hex) SMaBiT GmbH +100000-1FFFFF (base 16) SMaBiT GmbH + Friedrichstrasse 95 + Berlin 10117 + DE + +98-06-37 (hex) HwaCom Systems Inc. +C00000-CFFFFF (base 16) HwaCom Systems Inc. + 11Fl., No.108, Sec. 1, Hsin-Tai-Wu Rd., Hsi-Chih District + New Taipei New Taipei 221 + TW + +54-9A-11 (hex) Private +F00000-FFFFFF (base 16) Private + +24-15-10 (hex) Unitronux(Shenzhen) Intelligence Technology Co.,Ltd +A00000-AFFFFF (base 16) Unitronux(Shenzhen) Intelligence Technology Co.,Ltd + 7th floor,Building 7,ZhongYunTai industy Park, Tangtou 1st Road,Bao'an District. + Shenzhen Guangdong 518108 + CN + +98-06-37 (hex) Petersime +B00000-BFFFFF (base 16) Petersime + Centrumstraat 125 + Zulte 9870 + BE + +98-06-37 (hex) VR Technology(Shenzhen) Limited +D00000-DFFFFF (base 16) VR Technology(Shenzhen) Limited + Room 201,Huiheng Building,No.12,Gaoxin South 7th Road,Yuehai Steet,Nanshan District + Shenzhen Guangdong 518000 + CN + +98-06-37 (hex) SAMWONTECH +700000-7FFFFF (base 16) SAMWONTECH + YAKDAE-DONG, BUCHEON TECHNO-PARK + BUCHEON-CITY KYUNGGI-DO 14502 + KR + +98-06-37 (hex) Hangzhou Sanxin Network Technology Co.,Ltd +300000-3FFFFF (base 16) Hangzhou Sanxin Network Technology Co.,Ltd + No. 195, Wen Er Road, Xihu District, Xinyuan 11-18F + Hangzhou Zhejiang 310012 + CN + +98-06-37 (hex) NAB co,.LTD +900000-9FFFFF (base 16) NAB co,.LTD + 3-62-30 utukushigaoka aoba-ku + Yokohama-city KANAGAWA-KEN 2250002 + JP + +74-19-F8 (hex) Private +F00000-FFFFFF (base 16) Private + +E4-95-6E (hex) Private +F00000-FFFFFF (base 16) Private + +D0-5F-64 (hex) Shanghai Luying International Trade Co.,Ltd +900000-9FFFFF (base 16) Shanghai Luying International Trade Co.,Ltd + Room 1009 Block 12 No.858 South Huanzhen Road Baoshan District Shanghai City + Shanghai 200442 + CN + +D0-5F-64 (hex) Atoll Solutions Private Limited +500000-5FFFFF (base 16) Atoll Solutions Private Limited + #229, 2nd Floor, 2A Main, 5th Cross, New Thippasandra + Bangalore Karnataka 560075 + IN + +D0-5F-64 (hex) SHANGHAI ZHONGMI COMMUNICATION TECHNOLOGY CO.,LTD +200000-2FFFFF (base 16) SHANGHAI ZHONGMI COMMUNICATION TECHNOLOGY CO.,LTD + RM510,418GuipingRoad.Caohejing Hi-TECH-PARK + SHANGHAI 200233 + CN + +D0-5F-64 (hex) HUAQIN TELECOM HONG KONG LTD +300000-3FFFFF (base 16) HUAQIN TELECOM HONG KONG LTD + Unit 510,5/F, Lincoln Center,20 Yip Fung Street,Fanling + N.T. 999077 + HK + +2C-27-9E (hex) Private +300000-3FFFFF (base 16) Private + +44-D5-F2 (hex) CETC Avionics.L td +800000-8FFFFF (base 16) CETC Avionics.L td + No. 9, baichuan road, high-tech district + Chengdu Sichuan 611731 + CN + +44-D5-F2 (hex) VURO LLC +300000-3FFFFF (base 16) VURO LLC + 1441 Broadway, Suite 5011 + New York NY 10018 + US + +D0-5F-64 (hex) North American Blue Tiger Company, LLC +B00000-BFFFFF (base 16) North American Blue Tiger Company, LLC + 3727 Greenbriar Dr. Suite 119 + Stafford TX 77477 + US + +44-D5-F2 (hex) SIMPLERED TECHNOLOGY LTD. +100000-1FFFFF (base 16) SIMPLERED TECHNOLOGY LTD. + 8F., No.23, Ln. 155, Sec. 3, Beishen Rd., Shenkeng Dist. + New Taipei City 222 + TW + +44-D5-F2 (hex) APPOTRONICS CO., LTD +400000-4FFFFF (base 16) APPOTRONICS CO., LTD + 4th Floor,SZICC,NO.1089,Chaguang Road,Nanshan District, Shenzhen, China + Shenzhen Guangdong 518000 + CN + +44-D5-F2 (hex) TIBA Research & Development (1986) LTD +000000-0FFFFF (base 16) TIBA Research & Development (1986) LTD + 17 Ha'Mefalsim St. Kiryat Arye + Petach Tikva Israel 4951251 + IL + +FC-A4-7A (hex) Broadcom Inc. +000000-0FFFFF (base 16) Broadcom Inc. + Wernerwerkstr. 2 + Regensburg Bavaria 93055 + DE + +FC-A4-7A (hex) Shenzhen Nokelock Technology Co, Ltd. +B00000-BFFFFF (base 16) Shenzhen Nokelock Technology Co, Ltd. + 9th Floor, B Block, Fuhua Technology Building, No 9116 Beihuan Road, Xili Street, Nanshan District, + Shenzhen 518057 + CN + +FC-A4-7A (hex) Token +600000-6FFFFF (base 16) Token + 4545 East River Road, Suite 310 + Henrietta NY 14586 + US + +2C-16-BD (hex) Sunit Oy +400000-4FFFFF (base 16) Sunit Oy + Taitoraitti 1 + Kajaani 87400 + FI + +8C-59-3C (hex) Scharfe-Sicht GmbH +B00000-BFFFFF (base 16) Scharfe-Sicht GmbH + Huttropstraße 60 + Essen Nordrhein-Westfalen 45138 + DE + +8C-59-3C (hex) ecom instruments GmbH +A00000-AFFFFF (base 16) ecom instruments GmbH + Industriestr.2 + Assamstadt Baden-Württemberg 97959 + DE + +8C-59-3C (hex) Shenzhen Tian-Power Technology Co.,Ltd. +E00000-EFFFFF (base 16) Shenzhen Tian-Power Technology Co.,Ltd. + Guangming New District Gongming Office Yulu Community No. 6 Industrial Zone Building 26 + Shenzhen Guangdong 518000 + CN + +B4-A2-EB (hex) QKM Technology(Dongguan)Co.,Ltd +000000-0FFFFF (base 16) QKM Technology(Dongguan)Co.,Ltd + 2F,Block A Building 17,NO. 1,Headquarter,No.4,Xinzhu Road,SSL National Hi-tech Industrial Development Zone + Dongguan Guangdong 523808 + CN + +B4-A2-EB (hex) Kona I +700000-7FFFFF (base 16) Kona I + 4F EXCON Venture-Tower, 3, Eunhaeng-ro, Youngdeungpo-gu, + Seoul 07237 + KR + +2C-D1-41 (hex) Private +F00000-FFFFFF (base 16) Private + +D0-C8-57 (hex) Eco Mobile +700000-7FFFFF (base 16) Eco Mobile + Samoborska cesta 330 + Zagreb Zagreb 10090 + HR + +D0-C8-57 (hex) Mobicon +300000-3FFFFF (base 16) Mobicon + #406, 97, Jungbu-daero 448beon-gil, Yeongtong-gu + Suwon-si Gyeonggi-do 16521 + KR + +60-95-CE (hex) Synamedia +C00000-CFFFFF (base 16) Synamedia + Luipaardstraat 12 + Kortrijk West-Vlaanderen 8500 + BE + +1C-82-59 (hex) ESTec Corporation +A00000-AFFFFF (base 16) ESTec Corporation + 22, Yusangongdan 9-gil + Yangsan Gyeongsangnam-do 50592 + KR + +1C-82-59 (hex) CGI IT UK LIMITED +600000-6FFFFF (base 16) CGI IT UK LIMITED + 20 Fenchurch Street, 14th Floor + London EC3M 3BY + GB + +60-95-CE (hex) Untangle, Inc. +400000-4FFFFF (base 16) Untangle, Inc. + 100 W. San Fernando St., Ste. 565 + San Jose CA 95113 + US + +F0-23-B9 (hex) Private +D00000-DFFFFF (base 16) Private + +B0-FD-0B (hex) IDspire Corporation Ltd. +100000-1FFFFF (base 16) IDspire Corporation Ltd. + 9F, No. 266, Sec. 1, Wenhua Rd., Banqiao Dist. + New Taipei City 22041 + TW + +84-8B-CD (hex) SouXin Corporate +000000-0FFFFF (base 16) SouXin Corporate + 33 Jingyou Road + Nanjing Jiangsu 211100 + CN + +B0-FD-0B (hex) Shenzhen FEIBIT Electronic Technology Co.,LTD +E00000-EFFFFF (base 16) Shenzhen FEIBIT Electronic Technology Co.,LTD + 5th floor,Bld. A1, Lilang Software Park + Shenzhen 518112 + CN + +C8-2C-2B (hex) Smart Wires Inc +C00000-CFFFFF (base 16) Smart Wires Inc + 3292 Whipple Road + Union City CA 94587 + US + +C8-2C-2B (hex) Verifone Systems (China),lnc. +800000-8FFFFF (base 16) Verifone Systems (China),lnc. + 2nd Floor,No.39,Region C, Tongpan Road,Gulou District + fuzhou fujian 350004 + CN + +C8-2C-2B (hex) Fränkische Rohrwerke Gebr. Kirchner GmbH & Co. KG +E00000-EFFFFF (base 16) Fränkische Rohrwerke Gebr. Kirchner GmbH & Co. KG + Hellinger Str. 1 + Königsberg/Bayern 97486 + DE + +C8-2C-2B (hex) Repp Health +200000-2FFFFF (base 16) Repp Health + 1919 14th Street , Suite 700 + Boulder CO 80302 + US + +E4-1E-0A (hex) FireAngel Safety Technology Ltd +A00000-AFFFFF (base 16) FireAngel Safety Technology Ltd + Sir William Lyons Road, Vanguard Centre + Coventry Warwickshire CV4 7EZ + GB + +E4-1E-0A (hex) Avast Software s.r.o. +300000-3FFFFF (base 16) Avast Software s.r.o. + Pikrtova 1737/1a + Prague 4 14000 + CZ + +C8-63-14 (hex) Taylor Dynamometer +E00000-EFFFFF (base 16) Taylor Dynamometer + 3602 W Wheelhouse Rd. + Milwaukee WI 53208 + US + +C8-63-14 (hex) Western Reserve Controls, Inc. +000000-0FFFFF (base 16) Western Reserve Controls, Inc. + 1485 Exeter Dr. + Akron OH 44306 + US + +C8-63-14 (hex) Freeus LLC +C00000-CFFFFF (base 16) Freeus LLC + 640 W 1100 S + Ogden UT 84404 + US + +34-E1-D1 (hex) Genius Pros +700000-7FFFFF (base 16) Genius Pros + Floor 13, Building B, NO. 859 West Shixiang Road, Xihu District, Hangzhou City + Hangzhou 310012 + CN + +34-E1-D1 (hex) ASA Innovation & Technology Ltd. +400000-4FFFFF (base 16) ASA Innovation & Technology Ltd. + Room 506, 5/F, Enterprise Place, No. 5 Science Park West Ave., Hong Kong Science Park + Shatin NT 00000 + HK + +34-E1-D1 (hex) Ningbo Hua Gao Mdt Info Tech Ltd +600000-6FFFFF (base 16) Ningbo Hua Gao Mdt Info Tech Ltd + NO.655,Xueshi Road, Yinzhou District, Ningbo, Zhejiang,China + Ningbo Zhejiang 315100 + CN + +34-E1-D1 (hex) Rinco Ultrasonics AG +300000-3FFFFF (base 16) Rinco Ultrasonics AG + Industriestrasse 4 + Romanshorn Thurgau 8590 + CH + +C8-63-14 (hex) Meyer Electronics Limited +500000-5FFFFF (base 16) Meyer Electronics Limited + 382 Kwun Tong Road + Hong Kong 0000 + HK + +FC-D2-B6 (hex) Silicon (Shenzhen) Electronic Technology Co.,Ltd. +C00000-CFFFFF (base 16) Silicon (Shenzhen) Electronic Technology Co.,Ltd. + 5F, Block A,No. 9 Yuexing 3rd Road, Yuehai Subdistrict Office, Nanshan District + Shenzhen Guangdong 518000 + CN + +FC-D2-B6 (hex) Univer S.p.A. +E00000-EFFFFF (base 16) Univer S.p.A. + Via Eraclito 31 + Milan 20128 + IT + +34-E1-D1 (hex) Apart Audio NV +900000-9FFFFF (base 16) Apart Audio NV + Industriepark Brechtsebaan 8 bus 1 + Schoten 2900 + BE + +FC-D2-B6 (hex) NREAL TECHNOLOGY LIMITED +A00000-AFFFFF (base 16) NREAL TECHNOLOGY LIMITED + RM 1901,19/F LEE GARDEN ONE 33 HYSAN AVENUE CAUSEWAY BAY + HONG KONG 999077 + HK + +74-5B-C5 (hex) Haikou Frun Flash&Mcu Microcontrol Technology Development Co.,Ltd +900000-9FFFFF (base 16) Haikou Frun Flash&Mcu Microcontrol Technology Development Co.,Ltd + 5 floor A1-9, A building, incubation center, Haikou national hi tech Development Zone + Haikou Hainan 570206 + CN + +74-5B-C5 (hex) Smartiply Inc. +B00000-BFFFFF (base 16) Smartiply Inc. + 233 Mt. Airy Road + Basking Ridge NJ 07920 + US + +74-5B-C5 (hex) OXON AG +300000-3FFFFF (base 16) OXON AG + Waldeggstrasse 47 + Liebefeld 3097 + CH + +E4-4C-C7 (hex) HANGZHOU OLE-SYSTEMS CO., LTD +600000-6FFFFF (base 16) HANGZHOU OLE-SYSTEMS CO., LTD + No.35 Jiuhuan Road, Jianggan District , Hangzhou , Zhejiang , China + Hangzhou Zhejiang 310019 + CN + +E4-4C-C7 (hex) Channel Enterprises (HK) Ltd. +700000-7FFFFF (base 16) Channel Enterprises (HK) Ltd. + Room 2006, 20/F., 43-47 Wang Lung Street, + Tsuen Wan NA + HK + +E4-4C-C7 (hex) CE LABS, LLC +500000-5FFFFF (base 16) CE LABS, LLC + 3209 WOOD DRIVE + GARLAND TX 75041 + US + +E0-5A-9F (hex) Shenzhen Rongan Networks Technology Co.,Ltd +B00000-BFFFFF (base 16) Shenzhen Rongan Networks Technology Co.,Ltd + Room 1903, Industrial and Research building of Sun Yat-Sen university,no.1, Yuexing 4th road, Yuehai street,Nanshan district + Shenzhen Guangdong 518057 + CN + +E0-5A-9F (hex) Link of Things Co., Ltd. +300000-3FFFFF (base 16) Link of Things Co., Ltd. + 9F, Park St. 3-2, NanKang Software Park, Taipei, Taiwan + Taipei 115 + TW + +4C-BC-98 (hex) Quake Global Inc +200000-2FFFFF (base 16) Quake Global Inc + 4711 VIEWRIDGE AVE., STE 150 + SAN DIEGO CA 92123 + US + +34-04-9E (hex) Private +900000-9FFFFF (base 16) Private + +38-B8-EB (hex) Private +700000-7FFFFF (base 16) Private + +4C-BC-98 (hex) Dongguan SmartAction Technology Co.,Ltd +B00000-BFFFFF (base 16) Dongguan SmartAction Technology Co.,Ltd + Room1109,Building D,First Place,Nancheng District, Dongguan + Dongguan Guangdong 523000 + CN + +4C-BC-98 (hex) Gronic Systems GmbH +500000-5FFFFF (base 16) Gronic Systems GmbH + Hilpertswiese 7 + Birstein 63633 + DE + +4C-BC-98 (hex) Machine Max +300000-3FFFFF (base 16) Machine Max + Shell Centre + London SE1 7NA + GB + +38-B1-9E (hex) Thrust Networks +600000-6FFFFF (base 16) Thrust Networks + Pangeran Jayakarta 129 No B 7 + Jakarta Jakarta 10730 + ID + +D8-86-0B (hex) Teplovodokhran Ltd. +400000-4FFFFF (base 16) Teplovodokhran Ltd. + Novaya , 51v + Ryazan 390027 + RU + +D8-86-0B (hex) DIGITAL CONCEPTS +900000-9FFFFF (base 16) DIGITAL CONCEPTS + 3108 RIVERPORT TECH CENTER DR + MARYLAND HEIGHTS MO 630434825 + US + +E0-5A-9F (hex) Hale Products +400000-4FFFFF (base 16) Hale Products + 607 NW 27th Ave + Ocala FL 34475 + US + +D8-86-0B (hex) GLO Science +A00000-AFFFFF (base 16) GLO Science + 10 West 37th Street, 1001 + New York NY 10018 + US + +D8-86-0B (hex) SCANMATIK +600000-6FFFFF (base 16) SCANMATIK + Letnaya 18-2 + Mytischi Moscow 141008 + RU + +38-B1-9E (hex) Dallas Delta Corporation +D00000-DFFFFF (base 16) Dallas Delta Corporation + 102 Albert Street + Brunswick East Victoria 3057 + AU + +38-B1-9E (hex) AVO DEVELOPMENT LTD +300000-3FFFFF (base 16) AVO DEVELOPMENT LTD + 179 Shepherds Hill + Romford Essex RM3 0NR + GB + +84-39-BE (hex) HINO ENGINEERING, INC +000000-0FFFFF (base 16) HINO ENGINEERING, INC + 60-7 Takakuramachi + Hachiouji Tokyo 192-0033 + JP + +CC-D3-9D (hex) Glenair +700000-7FFFFF (base 16) Glenair + 1211 Air Way + Glendale CA 91201 + US + +D4-25-CC (hex) EISST Ltd +300000-3FFFFF (base 16) EISST Ltd + 10 Queen Street Place + London EC4R 1AG + GB + +D4-25-CC (hex) E-MetroTel +A00000-AFFFFF (base 16) E-MetroTel + 2828 West Parker Unit B201 + Plano TX 75075 + US + +D4-25-CC (hex) Coperion +E00000-EFFFFF (base 16) Coperion + 590 WOODBURY GLASSBORO RD. + SEWELL NJ 08080 + US + +D4-25-CC (hex) NORDI TELEKOMMUNIKATSIOONI OÜ +000000-0FFFFF (base 16) NORDI TELEKOMMUNIKATSIOONI OÜ + Valukoja 8 + Tallinn city Estonian Republic 11415 + EE + +CC-D3-9D (hex) MagTarget LLC +300000-3FFFFF (base 16) MagTarget LLC + 1300 Reamwood Ave Sunnyvale CA + SUNNYVALE CA 94089 + US + +D4-25-CC (hex) Eware Information Technology com.,Ltd +100000-1FFFFF (base 16) Eware Information Technology com.,Ltd + No.402,Building 5,Software Park,Keji Mid 3nd Road,Nanshan District + Shenzhen Guangdong 518057 + CN + +9C-69-B4 (hex) Teptron AB +900000-9FFFFF (base 16) Teptron AB + Box 1009 + Varberg Halland 43213 + SE + +4C-91-7A (hex) LumiGrow Inc. +400000-4FFFFF (base 16) LumiGrow Inc. + 1480 64th Street, Suite #150 + Emeryville CA 94608 + US + +9C-69-B4 (hex) Skydock do Brasil Ltda +800000-8FFFFF (base 16) Skydock do Brasil Ltda + Rua Gralha Azul, 147 + Quatro Barras PR 83420-000 + BR + +9C-69-B4 (hex) PCI Limited +700000-7FFFFF (base 16) PCI Limited + 35, Pioneer Road North + Singapore 628475 + SG + +6C-DF-FB (hex) AAON +600000-6FFFFF (base 16) AAON + 2425 Yukon Ave + Tulsa OK 74107 + US + +6C-DF-FB (hex) CELL System Co.,Ltd. +B00000-BFFFFF (base 16) CELL System Co.,Ltd. + 1-2-8 Azamino-minami, Aobaku + Yokohama Kanagawa 225-0012 + JP + +4C-91-7A (hex) Camsat Przemysław Gralak +800000-8FFFFF (base 16) Camsat Przemysław Gralak + Ogrodowa 2A + Solec Kujawski Bydgoszcz 86-050 + PL + +4C-91-7A (hex) Hangzhou Hangtu Technology Co.,Ltd. +900000-9FFFFF (base 16) Hangzhou Hangtu Technology Co.,Ltd. + Room A301, no.11, xiyuan eighth road, xihu district + Hangzhou Zhejiang 310000 + CN + +6C-DF-FB (hex) YongTechs Electric Co. Ltd +900000-9FFFFF (base 16) YongTechs Electric Co. Ltd + 18F-8, No.118, Ci-Yun Rd., Hsin Chu 30072, Taiwan(R.O.C.) + Hsin Chu 30072 + TW + +6C-DF-FB (hex) Hardmeier +800000-8FFFFF (base 16) Hardmeier + Pärnu mnt 102 + Tallinn 11312 + EE + +7C-BC-84 (hex) Xuji Changnan Communication Equipment Co., Ltd. +700000-7FFFFF (base 16) Xuji Changnan Communication Equipment Co., Ltd. + No. 2725, Xu You Xi Road + Xuchang Henan 461001 + CN + +7C-BC-84 (hex) OPNT BV +A00000-AFFFFF (base 16) OPNT BV + De Boelelaan 1081 + Amsterdam 1081 HV + NL + +7C-BC-84 (hex) Xiamen Mage Information Technology Co.,Ltd. +100000-1FFFFF (base 16) Xiamen Mage Information Technology Co.,Ltd. + Room 302B, No.40 Guanri Road, Software Park II + Xiamen Fujian 361008 + CN + +7C-BC-84 (hex) Société de Transport de Montréal +600000-6FFFFF (base 16) Société de Transport de Montréal + 800, de La Gauchetière, bureau 8440 + Montréal Québec H5A 1J6 + CA + +98-F9-C7 (hex) ARIMA Communications Corp. +700000-7FFFFF (base 16) ARIMA Communications Corp. + 6F.,No.866,Zhongzheng Rd.,Zhonghe Dist., + New Taipei City Taiwan 23586 + TW + +0C-FE-5D (hex) Beijing WayClouds Technology Co., Ltd. +300000-3FFFFF (base 16) Beijing WayClouds Technology Co., Ltd. + RM501, 5F, DASCOM BD,NO.9 SHANGDI EAST RD, HAIDIAN DISTRICT,BEIJING,CHINA + Beijing 100085 + CN + +98-F9-C7 (hex) MSB Elektronik und Gerätebau GmbH +A00000-AFFFFF (base 16) MSB Elektronik und Gerätebau GmbH + Hofwiesenstr. 23 + Crailsheim 74564 + DE + +6C-5C-3D (hex) Reconova Technologies +B00000-BFFFFF (base 16) Reconova Technologies + B103,Shenzhen Institute of Nanjing University,Keyuan Road,Hi-Tech Park,Nanshan District + Shenzhen Guangdong 518000 + CN + +6C-5C-3D (hex) Syowatsusinkougyo Co.,Ltd. +D00000-DFFFFF (base 16) Syowatsusinkougyo Co.,Ltd. + 35 Ozekiazakitada,Azai-cho + Ichinomiya-City Aichi 491-0101 + JP + +6C-5C-3D (hex) krtkl inc. +A00000-AFFFFF (base 16) krtkl inc. + 350 Townsend Street, Suite 301A + San Francisco CA 94107 + US + +1C-FD-08 (hex) A&B Technology +600000-6FFFFF (base 16) A&B Technology + 81, Geumnam-ro, Buk-gu + Gwangju 61247 + KR + +6C-5C-3D (hex) choyang powertech +C00000-CFFFFF (base 16) choyang powertech + 11. Deoksan-ro 189beon-gil. + ilsan seo-gu. Goyang-si Gyeonggi-do 10205 + KR + +6C-5C-3D (hex) SOUNDKING ELECTRONICS&SOUND CO., LTD. +700000-7FFFFF (base 16) SOUNDKING ELECTRONICS&SOUND CO., LTD. + No.818 Chengxin RoadYinzhou Investment Business Park + Ningbo Zhejiang 315105 + CN + +1C-FD-08 (hex) Beijing Hengxin Rainbow Information Technology Co.,Ltd +500000-5FFFFF (base 16) Beijing Hengxin Rainbow Information Technology Co.,Ltd + 11Floor,north district,newton business building,No.25 Landian factory south road,Haidian District + Beijing Beijing 100097 + CN + +A8-3F-A1 (hex) Exel s.r.l. unipersonale +B00000-BFFFFF (base 16) Exel s.r.l. unipersonale + via di corticella 201 + bologna BO 40128 + IT + +A8-3F-A1 (hex) Guangzhou Tupu Internet Technology Co., Ltd. +300000-3FFFFF (base 16) Guangzhou Tupu Internet Technology Co., Ltd. + 602, No.11, Jiangong Road, Tianhe Software Park, Tianhe District + Guangzhou Guangdong 510665 + CN + +3C-6A-2C (hex) Bosch Automotive Products (Suzhou) Co., Ltd. +200000-2FFFFF (base 16) Bosch Automotive Products (Suzhou) Co., Ltd. + No. 455 Xing Long Street + Suzhou 215000 + CN + +3C-6A-2C (hex) Phytium Technology Co., Ltd. +B00000-BFFFFF (base 16) Phytium Technology Co., Ltd. + Building 5, XinAn Business Square, Haiyuan Middle Road + Binhai New District, Tianjin 300450 + CN + +3C-6A-2C (hex) Qingdao iGuan Technology Co., Ltd. +500000-5FFFFF (base 16) Qingdao iGuan Technology Co., Ltd. + Room416, Science and Technology Park, Ocean University of China, No.23 HongKongEast Road + Qingdao Shandong 266100 + CN + +A8-3F-A1 (hex) Zhejiang Wellsun Intelligent Technology Co.,Ltd. +400000-4FFFFF (base 16) Zhejiang Wellsun Intelligent Technology Co.,Ltd. + No.15,Xingye East 3rd St.,Fuxi District,Tiantai County + Taizhou Zhejiang 317200 + CN + +A8-3F-A1 (hex) Shenzhen BIO I/E Co.,Ltd +D00000-DFFFFF (base 16) Shenzhen BIO I/E Co.,Ltd + Huafan Industrial Park,Building #12, Henggang JianLong Village Industrial Zone, Longgang District + Shenzhen GuangDong province 518115 + CN + +00-55-DA (hex) Private +F00000-FFFFFF (base 16) Private + +30-0A-60 (hex) Newtons4th Ltd +700000-7FFFFF (base 16) Newtons4th Ltd + 1 Bede Island Road + Leicester LE2 7EA + GB + +A4-ED-43 (hex) TOEC TECHNOLOGY CO.,LTD. +E00000-EFFFFF (base 16) TOEC TECHNOLOGY CO.,LTD. + 6 Taishan Road Hexi District Tianjin China + Tian Jin Tian Jin 300211 + CN + +A4-ED-43 (hex) Dongguan Mingji Electronics technology Group Co., Ltd. +300000-3FFFFF (base 16) Dongguan Mingji Electronics technology Group Co., Ltd. + NO.93,188 Industrial Road, Pingshan Village,Tangxia Town, Dongguan city, Guangdong Province , China. + DONGGUAN GUANGDONG 523710 + CN + +A4-ED-43 (hex) leakSMART +C00000-CFFFFF (base 16) leakSMART + 5920 GREENE POINTE DRIVE S GROVEPORT + Groveport OH 43125 + US + +A4-ED-43 (hex) INGELABS S.L. +100000-1FFFFF (base 16) INGELABS S.L. + Av. Juan Lopez Peñalver, 21 + Malaga Malaga 29590 + ES + +A0-28-33 (hex) Kalray S.A. +C00000-CFFFFF (base 16) Kalray S.A. + 180 avenue de l’Europe + Montbonnot Saint Martin 38330 + FR + +84-89-EC (hex) BYDA Co. Ltd., +700000-7FFFFF (base 16) BYDA Co. Ltd., + 4F, KNS Bldg., 8, Gaepo-ro 25 gil, Gangnam-gu + Seoul 06306 + KR + +84-89-EC (hex) SHINKAWA LTD. +C00000-CFFFFF (base 16) SHINKAWA LTD. + Shinjuku Front Tower 32F, 2-21-1 Kitashinjyuku + Shinjuku-ku Tokyo 169-0074 + JP + +9C-F6-DD (hex) AVI Pty Ltd +A00000-AFFFFF (base 16) AVI Pty Ltd + 9 Pitt Way + Booragoon Western Australia 6154 + AU + +30-09-F9 (hex) Punkt Tronics AG +400000-4FFFFF (base 16) Punkt Tronics AG + Via Losanna 4 + Lugano 6900 + CH + +C0-83-59 (hex) Beijing Cloud Fly Technology Development Co.Ltd +600000-6FFFFF (base 16) Beijing Cloud Fly Technology Development Co.Ltd + No. 1703, Zhong An Sheng Ye Building, No. 168 Bei Yuan Road, Chaoyang District, Beijing + Beijing Beijing 100101 + CN + +9C-F6-DD (hex) Capital Engineering & Research Incorporation Ltd. +400000-4FFFFF (base 16) Capital Engineering & Research Incorporation Ltd. + NO.7 JianAnJie, Beijing Economic-Technological Development Area + Beijing 100176 + CN + +9C-F6-DD (hex) KXT Technology Co., Ltd. +700000-7FFFFF (base 16) KXT Technology Co., Ltd. + 3F. No.42, Sec. 2, Chongsin Rd., Sanchong Dist. + New Taipei City 241 + TW + +C0-83-59 (hex) Gardner Denver Thomas GmbH +D00000-DFFFFF (base 16) Gardner Denver Thomas GmbH + Livry-Gargan-Straße 10 + Fürstenfeldbruck Bavaria 82256 + DE + +04-C3-E6 (hex) Amiosec Ltd +D00000-DFFFFF (base 16) Amiosec Ltd + Unit 5 Miller Court + Tewkesbury Gloucestershire GL20 8DN + GB + +04-C3-E6 (hex) Innovusion Inc. +400000-4FFFFF (base 16) Innovusion Inc. + 4920 El Camino Real + Los Altos CA 94022 + US + +04-C3-E6 (hex) SLOC GmbH +800000-8FFFFF (base 16) SLOC GmbH + Nikolaiplatz 4 + Graz Styria 8020 + AT + +B4-4B-D6 (hex) SHENZHEN TITA INTERACTIVE TECHNOLOGY CO.,LTD +100000-1FFFFF (base 16) SHENZHEN TITA INTERACTIVE TECHNOLOGY CO.,LTD + Floor 23, Haowei Technology Mansion,Keji south eighth Road, Gaoxin Sci-Tech. Park(South Zone), + Shenzhen Guangdong 518000 + CN + +D4-7C-44 (hex) LS Communication Co.,Ltd. +500000-5FFFFF (base 16) LS Communication Co.,Ltd. + LS Bldg., Hwachang-ro, 95(Seoksoo-dong), Manan-gu + Anyang-city Gyeonggi-do 13905 + KR + +3C-42-7E (hex) ROBOX SMART MOTION (WUHU) CO.,LTD +D00000-DFFFFF (base 16) ROBOX SMART MOTION (WUHU) CO.,LTD + No.96,Wanchun East Road,Jiujiang Economic Development District,Wuhu,Anhui,China + Wuhu Anhui 241000 + CN + +3C-42-7E (hex) snap40 Ltd +A00000-AFFFFF (base 16) snap40 Ltd + 24 Forth Street + Edinburgh EH1 3LH + GB + +D4-7C-44 (hex) Beijing Maystar Information Technology Co., Ltd. +800000-8FFFFF (base 16) Beijing Maystar Information Technology Co., Ltd. + Building B 5/F,Shangdi Keji Zonghe Building,No.22 Shangdi Information Road, Haidian District + Beijing 100084 + CN + +A0-19-B2 (hex) Ahgora Sistemas SA +E00000-EFFFFF (base 16) Ahgora Sistemas SA + Rodovia José Carlos Daux (SC-401), 600 (Km 01) - ParqTec Alfa - Módulo 08 + Florianópolis Santa Catarina 88030000 + BR + +D4-7C-44 (hex) ASDA ICT Co., Ltd. +600000-6FFFFF (base 16) ASDA ICT Co., Ltd. + 4F-2,No.2,Sec.4,Zhongyang Rd,Tucheng Dist, + New Taipei City 999079 + TW + +2C-48-35 (hex) Scout Security, Inc. +500000-5FFFFF (base 16) Scout Security, Inc. + 210 N Racine Ave, STE 2M + Chicago IL 60607 + US + +A0-19-B2 (hex) MIS Industrie Systeme GmbH & Co. KG +800000-8FFFFF (base 16) MIS Industrie Systeme GmbH & Co. KG + Lohwiese 7 + Scheuring Bavaria 86937 + DE + +A0-19-B2 (hex) Beijing Deephi Intelligent Technology Co., Ltd +200000-2FFFFF (base 16) Beijing Deephi Intelligent Technology Co., Ltd + 7F Building D, Tsinghua Tongfang High-Tech PlazaRoom 1706, Building D-East, Tsinghua Tongfang High-Tech Plaza Haidian District, Beijing, 100083, China + BEIJING HAIDIAN 100083 + CN + +2C-48-35 (hex) Progress Rail Services, Inspection and Information Systems +000000-0FFFFF (base 16) Progress Rail Services, Inspection and Information Systems + 3801-1 South Selsa Road + Independence null 64057 + US + +2C-48-35 (hex) Newtrax Technologies Inc +300000-3FFFFF (base 16) Newtrax Technologies Inc + 360 St-Jacques, Floor 8 + Montreal Quebec H2Y 1P5 + CA + +2C-48-35 (hex) Advanced Electronics Company Ltd +100000-1FFFFF (base 16) Advanced Electronics Company Ltd + POBOX 90916, KKIA INDUSTRIAL ESTATE + RIYADH CENTRAL 11623 + SA + +8C-1C-DA (hex) Septentrio NV +500000-5FFFFF (base 16) Septentrio NV + Interleuvenlaan 15i + Leuven 3001 + BE + +8C-1C-DA (hex) CEOS Pty Ltd +000000-0FFFFF (base 16) CEOS Pty Ltd + 3/17 Burgundy Street, + Heidelberg VIC 3084 + AU + +3C-24-F0 (hex) Sivat Technology Co.,Ltd. +800000-8FFFFF (base 16) Sivat Technology Co.,Ltd. + Room 1602, Starbuilding 2, west Complex of ChangYing TianJie ChaoYang District + BeiJing Beijing 100024 + CN + +8C-1C-DA (hex) Riegl Laser Measurement Systems GmbH +D00000-DFFFFF (base 16) Riegl Laser Measurement Systems GmbH + Riedenburgstraße 48 + Horn Niederösterreich A-3580 + AT + +8C-1C-DA (hex) K Technology Corporation +700000-7FFFFF (base 16) K Technology Corporation + LIVMO Rising Bldg. 5F, 3-19-1 + Shin-Yokohama, Kohoku-ku, Yokohama, Kanagawa 222-0033 + JP + +0C-73-EB (hex) Tiinlab Acoustic Technology (Shenzhen) Co., Ltd. +300000-3FFFFF (base 16) Tiinlab Acoustic Technology (Shenzhen) Co., Ltd. + Tianliao Building F14 East Block (New Materials Industrial Park), Xueyuan Road, Nanshan District, + Shenzhen Guangdong 518055 + CN + +0C-73-EB (hex) D-Link (Shanghai)Limited Corp. +D00000-DFFFFF (base 16) D-Link (Shanghai)Limited Corp. + Registered Address: Part J1, Floor 1, Building 2, No.115, Fute West First Road, China(Shanghai) Pilot Free Trade Zone + Shanghai 200000 + CN + +0C-73-EB (hex) Dinkle Enterprise Co., Ltd. +700000-7FFFFF (base 16) Dinkle Enterprise Co., Ltd. + No.19, Wuquan 2nd Rd., Wugu Dist. + New Taipei City 24890 + TW + +0C-73-EB (hex) Synaccess Networks +B00000-BFFFFF (base 16) Synaccess Networks + 14425 N 79th St., Suite C + Scottsdale AZ 85260 + US + +0C-73-EB (hex) Deltapath, Inc. +200000-2FFFFF (base 16) Deltapath, Inc. + 2107 N 1ST ST, STE 660 + San Jose CA 95131 + US + +0C-73-EB (hex) Pi Innovo LLC +A00000-AFFFFF (base 16) Pi Innovo LLC + 47023 Five Mile Rd + Plymouth MI 48170 + US + +3C-24-F0 (hex) Inter Action Corporation +600000-6FFFFF (base 16) Inter Action Corporation + 14F,Yokohama-Kanazawa High-Tech Center,1-1, + Yokohama Kanagawa 236-0004 + JP + +3C-24-F0 (hex) Siemens AG - Siemens Deutschland Mobility +900000-9FFFFF (base 16) Siemens AG - Siemens Deutschland Mobility + Otto-Hahn-Ring 6 + Munich 81379 + DE + +0C-73-EB (hex) Taiwan Pulse Motion Co., Ltd. +E00000-EFFFFF (base 16) Taiwan Pulse Motion Co., Ltd. + 5F.-11, No. 210, Gongyequ 38th Rd. + Taichung City 40768 + TW + +3C-24-F0 (hex) COMATIS +B00000-BFFFFF (base 16) COMATIS + 8 rue Carnot + SAINT-CYR-L'ECOLE 78210 + FR + +48-65-EE (hex) SmartDisplayer Technology Co., Ltd. +800000-8FFFFF (base 16) SmartDisplayer Technology Co., Ltd. + No. 2-1, Gongjian Rd., Qidu Dist, Keelung City, 20647, Taiwan (R.O.C.) + Keelung 20647 + TW + +48-0B-B2 (hex) Annapurna labs +600000-6FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +48-0B-B2 (hex) Popit Oy +B00000-BFFFFF (base 16) Popit Oy + Metsänneidonkuja 6 + Espoo 02130 + FI + +88-5F-E8 (hex) Sonnet Labs Inc. +300000-3FFFFF (base 16) Sonnet Labs Inc. + 8 The Green Suite #6290 + Dover DE 19901 + US + +88-5F-E8 (hex) Hauch & Bach ApS +500000-5FFFFF (base 16) Hauch & Bach ApS + Femstykket 6 + Lynge 3540 + DK + +88-5F-E8 (hex) Sowee +900000-9FFFFF (base 16) Sowee + 4 place des Vosges + Courbevoie 92400 + FR + +88-5F-E8 (hex) Red Technologies, LLC. +700000-7FFFFF (base 16) Red Technologies, LLC. + 34 Parker + Irvine CA 92618 + US + +F0-41-C8 (hex) Shenzhen Medica Technology Development Co., Ltd. +200000-2FFFFF (base 16) Shenzhen Medica Technology Development Co., Ltd. + 2F Building A, Tongfang Information Harbor, No.11, East Langshan Road, Nanshan District + Shenzhen 518000 + CN + +F0-41-C8 (hex) Shanghai Think-Force Electronic Technology Co. Ltd +C00000-CFFFFF (base 16) Shanghai Think-Force Electronic Technology Co. Ltd + North ZhongShan Road, No. 3000, Room 2608 + Shanghai 200000 + CN + +F0-41-C8 (hex) Shenzhen Umind Technology Co., Ltd. +E00000-EFFFFF (base 16) Shenzhen Umind Technology Co., Ltd. + Add: D2-6A, TCL Science Park, 1001 ZhongshanYuan Road, Nanshan District + Shenzhen Guangdong 581055 + CN + +40-A3-6B (hex) SKS-Kinkel Elektronik GmbH +400000-4FFFFF (base 16) SKS-Kinkel Elektronik GmbH + Im Industriegebiet 9 + Hof 56472 + DE + +30-1F-9A (hex) MICOMSOFT CO.,LTD. +300000-3FFFFF (base 16) MICOMSOFT CO.,LTD. + 6F,KEIHAN-YODOYABASHI BLDG., 3-2-25,KITAHAMA,CHUO-KU + osaka 541-0041 + JP + +30-1F-9A (hex) HUNAN CHANGSHA HENGJIAN TECHNOLDGY DEVELPMENT CO.,LTD. +A00000-AFFFFF (base 16) HUNAN CHANGSHA HENGJIAN TECHNOLDGY DEVELPMENT CO.,LTD. + Jiayun Road 209 + Changsha Hunan 410205 + CN + +88-A9-A7 (hex) Sieper Lüdenscheid GmbH & Co. KG +600000-6FFFFF (base 16) Sieper Lüdenscheid GmbH & Co. KG + Schlittenbacher Straße 60 + Lüdenscheid 58511 + DE + +A4-DA-22 (hex) SolidPro Technology Corporation +800000-8FFFFF (base 16) SolidPro Technology Corporation + 10F.-1, No.150, Jian 1st Rd. + Zhonghe Dist. New Taipei City 23511 + TW + +DC-E5-33 (hex) SAN Engineering +700000-7FFFFF (base 16) SAN Engineering + 434-31 UTO Korea BD. 4F + Seongnam-si Jungwon-gu Gyunggi-do 13230 + KR + +DC-E5-33 (hex) ShenZhen C&D Electronics CO.Ltd. +300000-3FFFFF (base 16) ShenZhen C&D Electronics CO.Ltd. + 9th FIoor, Building 9, No.1 Qingxiang road, BaoNeng Science and TechnoIogy Industrial Park, Longhua New District + ShenZhen GuangDong 518000 + CN + +C4-FF-BC (hex) KAGA ELECTRONICS CO.,LTD. +B00000-BFFFFF (base 16) KAGA ELECTRONICS CO.,LTD. + 20 Kandamatsunaga-cho + Chiyoda-ku TOKYO 101-8627 + JP + +9C-43-1E (hex) Wireless Environment, LLC +400000-4FFFFF (base 16) Wireless Environment, LLC + 600 Beta Drive Unit 100 Mayfield Village, OH 44143,US + Mayfield Village OH 44143 + US + +9C-43-1E (hex) Symfun Telecom Ltd +100000-1FFFFF (base 16) Symfun Telecom Ltd + Floor 4 Building 11 Xi Qi Dian Jia Yuan + Beijing 100083 + CN + +9C-43-1E (hex) Optris GmbH +700000-7FFFFF (base 16) Optris GmbH + Ferdinand-Buisson-Str. 14 + Berlin 13127 + DE + +2C-D1-41 (hex) Private +D00000-DFFFFF (base 16) Private + +28-2C-02 (hex) Shenzhen emb-star technology co. LTD +200000-2FFFFF (base 16) Shenzhen emb-star technology co. LTD + 2/f,building C,qinghu science park,qingxiang road,qinghu,longhua new district + shenzhen Guangdong 518131 + CN + +F8-B5-68 (hex) Whizpace Pte. Ltd. +B00000-BFFFFF (base 16) Whizpace Pte. Ltd. + 77 Ayer Rajah Crescent, #02-30 + Singapore 139954 + SG + +F8-B5-68 (hex) Maven Wireless AB +800000-8FFFFF (base 16) Maven Wireless AB + Torshamnsgatan 35 + KISTA 164 40 + SE + +40-48-FD (hex) Cloud4Wi +700000-7FFFFF (base 16) Cloud4Wi + 22 Cleveland St + San Francisco null 94103 + US + +40-48-FD (hex) Ecotap B.V. +C00000-CFFFFF (base 16) Ecotap B.V. + Industrieweg 4 + Boxtel 5281RW + NL + +40-48-FD (hex) Swarco Technology ApS +600000-6FFFFF (base 16) Swarco Technology ApS + C. F. Tietgens Boulevard 25 + Odense SØ Danmark 5220 + DK + +40-48-FD (hex) MITHRAS Technology Co., LTD +200000-2FFFFF (base 16) MITHRAS Technology Co., LTD + 4F.-3, No. 880, Zhongzheng Rd., Zhonghe Dist., + New Taipei 23586 + TW + +38-73-EA (hex) Light Blue Optics Ltd. +400000-4FFFFF (base 16) Light Blue Optics Ltd. + St John's Innovation Centre, Cowley Road + Cambridge Cambridgeshire CB40WS + GB + +EC-9F-0D (hex) CRRC QINGDAO SIFANG ROLLING STOCK RESEARCH INSTITUTE CO.,LTD +B00000-BFFFFF (base 16) CRRC QINGDAO SIFANG ROLLING STOCK RESEARCH INSTITUTE CO.,LTD + No.231 Ruichang Road Qingdao City + Qingdao Shandong 266000 + CN + +38-73-EA (hex) ISTCONTROL +500000-5FFFFF (base 16) ISTCONTROL + #1203, 37 Maebongsan-ro, Mapo-gu + Seoul 03909 + KR + +EC-9F-0D (hex) flexlog GmbH +A00000-AFFFFF (base 16) flexlog GmbH + Zur Gießerei 4 + Karlsruhe 76227 + DE + +34-D0-B8 (hex) Skytech Creations Limited +900000-9FFFFF (base 16) Skytech Creations Limited + Flat F, 23/F., Block 2, Kingswin Industrial Building, 32-50 Lei Muk Road + Kwai Chung 000000 + HK + +34-D0-B8 (hex) Glory Mark Electronic Ltd. Taiwan Branch (B.V.I.) +C00000-CFFFFF (base 16) Glory Mark Electronic Ltd. Taiwan Branch (B.V.I.) + 3F, No. 6, Lane 148, Li De St., Chungho Dist. + New Taipei City Taiwan 235 + TW + +34-D0-B8 (hex) EQPlay Intelligent Technology(Kunshan) Co,Ltd. +400000-4FFFFF (base 16) EQPlay Intelligent Technology(Kunshan) Co,Ltd. + No. 58 Xinnengyuan Road, Yushan Town, Kunshan + Kunshan Jiangsu 215300 + CN + +AC-1D-DF (hex) Sichuan Odot Automation System Co.,Ltd. +800000-8FFFFF (base 16) Sichuan Odot Automation System Co.,Ltd. + No.6,Hongsheng Street + MianYang SiChuan 621102 + CN + +AC-1D-DF (hex) ConectaIP Tecnologia S.L. +200000-2FFFFF (base 16) ConectaIP Tecnologia S.L. + Novell 58, 4.2 + Barcelona 08014 + ES + +34-D0-B8 (hex) NTX Embedded +D00000-DFFFFF (base 16) NTX Embedded + 4275 Kellway Circle, Suite #106 + Addison TX 75001 + US + +AC-1D-DF (hex) Solare Datensysteme GmbH +900000-9FFFFF (base 16) Solare Datensysteme GmbH + Fuhrmannstraße 9 + Geislingen-Binsdorf Baden-Wuerttemberg 72351 + DE + +CC-22-37 (hex) Tolomatic, Inc. +B00000-BFFFFF (base 16) Tolomatic, Inc. + 3800 County Road 116 + Hamel MN 55340 + US + +74-1A-E0 (hex) ITS Partner (O.B.S) S.L. +E00000-EFFFFF (base 16) ITS Partner (O.B.S) S.L. + Av. Corts Catalanes 9-11 + Sant Cugat del Valles Barcelona 08173 + ES + +CC-22-37 (hex) MANUFACTURAS Y TRANSFORMADOS AB, S.L. +E00000-EFFFFF (base 16) MANUFACTURAS Y TRANSFORMADOS AB, S.L. + SANT ANTONI DE BAIX, 110-112 + IGUALADA BARCELONA 08700 + ES + +74-1A-E0 (hex) BÄR Bahnsicherung AG +700000-7FFFFF (base 16) BÄR Bahnsicherung AG + Luppmenstrasse 3 + Fehraltorf 8320 + CH + +74-1A-E0 (hex) Broadcast Wireless Systems Ltd +800000-8FFFFF (base 16) Broadcast Wireless Systems Ltd + Unit 9, Swanwick Business Centre, Bridge Road + Southampton Hampshire SO31 7GB + GB + +04-71-4B (hex) Shenzhen WayOS Technology Crop., Ltd. +200000-2FFFFF (base 16) Shenzhen WayOS Technology Crop., Ltd. + F18, Yousong Business Building, Longhua New Districe, Shenzhen, China + Shenzhen Guangdong 518109 + CN + +CC-22-37 (hex) Apeiron Data Systems +200000-2FFFFF (base 16) Apeiron Data Systems + 81 Blue Ravine Road + Folsom CA 95630 + US + +2C-27-9E (hex) Amaryllo International Inc. +E00000-EFFFFF (base 16) Amaryllo International Inc. + 4F, No. 159, Xianzheng 9th Rd., + ZUHUBEI CITY HSINCHU COUNTY 302 + TW + +2C-27-9E (hex) octoScope, Inc. +900000-9FFFFF (base 16) octoScope, Inc. + 305 Foster Street, #104 + Littleton MA 01460 + US + +2C-27-9E (hex) Institut Dr. Foerster GmbH & Co. KG +800000-8FFFFF (base 16) Institut Dr. Foerster GmbH & Co. KG + In Laisen 70 + Reutlingen 72766 + DE + +CC-22-37 (hex) SHENZHEN HOOENERGY TECHNOLOGY CO.,LTD +D00000-DFFFFF (base 16) SHENZHEN HOOENERGY TECHNOLOGY CO.,LTD + NO.5C3-5,BLOCK CD,TIANZHANDASHA,FUTIAN DISTRICT + SHENZHEN 518000 + CN + +2C-27-9E (hex) Shijiazhuang King Transportation Equipment Co.,Ltd +400000-4FFFFF (base 16) Shijiazhuang King Transportation Equipment Co.,Ltd + No.255 Changjiang Road + Shijiazhuang Hebei 050000 + CN + +18-9B-A5 (hex) Shenzhen Tong Tai Yi information Technology Co.,Ltd +800000-8FFFFF (base 16) Shenzhen Tong Tai Yi information Technology Co.,Ltd + District C,3rd Floor,Bldg B1,Digital Tech Park,7th GaoXin South Blvd,Tech Park,NanShan,ShenZhen,China + shenzhen guangdong 518102 + CN + +84-39-BE (hex) ShenZhen Fudeyu Technology co.,Ltd +300000-3FFFFF (base 16) ShenZhen Fudeyu Technology co.,Ltd + 1st Floor, Building C, No.3 Jinyuan Road, Heao Strict, Henggang Street, Longgang Area, Shenzhen. + Shenzhen Guangdong province 518115 + CN + +18-9B-A5 (hex) PHINETWORKS +300000-3FFFFF (base 16) PHINETWORKS + 412, Woorim E-Biz Center 2, Digital ro 33 gil + Seoul Guro gu 08377 + KR + +34-29-8F (hex) Nanjing Sandemarine Electric Co.,Ltd +800000-8FFFFF (base 16) Nanjing Sandemarine Electric Co.,Ltd + Room 202, D Building, No.2 Dongda Road, Pukou District, Nanjing, Jiangsu Province, P.R.China + Nanjing Jiangsu 210032 + CN + +90-4E-91 (hex) SKODA ELECTRIC a.s. +D00000-DFFFFF (base 16) SKODA ELECTRIC a.s. + Tylova 1/57 + Plzen 301 28 + CZ + +18-9B-A5 (hex) APANA Inc. +900000-9FFFFF (base 16) APANA Inc. + 4290 Pacific Hwy A + Bellingham WA 98226 + US + +90-4E-91 (hex) Wrtnode technology Inc. +400000-4FFFFF (base 16) Wrtnode technology Inc. + Dingsi Lu #18, Shahe, Changping Dist. + Beijing 102209 + CN + +34-29-8F (hex) Schnick-Schnack-Systems GmbH +B00000-BFFFFF (base 16) Schnick-Schnack-Systems GmbH + Mathias-Brüggen Str. 79 + Koeln 50829 + DE + +34-29-8F (hex) Chengdu Meross Technology Co., Ltd. +100000-1FFFFF (base 16) Chengdu Meross Technology Co., Ltd. + No. 25, Yizhou Avenue, Gaoxin + Chengdu Sichuan 610000 + CN + +34-29-8F (hex) Bellman & Symfon +600000-6FFFFF (base 16) Bellman & Symfon + Södra Långebergsgatan 30 + Västra Frölunda 42132 + SE + +34-00-8A (hex) SHENZHEN WXL ELECTRONICS CO., LTD. +E00000-EFFFFF (base 16) SHENZHEN WXL ELECTRONICS CO., LTD. + Internet Industry Base,Baoyuan Road,Bao'an District + Shenzhen 518100 + CN + +34-00-8A (hex) Project Engineering srl +B00000-BFFFFF (base 16) Project Engineering srl + Via Colle Ramole 11 + Impruneta FI 50023 + IT + +34-29-8F (hex) Virtual Trunk Pte Ltd +A00000-AFFFFF (base 16) Virtual Trunk Pte Ltd + 12 Kallang Avenue + Aperia #04-30 339511 + SG + +34-29-8F (hex) Beijing Vorx Telecommunications Co., Ltd. +300000-3FFFFF (base 16) Beijing Vorx Telecommunications Co., Ltd. + No.3 Minzhuang Rd, Haidian District + Beijing 100195 + CN + +34-00-8A (hex) Angee Technologies Ltd. +000000-0FFFFF (base 16) Angee Technologies Ltd. + City House, 3 Cranwood Street + London EC1V 9PE + GB + +78-D8-00 (hex) Shenzhen Envicool Information Technology Co., Ltd +100000-1FFFFF (base 16) Shenzhen Envicool Information Technology Co., Ltd + Building 9, Hongxin Industrial Park, Guanlan, Longhua District, + Shenzhen Guangdong 518110 + CN + +78-D8-00 (hex) Shenzhen Scodeno Technology Co,. Ltd. +300000-3FFFFF (base 16) Shenzhen Scodeno Technology Co,. Ltd. + New Longhua District,Guanlan rich Industrial Zone No. 22,Silicon Valley Power Digital Industrial Park A6 Building 2 floor + Shenzhen Guangdong 518110 + CN + +78-D8-00 (hex) Shenzhen Chenzhuo Technology Co., Ltd. +C00000-CFFFFF (base 16) Shenzhen Chenzhuo Technology Co., Ltd. + 301,3/F,Longtangge,1183 Liuxian Avenue,Nanshan + Shenzhen Guangdong 518055 + CN + +78-D8-00 (hex) Salunda Ltd +800000-8FFFFF (base 16) Salunda Ltd + 6 Avonbury Business Park, Howes Lane + Bicester Oxon Ox26 2UA + GB + +7C-BA-CC (hex) ALPHA TECHNOLOGIES, LLC +E00000-EFFFFF (base 16) ALPHA TECHNOLOGIES, LLC + 3030 GILCHRIST ROAD + AKRON OH 44305 + US + +7C-BA-CC (hex) Flying Loft Inc. +C00000-CFFFFF (base 16) Flying Loft Inc. + Rm. 1602, 16th floor, JNK Digital Tower 111 + Seoul 08390 + KR + +F8-8A-3C (hex) Avateq Corp. +E00000-EFFFFF (base 16) Avateq Corp. + 3555 - 14th Ave., Unit 18 + Markham ON L3R 0H5 + CA + +40-A3-6B (hex) SFT Co., Ltd. +800000-8FFFFF (base 16) SFT Co., Ltd. + 2-7-11 + Yamato-shi Fukaminishi 242-0018 + JP + +4C-65-A8 (hex) High Infinity Germany +E00000-EFFFFF (base 16) High Infinity Germany + Freiburgerstr. 9 + Emmendingen Deutschland 79312 + DE + +4C-65-A8 (hex) Nuviz Oy +600000-6FFFFF (base 16) Nuviz Oy + Joensuunkatu 7 + Salo 24100 + FI + +F8-8A-3C (hex) FARA AS +B00000-BFFFFF (base 16) FARA AS + Sjøgangen 4 + Trondheim NO-7010 + NO + +F8-8A-3C (hex) ART SPA +000000-0FFFFF (base 16) ART SPA + VOC.PISCHIELLO, 20 + PASSIGNANO SUL TRASIMENO PG 06065 + IT + +8C-14-7D (hex) Nanjing bilian information Technology Co.,Ltd. +400000-4FFFFF (base 16) Nanjing bilian information Technology Co.,Ltd. + Room 407,Building 1,No.8.Huayuan Road,Xuanwu District,Nanjing + Nanjing Jiangsu 210000 + CN + +8C-14-7D (hex) Bluemega Document & Print Services +A00000-AFFFFF (base 16) Bluemega Document & Print Services + 1 Allée de Londres - Batiment Les Bénares + Villejust Essonne 91140 + FR + +4C-65-A8 (hex) Instant Byte, S.L. +800000-8FFFFF (base 16) Instant Byte, S.L. + Calle Julio Palacios, 10 Naves 1-5, Pol. Ind. Ntra. Sra. de Butarque + Leganés Madrid 28914 + ES + +4C-65-A8 (hex) Orica Europe Pty Ltd & Co KG +200000-2FFFFF (base 16) Orica Europe Pty Ltd & Co KG + Muelheimer Strasse 5 + Troisdorf NRW 53840 + DE + +A0-C5-F2 (hex) UnaliWear, Inc. +D00000-DFFFFF (base 16) UnaliWear, Inc. + 3410 Cherry Lane + Austin TX 78703 + US + +A0-C5-F2 (hex) Impulse Networks Pte Ltd +900000-9FFFFF (base 16) Impulse Networks Pte Ltd + 1 Raffles Place, #44-08 Raffles Place + Singapore 048616 + SG + +50-FF-99 (hex) IPC Global +400000-4FFFFF (base 16) IPC Global + 4 Wadhurst Drive + Boronia Victoria 3155 + AU + +A0-C5-F2 (hex) CoolR Group Inc +800000-8FFFFF (base 16) CoolR Group Inc + 14100 Parke Long Ct Suite I + Chantilly VA 20151 + US + +A0-C5-F2 (hex) Glooko inc +C00000-CFFFFF (base 16) Glooko inc + 899 W. Evelyn Avenue + Mountain View CA 94041 + US + +F0-23-B9 (hex) Xiamen Jinhaode Electronic Co.,Ltd +600000-6FFFFF (base 16) Xiamen Jinhaode Electronic Co.,Ltd + 2003# Fuyu Build, Changqing Road 536, Siming + Xiamen Fujian 361009 + CN + +F0-23-B9 (hex) Aquametro AG +000000-0FFFFF (base 16) Aquametro AG + Ringstr. 75 + Therwil 4106 + CH + +F0-23-B9 (hex) G3 TECHNOLOGIES< INC +800000-8FFFFF (base 16) G3 TECHNOLOGIES< INC + 2904 BACK ACRE CIRCLE, STE 107 + MOUNT AIRY MD 21771 + US + +04-71-4B (hex) Gimso Mobile Ltd +E00000-EFFFFF (base 16) Gimso Mobile Ltd + 16 Hatidhar St + Raanana 4366518 + IL + +F0-23-B9 (hex) EZVIS LIMITED +400000-4FFFFF (base 16) EZVIS LIMITED + FLAT/RM 1605A Ho KING COMMERCIAL CENTRE 2-16 FA YUEN STREET + HONGKONG 999077 + HK + +60-D7-E3 (hex) Avalun +000000-0FFFFF (base 16) Avalun + 7 parvis louis neel + grenoble 38000 + FR + +60-D7-E3 (hex) Wilderness Labs Inc. +A00000-AFFFFF (base 16) Wilderness Labs Inc. + 700 Edgewater Blvd., #108 + Foster City CA 94404 + US + +60-D7-E3 (hex) Revol Technologies inc +500000-5FFFFF (base 16) Revol Technologies inc + 5336 Queen Mary Cote-St-Lu, APT#5 + montreal QC H3X1T8 + CA + +60-D7-E3 (hex) SKS Automaatio oy +300000-3FFFFF (base 16) SKS Automaatio oy + Martinkylantie 50 + Vantaa 01720 + FI + +08-ED-02 (hex) D2SLink Systems +000000-0FFFFF (base 16) D2SLink Systems + 47 Rue Marcel Dassault + Boulogne Billancourt 92514 + FR + +08-ED-02 (hex) Imperx, Inc +100000-1FFFFF (base 16) Imperx, Inc + 6421 Congress Avenue + Boca Raton FL 33487 + US + +98-AA-FC (hex) Comarch S.A. +E00000-EFFFFF (base 16) Comarch S.A. + Al. Jana Pawla II 39A + Krakow Poland 31-864 + PL + +98-AA-FC (hex) BEAM Authentic +900000-9FFFFF (base 16) BEAM Authentic + 25 Tamalpais Avenue, Suite C + San Anselmo CA 94960 + US + +98-AA-FC (hex) dots Inc. +C00000-CFFFFF (base 16) dots Inc. + 10F WiL Office, Izumi Garden Tower, 1-6-1 Roppongi, Minatoku + Tokyo Tokyo 1066010 + JP + +14-4F-D7 (hex) D&S Cable Industries (HK) Limited +C00000-CFFFFF (base 16) D&S Cable Industries (HK) Limited + 11th Floor,AXA Centre, 151 Gloucester Road Hong Kong + HONGKONG 999077 + CN + +14-4F-D7 (hex) FedEx Services OTI +200000-2FFFFF (base 16) FedEx Services OTI + 920 W Poplar Ave, Suite 101 + Collierville TN 38017 + US + +14-4F-D7 (hex) Annapurna labs +000000-0FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +F8-02-78 (hex) BETTINI SRL +700000-7FFFFF (base 16) BETTINI SRL + VIA CESARE BATTISTI 22 + CESANO MADERNO MILAN 20031 + IT + +14-4F-D7 (hex) NPort Networks Inc., +800000-8FFFFF (base 16) NPort Networks Inc., + 9F No. 242 BaoAi street, ShuLin District, + New Taipei Taiwan 23845 + TW + +14-4F-D7 (hex) Zehnder Group AG +100000-1FFFFF (base 16) Zehnder Group AG + Moortalstrasse 1 + Gränichen CH-5722 + CH + +A4-11-63 (hex) Dspread Technology (Beijing) Inc. +800000-8FFFFF (base 16) Dspread Technology (Beijing) Inc. + Jingxin Building, 2045 Suite , Chaoyang District + Beijing 100027 + CN + +A4-11-63 (hex) Pax +300000-3FFFFF (base 16) Pax + 4 cresswell gardens + london England sw5 0bj + GB + +1C-A0-D3 (hex) Dynamic Connect (Suzhou) Hi-Tech Electronic Co.,Ltd. +500000-5FFFFF (base 16) Dynamic Connect (Suzhou) Hi-Tech Electronic Co.,Ltd. + Unit C&D, No.201 WuXiang, Export Processing Zone A No.200Suhong Road SIP + Suzhou JiangSu 215021 + CN + +1C-A0-D3 (hex) NPO TELECOM JSC +400000-4FFFFF (base 16) NPO TELECOM JSC + 31, Votkinskoe shosse str. + Izhevsk Udmurtia 426039 + RU + +1C-A0-D3 (hex) Intertecno SRL NISUTA +600000-6FFFFF (base 16) Intertecno SRL NISUTA + Av. Belgrano 1209 + Capital Federal Buenos Aires 1093 + AR + +1C-A0-D3 (hex) SAVELEC +300000-3FFFFF (base 16) SAVELEC + rue de la houille blanche + HERMILLON SAVOIE 73300 + FR + +40-F3-85 (hex) KATO ENGINEERING INC. +500000-5FFFFF (base 16) KATO ENGINEERING INC. + 2075 HOWARD DRIVE WEST + NORTH MANKATO MN 56003 + US + +40-F3-85 (hex) BBB Inc. +E00000-EFFFFF (base 16) BBB Inc. + 28, Yatap-ro, Bundang-gu + Seongnam-si Gyeonggi-do 13522 + KR + +8C-C8-F4 (hex) ITECH Electronic Co.,ltd. +400000-4FFFFF (base 16) ITECH Electronic Co.,ltd. + No.108, XiShanqiao Nanlu + Nanjing Jiangsu 210039 + CN + +34-04-9E (hex) ND SatCom GmbH +E00000-EFFFFF (base 16) ND SatCom GmbH + Graf-von-Soden-Straße + Immenstaad Baden-Württemberg 88090 + DE + +34-04-9E (hex) Seeiner Technology Co.,LTD +500000-5FFFFF (base 16) Seeiner Technology Co.,LTD + floor 6,Building 14,No.1008 Xiangwang street,Hangzhou City,Zhejiang province + hangzhou 311121 + CN + +34-04-9E (hex) Nanjing Mythware Information Technology Co., Ltd. +300000-3FFFFF (base 16) Nanjing Mythware Information Technology Co., Ltd. + Level 13, Unit 3, Zijin Entrepreneur R&D Centre, No.89 Shengli Road, Jiangning District + Nanjing Jiangsu 211106 + CN + +A4-58-0F (hex) Finetree Communications Inc +E00000-EFFFFF (base 16) Finetree Communications Inc + #406, Shinyatap Prugiocity2, Yanghyunro 405 + Seungnamsi 13439 + KR + +7C-CB-E2 (hex) Easy Broadband Technology Co., Ltd. +B00000-BFFFFF (base 16) Easy Broadband Technology Co., Ltd. + 3rd Floor, Jinyanlong Building, Xisanqi Bridge, Haidian District, Beijing 100096, China + Beijing Beijing 100096 + CN + +7C-CB-E2 (hex) Hangzhou Kaicom Communication Co.,Ltd +700000-7FFFFF (base 16) Hangzhou Kaicom Communication Co.,Ltd + 12th Floor,Block B CONBA Building,No.288 jiangnan Avenue , Binjiang District, Hangzhou, China + Hangzhou Zhejiang 310051 + CN + +50-0B-91 (hex) Shenzhen Lucky Sonics Co .,Ltd +D00000-DFFFFF (base 16) Shenzhen Lucky Sonics Co .,Ltd + 201A, BLOCK 10 ROW 1, SHANGTUN VILLAGE HESHUIKOU COMMUNITY,GO NGMING STREET, GUANGMING DISTRICT + SHENZHEN GUANGDONG 518107 + CN + +A4-58-0F (hex) CoAsia Microelectronics Corp. +500000-5FFFFF (base 16) CoAsia Microelectronics Corp. + 13F, No. 3-2, Park St. Nangang District + Taipei 11503 + TW + +50-0B-91 (hex) Shenzhen zhong ju Fiber optical Co.Ltd +E00000-EFFFFF (base 16) Shenzhen zhong ju Fiber optical Co.Ltd + 3t Floor Build A .jin he Rui park .guan lan. + Shen zhen Guang dong 518000 + CN + +A4-58-0F (hex) Shenzhen City billion Leiden science and Technology Co., Ltd. +400000-4FFFFF (base 16) Shenzhen City billion Leiden science and Technology Co., Ltd. + Shenzhen City, Baoan District Songgang Street Community Goodrich Tantou Industrial Park plant building 2 + Shenzhen City Guangdong Province 518000 + CN + +1C-C0-E1 (hex) Videri Inc. +400000-4FFFFF (base 16) Videri Inc. + 541 West 23rd Street + New York NY 10011 + US + +50-0B-91 (hex) Diamond Traffic Products, Inc +C00000-CFFFFF (base 16) Diamond Traffic Products, Inc + 76433 Alder Street + Oakridge OR 97463 + US + +7C-CB-E2 (hex) Heyuan Yongyida Technology Holdings Co.,Ltd. +000000-0FFFFF (base 16) Heyuan Yongyida Technology Holdings Co.,Ltd. + Xin Yong Yi Science Park, GaoXin 3rd Road, High-tech Zone + Heyuan Guangdong 517000 + CN + +7C-CB-E2 (hex) Astrum Technologies CC +300000-3FFFFF (base 16) Astrum Technologies CC + Unit 49, Sandton View Office Park, 1 Conduit Str, Lyme Park + Johannesburg Gauteng 2060 + ZA + +24-4E-7B (hex) Tekelek Europe Ltd +000000-0FFFFF (base 16) Tekelek Europe Ltd + Unit 118 Shannon Free zone + Shannon Co. Clare + IE + +7C-CB-E2 (hex) CeoTronics AG +100000-1FFFFF (base 16) CeoTronics AG + Adam-Opel-Str. 6 + Roedermark Hessen 63322 + DE + +24-4E-7B (hex) Shenzhen AWT science & technology limited +A00000-AFFFFF (base 16) Shenzhen AWT science & technology limited + 22E of Huari Building,Nanhua Garden,South Of Huaqiang Road,Futian Area + Shenzhen 518057 + CN + +4C-E1-73 (hex) DAIKOKU DENKI CO.,LTD. +600000-6FFFFF (base 16) DAIKOKU DENKI CO.,LTD. + 1-43-5 Nagono Nakamura-ku + Nagoya Aichi 450-8640 + JP + +48-65-EE (hex) EnBW Energie Baden-Württemberg AG +B00000-BFFFFF (base 16) EnBW Energie Baden-Württemberg AG + Durlacher Allee 93 + Karlsruhe 76131 + DE + +48-65-EE (hex) Gopod Group Limited +100000-1FFFFF (base 16) Gopod Group Limited + 5-6/f,building 8,Lianjian Industrial Park,Longhua + Shenzhen 518109 + CN + +24-4E-7B (hex) UniMAT Automation Technology Co., Ltd. +900000-9FFFFF (base 16) UniMAT Automation Technology Co., Ltd. + 5/F, Building 15&16, Wisdomland Business Park, Road 2 Nantou port, Nanshan District + Shenzhen Guangdong 518052 + CN + +48-65-EE (hex) Winn Technology Co.,Ltd +D00000-DFFFFF (base 16) Winn Technology Co.,Ltd + Winn Tech Industrial Park Xianghe Rd.Xinmin Area,Chang an,Dongguan City Guangdong Province,China. + Dongguan Guangdong 523879 + CN + +48-65-EE (hex) Data Technology Inc. +300000-3FFFFF (base 16) Data Technology Inc. + Tachikawa Nishiki-cho Bldg 8F, 1-8-7 Nishiki-cho + Tachikawa-shi Tokyo 190-0022 + JP + +4C-E1-73 (hex) Nanjing Tongke Technology Development Co., LTD +800000-8FFFFF (base 16) Nanjing Tongke Technology Development Co., LTD + 8 Taishan Road jianye + Nanjing 210000 + CN + +1C-C0-E1 (hex) HANGZHOU SOFTEL OPTIC CO., LTD +300000-3FFFFF (base 16) HANGZHOU SOFTEL OPTIC CO., LTD + 101 BINKANG ROAD, BINJIANG DISTRICT + HANGZHOU ZHEJIANG 310052 + CN + +4C-E1-73 (hex) Huizhou Dehong Technology Co., Ltd. +400000-4FFFFF (base 16) Huizhou Dehong Technology Co., Ltd. + Dongxing + Huizhou Guangdong 516210 + CN + +4C-E1-73 (hex) Shanghai Ehong Technology Co.,Ltd +B00000-BFFFFF (base 16) Shanghai Ehong Technology Co.,Ltd + RM1505,blk 1st,No.833 South Hongmei Road Minhang Dis + Shanghai shanghai 200237 + CN + +AC-64-DD (hex) DIGIBIRD TECHNOLOGY CO., LTD. +E00000-EFFFFF (base 16) DIGIBIRD TECHNOLOGY CO., LTD. + LONGGUAN BUSINESS CENTER, SUITE 501. HUILONGGUAN W., ST., CHANGPING + BEIJING BEIJING 102208 + CN + +1C-C0-E1 (hex) SECHERON SA +A00000-AFFFFF (base 16) SECHERON SA + Rue du Pre Bouvier 25 + SATIGNY GENEVA 1242 + CH + +4C-E1-73 (hex) NewVastek +500000-5FFFFF (base 16) NewVastek + 5F., No.65, Shitan Rd. + Taipei City Neihu Dist. 11469 + TW + +38-3A-21 (hex) Chengdu Krosslan Technology Inc. +700000-7FFFFF (base 16) Chengdu Krosslan Technology Inc. + 4F,Tower B, Rennan Mansion, No.5 Section 3, 2nd Ring Road South + Chengdu Sichuan 610041 + CN + +38-3A-21 (hex) Skylark Wireless LLC +900000-9FFFFF (base 16) Skylark Wireless LLC + 1953 Richmond Ave. + Houston TX 77098 + US + +38-3A-21 (hex) SDNware technology co.,LTD +E00000-EFFFFF (base 16) SDNware technology co.,LTD + 166 Renai Road + Suzhou 215000 + CN + +AC-64-DD (hex) infypower Co., Ltd +300000-3FFFFF (base 16) infypower Co., Ltd + -101, No. 3009, Shahexi Road, Nanshan District, + shenzhen guangdong 518055 + CN + +38-3A-21 (hex) Pactron +B00000-BFFFFF (base 16) Pactron + 3000 Patrick Henry + Santa Clara CA 95054 + US + +F8-1D-78 (hex) ADTECHNO Inc. +100000-1FFFFF (base 16) ADTECHNO Inc. + 2-3-10 Kudanminami, Chiyoda-Ku + Tokyo 102-0074 + JP + +70-F8-E7 (hex) Flexim Security Oy +600000-6FFFFF (base 16) Flexim Security Oy + P.O.Box 700 + ESPOO Southern Finland 02131 + FI + +70-F8-E7 (hex) Kontech Electronics Co., Ltd +900000-9FFFFF (base 16) Kontech Electronics Co., Ltd + Longhua,Dalang,Langkou Industry Park + shenzhen Guangdong 518109 + CN + +70-F8-E7 (hex) SHENZHEN Xin JiuNing Electronics Co Ltd +000000-0FFFFF (base 16) SHENZHEN Xin JiuNing Electronics Co Ltd + Floor 2, Building 11, WaiMao Industrial Park, Shiyan Subdistrict , Baoan District, Shenzhen + SHENZHEN GUANGDONG 518108 + CN + +70-F8-E7 (hex) Eclipse Security +800000-8FFFFF (base 16) Eclipse Security + 3900 N. 29th Ave + Hollywood FL 33020 + US + +F8-1D-78 (hex) SHENZHUOYUE TECHNOLOGY.,LTD +C00000-CFFFFF (base 16) SHENZHUOYUE TECHNOLOGY.,LTD + Room 815/816 , ShangMei Times Building, No. 57 LongGuan East Road,Long Hua New District, + Shenzhen Guangdong 518000 + CN + +70-F8-E7 (hex) System Level Solutions (India) Pvt. +100000-1FFFFF (base 16) System Level Solutions (India) Pvt. + 32, D4, Phase-1, GIDC, V U Nagar + Anand Gujarat 388121 + IN + +84-E0-F4 (hex) iSolution Technologies Co.,Ltd. +A00000-AFFFFF (base 16) iSolution Technologies Co.,Ltd. + 5F,Bldg #6, Zhongguan Honghualing Industrial South Park + Shenzhen Guangdong 518055 + CN + +84-E0-F4 (hex) Dantherm +700000-7FFFFF (base 16) Dantherm + Marienlystvej 65 + Skive 7800 + DK + +84-E0-F4 (hex) Liaoning IK'SONYA Science and Technology Co., Ltd. +600000-6FFFFF (base 16) Liaoning IK'SONYA Science and Technology Co., Ltd. + Floor9, Building E01, No.861-1 Shangshengoucun Dongling District Shenyang City Liaoning Province + Shenyang 110000 + CN + +84-E0-F4 (hex) MedicusTek Inc. +100000-1FFFFF (base 16) MedicusTek Inc. + 9F No.3-2 Yuanqu St. Nangang Dist. + Taipei 11503 + TW + +84-E0-F4 (hex) RAY Co.,LTD +800000-8FFFFF (base 16) RAY Co.,LTD + 3~4F, 332-7, Samsung1-ro + Hwaseong-si Gyeonggi-do 445-330 + KR + +C0-D3-91 (hex) XENA SECURITY LIMITED +800000-8FFFFF (base 16) XENA SECURITY LIMITED + ROOM 1210, WANG CHEONG ENTERPRISE CENTRE, 65 CHAI WAN KOK STREET, TSUEN WAN, N.T. + HONG KONG Select State 000000 + HK + +C0-D3-91 (hex) Hofon Automation Co.,Ltd +200000-2FFFFF (base 16) Hofon Automation Co.,Ltd + 8th floor,3rd building of Lierda,No1328 Wenyi Road + Hangzhou Zhejiang 310000 + CN + +98-6D-35 (hex) blossom communications corp. +400000-4FFFFF (base 16) blossom communications corp. + Floor 19, No. 104, Sec. 1, Sin Tai Wu Road, Xi Zhi District + New Taipei City 221 + TW + +C0-D3-91 (hex) IXON B.V. +300000-3FFFFF (base 16) IXON B.V. + Vierlingsbeekseweg 52A + Overloon Noord-Brabant 5825 AX + NL + +58-E8-76 (hex) Chengdu Vision-Zenith Technology Co.,Ltd +800000-8FFFFF (base 16) Chengdu Vision-Zenith Technology Co.,Ltd + 3rd Floor,Unit 1 Building 6,No.88 of Tianchen Road West Science Park, Hi-tech zone west + Chengdu Sichuan 610000 + CN + +58-E8-76 (hex) SHENZHEN DIGISSIN TECHNOLOGY +A00000-AFFFFF (base 16) SHENZHEN DIGISSIN TECHNOLOGY + Room 315, Zixinda Building, No. 1053, BAOYUAN Road, Xixiang, Baoan District, + SHENZHEN GUANGDONG 518102 + CN + +58-E8-76 (hex) KUSTOM SIGNALS INC +C00000-CFFFFF (base 16) KUSTOM SIGNALS INC + 1010 W CHESTNUT + CHANUTE KS 66720 + US + +C0-D3-91 (hex) REGULUS CO.,LTD. +D00000-DFFFFF (base 16) REGULUS CO.,LTD. + Yotsuya Orchid Bldg. 23-3 Daikyo-cho + Shinjuku-ku Tokyo 160-0015 + JP + +F0-AC-D7 (hex) Sercomm Corporation. +400000-4FFFFF (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +F0-AC-D7 (hex) Hanju Network Technologies Co. +700000-7FFFFF (base 16) Hanju Network Technologies Co. + lvdilanhai building 2303, zhangba street + Xi'an ShaanXi 710065 + CN + +F0-AC-D7 (hex) Telefonix Incorporated +800000-8FFFFF (base 16) Telefonix Incorporated + 2340 Ernie Krueger Circle + Waukegan null 60087 + US + +F0-AC-D7 (hex) PAVO TASARIM URETIM TICARET A.S. +500000-5FFFFF (base 16) PAVO TASARIM URETIM TICARET A.S. + Teknopark Istanbul Ar-Ge Binalari 1.Blok Pendik + Istanbul Select State 34349 + TR + +F0-AC-D7 (hex) Suzhou Pairlink Network Technology +600000-6FFFFF (base 16) Suzhou Pairlink Network Technology + Room304, Building 4, No.209, Zhu Yuan Road, Suzhou new district + Suzhou Jiangsu 215011 + CN + +28-36-38 (hex) Knowles Electronics LLC +000000-0FFFFF (base 16) Knowles Electronics LLC + 1151 Maplewood Drive + Itasca IL 60143 + US + +28-36-38 (hex) APPEAK Technology System Co.Ltd. +D00000-DFFFFF (base 16) APPEAK Technology System Co.Ltd. + 12F.,No176,Sec.2 Beixin Rd. + Xindian Dist New Taipei City 231 + TW + +28-36-38 (hex) Dspread Technology (Beijing) Inc. +400000-4FFFFF (base 16) Dspread Technology (Beijing) Inc. + Jingxin Building, 2045 Suite , Chaoyang District + Beijing 100027 + CN + +28-36-38 (hex) Bluekey Pty Ltd +A00000-AFFFFF (base 16) Bluekey Pty Ltd + 6/28 Newheath Dr + Arundel Queensland 4214 + AU + +8C-19-2D (hex) You Zhengcheng co.,ltd +C00000-CFFFFF (base 16) You Zhengcheng co.,ltd + Baoan District 45 District + shenzhen guangdong 518133 + CN + +8C-19-2D (hex) Charmlink Tech(HK) Co.,Limited +400000-4FFFFF (base 16) Charmlink Tech(HK) Co.,Limited + UNIT 04,7/F BRIGHT WAY TOWER NO.33 MONG KOK RD KL + HONGKONG 999077 + HK + +8C-19-2D (hex) SRETT +700000-7FFFFF (base 16) SRETT + 305 Avenue Le jour se lève + Boulogne-Billancourt 92100 + FR + +8C-19-2D (hex) Abside Networks, Inc. +B00000-BFFFFF (base 16) Abside Networks, Inc. + 16 heritage road + Acton MA 01720 + US + +8C-19-2D (hex) ViaWear, Inc. +900000-9FFFFF (base 16) ViaWear, Inc. + 801 Key Route Blvd + Albany CA 94706 + US + +8C-19-2D (hex) Shenzhen Cylan Technology Co.,Ltd +800000-8FFFFF (base 16) Shenzhen Cylan Technology Co.,Ltd + Room 605.607.608,Minning Business Building,Caitian North Road,Futian District,Shenzhen + Shenzhen Guangdong 518036 + CN + +CC-D3-1E (hex) Siemens AG, MO MLT BG +900000-9FFFFF (base 16) Siemens AG, MO MLT BG + Eggenbergerstr. 31 + Graz Styria 8020 + AT + +D0-D9-4F (hex) DUKSANMECASYS CO., LTD. +D00000-DFFFFF (base 16) DUKSANMECASYS CO., LTD. + 7F The 6th Byucksan Digital Valley 481-4 Gasan-Dong Geumcheon-Gu + SEOUL 08501 + KR + +C4-7C-8D (hex) GETEMED Medizin- und Informationstechnik AG +800000-8FFFFF (base 16) GETEMED Medizin- und Informationstechnik AG + Oderstrasse 77 + Teltow Brandenburg 14513 + DE + +C4-7C-8D (hex) GC AUTOMATION CO,LTD +B00000-BFFFFF (base 16) GC AUTOMATION CO,LTD + SECOND FLOOR,BLD 10,GRAIN INDUSTRIAL PARK,NO.299 GUANPING ROAD,GUANLAN NEW DISTRICT,SHENZHEN CITY,CHINA + Shenzhen 518000 + CN + +C4-7C-8D (hex) Silvus technologies inc +A00000-AFFFFF (base 16) Silvus technologies inc + 10990 Wilshire blvd. suite 1500 + Los Angeles CA 90024 + US + +C4-7C-8D (hex) ROBOSTAR +400000-4FFFFF (base 16) ROBOSTAR + 700, Suin-ro, Sangnok-gu + Ansan-si Kyŏnggi-do 426-220 + KR + +68-91-D0 (hex) Outstanding Technology Co., Ltd. +E00000-EFFFFF (base 16) Outstanding Technology Co., Ltd. + 9th floor, New Yaesu bldg., 3-5-12 nihon-bashi + Chuo-ku Tokyo 103-0027 + JP + +C4-7C-8D (hex) Watec Co., Ltd. +300000-3FFFFF (base 16) Watec Co., Ltd. + 254-2 Nihonkoku, Daihoji + Tsuruoka-shi Yamagata 997-0017 + JP + +68-91-D0 (hex) Multi Alarm Zrt. +100000-1FFFFF (base 16) Multi Alarm Zrt. + Basamalom u. 33. + Pécs Baranya 7630 + HU + +68-91-D0 (hex) QUANTEX +900000-9FFFFF (base 16) QUANTEX + 010000, Republic of Kazakhstan, Astana, Dostyk st., 5/2, VP 3 + Astana 010000 + KZ + +E0-B6-F5 (hex) POMCube Inc. +600000-6FFFFF (base 16) POMCube Inc. + 19363 Brockton Ln + Saratoga CA 95070 + US + +E0-B6-F5 (hex) Huizhou GISUN Industrial CO. LTD +300000-3FFFFF (base 16) Huizhou GISUN Industrial CO. LTD + Gisun Industry Park,Dong Ao Village, Sha Tian Town,HuiYang District ,Huizhou China + Huizhou Guangdong 518114 + CN + +68-91-D0 (hex) NIPK Electron Co. +500000-5FFFFF (base 16) NIPK Electron Co. + Leningradskaya str. 52a. lit.A, pos. Pesochny + Saint-Petersburg 197758 + RU + +E0-B6-F5 (hex) funktel GmbH +C00000-CFFFFF (base 16) funktel GmbH + Windmühlenbergstr. 20-22 + Salzgitter 38259 + DE + +50-FF-99 (hex) SHENZHEN KINGVT ELECTRONICS CO.,LTD +200000-2FFFFF (base 16) SHENZHEN KINGVT ELECTRONICS CO.,LTD + 8/F,NO.100,LANGKOU INDUSTRLAL PARK,DALANG STREET,NEW LONGHUA DISTRCT,SHENZHEN,R.R.C + Shenzhen 518000 + CN + +E0-B6-F5 (hex) Yuneec International(China)Co.,Ltd +800000-8FFFFF (base 16) Yuneec International(China)Co.,Ltd + 388 Zhengwei Road,JinXi Town,Kunshan,Jiangsu,China + Kunshan Jiangsu 215300 + CN + +98-6D-35 (hex) Zhejiang Hanshow Technology Co., Ltd. +700000-7FFFFF (base 16) Zhejiang Hanshow Technology Co., Ltd. + Floor 18, Building C, Ruipu Plaza, No.15,Hongjunying South Rd, Beijing, China + beijing beijing 100012 + CN + +50-FF-99 (hex) Honeywell International +700000-7FFFFF (base 16) Honeywell International + 13475 Danielson St # 100 + Poway CA 92064 + US + +7C-47-7C (hex) Shenzhen Eunicum Electric Co.,Ltd. +800000-8FFFFF (base 16) Shenzhen Eunicum Electric Co.,Ltd. + 3/F Building 11, Lishan Industrial Park, Yueliangwan,Nanshan District + Shenzhen Guangdong 518054 + CN + +7C-47-7C (hex) Photosynth Inc. +100000-1FFFFF (base 16) Photosynth Inc. + 5-11-1 Sumitomo Seimei Gotanda Bldg. 3F + Osaki, Shinagawa-ku Tokyo 141-0032 + JP + +7C-47-7C (hex) Zerosystem LTD.Co +600000-6FFFFF (base 16) Zerosystem LTD.Co + #905 Hansol Technotown 455 Gyeongsu-Daero + Gunpo Gyeonggido 435-831 + KR + +98-6D-35 (hex) Vitronic Dr.-Ing. Stein Bildverarbeitungssysteme GmbH +600000-6FFFFF (base 16) Vitronic Dr.-Ing. Stein Bildverarbeitungssysteme GmbH + Hasengartenstraße 14 + Wiesbaden Hessen 65189 + DE + +98-6D-35 (hex) Praesideo B.V. +D00000-DFFFFF (base 16) Praesideo B.V. + P.O. Box 24008 + Utrecht 3502 MA + NL + +7C-47-7C (hex) BungBungame Inc +000000-0FFFFF (base 16) BungBungame Inc + 15F., No.19-11, Sanchong Rd., Nangang Dist., Taipei City 115, Taiwan (R.O.C.) + Taipei 100 + TW + +7C-47-7C (hex) Midwest Microwave Solutions +500000-5FFFFF (base 16) Midwest Microwave Solutions + 2000 Progress Drive + Hiawatha IA 52233 + US + +5C-F2-86 (hex) Daisen Electronic Industrial Co., Ltd. +E00000-EFFFFF (base 16) Daisen Electronic Industrial Co., Ltd. + 4-9-24 Nipponbashi, Naniwa-ku + Osaka 556-0005 + JP + +5C-F2-86 (hex) Unfors Raysafe AB +A00000-AFFFFF (base 16) Unfors Raysafe AB + Uggledalsvagen 29 + Billdal 42740 + SE + +38-FD-FE (hex) New Telecom Solutions LLC +400000-4FFFFF (base 16) New Telecom Solutions LLC + Kedrova 15 + Moscow Moscow 117036 + RU + +38-FD-FE (hex) CaptiveAire Systems Inc. +500000-5FFFFF (base 16) CaptiveAire Systems Inc. + 4641 Paragon Park + Raleigh NC 27616 + US + +78-CA-83 (hex) Elanview Technology Co.,Ltd +C00000-CFFFFF (base 16) Elanview Technology Co.,Ltd + NO.7001,Zhongchun Road,Minghang District, Shanghai + shanghai shanghai 201101 + CN + +78-CA-83 (hex) Beijing CarePulse Electronic Technology +700000-7FFFFF (base 16) Beijing CarePulse Electronic Technology + #6302 Hua Yuan Shang Wo Hui Guan, Hua Yuan Dong Road 30, Hai Dian District + BEIJING 100191 + CN + +38-B8-EB (hex) CeeNex Inc +800000-8FFFFF (base 16) CeeNex Inc + 1200 Aerowood Drive Unit 30 + Mississauga, ON Canada L4W 2S7 L4W 2S7 + CA + +78-CA-83 (hex) IHM +800000-8FFFFF (base 16) IHM + Vandtaarnsvej 87 + Soborg Copenhagen 2860 + DK + +78-CA-83 (hex) Zhejiang Science Electronic Tech Co., Ltd +B00000-BFFFFF (base 16) Zhejiang Science Electronic Tech Co., Ltd + F5, Huichuang Building ,No.88, Headquarters Business Garden + Nanhu District, Jiaxing Zhejiang 314000 + CN + +1C-87-74 (hex) Xiaoxinge (Tangshan) Electronic Technology Co., Ltd. +500000-5FFFFF (base 16) Xiaoxinge (Tangshan) Electronic Technology Co., Ltd. + D9G Fuhua Plaza, 8# North Street, Chaoyangmen, Dongcheng District + Beijing Beijing 100027 + CN + +1C-87-74 (hex) New Nordic Engineering +C00000-CFFFFF (base 16) New Nordic Engineering + Inge Lehmanns Gade 10 + Aarhus 8000 + DK + +1C-88-79 (hex) Toshiba Toko Meter Systems Co., LTD. +800000-8FFFFF (base 16) Toshiba Toko Meter Systems Co., LTD. + 3484, Sakuragaoka, Kurohama + Hasuda-shi Saitama 349-0192 + JP + +1C-87-74 (hex) Weber Marking Systems GmbH +400000-4FFFFF (base 16) Weber Marking Systems GmbH + Maarweg 33 + Rheinbreitbach Rheinland-Pfalz 53619 + DE + +1C-87-74 (hex) Ing Buero Ziegler +700000-7FFFFF (base 16) Ing Buero Ziegler + Schönau + Huetten 8825 + CH + +1C-87-74 (hex) CLABER SPA +D00000-DFFFFF (base 16) CLABER SPA + VIA PONTEBBANA 22 + FIUME VENETO PORDENONE 33080 + IT + +1C-87-79 (hex) Istria soluciones de criptografia, S. A. +900000-9FFFFF (base 16) Istria soluciones de criptografia, S. A. + Calle la Fragua, 6 + Tres Cantos Madrid 28760 + ES + +1C-87-79 (hex) Hangzhou Xiaowen Intelligent Technology Co., Ltd. +A00000-AFFFFF (base 16) Hangzhou Xiaowen Intelligent Technology Co., Ltd. + Room 610、611, F/6, Huaye Building,No.511, Jianye Road, Binjiang District + Hang Zhou Zhe Jiang 310053 + CN + +1C-87-79 (hex) ZHEJIANG ITENAL TECHNOLOGY CO.,LTD +800000-8FFFFF (base 16) ZHEJIANG ITENAL TECHNOLOGY CO.,LTD + SHOES INDUSTRIAL PARK + WENZHOU ZHEJIANG 325401 + CN + +1C-87-79 (hex) A-GEAR COMPANY LIMITED +100000-1FFFFF (base 16) A-GEAR COMPANY LIMITED + 3F, Building 3, Unit 1, YingJunNianHa Park, LongGang Avenue, LongGang + Shenzhen Guangdong 518114 + CN + +84-39-BE (hex) Shenzhen Horn Audio Co.,Ltd. +B00000-BFFFFF (base 16) Shenzhen Horn Audio Co.,Ltd. + NO.6 4th GuiHua road,PingShan, + Shenzhen Guangdong 518118 + CN + +84-39-BE (hex) Diamond Products LLC +800000-8FFFFF (base 16) Diamond Products LLC + 21350 Lassen St, Chatsworth, CA 91311, United States + Chatsworth CA 91311 + US + +40-A3-6B (hex) Amobile Intelligent Corp. +B00000-BFFFFF (base 16) Amobile Intelligent Corp. + 18F-1 150 Jianyi Road + New Taipei City 23511 + TW + +40-A3-6B (hex) Pella Corporation +700000-7FFFFF (base 16) Pella Corporation + 102 Main St + Pella IA 50219 + US + +40-A3-6B (hex) Omnitracs, LLC +300000-3FFFFF (base 16) Omnitracs, LLC + 717 North Harwood St. + Dallas TX 75201 + US + +40-A3-6B (hex) Fin Robotics Inc +000000-0FFFFF (base 16) Fin Robotics Inc + 11871 Hilltop Dr, Losaltos Hills + Los Altos CA 94024 + US + +80-0A-80 (hex) Beijing Gooagoo Technical Service Co.,Ltd. +600000-6FFFFF (base 16) Beijing Gooagoo Technical Service Co.,Ltd. + Room 402A,Block E,Wangjing Technology Park,Lize Road + Beijing Beijing 100102 + CN + +80-0A-80 (hex) Shenzhen Zidoo Technology Co., Ltd. +500000-5FFFFF (base 16) Shenzhen Zidoo Technology Co., Ltd. + Room 12D,Block A CENTRAL GREAT SEARCHINGS, + Shenzhen Guangdong 518100 + CN + +00-55-DA (hex) Donguan WideLink Communication Technology Co.,Ltd. +C00000-CFFFFF (base 16) Donguan WideLink Communication Technology Co.,Ltd. + Guangdong dongguan songshan lake high new technology industry development zone industrial south road no. 6 3 building the second floor + Dongguan city Guangdong province 523808 + CN + +00-55-DA (hex) LUCISTECHNOLOGIES(SHANGHAI)CO.,LTD +700000-7FFFFF (base 16) LUCISTECHNOLOGIES(SHANGHAI)CO.,LTD + No.57.East Caohejing.Building Lucis XuHui District, Shanghai.200235.China + SHANGHAI SHANGHAI 200235 + CN + +CC-1B-E0 (hex) Earphone Connection, Ubc. +500000-5FFFFF (base 16) Earphone Connection, Ubc. + 25139 Ave Stanford + Valnecia CA 91355 + US + +A0-3E-6B (hex) Nanjing zhanyi software technology co., LTD +E00000-EFFFFF (base 16) Nanjing zhanyi software technology co., LTD + Room 1101-1,Building No.2,No.106 Software Avenue,Yuhuatai District,Nanjing Jiangsu + Nanjing Jiangsu 210000 + CN + +A0-3E-6B (hex) Business Support Consultant Co.,Ltd +100000-1FFFFF (base 16) Business Support Consultant Co.,Ltd + Room 703-705, 5 Guihua Road, Futian Free Trade Zone, Shenzhen, China + Shenzhen Guangdong 518038 + CN + +00-55-DA (hex) Novexx Solutions GmbH +300000-3FFFFF (base 16) Novexx Solutions GmbH + Ohmstrasse 3 + Eching Bayern 85386 + DE + +DC-44-27 (hex) Nautilus Infotech CO., Ltd. +B00000-BFFFFF (base 16) Nautilus Infotech CO., Ltd. + No.55, Fengcheng St., Bade District, Taoyuan City 334, Taiwan(R.O.C) + Taoyuan City NA 334 + TW + +DC-44-27 (hex) Pyrexx Technologies GmbH +C00000-CFFFFF (base 16) Pyrexx Technologies GmbH + Spichernstr. 2 + Berlin Berlin 10777 + DE + +DC-44-27 (hex) Shanghai Huahong Integrated Circuit Co.,Ltd +A00000-AFFFFF (base 16) Shanghai Huahong Integrated Circuit Co.,Ltd + No.39,Lane572,Bi Bo Road,Zhangjiang High-Tech Park,Shanghai + Shanghai Shanghai 201203 + CN + +1C-21-D1 (hex) Private +C00000-CFFFFF (base 16) Private + +C8-8E-D1 (hex) German Pipe GmbH +100000-1FFFFF (base 16) German Pipe GmbH + Darrweg 43 + Nordhausen Thuringia D-99734 + DE + +1C-21-D1 (hex) Ognios GmbH +100000-1FFFFF (base 16) Ognios GmbH + Dr.-Hans-Lechner-Straße 6 + Wals-Siezenheim Salzburg 5071 + AT + +B0-C5-CA (hex) D&T Inc. +900000-9FFFFF (base 16) D&T Inc. + Gajungbukro 26-121 + YouSung Gu Daejeon 305-343 + KR + +DC-44-27 (hex) Nex Technologies PTY LTD +400000-4FFFFF (base 16) Nex Technologies PTY LTD + 7 Pimpala Street + Lithgow New South Wales 2790 + AU + +78-C2-C0 (hex) Beijing Coilabs technology co.,ltd +800000-8FFFFF (base 16) Beijing Coilabs technology co.,ltd + The 8th floor, Zhongguancun Dream Lab Building, No.1 Haidian Street, Haidian District, Beijing City, China + Beijing Beijing 100086 + CN + +78-C2-C0 (hex) Ombitron, Inc. +A00000-AFFFFF (base 16) Ombitron, Inc. + 1425 Broadway + Seattle Washington 98122 + US + +78-C2-C0 (hex) KORF Inc. +D00000-DFFFFF (base 16) KORF Inc. + 201, Radio Engineering Center + Yuseong-gu Daejeon 305-510 + KR + +B4-37-D1 (hex) Yireh Auto Tech Co.,Ltd. +600000-6FFFFF (base 16) Yireh Auto Tech Co.,Ltd. + #703, 311 Nowon-ro, Nowon-gu + Seoul Seoul 139865 + KR + +B4-37-D1 (hex) Lezyne INC USA +000000-0FFFFF (base 16) Lezyne INC USA + 645 Tank Farm + San Luis Obispo California 93401 + US + +78-C2-C0 (hex) Guangzhou Hongcai Stage Equipment co.,ltd +700000-7FFFFF (base 16) Guangzhou Hongcai Stage Equipment co.,ltd + no.32 Changsha Rd Shayong village + Guangzhou Guangdong 511450 + CN + +B4-37-D1 (hex) GE Power Management +700000-7FFFFF (base 16) GE Power Management + Avenida Pinoa 10 + Zamudio Vizcaya 48170 + ES + +74-F8-DB (hex) WiFi Hotspots, SL +400000-4FFFFF (base 16) WiFi Hotspots, SL + C/ Montaña Clara, No.18 + Fañabe Tenerife 38760 + ES + +74-F8-DB (hex) Shenzhen Ruishi Information Technology Co.,Ltd. +200000-2FFFFF (base 16) Shenzhen Ruishi Information Technology Co.,Ltd. + 9G,Building A,Nanyuemingzhu Buliding,No.2322, Houhai Avenue,Nanshan District + Shenzhen Guangdong 518062 + CN + +74-F8-DB (hex) InnoTrans Communications +300000-3FFFFF (base 16) InnoTrans Communications + 5850 Hellyer Ave + San Jose CA 95138 + US + +74-F8-DB (hex) Wuhan Tianyu Information Industry Co., Ltd. +700000-7FFFFF (base 16) Wuhan Tianyu Information Industry Co., Ltd. + HUST Industry Park, East-Lake Development Zone + Wuhan Hubei 430223 + CN + +54-9A-11 (hex) Niveo International BV +700000-7FFFFF (base 16) Niveo International BV + Communicatieweg 9-L + Mijdrecht 3641 SG + NL + +54-9A-11 (hex) Beijing HTSmartech Co.,Ltd +E00000-EFFFFF (base 16) Beijing HTSmartech Co.,Ltd + Suite 301,Unit 2,Building 6,No.29,Jing Hai + Beijing Beijing 100176 + CN + +54-9A-11 (hex) eTauro LLC +400000-4FFFFF (base 16) eTauro LLC + PMB 128 + Houston TX 77044 + US + +54-9A-11 (hex) Royal Boon Edam International BV +300000-3FFFFF (base 16) Royal Boon Edam International BV + PO box 40 + Edam Noord Holland 1135 ZG + NL + +54-9A-11 (hex) Shenzhen Excera Technology Co.,Ltd. +000000-0FFFFF (base 16) Shenzhen Excera Technology Co.,Ltd. + 4Th floor,Block A,,JunXiangDA Building,No.9 ZhongShan Park Road + ShenZhen Guangdong 518052 + CN + +80-7B-85 (hex) Interplan Co., Ltd. +A00000-AFFFFF (base 16) Interplan Co., Ltd. + 5F Ishihara Bld. 3-3-12 Iidabashi + Chiyoda-ku Tokyo 102-0072 + JP + +64-FB-81 (hex) Dongyang unitech.co.ltd +D00000-DFFFFF (base 16) Dongyang unitech.co.ltd + 8F dearung technotown 13 + seoul 153-803 + KR + +64-FB-81 (hex) Bridgeport Instruments, LLC +C00000-CFFFFF (base 16) Bridgeport Instruments, LLC + 11740 Jollyville Rd. + Austin TX 78759 + US + +64-FB-81 (hex) Seven Solutions S.L +200000-2FFFFF (base 16) Seven Solutions S.L + C/Periodista Rafael Gómez Montero, 2. + Granada Granada 18014 + ES + +64-FB-81 (hex) ChengDu KeChuang LongXin Sci-tech Co.,Ltd +E00000-EFFFFF (base 16) ChengDu KeChuang LongXin Sci-tech Co.,Ltd + 12 South 1Section,First Ring Road + ChengDu Sichuan 610041 + CN + +64-FB-81 (hex) hiQview Corporation +900000-9FFFFF (base 16) hiQview Corporation + 2 Fl., No. 282, Sec. 6, Zhongxiao E. Rd., + Taipei 11558 + TW + +80-7B-85 (hex) Quickte Technology Co.,Ltd +600000-6FFFFF (base 16) Quickte Technology Co.,Ltd + 4thF/Bldg44, XiLiTong Long industrial Zone, + Shenzhen Guangdong province 518052 + CN + +80-E4-DA (hex) Beijing Yuantel Technolgy Co.,Ltd-Shenzhen Branch +400000-4FFFFF (base 16) Beijing Yuantel Technolgy Co.,Ltd-Shenzhen Branch + Room502,B BLdg, Fuan mansion + Shenzhen Gangdong 518000 + CN + +80-E4-DA (hex) Krizer international Co,. Ltd. +800000-8FFFFF (base 16) Krizer international Co,. Ltd. + RM 9F, Block B, Central Building + shenzhen guangdong 518101 + CN + +80-E4-DA (hex) Nanjing LILO Technology Co. Ltd. +B00000-BFFFFF (base 16) Nanjing LILO Technology Co. Ltd. + YouLeHui Building E, 3011 + Beijing Beijing 100000 + CN + +80-E4-DA (hex) EVER Sp. z o.o. +C00000-CFFFFF (base 16) EVER Sp. z o.o. + ul. Grudzinskiego 30 + Swarzedz wielkopolskie 62-020 + PL + +1C-CA-E3 (hex) eSight Corporation +D00000-DFFFFF (base 16) eSight Corporation + 535 Legget Drive + Ottawa Ontario K2K3B8 + CA + +80-E4-DA (hex) Beijing Gaokezhongtian Technology Co Ltd +300000-3FFFFF (base 16) Beijing Gaokezhongtian Technology Co Ltd + Beijing City Haidian District 23 Liangziyinzuo 806 room + beijing beijing 100191 + CN + +1C-CA-E3 (hex) Bird Home Automation GmbH +700000-7FFFFF (base 16) Bird Home Automation GmbH + Joachimsthaler Str. 12 + Berlin Berlin 10719 + DE + +2C-D1-41 (hex) XiaMen 35.com Technology Co,.Ltd. +700000-7FFFFF (base 16) XiaMen 35.com Technology Co,.Ltd. + 8th.building,Guanri Road,Software Park + Xiamen Fujian 361008 + CN + +90-C6-82 (hex) Cinet Inc +700000-7FFFFF (base 16) Cinet Inc + 8616 Phoenix Drive + Manassas VA 20110 + US + +90-C6-82 (hex) Innovative Electronic Technology +300000-3FFFFF (base 16) Innovative Electronic Technology + IET House + Potten End Herts HP42RN + GB + +90-C6-82 (hex) Teletek Electronics +800000-8FFFFF (base 16) Teletek Electronics + 14A Srebarna Str. + Sofia 1407 + BG + +90-C6-82 (hex) Nanjing Jiexi Technologies Co., Ltd. +600000-6FFFFF (base 16) Nanjing Jiexi Technologies Co., Ltd. + 2ND FLOOR,BUILDING 9,JIANGSU SOFTWARE + Nanjing Jiangsu 210023 + CN + +2C-6A-6F (hex) Shanghai Shuncom Electronic Technology Co.,Ltd +000000-0FFFFF (base 16) Shanghai Shuncom Electronic Technology Co.,Ltd + 8/F,No.4 building,No.3000 Longdong Ave,, + shanghai shanghai 201203 + CN + +90-C6-82 (hex) Shanghai HuRong Communication Technology Development Co., Ltd. +E00000-EFFFFF (base 16) Shanghai HuRong Communication Technology Development Co., Ltd. + Room 342,Building A,No.68. Donghe Road, Chengqiao town, Chongming county(Chengqiao Economic Development Zone) + shanghai shanghai 202150 + CN + +2C-6A-6F (hex) Wellntel, Inc. +A00000-AFFFFF (base 16) Wellntel, Inc. + 4230 N Oakland Ave, Suite 202 + Milwaukee WI 53211 + US + +2C-D1-41 (hex) Bowei Technology Company Limited +600000-6FFFFF (base 16) Bowei Technology Company Limited + Room 1716, Building Xinmao, + Shanghai 200233 + CN + +28-FD-80 (hex) Digital Signal Corp +400000-4FFFFF (base 16) Digital Signal Corp + 14000 Thunderbolt Place + Chantilly VA 20151 + US + +A0-BB-3E (hex) Xiamen Kehua Hengsheng Co.,Ltd +600000-6FFFFF (base 16) Xiamen Kehua Hengsheng Co.,Ltd + No.457,Malong Road,Torch High-tech Industrial Zone + Xiamen Fujian 361000 + CN + +A0-BB-3E (hex) AutarcTech GmbH +800000-8FFFFF (base 16) AutarcTech GmbH + Technologiepark 1 + Ansbach Bavaria 91522 + DE + +A0-BB-3E (hex) Sandal Plc +900000-9FFFFF (base 16) Sandal Plc + Unit 5 Harold Close + Harlow Essex + GB + +F8-02-78 (hex) Innodisk +200000-2FFFFF (base 16) Innodisk + 5F., No.237, Sec. 1, Datong Rd., Xizhi Dist., + New Taipei City Taiwan 221 + TW + +F8-02-78 (hex) Beijing Redcdn Technology, Co., Ltd +900000-9FFFFF (base 16) Beijing Redcdn Technology, Co., Ltd + 7F, B block, Yu Hui building + Haidian District Beijing 100142 + CN + +2C-26-5F (hex) Motec GmbH +500000-5FFFFF (base 16) Motec GmbH + Oberweyerer Strasse 21 + Hadamar-Steinbach Hessen 65589 + DE + +2C-26-5F (hex) Hysentel Technology Co., Ltd +E00000-EFFFFF (base 16) Hysentel Technology Co., Ltd + Floor 2 Building L No.26# 2 xiang + Shenzhen Guangdong 518101 + CN + +A4-4F-29 (hex) Comsel System Ltd +300000-3FFFFF (base 16) Comsel System Ltd + Universitetsstranden 5 + Vasa 65200 + FI + +0C-EF-AF (hex) Sentry360 +400000-4FFFFF (base 16) Sentry360 + 23807 W Andrew Road + Plainfield IL 60585 + US + +3C-39-E7 (hex) University of British Columbia +400000-4FFFFF (base 16) University of British Columbia + Department of Civil Engineering + Vancouver BC V6T 1Z4 + CA + +3C-39-E7 (hex) BEWATEC Kommunikationstechnik GmbH +100000-1FFFFF (base 16) BEWATEC Kommunikationstechnik GmbH + Orkotten 65 + Telgte NRW 48291 + DE + +10-07-23 (hex) RippleTek Tech Ltd +000000-0FFFFF (base 16) RippleTek Tech Ltd + Tianyi Street #38 Idealisim Center Building #1 Room #705 + Chengdu Sichuan 610041 + CN + +B8-D8-12 (hex) Lam Research +D00000-DFFFFF (base 16) Lam Research + 4305 cushing parkway + Fremont California 94538 + US + +D0-22-12 (hex) AIM +100000-1FFFFF (base 16) AIM + 21, avenue de la Plaine Fleurie + MEYLAN ISERE 38240 + FR + +B8-D8-12 (hex) Yuwei Info&Tech Development Co.,Ltd +C00000-CFFFFF (base 16) Yuwei Info&Tech Development Co.,Ltd + Floor 6, Taike Building, No 2 Taike Road, Futian + Shenzhen Guangdong 518049 + CN + +E8-18-63 (hex) clabsys +100000-1FFFFF (base 16) clabsys + 9F Elentec-dong, Pangyo 7 Venture Valley II, 633 + Seongnam-si Kyeonggi-do 463-010 + KR + +E8-18-63 (hex) Siliconcube +700000-7FFFFF (base 16) Siliconcube + Room 702, KSIA Building, 182, + Seongnam-si Gyeonggi-do 463-400 + KR + +D0-22-12 (hex) Shenzhen SIC Technology. Co., Ltd. +800000-8FFFFF (base 16) Shenzhen SIC Technology. Co., Ltd. + Room 601-31,Floor 6,Meinian International Square + Shenzhen Guangdong 518042 + CN + +D0-22-12 (hex) URANO INDUSTRIA DE BALANCAS E EQUIPAMENTOS LTDA +600000-6FFFFF (base 16) URANO INDUSTRIA DE BALANCAS E EQUIPAMENTOS LTDA + RUA IRMAO PEDRO, 709 + CANOAS RS 92020550 + BR + +E8-18-63 (hex) BSM Wireless Inc. +900000-9FFFFF (base 16) BSM Wireless Inc. + 75 International Blvd. + Toronto Ontario M9W 6L9 + CA + +D0-22-12 (hex) RHENAC Systems GmbH +200000-2FFFFF (base 16) RHENAC Systems GmbH + Christian-Lassen-Str. 16 + Bonn NRW 53117 + DE + +74-E1-4A (hex) emz-Hanauer GmbH & Co. KGaA +300000-3FFFFF (base 16) emz-Hanauer GmbH & Co. KGaA + Siemensstrasse 1 + Nabburg Bavaria 92507 + DE + +74-E1-4A (hex) open joint stock company YUG-SISTEMA plus +400000-4FFFFF (base 16) open joint stock company YUG-SISTEMA plus + + Krasnodar Krasnodar Region 350072 + RU + +B8-D8-12 (hex) VOTEM +100000-1FFFFF (base 16) VOTEM + 27, Geodudanji 1-gil, + Chuncheon-Si Gangwon-Do 200-883 + KR + +B8-D8-12 (hex) Vonger Electronic Technology Co.,Ltd. +600000-6FFFFF (base 16) Vonger Electronic Technology Co.,Ltd. + Qiaodong Street #24 + Taiyuan Shanxi 030001 + CN + +E4-95-6E (hex) NationalchipKorea +700000-7FFFFF (base 16) NationalchipKorea + #1109, Ace PyeongchonTower + Anyang-si Gyeonggi-do 431-804 + KR + +E4-95-6E (hex) Tacom Projetos Bilhetagem Inteligente ltda +E00000-EFFFFF (base 16) Tacom Projetos Bilhetagem Inteligente ltda + 3800 Raja Gabaglia avenue + Belo Horizonte Minas Gerais 30494310 + BR + +E4-95-6E (hex) Shanghai DGE Co., Ltd +300000-3FFFFF (base 16) Shanghai DGE Co., Ltd + No.6608, Beisong Road, + Shanghai 201611 + CN + +E4-95-6E (hex) Guang Lian Zhi Tong Technology Limited +400000-4FFFFF (base 16) Guang Lian Zhi Tong Technology Limited + Room 1102 Baoyuanhuafeng Economy Bldg + Shenzhen Guang Dong 518000 + + +BC-66-41 (hex) Shenzhen Yaguang communication CO.,LTD +800000-8FFFFF (base 16) Shenzhen Yaguang communication CO.,LTD + 7 Floor,3 building,Guangqian community ,Bagua Load + Shenzhen Guangdong 518029 + CN + +E4-95-6E (hex) Tband srl +100000-1FFFFF (base 16) Tband srl + via A. Meucci, 4 + Preganziol Treviso 31022 + IT + +BC-66-41 (hex) EBlink +A00000-AFFFFF (base 16) EBlink + 3-5 Rue Marcel Pagnol + Boussy Saint Antoine France 91800 + FR + +58-FC-DB (hex) Applied Device Technologies +E00000-EFFFFF (base 16) Applied Device Technologies + 400 West Front Street + Traverse City Michigan 49684 + US + +58-FC-DB (hex) XIAMEN LEELEN TECHNOLOGY CO.,LTD +D00000-DFFFFF (base 16) XIAMEN LEELEN TECHNOLOGY CO.,LTD + 65 Sunban South Rd. + Xiamen Fujian 361021 + CN + +BC-66-41 (hex) Process-Electronic Sp. z o.o. +200000-2FFFFF (base 16) Process-Electronic Sp. z o.o. + ul. Jednosci 48 + Sosnowiec slaskie 41-218 + PL + +58-FC-DB (hex) Beseye Cloud Security Co. Ltd. +200000-2FFFFF (base 16) Beseye Cloud Security Co. Ltd. + 3F.-1, No.45-1, Dexing W. Rd., Shilin Dist. + Taipei City Taiwan 11158 + TW + +B0-1F-81 (hex) SHENZHEN YIFANG DIGITAL TECHNOLOGY CO.,LTD. +400000-4FFFFF (base 16) SHENZHEN YIFANG DIGITAL TECHNOLOGY CO.,LTD. + Building NO.22,23, Fifth Region, Baiwangxin Industrial Park, Songbai Rd., Nanshan + Shenzhen Guangdong 518108 + CN + +F4-0E-11 (hex) Sterna Security +900000-9FFFFF (base 16) Sterna Security + 100 West Sambandam road + Coimbatore Tamilnadu 641002 + IN + +B0-1F-81 (hex) Rademacher Geraete-Elektronik GmbH +B00000-BFFFFF (base 16) Rademacher Geraete-Elektronik GmbH + Buschkamp 7 + Rhede NRW 46414 + DE + +14-1F-BA (hex) Newings Communication CO., LTD. +B00000-BFFFFF (base 16) Newings Communication CO., LTD. + 12F, Block 1, NO 7866, Humin Rd, Minhang District, Shanghai, China + Shanghai Shanghai 200000 + CN + +F4-0E-11 (hex) realphone technology co.,ltd +000000-0FFFFF (base 16) realphone technology co.,ltd + room 1207,block b, haisong building,tairan9th road park,futian district,shenzhen,china + shenzhen guangdong 518400 + CN + +F4-0E-11 (hex) Axel srl +200000-2FFFFF (base 16) Axel srl + Via del Santo, 143 + Limena PD 35010 + IT + +7C-70-BC (hex) Tohan Engineering Corporation +B00000-BFFFFF (base 16) Tohan Engineering Corporation + 1-701-1 Baba + Sennan-shi Osaka 590-0525 + JP + +14-1F-BA (hex) Private +300000-3FFFFF (base 16) Private + +BC-34-00 (hex) AURALIC LIMITED +A00000-AFFFFF (base 16) AURALIC LIMITED + Room 102, Building No.7 + Beijing 102200 + CN + +A4-3B-FA (hex) SHEN ZHEN PASUN TECH CO.LTD. +900000-9FFFFF (base 16) SHEN ZHEN PASUN TECH CO.LTD. + Room B406, Taojindi E-Business Incubator Base + SHENZHEN GUANGDONG 518131 + CN + +BC-34-00 (hex) Cameron +600000-6FFFFF (base 16) Cameron + 14450 John F. Kennedy Blvd + Houston TX 77032 + + +7C-70-BC (hex) FLEXIM GmbH +300000-3FFFFF (base 16) FLEXIM GmbH + Wolfener Strasse 36 + BERLIN 12681 + DE + +D0-76-50 (hex) CentrAlert, Inc. +000000-0FFFFF (base 16) CentrAlert, Inc. + 275 Meijer Way + Lexington KY 40503 + US + +A4-3B-FA (hex) Circus World Displays Ltd +300000-3FFFFF (base 16) Circus World Displays Ltd + 4080 Montrose Rd + Niagara Falls Ontario L2H 1J9 + CA + +A4-3B-FA (hex) Beijing Uniwill Science and Technology Co,Ltd +100000-1FFFFF (base 16) Beijing Uniwill Science and Technology Co,Ltd + NO.30 Jinyuan Road Daxing Zone + Beijing 102600 + CN + +A4-3B-FA (hex) Chengdu Territory Technology Co.,Ltd +000000-0FFFFF (base 16) Chengdu Territory Technology Co.,Ltd + Flat 23, #4, Senhua Gargden Shaoling Road + Chengdu Sichuan 610000 + CN + +D0-76-50 (hex) tecnotron elekronik gmbh +D00000-DFFFFF (base 16) tecnotron elekronik gmbh + Wildberg 64 + Weissensberg Bavaria 88138 + DE + +D0-76-50 (hex) Greenwave Scientific +900000-9FFFFF (base 16) Greenwave Scientific + 2720 Discovery Dr. + Raleigh North Carolina 27612 + US + +74-19-F8 (hex) IDEXX Laboratories, Inc +B00000-BFFFFF (base 16) IDEXX Laboratories, Inc + 1 IDEXX Drive + Westbrook ME 04092 + US + +74-19-F8 (hex) Heptagon Systems PTY. LTD. +700000-7FFFFF (base 16) Heptagon Systems PTY. LTD. + 625-627 Ringwood Warrandyte Road + Ringwood North VIC 3124 + AU + +74-19-F8 (hex) Bach Icon ApS +C00000-CFFFFF (base 16) Bach Icon ApS + Ambolten 8 + Hoersholm DK 2970 + DK + +4C-4B-F9 (hex) Beijing AutoAi Technology co. LTD +E00000-EFFFFF (base 16) Beijing AutoAi Technology co. LTD + The building of Navinfo ,at the intersection Yongfeng road and Beiqing road,Haidian District + Beijing Beijing 100094 + CN + +40-11-75 (hex) Kanda Kogyo +200000-2FFFFF (base 16) Kanda Kogyo + 3-6 Kandacho + HImeji Hyogo 6700991 + JP + +40-11-75 (hex) Beijing Gemotech Intelligent Technology Co., Ltd. +800000-8FFFFF (base 16) Beijing Gemotech Intelligent Technology Co., Ltd. + NO.1 Development Road,Beijing International Information Industrial Base,Huilongguan Town,Changping District + Beijing Beijing 102206 + CN + +40-11-75 (hex) ADH Guardian USA +900000-9FFFFF (base 16) ADH Guardian USA + 122 Penn St + El Segundo CA 90245 + US + +04-D1-6E (hex) ShenZhen Huafu Information technology Co.?Ltd +400000-4FFFFF (base 16) ShenZhen Huafu Information technology Co.?Ltd + T2-B5 FLOOR, shenzhen software park, gaoxin south 7th road, yuehai street, nanshan district + ShenZhen GuangDong 518000 + CN + +24-4E-7B (hex) Church & Dwight Co., Inc. +D00000-DFFFFF (base 16) Church & Dwight Co., Inc. + 500 Charles Ewing Blvd + Ewing NJ 08628 + US + +04-D1-6E (hex) CHENGDU INTERLINK SCIENCE AND TECHNOLOGY CO.,LTD +800000-8FFFFF (base 16) CHENGDU INTERLINK SCIENCE AND TECHNOLOGY CO.,LTD + Room 1305, 12A Level, Wanke Huamao Building + Sichuan Chengdu 610051 + CN + +04-D1-6E (hex) PacPort Corporation +C00000-CFFFFF (base 16) PacPort Corporation + Ginza 6-10-1, GINZA SIX 13F, Chuo-ku + Tokyo Tokyo 1040061 + JP + +04-D1-6E (hex) Launch Tech Co., Ltd. +100000-1FFFFF (base 16) Launch Tech Co., Ltd. + Launch Industrial Park, No.4012, North of Wuhe Road, Bantian Street, Longgang District, + Shenzhen Guangdong 518100 + CN + +04-D1-6E (hex) Envision Energy +700000-7FFFFF (base 16) Envision Energy + 8/F, Building B, SOHO Zhongshan Plaza, 1065 West Zhongshan Road + Shanghai 200051 + CN + +44-03-77 (hex) Hangzhou Asia Infrastructure Tech. Co., Ltd. +B00000-BFFFFF (base 16) Hangzhou Asia Infrastructure Tech. Co., Ltd. + No.7 Xiyuan Rd, Sandun Town, Westlake District + Hangzhou Zhejiang 310000 + CN + +44-03-77 (hex) Stara S/A Indústria de Implementos Agrícolas +700000-7FFFFF (base 16) Stara S/A Indústria de Implementos Agrícolas + Avenida Stara 519 + Não-Me-Toque Rio Grande do Sul 99470000 + BR + +50-62-55 (hex) AVTECH Software, Inc. +700000-7FFFFF (base 16) AVTECH Software, Inc. + 16 Cutler Str, Cutler Mill + Warren RI 02885 + US + +50-62-55 (hex) Hypertech Advance Co., LTD +300000-3FFFFF (base 16) Hypertech Advance Co., LTD + 1F., No. 9, Changchun 6th Rd., Zhongli Dist., + Taoyuan City 320 + TW + +50-62-55 (hex) Suzhou Ruixinjie Information Technology Co.,Ltd +500000-5FFFFF (base 16) Suzhou Ruixinjie Information Technology Co.,Ltd + Room 907,No. 99 Changli Road + Suzhou Jiangsu 215000 + CN + +64-31-39 (hex) Hunan Voc Acoustics Technology Co., Ltd. +600000-6FFFFF (base 16) Hunan Voc Acoustics Technology Co., Ltd. + State Industrialpark, Jiulong Development Zone, Yanling County + Zhuzhou Hunan 412500 + CN + +50-62-55 (hex) AED Distribution +C00000-CFFFFF (base 16) AED Distribution + Bedrijvenpark De Veert 13/004 + Willebroek 2830 + BE + +64-31-39 (hex) KOANGYOW INTEGRATION MACHINE CO., LTD. +300000-3FFFFF (base 16) KOANGYOW INTEGRATION MACHINE CO., LTD. + 7F., No. 566, Zhongzheng Rd., Xindian Dist. + New Taipei City 23148 + TW + +64-31-39 (hex) SHEN ZHEN FUCHANG TECHNOLOGY Co.,Ltd. +C00000-CFFFFF (base 16) SHEN ZHEN FUCHANG TECHNOLOGY Co.,Ltd. + Floor 4 11 Building Qixing Factory,Niu Cheng 2rd Industrial Area,Xili Nanshan District + Shenzhen GUANGDONG 518055 + CN + +C4-95-4D (hex) SolidGear Corporation +C00000-CFFFFF (base 16) SolidGear Corporation + Shinyokohama Kaneko Bldg 8F, 2-3-9 ShinYokohama Kohoku-ku + Yokohama Knanagawa 222-0033 + JP + +C4-95-4D (hex) Sercomm Corporation. +300000-3FFFFF (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +00-69-67 (hex) Hangzhou Wise IOT Technology Co.,Ltd +900000-9FFFFF (base 16) Hangzhou Wise IOT Technology Co.,Ltd + Room 405, Building 2, No. 31, Science and Technology Avenue, Yuhang Street, Yuhang District + Hangzhou Zhejiang 310012 + CN + +64-31-39 (hex) Active Brains +400000-4FFFFF (base 16) Active Brains + Yokohama Dia BLDG 8F 1-7 Kinkocho Kanagawa-ku + Yokohama Kanagawa 221-0056 + JP + +00-69-67 (hex) Ambient-System sp. z o.o. +800000-8FFFFF (base 16) Ambient-System sp. z o.o. + ul. Galaktyczna 37 + Gdansk 80-299 + PL + +00-69-67 (hex) Datapan d.o.o. +B00000-BFFFFF (base 16) Datapan d.o.o. + Velika Pot 19 + Solkan 5250 + SI + +00-69-67 (hex) Tianjin Lianwu Technology Co., Ltd. +E00000-EFFFFF (base 16) Tianjin Lianwu Technology Co., Ltd. + Room 201, 2nd floor, Building 8, No.35, Caizhi Street, Xuefu Industrial Zone, Xiqing District + Tianjin Tianjin 300380 + CN + +A0-22-4E (hex) IST ElektronikgesmbH +A00000-AFFFFF (base 16) IST ElektronikgesmbH + Marktplatz 40 + Neukirchen am Walde Upper Austria 4724 + AT + +A0-22-4E (hex) rNET Controls +100000-1FFFFF (base 16) rNET Controls + 8231 SW Cirrus Dr + Beaverton OR 97008 + US + +20-0A-0D (hex) Tecnint HTE SRL +700000-7FFFFF (base 16) Tecnint HTE SRL + Via della Tecnica 16/18 + Osnago Lecco 23875 + IT + +20-0A-0D (hex) IRSAP +A00000-AFFFFF (base 16) IRSAP + Via delle Industrie, 211 + Arqua' Polesine Veneto 45031 + IT + +40-2C-76 (hex) Annapurna labs +200000-2FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +40-2C-76 (hex) Baumer Bourdon-Haenni +500000-5FFFFF (base 16) Baumer Bourdon-Haenni + 125 Rue de la marre + Vendôme 41100 + FR + +40-2C-76 (hex) NowTechnologies Zrt +A00000-AFFFFF (base 16) NowTechnologies Zrt + 18 Realtanoda + Budapest 1053 + HU + +50-DE-19 (hex) Shenzhen Vipstech Co., Ltd +C00000-CFFFFF (base 16) Shenzhen Vipstech Co., Ltd + Building 10th, Baiwangxin Industrial Park, No. 1002 Songbai Road, Xili Street, + Shenzhen Guangdong 518100 + CN + +50-DE-19 (hex) Telic AG +000000-0FFFFF (base 16) Telic AG + Raiffeisenallee 12b + Oberhaching 82041 + DE + +3C-FA-D3 (hex) Shenzhen zhong ju Fiber optical Co.Ltd +C00000-CFFFFF (base 16) Shenzhen zhong ju Fiber optical Co.Ltd + 3t Floor Build A .jin he Rui park .guan lan. + Shen zhen Guang dong 518000 + CN + +3C-FA-D3 (hex) Naruida Technology Ltd. +200000-2FFFFF (base 16) Naruida Technology Ltd. + 2 Gangle Road,Tangjia Bay Town, High Tech Zone + Zhuhai Guangdong 519080 + CN + +90-E2-FC (hex) Huddly AS +900000-9FFFFF (base 16) Huddly AS + Karenslyst Allé 51 + Oslo 0279 + NO + +90-E2-FC (hex) Shenzhen Dingsheng Intelligent Technology Co., Ltd +B00000-BFFFFF (base 16) Shenzhen Dingsheng Intelligent Technology Co., Ltd + 10/F Block C, Skyworth Building, Gaoxin South 1st Rd., Hi-Tech Park, Nanshan District + Shenzhen Guangdong 518000 + CN + +14-AE-85 (hex) Veo Technologies +900000-9FFFFF (base 16) Veo Technologies + Aldersrogade 6c, 4. sal + København Denmark 2100 + DK + +14-AE-85 (hex) SHENZHEN HONOR ELECTRONIC CO.,LTD +700000-7FFFFF (base 16) SHENZHEN HONOR ELECTRONIC CO.,LTD + No. A Building, Xinghui Industrial Park, Gushu No. 2Rd, + SHEN ZHEN GUANG DONG 518000 + CN + +94-CC-04 (hex) Shenzhen Link technology Co.,Ltd +300000-3FFFFF (base 16) Shenzhen Link technology Co.,Ltd + 901,9/F,Dahong High TechIndusryPark?NO.6-18,Xinhe Road,Xinqiao Community,Baoan District + Shenzhen Guangdong 518000 + CN + +94-CC-04 (hex) SHENZHEN SANRAY TECHNOLOGY CO.,LTD +500000-5FFFFF (base 16) SHENZHEN SANRAY TECHNOLOGY CO.,LTD + 1B08 2/F Folk Culture Industrial Park,Qunli Second Road, Baoan District + Shenzhen GuangDong 518101 + CN + +94-CC-04 (hex) GOCOAX, INC +100000-1FFFFF (base 16) GOCOAX, INC + 15902A Halliburton Rd #662 + Hacienda Heights CA 91745 + US + +94-05-BB (hex) Chengdu Zhongheng Network Co.,Ltd. +500000-5FFFFF (base 16) Chengdu Zhongheng Network Co.,Ltd. + No.898 Baicao Road, Chengdu High-tech Zone (Western District) + Chengdu Sichuan 611731 + CN + +D0-C8-57 (hex) IFLYTEK CO.,LTD. +D00000-DFFFFF (base 16) IFLYTEK CO.,LTD. + National Intelligent Speech High-tech Industrialization Base, No. 666, Wangjiang Road West, + Hefei An hui 230088 + CN + +94-CC-04 (hex) Shanxi Baixin Information Technology Co., Ltd. +C00000-CFFFFF (base 16) Shanxi Baixin Information Technology Co., Ltd. + Room 210-213, Room 215-217, Room 219-220, No.2, Yari Street, Taiyuan University Park, Shanxi Comprehensive Reform Demonstration Zone + Taiyuan Shanxi 030032 + CN + +94-05-BB (hex) ZIGPOS GmbH +600000-6FFFFF (base 16) ZIGPOS GmbH + Räcknitzhöhe 35a + Dresden Saxony 01217 + DE + +94-05-BB (hex) SolarEdge Technologies +A00000-AFFFFF (base 16) SolarEdge Technologies + 1 Abba Eban St. + Herzelia 46725 + IL + +F4-90-CB (hex) Airbeam Wireless Technologies Inc. +600000-6FFFFF (base 16) Airbeam Wireless Technologies Inc. + #125, 21320 Gordon Way + Richmond British Columbia V6W 1J8 + CA + +20-85-93 (hex) UNILUMIN GROUP CO.,LTD +300000-3FFFFF (base 16) UNILUMIN GROUP CO.,LTD + No.112 Yongfu Rd.,BaoanDistrict, + shenzhen guangdong 518103 + CN + +20-85-93 (hex) Eilersen Electric A/S +600000-6FFFFF (base 16) Eilersen Electric A/S + Kokkedal Industripark 4 + Kokkedal 2980 + DK + +4C-4B-F9 (hex) Stored Energy Systems +B00000-BFFFFF (base 16) Stored Energy Systems + 1840 Industrial Circle + Longmont CO 80501 + US + +DC-E5-33 (hex) Private +A00000-AFFFFF (base 16) Private + +24-15-10 (hex) SHANDONG KEHUI POWER AUTOMATION CO. LTD. +600000-6FFFFF (base 16) SHANDONG KEHUI POWER AUTOMATION CO. LTD. + No. 16,Sanying Road + Zibo Shandong 255087 + CN + +24-15-10 (hex) Kaiyun +300000-3FFFFF (base 16) Kaiyun + Fuhao + Dongguang 523617 + CN + +DC-44-27 (hex) Private +F00000-FFFFFF (base 16) Private + +2C-D1-41 (hex) IntelliLUM +200000-2FFFFF (base 16) IntelliLUM + 8850 Terabyte Court + Reno Nevada 89521 + US + +98-06-37 (hex) Shenzhen Y&D Electronics Information Co., Ltd +800000-8FFFFF (base 16) Shenzhen Y&D Electronics Information Co., Ltd + 601-602, 6/F, Antenna Building, No 17, Keji North 1st Road, Nanshan District + Shenzhen 518055 + CN + +98-06-37 (hex) BOEING SSG +600000-6FFFFF (base 16) BOEING SSG + 5905 LEGACY DR, SUITE 325 + PLANO TX 75024 + US + +1C-21-D1 (hex) Private +F00000-FFFFFF (base 16) Private + +FC-A4-7A (hex) SHENZHEN KUKU TECHNOLOGY CO.,LTD +D00000-DFFFFF (base 16) SHENZHEN KUKU TECHNOLOGY CO.,LTD + No.205,2F,17th Block,PingShan Industrial District,TaoYuan Street, NanShan + ShenZhen GuangDong 518055 + CN + +D0-5F-64 (hex) Shenzhen Canzone Technology Co.,Ltd. +D00000-DFFFFF (base 16) Shenzhen Canzone Technology Co.,Ltd. + Minzhi Street Longhua District + ShenZhen 518000 + CN + +2C-16-BD (hex) Curtiss-Wright Drive Technology +100000-1FFFFF (base 16) Curtiss-Wright Drive Technology + Badstrasse 5 + Neuhausen am Rheinfall Schaffhausen 8212 + CH + +2C-16-BD (hex) Saft AB +300000-3FFFFF (base 16) Saft AB + Jungnergatan + Oskarshamn 57228 + SE + +2C-16-BD (hex) Beijing Jishi Huitong Technology Co., Ltd. +000000-0FFFFF (base 16) Beijing Jishi Huitong Technology Co., Ltd. + 4/F,No.3 building,No.8,Haiying Road,Fengtai District + Beijing Beijing 100070 + CN + +2C-16-BD (hex) AIMCO +200000-2FFFFF (base 16) AIMCO + 10000 SE Pine St + Portland OR 97216 + US + +2C-16-BD (hex) SCT OPTRONICS CO., LTD +700000-7FFFFF (base 16) SCT OPTRONICS CO., LTD + Floor 9, Block B, Building 7, Shenzhen Bay Technology Ecological Park, Nanshan District + Shenzhen Guangdong 518057 + CN + +2C-16-BD (hex) Shanghai Walktech Information Technology Co.,Ltd. +900000-9FFFFF (base 16) Shanghai Walktech Information Technology Co.,Ltd. + 4F , No 85, Lane 1198, North Qin Zhou Road, Xu Hui District + Shanghai Shanghai 200233 + CN + +FC-A4-7A (hex) Oberix Group Pty Ltd +900000-9FFFFF (base 16) Oberix Group Pty Ltd + 22 McIntyre Street + Burwood VIC 3125 + AU + +FC-A4-7A (hex) KARRY COMMUNICATION LIMITED +800000-8FFFFF (base 16) KARRY COMMUNICATION LIMITED + FLAT/RM 705 7/F SUNBEAM PLAZA 1155 CANTON ROAD MONGKOK KL + Hong Kong 999077 + HK + +8C-59-3C (hex) Nanonord A/S +800000-8FFFFF (base 16) Nanonord A/S + Skjernvej 4A + Aalborg 9220 + DK + +8C-59-3C (hex) Future Robot Technology Co., Limited +100000-1FFFFF (base 16) Future Robot Technology Co., Limited + Room 406 Block A South Wind Tower, Nanshan Cloud Valley Innovation Industry Park, No 4093 Lau Sin Avenue Taoyuan Street Nanshan District + Shenzhen Guangdong 518000 + CN + +8C-59-3C (hex) Spectranetix +500000-5FFFFF (base 16) Spectranetix + 845 Stewart Drive, Suite B + Sunnyvale CA 94085 + US + +B4-A2-EB (hex) SHENZHEN ZHUIFENGMA TECHNOLOGY CO., LTD +800000-8FFFFF (base 16) SHENZHEN ZHUIFENGMA TECHNOLOGY CO., LTD + 2 FLOOR WEST WING BLOCK 3 NO.28 LANGSHAN ROAD, NANSHAN DISTRICT + SHENZHEN Guangdong 518040 + CN + +B4-A2-EB (hex) SALZBRENNER media GmbH +D00000-DFFFFF (base 16) SALZBRENNER media GmbH + Industriegebiet See 1 + Buttenheim 96155 + DE + +BC-97-40 (hex) Shenzhen Colorwin Optical Technology Co.,Ltd +600000-6FFFFF (base 16) Shenzhen Colorwin Optical Technology Co.,Ltd + 201-2,2nd Floor,G3 Building, TCL International E City,1001 Zhongshanyuan Road,Nanshan District + Shenzhen Guangdong 518055 + CN + +BC-97-40 (hex) Direct Communication Solutions +900000-9FFFFF (base 16) Direct Communication Solutions + 17150 Via del Campo, Ste 200 + San Diego CA 92127 + US + +D0-C8-57 (hex) Nanjing Magewell Electronics Co.,Ltd +800000-8FFFFF (base 16) Nanjing Magewell Electronics Co.,Ltd + 14th Floor, Building 3, No. 89 Shengli Road, Jiangning Economic and Technological Development Zone + Nanjing Jiangsu 211100 + CN + +D0-C8-57 (hex) Dante Security Inc. +C00000-CFFFFF (base 16) Dante Security Inc. + 303 MERRICK RD., Unit 208 + LYNBROOK NY 11563 + US + +BC-97-40 (hex) B4ComTechnologies LLC +E00000-EFFFFF (base 16) B4ComTechnologies LLC + Office 2/6, 16a, Ivana Babushkina street + Moscow 117292 + RU + +BC-97-40 (hex) Amap Information Technology Co., Ltd +A00000-AFFFFF (base 16) Amap Information Technology Co., Ltd + A051, No.01, 3/F, No.55 Suzhou Street, Haidian District + Beijing Beijing 100080 + CN + +BC-97-40 (hex) LISTEC GmbH +C00000-CFFFFF (base 16) LISTEC GmbH + Am Sandberg 34 + Isen Bavaria 84424 + DE + +D0-C8-57 (hex) YUAN High-Tech Development Co., Ltd. +000000-0FFFFF (base 16) YUAN High-Tech Development Co., Ltd. + 18F, No.88, Sec. 2, Chung Hsiao E.Rd., + Taipei, Taiwan 10050 + TW + +BC-97-40 (hex) Wind Mobility Technology (Beijing) Co., Ltd +400000-4FFFFF (base 16) Wind Mobility Technology (Beijing) Co., Ltd + 13603, Building 13, No. 2, Nanzhuzhang Hutong, Dongcheng District + Beijing Beijing 100010 + CN + +60-95-CE (hex) Q-SENTECH Co.,Ltd. +200000-2FFFFF (base 16) Q-SENTECH Co.,Ltd. + #201,170 Seonyu-ro, Yeongdeungpo-gu + Seoul Korea 07255 + KR + +1C-82-59 (hex) Microtronics Engineering GmbH +E00000-EFFFFF (base 16) Microtronics Engineering GmbH + Hauptstrasse 7 + Ruprechtshofen 3244 + AT + +1C-82-59 (hex) Diatrend Corporation +200000-2FFFFF (base 16) Diatrend Corporation + Grand Front Osaka Tower-B 28F, 3-1 ofuka-cho, kita-ku + Osaka Osaka 530-0011 + JP + +1C-82-59 (hex) SHENZHEN AOA TECHNOLOGY CO.,LTD +800000-8FFFFF (base 16) SHENZHEN AOA TECHNOLOGY CO.,LTD + B624,C1 Building,Hengchao Industrial Park,Tangtou Road,Shiyan,Bao'an District + SHENZHEN Guangdong 518108 + CN + +84-8B-CD (hex) WORMIT +C00000-CFFFFF (base 16) WORMIT + Sec.1,Xintai 5th Rd.,Xizhi Dist. + New Taipei City 22101 + TW + +B0-FD-0B (hex) Taian Yuqi Communication Technology Co., Ltd +500000-5FFFFF (base 16) Taian Yuqi Communication Technology Co., Ltd + Building 4, Fengxiang Road, Tai'an Development Zone + Tai’an Shandong 271000 + CN + +B0-FD-0B (hex) Eagle Acoustics Manufacturing, LLC +900000-9FFFFF (base 16) Eagle Acoustics Manufacturing, LLC + 333 E IL ROUTE 83, Ste. 100 + MUNDELEIN IL 60060-4214 + US + +1C-82-59 (hex) Shanghai Xiaoyan Technology Co., Ltd. +900000-9FFFFF (base 16) Shanghai Xiaoyan Technology Co., Ltd. + Room 503, Building B, NO. 2305, Zuchongzhi Road + Shanghai Shanghai 201203 + CN + +84-8B-CD (hex) Logic Supply +400000-4FFFFF (base 16) Logic Supply + 35 Thompson St + South Burlington VT 05403 + US + +B0-FD-0B (hex) Everynet Oy +700000-7FFFFF (base 16) Everynet Oy + At Azets Insight Oy, Hatanpään valtatie 26 (5.krs) + Tampere 33100 + FI + +B0-FD-0B (hex) Vista Manufacturing +200000-2FFFFF (base 16) Vista Manufacturing + 53345 Columbia Drive + Elkhart IN 46514 + US + +8C-14-7D (hex) Private +100000-1FFFFF (base 16) Private + +C8-2C-2B (hex) RF Engineering and Energy Resource +300000-3FFFFF (base 16) RF Engineering and Energy Resource + 4460 Commercial Ave. + Portage MI 49002 + US + +C8-2C-2B (hex) iWave Systems Tech Pvt Ltd +400000-4FFFFF (base 16) iWave Systems Tech Pvt Ltd + 7/B 29th Main, BTM Layout 2nd Stage + Bengalore Kamataka 560076 + IN + +C8-2C-2B (hex) DALCO AG +500000-5FFFFF (base 16) DALCO AG + Industriestr. 28 + Volketswil ZH 8604 + CH + +1C-CA-E3 (hex) Private +F00000-FFFFFF (base 16) Private + +C8-63-14 (hex) Optictimes Co.,Ltd +A00000-AFFFFF (base 16) Optictimes Co.,Ltd + Hangzhou City, Zhejiang Province + Hangzhou Zhejiang 310023 + CN + +E4-1E-0A (hex) Tritium Pty Ltd +700000-7FFFFF (base 16) Tritium Pty Ltd + 1/31 Archimedes PL. + Murarrie QLD 4172 + AU + +E4-1E-0A (hex) Zavod № 423 +000000-0FFFFF (base 16) Zavod № 423 + 2B, Zavodskoy proezd + Bogoroditsk Tula 301830 + RU + +CC-D3-9D (hex) Shanghai tongli information technology co. LTD +E00000-EFFFFF (base 16) Shanghai tongli information technology co. LTD + Floor 2, building 1, liqin building, No.1885, metropolis road, minhang district + Shanghai Shanghai 201108 + CN + +E4-1E-0A (hex) Aeroel srl +500000-5FFFFF (base 16) Aeroel srl + Vai Pier Paolo Pasolini 35/3 + Pradamano Udine 33040 + IT + +FC-D2-B6 (hex) Winglet Systems Inc. +900000-9FFFFF (base 16) Winglet Systems Inc. + 4-6, Shinyokohama 2-chome, Kohoku-ku + Yokohama Kanagawa 222-0033 + JP + +34-E1-D1 (hex) CREW by True Rowing, Inc. +C00000-CFFFFF (base 16) CREW by True Rowing, Inc. + 14 Arrow St, Floor 4 + Cambridge MA 02138 + US + +34-E1-D1 (hex) SAMA NextGen PTE Limited +100000-1FFFFF (base 16) SAMA NextGen PTE Limited + 16 Collyer Quay, #21-00 Income AT Raffels, Singapore 049318 + Singapore 049318 + SG + +34-E1-D1 (hex) HI-TECH.ORG +D00000-DFFFFF (base 16) HI-TECH.ORG + Volgogradskiy prospekt, 43, k.3, room XXVI + Moscow 109316 + RU + +D4-7C-44 (hex) Huaqin Telecom Technology Co.,Ltd. +D00000-DFFFFF (base 16) Huaqin Telecom Technology Co.,Ltd. + Building 1,No.399, Keyuan Road, Pudong, Shanghai China + Shanghai 200120 + CN + +FC-D2-B6 (hex) Soma GmbH +200000-2FFFFF (base 16) Soma GmbH + Gewerbering 9 + Schalksmühle NRW 58579 + DE + +E4-4C-C7 (hex) Beijing Zhongchuangwei Nanjing Quantum Communication Technology Co., Ltd. +400000-4FFFFF (base 16) Beijing Zhongchuangwei Nanjing Quantum Communication Technology Co., Ltd. + No. 88, pubin avenue, jiangpu street, pukou district, nanjing city + nanjing Jiangsu 210000 + CN + +E4-4C-C7 (hex) Alert Alarm AB +000000-0FFFFF (base 16) Alert Alarm AB + Råsundavägen 4 + Solna Stockholm 16967 + SE + +4C-BC-98 (hex) Shenzhen Shanling Digital Technology Development Co.,Ltd. +800000-8FFFFF (base 16) Shenzhen Shanling Digital Technology Development Co.,Ltd. + No.10, Chiwan 1 Road, Shekou, Nanshan + Shenzhen GuangDong 518068 + CN + +E4-4C-C7 (hex) JSC Svyaz Inginiring M +300000-3FFFFF (base 16) JSC Svyaz Inginiring M + Varshavskoe Shosse, 42 + Moscow 115230 + RU + +4C-BC-98 (hex) Nemon Co., Ltd. +400000-4FFFFF (base 16) Nemon Co., Ltd. + B-834, 164 Tancheonsangro, Bundang + Seongnam Gyeonggi 13631 + KR + +E0-5A-9F (hex) ShenZhen Arts Changhua Intelligent Technology Co., Ltd +E00000-EFFFFF (base 16) ShenZhen Arts Changhua Intelligent Technology Co., Ltd + 15i, Taibang Science & Technology Building, Science and Technology South 8th Road, Hi-Tech Park South Area + Shenzhen Guangdong 518057 + CN + +8C-C8-F4 (hex) Private +700000-7FFFFF (base 16) Private + +98-02-D8 (hex) Private +F00000-FFFFFF (base 16) Private + +D8-86-0B (hex) Get SAT +200000-2FFFFF (base 16) Get SAT + Hamada 12 + Rehovot Select From Dropdown 7670316 + IL + +E0-5A-9F (hex) OMB Guitars LLC +700000-7FFFFF (base 16) OMB Guitars LLC + 24 Hazorim St + Efrat Jerusalem 90435 + IL + +E0-5A-9F (hex) AITEC SYSTEM CO., LTD. +100000-1FFFFF (base 16) AITEC SYSTEM CO., LTD. + 466-1 Aoto-cho, Midori-ku + Yokohama-shi Kanagawa 226-0022 + JP + +C4-FF-BC (hex) viRaTec GmbH +E00000-EFFFFF (base 16) viRaTec GmbH + Phorusgasse 8/1 + Wien 1040 + AT + +38-B1-9E (hex) Basalte BVBA +400000-4FFFFF (base 16) Basalte BVBA + Hundelgemsesteenweg 1a + Merelbeke 9820 + BE + +CC-D3-9D (hex) Continental Control Systems +200000-2FFFFF (base 16) Continental Control Systems + 2150 Miller Drive Suite A + Longmont CO 80501 + US + +CC-D3-9D (hex) Hangzhou Scooper Technology Co.,Ltd. +C00000-CFFFFF (base 16) Hangzhou Scooper Technology Co.,Ltd. + Room706,707,5th,No.998,Wenyi West Raod,Wuchang Street,Yuhang District,Hangzhou + HangZhou ZheJiang 311121 + CN + +CC-D3-9D (hex) INX CO.,LTD. +000000-0FFFFF (base 16) INX CO.,LTD. + 6F Nippatsu Nishiguchi Bldg 3-32-1 Tsuruya-cho Kanagawa-ku + Yokohama-shi Kanagawa 221-0835 + JP + +D4-25-CC (hex) Nanjing LES Information Technology Co., Ltd +600000-6FFFFF (base 16) Nanjing LES Information Technology Co., Ltd + No.8,YongZhi Road + Nanjing Jiangsu 210014 + CN + +D4-25-CC (hex) Veea +B00000-BFFFFF (base 16) Veea + 164 E183rd street + New York NY 10028 + US + +D4-25-CC (hex) Combined Energy Technologies Pty Ltd +D00000-DFFFFF (base 16) Combined Energy Technologies Pty Ltd + 19 The Avenue + Newport NSW 2106 + AU + +9C-69-B4 (hex) Globalcom Engineering SPA +400000-4FFFFF (base 16) Globalcom Engineering SPA + Via Volta 9 + MORNAGO VA 21020 + IT + +4C-91-7A (hex) Inster Tecnología y Comunicaciones SAU +100000-1FFFFF (base 16) Inster Tecnología y Comunicaciones SAU + Avda. Rita Levi Montalcini, 2 Parcela 5, Tecnogetafe - Getafe + Madrid 28906 + ES + +4C-91-7A (hex) S.I.C.E.S. srl +700000-7FFFFF (base 16) S.I.C.E.S. srl + Via Molinello, 8B + Jerago con Orago VARESE 21040 + IT + +9C-69-B4 (hex) MOZI (Shenzhen) Artificial Intelligence Technology Co., Ltd. +200000-2FFFFF (base 16) MOZI (Shenzhen) Artificial Intelligence Technology Co., Ltd. + Room 1305, Building A Phase I Innovation and Technology Square, 4 Tairan Road, Futian + Shenzhen Guangdong 518000 + CN + +9C-69-B4 (hex) Appareo Systems, LLC +300000-3FFFFF (base 16) Appareo Systems, LLC + 1830 NDSU Research Circle N + Fargo ND 58102 + US + +6C-DF-FB (hex) Guilin Zhishen Information TechonlogyCO.,Ltd +A00000-AFFFFF (base 16) Guilin Zhishen Information TechonlogyCO.,Ltd + Creative Industrial Park,GuiMo Rd.,Qi Xing + Guilin Guangxi 541004 + CN + +6C-DF-FB (hex) Greenbird Vertriebs GmbH +500000-5FFFFF (base 16) Greenbird Vertriebs GmbH + Georg Sigl-Straße 40-42 + Breitenfurt bei Wien Niederösterreich 2384 + AT + +0C-EF-AF (hex) Private +F00000-FFFFFF (base 16) Private + +6C-DF-FB (hex) Toucan Systems Ltd +C00000-CFFFFF (base 16) Toucan Systems Ltd + 3 Roseheyworth Business Park + Abertillery Bleanau Gwent NP13 1SP + GB + +98-F9-C7 (hex) Promess GmbH +400000-4FFFFF (base 16) Promess GmbH + Schaffhausener Str. 44 + Berlin 12099 + DE + +98-F9-C7 (hex) Renalsense +800000-8FFFFF (base 16) Renalsense + Hamarpe 3 + Jerusalem 9777403 + IL + +98-F9-C7 (hex) SHENZHEN HUNTKEY ELECTRIC CO., LTD. +000000-0FFFFF (base 16) SHENZHEN HUNTKEY ELECTRIC CO., LTD. + Huntkey Industrial Park, Xue-Xiang Village, Bantian, Longgang District, + Shenzhen Guangdong 518129 + CN + +98-F9-C7 (hex) HighSecLabs +100000-1FFFFF (base 16) HighSecLabs + 29 Haeshel St + Caesarea 3088900 + IL + +0C-FE-5D (hex) CTK Contact Electronics co., Ltd. +800000-8FFFFF (base 16) CTK Contact Electronics co., Ltd. + 6F-5, No79, Sec 1, Xintai 5th RD, Xizhi Dist + New Taipei City 22101 + TW + +0C-FE-5D (hex) Fujian Jieyu Computer Technology Co., Ltd. +A00000-AFFFFF (base 16) Fujian Jieyu Computer Technology Co., Ltd. + 3rd Floor, Building 21, Cangshan Park, Jinshan Orange Garden Industrial Park, Cangshan District + Fuzhou Fujian 350000 + CN + +A4-58-0F (hex) Homebeaver +C00000-CFFFFF (base 16) Homebeaver + 3 place ville marie, 4th floor + Montreal Quebec H3B 2E3 + CA + +6C-5C-3D (hex) Clinton Electronics Corporation +E00000-EFFFFF (base 16) Clinton Electronics Corporation + 6701 Clinton Road + Loves Park IL 61111 + US + +0C-FE-5D (hex) Dspread International Co.,Limited +200000-2FFFFF (base 16) Dspread International Co.,Limited + UNIT 402. 4/F FAIRMONT HSE NO.8 COTTON TREE DRIVE ADMIRALTY + HONG KONG HONG KONG 999077 + HK + +1C-FD-08 (hex) sunweit industrial limited +700000-7FFFFF (base 16) sunweit industrial limited + Block A ,503B Room,Zhihui Innovation Centre + Shenzhen GUANGDONG 518000 + CN + +1C-FD-08 (hex) InSeat Solutions, LLC +000000-0FFFFF (base 16) InSeat Solutions, LLC + 1871 Wright Avenue + La Verne CA 91750 + US + +1C-FD-08 (hex) guangzhou huiqun intelligent technology co. LTD +B00000-BFFFFF (base 16) guangzhou huiqun intelligent technology co. LTD + room 502, building 2, no. 6, haijing road, xinzao town, panyu district + guangzhou guangdong 511436 + CN + +1C-FD-08 (hex) SABIK Offshore GmbH +400000-4FFFFF (base 16) SABIK Offshore GmbH + Wilhelm-Maybach-Straße 3 + Schwerin Mecklenburg-Vorpommern D-19061 + DE + +1C-FD-08 (hex) HiHi Ltd +200000-2FFFFF (base 16) HiHi Ltd + Loewy House 11 Enterprise Way + Christchurch BH236EW + GB + +1C-FD-08 (hex) Umeox Innovations Co.,Ltd +300000-3FFFFF (base 16) Umeox Innovations Co.,Ltd + Room 1208-09, Research Building, Tsinghua Information Port, No. 1, Xindong Road, Nanshan District, Shenzhen + Shenzhen Guangdong 518000 + CN + +6C-5C-3D (hex) Hangzhou Netease Yanxuan Trading Co.,Ltd +600000-6FFFFF (base 16) Hangzhou Netease Yanxuan Trading Co.,Ltd + Room 410,No.4 Building,No.599 Road Wangshang, + Hangzhou, Binjiang District, Zhejiang Province 310052 + CN + +6C-5C-3D (hex) Shenzhen Justek Technology Co., Ltd +100000-1FFFFF (base 16) Shenzhen Justek Technology Co., Ltd + 5/F, Building No.818, Qingtiexi Mabu Community, Bao 'an DistrictXixiang Street, + Shenzhen Guangdong 518102 + CN + +3C-6A-2C (hex) Beijing Donghua Hongtai Polytron Technologies Inc +E00000-EFFFFF (base 16) Beijing Donghua Hongtai Polytron Technologies Inc + Room 126,Layer 1, Mudan building, , Huayuan Road No. 2, Haidian District + Beijing Beijing 100089 + CN + +D0-22-12 (hex) Private +F00000-FFFFFF (base 16) Private + +CC-1B-E0 (hex) Private +F00000-FFFFFF (base 16) Private + +3C-6A-2C (hex) Homegear GmbH +700000-7FFFFF (base 16) Homegear GmbH + Am Schützenplatz 3 + Preetz Schleswig-Holstein 24211 + DE + +30-0A-60 (hex) Sixth Energy Technologies Private Limited +D00000-DFFFFF (base 16) Sixth Energy Technologies Private Limited + #62, Sri Varda, 10th main, HMT Layout, R.T.Nagar + Bangalore Karnataka 560032 + IN + +3C-6A-2C (hex) Rio Lago Technologies LLC +000000-0FFFFF (base 16) Rio Lago Technologies LLC + 17741 Ludlow St. + Granada Hills CA 91344-4502 + US + +30-0A-60 (hex) Private +300000-3FFFFF (base 16) Private + +30-0A-60 (hex) KAZUtechnica Co.,Ltd. +000000-0FFFFF (base 16) KAZUtechnica Co.,Ltd. + 1-9-18,Chuo,Chuo-ku + Sagamihara-shi Kanagawa 2520239 + JP + +30-0A-60 (hex) A9 +500000-5FFFFF (base 16) A9 + 27,BUCHEON-RO 198BEON-GIL + BUCHEON-SI GYEONGGI-DO 14555 + KR + +30-0A-60 (hex) Imageo s.r.o. +E00000-EFFFFF (base 16) Imageo s.r.o. + Golcova 485 + Praha 14800 + CZ + +3C-6A-2C (hex) La Barrière Automatique +600000-6FFFFF (base 16) La Barrière Automatique + 451 chemin de Champivost + Limonest 69760 + FR + +74-E1-4A (hex) Private +F00000-FFFFFF (base 16) Private + +C8-8E-D1 (hex) Private +F00000-FFFFFF (base 16) Private + +A4-ED-43 (hex) Heyuan intelligence technology CO.,Ltd +900000-9FFFFF (base 16) Heyuan intelligence technology CO.,Ltd + No.1166 Xinluo Street + Jinan City Shandong Province 250101 + CN + +A0-28-33 (hex) JGR Optics Inc +500000-5FFFFF (base 16) JGR Optics Inc + 160 Michael Cowpland Drive + Ottawa Ontario K2M 1P6 + CA + +A0-28-33 (hex) Firm INFORMTEST Ltd. +400000-4FFFFF (base 16) Firm INFORMTEST Ltd. + APT. 8, LODG. XIV ,FL.6, bld.4, Passage Savelkinsky + Zelenograd Moscow 124482 + RU + +A0-28-33 (hex) Kryptus Information Security S/A +700000-7FFFFF (base 16) Kryptus Information Security S/A + Rua Maria Tereza Dias da Silva 270 + Cidade Universitaria Campinas-SP CEP 13083-820 + BR + +A0-28-33 (hex) IMESHX CORPORATION LIMITED +900000-9FFFFF (base 16) IMESHX CORPORATION LIMITED + 10A7F, ShenZhen Bay Technology Ecological Park, NanShan District, + Shenzhen Guangdong 518000 + CN + +9C-F6-DD (hex) Savari Inc +800000-8FFFFF (base 16) Savari Inc + 2005 De la cruz blvd, st 111, + santa clara CA 95050 + US + +58-E8-76 (hex) Private +000000-0FFFFF (base 16) Private + +30-09-F9 (hex) Beijing Mydreamplus Information Technology Co., Ltd. +600000-6FFFFF (base 16) Beijing Mydreamplus Information Technology Co., Ltd. + Room 301-2, North Building, No. 11, CangJingGuan Lane, DongCheng District, + Beijing Beijing 100005 + CN + +84-89-EC (hex) Newell Brands +A00000-AFFFFF (base 16) Newell Brands + 221 River Street + Hoboken NJ 07030 + US + +84-89-EC (hex) EPSa Elektronik & Präzisionsbau Saalfeld GmbH +B00000-BFFFFF (base 16) EPSa Elektronik & Präzisionsbau Saalfeld GmbH + Remschuetzer Str. 1 + Saalfeld/Saale 07318 + DE + +30-09-F9 (hex) Shenzhen Sunvell Electronics Co., Ltd. +100000-1FFFFF (base 16) Shenzhen Sunvell Electronics Co., Ltd. + 5th Floor, Building F, Hongzhu Yongqi Technology Park, Lezhujiao Village, Xixiang Town, Bao’ an District, + Shenzhen GuangDong 518000 + CN + +30-09-F9 (hex) Shenzhen Tencent Computer System Co., Ltd. +A00000-AFFFFF (base 16) Shenzhen Tencent Computer System Co., Ltd. + 5-10 Building High-tech Zone, Nanshan District, + Shenzhen Guangdong Province 518057 + CN + +30-09-F9 (hex) essence security +800000-8FFFFF (base 16) essence security + Aba Even 12 st + Herzelia 4672530 + IL + +30-09-F9 (hex) Maytronics Ltd. +700000-7FFFFF (base 16) Maytronics Ltd. + Kibbutz Yizrael + Kibbutz Yizrael 1935000 + IL + +30-09-F9 (hex) VELSITEC-CLIBASE +500000-5FFFFF (base 16) VELSITEC-CLIBASE + LA RATELIERE + SAINT-JUST-MALMONT Haute-Loire 43240 + FR + +C0-83-59 (hex) Shenzhen Pay Device Technology Co., Ltd. +900000-9FFFFF (base 16) Shenzhen Pay Device Technology Co., Ltd. + Room 502,Peng’s Building,Fanshen Road,43# Baoan District + Shenzhen Guangdong 518101 + CN + +9C-F6-DD (hex) RYEEX Technology Co.,Ltd. +300000-3FFFFF (base 16) RYEEX Technology Co.,Ltd. + RM106,Joinin Hub,Builing J District 71,Construction Industrial Park,Xin'an Street,Bao'an, Shenzhen,China + SHENZHEN GUANGDONG 518101 + CN + +9C-F6-DD (hex) Lighting New Energy Technology Co., Ltd. +C00000-CFFFFF (base 16) Lighting New Energy Technology Co., Ltd. + Room 402, Building 22, Chentian Industrial Zone, Xixiang Street, Bao'an District, + Shenzhen Guangdong 518100 + CN + +C0-83-59 (hex) Cyber Sciences, Inc. +E00000-EFFFFF (base 16) Cyber Sciences, Inc. + 229 Castlewood Dr, Suite E + Murfreesboro TN 37129 + US + +C0-83-59 (hex) Private +C00000-CFFFFF (base 16) Private + +C0-83-59 (hex) Huaxin SM Optics Co. LTD. +200000-2FFFFF (base 16) Huaxin SM Optics Co. LTD. + 5F,B8,Tianfu software Park,Tianfu Road + Chengdu Sichuan 610041 + CN + +04-C3-E6 (hex) Flintec UK Ltd. +B00000-BFFFFF (base 16) Flintec UK Ltd. + W4/5 Capital Point, Wentloog Avenue + Cardiff Cardiff CF3 2PW + GB + +3C-42-7E (hex) Grandway Technology (Shenzhen) Limited +000000-0FFFFF (base 16) Grandway Technology (Shenzhen) Limited + Block 7, Zhu Keng Industrial Zone + Ping Shan District Shenzhen 518118 + CN + +04-C3-E6 (hex) Ekin Teknoloji San ve Tic A.S. +900000-9FFFFF (base 16) Ekin Teknoloji San ve Tic A.S. + maden mah. gediz. sok. no:7, sariyer + istanbul 34450 + TR + +04-C3-E6 (hex) Invasys +500000-5FFFFF (base 16) Invasys + Sochorova 36 + Brno 616 00 + CZ + +04-C3-E6 (hex) Extech Electronics Co., LTD. +300000-3FFFFF (base 16) Extech Electronics Co., LTD. + 17F., No.237, Sec. 1, Datong Rd., Xizhi Dist. + New Taipei City 22161 + TW + +C0-83-59 (hex) Viper Design, LLC +500000-5FFFFF (base 16) Viper Design, LLC + 125 Glancy St. + Goodlettsville TN 37072 + US + +B4-4B-D6 (hex) Qstar Technology Co,Ltd +900000-9FFFFF (base 16) Qstar Technology Co,Ltd + 311# Xindongxing Business Centre ,2rd Road liuxian ,Bao'an Shenzhen China + Shenzhen Guangdong 518100 + CN + +B4-4B-D6 (hex) CHUNGHSIN INTERNATIONAL ELECTRONICS CO.,LTD. +E00000-EFFFFF (base 16) CHUNGHSIN INTERNATIONAL ELECTRONICS CO.,LTD. + 618-2# Gongren West Road,Jiaojiang, + Taizhou Zhejiang 317700 + CN + +B4-4B-D6 (hex) Arnouse Digital Devices Corp +800000-8FFFFF (base 16) Arnouse Digital Devices Corp + 1983 Marcus Ave, Suite 104 + Lake Success NY 11042 + US + +3C-42-7E (hex) Teknoware Oy +400000-4FFFFF (base 16) Teknoware Oy + Ilmarisentie 8 + Lahti 15200 + FI + +D4-7C-44 (hex) Tendzone International Pte Ltd +A00000-AFFFFF (base 16) Tendzone International Pte Ltd + Rm 202, Blk C, Huahan Innovation Park, No.16 Langshan Rd,Nanshan District + Shenzhen GuangDong 518057 + CN + +D4-7C-44 (hex) Innoviz Technologies LTD +100000-1FFFFF (base 16) Innoviz Technologies LTD + Atir Yeda 15 + Kfar Saba Ha Sharon 4464312 + IL + +D4-7C-44 (hex) Exafore Oy +000000-0FFFFF (base 16) Exafore Oy + Hermiankatu 6-8D + Tampere 33720 + FI + +D4-7C-44 (hex) OMRON SENTECH CO., LTD. +300000-3FFFFF (base 16) OMRON SENTECH CO., LTD. + 9F, Ebina Prime Tower, 9-50, Chuo 2 Chome + Ebina-City Kanagawa 243-0432 + JP + +2C-48-35 (hex) Rheonik Messtechnik GmbH +200000-2FFFFF (base 16) Rheonik Messtechnik GmbH + Rudolf-Diesel-Str., 5 + Odelzhausen Deutschland 85235 + DE + +A0-19-B2 (hex) Adomi +A00000-AFFFFF (base 16) Adomi + 777 Mariners Island Blvd. Suite 150 + San Mateo CA 94404 + US + +A0-19-B2 (hex) Osatec +400000-4FFFFF (base 16) Osatec + 15 Parkovaya + Moscow 105203 + WS + +A0-19-B2 (hex) Lon Microsystems Inc. +900000-9FFFFF (base 16) Lon Microsystems Inc. + 11F Ali center Tianfu four street + chengdu sichuan 610041 + CN + +2C-48-35 (hex) SureFlap Ltd +900000-9FFFFF (base 16) SureFlap Ltd + 7 The Irwin Centre, Scotland Road, Dry Drayton + Cambridge Cambridgeshire CB23 8AR + GB + +CC-D3-1E (hex) ShenZhenBoryNet Co.,LTD. +E00000-EFFFFF (base 16) ShenZhenBoryNet Co.,LTD. + building 9.C-18-n,baoneng tech.park qingxiang road longhua district,shenzhen + shenzhen guangzhou 518109 + CN + +2C-48-35 (hex) Santec Corporation +C00000-CFFFFF (base 16) Santec Corporation + 5823 Ohkusa-Nenjozaka + Komaki Aichi 485-0802 + JP + +2C-48-35 (hex) Exertus Oy +600000-6FFFFF (base 16) Exertus Oy + Kampusranta 9 C + Seinäjoki 60320 + FI + +8C-1C-DA (hex) Alcidae Inc +C00000-CFFFFF (base 16) Alcidae Inc + 535 Mission St, 14th Fl, + San Francisco CA 94105 + US + +8C-1C-DA (hex) Electronic Controlled Systems, Inc. +E00000-EFFFFF (base 16) Electronic Controlled Systems, Inc. + 11200 Hampshire Ave South + Bloomington MN 55438 + US + +8C-1C-DA (hex) LocoLabs LLC +600000-6FFFFF (base 16) LocoLabs LLC + 3350 Scott Blvd, Bldg 56 + Santa Clara CA 95054 + US + +3C-24-F0 (hex) Wisycom +300000-3FFFFF (base 16) Wisycom + Via Spin 156 + Romano D'Ezzelino Vicenza 36060 + IT + +3C-24-F0 (hex) SHENZHEN PINSIDA TECHNOLOGY CO.,LTD. +000000-0FFFFF (base 16) SHENZHEN PINSIDA TECHNOLOGY CO.,LTD. + 411,4/F,Building A,Pengnian Science Park,Honghua IV Road,Xili,Nanshan District + Shenzhen Guangdong 518000 + CN + +0C-73-EB (hex) Shenzhen Samchung Video Technology Co., Ltd. +C00000-CFFFFF (base 16) Shenzhen Samchung Video Technology Co., Ltd. + Xixiang Street 4016 Bao'an Avenue + Yong Kai Business Building A, Bao'an District of Shenzhen City Guangdong 528470 + CN + +8C-1C-DA (hex) GEOMC +200000-2FFFFF (base 16) GEOMC + Suite514, 130, Digital-ro + Seoul 08589 + KP + +3C-24-F0 (hex) Laipac Technology Inc. +200000-2FFFFF (base 16) Laipac Technology Inc. + 20 Mural St. Unit 5 + Richmond Hill ON - Ontario L4B 1K3 + CA + +3C-24-F0 (hex) Inter-Coastal Electronics +400000-4FFFFF (base 16) Inter-Coastal Electronics + 5750 E McKellips Rd + Mesa AZ 85215 + US + +0C-73-EB (hex) Beijing L&S Lancom Platform Tech. Co., Ltd. +900000-9FFFFF (base 16) Beijing L&S Lancom Platform Tech. Co., Ltd. + 1st Floor, Xingtianhaiyuan Building, Xianghuangqi Eaast Rd, Nondda South Rd,Haidian District + Beijing 100193 + CN + +0C-73-EB (hex) EVERSEC TECHNOLOGY CORPORATION +100000-1FFFFF (base 16) EVERSEC TECHNOLOGY CORPORATION + F5,Tower D,JingYi Technology Building NO.9 Dazhongsi East Road.,Beijing,P.R.China + BEIJING BEIJING 100086 + CN + +0C-73-EB (hex) Beijing Miiiw Technology Co., Ltd +800000-8FFFFF (base 16) Beijing Miiiw Technology Co., Ltd + Room 3008, 3rd Floor, Qunfang Building, Bowangyuan, Yangfangdian Rd, Haidian District + Beijing 100010 + CN + +48-0B-B2 (hex) XIAMEN RONGTA TECHNOLOGY CO.,LTD. +A00000-AFFFFF (base 16) XIAMEN RONGTA TECHNOLOGY CO.,LTD. + 3F, E Plant, Gaoqi Industrial Zones, No.195, Gaoqi Community, Gaodian Village, Huli + Xiamen 361000 + CN + +48-0B-B2 (hex) Beijing Dragon Resources Limited. +700000-7FFFFF (base 16) Beijing Dragon Resources Limited. + Tongjunzhuangxinlukou (500meters east) Shilipu Town, MiyunCountry, Beijing101500, China + BeiJing 101500 + CN + +48-0B-B2 (hex) Thales CETCA Avionics CO., Ltd +200000-2FFFFF (base 16) Thales CETCA Avionics CO., Ltd + NO.9 Baichuan road,Hi-tech industry west zone park, Chengdu, Sichuan + Chengdu Sichuan 611731 + CN + +88-5F-E8 (hex) Inor Process AB +C00000-CFFFFF (base 16) Inor Process AB + Travbanegatan 10 + Malmo Skane SE-213 77 + SE + +88-5F-E8 (hex) Beijing laiwei Technology Co.,Ltd +400000-4FFFFF (base 16) Beijing laiwei Technology Co.,Ltd + Room 205,2/F,No.1 Fazhan Road Beijing information international base Huilongguan town Changping district Beijing + Beijing Beijing 102206 + CN + +88-5F-E8 (hex) zhejiang yuanwang communication technolgy co.,ltd +D00000-DFFFFF (base 16) zhejiang yuanwang communication technolgy co.,ltd + No. 6 of shen shi lei lu Road + ZhuJi Zhejiang 311800 + CN + +B8-D8-12 (hex) Visual Productions BV +800000-8FFFFF (base 16) Visual Productions BV + Rollandstraat 55ZW + Haarlem 2013SM + NL + +30-1F-9A (hex) NCM Supplies, Inc. +400000-4FFFFF (base 16) NCM Supplies, Inc. + 8125 NW 64th Street + Miami FL 33166 + US + +30-1F-9A (hex) Triax A/S +700000-7FFFFF (base 16) Triax A/S + Bjornkaervej 3 + Hornsyld Denmark 8783 + DK + +F0-41-C8 (hex) POSTIUM KOREA CO., LTD. +800000-8FFFFF (base 16) POSTIUM KOREA CO., LTD. + A208 Samsong Techno Valley, 140 Tongil-ro, Deogyang-gu + Koyang-si Kyeonggi-do 10594 + KR + +30-1F-9A (hex) Origami Group Limited +C00000-CFFFFF (base 16) Origami Group Limited + Unit 913, 9/F.,Tower 2 Cheung Sha Wan Plaza, 833 Cheung Sha Wan Road, Kowloon + Hong Kong 000000 + HK + +30-1F-9A (hex) Shenzhen Fengliyuan Energy Conservating Technology Co. Ltd +E00000-EFFFFF (base 16) Shenzhen Fengliyuan Energy Conservating Technology Co. Ltd + 8th floor of building A, Baoshan Industrial Estate, Longhua District, Shenzhen + Shenzhen Guangdong 518131 + CN + +F0-41-C8 (hex) LINPA ACOUSTIC TECHNOLOGY CO.,LTD +000000-0FFFFF (base 16) LINPA ACOUSTIC TECHNOLOGY CO.,LTD + 2A,No60 , Lizhong Road,DaliQingxi Town + Dongguan Guandong 523648 + CN + +88-A9-A7 (hex) Honeywell spol. s.r.o. HTS CZ o.z. +200000-2FFFFF (base 16) Honeywell spol. s.r.o. HTS CZ o.z. + Turanka 100/1387 + Brno 62700 + CZ + +88-A9-A7 (hex) TWK-ELEKTRONIK +B00000-BFFFFF (base 16) TWK-ELEKTRONIK + Heinrichstr. 85 + Duesseldorf 40239 + DE + +88-A9-A7 (hex) AndroVideo Inc. +C00000-CFFFFF (base 16) AndroVideo Inc. + 2f-4, 17, Lane 91, Nei Hu Rd., Sec. 1 + Taipei 11441 + TW + +F0-41-C8 (hex) XI'AN MEI SHANG MEI WIRELESS TECHNOLOGY.Co., Ltd. +500000-5FFFFF (base 16) XI'AN MEI SHANG MEI WIRELESS TECHNOLOGY.Co., Ltd. + Xi'an Beilin District Yanta Middle Road No. 17A XIN QING YA YUAN 2-5C + XI'AN shanxi 710000 + CN + +88-A9-A7 (hex) FlashForge Corporation +900000-9FFFFF (base 16) FlashForge Corporation + No.518, Xianyuan Road + Jinhua Zhejiang 321000 + CN + +A4-DA-22 (hex) AURANEXT +600000-6FFFFF (base 16) AURANEXT + 202 quai de clichy + CLICHY 92110 + FR + +DC-E5-33 (hex) WECAN Solution Inc. +600000-6FFFFF (base 16) WECAN Solution Inc. + 71, Yulhadong-ro 8-gil, Dong-gu, Daegu, Republic of Korea + Daegu 41102 + KR + +A4-DA-22 (hex) Malldon Technology Limited +900000-9FFFFF (base 16) Malldon Technology Limited + 607 Longsheng Technology Building, Longhua Dist + Shenzhen Guangdong 518000 + CN + +88-A9-A7 (hex) Mikroelektronika +300000-3FFFFF (base 16) Mikroelektronika + Batajnicki drum 23 + Belgrade 11186 + RS + +C4-FF-BC (hex) Shenzhen C & D Electronics Co., Ltd. +600000-6FFFFF (base 16) Shenzhen C & D Electronics Co., Ltd. + 9th FIoor, Building 9, No.1 Qingxiang road, BaoNeng Science and TechnoIogy Industrial Park, Longhua New District + ShenZhen GuangDong 518000 + CN + +C4-FF-BC (hex) ShenZhen ZYT Technology co., Ltd +800000-8FFFFF (base 16) ShenZhen ZYT Technology co., Ltd + Floor four,Build C,FuSen Industrial park, HangCheng Avenue,Baoan District + Shenzhen GuangDong 518000 + CN + +C4-FF-BC (hex) Beijing KDF information technology co. LTD. +D00000-DFFFFF (base 16) Beijing KDF information technology co. LTD. + Room14C,TowerA,,LindaBuilding,No.8,Dongtucheng Road,Chaoyang District, Beijing. + Beijing 100013 + CN + +C4-FF-BC (hex) Advanced Navigation +A00000-AFFFFF (base 16) Advanced Navigation + Level 8, 37 Pitt Street + Sydney NSW 2000 + AU + +C4-FF-BC (hex) Mobiletron Electronics Co., Ltd +200000-2FFFFF (base 16) Mobiletron Electronics Co., Ltd + 85, Sec.4, Chung-Ching Rd., Ta-Ya District + Taichung 428 + TW + +C4-FF-BC (hex) KyongBo Electric Co., Ltd. +C00000-CFFFFF (base 16) KyongBo Electric Co., Ltd. + 5, Seongsuil-ro 12-gagil Seongdong-gu + Seoul 04792 + KR + +9C-43-1E (hex) ProMOS Technologies Inc. +500000-5FFFFF (base 16) ProMOS Technologies Inc. + 3A3, No.1, Lixing 1st Rd., East Dist., + Hsinchu City Taiwan 300 + TW + +9C-43-1E (hex) Wunda Group plc +800000-8FFFFF (base 16) Wunda Group plc + Unit 1-5, Hawthorn, Crick + Caldicot Monmouthshire NP26 5UT + GB + +9C-43-1E (hex) R-S-I Elektrotechnik GmbH CO KG +600000-6FFFFF (base 16) R-S-I Elektrotechnik GmbH CO KG + Woelkestrasse 11 + Schweitenkirchen 85276 + DE + +9C-43-1E (hex) CONTINENT Co. Ltd +900000-9FFFFF (base 16) CONTINENT Co. Ltd + Bumazhnaya st., 16/3 lit B, of. 414 + Saint-Petersburg 190020 + RU + +28-2C-02 (hex) Dexin Digital Technology Corp. Ltd. +300000-3FFFFF (base 16) Dexin Digital Technology Corp. Ltd. + No.10 and 12, Wuxing Fourth Road,Wuhou District Chengdu 610045 Sichuan, PR China + chengdu Sichuan 610045 + CN + +9C-43-1E (hex) Advanced Logic Technology (ALT) sa +300000-3FFFFF (base 16) Advanced Logic Technology (ALT) sa + Route de Niederpallen, 30H + Redange-sur-Attert Luxembourg 8506 + LU + +F8-B5-68 (hex) Beijing Wanji Techonology Co., Ltd. +900000-9FFFFF (base 16) Beijing Wanji Techonology Co., Ltd. + NO.12 Building,Zhongguancun Software Park,Haidian District + beijing beijing 100193 + CN + +28-2C-02 (hex) Telecom and Microelectonic Industries +700000-7FFFFF (base 16) Telecom and Microelectonic Industries + 1-ja ulica Buhvostova, d.12/11, korp.53, floor 13 + Moscow 107258 + RU + +28-2C-02 (hex) Systec Intelligent Building Technology (Tianjin) Co.,Ltd. +900000-9FFFFF (base 16) Systec Intelligent Building Technology (Tianjin) Co.,Ltd. + Room 1312, Building D, HI-Tech. Information Square, No.8 Huatian Rd., Huayuan HI-Tech. Park + Tianjin 300384 + CN + +F8-B5-68 (hex) ZAO "RADIUS Avtomatika" +E00000-EFFFFF (base 16) ZAO "RADIUS Avtomatika" + Panfilovskiy prospekt, 10/3 + Zelenograd Moscow 124489 + RU + +28-2C-02 (hex) Lookman Electroplast Industries Ltd +600000-6FFFFF (base 16) Lookman Electroplast Industries Ltd + Old No : 9, New No : 15, II Street Etn., III Main Road , CIT Nagar, Nandanam + Chennai Tamilnadu 600035 + IN + +F8-B5-68 (hex) SinePulse GmbH +A00000-AFFFFF (base 16) SinePulse GmbH + Kistlerhofstr. 170 + Munich D-81379 + DE + +F8-B5-68 (hex) Shenzhen New-Bund Technology Co., Ltd. +200000-2FFFFF (base 16) Shenzhen New-Bund Technology Co., Ltd. + Room20A, 20th Floor, HSAE Technology Building, Nanshan District, + Shenzhen 518000 + CN + +F8-B5-68 (hex) CloudMinds (Shenzhen) Holdings Co., Ltd +700000-7FFFFF (base 16) CloudMinds (Shenzhen) Holdings Co., Ltd + Tower 3, 33F, Unit B, Wangjing SOHO,Wangjing Street No.10 + beijing 100102 + CN + +40-48-FD (hex) Dorel Juvenile +800000-8FFFFF (base 16) Dorel Juvenile + 25 Forbes Blvd + Foxborough MA 02035 + US + +40-48-FD (hex) The 52nd Research Institute of China Electronic Technology Group Corporation +500000-5FFFFF (base 16) The 52nd Research Institute of China Electronic Technology Group Corporation + No.36 Ma Cheng Road, + Hangzhou Zhejiang 310012 + CN + +40-48-FD (hex) BEIJING C&W ELECTRONICS(GROUP)CO.,LTD +000000-0FFFFF (base 16) BEIJING C&W ELECTRONICS(GROUP)CO.,LTD + No.14 Jiuxianqiao,chaoyang,Beijing,China + Beijing Beijing 100015 + CN + +F8-B5-68 (hex) 3SI Security Systems, Inc +C00000-CFFFFF (base 16) 3SI Security Systems, Inc + 101 Lindenwood Drive, Suite 200 + Malvern PA 19355 + US + +40-48-FD (hex) NOX Systems AG +D00000-DFFFFF (base 16) NOX Systems AG + Alvierweg 17 + Vaduz FL 9490 + LI + +38-73-EA (hex) Lightform, Inc. +900000-9FFFFF (base 16) Lightform, Inc. + 123 Langton St. + San Francisco CA 94103 + US + +38-73-EA (hex) Live Sentinel +600000-6FFFFF (base 16) Live Sentinel + 27 Armthorpe Rd. + Brampton Ontario L6T 5M4 + CA + +EC-9F-0D (hex) Simula Technology Inc. +100000-1FFFFF (base 16) Simula Technology Inc. + 14 F, 1351, Zhong-Zheng Rd. + Taoyuan 330 + TW + +EC-9F-0D (hex) Shenzhen Compare Electronics Co., Ltd +600000-6FFFFF (base 16) Shenzhen Compare Electronics Co., Ltd + 18F 5D First Area, Shenzhen Bay Eco-tech Park, Nanshan District, Shenzhen 518057, China + Shenzhen City (深圳市) Guangdong 518057 + CN + +EC-9F-0D (hex) Zhejiang HEJU Communication Technology Co., Ltd +800000-8FFFFF (base 16) Zhejiang HEJU Communication Technology Co., Ltd + F4,Block B, Lotus Commercial Building,Lianhua Street 333#,XiHu District + HANGZHOU ZHEJIANG 310012 + CN + +34-D0-B8 (hex) OROSOUND SAS +B00000-BFFFFF (base 16) OROSOUND SAS + 48 RUE AMELOT + PARIS 75011 + FR + +AC-1D-DF (hex) Motec Pty Ltd +400000-4FFFFF (base 16) Motec Pty Ltd + 121 Merrindale Drive + Croydon South Victoria 3136 + AU + +AC-1D-DF (hex) Green IT Korea Co., Ltd. +700000-7FFFFF (base 16) Green IT Korea Co., Ltd. + 1, Gaun-ro 1-gil, Namyangju-si + Seoul 12263 + KR + +AC-1D-DF (hex) Shenzhen Ouzheng Electronic Tech Co,.Ltd +500000-5FFFFF (base 16) Shenzhen Ouzheng Electronic Tech Co,.Ltd + Longgang District Pinghu Street Fangkeng Road No 7 B Building 2nd Floor + Shenzhen Guangdong 518111 + CN + +CC-22-37 (hex) shenzhen zonglian network technology limited +A00000-AFFFFF (base 16) shenzhen zonglian network technology limited + floor 3, building 3, yuepeng industry area, guanlan avenue,longhua new district + shenzhen guangdong 518000 + CN + +CC-22-37 (hex) E Ink Corp +900000-9FFFFF (base 16) E Ink Corp + 1000 Technology Park Drive + Billerica MA 01821 + US + +74-1A-E0 (hex) Socionext Inc. +100000-1FFFFF (base 16) Socionext Inc. + Nomura Shin-Yokohama Bldg., 2-10-23 Shin-Yokohama, Kohoku-ku + Yokohama Kanagawa 222-0033 + JP + +CC-22-37 (hex) Safilo S.p.A. +800000-8FFFFF (base 16) Safilo S.p.A. + Settima Strada + Padova 35129 + IT + +2C-27-9E (hex) Electronique Bluewave Inc. +100000-1FFFFF (base 16) Electronique Bluewave Inc. + 5292 Marquette + Montreal Qc H2J 3Z3 + CA + +2C-27-9E (hex) Exegy Inc +A00000-AFFFFF (base 16) Exegy Inc + 349 Marshall Avenue, Suite 100 + Saint Louis 63119 + US + +90-4E-91 (hex) Shanghai JaWay Information Technology Co., Ltd. +B00000-BFFFFF (base 16) Shanghai JaWay Information Technology Co., Ltd. + Rm. 1102, Science and Technology Building A, No. 900 of Yishan Road, Xuhui District, + Shanghai 200030 + CN + +B8-D8-12 (hex) Glamo Inc. +000000-0FFFFF (base 16) Glamo Inc. + 6F Sunshinecity Bunkakaikan, + Tokyo Toshima-ku 1708630 + JP + +2C-27-9E (hex) FOCAL-JMLab +700000-7FFFFF (base 16) FOCAL-JMLab + 108 rue de l'Avenir + La Talaudière 42353 + FR + +90-4E-91 (hex) Teleepoch Ltd +300000-3FFFFF (base 16) Teleepoch Ltd + No.13 Langshan Rd,HiTech Park,Nanshan District + Shenzhen Guangdong 518000 + CN + +18-9B-A5 (hex) legendsky tech +D00000-DFFFFF (base 16) legendsky tech + RM2210 PENG YUN GE JINGLI MANSION NO.48 BEILI ROAD SOUTH + ShenZhen 518109 + CN + +18-9B-A5 (hex) SHENZHEN FIONEXX TECHNOLOGIES LTD. +A00000-AFFFFF (base 16) SHENZHEN FIONEXX TECHNOLOGIES LTD. + RM503, The 1st office Bldg, Vanke Red Cube Mansion, Buji Street, Longgang District, + shenzhen Guangdong 518000 + CN + +18-9B-A5 (hex) Beijing Xinertel Technology Co., Ltd. +700000-7FFFFF (base 16) Beijing Xinertel Technology Co., Ltd. + 101, Building No.5, No.8 Chuangye Road., Haidian District + Beijing Beijing 100085 + CN + +90-4E-91 (hex) Showtacle s.r.o. +C00000-CFFFFF (base 16) Showtacle s.r.o. + Pecnianska 21 + Bratislava Choose State / Province 85101 + SK + +18-9B-A5 (hex) Taiwan Name Plate Co.,LTD +E00000-EFFFFF (base 16) Taiwan Name Plate Co.,LTD + No.36, Huaya 1st Rd., Guishan Dist., Taoyuan City 33383, Taiwan + Taoyuan City Taiwan 33383 + CN + +18-9B-A5 (hex) Starfire Industries LLC +500000-5FFFFF (base 16) Starfire Industries LLC + 2109 South Oak St., Suite 100 + Champaign IL 61820 + US + +CC-1B-E0 (hex) Microtech System,Inc +000000-0FFFFF (base 16) Microtech System,Inc + A-1102, Digital Empire Building + Suwon Gyeonggi-do 16690 + KR + +18-9B-A5 (hex) Dectris Ltd. +000000-0FFFFF (base 16) Dectris Ltd. + Taefernweg 1 + Baden-Daettwil 5405 + CH + +34-29-8F (hex) Keystone Electronic Solutions +D00000-DFFFFF (base 16) Keystone Electronic Solutions + 469 Julius Jeppe St, Waterkloof + Pretoria Gauteng 0181 + ZA + +28-F5-37 (hex) Herbert Waldmann GmbH & Co. KG +900000-9FFFFF (base 16) Herbert Waldmann GmbH & Co. KG + Peter-Henlein-Straße 5 + Villingen-Schwenningen Baden-Württemberg 78056 + DE + +28-F5-37 (hex) Performance Motion Devices +E00000-EFFFFF (base 16) Performance Motion Devices + 1 Technology Park Drive + Westford MA 01886 + US + +28-F5-37 (hex) MyOmega Systems GmbH +600000-6FFFFF (base 16) MyOmega Systems GmbH + Neumeyerstr. 28-34 + Nürnberg Bavaria 90411 + DE + +78-D8-00 (hex) Björkviks Consulting AB +500000-5FFFFF (base 16) Björkviks Consulting AB + Hällkanavägen 7 + Bro 19791 + SE + +78-D8-00 (hex) Maddalena S.p.A. +B00000-BFFFFF (base 16) Maddalena S.p.A. + via G.B. Maddalena 2/4 + Povoletto UD 33040 + IT + +78-D8-00 (hex) SightLine Applications +900000-9FFFFF (base 16) SightLine Applications + 2828 SW CORBETT AVE + PORTLAND OR 97201 + US + +7C-BA-CC (hex) Briowireless Inc. +B00000-BFFFFF (base 16) Briowireless Inc. + 4593 Louis-B Mayer + Laval QC - Quebec H7P 6G5 + CA + +7C-BA-CC (hex) Virgin Orbit +700000-7FFFFF (base 16) Virgin Orbit + 4022 E. Conant Street + Long Beach CA 90808 + US + +7C-BA-CC (hex) SIGMA-ELEKTRO GmbH +D00000-DFFFFF (base 16) SIGMA-ELEKTRO GmbH + Dr.-Julius-Leber-Str. 15 + Neustadt an der Weinstraße Germany 67433 + DE + +F8-8A-3C (hex) Protos GmbH +A00000-AFFFFF (base 16) Protos GmbH + Herrschaftswiesen 11 + Koblach 6842 + AT + +4C-65-A8 (hex) TEL-Electronics Ltd +500000-5FFFFF (base 16) TEL-Electronics Ltd + Sovetskaya, 85 + Molzino Moscow region 142411 + RU + +F8-8A-3C (hex) Cadmus Electronic Co.,Ltd. +800000-8FFFFF (base 16) Cadmus Electronic Co.,Ltd. + 4F.-3, No.872, Jhongjheng Rd., Jhonghe Dist., + New Taipei City Taiwan (R.O.C.) 23586 + TW + +F8-8A-3C (hex) Carefree of Colorado +100000-1FFFFF (base 16) Carefree of Colorado + 2145 W 6th Ave + Broomfield CO 80020 + US + +F8-8A-3C (hex) KOKKIA INC +500000-5FFFFF (base 16) KOKKIA INC + 43575 Mission Blvd, #302 + Fremont CA 94539 + US + +F8-8A-3C (hex) Beijing Zhong Chuang Communication Technology Ltd. +600000-6FFFFF (base 16) Beijing Zhong Chuang Communication Technology Ltd. + RM# 712-35, 7th Floor, #2 Xin Xi Road, Shangdi, Haidian District + Beijing 100085 + CN + +F8-8A-3C (hex) GO-LINK TECHNOLOGY CO., LTD. +400000-4FFFFF (base 16) GO-LINK TECHNOLOGY CO., LTD. + Rm. 4, 14F., No.9, Sec.3, Zhonghua Rd., + Hsinchu City 30060 + TW + +4C-65-A8 (hex) Plus One Japan Limited +400000-4FFFFF (base 16) Plus One Japan Limited + 2-8-6,Nishishinbashi + Minato-ku Tokyo 105-0003 + JP + +8C-14-7D (hex) Electrical & Automation Larsen & Toubro Limited +E00000-EFFFFF (base 16) Electrical & Automation Larsen & Toubro Limited + Mysore Campus, KIADB Industrial Area, Hebbal, Hootagalli + Mysore Karnataka 570020 + IN + +8C-14-7D (hex) Bausch Datacom NV/SA +B00000-BFFFFF (base 16) Bausch Datacom NV/SA + Tiensesteenweg 54-56 + Korbeek-Lo Vlaams-Brabant - Belgium 3360 + BE + +8C-14-7D (hex) Nio +000000-0FFFFF (base 16) Nio + 3200 North 1st Street + San Jose NY 95134 + US + +A0-C5-F2 (hex) AiCare Corp. +400000-4FFFFF (base 16) AiCare Corp. + 1917 Scepter Ct + San Jose CA 95132 + US + +8C-14-7D (hex) Shenzhen Lanxus technology Co. Ltd. +D00000-DFFFFF (base 16) Shenzhen Lanxus technology Co. Ltd. + 3rd Floor, Block A, Aerospace micromotor building, Science Park North, Nanshan District + Shenzhen China 518000 + CN + +F0-23-B9 (hex) Ubiant +100000-1FFFFF (base 16) Ubiant + 2 Place de Francfort + Lyon 69003 + FR + +F0-23-B9 (hex) Q Core Medical Ltd +B00000-BFFFFF (base 16) Q Core Medical Ltd + Yad Haruzim 29, PO Box 8639 + Netanya 4250529 + IL + +40-ED-98 (hex) Integrated Design Ltd +A00000-AFFFFF (base 16) Integrated Design Ltd + Feltham Point, Air Park Way + Feltham Middlesex TW137EQ + GB + +04-71-4B (hex) Shenzhen BoClouds Technology Co.,Ltd. +D00000-DFFFFF (base 16) Shenzhen BoClouds Technology Co.,Ltd. + Room 909, Unit A, Cadre Group Centre Building, No.168 TongSha Road, XiLi Town, Nanshan + Shenzhen GuangDong 518000 + CN + +F0-23-B9 (hex) Annapurna labs +A00000-AFFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +F0-23-B9 (hex) BSP RUS Ltd. +300000-3FFFFF (base 16) BSP RUS Ltd. + 174/1 Stavropolskaya street + Krasnodar Krasnodar 350001 + RU + +04-71-4B (hex) Griesser Electronic AG +300000-3FFFFF (base 16) Griesser Electronic AG + Tänikonerstrasse 3 + Aadorf Thurgau 8355 + CH + +04-71-4B (hex) Bureau Electronique Appliquee +500000-5FFFFF (base 16) Bureau Electronique Appliquee + Allee des Noisetiers, 5 + ANGLEUR LIEGE 4031 + BE + +60-D7-E3 (hex) Ameli s.r.l. +600000-6FFFFF (base 16) Ameli s.r.l. + via Guido Rossa,10 + Impruneta Firenze 50023 + IT + +08-ED-02 (hex) Telstra Corporation Limited +E00000-EFFFFF (base 16) Telstra Corporation Limited + Level 2 / 150 Lonsdale St + Melbourne Victoria 3000 + AU + +98-AA-FC (hex) Dalian Eastern Display Co., Ltd. +000000-0FFFFF (base 16) Dalian Eastern Display Co., Ltd. + No.99-5 Huaihe Middle Road E.& T Development Zone Dalian, China + Dalian Liaoning 116600 + CN + +14-4F-D7 (hex) Edan Instruments, Inc. +E00000-EFFFFF (base 16) Edan Instruments, Inc. + No.15, Jinhui Rd., Jinsha Community, Kengzi Subdistrict, Pingshan District, + Shenzhen Guangdong 518122 + CN + +98-AA-FC (hex) SURTEC +100000-1FFFFF (base 16) SURTEC + 616 avenue de l'Europe + Le Creusot burgundy 71206 + FR + +08-ED-02 (hex) Origami Energy Ltd +D00000-DFFFFF (base 16) Origami Energy Ltd + Ashcombe Court, Woolsack Way + Godalming GU7 1LQ + GB + +14-4F-D7 (hex) Shanghai B&A Technology Co., Ltd +D00000-DFFFFF (base 16) Shanghai B&A Technology Co., Ltd + 4F, No. 150 Cailun Rd, Zhangjiang + Shanghai 201210 + CN + +14-4F-D7 (hex) Emerson Network Power (India) Pvt. Ltd. +900000-9FFFFF (base 16) Emerson Network Power (India) Pvt. Ltd. + Plot No. G-1, Additional Ambernath Industrial Area, MIDC Phase-2, Bohonoli + Ambernath, Maharashtra 421 506 + IN + +A4-11-63 (hex) SHENZHEN YIWANJIA INFORMATION TECHNOLOGY CO.,LTD +700000-7FFFFF (base 16) SHENZHEN YIWANJIA INFORMATION TECHNOLOGY CO.,LTD + Zone B,Floor 15,NO.2 Building,Yihe Road,Shilong Community,Shiyan Street,Baoan District + Shenzhen 518000 + CN + +14-4F-D7 (hex) FLS FINLAND OY +500000-5FFFFF (base 16) FLS FINLAND OY + Voudinkatu 35 A + Raisio FI21200 + FI + +A4-11-63 (hex) Carbon, Inc. +500000-5FFFFF (base 16) Carbon, Inc. + 312 Chestnut St + Redwood City CA 94063 + US + +A4-11-63 (hex) SHENZHEN ZHISHI TECHNOLOGY CO., LTD. +D00000-DFFFFF (base 16) SHENZHEN ZHISHI TECHNOLOGY CO., LTD. + Room 712 in 3A of Hecheng Century Garden,Wuhe Street South No.118,Longgang District,Shenzhen + SHENZHEN GUANG DONG 518000 + CN + +1C-A0-D3 (hex) OOO Tekhnotronika +000000-0FFFFF (base 16) OOO Tekhnotronika + Studeniy 4/1 + Moscow 127282 + RU + +40-A3-6B (hex) Securiton AG +600000-6FFFFF (base 16) Securiton AG + Alpenstrasse 20, P.O. Box 127 + Zollikofen CH-3052 + CH + +A4-11-63 (hex) Moog Music Inc. +B00000-BFFFFF (base 16) Moog Music Inc. + 160 Broadway St + Asheville NC 28801 + US + +40-F3-85 (hex) Teleepoch Ltd +800000-8FFFFF (base 16) Teleepoch Ltd + No.13 Langshan Rd,HiTech Park,Nanshan District + Shenzhen Guangdong 518000 + CN + +40-F3-85 (hex) SubPac +000000-0FFFFF (base 16) SubPac + 380 Portage Ave. + Palo Alto CA 94306 + US + +8C-C8-F4 (hex) Strongbyte Solutions Limited +800000-8FFFFF (base 16) Strongbyte Solutions Limited + Unit 7, Wychwood Business Centre + Chipping Norton Oxfordshire OX7 6XU + GB + +40-F3-85 (hex) Beijing Zongheng Electro-Mechanical Technology Development Co. +200000-2FFFFF (base 16) Beijing Zongheng Electro-Mechanical Technology Development Co. + No.1 Fenghui East Road, Yongfeng Industry Base, Haidian District, Beijing China + Beijing 100094 + CN + +8C-C8-F4 (hex) Evaporcool Solutions +E00000-EFFFFF (base 16) Evaporcool Solutions + 5100 Wilfong Road + Memphis TN 38134 + US + +40-F3-85 (hex) Creanord +A00000-AFFFFF (base 16) Creanord + Pasilanraitio 9B + Helsinki Uusimaa 00240 + FI + +40-F3-85 (hex) Digital Bros S.p.A. +D00000-DFFFFF (base 16) Digital Bros S.p.A. + via Tortona, 37 + Milan MI 20144 + IT + +8C-C8-F4 (hex) Dark Horse Connect LLC +200000-2FFFFF (base 16) Dark Horse Connect LLC + 13492 Research Blvd, Ste 336 + Austin TX 78750 + US + +8C-C8-F4 (hex) Shenzhen KSTAR Science and Technology Co., Ltd +C00000-CFFFFF (base 16) Shenzhen KSTAR Science and Technology Co., Ltd + Kstar Industrial Park, 7th Road, Guangming Hi- Tech Industrial Zone + Shenzhen 518070 + CN + +50-A4-D0 (hex) Changsha SinoCare, Inc +A00000-AFFFFF (base 16) Changsha SinoCare, Inc + No.265 Gu yuan road Hi-Tech Zone, Yuelu district + Changsha Hunan 410205 + CN + +50-A4-D0 (hex) Axel Technology +D00000-DFFFFF (base 16) Axel Technology + Via Caduti di Sabbiuno 6/F + Anzola dell'Emilia 40011 + IT + +50-A4-D0 (hex) Sagetech Corporation +E00000-EFFFFF (base 16) Sagetech Corporation + PO Box 1146 + White Salmon WA 98672 + US + +50-A4-D0 (hex) Raven Industries Inc. +400000-4FFFFF (base 16) Raven Industries Inc. + 205 E 6TH Street + Sioux Falls SD 57104 + US + +34-04-9E (hex) GoChip Inc. +000000-0FFFFF (base 16) GoChip Inc. + 275 Airpark Blvd, Suite 100 + Chico CA 95973 + US + +40-ED-98 (hex) A-IOX INC. +200000-2FFFFF (base 16) A-IOX INC. + 10Fl., No. 497, Sec. 2, Tiding Blvd., Neihu Dist. + Taipei City 11493 + TW + +34-04-9E (hex) Life Interface Co., Ltd. +600000-6FFFFF (base 16) Life Interface Co., Ltd. + 2-1-16 + Minato Tokyo 1050013 + JP + +40-ED-98 (hex) GuangZhou FiiO Electronics Technology Co.,Ltd +100000-1FFFFF (base 16) GuangZhou FiiO Electronics Technology Co.,Ltd + 201,2/F, F Building, Hougang Industrial Zone, Shigang Village, huangshi West Road,Baiyun District + GuangZhou 510430 + CN + +40-ED-98 (hex) BloomSky,Inc. +C00000-CFFFFF (base 16) BloomSky,Inc. + 723 N Shoreline Blvd. + Mountain view CA 94043 + US + +50-0B-91 (hex) Igor, Inc. +000000-0FFFFF (base 16) Igor, Inc. + 5619 NW 86th St. + Johnston IA 50131 + US + +A4-58-0F (hex) Stone Lock Global, Inc. +100000-1FFFFF (base 16) Stone Lock Global, Inc. + 101 N Church St + Olathe KS 66061 + US + +A4-58-0F (hex) AIR LIQUIDE MEDICAL SYSTEMS +800000-8FFFFF (base 16) AIR LIQUIDE MEDICAL SYSTEMS + + + + +50-0B-91 (hex) Annapurna labs +200000-2FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +A4-58-0F (hex) Ksenia Security srl +900000-9FFFFF (base 16) Ksenia Security srl + SP Valtesino 44 + Ripatransone AP 63065 + IT + +50-0B-91 (hex) Sinope technologies Inc +400000-4FFFFF (base 16) Sinope technologies Inc + 705 Montrichard + St-Jean-Sur-Richelieu Quebec J2X5K8 + CA + +7C-CB-E2 (hex) 1000eyes GmbH +200000-2FFFFF (base 16) 1000eyes GmbH + Joachimsthaler Str. 12 + Berlin 10719 + DE + +7C-CB-E2 (hex) SY Electronics Limited +600000-6FFFFF (base 16) SY Electronics Limited + 7 Worrall Street + Salford M5 4TH + GB + +7C-CB-E2 (hex) Aplex Technology Inc. +E00000-EFFFFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +24-4E-7B (hex) Nanjing Wanlida Technology Co., Ltd. +700000-7FFFFF (base 16) Nanjing Wanlida Technology Co., Ltd. + Wanlida Industry Zone, Nanjing County + Zhangzhou Fujian 363601 + CN + +7C-CB-E2 (hex) Hangzhou Haohaokaiche Technology Co.,Ltd. +900000-9FFFFF (base 16) Hangzhou Haohaokaiche Technology Co.,Ltd. + Building 7, Haichuang Park, No.998 Wenyi West Road, Yuhang District + Hangzhou Zhejiang 331000 + CN + +7C-CB-E2 (hex) DTECH Labs, Inc. +500000-5FFFFF (base 16) DTECH Labs, Inc. + 21580 Beaumeade Circle, Suite 230 + Ashburn VA 20147 + US + +48-65-EE (hex) shenzhen sunflower technologies CO., LIMITED +600000-6FFFFF (base 16) shenzhen sunflower technologies CO., LIMITED + 207, 4th Tower , ZhongXing industrial City, Nanshan zone + ShenZhen GangDong 518000 + CN + +48-65-EE (hex) DefPower Ltd +000000-0FFFFF (base 16) DefPower Ltd + 6 Repton Close + Basildon SS13 1LE + GB + +4C-E1-73 (hex) Shenzhen Evolution Dynamics Co., Ltd. +900000-9FFFFF (base 16) Shenzhen Evolution Dynamics Co., Ltd. + Room 1212, Wanjun trade building, Baoxing Rd No.21, Baoan District, Shenzhen City, China + shenzhen GuangDong 518100 + CN + +1C-C0-E1 (hex) Exigent Sensors +B00000-BFFFFF (base 16) Exigent Sensors + 11331 Markon Dr + Garden Grove CA 92841 + US + +1C-C0-E1 (hex) Ospicon Company Limited +900000-9FFFFF (base 16) Ospicon Company Limited + Room 1025, 10/F., Metro Centre II, 21 Lam Hing St., + Kowloon Bay Kowloon 00000 + HK + +4C-E1-73 (hex) Nexoforge Inc. +100000-1FFFFF (base 16) Nexoforge Inc. + 4514 47 Ave + Leduc Alberta T9E 5S9 + CA + +1C-C0-E1 (hex) NewLand (NZ) Communication Tech Limited +D00000-DFFFFF (base 16) NewLand (NZ) Communication Tech Limited + 39A WAIPA ST BIRKENHEAD + AUCKLAND Auckland 0626 + NZ + +AC-64-DD (hex) PFDC ELANCYL +800000-8FFFFF (base 16) PFDC ELANCYL + LES CAUQUILLOUS + 81506 LAVAUR CEDEX 81506 + FR + +AC-64-DD (hex) Shenzhen PuHua Technology Co., Ltd +200000-2FFFFF (base 16) Shenzhen PuHua Technology Co., Ltd + 4/F BLDG-B, Forzen Technology Park,Fuyuan 2nd Road, Fuyong Town, Baoan District + shenzhen 518103 + CN + +AC-64-DD (hex) Bluewave Global Manufacturing Limited +A00000-AFFFFF (base 16) Bluewave Global Manufacturing Limited + 82/F, International Commerce Centre, 1 Austin Road + West Kowloon 0 + HK + +AC-64-DD (hex) Wittmann Kunststoffgeräte GmbH +700000-7FFFFF (base 16) Wittmann Kunststoffgeräte GmbH + Lichtblaustraße 10 + Vienna Vienna 1220 + AT + +38-3A-21 (hex) R3C Information(Shenzhen) Co.,Ltd. +000000-0FFFFF (base 16) R3C Information(Shenzhen) Co.,Ltd. + 2F,JinHuiQiou Building,Langshan2 Road,Hi-Tech Ind.Park, Nanshan District + Shenzhen GuangDong 86 + CN + +38-3A-21 (hex) HOBART GmbH +100000-1FFFFF (base 16) HOBART GmbH + Robert-Bosch-Straße 17 + Offenburg Baden-Württemberg 77656 + DE + +F8-1D-78 (hex) GUANGDONG ENOK COMMUNICATION CO., LTD. +E00000-EFFFFF (base 16) GUANGDONG ENOK COMMUNICATION CO., LTD. + No.139 Lixiang road, Songmushan Dalang town, Dongguan,Guangdong ,China + DongGuan GuanDong 523795 + CN + +38-3A-21 (hex) OOO NPP Uraltechnologiya +500000-5FFFFF (base 16) OOO NPP Uraltechnologiya + Studencheskaya str. 16-130 + Ekaterinburg 620137 + RU + +F8-1D-78 (hex) WUHAN GUIDE INFRARED CO.,LTD +700000-7FFFFF (base 16) WUHAN GUIDE INFRARED CO.,LTD + No.6 Huanglongshan South Rd + Wuhan Hubei 430070 + CN + +F8-1D-78 (hex) SigmaConnectivityAB +B00000-BFFFFF (base 16) SigmaConnectivityAB + Mobilv 10 + Lund 223 62 + SE + +C0-D3-91 (hex) B9Creations +100000-1FFFFF (base 16) B9Creations + 525 University Loop Ste 115 + Rapid City SD 57701 + US + +F0-AC-D7 (hex) Fiziico Co., Ltd. +E00000-EFFFFF (base 16) Fiziico Co., Ltd. + 8F-3, No. 15, Ln 360, Sec. 1, Neihu Rd., Neihu District + Taipei 11493 + TW + +98-6D-35 (hex) my-PV GmbH +C00000-CFFFFF (base 16) my-PV GmbH + Teichstrasse 43 + Neuzeug 4523 + AT + +F0-AC-D7 (hex) Zhejiang Makepower Electronics,Inc. +B00000-BFFFFF (base 16) Zhejiang Makepower Electronics,Inc. + Building 2, Estate 10, Wenzhou Hi-Tech Industrial Development Area, zhejiang, China + shenzhen 518000 + CN + +28-36-38 (hex) CHARGELIB +500000-5FFFFF (base 16) CHARGELIB + 11 CITE VANEAU + PARIS 75007 + FR + +28-36-38 (hex) Georg Neumann GmbH +600000-6FFFFF (base 16) Georg Neumann GmbH + Leipziger Str. 112 + Berlin 10117 + DE + +B0-C5-CA (hex) EM-Tech +000000-0FFFFF (base 16) EM-Tech + 40, Changwon-daero 1144beon-gil, Seongsan-gu + Changwon Gyeongsangnam-do 642-120 + KR + +8C-19-2D (hex) Pyras Technology Inc. +D00000-DFFFFF (base 16) Pyras Technology Inc. + 6F, No. 1353, Chung Cheng Rd., Taoyuan Dist., + Taoyuan City Select State 33071 + TW + +8C-19-2D (hex) Noritsu Precision Co., Ltd. +000000-0FFFFF (base 16) Noritsu Precision Co., Ltd. + 579-1 Umehara + Wakayama Wakayama 640-8550 + JP + +78-CA-83 (hex) Eksagate Elektronik Mühendislik ve Bilgisayar San. Tic. A.Ş. +A00000-AFFFFF (base 16) Eksagate Elektronik Mühendislik ve Bilgisayar San. Tic. A.Ş. + ŞEHİT AHMET SOK. 12/1 MECİDİYEKÖY + istanbul 34381 + TR + +8C-19-2D (hex) smartHome Partner GmbH +600000-6FFFFF (base 16) smartHome Partner GmbH + Dalbker Strasse 138 + Oerlinghausen NRW 33813 + DE + +1C-87-76 (hex) Dspread Technology (Beijing) Inc. +000000-0FFFFF (base 16) Dspread Technology (Beijing) Inc. + Jingxin Building, 2045 Suite , Chaoyang District + Beijing 100027 + CN + +D0-D9-4F (hex) ARROWAVE TECHNOLOGIES LIMITED +C00000-CFFFFF (base 16) ARROWAVE TECHNOLOGIES LIMITED + L1, 1st Floor, LIC Colony, Sector-14, 10th Main, Jeevanbhima Nagar + Bangalore Karnataka 560075 + IN + +D0-D9-4F (hex) Shenzhen FDC Electuonic Co.,Ltd. +A00000-AFFFFF (base 16) Shenzhen FDC Electuonic Co.,Ltd. + Gushu Community, Xixiang Street, Baoan Dist. ShenZhen, GuangDong, China + Shenzhen Guangdong 518126 + CN + +CC-D3-1E (hex) PJG Systementwicklung GmbH +400000-4FFFFF (base 16) PJG Systementwicklung GmbH + Billrothstrasse 2A + Vienna Vienna 1190 + AT + +CC-D3-1E (hex) NantEnergy +C00000-CFFFFF (base 16) NantEnergy + 8455 North 90th Street Suite 4 + Scottsdale AZ 85258 + US + +E0-B6-F5 (hex) Advatek Lighting Pty Ltd +E00000-EFFFFF (base 16) Advatek Lighting Pty Ltd + 16 / 62 Ramset Drive + Chirnside Park VIC 3116 + AU + +E0-B6-F5 (hex) Shanghai- British Information Technology Co., Ltd +200000-2FFFFF (base 16) Shanghai- British Information Technology Co., Ltd + No.1 Building, No.433 Guoshoujing Road, Pudong District, Shanghai + shanghai 201203 + CN + +2C-26-5F (hex) AATON DIGITAL +C00000-CFFFFF (base 16) AATON DIGITAL + 2 RUE DE LA PAIX + GRENOBLE RHONE-ALPES 38000 + FR + +50-FF-99 (hex) Yongjing Shanghai Electronic Science and Technology +300000-3FFFFF (base 16) Yongjing Shanghai Electronic Science and Technology + Room 202,Building 2,No.65,Lane1398,Xin Zhu Road, Minhang District Shanghai. + shanghai shanghai 201100 + CN + +E0-B6-F5 (hex) Motiveprime Consumer Electronics Pvt Ltd +900000-9FFFFF (base 16) Motiveprime Consumer Electronics Pvt Ltd + #244,17th cross Sector 6 HSR Layout + Bangalore Karnataka 560102 + IN + +E0-B6-F5 (hex) Shenzhen Civicom Technology Co.,Limited +500000-5FFFFF (base 16) Shenzhen Civicom Technology Co.,Limited + Room 1302,Microprofit Building,Gaoxin 6th Avenue,Hi-tech Park,Nanshan District + Shenzhen Guangdong 518057 + CN + +50-FF-99 (hex) Garrison Technology +500000-5FFFFF (base 16) Garrison Technology + 20-22 Wenlock Road + London London N1 7GU + GB + +98-6D-35 (hex) PDAHL +500000-5FFFFF (base 16) PDAHL + Gammagatan 1 + Moelndal Sweden 43949 + SE + +7C-47-7C (hex) I-Convergence.com +E00000-EFFFFF (base 16) I-Convergence.com + 2A2212, No.32 Baiziwan Road, Chaoyang District + Beijing 100021 + CN + +7C-47-7C (hex) RLC Electronics Systems +400000-4FFFFF (base 16) RLC Electronics Systems + 10 Corporate Blvd. + Sinking Spring PA 19608 + US + +7C-47-7C (hex) DaLian Cheering Tech Co.,Ltd +900000-9FFFFF (base 16) DaLian Cheering Tech Co.,Ltd + 321-1 Tuqiang Street RM308,DDA + DaLian Liaoning 116023 + CN + +38-FD-FE (hex) Swedish Adrenaline AB +B00000-BFFFFF (base 16) Swedish Adrenaline AB + Pilefeltsgatan 73 + Halmstad 302 50 + SE + +38-FD-FE (hex) Indra Navia AS +800000-8FFFFF (base 16) Indra Navia AS + Olaf Helsets vei 6, P.O. Box 150 Oppsal + Oslo 0619 + NO + +38-FD-FE (hex) OOO Group of Industrial Technologies +900000-9FFFFF (base 16) OOO Group of Industrial Technologies + Profsoyuznaya st. 124A + Moscow Moscow 117321 + RU + +38-FD-FE (hex) Edge I&D Co., Ltd. +000000-0FFFFF (base 16) Edge I&D Co., Ltd. + 1342-12, Gyeongchung-daero, Chowol-eup + Gwangju-si Gyeonggi-do 12735 + KR + +5C-F2-86 (hex) Access IS +700000-7FFFFF (base 16) Access IS + 18 Suttons Business Park + READING Berks RG6 1AZ + GB + +38-B8-EB (hex) Ajax Systems Inc +C00000-CFFFFF (base 16) Ajax Systems Inc + 910 Foulk Road, Suite 201 + Wilmington, 19803 + UA + +38-B8-EB (hex) NHS Sistemas de Energia +900000-9FFFFF (base 16) NHS Sistemas de Energia + Juscelino Kubitscheck de Oliveira 5270 + Curitiba Parana 81260000 + BR + +38-B8-EB (hex) UMLOGICS +400000-4FFFFF (base 16) UMLOGICS + 17, Techno2ro, Yuseong-gu + Daejeon 34012 + KR + +38-B8-EB (hex) SECAD SA +A00000-AFFFFF (base 16) SECAD SA + Zac des Pellants + St Martin du Fresne 01430 + FR + +38-FD-FE (hex) Management Service Corporation +A00000-AFFFFF (base 16) Management Service Corporation + 1-7-12 Marunouchi, Chiyoda-ku + Tokyo 100-0005 + JP + +38-B8-EB (hex) Bumjin C&L Co., Ltd. +000000-0FFFFF (base 16) Bumjin C&L Co., Ltd. + 9B 10L, 833-14 Wonsi-dong Danwon-gu + Ansan Gyeonggi 15612 + KR + +78-CA-83 (hex) Pinhole (Beijing) Technology Co., Ltd. +400000-4FFFFF (base 16) Pinhole (Beijing) Technology Co., Ltd. + Room 1001-008, No.1 Building, No. 3 Haidian Street, Haidian District + Beijing 100190 + CN + +78-CA-83 (hex) Neofon GmbH +300000-3FFFFF (base 16) Neofon GmbH + Sonnengrund 13a + Starnberg 82319 + DE + +78-CA-83 (hex) APC +200000-2FFFFF (base 16) APC + PO Box 30204 + Al-Khobar 31952 + SA + +78-CA-83 (hex) Nomiku +600000-6FFFFF (base 16) Nomiku + 475 Alvarado St Apt 2 + San Francisco CA 94114 + US + +1C-88-79 (hex) Orion Labs inc +E00000-EFFFFF (base 16) Orion Labs inc + 2125 Mission St + San Francisco CA 94110 + US + +1C-88-79 (hex) Beijing Raycores Technology Co.,Ltd +D00000-DFFFFF (base 16) Beijing Raycores Technology Co.,Ltd + 1113# 11/F #A Building No.118 Huilongguan West Street,Changping District + Beijing 102208 + CN + +1C-87-74 (hex) Surtec Industries, Inc +800000-8FFFFF (base 16) Surtec Industries, Inc + 9 Kon Jan North Road, Liutu Industrial Zone + Keelung 20647 + TW + +1C-88-79 (hex) Ultraflux +400000-4FFFFF (base 16) Ultraflux + 9 Allee Rosa Luxembourg + Eragny 95610 + FR + +1C-87-74 (hex) Nebbiolo Technologies +A00000-AFFFFF (base 16) Nebbiolo Technologies + 860 Hillview Court, #310 + Milpitas CA 94035 + US + +1C-87-74 (hex) Wide World Trade HK ltd. +900000-9FFFFF (base 16) Wide World Trade HK ltd. + Office Tower, Convention Plaza, 1 Harbour Road, Wanchai + Hong Kong 4210 + HK + +1C-87-74 (hex) Silora R&D +300000-3FFFFF (base 16) Silora R&D + Kibbutz Kfar-Masaryk + Haifa 25208 + IL + +1C-87-74 (hex) SIGFOX +100000-1FFFFF (base 16) SIGFOX + Bâtiment E-volution - 425, rue Jean Rostand + Labege 31670 + FR + +1C-87-76 (hex) Qivivo +D00000-DFFFFF (base 16) Qivivo + 11 impasse Juton + NANTES 44000 + FR + +1C-87-76 (hex) Guangzhou Video-Star Electronics Co.,Ltd. +800000-8FFFFF (base 16) Guangzhou Video-Star Electronics Co.,Ltd. + 6F/No.6 Building, No.9/4th Lanyu St., GZ Economy&Technology Development Area + Guangzhou Guangdong 510730 + CN + +1C-87-76 (hex) philandro Software GmbH +600000-6FFFFF (base 16) philandro Software GmbH + Rosenbergstr. 46 + Stuttgart 70176 + DE + +1C-87-76 (hex) Corporate Systems Engineering +700000-7FFFFF (base 16) Corporate Systems Engineering + 1215 Brookville Way + Indianapolis IN 46239 + US + +1C-87-76 (hex) Tokyo Drawing Ltd. +900000-9FFFFF (base 16) Tokyo Drawing Ltd. + 103 Ni Terai-machi + Nomi-shi Ishikawa 923-1121 + JP + +1C-87-76 (hex) Unjo AB +300000-3FFFFF (base 16) Unjo AB + Bergfotsgatan 3B + Mölndal SE-43135 + SE + +1C-87-79 (hex) Visual Land Inc. +300000-3FFFFF (base 16) Visual Land Inc. + 17785 Center Court Dr. #670 + Cerritos CA 90703 + US + +1C-87-79 (hex) Wurm GmbH & Co. KG Elektronische Systeme +000000-0FFFFF (base 16) Wurm GmbH & Co. KG Elektronische Systeme + Morsbachtalstr. 30 + Remscheid 42857 + DE + +1C-87-76 (hex) Ibeo Automotive Systems GmbH +200000-2FFFFF (base 16) Ibeo Automotive Systems GmbH + Merkurring 60-62 + Hamburg 22143 + DE + +40-A3-6B (hex) FAOD Co.,Ltd. +D00000-DFFFFF (base 16) FAOD Co.,Ltd. + #301, U-Tower, 1029, Yeongdeok-dong, Giheung-gu + Yongin-si Gyeonggi-do 446-908 + KR + +84-39-BE (hex) Guangdong SunMeng Information Technology Co. Ltd. +900000-9FFFFF (base 16) Guangdong SunMeng Information Technology Co. Ltd. + Yuexiu District of Shuiyin Road No.56th courtyard No.1 building six-floor + Guangzhou Guangdong 510627 + CN + +84-39-BE (hex) Shenzhen IP3 Century Intelligent Technology Co., Ltd +600000-6FFFFF (base 16) Shenzhen IP3 Century Intelligent Technology Co., Ltd + Unit A1, 11F, Block A, Tongfang Information Harbor, No.11, Langshan Road, Hi-Tech Park(North), Nanshan District, Shenzhen + Shenzhen Guangdong 518010 + CN + +40-A3-6B (hex) TOPROOTTechnology Corp. Ltd. +200000-2FFFFF (base 16) TOPROOTTechnology Corp. Ltd. + 5F-8, No. 14, Lane 609, Sec.5, Chongsin Rd., + Sanchong Dist. NewTaipei City 241 + TW + +70-88-6B (hex) Beijing Strongleader Science & Technology Co., Ltd. +B00000-BFFFFF (base 16) Beijing Strongleader Science & Technology Co., Ltd. + No. 12 Yard, Zhong Guan Cun South St. + Beijing Beijing 100081 + CN + +70-88-6B (hex) RHXTune Technology Co.,Ltd +A00000-AFFFFF (base 16) RHXTune Technology Co.,Ltd + Room 409, TianGong building A, Xueyuan Road 30, Haidian District + Beijing Beijing 100083 + CN + +70-88-6B (hex) HORI CO., LTD. +400000-4FFFFF (base 16) HORI CO., LTD. + 640, Saedo-cho + Yokohama-city Kanagawa 224-0054 + JP + +70-88-6B (hex) MAX4G, Inc. +C00000-CFFFFF (base 16) MAX4G, Inc. + 6400 Flying Cloud Drive, Suite 225 + Eden Prairie MN 55344 + US + +70-88-6B (hex) Veracity UK Ltd +000000-0FFFFF (base 16) Veracity UK Ltd + 4 Dow Road + Monkton, Prestwick KA9 2TU + GB + +80-0A-80 (hex) Dongguan I-Chime electrinics Co.,Ltd +100000-1FFFFF (base 16) Dongguan I-Chime electrinics Co.,Ltd + 3/F,A/B,west of Xiangmang road,Fugang village + Dongguan Guangdong 523660 + CN + +CC-1B-E0 (hex) Sichuan Dianjia network technology Co.Ltd. +700000-7FFFFF (base 16) Sichuan Dianjia network technology Co.Ltd. + East 6F,No.51 East Wenshui Road,Hongkou District + Shanghai Shanghai 200437 + CN + +CC-1B-E0 (hex) i-Trinetech Co.,Ltd. +200000-2FFFFF (base 16) i-Trinetech Co.,Ltd. + 4th FL.,East Wing of M-8 Building,Sparrow Ridge Industrial Zone,Science&Technology Park,Nanshan District.,Shenzhen City + Shenzhen Guangdong 518057 + CN + +CC-1B-E0 (hex) ART&CORE Inc +B00000-BFFFFF (base 16) ART&CORE Inc + 6F, 44, Burim-ro 170beon-gil, Dongan-gu, + Anyang-si Gyeonggi-do 431-060 + KR + +00-55-DA (hex) Shinko Technos co.,ltd. +000000-0FFFFF (base 16) Shinko Technos co.,ltd. + 2-5-1, Senba Higashi + Mino Osaka 562-0035 + JP + +C8-8E-D1 (hex) Aventics GmbH +E00000-EFFFFF (base 16) Aventics GmbH + Ulmer Str. 4 + Laatzen Lower Saxony 30880 + DE + +A0-3E-6B (hex) iLoda Solutions Limited +300000-3FFFFF (base 16) iLoda Solutions Limited + 217A, 2/F, Enterprise Place + Hong Kong Hong Kong 000000 + HK + +A0-3E-6B (hex) Wuhan Rui Ying Tong Network Technology Co., Ltd(China) +600000-6FFFFF (base 16) Wuhan Rui Ying Tong Network Technology Co., Ltd(China) + No.303, Optics Valley Avenue, Wuhan, Hubei, China + Wuhan Hubei 430074 + CN + +A0-3E-6B (hex) SinoGrid Software Systems Inc. +700000-7FFFFF (base 16) SinoGrid Software Systems Inc. + 3rd Floor , No.4 Aviation Industry Technology Park + Beijing Beijing 101111 + CN + +1C-21-D1 (hex) Microview Science and Technology Co.,Ltd +300000-3FFFFF (base 16) Microview Science and Technology Co.,Ltd + NO.29 Zhufang Road,Shangdi,Haidian District,Beijing,P.R.China + Beijing Beijing 100085 + CN + +1C-21-D1 (hex) Scientific-Production Enterprise Dynamics +400000-4FFFFF (base 16) Scientific-Production Enterprise Dynamics + Anisimova street, 6 + Cheboksary Chuvash Republic 428015 + RU + +DC-44-27 (hex) Neusoft Corporation +900000-9FFFFF (base 16) Neusoft Corporation + No.2 Xinxiu Street,Hunnan New District,Shenyang,Liaoning,China + Shenyang Liaoning 110179 + CN + +C8-8E-D1 (hex) AISWORLD PRIVATE LIMITED +000000-0FFFFF (base 16) AISWORLD PRIVATE LIMITED + ROOM 1406, 14/F., WING TUCK COMMERCIAL CENTRE 177-183 WING LOK STREET, SHEUNG WAN. HONG KONG + HONG KONG SHEUNG WAN 999077 + HK + +B0-C5-CA (hex) Audio Elektronik İthalat İhracat San ve Tic A.Ş. +E00000-EFFFFF (base 16) Audio Elektronik İthalat İhracat San ve Tic A.Ş. + Esenkent Mah. Barajyolu cad. No:26 + İstanbul Ümraniye 34776 + TR + +B0-C5-CA (hex) Private +D00000-DFFFFF (base 16) Private + +B0-C5-CA (hex) XMetrics +C00000-CFFFFF (base 16) XMetrics + Via Caravaggio, 3 + Bussero MI 20060 + IT + +DC-44-27 (hex) Century Audio, Inc. +500000-5FFFFF (base 16) Century Audio, Inc. + 6220 Overlook Rd. + Peachtree Corners Georgia 30092 + US + +B0-C5-CA (hex) abode systems, inc. +300000-3FFFFF (base 16) abode systems, inc. + 2625 Middlefield Road + Palo Alto CA 94306 + US + +78-C2-C0 (hex) Huwomobility +E00000-EFFFFF (base 16) Huwomobility + 1196 Borregas Ave, Suite 100 + Sunnyvale California 94089 + US + +78-C2-C0 (hex) SES +900000-9FFFFF (base 16) SES + 35-39 avenue du Danemark + TOURS Indre et Loire 37072 + FR + +74-F8-DB (hex) Simon Electric (China) Co.,ltd +D00000-DFFFFF (base 16) Simon Electric (China) Co.,ltd + No.1 Simon Rd, Jiangsu Haian, China + Nantong Jiangsu 226601 + CN + +74-F8-DB (hex) Songam Syscom Co. LTD. +800000-8FFFFF (base 16) Songam Syscom Co. LTD. + 1672-1, Donghwa-Ri, Munmak-Eup + Wonju Gangwon-Do 220-801 + KR + +74-F8-DB (hex) Shenzhen Melon Electronics Co.,Ltd +600000-6FFFFF (base 16) Shenzhen Melon Electronics Co.,Ltd + 3 Floor ,A5 building ,YinLong Technology Industrial Park ,Shenshan Road 292 ,Longgang District + Shenzhen Guangdong 518116 + CN + +78-C2-C0 (hex) XRONOS-INC +100000-1FFFFF (base 16) XRONOS-INC + SHINANOMACHI35 + SHINJUKUKU TOKYO 160-0016 + JP + +B4-37-D1 (hex) Union Tecnologica Noxium S.L. +E00000-EFFFFF (base 16) Union Tecnologica Noxium S.L. + Calle Averroes nº8, Edificio Acropolis + Sevilla Sevilla 41020 + ES + +B4-37-D1 (hex) ZXY Sport Tracking +D00000-DFFFFF (base 16) ZXY Sport Tracking + Ingvald Ystgaards vei 1 + Trondheim Norway 7047 + NO + +B4-37-D1 (hex) NSI Co., Ltd. +B00000-BFFFFF (base 16) NSI Co., Ltd. + 3F, No.33-1, Lane235, Sung-Chiang Road + Taipei 10483 + TW + +88-5D-90 (hex) CPAC Systems +300000-3FFFFF (base 16) CPAC Systems + Bergskroken 3 + Gothenburg Västra Götaland 40123 + SE + +88-5D-90 (hex) Shenzhen JingHanDa Electronics Co.Ltd +500000-5FFFFF (base 16) Shenzhen JingHanDa Electronics Co.Ltd + 5th Floor,No 4 ,Road 1,ShangXue Technology industrial Park,LongGang district,ShenZhen,GuangDong,China + ShenZhen GuangDong 518129 + CN + +88-5D-90 (hex) FOSHAN HUAGUO OPTICAL CO.,LTD +000000-0FFFFF (base 16) FOSHAN HUAGUO OPTICAL CO.,LTD + NO.3 Changhong East Road,Zhanghca Town Foshan City Guang Dong,China + Foshan Guang Dong 528000 + CN + +80-7B-85 (hex) Mersen +E00000-EFFFFF (base 16) Mersen + 374 Merrimac St + Newburyport MA 01950 + US + +54-9A-11 (hex) Orient Direct, Inc. +600000-6FFFFF (base 16) Orient Direct, Inc. + 974 Commercial St. + Palo Alto California 94303 + US + +54-9A-11 (hex) Xi'an Hua Fan Technology Co.,Ltd. +C00000-CFFFFF (base 16) Xi'an Hua Fan Technology Co.,Ltd. + Room No.1,3rd Floor,Xi Tie Gong Cheng Da Sha,No.205 Jinhua Road,Xincheng District + Xi'an Shaanxi 710032 + CN + +88-5D-90 (hex) Hexaglobe +D00000-DFFFFF (base 16) Hexaglobe + 1 rue Méhul + Paris 75002 + FR + +80-7B-85 (hex) Kaynes Technology India Pvt Ltd +D00000-DFFFFF (base 16) Kaynes Technology India Pvt Ltd + 23-25, Belagola Food Industrial Area + MYSORE Karnataka 570016 + IN + +64-FB-81 (hex) SHANGHAI SIMCOM LIMITED +000000-0FFFFF (base 16) SHANGHAI SIMCOM LIMITED + Building A, SIM technology Building, N0.633 JinZhong Road, + Shanghai / 200335 + CN + +64-FB-81 (hex) XIMO Communication Technology Co., Ltd +600000-6FFFFF (base 16) XIMO Communication Technology Co., Ltd + 3rd Floor,F region,418#,Tian Lin Road, Xuhui District, Shanghai + shanghai shanghai 200233 + CN + +1C-CA-E3 (hex) Dabi Atlante S/A Industrias Medico Odontológicas +E00000-EFFFFF (base 16) Dabi Atlante S/A Industrias Medico Odontológicas + Av. Presidente Castelo Branco, 2525 + Ribeirão Preto São Paulo 14095-903 + BR + +80-E4-DA (hex) Dalian Roiland Technology Co.,Ltd +D00000-DFFFFF (base 16) Dalian Roiland Technology Co.,Ltd + 11th floor,7Huixian Yuan, + Dalian, Liaoning 116023 + CN + +80-E4-DA (hex) CAVALRY STORAGE INC +500000-5FFFFF (base 16) CAVALRY STORAGE INC + 4251 E BRICKELL ST + ONTARIO CA 91761 + US + +80-E4-DA (hex) BroadMedia Co., Ltd. +600000-6FFFFF (base 16) BroadMedia Co., Ltd. + 102-124, 106 Youngdeungpo Ro + Seoul N/A 150-935 + KR + +1C-CA-E3 (hex) Shenzhen Smart Device Technology Co.,LTD +300000-3FFFFF (base 16) Shenzhen Smart Device Technology Co.,LTD + SSMEC Building, Gao Xin Nan First Avenue Hi-Tech Park South + Shenzhen GuangDong 518057 + CN + +1C-CA-E3 (hex) Sunray Medical Apparatus Co.,Ltd. +400000-4FFFFF (base 16) Sunray Medical Apparatus Co.,Ltd. + 4/F No.242 Tianhe Dong Road ,510620 Guangzhou, PEOPLE’S REPUBLICA OF CHINA + Guangzhou Guangdong 510620 + CN + +1C-CA-E3 (hex) SHIN-YOSHA CORPORATION +900000-9FFFFF (base 16) SHIN-YOSHA CORPORATION + Oyamagaoka3-9-1 + Machida Tokyo 1940215 + JP + +1C-CA-E3 (hex) OxySec S.r.l. +800000-8FFFFF (base 16) OxySec S.r.l. + via delle Querce, 7 + Treviolo Bergamo 24048 + IT + +2C-6A-6F (hex) Milbank Manufacturing Co. +800000-8FFFFF (base 16) Milbank Manufacturing Co. + 4801 Deramus Ave. + Kansas City MO 64120 + US + +2C-D1-41 (hex) Ezee Systems Limited +100000-1FFFFF (base 16) Ezee Systems Limited + Room 2103, Singga Commercial Centre + Hong Kong HKSAR HK + HK + +2C-6A-6F (hex) EATON FHF Funke + Huster Fernsig GmbH +E00000-EFFFFF (base 16) EATON FHF Funke + Huster Fernsig GmbH + Gewerbeallee 15 - 19 + Muelheim an der Ruhr NRW 45478 + DE + +90-C6-82 (hex) Lachmann & Rink GmbH +B00000-BFFFFF (base 16) Lachmann & Rink GmbH + Hommeswiese 129 + Freudenberg NRW 57258 + DE + +90-C6-82 (hex) Li Seng Technology Ltd. +C00000-CFFFFF (base 16) Li Seng Technology Ltd. + Room 901, 9/F Shiu Fung Hong Building + Hong Kong 852 + HK + +90-C6-82 (hex) S.A.E.T. S.R.L. +500000-5FFFFF (base 16) S.A.E.T. S.R.L. + VIA PO 13 + BUSCA CUNEO 12022 + IT + +2C-D1-41 (hex) Resus Industries +B00000-BFFFFF (base 16) Resus Industries + Kleine monnikenwerve 9 + Brugge West-Vlaanderen 8000 + BE + +2C-6A-6F (hex) SHEN ZHEN SIS SCIENCE & TECHNOLOGY LTD. +500000-5FFFFF (base 16) SHEN ZHEN SIS SCIENCE & TECHNOLOGY LTD. + Room 201, Block A, No.1, Qianwan Road 1, + Shenzhen Guangdong 518000 + CN + +A0-BB-3E (hex) Shenzhen Talent Technology company limited +D00000-DFFFFF (base 16) Shenzhen Talent Technology company limited + 105~107,1/F,Bldg T3,Shenzhen SW Park,No 011,High-teh South 7th Road, Nanshan District,Shenzhen + Shenzhen Guangdong 518040 + CN + +A0-BB-3E (hex) Ewig Industries Macao Commercial Offshore Ltd +C00000-CFFFFF (base 16) Ewig Industries Macao Commercial Offshore Ltd + Avenida da Praia Grande No. 619 + Macau Macau 000000 + CN + +2C-6A-6F (hex) NanChang LangJie Technology Co.,Ltd +200000-2FFFFF (base 16) NanChang LangJie Technology Co.,Ltd + Room 819,No.3 Building,XianFeng Property,No.948 HuoJu Street,GaoXin District + NanChang JiangXi 330096 + CN + +A0-BB-3E (hex) DirectOut GmbH +200000-2FFFFF (base 16) DirectOut GmbH + Leipziger Str. 32 + Mittweida Saxony 09648 + DE + +98-02-D8 (hex) EBI Ltd. +500000-5FFFFF (base 16) EBI Ltd. + 1305 Metro Loft + Kwai Chung NT HKG + HK + +98-02-D8 (hex) AGV spa +C00000-CFFFFF (base 16) AGV spa + Strada Savonesa 12 + rivalta scrivia (AL) italy 15057 + IT + +98-02-D8 (hex) United Power Research Technology Corp. +200000-2FFFFF (base 16) United Power Research Technology Corp. + 8F.-5,No.83,Sec.2,Dongda Rd.,North Dist., + Hsinchu City Taiwan 300 + TW + +28-FD-80 (hex) Poket Hardware GmbH +B00000-BFFFFF (base 16) Poket Hardware GmbH + Borsigstr. 9. + Berlin Berlin 10115 + DE + +28-FD-80 (hex) Apollo Digital (Taiwan) Ltd. +A00000-AFFFFF (base 16) Apollo Digital (Taiwan) Ltd. + Rm. A, 9F, No.68, Sec. 2, + New Taipei City Taiwan 22065 + TW + +2C-26-5F (hex) Rexgen Inc. +B00000-BFFFFF (base 16) Rexgen Inc. + 127, Wonmanseong-ro, Deokjin -gu + Jeonju-si Jeonbuk 561-202 + KR + +28-FD-80 (hex) Xiaocong Network Limited +500000-5FFFFF (base 16) Xiaocong Network Limited + 2F,Building 3, No.200, Guoding East Road (Innovation Works) + Shanghai 200093 + CN + +28-FD-80 (hex) JINLITONG INTERNATIONAL CO.,LTD +900000-9FFFFF (base 16) JINLITONG INTERNATIONAL CO.,LTD + KangMai Industrial Zone ,B building, F/3, + Shenzhen guangdong 518110 + CN + +28-FD-80 (hex) Jasco Products Company +800000-8FFFFF (base 16) Jasco Products Company + 10 East Memorial Road + Oklahoma City Oklahoma 73114 + US + +28-FD-80 (hex) Vigil Monitoring +600000-6FFFFF (base 16) Vigil Monitoring + Suite 201, Ironbank + Auckland Auckland 1010 + NZ + +2C-26-5F (hex) Brüel & Kjaer Vibro GmbH +900000-9FFFFF (base 16) Brüel & Kjaer Vibro GmbH + Leydheckerstrasse 10 + Darmstadt Hessen 64293 + DE + +2C-26-5F (hex) E Core Corporation +D00000-DFFFFF (base 16) E Core Corporation + 2F., No.15, Yijiang St., Zhongshan Dist., + Taipie Taiwan 10456 + TW + +0C-EF-AF (hex) Syntrans AB +700000-7FFFFF (base 16) Syntrans AB + Teknikringen 4C + Linkoping SE-58330 + SE + +0C-EF-AF (hex) Infinisource Inc. +E00000-EFFFFF (base 16) Infinisource Inc. + 9350 South 150 East + Sandy UT 84070 + US + +0C-EF-AF (hex) CJSC «Svyaz Engineering» +D00000-DFFFFF (base 16) CJSC «Svyaz Engineering» + 6th Radialnaya, 9 + Moscow 115404 + + +A4-4F-29 (hex) Shenzhen Huadoo Bright Group Limitied +C00000-CFFFFF (base 16) Shenzhen Huadoo Bright Group Limitied + Room 13E, Jinsong Buiding, Tai ran 4th Rood, Chegong Miao,Futian Distrct + Shenzhen Guangdong 51800 + CN + +F8-02-78 (hex) EMBUX Technology Co., Ltd. +800000-8FFFFF (base 16) EMBUX Technology Co., Ltd. + 11F, 657, Bannan Road + New Taipei City New Taipei City 235 + TW + +F8-02-78 (hex) Witium Co., Ltd +600000-6FFFFF (base 16) Witium Co., Ltd + Room 605A, E Building, NO.7001 Zhongchun Road + Shanghai Shanghai 201101 + CN + +3C-39-E7 (hex) Hannstar Display Corp +000000-0FFFFF (base 16) Hannstar Display Corp + 4F., No.15, Ln. 168, Xingshan Rd., + Taipei Taiwan (R.O.C.) 11469 + TW + +10-07-23 (hex) TESSERA TECHNOLOGY INC. +A00000-AFFFFF (base 16) TESSERA TECHNOLOGY INC. + 2710-1 4F, Noborito, Tama-ku + Kawasaki-shi Kanagawa 214-0014 + JP + +A4-4F-29 (hex) Certi Networks Sdn Bhd +900000-9FFFFF (base 16) Certi Networks Sdn Bhd + 2-8 Level 8 Wisma Manjalara + Kuala Lumpur Wilayah Persekutuan Kuala Lumpur 52200 + MY + +3C-39-E7 (hex) MARPOSS SPA +E00000-EFFFFF (base 16) MARPOSS SPA + VIA SALICETO 13 + BENTIVOGLIO BOLOGNA 40010 + IT + +A4-4F-29 (hex) Protean Payment +700000-7FFFFF (base 16) Protean Payment + 617 Detroit St + Ann Arbor Michigan 48104 + US + +A4-4F-29 (hex) Innovations in Optics, Inc. +800000-8FFFFF (base 16) Innovations in Optics, Inc. + 82 Cummings Park + Woburn MA 01801 + US + +10-07-23 (hex) Wireless input technology Inc. +900000-9FFFFF (base 16) Wireless input technology Inc. + 34339 N. Bobolink Trail + Grayslake IL 60030 + US + +3C-39-E7 (hex) RO.VE.R. Laboratories S.p.A +600000-6FFFFF (base 16) RO.VE.R. Laboratories S.p.A + Via Parini 2/4 + Colombare di SIrmione BS 25019 + IT + +10-07-23 (hex) Tongfang computer co.Ltd. +300000-3FFFFF (base 16) Tongfang computer co.Ltd. + F8 building 2, 2nd section, Gaoxinqi strategic emerging industry part, liuxian 1st Rd. the 67 district, Bao an district, shenzhen, china + shenzhen guangdong 518100 + CN + +D0-22-12 (hex) SHENZHEN ZHONGXI SECURITY CO.,LTD +D00000-DFFFFF (base 16) SHENZHEN ZHONGXI SECURITY CO.,LTD + 2F,East 420Building,Bagua 3rd, Futian, Shenzhen + shenzhen guangdong ZIP + CN + +E8-18-63 (hex) Shenzhen Hipad Telecommunication Technology Co.,Ltd +C00000-CFFFFF (base 16) Shenzhen Hipad Telecommunication Technology Co.,Ltd + Room 502-503,Building C3 ,Kexing Science Park,Sci-Tech.Park(M.Zone),Nanshan District,Shenzhen + Shenzhen Guangdong 518000 + CN + +10-07-23 (hex) Audio Engineering Ltd. +400000-4FFFFF (base 16) Audio Engineering Ltd. + 75 Parnell Rise + Auckland 1052 + NZ + +E8-18-63 (hex) WETEK ELECTRONICS LIMITED +500000-5FFFFF (base 16) WETEK ELECTRONICS LIMITED + #604, TOWER A NEW TRADE PLAZA + HONG KONG HONG KONG 999077 + HK + +E8-18-63 (hex) DIGITAL DYNAMICS, INC. +D00000-DFFFFF (base 16) DIGITAL DYNAMICS, INC. + 5 VICTOR SQUARE + SCOTTS VALLEY CA. 95066 + US + +74-E1-4A (hex) Wuhan Shenghong Laser Projection Technology Co.,LTD +C00000-CFFFFF (base 16) Wuhan Shenghong Laser Projection Technology Co.,LTD + Room 403,Tower A11,Optical valley software Park,No.1 GuanShan first Road,East lake development Zone + Wuhan Hubei 430000 + CN + +74-E1-4A (hex) Diamond Kinetics +E00000-EFFFFF (base 16) Diamond Kinetics + 700 River Ave., Suite 318 + Pittsburgh PA 15212 + US + +74-E1-4A (hex) KLIMAT SOLEC Sp. z o.o. +200000-2FFFFF (base 16) KLIMAT SOLEC Sp. z o.o. + Nadborna 2a + Solec Kujawski Kujawsko-Pomorskie 86-050 + PL + +74-E1-4A (hex) Altenburger Electronic GmbH +000000-0FFFFF (base 16) Altenburger Electronic GmbH + Schlossweg 5 + Seelbach BW 77960 + DE + +74-E1-4A (hex) Cerevo Inc. +100000-1FFFFF (base 16) Cerevo Inc. + River-side-seven bldg. 3F, 2-7-9, Sotokanda + Tiyoda Tokyo 101-0021 + JP + +74-E1-4A (hex) Emerging Technology (Holdings) Ltd. +600000-6FFFFF (base 16) Emerging Technology (Holdings) Ltd. + 17/F, C-Bons International Center, 108 Wai Yip Street, + Hong Kong Hong Kong Hong Kong + CN + +B8-D8-12 (hex) Neuropace Inc. +700000-7FFFFF (base 16) Neuropace Inc. + 455 N Bernardo Ave + Mountain View California 94043 + US + +BC-66-41 (hex) Shenzhen General Measure Technology Co., Ltd +900000-9FFFFF (base 16) Shenzhen General Measure Technology Co., Ltd + 4th Floor, No.6 Block Science&Technologt Industrial Park of Privately Owned Enterprises + Shenzhen Guangdong 518000 + CN + +BC-66-41 (hex) Scientific Games +500000-5FFFFF (base 16) Scientific Games + 1500 Bluegrass Lakes Parkway + Alpharetta GA 30004 + US + +E4-95-6E (hex) Shanghai Hoping Technology Co., Ltd. +200000-2FFFFF (base 16) Shanghai Hoping Technology Co., Ltd. + Room 224, Building 3, No.99 + Shanghai 201210 + CN + +BC-66-41 (hex) Solectria Renewables, LLC +300000-3FFFFF (base 16) Solectria Renewables, LLC + 360 Merrimack St. + Lawrence MA 01843 + US + +E4-95-6E (hex) SHENZHEN JOYETECH ELECTRONICS CO., LTD. +600000-6FFFFF (base 16) SHENZHEN JOYETECH ELECTRONICS CO., LTD. + 9th Blvd.Changxing New Tech.Industry Zone,Shajing Town,Baoan District + shenzhen Guangdong 518104 + CN + +58-FC-DB (hex) Shanghai Qianjin Electronic Equipment Co. Ltd +800000-8FFFFF (base 16) Shanghai Qianjin Electronic Equipment Co. Ltd + 4/F,Building No.2,401 Caobao Road + Shanghai 200233 + + +58-FC-DB (hex) Shenzhen Siecom Communication Technology Development Co.,Ltd. +500000-5FFFFF (base 16) Shenzhen Siecom Communication Technology Development Co.,Ltd. + Wanwei building401 ,Industry 5th Road + Shenzhen Guangdong 518067 + CN + +58-FC-DB (hex) Excenon Mobile Technology Co., Ltd. +C00000-CFFFFF (base 16) Excenon Mobile Technology Co., Ltd. + 5th Floor, Building 1, Software Park, Kejizhong 2nd Rd, High-Tech Zone, Nanshan + Shenzhen Guangdong 518000 + CN + +58-FC-DB (hex) Open Roads Consulting, Inc. +700000-7FFFFF (base 16) Open Roads Consulting, Inc. + 103 Watson Rd. + Chesapeake Virginia 23320 + US + +B0-1F-81 (hex) Advanced & Wise Technology Corp. +E00000-EFFFFF (base 16) Advanced & Wise Technology Corp. + 5F, No. 3-2, Industry East 9th Road, Hsinchu Science Park, + Hsinchu City Hsinchu 30075 + TW + +58-FC-DB (hex) Custom Biogenic Systems +300000-3FFFFF (base 16) Custom Biogenic Systems + 74100 Van Dyke Road + MI Michigan 48065 + US + +B0-1F-81 (hex) Technion Oy +800000-8FFFFF (base 16) Technion Oy + Linkkikatu 15 + Naantali Länsi-Suomi 21100 + FI + +B0-1F-81 (hex) COMOTA Co., Ltd. +600000-6FFFFF (base 16) COMOTA Co., Ltd. + Queens Tower C 10F + Yokohama Kanagawa 220-6210 + JP + +BC-66-41 (hex) InSync Technology Ltd +000000-0FFFFF (base 16) InSync Technology Ltd + Tilbrook House + Petersfield Hampshire GU31 4AZ + GB + +58-FC-DB (hex) Certis Technology International +100000-1FFFFF (base 16) Certis Technology International + Certis CISCO + Singapore 409179 + + +B0-1F-81 (hex) Uvax Concepts +100000-1FFFFF (base 16) Uvax Concepts + Calle Corretger 71-2 + Paterna Other 46980 + ES + +B0-1F-81 (hex) Dalian GigaTec Electronics Co.,Ltd +000000-0FFFFF (base 16) Dalian GigaTec Electronics Co.,Ltd + No.3 Kehai Street, Hi-Tech Zone + Dalian Liao Ning 116023 + CN + +F4-0E-11 (hex) DXG Technology Corp. +D00000-DFFFFF (base 16) DXG Technology Corp. + 15FL.,NO.4,SEC.3, + Taipei 10477 + TW + +F4-0E-11 (hex) Dayang Technology Development Inc. +400000-4FFFFF (base 16) Dayang Technology Development Inc. + Dayang Building + Haidian District Beijing 100193 + CN + +14-1F-BA (hex) Black Moth Technologies +900000-9FFFFF (base 16) Black Moth Technologies + 17 Waverley St + Annerley Queensland 4103 + AU + +7C-70-BC (hex) Lukup Media +C00000-CFFFFF (base 16) Lukup Media + 25/2 Norris Road + Bangalore Karnataka 560025 + IN + +7C-70-BC (hex) dogtra +900000-9FFFFF (base 16) dogtra + 35, Namdongdong-ro 33beon-gil, Namdong-gu, Incheon, + Seoul KS006 + KR + +14-1F-BA (hex) Deutsche Energieversorgung GmbH +200000-2FFFFF (base 16) Deutsche Energieversorgung GmbH + Am Schenkberg 12 + Leipzig Bundesland / Region wählen 04349 + DE + +7C-70-BC (hex) HOPERUN MMAX DIGITAL PTE. LTD. +E00000-EFFFFF (base 16) HOPERUN MMAX DIGITAL PTE. LTD. + 152 BEACH ROAD + SINGAPORE 189721 + SG + +7C-70-BC (hex) Mennekes Elektrotechnik GmbH & Co. KG +800000-8FFFFF (base 16) Mennekes Elektrotechnik GmbH & Co. KG + Aloys-Mennekes-Str. 1 + Kirchhundem NRW 57399 + DE + +7C-70-BC (hex) Canary Connect, Inc. +500000-5FFFFF (base 16) Canary Connect, Inc. + 132 East 43rd Street + New York NY 10017 + US + +BC-34-00 (hex) Dexcel Design Pvt Ltd +400000-4FFFFF (base 16) Dexcel Design Pvt Ltd + #138, Level 3,4 - Maruthi Tower + Bangalore Karnataka 560008 + IN + +7C-70-BC (hex) Digital Lumens +200000-2FFFFF (base 16) Digital Lumens + 374 Congress Street, 6th Floor + Boston MA 02210 + US + +A4-3B-FA (hex) JSC “Component-ASU” +D00000-DFFFFF (base 16) JSC “Component-ASU” + Severnyi proezd 1, k. 5/6 + Chernogolovka Moscow Region 142432 + + +A4-3B-FA (hex) Maxon Australia +400000-4FFFFF (base 16) Maxon Australia + 36a Gibson Ave + Padstow New South Wales 2211 + AU + +D0-76-50 (hex) Revox Inc. +E00000-EFFFFF (base 16) Revox Inc. + 1880-2 Kamimizo, Chuo-ku, + Sagamihara Kanagawa 252-0243 + JP + +A4-3B-FA (hex) Alpwise +800000-8FFFFF (base 16) Alpwise + 4 avenue Louis Doyen Weil + Grenoble Rhône-Alpes 38000 + FR + +D0-76-50 (hex) Picobrew LLC +600000-6FFFFF (base 16) Picobrew LLC + 2121 N 35th Street + Seattle WA 98103 + US + +74-19-F8 (hex) Ansjer Electronics Co., Ltd. +D00000-DFFFFF (base 16) Ansjer Electronics Co., Ltd. + 4 Bldg., Pinglan Indl. Park, Nanping, + Zhuhai Guangdong 519060 + CN + +D0-76-50 (hex) Annapurna Labs +500000-5FFFFF (base 16) Annapurna Labs + 1830 The Alameda + San Jose California 95126 + US + +40-11-75 (hex) BWT Tianjin Ltd. +A00000-AFFFFF (base 16) BWT Tianjin Ltd. + 1st Floor ,C Block,NO.225,Jinger Road ,Konggang Economic District,Tianjin 300308 ,China + Tianjin 300000 + CN + +4C-4B-F9 (hex) Shenzhen Haichuan Intelligent Information Technology Co., Ltd. +D00000-DFFFFF (base 16) Shenzhen Haichuan Intelligent Information Technology Co., Ltd. + 1208 District B,Jinhui Building, 2079 Nanhai Avenue,Dengliang Community,Nanshan Street,Nanshan District + Shenzhen Guangdong 518101 + CN + +54-A4-93 (hex) Advice +B00000-BFFFFF (base 16) Advice + 16 Atir Yeda St + Kfar Saba Not applicable 4464321 + IL + +10-DC-B6 (hex) Private +000000-0FFFFF (base 16) Private + +54-A4-93 (hex) Wonders Technology Co., Ltd. +A00000-AFFFFF (base 16) Wonders Technology Co., Ltd. + 4/F,Tower A,3rd Building,Tian'an Cloud Park,Bantian Avenue,Longgang District + Shenzhen 518129 + CN + +04-D1-6E (hex) s.d.i. s.p.a. +200000-2FFFFF (base 16) s.d.i. s.p.a. + Edison, 10 + Trezzano sul Naviglio Milano 20090 + IT + +04-D1-6E (hex) FUZHOU ZHUOYI ELECTRONIC CO.,LTD +900000-9FFFFF (base 16) FUZHOU ZHUOYI ELECTRONIC CO.,LTD + NO.22 BAIHUAZHOU ROAD,FUZHOU,FUJIAN,CHINA + FUZHOU FUJIAN 350008 + CN + +54-A4-93 (hex) Do Easy International Limited +900000-9FFFFF (base 16) Do Easy International Limited + No. 107, Wenjian St., Fengshan Dist. + Kaohsiung 83067 + TW + +54-A4-93 (hex) RED Hydrogen LLC +700000-7FFFFF (base 16) RED Hydrogen LLC + 15 Cushing + IRVINE CA 92618 + US + +44-03-77 (hex) Norden Communication UK Ltd. +500000-5FFFFF (base 16) Norden Communication UK Ltd. + Unit-13, Baker Close, Oakwood Business Park + Clacton-On-Sea Essex CO15 4BD + GB + +44-03-77 (hex) symplr +A00000-AFFFFF (base 16) symplr + 1550 Innovation Way + Hartford WI 53027 + US + +44-03-77 (hex) Musashi Seimitsu Industry Co.,Ltd +000000-0FFFFF (base 16) Musashi Seimitsu Industry Co.,Ltd + 39-5 Daizen,Ueta-cho + Toyohashi Aichi 441-8560 + JP + +44-03-77 (hex) Annapurna labs +300000-3FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +50-62-55 (hex) CCTV Manufacturer +A00000-AFFFFF (base 16) CCTV Manufacturer + Room 1807,Bagua 4 Rd,Futian District + Shenzhen Guangdong 518029 + CN + +50-62-55 (hex) Roda industrial development Co.,Ltd. +800000-8FFFFF (base 16) Roda industrial development Co.,Ltd. + 2-3F,Building C,Unistar Park,GenYu Road,GuangMing New District + Shenzhen 518000 + CN + +50-62-55 (hex) Hagiwara Solutions Co., Ltd +100000-1FFFFF (base 16) Hagiwara Solutions Co., Ltd + 7F, Sakae TV BLD, 3-10-32, Nishiki, Naka-ku, + Nagoya City Aichi Prefecture 460-0003 + JP + +64-31-39 (hex) Shenzhen He&e Technology Co.,Ltd. +500000-5FFFFF (base 16) Shenzhen He&e Technology Co.,Ltd. + 2nd Floor, Building A7, Shenzhen Low Carbon Technology Demonstration Park, Silicon Valley Power, Guiyue Road, Guanlan Street, Longhua District, Shenzhen, China + ShenZhen 518100 + CN + +64-31-39 (hex) Shenzhen Huanyin Electronics Ltd. +800000-8FFFFF (base 16) Shenzhen Huanyin Electronics Ltd. + Room 1707, 17/F, West Block, Nanshan Digital Culture Industrial Base, Nanshan District + Shenzhen Guangdong 519052 + CN + +64-31-39 (hex) Product Development Associates, Inc. +A00000-AFFFFF (base 16) Product Development Associates, Inc. + 1145 E. Cliff Rd + Burnsville MN 55337 + US + +C4-95-4D (hex) Newland Era Edu Hi-Tech(BeiJing)Co.,Ltd +D00000-DFFFFF (base 16) Newland Era Edu Hi-Tech(BeiJing)Co.,Ltd + No. 1, Linkong 2 Road,North Wenhuaying Village, Gaoliying Town, Shunyi District, Beijing + Beijing 101303 + CN + +64-31-39 (hex) Smartplus Inc. +200000-2FFFFF (base 16) Smartplus Inc. + 415 steelcase road east + markham Ontario L3R1G3 + CA + +C4-95-4D (hex) Multicom, Inc +B00000-BFFFFF (base 16) Multicom, Inc + 1076 Florida Central Parkway + Longwood FL 32750 + US + +00-69-67 (hex) PANGAEA SOLUTION INC +700000-7FFFFF (base 16) PANGAEA SOLUTION INC + 774, Yuseong-daero, Yuseong-gu, + Daejeon Daejeon 34171 + KR + +00-69-67 (hex) Command Alkon, Inc +400000-4FFFFF (base 16) Command Alkon, Inc + 1800 International Park Dr., Ste 400 + Birmingham AL 35243 + US + +C4-95-4D (hex) Canare Electric Co., Ltd. +E00000-EFFFFF (base 16) Canare Electric Co., Ltd. + B-13F,Shiba Park Bldg.,2-4-1,Shiba-Koen + Minato Tokyo 105-0011 + JP + +00-69-67 (hex) Desird Design R&D +C00000-CFFFFF (base 16) Desird Design R&D + Mehmetçik Mahallesi Aspendos Bulvar? No:99A Muratpa?a/ANTALYA + Antalya 07300 + TR + +A0-22-4E (hex) Kyung In Electronics +000000-0FFFFF (base 16) Kyung In Electronics + #1411, Byucksan Digital Valley 2, 184, Gasan Digital2-ro, Geumcheon-gu + Seoul 08501 + KR + +A0-22-4E (hex) TMGcore LLC +400000-4FFFFF (base 16) TMGcore LLC + 6815 Communications Pkwy + Plano TX 75024 + US + +A0-22-4E (hex) EISST International Ltd +800000-8FFFFF (base 16) EISST International Ltd + 10 Queen Street Place + London London EC4R 1AG + GB + +20-0A-0D (hex) Wideband Systems, Inc. +100000-1FFFFF (base 16) Wideband Systems, Inc. + 11900 Bournefield Way STE 120 + Silver Spring MD 20904 + US + +20-0A-0D (hex) sehwa +C00000-CFFFFF (base 16) sehwa + 231, Techno 2-ro, Yuseong-gu, Daejeon, Republic of Korea + Daejeon Daejeon 34026 + KR + +20-0A-0D (hex) Shenzhen Zhangyue Technology Co.,Ltd +500000-5FFFFF (base 16) Shenzhen Zhangyue Technology Co.,Ltd + Nanshan District Yuehai Street Weixin Software Science Park Building 8 9th Floor Room 903 + Shenzhen Guangdong 518500 + CN + +40-2C-76 (hex) Guangzhou Qi'an Technology Co., Ltd. +D00000-DFFFFF (base 16) Guangzhou Qi'an Technology Co., Ltd. + No. 3, Dasonggang, Jiangnan Avenue Middle Road, Haizhu District, Guangzhou (office only) + Guangzhou Guangdong 510220 + CN + +40-2C-76 (hex) Beijing Kuaiyu Electronic Co., Ltd. +B00000-BFFFFF (base 16) Beijing Kuaiyu Electronic Co., Ltd. + Kuaiyu Technologies, Building 11, Yuquan Huigu, Tsinghua Science Park, No. 3 Minzhuang Road, Haidian District, Beijing + Beijing 100195 + CN + +50-DE-19 (hex) Langogo Technology Co., Ltd. +400000-4FFFFF (base 16) Langogo Technology Co., Ltd. + 2/F, Boxun Building, Keyuan North Road, Nanshan District + Shenzhen Guangdong 518103 + CN + +3C-FA-D3 (hex) GRG Banking Technology Co.,Ltd +400000-4FFFFF (base 16) GRG Banking Technology Co.,Ltd + 232 Gaotang Road,Tianhe District + Guangzhou Guangdong 510000 + CN + +3C-FA-D3 (hex) UltiMachine +A00000-AFFFFF (base 16) UltiMachine + 200 12th St. N. + South Pittsburg TN 37380 + US + +3C-FA-D3 (hex) Harman Connected Services, Inc. +300000-3FFFFF (base 16) Harman Connected Services, Inc. + 636 Ellis Street Mountain View + New York CA 10003 + US + +B0-B3-53 (hex) Rizhao SUNWAM International Co., Ltd. +200000-2FFFFF (base 16) Rizhao SUNWAM International Co., Ltd. + No.001-00-114, Ruiyuan Mingcheng, Haiqu Zhong Road + Rizhao Shandong 276800 + CN + +B0-B3-53 (hex) Ledger +A00000-AFFFFF (base 16) Ledger + 1 rue du mail + Paris 75002 + FR + +14-AE-85 (hex) Trimble LEM +800000-8FFFFF (base 16) Trimble LEM + 10368 Westmoor Dr + Westminster CO 80021 + US + +14-AE-85 (hex) Kayamatics Limited +000000-0FFFFF (base 16) Kayamatics Limited + Room 1209, Trend Centre, 29 Cheung Lee Street + Chaiwan NA NA + HK + +64-62-66 (hex) Shenzhen C & D Electronics Co., Ltd. +700000-7FFFFF (base 16) Shenzhen C & D Electronics Co., Ltd. + 9th FIoor, Building 9, No.1 Qingxiang road, BaoNeng Science and TechnoIogy Industrial Park, Longhua New District + ShenZhen GuangDong 518000 + CN + +64-62-66 (hex) Signal Hound +B00000-BFFFFF (base 16) Signal Hound + 1502 SE Commerce Ave Suite 101 + Battle Ground WA 98604 + US + +64-62-66 (hex) Chunghwa System Integration Co., Ltd. +900000-9FFFFF (base 16) Chunghwa System Integration Co., Ltd. + 2F., No. 35, Aiguo E. Rd., + Taipei 106 + TW + +64-62-66 (hex) Protectli +200000-2FFFFF (base 16) Protectli + 1315 Hot Springs Way + Vista CA 92081 + US + +64-62-66 (hex) Redstone Systems, Inc. +400000-4FFFFF (base 16) Redstone Systems, Inc. + 24 School Street, 2nd floor + Boston 02108 + US + +64-62-66 (hex) Kobol Innovations Pte. Ltd. +D00000-DFFFFF (base 16) Kobol Innovations Pte. Ltd. + 101 Cecil Street, #26-01/07 Tong Eng Building + Singapore 069533 + SG + +94-05-BB (hex) AUSTAR HEARING SCIENCE AND TECHNILIGY(XIAMEN)CO.,LTD +B00000-BFFFFF (base 16) AUSTAR HEARING SCIENCE AND TECHNILIGY(XIAMEN)CO.,LTD + RM201,No.2Gaoqi South 12th Road,HuliDist + XIamen Fujian 361006 + CN + +94-05-BB (hex) LAO INDUSTRIA LTDA +C00000-CFFFFF (base 16) LAO INDUSTRIA LTDA + AV DR MAURO LINDENBERG MONTEIRO, 1003 + OSASCO SÃO PAULO 06278010 + BR + +F4-90-CB (hex) Avilution +500000-5FFFFF (base 16) Avilution + 103 Shoreline Dr + Madison AL 35758 + US + +F4-90-CB (hex) OmniNet +400000-4FFFFF (base 16) OmniNet + 6410 Del Rio Rd + Charlotte NC 28277 + US + +4C-4B-F9 (hex) Shandong Linkotech Electronic Co., Ltd. +600000-6FFFFF (base 16) Shandong Linkotech Electronic Co., Ltd. + 22nd Floor, Building 2, Aosheng Building, No.1166 Xinyi Street, High-tech Zone + Jinan Shandong 250101 + CN + +4C-4B-F9 (hex) Power Active Co., Ltd +300000-3FFFFF (base 16) Power Active Co., Ltd + 4F, No.23, Wugong 6th Rd., Wugu Dist. + New Taipei City 248 + TW + +4C-4B-F9 (hex) Multitek Elektronik Sanayi ve Ticaret A.S. +000000-0FFFFF (base 16) Multitek Elektronik Sanayi ve Ticaret A.S. + Meclis Mah. Ataturk Cad. No:47, sancaktepe + istanbul 34785 + TR + +20-85-93 (hex) Mid Continent Controls, Inc. +200000-2FFFFF (base 16) Mid Continent Controls, Inc. + 901 North River Street + Derby KS 67037 + US + +34-04-9E (hex) Connected IO +100000-1FFFFF (base 16) Connected IO + 573 University Ave + Los Gatos CA 95032 + US + +20-85-93 (hex) Private +900000-9FFFFF (base 16) Private + +24-15-10 (hex) Topgolf Sweden AB +900000-9FFFFF (base 16) Topgolf Sweden AB + Svärdvägen 11 + Danderyd Stockholm 182 33 + SE + +24-15-10 (hex) SuZhou A-rack Information Technology Co.,Ltd +700000-7FFFFF (base 16) SuZhou A-rack Information Technology Co.,Ltd + No.10 Xinting Road,Suzhou New District + Suzhou Jiangsu 215000 + CN + +20-85-93 (hex) AASSET SECURITY +800000-8FFFFF (base 16) AASSET SECURITY + 153 RUE MICHEL CARRE + ARGENTEUIL 95100 + FR + +20-85-93 (hex) Wave-In Communication +500000-5FFFFF (base 16) Wave-In Communication + 8F, No.322, Sec. 1, Neihu Rd., Neihu Dist. + Taipei City 114 + TW + +BC-66-41 (hex) Private +F00000-FFFFFF (base 16) Private + +98-06-37 (hex) Angora Networks +A00000-AFFFFF (base 16) Angora Networks + Alacaatli Mah. Park Cad 47/31, Cayyolu + Ankara 06810 + TR + +64-FB-81 (hex) Private +F00000-FFFFFF (base 16) Private + +78-C2-C0 (hex) Private +F00000-FFFFFF (base 16) Private + +14-1F-BA (hex) Private +F00000-FFFFFF (base 16) Private + +58-FC-DB (hex) Private +F00000-FFFFFF (base 16) Private + +74-F8-DB (hex) Private +F00000-FFFFFF (base 16) Private + +7C-70-BC (hex) Private +F00000-FFFFFF (base 16) Private + +D0-76-50 (hex) Private +F00000-FFFFFF (base 16) Private + +44-D5-F2 (hex) Shenzhen Hebang Electronic Co., Ltd +200000-2FFFFF (base 16) Shenzhen Hebang Electronic Co., Ltd + 2nd Floor West, Bldg B, Kelunte Low Carbon Industry Park, Huarong Road, Dalang, Longhua District + Shenzhen 518000 + CN + +98-06-37 (hex) Chengdu Shuwei Communication Technology Co.,Ltd +400000-4FFFFF (base 16) Chengdu Shuwei Communication Technology Co.,Ltd + The Second floor, G4 Building, G zone, Tianfu Software Park, 1800 Yizhou Avenue, High Tech Dsitrict + Chengdu Sichuan 610041 + CN + +D0-5F-64 (hex) Nanjing Huamai Technology Co.,Ltd +C00000-CFFFFF (base 16) Nanjing Huamai Technology Co.,Ltd + No.11 Runfa Road, Dongshan Industry Gathering Zone, Jiangning District + Nanjing Jiangsu 210000 + CN + +44-D5-F2 (hex) Valeo Interior Controls (Shenzhen) Co.,Ltd +B00000-BFFFFF (base 16) Valeo Interior Controls (Shenzhen) Co.,Ltd + North Junyi Ind. Park, Huaide Vil., Fuyong Town, Baoan Dist. + Shenzhen Guangzhong 518103 + CN + +44-D5-F2 (hex) tiga.eleven GmbH +500000-5FFFFF (base 16) tiga.eleven GmbH + Stallburggasse 2/37 + Viennna 1010 + AT + +D0-5F-64 (hex) PartnerNET LTD +A00000-AFFFFF (base 16) PartnerNET LTD + Salaminos 5 + Nicossia Strovolos 2044 + CY + +FC-A4-7A (hex) Hefei Feier Smart Science&Technology Co. Ltd +E00000-EFFFFF (base 16) Hefei Feier Smart Science&Technology Co. Ltd + 6 / F 1#ZhongShi Building,CSV, High-tech Zone + HEFEI 230000 + CN + +FC-A4-7A (hex) HOOC AG +400000-4FFFFF (base 16) HOOC AG + Torweg 8 + Visp VS 3930 + CH + +2C-16-BD (hex) Beijing Zhijian Link Technology Co., Ltd. +500000-5FFFFF (base 16) Beijing Zhijian Link Technology Co., Ltd. + C3-1358, 3rd floor, No. 18 North Taipingzhuang Road, Haidian District + Beijing Beijing 100088 + CN + +FC-A4-7A (hex) Syfer +500000-5FFFFF (base 16) Syfer + 227 SANDY SPRINGS PL SUITE D-454 + Atlanta GA 30328-5918 + US + +FC-A4-7A (hex) Ant Financial(Hang Zhou)Network Technology Co.,Ltd. +200000-2FFFFF (base 16) Ant Financial(Hang Zhou)Network Technology Co.,Ltd. + 801-10,8th Floor B Section,556Xixi Road,XihuDistrict, + HangzhouCity ZhejiangProvince 310007 + CN + +2C-16-BD (hex) Molex Incorporated +E00000-EFFFFF (base 16) Molex Incorporated + 46360 Fremont Blvd + Fremont CA 94538 + US + +D0-5F-64 (hex) wallbe GmbH +400000-4FFFFF (base 16) wallbe GmbH + Paderborner Straße 76 + Schlangen NRW 33189 + DE + +D0-5F-64 (hex) Decathlon SA +000000-0FFFFF (base 16) Decathlon SA + 4 Boulevard de Mons + Villeneuve d'Ascq Haut de France 59650 + FR + +B4-A2-EB (hex) DCI International, LLC. +100000-1FFFFF (base 16) DCI International, LLC. + 305 N Springbrook Road + Newberg OR 97132 + US + +B4-A2-EB (hex) ShenZhen Lark Acoustics Co., Ltd. +600000-6FFFFF (base 16) ShenZhen Lark Acoustics Co., Ltd. + Room 2406, Northwestern Polytechnical University, Gaoxin South Nine Road,Nanshan District + Shenzhen Guangdong 518000 + CN + +2C-16-BD (hex) Hangzhou Yanzhi Technology Co.,Ltd. +D00000-DFFFFF (base 16) Hangzhou Yanzhi Technology Co.,Ltd. + Room 406, 4th floor, building 6,316 jianghong south road,Binjiang Dist + Hangzhou Zhejiang 310030 + CN + +B4-A2-EB (hex) Dongguan Finslink Communication Technology Co.,Ltd. +E00000-EFFFFF (base 16) Dongguan Finslink Communication Technology Co.,Ltd. + Room 202,2nd floor,G3 Building, University Innovation City,Songshan Lake High-tech Industrial Development Zone + Dongguan Guangdong 523808 + CN + +8C-59-3C (hex) Dantherm Cooling Inc. +C00000-CFFFFF (base 16) Dantherm Cooling Inc. + 110 Corporate Dr., Suite K + Spartanburg SC 29303 + US + +B4-A2-EB (hex) Canaan Creative Co.,Ltd. +300000-3FFFFF (base 16) Canaan Creative Co.,Ltd. + ZPark 27# QianFang Science Building C, Haidian District, Beijing, China. + Beijing Beijing 100094 + CN + +2C-16-BD (hex) CLOUDWALK TECHNOLOGY CO.,LTD +600000-6FFFFF (base 16) CLOUDWALK TECHNOLOGY CO.,LTD + Five Floors of Block 106, West Jinkai Avenue, Yubei District + Chongqing Chongqing 401120 + CN + +D0-C8-57 (hex) Imin Technology Pte Ltd +400000-4FFFFF (base 16) Imin Technology Pte Ltd + 77 Sciene park Drive #03-10 Cintech III + Singapore Singapore 118256 + SG + +74-5B-C5 (hex) Beijing Inspiry Technology Co., Ltd. +100000-1FFFFF (base 16) Beijing Inspiry Technology Co., Ltd. + Building No. 5, East Zone, No. 10, Xibeiwang East Road, Haidian District + Beijing Beijing 100092 + CN + +D0-C8-57 (hex) shenzhen cnsun +A00000-AFFFFF (base 16) shenzhen cnsun + 5 Floor, 2 Building,Tongfuyu Industrial City + shenzhen guangdong 518000 + CN + +D0-C8-57 (hex) Shenzhen xiaosha Intelligence Technology Co. Ltd +900000-9FFFFF (base 16) Shenzhen xiaosha Intelligence Technology Co. Ltd + Poly Building, 2702 Nanhai Avenue, Nanshan District + Shenzhen Guangdong 518054 + CN + +D0-C8-57 (hex) Innovative Industrial(HK)Co., Limited +600000-6FFFFF (base 16) Innovative Industrial(HK)Co., Limited + OFFICE 3A,12/F,KAISER CENTRE,NO.18CENTRE STREET + SAI YING PUN 999077 + HK + +30-0A-60 (hex) Beijing Ruiteng Zhongtian TECH Ltd.,Co +100000-1FFFFF (base 16) Beijing Ruiteng Zhongtian TECH Ltd.,Co + Blk 6,Rm 602,Noble CenterⅡ,No.1 Automotive Museum East Lane,South Fourth Ring Road, Fengtai District + Beijing Beijing 100070 + CN + +BC-97-40 (hex) Lattec I/S +200000-2FFFFF (base 16) Lattec I/S + Blytækkervej 10 + Hillerød 3400 + DK + +A4-3B-FA (hex) Private +F00000-FFFFFF (base 16) Private + +D0-C8-57 (hex) FORGAMERS INC. +200000-2FFFFF (base 16) FORGAMERS INC. + 6F., NO.51, DONGXING RD., XINYI DIST., TAIPEI CITY 110-70, TAIWAN + Taipei 110 + TW + +60-95-CE (hex) Cadmo Soluciones SAC +700000-7FFFFF (base 16) Cadmo Soluciones SAC + Av. Angamos Este 2495 Dpt. 301, San Borja + Lima Lima 15036 + PE + +60-95-CE (hex) GovComm +D00000-DFFFFF (base 16) GovComm + 3830 SW 30 Ave + Fort Lauderdale FL 33312 + US + +60-95-CE (hex) Ponoor Experiments Inc. +100000-1FFFFF (base 16) Ponoor Experiments Inc. + Higashi-shinagawa 1-33-10, Terrada Art Complex 216 + Shinagawa-ku Tokyo 1400002 + JP + +BC-97-40 (hex) Alpha ESS Co., Ltd. +000000-0FFFFF (base 16) Alpha ESS Co., Ltd. + JiuHua Road 888, Nantong High-Tech Industrial Development Zone, + Nantong Jiangsu 226300 + CN + +60-95-CE (hex) (UN)MANNED +A00000-AFFFFF (base 16) (UN)MANNED + Baron Ruzettelaan 3 + Brugge 8310 + BE + +60-95-CE (hex) Jlztlink Industry(ShenZhen)Co.,Ltd. +900000-9FFFFF (base 16) Jlztlink Industry(ShenZhen)Co.,Ltd. + D-502#,Tongan logistics center,Sanwei hangkong 30#,Xiang street,Baoan, + Shenzhen Guangdong 518000 + CN + +60-95-CE (hex) Robot S.A. +300000-3FFFFF (base 16) Robot S.A. + Gremi de Cirurgians i Barbers 22 + Palma de Mallorca SPAIN / Balearic Islands 07009 + ES + +BC-97-40 (hex) Rollock Oy +D00000-DFFFFF (base 16) Rollock Oy + Viestitie 2 B + Kajaani 87700 + FI + +BC-34-00 (hex) Private +F00000-FFFFFF (base 16) Private + +1C-82-59 (hex) Shandong Luneng Intelligence Technology CO., Ltd +000000-0FFFFF (base 16) Shandong Luneng Intelligence Technology CO., Ltd + Shandong Jinan Hightech zone Yinhe building block B, 2008 Xinluo Street + Jinan Shandong 250100 + CN + +1C-82-59 (hex) Jump Trading +700000-7FFFFF (base 16) Jump Trading + 1 London Wall + London EC2Y 5EA + GB + +1C-82-59 (hex) winsun AG +400000-4FFFFF (base 16) winsun AG + Beeschi Mattenstrasse 2 + Steg Wallis 3940 + CH + +F8-1D-78 (hex) TELEOFIS +800000-8FFFFF (base 16) TELEOFIS + 1K3, Electrolitny proezd + Moscow 115230 + RU + +1C-82-59 (hex) Applied Concepts, Inc. +D00000-DFFFFF (base 16) Applied Concepts, Inc. + 855 E Collins Blvd + Richardson TX 75081 + US + +84-8B-CD (hex) CHONGQING HUAYI KANGDAO TECHNOLOGY CO.,LTD. +B00000-BFFFFF (base 16) CHONGQING HUAYI KANGDAO TECHNOLOGY CO.,LTD. + 14th Floor, Unicom Building, 192 Yuzhou Road, Yuzhong District + CHONGQING 410010 + CN + +84-8B-CD (hex) NORALSY +900000-9FFFFF (base 16) NORALSY + 16 rue Lavoisier + Chennevieres sur Marne Ile de France 94430 + FR + +1C-82-59 (hex) Evondos Oy +C00000-CFFFFF (base 16) Evondos Oy + Salorankatu 5-7 + Salo 24240 + FI + +1C-82-59 (hex) Fagus-GreCon Greten GmbH & Co. KG +500000-5FFFFF (base 16) Fagus-GreCon Greten GmbH & Co. KG + Hannoversche Straße 58 + Alfeld 31061 + DE + +1C-82-59 (hex) C&A Marketing, INC. +300000-3FFFFF (base 16) C&A Marketing, INC. + 114 Tived Lane East + Edison NJ 08837 + US + +B0-FD-0B (hex) MartinLogan, Ltd. +B00000-BFFFFF (base 16) MartinLogan, Ltd. + 2101 Delware St + Lawrence KS 66046 + US + +B0-FD-0B (hex) DNESO TEN Ltd. +600000-6FFFFF (base 16) DNESO TEN Ltd. + 1-2-28,gosho-doori,hyougo-ku + kobe hyougo 652-8510 + JP + +84-8B-CD (hex) Shenzhen LTIME In-Vehicle Entertainment System Company Limited +100000-1FFFFF (base 16) Shenzhen LTIME In-Vehicle Entertainment System Company Limited + 4/F, Building 1, Nangang 1st Industrial Park No. 1029, Songbai Road, Xili, Nanshan District + SHENZHEN GUANGDONG 518055 + CN + +B0-FD-0B (hex) Haltian Products Oy +C00000-CFFFFF (base 16) Haltian Products Oy + Yrttipellontie 1D + Oulu 90230 + FI + +80-7B-85 (hex) Private +F00000-FFFFFF (base 16) Private + +E4-1E-0A (hex) IDvaco Private Limited +200000-2FFFFF (base 16) IDvaco Private Limited + Aljunied road, 627A,06-02 + singapore singapore 389842 + SG + +E4-1E-0A (hex) Connected Cars A/S +100000-1FFFFF (base 16) Connected Cars A/S + Park Allé 355 + Brøndby 2605 + DK + +E4-1E-0A (hex) B METERS S.R.L. +900000-9FFFFF (base 16) B METERS S.R.L. + VIA FRIULI 3 + GONARS UDINE 33050 + IT + +E4-1E-0A (hex) Safety Vision, LLC +B00000-BFFFFF (base 16) Safety Vision, LLC + 6100 West Sam Houston Parkway North + Houston TX 77041-5113 + US + +E4-1E-0A (hex) XPR Group +400000-4FFFFF (base 16) XPR Group + Drève Richelle 161 - WOP G + Waterloo 1410 + BE + +E4-1E-0A (hex) SFC Energy AG +600000-6FFFFF (base 16) SFC Energy AG + Eugen-Saenger-Ring 7 + Brunnthal 85649 + DE + +C8-63-14 (hex) Shenzhen Lihewei Electronics Co.,Ltd.Hunan Branch +B00000-BFFFFF (base 16) Shenzhen Lihewei Electronics Co.,Ltd.Hunan Branch + Room 501,Room 502,Building 2,Xinggong Technology Park,No.100 Luyun Road, High-tech Development Zone + Changsha Hunan 410000 + CN + +34-E1-D1 (hex) Hubitat Inc. +800000-8FFFFF (base 16) Hubitat Inc. + 20343 N Hayden Rd, Suite 105-280 + Scottsdale AZ 85255 + US + +34-E1-D1 (hex) APG Cash Drawer, LLC +B00000-BFFFFF (base 16) APG Cash Drawer, LLC + 5250 Industrial Blvd NE + Minneapolis MN 55421 + US + +34-E1-D1 (hex) OrCam Technologies +A00000-AFFFFF (base 16) OrCam Technologies + Kiryat Hamada 3 + JERUSALEM 97775603 + IL + +C8-63-14 (hex) Tymphany Acoustic Technology (Huizhou) Co., Ltd. +200000-2FFFFF (base 16) Tymphany Acoustic Technology (Huizhou) Co., Ltd. + Tymphany Industrial Area, Xin Lian Village, XinXu Town, HuiYang District + Huizhou Guangdong 516223 + CN + +FC-D2-B6 (hex) Cirque Audio Technology Co.,Ltd +600000-6FFFFF (base 16) Cirque Audio Technology Co.,Ltd + No.2 Road BeiYiHeng,HuangJiaBao Industrial Park,ShiPai Town,DongGuan City,GuangDong,China + DongGuan GuangDong 523000 + CN + +FC-D2-B6 (hex) LINK (FAR-EAST) CORPORATION +100000-1FFFFF (base 16) LINK (FAR-EAST) CORPORATION + No.192, Lian-Cheng Rd., Chung-Ho, Taipei,Taiwan 23553 + Taipei Taiwan 23553 + TW + +FC-D2-B6 (hex) SHEN ZHEN XIN HAO YUAN PRECISION TECHNOLOGY CO.,L TD +400000-4FFFFF (base 16) SHEN ZHEN XIN HAO YUAN PRECISION TECHNOLOGY CO.,L TD + 1,2,3 Building,XinHaoYuan Industrial Area,HeYi Community,Shajing Street,BaoAn District.Shenzhen + shenzhen guangdongsheng 518000 + CN + +FC-D2-B6 (hex) Teamly Digital +700000-7FFFFF (base 16) Teamly Digital + 11-13 Avenue de Friedland + Paris Ile de France 75008 + FR + +74-5B-C5 (hex) Qingdao Wintec System Co., Ltd +E00000-EFFFFF (base 16) Qingdao Wintec System Co., Ltd + Wintec Park, Xinye Road, High-tech Zone, Qingdao, China 266114 + QING DAO shan dong of China 6805 + CN + +74-5B-C5 (hex) SIGLENT TECHNOLOGIES CO., LTD. +200000-2FFFFF (base 16) SIGLENT TECHNOLOGIES CO., LTD. + Blog No.4 & No.5, Antongda Industrial Zone, 3rd Liuxian Road, Bao’an District, Shenzhen, 518101, China. + Shenzhen Guangdong 518101 + CN + +74-5B-C5 (hex) Yekani Manufacturing PTY Ltd +600000-6FFFFF (base 16) Yekani Manufacturing PTY Ltd + Fourways Golf Park,Selbourne Building,Roos St + Witkoppen Gauteng 5214 + ZA + +74-5B-C5 (hex) SHENZHEN ATX TECHNOLOGY CO.,LTD +700000-7FFFFF (base 16) SHENZHEN ATX TECHNOLOGY CO.,LTD + 7/F,Zhengjiyuan Buiding,2 Road,Qianjing, Xixiang, Baoan District + Shenzhen GUANGDONG 518000 + CN + +E4-4C-C7 (hex) Ottomate International Pvt. Ltd. +900000-9FFFFF (base 16) Ottomate International Pvt. Ltd. + Awfis Building, 5th Floor, Plot # 7, Sector-44 + Gurgaon Haryana 122003 + IN + +E4-4C-C7 (hex) ACS-Solutions GmbH +100000-1FFFFF (base 16) ACS-Solutions GmbH + Science Park 2 + Saarbrücken 66123 + DE + +E4-4C-C7 (hex) Telo Systems Limitd +D00000-DFFFFF (base 16) Telo Systems Limitd + 4/F, Chuangye Building, Seven-Star Park, Yu'an 2nd Road + ShenZhen GuangDong 518000 + CN + +E4-4C-C7 (hex) SmallHD +B00000-BFFFFF (base 16) SmallHD + 301 Gregson Dr + Cary NC 27511 + US + +74-5B-C5 (hex) SpringCard +500000-5FFFFF (base 16) SpringCard + 2 voie La Cardon, Parc Gutenberg + PALAISEAU IDF 91120 + FR + +74-5B-C5 (hex) IRS Systementwicklung GmbH +000000-0FFFFF (base 16) IRS Systementwicklung GmbH + Pfaffenthanner Weg, 5 + Brennberg 93179 + DE + +1C-A0-D3 (hex) Private +700000-7FFFFF (base 16) Private + +28-FD-80 (hex) Private +F00000-FFFFFF (base 16) Private + +E0-5A-9F (hex) ShenZhen Mornsun Smartlinker Limited Co., LTD +C00000-CFFFFF (base 16) ShenZhen Mornsun Smartlinker Limited Co., LTD + South 2nd Flr, 23 Bldg, Yuanxi Industrial Zone, Kefa Rd, Nanshan Keji Yuan + ShenZhen GuangDong 518058 + CN + +4C-BC-98 (hex) Elink Technology (Shenzhen) Co., Limited +D00000-DFFFFF (base 16) Elink Technology (Shenzhen) Co., Limited + C-323,Baoan,Xinyidai Info.Tech.Industrial Park, No.139 Chuangye Er Rd.,Baoan District + Shenzhen Guangdong 518101 + CN + +E0-5A-9F (hex) Fujian Newland Auto-ID Tech. Co.,Ltd. +800000-8FFFFF (base 16) Fujian Newland Auto-ID Tech. Co.,Ltd. + Newland Science & Technology Park, No.1 Rujiang West Rd,Mawei,Fuzhou, P.R.China + Fuzhou Fujian 350015 + CN + +4C-BC-98 (hex) Charge-Amps AB +000000-0FFFFF (base 16) Charge-Amps AB + GUSTAV III:S BOULEVARD 42, 8TR + SOLNA 16973 + SE + +38-B1-9E (hex) ShenZhen ShuaiXian Electronic Equipment Co.Ltd +E00000-EFFFFF (base 16) ShenZhen ShuaiXian Electronic Equipment Co.Ltd + No. 10, Lane 3, Longxing Rd, Dakang Village,HengGang Town + ShenZhen Guangdong 518115 + CN + +D8-86-0B (hex) Auvidea GmbH +300000-3FFFFF (base 16) Auvidea GmbH + Kellerberg 3 + Denklingen 86920 + DE + +28-F5-37 (hex) 1MORE +800000-8FFFFF (base 16) 1MORE + TianliaoBuilding F14 + New Materials Industrial Park,Xueyuan Blvd Shenzhen, Nanshan District 518005 + CN + +D8-86-0B (hex) YUSAN INDUSTRIES LIMITED   +C00000-CFFFFF (base 16) YUSAN INDUSTRIES LIMITED   + UNIT 8-9, 8/F., HONOUR INDUSTRIAL CENTRE, 6 SUN YIP STREET, CHAI WAN + HongKong 999077 + HK + +D8-86-0B (hex) Library Ideas +B00000-BFFFFF (base 16) Library Ideas + PO Box 9 + Vienna VA 22183 + US + +D8-86-0B (hex) ComNav Technology Ltd. +D00000-DFFFFF (base 16) ComNav Technology Ltd. + Buliding 2,No. 618 Chengliu Middle Road + JiaDing District Shanghai 201801 + CN + +38-B1-9E (hex) Star Electronics GmbH & CoKG +500000-5FFFFF (base 16) Star Electronics GmbH & CoKG + Jahnstraße, 86 + Göppingen 73037 + DE + +38-B1-9E (hex) HDANYWHERE +200000-2FFFFF (base 16) HDANYWHERE + Unit 23 Link Business Centre + Malvern Worcs WR14 1UQ + GB + +38-B1-9E (hex) Aeroespacial Guosheng Technology Co., Ltd +A00000-AFFFFF (base 16) Aeroespacial Guosheng Technology Co., Ltd + 501 Edificio Gaode, No. 10 Huayuan East Road, + Haiden DIstrict Beijing 100191 + CN + +D8-86-0B (hex) Shenzhen Yidong Technology Co.,Ltd +E00000-EFFFFF (base 16) Shenzhen Yidong Technology Co.,Ltd + 13th Floor,Jia'anda Building, No.110 Huafan Road,Tongsheng Community, Dalang Street,Longhua District + Shenzhen Guangdong 518000 + CN + +D8-86-0B (hex) VRINDA NANO TECHNOLOGIES PVT LTD +800000-8FFFFF (base 16) VRINDA NANO TECHNOLOGIES PVT LTD + PLOT NO.283, SECTOR 7, IMT MANESAR, GURGAON + INDIA HARYANA 122050 + IN + +38-B1-9E (hex) Triple Jump Medical +000000-0FFFFF (base 16) Triple Jump Medical + 5 HaCarmel St. + Yokneam 2069203 + IL + +38-B1-9E (hex) BoCo Inc. +800000-8FFFFF (base 16) BoCo Inc. + Isshin Bldg 6F,Yaesu 2-11-7 + Chuo-ku, Tokyo 104-0028 + JP + +38-B1-9E (hex) Gesellschaft industrieller Technologien +C00000-CFFFFF (base 16) Gesellschaft industrieller Technologien + Hauptstraße 10 + Großbeeren 14979 + DE + +CC-D3-9D (hex) Q-Branch Labs, Inc. +B00000-BFFFFF (base 16) Q-Branch Labs, Inc. + 427 N. Tatnall St., Suite #82712 + Wilmington DE 19801 + US + +CC-D3-9D (hex) Shenzhen Chenggu Technology Co., Ltd +400000-4FFFFF (base 16) Shenzhen Chenggu Technology Co., Ltd + Longgang District Jihua street Zhonghaixin Industrial Innovation City 19A 3F + Shenzhen Guagndong 518112 + CN + +CC-D3-9D (hex) Krontech +600000-6FFFFF (base 16) Krontech + I.T.U ARI 3 Teknokent Kron Telekomunikasyon, Maslak + Istanbul 34467 + TR + +CC-D3-9D (hex) Bejing Nexsec Inc. +900000-9FFFFF (base 16) Bejing Nexsec Inc. + Floor 5, Room 5001,Buliding No.4,Fengxian Middle Road No.7 + (Beike Industrial Park),Haidian District, Beijing 100094 + CN + +CC-D3-9D (hex) Obelisk Inc. +800000-8FFFFF (base 16) Obelisk Inc. + 67 Batterymarch Street, Floor 4 + Boston 02110 + US + +D4-25-CC (hex) TAKUMI JAPAN LTD +900000-9FFFFF (base 16) TAKUMI JAPAN LTD + 3-9-3 Uchiyama building 7F Nishishinbashi + Minato-ku Tokyo Tokyo 1050003 + JP + +9C-69-B4 (hex) NINGBO SHEN LINK COMMUNICATION TECHNOLOGY CO., LTD +E00000-EFFFFF (base 16) NINGBO SHEN LINK COMMUNICATION TECHNOLOGY CO., LTD + NO.87,FENGMINGROAD,LIZHOUSTREET, YUYAO, ZHEJIANG + NINGBO ZHEJIANG 315400 + CN + +4C-91-7A (hex) Openeye +600000-6FFFFF (base 16) Openeye + 23221 East Knox Avenue + Liberty Lake WA 99019 + US + +4C-91-7A (hex) Smart Access +300000-3FFFFF (base 16) Smart Access + Nauchnuy Proezd 10 + Moscow 117246 + RU + +9C-69-B4 (hex) Suzhou Fitcan Technology Co.,LTD +000000-0FFFFF (base 16) Suzhou Fitcan Technology Co.,LTD + Kechuang Road + Suzhou City Jiangsu Province 215163 + CN + +9C-69-B4 (hex) Guangdong Hanwei intergration Co.,Ltd +C00000-CFFFFF (base 16) Guangdong Hanwei intergration Co.,Ltd + Room 404,7# Hongtai Zhihui Gu, No.23 Sicheng Road + Guangzhou Guangdong 510663 + CN + +9C-69-B4 (hex) Shenzhen jiahua zhongli technology co.LTD +600000-6FFFFF (base 16) Shenzhen jiahua zhongli technology co.LTD + 3/F,building B,JINHU building,industrial road,longhua new district + Shenzhen Guangdong 518109 + CN + +6C-DF-FB (hex) Nanjing Buruike Electronics Technology Co., Ltd. +D00000-DFFFFF (base 16) Nanjing Buruike Electronics Technology Co., Ltd. + Jiangning District Moling Street, SuYuan Avenue No.117 Building 2, Floor 5 Room 541 + Nanjing Jiangsu 210000 + CN + +4C-91-7A (hex) Alibaba (Beijing) Software Service Inc. +C00000-CFFFFF (base 16) Alibaba (Beijing) Software Service Inc. + No. 301, 3 floor, 9 building, four district, Wangjing East Garden, Chaoyang District, + Beijing Beijing 100102 + CN + +4C-91-7A (hex) mtekvision +500000-5FFFFF (base 16) mtekvision + 6F, C's Tower, 58, Pangyo-ro 255veon-gil, Bundang-gu + seongnam-si Gyeonggi-do 13486 + KR + +7C-BC-84 (hex) Beijing Topnew Group Co., Ltd +E00000-EFFFFF (base 16) Beijing Topnew Group Co., Ltd + No.9, A, Jin Tai Li, ChaoYang District + Beijing 100026 + CN + +7C-BC-84 (hex) Shenzhen Kuang-chi Space Technology Co., Ltd. +800000-8FFFFF (base 16) Shenzhen Kuang-chi Space Technology Co., Ltd. + No. 1 building, No. 2 Reservoir Road, Nan Keng community , Bantian street, Longgang District, Shenzhen + shenzhen Guangdong 518000 + CN + +6C-DF-FB (hex) Lineable Inc +400000-4FFFFF (base 16) Lineable Inc + 5, Ttukseom-ro 1na-gil, Seongdong-gu, Seoul, Republic of Korea, Heyground, G505 + Seoul Seoul 04779 + KR + +98-F9-C7 (hex) NC-LINK Technology Co., Ltd. +E00000-EFFFFF (base 16) NC-LINK Technology Co., Ltd. + Block A2 Jinhai Business Mansion, Jinhai Road, Xixiang town + Shenzhen Guangdong 518101 + CN + +7C-BC-84 (hex) Shanghai Yitu Technology Co. Ltd +300000-3FFFFF (base 16) Shanghai Yitu Technology Co. Ltd + 23/F, Tower 1, No.523 Loushanguan Road, Changning District + Shanghai 200051 + CN + +0C-FE-5D (hex) Antailiye Technology Co.,Ltd +600000-6FFFFF (base 16) Antailiye Technology Co.,Ltd + 7/F,Zhengjiyuan Buiding,2 Road,Qianjing, Xixiang, Baoan District,Shenzhen + SHEN ZHEN GUANGDONG 518000 + CN + +0C-FE-5D (hex) Yantai Dongfang Wisdom Electic Co.,Ltd. +400000-4FFFFF (base 16) Yantai Dongfang Wisdom Electic Co.,Ltd. + 6 Jindu Road + Yantai Shandong 264003 + CN + +98-F9-C7 (hex) Pozyx NV +200000-2FFFFF (base 16) Pozyx NV + Vrijdagmarkt 10/201 + Gent Oost-Vlaanderen 9000 + BE + +0C-FE-5D (hex) SELECTRIC Nachrichten-Systeme GmbH +500000-5FFFFF (base 16) SELECTRIC Nachrichten-Systeme GmbH + Haferlandweg 18 + Münster 48155 + DE + +0C-FE-5D (hex) Vermes Microdispensing GmbH +700000-7FFFFF (base 16) Vermes Microdispensing GmbH + Palnkamer Strasse 18 + Otterfing Bayern 83624 + DE + +10-07-23 (hex) Private +F00000-FFFFFF (base 16) Private + +6C-5C-3D (hex) IskraUralTEL +900000-9FFFFF (base 16) IskraUralTEL + Komvuzovkaya + Ekaterinburg 620137 + RU + +6C-5C-3D (hex) HTI Co., LTD. +400000-4FFFFF (base 16) HTI Co., LTD. + Rm741, Kyungin Ctr., 20, Baekbeom-ro 577, Bupyung-Gu + Incheon 21449 + KR + +A8-3F-A1 (hex) Plejd AB +700000-7FFFFF (base 16) Plejd AB + Göteborgsvägen 52 + Mölndal 431 37 + SE + +A8-3F-A1 (hex) Guangzhou Navigateworx Technologies Co., Limited +E00000-EFFFFF (base 16) Guangzhou Navigateworx Technologies Co., Limited + Room 2320, Qianjin Commercial Building, Dongpu Town + Guangzhou Guangdong 510660 + CN + +A8-3F-A1 (hex) Shanghai East China Computer Co., Ltd +A00000-AFFFFF (base 16) Shanghai East China Computer Co., Ltd + 27/F Tower B, No.391 Guiping Rd + Shanghai Shanghai 200233 + CN + +A0-3E-6B (hex) Private +F00000-FFFFFF (base 16) Private + +A8-3F-A1 (hex) Laonz Co.,Ltd +C00000-CFFFFF (base 16) Laonz Co.,Ltd + 15-3,Eonnam-Gil,Seocho-gu + Seoul 06779 + KR + +3C-6A-2C (hex) figur8, Inc. +300000-3FFFFF (base 16) figur8, Inc. + 2 Park Plaza, Suite 605 + BOSTON MA 02116 + US + +30-0A-60 (hex) Realtime biometrics India pvt ltd +600000-6FFFFF (base 16) Realtime biometrics India pvt ltd + C-68,1st Floor ganesh nagar pandav nagar complex + delhi Delhi 110092 + IN + +A4-ED-43 (hex) Shanghai Facom Electronics Technology Co, ltd. +600000-6FFFFF (base 16) Shanghai Facom Electronics Technology Co, ltd. + The third floor, A area, Huaxu road No. 685 + Shanghai Xujing town,Qingpu 200217 + CN + +30-0A-60 (hex) Advanced Electronic Designs, Inc. +200000-2FFFFF (base 16) Advanced Electronic Designs, Inc. + 233 Enterprise Blvd + Bozeman MT 59718 + US + +A0-28-33 (hex) SHANGHAI XUNTAI INFORMATION TECHNOLOGY CO.,LTD. +300000-3FFFFF (base 16) SHANGHAI XUNTAI INFORMATION TECHNOLOGY CO.,LTD. + ET SPACE, ZIZHU PARK, NO.555, DONGCHUAN RD. + SHANGHAI SHANGHAI 200241 + CN + +A0-28-33 (hex) Ordercube GmbH +100000-1FFFFF (base 16) Ordercube GmbH + Aßlinger Str. 6 + Grafing b. München Bayern 85567 + DE + +A0-28-33 (hex) Medical Evolution Kft +A00000-AFFFFF (base 16) Medical Evolution Kft + Liszenko telep 1 + Pomaz 2013 + HU + +A0-28-33 (hex) HZHY TECHNOLOGY +800000-8FFFFF (base 16) HZHY TECHNOLOGY + The 2th floor,Longzeyuan Multi-use + beijing 102208 + CN + +A4-ED-43 (hex) Beijing ICPC CO.,Ltd. +500000-5FFFFF (base 16) Beijing ICPC CO.,Ltd. + Fengtai District HuaXiang LiuQuan West Road NO.8 Xinhua ShuangChuangYuan Building B Floor 2 NO.203 + Beijing Beijing 100070 + CN + +A4-ED-43 (hex) NETAS TELEKOMUNIKASYON A.S. +400000-4FFFFF (base 16) NETAS TELEKOMUNIKASYON A.S. + Kurtköy Mahallesi, Osmanlı Blv. No:11 + Pendik Istanbul 34912 + TR + +A4-ED-43 (hex) Guangzhou Maxfaith Communication Technology Co.,LTD. +A00000-AFFFFF (base 16) Guangzhou Maxfaith Communication Technology Co.,LTD. + 3rd Floor,Office of Youtong Zone,No.139,Zhongshan Avenue + Guangzhou 510665 + CN + +84-89-EC (hex) Price Industries Limited +D00000-DFFFFF (base 16) Price Industries Limited + 638 Raleigh Street + Winnipeg Manitoba R2K3Z9 + CA + +30-09-F9 (hex) ZhongLi HengFeng (Shenzhen) Technology co.,Ltd. +E00000-EFFFFF (base 16) ZhongLi HengFeng (Shenzhen) Technology co.,Ltd. + Room 402C Donglian Buiding,Chuangye NO 2 road,Baoan + Shenzhen Guangdong 430000 + CN + +30-09-F9 (hex) Sichuan Nebula Networks Co.,LTD. +B00000-BFFFFF (base 16) Sichuan Nebula Networks Co.,LTD. + Floor 21 Building 2,No.200 Tianquan Road,West Hi-Tech Zone, + Chengdu Sichuan 611731 + CN + +84-89-EC (hex) thousand star tech LTD. +200000-2FFFFF (base 16) thousand star tech LTD. + guan nan yuan 1 road dangdai optical valley dream workshop + wuhan hubei 430070 + CN + +9C-F6-DD (hex) Shanxi ZhuoZhi fei High Electronic Technology Co. Ltd. +E00000-EFFFFF (base 16) Shanxi ZhuoZhi fei High Electronic Technology Co. Ltd. + Red flag East Street + yuncheng shanxi 044000 + CN + +B8-D8-12 (hex) IPM Sales and service Co.,Ltd. +200000-2FFFFF (base 16) IPM Sales and service Co.,Ltd. + 250-252 Soi 29 Somdet Prachaotaksin Road + Bangkok Bangkok 10600 + TH + +9C-F6-DD (hex) Beijing Sifang Automation Co., Ltd. +200000-2FFFFF (base 16) Beijing Sifang Automation Co., Ltd. + No.9,Shangdi 4th Street,Haidian District + Beijing 100085 + CN + +9C-F6-DD (hex) b8ta Inc. +500000-5FFFFF (base 16) b8ta Inc. + 164 Townsend St + San Francisco CA 94107 + US + +9C-F6-DD (hex) Annapurna labs +000000-0FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +30-09-F9 (hex) Honeywell +C00000-CFFFFF (base 16) Honeywell + 13350 US Hwy 19 N + Clearwater null 33764 + US + +C0-83-59 (hex) CHONGQING JIUYU SMART TECHNOLOGY CO.LTD. +000000-0FFFFF (base 16) CHONGQING JIUYU SMART TECHNOLOGY CO.LTD. + T2-11-3, No. 2 Jiangbeizui Financial City, Jiangbei District, + Chongqing Chongqing 400000 + CN + +04-C3-E6 (hex) Shenzhen Shuotian Information Technology Co., LTD +600000-6FFFFF (base 16) Shenzhen Shuotian Information Technology Co., LTD + Xixiang Street , Bao'an District + Shenzhen Guangdong 518000 + CN + +04-C3-E6 (hex) Advanced Digital Technologies, s.r.o. +700000-7FFFFF (base 16) Advanced Digital Technologies, s.r.o. + Purkynova 649/127 + Medlanky Brno 612 00 + CZ + +04-C3-E6 (hex) Guangdong New Pulse Electric Co., Ltd. +100000-1FFFFF (base 16) Guangdong New Pulse Electric Co., Ltd. + No. 38 South Kemu Road + Guangzhou City Tianhe District, Guangdong Province 510520 + CN + +3C-42-7E (hex) Xiaoniu network technology (Shanghai) Co., Ltd. +E00000-EFFFFF (base 16) Xiaoniu network technology (Shanghai) Co., Ltd. + Room 706, building 3, no.20 east road, jingan district. + Shang hai 200040 + CN + +04-C3-E6 (hex) SiS Technology +200000-2FFFFF (base 16) SiS Technology + Business Park Varna, building B1, floor 4 + Varna 9000 + BG + +3C-42-7E (hex) Dongguan Taide Industrial Co.,Ltd. +100000-1FFFFF (base 16) Dongguan Taide Industrial Co.,Ltd. + Taide Industrial Park,Phase 2 Jinfenghuang Industrial District Huangdong,Fenggang Town + Dongguan City GuangDong 523696 + CN + +D4-7C-44 (hex) YunDing Network Technology (Beijing) Co., Ltd +200000-2FFFFF (base 16) YunDing Network Technology (Beijing) Co., Ltd + A521,Floor 5, Tencent Space Building No.388, Hui long guan East St. + Beijing 100000 + CN + +D4-7C-44 (hex) Suzhou Wan Dian Zhang Network Technology Co., Ltd +900000-9FFFFF (base 16) Suzhou Wan Dian Zhang Network Technology Co., Ltd + No. 209 Zhuyuan Road, High-tech Zone + Suzhou City Jiangsu 215010 + CN + +B4-4B-D6 (hex) Shenzhen Huabai Intelligent Technology Co., Ltd. +A00000-AFFFFF (base 16) Shenzhen Huabai Intelligent Technology Co., Ltd. + Science Park South District Shenzhen Digital + Technology Park Building B2 4th Floor Area A Shenzhen, Guangdong 518000 + CN + +3C-42-7E (hex) GJS Co., Ltd. +700000-7FFFFF (base 16) GJS Co., Ltd. + 305, Qianhai Innovation and Entrepreneur Hub, Bldg. C Qianwan 1st Rd., Nanshan District + Shenzhen Guangdong 518000 + CN + +3C-42-7E (hex) TAITEX CORPORATION +900000-9FFFFF (base 16) TAITEX CORPORATION + 1-7-12,WAKATAKE + ICHINOMIYA-SHI AICHI-KEN 491-0832 + JP + +B4-4B-D6 (hex) Impakt S.A. +C00000-CFFFFF (base 16) Impakt S.A. + Stanislawa Lema 16 + Mosina Wielkopolska 62-050 + PL + +A0-19-B2 (hex) Power Diagnostic Service Co., LTD. +300000-3FFFFF (base 16) Power Diagnostic Service Co., LTD. + No.10, Ln.482, Sec.4 Zhonghua Rd. + Hsinchu City 30094 + TW + +CC-D3-1E (hex) CUJO LLC +D00000-DFFFFF (base 16) CUJO LLC + 2512 Artesia Blvd + Redondo Beach CA 90278 + US + +A0-19-B2 (hex) LDA Technologies +C00000-CFFFFF (base 16) LDA Technologies + 2680 Matheson Blvd E., Suite 102 + Mississauga Ontario L4W2C6 + CA + +A0-19-B2 (hex) Vast Production Services +000000-0FFFFF (base 16) Vast Production Services + 307 Robbins Drive + Troy MI 48083 + US + +74-F8-DB (hex) Ballard Technology, Inc, +A00000-AFFFFF (base 16) Ballard Technology, Inc, + 11400 Airport Rd + Everett 98204 + US + +2C-48-35 (hex) DPS Electronics +800000-8FFFFF (base 16) DPS Electronics + 317 Gallatin Park Dr #2 + Bozeman MT 59715 + US + +2C-48-35 (hex) Shanghai Visteon Automotive Electronics System CO. Ltd. +B00000-BFFFFF (base 16) Shanghai Visteon Automotive Electronics System CO. Ltd. + No.1268, East Kangqiao Road, Pudong District, + ShangHai 201315 + CN + +8C-1C-DA (hex) Anntec (Beijing) Technology Co.,Ltd. +400000-4FFFFF (base 16) Anntec (Beijing) Technology Co.,Ltd. + F803, Shangdi Third Street, No.9,HaiDian District + Beijing 100080 + CN + +3C-24-F0 (hex) CASKY eTech Co., Ltd. +500000-5FFFFF (base 16) CASKY eTech Co., Ltd. + 10th Floor, Viva Plaza, Yard 29 Suzhou Street, Haidian District, + Beijing Beijing 100080 + CN + +0C-73-EB (hex) Green Fox Electro AS +600000-6FFFFF (base 16) Green Fox Electro AS + Wessels veg 63 + STJORDAL NO-7502 + NO + +8C-1C-DA (hex) China Potevio Co., Ltd +A00000-AFFFFF (base 16) China Potevio Co., Ltd + No.6, haidian north second street, haidian district, Beijing + Beijing Beijing 100080 + CN + +3C-24-F0 (hex) Travis Holding B.V. +D00000-DFFFFF (base 16) Travis Holding B.V. + Stationsplein 45, A4.002 3013 AK + Rotterdam 3013AK + NL + +3C-24-F0 (hex) Abrites Ltd. +100000-1FFFFF (base 16) Abrites Ltd. + 147 Cherni Vrah Blvd. + Sofia Sofia 1407 + BG + +48-0B-B2 (hex) Solaredge LTD. +500000-5FFFFF (base 16) Solaredge LTD. + Hamada 1 + Herzelia 4673335 + IL + +48-0B-B2 (hex) shanghai Rinlink Intelligent Technology Co., Ltd. +300000-3FFFFF (base 16) shanghai Rinlink Intelligent Technology Co., Ltd. + Room1510,ROAD Xiuwen,Minhang District + shanghai 201100 + CN + +88-5F-E8 (hex) Unicom Global, Inc. +E00000-EFFFFF (base 16) Unicom Global, Inc. + 581, Ruiguang Road, Neihu Dist. + Taipei 11492 + TW + +30-1F-9A (hex) FINE TRIUMPH TECHNOLOGY CORP.,LTD. +800000-8FFFFF (base 16) FINE TRIUMPH TECHNOLOGY CORP.,LTD. + Xixiang + Shenzhen Guangdong 518126 + CN + +30-1F-9A (hex) Beijing Surestar Technology Co. Ltd, +500000-5FFFFF (base 16) Beijing Surestar Technology Co. Ltd, + Room 502, building 1, No. 5 Yongfeng Road, Haidian District + Beijing 100089 + CN + +30-1F-9A (hex) ILSAN ELECTRONICS +000000-0FFFFF (base 16) ILSAN ELECTRONICS + 433Beon-gil 52,Sasang-ro,Sasang-gu + Busan 46923 + KR + +30-1F-9A (hex) Dewesoft d.o.o. +100000-1FFFFF (base 16) Dewesoft d.o.o. + Gabrsko 11a + Trbovlje 1420 + SI + +F0-41-C8 (hex) SHENZHEN WISEWING INTERNET TECHNOLOGY CO.,LTD +300000-3FFFFF (base 16) SHENZHEN WISEWING INTERNET TECHNOLOGY CO.,LTD + No.826,Zone 1,Block B,Famous industrial product display purchasing center,Baoyuan Road,Xixiang,Bao'an Dis., Shenzhen,P.R.China + shenzhen China 518102 + CN + +88-A9-A7 (hex) Thomas & Darden, Inc +400000-4FFFFF (base 16) Thomas & Darden, Inc + 916 Springdale Rd Bldg 4 #104 + Austin 78702 + US + +F0-41-C8 (hex) Powervault Ltd +B00000-BFFFFF (base 16) Powervault Ltd + 29 Shand Street, London Bridge + London SE1 2ES + GB + +A4-DA-22 (hex) EHO.LINK +C00000-CFFFFF (base 16) EHO.LINK + 5 Avenue de Saint Menet, Imm. Axiome, Bat. B + Marseille 13011 + FR + +88-A9-A7 (hex) Zhejiang Haoteng Electronic Technology Co.,Ltd. +A00000-AFFFFF (base 16) Zhejiang Haoteng Electronic Technology Co.,Ltd. + Zhejiang Lishui city streets Nanming mountain Shek road Liandu District No. 268 Building 2 block B + Lishui Zhejiang 323000 + CN + +DC-E5-33 (hex) Giant Power Technology Biomedical Corporation +E00000-EFFFFF (base 16) Giant Power Technology Biomedical Corporation + Rm201, 2nd Educational Building, No. 84, Gongzhuan Rd, Taishan Dist + New Taipei City 24301 + TW + +DC-E5-33 (hex) Suzhou ATES electronic technology co.LTD +D00000-DFFFFF (base 16) Suzhou ATES electronic technology co.LTD + NO.2 aimin road,Xiangcheng district + Suzhou city Jiangsu Province 215002 + CN + +DC-E5-33 (hex) BRCK +C00000-CFFFFF (base 16) BRCK + PO Box 58275-00200, 2nd Floor Bishop Magua Center, George Padmore Lane, 2nd Floor Bishop Magua Center, George Padmore Lane + Nairobi Nairobi 00200 + KE + +DC-E5-33 (hex) shenzhen bangying electronics co,.ltd +400000-4FFFFF (base 16) shenzhen bangying electronics co,.ltd + 3/F Building 16,Hongfa industrialPark,Tangtou Shiyan Town + shenzhen guangdong 518000 + CN + +DC-E5-33 (hex) Tiertime Corporation +900000-9FFFFF (base 16) Tiertime Corporation + 2398 Walsh Avenue + Santa Clara CA 95051 + US + +DC-E5-33 (hex) FLYHT Aerospace +000000-0FFFFF (base 16) FLYHT Aerospace + 300E 1144 - 29th St. N.E. + Calgary AB T2E7P1 + CA + +9C-43-1E (hex) SuZhou Jinruiyang Information Technology CO.,LTD +C00000-CFFFFF (base 16) SuZhou Jinruiyang Information Technology CO.,LTD + NO.1003 Room A1 Buliding Tengfei Business Park in Suzhou Industrial Park. + Suzhou Jiangsu 215123 + CN + +9C-43-1E (hex) JNL Technologies Inc +B00000-BFFFFF (base 16) JNL Technologies Inc + W1205 Industrial Dr + Ixonia WI 53036 + US + +C4-FF-BC (hex) iMageTech CO.,LTD. +400000-4FFFFF (base 16) iMageTech CO.,LTD. + 5F., No.16, Lane 15, Sec. 6, Mincyuan E. Rd., Neihu District, + TAIPEI 114 + TW + +C4-FF-BC (hex) SHENZHEN KALIF ELECTRONICS CO.,LTD +300000-3FFFFF (base 16) SHENZHEN KALIF ELECTRONICS CO.,LTD + 1、2 and 3 Floor, No.114, Haochong No.2 Industry Area, Hongxing Community, Songgang, Baoan, Shenzhen + SHENZHEN GuangDong 518105 + CN + +28-2C-02 (hex) Epoch International Enterprises, Inc. +C00000-CFFFFF (base 16) Epoch International Enterprises, Inc. + 10542 Calle Lee, #114 + Los Alamitos CA 90720 + US + +28-2C-02 (hex) EFENTO T P SZYDŁOWSKI K ZARĘBA SPÓŁKA JAWNA +400000-4FFFFF (base 16) EFENTO T P SZYDŁOWSKI K ZARĘBA SPÓŁKA JAWNA + Dietla 93/6 + Kraków 31-031 + PL + +F8-B5-68 (hex) PT. Eyro Digital Teknologi +100000-1FFFFF (base 16) PT. Eyro Digital Teknologi + Jalan Amir Mahmud IX/23 + Surabaya Jawa Timur 60294 + ID + +40-48-FD (hex) RL Controls LLC. +300000-3FFFFF (base 16) RL Controls LLC. + 2 G Gill St + Woburn MA 01801 + US + +40-48-FD (hex) Dynamic Engineering +400000-4FFFFF (base 16) Dynamic Engineering + Dynamic Engineering, 150 DuBois St. Suite C + Santa Cruz CA 95060 + US + +40-48-FD (hex) Magenta Labs, Inc. +B00000-BFFFFF (base 16) Magenta Labs, Inc. + P.O. BOX 77234 + San Francisco CA 94107 + US + +40-48-FD (hex) Fast Programming +100000-1FFFFF (base 16) Fast Programming + Alyarmouk + Riyadh Ar Riyadh 13251 + SA + +40-48-FD (hex) SMART SENSOR DEVICES AB +E00000-EFFFFF (base 16) SMART SENSOR DEVICES AB + Sollentunavägen 67A + Sollentuna Stockholm 19140 + SE + +38-73-EA (hex) Eyesight(Shanghai)Communication Technology Co.,Ltd. +200000-2FFFFF (base 16) Eyesight(Shanghai)Communication Technology Co.,Ltd. + Room 820, C/F, Building 1, NO. 3000 Longdong Avenue, China(Shanghai) Pilot Free Trade + ShangHai ShangHai 201203 + CN + +38-73-EA (hex) L-3 Communications Mobile-Vision, Inc. +000000-0FFFFF (base 16) L-3 Communications Mobile-Vision, Inc. + 400 Commons Way STE F + Rockaway 07866 + US + +38-73-EA (hex) Rock Electronic Co., Ltd. +800000-8FFFFF (base 16) Rock Electronic Co., Ltd. + No. 1 Chuangsheng Rd. + shenzhen Guangdong 518055 + CN + +EC-9F-0D (hex) Paw-Taw-John Services, Inc. +500000-5FFFFF (base 16) Paw-Taw-John Services, Inc. + 18125 N Ramsey Rd + Rathdrum ID 83858-8288 + US + +EC-9F-0D (hex) Hesai Photonics Technology Co., Ltd +000000-0FFFFF (base 16) Hesai Photonics Technology Co., Ltd + 10th Floor, Building L2-B, Hongqiao World Center + Shanghai Shanghai 200010 + CN + +EC-9F-0D (hex) Sarcos Corp +C00000-CFFFFF (base 16) Sarcos Corp + 360 S Wakara Way + Salt Lake City UT 84108 + US + +EC-9F-0D (hex) FCI +900000-9FFFFF (base 16) FCI + B-7F,Silicon Park, 35, Pangyo-ro 255 beon-gil,Bundang-gu + Seongnam si Gyeonggi-do. KOREA 13486 + KR + +EC-9F-0D (hex) Bei jing Lian Shan times Techonology Co.Ltd +700000-7FFFFF (base 16) Bei jing Lian Shan times Techonology Co.Ltd + Beijing Haidian.No.2 of Yong Cheng North Road Building 1.402 + Beijing 100094 + CN + +34-D0-B8 (hex) eesy-innovation GmbH +500000-5FFFFF (base 16) eesy-innovation GmbH + Otto-Hahn-Str. 13b + Munich Bavaria 85521 + DE + +34-D0-B8 (hex) Vtrek Group International Ltd. +800000-8FFFFF (base 16) Vtrek Group International Ltd. + Room 1204,12/F.,Tower1,Silvercord,30 Canton Road,Tsim Sha Tsui + Hong Kong 999077 + HK + +34-D0-B8 (hex) Blustream Pty Ltd +200000-2FFFFF (base 16) Blustream Pty Ltd + 24 Lionel Road + Mt. Waverley Victoria 3149 + AU + +AC-1D-DF (hex) CRDE +300000-3FFFFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +34-D0-B8 (hex) Tascent, Inc. +300000-3FFFFF (base 16) Tascent, Inc. + 475 Alberto Way, Suite #200 + Los Gatos CA 95032 + US + +74-1A-E0 (hex) SAIERCOM CORPORATION +A00000-AFFFFF (base 16) SAIERCOM CORPORATION + ROOM 11501,FLOOR 15,UNIT 1,BLOCK 1,RENOVATION CENTER,TUANJIE SOUTH RD.,HI-TECH ZONE,XIAN,SHAANXI + XIAN SHAANXI 710065 + CN + +74-1A-E0 (hex) Blocks Wearables Inc. +600000-6FFFFF (base 16) Blocks Wearables Inc. + 1800 Century Park East, 10th Floor + Los Angeles CA 90067 + US + +74-1A-E0 (hex) Voltaware Services Limited +D00000-DFFFFF (base 16) Voltaware Services Limited + 230 High Street + Swanage BH19 2PQ + GB + +54-9A-11 (hex) Elotech Industrieelektronik GmbH +500000-5FFFFF (base 16) Elotech Industrieelektronik GmbH + Verbindungsstr. 27 + Hilden NRW 40723 + DE + +CC-22-37 (hex) SHANGHAI CARGOA M.&E.EQUIPMENT CO.LTD +400000-4FFFFF (base 16) SHANGHAI CARGOA M.&E.EQUIPMENT CO.LTD + 98 shunda road 9#,nanxiang town, Jianding district + Shanghai, 200182P.R. 200182 + CN + +CC-22-37 (hex) Hebei ZHSF Technology Co.,Ltd. +C00000-CFFFFF (base 16) Hebei ZHSF Technology Co.,Ltd. + 88 Xinshi South Road + Shijiazhuang, Hebei 050000 + CN + +CC-22-37 (hex) XConnect Professional Services +300000-3FFFFF (base 16) XConnect Professional Services + 459 Westlake Dr + Brisbane QLD 4074 + AU + +2C-27-9E (hex) AudioNord Distribution A/S +500000-5FFFFF (base 16) AudioNord Distribution A/S + Moelbakvej 4 + Lystrup 8520 + DK + +18-9B-A5 (hex) ChengDu Vantron Technology, Ltd. +100000-1FFFFF (base 16) ChengDu Vantron Technology, Ltd. + 6th Floor, 1st Building,No.9, 3rd WuKe East Street, WuHou District, + ChengDu SiChuan 610045 + CN + +90-4E-91 (hex) CUTTER Systems spol. s r.o. +900000-9FFFFF (base 16) CUTTER Systems spol. s r.o. + Milicova 2530/26 + Prostejov 79601 + CZ + +90-4E-91 (hex) mcf88 SRL +500000-5FFFFF (base 16) mcf88 SRL + Via Roma, 3 + Sozzago Novara 28060 + IT + +90-4E-91 (hex) IBM +700000-7FFFFF (base 16) IBM + 9000 south rita rd + Tucson AZ 85744 + US + +90-4E-91 (hex) North Pole Engineering, Inc. +200000-2FFFFF (base 16) North Pole Engineering, Inc. + 221 N. 1st. St., Suite 310 + Minneapolis MN 55401 + US + +50-FF-99 (hex) Informa LLC +E00000-EFFFFF (base 16) Informa LLC + 215 N. College Ave + Indianapolis IN 46202 + US + +90-4E-91 (hex) Nuwa Robotics (HK) Limited Taiwan Branch +600000-6FFFFF (base 16) Nuwa Robotics (HK) Limited Taiwan Branch + 9F., No.101, Sec. 3, Nanjing E. Rd., Zhongshan Dist. + Taipei 10487 + TW + +90-4E-91 (hex) Spirtech +000000-0FFFFF (base 16) Spirtech + 29 rue du Louvre + Paris 75002 + FR + +34-29-8F (hex) Shenzhen Advance River System Technology Co., Ltd +200000-2FFFFF (base 16) Shenzhen Advance River System Technology Co., Ltd + 6/F South Factory,2nd Jinxiang Building,Xinzhou South Road,Futian District, + Shenzhen Guangdong 518048 + CN + +34-00-8A (hex) ChengDu HuiZhong Cloud Information Technology Co., Ltd. +D00000-DFFFFF (base 16) ChengDu HuiZhong Cloud Information Technology Co., Ltd. + NO.1 CHENGJI ROAD ,CHENGHUA DISTRICT + CHENGDU CITY SICHUAN 610000 + CN + +28-F5-37 (hex) Shenzhen Modern Cowboy Technology Co.,Ltd. +700000-7FFFFF (base 16) Shenzhen Modern Cowboy Technology Co.,Ltd. + Room 1006,Beike building,Keyuan road,Yuehai streets,Nanshan District + Shenzhen Guangdong Province 518200 + CN + +28-F5-37 (hex) PRIMETECH ENGINEERING CORP. +300000-3FFFFF (base 16) PRIMETECH ENGINEERING CORP. + Koishikawadaikoku Bldg. 3F, 1-3-25 + Koishikawa, Bunkyo-ku Tokyo 112-0002 + JP + +34-00-8A (hex) Keruyun Technoligies(Beijing) Corporation Limited +900000-9FFFFF (base 16) Keruyun Technoligies(Beijing) Corporation Limited + Room 405, Taibang Technical Building, High-tech south 4 road, Nanshan + Shenzhen Guangdong 518000 + CN + +34-00-8A (hex) RPE Monitor +200000-2FFFFF (base 16) RPE Monitor + Krasnokursantskaya 104a + Rostov-on-Don Select 344068 + RU + +34-00-8A (hex) Shenzhen Eternal Idea Tech Co.,Ltd +C00000-CFFFFF (base 16) Shenzhen Eternal Idea Tech Co.,Ltd + 5/F, Building C, Chuangwei Technology Park,1st Rd,Shiyan tangtou,Baoan District, Shenzhen, Guang Dong Province,PRC + Shenzhen Guang Dong 518000 + CN + +34-00-8A (hex) Fotonic i Norden AB +400000-4FFFFF (base 16) Fotonic i Norden AB + Box 733 + Skelleftea SE 93127 + SE + +28-F5-37 (hex) Umojo +100000-1FFFFF (base 16) Umojo + 1 E. Superior St., Suite 402 + Chicago IL 60611 + US + +28-F5-37 (hex) Atomrock LLC +500000-5FFFFF (base 16) Atomrock LLC + 22525 SE 64th Place, Suite 2288 + Issaquah 98027 + US + +28-F5-37 (hex) Skyrockettoys LLC +D00000-DFFFFF (base 16) Skyrockettoys LLC + 12910 culver blvd Ste F + los angeles CA 90066 + US + +28-F5-37 (hex) Valeo Siemens eAutomotive Norway +000000-0FFFFF (base 16) Valeo Siemens eAutomotive Norway + Graaterudveien 41 + Drammen Buskerud 3036 + NO + +28-F5-37 (hex) LogiM GmbH Software und Entwicklung +B00000-BFFFFF (base 16) LogiM GmbH Software und Entwicklung + Mahonienweg 22b + Berlin 12437 + DE + +78-D8-00 (hex) Insignal Co., Ltd. +A00000-AFFFFF (base 16) Insignal Co., Ltd. + #301, Ace High-end Tower 1st, 5 Digital-ro 26-gil + Seoul ASI KR KS013 SEOUL + KR + +7C-BA-CC (hex) Sun Asia Trade Co. +400000-4FFFFF (base 16) Sun Asia Trade Co. + RM 1005 10/F, HOKING COMMERCIAL CENTRE,2-16 FA YUEN STREET MONGKOk + Hong Kong Hong Kong 9998800 + HK + +7C-BA-CC (hex) Changsha SUNYE Electric Co., Ltd. +100000-1FFFFF (base 16) Changsha SUNYE Electric Co., Ltd. + hi tech Zone, Sheng Xin Road, No. 669 + Changsha Hunan 410000 + CN + +78-D8-00 (hex) CS Instruments GmbH +400000-4FFFFF (base 16) CS Instruments GmbH + Zindelsteiner Straße 15 + VS-Tannheim 78052 + DE + +AC-64-DD (hex) HMicro Inc +D00000-DFFFFF (base 16) HMicro Inc + 39355 California St., Suite 303 + Fremont null 94538 + US + +4C-65-A8 (hex) Suzhou Embedded Electronic Technology Co., Ltd. +A00000-AFFFFF (base 16) Suzhou Embedded Electronic Technology Co., Ltd. + Room 15A05, KeJi GuangChang,QianJinDong Road + Kunshan Jiangsu 215300 + CN + +F8-8A-3C (hex) Shenzhen Shengyuan Tech Ltd. +300000-3FFFFF (base 16) Shenzhen Shengyuan Tech Ltd. + Science and Technology Park North District, high tech North six Road, LAN LAN Technology Park, building C-309,Shenzhen Nanshan District, Guangdong Province, China + shenzhen guangdong 518000 + CN + +4C-65-A8 (hex) Roost +300000-3FFFFF (base 16) Roost + 955, Benecia Ave + Sunnyvale CA 94085 + US + +F8-8A-3C (hex) KLATU Networks Inc +200000-2FFFFF (base 16) KLATU Networks Inc + 4174 NE Lookout Lane + Poulsbo WA 98370 + US + +A0-C5-F2 (hex) Synapsys Solutions Ltd. +E00000-EFFFFF (base 16) Synapsys Solutions Ltd. + 1 Woodlands Court, Albert Drive + Burgess Hill West Sussex RH15 9TN + GB + +A0-C5-F2 (hex) KNS Group LLC (YADRO Company) +100000-1FFFFF (base 16) KNS Group LLC (YADRO Company) + Spartakovskaya sq., 14, bl. 1 + Moscow 105082 + RU + +A0-C5-F2 (hex) Speedgoat GmbH +200000-2FFFFF (base 16) Speedgoat GmbH + Waldeggstrasse 30 + Liebefeld BE 3097 + CH + +A0-C5-F2 (hex) Viettronimex JSC +700000-7FFFFF (base 16) Viettronimex JSC + 74-76 Nguyen Hue street, Ben nghe ward, distric 1 + Ho Chi Minh 70000 + VN + +04-71-4B (hex) Neurio Technology Inc. +000000-0FFFFF (base 16) Neurio Technology Inc. + 43 West Hastings Street + Vancouver BC V6B 1G4 + CA + +04-71-4B (hex) Lighthouse AI, Inc +900000-9FFFFF (base 16) Lighthouse AI, Inc + 380 Portage Ave + Palo Alto CA 94306 + US + +F0-23-B9 (hex) Emu Technology +900000-9FFFFF (base 16) Emu Technology + 1400 E. Angela Blvd. #101 + South Bend IN 46617 + US + +F0-23-B9 (hex) Audeara Pty. Ltd. +500000-5FFFFF (base 16) Audeara Pty. Ltd. + 375 Wickham Terrace + Brisbane Queensland 4000 + AU + +60-D7-E3 (hex) Elap s.r.l. +100000-1FFFFF (base 16) Elap s.r.l. + Via V. Veneto 4 + Corsico Milano 20094 + IT + +04-71-4B (hex) DIGIBEST TECHNOLOGY CO., LTD. +B00000-BFFFFF (base 16) DIGIBEST TECHNOLOGY CO., LTD. + 4F ,No.65 , SHITAN ROAD , NEIHU DIST. + TAIPEI 114 + TW + +04-71-4B (hex) KittyHawk Corporation +C00000-CFFFFF (base 16) KittyHawk Corporation + 2700 Broderick Way + Mountain View CA 94043 + US + +1C-C0-E1 (hex) SHENZHEN KINSTONE D&T DEVELOP CO.,LTD +700000-7FFFFF (base 16) SHENZHEN KINSTONE D&T DEVELOP CO.,LTD + 5F, A2 Building ,XinJianXing Tech Industrial Park,Fengxin Road ,Lou Cun , Gongming Street,Guangming New Dist., + Shenzhen Guangdong 518000 + CN + +08-ED-02 (hex) Eleven Engineering Incorporated +700000-7FFFFF (base 16) Eleven Engineering Incorporated + 10150 - 100 Street, Suite 800 + Edmonton Canada, Alberta T5J 0P6 + CA + +08-ED-02 (hex) TES Touch Embedded Solutions Inc. +200000-2FFFFF (base 16) TES Touch Embedded Solutions Inc. + 3F, No. 141, Sec. 3, Ren'ai Rd., + Taipei 106 + TW + +98-AA-FC (hex) Resonant Systems Inc. +B00000-BFFFFF (base 16) Resonant Systems Inc. + Tsurumi chiyoda building,4-34-26,Tsurumi-tyuou,Tsurumi + Yokohama-shi kanagawa-ken 230-0051 + JP + +98-AA-FC (hex) Shenzhen UniStrong Science & Technology Co., Ltd +200000-2FFFFF (base 16) Shenzhen UniStrong Science & Technology Co., Ltd + B,4-4Factory,Zhengcheng Road, Fuyong Baoan District, + Shenzhen 518103 + CN + +98-AA-FC (hex) SENKO Co.,Ltd. +A00000-AFFFFF (base 16) SENKO Co.,Ltd. + 73 Oesammiro15beon-gil + Osan-si Gyeonggi-do 18111 + KR + +08-ED-02 (hex) HANTAS CO., LTD. +800000-8FFFFF (base 16) HANTAS CO., LTD. + 474 Dunchondaero, Jungwon-gu + Seongnam-si Kyonggi-do 13229 + KR + +14-4F-D7 (hex) Red Technology Limited +400000-4FFFFF (base 16) Red Technology Limited + Room 702, 7/F., Fu Fai Commercial Centre, 27 Hillier Street, Sheung Wan + Hong Kong 999077 + HK + +14-4F-D7 (hex) Qingdao Wodatong Electronics Co., Ltd. +300000-3FFFFF (base 16) Qingdao Wodatong Electronics Co., Ltd. + West of Committees, HouHaiXi Community, JiHongTan Street, Chengyang District, + Qingdao Shandong 266111 + CN + +14-4F-D7 (hex) Unirobot Corporation +A00000-AFFFFF (base 16) Unirobot Corporation + MK Hatagaya Sasazuka building 6F, Hatagaya, Shibuya-ku + Tokyo Japan 1510072 + JP + +A4-11-63 (hex) Beijing XiaoRui Technology Co., Ltd +600000-6FFFFF (base 16) Beijing XiaoRui Technology Co., Ltd + Room 1201, Zhongqing Building, East Third Ring Road, Chaoyang District, Beijing + Beijing Beijing 100029 + CN + +1C-A0-D3 (hex) NovTech, Inc. +200000-2FFFFF (base 16) NovTech, Inc. + 7401 Wiles Road, Suite 229 + Coral Springs FL 33067 + US + +40-F3-85 (hex) URMET Home & Building Solutions Pty Ltd +B00000-BFFFFF (base 16) URMET Home & Building Solutions Pty Ltd + 36 Ricketty Street + Mascot NSW 2020 + AU + +40-F3-85 (hex) Johnson Matthey +100000-1FFFFF (base 16) Johnson Matthey + MTC, The Moat + Billingham Cleveland TS23 4ED + GB + +8C-C8-F4 (hex) Beijing KXWELL Technology CO., LTD +500000-5FFFFF (base 16) Beijing KXWELL Technology CO., LTD + Room 12A05, North Real Estate Building, Block 3 + 81 Zizhuyuan Road, Haidian District Beijing 100089 + CN + +40-F3-85 (hex) Clixxo Broadband Private Limited +C00000-CFFFFF (base 16) Clixxo Broadband Private Limited + Suite # 10, 3rd Floor, Tower 2, Stellar IT Park, C-25, Sector 62 + Noida Uttar Pradesh 201301 + IN + +50-A4-D0 (hex) Beijing YangLian Networks Technology co., LTD +C00000-CFFFFF (base 16) Beijing YangLian Networks Technology co., LTD + Building 17, East Zone, No.10 Xibeiwang Dong Rd, Haidian District, Beijing, PRC + BeiJing 100193 + CN + +8C-C8-F4 (hex) Beijing Xinxunxintong Eletronics Co.,Ltd +D00000-DFFFFF (base 16) Beijing Xinxunxintong Eletronics Co.,Ltd + No.9 Yingfu Road,Haidian District + Beijing 100192 + CN + +8C-C8-F4 (hex) PTYPE Co., LTD. +B00000-BFFFFF (base 16) PTYPE Co., LTD. + B121, B-dong, Keumkang Penterium IT Tower, 810, Gwanyand 2-dong, Dongan-gu + Anyang-si Gyeonggi-do 14056 + KR + +50-A4-D0 (hex) Guangzhou Hysoon Electronic Co., Ltd. +300000-3FFFFF (base 16) Guangzhou Hysoon Electronic Co., Ltd. + No.1, Fenghuang South Road, Xinhua, Huadu District + Guangzhou Guangdong 510800 + CN + +34-04-9E (hex) Harbin Yantuo Science and Technology Development Co., Ltd +400000-4FFFFF (base 16) Harbin Yantuo Science and Technology Development Co., Ltd + No. 15 Xingnan Road, Nangang District + Harbin Heilongjiang Province 150000 + CN + +40-ED-98 (hex) Hangzhou GANX Technology Co.,Ltd. +D00000-DFFFFF (base 16) Hangzhou GANX Technology Co.,Ltd. + Room 502, Building 2, No 1180, BinAn Rd, Binjiang District + Hangzhou Zhejiang 310000 + CN + +40-ED-98 (hex) TeraTron GmbH +900000-9FFFFF (base 16) TeraTron GmbH + Bunsenstr. 10 + Gummersbach DE 51647 + DE + +40-ED-98 (hex) BORDA TECHNOLOGY +E00000-EFFFFF (base 16) BORDA TECHNOLOGY + ITU ARI TEKNOKENT ARI 3 NO 504 + ISTANBUL 34369 + TR + +50-0B-91 (hex) EWIN TECHNOLOGY LIMITED +300000-3FFFFF (base 16) EWIN TECHNOLOGY LIMITED + 3rd floor, No. 12, LIYE Road, 2nd industrial District, South Zone, + Zhongshan Guangdong 528400 + CN + +50-0B-91 (hex) Security Alarms & Co. S.A. +600000-6FFFFF (base 16) Security Alarms & Co. S.A. + Z.I. Tresi 6D + Preverenges 1028 + CH + +A4-58-0F (hex) Changsha Tai Hui Network Technology Co.,Ltd +700000-7FFFFF (base 16) Changsha Tai Hui Network Technology Co.,Ltd + 102-202 Building A2,Luguyu Garden,No.27 Wenxuan Rd,Gaoxin District,Changsha + changsha hunan 410205 + CN + +A4-58-0F (hex) ABB AB PGHV +B00000-BFFFFF (base 16) ABB AB PGHV + Lyviksvägen 4 + Ludvika 77180 + SE + +A4-58-0F (hex) Engineered SA +300000-3FFFFF (base 16) Engineered SA + Avenue des Sports 28 + Yverdon-les-Bains VD 1400 + CH + +7C-CB-E2 (hex) optilink networks pvt ltd +D00000-DFFFFF (base 16) optilink networks pvt ltd + 501/502, sanjona complex, hemu kalani marg, chembur + mumbai maharashtra 400071 + IN + +7C-CB-E2 (hex) Ningbo bird sales co.,LTD +400000-4FFFFF (base 16) Ningbo bird sales co.,LTD + NO.999 Dacheng East Road + Fenghua City Zhejiang Province 315559 + CN + +48-65-EE (hex) CNU +E00000-EFFFFF (base 16) CNU + No.8 Everygreen Road, Haidian District 3 layer 313 + Beijing 100195 + CN + +48-65-EE (hex) Swistec Systems AG +500000-5FFFFF (base 16) Swistec Systems AG + Allmendstrasse 30 + Fehraltorf ZH 8320 + CH + +10-07-23 (hex) Shenzhen Xinfa Electronic Co.,ltd +C00000-CFFFFF (base 16) Shenzhen Xinfa Electronic Co.,ltd + NO.57., Baoli Rd.,Buji Town.,Longgang District.,Shenzhen city.,guangdong province.,China + shenzhen guangdong 518112 + CN + +24-4E-7B (hex) sonoscape +100000-1FFFFF (base 16) sonoscape + yuquan road + shenzhen guangdong 518052 + CN + +24-4E-7B (hex) Mighty Audio, Inc. +B00000-BFFFFF (base 16) Mighty Audio, Inc. + 707 Coeur d'Alene Ave + Venice CA 90291 + US + +24-4E-7B (hex) Shenzhen Ruixunyun Technology Co.,Ltd. +300000-3FFFFF (base 16) Shenzhen Ruixunyun Technology Co.,Ltd. + Rm 311, 2Bldg.,Xunmei Technology Plaza, Keyuan Avenue, Nanshan District + Shenzhen Guangdong 518057 + CN + +24-4E-7B (hex) CHUNGHSIN TECHNOLOGY GROUP CO.,LTD +C00000-CFFFFF (base 16) CHUNGHSIN TECHNOLOGY GROUP CO.,LTD + 618-2#GONGREN WEST ROAD,JIAOJIANG AREA + TAIZHOU ZHEJIANG 318000 + CN + +1C-C0-E1 (hex) Abbott Medical Optics Inc. +200000-2FFFFF (base 16) Abbott Medical Optics Inc. + 510 Cottonwood Drive + Milpitas CA 95035 + US + +1C-C0-E1 (hex) Monument Labs, Inc. +600000-6FFFFF (base 16) Monument Labs, Inc. + 222 W. Merchandise Mart Plaza Ste 1212 + Chicago IL 60654 + US + +4C-E1-73 (hex) KTC(K-TEL) +D00000-DFFFFF (base 16) KTC(K-TEL) + 98, Sandan-ro 132beon-gil + Uijeongbu-si Gyeonggi-do 11781 + KR + +AC-64-DD (hex) Beijing Hamigua Technology Co., Ltd. +C00000-CFFFFF (base 16) Beijing Hamigua Technology Co., Ltd. + Building C 02B-322, No.28A, Information Road, Haidian District + BEIJING BEIJING 100000 + CN + +4C-E1-73 (hex) Beijing Sutongwang E-Business Co., Ltd +000000-0FFFFF (base 16) Beijing Sutongwang E-Business Co., Ltd + Room 1108, Qingyun modern building. NO.43 Bei San Huan Xi Road + Beijing Beijing 100086 + CN + +38-3A-21 (hex) Mission Embedded GmbH +C00000-CFFFFF (base 16) Mission Embedded GmbH + Gutheil-Schoder-Gasse 8-12 + Wien Wien 1100 + AT + +F8-1D-78 (hex) DACONS +500000-5FFFFF (base 16) DACONS + 90, Centum jungang-ro, Haeundae-gu + Busan 48059 + KR + +38-3A-21 (hex) Shanghai Greatwall Safety System Co.,Ltd +300000-3FFFFF (base 16) Shanghai Greatwall Safety System Co.,Ltd + 502B - Bloc ,No.168 Luoyang Str + ShangHai 201100 + CN + +F8-1D-78 (hex) Ophrys Systèmes +900000-9FFFFF (base 16) Ophrys Systèmes + 6 rue Valérien Perrin + Seyssinet 38170 + FR + +70-F8-E7 (hex) Dr. Simon Consulting GmbH +300000-3FFFFF (base 16) Dr. Simon Consulting GmbH + Friedrichstr. 35 + Göppingen 73033 + DE + +F8-1D-78 (hex) Xperio Labs Limited +200000-2FFFFF (base 16) Xperio Labs Limited + Unit 3709, 37th Floor, Tower II, Lippo Centre, 89 Queensway, Admiralty, + Hong Kong Hong Kong Hong Kong + HK + +70-F8-E7 (hex) TiVACI CORPORATION PTE LTD +A00000-AFFFFF (base 16) TiVACI CORPORATION PTE LTD + 264A Tanjong Katong Road + Singapore 437051 + SG + +84-E0-F4 (hex) AIMTRON CORPORATION +C00000-CFFFFF (base 16) AIMTRON CORPORATION + 555 S VERMONT ST + PALATINE IL 60067 + US + +84-E0-F4 (hex) ASL Intercom B.V. +300000-3FFFFF (base 16) ASL Intercom B.V. + Zonnebaan 42 + Utrecht 3542EG + NL + +84-E0-F4 (hex) Orchard Electronics Co., Ltd. +B00000-BFFFFF (base 16) Orchard Electronics Co., Ltd. + 8F,No.2,Lane 235,Bao-Chiao Rd., Hsin-Tien District, + New Taipei City 23145 + TW + +C0-D3-91 (hex) SAMSARA NETWORKS INC +E00000-EFFFFF (base 16) SAMSARA NETWORKS INC + 525 York St + San Francisco CA 94110 + US + +C0-D3-91 (hex) Alpha Audiotronics, Inc. +A00000-AFFFFF (base 16) Alpha Audiotronics, Inc. + 401 Park Avenue South, Fl. 10 + New York NY 10016 + US + +C0-D3-91 (hex) Zhinengguo technology company limited +C00000-CFFFFF (base 16) Zhinengguo technology company limited + Taiyueshangwu building, Luozhuang East road, Haidian District + beijing beijing 100088 + CN + +84-E0-F4 (hex) ShenZhen Panrich Technology Limited +000000-0FFFFF (base 16) ShenZhen Panrich Technology Limited + room 1321 qinghai building,beihuan rd,futian district + shenzhen 518034 + CN + +58-E8-76 (hex) TEM Mobile Limited +900000-9FFFFF (base 16) TEM Mobile Limited + RM1703, North Block, Cangsong Building, Tairan 6 road, Futian District, Shenzhen. + Shenzhen Guangdong 518000 + CN + +C0-D3-91 (hex) WiTagg, Inc +500000-5FFFFF (base 16) WiTagg, Inc + 1045 Linda Vista Avenue + Mountain View 94043 + US + +F0-AC-D7 (hex) Smart Power Technology Co., Ltd. +D00000-DFFFFF (base 16) Smart Power Technology Co., Ltd. + Room 102,Unit A,Building 32,No.999,Gaoxinqi Road, High Tech Industrial Development Zone,Nanchang,Jiangxi + Nanchang City Jiangxi Province 330096 + CN + +58-E8-76 (hex) PROBIT SRL +400000-4FFFFF (base 16) PROBIT SRL + Pantelimon, 1 + Bucharest 021591 + RO + +F0-AC-D7 (hex) Groupeer Technologies +A00000-AFFFFF (base 16) Groupeer Technologies + 17 avenue Georges 5 + Paris Ile-de-France 75008 + FR + +28-36-38 (hex) Shenzhen Zhi Hua Creative Technology Co., Ltd. +900000-9FFFFF (base 16) Shenzhen Zhi Hua Creative Technology Co., Ltd. + Bao`an District, Shenzhen Baoan District Xixiang Bao yuan road beach village in the 8-905 room + Shenzhen 518000 + CN + +5C-F2-86 (hex) Hangzhou Signwei Electronics Technology Co., Ltd +000000-0FFFFF (base 16) Hangzhou Signwei Electronics Technology Co., Ltd + 408 Room, 7 Cuibai Road,xihu District + Hangzhou Zhejiang 310012 + CN + +28-36-38 (hex) Panasonic System Solutions Europe +100000-1FFFFF (base 16) Panasonic System Solutions Europe + Panasonic Marketing Europe GmbH, Hagenauer Str. 43 + Wiesbaden 65203 + DE + +8C-19-2D (hex) ELCO(TIANJIN)ELECTRONICS CO.,LTD. +500000-5FFFFF (base 16) ELCO(TIANJIN)ELECTRONICS CO.,LTD. + NO. 12 4th XEDA Branch Road,XiQing Economic Development Area + Tianjin 300385 + CN + +D0-D9-4F (hex) Teco Image Systems Co., Ltd. +200000-2FFFFF (base 16) Teco Image Systems Co., Ltd. + 2F., No. 1568-1, Chung Shan Road, Sec. 1, Kuang-In + Taoyuan 328 + TW + +D0-D9-4F (hex) Hyundai Autohow +600000-6FFFFF (base 16) Hyundai Autohow + Starwith 0914, Heungandaero427-38 + Anyang Gyunggi 14059 + KR + +D0-D9-4F (hex) Hangzhou xiaoben technology co.,Ltd +900000-9FFFFF (base 16) Hangzhou xiaoben technology co.,Ltd + Room 401,Building 5,No.503,Xingguo Road,Qianjiang Economic Development Area + Hangzhou Zhejiang 311106 + CN + +D0-D9-4F (hex) mycable GmbH +100000-1FFFFF (base 16) mycable GmbH + Gartenstrasse 10 + Neumuenster Schleswig Holstein 24534 + DE + +D0-D9-4F (hex) MAX Smart Home, LLC +B00000-BFFFFF (base 16) MAX Smart Home, LLC + 3830 Valley Centre Dr, STE 705-852 + San Diego CA 92130 + US + +CC-D3-1E (hex) KEN A/S +300000-3FFFFF (base 16) KEN A/S + Bøgebjergvej 60 + Brobyværk Denmark 5672 + DK + +CC-D3-1E (hex) Neptune Systems +200000-2FFFFF (base 16) Neptune Systems + 15750 Vineyard Blvd Suite 150 + MORGAN HILL CA 95037 + US + +CC-D3-1E (hex) SAMIM Co +000000-0FFFFF (base 16) SAMIM Co + No. 47/19, Iranshahr St., Tehran, Iran + Tehran Tehran 1581633939 + IR + +CC-D3-1E (hex) Rondo Burgdorf AG +100000-1FFFFF (base 16) Rondo Burgdorf AG + Heimiswilstrasse 42 + Burgdorf 3400 + CH + +C4-7C-8D (hex) ATI +000000-0FFFFF (base 16) ATI + 30 Jeffries Street + Boston MA 02128 + US + +68-91-D0 (hex) femrice +600000-6FFFFF (base 16) femrice + Rm408,Tower B,Jiahu Building,Shangdi 3rd Street,Haidian,Beijing,China + Beijing 100085 + CN + +C4-7C-8D (hex) Labor Strauss Sicherungsanlagenbau GmbH +E00000-EFFFFF (base 16) Labor Strauss Sicherungsanlagenbau GmbH + Wiegelestraße 36 + Vienna 1230 + AT + +C4-7C-8D (hex) LYNX INNOVATION LITIMED +100000-1FFFFF (base 16) LYNX INNOVATION LITIMED + Unit 8A,331 Rosedale Road Albany,North Shore City 0632 Auckland,New Zealand + Auckland 0632 + NZ + +68-91-D0 (hex) Central Railway Manufacturing +000000-0FFFFF (base 16) Central Railway Manufacturing + 8933 Western Way Suite 8 + Jacksonville FL 32256 + US + +68-91-D0 (hex) Shenzhen NeaTech Intelligence Technology Co., Ltd. +200000-2FFFFF (base 16) Shenzhen NeaTech Intelligence Technology Co., Ltd. + C.8F, Bofook Lilang Industry Park, Bulan Road, Nanwan Street, Longgang + Shenzhen Guangdong 518112 + CN + +E0-B6-F5 (hex) Shenzhen Xrinda Technology Ltd +700000-7FFFFF (base 16) Shenzhen Xrinda Technology Ltd + Fl#15, Tianming Technology Building, Wushitou Road No.8, North high-tech park, Nanshan District, Shenzhen,P.R.China + Shenzhen Guangdong 518052 + CN + +E0-B6-F5 (hex) BeSTAR Corporation +000000-0FFFFF (base 16) BeSTAR Corporation + 8th F/L, UNIQUEST B/D, 314, Hwangsaeul-ro, Bundang-gu + Seongnam-si Gyeonggi-do 13591 + KR + +50-FF-99 (hex) Sea Eagle Optoelectronic Information Technology(Tianjin)co,Ltd +900000-9FFFFF (base 16) Sea Eagle Optoelectronic Information Technology(Tianjin)co,Ltd + Nankai District + Tianjin Tianjin 300000 + CN + +98-6D-35 (hex) DH Mechatronic AG +300000-3FFFFF (base 16) DH Mechatronic AG + Georg-Sasse-Straße 28-32 + Ammersbek Schleswig-Holstein 22949 + DE + +50-FF-99 (hex) Simicon +000000-0FFFFF (base 16) Simicon + Mendeleevskay str. 8 + Saint-Petersburg 194044 + RU + +50-FF-99 (hex) LEGEND WINNER LIMITED +600000-6FFFFF (base 16) LEGEND WINNER LIMITED + FLAT/RM 18-19 13/F HOLLYWOOD PLAZA 610 NATHAN ROAD MONGKOK + HONG kONG 00852 + HK + +98-6D-35 (hex) Shenzhen MALATA Mobile Communication Co.,LTD +000000-0FFFFF (base 16) Shenzhen MALATA Mobile Communication Co.,LTD + 25F, Malata Technology Building, No. 9998 Shennan Avenue, Hi-techPark, Nanshan District + Shenzhen GUANGDONG 518057 + CN + +7C-47-7C (hex) Dspread Technology (Beijing) Inc. +A00000-AFFFFF (base 16) Dspread Technology (Beijing) Inc. + Jingxin Building, 2045 Suite , Chaoyang District + Beijing 100027 + CN + +7C-47-7C (hex) BlueSmart Technology Corporation +700000-7FFFFF (base 16) BlueSmart Technology Corporation + 1451 Grant Road, Suite 200 + Mountain View CA 94042 + US + +7C-47-7C (hex) Speedifi Inc +D00000-DFFFFF (base 16) Speedifi Inc + 1163 Kassel Terrace + Sunnyvale CA 94089 + + +5C-F2-86 (hex) CHIPSEN Co.,Ltd. +400000-4FFFFF (base 16) CHIPSEN Co.,Ltd. + Haan-ro 60 + Gwang-myeong Gyeonggi-do 14322 + KR + +5C-F2-86 (hex) iSon Tech +100000-1FFFFF (base 16) iSon Tech + Rm. 3, 2F., No.417, Guangfu S. Rd., Sinyi Dist. + Taipei Taiwan 110 + TW + +38-FD-FE (hex) Inspero Inc +600000-6FFFFF (base 16) Inspero Inc + C101, Ju'Er Hu Tong, Dong Cheng Qu + Beijing Beijing 100001 + CN + +38-FD-FE (hex) FUBA Automotive Electronics GmbH +D00000-DFFFFF (base 16) FUBA Automotive Electronics GmbH + Tec Center 1 + Bad Salzdetfurth 31162 + DE + +38-B8-EB (hex) 1.A Connect GmbH +100000-1FFFFF (base 16) 1.A Connect GmbH + Obere Seestrasse 13 + Nohfelden Saarland 66625 + DE + +78-CA-83 (hex) Konecranes +E00000-EFFFFF (base 16) Konecranes + Koneenkatu 8 + Hyvinkää 05801 + FI + +38-B8-EB (hex) Aina Wireless Inc +300000-3FFFFF (base 16) Aina Wireless Inc + Hub Salo, Tehdaskatu 6 + Salo 24100 + FI + +78-CA-83 (hex) Huatune Technology (Shanghai) Co., Ltd. +500000-5FFFFF (base 16) Huatune Technology (Shanghai) Co., Ltd. + No.8 Longxi RD + Shanghai Changning District 200336 + CN + +1C-88-79 (hex) Sensys Networks, Inc. +700000-7FFFFF (base 16) Sensys Networks, Inc. + 1608 4th St. Suite 200 + Berkeley CA 94710 + US + +1C-87-74 (hex) Schawbel Technologies LLC +600000-6FFFFF (base 16) Schawbel Technologies LLC + 24 New England Executive Park, Suite 150 + Burlington MA 01803 + US + +1C-87-74 (hex) HABEY USA Inc. +B00000-BFFFFF (base 16) HABEY USA Inc. + Room 205,Block A, Hua Feng Business Building ,Qian Jin 1st Road, Baoan 25 Area, Shenzhen 518101, China. + Shenzhen Guang Dong 518101 + CN + +1C-88-79 (hex) Shenzhen Xiaoxi Technology Co., Ltd. +300000-3FFFFF (base 16) Shenzhen Xiaoxi Technology Co., Ltd. + 2F, Wing D, Building 5, Software Industry Base, No.14, Haitian 2nd Road, Nanshan District + Shenzhen Guangdong 518000 + CN + +1C-88-79 (hex) SHENZHENFREELINK ELECTRONIC CO.,LTD +500000-5FFFFF (base 16) SHENZHENFREELINK ELECTRONIC CO.,LTD + 3/F,Building A,Quanyongyuan industrial park,Langkou industrial area,Dalang,Bao'an District,Shenzhen,China + Shenzhen 518000 + CN + +1C-87-76 (hex) Strone Technology +C00000-CFFFFF (base 16) Strone Technology + 13 Ellis Street + South Yarra Victoria 3141 + AU + +1C-87-76 (hex) Jiangsu ETERN COMMUNICATION Co.,ltd +A00000-AFFFFF (base 16) Jiangsu ETERN COMMUNICATION Co.,ltd + 888 YUEXIU ROAD, LILI TOWN, WUJIANG DISTRICT, + Suzhou Jiangsu 215211 + CN + +1C-87-76 (hex) Zhuhai MYZR Technology Co.,Ltd +500000-5FFFFF (base 16) Zhuhai MYZR Technology Co.,Ltd + Room 302,Area D2,National Hi-tech Zone,NO.1,Software Park Road + Zhuhai 519085 + CN + +1C-88-79 (hex) Xingtera China Ltd +900000-9FFFFF (base 16) Xingtera China Ltd + 88 Chenhui Rd Bldg 1 Ste 303 + Shanghai 201203 + CN + +1C-87-79 (hex) Novetta +400000-4FFFFF (base 16) Novetta + 7921 Jones Branch Drive + McLean VA 22102 + US + +84-39-BE (hex) Neat S.r.l. +500000-5FFFFF (base 16) Neat S.r.l. + via Edoardo D'Onofrio 304 + Rome ITALY 00155 + IT + +84-39-BE (hex) Shenzhen Ramos Digital Technology Co,.Ltd. +400000-4FFFFF (base 16) Shenzhen Ramos Digital Technology Co,.Ltd. + 3F,Noth Block B, No.2 Kingdee Software Park, Keji South 12th Road, High-Tech Industrial Park, Nanshan District,Shenzhen 518057 + Shenzhen Guangdong 518000 + CN + +40-A3-6B (hex) National Research Council of Canada +500000-5FFFFF (base 16) National Research Council of Canada + 717 White Lake Road + Kaleden British Columbia V0H1K0 + CA + +40-A3-6B (hex) Embrionix Design Inc. +A00000-AFFFFF (base 16) Embrionix Design Inc. + 2120 Monterey, suite 200 + Laval Québec H7L3S3 + CA + +70-88-6B (hex) Chengdu Ophylink Communication Technology Ltd. +500000-5FFFFF (base 16) Chengdu Ophylink Communication Technology Ltd. + 3F,Bldg3,No.333,Yunhua Road,Hig-tech Zone + Chengdu Sichuan 610041 + CN + +70-88-6B (hex) CVnet +200000-2FFFFF (base 16) CVnet + 111, Maeyeong-ro 345beon-gil, Yeongtong-gu + Suwon-si Gyeonggi-do 16703 + KR + +CC-1B-E0 (hex) Guangzhou Southelectric Power Science Technology Development Co.,Ltd. +C00000-CFFFFF (base 16) Guangzhou Southelectric Power Science Technology Development Co.,Ltd. + No.1, zhongsuihua south street, Jiangnan BLVD, + Guangzhou Guangdong 510310 + CN + +A0-3E-6B (hex) Jining SmartCity Infotech Co.Ltd. +D00000-DFFFFF (base 16) Jining SmartCity Infotech Co.Ltd. + Technology Center,Renchen District, + Jining Shandong 272000 + CN + +00-55-DA (hex) KoolPOS Inc. +100000-1FFFFF (base 16) KoolPOS Inc. + 5th Floor, B Section, Virgo Building, + Wuxi Jiangsu 214135 + CN + +CC-1B-E0 (hex) Laserworld (Switzerland) AG +400000-4FFFFF (base 16) Laserworld (Switzerland) AG + Kreuzlingerstrasse 5 + Lengwil TG 8574 + CH + +00-55-DA (hex) Datapath Limited +400000-4FFFFF (base 16) Datapath Limited + Bemrose House, + Derby Derbyshire DE21 6XQ + GB + +00-55-DA (hex) BroadSoft, Inc. +800000-8FFFFF (base 16) BroadSoft, Inc. + 550 S. Winchester Blvd. Suite 250 + San Jose California 95128 + US + +00-55-DA (hex) Nanoleaf +500000-5FFFFF (base 16) Nanoleaf + 162 John Street + Toronto Ontario M5V2E5 + CA + +00-55-DA (hex) Speechlab +A00000-AFFFFF (base 16) Speechlab + Gaasterlandstraat 3 + Amsterdam NH 1079RH + NL + +C8-8E-D1 (hex) Advanced Micro Controls Inc. +B00000-BFFFFF (base 16) Advanced Micro Controls Inc. + 20 Gear Dr. + Terryville CT 06786 + US + +C8-8E-D1 (hex) Electronic Controls Design, Inc. +800000-8FFFFF (base 16) Electronic Controls Design, Inc. + 4287-B SE International Way + Milwaukie OR 97222 + US + +C8-8E-D1 (hex) Focalcrest, Ltd. +900000-9FFFFF (base 16) Focalcrest, Ltd. + Shenzhen City, Futian District Tairan nine road Haisong building B, room 1101 + shenzhen 广东 518040 + CN + +A0-3E-6B (hex) Shenzhen Neostra Technology Co.Ltd +A00000-AFFFFF (base 16) Shenzhen Neostra Technology Co.Ltd + 7th Building,Huaide Cuihai Industrial Park,Fuyong, + Shenzhen Guangdong 518000 + CN + +B0-C5-CA (hex) SunTech Medical, Inc. +600000-6FFFFF (base 16) SunTech Medical, Inc. + 507 Airport Blvd. + Morrisville NC 27560 + US + +DC-44-27 (hex) Skywave Technology Co,.Ltd. +200000-2FFFFF (base 16) Skywave Technology Co,.Ltd. + Beijing Chaoyang District, River Park 22-4-902 + Beijing Chaoyang 100107 + CN + +DC-44-27 (hex) EK-TEAM Elektronik- u. Kunststoff-Technik GmbH +600000-6FFFFF (base 16) EK-TEAM Elektronik- u. Kunststoff-Technik GmbH + Schnackenburgallee 43 + Hamburg Hamburg 22525 + DE + +DC-44-27 (hex) EcoGuard AB +700000-7FFFFF (base 16) EcoGuard AB + Radiatorvägen 11 + ÖREBRO - 70227 + SE + +B0-C5-CA (hex) shanghai University Ding-Tech software Corp.,ltd +400000-4FFFFF (base 16) shanghai University Ding-Tech software Corp.,ltd + No.9 Lane3,CaoDong Feeder Rd, Xuhui Area,shanghai,China + shanghai shanghai 200235 + CN + +78-C2-C0 (hex) Shanghai Hanyi Technologies Co,.Ltd. +C00000-CFFFFF (base 16) Shanghai Hanyi Technologies Co,.Ltd. + Room 2008, Feidiao International Building + Shanghai Shanghai 200030 + CN + +B4-37-D1 (hex) NANJING PUTIAN TELECOMMUNICATIONS TECHNOLOGY CO.,LTD. +C00000-CFFFFF (base 16) NANJING PUTIAN TELECOMMUNICATIONS TECHNOLOGY CO.,LTD. + No.1 Putian Road,Yuhuamenwai,Nanjing + Nan Jing Jiang Su 210022 + CN + +B4-37-D1 (hex) Nanjing yuekong Intelligent Technology +900000-9FFFFF (base 16) Nanjing yuekong Intelligent Technology + Room 923, No.2 Building, Deying International Square, No.222, Changhon + Nanjing Jiangsu 210012 + CN + +78-C2-C0 (hex) Ningbo Sanxing Electric Co., Ltd. +300000-3FFFFF (base 16) Ningbo Sanxing Electric Co., Ltd. + Fengwan No. 17, Cicheng Town, + Ningbo Zhejiang 315033 + CN + +78-C2-C0 (hex) RONIX incorporated +200000-2FFFFF (base 16) RONIX incorporated + 904, 648, Seobusaet-gil, + SEOUL GEUMCHEON-GU 153-803 + KR + +74-F8-DB (hex) TBM CO., LTD. +C00000-CFFFFF (base 16) TBM CO., LTD. + A-806, 282 Hakeui-Ro + Anyang-City Gyeonggi-Do 431-810 + KR + +74-F8-DB (hex) Bernard Krone Holding GmbH & Co. KG +E00000-EFFFFF (base 16) Bernard Krone Holding GmbH & Co. KG + Heinrich-Krone-Str. 10 + Spelle Niedersachsen 48480 + DE + +B4-37-D1 (hex) Stratom, Inc. +500000-5FFFFF (base 16) Stratom, Inc. + 5375 Western Avenue Suite A + Boulder Colorado 80301 + US + +B4-37-D1 (hex) KOMSIS ELEKTRONIK SISTEMLERI SAN. TIC. LTD.STI +400000-4FFFFF (base 16) KOMSIS ELEKTRONIK SISTEMLERI SAN. TIC. LTD.STI + SERIF ALI MAH. TURKER CAD. MIRAS SOK. + ISTANBUL UMRANIYE 34775 + TR + +B4-37-D1 (hex) eInfochips Limited +800000-8FFFFF (base 16) eInfochips Limited + 303 Parishram Building, 5/B Rashmi Society + Ahmedabad Gujarat 380009 + IN + +54-9A-11 (hex) Elite Silicon Technology, Inc. +B00000-BFFFFF (base 16) Elite Silicon Technology, Inc. + 5F-B, No.24-2, Idustry E. Road IV. + Hsinchu Taiwan 300 + TW + +54-9A-11 (hex) Tite, Inc. +800000-8FFFFF (base 16) Tite, Inc. + 11040 Bollinger Canyon Road, Suite E-107 + San Ramon CA 94582 + US + +74-F8-DB (hex) Enercon Technologies +000000-0FFFFF (base 16) Enercon Technologies + 25 Northbrook Drive + Gray ME 04039 + US + +88-5D-90 (hex) Unitac Technology Limited +E00000-EFFFFF (base 16) Unitac Technology Limited + Unit 01, 10/F Carnival Comm. Bldg, + North Point - - + HK + +88-5D-90 (hex) Shenzhen Speedrun Technologies Co.,Ltd. +A00000-AFFFFF (base 16) Shenzhen Speedrun Technologies Co.,Ltd. + Room 303,Builing 5, GuiYuan Garden, NO.62 Airong Road, SheKou, NanShan District + ShenZhen GuangDong 518067 + CN + +74-F8-DB (hex) Capwave Technologies Inc +B00000-BFFFFF (base 16) Capwave Technologies Inc + 1501 Ocean Ave + Asbury Park NJ 07712 + US + +74-F8-DB (hex) Avantree Corporation +900000-9FFFFF (base 16) Avantree Corporation + 41871 Via San Miguel + Fremont CA 94539 + US + +88-5D-90 (hex) Creative Sensor Inc. +800000-8FFFFF (base 16) Creative Sensor Inc. + 9F., No.501, Sec. 6, Nanjing E. Rd., Neihu Dist., Taipei City 114, Taiwan (R.O.C.) + Taipei City Taiwan 114 + TW + +88-5D-90 (hex) DAIDONG Industrial System Co., Ltd. +200000-2FFFFF (base 16) DAIDONG Industrial System Co., Ltd. + 153B 3L, Namdong Industrial Complex, 729-2, Gojan-dong + Incheon Kyeong-gi 405-822 + KR + +80-7B-85 (hex) EFCO +500000-5FFFFF (base 16) EFCO + 10F-3, No.270, SEc 4 Chung Hsiao E Rd + Taipei 10674 + TW + +80-7B-85 (hex) Zhuhai TOP Intelligence Electric Co., Ltd. +300000-3FFFFF (base 16) Zhuhai TOP Intelligence Electric Co., Ltd. + No.619,Huawei Road + Zhuhai City Guangdong Province 519070 + CN + +80-7B-85 (hex) Hangzhou Synway Information Engineering Co., Ltd +100000-1FFFFF (base 16) Hangzhou Synway Information Engineering Co., Ltd + No.3756 Nanhuan Road,Hangzhou,Zhejiang,P.R.China + Hangzhou Zhejiang 310053 + CN + +80-7B-85 (hex) Quantel USA, Inc. +400000-4FFFFF (base 16) Quantel USA, Inc. + 601 Haggerty Ln. + Bozeman Montana 59715 + US + +54-9A-11 (hex) Alfen BV +900000-9FFFFF (base 16) Alfen BV + Hefbrugweg + Almere Netherlands 1332AP + NL + +54-9A-11 (hex) Torrap Design Limited +200000-2FFFFF (base 16) Torrap Design Limited + Unit 6, 19 Gloucester Road + Hurstville New South Wales 2220 + AU + +64-FB-81 (hex) Securosys SA +700000-7FFFFF (base 16) Securosys SA + Technopark 1 + Zürich ZH 8005 + CH + +1C-CA-E3 (hex) TengFeng +500000-5FFFFF (base 16) TengFeng + 3F, 1st Bldg, Yuejun Zhenxing lnd. Park, + Shenzhen Guangdong 518000 + CN + +80-E4-DA (hex) Guangzhou Pinzhong Electronic Technology CO., LTD +100000-1FFFFF (base 16) Guangzhou Pinzhong Electronic Technology CO., LTD + Room 810, Yinglong Plaza + Guangzhou Guangdong 510000 + CN + +80-E4-DA (hex) Thurlby Thandar Instruments LTD +200000-2FFFFF (base 16) Thurlby Thandar Instruments LTD + Glebe Road + Huntingdon Cambridgeshire PE29 7DR + GB + +1C-CA-E3 (hex) SIREA +A00000-AFFFFF (base 16) SIREA + 69 Rue de L'industrie + CASTRES Midi-Pyrénée 81100 + FR + +2C-D1-41 (hex) PIN SHANG LED Co., LTD. +C00000-CFFFFF (base 16) PIN SHANG LED Co., LTD. + 5-6Floor, Huilongda Industrial Park,shuitian community, ShiYan Town,bao’an district, + ShenZhen Guangdong 518108 + CN + +2C-D1-41 (hex) Shanghai RW ELE&TEC CO.,LTD +400000-4FFFFF (base 16) Shanghai RW ELE&TEC CO.,LTD + 10th Floor, No 6, Lane 2500 Xiupu Road, Pudong New District, Shanghai + Shanghai Shanghai 201315 + CN + +90-C6-82 (hex) PowerShield Limited +D00000-DFFFFF (base 16) PowerShield Limited + 12 Target Court + Glenfield Auckland 0627 + NZ + +2C-6A-6F (hex) Holjeron +D00000-DFFFFF (base 16) Holjeron + 9524 SW Tualatin Sherwood Rd. + Tualatin OR 97062 + US + +2C-6A-6F (hex) Sensity Systems +C00000-CFFFFF (base 16) Sensity Systems + 480 Oakmead Parkway + Sunnyvale California 94085 + US + +90-C6-82 (hex) Neone, Inc. +400000-4FFFFF (base 16) Neone, Inc. + 2001 Travis Heights Blvd + Austin Texas 78704 + + +98-02-D8 (hex) Navroom Beijing, China +900000-9FFFFF (base 16) Navroom Beijing, China + Floor 22, Suite B, Xi'Ao Center, Datun Road + Beijing 100101 + CN + +98-02-D8 (hex) HySecurity +A00000-AFFFFF (base 16) HySecurity + 6623 South 228th Street + Kent WA 98032 + US + +98-02-D8 (hex) Ormazabal Protection&Automation +700000-7FFFFF (base 16) Ormazabal Protection&Automation + B/Basauntz, 2 + Igorre Bizkaia 48140 + ES + +A0-BB-3E (hex) Beijing Techshino Technology Co., Ltd. +B00000-BFFFFF (base 16) Beijing Techshino Technology Co., Ltd. + 8/F, Building No. 1, Huihuang International Plaza, Shangdi 10th Street, Haidian District, + Beijing Beijing 100085 + CN + +98-02-D8 (hex) Promicon Elektronik GmbH + Co.KG +D00000-DFFFFF (base 16) Promicon Elektronik GmbH + Co.KG + Im Michelreis 6 + Pliezhausen Baden-Württemberg 72124 + DE + +98-02-D8 (hex) HANSHIN MEDICAL CO., LTD. +B00000-BFFFFF (base 16) HANSHIN MEDICAL CO., LTD. + 166, Pyeongcheonro, Bupyeong-gu + Incheon Incheon 403-853 + KR + +98-02-D8 (hex) Stoerk-Tronic, Stoerk GmbH & Co.KG +000000-0FFFFF (base 16) Stoerk-Tronic, Stoerk GmbH & Co.KG + Untere Waldplätze 6 + Stuttgart Baden-Wuerttemberg 70569 + DE + +2C-6A-6F (hex) TINYCO +400000-4FFFFF (base 16) TINYCO + 3rd Fl., Dukwon Bldg., 1225-4 Gaepo-Dong + Seoul Gangnam-Ku 135-963 + KR + +2C-6A-6F (hex) Beep, Inc. +600000-6FFFFF (base 16) Beep, Inc. + 2519 Mission St + SAN FRANCISCO CA 94110 + US + +2C-6A-6F (hex) Cloudproject Generation Srl +300000-3FFFFF (base 16) Cloudproject Generation Srl + Via Melchiorre Gioia 82 + MILANO MI 20125 + IT + +A0-BB-3E (hex) SIMTEC Elektronik GmbH +700000-7FFFFF (base 16) SIMTEC Elektronik GmbH + Glonner Strasse 5 + Feldkirchen-Westerham Bayern 83620 + DE + +28-FD-80 (hex) Millcode +000000-0FFFFF (base 16) Millcode + Bergsgårdsliden 5 + Halmstad Halland 30272 + SE + +2C-26-5F (hex) Itus Networks, LLC +800000-8FFFFF (base 16) Itus Networks, LLC + 6319 Nepo Drive + San Jose CALIFORNIA 95119 + US + +2C-26-5F (hex) Coremate Technical Co., Ltd +700000-7FFFFF (base 16) Coremate Technical Co., Ltd + 7F., No576, Sec.1, Minsheng N. Rd., + Taoyuan 33393 + TW + +2C-26-5F (hex) GTA Electronics Co., Ltd. +400000-4FFFFF (base 16) GTA Electronics Co., Ltd. + 9F., No.788, Zhongzheng Rd., Zhonghe Dist. + New Taipei City 23586 + TW + +2C-26-5F (hex) Griessbach +100000-1FFFFF (base 16) Griessbach + Im Biotechnologiepark + Luckenwalde 14943 + DE + +28-FD-80 (hex) Galileo, Inc. +100000-1FFFFF (base 16) Galileo, Inc. + 5-3-29 Tokiwagi + Ueda Nagano 386-0027 + JP + +A0-BB-3E (hex) Link Labs +000000-0FFFFF (base 16) Link Labs + 130 Holiday Court, Suite 100 + Annapolis Maryland 21401 + US + +28-FD-80 (hex) Grandway Technology (Shenzhen) Limited +D00000-DFFFFF (base 16) Grandway Technology (Shenzhen) Limited + Block 7, Zhu Keng Industrial Zone + Ping Shan District Shenzhen 518118 + CN + +28-FD-80 (hex) University of York +700000-7FFFFF (base 16) University of York + York Neuroimaging Centre, The Biocentre + York Yorkshire YO10 5NY + GB + +F8-02-78 (hex) Luxul Technology Inc +A00000-AFFFFF (base 16) Luxul Technology Inc + 2F., No.3, Yuandong Rd + New Taipei City Taiwan 220 + TW + +0C-EF-AF (hex) Rotel +900000-9FFFFF (base 16) Rotel + 43-59 Queens Road East + Wanchai Hong Kong 00000 + HK + +0C-EF-AF (hex) Firmware Design AS +600000-6FFFFF (base 16) Firmware Design AS + Grannes Terrasse 45 + Hafrsfjord Rogaland N-4044 + NO + +F8-02-78 (hex) Reason Tecnologia SA +100000-1FFFFF (base 16) Reason Tecnologia SA + Rua Joaquim Carneiro, 192 + Florianópolis Santa Catarina 8811120 + BR + +F8-02-78 (hex) Dueton Systems s.r.o. +D00000-DFFFFF (base 16) Dueton Systems s.r.o. + Varsavska 290/13 + Prague 2 Vinohrady 120 00 + CZ + +A4-4F-29 (hex) LUCEOR +200000-2FFFFF (base 16) LUCEOR + 2 Place Jules Gevelot + ISSY LES MOULINEAUX IDF 92138 + FR + +A4-4F-29 (hex) Olssen B.V. +100000-1FFFFF (base 16) Olssen B.V. + Schrank 9 + Hardinxveld-Giessendam Zuid-Hollland 3371KJ + NL + +A4-4F-29 (hex) DGC Access AB +400000-4FFFFF (base 16) DGC Access AB + Sveavägen 145 + Stockholm Stockholms Län 113 46 + SE + +A4-4F-29 (hex) Selektro Power Inc +600000-6FFFFF (base 16) Selektro Power Inc + 3610 NW 115th Ave + Doral Florida 33178 + US + +A4-4F-29 (hex) Shanghai KuanYu Industrial Network Equipment Co.,Ltd +500000-5FFFFF (base 16) Shanghai KuanYu Industrial Network Equipment Co.,Ltd + 15/F,No.3003,Baoyang Road, Baoshan District, + Shanghai 201901 + CN + +3C-39-E7 (hex) chipsguide technology Co.,LTD +B00000-BFFFFF (base 16) chipsguide technology Co.,LTD + NanGuang road, DongHua design house 758 room + Shenzhen Guangdong 518000 + CN + +3C-39-E7 (hex) ELSA Japan Inc. +300000-3FFFFF (base 16) ELSA Japan Inc. + Mita UT Bldg., 3-42-10 Shiba, + Minato-ku, Tokyo 105-0014 + JP + +0C-EF-AF (hex) Engineering Center ENERGOSERVICE +300000-3FFFFF (base 16) Engineering Center ENERGOSERVICE + Kotlasskaya 26 + Arkhangelsk Arkhangelsk region 163046 + RU + +10-07-23 (hex) Beijing Assem Technology Co., ltd +100000-1FFFFF (base 16) Beijing Assem Technology Co., ltd + Floor 6, Jinglong International Plaza, + Chaoyang District Beijing 100107 + CN + +D0-22-12 (hex) GNS-GmbH +A00000-AFFFFF (base 16) GNS-GmbH + Adenauerstr. 18 + Wuerselen NRW 52146 + DE + +D0-22-12 (hex) Xperio Labs Ltd. +C00000-CFFFFF (base 16) Xperio Labs Ltd. + Unit 3709, 37th Floor, Tower II, + Hong Kong Hong Kong HONG KONG + HK + +10-07-23 (hex) ESTONE TECHNOLOGY INC +600000-6FFFFF (base 16) ESTONE TECHNOLOGY INC + 21015 Commerce Point Drive Walnut, CA 91789 + Los Angeles California 91789 + US + +E8-18-63 (hex) DongGuan Pengxun Electronics Technology Co., Ltd. +300000-3FFFFF (base 16) DongGuan Pengxun Electronics Technology Co., Ltd. + 10th floor, Jinhui Bussiness Building, + DongGuan City GuangDong Province 523850 + CN + +E8-18-63 (hex) Guangzhou Tianyi Electronics Co., Ltd +400000-4FFFFF (base 16) Guangzhou Tianyi Electronics Co., Ltd + A3, Hongtu Industrial Plot, Dashi town, + Guangzhou Guangdong, 511430, + CN + +B8-D8-12 (hex) ZheJiang FangTai Electirc Co., Ltd +E00000-EFFFFF (base 16) ZheJiang FangTai Electirc Co., Ltd + B11 Block, Science and Technology Park + Hangzhou ZheJiang 310024 + CN + +E8-18-63 (hex) DigiMagus Technology (Shenzhen) Co., Ltd +000000-0FFFFF (base 16) DigiMagus Technology (Shenzhen) Co., Ltd + 1206, Shenzhen University-town Business Park, Lishan Road + ShenZhen GuangDong 518055 + CN + +74-E1-4A (hex) aritec gmbh +800000-8FFFFF (base 16) aritec gmbh + Vorstadtgasse 15 + Maienfeld Outside U.S./Canada 7304 + CH + +B8-D8-12 (hex) iModesty Technology Corp. +300000-3FFFFF (base 16) iModesty Technology Corp. + 3F-1, No.76, Sec.2 Jiafeng S.Rd., + Zhubei County Taiwan 302 + TW + +E8-18-63 (hex) JDM Mobile Internet Solution(Shanghai) Co., Ltd. +A00000-AFFFFF (base 16) JDM Mobile Internet Solution(Shanghai) Co., Ltd. + 2F, Building D, BenQ Plaza, No.207 + Shanghai Shanghai 200335 + CN + +B8-D8-12 (hex) Entotem LTD +900000-9FFFFF (base 16) Entotem LTD + Unit 3, South Stanmore Stables, + Newbury Berks RG20 8SR + GB + +B8-D8-12 (hex) XIAMEN XINDECO LTD. +500000-5FFFFF (base 16) XIAMEN XINDECO LTD. + 5F.,XINXI BLDG.,HULI + Xiamen Fujian 361000 + CN + +74-E1-4A (hex) AStar Design Service Technologies Co., Ltd. +A00000-AFFFFF (base 16) AStar Design Service Technologies Co., Ltd. + 3F, No219-1, Jianguo Rd. Sindian Dist. + New Taipei City Taiwan 23142 + TW + +E8-18-63 (hex) ARTECH SOLUTION CO.,LTD +600000-6FFFFF (base 16) ARTECH SOLUTION CO.,LTD + 470/11 Pattanakarn Rd.,Suanluang,Bkk.10250 Thailand + Bangkok Bangkok 10250 + TH + +BC-66-41 (hex) Shenzhen Crave Communication Co.,ltd +C00000-CFFFFF (base 16) Shenzhen Crave Communication Co.,ltd + 8th Block, Dongfangming Industry Park + Shenzhen GuangDong 518000 + CN + +BC-66-41 (hex) Lucent Trans Electronics Co., Ltd +E00000-EFFFFF (base 16) Lucent Trans Electronics Co., Ltd + 9F-1, NO.16, CHIEN PAH RD., + NEW TAIPEI CITY 23511 + TW + +E4-95-6E (hex) eZeLink LLC +900000-9FFFFF (base 16) eZeLink LLC + Office 1104, Aspect Tower, Executive Towers, Business Bay + Dubai Dubai 111581 + AE + +BC-66-41 (hex) VSN Mobil +700000-7FFFFF (base 16) VSN Mobil + 1975 E. Sunrise Blbvd., #400 + Fort Lauderdale Florida 33304 + US + +58-FC-DB (hex) SWARCO TRAFFIC SYSTEMS GMBH +B00000-BFFFFF (base 16) SWARCO TRAFFIC SYSTEMS GMBH + Kelterstr. 67 + Unterensingen Baden-Württemberg 72669 + DE + +B0-1F-81 (hex) TAIWAN Anjie Electronics Co.,Ltd. +D00000-DFFFFF (base 16) TAIWAN Anjie Electronics Co.,Ltd. + One 7th Floor,No.125,Lane 235, Pao Chiao Xindian District + New Taipei City Xindian District 231 + TW + +BC-66-41 (hex) Sidus Novum Sp. z o. o. +B00000-BFFFFF (base 16) Sidus Novum Sp. z o. o. + Ul. Ogrodowa 3B/203 + Zielona Góra Lubuskie 65462 + PL + +58-FC-DB (hex) Xmodus Systems GmbH +A00000-AFFFFF (base 16) Xmodus Systems GmbH + Reiherstrasse 2 + Haiger Hessen 35708 + DE + +B0-1F-81 (hex) SHENZHEN GRID TECHNOLOGY CO.,LTD +500000-5FFFFF (base 16) SHENZHEN GRID TECHNOLOGY CO.,LTD + 6thfloor,jinda Technology Center,No.8 of kefeng Road ,Science and Technology Park,NanshanDist,Shenzhen + shenzhen guangdong 518054 + CN + +B0-1F-81 (hex) Private +200000-2FFFFF (base 16) Private + +F4-0E-11 (hex) Shenzhen Grandsun Electronic Co.,Ltd. +700000-7FFFFF (base 16) Shenzhen Grandsun Electronic Co.,Ltd. + Gaoqiao Industrial Zone,Baishitang Village, + Shenzhen Guangdong 518116 + CN + +F4-0E-11 (hex) Elektronika Naglic d.o.o. +E00000-EFFFFF (base 16) Elektronika Naglic d.o.o. + Goricica pri Ihanu 44 + Domzale 1230 + SI + +F4-0E-11 (hex) NIHON MEGA LOGIC CO.,LTD. +C00000-CFFFFF (base 16) NIHON MEGA LOGIC CO.,LTD. + Mitsui-Seimei-Kameido BLDG. 1F + Koutou-ku Tokyo 136-0071 + JP + +B0-1F-81 (hex) Sound United +300000-3FFFFF (base 16) Sound United + 11433 Cronridge Drive + Owings Mills Maryland 21117 + US + +F4-0E-11 (hex) E-SONG +500000-5FFFFF (base 16) E-SONG + BUSAN TECHNOPARK Head office & Factory: Unit 102 + Busan N/A 618-230 + KR + +F4-0E-11 (hex) Shenzhen headsun technology +300000-3FFFFF (base 16) Shenzhen headsun technology + 3 Floor, C Building, NanYuan Industrial + ShenZhen GuangDong 518000 + CN + +14-1F-BA (hex) Swiss Electronic (Shenzhen) Co., Ltd +C00000-CFFFFF (base 16) Swiss Electronic (Shenzhen) Co., Ltd + 2712 Great China International Exchange Square + Shenzhen Guangdong 518026 + CN + +14-1F-BA (hex) Shenzhen CATIC Information Technology Industry Co.,Ltd +800000-8FFFFF (base 16) Shenzhen CATIC Information Technology Industry Co.,Ltd + 3/FL, Block 1, Shenzhen Software Park, No.2, Gaoxin Middle Street,Nanshan + Shen Zhen Guang Dong 518057 + CN + +14-1F-BA (hex) Winsonic Electronics Co., Ltd. +A00000-AFFFFF (base 16) Winsonic Electronics Co., Ltd. + No. 290-1, Wen Chung Rd., + Taoyuan City 330 + TW + +14-1F-BA (hex) GloQuad +100000-1FFFFF (base 16) GloQuad + 301 Biz Incubation Center, GSBC + Suwon-si Gyeonggi-do 443-270 + KR + +7C-70-BC (hex) Ametek VIS +A00000-AFFFFF (base 16) Ametek VIS + 287 27 Road + Grand Junction CO 81503 + US + +BC-34-00 (hex) Parlay Labs dba Highfive +C00000-CFFFFF (base 16) Parlay Labs dba Highfive + 471 Emerson St. + Palo Alto California 94301 + US + +7C-70-BC (hex) XD-GE Automation CO.,LTD +100000-1FFFFF (base 16) XD-GE Automation CO.,LTD + 101# Fengcheng 6 Road + Xi'an ShanXi 710016 + CN + +A4-3B-FA (hex) ALSTOM Strongwish (Shenzhen) Co., Ltd +B00000-BFFFFF (base 16) ALSTOM Strongwish (Shenzhen) Co., Ltd + 5F, Building No.6, Keji Middle 2 Road, High-Tech Industrial Park + Shenzhen Guangdong 518057 + CN + +A4-3B-FA (hex) The Magstim Company Ltd. +E00000-EFFFFF (base 16) The Magstim Company Ltd. + Spring Gardens + Whitland Carmarthenshire SA34 0HR + GB + +BC-34-00 (hex) IPLINK Technology Corp +100000-1FFFFF (base 16) IPLINK Technology Corp + 8F-5, No. 347, Jingsin St. + New Taipei City 23582 + TW + +A4-3B-FA (hex) Plus One Japan Ltd. +A00000-AFFFFF (base 16) Plus One Japan Ltd. + Storia Akasaka 410, + Minato-ku Tokyo 1080052 + JP + +A4-3B-FA (hex) SHANGHAI XIETONG TECHNOLOGY INC. +C00000-CFFFFF (base 16) SHANGHAI XIETONG TECHNOLOGY INC. + 423 Wuning Road,Shanghai + Shanghai 200063 + CN + +D0-76-50 (hex) DAIKEN AUTOMACAO LTDA +100000-1FFFFF (base 16) DAIKEN AUTOMACAO LTDA + AVENIDA SAO GABRIEL,481 + COLOMBO PARANA 83404000 + BR + +D0-76-50 (hex) PelKorea +B00000-BFFFFF (base 16) PelKorea + 60, Haan-ro + Gwangmyeong-si Gyeonggi-do KS009 + KR + +D0-76-50 (hex) InventDesign +A00000-AFFFFF (base 16) InventDesign + Valschermkade 29 + Amsterdam Noord-Holland 1059CD + NL + +A4-3B-FA (hex) Powell Industries +200000-2FFFFF (base 16) Powell Industries + 201-55 Gostick Place + North Vancouver British Columbia V7M 3N2 + + +D0-76-50 (hex) ENCORED Technologies, Inc. +700000-7FFFFF (base 16) ENCORED Technologies, Inc. + 8F KTS, 215 Bongeunsa-ro + Seoul 135-831 + KR + +74-19-F8 (hex) Trend-tech Technology Co., Limited +100000-1FFFFF (base 16) Trend-tech Technology Co., Limited + NO. 609, Noble Plaza, Qianjin YiLu + Shenzhen Guangdong 518101 + CN + +74-19-F8 (hex) Cloudvue Technologies Corporation +400000-4FFFFF (base 16) Cloudvue Technologies Corporation + 830 Stewart Drive, Suite 115 + Sunnyvale CA 94085 + US + +74-19-F8 (hex) Essential Trading Systems Corp +300000-3FFFFF (base 16) Essential Trading Systems Corp + 9 Austin Drive + Marlborough CT 06447 + US + +4C-4B-F9 (hex) Shenzhen HommPro Technology Co.,Ltd +200000-2FFFFF (base 16) Shenzhen HommPro Technology Co.,Ltd + 5F,Building B,Zhengchangda Digital Technology Park,Jian'an Road,Tangwei community,Fuhai street,Bao'an District + Shenzhen GuangDong 518000 + CN + +40-11-75 (hex) Beijing Hexinruitong Electric Power Technology Co., Ltd. +300000-3FFFFF (base 16) Beijing Hexinruitong Electric Power Technology Co., Ltd. + Room 306, 3F, No.16, Shangdi 5 Street, Haidian District + Beijing Beijing 100085 + CN + +40-11-75 (hex) Guangzhou RALID Information System Co.Ltd +700000-7FFFFF (base 16) Guangzhou RALID Information System Co.Ltd + ROOM 201 at 2nd floor in 2nd Building,No.602, Guangshan 2nd Road, Tianhe District + Guangzhou Guangdong 510663 + CN + +40-11-75 (hex) NanJing HuaStart Network Technology Co.,Ltd. +D00000-DFFFFF (base 16) NanJing HuaStart Network Technology Co.,Ltd. + Room 568,Longmian Road,Jiangning District + Nanjing Jiang Su 210000 + CN + +40-11-75 (hex) Chongqing IQIYI Intelligence Technology Co., Ltd. +B00000-BFFFFF (base 16) Chongqing IQIYI Intelligence Technology Co., Ltd. + Yongli International Center, Sanlitun, Chaoyang District + Beijing Beijing 100027 + CN + +10-DC-B6 (hex) Annapurna labs +400000-4FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +40-11-75 (hex) disguise Technologies Limited +C00000-CFFFFF (base 16) disguise Technologies Limited + Units C&D 127 Great Suffolk Street + London SE1 1PP + GB + +10-DC-B6 (hex) Shenzhen Sunwoda intelligent hardware Co.,Ltd +E00000-EFFFFF (base 16) Shenzhen Sunwoda intelligent hardware Co.,Ltd + No.6-6,Yan Shan Rd.,Baoan District,Shenzhen City,China + Shenzhen Guangdong 518105 + CN + +10-DC-B6 (hex) Prolan Zrt. +600000-6FFFFF (base 16) Prolan Zrt. + Szentendrei út 1-3. + Budakalasz 2011 + HU + +54-A4-93 (hex) Shenzhen C & D Electronics Co., Ltd. +400000-4FFFFF (base 16) Shenzhen C & D Electronics Co., Ltd. + 9th FIoor, Building 9, No.1 Qingxiang road, BaoNeng Science and TechnoIogy Industrial Park, Longhua New District + ShenZhen GuangDong 518000 + CN + +10-DC-B6 (hex) Sanofi (Beijing) Pharmaceutical Co., Ltd. +800000-8FFFFF (base 16) Sanofi (Beijing) Pharmaceutical Co., Ltd. + No.7, Xingsheng Street, Beijing Economic and Technological Development Zone + Beijing Beijing 100176 + CN + +10-DC-B6 (hex) CAL-COMP INDUSTRIA E COMERCIO DE ELETRONICOS E INFORMATICA LTDA +200000-2FFFFF (base 16) CAL-COMP INDUSTRIA E COMERCIO DE ELETRONICOS E INFORMATICA LTDA + AVENIDA TORQUATO TAPAJOS, 7503 TARUMA GALPAO 2 - CNPJ: 07.200.194/0003-80 + MANAUS AMAZONAS 69041-025 + BR + +54-A4-93 (hex) ShenZhen Smart&Aspiration Co.,LTD +100000-1FFFFF (base 16) ShenZhen Smart&Aspiration Co.,LTD + Guanlan + ShenZhen GuangDong 518000 + CN + +54-A4-93 (hex) Chengdu EVECCA Technology Co.,Ltd. +800000-8FFFFF (base 16) Chengdu EVECCA Technology Co.,Ltd. + Floor 20, Building B, Xingchen International, No.555, Middle Section of Yizhou Avenue + Chengdu Sichuan 610015 + CN + +54-A4-93 (hex) AUSOUNDS INTELLIGENCE, LLC +500000-5FFFFF (base 16) AUSOUNDS INTELLIGENCE, LLC + 929 108TH AVE NE STE 1200, BELLEVUE, WA, 98004-4787, UNITED STATES + BELLEVUE WA 98004 + US + +54-A4-93 (hex) ASSEM TECHNOLOGY CO.,LTD. +D00000-DFFFFF (base 16) ASSEM TECHNOLOGY CO.,LTD. + No. 17, Minquan St., Tucheng Dist., + New Taipei City Taiwan (R.O.C.) 236 + TW + +04-D1-6E (hex) Elotec Fischer Elektronik GmbH +D00000-DFFFFF (base 16) Elotec Fischer Elektronik GmbH + Nordgaustraße 20 + Furth im Wald Bavaria 93437 + DE + +54-A4-93 (hex) Nederman Holding AB +E00000-EFFFFF (base 16) Nederman Holding AB + Sydhamnsgatan 2 + Helsingborg Sweden 252 28 + SE + +44-03-77 (hex) OMNISENSE SYSTEMS PRIVATE LIMITED TAIWAN BRANCH +D00000-DFFFFF (base 16) OMNISENSE SYSTEMS PRIVATE LIMITED TAIWAN BRANCH + 7th Floor, No. 10, Lane 30, Lane 358, Ruiguang Road, Neihu District, Taipei, Taiwan + Taipei 114 + TW + +50-62-55 (hex) Ufanet SC +000000-0FFFFF (base 16) Ufanet SC + bldg 4/3, Prospect Octyabrya + Ufa 450001 + RU + +64-31-39 (hex) Dongguan Huili electroacoustic Industrial Co.,ltd +700000-7FFFFF (base 16) Dongguan Huili electroacoustic Industrial Co.,ltd + Dalang Town, Biyun Cai Bai Cun East Second Street 66,A4 Building 501 + Dongguan Guangdong 523770 + CN + +50-62-55 (hex) Southern Ground Audio LLC +900000-9FFFFF (base 16) Southern Ground Audio LLC + 101 Gardner Park + Peachtree City GA 30269 + US + +C4-95-4D (hex) Shenzhen Xtooltech Co., Ltd +900000-9FFFFF (base 16) Shenzhen Xtooltech Co., Ltd + 10574 Acacia St, Suite D4 + Rancho Cucamonga CA 91730 + US + +C4-95-4D (hex) Shen Zhen Euse Technology Co.,Ltd +200000-2FFFFF (base 16) Shen Zhen Euse Technology Co.,Ltd + 4/F, Block A2, Xinhao First Industrial Zone,  Qiaotou Community, Fuhai Street + Shenzhen Guangdong 518103 + CN + +A0-22-4E (hex) ProPhotonix +300000-3FFFFF (base 16) ProPhotonix + 3020 Euro Business Park + Co Cork Little Island n/A + IE + +A0-22-4E (hex) Applied Information, Inc. +700000-7FFFFF (base 16) Applied Information, Inc. + 4411 Suwanee Dam Rd, Suite 510 + Suwanee GA 30024 + US + +20-0A-0D (hex) Netinovo Technologies(Shenzhen) Ltd +200000-2FFFFF (base 16) Netinovo Technologies(Shenzhen) Ltd + 101,201,301,Bldg8,No.1 industry zone,Shanmen Community,Yanluo Street + Shenzhen Guangdong 518105 + CN + +20-0A-0D (hex) bcheck NV +800000-8FFFFF (base 16) bcheck NV + Livornostraat 66/12 + Brussels Brussels 1000 + BE + +40-2C-76 (hex) Suteng Innovation Technology Co., Ltd. +800000-8FFFFF (base 16) Suteng Innovation Technology Co., Ltd. + 10-11/F, Block 3, Chongwen Garden, Nanshan IPark, 3370 Liuxian Avenue, Nanshan District + Shenzhen 518000 + CN + +40-2C-76 (hex) Lista AG +000000-0FFFFF (base 16) Lista AG + Fabrikstrasse 1 + Erlen TG 8586 + CH + +40-2C-76 (hex) Zhejiang Guoli Security Technology Co., Ltd. +700000-7FFFFF (base 16) Zhejiang Guoli Security Technology Co., Ltd. + Room (1-1-178), No. 150, Zhangpu Road, Jiushigang Town, Haishu District + Ningbo Zhejiang 315000 + CN + +40-2C-76 (hex) Annapurna labs +900000-9FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +50-DE-19 (hex) BRAINWARE TERAHERTA INFORMATION TECHNOLOGY CO.,LTD. +B00000-BFFFFF (base 16) BRAINWARE TERAHERTA INFORMATION TECHNOLOGY CO.,LTD. + F3 and F4 of Innovation Industrial Park Phase II in Hefei High-tech Zone + Hefei Anhui 230000 + CN + +40-2C-76 (hex) Guangzhou LANGO Electronics Technology Co., Ltd. +600000-6FFFFF (base 16) Guangzhou LANGO Electronics Technology Co., Ltd. + 136#, Gaopu Road, Tianhe District + Guangzhou Guangdong 510663 + CN + +50-DE-19 (hex) Penny & Giles Aerospace Ltd +D00000-DFFFFF (base 16) Penny & Giles Aerospace Ltd + 15 Enterprise Way + Christchurch Dorset BH23 6HH + GB + +50-DE-19 (hex) Bliq B.V. +500000-5FFFFF (base 16) Bliq B.V. + Hogeweyselaan 145 + Weesp 1382JK + NL + +50-DE-19 (hex) Private +E00000-EFFFFF (base 16) Private + +3C-FA-D3 (hex) AMobile Solutions (Xiamen) CO. , LTD. +D00000-DFFFFF (base 16) AMobile Solutions (Xiamen) CO. , LTD. + Room 105A, building 5#, No. 20-24 East Huoju Road, Huoju Park, Xiamen Torch Hi-tech zone + Xiamen 361006 + CN + +3C-FA-D3 (hex) Energous Corporation +800000-8FFFFF (base 16) Energous Corporation + 3590 N. First Street + San Jose CA 95134 + US + +3C-FA-D3 (hex) Gulf Security Technology Co., Ltd +500000-5FFFFF (base 16) Gulf Security Technology Co., Ltd + 80 Changjiang East Road, Economic & Technology Development Zone + Qinhuangdao Hebei 066000 + CN + +3C-FA-D3 (hex) Home Control AS +000000-0FFFFF (base 16) Home Control AS + Postboks 1618 Vika + Oslo 0119 + NO + +B0-B3-53 (hex) HANMECIPS CO. +900000-9FFFFF (base 16) HANMECIPS CO. + 17, Alphacity 1-ro 31-gil, Suseong-gu, Daegu, Republic of Korea + TAEGU TAEGU/053 ASIKRKS002TAEGU + KR + +B0-B3-53 (hex) Zenlayer +500000-5FFFFF (base 16) Zenlayer + 21680 GATEWAY CENTER DR., Suite#350 + DIAMOND BAR CA 91765 + US + +90-E2-FC (hex) Beijing Lanxum Computer Technology CO.,LTD. +D00000-DFFFFF (base 16) Beijing Lanxum Computer Technology CO.,LTD. + 3A Floor,BlockB,Technology Fortune Center,No 8 Xueqing Road,Haidian District, + Beijing Beijing 100192 + CN + +90-E2-FC (hex) ShenZhen Temwey Innovation Technology Co.,Ltd. +200000-2FFFFF (base 16) ShenZhen Temwey Innovation Technology Co.,Ltd. + Room 1008, 10/F, Bld.B, Bantian International Centre, No. 5 South Huancheng Road, Bantian Street of Shenzhen Longgang District + SHENZHEN GUANGDONG 518129 + CN + +90-E2-FC (hex) Dongguan Kangyong electronics technology Co. Ltd +400000-4FFFFF (base 16) Dongguan Kangyong electronics technology Co. Ltd + No 9,Yincheng 1st Road, Xiabian Village, Chang’an Town + Dongguan GuangDong 523877 + CN + +90-E2-FC (hex) bitsensing Inc. +800000-8FFFFF (base 16) bitsensing Inc. + 165, Yeoksam-ro, + Gangnam-gu, Seoul, Republic of Korea 06247 + KR + +90-E2-FC (hex) Stanley Security +C00000-CFFFFF (base 16) Stanley Security + 8350 Sunlight Drive + Fishers IN 46037 + US + +14-AE-85 (hex) iSolution Technologies Co.,Ltd. +D00000-DFFFFF (base 16) iSolution Technologies Co.,Ltd. + 5F,Bldg #6, Zhongguan Honghualing Industrial South Park + Shenzhen Guangdong 518055 + CN + +7C-BC-84 (hex) VANTAGE INTEGRATED SECURITY SOLUTIONS PVT LTD +D00000-DFFFFF (base 16) VANTAGE INTEGRATED SECURITY SOLUTIONS PVT LTD + B3, Bredon House, 321, Tettenhall Road, Tettenhall + Wolverhampton West Midlands WV6 0JZ + GB + +64-62-66 (hex) FaceHeart Inc. +300000-3FFFFF (base 16) FaceHeart Inc. + Rm. 8, 19F., No.118, Ciyun Rd., East Dist. + Hsinchu Taiwan 300 + TW + +64-62-66 (hex) Sensoro Co., Ltd. +A00000-AFFFFF (base 16) Sensoro Co., Ltd. + 7F D-Block, Lei Shing Hong Center, No. 8 Guangshun South Street, Chaoyang District, + Beijing Beijing 100102 + CN + +64-62-66 (hex) Pass & Seymour, Inc d/b/a Legrand +600000-6FFFFF (base 16) Pass & Seymour, Inc d/b/a Legrand + 50 Boyd Ave + Syracuse NY 13209 + US + +94-CC-04 (hex) Shandong free optical technology co., ltd. +B00000-BFFFFF (base 16) Shandong free optical technology co., ltd. + 195 East First Street, Industrial First Street, Economic Development Zone, Weifang, Weicheng District, + Weifeng Shandong 216000 + CN + +94-CC-04 (hex) ENTEC Electric & Electronic Co., LTD. +900000-9FFFFF (base 16) ENTEC Electric & Electronic Co., LTD. + 78-2 Buncheon-ri, Bongdam-eup + Hwaseong-city Gyungki-do 445-894 + KR + +94-CC-04 (hex) SynchronicIT BV +E00000-EFFFFF (base 16) SynchronicIT BV + Spoorstraat 155, room 413 + Gennep Nederland 6591 GT + NL + +F4-90-CB (hex) Simavita (Aust) Pty Ltd +D00000-DFFFFF (base 16) Simavita (Aust) Pty Ltd + Suite 2.02, L2, 54 Miller Street + North Sydney NSW 2060 + AU + +F4-90-CB (hex) Ricker Lyman Robotic +300000-3FFFFF (base 16) Ricker Lyman Robotic + 319 Main Street + Beacon NY 12508 + US + +20-85-93 (hex) Great Lite International +700000-7FFFFF (base 16) Great Lite International + 11F., No.207-2, Sec. 3, Beixin Rd., Xindian Dist., + New Taipei City Taiwan 23143 + TW + +4C-4B-F9 (hex) Tecnoplus Srl +900000-9FFFFF (base 16) Tecnoplus Srl + Via Cilavegna, 53 + Gravellona Lomellina Pavia 27020 + IT + +98-06-37 (hex) Summa nv +200000-2FFFFF (base 16) Summa nv + Rochesterlaan 6 + Gistel 8470 + BE + +98-06-37 (hex) Shanghai Jinnian information technology Co. Ltd +E00000-EFFFFF (base 16) Shanghai Jinnian information technology Co. Ltd + Room 102-105 ,block 1 , No.33 leshan Road + Shanghai Shanghai 200030 + CN + +24-15-10 (hex) Annapurna labs +400000-4FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +44-D5-F2 (hex) Auctus Technologies Co.,Ltd. +900000-9FFFFF (base 16) Auctus Technologies Co.,Ltd. + 17F, Building 3, China Science and Technology Development Park, No. 009, 1st South Gaoxin Road, Nanshan District + Shenzhen Guangdong 518000 + CN + +44-D5-F2 (hex) Shenzhen Qiutian Technology Co.,Ltd +700000-7FFFFF (base 16) Shenzhen Qiutian Technology Co.,Ltd + 5B01 5F Wangtang Building Xingao Road Xili Nanshan District + Shenzhen Guangdong 518000 + CN + +44-D5-F2 (hex) Joint-Stock Company Research and Development Center ELVEES +E00000-EFFFFF (base 16) Joint-Stock Company Research and Development Center ELVEES + Proezd 4922, Dom 4, Stroenie 2 + Zelenograd Moscow 124498 + RU + +44-D5-F2 (hex) neocontrol soluções em automação +C00000-CFFFFF (base 16) neocontrol soluções em automação + rua santa fe 100 + belo horizonte MG 30320-130 + BR + +D0-5F-64 (hex) Hangzhou ToupTek Photonics Co., Ltd. +100000-1FFFFF (base 16) Hangzhou ToupTek Photonics Co., Ltd. + 4F, Block A, B, Building 2, NO.321, Jinpeng Street, Xihu District + Hangzhou Zhejiang 310030 + CN + +FC-A4-7A (hex) Shenzhen VMAX New Energy Co., Ltd. +100000-1FFFFF (base 16) Shenzhen VMAX New Energy Co., Ltd. + 5F, Fengyun Building, No.5 Road, Hi-Tech Industrial Park (North), Nanshan District, + Shenzhen Guangdong 518057 + CN + +D0-5F-64 (hex) Beijing Core Shield Group Co., Ltd. +700000-7FFFFF (base 16) Beijing Core Shield Group Co., Ltd. + 2/F, Tower C, Building 4, Zhongguancun Software Park, No.8 Dongbeiwang West Road, Haidian District, Beijing, China + Beijing 100085 + CN + +2C-16-BD (hex) Shenzhen elink smart Co., ltd +800000-8FFFFF (base 16) Shenzhen elink smart Co., ltd + Floor 2,Building A , Hongtian Xinfengze Industrial Park Huang Pu Community , Xin Qiao District ,Baoan Area + shenzhen Guangdong Province 518101 + CN + +2C-16-BD (hex) Shenzhen Haiying Wire Tech Co., Ltd. +A00000-AFFFFF (base 16) Shenzhen Haiying Wire Tech Co., Ltd. + 5/F, No. 6 Bldg, Longcheng Industrial Park, Longhua District + Shenzhen Guangdong 518110 + CN + +FC-A4-7A (hex) Cliptech Industria e Comercio Ltda +300000-3FFFFF (base 16) Cliptech Industria e Comercio Ltda + ROD VICE PREF HERMENEGILDO TONOLI, 2285 + ITUPEVA SAO PAULO 13295000 + BR + +B4-A2-EB (hex) Softel SA de CV +400000-4FFFFF (base 16) Softel SA de CV + Camino a Santa Teresa + Tlalpan 14010 + MX + +B4-A2-EB (hex) Katerra Inc +200000-2FFFFF (base 16) Katerra Inc + 2494 Sand Hill Rd, Bldg 7, Suite 100 + Menlo Park CA 94025-6981 + US + +80-E4-DA (hex) Private +F00000-FFFFFF (base 16) Private + +8C-59-3C (hex) Qbic Technology Co., Ltd +600000-6FFFFF (base 16) Qbic Technology Co., Ltd + 26F.-12, No.99, Sec. 1, Xintai 5th Rd., Xizhi Dist., + New Taipei 22175 + TW + +8C-59-3C (hex) IDRO-ELETTRICA S.P.A. +D00000-DFFFFF (base 16) IDRO-ELETTRICA S.P.A. + VIA BELLINI 2 + SAN CESARIO SUL PANARO ITALY/MODENA 41018 + IT + +8C-59-3C (hex) Chongqing beimoting technology co.ltd +300000-3FFFFF (base 16) Chongqing beimoting technology co.ltd + 97-2 keyuan 2nd street, jiulongpo district, + Chongqing Chongqing 400039 + CN + +8C-59-3C (hex) Fujian Chaozhi Group Co., Ltd. +000000-0FFFFF (base 16) Fujian Chaozhi Group Co., Ltd. + Chaozhi Group, 13th Floor, Zhongqing Building, Haixi Science and Technology Park, Shangjie Town, Minhou County + Fuzhou Fujian 350000 + CN + +D0-C8-57 (hex) CHUNGHSIN INTERNATIONAL ELECTRONICS CO.,LTD. +B00000-BFFFFF (base 16) CHUNGHSIN INTERNATIONAL ELECTRONICS CO.,LTD. + 618-2# Gongren West Road,Jiaojiang, + Taizhou Zhejiang 317700 + CN + +D0-C8-57 (hex) DALI A/S +100000-1FFFFF (base 16) DALI A/S + Dali Alle 1 + Norager 9610 + DK + +BC-97-40 (hex) ForoTel +B00000-BFFFFF (base 16) ForoTel + 77, Shaumyana Str. + Rostov-na-Donu UFO 344079 + RU + +BC-97-40 (hex) Gaodi Rus +800000-8FFFFF (base 16) Gaodi Rus + Korneeva, 14 + Elektrostal Moscow region 144009 + RU + +60-95-CE (hex) AdvanWISE Corporation +500000-5FFFFF (base 16) AdvanWISE Corporation + No.11, Aly. 18, Ln. 85, Fuqun St., Xiangshan Dist. + Hsinchu 30067 + TW + +84-8B-CD (hex) Dunst tronic GmbH +800000-8FFFFF (base 16) Dunst tronic GmbH + Seevetalstraße, 2 + Seevetal Niedersachsen 21217 + DE + +84-8B-CD (hex) Annapurna labs +300000-3FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +84-8B-CD (hex) Emotiv Inc +E00000-EFFFFF (base 16) Emotiv Inc + 490 Post Street + San Francisco CA 94102 + US + +84-8B-CD (hex) ENGISAT LDA +D00000-DFFFFF (base 16) ENGISAT LDA + RUA CENTRAL SAO LOURENÇO Nº 312 + VILAR DE ANDORINHO PORTO 4430-358 + PT + +84-8B-CD (hex) Smart Code (Shenzhen) Technology Co.,Ltd +700000-7FFFFF (base 16) Smart Code (Shenzhen) Technology Co.,Ltd + Keji North 3rd Rd + Shenzhen guangdong 518000 + CN + +B0-FD-0B (hex) Fasii Information Technology (Shanghai) Ltd. +400000-4FFFFF (base 16) Fasii Information Technology (Shanghai) Ltd. + Room 5011, Building 1, No.335 Guoding Road, Yangpu District + Shanghai Shanghai 200433 + CN + +B0-FD-0B (hex) TAE HYUNG Industrial Electronics Co., Ltd. +000000-0FFFFF (base 16) TAE HYUNG Industrial Electronics Co., Ltd. + 301-404, Bucheon Technopark, 345, Seokcheon-ro + Bucheon-si Gyeonggi-do 14501 + KR + +84-8B-CD (hex) Sphera Telecom +A00000-AFFFFF (base 16) Sphera Telecom + Pos. Moscowskiy, 22-nd km of Kievskoye highway, household 4, building 2, body G, office 802G + Moscow 108811 + RU + +C8-2C-2B (hex) Shiftall Inc. +A00000-AFFFFF (base 16) Shiftall Inc. + 4F TokyoDaiwa Bldg., 2-6-10 Nihonbashibakurocho, + Chuo, Tokyo 1030002 + JP + +C8-2C-2B (hex) BIOT Sp. z o.o. +900000-9FFFFF (base 16) BIOT Sp. z o.o. + Nowy Kisielin-Nowa 7 + Zielona Góra Lubuskie 66-002 + PL + +E4-1E-0A (hex) Shanghai LeXiang Technology Co., Ltd +E00000-EFFFFF (base 16) Shanghai LeXiang Technology Co., Ltd + Floor 6,Building 8,Yanjiaqiao Road,Pudong Area ,Shanghai ,China + shanghai 200125 + CN + +C8-2C-2B (hex) Fungible, Inc. +000000-0FFFFF (base 16) Fungible, Inc. + 3201 Scott Blvd., 2nd floor + Santa Clara CA 95054 + US + +B0-FD-0B (hex) Habana Labs LTD +D00000-DFFFFF (base 16) Habana Labs LTD + 5 Tarshish St, + Caesarea 3079821 + IL + +E4-1E-0A (hex) TELETASK BELGIUM +C00000-CFFFFF (base 16) TELETASK BELGIUM + Ottergemsesteenweg-zuid 729 + GENT Oost-Vlaanderen 9000 + BE + +C8-63-14 (hex) GRINBI PARTNERS +600000-6FFFFF (base 16) GRINBI PARTNERS + 222, Dogok-ro, Gangnam-gu + Seoul 06272 + KR + +E4-1E-0A (hex) ROMO Wind A/S +D00000-DFFFFF (base 16) ROMO Wind A/S + Olof Palmes Allé 47 + Aarhus N 8200 + DK + +C8-63-14 (hex) Shenzhen Wesion Technology Co., Ltd +700000-7FFFFF (base 16) Shenzhen Wesion Technology Co., Ltd + A511, Mingyou Purchasing Center, Baoyuan Road, Xixiang Street + Shenzhen Guangdong 518102 + CN + +C8-63-14 (hex) Shenzhen Zero Zero Infinity Technology Co.,Ltd. +400000-4FFFFF (base 16) Shenzhen Zero Zero Infinity Technology Co.,Ltd. + 309 Rainbow Technology Building, 36 Gaoxin North 6th Road, Xili Street + Shenzhen Guangdong 518000 + CN + +C8-63-14 (hex) Telematix AG +D00000-DFFFFF (base 16) Telematix AG + Freiburgstrasse 251 + Bern Bern 3018 + CH + +C8-63-14 (hex) TrackMan +300000-3FFFFF (base 16) TrackMan + Stubbeled 2 + Vedbaek 2950 + DK + +34-E1-D1 (hex) Annapurna labs +E00000-EFFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +FC-D2-B6 (hex) Oviss Labs Inc. +800000-8FFFFF (base 16) Oviss Labs Inc. + 46259 Warm Springs Blvd + Fremont CA 94539 + US + +34-E1-D1 (hex) Tianjin Sublue Ocean Science & Technology Co., Ltd +000000-0FFFFF (base 16) Tianjin Sublue Ocean Science & Technology Co., Ltd + No.29 Factory No.156 Nanhai Road,TEDA + Tianjin 300050 + CN + +34-E1-D1 (hex) Doki Technologies Limited +500000-5FFFFF (base 16) Doki Technologies Limited + Unit 601,Tower One, Silvercord, 30 Canton Road, Tsim Sha Tsui + Kowloon 00000 + HK + +34-E1-D1 (hex) Teton Camera LLC +200000-2FFFFF (base 16) Teton Camera LLC + PO BOX 648 + PINEDALE WY 82941-0648 + US + +74-5B-C5 (hex) EDOMO Systems GmbH +800000-8FFFFF (base 16) EDOMO Systems GmbH + Obertorplatz 2 + Landau Deutschland (DEU) 76829 + DE + +90-C6-82 (hex) Private +F00000-FFFFFF (base 16) Private + +FC-D2-B6 (hex) Grandway Technology (Shenzhen) Limited +500000-5FFFFF (base 16) Grandway Technology (Shenzhen) Limited + Block 7, Zhu Keng Industrial Zone + Ping Shan District Shenzhen 518118 + CN + +FC-D2-B6 (hex) CG POWER AND INDUSTRIAL SOLUTIONS LTD +000000-0FFFFF (base 16) CG POWER AND INDUSTRIAL SOLUTIONS LTD + A-3, MIDC , AMBAD + NASHIK MAHARASHTRA 422010 + IN + +FC-D2-B6 (hex) T CHIP DIGITAL TECHNOLOGY CO.LTD +B00000-BFFFFF (base 16) T CHIP DIGITAL TECHNOLOGY CO.LTD + Room 320, C Tower, Jingji Building, HuaFeng Headquarter, Xixiang, Baoan + SHENZHEN Guangdong 518000 + CN + +E4-4C-C7 (hex) FLK information security technology Co,. Ltd +E00000-EFFFFF (base 16) FLK information security technology Co,. Ltd + Room 1801, Yinfeng Building, No. 1505, Binsheng Road, Binjiang District + Hangzhou Zhejiang 310051 + CN + +E4-4C-C7 (hex) IAG GROUP LTD +800000-8FFFFF (base 16) IAG GROUP LTD + IAG Industrial Park, Jiuwei, Xixiang Town, Baoan, Shenzhen, China. + shenzhen 518000 + CN + +74-5B-C5 (hex) uGrid Network Inc. +400000-4FFFFF (base 16) uGrid Network Inc. + 602 Gabriola Way + Ottawa Ontario K2T 0M2 + CA + +E4-4C-C7 (hex) Muzik Inc +A00000-AFFFFF (base 16) Muzik Inc + 9220 Sunset Blvd #112 + West Hollywood CA 90069 + US + +4C-BC-98 (hex) Airtex Manufacturing Partnership +900000-9FFFFF (base 16) Airtex Manufacturing Partnership + 1441 Hastings Cres. SE + Calgary Alberta T2G 4C8 + CA + +4C-BC-98 (hex) Voegtlin Instruments GmbH +700000-7FFFFF (base 16) Voegtlin Instruments GmbH + Langenhagstrasse 1 + Aesch CH-4147 + CH + +4C-BC-98 (hex) Heliotis AG +C00000-CFFFFF (base 16) Heliotis AG + Längenbold 5 + Root 6037 + CH + +4C-BC-98 (hex) Humanplus Intelligent Robotics Technology Co.,Ltd. +600000-6FFFFF (base 16) Humanplus Intelligent Robotics Technology Co.,Ltd. + Room507,5th Floor, Zhongguancun Frontier Technology Innovation Building, No. 67 North Fourth Ring Road,Haidian District, + Beijing Beijing 100089 + CN + +2C-26-5F (hex) Private +F00000-FFFFFF (base 16) Private + +A0-BB-3E (hex) Private +F00000-FFFFFF (base 16) Private + +2C-6A-6F (hex) Private +F00000-FFFFFF (base 16) Private + +4C-65-A8 (hex) ZMIN Technologies +B00000-BFFFFF (base 16) ZMIN Technologies + Room 403-405, Building C, Baoan New Generation Information Technology Industrial Park, No.139, Chuangye 2 Rd., Baoan District + ShenZhen GuangDong 518101 + CN + +E0-5A-9F (hex) Chengdu Song Yuan Electronic Technology Co.,Ltd +200000-2FFFFF (base 16) Chengdu Song Yuan Electronic Technology Co.,Ltd + Building 63 Cui Feng International, No.366 Bai Cao Road, High-tech West Zone + Chengdu Sichuan 610000 + CN + +E0-5A-9F (hex) Contemporary Amperex Technology Co., Limited +A00000-AFFFFF (base 16) Contemporary Amperex Technology Co., Limited + No.2 Xingang Road, Zhangwan Town, Jiaocheng District + Ningde Fujian 352000 + CN + +E0-5A-9F (hex) Annapurna labs +000000-0FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +E0-5A-9F (hex) Mountz, Inc. +D00000-DFFFFF (base 16) Mountz, Inc. + 1080 N. 11th Street + San Jose CA 95112 + US + +E0-5A-9F (hex) TRYEN +500000-5FFFFF (base 16) TRYEN + Manan-gu Anyang-ro 110 + Anyang Kyeong-gi 14035 + KR + +38-B1-9E (hex) Freedompro Srl +100000-1FFFFF (base 16) Freedompro Srl + Via Frova, 34 + Cinisello Balsamo 20092 + IT + +D8-86-0B (hex) Krspace +100000-1FFFFF (base 16) Krspace + Building 1, Junhao Central Park Plaza + ChaoYang District Beijing 100125 + CN + +38-B1-9E (hex) Doepke Schaltgeräte GmbH +900000-9FFFFF (base 16) Doepke Schaltgeräte GmbH + Stellmacherstr. 11 + Norden Niedersachsen 26506 + DE + +28-36-38 (hex) Swisson AG +C00000-CFFFFF (base 16) Swisson AG + Fabrikstrasse 21 + Lyss 3250 + CH + +CC-D3-9D (hex) Evoko Unlimited AB +100000-1FFFFF (base 16) Evoko Unlimited AB + Hästholmsvägen 32 + Nacka 13130 + SE + +D4-25-CC (hex) bvk technology +500000-5FFFFF (base 16) bvk technology + Mithatpasa Mah. Serin Cikmazi No:4 C Blok Kemerburgaz, Eyupsultan + Istanbul Istanbul 34075 + TR + +D4-25-CC (hex) POSNET Polska S.A. +C00000-CFFFFF (base 16) POSNET Polska S.A. + ul. Municypalna 33 + Warszawa 02-281 + PL + +D4-25-CC (hex) MusicLens Inc. +200000-2FFFFF (base 16) MusicLens Inc. + 311 E VALLEY BLVD#112 PMB27 + SANGABRIEL CA 91776 + US + +CC-D3-9D (hex) Lubelskie Fabryki Wag FAWAG S.A. +A00000-AFFFFF (base 16) Lubelskie Fabryki Wag FAWAG S.A. + Łęczyńska 58 + Lublin 20-954 + PL + +38-B1-9E (hex) Beijing Memblaze Technology Co Ltd +700000-7FFFFF (base 16) Beijing Memblaze Technology Co Ltd + Building B2,Dongsheng Park, 66 Xixiaokou Road, Haidian + Beijing Beijing 100192 + CN + +9C-69-B4 (hex) EA Technology Ltd +100000-1FFFFF (base 16) EA Technology Ltd + Capenhurst Technology Park + Chester Cheshire CH16ES + GB + +D4-25-CC (hex) DOLBY LABORATORIES, INC. +800000-8FFFFF (base 16) DOLBY LABORATORIES, INC. + 100 Potrero Avenue + San Francisco CA 94103-4938 + US + +68-91-D0 (hex) G-TECH Instruments Inc. +400000-4FFFFF (base 16) G-TECH Instruments Inc. + 2F.-2, No.83, Sec. 2, Gongdao 5th Rd., East Dist. + Hsinchu 30070 + TW + +9C-69-B4 (hex) Intellect module LLC +D00000-DFFFFF (base 16) Intellect module LLC + Krasnogo kursanta str. 25 lit. J + Saint-Petersburg 197110 + RU + +D4-25-CC (hex) BlueCats US, LLC +700000-7FFFFF (base 16) BlueCats US, LLC + 6767 OLD MADISON PIKE NW, SUITE 300 + Huntsville AL 35806 + US + +4C-91-7A (hex) Annapurna labs +E00000-EFFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +4C-91-7A (hex) Erlab DFS SAS +A00000-AFFFFF (base 16) Erlab DFS SAS + Parc d'Affaires des Portes - BP403 + Val de Reuil 27104 + FR + +6C-DF-FB (hex) Sercomm Corporation. +200000-2FFFFF (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +4C-91-7A (hex) AvertX +B00000-BFFFFF (base 16) AvertX + 23221 E. Knox Ave + Liberty Lake WA 99019 + US + +6C-DF-FB (hex) Shenzhen HDCVT Technology +000000-0FFFFF (base 16) Shenzhen HDCVT Technology + Floor 7, Building 5, Lihe Industrial Park, Songbai Road, Xili Street, Nanshan District + Shenzhen Guangdong 518055 + CN + +7C-BC-84 (hex) Guangzhou Puppyrobot Technology Co.Ltd Beijing Branch +B00000-BFFFFF (base 16) Guangzhou Puppyrobot Technology Co.Ltd Beijing Branch + R&F center,63 East middle 3rd ring road + beijing 10000 + CN + +7C-BC-84 (hex) HITIQ LIMITED +900000-9FFFFF (base 16) HITIQ LIMITED + 628 Newcastle St + Leederville WA 6007 + AU + +7C-BC-84 (hex) Tibit Communications +C00000-CFFFFF (base 16) Tibit Communications + 1 Willowbrook Court, Suite 150 + Petaluma CA 94954 + US + +7C-BC-84 (hex) CONTINENTAL +400000-4FFFFF (base 16) CONTINENTAL + 1 AVENUE PAUL OURLIAC + TOULOUSE 31100 + FR + +7C-BC-84 (hex) 3S Technology Co., Ltd. +200000-2FFFFF (base 16) 3S Technology Co., Ltd. + 301-1103, 345, Seokcheon-ro + Bucheon-si Gyeonggi-do 14501 + KR + +7C-BC-84 (hex) AG Neovo +000000-0FFFFF (base 16) AG Neovo + 5F-1, No. 3-1, Park Street, Nangang District, Taipei, 11503, Taiwan + Taipei 11503 + TW + +98-F9-C7 (hex) Beijing Horizon Information Technology Co., Ltd +300000-3FFFFF (base 16) Beijing Horizon Information Technology Co., Ltd + 3F,Unit H, West Gate, Hailong Mansion, No.1 Zhongguancun Street, Haidian District + Beijing 100080 + CN + +9C-43-1E (hex) HAESUNG DS +200000-2FFFFF (base 16) HAESUNG DS + 8F, Haesung 2 Building, 508, Teheran-ro, Gangnam-gu + Seoul 06178 + KR + +0C-FE-5D (hex) Maksat Technologies P Ltd +D00000-DFFFFF (base 16) Maksat Technologies P Ltd + D-10/6, Okhla, Phase-I, Okhla + New Delhi Delhi 110020 + IN + +98-F9-C7 (hex) ShenZhen Chuangwei Electronic Appliance Co.,Ltd +C00000-CFFFFF (base 16) ShenZhen Chuangwei Electronic Appliance Co.,Ltd + 4F & 6F, Overseas plant south, Skyworth Industrial Park, Shiyan Street, Bao'an District, + Shenzhen Guangdong 518101 + CN + +98-F9-C7 (hex) HIROIA Communications Pte. Ltd. Taiwan Branch +B00000-BFFFFF (base 16) HIROIA Communications Pte. Ltd. Taiwan Branch + 7F., No.189, Xinhu 3rd Rd., Neihu Dist., + Taipei City 11494 + TW + +0C-FE-5D (hex) Celerway Communication AS +900000-9FFFFF (base 16) Celerway Communication AS + Martin Lingesvei 25 + Fornebu 1364 + NO + +0C-FE-5D (hex) Fender Musical Instrument +100000-1FFFFF (base 16) Fender Musical Instrument + 17600 N Perimeter DR #100 + Scottsdale AZ 85255 + US + +0C-FE-5D (hex) YINUO-LINK LIMITED +B00000-BFFFFF (base 16) YINUO-LINK LIMITED + 5 Floor, Chuangyecheng,Xinghua Road,Xingwei,Fuyong + Shenzhen Guangdong 518103 + CN + +80-0A-80 (hex) Private +F00000-FFFFFF (base 16) Private + +C0-D3-91 (hex) Private +B00000-BFFFFF (base 16) Private + +1C-FD-08 (hex) MESHBOX FOUNDATION PTE. LTD. +E00000-EFFFFF (base 16) MESHBOX FOUNDATION PTE. LTD. + 152 Beach Road #14-02 GATEWAY EAST TOWER + SINGAPORE 189721 + SG + +1C-FD-08 (hex) Tianjin Keyvia Electric Co.,Ltd +D00000-DFFFFF (base 16) Tianjin Keyvia Electric Co.,Ltd + No.15 HaitaiFazhanErlu Road, Binhai Hi-tech Industrial Huayuan Development Area(Outer Ring) + Tianjin Tianjin 300392 + CN + +1C-FD-08 (hex) Shanghai YottaTech Co Ltd (上海尧它科技有限公司) +C00000-CFFFFF (base 16) Shanghai YottaTech Co Ltd (上海尧它科技有限公司) + 399 keyuan Rd, Pudong New District + Shanghai 201203 + CN + +1C-FD-08 (hex) Banmak Technogies Co.,Ltd +A00000-AFFFFF (base 16) Banmak Technogies Co.,Ltd + 302, Building R3-B, High-Tech Park + Shenzhen Guangdong 518057 + CN + +1C-FD-08 (hex) Shenzhen SEWO Technology Co.,Ltd. +100000-1FFFFF (base 16) Shenzhen SEWO Technology Co.,Ltd. + Busha Road No 231. Buji Street. Longgang District. + Shenzhen Guangdong 518112 + CN + +6C-5C-3D (hex) Vertiv Industrial Systems +200000-2FFFFF (base 16) Vertiv Industrial Systems + 30 avenue Montgolfier + Chassieu 69684 + FR + +6C-5C-3D (hex) KWONG MING ELECTRICAL MANUFACTORY LIMITED +300000-3FFFFF (base 16) KWONG MING ELECTRICAL MANUFACTORY LIMITED + A3 bldg, Kwong Ming, Technology Industrial Zone, Shiwan Town, Boluo County + Huizhou Guangdong 516100 + CN + +B8-D8-12 (hex) Private +F00000-FFFFFF (base 16) Private + +A8-3F-A1 (hex) Imecon Engineering SrL +000000-0FFFFF (base 16) Imecon Engineering SrL + via Gerola 13/15 + Fiesco CR 26010 + IT + +A8-3F-A1 (hex) Shenzhen ITLONG Intelligent Technology Co.,Ltd +900000-9FFFFF (base 16) Shenzhen ITLONG Intelligent Technology Co.,Ltd + 12th floor, Building C1, Nanshan Zhiyuan, 1001 Xueyuan Avenue , Nanshan District + Shenzhen Guangdong 518055 + CN + +3C-6A-2C (hex) WICKS Co., Ltd. +900000-9FFFFF (base 16) WICKS Co., Ltd. + 202,1-29 shingi takasu + kochi City Kochi 781-8103 + JP + +A8-3F-A1 (hex) Sercomm Corporation. +500000-5FFFFF (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +30-0A-60 (hex) AVIC JONHON OPTRONIC TECHNOLOGY CO., LTD. +400000-4FFFFF (base 16) AVIC JONHON OPTRONIC TECHNOLOGY CO., LTD. + Zhoushan Road10,Jianxi District,Luoyang City + Luoyang City Henan Province 471003 + CN + +30-0A-60 (hex) Bronkhorst High-Tech BV +800000-8FFFFF (base 16) Bronkhorst High-Tech BV + Nijverheidsstraat 1a + Ruurlo Gelderland NL-7261AK + NL + +A4-ED-43 (hex) Paragon Business Solutions Ltd. +B00000-BFFFFF (base 16) Paragon Business Solutions Ltd. + 303-5th Avenue, Suite # 1007 + New York 10016 + US + +A4-ED-43 (hex) Shanghai Mission Information Technologies (Group) Co.,Ltd +200000-2FFFFF (base 16) Shanghai Mission Information Technologies (Group) Co.,Ltd + Room 803, modern traffic building (East District), 218 Hengfeng Road, Jingan District + Shanghai 200041 + CN + +A4-ED-43 (hex) Sweam AB +000000-0FFFFF (base 16) Sweam AB + Kistagången 12 + Kista Stockholm 16440 + SE + +A0-28-33 (hex) Precision Planting, LLC. +E00000-EFFFFF (base 16) Precision Planting, LLC. + 23207 Townline Rd. + Tremont IL 61568 + US + +84-89-EC (hex) SmartGiant Technology +000000-0FFFFF (base 16) SmartGiant Technology + 1 North Zhong Jia Zhuang, Shi Gang Dong, Da Long Street + Guangzhou Guangdong 510000 + CN + +84-89-EC (hex) Zephyr Engineering, Inc. +500000-5FFFFF (base 16) Zephyr Engineering, Inc. + 2412 W. Huntington Dr. + Tempe AZ 85282 + US + +84-89-EC (hex) Aerionics Inc. +300000-3FFFFF (base 16) Aerionics Inc. + 3601 N St Paul Avenue + Sioux Falls SD 57104 + US + +A0-28-33 (hex) FlexLink AB +B00000-BFFFFF (base 16) FlexLink AB + BYFOGDEGATAN 11 + GOTEBORG 41505 + SE + +68-91-D0 (hex) Ambitio LLC +300000-3FFFFF (base 16) Ambitio LLC + 10505 NW 27th ST + Doral FL 33172 + US + +D4-7C-44 (hex) Sammi Onformation Systems +400000-4FFFFF (base 16) Sammi Onformation Systems + Gasan Digital 1-ro 212 + Geumcheon-gu Seoul 08502 + KR + +9C-F6-DD (hex) Shenzhen Xtooltech Co., Ltd +600000-6FFFFF (base 16) Shenzhen Xtooltech Co., Ltd + 10574 Acacia St, Suite D4 + Rancho Cucamonga CA 91730 + US + +78-C2-C0 (hex) Ory Laboratory Co., Ltd. +400000-4FFFFF (base 16) Ory Laboratory Co., Ltd. + 502 Bravi Mitaka, 1-3-11 Nishikubo + Musashino-shi Tokyo 180-0013 + JP + +30-09-F9 (hex) Beijing Netswift Technology Co.,Ltd. +200000-2FFFFF (base 16) Beijing Netswift Technology Co.,Ltd. + No. 7, 7th floor, No.49 Zhichun Road, Haidian District + Beijing Beijing 100190 + CN + +30-09-F9 (hex) Bonraybio +900000-9FFFFF (base 16) Bonraybio + 4F., No.118, Gongye 9th Rd., Dali Dist., + Taichung City Taiwan 412 + TW + +30-09-F9 (hex) Hurray Cloud Technology Co., Ltd. +000000-0FFFFF (base 16) Hurray Cloud Technology Co., Ltd. + 7F., No.407, Sec. 2, Zhongshan Rd., Zhonghe Dist., + New Taipei City 235 + TW + +84-89-EC (hex) Shenzhen Xtooltech Co., Ltd +900000-9FFFFF (base 16) Shenzhen Xtooltech Co., Ltd + 10574 Acacia St, Suite D4 + Rancho Cucamonga CA 91730 + US + +C0-83-59 (hex) ANTS +400000-4FFFFF (base 16) ANTS + 88, Simindae-ro, Dongan-Gu + Anyang 14079 + KR + +C0-83-59 (hex) Gemvax Technology ,. Co.Ltd +100000-1FFFFF (base 16) Gemvax Technology ,. Co.Ltd + 30, Techno1-ro, Yuseong-gu, Daejeon + Daejeon 34016 + KR + +9C-F6-DD (hex) Foshan Synwit Technology Co.,Ltd. +D00000-DFFFFF (base 16) Foshan Synwit Technology Co.,Ltd. + Room 501, Building 10, Leaguar Science Park, Shishan town, Nanhai + FoShan Guangdong 528225 + CN + +04-C3-E6 (hex) DREAMKAS LLC +000000-0FFFFF (base 16) DREAMKAS LLC + Bolshoy Sampsoniyevskiy pr., 62A, office 2H + Saint-Petersburg 194044 + RU + +04-C3-E6 (hex) SHANTOU YINGSHENG IMPORT & EXPORT TRADING CO.,LTD. +C00000-CFFFFF (base 16) SHANTOU YINGSHENG IMPORT & EXPORT TRADING CO.,LTD. + Chenghua Industrial Zone,Wenguan Road,Chenghai District + Shantou City Guangdong 515800 + CN + +3C-42-7E (hex) Edit Srl +600000-6FFFFF (base 16) Edit Srl + Via Grotte di Nottola 10 + Cisterna di Latina Latina 04012 + IT + +3C-42-7E (hex) UBTECH ROBOTICS CORP +800000-8FFFFF (base 16) UBTECH ROBOTICS CORP + 22 Floor, Block C1, Nanshan I Park, No. 1001 Xueyuan Road, Nanshan District, + Shenzhen guangdong 518071 + CN + +A0-C5-F2 (hex) Quantlab Financial, LLC +000000-0FFFFF (base 16) Quantlab Financial, LLC + 3 Greenway Plaza, Suite 200 + 3 Greenway Plaza TX 77046 + US + +B4-4B-D6 (hex) ShenZhen Comstar Technology Company +500000-5FFFFF (base 16) ShenZhen Comstar Technology Company + Pengnian Science Park Building A 314 + Shenzhen Guangdong 518040 + CN + +B4-4B-D6 (hex) Shenzhen Cudy Technology Co., Ltd. +200000-2FFFFF (base 16) Shenzhen Cudy Technology Co., Ltd. + The Great Wall Building,No3 Kefa Road + Shenzhen Guangdong 518000 + CN + +B4-4B-D6 (hex) ELLETA SOLUTIONS LTD +D00000-DFFFFF (base 16) ELLETA SOLUTIONS LTD + Yetsi'at Eropa Street 20 + Hadera 3848427 + IL + +3C-42-7E (hex) Compal Electronics INC. +B00000-BFFFFF (base 16) Compal Electronics INC. + No.8 , Nandong Road , PingZhen Dist. + Taoyuan Taiwan 32455 + TW + +A0-19-B2 (hex) SZBROAD TECHNOLOGY (HK) CO.,LTMITED +500000-5FFFFF (base 16) SZBROAD TECHNOLOGY (HK) CO.,LTMITED + FLAT/RM 5 BLK B 14/F WAH HEN COMMERCIAL CENTRE + 383 HENNESSY ROAD WANCHAI Hong Kong 00000 + HK + +A0-19-B2 (hex) El Sewedy Electrometer Egypt S.A.E. +100000-1FFFFF (base 16) El Sewedy Electrometer Egypt S.A.E. + Plot No. 154/173 Industrial Zone 2 + ET-6th October City + EG + +2C-48-35 (hex) Collatz+Trojan GmbH +A00000-AFFFFF (base 16) Collatz+Trojan GmbH + Borsteler Chaussee85-99a + Hamburg Hamburg 22453 + DE + +8C-1C-DA (hex) Raychem RPG PVT. LTD. +900000-9FFFFF (base 16) Raychem RPG PVT. LTD. + Safari Crossing, Near Halol GIDC, Village - Kanjari, Taluka - Halol + Halol Gujarat 389350 + IN + +8C-1C-DA (hex) ATOL LLC +800000-8FFFFF (base 16) ATOL LLC + Bolshaya Novodmitrovskaya str., 14, build 4 + Moscow 127015 + RU + +2C-48-35 (hex) GEARTECH LTD +400000-4FFFFF (base 16) GEARTECH LTD + R310/312,3/F,Beike Venture Building,No.1077,Nanhai Avenue,Nanshan District + Shenzhen Guangdong 518067 + CN + +3C-24-F0 (hex) Shenzhen Bestway Technology Co., Ltd +A00000-AFFFFF (base 16) Shenzhen Bestway Technology Co., Ltd + 2nd Floor, Building 9, Jingxuan Industrial Park, East Ring Road, Longhua District, + Shenzhen GuangDong 518109 + CN + +3C-24-F0 (hex) GETMOBIT LLC +E00000-EFFFFF (base 16) GETMOBIT LLC + d. 4 str. 2 pom. 137, ul. Programmistov + Dubna Moscow 141983 + RU + +8C-1C-DA (hex) Structura Technology & Innovation +300000-3FFFFF (base 16) Structura Technology & Innovation + via Roveredo 20/B + Pordenone PN 33170 + IT + +8C-1C-DA (hex) GESAS GmbH +100000-1FFFFF (base 16) GESAS GmbH + Pfaelzer Ring 18 + Hockenheim Baden-Wuerttemberg 68766 + DE + +3C-24-F0 (hex) Authentico Technologies +C00000-CFFFFF (base 16) Authentico Technologies + Erikdahlbergsgatan 4 + Göteborg 41126 + SE + +8C-1C-DA (hex) T+A elektroakustik GmbH & Co.KG +B00000-BFFFFF (base 16) T+A elektroakustik GmbH & Co.KG + Planckstr. 9-11 + Herford 32052 + DE + +48-0B-B2 (hex) BAJA ELECTRONICS TECHNOLOGY LIMITED +100000-1FFFFF (base 16) BAJA ELECTRONICS TECHNOLOGY LIMITED + 403, Unit 3, Building 3, Zhongdian Hi-Tech Park, No.1 Kejiqi Rd. + Zhuhai Guangdong 519080 + CN + +48-0B-B2 (hex) M2Lab Ltd. +D00000-DFFFFF (base 16) M2Lab Ltd. + 148 Des Voeux Rd Central + Hong Kong HK + HK + +48-0B-B2 (hex) Ridango AS +000000-0FFFFF (base 16) Ridango AS + Pärnu maantee 139E/13 + Tallinn Harjumaa 11317 + EE + +48-0B-B2 (hex) Beijing MFOX technology Co., Ltd. +E00000-EFFFFF (base 16) Beijing MFOX technology Co., Ltd. + B zone,floor 2,NO.A5 east Rongchang street .BDA (yizhuang) BeiJing + BeiJing BeiJing 100176 + CN + +0C-73-EB (hex) Husty M.Styczen J.Hupert Sp.J. +500000-5FFFFF (base 16) Husty M.Styczen J.Hupert Sp.J. + Rzepakowa 5e + Krakow malopolska 31-989 + PL + +0C-73-EB (hex) Gemini Data Loggers (UK) Limited +000000-0FFFFF (base 16) Gemini Data Loggers (UK) Limited + Scientific House, Terminus Road + Chichester West Sussex PO19 8UJ + GB + +88-5F-E8 (hex) Lisle Design Ltd +A00000-AFFFFF (base 16) Lisle Design Ltd + New Technology Centre, North Haugh + St. Andrews Fife KY16 9SR + GB + +30-1F-9A (hex) YiSheng technology co.,LTD +600000-6FFFFF (base 16) YiSheng technology co.,LTD + Xintian road no:71, F#202 + shenzhen baoan 518103 + CN + +88-5F-E8 (hex) Shenzhen Xin Kingbrand Enterprises Co.,Ltd +600000-6FFFFF (base 16) Shenzhen Xin Kingbrand Enterprises Co.,Ltd + KingBrand Industrial Zone, Nanpu Road,Shang Liao Lin Pikeng,Shajing Town,Baoan District + Shenzhen 518000 + CN + +2C-D1-41 (hex) Beijing Hexing Chuangxiang Technology Co., Ltd. +900000-9FFFFF (base 16) Beijing Hexing Chuangxiang Technology Co., Ltd. + 1306,A block,No.6 Zhichun Road + Haidian District, Beijing 100088 + CN + +30-1F-9A (hex) OLIMEX Ltd +D00000-DFFFFF (base 16) OLIMEX Ltd + 2 Pravda + Plovidv 4000 + BG + +88-5F-E8 (hex) Jungheinrich Norderstedt AG & Co. KG +000000-0FFFFF (base 16) Jungheinrich Norderstedt AG & Co. KG + Lawaetzstr. 9-13 + Norderstedt 22844 + DE + +88-5F-E8 (hex) Opto Engineering +200000-2FFFFF (base 16) Opto Engineering + Circonvallazione Sud, 15 + Mantova 46100 + IT + +30-1F-9A (hex) Private +900000-9FFFFF (base 16) Private + +F0-41-C8 (hex) Shenzhen Nufilo Electronic Technology Co., Ltd. +900000-9FFFFF (base 16) Shenzhen Nufilo Electronic Technology Co., Ltd. + Tianliao Building West Unit F1315, (New Materials Industrial Park), Xueyuan Road, Nanshan District + Shenzhen Guangdong 518055 + CN + +F0-41-C8 (hex) Nanchang BlackShark Co.,Ltd. +700000-7FFFFF (base 16) Nanchang BlackShark Co.,Ltd. + Room 319, Jiaoqiao Town Office Building, Economic and Technical development zone, Nanchang City, Jiangxi Province. + Nanchang 330013 + CN + +88-A9-A7 (hex) Impact Distribution +E00000-EFFFFF (base 16) Impact Distribution + Ter Heidelaan 50a + Aarschot 3200 + BE + +88-A9-A7 (hex) psb intralogistics GmbH +800000-8FFFFF (base 16) psb intralogistics GmbH + Blocksbergstrasse 145 + Pirmasens 66955 + DE + +F0-41-C8 (hex) AED Engineering GmbH +600000-6FFFFF (base 16) AED Engineering GmbH + Taunusstr. 51 + Munich Bavaria 80807 + DE + +88-A9-A7 (hex) Solaredge LTD. +100000-1FFFFF (base 16) Solaredge LTD. + Hamada 1 + Herzelia 4673335 + IL + +A4-DA-22 (hex) General Electric Company +000000-0FFFFF (base 16) General Electric Company + Valle del Cedro #1551 + Ciudad Juarez Chih 32575 + MX + +88-A9-A7 (hex) kimura giken corporation +700000-7FFFFF (base 16) kimura giken corporation + 4-9-19 kamiyoga + Setagaya-ku Tokyo 158-0098 + JP + +A4-DA-22 (hex) Wyze Labs Inc +200000-2FFFFF (base 16) Wyze Labs Inc + 22522 29TH DR SE L101 + BOTHELL WA 98021 + US + +A4-DA-22 (hex) Quuppa Oy +E00000-EFFFFF (base 16) Quuppa Oy + Keilaranta 1 + Espoo 02150 + FI + +9C-43-1E (hex) ST Access Control System Corp. +A00000-AFFFFF (base 16) ST Access Control System Corp. + 3F., No. 111 Zhongzheng Rd., Banciao Dist., New Taipei City + New Taipei City 22054 + TW + +DC-E5-33 (hex) Controls Inc +500000-5FFFFF (base 16) Controls Inc + 5204 Portside Drive + Medina OH 44256 + US + +C4-FF-BC (hex) Danego BV +000000-0FFFFF (base 16) Danego BV + Protonenlaan 24 + Uden NB 5405 NE + NL + +C4-FF-BC (hex) Critical Link +700000-7FFFFF (base 16) Critical Link + 6712 Brooklawn Parkway + Syracuse null 13211 + US + +28-2C-02 (hex) Shenzhen Neoway Technology Co.,Ltd. +800000-8FFFFF (base 16) Shenzhen Neoway Technology Co.,Ltd. + 4F-2#,Lian Jian Science & Industry Park,Huarong Road,Dalang Street,Longhua District + Shenzhen Guangdong 518000 + CN + +28-2C-02 (hex) Capintec, Inc. +E00000-EFFFFF (base 16) Capintec, Inc. + 7 Vreeland Road + Florham Park NJ 07932 + US + +28-2C-02 (hex) SHENZHEN DOMENOR TECHNOLOGY LLC +D00000-DFFFFF (base 16) SHENZHEN DOMENOR TECHNOLOGY LLC + F4, BUILDING A3, SILICON VALLEY POWER TECHNOLOGY PARK, SILI ROAD, KUKENG COMMUNITY, GUANLAN TOWN,LONGHUA DISTRICT + SHENZHEN GUANGDONG 518110 + CN + +F8-B5-68 (hex) Solarius +D00000-DFFFFF (base 16) Solarius + Kaeshaldenstrasse 39 + Zurich 8052 + CH + +28-2C-02 (hex) Astronics AES +100000-1FFFFF (base 16) Astronics AES + 12950 Willows Rd NE + Kirkland WA 98034 + US + +F8-B5-68 (hex) Package Guard, Inc +600000-6FFFFF (base 16) Package Guard, Inc + 2819 33rd ave so + seattle WA 98144 + US + +18-9B-A5 (hex) Innominds Software Inc +400000-4FFFFF (base 16) Innominds Software Inc + 2055 Junction Ave Suite 122, San Jose CA 95131 + San Jose CA 95131 + US + +40-48-FD (hex) Shenzhen Yifang Digital Technology Co., LTD. +A00000-AFFFFF (base 16) Shenzhen Yifang Digital Technology Co., LTD. + Building NO. 23, Fifth Region, Baiwangxin Industrial Park, Songbai Rd. Nanshan, Shenzhen + Shenzhen 518108 + CN + +38-73-EA (hex) Shanghai ZoomSmart Technology Co., Ltd. +B00000-BFFFFF (base 16) Shanghai ZoomSmart Technology Co., Ltd. + ROOM 802, No. 189, Hengxi Road, Pujiang Town, Minhang District, Shanghai PRC + Shanghai 200000 + CN + +EC-9F-0D (hex) MAX Technologies +E00000-EFFFFF (base 16) MAX Technologies + 2051 Victoria Av. + St-Lambert Quebec J4S1H1 + CA + +38-73-EA (hex) KingWay Information Co.,Ltd. +100000-1FFFFF (base 16) KingWay Information Co.,Ltd. + 3/F Rongxin business organization #56 Jinyan Road + Fuzhou Fujian 350000 + CN + +EC-9F-0D (hex) Waverly Labs Inc. +300000-3FFFFF (base 16) Waverly Labs Inc. + 19 Morris Avenue + Brooklyn NY 11205 + US + +34-D0-B8 (hex) Kongqiguanjia (Beijing)Technology co.,ltd +E00000-EFFFFF (base 16) Kongqiguanjia (Beijing)Technology co.,ltd + Room 1201,Block A,Building of Fesco,Xidawang Road,Chaoyang district + Beijing Beijing 100022 + CN + +34-D0-B8 (hex) NumberFour AG +600000-6FFFFF (base 16) NumberFour AG + Schoenhauser Allee 8 + Berlin 10119 + DE + +EC-9F-0D (hex) DRB Systems +200000-2FFFFF (base 16) DRB Systems + 3245 Pickle Road + Akron OH 44312 + US + +EC-9F-0D (hex) SKS Control Oy +D00000-DFFFFF (base 16) SKS Control Oy + Martinkyläntie 50 + Vantaa 01720 + FI + +AC-1D-DF (hex) PiOctave Solutions Pvt Ltd +000000-0FFFFF (base 16) PiOctave Solutions Pvt Ltd + #1217, Ground Floor,4th Cross Road, 1st Block, HAL 3rd Stage + BENGALURU KARNATAKA 560 075 + IN + +AC-1D-DF (hex) Duravit AG +E00000-EFFFFF (base 16) Duravit AG + Werderstr. 36 + Hornberg Baden Wuerttemberg 78132 + DE + +34-D0-B8 (hex) Shenzhen Rikomagic Tech Corp.,Ltd +700000-7FFFFF (base 16) Shenzhen Rikomagic Tech Corp.,Ltd + 7021,7F Beifang Junyi Business Center, Lixin South RD,Fuyong Street,Bao'an + Shenzhen Guangdong 518103 + CN + +AC-1D-DF (hex) Beijing Chunhong Technology Co., Ltd. +C00000-CFFFFF (base 16) Beijing Chunhong Technology Co., Ltd. + Room1502 Hailong Plaza, Zhongguancun, Haidian, Beijing + Beijing 100000 + CN + +34-D0-B8 (hex) Shenzhen Bao Lai Wei Intelligent Technology Co., L +100000-1FFFFF (base 16) Shenzhen Bao Lai Wei Intelligent Technology Co., L + Longgang Street Baolong Wu Road on the 2nd + Shenzhen Guangdong Province 518116 + CN + +74-1A-E0 (hex) SHEN ZHEN YINGJIACHUANG ELECTRONICS TECHNOLOGY CO.,LTD. +B00000-BFFFFF (base 16) SHEN ZHEN YINGJIACHUANG ELECTRONICS TECHNOLOGY CO.,LTD. + Building A,Baishunjia Industrial Park,Guangming New District + Shenzhen 518107 + CN + +74-1A-E0 (hex) Philips Personal Health Solutions +300000-3FFFFF (base 16) Philips Personal Health Solutions + High Tech Campus, HTC37 floor 0 + Eindhoven 5656 AE + NL + +AC-1D-DF (hex) Shenzheng SenseTime Technology Co. Ltd +600000-6FFFFF (base 16) Shenzheng SenseTime Technology Co. Ltd + 7F,Haixiang plaza, No.1052 Nanhai Road, Nanshan district + Shenzhen Guangdong 518000 + CN + +CC-22-37 (hex) Beijing Safesoft Greatmaker Co.,ltd +500000-5FFFFF (base 16) Beijing Safesoft Greatmaker Co.,ltd + Room 501 ,Unit. D, Jinyujiahua Building ,No. 9 ,Shangdi Three Street , Haidian District + Beijing 100144 + CN + +CC-22-37 (hex) Siemens AG Austria +600000-6FFFFF (base 16) Siemens AG Austria + Siemensstrasse 90 + Wien A-1210 + AT + +CC-22-37 (hex) Shanghai Doit IOT Technology Co.,Ltd. +700000-7FFFFF (base 16) Shanghai Doit IOT Technology Co.,Ltd. + 410-412 rooms of 1B business building in NO.1588 ,lianhang road, minhang district + Shanghai 201100 + CN + +CC-22-37 (hex) MEDCOM sp. z o.o. +000000-0FFFFF (base 16) MEDCOM sp. z o.o. + ul. Jutrzenki 78a + Warszawa woj. mazowieckie 02-230 + PL + +90-4E-91 (hex) Shenzhen Cloudynamo Internet Technologies Co.,LTD. +E00000-EFFFFF (base 16) Shenzhen Cloudynamo Internet Technologies Co.,LTD. + NO.502 lingyun Building honglang north second road + shenzhen 518000 + CN + +90-4E-91 (hex) CommandScape, Inc. +800000-8FFFFF (base 16) CommandScape, Inc. + 505 South Flagler Dr, Suite 900 + West Palm Beach FL 33401 + US + +90-4E-91 (hex) Kaertech Limited +A00000-AFFFFF (base 16) Kaertech Limited + Unit 1601, 21-24 Connaught Road West + Hong Kong Sheung Wan 00000 + HK + +18-9B-A5 (hex) Mantra Softech India Pvt Ltd +600000-6FFFFF (base 16) Mantra Softech India Pvt Ltd + B203, Shapath Hexa, S.G. Highway, Sola, + Ahmedabad Gujarat 380060 + IN + +18-9B-A5 (hex) Eutron SPA +B00000-BFFFFF (base 16) Eutron SPA + Via Crespi 29/31 + Pradalunga Bergamo 24020 + IT + +2C-27-9E (hex) WAYCOM Technology Co.,Ltd +C00000-CFFFFF (base 16) WAYCOM Technology Co.,Ltd + E-605,BLDG 201,A10 Jiuxianqiao North Road Chaoyang District,Beijing 100015,China + Beijing 100000 + CN + +34-29-8F (hex) ARC Technology Co., Ltd +E00000-EFFFFF (base 16) ARC Technology Co., Ltd + 4F.-2, No.26, Wuquan 2nd Road, + Xinzhuang District, New Taipei City 24892 + TW + +34-00-8A (hex) Federal Aviation Administration +500000-5FFFFF (base 16) Federal Aviation Administration + Atlantic City Int'l Airport, Bldg. 270 + Atlantic City NJ 08405 + US + +34-29-8F (hex) BlackEdge Capital +000000-0FFFFF (base 16) BlackEdge Capital + 801 West Adams Street, Suite 500 + Chicago 60607 + US + +34-00-8A (hex) Sithon Technologies SAS +600000-6FFFFF (base 16) Sithon Technologies SAS + 115 Rue Claude Chappe + Plouzane 29280 + FR + +34-29-8F (hex) Dongguan Kingtron Electronics Tech Co., Ltd +700000-7FFFFF (base 16) Dongguan Kingtron Electronics Tech Co., Ltd + No.3 Fumin North Rd,Shu'an Industrial Park, Humen Town + Dongguan Guangdong China 523929 + CN + +18-9B-A5 (hex) Airprotec +200000-2FFFFF (base 16) Airprotec + Avenue de l'Industrie 22 + Braine-l'Alleud 1420 + BE + +34-00-8A (hex) Globex 99 LTD +300000-3FFFFF (base 16) Globex 99 LTD + Trakia bl. 240 + Plovdiv 4000 + BG + +0C-EF-AF (hex) Hubei Century Network Technology Co., Ltd +B00000-BFFFFF (base 16) Hubei Century Network Technology Co., Ltd + 9-11th floor, B7, FinancialHarbour, NO.77, Guanggu Avenue, East Lake New Technology Development Zone + Wuhan Hubei 430074 + CN + +34-00-8A (hex) ZQAM Communications +100000-1FFFFF (base 16) ZQAM Communications + 3F., No.6, Innovation Road II, Science Park, + Hsinchu 30076 + TW + +28-F5-37 (hex) Matricx Singapore Pte Ltd +C00000-CFFFFF (base 16) Matricx Singapore Pte Ltd + 2nd Flr. 2 Bldg., Detai Technology Industrial Park, Huarong Road No. 460, Dalang, Longhua district, + Shenzhen Guangdong 518000 + CN + +28-F5-37 (hex) Unicair Communication Tec Co., Ltd. +200000-2FFFFF (base 16) Unicair Communication Tec Co., Ltd. + 深圳市宝安区西乡航空路与顺昌路交汇处梧桐岛1号楼8楼 + ShenZhen 418100 + CN + +78-D8-00 (hex) Kverneland Group Mechatronics +000000-0FFFFF (base 16) Kverneland Group Mechatronics + Hoofdweg 1278 + Nieuw-Vennep Noord Holland NL-2153 LR + NL + +78-D8-00 (hex) Alango Technologies Ltd +600000-6FFFFF (base 16) Alango Technologies Ltd + Etgar 2, Carmel Biulding 1rd floor + Tirat Carmel Haifa 39100 + IL + +28-F5-37 (hex) Phyn LLC +400000-4FFFFF (base 16) Phyn LLC + 1855 Del Amo Blvd + Torrance CA 90501 + US + +78-D8-00 (hex) Shanghai Espacetime Technology Co.,Ltd. +200000-2FFFFF (base 16) Shanghai Espacetime Technology Co.,Ltd. + Room 1202-A ,NO.570 , Shengxia Road , Pudong + Shanghai 200120 + CN + +7C-BA-CC (hex) Maco Lighting Pty. Ltd. +200000-2FFFFF (base 16) Maco Lighting Pty. Ltd. + 5/9 Stockwell Place + Archerfield Queensland 4108 + AU + +7C-BA-CC (hex) Collinear Networks Inc. +800000-8FFFFF (base 16) Collinear Networks Inc. + 2901 Tasman Drive + Santa Clara CA 95054 + US + +78-D8-00 (hex) NimbeLink Corp +700000-7FFFFF (base 16) NimbeLink Corp + 3131 Fernbrook LN N, Ste 100 + Plymouth MN 55447 + US + +F8-8A-3C (hex) withus +900000-9FFFFF (base 16) withus + Rua Dr. Mario Sacramento Ed. Colombo II N22 + Aveiro 3810-106 + PT + +7C-BA-CC (hex) TGT Limited +000000-0FFFFF (base 16) TGT Limited + Flat/Rm 1003 10/F, Witty Commercial Building, 1A-1L Tung Choi Street, Hong Kong + HongKong 529060 + HK + +F8-8A-3C (hex) THK Co.,LTD. +D00000-DFFFFF (base 16) THK Co.,LTD. + 4-9-16 Higashikoujiya + Ota Tokyo 1440033 + JP + +F8-8A-3C (hex) EXCETOP TECHNOLOGY (BEIJING) CO., LTD. +C00000-CFFFFF (base 16) EXCETOP TECHNOLOGY (BEIJING) CO., LTD. + A03, 9th Floor, Horizon International Tower, No.6, Zhichun Road, Haidian District + Beijing 100191 + CN + +4C-65-A8 (hex) Qingping Technology (Beijing) Co., Ltd. +D00000-DFFFFF (base 16) Qingping Technology (Beijing) Co., Ltd. + Room 401, Block B, Fangheng Times Square, No. 10 Wangjing Street, Chaoyang District + Beijing 100102 + CN + +A0-C5-F2 (hex) Shenzhen Feima Robotics Technology Co.,Ltd +300000-3FFFFF (base 16) Shenzhen Feima Robotics Technology Co.,Ltd + 1/f,16 ,Zhiheng Industrial Park, Nantou Second Road, Nantou Street, Nanshan District + Shenzhen Guangdong 518000 + CN + +F0-23-B9 (hex) Raysgem Electronics and Technology Co.Ltd +200000-2FFFFF (base 16) Raysgem Electronics and Technology Co.Ltd + 4th Floor, Block2 HuafengIndustrial park for Oversea Students Baolong 1st Road Longgang + Shenzhen Guangdong 518118 + CN + +8C-14-7D (hex) Reynaers Aluminium +C00000-CFFFFF (base 16) Reynaers Aluminium + Oude Liersebaan 266 + Duffel 2570 + BE + +8C-14-7D (hex) Remotec Technology Limited +300000-3FFFFF (base 16) Remotec Technology Limited + FLAT/RM 2 , BLK 2 , 2/F , TONIC INDUSTRIAL CENTRE , 19 LAM HING STREET , KOWLOON BAY + HONG KONG 00000 + HK + +8C-14-7D (hex) V2 S.p.A. +800000-8FFFFF (base 16) V2 S.p.A. + Corso Principi di Piemonte 65/67 + Racconigi Cuneo 12035 + IT + +A0-C5-F2 (hex) ShenZhen JuWangShi Tech +600000-6FFFFF (base 16) ShenZhen JuWangShi Tech + Room 1701 Unit B2,Kexing Science Park,Keyuan Road + ShenZhen NanShan 518057 + CN + +A0-C5-F2 (hex) Spacepath Communications Ltd +500000-5FFFFF (base 16) Spacepath Communications Ltd + Unit 4, Bartley Point, Osborn Way + Hook, Hampshire RG27 9GX + GB + +8C-14-7D (hex) Agilent S.p.A +200000-2FFFFF (base 16) Agilent S.p.A + Via.flli Varian 54 + Leini Torino 10040 + IT + +8C-14-7D (hex) UrbanHello +700000-7FFFFF (base 16) UrbanHello + 13 rue Saint Antoine + Paris 75004 + FR + +F0-23-B9 (hex) Transcend Building Automation control network corporation +700000-7FFFFF (base 16) Transcend Building Automation control network corporation + 15F. No.145 Ren’ai Rd. Xizhi Dist. + New Taipei City Taiwan 22164 + TW + +04-71-4B (hex) Armstrong Fluid Technology +600000-6FFFFF (base 16) Armstrong Fluid Technology + 23 Bertrand Avenue + Toronto Ontario M1L2P3 + CA + +60-D7-E3 (hex) LongSung Technology (Shanghai) Co.,Ltd. +900000-9FFFFF (base 16) LongSung Technology (Shanghai) Co.,Ltd. + Room 606, Block B, Bldg. 1, No. 3000 Longdong Avenue., Zhangjiang Hi-Tech Park, Pudong District + ShangHai 201203 + CN + +04-71-4B (hex) Omylis Pte Ltd +700000-7FFFFF (base 16) Omylis Pte Ltd + 150, South Bridge Road #06-04B, Fook Hai Building + Singapore 058727 + SG + +60-D7-E3 (hex) Novo innovations Ltd +200000-2FFFFF (base 16) Novo innovations Ltd + Westwood way + Westwood business park Coventry Cv4 8lg + GB + +08-ED-02 (hex) SANGO ELECTRONICS CO +600000-6FFFFF (base 16) SANGO ELECTRONICS CO + RM 253,2/F,BLOCK A, CAMBRIDGE PLAZA,188,SANWAN ROAD, SHEUNG SHUI,HONG KONG + HongKong 518131 + CN + +08-ED-02 (hex) Jiangsu Logread Network Technology Co., LTD. +300000-3FFFFF (base 16) Jiangsu Logread Network Technology Co., LTD. + No. 100 # 9, Shu Gang West Road, HanJiang Area, + Yangzhou Jiangsu 225100 + CN + +08-ED-02 (hex) Vigitron Inc. +500000-5FFFFF (base 16) Vigitron Inc. + 7810 Trade Street, STE 100 + San Diego CA 92121 + US + +08-ED-02 (hex) Fio Corporation +400000-4FFFFF (base 16) Fio Corporation + 111 Queen Street East, Suite 500 + Toronto ON M5C 1S2 + CA + +08-ED-02 (hex) Victiana SRL +A00000-AFFFFF (base 16) Victiana SRL + Strada A. Hasdeu, nr. 66/3 + Chisinau MD-2001 + MD + +60-D7-E3 (hex) Phase One A/S +700000-7FFFFF (base 16) Phase One A/S + Roskildevej 39 + Frederiksberg 2000 + DK + +98-AA-FC (hex) Shenzhen Hubsan Technology Co.,LTD. +700000-7FFFFF (base 16) Shenzhen Hubsan Technology Co.,LTD. + Xuefu Road, Nanshan District, + 13th Floor, Bldg 1C, Shenzhen Software Industry Base, Xuefu Road, Nanshan District, Guangdong 518054 + CN + +98-AA-FC (hex) SPM Instrument AB +500000-5FFFFF (base 16) SPM Instrument AB + Box 504 + Strängnäs SE-64525 + SE + +A4-11-63 (hex) Viloc +C00000-CFFFFF (base 16) Viloc + Langestraat, 221 + Zandhoven België 2240 + BE + +1C-C0-E1 (hex) Nitto Seiko +C00000-CFFFFF (base 16) Nitto Seiko + shiroyama-cho 2banti + Ayabe-si Kyoto-hu 623-0003 + JP + +A4-11-63 (hex) Adetel Equipment +000000-0FFFFF (base 16) Adetel Equipment + 3200 rue guénette + Montréal Québec H4S 2G5 + CA + +A4-11-63 (hex) tinylogics +E00000-EFFFFF (base 16) tinylogics + St John's Innovation Centre, Cambridge + London CB4 0WS + GB + +A4-11-63 (hex) ISE GmbH +A00000-AFFFFF (base 16) ISE GmbH + Osterstrasse 15 + Oldenburg 26122 + DE + +A4-11-63 (hex) Allgo Tech. (Beijing) Co.,Ltd +200000-2FFFFF (base 16) Allgo Tech. (Beijing) Co.,Ltd + Room 6012 Innovation Building ,NO.101 Southwest of 4th Ring Road, Fengtai District + Beijing Beijing 100070 + CN + +14-4F-D7 (hex) Shenzhen V-Streaming Technology Co., Ltd. +700000-7FFFFF (base 16) Shenzhen V-Streaming Technology Co., Ltd. + Room610, LangShanGe Building, Yugu Hi-Tech Park, Liuxin Road 1183, Nanshan District + Shenzhen Guangdong 518000 + CN + +1C-A0-D3 (hex) LYT inc. +C00000-CFFFFF (base 16) LYT inc. + 440, North Wolfe Road + Sunnyvale CA 94085 + US + +1C-A0-D3 (hex) Desarrollos y Soluciones Guinea I+D S.L. +800000-8FFFFF (base 16) Desarrollos y Soluciones Guinea I+D S.L. + Avda. de los Trabajadores nº2 1ªPlanta + Illescas Toledo 45200 + ES + +A4-11-63 (hex) INTER CONTROL Hermann Köhler Elektrik GmbH & Co.KG +100000-1FFFFF (base 16) INTER CONTROL Hermann Köhler Elektrik GmbH & Co.KG + Schafhofstrasse 30 + Nuernberg 90411 + DE + +38-FD-FE (hex) New Garden Co., Ltd. +C00000-CFFFFF (base 16) New Garden Co., Ltd. + 2F, NO.58, Xingshan Rd., Neihu., + Taipei 114 + TW + +A4-11-63 (hex) AlterG, Inc. +400000-4FFFFF (base 16) AlterG, Inc. + 48438 Milmont Drive + Fremont CA 94538 + US + +1C-A0-D3 (hex) Jabil circuit italia srl +100000-1FFFFF (base 16) Jabil circuit italia srl + Via Giovanni Francesco Maggio' Agglomerato Industriale + marcianise caserta 81025 + IT + +1C-A0-D3 (hex) DSM Messtechnik GmbH +A00000-AFFFFF (base 16) DSM Messtechnik GmbH + Dieselstrasse 16 + Aalen Baden-Wuerttemberg 73431 + DE + +1C-A0-D3 (hex) ERATO (HK) Corporation Limited +D00000-DFFFFF (base 16) ERATO (HK) Corporation Limited + Unit P,8th floor, Kaiser Estate 3rd Phase, No,11 Hok Yuen Street, Hung Hom + Kowloon Hong Kong 999077 + HK + +58-E8-76 (hex) DivioTec Inc. +600000-6FFFFF (base 16) DivioTec Inc. + 19F-1A, No.97, Sec. 4, ChongXin Rd., San Chong Dist., + New Taipei 24161 + TW + +50-A4-D0 (hex) ZHENG DIAN ELECTRONICS LIMITED +B00000-BFFFFF (base 16) ZHENG DIAN ELECTRONICS LIMITED + 11 Xianghe Street, Xinmin, Changan + Dongguan Guangdong 523879 + CN + +50-A4-D0 (hex) Beijing ANTVR Technology Co., LTD +100000-1FFFFF (base 16) Beijing ANTVR Technology Co., LTD + 4th floor of Building C, Lenovo Beijing Innovation Center, No. 6 Shangdi West Rd., Haidian Distr., Beijing 100085, China + Beijing Beijing 100085 + CN + +40-F3-85 (hex) Lennox International Incorporated +600000-6FFFFF (base 16) Lennox International Incorporated + 1600 Metrocrest Drive + Carrollton TX 75006 + US + +80-7B-85 (hex) Chendu Ningshui Technology Co.,Ltd +700000-7FFFFF (base 16) Chendu Ningshui Technology Co.,Ltd + Baiyun Road ,xindu District ,ChengDu city, Sichuan Province ,China + Chengdu Sichuan 610500 + CN + +40-F3-85 (hex) Fast Precision Technologies Co. Ltd. +900000-9FFFFF (base 16) Fast Precision Technologies Co. Ltd. + 4th Floor, Yang Tian Bldg., Chuang Ye Er Road & Yang Tian Road, Bao An District + Shenzhen Guangdong 518101 + CN + +50-A4-D0 (hex) Seneco A/S +200000-2FFFFF (base 16) Seneco A/S + Bøgekildevej 4 + Hasselager Danmark 8361 + DK + +34-04-9E (hex) Pebble Technology +700000-7FFFFF (base 16) Pebble Technology + 900 Middlefield Road, Floor 5 + Redwood City CA 94063 + US + +50-A4-D0 (hex) PointGrab +600000-6FFFFF (base 16) PointGrab + 4 Haharash Str + Hod Hasharon 45240 + IL + +34-04-9E (hex) EFD Induction +200000-2FFFFF (base 16) EFD Induction + Boleveien 10 + skien 3724 + NO + +34-04-9E (hex) i3 International Inc. +A00000-AFFFFF (base 16) i3 International Inc. + 780 Birchmount Road + Scarborough Ontario M1K5H4 + CA + +A4-58-0F (hex) BLOKS. GmbH +200000-2FFFFF (base 16) BLOKS. GmbH + Agnes-Pockels-Bogen 1 + Munich 80992 + DE + +A4-58-0F (hex) INNOPRO +000000-0FFFFF (base 16) INNOPRO + Building 33, Dahe Industrial Zone, Huanguan South Rd., Guanlan Street, + ShenZhen GuangDong 518100 + CN + +40-ED-98 (hex) GUANGZHOU AURIC INTELLIGENT TECHNOLOGY CO.,LTD. +800000-8FFFFF (base 16) GUANGZHOU AURIC INTELLIGENT TECHNOLOGY CO.,LTD. + Room 209, No. 115, JiuFoJianShe Road, Sino-Singapore Guangzhou Knowledge City, Huangpu District, Guangzhou + Guangzhou Guangdong 510555 + CN + +40-ED-98 (hex) Knox Company +300000-3FFFFF (base 16) Knox Company + 1601 W DEER VALLEY RD + Phoenix AZ 85027-2112 + US + +40-ED-98 (hex) Kendrion Kuhnke Automation GmbH +400000-4FFFFF (base 16) Kendrion Kuhnke Automation GmbH + Luetjenburger Strasse 101 + Malente SH 23714 + DE + +50-0B-91 (hex) Machfu, Inc. +900000-9FFFFF (base 16) Machfu, Inc. + 20271 Goldenrod Ln + Germantown MD 20876 + US + +50-0B-91 (hex) jiangsu zhongling high-tech CO.,LTD. +500000-5FFFFF (base 16) jiangsu zhongling high-tech CO.,LTD. + NO.168 shugangdong road yangzhou city jiangsu china + yangzhou 225000 + CN + +50-0B-91 (hex) New Audio LLC +A00000-AFFFFF (base 16) New Audio LLC + 132 W 31st Street Suite 701 + New York NY 10001 + US + +7C-CB-E2 (hex) Shanghai Institute of Applied Physics, Chinese Academy of Sciences +A00000-AFFFFF (base 16) Shanghai Institute of Applied Physics, Chinese Academy of Sciences + 239 Zhang Heng Road, Pudong New District + Shanghai Shanghai 201203 + CN + +50-0B-91 (hex) SPD Development Company Ltd +100000-1FFFFF (base 16) SPD Development Company Ltd + Stannard Way, Priory Business Park + Bedford MK44 3UP + GB + +50-0B-91 (hex) thumbzup UK Limited +B00000-BFFFFF (base 16) thumbzup UK Limited + 6th Floor, 94 Wigmore Street + London W1U 3RF + GB + +48-65-EE (hex) VideoStitch, Inc +900000-9FFFFF (base 16) VideoStitch, Inc + 4677 Old Ironsides Dr, Suite 320 + Santa Clara CA 95054 + US + +48-65-EE (hex) CaptionCall +200000-2FFFFF (base 16) CaptionCall + 4215 Riverboat Road + Salt Lake City UT 84123 + US + +24-4E-7B (hex) Cyber1st +800000-8FFFFF (base 16) Cyber1st + Meteor Centre, Mansfield Road + Derby Derbyshire DE21 4SY + GB + +24-4E-7B (hex) Owasys Advanced Wireless Devices +600000-6FFFFF (base 16) Owasys Advanced Wireless Devices + Parque Tecnologico, 207-B + Zamudio Vizcaya E-48170 + ES + +48-65-EE (hex) Shenzhen Inpor cloud Computing Co., Ltd. +A00000-AFFFFF (base 16) Shenzhen Inpor cloud Computing Co., Ltd. + 15th Floor, Building B4, Kexing Science Park, Nanshan District zip + guangdong 518000 + CN + +48-65-EE (hex) DNV GL +C00000-CFFFFF (base 16) DNV GL + Utrechtseweg 310 + Arnhem 6812 AR + NL + +1C-C0-E1 (hex) Kids Wireless Inc +500000-5FFFFF (base 16) Kids Wireless Inc + 200 Bathurst Dr. + Waterloo Ontario N2V 2L7 + CA + +1C-C0-E1 (hex) Hangzhou Kaierda Electric Welding Machine Co.,Ltd +100000-1FFFFF (base 16) Hangzhou Kaierda Electric Welding Machine Co.,Ltd + #6 Kenhui Five Road,Xiaoshan Economic & Technology Development Zone + Hangzhou 311232 + CN + +1C-C0-E1 (hex) Yun Yang Fire Safety Equipment Co.,Ltd. +E00000-EFFFFF (base 16) Yun Yang Fire Safety Equipment Co.,Ltd. + No.11-4, Wanjin Rd., Dashe Dist., + Kaohsiung City 815 + TW + +AC-64-DD (hex) Kpnetworks Ltd. +600000-6FFFFF (base 16) Kpnetworks Ltd. + 4-5-11-10F Shiba + Minato-ku Tokyo 108-0014 + JP + +AC-64-DD (hex) SHANGHAI ZTE TECHNOLOGIES CO.,LTD +500000-5FFFFF (base 16) SHANGHAI ZTE TECHNOLOGIES CO.,LTD + Bibo Road, Shanghai Pudong Zhangjiang Hi-Tech Park, Building No. 889, ZTE H Block 6F + SHANGHAI SHANGHAI 201210 + CN + +4C-E1-73 (hex) jvi +A00000-AFFFFF (base 16) jvi + Ettenbergstrasse 19 + Deckenpfronn 75392 + DE + +AC-64-DD (hex) Jia-Teng +000000-0FFFFF (base 16) Jia-Teng + 4F., No.417, Ruiguang Rd., Neihu Dist., Taipei City 114, Taiwan (R.O.C) + Taipei Taipei 114 + TW + +AC-64-DD (hex) Micro Connect Pty Ltd +900000-9FFFFF (base 16) Micro Connect Pty Ltd + 22 Gardenia Place + FOREST GLEN QLD 4556 + AU + +4C-E1-73 (hex) Lenovo Data Center Group +200000-2FFFFF (base 16) Lenovo Data Center Group + 8001 Development Dr + Morrisville NC 27560 + US + +4C-E1-73 (hex) Ersúles Limited +700000-7FFFFF (base 16) Ersúles Limited + Unit 17 Sandyford Office Park + Dublin D18 NP77 + IE + +38-3A-21 (hex) Foresight Sports +A00000-AFFFFF (base 16) Foresight Sports + 9965 Carroll Canyon Road + San Diego CA 92131 + US + +38-3A-21 (hex) Alicat Scientific +800000-8FFFFF (base 16) Alicat Scientific + 7641 N Business Park Dr + Tucson AZ 85743 + US + +F8-1D-78 (hex) Dongguan Shun Hing Plastics Limited +000000-0FFFFF (base 16) Dongguan Shun Hing Plastics Limited + No.11,13,15,Zhongfang Industrial Road,Shatou,Changan Town + Dongguan City Guangdong 523861 + CN + +F8-1D-78 (hex) Zengge Co., Limited +600000-6FFFFF (base 16) Zengge Co., Limited + 3/F, B Building, Second Laowei Industrial Zone, Longhua District + Shenzhen Guangdong 518109 + CN + +70-F8-E7 (hex) CUAV +E00000-EFFFFF (base 16) CUAV + zengcheng city xiapu + guangzhou guangdong 511340 + CN + +70-F8-E7 (hex) Beijing Eehuu Technology Co.,Ltd. +500000-5FFFFF (base 16) Beijing Eehuu Technology Co.,Ltd. + Room 2010, 3rd floor, Building #10, No.39 Sanlihe Road, Haidian District, Beijing, China + BEIJING Beijing 10000 + CN + +70-F8-E7 (hex) NST Technology Limited Co.,Ltd. +700000-7FFFFF (base 16) NST Technology Limited Co.,Ltd. + 1F,ABuilding,Juxie Zuo,No.18 Zhenze Road, + wuxi Jiangsu 214073 + CN + +70-F8-E7 (hex) CLIP Inc. +400000-4FFFFF (base 16) CLIP Inc. + 4-5-18,Hommachi,Chuo-ku + Osaka-city Osaka-fu 541-0053 + JP + +84-E0-F4 (hex) Hangzhou Nationalchip Science & Technology Co.,Ltd. +500000-5FFFFF (base 16) Hangzhou Nationalchip Science & Technology Co.,Ltd. + 5-6th Floor, Innovation Mansion East Software Park,90# Wensan Road + Hangzhou Zhejiang 310012 + CN + +70-F8-E7 (hex) System-on-Chip engineering +D00000-DFFFFF (base 16) System-on-Chip engineering + Jose María Escuza 23 Entreplanta Dcha D + Bilbao Bizkaia ES48013 + ES + +70-F8-E7 (hex) Photonfocus AG +B00000-BFFFFF (base 16) Photonfocus AG + Bahnhofplatz 10 + Lachen SZ 8853 + CH + +84-E0-F4 (hex) SHENZHEN HCN.ELECTRONICS CO.,LTD. +900000-9FFFFF (base 16) SHENZHEN HCN.ELECTRONICS CO.,LTD. + 8F, Block C3, Nanshan I Park, No.1001 Xueyuan Road, Nanshan District + shenzhen guangdong 518040 + CN + +84-E0-F4 (hex) Logos01 Srl +D00000-DFFFFF (base 16) Logos01 Srl + Via Pertini 23 + Marmirolo MN 46045 + IT + +84-E0-F4 (hex) PetroInTrade +400000-4FFFFF (base 16) PetroInTrade + Engelsa 71 + Saint-Peterburg 194214 + RU + +C0-D3-91 (hex) Fuzhou Jinshi Technology Co.,Ltd. +000000-0FFFFF (base 16) Fuzhou Jinshi Technology Co.,Ltd. + Block A, Building 39#,District D, Software Park + Fuzhou Fujian Province 350003 + CN + +C0-D3-91 (hex) Vernier Software & Technology +400000-4FFFFF (base 16) Vernier Software & Technology + 13979 SW Millikan Way + Beaverton OR 97005 + US + +5C-F2-86 (hex) Shenzhen VST Automotive Electronics Co., LTD +900000-9FFFFF (base 16) Shenzhen VST Automotive Electronics Co., LTD + 3 floor,1Building, No.3 West of ShangXue Science and technology park, Bantian town, LongGang District + ShenZhen Guangdong 518100 + CN + +C0-D3-91 (hex) Ernitec +600000-6FFFFF (base 16) Ernitec + Tempovej 41 + Ballerup 2750 + DK + +58-E8-76 (hex) Beijing Perabytes IS Technology Co., Ltd +100000-1FFFFF (base 16) Beijing Perabytes IS Technology Co., Ltd + 2F, Office Building, No. 2 Yard, Longxiang Printing-plate Group, North of Huilongguan Village, Huilongguan Town, ChangPing District,Beijing 102208, P.R. China + Beijing Beijing 102208 + CN + +58-E8-76 (hex) Baoruh Electronic Co., Ltd. +E00000-EFFFFF (base 16) Baoruh Electronic Co., Ltd. + o.285, Dingciang Street, Kaohsiung, 80790 Taiwan. + Kaohsiung 80790 + TW + +58-E8-76 (hex) Coala Life AB +200000-2FFFFF (base 16) Coala Life AB + Riddargatan 18 + Stockholm 11451 + SE + +58-E8-76 (hex) Chronos Technology Ltd. +700000-7FFFFF (base 16) Chronos Technology Ltd. + Stowfield House + Lydbrook Gloucestershire GL17 9PD + GB + +F0-AC-D7 (hex) Simprints Technology Ltd +C00000-CFFFFF (base 16) Simprints Technology Ltd + The Chesterton Tower + Cambridge CB4 1DZ + GB + +B0-C5-CA (hex) SHENZHEN KTC TECHNOLOGY GROUP +700000-7FFFFF (base 16) SHENZHEN KTC TECHNOLOGY GROUP + Northern Wuhe Road,Banxuegang Industry Area,Buji,Shenzhen,China + Shenzhen Guangdong 518129 + CN + +F0-AC-D7 (hex) U3storage Technologies Co., Ltd +900000-9FFFFF (base 16) U3storage Technologies Co., Ltd + information Road No. 26 , Haidian District + BEIJING 100085 + CN + +28-36-38 (hex) SHENZHEN GOSPELL SMARTHOME ELECTRONIC CO., LTD. +200000-2FFFFF (base 16) SHENZHEN GOSPELL SMARTHOME ELECTRONIC CO., LTD. + Block F10~13, F518 Idea Land, Bao Yuan Road, Baoan, Shenzhen + Shenzhen Guangdong 518102 + CN + +28-36-38 (hex) Sabinetek +300000-3FFFFF (base 16) Sabinetek + NO.1406 Hong Yuan Building ,Jiu Xian Qiao Road A 4,Chao Yang Beijing China + Beijing Beijing 100000 + CN + +78-CA-83 (hex) Hubei Boyuan Zhijia Network Media Co. Ltd. +D00000-DFFFFF (base 16) Hubei Boyuan Zhijia Network Media Co. Ltd. + Wuhan City, Hubei City, Optics Valley Province, Optics Valley 77, city, financial port A3 12 + Wuhan Hubei 42000 + CN + +78-C2-C0 (hex) SICHUAN TIANYI COMHEART TELECOMCO.,LTD +600000-6FFFFF (base 16) SICHUAN TIANYI COMHEART TELECOMCO.,LTD + FL12,TowerB,Tianyi international Hotel,No.2 West Section One, Second Ring Road, Chengdu, Sichuan + Chengdu Sichuan 610000 + CN + +8C-19-2D (hex) Elcon AB +E00000-EFFFFF (base 16) Elcon AB + Hyttrisvagen 27 + Nyhammar 77014 + SE + +8C-19-2D (hex) Greenfield Technology +300000-3FFFFF (base 16) Greenfield Technology + 1 bis rue marcel paul + massy 91300 + FR + +D0-D9-4F (hex) APPOTRONICS CO., LTD +E00000-EFFFFF (base 16) APPOTRONICS CO., LTD + 4th Floor,SZICC,NO.1089,Chaguang Road,Nanshan District, Shenzhen, China + Shenzhen Guangdong 518000 + CN + +CC-D3-1E (hex) Shenzhen Decnta Technology Co.,LTD. +700000-7FFFFF (base 16) Shenzhen Decnta Technology Co.,LTD. + F13,No.02,Building Shangqi,Nanhaidadao 4050 Nanshan District,Shenzhen,P.R.China + shenzhen Guangdong 518057 + CN + +C4-7C-8D (hex) Star2Star Communications, LLC +200000-2FFFFF (base 16) Star2Star Communications, LLC + 600 Tallevast Road, Suite 202 + Sarasota FL 34243 + US + +CC-D3-1E (hex) NTmore.Co.,Ltd +500000-5FFFFF (base 16) NTmore.Co.,Ltd + 38, Heungan-daero 427 beon-gil, Dongan-gu + Anyang Gyeonggi 431-801 + KR + +CC-D3-1E (hex) inoage GmbH +800000-8FFFFF (base 16) inoage GmbH + Wiener Str. 56 + Dresden 01219 + DE + +C4-7C-8D (hex) Anhui GuangXing Linked-Video Communication Technology Co, Ltd. +D00000-DFFFFF (base 16) Anhui GuangXing Linked-Video Communication Technology Co, Ltd. + Floor 6, Block B, Idiopathic Information Technology Port, Kefeng Road No. 2, Nanshan District + Shenzhen Guangdong 518057 + CN + +68-91-D0 (hex) solvimus GmbH +800000-8FFFFF (base 16) solvimus GmbH + Ehrenbergstr. 11 + Ilmenau 98693 + DE + +68-91-D0 (hex) Spraying Systems Co. +C00000-CFFFFF (base 16) Spraying Systems Co. + North Ave. and Schmale Road P.O. Box 7900 + Wheaton IL 60187-7901 + US + +68-91-D0 (hex) Fuzhou x-speed information technology Co.,Ltd. +D00000-DFFFFF (base 16) Fuzhou x-speed information technology Co.,Ltd. + tianewan 30#1601 Pushang Load,Cangshan District, + Fuzhou Fujian 350008 + CN + +E0-B6-F5 (hex) Moog Crossbow +B00000-BFFFFF (base 16) Moog Crossbow + 1421 McCarthy Blvd + Milpitas CA 95035 + US + +E0-B6-F5 (hex) START TODAY CO.,LTD. +100000-1FFFFF (base 16) START TODAY CO.,LTD. + WBG Malibu West 16 Floor 2-6-1 Nakase Mihama-ku, Chiba + Chiba Chiba 261-7116 + JP + +50-FF-99 (hex) metraTec GmbH +A00000-AFFFFF (base 16) metraTec GmbH + Niels-Bohr-Str. 5 + Magdeburg Sachsen-Anh. 39106 + DE + +50-FF-99 (hex) Dolphin Concepts Limited +800000-8FFFFF (base 16) Dolphin Concepts Limited + A 10, Unit B-E + 11/F, Genesis, 33-35 Wong Chuk Hang Road, Hong Kong 11111 + HK + +98-6D-35 (hex) SHENZHEN FISE TECHNOLOGY HOLDING CO.,LTD. +200000-2FFFFF (base 16) SHENZHEN FISE TECHNOLOGY HOLDING CO.,LTD. + No.6 Building, Longfu Industrial Area, Huarong Road, Tongsheng Community, Dalang Street, Longhua New District, Shenzhen, Guangdong, China + shenzhen guangdong 518000 + CN + +98-6D-35 (hex) INTECH +B00000-BFFFFF (base 16) INTECH + 1F No. 45, Wanghai Road / Software Park Phase Ⅱ, Xiamen, China + Xiamen Fujian 361008 + CN + +98-6D-35 (hex) BAYCOM OPTO-ELECTRONICS TECHNOLGY CO., LTD. +E00000-EFFFFF (base 16) BAYCOM OPTO-ELECTRONICS TECHNOLGY CO., LTD. + 3F, NO.9, INDUSTRIAL EAST 9TH RD. HSINCHU SCIENCE PARK, HSIN-CHU CITY, TAIWAN, R.O.C. + HSIN-CHU 30075 + TW + +98-6D-35 (hex) iWave Japan, Inc. +A00000-AFFFFF (base 16) iWave Japan, Inc. + 8F-B,Kannai Sumiyoshi Building,3-29 Sumiyoshi-Cho,Naka-Ku, + Yokohama, Kanagawa 231-0013 + JP + +10-07-23 (hex) Diginet Control Systems Pty Ltd +200000-2FFFFF (base 16) Diginet Control Systems Pty Ltd + 96-112 Gow Street + Padstow New South Wales 2211 + AU + +7C-47-7C (hex) Hangzhou Yiyitaidi Information Technology Co., Ltd. +B00000-BFFFFF (base 16) Hangzhou Yiyitaidi Information Technology Co., Ltd. + #9 Jiuhuan Road, Building 1B208, Jianggan District + Hangzhou Zhejiang 310019 + CN + +5C-F2-86 (hex) Itron UK Limited +B00000-BFFFFF (base 16) Itron UK Limited + Harfreys Road , Harfreys Ind. Estate + Great Yarmouth NR31 0LS + GB + +38-FD-FE (hex) WAYTONE (BEIIJNG) COMMUNICATIONS CO.,LTD +100000-1FFFFF (base 16) WAYTONE (BEIIJNG) COMMUNICATIONS CO.,LTD + ROOM 201B,KESHI BUILDING,NO.28 XINXI ROAD HAIDIAN BEIJING,P.R.CHINA + Beijing Beijing 100085 + CN + +7C-47-7C (hex) POWERLAND LIMITED +200000-2FFFFF (base 16) POWERLAND LIMITED + 7F, Buiding A2, ZhongTai Information Industry Park, DeZheng Road, ShiYan Street. + ShenZhen GuangDong 518108 + CN + +38-B8-EB (hex) Yellowbrick Data, Inc. +D00000-DFFFFF (base 16) Yellowbrick Data, Inc. + 250 Cambridge Av., Suite 201 + Palo Alto CA 94306 + US + +38-FD-FE (hex) Siemens AG, PG IE R&D +300000-3FFFFF (base 16) Siemens AG, PG IE R&D + Siemensalle 84 + Karlsruhe 76187 + DE + +38-B8-EB (hex) MATRIXSTREAM TECHNOLOGIES, INC. +600000-6FFFFF (base 16) MATRIXSTREAM TECHNOLOGIES, INC. + 303 Twin Dolphins Drive 6th Floor Redwood Shores, california,USA 94065 + california 94065 + AM + +38-B8-EB (hex) barox Kommunikation GmbH +200000-2FFFFF (base 16) barox Kommunikation GmbH + Marie-Curie-Strasse 8 + Lörrach DE-79539 + DE + +1C-88-79 (hex) gekartel AG +B00000-BFFFFF (base 16) gekartel AG + Julius-Otto-Straße 7 + Dresden 01219 + DE + +1C-88-79 (hex) Newps co.,ltd +000000-0FFFFF (base 16) Newps co.,ltd + 33, Hoguk-ro + Daegu Korea 41502 + KR + +1C-87-74 (hex) Quest Integrity +E00000-EFFFFF (base 16) Quest Integrity + 19823 58TH PL S, STE 100 + Kent WA 98032 + US + +1C-88-79 (hex) ITW-FEG +A00000-AFFFFF (base 16) ITW-FEG + 155 Harlem Avenue + Glenview IL 60025 + US + +1C-87-76 (hex) Artis GmbH +E00000-EFFFFF (base 16) Artis GmbH + Buchenring 40 + Egestorf 21272 + DE + +1C-88-79 (hex) ANDRA Sp. z o.o. +100000-1FFFFF (base 16) ANDRA Sp. z o.o. + Pryzmaty 6/8 + Warszawa 02-226 + PL + +1C-87-79 (hex) ASSYSTEM France +E00000-EFFFFF (base 16) ASSYSTEM France + 13 rue Marie Louise Dissard + TOULOUSE 31024 + FR + +1C-87-74 (hex) Nichigaku +200000-2FFFFF (base 16) Nichigaku + Oimachi 1-49-15 + Shinagawa Tokyo 1400014 + JP + +1C-87-74 (hex) Philips Personal Health Solutions +000000-0FFFFF (base 16) Philips Personal Health Solutions + High Tech Campus, HTC37 floor 0 + Eindhoven 5656 AE + NL + +1C-87-76 (hex) Hekatron Vertriebs GmbH +B00000-BFFFFF (base 16) Hekatron Vertriebs GmbH + Brühlmatten 9 + Sulzburg 79295 + DE + +1C-87-76 (hex) RDP.RU +400000-4FFFFF (base 16) RDP.RU + 3 Davydkovskaya street + Moscow 121352 + RU + +1C-87-79 (hex) TASC Systems Inc. +700000-7FFFFF (base 16) TASC Systems Inc. + 9415 - 202 Street + Langley BRITISH COLUMBIA V1M4B5 + CA + +1C-87-79 (hex) SMARTMOVT TECHNOLOGY Co., LTD +200000-2FFFFF (base 16) SMARTMOVT TECHNOLOGY Co., LTD + Room204-210, F3 building, F518 Idea Land, Baoyuan road, Xixiang Ave, Bao’an District + Shenzhen Guangdong 518100 + CN + +1C-87-79 (hex) Beijing Geedeen Technology Co., Ltd +B00000-BFFFFF (base 16) Beijing Geedeen Technology Co., Ltd + Room 1701, Building A, Boya International Center, Lizezhongerlu, Chaoyang District + Beijing Beijing 100102 + CN + +84-39-BE (hex) Guangzhou Heygears Technology Ltd +100000-1FFFFF (base 16) Guangzhou Heygears Technology Ltd + Room 2301, #379 Zhongshan Road Central + Guangzhou Guangdong 510000 + CN + +70-88-6B (hex) Church & Dwight Co., Inc. +600000-6FFFFF (base 16) Church & Dwight Co., Inc. + 500 Charles Ewing Blvd + Ewing NJ 08628 + US + +40-A3-6B (hex) Onion Corporation +C00000-CFFFFF (base 16) Onion Corporation + 186 Denison Street + Markham Ontario L3R 1B5 + CA + +70-88-6B (hex) Bitfinder Inc +100000-1FFFFF (base 16) Bitfinder Inc + 20660 Stevens Creeks #345 + Cupertino CA 95014 + US + +40-A3-6B (hex) TW-TeamWare +100000-1FFFFF (base 16) TW-TeamWare + Via Pindaro, 19 + Milano 20128 + IT + +70-88-6B (hex) Cable Matters Inc. +800000-8FFFFF (base 16) Cable Matters Inc. + 153 Northboro Road, Suite 5 + Southborough MA 01772 + US + +70-88-6B (hex) Shenzhen Coolhear Information Technology Co., Ltd. +900000-9FFFFF (base 16) Shenzhen Coolhear Information Technology Co., Ltd. + Room 502,Building A4, Kexing Science Park, Keyuan Road, Nanshan Distrct, Shenzhen, Guangdong, + Shenzhen Guangdong 518000 + CN + +00-55-DA (hex) OOO DEKATRON +600000-6FFFFF (base 16) OOO DEKATRON + Oseny boulevard 15 apart. 394 + Moscow Moscow 121609 + RU + +00-55-DA (hex) Quantum Communication Technology Co., Ltd.,Anhui +900000-9FFFFF (base 16) Quantum Communication Technology Co., Ltd.,Anhui + D3 Innovation Industrial Park, No. 800 Wangjiang West Road, Hefei Hi-tech Industrial Development Zone, Hefei City, Anhui Province, China + Hefei Anhui 230088 + CN + +CC-1B-E0 (hex) Cassia Networks +E00000-EFFFFF (base 16) Cassia Networks + Room B206 , ZhongGuanCun FaZhanDaSha + Beijing Beijing 100085 + CN + +80-0A-80 (hex) Golana Technology (Shenzhen) Co., Ltd. +000000-0FFFFF (base 16) Golana Technology (Shenzhen) Co., Ltd. + 4th Floor, Integration Building A1 + Shenzhen Guangdong 518129 + CN + +CC-1B-E0 (hex) Matter Labs Pty Ltd +A00000-AFFFFF (base 16) Matter Labs Pty Ltd + Suite 105 + South Yarra Vic 3141 + AU + +CC-1B-E0 (hex) Beijing Daotongtianxia Co.Ltd. +100000-1FFFFF (base 16) Beijing Daotongtianxia Co.Ltd. + Beijing, Haidian District, Taiyueyuan Building No.1, Taiyueshangwu Center Flo.5 + Beijing Beijing 100088 + CN + +A0-3E-6B (hex) Shenzhen Nufilo Inc. +400000-4FFFFF (base 16) Shenzhen Nufilo Inc. + Tianliao Building F3,(New Materials Industrial Park),Xueyuan Road,Nanshan District,Shenzhen City,P.R.China + Shenzhen Guangdong 518055 + CN + +C8-8E-D1 (hex) Ube, Inc. (dba Plum) +700000-7FFFFF (base 16) Ube, Inc. (dba Plum) + 9800 N. Lamar Blvd., STE 310 + Austin TX 78753-4160 + US + +C8-8E-D1 (hex) Shanghai Bwave Technology Co.,Ltd +C00000-CFFFFF (base 16) Shanghai Bwave Technology Co.,Ltd + 6F,Building12,399 Keyuan Road, Zhangjiang Hi-Tech Park,shanghai,china + Shanghai Shanghai 201203 + CN + +A0-3E-6B (hex) KoCoS Messtechnik AG +B00000-BFFFFF (base 16) KoCoS Messtechnik AG + Südring 42 + Korbach Hessen 34497 + DE + +C8-8E-D1 (hex) PHOENIX ENGINEERING CORP. +D00000-DFFFFF (base 16) PHOENIX ENGINEERING CORP. + 466-3 Fujikubo + Irumagun Saitama 354-0041 + JP + +A0-3E-6B (hex) s&t embedded GmbH +000000-0FFFFF (base 16) s&t embedded GmbH + Breslauer Str. 3 + Eching Bayern 85386 + DE + +1C-21-D1 (hex) LG CNS +A00000-AFFFFF (base 16) LG CNS + 21F, FKI Tower, 24, Yeoui-daero, Yeongdeungpo-gu + Seoul 150-881 + KR + +1C-21-D1 (hex) Global Design Solutions Ltd +B00000-BFFFFF (base 16) Global Design Solutions Ltd + Unit 13 + Bristol England BS44ED + GB + +1C-21-D1 (hex) Wuhan TieChi Detection Technology Co., Ltd. +600000-6FFFFF (base 16) Wuhan TieChi Detection Technology Co., Ltd. + Hongshan District Luo Yu RoadBainaohui room 1513 + Wuhan Hubei 430000 + CN + +1C-21-D1 (hex) Toyo System CO.,LTD. +000000-0FFFFF (base 16) Toyo System CO.,LTD. + 106-1,Zenita,Joban-Nishigo, + Iwaki, Fukushima 972-8316 + JP + +1C-21-D1 (hex) Varaani Works Oy +200000-2FFFFF (base 16) Varaani Works Oy + Takojankatu 1c B 16 + Tampere Pirkanmaa 33540 + FI + +DC-44-27 (hex) Rohde&Schwarz Topex SA +D00000-DFFFFF (base 16) Rohde&Schwarz Topex SA + 71th-73th Nicolae Caramfil street, 2nd floor, 1th district + Bucuresti Romania 014142 + RO + +1C-21-D1 (hex) Liscotech System Co., Ltd. +D00000-DFFFFF (base 16) Liscotech System Co., Ltd. + 4F. No. 342 Sec.4 Chenggong Rd. Neihu Dist. + Taipei TW 11458 + TW + +1C-21-D1 (hex) Soundtrack Your Brand Sweden AB +700000-7FFFFF (base 16) Soundtrack Your Brand Sweden AB + Birger Jarlsgatan 43 + Stockholm 11145 + SE + +C8-8E-D1 (hex) Fibergate.Inc +500000-5FFFFF (base 16) Fibergate.Inc + KDX Shibadaimon.Bld 2F Shibadaimon Minato-ku Tokyo 105-0012 Japan + Tokyo Minato-ku 105-0012 + JP + +DC-44-27 (hex) VerifEye Technologies +E00000-EFFFFF (base 16) VerifEye Technologies + 2-151 Whitehall Dr. + Markham ON L3R9T1 + CA + +C8-8E-D1 (hex) Linx Technologies +300000-3FFFFF (base 16) Linx Technologies + 159 Ort Lane + Merlin OR 97532 + US + +C8-8E-D1 (hex) Comlab AG +400000-4FFFFF (base 16) Comlab AG + Ey 13 + Ittigen BE 3076 + CH + +B0-C5-CA (hex) TEM Mobile Limited +A00000-AFFFFF (base 16) TEM Mobile Limited + RM1703, North Block, Cangsong Building, Tairan 6 road, Futian District, Shenzhen. + Shenzhen Guangdong 518000 + CN + +B0-C5-CA (hex) RISECOMM (HK) TECHNOLOGY CO. LIMITED +B00000-BFFFFF (base 16) RISECOMM (HK) TECHNOLOGY CO. LIMITED + Skyworth Building C501, Hi-tech Industrial Park, Shenzhen, China + shenzhan guangdong 518057 + CN + +B0-C5-CA (hex) LOWOTEC GmbH +200000-2FFFFF (base 16) LOWOTEC GmbH + Marie-Curie-Str. 1 + Oldenburg Niedersachsen 26129 + DE + +78-C2-C0 (hex) ShenZhen TuLing Robot CO.,LTD +500000-5FFFFF (base 16) ShenZhen TuLing Robot CO.,LTD + BLK 9, No 28, Langshan Road, Northern District of High Tech. Industry Park, Nanshan Dist., SZ., PRC. + ShenZhen GuangDong 518000 + CN + +B4-37-D1 (hex) Axiomatic Technologies Corporation +A00000-AFFFFF (base 16) Axiomatic Technologies Corporation + 5915 Wallace St. + Mississauga ON L4Z1Z8 + CA + +74-F8-DB (hex) GHL Advanced Technology GmbH & Co. KG +100000-1FFFFF (base 16) GHL Advanced Technology GmbH & Co. KG + Marie-Curie-Str. 20 + Kaiserslautern RP 67661 + DE + +54-9A-11 (hex) Hangzhou duotin Technology Co., Ltd. +D00000-DFFFFF (base 16) Hangzhou duotin Technology Co., Ltd. + Haichuang Garden of Hangzhou city Yuhang District 4 Building 407B + hangzhou Zhejiang 311100 + CN + +88-5D-90 (hex) Gigatech R&D Corp. +900000-9FFFFF (base 16) Gigatech R&D Corp. + 7F-5, 16 Jian 8th road, Zhonghe Dist. + New Taipei City Taiwan 23511 + TW + +88-5D-90 (hex) ShenZhen Yuyangsheng technology company LTD +100000-1FFFFF (base 16) ShenZhen Yuyangsheng technology company LTD + Yinfeng industrial park Jiu wei community + shenzhen guangdong 518000 + CN + +88-5D-90 (hex) Hi-Profile Achievement (M) Sdn Bhd +600000-6FFFFF (base 16) Hi-Profile Achievement (M) Sdn Bhd + 42A, Lorong Teras Jaya 2, Kawasan Perniagaan Teras Jaya + Butterworth Pulau Pinang 13400 + MY + +54-9A-11 (hex) VendNovation LLC +A00000-AFFFFF (base 16) VendNovation LLC + 13400 NE 20th Street + Bellevue WA 98005 + US + +80-7B-85 (hex) Shiroshita Industrial Co., Ltd. +000000-0FFFFF (base 16) Shiroshita Industrial Co., Ltd. + 1-1-58, Tokiiri + Ueda-shi Nagano 386-0015 + JP + +80-7B-85 (hex) Phoenix Co.,Ltd. +200000-2FFFFF (base 16) Phoenix Co.,Ltd. + Perl Iidabashi Bldg., + Chiyoda-ku Tokyo 102-0072 + JP + +64-FB-81 (hex) Sichuan Haige Actec Communication Technology Co.,Ltd. +B00000-BFFFFF (base 16) Sichuan Haige Actec Communication Technology Co.,Ltd. + 8 Mintai Road, Youxian District, Mianyang City, Sichuan + Mianyang City Sichuan 621022 + CN + +80-7B-85 (hex) IDair, LLC +800000-8FFFFF (base 16) IDair, LLC + 6767 Old Madison Pike + Huntsville AL 35806 + US + +80-E4-DA (hex) Neutronics +A00000-AFFFFF (base 16) Neutronics + 456 Creamery Way + Exton Pennsylvania 19341 + US + +64-FB-81 (hex) Narrative AB +100000-1FFFFF (base 16) Narrative AB + Agatan 55A + Linkoping - 58222 + SE + +1C-CA-E3 (hex) Insigma Inc +200000-2FFFFF (base 16) Insigma Inc + 43490, Yukon Drive, Suite 102 + Ashburn VA 20147 + US + +80-E4-DA (hex) Akenori PTE LTD +E00000-EFFFFF (base 16) Akenori PTE LTD + 176 JOO CHIAT ROAD #02-02 + 427447 + SG + +1C-CA-E3 (hex) Dream Visions Co., LTD +B00000-BFFFFF (base 16) Dream Visions Co., LTD + 90 Chongpa_Ro YoungSan-Gu + Seoul Seoul 140-742 + KR + +1C-CA-E3 (hex) Gahdeung Elecom +C00000-CFFFFF (base 16) Gahdeung Elecom + 203, Rojinmedical, 717, Lee-Dong, Sanrok-Gu + ANSAN Kyeonggi-Do ASI|KR|KS009|ANSAN + KR + +1C-CA-E3 (hex) TOKAI RIKA CO., LTD. +600000-6FFFFF (base 16) TOKAI RIKA CO., LTD. + 3-260 + Niwa-gun, Oguchi-cho Aichi 480-0195 + JP + +90-C6-82 (hex) Shenzhen Photon Broadband Technology CO., LTD +100000-1FFFFF (base 16) Shenzhen Photon Broadband Technology CO., LTD + 8/F,C Bldg, Funing Hi-Tech Industrial Park, No.71 Fuyong Xintian Road,Baoan District Shenzhen,China + Shenzhen Guangdong 518103 + CN + +90-C6-82 (hex) ekey biometric systems gmbh +200000-2FFFFF (base 16) ekey biometric systems gmbh + Lunzerstrsasse 89 + Linz Upper Austria 4020 + AT + +90-C6-82 (hex) ACT +900000-9FFFFF (base 16) ACT + Unit C1, South City Business Center + Dublin + IE + +2C-D1-41 (hex) AOptix Technologies, Inc +300000-3FFFFF (base 16) AOptix Technologies, Inc + 675 Campbell Technology Pkwy + Campbell CA 95008 + US + +2C-D1-41 (hex) iCIRROUND Inc +000000-0FFFFF (base 16) iCIRROUND Inc + 7F,No.,79, Chou-Tze St., + Taipei Taiwan 114 + TW + +90-C6-82 (hex) Beijing Acorn Networks Corporation +A00000-AFFFFF (base 16) Beijing Acorn Networks Corporation + 1A-601,Wang Jing Street, Chao Yang Qu, Beijing, China + Beijing Beijing 100102 + CN + +2C-6A-6F (hex) Schneider Electric Korea +B00000-BFFFFF (base 16) Schneider Electric Korea + 14F Kbiz DMC tower, + Seoul 121-904 + KR + +2C-D1-41 (hex) Minno LLC +800000-8FFFFF (base 16) Minno LLC + 421 North Milpas Street + Santa Barbara CA 93103 + US + +A0-BB-3E (hex) COMSYS Communications Systems Service GmbH +400000-4FFFFF (base 16) COMSYS Communications Systems Service GmbH + TecCenter + Bad Salzdetfurth Niedersachsen 31162 + DE + +98-02-D8 (hex) Fritz Kuebler GmbH +600000-6FFFFF (base 16) Fritz Kuebler GmbH + Schubertstrasse 47 + Villingen-Schwenningen Baden-Wuerttemberg 78054 + DE + +98-02-D8 (hex) Grammer EiA Electronics nv +300000-3FFFFF (base 16) Grammer EiA Electronics nv + Vluchtenburgstraat 3B + Aartselaar Antwerp 2630 + BE + +A0-BB-3E (hex) Messtechnik Sachs GmbH +E00000-EFFFFF (base 16) Messtechnik Sachs GmbH + Siechenfeldstr. 30/1 + Schorndorf Germany 73614 + DE + +98-02-D8 (hex) SHENZHEN ATEKO PHOTOELECTRICITY CO LTD +100000-1FFFFF (base 16) SHENZHEN ATEKO PHOTOELECTRICITY CO LTD + 4-5F, E1 Building, TCL International E City, No.1001 Zhongshanyuan Road, Nanshan District + Shenzhen, Guangdong 518052 + CN + +F8-02-78 (hex) Lit Technologies +E00000-EFFFFF (base 16) Lit Technologies + 2011 Stampede Dr + Farmington Utah 84025 + US + +2C-26-5F (hex) XIAMEN VORLINK IOT TECHNOLOGY CO.,LTD. +000000-0FFFFF (base 16) XIAMEN VORLINK IOT TECHNOLOGY CO.,LTD. + No.306 of Chengye Bldg., Xiamen Pioneering Park for Overseas Chinese Scholars + xiamen fujian 361000 + CN + +28-FD-80 (hex) T-Radio AS +E00000-EFFFFF (base 16) T-Radio AS + Stensarmen 3A + Tønsberg 3112 + NO + +2C-26-5F (hex) Appostar Technology Co. Ltd +600000-6FFFFF (base 16) Appostar Technology Co. Ltd + 13F., No.213, Sec. 3, Beixin Rd., Xindian Dist., New Taipei City 231, Taiwan (R.O.C.) + Xindian Dist New Taipei City 231 + TW + +2C-26-5F (hex) shenzhen Clever Electronic Co., Ltd. +300000-3FFFFF (base 16) shenzhen Clever Electronic Co., Ltd. + Building 8, Baiwang Creative Park(UTCP),Nanshan District,Shenzhen,China + Shenzhen GuangDong 518055 + CN + +28-FD-80 (hex) NUUO, Inc. +300000-3FFFFF (base 16) NUUO, Inc. + B1, No.207-1, Sec. 3, Beixin Rd. + New Taipei City Xindian Dist. 231 + TW + +0C-EF-AF (hex) PREMIUM SA +500000-5FFFFF (base 16) PREMIUM SA + C/ Dolors Aleu 19 2º 2º + Hospitalet del Llobregat Barcelona 08908 + ES + +F8-02-78 (hex) Technology Research, LLC +C00000-CFFFFF (base 16) Technology Research, LLC + 4525 140th Ave North + Clearwater FL 33762 + US + +0C-EF-AF (hex) BSX Athletics +800000-8FFFFF (base 16) BSX Athletics + 2500 E T C Jester Blvd. + Houston TX 77008 + US + +F8-02-78 (hex) 3Shape Holding A/S +300000-3FFFFF (base 16) 3Shape Holding A/S + Holmens Kanal 7,2 + Copenhagen K. Copenhagen 1060 + DK + +F8-02-78 (hex) Digatron Power Electronics GmbH +000000-0FFFFF (base 16) Digatron Power Electronics GmbH + Tempelhofer Str. 12-14 + Aachen NRW 52068 + DE + +F8-02-78 (hex) Electric Objects +500000-5FFFFF (base 16) Electric Objects + 356 Bowery + New York NY 10021 + US + +A4-4F-29 (hex) Neotech Systems Pvt. Ltd. +E00000-EFFFFF (base 16) Neotech Systems Pvt. Ltd. + B-25, 2nd floor + New Delhi Delhi 110049 + IN + +A4-4F-29 (hex) HALLIBURTON +D00000-DFFFFF (base 16) HALLIBURTON + 445 WOODLINE DR + SPRING TX 77386 + US + +3C-39-E7 (hex) iiM AG +A00000-AFFFFF (base 16) iiM AG + Neuer Friedberg 5 + Suhl Thuringia 98527 + DE + +3C-39-E7 (hex) Zone Controls AB +900000-9FFFFF (base 16) Zone Controls AB + Verkstadsvägen 6 + Västerhaninge Stockholms län 137 37 + SE + +3C-39-E7 (hex) Sensor to Image GmbH +700000-7FFFFF (base 16) Sensor to Image GmbH + Lechtorstrasse 20 + Schongau Bavaria 86956 + DE + +0C-EF-AF (hex) LUMEL S.A. +200000-2FFFFF (base 16) LUMEL S.A. + Ul.Slubicka 1 + Zielona Gora 65-127 + PL + +10-07-23 (hex) Ion Professional Solutions +800000-8FFFFF (base 16) Ion Professional Solutions + 4514 Flower Bridge Ct + Humble Texas 77396 + US + +10-07-23 (hex) First Chair Acoustics Co., Ltd. +E00000-EFFFFF (base 16) First Chair Acoustics Co., Ltd. + No. 53, Lane 17, Yuhe Street + Taoyuan City, Taoyuan County 33057 + TW + +10-07-23 (hex) Fujian Quanzhou Dong Ang Electronics Co., Ltd. +B00000-BFFFFF (base 16) Fujian Quanzhou Dong Ang Electronics Co., Ltd. + 5th floor of Hengtaixing mansion, Yingbin Road + Quanzhou Fujian 362000 + CN + +10-07-23 (hex) nanoTech Co., Ltd. +700000-7FFFFF (base 16) nanoTech Co., Ltd. + 4-2-17 Chuorinka + Yamato Kanagawa 242-0007 + JP + +D0-22-12 (hex) UAB "SALDA" +900000-9FFFFF (base 16) UAB "SALDA" + Ragaines 100 + Šiauliai Europe LT-78109 + LT + +D0-22-12 (hex) Schleifenbauer Holding BV +B00000-BFFFFF (base 16) Schleifenbauer Holding BV + Rietwaard 15 + Hertogenbosch 5236WC + NL + +D0-22-12 (hex) Shanghai Routech Co., Ltd +500000-5FFFFF (base 16) Shanghai Routech Co., Ltd + R.709-(2), B Zone, No.668 Eastern Beijing Rd. Shanghai P.R.C + Shanghai Shanghai 200001 + CN + +D0-22-12 (hex) Cliptech Industria e Comercio Ltda +700000-7FFFFF (base 16) Cliptech Industria e Comercio Ltda + ROD VICE PREF HERMENEGILDO TONOLI, 2285 + ITUPEVA SAO PAULO 13295000 + BR + +D0-22-12 (hex) u::Lux GmbH +E00000-EFFFFF (base 16) u::Lux GmbH + Rechtes Salzachufer 42 + Bergheim Salzburg 5101 + AT + +74-E1-4A (hex) Knog Pty Ltd +D00000-DFFFFF (base 16) Knog Pty Ltd + 453 Church St + Richmond VIC 3128 + AU + +74-E1-4A (hex) Loctek Visual Technology Corp. +B00000-BFFFFF (base 16) Loctek Visual Technology Corp. + Floor 20 Aux Building No.757 Rili Middle Road Yinzhou District Ningbo China + Ningbo zhejiang 315199 + CN + +E8-18-63 (hex) Acopian Technical Company +E00000-EFFFFF (base 16) Acopian Technical Company + 131 Loomis Street + Easton PA 18045 + US + +B8-D8-12 (hex) Docobo Limited +B00000-BFFFFF (base 16) Docobo Limited + The Old Granary, 21 High Street + Leatherhead Surrey KT23 4AA + GB + +E4-95-6E (hex) iConservo Inc +B00000-BFFFFF (base 16) iConservo Inc + 35 Tesla + Irvine CA 92618 + + +E4-95-6E (hex) Red Point Positioning, Corp. +A00000-AFFFFF (base 16) Red Point Positioning, Corp. + 20 Webster Street, Suite 411 + Brookline MASSACHUSETTS 02446 + US + +74-E1-4A (hex) UTU Oy +500000-5FFFFF (base 16) UTU Oy + Ahjontie 1 + Ulvila Finland 28400 + FI + +E4-95-6E (hex) ELAN SYSTEMS +500000-5FFFFF (base 16) ELAN SYSTEMS + 10 IHASZ STR + BUDAPEST 1105 + HU + +E4-95-6E (hex) Shenzhen Arronna Telecom Co.,Ltd +C00000-CFFFFF (base 16) Shenzhen Arronna Telecom Co.,Ltd + 4F, Block 1, No 17-2, Pingxi South Rd + Shenzhen Guangdong 518117 + CN + +B0-1F-81 (hex) CIDE Interactive +900000-9FFFFF (base 16) CIDE Interactive + Viladecans Business Pk, Edificio Brasil + Viladecans Barcelona 08840 + ES + +58-FC-DB (hex) Timex Group USA Inc +600000-6FFFFF (base 16) Timex Group USA Inc + 555 Christian Rd + Middlebury CT 06762 + US + +BC-66-41 (hex) ARGUS-SPECTRUM +400000-4FFFFF (base 16) ARGUS-SPECTRUM + Serdobolskaya str.,65 + St-Petersburg 197342 + RU + +B0-1F-81 (hex) Steffens Systems GmbH +A00000-AFFFFF (base 16) Steffens Systems GmbH + Mathias-Brüggenstr. 83 + Cologne NRW 50829 + DE + +F4-0E-11 (hex) Zeepro Inc. +800000-8FFFFF (base 16) Zeepro Inc. + 151 10th Street + San Francisco California 94103 + US + +F4-0E-11 (hex) Alpha Design Technologies Pvt Ltd +600000-6FFFFF (base 16) Alpha Design Technologies Pvt Ltd + #9, Service Road, HAL II Stage + Bangalore Karnataka 560008 + IN + +14-1F-BA (hex) AJIS(DALIAN)co.,LTD +D00000-DFFFFF (base 16) AJIS(DALIAN)co.,LTD + Room 202B + Dalian Liaoning 116023 + CN + +F4-0E-11 (hex) BRADAR INDUSTRIA SA +B00000-BFFFFF (base 16) BRADAR INDUSTRIA SA + AVENIDA SHISHIMA HIFUMI,2911 + SÃO JOSE DOS CAMPOS SÃO PAULO 12244-000 + BR + +BC-34-00 (hex) MATICA TECHNOLOGIES AG +800000-8FFFFF (base 16) MATICA TECHNOLOGIES AG + 52 TECKSTRASSE + ESSLINGEN AM NECKAR BADEN WUERTTENBERG 73734 + DE + +BC-34-00 (hex) Shenzhen PHilorise Technical Limited +900000-9FFFFF (base 16) Shenzhen PHilorise Technical Limited + Floor 4, Building 2, TingWeiGongYeQu, + ShenZhen GuangDong 518010 + CN + +14-1F-BA (hex) Thales Communications & Security SAS +600000-6FFFFF (base 16) Thales Communications & Security SAS + BP 57 + Bretigny-sur-Orge CEDEX France F 91229 + FR + +BC-34-00 (hex) Hangzhou Linker Digital Technology Co., Ltd +D00000-DFFFFF (base 16) Hangzhou Linker Digital Technology Co., Ltd + 4-5F, C Building, Jinrun Tech-Garden, 399# Qiuyi Road, Binjiang District + Hangzhou ZheJiang 310052 + CN + +BC-34-00 (hex) LLD Technology Ltd. +E00000-EFFFFF (base 16) LLD Technology Ltd. + 4F., No. 220, Sec. 1, Zhongshan Rd., + New Taipei City, Taiwan 234 + TW + +BC-34-00 (hex) FARO TECHNOLOGIES, INC. +B00000-BFFFFF (base 16) FARO TECHNOLOGIES, INC. + 125 Technology Park + Lake Mary FL 32746 + US + +7C-70-BC (hex) mk-messtechnik GmbH +D00000-DFFFFF (base 16) mk-messtechnik GmbH + Zeppelinstr. 1 + Notzingen D 73274 + DE + +7C-70-BC (hex) Bidgely +600000-6FFFFF (base 16) Bidgely + 298 S Sunnyvale Ave + Sunnyvale CA 94086 + US + +14-1F-BA (hex) Inttelix Brasil Tecnologia e Sistemas Ltda +500000-5FFFFF (base 16) Inttelix Brasil Tecnologia e Sistemas Ltda + Rua Desembargador Jorge Fontana, 112B, Belvedere + Belo Horizonte Minas Gerais 30320-670 + BR + +14-1F-BA (hex) Shenzhen Mining Technology Co.,Ltd. +000000-0FFFFF (base 16) Shenzhen Mining Technology Co.,Ltd. + 2017#Baoan Internet Industry Base,Langman Gangwan + Shenzhen Guangdong 518000 + CN + +BC-34-00 (hex) LifeSmart +200000-2FFFFF (base 16) LifeSmart + 1911, Huarong Times Plaza + Hangzhou Zhejiang 310052 + CN + +D0-76-50 (hex) Electro-Motive Diesel +C00000-CFFFFF (base 16) Electro-Motive Diesel + 9301 W. 55th Street + La Grange IL 60525 + US + +BC-34-00 (hex) NDSL, Inc. +500000-5FFFFF (base 16) NDSL, Inc. + 4112 Blue Ridge Road + Raleigh North Carolina 27612 + US + +A4-3B-FA (hex) BOI Solutions +500000-5FFFFF (base 16) BOI Solutions + 955 Mound Rd + Miamisburg Ohio 45342 + US + +D0-76-50 (hex) Happo Solutions Oy +200000-2FFFFF (base 16) Happo Solutions Oy + Graanintie 5 + MIKKELI 50190 + FI + +74-19-F8 (hex) Volacomm Co., Ltd +E00000-EFFFFF (base 16) Volacomm Co., Ltd + 15F-6., No.7, Sec.3, New Taipei Blvd., Xinzhuang Dist., New Taipei City 242., Taiwan (R.O.C) + Xinzhuang Dist. New Taipei City 242 + TW + +74-19-F8 (hex) Baudisch Electronic GmbH +600000-6FFFFF (base 16) Baudisch Electronic GmbH + Im Gewerbegebiet 7-9 + Wäschenbeuren Baden-Württemberg 73116 + DE + +D0-76-50 (hex) TAPKO Technologies GmbH +300000-3FFFFF (base 16) TAPKO Technologies GmbH + Im Gewerbepark A15 + Regensburg Bayern 93059 + DE + +74-19-F8 (hex) Marmitek +000000-0FFFFF (base 16) Marmitek + Postbus 4257 + Eindhoven NB 5604 EG + NL + +40-11-75 (hex) ShenZhen LanShuo Communication Equipment CO.,LTD. +600000-6FFFFF (base 16) ShenZhen LanShuo Communication Equipment CO.,LTD. + NO.12,YUMIN ROAD,SHAJING TOWN,BAO’AN DISTRICT + SHENZHEN 518104 + CN + +10-DC-B6 (hex) BBPOS International Limited +C00000-CFFFFF (base 16) BBPOS International Limited + Suite 1602, Tower 2, Nina Tower, 8 Yeung Uk Road, Tsuen Wan, NT + Hong Kong China 00000 + HK + +10-DC-B6 (hex) Eyeball Fintech Company +B00000-BFFFFF (base 16) Eyeball Fintech Company + Rm. 545, 5F., No. 19-11, Sanchong Rd., Nangang Dist. + Taipei City Taiwan 11501 + TW + +10-DC-B6 (hex) HANACNS +300000-3FFFFF (base 16) HANACNS + 42-11, Taejanggongdan-gil, Wonju-si + Gangwon-do 26311 + KR + +10-DC-B6 (hex) LeoLabs +D00000-DFFFFF (base 16) LeoLabs + Jankowicka 51 + Rybnik 44-218 + PL + +10-DC-B6 (hex) Fuzhou Rockchip Electronics Co.,Ltd +900000-9FFFFF (base 16) Fuzhou Rockchip Electronics Co.,Ltd + No. 18 Building, A District, No.89,software Boulevard Fuzhou,Fujian,PRC + Fuzhou FuJian 350003 + CN + +10-DC-B6 (hex) ABB Switzerland Ltd. +100000-1FFFFF (base 16) ABB Switzerland Ltd. + Fabrikstrasse 3 + Lenzburg 5600 + CH + +10-DC-B6 (hex) Milesight Taiwan +500000-5FFFFF (base 16) Milesight Taiwan + 10F., No. 87, Sec. 4, Chongxin Rd + Sanchong Dist New Taipei City 24161 + TW + +54-A4-93 (hex) BJ COTYTECH TECHNOLOGY CO.,LTD +C00000-CFFFFF (base 16) BJ COTYTECH TECHNOLOGY CO.,LTD + Rm2302,Block B,Haojing Building,Zhichun Road,Haidian District + BeiJing BeiJing 100086 + CN + +54-A4-93 (hex) Hannto Technology Co., Ltd +600000-6FFFFF (base 16) Hannto Technology Co., Ltd + Rm 704,No.1,Lane 88,Shengrong Road, Free Trade Pilot Area, + Shanghai Shanghai 200120 + CN + +54-A4-93 (hex) genua GmbH +200000-2FFFFF (base 16) genua GmbH + Domagkstr. 7 + Kirchheim 85551 + DE + +04-D1-6E (hex) Metra Electronics +A00000-AFFFFF (base 16) Metra Electronics + 460 Walker Street + Holly Hill FL 32117 + US + +04-D1-6E (hex) ETL Elektrotechnik Lauter GmbH +600000-6FFFFF (base 16) ETL Elektrotechnik Lauter GmbH + Konrad-Zuse-Str. 2 + Mauerstetten Bavaria 87665 + DE + +04-D1-6E (hex) Beijing Huaxia Qixin Technology Co., Ltd. +300000-3FFFFF (base 16) Beijing Huaxia Qixin Technology Co., Ltd. + 7th Floor, Building 1, No. 18, Yangfangdian Road, Haidian District, Beijing 705 + Beijing Beijing 100038 + CN + +04-D1-6E (hex) National Radio & Telecommunication Corporation - NRTC +B00000-BFFFFF (base 16) National Radio & Telecommunication Corporation - NRTC + House 420, Street 13, Chaklala Scheme 3 + Rawalpindi Islamabad 46000 + PK + +04-D1-6E (hex) INTRIPLE, a.s. +000000-0FFFFF (base 16) INTRIPLE, a.s. + K Zelenci 2957/5 + Praha 9 - Horni Pocernice 193 00 + CZ + +44-03-77 (hex) SHENZHEN UT-KING TECHNOLOGY CO.,LTD +900000-9FFFFF (base 16) SHENZHEN UT-KING TECHNOLOGY CO.,LTD + 504, Building B ,Guangming Industrial Park, Zhonghua Road, Minzhi, Longhua District + SHENZHEN GUANGDONG 518131 + CN + +44-03-77 (hex) Gemmy Electronics (Shenzhen) Co, Ltd +800000-8FFFFF (base 16) Gemmy Electronics (Shenzhen) Co, Ltd + Datianyang Ind. Estate, Dongfang Road, Dangfang Road, Songgang Town, Bao'an District + Shenzhen Guangdong 518105 + CN + +44-03-77 (hex) BIG Climatic Manufacture, Co. LTD, Zhongshan Branch +C00000-CFFFFF (base 16) BIG Climatic Manufacture, Co. LTD, Zhongshan Branch + Nantou Dadao, 20 + Zhongshan Guangdong 528427 + CN + +50-62-55 (hex) Shenzhen Sinway South Technology Co., Ltd +600000-6FFFFF (base 16) Shenzhen Sinway South Technology Co., Ltd + No.7, Guantian Road, Guanlan Street, Longhua District + Shenzhen Guangdong 518110 + CN + +50-62-55 (hex) CHENGDU COVE TECHNOLOGY CO.,LTD +B00000-BFFFFF (base 16) CHENGDU COVE TECHNOLOGY CO.,LTD + No.1-3, Floor 4, Building 2,No.1366 Middle Section of Tianfu Ave + Chengdu SICHUAN 610000 + CN + +50-62-55 (hex) XSLAB Inc. +400000-4FFFFF (base 16) XSLAB Inc. + #1103, 11, DIGITAL-RO 33-GIL, GURO-GU + SEOUL 08380 + KR + +50-62-55 (hex) ShenZhen ChuangMo Electronics Technology Co., Ltd +200000-2FFFFF (base 16) ShenZhen ChuangMo Electronics Technology Co., Ltd + West Floor 4,building A,Bafangyuan high and new industrial zone,No.108 Zhoushi Rd.,Shiyan sub-district,Baoan, + Shenzhen Guangdong 518108 + CN + +64-31-39 (hex) SHENZHEN EMEET INTELLIGENT TECHNOLOGY CO., LTD. +000000-0FFFFF (base 16) SHENZHEN EMEET INTELLIGENT TECHNOLOGY CO., LTD. + Unit 2C,Building A6,Guangming Science Park,Guangming Road 3009 + Shenzhen Guangdong 518000 + CN + +64-31-39 (hex) ZHEJIANG MOORGEN INTELLIGENT TECHNOLOGY CO.,LTD +D00000-DFFFFF (base 16) ZHEJIANG MOORGEN INTELLIGENT TECHNOLOGY CO.,LTD + 5 / F, Building A, qinghua pioneer park?No. 318 Tianhu Road, Camel Street, Zhenhai District + Ningbo 315202 + CN + +64-31-39 (hex) ATG UV Technology +E00000-EFFFFF (base 16) ATG UV Technology + Genesis House + Wigan WN5 8AA + GB + +C4-95-4D (hex) Marble Automation +500000-5FFFFF (base 16) Marble Automation + Keteldiep 6 + Urk 8321 MH + NL + +00-69-67 (hex) Shenzhen Xiao Bi En Culture Education Technology Co.,Ltd. +500000-5FFFFF (base 16) Shenzhen Xiao Bi En Culture Education Technology Co.,Ltd. + 4GH Unit,Block D,Central Avenue,Intersection of Xixiang Avenue and Baoyuan Road,Labor Community,Xixiang Street,Baoan District + Shenzhen China 518102 + CN + +00-69-67 (hex) Annapurna labs +000000-0FFFFF (base 16) Annapurna labs + Matam Scientific Industries Center, Building 8.2 + Mail box 15123 Haifa 3508409 + IL + +00-69-67 (hex) Suzhou Radiant Lighting Technology Co.,Ltd +300000-3FFFFF (base 16) Suzhou Radiant Lighting Technology Co.,Ltd + Jiatai Road West, Shuanglong Industrial Park,Fenghuang Town + Zhangjiagang Jiangsu 215600 + CN + +A0-22-4E (hex) Zhuhai Cheer Technology Co., LTD. +500000-5FFFFF (base 16) Zhuhai Cheer Technology Co., LTD. + No.8 Hongwan Road, Hongwan Industry Zone, Xiangzhou District + Zhuhai Guangdong 519060 + CN + +A0-22-4E (hex) Digifocus Technology Inc. +D00000-DFFFFF (base 16) Digifocus Technology Inc. + 6F, No.89, Xinhu 1st Rd., Neihu Dist. + Taipei City 11494 + TW + +A0-22-4E (hex) Delta Tau Data Systems, Inc. +900000-9FFFFF (base 16) Delta Tau Data Systems, Inc. + 21314 Lassen St. + Chatsworth CA 91311 + US + +A0-22-4E (hex) Closed Joint-Stock Company NORSI-TRANS +200000-2FFFFF (base 16) Closed Joint-Stock Company NORSI-TRANS + B.Novodmitrovskaya Street, house 12, building 15 + Moscow 127015 + RU + +A0-22-4E (hex) All Inspire Health Inc. +B00000-BFFFFF (base 16) All Inspire Health Inc. + 19 Morris Avenue, Building 128, Cumberland Gate + Brooklyn NY 11205 + US + +20-0A-0D (hex) Welzek (Beijing) Technologies Co, Ltd +900000-9FFFFF (base 16) Welzek (Beijing) Technologies Co, Ltd + No 201,Building 12, Chaolai Science Park, No.36 Chuangyuan RoadLaiguangying, Chaoyang Disctrict + Beijing Beijing 100012 + CN + +20-0A-0D (hex) Virtium +400000-4FFFFF (base 16) Virtium + 30052 Tomas + Racho Santa MArgarita CA 92688 + US + +20-0A-0D (hex) halstrup-walcher GmbH +000000-0FFFFF (base 16) halstrup-walcher GmbH + Stegener Straße 10 + Kirchzarten 79199 + DE + +40-2C-76 (hex) gridX GmbH +C00000-CFFFFF (base 16) gridX GmbH + Oppenhoffallee 143 + Aachen 52066 + DE + +50-DE-19 (hex) OCEANCCTV LTD +600000-6FFFFF (base 16) OCEANCCTV LTD + 4F., No. 1, Ln. 297, Xinyi Rd.,Banqiao Dist., + New Taipei City 220 + TW + +40-2C-76 (hex) LS Energy Solutions +E00000-EFFFFF (base 16) LS Energy Solutions + 9201 Forsyth Park Drive + Charlotte NC 28273 + US + +50-DE-19 (hex) IVATIV, INC +800000-8FFFFF (base 16) IVATIV, INC + 6141 RUNNING SPRINGS RD + SAN JOSE CA 95135 + US + +3C-FA-D3 (hex) Nox Medical +600000-6FFFFF (base 16) Nox Medical + Katrinartun 2 + Reykjavik 105 + IS + +B0-B3-53 (hex) AD HOC DEVELOPMENTS S.L +300000-3FFFFF (base 16) AD HOC DEVELOPMENTS S.L + C/ Crisol 3 + RIVAS-VACIAMADRID Madrid 28522 + ES + +B0-B3-53 (hex) Hangzhou Hikrobot Technology Co., Ltd. +600000-6FFFFF (base 16) Hangzhou Hikrobot Technology Co., Ltd. + Room 304, Unit B, Building 2, 399 Danfeng Road, Binjiang District, Hangzhou, Zhejiang + Hangzhou 310052 + CN + +B0-B3-53 (hex) Sprocomm Technologies CO.,LTD. +100000-1FFFFF (base 16) Sprocomm Technologies CO.,LTD. + 5D F1.6 Block,Tianfa Building,Tianan Chegongmiao Industrial park,Futian Dist + shenzhen guangdong 518000 + CN + +B0-B3-53 (hex) VOXISCOM +800000-8FFFFF (base 16) VOXISCOM + Rue Jules Ferry + PORNIC 44210 + FR + +B0-B3-53 (hex) Innotas Elektronik GmbH +400000-4FFFFF (base 16) Innotas Elektronik GmbH + Rathenaustr. 18a + Zittau D-02763 + DE + +3C-FA-D3 (hex) Mirico +E00000-EFFFFF (base 16) Mirico + 30 DongSan Rd 9th floor Mirico + Ansan Gyunggi 15434 + KR + +90-E2-FC (hex) Power Engineering & Manufacturing, Inc. +A00000-AFFFFF (base 16) Power Engineering & Manufacturing, Inc. + 1463 94th Lane NE + Blaine MN 55449 + US + +90-E2-FC (hex) Sindoh Techno Co., Ltd. +600000-6FFFFF (base 16) Sindoh Techno Co., Ltd. + Sindoh Bldg., 6, Hyoryeong-ro 61-gil, Seocho-gu + Seoul 06643 + KR + +90-E2-FC (hex) Shenzhen Hisource Technology Development CO.,Ltd. +300000-3FFFFF (base 16) Shenzhen Hisource Technology Development CO.,Ltd. + Dalang + Shenzhen Guangdong 518109 + CN + +90-E2-FC (hex) TOTALONE TECHNOLOGY CO., LTD. +500000-5FFFFF (base 16) TOTALONE TECHNOLOGY CO., LTD. + 3F.-1, NO.18, LN. 48, XingShan RD., + Taipei Neihu dist 11469 + TW + +90-E2-FC (hex) Yite technology +100000-1FFFFF (base 16) Yite technology + No. 56, Xiaobei Rd., North Dist + tainan 70448 + TW + +90-E2-FC (hex) DevCom spol. s r.o. +E00000-EFFFFF (base 16) DevCom spol. s r.o. + Božanovská 884 + Praha Select a State 19300 + CZ + +14-AE-85 (hex) IO Industries Inc. +C00000-CFFFFF (base 16) IO Industries Inc. + 15940 Robin's Hill Rd + London Ontario N5V 0A4 + CA + +14-AE-85 (hex) AZ-TECHNOLOGY SDN BHD +500000-5FFFFF (base 16) AZ-TECHNOLOGY SDN BHD + A108 & A109 BLOCK A KELANA BUSINESS CENTRE NO: 97 JALAN SS7/2 KELANA JAYA + PETALING JAYA SELANGOR 47301 + MY + +14-AE-85 (hex) CENTERVUE SPA +400000-4FFFFF (base 16) CENTERVUE SPA + VIA SAN MARCO 9/H + PADOVA PADOVA 35129 + IT + +90-E2-FC (hex) Fair Winds Digital srl +700000-7FFFFF (base 16) Fair Winds Digital srl + Via Italo Svevo 85 + Rome Italy 00137 + IT + +14-AE-85 (hex) TMG TE GmbH +600000-6FFFFF (base 16) TMG TE GmbH + Zur Gießerei 10 + Karlsruhe 776227 + DE + +14-AE-85 (hex) NTC SOFT +B00000-BFFFFF (base 16) NTC SOFT + B-805, Gwangmyeong SK Techno park, 60, Haan-ro, + Gwangmyeong-si Gyeonggi-do 14322 + KR + +14-AE-85 (hex) Sercomm Corporation. +E00000-EFFFFF (base 16) Sercomm Corporation. + 3F,No.81,Yu-Yih Rd.,Chu-Nan Chen + Miao-Lih Hsuan 115 + TW + +64-62-66 (hex) Jiangsu Aisida Electronic Co.,Ltd +C00000-CFFFFF (base 16) Jiangsu Aisida Electronic Co.,Ltd + Aisida Industrial Park,Lanling Road,Danyang Development Zone + DanYang JiangSu 212300 + CN + +94-CC-04 (hex) Hangzhou Yongkong Technology Co., Ltd. +000000-0FFFFF (base 16) Hangzhou Yongkong Technology Co., Ltd. + Room 503, Building 12, Lefu Zhihui Garden, 28 Xiangyuan Road, Gongshu Distric + Hangzhou Zhejiang 310000 + CN + +94-CC-04 (hex) Gowing Business And Contracting Wenzhou Co., LTD +700000-7FFFFF (base 16) Gowing Business And Contracting Wenzhou Co., LTD + Room 101, No.4 Liming Industrial District, Lucheng, Wenzhou, China + Wenzhou 325000 + CN + +94-CC-04 (hex) CircuitWerkes, Inc. +800000-8FFFFF (base 16) CircuitWerkes, Inc. + 2805 NW 6th St + Gainesville FL 32609 + US + +14-AE-85 (hex) IFLYTEK CO.,LTD. +300000-3FFFFF (base 16) IFLYTEK CO.,LTD. + National Intelligent Speech High-tech Industrialization Base, No. 666, Wangjiang Road West, + Hefei An hui 230088 + CN + +94-05-BB (hex) Shenzhen Baolijie Technology Co., Ltd. +400000-4FFFFF (base 16) Shenzhen Baolijie Technology Co., Ltd. + D2,No.47,Shasan Road,Sha jing Street,Baoan District + Shenzhen Kowloon 518104 + CN + +94-CC-04 (hex) ProConnections, Inc. +400000-4FFFFF (base 16) ProConnections, Inc. + 30 Massachusetts, Ave, Suite 301 + North Andover MA 01845 + US + +94-05-BB (hex) Neurik AG +300000-3FFFFF (base 16) Neurik AG + Im alten Riet 143 + Schaan SCHAAN 9494 + LI + +94-05-BB (hex) Dongguan Kingtron Electronics Tech Co., Ltd +100000-1FFFFF (base 16) Dongguan Kingtron Electronics Tech Co., Ltd + No.3 Fumin North Rd,Shu'an Industrial Park, Humen Town + Dongguan Guangdong China 523929 + CN + +94-05-BB (hex) Sunthink S&T Development Co.,Ltd +D00000-DFFFFF (base 16) Sunthink S&T Development Co.,Ltd + A3-f1, xinghezhong Technology Green Valley, No.14, luolei Industrial Avenue, Shiyan street, Bao'an District + Shenzhen 518100 + CN + +DC-44-27 (hex) Tesla,Inc. +100000-1FFFFF (base 16) Tesla,Inc. + 3500 Deer Creek Road + Palo Alto CA 94304 + US diff --git a/hwdb.d/ma-small.txt b/hwdb.d/ma-small.txt new file mode 100644 index 00000000..31d6fce3 --- /dev/null +++ b/hwdb.d/ma-small.txt @@ -0,0 +1,21870 @@ +OUI Organization +OUI-36/MA-S Range Organization + Address + +70-B3-D5 (hex) TELEPLATFORMS +F2F000-F2FFFF (base 16) TELEPLATFORMS + Polbina st., 3/1 + Moscow 109388 + RU + +70-B3-D5 (hex) 2M Technology +719000-719FFF (base 16) 2M Technology + 802 Greenview Drive + Grand Prairie TX 75050 + US + +70-B3-D5 (hex) Truecom Telesoft Private Limited +9FC000-9FCFFF (base 16) Truecom Telesoft Private Limited + 2nd Floor, Block N, Safal Mondeal Retail Park, S.G Highway, Bodakdev + Ahmedabad Gujarat 380056 + IN + +70-B3-D5 (hex) DSILOG +577000-577FFF (base 16) DSILOG + 104 rue Marcel Pagnol + Voreppe 38340 + FR + +70-B3-D5 (hex) Radikal d.o.o. +56F000-56FFFF (base 16) Radikal d.o.o. + J. Mise 8 + Sesvete Sesvete 10360 + HR + +70-B3-D5 (hex) OSAKI DATATECH CO., LTD. +A0F000-A0FFFF (base 16) OSAKI DATATECH CO., LTD. + 2-1-10 Higashi-Gotanda Shinagawa-ku + Tokyo 141-0022 + JP + +70-B3-D5 (hex) Ochno AB +03A000-03AFFF (base 16) Ochno AB + c/o Westras, Kopparbergsv 6 + Västerås 72213 + SE + +70-B3-D5 (hex) Sanwa New Tec Co.,Ltd +155000-155FFF (base 16) Sanwa New Tec Co.,Ltd + 6536 Honjyou + Kunitomi-cho Higashimorokata-gun Miyazaki 880-1101 + JP + +70-B3-D5 (hex) VECTOR.CO.,LTD. +D33000-D33FFF (base 16) VECTOR.CO.,LTD. + 2-12-16 Ekiminami + Kosai Shizuoka 431-0427 + JP + +70-B3-D5 (hex) Acrodea, Inc. +6A4000-6A4FFF (base 16) Acrodea, Inc. + 3F, Daisan Yamada Bldg., 22 Aizumi-cho + Shinjuku-ku Tokyo 1600005 + JP + +70-B3-D5 (hex) ООО РОНЕКС +F3E000-F3EFFF (base 16) ООО РОНЕКС + Автомобильный проезд, д. 10, стр. 4, пом. 201 + Москва Россия, Московская область 109052 + RU + +70-B3-D5 (hex) Clearly IP Inc +9B0000-9B0FFF (base 16) Clearly IP Inc + 2416 Industrial Dr Unit F + Neenah WI 54956 + US + +70-B3-D5 (hex) BARCO, s.r.o. +62F000-62FFFF (base 16) BARCO, s.r.o. + Hradistska 849 + Buchlovice 68708 + CZ + +70-B3-D5 (hex) C Tech Bilişim Teknolojileri San. ve Tic. AŞ +DCD000-DCDFFF (base 16) C Tech Bilişim Teknolojileri San. ve Tic. AŞ + Teknopark İstanbul, TGB, Sanayi Mah. Teknopark Bulvarı, No:1, Blok:1 Kat:2, Kurtköy-Pendik 34912, İSTANBUL + Istanbul 34912 + TR + +70-B3-D5 (hex) BRS Sistemas Eletrônicos +356000-356FFF (base 16) BRS Sistemas Eletrônicos + Rua Gomes de Freitas, 491 / 204 + Porto Alegre RS 91380-000 + BR + +70-B3-D5 (hex) VITEC +D61000-D61FFF (base 16) VITEC + 99 rue pierre sémard + Chatillon France 92320 + FR + +70-B3-D5 (hex) RCH ITALIA SPA +A34000-A34FFF (base 16) RCH ITALIA SPA + VIA CENDON 39 + SILEA TREVISO 31057 + IT + +70-B3-D5 (hex) Wagner Group GmbH +59A000-59AFFF (base 16) Wagner Group GmbH + Schleswigstrasse 1-5 + Langenhagen 30853 + DE + +70-B3-D5 (hex) FX TECHNOLOGY LIMITED +FCE000-FCEFFF (base 16) FX TECHNOLOGY LIMITED + 38a High Street, Northwood + Middlesex - HA6 1BN + GB + +70-B3-D5 (hex) CT Company +667000-667FFF (base 16) CT Company + Godovikova , 9, Moscow + Moscow RUSSIA 129085 + RU + +70-B3-D5 (hex) Zhejiang Zhaolong Interconnect Technology Co.,Ltd +A68000-A68FFF (base 16) Zhejiang Zhaolong Interconnect Technology Co.,Ltd + Shilin Industrial Zone,Xinshi, Deqing,Zhejiang,China + Deqing Zhejiang 313200 + CN + +70-B3-D5 (hex) ENTEC Electric & Electronic Co., LTD. +C7A000-C7AFFF (base 16) ENTEC Electric & Electronic Co., LTD. + 78-2 Buncheon-ri, Bongdam-eup + Hwaseong-city Gyungki-do 445-894 + KR + +70-B3-D5 (hex) Private +6F4000-6F4FFF (base 16) Private + +70-B3-D5 (hex) Guan Show Technologe Co., Ltd. +1FC000-1FCFFF (base 16) Guan Show Technologe Co., Ltd. + No.127, Jianguo 1st Rd., Lingya Dist. + Kaohsiung City 802 + TW + +70-B3-D5 (hex) LLC NPO Svyazkomplektservis +588000-588FFF (base 16) LLC NPO Svyazkomplektservis + Bronnitskaya str., 3 + Podolsk Moscow region 142103 + RU + +70-B3-D5 (hex) Equos Research Co., Ltd +34D000-34DFFF (base 16) Equos Research Co., Ltd + Akihabara Daibiru 7F, 1-18-13 Sotokanda + Chiyoda-ku Tokyo 101-0021 + JP + +70-B3-D5 (hex) Aetina Corporation +171000-171FFF (base 16) Aetina Corporation + 2F-1, No.237, Sec.1, Datong Rd., Xizhi Dist., + New Taipei City No State 221 + TW + +70-B3-D5 (hex) ECOINET +420000-420FFF (base 16) ECOINET + 519, 2 Gasandigital 1ro, Geumcheon-gu + seoul 08591 + KR + +70-B3-D5 (hex) Southern Ground Audio LLC +CD4000-CD4FFF (base 16) Southern Ground Audio LLC + 101 Gardner Park + Peachtree City GA 30269 + US + +70-B3-D5 (hex) DEUTA-WERKE GmbH +13A000-13AFFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach 51465 + DE + +70-B3-D5 (hex) Hermann Automation GmbH +B2F000-B2FFFF (base 16) Hermann Automation GmbH + Erlenwiese 15 + Mengerskirchen Hessen D-35794 + DE + +70-B3-D5 (hex) Worldsensing +2C7000-2C7FFF (base 16) Worldsensing + Carrer Viriat 47, Edificio Numancia 1 7th floor + Barcelona - Please Choose - 08014 + ES + +70-B3-D5 (hex) BAYKON Endüstriyel Kontrol Sistemleri San. ve Tic. A.Ş. +258000-258FFF (base 16) BAYKON Endüstriyel Kontrol Sistemleri San. ve Tic. A.Ş. + Kimya Sanayicileri Org. San. Bolgesi Organik Cad. No:31 + Istanbul Tuzla 34956 + TR + +70-B3-D5 (hex) wtec GmbH +ABD000-ABDFFF (base 16) wtec GmbH + Dornbachstrasse 1a + Bad Homburg 61352 + DE + +70-B3-D5 (hex) DAO QIN TECHNOLOGY CO.LTD. +3BD000-3BDFFF (base 16) DAO QIN TECHNOLOGY CO.LTD. + No. 359, Zhongxiao Rd + Chishang Township Taitung County 958 + TW + +70-B3-D5 (hex) Ascon Tecnologic S.r.l. +57E000-57EFFF (base 16) Ascon Tecnologic S.r.l. + via Indipendenza, 56 + Vigevano PV 27029 + IT + +70-B3-D5 (hex) Private +2D7000-2D7FFF (base 16) Private + +70-B3-D5 (hex) Idneo Technologies S.A.U. +CF8000-CF8FFF (base 16) Idneo Technologies S.A.U. + Gran Via Carlos III , 98 Planta 5 + Barcelona Barcelona 08028 + ES + +70-B3-D5 (hex) Private +A9F000-A9FFFF (base 16) Private + +70-B3-D5 (hex) Arevita +5E1000-5E1FFF (base 16) Arevita + Baltu ave 145 + Kaunas Select 47125 + LT + +70-B3-D5 (hex) Virsae Group Ltd +151000-151FFF (base 16) Virsae Group Ltd + B:HIVE, 74 Taharoto Road, Smales Farm + Takapuna Auckland 0622 + NZ + +70-B3-D5 (hex) Automata GmbH & Co. KG +1F9000-1F9FFF (base 16) Automata GmbH & Co. KG + Gewerbering 5 + Ried Bavaria 86510 + DE + +70-B3-D5 (hex) AMEDTEC Medizintechnik Aue GmbH +50A000-50AFFF (base 16) AMEDTEC Medizintechnik Aue GmbH + Schneeberger Str. 5 + Aue 08280 + DE + +70-B3-D5 (hex) OCEANCCTV LTD +FD5000-FD5FFF (base 16) OCEANCCTV LTD + 4F., No. 1, Ln. 297, Xinyi Rd.,Banqiao Dist., + New Taipei City 220 + TW + +70-B3-D5 (hex) Blake UK +9DA000-9DAFFF (base 16) Blake UK + 177-187, Rutland Road + Sheffield --select-- S3 9PT + GB + +70-B3-D5 (hex) Angora Networks +822000-822FFF (base 16) Angora Networks + Alacaatli Mah. Park Cad 47/31, Cayyolu + Ankara 06810 + TR + +70-B3-D5 (hex) Clever Devices +A2B000-A2BFFF (base 16) Clever Devices + 300 Crossways Park Dr + Woodbury NY 11797 + US + +70-B3-D5 (hex) Sikom AS +237000-237FFF (base 16) Sikom AS + Neptunvegen 6 + Verdal 7652 + NO + +70-B3-D5 (hex) MIRAE INFORMATION TECHNOLOGY CO., LTD. +056000-056FFF (base 16) MIRAE INFORMATION TECHNOLOGY CO., LTD. + GYEONGGI-DO + SEONGNAM-SI JUNGWON-GU 13376 + KR + +70-B3-D5 (hex) Invent Vision - iVision Sistemas de Imagem e Visão S.A. +E29000-E29FFF (base 16) Invent Vision - iVision Sistemas de Imagem e Visão S.A. + R. Prof. José Vieira de Mendonça, 770, 2° andar - BHTEC, Parque Tecnológico de Belo Horizonte + Belo Horizonte Minas Gerais 31310-260 + BR + +70-B3-D5 (hex) COSMOIT.CO.LTD +754000-754FFF (base 16) COSMOIT.CO.LTD + 14Fl., Ace Twin Tower II, 273, Digital-ro, Guro-gu + Seoul 08381 + KR + +70-B3-D5 (hex) Sicon srl +BEE000-BEEFFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) Sanmina Israel +66D000-66DFFF (base 16) Sanmina Israel + Koren Industrial Zone , POBox 102 + Maalot Israel 2101002 + IL + +70-B3-D5 (hex) XANTIA SA +33F000-33FFFF (base 16) XANTIA SA + Chemin du Longchamps 99 + Bienne 2504 + CH + +70-B3-D5 (hex) Acutronic Link Robotics AG +21A000-21AFFF (base 16) Acutronic Link Robotics AG + Calle Venta de la Estrella, 6 Pab. 130 + VITORIA-GASTEIZ ALAVA 01003 + ES + +70-B3-D5 (hex) Xiamen Beogold Technology Co. Ltd. +490000-490FFF (base 16) Xiamen Beogold Technology Co. Ltd. + 11F Amoy Institute of Technovation,Jimei District + Xiamen Fujian 361021 + CN + +70-B3-D5 (hex) Benetel +E15000-E15FFF (base 16) Benetel + Guinness Enterprise Centre, Taylors Lane, + Dublin D08 XV25 + IE + +70-B3-D5 (hex) Zaxcom Inc +9CC000-9CCFFF (base 16) Zaxcom Inc + 230 West Parkway STE 9 + Pompton Plains NJ 07444 + US + +70-B3-D5 (hex) RADAR +CB1000-CB1FFF (base 16) RADAR + 547 W 27th St. + NEW YORK NY 10001-5670 + US + +70-B3-D5 (hex) Soehnle Industrial Solutions GmbH +F89000-F89FFF (base 16) Soehnle Industrial Solutions GmbH + Gaildorfer Strasse 6 + Backnang 71522 + DE + +70-B3-D5 (hex) vision systems safety tech +98A000-98AFFF (base 16) vision systems safety tech + Route d’Irigny – ZI NORD - BP 32 + Brignais Rhone alpes auverne 69530 + FR + +70-B3-D5 (hex) GMI Ltd +C93000-C93FFF (base 16) GMI Ltd + Inchinnan Business Park + Renfre PA4 9RG + GB + +70-B3-D5 (hex) ENTEC Electric & Electronic Co., LTD. +1DF000-1DFFFF (base 16) ENTEC Electric & Electronic Co., LTD. + 78-2 Buncheon-ri, Bongdam-eup + Hwaseong-city Gyungki-do 445-894 + KR + +70-B3-D5 (hex) comtac AG +F3F000-F3FFFF (base 16) comtac AG + Allenwindenstrasse 1 + Flurlingen 8247 + CH + +70-B3-D5 (hex) DEUTA-WERKE GmbH +E33000-E33FFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) ALBIRAL DISPLAY SOLUTIONS SL +497000-497FFF (base 16) ALBIRAL DISPLAY SOLUTIONS SL + Fàtima 25 + Sant Hipòlit de Voltregà Barcelona 08512 + ES + +70-B3-D5 (hex) PABLO AIR Co., LTD +9A9000-9A9FFF (base 16) PABLO AIR Co., LTD + #E-1606, 30, Songdomirae-ro, Yeonsu-gu + Incheon 21990 + KR + +70-B3-D5 (hex) Cloud Intelligence Pty Ltd +574000-574FFF (base 16) Cloud Intelligence Pty Ltd + 43/10 Gladstone Rd + Castle Hill NSW 2154 + AU + +70-B3-D5 (hex) COMPAL ELECTRONICS, INC. +4F2000-4F2FFF (base 16) COMPAL ELECTRONICS, INC. + No.500, Ruiguang Rd., Neihu District, + Taipei 11492 + TW + +70-B3-D5 (hex) RCH ITALIA SPA +5D4000-5D4FFF (base 16) RCH ITALIA SPA + VIA CENDON 39 + SILEA TREVISO 31057 + IT + +70-B3-D5 (hex) iOne +330000-330FFF (base 16) iOne + 8F-2, #75, sec 1, Hsin Tai Wu Rd., Hsi Chih District + New Taipei City, Taiwan 22101 + TW + +70-B3-D5 (hex) Private +9EE000-9EEFFF (base 16) Private + +70-B3-D5 (hex) Wuhan Xingtuxinke ELectronic Co.,Ltd +70E000-70EFFF (base 16) Wuhan Xingtuxinke ELectronic Co.,Ltd + NO.C3-8F,Software Park,Optics Valley,East Lake Development Zone,Wuhan,Hubei,China + Wuhan Hubei 430074 + CN + +70-B3-D5 (hex) Airity Technologies Inc. +545000-545FFF (base 16) Airity Technologies Inc. + 1505 Woodside Rd + Redwood City CA 94061 + US + +70-B3-D5 (hex) Elbit Systems of America +C24000-C24FFF (base 16) Elbit Systems of America + 4700 Marine Creek Parkway + Fort Worth TX 76179 + US + +70-B3-D5 (hex) Private +6CF000-6CFFFF (base 16) Private + +70-B3-D5 (hex) ProHound Controles Eirelli +0D0000-0D0FFF (base 16) ProHound Controles Eirelli + Rua Felipe José de Figueiredo, 45 + São Paulo São Paulo 03807300 + BR + +70-B3-D5 (hex) Samriddi Automations Pvt. Ltd. +BBA000-BBAFFF (base 16) Samriddi Automations Pvt. Ltd. + F-365 + Noida up 201307 + IN + +70-B3-D5 (hex) Monnit Corporation +D1A000-D1AFFF (base 16) Monnit Corporation + 3400 S West Temple + Taylorsville UT 84115 + US + +70-B3-D5 (hex) Hypex Electronics BV +287000-287FFF (base 16) Hypex Electronics BV + Kattegat 8 + Groningen Groningen 9723 JP + NL + +70-B3-D5 (hex) Algodue Elettronica Srl +49B000-49BFFF (base 16) Algodue Elettronica Srl + Via Passerina 3/A + Fontaneto d'Agogna Novara 28010 + IT + +70-B3-D5 (hex) ASML +DE5000-DE5FFF (base 16) ASML + 17075 Thornmint Ct + San Diego 92127 + US + +70-B3-D5 (hex) O-Net Communications(Shenzhen)Limited +9A2000-9A2FFF (base 16) O-Net Communications(Shenzhen)Limited + No. 35, Cuijing Road, Pingshan New District + Shenzhen Guangdong 518118 + CN + +70-B3-D5 (hex) Camwell India LLP +E78000-E78FFF (base 16) Camwell India LLP + Plot no 72/11/2, Ground Floor + Mundka DELHI 110041 + IN + +70-B3-D5 (hex) Guan Show Technologe Co., Ltd. +752000-752FFF (base 16) Guan Show Technologe Co., Ltd. + No.127, Jianguo 1st Rd., Lingya Dist. + Kaohsiung City 802 + TW + +70-B3-D5 (hex) Sonel S.A. +F71000-F71FFF (base 16) Sonel S.A. + Wokulskiego 11 + Swidnica Dolnoslaskie 58-100 + PL + +70-B3-D5 (hex) Siemens Mobility GmbH - MO TI SPA +E40000-E40FFF (base 16) Siemens Mobility GmbH - MO TI SPA + Rudower Chaussee 29 + Berlin Berlin 12489 + DE + +70-B3-D5 (hex) PEEK TRAFFIC +0C7000-0C7FFF (base 16) PEEK TRAFFIC + 5401 N SAM HOUSTON PKWY W + HOUSTON null 77086 + US + +70-B3-D5 (hex) DEVAU Lemppenau GmbH +4A2000-4A2FFF (base 16) DEVAU Lemppenau GmbH + Wolbringstrasse 12 + Bocholt NRW 46397 + DE + +70-B3-D5 (hex) Tieline Research Pty Ltd +FCB000-FCBFFF (base 16) Tieline Research Pty Ltd + PO Box 2092 + MALAGA Western Australia 6944 + AU + +70-B3-D5 (hex) National Radio & Telecommunication Corporation - NRTC +949000-949FFF (base 16) National Radio & Telecommunication Corporation - NRTC + T&T Complex, Haripur + Haripur KPK 22620 + PK + +70-B3-D5 (hex) Electrónica Falcón S.A.U +36E000-36EFFF (base 16) Electrónica Falcón S.A.U + Polígono Industrial Escopar, Calle E, Nº 1 + Peralta Navarra 31350 + ES + +70-B3-D5 (hex) Hessware GmbH +7AF000-7AFFFF (base 16) Hessware GmbH + Weinheimer Straße 68 + Mannheim BW 68309 + DE + +70-B3-D5 (hex) Authenticdata +836000-836FFF (base 16) Authenticdata + 12F-8, No.100, Sec. 1, Jiafeng 11th Rd., Zhubei City + HsinChu 30273 + TW + +70-B3-D5 (hex) ISAC SRL +07C000-07CFFF (base 16) ISAC SRL + via Maestri del Lavoro 30 + CASCINA PISA 56021 + IT + +70-B3-D5 (hex) FARECO +8AE000-8AEFFF (base 16) FARECO + 8 EUROPARC de la Sainte Victoire + MEYREUIL 13590 + FR + +70-B3-D5 (hex) Advice +926000-926FFF (base 16) Advice + 16 Atir Yeda St + Kfar Saba Not applicable 4464321 + IL + +70-B3-D5 (hex) robert juliat +EE8000-EE8FFF (base 16) robert juliat + 32 route de beaumont + fresnoy en thelle Oise 60530 + FR + +70-B3-D5 (hex) LINEAGE POWER PVT LTD., +9C5000-9C5FFF (base 16) LINEAGE POWER PVT LTD., + 30-A1, KIADB, 1ST PHASE INDUSTRIAL ESTATE,KUMBALGODU, BANGALORE-MYSORE ROAD + BANGALORE KARNATAKA 560074 + IN + +70-B3-D5 (hex) VNT electronics s.r.o. +0E9000-0E9FFF (base 16) VNT electronics s.r.o. + Dvorská, 605 + Lanškroun-Ostrovské Předměstí (okres Ústí nad Orlicí) 56301 + CZ + +70-B3-D5 (hex) Airmar Technology Corp +08C000-08CFFF (base 16) Airmar Technology Corp + 35 Meadowbrook Dr + Milford NH 03055 + US + +70-B3-D5 (hex) Myostat Motion Control Inc +96E000-96EFFF (base 16) Myostat Motion Control Inc + 17817 Leslie St #21 + Newmarket ON L3Y8C6 + CA + +70-B3-D5 (hex) AUDI AG +01B000-01BFFF (base 16) AUDI AG + Auto-Union-Strasse 1 + Ingolstadt 85045 + DE + +70-B3-D5 (hex) FSR, INC. +A44000-A44FFF (base 16) FSR, INC. + 244 Bergen Blvd + Wodland Park NJ 07424 + US + +70-B3-D5 (hex) DEUTA-WERKE GmbH +E47000-E47FFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +CBA000-CBAFFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) chiconypower +3A0000-3A0FFF (base 16) chiconypower + 23F, No.69, Sec. 2, Guangfu Rd., Sanchong Dist., New Taipei City 241, Taiwan (R.O.C.) + New Taipei Taiwan 241 + TW + +70-B3-D5 (hex) HD Vision Systems GmbH +F18000-F18FFF (base 16) HD Vision Systems GmbH + Berliner Str. 43 + Heidelberg 69120 + DE + +70-B3-D5 (hex) Signals and systems india pvt ltd +2ED000-2EDFFF (base 16) Signals and systems india pvt ltd + 15/D-19, 3rd Main Road, SIPCOT IT PARK, SIRUSERI, OMR + CHENNAI TAMIL NADU 603103 + IN + +70-B3-D5 (hex) Piranha EMS Inc. +006000-006FFF (base 16) Piranha EMS Inc. + 2681 Zanker Road + San Jose CA 95134 + US + +70-B3-D5 (hex) Biotage Sweden AB +4D2000-4D2FFF (base 16) Biotage Sweden AB + Vimpelgatan 5 + Uppsala 753 18 + SE + +70-B3-D5 (hex) Datamars SA +AA9000-AA9FFF (base 16) Datamars SA + Via Industria 16 + Lamone 6814 + CH + +70-B3-D5 (hex) Peter Huber Kaeltemaschinenbau AG +08B000-08BFFF (base 16) Peter Huber Kaeltemaschinenbau AG + Werner-von-Siemens-Str. 1 + Offenburg Ba-Wue 77656 + DE + +70-B3-D5 (hex) ESYSE GmbH Embedded Systems Engineering +008000-008FFF (base 16) ESYSE GmbH Embedded Systems Engineering + Ruth-Niehaus Str. 8 + Meerbusch Nordrhein-Westfalen 40667 + DE + +70-B3-D5 (hex) Toshiba Electron Tubes & Devices Co., Ltd. +D28000-D28FFF (base 16) Toshiba Electron Tubes & Devices Co., Ltd. + 1385, Shimoishigami + Otawara-shi Tochigi 324-8550 + JP + +70-B3-D5 (hex) Waldo System +CA1000-CA1FFF (base 16) Waldo System + 4th Floor, 658, Yangcheon-ro, Gangseo-gu, + Seoul 07554 + KR + +70-B3-D5 (hex) MOTION LIB,Inc. +27C000-27CFFF (base 16) MOTION LIB,Inc. + Saiwai-ku ,Shinkawasaki 7-7-237 + Kawasaki City Kanagawa 212-0032 + JP + +70-B3-D5 (hex) APG Cash Drawer, LLC +ACF000-ACFFFF (base 16) APG Cash Drawer, LLC + 5250 Industrial Blvd NE + Minneapolis MN 55421 + US + +70-B3-D5 (hex) Gastech Australia Pty Ltd +793000-793FFF (base 16) Gastech Australia Pty Ltd + 24 Baretta Road + Wanagra WA 6065 + AU + +70-B3-D5 (hex) Microvideo +4E0000-4E0FFF (base 16) Microvideo + Copley Hill Business Park, Cambridge Road + Babraham CB22 3GN + GB + +70-B3-D5 (hex) Cambria Corporation +B6B000-B6BFFF (base 16) Cambria Corporation + 1328 North 128th Street + Seattle WA 98133 + US + +70-B3-D5 (hex) eWireless +BC3000-BC3FFF (base 16) eWireless + 4629 n capitol ave + Indianapolis IN 46208 + US + +70-B3-D5 (hex) Fluid Components Intl +9F9000-9F9FFF (base 16) Fluid Components Intl + 1755 La Costa Meadows Dr. + San Marcos CA 92078 + US + +70-B3-D5 (hex) Dokuen Co. Ltd. +334000-334FFF (base 16) Dokuen Co. Ltd. + 12-3 minami-matsunoki-cho higashi-kujo minami-ku + kyoto 6018023 + JP + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +BD8000-BD8FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Sanmina Israel +3D4000-3D4FFF (base 16) Sanmina Israel + Koren Industrial Zone , POBox 102 + Maalot Israel 2101002 + IL + +70-B3-D5 (hex) TATTILE SRL +937000-937FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Last Mile Gear +EBA000-EBAFFF (base 16) Last Mile Gear + 1119 11th Ave + LONGVIEW WA 98632 + US + +70-B3-D5 (hex) WAVE +ED7000-ED7FFF (base 16) WAVE + 12078 University City Boulevard + Harrisburg NC 28075 + US + +70-B3-D5 (hex) Season Electronics Ltd +15E000-15EFFF (base 16) Season Electronics Ltd + 600 Nest Business Park + Havant Hampshire PO9 5TL + GB + +70-B3-D5 (hex) Sicon srl +7C7000-7C7FFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) Cooltera Limited +DD5000-DD5FFF (base 16) Cooltera Limited + Fircroft House, Fircroft Way + Edenbridge Kent TN8 6EJ + GB + +70-B3-D5 (hex) HoseoTelnet Inc... +11B000-11BFFF (base 16) HoseoTelnet Inc... + Hoseo Plaza B/D 7F, 416 + Gangseo-ro, Gangseo-gu Seoul 07583 + KR + +70-B3-D5 (hex) Bespoon +0F7000-0F7FFF (base 16) Bespoon + 17 rue du Lac St andre + Le bourget du Lac 73370 + FR + +70-B3-D5 (hex) U-JIN Mesco Co., Ltd. +868000-868FFF (base 16) U-JIN Mesco Co., Ltd. + Nakajima-cho 18-22 + Nishinomiya Hyogo 663-8105 + JP + +70-B3-D5 (hex) Guan Show Technologe Co., Ltd. +E2B000-E2BFFF (base 16) Guan Show Technologe Co., Ltd. + No.127, Jianguo 1st Rd., Lingya Dist. + Kaohsiung City 802 + TW + +70-B3-D5 (hex) CMT Medical technologies +950000-950FFF (base 16) CMT Medical technologies + Hacarmel 7/2 + Yoqneam 20692 + IL + +70-B3-D5 (hex) Abionic +BC1000-BC1FFF (base 16) Abionic + Route de la Corniche 5 + Epalinges 1066 + CH + +70-B3-D5 (hex) SYSCO Sicherheitssysteme GmbH +471000-471FFF (base 16) SYSCO Sicherheitssysteme GmbH + Nebenstrasse 13 + Hasselroth Hessen 63594 + DE + +70-B3-D5 (hex) PKE Electronics AG +61E000-61EFFF (base 16) PKE Electronics AG + Computerstraße, 6 + Wien Wien 1100 + AT + +70-B3-D5 (hex) TATTILE SRL +ACB000-ACBFFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Honeywell +F4D000-F4DFFF (base 16) Honeywell + Aerospace - ETS + Clearwater 33764 + US + +70-B3-D5 (hex) Honeywell +F70000-F70FFF (base 16) Honeywell + 13350 US Highway 19 N + Clearwater null 33764 + US + +70-B3-D5 (hex) TECNOWATT +B1F000-B1FFFF (base 16) TECNOWATT + Via dell'Aeronautica + Bergamo 24035 + IT + +70-B3-D5 (hex) Symetrics Industries d.b.a. Extant Aerospace +0A8000-0A8FFF (base 16) Symetrics Industries d.b.a. Extant Aerospace + 1615 West NASA Blvd + Melbourne FL 32901 + US + +70-B3-D5 (hex) Cygnetic Technologies (Pty) Ltd +B94000-B94FFF (base 16) Cygnetic Technologies (Pty) Ltd + 10 Church Street + Cape Town 7550 + ZA + +70-B3-D5 (hex) VISION SYSTEMS AURTOMOTIVE (SAFETY TECH) +948000-948FFF (base 16) VISION SYSTEMS AURTOMOTIVE (SAFETY TECH) + CHEMIN DE CHIRADIE + BRIGNAIS RHONE ALPES AUVERGNE 69530 + FR + +70-B3-D5 (hex) CoreKinect +84C000-84CFFF (base 16) CoreKinect + 5024 S. Ash Ave, Suite 101 + Tempe AZ 85282 + US + +70-B3-D5 (hex) KST technology +8A5000-8A5FFF (base 16) KST technology + KST B/D 4-5, Wiryeseong-daero 12-gil + Songpa-gu Seoul 05636 + KR + +70-B3-D5 (hex) Moduware PTY LTD +FC8000-FC8FFF (base 16) Moduware PTY LTD + 502/37 Swanston Street + Melbourne Victoria 3000 + AU + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +2CF000-2CFFFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbühl Bavaria 91550 + DE + +70-B3-D5 (hex) Argon ST +A9E000-A9EFFF (base 16) Argon ST + 12701 Fair Lakes Circle + Fairfax VA 22033 + US + +70-B3-D5 (hex) TripleOre +862000-862FFF (base 16) TripleOre + Kazernestraat 19 + Venlo 5928 NL + NL + +70-B3-D5 (hex) ioThings +993000-993FFF (base 16) ioThings + Past. Debijestraat 42 + Hegelsom Limburg 5963AG + NL + +70-B3-D5 (hex) MICAS AG +AB3000-AB3FFF (base 16) MICAS AG + Turleyring 18-22 + Oelsnitz 09376 + DE + +70-B3-D5 (hex) Acrodea, Inc. +406000-406FFF (base 16) Acrodea, Inc. + 3F, Daisan Yamada Bldg., 22 Aizumi-cho + Shinjuku-ku Tokyo 1600005 + JP + +70-B3-D5 (hex) LG Electronics +9E3000-9E3FFF (base 16) LG Electronics + 10, Magokjungang 10-ro, Gangseo-gu + Seoul 07796 + KR + +70-B3-D5 (hex) Microtronics Engineering GmbH +D24000-D24FFF (base 16) Microtronics Engineering GmbH + Hauptstrasse 7 + Ruprechtshofen 3244 + AT + +70-B3-D5 (hex) Medical Monitoring Center OOD +92E000-92EFFF (base 16) Medical Monitoring Center OOD + Office 8, 10 Poduevo Street + Sofia 1680 + BG + +70-B3-D5 (hex) Guilin Tryin Technology Co.,Ltd +460000-460FFF (base 16) Guilin Tryin Technology Co.,Ltd + Room C-306, Innovation Building,Information Industry Park, Chaoyang Road,Guilin,China + GuiLin Guangxi 541000 + CN + +70-B3-D5 (hex) Acrodea, Inc. +67D000-67DFFF (base 16) Acrodea, Inc. + 3F, Daisan Yamada Bldg., 22 Aizumi-cho + Shinjuku-ku Tokyo 1600005 + JP + +70-B3-D5 (hex) Human Systems Integration +085000-085FFF (base 16) Human Systems Integration + 153 Washington St, 4th Floor + Walpole MA 02170 + US + +70-B3-D5 (hex) Vistec Electron Beam GmbH +17B000-17BFFF (base 16) Vistec Electron Beam GmbH + Ilmstraße 4 + Jena 07743 + DE + +70-B3-D5 (hex) Tornado Modular Systems +A87000-A87FFF (base 16) Tornado Modular Systems + Inzhenernaya st. 4a + Novosibirsk Novosibirsk 630128 + RU + +70-B3-D5 (hex) Common Sense Monitoring Solutions Ltd. +0D1000-0D1FFF (base 16) Common Sense Monitoring Solutions Ltd. + Unit 1, Holts Court + Threshers Bush Essex CM17 0NS + GB + +70-B3-D5 (hex) FUJICOM Co.,Ltd. +00A000-00AFFF (base 16) FUJICOM Co.,Ltd. + 8-10-17-403, HON-chou + KOUNOSU-shi SAITAMA-ken 3650038 + JP + +70-B3-D5 (hex) Sanmina Israel +984000-984FFF (base 16) Sanmina Israel + Koren Industrial Zone , POBox 102 + Maalot Israel 2101002 + IL + +70-B3-D5 (hex) Saankhya Labs Private Limited +CA3000-CA3FFF (base 16) Saankhya Labs Private Limited + Embassy Icon, 3rd Floor, No. 3, Infantry Road, + Bangalore Karnataka 560001 + IN + +70-B3-D5 (hex) EA Elektroautomatik GmbH & Co. KG +5ED000-5EDFFF (base 16) EA Elektroautomatik GmbH & Co. KG + Helmholtzstraße 31-33 + Viersen NRW 41747 + DE + +70-B3-D5 (hex) HANYOUNG NUX CO.,LTD +103000-103FFF (base 16) HANYOUNG NUX CO.,LTD + 28. GILPA-RO + INCHEON NAM-GU 22121 + KR + +70-B3-D5 (hex) Vocality international T/A Cubic +75F000-75FFFF (base 16) Vocality international T/A Cubic + Lydling Barn,Lydling Farm,, Puttenham Lane + Godalming Surrey gu8 6ap + GB + +70-B3-D5 (hex) Adel System srl +375000-375FFF (base 16) Adel System srl + VIA LUIGI BARCHI, 9/B + Reggio Emilia 42124 + IT + +70-B3-D5 (hex) AIROBOT OÜ +1D3000-1D3FFF (base 16) AIROBOT OÜ + Pardi 32-1 + Pärnu 80016 + EE + +70-B3-D5 (hex) Ariston Thermo s.p.a. +C11000-C11FFF (base 16) Ariston Thermo s.p.a. + Via Aristide Merloni 45 + Fabriano Ancona 60044 + IT + +70-B3-D5 (hex) Scenario Automation +8B4000-8B4FFF (base 16) Scenario Automation + Rua Paulo Elias, 216 + São Carlos São Paulo 13564400 + BR + +70-B3-D5 (hex) CT Company +3AD000-3ADFFF (base 16) CT Company + Godovikova , 9, Moscow + Moscow RUSSIA 129085 + RU + +70-B3-D5 (hex) Rishaad Brown +D09000-D09FFF (base 16) Rishaad Brown + 224 Thoreau dr. Apt.D + Yorktown VA 23693 + US + +70-B3-D5 (hex) Verity Studios AG +7AC000-7ACFFF (base 16) Verity Studios AG + Zürcherstrasse 39 + Schlieren 8952 + CH + +70-B3-D5 (hex) WARECUBE,INC +F06000-F06FFF (base 16) WARECUBE,INC + #A-811, 142-10, Saneop-ro, 156beon-gil, Gwonseon-gu + Suwon-si 16648 + KR + +70-B3-D5 (hex) SEASON DESIGN TECHNOLOGY +2C9000-2C9FFF (base 16) SEASON DESIGN TECHNOLOGY + FLOOR 4, WARDS EXCHANGE, 199 ECCLESALL ROAD + SHEFFIELD SOUTH YORKSHIRE S11 8HW + GB + +70-B3-D5 (hex) Silex Inside +3BA000-3BAFFF (base 16) Silex Inside + rue du bosquet 7 + LouvainlaNeuve Brabant 1348 + BE + +70-B3-D5 (hex) ENTEC Electric & Electronic Co., LTD. +E0B000-E0BFFF (base 16) ENTEC Electric & Electronic Co., LTD. + 78-2 Buncheon-ri, Bongdam-eup + Hwaseong-city Gyungki-do 445-894 + KR + +70-B3-D5 (hex) Sicon srl +145000-145FFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) TATTILE SRL +2CA000-2CAFFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +00-1B-C5 (hex) Dynasthetics +074000-074FFF (base 16) Dynasthetics + 801-484-3820 + Salt Lake City UT 84119 + US + +70-B3-D5 (hex) Teko Telecom Srl +29C000-29CFFF (base 16) Teko Telecom Srl + via Meucci 24/a + Castel San Pietro Terme Bologna 40024 + IT + +70-B3-D5 (hex) ERA a.s. +A90000-A90FFF (base 16) ERA a.s. + Prumyslova 462 + Pardubice 53003 + CZ + +70-B3-D5 (hex) X-SPEX GmbH +D6F000-D6FFFF (base 16) X-SPEX GmbH + Albert-Einstein-Str. 14 + Berlin Berlin 12489 + DE + +70-B3-D5 (hex) Gedomo GmbH +7D7000-7D7FFF (base 16) Gedomo GmbH + Erlacker 483 + Poellau bei Hartberg Steiermark 8225 + AT + +70-B3-D5 (hex) TORGOVYY DOM TEHNOLOGIY LLC +7C0000-7C0FFF (base 16) TORGOVYY DOM TEHNOLOGIY LLC + The village of Rumyantsevo, Build.1 + Moscow Moscow 142784 + RU + +70-B3-D5 (hex) Raft Technologies +8D0000-8D0FFF (base 16) Raft Technologies + Habarzel 25 + Tel aviv 6971035 + IL + +70-B3-D5 (hex) Zamir Recognition Systems Ltd. +981000-981FFF (base 16) Zamir Recognition Systems Ltd. + Manachat Tech Park 1/22 + Jerusalem 96951 + IL + +70-B3-D5 (hex) University Of Groningen +700000-700FFF (base 16) University Of Groningen + Broerstraat 5 + Groningen Groningen 9712 CP + NL + +70-B3-D5 (hex) Association Romandix +AEB000-AEBFFF (base 16) Association Romandix + rue de Sebeillon 9b + Lausanne Vaud 1004 + CH + +70-B3-D5 (hex) AdInte, inc. +BAC000-BACFFF (base 16) AdInte, inc. + 347-1, Shijo-cho, Shimogyo-ku, 7F CUBE Nishikarasuma BLDG. + Kyoto-shi Kyoto 6008441 + JP + +70-B3-D5 (hex) Insitu, Inc +B3B000-B3BFFF (base 16) Insitu, Inc + 118 E Columbia River Way + Bingen WA 98605 + US + +70-B3-D5 (hex) Insitu, Inc +7AD000-7ADFFF (base 16) Insitu, Inc + 118 E Columbia River Way + Bingen WA 98605 + US + +70-B3-D5 (hex) HiDes, Inc. +837000-837FFF (base 16) HiDes, Inc. + 6F, No.86, Baozhong Rd., Xindian Dist., + New Taipei City New Taipei City 23144 + TW + +70-B3-D5 (hex) SENSO2ME +F7A000-F7AFFF (base 16) SENSO2ME + Zandhoef 16 + KASTERLEE België 2460 + BE + +70-B3-D5 (hex) ELDES +9A0000-9A0FFF (base 16) ELDES + Ukmerges 283B + Vilnius 06313 + LT + +70-B3-D5 (hex) Mimo Networks +25D000-25DFFF (base 16) Mimo Networks + 701 E Middlefield Road Mountain View, + Mountain View CA 94043 + US + +70-B3-D5 (hex) Vtron Pty Ltd +15D000-15DFFF (base 16) Vtron Pty Ltd + Unit 2, 62 Township Drive West + West Burleigh Queensland 4219 + AU + +70-B3-D5 (hex) Abbas, a.s. +B18000-B18FFF (base 16) Abbas, a.s. + Edisonova 5 + Brno CZ 61200 + CZ + +70-B3-D5 (hex) Emergency Lighting Products Limited +480000-480FFF (base 16) Emergency Lighting Products Limited + Gillmans Industrial Estate, Natts Lane + Billingshurst RH14 9EZ + GB + +70-B3-D5 (hex) Kunshan excellent Intelligent Technology Co., Ltd. +BE4000-BE4FFF (base 16) Kunshan excellent Intelligent Technology Co., Ltd. + Room 2002 Site B Modern Square No 8 Wei yi Road + kunshan Jiangsu Province 215301 + CN + +70-B3-D5 (hex) DIMASTEC GESTAO DE PONTO E ACESSO EIRELI-ME +F8F000-F8FFFF (base 16) DIMASTEC GESTAO DE PONTO E ACESSO EIRELI-ME + Praça Rotary Club, 355 + Ribeirão Preto São Paulo 14021-355 + BR + +70-B3-D5 (hex) QUANTAFLOW +6EB000-6EBFFF (base 16) QUANTAFLOW + AVENUE DU CANADA + HONFLEUR 14600 + FR + +70-B3-D5 (hex) JUSTEK INC +EB5000-EB5FFF (base 16) JUSTEK INC + 613-9, DONGCHUN-RI, JINWI-MYEON + PYEONGTAEK-SI GYEONGGI-DO 17711 + KR + +70-B3-D5 (hex) Neuron GmbH +E1B000-E1BFFF (base 16) Neuron GmbH + Badenerstrasse 9 + Brugg 5200 + CH + +70-B3-D5 (hex) Critical Link LLC +EF9000-EF9FFF (base 16) Critical Link LLC + 6712 Brooklawn Pkwy + Syracuse NY 13211 + US + +70-B3-D5 (hex) TechSigno srl +0A2000-0A2FFF (base 16) TechSigno srl + Via Giovanni Paolo II, 3 + Udiner UD 33100 + IT + +70-B3-D5 (hex) BLOCKSI LLC +95E000-95EFFF (base 16) BLOCKSI LLC + 228 Hamilton avenue 3rd floor + Palo Alto 94301 + US + +70-B3-D5 (hex) thou&tech +782000-782FFF (base 16) thou&tech + 161, Simin-daero, Dongan-gu, Anyang-si + Anyang-si Gyeonggi-do 14067 + KR + +70-B3-D5 (hex) VAGLER International Sdn Bhd +582000-582FFF (base 16) VAGLER International Sdn Bhd + 2006 Jalan Jelawat, Seberang Jaya Industrial Estate + Prai Penang 13700 + MY + +70-B3-D5 (hex) HOW-E +741000-741FFF (base 16) HOW-E + No. 19, Alley 16, Lane 61, Yangmei dist. + Taoyuan City 32647 + TW + +70-B3-D5 (hex) Telstra +026000-026FFF (base 16) Telstra + 231 Elisabeth St + SYDNEY NSW 2000 + AU + +70-B3-D5 (hex) JL World Corporation Limited +D54000-D54FFF (base 16) JL World Corporation Limited + Unit 20, 5/F., Block B, Proficient Industrial Centre + Kowloon Bay 0000 + HK + +70-B3-D5 (hex) GlobalTest LLC +A1F000-A1FFFF (base 16) GlobalTest LLC + Pavlika Morozova 6 + Sarov Nizhnij Novgorod 607185 + RU + +70-B3-D5 (hex) Array Technologies Inc. +A4E000-A4EFFF (base 16) Array Technologies Inc. + 21 Sequin Drive + Glastonbury 06033 + US + +70-B3-D5 (hex) BioBusiness +A08000-A08FFF (base 16) BioBusiness + 4 Elsafwa Towers, Ellebiny st, Mariutia Haram + Giza Cairo 12111 + EG + +70-B3-D5 (hex) Landis Gyr +0B6000-0B6FFF (base 16) Landis Gyr + Hasdrubal Bellegard, 400, CIC + Curitiba Paraná 81460120 + BR + +70-B3-D5 (hex) Lode BV +716000-716FFF (base 16) Lode BV + Zernikepark 16 + Groningen 9747 AN + NL + +70-B3-D5 (hex) Telonic Berkeley Inc +61D000-61DFFF (base 16) Telonic Berkeley Inc + 1080 La Mirada Ct. + Vista CA 92081 + US + +70-B3-D5 (hex) PAMIR Inc +D93000-D93FFF (base 16) PAMIR Inc + B-222, 606, Seobusaet-gil, Geumcheon-gu + Seoul 08504 + KR + +70-B3-D5 (hex) NOTICE Co., Ltd. +CAB000-CABFFF (base 16) NOTICE Co., Ltd. + A-1307/8, Keumkang Penterium IT Tower, 282, Hagui-ro + Anyang Gyeonggi-do 14056 + KR + +70-B3-D5 (hex) Sierra Nevada Corporation +252000-252FFF (base 16) Sierra Nevada Corporation + 444 Salomon Circle + Sparks NV 89434 + US + +70-B3-D5 (hex) Uwinloc +D6B000-D6BFFF (base 16) Uwinloc + 57 Avenue Jean Monnet + Colomiers 31770 + FR + +70-B3-D5 (hex) Rtone +5F3000-5F3FFF (base 16) Rtone + 120 rue de Saint cyr + Lyon 69009 + FR + +70-B3-D5 (hex) EIIT SA +608000-608FFF (base 16) EIIT SA + Camino Robledo de Chavela 9B + Valdemorillo Madrid / Madrid 28210 + ES + +70-B3-D5 (hex) IOT Engineering +16B000-16BFFF (base 16) IOT Engineering + 3 Eglington Ave + Epson Auckland 1024 + NZ + +70-B3-D5 (hex) TATTILE SRL +B21000-B21FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Alma +BA9000-BA9FFF (base 16) Alma + 4A, Bd de la Gare, Porte 1 + Boissy St Léger PACA 94470 + FR + +70-B3-D5 (hex) International Roll-Call Corporation +4B8000-4B8FFF (base 16) International Roll-Call Corporation + 8346 Old Richfood Road + Mechanicsville VA 23116 + US + +70-B3-D5 (hex) S.I.C.E.S. srl +EA7000-EA7FFF (base 16) S.I.C.E.S. srl + Via Molinello, 8B + Jerago con Orago VARESE 21040 + IT + +70-B3-D5 (hex) RCATSONE +3AA000-3AAFFF (base 16) RCATSONE + 5925 Airport Road - Suite 905 + Mississauga Ontario L4V 1W1 + CA + +70-B3-D5 (hex) TAIYO SEIKI CO.,LTD. +69B000-69BFFF (base 16) TAIYO SEIKI CO.,LTD. + 1600 Aza-Shironoshita Asahi + Shin Asahi-cho Takashima, Shiga 520-1501 + JP + +70-B3-D5 (hex) PLUTO Solution co.,ltd. +842000-842FFF (base 16) PLUTO Solution co.,ltd. + B-1018, Kumkang Penterium IT Tower, 282, Hagui-ro, Dongan-gu + Anyang-si Gyeonggi-do 14056 + KR + +70-B3-D5 (hex) SHENZHEN GAONA ELECTRONIC CO.LTD +031000-031FFF (base 16) SHENZHEN GAONA ELECTRONIC CO.LTD + F3.East block. Xinwu Industrial Building, Longzhu Road.Nanshan District + Shenzhen Guangdong China 518000 + CN + +00-1B-C5 (hex) SKODA ELECTRIC a.s. +0B2000-0B2FFF (base 16) SKODA ELECTRIC a.s. + Tylova 1/57 + Plzen 301 28 + CZ + +70-B3-D5 (hex) S Labs sp. z o.o. +C53000-C53FFF (base 16) S Labs sp. z o.o. + Jasnogórska, 44 + Kraków Lesser Poland 31-358 + PL + +70-B3-D5 (hex) Dameca a/s +EEA000-EEAFFF (base 16) Dameca a/s + Islevdalvej 211 + Roedovre 2610 + DK + +70-B3-D5 (hex) Cardinal Scale Mfg Co +488000-488FFF (base 16) Cardinal Scale Mfg Co + 203 E. Daugherty + Webb City MO 64870 + US + +70-B3-D5 (hex) ISO/TC 22/SC 31 +319000-319FFF (base 16) ISO/TC 22/SC 31 + Behrenstr. 35 + Berlin 10117 + DE + +70-B3-D5 (hex) ndb technologies +0B2000-0B2FFF (base 16) ndb technologies + 1405-111 Av Saint-Jean-Baptiste + Quebec Quebec G2E5K2 + CA + +70-B3-D5 (hex) Nanjing Dandick Science&technology development co., LTD +E7D000-E7DFFF (base 16) Nanjing Dandick Science&technology development co., LTD + No.5,JinMa Road,MaQun Science Park,Qixia district + NanJing Jiang Su 210049 + CN + +70-B3-D5 (hex) Critical Link LLC +E5E000-E5EFFF (base 16) Critical Link LLC + 6712 Brooklawn Parkway + Syracuse null 13211 + US + +70-B3-D5 (hex) SISTEM SA +DB8000-DB8FFF (base 16) SISTEM SA + Avda.Rita Levi Montalcini, nº2 Parcela 5 + Getafe Madrid 28906 + ES + +70-B3-D5 (hex) Fortress Cyber Security +674000-674FFF (base 16) Fortress Cyber Security + 189 South Orange Ave, Suite 1950 + Orlando FL 32801 + US + +70-B3-D5 (hex) QUICCO SOUND Corporation +A7E000-A7EFFF (base 16) QUICCO SOUND Corporation + B2,1-3-3-1,Incubate Center, Shin-Miyakoda, Kita-ku + Hamamatsu Shizuoka 431-2103 + JP + +70-B3-D5 (hex) RDT Ltd +7DF000-7DFFFF (base 16) RDT Ltd + Pavilion C2, Ashwood Park, Ashwood Way + Basingstoke Hampshire RG23 8BG + GB + +70-B3-D5 (hex) Package Guard, Inc +878000-878FFF (base 16) Package Guard, Inc + 2819 33rd ave so + seattle WA 98144 + US + +70-B3-D5 (hex) SDK Kristall +7D2000-7D2FFF (base 16) SDK Kristall + Polevaia Sabirovskaia 49A, 1H + Saint-Petersburg Russia 197183 + RU + +70-B3-D5 (hex) Leviathan Solutions Ltd. +A69000-A69FFF (base 16) Leviathan Solutions Ltd. + Kazal utca 64-66 + Budapest 1031 + HU + +70-B3-D5 (hex) BEDEROV GmbH +371000-371FFF (base 16) BEDEROV GmbH + Rankestr. 8 + Berlin Berlin 10789 + DE + +70-B3-D5 (hex) Sensoterra BV +DC9000-DC9FFF (base 16) Sensoterra BV + Science Park 106 + Amsterdam 1098 XG + NL + +70-B3-D5 (hex) Fusar Technologies inc +E6C000-E6CFFF (base 16) Fusar Technologies inc + 385 Monmouth St #2 + Jersey City NJ 07302 + US + +70-B3-D5 (hex) FOCAL-JMLab +96B000-96BFFF (base 16) FOCAL-JMLab + 108 rue de l'Avenir + La Talaudière 42353 + FR + +70-B3-D5 (hex) Comrod AS +408000-408FFF (base 16) Comrod AS + Fiskaaveien 1 + TAU 4120 + NO + +70-B3-D5 (hex) Santa Barbara Imaging Systems +446000-446FFF (base 16) Santa Barbara Imaging Systems + 340 Storke Road, Suite 101 + Goleta CA 93117 + US + +70-B3-D5 (hex) SENSONEO +007000-007FFF (base 16) SENSONEO + Kollarova 27 + Bratislava Slovak Republic 84106 + SK + +70-B3-D5 (hex) BRS Sistemas Eletrônicos +55E000-55EFFF (base 16) BRS Sistemas Eletrônicos + Rua Gomes de Freitas, 491 / 204 + Porto Alegre RS 91380-000 + BR + +70-B3-D5 (hex) ARC Technology Solutions, LLC +FAD000-FADFFF (base 16) ARC Technology Solutions, LLC + 165 Ledge Street + Nashua NH 03060 + US + +70-B3-D5 (hex) vivaMOS +AC7000-AC7FFF (base 16) vivaMOS + 2 Venture Road + Southampton Hampshire SO16 7NP + GB + +70-B3-D5 (hex) Southern Innovation +C16000-C16FFF (base 16) Southern Innovation + 729 Nicholson street + Carlton North Victoria 3054 + AU + +70-B3-D5 (hex) Micro Electroninc Products +DB2000-DB2FFF (base 16) Micro Electroninc Products + TT Vasumweg 150 + Amsterdam 1033 SH + NL + +70-B3-D5 (hex) Circuitlink Pty Ltd +094000-094FFF (base 16) Circuitlink Pty Ltd + 4 / 87 Station Road + Seven Hills NSW 2147 + AU + +70-B3-D5 (hex) Baumtec GmbH +AEF000-AEFFFF (base 16) Baumtec GmbH + Behringstr.6 + Rodgau Hessen 63110 + DE + +70-B3-D5 (hex) Rievtech Electronic Co.,Ltd +8C1000-8C1FFF (base 16) Rievtech Electronic Co.,Ltd + Room 505, Building A, No.88,Dazhou Road,Tiexinqiao,Yu huatai District, Nanjing City, Jiangsu Province,P.R.China +0086 25 52895099 52890138 info@rievtech.com sales@rievtech.com + Nanjing City Jiangsu Province 210000 + CN + +70-B3-D5 (hex) CRDE +DEE000-DEEFFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) Ash Technologies +30B000-30BFFF (base 16) Ash Technologies + Unit B5, M7 Business Park + Naas Kildare W91P684 + IE + +70-B3-D5 (hex) Step Technica Co., Ltd. +28C000-28CFFF (base 16) Step Technica Co., Ltd. + 757-3 Shimofujisawa + Iruma-shi Saitama-ken 3580011 + JP + +70-B3-D5 (hex) Chelsea Technologies Group Ltd +579000-579FFF (base 16) Chelsea Technologies Group Ltd + 55, Central Avenue + West Molesey Surrey KT8 2QZ + GB + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +B6A000-B6AFFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) CircuitMeter Inc. +365000-365FFF (base 16) CircuitMeter Inc. + 1238 Maple Ridge Dr + Pickering Ontario L1X 1A5 + CA + +70-B3-D5 (hex) KST technology +861000-861FFF (base 16) KST technology + 164-1, KST b/d., Bangi-dong, songpa-gu + SEOUL N/A 138-050 + KR + +70-B3-D5 (hex) MobiPromo +A73000-A73FFF (base 16) MobiPromo + 10, 64-72 Beresford Rd + Lilydale Victoria 3140 + AU + +70-B3-D5 (hex) Nefteavtomatika +585000-585FFF (base 16) Nefteavtomatika + 50-letiay Oktyabria, 24 + Ufa 450005 + RU + +70-B3-D5 (hex) Blair Companies +442000-442FFF (base 16) Blair Companies + 5107 Kissell Ave + Altoona PA 16601 + US + +70-B3-D5 (hex) Equatel +911000-911FFF (base 16) Equatel + Bury New Road + Manchester M25 0JW + GB + +70-B3-D5 (hex) RJ45 Technologies +9D0000-9D0FFF (base 16) RJ45 Technologies + 7, rue Roland Martin + Champigny sur Marne France 94500 + FR + +70-B3-D5 (hex) Power Electronics Espana, S.L. +B56000-B56FFF (base 16) Power Electronics Espana, S.L. + C/ Leonardo Da Vinci, 24-26 + Paterna Valencia 46980 + ES + +70-B3-D5 (hex) S.C.E. srl +AF6000-AF6FFF (base 16) S.C.E. srl + Via Giardini 1271/A + Modena Italy 41126 + IT + +70-B3-D5 (hex) Seraphim Optronics Ltd +ADF000-ADFFFF (base 16) Seraphim Optronics Ltd + 2 hacarmel st + Yokneam Israel 20692 + IL + +70-B3-D5 (hex) KLEIBER Infrared GmbH +672000-672FFF (base 16) KLEIBER Infrared GmbH + Am Gewände 3 + Unterwellenborn Thüringen 07333 + DE + +70-B3-D5 (hex) DORLET SAU +135000-135FFF (base 16) DORLET SAU + Albert Eistein 34 + Alava SPAIN 01510 + ES + +70-B3-D5 (hex) ProTom International +997000-997FFF (base 16) ProTom International + 1100 Parker Square, Suite 230 + Flower Mound TX 75028 + US + +70-B3-D5 (hex) Systolé Hardware B.V. +B30000-B30FFF (base 16) Systolé Hardware B.V. + Hogehilweg, 5E + Amsterdam 1101 CA + NL + +70-B3-D5 (hex) ZAO ZEO +07A000-07AFFF (base 16) ZAO ZEO + Khachaturiana 14a + Moscow 127562 + RU + +70-B3-D5 (hex) Motomuto Aps +F05000-F05FFF (base 16) Motomuto Aps + Arresoevej 11 + Risskov MIDT 8240 + DK + +70-B3-D5 (hex) synchrotron SOLEIL +378000-378FFF (base 16) synchrotron SOLEIL + l'orme des merisiers + gif sur yvette 91192 + FR + +70-B3-D5 (hex) Contiweb +DFD000-DFDFFF (base 16) Contiweb + Ir. Wagterstraat 10 + Boxmeer 5831 AZ + NL + +70-B3-D5 (hex) Specialised Imaging Limited +D1C000-D1CFFF (base 16) Specialised Imaging Limited + 6 Harvington Park + Pitstone Bucks LU7 9GX + GB + +70-B3-D5 (hex) Viko Elektrik-Elektronik A.Ş. +EC8000-EC8FFF (base 16) Viko Elektrik-Elektronik A.Ş. + Abdurrahmangazi Mah. Ebubekir Cad. No:44 Sancaktepe + Istanbul 34887 + TR + +70-B3-D5 (hex) ATX Networks Corp +9D9000-9D9FFF (base 16) ATX Networks Corp + 1-501 Clements Road West + Ajax Ontario L1s7H4 + CA + +70-B3-D5 (hex) Giant Power Technology Biomedical Corporation +A8B000-A8BFFF (base 16) Giant Power Technology Biomedical Corporation + Rm201, 2nd Educational Building, No. 84, Gongzhuan Rd, Taishan Dist + New Taipei City 24301 + TW + +70-B3-D5 (hex) LUCEO +6BB000-6BBFFF (base 16) LUCEO + 16 Rue Laënnec + Vern Sur Seiche Bretagne 35770 + FR + +70-B3-D5 (hex) INEO-SENSE +637000-637FFF (base 16) INEO-SENSE + 125 rue de l'Hostellerie, Immeuble Ellipsis - Niv 4-12 + NIMES 30900 + FR + +70-B3-D5 (hex) Lumacron Technology Ltd. +778000-778FFF (base 16) Lumacron Technology Ltd. + 4 Pitreavie Court, Pitreavie Business Park + Dunfermline Fife KY11 8UU + GB + +70-B3-D5 (hex) Gecko Robotics Inc +04A000-04AFFF (base 16) Gecko Robotics Inc + 6901 Lynn Way, Suite 310 + Pittsburgh PA 15208 + US + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +FBD000-FBDFFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Fourth Frontier Technologies Private Limited +E2C000-E2CFFF (base 16) Fourth Frontier Technologies Private Limited + 91 Bhuvaneshwari Nagar, CV Raman Nagar Post + Bangalore Karnataka 560093 + IN + +70-B3-D5 (hex) hera Laborsysteme GmbH +4C2000-4C2FFF (base 16) hera Laborsysteme GmbH + Hermann-Rapp-Str. 40 + Blaufelden 74572 + DE + +70-B3-D5 (hex) Proximus +AA6000-AA6FFF (base 16) Proximus + Bld du Roi Albert II 27 + Brussels 1030 + BE + +70-B3-D5 (hex) Joehl & Koeferli AG +81A000-81AFFF (base 16) Joehl & Koeferli AG + Wittenwilerstrasse 31 + Aadorf TG 8355 + CH + +70-B3-D5 (hex) TATTILE SRL +825000-825FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Tunstall A/S +2F8000-2F8FFF (base 16) Tunstall A/S + Niels Bohrs vej 42 + Stilling Skanderborg 8660 + DK + +70-B3-D5 (hex) Tibit Communications +523000-523FFF (base 16) Tibit Communications + 1 Willowbrook Court, Suite 150 + Petaluma CA 94954 + US + +70-B3-D5 (hex) ATG UV Technology +E9C000-E9CFFF (base 16) ATG UV Technology + Genesis House + Wigan WN5 8AA + GB + +70-B3-D5 (hex) Cybercom AB +FF7000-FF7FFF (base 16) Cybercom AB + Lindholmenspiren 3A + Göteborg Vastra götland 41756 + SE + +70-B3-D5 (hex) IoTrek Technology Private Limited +A07000-A07FFF (base 16) IoTrek Technology Private Limited + Paharganj, Delhi + New Delhi New Delhi 110055 + IN + +70-B3-D5 (hex) ANKER-EAST +C4B000-C4BFFF (base 16) ANKER-EAST + B. Raznochinnaya 28 + St Petersburg 197110 + RU + +70-B3-D5 (hex) Schneider Displaytechnik GmbH +9C0000-9C0FFF (base 16) Schneider Displaytechnik GmbH + Tegelweg, 14 + Paderborn 33102 + DE + +70-B3-D5 (hex) Canam Technology, Inc. +B97000-B97FFF (base 16) Canam Technology, Inc. + 5318 East 2nd. St, #700 + Long Beach CA 90803 + US + +70-B3-D5 (hex) FRANKLIN FRANCE +767000-767FFF (base 16) FRANKLIN FRANCE + 13 RUE LOUIS ARMAND + OZOIR LA FERRIERE 77330 + FR + +70-B3-D5 (hex) ENERGISME +465000-465FFF (base 16) ENERGISME + 88 avenue du General Leclerc + Boulogne Billancourt 92100 + FR + +70-B3-D5 (hex) DUVAL MESSIEN +F07000-F07FFF (base 16) DUVAL MESSIEN + 30 RUE DE LA VARENNE + ST MAUR DES FOSSES 94100 + FR + +70-B3-D5 (hex) TTC TELEKOMUNIKACE, s.r.o. +6B1000-6B1FFF (base 16) TTC TELEKOMUNIKACE, s.r.o. + Trebohosticka 5 + Praha 10 Praha 10000 + CZ + +70-B3-D5 (hex) Smith Meter, Inc. +816000-816FFF (base 16) Smith Meter, Inc. + 1602 Wagner Ave. + Erie PA 16514 + US + +70-B3-D5 (hex) The Institute of Mine Seismology +930000-930FFF (base 16) The Institute of Mine Seismology + 175 Tinderbox Road + Tinderbox, Hobart Tasmania 7054 + AU + +70-B3-D5 (hex) Beijing Wing ICT Technology Co., Ltd. +EBB000-EBBFFF (base 16) Beijing Wing ICT Technology Co., Ltd. + Room901,Fuhai international harbour Building,Daliushu Road No.17,Haidian District + Beijing Beijing 100081 + CN + +70-B3-D5 (hex) HDANYWHERE +60E000-60EFFF (base 16) HDANYWHERE + Unit 23 Link Business Centre + Malvern Worcs WR14 1UQ + GB + +70-B3-D5 (hex) Revolution Retail Systems, LLC +B53000-B53FFF (base 16) Revolution Retail Systems, LLC + 1840 Hutton Drive Ste 130 + Carrollton TX 75006 + US + +70-B3-D5 (hex) APG Cash Drawer, LLC +37A000-37AFFF (base 16) APG Cash Drawer, LLC + 5250 Industrial Blvd NE + Minneapolis MN 55421 + US + +70-B3-D5 (hex) Pivothead +63C000-63CFFF (base 16) Pivothead + 1224 Speer Blvd. + Denver CO 80204 + US + +70-B3-D5 (hex) exceet electronics GesmbH +A85000-A85FFF (base 16) exceet electronics GesmbH + Wildbichlerstraße 2e + Ebbs Austria 6341 + AT + +70-B3-D5 (hex) digital-spice +AFF000-AFFFFF (base 16) digital-spice + toyohira529-2 + chino nagano 391-0213 + JP + +70-B3-D5 (hex) Miguel Corporate Services Pte Ltd +136000-136FFF (base 16) Miguel Corporate Services Pte Ltd + 18 Sin Ming Lane #06-32 Midview City + Singapore 573960 + SG + +70-B3-D5 (hex) XotonicsMED GmbH +C06000-C06FFF (base 16) XotonicsMED GmbH + Gewerbestrasse, 19 + Treuen OT Hartmannsgrün Saxony 08233 + DE + +70-B3-D5 (hex) Megaflex Oy +7E5000-7E5FFF (base 16) Megaflex Oy + Nuijamiestentie 3 c 1 + Helsinki Select State 00400 + FI + +70-B3-D5 (hex) FDSTiming +5F4000-5F4FFF (base 16) FDSTiming + Rue du Nord 123 + la Chaux-de-Fonds 2300 + CH + +70-B3-D5 (hex) Euklis by GSG International +D32000-D32FFF (base 16) Euklis by GSG International + via Colombo 23 + Trezzano sul Naviglio MI 20090 + IT + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +9C7000-9C7FFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) Wuhan Xingtuxinke ELectronic Co.,Ltd +D9A000-D9AFFF (base 16) Wuhan Xingtuxinke ELectronic Co.,Ltd + NO.C3-8F,Software Park,Optics Valley,East Lake Development Zone,Wuhan,Hubei,China + Wuhan Hubei 430074 + CN + +70-B3-D5 (hex) PTYPE Co., LTD. +6B0000-6B0FFF (base 16) PTYPE Co., LTD. + B121, B-dong, Keumkang Penterium IT Tower, 810, Gwanyand 2-dong, Dongan-gu + Anyang-si Gyeonggi-do 14056 + KR + +70-B3-D5 (hex) WELT Corporation +8CB000-8CBFFF (base 16) WELT Corporation + Seocho, Bangbae, 481-5 + Seoul 06699 + KR + +70-B3-D5 (hex) Hangzhou SunTown Intelligent Science & Technology Co.,Ltd. +90A000-90AFFF (base 16) Hangzhou SunTown Intelligent Science & Technology Co.,Ltd. + Hangzhou Zhenhua Road, Xihu District No. 298 West Port A District 2 16F + Hangzhou Zhejiang Province 310030 + CN + +70-B3-D5 (hex) ATE Systems Inc +594000-594FFF (base 16) ATE Systems Inc + 85 Rangeway Road + N Billerica MA 01862 + US + +70-B3-D5 (hex) TD ECOPHISIKA +27A000-27AFFF (base 16) TD ECOPHISIKA + Vernadskogo,77 + Moscow 119415 + RU + +70-B3-D5 (hex) Alion Science & Technology +70F000-70FFFF (base 16) Alion Science & Technology + 220 Salina Meadows Pkwy, Suite 210 + Syracuse NY 13212 + US + +70-B3-D5 (hex) Inova Design Solutions Ltd +131000-131FFF (base 16) Inova Design Solutions Ltd + 40 Occam Road + Guildford SURREY GU2 7YG + GB + +70-B3-D5 (hex) DCNS +989000-989FFF (base 16) DCNS + 40-42 Rue du docteur Finlay + PARIS CEDEX 15 75732 + FR + +70-B3-D5 (hex) Instec, Inc. +22F000-22FFFF (base 16) Instec, Inc. + 5589 Arapahoe Avenue, Ste. 208 + Boulder CO 80303 + US + +70-B3-D5 (hex) Montalvo +227000-227FFF (base 16) Montalvo + 50 hutcherson drive + Gorham ME 04038 + US + +70-B3-D5 (hex) DR.BRIDGE AQUATECH +779000-779FFF (base 16) DR.BRIDGE AQUATECH + 4F., No.40, Sec. 3, Chengde Rd., Datong Dist., + Taipei 103 + TW + +70-B3-D5 (hex) Design For Life Systems +A20000-A20FFF (base 16) Design For Life Systems + Unit 15, Jubilee Enterprise Centre + Weymouth DT47BS + GB + +70-B3-D5 (hex) Finder SpA +FEC000-FECFFF (base 16) Finder SpA + via Drubiaglio 14 + Almese TO 10040 + IT + +70-B3-D5 (hex) XGEM SAS +498000-498FFF (base 16) XGEM SAS + 9 Rue de la Négresse + Biarritz 64200 + FR + +70-B3-D5 (hex) TIAMA +A33000-A33FFF (base 16) TIAMA + ZA des Plattes - 1 Chemin des Plattes + VOURLES 69390 + FR + +70-B3-D5 (hex) Advanced Products Corporation Pte Ltd +CED000-CEDFFF (base 16) Advanced Products Corporation Pte Ltd + 5006 Ang Mo Kio Ave 5, #05-01/12 TECHPlace II + Singapore 569873 + SG + +70-B3-D5 (hex) D.Marchiori Srl +42C000-42CFFF (base 16) D.Marchiori Srl + Via Pontina Km 43,856 + Aprilia LT 04011 + IT + +70-B3-D5 (hex) RF Track +E82000-E82FFF (base 16) RF Track + 80, avenue des buttes de Coesmes + Rennes 35700 + FR + +70-B3-D5 (hex) CRDE +855000-855FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) aelettronica group srl +4A7000-4A7FFF (base 16) aelettronica group srl + via matteotti,22 + gaggiano milano 20083 + IT + +70-B3-D5 (hex) JETI Technische Instrumente GmbH +938000-938FFF (base 16) JETI Technische Instrumente GmbH + Tatzendpromenade 2 + Jena 07745 + DE + +70-B3-D5 (hex) Flextronics Canafa Design Services +F8D000-F8DFFF (base 16) Flextronics Canafa Design Services + 1280 Teron Road + Ottawa ON K2K 2C1 + CA + +70-B3-D5 (hex) SOLVERIS sp. z o.o. +4C7000-4C7FFF (base 16) SOLVERIS sp. z o.o. + Majdan Krasieniński 16A + Niemce lubelskie 21-025 + PL + +70-B3-D5 (hex) Aplex Technology Inc. +9B1000-9B1FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) Netemera Sp. z o.o. +CA4000-CA4FFF (base 16) Netemera Sp. z o.o. + Ostrobramska 83/1208A + Warszawa mazowieckie 04-175 + PL + +70-B3-D5 (hex) GS Industrie-Elektronik GmbH +A53000-A53FFF (base 16) GS Industrie-Elektronik GmbH + Porschestrasse 11 + Leverkusen 51381 + DE + +70-B3-D5 (hex) Morgan Schaffer Inc. +7C2000-7C2FFF (base 16) Morgan Schaffer Inc. + 8300 rue St-Patrick bureau 150 + LaSalle Quebec H8N 2H1 + CA + +70-B3-D5 (hex) PEEK TRAFFIC +68F000-68FFFF (base 16) PEEK TRAFFIC + 5401 N SAM HOUSTON PKWY W + HOUSTON TX 77086 + US + +70-B3-D5 (hex) Bel Power Solutions GmbH +CAA000-CAAFFF (base 16) Bel Power Solutions GmbH + Ackerstrasse 56 + Uster 8610 + CH + +70-B3-D5 (hex) Pycom Ltd +499000-499FFF (base 16) Pycom Ltd + 57 Avenue Road + Cranleigh Surrey GU6 7LJ + GB + +70-B3-D5 (hex) Sertone, a division of Opti-Knights Ltd +584000-584FFF (base 16) Sertone, a division of Opti-Knights Ltd + Chesterfield House, 207 Old Marylebone Road + London NW1 5QP + GB + +70-B3-D5 (hex) SICS Swedish ICT +7D5000-7D5FFF (base 16) SICS Swedish ICT + Isafjordsgatan 22 + Kista Stockholm SE-164 40 + SE + +70-B3-D5 (hex) HOSIN INDUSTRIAL LIMITED +692000-692FFF (base 16) HOSIN INDUSTRIAL LIMITED + 15 Floor, Investment building, Shennan Road 4009, Futian + Shenzhen 518031 + CN + +70-B3-D5 (hex) ACS MOTION CONTROL +9D2000-9D2FFF (base 16) ACS MOTION CONTROL + 1 Hataasia St., Ramat Gabriel Industrial Park, + Migdal Ha'Emek Israel 2307037 + IL + +70-B3-D5 (hex) CJSC «Russian telecom equipment company» (CJSC RTEC) +6C5000-6C5FFF (base 16) CJSC «Russian telecom equipment company» (CJSC RTEC) + Zvenigorodskaya 2-nd street 13/15 + Moscow 123022 + RU + +70-B3-D5 (hex) Open Grow +696000-696FFF (base 16) Open Grow + Edifício Expobeiras + Viseu Viseu 3500 618 + PT + +70-B3-D5 (hex) Sontay Ltd. +55A000-55AFFF (base 16) Sontay Ltd. + Four Elms Road + Edenbridge TN86AB + GB + +70-B3-D5 (hex) NEXTtec srl +02D000-02DFFF (base 16) NEXTtec srl + Via Ivrea 71/B + Rivoli TO 10098 + IT + +70-B3-D5 (hex) Survalent Technology Corporation +78C000-78CFFF (base 16) Survalent Technology Corporation + 7965 Heritage Road + Brampton Ontario L6Y 5X5 + CA + +70-B3-D5 (hex) LOGIX ITS Inc +B7D000-B7DFFF (base 16) LOGIX ITS Inc + 990 upton + lasalle Quebec h8r2t9 + CA + +70-B3-D5 (hex) Eiden Co.,Ltd. +167000-167FFF (base 16) Eiden Co.,Ltd. + 2-7-1 kurigi,asao-ku,kawasaki-shi + kanagawa 215-0033 + JP + +70-B3-D5 (hex) B.P.A. SRL +49F000-49FFFF (base 16) B.P.A. SRL + Via Primo Villa 2/1 + Burago di Molgora MB 20875 + IT + +70-B3-D5 (hex) MART NETWORK SOLUTIONS LTD +ABE000-ABEFFF (base 16) MART NETWORK SOLUTIONS LTD + ABBEY HOUSE, 450 BATH ROAD + LONGFORD MIDDLESEX UB70EB + GB + +70-B3-D5 (hex) Rohde&Schwarz Topex SA +186000-186FFF (base 16) Rohde&Schwarz Topex SA + 71th-73th Nicolae Caramfil street, 2nd floor, 1th district + Bucuresti Romania 014142 + RO + +70-B3-D5 (hex) Kratos Analytical Ltd +8DB000-8DBFFF (base 16) Kratos Analytical Ltd + Trafford Wharf Road + Manchester M17 1GP + GB + +70-B3-D5 (hex) WUHAN EASYLINKIN TECHNOLOGY co.,LTD +88B000-88BFFF (base 16) WUHAN EASYLINKIN TECHNOLOGY co.,LTD + 22 Optics Valley Ave.,East Lake New Technology Development Zone + WUHAN HUBEI 430000 + CN + +70-B3-D5 (hex) Mechatronics Systems Private Limited +5E6000-5E6FFF (base 16) Mechatronics Systems Private Limited + S No. 107, Warje, Mechatronics House, Off Mumbai Bangalore Bypass Highway, Near Rosary School, + Pune Maharashtra 411058 + IN + +70-B3-D5 (hex) SensoTec GmbH +AAC000-AACFFF (base 16) SensoTec GmbH + Hinter dem Turme 15 + Braunschweig 38114 + DE + +70-B3-D5 (hex) CRDE +6EC000-6ECFFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) CTAG - ESG36871424 +B55000-B55FFF (base 16) CTAG - ESG36871424 + Pol. Industrial A Granxa, Calle A, parcelas 249-250 + Porriño Pontevedra 36400 + ES + +70-B3-D5 (hex) Aplex Technology Inc. +986000-986FFF (base 16) Aplex Technology Inc. + 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District + Shenzhen Guangdong 518054 + CN + +70-B3-D5 (hex) TLV CO., LTD. +A2C000-A2CFFF (base 16) TLV CO., LTD. + 881 Nagasuna, Noguchi + Kakogawa, Hyogo 675-8511 + JP + +70-B3-D5 (hex) TATTILE SRL +881000-881FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) mapna group +04C000-04CFFF (base 16) mapna group + mirdamad + Tehran 0512258788 + IR + +70-B3-D5 (hex) w-tec AG +A10000-A10FFF (base 16) w-tec AG + Dombachstrasse 1a + Bad Homburg 61352 + DE + +70-B3-D5 (hex) Vitrea Smart Home Technologies +51B000-51BFFF (base 16) Vitrea Smart Home Technologies + 11 Moshe Levi st. + Rishon Lezion 7565828 + IL + +70-B3-D5 (hex) Proconex 2010 Inc. +CCE000-CCEFFF (base 16) Proconex 2010 Inc. + 16753 Hymus Blvd. + Kirkland Quebec H9H 3L4 + CA + +70-B3-D5 (hex) Marques,S.A. +643000-643FFF (base 16) Marques,S.A. + Zona Industrial da Alagoa - APT 3134 + Águeda Aveiro 3754-901 + PT + +70-B3-D5 (hex) Transelektronik Messgeräte GmbH +A7C000-A7CFFF (base 16) Transelektronik Messgeräte GmbH + Theresiengasse 3 + Wien Austria 1180 + AT + +70-B3-D5 (hex) Dolotron d.o.o. +91B000-91BFFF (base 16) Dolotron d.o.o. + Ziskovec 141 + Cakovec 40000 + HR + +70-B3-D5 (hex) GD Mission Systems +39C000-39CFFF (base 16) GD Mission Systems + 8220 E. Roosevelt St. + Scottsdale AZ 85257 + US + +70-B3-D5 (hex) APG Cash Drawer, LLC +712000-712FFF (base 16) APG Cash Drawer, LLC + 5250 Industrial Blvd NE + Minneapolis MN 55421 + US + +70-B3-D5 (hex) Rimota Limited +8F2000-8F2FFF (base 16) Rimota Limited + Archer House, Britland Estate, Northbourne Road + Eastbourne East Sussex BN22 8PW + GB + +70-B3-D5 (hex) ZIGPOS GmbH +879000-879FFF (base 16) ZIGPOS GmbH + Strehlener Straße 12/14 + Dresden Saxony 01069 + DE + +70-B3-D5 (hex) Novoptel GmbH +AC3000-AC3FFF (base 16) Novoptel GmbH + EIM-E, Warburger Str. 100 + Paderborn 33098 + DE + +70-B3-D5 (hex) Applied Radar, Inc. +35A000-35AFFF (base 16) Applied Radar, Inc. + 315 Commerce Park Road Unit 3 + North Kingstown RI 02886 + US + +70-B3-D5 (hex) MAVILI ELEKTRONIK TIC. VE SAN. A.S. +DE4000-DE4FFF (base 16) MAVILI ELEKTRONIK TIC. VE SAN. A.S. + Serifali Mah. Kutup Sk. No: 27/1-2-4 + Istanbul Umraniye 34775 + TR + +70-B3-D5 (hex) Otto Bihler Maschinenfabrik GmbH & Co. KG +6BF000-6BFFFF (base 16) Otto Bihler Maschinenfabrik GmbH & Co. KG + Lechbrucker Str. 15 + Halblech 87642 + DE + +70-B3-D5 (hex) CRDE +D65000-D65FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) ACD Elekronik GmbH +DE2000-DE2FFF (base 16) ACD Elekronik GmbH + Engelberg 2 + Achstetten 88480 + DE + +70-B3-D5 (hex) Instro Precision Limited +B81000-B81FFF (base 16) Instro Precision Limited + 15 Hornet Close, Pysons Road Industrial Estate + Broadstairs Kent CT10 2YD + GB + +70-B3-D5 (hex) ES Industrial Systems Co., Ltd. +9E0000-9E0FFF (base 16) ES Industrial Systems Co., Ltd. + B-dong, 12, Baekseokgongdan 3-gil, Seobuk-gu, Cheonan-si, Chungcheongnam-do + Cheonan-si Chungcheongnam-do 31094 + KR + +70-B3-D5 (hex) Trapeze Software Group Inc +A66000-A66FFF (base 16) Trapeze Software Group Inc + 5265 Rockwell Dr NE + Cedar Rapids IA 52402 + US + +70-B3-D5 (hex) InsideRF Co., Ltd. +0FA000-0FAFFF (base 16) InsideRF Co., Ltd. + 801 31 Seongsui-ro 24-gil Seongdong-gu + Seoul Asia 04798 + KR + +70-B3-D5 (hex) Access Control Systems JSC +1AB000-1ABFFF (base 16) Access Control Systems JSC + Bogatyrsky av. 18/1 office 505 + Sankt-Peterburg 197348 + RU + +70-B3-D5 (hex) AT-Automation Technology GmbH +028000-028FFF (base 16) AT-Automation Technology GmbH + Hermann-Boessow-Str. 6-8 + Bad Oldesloe D-23843 + DE + +70-B3-D5 (hex) tinnos +CF2000-CF2FFF (base 16) tinnos + 4th Floor, 25, Banpo-daero + Seocho-gu Seoul 06710 + KR + +70-B3-D5 (hex) G-PHILOS CO.,LTD +D34000-D34FFF (base 16) G-PHILOS CO.,LTD + #602,3 RDWOOLIMLIONSVALLY 24, DUNCHONDAERO, 388BEAN-GIL JUNGWONGU + SEOUNGNAM-SI GYEONGGI-DO 13403 + KR + +70-B3-D5 (hex) emperor brands +658000-658FFF (base 16) emperor brands + 11345 Ventura Blvd + Studio City CA 90043 + US + +70-B3-D5 (hex) Dewetron GmbH +D94000-D94FFF (base 16) Dewetron GmbH + Parkring 4 + Grambach 8074 + AT + +70-B3-D5 (hex) Grace Design/Lunatec LLC +A3B000-A3BFFF (base 16) Grace Design/Lunatec LLC + 4689 Ute Highway + Longmont CO 80503 + US + +70-B3-D5 (hex) IDA +B89000-B89FFF (base 16) IDA + 1801 38th Street South + Fargo ND 58103 + US + +70-B3-D5 (hex) Uni Control System Sp. z o. o. +05A000-05AFFF (base 16) Uni Control System Sp. z o. o. + Kartuska 391A + Gdansk Pomorskie 80-125 + PL + +70-B3-D5 (hex) ATEME +531000-531FFF (base 16) ATEME + 6 rue Dewoitine + Vélizy-Villacoublay 78140 + FR + +70-B3-D5 (hex) Reactec Ltd +7A0000-7A0FFF (base 16) Reactec Ltd + Vantage Point + Edinburgh -- select a state -- EH11 4DF + GB + +70-B3-D5 (hex) RedWave Labs Ltd +B67000-B67FFF (base 16) RedWave Labs Ltd + 173 Curie Ave + Didcot OX11 0QG + GB + +70-B3-D5 (hex) INFRASAFE/ ADVANTOR SYSTEMS +C32000-C32FFF (base 16) INFRASAFE/ ADVANTOR SYSTEMS + 12612 CHALLENGER PARKWAY + ORLANDO FL 32826 + US + +70-B3-D5 (hex) OCULI VISION +17E000-17EFFF (base 16) OCULI VISION + Dubai Multi Commodities Centre, Jumeirah Lake Towers, HDS TOWER + Office 304 Dubai PO Box 341061 + AE + +70-B3-D5 (hex) Wincode Technology Co., Ltd. +3F4000-3F4FFF (base 16) Wincode Technology Co., Ltd. + 13F., No.219, Sec. 3, Beixin Rd., + Xindian Dist New Taipei City 231 + TW + +70-B3-D5 (hex) Thinnect, Inc, +E39000-E39FFF (base 16) Thinnect, Inc, + 440 N Wolfe Rd + Sunnyvale CA 94085 + US + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +FD8000-FD8FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Power Ltd. +37B000-37BFFF (base 16) Power Ltd. + Kazal str. 64-66 + Budapest 1031 + HU + +70-B3-D5 (hex) CRDE +CAC000-CACFFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) PushCorp, Inc. +74E000-74EFFF (base 16) PushCorp, Inc. + 3001 W. Kingsley Rd. + Garland TX 75041 + US + +70-B3-D5 (hex) Mecsel Oy +7E9000-7E9FFF (base 16) Mecsel Oy + Laitilankuja 5 + Helsinki 00420 + FI + +70-B3-D5 (hex) Mango DSP, Inc. +6DF000-6DFFFF (base 16) Mango DSP, Inc. + 83 East Avenue Suite#115 + Norwalk CT 06851 + US + +70-B3-D5 (hex) AppTek +06C000-06CFFF (base 16) AppTek + 6867 Elm Street, Suite 300 + McLean VA 22101 + US + +70-B3-D5 (hex) VITEC MULTIMEDIA +A9D000-A9DFFF (base 16) VITEC MULTIMEDIA + 99, rue Pierre Sémard + CHATILLON 92324 CEDEX + FR + +70-B3-D5 (hex) Motec Pty Ltd +618000-618FFF (base 16) Motec Pty Ltd + 121 Merrindale Drive + Croydon South Victoria 3136 + AU + +70-B3-D5 (hex) ORCA Technologies, LLC +7CF000-7CFFFF (base 16) ORCA Technologies, LLC + 934 Calle Negocio, Suite B + San Clemente CA 92673 + US + +70-B3-D5 (hex) Connoiseur Electronics Private Limited +8BE000-8BEFFF (base 16) Connoiseur Electronics Private Limited + Connoiseur House, #12, 13th Main, 12th cross, Doopanahalli, H.A.L. 2nd Stage, Indiranagar + Bangalore Karnataka 560038 + IN + +70-B3-D5 (hex) SA Instrumentation Limited +733000-733FFF (base 16) SA Instrumentation Limited + Mill Court, Mill Lane + Tayport Fife DD6 9EL + GB + +70-B3-D5 (hex) Orange Tree Technologies Ltd +FB5000-FB5FFF (base 16) Orange Tree Technologies Ltd + 173 Curie Avenue, Harwell Oxford + Didcot Oxfordshire OX11 0QG + GB + +70-B3-D5 (hex) Tornado Modular Systems +23E000-23EFFF (base 16) Tornado Modular Systems + Inzhenernaya st. 4a + Novosibirsk 630128 + RU + +70-B3-D5 (hex) Pedax Danmark +286000-286FFF (base 16) Pedax Danmark + Tinvej 5 + Espergærde Sjælland 3060 + DK + +70-B3-D5 (hex) MARKUS LABS +F65000-F65FFF (base 16) MARKUS LABS + Potocna 16 + Kosice 04001 + SK + +70-B3-D5 (hex) Potter Electric Signal Co. LLC +261000-261FFF (base 16) Potter Electric Signal Co. LLC + 1609 Park 370 Place + Hazelwood MO 63042 + US + +70-B3-D5 (hex) MobiPromo +09E000-09EFFF (base 16) MobiPromo + 10, 64-72 Beresford Rd + Lilydale Victoria 3140 + AU + +70-B3-D5 (hex) Nordic Automation Systems AS +B02000-B02FFF (base 16) Nordic Automation Systems AS + Strandgata 12 + Hareid Møre og Romsdal 6060 + NO + +70-B3-D5 (hex) Elektronik & Präzisionsbau Saalfeld GmbH +187000-187FFF (base 16) Elektronik & Präzisionsbau Saalfeld GmbH + Remschützer Straße 1 + Saalfeld Thüringen 07318 + DE + +70-B3-D5 (hex) TruTeq Devices (Pty) Ltd +942000-942FFF (base 16) TruTeq Devices (Pty) Ltd + Ameton House, 1028 Clifton Avenue + Lyttelton Manor X3, Centurion Gauteng 0157 + ZA + +70-B3-D5 (hex) Hatel Elektronik LTD. STI. +1E3000-1E3FFF (base 16) Hatel Elektronik LTD. STI. + 1348 Sok. No:2/V Keremogli Is Merkezi - Yenisehir + IZMIR Konak 35170 + TR + +70-B3-D5 (hex) Picture Elements, Inc. +0EE000-0EEFFF (base 16) Picture Elements, Inc. + 777 Panoramic Way + Berkeley CA 94704 + US + +70-B3-D5 (hex) Kendrion Mechatronics Center GmbH +E49000-E49FFF (base 16) Kendrion Mechatronics Center GmbH + Werner-von-Siemens-Str. 12 + Ilmenau 98693 + DE + +70-B3-D5 (hex) Grossenbacher Systeme AG +A92000-A92FFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) IMAGE TECH CO.,LTD +578000-578FFF (base 16) IMAGE TECH CO.,LTD + 4-9-22,Sanarudai + Naka-ku,Hamamatsu Shizuoka Prefecture 432-8021 + JP + +70-B3-D5 (hex) TATTILE SRL +C7F000-C7FFFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Grupo Epelsa S.L. +D9E000-D9EFFF (base 16) Grupo Epelsa S.L. + C/ Punto Net,3 + Alcala de Henares Madrid 28805 + ES + +70-B3-D5 (hex) E2G srl +659000-659FFF (base 16) E2G srl + Via Polveriera, 6 + Novate Milanese Milano 20026 + IT + +70-B3-D5 (hex) HYOSUNG Power & Industrial Systems +41A000-41AFFF (base 16) HYOSUNG Power & Industrial Systems + 119, Mapo-daero, Mapo-gu + Seoul 04144 + KR + +70-B3-D5 (hex) Flintab AB +D60000-D60FFF (base 16) Flintab AB + Kabelvägen 4 + Jönköping 55302 + SE + +70-B3-D5 (hex) FR-Team International SA +476000-476FFF (base 16) FR-Team International SA + Zone industrielle lotissement Vulcalux 10 + Windhof 8399 + LU + +70-B3-D5 (hex) Perceptics, LLC +88A000-88AFFF (base 16) Perceptics, LLC + 11130 Kingston Pike, Ste 6 + Farragut TN 37934 + US + +70-B3-D5 (hex) EMAC, Inc. +729000-729FFF (base 16) EMAC, Inc. + 2390 EMAC Way + Carbondale IL 62901 + US + +70-B3-D5 (hex) Aplex Technology Inc. +605000-605FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) Kopis Mobile LLC +A06000-A06FFF (base 16) Kopis Mobile LLC + 3010 Lakeland Cv Suite M + Flowood MS 39232 + US + +70-B3-D5 (hex) Smeg S.p.A. +1C4000-1C4FFF (base 16) Smeg S.p.A. + via Leonardo da Vinci 4 + Guastalla RE 42016 + IT + +70-B3-D5 (hex) Dofuntech Co.,LTD. +8F6000-8F6FFF (base 16) Dofuntech Co.,LTD. + RM306, Block E, RD Xinjunhuan,Pujiang + Minghang Shanghai 201113 + CN + +70-B3-D5 (hex) Vista Research, Inc. +D38000-D38FFF (base 16) Vista Research, Inc. + 2231 Crystal Drive, Suite 515 + Arlington VA 22202 + US + +70-B3-D5 (hex) Abbott Medical Optics Inc. +943000-943FFF (base 16) Abbott Medical Optics Inc. + 510 Cottonwood Drive + Milpitas CA 95035 + US + +70-B3-D5 (hex) TWIN DEVELOPMENT +BF2000-BF2FFF (base 16) TWIN DEVELOPMENT + FAUBOURG DE BRUXELLES 320 + GOSSSELIES 6041 + BE + +70-B3-D5 (hex) HAS co.,ltd. +2B3000-2B3FFF (base 16) HAS co.,ltd. + 4F Kojimachi Shimira Bldg., 4-1-5 Kojimachi + Chiyoda-ku TOKYO 1020083 + JP + +70-B3-D5 (hex) AlyTech +45C000-45CFFF (base 16) AlyTech + 3 rue Condorcet + Juvisy sur Orge 91260 + FR + +70-B3-D5 (hex) RedLeaf Security +7E3000-7E3FFF (base 16) RedLeaf Security + 1226 Islington Avenue, Center Tower, 8-10th Floor + Toronto M8X 1Y8 + CA + +70-B3-D5 (hex) CONSOSPY +2F9000-2F9FFF (base 16) CONSOSPY + 2, AVENUE GALILEE + CHASSENEUIL-DU-POITOU VIENNE 86360 + FR + +70-B3-D5 (hex) Dakton Microlabs LLC +11D000-11DFFF (base 16) Dakton Microlabs LLC + 520 Brickell Key Drive, A-1811 + Miami FL 33131 + US + +70-B3-D5 (hex) GRIDSMART Technologies +7EC000-7ECFFF (base 16) GRIDSMART Technologies + 10545 Hardin Valley Rd + Knoxville TN 37932 + US + +70-B3-D5 (hex) ChamSys Ltd +0BE000-0BEFFF (base 16) ChamSys Ltd + Unit 3B Richmond Works, Pitt Road + Southampton Hampshire SO15 3FQ + GB + +70-B3-D5 (hex) Comark Interactive Solutions +39D000-39DFFF (base 16) Comark Interactive Solutions + 430 Fortune Blvd + Milford MA 01757 + US + +70-B3-D5 (hex) Wave Music Ltd +A3C000-A3CFFF (base 16) Wave Music Ltd + Suite 1309 Asia Standard Tower + 59-65 Queens Road Central Hong Kong 000000 + HK + +70-B3-D5 (hex) Yönnet Akıllı Bina ve Otomasyon Sistemleri +C77000-C77FFF (base 16) Yönnet Akıllı Bina ve Otomasyon Sistemleri + Şebnem Sokak Tavukçuoglu + Istanbul Bostancı/Kadıköy 34744 + TR + +70-B3-D5 (hex) DEUTA-WERKE GmbH +A95000-A95FFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) EPD Electronics +5B1000-5B1FFF (base 16) EPD Electronics + 5 Acee Drive + Natrona Heights PA 15065 + US + +70-B3-D5 (hex) HUSTY M.Styczen J.Hupert sp.j. +B28000-B28FFF (base 16) HUSTY M.Styczen J.Hupert sp.j. + ul.Rzepakowa 5e + Krakow malopolska 31-989 + PL + +70-B3-D5 (hex) Wuxi New Optical Communication Co.,Ltd. +524000-524FFF (base 16) Wuxi New Optical Communication Co.,Ltd. + Room 301,Building No. 2, Zhongguancun Software Park Taihu Sub-park + Wuxi Jiangsu 214315 + CN + +70-B3-D5 (hex) WICOM1 GmbH +57D000-57DFFF (base 16) WICOM1 GmbH + Im Frauental 15 + Amberg Bavaria 92224 + DE + +70-B3-D5 (hex) QUERCUS TECHNOLOGIES, S.L. +A12000-A12FFF (base 16) QUERCUS TECHNOLOGIES, S.L. + Antoni Isern 4 baixos + Reus Tarragona 43205 + ES + +70-B3-D5 (hex) Net And Print Inc. +AF5000-AF5FFF (base 16) Net And Print Inc. + 52-1, Aza Kawakubo, + Koriyama Fukushima 963-0725 + JP + +70-B3-D5 (hex) SmartGuard LLC +C01000-C01FFF (base 16) SmartGuard LLC + 3660 Technology Drive NE + Minneapolis MN 55418 + US + +70-B3-D5 (hex) INFOSOFT DIGITAL DESIGN & SERVICES PRIVATE LIMITED +4EB000-4EBFFF (base 16) INFOSOFT DIGITAL DESIGN & SERVICES PRIVATE LIMITED + 104-105, Suneja Tower-1 + New Delhi Delhi 110058 + IN + +70-B3-D5 (hex) Shachihata Inc. +6FB000-6FBFFF (base 16) Shachihata Inc. + 37 , SHINMEI-CHO , KOUWA + INAZAWA AICHI 492-8102 + JP + +70-B3-D5 (hex) ERMINE Corporation +D73000-D73FFF (base 16) ERMINE Corporation + Hirooka-Harashinden 573-6, SK-Residence, + Shiojiri Nagano 399-0706 + JP + +70-B3-D5 (hex) Netbric Technology Co.,Ltd. +64A000-64AFFF (base 16) Netbric Technology Co.,Ltd. + Room 801D, POWER CREATIVE #E, 1st Shangdi + BeiJing 100085 + CN + +70-B3-D5 (hex) Golden Grid Systems +20A000-20AFFF (base 16) Golden Grid Systems + 2775 Curry Street + pleasanton California 94588 + US + +70-B3-D5 (hex) CRDE +7C8000-7C8FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) SURTEC +5FC000-5FCFFF (base 16) SURTEC + 616 avenue de l'Europe + Le Creusot burgundy 71206 + FR + +70-B3-D5 (hex) GLOBALCOM ENGINEERING SPA +D3F000-D3FFFF (base 16) GLOBALCOM ENGINEERING SPA + Via Volta 9 + MORNAGO VA 21020 + IT + +70-B3-D5 (hex) Precitec Optronik GmbH +0C5000-0C5FFF (base 16) Precitec Optronik GmbH + Schleussnerstraße 54 + Neu-Isenburg Hessen 63263 + DE + +70-B3-D5 (hex) Swiftnet SOC Ltd +76A000-76AFFF (base 16) Swiftnet SOC Ltd + Bldg 22, Cambridge Office Park + Centurion Gauteng 0157 + ZA + +70-B3-D5 (hex) Triax A/S +D7E000-D7EFFF (base 16) Triax A/S + Bjornkaervej 3 + Hornsyld Denmark 8783 + DK + +70-B3-D5 (hex) Grupo Epelsa S.L. +EA4000-EA4FFF (base 16) Grupo Epelsa S.L. + C/ Punto Net,3 + Alcala de Henares Madrid 28805 + ES + +70-B3-D5 (hex) NARA CONTROLS INC. +FDF000-FDFFFF (base 16) NARA CONTROLS INC. + NARA BUILDING, 12TH FLOOR 719 + SEOUL SEOUL 100-043 + KR + +70-B3-D5 (hex) ART SPA +E7A000-E7AFFF (base 16) ART SPA + VOC.PISCHIELLO, 20 + PASSIGNANO SUL TRASIMENO PG 06065 + IT + +70-B3-D5 (hex) Aplex Technology Inc. +F00000-F00FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) Dorsett Technologies, Inc. +E76000-E76FFF (base 16) Dorsett Technologies, Inc. + + Yadkinville NC 27055 + US + +70-B3-D5 (hex) Yaviar +226000-226FFF (base 16) Yaviar + Mamina-Sibiryaka 145 + Ekaterinburg Sverdlovsk oblast 620137 + RU + +70-B3-D5 (hex) LumiGrow, Inc +172000-172FFF (base 16) LumiGrow, Inc + 8 Digital Drive + Novato CA 94949 + US + +70-B3-D5 (hex) TRIUMPH BOARD a.s. +D57000-D57FFF (base 16) TRIUMPH BOARD a.s. + Neklanova 122/15 + Prague 12800 + CZ + +70-B3-D5 (hex) Hydra Controls +3FF000-3FFFFF (base 16) Hydra Controls + 291 Worcester Road + New Braintree MA 01531 + US + +70-B3-D5 (hex) Elektro-System s.c. +343000-343FFF (base 16) Elektro-System s.c. + Sienkiewicza 25 + Kutno łódzkie 99-300 + PL + +70-B3-D5 (hex) Dynetics, Inc. +B91000-B91FFF (base 16) Dynetics, Inc. + 1004 Explorer Blvd + Huntsville AL 35806 + US + +70-B3-D5 (hex) Xiamen Maxincom Technologies Co., Ltd. +9E7000-9E7FFF (base 16) Xiamen Maxincom Technologies Co., Ltd. + B1F, A District, HuaXun Building, + Xiamen Fujian 361000 + CN + +70-B3-D5 (hex) Quadio Devices Private Limited +472000-472FFF (base 16) Quadio Devices Private Limited + 101 Business Avenue + Pune Maharashtra 411001 + IN + +70-B3-D5 (hex) sydetion UG (h.b.) +538000-538FFF (base 16) sydetion UG (h.b.) + Helfensteinstr. 14 + GOEPPINGEN BW 73037 + DE + +70-B3-D5 (hex) Bolide Technology Group, Inc. +2DC000-2DCFFF (base 16) Bolide Technology Group, Inc. + 468 S. San Dimas Ave., + San Dimas CA 91773 + US + +70-B3-D5 (hex) MC2-Technologies +505000-505FFF (base 16) MC2-Technologies + 5 rue du Colibri + Villeneuve d'Ascq Nord 59650 + FR + +70-B3-D5 (hex) EIDOS s.p.a. +35E000-35EFFF (base 16) EIDOS s.p.a. + Via dell'Industria, 11 + CHIERI TO 10023 + IT + +70-B3-D5 (hex) DuraComm Corporation +6B3000-6B3FFF (base 16) DuraComm Corporation + 6655 Troost Avenue + Kansas City MO 64131 + US + +70-B3-D5 (hex) Aplex Technology Inc. +2EE000-2EEFFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) ID Lock AS +F2D000-F2DFFF (base 16) ID Lock AS + Stasjonsveien 46 + Moi Rogaland 4460 + NO + +70-B3-D5 (hex) GACI +4AD000-4ADFFF (base 16) GACI + 5 avenue du Québec + Villebon sur Yvette Essonne 91140 + FR + +70-B3-D5 (hex) Sensor Developments +935000-935FFF (base 16) Sensor Developments + Nordre Kullerød 21 + Sandefjord 3241 + NO + +70-B3-D5 (hex) Array Telepresence +C2A000-C2AFFF (base 16) Array Telepresence + 7593 Tylers Place Blvd. + West Chester Ohio 45069 + US + +70-B3-D5 (hex) Solid State Disks Ltd +C85000-C85FFF (base 16) Solid State Disks Ltd + The Granary + Reading Berkshire RG74BB + GB + +70-B3-D5 (hex) dinosys +F36000-F36FFF (base 16) dinosys + 501,35,Gwangnaruro 6-gil, + Seoul Seoul 133-832 + KR + +70-B3-D5 (hex) Solectrix +342000-342FFF (base 16) Solectrix + Fürther Str. 244b + Nürnberg Bayern 90429 + DE + +70-B3-D5 (hex) Signature Control Systems, LLC. +E20000-E20FFF (base 16) Signature Control Systems, LLC. + 425 Brice Rd. North + Blacklick OH 43004 + US + +70-B3-D5 (hex) OAS Sweden AB +347000-347FFF (base 16) OAS Sweden AB + Brorod 7774 + Klippan Skane 26492 + SE + +70-B3-D5 (hex) iSiS-Ex Limited +530000-530FFF (base 16) iSiS-Ex Limited + Unit A & B Windmill Industrial Estate + Malton North Yorkshire YO17 6BT + GB + +70-B3-D5 (hex) Herrick Tech Labs +3F9000-3F9FFF (base 16) Herrick Tech Labs + 20201 Century Blvd. + Germantown MD 20874 + US + +70-B3-D5 (hex) Sarokal Test Systems Oy +FA2000-FA2FFF (base 16) Sarokal Test Systems Oy + Paulaharjuntie 20 B 2 + Oulu Oulu 90530 + FI + +70-B3-D5 (hex) Profound Medical Inc. +B8B000-B8BFFF (base 16) Profound Medical Inc. + 3080 Yonge St Suite 4040 + Toronto Ontario M4N3N1 + CA + +70-B3-D5 (hex) MECA SYSTEM +A1C000-A1CFFF (base 16) MECA SYSTEM + 1-906 INNOPLEX 552 + Suwon-si Gyeonggi-do 443380 + KR + +70-B3-D5 (hex) GE Aviation Cheltenham +52B000-52BFFF (base 16) GE Aviation Cheltenham + Evesham Road + Cheltenham Glos GL52 8SF + GB + +70-B3-D5 (hex) AMMT GmbH +D80000-D80FFF (base 16) AMMT GmbH + Anselm-Feuerbach-Str. 6 + Frankenthal RLP 67227 + DE + +70-B3-D5 (hex) SAVRONİK ELEKTRONİK +15F000-15FFFF (base 16) SAVRONİK ELEKTRONİK + ORGANİZE SAN BÖL. + ESKİŞEHİR ODUNPAZARI 26110 + TR + +70-B3-D5 (hex) Jingtu Printing Systems Co., Ltd +78B000-78BFFF (base 16) Jingtu Printing Systems Co., Ltd + 25 Xiaoyun Road, + Beijing 100027 + CN + +70-B3-D5 (hex) Hear Gear, Inc. +A26000-A26FFF (base 16) Hear Gear, Inc. + 7800 Technology Drive + West Melbourne Florida 32904 + US + +70-B3-D5 (hex) LECIP CORPORATION +A50000-A50FFF (base 16) LECIP CORPORATION + 1260-1 + Motosu-shi Gifu-ken 501-0401 + JP + +70-B3-D5 (hex) Russian Telecom Equipment Company +D9B000-D9BFFF (base 16) Russian Telecom Equipment Company + 3, Kapranov lane + Moscow Moscow 123242 + RU + +70-B3-D5 (hex) Vaisala Oyj +5FF000-5FFFFF (base 16) Vaisala Oyj + Vanha Nurmijarventie 21 + VANTAA Fin-01670 + FI + +70-B3-D5 (hex) Symbicon Ltd +7A7000-7A7FFF (base 16) Symbicon Ltd + Heinimäentie 1 + Kajaani Finland 87250 + FI + +70-B3-D5 (hex) Soniclean Pty Ltd +79B000-79BFFF (base 16) Soniclean Pty Ltd + 38 Anderson Street + Thebarton SA 5031 + AU + +70-B3-D5 (hex) GOMA ELETTRONICA SpA +D79000-D79FFF (base 16) GOMA ELETTRONICA SpA + Via Carlo Capelli 89 + TURIN TO 10146 + IT + +70-B3-D5 (hex) GEGA ELECTRONIQUE +65D000-65DFFF (base 16) GEGA ELECTRONIQUE + 1 RUE SAINT ELOI + MONTCEAU LES MINES SAONE ET LOIRE 71300 + FR + +70-B3-D5 (hex) Lumine Lighting Solutions Oy +83F000-83FFFF (base 16) Lumine Lighting Solutions Oy + Albertinkatu 27b + Helsinki Uusimaa 00180 + FI + +70-B3-D5 (hex) DISK Multimedia s.r.o. +E70000-E70FFF (base 16) DISK Multimedia s.r.o. + Sokolska 13 + Boskovice JM 68001 + CZ + +70-B3-D5 (hex) Commsignia Ltd. +C5A000-C5AFFF (base 16) Commsignia Ltd. + Bartok Bela ut 105-113. Building 4. Floor 2 + Budapest Budapest 1115 + HU + +70-B3-D5 (hex) CAS Medical Systems, Inc +9DB000-9DBFFF (base 16) CAS Medical Systems, Inc + 44 East Industrial Road + Branford CT 06405 + US + +70-B3-D5 (hex) JSC Electrical Equipment Factory +A6E000-A6EFFF (base 16) JSC Electrical Equipment Factory + Otradnaya str, 6 + Moscow 129626 + RU + +70-B3-D5 (hex) Airborne Engineering Limited +46B000-46BFFF (base 16) Airborne Engineering Limited + 3 Landmark House + Glastonbury Somerset BA6 9FR + GB + +70-B3-D5 (hex) Alpha Elettronica s.r.l. +F7E000-F7EFFF (base 16) Alpha Elettronica s.r.l. + Strada Antolini 2/a + Collecchio Parma 43044 + IT + +70-B3-D5 (hex) Head +3E3000-3E3FFF (base 16) Head + kita-ku tenjinbashi 2-2-25 + Osaka-shi Osaka 5300041 + JP + +70-B3-D5 (hex) hangzhou battle link technology Co.,Ltd +ED5000-ED5FFF (base 16) hangzhou battle link technology Co.,Ltd + xipu road no. 1503 binke building, room 1606 + hangzhou binjiang zhejiang 310052 + CN + +70-B3-D5 (hex) CP contech electronic GmbH +EB1000-EB1FFF (base 16) CP contech electronic GmbH + Westring 31a + Leopoldshöhe NRW 33818 + DE + +70-B3-D5 (hex) Tecnint HTE SRL +FC6000-FC6FFF (base 16) Tecnint HTE SRL + Via della Tecnica 16/18 + Osnago Lecco 23875 + IT + +70-B3-D5 (hex) Communication Technology Ltd. +0A4000-0A4FFF (base 16) Communication Technology Ltd. + 11F,No.166, Jian 1th Rd.,Jhonghe Dist. + 11F,No.166, Jian 1th Rd.,Jhonghe Dist. + TW + +70-B3-D5 (hex) Haag-Streit AG +5C5000-5C5FFF (base 16) Haag-Streit AG + Gartenstadtstrasse 10 + Koeniz Bern CH-3098 + CH + +70-B3-D5 (hex) DSP DESIGN +5E4000-5E4FFF (base 16) DSP DESIGN + TAPTON PK INNOVATION CENTRE + CHESTERFIELD DERBYSHIRE S41 0TZ + GB + +70-B3-D5 (hex) ACS MOTION CONTROL +0EC000-0ECFFF (base 16) ACS MOTION CONTROL + 1 Hataasia St., Ramat Gabriel Industrial Park, + Migdal Ha'Emek Israel 2307037 + IL + +70-B3-D5 (hex) speedsignal GmbH +C25000-C25FFF (base 16) speedsignal GmbH + Aeussere Oberaustr. 20 + Rosenheim Bavaria 83026 + DE + +70-B3-D5 (hex) astozi consulting Tomasz Zieba +DF0000-DF0FFF (base 16) astozi consulting Tomasz Zieba + ul. Inzynierska 8/20 + Nowa Sol Lubuskie 67-100 + PL + +70-B3-D5 (hex) FUELCELLPOWER +0A5000-0A5FFF (base 16) FUELCELLPOWER + D-301, Bundang Technopark, yatop-dong + Gyeonggi-do, Korea Bundang-gu, Seongnam-si 463-760 + KR + +70-B3-D5 (hex) MOG Laboratories Pty Ltd +84A000-84AFFF (base 16) MOG Laboratories Pty Ltd + 18 Boase St + Brunswick VIC 3056 + AU + +70-B3-D5 (hex) iungo +6F3000-6F3FFF (base 16) iungo + Vrouwenlaan 62 + Zwolle Overijssel 8017 HS + NL + +70-B3-D5 (hex) Power Security Systems Ltd. +AFA000-AFAFFF (base 16) Power Security Systems Ltd. + Kazal str. 64-66 + Budapest Budapest 1031 + HU + +70-B3-D5 (hex) Plum sp. z o.o +104000-104FFF (base 16) Plum sp. z o.o + Ignatki 27a + Kleosin podlaskie 16-001 + PL + +70-B3-D5 (hex) Multipure International +CDE000-CDEFFF (base 16) Multipure International + 7251 Cathedral Rock Dr. + Las Vegas Nevada 89128 + US + +70-B3-D5 (hex) KST technology +0AB000-0ABFFF (base 16) KST technology + 164-1, KST b/d., Bangi-dong, songpa-gu + SEOUL N/A 138-050 + KR + +70-B3-D5 (hex) Phoniro Systems AB +731000-731FFF (base 16) Phoniro Systems AB + Rorkullsvagen 4 + Halmstad Halland 30241 + SE + +70-B3-D5 (hex) Peek Traffic +501000-501FFF (base 16) Peek Traffic + 2906 Corporate Way + Palmetto FL 34235 + US + +70-B3-D5 (hex) NELS Ltd. +82C000-82CFFF (base 16) NELS Ltd. + bldg.23, h.5, proezd 4806. + Moscow, Zelenograd Moscow 124498 + RU + +70-B3-D5 (hex) Environexus +A62000-A62FFF (base 16) Environexus + 50 Ricketts Road + Mount Waverley VIC 3149 + AU + +70-B3-D5 (hex) PCSC +A57000-A57FFF (base 16) PCSC + 3541 Challenger Street + Torrance CA 90503 + US + +70-B3-D5 (hex) VECTARE Inc +6D9000-6D9FFF (base 16) VECTARE Inc + 10340 Democracy Ln Ste 101 + Fairfax VA 22030 + US + +70-B3-D5 (hex) Stmovic +8F5000-8F5FFF (base 16) Stmovic + 201 2, 3 th. + Gangdonggu Seoul 134-811 + KR + +70-B3-D5 (hex) AGR International +ABF000-ABFFFF (base 16) AGR International + 615 Whitestown Road + Butler PA 16001 + US + +70-B3-D5 (hex) BKM-Micronic Richtfunkanlagen GmbH +ABC000-ABCFFF (base 16) BKM-Micronic Richtfunkanlagen GmbH + Im Steinernen Kreuz 19 + Wurmberg 75449 + DE + +70-B3-D5 (hex) SSL - Electrical Aerospace Ground Equipment Section +03B000-03BFFF (base 16) SSL - Electrical Aerospace Ground Equipment Section + 3852 Fabian Way + Palo Alto CALIFORNIA 94303 + US + +70-B3-D5 (hex) Kubu, Inc. +19C000-19CFFF (base 16) Kubu, Inc. + 991 El Cajon Way + Palo Alto CA 94303 + US + +70-B3-D5 (hex) DORLET SAU +B3C000-B3CFFF (base 16) DORLET SAU + Albert Eistein 34 + Alava SPAIN 01510 + ES + +70-B3-D5 (hex) Videri Inc. +33C000-33CFFF (base 16) Videri Inc. + 541 West 23rd Street + New York NY 10011 + US + +70-B3-D5 (hex) AL ZAJEL MODERN TELECOMM +F68000-F68FFF (base 16) AL ZAJEL MODERN TELECOMM + PO BOX:3932 + AL QURUM MUSCAT 112 + OM + +70-B3-D5 (hex) idaqs Co.,Ltd. +634000-634FFF (base 16) idaqs Co.,Ltd. + M&I Building 2F + Suginami-Ku Tokyo 167-0042 + JP + +70-B3-D5 (hex) RFL Electronics, Inc. +54E000-54EFFF (base 16) RFL Electronics, Inc. + 353 Powerville Road + Booton Twp. NJ 07005 + US + +70-B3-D5 (hex) TWC +204000-204FFF (base 16) TWC + 12101 Airport Way + Broomfield CO 80021 + US + +70-B3-D5 (hex) Schwer+Kopka GmbH +099000-099FFF (base 16) Schwer+Kopka GmbH + Herkner Str. 4 + Weingarten Baden Württemberg 88250 + DE + +70-B3-D5 (hex) Private +C6A000-C6AFFF (base 16) Private + +70-B3-D5 (hex) Marimo electronics Co.,Ltd. +029000-029FFF (base 16) Marimo electronics Co.,Ltd. + 1071,SUWAGATA + UEDA NAGANO 3860032 + JP + +70-B3-D5 (hex) Woodside Electronics +E27000-E27FFF (base 16) Woodside Electronics + 1311 Bluegrass Pl + Woodland California 95776 + US + +70-B3-D5 (hex) DSP DESIGN +C81000-C81FFF (base 16) DSP DESIGN + TAPTON PK INNOVATION CENTRE + CHESTERFIELD DERBYSHIRE S41 0TZ + GB + +70-B3-D5 (hex) MI INC. +E53000-E53FFF (base 16) MI INC. + 3F Daiichi-Heiwa-Bldg. 5-1, Kabuto-cho + TOKYO Chuo-ku 103-0026 + JP + +70-B3-D5 (hex) adidas AG +7A9000-7A9FFF (base 16) adidas AG + Adi-Dassler-Strasse 1 + Herzogenaurach Bayern 91074 + DE + +70-B3-D5 (hex) O-Net Automation Technology (Shenzhen)Limited +EE4000-EE4FFF (base 16) O-Net Automation Technology (Shenzhen)Limited + #35 Cuijing Road,Pingshan New District,Guangdong,Shenzhen.China + Shenzhen Guangdong 518118 + CN + +70-B3-D5 (hex) Myro Control, LLC +B2A000-B2AFFF (base 16) Myro Control, LLC + 201 164th Ave NE + Redmond WA 98052 + US + +70-B3-D5 (hex) Labotect Labor-Technik-Göttingen GmbH +61F000-61FFFF (base 16) Labotect Labor-Technik-Göttingen GmbH + Kampweg 12 + Rosdorf 37124 + DE + +70-B3-D5 (hex) AOT System GmbH +655000-655FFF (base 16) AOT System GmbH + Am Becketal 14 + Bremen 28755 + DE + +70-B3-D5 (hex) Baader Planetarium GmbH +E07000-E07FFF (base 16) Baader Planetarium GmbH + Zur Sternwarte + Mammendorf Bavaria 82291 + DE + +70-B3-D5 (hex) Acco Brands Europe +6F6000-6F6FFF (base 16) Acco Brands Europe + Oxford house + Aylesbury Buckinghamshire HP21 8SZ + GB + +70-B3-D5 (hex) SINTOKOGIO, LTD +42F000-42FFFF (base 16) SINTOKOGIO, LTD + 3-1, Honohara + Toyokawa Aichi 4428505 + JP + +70-B3-D5 (hex) Sensor Highway Ltd +702000-702FFF (base 16) Sensor Highway Ltd + Unit 7, The Quadrangle + Romsey United Kingdom SO51 9DL + GB + +70-B3-D5 (hex) Don Electronics Ltd +044000-044FFF (base 16) Don Electronics Ltd + Westfield Industrial Estate + Leeds West Yorkshire LS19 7LX + GB + +70-B3-D5 (hex) Scanvaegt Nordic A/S +F38000-F38FFF (base 16) Scanvaegt Nordic A/S + Johann Gutenbergs vej 5-9 + Aarhus N 8200 + DK + +70-B3-D5 (hex) Dromont S.p.A. +C2C000-C2CFFF (base 16) Dromont S.p.A. + via Borzone 42 + Grinzane Cavour Cuneo 12060 + IT + +70-B3-D5 (hex) InAccess Networks SA +077000-077FFF (base 16) InAccess Networks SA + 12, Sorou str. + Maroussi Athens GR15125 + GR + +70-B3-D5 (hex) QUERCUS TECHNOLOGIES, S. L. +4C1000-4C1FFF (base 16) QUERCUS TECHNOLOGIES, S. L. + Antoni Isern 4 + Reus Tarragona 43205 + ES + +70-B3-D5 (hex) FLSmidth +D4E000-D4EFFF (base 16) FLSmidth + Vigerslev Allé 77 + Valby Copenhagen 2500 + DK + +70-B3-D5 (hex) Nexus Tech. VN +B8A000-B8AFFF (base 16) Nexus Tech. VN + 2139 Corktree Ln + San Jose California 95132 + US + +70-B3-D5 (hex) Lenoxi Automation s.r.o. +D8B000-D8BFFF (base 16) Lenoxi Automation s.r.o. + Lipa 218 + Lipa u Havlickova Brodu Vysocina 58257 + + +70-B3-D5 (hex) Ingenieurbuero SOMTRONIK +814000-814FFF (base 16) Ingenieurbuero SOMTRONIK + Riesebusch 17 + Bad Schwartau Schleswig Holstein 23611 + DE + +70-B3-D5 (hex) XTech2 SIA +29D000-29DFFF (base 16) XTech2 SIA + Katrinas dambis 24a-15 + Riga LV1045 + LV + +70-B3-D5 (hex) ProConnections, Inc. +0A9000-0A9FFF (base 16) ProConnections, Inc. + 239 Littleton Road + Westford Massachusettes 01886 + US + +70-B3-D5 (hex) SBS-Feintechnik GmbH & Co. KG +ECD000-ECDFFF (base 16) SBS-Feintechnik GmbH & Co. KG + Hermann-Burger-Str. 31 + Schonach 78136 + DE + +70-B3-D5 (hex) ACS electronics srl +35C000-35CFFF (base 16) ACS electronics srl + Via Lamaneigra 10/R + Tribogna Genova 16030 + + +70-B3-D5 (hex) Fantom Wireless, Inc. +190000-190FFF (base 16) Fantom Wireless, Inc. + 156 2nd Street, Suite #614 + San Francisco CA 94014 + + +70-B3-D5 (hex) PLCiS +0E0000-0E0FFF (base 16) PLCiS + B115,Lotte plaza Bldg,971-1, + Suwon GyungGi-Do 443-811 + KR + +70-B3-D5 (hex) Ultra Electronics Sonar System Division +3ED000-3EDFFF (base 16) Ultra Electronics Sonar System Division + 418, Bridport Road + Greenford Middlesex UB6 8UA + GB + +00-1B-C5 (hex) Dialine +0C8000-0C8FFF (base 16) Dialine + 1 allee du pressoir + Sucy en Brie Val de Marne 94370 + FR + +00-1B-C5 (hex) WIZZILAB SAS +0C7000-0C7FFF (base 16) WIZZILAB SAS + 64 rue Greneta + Paris 75002 + FR + +00-1B-C5 (hex) ELDES +0C4000-0C4FFF (base 16) ELDES + Ukmerges 283B + Vilnius 06313 + LT + +00-1B-C5 (hex) Denki Kogyo Company, Limited +0B9000-0B9FFF (base 16) Denki Kogyo Company, Limited + 13-4 Satsuki-cho + Kanuma-shi Tochigi 3220014 + JP + +00-1B-C5 (hex) Exibea AB +0B5000-0B5FFF (base 16) Exibea AB + Ekmansgatan 3 + 411 SE- 41132 + SE + +00-1B-C5 (hex) FSM Solutions Limited +0B3000-0B3FFF (base 16) FSM Solutions Limited + Granatny per 2/9-73 + Moscow Moscow 123001 + RU + +00-1B-C5 (hex) Roslen Eco-Networking Products +0B1000-0B1FFF (base 16) Roslen Eco-Networking Products + 2010 Vada Ranch Road + Auburn CA 95603 + US + +00-1B-C5 (hex) HomerSoft sp. z o.o. +0A0000-0A0FFF (base 16) HomerSoft sp. z o.o. + Kapelanka 13B + Krakow 30-347 + PL + +00-1B-C5 (hex) Navitar Inc +09D000-09DFFF (base 16) Navitar Inc + 200 Commerce Dr + Rochester NY 14623 + US + +00-1B-C5 (hex) Sanstreak Corp. +096000-096FFF (base 16) Sanstreak Corp. + 300 Santana Row + San Jose CA 95128 + US + +00-1B-C5 (hex) Ambient Devices, Inc. +093000-093FFF (base 16) Ambient Devices, Inc. + One Broadway + Cambridge MA 02142 + US + +00-1B-C5 (hex) Arnouse Digital Devices, Corp. +092000-092FFF (base 16) Arnouse Digital Devices, Corp. + 1983 Marcus Ave., Suite 104 + Lake Success New York 11042 + US + +00-1B-C5 (hex) Unilever R&D +08F000-08FFFF (base 16) Unilever R&D + Port Sunlight + Bebington Wirral ch63 3jw + GB + +00-1B-C5 (hex) Nistica +08B000-08BFFF (base 16) Nistica + 745 Route 202-206 + Bridgewater NJ 08807 + US + +00-1B-C5 (hex) Oberon microsystems, Inc. +085000-085FFF (base 16) Oberon microsystems, Inc. + Technoparkstrasse 1 + Zurich ZH 8005 + CH + +00-1B-C5 (hex) head +07C000-07CFFF (base 16) head + kita-ku tenjinbashi 2-2-25 + Osaka-shi Osaka 5300041 + JP + +00-1B-C5 (hex) Greatcom AG +07D000-07DFFF (base 16) Greatcom AG + Gewerbestrasse 20 + Egg ZH 8132 + CH + +00-1B-C5 (hex) LUMINO GmbH +080000-080FFF (base 16) LUMINO GmbH + Europark Fichtenhain A8 + Krefeld NRW 47807 + US + +00-1B-C5 (hex) Datasat Digital Entertainment +069000-069FFF (base 16) Datasat Digital Entertainment + 9631 Topanga Canyon Place + Chatsworth California 91311 + US + +00-1B-C5 (hex) Embit srl +067000-067FFF (base 16) Embit srl + via Emilia est, 911 + Modena Modena 41122 + IT + +00-1B-C5 (hex) Enkora Oy Ltd +064000-064FFF (base 16) Enkora Oy Ltd + Köydenpunojankatu 8 G + Helsinki Uusimaa 00180 + FI + +00-1B-C5 (hex) Scientific-Technical Center Epsilon Limited company +061000-061FFF (base 16) Scientific-Technical Center Epsilon Limited company + Shkiperskiy Protok, plot 14, building 1 + St.-Petersburg - 199106 + RU + +00-1B-C5 (hex) optiMEAS GmbH +058000-058FFF (base 16) optiMEAS GmbH + Am Houiller Platz 4 + Friedrichsdorf 61381 + DE + +00-1B-C5 (hex) EREE Electronique +057000-057FFF (base 16) EREE Electronique + 6 avenue Dr Schweitzer + MEYZIEU 69882 + FR + +00-1B-C5 (hex) LUMIPLAN TRANSPORT +055000-055FFF (base 16) LUMIPLAN TRANSPORT + 1 ,Impasse Augustin Fresnel + SAINT-HERBLAIN 44815 + FR + +00-1B-C5 (hex) EUROCONTROL S.p.A. +049000-049FFF (base 16) EUROCONTROL S.p.A. + Via Varenna 52/A + Genova Italy 16155 + IT + +00-1B-C5 (hex) Marvel Digital International Limited +045000-045FFF (base 16) Marvel Digital International Limited + 15/F Siu On Centre + Wanchai HKSAR + HK + +00-1B-C5 (hex) JE Suunnittelu Oy +033000-033FFF (base 16) JE Suunnittelu Oy + Teollisuustie 16 + Pietarsaari 68600 + FI + +00-1B-C5 (hex) InterCEL Pty Ltd +034000-034FFF (base 16) InterCEL Pty Ltd + 33 Glenvale Crescent + Mulgrave Victoria 3170 + AU + +00-1B-C5 (hex) ADIXEIN LIMITED +031000-031FFF (base 16) ADIXEIN LIMITED + 14 Plater Drive + Oxford Oxfordshire OX2 6QT + GB + +00-1B-C5 (hex) Care Everywhere LLC +02C000-02CFFF (base 16) Care Everywhere LLC + 9 Tech Circle + Natick MA 01760 + US + +00-1B-C5 (hex) Saturn South Pty Ltd +02B000-02BFFF (base 16) Saturn South Pty Ltd + 4 Maning Avenue + Sandy Bay Tasmania 7005 + AU + +00-1B-C5 (hex) STECHWIN.CO.LTD. +028000-028FFF (base 16) STECHWIN.CO.LTD. + 368-2, HwaGok 1-Dong + Seoul 157-884 + KR + +00-1B-C5 (hex) CJSC STC SIMOS +022000-022FFF (base 16) CJSC STC SIMOS + 41, Geroyev Khasana Str. + Perm 614990 + RU + +00-1B-C5 (hex) Momentum Data Systems +020000-020FFF (base 16) Momentum Data Systems + 17330 Brookhurst Street + Fountain Valley CA 92708 + US + +00-1B-C5 (hex) Openpeak, Inc +021000-021FFF (base 16) Openpeak, Inc + 1750 Clint Moore Rd + Boca Raton Florida 33487 + US + +00-1B-C5 (hex) Saturn Solutions Ltd +01F000-01FFFF (base 16) Saturn Solutions Ltd + Ingles Yard + Folkestone Kent CT20 2RY + GB + +00-1B-C5 (hex) Energotechnica OOO NPP Ltd +016000-016FFF (base 16) Energotechnica OOO NPP Ltd + 3, Lermontova str. + Penza + RU + +00-1B-C5 (hex) Mercury HMI Ltd +00A000-00AFFF (base 16) Mercury HMI Ltd + George House + Malton North Yorkshire Y017 6YB + GB + +00-1B-C5 (hex) Softel SA de CV +010000-010FFF (base 16) Softel SA de CV + Camino a Santa Teresa + Tlalpan 14010 + MX + +00-1B-C5 (hex) Quantum Technology Sciences, Inc. +00C000-00CFFF (base 16) Quantum Technology Sciences, Inc. + 1980 N. Atlantic Ave., Suite 930 + Cocoa Beach FL 32931 + US + +00-1B-C5 (hex) Solomon Systech Pte Ltd +009000-009FFF (base 16) Solomon Systech Pte Ltd + 3 Bishan Place, + 579838 + SG + +70-B3-D5 (hex) Biennebi s.r.l. +537000-537FFF (base 16) Biennebi s.r.l. + Via Santi 23 + Bione Brescia 25070 + IT + +70-B3-D5 (hex) ORtek Technology, Inc. +3D0000-3D0FFF (base 16) ORtek Technology, Inc. + 13F, no.150, Jian-Yi Rd., ZhongHe Dist. + New Taipei City Taiwan 23511 + TW + +70-B3-D5 (hex) Primalucelab isrl +329000-329FFF (base 16) Primalucelab isrl + VIA BRENTELLA 53/7 + ROVEREDO IN PIANO PN 33080 + IT + +70-B3-D5 (hex) cal4care Pte Ltd +043000-043FFF (base 16) cal4care Pte Ltd + 118 Aljunied AVE 2 + SINGAPORE SINGAPORE 380118 + SG + +70-B3-D5 (hex) Golding Audio Ltd +454000-454FFF (base 16) Golding Audio Ltd + 8 Peartree Business Centre, Stanway + Colchester Essex CO30JN + GB + +70-B3-D5 (hex) DEUTA-WERKE GmbH +81D000-81DFFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) Shenzhen Virtual Clusters Information Technology Co.,Ltd. +0DD000-0DDFFF (base 16) Shenzhen Virtual Clusters Information Technology Co.,Ltd. + Room 201,Building A,No.1,Qianhai 1st Road,Shengang cooperation zone,Qianhai + Shenzhen 518054 + CN + +70-B3-D5 (hex) TATTILE SRL +EC5000-EC5FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Lumentum +BFD000-BFDFFF (base 16) Lumentum + 460 N McCarthy Blvd + Milpitas CA 95035 + US + +70-B3-D5 (hex) Nuance Hearing Ltd. +569000-569FFF (base 16) Nuance Hearing Ltd. + Raoul Wallenberg 24, Building A1, Floor 3 + Tel Aviv 6971920 + IL + +70-B3-D5 (hex) Connected Response +C9C000-C9CFFF (base 16) Connected Response + 12 Meiklejohn Street + Stirling Stirling FK9 5HQ + GB + +70-B3-D5 (hex) IHI Rotating Machinery Engineering Co.,Ltd. +89C000-89CFFF (base 16) IHI Rotating Machinery Engineering Co.,Ltd. + 1, Shin-nakahara-cho, Isogo-ku + Yokohama Kanagawa 235-8501 + JP + +70-B3-D5 (hex) iREA System Industry +113000-113FFF (base 16) iREA System Industry + Rm 210, Sahwa-ro 210, Uichang-gu + Changwon-si Gyeongsangnam-do 51390 + KR + +70-B3-D5 (hex) Netzikon GmbH +D3D000-D3DFFF (base 16) Netzikon GmbH + Gerberstrasse 34 + Backnang 71522 + DE + +70-B3-D5 (hex) WiFi Nation Ltd +95F000-95FFFF (base 16) WiFi Nation Ltd + Unit 53, CoWorkz Business Centre, Chester West Employment Park, Minerva Avenue, + Chester Cheshire CH1 4QL + GB + +70-B3-D5 (hex) Suzhou Sapa Automotive Technology Co.,Ltd +9AC000-9ACFFF (base 16) Suzhou Sapa Automotive Technology Co.,Ltd + Room 812, Building 1, Suhong Road 177 + Suzhou Jiangsu 215000 + CN + +70-B3-D5 (hex) LX Design House +221000-221FFF (base 16) LX Design House + 4 Cornwallis Street + Eveleigh NSW 2015 + AU + +70-B3-D5 (hex) Amazon Technologies Inc. +270000-270FFF (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno 89507 + US + +70-B3-D5 (hex) i-View Communication Inc. +CA7000-CA7FFF (base 16) i-View Communication Inc. + 2F, No.70, Min De Rd, Chutung, 310-48 Hsinchu, Taiwan + Hsinchu County Chutung 310148 + TW + +70-B3-D5 (hex) Leidos +E10000-E10FFF (base 16) Leidos + 7031 Albert Einstein Drive + Columbia MD 21046 + US + +70-B3-D5 (hex) Combilent +C50000-C50FFF (base 16) Combilent + Ryttermarken 5 + Farum 3520 + DK + +70-B3-D5 (hex) RCH ITALIA SPA +971000-971FFF (base 16) RCH ITALIA SPA + VIA CENDON 39 + SILEA TREVISO 31057 + IT + +70-B3-D5 (hex) IOTIZE +9CF000-9CFFFF (base 16) IOTIZE + 960 chemin de la Croix Verte + Montbonnot-Saint-Martin Isere 38330 + FR + +70-B3-D5 (hex) Contec Americas Inc. +914000-914FFF (base 16) Contec Americas Inc. + 3991 Sarno Rd + Melbourne FL 32934 + US + +70-B3-D5 (hex) Sadel S.p.A. +68B000-68BFFF (base 16) Sadel S.p.A. + via Marino Serenari, 1 + Castel Maggiore Bologna 40013 + IT + +70-B3-D5 (hex) NEXELEC +40F000-40FFFF (base 16) NEXELEC + 15 Allée FJ BROUSSAIS + VANNES 56000 + FR + +70-B3-D5 (hex) Loma Systems s.r.o. +9B8000-9B8FFF (base 16) Loma Systems s.r.o. + Southwood + Farnborough Hampshire GU14 0NY + GB + +70-B3-D5 (hex) Wartsila Voyage Limited +A05000-A05FFF (base 16) Wartsila Voyage Limited + 13-18 City Quay + Dublin 2 D02 ED70 + IE + +70-B3-D5 (hex) Wartsila Voyage Limited +ED8000-ED8FFF (base 16) Wartsila Voyage Limited + 13-18 City Quay + Dublin 2 D02 ED70 + IE + +70-B3-D5 (hex) Sakura Seiki Co.,Ltd. +082000-082FFF (base 16) Sakura Seiki Co.,Ltd. + 75-5, Imojiya + Chikuma-city Nagano Prefecture 387-0015 + JP + +70-B3-D5 (hex) Amazon Technologies Inc. +E6F000-E6FFFF (base 16) Amazon Technologies Inc. + P.O Box 8102 + Reno NV 89507 + US + +70-B3-D5 (hex) Private +11A000-11AFFF (base 16) Private + +70-B3-D5 (hex) Mettler Toledo +4FC000-4FCFFF (base 16) Mettler Toledo + 1571 Northpointe Parkway + Lutz FL 33558 + US + +70-B3-D5 (hex) Power Electronics Espana, S.L. +56E000-56EFFF (base 16) Power Electronics Espana, S.L. + C/ Leonardo Da Vinci, 24-26 + Paterna Valencia 46980 + ES + +70-B3-D5 (hex) GSP Sprachtechnologie GmbH +695000-695FFF (base 16) GSP Sprachtechnologie GmbH + Teltowkanalstraße 1 + Berlin 12247 + DE + +70-B3-D5 (hex) Clecell +565000-565FFF (base 16) Clecell + 26, Beobwon-ro 9-gil + Song-pa gu Seoul 06210 + KR + +70-B3-D5 (hex) RCH Vietnam Limited Liability Company +060000-060FFF (base 16) RCH Vietnam Limited Liability Company + Workshop F.01B-2, Lot No. F.01B Long Hau + Ho Chi Minh City Ho Chi Minh 70000 + VN + +70-B3-D5 (hex) LLC NTC ACTOR +86F000-86FFFF (base 16) LLC NTC ACTOR + Zelenograd, Sostovaya alleya, bld.6, str.22 + Moscow 124489 + RU + +70-B3-D5 (hex) Leica Microsystems Ltd. Shanghai +D30000-D30FFF (base 16) Leica Microsystems Ltd. Shanghai + 258 Jinzang Road, Building 1, Pudong + Shanghai Shanghai 201206 + CN + +70-B3-D5 (hex) Solid State Disks Ltd +F91000-F91FFF (base 16) Solid State Disks Ltd + The Granary + Reading Berkshire RG74BB + GB + +70-B3-D5 (hex) RCH Vietnam Limited Liability Company +786000-786FFF (base 16) RCH Vietnam Limited Liability Company + Workshop F.01B-2, Lot No. F.01B Long Hau + Ho Chi Minh City Ho Chi Minh 70000 + VN + +70-B3-D5 (hex) Scanvaegt Systems A/S +C10000-C10FFF (base 16) Scanvaegt Systems A/S + Scanvaegt Systems A/S, Johann Gutenbergs Vej 5-9 + Aarhus N 8200 + DK + +70-B3-D5 (hex) Toptech Systems, Inc. +E97000-E97FFF (base 16) Toptech Systems, Inc. + 1124 Florida Central Parkway + Longwood FL 32750 + US + +70-B3-D5 (hex) Acouva, Inc. +E0A000-E0AFFF (base 16) Acouva, Inc. + 2269 Chestnut St + San Francisico CA 94123 + US + +70-B3-D5 (hex) Suzhou Wansong Electric Co.,Ltd +92D000-92DFFF (base 16) Suzhou Wansong Electric Co.,Ltd + Shaxi industrial development zone + Taicang Jiangsu 215421 + CN + +70-B3-D5 (hex) Nanotok LLC +EF1000-EF1FFF (base 16) Nanotok LLC + 3075 Raccoon Point Rd + Eastsound WA 98245 + US + +70-B3-D5 (hex) MacGray Services +1D6000-1D6FFF (base 16) MacGray Services + 404 Wyman St + Waltham MA 02451 + + +70-B3-D5 (hex) Romteck Australia +394000-394FFF (base 16) Romteck Australia + 40 O’Malley Street, Osborne Park + Perth Western Australia 6017 + AU + +70-B3-D5 (hex) Romteck Australia +791000-791FFF (base 16) Romteck Australia + 40 O’Malley Street, Osborne Park + Perth Western Australia 6017 + AU + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +642000-642FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Leontech Limited +201000-201FFF (base 16) Leontech Limited + 1208 WorkingBerg Commercial Buildung, 41-47 Marble Road + Hong Kong Hong Kong 00000 + HK + +70-B3-D5 (hex) VANTAGE INTEGRATED SECURITY SOLUTIONS PVT LTD +6BE000-6BEFFF (base 16) VANTAGE INTEGRATED SECURITY SOLUTIONS PVT LTD + B3, Bredon House, 321, Tettenhall Road, Tettenhall + Wolverhampton West Midlands WV6 0JZ + GB + +70-B3-D5 (hex) Todd Digital Limited +C9A000-C9AFFF (base 16) Todd Digital Limited + Level 15, 95 Customhouse Quay + Wellington 6011 + NZ + +70-B3-D5 (hex) JENG IoT BV +5AF000-5AFFFF (base 16) JENG IoT BV + Steenbokstraat 33 + APELDOORN Gelderland 7324 AZ + NL + +70-B3-D5 (hex) TXMission Ltd. +F47000-F47FFF (base 16) TXMission Ltd. + CP House, Otterspool Way + Watford Hertfordshire WD25 8HU + GB + +70-B3-D5 (hex) Technology Link Corporation +B1B000-B1BFFF (base 16) Technology Link Corporation + Shin-Yokohama Kohoku-ku + yokohama kanagawa 222-0033 + JP + +70-B3-D5 (hex) Tucsen Photonics Co., Ltd. +8A7000-8A7FFF (base 16) Tucsen Photonics Co., Ltd. + 6F NO.1 building Caimao Zone, 756# Qi an Road, Gaishan Town, Cangshan Area, Fuzhou, Fujian, PR, CHINA. + fuzhou 350000 + CN + +70-B3-D5 (hex) sensorway +C52000-C52FFF (base 16) sensorway + A-339 samsong techno valley, 140 tongilro, deockyanggu + goyangsi gyeonggido 10594 + KR + +70-B3-D5 (hex) KDT Corp. +E72000-E72FFF (base 16) KDT Corp. + no1705-1, BLDG 3#, Lantian shixin plaza, keqiao zone + shaoxing zhejiang 312030 + CN + +70-B3-D5 (hex) Beijing Yourong Runda Rechnology Development Co.Ltd. +980000-980FFF (base 16) Beijing Yourong Runda Rechnology Development Co.Ltd. + Changping District Science and Technology Park Advanced Road 37 + Beijing 6219650 + CN + +70-B3-D5 (hex) R.C. Systems Inc +52F000-52FFFF (base 16) R.C. Systems Inc + 8621 hwy. 6 + hitchcock TX 77563 + US + +70-B3-D5 (hex) Dalcnet srl +1CF000-1CFFFF (base 16) Dalcnet srl + Via Meucci 35 + Brendola Vicenza 36040 + IT + +70-B3-D5 (hex) AUTOMATICA Y REGULACION S.A. +EBF000-EBFFFF (base 16) AUTOMATICA Y REGULACION S.A. + Condell 1735, Nunoa + Santiago RM 7770331 + CL + +70-B3-D5 (hex) Digital Solutions JSC +D9F000-D9FFFF (base 16) Digital Solutions JSC + room 4, office 1, 3rd floor, building 7, house 9a, 2nd Sinichkina Str. + Moscow 111020 + RU + +70-B3-D5 (hex) Oculii +B96000-B96FFF (base 16) Oculii + 829 Space Dr + Beavercreek OH 45434 + US + +70-B3-D5 (hex) XPS ELETRONICA LTDA +4F3000-4F3FFF (base 16) XPS ELETRONICA LTDA + AVENIDA JAÇANÃ, 470/474 - VILA NELSON + SÃO PAULO SÃO PAULO 02273-001 + BR + +70-B3-D5 (hex) Firecom, Inc. +331000-331FFF (base 16) Firecom, Inc. + 3927 59th Street + Woodside NY 11377 + US + +70-B3-D5 (hex) DOGA +62A000-62AFFF (base 16) DOGA + 11 rue Lavoisier + MAUREPAS 78310 + FR + +70-B3-D5 (hex) EVCO SPA +A80000-A80FFF (base 16) EVCO SPA + VIA FELTRE N. 81 + SEDICO BELLUNO 32036 + IT + +70-B3-D5 (hex) Forcite Helmet Systems Pty Ltd +5F8000-5F8FFF (base 16) Forcite Helmet Systems Pty Ltd + 63 Dixon Street, Haymarket, Haymarket HQ + Sydney NSW 2000 + AU + +70-B3-D5 (hex) KRISTECH Krzysztof Kajstura +66C000-66CFFF (base 16) KRISTECH Krzysztof Kajstura + Porzeczkowa 12 + Ustroń Please select region, state or province 43-450 + PL + +70-B3-D5 (hex) Songwoo Information & Technology Co., Ltd +824000-824FFF (base 16) Songwoo Information & Technology Co., Ltd + 24-9, Jinju-daero 404beon-gil, Jinju-si, Gyeongsangnam-do, Korea + Jinju Gyeongsangnam-do 52826 + KR + +70-B3-D5 (hex) Preston Industries dba PolyScience +F82000-F82FFF (base 16) Preston Industries dba PolyScience + 6600 W. Touhy Ave + Niles IL 60714-4588 + US + +70-B3-D5 (hex) Sorion Electronics ltd +26D000-26DFFF (base 16) Sorion Electronics ltd + Unit 12 Magreal ind. est + Ladywood, Birmingham West Midlands B16 0QZ + GB + +70-B3-D5 (hex) Unipower AB +A49000-A49FFF (base 16) Unipower AB + PO Box 411 + SE-441 28 Alingsas + SE + +70-B3-D5 (hex) Intelligent Security Systems (ISS) +514000-514FFF (base 16) Intelligent Security Systems (ISS) + 1480 US Highway 9 North Suite 202 + Woodbridge NJ 07095 + US + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +F94000-F94FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Boston Dynamics +292000-292FFF (base 16) Boston Dynamics + + + + +70-B3-D5 (hex) TIAMA +4BC000-4BCFFF (base 16) TIAMA + ZA des Plattes - 1 Chemin des Plattes + VOURLES 69390 + FR + +70-B3-D5 (hex) Natav Services Ltd. +E8D000-E8DFFF (base 16) Natav Services Ltd. + Binyamin 39/1 + Modiin Israel 7175260 + IL + +70-B3-D5 (hex) COTT Electronics +D23000-D23FFF (base 16) COTT Electronics + 71-75 Shelton Street + London WC2H 9JQ + GB + +70-B3-D5 (hex) VITEC +5E8000-5E8FFF (base 16) VITEC + 99 rue pierre semard + Chatillon 92320 + FR + +70-B3-D5 (hex) VITEC +05E000-05EFFF (base 16) VITEC + 99 rue pierre sémard + Chatillon France 92320 + FR + +70-B3-D5 (hex) EA Elektroautomatik GmbH & Co. KG +957000-957FFF (base 16) EA Elektroautomatik GmbH & Co. KG + Helmholtzstraße 31-33 + Viersen NRW 41747 + DE + +70-B3-D5 (hex) Beijing Yutian Technology Co., Ltd. +409000-409FFF (base 16) Beijing Yutian Technology Co., Ltd. + First floor, Jiangshan Holding Building, No.6 Academy of Agricultural Sciences West Road, Haidian District + Beijing Beijing 100097 + CN + +70-B3-D5 (hex) MARINE INSTRUMENTS, S.A. +931000-931FFF (base 16) MARINE INSTRUMENTS, S.A. + acabaleiro@marineinstruments.es + Nigran Spain 36350 + ES + +70-B3-D5 (hex) KSE GmbH +0F6000-0F6FFF (base 16) KSE GmbH + Frühlingstraße 31-33 + Ingolstadt 85055 + DE + +70-B3-D5 (hex) Edgeware AB +449000-449FFF (base 16) Edgeware AB + Master Samuelsgatan 42 + Stockholm 11157 + SE + +70-B3-D5 (hex) MRC Systems GmbH +72A000-72AFFF (base 16) MRC Systems GmbH + Hans-Bunte-Str. 10 + Heidelberg 69123 + DE + +70-B3-D5 (hex) DEUTA-WERKE GmbH +6D3000-6D3FFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach 51465 + DE + +70-B3-D5 (hex) COMPAR Computer GmbH +701000-701FFF (base 16) COMPAR Computer GmbH + Steigweg 24 + Kitzingen 97318 + DE + +70-B3-D5 (hex) Cubitech +91D000-91DFFF (base 16) Cubitech + 4-6 Kiprou str + Tavros Athens 17778 + GR + +70-B3-D5 (hex) DAVE SRL +3EA000-3EAFFF (base 16) DAVE SRL + VIA TALPONEDO 29/A + PORCIA PORDENONE 330850 + IT + +70-B3-D5 (hex) Hangzhou Leaper Technology Co. Ltd. +8BF000-8BFFFF (base 16) Hangzhou Leaper Technology Co. Ltd. + 20Th floor, Xinghui Center, 723 Dayuan Road + Hangzhou Zhejiang Province 311300 + CN + +70-B3-D5 (hex) Oxford Monitoring Solutions Ltd +102000-102FFF (base 16) Oxford Monitoring Solutions Ltd + Oakfield Estate + Eynsham Oxford OX298JG + GB + +70-B3-D5 (hex) Heim- & Bürokommunikation Ilmert e.K. +DF4000-DF4FFF (base 16) Heim- & Bürokommunikation Ilmert e.K. + Jakobsbrunnenstr. 14 + Frankfurt am Main 60386 + DE + +70-B3-D5 (hex) GeoSpectrum Technologies Inc +3CB000-3CBFFF (base 16) GeoSpectrum Technologies Inc + 10 Akerley Blvd, #19 + Dartmouth Nova Scotia B3B1J4 + CA + +70-B3-D5 (hex) Morgan Schaffer Inc. +1F7000-1F7FFF (base 16) Morgan Schaffer Inc. + 8300 rue St-Patrick bureau 150 + LaSalle Quebec H8N 2H1 + CA + +70-B3-D5 (hex) Beijing PanGu Company +E54000-E54FFF (base 16) Beijing PanGu Company + Beijing agricultural college + Beijing 100010 + CN + +70-B3-D5 (hex) Sensative AB +2C0000-2C0FFF (base 16) Sensative AB + Mobilvägen 10 + Lund 22362 + SE + +70-B3-D5 (hex) Astronomical Research Cameras, Inc. +24C000-24CFFF (base 16) Astronomical Research Cameras, Inc. + 2247 San Diego Ave #135 + San Diego CA 92110 + US + +70-B3-D5 (hex) Echogear +571000-571FFF (base 16) Echogear + 12884 Frontrunner Blvd Ste 201 + Draper UT 84020 + US + +70-B3-D5 (hex) WARECUBE,INC +463000-463FFF (base 16) WARECUBE,INC + #A-811, 142-10, Saneop-ro, 156beon-gil, Gwonseon-gu + Suwon-si 16648 + KR + +70-B3-D5 (hex) Fath Mechatronics +DC3000-DC3FFF (base 16) Fath Mechatronics + Hügelmühle 31 + Spalt bavaria 91174 + DE + +70-B3-D5 (hex) VITEC +0CA000-0CAFFF (base 16) VITEC + 99, rue Pierre Semard + CHATILLON 92320 + FR + +70-B3-D5 (hex) Eastone Century Technology Co.,Ltd. +210000-210FFF (base 16) Eastone Century Technology Co.,Ltd. + A12 Floor, Information Port, 16 Keyun Road, Tianhe DistrictGuangzhou + Guangzhou GuangDong 510000 + CN + +70-B3-D5 (hex) RCH ITALIA SPA +7FE000-7FEFFF (base 16) RCH ITALIA SPA + Via Cendon 39 + SILEA Treviso 31057 + IT + +70-B3-D5 (hex) RCH ITALIA SPA +857000-857FFF (base 16) RCH ITALIA SPA + Via Cendon 39 + SILEA Treviso 31057 + IT + +70-B3-D5 (hex) BESO sp. z o.o. +C00000-C00FFF (base 16) BESO sp. z o.o. + Mlynska 1a + Brzeg Dolny 56-120 + PL + +70-B3-D5 (hex) Automata Spa +E14000-E14FFF (base 16) Automata Spa + Via Carducci 705 + Caronno Pertusella Varese 21042 + IT + +70-B3-D5 (hex) digitrol limited +477000-477FFF (base 16) digitrol limited + CORONET WAY, ENTERPRISE PARK + SWANSEA WEST GLAMORGAN SA6 8RH + GB + +70-B3-D5 (hex) INTECH +E9D000-E9DFFF (base 16) INTECH + Vavilova st,13/7 + Moscow 117312 + RU + +70-B3-D5 (hex) GREATWALL Infotech Co., Ltd. +946000-946FFF (base 16) GREATWALL Infotech Co., Ltd. + 7F, No. 143, Sec. 3, Cheng Gong Road,, Neihu District + Taipei Taiwan 114 + TW + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +BD4000-BD4FFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) NanoSense +8ED000-8EDFFF (base 16) NanoSense + 123 rue de Bellevue, RDC + Boulogne Billancourt 92100 + FR + +70-B3-D5 (hex) Tonbo Imaging Pte Ltd +506000-506FFF (base 16) Tonbo Imaging Pte Ltd + 77 Science Park Drive,CINTECH III, Singapore Science Park I + Singapore 118256 + SG + +70-B3-D5 (hex) ABB +080000-080FFF (base 16) ABB + Fulachstrasse 150 + Schaffhausen 8200 + CH + +70-B3-D5 (hex) EYEDEA +FB9000-FB9FFF (base 16) EYEDEA + Rm.367, 3Fl., Enterprise Support Hub, 815, Daewangpangyo-ro, Sujeong-gu + Seongnam-si Gyeonggi-do 13449 + KR + +70-B3-D5 (hex) Private +30E000-30EFFF (base 16) Private + +70-B3-D5 (hex) KJ3 Elektronik AB +FB2000-FB2FFF (base 16) KJ3 Elektronik AB + Fornåsa 110 + Fornåsa 59033 + SE + +70-B3-D5 (hex) Orlaco Products B.V. +620000-620FFF (base 16) Orlaco Products B.V. + Albert Plesmanstraat 42 + Barneveld 3772MN + NL + +70-B3-D5 (hex) GSI Technology +2A6000-2A6FFF (base 16) GSI Technology + Raul Walenberg 18 + Tel Aviv IL 6971915 + IL + +70-B3-D5 (hex) Private +1D7000-1D7FFF (base 16) Private + +70-B3-D5 (hex) Orlaco Products B.V. +EAE000-EAEFFF (base 16) Orlaco Products B.V. + Albert Plesmanstraat 42 + Barneveld 3772MN + NL + +70-B3-D5 (hex) iGrid T&D +B50000-B50FFF (base 16) iGrid T&D + C. Marie Curie, 8-14 + Barcelona Catalonia 08042 + ES + +70-B3-D5 (hex) Izome +9BE000-9BEFFF (base 16) Izome + route de chaudron + Montrevault sur Evre Maine et Loire 49110 + FR + +70-B3-D5 (hex) Ethical Lighting and Sensor Solutions Limited +5B6000-5B6FFF (base 16) Ethical Lighting and Sensor Solutions Limited + Unit 5 Churchill Industrial Estate + Cheltenham Gloucestershire GL53 7EG + GB + +70-B3-D5 (hex) Divelbiss Corporation +F43000-F43FFF (base 16) Divelbiss Corporation + 9778 Mount Gilead Road + Fredericktown OH 43019 + US + +70-B3-D5 (hex) TATTILE SRL +8AA000-8AAFFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) ATION Corporation +32C000-32CFFF (base 16) ATION Corporation + 6FL, Room no.602, 14, Nonhyeon-ro 95-gil, Gangnam-gu + Seoul 06131 + KR + +70-B3-D5 (hex) MECT SRL +7C4000-7C4FFF (base 16) MECT SRL + VIA E. FERMI 57/59 + ALPIGNANO 10091 + IT + +70-B3-D5 (hex) Shenzhen Wesion Technology Co., Ltd +863000-863FFF (base 16) Shenzhen Wesion Technology Co., Ltd + A511, Mingyou Purchasing Center, Baoyuan Road, Xixiang Street + Shenzhen Guangdong 518102 + CN + +70-B3-D5 (hex) Power Electronics Espana, S.L. +AB2000-AB2FFF (base 16) Power Electronics Espana, S.L. + C/ Leonardo Da Vinci, 24-26 + Paterna Valencia 46980 + ES + +70-B3-D5 (hex) IMP-Computer Systems +354000-354FFF (base 16) IMP-Computer Systems + Volgina 15 + Belgrade 11000 + RS + +70-B3-D5 (hex) IMP-TELEKOMUNIKACIJE DOO +38D000-38DFFF (base 16) IMP-TELEKOMUNIKACIJE DOO + Volgina 15 + Belgrade 11060 + RS + +70-B3-D5 (hex) Grossenbacher Systeme AG +803000-803FFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) Qntra Technology +EA1000-EA1FFF (base 16) Qntra Technology + Velcho Atanasov 47 + Sofia Sofia 1505 + BG + +70-B3-D5 (hex) Heroic Technologies Inc. +5E7000-5E7FFF (base 16) Heroic Technologies Inc. + 200-155 East Beaver Creek Rd + Richmond Hill Ontario L4B2N1 + CA + +70-B3-D5 (hex) Grupo Epelsa S.L. +7DA000-7DAFFF (base 16) Grupo Epelsa S.L. + C/ Punto Net,3 + Alcala de Henares Madrid 28805 + ES + +70-B3-D5 (hex) ZAO ZEO +B60000-B60FFF (base 16) ZAO ZEO + Khachaturiana 14a + Moscow 127562 + RU + +70-B3-D5 (hex) Agrident GmbH +EDE000-EDEFFF (base 16) Agrident GmbH + Steinklippenstrasse 10 + Barsinghausen Low Saxonia 30890 + DE + +70-B3-D5 (hex) MondeF +1D9000-1D9FFF (base 16) MondeF + Neutronstraat 7-2 + Groningen Groningen 9743AM + NL + +70-B3-D5 (hex) Alere Technologies AS +91C000-91CFFF (base 16) Alere Technologies AS + Kjelsaasveien 161 + Oslo Oslo 0382 + NO + +70-B3-D5 (hex) BIGHOUSE.,INC. +B80000-B80FFF (base 16) BIGHOUSE.,INC. + 72-11, Pyeongchangmunwha-ro + SEOUL KOREA 03011 + KR + +70-B3-D5 (hex) LG Electronics +4F1000-4F1FFF (base 16) LG Electronics + Science Park W5, 10, Magokjungang 10-ro, Gangseo-gu + Seoul 07796 + KR + +70-B3-D5 (hex) Kniggendorf + Kögler Security GmbH +3DD000-3DDFFF (base 16) Kniggendorf + Kögler Security GmbH + Hamburger Straße 4 + Laatzen 30880 + DE + +70-B3-D5 (hex) 812th AITS +590000-590FFF (base 16) 812th AITS + 300 E Yeagar Blvd + Edwards AFB CA 93524 + US + +70-B3-D5 (hex) OOO Alyans +107000-107FFF (base 16) OOO Alyans + 9 maya, 20 + Krasnoyarsk Krasnoyarski Krai 660125 + RU + +70-B3-D5 (hex) ABB S.p.A. +5A7000-5A7FFF (base 16) ABB S.p.A. + Via Pisani 16 + Milano MI 20124 + IT + +70-B3-D5 (hex) W. H. Leary Co., Inc. +1C0000-1C0FFF (base 16) W. H. Leary Co., Inc. + 8440B West 183rd Pl + Tinley Park IL 60487 + US + +70-B3-D5 (hex) Creative Electronics Ltd +5EC000-5ECFFF (base 16) Creative Electronics Ltd + Broomwood, South Park + SEVENOAKS Kent TN131EL + GB + +70-B3-D5 (hex) Plexus +B2D000-B2DFFF (base 16) Plexus + 5511 Capital Center Drive, Ste 600 + Raleigh NC 27606 + US + +70-B3-D5 (hex) WAVES SYSTEM +CE4000-CE4FFF (base 16) WAVES SYSTEM + La Ville en Bois + BOUAYE Loire Atlantique 44830 + FR + +70-B3-D5 (hex) Ruag Defence France SAS +598000-598FFF (base 16) Ruag Defence France SAS + Chemin Jean Thomas + Terssac 81150 + FR + +70-B3-D5 (hex) SwineTech, Inc. +DC2000-DC2FFF (base 16) SwineTech, Inc. + 230 2nd Street SE, Ste 302 + Cedar Rapids IA 52401 + US + +70-B3-D5 (hex) sohonet ltd +0CF000-0CFFFF (base 16) sohonet ltd + 3-5, Soho Street + London London W1D 3DG + GB + +70-B3-D5 (hex) Scame Sistemi srl +F04000-F04FFF (base 16) Scame Sistemi srl + Via Lombardia 5 + Arluno Milan 20010 + IT + +70-B3-D5 (hex) RF Code +94B000-94BFFF (base 16) RF Code + 2600 Longhorn Blvd. ste 111 + Austin null 78758 + US + +70-B3-D5 (hex) Audiodo AB +1FF000-1FFFFF (base 16) Audiodo AB + Östra Varvsgatan 4 + Malmö 21114 + SE + +70-B3-D5 (hex) EA Elektroautomatik GmbH & Co. KG +8CD000-8CDFFF (base 16) EA Elektroautomatik GmbH & Co. KG + Helmholtzstraße 31-33 + Viersen NRW 41747 + DE + +70-B3-D5 (hex) TruTeq Wireless (Pty) Ltd +4AB000-4ABFFF (base 16) TruTeq Wireless (Pty) Ltd + Ameton House + Centurion Gauteng 0157 + ZA + +70-B3-D5 (hex) IPG Photonics Corporation +2E6000-2E6FFF (base 16) IPG Photonics Corporation + 377 Simarano Drive + Marlborough MA 01752 + US + +70-B3-D5 (hex) Open System Solutions Limited +FAB000-FABFFF (base 16) Open System Solutions Limited + Unit 33, Mitchell Point, Ensign Way + Southampton Hampshire SO31 4RF + GB + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +2DE000-2DEFFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) Centro de Ingenieria y Desarrollo industrial +73C000-73CFFF (base 16) Centro de Ingenieria y Desarrollo industrial + Av. Playa Pie de la cuesta No.702 Desarrollo san pablo + Queretaro Queretaro 76125 + MX + +70-B3-D5 (hex) Coral Telecom Limited +C8E000-C8EFFF (base 16) Coral Telecom Limited + E-2, Sector 63 + Noida Uttar Pradesh 201301 + IN + +70-B3-D5 (hex) Smashtag Ltd +F6F000-F6FFFF (base 16) Smashtag Ltd + Unit B6 Beech House, Melbourn Science Park + Royston Hertfordshire SG8 6HB + GB + +70-B3-D5 (hex) David Horn Communications Ltd +ABB000-ABBFFF (base 16) David Horn Communications Ltd + Enterprise way,, Bramingham Business park + Luton Bedfordshire LU3 4BU + GB + +70-B3-D5 (hex) CRDMDEVEOPPEMENTS +B5F000-B5FFFF (base 16) CRDMDEVEOPPEMENTS + 13 Petit chemin de la generale + Villenave d'Ornon Gironde 33140 + FR + +70-B3-D5 (hex) Tecnint HTE SRL +ACA000-ACAFFF (base 16) Tecnint HTE SRL + Via della Tecnica 16/18 + Osnago Lecco 23875 + IT + +70-B3-D5 (hex) Ascenix Corporation +3A4000-3A4FFF (base 16) Ascenix Corporation + 1120 Benfield Blvd. STE A + Millersville MD 21108 + US + +70-B3-D5 (hex) NAJIN automation +6CB000-6CBFFF (base 16) NAJIN automation + 7F Rm.144, Hyoryeong-Ro 304 + Seocho-Gu Seoul 06720 + KR + +70-B3-D5 (hex) Camsat Przemysław Gralak +FE9000-FE9FFF (base 16) Camsat Przemysław Gralak + Ogrodowa 2A + Solec Kujawski 86-050 + PL + +70-B3-D5 (hex) TAALEX Systemtechnik GmbH +553000-553FFF (base 16) TAALEX Systemtechnik GmbH + Schubertstrasse 27 + Stadtlohn NRW 48703 + DE + +70-B3-D5 (hex) Foerster-Technik GmbH +9F7000-9F7FFF (base 16) Foerster-Technik GmbH + Gerwigstraße 25 + Engen Baden-Württemberg 78234 + DE + +70-B3-D5 (hex) wallbe GmbH +543000-543FFF (base 16) wallbe GmbH + Paderborner Straße 76 + Schlangen NRW 33189 + DE + +70-B3-D5 (hex) Cardinal Scales Manufacturing Co +30F000-30FFFF (base 16) Cardinal Scales Manufacturing Co + 203 East Daugherty Street + Webb City MO 64870 + US + +70-B3-D5 (hex) Vision4ce Ltd +D01000-D01FFF (base 16) Vision4ce Ltd + Unit 4, Wokingham Commercial Centre + Wokingham Berkshire RG41 2RF + GB + +70-B3-D5 (hex) Virtual Control Systems Ltd +EC3000-EC3FFF (base 16) Virtual Control Systems Ltd + 27 Main Street, Overton + Morecambe Lancashire LA3 3HF + GB + +70-B3-D5 (hex) SOREL GmbH Mikroelektronik +A84000-A84FFF (base 16) SOREL GmbH Mikroelektronik + REME-Str. 12 + Wetter 58300 + DE + +70-B3-D5 (hex) Energy Wall +990000-990FFF (base 16) Energy Wall + 1002 New Holland Ave + Lancaster PA 17601 + US + +70-B3-D5 (hex) Potter Electric Signal Co. LLC +B9A000-B9AFFF (base 16) Potter Electric Signal Co. LLC + 1609 Park 370 Place + Hazelwood MO 63042 + US + +70-B3-D5 (hex) CAPTEMP, Lda +49E000-49EFFF (base 16) CAPTEMP, Lda + Rua São João, s/n - Ladeira das Leais + Pombal 3100-346 + PT + +70-B3-D5 (hex) DogWatch Inc +302000-302FFF (base 16) DogWatch Inc + 10 Michigan Drive + Natick MA 01760 + US + +70-B3-D5 (hex) PSL ELEKTRONİK SANAYİ VE TİCARET A.S. +510000-510FFF (base 16) PSL ELEKTRONİK SANAYİ VE TİCARET A.S. + Antalya OSB 3. Kısım 25. Cadde No:30 + ANTALYA 07190 + TR + +70-B3-D5 (hex) eze System, Inc. +2F5000-2F5FFF (base 16) eze System, Inc. + 785 Orchard Dr #100 + Folsom CA 95630 + US + +70-B3-D5 (hex) Shengli Financial Software Development +F22000-F22FFF (base 16) Shengli Financial Software Development + 3766 Nanhuan Road, Binjiang + Hangzhou 310051 + CN + +70-B3-D5 (hex) Gogo BA +1E8000-1E8FFF (base 16) Gogo BA + 105 Edgeview Drive + Broomfield CO 80021 + US + +70-B3-D5 (hex) Mighty Cube Co., Ltd. +403000-403FFF (base 16) Mighty Cube Co., Ltd. + UNIZO Nihonbashihoncho 3-CHome Building 5F 3-8-4 Nihonbashi-honcho + Chuo-ku TOKYO 103-0023 + JP + +70-B3-D5 (hex) Software Systems Plus +7DC000-7DCFFF (base 16) Software Systems Plus + 9924 N. Ash Avenue + Kansas City null 64157 + US + +70-B3-D5 (hex) Digital Way +437000-437FFF (base 16) Digital Way + 1 Chemin des CHAUX + Saint-Etienne Loire 42000 + FR + +70-B3-D5 (hex) IoT Routers Limited +F51000-F51FFF (base 16) IoT Routers Limited + The Barn, 22 Brackendale + Bradford West Yorkshire BD10 0SJ + GB + +70-B3-D5 (hex) LSC Lighting Systems (Aust) Pty Ltd +CC2000-CC2FFF (base 16) LSC Lighting Systems (Aust) Pty Ltd + 65-67 Discovery Road + Dandenong South Victoria 3175 + AU + +70-B3-D5 (hex) APG Cash Drawer, LLC +C9D000-C9DFFF (base 16) APG Cash Drawer, LLC + 5250 Industrial Blvd NE + Minneapolis MN 55421 + US + +70-B3-D5 (hex) EIDOS s.r.l. +890000-890FFF (base 16) EIDOS s.r.l. + via dell'Industria, 11 Z.I. Fontaneto + CHIERI Turin 10023 + IT + +70-B3-D5 (hex) Ahrens & Birner Company GmbH +6D2000-6D2FFF (base 16) Ahrens & Birner Company GmbH + Virchowstreet 19/19a + Nuremberg 90409 + DE + +70-B3-D5 (hex) Daatrics LTD +A5F000-A5FFFF (base 16) Daatrics LTD + 4th Floor, 86-90 Paul Street + LONDON EC2A 4NE + GB + +70-B3-D5 (hex) BRS Sistemas Eletrônicos +F16000-F16FFF (base 16) BRS Sistemas Eletrônicos + Rua Gomes de Freitas, 491 / 204 + Porto Alegre RS 91380-000 + BR + +70-B3-D5 (hex) Boffins Technologies AB +E5D000-E5DFFF (base 16) Boffins Technologies AB + Russgatan 5 + Malmö 212 35 + SE + +70-B3-D5 (hex) Liaoyun Information Technology Co., Ltd. +40E000-40EFFF (base 16) Liaoyun Information Technology Co., Ltd. + Floor 5, Building 8, No. 690 Bibo Road + Shanghai 201203 + CN + +70-B3-D5 (hex) BT9 +6B8000-6B8FFF (base 16) BT9 + Dolev 33 + Tefen 2495900 + IL + +70-B3-D5 (hex) biosilver .co.,ltd +43F000-43FFFF (base 16) biosilver .co.,ltd + 2-14-4, shinyokohama + yokohama kanagawa 2220033 + JP + +70-B3-D5 (hex) Hongin., Ltd +355000-355FFF (base 16) Hongin., Ltd + 160, Daehwa-ro, Daedeok-gu + Daejeon Republic of Korea 34368 + KR + +70-B3-D5 (hex) Centum Adetel Group +FD7000-FD7FFF (base 16) Centum Adetel Group + 4 Chemin du ruisseau + Ecully 69130 + FR + +70-B3-D5 (hex) CRUXELL Corp. +518000-518FFF (base 16) CRUXELL Corp. + A-405 Migun techno world II,187 techno 2-ro, Yusong-gu + Daejeon Daejeon 34025 + KR + +70-B3-D5 (hex) Shenzhen Hui Rui Tianyan Technology Co., Ltd. +FA5000-FA5FFF (base 16) Shenzhen Hui Rui Tianyan Technology Co., Ltd. + 7th Floor, Yuemei Building, Gaoxin South Road, Nanshan District + Shenzhen Guangdong 518000 + CN + +70-B3-D5 (hex) AEV Broadcast Srl +0EA000-0EAFFF (base 16) AEV Broadcast Srl + Via Della Tecnica, 33 + Argelato BO - VAT IT03167451206 40050 + IT + +70-B3-D5 (hex) Veo Technologies +A9C000-A9CFFF (base 16) Veo Technologies + Skyttegade 7, 3. tv + Copenhagen Denmark 2200 + DK + +70-B3-D5 (hex) BLUE-SOLUTIONS CANADA INC. +EE7000-EE7FFF (base 16) BLUE-SOLUTIONS CANADA INC. + 1560 RUE DE COULOMB + BOUCHERVILLE QUEBEC J4B 7Z7 + CA + +70-B3-D5 (hex) Vocality international T/A Cubic +4EA000-4EAFFF (base 16) Vocality international T/A Cubic + Lydling Barn,Lydling Farm,, Puttenham Lane + Godalming Surrey gu8 6ap + GB + +70-B3-D5 (hex) CDR SRL +F58000-F58FFF (base 16) CDR SRL + VIA DEGLI ARTIGIANI 6 + GINESTRA FIORENTINA FLORENCE 50055 + IT + +70-B3-D5 (hex) SilTerra Malaysia Sdn. Bhd. +31B000-31BFFF (base 16) SilTerra Malaysia Sdn. Bhd. + Lot 8, Phase II, Kulim Hi-Tech Park + KULIM KEDAH 09000 + MY + +70-B3-D5 (hex) Dr. Zinngrebe GmbH +42E000-42EFFF (base 16) Dr. Zinngrebe GmbH + Schillerstraße 1/15 + Ulm Baden-Württemberg 89077 + DE + +70-B3-D5 (hex) Lumiplan Duhamel +E94000-E94FFF (base 16) Lumiplan Duhamel + 2 rue de l'industrie + Domène Isère 38420 + FR + +70-B3-D5 (hex) Newshine +A64000-A64FFF (base 16) Newshine + Pingcheng Rd + Shanghai Shanghai 201800 + CN + +70-B3-D5 (hex) OS42 UG (haftungsbeschraenkt) +9D1000-9D1FFF (base 16) OS42 UG (haftungsbeschraenkt) + Wachtelstrasse 81 + Hamburg 22305 + DE + +70-B3-D5 (hex) csintech +DB6000-DB6FFF (base 16) csintech + 234, Oksan-ro + Bucheon-si Gyeonggi-do 14521 + KR + +70-B3-D5 (hex) Aldridge Electrical Industries +848000-848FFF (base 16) Aldridge Electrical Industries + 10-16 Sir Joseph Banks Drive + Sydney NSW 2231 + AU + +70-B3-D5 (hex) alfamation spa +675000-675FFF (base 16) alfamation spa + via cadore 21 + lissone mb 20851 + IT + +70-B3-D5 (hex) Incusense +7F5000-7F5FFF (base 16) Incusense + 424 NE 4th st + McMinnville OR 97128 + US + +70-B3-D5 (hex) Onosokki Co.,Ltd +8C6000-8C6FFF (base 16) Onosokki Co.,Ltd + 3-9-3 shinyokohama,kohoku + yokohama 222-8507 + JP + +70-B3-D5 (hex) LEGENDAIRE TECHNOLOGY CO., LTD. +02F000-02FFFF (base 16) LEGENDAIRE TECHNOLOGY CO., LTD. + 2F,No.278,Fu Shun Rd. + Taichung City 40764 + TW + +70-B3-D5 (hex) Lexi Devices, Inc. +AC4000-AC4FFF (base 16) Lexi Devices, Inc. + 2342 Shattuck Ave, #260 + Berkeley 94704 + US + +70-B3-D5 (hex) Fidalia Networks Inc +CC3000-CC3FFF (base 16) Fidalia Networks Inc + 1 Port Street East + Mississauga Ontario L5G4N1 + CA + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +5F9000-5F9FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Dia-Stron Limited +EA8000-EA8FFF (base 16) Dia-Stron Limited + Unit 9 Focus Way + Andover Hampshire SP10 5NY + GB + +70-B3-D5 (hex) wallbe GmbH +07B000-07BFFF (base 16) wallbe GmbH + Paderborner Straße 76 + Schlangen NRW 33189 + DE + +70-B3-D5 (hex) Hanwell Technology Co., Ltd. +32D000-32DFFF (base 16) Hanwell Technology Co., Ltd. + 3F., No. 41, Dongxing Rd., Xinyi District. + Taipei 11070 + TW + +70-B3-D5 (hex) Amfitech ApS +123000-123FFF (base 16) Amfitech ApS + Platzvej 2 + Vejle Syddanmark 7100 + DK + +70-B3-D5 (hex) Procon Electronics Pty Ltd +8EB000-8EBFFF (base 16) Procon Electronics Pty Ltd + P O Box 164 + Seven Hills NSW 1730 + AU + +70-B3-D5 (hex) TASK SISTEMAS DE COMPUTACAO LTDA +961000-961FFF (base 16) TASK SISTEMAS DE COMPUTACAO LTDA + Rua 2 / 112 Jardim Itatiaia + Itatiaia Rio de Janeiro 27580-000 + BR + +70-B3-D5 (hex) AooGee Controls Co., LTD. +1CC000-1CCFFF (base 16) AooGee Controls Co., LTD. + Siming District office building 14, Fu Lian + Xiamen Fujian 361000 + CN + +70-B3-D5 (hex) FRAKO Kondensatoren und Anlagenbau GmbH +014000-014FFF (base 16) FRAKO Kondensatoren und Anlagenbau GmbH + Tscheulinstr. 21a + Teningen 79331 + DE + +70-B3-D5 (hex) Akse srl +09A000-09AFFF (base 16) Akse srl + Via Aldo Moro, 39 + Reggio Emilia Italy 42124 + IT + +70-B3-D5 (hex) LINEAGE POWER PVT LTD., +0C9000-0C9FFF (base 16) LINEAGE POWER PVT LTD., + 30-A1, KIADB, 1ST PHASE INDUSTRIAL ESTATE,KUMBALGODU, BANGALORE-MYSORE ROAD + BANGALORE KARNATAKA 560074 + IN + +70-B3-D5 (hex) INTERNET PROTOCOLO LOGICA SL +B0B000-B0BFFF (base 16) INTERNET PROTOCOLO LOGICA SL + Sector Foresta 43, local 26 + Tres Cantos Madrid 28760 + ES + +70-B3-D5 (hex) Ellenex Pty Ltd +CD0000-CD0FFF (base 16) Ellenex Pty Ltd + 91 Tope Street + South Melbourne VIC 3205 + AU + +70-B3-D5 (hex) Blue Access Inc +C66000-C66FFF (base 16) Blue Access Inc + P.O. Box + Erie CO 80516 + US + +70-B3-D5 (hex) provedo +A54000-A54FFF (base 16) provedo + Friedrich-Ebert-Straße, 63 + Leipzig 04109 + DE + +70-B3-D5 (hex) Okolab Srl +BF9000-BF9FFF (base 16) Okolab Srl + Via G. di Prisco n. 152 + Ottaviano NA 80044 + IT + +70-B3-D5 (hex) TEX COMPUTER SRL +5FA000-5FAFFF (base 16) TEX COMPUTER SRL + VIA MERCADANTE 35 + CATTOLICA RIMINI 47841 + IT + +70-B3-D5 (hex) EN ElectronicNetwork Hamburg GmbH +015000-015FFF (base 16) EN ElectronicNetwork Hamburg GmbH + Meiendorfer Strasse 205 + Hamburg 22145 + DE + +70-B3-D5 (hex) Convergent Design +1F8000-1F8FFF (base 16) Convergent Design + 4525 Northpark Drive + Colorado Springs CO 80918 + US + +70-B3-D5 (hex) FRS GmbH & Co. KG +F8A000-F8AFFF (base 16) FRS GmbH & Co. KG + Weingartenstr. 1-3 + Dortmund NW 44263 + DE + +70-B3-D5 (hex) MSB Elektronik und Gerätebau GmbH +E9E000-E9EFFF (base 16) MSB Elektronik und Gerätebau GmbH + Hofwiesenstr. 23 + Crailsheim 74564 + DE + +70-B3-D5 (hex) Potter Electric Signal Co. LLC +1BE000-1BEFFF (base 16) Potter Electric Signal Co. LLC + 1609 Park 370 Place + Hazelwood MO 63042 + US + +70-B3-D5 (hex) DiTEST Fahrzeugdiagnose GmbH +109000-109FFF (base 16) DiTEST Fahrzeugdiagnose GmbH + ALTE POSTSTRASSE 152 + A-8020 GRAZ STEIERMARK + AT + +70-B3-D5 (hex) Merlin CSI +C41000-C41FFF (base 16) Merlin CSI + 10755 Scripps Poway Pkwy # 524 + San Diego CA 92131 + US + +70-B3-D5 (hex) CHRONOMEDIA +21F000-21FFFF (base 16) CHRONOMEDIA + #508, 1130, Beoman-ro, Geumcheon-gu + Seoul 08595 + KR + +70-B3-D5 (hex) SHANGHAI IRISIAN OPTRONICS TECHNOLOGY CO.,LTD. +2D2000-2D2FFF (base 16) SHANGHAI IRISIAN OPTRONICS TECHNOLOGY CO.,LTD. + 8F, NO.800, Huanhu NO.2 Road (W), Pudong New District, Shanghai 201306, China + Shanghai Shanghai 201306 + CN + +70-B3-D5 (hex) Naval Group +382000-382FFF (base 16) Naval Group + 40-42 Rue Du Docteur Finlay + PARIS CEDEX 15 75732 + FR + +70-B3-D5 (hex) EIFFAGE ENERGIE ELECTRONIQUE +037000-037FFF (base 16) EIFFAGE ENERGIE ELECTRONIQUE + D937 + VERQUIN 62131 + FR + +70-B3-D5 (hex) Telefrank GmbH +A82000-A82FFF (base 16) Telefrank GmbH + Am Wildengrund 1 + Altenambach TH 98553 + DE + +70-B3-D5 (hex) Orange Tree Technologies Ltd +EF4000-EF4FFF (base 16) Orange Tree Technologies Ltd + 173 Curie Avenue, Harwell Oxford + Didcot Oxfordshire OX11 0QG + GB + +70-B3-D5 (hex) Yukilab +7D6000-7D6FFF (base 16) Yukilab + 1-7-3 Sekiya-Matsunami, Chuo + Niigata Niigata 951-8161 + JP + +70-B3-D5 (hex) SYS TEC electronic GmbH +BAF000-BAFFFF (base 16) SYS TEC electronic GmbH + Am Windrad 2 + Heinsdorfergrund D-08468 + DE + +70-B3-D5 (hex) Technica Engineering GmbH +4C0000-4C0FFF (base 16) Technica Engineering GmbH + Leopoldstraße 236 + Munich 80807 + DE + +70-B3-D5 (hex) SiFive +92F000-92FFFF (base 16) SiFive + 1875 S Grant St + San Mateo CA 94403 + US + +70-B3-D5 (hex) KnowRoaming +D6A000-D6AFFF (base 16) KnowRoaming + 90 Eglinton Ave. E + Toronto Ontario - ON M4P2Y3 + CA + +70-B3-D5 (hex) Pietro Fiorentini +A76000-A76FFF (base 16) Pietro Fiorentini + Via Enrico Fermi + Arcugnano 36057 + IT + +70-B3-D5 (hex) Private +720000-720FFF (base 16) Private + +70-B3-D5 (hex) OnYield Inc Ltd +B74000-B74FFF (base 16) OnYield Inc Ltd + 814 Houston Centre, 63 Mody Road + Kowloon TST East + HK + +70-B3-D5 (hex) Hangzhou Woosiyuan Communication Co.,Ltd. +1F4000-1F4FFF (base 16) Hangzhou Woosiyuan Communication Co.,Ltd. + 13 Dongyuexincun Xihu district + Hangzhou Zhejiang 310023 + CN + +70-B3-D5 (hex) ZAO ZEO +B43000-B43FFF (base 16) ZAO ZEO + Khachaturiana 14a + Moscow 127562 + RU + +70-B3-D5 (hex) Roxford +651000-651FFF (base 16) Roxford + PO Box 231851 + Encinitas CA 92023-1851 + US + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +8D9000-8D9FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Granite River Labs Inc +749000-749FFF (base 16) Granite River Labs Inc + 3500 Thomas Rd # A, + Santa Clara 95054 + US + +70-B3-D5 (hex) OÜ ELIKO Tehnoloogia Arenduskeskus +D4A000-D4AFFF (base 16) OÜ ELIKO Tehnoloogia Arenduskeskus + Mäealuse 2/1 + Tallinn Harju 12618 + EE + +70-B3-D5 (hex) Shandong Hospot IOT Technology Co.,Ltd. +576000-576FFF (base 16) Shandong Hospot IOT Technology Co.,Ltd. + No.96 Road Fuyang + Rizhao Shandong 276800 + CN + +70-B3-D5 (hex) Yaham Optoelectronics Co., Ltd +2FE000-2FEFFF (base 16) Yaham Optoelectronics Co., Ltd + Bldg A & Bldg D, Yongwei Industrial Park,#118 Yongfu Rd, Qiaotou Community, Fuyong,Bao'an District,Shenzhen + Shenzhen Bao'an District/GuangDong 518103 + CN + +70-B3-D5 (hex) FlowNet LLC +526000-526FFF (base 16) FlowNet LLC + 580 Lake Ave + Lancaster NY 14086 + US + +70-B3-D5 (hex) HZHY TECHNOLOGY +4A6000-4A6FFF (base 16) HZHY TECHNOLOGY + The 2th floor,Longzeyuan Multi-use + beijing 102208 + CN + +70-B3-D5 (hex) D.E.M. SPA +C1C000-C1CFFF (base 16) D.E.M. SPA + Z.I. VILLANOVA 20 + Longarone (BL) 32013 + IT + +70-B3-D5 (hex) Globalcom Engineering SPA +A0D000-A0DFFF (base 16) Globalcom Engineering SPA + Via Volta 39 + CARDANO AL CAMPO VA 21010 + IT + +70-B3-D5 (hex) FOSHAN VOHOM +2BF000-2BFFFF (base 16) FOSHAN VOHOM + Unit 402, 4/F ENT A3 Bldg, Hantian Science and Technology City, No. 17 Shenhai RD. + Foshan Guangdong 528200 + CN + +70-B3-D5 (hex) Hills Health Solutions +78A000-78AFFF (base 16) Hills Health Solutions + Unit 1, Builing F, 3-29 Birnie Ave + Lidcombe New South Wales 2141 + AU + +70-B3-D5 (hex) Triax A/S +941000-941FFF (base 16) Triax A/S + Bjornkaervej 3 + Hornsyld Denmark 8783 + DK + +70-B3-D5 (hex) Metrum Sweden AB +F98000-F98FFF (base 16) Metrum Sweden AB + Anders Personsgatan 16 + Goteborg 41664 + SE + +70-B3-D5 (hex) Quantum Opus, LLC +602000-602FFF (base 16) Quantum Opus, LLC + 45211 Helm St + Plymouth MI 48170 + US + +70-B3-D5 (hex) MatchX GmbH +1CB000-1CBFFF (base 16) MatchX GmbH + Adalbert Str.8 + Berlin 10999 + DE + +70-B3-D5 (hex) Avant Technologies, Inc +410000-410FFF (base 16) Avant Technologies, Inc + Road 156 Caguas West Ind. Park bldg 39 + Caguas PR 00726 + US + +70-B3-D5 (hex) SHINWA INDUSTRIES, INC. +F87000-F87FFF (base 16) SHINWA INDUSTRIES, INC. + Daisan Nishi-Aoyama Bldg. 6F 1-8-1 Shibuya + Shibuya-ku Tokyo 150-0002 + JP + +70-B3-D5 (hex) HEITEC AG +228000-228FFF (base 16) HEITEC AG + Dr.-Otto-Leich-Str. 16 + Eckental Bavaria 90542 + DE + +70-B3-D5 (hex) Divigraph (Pty) LTD +A86000-A86FFF (base 16) Divigraph (Pty) LTD + Postnet Suite 72, Private Bag X7 + Chempet 7442 + ZA + +70-B3-D5 (hex) Impulse Automation +7A3000-7A3FFF (base 16) Impulse Automation + Obuhovskoy Oborony 120-B + Saint Petersburg Saint Petersburg 192012 + RU + +70-B3-D5 (hex) MonsoonRF, Inc. +0F3000-0F3FFF (base 16) MonsoonRF, Inc. + 7740 Garvey Ave, Unit D + Rosemead CA 91770 + US + +70-B3-D5 (hex) Planewave Instruments +CB4000-CB4FFF (base 16) Planewave Instruments + 1819 Kona Dr. + Compton CA 90220 + US + +70-B3-D5 (hex) NESA SRL +BFA000-BFAFFF (base 16) NESA SRL + Via Sartori, 6/8 + Vidor Treviso 31020 + IT + +70-B3-D5 (hex) ONDEMAND LABORATORY Co., Ltd. +069000-069FFF (base 16) ONDEMAND LABORATORY Co., Ltd. + Daiba 449 Space 369 Building 2F + Mishima Shizuoka 411-0803 + JP + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +08A000-08AFFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Particle sizing systems +670000-670FFF (base 16) Particle sizing systems + 8203 Kristel Cir + New Port Richey FL 34652 + US + +70-B3-D5 (hex) FLUDIA +4A0000-4A0FFF (base 16) FLUDIA + 4T rue honoré d'estienne d'orves + Suresnes 92150 + FR + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +E86000-E86FFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) RELISTE Ges.m.b.H. +1B9000-1B9FFF (base 16) RELISTE Ges.m.b.H. + Enzersdorfer Strasse 8-10 + Brunn am Gebirge 2345 + AT + +70-B3-D5 (hex) Hagenuk KMT Kabelmesstechnik GmbH +132000-132FFF (base 16) Hagenuk KMT Kabelmesstechnik GmbH + Röderaue 41 + Radeburg Sachsen 01471 + DE + +70-B3-D5 (hex) Jiangsu Jinheng Information Technology Co.,Ltd. +492000-492FFF (base 16) Jiangsu Jinheng Information Technology Co.,Ltd. + LuHe District,XieJiaDian,Ninggang Road No.81 + Nanjing Jiangsu 210035 + CN + +70-B3-D5 (hex) MAMAC Systems, Inc. +BA2000-BA2FFF (base 16) MAMAC Systems, Inc. + 8189 Century Blvd. + Chanhassen null 55317-8002 + US + +70-B3-D5 (hex) Ofil USA +9E2000-9E2FFF (base 16) Ofil USA + 5415 Sugarloaf Parkway Suite 1102 A&B + Lawrenceville GA 30043 + US + +70-B3-D5 (hex) iTelaSoft Pvt Ltd +6F0000-6F0FFF (base 16) iTelaSoft Pvt Ltd + No. 02, Balapokuna Road + Colombo 06 00600 + LK + +70-B3-D5 (hex) CE LINK LIMITED +547000-547FFF (base 16) CE LINK LIMITED + 2/F, Building G, Licheng Tech. Ind. Zone + Shenzhen Guangdong 518104 + CN + +70-B3-D5 (hex) Integritech +BB4000-BB4FFF (base 16) Integritech + 6434 E. Main Street, Unit 103 + Reynoldsburg OH 43068 + US + +70-B3-D5 (hex) I.E. Sevko A.V. +8F7000-8F7FFF (base 16) I.E. Sevko A.V. + 7-1-97, Polyarnaya st. + Moscow 127081 + RU + +70-B3-D5 (hex) Systems Engineering Arts Pty Ltd +3CF000-3CFFFF (base 16) Systems Engineering Arts Pty Ltd + 56 Benbow St + Yarraville Vic 3013 + AU + +70-B3-D5 (hex) Embedded Arts Co., Ltd. +0C6000-0C6FFF (base 16) Embedded Arts Co., Ltd. + 1-1-6 Ryousoutuuun Bldg. 2F + Kisarazu-shi Chiba 292-0067 + JP + +70-B3-D5 (hex) DAVE SRL +EF7000-EF7FFF (base 16) DAVE SRL + VIA TALPONEDO 29/A + PORCIA PORDENONE 330850 + IT + +70-B3-D5 (hex) Movicom LLC +5DB000-5DBFFF (base 16) Movicom LLC + Nauchny proezd, 20 + Moscow 117246 + RU + +70-B3-D5 (hex) Toughdog Security Systems +A32000-A32FFF (base 16) Toughdog Security Systems + 1317 E Hackberry Ave + McAllen TX 78501 + US + +70-B3-D5 (hex) Stanet Co.,Ltd +841000-841FFF (base 16) Stanet Co.,Ltd + 6F., No.67, Guangfu S. Rd. + Taipei 105 + TW + +70-B3-D5 (hex) FreeFlight Systems +5F6000-5F6FFF (base 16) FreeFlight Systems + 8150 Springwood Drive, Suite 100 + Irving TX 75063 + US + +70-B3-D5 (hex) APG Cash Drawer, LLC +BB3000-BB3FFF (base 16) APG Cash Drawer, LLC + 5250 Industrial Blvd NE + Minneapolis MN 55421 + US + +70-B3-D5 (hex) Silixa Ltd +FAE000-FAEFFF (base 16) Silixa Ltd + 230 Centennial Park + Elstree Hertfordshire WD6 3SN + GB + +70-B3-D5 (hex) ENTEC Electric & Electronic CO., LTD +07E000-07EFFF (base 16) ENTEC Electric & Electronic CO., LTD + 78-2 Buncheon-ri + Hwaseong-city Gyungki-do 445-894 + KR + +70-B3-D5 (hex) Turbo Technologies Corporation +3AF000-3AFFFF (base 16) Turbo Technologies Corporation + Rm701,Building C2,Land of Innovation City of Future,No.999.Gaoxin Avenue,East Lake Hi-Tech Zone + Wuhan Hubei 430075 + CN + +70-B3-D5 (hex) Ensys srl +BBF000-BBFFFF (base 16) Ensys srl + Via Zamenhof, 817 + Vicenza Vicenza 36100 + IT + +70-B3-D5 (hex) EFG CZ spol. s r.o. +897000-897FFF (base 16) EFG CZ spol. s r.o. + Na Jarově 4 + Praha 3 Czech republic 13000 + CZ + +70-B3-D5 (hex) Husty M.Styczen J.Hupert Sp.J. +086000-086FFF (base 16) Husty M.Styczen J.Hupert Sp.J. + Rzepakowa 5e + Krakow malopolska 31-989 + PL + +70-B3-D5 (hex) Controlrad +CD3000-CD3FFF (base 16) Controlrad + 20(49), HaTaas st, + Kfar-Saba, Israel 4442520 + IL + +70-B3-D5 (hex) Globalcom Engineering SPA +284000-284FFF (base 16) Globalcom Engineering SPA + Via Volta 39 + CARDANO AL CAMPO VA 21010 + IT + +70-B3-D5 (hex) Javasparrow Inc. +991000-991FFF (base 16) Javasparrow Inc. + 303,1-31-17,Koudou + Adachi Tokyo 120013 + JP + +70-B3-D5 (hex) KM OptoElektronik GmbH +9D7000-9D7FFF (base 16) KM OptoElektronik GmbH + Mollenbachstraße 14 + Leonberg Württemberg 71229 + DE + +70-B3-D5 (hex) viZaar industrial imaging AG +4E5000-4E5FFF (base 16) viZaar industrial imaging AG + Hechinger Strasse 152 + Albstadt Baden-Württemberg 72461 + DE + +70-B3-D5 (hex) ic-automation GmbH +D44000-D44FFF (base 16) ic-automation GmbH + Alexander-Diehl-Straße, 2A + Mainz Deutschland 55130 + DE + +70-B3-D5 (hex) WOOJIN Inc +203000-203FFF (base 16) WOOJIN Inc + Gyeonggi + Hwaseong Dongbu-daero 970beon-gil 110 18481 + KR + +70-B3-D5 (hex) Neoptix Inc. +EC7000-EC7FFF (base 16) Neoptix Inc. + 1415 Frank-Carrel + Quebec G1N4N7 + CA + +70-B3-D5 (hex) Newtouch Electronics (Shanghai) Co.,Ltd. +DFA000-DFAFFF (base 16) Newtouch Electronics (Shanghai) Co.,Ltd. + No.418, 4F, Building 1, Lujiazui Software Park No.98, Lane 91, E Shan Rd + ShangHai 200127 + CN + +70-B3-D5 (hex) Tecnint HTE SRL +809000-809FFF (base 16) Tecnint HTE SRL + Via della Tecnica 16/18 + Osnago Lecco 23875 + IT + +70-B3-D5 (hex) Virtuosys Ltd +BEA000-BEAFFF (base 16) Virtuosys Ltd + The Tramshed Offices, Beehive Yard + Bath Somerset BA1 5BB + GB + +70-B3-D5 (hex) WeVo Tech +273000-273FFF (base 16) WeVo Tech + 2985 Drew Road + Mississauga Ontario L4T0A4 + CA + +70-B3-D5 (hex) Sicon srl +A35000-A35FFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) AML +6E7000-6E7FFF (base 16) AML + 2190 Regal Parkway + Euless TX 76040 + US + +70-B3-D5 (hex) Kranze Technology Solutions +C1D000-C1DFFF (base 16) Kranze Technology Solutions + 742 Pinecrest Dr + Prospect Heights IL 60070 + US + +70-B3-D5 (hex) LYNX Technik AG +5D8000-5D8FFF (base 16) LYNX Technik AG + Brunnenweg 3 + Weiterstadt Hessen 64331 + DE + +70-B3-D5 (hex) Risk Expert sarl +34E000-34EFFF (base 16) Risk Expert sarl + 63, Rue de Hollerich + Luxembourg 1741 + LU + +70-B3-D5 (hex) Kazan Networks Corporation +768000-768FFF (base 16) Kazan Networks Corporation + 660 Auburn Folsom Rd, Suite 204 + Auburn CA 95722 + US + +70-B3-D5 (hex) TELEPLATFORMS +5FB000-5FBFFF (base 16) TELEPLATFORMS + Polbina st., 3/1 + Moscow 109388 + RU + +70-B3-D5 (hex) SENSO2ME +631000-631FFF (base 16) SENSO2ME + Zandhoef 16 + KASTERLEE België 2460 + BE + +70-B3-D5 (hex) T+A elektroakustik GmbH & Co.KG +69F000-69FFFF (base 16) T+A elektroakustik GmbH & Co.KG + Planckstr. 9-11 + Herford 32052 + DE + +70-B3-D5 (hex) NIPPON SEIKI CO., LTD. +18E000-18EFFF (base 16) NIPPON SEIKI CO., LTD. + 2-8 Higashi-Takami 2-Chome + NAGAOKA NIIGATA 940-0006 + JP + +70-B3-D5 (hex) SEASON DESIGN TECHNOLOGY +AF0000-AF0FFF (base 16) SEASON DESIGN TECHNOLOGY + FLOOR 4, WARDS EXCHANGE, 199 ECCLESALL ROAD + SHEFFIELD SOUTH YORKSHIRE S11 8HW + GB + +70-B3-D5 (hex) Advanced Devices SpA +445000-445FFF (base 16) Advanced Devices SpA + via Spagna 240-242 + Rende Cosenza 87036 + IT + +70-B3-D5 (hex) SPEECH TECHNOLOGY CENTER LIMITED +74D000-74DFFF (base 16) SPEECH TECHNOLOGY CENTER LIMITED + 4 Krasutskogo str. + Saint Petersburg 196084 + RU + +70-B3-D5 (hex) Iradimed +E57000-E57FFF (base 16) Iradimed + 1025 Willa Springs Dr. + Winter Springs FL 32708-____ + US + +70-B3-D5 (hex) em-tec GmbH +DD1000-DD1FFF (base 16) em-tec GmbH + Lerchenberg 20 + Finning Bavaria 86923 + DE + +70-B3-D5 (hex) Clover Electronics Technology Co., Ltd. +08D000-08DFFF (base 16) Clover Electronics Technology Co., Ltd. + 505 room, No.6-18 building, XinHe road, Shajing town, Baoan district + SHENZHEN GUANGDONG 518000 + CN + +70-B3-D5 (hex) Przemyslowy Instytut Automatyki i Pomiarow +ED1000-ED1FFF (base 16) Przemyslowy Instytut Automatyki i Pomiarow + Al. Jerozolimskie 202 + Warszawa Mazowieckie 02-486 + PL + +70-B3-D5 (hex) HRT +D3C000-D3CFFF (base 16) HRT + via Pio La Torre 13 + Campogalliano 41011 + IT + +70-B3-D5 (hex) Beijing Zhongyi Yue Tai Technology Co., Ltd +2B0000-2B0FFF (base 16) Beijing Zhongyi Yue Tai Technology Co., Ltd + Building 809, Xiaoying Road + Beijing Chaoyang District 100101 + CN + +70-B3-D5 (hex) Spark Lasers +2E2000-2E2FFF (base 16) Spark Lasers + IOGS - Bâtiment IOA - Rue François Mitterrand + Talence 33400 + FR + +70-B3-D5 (hex) OOO Microlink-Svyaz +129000-129FFF (base 16) OOO Microlink-Svyaz + 1st veshnjakovsky proezd 7 + moscow moscow 109456 + RU + +70-B3-D5 (hex) Lookman Electroplast Industries Ltd +38B000-38BFFF (base 16) Lookman Electroplast Industries Ltd + Old No : 9, New No : 15, II Street Etn., III Main Road , CIT Nagar, Nandanam + Chennai Tamilnadu 600035 + IN + +70-B3-D5 (hex) ACEMIS FRANCE +64C000-64CFFF (base 16) ACEMIS FRANCE + 36 RUE ARISTIDE BERGES + CUGNAUX 31270 + FR + +70-B3-D5 (hex) Fischer Block, Inc. +80B000-80BFFF (base 16) Fischer Block, Inc. + 21 S High St + West Chester PA 19382 + US + +70-B3-D5 (hex) Akribis Systems +175000-175FFF (base 16) Akribis Systems + Block 5012 Techplace II, #01-05 Ang Mo Kio Avenue 5 + Singapore Singapore 569876 + SG + +70-B3-D5 (hex) TATA POWER SED +60A000-60AFFF (base 16) TATA POWER SED + 42-43 Electronics City + Bengaluru Karnataka 560100 + IN + +70-B3-D5 (hex) Zetechtics Ltd +888000-888FFF (base 16) Zetechtics Ltd + Main Street Amotherby + Malton YO176TA + GB + +70-B3-D5 (hex) CONTINENT, Ltd +9B2000-9B2FFF (base 16) CONTINENT, Ltd + Liflandskaya + St.-Petersburg 190020 + RU + +70-B3-D5 (hex) InnoSenT +332000-332FFF (base 16) InnoSenT + Am Roedertor 30 + Donnersdorf Bavaria 97499 + DE + +70-B3-D5 (hex) Arnouse Digital Devices Corp +831000-831FFF (base 16) Arnouse Digital Devices Corp + 1983 Marcus Ave, Suite 104 + Lake Success NY 11042 + US + +70-B3-D5 (hex) HANGZHOU HUALAN MICROELECTRONIQUE CO.,LTD +FEF000-FEFFFF (base 16) HANGZHOU HUALAN MICROELECTRONIQUE CO.,LTD + 22F,BUILDING-1 OF HUA RUI CENTER,FIRST JIANSHE ROAD,XIAOSHAN DISTRICT + HANGZHOU ZHEJIANG 311200 + CN + +70-B3-D5 (hex) TELL Software Hungaria Kft. +276000-276FFF (base 16) TELL Software Hungaria Kft. + Vagohid u. 2. + Debrecen 4034 + HU + +70-B3-D5 (hex) Wart-Elektronik +AD2000-AD2FFF (base 16) Wart-Elektronik + Nickenicher Strasse 24 + Andernach 56626 + DE + +70-B3-D5 (hex) Procon automatic systems GmbH +549000-549FFF (base 16) Procon automatic systems GmbH + Bettwiesenweg 18 + Sellnrod 35325 + DE + +70-B3-D5 (hex) Norbit ODM AS +F45000-F45FFF (base 16) Norbit ODM AS + Stiklestadveien 1 + Trondheim 7041 + NO + +70-B3-D5 (hex) Inphi Corporation +370000-370FFF (base 16) Inphi Corporation + 112 S. Lakeview Canyon Rd., Suite 100 + Westlake Village CA 91362 + US + +70-B3-D5 (hex) Gencoa Ltd +17A000-17AFFF (base 16) Gencoa Ltd + 4 De Havilland Drive + Liverpool Merseyside L24 8RN + GB + +70-B3-D5 (hex) Gogo BA +C60000-C60FFF (base 16) Gogo BA + 303 S. Technology Ct + Broomfield 80021 + US + +70-B3-D5 (hex) Data Strategy Limited +FF1000-FF1FFF (base 16) Data Strategy Limited + 259 Shirland Road, Maida Vale + London Please Select... W9 3JW + GB + +70-B3-D5 (hex) Quantum Detectors +2C2000-2C2FFF (base 16) Quantum Detectors + R104, RAL, Fermi Avenue + Harwell Oxford Oxfordshire OX11 0QX + GB + +70-B3-D5 (hex) CRDE +572000-572FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) Stiebel Eltron GmbH +C45000-C45FFF (base 16) Stiebel Eltron GmbH + Dr.-Stiebel-Strasse 33 + Holzminden 37603 + DE + +70-B3-D5 (hex) Satcube AB +F77000-F77FFF (base 16) Satcube AB + Anders Carlssons gata 7 + Gothenburg 41755 + SE + +70-B3-D5 (hex) Vtron Pty Ltd +B2B000-B2BFFF (base 16) Vtron Pty Ltd + Unit 2, 62 Township Drive West + West Burleigh Queensland 4219 + AU + +70-B3-D5 (hex) Hexagon Metrology SAS +5E0000-5E0FFF (base 16) Hexagon Metrology SAS + 2 rue François Arago + Montoire sur le Loir Loir et Cher 41800 + FR + +70-B3-D5 (hex) Macnica Technology +E8E000-E8EFFF (base 16) Macnica Technology + 380 Stevens Avenue + Solana Beach CA 92075 + US + +70-B3-D5 (hex) MeQ Inc. +F0D000-F0DFFF (base 16) MeQ Inc. + 6028 Dimm Way + Richmond CA 94805 + US + +70-B3-D5 (hex) Welltec Corp. +115000-115FFF (base 16) Welltec Corp. + 1075-93 Seongseok-dong, Ilsandong-gu + Goyang-si Gyeonggi-do 10251 + KR + +70-B3-D5 (hex) Rugged Science +773000-773FFF (base 16) Rugged Science + 2511 Walmer Ave + Norfolk VA 23513 + US + +70-B3-D5 (hex) Bresslergroup +288000-288FFF (base 16) Bresslergroup + 1216 Arch Street, Floor 7 + Philadelphia PA 19107 + US + +70-B3-D5 (hex) Combilent +E04000-E04FFF (base 16) Combilent + Gydevang 21D + Alleroed 3450 + DK + +70-B3-D5 (hex) Beijing One City Science & Technology Co., LTD +0F1000-0F1FFF (base 16) Beijing One City Science & Technology Co., LTD + Room 901, Building #6, FENGCHUANG KeJi Park + YIZHUANG economic development zone, District Daxing Beijing 100176 + CN + +70-B3-D5 (hex) SHEN ZHEN HUAWANG TECHNOLOGY CO; LTD +A30000-A30FFF (base 16) SHEN ZHEN HUAWANG TECHNOLOGY CO; LTD + Longhua New District Qing Xiang Road, Bao Neng Technology Park + SHEN ZHEN GUANG DONG 518109 + CN + +70-B3-D5 (hex) Savari Inc +040000-040FFF (base 16) Savari Inc + 2005 De la cruz blvd, st 111, + santa clara CA 95050 + US + +70-B3-D5 (hex) Mr.Loop +53B000-53BFFF (base 16) Mr.Loop + 7F.-6, No.237, Sec. 1,Datong Rd. Xizhi Dist. + New Taipei City 22161 + TW + +70-B3-D5 (hex) CRDE +D40000-D40FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) HCH. Kündig & CIE. AG +753000-753FFF (base 16) HCH. Kündig & CIE. AG + Joweid Zentrum 11 + Rüti ZH 8630 + CH + +70-B3-D5 (hex) Practical Software Studio LLC +0BC000-0BCFFF (base 16) Practical Software Studio LLC + 1 Northfield Plaza, Suite 300 + Northfield IL 60093 + US + +70-B3-D5 (hex) Pullnet Technology,S.L. +AA4000-AA4FFF (base 16) Pullnet Technology,S.L. + Parc Tecnologic BCNord + Barcelona Catalonia 08042 + ES + +70-B3-D5 (hex) Mini Solution Co. Ltd. +C68000-C68FFF (base 16) Mini Solution Co. Ltd. + 2-98-85, Yarimizu + Hachiouji Toyko 1920375 + JP + +70-B3-D5 (hex) Fläkt Woods AB +2E5000-2E5FFF (base 16) Fläkt Woods AB + Fläktgatan 1 + Jönköping Foreign state 55184 + SE + +70-B3-D5 (hex) Sicon srl +D37000-D37FFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) THEMA +CAE000-CAEFFF (base 16) THEMA + le praesidium , 350 av du club hippique + aix en provence france 13090 + FR + +70-B3-D5 (hex) Woods Hole Oceanographic Institution +15C000-15CFFF (base 16) Woods Hole Oceanographic Institution + 92 Water Street MS#10 + Woods Hole MA 02543 + US + +70-B3-D5 (hex) HUNTER LIBERTY CORPORATION +FC2000-FC2FFF (base 16) HUNTER LIBERTY CORPORATION + 85 GOLF CREST DRIVE, SUITE 301 + ACWORTH GA 30101 + US + +70-B3-D5 (hex) Brechbuehler AG +0D9000-0D9FFF (base 16) Brechbuehler AG + Steinwiesenstrasse 3 + Schlieren 8952 + CH + +70-B3-D5 (hex) BuddyGuard GmbH +36F000-36FFFF (base 16) BuddyGuard GmbH + Dircksenstr. 40 + Berlin Berlin 10178 + DE + +70-B3-D5 (hex) Edgeware AB +6EA000-6EAFFF (base 16) Edgeware AB + Master Samuelsgatan 42 + Stockholm 11157 + SE + +70-B3-D5 (hex) SinTau SrL +0E3000-0E3FFF (base 16) SinTau SrL + Viale Nizza 11 + L'Aquila 67100 + IT + +70-B3-D5 (hex) Lanmark Controls Inc. +39E000-39EFFF (base 16) Lanmark Controls Inc. + 125 Nagog Park + Acton MA 01720 + US + +70-B3-D5 (hex) Epdm Pty Ltd +F3B000-F3BFFF (base 16) Epdm Pty Ltd + 2 / 1013 Centre Road + Bentleigh East Victoria 3165 + AU + +70-B3-D5 (hex) Solace Systems Inc. +0A3000-0A3FFF (base 16) Solace Systems Inc. + 535 Legget Drive, + Kanata Ontario K2K3B8 + CA + +70-B3-D5 (hex) Standard Backhaul Communications +75A000-75AFFF (base 16) Standard Backhaul Communications + + + + +70-B3-D5 (hex) Bolide Technology Group, Inc. +241000-241FFF (base 16) Bolide Technology Group, Inc. + 468 S. San Dimas Ave., + San Dimas CA 91773 + US + +70-B3-D5 (hex) Sentry360 +D84000-D84FFF (base 16) Sentry360 + 23807 W Andrew Road + Plainfield IL 60585 + US + +70-B3-D5 (hex) Cosylab d.d. +635000-635FFF (base 16) Cosylab d.d. + Teslova ulica 30 + Ljubljana 1000 + SI + +70-B3-D5 (hex) Slot3 GmbH +443000-443FFF (base 16) Slot3 GmbH + Am Brambusch 22 + Luenen Germany 44536 + DE + +70-B3-D5 (hex) Globalcom Engineering SPA +352000-352FFF (base 16) Globalcom Engineering SPA + Via Volta 39 + CARDANO AL CAMPO VA 21010 + IT + +70-B3-D5 (hex) Tecnologix s.r.l. +1E4000-1E4FFF (base 16) Tecnologix s.r.l. + Via dei Biancospini 6 + Milano Mi 20146 + IT + +70-B3-D5 (hex) Opgal Optronic Industries +2AD000-2ADFFF (base 16) Opgal Optronic Industries + Hanapach 21 + Carmiel 2161401 + IL + +70-B3-D5 (hex) Supracon AG +5D3000-5D3FFF (base 16) Supracon AG + An der Lehmgrube 11 + Jena Thüringen 07751 + DE + +70-B3-D5 (hex) Alere Technologies AS +A4C000-A4CFFF (base 16) Alere Technologies AS + Kjelsaasveien 161 + Oslo Oslo 0382 + NO + +70-B3-D5 (hex) Proterra +2C3000-2C3FFF (base 16) Proterra + 1 Whitlee Ct + Greenville SC 29607 + US + +70-B3-D5 (hex) Synics AG +BD5000-BD5FFF (base 16) Synics AG + Querstr. 8 + Regensdorf 8105 + CH + +70-B3-D5 (hex) Agilack +4CE000-4CEFFF (base 16) Agilack + 12 avenue Jules Verne + Saint Sebastien sur loire 44230 + FR + +70-B3-D5 (hex) Meridian Technologies Inc +924000-924FFF (base 16) Meridian Technologies Inc + 700 Elmont Rd + Elmont NY 11003 + US + +70-B3-D5 (hex) Paul Scherrer Institut (PSI) +3B7000-3B7FFF (base 16) Paul Scherrer Institut (PSI) + WHGA/U130 + Villigen-PSI Aargau CH-5232 + CH + +70-B3-D5 (hex) CMI, Inc. +4EF000-4EFFFF (base 16) CMI, Inc. + 316 East 9th Street + Owensboro KY 42303 + US + +70-B3-D5 (hex) Beijing DamingWuzhou Science&Technology Co., Ltd. +A36000-A36FFF (base 16) Beijing DamingWuzhou Science&Technology Co., Ltd. + 8001,8 Floor,Building C,KanjianBaoshen Square,Haidian District + Beijing 100192 + CN + +70-B3-D5 (hex) MCQ TECH GmbH +A58000-A58FFF (base 16) MCQ TECH GmbH + Ottilienweg 9 + Blumberg BW 78176 + DE + +70-B3-D5 (hex) Density Inc. +785000-785FFF (base 16) Density Inc. + 235 HARRISON ST, Mail Drop 24 + Syracuse NY 13202 + US + +70-B3-D5 (hex) IROC AB +39B000-39BFFF (base 16) IROC AB + Bärtas Väg 15 + Kode Västra Götaland 442 98 + + +70-B3-D5 (hex) ProtoPixel SL +2DB000-2DBFFF (base 16) ProtoPixel SL + C/Pujades 77-79, 5e 4a + Barcelona Barcelona 08005 + ES + +70-B3-D5 (hex) Trinity College Dublin +99E000-99EFFF (base 16) Trinity College Dublin + Dunlop Oriel House, Fenian Street + Dublin 2 2 + IE + +70-B3-D5 (hex) comtime GmbH +1E9000-1E9FFF (base 16) comtime GmbH + Gutenbergring 22 + Norderstedt 22848 + DE + +70-B3-D5 (hex) HAXE SYSTEME +49A000-49AFFF (base 16) HAXE SYSTEME + 1, rue de Lorraine + La Chapelle sur Erdre Pays de la Loire 44240 + FR + +70-B3-D5 (hex) BirdDog Australia +C7E000-C7EFFF (base 16) BirdDog Australia + Unit 1, 8 Theobald St + THORNBURY VIC 3071 + AU + +70-B3-D5 (hex) ATOM GIKEN Co.,Ltd. +AC5000-AC5FFF (base 16) ATOM GIKEN Co.,Ltd. + 92-2 KATASE + FUJISAWA KANAGAWA 251-0032 + JP + +70-B3-D5 (hex) ADE Technology Inc. +F30000-F30FFF (base 16) ADE Technology Inc. + 15F. No.90, Xingde Rd., Sanchong Dist. + New Taipei City 24158 + TW + +70-B3-D5 (hex) Husty M.Styczen J.Hupert Sp.J. +54C000-54CFFF (base 16) Husty M.Styczen J.Hupert Sp.J. + Rzepakowa 5e + Krakow malopolska 31-989 + PL + +70-B3-D5 (hex) George Wilson Industries Ltd +48A000-48AFFF (base 16) George Wilson Industries Ltd + Barlow Road, Aldermans Green Industrial Estate + Coventry West Midlands CV2 2LD + GB + +70-B3-D5 (hex) Get SAT +F95000-F95FFF (base 16) Get SAT + Hamada 12 + Rehovot Select From Dropdown 7670316 + IL + +70-B3-D5 (hex) Apantac LLC +CD5000-CD5FFF (base 16) Apantac LLC + 7556 SW Bridgeport Road + Durham OR 97224 + US + +70-B3-D5 (hex) Checkbill Co,Ltd. +947000-947FFF (base 16) Checkbill Co,Ltd. + 3306~7-ho, Beonyeonggwan, Chungnam Techno Park, 136, Jiksan-ro, Jiksan-eup, Seobuk-gu + Cheonan-si Chungcheongnam-do 31035 + KR + +70-B3-D5 (hex) DWEWOONG ELECTRIC Co., Ltd. +BC2000-BC2FFF (base 16) DWEWOONG ELECTRIC Co., Ltd. + 10, Hwanggeum-ro 127beon-gil Yangchon-eup + Gimpo-si Gyeonggi-do 10048 + KR + +70-B3-D5 (hex) MG s.r.l. +405000-405FFF (base 16) MG s.r.l. + via Monte Bianco, 1 + Solbiate Olona VA 21058 + IT + +70-B3-D5 (hex) ZAO ZEO +083000-083FFF (base 16) ZAO ZEO + Khachaturiana 14a + Moscow 127562 + RU + +70-B3-D5 (hex) Infosocket Co., Ltd. +C0A000-C0AFFF (base 16) Infosocket Co., Ltd. + 1-6-1-303 + Musashino Tokyo 180-0005 + JP + +70-B3-D5 (hex) HolidayCoro +009000-009FFF (base 16) HolidayCoro + 27719 Nelson St + Spring TX 77373 + US + +70-B3-D5 (hex) EFENTO T P SZYDŁOWSKI K ZARĘBA SPÓŁKA JAWNA +1BB000-1BBFFF (base 16) EFENTO T P SZYDŁOWSKI K ZARĘBA SPÓŁKA JAWNA + Dietla 93/6 + Kraków 31-031 + PL + +70-B3-D5 (hex) Merten GmbH&CoKG +550000-550FFF (base 16) Merten GmbH&CoKG + Fritz-Kotz-Str. 8 + Wiehl NRW 51674 + DE + +70-B3-D5 (hex) AndFun Co.,Ltd. +BE8000-BE8FFF (base 16) AndFun Co.,Ltd. + 5972-2 Ohkusa + Komaki Aichi 4850802 + JP + +70-B3-D5 (hex) Technica Engineering GmbH +28D000-28DFFF (base 16) Technica Engineering GmbH + Leopoldstraße 236 + Munich 80807 + DE + +70-B3-D5 (hex) DAVE SRL +142000-142FFF (base 16) DAVE SRL + VIA TALPONEDO 29/A + PORCIA PORDENONE 330850 + IT + +70-B3-D5 (hex) LDA audio video profesional S.L. +1C8000-1C8FFF (base 16) LDA audio video profesional S.L. + C/ Severo Ochoa, 31 + Malaga Malaga 29590 + ES + +70-B3-D5 (hex) Sensobox GmbH +C15000-C15FFF (base 16) Sensobox GmbH + Eschenstrasse 24 + 6005 Lucerne 6005 + CH + +70-B3-D5 (hex) Stesalit Systems Ltd +67B000-67BFFF (base 16) Stesalit Systems Ltd + Stesalit Towers, Block GP, Sector 5, Salt Lake Electronics Complex, + Kolkata West Bengal 700091 + IN + +70-B3-D5 (hex) midBit Technologies, LLC +EBD000-EBDFFF (base 16) midBit Technologies, LLC + 153 Homestead Ln + Romney WV 26757 + US + +70-B3-D5 (hex) OMESH CITY GROUP +A8E000-A8EFFF (base 16) OMESH CITY GROUP + 202,A building,Xu Zhuang Software Park,Xuan Wu District + Nangjing Jiangsu 240042 + CN + +70-B3-D5 (hex) Gamber Johnson-LLC +178000-178FFF (base 16) Gamber Johnson-LLC + 3001 Borham Ave + Stevens Point WI 54481 + US + +70-B3-D5 (hex) Molekule +A5C000-A5CFFF (base 16) Molekule + 2507 Bryant St. + San Francisco CA 94110 + US + +70-B3-D5 (hex) Seiwa Giken +48F000-48FFFF (base 16) Seiwa Giken + 4-4-23 Hotarugaike-higashimachi + Toyonaka-City Osaka 560-0032 + JP + +70-B3-D5 (hex) AE Van de Vliet BVBA +C4F000-C4FFFF (base 16) AE Van de Vliet BVBA + INDUSTRIEDIJK 14 + TURNHOUT ANTWERPEN 2300 + BE + +70-B3-D5 (hex) Acacia Research +BF5000-BF5FFF (base 16) Acacia Research + 5 Butler Drive + HENDON South Australia 5014 + AU + +70-B3-D5 (hex) ALPHA Corporation +D67000-D67FFF (base 16) ALPHA Corporation + 1-6-8 Fukuura, + Yokohama City, Kanazawa-ku, Kanagawa 236-0004 + JP + +70-B3-D5 (hex) ATHREYA INC +85D000-85DFFF (base 16) ATHREYA INC + 261 Conlins Road + TORONTO ON M1C1C4 + CA + +70-B3-D5 (hex) SYSDEV Srl +C0E000-C0EFFF (base 16) SYSDEV Srl + via Lamarmora 16 + Torino TO 10128 + IT + +70-B3-D5 (hex) LECO Corporation +599000-599FFF (base 16) LECO Corporation + 3000 Lakeview Ave. + St. Joseph null 49085 + US + +70-B3-D5 (hex) SiS Technology +E71000-E71FFF (base 16) SiS Technology + Business Park Varna, building B1, floor 4 + Varna 9000 + BG + +70-B3-D5 (hex) Excel Medical Electronics LLC +7DD000-7DDFFF (base 16) Excel Medical Electronics LLC + 801 Maplewood Dr. + Jupiter null 33458 + US + +70-B3-D5 (hex) ChongQing JianTao Technology Co., Ltd. +486000-486FFF (base 16) ChongQing JianTao Technology Co., Ltd. + 10th, Building NO.C1, District E, Dawn industrial area, CunTan, JiangBei District, ChongQing City. China + ChongQing ChongQing 400025 + CN + +70-B3-D5 (hex) FoodALYT GmbH +D91000-D91FFF (base 16) FoodALYT GmbH + Robert-Hooke-Str.8 + Bremen Bremen 28359 + DE + +70-B3-D5 (hex) Exicom Technologies fze +3AE000-3AEFFF (base 16) Exicom Technologies fze + Technology park , P.O.box 327792 + Ras Al Khaimah FTZ Ras Al Khaimah 327792 + AE + +70-B3-D5 (hex) TESEC Corporation +461000-461FFF (base 16) TESEC Corporation + 391-1, Kamikitadai 3-Chome + Higasiyamato Tokyo 2070023 + JP + +70-B3-D5 (hex) AERONAUTICAL & GENERAL INSTRUMENTS LTD. +FDE000-FDEFFF (base 16) AERONAUTICAL & GENERAL INSTRUMENTS LTD. + FLEETS POINT + POOLE DORSET BH12 3SS + GB + +70-B3-D5 (hex) oxynet Solutions +3D5000-3D5FFF (base 16) oxynet Solutions + G04 A block, Ground Floor, King Space Meadows, Thanisandra Main Road + Bangalore Karnataka 560077 + IN + +70-B3-D5 (hex) CAB S.R.L. +B11000-B11FFF (base 16) CAB S.R.L. + VIA CARDUCCI, 41/E + SAN GIULIANO MILANESE MILANO 20098 + IT + +70-B3-D5 (hex) IDEAL INDUSTRIES Ltd t/a Casella +A91000-A91FFF (base 16) IDEAL INDUSTRIES Ltd t/a Casella + Regent House, Wolseley Road + Kempston, Bedford Bedfordshire MK427JY + GB + +70-B3-D5 (hex) BeatCraft, Inc. +AE5000-AE5FFF (base 16) BeatCraft, Inc. + 5F, S.HARUYAMA BLDG, Kinshi2-13-6 + Sumida Tokyo 1300013 + JP + +70-B3-D5 (hex) Zumbach Electronic AG +7B4000-7B4FFF (base 16) Zumbach Electronic AG + Hauptstrasse 93 + Orpund Bern 2552 + CH + +70-B3-D5 (hex) Shanghai EICT Global Service Co., Ltd +FC9000-FC9FFF (base 16) Shanghai EICT Global Service Co., Ltd + Room 1105 NO.376 ZhaojiaBang Road, XuHui District + Shanghai 200031 + CN + +70-B3-D5 (hex) Telairity Semiconductor +1A3000-1A3FFF (base 16) Telairity Semiconductor + 3375 Scott Blvd. + Santa Clara CA 95054 + US + +70-B3-D5 (hex) Weltek Technologies Co. Ltd. +A4F000-A4FFFF (base 16) Weltek Technologies Co. Ltd. + Flat A-B, 12/F, Block 1, Wah Fung Ind. Centre, 33-39 Kwai Fung Crescent, Kwai Chung, N.T. + HK 852 + HK + +70-B3-D5 (hex) CCII Systems (Pty) Ltd +BE6000-BE6FFF (base 16) CCII Systems (Pty) Ltd + Unit 3, 67 Rosmead Avenue + Cape Town Cape 7708 + ZA + +70-B3-D5 (hex) Neurio Technology Inc. +750000-750FFF (base 16) Neurio Technology Inc. + 43 West Hastings Street + Vancouver BC V6B 1G4 + CA + +70-B3-D5 (hex) Rohde&Schwarz Topex SA +243000-243FFF (base 16) Rohde&Schwarz Topex SA + 71th-73th Nicolae Caramfil street, 2nd floor, 1th district + Bucuresti Romania 014142 + RO + +70-B3-D5 (hex) P&S GmbH +09D000-09DFFF (base 16) P&S GmbH + Hainstr. 13 + Gera Germany 07545 + DE + +70-B3-D5 (hex) Dynamic Connect (Suzhou) Hi-Tech Electronic Co.,Ltd. +33E000-33EFFF (base 16) Dynamic Connect (Suzhou) Hi-Tech Electronic Co.,Ltd. + Unit C&D, No.201 WuXiang, Export Processing Zone A No.200Suhong Road SIP + Suzhou JiangSu 215021 + CN + +70-B3-D5 (hex) Eleven Engineering Incorporated +6E6000-6E6FFF (base 16) Eleven Engineering Incorporated + 10150 - 100 Street, Suite 800 + Edmonton Canada, Alberta T5J 0P6 + CA + +70-B3-D5 (hex) CL International +ABA000-ABAFFF (base 16) CL International + 12th Floor, Woolim Lions Valley 1 Bldg 27, Dunchon-daero 457beongil, Jungwon-gu + Seongnam Kyeonggi-do 462-806 + KR + +70-B3-D5 (hex) Aplex Technology Inc. +35F000-35FFFF (base 16) Aplex Technology Inc. + 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District + Shenzhen Guangdong 518054 + CN + +70-B3-D5 (hex) Emka Technologies +AF1000-AF1FFF (base 16) Emka Technologies + 59 bd General Martial Valin + PARIS 75015 + FR + +70-B3-D5 (hex) Siemens AG +C87000-C87FFF (base 16) Siemens AG + MO TPE RE PI + Erlangen Bavaria 91052 + DE + +70-B3-D5 (hex) Aplex Technology Inc. +18B000-18BFFF (base 16) Aplex Technology Inc. + 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District + Shenzhen Guangdong 518054 + CN + +70-B3-D5 (hex) MiraeSignal Co., Ltd +38C000-38CFFF (base 16) MiraeSignal Co., Ltd + #203 E-dong Bundang Techno Park Yatapdong + Sungnam Kyungkido 463760 + KR + +70-B3-D5 (hex) Stara S/A Indústria de Implementos Agrícolas +13E000-13EFFF (base 16) Stara S/A Indústria de Implementos Agrícolas + Avenida Stara 519 + Não-Me-Toque Rio Grande do Sul 99470000 + BR + +70-B3-D5 (hex) BlueMark Innovations BV +325000-325FFF (base 16) BlueMark Innovations BV + Hengelosestraat 517 + Enschede 7521 AG + NL + +70-B3-D5 (hex) Östling Marking Systems GmbH +A96000-A96FFF (base 16) Östling Marking Systems GmbH + Broßhauserstr. 27 + Solingen 42697 + DE + +70-B3-D5 (hex) Meta-chrom Co. Ltd. +68D000-68DFFF (base 16) Meta-chrom Co. Ltd. + Baumana St.,100 + Yoshkar-Ola Select State 424000 + RU + +70-B3-D5 (hex) xm +840000-840FFF (base 16) xm + 50, Cheomdangwagi-ro 208beon-gil, Buk-gu, Gwangju, Korea + Gwangju 61012 + KR + +70-B3-D5 (hex) MART NETWORK SOLUTIONS LTD +94F000-94FFFF (base 16) MART NETWORK SOLUTIONS LTD + ABBEY HOUSE, 450 BATH ROAD + LONGFORD MIDDLESEX UB70EB + GB + +70-B3-D5 (hex) TextNinja Co. +283000-283FFF (base 16) TextNinja Co. + 222 W Merchandise Mart Plaza, Suite 1212 + Chicago IL 60654 + US + +70-B3-D5 (hex) Micro Trend Automation Co., LTD +50E000-50EFFF (base 16) Micro Trend Automation Co., LTD + 3F, No 78 Cheng Kung Road Sec1 + Taipei Nan Kang 11570 + TW + +70-B3-D5 (hex) Explorer Inc. +E85000-E85FFF (base 16) Explorer Inc. + 379-22 kikyou-cho + Hakodate Hokkaido 041-0801 + JP + +70-B3-D5 (hex) Sicon srl +30C000-30CFFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) Innoflight, Inc. +BB7000-BB7FFF (base 16) Innoflight, Inc. + 9985 Pacific Heights Blvd, Suite 250 + San Diego CA 92121 + US + +70-B3-D5 (hex) CRDE +D63000-D63FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) Discover Video +440000-440FFF (base 16) Discover Video + Bld 3 + Wallingford CT 06492 + US + +70-B3-D5 (hex) Moog Rekofa GmbH +4D5000-4D5FFF (base 16) Moog Rekofa GmbH + Bergstrasse 41 + Antweiler Rhineland-Palatinate 53533 + DE + +70-B3-D5 (hex) Electronic Equipment Company Pvt. Ltd. +640000-640FFF (base 16) Electronic Equipment Company Pvt. Ltd. + 146/2, Old China Bazar Street, + Kolkata West Bengal 700001 + IN + +70-B3-D5 (hex) Zebra Elektronik A.S. +259000-259FFF (base 16) Zebra Elektronik A.S. + Kayisdagi Cd. Baris Sk. No:2 K:5 Kucukbakkalkoy + Istanbul NA 34750 + TR + +70-B3-D5 (hex) Tanaka Information System, LLC. +60F000-60FFFF (base 16) Tanaka Information System, LLC. + 3-17-18 Higashi-Nakano, + Nakano-ku Tokyo 1640003 + JP + +00-1B-C5 (hex) Onnet Technologies and Innovations LLC +087000-087FFF (base 16) Onnet Technologies and Innovations LLC + 1, Opp GIBCA CAMP + AJMAN AJMAN 52141 + AE + +70-B3-D5 (hex) Jireh Industries Ltd. +974000-974FFF (base 16) Jireh Industries Ltd. + 53158 Range Road 224 + Ardrossan Alberta T8E2K4 + CA + +70-B3-D5 (hex) Aplex Technology Inc. +4B7000-4B7FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) P4Q ELECTRONICS, S.L. +3C5000-3C5FFF (base 16) P4Q ELECTRONICS, S.L. + CTRA. BILBAO BALMASEDA, KM9 + ALONSOTEGUI VIZCAYA 48810 + ES + +70-B3-D5 (hex) Alligator Communications +9CB000-9CBFFF (base 16) Alligator Communications + 317 Brokaw Road + Santa Clara CA 95050 + US + +70-B3-D5 (hex) Preston Industries dba PolyScience +9EB000-9EBFFF (base 16) Preston Industries dba PolyScience + 6600 W. Touhy Ave + Niles IL 60714-4588 + US + +70-B3-D5 (hex) Depro Électronique inc +7E2000-7E2FFF (base 16) Depro Électronique inc + 755 Cure-Boivin local 22 + Boisbriand Quebec J7G2J2 + CA + +70-B3-D5 (hex) Szabo Software & Engineering UK Ltd +F08000-F08FFF (base 16) Szabo Software & Engineering UK Ltd + 43 Angrave Rd + East Leake Leicester LE12 6JA + GB + +70-B3-D5 (hex) STC Rainbow Ltd. +1A8000-1A8FFF (base 16) STC Rainbow Ltd. + 5-y Donskoy pr-d, 15с2 + Moscow 119334 + RU + +70-B3-D5 (hex) Cubro Acronet GesmbH +01A000-01AFFF (base 16) Cubro Acronet GesmbH + Geiselberstraße 17 / 6 Floor + Vienna Vienna 1110 + AT + +70-B3-D5 (hex) VNG Corporation +8D8000-8D8FFF (base 16) VNG Corporation + 322B Lý Thường Kiệt, P.14 + Hồ Chí Minh 70000 + VN + +70-B3-D5 (hex) Lumiplan Duhamel +070000-070FFF (base 16) Lumiplan Duhamel + 2 rue de l'industrie + Domène Isère 38420 + FR + +70-B3-D5 (hex) The Things Network Foundation +7ED000-7EDFFF (base 16) The Things Network Foundation + Herengracht 182 + Amsterdam NH 1016BR + NL + +70-B3-D5 (hex) Sensapex Oy +45D000-45DFFF (base 16) Sensapex Oy + Teknologiatie 13 + Oulu 90590 + FI + +70-B3-D5 (hex) Ensura Solutions BV +CBE000-CBEFFF (base 16) Ensura Solutions BV + Hofstraat 4 + Ulft Gelderland 7071 KB + NL + +70-B3-D5 (hex) GSP Sprachtechnologie GmbH +120000-120FFF (base 16) GSP Sprachtechnologie GmbH + Teltowkanalstraße 1 + Berlin 12247 + DE + +70-B3-D5 (hex) Coester Automação Ltda +975000-975FFF (base 16) Coester Automação Ltda + Rua Jacy Porto, 1157 + Sao Leopoldo RS 93025-120 + BR + +70-B3-D5 (hex) Robert Bosch, LLC +652000-652FFF (base 16) Robert Bosch, LLC + 256 Raceway Drive, Suite 4 + Mooresville NC 28117 + US + +70-B3-D5 (hex) Windar Photonics +5FD000-5FDFFF (base 16) Windar Photonics + Helgeshoj Alle 16 + Taastrup Copenhagen 2630 + DK + +70-B3-D5 (hex) CT Company +5A3000-5A3FFF (base 16) CT Company + Godovikova , 9, Moscow + Moscow RUSSIA 129085 + RU + +70-B3-D5 (hex) Cathwell AS +BA1000-BA1FFF (base 16) Cathwell AS + Kongshavnsgate 18 + Langesund Telemark N-3970 + NO + +70-B3-D5 (hex) Aplex Technology Inc. +BFE000-BFEFFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) KST technology +F7B000-F7BFFF (base 16) KST technology + 164-1, KST b/d., Bangi-dong, songpa-gu + SEOUL N/A 138-050 + KR + +70-B3-D5 (hex) SIEMENS AS +CCA000-CCAFFF (base 16) SIEMENS AS + Bratsbergveien 5 + Trondheim 7037 + NO + +70-B3-D5 (hex) NPF Modem, LLC +8B2000-8B2FFF (base 16) NPF Modem, LLC + Kolomyazhskiy prosp. 27A + Saint-Petersburg 197341 + RU + +70-B3-D5 (hex) SOCIEDAD IBERICA DE CONSTRUCCIONES ELECTRICAS, S.A. (SICE) +EEE000-EEEFFF (base 16) SOCIEDAD IBERICA DE CONSTRUCCIONES ELECTRICAS, S.A. (SICE) + C/Sepulveda, 6 + ALCOBENDAS MADRID 28108 + ES + +70-B3-D5 (hex) Project Service S.a.s. +781000-781FFF (base 16) Project Service S.a.s. + Via Paderno 31/C + Seriate Bergamo 24068 + IT + +70-B3-D5 (hex) UPM Technology, Inc +75C000-75CFFF (base 16) UPM Technology, Inc + 3000 NW Stucki pl ste #100 + Hillsboro OR OR 97124 + US + +70-B3-D5 (hex) Groupeer Technologies +054000-054FFF (base 16) Groupeer Technologies + 17 avenue Georges 5 + Paris Ile-de-France 75008 + FR + +70-B3-D5 (hex) Seal Shield, LLC +33B000-33BFFF (base 16) Seal Shield, LLC + 2000 N. Alafaya Trail Suite 350 + Jacksonville FL 32826 + US + +70-B3-D5 (hex) Grupo Epelsa S.L. +CA8000-CA8FFF (base 16) Grupo Epelsa S.L. + C/ Punto Net,3 + Alcala de Henares Madrid 28805 + ES + +70-B3-D5 (hex) TATTILE SRL +323000-323FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) TATTILE SRL +8F3000-8F3FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) PBSI Group Limited +609000-609FFF (base 16) PBSI Group Limited + Belle Vue Works, Boundary Street + Manchester Lancashire M12 5NG + GB + +70-B3-D5 (hex) Vironova AB +C3B000-C3BFFF (base 16) Vironova AB + Gävlegatan 22 + Stockholm 11330 + SE + +70-B3-D5 (hex) 5nines +1B4000-1B4FFF (base 16) 5nines + Avalon Four, Mill Street + Cape Town Western Cape 8001 + ZA + +70-B3-D5 (hex) Innitive B.V. +66B000-66BFFF (base 16) Innitive B.V. + Brouwerijstraat 20 + Enschede Overijssel 7523xd + NL + +70-B3-D5 (hex) Al Kamel Systems S.L. +BB8000-BB8FFF (base 16) Al Kamel Systems S.L. + Priora Xixilona, 93 + La Garriga Barcelona 08530 + ES + +70-B3-D5 (hex) XpertSea Solutions inc. +996000-996FFF (base 16) XpertSea Solutions inc. + 2700 Jean-Perrin suite 170 + Québec QC G2C 1S9 + CA + +00-1B-C5 (hex) ChamSys Ltd +042000-042FFF (base 16) ChamSys Ltd + Unit 3B Richmond Works + Southampton Hampshire SO15 3FQ + GB + +70-B3-D5 (hex) Sea Shell Corporation +671000-671FFF (base 16) Sea Shell Corporation + 10th Fl. Chuohtanimachi bldg. 9-3-7, Tanimachi, Chuohku + Osaka 542-0012 + JP + +70-B3-D5 (hex) InDiCor +FC1000-FC1FFF (base 16) InDiCor + Kornstr. 18 + Horgenzell 88263 + DE + +70-B3-D5 (hex) Waversa Systems +D07000-D07FFF (base 16) Waversa Systems + #1002 Pankyo-Innovalley, 622 Sampyong-dong, Bundang-gu + Seongnam-si, Kyeonggi-do 13486 + KR + +70-B3-D5 (hex) IST Technologies (SHENZHEN) Limited +081000-081FFF (base 16) IST Technologies (SHENZHEN) Limited + Flat 1203, Block C6, HengFeng Industrial City, HeZhou, + Shenzhen Guangdong 518126 + CN + +70-B3-D5 (hex) TDI. Co., LTD +E48000-E48FFF (base 16) TDI. Co., LTD + 80 Daehak-ro, Sankyuk-dong, Buk-gu + Deagu Deagu 41566 + KR + +70-B3-D5 (hex) R&D Gran-System-S LLC +185000-185FFF (base 16) R&D Gran-System-S LLC + F.Skoriny 54A + Minsk NA 220141 + BY + +70-B3-D5 (hex) Triple Play Communications +C26000-C26FFF (base 16) Triple Play Communications + 250 East Drive, Suite F + Melbourne Florida 32904 + US + +70-B3-D5 (hex) Apator Miitors ApS +771000-771FFF (base 16) Apator Miitors ApS + Bautavej 1A + Aarhus V Midtjylland 8210 + DK + +70-B3-D5 (hex) North Pole Engineering, Inc. +066000-066FFF (base 16) North Pole Engineering, Inc. + 221 N. 1st. St., Suite 310 + Minneapolis MN 55401 + US + +70-B3-D5 (hex) QIAGEN Instruments AG +7B9000-7B9FFF (base 16) QIAGEN Instruments AG + Garstligweg 8 + Hombrechtikon Zurich 8634 + CH + +70-B3-D5 (hex) Sadel S.p.A. +7AA000-7AAFFF (base 16) Sadel S.p.A. + via Marino Serenari, 1 + Castel Maggiore Bologna 40013 + IT + +70-B3-D5 (hex) Medtronic +B34000-B34FFF (base 16) Medtronic + 7 Hamarpe Street + Jerusalem Israel 97774 + IL + +70-B3-D5 (hex) Prisma Telecom Testing Srl +740000-740FFF (base 16) Prisma Telecom Testing Srl + Via Petrocchi, 4 + Milano MI 20127 + IT + +70-B3-D5 (hex) Itrinegy Ltd. +BED000-BEDFFF (base 16) Itrinegy Ltd. + Albany Chambers + Welwyn Garden City Herts AL7 1HL + GB + +70-B3-D5 (hex) Fluid Components International +A1D000-A1DFFF (base 16) Fluid Components International + 1755 La Costa Meadows Drive + San Marcos CA 92078 + US + +70-B3-D5 (hex) TATTILE SRL +2F6000-2F6FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Solystic +F85000-F85FFF (base 16) Solystic + 152/160 av Aristide Briand + Bagneux Region Parisienne 92227 + FR + +70-B3-D5 (hex) Aplex Technology Inc. +817000-817FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) OTI LTD +76F000-76FFFF (base 16) OTI LTD + Z.H.R Ind.Zone + Rosh Pina North Israel 1200000 + IL + +70-B3-D5 (hex) Critical Link LLC +B51000-B51FFF (base 16) Critical Link LLC + 6712 Brooklawn Parkway + Syracuse New York 13211 + US + +70-B3-D5 (hex) Xsight Systems Ltd. +504000-504FFF (base 16) Xsight Systems Ltd. + 11 Haavoda Street + Rosh-Haayin Shfela 4801761 + IL + +70-B3-D5 (hex) Mikrotron Mikrocomputer, Digital- und Analogtechnik GmbH +5EE000-5EEFFF (base 16) Mikrotron Mikrocomputer, Digital- und Analogtechnik GmbH + Landshuter Str. 20 - 22 + Unterschleissheim Bavaria 85716 + DE + +70-B3-D5 (hex) BroadSoft Inc +F11000-F11FFF (base 16) BroadSoft Inc + 550 S Winchester Blvd + San Jose CA 95128 + US + +70-B3-D5 (hex) Sigma Connectivity AB +E0D000-E0DFFF (base 16) Sigma Connectivity AB + BOX99 + Lund Skane SE- 221 00 + SE + +70-B3-D5 (hex) Aplex Technology Inc. +D90000-D90FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) DETECT Australia +DD7000-DD7FFF (base 16) DETECT Australia + 40 Clements Avenue + Bundoora Victoria 3083 + AU + +70-B3-D5 (hex) Firehose Labs, Inc. +F79000-F79FFF (base 16) Firehose Labs, Inc. + 1540 Oak Creek Dr #404 + Palo Alto CA 94304 + US + +70-B3-D5 (hex) Fuchu Giken, Inc. +303000-303FFF (base 16) Fuchu Giken, Inc. + 5-38-33 + Fuchu-shi Tokyo 183-0026 + JP + +70-B3-D5 (hex) BRNET CO.,LTD. +2EB000-2EBFFF (base 16) BRNET CO.,LTD. + Zhoushi Jiangnan mingzhu garden 48-902 + KUNSHAN JIANGSU 215300 + CN + +70-B3-D5 (hex) DORLET SAU +A56000-A56FFF (base 16) DORLET SAU + Albert Eistein 34 + Alava SPAIN 01510 + ES + +70-B3-D5 (hex) CT Company +230000-230FFF (base 16) CT Company + 9F.-1, No,Jian 8th Rd. + Jhonghe Dist New Taipei 23511 + TW + +70-B3-D5 (hex) vitalcare +0FC000-0FCFFF (base 16) vitalcare + Unit 14, 31-33 Chaplin Drive + Lane cove NSW 2066 + AU + +70-B3-D5 (hex) Temperature@lert +4DB000-4DBFFF (base 16) Temperature@lert + 108 Lincoln St. + Boston MA 02111 + US + +70-B3-D5 (hex) Flexim Security Oy +7C3000-7C3FFF (base 16) Flexim Security Oy + P.O.Box 700 + ESPOO Southern Finland 02131 + FI + +70-B3-D5 (hex) Neptec Technologies Corp. +3E4000-3E4FFF (base 16) Neptec Technologies Corp. + 302 Legget Drive + Kanata Ontario K2K 1Y5 + CA + +70-B3-D5 (hex) Phyton, Inc. Microsystems and Development Tools +8A4000-8A4FFF (base 16) Phyton, Inc. Microsystems and Development Tools + 7206 Bay Parkway + Brooklyn NY 11204 + US + +70-B3-D5 (hex) PK Sound +9C9000-9C9FFF (base 16) PK Sound + Bay 133 2634 45th Ave SE + Calgary Alberta T2B 3M1 + CA + +70-B3-D5 (hex) Engage Technologies +FCD000-FCDFFF (base 16) Engage Technologies + 7041 Boone Ave. N + Brooklyn Park MN 55428 + US + +70-B3-D5 (hex) CheckBill Co,Ltd. +079000-079FFF (base 16) CheckBill Co,Ltd. + jiksan-eup, Seobuk-gu 28, 4sandan 5-gil + Cheonan-si Chungcheongnam-do 331-814 + KR + +70-B3-D5 (hex) Alturna Networks +714000-714FFF (base 16) Alturna Networks + De Huchtstraat 35 + Almere Fleovland 1327 EC + NL + +70-B3-D5 (hex) UFATECH LTD +1A0000-1A0FFF (base 16) UFATECH LTD + Mendeleev st 134 + UFA RB 450073 + RU + +70-B3-D5 (hex) Videogenix +730000-730FFF (base 16) Videogenix + 1423 Beacon St + Brookline MA 02446 + US + +70-B3-D5 (hex) dieEntwickler Elektronik GmbH +7A8000-7A8FFF (base 16) dieEntwickler Elektronik GmbH + Linzer Str. 4 + Bad Zell Upper Austria 4283 + AT + +70-B3-D5 (hex) Speedifi Inc +D7A000-D7AFFF (base 16) Speedifi Inc + 1163 Kassel Terrace + Sunnyvale CA 94089 + + +70-B3-D5 (hex) SD Biosensor +737000-737FFF (base 16) SD Biosensor + C-4th & 5th Floor, Digital Empire Building, 980-3 + Suwon-si Kyonggi-do ASI|KR|KS002|SUWON + KR + +70-B3-D5 (hex) Sierra Nevada Corporation +339000-339FFF (base 16) Sierra Nevada Corporation + 444 Salomon Circle + Sparks NV 89434 + US + +70-B3-D5 (hex) StromIdee GmbH +703000-703FFF (base 16) StromIdee GmbH + Walzmühlestrasse 51 + Frauenfeld TG 8500 + CH + +70-B3-D5 (hex) Tofino +838000-838FFF (base 16) Tofino + 47823 Westinghouse Dr. + Fremont California 94539 + US + +70-B3-D5 (hex) Rexxam Co.,Ltd. +B35000-B35FFF (base 16) Rexxam Co.,Ltd. + Ikenouchi 958 + Takamatsu-shi, Kounan-cho Kagawa-prefecture 761-1494 + JP + +70-B3-D5 (hex) Techno Mathematical Co.,Ltd +916000-916FFF (base 16) Techno Mathematical Co.,Ltd + 7F, Gotanda NN Bldg., + Shinagawa-ku Tokyo 141-0031 + JP + +70-B3-D5 (hex) BroadSoft Inc +AB5000-AB5FFF (base 16) BroadSoft Inc + 550 S Winchester Blvd + San Jose CA 95128 + US + +70-B3-D5 (hex) Data Physics Corporation +80D000-80DFFF (base 16) Data Physics Corporation + 1741 Technology Drive, Suite 260 + San Jose California 95110 + US + +70-B3-D5 (hex) LACE LLC. +4B1000-4B1FFF (base 16) LACE LLC. + Obukhovskoy oborony 70/2, office 416 + Saint-Petersburg Saint-Petersburg 192029 + RU + +70-B3-D5 (hex) VEILUX INC. +FE7000-FE7FFF (base 16) VEILUX INC. + 802 GREENVIEW DR. STE 200 + GRAND PRAIRIE 75050 + US + +70-B3-D5 (hex) METRONIC APARATURA KONTROLNO - POMIAROWA +1A5000-1A5FFF (base 16) METRONIC APARATURA KONTROLNO - POMIAROWA + WYBICKIEGO 7 + KRAKOW MALOPOLSKA 31-261 + PL + +70-B3-D5 (hex) WiTagg, Inc +4F4000-4F4FFF (base 16) WiTagg, Inc + 1045 Linda Vista Avenue + Mountain View CA 94043 + US + +70-B3-D5 (hex) Lazer Safe Pty Ltd +63B000-63BFFF (base 16) Lazer Safe Pty Ltd + 27 Action Road + Perth WA 6090 + AU + +70-B3-D5 (hex) Power Electronics Espana, S.L. +431000-431FFF (base 16) Power Electronics Espana, S.L. + C/ Leonardo Da Vinci, 24-26 + Paterna Valencia 46980 + ES + +70-B3-D5 (hex) PA CONSULTING SERVICES +0A6000-0A6FFF (base 16) PA CONSULTING SERVICES + CAMBRIDGE TECH CENTRE + MELBOURN HERTFORDSHIRE SG8 6DP + GB + +70-B3-D5 (hex) KOMSIS ELEKTRONIK SISTEMLERI SAN. TIC. LTD.STI +9CA000-9CAFFF (base 16) KOMSIS ELEKTRONIK SISTEMLERI SAN. TIC. LTD.STI + MEVLANA MAH. BATTAL SOK. NO:4 + ISTANBUL SANCAKTEPE 34791 + TR + +70-B3-D5 (hex) Thales Nederland BV +324000-324FFF (base 16) Thales Nederland BV + PO Box 42 + Hengelo OV 7554 PA + NL + +70-B3-D5 (hex) Parent Power +361000-361FFF (base 16) Parent Power + 35 Garland Way + Trigg Western Australia 6029 + AU + +70-B3-D5 (hex) Cityntel OU +589000-589FFF (base 16) Cityntel OU + Akadeemia tee 21/1 + Tallinn Harjumaa 12618 + EE + +70-B3-D5 (hex) DELTA TAU DATA SYSTEMS, INC. +231000-231FFF (base 16) DELTA TAU DATA SYSTEMS, INC. + 21314 LASSEN STREET + CHATSWORTH CALIFORNIA 91311 + US + +70-B3-D5 (hex) JK DEVICE CORPORATION +4DC000-4DCFFF (base 16) JK DEVICE CORPORATION + RYOGOKU 4-35-1-304 + SUMIDA-KU TOKYO 1300026 + JP + +70-B3-D5 (hex) Plazma-T +4BB000-4BBFFF (base 16) Plazma-T + Fryazevskaya str, 10 + Moscow Moscow 111396 + RU + +70-B3-D5 (hex) Dalcnet srl +CE3000-CE3FFF (base 16) Dalcnet srl + Via Meucci 35 + Brendola Vicenza 36040 + IT + +70-B3-D5 (hex) Manvish eTech Pvt. Ltd. +F78000-F78FFF (base 16) Manvish eTech Pvt. Ltd. + No. 78, Elephant Rock Road + Bangalore Karnataka 560011 + IN + +70-B3-D5 (hex) Nidec Avtron Automation Corp +4DF000-4DFFFF (base 16) Nidec Avtron Automation Corp + 8901 East Pleasant Valley Rd + Independence Ohio 44131 + US + +70-B3-D5 (hex) AML +DF2000-DF2FFF (base 16) AML + 2190 Regal Parkway + Euless TX 76040 + US + +70-B3-D5 (hex) North Star Bestech Co., +421000-421FFF (base 16) North Star Bestech Co., + 203,e-spce b/d, digital-ro 27-gil, guro-gu + seoul guro-gu 152-789 + KR + +70-B3-D5 (hex) CJSC «INTERSET» +811000-811FFF (base 16) CJSC «INTERSET» + 117292, Moscow, Nakhimovsky prospekt 52/27, office B + Moscow Moscow 117292 + RU + +70-B3-D5 (hex) Enovative Networks, Inc. +6DA000-6DAFFF (base 16) Enovative Networks, Inc. + 1901 Central Drive + Bedford TX 76021 + US + +70-B3-D5 (hex) Kwant Controls BV +74C000-74CFFF (base 16) Kwant Controls BV + Voltastraat 3 + Sneek Select Your State or Province 8606 JW + NL + +70-B3-D5 (hex) Dataforth Corporation +6FA000-6FAFFF (base 16) Dataforth Corporation + 3331 E. Hemisphere Loop + Tucson AZ 85706 + US + +70-B3-D5 (hex) Signal Processing Devices Sweden AB +9BD000-9BDFFF (base 16) Signal Processing Devices Sweden AB + Teknikringen 6 + Linköping SE-58330 + SE + +70-B3-D5 (hex) ABB SPA - DMPC +6E0000-6E0FFF (base 16) ABB SPA - DMPC + VIA ALBARETO 35 + GENOVA ITALY 16153 + IT + +70-B3-D5 (hex) Stellwerk GmbH +600000-600FFF (base 16) Stellwerk GmbH + Am Saegewerk 3 + Baienfurt BW 88255 + DE + +70-B3-D5 (hex) Peek Traffic +875000-875FFF (base 16) Peek Traffic + 2906 Corporate Way + Palmetto FL 34235 + US + +70-B3-D5 (hex) Communication Technology Ltd. +9D3000-9D3FFF (base 16) Communication Technology Ltd. + 11F,No.166, Jian 1th Rd.,Jhonghe Dist. + New Taipei 23511 + TW + +70-B3-D5 (hex) Mistral Solutions Pvt. LTD +500000-500FFF (base 16) Mistral Solutions Pvt. LTD + No. 60 Adarsh Regent 100 Ft Ring Road + Bangalore Karnataka 560071 + IN + +70-B3-D5 (hex) Hanshin Electronics +F72000-F72FFF (base 16) Hanshin Electronics + Namhangnam-Ro 45, Yeongdo-Gu, Busan, Korea + Busan N/C 606816 + KR + +70-B3-D5 (hex) serva transport systems GmbH +46F000-46FFFF (base 16) serva transport systems GmbH + Gut Sossau 31 + Grabenstaett Bayern 83355 + DE + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +5C8000-5C8FFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) Bentec GmbH Drilling & Oilfield Systems +285000-285FFF (base 16) Bentec GmbH Drilling & Oilfield Systems + Deilmannstraße 1 + Bad Bentheim Lower Saxony 48455 + DE + +70-B3-D5 (hex) ESII +EC6000-EC6FFF (base 16) ESII + 2 Rue de la Prade + LAVERUNE LR 34880 + FR + +70-B3-D5 (hex) CertUsus GmbH +665000-665FFF (base 16) CertUsus GmbH + Fidlerstrasse 4 + Ermatingen Thurgau 8272 + CH + +70-B3-D5 (hex) Contineo s.r.o. +D46000-D46FFF (base 16) Contineo s.r.o. + Jiskrova 4 + Košice - 040 01 + SK + +70-B3-D5 (hex) Zhejiang Wellsun Electric Meter Co.,Ltd +AE3000-AE3FFF (base 16) Zhejiang Wellsun Electric Meter Co.,Ltd + No 189 East Xixia Road + Taizhou Zhejiang 317200 + CN + +70-B3-D5 (hex) Gridless Power Corperation +EA3000-EA3FFF (base 16) Gridless Power Corperation + 13 Fern Ave + Collingswood New Jersey 08108 + US + +70-B3-D5 (hex) AeroVision Avionics, Inc. +7F1000-7F1FFF (base 16) AeroVision Avionics, Inc. + 2F, No.30, R&D Rd. II, + Hsinchu City Hsinchu City 30076 + TW + +70-B3-D5 (hex) DAVE SRL +63A000-63AFFF (base 16) DAVE SRL + VIA TALPONEDO 29/A + PORCIA PORDENONE 330850 + IT + +70-B3-D5 (hex) Tieto Sweden AB +C9B000-C9BFFF (base 16) Tieto Sweden AB + Kanikenäsbanken 12 + Karlstad Karlstad 65115 + SE + +70-B3-D5 (hex) XAVi Technologies Corp. +C03000-C03FFF (base 16) XAVi Technologies Corp. + 9F., No129, Xingde RD.,Sanchong Dist., + New Taipei Taiwan 24158 + TW + +70-B3-D5 (hex) BroadSoft Inc +E95000-E95FFF (base 16) BroadSoft Inc + 550 S Winchester Blvd + San Jose CA 95128 + US + +70-B3-D5 (hex) Teuco Guzzini +2D5000-2D5FFF (base 16) Teuco Guzzini + Via V. Guzzini, 2 + Montelupone Macerata 62010 + IT + +70-B3-D5 (hex) Innominds Software Private Limited +DE7000-DE7FFF (base 16) Innominds Software Private Limited + Sy No 109,110,111/2, Q City, 6th Floor, + Hyderabad Telangana 500032 + IN + +70-B3-D5 (hex) CRAVIS CO., LIMITED +7EF000-7EFFFF (base 16) CRAVIS CO., LIMITED + Room 11, 7/F., Metro Centre, Phase 1 No.32 + Lam Hing Street Kowloon Bay 0000 + HK + +70-B3-D5 (hex) Elektronik Art +B9B000-B9BFFF (base 16) Elektronik Art + 80 Melgiewska Str. + Lublin Lublin 20234 + PL + +70-B3-D5 (hex) Mesh Motion Inc +CF3000-CF3FFF (base 16) Mesh Motion Inc + 242 Stanford Ave + Kensington California 94708 + US + +70-B3-D5 (hex) Molekuler Goruntuleme A.S. +7CD000-7CDFFF (base 16) Molekuler Goruntuleme A.S. + Tubitak-MAM, TEKSEB + Kocaeli Kocaeli 41470 + TR + +70-B3-D5 (hex) Nke +E75000-E75FFF (base 16) Nke + Rue Gutenberg + Hennebont Brittany 56700 + FR + +70-B3-D5 (hex) UNISOR MULTISYSTEMS LTD +05F000-05FFFF (base 16) UNISOR MULTISYSTEMS LTD + HAYETZIRA 6 ST + NETANYA ISRAEL 4250578 + IL + +70-B3-D5 (hex) MEIDEN SYSTEM SOLUTIONS +EFE000-EFEFFF (base 16) MEIDEN SYSTEM SOLUTIONS + 515 + NUMAZU SHIZUOKA 410-8588 + JP + +70-B3-D5 (hex) TATTILE SRL +412000-412FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Avant Technologies +097000-097FFF (base 16) Avant Technologies + P.O. Box 9359 + Caguas Puerto Rico 00726 + PR + +70-B3-D5 (hex) GD Mission Systems +DAD000-DADFFF (base 16) GD Mission Systems + 8220 E. Roosevelt St. + Scottsdale AZ 85257 + US + +70-B3-D5 (hex) Kitron UAB +182000-182FFF (base 16) Kitron UAB + Taikos pr. 151 + Kaunas Kaunas LT-52119 + LT + +70-B3-D5 (hex) KYS,INC +5EA000-5EAFFF (base 16) KYS,INC + C-605 Digital Empire Bldg + Yeongtong-gu Suwon-si, Gyoenggi-do 443-702 + KR + +70-B3-D5 (hex) SENSEON Corporation +6F8000-6F8FFF (base 16) SENSEON Corporation + 5-23-31 Mori Isogo-Ku + Yokohama Kanagawa 235-0023 + JP + +70-B3-D5 (hex) inomed Medizintechnik GmbH +092000-092FFF (base 16) inomed Medizintechnik GmbH + Im Hausgruen 29 + Emmendingen Baden Württemberg 79312 + DE + +70-B3-D5 (hex) Fresh Idea Factory BV +35D000-35DFFF (base 16) Fresh Idea Factory BV + Torenmolenlaan 67 + Lochem Nederland - Nederlands 7241VL + NL + +70-B3-D5 (hex) HMicro Inc +1A1000-1A1FFF (base 16) HMicro Inc + 39355 California St., Suite 303 + Fremont California 94538 + US + +70-B3-D5 (hex) BroadSoft Inc +7B3000-7B3FFF (base 16) BroadSoft Inc + 550 S Winchester Blvd + San Jose CA 95128 + US + +70-B3-D5 (hex) RM Michaelides Software & Elektronik GmbH +062000-062FFF (base 16) RM Michaelides Software & Elektronik GmbH + Donaustrasse 14 + Fulda Hessen 36043 + + +70-B3-D5 (hex) JungwooEng Co., Ltd +B8D000-B8DFFF (base 16) JungwooEng Co., Ltd + #864-5, Gwanyang2-dong, Dongan-gu + Anyang-si Gyeonggi-do 431-804 + KR + +70-B3-D5 (hex) Automata GmbH & Co. KG +57C000-57CFFF (base 16) Automata GmbH & Co. KG + Gewerbering 5 + Ried Bavaria 86510 + DE + +70-B3-D5 (hex) Martec S.p.A. +1F5000-1F5FFF (base 16) Martec S.p.A. + Via dell'Industria 1/3 + Vignate Milano 20060 + IT + +70-B3-D5 (hex) DiTEST Fahrzeugdiagnose GmbH +112000-112FFF (base 16) DiTEST Fahrzeugdiagnose GmbH + Alte Poststraße 152 + Graz Steiermark 8020 + AT + +70-B3-D5 (hex) Esource Srl +205000-205FFF (base 16) Esource Srl + via del Caravaggio 3 + Milano Mi 20144 + IT + +70-B3-D5 (hex) IBM Research GmbH +708000-708FFF (base 16) IBM Research GmbH + Saeumerstrasse 4 + Rueschlikon ZH 8803 + CH + +70-B3-D5 (hex) Tokyo Communication Equipment MFG Co.,ltd. +BEC000-BECFFF (base 16) Tokyo Communication Equipment MFG Co.,ltd. + 3-8-13 + Minato-ku Tokyo 1080074 + JP + +70-B3-D5 (hex) Robot Pub Group +85C000-85CFFF (base 16) Robot Pub Group + 4 Gleneagles Court + Wakefield UK WF6 1WW + GB + +70-B3-D5 (hex) Elsuhd Net Ltd Co. +025000-025FFF (base 16) Elsuhd Net Ltd Co. + Karrada dakhil-Q 909- St.20-Building 74 + Karrada Baghdad 10001 + IQ + +70-B3-D5 (hex) Simple Works, Inc. +AA0000-AA0FFF (base 16) Simple Works, Inc. + PO Box 345 + Libertyville Illinois 60048 + US + +70-B3-D5 (hex) AML +709000-709FFF (base 16) AML + 2190 Regal Parkway + Euless TX 76040 + US + +70-B3-D5 (hex) ePOINT Embedded Computing Limited +B8C000-B8CFFF (base 16) ePOINT Embedded Computing Limited + Williamton House + Culross Fife KY12 8HL + GB + +70-B3-D5 (hex) Telink Semiconductor CO, Limtied, Taiwan +058000-058FFF (base 16) Telink Semiconductor CO, Limtied, Taiwan + Room 1050, 10F, Bld H, YuanQu St. + Taipei Taiwan 11503 + TW + +70-B3-D5 (hex) LandmarkTech Systems Technology Co.,Ltd. +755000-755FFF (base 16) LandmarkTech Systems Technology Co.,Ltd. + Room221, Building #29, No.368 Zhangjiang Rd., + Shanghai 201210 + CN + +70-B3-D5 (hex) AeroVision Avionics, Inc. +956000-956FFF (base 16) AeroVision Avionics, Inc. + 2F, No.30, R&D. II, Science Park, + Hsinchu City Taiwan 30076 + TW + +70-B3-D5 (hex) Qingdao Haitian Weiye Automation Control System Co., Ltd +54D000-54DFFF (base 16) Qingdao Haitian Weiye Automation Control System Co., Ltd + D&D Wealth Building + Qingdao Shandong 266000 + CN + +70-B3-D5 (hex) octoScope +EF3000-EF3FFF (base 16) octoScope + 305 Foster Street + Littleton Massachusetts 01460 + US + +70-B3-D5 (hex) 5-D Systems, Inc. +BDA000-BDAFFF (base 16) 5-D Systems, Inc. + 1 Chisholm Trail + Round Rock TX 78681 + US + +70-B3-D5 (hex) Sunrise Systems Electronics Co. Inc. +BBE000-BBEFFF (base 16) Sunrise Systems Electronics Co. Inc. + 720 Washington street + Pembroke MA 02359 + US + +70-B3-D5 (hex) GNF +751000-751FFF (base 16) GNF + 10675 John Jay Hopkins Drive + San Diego CA 92121 + US + +70-B3-D5 (hex) Procon Electronics Pty Ltd +CBC000-CBCFFF (base 16) Procon Electronics Pty Ltd + P O Box 164 + Seven Hills NSW 1730 + AU + +70-B3-D5 (hex) Secuinfo Co. Ltd +B08000-B08FFF (base 16) Secuinfo Co. Ltd + 1411, Kranz Techno, 5442-1 + Seongnam-si Gyeonggi-do 462-729 + KR + +70-B3-D5 (hex) INCAA Computers +587000-587FFF (base 16) INCAA Computers + Po Box 722 + Apeldoorn Gelderland 7300 AS + NL + +70-B3-D5 (hex) Intercore GmbH +A15000-A15FFF (base 16) Intercore GmbH + Oberlandstrasse 13-14 + Berlin 12099 + DE + +70-B3-D5 (hex) ICP NewTech Ltd +E4A000-E4AFFF (base 16) ICP NewTech Ltd + Kilbrittain + Bandon Cork WLF-17-68G + IE + +70-B3-D5 (hex) Quasonix, LLC +23C000-23CFFF (base 16) Quasonix, LLC + 6025 Schumacher Park Dr + West Chester Ohio 45069 + US + +70-B3-D5 (hex) Atessa, Inc. +7E7000-7E7FFF (base 16) Atessa, Inc. + 5000 Hopyard Rd. + Pleasanton CA 94588 + US + +70-B3-D5 (hex) GHL Systems Berhad +ADD000-ADDFFF (base 16) GHL Systems Berhad + Unit L8 C-G-15, Block C, + Bandar Sri Damansara Kuala Lumpur 52200 + MY + +70-B3-D5 (hex) Exfrontier Co., Ltd. +E74000-E74FFF (base 16) Exfrontier Co., Ltd. + 5-27 Shinano-Cho + Seto-City Aichi 480-1207 + JP + +70-B3-D5 (hex) NETA Elektronik AS +C78000-C78FFF (base 16) NETA Elektronik AS + Yukari Dudullu Organize Sanayi Bolgesi + Istanbul - 34775 + TR + +70-B3-D5 (hex) Farmobile +5A8000-5A8FFF (base 16) Farmobile + 18132 Melrose Dr. + Bucyrus KS 66013 + + +70-B3-D5 (hex) Nautel Limted +EB0000-EB0FFF (base 16) Nautel Limted + 10089 Peggy's Cove Road + Hackett's Cove Nova Scotia B3Z 3J4 + CA + +70-B3-D5 (hex) Olssen +E08000-E08FFF (base 16) Olssen + Schrank 9 + Hardinxveld-Giessendam Zuid Holland 3371kj + NL + +70-B3-D5 (hex) YotaScope Technologies Co., Ltd. +D47000-D47FFF (base 16) YotaScope Technologies Co., Ltd. + 3F, No. 7-1, Jhongsing Road., + New Taipei City 23678 + TW + +70-B3-D5 (hex) WPGSYS Pte Ltd +D86000-D86FFF (base 16) WPGSYS Pte Ltd + 5 Harper Road #04-01 + 369673 + SG + +70-B3-D5 (hex) ambiHome GmbH +A0B000-A0BFFF (base 16) ambiHome GmbH + Theaterstrasse 19 + Aachen NRW 52062 + + +70-B3-D5 (hex) ELOMAC Elektronik GmbH +3DE000-3DEFFF (base 16) ELOMAC Elektronik GmbH + Heinrich-Vogl-Str. 14 + Ebersberg Bayern 85560 + DE + +70-B3-D5 (hex) Cari Electronic +AE9000-AE9FFF (base 16) Cari Electronic + 8 rue olivier de Serres + Valence Drome 26958 + FR + +70-B3-D5 (hex) XV360 Optical Information Systems Ltd. +184000-184FFF (base 16) XV360 Optical Information Systems Ltd. + 241, Sean Bldgs. Floor 1, S.Psaila Street + Birkirkara Malta BKR9078 + MT + +70-B3-D5 (hex) INRADIOS GmbH +6B6000-6B6FFF (base 16) INRADIOS GmbH + Nossener Bruecke 12 + Dresden SAX 01187 + DE + +70-B3-D5 (hex) Wanco Inc +0AA000-0AAFFF (base 16) Wanco Inc + 5870 Tennyson St + Arvada CO 80003 + US + +70-B3-D5 (hex) Solar Network & Partners +EDD000-EDDFFF (base 16) Solar Network & Partners + Corneliusstr. 90 + Geilenkirchen NRW 52511 + DE + +00-1B-C5 (hex) inomatic GmbH +0C3000-0C3FFF (base 16) inomatic GmbH + + Nordhorn 48513 + DE + +00-1B-C5 (hex) YESpay International Ltd +0BE000-0BEFFF (base 16) YESpay International Ltd + Checknet House + Barnet Hertfordshire EN4 8QZ + GB + +00-1B-C5 (hex) Hangzhou Zhiping Technology Co., Ltd. +0A1000-0A1FFF (base 16) Hangzhou Zhiping Technology Co., Ltd. + Room 619, Science and technology square, East software park, + Hangzhou Zhejiang 310012 + CN + +00-1B-C5 (hex) Hettich Benelux +0A2000-0A2FFF (base 16) Hettich Benelux + de Aaldor 9 + Geldermalsen Gelderland 4191PC + NL + +00-1B-C5 (hex) ENTE Sp. z o.o. +09F000-09FFFF (base 16) ENTE Sp. z o.o. + ul. Gaudiego 7 + Gliwice Śląskie 44-100 + PL + +00-1B-C5 (hex) Shenzhen Guang Lian Zhi Tong Limited +09A000-09AFFF (base 16) Shenzhen Guang Lian Zhi Tong Limited + Room 2411, Block E, Xi hai ming zhu + Shenzhen Guangdong 518000 + CN + +00-1B-C5 (hex) PREVAC sp. z o.o. +095000-095FFF (base 16) PREVAC sp. z o.o. + ul. Raciborska 61 + 44-362 Rogow, Silesia + PL + +00-1B-C5 (hex) Topicon +08A000-08AFFF (base 16) Topicon + Room 201, 2F, Lee Loong Building + Central + HK + +00-1B-C5 (hex) DIWEL +083000-083FFF (base 16) DIWEL + 80 avenue des buttes de coesmes + RENNES 35700 + FR + +00-1B-C5 (hex) TGS Geophysical Company (UK) Limited +082000-082FFF (base 16) TGS Geophysical Company (UK) Limited + Millbank House + Surbiton KT6 6AP + GB + +00-1B-C5 (hex) Momentum Data Systems +077000-077FFF (base 16) Momentum Data Systems + 5432 Bolsa Ave + Huntington Beach California 92649 + US + +00-1B-C5 (hex) Ohio Semitronics, Inc. +072000-072FFF (base 16) Ohio Semitronics, Inc. + 4242 Reynolds Dr + Hilliard Ohio 43026 + US + +00-1B-C5 (hex) Kitron GmbH +075000-075FFF (base 16) Kitron GmbH + Lessingstr. 24 + Großbettlingen Baden-Württemberg 72663 + DE + +00-1B-C5 (hex) HCS KABLOLAMA SISTEMLERI SAN. ve TIC.A.S. +068000-068FFF (base 16) HCS KABLOLAMA SISTEMLERI SAN. ve TIC.A.S. + Turgutreis Mah. Barbaros Cad. + Esenler / ISTANBUL 34235 + TR + +00-1B-C5 (hex) ENSTECH +060000-060FFF (base 16) ENSTECH + Sunil Technopia 802, #440 + Seongnam-City South Korea / Kyunggi-do 462-120 + KR + +00-1B-C5 (hex) Suretrak Global Pty Ltd +05C000-05CFFF (base 16) Suretrak Global Pty Ltd + PO Box 7075 + Wetherill Park NSW 2164 + AU + +00-1B-C5 (hex) Mitsubishi Electric India PVT. LTD +04E000-04EFFF (base 16) Mitsubishi Electric India PVT. LTD + Emerald House, EL-3 + Pune Maharashtra 411026 + IN + +00-1B-C5 (hex) Orbital Systems, Ltd. +04F000-04FFFF (base 16) Orbital Systems, Ltd. + 3807 Carbon Rd. + Irving TEXAS 75038 + US + +00-1B-C5 (hex) Certis Technology International Pte Ltd +04A000-04AFFF (base 16) Certis Technology International Pte Ltd + Certis CISCO Centre + 409179 409179 + SG + +00-1B-C5 (hex) Silicon Controls +04B000-04BFFF (base 16) Silicon Controls + Unit 14A + Macqaurie Park NSW 2113 + AU + +00-1B-C5 (hex) GÉANT +046000-046FFF (base 16) GÉANT + Singel 468D + Amsterdam Noord-Holland 1017AW + NL + +00-1B-C5 (hex) Xiphos Systems Corp. +03C000-03CFFF (base 16) Xiphos Systems Corp. + Suite 500 + Montreal QC H2W 1Y5 + CA + +00-1B-C5 (hex) rioxo GmbH +03D000-03DFFF (base 16) rioxo GmbH + Im Grund 15 + Baden-Dättwil AG 5405 + CH + +00-1B-C5 (hex) Promixis, LLC +03B000-03BFFF (base 16) Promixis, LLC + 211 Edenberry Avenue + Jupiter FL 33458 + US + +00-1B-C5 (hex) LOMAR SRL +036000-036FFF (base 16) LOMAR SRL + VIA PETRARCA + FLERO BRESCIA 25020 + IT + +00-1B-C5 (hex) Fibrain Co. Ltd. +02F000-02FFFF (base 16) Fibrain Co. Ltd. + ul. Wspólna 4A + Rzeszów Podkarpacie 35-205 + PL + +00-1B-C5 (hex) DDTRONIK Dariusz Dowgiert +02D000-02DFFF (base 16) DDTRONIK Dariusz Dowgiert + Chabrowa 2 + Czarna Bialostocka Podlaskie 16-020 + PL + +00-1B-C5 (hex) Analytical Instrument Systems, Inc. +02A000-02AFFF (base 16) Analytical Instrument Systems, Inc. + P.O. Box 458 + Flemington New Jersey 08822 + US + +00-1B-C5 (hex) 2 FRANCE MARINE +029000-029FFF (base 16) 2 FRANCE MARINE + 61, route de la Chapelle de Rousse + GAN 64290 + FR + +00-1B-C5 (hex) CAMEA, spol. s r.o. +027000-027FFF (base 16) CAMEA, spol. s r.o. + Korenskeho 25 + Brno 621 00 + CZ + +00-1B-C5 (hex) ANNECY ELECTRONIQUE SAS +024000-024FFF (base 16) ANNECY ELECTRONIQUE SAS + Parc Altaīs, 1 Rue Callisto + CHAVANOD FRANCE 74650 + FR + +00-1B-C5 (hex) MAGO di Della Mora Walter +023000-023FFF (base 16) MAGO di Della Mora Walter + Via S.Vidotto 2/3 + Codroipo fr. Biauzzo Udine (UD) 33033 + IT + +00-1B-C5 (hex) Private +01E000-01EFFF (base 16) Private + +00-1B-C5 (hex) Coolit Systems, Inc. +01C000-01CFFF (base 16) Coolit Systems, Inc. + 3920 - 29th St. N.E. + Calgary AB T1Y6B6 + CA + +00-1B-C5 (hex) Commonwealth Scientific and Industrial Research Organisation +01B000-01BFFF (base 16) Commonwealth Scientific and Industrial Research Organisation + PO Box 883 + Kenmore Queensland 4069 + AU + +00-1B-C5 (hex) cPacket Networks +017000-017FFF (base 16) cPacket Networks + 2061 Landings Drive + Mountain View CA 94043 + US + +00-1B-C5 (hex) Tokyo Cosmos Electric, Inc. +012000-012FFF (base 16) Tokyo Cosmos Electric, Inc. + 2-268 Sobudai + Zama Kanagawa 252-8550 + JP + +00-1B-C5 (hex) MicroSigns Technologies Inc +003000-003FFF (base 16) MicroSigns Technologies Inc + 1350 Mazurette + Montreal QC H1V 2C8 + CA + +70-B3-D5 (hex) KMtronic ltd +299000-299FFF (base 16) KMtronic ltd + Dobri Czintulov 28A str. + Gorna Oryahovica VT 5100 + BG + +70-B3-D5 (hex) Grossenbacher Systeme AG +3EB000-3EBFFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) Kyoto Denkiki +F0F000-F0FFFF (base 16) Kyoto Denkiki + makishima 16 19-1 + Uji 6110041 + JP + +70-B3-D5 (hex) Copious Imaging LLC +4E8000-4E8FFF (base 16) Copious Imaging LLC + 83 Hartwell Ave, Suite 150 + Lexington MA 02421 + US + +70-B3-D5 (hex) APEX Stabilizations GmbH +A52000-A52FFF (base 16) APEX Stabilizations GmbH + Künstlergasse 11, 4. OG, Top 2 + Vienna 1150 + AT + +70-B3-D5 (hex) NEOPATH INTEGRATED SYSTEMS LTDA +067000-067FFF (base 16) NEOPATH INTEGRATED SYSTEMS LTDA + Rua Paulo Emídio Barbosa, 485 - sala 302 + Rio de Janeiro Rio de Janeiro 21941-907 + BR + +70-B3-D5 (hex) Waco Giken Co., Ltd. +815000-815FFF (base 16) Waco Giken Co., Ltd. + 1-1-50, Suehiro-Cho, + Tsurumi-Ku, Yokohama 230-0045 + JP + +70-B3-D5 (hex) Monnit Corporation +D16000-D16FFF (base 16) Monnit Corporation + 3400 S West Temple + Salt Lake City 84115 + US + +70-B3-D5 (hex) Harmonic Design GmbH +1F0000-1F0FFF (base 16) Harmonic Design GmbH + Bahnhofstraße 1 + Steinheim 71711 + DE + +70-B3-D5 (hex) hmt telematik GmbH +EC4000-EC4FFF (base 16) hmt telematik GmbH + Grazer Str. 34b + Graz 8045 + AT + +70-B3-D5 (hex) Exsom Computers LLC +4BF000-4BFFFF (base 16) Exsom Computers LLC + Office 3206, The Citadel Tower, Business Bay + Dubai Dubai 72891 + AE + +70-B3-D5 (hex) Piranha EMS Inc. +8CC000-8CCFFF (base 16) Piranha EMS Inc. + 2681 Zanker Road + San Jose CA 95134 + US + +70-B3-D5 (hex) Small Data Garden Oy +568000-568FFF (base 16) Small Data Garden Oy + Paloheimonkatu 2 + Riihimäki 11130 + FI + +70-B3-D5 (hex) Densitron Technologies Ltd +E3C000-E3CFFF (base 16) Densitron Technologies Ltd + 16 South Park + Sevenoaks Kent TN13 1AN + GB + +70-B3-D5 (hex) Shanghai AiGentoo Information Technology Co.,Ltd. +4FF000-4FFFFF (base 16) Shanghai AiGentoo Information Technology Co.,Ltd. + No.309 room 2445 14C?Tanggu Road?Hongkou District + Shanghai 200080 + CN + +70-B3-D5 (hex) GENTEC ELECTRO-OPTICS +CF7000-CF7FFF (base 16) GENTEC ELECTRO-OPTICS + 445 ST-JEAN-BAPTISTE SUITE 160 + Quebec Quebec G2E 5N7 + CA + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +519000-519FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Ossiaco +CB0000-CB0FFF (base 16) Ossiaco + 355 Peel St. + Montreal Quebec H3C2G9 + CA + +70-B3-D5 (hex) Profotech +5AD000-5ADFFF (base 16) Profotech + Volgogradsky prospekt, 42/5 + Moscow 109316 + RU + +70-B3-D5 (hex) A & T Technologies +143000-143FFF (base 16) A & T Technologies + ul. Baumana 57a-31 + Kemerovo 650040 + RU + +70-B3-D5 (hex) INNOVATIVE CONCEPTS AND DESIGN LLC +DAF000-DAFFFF (base 16) INNOVATIVE CONCEPTS AND DESIGN LLC + 107 Trumbull Street, Bldg F8 + Elizabeth NJ 07206 + US + +70-B3-D5 (hex) Contec Americas Inc. +363000-363FFF (base 16) Contec Americas Inc. + 3991 Sarno Rd + Melbourne FL 32934 + US + +70-B3-D5 (hex) GABO +757000-757FFF (base 16) GABO + Gyeonggido + Ansan 15617 + KR + +70-B3-D5 (hex) Pro-Digital Projetos Eletronicos Ltda +56D000-56DFFF (base 16) Pro-Digital Projetos Eletronicos Ltda + RUA SENADOR SARAIVA 200 + CURITIBA PR 80510300 + BR + +70-B3-D5 (hex) Season Electronics Ltd +67E000-67EFFF (base 16) Season Electronics Ltd + 600 Nest Business Park + Havant Hampshire PO9 5TL + GB + +70-B3-D5 (hex) SUS Corporation +422000-422FFF (base 16) SUS Corporation + 6F, S-patio Bldg. 14-25 Minami-cho, Suruga-ku, + Shizuoka city, Shizuoka 422-8067 + JP + +70-B3-D5 (hex) Emporia Renewable Energy Corp +EB8000-EB8FFF (base 16) Emporia Renewable Energy Corp + 7901 Shaffer Pkwy + Littleton CO 80127 + US + +70-B3-D5 (hex) Loma Systems s.r.o. +5EB000-5EBFFF (base 16) Loma Systems s.r.o. + U Lomy 1069 + Dob?any 33441 + CZ + +70-B3-D5 (hex) OOO Research and Production Center Computer Technologies +606000-606FFF (base 16) OOO Research and Production Center Computer Technologies + Komsomolsky avenue, 90-17 + Perm Perm Region 614010 + RU + +70-B3-D5 (hex) GSI GeoSolutions International Ltd +8BC000-8BCFFF (base 16) GSI GeoSolutions International Ltd + Ahornweg 5A + Othmarsingen 5504 + CH + +70-B3-D5 (hex) CorDes, LLC +FA9000-FA9FFF (base 16) CorDes, LLC + 20243 Kentucky Oaks Ct + Ashburn VA 20147 + US + +70-B3-D5 (hex) Yite technology +321000-321FFF (base 16) Yite technology + No. 56, Xiaobei Rd., North Dist + tainan 70448 + TW + +70-B3-D5 (hex) Wartsila Voyage Limited +9D4000-9D4FFF (base 16) Wartsila Voyage Limited + 13-18 City Quay + Dublin 2 D02 ED70 + IE + +70-B3-D5 (hex) Typhon Treatment Systems Ltd +F97000-F97FFF (base 16) Typhon Treatment Systems Ltd + Unit 10, Newton Gate Industrial Estate + Penrith Cumbria CA11 0BF + GB + +70-B3-D5 (hex) Franz Kessler GmbH +C44000-C44FFF (base 16) Franz Kessler GmbH + Franz-Kessler-Str. 2 + Bad Buchau Baden-Wuerttemberg 88422 + DE + +70-B3-D5 (hex) WIKA Alexander Wiegand SE & Co. KG +97B000-97BFFF (base 16) WIKA Alexander Wiegand SE & Co. KG + Alexander-Wiegand-Strasse 30 + Klingenberg 63911 + DE + +70-B3-D5 (hex) Conserv Solutions +310000-310FFF (base 16) Conserv Solutions + 2222 2nd Ave N. Suite 204 + Birmingham AL 35203 + US + +70-B3-D5 (hex) Guan Show Technologe Co., Ltd. +03E000-03EFFF (base 16) Guan Show Technologe Co., Ltd. + No.127, Jianguo 1st Rd., Lingya Dist. + Kaohsiung City 802 + TW + +70-B3-D5 (hex) RCH Vietnam Limited Liability Company +DA9000-DA9FFF (base 16) RCH Vietnam Limited Liability Company + Workshop F.01B-2, Lot No. F.01B Long Hau + Ho Chi Minh City Ho Chi Minh 70000 + VN + +70-B3-D5 (hex) OOO NTC Rotek +62C000-62CFFF (base 16) OOO NTC Rotek + Malaya Krasnoselskaya str., build. 2/8, block 7, floor 4, dep. II, room 5 + Moscow Moscow 107140 + RU + +70-B3-D5 (hex) SHANDHAI LANDLEAF ARCHITECTURE TECHNOLOGY CO.,LTD +B5D000-B5DFFF (base 16) SHANDHAI LANDLEAF ARCHITECTURE TECHNOLOGY CO.,LTD + Real Power Innovation Center tower NO.2,7Floor,No.51 Zhengxue Road,Yangpu District + SHANGHAI SHANGHAI 200433 + CN + +70-B3-D5 (hex) ITG.CO.LTD +281000-281FFF (base 16) ITG.CO.LTD + 617, anyang Megavally, 268, Hagui-ro, Dongan-gu + Anyang 14056 + KR + +70-B3-D5 (hex) Utrend Technology (Shanghai) Co., Ltd +7C6000-7C6FFF (base 16) Utrend Technology (Shanghai) Co., Ltd + Building #3-P, No 780 Cailun Road + Shanghai Shanghai 201203 + CN + +70-B3-D5 (hex) Olympus NDT Canada +5BB000-5BBFFF (base 16) Olympus NDT Canada + 3415 rue Pierre Ardouin + Québec Québec G1P 0B3 + CA + +70-B3-D5 (hex) Dosepack India LLP +2B5000-2B5FFF (base 16) Dosepack India LLP + 429/A,Kalasagar Shopping Hub, Sattadhar Cross Road + Ahmedabad Gujarat 380061 + IN + +70-B3-D5 (hex) Serveron Corporation +FF4000-FF4FFF (base 16) Serveron Corporation + 13550 SW Karl Braun Drive + Beaverton OR 97077 + US + +70-B3-D5 (hex) TIAMA +8BA000-8BAFFF (base 16) TIAMA + ZA des Plattes - 1 Chemin des Plattes + VOURLES 69390 + FR + +70-B3-D5 (hex) IAAN Co., Ltd +67F000-67FFFF (base 16) IAAN Co., Ltd + 4F 261 Yangjae-dong, Seocho-gu + Seoul 06777 + KR + +70-B3-D5 (hex) Stealth Communications +86A000-86AFFF (base 16) Stealth Communications + 1 Penn Plaza, Suite 6308 + New York NY 10119 + US + +70-B3-D5 (hex) Pneumax S.p.A. +A60000-A60FFF (base 16) Pneumax S.p.A. + Via Cascina Barbellina 10 + Lurano 24050 + IT + +70-B3-D5 (hex) Guan Show Technologe Co., Ltd. +F80000-F80FFF (base 16) Guan Show Technologe Co., Ltd. + No.127, Jianguo 1st Rd., Lingya Dist. + Kaohsiung City 802 + TW + +70-B3-D5 (hex) ENLESS WIRELESS +4FD000-4FDFFF (base 16) ENLESS WIRELESS + 45 TER AVENUE DE VERDUN + BRUGES 33520 + FR + +70-B3-D5 (hex) Newtec A/S +18F000-18FFFF (base 16) Newtec A/S + Stærmosegårdsvej 18 + Odense SV Region Syd 5230 + DK + +70-B3-D5 (hex) AUDIO VISUAL DIGITAL SYSTEMS +A7F000-A7FFFF (base 16) AUDIO VISUAL DIGITAL SYSTEMS + PLOT NO.180 PHASE V SECTOR56, HSIIDC I.E KUNDLI SONEPAT + SONEPAT HARYANA 131028 + IN + +70-B3-D5 (hex) DEUTA-WERKE GmbH +1BF000-1BFFFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) DONG IL VISION Co., Ltd. +038000-038FFF (base 16) DONG IL VISION Co., Ltd. + #9 Ftrek tower, 11-25, Simindaero 327 beongil,Dongan-gu + Anyangi-Si Gyeonggi-Do 14055 + KR + +70-B3-D5 (hex) Cetitec GmbH +B36000-B36FFF (base 16) Cetitec GmbH + Mannheimer Strasse 17 + Pforzheim 75179 + DE + +70-B3-D5 (hex) Kamacho Scale Co., Ltd. +385000-385FFF (base 16) Kamacho Scale Co., Ltd. + 2246 Mure + Takamatsu-shi Kagawa-ken 761-0196 + JP + +70-B3-D5 (hex) Vessel Technology Ltd +44D000-44DFFF (base 16) Vessel Technology Ltd + Banchory Business Centre, Burn O'Bennie Road + Banchory Aberdeenshire AB31 5ZU + GB + +70-B3-D5 (hex) Munters +FA8000-FA8FFF (base 16) Munters + Hasivim 18 + Pethch Tikva Israel 4959376 + IL + +70-B3-D5 (hex) Visual Robotics +0F4000-0F4FFF (base 16) Visual Robotics + 38 Irving Rd + Eugene OR 97404 + US + +70-B3-D5 (hex) TangRen C&S CO., Ltd +3FC000-3FCFFF (base 16) TangRen C&S CO., Ltd + 3a-5d, Tingwei Daxia, Tingwei Industrial Park, No. 6, Liufang Road, Bao'an District + Shenzhen Guangdong 518052 + CN + +70-B3-D5 (hex) TEX COMPUTER SRL +6C2000-6C2FFF (base 16) TEX COMPUTER SRL + VIA MERCADANTE 35 + CATTOLICA RIMINI 47841 + IT + +70-B3-D5 (hex) LOTES TM OOO +EA5000-EA5FFF (base 16) LOTES TM OOO + Barklaya 22, str.1 + Moscow 121309 + RU + +70-B3-D5 (hex) Yi An Electronics Co., Ltd +F28000-F28FFF (base 16) Yi An Electronics Co., Ltd + 5F.-2, No. 81, Sec. 1, Xintai 5th Rd., Xizhi Dist + New Taipei City 22101 + TW + +70-B3-D5 (hex) System West dba ICS Electronics +E06000-E06FFF (base 16) System West dba ICS Electronics + 7034 Commerce Circle Suite A + Pleasanton CA 94588 + US + +70-B3-D5 (hex) Nevotek +358000-358FFF (base 16) Nevotek + 5201 Great America Pkwy ste 320 + Santa Clara CA 95054 + US + +70-B3-D5 (hex) Arctos Showlasertechnik GmbH +D02000-D02FFF (base 16) Arctos Showlasertechnik GmbH + Sägewerkstraße 16 + Saaldorf-Surheim Bavaria 83416 + DE + +70-B3-D5 (hex) Gremesh.com +218000-218FFF (base 16) Gremesh.com + Beursplein 37 + Rotterdam Zuid-Holland 3011 AA + NL + +70-B3-D5 (hex) Peter Huber Kaeltemaschinenbau AG +5B2000-5B2FFF (base 16) Peter Huber Kaeltemaschinenbau AG + Werner-von-Siemens-Str. 1 + Offenburg Ba-Wue 77656 + DE + +70-B3-D5 (hex) Private +FFF000-FFFFFF (base 16) Private + +70-B3-D5 (hex) SENSO2ME +BC0000-BC0FFF (base 16) SENSO2ME + Lange Gasthiuisstraat 29 + ANTWERP Antwerp 2000 + BE + +70-B3-D5 (hex) JLCooper Electronics +8EA000-8EAFFF (base 16) JLCooper Electronics + 142 Arena St + El Segundo CA 90245 + US + +70-B3-D5 (hex) R Cubed Engineering, LLC +C59000-C59FFF (base 16) R Cubed Engineering, LLC + 705 10th Ave W unit 102 + Palmetto 34221 + US + +70-B3-D5 (hex) Rotem Industry LTD +B65000-B65FFF (base 16) Rotem Industry LTD + Rotem Industrial Park + Mishor Rotem D.N. Arava 8680600 + IL + +70-B3-D5 (hex) The Dini Group, La Jolla inc. +83E000-83EFFF (base 16) The Dini Group, La Jolla inc. + 7469 Draper Ave. + La Jolla CA 92037 + US + +70-B3-D5 (hex) Metralight, Inc. +DC1000-DC1FFF (base 16) Metralight, Inc. + 533 Airport Blvd., #400 + Burlingame CA 94010 + US + +70-B3-D5 (hex) Gateview Technologies +A70000-A70FFF (base 16) Gateview Technologies + 104 White St #201 + Wake Forest 27587 + US + +70-B3-D5 (hex) Selex ES Inc. +521000-521FFF (base 16) Selex ES Inc. + 4221 Tudor Lane + Greensboro NC 27410 + US + +70-B3-D5 (hex) Operational Technology Solutions +4D6000-4D6FFF (base 16) Operational Technology Solutions + Level 10 555 Lonsdale Street + Melbourne Victoria 3000 + AU + +70-B3-D5 (hex) Laborie +337000-337FFF (base 16) Laborie + 6415 Northwest Drive, Unit 2 + Mississauga Ontario L4V1X1 + CA + +70-B3-D5 (hex) ENS Engineered Network Systems +983000-983FFF (base 16) ENS Engineered Network Systems + 14451 Ewing Ave. Suite 100 + Burnsville MN 55306 + US + +70-B3-D5 (hex) JSC VIST Group +A8A000-A8AFFF (base 16) JSC VIST Group + Dokuchaev lane, 3, bld. 1, attic, premise 1, room 14 + Moscow 107078 + RU + +70-B3-D5 (hex) Legrand Electric Ltd +093000-093FFF (base 16) Legrand Electric Ltd + Unit 10 Cowley Road + Blyth Northumberland NE24 5TF + GB + +70-B3-D5 (hex) DEUTA-WERKE GmbH +4A4000-4A4FFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) INTERNET PROTOCOLO LOGICA SL +B58000-B58FFF (base 16) INTERNET PROTOCOLO LOGICA SL + Sector Foresta 43, local 26 + Tres Cantos Madrid 28760 + ES + +70-B3-D5 (hex) Sicon srl +D49000-D49FFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) Syscom Instruments SA +BE7000-BE7FFF (base 16) Syscom Instruments SA + industrie 21 + Sainte-Croix 1450 + CH + +70-B3-D5 (hex) AutomationX GmbH +CD7000-CD7FFF (base 16) AutomationX GmbH + Lauzilgasse 13 + Graz Styria 8020 + AT + +70-B3-D5 (hex) Onethinx BV +068000-068FFF (base 16) Onethinx BV + Punterweg 2 + Zwolle OV 8042 PB + NL + +70-B3-D5 (hex) Private +401000-401FFF (base 16) Private + +70-B3-D5 (hex) Alpha ESS Co., Ltd. +7A2000-7A2FFF (base 16) Alpha ESS Co., Ltd. + JiuHua Road 888, Nantong High-Tech Industrial Development Zone, + Nantong Jiangsu 226300 + CN + +70-B3-D5 (hex) NTO IRE-POLUS +6FE000-6FEFFF (base 16) NTO IRE-POLUS + Akademika Vvedenskogo 1/2 + Fryazino 141190 + RU + +70-B3-D5 (hex) microtec Sicherheitstechnik GmbH +DFE000-DFEFFF (base 16) microtec Sicherheitstechnik GmbH + Auf der Langwies 20 + Hünstetten 65510 + DE + +70-B3-D5 (hex) FRESENIUS MEDICAL CARE +4CC000-4CCFFF (base 16) FRESENIUS MEDICAL CARE + 496 So. Abbott Ave + Milpitas CA 95035 + US + +70-B3-D5 (hex) OHASHI ENGINEERING CO.,LTD. +556000-556FFF (base 16) OHASHI ENGINEERING CO.,LTD. + 1-471-8 TOYONODAI + KAZO-CITY SAITAMA 349-1148 + JP + +70-B3-D5 (hex) JIANGSU HORAINTEL CO.,LTD +D8A000-D8AFFF (base 16) JIANGSU HORAINTEL CO.,LTD + 32 Buidling R&D Center, No.99 Chuqiao Road + ZHENJIANG JIANGSU 212009 + CN + +70-B3-D5 (hex) AVA Monitoring AB +31D000-31DFFF (base 16) AVA Monitoring AB + Vädursgatan 6 + Göteborg Västra götaland 412 50 + SE + +70-B3-D5 (hex) PAL Inc. +05B000-05BFFF (base 16) PAL Inc. + 2217-2 Hayashicho + Takamatsu Kagawa 7610301 + JP + +70-B3-D5 (hex) TimeMachines Inc. +5A6000-5A6FFF (base 16) TimeMachines Inc. + 300 S 68th Street Place, Suite 100 + Lincoln NE 68510 + US + +70-B3-D5 (hex) Cobo, Inc. +EAD000-EADFFF (base 16) Cobo, Inc. + 3624 Alta Vista Avenue + Santa Rosa CA 95409 + US + +70-B3-D5 (hex) Discover Battery +6F1000-6F1FFF (base 16) Discover Battery + #4 - 13511 Crestwood Place + Richmond BC v6v 2e9 + CA + +70-B3-D5 (hex) Itronics Ltd +9B7000-9B7FFF (base 16) Itronics Ltd + 8a Triton Dr, Rosedale + Auckland 0632 + NZ + +70-B3-D5 (hex) Tapdn +FDC000-FDCFFF (base 16) Tapdn + 840 Apollo St Suite 100 + El Segundo CA 90245 + US + +70-B3-D5 (hex) Controlled Power Company +BA8000-BA8FFF (base 16) Controlled Power Company + 1955 Stephenston Hwy + Troy MI 48083 + US + +70-B3-D5 (hex) Editech Co., Ltd +79D000-79DFFF (base 16) Editech Co., Ltd + 284, Gongdan-ro + Gunpo-si Gyeonggi-do 15809 + KR + +70-B3-D5 (hex) Talleres de Escoriaza SA +C08000-C08FFF (base 16) Talleres de Escoriaza SA + Barrio Ventas, 35 + Irun Gipuzkoa 20305 + ES + +70-B3-D5 (hex) Gamber Johnson-LLC +DBC000-DBCFFF (base 16) Gamber Johnson-LLC + 3001 Borham Ave + Stevens Point WI 54481 + US + +70-B3-D5 (hex) EXASCEND (Wuhan) Co., Ltd +851000-851FFF (base 16) EXASCEND (Wuhan) Co., Ltd + West 2nd-3rd Floor, No. 2 Building, Guan Nan Industrial Park,Te 1 Hao, Gao Xing 2 Lu,Dong Hu New Technology Development District + Wuhan Hubei 430000 + CN + +70-B3-D5 (hex) Niron systems & Projects +FED000-FEDFFF (base 16) Niron systems & Projects + PO Box 8546 + Netania 4250407 + IL + +70-B3-D5 (hex) Nubewell Networks Pvt Ltd +61B000-61BFFF (base 16) Nubewell Networks Pvt Ltd + 1242, Ground Floor, 4th Main, 4th Cross, BTM 4th stage, 1st Block, Deverachikkanahalli + Bangalore Karnataka 560076 + IN + +70-B3-D5 (hex) Paratec Ltd. +AEC000-AECFFF (base 16) Paratec Ltd. + P.O.Box 3574 + Haifa 3103402 + IL + +70-B3-D5 (hex) Slan +788000-788FFF (base 16) Slan + 11 rue de la Senette + Carrieres sous Poissy 78955 + FR + +70-B3-D5 (hex) EGISTECH CO.,LTD. +603000-603FFF (base 16) EGISTECH CO.,LTD. + 611 2Dong 98, Gasan digital 2-ro + Geumcheon-gu Seoul 08506 + KR + +70-B3-D5 (hex) Nippon Marine Enterprises, Ltd. +533000-533FFF (base 16) Nippon Marine Enterprises, Ltd. + 14-1, Ogawa-cho + Yokosuka Kanagawa 2380004 + JP + +70-B3-D5 (hex) Aethera Technologies +9B9000-9B9FFF (base 16) Aethera Technologies + 63 Crane Lake Drive + Halifax NS B3S 1B5 + CA + +70-B3-D5 (hex) hiSky S.C.S LTD +2E1000-2E1FFF (base 16) hiSky S.C.S LTD + 24 Ammal + Rosh Hain 4809268 + IL + +70-B3-D5 (hex) QuestHouse, Inc. +84B000-84BFFF (base 16) QuestHouse, Inc. + Rm 204, 5 B/D, 20 Techno 1-ro, Yuseong-gu + Daejeon 34016 + KR + +70-B3-D5 (hex) Private +A03000-A03FFF (base 16) Private + +70-B3-D5 (hex) Insitu Inc. +D36000-D36FFF (base 16) Insitu Inc. + 901 E Bingen Point Way + Bingen WA 98605 + US + +70-B3-D5 (hex) Pano0ramic Power +669000-669FFF (base 16) Pano0ramic Power + 15 Atir Yeda + Kfar Saba 4464312 + IL + +00-1B-C5 (hex) Private +0B8000-0B8FFF (base 16) Private + +70-B3-D5 (hex) Dat-Con d.o.o. +CDC000-CDCFFF (base 16) Dat-Con d.o.o. + Cvetlična ulica 52 + Polzela 3313 + SI + +70-B3-D5 (hex) PixelApps s.r.o. +251000-251FFF (base 16) PixelApps s.r.o. + Hošťálkova 633/49 + Praha 6 16900 + CZ + +70-B3-D5 (hex) MICRO DEBUG, Y.K. +020000-020FFF (base 16) MICRO DEBUG, Y.K. + 5-18-15 Oowada-cho + hachiouji Tokyo 192-0045 + JP + +70-B3-D5 (hex) amakidenki +9FD000-9FDFFF (base 16) amakidenki + m.okuyama@amaki.co.jp + higashiyamatoshi tokyo 207-0004 + JP + +70-B3-D5 (hex) OSMOZIS +A9B000-A9BFFF (base 16) OSMOZIS + 7 AVENUE DE L'EUROPE + CLAPIERS LANGUEDOC ROUSSSILLON 34830 + FR + +70-B3-D5 (hex) Project Service S.r.l. +A2D000-A2DFFF (base 16) Project Service S.r.l. + Via Paderno 31/C + Seriate (BG) 24068 + IT + +70-B3-D5 (hex) Avid Controls Inc +447000-447FFF (base 16) Avid Controls Inc + 41261 Park 290 Dr + WALLER TX 77484 + US + +70-B3-D5 (hex) Alcohol Countermeasure Systems +FD0000-FD0FFF (base 16) Alcohol Countermeasure Systems + 60 International Blvd + Toronto Ontario M9W 6J2 + CA + +70-B3-D5 (hex) Applied Silver +239000-239FFF (base 16) Applied Silver + 26254 Eden Landing Road + Hayward CA 94545 + US + +70-B3-D5 (hex) DKI Technology Co., Ltd +D00000-D00FFF (base 16) DKI Technology Co., Ltd + Room #1005, DONGHWA BLDG, 71, Yeouinaru-ro, Yeongdeungpo-gu + Seoul Seoul KR-11 + KR + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +AA5000-AA5FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Fracarro srl +E8C000-E8CFFF (base 16) Fracarro srl + via Cazzaro 3 + Castelfranco Veneto 31033 + IT + +70-B3-D5 (hex) Crown Solar Power Fencing Systems +9D6000-9D6FFF (base 16) Crown Solar Power Fencing Systems + 123/A, Ushodaya Towers Shahpurnagar, Jeedimetla + Hyderabad Telangana 500055 + IN + +70-B3-D5 (hex) Hiber +DBE000-DBEFFF (base 16) Hiber + Keizersgracht 209-sous + Amsterdam Noord-Holland 1016DT + NL + +70-B3-D5 (hex) MEGGITT +1EE000-1EEFFF (base 16) MEGGITT + 14600 MYFORD RD + IRVINE CA 92606 + US + +70-B3-D5 (hex) SET Power Systems GmbH +DAB000-DABFFF (base 16) SET Power Systems GmbH + August Braun Strasse 3 + Wangen Baden Wuerttemberg 88239 + DE + +70-B3-D5 (hex) Prior Scientific Instruments Ltd +A7D000-A7DFFF (base 16) Prior Scientific Instruments Ltd + 3-4 Fielding industrial estate, Fulbourn + Cambridge Cambridgeshire CB21 5ET + GB + +70-B3-D5 (hex) AUTOMATIZACION Y CONECTIVIDAD SA DE CV +59B000-59BFFF (base 16) AUTOMATIZACION Y CONECTIVIDAD SA DE CV + LA GARITA ANDADOR 6 DUPLEX 1 CASA 2 + CDMX TLALPAN 14390 + MX + +70-B3-D5 (hex) Blue Skies Global LLC +1D8000-1D8FFF (base 16) Blue Skies Global LLC + PO Box 796 + Williams Bay WI 53191 + US + +70-B3-D5 (hex) Alcodex Technologies Private Limited +098000-098FFF (base 16) Alcodex Technologies Private Limited + 7/719-B, PLOT 180, Mavelipuram colony, Kakkanad + ernakulam Kerala 682030 + IN + +70-B3-D5 (hex) Digital Media Professionals +BC4000-BC4FFF (base 16) Digital Media Professionals + 16F NakanoCentralParkSouth,4-10-2 Nakano + Nakano-ku Tokyo 164-0001 + JP + +70-B3-D5 (hex) Lightdrop +072000-072FFF (base 16) Lightdrop + Matiční 730/3 + Ostrava 70200 + CZ + +70-B3-D5 (hex) NeurIT s.r.o. +2E9000-2E9FFF (base 16) NeurIT s.r.o. + Husovo náměstí 14 + Hostivice Czech Republic 25301 + CZ + +70-B3-D5 (hex) Shishido Electrostatic, Ltd. +22A000-22AFFF (base 16) Shishido Electrostatic, Ltd. + 4-7-21 Chigasaki-higashi, Tsuzuki-ku + Yokohama Kanagawa Prefecture 224-0033 + JP + +70-B3-D5 (hex) Consarc Corporation +BD6000-BD6FFF (base 16) Consarc Corporation + 100 Indel Ave + Rancocas NJ 08073 + US + +70-B3-D5 (hex) Amber Kinetics Inc +05C000-05CFFF (base 16) Amber Kinetics Inc + 32920 Alvarado-Niles Rd #250 + Union City CA 94587 + US + +70-B3-D5 (hex) Qingdao CNR HITACH Railway Signal&communication co.,ltd +802000-802FFF (base 16) Qingdao CNR HITACH Railway Signal&communication co.,ltd + 231-2 Ruichang Road + Qingdao 266031 + CN + +70-B3-D5 (hex) Zumbach Electronic AG +B10000-B10FFF (base 16) Zumbach Electronic AG + Hauptstrasse 93 + Orpund Bern 2552 + CH + +70-B3-D5 (hex) VTC Digicom +C4C000-C4CFFF (base 16) VTC Digicom + 23 Lac Trung + Ha Noi Ha Noi 100000 + VN + +70-B3-D5 (hex) WICELL TECHNOLOGY +BB0000-BB0FFF (base 16) WICELL TECHNOLOGY + 61 Dien Bien Phu + Ho Chi Minh 700000 + VN + +70-B3-D5 (hex) KOMZ - IZMERENIYA +45B000-45BFFF (base 16) KOMZ - IZMERENIYA + Pravobulachnaya 35/2 + Kazan 420111 + RU + +70-B3-D5 (hex) GoTrustID Inc. +B38000-B38FFF (base 16) GoTrustID Inc. + 800 N. State Street, Suite 402, Dover + County of Kent DE 19901 + US + +70-B3-D5 (hex) Communication Systems Solutions +E0C000-E0CFFF (base 16) Communication Systems Solutions + 6030 S. 58th Street + Lincoln NE 68516 + US + +70-B3-D5 (hex) Private +591000-591FFF (base 16) Private + +70-B3-D5 (hex) Private +376000-376FFF (base 16) Private + +00-1B-C5 (hex) Corporate Systems Engineering +015000-015FFF (base 16) Corporate Systems Engineering + 1215 Brookville Way + Indianapolis IN 46239 + US + +70-B3-D5 (hex) Armstrong International, Inc. +15B000-15BFFF (base 16) Armstrong International, Inc. + 816 Maple Street + Three Rivers MI 49093 + US + +70-B3-D5 (hex) Private +738000-738FFF (base 16) Private + +70-B3-D5 (hex) Ya Batho Trading (Pty) Ltd +AE6000-AE6FFF (base 16) Ya Batho Trading (Pty) Ltd + 9 Estee Ackerman Street + Jet Park Gauteng 1462 + ZA + +70-B3-D5 (hex) MicroElectronics System Co.Ltd +8DA000-8DAFFF (base 16) MicroElectronics System Co.Ltd + 29 uchihata-cho Nishinokyo Nakagyoku + Kyoto City Kyoto-fu 604-8411 + JP + +70-B3-D5 (hex) Private +B71000-B71FFF (base 16) Private + +70-B3-D5 (hex) Engage Technologies +977000-977FFF (base 16) Engage Technologies + 7041 Boone Avenue North + Brooklyn Park MN 55428 + US + +70-B3-D5 (hex) Opti-Sciences, Inc. +338000-338FFF (base 16) Opti-Sciences, Inc. + 8 Winn Ave + Hudson NH 03051 + US + +70-B3-D5 (hex) Silent Gliss International Ltd +B66000-B66FFF (base 16) Silent Gliss International Ltd + Worbstrasse 210 + Guemligen 3073 + CH + +70-B3-D5 (hex) Videoport S.A. +441000-441FFF (base 16) Videoport S.A. + Sigma Business Center, Building A Nivel 2 + San Pedro San Jose 11501 + CR + +70-B3-D5 (hex) AKIS technologies +402000-402FFF (base 16) AKIS technologies + Ciurlionio g. 82 + Vilnius Lithuania 03100 + LT + +70-B3-D5 (hex) Satixfy Israel Ltd. +978000-978FFF (base 16) Satixfy Israel Ltd. + 12 Hamada st. + Rehovot 7670300 + IL + +70-B3-D5 (hex) ANALOGICS TECH INDIA LTD +B49000-B49FFF (base 16) ANALOGICS TECH INDIA LTD + PLOT # 9/10, NACHARAM INDUSTRIAL ESTATE + HYDERABAD TELANGANA 500076 + IN + +70-B3-D5 (hex) ACD Elekronik GmbH +673000-673FFF (base 16) ACD Elekronik GmbH + Engelberg 2 + Achstetten 88480 + DE + +70-B3-D5 (hex) Aural Ltd +76C000-76CFFF (base 16) Aural Ltd + Aural Ltd, 3b Wellington Close, Parkgate Industrial Estate + KNUTSFORD Cheshire WA16 8XL + GB + +70-B3-D5 (hex) LINEAGE POWER PVT LTD., +516000-516FFF (base 16) LINEAGE POWER PVT LTD., + 30-A1, KIADB, 1ST PHASE INDUSTRIAL ESTATE,KUMBALGODU, BANGALORE-MYSORE ROAD + BANGALORE KARNATAKA 560074 + IN + +70-B3-D5 (hex) Sense For Innovation +1EA000-1EAFFF (base 16) Sense For Innovation + Nistelrodeseweg 9A + Uden 5406 PT + NL + +70-B3-D5 (hex) ENTEC Electric & Electronic Co., LTD. +E84000-E84FFF (base 16) ENTEC Electric & Electronic Co., LTD. + 78-2 Buncheon-ri, Bongdam-eup + Hwaseong-city Gyungki-do 445-894 + KR + +70-B3-D5 (hex) AML +759000-759FFF (base 16) AML + 2190 Regal Parkway + Euless TX 76040 + US + +70-B3-D5 (hex) NIRIT- Xinwei Telecom Technology Co., Ltd. +F27000-F27FFF (base 16) NIRIT- Xinwei Telecom Technology Co., Ltd. + 2-й Кожуховский проезд, д.12, стр.2 + Moscow 115432 + RU + +70-B3-D5 (hex) Schneider Electric Motion USA +8D7000-8D7FFF (base 16) Schneider Electric Motion USA + 370 N. Main St. + Marlborough CT 06447 + US + +70-B3-D5 (hex) DOBE Computing +9DF000-9DFFFF (base 16) DOBE Computing + Dong-Bu 61 Song-Dam Univ. Chang-Ui 203 + Yong-In 17145 + KR + +70-B3-D5 (hex) Laser Imagineering Vertriebs GmbH +FDD000-FDDFFF (base 16) Laser Imagineering Vertriebs GmbH + Rudolf-Diesel-Weg 5 + Moelln 23879 + DE + +70-B3-D5 (hex) Avidbots Corporation +B4D000-B4DFFF (base 16) Avidbots Corporation + 975 Bleams Road, Unit 5 + Kitchener Ontario N2E 3Z5 + CA + +70-B3-D5 (hex) Reckeen HDP Media sp. z o.o. sp. k. +3A1000-3A1FFF (base 16) Reckeen HDP Media sp. z o.o. sp. k. + Robotnicza 68c + Wroclaw 53608 + PL + +70-B3-D5 (hex) DEUTA-WERKE GmbH +F84000-F84FFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) Sun Creative (ZheJiang) Technology INC. +2B2000-2B2FFF (base 16) Sun Creative (ZheJiang) Technology INC. + 3#Building No.181 Wuchang street + HANGZHOU ZHE JIANG 310023 + CN + +70-B3-D5 (hex) BASF Corporation +680000-680FFF (base 16) BASF Corporation + 26 Davis Drive + Research Triangle Park NC 27709 + US + +70-B3-D5 (hex) ACCEL CORP +53D000-53DFFF (base 16) ACCEL CORP + 16-32 Nakamachi + CHINO Nagano 3910005 + JP + +70-B3-D5 (hex) Advansid +3F7000-3F7FFF (base 16) Advansid + Via Alla Cascata 56/C + Trento 38123 + IT + +70-B3-D5 (hex) SCHMID electronic +764000-764FFF (base 16) SCHMID electronic + Badstrasse 39 + Reutlingen 72766 + DE + +70-B3-D5 (hex) Globalcom Engineering SPA +636000-636FFF (base 16) Globalcom Engineering SPA + Via Volta 39 + CARDANO AL CAMPO VA 21010 + IT + +70-B3-D5 (hex) Harvard Technology Ltd +56A000-56AFFF (base 16) Harvard Technology Ltd + Tyler Close, Normanton + Wakefield WF6 1RL + GB + +70-B3-D5 (hex) Roboteq +DA5000-DA5FFF (base 16) Roboteq + 7812 E Acoma dr + Scottsdale AZ 85260 + US + +70-B3-D5 (hex) CAMEON S.A. +235000-235FFF (base 16) CAMEON S.A. + 3 rue de la Bavière + La Chapelle sur Erdre Loire-Atlantique 44240 + FR + +70-B3-D5 (hex) Computech International +280000-280FFF (base 16) Computech International + 525 Northern Boulevard + Great Neck NY 11021 + US + +70-B3-D5 (hex) Groupe Paris-Turf +9AB000-9ABFFF (base 16) Groupe Paris-Turf + 45 avenue Victor-Hugo, Bâtiment 270, 2e étage + AUBERVILLIERS 93300 + FR + +00-1B-C5 (hex) Osborne Coinage Co +032000-032FFF (base 16) Osborne Coinage Co + 2851 Massachusetts Avenue + Cincinnati OH 45225 + US + +00-1B-C5 (hex) VEILUX INC. +0B6000-0B6FFF (base 16) VEILUX INC. + 802 GREENVIEW DR. STE 200 + GRAND PRAIRIE 75050 + US + +70-B3-D5 (hex) KST technology +C05000-C05FFF (base 16) KST technology + KST B/D 4-5, Wiryeseong-daero 12-gil + Songpa-gu Seoul 05636 + KR + +70-B3-D5 (hex) EA Elektroautomatik GmbH & Co. KG +26C000-26CFFF (base 16) EA Elektroautomatik GmbH & Co. KG + Helmholtzstraße 31-33 + Viersen NRW 41747 + DE + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +85F000-85FFFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) EGICON SRL +6F7000-6F7FFF (base 16) EGICON SRL + Via Posta Vecchia 36 + Mirandola Modena 41037 + IT + +70-B3-D5 (hex) Smith Meter, Inc. +706000-706FFF (base 16) Smith Meter, Inc. + 1602 Wagner Ave. + Erie 16514 + US + +70-B3-D5 (hex) SL Audio A/S +E43000-E43FFF (base 16) SL Audio A/S + Ulvevej 28, Danmark + Skive Denmark 7800 + DK + +70-B3-D5 (hex) SANYU SWITCH CO., LTD. +F14000-F14FFF (base 16) SANYU SWITCH CO., LTD. + Muro 1639-2 + Kikuchi-gun Ohzu-cho Kumamoto-pref. 869-1235 + JP + +70-B3-D5 (hex) MEDEX +B4A000-B4AFFF (base 16) MEDEX + 240 Allée Jacques Monod + Saint-Priest France 69800 + FR + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +161000-161FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbühl Bavaria 91550 + DE + +70-B3-D5 (hex) Beijing Nacao Technology Co., Ltd. +105000-105FFF (base 16) Beijing Nacao Technology Co., Ltd. + 1912B, Zhongguancunkemao Building, Zhongguancun Da Jie + Beijing 100080 + CN + +70-B3-D5 (hex) IONETECH +876000-876FFF (base 16) IONETECH + #50,sicheongseo4gil + yeosu jeonnam 59674 + KR + +70-B3-D5 (hex) Beijing Daswell Science and Technology Co.LTD +06F000-06FFFF (base 16) Beijing Daswell Science and Technology Co.LTD + 6th floor,Building B,Dachen Industry Park, NO.10 Jingyuan Street, BDA + Beijing Beijing 100176 + CN + +70-B3-D5 (hex) Redfish Group Pty Ltd +DA6000-DA6FFF (base 16) Redfish Group Pty Ltd + Level 3, 24 Little Edward Street + Spring Hill QLD 4000 + AU + +70-B3-D5 (hex) Impolux GmbH +EEC000-EECFFF (base 16) Impolux GmbH + Boschstr. 7 + Kastellaun RLP 56288 + DE + +70-B3-D5 (hex) Centero +CE2000-CE2FFF (base 16) Centero + 1640 Powers Ferry Road Bldg.14-360 + Marietta GA 30067 + US + +70-B3-D5 (hex) STREGA +770000-770FFF (base 16) STREGA + Dreve de la Meute 31 + Waterloo 1410 + BE + +70-B3-D5 (hex) Burk Technology +985000-985FFF (base 16) Burk Technology + 7 Beaver Brook road + Littleton MA 01460 + US + +70-B3-D5 (hex) Heng Dian Technology Co., Ltd +FEA000-FEAFFF (base 16) Heng Dian Technology Co., Ltd + No.9, Yunmei Road,Tianmulake Town + Liyang Jiangsu 213300 + CN + +70-B3-D5 (hex) Fen Systems Ltd +B1E000-B1EFFF (base 16) Fen Systems Ltd + 110 Cromwell Road + Cambridge CB1 3EG + GB + +70-B3-D5 (hex) INVIXIUM ACCESS INC. +87D000-87DFFF (base 16) INVIXIUM ACCESS INC. + 50 ACADIA AVE, 310 + MARKHAM Ontario L3R0B3 + CA + +70-B3-D5 (hex) JSK System +B7F000-B7FFFF (base 16) JSK System + Wiośniana, 30/32 + Łódź 93-228 + PL + +70-B3-D5 (hex) Enertex Bayern GmbH +DC8000-DC8FFF (base 16) Enertex Bayern GmbH + Ebermannstädter Str. 8 + Forchheim Bayern 91301 + DE + +70-B3-D5 (hex) Liteon Technology Corporation +073000-073FFF (base 16) Liteon Technology Corporation + 8F, 866, Chung-Cheng Road, Chung Ho + New Taipei City Taiwan 23585 + TW + +70-B3-D5 (hex) Orlaco Products B.V. +240000-240FFF (base 16) Orlaco Products B.V. + Albert Plesmanstraat 42 + Barneveld 3772MN + NL + +70-B3-D5 (hex) Invisible Systems Limited +5F2000-5F2FFF (base 16) Invisible Systems Limited + 9 Beetham Road + Milnthorpe Cumbria LA7 7QL + GB + +70-B3-D5 (hex) Refine Technology, LLC +EBC000-EBCFFF (base 16) Refine Technology, LLC + 26 Chapin Road, Unit 1107, PO Box 691 + Pine Brook NJ 07058 + US + +70-B3-D5 (hex) Heartlandmicropayments +455000-455FFF (base 16) Heartlandmicropayments + 2115 Chapman Road Suite 159 + Chattanooga TN 37421 + US + +70-B3-D5 (hex) AVI Pty Ltd +790000-790FFF (base 16) AVI Pty Ltd + 9 Pitt Way + Booragoon Western Australia 6154 + AU + +70-B3-D5 (hex) PEEK TRAFFIC +C65000-C65FFF (base 16) PEEK TRAFFIC + 5401 N SAM HOUSTON PKWY W + HOUSTON null 77086 + US + +70-B3-D5 (hex) Kalfire +64B000-64BFFF (base 16) Kalfire + Geloërveldweg 21 + Belfeld Limburg 5951 DH + NL + +70-B3-D5 (hex) Biovigil Hygiene Technologies +DB1000-DB1FFF (base 16) Biovigil Hygiene Technologies + 924 N. Main st., Suite 2 + Ann Arbor MI 48104 + US + +70-B3-D5 (hex) Talleres de Escoriaza SA +532000-532FFF (base 16) Talleres de Escoriaza SA + Barrio Ventas, 35 + Irun Gipuzkoa 20305 + ES + +70-B3-D5 (hex) Labtronik s.r.l. +6C1000-6C1FFF (base 16) Labtronik s.r.l. + Via di Cervara 49 + Rome Italy 00155 + IT + +70-B3-D5 (hex) Vitro Technology Corporation +F19000-F19FFF (base 16) Vitro Technology Corporation + Box 91232 + Austin TX 78709-1232 + US + +70-B3-D5 (hex) Riegl Laser Measurement Systems GmbH +F10000-F10FFF (base 16) Riegl Laser Measurement Systems GmbH + Riedenburgstraße 48 + Horn Niederösterreich A-3580 + AT + +70-B3-D5 (hex) Robotelf Technologies (Chengdu) Co., Ltd. +1A6000-1A6FFF (base 16) Robotelf Technologies (Chengdu) Co., Ltd. + N3-4-1-1914, Global Center, No. 1700, Tianfu Road North, High-rech Zone + Chengdu City Sichuan 610041 + CN + +70-B3-D5 (hex) Nautel Limited +87C000-87CFFF (base 16) Nautel Limited + 10089 Peggy's Cove Road + Hackett's Cove Nova Scotia B3Z3J4 + CA + +70-B3-D5 (hex) M.T. S.R.L. +141000-141FFF (base 16) M.T. S.R.L. + VIA MONZA 83 + GESSATE 20060 + IT + +70-B3-D5 (hex) Walk Horizon Technology (Beijing) Co., Ltd. +154000-154FFF (base 16) Walk Horizon Technology (Beijing) Co., Ltd. + Rm121 B1 Shouxindasha Building, 5 Jiangtailu Rd., Chaoyang District + Beijing 100015 + CN + +70-B3-D5 (hex) CoXlab Inc. +DF1000-DF1FFF (base 16) CoXlab Inc. + 312 Hannuri-daero, 309 + Sejong 30128 + KR + +70-B3-D5 (hex) BCD Audio +728000-728FFF (base 16) BCD Audio + 5 Bristol Way, Stoke Gardens + Slough Berkshire SL1 3QE + GB + +70-B3-D5 (hex) Zigencorp, Inc +739000-739FFF (base 16) Zigencorp, Inc + 6934 Canby Avenue 107 + Reseda CA 91335 + US + +70-B3-D5 (hex) E-MetroTel +FF0000-FF0FFF (base 16) E-MetroTel + 2828 West Parker Unit B201 + Plano TX 75075 + US + +70-B3-D5 (hex) Euklis by GSG International +AD8000-AD8FFF (base 16) Euklis by GSG International + via Colombo 23 + Trezzano sul Naviglio MI 20090 + IT + +70-B3-D5 (hex) Mesa Labs, Inc. +23A000-23AFFF (base 16) Mesa Labs, Inc. + 12100 West 6th Ave. + Lakewood CO 80228 + US + +70-B3-D5 (hex) Systems With Intelligence Inc. +93E000-93EFFF (base 16) Systems With Intelligence Inc. + 6889 Rexwood Road, Unit 9 + Mississauga Ontario L4V 1R2 + CA + +70-B3-D5 (hex) Gentec Systems Co. +469000-469FFF (base 16) Gentec Systems Co. + 5F., No.51-3, Fuxing Rd., Xindian Dist., + New Taipei City 23150 + TW + +70-B3-D5 (hex) Guangzhou Male Industrial Animation Technology Co.,Ltd. +0D4000-0D4FFF (base 16) Guangzhou Male Industrial Animation Technology Co.,Ltd. + 4/F,Block A, 23 Huancun Road,Dalong Street, Panyu District,Guangzhou City + Guangzhou City Guangdong Province 514000 + CN + +70-B3-D5 (hex) BigStuff3, Inc. +64E000-64EFFF (base 16) BigStuff3, Inc. + 4352 Fenton Rd + Hartland MI 48353 + US + +70-B3-D5 (hex) DEUTA-WERKE GmbH +EF5000-EF5FFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) Wimate Technology Solutions Private Limited +253000-253FFF (base 16) Wimate Technology Solutions Private Limited + 96, 34th B cross, 16th Main, Jayanagar 4th T block + Bangalore Karnataka 560041 + IN + +70-B3-D5 (hex) ELEUSI GmbH +1CD000-1CDFFF (base 16) ELEUSI GmbH + Rottendorferstrasse 1 + Feldkirchen Kaernten 9560 + AT + +70-B3-D5 (hex) Core Balance Co., Ltd. +D5F000-D5FFFF (base 16) Core Balance Co., Ltd. + #1807, #1808, 308-4, Seongsu-dong 2-ga, Seongdong-gu + Seoul 04781 + KR + +00-1B-C5 (hex) TechSolutions A/S +0C2000-0C2FFF (base 16) TechSolutions A/S + Lyskaer 15, 2 + Herlev 2730 + DK + +70-B3-D5 (hex) G+D Mobile Security +024000-024FFF (base 16) G+D Mobile Security + C/ 114 nº 27, Polígon Pratenc + El Prat de Llobregat Barcelona E-08820 + ES + +70-B3-D5 (hex) PHB Eletronica Ltda. +904000-904FFF (base 16) PHB Eletronica Ltda. + Aroaba St., 129 + São Paulo 05315-020 + BR + +70-B3-D5 (hex) ETON Deutschland Electro Acoustic GmbH +213000-213FFF (base 16) ETON Deutschland Electro Acoustic GmbH + Pfaffenweg 21 + Neu-Ulm Bavaria 89231 + DE + +70-B3-D5 (hex) Saratoga Speed, Inc. +55C000-55CFFF (base 16) Saratoga Speed, Inc. + 2701 Zanker Rd + San Jose CA 95134 + US + +70-B3-D5 (hex) AmTote Australasia +DAA000-DAAFFF (base 16) AmTote Australasia + Unit3, 28 LeightonPlace. + HORNSBY NSW 2077 + AU + +70-B3-D5 (hex) TRIDENT INFOSOL PVT LTD +C8F000-C8FFFF (base 16) TRIDENT INFOSOL PVT LTD + NO1A , KUSHAL GARDEN , PEENYA INDUSTRIAL AREA + BANGALORE 560058 + IN + +70-B3-D5 (hex) OSUNG LST CO.,LTD. +B64000-B64FFF (base 16) OSUNG LST CO.,LTD. + #433-31, Sandong-ro, Eumbong-myeon + Asan-si Chungcheongnam-do 31418 + KR + +70-B3-D5 (hex) ELBIT SYSTEMS BMD AND LAND EW - ELISRA LTD +24F000-24FFFF (base 16) ELBIT SYSTEMS BMD AND LAND EW - ELISRA LTD + Hamerchava 29 + holon 58101 + IL + +70-B3-D5 (hex) Valk Welding B.V. +5DA000-5DAFFF (base 16) Valk Welding B.V. + Staalindustrieweg 15 + Alblasserdam Zuid Holland 2952 AT + NL + +70-B3-D5 (hex) Special Services Group, LLC +0F8000-0F8FFF (base 16) Special Services Group, LLC + PO Box 825 + Denair CA 95316 + US + +70-B3-D5 (hex) AEM Singapore Pte. Ltd. +AC1000-AC1FFF (base 16) AEM Singapore Pte. Ltd. + 52 Serangoon North Ave 4 + Singapore Singapore 555853 + SG + +70-B3-D5 (hex) Fire4 Systems UK Ltd +E69000-E69FFF (base 16) Fire4 Systems UK Ltd + 8 Regent Street + Leeds West Yorkshire LS7 4PE + GB + +70-B3-D5 (hex) Preston Industries dba PolyScience +3B5000-3B5FFF (base 16) Preston Industries dba PolyScience + 6600 W. Touhy Ave + Niles IL 60714-4588 + US + +70-B3-D5 (hex) Stone Three +7BF000-7BFFFF (base 16) Stone Three + 24 Gardner Williams Ave + Somerset West Western Cape 7130 + ZA + +70-B3-D5 (hex) Cyanview +E3A000-E3AFFF (base 16) Cyanview + 26, Rue de la Foire + Papignies 7861 + BE + +70-B3-D5 (hex) Matrix Orbital Corporation +2B7000-2B7FFF (base 16) Matrix Orbital Corporation + Suite 602, 4774 Westwinds Dr NE + Calgary Alberta T3J 0L7 + CA + +70-B3-D5 (hex) BLOCKSI LLC +9E6000-9E6FFF (base 16) BLOCKSI LLC + 228 Hamilton avenue 3rd floor + Palo Alto 94301 + US + +70-B3-D5 (hex) Krontech +6E9000-6E9FFF (base 16) Krontech + I.T.U ARI 3 Teknokent Kron Telekomunikasyon, Maslak + Istanbul 34467 + TR + +70-B3-D5 (hex) ELVA-1 MICROWAVE HANDELSBOLAG +FA3000-FA3FFF (base 16) ELVA-1 MICROWAVE HANDELSBOLAG + c/o Hornlund, Kungsgatan 54 + Furulund 244 62 + SE + +70-B3-D5 (hex) EA Elektroautomatik GmbH & Co. KG +743000-743FFF (base 16) EA Elektroautomatik GmbH & Co. KG + Helmholtzstraße 31-33 + Viersen NRW 41747 + DE + +70-B3-D5 (hex) Waterkotte GmbH +7EA000-7EAFFF (base 16) Waterkotte GmbH + Gewerkenstr. 15 + Herne 44628 + DE + +70-B3-D5 (hex) Mo-Sys Engineering Ltd +075000-075FFF (base 16) Mo-Sys Engineering Ltd + Thames Bank House, Tunnel Avenue + London SE100PA + GB + +70-B3-D5 (hex) Prisma Telecom Testing Srl +689000-689FFF (base 16) Prisma Telecom Testing Srl + Via Petrocchi, 4 + Milano MI 20127 + IT + +70-B3-D5 (hex) KRONOTECH SRL +8C8000-8C8FFF (base 16) KRONOTECH SRL + VIALE UNGHERIA 125 + UDINE ITALY/UDINE 33100 + IT + +70-B3-D5 (hex) HAVELSAN A.Ş. +096000-096FFF (base 16) HAVELSAN A.Ş. + Mustafa Kemal Mah. 2120.Cad. No.39 + ANKARA 06510 + TR + +70-B3-D5 (hex) Triax A/S +963000-963FFF (base 16) Triax A/S + Bjornkaervej 3 + Hornsyld Denmark 8783 + DK + +70-B3-D5 (hex) KST technology +351000-351FFF (base 16) KST technology + KST B/D 4-5, Wiryeseong-daero 12-gil + Songpa-gu Seoul 05636 + KR + +70-B3-D5 (hex) KSE GmbH +D41000-D41FFF (base 16) KSE GmbH + Frühlingstraße 31-33 + Ingolstadt 85055 + DE + +70-B3-D5 (hex) bobz GmbH +81B000-81BFFF (base 16) bobz GmbH + Südring 3d + Wentorf b. Hamburg SH 21465 + DE + +70-B3-D5 (hex) GHM-Messtechnik GmbH (Standort IMTRON) +B6C000-B6CFFF (base 16) GHM-Messtechnik GmbH (Standort IMTRON) + Carl-Benz-Strasse 11 + Owingen Baden-Würrtemberg 88696 + DE + +70-B3-D5 (hex) Core Akıllı Ev Sistemleri +6FD000-6FDFFF (base 16) Core Akıllı Ev Sistemleri + Akdeniz Mah. Cumhuriyet Bulvarı No:82/802 Konak + İzmir 35210 + TR + +70-B3-D5 (hex) WeWork Companies, Inc. +2CC000-2CCFFF (base 16) WeWork Companies, Inc. + 115 W 18th St + New York NY 10011 + US + +70-B3-D5 (hex) Link Electric & Safety Control Co. +60D000-60DFFF (base 16) Link Electric & Safety Control Co. + 444 McNally Drive + Nashville 37211 + US + +70-B3-D5 (hex) Adigitalmedia +B3A000-B3AFFF (base 16) Adigitalmedia + #211, 444, Hangeulbiseok-ro, Nowon-gu + seoul 01666 + KR + +70-B3-D5 (hex) LG Electronics +723000-723FFF (base 16) LG Electronics + 189, LG Gasan Digital Center, Gasan digital 1-ro, Geumcheon-gu + Seoul 153-803 + KR + +70-B3-D5 (hex) Galios +EA6000-EA6FFF (base 16) Galios + Dmitriy Donskoy, 35A, 526 + Tver 170006 + RU + +70-B3-D5 (hex) RADA Electronics Industries Ltd. +C4D000-C4DFFF (base 16) RADA Electronics Industries Ltd. + 7 Gibory Israel St. + Netanya 42504 + IL + +70-B3-D5 (hex) Breas Medical AB +E88000-E88FFF (base 16) Breas Medical AB + Företagsvägen 1 + Mölnlycke SE-435 33 + SE + +70-B3-D5 (hex) Wilson Electronics +95C000-95CFFF (base 16) Wilson Electronics + 3301 E. Deseret Dr. + Saint George UT 84790 + US + +70-B3-D5 (hex) McQ Inc +C6C000-C6CFFF (base 16) McQ Inc + 1551 FORBES ST + Fredericksburg VA 22405 + US + +70-B3-D5 (hex) Paradigm Technology Services B.V. +940000-940FFF (base 16) Paradigm Technology Services B.V. + Ambachtsweg 7 + Groot-Ammers 2964LG + NL + +70-B3-D5 (hex) Xacti Corporation +828000-828FFF (base 16) Xacti Corporation + Tower East 28F, Umeda Sky bldg, 1-1-88, Oyodonaka, Kita-ku, + Osaka Osaka 5316028 + JP + +70-B3-D5 (hex) QUALITTEQ LLC +760000-760FFF (base 16) QUALITTEQ LLC + 16th Parkovaya 26/1 + Moscow 105484 + RU + +70-B3-D5 (hex) Ideetron b.v. +9B5000-9B5FFF (base 16) Ideetron b.v. + Dorpsstraat 81 + Doorn Utrecht 3941JL + NL + +70-B3-D5 (hex) Digital Matter Pty Ltd +705000-705FFF (base 16) Digital Matter Pty Ltd + 9/100 Railway Rd + Subiaco WA 6008 + AU + +70-B3-D5 (hex) mg-sensor GmbH +2BD000-2BDFFF (base 16) mg-sensor GmbH + Airport Boulevard B 210 + Rheinmuenster 77836 + DE + +70-B3-D5 (hex) UnI Systech Co.,Ltd +894000-894FFF (base 16) UnI Systech Co.,Ltd + A-511 Sigma2 164,Tancheongsang-ro,Bundang-gu + Seongnam-si Gyeonggi-do 13631 + KR + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +DE6000-DE6FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) BESTCODE LLC +E3F000-E3FFFF (base 16) BESTCODE LLC + 3034 SE Loop 820 + Fort Worth TX 76140 + US + +70-B3-D5 (hex) ENTEC Electric & Electronic Co., LTD. +92B000-92BFFF (base 16) ENTEC Electric & Electronic Co., LTD. + 78-2 Buncheon-ri, Bongdam-eup + Hwaseong-city Gyungki-do 445-894 + KR + +70-B3-D5 (hex) Wi6labs +8F8000-8F8FFF (base 16) Wi6labs + 1137 A - Avenue des Champs Blancs + Cesson Sevigné 35510 + FR + +70-B3-D5 (hex) Sanmina Israel +1E6000-1E6FFF (base 16) Sanmina Israel + Koren Industrial Zone , POBox 102 + Maalot Israel 2101002 + IL + +70-B3-D5 (hex) Elbit Systems of America +826000-826FFF (base 16) Elbit Systems of America + 4700 Marine Creek Parkway + Fort Worth TX 76179 + US + +70-B3-D5 (hex) NASA Johnson Space Center +2AB000-2ABFFF (base 16) NASA Johnson Space Center + 2101 NASA Parkway + Houston TX 77058 + US + +70-B3-D5 (hex) LP Technologies Inc. +727000-727FFF (base 16) LP Technologies Inc. + 1919 N. Amidon St 216 + Wichita KS 67203 + US + +70-B3-D5 (hex) Health Care Originals, Inc. +2F2000-2F2FFF (base 16) Health Care Originals, Inc. + 1 Pleasant St., Ste. 442 + Rochester NY 14604 + US + +70-B3-D5 (hex) Spectrum Brands +254000-254FFF (base 16) Spectrum Brands + 19701 DaVinci + Lake Forest 92656 + US + +70-B3-D5 (hex) Vidisys GmbH +133000-133FFF (base 16) Vidisys GmbH + Rudolf-Diesel-Ring 30 + Sauerlach Bavaria 82054 + DE + +70-B3-D5 (hex) SANSFIL Technologies +844000-844FFF (base 16) SANSFIL Technologies + rue pierre Fontaine Str + paris NA 04271 + FR + +70-B3-D5 (hex) Blu Wireless Technology Ltd +6E8000-6E8FFF (base 16) Blu Wireless Technology Ltd + Engine Shed, Station Approach, + Bristol BS1 6QH + GB + +70-B3-D5 (hex) Thiel Audio Products Company, LLC +EB9000-EB9FFF (base 16) Thiel Audio Products Company, LLC + 566 Mainstream Dr, Suite 500 + Nashville TN 37228 + US + +70-B3-D5 (hex) Intermind Inc. +4A5000-4A5FFF (base 16) Intermind Inc. + 2-64-4-2104 Hiyoshi-honchou Kouhoku-ku + Yokohama kanagawa 2230062 + JP + +70-B3-D5 (hex) ACD Elekronik GmbH +D98000-D98FFF (base 16) ACD Elekronik GmbH + Engelberg 2 + Achstetten 88480 + DE + +70-B3-D5 (hex) CONNIT +6AD000-6ADFFF (base 16) CONNIT + 231 rue Pierre et Marie Curie + LABEGE 31670 + FR + +70-B3-D5 (hex) Aton srl +5BF000-5BFFFF (base 16) Aton srl + Via Guido Rossa 5 + Spilamberto MO 41057 + IT + +70-B3-D5 (hex) Dutile, Glines and Higgins Corporation +FF8000-FF8FFF (base 16) Dutile, Glines and Higgins Corporation + P.O. Box 5638 + Manchester NH 03108 + US + +70-B3-D5 (hex) OPTSYS +58C000-58CFFF (base 16) OPTSYS + 7, rue Salvador Dali – BP 505 + SAINT ETIENNE 42007 + FR + +70-B3-D5 (hex) Tech4Race +C0C000-C0CFFF (base 16) Tech4Race + 1137 A avenue des champs blancs + Cesson-Sévigné 35510 + FR + +70-B3-D5 (hex) TSAT AS +0D3000-0D3FFF (base 16) TSAT AS + Martin Linges v 25 + Fornebu 1364 + NO + +70-B3-D5 (hex) Dandong Dongfang Measurement & Control Technology Co., Ltd. +C33000-C33FFF (base 16) Dandong Dongfang Measurement & Control Technology Co., Ltd. + No. 136, Binjiang M. Road, Yanjiang Development Zone + Dandong Liaoning 118000 + CN + +70-B3-D5 (hex) PROFEN COMMUNICATIONS +CC8000-CC8FFF (base 16) PROFEN COMMUNICATIONS + Famas Plaza A Blok Kat: 10 No:35 Okmeydani + Istanbul 34384 + TR + +70-B3-D5 (hex) Mipot S.p.a. +C20000-C20FFF (base 16) Mipot S.p.a. + Via Corona 5 + Cormons 34071 + IT + +70-B3-D5 (hex) Securolytics, Inc. +125000-125FFF (base 16) Securolytics, Inc. + 2002 Summit Boulevard, Suite 300 + Atlanta GA 30319 + US + +70-B3-D5 (hex) Thermo Fisher Scientific +D69000-D69FFF (base 16) Thermo Fisher Scientific + 27 forge Parkway + Franklin MA 02038 + US + +70-B3-D5 (hex) S.E.I. CO.,LTD. +56B000-56BFFF (base 16) S.E.I. CO.,LTD. + 59 Nirayama Tada + Izunokuni Shizuoka 4102133 + JP + +70-B3-D5 (hex) Camsat Przemysław Gralak +807000-807FFF (base 16) Camsat Przemysław Gralak + Ogrodowa 2A + Solec Kujawski Bydgoszcz 86-050 + PL + +70-B3-D5 (hex) Lithe Technology, LLC +EE3000-EE3FFF (base 16) Lithe Technology, LLC + 4574 North First Avenue, Suite 100 + Tucson AZ 85718 + US + +70-B3-D5 (hex) TIAMA +FA0000-FA0FFF (base 16) TIAMA + ZA des Plattes - 1 Chemin des Plattes + VOURLES 69390 + FR + +70-B3-D5 (hex) Elystec Technology Co., Ltd +D4C000-D4CFFF (base 16) Elystec Technology Co., Ltd + Room 601, Zhong Da Court,Zhong Guan Garden,No.1311 Liuxian Road + Shenzhen Guangdong 518000 + CN + +70-B3-D5 (hex) Shenzhen Virtual Clusters Information Technology Co.,Ltd. +7F3000-7F3FFF (base 16) Shenzhen Virtual Clusters Information Technology Co.,Ltd. + Room 201,Building A,No.1,Qianhai 1st Road,Shengang cooperation zone,Qianhai + Shenzhen 518054 + CN + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +C79000-C79FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Cominfo, Inc. +0A0000-0A0FFF (base 16) Cominfo, Inc. + Nabrezi 695 + Zlin 760 01 + CZ + +70-B3-D5 (hex) CRDE +DA4000-DA4FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) ijin co.,ltd. +2D0000-2D0FFF (base 16) ijin co.,ltd. + #109 BI, Hanyandaehak-ro + Ansan South Korea 15588 + KR + +70-B3-D5 (hex) Zeroplus Technology Co.,Ltd. +9C1000-9C1FFF (base 16) Zeroplus Technology Co.,Ltd. + 3F.,No.121,Jian 8th Rd.,Zhonghe Dist., + New Taipei City Taiwan 23585 + TW + +70-B3-D5 (hex) A Trap, USA +763000-763FFF (base 16) A Trap, USA + 2021 Sperry Ave, Unit 11 + Ventura CA 93003 + US + +70-B3-D5 (hex) JSC “Scientific Industrial Enterprise Rubin +F25000-F25FFF (base 16) JSC “Scientific Industrial Enterprise Rubin + 2, Baydukov str. + Penza Penza reg. 440000 + RU + +70-B3-D5 (hex) LINEAGE POWER PVT LTD., +AA3000-AA3FFF (base 16) LINEAGE POWER PVT LTD., + 30-A1, KIADB, 1ST PHASE INDUSTRIAL ESTATE,KUMBALGODU, BANGALORE-MYSORE ROAD + BANGALORE KARNATAKA 560074 + IN + +70-B3-D5 (hex) TATTILE SRL +967000-967FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Potter Electric Signal Co. LLC +C17000-C17FFF (base 16) Potter Electric Signal Co. LLC + 1609 Park 370 Place + Hazelwood 63042 + US + +70-B3-D5 (hex) PEEK TRAFFIC +A28000-A28FFF (base 16) PEEK TRAFFIC + 5401 N SAM HOUSTON PKWY W + HOUSTON null 77086 + US + +70-B3-D5 (hex) Shanghai Daorech Industry Developmnet Co.,Ltd +9DC000-9DCFFF (base 16) Shanghai Daorech Industry Developmnet Co.,Ltd + 21F Hitech Plaza No.488 South Wu Ning Road + shanghai shanghai 200042 + CN + +70-B3-D5 (hex) Monnit Corporation +02E000-02EFFF (base 16) Monnit Corporation + 3400 S WEST TEMPLE + SALT LAKE CITY UT 84115 + US + +70-B3-D5 (hex) Axatel SrL +D8E000-D8EFFF (base 16) Axatel SrL + Via del Mercato Nuovo, 75 + VICENZA ITALY 36100 + IT + +70-B3-D5 (hex) comtac AG +BF6000-BF6FFF (base 16) comtac AG + Allenwindenstrasse 1 + Flurlingen 8247 + CH + +70-B3-D5 (hex) ModulaTeam GmbH +F0C000-F0CFFF (base 16) ModulaTeam GmbH + Schrannenplatz 6 + Erding Bavaria 85435 + DE + +70-B3-D5 (hex) Fracarro srl +E59000-E59FFF (base 16) Fracarro srl + VIA CAZZARO 3 + CASTELFRANCO VENETO TV 31033 + IT + +70-B3-D5 (hex) Qtechnology A/S +C74000-C74FFF (base 16) Qtechnology A/S + Valby Langgade 142, 1. + Valby DK 2500 + DK + +70-B3-D5 (hex) SPEA SPA +3F3000-3F3FFF (base 16) SPEA SPA + Via Torino 16 + Volpiano Piemonte 10088 + IT + +70-B3-D5 (hex) Raven Systems Design, Inc +0B0000-0B0FFF (base 16) Raven Systems Design, Inc + 7777 Wall St + Valley View OH 44125 + US + +70-B3-D5 (hex) Mitsubishi Electric Micro-Computer Application Software Co.,Ltd. +F37000-F37FFF (base 16) Mitsubishi Electric Micro-Computer Application Software Co.,Ltd. + Inadera, 2-5-1 + Amagasaki Hyogo 661-0981 + JP + +70-B3-D5 (hex) SMITEC S.p.A. +138000-138FFF (base 16) SMITEC S.p.A. + Via Carlo Ceresa, 10 + San Giovanni Bianco Bergamo 24015 + IT + +70-B3-D5 (hex) LGE +630000-630FFF (base 16) LGE + 2621, Nambusunhwan-ro, Gangnam-gu + Seoul 06267 + KR + +70-B3-D5 (hex) Veeco Instruments +D08000-D08FFF (base 16) Veeco Instruments + 4875 Constellation Dr + St. Paul MN 55127 + US + +70-B3-D5 (hex) University of Wisconsin Madison - Department of High Energy Physics +98C000-98CFFF (base 16) University of Wisconsin Madison - Department of High Energy Physics + 1150 University Ave + Madison WI 53706 + US + +70-B3-D5 (hex) Excelfore Corporation +7A1000-7A1FFF (base 16) Excelfore Corporation + 3155 Kearnet St, Suite 200 + Fremont CA 94538 + US + +70-B3-D5 (hex) Critical Link LLC +F1D000-F1DFFF (base 16) Critical Link LLC + 6712 Brooklawn Parkway + Syracuse null 13211 + US + +70-B3-D5 (hex) XLOGIC srl +85E000-85EFFF (base 16) XLOGIC srl + Via A. Grandi 23 + Cinisello Balsamo 20092 + IT + +70-B3-D5 (hex) Unlimiterhear co.,ltd. taiwan branch +902000-902FFF (base 16) Unlimiterhear co.,ltd. taiwan branch + 5F-1 No18.-1, sec.3 , Ren-Ai Rd. + Taipei City 106 + TW + +70-B3-D5 (hex) DYCEC, S.A. +1DE000-1DEFFF (base 16) DYCEC, S.A. + Torres Quevedo, 1-P.T.M. + Tres Cantos Madrid 28760 + ES + +70-B3-D5 (hex) Symetrics Industries d.b.a. Extant Aerospace +FFC000-FFCFFF (base 16) Symetrics Industries d.b.a. Extant Aerospace + 1615 West NASA Blvd + Melbourne FL 32901 + US + +70-B3-D5 (hex) Nordson Corporation +FA7000-FA7FFF (base 16) Nordson Corporation + 11475 Lakefield Dr + Duluth GA 30097 + US + +70-B3-D5 (hex) Radig Hard & Software +FAF000-FAFFFF (base 16) Radig Hard & Software + An der Bahn 18 + Kreuztal 57223 + DE + +70-B3-D5 (hex) GREEN HOUSE CO., LTD. +4CF000-4CFFFF (base 16) GREEN HOUSE CO., LTD. + 5F Unosawa Building + Ebisu Shibuya-ku Tokyo 150-0013 + JP + +70-B3-D5 (hex) ACD Elekronik GmbH +5CA000-5CAFFF (base 16) ACD Elekronik GmbH + Engelberg 2 + Achstetten 88480 + DE + +70-B3-D5 (hex) Skopei B.V. +880000-880FFF (base 16) Skopei B.V. + Haagweg 199 + Rijswijk ZH 2281AM + NL + +70-B3-D5 (hex) Edgeware AB +60B000-60BFFF (base 16) Edgeware AB + Master Samuelsgatan 42 + Stockholm 11157 + SE + +70-B3-D5 (hex) Edgeware AB +9F6000-9F6FFF (base 16) Edgeware AB + Master Samuelsgatan 42 + Stockholm 11157 + SE + +70-B3-D5 (hex) Tata Communications Ltd. +F83000-F83FFF (base 16) Tata Communications Ltd. + VSB Mahatma Gandhi Road Fort Mumbai + Mumbai Maharashtra 400001 + IN + +70-B3-D5 (hex) Triax A/S +C2E000-C2EFFF (base 16) Triax A/S + Bjornkaervej 3 + Hornsyld Denmark 8783 + DK + +70-B3-D5 (hex) HAIYANG OLIX CO.,LTD. +5E5000-5E5FFF (base 16) HAIYANG OLIX CO.,LTD. + 103-903 BUCHEONTECHNOPARK 364 SAMJEONG + BUCHEON GEYONGGI 421-740 + KR + +70-B3-D5 (hex) PTN Electronics Limited +0A1000-0A1FFF (base 16) PTN Electronics Limited + G2, JinXiongDa Technology Park, HuanGuan Road South 105th GuanLan Block, LongHua New District + ShenZhen City guangdong 518000 + CN + +70-B3-D5 (hex) Merus Power Dynamics Ltd. +37C000-37CFFF (base 16) Merus Power Dynamics Ltd. + Pirkkalaistie 1 + Nokia 37100 + FI + +70-B3-D5 (hex) DoWoo Digitech +039000-039FFF (base 16) DoWoo Digitech + A-706ho,Ssangyong IT Twintower, dunchondaero, JungWon-Gu + Seongnam-si Gyeonggi-do 13216 + KR + +70-B3-D5 (hex) Dextera Labs +0EF000-0EFFFF (base 16) Dextera Labs + 3175 Quatre-Bourgeois #104 + Quebec Quebec G1W2K7 + CA + +70-B3-D5 (hex) ENGenesis +D25000-D25FFF (base 16) ENGenesis + 19 Technology Drive + Auburn MA 01501 + US + +70-B3-D5 (hex) Zehntner Testing Instruments +267000-267FFF (base 16) Zehntner Testing Instruments + Gewerbestrasse 4 + Sissach 4450 + CH + +70-B3-D5 (hex) APPLIED PROCESSING +E67000-E67FFF (base 16) APPLIED PROCESSING + 176 rue du Marechal Foch + Flins sur Seine 78410 + FR + +70-B3-D5 (hex) National TeleConsultants LLC +173000-173FFF (base 16) National TeleConsultants LLC + 550 North Brand Boulevard, 17th Floor + Glendale CA 91203-1944 + US + +70-B3-D5 (hex) Engage Technologies +20D000-20DFFF (base 16) Engage Technologies + 7041 Boone Avenue North + Brooklyn Park MN 55428 + US + +70-B3-D5 (hex) RTDS Technologies Inc. +542000-542FFF (base 16) RTDS Technologies Inc. + 100-150 Innovation Drive + Winnipeg Manitoba R3T 2E1 + CA + +70-B3-D5 (hex) WM Design s.r.o +D55000-D55FFF (base 16) WM Design s.r.o + Zamoravi 1572 + Napajedla 76361 + CZ + +70-B3-D5 (hex) JSC Kaluga Astral +E98000-E98FFF (base 16) JSC Kaluga Astral + Tsyolkovsky 4 + Kaluga Kaluga 248000 + RU + +70-B3-D5 (hex) eleven-x +149000-149FFF (base 16) eleven-x + 295 Hagey Blvd + Waterloo Ontario N2L 6R5 + CA + +70-B3-D5 (hex) REQUEA +952000-952FFF (base 16) REQUEA + 9 RUE ROBERT + LYON 69006 + FR + +70-B3-D5 (hex) Grossenbacher Systeme AG +5E2000-5E2FFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) Shanghai JaWay Information Technology Co., Ltd. +5C1000-5C1FFF (base 16) Shanghai JaWay Information Technology Co., Ltd. + Rm. 1102, Science and Technology Building A, No. 900 of Yishan Road, Xuhui District, + Shanghai 200030 + CN + +70-B3-D5 (hex) Telecast Inc. +BE9000-BE9FFF (base 16) Telecast Inc. + Jindaiji-Motomachi 3-36-11-103 + Chofu Tokyo 182-0017 + JP + +70-B3-D5 (hex) Code Blue Corporation +6D0000-6D0FFF (base 16) Code Blue Corporation + 259 Hedcor Street + Holland MI 49423 + US + +70-B3-D5 (hex) NimbeLink Corp +16F000-16FFFF (base 16) NimbeLink Corp + 3131 Fernbrook LN N, Ste 100 + Plymouth MN 55447 + US + +70-B3-D5 (hex) Birket Engineering +188000-188FFF (base 16) Birket Engineering + 162 W Plant St + Winter Garden FL 34787 + US + +70-B3-D5 (hex) Geppetto Electronics +11F000-11FFFF (base 16) Geppetto Electronics + 2784 Homestead Rd. #323 + Santa Clara CA 95051 + US + +70-B3-D5 (hex) Zhejiang Hao Teng Electronic Technology Co., Ltd. +563000-563FFF (base 16) Zhejiang Hao Teng Electronic Technology Co., Ltd. + Liandu District Information Industry Park 12 + Lishui ZhejiangZhejiang Hao Teng Electronic Technology Co., Ltd. 323000 + CN + +70-B3-D5 (hex) F-domain corporation +8C2000-8C2FFF (base 16) F-domain corporation + 157 Nakayashiki Sobue town + Inazawa city Aichi pref. 495-0001 + JP + +70-B3-D5 (hex) VAPE RAIL INTERNATIONAL +597000-597FFF (base 16) VAPE RAIL INTERNATIONAL + 9 RUE DES NOISETIERS + MONTREAL LA CLUSE 01460 + FR + +70-B3-D5 (hex) EarTex +462000-462FFF (base 16) EarTex + 41 Corsham Street + London England N1 6DR + GB + +70-B3-D5 (hex) RF Code +ADB000-ADBFFF (base 16) RF Code + 2600 Longhorn Blvd. ste 111 + Austin null 78758 + US + +70-B3-D5 (hex) REO AG +850000-850FFF (base 16) REO AG + Brühlerstr. 100 + Solingen 42657 + DE + +70-B3-D5 (hex) CT Company +5D5000-5D5FFF (base 16) CT Company + Godovikova , 9, Moscow + Moscow RUSSIA 129085 + RU + +70-B3-D5 (hex) Dream I System Co., Ltd +04B000-04BFFF (base 16) Dream I System Co., Ltd + #510, 298, Beotkkot-ro, Ceumcheon-gu + Seoul 08510 + KR + +70-B3-D5 (hex) DOSADORES ALLTRONIC +C3E000-C3EFFF (base 16) DOSADORES ALLTRONIC + RUA VALENTE DE NOVAIS, 270 + SÃO PAULO SAO PAULO 08120-420 + BR + +70-B3-D5 (hex) Novathings +81E000-81EFFF (base 16) Novathings + 100 Impasse des houilleres + MEYREUIL 13590 + FR + +70-B3-D5 (hex) Honeywell Safety Products USA, Inc +C0F000-C0FFFF (base 16) Honeywell Safety Products USA, Inc + 7828 Waterville Road + San Diego CA 92154 + US + +70-B3-D5 (hex) Delta Solutions LLC +0E5000-0E5FFF (base 16) Delta Solutions LLC + Kolokolnikov per., 22, building 5 + Moscow 107045 + RU + +70-B3-D5 (hex) Applied Materials +7E1000-7E1FFF (base 16) Applied Materials + 35 Dory Rd + Gloucester MA 01930 + US + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +BCC000-BCCFFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) OSR R&D ISRAEL LTD +AB0000-AB0FFF (base 16) OSR R&D ISRAEL LTD + 24 Magshimim St + Petah-Tikva 4934833 + IL + +70-B3-D5 (hex) Motec Pty Ltd +B77000-B77FFF (base 16) Motec Pty Ltd + 121 Merrindale Drive + Croydon South Victoria 3136 + AU + +70-B3-D5 (hex) CRDE +ACD000-ACDFFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) New Imaging Technologies +2AC000-2ACFFF (base 16) New Imaging Technologies + 1 impasse de la noisette, Bâtiment D, BP 426 + Verrières le buisson Essonne 91370 + FR + +70-B3-D5 (hex) Alpiq InTec Management AG +833000-833FFF (base 16) Alpiq InTec Management AG + Hohlstrasse 188 + Zürich 8004 + CH + +70-B3-D5 (hex) Netberg +CCF000-CCFFFF (base 16) Netberg + 2F-1 No.36, Park St., Nangang District + Taipei 11560 + TW + +70-B3-D5 (hex) Hudson Robotics +1DB000-1DBFFF (base 16) Hudson Robotics + 10 Stern Ave + Springfield NJ 07081 + US + +70-B3-D5 (hex) Asis Pro +593000-593FFF (base 16) Asis Pro + 27 Shaked st + Hevel Modiin Industrial Park 7319900 + IL + +70-B3-D5 (hex) Orbit International +B3F000-B3FFFF (base 16) Orbit International + 80 Cabot Ct + Hauppauge NY 11788 + US + +70-B3-D5 (hex) COMTECH Kft. +09F000-09FFFF (base 16) COMTECH Kft. + Torok Ignac u. 66. + Gyor Gyor-Moson-Sopron 9028 + HU + +70-B3-D5 (hex) Eginity, Inc. +910000-910FFF (base 16) Eginity, Inc. + 37 N Orange Ave STE 770 + Orlando 32801 + US + +70-B3-D5 (hex) Schneider Electric Motion USA +7D1000-7D1FFF (base 16) Schneider Electric Motion USA + 370 N. Main St. + Marlborough CT 06447 + US + +70-B3-D5 (hex) BELECTRIC GmbH +2B9000-2B9FFF (base 16) BELECTRIC GmbH + Wadenbrunner Str, 10 + Kolitzheim Bavaria 97509 + DE + +70-B3-D5 (hex) Xemex NV +AAA000-AAAFFF (base 16) Xemex NV + Metropoolstraat 11a + Schoten Antwerp BE-2900 + BE + +70-B3-D5 (hex) KST technology +012000-012FFF (base 16) KST technology + 164-1, KST b/d., Bangi-dong, songpa-gu + SEOUL N/A 138-050 + KR + +70-B3-D5 (hex) J-Factor Embedded Technologies +19E000-19EFFF (base 16) J-Factor Embedded Technologies + 1441 Laura Lane #201 + Pottstown PA 19464 + US + +70-B3-D5 (hex) ADTEK +1EF000-1EFFFF (base 16) ADTEK + 4F-18,No.14,Lane 609,Sec.5,Chongsin Rd.,Sanchong Dist, + New Taipei City Taiwan,(R.O.C) 24159 + TW + +70-B3-D5 (hex) Becton Dickinson +36A000-36AFFF (base 16) Becton Dickinson + 7 Loveton Circle + Sparks MD 21152 + US + +70-B3-D5 (hex) Vitsch Electronics +6A8000-6A8FFF (base 16) Vitsch Electronics + Dragonder 24-E + Valkenswaard Noord-Brabant 5554 GM + NL + +70-B3-D5 (hex) Intercomp S.p.A. +9B6000-9B6FFF (base 16) Intercomp S.p.A. + Via della Scienza, 27 + Verona 37139 + IT + +70-B3-D5 (hex) carbonTRACK +F35000-F35FFF (base 16) carbonTRACK + Level 2 104 Burwood Road + Hawthorn Vic 3122 + AU + +70-B3-D5 (hex) PPI Inc. +A21000-A21FFF (base 16) PPI Inc. + Cheomdan-Gwagiro 345 + Gwangju Buk-gu 61 008 + KR + +70-B3-D5 (hex) GridBridge Inc +CE5000-CE5FFF (base 16) GridBridge Inc + 130 Penmarc Drive, Suite 101 + Raleigh NC 27603 + US + +70-B3-D5 (hex) Sea Air and Land Communications Ltd +5AB000-5ABFFF (base 16) Sea Air and Land Communications Ltd + 10 Magdala Place + Christchurch Canterbury 8024 + NZ + +70-B3-D5 (hex) HBH Microwave GmbH +CD2000-CD2FFF (base 16) HBH Microwave GmbH + Helmholtzstr. 1 + Stutensee 76297 + DE + +70-B3-D5 (hex) Firefly RFID Solutions +8B3000-8B3FFF (base 16) Firefly RFID Solutions + 1521 Boone Trail Rd + Sanford NC 27330 + US + +70-B3-D5 (hex) Bartec GmbH +AAD000-AADFFF (base 16) Bartec GmbH + Max-Eyth-Str. 16 + Bad Mergentheim 97980 + DE + +70-B3-D5 (hex) POLSYSTEM SI SP. Z O.O., S.K.A. +B9E000-B9EFFF (base 16) POLSYSTEM SI SP. Z O.O., S.K.A. + Francuska 92 + Wrocław Dolnośląskie 54-405 + PL + +70-B3-D5 (hex) TSUBAKIMOTO CHAIN CO. +85B000-85BFFF (base 16) TSUBAKIMOTO CHAIN CO. + Nakanoshima Mitsui Building, 6F, 3-3-3, Nakanoshima + Kita-ku Osaka 530-0005 + JP + +70-B3-D5 (hex) Vtron Pty Ltd +E0F000-E0FFFF (base 16) Vtron Pty Ltd + Unit 2, 62 Township Drive West + West Burleigh Queensland 4219 + AU + +70-B3-D5 (hex) Shanghai Longpal Communication Equipment Co., Ltd. +896000-896FFF (base 16) Shanghai Longpal Communication Equipment Co., Ltd. + 18 LongPal Building, GuangFuLin Rd 4855 + Shanghai 201616 + CN + +70-B3-D5 (hex) GreenFlux +12E000-12EFFF (base 16) GreenFlux + Mauritskade 63 + Amsterdam 1092 AD + NL + +70-B3-D5 (hex) SLAT +349000-349FFF (base 16) SLAT + 11 Rue Jean-Elysée DUPUY + Champagne au Mont d'Or Rhône 69543 + FR + +70-B3-D5 (hex) CIELLE S.R.L. +12C000-12CFFF (base 16) CIELLE S.R.L. + VIA TONIOLO, 6 + PERO DI BREDA DI PIAVE TREVISO 31030 + IT + +70-B3-D5 (hex) QuirkLogic +885000-885FFF (base 16) QuirkLogic + 3600 4th Street SE + Calgary Alberta T2G2W3 + CA + +70-B3-D5 (hex) Critical Link LLC +761000-761FFF (base 16) Critical Link LLC + 6712 BROOKLAWN PKWY + SYRACUSE NY 13211 + US + +70-B3-D5 (hex) Moving iMage Technologies LLC +4C5000-4C5FFF (base 16) Moving iMage Technologies LLC + 17760 Newhope Street Suite B + Fountain Valley CA 92708 + US + +70-B3-D5 (hex) Ideas srl +9FA000-9FAFFF (base 16) Ideas srl + Via dei Brughi, 21 + Gessate Milan 20060 + IT + +70-B3-D5 (hex) M2M Cybernetics Pvt Ltd +FCA000-FCAFFF (base 16) M2M Cybernetics Pvt Ltd + GH-11, Ahinsa Khand 2, Indirapuram + Ghaziabad Uttar Pradesh 201010 + IN + +70-B3-D5 (hex) Procon Electronics Pty Ltd +55B000-55BFFF (base 16) Procon Electronics Pty Ltd + P O Box 164 + Seven Hills NSW 1730 + AU + +70-B3-D5 (hex) Samriddi Automations Pvt. Ltd. +11C000-11CFFF (base 16) Samriddi Automations Pvt. Ltd. + F-365 + Noida up 201307 + IN + +70-B3-D5 (hex) Promess Inc. +1DA000-1DAFFF (base 16) Promess Inc. + 11429 Grand River + Brighton MI 48116 + US + +70-B3-D5 (hex) GIFAS-ELECTRIC GmbH +650000-650FFF (base 16) GIFAS-ELECTRIC GmbH + Dietrichstrasse 2 + Rheineck St.Gallen 9424 + CH + +70-B3-D5 (hex) Netool LLC +75B000-75BFFF (base 16) Netool LLC + 18515 san Antonio street + fountain valley CA 92708 + US + +70-B3-D5 (hex) ROMO Wind A/S +147000-147FFF (base 16) ROMO Wind A/S + Olof Palmes Allé 47 + Aarhus N 8200 + DK + +70-B3-D5 (hex) Aplex Technology Inc. +906000-906FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) Zoe Medical +721000-721FFF (base 16) Zoe Medical + 460 Boston Street + Topsfield MA 01983 + US + +70-B3-D5 (hex) UNMANNED SPA +0D2000-0D2FFF (base 16) UNMANNED SPA + sevilla lote 13 s/n + Valdivia Los Rios 5090000 + CL + +70-B3-D5 (hex) Grossenbacher Systeme AG +C91000-C91FFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) ART SPA +6B5000-6B5FFF (base 16) ART SPA + VOC.PISCHIELLO, 20 + PASSIGNANO SUL TRASIMENO PG 06065 + IT + +70-B3-D5 (hex) Aplex Technology Inc. +65A000-65AFFF (base 16) Aplex Technology Inc. + 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District + Shenzhen Guangdong 518054 + CN + +70-B3-D5 (hex) Aplex Technology Inc. +7CE000-7CEFFF (base 16) Aplex Technology Inc. + 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District + Shenzhen Guangdong 518054 + CN + +70-B3-D5 (hex) GWF MessSysteme AG +387000-387FFF (base 16) GWF MessSysteme AG + Obergrundstrasse 119 + Luzern 6002 + CH + +70-B3-D5 (hex) Power Ltd. +776000-776FFF (base 16) Power Ltd. + Kazal str. 64-66 + Budapest 1031 + HU + +70-B3-D5 (hex) CTG sp. z o. o. +396000-396FFF (base 16) CTG sp. z o. o. + ul. Katowicka 24 + Jastrzebie-Zdroj 44-335 + PL + +70-B3-D5 (hex) Grossenbacher Systeme AG +297000-297FFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) UB330.net d.o.o. +B72000-B72FFF (base 16) UB330.net d.o.o. + Radio cesta 1 + Domzale 1230 + SI + +70-B3-D5 (hex) Living Water +367000-367FFF (base 16) Living Water + 629 Yorkshire Ct + Livermore CA 94551 + US + +70-B3-D5 (hex) Telaeris, Inc. +7DE000-7DEFFF (base 16) Telaeris, Inc. + 9123 Chesapeake Dr. + San Diego CA 92123 + US + +70-B3-D5 (hex) WiTagg, Inc +4FE000-4FEFFF (base 16) WiTagg, Inc + 1045 Linda Vista Avenue + Mountain View CA 94043 + US + +70-B3-D5 (hex) Andium +0BD000-0BDFFF (base 16) Andium + 609 E 11th Street, 2B + New York NY 10009 + US + +70-B3-D5 (hex) StreamPlay Oy Ltd +D2B000-D2BFFF (base 16) StreamPlay Oy Ltd + Sarankulmankatu 12 B + Tampere 33900 + FI + +70-B3-D5 (hex) KMtronic ltd +3A5000-3A5FFF (base 16) KMtronic ltd + Dobri Czintulov 28A str. + Gorna Oryahovica VT 5100 + BG + +70-B3-D5 (hex) Spanawave Corporation +DFF000-DFFFFF (base 16) Spanawave Corporation + 1640 Lead Hill Blvd., Suite 130 + Roseville CA 95661 + US + +70-B3-D5 (hex) SEASON DESIGN TECHNOLOGY +10A000-10AFFF (base 16) SEASON DESIGN TECHNOLOGY + FLOOR 4, WARDS EXCHANGE, 199 ECCLESALL ROAD + SHEFFIELD SOUTH YORKSHIRE S11 8HW + GB + +70-B3-D5 (hex) Groupe Citypassenger Inc +E7E000-E7EFFF (base 16) Groupe Citypassenger Inc + 1117 sainte catherine ouest + Montreal Quebec H3B1H9 + CA + +70-B3-D5 (hex) Voltaware Limited +277000-277FFF (base 16) Voltaware Limited + 282 Earls Court Road + London London SW5 9AS + GB + +70-B3-D5 (hex) United States Technologies Inc. +74F000-74FFFF (base 16) United States Technologies Inc. + 1701 Pollitt Drive + Fair Lawn NJ 07410 + US + +70-B3-D5 (hex) Sycomp Electronic GmbH +3F6000-3F6FFF (base 16) Sycomp Electronic GmbH + Einsteinstr 7 + Dachau 85221 + DE + +70-B3-D5 (hex) GILLAM-FEI S.A. +31E000-31EFFF (base 16) GILLAM-FEI S.A. + Mont St Martin 58 + LIEGE B4000 + BE + +70-B3-D5 (hex) ISAC SRL +ADE000-ADEFFF (base 16) ISAC SRL + via Maestri del Lavoro 30 + CASCINA PISA 56021 + IT + +70-B3-D5 (hex) HMicro Inc +8C5000-8C5FFF (base 16) HMicro Inc + 39355 California St., Suite 303 + Fremont null 94538 + US + +70-B3-D5 (hex) Par-Tech, Inc. +47C000-47CFFF (base 16) Par-Tech, Inc. + 139 Premier Dr. + Lake Orion MI 48359 + US + +70-B3-D5 (hex) Beeper Communications Ltd. +8EF000-8EFFFF (base 16) Beeper Communications Ltd. + No6, Hataas str. + Ramat-Gan 5251247 + IL + +70-B3-D5 (hex) Impulse Networks Pte Ltd +493000-493FFF (base 16) Impulse Networks Pte Ltd + 1 Raffles Place, #44-08 Raffles Place + Singapore 048616 + SG + +70-B3-D5 (hex) CARE PVT LTD +FE4000-FE4FFF (base 16) CARE PVT LTD + 19-A Attaturk Avenue G-5/1 + Islamabad Fedral Capital 44000 + PK + +70-B3-D5 (hex) Silicon Safe Ltd +544000-544FFF (base 16) Silicon Safe Ltd + St John's Innovation centre, Crowley road + Cambridge Cambridgeshire Cb4 ows + GB + +70-B3-D5 (hex) Les distributions Multi-Secure incorporee +FEB000-FEBFFF (base 16) Les distributions Multi-Secure incorporee + 7 Provost + La Prairie Quebec J5R 5Y7 + CA + +70-B3-D5 (hex) Redco Audio Inc +429000-429FFF (base 16) Redco Audio Inc + 1701 Stratford Ave + Stratford CT 06615 + US + +70-B3-D5 (hex) DEUTA-WERKE GmbH +202000-202FFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) Lucas-Nülle GmbH +0B8000-0B8FFF (base 16) Lucas-Nülle GmbH + Siemensstr. 2 + Kerpen NRW 50170 + DE + +70-B3-D5 (hex) INTERNET PROTOCOLO LOGICA SL +B93000-B93FFF (base 16) INTERNET PROTOCOLO LOGICA SL + Sector Foresta 43, local 26 + Tres Cantos Madrid 28760 + ES + +70-B3-D5 (hex) CRDE +592000-592FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) RIC Electronics +12B000-12BFFF (base 16) RIC Electronics + 1 - 5628 Riverbend Drive + Burnaby BC V3N 0C1 + CA + +70-B3-D5 (hex) Vocality International Ltd +0FE000-0FEFFF (base 16) Vocality International Ltd + Lydling Barn + Shackleford Surrey GU8 6AP + GB + +70-B3-D5 (hex) 2-Observe +14D000-14DFFF (base 16) 2-Observe + Rue du Bois Saint-Jean, 15/1 + Sereing Liège 4102 + BE + +70-B3-D5 (hex) FLEXTRONICS +216000-216FFF (base 16) FLEXTRONICS + Carretera Base Aerea 5850 int 4 + Zapopan Jalisco 45136 + MX + +70-B3-D5 (hex) Dynacard Co., Ltd. +955000-955FFF (base 16) Dynacard Co., Ltd. + 1F.,No.19-1,Ln.222,Dunhua N.Rd. + Taipei Tapei 105 + TW + +70-B3-D5 (hex) GLIAL TECHNOLOGY +6A1000-6A1FFF (base 16) GLIAL TECHNOLOGY + 7 Rue Aristide Briand + Nuits-Saint-Georges 21700 + FR + +70-B3-D5 (hex) Integrated Control Corp. +895000-895FFF (base 16) Integrated Control Corp. + 748 Park Ave + Huntington NY 11743 + US + +70-B3-D5 (hex) TTI Ltd +3CA000-3CAFFF (base 16) TTI Ltd + 5-y Donskoy pr-d, 15с2 + Moscow 119334 + RU + +70-B3-D5 (hex) CASWA +5BE000-5BEFFF (base 16) CASWA + Unit2/33 Horus bend + Bibra Lake WA 6163 + AU + +70-B3-D5 (hex) Detec Systems Ltd +13C000-13CFFF (base 16) Detec Systems Ltd + 1728 Shearwater Terrace + Sidney BC V8L 5L4 + CA + +70-B3-D5 (hex) Toray Medical Co.,Ltd +2FA000-2FAFFF (base 16) Toray Medical Co.,Ltd + 405-65 onoue ashitaka + numadu shizuoka 410-0001 + JP + +70-B3-D5 (hex) Solvera Lynx d.d. +7F8000-7F8FFF (base 16) Solvera Lynx d.d. + Stegne 23A + 1000 Ljubljana Ljubljana 00386 + SI + +70-B3-D5 (hex) OOO Research and Production Center Computer Technologies +4C4000-4C4FFF (base 16) OOO Research and Production Center Computer Technologies + Komsomolsky avenue, 90-17 + Perm Perm Region 614010 + RU + +70-B3-D5 (hex) Momentum Data Systems +E45000-E45FFF (base 16) Momentum Data Systems + 5432 Bolsa Ave Unit B + Huntington Beach CA 92649 + US + +70-B3-D5 (hex) Skreens +EB7000-EB7FFF (base 16) Skreens + 22 Ames Road + Foxboro MA 02035 + US + +70-B3-D5 (hex) VirtualHere Pty. Ltd. +F56000-F56FFF (base 16) VirtualHere Pty. Ltd. + 6/5 Wentworth St + Manly NSW 2095 + AU + +70-B3-D5 (hex) ABB +892000-892FFF (base 16) ABB + Fulachstrasse 150 + Schaffhausen 8200 + CH + +70-B3-D5 (hex) Transportal Solutions Ltd +EA2000-EA2FFF (base 16) Transportal Solutions Ltd + The Offices @ The Old Cow Barn + Masham North Yorkshire HG4 4NE + GB + +70-B3-D5 (hex) Power Electronics Espana, S.L. +148000-148FFF (base 16) Power Electronics Espana, S.L. + C/ Leonardo Da Vinci, 24-26 + Paterna Valencia 46980 + ES + +70-B3-D5 (hex) Cubitech +893000-893FFF (base 16) Cubitech + 4-6 Kiprou str + Tavros Athens 17778 + GR + +70-B3-D5 (hex) Kokam Co., Ltd +A2E000-A2EFFF (base 16) Kokam Co., Ltd + 1022, Gyeongsu-daero, Jangan-gu + Suwon-si Gyeonggi-do 16203 + KR + +70-B3-D5 (hex) Digital Outfit +353000-353FFF (base 16) Digital Outfit + 329 15th St E + North Vancouver BC V7L 2R6 + CA + +70-B3-D5 (hex) A.F.MENSAH, INC +F5B000-F5BFFF (base 16) A.F.MENSAH, INC + 252 NASSAU ST, 2ND FLOOR + PRINCETON NJ 08542 + US + +70-B3-D5 (hex) Business Marketers Group, Inc. +A72000-A72FFF (base 16) Business Marketers Group, Inc. + N56W24720 N. Corporate Circle + Sussex WI 53089 + US + +70-B3-D5 (hex) BBR Verkehrstechnik GmbH +AEA000-AEAFFF (base 16) BBR Verkehrstechnik GmbH + Pillaustrasse 1e + Braunschweig 38126 + DE + +70-B3-D5 (hex) Qowisio +F6D000-F6DFFF (base 16) Qowisio + 4 rue fulton + Angers 49000 + FR + +70-B3-D5 (hex) TATTILE SRL +0D6000-0D6FFF (base 16) TATTILE SRL + via G.Donizetti 1/3/5 + Brescia 25030 + IT + +70-B3-D5 (hex) infrachip +551000-551FFF (base 16) infrachip + Danwan-Gu, Yeonsuwan-Ro, Post-Bi Center + Ansan Gyeonggi 425-849 + KR + +70-B3-D5 (hex) MAHLE +B7A000-B7AFFF (base 16) MAHLE + 23030 Haggerty Road + Farmington Hills MI 48335 + US + +70-B3-D5 (hex) Becton Dickinson +6C7000-6C7FFF (base 16) Becton Dickinson + 7 Loveton Circle + Sparks MD 21152 + US + +70-B3-D5 (hex) Shenzhen Riitek Technology Co.,Ltd +913000-913FFF (base 16) Shenzhen Riitek Technology Co.,Ltd + 4F, Building1, Zhongkenou Industry Park, Hezhou Development, Baoan district, + Shenzhen, 518000 + CN + +70-B3-D5 (hex) BEEcube Inc. +CC1000-CC1FFF (base 16) BEEcube Inc. + 39465 Paseo Padre Pkwy + Fremont CA 94538 + US + +70-B3-D5 (hex) Syncopated Engineering Inc +522000-522FFF (base 16) Syncopated Engineering Inc + 13136 Williamfield Dr + Ellicott City MD 21042 + US + +70-B3-D5 (hex) ATS-CONVERS +901000-901FFF (base 16) ATS-CONVERS + Yana Fabrittsyusa str., 10 + Pskov 180017 + RU + +70-B3-D5 (hex) EMAC, Inc. +654000-654FFF (base 16) EMAC, Inc. + 2390 EMAC Way + Carbondale IL 62901 + US + +70-B3-D5 (hex) Kuebrich Ingeniergesellschaft mbh & Co. KG +CB6000-CB6FFF (base 16) Kuebrich Ingeniergesellschaft mbh & Co. KG + Weissmuehle 10 + Priesendorf 96170 + DE + +70-B3-D5 (hex) Zehnder Group Nederland +426000-426FFF (base 16) Zehnder Group Nederland + Postbus 621 + Zwolle 8000 AP + NL + +70-B3-D5 (hex) Rational Production srl Unipersonale +D70000-D70FFF (base 16) Rational Production srl Unipersonale + Via L. Galvani 7/H + Albano S. Alessandro Bergamo 24061 + IT + +70-B3-D5 (hex) Harbin Cheng Tian Technology Development Co., Ltd. +CF4000-CF4FFF (base 16) Harbin Cheng Tian Technology Development Co., Ltd. + ROOM140,Building21A,145 Nantong Street + Harbin Heilongjiang 150001 + CN + +70-B3-D5 (hex) SHEN ZHEN TTK TECHNOLOGY CO,LTD +4B9000-4B9FFF (base 16) SHEN ZHEN TTK TECHNOLOGY CO,LTD + 8/F, Nan Yuan commerical Bldg,Minzhi,Long Hua town,Baoan,district,Shenzhen + SHEN ZHEN GuangDong 51813 + CN + +70-B3-D5 (hex) Electronic Navigation Ltd +B7C000-B7CFFF (base 16) Electronic Navigation Ltd + 65 Gaunt Street + Auckland 1010 + NZ + +70-B3-D5 (hex) Sinoembed +83C000-83CFFF (base 16) Sinoembed + RM1105,No 2078,YueLiangWan Road,NanShan District + ShenZhen GuangDong 518000 + CN + +70-B3-D5 (hex) NORTHBOUND NETWORKS PTY. LTD. +6CD000-6CDFFF (base 16) NORTHBOUND NETWORKS PTY. LTD. + 14 Sommersby Road + Point Cook Victoria 3030 + AU + +70-B3-D5 (hex) Critical Link LLC +AF9000-AF9FFF (base 16) Critical Link LLC + 6712 Brooklawn Parkway + Syracuse null 13211 + US + +70-B3-D5 (hex) WyreStorm Technologies Ltd +D5A000-D5AFFF (base 16) WyreStorm Technologies Ltd + 445 Hoes Lane + Piscataway NJ 08554 + US + +70-B3-D5 (hex) WyreStorm Technologies Ltd +D5B000-D5BFFF (base 16) WyreStorm Technologies Ltd + 445 Hoes Lane + Piscataway NJ 08554 + US + +70-B3-D5 (hex) Unitro Fleischmann +C92000-C92FFF (base 16) Unitro Fleischmann + Gaildorfer Strasse 15 + Backnang 71522 + DE + +70-B3-D5 (hex) Aplex Technology Inc. +F57000-F57FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) Sienna Corporation +13B000-13BFFF (base 16) Sienna Corporation + 475 Horizon drive + Suwanee GA 30024 + US + +70-B3-D5 (hex) Monnit Corporation +377000-377FFF (base 16) Monnit Corporation + 450 South Simmons STE 670 + Kaysville UT 84037 + US + +70-B3-D5 (hex) Virta Laboratories, Inc. +140000-140FFF (base 16) Virta Laboratories, Inc. + 1327 Jones Dr + Ann Arbor Michigan 48105 + US + +70-B3-D5 (hex) ARECO +C07000-C07FFF (base 16) ARECO + 114 chemin de Saint Marc + GRASSE PACA 06130 + FR + +70-B3-D5 (hex) Foro Tel +18D000-18DFFF (base 16) Foro Tel + 77, Shaumyana Str. + Rostov-na-Donu UFO 344079 + RU + +70-B3-D5 (hex) SPX Flow Technology BV +01F000-01FFFF (base 16) SPX Flow Technology BV + Munnikenheiweg 41 + Etten-Leur Noord-Braband 4879NE + NL + +70-B3-D5 (hex) Nxcontrol system Co., Ltd. +CA9000-CA9FFF (base 16) Nxcontrol system Co., Ltd. + 10F, No. 257, Wenxing Rd. + Zhubei City Hsinchu county 30264 + TW + +70-B3-D5 (hex) GridNavigator +EDF000-EDFFFF (base 16) GridNavigator + 200 Varick Street #508 + New York NY 10014 + US + +70-B3-D5 (hex) DSan Corporation +DCA000-DCAFFF (base 16) DSan Corporation + 142 Mineola Avenue + Roslyn Heights NY 11577 + US + +70-B3-D5 (hex) IntelliDesign Pty Ltd +061000-061FFF (base 16) IntelliDesign Pty Ltd + 99 Bluestone Circuit + Seventeen Mile Rocks Qld 4073 + AU + +70-B3-D5 (hex) ISPHER +517000-517FFF (base 16) ISPHER + Chemin des Aulx 21 + PLAN LES OUATES CANTON DE GENEVE 1228 + CH + +70-B3-D5 (hex) LPA Excil Electronics +383000-383FFF (base 16) LPA Excil Electronics + Ripley Drive + Wakefield West Yorkshire WF6 1QT + GB + +70-B3-D5 (hex) HIPODROMO DE AGUA CALIENTE SA CV +328000-328FFF (base 16) HIPODROMO DE AGUA CALIENTE SA CV + BLVD AGUA CALIENTE 12027 + TIJUANA BAJA CALIFORNIA 22420 + MX + +70-B3-D5 (hex) neocontrol soluções em automação +891000-891FFF (base 16) neocontrol soluções em automação + rua santa fe 100 + belo horizonte MG 30320-130 + BR + +70-B3-D5 (hex) ERAESEEDS co.,ltd. +8F0000-8F0FFF (base 16) ERAESEEDS co.,ltd. + 284-2, WONHYORO3-GA, YONGSAN-GU + SEOUL 140-849 + KR + +70-B3-D5 (hex) Sportzcast +D29000-D29FFF (base 16) Sportzcast + 1144 Citrus Oaks Run + Winter Springs FL 32708 + US + +70-B3-D5 (hex) TCI +7F2000-7F2FFF (base 16) TCI + 3541 Gateway Blvd + Fremont CA 94538 + US + +70-B3-D5 (hex) DELTA +E4B000-E4BFFF (base 16) DELTA + Venlighedsvej 4 + Horsholm Denmark 2970 + DK + +70-B3-D5 (hex) GLT Exports Ltd +34C000-34CFFF (base 16) GLT Exports Ltd + Detection House + Swansea County of Swansea SA1 2EN + GB + +70-B3-D5 (hex) Tanaka Electric Industry Co., Ltd. +52D000-52DFFF (base 16) Tanaka Electric Industry Co., Ltd. + 7-3-31 Takadono, + Osaka-shi Osaka 535-0031 + JP + +70-B3-D5 (hex) Pantec Engineering AG +BE5000-BE5FFF (base 16) Pantec Engineering AG + Industriering 21 + Ruggell Principality of Liechtenstein 9491 + LI + +70-B3-D5 (hex) Transtronic AB +ECA000-ECAFFF (base 16) Transtronic AB + Fabriksgatan 1 + Köping Västmanland 73124 + SE + +70-B3-D5 (hex) Techworld Industries Ltd +1AD000-1ADFFF (base 16) Techworld Industries Ltd + Unit 1705, 17/F, Nanyang Plaza, 57 Hung To Road, + Hong Kong N/A N/A + HK + +70-B3-D5 (hex) Domus S.C. +E6D000-E6DFFF (base 16) Domus S.C. + 87 A Oriente #1623 Local A + Puebla Puebla 72587 + MX + +70-B3-D5 (hex) Vena Engineering Corporation +FBB000-FBBFFF (base 16) Vena Engineering Corporation + 7 Hangar Way + Watsonville CA 95076 + US + +70-B3-D5 (hex) OptiScan Biomedical Corp. +088000-088FFF (base 16) OptiScan Biomedical Corp. + 24590 Clawiter Road + Hayward CA 94545 + US + +70-B3-D5 (hex) Cymtec Ltd +903000-903FFF (base 16) Cymtec Ltd + Tredomen Business Centre + Ystrad Mynach Caerphilly CF82 7FN + GB + +70-B3-D5 (hex) Trimble +76D000-76DFFF (base 16) Trimble + 6-8 Kondorfa street + Budapest 1116 + HU + +70-B3-D5 (hex) Acorde Technologies +9F2000-9F2FFF (base 16) Acorde Technologies + PCTCAN - Av. Albert Einstein, 6 + Santander Cantabria 39011 + ES + +70-B3-D5 (hex) Elesar Limited +03F000-03FFFF (base 16) Elesar Limited + Future Business Centre + Cambridge Cambridgeshire CB4 2HY + GB + +70-B3-D5 (hex) ASL Holdings +F73000-F73FFF (base 16) ASL Holdings + The Oaks + Pitsford Northants NN6 9AA + GB + +70-B3-D5 (hex) VendNovation LLC +1E5000-1E5FFF (base 16) VendNovation LLC + 13400 NE 20th Street + Bellevue WA 98005 + US + +70-B3-D5 (hex) Kron Medidores +72D000-72DFFF (base 16) Kron Medidores + Rua Alexandre de Gusmão, 278 + São Paulo São Paulo 04760-020 + BR + +70-B3-D5 (hex) Remote Sensing Solutions, Inc. +3D7000-3D7FFF (base 16) Remote Sensing Solutions, Inc. + 3179 MAIN ST UNIT 3 + BARNSTABLE MA 02630 + US + +70-B3-D5 (hex) Revolution Retail Systems +F54000-F54FFF (base 16) Revolution Retail Systems + 1840 Hutton Drive + Carrollton Texas 75006 + US + +70-B3-D5 (hex) Nasdaq +0E6000-0E6FFF (base 16) Nasdaq + 165 Broadway + New York NY 10006 + US + +70-B3-D5 (hex) Tempus Fugit Consoles bvba +087000-087FFF (base 16) Tempus Fugit Consoles bvba + Albert I-straat 40 + Schepdaal n/a 1703 + BE + +70-B3-D5 (hex) Cloud4Wi +45F000-45FFFF (base 16) Cloud4Wi + 22 Cleveland St + San Francisco CALIFORNIA 94103 + US + +70-B3-D5 (hex) Software Systems Plus +F01000-F01FFF (base 16) Software Systems Plus + 9924 N. Ash Avenue + Kansas City MISSOURI 64157 + US + +70-B3-D5 (hex) BELT S.r.l. +E55000-E55FFF (base 16) BELT S.r.l. + Corso Vinzaglio, 2 + Torino TO 10121 + IT + +70-B3-D5 (hex) DSIT Solutions LTD +B47000-B47FFF (base 16) DSIT Solutions LTD + Rechvam Zeevi 2 + Givat-Shmuel 5401777 + IL + +70-B3-D5 (hex) Inspike S.R.L. +2F1000-2F1FFF (base 16) Inspike S.R.L. + via G. De Castillia 7 + Vimercate MB 20871 + IT + +70-B3-D5 (hex) SEMEX-EngCon GmbH +789000-789FFF (base 16) SEMEX-EngCon GmbH + Pforzheimer Str. 202D + Ettlingen Baden-Wuerttemberg 76275 + DE + +70-B3-D5 (hex) B.E.A. sa +0DF000-0DFFFF (base 16) B.E.A. sa + Allée des Noisetiers 5 + Angleur Liege 4031 + BE + +70-B3-D5 (hex) Private +119000-119FFF (base 16) Private + +70-B3-D5 (hex) SP Controls +823000-823FFF (base 16) SP Controls + 930 Linde Ave + South San Francisco CA 94080 + US + +70-B3-D5 (hex) eumig industrie-tv GmbH +923000-923FFF (base 16) eumig industrie-tv GmbH + Gewerbeparkstr. 9 + Anif Salzburg 5081 + AT + +70-B3-D5 (hex) 3City Electronics +146000-146FFF (base 16) 3City Electronics + Jaskowa Dolina 9/5a + Gdansk pomorskie 80-252 + PL + +70-B3-D5 (hex) Subinitial LLC +D9C000-D9CFFF (base 16) Subinitial LLC + 10160 Three Oaks Way + Santee CA 92071 + US + +70-B3-D5 (hex) Wuhan Xingtuxinke ELectronic Co.,Ltd +435000-435FFF (base 16) Wuhan Xingtuxinke ELectronic Co.,Ltd + NO.C3-8F,Software Park,Optics Valley,East Lake Development Zone,Wuhan,Hubei,China + Wuhan Hubei 430074 + CN + +70-B3-D5 (hex) DSP DESIGN LTD +208000-208FFF (base 16) DSP DESIGN LTD + TAPTON PARK INNOVATION CENTRE + CHESTERFIELD DERBYSHIRE S41 0TZ + GB + +70-B3-D5 (hex) HOERMANN GmbH +B78000-B78FFF (base 16) HOERMANN GmbH + Hauptstr. 45-47 + Kirchseeon Bavaria 85614 + DE + +70-B3-D5 (hex) Private +D0A000-D0AFFF (base 16) Private + +70-B3-D5 (hex) CSINFOTEL +C97000-C97FFF (base 16) CSINFOTEL + 3F, daedeok-daero 566, Yuseong-gu, Daejeon + Daejeon Republic of Korea 305-340 + KR + +70-B3-D5 (hex) Protium Technologies, Inc. +459000-459FFF (base 16) Protium Technologies, Inc. + 10 Bearfoot Rd. + Northborough MA 01532 + US + +70-B3-D5 (hex) Midfin Systems +E4E000-E4EFFF (base 16) Midfin Systems + 2509 152nd Ave NE + Redmond WA 98052 + US + +70-B3-D5 (hex) Wallner Automation GmbH +5A2000-5A2FFF (base 16) Wallner Automation GmbH + Kenzianweg 8 + Schaerding Upper Austria A-4780 + AT + +70-B3-D5 (hex) Intelligent Energy Ltd +C55000-C55FFF (base 16) Intelligent Energy Ltd + Holywell Park + Loughborough Leicestershire LE11 3GB + GB + +70-B3-D5 (hex) Creotech Instruments S.A. +91E000-91EFFF (base 16) Creotech Instruments S.A. + ul. Gen. L. Okulickiego 7/9 + Piaseczno Mazovia 05-500 + PL + +70-B3-D5 (hex) McKay Brothers LLC +A4B000-A4BFFF (base 16) McKay Brothers LLC + 2355 Broadway + Oakland CA 94612 + US + +70-B3-D5 (hex) Energybox Limited +FA4000-FA4FFF (base 16) Energybox Limited + 4901 Central Plaza, 18 Harbour Road + Wanchai Hong Kong 0000 + HK + +70-B3-D5 (hex) OrbiWise SA +078000-078FFF (base 16) OrbiWise SA + c/o Fongit + Plan-les-Ouates Geneva 1228 + CH + +70-B3-D5 (hex) Trident RFID Pty Ltd +73E000-73EFFF (base 16) Trident RFID Pty Ltd + Unit 1/24 Redcliffe Gardens Drive + Clontarf QLD 4019 + AU + +70-B3-D5 (hex) APEN GROUP SpA (VAT IT08767740155) +EAB000-EABFFF (base 16) APEN GROUP SpA (VAT IT08767740155) + Via Isonzo 1 + Pessano con Bornago MI 20060 + IT + +70-B3-D5 (hex) ACD Elektronik GmbH +C5B000-C5BFFF (base 16) ACD Elektronik GmbH + Engelberg 2 + Achstetten 88480 + DE + +70-B3-D5 (hex) Getein Biotechnology Co.,ltd +E90000-E90FFF (base 16) Getein Biotechnology Co.,ltd + No.9 Bofu Road,Luhe District, Nanjing,china + Nanjing jiangsu 211505 + CN + +70-B3-D5 (hex) Russian Telecom Equipment Company +0D7000-0D7FFF (base 16) Russian Telecom Equipment Company + 3, Kapranov lane + Moscow Moscow 123242 + RU + +70-B3-D5 (hex) WiViCom Co., Ltd. +B29000-B29FFF (base 16) WiViCom Co., Ltd. + 602 Shichiku Sogo Building + Niigata Niigata 950-0916 + JP + +70-B3-D5 (hex) Tornado Modular Systems +CF6000-CF6FFF (base 16) Tornado Modular Systems + Inzhenernaya st. 4a + Novosibirsk Novosibirsk 630128 + RU + +70-B3-D5 (hex) Solace Systems Inc. +44E000-44EFFF (base 16) Solace Systems Inc. + 535 Legget Drive, + Kanata Ontario K2K3B8 + CA + +70-B3-D5 (hex) Verti Tecnologia +CB8000-CB8FFF (base 16) Verti Tecnologia + Praça Osório, 437, 5º andar + Curitiba Parana 80020-010 + BR + +70-B3-D5 (hex) HEADROOM Broadcast GmbH +D48000-D48FFF (base 16) HEADROOM Broadcast GmbH + RudowerChaussee 29/31 + Berlin Berlin 12489 + DE + +70-B3-D5 (hex) Telenor Connexion AB +27D000-27DFFF (base 16) Telenor Connexion AB + 116 88 + Stockholm Sverige SE-116 88 + SE + +70-B3-D5 (hex) Datasat Digital Entertainment +B24000-B24FFF (base 16) Datasat Digital Entertainment + 9631 Topanga Canyon Place + Chatsworth California 91311 + US + +70-B3-D5 (hex) Sensortech Systems Inc. +BEF000-BEFFFF (base 16) Sensortech Systems Inc. + 2221 E. Celsius Avenue + Oxnard CA 93030 + US + +70-B3-D5 (hex) Imagine Inc. +3D2000-3D2FFF (base 16) Imagine Inc. + 2-24-1-915 Kamiosaki + Shinagawa-Ku Tokyo 141-0021 + JP + +70-B3-D5 (hex) Task Sistemas +181000-181FFF (base 16) Task Sistemas + Rua Visconde de Ouro Preto 5/8 + Rio de Janeiro RJ 22250180 + BR + +70-B3-D5 (hex) Sicon srl +36C000-36CFFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) Bandelin electronic GmbH & Co. KG +A99000-A99FFF (base 16) Bandelin electronic GmbH & Co. KG + Heinrichstraße 3-4 + Berlin Berlin 12207 + DE + +70-B3-D5 (hex) TOFWERK AG +732000-732FFF (base 16) TOFWERK AG + Uttigenstrasse 22 + Thun BE 3600 + CH + +70-B3-D5 (hex) Becker Nachrichtentechnik GmbH +820000-820FFF (base 16) Becker Nachrichtentechnik GmbH + Kapellenweg 3 + Asbach Rheinland-Pfalz 53567 + DE + +70-B3-D5 (hex) LSL systems +58F000-58FFFF (base 16) LSL systems + 303. SanHak. Hallym university. + Chuncheon. KW 200-702 + KR + +70-B3-D5 (hex) Assembly Contracts Ltd +B8F000-B8FFFF (base 16) Assembly Contracts Ltd + Ledson Road + Manchester Lancashire M23 9GP + GB + +70-B3-D5 (hex) POLVISION +610000-610FFF (base 16) POLVISION + ul. Witkowska 16 + Wrocław woj. dolnośląskie 51-003 + PL + +70-B3-D5 (hex) HUSTY M.Styczen J.Hupert Sp.J. +77C000-77CFFF (base 16) HUSTY M.Styczen J.Hupert Sp.J. + Rzepakowa 5e + Krakow malopolska 31-989 + PL + +70-B3-D5 (hex) PANORAMIC POWER +07D000-07DFFF (base 16) PANORAMIC POWER + 20 ATIR YEDA ST. + KFAR-SABA ISRAEL 44643 + IL + +70-B3-D5 (hex) DTECH Labs, Inc. +CFF000-CFFFFF (base 16) DTECH Labs, Inc. + 22876 Shaw Rd + Sterling Virginia 20166 + US + +70-B3-D5 (hex) NimbeLink Corp +D3B000-D3BFFF (base 16) NimbeLink Corp + 3131 Fernbrook LN N, Ste 100 + Plymouth MN 55447 + US + +70-B3-D5 (hex) iotec GmbH +E28000-E28FFF (base 16) iotec GmbH + Albert-Einstein-Str. 1 + Osnabrück Niedersachsen 49076 + DE + +70-B3-D5 (hex) June Automation Singapore Pte. Ltd. +CE7000-CE7FFF (base 16) June Automation Singapore Pte. Ltd. + blk4008 #02-03, + Singapore N/A 569625 + SG + +70-B3-D5 (hex) Thurlby Thandar Instruments LTD +E58000-E58FFF (base 16) Thurlby Thandar Instruments LTD + Glebe Road + Huntingdon Cambridgeshire PE29 7DR + GB + +70-B3-D5 (hex) Future Skies +C43000-C43FFF (base 16) Future Skies + 1333 Campus Parkway + Neptune New Jersey 07753 + US + +70-B3-D5 (hex) Xafax Nederland bv +EC1000-EC1FFF (base 16) Xafax Nederland bv + Postbus 107 + Alkmaar NH 1800AC + NL + +70-B3-D5 (hex) LightDec GmbH & Co. KG +CF1000-CF1FFF (base 16) LightDec GmbH & Co. KG + Robert-Bosch-Str. 6 + Ingolstadt Bavaria 85053 + DE + +70-B3-D5 (hex) Rosslare Enterprises Limited +682000-682FFF (base 16) Rosslare Enterprises Limited + Flat 912 Wing Fat Industrial Building + Kowloon Bay Kowloon + HK + +70-B3-D5 (hex) Datum Electronics Limited +250000-250FFF (base 16) Datum Electronics Limited + Needles Building + East Cowes Isle of Wight PO32 6RF + GB + +70-B3-D5 (hex) PAVO TASARIM ÜRETİM TİC A.Ş. +34A000-34AFFF (base 16) PAVO TASARIM ÜRETİM TİC A.Ş. + Teknopark İstanbul Ar-Ge Binaları. 1.Blok + İSTANBUL PENDİK 34349 + TR + +70-B3-D5 (hex) Sigmann Elektronik GmbH +95A000-95AFFF (base 16) Sigmann Elektronik GmbH + Hauptstrasse 53 + Hueffenhardt 74928 + DE + +70-B3-D5 (hex) Shooter Detection Systems +EB2000-EB2FFF (base 16) Shooter Detection Systems + 300 Newburyport Turnpike + Rowley MA 01969 + US + +70-B3-D5 (hex) SPC Bioclinicum +DF3000-DF3FFF (base 16) SPC Bioclinicum + Ugreshskaya 2 b.83 + Moscow Moscow 115088 + RU + +70-B3-D5 (hex) SIGLEAD INC +AB7000-AB7FFF (base 16) SIGLEAD INC + NAKAGAWACHUO1-38-10 + YOKOHAMA KANAGAWA 224-0003 + JP + +70-B3-D5 (hex) ARP Corporation +B88000-B88FFF (base 16) ARP Corporation + 166-1 Horikawa + Hadano Kanagawa 259-1305 + JP + +70-B3-D5 (hex) ACD Elektronik GmbH +FDA000-FDAFFF (base 16) ACD Elektronik GmbH + Engelberg 2 + Achstetten 88480 + DE + +70-B3-D5 (hex) ELAMAKATO GmbH +57B000-57BFFF (base 16) ELAMAKATO GmbH + Ottostrasse 5 + Eggenstein-Leopoldshafen Baden-Württemberg 76344 + DE + +70-B3-D5 (hex) Eagle Mountain Technology +559000-559FFF (base 16) Eagle Mountain Technology + 1811 MacCullen Drive + Erie CO 80516 + US + +70-B3-D5 (hex) Condev-Automation GmbH +DEC000-DECFFF (base 16) Condev-Automation GmbH + Obere Erlentiefenstr. 27 + Bergkamen NRW 59192 + DE + +70-B3-D5 (hex) CAITRON Industrial Solutions GmbH +305000-305FFF (base 16) CAITRON Industrial Solutions GmbH + Eich 8 + Ramerberg Bavaria 83561 + DE + +70-B3-D5 (hex) Telefonix Incorporated +83B000-83BFFF (base 16) Telefonix Incorporated + 2340 Ernie Krueger Circle + Waukegan Illinois 60087 + US + +70-B3-D5 (hex) Special Projects Group, Inc +2FD000-2FDFFF (base 16) Special Projects Group, Inc + 45 Wingate St + Haverhill MA 0832 + US + +70-B3-D5 (hex) Hanwa Electronic Ind.Co.,Ltd. +010000-010FFF (base 16) Hanwa Electronic Ind.Co.,Ltd. + 689-3,Ogaito + Wakayama 649-6272 + JP + +70-B3-D5 (hex) NextEra Energy Resources, LLC +EFA000-EFAFFF (base 16) NextEra Energy Resources, LLC + 700 Universe Blvd + Juno Beach Florida 33408 + US + +70-B3-D5 (hex) Taitotekniikka +2A5000-2A5FFF (base 16) Taitotekniikka + Elielinaukio aukio 3 + Helsinki 00100 + FI + +70-B3-D5 (hex) Human Oriented Technology, Inc. +507000-507FFF (base 16) Human Oriented Technology, Inc. + Rm 1021, 10/F SOLO Bldg + Tsimshatsui Kowloon + TW + +70-B3-D5 (hex) 4CAM GmbH +96F000-96FFFF (base 16) 4CAM GmbH + Hauptstrasse 18 + Reimlingen Bayern 86756 + DE + +70-B3-D5 (hex) CORES Corporation +8CE000-8CEFFF (base 16) CORES Corporation + 338-3 Furukawado + Tsuru-shi Yamanashi 402-0004 + JP + +70-B3-D5 (hex) Ultamation Limited +346000-346FFF (base 16) Ultamation Limited + Liverpool Science Park, ic2 + Liverpool Merseyside L3 5RF + GB + +70-B3-D5 (hex) Innerspec Technologies Inc. +79A000-79AFFF (base 16) Innerspec Technologies Inc. + 4004 Murray Place + Lynchburg Virgnia 24501 + US + +70-B3-D5 (hex) Fundación Cardiovascular de Colombia +51E000-51EFFF (base 16) Fundación Cardiovascular de Colombia + Cra 5 No 6 - 33. Floridablanca + Bucaramanga Floridablanca 681003 + CO + +70-B3-D5 (hex) VX Instruments GmbH +625000-625FFF (base 16) VX Instruments GmbH + Bernsteinstraße 41 A + Altdorf-Landshut Bavaria 84032 + DE + +70-B3-D5 (hex) SVP Broadcast Microwave S.L. +1AC000-1ACFFF (base 16) SVP Broadcast Microwave S.L. + Zubiaurre, 7 bajo + Iurreta Vizcaya 48215 + ES + +70-B3-D5 (hex) FARO TECHNOLOGIES, INC. +936000-936FFF (base 16) FARO TECHNOLOGIES, INC. + 125 Technology Park + Lake Mary FL 32746 + US + +70-B3-D5 (hex) Clock-O-Matic +2F0000-2F0FFF (base 16) Clock-O-Matic + De Vunt 14 + Holsbeek VBR 3220 + BE + +70-B3-D5 (hex) RMI Laser LLC +C58000-C58FFF (base 16) RMI Laser LLC + 106 Laser Drive + Lafayette Colorado 80026 + US + +70-B3-D5 (hex) HKC Limited +CB7000-CB7FFF (base 16) HKC Limited + Parkway Business Centre + Ballymount Dublin Dublin 24 + IE + +70-B3-D5 (hex) Molu Technology Inc., LTD. +D8F000-D8FFFF (base 16) Molu Technology Inc., LTD. + NO. 25, Ln., 230, Zhonghe Rd., + Zhonghe Dist. New Taipei City 235 + TW + +70-B3-D5 (hex) Quickware Eng & Des LLC +80F000-80FFFF (base 16) Quickware Eng & Des LLC + 32 Pleasant St + Waltham MA 02452 + US + +70-B3-D5 (hex) Avionica +0F0000-0F0FFF (base 16) Avionica + 9941 West Jessamine St + Miami Florida 33157 + US + +70-B3-D5 (hex) KeFF Networks +994000-994FFF (base 16) KeFF Networks + Sorogatan 1 + Kista Stockholm 16441 + SE + +70-B3-D5 (hex) Ars Products +F63000-F63FFF (base 16) Ars Products + 30 Crabtree Lane + Woodstock CT 06281 + US + +70-B3-D5 (hex) FRS GmbH & Co. KG +F62000-F62FFF (base 16) FRS GmbH & Co. KG + Weingartenstr. 1-3 + Dortmund NW 44263 + DE + +70-B3-D5 (hex) KINEMETRICS +CE9000-CE9FFF (base 16) KINEMETRICS + 222 VISTA AVENUE + PASADENA CA 91107 + US + +70-B3-D5 (hex) POWERCRAFT ELECTRONICS PVT. LTD. +090000-090FFF (base 16) POWERCRAFT ELECTRONICS PVT. LTD. + 305, 3rd FLOOR, BLUE ROSE INDUSTRIAL ESTATE, + MUMBAI MAHARASHTRA 400066 + IN + +70-B3-D5 (hex) DSD MICROTECHNOLOGY,INC. +308000-308FFF (base 16) DSD MICROTECHNOLOGY,INC. + 4700 WEST PROSPECT ROAD + FORT LAUDERDALE FLORIDA 33309 + US + +70-B3-D5 (hex) Accusonic +908000-908FFF (base 16) Accusonic + 28 Patterson Brook Road + West Wareham MA 02576 + US + +70-B3-D5 (hex) Overline Systems +28F000-28FFFF (base 16) Overline Systems + 21 av. Sophie Wallerstein + Andernos Aquitaine 33510 + FR + +70-B3-D5 (hex) Hosokawa Micron Powder Systems +4C8000-4C8FFF (base 16) Hosokawa Micron Powder Systems + 10 Chatham Road + Summit New Jersey 07901 + US + +70-B3-D5 (hex) RedRat Ltd +FD1000-FD1FFF (base 16) RedRat Ltd + The Business & Technology Centre + Saffron Walden Essex CB11 3AQ + + +00-1B-C5 (hex) EREE Electronique +0C1000-0C1FFF (base 16) EREE Electronique + 6 avenue Dr Schweitzer + MEYZIEU 69882 + FR + +00-1B-C5 (hex) kuwatec, Inc. +0BC000-0BCFFF (base 16) kuwatec, Inc. + 2-39-5 Umesato + Suginami-ku Tokyo 166-0011 + JP + +00-1B-C5 (hex) COBAN SRL +0B4000-0B4FFF (base 16) COBAN SRL + VIA BERGAMO,1910 + CARONNO PERTUSELLA VA 21042 + IT + +00-1B-C5 (hex) J-D.COM +0B0000-0B0FFF (base 16) J-D.COM + 6 rue Blaise pascal + Elancourt 78990 + FR + +00-1B-C5 (hex) Senceive Ltd +0AA000-0AAFFF (base 16) Senceive Ltd + Hurlingham Studios + London SW6 3PA + GB + +00-1B-C5 (hex) Balter Security GmbH +0A6000-0A6FFF (base 16) Balter Security GmbH + In den Diken 33 + Duesseldorf NRW 40472 + DE + +00-1B-C5 (hex) reelyActive +094000-094FFF (base 16) reelyActive + 501-1015 rue William + Montreal Quebec H3C 1P4 + CA + +00-1B-C5 (hex) UAB Kitron +099000-099FFF (base 16) UAB Kitron + Taikos 151 + Kaunas Lithuania LT-52119 + US + +00-1B-C5 (hex) TrendPoint Systems +08E000-08EFFF (base 16) TrendPoint Systems + 1595 E. 6th Street + Corona CA 92879 + US + +00-1B-C5 (hex) Bio Molecular System Pty Ltd +07E000-07EFFF (base 16) Bio Molecular System Pty Ltd + 5/3 Northward St + Upper Coomera Queensland 4209 + AU + +00-1B-C5 (hex) Hitechlab Inc +07F000-07FFFF (base 16) Hitechlab Inc + Hotarugaike-Nishimachi 2-14-14 + Toyonaka Osaka 560-0036 + JP + +00-1B-C5 (hex) tado GmbH +073000-073FFF (base 16) tado GmbH + Kochelseestraße 8-10 + München Deutschland 81371 + DE + +00-1B-C5 (hex) Center for E-Commerce Infrastructure Development, The University of Hong Kong +071000-071FFF (base 16) Center for E-Commerce Infrastructure Development, The University of Hong Kong + Room 301, Chow Yei Ching Building, + + HK + +00-1B-C5 (hex) TES Electronic Solutions (I) Pvt. Ltd. +06D000-06DFFF (base 16) TES Electronic Solutions (I) Pvt. Ltd. + #65, 35th Main, 100 feet Ring Road, + Bangalore Karnataka 560068 + IN + +00-1B-C5 (hex) Check-It Solutions Inc +063000-063FFF (base 16) Check-It Solutions Inc + 1601A - 4th Ave + Regina Saskatchewan S4R 8P9 + CA + +00-1B-C5 (hex) Klingenthaler Musikelektronik GmbH +05F000-05FFFF (base 16) Klingenthaler Musikelektronik GmbH + Auerbacher Str. 268 + Klingenthal Saxony 08248 + DE + +00-1B-C5 (hex) Ecomed-Complex +05E000-05EFFF (base 16) Ecomed-Complex + Petrogradskaya nab. 34 + Saint-Petersburg 197101 + RU + +00-1B-C5 (hex) konzeptpark GmbH +05B000-05BFFF (base 16) konzeptpark GmbH + Georg-Ohm-Straße 2 + Lahnau Hesse 35633 + DE + +00-1B-C5 (hex) POSTEC DATA SYSTEMS +05A000-05AFFF (base 16) POSTEC DATA SYSTEMS + 45-47 Paul Matthews Road + Auckland 0632 + NZ + +00-1B-C5 (hex) QQ Navigation AB +051000-051FFF (base 16) QQ Navigation AB + Gryt 44 + Ösmo 14892 + SE + +00-1B-C5 (hex) PT. Amanindo Nusapadu +047000-047FFF (base 16) PT. Amanindo Nusapadu + Jalan Pangeran Jayakarta 101 Blok D No. 4~5 + Jakarta Jawa Barat 10730 + ID + +00-1B-C5 (hex) Rhino Controls Ltd. +04C000-04CFFF (base 16) Rhino Controls Ltd. + 13545 113 Ave + Surrey British Columbia V3R 6S9 + CA + +00-1B-C5 (hex) DesignA Electronics Limited +041000-041FFF (base 16) DesignA Electronics Limited + Unit 6 + Christchurch New Zealand 8011 + NZ + +00-1B-C5 (hex) Daylight Solutions, Inc +03E000-03EFFF (base 16) Daylight Solutions, Inc + 15378 Avenue of Science + San Diego CA 92128 + US + +00-1B-C5 (hex) ELTRADE Ltd +03F000-03FFFF (base 16) ELTRADE Ltd + blvd. G.Delchev blok 102 + Sofia 1404 + BG + +00-1B-C5 (hex) SEED International Ltd. +038000-038FFF (base 16) SEED International Ltd. + Unit 1201, Pan-pacific Plaza, No.12A, South Street Zhongguancun, + Beijing 100081 + CN + +00-1B-C5 (hex) ITW Reyflex North America +037000-037FFF (base 16) ITW Reyflex North America + 195 E Algonquin Road + Des Plaines IL 60090 + US + +00-1B-C5 (hex) OctoGate it Security Systems GmbH +030000-030FFF (base 16) OctoGate it Security Systems GmbH + Klingender Strasse 5 + Paderborn NRW 33100 + DE + +00-1B-C5 (hex) andersen lighting GmbH +025000-025FFF (base 16) andersen lighting GmbH + Technologiezentrum + Hildesheim D-31137 + DE + +00-1B-C5 (hex) DIMEP Sistemas +026000-026FFF (base 16) DIMEP Sistemas + Av. Mofarrej, 840 + São Paulo 05311000 + BR + +00-1B-C5 (hex) Dunlop Systems & Components +019000-019FFF (base 16) Dunlop Systems & Components + Holbrook Lane + Coventry West Midlands CV6 4QX + GB + +00-1B-C5 (hex) Advanced Scientific Concepts, Inc. +00D000-00DFFF (base 16) Advanced Scientific Concepts, Inc. + 135 E. Ortega Street + Santa Barbara CA 93101 + US + +00-1B-C5 (hex) Private +014000-014FFF (base 16) Private + +00-1B-C5 (hex) Intellvisions Software Ltd +004000-004FFF (base 16) Intellvisions Software Ltd + 303, Steel House, 24 Mahal Indl Estate + Mumbai Maharashtra 400093 + IN + +00-1B-C5 (hex) OpenRB.com, Direct SIA +001000-001FFF (base 16) OpenRB.com, Direct SIA + E. Birznieka-Upisha + Riga LV-1050 + LV + +70-B3-D5 (hex) YAMAKATSU ELECTRONICS INDUSTRY CO., LTD. +053000-053FFF (base 16) YAMAKATSU ELECTRONICS INDUSTRY CO., LTD. + 1-37-23, Suenaga, Takatsu + Kawasaki-City Kanagawa 213-0013 + JP + +70-B3-D5 (hex) ard sa +206000-206FFF (base 16) ard sa + Micropolis Bat Clematis + Gap France 05000 + FR + +70-B3-D5 (hex) Guangzhou Haoxiang Computer Technology Co.,Ltd. +42B000-42BFFF (base 16) Guangzhou Haoxiang Computer Technology Co.,Ltd. + Room 502, 4th Floor, No. 6 Building, Hongtai Wisdom Valley, No. 21 Sicheng Road, Tianhe District + Guangzhou Guangdong 510665 + CN + +70-B3-D5 (hex) Hunan Shengyun Photoelectric Technology Co., Ltd. +7CA000-7CAFFF (base 16) Hunan Shengyun Photoelectric Technology Co., Ltd. + Unit 2, Building E8, Lugu Enterprise Plaza, Yuelu District + Changsha Hunan 410205 + CN + +70-B3-D5 (hex) Nordson Corporation +830000-830FFF (base 16) Nordson Corporation + 11475 Lakefield Dr + Duluth GA 30097 + US + +70-B3-D5 (hex) Medicomp, Inc +279000-279FFF (base 16) Medicomp, Inc + 600 Atlantis Rd + Melbourne FL 32904 + US + +70-B3-D5 (hex) CYNIX Systems Inc +320000-320FFF (base 16) CYNIX Systems Inc + Dunchon-daero + Seongnam-si Gyeonggi-do 13215 + KR + +70-B3-D5 (hex) OOO Research and Production Center Computer Technologies +B84000-B84FFF (base 16) OOO Research and Production Center Computer Technologies + Komsomolsky avenue, 90-17 + Perm Perm Region 614010 + RU + +70-B3-D5 (hex) Magneti Marelli S.p.A. Electronics +F44000-F44FFF (base 16) Magneti Marelli S.p.A. Electronics + Viale Aldo Borletti 61/63 + Corbetta MI 20011 + IT + +70-B3-D5 (hex) Bolide Technology Group, Inc. +9E1000-9E1FFF (base 16) Bolide Technology Group, Inc. + 468 S. San Dimas Ave., + San Dimas CA 91773 + US + +70-B3-D5 (hex) RCH ITALIA SPA +BF8000-BF8FFF (base 16) RCH ITALIA SPA + VIA CENDON 39 + SILEA TREVISO 31057 + IT + +70-B3-D5 (hex) Orion S.r.l. +41F000-41FFFF (base 16) Orion S.r.l. + Via Alessandro Volta 25/B + Veggiano Padova 35030 + IT + +70-B3-D5 (hex) Digifocus Technology Inc. +ECC000-ECCFFF (base 16) Digifocus Technology Inc. + 6F, No.89, Xinhu 1st Rd., Neihu Dist. + Taipei City 11494 + TW + +70-B3-D5 (hex) Foxtel srl +4F7000-4F7FFF (base 16) Foxtel srl + via della chimica 25 + viterbo 01100 + IT + +70-B3-D5 (hex) Palarum LLC +45A000-45AFFF (base 16) Palarum LLC + 986 BELVEDERE DRIVE, Suite B + LEBANON OH 45036 + US + +70-B3-D5 (hex) Cubitech +AED000-AEDFFF (base 16) Cubitech + 4-6 Kiprou str + Tavros Athens 17778 + GR + +70-B3-D5 (hex) DynaMount LLC +B5B000-B5BFFF (base 16) DynaMount LLC + 16357 Whispering Oaks Dr + Ramona CA 92065 + US + +70-B3-D5 (hex) Zerospace ICT Services B.V. +9E8000-9E8FFF (base 16) Zerospace ICT Services B.V. + Johan Huizingalaan 400 + Amsterdam Noord-Holland 1066 JS + NL + +70-B3-D5 (hex) Kahler Automation +0D5000-0D5FFF (base 16) Kahler Automation + 808 Timberlake Rd + Fairmont MN 56031 + US + +70-B3-D5 (hex) GLOBAL-KING INTERNATIONAL CO., LTD. +06E000-06EFFF (base 16) GLOBAL-KING INTERNATIONAL CO., LTD. + 5F., No. 19, Qingxiang St., Tucheng Dist., + New Taipei City Taiwan 236 + TW + +70-B3-D5 (hex) Abbott Diagnostics Technologies AS +6DD000-6DDFFF (base 16) Abbott Diagnostics Technologies AS + P. O. Box 6863 Rodeløkka + Oslo Oslo 0504 + NO + +70-B3-D5 (hex) Systems Technologies +5B4000-5B4FFF (base 16) Systems Technologies + 11310 N Government Way + Hayden ID 83835 + US + +70-B3-D5 (hex) Monixo +47B000-47BFFF (base 16) Monixo + 16 rue alexandre + Creteil 94000 + FR + +70-B3-D5 (hex) Benchmark Electronics BV +CC4000-CC4FFF (base 16) Benchmark Electronics BV + Lelyweg 10 + Almelo Overijssel 7602 EA + NL + +70-B3-D5 (hex) Xacti Corporation +1D2000-1D2FFF (base 16) Xacti Corporation + Tower East 28F,Umeda Sky Building,1-1-88,Oyodonaka,Kita-ku + Osaka Osaka 531-6048 + JP + +70-B3-D5 (hex) Cambridge Technology, Inc. +EFD000-EFDFFF (base 16) Cambridge Technology, Inc. + 125 middlesex turnpike + bedford MA 01730 + US + +70-B3-D5 (hex) AXING AG +00B000-00BFFF (base 16) AXING AG + Gewerbehaus Moskau + Ramsen 8262 + CH + +70-B3-D5 (hex) NIRECO CORPORATION +0CB000-0CBFFF (base 16) NIRECO CORPORATION + 2951-4, Ishikawa-machi + Hachioji-shi Tokyo 192-8522 + JP + +70-B3-D5 (hex) Hifocus Electronics India Private Limited +B25000-B25FFF (base 16) Hifocus Electronics India Private Limited + No. 3 Sunguvar Street, Chintadripet + Chennai Tamil Nadu 600002 + IN + +70-B3-D5 (hex) Wartsila Voyage Limited +304000-304FFF (base 16) Wartsila Voyage Limited + 13-18 City Quay + Dublin 2 D02 ED70 + IE + +70-B3-D5 (hex) CAITRON GmbH +B87000-B87FFF (base 16) CAITRON GmbH + Eich 8 + Ramerberg 83561 + DE + +70-B3-D5 (hex) WideNorth AS +2B8000-2B8FFF (base 16) WideNorth AS + Vollsveien 13C + Lysaker 1366 + NO + +70-B3-D5 (hex) TRANSLITE GLOBAL LLC +DBD000-DBDFFF (base 16) TRANSLITE GLOBAL LLC + 6644 ANTOINE DRIVE + HOUSTON TX 77091 + US + +70-B3-D5 (hex) Ellego Powertec Oy +CEF000-CEFFFF (base 16) Ellego Powertec Oy + Linnapellontie 18 + Halikko 24910 + FI + +70-B3-D5 (hex) SmartD Technologies Inc +AB6000-AB6FFF (base 16) SmartD Technologies Inc + 400 Montfort + Montreal Qc H3C4J9 + CA + +70-B3-D5 (hex) Elvys s.r.o +12A000-12AFFF (base 16) Elvys s.r.o + Polska 9 + Kosice 04011 + SK + +70-B3-D5 (hex) Active Brains +2BA000-2BAFFF (base 16) Active Brains + Yokohama Dia BLDG 8F 1-7 Kinkocho Kanagawa-ku + Yokohama Kanagawa 221-0056 + JP + +70-B3-D5 (hex) GDI Technology Inc +8B8000-8B8FFF (base 16) GDI Technology Inc + 12400 SW 134 Ct #14 + Miami FL 33186 + US + +70-B3-D5 (hex) MONTRADE SPA +EE2000-EE2FFF (base 16) MONTRADE SPA + Via Armando Sarti 6 + Bologna 40132 + IT + +70-B3-D5 (hex) Mettler Toledo +D64000-D64FFF (base 16) Mettler Toledo + 1571 Northpointe Parkway + Lutz FL 33558 + US + +70-B3-D5 (hex) Mettler Toledo +74A000-74AFFF (base 16) Mettler Toledo + 1571 Northpointe Parkway + Lutz FL 33558 + US + +70-B3-D5 (hex) W.A. Benjamin Electric Co. +4E4000-4E4FFF (base 16) W.A. Benjamin Electric Co. + 1615 Staunton Ave. + Los Angeles CA 60021 + US + +70-B3-D5 (hex) Mettler Toledo +84F000-84FFFF (base 16) Mettler Toledo + 1571 Northpointe Parkway + Lutz FL 33558 + US + +70-B3-D5 (hex) THELIGHT Luminary for Cine and TV S.L. +A41000-A41FFF (base 16) THELIGHT Luminary for Cine and TV S.L. + C/ Cerdanya, 11-A + Sant Quirze del Valles Barcelona 08192 + ES + +70-B3-D5 (hex) TATTILE SRL +48B000-48BFFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Elsist Srl +4C9000-4C9FFF (base 16) Elsist Srl + Via G. Brodolini, 15 + Casale Monf.to Alessandria 15033 + IT + +70-B3-D5 (hex) HANKOOK CTEC CO,. LTD. +6EE000-6EEFFF (base 16) HANKOOK CTEC CO,. LTD. + 404 Hallasigmavalley, 53, Gasandigital 2-ro Geumcheongu + Seoul 08588 + KR + +70-B3-D5 (hex) Olympus NDT Canada +3F1000-3F1FFF (base 16) Olympus NDT Canada + 3415 rue Pierre Ardouin + Québec Québec G1P 0B3 + CA + +70-B3-D5 (hex) Cominfo, Inc. +617000-617FFF (base 16) Cominfo, Inc. + Nabrezi 695 + Zlin 760 01 + CZ + +70-B3-D5 (hex) HAN CHANG +C3A000-C3AFFF (base 16) HAN CHANG + 171, Gasan digital 1-ro, Geumcheon-gu, Seoul, Republic of Korea + Seoul Geumcheon-gu, Seoul 08503 + KR + +70-B3-D5 (hex) SinterCast +425000-425FFF (base 16) SinterCast + Kungsgatan 2 + Katrineholm Please Select..sodermanland. 64130 + SE + +70-B3-D5 (hex) ECS s.r.l. +487000-487FFF (base 16) ECS s.r.l. + Via dell'Artigianato n. 24 + Belluno BL 32100 + IT + +70-B3-D5 (hex) Konrad GmbH +575000-575FFF (base 16) Konrad GmbH + Fritz-Reichle-Ring.12 + Radolfzell 78315 + DE + +70-B3-D5 (hex) Dalian Laike Technology Development Co., Ltd +DAC000-DACFFF (base 16) Dalian Laike Technology Development Co., Ltd + Room 406, 4th Floor, Block A, 29 Xixian Street, Dalian High-tech Industrial Park + Dalian Liaoning 116085 + CN + +70-B3-D5 (hex) Conclusive Engineering +B9D000-B9DFFF (base 16) Conclusive Engineering + Ligocka 103/3 + Katowice Silesia 40-568 + PL + +70-B3-D5 (hex) Sevensense Robotics AG +9C3000-9C3FFF (base 16) Sevensense Robotics AG + Weinbergstrasse 35 + Zurich 8092 + CH + +70-B3-D5 (hex) Hodwa Co., Ltd +2C4000-2C4FFF (base 16) Hodwa Co., Ltd + 3F., No. 216, Xinhu 1st Rd., Neihu Dist. + Taipei 11494 + TW + +70-B3-D5 (hex) RCH Vietnam Limited Liability Company +159000-159FFF (base 16) RCH Vietnam Limited Liability Company + Workshop F.01B-2, Lot No. F.01B Long Hau + Ho Chi Minh City Ho Chi Minh 70000 + VN + +70-B3-D5 (hex) Visility +964000-964FFF (base 16) Visility + Universitetsparken 7 + Roskilde 4000 + DK + +70-B3-D5 (hex) Public Joint Stock Company Morion +97E000-97EFFF (base 16) Public Joint Stock Company Morion + Kosmonavtov Avn, 111, bld 1 + Perm Perm 614066 + RU + +70-B3-D5 (hex) Screen Innovations +CFB000-CFBFFF (base 16) Screen Innovations + 9715 Burnet Rd B-400 + Austin TX 78758 + US + +70-B3-D5 (hex) Insitu, Inc. +865000-865FFF (base 16) Insitu, Inc. + 118 E Columbia River Way + Bingen WA 98605 + US + +70-B3-D5 (hex) German Power GmbH +C31000-C31FFF (base 16) German Power GmbH + Freiburger Strasse 7 + Pforzheim 75179 + DE + +70-B3-D5 (hex) Lyse AS +F23000-F23FFF (base 16) Lyse AS + Breiflåtveien 18 + Stavanger 4017 + NO + +70-B3-D5 (hex) Outsight SA +3EC000-3ECFFF (base 16) Outsight SA + 2 rue de Berite + Paris 75006 + FR + +70-B3-D5 (hex) Hefei STAROT Technology Co.,Ltd +4D3000-4D3FFF (base 16) Hefei STAROT Technology Co.,Ltd + 406, 4th Floor, Quality Control Building, Saipu Science Park, No. 6 Yunfei Road, High-tech Zone + hefei anhui 230000 + CN + +70-B3-D5 (hex) SysCom Automationstechnik GmbH +117000-117FFF (base 16) SysCom Automationstechnik GmbH + An der Lehmkaute 13 + Bad Marienberg Rheinland-Pfalz 56470 + DE + +70-B3-D5 (hex) Walton Hi-Tech Industries Ltd. +E5C000-E5CFFF (base 16) Walton Hi-Tech Industries Ltd. + HOLDING NO. I-65/2, WARD NO-07 + CHANDRA, KALIAKOIR, GAZIPUR. 1750 + BD + +70-B3-D5 (hex) Flextronics International Kft +699000-699FFF (base 16) Flextronics International Kft + 38. Zrinyi Str. + Zalaegerszeg Zala 8900 + HU + +70-B3-D5 (hex) JFA Electronics Industry and Commerce EIRELI +5F7000-5F7FFF (base 16) JFA Electronics Industry and Commerce EIRELI + Rua Flor das Pedras, 175 + Belo Horizonte Minas Gerais 30810-000 + BR + +70-B3-D5 (hex) Hubbell Power Systems +858000-858FFF (base 16) Hubbell Power Systems + 353 Powerville Road + Boonton Township NJ 07005 + US + +70-B3-D5 (hex) aquila biolabs GmbH +7DB000-7DBFFF (base 16) aquila biolabs GmbH + Arnold-Sommerfeld-Ring 2 + Baesweiler NRW 52499 + DE + +70-B3-D5 (hex) Sicon srl +C82000-C82FFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) LGE +DAE000-DAEFFF (base 16) LGE + 10, Magokjungang 10-ro, Gangseo-gu + Seoul 07796 + KR + +70-B3-D5 (hex) Jonsa Australia Pty Ltd +335000-335FFF (base 16) Jonsa Australia Pty Ltd + Unit D2 3-29 Birnie Ave + Lidcombe NSW 2141 + AU + +70-B3-D5 (hex) GreenWake Technologies +467000-467FFF (base 16) GreenWake Technologies + 56 boulevard Niels Bohr, CEI2 + Villeurbanne 69100 + FR + +70-B3-D5 (hex) shenzhen suofeixiang technology Co.,Ltd +EEB000-EEBFFF (base 16) shenzhen suofeixiang technology Co.,Ltd + sales09@sfxhd.com + shenzhen 518000 + CN + +70-B3-D5 (hex) RCH Vietnam Limited Liability Company +97D000-97DFFF (base 16) RCH Vietnam Limited Liability Company + Workshop F.01B-2, Lot No. F.01B Long Hau + Ho Chi Minh City Ho Chi Minh 70000 + VN + +70-B3-D5 (hex) SNK, Inc. +E12000-E12FFF (base 16) SNK, Inc. + Rm 302 Inobiz park, 1646, Yuseong-daero, Yuseong-gu + Daejeon 34054 + KR + +70-B3-D5 (hex) SYLink Technologie +466000-466FFF (base 16) SYLink Technologie + 18 rue de la conche + Mirefleurs Auvergne 63730 + FR + +70-B3-D5 (hex) silicom +F64000-F64FFF (base 16) silicom + 14 Atir-Yeda St/ + Kfar-Sava Israel 44000 + IL + +70-B3-D5 (hex) NSP Europe Ltd +18A000-18AFFF (base 16) NSP Europe Ltd + Unit 5, Devonshire Business Park + Borehamwood Hert WD6 1NA + GB + +70-B3-D5 (hex) Kospel S.A. +249000-249FFF (base 16) Kospel S.A. + Olchowa 1 + Koszalin 75-136 + PL + +70-B3-D5 (hex) Microchip Technology Germany II GmbH&Co.KG +77F000-77FFFF (base 16) Microchip Technology Germany II GmbH&Co.KG + Emmy-Noether-Straße 14 + Karlsruhe 76131 + DE + +70-B3-D5 (hex) Trust Automation +C98000-C98FFF (base 16) Trust Automation + 125 Venture Dr + San Luis Obispo CA 93401 + US + +70-B3-D5 (hex) ARCLAN'SYSTEM +25C000-25CFFF (base 16) ARCLAN'SYSTEM + 1140 rue Ampère - Actimart II - Lot 9 + AIX EN PROVENCE 13290 + FR + +70-B3-D5 (hex) Taejin InfoTech +A75000-A75FFF (base 16) Taejin InfoTech + 40, Imi-ro, A-411 + Uiwang-si Gyeonggi-do 16006 + KR + +70-B3-D5 (hex) Coheros Oy +D2E000-D2EFFF (base 16) Coheros Oy + Tammukkakatu 6 + Nokia 37130 + FI + +70-B3-D5 (hex) Gogo Business Aviation +E24000-E24FFF (base 16) Gogo Business Aviation + 105 Edgeview Dr., Suite 300 + Broomfield CO 80021 + US + +70-B3-D5 (hex) Smart Embedded Systems +A09000-A09FFF (base 16) Smart Embedded Systems + 6701 Koll Center Parkway #250 + Pleasonton CA 94566 + US + +70-B3-D5 (hex) Guan Show Technologe Co., Ltd. +F6A000-F6AFFF (base 16) Guan Show Technologe Co., Ltd. + No.127, Jianguo 1st Rd., Lingya Dist. + Kaohsiung City 802 + TW + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +BBB000-BBBFFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) D-E-K GmbH & Co.KG +219000-219FFF (base 16) D-E-K GmbH & Co.KG + Südfeld 9 + Ascheberg / Herbern 58387 + DE + +70-B3-D5 (hex) AvMap srlu +B4F000-B4FFFF (base 16) AvMap srlu + Viale Zaccagna 6 + Carrara 54033 + IT + +70-B3-D5 (hex) Theatrixx Technologies, Inc. +5DD000-5DDFFF (base 16) Theatrixx Technologies, Inc. + 1655 Richardson + Montreal QC H3K3J7 + CA + +70-B3-D5 (hex) EA Elektroautomatik GmbH & Co. KG +6BC000-6BCFFF (base 16) EA Elektroautomatik GmbH & Co. KG + Helmholtzstraße 31-33 + Viersen NRW 41747 + DE + +70-B3-D5 (hex) Adolf Nissen Elektrobau GmbH + Co. KG +101000-101FFF (base 16) Adolf Nissen Elektrobau GmbH + Co. KG + Friedrichstädter Chaussee 4 + Tönning 25832 + DE + +70-B3-D5 (hex) TinTec Co., Ltd. +5AE000-5AEFFF (base 16) TinTec Co., Ltd. + #825 101, Magokseo-ro, Gangseo-gu + Seoul 07798 + KR + +70-B3-D5 (hex) Blue Storm Associates, Inc. +9EA000-9EAFFF (base 16) Blue Storm Associates, Inc. + 8605 Cross View + Fairfax Station 22039 + US + +70-B3-D5 (hex) Neuronal Innovation Control S.L. +F0A000-F0AFFF (base 16) Neuronal Innovation Control S.L. + Anade Real 11 + Oleiros A Coruna 15179 + ES + +70-B3-D5 (hex) LECO Corporation +684000-684FFF (base 16) LECO Corporation + 3000 Lakeview Ave. + St. Joseph null 49085 + US + +70-B3-D5 (hex) SPETSSTROY-SVYAZ Ltd +A39000-A39FFF (base 16) SPETSSTROY-SVYAZ Ltd + 13-26 B. Bulvarnaya St. + Taganrog Rostov 347913 + RU + +70-B3-D5 (hex) AirBie AG +0B1000-0B1FFF (base 16) AirBie AG + Kinkelstrasse 36 + Zurich Zurich 8006 + CH + +70-B3-D5 (hex) 3DGence sp. z o.o. +D15000-D15FFF (base 16) 3DGence sp. z o.o. + Mickiewicza 29 + Katowice Slaskie 40-085 + PL + +70-B3-D5 (hex) ASHIDA Electronics Pvt. Ltd +D39000-D39FFF (base 16) ASHIDA Electronics Pvt. Ltd + ASHIDA House Plot No A308 Road No. 21 Wagle Ind. Estate + Thane Maharashtra 400604 + IN + +70-B3-D5 (hex) COMPAL ELECTRONICS, INC. +26F000-26FFFF (base 16) COMPAL ELECTRONICS, INC. + No.500, Ruiguang Rd., Neihu District, + Taipei 11492 + TW + +70-B3-D5 (hex) ARKRAY, Inc. Kyoto Laboratory +C4E000-C4EFFF (base 16) ARKRAY, Inc. Kyoto Laboratory + Yousuien-nai + Kyoto Kamigyo-ku 602-0008 + JP + +70-B3-D5 (hex) EM Clarity Pty Ltd +C7B000-C7BFFF (base 16) EM Clarity Pty Ltd + 55 Curzon St + Tennyson QLD 4105 + AU + +70-B3-D5 (hex) Smith Meter, Inc. +414000-414FFF (base 16) Smith Meter, Inc. + 1602 Wagner Ave. + Erie PA 16514 + US + +70-B3-D5 (hex) Echo Ridge, LLC +1AA000-1AAFFF (base 16) Echo Ridge, LLC + 100 Carpenter Drive + Sterling VA 20164 + US + +70-B3-D5 (hex) SURUGA SEIKI CO., LTD. +9FE000-9FEFFF (base 16) SURUGA SEIKI CO., LTD. + 505, Nanatsushinya, Shimizu-ku + Shizuoka-shi Shizuoka 424-8566 + JP + +70-B3-D5 (hex) HIPODROMO DE AGUA CALIENTE, S.A. DE C.V. +E56000-E56FFF (base 16) HIPODROMO DE AGUA CALIENTE, S.A. DE C.V. + BLVD. AGUA CALIENTE 12027 + TIJUANA BAJA CALIFORNIA 22420 + MX + +70-B3-D5 (hex) CHIeru., CO., Ltd. +783000-783FFF (base 16) CHIeru., CO., Ltd. + Tennozu Central Tower 3F, 2-2-24, Higashi-shinagawa, Shinagawa-ku + tokyo 140-0002 + JP + +70-B3-D5 (hex) VITEC +22B000-22BFFF (base 16) VITEC + 99 rue pierre sémard + Chatillon France 92320 + FR + +70-B3-D5 (hex) SLAT +E81000-E81FFF (base 16) SLAT + 11 Rue Jean-Elysée DUPUY + Champagne au Mont d'Or Rhône 69543 + FR + +70-B3-D5 (hex) CertusNet Inc. +C83000-C83FFF (base 16) CertusNet Inc. + No.699-22 Xuanwu Avenue, Xuanwu District + Nanjing Jiangsu 210042 + CN + +70-B3-D5 (hex) eumig industrie-TV GmbH. +7FF000-7FFFFF (base 16) eumig industrie-TV GmbH. + Gewerbeparkstrasse 9 + Anif Salzburg 5081 + AT + +70-B3-D5 (hex) NORTHBOUND NETWORKS PTY. LTD. +874000-874FFF (base 16) NORTHBOUND NETWORKS PTY. LTD. + 14 Sommersby Road + Point Cook Victoria 3030 + AU + +70-B3-D5 (hex) EAX Labs s.r.o. +158000-158FFF (base 16) EAX Labs s.r.o. + Krizovnicka 86/6 + Praha 1 11000 + CZ + +70-B3-D5 (hex) Liberty Reach +3FB000-3FBFFF (base 16) Liberty Reach + 3550 W Liberty Rd Suite 5 + Ann Arbor MI 48103 + US + +70-B3-D5 (hex) Ongisul Co.,Ltd. +458000-458FFF (base 16) Ongisul Co.,Ltd. + Yangji Building 6F, 85, Seonghwang-ro + Dongnam-gu, Cheonan-si, Chungcheongnam-do 31125 + KR + +70-B3-D5 (hex) VisioGreen +F6C000-F6CFFF (base 16) VisioGreen + 26, Avenue Winston Churchill + Louviers 27 Eure 27400 + FR + +70-B3-D5 (hex) LINEAGE POWER PVT LTD., +6CA000-6CAFFF (base 16) LINEAGE POWER PVT LTD., + 30-A1, KIADB, 1ST PHASE INDUSTRIAL ESTATE,KUMBALGODU, BANGALORE-MYSORE ROAD + BANGALORE KARNATAKA 560074 + IN + +70-B3-D5 (hex) Private +FFE000-FFEFFF (base 16) Private + +70-B3-D5 (hex) Alere Technologies AS +70B000-70BFFF (base 16) Alere Technologies AS + Kjelsaasveien 161 + Oslo Oslo 0382 + NO + +70-B3-D5 (hex) Cursor Systems NV +E38000-E38FFF (base 16) Cursor Systems NV + Drevendaal 14 + Sint-Katelijne-Waver Antwerpen 2860 + BE + +70-B3-D5 (hex) Innotas Elektronik GmbH +C51000-C51FFF (base 16) Innotas Elektronik GmbH + Rathenaustr. 18a + Zittau D-02763 + DE + +70-B3-D5 (hex) DEUTA-WERKE GmbH +6E5000-6E5FFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + , Bergisch Gladbach 51465 + DE + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +CC6000-CC6FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Yamamoto Works Ltd. +DFB000-DFBFFF (base 16) Yamamoto Works Ltd. + 3-1-3 Kashiwaza + Ageo Saitama 3620075 + JP + +70-B3-D5 (hex) Prolan Zrt. +C04000-C04FFF (base 16) Prolan Zrt. + Szentendrei út 1-3. + Budakalasz 2011 + HU + +70-B3-D5 (hex) Umano Medical Inc. +E1E000-E1EFFF (base 16) Umano Medical Inc. + 230, Boul. Nilus-Leclerc + L'Islet Québec G0R 2C0 + CA + +70-B3-D5 (hex) AEye, Inc. +B52000-B52FFF (base 16) AEye, Inc. + 5700 Stoneridge Drive, Suite 102 + Pleasanton CA 94588 + US + +70-B3-D5 (hex) EMDEP CENTRO TECNOLOGICO MEXICO +83A000-83AFFF (base 16) EMDEP CENTRO TECNOLOGICO MEXICO + Circuito Corral de Piedras #36, Polígono Empresarial San Miguel + San Miguel de Allende Guanajuato 37880 + MX + +70-B3-D5 (hex) RCH ITALIA SPA +42D000-42DFFF (base 16) RCH ITALIA SPA + Via Cendon 39 + SILEA Treviso 31057 + IT + +70-B3-D5 (hex) Cetto Industries +B73000-B73FFF (base 16) Cetto Industries + Dechenstr. 9-15 + Ratingen 40878 + DE + +70-B3-D5 (hex) APE GmbH +8C4000-8C4FFF (base 16) APE GmbH + Plauener Str. 163-165, Haus N + Berlin 13053 + DE + +70-B3-D5 (hex) Melecs EWS GmbH +E8A000-E8AFFF (base 16) Melecs EWS GmbH + GZO-Technologiestrasse 1 + Siegendorf 7011 + AT + +70-B3-D5 (hex) Grossenbacher Systeme AG +BB5000-BB5FFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) iMAR Navigation GmbH +A42000-A42FFF (base 16) iMAR Navigation GmbH + Im Reihersbruch 3 + St. Ingbert Saarland 66386 + DE + +70-B3-D5 (hex) Viper Innovations Ltd +A45000-A45FFF (base 16) Viper Innovations Ltd + 45 Martingale Way + Bristol BS20 7AW + GB + +70-B3-D5 (hex) SamabaNova Systems +F29000-F29FFF (base 16) SamabaNova Systems + 2100 Geng Rd #103 + Palo Alto CA 94303 + US + +70-B3-D5 (hex) LANSITEC TECHNOLOGY CO., LTD +A4D000-A4DFFF (base 16) LANSITEC TECHNOLOGY CO., LTD + No. 8 Huashen Avenue + Nanjing Jiangsu 210012 + CN + +70-B3-D5 (hex) ELINKGATE JSC +37E000-37EFFF (base 16) ELINKGATE JSC + J4A Buu Long Dist 10 + Ho Chi Minh Vietnam 70350 + VN + +70-B3-D5 (hex) ICT BUSINESS GROUP of Humanrights Center for disabled people +B20000-B20FFF (base 16) ICT BUSINESS GROUP of Humanrights Center for disabled people + #A1101-6,70 Gyeongin-ro 71-gil, + Seoul Yeongdeungpo-gu 07286 + KR + +70-B3-D5 (hex) TIECHE Engineered Systems +795000-795FFF (base 16) TIECHE Engineered Systems + 940 Enchanted Way,Suite 104 + Simi Valley CA 93065 + US + +70-B3-D5 (hex) Multiple Access Communications Ltd +558000-558FFF (base 16) Multiple Access Communications Ltd + Delta House, Southampton Science Park + Southampton Hampshire SO16 7NS + GB + +70-B3-D5 (hex) FIRST RF Corporation +7BC000-7BCFFF (base 16) FIRST RF Corporation + 6150 Lookout Rd + Boulder CO 80301 + US + +70-B3-D5 (hex) PROMOMED RUS LLC +D3A000-D3AFFF (base 16) PROMOMED RUS LLC + UL. POCHTOVAYA M., D. 2/2,C.1,P.iK2 I, K.2 + Moscow 129090 + RU + +70-B3-D5 (hex) Vega-Absolute +0AD000-0ADFFF (base 16) Vega-Absolute + Kirova 113/1 + Novosibirsk 630008 + RU + +70-B3-D5 (hex) Acrodea, Inc. +4A8000-4A8FFF (base 16) Acrodea, Inc. + 3F, Daisan Yamada Bldg., 22 Aizumi-cho + Shinjuku-ku Tokyo 1600005 + JP + +70-B3-D5 (hex) MaNima Technologies BV +DD9000-DD9FFF (base 16) MaNima Technologies BV + Hastelweg 260B + Eindhoven Noord-Brabant 5652CN + NL + +70-B3-D5 (hex) Integrotech sp. z o.o. +6BA000-6BAFFF (base 16) Integrotech sp. z o.o. + plac Zwyciestwa 2 bud. D + Lodz lodzkie 90-312 + PL + +70-B3-D5 (hex) Xitron +388000-388FFF (base 16) Xitron + 4750 Venture Drive + Ann Arbor MI 48108 + US + +70-B3-D5 (hex) Private +4F8000-4F8FFF (base 16) Private + +70-B3-D5 (hex) Becton Dickinson +808000-808FFF (base 16) Becton Dickinson + 7 Loveton Circle + Sparks MD 21152 + US + +70-B3-D5 (hex) INTERNET PROTOCOLO LOGICA SL +275000-275FFF (base 16) INTERNET PROTOCOLO LOGICA SL + Sector Foresta 43, local 26 + Tres Cantos Madrid 28760 + ES + +70-B3-D5 (hex) MECT SRL +628000-628FFF (base 16) MECT SRL + VIA E. FERMI 57/59 + ALPIGNANO TORINO 10093 + IT + +70-B3-D5 (hex) SITA Messtechnik GmbH +535000-535FFF (base 16) SITA Messtechnik GmbH + Gostritzer Str. 63 + Dresden 01217 + DE + +70-B3-D5 (hex) KBS Industrieelektronik GmbH +860000-860FFF (base 16) KBS Industrieelektronik GmbH + Burkheimer Str. 10 + Freiburg 79111 + DE + +70-B3-D5 (hex) Aaronia AG +B1A000-B1AFFF (base 16) Aaronia AG + Kauthenbergstr. 14 + Strickscheid 54597 + DE + +70-B3-D5 (hex) MBio Diagnostics, Inc. +57F000-57FFFF (base 16) MBio Diagnostics, Inc. + 5603 Arapahoe Avenue, Suite 1 + BOULDER CO 80303 + US + +70-B3-D5 (hex) Acrodea, Inc. +E79000-E79FFF (base 16) Acrodea, Inc. + 3F, Daisan Yamada Bldg., 22 Aizumi-cho + Shinjuku-ku Tokyo 1600005 + JP + +70-B3-D5 (hex) TEX COMPUTER SRL +1E1000-1E1FFF (base 16) TEX COMPUTER SRL + VIA MERCADANTE 35 + CATTOLICA RIMINI 47841 + IT + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +150000-150FFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) Magnamed Tecnologia Medica S/A +648000-648FFF (base 16) Magnamed Tecnologia Medica S/A + Rua Des. Eliseu Guilherme, 292 6 Andar + Sao Paulo SP 04004-030 + BR + +70-B3-D5 (hex) Traffic and Parking Control Co, Inc. +0A7000-0A7FFF (base 16) Traffic and Parking Control Co, Inc. + 5100 W. Brown Deer Rd. + Brown Deer WI 53223 + US + +70-B3-D5 (hex) Shenzhen Luxurite Smart Home Ltd +121000-121FFF (base 16) Shenzhen Luxurite Smart Home Ltd + 13th Floor, Kenuo Building, No. 7 road, TongGuan Street, GuangMing + Shenzhen GuangDong 518000 + CN + +70-B3-D5 (hex) Fiber Optika Technologies Pvt. Ltd. +47E000-47EFFF (base 16) Fiber Optika Technologies Pvt. Ltd. + #38, 22nd Main, 14th Cross, Padmanabhanagar + Bangalore Karnataka 560070 + IN + +70-B3-D5 (hex) AT-Automation Technology GmbH +345000-345FFF (base 16) AT-Automation Technology GmbH + Hermann-Boessow-Str. 6-8 + Bad Oldesloe D-23843 + DE + +70-B3-D5 (hex) C-COM Satellite Systems Inc. +D4F000-D4FFFF (base 16) C-COM Satellite Systems Inc. + 2574 Sheffield Road + Ottawa Ontario K1B3V7 + CA + +70-B3-D5 (hex) OutdoorLink +6A3000-6A3FFF (base 16) OutdoorLink + 3058 Leeman Ferry Rd + Huntsville AL 35801 + US + +70-B3-D5 (hex) Sasken Technologies Ltd +BCD000-BCDFFF (base 16) Sasken Technologies Ltd + 139/25, Amarjyothi Layout, Domlur + Bangalore 560071 + IN + +70-B3-D5 (hex) FAS Electronics (Fujian) Co.,LTD. +B46000-B46FFF (base 16) FAS Electronics (Fujian) Co.,LTD. + #1 Building,Weihuang Industrial Zone, Qingkou Invest District + Minhou city, Fuzhou Fujian 350119 + CN + +70-B3-D5 (hex) Algodue Elettronica Srl +89A000-89AFFF (base 16) Algodue Elettronica Srl + Via P. Gobetti, 16F + Maggiora NO 28014 + IT + +70-B3-D5 (hex) HongSeok Ltd. +C40000-C40FFF (base 16) HongSeok Ltd. + 166, Osan-ro, Osan-myeon + Iksan-si Jeollabuk-do 54670 + KR + +70-B3-D5 (hex) BP Lubricants USA, Inc. +94E000-94EFFF (base 16) BP Lubricants USA, Inc. + 201 North Webster + White Cloud MI 49349 + US + +70-B3-D5 (hex) Algodue Elettronica Srl +430000-430FFF (base 16) Algodue Elettronica Srl + Via Passerina 3/A + Fontaneto d'Agogna Novara 28010 + IT + +70-B3-D5 (hex) SmartSafe +A7B000-A7BFFF (base 16) SmartSafe + Avenida das Américas 3301 Bloco 01 Lojas 102/110 + Rio de Janeiro RJ 22631-003 + BR + +70-B3-D5 (hex) aelettronica group srl +9C4000-9C4FFF (base 16) aelettronica group srl + via matteotti,22 + gaggiano milano 20083 + IT + +70-B3-D5 (hex) Changshu Ruite Electric Co.,Ltd. +391000-391FFF (base 16) Changshu Ruite Electric Co.,Ltd. + No.2,Qingdao Road,Yushan High-tech Industrial Development Zone + Changshu Jiangshu 215500 + CN + +70-B3-D5 (hex) Zhiye Electronics Co., Ltd. +8E2000-8E2FFF (base 16) Zhiye Electronics Co., Ltd. + No. 1117, Pioneer Road, High-tech Zone + Jinan City Shandong Province 250101 + CN + +70-B3-D5 (hex) AVA Technologies Inc. +72F000-72FFFF (base 16) AVA Technologies Inc. + 45 East Cordova St, AVA Technologies Inc. + Vancouver BC V6A 1K3 + CA + +70-B3-D5 (hex) Position Imaging +A5D000-A5DFFF (base 16) Position Imaging + 22 marin way unit 1 + stratham NH 03885 + US + +70-B3-D5 (hex) AixControl GmbH +972000-972FFF (base 16) AixControl GmbH + Sonnenweg 15 + Aachen NRW 52070 + DE + +70-B3-D5 (hex) AVL DiTEST +86B000-86BFFF (base 16) AVL DiTEST + Fahrzeugdiagnose GmbH + Graz Steiermark 8020 + AT + +70-B3-D5 (hex) Graphcore Ltd +1B3000-1B3FFF (base 16) Graphcore Ltd + 11-19 Wine Street + Bristol BS1 2PH + GB + +70-B3-D5 (hex) GRIDSMART Technologies +D50000-D50FFF (base 16) GRIDSMART Technologies + 10545 Hardin Valley Rd + Knoxville TN 37932 + US + +70-B3-D5 (hex) Shenzhen Siera Technology Ltd +1BD000-1BDFFF (base 16) Shenzhen Siera Technology Ltd + Room 2039, Shenhai Building, Wanzhong Village, Bulong Road, Minzhi, Longhua district, City: Shenzhen + Shenzhen Guangdong 518131 + CN + +70-B3-D5 (hex) SYS TEC electronic GmbH +41B000-41BFFF (base 16) SYS TEC electronic GmbH + Am Windrad 2 + Heinsdorfergrund D-08468 + DE + +70-B3-D5 (hex) Sportsbeams Lighting, Inc. +013000-013FFF (base 16) Sportsbeams Lighting, Inc. + 1260 Pine Forest Cir + Round Rock TX 78665 + US + +70-B3-D5 (hex) ANYROAM +003000-003FFF (base 16) ANYROAM + 2450 E.J. Chapman DR + Knoxville TN 37996 + US + +70-B3-D5 (hex) Telensa Ltd +56C000-56CFFF (base 16) Telensa Ltd + Iconix 3, London Road + Pampisford Cambridgeshire CB22 3EG + GB + +70-B3-D5 (hex) Techno Broad,Inc +512000-512FFF (base 16) Techno Broad,Inc + 2-12-12, shin-chiba,chuo-ku, + chiba chiba 2600031 + JP + +70-B3-D5 (hex) Open System Solutions Limited +44B000-44BFFF (base 16) Open System Solutions Limited + Saltmakers House + Southampton Hampshire SO31 4NB + GB + +70-B3-D5 (hex) NOA Co., Ltd. +4EE000-4EEFFF (base 16) NOA Co., Ltd. + #201, 96, Seokho-ro, Sangrok-gu + Ansan-si Gyeonggi-do 15579 + KR + +70-B3-D5 (hex) Secturion Systems +CFE000-CFEFFF (base 16) Secturion Systems + 520 N Marketplace Dr, + Centerville UT 84014 + US + +70-B3-D5 (hex) SOFTLAND INDIA LTD +C29000-C29FFF (base 16) SOFTLAND INDIA LTD + #14A, KINFRA SMALL INDUSTRIES PARK, MENAMKULAM, KAZHAKOOTTAM + TRIVANDRUM KERALA 695586 + IN + +70-B3-D5 (hex) Sunstone Engineering +2FF000-2FFFFF (base 16) Sunstone Engineering + 1693 American Way Suite 5 + Payson UT 84651 + US + +70-B3-D5 (hex) FSR, INC. +071000-071FFF (base 16) FSR, INC. + 244 BERGEN BLVD + WOODLAND PARK NJ 07424 + US + +70-B3-D5 (hex) eSys Solutions Sweden AB +A22000-A22FFF (base 16) eSys Solutions Sweden AB + Sandsborgsvagen 50 + Enskede 12233 + SE + +70-B3-D5 (hex) EvoLogics GmbH +F9B000-F9BFFF (base 16) EvoLogics GmbH + Ackerstr. 76 + Berlin 13355 + DE + +70-B3-D5 (hex) Franke Aquarotter GmbH +BB6000-BB6FFF (base 16) Franke Aquarotter GmbH + Parkstraße 1-5 + Ludwigsfelde 14974 + DE + +70-B3-D5 (hex) Bacsoft +4B3000-4B3FFF (base 16) Bacsoft + Hazarhan 13 + Kiryat Gat 8258112 + IL + +70-B3-D5 (hex) C21 Systems Ltd +14B000-14BFFF (base 16) C21 Systems Ltd + Dunston Innovation Centre + Chesterfield Derbyshire S41 8NG + GB + +70-B3-D5 (hex) Zaklad Energoelektroniki Twerd +3FA000-3FAFFF (base 16) Zaklad Energoelektroniki Twerd + Aleksandrowska 28/30 + Torun 87100 + PL + +70-B3-D5 (hex) CODESYSTEM Co.,Ltd +FC0000-FC0FFF (base 16) CODESYSTEM Co.,Ltd + #705, Namsung Plaza(Ace9), 130 Digitalro, Keumchon-Gu + Seoul 08589 + KR + +70-B3-D5 (hex) Telefire +2E8000-2E8FFF (base 16) Telefire + 43 hasivim + Petah Tikva Israel 49000 + IL + +70-B3-D5 (hex) Private +F7C000-F7CFFF (base 16) Private + +70-B3-D5 (hex) boekel +AF8000-AF8FFF (base 16) boekel + 855 pennsylvania blvd + feasterville PA 19053 + US + +70-B3-D5 (hex) BlueBox Video Limited +4C6000-4C6FFF (base 16) BlueBox Video Limited + Drysdale View, Fenny Bentley + Ashbourne DE6 1LA + GB + +70-B3-D5 (hex) DAVE SRL +189000-189FFF (base 16) DAVE SRL + VIA TALPONEDO 29/A + PORCIA PORDENONE 330850 + IT + +70-B3-D5 (hex) Solar RIg Technologies +293000-293FFF (base 16) Solar RIg Technologies + 651 Garden Street + Carlstadt NJ 07072 + US + +70-B3-D5 (hex) merkur Funksysteme AG +B0F000-B0FFFF (base 16) merkur Funksysteme AG + Wassergrabe 14 + Sursee 6210 + CH + +70-B3-D5 (hex) HERUTU ELECTRONICS CORPORATION +E32000-E32FFF (base 16) HERUTU ELECTRONICS CORPORATION + 62-1 Toyooka-cho, Kita-ku + Hamamatsu Shizuoka 433-8103 + JP + +70-B3-D5 (hex) MG s.r.l. +688000-688FFF (base 16) MG s.r.l. + via Monte Bianco, 1 + Solbiate Olona VA 21058 + IT + +70-B3-D5 (hex) DOLBY LABORATORIES, INC. +3F5000-3F5FFF (base 16) DOLBY LABORATORIES, INC. + 100 Potrero Avenue + San Francisco CA 94103-4938 + US + +70-B3-D5 (hex) Koco Motion US LLC +707000-707FFF (base 16) Koco Motion US LLC + 335 Cochrane Circle + Morgan Hill CA 95037 + US + +70-B3-D5 (hex) NAC Planning Co., Ltd. +87F000-87FFFF (base 16) NAC Planning Co., Ltd. + NREG Akihabara Bldg 2F, 1-8-13, Sotokanda + Chiyoda-ku Tokyo 101-0021 + JP + +70-B3-D5 (hex) Elektronik Art S.C. +82D000-82DFFF (base 16) Elektronik Art S.C. + Mełgiewska 80 + Lublin 20-234 + PL + +70-B3-D5 (hex) TEKVEL Ltd. +1DC000-1DCFFF (base 16) TEKVEL Ltd. + Federativny prospekt, 5-1-5 + Moscow Moscow 111399 + RU + +70-B3-D5 (hex) TIAMA +C4A000-C4AFFF (base 16) TIAMA + ZA des Plattes - 1 Chemin des Plattes + VOURLES 69390 + FR + +70-B3-D5 (hex) Adeli +E61000-E61FFF (base 16) Adeli + Route de Sandrans + Saint Trivier sur Moignans Ain 01990 + FR + +70-B3-D5 (hex) Code Blue Corporation +A8D000-A8DFFF (base 16) Code Blue Corporation + 259 Hedcor Street + Holland MI 49423 + US + +70-B3-D5 (hex) Smart Vision Lights +BCB000-BCBFFF (base 16) Smart Vision Lights + 2359 Holton Rd + Muskegon MI 49445 + US + +70-B3-D5 (hex) SYS TEC electronic GmbH +C64000-C64FFF (base 16) SYS TEC electronic GmbH + Am Windrad 2 + Heinsdorfergrund D-08468 + DE + +70-B3-D5 (hex) ATT Nussbaum Prüftechnik GmbH +2A3000-2A3FFF (base 16) ATT Nussbaum Prüftechnik GmbH + Robert-Koch-Str. 35 + Kehl-Auenheim 77694 + DE + +70-B3-D5 (hex) WINNERS DIGITAL CORPORATION +8A2000-8A2FFF (base 16) WINNERS DIGITAL CORPORATION + 3F, No. 4, Ln. 263, Chongyang Rd., Nangang Dist., + Taipei City Taiwan 115-73 + TW + +70-B3-D5 (hex) Private +E22000-E22FFF (base 16) Private + +70-B3-D5 (hex) H3D, Inc. +3F2000-3F2FFF (base 16) H3D, Inc. + 812 Avis Drive + Ann Arbor MI 48108 + US + +70-B3-D5 (hex) PT. Emsonic Indonesia +360000-360FFF (base 16) PT. Emsonic Indonesia + Jl.Timor Blok E5, MM2100 Industrial Town Jatiwangi Cikarang Barat + Bekasi Jawa Barat 17530 + ID + +70-B3-D5 (hex) IDEA SPA +415000-415FFF (base 16) IDEA SPA + VIA PARALLELA 2/4 + VILLA BARTOLOMEA VERONA 37049 + IT + +70-B3-D5 (hex) RCD Radiokomunikace +225000-225FFF (base 16) RCD Radiokomunikace + U Posty 26 + Stare Hradiste 53352 + CZ + +70-B3-D5 (hex) Millennial Net, Inc. +3B0000-3B0FFF (base 16) Millennial Net, Inc. + 24 Hartwell Avenue + Lexington MA 02421 + US + +70-B3-D5 (hex) Grossenbacher Systeme AG +758000-758FFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) FSTUDIO CO LTD +C0B000-C0BFFF (base 16) FSTUDIO CO LTD + Yanagawa Bldg. 2F 5-16-13 + Watanabe-Dori Chuo-ku Fukuoka Fukuoka 810-0004 + JP + +70-B3-D5 (hex) Den Automation +0BF000-0BFFFF (base 16) Den Automation + Unit 6.05, Metropolitan Wharf + London E1W 3SS + GB + +70-B3-D5 (hex) EDCO Technology 1993 ltd +B9C000-B9CFFF (base 16) EDCO Technology 1993 ltd + 10 hamelacha street + Rosh haayin 4809118 + IL + +70-B3-D5 (hex) 3D Printing Specialists +CDF000-CDFFFF (base 16) 3D Printing Specialists + 7916 Grow Ln + Houston TX 77040 + US + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +17F000-17FFFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbühl Bavaria 91550 + DE + +70-B3-D5 (hex) eumig industrie-TV GmbH. +AA2000-AA2FFF (base 16) eumig industrie-TV GmbH. + Gewerbeparkstrasse 9 + Anif Salzburg 5081 + AT + +70-B3-D5 (hex) Xylon +C1A000-C1AFFF (base 16) Xylon + Fallerovo setaliste 22 + Zagreb 10000 + HR + +70-B3-D5 (hex) FUKUDA SANGYO CO., LTD. +C9E000-C9EFFF (base 16) FUKUDA SANGYO CO., LTD. + Nazukari 996 + Nagareyama Chiba 2700145 + JP + +70-B3-D5 (hex) Private +73A000-73AFFF (base 16) Private + +70-B3-D5 (hex) Rako Controls Ltd +084000-084FFF (base 16) Rako Controls Ltd + Knight Road + Rochester Kent ME2 2AH + GB + +70-B3-D5 (hex) Airthings +53C000-53CFFF (base 16) Airthings + Wergelandsveien 7 + Oslo 0167 + NO + +70-B3-D5 (hex) Sankyo Intec co.,ltd +664000-664FFF (base 16) Sankyo Intec co.,ltd + Tokimata127 + Iida Nagano 3992563 + JP + +70-B3-D5 (hex) SOFTCREATE CORP. +3C7000-3C7FFF (base 16) SOFTCREATE CORP. + 2-15-1 Shibuya + Shibuya-ku Tokyo 150-0002 + JP + +70-B3-D5 (hex) Tecsys do Brasil Industrial Ltda +9AA000-9AAFFF (base 16) Tecsys do Brasil Industrial Ltda + Rua Oros, 146 + Sao Jose dos Campos SP 12237150 + BR + +70-B3-D5 (hex) PCSC +515000-515FFF (base 16) PCSC + 3541 Challenger St. + Torrance CA 90503 + US + +70-B3-D5 (hex) CAPSYS +A0A000-A0AFFF (base 16) CAPSYS + ZI Parc technologique des Fontaines + BERNIN 38190 + FR + +70-B3-D5 (hex) Akse srl +5CC000-5CCFFF (base 16) Akse srl + Via Aldo Moro, 39 + Reggio Emilia Italy 42124 + IT + +70-B3-D5 (hex) INSEVIS GmbH +508000-508FFF (base 16) INSEVIS GmbH + Am Weichselgarten 7 + Erlangen D-91058 + DE + +70-B3-D5 (hex) SoFiHa +78F000-78FFFF (base 16) SoFiHa + Hagenower Strasee 73 + Schwerin 19061 + DE + +70-B3-D5 (hex) Guangzhou Moblin Technology Co., Ltd. +E52000-E52FFF (base 16) Guangzhou Moblin Technology Co., Ltd. + 35 Tianshou Rd, Tianhe District + Guangzhou Guangdong 510000 + CN + +70-B3-D5 (hex) Fink Telecom Services +23B000-23BFFF (base 16) Fink Telecom Services + Paradieshofstrasse 101 + Basel 4054 + CH + +70-B3-D5 (hex) Koizumi Lighting Technology Corp. +19F000-19FFFF (base 16) Koizumi Lighting Technology Corp. + 3-5-2-Chome + Higashinakamoto,Higashinari-ku,Osaka 537-0021 + JP + +70-B3-D5 (hex) Private +389000-389FFF (base 16) Private + +70-B3-D5 (hex) Touchnet/OneCard +478000-478FFF (base 16) Touchnet/OneCard + 2115 Chapman Rd. Suite 159 + Chattanooga TN 37421 + US + +70-B3-D5 (hex) Power Electronics Espana, S.L. +2A9000-2A9FFF (base 16) Power Electronics Espana, S.L. + C/ Leonardo Da Vinci, 24-26 + Paterna Valencia 46980 + ES + +70-B3-D5 (hex) Hangzhou Youshi Industry Co., Ltd. +4EC000-4ECFFF (base 16) Hangzhou Youshi Industry Co., Ltd. + Unit 501-38, Blue Sky Business Centre,GongShu District, + Hangzhou Zhejiang 310000 + CN + +70-B3-D5 (hex) YAWATA ELECTRIC INDUSTRIAL CO.,LTD. +BCE000-BCEFFF (base 16) YAWATA ELECTRIC INDUSTRIAL CO.,LTD. + 1-17-1 Ohmorihigashi + Ohta-ku Tokyo 143-0012 + JP + +70-B3-D5 (hex) MITSUBISHI HEAVY INDUSTRIES THERMAL SYSTEMS, LTD. +A37000-A37FFF (base 16) MITSUBISHI HEAVY INDUSTRIES THERMAL SYSTEMS, LTD. + 3-1, Asahi, Nishibiwajima-Cho + Kiyosu Aichi 452-8561 + JP + +70-B3-D5 (hex) samwooeleco +676000-676FFF (base 16) samwooeleco + A-1001,#119,GASAN-DIGITAL 1RO, GEUMCHEON-GU + SEOUL 153-773 + KR + +70-B3-D5 (hex) Suprock Technologies +613000-613FFF (base 16) Suprock Technologies + 45 Scott Hill Rd + Warren NH 03279 + US + +70-B3-D5 (hex) GSP Sprachtechnologie GmbH +2A4000-2A4FFF (base 16) GSP Sprachtechnologie GmbH + Teltowkanalstraße 1 + Berlin 12247 + DE + +70-B3-D5 (hex) OnYield Inc Ltd +D72000-D72FFF (base 16) OnYield Inc Ltd + 814 Houston Centre, 63 Mody Road + Kowloon TST East + HK + +70-B3-D5 (hex) Eurotek Srl +1D1000-1D1FFF (base 16) Eurotek Srl + Strada Comunale Savonesa, 9 + Rivalta Scrivia AL 15050 + IT + +70-B3-D5 (hex) Redcap Solutions s.r.o. +027000-027FFF (base 16) Redcap Solutions s.r.o. + Na Viničních Horách 16 + Praha 6 16000 + CZ + +70-B3-D5 (hex) Colorimetry Research, Inc +10E000-10EFFF (base 16) Colorimetry Research, Inc + 26612 Heirloom Place + Santa Clarita CA 91350 + US + +70-B3-D5 (hex) LG Electronics +257000-257FFF (base 16) LG Electronics + 10, Magokjungang 10-ro, Gangseo-gu + Seoul 07796 + KR + +70-B3-D5 (hex) De Haardt bv +CA2000-CA2FFF (base 16) De Haardt bv + Marithaime 6 + Elst 6662 WD + NL + +70-B3-D5 (hex) Exi Flow Measurement Ltd +AAF000-AAFFFF (base 16) Exi Flow Measurement Ltd + Unit 22 Ford Lane business Park + Ford, ARUNDEL West Sussex BN164HP + GB + +70-B3-D5 (hex) Resolution Systems +D89000-D89FFF (base 16) Resolution Systems + 1/214 Greenhill Rd + Eastwood South Australia 6063 + AU + +70-B3-D5 (hex) Urbana Smart Solutions Pte Ltd +224000-224FFF (base 16) Urbana Smart Solutions Pte Ltd + 6 Eu Tong Sen Street #06-20 The Central + Singapore 059817 + SG + +70-B3-D5 (hex) Henrich Electronics Corporation +436000-436FFF (base 16) Henrich Electronics Corporation + 225 Deming Place + Westmont IL 60559 + US + +00-1B-C5 (hex) Triax A/S +08C000-08CFFF (base 16) Triax A/S + Bjornkaervej 3 + Hornsyld Denmark 8783 + DK + +70-B3-D5 (hex) Agramkow Fluid Systems A/S +4AF000-4AFFFF (base 16) Agramkow Fluid Systems A/S + Augustenborg Landevej 19 + Soenderborg DK 6400 + DK + +70-B3-D5 (hex) Advice +810000-810FFF (base 16) Advice + 16 Atir Yeda St + Kfar Saba Not applicable 4464321 + IL + +70-B3-D5 (hex) Uplevel Systems Inc +A13000-A13FFF (base 16) Uplevel Systems Inc + 6950 SW Hampton Street, Suite 308 + Tigard OR 97223 + US + +70-B3-D5 (hex) Cambridge Pixel +023000-023FFF (base 16) Cambridge Pixel + New Cambridge House, Litlington + Royston Herts SG8 0SS + GB + +70-B3-D5 (hex) SAICE +FB7000-FB7FFF (base 16) SAICE + 5-23-1 + Shinagawa Higashi-Gotanda Tokyo 141-0022 + JP + +70-B3-D5 (hex) Hermann Lümmen GmbH +D4B000-D4BFFF (base 16) Hermann Lümmen GmbH + Biberweg 32 + Troisdorf 53842 + DE + +70-B3-D5 (hex) Hi Tech Systems Ltd +4B4000-4B4FFF (base 16) Hi Tech Systems Ltd + Holbrook House, Oakley Lane + Basingstoke Hampshire RG23 7JY + GB + +70-B3-D5 (hex) PULLNET TECHNOLOGY, SA DE CV SSC1012302S73 +70A000-70AFFF (base 16) PULLNET TECHNOLOGY, SA DE CV SSC1012302S73 + LUZ SAVIÑON 2007 + BENITO JUAREZ CIUDAD DE MEXICO 03020 + MX + +70-B3-D5 (hex) KOSMEK.Ltd +BB9000-BB9FFF (base 16) KOSMEK.Ltd + Murodani 2-1-5, Nishi-ku + Kobe-City Hyogo Pref. 6512241 + JP + +70-B3-D5 (hex) Jacarta Ltd +09B000-09BFFF (base 16) Jacarta Ltd + Wagon Yard, London Road + Marlborough SN8 1LH + GB + +70-B3-D5 (hex) Private +DE9000-DE9FFF (base 16) Private + +70-B3-D5 (hex) ST Aerospace Systems +27F000-27FFFF (base 16) ST Aerospace Systems + 505A Airport Road Paya Lebar + Singapore Singapore 539934 + SG + +70-B3-D5 (hex) SoftLab-NSK +555000-555FFF (base 16) SoftLab-NSK + Pr.Koptjuga 1 + Novosibirsk 630090 + RU + +70-B3-D5 (hex) Nortek Global HVAC +4D4000-4D4FFF (base 16) Nortek Global HVAC + Fens Pool Ave + Brierley Hill West Midlands DY5 1QA + GB + +70-B3-D5 (hex) Tunstall A/S +A17000-A17FFF (base 16) Tunstall A/S + Niels Bohrs vej 42 + Stilling Skanderborg 8660 + DK + +00-1B-C5 (hex) Vigor Electric Corp +00E000-00EFFF (base 16) Vigor Electric Corp + No. 42-12. Pidao Village + New Taipei 251 + TW + +70-B3-D5 (hex) RealD +CCB000-CCBFFF (base 16) RealD + 5700 Flatiron Parkway + Boulder CO 80301 + US + +70-B3-D5 (hex) OptoPrecision GmbH +4F9000-4F9FFF (base 16) OptoPrecision GmbH + Auf der Höhe 15 + Bremen Bremen 28357 + DE + +70-B3-D5 (hex) Richard Paul Russell Ltd +98B000-98BFFF (base 16) Richard Paul Russell Ltd + The Lodge, Unit 1 Barnes Farm Business Park + Milford on Sea Hampshire SO41 0AP + GB + +70-B3-D5 (hex) Avionica +611000-611FFF (base 16) Avionica + 9941 West Jessamine St + Miami FL 33157 + US + +70-B3-D5 (hex) Collini Dienstleistungs GmbH +C67000-C67FFF (base 16) Collini Dienstleistungs GmbH + Schweizerstr. 59 + Hohenems A 6845 + AT + +70-B3-D5 (hex) Imecon Engineering SrL +5E3000-5E3FFF (base 16) Imecon Engineering SrL + via Gerola 13/15 + Fiesco CR 26010 + IT + +70-B3-D5 (hex) ATBiS Co.,Ltd +C2F000-C2FFFF (base 16) ATBiS Co.,Ltd + #1603 5th. Ace High-end Tower, 226 Gasan Digital 1-ro, Geumcheon-gu + Seoul 08502 + KR + +70-B3-D5 (hex) Shenzhen bayue software co. LTD +784000-784FFF (base 16) Shenzhen bayue software co. LTD + B301, second phase of China merchants street technology building, nanshan district + ShenZhen 518000 + CN + +70-B3-D5 (hex) X-Laser LLC +711000-711FFF (base 16) X-Laser LLC + 9125 Whiskey Bottom Rd Ste A + Laurel MD 20723 + US + +70-B3-D5 (hex) QUERCUS TECHNOLOGIES, S.L. +777000-777FFF (base 16) QUERCUS TECHNOLOGIES, S.L. + Av. Onze de Setembre 19 + Reus Tarragona 43203 + ES + +70-B3-D5 (hex) Shenzhen INVT Electric Co.,Ltd +1D0000-1D0FFF (base 16) Shenzhen INVT Electric Co.,Ltd + INVT Bldg., GaoFa Scientific Park, Longjing, Nanshan, Shenzhen. + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) White Matter LLC +368000-368FFF (base 16) White Matter LLC + 999 3rd Ave 700 + Seattle 98104 + US + +70-B3-D5 (hex) Critical Link LLC +D5C000-D5CFFF (base 16) Critical Link LLC + 6712 Brooklawn Parkway + Syracuse null 13211 + US + +70-B3-D5 (hex) Secure Systems & Services +717000-717FFF (base 16) Secure Systems & Services + 24, Chemin de la Pouranque + F-13752 LES PENNES MIRABEAU CS30084 + FR + +70-B3-D5 (hex) YG COMPANY CO., LTD +63F000-63FFFF (base 16) YG COMPANY CO., LTD + 65, Techno 3-ro + Daejeon Yuseong-gu 34016 + KR + +70-B3-D5 (hex) SYS TEC electronic GmbH +7FD000-7FDFFF (base 16) SYS TEC electronic GmbH + Am Windrad 2 + Heinsdorfergrund D-08468 + DE + +70-B3-D5 (hex) JSC InformInvestGroup +91F000-91FFFF (base 16) JSC InformInvestGroup + Moscow, Prospekt Andropova street, 18 + Moscow Moscow State 115432 + RU + +70-B3-D5 (hex) Autocom Diagnostic Partner AB +98E000-98EFFF (base 16) Autocom Diagnostic Partner AB + Grafitvägen 23B + TROLLHÄTTAN 46138 + SE + +70-B3-D5 (hex) Ultimate Software +03C000-03CFFF (base 16) Ultimate Software + 2000 Ultimate Way + Weston FL 33326 + US + +70-B3-D5 (hex) Microgate Srl +7AB000-7ABFFF (base 16) Microgate Srl + Via Stradivari, 4 + BOLZANO BZ 39100 + IT + +70-B3-D5 (hex) Polynet Telecommunications Consulting and Contractor Ltd. +877000-877FFF (base 16) Polynet Telecommunications Consulting and Contractor Ltd. + Montevideo street 3/b + Budapest 1037 + HU + +70-B3-D5 (hex) LOGICUBE INC +999000-999FFF (base 16) LOGICUBE INC + 19755 Nordhoff Place + Chatsworth CA 91311 + US + +70-B3-D5 (hex) Schneider Electric Motion USA +153000-153FFF (base 16) Schneider Electric Motion USA + 370 N. Main St. + Marlborough CT 06447 + US + +70-B3-D5 (hex) TOSEI ENGINEERING CORP. +24B000-24BFFF (base 16) TOSEI ENGINEERING CORP. + 4-6, Higashi-Nakanuki-machi + Tsuchiura-city Ibaraki 300-0006 + JP + +70-B3-D5 (hex) Korea Airports Corporation +2CD000-2CDFFF (base 16) Korea Airports Corporation + 78 Haneul-gil Gangseo-gu + SEOUL 07505 + KR + +70-B3-D5 (hex) DEK Technologies +D22000-D22FFF (base 16) DEK Technologies + cnr Riggall Street and Maldon Street + Broadmeadows Victoria 3047 + AU + +70-B3-D5 (hex) PHPower Srl +A3F000-A3FFFF (base 16) PHPower Srl + Via Borgonuovo 27 + Milano MI 20121 + IT + +70-B3-D5 (hex) Saline Lectronics, Inc. +246000-246FFF (base 16) Saline Lectronics, Inc. + 710 N Maple Rd + Saline MI 48176 + US + +70-B3-D5 (hex) Global Technical Systems +19B000-19BFFF (base 16) Global Technical Systems + 784 Lynnhaven Parkway + Virginia Beach VA 23452 + US + +70-B3-D5 (hex) Cannex Technology Inc. +CD1000-CD1FFF (base 16) Cannex Technology Inc. + No.182, Sec.2, Yuanlu Rd. + Sihu Changhua 51449 + TW + +70-B3-D5 (hex) Intecom +CC5000-CC5FFF (base 16) Intecom + ul.Hrustalnaya d11.korp2 + Saint-Petersburg SPb 192019 + RU + +70-B3-D5 (hex) Certus Operations Ltd +4B2000-4B2FFF (base 16) Certus Operations Ltd + Dragonara Business Centre, 5th Floor, Dragonara Road c/w Ball Street + St Julians STJ 3141 + MT + +70-B3-D5 (hex) NETWAYS GmbH +73D000-73DFFF (base 16) NETWAYS GmbH + Deutschherrnstraße 15 + Nürnberg 90429 + DE + +70-B3-D5 (hex) Flirtey Inc +2AA000-2AAFFF (base 16) Flirtey Inc + P O BOX 7315 + Reno NV 89510 + US + +70-B3-D5 (hex) Spectrum Techniques, LLC +953000-953FFF (base 16) Spectrum Techniques, LLC + 106 Union Valley Rd + Oak Ridge TN 37930 + US + +70-B3-D5 (hex) Southern Tier Technologies +9D5000-9D5FFF (base 16) Southern Tier Technologies + 307 CHAUMONT DR + ENDWELL NY 13760-5831 + US + +70-B3-D5 (hex) The Dini Group, La Jolla inc. +678000-678FFF (base 16) The Dini Group, La Jolla inc. + 7469 Draper Ave. + La Jolla CA 92037 + US + +70-B3-D5 (hex) Grossenbacher Systeme AG +0DE000-0DEFFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) SureFlap Ltd +F9C000-F9CFFF (base 16) SureFlap Ltd + 7 The Irwin Centre, Scotland Road, Dry Drayton + Cambridge Cambridgeshire CB23 8AR + GB + +70-B3-D5 (hex) Enlaps +F75000-F75FFF (base 16) Enlaps + 29 chemin du vieux chene, Tarmac + MEYLAN 38240 + FR + +70-B3-D5 (hex) megatec electronic GmbH +8A8000-8A8FFF (base 16) megatec electronic GmbH + Lehenhammer 14 + Etzelwang Bayern 92268 + DE + +70-B3-D5 (hex) DEUTA-WERKE GmbH +432000-432FFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) Service Plus LLC +169000-169FFF (base 16) Service Plus LLC + Kotlyakovskaya str. 5 + Moscow 115201 + RU + +70-B3-D5 (hex) Omwave +B13000-B13FFF (base 16) Omwave + 34 bis rue d'Estienne d'Orves + Montrouge Ile de France 92120 + FR + +70-B3-D5 (hex) Radixon s.r.o. +2F4000-2F4FFF (base 16) Radixon s.r.o. + Opatska 19 + Kosice-Krasna 04018 + SK + +70-B3-D5 (hex) GSF Corporation Pte Ltd +B98000-B98FFF (base 16) GSF Corporation Pte Ltd + 60 Paya Lebar Road + # 12-05 Paya Lebar Square 409051 + SG + +70-B3-D5 (hex) Hella Gutmann Solutions GmbH +5B8000-5B8FFF (base 16) Hella Gutmann Solutions GmbH + Am Krebsbach 2 + Ihringen Baden Württemberg 79241 + DE + +70-B3-D5 (hex) HKW-Elektronik GmbH +035000-035FFF (base 16) HKW-Elektronik GmbH + Eisenacher Str. 42b + Wutha-Farnroda Thüringen 99848 + DE + +70-B3-D5 (hex) OOO NPP Mars-Energo +374000-374FFF (base 16) OOO NPP Mars-Energo + 199034 V.O. 13 liniya, 6-8, lit.A, office 40H, + Saint-Petersburg 199034 + RU + +70-B3-D5 (hex) CRDE +381000-381FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) RFL Electronics, Inc. +FA6000-FA6FFF (base 16) RFL Electronics, Inc. + 353 Powerville Road + Booton Twp. 07005 + US + +70-B3-D5 (hex) Fiberbase +30D000-30DFFF (base 16) Fiberbase + #516 Complex-dong Heongduk IT Valley, Heonduk 1ro 13, Giheong-gu + Young-in Gyeong-gi 16954 + KR + +70-B3-D5 (hex) Vensi, Inc. +379000-379FFF (base 16) Vensi, Inc. + 113 McHenry Rd #191 + Buffalo Grove IL 60089 + US + +70-B3-D5 (hex) AeroVision Avionics, Inc. +77B000-77BFFF (base 16) AeroVision Avionics, Inc. + 2F, No.30, R&D. II, Science Park, + Hsinchu City Taiwan 30076 + TW + +70-B3-D5 (hex) Grupo Epelsa S.L. +C14000-C14FFF (base 16) Grupo Epelsa S.L. + C/ Punto Net,3 + Alcala de Henares Madrid 28805 + ES + +70-B3-D5 (hex) Matsuhisa Corporation +F42000-F42FFF (base 16) Matsuhisa Corporation + 55-20 Katayama-cho + Fukui-shi 910-3611 + JP + +70-B3-D5 (hex) Daavlin +F24000-F24FFF (base 16) Daavlin + 205 W Bement St. + Bryan OH 43506 + US + +70-B3-D5 (hex) Twoway Communications, Inc. +FBC000-FBCFFF (base 16) Twoway Communications, Inc. + 41 Wu Kung 6 Rd., New Taipei Industrial Park, New Taipei City,24891,Taiwan,R.O.C. + New Taipei city Taipei 24891 + TW + +70-B3-D5 (hex) Axess AG +413000-413FFF (base 16) Axess AG + Sonystrasse 18 + Anif Salzburg 5081 + AT + +70-B3-D5 (hex) Green Access Ltd +B2E000-B2EFFF (base 16) Green Access Ltd + Hearle Way + Hatfield Hertfordshire AL10 9EW + GB + +70-B3-D5 (hex) Intra Corporation +DDB000-DDBFFF (base 16) Intra Corporation + 885 Manufacturers Dr. + Westland MI 48186 + US + +70-B3-D5 (hex) Network Additions +8EE000-8EEFFF (base 16) Network Additions + 2-14-10 Minamiyana + Hadano Kanagawa 2570003 + JP + +70-B3-D5 (hex) Newtec A/S +245000-245FFF (base 16) Newtec A/S + Stærmosegårdsvej 18 + Odense SV Region Syd 5230 + DK + +70-B3-D5 (hex) Orion Technologies, LLC +C6E000-C6EFFF (base 16) Orion Technologies, LLC + 12605 Challenger Pkwy, Ste 130 + ORLANDO FL 32826 + US + +70-B3-D5 (hex) GP Systems GmbH +D6C000-D6CFFF (base 16) GP Systems GmbH + Ochshäuser Str. 45 + Kassel 34123 + DE + +70-B3-D5 (hex) The Morey Corporation +D4D000-D4DFFF (base 16) The Morey Corporation + 100 Morey Drive + Woodridge IL 60517 + US + +70-B3-D5 (hex) Rollogo Limited +C8C000-C8CFFF (base 16) Rollogo Limited + 22/F., Far East Finance Centre, 16 Harcourt Road, Admiralty, + Hong Kong 000000 + HK + +70-B3-D5 (hex) DAVE SRL +59C000-59CFFF (base 16) DAVE SRL + VIA TALPONEDO 29/A + PORCIA PORDENONE 330850 + IT + +70-B3-D5 (hex) Quantum Design Inc. +84D000-84DFFF (base 16) Quantum Design Inc. + 10307 Pacific Center Court + San Diego CA 92121 + US + +70-B3-D5 (hex) DTRON Communications (Pty) Ltd +90F000-90FFFF (base 16) DTRON Communications (Pty) Ltd + A18 Bellville Business Park, cnr Mike Pienaar blvd & Voortrekker road + Bellville Western Cape 7530 + ZA + +70-B3-D5 (hex) Rapiscan Systems +CC9000-CC9FFF (base 16) Rapiscan Systems + 14000 Mead Street + Longmont CO 80504 + US + +70-B3-D5 (hex) TEX COMPUTER SRL +108000-108FFF (base 16) TEX COMPUTER SRL + VIA MERCADANTE 35 + CATTOLICA RIMINI 47841 + IT + +70-B3-D5 (hex) ASE GmbH +47F000-47FFFF (base 16) ASE GmbH + Lußhardtstraße 6 + Bruchsal 76646 + DE + +70-B3-D5 (hex) Fraunhofer-Institut IIS +677000-677FFF (base 16) Fraunhofer-Institut IIS + Am Wolfsmantel 33 + Erlangen Bayern 91058 + DE + +70-B3-D5 (hex) DACOM West GmbH +1B6000-1B6FFF (base 16) DACOM West GmbH + Schallbruch 19-21 + Haan 42781 + DE + +70-B3-D5 (hex) Zamir Recognition Systems Ltd. +D92000-D92FFF (base 16) Zamir Recognition Systems Ltd. + Manachat Tech Park 1/22 + Jerusalem 96951 + IL + +70-B3-D5 (hex) AVER +0B4000-0B4FFF (base 16) AVER + 13000 Danielson St Ste A + Poway CA 92064 + US + +70-B3-D5 (hex) ​ASUNG TECHNO CO.,Ltd +8AC000-8ACFFF (base 16) ​ASUNG TECHNO CO.,Ltd + 462, Dogok-ro, Songpa-gu, Seoul, Republic of Korea + SEOUL Repubilc of KOREA 05574 + KR + +70-B3-D5 (hex) Fracarro srl +211000-211FFF (base 16) Fracarro srl + via Cazzaro 3 + Castelfranco Veneto 31033 + IT + +70-B3-D5 (hex) MSB Elektronik und Gerätebau GmbH +96D000-96DFFF (base 16) MSB Elektronik und Gerätebau GmbH + Hofwiesenstr. 23 + Crailsheim 74564 + DE + +70-B3-D5 (hex) VITEC +127000-127FFF (base 16) VITEC + 99, rue Pierre Semard + CHATILLON 92320 + FR + +70-B3-D5 (hex) WOW System +6A6000-6A6FFF (base 16) WOW System + #411, MEGA Center, 124, Sagimakgol-ro, Jungwon-gu + Seongnam-si 13207 + KR + +70-B3-D5 (hex) Eurotronik Kranj d.o.o. +805000-805FFF (base 16) Eurotronik Kranj d.o.o. + Stirnova 8 + Kranj 4000 + SI + +70-B3-D5 (hex) Sanko-sha,inc. +7E0000-7E0FFF (base 16) Sanko-sha,inc. + 3-9-12 ChuorinkanNishi + Yamato-shi Kanagawa-Prefecture 242-0008 + JP + +70-B3-D5 (hex) Mannkind Corporation +7E8000-7E8FFF (base 16) Mannkind Corporation + 1 Casper Street + Danbury CT 06810 + US + +70-B3-D5 (hex) BTG Instruments AB +C49000-C49FFF (base 16) BTG Instruments AB + Industrigatan 1-3 + Saffle Varmland 66132 + SE + +70-B3-D5 (hex) Luxar Tech, Inc. +653000-653FFF (base 16) Luxar Tech, Inc. + 42840 Christy St, Suite 101 + Fremont CA 94538 + US + +70-B3-D5 (hex) WIXCON Co., Ltd +2B1000-2B1FFF (base 16) WIXCON Co., Ltd + Room 803, 77, Seongsuil-ro, Seongdong-gu + SEOUL 04790 + KR + +70-B3-D5 (hex) HKC Limited +F1F000-F1FFFF (base 16) HKC Limited + Parkway Business Centre + Ballymount Dublin Dublin 24 + IE + +70-B3-D5 (hex) Gogo BA +002000-002FFF (base 16) Gogo BA + 105 Edgeview Drive + Broomfield CO 80021 + US + +70-B3-D5 (hex) Dataspeed Inc +215000-215FFF (base 16) Dataspeed Inc + 1935 Enterprise Dr + Rochester Hills MI 48309 + US + +70-B3-D5 (hex) neQis +10F000-10FFFF (base 16) neQis + Star House, Star Hill + Rochester Kent ME11UX + GB + +70-B3-D5 (hex) U-Tech +06B000-06BFFF (base 16) U-Tech + #306 Building 25, Simin-daero 284 beon-gil, Dongan-gu + Anyang-si Gyeonggi-do 14067 + KR + +70-B3-D5 (hex) Ravelin Ltd +022000-022FFF (base 16) Ravelin Ltd + Prof. Popova str 4 + St Petersburg Russia 197022 + RU + +70-B3-D5 (hex) CRDE +14C000-14CFFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) Modtronix Engineering +90D000-90DFFF (base 16) Modtronix Engineering + Boden PL + Castle Hill NSW 2154 + AU + +70-B3-D5 (hex) Stahl GmbH +DCE000-DCEFFF (base 16) Stahl GmbH + Wilhelm-Maybach-Str. 3 + Crailsheim 74564 + DE + +70-B3-D5 (hex) Hiquel Elektronik- und Anlagenbau GmbH +22C000-22CFFF (base 16) Hiquel Elektronik- und Anlagenbau GmbH + Bairisch Koelldorf 266 + Bad Gleichenberg 8344 + AT + +70-B3-D5 (hex) Overspeed SARL +9C6000-9C6FFF (base 16) Overspeed SARL + 53 bis boulevard des Belges + Rouen 76000 + FR + +70-B3-D5 (hex) GY-FX SAS +4BE000-4BEFFF (base 16) GY-FX SAS + 38 rue du Botrel + 35690 Brittany Acigne + FR + +70-B3-D5 (hex) TMSI LLC +745000-745FFF (base 16) TMSI LLC + 9073 Pleasantwood Ave NW + North Canton OH 44720 + US + +70-B3-D5 (hex) SmartNodes +209000-209FFF (base 16) SmartNodes + Quai Banning 6 + Liège Liège 4000 + BE + +70-B3-D5 (hex) Incoil Induktion AB +F12000-F12FFF (base 16) Incoil Induktion AB + Brandthovdagatan 29 + Vasteras Vastmanland 72135 + SE + +70-B3-D5 (hex) KOMS Co.,Ltd. +05D000-05DFFF (base 16) KOMS Co.,Ltd. + 1059 Kitakata + Iida Nagano 395-0151 + JP + +70-B3-D5 (hex) Rail Power Systems GmbH +7B2000-7B2FFF (base 16) Rail Power Systems GmbH + Frankfurter Straße 111 + Offenbach am Main Hessen 63067 + DE + +70-B3-D5 (hex) BÄR Bahnsicherung AG +348000-348FFF (base 16) BÄR Bahnsicherung AG + Luppmenstrasse 3 + Fehraltorf 8320 + CH + +70-B3-D5 (hex) Sensile Technologies SA +AD1000-AD1FFF (base 16) Sensile Technologies SA + Rue de Lausanne 45 + Morges VD 1110 + CH + +70-B3-D5 (hex) Miravue +92A000-92AFFF (base 16) Miravue + 75 E 400 S STE 302 + Salt Lake City UT 84111 + US + +70-B3-D5 (hex) OCEAN +16C000-16CFFF (base 16) OCEAN + 30 rue Mozart + CLICHY 92110 + FR + +70-B3-D5 (hex) Idyllic Engineering Pte Ltd +D58000-D58FFF (base 16) Idyllic Engineering Pte Ltd + Blk 62B, Strathmore Ave, #04-58 + Singapore Singapore 143062 + SG + +70-B3-D5 (hex) Computerwise, Inc. +CEA000-CEAFFF (base 16) Computerwise, Inc. + 302 N. Winchester + Olathe KS 66062 + US + +70-B3-D5 (hex) Next Sight srl +511000-511FFF (base 16) Next Sight srl + via Roveredo 20/b + pordenone Italy 33170 + IT + +70-B3-D5 (hex) Embedded Systems Lukasz Panasiuk +A18000-A18FFF (base 16) Embedded Systems Lukasz Panasiuk + Wielkopolska 2A/9 + Kolobrzeg 78100 + PL + +70-B3-D5 (hex) Dot System S.r.l. +954000-954FFF (base 16) Dot System S.r.l. + Via Marco Biagi 34 + Lomagna Lecco 23871 + IT + +70-B3-D5 (hex) LG Electronics +88D000-88DFFF (base 16) LG Electronics + 2621, Nuambusunhwan-ro, Gangnam-gu, + Seoul 135-860 + KR + +70-B3-D5 (hex) Brinkmann Audio GmbH +1D4000-1D4FFF (base 16) Brinkmann Audio GmbH + Im Himmelreich 13 + Achberg 88147 + DE + +70-B3-D5 (hex) Profcon AB +86E000-86EFFF (base 16) Profcon AB + Victor Hasselblads gata 9 + Västra Frölunda 42131 + SE + +70-B3-D5 (hex) Marioff Corporation Oy +222000-222FFF (base 16) Marioff Corporation Oy + Äyritie 24 + Vantaa 01510 + FI + +70-B3-D5 (hex) LAMTEC Meß- und Regeltechnik für Feuerungen GmbH & Co. KG +5BC000-5BCFFF (base 16) LAMTEC Meß- und Regeltechnik für Feuerungen GmbH & Co. KG + Wiesenstraße 6 + Walldorf Baden Württemberg 69190 + DE + +70-B3-D5 (hex) Petring Energietechnik GmbH +CF5000-CF5FFF (base 16) Petring Energietechnik GmbH + Paderborner Str.76 + Schlangen Deutschland 33189 + DE + +70-B3-D5 (hex) iRF - Intelligent RF Solutions, LLC +21D000-21DFFF (base 16) iRF - Intelligent RF Solutions, LLC + 14600 York Road, Suite B + Sparks MD 21152 + US + +70-B3-D5 (hex) Gilbarco Veeder-Root ‎ +269000-269FFF (base 16) Gilbarco Veeder-Root ‎ + Level 1, 20 Highgate Street + Auburn NSW 2144 + AU + +70-B3-D5 (hex) Aeryon Labs Inc +482000-482FFF (base 16) Aeryon Labs Inc + 575 Kumpf Dr + Waterloo ON N2V 1K3 + CA + +70-B3-D5 (hex) Rudy Tellert +8EC000-8ECFFF (base 16) Rudy Tellert + Dorfstr. 15 + Werneck 97440 + DE + +70-B3-D5 (hex) SenSys (Design Electronics Ltd) +FBF000-FBFFFF (base 16) SenSys (Design Electronics Ltd) + 71 Redwood Valley Lane RD1 + Richmond Tasman 7081 + NZ + +70-B3-D5 (hex) WARECUBE,INC +4A9000-4A9FFF (base 16) WARECUBE,INC + 3F, 119-59, Sasadong + Ansansi Gyunggido 426-220 + KR + +70-B3-D5 (hex) L-3 communications ComCept Division +E09000-E09FFF (base 16) L-3 communications ComCept Division + 1700 Science Place + Rockwall TX 75032 + US + +70-B3-D5 (hex) CEA Technologies Pty Ltd +68E000-68EFFF (base 16) CEA Technologies Pty Ltd + 59-65 Gladstone St + Fyshwick ACT 2609 + AU + +70-B3-D5 (hex) KST technology +7F4000-7F4FFF (base 16) KST technology + 164-1, KST b/d., Bangi-dong, songpa-gu + SEOUL N/A 138-050 + KR + +70-B3-D5 (hex) TELECOM SANTE +272000-272FFF (base 16) TELECOM SANTE + 8 SQUARE DU CHENE GERMAIN + CESSON SEVIGNE 35510 + FR + +70-B3-D5 (hex) Henri Systems Holland bv +122000-122FFF (base 16) Henri Systems Holland bv + Scheepmalersstraat 33 + Zwijndrecht ZH 3334 KG + NL + +70-B3-D5 (hex) ELSAG +1C5000-1C5FFF (base 16) ELSAG + 205H Creek Ridge ROad + Greensboro NC 27406 + US + +70-B3-D5 (hex) ModuSystems, Inc +260000-260FFF (base 16) ModuSystems, Inc + 780 Montague Expressway Suite 203 + San Jose CA 95131 + US + +70-B3-D5 (hex) Invertek Drives Ltd +939000-939FFF (base 16) Invertek Drives Ltd + Offa's Dyke Business Park + Welshpool Powys SY21 8JF + GB + +70-B3-D5 (hex) QUERCUS TECHNOLOGIES, S.L. +03D000-03DFFF (base 16) QUERCUS TECHNOLOGIES, S.L. + Av. Onze de Setembre 19 + Reus Tarragona 43203 + ES + +70-B3-D5 (hex) CMC Industrial Electronics Ltd +18C000-18CFFF (base 16) CMC Industrial Electronics Ltd + 305-3602 Gilmore Way + Burnaby BC v5g4w9 + CA + +70-B3-D5 (hex) BIZERBA LUCEO +E1A000-E1AFFF (base 16) BIZERBA LUCEO + 16 RUE LAENNEC + VERN SUR SEICHE 35772 + FR + +70-B3-D5 (hex) Allied Data Systems +8CA000-8CAFFF (base 16) Allied Data Systems + 67/176 South Creek Road + Cromer NSW 2099 + AU + +70-B3-D5 (hex) Vigilate srl +B0C000-B0CFFF (base 16) Vigilate srl + Via Napoleonica, 6 + Rezzato BS 25086 + IT + +70-B3-D5 (hex) eeas gmbh +86C000-86CFFF (base 16) eeas gmbh + Bachstrasse 44 + Schwertberg 4311 + AT + +70-B3-D5 (hex) Asymmetric Technologies +9F8000-9F8FFF (base 16) Asymmetric Technologies + 1395 Grandview Avenue, Suite 3 + Columbus OH 43212 + US + +70-B3-D5 (hex) CISTECH Solutions +C3D000-C3DFFF (base 16) CISTECH Solutions + 170 JAMES ST + TOOWOOMBA QLD 4350 + AU + +70-B3-D5 (hex) Grupo Epelsa S.L. +2EC000-2ECFFF (base 16) Grupo Epelsa S.L. + C/ Punto Net,3 + Alcala de Henares Madrid 28805 + ES + +70-B3-D5 (hex) Wuhan Xingtuxinke ELectronic Co.,Ltd +32A000-32AFFF (base 16) Wuhan Xingtuxinke ELectronic Co.,Ltd + NO.C3-8F,Software Park,Optics Valley,East Lake Development Zone,Wuhan,Hubei,China + Wuhan Hubei 430074 + CN + +70-B3-D5 (hex) INFO CREATIVE (HK) LTD +24D000-24DFFF (base 16) INFO CREATIVE (HK) LTD + 44A 12/F,LUENTAK BLD.,JORDAN RD.,KOWLOON + HONGKONG 999077 + HK + +70-B3-D5 (hex) Shenzhen Rongda Computer Co.,Ltd +289000-289FFF (base 16) Shenzhen Rongda Computer Co.,Ltd + Room A616, Aoshida Building, Zhongkang Road, Futian District + Shenzhen Guangdong 518049 + CN + +70-B3-D5 (hex) FIBERNET LTD +041000-041FFF (base 16) FIBERNET LTD + 9 Hakidma st. Hi-Tech City Park, + Yokneam Non-US/Canada 2069206 + IL + +70-B3-D5 (hex) Electroimpact, Inc. +D9D000-D9DFFF (base 16) Electroimpact, Inc. + 4413 Chennault Beach Rd + Mukilteo WA 98275 + US + +70-B3-D5 (hex) Centuryarks Ltd., +52C000-52CFFF (base 16) Centuryarks Ltd., + 3-13-1,Nishiazabu + Minato-ku Tokyo 106-0031 + JP + +70-B3-D5 (hex) EMSCAN Corp. +DD8000-DD8FFF (base 16) EMSCAN Corp. + 1 - 1715 27 ave NE + Calgary Alberta T2E 7E1 + CA + +70-B3-D5 (hex) Septentrio NV +87E000-87EFFF (base 16) Septentrio NV + Interleuvenlaan 15i + Leuven 3001 + BE + +70-B3-D5 (hex) S-I-C +73B000-73BFFF (base 16) S-I-C + Schornbacher Weg 37-8 + Schorndorf BW 73614 + DE + +70-B3-D5 (hex) ELECTRONIC SYSTEMS DESIGN SPRL +DFC000-DFCFFF (base 16) ELECTRONIC SYSTEMS DESIGN SPRL + Rue de l'Etang 40 + Waterloo 1410 + BE + +70-B3-D5 (hex) GBS COMMUNICATIONS, LLC +A89000-A89FFF (base 16) GBS COMMUNICATIONS, LLC + 10773 NW 58TH STREET, STE 712 + DORAL FL 33178 + US + +70-B3-D5 (hex) Potter Electric Signal Co. LLC +A1B000-A1BFFF (base 16) Potter Electric Signal Co. LLC + 1609 Park 370 Place + Hazelwood MO 63042 + US + +70-B3-D5 (hex) Aquavision Distribution Ltd +0DA000-0DAFFF (base 16) Aquavision Distribution Ltd + unit 7 Riverpark, Billet Lane + Berkhamsted Hertfordshire HP4 1HL + GB + +70-B3-D5 (hex) CODEC Co., Ltd. +B37000-B37FFF (base 16) CODEC Co., Ltd. + 1-29-18 Tamagawa + Choufu-shi Tokyo 182-0025 + JP + +70-B3-D5 (hex) RCS Energy Management Ltd +A5A000-A5AFFF (base 16) RCS Energy Management Ltd + RMS House + Newbury Berkshire RG14 5PX + GB + +70-B3-D5 (hex) Ecologicsense +F96000-F96FFF (base 16) Ecologicsense + 605 Avenue Olivier Perroy + Rousset Bouches du Rhône 13790 + FR + +70-B3-D5 (hex) Woodam Co., Ltd. +C86000-C86FFF (base 16) Woodam Co., Ltd. + Na 555, EZEN Mecha zone, 117 Hwanggeum-ro, Yangchon-eup + Gimpo Gyeonggi-do 10048 + KR + +70-B3-D5 (hex) Aplex Technology Inc. +666000-666FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) ATEME +607000-607FFF (base 16) ATEME + 6 rue Dewoitine + Vélizy-Villacoublay 78140 + FR + +70-B3-D5 (hex) Nable Communications, Inc. +F5C000-F5CFFF (base 16) Nable Communications, Inc. + A-dong 702-ho, 660, Daewangpangyo-ro, Bundang-gu + Seongnam-si Gyeonggi-do 13494 + KR + +70-B3-D5 (hex) Code Hardware SA +29F000-29FFFF (base 16) Code Hardware SA + 100 Metros Norte Hogar de Ancianos + Quesada 21001 + CR + +70-B3-D5 (hex) Thermo Fisher Scientific +F76000-F76FFF (base 16) Thermo Fisher Scientific + 27 forge Parkway + Franklin MA 02038 + US + +70-B3-D5 (hex) DISMUNTEL, S.A. +E8F000-E8FFFF (base 16) DISMUNTEL, S.A. + P.I Cotes c/aiguaders, 15 + Valencia Algemesi 46680 + ES + +70-B3-D5 (hex) L.I.F.E. Corporation SA +D2F000-D2FFFF (base 16) L.I.F.E. Corporation SA + 20, rue Jean-Pierre Beicht + Luxembourg L-1226 + LU + +70-B3-D5 (hex) BHARAT HEAVY ELECTRICALS LIMITED +163000-163FFF (base 16) BHARAT HEAVY ELECTRICALS LIMITED + ELECTRONICS DIVISION , P.B NO. 2606 , MYSORE ROAD, + BANGALORE KARNATAKA 560026 + IN + +70-B3-D5 (hex) QUISS AG +E30000-E30FFF (base 16) QUISS AG + Lilienthalstr. 5 + Puchheim Bavarian 82178 + DE + +70-B3-D5 (hex) HL2 group +821000-821FFF (base 16) HL2 group + 2 Avenue Galilee + Chasseneuil Futuroscope 86961 + FR + +70-B3-D5 (hex) Volansys technologies pvt ltd +9AE000-9AEFFF (base 16) Volansys technologies pvt ltd + Block A-7th Floor, Safal Profitaire, Corporate Road, Prahaladnagar + Ahmedabad Gujarat 380015 + IN + +70-B3-D5 (hex) Arnouse Digital Devices Corp +DB0000-DB0FFF (base 16) Arnouse Digital Devices Corp + 1983 Marcus Ave, Suite 104 + Lake Success NY 11042 + US + +70-B3-D5 (hex) Syscom Instruments SA +DDC000-DDCFFF (base 16) Syscom Instruments SA + industrie 21 + Sainte-Croix 1450 + CH + +70-B3-D5 (hex) Tecogen Inc. +4B0000-4B0FFF (base 16) Tecogen Inc. + 45 First Avenue + Waltham MA 02451 + US + +70-B3-D5 (hex) elsys +71B000-71BFFF (base 16) elsys + 203-59, Yulchonsandan 2-ro, Yulchon-myeon + Yeosu-si Jeollanam-do 59602 + KR + +70-B3-D5 (hex) ControlWorks, Inc. +89B000-89BFFF (base 16) ControlWorks, Inc. + Jinil Bldg. Suite401, 13 Eonju-ro 81 gil, Gangnam-gu, + Seoul 06222 + KR + +70-B3-D5 (hex) Adimec Advanced Image Systems +854000-854FFF (base 16) Adimec Advanced Image Systems + Luchthavenweg 91 + Eindhoven 5657 EA + NL + +70-B3-D5 (hex) Hildebrand Technology Limited +21E000-21EFFF (base 16) Hildebrand Technology Limited + 16 Mortimer Street + London London W1T 3JL + GB + +70-B3-D5 (hex) Saratov Electrounit Production Plant named after Sergo Ordzhonikidze, OJSC +BE3000-BE3FFF (base 16) Saratov Electrounit Production Plant named after Sergo Ordzhonikidze, OJSC + 239, Bolshaya Sadovaya + Saratov Saratovskaya oblast 410005 + RU + +70-B3-D5 (hex) 3PS Inc +FB3000-FB3FFF (base 16) 3PS Inc + 1300 Arrow Point Drive + Cedar Park TX 78613 + US + +70-B3-D5 (hex) Alazar Technologies Inc. +697000-697FFF (base 16) Alazar Technologies Inc. + 310 - 6600 Trans-Canada Hwy + Pointe-Claire QC H9R 4S2 + CA + +70-B3-D5 (hex) E-T-A Elektrotechnische Apparate GmbH +AE7000-AE7FFF (base 16) E-T-A Elektrotechnische Apparate GmbH + Industriestr. 2-8 + Altdorf 90518 + DE + +70-B3-D5 (hex) Vtron Pty Ltd +400000-400FFF (base 16) Vtron Pty Ltd + Unit 2, 62 Township Drive West + West Burleigh Queensland 4219 + AU + +70-B3-D5 (hex) Innovative Circuit Technology +889000-889FFF (base 16) Innovative Circuit Technology + 26921 Gloucester Way + Langley BC V4W 3Y3 + CA + +70-B3-D5 (hex) DORLET SAU +58D000-58DFFF (base 16) DORLET SAU + Albert Eistein 34 + Alava SPAIN 01510 + ES + +70-B3-D5 (hex) AKEO PLUS +6FF000-6FFFFF (base 16) AKEO PLUS + ZA EN BEAUVOIR 769 RUE DE LA OUTARDE + CHATEAU GAILLARD 01500 + FR + +70-B3-D5 (hex) Rocket Lab Ltd. +61A000-61AFFF (base 16) Rocket Lab Ltd. + 3A Airpark Drive + Mangere Auckland 2022 + NZ + +70-B3-D5 (hex) PARK24 +EA0000-EA0FFF (base 16) PARK24 + 48 rue René CLAIR + PARIS 75018 + FR + +70-B3-D5 (hex) Carlson Wireless Technologies Inc. +174000-174FFF (base 16) Carlson Wireless Technologies Inc. + 2700 Foster Ave. + Arcata CA 95521 + US + +70-B3-D5 (hex) swissled technologies AG +649000-649FFF (base 16) swissled technologies AG + chemin des chalets 7 + chavannes de bogis 1279 + CH + +70-B3-D5 (hex) A-M Systems +3BB000-3BBFFF (base 16) A-M Systems + PO BOX 850 + Carlsborg WA 98324 + US + +70-B3-D5 (hex) Stercom Power Solutions GmbH +274000-274FFF (base 16) Stercom Power Solutions GmbH + Sebastian-Tiefenthalerstr. 15 + Rohrdorf Bayern 83101 + DE + +70-B3-D5 (hex) db Broadcast Products Ltd +7FB000-7FBFFF (base 16) db Broadcast Products Ltd + Kestrel House Sedgeway Business Park Witchford + Ely Cambridgeshire CB6 2HY + GB + +70-B3-D5 (hex) Krabbenhøft og Ingolfsson +F9A000-F9AFFF (base 16) Krabbenhøft og Ingolfsson + Thorsgade 59, 4. tv. + København N Danmark 2200 + DK + +70-B3-D5 (hex) Fujian Landfone Information Technology Co.,Ltd +91A000-91AFFF (base 16) Fujian Landfone Information Technology Co.,Ltd + Room 305, third floor,NO.550,Western suburbs Industrial Road,Hongshan Town,Gulou District,Fuzhou,P.R.China + Fuzhou Fujian 350001 + CN + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +513000-513FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Diamante Lighting Srl +925000-925FFF (base 16) Diamante Lighting Srl + via Einaudi, 8 + Alessandria AL 15121 + IT + +70-B3-D5 (hex) Xentech Solutions Limited +C63000-C63FFF (base 16) Xentech Solutions Limited + Suite 6 Stanta Business Centre, 3 Soothouse Spring + St Albans Hertfordshire AL36PF + GB + +70-B3-D5 (hex) Aplex Technology Inc. +106000-106FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) EREE Electronique +D11000-D11FFF (base 16) EREE Electronique + 6 avenu Dr Schweitzer + MEYZIEU 69882 + FR + +70-B3-D5 (hex) Burk Technology +BD2000-BD2FFF (base 16) Burk Technology + 7 Beaver Brook road + Littleton MA 01460 + US + +70-B3-D5 (hex) Amada Miyachi America Inc. +7B6000-7B6FFF (base 16) Amada Miyachi America Inc. + 1820 S. Myrtle Avenue + Monrovia CA 91016 + US + +70-B3-D5 (hex) Vocality International Ltd +10C000-10CFFF (base 16) Vocality International Ltd + Lydling Barn + Guildford Surrey GU86AP + GB + +70-B3-D5 (hex) The DX Shop Limited +37D000-37DFFF (base 16) The DX Shop Limited + Eliot Business Park + Nuneaton Warwickshire CV10 7RJ + GB + +70-B3-D5 (hex) TIAMA +0C4000-0C4FFF (base 16) TIAMA + ZA des Plattes - 1 Chemin des Plattes + VOURLES 69390 + FR + +70-B3-D5 (hex) CRDE +818000-818FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) SciTronix +3BC000-3BCFFF (base 16) SciTronix + Neufeld 6a + Höchst 6973 + AT + +70-B3-D5 (hex) LHA Systems (Pty) Ltd +180000-180FFF (base 16) LHA Systems (Pty) Ltd + 1 Innovation Center, Technopark + Stellenbosch Western Cape 7600 + ZA + +70-B3-D5 (hex) Rohde&Schwarz Topex SA +932000-932FFF (base 16) Rohde&Schwarz Topex SA + 71th-73th Nicolae Caramfil street, 2nd floor, 1th district + Bucuresti Romania 014142 + RO + +70-B3-D5 (hex) AEC s.r.l. +CCC000-CCCFFF (base 16) AEC s.r.l. + Via Zambon, 33/A + Creazzo Vicenza 36051 + IT + +70-B3-D5 (hex) ADETEC SAS +4E9000-4E9FFF (base 16) ADETEC SAS + 8 rue de l'Angoumois + ARGENTEUIL 95100 + FR + +70-B3-D5 (hex) Power Electronics Espana, S.L. +F4F000-F4FFFF (base 16) Power Electronics Espana, S.L. + C/ Leonardo Da Vinci, 24-26 + Paterna Valencia 46980 + ES + +70-B3-D5 (hex) Aplex Technology Inc. +B33000-B33FFF (base 16) Aplex Technology Inc. + 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District + Shenzhen Guangdong 518054 + CN + +70-B3-D5 (hex) Aplex Technology Inc. +3D9000-3D9FFF (base 16) Aplex Technology Inc. + 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District + Shenzhen Guangdong 518054 + CN + +70-B3-D5 (hex) Aplex Technology Inc. +E7C000-E7CFFF (base 16) Aplex Technology Inc. + 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District + Shenzhen Guangdong 518054 + CN + +70-B3-D5 (hex) NextEV Co., Ltd. +200000-200FFF (base 16) NextEV Co., Ltd. + 20 Building, No. 56 AnTuo Road, Anting Town, Jiading + Shanghai Shanghai 201805 + CN + +70-B3-D5 (hex) Sicon srl +3B2000-3B2FFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) NUMATA R&D Co.,Ltd +E9B000-E9BFFF (base 16) NUMATA R&D Co.,Ltd + 1-68 Furukawa-ekiminami + Osaki city 989-6161 + JP + +70-B3-D5 (hex) Active Research Limited +6A0000-6A0FFF (base 16) Active Research Limited + Unit 5, Wessex Trade Centre, Ringwood Road + Poole Dorset BH12 3PF + GB + +70-B3-D5 (hex) Scame Sistemi srl +2F3000-2F3FFF (base 16) Scame Sistemi srl + Via Lombardia 5 + Arluno Milan 20010 + IT + +70-B3-D5 (hex) Triax A/S +C9F000-C9FFFF (base 16) Triax A/S + Bjornkaervej 3 + Hornsyld Denmark 8783 + DK + +70-B3-D5 (hex) Muuntosähkö Oy - Trafox +A59000-A59FFF (base 16) Muuntosähkö Oy - Trafox + Niittylänpolku 4 + Helsinki 00620 + FI + +70-B3-D5 (hex) Cello Electronics (UK) Ltd +295000-295FFF (base 16) Cello Electronics (UK) Ltd + Cliff Lodge + Leyburn North Yorkshire DL8 5NS + GB + +70-B3-D5 (hex) Labinvent JSC +C1B000-C1BFFF (base 16) Labinvent JSC + vul. Adoewskaha 131, office 303 + Minsk Minsk 220018 + BY + +70-B3-D5 (hex) Gigaray +F3C000-F3CFFF (base 16) Gigaray + 100 Dicui Road + Wuxi Jiangsu 214072 + CN + +70-B3-D5 (hex) Nu-Tek Power Controls and Automation +97C000-97CFFF (base 16) Nu-Tek Power Controls and Automation + 6, Hosa Road , G.K Layout, Electronic City post + Bangalore Karnataka 560100 + IN + +70-B3-D5 (hex) Tagarno AS +DA8000-DA8FFF (base 16) Tagarno AS + Sandovej 4 + Horsens Denmark DK-8700 + DK + +70-B3-D5 (hex) ANTEK GmbH +90C000-90CFFF (base 16) ANTEK GmbH + Im Koechersgrund 3 + Beilstein Baden-Württemberg 71717 + DE + +70-B3-D5 (hex) Bionics co.,ltd. +A78000-A78FFF (base 16) Bionics co.,ltd. + Honmachi 1chome 2-1 Honmachi-riverside-bill 2F + osaka-city osaka-fu 541-0053 + JP + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +742000-742FFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) SYS TEC electronic GmbH +AB4000-AB4FFF (base 16) SYS TEC electronic GmbH + Am Windrad 2 + Heinsdorfergrund D-08468 + DE + +70-B3-D5 (hex) BAE Systems Surface Ships Limited +02A000-02AFFF (base 16) BAE Systems Surface Ships Limited + BAE Systems Surface Ships Ltd Broad Oak + Portsmouth Hampshire PO3 5PQ + GB + +70-B3-D5 (hex) M-Tech Innovations Limited +8B1000-8B1FFF (base 16) M-Tech Innovations Limited + Plot No. 1/2, Rajiv Gandhi Infotech Park, + Pune Maharashtra 411057 + IN + +70-B3-D5 (hex) allora Factory BVBA +EE1000-EE1FFF (base 16) allora Factory BVBA + Lijsterlaan 11 + Bornem 2880 + BE + +70-B3-D5 (hex) Easy Digital Concept +0B9000-0B9FFF (base 16) Easy Digital Concept + 1 avenue Girardot + Montmorency 95160 + FR + +70-B3-D5 (hex) Aplex Technology Inc. +528000-528FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) Entech Electronics +17D000-17DFFF (base 16) Entech Electronics + 37 Belford Ave + Adelaide Australia 5008 + AU + +70-B3-D5 (hex) Digital Yacht Ltd +BA7000-BA7FFF (base 16) Digital Yacht Ltd + Failand Farm + Bristol Avon BS8 3TR + GB + +70-B3-D5 (hex) Arnouse Digital Devices, Corp. +28B000-28BFFF (base 16) Arnouse Digital Devices, Corp. + 1983 Marcus Ave., Suite 104 + Lake Success null 11042 + US + +70-B3-D5 (hex) Vivalnk +3A9000-3A9FFF (base 16) Vivalnk + 4655 Old Ironsides Dr, #390 + Santa Clara CA 95054 + US + +70-B3-D5 (hex) Atos spa +2E7000-2E7FFF (base 16) Atos spa + Via alla Piana 57 + Sesto Calende Varese 21018 + IT + +70-B3-D5 (hex) Galileo Tıp Teknolojileri San. ve Tic. A.S. +FE2000-FE2FFF (base 16) Galileo Tıp Teknolojileri San. ve Tic. A.S. + Bulgurlu Mah. Kanyon Cd. 89/1 Battalgazi + Malatya 44000 + TR + +70-B3-D5 (hex) enModus +772000-772FFF (base 16) enModus + Cas-Gwent Chambers, Welsh Street + Chepstow Monmouthshire NP165X + GB + +70-B3-D5 (hex) Shenzhen Rihuida Electronics Co,. Ltd +046000-046FFF (base 16) Shenzhen Rihuida Electronics Co,. Ltd + Fuzhong Industrial Park #4 + Shenzhen 518103 + CN + +70-B3-D5 (hex) Prozess Technologie +B5C000-B5CFFF (base 16) Prozess Technologie + 6124 Delmar Blvd + St. Louis MO 63112 + US + +70-B3-D5 (hex) DALIAN LEVEAR ELECTRIC CO., LTD +FD2000-FD2FFF (base 16) DALIAN LEVEAR ELECTRIC CO., LTD + DA LIAN GAN JING ZI + DA LIAN LIAO NING 116033 + CN + +70-B3-D5 (hex) UCONSYS +232000-232FFF (base 16) UCONSYS + R.506, Blk. 17T11, Nguyen Thi Dinh Str. + Hanoi 123456 + VN + +70-B3-D5 (hex) Xcenter AS +E1C000-E1CFFF (base 16) Xcenter AS + Kjorbokollen 30 + Sandvika - 1337 + NO + +70-B3-D5 (hex) Kohler Mira Ltd +F55000-F55FFF (base 16) Kohler Mira Ltd + Cromwell Road + Cheltenham Gloucestershire GL52 5EP + GB + +70-B3-D5 (hex) PROFITT Ltd +091000-091FFF (base 16) PROFITT Ltd + office 5H, block 14-2 lit.A, Raevsky av. + Saint-Petersburg 194064 + RU + +70-B3-D5 (hex) IES S.r.l. +8B0000-8B0FFF (base 16) IES S.r.l. + Via Amedeo Nazzari, 3 + Anzio Roma 00042 + IT + +70-B3-D5 (hex) Sorama BV +26B000-26BFFF (base 16) Sorama BV + Torenallee 20 + Eindhoven Noord-Brabant 5617 BC + NL + +70-B3-D5 (hex) Ai-Lynx +847000-847FFF (base 16) Ai-Lynx + 1 avenue de l'Atlantique + Les Ulis 91940 + FR + +70-B3-D5 (hex) Software Motor Corp +5D1000-5D1FFF (base 16) Software Motor Corp + 1295 Forgewood Avenue + Sunnyvale CA 94089 + US + +70-B3-D5 (hex) Sensohive Technologies +384000-384FFF (base 16) Sensohive Technologies + Cortex Park 26 + Odense M 5230 + DK + +70-B3-D5 (hex) 8Cups +A6F000-A6FFFF (base 16) 8Cups + 29, Gonghang-daero 61-gil, Gangseo-gu + Seoul 07563 + KR + +70-B3-D5 (hex) Transit Solutions, LLC. +28A000-28AFFF (base 16) Transit Solutions, LLC. + 114 West Grandview Avenue + Zelienople PA 16063 + US + +70-B3-D5 (hex) Ascon Tecnologic S.r.l. +5A0000-5A0FFF (base 16) Ascon Tecnologic S.r.l. + via Indipendenza, 56 + Vigevano PV 27029 + IT + +70-B3-D5 (hex) Forschungs- und Transferzentrum Leipzig e.V. +124000-124FFF (base 16) Forschungs- und Transferzentrum Leipzig e.V. + Karl-Liebknecht-Strasse 143 + Leipzig 04277 + DE + +70-B3-D5 (hex) PTYPE Co., LTD. +69E000-69EFFF (base 16) PTYPE Co., LTD. + B121, B-dong, Keumkang Penterium IT Tower, 810, Gwanyand 2-dong, Dongan-gu + Anyang-si Gyeonggi-do 14056 + KR + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +DB4000-DB4FFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) Grupo Epelsa S.L. +D1B000-D1BFFF (base 16) Grupo Epelsa S.L. + C/ Punto Net,3 + Alcala de Henares Madrid 28805 + ES + +70-B3-D5 (hex) Swissponic Sagl +52E000-52EFFF (base 16) Swissponic Sagl + via Pedemonte 28a + Bellinzona Ticino 6500 + CH + +70-B3-D5 (hex) Herholdt Controls srl +4A1000-4A1FFF (base 16) Herholdt Controls srl + Via Mestre 13 + Milan 20132 + IT + +70-B3-D5 (hex) MESOTECHNIC +AFE000-AFEFFF (base 16) MESOTECHNIC + 9 rue Léopold Sédar-Senghor + COLOMBELLES 14460 + FR + +70-B3-D5 (hex) OHMORI ELECTRIC INDUSTRIES CO.LTD +6A9000-6A9FFF (base 16) OHMORI ELECTRIC INDUSTRIES CO.LTD + Tuzuki-ku 1 Higashiyamata + Yokohama-shi Kanagawa-ken 224-0024 + JP + +70-B3-D5 (hex) PDD Group Ltd +D81000-D81FFF (base 16) PDD Group Ltd + 87 Richford Street + London Greater London W6 7HJ + GB + +70-B3-D5 (hex) NEMEUS-SAS +326000-326FFF (base 16) NEMEUS-SAS + 1 rue de la Chalotais Bat A + Cesson-Sévigné 35510 + FR + +70-B3-D5 (hex) SHIZUKI ELECTRIC CO.,INC +FE6000-FE6FFF (base 16) SHIZUKI ELECTRIC CO.,INC + 10-45 Taisha-cho + Nishinomiya-shi Hyogo 662-0867 + JP + +70-B3-D5 (hex) EMAC, Inc. +8AB000-8ABFFF (base 16) EMAC, Inc. + 2390 EMAC Way + Carbondale IL 62901 + US + +70-B3-D5 (hex) Fin Robotics Inc +0C8000-0C8FFF (base 16) Fin Robotics Inc + 11871 Hilltop Dr, Losaltos Hills + Los Altos CA 94024 + US + +70-B3-D5 (hex) OPTIX JSC +E77000-E77FFF (base 16) OPTIX JSC + 19 Kliment Ohridski str. + Sofia Sofia 1756 + BG + +70-B3-D5 (hex) Bayern Engineering GmbH & Co. KG +570000-570FFF (base 16) Bayern Engineering GmbH & Co. KG + Maillinger Str.13 + Bad Aibling Bavaria 83043 + DE + +70-B3-D5 (hex) Project Decibel, Inc. +645000-645FFF (base 16) Project Decibel, Inc. + 745 Atlantic Ave Fl 8 + Boston MA 02111 + US + +70-B3-D5 (hex) eCozy GmbH +DE0000-DE0FFF (base 16) eCozy GmbH + Trimburgstr. 2 + Munich Bavaria 81249 + DE + +70-B3-D5 (hex) Innosonix GmbH +14E000-14EFFF (base 16) Innosonix GmbH + Hauptstrasse 35 + Ahorn Bayern 96482 + DE + +70-B3-D5 (hex) MoviTHERM +694000-694FFF (base 16) MoviTHERM + 15540 Rockfield Blvd C110 + Irvine CA 92618 + US + +70-B3-D5 (hex) Sailmon BV +033000-033FFF (base 16) Sailmon BV + Vlierweg 22 + Amsterdam Noord-Holland 1032 LG + NL + +70-B3-D5 (hex) IDOSENS +407000-407FFF (base 16) IDOSENS + 51 chemin du vieux chene + MEYLAN ISERE 38240 + FR + +70-B3-D5 (hex) GID Industrial +25B000-25BFFF (base 16) GID Industrial + 1218 Executive Drive West + Richardson TX 75081 + US + +70-B3-D5 (hex) DIEHL Controls +313000-313FFF (base 16) DIEHL Controls + Pfannerstrasse 75-83 + Wangen im Allgaeu D 88239 + DE + +70-B3-D5 (hex) APOLLO GIKEN Co.,Ltd. +3E9000-3E9FFF (base 16) APOLLO GIKEN Co.,Ltd. + 2-6-25 CHIGASAKIMINAMI TSUZUKI-KU + Yokohama Kanagawa 2240037 + JP + +70-B3-D5 (hex) Acc+Ess Ltd +FCF000-FCFFFF (base 16) Acc+Ess Ltd + Glenrhu + Wick Highland KW1 4TW + GB + +70-B3-D5 (hex) Paradigm Communication Systems Ltd +B3E000-B3EFFF (base 16) Paradigm Communication Systems Ltd + Paradigm House + Alton Hants GU34 2PP + GB + +70-B3-D5 (hex) ePOINT Embedded Computing Limited +01E000-01EFFF (base 16) ePOINT Embedded Computing Limited + Williamton House + Culross Fife KY12 8HL + GB + +70-B3-D5 (hex) Nanospeed Technologies Limited +E35000-E35FFF (base 16) Nanospeed Technologies Limited + Devonshire House + Borehamwood Hertfordshire WD6 1QQ + GB + +70-B3-D5 (hex) FUJICOM Co.,Ltd. +9F0000-9F0FFF (base 16) FUJICOM Co.,Ltd. + 1581-1, Wakakodama, Gyouda-shi + Saitama-ken 3610017 + JP + +70-B3-D5 (hex) ADAMCZEWSKI elektronische Messtechnik GmbH +364000-364FFF (base 16) ADAMCZEWSKI elektronische Messtechnik GmbH + Felix-Wankel-Str. 13 + Zaberfeld Baden-Württemberg 74374 + DE + +70-B3-D5 (hex) ENVItech s.r.o. +6F9000-6F9FFF (base 16) ENVItech s.r.o. + Janka Krala 16 + Trencin 911 01 + SK + +70-B3-D5 (hex) servicios de consultoria independiente S.L. +59D000-59DFFF (base 16) servicios de consultoria independiente S.L. + c/doctor apolinario macias 22. of.2 + las palmas de gran canaria Las Palmas 35011 + ES + +70-B3-D5 (hex) RANIX,Inc. +404000-404FFF (base 16) RANIX,Inc. + 3F, Handock Bldg., 2645 Nambusunhwan-ro, Gangnam-gu, Seoul, Korea + Seoul Gangnam-gu 135-859 + KR + +70-B3-D5 (hex) DK-Technologies A/S +3C0000-3C0FFF (base 16) DK-Technologies A/S + Marielundvej 37D + Herlev _ 2730 + DK + +70-B3-D5 (hex) Teletypes Manufacturing Plant +554000-554FFF (base 16) Teletypes Manufacturing Plant + 141, Saltykova-Schedrina Stree + Kaluga Kaluga/Kaluga region 248002 + RU + +70-B3-D5 (hex) FeldTech GmbH +A01000-A01FFF (base 16) FeldTech GmbH + Goestingerstrasse 70 + Graz - 8051 + AT + +70-B3-D5 (hex) ATEME +DC0000-DC0FFF (base 16) ATEME + 26 Burospace + Bievres IDF 91470 + + +70-B3-D5 (hex) SINED srl +C88000-C88FFF (base 16) SINED srl + Via 25 Aprile 34 + Granarolo Bologna 40057 + IT + +70-B3-D5 (hex) CommBox P/L +835000-835FFF (base 16) CommBox P/L + 3b/10 Rodborough Rd + Frenchs Forest NSW 2086 + AU + +70-B3-D5 (hex) Quaesta Instruments, LLC +88F000-88FFFF (base 16) Quaesta Instruments, LLC + 1665 E 18th Street + Tucson AZ 85719 + US + +70-B3-D5 (hex) Private +ADA000-ADAFFF (base 16) Private + +70-B3-D5 (hex) MEPS Realtime +866000-866FFF (base 16) MEPS Realtime + 6451 El Camino Real + Carlsbad California 92009 + US + +70-B3-D5 (hex) PlayAlive A/S +82E000-82EFFF (base 16) PlayAlive A/S + Platzvej 2 + Vejle Denmark 7100 + DK + +70-B3-D5 (hex) Applied Systems Engineering, Inc. +9C8000-9C8FFF (base 16) Applied Systems Engineering, Inc. + 1671 Dell Ave. + Campbell CA 95008 + US + +70-B3-D5 (hex) Bunka Shutter Co., Ltd. +5A9000-5A9FFF (base 16) Bunka Shutter Co., Ltd. + 644-1 Tenjingoe,Ooaza-Kamiishizuka + Oyama Tochigi 323-0063 + JP + +70-B3-D5 (hex) Damerell Design Limited (DCL) +D8C000-D8CFFF (base 16) Damerell Design Limited (DCL) + 111 St Michaels Road + Aldershot Hampshire GU12 4JW + GB + +70-B3-D5 (hex) Aplex Technology Inc. +C21000-C21FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) Sinftech LLC +4BA000-4BAFFF (base 16) Sinftech LLC + 406, 1, Rizhskaya street + Saint Petersburg Saint Petersburg 195196 + RU + +70-B3-D5 (hex) Metromatics Pty Ltd +827000-827FFF (base 16) Metromatics Pty Ltd + 25 Flinders Pde + North Lakes QLD 4509 + AU + +70-B3-D5 (hex) Plasmability, LLC +2A7000-2A7FFF (base 16) Plasmability, LLC + 4715 Steiner Ranch Blvd + Austin TX 78732 + US + +70-B3-D5 (hex) Laser Imagineering GmbH +0D8000-0D8FFF (base 16) Laser Imagineering GmbH + Rudolf-Diesel-Weg 5 + Moelln Schleswig Holstein 23879 + DE + +70-B3-D5 (hex) Smart Energy Code Company Limited +1F3000-1F3FFF (base 16) Smart Energy Code Company Limited + 8 Fenchurch Place + London England, London EC3M 4AJ + GB + +70-B3-D5 (hex) WARECUBE,INC +BAE000-BAEFFF (base 16) WARECUBE,INC + 3F, 119-59, Sasadong + Ansansi Gyunggido 426-220 + KR + +70-B3-D5 (hex) Fenotech Inc. +B85000-B85FFF (base 16) Fenotech Inc. + 3478 Buskirk Ave Ste 1000 + Pleasant Hill CA 94523 + US + +70-B3-D5 (hex) Pullnet Technology,S.L. +D8D000-D8DFFF (base 16) Pullnet Technology,S.L. + Parc Tecnologic BCNord + Barcelona Catalonia 08042 + ES + +70-B3-D5 (hex) EQUIPOS DE TELECOMUNICACIÓN OPTOELECTRÓNICOS, S.A. +2BC000-2BCFFF (base 16) EQUIPOS DE TELECOMUNICACIÓN OPTOELECTRÓNICOS, S.A. + POL.MALPICA, C/F OESTE, G.QUEJIDO, 74 + ZARAGOZA ZARAGOZA 50057 + ES + +70-B3-D5 (hex) HDL da Amazônia Industria Eletrônica Ltda +A27000-A27FFF (base 16) HDL da Amazônia Industria Eletrônica Ltda + Avenida Abiurana, 1150 - Distrito + Manaus MN 69075-010 + BR + +70-B3-D5 (hex) Visual Engineering Technologies Ltd +6D1000-6D1FFF (base 16) Visual Engineering Technologies Ltd + The Barns, Kemps Farm + Colchester Essex CO3 8NB + GB + +70-B3-D5 (hex) Birdland Audio +AD5000-AD5FFF (base 16) Birdland Audio + 484 Washington St. Ste.B-450 + Monterey CA 93940 + US + +70-B3-D5 (hex) AVI Pty Ltd +3E2000-3E2FFF (base 16) AVI Pty Ltd + 9 Pitt Way + Booragoon Western Australia 6154 + AU + +70-B3-D5 (hex) PCME Ltd. +FE8000-FE8FFF (base 16) PCME Ltd. + Clearview Building + St Ives Cambridgeshire PE27 3GH + GB + +70-B3-D5 (hex) pureLiFi Ltd +958000-958FFF (base 16) pureLiFi Ltd + ETTC, Alrick Building + Edinburgh Edinburgh EH9 3BF + GB + +70-B3-D5 (hex) PEEK TRAFFIC +C3C000-C3CFFF (base 16) PEEK TRAFFIC + 5401 N SAM HOUSTON PKWY W + HOUSTON TEXAS 77086 + US + +70-B3-D5 (hex) Technik & Design GmbH +BAD000-BADFFF (base 16) Technik & Design GmbH + Rhinstrasse 84 + Berlin Berlin 12681 + DE + +70-B3-D5 (hex) RF Code +A51000-A51FFF (base 16) RF Code + 2600 Longhorn Blvd. ste 111 + Austin Texas 78758 + US + +70-B3-D5 (hex) Qxperts Italia S.r.l. +5B0000-5B0FFF (base 16) Qxperts Italia S.r.l. + Via Muratori 9 + Genova Italy 16152 + IT + +70-B3-D5 (hex) Road-iQ, LLC +4DD000-4DDFFF (base 16) Road-iQ, LLC + 2183 Alpine Way + Bellingham WA 98226 + US + +70-B3-D5 (hex) LLVISION TECHNOLOGY CO.,LTD +E21000-E21FFF (base 16) LLVISION TECHNOLOGY CO.,LTD + Room302,Building A Fuxing,No.30 He Tao Yuan,Guan Dong Dian Bei Jie + Beijing Beijing 100026 + CN + +70-B3-D5 (hex) AML Oceanographic +0CD000-0CDFFF (base 16) AML Oceanographic + 2071 Malaview Avenue + Sidney British Columbia V8L 5X6 + CA + +70-B3-D5 (hex) Twoway Communications, Inc. +4AA000-4AAFFF (base 16) Twoway Communications, Inc. + 41 Wu Kung 6 Rd., New Taipei Industrial Park, New Taipei City,24891,Taiwan,R.O.C. + New Taipei city Taipei 24891 + TW + +70-B3-D5 (hex) Kentech Instruments Limited +EAC000-EACFFF (base 16) Kentech Instruments Limited + The Isis Building + Wallingford Oxfordshire OX10 8BA + GB + +70-B3-D5 (hex) Global Communications Technology LLC +8AD000-8ADFFF (base 16) Global Communications Technology LLC + 4915 Waters Edge Dr + Raleigh North Carolina 27606-2394 + US + +70-B3-D5 (hex) Conjing Networks Inc. +134000-134FFF (base 16) Conjing Networks Inc. + 4F., No.108, Zhenxing Rd., East Dist. + Hsinchu City Taiwan 30063 + TW + +70-B3-D5 (hex) CW2. Gmbh & Co. KG +79E000-79EFFF (base 16) CW2. Gmbh & Co. KG + Tübinger Straße 43 + Stuttgart Baden-Württemberg 70178 + DE + +70-B3-D5 (hex) Vtron Pty Ltd +341000-341FFF (base 16) Vtron Pty Ltd + Unit 2, 62 Township Drive West + West Burleigh Queensland 4219 + AU + +70-B3-D5 (hex) HAMEG GmbH +F5A000-F5AFFF (base 16) HAMEG GmbH + Industriestr. 6 + Mainhausen Hessen 63533 + DE + +70-B3-D5 (hex) Vitec System Engineering Inc. +799000-799FFF (base 16) Vitec System Engineering Inc. + 1-2-5 + Shinagawa-ku Tokyo 140-0002 + JP + +70-B3-D5 (hex) Akenori PTE LTD +6A5000-6A5FFF (base 16) Akenori PTE LTD + 176 JOO CHIAT ROAD #02-02 + 427447 + SG + +70-B3-D5 (hex) Amrehn & Partner EDV-Service GmbH +20E000-20EFFF (base 16) Amrehn & Partner EDV-Service GmbH + Friedrich-König-Straße 11 + Waldbüttelbrunn Bayern 97297 + DE + +70-B3-D5 (hex) West-Com Nurse Call Systems, Inc. +AA8000-AA8FFF (base 16) West-Com Nurse Call Systems, Inc. + 2200 Cordelia Road + Fairfield CA 94534 + US + +70-B3-D5 (hex) FOTONA D.D. +BD3000-BD3FFF (base 16) FOTONA D.D. + Stegne 7 + Ljubljana 1000 + SI + +70-B3-D5 (hex) Redwood Systems +A2A000-A2AFFF (base 16) Redwood Systems + 3839 Spinnaker Court + Fremont CA 94538 + US + +70-B3-D5 (hex) Wiingtech International Co. LTD. +6ED000-6EDFFF (base 16) Wiingtech International Co. LTD. + 2F., No. 51, LN. 174, Chungshiao Rd. + New Taipei City Taiwan 220 + TW + +70-B3-D5 (hex) Smith Meter, Inc. +E23000-E23FFF (base 16) Smith Meter, Inc. + 1602 Wagner Ave. + Erie PA 16510 + US + +70-B3-D5 (hex) KSJ Co.Ltd +917000-917FFF (base 16) KSJ Co.Ltd + Address 4F Kurosu Bldg. + Nakano-ku Tokyo 1640012 + JP + +70-B3-D5 (hex) PXM sp.k. +EFB000-EFBFFF (base 16) PXM sp.k. + Przemyslowa 12 + Krakow Malopolska 30-701 + PL + +70-B3-D5 (hex) Tiab Limited +DF6000-DF6FFF (base 16) Tiab Limited + Upton Lodge Buildings, + Middleton Cheney Banbury OX17 2PJ + GB + +70-B3-D5 (hex) Dynamic Controls +AB9000-AB9FFF (base 16) Dynamic Controls + 17 Print Place + Christchurch Canterbury 8024 + NZ + +70-B3-D5 (hex) Redler Computers +41E000-41EFFF (base 16) Redler Computers + Hamelacha St., 8 ,New Industrial Zone + Netanya Israel 42815 + IL + +70-B3-D5 (hex) ATX NETWORKS LTD +A00000-A00FFF (base 16) ATX NETWORKS LTD + Halapid 12 st + Petach tikva Israel 4917001 + IL + +70-B3-D5 (hex) Confed Holding B.V. +99F000-99FFFF (base 16) Confed Holding B.V. + Beurtschipper 2-4 + Nijkerk n.a. 3861SC + NL + +70-B3-D5 (hex) BRS Sistemas Eletronicos +D97000-D97FFF (base 16) BRS Sistemas Eletronicos + Rua Gomes de Freitas, 491/204 + Porto Alegre - RS (Non U.S.) 91380-000 + BR + +70-B3-D5 (hex) Li Seng Technology Ltd., +4F0000-4F0FFF (base 16) Li Seng Technology Ltd., + 901., Siu Fung Hong Building + Hong Kong Hong Kong 852 + HK + +70-B3-D5 (hex) Zenros ApS +F39000-F39FFF (base 16) Zenros ApS + Kongevejen 331- 1. + Holte Hovedstaden DK2840 + DK + +70-B3-D5 (hex) TELETASK +C56000-C56FFF (base 16) TELETASK + Ottergemsesteenweg-Zuid 729 + GENT 9000 + BE + +70-B3-D5 (hex) Private +22E000-22EFFF (base 16) Private + +70-B3-D5 (hex) Coherent Logix, Inc. +2BE000-2BEFFF (base 16) Coherent Logix, Inc. + 1120 S Capital of TX HWY + Austin TX 78746 + US + +70-B3-D5 (hex) Figment Design Laboratories +417000-417FFF (base 16) Figment Design Laboratories + 113 11th Avenue + Johannesburg Gauteng 2170 + ZA + +70-B3-D5 (hex) Power Electronics Espana, S.L. +4CD000-4CDFFF (base 16) Power Electronics Espana, S.L. + C/ Leonardo Da Vinci, 24-26 + Paterna Valencia 46980 + ES + +70-B3-D5 (hex) Institute of Power Engineering, Gdansk Division +6E4000-6E4FFF (base 16) Institute of Power Engineering, Gdansk Division + Mikolaja Reja 27 + Gdansk Pomorskie 80-870 + PL + +70-B3-D5 (hex) Lieron BVBA +E6E000-E6EFFF (base 16) Lieron BVBA + Beversluis 6 + Wezemaal Vl. Brabant 3111 + BE + +70-B3-D5 (hex) FeCon GmbH +BE1000-BE1FFF (base 16) FeCon GmbH + Eckernförder Landstraße 78 + Flensburg Schleswig Holstein 24941 + DE + +70-B3-D5 (hex) Nanjing Magewell Electronics Co., Ltd. +75D000-75DFFF (base 16) Nanjing Magewell Electronics Co., Ltd. + Romm 701, Building C, Win-world Innovation Park + Nanjing Jiangsu 211100 + CN + +70-B3-D5 (hex) Roush +65B000-65BFFF (base 16) Roush + 12249 Levan + Livonia MI 48150 + US + +70-B3-D5 (hex) Nexus Technologies Pty Ltd +0C1000-0C1FFF (base 16) Nexus Technologies Pty Ltd + 66-68 Wedgewood Road + Hallam Victoria 3803 + AU + +70-B3-D5 (hex) HI-TECH SYSTEM Co. Ltd. +26E000-26EFFF (base 16) HI-TECH SYSTEM Co. Ltd. + 76-22 Toiso + Eniwa Hokkaido 061-1405 + JP + +70-B3-D5 (hex) Zehetner-Elektronik GmbH +5E9000-5E9FFF (base 16) Zehetner-Elektronik GmbH + Florianerstrasse 19 + Sankt Marien 4502 + AT + +70-B3-D5 (hex) RFEL Ltd +9F1000-9F1FFF (base 16) RFEL Ltd + Unit B, The Apex + Newport Isle of Wight PO30 5XW + GB + +70-B3-D5 (hex) MeshWorks Wireless Oy +C39000-C39FFF (base 16) MeshWorks Wireless Oy + Haarlankatu 1 J + Tampere No selection required 33230 + FI + +70-B3-D5 (hex) GAMPT mbH +796000-796FFF (base 16) GAMPT mbH + Hallesche Str. 99F + Merseburg S-A 06217 + DE + +70-B3-D5 (hex) Tresent Technologies +030000-030FFF (base 16) Tresent Technologies + 104 Bartlett Drive + Schwenksville Pennsylvania 19473 + US + +70-B3-D5 (hex) Lookout Portable Security +B82000-B82FFF (base 16) Lookout Portable Security + 4105 Royal Dr. #100 + Kennesaw GA 30144 + US + +70-B3-D5 (hex) Videotrend srl +39A000-39AFFF (base 16) Videotrend srl + Via Brughetti 9/H + Bovisio Masciago Monza Brianza 20813 + IT + +70-B3-D5 (hex) SIMON TECH, S.L. +882000-882FFF (base 16) SIMON TECH, S.L. + Diputació, 390 + BARCELONA BARCELONA 08013 + ES + +70-B3-D5 (hex) Smart Service Technologies CO., LTD +660000-660FFF (base 16) Smart Service Technologies CO., LTD + No.802, 2-12-3, Imajuku, Nishi-ku + Fukuoka Fukuoka 819-0167 + JP + +70-B3-D5 (hex) Vickers Electronics Ltd +9F5000-9F5FFF (base 16) Vickers Electronics Ltd + Unit 14, Alliance House + Trafford Park Manchester M17 1QS + GB + +70-B3-D5 (hex) Connor Winfield LTD +D0C000-D0CFFF (base 16) Connor Winfield LTD + Bay 143 Shannon Ind Est + Shannon Clare 0000 + IE + +70-B3-D5 (hex) OMEGA BILANCE SRL SOCIETA' UNIPERSONALE +48D000-48DFFF (base 16) OMEGA BILANCE SRL SOCIETA' UNIPERSONALE + VIA FRANCESCO CARACCIOLO, 115 + NAPLES NAPLES 80122 + IT + +70-B3-D5 (hex) Loop Labs, Inc. +3DA000-3DAFFF (base 16) Loop Labs, Inc. + 207 South Bannock Street + Denver Colorado 80223 + US + +70-B3-D5 (hex) INTERNET PROTOCOLO LOGICA SL +0FF000-0FFFFF (base 16) INTERNET PROTOCOLO LOGICA SL + Sector Foresta 43, local 26 + Tres Cantos Madrid 28760 + ES + +70-B3-D5 (hex) Glidewell Laboratories +502000-502FFF (base 16) Glidewell Laboratories + 4141 MacArthur Blvd + Newport Beach CA 92660 + US + +70-B3-D5 (hex) Metek Meteorologische Messtechnik GmbH +A6D000-A6DFFF (base 16) Metek Meteorologische Messtechnik GmbH + Fritz-Straßmann-Straße 4 + Elmshorn Schleswig-Holstein D-25337 + + +70-B3-D5 (hex) Beijing CONvision Technology Co.,Ltd +08E000-08EFFF (base 16) Beijing CONvision Technology Co.,Ltd + suzhoujie apartment #33 room 1302 + Beijing 100080 + CN + +70-B3-D5 (hex) WoKa-Elektronik GmbH +8E1000-8E1FFF (base 16) WoKa-Elektronik GmbH + Fulder Tor 30 + Alsfeld Hessen 36304 + DE + +70-B3-D5 (hex) SOUDAX EQUIPEMENTS +8E0000-8E0FFF (base 16) SOUDAX EQUIPEMENTS + 14 AVE DE LA MAULDRE + EPONE IDF 78680 + FR + +70-B3-D5 (hex) Cyviz AS +C6D000-C6DFFF (base 16) Cyviz AS + Vestre svanholmen 6 + Sandnes NO N4313 + NO + +70-B3-D5 (hex) Qprel srl +DA1000-DA1FFF (base 16) Qprel srl + Via Fiorentina 578/D + Pistoia Italy 51100 + IT + +70-B3-D5 (hex) Cyberteam Sp z o o +36D000-36DFFF (base 16) Cyberteam Sp z o o + Kalinowice 157 + Zamosc Lubelskie 22400 + PL + +70-B3-D5 (hex) LunaNexus Inc +55D000-55DFFF (base 16) LunaNexus Inc + 1-8-29 nishimiyahara + Osakashi yodogawa-ku Osaka-fu 5320004 + JP + +70-B3-D5 (hex) Houston Radar LLC +D1E000-D1EFFF (base 16) Houston Radar LLC + 12818 Century Dr + Stafford Texas 77477 + US + +70-B3-D5 (hex) Veryx Technologies Private Limited +43D000-43DFFF (base 16) Veryx Technologies Private Limited + Floor 1, RR Tower 4, Thiru-Vi-Ka Industrial Estate + Chennai Tamil Nadu 600032 + IN + +70-B3-D5 (hex) Deymed Diagnostic +BCA000-BCAFFF (base 16) Deymed Diagnostic + Velky Drevic 91 + Hronov Kralovehradecky kraj 54934 + CZ + +70-B3-D5 (hex) managee GmbH & Co KG +5F0000-5F0FFF (base 16) managee GmbH & Co KG + Marbergweg 79 + Cologne NRW 51107 + DE + +70-B3-D5 (hex) Niveo International BV +8DC000-8DCFFF (base 16) Niveo International BV + Communicatieweg 9L + Mijdrecht ZH 3641SG + NL + +70-B3-D5 (hex) ATEME +3E5000-3E5FFF (base 16) ATEME + 26 Burospace + Bievres IDF 91470 + + +70-B3-D5 (hex) Guardian Controls International Ltd +710000-710FFF (base 16) Guardian Controls International Ltd + 56 Crewe Road + Sandbach Cheshire CW11 4NN + GB + +70-B3-D5 (hex) DiTEST Fahrzeugdiagnose GmbH +AEE000-AEEFFF (base 16) DiTEST Fahrzeugdiagnose GmbH + Alte Poststraße 152 + Graz Steiermark 8020 + AT + +70-B3-D5 (hex) Ipitek +ECF000-ECFFFF (base 16) Ipitek + 2320 Faraday Ave + Carlsbad CA 92008 + US + +70-B3-D5 (hex) STRACK LIFT AUTOMATION GmbH +A40000-A40FFF (base 16) STRACK LIFT AUTOMATION GmbH + Lise-Meitner-Straße 2 + Wülfrath NRW 42489 + DE + +70-B3-D5 (hex) XI'AN SHENMING ELECTRON TECHNOLOGY CO.,LTD +B16000-B16FFF (base 16) XI'AN SHENMING ELECTRON TECHNOLOGY CO.,LTD + 1-2-4-2401 XIANGSHU NO.3 KEJI FIVE STREET + XI'AN SHANXI 710000 + CN + +70-B3-D5 (hex) Census Digital Incorporated +86D000-86DFFF (base 16) Census Digital Incorporated + 72 Dynamic Drive + Toronto Ontario M1V 3Z5 + CA + +70-B3-D5 (hex) WIBOND Informationssysteme GmbH +F2A000-F2AFFF (base 16) WIBOND Informationssysteme GmbH + Neustädter Strasse 19 + Parkstein Bayern 92711 + DE + +70-B3-D5 (hex) Fluid Management Technology +A7A000-A7AFFF (base 16) Fluid Management Technology + PO Box 3197 + Port Adelaide South Australia 5015 + AU + +70-B3-D5 (hex) Providius Corp +BBD000-BBDFFF (base 16) Providius Corp + 848 Main St E + Hamilton Ontario L8M1L9 + CA + +70-B3-D5 (hex) UNI DIMENXI SDN BHD +C96000-C96FFF (base 16) UNI DIMENXI SDN BHD + A-1-05, SME Technopreneur Centre Cyberjaya, + Cyberjaya Selangor Darul Ehsan 63000 + MY + +70-B3-D5 (hex) Botek Systems AB +A2F000-A2FFFF (base 16) Botek Systems AB + Box 35 + Ulricehamn 52321 + SE + +70-B3-D5 (hex) Lehigh Electric Products Co +5B5000-5B5FFF (base 16) Lehigh Electric Products Co + 6265 Hamilton Blvd + Allentown PA 18106 + US + +70-B3-D5 (hex) Eta Beta Srl +B15000-B15FFF (base 16) Eta Beta Srl + Via Mura dei Francesi, 26 + Ciampino Roma 00043 + IT + +70-B3-D5 (hex) Honeywell +9A7000-9A7FFF (base 16) Honeywell + 13350 US Highway 19 N + Clearwater FLORIDA 33764 + US + +70-B3-D5 (hex) Cygnus LLC +0FB000-0FBFFF (base 16) Cygnus LLC + 510 East 41st St + Paterson NJ 07504 + US + +70-B3-D5 (hex) KST technology +C8D000-C8DFFF (base 16) KST technology + 164-1, KST b/d., Bangi-dong, songpa-gu + SEOUL N/A 138-050 + KR + +70-B3-D5 (hex) BIO RAD LABORATORIES +DDD000-DDDFFF (base 16) BIO RAD LABORATORIES + 6000 JAMES WATSON DR. + HERCULES CA 94547 + US + +70-B3-D5 (hex) GD Mission Systems +C27000-C27FFF (base 16) GD Mission Systems + 8220 E. Roosevelt St. + Scottsdale AZ 85257 + US + +70-B3-D5 (hex) Glova Rail A/S +918000-918FFF (base 16) Glova Rail A/S + Elvej 3 + Odense S 5260 + DK + +70-B3-D5 (hex) Oso Technologies +871000-871FFF (base 16) Oso Technologies + 301 N. Neil St. + Champaign Illinois 61820 + US + +00-1B-C5 (hex) UAB Kitron +0C9000-0C9FFF (base 16) UAB Kitron + Taikos 151 + Kaunas Lithuania LT-52119 + US + +00-1B-C5 (hex) Gill Instruments Ltd +0C5000-0C5FFF (base 16) Gill Instruments Ltd + Saltmarsh Park + Lymington Hampshire SO41 9EG + GB + +00-1B-C5 (hex) Connode +0C6000-0C6FFF (base 16) Connode + Järnvägsgatan 10 PO Box 1094 + Sundbyberg 17222 + SE + +00-1B-C5 (hex) NT MICROSYSTEMS +0BA000-0BAFFF (base 16) NT MICROSYSTEMS + Midori-ku + Yokohama Kanagawa 2260017 + JP + +00-1B-C5 (hex) Bridge Diagnostics, Inc. +0BD000-0BDFFF (base 16) Bridge Diagnostics, Inc. + 1995 57th Court N.Ste 100 + Boulder Co 80301 + US + +00-1B-C5 (hex) Tierra Japan Co.,Ltd +0AD000-0ADFFF (base 16) Tierra Japan Co.,Ltd + Cosmos Mansion 201 + Shinjuku-ku Tokyo 169-0072 + JP + +00-1B-C5 (hex) Enerwise Solutions Ltd. +0AF000-0AFFFF (base 16) Enerwise Solutions Ltd. + Flat/Room 510, 5/F Wayson,Comm Building + + HK + +00-1B-C5 (hex) Elektrometal SA +0A9000-0A9FFF (base 16) Elektrometal SA + Stawowa 71 + Cieszyn Slaskie 43-400 + PL + +00-1B-C5 (hex) L.G.L. Electronics S.p.a. +0A7000-0A7FFF (base 16) L.G.L. Electronics S.p.a. + Via Ugo Foscolo, 156 + Gandino Bergamo 24024 + IT + +00-1B-C5 (hex) Link Precision +0A8000-0A8FFF (base 16) Link Precision + Rua Lauro Linhares, 589 + Florianópolis SC 88036001 + BR + +00-1B-C5 (hex) AVnu Alliance +0AC000-0ACFFF (base 16) AVnu Alliance + 3855 SW 153rd Drive + Beaverton Oregon 97003 + US + +00-1B-C5 (hex) Tesla Controls +0A5000-0A5FFF (base 16) Tesla Controls + 8400 Miramar Road + San Diego CA 92126 + US + +00-1B-C5 (hex) RADMOR S.A. +0A4000-0A4FFF (base 16) RADMOR S.A. + HUTNICZA 3 + GDYNIA Pomorskie 81-212 + PL + +00-1B-C5 (hex) K+K Messtechnik GmbH +09E000-09EFFF (base 16) K+K Messtechnik GmbH + St.-Wendel-Str. 12 + Braunschweig Niedersachsen 38116 + DE + +00-1B-C5 (hex) YIK Corporation +09B000-09BFFF (base 16) YIK Corporation + B-4F,Pangyo Silicon Park 613 + seongnam-si Gyeonggi-do 463-400 + KR + +00-1B-C5 (hex) Plexstar Inc. +097000-097FFF (base 16) Plexstar Inc. + 209 S H 121 Bypass, STE 35 + Lewisville TX 75067 + US + +00-1B-C5 (hex) 3green ApS +091000-091FFF (base 16) 3green ApS + Tinghaven 5 + Vodskov 9000 + DK + +00-1B-C5 (hex) Seven Solutions S.L +090000-090FFF (base 16) Seven Solutions S.L + C/Baza, parcela 19, + Peligros Granada 18210 + ES + +00-1B-C5 (hex) CAST Group of Companies Inc. +086000-086FFF (base 16) CAST Group of Companies Inc. + 35 Ripley Ave. + Toronto Ontario M6S3P2 + CA + +00-1B-C5 (hex) Applied Innovations Research LLC +084000-084FFF (base 16) Applied Innovations Research LLC + 21265 Radisson Road + Shorewood MN 55331-9191 + US + +00-1B-C5 (hex) QCORE Medical +07B000-07BFFF (base 16) QCORE Medical + 14 Hamefalsim St + Petach Tikva Israel 49130 + IL + +00-1B-C5 (hex) Servicios Electronicos Industriales Berbel s.l. +07A000-07AFFF (base 16) Servicios Electronicos Industriales Berbel s.l. + Calle San Jose N + PINTO MADRID 28320 + ES + +00-1B-C5 (hex) Donbass Soft Ltd and Co.KG +078000-078FFF (base 16) Donbass Soft Ltd and Co.KG + Im Gewerbepark C25 + Regensburg Bavaria 93059 + DE + +00-1B-C5 (hex) PLAiR Media, Inc +076000-076FFF (base 16) PLAiR Media, Inc + 2901 Tasman Dr. + Santa Clara California 95054 + US + +00-1B-C5 (hex) IST GmbH +06A000-06AFFF (base 16) IST GmbH + Peter-Henlein-Str. 11 + Guenzburg 86312 + DE + +00-1B-C5 (hex) Manufacturas y transformados AB +066000-066FFF (base 16) Manufacturas y transformados AB + Sant Antoni de Baix 110-112 + Igualada Barcelona 08700 + ES + +00-1B-C5 (hex) Metrycom Communications Ltd +053000-053FFF (base 16) Metrycom Communications Ltd + 2 Koifman st. + Tel Aviv 68012 + IL + +00-1B-C5 (hex) Engineering Center ENERGOSERVICE +052000-052FFF (base 16) Engineering Center ENERGOSERVICE + 26 Kotlasskaya str. + Arkhangelsk 163046 + RU + +00-1B-C5 (hex) INPIXAL +059000-059FFF (base 16) INPIXAL + 80 Avenue des Buttes de Coesmes + RENNES BRETAGNE 35700 + FR + +00-1B-C5 (hex) ThinKom Solutions, Inc +056000-056FFF (base 16) ThinKom Solutions, Inc + 20000 Mariner Ave + Torrance CA 90503 + US + +00-1B-C5 (hex) TeliSwitch Solutions +050000-050FFF (base 16) TeliSwitch Solutions + 7 Hatochna st. + Kfar Saba 44641 + IL + +00-1B-C5 (hex) eiraku electric corp. +04D000-04DFFF (base 16) eiraku electric corp. + osaki 1-19-1 + tokyo shinagawa 141-0032 + JP + +00-1B-C5 (hex) ZAO "RADIUS Avtomatika" +044000-044FFF (base 16) ZAO "RADIUS Avtomatika" + Panfilovskiy prospekt, 10/3 + Zelenograd Moscow 124489 + RU + +00-1B-C5 (hex) XPossible Technologies Pte Ltd +048000-048FFF (base 16) XPossible Technologies Pte Ltd + 105 Tampines Road + 535127 + SG + +00-1B-C5 (hex) Coincident, Inc. +043000-043FFF (base 16) Coincident, Inc. + 337 Summer Street + Boston MA 02210 + US + +00-1B-C5 (hex) MindMade Sp. z o.o. +03A000-03AFFF (base 16) MindMade Sp. z o.o. + Sniadeckich 10 + Warsaw 00-656 + PL + +00-1B-C5 (hex) BETTINI SRL +02E000-02EFFF (base 16) BETTINI SRL + VIA CESARE BATTISTI 22 + CESANO MADERNO MILAN 20031 + IT + +00-1B-C5 (hex) Simavita Pty Ltd +00F000-00FFFF (base 16) Simavita Pty Ltd + 492 St Kilda Road + Melbourne Victoria 3004 + AU + +00-1B-C5 (hex) Converging Systems Inc. +000000-000FFF (base 16) Converging Systems Inc. + 32420 Nautilus Drive + Rancho Palos Verdes CA 90275 + US + +00-1B-C5 (hex) GORAMO - Janusz Gorecki +002000-002FFF (base 16) GORAMO - Janusz Gorecki + ul. Szancowa 82 + PL 01-458 + PL + +00-1B-C5 (hex) Dalaj Electro-Telecom +008000-008FFF (base 16) Dalaj Electro-Telecom + 1st Floor, Confidence Insurance Building + Akure Ondo 2341 + NG + +70-B3-D5 (hex) Tempris GmbH +539000-539FFF (base 16) Tempris GmbH + Industriestr. 7 + Holzkirchen 83607 + DE + +70-B3-D5 (hex) RCH ITALIA SPA +057000-057FFF (base 16) RCH ITALIA SPA + VIA CENDON 39 + SILEA TREVISO 31057 + IT + +70-B3-D5 (hex) ELA INNOVATION +C76000-C76FFF (base 16) ELA INNOVATION + 297 RUE MAURICE BEJART + MONTPELLIER 34080 + FR + +70-B3-D5 (hex) AB PRECISION (POOLE) LTD +064000-064FFF (base 16) AB PRECISION (POOLE) LTD + 1 FLEETS LANE + POOLE DORSET BH15 3BZ + GB + +70-B3-D5 (hex) Schneider Electric Motion USA +ACC000-ACCFFF (base 16) Schneider Electric Motion USA + 370 N. Main St. + Marlborough CT 06447 + US + +70-B3-D5 (hex) NIDEC LEROY-SOMER +780000-780FFF (base 16) NIDEC LEROY-SOMER + Boulevard Marcellin Leroy zone industriel angoulême + Angoulême 16800 + FR + +70-B3-D5 (hex) ARROW (CHINA) ELECTRONICS TRADING CO., LTD. +6AB000-6ABFFF (base 16) ARROW (CHINA) ELECTRONICS TRADING CO., LTD. + Floor 28, taikang financial building, building 1, yard 38, dongsanhuan north road, chaoyang district, Beijing + beijing beijing 100033 + CN + +70-B3-D5 (hex) Shenzhen Chanslink Network Technology Co., Ltd +49D000-49DFFF (base 16) Shenzhen Chanslink Network Technology Co., Ltd + Room 432, Block A,CMEC Plaza, Buji Road 1028 + Shenzhen Guangdong 518001 + CN + +70-B3-D5 (hex) Aloxy +7BB000-7BBFFF (base 16) Aloxy + Sint-Pietersvliet 7 + Antwerp 2000 + BE + +70-B3-D5 (hex) Umweltanalytik Holbach GmbH +DD6000-DD6FFF (base 16) Umweltanalytik Holbach GmbH + Sperberweg 3 + Wadern 66687 + DE + +70-B3-D5 (hex) Azmoon Keifiat +41D000-41DFFF (base 16) Azmoon Keifiat + #3,19th Alley,Gandi Ave,Tehran + Tehran Tehran 1517865314 + IR + +70-B3-D5 (hex) Becton Dickinson +6B9000-6B9FFF (base 16) Becton Dickinson + 7 Loveton Circle + Sparks MD 21152 + US + +70-B3-D5 (hex) Changzhou Rapid Information Technology Co,Ltd +E80000-E80FFF (base 16) Changzhou Rapid Information Technology Co,Ltd + Sanjing World Tech Park,3rd Floor,Bld NO3 NO.18huashan Road + Changzhou Jiangsu 213001 + CN + +70-B3-D5 (hex) SC3 Automation +EE9000-EE9FFF (base 16) SC3 Automation + 790 Principale Ouest + Magog Quebec J1X2B3 + CA + +70-B3-D5 (hex) Navaero Avionics AB +045000-045FFF (base 16) Navaero Avionics AB + Forradsgatan 4 + Sundsvall Vasternorrland 85633 + SE + +70-B3-D5 (hex) ResIOT UBLSOFTWARE SRL +DD4000-DD4FFF (base 16) ResIOT UBLSOFTWARE SRL + Ripa di Porta Ticinese, 39 + Milano Mi 20143 + IT + +70-B3-D5 (hex) AZ-TECHNOLOGY SDN BHD +C69000-C69FFF (base 16) AZ-TECHNOLOGY SDN BHD + A108 & A109 BLOCK A KELANA BUSINESS CENTRE NO: 97 JALAN SS7/2 KELANA JAYA + PETALING JAYA SELANGOR 47301 + MY + +70-B3-D5 (hex) GTI Technologies Inc +B5A000-B5AFFF (base 16) GTI Technologies Inc + 12707 High Bluff Dr, ste 200 + San Diego CA 92130 + US + +70-B3-D5 (hex) JSC «SATIS-TL-94» +CB9000-CB9FFF (base 16) JSC «SATIS-TL-94» + 1, bld.2, Timiryazevskaya str. + Moscow 127422 + RU + +70-B3-D5 (hex) Dynics +B5E000-B5EFFF (base 16) Dynics + 620 Technology Drive + Ann Arbor MI 48108 + US + +70-B3-D5 (hex) OOO Research and Production Center Computer Technologies +F3A000-F3AFFF (base 16) OOO Research and Production Center Computer Technologies + Komsomolsky avenue, 90-17 + Perm Perm Region 614010 + RU + +70-B3-D5 (hex) Icon Industrial Engineering +662000-662FFF (base 16) Icon Industrial Engineering + Radio street, 24/2, office 101 + Moscow Moscow 105005 + RU + +70-B3-D5 (hex) Contec Americas Inc. +392000-392FFF (base 16) Contec Americas Inc. + 3991 Sarno Rd + Melbourne FL 32934 + US + +70-B3-D5 (hex) Contec Americas Inc. +D10000-D10FFF (base 16) Contec Americas Inc. + 3991 Sarno Rd + Melbourne FL 32934 + US + +70-B3-D5 (hex) Contec Americas Inc. +8B7000-8B7FFF (base 16) Contec Americas Inc. + 3991 Sarno Rd + Melbourne FL 32934 + US + +70-B3-D5 (hex) NCE Network Consulting Engineering srl +834000-834FFF (base 16) NCE Network Consulting Engineering srl + via Novaluce 42 + Tremestieri Etneo Catania 95030 + IT + +70-B3-D5 (hex) Mitsubishi Electric India Pvt. Ltd. +797000-797FFF (base 16) Mitsubishi Electric India Pvt. Ltd. + EL3, J BLOCK, M.I.D.C. Bhosari + PUNE Maharastra 411027 + IN + +70-B3-D5 (hex) Shanghai Brellet Telecommunication Technology Co., Ltd. +9AF000-9AFFFF (base 16) Shanghai Brellet Telecommunication Technology Co., Ltd. + Building 2, No.5555, Shenzhuan Road, Songjiang District + Shanghai 201619 + CN + +70-B3-D5 (hex) e-Matix Corporation +89D000-89DFFF (base 16) e-Matix Corporation + 5812 Machine Drive + Huntington Beach CA 92649 + US + +70-B3-D5 (hex) Guangdong Centnet Technology Co.,Ltd +06A000-06AFFF (base 16) Guangdong Centnet Technology Co.,Ltd + Room403/410, 2nd Building, No 4 South of Industrial Rd, Songshan Lake industrial Park, + Dongguan Guangdong 523808 + CN + +00-1B-C5 (hex) Evondos Oy +0AB000-0ABFFF (base 16) Evondos Oy + Salorankatu 5-7 + Salo 24240 + FI + +70-B3-D5 (hex) Yuksek Kapasite Radyolink Sistemleri San. ve Tic. A.S. +B9F000-B9FFFF (base 16) Yuksek Kapasite Radyolink Sistemleri San. ve Tic. A.S. + Ikitelli Osb Mah., TU Ikitelli Teknopark Sok. 1/Z18 + Istanbul Basaksehir 34490 + TR + +70-B3-D5 (hex) Talleres de Escoriaza SA +26A000-26AFFF (base 16) Talleres de Escoriaza SA + Barrio Ventas, 35 + Irun Gipuzkoa 20305 + ES + +70-B3-D5 (hex) OOO Research and Production Center Computer Technologies +843000-843FFF (base 16) OOO Research and Production Center Computer Technologies + Komsomolsky avenue, 90-17 + Perm Perm Region 614010 + RU + +70-B3-D5 (hex) Mettler Toledo +BB2000-BB2FFF (base 16) Mettler Toledo + 1571 Northpointe Parkway + Lutz FL 33558 + US + +70-B3-D5 (hex) Mettler Toledo +27E000-27EFFF (base 16) Mettler Toledo + 1571 Northpointe Parkway + Lutz FL 33558 + US + +70-B3-D5 (hex) S.E.I. CO.,LTD. +12D000-12DFFF (base 16) S.E.I. CO.,LTD. + 59 Nirayama Tada + Izunokuni Shizuoka 4102133 + JP + +70-B3-D5 (hex) Code Blue Corporation +74B000-74BFFF (base 16) Code Blue Corporation + 259 Hedcor St. + Holland MI 49423 + US + +70-B3-D5 (hex) Hangzhou Weimu Technology Co,.Ltd. +6AE000-6AEFFF (base 16) Hangzhou Weimu Technology Co,.Ltd. + 3 / f, building 1, yongle village, cangqian street, yuhang district + Hangzhou Zhejiang 310000 + CN + +70-B3-D5 (hex) Semacon Business Machines +5DF000-5DFFFF (base 16) Semacon Business Machines + 7430 Trade Street + San Diego CA 92121 + US + +70-B3-D5 (hex) CT Company +50D000-50DFFF (base 16) CT Company + Godovikova , 9, Moscow + Moscow RUSSIA 129085 + RU + +70-B3-D5 (hex) Pure Air Filtration +0E7000-0E7FFF (base 16) Pure Air Filtration + 6050 peachtree Pkwy + Norcross GA 30092 + US + +70-B3-D5 (hex) DAVE SRL +CAF000-CAFFFF (base 16) DAVE SRL + VIA TALPONEDO 29/A + PORCIA PORDENONE 330850 + IT + +70-B3-D5 (hex) HighTechSystem Co.,Ltd. +F53000-F53FFF (base 16) HighTechSystem Co.,Ltd. + 1-16-7 Matsunami + Yamagata-shi Yamagata 990-0023 + JP + +70-B3-D5 (hex) Trident Systems Inc +951000-951FFF (base 16) Trident Systems Inc + 10201 Fairfax Blvd Suite 300 + Fairfax VA 22030 + US + +70-B3-D5 (hex) Hangzhou landesker digital technology co. LTD +50C000-50CFFF (base 16) Hangzhou landesker digital technology co. LTD + Gudun road Youpanshidai Center + Hangzhou Zhejiang 310030 + CN + +70-B3-D5 (hex) Aug. Winkhaus GmbH & Co. KG +0C3000-0C3FFF (base 16) Aug. Winkhaus GmbH & Co. KG + August-Winkhaus-Straße 31 + Telgte NRW 48291 + DE + +70-B3-D5 (hex) SMART IN OVATION GmbH +A3D000-A3DFFF (base 16) SMART IN OVATION GmbH + Meitnerstraße 10 + Stuttgart 70563 + DE + +70-B3-D5 (hex) PTS Technologies Pte Ltd +CA5000-CA5FFF (base 16) PTS Technologies Pte Ltd + BLk 2, Kaki Bukit Ave 1 , #04-05 + Singapore 417938 + SG + +70-B3-D5 (hex) HGL Dynamics Ltd +021000-021FFF (base 16) HGL Dynamics Ltd + Hamilton Barr House, Bridge Mews + Godalming Surrey GU7 1HZ + GB + +70-B3-D5 (hex) Cognosos, Inc. +BE0000-BE0FFF (base 16) Cognosos, Inc. + 1100 Spring St. NW, Suite 300A + Atlanta GA 30309 + US + +70-B3-D5 (hex) OOO Research and Production Center Computer Technologies +0F9000-0F9FFF (base 16) OOO Research and Production Center Computer Technologies + Komsomolsky avenue, 90-17 + Perm Perm Region 614010 + RU + +70-B3-D5 (hex) Nordmann International GmbH +9A4000-9A4FFF (base 16) Nordmann International GmbH + Huobstrasse 10 + Pfäffikon SZ 8808 + CH + +70-B3-D5 (hex) Orlaco Products B.V. +074000-074FFF (base 16) Orlaco Products B.V. + Albert Plesmanstraat 42 + Barneveld 3772MN + NL + +70-B3-D5 (hex) ACQUA-SYSTEMS srls +8F4000-8F4FFF (base 16) ACQUA-SYSTEMS srls + Via Italia 121 + Marnate Varese 21050 + IT + +70-B3-D5 (hex) ADMiTAS CCTV Taiwan Co. Ltd +0CC000-0CCFFF (base 16) ADMiTAS CCTV Taiwan Co. Ltd + 12F-3, No. 77 Xinpu 6th Street, Taoyuan District + Taoyuan 330 + TW + +70-B3-D5 (hex) PolyTech A/S +F4C000-F4CFFF (base 16) PolyTech A/S + HI Park 445 + Herning Herning 7400 + DK + +70-B3-D5 (hex) Zhuhai Lonl electric Co.,Ltd. +EA9000-EA9FFF (base 16) Zhuhai Lonl electric Co.,Ltd. + 2nd floor, building B3, nanfang software park, xiangzhou district + Zhuhai Guangdong 519000 + CN + +70-B3-D5 (hex) Shanghai Tiancheng Communication Technology Corporation +1C3000-1C3FFF (base 16) Shanghai Tiancheng Communication Technology Corporation + No.618,Guangxing Rd.,Songjiang + shanghai 200090 + CN + +70-B3-D5 (hex) SAMBO HITECH +282000-282FFF (base 16) SAMBO HITECH + 469,Seokjung-ro,Namdong-Gu + Incheon 21501 + KR + +70-B3-D5 (hex) M.A.C. Solutions (UK) Ltd +F9F000-F9FFFF (base 16) M.A.C. Solutions (UK) Ltd + Units 6-7 Kingfisher Business Park, Arthur Street + Redditch Worcestershire B98 8LG + GB + +70-B3-D5 (hex) ERA TOYS LIMITED +193000-193FFF (base 16) ERA TOYS LIMITED + Room 505, 5th Floor, Beverley Commercial Centre, 87-105 Chatham Road South + Tsim Sha Tsui Kowloon 0000 + HK + +70-B3-D5 (hex) T&M Media Pty Ltd +B41000-B41FFF (base 16) T&M Media Pty Ltd + 6, 476 Gardeners Road + Alexandria NSW 2015 + AU + +70-B3-D5 (hex) A&T Corporation +32E000-32EFFF (base 16) A&T Corporation + 2023-1 + Endo, Fujisawa, Kanagawa 252-0816 + JP + +70-B3-D5 (hex) Scorpion Precision Industry (HK)CO. Ltd. +02B000-02BFFF (base 16) Scorpion Precision Industry (HK)CO. Ltd. + 16th Floor, Excelsior Industrial Building,68-76 Sha Tsui Road, + Tsuen Wan New Territories 999077 + HK + +70-B3-D5 (hex) Shenzhen CAMERAY ELECTRONIC CO., LTD +1E2000-1E2FFF (base 16) Shenzhen CAMERAY ELECTRONIC CO., LTD + 4-5FL, Building 1, Guanghui Science, and Technology Park; Minqing Road, Longhua Town + shenzhen GD 518109 + CN + +70-B3-D5 (hex) Vulcan Wireless Inc. +E4D000-E4DFFF (base 16) Vulcan Wireless Inc. + 2218 Faraday Ave Suite 110 + Carlsbad CA 92008 + US + +70-B3-D5 (hex) MIVO Technology AB +1D5000-1D5FFF (base 16) MIVO Technology AB + Hornsbergsvägen 28 + Stockholm 11215 + SE + +70-B3-D5 (hex) Cryptotronix LLC +0DB000-0DBFFF (base 16) Cryptotronix LLC + P.O. Box 273029 + Fort Collins CO 80525 + US + +70-B3-D5 (hex) TOMEI TSUSHIN KOGYO CO,.LTD +FB1000-FB1FFF (base 16) TOMEI TSUSHIN KOGYO CO,.LTD + 100-3, Amaike Kodacho + Inazawa Shi Aichi ken 4928274 + JP + +70-B3-D5 (hex) RCH Vietnam Limited Liability Company +C09000-C09FFF (base 16) RCH Vietnam Limited Liability Company + Workshop F.01B-2, Lot No. F.01B Long Hau + Ho Chi Minh City Ho Chi Minh 70000 + VN + +70-B3-D5 (hex) Copper Labs, Inc. +F69000-F69FFF (base 16) Copper Labs, Inc. + 3015 Sterling Circle #200 + Boulder CO 80301 + US + +70-B3-D5 (hex) DogWatch Inc +1E7000-1E7FFF (base 16) DogWatch Inc + 10 Michigan Drive + Natick 01760 + US + +70-B3-D5 (hex) Grossenbacher Systeme AG +B75000-B75FFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) ITsynergy Ltd +D2A000-D2AFFF (base 16) ITsynergy Ltd + 9 Bonhill Street + London EC2A 4DJ + GB + +70-B3-D5 (hex) SHENZHEN HUINENGYUAN Technology Co., Ltd +A83000-A83FFF (base 16) SHENZHEN HUINENGYUAN Technology Co., Ltd + Room 206, 3 Building, Hongwanchuangke Center, Gushu, Xixiang, Baoan District + Shenzhen Guangdong 518126 + CN + +70-B3-D5 (hex) Vars Technology +C94000-C94FFF (base 16) Vars Technology + Squires gate industrial estate Unit 14 + Blackpool lancashire FY4 3RN + GB + +70-B3-D5 (hex) Burk Technology +641000-641FFF (base 16) Burk Technology + 7 Beaver Brook road + Littleton MA 01460 + US + +70-B3-D5 (hex) Inventeq B.V. +529000-529FFF (base 16) Inventeq B.V. + Ravenlaan 27 + Blaricum 1261WT + NL + +70-B3-D5 (hex) Vaunix Technology Corporation +EE6000-EE6FFF (base 16) Vaunix Technology Corporation + 7 New Pasture Rd + Newburyport MA 01950 + US + +70-B3-D5 (hex) Portrait Displays, Inc. +D77000-D77FFF (base 16) Portrait Displays, Inc. + 6663 OWENS DR + PLEASANTON CA 94588 + US + +70-B3-D5 (hex) chargeBIG +869000-869FFF (base 16) chargeBIG + Pragstraße 26-46 + Stuttgart 70376 + DE + +70-B3-D5 (hex) Tricom Research Inc. +601000-601FFF (base 16) Tricom Research Inc. + 17791 Sky Park Circle Suite GHJ + Irvine CA 92614 + US + +70-B3-D5 (hex) DISMUNTEL SAL +92C000-92CFFF (base 16) DISMUNTEL SAL + Pol ind cotes + Algemesi Valencia 46680 + ES + +70-B3-D5 (hex) Chengdu Lingya Technology Co., Ltd. +F4B000-F4BFFF (base 16) Chengdu Lingya Technology Co., Ltd. + 8 Floor, Block A, West City International Phase II, 48 Shuxi Road, Jinniu District + Chengdu Sichuan 610037 + CN + +70-B3-D5 (hex) xmi systems +A6B000-A6BFFF (base 16) xmi systems + Sonnenbergstrasse 7 + Hergiswil 6052 + CH + +70-B3-D5 (hex) Tecsag Innovation AG +77A000-77AFFF (base 16) Tecsag Innovation AG + Verenastrasse 4b + Wollerau 8832 + CH + +70-B3-D5 (hex) Controles S.A. +A6C000-A6CFFF (base 16) Controles S.A. + Rivera 3314 + Montevideo Montevideo 11300 + UY + +70-B3-D5 (hex) Vishay Nobel AB +BFC000-BFCFFF (base 16) Vishay Nobel AB + Box 423 + Karlskoga SE-691 27 + SE + +70-B3-D5 (hex) Hyannis Port Research +FB8000-FB8FFF (base 16) Hyannis Port Research + 75 2nd Ave, Suite 210 + Needham MA 02494 + US + +70-B3-D5 (hex) Henschel-Robotics GmbH +8C7000-8C7FFF (base 16) Henschel-Robotics GmbH + Mulchlingerstrasse, 67 + Winterthur Zuerich 8405 + CH + +70-B3-D5 (hex) Linc Technology Corporation dba Data-Linc Group +C84000-C84FFF (base 16) Linc Technology Corporation dba Data-Linc Group + 1125 12th Ave NW # B-2 + Issaquah WA 98027 + US + +70-B3-D5 (hex) Green Instruments A/S +79F000-79FFFF (base 16) Green Instruments A/S + Erhvervsparken 29 + Broenderslev 9700 + DK + +70-B3-D5 (hex) Solace Systems Inc. +D31000-D31FFF (base 16) Solace Systems Inc. + 535 Legget Drive, + Kanata Ontario K2K3B8 + CA + +70-B3-D5 (hex) Den Automation +787000-787FFF (base 16) Den Automation + Unit 6.05, Metropolitan Wharf + London E1W 3SS + GB + +70-B3-D5 (hex) Airthings +2A0000-2A0FFF (base 16) Airthings + Wergelandsveien 7 + Oslo 0167 + NO + +70-B3-D5 (hex) Micatu +67A000-67AFFF (base 16) Micatu + 315 Daniel Zenker Drive + Horseheads NY 14845 + US + +70-B3-D5 (hex) Potter Electric Signal Co. LLC +832000-832FFF (base 16) Potter Electric Signal Co. LLC + 1609 Park 370 Place + Hazelwood MO 63042 + US + +70-B3-D5 (hex) Mutelcor GmbH +170000-170FFF (base 16) Mutelcor GmbH + An der Bastei, 42A + Duisburg NRW 47259 + DE + +70-B3-D5 (hex) Wuhan Xingtuxinke ELectronic Co.,Ltd +CDB000-CDBFFF (base 16) Wuhan Xingtuxinke ELectronic Co.,Ltd + NO.C3-8F,Software Park,Optics Valley,East Lake Development Zone,Wuhan,Hubei,China + Wuhan Hubei 430074 + CN + +70-B3-D5 (hex) WTE Limited +C8A000-C8AFFF (base 16) WTE Limited + 1 Pukeko Place, Southshore + Christchurch Canterbury 8062 + NZ + +70-B3-D5 (hex) SHS SRL +BD0000-BD0FFF (base 16) SHS SRL + Via Ponte di Sirico,48 + SAVIANO NAPLES 80039 + IT + +70-B3-D5 (hex) Sadel S.p.A. +A74000-A74FFF (base 16) Sadel S.p.A. + via Marino Serenari, 1 + Castel Maggiore Bologna 40013 + IT + +70-B3-D5 (hex) HORIBA ABX SAS +B00000-B00FFF (base 16) HORIBA ABX SAS + rue du caducee + Montpellier Herault 34000 + FR + +70-B3-D5 (hex) VITEC +F17000-F17FFF (base 16) VITEC + 99 rue pierre sémard + Chatillon France 92320 + FR + +70-B3-D5 (hex) VITEC +CDA000-CDAFFF (base 16) VITEC + 99 rue pierre sémard + Chatillon France 92320 + FR + +70-B3-D5 (hex) Potomac Electric Corporation +E63000-E63FFF (base 16) Potomac Electric Corporation + One Westinghouse Plaza + Boston MA 02136 + US + +70-B3-D5 (hex) Bintel AB +970000-970FFF (base 16) Bintel AB + Mobilvägen 10 + Lund Skåne 22362 + SE + +70-B3-D5 (hex) HEITEC AG +F48000-F48FFF (base 16) HEITEC AG + Dr.-Otto-Leich-Str. 16 + Eckental Bavaria 90542 + DE + +70-B3-D5 (hex) Simpulse +DED000-DEDFFF (base 16) Simpulse + 7 rue de la croix Martre + Palaiseau 91120 + FR + +70-B3-D5 (hex) Season Electronics Ltd +65E000-65EFFF (base 16) Season Electronics Ltd + 600 Nest Business Park + Havant Hampshire PO9 5TL + GB + +70-B3-D5 (hex) ATGS +726000-726FFF (base 16) ATGS + 11 POLBINA ST. + MOSCOW 109388 + RU + +70-B3-D5 (hex) GlooVir Inc. +47A000-47AFFF (base 16) GlooVir Inc. + #413, 96 Gajeongbuk-Ro + Daejeon Yuseong 34111 + KR + +70-B3-D5 (hex) SIPRO s.r.l. +398000-398FFF (base 16) SIPRO s.r.l. + VIALE DELL'INDUSTRIA, 7 + VERONA VERONA 37135 + IT + +70-B3-D5 (hex) Profcon AB +496000-496FFF (base 16) Profcon AB + Victor Hasselblads gata 9 + Västra Frölunda 42131 + SE + +70-B3-D5 (hex) Private +580000-580FFF (base 16) Private + +70-B3-D5 (hex) Technological Application and Production One Member Liability Company (Tecapro company) +456000-456FFF (base 16) Technological Application and Production One Member Liability Company (Tecapro company) + 18A Cong Hoa street + Ho Chi Minh city Ho Chi Minh city 700000 + VN + +70-B3-D5 (hex) KRONOTECH SRL +D56000-D56FFF (base 16) KRONOTECH SRL + VIALE UNGHERIA 125 + UDINE ITALY/UDINE 33100 + IT + +70-B3-D5 (hex) LG Electronics +884000-884FFF (base 16) LG Electronics + 19, Yangje-daero 11gil, Seocho-gu + Seoul 06772 + KR + +70-B3-D5 (hex) RITEC +AC0000-AC0FFF (base 16) RITEC + 25 East Easy St + Simi Valley CA 93065 + US + +70-B3-D5 (hex) Carlo Gavazzi Industri +EFF000-EFFFFF (base 16) Carlo Gavazzi Industri + Over Hadstenvej 40 + Hadsten Denmark 8370 + DK + +70-B3-D5 (hex) GJD Manufacturing +E25000-E25FFF (base 16) GJD Manufacturing + Unit 2, Birch Business Park, Whittle Lane + Heywood OL10 2SX + GB + +70-B3-D5 (hex) INFRASAFE/ ADVANTOR SYSTEMS +5BA000-5BAFFF (base 16) INFRASAFE/ ADVANTOR SYSTEMS + 12612 CHALLENGER PARKWAY + ORLANDO FL 32826 + US + +70-B3-D5 (hex) DORLET SAU +8DF000-8DFFFF (base 16) DORLET SAU + Albert Eistein 34 + Alava SPAIN 01510 + ES + +70-B3-D5 (hex) Yite technology +BC9000-BC9FFF (base 16) Yite technology + No. 56, Xiaobei Rd., North Dist + Tainan 70448 + TW + +70-B3-D5 (hex) Xiris Automation Inc. +9BF000-9BFFFF (base 16) Xiris Automation Inc. + 1016 Sutton Dr, Unit C5 + Burlington Ontario L7L 6B8 + CA + +70-B3-D5 (hex) RCH ITALIA SPA +99B000-99BFFF (base 16) RCH ITALIA SPA + VIA CENDON 39 + SILEA TREVISO 31057 + IT + +70-B3-D5 (hex) Thruvision Limited +4FA000-4FAFFF (base 16) Thruvision Limited + 121 Olympic Avenue, Milton Park + Abingdon Oxfordshire OX14 4SA + GB + +70-B3-D5 (hex) DAVEY BICKFORD +1A4000-1A4FFF (base 16) DAVEY BICKFORD + CHEMIN DE LA PYROTECHNIE + HERY 89550 + FR + +70-B3-D5 (hex) QUERCUS TECHNOLOGIES, S.L. +40B000-40BFFF (base 16) QUERCUS TECHNOLOGIES, S.L. + Av. Onze de Setembre 19 + Reus Tarragona 43203 + ES + +70-B3-D5 (hex) KeyW Corporation +7CB000-7CBFFF (base 16) KeyW Corporation + 7763 Old Telegraph Road + Severn MD 21144 + US + +70-B3-D5 (hex) Transit Solutions, LLC. +019000-019FFF (base 16) Transit Solutions, LLC. + 114 West Grandview Avenue + Zelienople 16063 + US + +70-B3-D5 (hex) MULTIVOICE LLC +B06000-B06FFF (base 16) MULTIVOICE LLC + 224 S. Main St #401 + Springville UT 84660 + US + +70-B3-D5 (hex) AMS Controls, Inc. +444000-444FFF (base 16) AMS Controls, Inc. + 12180 Prichard Farm Road + Maryland Heights MO 63043 + US + +70-B3-D5 (hex) 3S - Sensors, Signal Processing, Systems GmbH +982000-982FFF (base 16) 3S - Sensors, Signal Processing, Systems GmbH + Saar-Lor-Lux-Straße 11 + Saarbrücken 66115 + DE + +70-B3-D5 (hex) Leonardo Sistemi Integrati S.r.l. +111000-111FFF (base 16) Leonardo Sistemi Integrati S.r.l. + Via Greto di Cornigliano, 6R + Genova 16152 + IT + +70-B3-D5 (hex) WoKa-Elektronik GmbH +8A9000-8A9FFF (base 16) WoKa-Elektronik GmbH + Fulder Tor 30 + Alsfeld Hessen 36304 + DE + +70-B3-D5 (hex) Jeaway CCTV Security Ltd,. +E00000-E00FFF (base 16) Jeaway CCTV Security Ltd,. + No. 24, Yifa St., Sanmin Dist. + Kaohsiung 807 + TW + +70-B3-D5 (hex) Flexsolution APS +C54000-C54FFF (base 16) Flexsolution APS + Østervangsvej 39 + Esbjerg N Jylland 6715 + DK + +70-B3-D5 (hex) Ametek Solidstate Controls +6DE000-6DEFFF (base 16) Ametek Solidstate Controls + 875 DEARBORN DR + COLUMBUS OH 43085-1586 + US + +70-B3-D5 (hex) Clean-Lasersysteme GmbH +C5F000-C5FFFF (base 16) Clean-Lasersysteme GmbH + Dornkaulstr. 6-8 + Herzogenrath NRW 52134 + DE + +70-B3-D5 (hex) Private +E2D000-E2DFFF (base 16) Private + +70-B3-D5 (hex) Altaneos +69A000-69AFFF (base 16) Altaneos + Chaussée Verte, 93B + Saint-Georges 4470 + BE + +70-B3-D5 (hex) EXARA Group +00C000-00CFFF (base 16) EXARA Group + Andropova pr. 18 1 + Moscow 115432 + RU + +70-B3-D5 (hex) TrexEdge, Inc. +0F2000-0F2FFF (base 16) TrexEdge, Inc. + 1-2-2 Osaki + Shinagawa Tokyo 1410032 + JP + +70-B3-D5 (hex) Zamir Recognition Systems Ltd. +46E000-46EFFF (base 16) Zamir Recognition Systems Ltd. + Manachat Tech Park 1/22 + Jerusalem 96951 + IL + +70-B3-D5 (hex) Preo Industries Far East Limited +CBD000-CBDFFF (base 16) Preo Industries Far East Limited + 31-39 Wo Tong Tsui Street + Hong Kong 999077 + HK + +70-B3-D5 (hex) Gluon Solutions Inc. +BA6000-BA6FFF (base 16) Gluon Solutions Inc. + 6951 Southfront Road + Livermore CA 94551 + US + +70-B3-D5 (hex) Bavaria Digital Technik GmbH +F1C000-F1CFFF (base 16) Bavaria Digital Technik GmbH + Rehbichler Weg 26 + Pfronten Bayern 87459 + DE + +70-B3-D5 (hex) Vectology,Inc +F50000-F50FFF (base 16) Vectology,Inc + UU bld 4F 2-5-2 Shinyokohama + Kouhoku-ku Yokohama Kanagawa 2220033 + JP + +70-B3-D5 (hex) U&R GmbH Hardware- und Systemdesign +BC5000-BC5FFF (base 16) U&R GmbH Hardware- und Systemdesign + In den Wiesen 2 + Erbach 89155 + DE + +70-B3-D5 (hex) VITEC +DD3000-DD3FFF (base 16) VITEC + 99, rue Pierre Semard + CHATILLON 92320 + FR + +70-B3-D5 (hex) Decentlab GmbH +7BA000-7BAFFF (base 16) Decentlab GmbH + Ueberlandstrasse 129 + Duebendorf 8600 + CH + +70-B3-D5 (hex) Loanguard T/A SE Controls +2FC000-2FCFFF (base 16) Loanguard T/A SE Controls + Wellington Crescent + Lichfield Staffordshire WS13 8RZ + GB + +70-B3-D5 (hex) Lupa Tecnologia e Sistemas Ltda +0ED000-0EDFFF (base 16) Lupa Tecnologia e Sistemas Ltda + Rua Viscondessa de Cavalcanti, 50 - Poço Rico + Juiz de Fora Minas Gerais 36020-070 + BR + +70-B3-D5 (hex) OBSERVER FOUNDATION +633000-633FFF (base 16) OBSERVER FOUNDATION + Narva mnt 5 + Tallinn city Harju county 10117 + EE + +70-B3-D5 (hex) tiga.eleven GmbH +FF2000-FF2FFF (base 16) tiga.eleven GmbH + Stallburggasse 2/37 + Viennna 1010 + AT + +70-B3-D5 (hex) GETRALINE +FD4000-FD4FFF (base 16) GETRALINE + 15 RUE D'ANGIVILLER + VERSAILLES 78000 + FR + +70-B3-D5 (hex) Beijing Huanyu Zhilian Science &Technology Co., Ltd. +DF5000-DF5FFF (base 16) Beijing Huanyu Zhilian Science &Technology Co., Ltd. + 2/F 202-030, Building 2, No. 1, Gaolizhang Road, Haidian District,Beijing + Beijing Beijing 100095 + CN + +70-B3-D5 (hex) Smart Controls LLC +199000-199FFF (base 16) Smart Controls LLC + 10000 St. Clair Ave. + Fairview Heights IL 62208 + US + +70-B3-D5 (hex) MAC Solutions (UK) Ltd +E6A000-E6AFFF (base 16) MAC Solutions (UK) Ltd + Units 6 & 7, Kingfisher Business Park, Arthur Street + Redditch Worcestershire B98 8LG + GB + +70-B3-D5 (hex) Microsoft Research +4AC000-4ACFFF (base 16) Microsoft Research + 1 Microsoft Way + Redmond WA 98052 + US + +70-B3-D5 (hex) THETA432 +E1F000-E1FFFF (base 16) THETA432 + 1730 E Holly Ave suite 805 + El Segundo CA 90245 + US + +70-B3-D5 (hex) Root Automation +6A2000-6A2FFF (base 16) Root Automation + 1916 Fort Jones Rd + Yreka CA 96097 + US + +70-B3-D5 (hex) DIEHL Connectivity Solutions +1F1000-1F1FFF (base 16) DIEHL Connectivity Solutions + Stephanstraße 49 + Nürnberg Bayern 90478 + DE + +70-B3-D5 (hex) SA Photonics +E17000-E17FFF (base 16) SA Photonics + 120 Knowles Drive + Los Gatos CA 95032 + US + +70-B3-D5 (hex) Elbit Systems of America +B7E000-B7EFFF (base 16) Elbit Systems of America + 4700 Marine Creek Parkway + Fort Worth TX 76179 + US + +70-B3-D5 (hex) SHENZHEN WITLINK CO.,LTD. +CF0000-CF0FFF (base 16) SHENZHEN WITLINK CO.,LTD. + 1211 Room,Satellite building,Southern Hi-Tech Zone,Nanshan District + ShenZhen Guangdong 518000 + CN + +70-B3-D5 (hex) ComNav Technology Ltd. +E3B000-E3BFFF (base 16) ComNav Technology Ltd. + Buliding 2,No. 618 Chengliu Middle Road + JiaDing District Shanghai 201801 + CN + +70-B3-D5 (hex) Pengo Technology Co., Ltd +DB7000-DB7FFF (base 16) Pengo Technology Co., Ltd + No. 13, Alley 7, Lane 533, Rongxing Road, Bade District + Taoyuan City 33463 + TW + +70-B3-D5 (hex) ifak technology + service GmbH +264000-264FFF (base 16) ifak technology + service GmbH + Ludwig-Erhard-Allee 10 + Karlsruhe 76131 + DE + +70-B3-D5 (hex) Edgeware AB +B6E000-B6EFFF (base 16) Edgeware AB + Master Samuelsgatan 42 + Stockholm 11157 + SE + +70-B3-D5 (hex) JNR Sports Holdings, LLC +3E7000-3E7FFF (base 16) JNR Sports Holdings, LLC + 656 NORTH RD + CANDIA NH 03034-2027 + US + +70-B3-D5 (hex) Elcoma +31F000-31FFFF (base 16) Elcoma + Rua Barbosa Lima, 149 + Recife Pernambuco 50030-330 + BR + +70-B3-D5 (hex) Wireless Systems Solutions LLC +F86000-F86FFF (base 16) Wireless Systems Solutions LLC + 630 Davis Drive Suite 250 + Morrisville NC 27560 + US + +70-B3-D5 (hex) Project H Pty Ltd +114000-114FFF (base 16) Project H Pty Ltd + 168 Abbotts Rd + Glen Innes NSW 2370 + AU + +70-B3-D5 (hex) HeadsafeIP PTY LTD +800000-800FFF (base 16) HeadsafeIP PTY LTD + 231 Birrell st + bronte nsw 2024 + AU + +70-B3-D5 (hex) Magnetek +C70000-C70FFF (base 16) Magnetek + N49W13650 Campbell Dr + Menomonee Falls WI 53051 + US + +70-B3-D5 (hex) 4Jtech s.r.o. +16A000-16AFFF (base 16) 4Jtech s.r.o. + Ringhofferova 115/1 + Prague Czech Republic 155 21 + CZ + +70-B3-D5 (hex) Capgemini Netherlands +0B5000-0B5FFF (base 16) Capgemini Netherlands + Reykjavikplein 1 + Utrecht 3543KA + NL + +70-B3-D5 (hex) Peloton Technology +43E000-43EFFF (base 16) Peloton Technology + 1060 La Avenida + Mountain View CA 94043 + US + +70-B3-D5 (hex) ATL-SD +B76000-B76FFF (base 16) ATL-SD + Ogawacho 1-1034-11 + Kodaira Tokyo 187-0032 + JP + +70-B3-D5 (hex) Motec Pty Ltd +71E000-71EFFF (base 16) Motec Pty Ltd + 121 Merrindale Drive + Croydon South Victoria 3136 + AU + +70-B3-D5 (hex) DORLET SAU +4F6000-4F6FFF (base 16) DORLET SAU + Albert Eistein 34 + Alava SPAIN 01510 + ES + +70-B3-D5 (hex) Ensotech Limited +C2D000-C2DFFF (base 16) Ensotech Limited + Unit F, 6 Floor, Cheung Hing Shing Centre, No.23 Sha Tsui Road + Tsuen Wan 0000 + HK + +70-B3-D5 (hex) Unmukti Technology Pvt Ltd +24A000-24AFFF (base 16) Unmukti Technology Pvt Ltd + 2/288, Vishwas Khand, Gomti Nagar + Lucknow Uttar Pradesh 226010 + IN + +70-B3-D5 (hex) Digital Instrument Transformers +54A000-54AFFF (base 16) Digital Instrument Transformers + 26 Bolshaya Vorobyovskaya, off 27 + Ivanovo 153000 + RU + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +1C9000-1C9FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 6 + Dinkelsbuehl Bavaria 91550 + DE + +70-B3-D5 (hex) Rhythm Engineering, LLC. +57A000-57AFFF (base 16) Rhythm Engineering, LLC. + 11228 Thompson Ave. + Lenexa KS 66219 + US + +70-B3-D5 (hex) LG Electronics +765000-765FFF (base 16) LG Electronics + LG Science Park, 10, Magokjungang 10-ro, GangSeo-gu + SEOUL 07796 + KR + +70-B3-D5 (hex) APG Cash Drawer, LLC +77D000-77DFFF (base 16) APG Cash Drawer, LLC + 5250 Industrial Blvd NE + Minneapolis MN 55421 + US + +70-B3-D5 (hex) AvMap srlu +048000-048FFF (base 16) AvMap srlu + Viale Zaccagna 6 + Carrara 54033 + IT + +70-B3-D5 (hex) Parkalot Denmark ApS +638000-638FFF (base 16) Parkalot Denmark ApS + Niels Jernes Vej 12 + Aalborg East 9220 + DK + +70-B3-D5 (hex) Insitu, Inc +DD2000-DD2FFF (base 16) Insitu, Inc + 118 E Columbia River Way + Bingen WA 98605 + US + +70-B3-D5 (hex) dds +F21000-F21FFF (base 16) dds + 606, Woolim Lions Valley 2Cha, 2, Gasan digital 1-ro Geumcheon-gu + Seoul 08591 + KR + +70-B3-D5 (hex) Kawasaki Robot Service,Ltd. +FEE000-FEEFFF (base 16) Kawasaki Robot Service,Ltd. + 2-1-9,Takatsukadai,Nishi-ku + Kobe Hyogo 651-2271 + JP + +70-B3-D5 (hex) WiSuite USA +19A000-19AFFF (base 16) WiSuite USA + 13201 Stephens Road Suite E + Warren MI 48089 + US + +70-B3-D5 (hex) Access Protocol Pty Ltd +686000-686FFF (base 16) Access Protocol Pty Ltd + 45 Sarich Court + Osborne Park Western Australia 6017 + AU + +70-B3-D5 (hex) COPPERNIC SAS +25F000-25FFFF (base 16) COPPERNIC SAS + 185 avenue Archimede + Aix en Provence 13857 + FR + +70-B3-D5 (hex) KST technology +8BB000-8BBFFF (base 16) KST technology + KST B/D 4-5, Wiryeseong-daero 12-gil + Songpa-gu Seoul 05636 + KR + +70-B3-D5 (hex) Voleatech GmbH +DA3000-DA3FFF (base 16) Voleatech GmbH + Grathwohlstr. 5 + Reutlingen 72762 + DE + +70-B3-D5 (hex) Leder Elektronik Design +22D000-22DFFF (base 16) Leder Elektronik Design + Bruchweg 10 + Ketsch Baden-Wuerttemberg 68775 + DE + +70-B3-D5 (hex) KDT +748000-748FFF (base 16) KDT + 126, Haeoreum-gil, Namsan-myeon + Chuncheon-si Gangwon-do 200-911 + KR + +70-B3-D5 (hex) SODAQ +ADC000-ADCFFF (base 16) SODAQ + Laapersveld 75 + Hilversum - 1213 VB + NL + +70-B3-D5 (hex) Behr Technologies Inc +C1F000-C1FFFF (base 16) Behr Technologies Inc + 10 York Mills Road, Suite 610 + Toronto Ontario M2P 2G4 + CA + +70-B3-D5 (hex) Communication Systems Solutions +7F9000-7F9FFF (base 16) Communication Systems Solutions + 6030 S 58th ST, STE C + Litcoln NE 68516 + US + +70-B3-D5 (hex) APG Cash Drawer, LLC +BCF000-BCFFFF (base 16) APG Cash Drawer, LLC + 5250 Industrial Blvd NE + Minneapolis MN 55421 + US + +70-B3-D5 (hex) ODAWARAKIKI AUTO-MACHINE MFG.CO.,LTD +F88000-F88FFF (base 16) ODAWARAKIKI AUTO-MACHINE MFG.CO.,LTD + 1-11-3 Nakacho + Odawara Kanagawa 250-0005 + JP + +70-B3-D5 (hex) Beijing HuaLian Technology Co, Ltd. +623000-623FFF (base 16) Beijing HuaLian Technology Co, Ltd. + Floor4 16C, north district of Ufida software park, No. 68 Beiqing road, HaiDian district. + Beijing Beijing 100094 + CN + +70-B3-D5 (hex) UR FOG S.R.L. +B8E000-B8EFFF (base 16) UR FOG S.R.L. + Via Toscana 38 + San Mauro Torinese TO 10099 + IT + +70-B3-D5 (hex) Samwell International Inc +A71000-A71FFF (base 16) Samwell International Inc + No. 317-1, Sec.2, An Kang Rd., Hsintien Dist + New Taipei City 231 + TW + +70-B3-D5 (hex) PEEK TRAFFIC +718000-718FFF (base 16) PEEK TRAFFIC + 5401 N SAM HOUSTON PKWY W + HOUSTON null 77086 + US + +70-B3-D5 (hex) EMAC, Inc. +679000-679FFF (base 16) EMAC, Inc. + 2390 EMAC Way + Carbondale IL 62901 + US + +70-B3-D5 (hex) EDFelectronics JRMM Sp z o.o. sp.k. +234000-234FFF (base 16) EDFelectronics JRMM Sp z o.o. sp.k. + Rybnicka 64 + Radlin 44-310 + PL + +70-B3-D5 (hex) winsun AG +F67000-F67FFF (base 16) winsun AG + Beeschi Mattenstrasse 2 + Steg Wallis 3940 + CH + +70-B3-D5 (hex) MI Inc. +6FC000-6FCFFF (base 16) MI Inc. + 6F, Toto building, 5-1-4, Toranomon, Minato-ku + Tokyo 1050001 + JP + +70-B3-D5 (hex) Orion Corporation +97A000-97AFFF (base 16) Orion Corporation + 2nd Fl., Shin-Showa No.5 Bldg., 1-5-15 Higashi-Sakata + Kimitsu Chiba 299-1144 + JP + +70-B3-D5 (hex) Rehwork GmbH +5A5000-5A5FFF (base 16) Rehwork GmbH + Ivo-Hauptmann-Ring 14 + Hamburg 22159 + DE + +70-B3-D5 (hex) Dynamic Perspective GmbH +2A8000-2A8FFF (base 16) Dynamic Perspective GmbH + Wehlistrasse 29/1/1 + Vienna 1200 + AT + +70-B3-D5 (hex) Compusign Systems Pty Ltd +050000-050FFF (base 16) Compusign Systems Pty Ltd + 8/10 Clarice Road + Box Hill Victoria 3128 + AU + +70-B3-D5 (hex) dA Tomato Limited +966000-966FFF (base 16) dA Tomato Limited + 8/2 Paribag, Hatirpool, Motaleb Tower, Tower 1, 11A + Dhaka DAC 1000 + BD + +70-B3-D5 (hex) PROEL TSI s.r.l. +5CF000-5CFFFF (base 16) PROEL TSI s.r.l. + VIA DIVISIONE JULIA, 10 + MANZANO UD 33044 + IT + +70-B3-D5 (hex) MiWave Consulting, LLC +0E1000-0E1FFF (base 16) MiWave Consulting, LLC + 1117 Paine Court + Raleigh NC 27609 + US + +70-B3-D5 (hex) Vibrationmaster +C35000-C35FFF (base 16) Vibrationmaster + Rue Du Commerce, Technoport 3A + FOETZ 3895 + LU + +70-B3-D5 (hex) BEIJING ZGH SECURITY RESEARCH INSTITUTE CO., LTD +6C3000-6C3FFF (base 16) BEIJING ZGH SECURITY RESEARCH INSTITUTE CO., LTD + Room 1407, Tianchen Plaza, Chaoyang District + BeiJing BeiJing 100020 + CN + +70-B3-D5 (hex) Private +66A000-66AFFF (base 16) Private + +70-B3-D5 (hex) Keepen +69C000-69CFFF (base 16) Keepen + 12, rue Anselme + Saint-Ouen 93400 + FR + +70-B3-D5 (hex) VEILUX INC. +CFC000-CFCFFF (base 16) VEILUX INC. + 802 GREENVIEW DR. STE 200 + GRAND PRAIRIE 75050 + US + +70-B3-D5 (hex) VEILUX INC. +58E000-58EFFF (base 16) VEILUX INC. + 802 GREENVIEW DR. STE 200 + GRAND PRAIRIE 75050 + US + +70-B3-D5 (hex) Wit.com Inc +434000-434FFF (base 16) Wit.com Inc + 1251 Park Ave + Emeryville CA 94608 + US + +70-B3-D5 (hex) ETA Technology Pvt Ltd +A94000-A94FFF (base 16) ETA Technology Pvt Ltd + No. 484-D, 13th Cross, IV Phase, Peenya Industrial Area, + Bangalore Karnataka 560058 + IN + +70-B3-D5 (hex) CRESPRIT INC. +C38000-C38FFF (base 16) CRESPRIT INC. + D-315 ,177, Jeongjail-ro, Bundang-gu + Seongnam-si 13557 + KR + +70-B3-D5 (hex) Robotic Research, LLC +EB4000-EB4FFF (base 16) Robotic Research, LLC + 555 Quince Orchard Rd, Suite 300 + Gaithersburg MD 20878 + US + +70-B3-D5 (hex) NINGBO CRRC TIMES TRANSDUCER TECHNOLOGY CO., LTD +907000-907FFF (base 16) NINGBO CRRC TIMES TRANSDUCER TECHNOLOGY CO., LTD + No.138 Zhenyong Road + Ningbo Zhejiang 315021 + CN + +70-B3-D5 (hex) ETA-USA +23F000-23FFFF (base 16) ETA-USA + 16170 Vineyard Blvd., #180 + Morgan Hill CA 95037 + US + +70-B3-D5 (hex) MyoungSung System +9B4000-9B4FFF (base 16) MyoungSung System + 205, Manhae-ro, Danwon-gu + Ansan Gyeonggi-do 15421 + KR + +70-B3-D5 (hex) RZB Rudolf Zimmermann, Bamberg GmbH +D71000-D71FFF (base 16) RZB Rudolf Zimmermann, Bamberg GmbH + Rheinstraße 16 + Bamberg Bavaria 96052 + DE + +70-B3-D5 (hex) Hagiwara Solutions Co., Ltd. +3C4000-3C4FFF (base 16) Hagiwara Solutions Co., Ltd. + 2-5-12 Nishiki, Naka-ku + Nagoya-shi Aichi-ken 460-0003 + JP + +70-B3-D5 (hex) MB connect line GmbH Fernwartungssysteme +B39000-B39FFF (base 16) MB connect line GmbH Fernwartungssysteme + Winnettener Straße 5 + Dinkelsbühl Bavaria 91550 + DE + +70-B3-D5 (hex) Sensefarm AB +546000-546FFF (base 16) Sensefarm AB + Mobilvagen 10 + Lund 22362 + SE + +70-B3-D5 (hex) ESPAI DE PRODUCCIÓ I ELECTRÓNI +162000-162FFF (base 16) ESPAI DE PRODUCCIÓ I ELECTRÓNI + C/Johannes Gutenberg, 4 y 6 + Paterna Valencia 46980 + ES + +70-B3-D5 (hex) machineQ +3E6000-3E6FFF (base 16) machineQ + 1900 market st + philadelphia PA 19103 + US + +70-B3-D5 (hex) shanghai qiaoqi zhinengkeji +ED0000-ED0FFF (base 16) shanghai qiaoqi zhinengkeji + building 34, lane 333, laifang road + shanghai 201615 + CN + +70-B3-D5 (hex) Alere Technologies AS +F52000-F52FFF (base 16) Alere Technologies AS + Kjelsaasveien 161 + Oslo Oslo 0382 + NO + +70-B3-D5 (hex) Advanced Ventilation Applications, Inc. +DEA000-DEAFFF (base 16) Advanced Ventilation Applications, Inc. + 2158 Gordon Ave. + Menlo Park CA 94025 + US + +70-B3-D5 (hex) HORIZON TELECOM +960000-960FFF (base 16) HORIZON TELECOM + 6 rue de GUEUGNON + MONTCEAU LES MINES 71300 + FR + +70-B3-D5 (hex) Metatronics B.V. +C7D000-C7DFFF (base 16) Metatronics B.V. + Torenallee 42-54 + Eindhoven 5617 BD + NL + +70-B3-D5 (hex) Fater Rasa Noor +5F1000-5F1FFF (base 16) Fater Rasa Noor + Damavand St. , Between Khaghani and Ayat station, Hadi Building, no.499, second floor + Tehran Tehran 0098 + IR + +70-B3-D5 (hex) Foxconn 4Tech +A46000-A46FFF (base 16) Foxconn 4Tech + U Zámečku 27 + Pardubice Česká republika 53003 + CZ + +70-B3-D5 (hex) ADVEEZ +7EE000-7EEFFF (base 16) ADVEEZ + 12 RUE MICHEL LABROUSSE, BATIMENT 6 + toulouse FRANCE 31100 + FR + +70-B3-D5 (hex) LGM Ingénierie +968000-968FFF (base 16) LGM Ingénierie + 13 avenue Morane Saulnier + Vélizy-Villacoublay 78140 + FR + +70-B3-D5 (hex) D.T.S Illuminazione Srl +D7C000-D7CFFF (base 16) D.T.S Illuminazione Srl + Via Fagnano Selve, 12 / 14 + Misano Adriatico Rimini 47843 + IT + +70-B3-D5 (hex) TATTILE SRL +EEF000-EEFFFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) GL TECH CO.,LTD +248000-248FFF (base 16) GL TECH CO.,LTD + No. Ten Changchun Road + ZHENGZHOU HENAN 455000 + CN + +70-B3-D5 (hex) ard sa +D6E000-D6EFFF (base 16) ard sa + Micropolis Bat Clematis + Gap France 05000 + FR + +70-B3-D5 (hex) Duerkopp-Adler +3C9000-3C9FFF (base 16) Duerkopp-Adler + Potsdamerstr. 190 + Bielefeld 33719 + DE + +70-B3-D5 (hex) Grossenbacher Systeme AG +6B7000-6B7FFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) RoboCore Tecnologia +0AC000-0ACFFF (base 16) RoboCore Tecnologia + Estrada das Lagrimas 1986 sala 22 + Sao Caetano do Sul SP 09580500 + BR + +70-B3-D5 (hex) DEA SYSTEM SPA +8FA000-8FAFFF (base 16) DEA SYSTEM SPA + VIA DELLA TECNICA 6 + PIOVENE ROCCHETTE VICENZA 36013 + IT + +70-B3-D5 (hex) Blue Marble Communications, Inc. +77E000-77EFFF (base 16) Blue Marble Communications, Inc. + 9520 Padgett St, Suite 101 + San Diego CA 92126 + US + +70-B3-D5 (hex) Enyx SA +21C000-21CFFF (base 16) Enyx SA + 8 rue greneta + Paris 75003 + FR + +70-B3-D5 (hex) SonoSound ApS +656000-656FFF (base 16) SonoSound ApS + Malov Byvej 229 + Malov Hovedstaden 2760 + DK + +70-B3-D5 (hex) Andasis Elektronik San. ve Tic. A.Ş. +D62000-D62FFF (base 16) Andasis Elektronik San. ve Tic. A.Ş. + Teknopark İstanbul, Sanayi Mah, Teknopark Bulvarı, No:1/1C 1206 Pendik/İstanbul + İstanbul 34906 + TR + +70-B3-D5 (hex) RFRain LLC +F5F000-F5FFFF (base 16) RFRain LLC + 8 THE GREEN SUITE 4510 + Dover DE 19901 + US + +70-B3-D5 (hex) UMAN +722000-722FFF (base 16) UMAN + Unit 12, Oxbow Crescent, Esturies, Century City + Cape Town Western Cape 7441 + ZA + +70-B3-D5 (hex) SLAT +920000-920FFF (base 16) SLAT + 11 Rue Jean-Elysée DUPUY + Champagne au Mont d'Or Rhône 69543 + FR + +70-B3-D5 (hex) Star Systems International +5EF000-5EFFFF (base 16) Star Systems International + Unit 04, 12/F Vanta Industrial Centre, 21-33 Tai Lin Pai Road + Kwai Chung 852 + HK + +70-B3-D5 (hex) CT Company +2D4000-2D4FFF (base 16) CT Company + Godovikova , 9, Moscow + Moscow RUSSIA 129085 + RU + +70-B3-D5 (hex) Brakels IT +54B000-54BFFF (base 16) Brakels IT + Veldboersweg 10a + Langeveen Overijssel 7679TL + NL + +70-B3-D5 (hex) GS Elektromedizinsiche Geräte G. Stemple GmbH +144000-144FFF (base 16) GS Elektromedizinsiche Geräte G. Stemple GmbH + Hauswiesenstr. 26 + Kaufering Bayern 86916 + DE + +70-B3-D5 (hex) Chengdu Cove Technology CO.,LTD +24E000-24EFFF (base 16) Chengdu Cove Technology CO.,LTD + 6-419, Hi-tech Incubation Park, No.1480 Tianfu Ave + Chengdu Sichuan 610000 + CN + +70-B3-D5 (hex) DORLET SAU +8E3000-8E3FFF (base 16) DORLET SAU + Albert Eistein 34 + Alava SPAIN 01510 + ES + +70-B3-D5 (hex) Cubitech +7D0000-7D0FFF (base 16) Cubitech + 4-6 Kiprou str + Tavros Athens 17778 + GR + +70-B3-D5 (hex) Hangzhou AwareTec Technology Co., Ltd +5DE000-5DEFFF (base 16) Hangzhou AwareTec Technology Co., Ltd + 6th Floor,Building 2,No.307 Liuhe Road,Binjiang District,Hangzhou 城市: Hangzhou + Hangzhou Zhejiang 310000 + CN + +70-B3-D5 (hex) TIAMA +BA3000-BA3FFF (base 16) TIAMA + ZA des Plattes - 1 Chemin des Plattes + VOURLES 69390 + FR + +00-1B-C5 (hex) Triax A/S +0BB000-0BBFFF (base 16) Triax A/S + Bjornkaervej 3 + Hornsyld Denmark 8783 + DK + +70-B3-D5 (hex) APP Engineering, Inc. +049000-049FFF (base 16) APP Engineering, Inc. + 5234 Elmwood Avenue + Indianapolis IN 46203 + US + +70-B3-D5 (hex) Shanghai YuanAn Environmental Protection Technology Co.,Ltd +6D8000-6D8FFF (base 16) Shanghai YuanAn Environmental Protection Technology Co.,Ltd + Rm213/225,Oriental Pearl European City,No 285 East luochuan Road + Shanghai Shanghai 200072 + CN + +70-B3-D5 (hex) Cardinal Health +75E000-75EFFF (base 16) Cardinal Health + 444 McDonnell Blvd. + Hazelwood MO 63042 + US + +70-B3-D5 (hex) Monnit Corporation +236000-236FFF (base 16) Monnit Corporation + 3400 S West Temple + Salt Lake City 84115 + US + +70-B3-D5 (hex) Melecs EWS GmbH +704000-704FFF (base 16) Melecs EWS GmbH + GZO-Technologiestrasse 1 + Siegendorf 7011 + AT + +70-B3-D5 (hex) Triton Electronics Ltd +7A5000-7A5FFF (base 16) Triton Electronics Ltd + Bigods Hall, Bigods Lane + DUNMOW Essex CM63BE + GB + +70-B3-D5 (hex) Lab241 Co.,Ltd. +21B000-21BFFF (base 16) Lab241 Co.,Ltd. + 25Dong 241Ho, 97, Siheung-daero, Geumcheon-gu + Seoul Seoul 08639 + KR + +70-B3-D5 (hex) Infodev Electronic Designers Intl. +DBF000-DBFFFF (base 16) Infodev Electronic Designers Intl. + 1995 rue Frank-Carrel Suite 202 + Quebec Quebec G1N4H9 + CA + +70-B3-D5 (hex) KWS-Electronic GmbH +EB3000-EB3FFF (base 16) KWS-Electronic GmbH + Sportplatzstrasse 1 + Grosskarolinenfeld D-83109 + DE + +70-B3-D5 (hex) Alere Technologies AS +2AE000-2AEFFF (base 16) Alere Technologies AS + Kjelsaasveien 161 + Oslo Oslo 0382 + NO + +70-B3-D5 (hex) Intesens +B17000-B17FFF (base 16) Intesens + 425 rue Jean Rostand + labege 31670 + FR + +70-B3-D5 (hex) Shanghai Holystar Information Technology Co.,Ltd +6E1000-6E1FFF (base 16) Shanghai Holystar Information Technology Co.,Ltd + 8F Building A3 NO.1528 Gumei Rd Shanghai China PR + shanghai 200233 + CN + +70-B3-D5 (hex) CSM MACHINERY srl +FE3000-FE3FFF (base 16) CSM MACHINERY srl + Via Cadore Mare, 25 + Cimetta di Codognè Treviso 31013 + IT + +70-B3-D5 (hex) Plantiga Technologies Inc +525000-525FFF (base 16) Plantiga Technologies Inc + 324-611 Alexander Street + Vancouver British Columbia V6A 1E1 + CA + +70-B3-D5 (hex) Renesas Electronics +340000-340FFF (base 16) Renesas Electronics + 2801 Scott Blvd + Santa Clara CA 95050 + US + +70-B3-D5 (hex) HGH SYSTEMES INFRAROUGES +853000-853FFF (base 16) HGH SYSTEMES INFRAROUGES + 10 Rue Maryse Bastié + Igny IDF 91430 + FR + +70-B3-D5 (hex) Grupo Epelsa S.L. +4E1000-4E1FFF (base 16) Grupo Epelsa S.L. + C/ Punto Net,3 + Alcala de Henares Madrid 28805 + ES + +70-B3-D5 (hex) KMtronic ltd +0AF000-0AFFFF (base 16) KMtronic ltd + Dobri Czintulov 28A str. + Gorna Oryahovica VT 5100 + BG + +70-B3-D5 (hex) FactoryLab B.V. +5DC000-5DCFFF (base 16) FactoryLab B.V. + Lindtsedijk 54 + Zwijndrecht Zuid Holland 3336LE + NL + +70-B3-D5 (hex) OLEDCOMM +A43000-A43FFF (base 16) OLEDCOMM + 10-12 avenue de l'Europe + Vélizy Villacoublay Ile de France 78140 + FR + +70-B3-D5 (hex) Peter Huber Kaeltemaschinenbau AG +D7B000-D7BFFF (base 16) Peter Huber Kaeltemaschinenbau AG + Werner-von-Siemens-Str. 1 + Offenburg Ba-Wue 77656 + DE + +70-B3-D5 (hex) SHENZHEN WISEWING INTERNET TECHNOLOGY CO.,LTD +94A000-94AFFF (base 16) SHENZHEN WISEWING INTERNET TECHNOLOGY CO.,LTD + No.826,Zone 1,Block B,Famous industrial product display purchasing center,Baoyuan Road,Xixiang,Bao'an Dis., Shenzhen,P.R.China + shenzhen China 518102 + CN + +70-B3-D5 (hex) Storbyte, Inc. +63D000-63DFFF (base 16) Storbyte, Inc. + 1800 Washington Blvd Suite 412 + Baltimore MD 21230 + US + +70-B3-D5 (hex) Savari Inc +207000-207FFF (base 16) Savari Inc + 2005 De la cruz blvd, st 111, + santa clara CA 95050 + US + +70-B3-D5 (hex) Selex ES Inc. +F5E000-F5EFFF (base 16) Selex ES Inc. + 4221 Tudor Lane + Greensboro NC 27410 + US + +70-B3-D5 (hex) iFreecomm Technology Co., Ltd +032000-032FFF (base 16) iFreecomm Technology Co., Ltd + D401, NO.16 Langshan Road, Nanshan District + Shenzhen Guangdong 518057 + CN + +70-B3-D5 (hex) QIAGEN Instruments AG +A29000-A29FFF (base 16) QIAGEN Instruments AG + Garstligweg 8 + Hombrechtikon Zurich 8634 + CH + +70-B3-D5 (hex) True Networks Ltd. +AF2000-AF2FFF (base 16) True Networks Ltd. + #401 51 Seongnam-Daero Bundang-gu + SEONGNAM-si GYEONGGI-do 13636 + KR + +70-B3-D5 (hex) EPSOFT Co., Ltd +A3A000-A3AFFF (base 16) EPSOFT Co., Ltd + 301, Bupyeong-daero, Bupyeong-gu + Incheon 21315 + KR + +70-B3-D5 (hex) Visual Fan +FD6000-FD6FFF (base 16) Visual Fan + Brazilor nr.61 + Brasov Brasov 500313 + RO + +70-B3-D5 (hex) InOut Communication Systems +FF9000-FF9FFF (base 16) InOut Communication Systems + via Nobel, 10 + Noventa di Piave Venezia 30020 + IT + +70-B3-D5 (hex) Sensor 42 +BFB000-BFBFFF (base 16) Sensor 42 + 1165 Linda Vista, #110 + San Marcos CA 92078 + US + +70-B3-D5 (hex) Electrolux +7A6000-7A6FFF (base 16) Electrolux + Corso Lino Zanussi 24 + Porcia PORDENONE 33080 + IT + +70-B3-D5 (hex) Movimento Group AB +357000-357FFF (base 16) Movimento Group AB + 45550 Commerce Center Drive + Plymouth MI 48170 + US + +70-B3-D5 (hex) IDEM INC. +DC6000-DC6FFF (base 16) IDEM INC. + 17302 Daimler St. STE A + Irvine CA 92614 + US + +70-B3-D5 (hex) MANSION INDUSTRY CO., LTD. +734000-734FFF (base 16) MANSION INDUSTRY CO., LTD. + 5F., No.6, Siwei Ln., Zhongzheng Rd., Xindian Dist., + New Taipei City 231 + TW + +70-B3-D5 (hex) Wavemed srl +813000-813FFF (base 16) Wavemed srl + Via di campo gillaro 29/a + San Cesareo Roma 00030 + IT + +70-B3-D5 (hex) Spaceflight Industries +98F000-98FFFF (base 16) Spaceflight Industries + 1505 Westlake Ave N, Ste 600 + Seattle WA 98109 + US + +70-B3-D5 (hex) Keycom Corp. +C37000-C37FFF (base 16) Keycom Corp. + 3-39-14 Minamiotsuka + Toshima-ku Tokyo 170-0005 + JP + +70-B3-D5 (hex) Enerwise Solutions Ltd. +99C000-99CFFF (base 16) Enerwise Solutions Ltd. + Flat/Room 510, 5/F, Wayson Comm Building + Hong Kong none none + HK + +70-B3-D5 (hex) Scrona AG +00D000-00DFFF (base 16) Scrona AG + Technoparkstrasse 1 + Zurich Zurich 8005 + CH + +70-B3-D5 (hex) Axxess Identification Ltd +616000-616FFF (base 16) Axxess Identification Ltd + 27-28 Shrivenham Hundred Business Park + Swindon Wiltshire SN6 8TZ + GB + +70-B3-D5 (hex) RIKEN OPTECH CORPORATION +63E000-63EFFF (base 16) RIKEN OPTECH CORPORATION + 5615-1 Taguchi + Saku-city Nagano 384-0412 + JP + +70-B3-D5 (hex) Asystems Corporation +255000-255FFF (base 16) Asystems Corporation + 10F., No.70, Sec.1, Keelung Rd + Taipei Taiwan 11070 + TW + +70-B3-D5 (hex) Private +278000-278FFF (base 16) Private + +70-B3-D5 (hex) Arrowvale Electronics +B07000-B07FFF (base 16) Arrowvale Electronics + Shawbank Road + Redditch Worcestershire B98 8YN + GB + +70-B3-D5 (hex) NAS Australia P/L +E91000-E91FFF (base 16) NAS Australia P/L + 28 Newstead Terrace + Newstead QLD 4006 + AU + +70-B3-D5 (hex) Data Informs LLC +566000-566FFF (base 16) Data Informs LLC + 9838 Nevada Avenue + Chatsworth CA 91311-4040 + US + +70-B3-D5 (hex) MI Inc. +D26000-D26FFF (base 16) MI Inc. + 6F, Toto building, 5-1-4, Toranomon, Minato-ku + Tokyo 1050001 + JP + +70-B3-D5 (hex) Shangdong Bosure Automation Technology Ltd +A88000-A88FFF (base 16) Shangdong Bosure Automation Technology Ltd + No.1 Shunhua Road, Gaoxin District + Jinan Shangdong 250101 + CN + +70-B3-D5 (hex) Maharsystem +72E000-72EFFF (base 16) Maharsystem + No 1, 5th Alley ,Ozgol , Artesh Blvd + Tehran Tehran 1694937141 + IR + +70-B3-D5 (hex) HumanEyes Technologies Ltd. +9DD000-9DDFFF (base 16) HumanEyes Technologies Ltd. + Neve Ilan + Neve Ilan 90850 + IL + +70-B3-D5 (hex) Shenzhen SanYeCao Electronics Co.,Ltd +E7B000-E7BFFF (base 16) Shenzhen SanYeCao Electronics Co.,Ltd + 505, 5/F, Dahong High Tech Industry Park, No.6-18, Xinhe Road, Shajing, Baoan District, Shenzhen + SHENZHEN GUANGDONG 518100 + CN + +70-B3-D5 (hex) RMA Mess- und Regeltechnik GmbH & Co.KG +DF8000-DF8FFF (base 16) RMA Mess- und Regeltechnik GmbH & Co.KG + Forsthausstr. 3 + Rheinau 77866 + DE + +70-B3-D5 (hex) Cellier Domesticus inc +E96000-E96FFF (base 16) Cellier Domesticus inc + 840 5E avenue + Montreal Quebec H9c1j5 + CA + +70-B3-D5 (hex) COMM-connect A/S +EED000-EEDFFF (base 16) COMM-connect A/S + Raasigvangen 2 + Slangerup DK-3550 + DK + +70-B3-D5 (hex) Plasmapp Co.,Ltd. +E18000-E18FFF (base 16) Plasmapp Co.,Ltd. + 83, Jukdong-ro, Yuseong-gu, + Daejeon KS015 + KR + +70-B3-D5 (hex) Harborside Technology +845000-845FFF (base 16) Harborside Technology + 140 Mcknitt Pl + Garner NC 27529 + US + +70-B3-D5 (hex) Rockwell Collins Canada +839000-839FFF (base 16) Rockwell Collins Canada + 30 Edgewater Street, Suite 104 + Ottawa ON K2L1V8 + CA + +70-B3-D5 (hex) HEITEC AG +557000-557FFF (base 16) HEITEC AG + Dr.-Otto-Leich-Str. 16 + Eckental Bavaria 90542 + DE + +70-B3-D5 (hex) Pano0ramic Power +53A000-53AFFF (base 16) Pano0ramic Power + 15 Atir Yeda + Kfar Saba 4464312 + IL + +70-B3-D5 (hex) ND METER +68C000-68CFFF (base 16) ND METER + 228 BOLTON ROAD + BRADFORD BD3 0QW + GB + +70-B3-D5 (hex) CRDE +C42000-C42FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) DIGIVERV INC +548000-548FFF (base 16) DIGIVERV INC + 1515 Evanvale Dr + Allen TX 75013 + US + +70-B3-D5 (hex) Council Rock +7C9000-7C9FFF (base 16) Council Rock + 11 Centre Park + Rochester 14614 + US + +70-B3-D5 (hex) Blink Services AB +2A1000-2A1FFF (base 16) Blink Services AB + Generalsgatan 5 + Malmö 211 33 + SE + +70-B3-D5 (hex) KST technology +CB3000-CB3FFF (base 16) KST technology + KST B/D 4-5, Wiryeseong-daero 12-gil + Songpa-gu Seoul 05636 + KR + +70-B3-D5 (hex) Boutronic +359000-359FFF (base 16) Boutronic + Edisonstraat 24 + 's-Gravenzande Nederland 2691GT + NL + +70-B3-D5 (hex) Abalance Corporation +07F000-07FFFF (base 16) Abalance Corporation + Tennozu First Tower 5F, 2-2-4 Higashishinagawa + Shinagawa-ku Tokyo 140-0002 + JP + +70-B3-D5 (hex) HUGEL GmbH +04E000-04EFFF (base 16) HUGEL GmbH + Seestrasse 4 + Oberrieden ZH 8942 + CH + +70-B3-D5 (hex) EZSYS Co., Ltd. +D43000-D43FFF (base 16) EZSYS Co., Ltd. + E-914,E-915, 60, Haan-ro(Soha-dong, Gwangmyeong SK Technopark) + Gwangmyeong-si Gyeonggi-do 14322 + KR + +70-B3-D5 (hex) SRS Group s.r.o. +95B000-95BFFF (base 16) SRS Group s.r.o. + Rybnicna 36/D + Bratislava 83107 + SK + +70-B3-D5 (hex) JASCO Applied Sciences Canada Ltd +7F7000-7F7FFF (base 16) JASCO Applied Sciences Canada Ltd + 32 Troop Avenue, Suite 202 + Dartmouth Nova Scotia B3B 1Z1 + CA + +70-B3-D5 (hex) CRDE +6B2000-6B2FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) RIOT +715000-715FFF (base 16) RIOT + 295 Kent ave + ferndale, Randburg Gauteng 2194 + ZA + +70-B3-D5 (hex) Design SHIFT +FDB000-FDBFFF (base 16) Design SHIFT + 3475 Edison Way, Suite G + Menlo Park CA 94025 + US + +70-B3-D5 (hex) Sensorberg GmbH +6AF000-6AFFFF (base 16) Sensorberg GmbH + Leipziger Str. 126 + Berlin Berlin 10117 + DE + +70-B3-D5 (hex) Rheonics GmbH +D20000-D20FFF (base 16) Rheonics GmbH + Rheonics GmbH, Technoparkstr. 2 + Winterthur Schweiz 8406 + CH + +70-B3-D5 (hex) Emtel System Sp. z o.o. +969000-969FFF (base 16) Emtel System Sp. z o.o. + Promienista 11 + Poznan 60-288 + PL + +70-B3-D5 (hex) Amphenol Advanced Sensors +A9A000-A9AFFF (base 16) Amphenol Advanced Sensors + Amphenol Interconnect India Private Ltd, MAHAVEER TECHNO PARK APIIC, Plot no.6, Survey No.64, Software Units layout, Hi-tech City, Madhapur, + HYDERABAD Telangana 500081 + IN + +70-B3-D5 (hex) Mentor Graphics +3FE000-3FEFFF (base 16) Mentor Graphics + 46871 Bayside Parkway + Fremont CA 94538 + US + +70-B3-D5 (hex) DWQ Informatikai Tanacsado es Vezerlestechnikai KFT +B48000-B48FFF (base 16) DWQ Informatikai Tanacsado es Vezerlestechnikai KFT + Bathoty Istvan str 14 + Rackeve 2300 + HU + +70-B3-D5 (hex) Skyriver Communications Inc. +C22000-C22FFF (base 16) Skyriver Communications Inc. + 7310 Miramar Rd. #600 + San Diego CA 92126 + US + +70-B3-D5 (hex) K&J Schmittschneider AG +9B3000-9B3FFF (base 16) K&J Schmittschneider AG + Wiesholzstrasse 452 + Ramsen Schaffhausen 8262 + CH + +70-B3-D5 (hex) Meta Computing Services, Corp +E9A000-E9AFFF (base 16) Meta Computing Services, Corp + 5795 S Sandhill Rd Suite F + Las Vegas NV 89120 + US + +70-B3-D5 (hex) ExSens Technology (Pty) Ltd. +14A000-14AFFF (base 16) ExSens Technology (Pty) Ltd. + 39 Kelly Road, The Palisades Business Park Unit C1 + Boksburg Gauteng 1459 + ZA + +70-B3-D5 (hex) Digital Domain +4E7000-4E7FFF (base 16) Digital Domain + 1700 Main St Ste 222 + Washougal WA 98671 + US + +70-B3-D5 (hex) Tieline Research Pty Ltd +20F000-20FFFF (base 16) Tieline Research Pty Ltd + PO Box 2092 + MALAGA Western Australia 6944 + AU + +70-B3-D5 (hex) Herrmann Datensysteme GmbH +B04000-B04FFF (base 16) Herrmann Datensysteme GmbH + Gewerbepark 10 + Großpostwitz OT Ebendörfel 02692 + DE + +70-B3-D5 (hex) Symboticware Incorporated +945000-945FFF (base 16) Symboticware Incorporated + 1545 Maley Drive + Sudbury ON P3A 4R7 + CA + +70-B3-D5 (hex) ASPT, INC. +192000-192FFF (base 16) ASPT, INC. + 303-ho B-dong Songdosmartvalley, 30 Songdomirae-ro Yeonsu-gu + Incheon 21990 + KR + +70-B3-D5 (hex) CONTROL SYSTEMS Srl +229000-229FFF (base 16) CONTROL SYSTEMS Srl + Via del Brolo, 14 + Cremona CR 26100 + IT + +70-B3-D5 (hex) SHANGHAI CHENZHU INSTRUMENT CO., LTD. +46C000-46CFFF (base 16) SHANGHAI CHENZHU INSTRUMENT CO., LTD. + Building 6, 201 Minyi Road, Songjiang District + Shanghai 201612 + CN + +70-B3-D5 (hex) Applied Satellite Engineering +A48000-A48FFF (base 16) Applied Satellite Engineering + 16559 N 92nd, Suite 101 + Scottsdale AZ 85260 + US + +70-B3-D5 (hex) LINEAGE POWER PVT LTD., +479000-479FFF (base 16) LINEAGE POWER PVT LTD., + 186/3, #117, HOODY VILLAGE MAHADEVAPURA POST, WHITEFIELD RD. + BANGALORE KAR 560048 + IN + +70-B3-D5 (hex) EA Elektroautomatik GmbH & Co. KG +CE1000-CE1FFF (base 16) EA Elektroautomatik GmbH & Co. KG + Helmholtzstraße 31-33 + Viersen NRW 41747 + DE + +70-B3-D5 (hex) System 11 Sp. z o.o. +9DE000-9DEFFF (base 16) System 11 Sp. z o.o. + Wieniawskiego 18 + Chorzow 41-506 + PL + +70-B3-D5 (hex) KANOA INC +A47000-A47FFF (base 16) KANOA INC + 760 Bryant Street + San Francisco CA 94107 + US + +70-B3-D5 (hex) Biwave Technologies, Inc. +168000-168FFF (base 16) Biwave Technologies, Inc. + 3F-6, No. 77, Keelung Rd., Sec. 2 + Taipei 11491 + TW + +70-B3-D5 (hex) Mencom Corporation +596000-596FFF (base 16) Mencom Corporation + 5750 McEver Road + Oakwood GA 30566 + US + +70-B3-D5 (hex) Fiem Industries Ltd. +495000-495FFF (base 16) Fiem Industries Ltd. + Unit VII, Plot No. 1915, Rai Industrial Estate, Phase-V + Sonepat Haryana 131029 + IN + +70-B3-D5 (hex) Wyebot, Inc. +8C3000-8C3FFF (base 16) Wyebot, Inc. + 2 Mount Royal Ave. + Marlborough MA 01752 + US + +70-B3-D5 (hex) Advanced Vision Technology Ltd +E50000-E50FFF (base 16) Advanced Vision Technology Ltd + Thames House, Mere Park + Marlow Buckinghamshire SL7 1PB + GB + +70-B3-D5 (hex) Foerster-Technik GmbH +2B4000-2B4FFF (base 16) Foerster-Technik GmbH + Gerwigstraße 25 + Engen Baden-Württemberg 78234 + DE + +70-B3-D5 (hex) China Entropy Co., Ltd. +E16000-E16FFF (base 16) China Entropy Co., Ltd. + Haidian District + Beijing 100085 + CN + +70-B3-D5 (hex) ard sa +489000-489FFF (base 16) ard sa + Micropolis Bat Clematis + Gap France 05000 + FR + +70-B3-D5 (hex) ITS Industrial Turbine Services GmbH +9A1000-9A1FFF (base 16) ITS Industrial Turbine Services GmbH + Fabriksplatz 1 + Steyrermuehl Upper Austria 4662 + AT + +70-B3-D5 (hex) CG-WIRELESS +BF3000-BF3FFF (base 16) CG-WIRELESS + LE MOUSTOIR + PLOGASTEL SAINT GERMAIN 29710 + FR + +70-B3-D5 (hex) Vishay Nobel AB +873000-873FFF (base 16) Vishay Nobel AB + Box 423 + Karlskoga SE-691 27 + SE + +70-B3-D5 (hex) DesignA Electronics Limited +661000-661FFF (base 16) DesignA Electronics Limited + Unit 6 + Christchurch New Zealand 8011 + NZ + +70-B3-D5 (hex) Visualware, Inc. +2A2000-2A2FFF (base 16) Visualware, Inc. + 937 SIERRA DRIVE + TURLOCK CA 95380 + US + +70-B3-D5 (hex) Sumer Data S.L +011000-011FFF (base 16) Sumer Data S.L + Francisco Ayala,2 + Rivas-Vaciamadrid Madrid 28522 + ES + +70-B3-D5 (hex) LG Electronics +927000-927FFF (base 16) LG Electronics + 2621, Nuambusunhwan-ro, Gangnam-gu, + Seoul 135-860 + KR + +70-B3-D5 (hex) Intervala +3F0000-3F0FFF (base 16) Intervala + 700 Braddock Avenue + East Pittsburgh PA 15112-1242 + US + +70-B3-D5 (hex) PoolDigital GmbH & Co. KG +063000-063FFF (base 16) PoolDigital GmbH & Co. KG + Kaffeegasse, 7 + Halsenbach 56283 + DE + +70-B3-D5 (hex) HORIBA ABX SAS +AB8000-AB8FFF (base 16) HORIBA ABX SAS + rue du caducee + Montpellier Herault 34000 + FR + +70-B3-D5 (hex) International Center for Elementary Particle Physics, The University of Tokyo +F9E000-F9EFFF (base 16) International Center for Elementary Particle Physics, The University of Tokyo + 7-3-1 Hongo, Bunkyo-ku + Tokyo 113-0033 + JP + +70-B3-D5 (hex) Star Electronics GmbH & Co. KG +3BF000-3BFFFF (base 16) Star Electronics GmbH & Co. KG + Jahnstraße 86 + Göppingen BW 73037 + DE + +70-B3-D5 (hex) CableLabs +BD1000-BD1FFF (base 16) CableLabs + 858 Coal Creek Circle + Louisville CO 80027 + US + +70-B3-D5 (hex) Guangxi Hunter Information Industry Co.,Ltd +397000-397FFF (base 16) Guangxi Hunter Information Industry Co.,Ltd + Hunter Building,Creative Industry Park In Guilin,China + Guilin Guangxi Province 541004 + CN + +70-B3-D5 (hex) LOOK EASY INTERNATIONAL LIMITED +0C2000-0C2FFF (base 16) LOOK EASY INTERNATIONAL LIMITED + 4th Floor, No. 551, Guang-Fu South Road + Taipei Xinyi District 11074 + TW + +70-B3-D5 (hex) ATX Networks Corp +51C000-51CFFF (base 16) ATX Networks Corp + 1-501 Clements Road West + Ajax Ontario L1s7H4 + CA + +70-B3-D5 (hex) Grossenbacher Systeme AG +0E8000-0E8FFF (base 16) Grossenbacher Systeme AG + Spinnereistrasse 10 + St. Gallen 9008 + CH + +70-B3-D5 (hex) Sierra Pacific Innovations Corp +EBE000-EBEFFF (base 16) Sierra Pacific Innovations Corp + 6620 S Tenaya Way + Las Vegas 89113 + US + +70-B3-D5 (hex) Terragene S.A +9CE000-9CEFFF (base 16) Terragene S.A + Guemes 2879 + Rosario Santa fe 2000 + AR + +70-B3-D5 (hex) FINANCIERE DE L'OMBREE (eolane) +31C000-31CFFF (base 16) FINANCIERE DE L'OMBREE (eolane) + La Fresnay + Le Fresne sur Loire 49123 + FR + +70-B3-D5 (hex) OES Inc. +1B8000-1B8FFF (base 16) OES Inc. + 4056 Blakie Road + London ON N6L1P7 + CA + +70-B3-D5 (hex) DKS Dienstl.ges. f. Komm.anl. d. Stadt- u. Reg.verk. mbH +EF8000-EF8FFF (base 16) DKS Dienstl.ges. f. Komm.anl. d. Stadt- u. Reg.verk. mbH + Robert-Perthel-Str. 79 + Cologne 50739 + DE + +70-B3-D5 (hex) BRUSHIES +85A000-85AFFF (base 16) BRUSHIES + 6402 Langer Lane + Lino Lakes MN 55038 + US + +70-B3-D5 (hex) Quan International Co., Ltd. +724000-724FFF (base 16) Quan International Co., Ltd. + 4F, No. 196, Hsinghu 3rd Rd., Neihu District + Taipei 11494 + TW + +70-B3-D5 (hex) Key Chemical & Equipment Company +427000-427FFF (base 16) Key Chemical & Equipment Company + 13195 49th Street North Suite H + Clearwater FL 33762 + US + +70-B3-D5 (hex) Earth Works +61C000-61CFFF (base 16) Earth Works + 13-21 Saiwaityou + Kofu Yamanashi 400-0857 + JP + +70-B3-D5 (hex) Layer Logic Inc +C5C000-C5CFFF (base 16) Layer Logic Inc + 5412 Courseview Drive, suite 100 + Mason OH 45040 + US + +70-B3-D5 (hex) Eutron SPA +DCC000-DCCFFF (base 16) Eutron SPA + Via Crespi 29/31 + Pradalunga Bergamo 24020 + IT + +70-B3-D5 (hex) Device Solutions Ltd +BAA000-BAAFFF (base 16) Device Solutions Ltd + PO Box 131 + Rolleston Canterbury 7614 + NZ + +70-B3-D5 (hex) DEUTA-WERKE GmbH +25A000-25AFFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) SEASON DESIGN TECHNOLOGY +94D000-94DFFF (base 16) SEASON DESIGN TECHNOLOGY + FLOOR 4, WARDS EXCHANGE, 199 ECCLESALL ROAD + SHEFFIELD SOUTH YORKSHIRE S11 8HW + GB + +70-B3-D5 (hex) Altron, a.s. +693000-693FFF (base 16) Altron, a.s. + Novodvorska 994/138 + Praha 14221 + CZ + +70-B3-D5 (hex) Matrix Switch Corporation +90B000-90BFFF (base 16) Matrix Switch Corporation + 431 Crown Point Circle, Suite 200 + Grass Valley CA 95945 + US + +70-B3-D5 (hex) Beijing Wisetone Information Technology Co.,Ltd. +C12000-C12FFF (base 16) Beijing Wisetone Information Technology Co.,Ltd. + B-7A ,48A Zhichun Road,Haidian District,Beijing + Beijing Beijing 100098 + CN + +70-B3-D5 (hex) WIZNOVA +C62000-C62FFF (base 16) WIZNOVA + 403, Daedeok Plaza1, 12, Dochon-ro, Jungwon-gu, Gyeonggi-do + Seongnam KS009 + KR + +70-B3-D5 (hex) Elsist Srl +13D000-13DFFF (base 16) Elsist Srl + Via G. Brodolini, 15 + Casale Monf.to Alessandria 15033 + IT + +70-B3-D5 (hex) Swiss Audio +735000-735FFF (base 16) Swiss Audio + 6 Rue de Saint-Léger + Geneva Geneva 1205 + CH + +70-B3-D5 (hex) NuRi&G Engineering co,.Ltd. +72C000-72CFFF (base 16) NuRi&G Engineering co,.Ltd. + #66-33, Elevator road, Geochang Industrial Complex + Geochang-gun Gyeongsangnam-do 50148 + KR + +70-B3-D5 (hex) IOOOTA Srl +F8B000-F8BFFF (base 16) IOOOTA Srl + Via Molino Rosso, 8 + Imola BO 40026 + IT + +70-B3-D5 (hex) GMI Ltd +F03000-F03FFF (base 16) GMI Ltd + Inchinnan Business Park + Renfre PA4 9RG + GB + +70-B3-D5 (hex) TEX COMPUTER SRL +28E000-28EFFF (base 16) TEX COMPUTER SRL + VIA MERCADANTE 35 + CATTOLICA RIMINI 47841 + IT + +70-B3-D5 (hex) RBS Netkom GmbH +934000-934FFF (base 16) RBS Netkom GmbH + Muenchnerstrasse 87b + Dachau 85221 + DE + +70-B3-D5 (hex) MyDefence Communication ApS +3BE000-3BEFFF (base 16) MyDefence Communication ApS + Sundsholmen 25 + Noerresundby Danmark 9400 + DK + +70-B3-D5 (hex) Itest communication Tech Co., LTD +503000-503FFF (base 16) Itest communication Tech Co., LTD + F2,#2,2nd Southern IND Zone of HongHualing,Nanshan District + shenzhen guangdong 518000 + CN + +70-B3-D5 (hex) BMT Messtechnik Gmbh +5D6000-5D6FFF (base 16) BMT Messtechnik Gmbh + Güterfelder Damm 87-91 + Stahnsdorf 14532 + DE + +70-B3-D5 (hex) Unicom Global, Inc. +9FB000-9FBFFF (base 16) Unicom Global, Inc. + 581, Ruiguang Road, Neihu Dist. + Taipei 11492 + TW + +70-B3-D5 (hex) Vivaldi Clima Srl +457000-457FFF (base 16) Vivaldi Clima Srl + Via Pascoli 13 + Casazza Lombardia 24060 + IT + +70-B3-D5 (hex) Hyundai MNSOFT +D75000-D75FFF (base 16) Hyundai MNSOFT + 74, Wonhyoro, Yongsan-gu, Seoul 140-711, korea + Seoul N/A KS013 + KR + +70-B3-D5 (hex) Re spa - Controlli Industriali - IT01782300154 +ECB000-ECBFFF (base 16) Re spa - Controlli Industriali - IT01782300154 + via Firenze 3 + Bussero 20060 + IT + +70-B3-D5 (hex) FIRST LIGHT IMAGING +B09000-B09FFF (base 16) FIRST LIGHT IMAGING + 100 route des Houilleres + MEYREUIL 13590 + FR + +70-B3-D5 (hex) Critical Link LLC +42A000-42AFFF (base 16) Critical Link LLC + 6712 Brooklawn Parkway + Syracuse null 13211 + US + +70-B3-D5 (hex) FOSHAN SHILANTIAN NETWORK S.T. CO., LTD. +C5D000-C5DFFF (base 16) FOSHAN SHILANTIAN NETWORK S.T. CO., LTD. + NO.11,ZHANGCHA ROAD,CHANCHENG DISTRICT + FOSHAN GUANGDONG 528000 + CN + +70-B3-D5 (hex) EWATTCH +475000-475FFF (base 16) EWATTCH + 13, rue Maurice Jeandon + Saint Die des Vosges Lorraine 88100 + FR + +70-B3-D5 (hex) nyantec GmbH +C6F000-C6FFFF (base 16) nyantec GmbH + Europaplatz 2 + Berlin 10557 + DE + +70-B3-D5 (hex) Iotopia Solutions +317000-317FFF (base 16) Iotopia Solutions + 711 Atlantic Ave + Boston MA 02111 + US + +70-B3-D5 (hex) COSMOS web Co., Ltd. +3E8000-3E8FFF (base 16) COSMOS web Co., Ltd. + 5-4-1 Kuryu Aoba-ku + Sendai-shi Miyagi 989-3122 + JP + +70-B3-D5 (hex) SANO SERVICE Co.,Ltd +D95000-D95FFF (base 16) SANO SERVICE Co.,Ltd + 2-10-3 Sotokanda Chiyoda-ku + Tokyo 1010021 + JP + +70-B3-D5 (hex) BISTOS.,Co.,Ltd +97F000-97FFFF (base 16) BISTOS.,Co.,Ltd + 7th Fl., A Bldg., Woolim Lions Valley 5-cha, 144-3, Sangdaewon-dong, Jungwon-gu + Seongnam-si Gyeonggi-do 462-739 + KR + +70-B3-D5 (hex) Autonomic Controls, Inc. +973000-973FFF (base 16) Autonomic Controls, Inc. + 28 Kaysal Ct + ARMONK NY 10504 + US + +70-B3-D5 (hex) Peter Huber Kaeltemaschinenbau GmbH +CD9000-CD9FFF (base 16) Peter Huber Kaeltemaschinenbau GmbH + Werner-von-Siemens-Str. 1 + Offenburg Ba-Wue 77656 + DE + +70-B3-D5 (hex) AXIS CORPORATION +987000-987FFF (base 16) AXIS CORPORATION + Higashi Tokorozawa 2-24-5 + Tokorozawa-shi Saitama 359-0021 + JP + +70-B3-D5 (hex) Atonarp Micro-Systems India Pvt. Ltd. +976000-976FFF (base 16) Atonarp Micro-Systems India Pvt. Ltd. + The Millenia, Tower A, 3rd Floor, No. 1&2 Murphy Road – Ulsoor, + Bangalore Karnataka 560008 + IN + +70-B3-D5 (hex) Innominds Software Inc +0CE000-0CEFFF (base 16) Innominds Software Inc + 2055 Junction Ave Suite 122, San Jose CA 95131 + San Jose CA 95131 + US + +70-B3-D5 (hex) Assembly Contracts Limited +54F000-54FFFF (base 16) Assembly Contracts Limited + Ledson Road + Wythenshawe Manchester M23 9GP + GB + +70-B3-D5 (hex) ATX Networks Corp +644000-644FFF (base 16) ATX Networks Corp + 1-501 Clements Road West + Ajax Ontario L1s7H4 + CA + +70-B3-D5 (hex) Netfort Solutions +EDB000-EDBFFF (base 16) Netfort Solutions + 10 Hamlin Manor,, GLENLUCE DRIVE, + Douglasdale Johannesburg 2191 + ZA + +70-B3-D5 (hex) Lattech Systems Pty Ltd +197000-197FFF (base 16) Lattech Systems Pty Ltd + 24 Richelieu Street + Durbanville Western Cape 7550 + ZA + +70-B3-D5 (hex) Fortuna Impex Pvt ltd +9AD000-9ADFFF (base 16) Fortuna Impex Pvt ltd + 12D Harrington Mansions , 8 Ho Chi Minh Sarani + Kolkata West Bengal 700071 + IN + +70-B3-D5 (hex) Sakura Seiki Co.,Ltd. +B62000-B62FFF (base 16) Sakura Seiki Co.,Ltd. + 75-5, Imojiya + Chikuma-city Nagano Prefecture 387-0015 + JP + +70-B3-D5 (hex) Qualitronix Madrass Pvt Ltd +A19000-A19FFF (base 16) Qualitronix Madrass Pvt Ltd + No112, Tiny Sector, Guindy Industrial Estate, + Chennai TamilNadu 600032 + IN + +70-B3-D5 (hex) Medisafe International +7B0000-7B0FFF (base 16) Medisafe International + Twyford Road + Bishops Stortford Hertfordshire CM23 3LJ + GB + +70-B3-D5 (hex) Littlemore Scientific +F81000-F81FFF (base 16) Littlemore Scientific + Gutchpool Farm + Gillingham Dorset SP8 5QP + GB + +70-B3-D5 (hex) Link Care Services +C80000-C80FFF (base 16) Link Care Services + 3bis rue Taylor + Paris Paris 75010 + FR + +70-B3-D5 (hex) TATTILE SRL +5C4000-5C4FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Potter Electric Signal Co. LLC +7A4000-7A4FFF (base 16) Potter Electric Signal Co. LLC + 1609 Park 370 Place + Hazelwood 63042 + US + +70-B3-D5 (hex) Arete Associates +238000-238FFF (base 16) Arete Associates + 9301 Corbin Ave Suite 2000 + Northridge CA 91324 + US + +70-B3-D5 (hex) RWS Automation GmbH +E4F000-E4FFFF (base 16) RWS Automation GmbH + Neuer Weg 2 + Niefern - Öschelbronn 75223 + DE + +70-B3-D5 (hex) Suzhou PowerCore Technology Co.,Ltd. +CCD000-CCDFFF (base 16) Suzhou PowerCore Technology Co.,Ltd. + Building #3,No.9 Xuesen Road,Science&Technology Town,Suzhou New District + Suzhou Jiangsu 215000 + CN + +70-B3-D5 (hex) Supervision Test et Pilotage +B23000-B23FFF (base 16) Supervision Test et Pilotage + 70 avenue de Rome + LA SEYNE SUR MER 83500 + FR + +70-B3-D5 (hex) SolwayTech +BD9000-BD9FFF (base 16) SolwayTech + 124, Jungdae-ro, Songpa-gu + seoul 05829 + KR + +70-B3-D5 (hex) Colmek +D05000-D05FFF (base 16) Colmek + 6526 S Cottonwood St + Murray UT 84107 + US + +70-B3-D5 (hex) DSP4YOU LTd +12F000-12FFFF (base 16) DSP4YOU LTd + Unit 1204, 106 How Ming Street + Hong Kong 0000 + HK + +70-B3-D5 (hex) LogiM GmbH Software und Entwicklung +FAA000-FAAFFF (base 16) LogiM GmbH Software und Entwicklung + Mahonienweg 22b + Berlin 12437 + DE + +70-B3-D5 (hex) B/E Aerospace, Inc. +448000-448FFF (base 16) B/E Aerospace, Inc. + 355 Knickerbocker Ave + Bohemia NY 11716 + US + +70-B3-D5 (hex) Vtron Pty Ltd +3EF000-3EFFFF (base 16) Vtron Pty Ltd + Unit 2, 62 Township Drive West + West Burleigh Queensland 4219 + AU + +70-B3-D5 (hex) Ascendent Technology Group +D66000-D66FFF (base 16) Ascendent Technology Group + 15 - 9th Avenue South + Cranbrook BC V1C 2L9 + CA + +70-B3-D5 (hex) ENTEC Electric & Electronic Co., LTD. +B44000-B44FFF (base 16) ENTEC Electric & Electronic Co., LTD. + 78-2 Buncheon-ri, Bongdam-eup + Hwaseong-city Gyungki-do 445-894 + KR + +70-B3-D5 (hex) JSC OTZVUK +615000-615FFF (base 16) JSC OTZVUK + 10-30 Dostoevskogo Str. + Saint-Petersburg 191119 + RU + +70-B3-D5 (hex) Beijing Arrow SEED Technology Co,.Ltd. +A4A000-A4AFFF (base 16) Beijing Arrow SEED Technology Co,.Ltd. + 28/F, Taikang Financial Tower, 38 North Street of East 3rd Ring, Chaoyang District + beijing beijing 100033 + CN + +70-B3-D5 (hex) FutureTechnologyLaboratories INC. +B59000-B59FFF (base 16) FutureTechnologyLaboratories INC. + 3-2 Shinsakae-3chome Naka-ku + Nagoya Aichi 460-0007 + JP + +70-B3-D5 (hex) Varikorea +3A7000-3A7FFF (base 16) Varikorea + #505 kolon digital tower aston, gasan, geumcheon + seoul 08502 + KR + +70-B3-D5 (hex) TEX COMPUTER SRL +F99000-F99FFF (base 16) TEX COMPUTER SRL + Tex Computer Srl Via Mercadante 35 + Cattolica RIMINI 47841 + IT + +70-B3-D5 (hex) ConectaIP Tecnologia S.L. +A5E000-A5EFFF (base 16) ConectaIP Tecnologia S.L. + Novell 58 + Barcelona 08014 + ES + +70-B3-D5 (hex) MVT Video Technologies R + H Maedler GbR +5CD000-5CDFFF (base 16) MVT Video Technologies R + H Maedler GbR + Neustraße 35-37 + Velbert 42553 + DE + +70-B3-D5 (hex) eSoftThings +9EC000-9ECFFF (base 16) eSoftThings + 80 Avenue des Buttes de Coesmes + RENNES 35700 + FR + +70-B3-D5 (hex) DimoSystems BV +AF7000-AF7FFF (base 16) DimoSystems BV + PO Box 875 + Gorinchem Zuid-Holland 4200AW + NL + +70-B3-D5 (hex) StarBridge, Inc. +1B5000-1B5FFF (base 16) StarBridge, Inc. + 3-5-10 + Tachikawa Tokyo 190-0023 + JP + +70-B3-D5 (hex) Energi innovation Aps +307000-307FFF (base 16) Energi innovation Aps + HC andersens alle 3 + Vejen Danmark 6600 + DK + +70-B3-D5 (hex) Asia Pacific Satellite Coummunication Inc. +C8B000-C8BFFF (base 16) Asia Pacific Satellite Coummunication Inc. + 9F, Lotte IT Castle 2-Dong, #550-1, Gasan-Dong, Geumchon-Gu, + SEOUL 08506 + KR + +70-B3-D5 (hex) RF CREATIONS LTD +1DD000-1DDFFF (base 16) RF CREATIONS LTD + St John's Innovation Centre + Cambridge Cambridgeshire CB4 0WS + GB + +70-B3-D5 (hex) SECLAB +CB2000-CB2FFF (base 16) SECLAB + 40 Avenue Theroigne de Mericourt + MONTPELLIER 34000 + FR + +70-B3-D5 (hex) Norsat International Inc. +0AE000-0AEFFF (base 16) Norsat International Inc. + 110-4020 Viking Way + Richmond BC V6V 2L4 + CA + +70-B3-D5 (hex) Dainichi Denshi Co.,LTD +8CF000-8CFFFF (base 16) Dainichi Denshi Co.,LTD + 12-27 Enoki-cho + Suita city Osaka 564-0053 + JP + +70-B3-D5 (hex) Rohde&Schwarz Topex SA +296000-296FFF (base 16) Rohde&Schwarz Topex SA + 71th-73th Nicolae Caramfil street, 2nd floor, 1th district + Bucuresti Romania 014142 + RO + +70-B3-D5 (hex) Tecnint HTE SRL +217000-217FFF (base 16) Tecnint HTE SRL + Via della Tecnica 16/18 + Osnago Lecco 23875 + IT + +70-B3-D5 (hex) Rohde&Schwarz Topex SA +FB0000-FB0FFF (base 16) Rohde&Schwarz Topex SA + 71th-73th Nicolae Caramfil street, 2nd floor, 1th district + Bucuresti Romania 014142 + RO + +70-B3-D5 (hex) DomoSafety S.A. +B99000-B99FFF (base 16) DomoSafety S.A. + Innovation Park - Site EPFL + Lausanne 1015 + CH + +70-B3-D5 (hex) MobiPromo +1FE000-1FEFFF (base 16) MobiPromo + 10, 64-72 Beresford Rd + Lilydale Victoria 3140 + AU + +70-B3-D5 (hex) RF Industries +F0B000-F0BFFF (base 16) RF Industries + PO Box 5 + Welland SA 5007 + AU + +70-B3-D5 (hex) Aplex Technology Inc. +FF3000-FF3FFF (base 16) Aplex Technology Inc. + 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District + Shenzhen Guangdong 518054 + CN + +70-B3-D5 (hex) Aplex Technology Inc. +65C000-65CFFF (base 16) Aplex Technology Inc. + 2Q , NanYouTianAn industrial park Tower4 ,Nanshan District + Shenzhen Guangdong 518054 + CN + +70-B3-D5 (hex) Safelet BV +B1D000-B1DFFF (base 16) Safelet BV + Bilderdijkkade 26a-hs + amsterdam 1053 vc + NL + +70-B3-D5 (hex) Nuviz Oy +AAE000-AAEFFF (base 16) Nuviz Oy + Joensuunkatu 7 + Salo 24100 + FI + +70-B3-D5 (hex) Technical Panels Co. Ltd. +C34000-C34FFF (base 16) Technical Panels Co. Ltd. + 288 Soi Chalongkrung 31, Lat Krabang + Bangkok Bangkok 10520 + TH + +70-B3-D5 (hex) Ayre Acoustics, Inc. +0BA000-0BAFFF (base 16) Ayre Acoustics, Inc. + 2300 Central Ave, #B + Boulder CO 80301 + US + +70-B3-D5 (hex) Shenzhen Weema TV Technology Co.,Ltd. +AA1000-AA1FFF (base 16) Shenzhen Weema TV Technology Co.,Ltd. + 4/F,Building two,YuChang Industrial Park,No.28,Guangda Road,Henggang Street,Longgang,Shenzhen. + shenzhen 518000 + CN + +70-B3-D5 (hex) Reinhardt System- und Messelectronic GmbH +4AE000-4AEFFF (base 16) Reinhardt System- und Messelectronic GmbH + Bergstr. 33 + Obermuehlhausen 86911 + DE + +70-B3-D5 (hex) Sol Welding srl +E3E000-E3EFFF (base 16) Sol Welding srl + Via Meucci 26 + Costabissara Italy / Vicenza 36030 + IT + +70-B3-D5 (hex) Silicann Systems GmbH +62B000-62BFFF (base 16) Silicann Systems GmbH + Schillerplatz 10 + Rostock 18055 + DE + +70-B3-D5 (hex) BRS Sistemas Eletrônicos +1FD000-1FDFFF (base 16) BRS Sistemas Eletrônicos + Rua Gomes de Freitas, 491 / 204 + Porto Alegre RS 91380-000 + BR + +70-B3-D5 (hex) ATOM GIKEN Co.,Ltd. +7D9000-7D9FFF (base 16) ATOM GIKEN Co.,Ltd. + 92-2 KATASE + FUJISAWA KANAGAWA 251-0032 + JP + +70-B3-D5 (hex) Tickster AB +350000-350FFF (base 16) Tickster AB + Magasinsgatan 8 + Arvika Värmland SE67131 + SE + +70-B3-D5 (hex) Merz s.r.o. +E2E000-E2EFFF (base 16) Merz s.r.o. + U Sirotcince 353/7 + Liberec 460 01 + CZ + +70-B3-D5 (hex) Leo Bodnar Electronics Ltd +E3D000-E3DFFF (base 16) Leo Bodnar Electronics Ltd + Unit 8 New Rookery Farm + Silverstone NN12 8UP + GB + +70-B3-D5 (hex) INTEC International GmbH +B26000-B26FFF (base 16) INTEC International GmbH + Killertalstr. 4 + Hechingen 72379 + DE + +70-B3-D5 (hex) Aplex Technology Inc. +8E4000-8E4FFF (base 16) Aplex Technology Inc. + 2nd Floor,Tower3,District5,HongHuaLing industrial park, Nanshan District + Shenzhen Guangdong 518055 + CN + +70-B3-D5 (hex) MEDIAM Sp. z o.o. +F13000-F13FFF (base 16) MEDIAM Sp. z o.o. + Wadowicka 12 + Kraków 30-415 + PL + +70-B3-D5 (hex) Coveloz Technologies Inc. +042000-042FFF (base 16) Coveloz Technologies Inc. + 232 Herzberg Road, Suite 204 + Kanata Ontario K2K 2A1 + CA + +70-B3-D5 (hex) PMT Corporation +804000-804FFF (base 16) PMT Corporation + 1705-1 Satani,Sue + Kasuya-gun Fukuoka 811-2115 + JP + +70-B3-D5 (hex) ALTRAN UK +179000-179FFF (base 16) ALTRAN UK + 22 St Lawrence Street + Bath Somerset BA1 1AN + GB + +70-B3-D5 (hex) Qwave Inc +B31000-B31FFF (base 16) Qwave Inc + 18725 Metler Ct + Saratoga CA 95070 + US + +70-B3-D5 (hex) PERFORMANCE CONTROLS, INC. +8D3000-8D3FFF (base 16) PERFORMANCE CONTROLS, INC. + 151 DOMORAH DRIVE + MONTGOMERYVILLE PA 18936 + US + +70-B3-D5 (hex) Husty M.Styczen J.Hupert Sp.J. +194000-194FFF (base 16) Husty M.Styczen J.Hupert Sp.J. + Rzepakowa 5e + Krakow malopolska 31-989 + PL + +70-B3-D5 (hex) Tirasoft Nederland +766000-766FFF (base 16) Tirasoft Nederland + Hyacinthstraat174 + Groningen Groningen 9713XK + NL + +70-B3-D5 (hex) Automation Networks & Solutions LLC +2BB000-2BBFFF (base 16) Automation Networks & Solutions LLC + 8300 FM 1960 West, Suite 450 + Houston TX 77070 + US + +70-B3-D5 (hex) DimoCore Corporation +AE1000-AE1FFF (base 16) DimoCore Corporation + GoldenBill #930, GwangDukDae-ro 206 + Ahnsan Kyonggi-do 15462 + KR + +70-B3-D5 (hex) AIMCO +3C3000-3C3FFF (base 16) AIMCO + 10000 SE Pine St + Portland OR 97216 + US + +70-B3-D5 (hex) KEVIC. inc, +99A000-99AFFF (base 16) KEVIC. inc, + 5, Nonhyunro 24 Gil, Gangnam-gu + Seoul 06302 + KR + +70-B3-D5 (hex) Xiamen Point Circle Technologh Co,ltd +DB5000-DB5FFF (base 16) Xiamen Point Circle Technologh Co,ltd + S307SouthBuildingWeiYeBuildinPioneering Park,Huli District,Xia M XIAMEN + Xiamen 361000 + CN + +70-B3-D5 (hex) SMTC Corporation +AC6000-AC6FFF (base 16) SMTC Corporation + 2302 Trade Zone Blvd + San Jose 95131 + US + +70-B3-D5 (hex) Hanbat National University +FBE000-FBEFFF (base 16) Hanbat National University + Hanbat National Univ., Deongmyeong-dong, Yuseong-gu + Daejeon 34158 + KR + +70-B3-D5 (hex) Cardinal Scale Mfg Co +268000-268FFF (base 16) Cardinal Scale Mfg Co + 203 E. Daugherty + Webb City MO 64870 + US + +70-B3-D5 (hex) Cottonwood Creek Technologies, Inc. +9EF000-9EFFFF (base 16) Cottonwood Creek Technologies, Inc. + 7108 S. Alton Way, Ste G-102 + Centennial 80112 + US + +70-B3-D5 (hex) TATTILE SRL +AF4000-AF4FFF (base 16) TATTILE SRL + VIA DONIZETTI, 1/3/5 + MAIRANO BRESCIA 25030 + IT + +70-B3-D5 (hex) Hoshin Electronics Co., Ltd. +1C7000-1C7FFF (base 16) Hoshin Electronics Co., Ltd. + 3-9-12, Miyamaedaira, Miyamae-Ku + Kawasaki-Shi Kanagawa 216-0006 + JP + +70-B3-D5 (hex) DermaLumics S.L. +29B000-29BFFF (base 16) DermaLumics S.L. + Ronda de Poniente 16, 1E + Tres Cantos Madrid 28760 + ES + +70-B3-D5 (hex) Presentation Switchers, Inc. +428000-428FFF (base 16) Presentation Switchers, Inc. + 2324 Cheney-Spokane Road + Cheney WA 99004 + US + +70-B3-D5 (hex) DIgSILENT GmbH +FCC000-FCCFFF (base 16) DIgSILENT GmbH + Heinrich-Hertz-Str. 9 + Gomaringen 72810 + DE + +70-B3-D5 (hex) EMPELOR GmbH +76B000-76BFFF (base 16) EMPELOR GmbH + Gubelstr. 12 + Zug Zug 6300 + CH + +70-B3-D5 (hex) Sator Controls s.r.o. +F1A000-F1AFFF (base 16) Sator Controls s.r.o. + Ke Zdravotnímu středisku 103/1 + Praha - Řeporyje Select State 15500 + CZ + +70-B3-D5 (hex) Shanghai JCY Technology Company +F2E000-F2EFFF (base 16) Shanghai JCY Technology Company + 304, 228 Jiang Chang 3rd Road + Shanghai,China Shanghai 200436 + CN + +70-B3-D5 (hex) Sorynorydotcom Inc +38F000-38FFFF (base 16) Sorynorydotcom Inc + 206-1, 2F, 8, Suseong-ro, Gwonseon-gu + Suwon-si Gyeonggi-do 16426 + KR + +70-B3-D5 (hex) Toptech Systems, Inc. +8B9000-8B9FFF (base 16) Toptech Systems, Inc. + 1124 Florida Central Parkway + Longwood FL 32750 + US + +70-B3-D5 (hex) KRONOTECH SRL +FB6000-FB6FFF (base 16) KRONOTECH SRL + VIALE UNGHERIA 125 + UDINE ITALY/UDINE 33100 + IT + +70-B3-D5 (hex) Eva Automation +747000-747FFF (base 16) Eva Automation + 401 Warren Street + Redwood City CA 94063 + US + +70-B3-D5 (hex) Pro-Digital Projetos Eletronicos Ltda +059000-059FFF (base 16) Pro-Digital Projetos Eletronicos Ltda + RUA SENADOR SARAIVA 200 + CURITIBA PR 80510300 + BR + +70-B3-D5 (hex) KZTA +647000-647FFF (base 16) KZTA + S.-Shhedrina + Kaluga 248002 + RU + +70-B3-D5 (hex) Azcom Technology S.r.l. +D51000-D51FFF (base 16) Azcom Technology S.r.l. + Strada 6 Palazzo N2 + Rozzano MI 20089 + IT + +70-B3-D5 (hex) OCEANIX INC. +1A9000-1A9FFF (base 16) OCEANIX INC. + 15703 LAKE LODGE DR + HOUSTON TX 77062 + US + +70-B3-D5 (hex) Xped Corporation Pty Ltd +152000-152FFF (base 16) Xped Corporation Pty Ltd + Innovation House + Mawson Lakes SA 5095 + AU + +70-B3-D5 (hex) SENSING LABS +80A000-80AFFF (base 16) SENSING LABS + CAP OMÉGA - Rond Point Benjamin Franklin + MONTPELLIER 34960 + FR + +70-B3-D5 (hex) ATIM Radiocommunication +9BA000-9BAFFF (base 16) ATIM Radiocommunication + Chemin des Guillets + Villard de Lans 38250 + FR + +70-B3-D5 (hex) YEHL & JORDAN LLC +E02000-E02FFF (base 16) YEHL & JORDAN LLC + 114 Paige Bend + Hutto TX 78634 + US + +70-B3-D5 (hex) VEILUX INC. +4B6000-4B6FFF (base 16) VEILUX INC. + 802 GREENVIEW DR. STE 200 + GRAND PRAIRIE 75050 + US + +70-B3-D5 (hex) CRDE +8A6000-8A6FFF (base 16) CRDE + ZI DES GRANDS CAMPS + MERCUES LOT 46090 + FR + +70-B3-D5 (hex) E-PLUS TECHNOLOGY CO., LTD +B05000-B05FFF (base 16) E-PLUS TECHNOLOGY CO., LTD + 21F, NO.1-145, Zhonghua Rd. + Tainan Yongkang Dist 71084 + TW + +70-B3-D5 (hex) TerOpta Ltd +3CC000-3CCFFF (base 16) TerOpta Ltd + 108 Balmoral Drive + Nottingham NG9 3FT + GB + +70-B3-D5 (hex) ACD Elekronik GmbH +3C6000-3C6FFF (base 16) ACD Elekronik GmbH + Engelberg 2 + Achstetten 88480 + DE + +70-B3-D5 (hex) OutSys +929000-929FFF (base 16) OutSys + Via Caracciolo, 65 + MIlano MI 20155 + IT + +70-B3-D5 (hex) CHARGELIB +EF6000-EF6FFF (base 16) CHARGELIB + 11 CITE VANEAU + PARIS 75007 + FR + +70-B3-D5 (hex) signalparser +214000-214FFF (base 16) signalparser + #901-1 A-dong, Bundang Technopark, 697, Pangyo-ro, Bundang-gu + Seongnam-si Gyeonggi-do 13511 + KR + +70-B3-D5 (hex) Movis +B6D000-B6DFFF (base 16) Movis + Naverland 2, 4. sal + Glostrup Denmark DK-2600 + DK + +70-B3-D5 (hex) IEM SA +2EF000-2EFFFF (base 16) IEM SA + 109 chemin du pont du centenaire + Plan-les-Ouates 1228 + CH + +70-B3-D5 (hex) Shadin Avionics +794000-794FFF (base 16) Shadin Avionics + 6831 Oxford Street + St. Louis Park MN 55426 + US + +70-B3-D5 (hex) Wuhan Xingtuxinke ELectronic Co.,Ltd +B40000-B40FFF (base 16) Wuhan Xingtuxinke ELectronic Co.,Ltd + NO.C3-8F,Software Park,Optics Valley,East Lake Development Zone,Wuhan,Hubei,China + Wuhan Hubei 430074 + CN + +70-B3-D5 (hex) Axotec Technologies GmbH +BAB000-BABFFF (base 16) Axotec Technologies GmbH + Sudetenstraße 88 + Geretsried Bavaria 82538 + DE + +70-B3-D5 (hex) Grupo Epelsa S.L. +76E000-76EFFF (base 16) Grupo Epelsa S.L. + C/ Punto Net,3 + Alcala de Henares Madrid 28805 + ES + +70-B3-D5 (hex) Beijing Aumiwalker technology CO.,LTD +D0E000-D0EFFF (base 16) Beijing Aumiwalker technology CO.,LTD + Floor 6, Tower 1, No.1 Zhonghe Road Fengtai Science Park Beijing P.R.C. + Beijing Beijing 100071 + CN + +70-B3-D5 (hex) Streambox Inc +F6E000-F6EFFF (base 16) Streambox Inc + 1848 Westlake Ave N + Seattle WA 98109 + US + +70-B3-D5 (hex) Schildknecht AG +494000-494FFF (base 16) Schildknecht AG + Haugweg 26 + Murr 71711 + DE + +70-B3-D5 (hex) effectas GmbH +78E000-78EFFF (base 16) effectas GmbH + Bundesstrasse 6 + Zug 6300 + CH + +70-B3-D5 (hex) Spectra Displays Ltd +266000-266FFF (base 16) Spectra Displays Ltd + Unit 25 Lancaster Way Business Park + Ely Cambridgeshire CB6 3NW + GB + +70-B3-D5 (hex) attocube systems AG +D76000-D76FFF (base 16) attocube systems AG + Koeniginstrasse 11A + Muenchen 80997 + DE + +70-B3-D5 (hex) IEEE Registration Authority +9F3000-9F3FFF (base 16) IEEE Registration Authority + 445 Hoes Lane + Piscataway NJ 08554 + US + +70-B3-D5 (hex) Jemac Sweden AB +16E000-16EFFF (base 16) Jemac Sweden AB + Trångsundsvägen 20A + Kalmar 39356 + SE + +70-B3-D5 (hex) ECON Technology Co.Ltd +E93000-E93FFF (base 16) ECON Technology Co.Ltd + Mogan Road 1418-41-4 + Hangzhou Zhejiang 310015 + CN + +70-B3-D5 (hex) Boulder Amplifiers, Inc. +4BD000-4BDFFF (base 16) Boulder Amplifiers, Inc. + 3225 Prairie Avenue + Boulder CO 80301 + US + +70-B3-D5 (hex) AnyComm.Co.,Ltd. +AE0000-AE0FFF (base 16) AnyComm.Co.,Ltd. + 3F, 54, Simin-daero 327beon-gil + Dongan-gu Anyang-si Gyeonggi-do Gyeonggi-do 14055 + KR + +70-B3-D5 (hex) SOREDI touch systems GmbH +001000-001FFF (base 16) SOREDI touch systems GmbH + Werner-von-Siemens-Str. 13 + Olching Bavaria 82140 + DE + +70-B3-D5 (hex) Xerox International Partners +7EB000-7EBFFF (base 16) Xerox International Partners + 3174 Porter Drive + Palo Alto 94304 + US + +70-B3-D5 (hex) TOPROOTTechnology Corp. Ltd. +1E0000-1E0FFF (base 16) TOPROOTTechnology Corp. Ltd. + 5F-8, No. 14, Lane 609, Sec.5, Chongsin Rd., + New Taipei City Taipei 241 + TW + +70-B3-D5 (hex) TriLED +439000-439FFF (base 16) TriLED + Dijkstraat 8 + Ham Limburg 3945 + BE + +70-B3-D5 (hex) DM RADIOCOM +8A0000-8A0FFF (base 16) DM RADIOCOM + CD 908 + 13720 BELCODENE 13380 + FR + +70-B3-D5 (hex) Contraves Advanced Devices Sdn. Bhd. +4D1000-4D1FFF (base 16) Contraves Advanced Devices Sdn. Bhd. + Batu Berendam FTZ, PO Box 39,75700 Malacca, Malaysia. + Melacca No State 75700 + MY + +70-B3-D5 (hex) WyreStorm Technologies Ltd +D59000-D59FFF (base 16) WyreStorm Technologies Ltd + 22 Ergo Business Park, Kelvin Road + Greenbridge Swindon SN3 3JW + GB + +70-B3-D5 (hex) Mobile Devices Unlimited +14F000-14FFFF (base 16) Mobile Devices Unlimited + 1611 North Austin Avenue + Chicago IL 60639-4073 + US + +70-B3-D5 (hex) Sandia National Laboratories +D74000-D74FFF (base 16) Sandia National Laboratories + 1515 Eubank BLVD SE + Albuquerque New Mexico 87123 + US + +70-B3-D5 (hex) IDS Innomic GmbH +37F000-37FFFF (base 16) IDS Innomic GmbH + Zum Buchhorst 35 + Salzwedel Sachsen-Anhalt 29410 + DE + +70-B3-D5 (hex) Gupsy GmbH +100000-100FFF (base 16) Gupsy GmbH + Metzgerstrasse 67 + Aachen NRW 52070 + DE + +70-B3-D5 (hex) KDT +2CE000-2CEFFF (base 16) KDT + 126, Haeoreum-gil, Namsan-myeon + Chuncheon-si Gangwon-do 200-911 + KR + +70-B3-D5 (hex) Beijing Hzhytech Technology Co.Ltd +EE5000-EE5FFF (base 16) Beijing Hzhytech Technology Co.Ltd + The 2th floor,Longzeyuan Multi-use + Beijing 102208 + CN + +70-B3-D5 (hex) Schneider Electric Motion +2EA000-2EAFFF (base 16) Schneider Electric Motion + 370 North Main St + Marlborough CT 06447 + US + +70-B3-D5 (hex) DSP DESIGN +D42000-D42FFF (base 16) DSP DESIGN + TAPTON PK INNOVATION CENTRE + CHESTERFIELD DERBYSHIRE S41 0TZ + GB + +70-B3-D5 (hex) Galea Electric S.L. +A04000-A04FFF (base 16) Galea Electric S.L. + Zeharkale 36, Edificio Izarra Centre + Ermua Bizkaia 48260 + ES + +70-B3-D5 (hex) FIDELTRONIK POLAND SP. Z O.O. +D12000-D12FFF (base 16) FIDELTRONIK POLAND SP. Z O.O. + Beniowskiego 1 + + PL + +70-B3-D5 (hex) Chromalox, Inc. +84E000-84EFFF (base 16) Chromalox, Inc. + 1347 Heil Quaker Blvd + La Vergne TN 37086 + US + +70-B3-D5 (hex) Sicon srl +04D000-04DFFF (base 16) Sicon srl + Via Sila 1/3 + Isola Vicentina Vicenza 36033 + IT + +70-B3-D5 (hex) Flashnet SRL +BF1000-BF1FFF (base 16) Flashnet SRL + Str. Fundatura Harmanului nr.4A + Brasov Brasov 500240 + RO + +70-B3-D5 (hex) AeroVision Avionics, Inc. +DDF000-DDFFFF (base 16) AeroVision Avionics, Inc. + 2F, No.30, R&D Rd. II, + Hsinchu City Hsinchu City 30076 + TW + +70-B3-D5 (hex) Micram Instruments Ltd +774000-774FFF (base 16) Micram Instruments Ltd + 5 The Parade + Auckland 2012 + NZ + +70-B3-D5 (hex) SARL S@TIS +933000-933FFF (base 16) SARL S@TIS + 19, Rue de Bretagne + Saint Quentin Fallavier Rhone-Alpes 38070 + FR + +70-B3-D5 (hex) Allim System Co,.Ltd. +48E000-48EFFF (base 16) Allim System Co,.Ltd. + #605, E&C Venture Dream Tower 6Cha, + Seoul Seoul 152-179 + KR + +70-B3-D5 (hex) Benchmark Electronics BV +9ED000-9EDFFF (base 16) Benchmark Electronics BV + Lelyweg 10 + Almelo Overijssel 7602 EA + NL + +70-B3-D5 (hex) Refecor Oy +DF7000-DF7FFF (base 16) Refecor Oy + Isokatu 8A1 + OULU FInland 90100 + FI + +70-B3-D5 (hex) ARD +C89000-C89FFF (base 16) ARD + MICROPOLIS + GAP CEDEX paca 05005 + FR + +70-B3-D5 (hex) Kalycito Infotech Private Limited +43B000-43BFFF (base 16) Kalycito Infotech Private Limited + 6/2 & 6/3,Pappampatti Pirivu, Trichy Road, + Coimbatore Tamil Nadu 641103 + IN + +70-B3-D5 (hex) NetBoxSC, LLC +852000-852FFF (base 16) NetBoxSC, LLC + 43774 Bemis Road + Belleville MI 48111 + US + +70-B3-D5 (hex) Mes Communication Co., Ltd +A93000-A93FFF (base 16) Mes Communication Co., Ltd + 5F, No. 6 , Szu Wei Lane , Chung Cheng + New Taipei City 231 + TW + +70-B3-D5 (hex) VideoRay LLC +CD6000-CD6FFF (base 16) VideoRay LLC + 212 E High Street + Pottstown Pennsylvania 19464 + US + +70-B3-D5 (hex) Movidius SRL +32F000-32FFFF (base 16) Movidius SRL + Str Gh Lazar, Nb24 + Timisoara - 300081 + RO + +70-B3-D5 (hex) Data Sciences International +7C1000-7C1FFF (base 16) Data Sciences International + 119 14th St. NW + St. Paul MN 55112 + US + +70-B3-D5 (hex) SERIAL IMAGE INC. +166000-166FFF (base 16) SERIAL IMAGE INC. + 16530 Ventura Blvd. + Encino California 91436 + US + +70-B3-D5 (hex) PLR Prueftechnik Linke und Ruehe GmbH +595000-595FFF (base 16) PLR Prueftechnik Linke und Ruehe GmbH + Altenhaeuser Str. 6 + Magdeburg Saxony-Anhalt 39126 + DE + +70-B3-D5 (hex) Oso Technologies, Inc. +4DE000-4DEFFF (base 16) Oso Technologies, Inc. + 722 W KILLARNEY ST + Urbana Illinois 61801 + US + +70-B3-D5 (hex) Abitsoftware, Ltd. +3D8000-3D8FFF (base 16) Abitsoftware, Ltd. + Passfield Business Centre + Passfield, Liphook Hampshire GU30 7SB + GB + +70-B3-D5 (hex) IMST GmbH +8FF000-8FFFFF (base 16) IMST GmbH + Carl-Friedrich-Gauss-Str. 2-4 + Kamp-Lintfort Northrhine-Westfalia 47475 + DE + +70-B3-D5 (hex) KITRON UAB +470000-470FFF (base 16) KITRON UAB + TAIKOS 151 + KAUNAS KAUNAS LT-52119 + LT + +70-B3-D5 (hex) Peter Huber +2E0000-2E0FFF (base 16) Peter Huber + Kaeltemaschinenbau GmbH + Offenburg Ba-Wue 77656 + DE + +70-B3-D5 (hex) ATX NETWORKS LTD +F1E000-F1EFFF (base 16) ATX NETWORKS LTD + Halapid 12 st + Petach tikva Israel 4917001 + IL + +70-B3-D5 (hex) Korea Plant Maintenance +DF9000-DF9FFF (base 16) Korea Plant Maintenance + 102 DTC Tower + Seongnam-si Gyeonggi-do 463-400 + KR + +70-B3-D5 (hex) Hella Gutmann Solutions GmbH +F93000-F93FFF (base 16) Hella Gutmann Solutions GmbH + Am Krebsbach 2 + Ihringen BW 79241 + DE + +70-B3-D5 (hex) C21 Systems Ltd +7E4000-7E4FFF (base 16) C21 Systems Ltd + Dunston Innovation Centre + Chesterfield Derbyshire S41 8NG + GB + +70-B3-D5 (hex) Magosys Systems LTD +00E000-00EFFF (base 16) Magosys Systems LTD + Gad Feinstein 13 + Rehovot 7638517 + IL + +70-B3-D5 (hex) Kvazar LLC +2D6000-2D6FFF (base 16) Kvazar LLC + 200-letiya goroda 2 + Noginsk Moscow region 142400 + RU + +70-B3-D5 (hex) Evolute Systems Private Limited +D2D000-D2DFFF (base 16) Evolute Systems Private Limited + Sri Rama, 15/6, 3rd Floor + Bangalore Karnataka 560008 + IN + +70-B3-D5 (hex) Guidance Navigation Limited +E36000-E36FFF (base 16) Guidance Navigation Limited + 4 Dominus Way + Leicester Leicestershire LE19 1RP + GB + +70-B3-D5 (hex) DEUTA-WERKE GmbH +08F000-08FFFF (base 16) DEUTA-WERKE GmbH + Paffrather Str. 140 + Bergisch Gladbach North Rhine-Westphalia 51465 + DE + +70-B3-D5 (hex) Isabellenhütte Heusler Gmbh &Co KG +F8E000-F8EFFF (base 16) Isabellenhütte Heusler Gmbh &Co KG + Eibacherweg 3-5 + Dillenburg Hessen 35683 + DE + +70-B3-D5 (hex) Lemonade Lab Inc +AD6000-AD6FFF (base 16) Lemonade Lab Inc + 1-10-8 Nishi-Azabu + Minato-ku Tokyo 106-0031 + JP + +70-B3-D5 (hex) Shanghai Tianhe Automation Instrumentation Co., Ltd. +AFB000-AFBFFF (base 16) Shanghai Tianhe Automation Instrumentation Co., Ltd. + room 501, block D, No. 100, lane 2891, Qilianshan Nan road, + Shanghai Shanghai 200331 + CN + +70-B3-D5 (hex) iLOQ Oy +CFD000-CFDFFF (base 16) iLOQ Oy + Yrttipellontie 10 + Oulu EMEA 90230 + FI + +70-B3-D5 (hex) C.D.N.CORPORATION +C73000-C73FFF (base 16) C.D.N.CORPORATION + 1-18-22 Ohtsubo-higashi,Miyazaki-Ciy + Miyazaki Miyazaki 880-0934 + JP + +70-B3-D5 (hex) bentrup Industriesteuerungen +870000-870FFF (base 16) bentrup Industriesteuerungen + Zum Buchwald 4-6 + Fernwald Hessia 35463 + DE + +70-B3-D5 (hex) Apogee Applied Research, Inc. +FBA000-FBAFFF (base 16) Apogee Applied Research, Inc. + 4401 Dayton Xenia Rd + Dayton Ohio 45432 + US + +70-B3-D5 (hex) Synaccess Networks Inc. +336000-336FFF (base 16) Synaccess Networks Inc. + 75 W. Baseline Rd. + Gilbert AZ 85233 + US + +70-B3-D5 (hex) Zigen Corp +D87000-D87FFF (base 16) Zigen Corp + 6934 Canby Avenue + Reseda CA 91335 + US + +70-B3-D5 (hex) LSB - LA SALLE BLANCHE +7B7000-7B7FFF (base 16) LSB - LA SALLE BLANCHE + RN 100 + APT EN PROVENCE 84 84400 + FR + +70-B3-D5 (hex) Liquid Instruments Pty Ltd +87B000-87BFFF (base 16) Liquid Instruments Pty Ltd + 31 Pokana Cct + Kaleen ACT 2617 + AU + +70-B3-D5 (hex) Ducommun Inc. +583000-583FFF (base 16) Ducommun Inc. + 700 Braddock Avenue + East Pittsburgh PA 15112 + US + +70-B3-D5 (hex) Versilis Inc. +4D8000-4D8FFF (base 16) Versilis Inc. + 4295 St-Elzear Ouest + Laval Quebec h7p4j3 + CA + +70-B3-D5 (hex) LayTec AG +995000-995FFF (base 16) LayTec AG + Seesener Str. 10 13 + Berlin Berlin 10709 + DE + +70-B3-D5 (hex) Talleres de Escoriaza +0DC000-0DCFFF (base 16) Talleres de Escoriaza + Barrio Ventas 35 + Irun Gipuzkoa 20305 + ES + +70-B3-D5 (hex) Exi Flow Measurement Ltd +7AE000-7AEFFF (base 16) Exi Flow Measurement Ltd + Unit 22 Ford Lane business Park + Ford, ARUNDEL West Sussex BN164HP + GB + +70-B3-D5 (hex) Integrated Systems Engineering, Inc. +48C000-48CFFF (base 16) Integrated Systems Engineering, Inc. + 600 South Holmes, STE 4 + St. Louis Missouri 63122 + US + +70-B3-D5 (hex) New Japan Radio Co., Ltd +AF3000-AF3FFF (base 16) New Japan Radio Co., Ltd + 2-1-1 Fukuoka + Fujimino Saitama 356-8510 + JP + +70-B3-D5 (hex) Trinity Solutions LLC +AC9000-AC9FFF (base 16) Trinity Solutions LLC + PO Box 309 + Mt. Nebo West Virginia 26679 + US + +70-B3-D5 (hex) Kumu Networks +01C000-01CFFF (base 16) Kumu Networks + 960 Hamlin Court + Sunnyvale California 94089 + US + +70-B3-D5 (hex) Nation-E Ltd. +DE8000-DE8FFF (base 16) Nation-E Ltd. + 89 Medinat hayehudim St. + Herziliya IL 4676672 + IL + +70-B3-D5 (hex) Sonel S.A. +775000-775FFF (base 16) Sonel S.A. + Wokulskiego 11 + Swidnica Dolnoslaskie 58-100 + PL + +70-B3-D5 (hex) CDR SRL +BDD000-BDDFFF (base 16) CDR SRL + VIA DEGLI ARTIGIANI 6 + GINESTRA FIORENTINA FLORENCE 50055 + IT + +70-B3-D5 (hex) Novo DR Ltd. +300000-300FFF (base 16) Novo DR Ltd. + 40 HaAtsmaut Road + Yehud - Please Choose - 5630417 + IL + +70-B3-D5 (hex) Hengen Technologies GmbH +F2C000-F2CFFF (base 16) Hengen Technologies GmbH + Vogesenstrasse 19a + Landau Rheinland-Pfalz 76829 + DE + +70-B3-D5 (hex) DEV Systemtechnik GmbH& Co KG +418000-418FFF (base 16) DEV Systemtechnik GmbH& Co KG + Gruener Weg 4A + Friedberg Hessen 61169 + DE + +70-B3-D5 (hex) ATEME +AA7000-AA7FFF (base 16) ATEME + 26 Burospace + Bievres IDF 91470 + + +70-B3-D5 (hex) Farmobile +13F000-13FFFF (base 16) Farmobile + 18132 Melrose Dr. + Bucyrus KS 66013 + + +70-B3-D5 (hex) Code Blue Corporation +C3F000-C3FFFF (base 16) Code Blue Corporation + 259 Hedcor St + Holland MI 49423 + US + +70-B3-D5 (hex) RF-Tuote Oy +849000-849FFF (base 16) RF-Tuote Oy + Joensuunkatu 13 + Salo 24130 + FI + +70-B3-D5 (hex) Sienda New Media Technologies GmbH +A81000-A81FFF (base 16) Sienda New Media Technologies GmbH + Lange Gasse 90 + Basel Basel-land 4052 + CH + +70-B3-D5 (hex) Logiwaste AB +D0D000-D0DFFF (base 16) Logiwaste AB + Gamla Stallet Stora Wäsby + Upplands Väsby Upplands Väsby 194 37 + SE + +70-B3-D5 (hex) Teenage Engineering AB +1AF000-1AFFFF (base 16) Teenage Engineering AB + Katarina Bangata 71 + Stockholm n/a 11642 + SE + +70-B3-D5 (hex) ConectaIP Tecnologia S.L. +D7F000-D7FFFF (base 16) ConectaIP Tecnologia S.L. + Novell 58, 4.2 + Barcelona 08014 + ES + +70-B3-D5 (hex) Bizwerks, LLC +A97000-A97FFF (base 16) Bizwerks, LLC + 1201 East 15th Street + Plano TX 75074 + US + +70-B3-D5 (hex) SerEnergy A/S +7B8000-7B8FFF (base 16) SerEnergy A/S + Lyngvej 8 + Aalborg Denmark 9000 + DK + +70-B3-D5 (hex) KST technology +3DB000-3DBFFF (base 16) KST technology + 164-1, KST b/d., Bangi-dong, songpa-gu + SEOUL N/A 138-050 + KR + +70-B3-D5 (hex) KLS Netherlands B.V. +DCF000-DCFFFF (base 16) KLS Netherlands B.V. + Buitenvaart 1401 + HOOGEVEEN DRENTHE 7905 SJ + NL + +70-B3-D5 (hex) TechOne +F92000-F92FFF (base 16) TechOne + 6-20-13-803, Chuo + Fukutsu Fukuoka 8113217 + JP + +70-B3-D5 (hex) Embest Technology Co., Ltd +A55000-A55FFF (base 16) Embest Technology Co., Ltd + Tower B 4/F, Shanshui Building, , Liuxian Ave. No. 1183, Taoyuan St., + Nanshan District, Shenzhen Gangdong Province 518055 + CN + +70-B3-D5 (hex) PulseTor LLC +A25000-A25FFF (base 16) PulseTor LLC + 1580 Reed Road + Pennington NJ 08534 + US + +70-B3-D5 (hex) Embsec AB +D1F000-D1FFFF (base 16) Embsec AB + Propellervagen 10 + Taby Taby 18362 + SE + +70-B3-D5 (hex) Tokyo Drawing Ltd. +164000-164FFF (base 16) Tokyo Drawing Ltd. + 103 Ni Terai-machi + Nomi-shi Ishikawa 923-1121 + JP + +70-B3-D5 (hex) Zulex International Co.,Ltd. +959000-959FFF (base 16) Zulex International Co.,Ltd. + 52/54 M.6 Talingchan-Suphanburi rd., + Bangyai Nonthaburi 11140 + TH + +70-B3-D5 (hex) Prolan Process Control Co. +FF5000-FF5FFF (base 16) Prolan Process Control Co. + Szentendrei út 1-3. + Budakalász HUngary 2013 + HU + +70-B3-D5 (hex) Seneco A/S +327000-327FFF (base 16) Seneco A/S + Bøgekildevej 4 + Hasselager Danmark 8361 + DK + +70-B3-D5 (hex) COMM-connect A/S +ECE000-ECEFFF (base 16) COMM-connect A/S + Raasigvangen 2 + Slangerup DK-3550 + DK + +70-B3-D5 (hex) IHI Inspection & Instrumentation Co., Ltd. +344000-344FFF (base 16) IHI Inspection & Instrumentation Co., Ltd. + 1-100, Takamatsu-Cho, + Tachikawa-Shi Tokyo 190-0011 + JP + +70-B3-D5 (hex) KMtronic Ltd. +6D6000-6D6FFF (base 16) KMtronic Ltd. + Dobri Czintulov 28A str. + Gorna Oryahovica VT 5100 + BG + +70-B3-D5 (hex) EIWA GIKEN INC. +BA4000-BA4FFF (base 16) EIWA GIKEN INC. + 5-708 FUSHIYA NAKAGAWA-KU + NAGOYA AICHI-PREFECTURE 454-0996 + JP + +70-B3-D5 (hex) JC HUNTER TECHNOLOGIES +C61000-C61FFF (base 16) JC HUNTER TECHNOLOGIES + 185 Custer St. Apt. 4 + Lander wy 82520 + US + +70-B3-D5 (hex) nVideon, Inc. +3B8000-3B8FFF (base 16) nVideon, Inc. + 3170 Sugarplum Rd. NE + Atlanta GA 30345 + US + +70-B3-D5 (hex) Private +220000-220FFF (base 16) Private + +70-B3-D5 (hex) Christ Elektronik GmbH +A5B000-A5BFFF (base 16) Christ Elektronik GmbH + Alpenstrasse 34 + Memmingen Bayern 87700 + DE + +70-B3-D5 (hex) FUJI DATA SYSTEM CO.,LTD. +E92000-E92FFF (base 16) FUJI DATA SYSTEM CO.,LTD. + 5-21-14 + AMAGASAKI-SHI HYOGO PREF 660-0892 + JP + +70-B3-D5 (hex) EUROPEAN ADVANCED TECHNOLOGIES +F8C000-F8CFFF (base 16) EUROPEAN ADVANCED TECHNOLOGIES + VIA CARDUCCI 32 + MILANO MILANO 20123 + IT + +70-B3-D5 (hex) SENSYS GmbH +F2B000-F2BFFF (base 16) SENSYS GmbH + Rabenfelde 5 + Bad Saarow/OT Neu Golm Brandenburg 15526 + DE + +70-B3-D5 (hex) Siemens Healthcare Diagnostics +20C000-20CFFF (base 16) Siemens Healthcare Diagnostics + 62 Flanders Bartley Road + Flanders NJ 07836 + US + +70-B3-D5 (hex) Hatteland Display AS +BC6000-BC6FFF (base 16) Hatteland Display AS + Pb. 446 Alnabru + Oslo Oslo N-0614 + NO + +70-B3-D5 (hex) MultiDyne +3DF000-3DFFFF (base 16) MultiDyne + 191 Forest Ave + Locust Valley NY 11560 + US + +70-B3-D5 (hex) Reonix Automation +0B3000-0B3FFF (base 16) Reonix Automation + #10 - 3716 56 ave SE + Calgary Alberta T2C2B5 + CA + +70-B3-D5 (hex) Molu Technology Inc., LTD. +0C0000-0C0FFF (base 16) Molu Technology Inc., LTD. + NO. 25, Ln., 230, Zhonghe Rd., + Zhonghe Dist. New Taipei City 235 + TW + +70-B3-D5 (hex) Aditec GmbH +3CE000-3CEFFF (base 16) Aditec GmbH + Talweg 17 + Offenau Baden-Wuerttemberg 74254 + DE + +70-B3-D5 (hex) IAI-Israel Aerospace Industries MBT +E4C000-E4CFFF (base 16) IAI-Israel Aerospace Industries MBT + 1 Altalef st. + Yehud Yehud 5610001 + IL + +70-B3-D5 (hex) Excel Medical Electronics LLC +DC5000-DC5FFF (base 16) Excel Medical Electronics LLC + 801 Maplewood Dr. + Jupiter Florida 33458 + US + +70-B3-D5 (hex) FEITIAN CO.,LTD. +E26000-E26FFF (base 16) FEITIAN CO.,LTD. + 7-F,7-15-17 Roppongi + MINATOKU TOKYO 106-0032 + JP + +70-B3-D5 (hex) Advitronics telecom bv +E99000-E99FFF (base 16) Advitronics telecom bv + Garnizoenstraat 1 + Velp (nb) Noord brabant 5363 VX + NL + +70-B3-D5 (hex) Asiga +362000-362FFF (base 16) Asiga + 2/36 Albert Street + St Peters NSW 2044 + AU + +70-B3-D5 (hex) Weigl Elektronik & Mediaprojekte +01D000-01DFFF (base 16) Weigl Elektronik & Mediaprojekte + Limberg 3 + Gramastetten Oberoesterreich 4201 + AT + +70-B3-D5 (hex) P&C Micro's Pty Ltd +6F2000-6F2FFF (base 16) P&C Micro's Pty Ltd + 14 Ricketts Road + Mount Waverley Victoria 3149 + AU + +70-B3-D5 (hex) Meiknologic GmbH +2E3000-2E3FFF (base 16) Meiknologic GmbH + Hölderlinweg 19a + Darmstadt Hessen 64285 + DE + +70-B3-D5 (hex) eSOL Co.,Ltd. +45E000-45EFFF (base 16) eSOL Co.,Ltd. + 8-1-31 + saitama 336-0026 + JP + +70-B3-D5 (hex) Chugoku Electric Manufacturing Co.,Inc +5AA000-5AAFFF (base 16) Chugoku Electric Manufacturing Co.,Inc + Ozu 4-4-32 + Minami-ku, Hirosima-shi HIROSHIMA 732-0802 + JP + +70-B3-D5 (hex) Eltwin A/S +FC5000-FC5FFF (base 16) Eltwin A/S + Torsoevej 1b + Risskov Aarhus 8240 + DK + +70-B3-D5 (hex) «Intellect module» LLC +819000-819FFF (base 16) «Intellect module» LLC + Krasnogo kursanta str. 25 lit. J + Saint-Petersburg 197110 + RU + +70-B3-D5 (hex) Skywave Networks Private Limited +2DA000-2DAFFF (base 16) Skywave Networks Private Limited + Achyut Mansion,H.No 7-1-621/48,Flat No 201,Above Sindhu Travels, + Hyderabad Andhra Pradesh 500038 + IN + +70-B3-D5 (hex) Guardian Controls International Ltd +016000-016FFF (base 16) Guardian Controls International Ltd + 56 Crewe Road + Sandbach Cheshire CW11 4NN + GB + +70-B3-D5 (hex) Heartland.Data Inc. +AC8000-AC8FFF (base 16) Heartland.Data Inc. + 361 Fukui-Cho + Ashikaga-City Tochigi-Pref 326-0338 + JP + +70-B3-D5 (hex) christmann informationstechnik + medien GmbH & Co. KG +564000-564FFF (base 16) christmann informationstechnik + medien GmbH & Co. KG + Ilseder Huette 10c + Ilsede Niedersachsen 31241 + DE + +70-B3-D5 (hex) IST ElektronikgesmbH +60C000-60CFFF (base 16) IST ElektronikgesmbH + Marktplatz 40 + Neukirchen am Walde Upper Austria 4724 + AT + +70-B3-D5 (hex) Kongsberg Intergrated Tactical Systems +EF2000-EF2FFF (base 16) Kongsberg Intergrated Tactical Systems + 10 Pinehurst Dr + Bellport New York 11713 + US + +70-B3-D5 (hex) Barnstormer Softworks +3E1000-3E1FFF (base 16) Barnstormer Softworks + 837 N Grant St. + Wooster OH 44691 + US + +70-B3-D5 (hex) Sudo Premium Engineering +052000-052FFF (base 16) Sudo Premium Engineering + Seoch dong, Seocho gu + ASI|KR|KS013|SEOUL + KR + +70-B3-D5 (hex) Vetaphone A/S +A0E000-A0EFFF (base 16) Vetaphone A/S + Fabriksvej 11 + Kolding Region syddanmark 6000 + DK + +70-B3-D5 (hex) Power Diagnostic Service +F61000-F61FFF (base 16) Power Diagnostic Service + No.5, Aly. 2, Ln. 261, Yanping Rd, + Hsinchu City Hsinchu County 300 + TW + +70-B3-D5 (hex) Flexsolution APS +433000-433FFF (base 16) Flexsolution APS + Østervangsvej 39 + Esbjerg N Jylland 6715 + DK + +70-B3-D5 (hex) MacGray Services +F34000-F34FFF (base 16) MacGray Services + 404 Wyman St + Waltham MA 02451 + + +70-B3-D5 (hex) AKIS technologies +FD3000-FD3FFF (base 16) AKIS technologies + Ciurlionio g. 82 + Vilnius Lithuania 03100 + LT + +70-B3-D5 (hex) BBI Engineering, Inc. +FA1000-FA1FFF (base 16) BBI Engineering, Inc. + 241 Quint Street + San Francisco California 94124 + US + +70-B3-D5 (hex) Tecnint HTE SRL +51D000-51DFFF (base 16) Tecnint HTE SRL + Via della Tecnica 16/18 + Osnago Lecco 23875 + IT + +70-B3-D5 (hex) Tband srl +9F4000-9F4FFF (base 16) Tband srl + Via A. Meucci, 4 + Preganziol Treviso 31022 + IT + +70-B3-D5 (hex) JamHub Corp. +3A8000-3A8FFF (base 16) JamHub Corp. + One Main Street + Whitinsville MA 01588 + US + +70-B3-D5 (hex) Monroe Electronics, Inc. +40A000-40AFFF (base 16) Monroe Electronics, Inc. + 100 Housel Avenue + Lyndonville NY 14098 + US + +70-B3-D5 (hex) J.D. Koftinoff Software, Ltd. +EDC000-EDCFFF (base 16) J.D. Koftinoff Software, Ltd. + 4-3600 Pleasant Valley Rd. + Vernon B.C V1T4L6 + CA + +70-B3-D5 (hex) Inras GmbH +B3D000-B3DFFF (base 16) Inras GmbH + Altenberger Straße 69 + Linz Oberösterreich A-4040 + AT + +70-B3-D5 (hex) Tunstall A/S +139000-139FFF (base 16) Tunstall A/S + Niels Bohrs vej 42 + Stilling Skanderborg 8660 + DK + +70-B3-D5 (hex) Evco S.p.a. +183000-183FFF (base 16) Evco S.p.a. + Via Feltre 81 + Sedico Belluno 32036 + IT + +70-B3-D5 (hex) Cellular Specialties, Inc. +3C2000-3C2FFF (base 16) Cellular Specialties, Inc. + 670 North Commercial Avenue, + Manchester NH 03101 + US + +00-1B-C5 (hex) TN Core Co.,Ltd. +0BF000-0BFFFF (base 16) TN Core Co.,Ltd. + 707, Daerung Post Tower 6, 50-3 + Seoul - 153715 + KR + +00-1B-C5 (hex) Digital Loggers, Inc. +0C0000-0C0FFF (base 16) Digital Loggers, Inc. + 2695 Walsh Avenue + Santa Clara CA 95051 + US + +00-1B-C5 (hex) Autelis, LLC +0B7000-0B7FFF (base 16) Autelis, LLC + 1820 W Calle De Pompas + Phoenix Arizona 85085 + US + +00-1B-C5 (hex) Techlan Reti s.r.l. +0AE000-0AEFFF (base 16) Techlan Reti s.r.l. + Via delle mondine 8 a/b + Carpi Modena 41012 + IT + +00-1B-C5 (hex) P A Network Laboratory Co.,Ltd +0A3000-0A3FFF (base 16) P A Network Laboratory Co.,Ltd + 2-12-10 Takanami Bld.3kai, Shiba, Minato-ku, Tokyo, 105-0014, Japan + Minato-ku Tokyo 1050014 + JP + +00-1B-C5 (hex) S.I.C.E.S. srl +09C000-09CFFF (base 16) S.I.C.E.S. srl + Via Molinello, 8B + Jerago con Orago VARESE 21040 + IT + +00-1B-C5 (hex) Cubic Systems, Inc. +098000-098FFF (base 16) Cubic Systems, Inc. + 139 Dino Drive + Ann Arbor MI 48103 + US + +00-1B-C5 (hex) EUREK SRL +08D000-08DFFF (base 16) EUREK SRL + VIA CELLETTA 8/B + IMOLA BOLOGNA 40026 + US + +00-1B-C5 (hex) SIGNATURE CONTROL SYSTEMS, INC. +089000-089FFF (base 16) SIGNATURE CONTROL SYSTEMS, INC. + 18 GOODYEAR STE 110 + IRVINE CA 92618 + US + +00-1B-C5 (hex) UAB Kitron +088000-088FFF (base 16) UAB Kitron + Taikos pr. 151 + Kaunas LT-52119 + LT + +00-1B-C5 (hex) WonATech Co., Ltd. +081000-081FFF (base 16) WonATech Co., Ltd. + 171-17 + Seocho-Gu Seoul 137-180 + KR + +00-1B-C5 (hex) HPI High Pressure Instrumentation GmbH +079000-079FFF (base 16) HPI High Pressure Instrumentation GmbH + Ueberfuhrgasse 37 + Graz Steiermark 8020 + AT + +00-1B-C5 (hex) LLC Emzior +06F000-06FFFF (base 16) LLC Emzior + Strelna, Svyazi Street, 34, Lit A, of. 234 + Saint-Petersburg 198515 + RU + +00-1B-C5 (hex) Siemens Industries, Inc, Retail & Commercial Systems +070000-070FFF (base 16) Siemens Industries, Inc, Retail & Commercial Systems + 9225 Bee Caves Rd + Austin TX 78733 + US + +00-1B-C5 (hex) Verified Energy, LLC. +06B000-06BFFF (base 16) Verified Energy, LLC. + PO Box 111 + Oneida New York 13421 + US + +00-1B-C5 (hex) Luxcon System Limited +06C000-06CFFF (base 16) Luxcon System Limited + Rm1605, SEAVIEW PLAZA, 283 SHAUKEIWAN RD, + HongKong + HK + +00-1B-C5 (hex) Two Dimensional Instruments, LLC +06E000-06EFFF (base 16) Two Dimensional Instruments, LLC + P O Box 159 + Crestwood KY 40014 + US + +00-1B-C5 (hex) Sulaon Oy +062000-062FFF (base 16) Sulaon Oy + Muuraintie 6 + Salo 24280 + FI + +00-1B-C5 (hex) Plair Media Inc. +065000-065FFF (base 16) Plair Media Inc. + 2901 Tasman Drive + Santa Clara California 95054 + US + +00-1B-C5 (hex) JSC Prominform +05D000-05DFFF (base 16) JSC Prominform + Gazeti Zvezda str., 24A + Perm Permskiy krai 614000 + RU + +00-1B-C5 (hex) Private +054000-054FFF (base 16) Private + +00-1B-C5 (hex) OOO Actidata +040000-040FFF (base 16) OOO Actidata + Bolshaya Pochtovaya 36 Bldg 10 + Moscow 105082 + RU + +00-1B-C5 (hex) EURESYS S.A. +039000-039FFF (base 16) EURESYS S.A. + Avenue du Pre-Aily 14 + ANGLEUR LIEGE 4031 + BE + +00-1B-C5 (hex) RTLS Ltd. +035000-035FFF (base 16) RTLS Ltd. + 42 Bol. Gruzinskaya str. + Moscow 123056 + RU + +00-1B-C5 (hex) Rose + Herleth GbR +01D000-01DFFF (base 16) Rose + Herleth GbR + Wendenweg 17 + Berlin 13595 + DE + +00-1B-C5 (hex) ABA ELECTRONICS TECHNOLOGY CO.,LTD +01A000-01AFFF (base 16) ABA ELECTRONICS TECHNOLOGY CO.,LTD + 10F-3,NO.2,SEC.4,JHONGYANG RD,TUCHENG CITY, + TAIPEI 236 + TW + +00-1B-C5 (hex) Zamir Recognition Systems Ltd. +013000-013FFF (base 16) Zamir Recognition Systems Ltd. + Manachat Tech Park 1/22 + Jerusalem 96951 + IL + +00-1B-C5 (hex) OOO NPP Mera +011000-011FFF (base 16) OOO NPP Mera + Pionerskaya 4 + Korolev Moscow reg 141070 + RU + +00-1B-C5 (hex) Private +005000-005FFF (base 16) Private + +00-1B-C5 (hex) TRIAX-HIRSCHMANN Multi-Media GmbH +006000-006FFF (base 16) TRIAX-HIRSCHMANN Multi-Media GmbH + Karl-Benz-Strasse 10 + Pliezhausen Baden-Württemberg 72124 + DE + +00-1B-C5 (hex) Energy Aware Technology +007000-007FFF (base 16) Energy Aware Technology + Suite 515 + Vancouver BC V6A3X3 + CA + +00-1B-C5 (hex) Private +00B000-00BFFF (base 16) Private + +70-B3-D5 (hex) Deep BV +55F000-55FFFF (base 16) Deep BV + Johan van Hasseltweg 39d + Amsterdam 1021KN + NL + +70-B3-D5 (hex) SHEN ZHEN QLS ELECTRONIC TECHNOLOGY CO.,LTD. +6E3000-6E3FFF (base 16) SHEN ZHEN QLS ELECTRONIC TECHNOLOGY CO.,LTD. + Room A1502, NiuLanQian Building, MinZhi Road, LongHua Town + ShenZhen GuangDong 518109 + CN + +70-B3-D5 (hex) Xavant +1EB000-1EBFFF (base 16) Xavant + 309 Derdepoort Rylaan, Silverton + Pretoria Gauteng 0181 + ZA + +70-B3-D5 (hex) Argosy Labs Inc. +E5B000-E5BFFF (base 16) Argosy Labs Inc. + 490 Canal St #14 + San Rafael CA 94901 + US + +70-B3-D5 (hex) Brayden Automation Corp +B19000-B19FFF (base 16) Brayden Automation Corp + 6230 Aviation Circle + Loveland CO 80538 + US + +70-B3-D5 (hex) Aditec GmbH +A38000-A38FFF (base 16) Aditec GmbH + Talweg 17 + Offenau Baden-Wuerttemberg 74254 + DE + +70-B3-D5 (hex) Elektro Adrian +FF6000-FF6FFF (base 16) Elektro Adrian + Via Garibaldi no.1 + Predazzo Trento 38037 + IT + +70-B3-D5 (hex) PEEK TRAFFIC +691000-691FFF (base 16) PEEK TRAFFIC + 5401 N SAM HOUSTON PKWY W + HOUSTON 77086 + US + +70-B3-D5 (hex) Dataflex International BV +52A000-52AFFF (base 16) Dataflex International BV + van Nassauweg 2-6 + Krimpen aan den IJssel Zuid-Holland 2921 LX + NL + +70-B3-D5 (hex) MATELEX +372000-372FFF (base 16) MATELEX + 26, AVENUE DU PETIT PARC + VINCENNES 94683 + FR + +70-B3-D5 (hex) ETL Elektrotechnik Lauter GmbH +DE3000-DE3FFF (base 16) ETL Elektrotechnik Lauter GmbH + Konrad-Zuse-Str. 2 + Mauerstetten Bavaria 87665 + DE + +70-B3-D5 (hex) Light field Lab +D27000-D27FFF (base 16) Light field Lab + 699 E Brokaw Rd + San Jose CA 95112 + US + +70-B3-D5 (hex) CENSIS, Uiversity of Glasgow +1C2000-1C2FFF (base 16) CENSIS, Uiversity of Glasgow + 121 George Street + Glasgow G1 1RD + GB + +70-B3-D5 (hex) Solarlytics, Inc. +366000-366FFF (base 16) Solarlytics, Inc. + 288 Lindbergh Avenue + LIVERMORE CA 94551 + US + +70-B3-D5 (hex) Phytron GmbH +7BE000-7BEFFF (base 16) Phytron GmbH + Industriestr. 12 + Groebenzell Bayern 82194 + DE + +70-B3-D5 (hex) KSE GmbH +38A000-38AFFF (base 16) KSE GmbH + Frühlingstraße 31-33 + Ingolstadt 85055 + DE + +70-B3-D5 (hex) Maytronics Ltd. +90E000-90EFFF (base 16) Maytronics Ltd. + + + + +70-B3-D5 (hex) InterTalk Critical Information Systems +5D0000-5D0FFF (base 16) InterTalk Critical Information Systems + 371 Cutler Avenue + Dartmouth Nova Scotia B3B 0J5 + CA + +70-B3-D5 (hex) fpgalabs.com +BA5000-BA5FFF (base 16) fpgalabs.com + p.Moskovskiy, d. Rumyantsevo, str.4 + Moscow 108811 + RU + +70-B3-D5 (hex) Gstar Creation Co .,Ltd +A67000-A67FFF (base 16) Gstar Creation Co .,Ltd + 1F NO53 Jimay Street san chong district + New Taipei 241 + TW + +70-B3-D5 (hex) JSC Kaluga Astral +E89000-E89FFF (base 16) JSC Kaluga Astral + Tsyolkovsky 4 + Kaluga Kaluga 248000 + RU + +70-B3-D5 (hex) Sunsa, Inc +BFF000-BFFFFF (base 16) Sunsa, Inc + 3422 Fait Ave + Baltimore MD 21224 + US + +70-B3-D5 (hex) Dream D&S Co.,Ltd +E8B000-E8BFFF (base 16) Dream D&S Co.,Ltd + 6F, 8, Jungdae-ro 8-gil, Songpa-gu + Seoul 05833 + KR + +70-B3-D5 (hex) FTG Corporation +017000-017FFF (base 16) FTG Corporation + 10 Commander Blvd. + Ajax Ontario M1S 3T2 + CA + +70-B3-D5 (hex) AddSecure Smart Grids +126000-126FFF (base 16) AddSecure Smart Grids + Campus Gräsvik 1 + Karlskrona 37175 + SE + +70-B3-D5 (hex) Changchun FAW Yanfeng Visteon Automotive Electronics.,Ltd. +93B000-93BFFF (base 16) Changchun FAW Yanfeng Visteon Automotive Electronics.,Ltd. + No.2338 Guanggu Street Changchun City + chang chun ji lin 130000 + CN + +70-B3-D5 (hex) Pantec AG +A98000-A98FFF (base 16) Pantec AG + Industriering 21 + Ruggell 9491 + LI + +70-B3-D5 (hex) Shachihata Inc. +51A000-51AFFF (base 16) Shachihata Inc. + 37 , SHINMEI-CHO , KOUWA + INAZAWA AICHI 492-8102 + JP + +70-B3-D5 (hex) Wartsila Voyage Limited +AE2000-AE2FFF (base 16) Wartsila Voyage Limited + 13-18 City Quay + Dublin 2 D02 ED70 + IE + +70-B3-D5 (hex) Unisight Digital Products +2D8000-2D8FFF (base 16) Unisight Digital Products + 99 Inverness Drive East, Suite#180 + Englewood CO 80112 + US + +70-B3-D5 (hex) H2O-YUG LLC +BDF000-BDFFFF (base 16) H2O-YUG LLC + Uralskaya st. 87/1 k + Krasnodar Krasnodarskiy krai 350059 + RU + +70-B3-D5 (hex) QBIC COMMUNICATIONS DMCC +8AF000-8AFFFF (base 16) QBIC COMMUNICATIONS DMCC + Office 302 1Lake Plaza Jumeirah Lake Towers Cluster T + Dubai 393518 + AE + +70-B3-D5 (hex) Softel +9A5000-9A5FFF (base 16) Softel + 35 bld 9, Nizhnyaya Krasnosel'skaya Ulitsa + Moscow 105066 + RU + +70-B3-D5 (hex) Shanghai Danyan Information Technology Co., Ltd. +1B1000-1B1FFF (base 16) Shanghai Danyan Information Technology Co., Ltd. + 12D, Building 7, 2388, Chenhang Road, Minhang District + Shanghai Shanghai 201114 + CN + +70-B3-D5 (hex) Innovative Control Systems, LP +89E000-89EFFF (base 16) Innovative Control Systems, LP + 10801 N. 24th Ave Ste 102 + Phoenix AZ 85029 + US + +70-B3-D5 (hex) ACD Elekronik GmbH +DA2000-DA2FFF (base 16) ACD Elekronik GmbH + Engelberg 2 + Achstetten 88480 + DE + +70-B3-D5 (hex) Chengdu Meihuan Technology Co., Ltd +C95000-C95FFF (base 16) Chengdu Meihuan Technology Co., Ltd + Floor 17, Building D6, Tianfu Software Park, + Chengdu Sichuan 610041 + CN + +70-B3-D5 (hex) The Fire Horn, Inc. +3F8000-3F8FFF (base 16) The Fire Horn, Inc. + 1212 Helen St + Paducah KY 42001 + US + +70-B3-D5 (hex) Absolent AB +EFC000-EFCFFF (base 16) Absolent AB + Staplaregatan 1 + Lidköping 53140 + SE + +70-B3-D5 (hex) Barracuda Measurement Solutions +FFA000-FFAFFF (base 16) Barracuda Measurement Solutions + 33434 FM 529 + brookshire TX 77423 + US + +70-B3-D5 (hex) Booz Allen Hamilton +A24000-A24FFF (base 16) Booz Allen Hamilton + 1900 West Park Drive, Suite 205 + Westborough 01581 + US + +70-B3-D5 (hex) Mothonic AB +8E6000-8E6FFF (base 16) Mothonic AB + Krouthéns Gata 8 + Linköping 582 55 + SE + +70-B3-D5 (hex) OOO Research and Production Center Computer Technologies +262000-262FFF (base 16) OOO Research and Production Center Computer Technologies + Komsomolsky avenue, 90-17 + Perm Perm Region 614010 + RU + +70-B3-D5 (hex) Digital Systems Engineering +034000-034FFF (base 16) Digital Systems Engineering + 17491 N. 93rd St. + Scottsdale AZ 85255 + US + +70-B3-D5 (hex) Lumiplan Duhamel +BB1000-BB1FFF (base 16) Lumiplan Duhamel + 2 rue de l'industrie + Domène Isère 38420 + FR + +70-B3-D5 (hex) Clear Flow by Antiference +1CE000-1CEFFF (base 16) Clear Flow by Antiference + Fradley Distribution Park, Wood End Lane + Lichfield Staffordshire WS13 8NE + GB + +70-B3-D5 (hex) SenseNL +8C0000-8C0FFF (base 16) SenseNL + Ambachtsweg 41 F + Pijnacker Zuid-Holland 2641 KT + NL + +70-B3-D5 (hex) LEMZ-T, LLC +306000-306FFF (base 16) LEMZ-T, LLC + Razvitia pr., 8 + Tomsk 634031 + RU + +70-B3-D5 (hex) LEAFF ENGINEERING SRL +34B000-34BFFF (base 16) LEAFF ENGINEERING SRL + Via Pastore 10 + Osimo AN 60027 + IT + +70-B3-D5 (hex) CONTES, spol. s r.o. +E2A000-E2AFFF (base 16) CONTES, spol. s r.o. + U podolskeho hrbitova 667/6 + Prague 14700 + CZ + +70-B3-D5 (hex) Braemar Manufacturing, LLC +93A000-93AFFF (base 16) Braemar Manufacturing, LLC + 1285 Corporate Center Drive Suite 150 + Eagan MN 55121 + US + +70-B3-D5 (hex) Potter Electric Signal Co. LLC +F5D000-F5DFFF (base 16) Potter Electric Signal Co. LLC + 1609 Park 370 Place + Hazelwood MO 63042 + US + +70-B3-D5 (hex) Viotec USA +899000-899FFF (base 16) Viotec USA + 3 East Third Ave + San Mateo CA 94401 + US + +70-B3-D5 (hex) Eredi Giuseppe Mercuri SPA +6CE000-6CEFFF (base 16) Eredi Giuseppe Mercuri SPA + via Cupa Vicinale S.Aniello, 88 + Naples 80146 + IT + +70-B3-D5 (hex) ITK Dr. Kassen GmbH +58A000-58AFFF (base 16) ITK Dr. Kassen GmbH + Beim Eberacker 3 + D-35633 Lahnau + DE + +70-B3-D5 (hex) RCH Vietnam Limited Liability Company +88E000-88EFFF (base 16) RCH Vietnam Limited Liability Company + Workshop F.01B-2, Lot No. F.01B Long Hau + Ho Chi Minh City Ho Chi Minh 70000 + VN + +70-B3-D5 (hex) Privafy, Inc +A6A000-A6AFFF (base 16) Privafy, Inc + 2 Burlington Woods Dr. Suite 200 + Burlington MA 01803 + US + +70-B3-D5 (hex) Contec Americas Inc. +5D2000-5D2FFF (base 16) Contec Americas Inc. + 3991 Sarno Rd + Melbourne FL 32934 + US + +70-B3-D5 (hex) elements +62D000-62DFFF (base 16) elements + Townsgate Road Suite 200 + Westlake Village CA 91361 + US + +70-B3-D5 (hex) DAT Informatics Pvt Ltd +244000-244FFF (base 16) DAT Informatics Pvt Ltd + Plot No 109 HPSIDC Industria Estate Davni, Baddi + Baddi HIMACHAL PRADESH 173205 + IN + +70-B3-D5 (hex) Abbott Diagnostics Technologies AS +6C6000-6C6FFF (base 16) Abbott Diagnostics Technologies AS + P. O. Box 6863 Rodeløkka + Oslo Oslo 0504 + NO + +70-B3-D5 (hex) RCH Vietnam Limited Liability Company +6BD000-6BDFFF (base 16) RCH Vietnam Limited Liability Company + Workshop F.01B-2, Lot No. F.01B Long Hau + Ho Chi Minh City Ho Chi Minh 70000 + VN + +70-B3-D5 (hex) Gamber Johnson-LLC +E34000-E34FFF (base 16) Gamber Johnson-LLC + 3001 Borham Ave + Stevens Point WI 54481 + US + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +C2B000-C2BFFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) YUYAMA MFG Co.,Ltd +1F2000-1F2FFF (base 16) YUYAMA MFG Co.,Ltd + 3-3-1 + TOYONAKASHI OSAKA 561-0841 + JP + +70-B3-D5 (hex) QUALITTEQ LLC +614000-614FFF (base 16) QUALITTEQ LLC + 16th Parkovaya 26/1 + Moscow 105484 + RU + +70-B3-D5 (hex) Adcole Maryland Aerospace +922000-922FFF (base 16) Adcole Maryland Aerospace + 669 Forest St + Marlborough MA 01752 + US + +70-B3-D5 (hex) eSMART Technologies SA +979000-979FFF (base 16) eSMART Technologies SA + Chemin de la Rueyre, 118 + Renens VD 1020 + CH + +70-B3-D5 (hex) Axnes AS +65F000-65FFFF (base 16) Axnes AS + Terje Løvåsvei 1 + Grimstad 4879 + NO + +70-B3-D5 (hex) Duplomatic MS spa +DE1000-DE1FFF (base 16) Duplomatic MS spa + Via Re Depaolini 24 + Parabiago Milan 20015 + IT + +70-B3-D5 (hex) Nanjing Pingguang Electronic Technology Co., Ltd +541000-541FFF (base 16) Nanjing Pingguang Electronic Technology Co., Ltd + B30/B31 4th Floor, Building#11, Shengtai Road, JiangNing District + NanJing 211100 + CN + +70-B3-D5 (hex) thingdust AG +3C1000-3C1FFF (base 16) thingdust AG + Moosstrasse 7 + Lucerne Lucerne 6003 + CH diff --git a/hwdb.d/meson.build b/hwdb.d/meson.build new file mode 100644 index 00000000..1f73a8bb --- /dev/null +++ b/hwdb.d/meson.build @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +hwdb_files = files(''' + 20-pci-vendor-model.hwdb + 20-pci-classes.hwdb + 20-usb-vendor-model.hwdb + 20-usb-classes.hwdb + 20-sdio-vendor-model.hwdb + 20-sdio-classes.hwdb + 20-bluetooth-vendor-product.hwdb + 20-acpi-vendor.hwdb + 20-OUI.hwdb + 20-net-ifname.hwdb + 20-vmbus-class.hwdb + 60-evdev.hwdb + 60-keyboard.hwdb + 60-sensor.hwdb + 70-joystick.hwdb + 70-mouse.hwdb + 70-pointingstick.hwdb + 70-touchpad.hwdb +'''.split()) + +if conf.get('ENABLE_HWDB') == 1 + install_data(hwdb_files, + install_dir : udevhwdbdir) + + meson.add_install_script('sh', '-c', + mkdir_p.format(join_paths(sysconfdir, 'udev/hwdb.d'))) + + meson.add_install_script('sh', '-c', + 'test -n "$DESTDIR" || @0@/systemd-hwdb update' + .format(rootbindir)) +endif + +############################################################ + +parse_hwdb_py = find_program('parse_hwdb.py') +if want_tests != 'false' + test('parse-hwdb', + parse_hwdb_py, + timeout : 90) +endif + +############################################################ + +run_target( + 'hwdb-update', + command : [hwdb_update_sh, meson.current_source_dir()]) + +run_target( + 'autosuspend-update', + command : [autosuspend_update_sh, project_source_root + '/tools/chromiumos']) diff --git a/hwdb.d/parse_hwdb.py b/hwdb.d/parse_hwdb.py new file mode 100755 index 00000000..b5395b11 --- /dev/null +++ b/hwdb.d/parse_hwdb.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: MIT +# +# This file is distributed under the MIT license, see below. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import glob +import string +import sys +import os + +try: + from pyparsing import (Word, White, Literal, ParserElement, Regex, LineEnd, + OneOrMore, Combine, Or, Optional, Suppress, Group, + nums, alphanums, printables, + stringEnd, pythonStyleComment, QuotedString, + ParseBaseException) +except ImportError: + print('pyparsing is not available') + sys.exit(77) + +try: + from evdev.ecodes import ecodes +except ImportError: + ecodes = None + print('WARNING: evdev is not available') + +try: + from functools import lru_cache +except ImportError: + # don't do caching on old python + lru_cache = lambda: (lambda f: f) + +EOL = LineEnd().suppress() +EMPTYLINE = LineEnd() +COMMENTLINE = pythonStyleComment + EOL +INTEGER = Word(nums) +STRING = QuotedString('"') +REAL = Combine((INTEGER + Optional('.' + Optional(INTEGER))) ^ ('.' + INTEGER)) +SIGNED_REAL = Combine(Optional(Word('-+')) + REAL) +UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_') + +TYPES = {'mouse': ('usb', 'bluetooth', 'ps2', '*'), + 'evdev': ('name', 'atkbd', 'input'), + 'id-input': ('modalias'), + 'touchpad': ('i8042', 'rmi', 'bluetooth', 'usb'), + 'joystick': ('i8042', 'rmi', 'bluetooth', 'usb'), + 'keyboard': ('name', ), + 'sensor': ('modalias', ), + } + +@lru_cache() +def hwdb_grammar(): + ParserElement.setDefaultWhitespaceChars('') + + prefix = Or(category + ':' + Or(conn) + ':' + for category, conn in TYPES.items()) + matchline = Combine(prefix + Word(printables + ' ' + '®')) + EOL + propertyline = (White(' ', exact=1).suppress() + + Combine(UDEV_TAG - '=' - Word(alphanums + '_=:@*.!-;, "') - Optional(pythonStyleComment)) + + EOL) + propertycomment = White(' ', exact=1) + pythonStyleComment + EOL + + group = (OneOrMore(matchline('MATCHES*') ^ COMMENTLINE.suppress()) - + OneOrMore(propertyline('PROPERTIES*') ^ propertycomment.suppress()) - + (EMPTYLINE ^ stringEnd()).suppress()) + commentgroup = OneOrMore(COMMENTLINE).suppress() - EMPTYLINE.suppress() + + grammar = OneOrMore(Group(group)('GROUPS*') ^ commentgroup) + stringEnd() + + return grammar + +@lru_cache() +def property_grammar(): + ParserElement.setDefaultWhitespaceChars(' ') + + dpi_setting = (Optional('*')('DEFAULT') + INTEGER('DPI') + Suppress('@') + INTEGER('HZ'))('SETTINGS*') + mount_matrix_row = SIGNED_REAL + ',' + SIGNED_REAL + ',' + SIGNED_REAL + mount_matrix = (mount_matrix_row + ';' + mount_matrix_row + ';' + mount_matrix_row)('MOUNT_MATRIX') + + props = (('MOUSE_DPI', Group(OneOrMore(dpi_setting))), + ('MOUSE_WHEEL_CLICK_ANGLE', INTEGER), + ('MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL', INTEGER), + ('MOUSE_WHEEL_CLICK_COUNT', INTEGER), + ('MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL', INTEGER), + ('ID_INPUT', Literal('1')), + ('ID_INPUT_ACCELEROMETER', Literal('1')), + ('ID_INPUT_JOYSTICK', Literal('1')), + ('ID_INPUT_KEY', Literal('1')), + ('ID_INPUT_KEYBOARD', Literal('1')), + ('ID_INPUT_MOUSE', Literal('1')), + ('ID_INPUT_POINTINGSTICK', Literal('1')), + ('ID_INPUT_SWITCH', Literal('1')), + ('ID_INPUT_TABLET', Literal('1')), + ('ID_INPUT_TABLET_PAD', Literal('1')), + ('ID_INPUT_TOUCHPAD', Literal('1')), + ('ID_INPUT_TOUCHSCREEN', Literal('1')), + ('ID_INPUT_TRACKBALL', Literal('1')), + ('MOUSE_WHEEL_TILT_HORIZONTAL', Literal('1')), + ('MOUSE_WHEEL_TILT_VERTICAL', Literal('1')), + ('POINTINGSTICK_SENSITIVITY', INTEGER), + ('POINTINGSTICK_CONST_ACCEL', REAL), + ('ID_INPUT_JOYSTICK_INTEGRATION', Or(('internal', 'external'))), + ('ID_INPUT_TOUCHPAD_INTEGRATION', Or(('internal', 'external'))), + ('XKB_FIXED_LAYOUT', STRING), + ('XKB_FIXED_VARIANT', STRING), + ('XKB_FIXED_MODEL', STRING), + ('KEYBOARD_LED_NUMLOCK', Literal('0')), + ('KEYBOARD_LED_CAPSLOCK', Literal('0')), + ('ACCEL_MOUNT_MATRIX', mount_matrix), + ('ACCEL_LOCATION', Or(('display', 'base'))), + ) + fixed_props = [Literal(name)('NAME') - Suppress('=') - val('VALUE') + for name, val in props] + kbd_props = [Regex(r'KEYBOARD_KEY_[0-9a-f]+')('NAME') + - Suppress('=') - + ('!' ^ (Optional('!') - Word(alphanums + '_')))('VALUE') + ] + abs_props = [Regex(r'EVDEV_ABS_[0-9a-f]{2}')('NAME') + - Suppress('=') - + Word(nums + ':')('VALUE') + ] + + grammar = Or(fixed_props + kbd_props + abs_props) + EOL + + return grammar + +ERROR = False +def error(fmt, *args, **kwargs): + global ERROR + ERROR = True + print(fmt.format(*args, **kwargs)) + +def convert_properties(group): + matches = [m[0] for m in group.MATCHES] + props = [p[0] for p in group.PROPERTIES] + return matches, props + +def parse(fname): + grammar = hwdb_grammar() + try: + with open(fname, 'r', encoding='UTF-8') as f: + parsed = grammar.parseFile(f) + except ParseBaseException as e: + error('Cannot parse {}: {}', fname, e) + return [] + return [convert_properties(g) for g in parsed.GROUPS] + +def check_match_uniqueness(groups): + matches = sum((group[0] for group in groups), []) + matches.sort() + prev = None + for match in matches: + if match == prev: + error('Match {!r} is duplicated', match) + prev = match + +def check_one_default(prop, settings): + defaults = [s for s in settings if s.DEFAULT] + if len(defaults) > 1: + error('More than one star entry: {!r}', prop) + +def check_one_mount_matrix(prop, value): + numbers = [s for s in value if s not in {';', ','}] + if len(numbers) != 9: + error('Wrong accel matrix: {!r}', prop) + try: + numbers = [abs(float(number)) for number in numbers] + except ValueError: + error('Wrong accel matrix: {!r}', prop) + bad_x, bad_y, bad_z = max(numbers[0:3]) == 0, max(numbers[3:6]) == 0, max(numbers[6:9]) == 0 + if bad_x or bad_y or bad_z: + error('Mount matrix is all zero in {} row: {!r}', + 'x' if bad_x else ('y' if bad_y else 'z'), + prop) + +def check_one_keycode(prop, value): + if value != '!' and ecodes is not None: + key = 'KEY_' + value.upper() + if not (key in ecodes or + value.upper() in ecodes or + # new keys added in kernel 5.5 + 'KBD_LCD_MENU' in key): + error('Keycode {} unknown', key) + +def check_properties(groups): + grammar = property_grammar() + for matches, props in groups: + prop_names = set() + for prop in props: + # print('--', prop) + prop = prop.partition('#')[0].rstrip() + try: + parsed = grammar.parseString(prop) + except ParseBaseException as e: + error('Failed to parse: {!r}', prop) + continue + # print('{!r}'.format(parsed)) + if parsed.NAME in prop_names: + error('Property {} is duplicated', parsed.NAME) + prop_names.add(parsed.NAME) + if parsed.NAME == 'MOUSE_DPI': + check_one_default(prop, parsed.VALUE.SETTINGS) + elif parsed.NAME == 'ACCEL_MOUNT_MATRIX': + check_one_mount_matrix(prop, parsed.VALUE) + elif parsed.NAME.startswith('KEYBOARD_KEY_'): + val = parsed.VALUE if isinstance(parsed.VALUE, str) else parsed.VALUE[0] + check_one_keycode(prop, val) + +def print_summary(fname, groups): + n_matches = sum(len(matches) for matches, props in groups) + n_props = sum(len(props) for matches, props in groups) + print('{}: {} match groups, {} matches, {} properties' + .format(fname, len(groups), n_matches, n_props)) + + if n_matches == 0 or n_props == 0: + error('{}: no matches or props'.format(fname)) + +if __name__ == '__main__': + args = sys.argv[1:] or sorted(glob.glob(os.path.dirname(sys.argv[0]) + '/[67][0-9]-*.hwdb')) + + for fname in args: + groups = parse(fname) + print_summary(fname, groups) + check_match_uniqueness(groups) + check_properties(groups) + + sys.exit(ERROR) diff --git a/hwdb.d/pci.ids b/hwdb.d/pci.ids new file mode 100644 index 00000000..59407399 --- /dev/null +++ b/hwdb.d/pci.ids @@ -0,0 +1,32441 @@ +# +# List of PCI ID's +# +# Version: 2020.01.25 +# Date: 2020-01-25 03:15:02 +# +# Maintained by Albert Pool, Martin Mares, and other volunteers from +# the PCI ID Project at https://pci-ids.ucw.cz/. +# +# New data are always welcome, especially if they are accurate. If you have +# anything to contribute, please follow the instructions at the web site. +# +# This file can be distributed under either the GNU General Public License +# (version 2 or higher) or the 3-clause BSD License. +# +# The database is a compilation of factual data, and as such the copyright +# only covers the aggregation and formatting. The copyright is held by +# Martin Mares and Albert Pool. +# + +# Vendors, devices and subsystems. Please keep sorted. + +# Syntax: +# vendor vendor_name +# device device_name <-- single tab +# subvendor subdevice subsystem_name <-- two tabs + +0001 SafeNet (wrong ID) +0010 Allied Telesis, Inc (Wrong ID) +# This is a relabelled RTL-8139 + 8139 AT-2500TX V3 Ethernet +0014 Loongson Technology LLC + 7a00 Hyper Transport Bridge Controller + 7a02 APB (Advanced Peripheral Bus) Controller + 7a03 Gigabit Ethernet Controller + 7a04 OTG USB Controller + 7a05 Vivante GPU (Graphics Processing Unit) + 7a06 DC (Display Controller) + 7a07 HDA (High Definition Audio) Controller + 7a08 SATA AHCI Controller + 7a09 PCI-to-PCI Bridge + 7a0b SPI Controller + 7a0c LPC Controller + 7a0f DMA (Direct Memory Access) Controller + 7a14 EHCI USB Controller + 7a15 Vivante GPU (Graphics Processing Unit) + 7a19 PCI-to-PCI Bridge + 7a24 OHCI USB Controller + 7a29 PCI-to-PCI Bridge +001c PEAK-System Technik GmbH + 0001 PCAN-PCI CAN-Bus controller + 001c 0004 2 Channel CAN Bus SJC1000 + 001c 0005 2 Channel CAN Bus SJC1000 (Optically Isolated) +003d Lockheed Martin-Marietta Corp +# Real TJN ID is e159, but they got it wrong several times --mj +0059 Tiger Jet Network Inc. (Wrong ID) +0070 Hauppauge computer works Inc. + 7801 WinTV HVR-1800 MCE +0071 Nebula Electronics Ltd. +0095 Silicon Image, Inc. (Wrong ID) + 0680 Ultra ATA/133 IDE RAID CONTROLLER CARD +# Wrong ID used in subsystem ID of the TELES.S0/PCI 2.x ISDN adapter +00a7 Teles AG (Wrong ID) +0100 nCipher Security +0123 General Dynamics +0128 Dell (wrong ID) +# 018a is not LevelOne but there is a board misprogrammed +018a LevelOne + 0106 FPC-0106TX misprogrammed [RTL81xx] +# 021b is not Compaq but there is a board misprogrammed +021b Compaq Computer Corporation + 8139 HNE-300 (RealTek RTL8139c) [iPaq Networking] +0270 Hauppauge computer works Inc. (Wrong ID) +0291 Davicom Semiconductor, Inc. (Wrong ID) +# SpeedStream is Efficient Networks, Inc, a Siemens Company +02ac SpeedStream + 1012 1012 PCMCIA 10/100 Ethernet Card [RTL81xx] +02e0 XFX Pine Group Inc. (Wrong ID) +0303 Hewlett-Packard Company (Wrong ID) +0308 ZyXEL Communications Corporation (Wrong ID) +0315 SK-Electronics Co., Ltd. +0357 TTTech Computertechnik AG (Wrong ID) + 000a TTP-Monitoring Card V2.0 +0432 SCM Microsystems, Inc. + 0001 Pluto2 DVB-T Receiver for PCMCIA [EasyWatch MobilSet] +0497 Dell Inc. (wrong ID) +0675 Dynalink + 1700 IS64PH ISDN Adapter + 1702 IS64PH ISDN Adapter + 1703 ISDN Adapter (PCI Bus, DV, W) + 1704 ISDN Adapter (PCI Bus, D, C) +0721 Sapphire, Inc. +0777 Ubiquiti Networks, Inc. +0795 Wired Inc. + 6663 Butane II (MPEG2 encoder board) + 6666 MediaPress (MPEG2 encoder board) +07d1 D-Link System Inc +0824 T1042 [Freescale] +0925 VIA Technologies, Inc. (Wrong ID) +0a89 BREA Technologies Inc +0b0b Rhino Equipment Corp. + 0105 R1T1 + 0205 R4FXO + 0206 RCB4FXO 4-channel FXO analog telephony card + 0305 R4T1 + 0405 R8FXX + 0406 RCB8FXX 8-channel modular analog telephony card + 0505 R24FXX + 0506 RCB24FXS 24-Channel FXS analog telephony card + 0605 R2T1 + 0705 R24FXS + 0706 RCB24FXO 24-Channel FXO analog telephony card + 0905 R1T3 Single T3 Digital Telephony Card + 0906 RCB24FXX 24-channel modular analog telephony card + 0a06 RCB672FXX 672-channel modular analog telephony card +0e11 Compaq Computer Corporation + 0001 PCI to EISA Bridge + 0002 PCI to ISA Bridge + 0046 Smart Array 64xx + 0e11 4091 Smart Array 6i + 0e11 409a Smart Array 641 + 0e11 409b Smart Array 642 + 0e11 409c Smart Array 6400 + 0e11 409d Smart Array 6400 EM + 0049 NC7132 Gigabit Upgrade Module + 004a NC6136 Gigabit Server Adapter + 005a Remote Insight II board - Lights-Out + 007c NC7770 1000BaseTX + 007d NC6770 1000BaseTX + 0085 NC7780 1000BaseTX + 00b1 Remote Insight II board - PCI device + 00bb NC7760 + 00ca NC7771 + 00cb NC7781 + 00cf NC7772 + 00d0 NC7782 + 00d1 NC7783 + 00e3 NC7761 + 0508 Netelligent 4/16 Token Ring + 1000 Triflex/Pentium Bridge, Model 1000 + 2000 Triflex/Pentium Bridge, Model 2000 + 3032 QVision 1280/p + 3033 QVision 1280/p + 3034 QVision 1280/p + 4000 4000 [Triflex] + 4040 Integrated Array + 4048 Compaq Raid LC2 + 4050 Smart Array 4200 + 4051 Smart Array 4250ES + 4058 Smart Array 431 + 4070 Smart Array 5300 + 4080 Smart Array 5i + 4082 Smart Array 532 + 4083 Smart Array 5312 + 4091 Smart Array 6i + 409a Smart Array 641 + 409b Smart Array 642 + 409c Smart Array 6400 + 409d Smart Array 6400 EM + 6010 HotPlug PCI Bridge 6010 + 7020 USB Controller + a0ec Fibre Channel Host Controller + a0f0 Advanced System Management Controller + 0e11 b0f3 ProLiant DL360 + a0f3 Triflex PCI to ISA Bridge + a0f7 PCI Hotplug Controller + 8086 002a PCI Hotplug Controller A + 8086 002b PCI Hotplug Controller B + a0f8 ZFMicro Chipset USB + a0fc FibreChannel HBA Tachyon + ae10 Smart-2/P RAID Controller + 0e11 4030 Smart-2/P Array Controller + 0e11 4031 Smart-2SL Array Controller + 0e11 4032 Smart Array 3200 Controller + 0e11 4033 Smart Array 3100ES Controller + 0e11 4034 Smart Array 221 Controller + ae29 MIS-L + ae2a MPC + ae2b MIS-E + ae31 System Management Controller + ae32 Netelligent 10/100 TX PCI UTP + ae33 Triflex Dual EIDE Controller + ae34 Netelligent 10 T PCI UTP + ae35 Integrated NetFlex-3/P + ae40 Netelligent Dual 10/100 TX PCI UTP + ae43 Netelligent Integrated 10/100 TX UTP + ae69 CETUS-L + ae6c Northstar + ae6d NorthStar CPU to PCI Bridge + b011 Netelligent 10/100 TX Embedded UTP + b012 Netelligent 10 T/2 PCI UTP/Coax + b01e NC3120 Fast Ethernet NIC + b01f NC3122 Fast Ethernet NIC + b02f NC1120 Ethernet NIC + b030 Netelligent 10/100 TX UTP + b04a 10/100 TX PCI Intel WOL UTP Controller + b060 Smart Array 5300 Controller + b0c6 NC3161 Fast Ethernet NIC + b0c7 NC3160 Fast Ethernet NIC + b0d7 NC3121 Fast Ethernet NIC + b0dd NC3131 Fast Ethernet NIC + b0de NC3132 Fast Ethernet Module + b0df NC6132 Gigabit Module + b0e0 NC6133 Gigabit Module + b0e1 NC3133 Fast Ethernet Module + b123 NC6134 Gigabit NIC + b134 NC3163 Fast Ethernet NIC + b13c NC3162 Fast Ethernet NIC + b144 NC3123 Fast Ethernet NIC + b163 NC3134 Fast Ethernet NIC + b164 NC3165 Fast Ethernet Upgrade Module + b178 Smart Array 5i/532 + 0e11 4080 Smart Array 5i + 0e11 4082 Smart Array 532 + 0e11 4083 Smart Array 5312 + b1a4 NC7131 Gigabit Server Adapter + b200 Memory Hot-Plug Controller + b203 Integrated Lights Out Controller + b204 Integrated Lights Out Processor + c000 Remote Insight Lights-Out Edition + f130 NetFlex-3/P ThunderLAN 1.0 + f150 NetFlex-3/P ThunderLAN 2.3 +0e55 HaSoTec GmbH +0eac SHF Communication Technologies AG + 0008 Ethernet Powerlink Managing Node 01 +0f62 Acrox Technologies Co., Ltd. +1000 Broadcom / LSI + 0001 53c810 + 1000 1000 LSI53C810AE PCI to SCSI I/O Processor + 0002 53c820 + 0003 53c825 + 1000 1000 LSI53C825AE PCI to SCSI I/O Processor (Ultra Wide) + 0004 53c815 + 0005 53c810AP + 0006 53c860 + 1000 1000 LSI53C860E PCI to Ultra SCSI I/O Processor + 000a 53c1510 + 0e11 b143 Integrated Dual Channel Wide Ultra2 SCSI Controller + 1000 1000 LSI53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Nonintelligent mode) + 000b 53C896/897 + 0e11 6004 EOB003 Series SCSI host adapter + 1000 1000 LSI53C896/7 PCI to Dual Channel Ultra2 SCSI Multifunction Controller + 1000 1010 LSI22910 PCI to Dual Channel Ultra2 SCSI host adapter + 1000 1020 LSI21002 PCI to Dual Channel Ultra2 SCSI host adapter + 13e9 1000 6221L-4U (Dual U2W SCSI, dual 10/100TX, graphics) + 000c 53c895 + 1000 1010 LSI8951U PCI to Ultra2 SCSI host adapter + 1000 1020 LSI8952U PCI to Ultra2 SCSI host adapter + 1de1 3906 DC-390U2B SCSI adapter + 1de1 3907 DC-390U2W + 000d 53c885 + 000f 53c875 + 0e11 7004 Embedded Ultra Wide SCSI Controller + 1000 1000 LSI53C876/E PCI to Dual Channel SCSI Controller + 1000 1010 LSI22801 PCI to Dual Channel Ultra SCSI host adapter + 1000 1020 LSI22802 PCI to Dual Channel Ultra SCSI host adapter + 1092 8760 FirePort 40 Dual SCSI Controller + 1775 10d0 V5D Single Board Computer Wide Ultra SCSI + 1775 10d1 V5D Single Board Computer Ultra SCSI + 1de1 3904 DC390F/U Ultra Wide SCSI Adapter + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1050 CT7 mainboard + 0010 53C1510 + 0e11 4040 Integrated Smart Array Controller + 0e11 4048 RAID LC2 Controller + 1000 1000 53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Intelligent mode) + 0012 53c895a + 1000 1000 LSI53C895A PCI to Ultra2 SCSI Controller + 0013 53c875a + 1000 1000 LSI53C875A PCI to Ultra SCSI Controller + 0014 MegaRAID Tri-Mode SAS3516 + 1028 1f3a PERC H745 Adapter + 1028 1f3b PERC H745 Front + 1028 1fd4 PERC H745P MX + 1137 020e UCSC-RAID-M5 12G Modular RAID Controller + 1d49 0602 ThinkSystem RAID 930-16i 4GB Flash PCIe 12Gb Adapter + 1d49 0604 ThinkSystem RAID 930-8e 4GB Flash PCIe 12Gb Adapter + 1d49 0607 ThinkSystem RAID 930-16i 8GB Flash PCIe 12Gb Adapter + 8086 352d Integrated RAID Module RMSP3AD160F + 8086 9460 RAID Controller RSP3TD160F + 8086 9480 RAID Controller RSP3MD088F + 0015 MegaRAID Tri-Mode SAS3416 + 1028 1f3c PERC H345 Adapter + 1028 1f3d PERC H345 Front + 1d49 0503 ThinkSystem RAID 530-16i PCIe 12Gb Adapter + 0016 MegaRAID Tri-Mode SAS3508 + 1028 1fc9 PERC H840 Adapter + 1028 1fcb PERC H740P Adapter + 1028 1fcd PERC H740P Mini + 1028 1fcf PERC H740P Mini + 1d49 0601 ThinkSystem RAID 930-8i 2GB Flash PCIe 12Gb Adapter + 1d49 0603 ThinkSystem RAID 930-24i 4GB Flash PCIe 12Gb Adapter + 8086 352e Integrated RAID Module RMSP3CD080F + 8086 352f Integrated RAID Module RMSP3HD080E + 8086 9461 RAID Controller RSP3DD080F + 0017 MegaRAID Tri-Mode SAS3408 + 1d49 0500 ThinkSystem RAID 530-8i PCIe 12Gb Adapter + 1d49 0502 ThinkSystem RAID 530-8i Dense Adapter + 8086 3528 Integrated RAID RMSP3LD060 + 8086 3529 Integrated RAID RMSP3LD060 + 8086 9441 RAID Controller RSP3WD080E + 001b MegaRAID Tri-Mode SAS3504 + 1d49 0605 ThinkSystem RAID 930-4i 2GB Flash Flex Adapter + 001c MegaRAID Tri-Mode SAS3404 + 1d49 0501 ThinkSystem RAID 530-4i Flex Adapter + 0020 53c1010 Ultra3 SCSI Adapter + 1000 1000 LSI53C1010-33 PCI to Dual Channel Ultra160 SCSI Controller + 107b 1040 Server Onboard 53C1010-33 + 1de1 1020 DC-390U3W + 0021 53c1010 66MHz Ultra3 SCSI Adapter + 1000 1000 LSI53C1000/1000R/1010R/1010-66 PCI to Ultra160 SCSI Controller + 1000 1010 Asus TR-DLS onboard 53C1010-66 + 103c 1300 Ultra160 SCSI [AB306A] + 103c 1310 Ultra160 SCSI [A9918A] + 103c 1330 Ultra160 SCSI [A7059A] + 103c 1340 Ultra160 SCSI [A7060A] + 124b 1070 PMC-USCSI3 + 4c53 1080 CT8 mainboard + 4c53 1300 P017 mezzanine (32-bit PMC) + 4c53 1310 P017 mezzanine (64-bit PMC) + 002f MegaRAID SAS 2208 IOV [Thunderbolt] + 1028 1f39 SPERC8-e + 1028 1f3e SPERC 8 + 0030 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI + 0e11 00da ProLiant ML 350 + 1028 0123 LSI Logic 1020/1030 + 1028 014a LSI Logic 1020/1030 + 1028 016c PowerEdge 1850 MPT Fusion SCSI/RAID (Perc 4) + 1028 0183 LSI Logic 1020/1030 + 1028 018a PERC 4/IM + 1028 1010 LSI U320 SCSI Controller + 103c 12c5 Ultra320 SCSI [A7173A] + 103c 1323 Core I/O LAN/SCSI Combo [AB314A] + 103c 3108 Single Channel Ultra320 SCSI HBA G2 + 103c 322a SC11Xe Ultra320 Single Channel PCIe x4 SCSI Host Bus Adapter (412911-B21) + 124b 1170 PMC-USCSI320 +# VMware's emulation of this device. Was missing from the list. + 15ad 1976 LSI Logic Parallel SCSI Controller + 1734 1052 PRIMERGY BX/RX/TX S2 series onboard SCSI(IME) + 0031 53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI + 0032 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI + 1000 1000 LSI53C1020/1030 PCI-X to Ultra320 SCSI Controller + 0033 1030ZC_53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI + 0040 53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI + 1000 0033 MegaRAID SCSI 320-2XR + 1000 0066 MegaRAID SCSI 320-2XRWS + 0041 53C1035ZC PCI-X Fusion-MPT Dual Ultra320 SCSI + 0050 SAS1064 PCI-X Fusion-MPT SAS + 1028 1f04 SAS 5/E + 1028 1f09 SAS 5i/R + 0052 MegaRAID SAS-3 3216/3224 [Cutlass] + 0053 MegaRAID SAS-3 3216/3224 [Cutlass] + 1000 9350 MegaRAID SAS 9341-16i + 1000 9351 MegaRAID SAS 9341-24i + 0054 SAS1068 PCI-X Fusion-MPT SAS + 1028 1f04 SAS 5/E Adapter Controller + 1028 1f05 SAS 5/i Adapter Controller + 1028 1f06 SAS 5/i Integrated Controller + 1028 1f07 SAS 5/iR Integrated RAID Controller + 1028 1f08 SAS 5/iR Integrated RAID Controller + 1028 1f09 SAS 5/iR Adapter RAID Controller + 15ad 1976 SAS Controller + 0055 SAS1068 PCI-X Fusion-MPT SAS + 1033 8336 SAS1068 + 0056 SAS1064ET PCI-Express Fusion-MPT SAS + 1014 03bb ServeRAID BR10il SAS/SATA Controller v2 + 8086 34dc AXX4SASMOD RAID Controller + 0057 M1064E MegaRAID SAS + 8086 346c Embedded Software RAID Technology II (ESTRII) + 0058 SAS1068E PCI-Express Fusion-MPT SAS + 1000 3140 SAS3081E-R 8-Port SAS/SATA Host Bus Adapter + 1028 021d SAS 6/iR Integrated Workstations RAID Controller + 1028 1f0e SAS 6/iR Adapter RAID Controller + 1028 1f0f SAS 6/iR Integrated Blades RAID Controller + 1028 1f10 SAS 6/iR Integrated RAID Controller + 103c 3229 SC44Ge Host Bus Adapter + 0059 MegaRAID SAS 8208ELP/8208ELP + 005a SAS1066E PCI-Express Fusion-MPT SAS + 005b MegaRAID SAS 2208 [Thunderbolt] + 1000 9265 MegaRAID SAS 9265-8i + 1000 9266 MegaRAID SAS 9266-8i + 1000 9267 MegaRAID SAS 9267-8i + 1000 9268 MegaRAID SAS 9265CV-8i / 9270CV-8i + 1000 9269 MegaRAID SAS 9266-4i + 1000 9270 MegaRAID SAS 9270-8i + 1000 9271 MegaRAID SAS 9271-8i + 1000 9272 MegaRAID SAS 9272-8i + 1000 9273 MegaRAID SAS 9270CV-8i + 1000 9274 MegaRAID SAS 9270-4i + 1000 9275 MegaRAID SAS 9271-8iCC + 1000 9276 MegaRAID SAS 9271-4i + 1000 9285 MegaRAID SAS 9285-8e + 1000 9288 MegaRAID SAS 9285CV-8e + 1000 9290 MegaRAID SAS 9286-8e + 1000 9291 MegaRAID SAS 9286CV-8e + 1000 9295 MegaRAID SAS 9286CV-8eCC + 1014 040b ServeRAID M5110 SAS/SATA Controller + 1014 040c ServeRAID M5120 SAS/SATA Controller + 1014 0412 ServeRAID M5110e SAS/SATA Controller + 1028 1f2d PERC H810 Adapter + 1028 1f30 PERC H710 Embedded + 1028 1f31 PERC H710P Adapter + 1028 1f33 PERC H710P Mini (for blades) + 1028 1f34 PERC H710P Mini (for monolithics) + 1028 1f35 PERC H710 Adapter + 1028 1f37 PERC H710 Mini (for blades) + 1028 1f38 PERC H710 Mini (for monolithics) + 15d9 0690 LSI MegaRAID ROMB + 8086 3510 RMS25PB080 RAID Controller + 8086 3511 RMS25PB040 RAID Controller + 8086 3512 RMT3PB080 RAID Controller + 8086 3513 Integrated RAID Module RMS25CB080 + 8086 3514 RMS25CB040 RAID Controller + 8086 351c RMS25PB080N RAID Controller + 8086 351d RMS25CB080N RAID Controller + 8086 9265 RS25DB080 RAID Controller + 8086 9268 RS25AB080 RAID Controller + 8086 9285 RS25NB008 RAID Controller + 8086 9288 RS25SB008 RAID Controller + 005c SAS1064A PCI-X Fusion-MPT SAS + 005d MegaRAID SAS-3 3108 [Invader] + 1000 9361 MegaRAID SAS 9361-8i + 1000 9363 MegaRAID SAS 9361-4i + 1000 9364 MegaRAID SAS 9364-8i + 1000 936a MegaRAID SAS 9364-8i + 1028 1f41 PERC H830 Adapter + 1028 1f42 PERC H730P Adapter + 1028 1f43 PERC H730 Adapter + 1028 1f47 PERC H730P Mini + 1028 1f48 PERC H730P Mini (for blades) + 1028 1f49 PERC H730 Mini + 1028 1f4a PERC H730 Mini (for blades) + 1028 1f4d PERC FD33xS + 1028 1f4f PERC H730P Slim + 1028 1f54 PERC FD33xD + 1028 1fd1 PERC H730P MX + 17aa 1052 ThinkServer RAID 720i + 17aa 1053 ThinkServer RAID 720ix + 1d49 0600 ThinkSystem RAID 730-8i 1GB Cache PCIe 12Gb Adapter + 1d49 0608 ThinkSystem RAID 730-8i 2GB Flash PCIe 12Gb Adapter + 1d49 0609 ThinkSystem RAID 730-8i 4GB Flash PCIe 12Gb Adapter + 8086 351e RMS3CC080 RAID Controller + 8086 351f RMS3CC040 RAID Controller + 8086 9360 RS3DC080 RAID Controller + 8086 9362 RS3DC040 RAID Controller + 8086 9380 RS3SC008 RAID Controller + 8086 9381 RS3MC044 RAID Controller + 005e SAS1066 PCI-X Fusion-MPT SAS + 005f MegaRAID SAS-3 3008 [Fury] + 1028 1f44 PERC H330 Adapter + 1028 1f4b PERC H330 Mini + 1028 1f4c PERC H330 Mini (for blades) + 1028 1f4d PERC H330 Embedded (for monolithic) + 1054 306a SAS 3004 iMR ROMB + 1d49 04db ServeRAID M1210 SAS/SATA Controller + 1d49 0504 ThinkSystem RAID 520-8i PCIe 12Gb Adapter + 0060 MegaRAID SAS 1078 + 1000 1006 MegaRAID SAS 8888ELP + 1000 100a MegaRAID SAS 8708ELP + 1000 100e MegaRAID SAS 8884E + 1000 100f MegaRAID SAS 8708E + 1000 1010 MegaRAID SATA 350-8ELP + 1000 1011 MegaRAID SATA 350-4ELP + 1000 1012 MegaRAID SAS 8704ELP + 1000 1016 MegaRAID SAS 8880EM2 + 1014 0363 MegaRAID SAS PCI Express ROMB + 1014 0364 SystemX MegaRAID SAS 8808E + 1014 0365 SystemX MegaRAID SAS 8884E + 1014 0379 SystemX MegaRAID SAS 8880EM2 + 1028 1f0a PERC 6/E Adapter RAID Controller + 1028 1f0b PERC 6/i Adapter RAID Controller + 1028 1f0c PERC 6/i Integrated RAID Controller + 1028 1f0d PERC 6/i Integrated RAID Controller + 1028 1f11 CERC 6/i Integrated RAID Controller + 1033 835a MegaRAID SAS PCI Express ROMB + 1043 824d MegaRAID SAS PCI Express ROMB + 1170 002f MegaRAID SAS PCI Express ROMB + 1170 0036 MegaRAID SAS PCI Express ROMB + 15d9 c080 MegaRAID SAS PCI Express ROMB + 17aa 6b7c MegaRAID SAS PCI Express ROMB + 18a1 0003 LSI MegaRAID SAS PCI Express ROMB + 8086 1006 RAID Controller SRCSAS28EP + 8086 100a RAID Controller SRCSAS28EV + 8086 1010 RAID Controller SRCSATA28E + 8086 34cc Integrated RAID Controller SROMBSAS28E + 8086 34cd Integrated RAID Controller SROMBSAS28E + 8086 3505 Integrated RAID Controller SROMBSASMP2 + 0062 SAS1078 PCI-Express Fusion-MPT SAS + 1000 0062 SAS1078 PCI-Express Fusion-MPT SAS + 0064 SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] + 1000 3030 9200-16e 6Gb/s SAS/SATA PCIe x8 External HBA + 1000 30c0 SAS 9201-16i + 1000 30d0 9201-16e 6Gb/s SAS/SATA PCIe x8 External HBA + 0065 SAS2116 PCI-Express Fusion-MPT SAS-2 [Meteor] + 006e SAS2308 PCI-Express Fusion-MPT SAS-2 + 0070 SAS2004 PCI-Express Fusion-MPT SAS-2 [Spitfire] + 1000 3010 SAS9211-4i + 1014 040e ServeRAID H1110 + 0071 MR SAS HBA 2004 + 0072 SAS2008 PCI-Express Fusion-MPT SAS-2 [Falcon] + 1000 3040 9210-8i + 1000 3080 9200-8e [LSI SAS 6Gb/s SAS/SATA PCIe x8 External HBA] + 1000 30b0 9200-8e [LSI SAS 6Gb/s SAS/SATA PCIe x8 External HBA] + 1028 1f1c 6Gbps SAS HBA Adapter + 1028 1f1d PERC H200 Adapter + 1028 1f1e PERC H200 Integrated + 1028 1f1f PERC H200 Modular + 1028 1f20 PERC H200 Embedded + 1028 1f22 PERC H200 Internal Tape Adapter + 8086 350f RMS2LL040 RAID Controller + 8086 3700 SSD 910 Series + 0073 MegaRAID SAS 2008 [Falcon] + 1000 9240 MegaRAID SAS 9240-8i + 1000 9241 MegaRAID SAS 9240-4i + 1000 92a0 MegaRAID SAS 9220-8i + 1014 03b1 ServeRAID M1015 SAS/SATA Controller + 1014 040d ServeRAID M1115 SAS/SATA Controller + 1028 1f4e PERC H310 Adapter + 1028 1f4f PERC H310 Integrated + 1028 1f50 PERC H310 Mini Blades + 1028 1f51 PERC H310 Mini Monolithics + 1028 1f52 PERC H310 Embedded1 + 1028 1f53 PERC H310 Embedded2 + 1028 1f54 PERC H310 Reserved + 1028 1f78 PERC H310 + 1054 3035 LSI MegaRAID SAS 9240-8i + 1137 0072 2004 iMR ROMB + 1137 0073 2008 ROMB + 1137 00b0 UCSC RAID SAS 2008M-8i + 1137 00b1 UCSC RAID SAS 2008M-8i + 1137 00c2 UCS E-Series Double Wide + 1137 00c3 UCS E-Series Single Wide + 15d9 0400 Supermicro SMC2008-iMR + 1734 1177 RAID Ctrl SAS 6G 0/1 (D2607) + 17aa 1051 ThinkServer RAID 510i + 8086 350d RMS2AF040 RAID Controller + 8086 9240 RAID Controller RS2WC080 + 8086 9241 RAID Controller RS2WC040 + 0074 SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] + 0076 SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] + 0077 SAS2108 PCI-Express Fusion-MPT SAS-2 [Liberator] + 0079 MegaRAID SAS 2108 [Liberator] + 1000 9251 MegaRAID SAS 9260-4ix + 1000 9256 MegaRAID SAS 9260-8ix + 1000 9260 MegaRAID SAS 9260-4i + 1000 9261 MegaRAID SAS 9260-8i + 1000 9262 MegaRAID SAS 9262-8i + 1000 9263 MegaRAID SAS 9261-8i + 1000 9264 MegaRAID SAS 9264-8i + 1000 9267 MegaRAID SAS 9260CV-4i + 1000 9268 MegaRAID SAS 9260CV-8i + 1000 9275 MegaRAID SAS 9280-8ex + 1000 9276 MR9260-16i + 1000 9280 MegaRAID SAS 9280-8e + 1000 9281 MegaRAID SAS 9281-8E + 1000 9282 MegaRAID SAS 9280-4i4e + 1000 9290 MegaRAID SAS 9280DE-24i4e + 1014 03b2 ServeRAID M5015 SAS/SATA Controller + 1014 03b3 ServeRAID M5025 SAS/SATA Controller + 1028 1f15 PERC H800 Adapter + 1028 1f16 PERC H700 Adapter + 1028 1f17 PERC H700 Integrated + 1028 1f18 PERC H700 Modular + 1028 1f1a PERC H800 Proto Adapter + 1028 1f1b PERC H700 Integrated + 1043 8480 PIKE-2108 16PD + 1734 1176 RAID Ctrl SAS 6G 5/6 512MB (D2616) + 1734 1177 RAID Ctrl SAS 6G 0/1 (D2607) + 8086 350b RMS2MH080 RAID Controller + 8086 9256 MegaRAID SAS 9260DE-8i RS2BL080DE + 8086 9260 RAID Controller RS2BL040 + 8086 9261 RAID Controller RS2BL080 + 8086 9264 RAID Controller RT3WB080 Warm Beach (Caster Lite) + 8086 9267 RAID Controller RS2VB040 + 8086 9268 RAID Controller RS2VB080 + 8086 9275 RAID Controller RS2PI008DE + 8086 9276 RAID Controller RS2WG160 + 8086 9280 RAID Controller RS2PI008 + 8086 9282 RAID Controller RS2MB044 + 8086 9290 RAID Controller RS2SG244 + 007c MegaRAID SAS 1078DE + 1014 0395 ServeRAID-AR10is SAS/SATA Controller + 007e SSS6200 PCI-Express Flash SSD + 1000 0504 Nytro NWD-BLP4-800 + 1000 0507 Nytro NWD-BLP4-1600 + 1000 0581 Nytro NWD-BLP4-400 + 1000 100d Nytro NWD-BFH6-1200 + 1000 100e Nytro NWD-BFH8-1600 + 1000 107e Nytro NWD-BFH8-3200 + 1000 1310 Nytro XP6302-8B1536 + 1000 1311 Nytro XP6302-8B2048 + 1000 1314 Nytro XP6302-8B4096 + 1000 150c Nytro XP6210-4A2048 + 1000 150f Nytro XP6210-4B2048 + 1000 160b Nytro XP6209-4A1024 + 1000 1613 Nytro XP6209-4B2048 + 108e 050a Nytro ELP4x200_4d_n + 108e 0581 Nytro ELP4x100_4d_n + 0080 SAS2208 PCI-Express Fusion-MPT SAS-2 + 0081 SAS2208 PCI-Express Fusion-MPT SAS-2 + 0082 SAS2208 PCI-Express Fusion-MPT SAS-2 + 0083 SAS2208 PCI-Express Fusion-MPT SAS-2 + 0084 SAS2208 PCI-Express Fusion-MPT SAS-2 + 0085 SAS2208 PCI-Express Fusion-MPT SAS-2 + 0086 SAS2308 PCI-Express Fusion-MPT SAS-2 + 15d9 0690 Onboard MegaRAID SAS2208 [Thunderbolt] + 15d9 0691 Onboard SAS2308 PCI-Express Fusion-MPT SAS-2 + 0087 SAS2308 PCI-Express Fusion-MPT SAS-2 + 1000 3020 9207-8i SAS2.1 HBA + 1000 3030 SAS9207-4i4e + 1000 3040 9207-8e SAS2.1 HBA + 1000 3050 SAS9217-8i + 1000 3060 SAS9217-4i4e + 1014 0472 N2125 External Host Bus Adapter + 1590 0041 H220i + 1590 0042 H221 / 9207-8e + 1590 0044 H220i + 8086 3000 RS25GB008 RAID Controller + 8086 3060 RS25FB044 RAID Controller + 8086 3516 RMS25JB080 RAID Controller + 8086 3517 RMS25JB040 RAID Controller + 8086 3518 RMS25KB080 RAID Controller + 8086 3519 RMS25KB040 RAID Controller + 8086 351a RMS25LB040 RAID Controller + 8086 351b RMS25LB080 RAID Controller + 008f 53c875J + 1092 8000 FirePort 40 SCSI Controller + 1092 8760 FirePort 40 Dual SCSI Host Adapter + 0090 SAS3108 PCI-Express Fusion-MPT SAS-3 + 0091 SAS3108 PCI-Express Fusion-MPT SAS-3 + 0094 SAS3108 PCI-Express Fusion-MPT SAS-3 + 0095 SAS3108 PCI-Express Fusion-MPT SAS-3 + 0096 SAS3004 PCI-Express Fusion-MPT SAS-3 + 0097 SAS3008 PCI-Express Fusion-MPT SAS-3 + 1000 3090 SAS9311-8i + 1000 30a0 SAS9300-8e + 1000 30e0 SAS9300-8i + 1000 3130 SAS 9300-16i + 1028 1f45 HBA330 Adapter + 1028 1f46 12Gbps HBA + 1028 1f53 HBA330 Mini + 1028 1fd2 HBA330 MX + 1028 1fd3 HBA330 MMZ +# Supermicro AOC-S3008L-L8e uses 0808 for their SAS3008 SAS controller + 15d9 0808 AOC-S3008L-L8e + 1bd4 000b 12G SAS3008IR + 1bd4 000c 12G SAS3008IT + 1bd4 0011 Inspur 12Gb 8i-3008 IT SAS HBA + 00ab SAS3516 Fusion-MPT Tri-Mode RAID On Chip (ROC) +# 8 Internal and 8 External port channel 9400 HBA + 1000 3040 HBA 9400-8i8e + 8086 3530 Integrated RAID Module RMSP3JD160J + 00ac SAS3416 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) +# Channel 16 internal port HBA + 1000 3000 HBA 9400-16i +# Channel 16 external port HBA + 1000 3020 HBA 9400-16e + 1028 1fe3 HBA345 Adapter + 1028 1fe4 HBA345 Front + 1d49 0201 ThinkSystem 430-16i SAS/SATA 12Gb HBA + 1d49 0203 ThinkSystem 430-16e SAS/SATA 12Gb HBA + 8086 3000 RAID Controller RSP3QD160J + 8086 3020 RAID Controller RSP3GD016J + 00ae SAS3508 Fusion-MPT Tri-Mode RAID On Chip (ROC) + 00af SAS3408 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + 1000 3010 HBA 9400-8i +# 9400 Channel 8 external port HBA + 1000 3030 HBA 9400-8e + 1d49 0200 ThinkSystem 430-8i SAS/SATA 12Gb HBA + 1d49 0202 ThinkSystem 430-8e SAS/SATA 12Gb HBA + 1d49 0204 ThinkSystem 430-8i SAS/SATA 12Gb Dense HBA + 00be SAS3504 Fusion-MPT Tri-Mode RAID On Chip (ROC) + 00bf SAS3404 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) + 00c0 SAS3324 PCI-Express Fusion-MPT SAS-3 + 00c1 SAS3324 PCI-Express Fusion-MPT SAS-3 + 00c2 SAS3324 PCI-Express Fusion-MPT SAS-3 + 00c3 SAS3324 PCI-Express Fusion-MPT SAS-3 + 00c4 SAS3224 PCI-Express Fusion-MPT SAS-3 + 00c5 SAS3316 PCI-Express Fusion-MPT SAS-3 + 00c6 SAS3316 PCI-Express Fusion-MPT SAS-3 + 00c7 SAS3316 PCI-Express Fusion-MPT SAS-3 + 00c8 SAS3316 PCI-Express Fusion-MPT SAS-3 + 00c9 SAS3216 PCI-Express Fusion-MPT SAS-3 + 00ce MegaRAID SAS-3 3316 [Intruder] + 1000 9371 MegaRAID SAS 9361-16i + 1000 9390 MegaRAID SAS 9380-8i8e + 00cf MegaRAID SAS-3 3324 [Intruder] + 1000 9370 MegaRAID SAS 9361-24i + 00d0 SAS3716 Fusion-MPT Tri-Mode RAID Controller Chip (ROC) +# 9405W 16 internal port channel HBA + 1000 3050 HBA 9405W-16i +# 9405W 8 internal and 8 external port channel HBA + 1000 3070 HBA 9405W-8i8e + 00d1 SAS3616 Fusion-MPT Tri-Mode I/O Controller Chip (IOC) +# 9405W 16 external port Channel HBA + 1000 3080 HBA 9405W-16e +# 9405W 16 internal port Channel HBA + 1000 3090 HBA 9405W-16i + 00d3 MegaRAID Tri-Mode SAS3716W + 00e0 Fusion-MPT 12GSAS/PCIe Unsupported SAS39xx + 00e1 Fusion-MPT 12GSAS/PCIe SAS39xx + 00e2 Fusion-MPT 12GSAS/PCIe Secure SAS39xx + 00e3 Fusion-MPT 12GSAS/PCIe Unsupported SAS39xx + 00e4 Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx +# Invalid part + 1028 200b HBA355i Adapter Invalid +# Invalid part + 1028 200c HBA355i Front Invalid +# Invalid part + 1028 200d HBA355e Adapter Invalid +# Invalid part + 1028 200e HBA350i MX Invalid +# Soft Secure + 00e5 Fusion-MPT 12GSAS/PCIe SAS38xx +# Soft Secure + 1028 200b HBA355i Adapter +# Soft Secure + 1028 200c HBA355i Front +# Soft Secure + 1028 200d HBA355e Adapter +# Soft Secure + 1028 200e HBA350i MX + 1d49 0205 ThinkSystem 440-16i SAS/SATA PCIe Gen4 12Gb Internal HBA + 1d49 0206 ThinkSystem 440-16e SAS/SATA PCIe Gen4 12Gb HBA + 00e6 Fusion-MPT 12GSAS/PCIe Secure SAS38xx + 1028 200b HBA355i Adapter + 1028 200c HBA355i Front + 1028 200d HBA355e Adapter + 1028 200e HBA355i MX + 1d49 0205 ThinkSystem 440-16i SAS/SATA PCIe Gen4 12Gb Internal HBA + 1d49 0206 ThinkSystem 440-16e SAS/SATA PCIe Gen4 12Gb HBA + 00e7 Fusion-MPT 12GSAS/PCIe Unsupported SAS38xx +# Tampered part + 1028 200b HBA355i Adapter Tampered +# Tampered part + 1028 200c HBA355i Front Tampered +# Tampered part + 1028 200d HBA355e Adapter Tampered +# Tampered part + 1028 200e HBA350i MX Tampered + 02b0 Virtual Endpoint on PCIe Switch + 1d49 0001 ThinkSystem 1610-4P NVMe Switch Adapter + 1d49 0002 ThinkSystem 810-4P NVMe Switch Adapter + 02b1 Virtual Endpoint on PCIe Switch (9749) + 1d49 0004 ThinkSystem 1610-8P NVMe Switch Adapter + 0407 MegaRAID + 1000 0530 MegaRAID 530 SCSI 320-0X RAID Controller + 1000 0531 MegaRAID 531 SCSI 320-4X RAID Controller + 1000 0532 MegaRAID 532 SCSI 320-2X RAID Controller + 1028 0531 PowerEdge Expandable RAID Controller 4/QC + 1028 0533 PowerEdge Expandable RAID Controller 4/QC + 8086 0530 MegaRAID Intel RAID Controller SRCZCRX + 8086 0532 MegaRAID Intel RAID Controller SRCU42X + 0408 MegaRAID + 1000 0001 MegaRAID SCSI 320-1E RAID Controller + 1000 0002 MegaRAID SCSI 320-2E RAID Controller + 1025 004d MegaRAID ACER ROMB-2E RAID Controller + 1028 0001 PowerEdge RAID Controller PERC4e/SC + 1028 0002 PowerEdge RAID Controller PERC4e/DC + 1028 0012 PowerEdge RAID Controller RAC4 + 1028 0015 PowerEdge RAID Controller PERC5 + 1028 1f03 PowerEdge RAID Controller PERC5 + 1734 1065 FSC MegaRAID PCI Express ROMB + 8086 0002 MegaRAID Intel RAID Controller SRCU42E + 8086 3449 MegaRAID Intel RAID Controller SROMBU + 0409 MegaRAID + 1000 3004 MegaRAID SATA 300-4X RAID Controller + 1000 3008 MegaRAID SATA 300-8X RAID Controller + 8086 3008 MegaRAID RAID Controller SRCS28X + 8086 3431 MegaRAID RAID Controller Alief SROMBU42E + 8086 3499 MegaRAID RAID Controller Harwich SROMBU42E + 0411 MegaRAID SAS 1068 + 1000 1001 MegaRAID SAS 8408E + 1000 1002 MegaRAID SAS 8480E + 1000 1003 MegaRAID SAS 8344ELP + 1000 1004 MegaRAID SAS 8308ELP + 1000 1008 MegaRAID SAS 84016E + 1000 100c MegaRAID SATA 300-12E + 1000 100d MegaRAID SATA 300-16E + 1000 2004 MegaRAID SATA 300-8ELP + 1000 2005 MegaRAID SATA 300-4ELP + 1033 8287 MegaRAID SAS PCI Express ROMB + 1054 3016 MegaRAID SAS RoMB Server + 1734 1081 MegaRAID SAS PCI Express ROMB + 1734 10a3 MegaRAID SAS PCI Express ROMB + 8086 1001 RAID Controller SRCSAS18E + 8086 1003 RAID Controller SRCSAS144E + 8086 3500 SROMBSAS18E RAID Controller + 8086 3501 SROMBSAS18E RAID Controller + 8086 3504 SROMBSAS18E RAID Controller + 0413 MegaRAID SAS 1068 [Verde ZCR] + 1000 1005 MegaRAID SAS 8300XLP + 0621 FC909 Fibre Channel Adapter + 0622 FC929 Fibre Channel Adapter + 1000 1020 44929 O Dual Fibre Channel card + 0623 FC929 LAN + 0624 FC919 Fibre Channel Adapter + 0625 FC919 LAN + 0626 FC929X Fibre Channel Adapter + 1000 1010 7202-XP-LC Dual Fibre Channel card + 0627 FC929X LAN + 0628 FC919X Fibre Channel Adapter + 0629 FC919X LAN + 0640 FC949X Fibre Channel Adapter + 0642 FC939X Fibre Channel Adapter + 0646 FC949ES Fibre Channel Adapter + 0701 83C885 NT50 DigitalScape Fast Ethernet + 0702 Yellowfin G-NIC gigabit ethernet + 1318 0000 PEI100X + 0804 SA2010 + 0805 SA2010ZC + 0806 SA2020 + 0807 SA2020ZC + 0901 61C102 + 1000 63C815 + 10e0 MegaRAID 12GSAS/PCIe Unsupported SAS39xx + 1028 1ae0 PERC H755 Adapter - Invalid Device + 1028 1ae1 PERC H755 Front - Invalid Device + 1028 1ae2 PERC H755N Front - Invalid Device + 1028 1ae3 PERC H755 MX - Invalid Device + 10e1 MegaRAID 12GSAS/PCIe SAS39xx + 1028 1ae0 PERC H755 Adapter + 1028 1ae1 PERC H755 Front + 1028 1ae2 PERC H755N Front + 1028 1ae3 PERC H755 MX + 1d49 060a ThinkSystem RAID 940-8i 4GB Flash PCIe Gen4 12Gb Adapter + 1d49 060b ThinkSystem RAID 940-8i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060c ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060d ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Internal Adapter + 1d49 060e ThinkSystem RAID 940-32i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060f ThinkSystem RAID 940-8e 4GB Flash PCIe Gen4 12Gb Adapter + 10e2 MegaRAID 12GSAS/PCIe Secure SAS39xx + 1028 1ae0 PERC H755 Adapter + 1028 1ae1 PERC H755 Front + 1028 1ae2 PERC H755N Front + 1028 1ae3 PERC H755 MX + 1d49 060a ThinkSystem RAID 940-8i 4GB Flash PCIe Gen4 12Gb Adapter + 1d49 060b ThinkSystem RAID 940-8i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060c ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060d ThinkSystem RAID 940-16i 8GB Flash PCIe Gen4 12Gb Internal Adapter + 1d49 060e ThinkSystem RAID 940-32i 8GB Flash PCIe Gen4 12Gb Adapter + 1d49 060f ThinkSystem RAID 940-8e 4GB Flash PCIe Gen4 12Gb Adapter + 10e3 MegaRAID 12GSAS/PCIe Unsupported SAS39xx + 1028 1ae0 PERC H755 Adapter - Tampered Device + 1028 1ae1 PERC H755 Front - Tampered Device + 1028 1ae2 PERC H755N Front - Tampered Device + 1028 1ae3 PERC H755 MX - Tampered Device + 10e4 MegaRAID 12GSAS/PCIe Unsupported SAS38xx + 10e5 MegaRAID 12GSAS/PCIe SAS38xx + 10e6 MegaRAID 12GSAS/PCIe Secure SAS38xx + 10e7 MegaRAID 12GSAS/PCIe Unsupported SAS38xx + 1960 MegaRAID + 1000 0518 MegaRAID 518 SCSI 320-2 Controller + 1000 0520 MegaRAID 520 SCSI 320-1 Controller + 1000 0522 MegaRAID 522 i4 133 RAID Controller + 1000 0523 MegaRAID SATA 150-6 RAID Controller + 1000 4523 MegaRAID SATA 150-4 RAID Controller + 1000 a520 MegaRAID ZCR SCSI 320-0 Controller + 1028 0518 MegaRAID 518 DELL PERC 4/DC RAID Controller + 1028 0520 MegaRAID 520 DELL PERC 4/SC RAID Controller + 1028 0531 PowerEdge Expandable RAID Controller 4/QC + 1028 0533 PowerEdge Expandable RAID Controller 4/QC + 8086 0520 MegaRAID RAID Controller SRCU41L + 8086 0523 MegaRAID RAID Controller SRCS16 + 3050 SAS2008 PCI-Express Fusion-MPT SAS-2 + 6001 DX1 Multiformat Broadcast HD/SD Encoder/Decoder +1001 Kolter Electronic + 0010 PCI 1616 Measurement card with 32 digital I/O lines + 0011 OPTO-PCI Opto-Isolated digital I/O board + 0012 PCI-AD/DA Analogue I/O board + 0013 PCI-OPTO-RELAIS Digital I/O board with relay outputs + 0014 PCI-Counter/Timer Counter Timer board + 0015 PCI-DAC416 Analogue output board + 0016 PCI-MFB Analogue I/O board + 0017 PROTO-3 PCI Prototyping board + 9100 INI-9100/9100W SCSI Host +# nee ATI Technologies, Inc. +1002 Advanced Micro Devices, Inc. [AMD/ATI] + 1304 Kaveri + 1305 Kaveri + 1306 Kaveri + 1307 Kaveri + 1308 Kaveri HDMI/DP Audio Controller + 1309 Kaveri [Radeon R6/R7 Graphics] + 130a Kaveri [Radeon R6 Graphics] + 130b Kaveri [Radeon R4 Graphics] + 130c Kaveri [Radeon R7 Graphics] + 130d Kaveri [Radeon R6 Graphics] + 130e Kaveri [Radeon R5 Graphics] + 130f Kaveri [Radeon R7 Graphics] + 1310 Kaveri + 1311 Kaveri + 1312 Kaveri + 1313 Kaveri [Radeon R7 Graphics] + 1314 Wrestler HDMI Audio + 174b 1001 PURE Fusion Mini + 1315 Kaveri [Radeon R5 Graphics] + 1316 Kaveri [Radeon R5 Graphics] + 1317 Kaveri + 1318 Kaveri [Radeon R5 Graphics] + 131b Kaveri [Radeon R4 Graphics] + 131c Kaveri [Radeon R7 Graphics] + 131d Kaveri [Radeon R6 Graphics] + 13e9 Ariel + 1478 Navi 10 XL Upstream Port of PCI Express Switch + 1479 Navi 10 XL Downstream Port of PCI Express Switch + 154c Kryptos + 154e Garfield + 1551 Arlene + 1552 Pooky + 1561 Anubis + 15d8 Picasso + 103c 8615 Pavilion Laptop 15-cw1xxx + 15dd Raven Ridge [Radeon Vega Series / Radeon Vega Mobile Series] + 103c 83c6 Radeon Vega 8 Mobile + 1458 d000 Radeon RX Vega 11 + 15de Raven/Raven2/Fenghuang HDMI/DP Audio Controller + 103c 8615 Pavilion Laptop 15-cw1xxx + 15df Raven/Raven2/Fenghuang/Renoir Cryptographic Coprocessor + 103c 8615 Pavilion Laptop 15-cw1xxx + 15ff Fenghuang [Zhongshan Subor Z+] + 1607 Arden + 1636 Renoir + 1714 BeaverCreek HDMI Audio [Radeon HD 6500D and 6400G-6600G series] + 103c 168b ProBook 4535s + 3150 RV380/M24 [Mobility Radeon X600] + 103c 0934 nx8220 + 3151 RV380 GL [FireMV 2400] + 3152 RV370/M22 [Mobility Radeon X300] + 3154 RV380/M24 GL [Mobility FireGL V3200] + 3155 RV380 GL [FireMV 2400] + 3171 RV380 GL [FireMV 2400] (Secondary) + 3e50 RV380 [Radeon X600] + 3e54 RV380 GL [FireGL V3200] + 3e70 RV380 [Radeon X600] (Secondary) + 4136 RS100 [Mobility IGP 320M] + 4137 RS200 [Radeon IGP 340] + 4144 R300 [Radeon 9500] + 4146 R300 [Radeon 9700 PRO] + 4147 R300 GL [FireGL Z1] + 4148 R350 [Radeon 9800/9800 SE] + 4150 RV350 [Radeon 9550/9600/X1050 Series] + 1002 0002 R9600 Pro primary (Asus OEM for HP) + 1002 0003 R9600 Pro secondary (Asus OEM for HP) + 1002 4722 All-in-Wonder 2006 AGP Edition + 1458 4024 GV-R96128D + 148c 2064 R96A-C3N + 148c 2066 R96A-C3N + 174b 7c19 Atlantis Radeon 9600 Pro + 174b 7c29 GC-R9600PRO + 17ee 2002 Radeon 9600 256Mb Primary + 18bc 0101 GC-R9600PRO (Primary) + 4151 RV350 [Radeon 9600 Series] + 1043 c004 A9600SE + 174b 7c37 Radeon 9600SE 128M DDR V/D/VO + 4152 RV360 [Radeon 9600/X1050 Series] + 1002 0002 Radeon 9600XT + 1002 4772 All-in-Wonder 9600 XT + 1043 c002 Radeon 9600 XT TVD + 1043 c01a A9600XT/TD + 1462 9510 RX9600XT (MS-8951) + 174b 7c29 Radeon 9600XT + 1787 4002 Radeon 9600 XT + 4153 RV350 [Radeon 9550] + 1043 010c A9550GE/TD + 1462 932c RX9550SE-TD128 (MS-8932) + 4154 RV350 GL [FireGL T2] + 4155 RV350 [Radeon 9600] + 4157 RV350 GL [FireGL T2] + 4158 68800AX [Graphics Ultra Pro PCI] + 4164 R300 [Radeon 9500 PRO] (Secondary) + 4165 R300 [Radeon 9700 PRO] (Secondary) + 4166 R300 [Radeon 9700 PRO] (Secondary) + 4168 RV350 [Radeon 9800 SE] (Secondary) + 4170 RV350 [Radeon 9550/9600/X1050 Series] (Secondary) + 1002 0003 R9600 Pro secondary (Asus OEM for HP) + 1002 4723 All-in-Wonder 2006 AGP Edition (Secondary) + 1458 4025 GV-R96128D (Secondary) + 148c 2067 R96A-C3N (Secondary) + 174b 7c28 GC-R9600PRO (Secondary) + 17ee 2003 Radeon 9600 256Mb (Secondary) + 18bc 0100 GC-R9600PRO (Secondary) + 4171 RV350 [Radeon 9600] (Secondary) + 1043 c005 A9600SE (Secondary) + 174b 7c36 Radeon 9600SE 128M DDR V/D/VO (secondary) + 4172 RV350 [Radeon 9600/X1050 Series] (Secondary) + 1002 0003 Radeon 9600XT (Secondary) + 1002 4773 All-in-Wonder 9600 XT (Secondary) + 1043 c003 A9600XT (Secondary) + 1043 c01b A9600XT/TD (Secondary) + 174b 7c28 Radeon 9600XT (Secondary) + 1787 4003 Radeon 9600 XT (Secondary) + 4173 RV350 [Radeon 9550] (Secondary) + 1043 010d A9550GE/TD (Secondary) + 4242 R200 [All-In-Wonder Radeon 8500 DV] + 1002 02aa Radeon 8500 AIW DV Edition + 4243 R200 PCI Bridge [All-in-Wonder Radeon 8500DV] + 4336 RS100 [Radeon IGP 320M] + 1002 4336 Pavilion ze4300 ATI Radeon Mobility U1 (IGP 320 M) + 103c 0024 Pavilion ze4400 builtin Video + 161f 2029 eMachines M5312 builtin Video + 4337 RS200M [Radeon IGP 330M/340M/345M/350M] + 1014 053a ThinkPad R40e + 103c 0850 Radeon IGP 345M + 4341 SB200 AC97 Audio Controller + 4342 SB200 PCI to PCI Bridge + 4345 SB200 EHCI USB Controller + 4346 Crayola 6 [XENOS Parent Die (XBOX 360)] + 4347 SB200 OHCI USB Controller #1 + 4348 SB200 OHCI USB Controller #2 + 4349 SB200 IDE Controller + 434c SB200 PCI to LPC Bridge + 434d SB200 AC97 Modem Controller + 4353 SB200 SMBus Controller + 4354 215CT [Mach64 CT PCI] + 4358 Mach64 CX [Graphics Xpression] + 4361 SB300 AC'97 Audio Controller + 4362 SB300 PCI to PCI Bridge + 4363 SB300 SMBus Controller + 4365 SB300 USB Controller (EHCI) + 4367 SB300 USB Controller (EHCI) + 4368 SB300 USB Controller (EHCI) + 4369 SB300 IDE Controller + 436c SB300 PCI to LPC Bridge + 436d SB300 AC97 Modem Controller + 436e SB300 Serial ATA Controller + 4370 IXP SB400 AC'97 Audio Controller + 1025 0079 Aspire 5024WLMMi + 1025 0091 Aspire 5032WXMi + 103c 2a05 Pavilion t3030.de Desktop PC + 103c 308b MX6125 + 105b 0c81 Realtek ALC 653 + 107b 0300 MX6421 + 1462 0131 MS-1013 Notebook + 4371 IXP SB4x0 PCI-PCI Bridge + 103c 308b MX6125 + 1462 7217 Aspire L250 + 4372 IXP SB4x0 SMBus Controller + 1025 0080 Aspire 5024WLMMi + 103c 2a20 Pavilion t3030.de Desktop PC + 103c 308b MX6125 + 1462 0131 MS-1013 Notebook + 1462 7217 Aspire L250 + 4373 IXP SB4x0 USB2 Host Controller + 1025 0080 Aspire 5024WLMMi + 103c 2a20 Pavilion t3030.de Desktop PC + 103c 308b MX6125 + 1462 7217 Aspire L250 + 4374 IXP SB4x0 USB Host Controller + 103c 2a20 Pavilion t3030.de Desktop PC + 103c 308b MX6125 + 1462 7217 Aspire L250 + 4375 IXP SB4x0 USB Host Controller + 1025 0080 Aspire 5024WLMMi + 103c 2a20 Pavilion t3030.de Desktop PC + 103c 308b MX6125 + 1462 7217 Aspire L250 + 4376 IXP SB4x0 IDE Controller + 1025 0080 Aspire 5024WLMMi + 103c 2a20 Pavilion t3030.de Desktop PC + 103c 308b MX6125 + 1462 0131 MS-1013 Notebook + 1462 7217 Aspire L250 + 4377 IXP SB4x0 PCI-ISA Bridge + 1025 0080 Aspire 5024WLMi + 103c 2a20 Pavilion t3030.de Desktop PC + 103c 308b MX6125 + 1462 7217 Aspire L250 + 4378 IXP SB400 AC'97 Modem Controller + 1025 0080 Aspire 5024WLMMi + 103c 308b MX6125 + 1462 0131 MS-1013 Notebook + 4379 IXP SB4x0 Serial ATA Controller + 1462 7141 Aspire L250 + 437a IXP SB400 Serial ATA Controller + 1002 4379 4379 Serial ATA Controller + 1002 437a 437A Serial ATA Controller + 1462 7141 Aspire L250 + 14f1 8800 Leadtek WinFast TV2000XP Expert + 437b IXP SB4x0 High Definition Audio Controller + 1002 437b IXP SB4x0 High Definition Audio Controller + 10cf 1326 Fujitsu Lifebook A3040 + 1734 10b8 Realtek High Definition Audio + 4380 SB600 Non-Raid-5 SATA + 103c 2813 DC5750 Microtower + 1179 ff50 Satellite P305D-S8995E + 1458 b003 GA-MA790FX-DS5 (rev. 1.0) + 1458 b005 Gigabyte GA-MA69G-S3H Motherboard + 1462 7327 K9AG Neo2 + 17f2 5999 KI690-AM2 Motherboard + 4381 SB600 SATA Controller (RAID 5 mode) + 4382 SB600 AC97 Audio + 4383 SBx00 Azalia (Intel HDA) + 1019 2120 A785GM-M + 103c 1611 Pavilion DM1Z-3000 + 103c 280a DC5750 Microtower + 1043 8230 M3A78-EH Motherboard + 1043 836c M4A785TD Motherboard + 1043 8410 M4A89GTD PRO/USB3 Motherboard + 1043 841b M5A88-V EVO + 1043 8445 M5A78L LE + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 1179 ff50 Satellite P305D-S8995E + 1458 a022 GA-MA770-DS3rev2.0 Motherboard + 17f2 5000 KI690-AM2 Motherboard + 4384 SBx00 PCI to PCI Bridge + 4385 SBx00 SMBus Controller + 1019 2120 A785GM-M + 103c 1611 Pavilion DM1Z-3000 + 103c 280a DC5750 Microtower + 1043 82ef M3A78-EH Motherboard + 1043 8389 M4A785TD Motherboard + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 1179 ff50 Satellite P305D-S8995E + 1458 4385 GA-MA770-DS3rev2.0 Motherboard + 1462 7368 K9AG Neo2 + 15d9 a811 H8DGU + 174b 1001 PURE Fusion Mini + 17f2 5000 KI690-AM2 Motherboard + 4386 SB600 USB Controller (EHCI) + 103c 280a DC5750 Microtower + 1179 ff50 Satellite P305D-S8995E + 1462 7368 K9AG Neo2 + 17f2 5000 KI690-AM2 Motherboard + 4387 SB600 USB (OHCI0) + 103c 280a DC5750 Microtower + 1179 ff50 Satellite P305D-S8995E + 1462 7368 K9AG Neo2 + 17f2 5000 KI690-AM2 Motherboard + 4388 SB600 USB (OHCI1) + 103c 280a DC5750 Microtower + 1179 ff50 Satellite P305D-S8995E + 1462 7368 K9AG Neo2 + 17f2 5000 KI690-AM2 Motherboard + 4389 SB600 USB (OHCI2) + 103c 280a DC5750 Microtower + 1179 ff50 Satellite P305D-S8995E + 1462 7368 K9AG Neo2 + 17f2 5000 KI690-AM2 Motherboard + 438a SB600 USB (OHCI3) + 103c 280a DC5750 Microtower + 1179 ff50 Satellite P305D-S8995E + 1462 7368 K9AG Neo2 + 17f2 5000 KI690-AM2 Motherboard + 438b SB600 USB (OHCI4) + 103c 280a DC5750 Microtower + 1179 ff50 Satellite P305D-S8995E + 1462 7368 K9AG Neo2 + 17f2 5000 KI690-AM2 Motherboard + 438c SB600 IDE + 103c 280a DC5750 Microtower + 1179 ff50 Satellite P305D-S8995E + 1458 5002 Gigabyte GA-MA69G-S3H Motherboard + 1462 7368 K9AG Neo2 + 17f2 5000 KI690-AM2 Motherboard + 438d SB600 PCI to LPC Bridge + 103c 280a DC5750 Microtower + 1179 ff50 Satellite P305D-S8995E + 1462 7368 K9AG Neo2 + 17f2 5000 KI690-AM2 Motherboard + 438e SB600 AC97 Modem + 4390 SB7x0/SB8x0/SB9x0 SATA Controller [IDE mode] + 1043 82ef M3A78-EH Motherboard + 1043 8389 M4A785TD Motherboard + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 1458 b002 GA-MA770-DS3rev2.0 Motherboard + 1849 4390 Motherboard (one of many) + 4391 SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] + 103c 1609 ProLiant MicroServer N36L + 103c 1611 Pavilion DM1Z-3000 + 1043 82ef M3A78-EH Motherboard + 1043 8443 M5A88-V EVO + 1043 84dd M5A99X EVO (R1.0) SB950 + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 174b 1001 PURE Fusion Mini + 4392 SB7x0/SB8x0/SB9x0 SATA Controller [Non-RAID5 mode] + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 4393 SB7x0/SB8x0/SB9x0 SATA Controller [RAID5 mode] + 4394 SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode] + 4395 SB8x0/SB9x0 SATA Controller [Storage mode] + 4396 SB7x0/SB8x0/SB9x0 USB EHCI Controller + 1019 2120 A785GM-M + 103c 1609 ProLiant MicroServer N36L + 103c 1611 Pavilion DM1Z-3000 + 1043 82ef M3A78-EH Motherboard + 1043 8443 M5A88-V EVO + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 15d9 a811 H8DGU + 174b 1001 PURE Fusion Mini + 4397 SB7x0/SB8x0/SB9x0 USB OHCI0 Controller + 1019 2120 A785GM-M + 103c 1609 ProLiant MicroServer N36L + 103c 1611 Pavilion DM1Z-3000 + 1043 82ef M3A78-EH Motherboard + 1043 8443 M5A88-V EVO + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 15d9 a811 H8DGU + 174b 1001 PURE Fusion Mini + 4398 SB7x0 USB OHCI1 Controller + 1019 2120 A785GM-M + 1043 82ef M3A78-EH Motherboard + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 15d9 a811 H8DGU + 4399 SB7x0/SB8x0/SB9x0 USB OHCI2 Controller + 1019 2120 A785GM-M + 1043 82ef M3A78-EH Motherboard + 1043 8443 M5A88-V EVO + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 174b 1001 PURE Fusion Mini + 439c SB7x0/SB8x0/SB9x0 IDE Controller + 1002 4392 MSI MS-7713 motherboard + 1019 2120 A785GM-M + 103c 1609 ProLiant MicroServer N36L + 1043 82ef M3A78-EH Motherboard + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 439d SB7x0/SB8x0/SB9x0 LPC host controller + 1019 2120 A785GM-M + 103c 1609 ProLiant MicroServer N36L + 103c 1611 Pavilion DM1Z-3000 + 1043 82ef M3A78-EH Motherboard + 1043 8443 M5A88-V EVO + 105b 0e13 N15235/A74MX mainboard / AMD SB700 + 174b 1001 PURE Fusion Mini + 43a0 SB700/SB800/SB900 PCI to PCI bridge (PCIE port 0) + 43a1 SB700/SB800/SB900 PCI to PCI bridge (PCIE port 1) + 43a2 SB900 PCI to PCI bridge (PCIE port 2) + 43a3 SB900 PCI to PCI bridge (PCIE port 3) + 4437 RS250 [Mobility Radeon 7000 IGP] + 4554 210888ET [Mach64 ET] + 4630 XENOS Parent Die (XBOX 360) + 4631 XENOS Daughter Die (XBOX 360) + 4654 Mach64 VT + 4742 Rage 3 [3D Rage PRO AGP 2X] + 1002 0040 Rage Pro Turbo AGP 2X + 1002 0044 Rage Pro Turbo AGP 2X + 1002 0061 Rage Pro AIW AGP 2X + 1002 0062 Rage Pro AIW AGP 2X + 1002 0063 Rage Pro AIW AGP 2X + 1002 0080 Rage Pro Turbo AGP 2X + 1002 0084 Rage Pro Turbo AGP 2X + 1002 4742 Rage Pro Turbo AGP 2X + 1002 8001 Rage Pro Turbo AGP 2X + 1028 0082 Rage Pro Turbo AGP 2X + 1028 4082 Optiplex GX1 Onboard Display Adapter + 1028 8082 Rage Pro Turbo AGP 2X + 1028 c082 Rage Pro Turbo AGP 2X + 8086 4152 Xpert 98D AGP 2X + 8086 464a Rage Pro Turbo AGP 2X + 4744 Rage 3 [3D Rage PRO AGP 1X] + 1002 4744 Rage Pro Turbo AGP + 8086 4d55 Rage 3D Pro AGP 1X [Intel MU440EX] + 4749 3D Rage PRO PCI + 1002 0061 Rage Pro AIW + 1002 0062 Rage Pro AIW + 474d Rage XL AGP 2X + 1002 0004 Xpert 98 RXL AGP 2X + 1002 0008 Xpert 98 RXL AGP 2X + 1002 0080 Rage XL AGP 2X + 1002 0084 Xpert 98 AGP 2X + 1002 474d Rage XL AGP + 1033 806a Rage XL AGP + 474e Rage XC AGP + 1002 474e Rage XC AGP + 474f Rage XL + 1002 0008 Rage XL + 1002 474f Rage XL + 4750 3D Rage Pro PCI + 1002 0040 Rage Pro Turbo + 1002 0044 Rage Pro Turbo + 1002 0080 Rage Pro Turbo + 1002 0084 Rage Pro Turbo + 1002 4750 Rage Pro Turbo + 4752 Rage 3 [Rage XL PCI] + 0e11 001e Proliant Rage XL + 1002 0008 Rage XL + 1002 4752 Proliant Rage XL + 1002 8008 Rage XL + 1014 0240 eServer xSeries server mainboard + 1028 00ce PowerEdge 1400 + 1028 00d1 PowerEdge 2550 + 1028 00d9 PowerEdge 2500 + 1028 0134 PowerEdge 600SC + 1028 014a PowerEdge 1750 + 1028 0165 PowerEdge 750 + 103c 10e1 NetServer Rage XL + 103c 3208 ProLiant DL140 G2 + 107b 6400 6400 Server + 1734 007a PRIMERGY RX/TX series onboard VGA + 1734 1073 Primergy Econel 200 D2020 mainboard + 8086 3411 SDS2 Mainboard + 8086 3427 S875WP1-E mainboard + 8086 5744 S845WD1-E mainboard + 4753 Rage XC + 1002 4753 Rage XC + 4754 Mach64 GT/GT-B [3D Rage I/II] + 4755 Mach64 GT-B [3D Rage II+ DVD] + 4756 Rage 2 [3D Rage IIC PCI] + 1002 4756 Rage IIC + 4757 Rage 2 [3D Rage IIC AGP] + 1002 4757 Rage IIC AGP + 1028 0089 Rage 3D IIC + 1028 008e PowerEdge 1300 onboard video + 1028 4082 Rage 3D IIC + 1028 8082 Rage 3D IIC + 1028 c082 Rage 3D IIC + 4758 Mach64 GX [WinTurbo] + 4759 Rage 3 [3D Rage IIC PCI] + 475a 3D Rage IIC AGP + 1002 0084 Rage 3D Pro AGP 2x XPERT 98 + 1002 0087 Rage 3D IIC + 1002 475a Rage IIC AGP + 4845 Xilleon 220 HBIU for HDTV2 + 4846 Xilleon 220 IDE for HDTV2 + 4847 Xilleon 220 USB for HDTV2 + 4848 Xilleon 220 DAIO-0 for HDTV2 + 4849 Xilleon 220 DAIO-1 for HDTV2 + 484a Xilleon 220 LPC for HDTV2 + 4850 Xilleon 215 HBIU for X215 + 4851 Xilleon 215 IDE for X215 + 4852 Xilleon 215 USB for X215 + 4853 Xilleon 215 DAIO-0 for X215 + 4854 Xilleon 215 DAIO-1 for X215 + 4855 Xilleon 225 HBIU for X225 + 4856 Xilleon 225 IDE for X225 + 4857 Xilleon 225 USB for X225 + 4858 Xilleon 225 DAIO-0 for X225 + 4859 Xilleon 225 DAIO-1 for X225 + 4860 Xilleon 210 HBIU for X210 + 4861 Xilleon 210 IDE for X210 + 4862 Xilleon 210 USB for X210 + 4863 Xilleon 210 DAIO-0 for X210 + 4864 Xilleon 210 DAIO-1 for X210 + 4865 Xilleon 226 HBIU for X226 + 4866 Xilleon 226 IDE for X226 + 4867 Xilleon 226 USB for X226 + 4868 Xilleon 226 DAIO-0 for X226 + 4869 Xilleon 226 DAIO-1 for X226 + 486a Xilleon 240S HBIU for X240S + 486b Xilleon 240H HBIU for X240H + 486c Xilleon 240S USB for X240S + 486d Xilleon 240H USB for X240H + 486e Xilleon 250 USB 1.1 for X250 + 486f Xilleon 260 USB 1.1 for X260 + 4870 Xilleon 250 HBIU for X250 + 4871 Xilleon 250 IDE for X250 + 4872 Xilleon 234/235 HBIU for X234/X235 + 4873 Xilleon 244/245 HBIU for X244/X245 + 4874 Xilleon 234/235 USB 1.1 for X234/X235 + 4875 Xilleon 260 HBIU for X260 + 4876 Xilleon 260 IDE for X260 + 4877 Xilleon 244/245 USB 1.1 for X244/X245 + 4878 Xilleon 270 HBIU for X270 + 487b Xilleon 242 HBIU for X242 + 487d Xilleon 242 USB 1.1 for X242 + 4880 Xilleon 254 HBIU for X254 + 4881 Xilleon 254 USB 1.1 for X254 + 4882 Xilleon 255 HBIU for X255 + 4883 Xilleon 255 USB 1.1 for X255 + 4884 Xilleon 243 HBIU for X243 + 4885 Xilleon 243 USB 1.1 for X243 + 4886 Xilleon 233 HBIU for X233 + 4887 Xilleon 233 USB 1.1 for X233 + 4888 Xilleon 143 HBIU for X143 + 4889 Xilleon 143 HBIU for X143L + 488a Xilleon 143 HBIU for X143S + 4966 RV250 [Radeon 9000 Series] + 10f1 0002 RV250 If [Tachyon G9000 PRO] + 148c 2039 RV250 If [Radeon 9000 Pro "Evil Commando"] + 1509 9a00 RV250 If [Radeon 9000 "AT009"] + 1681 0040 RV250 If [3D prophet 9000] + 174b 7176 Radeon 9000 Pro + 174b 7192 RV250 If [Radeon 9000 "Atlantis"] + 17af 2005 RV250 If [Excalibur Radeon 9000 Pro] + 17af 2006 RV250 If [Excalibur Radeon 9000] + 496e RV250 [Radeon 9000] (Secondary) + 4a49 R420 [Radeon X800 PRO/GTO AGP] + 174b 2620 R420 [Radeon X800 GTO AGP] + 4a4a R420 [Radeon X800 GT AGP] + 4a4b R420 [Radeon X800 AGP Series] + 4a4d R420 GL [FireGL X3-256] + 4a4e RV420/M18 [Mobility Radeon 9800] + 4a4f R420 [Radeon X850 AGP] + 4a50 R420 [Radeon X800 XT Platinum Edition AGP] + 4a54 R420 [Radeon X800 VE AGP] + 1002 4422 All-In-Wonder X800 VE AGP + 4a69 R420 [Radeon X800 PRO/GTO] (Secondary) + 4a6a R420 [Radeon X800] (Secondary) + 4a6b R420 [Radeon X800 XT AGP] (Secondary) + 4a70 R420 [Radeon X800 XT Platinum Edition AGP] (Secondary) + 4a74 R420 [Radeon X800 VE] (Secondary) + 4b49 R481 [Radeon X850 XT AGP] + 4b4b R481 [Radeon X850 PRO AGP] + 4b4c R481 [Radeon X850 XT Platinum Edition AGP] + 4b69 R481 [Radeon X850 XT AGP] (Secondary) + 4b6b R481 [Radeon X850 PRO AGP] (Secondary) + 4b6c R481 [Radeon X850 XT Platinum Edition AGP] (Secondary) + 4c42 Mach64 LT [3D Rage LT PRO AGP] + 0e11 b0e7 Rage LT Pro (Compaq Presario 5240) + 0e11 b0e8 Rage 3D LT Pro + 0e11 b10e 3D Rage LT Pro (Compaq Armada 1750) + 1002 0040 Rage LT Pro AGP 2X + 1002 0044 Rage LT Pro AGP 2X + 1002 4c42 Rage LT Pro AGP 2X + 1002 8001 Rage LT Pro AGP 2X + 1028 0085 Rage 3D LT Pro + 4c46 Rage Mobility 128 AGP 2X/Mobility M3 + 1002 0155 IBM Thinkpad A22p + 1014 0155 Thinkpad A22p + 1028 00b1 Latitude C600 + 4c47 3D Rage IIC PCI / Mobility Radeon 7500/7500C + 4c49 3D Rage LT PRO PCI + 1002 0004 Rage LT Pro + 1002 0040 Rage LT Pro + 1002 0044 Rage LT Pro + 1002 4c49 Rage LT Pro + 4c4d Rage Mobility AGP 2x Series + 0e11 b111 Armada M700 + 0e11 b160 Armada E500 + 1002 0084 Xpert 98 AGP 2X (Mobility) + 1014 0154 ThinkPad A20m/A21m + 1028 00aa Latitude CPt + 1028 00bb Latitude CPx + 1179 ff00 Satellite 1715XCDS laptop + 13bd 1019 PC-AR10 + 4c50 Rage 3 LT [3D Rage LT PRO PCI] + 1002 4c50 Rage LT Pro + 4c52 M1 [Rage Mobility-M1 PCI] + 1033 8112 Versa Note VXi + 4c54 264LT [Mach64 LT] + 4c57 RV200/M7 [Mobility Radeon 7500] + 1014 0517 ThinkPad T30 + 1014 0530 ThinkPad T4x Series + 1028 00e6 Radeon Mobility M7 LW (Dell Inspiron 8100) + 1028 012a Latitude C640 + 1043 1622 Mobility Radeon M7 (L3C/S) + 144d c006 Radeon Mobility M7 LW in vpr Matrix 170B4 + 4c58 RV200/M7 GL [Mobility FireGL 7800] + 4c59 RV100/M6 [Rage/Radeon Mobility Series] + 0e11 b111 Evo N600c + 1014 0235 ThinkPad A30/A30p (2652/2653) + 1014 0239 ThinkPad X22/X23/X24 + 103c 0025 XE4500 Notebook + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 104d 8140 PCG-Z1SP laptop + 1509 1930 Medion MD9703 + 4c66 RV250/M9 GL [Mobility FireGL 9000/Radeon 9000] + 1014 054d ThinkPad T41 + 4c6e RV250/M9 [Mobility Radeon 9000] (Secondary) + 4d46 Rage Mobility 128 AGP 4X/Mobility M4 + 4d52 Theater 550 PRO PCI [ATI TV Wonder 550] + 4d53 Theater 550 PRO PCIe + 4e44 R300 [Radeon 9700/9700 PRO] + 1002 515e Radeon ES1000 + 1002 5965 Radeon ES1000 + 4e45 R300 [Radeon 9500 PRO/9700] + 1002 0002 Radeon R300 NE [Radeon 9500 Pro] + 1681 0002 Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro] + 4e46 R300 [Radeon 9600 TX] + 4e47 R300 GL [FireGL X1] + 4e48 R350 [Radeon 9800 Series] + 4e49 R350 [Radeon 9800] + 4e4a R360 [Radeon 9800 XXL/XT] + 1002 4e4a R360 [Radeon 9800 XT] + 4e4b R350 GL [FireGL X2 AGP Pro] + 4e50 RV350/M10 / RV360/M11 [Mobility Radeon 9600 (PRO) / 9700] + 1025 005a TravelMate 290 + 1025 0064 Extensa 3000 series laptop: ATI RV360/M11 [Mobility Radeon 9700] + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 144d c00c P35 notebook + 1462 0311 MSI M510A + 1734 1055 Amilo M1420W + 4e51 RV350 [Radeon 9550/9600/X1050 Series] + 4e52 RV350/M10 [Mobility Radeon 9500/9700 SE] + 144d c00c P35 notebook + 4e54 RV350/M10 GL [Mobility FireGL T2] + 4e56 RV360/M12 [Mobility Radeon 9550] + 4e64 R300 [Radeon 9700 PRO] (Secondary) + 4e65 R300 [Radeon 9500 PRO] (Secondary) + 1002 0003 Radeon R300 NE [Radeon 9500 Pro] + 1681 0003 Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro] (Secondary) + 4e66 RV350 [Radeon 9600] (Secondary) + 4e67 R300 GL [FireGL X1] (Secondary) + 4e68 R350 [Radeon 9800 PRO] (Secondary) + 4e69 R350 [Radeon 9800] (Secondary) + 4e6a RV350 [Radeon 9800 XT] (Secondary) + 1002 4e6a R360 [Radeon 9800 XT] (Secondary) + 1002 4e71 M10 NQ [Radeon Mobility 9600] + 4e71 RV350/M10 [Mobility Radeon 9600] (Secondary) + 4f72 RV250 [Radeon 9000 Series] + 4f73 RV250 [Radeon 9000 Series] (Secondary) + 5044 All-In-Wonder 128 PCI + 1002 0028 Rage 128 AIW + 1002 0029 Rage 128 AIW + 5046 Rage 4 [Rage 128 PRO AGP 4X TMDS] + 1002 0004 Rage Fury Pro + 1002 0008 Rage Fury Pro/Xpert 2000 Pro + 1002 0014 Rage Fury Pro + 1002 0018 Rage Fury Pro/Xpert 2000 Pro + 1002 0028 Rage 128 Pro AIW AGP + 1002 002a Rage 128 Pro AIW AGP + 1002 0048 Rage Fury Pro + 1002 2000 Rage Fury MAXX AGP 4x (TMDS) (VGA device) + 1002 2001 Rage Fury MAXX AGP 4x (TMDS) (Extra device?!) + 5050 Rage128 [Xpert 128 PCI] + 1002 0008 Xpert 128 + 5052 Rage 128 PRO AGP 4X TMDS + 5144 R100 [Radeon 7200 / All-In-Wonder Radeon] + 1002 0008 Radeon 7000/Radeon VE + 1002 0009 Radeon 7000/Radeon + 1002 000a Radeon 7000/Radeon + 1002 001a Radeon 7000/Radeon + 1002 0029 Radeon AIW + 1002 0038 Radeon 7000/Radeon + 1002 0039 Radeon 7000/Radeon + 1002 008a Radeon 7000/Radeon + 1002 00ba Radeon 7000/Radeon + 1002 0139 Radeon 7000/Radeon + 1002 028a Radeon 7000/Radeon + 1002 02aa Radeon AIW + 1002 053a Radeon 7000/Radeon + 5148 R200 GL [FireGL 8800] + 1002 010a FireGL 8800 64Mb + 1002 0152 FireGL 8800 128Mb + 1002 0162 FireGL 8700 32Mb + 1002 0172 FireGL 8700 64Mb + 514c R200 [Radeon 8500/8500 LE] + 1002 003a Radeon R200 QL [Radeon 8500 LE] + 1002 013a Radeon 8500 + 148c 2026 R200 QL [Radeon 8500 Evil Master II Multi Display Edition] + 1681 0010 Radeon 8500 [3D Prophet 8500 128Mb] + 174b 7149 Radeon 8500 LE + 1787 0f08 Radeon R200 QL [PowerMagic Radeon 8500] + 514d R200 [Radeon 9100] + 5157 RV200 [Radeon 7500/7500 LE] + 1002 013a Radeon 7500 + 1002 0f2b ALL-IN-WONDER VE PCI + 1002 103a Dell Optiplex GX260 + 1458 4000 RV200 QW [RADEON 7500 PRO MAYA AR] + 148c 2024 RV200 QW [Radeon 7500LE Dual Display] + 148c 2025 RV200 QW [Radeon 7500 Evil Master Multi Display Edition] + 148c 2036 RV200 QW [Radeon 7500 PCI Dual Display] + 174b 7146 RV200 QW [Radeon 7500 LE] + 174b 7147 Radeon 7500 LE + 174b 7161 Radeon RV200 QW [Radeon 7500 LE] + 17af 0202 RV200 QW [Excalibur Radeon 7500LE] + 5159 RV100 [Radeon 7000 / Radeon VE] + 1002 000a Radeon 7000/Radeon VE + 1002 000b Radeon 7000 + 1002 0038 Radeon 7000/Radeon VE + 1002 003a Radeon 7000/Radeon VE + 1002 00ba Radeon 7000/Radeon VE + 1002 013a Radeon 7000/Radeon VE + 1002 0908 XVR-100 (supplied by Sun) +# The IBM card doubles as an ATI PCI video adapter + 1014 029a Remote Supervisor Adapter II (RSA2) + 1014 02c8 eServer xSeries server mainboard + 1028 016c PowerEdge 1850 Embedded Radeon 7000/VE + 1028 016d PowerEdge 2850 Embedded Radeon 7000-M + 1028 0170 PowerEdge 6850 Embedded Radeon 7000/VE + 1028 019a PowerEdge SC1425 + 103c 1292 Radeon 7000 + 1043 c00a A7000/T/64M + 1458 4002 RV100 QY [RADEON 7000 PRO MAYA AV Series] + 148c 2003 RV100 QY [Radeon 7000 Multi-Display Edition] + 148c 2023 RV100 QY [Radeon 7000 Evil Master Multi-Display] + 148c 2081 RV6DE + 174b 0280 Radeon RV100 QY [Radeon 7000/VE] + 174b 7112 Radeon VE 7000 + 174b 7c28 Radeon VE 7000 DDR + 1787 0202 RV100 QY [Excalibur Radeon 7000] + 17ee 1001 Radeon 7000 64MB DDR + DVI + 515e ES1000 + 1028 01bb PowerEdge 1955 Embedded ATI ES1000 + 1028 01df PowerEdge SC440 + 1028 01e6 PowerEdge 860 + 1028 01f0 PowerEdge R900 Embedded ATI ES1000 + 1028 0205 PowerEdge 2970 Embedded ATI ES1000 + 1028 020b PowerEdge T605 Embedded ATI ES1000 + 1028 020f PowerEdge R300 Embedded ATI ES1000 + 1028 0210 PowerEdge T300 Embedded ATI ES1000 + 1028 0221 PowerEdge R805 Embedded ATI ES1000 + 1028 0223 PowerEdge R905 Embedded ATI ES1000 + 1028 0225 PowerEdge T105 Embedded ATI ES1000 + 1028 023c PowerEdge R200 Embedded ATI ES1000 + 103c 1304 Integrity iLO2 Advanced KVM VGA [AD307A] + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 5245 Rage 128 GL PCI + 1002 0008 Xpert 128 + 1002 0028 Rage 128 AIW + 1002 0029 Rage 128 AIW + 1002 0068 Rage 128 AIW + 5246 Rage 128 (Rage 4) series + 1002 0004 Magnum/Xpert 128/Xpert 99 + 1002 0008 Rage 128 AGP 2x + 1002 0028 Rage 128 AIW AGP + 1002 0044 Rage Fury/Xpert 128/Xpert 2000 + 1002 0068 Rage 128 AIW AGP + 1002 0448 Rage Fury + 524b Rage 128 VR PCI + 524c Rage 128 VR AGP + 1002 0008 Xpert 99/Xpert 2000 + 1002 0088 Xpert 99 + 5346 Rage 128 SF/4x AGP 2x + 1002 0048 RAGE 128 16MB VGA TVOUT AMC PAL + 534d Rage 128 4X AGP 4x + 1002 0008 Xpert 99/Xpert 2000 + 1002 0018 Xpert 2000 + 5354 Mach 64 VT + 1002 5654 Mach 64 reference + 5446 Rage 128 PRO Ultra AGP 4x + 1002 0004 Rage Fury Pro + 1002 0008 Rage Fury Pro/Xpert 2000 Pro + 1002 0018 Rage Fury Pro/Xpert 2000 Pro + 1002 0028 Rage 128 AIW Pro AGP + 1002 0029 Rage 128 AIW + 1002 002a Rage 128 AIW Pro AGP + 1002 002b Rage 128 AIW + 1002 0048 Xpert 2000 Pro + 5452 Rage 128 PRO Ultra4XL VR-R AGP + 1002 001c Rage 128 Pro 4XL + 103c 1279 Rage 128 Pro 4XL + 5460 RV370/M22 [Mobility Radeon X300] + 1775 1100 CR11/VR11 Single Board Computer + 5461 RV370/M22 [Mobility Radeon X300] + 5462 RV380/M24C [Mobility Radeon X600 SE] + 5464 RV370/M22 GL [Mobility FireGL V3100] + 5549 R423 [Radeon X800 GTO] + 554a R423 [Radeon X800 XT Platinum Edition] + 554b R423 [Radeon X800 GT/SE] + 1002 0302 Radeon X800 SE + 554d R430 [Radeon X800 XL] + 1002 0322 All-In-Wonder X800 XL + 1458 2124 GV-R80L256V-B (AGP) + 554e R430 [All-In-Wonder X800 GT] + 554f R430 [Radeon X800] + 5550 R423 GL [FireGL V7100] + 5551 R423 GL [FireGL V5100] + 5569 R423 [Radeon X800 PRO] (Secondary) + 556b R423 [Radeon X800 GT] (Secondary) + 556d R430 [Radeon X800 XL] (Secondary) + 1458 2125 GV-R80L256V-B (AGP) + 556f R430 [Radeon X800] (Secondary) + 5571 R423 GL [FireGL V5100] (Secondary) + 564b RV410/M26 GL [Mobility FireGL V5000] + 564f RV410/M26 [Mobility Radeon X700 XL] + 5652 RV410/M26 [Mobility Radeon X700] + 5653 RV410/M26 [Mobility Radeon X700] + 1025 0080 Aspire 5024WLMi + 103c 0940 Compaq NW8240 Mobile Workstation + 5654 Mach64 VT [Video Xpression] + 1002 5654 Mach64VT Reference + 5655 264VT3 [Mach64 VT3] + 5656 Mach64 VT4 [Video Xpression+] + 5657 RV410 [Radeon X550 XTX / X700] + 5830 RS300 Host Bridge + 5831 RS300 Host Bridge + 5832 RS300 Host Bridge + 5833 RS300 Host Bridge + 5834 RS300 [Radeon 9100 IGP] + 5835 RS300M [Mobility Radeon 9100 IGP] + 5838 RS300 AGP Bridge + 5854 RS480 [Radeon Xpress 200 Series] (Secondary) + 5874 RS480 [Radeon Xpress 1150] (Secondary) + 5940 RV280 [Radeon 9200 PRO] (Secondary) + 17af 2021 Excalibur Radeon 9250 (Secondary) + 5941 RV280 [Radeon 9200] (Secondary) + 1458 4019 Radeon 9200 + 174b 7c12 Radeon 9200 + 17af 200d Excalibur Radeon 9200 + 18bc 0050 GC-R9200-C3 (Secondary) + 5944 RV280 [Radeon 9200 SE PCI] + 5950 RS480/RS482/RS485 Host Bridge + 1025 0080 Aspire 5024WLMMi + 103c 280a DC5750 Microtower + 103c 2a20 Pavilion t3030.de Desktop PC + 103c 308b MX6125 + 1462 0131 MS-1013 Notebook + 1462 7217 Aspire L250 + 5951 RX480/RX482 Host Bridge + 5952 RD580 Host Bridge + 5954 RS480 [Radeon Xpress 200 Series] + 1002 5954 RV370 [Radeon Xpress 200G Series] + 5955 RS480M [Mobility Radeon Xpress 200] + 1002 5955 RS480 0x5955 [Radeon XPRESS 200M 5955 (PCIE)] + 103c 308b MX6125 + 1462 0131 MS-1013 Notebook + 5956 RD790 Host Bridge + 5957 RX780/RX790 Host Bridge + 1849 5957 A770CrossFire Motherboard + 5958 RD780 Host Bridge + 5960 RV280 [Radeon 9200 PRO] + 17af 2020 Excalibur Radeon 9250 + 5961 RV280 [Radeon 9200] + 1002 2f72 All-in-Wonder 9200 Series + 1019 4c30 Radeon 9200 VIVO + 12ab 5961 YUAN SMARTVGA Radeon 9200 + 1458 4018 Radeon 9200 + 174b 7c13 Radeon 9200 + 17af 200c Excalibur Radeon 9200 + 18bc 0050 Radeon 9200 Game Buster + 18bc 0051 GC-R9200-C3 + 18bc 0053 Radeon 9200 Game Buster VIVO + 5962 RV280 [Radeon 9200] + 5964 RV280 [Radeon 9200 SE] + 1002 5964 Radeon 9200 SE, 64-bit 128MB DDR, 200/166MHz + 1043 c006 Radeon 9200 SE / TD / 128M + 1458 4018 Radeon 9200 SE + 1458 4032 Radeon 9200 SE 128MB + 147b 6191 R9200SE-DT + 148c 2073 CN-AG92E + 174b 7c13 Radeon 9200 SE + 1787 5964 Excalibur 9200SE VIVO 128M + 17af 2012 Radeon 9200 SE Excalibur + 18bc 0170 Sapphire Radeon 9200 SE 128MB Game Buster + 18bc 0173 GC-R9200L(SE)-C3H [Radeon 9200 Game Buster] + 5965 RV280 GL [FireMV 2200 PCI] + 5974 RS482/RS485 [Radeon Xpress 1100/1150] + 103c 280a DC5750 Microtower + 1462 7141 Aspire L250 + 5975 RS482M [Mobility Radeon Xpress 200] + 5978 RX780/RD790 PCI to PCI bridge (external gfx0 port A) + 1849 5957 A770CrossFire Motherboard + 5979 RD790 PCI to PCI bridge (external gfx0 port B) + 597a RD790 PCI to PCI bridge (PCI express gpp port A) + 597b RX780/RD790 PCI to PCI bridge (PCI express gpp port B) + 597c RD790 PCI to PCI bridge (PCI express gpp port C) + 597d RX780/RD790 PCI to PCI bridge (PCI express gpp port D) + 597e RD790 PCI to PCI bridge (PCI express gpp port E) + 1849 5957 A770CrossFire Motherboard + 597f RD790 PCI to PCI bridge (PCI express gpp port F) + 1849 5957 A770CrossFire Motherboard + 5980 RD790 PCI to PCI bridge (external gfx1 port A) + 5981 RD790 PCI to PCI bridge (external gfx1 port B) + 5982 RD790 PCI to PCI bridge (NB-SB link) + 5a10 RD890 Northbridge only dual slot (2x16) PCI-e GFX Hydra part + 5a11 RD890 Northbridge only single slot PCI-e GFX Hydra part + 5a12 RD890 Northbridge only dual slot (2x8) PCI-e GFX Hydra part + 15d9 a811 H8DGU + 5a13 RD890S/SR5650 Host Bridge + 5a14 RD9x0/RX980 Host Bridge + 5a15 RD890 PCI to PCI bridge (PCI express gpp port A) + 5a16 RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GFX port 0) + 5a17 RD890/RD9x0 PCI to PCI bridge (PCI Express GFX port 1) + 5a18 RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 0) + 15d9 a811 H8DGU + 5a19 RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 1) + 5a1a RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 2) + 5a1b RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 3) + 5a1c RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 4) + 5a1d RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP Port 5) + 5a1e RD890/RD9x0/RX980 PCI to PCI bridge (PCI Express GPP2 Port 0) + 5a1f RD890/RD990 PCI to PCI bridge (PCI Express GFX2 port 0) + 15d9 a811 H8DGU + 5a20 RD890/RD990 PCI to PCI bridge (PCI Express GFX2 port 1) + 5a23 RD890S/RD990 I/O Memory Management Unit (IOMMU) + 5a31 RC410 Host Bridge + 5a33 RS400 Host Bridge + 5a34 RS4xx PCI Express Port [ext gfx] + 5a36 RC4xx/RS4xx PCI Express Port 1 + 5a37 RC4xx/RS4xx PCI Express Port 2 + 5a38 RC4xx/RS4xx PCI Express Port 3 + 5a39 RC4xx/RS4xx PCI Express Port 4 + 5a3f RC4xx/RS4xx PCI Bridge [int gfx] + 1462 7217 Aspire L250 + 5a41 RS400 [Radeon Xpress 200] + 5a42 RS400M [Radeon Xpress 200M] + 5a61 RC410 [Radeon Xpress 200/1100] + 5a62 RC410M [Mobility Radeon Xpress 200M] + 5b60 RV370 [Radeon X300] + 1043 002a Extreme AX300SE-X + 1043 032e Extreme AX300/TD + 1458 2102 GV-RX30S128D (X300SE) + 1462 0400 RX300SE-TD128E (MS-8940 REV:200) + 1462 0402 RX300SE-TD128E (MS-8940) + 174b 0500 Radeon X300 (PCIE) + 196d 1086 X300SE HM + 5b62 RV370 [Radeon X600/X600 SE] + 5b63 RV370 [Radeon X300/X550/X1050 Series] + 5b64 RV370 GL [FireGL V3100] + 5b65 RV370 GL [FireMV 2200] + 5b66 RV370X + 5b70 RV370 [Radeon X300 SE] +# RX300SE-TD128E + 1462 0403 Radeon X300 SE 128MB DDR + 174b 0501 Radeon X300 SE + 196d 1087 Radeon X300 SE HyperMemory + 5b72 RV380 [Radeon X300/X550/X1050 Series] (Secondary) + 5b73 RV370 [Radeon X300/X550/X1050 Series] (Secondary) + 5b74 RV370 GL [FireGL V3100] (Secondary) + 5b75 RV370 GL [FireMV 2200] (Secondary) + 5c61 RV280/M9+ [Mobility Radeon 9200 AGP] + 5c63 RV280/M9+ [Mobility Radeon 9200 AGP] + 1002 5c63 Apple iBook G4 2004 + 144d c00c P30 notebook + 5d44 RV280 [Radeon 9200 SE] (Secondary) + 1458 4019 Radeon 9200 SE (Secondary) + 1458 4032 Radeon 9200 SE 128MB + 147b 6190 R9200SE-DT (Secondary) + 174b 7c12 Radeon 9200 SE (Secondary) + 1787 5965 Excalibur 9200SE VIVO 128M (Secondary) + 17af 2013 Radeon 9200 SE Excalibur (Secondary) + 18bc 0171 Radeon 9200 SE 128MB Game Buster (Secondary) + 18bc 0172 GC-R9200L(SE)-C3H [Radeon 9200 Game Buster] + 5d45 RV280 GL [FireMV 2200 PCI] (Secondary) + 5d48 R423/M28 [Mobility Radeon X800 XT] + 5d49 R423/M28 GL [Mobility FireGL V5100] + 5d4a R423/M28 [Mobility Radeon X800] + 5d4d R480 [Radeon X850 XT Platinum Edition] + 5d4e R480 [Radeon X850 SE] + 5d4f R480 [Radeon X800 GTO] + 5d50 R480 GL [FireGL V7200] + 5d52 R480 [Radeon X850 XT] + 1002 0b12 PowerColor X850XT PCIe (Primary) + 5d57 R423 [Radeon X800 XT] + 5d6d R480 [Radeon X850 XT Platinum Edition] (Secondary) + 5d6f R480 [Radeon X800 GTO] (Secondary) + 5d72 R480 [Radeon X850 XT] (Secondary) + 1002 0b13 PowerColor X850XT PCIe (Secondary) + 5d77 R423 [Radeon X800 XT] (Secondary) + 5e48 RV410 GL [FireGL V5000] + 5e49 RV410 [Radeon X700 Series] + 5e4a RV410 [Radeon X700 XT] + 5e4b RV410 [Radeon X700 PRO] + 5e4c RV410 [Radeon X700 SE] + 5e4d RV410 [Radeon X700] + 148c 2116 Bravo X700 + 5e4f RV410 [Radeon X700] + 1569 1e4f Radeon X550 XT + 5e6b RV410 [Radeon X700 PRO] (Secondary) + 5e6d RV410 [Radeon X700] (Secondary) + 148c 2117 Bravo X700 (Secondary) + 5f57 R423 [Radeon X800 XT] + 6600 Mars [Radeon HD 8670A/8670M/8750M] + 103c 1952 ProBook 455 G1 + 6601 Mars [Radeon HD 8730M] + 103c 2100 FirePro M4100 + 6604 Opal XT [Radeon R7 M265/M365X/M465] + 1025 0776 Aspire V5 Radeon R7 M265 + 103c 8006 FirePro M4170 + 103c 814f Litho XT [Radeon R7 M365X] + 103c 82aa Litho XT [Radeon R7 M465] + 17aa 3643 Radeon R7 A360 + 6605 Opal PRO [Radeon R7 M260X] + 103c 2259 FirePro M4150 + 6606 Mars XTX [Radeon HD 8790M] + 1028 0684 FirePro W4170M + 6607 Mars LE [Radeon HD 8530M / R5 M240] + 6608 Oland GL [FirePro W2100] + 13cc 3d28 MXRT-2600 + 6610 Oland XT [Radeon HD 8670 / R7 250/350] + 1019 0030 Radeon HD 8670 + 1028 2120 Radeon R7 250 + 1028 2322 Radeon R7 250 + 1462 2910 Radeon HD 8670 + 1462 2911 Radeon HD 8670 + 148c 7350 Radeon R7 350 + 1642 3c81 Radeon HD 8670 + 1642 3c91 Radeon HD 8670 + 1642 3f09 Radeon R7 350 + 6611 Oland [Radeon HD 8570 / R7 240/340 OEM] + 1028 210b Radeon R5 240 OEM + 174b 4248 Radeon R7 240 OEM + 174b a240 Radeon R7 240 OEM + 174b d340 Radeon R7 340 OEM + 1b0a 90d3 Radeon R7 240 OEM + 6613 Oland PRO [Radeon R7 240/340] + 148c 7340 Radeon R7 340 + 1682 7240 R7 240 2048 MB + 6631 Oland + 6640 Saturn XT [FirePro M6100] + 106b 014b Tropo XT [Radeon R9 M380 Mac Edition] + 6641 Saturn PRO [Radeon HD 8930M] + 6646 Bonaire XT [Radeon R9 M280X] + 6647 Saturn PRO/XT [Radeon R9 M270X/M280X] + 1043 223d N551ZU laptop Radeon R9 M280X + 6649 Bonaire [FirePro W5100] + 1002 0b0c FirePro W4300 + 103c 0b0c Bonaire [FirePro W4300] + 103c 230c FirePro W5100 + 13cc 3d2a MXRT-5600 + 6650 Bonaire + 6651 Bonaire + 6658 Bonaire XTX [Radeon R7 260X/360] + 1043 04d3 AMD Radeon R7 260X + 148c 0907 Radeon R7 360 + 1682 0907 Radeon R7 360 + 1682 7360 Radeon R7 360 + 665c Bonaire XT [Radeon HD 7790/8770 / R7 360 / R9 260/360 OEM] + 1043 0452 Radeon HD 7790 DirectCU II OC +# R7790-1GD5/OC + 1462 2930 Radeon HD 7790 OC + 1462 2932 Radeon HD 8770 + 1462 2934 Radeon R9 260 OEM + 1462 2938 Radeon R9 360 OEM + 148c 0907 Radeon R7 360 + 148c 9260 Radeon R9 260 OEM + 148c 9360 Radeon R9 360 OEM + 1682 0907 Radeon R7 360 +# FX-779A-CDB4 / FX-779A-CDBC + 1682 3310 Radeon HD 7790 Black Edition 2 GB +# 100356OCL / 11210-01-20G + 174b e253 Radeon HD 7790 Dual-X OC + 1787 2329 Radeon HD 7790 TurboDuo + 665d Bonaire [Radeon R7 200 Series] + 665f Tobago PRO [Radeon R7 360 / R9 360 OEM] + 1028 0b04 Radeon R9 360 OEM + 1462 2938 Radeon R9 360 OEM + 1462 3271 Radeon R9 360 OEM + 1682 7360 Radeon R7 360 + 6660 Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330 / M430 / Radeon 520 Mobile] + 1028 05ea Radeon HD 8670M + 1028 06bf Radeon R5 M335 + 103c 1970 Radeon HD 8670M + 103c 80be Radeon R5 M330 + 103c 8136 Radeon R5 M330 + 103c 8329 Radeon R7 M520 + 17aa 3633 Radeon R5 A330 + 17aa 3804 Radeon R5 M330 + 17aa 3809 Radeon R5 M330 + 17aa 381a Radeon R5 M430 + 17aa 390c Radeon R5 M330 + 6663 Sun PRO [Radeon HD 8570A/8570M] + 1025 0846 Radeon HD 8570A + 17aa 3805 Radeon HD 8570M + 6664 Jet XT [Radeon R5 M240] + 6665 Jet PRO [Radeon R5 M230 / R7 M260DX / Radeon 520 Mobile] + 17aa 1309 Radeon R7 M260DX + 17aa 368f Radeon R5 A230 + 6667 Jet ULT [Radeon R5 M230] + 666f Sun LE [Radeon HD 8550M / R5 M230] + 66a0 Vega 20 [Radeon Instinct] + 66a1 Vega 20 + 66a2 Vega 20 + 66a3 Vega 20 + 66a7 Vega 20 [Radeon Pro Vega 20] + 66af Vega 20 [Radeon VII] + 6704 Cayman PRO GL [FirePro V7900] + 6707 Cayman LE GL [FirePro V5900] + 6718 Cayman XT [Radeon HD 6970] + 6719 Cayman PRO [Radeon HD 6950] + 671c Antilles [Radeon HD 6990] + 671d Antilles [Radeon HD 6990] + 671f Cayman CE [Radeon HD 6930] + 6720 Blackcomb [Radeon HD 6970M/6990M] + 1028 048f Radeon HD 6990M + 1028 0490 Alienware M17x R3 Radeon HD 6970M + 1028 04a4 FirePro M8900 + 1028 04ba Radeon HD 6990M + 1028 053f FirePro M8900 + 106b 0b00 Radeon HD 6970M + 1558 5102 Radeon HD 6970M + 1558 5104 Radeon HD 6990M + 1558 7201 Radeon HD 6990M + 174b e188 Radeon HD 6970M + 6738 Barts XT [Radeon HD 6870] +# HD-687A-ZDFC + 1682 3103 Radeon HD 8670 + 1787 201a Barts XT [Radeon HD 6870 X2] + 1787 201b Barts XT [Radeon HD 6870 X2] + 6739 Barts PRO [Radeon HD 6850] + 1043 03b4 EAH6850 [Radeon HD 6850] + 673e Barts LE [Radeon HD 6790] + 148c 7720 Radeon HD 7720 OEM + 6740 Whistler [Radeon HD 6730M/6770M/7690M XT] + 1019 238c Radeon HD 6730M + 1019 238e Radeon HD 6730M + 1019 2391 Radeon HD 6730M + 1019 2392 Radeon HD 6770M + 1028 04a3 Precision M4600 + 1028 053e FirePro M5950 + 103c 1630 FirePro M5950 + 103c 1631 FirePro M5950 + 103c 164b Radeon HD 6730M + 103c 164e Radeon HD 6730M + 103c 1657 Radeon HD 6770M + 103c 1658 Radeon HD 6770M + 103c 165a Radeon HD 6770M + 103c 165b Radeon HD 6770M + 103c 1688 Radeon HD 6770M + 103c 1689 Radeon HD 6770M + 103c 168a Radeon HD 6770M + 103c 185e Radeon HD 7690M XT + 103c 3388 Radeon HD 6770M + 103c 3389 Radeon HD 6770M + 103c 3582 Radeon HD 6770M + 103c 366c Radeon HD 6730M + 1043 1d02 Radeon HD 6730M + 1043 1d12 Radeon HD 6730M + 104d 9084 Radeon HD 6730M + 104d 9085 Radeon HD 6730M + 144d b074 Radeon HD 6730M + 144d b077 Radeon HD 6730M + 144d b084 Radeon HD 6730M + 144d b088 Radeon HD 6730M + 17aa 3982 Radeon HD 6730M + 6741 Whistler [Radeon HD 6630M/6650M/6750M/7670M/7690M] + 1019 238e Radeon HD 6650M + 1019 238f Radeon HD 6650M + 1025 0379 Radeon HD 6650M + 1025 037b Radeon HD 6650M + 1025 037e Radeon HD 6650M + 1025 0382 Radeon HD 6650M + 1025 0384 Radeon HD 6650M + 1025 0385 Radeon HD 6650M + 1025 0386 Radeon HD 6650M + 1025 0387 Radeon HD 6650M + 1025 0388 Radeon HD 6650M + 1025 0442 Radeon HD 6650M + 1025 0451 Radeon HD 6650M + 1025 0489 Radeon HD 6650M + 1025 048b Radeon HD 6650M + 1025 048c Radeon HD 6650M + 1025 050a Radeon HD 6650M + 1025 050b Radeon HD 6650M + 1025 050c Radeon HD 6650M + 1025 050e Radeon HD 6650M + 1025 050f Radeon HD 6650M + 1025 0513 Radeon HD 6650M + 1025 0514 Radeon HD 6650M + 1025 0515 Radeon HD 6650M + 1025 0516 Radeon HD 6650M + 1025 051e Radeon HD 6650M + 1025 051f Radeon HD 6650M + 1025 0520 Radeon HD 6650M + 1025 0521 Radeon HD 6650M + 1025 052a Radeon HD 6650M + 1025 0555 Radeon HD 6650M + 1025 0556 Radeon HD 6650M + 1025 055d Radeon HD 6650M + 1025 055e Radeon HD 6650M + 1025 056d Radeon HD 6650M + 1025 059a Radeon HD 6650M + 1025 059b Radeon HD 6650M + 1025 059e Radeon HD 6650M + 1025 059f Radeon HD 6650M + 1025 0600 Radeon HD 6650M + 1025 0605 Radeon HD 6650M + 1025 0606 Radeon HD 6650M + 1025 0619 Radeon HD 6650M + 1028 04c1 Radeon HD 6630M + 1028 04c5 Radeon HD 6630M + 1028 04cd Radeon HD 6630M + 1028 04d7 Radeon HD 6630M + 1028 04d9 Radeon HD 6630M + 1028 052d Radeon HD 6630M + 103c 1617 Radeon HD 6650M + 103c 1646 Radeon HD 6750M + 103c 1647 Radeon HD 6650M + 103c 164b Radeon HD 6650M + 103c 164e Radeon HD 6650M + 103c 1688 Radeon HD 6750M + 103c 1689 Radeon HD 6750M + 103c 168a Radeon HD 6750M + 103c 1860 Radeon HD 7690M + 103c 3385 Radeon HD 6630M + 103c 3560 Radeon HD 6750M + 103c 358d Radeon HD 6750M + 103c 3590 Radeon HD 6750M + 103c 3593 Radeon HD 6750M + 103c 366c Radeon HD 6650M + 1043 1cd2 Radeon HD 6650M + 1043 2121 Radeon HD 6650M + 1043 2122 Radeon HD 6650M + 1043 2123 Radeon HD 6650M + 1043 2125 Radeon HD 7670M + 1043 2127 Radeon HD 7670M + 104d 907b Radeon HD 6630M + 104d 9080 Radeon HD 6630M + 104d 9081 Radeon HD 6630M + 106b 00e2 MacBookPro8,2 [Core i7, 15", Late 2011] + 1179 fd63 Radeon HD 6630M + 1179 fd65 Radeon HD 6630M + 144d c093 Radeon HD 6650M + 144d c0ac Radeon HD 6650M + 144d c0b3 Radeon HD 6750M + 144d c539 Radeon HD 6630M + 144d c609 Radeon HD 6630M + 152d 0914 Radeon HD 6650M + 17aa 21e1 Radeon HD 6630M + 17aa 3970 Radeon HD 6650M + 17aa 3976 Radeon HD 6650M + 1854 0907 Radeon HD 6650M + 6742 Whistler LE [Radeon HD 6610M/7610M] + 1002 6570 Turks [Radeon HD 6570] + 1019 2393 Radeon HD 6610M + 1043 1d82 K53SK Laptop Radeon HD 7610M + 1179 fb22 Radeon HD 7610M + 1179 fb23 Radeon HD 7610M + 1179 fb27 Radeon HD 7610M + 1179 fb2a Radeon HD 7610M + 1179 fb2c Radeon HD 7610M + 1179 fb30 Radeon HD 7610M + 1179 fb31 Radeon HD 7610M + 1179 fb32 Radeon HD 7610M + 1179 fb38 Radeon HD 7610M + 1179 fb39 Radeon HD 7610M + 1179 fb3a Radeon HD 7610M + 1179 fb3b Radeon HD 7610M + 1179 fb40 Radeon HD 7610M + 1179 fb41 Radeon HD 7610M + 1179 fb47 Radeon HD 7610M + 1179 fb48 Radeon HD 7610M + 1179 fb49 Radeon HD 7610M + 1179 fb51 Radeon HD 7610M + 1179 fb52 Radeon HD 7610M + 1179 fb53 Radeon HD 7610M + 1179 fb56 Radeon HD 7610M + 1179 fb81 Radeon HD 7610M + 1179 fb82 Radeon HD 7610M + 1179 fb83 Radeon HD 7610M + 1179 fc56 Radeon HD 7610M + 1179 fcd4 Radeon HD 7610M + 1179 fcee Radeon HD 7610M + 1458 6570 Turks [Radeon HD 6570] + 1462 6570 Turks [Radeon HD 6570] + 148c 6570 Turks [Radeon HD 6570] + 1682 6570 Turks [Radeon HD 6570] + 174b 5570 Turks [Radeon HD 5570] + 174b 6570 Turks [Radeon HD 6570] + 174b 7570 Turks [Radeon HD 7570] + 174b 8510 Turks [Radeon HD 8510] + 174b 8570 Turks [Radeon HD 8570] + 1787 6570 Turks [Radeon HD 6570] + 17af 6570 Turks [Radeon HD 6570] + 8086 2111 Radeon HD 6625M + 6743 Whistler [Radeon E6760] + 6749 Turks GL [FirePro V4900] + 15c3 2b06 MED-X4900 + 674a Turks GL [FirePro V3900] + 13cc 3d22 MXRT-2500 + 15c3 0106 MED-X3900 + 6750 Onega [Radeon HD 6650A/7650A] + 1462 2670 Radeon HD 6670A + 17aa 3079 Radeon HD 7650A + 17aa 307a Radeon HD 6650A + 17aa 3087 Radeon HD 7650A + 17aa 3618 Radeon HD 6650A + 17aa 3623 Radeon HD 6650A + 17aa 3627 Radeon HD 6650A + 6751 Turks [Radeon HD 7650A/7670A] + 1028 0548 Radeon HD 7650A + 1462 2671 Radeon HD 7670A + 1462 2672 Radeon HD 7670A + 1462 2680 Radeon HD 7650A + 1462 2681 Radeon HD 7650A + 17aa 3087 Radeon HD 7650A + 6758 Turks XT [Radeon HD 6670/7670] + 1028 0b0e Radeon HD 6670 + 103c 6882 Radeon HD 6670 + 1462 250a Radeon HD 7670 + 148c 7670 Radeon HD 7670 + 1545 7670 Radeon HD 7670 + 1682 3300 Radeon HD 7670 + 174b 7670 Radeon HD 7670 + 174b e181 Radeon HD 6670 + 1787 2309 Radeon HD 6670 + 6759 Turks PRO [Radeon HD 6570/7570/8550] + 103c 3130 Radeon HD 6570 + 1043 0403 Radeon HD 6570 + 1462 2500 Radeon HD 6570 + 1462 2509 Radeon HD 7570 + 148c 7570 Radeon HD 7570 + 1642 3a67 Radeon HD 6570 + 1682 3280 Radeon HD 7570 + 1682 3530 Radeon HD 8550 + 174b 7570 Radeon HD 7570 + 174b e142 Radeon HD 6570 + 174b e181 Radeon HD 6570 + 1b0a 908f Radeon HD 6570 + 1b0a 9090 Radeon HD 6570 + 1b0a 9091 Radeon HD 6570 + 1b0a 9092 Radeon HD 6570 + 1b0a 909e Radeon HD 6570 + 1b0a 90b5 Radeon HD 7570 + 1b0a 90b6 Radeon HD 7570 + 675b Turks [Radeon HD 7600 Series] + 675d Turks PRO [Radeon HD 7570] + 675f Turks LE [Radeon HD 5570/6510/7510/8510] + 148c 6510 Radeon HD 6510 + 148c 6530 Radeon HD 6530 + 148c 7510 Radeon HD 7510 + 1545 7570 Radeon HD 7570 + 174b 6510 Radeon HD 6510 + 174b 7510 Radeon HD 7510 + 174b 8510 Radeon HD 8510 + 1787 2012 Radeon HD 5570 2GB GDDR3 + 1787 2314 Radeon HD 5570 1GB DDR2/GDDR3 + 6760 Seymour [Radeon HD 6400M/7400M Series] + 1002 0124 Radeon HD 6470M + 1002 0134 Radeon HD 6470M + 1019 238b Radeon HD 6470M + 1019 238e Radeon HD 6470M + 1019 2390 Radeon HD 6470M + 1019 9985 Radeon HD 6470M + 1028 04c1 Radeon HD 6470M + 1028 04c3 Radeon HD 6470M + 1028 04ca Radeon HD 6470M + 1028 04cb Radeon HD 6470M + 1028 04cc Vostro 3350 + 1028 04d1 Radeon HD 6470M + 1028 04d3 Radeon HD 6470M + 1028 04d7 Radeon HD 6470M + 1028 0502 Radeon HD 6470M + 1028 0503 Radeon HD 6470M + 1028 0506 Radeon HD 6470M + 1028 0507 Radeon HD 6470M + 1028 0514 Radeon HD 6470M + 1028 051c Radeon HD 6450M + 1028 051d Radeon HD 6450M + 103c 161a Radeon HD 6470M + 103c 161b Radeon HD 6470M + 103c 161e Radeon HD 6470M + 103c 161f Radeon HD 6470M + 103c 1622 Radeon HD 6450M + 103c 1623 Radeon HD 6450M + 103c 164a Radeon HD 6470M + 103c 164d Radeon HD 6470M + 103c 1651 Radeon HD 6470M + 103c 1656 Radeon HD 6490M + 103c 1658 Radeon HD 6490M + 103c 1659 Radeon HD 6490M + 103c 165b Radeon HD 6490M + 103c 165d Radeon HD 6470M + 103c 165f Radeon HD 6470M + 103c 1661 Radeon HD 6470M + 103c 1663 Radeon HD 6470M + 103c 1665 Radeon HD 6470M + 103c 1667 Radeon HD 6470M + 103c 1669 Radeon HD 6470M + 103c 166b Radeon HD 6470M + 103c 166c Radeon HD 6470M + 103c 166e Radeon HD 6470M + 103c 1670 Radeon HD 6470M + 103c 1672 Radeon HD 6470M + 103c 167a Radeon HD 6470M + 103c 167b Radeon HD 6470M + 103c 167d Radeon HD 6490M + 103c 167f Radeon HD 6490M + 103c 168c Radeon HD 6470M + 103c 168f Radeon HD 6470M + 103c 1694 Radeon HD 6470M + 103c 1696 Radeon HD 6470M + 103c 1698 Radeon HD 6470M + 103c 169a Radeon HD 6470M + 103c 169c Radeon HD 6490M + 103c 1855 Radeon HD 7450M + 103c 1859 Radeon HD 7450M + 103c 185c Radeon HD 7450M + 103c 185d Radeon HD 7470M + 103c 185f Radeon HD 7470M + 103c 1863 Radeon HD 7450M + 103c 355c Radeon HD 6490M + 103c 355f Radeon HD 6490M + 103c 3563 Radeon HD 6470M + 103c 3565 Radeon HD 6470M + 103c 3567 Radeon HD 6470M + 103c 3569 Radeon HD 6470M + 103c 3581 Radeon HD 6490M + 103c 3584 Radeon HD 6470M + 103c 358c Radeon HD 6490M + 103c 358f Radeon HD 6490M + 103c 3592 Radeon HD 6490M + 103c 3596 Radeon HD 6490M + 103c 366b Radeon HD 6470M + 103c 3671 FirePro M3900 + 103c 3673 Radeon HD 6470M + 1043 100a Radeon HD 7470M + 1043 100c Radeon HD 6470M + 1043 101b Radeon HD 6470M + 1043 101c Radeon HD 6470M + 1043 102a Radeon HD 7450M + 1043 102c Radeon HD 6470M + 1043 104b Radeon HD 7470M + 1043 105d Radeon HD 7470M + 1043 106b Radeon HD 7470M + 1043 106d Radeon HD 7470M + 1043 107d Radeon HD 7470M + 1043 1cb2 Radeon HD 6470M + 1043 1d22 Radeon HD 6470M + 1043 1d32 Radeon HD 6470M + 1043 2001 Radeon HD 6470M + 1043 2002 Radeon HD 7470M + 1043 2107 Radeon HD 7470M + 1043 2108 Radeon HD 7470M + 1043 2109 Radeon HD 7470M + 1043 84a0 Radeon HD 6470M + 1043 84e9 Radeon HD 6470M + 1043 8515 Radeon HD 7470M + 1043 8517 Radeon HD 7470M + 1043 855a Radeon HD 7470M + 104d 907b Radeon HD 6470M + 104d 9081 Radeon HD 6470M + 104d 9084 Radeon HD 6470M + 104d 9085 Radeon HD 6470M + 1179 0001 Radeon HD 6450M + 1179 0003 Radeon HD 6450M + 1179 0004 Radeon HD 6450M + 1179 fb22 Radeon HD 7470M + 1179 fb23 Radeon HD 7470M + 1179 fb2c Radeon HD 7470M + 1179 fb31 Radeon HD 7470M + 1179 fb32 Radeon HD 7470M + 1179 fb33 Radeon HD 7470M + 1179 fb38 Radeon HD 7470M + 1179 fb39 Radeon HD 7470M + 1179 fb3a Radeon HD 7470M + 1179 fb40 Radeon HD 7470M + 1179 fb41 Radeon HD 7470M + 1179 fb42 Radeon HD 7470M + 1179 fb47 Radeon HD 7470M + 1179 fb48 Radeon HD 7470M + 1179 fb51 Radeon HD 7470M + 1179 fb52 Radeon HD 7470M + 1179 fb53 Radeon HD 7470M + 1179 fb81 Radeon HD 7470M + 1179 fb82 Radeon HD 7470M + 1179 fb83 Radeon HD 7470M + 1179 fc51 Radeon HD 6470M + 1179 fc52 Radeon HD 7470M + 1179 fc56 Radeon HD 7470M + 1179 fcd3 Radeon HD 7470M + 1179 fcd4 Radeon HD 7470M + 1179 fcee Radeon HD 7470M + 1179 fdee Radeon HD 7470M + 144d b074 Radeon HD 6470M + 144d b084 Radeon HD 6470M + 144d c095 Radeon HD 6470M + 144d c0b3 Radeon HD 6490M + 144d c538 Radeon HD 6470M + 144d c581 Radeon HD 6470M + 144d c589 Radeon HD 6470M + 144d c609 Radeon HD 7470M + 144d c625 Radeon HD 7470M + 144d c636 Radeon HD 7450M + 1462 10ac Radeon HD 6470M + 152d 0916 Radeon HD 6470M + 17aa 21e5 Radeon HD 6470M + 17aa 3900 Radeon HD 7450M + 17aa 3902 Radeon HD 7450M + 17aa 3969 Radeon HD 6470M + 17aa 3970 Radeon HD 7450M + 17aa 3976 Radeon HD 6470M + 17aa 397b Radeon HD 6470M + 17aa 397d Radeon HD 6470M + 17aa 5101 Radeon HD 7470M + 17aa 5102 Radeon HD 7450M + 17aa 5103 Radeon HD 7450M + 17aa 5106 Radeon HD 7450M + 1854 0897 Radeon HD 6470M + 1854 0900 Radeon HD 6470M + 1854 0908 Radeon HD 6470M + 1854 2015 Radeon HD 6470M + 6761 Seymour LP [Radeon HD 6430M] + 6763 Seymour [Radeon E6460] + 6764 Seymour [Radeon HD 6400M Series] + 6765 Seymour [Radeon HD 6400M Series] + 6766 Caicos + 6767 Caicos + 6768 Caicos + 6770 Caicos [Radeon HD 6450A/7450A] + 17aa 308d Radeon HD 7450A + 17aa 3623 Radeon HD 6450A + 17aa 3627 Radeon HD 6450A + 17aa 3629 Radeon HD 6450A + 17aa 363c Radeon HD 6450A + 17aa 3658 Radeon HD 7470A + 6771 Caicos XTX [Radeon HD 8490 / R5 235X OEM] + 6772 Caicos [Radeon HD 7450A] + 6778 Caicos XT [Radeon HD 7470/8470 / R5 235/310 OEM] + 1019 0024 Radeon HD 7470 + 1019 0027 Radeon HD 8470 + 1028 2120 Radeon HD 7470 + 1462 b491 Radeon HD 8470 + 1462 b492 Radeon HD 8470 + 1462 b493 Radeon HD 8470 OEM + 1462 b499 Radeon R5 235 OEM + 1642 3c65 Radeon HD 8470 + 1642 3c75 Radeon HD 8470 + 174b 8145 Radeon HD 8470 + 174b d145 Radeon R5 235 OEM + 174b d335 Radeon R5 310 OEM + 174b e145 Radeon HD 7470 + 17aa 3694 Radeon R5 A220 + 6779 Caicos [Radeon HD 6450/7450/8450 / R5 230 OEM] + 1019 0016 Radeon HD 6450 + 1019 0017 Radeon HD 6450 + 1019 0018 Radeon HD 6450 + 1028 2120 Radeon HD 6450 + 103c 2128 Radeon HD 6450 + 103c 2aee Radeon HD 7450A + 1092 6450 Radeon HD 6450 + 1462 2125 Radeon HD 6450 + 1462 2346 Radeon HD 7450 + 1462 2490 Radeon HD 6450 + 1462 2494 Radeon HD 6450 + 1462 2496 Radeon HD 7450 + 148c 7450 Radeon HD 7450 + 148c 8450 Radeon HD 8450 OEM + 1545 7470 Radeon HD 7470 + 1642 3a65 Radeon HD 6450 + 1642 3a66 Radeon HD 7450 + 1642 3a75 Radeon HD 6450 + 1642 3a76 Radeon HD 7450 + 1682 3200 Radeon HD 7450 + 174b 7450 Radeon HD 7450 + 174b e127 Radeon HD 6450 + 174b e153 Radeon HD 6450 + 174b e164 Radeon HD 6450 1 GB DDR3 + 174b e180 Radeon HD 6450 + 174b e201 Radeon HD 6450 + 17af 8450 Radeon HD 8450 OEM + 1b0a 9096 Radeon HD 6450 + 1b0a 9097 Radeon HD 6450 + 1b0a 90a8 Radeon HD 6450A + 1b0a 90b1 Radeon HD 6450 + 1b0a 90b3 Radeon HD 7450A + 1b0a 90bb Radeon HD 7450A + 677b Caicos PRO [Radeon HD 7450] + 6780 Tahiti XT GL [FirePro W9000] + 6784 Tahiti [FirePro Series Graphics Adapter] + 6788 Tahiti [FirePro Series Graphics Adapter] + 678a Tahiti PRO GL [FirePro Series] + 1002 030c FirePro W8000 + 1002 0310 FirePro S9000 + 1002 0420 Radeon Sky 700 + 1002 0422 Radeon Sky 900 + 1002 0710 FirePro S9050 + 1002 0b0e FirePro S10000 Passive + 1002 0b2a FirePro S10000 + 1028 030c FirePro W8000 + 1028 0710 FirePro S9000 + 6798 Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] + 1002 3000 Tahiti XT2 [Radeon HD 7970 GHz Edition] + 1002 3001 Tahiti XTL [Radeon R9 280X] + 1002 4000 Radeon HD 8970 OEM + 1043 041c HD 7970 DirectCU II + 1043 0420 HD 7970 DirectCU II TOP + 1043 0444 HD 7970 DirectCU II TOP + 1043 0448 HD 7970 DirectCU II TOP + 1043 044a Tahiti XT2 [Matrix HD 7970] + 1043 044c Tahiti XT2 [Matrix HD 7970 Platinum] + 1043 3001 Tahiti XTL [ROG Matrix R9 280X] + 1043 3006 Tahiti XTL [Radeon R9 280X DirectCU II TOP] + 1043 9999 ARES II + 106b 0127 FirePro D700 + 106b 0128 FirePro D700 + 1092 3000 Tahiti XT2 [Radeon HD 7970 GHz Edition] + 1458 2261 Tahiti XT2 [Radeon HD 7970 GHz Edition OC] +# GV-R928XOC-3GD + 1458 3001 Tahiti XTL [Radeon R9 280X OC] + 1462 2774 HD 7970 TwinFrozr III Boost Edition OC + 1682 3001 Tahiti XTL [Radeon R9 280X] + 1682 3211 Double D HD 7970 Black Edition +# FX-797A-TNBC + 1682 3213 HD 7970 Black Edition + 1682 3214 Double D HD 7970 + 1787 201c HD 7970 IceQ X² +# Radeon HD 7970 X2 + 1787 2317 Radeon HD 7990 + 1787 3000 Tahiti XT2 [Radeon HD 7970 GHz Edition] + 679a Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] + 1002 0b01 Radeon HD 8950 OEM + 1002 3000 Tahiti PRO2 [Radeon HD 7950 Boost] + 1462 3000 Radeon HD 8950 OEM + 174b a003 Radeon R9 280 + 679b Malta [Radeon HD 7990/8990 OEM] + 1002 0b28 Radeon HD 8990 OEM + 1002 0b2a Radeon HD 7990 + 1462 8036 Radeon HD 8990 OEM + 148c 8990 Radeon HD 8990 OEM + 679e Tahiti LE [Radeon HD 7870 XT] + 106b 0125 FirePro D500 + 106b 0126 FirePro D500 + 1787 2328 Radeon HD 7870 Black Edition 2 GB GDDR5 [2GBD5-2DHV3E] + 679f Tahiti + 67a0 Hawaii XT GL [FirePro W9100] + 1002 0335 FirePro S9150 + 1002 0735 FirePro S9170 + 1028 031f FirePro W9100 + 1028 0335 FirePro S9150 + 67a1 Hawaii PRO GL [FirePro W8100] + 1002 0335 FirePro S9100 + 1028 0335 FirePro S9100 + 67a2 Hawaii GL + 67a8 Hawaii + 67a9 Hawaii + 67aa Hawaii + 67b0 Hawaii XT / Grenada XT [Radeon R9 290X/390X] + 1028 0b00 Grenada XT [Radeon R9 390X] + 103c 6566 Radeon R9 390X + 1043 046a R9 290X DirectCU II + 1043 046c R9 290X DirectCU II OC + 1043 0474 Matrix R9 290X Platinum + 1043 0476 ARES III + 1043 04d7 Radeon R9 390X + 1043 04db Radeon R9 390X + 1043 04df Radeon R9 390X + 1043 04e9 Radeon R9 390X + 1458 227c R9 290X WindForce 3X OC + 1458 2281 R9 290X WindForce 3X OC + 1458 228c R9 290X WindForce 3X + 1458 228d R9 290X WindForce 3X OC + 1458 2290 R9 290X WindForce 3X + 1458 22bc Radeon R9 390X + 1458 22c1 Grenada PRO [Radeon R9 390] + 1462 2015 Radeon R9 390X + 1462 3070 R9 290X Lightning + 1462 3071 R9 290X Lightning + 1462 3072 R9 290X Lightning LE + 1462 3080 R9 290X Gaming + 1462 3082 R9 290X Gaming OC + 148c 2347 Devil 13 Dual Core R9 290X + 148c 2357 Grenada XT [Radeon R9 390X] + 1682 9290 Double Dissipation R9 290X + 1682 9395 Grenada XT [Radeon R9 390X] + 174b 0e34 Radeon R9 390X + 174b e282 Vapor-X R9 290X Tri-X OC + 174b e285 R9 290X Tri-X OC + 174b e324 Grenada XT2 [Radeon R9 390X] + 1787 2020 R9 290X IceQ X² Turbo + 1787 2357 Grenada XT [Radeon R9 390X] + 67b1 Hawaii PRO [Radeon R9 290/390] + 1043 04dd STRIX R9 390 + 148c 2358 Radeon R9 390 + 174b e324 Sapphire Nitro R9 390 + 67b9 Vesuvius [Radeon R9 295X2] + 67be Hawaii LE + 67c0 Ellesmere [Radeon Pro WX 7100 Mobile] + 67c2 Ellesmere [Radeon Pro V7300X / V7350x2] + 67c4 Ellesmere [Radeon Pro WX 7100] + 1002 0336 Radeon Pro Duo + 1002 1336 Radeon Pro Duo + 67c7 Ellesmere [Radeon Pro WX 5100] + 67ca Ellesmere [Polaris10] + 67cc Ellesmere [Polaris10] + 67cf Ellesmere [Polaris10] + 67d0 Ellesmere [Radeon Pro V7300X / V7350x2] + 67df Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] + 1002 0b37 Radeon RX 480 + 1028 1722 Radeon RX 570X + 1028 1723 Radeon RX 580X + 1043 04a8 Radeon RX 480 + 1043 04b0 Radeon RX 470 + 1043 04fb Radeon RX 480 + 1043 04fd Radeon RX 480 8GB + 1043 056a Radeon RX 590 + 106b 0161 Radeon Pro 580 + 106b 0162 Radeon Pro 575 + 106b 0163 Radeon Pro 570 + 1458 22f0 Radeon RX 570 + 1458 22f7 Radeon RX 570 Gaming 4G + 1462 3411 Radeon RX 470 + 1462 3413 Radeon RX 480 Gaming X 8GB + 1462 3416 Radeon RX 570 + 1462 3418 Radeon RX 580 Armor 4G OC + 1462 341e Radeon RX 570 Armor 4G OC + 1462 8a92 Radeon RX 580 + 148c 2372 Radeon RX 480 + 148c 2373 Radeon RX 470 + 1682 9470 Radeon RX 470 + 1682 9480 Radeon RX 480 + 1682 9588 Radeon RX 580 XTR + 1682 c570 Radeon RX 570 + 174b e347 Radeon RX 470/480 + 174b e349 Radeon RX 470 + 1787 a470 Radeon RX 470 + 1787 a480 Radeon RX 480 + 1849 5001 Phantom Gaming X RX 580 OC + 1849 5030 Phantom Gaming D Radeon RX580 8G OC + 1da2 e353 Radeon RX 570 Pulse 4GB + 1da2 e366 Nitro+ Radeon RX 570/580/590 + 67e0 Baffin [Radeon Pro WX 4170] + 103c 8270 Radeon Pro WX 4170 + 103c 8272 Radeon Pro WX 4170 + 67e1 Baffin [Polaris11] + 67e3 Baffin [Radeon Pro WX 4100] + 67e8 Baffin [Radeon Pro WX 4130/4150] + 1028 075d Radeon Pro WX 4150 + 1028 07b0 Radeon Pro WX 4130/4150 + 1028 07b1 Radeon Pro WX 4130 + 1028 175d Radeon Pro WX 4150 + 1028 17b0 Radeon Pro WX 4130/4150 + 1028 17b1 Radeon Pro WX 4130 + 103c 8275 Radeon Pro WX 4150 + 103c 8277 Radeon Pro WX 4150 + 67e9 Baffin [Polaris11] + 67eb Baffin [Radeon Pro V5300X] + 67ef Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] + 1028 1703 RX 560D OEM OC 2 GB + 103c 3421 Radeon RX 460 + 106b 0160 Radeon Pro 460 + 106b 0166 Radeon Pro 455 + 106b 0167 Radeon Pro 450 + 106b 0179 Radeon Pro 560 + 106b 017a Radeon Pro 555 + 106b 018f Radeon Pro 560X + 106b 0190 Radeon Pro 555X + 1642 1727 Polaris 21 XL [Radeon RX 560D] + 1682 956d Polaris 21 XL [Radeon RX 560D] + 67ff Baffin [Radeon RX 550 640SP / RX 560/560X] + 1002 0b04 Radeon RX 560 + 1028 1721 Radeon RX 560X + 1028 1726 Radeon RX 560DX + 103c 8479 Radeon RX 560X Mobile + 1043 04bc Radeon RX 560 + 1043 052f Radeon RX 560 + 1458 22ed Radeon RX 560 + 148c 2381 Radeon RX 560 + 1682 9560 Radeon RX 560 + 1da2 e348 Radeon RX 560 + 1da2 e367 Radeon RX 550 640SP + 6800 Wimbledon XT [Radeon HD 7970M] + 1002 0124 Radeon HD 7970M + 8086 2110 Radeon HD 7970M + 8086 2111 Radeon HD 7970M + 6801 Neptune XT [Radeon HD 8970M] + 1002 0124 Radeon HD 8970M + 1462 1117 Radeon R9 M290X + 8086 2110 Radeon HD 8970M + 8086 2111 Radeon HD 8970M + 6802 Wimbledon + 6806 Neptune + 6808 Pitcairn XT GL [FirePro W7000] + 1002 0310 FirePro S7000 + 1002 0420 Radeon Sky 500 + 103c 030c MED-X7000 + 13cc 3d25 MXRT-7500 + 15c3 030c MED-X7000 + 6809 Pitcairn LE GL [FirePro W5000] + 13cc 3d23 MXRT-5500 + 13cc 3d24 MXRT-5550 + 15c3 0b06 MED-X5000 + 6810 Curacao XT / Trinidad XT [Radeon R7 370 / R9 270X/370X] + 106b 012a FirePro D300 + 106b 012b FirePro D300 + 148c 0908 Radeon R9 370 OEM + 1682 7370 Radeon R7 370 + 6811 Curacao PRO [Radeon R7 370 / R9 270/370 OEM] + 1028 0b00 Trinidad PRO [Radeon R9 370 OEM] + 1043 2016 Trinidad PRO [Radeon R9 370 OEM] + 1458 2016 Trinidad PRO [Radeon R9 370 OEM] + 1462 2016 Trinidad PRO [Radeon R9 370 OEM] + 1462 3050 R9 270 Gaming OC + 148c 2016 Trinidad PRO [Radeon R9 370 OEM] + 1682 2015 Trinidad PRO [Radeon R7 370] + 174b 2015 NITRO Radeon R7 370 + 174b 2016 Trinidad PRO [Radeon R9 370 OEM] + 1787 2016 Trinidad PRO [Radeon R9 370 OEM] + 6816 Pitcairn + 6817 Pitcairn + 6818 Pitcairn XT [Radeon HD 7870 GHz Edition] + 1002 0b05 Radeon HD 8870 OEM + 174b 8b04 Radeon HD 8860 + 6819 Pitcairn PRO [Radeon HD 7850 / R7 265 / R9 270 1024SP] + 1043 042c Radeon HD 7850 + 1682 7269 Radeon R9 270 1024SP + 1682 9278 Radeon R9 270 1024SP + 174b a008 Radeon R9 270 1024SP + 174b e221 Radeon HD 7850 2GB GDDR5 DVI-I/DVI-D/HDMI/DP + 6820 Venus XTX [Radeon HD 8890M / R9 M275X/M375X] + 103c 1851 Radeon HD 7750M + 17aa 3643 Radeon R9 A375 + 17aa 3801 Radeon R9 M275 + 17aa 3824 Radeon R9 M375 + 6821 Venus XT [Radeon HD 8870M / R9 M270X/M370X] + 1002 031e FirePro SX4000 + 1028 05cc FirePro M5100 + 1028 15cc FirePro M5100 + 106b 0149 Radeon R9 M370X Mac Edition + 6822 Venus PRO [Radeon E8860] + 6823 Venus PRO [Radeon HD 8850M / R9 M265X] + 6825 Heathrow XT [Radeon HD 7870M] + 1028 053f FirePro M6000 + 1028 05cd FirePro M6000 + 1028 15cd FirePro M6000 + 103c 176c FirePro M6000 + 8086 2111 Chelsea PRO + 6826 Chelsea LP [Radeon HD 7700M Series] + 6827 Heathrow PRO [Radeon HD 7850M/8850M] + 6828 Cape Verde PRO [FirePro W600] + 15c3 2b1e MED-X6000 + 6829 Cape Verde + 682a Venus PRO + 682b Cape Verde PRO / Venus LE / Tropo PRO-L [Radeon HD 8830M / R7 250 / R7 M465X] + 0128 079c Radeon R7 465X + 1462 3012 Radeon R7 250 + 682c Cape Verde GL [FirePro W4100] + 682d Chelsea XT GL [FirePro M4000] + 682f Chelsea LP [Radeon HD 7730M] + 103c 1851 Radeon HD 7750M + 6835 Cape Verde PRX [Radeon R9 255 OEM] + 6837 Cape Verde LE [Radeon HD 7730/8730] + 1462 2796 Radeon HD 8730 + 1462 8092 Radeon HD 8730 + 148c 8730 Radeon HD 8730 + 1787 3000 Radeon HD 6570 + 683d Cape Verde XT [Radeon HD 7770/8760 / R7 250X] + 1002 0030 Radeon HD 8760 OEM + 1019 0030 Radeon HD 8760 OEM + 103c 6890 Radeon HD 8760 OEM + 1043 8760 Radeon HD 8760 OEM + 1462 2710 R7770-PMD1GD5 + 174b 8304 Radeon HD 8760 OEM + 683f Cape Verde PRO [Radeon HD 7750/8740 / R7 250E] + 1462 2790 Radeon HD 8740 + 1462 2791 Radeon HD 8740 + 1642 3b97 Radeon HD 8740 + 6840 Thames [Radeon HD 7500M/7600M Series] + 1025 050e Radeon HD 7670M + 1025 050f Radeon HD 7670M + 1025 0513 Radeon HD 7670M + 1025 0514 Radeon HD 7670M + 1025 056d Radeon HD 7670M + 1025 059a Radeon HD 7670M + 1025 059b Radeon HD 7670M + 1025 059e Radeon HD 7670M + 1025 0600 Radeon HD 7670M + 1025 0606 Radeon HD 7670M + 1025 0696 Radeon HD 7650M + 1025 0697 Radeon HD 7650M + 1025 0698 Radeon HD 7650M + 1025 0699 Radeon HD 7650M + 1025 0757 Radeon HD 7670M + 1028 056a Radeon HD 7670M + 1028 056e Radeon HD 7670M + 1028 0598 Radeon HD 7670M + 1028 059d Radeon HD 7670M + 1028 05a3 Radeon HD 7670M + 1028 05b9 Radeon HD 7670M + 1028 05bb Radeon HD 7670M + 103c 1789 FirePro M2000 + 103c 17f1 Radeon HD 7570M + 103c 17f4 Radeon HD 7650M + 103c 1813 Radeon HD 7590M + 103c 182f Radeon HD 7670M + 103c 1830 Radeon HD 7670M + 103c 1835 Radeon HD 7670M + 103c 183a Radeon HD 7670M + 103c 183c Radeon HD 7670M + 103c 183e Radeon HD 7670M + 103c 1840 Radeon HD 7670M + 103c 1842 Radeon HD 7670M + 103c 1844 Radeon HD 7670M + 103c 1848 Radeon HD 7670M + 103c 184a Radeon HD 7670M + 103c 184c Radeon HD 7670M + 103c 1895 Radeon HD 7670M + 103c 1897 Radeon HD 7670M + 103c 18a5 Radeon HD 7670M + 103c 18a7 Radeon HD 7670M + 103c 18f4 Radeon HD 7670M + 1043 100a Radeon HD 7670M + 1043 104b Radeon HD 7670M + 1043 10dc Radeon HD 7670M + 1043 2121 Radeon HD 7670M + 1043 2122 Radeon HD 7670M + 1043 2123 Radeon HD 7670M + 1043 2125 Radeon HD 7670M + 1043 2127 Radeon HD 7670M + 1179 fb11 Radeon HD 7670M + 1179 fb22 Radeon HD 7670M + 1179 fb23 Radeon HD 7670M + 1179 fb2c Radeon HD 7670M + 1179 fb31 Radeon HD 7670M + 1179 fb32 Radeon HD 7670M + 1179 fb38 Radeon HD 7670M + 1179 fb39 Radeon HD 7670M + 1179 fb3a Radeon HD 7670M + 1179 fb40 Radeon HD 7670M + 1179 fb41 Radeon HD 7670M + 1179 fb47 Radeon HD 7670M + 1179 fb48 Radeon HD 7670M + 1179 fb51 Radeon HD 7670M + 1179 fb52 Radeon HD 7670M + 1179 fb53 Radeon HD 7670M + 1179 fb81 Radeon HD 7670M + 1179 fb82 Radeon HD 7670M + 1179 fb83 Radeon HD 7670M + 1179 fc56 Radeon HD 7670M + 1179 fcd4 Radeon HD 7670M + 1179 fcee Radeon HD 7670M + 144d c0c5 Radeon HD 7690M + 144d c0ce Radeon HD 7670M + 144d c0da Radeon HD 7670M + 17aa 3970 Radeon HD 7670M + 17aa 397b Radeon HD 7670M + 17aa 5101 Radeon HD 7670M + 17aa 5102 Radeon HD 7670M + 17aa 5103 Radeon HD 7670M + 6841 Thames [Radeon HD 7550M/7570M/7650M] + 1028 0561 Radeon HD 7650M + 1028 056c Radeon HD 7650M + 1028 057f Radeon HD 7570M + 103c 17f1 Radeon HD 7570M + 103c 17f4 Radeon HD 7650M + 103c 1813 Radeon HD 7570M + 103c 183a Radeon HD 7650M + 103c 183c Radeon HD 7650M + 103c 183e Radeon HD 7650M + 103c 1840 Radeon HD 7650M + 103c 1842 Radeon HD 7650M + 103c 1844 Radeon HD 7650M + 1043 100a Radeon HD 7650M + 1043 104b Radeon HD 7650M + 1043 10dc Radeon HD 7650M + 1043 2134 Radeon HD 7650M + 1179 0001 Radeon HD 7570M + 1179 0002 Radeon HD 7570M + 1179 fb43 Radeon HD 7550M + 1179 fb91 Radeon HD 7550M + 1179 fb92 Radeon HD 7550M + 1179 fb93 Radeon HD 7550M + 1179 fba2 Radeon HD 7550M + 1179 fba3 Radeon HD 7550M + 144d c0c7 Radeon HD 7550M + 6842 Thames LE [Radeon HD 7000M Series] + 6843 Thames [Radeon HD 7670M] + 6860 Vega 10 [Radeon Instinct MI25] + 1002 0c35 Radeon PRO V320 + 1002 6c75 Radeon PRO V320 + 106b 017c Radeon Pro Vega 64 + 6861 Vega 10 XT [Radeon PRO WX 9100] + 6862 Vega 10 XT [Radeon PRO SSG] + 6863 Vega 10 XTX [Radeon Vega Frontier Edition] + 6864 Vega + 6867 Vega 10 XL [Radeon Pro Vega 56] + 6868 Vega 10 [Radeon PRO WX 8100/8200] + 686c Vega 10 [Radeon Instinct MI25 MxGPU] + 687f Vega 10 XL/XT [Radeon RX Vega 56/64] + 1002 0b36 RX Vega64 + 1002 6b76 RX Vega56 + 6880 Lexington [Radeon HD 6550M] + 103c 163c Pavilion dv6 Radeon HD 6550M + 6888 Cypress XT [FirePro V8800] + 6889 Cypress PRO [FirePro V7800] + 1002 0301 FirePro V7800P + 13cc 3d1f MXRT-7400 + 688a Cypress XT [FirePro V9800] + 1002 030c FirePro V9800P + 688c Cypress XT GL [FireStream 9370] + 688d Cypress PRO GL [FireStream 9350] + 6898 Cypress XT [Radeon HD 5870] + 1002 0b00 Radeon HD 5870 Eyefinity⁶ Edition + 106b 00d0 Radeon HD 5870 Mac Edition +# R5870-PM2D1G + 1462 8032 Radeon HD 5870 1 GB GDDR5 + 174b 6870 Radeon HD 6870 1600SP Edition + 6899 Cypress PRO [Radeon HD 5850] +# EAH5850 + 1043 0330 Radeon HD 5850 + 174b 237b Radeon HD 5850 X2 + 174b 6850 Radeon HD 6850 1440SP Edition + 689b Cypress PRO [Radeon HD 6800 Series] + 689c Hemlock [Radeon HD 5970] + 1043 0352 ARES + 689d Hemlock [Radeon HD 5970] + 689e Cypress LE [Radeon HD 5830] + 68a0 Broadway XT [Mobility Radeon HD 5870] + 1028 12ef FirePro M7820 + 103c 1520 FirePro M7820 + 68a1 Broadway PRO [Mobility Radeon HD 5850] + 106b 00cc iMac MC511 Mobility Radeon HD 5850 MXM Module + 68a8 Granville [Radeon HD 6850M/6870M] + 1025 0442 Radeon HD 6850M + 1025 0451 Radeon HD 6850M + 1025 050a Radeon HD 6850M + 1025 050b Radeon HD 6850M + 1025 050c Radeon HD 6850M + 1025 050e Radeon HD 6850M + 1025 050f Radeon HD 6850M + 1025 0513 Radeon HD 6850M + 1025 0514 Radeon HD 6850M + 1025 0515 Radeon HD 6850M + 1025 0516 Radeon HD 6850M + 1025 0525 Radeon HD 6850M + 1025 0526 Radeon HD 6850M + 1025 056d Radeon HD 6850M + 1028 048f Radeon HD 6870M + 1028 0490 Radeon HD 6870M + 1028 04b9 Radeon HD 6870M + 1028 04ba Radeon HD 6870M + 103c 159b Radeon HD 6850M + 144d c0ad Radeon HD 6850M + 68a9 Juniper XT [FirePro V5800] + 13cc 3d1e MXRT-5400 + 13cc 3d20 MXRT-5450 + 68b8 Juniper XT [Radeon HD 5770] + 106b 00cf MacPro5,1 [Mac Pro 2.8GHz DDR3] + 68b9 Juniper LE [Radeon HD 5670 640SP Edition] + 68ba Juniper XT [Radeon HD 6770] + 68be Juniper PRO [Radeon HD 5750] + 148c 3000 Radeon HD 6750 + 68bf Juniper PRO [Radeon HD 6750] + 174b 6750 Radeon HD 6750 + 68c0 Madison [Mobility Radeon HD 5730 / 6570M] + 1019 2383 Mobility Radeon HD 5730 + 1028 02a2 Mobility Radeon HD 5730 + 1028 02fe Mobility Radeon HD 5730 + 1028 0419 Mobility Radeon HD 5730 + 103c 147d Mobility Radeon HD 5730 + 103c 1521 Madison XT [FirePro M5800] + 103c 1593 Mobility Radeon HD 6570 + 103c 1596 Mobility Radeon HD 6570 + 103c 1599 Mobility Radeon HD 6570 + 1043 1c22 Mobility Radeon HD 5730 + 17aa 3927 Mobility Radeon HD 5730 + 17aa 3952 Mobility Radeon HD 5730 + 17aa 3978 Radeon HD 6570M + 68c1 Madison [Mobility Radeon HD 5650/5750 / 6530M/6550M] + 1025 0205 Mobility Radeon HD 5650 + 1025 0293 Mobility Radeon HD 5650 + 1025 0294 Mobility Radeon HD 5650 + 1025 0296 Mobility Radeon HD 5650 + 1025 0308 Mobility Radeon HD 5650 + 1025 030a Mobility Radeon HD 5650 + 1025 0311 Mobility Radeon HD 5650 + 1025 0312 Mobility Radeon HD 5650 + 1025 031c Mobility Radeon HD 5650 + 1025 031d Mobility Radeon HD 5650 + 1025 033d Mobility Radeon HD 5650 + 1025 033e Mobility Radeon HD 5650 + 1025 033f Mobility Radeon HD 5650 + 1025 0346 Mobility Radeon HD 5650 + 1025 0347 Aspire 7740G + 1025 0348 Mobility Radeon HD 5650 + 1025 0356 Mobility Radeon HD 5650 + 1025 0357 Mobility Radeon HD 5650 + 1025 0358 Mobility Radeon HD 5650 + 1025 0359 Mobility Radeon HD 5650 + 1025 035a Mobility Radeon HD 5650 + 1025 035b Mobility Radeon HD 5650 + 1025 035c Mobility Radeon HD 5650 + 1025 035d Mobility Radeon HD 5650 + 1025 035e Mobility Radeon HD 5650 + 1025 0360 Mobility Radeon HD 5650 + 1025 0362 Mobility Radeon HD 5650 + 1025 0364 Mobility Radeon HD 5650 + 1025 0365 Mobility Radeon HD 5650 + 1025 0366 Mobility Radeon HD 5650 + 1025 0367 Mobility Radeon HD 5650 + 1025 0368 Mobility Radeon HD 5650 + 1025 036c Mobility Radeon HD 5650 + 1025 036d Mobility Radeon HD 5650 + 1025 036e Mobility Radeon HD 5650 + 1025 036f Mobility Radeon HD 5650 + 1025 0372 Mobility Radeon HD 5650 + 1025 0373 Mobility Radeon HD 5650 + 1025 0377 Mobility Radeon HD 5650 + 1025 0378 Mobility Radeon HD 5650 + 1025 0379 Mobility Radeon HD 5650 + 1025 037a Mobility Radeon HD 5650 + 1025 037b Mobility Radeon HD 5650 + 1025 037e Mobility Radeon HD 5650 + 1025 037f Mobility Radeon HD 5650 + 1025 0382 Mobility Radeon HD 5650 + 1025 0383 Mobility Radeon HD 5650 + 1025 0384 Mobility Radeon HD 5650 + 1025 0385 Mobility Radeon HD 5650 + 1025 0386 Mobility Radeon HD 5650 + 1025 0387 Mobility Radeon HD 5650 + 1025 0388 Mobility Radeon HD 5650 + 1025 038b Mobility Radeon HD 5650 + 1025 038c Mobility Radeon HD 5650 + 1025 039a Mobility Radeon HD 5650 + 1025 0411 Mobility Radeon HD 5650 + 1025 0412 Mobility Radeon HD 5650 + 1025 0418 Mobility Radeon HD 5650 + 1025 0419 Mobility Radeon HD 5650 + 1025 0420 Mobility Radeon HD 5650 + 1025 0421 Mobility Radeon HD 5650 + 1025 0425 Mobility Radeon HD 5650 + 1025 042a Mobility Radeon HD 5650 + 1025 042e Mobility Radeon HD 5650 + 1025 042f Mobility Radeon HD 5650 + 1025 0432 Mobility Radeon HD 5650 + 1025 0433 Mobility Radeon HD 5650 + 1025 0442 Mobility Radeon HD 5650 + 1025 044c Mobility Radeon HD 5650 + 1025 044e Mobility Radeon HD 5650 + 1025 0451 Mobility Radeon HD 5650 + 1025 0454 Mobility Radeon HD 5650 + 1025 0455 Mobility Radeon HD 5650 + 1025 0475 Mobility Radeon HD 5650 + 1025 0476 Mobility Radeon HD 5650 + 1025 0487 Mobility Radeon HD 5650 + 1025 0489 Mobility Radeon HD 5650 + 1025 0498 Mobility Radeon HD 5650 + 1025 0517 Radeon HD 6550M + 1025 051a Radeon HD 6550M + 1025 051b Radeon HD 6550M + 1025 051c Radeon HD 6550M + 1025 051d Radeon HD 6550M + 1025 0525 Radeon HD 6550M + 1025 0526 Radeon HD 6550M + 1025 052b Radeon HD 6550M + 1025 052c Radeon HD 6550M + 1025 053c Radeon HD 6550M + 1025 053d Radeon HD 6550M + 1025 053e Radeon HD 6550M + 1025 053f Radeon HD 6550M + 1025 0607 Radeon HD 6550M + 1028 041b Mobility Radeon HD 5650 + 1028 0447 Mobility Radeon HD 5650 + 1028 0448 Mobility Radeon HD 5650 + 1028 0456 Mobility Radeon HD 5650 + 1028 0457 Mobility Radeon HD 5650 + 103c 1436 Mobility Radeon HD 5650 + 103c 1437 Mobility Radeon HD 5650 + 103c 1440 Mobility Radeon HD 5650 + 103c 1448 Mobility Radeon HD 5650 + 103c 1449 Mobility Radeon HD 5650 + 103c 144a Mobility Radeon HD 5650 + 103c 144b Mobility Radeon HD 5650 + 103c 147b Mobility Radeon HD 5650 + 103c 149c Mobility Radeon HD 5650 + 103c 149e Mobility Radeon HD 5650 + 103c 1521 Madison Pro [FirePro M5800] + 1043 1bc2 Mobility Radeon HD 5650 + 104d 9071 Mobility Radeon HD 5650 + 104d 9077 Mobility Radeon HD 5650 + 104d 9081 Mobility Radeon HD 5650 + 1179 fd00 Mobility Radeon HD 5650 + 1179 fd12 Mobility Radeon HD 5650 + 1179 fd1a Mobility Radeon HD 5650 + 1179 fd30 Mobility Radeon HD 5650 + 1179 fd31 Mobility Radeon HD 5650 + 1179 fd50 Mobility Radeon HD 5650 + 1179 fd52 Radeon HD 6530M + 1179 fd63 Radeon HD 6530M + 1179 fd65 Radeon HD 6530M + 1179 fdd0 Mobility Radeon HD 5650 + 1179 fdd2 Radeon HD 6530M + 144d c07e Mobility Radeon HD 5650 + 144d c085 Mobility Radeon HD 5650 + 14c0 0043 Mobility Radeon HD 5650 + 14c0 004d Mobility Radeon HD 5650 + 17aa 3928 Mobility Radeon HD 5650 + 17aa 3951 Mobility Radeon HD 5650 + 17aa 3977 Radeon HD 6550M + 68c7 Pinewood [Mobility Radeon HD 5570/6550A] + 1462 2241 Mobility Radeon HD 5570 + 1462 2243 Mobility Radeon HD 5570 + 1462 2244 Mobility Radeon HD 5570 + 1462 2245 Radeon HD 6550A + 1462 2246 Radeon HD 6550A + 68c8 Redwood XT GL [FirePro V4800] + 68c9 Redwood PRO GL [FirePro V3800] + 13cc 3d1d MXRT-2400 + 68d8 Redwood XT [Radeon HD 5670/5690/5730] + 1028 68e0 Radeon HD 5670 + 174b 5690 Radeon HD 5690 + 174b 5730 Radeon HD 5730 + 174b e151 Radeon HD 5670 + 1787 3000 Radeon HD 5730 + 17af 3010 Radeon HD 5730 + 17af 3011 Radeon HD 5690 + 68d9 Redwood PRO [Radeon HD 5550/5570/5630/6510/6610/7570] + 103c 6870 Radeon HD 5570 + 103c 6872 Radeon HD 5570 + 1043 03ce Radeon HD 5550 + 1462 2151 Radeon HD 5570 + 1462 2240 Radeon HD 5570 + 148c 3000 Radeon HD 6510 + 148c 3001 Radeon HD 6610 + 1545 5550 Radeon HD 5550 + 1545 7570 Radeon HD 7570 + 1642 3985 Radeon HD 5570 + 1642 3996 Radeon HD 5570 + 174b 3000 Radeon HD 6510 + 174b 6510 Radeon HD 6510 + 174b 6610 Radeon HD 6610 + 174b e142 Radeon HD 5570 + 1787 3000 Radeon HD 6510 + 17af 3000 Radeon HD 6510 + 17af 3010 Radeon HD 5630 + 68da Redwood LE [Radeon HD 5550/5570/5630/6390/6490/7570] + 148c 3000 Radeon HD 6390 + 148c 3001 Radeon HD 6490 + 1545 7570 Radeon HD 7570 + 174b 3000 Radeon HD 6390 + 174b 5570 Radeon HD 5570 + 174b 5630 Radeon HD 5630 + 174b 6490 Radeon HD 6490 + 1787 3000 Radeon HD 5630 + 17af 3000 Radeon HD 6390 + 17af 3010 Radeon HD 5630 + 68de Redwood + 68e0 Park [Mobility Radeon HD 5430/5450/5470] + 1028 0404 Mobility Radeon HD 5450 + 1028 0414 Mobility Radeon HD 5450 + 1028 0434 Mobility Radeon HD 5450 + 103c 1433 Mobility Radeon HD 5450 + 103c 1434 Mobility Radeon HD 5450 + 103c 1469 Mobility Radeon HD 5450 + 103c 146b Mobility Radeon HD 5450 + 103c 1486 TouchSmart tm2-2050er discrete GPU (Mobility Radeon HD 5450) + 103c 1622 Mobility Radeon HD 5450 + 103c 1623 Mobility Radeon HD 5450 + 103c eeee Mobility Radeon HD 5450 + 104d 9076 Mobility Radeon HD 5450 + 1682 304e Caicos [Radeon HD 5450] + 1682 6000 Caicos [Radeon HD 5450] + 17aa 9e52 FirePro M3800 + 17aa 9e53 FirePro M3800 + 68e1 Park [Mobility Radeon HD 5430] + 1043 041f Caicos [Radeon HD 7350] + 1043 3000 Caicos [Radeon HD 5450] + 148c 3000 Caicos [Radeon HD 5450] + 148c 3001 Caicos [Radeon HD 6230] + 148c 3002 Caicos [Radeon HD 6250] + 148c 3003 Caicos [Radeon HD 6350] + 148c 7350 Caicos [Radeon HD 7350] + 148c 8350 Caicos [Radeon HD 8350] + 1545 5450 Caicos [Radeon HD 5450] + 1545 7350 Caicos [Radeon HD 7350] + 1682 3000 Caicos [Radeon HD 5450] + 1682 6000 Caicos [Radeon HD 5450] + 1682 7350 Caicos [Radeon HD 7350] + 174b 3000 Caicos [Radeon HD 5450] + 174b 5470 Caicos [Radeon HD 5470] + 174b 6000 Caicos [Radeon HD 5450] + 174b 6230 Caicos [Radeon HD 6230] + 174b 6350 Caicos [Radeon HD 6350] + 174b 7350 Caicos [Radeon HD 7350] + 1787 3000 Caicos [Radeon HD 5450] + 17af 3000 Caicos [Radeon HD 5450] + 17af 3001 Caicos [Radeon HD 6230] + 17af 3014 Caicos [Radeon HD 6350] + 17af 3015 Caicos [Radeon HD 7350] + 17af 8350 Caicos [Radeon HD 8350 OEM] + 68e4 Robson CE [Radeon HD 6370M/7370M] + 1019 2386 Radeon HD 6350M + 1019 2387 Radeon HD 6350M + 1019 238d Radeon HD 6370M + 1019 238e Radeon HD 6370M + 1025 0382 Radeon HD 6370M + 1025 0489 Radeon HD 6370M + 1025 048a Radeon HD 6370M + 1025 048b Radeon HD 6370M + 1025 048c Radeon HD 6370M + 1028 04c1 Radeon HD 6370M + 1028 04ca Radeon HD 6370M + 1028 04cc Radeon HD 6370M + 1028 04cd Radeon HD 6370M + 1028 04d7 Radeon HD 6370M + 103c 1411 Radeon HD 6370M + 103c 1421 Radeon HD 6370M + 103c 1426 Radeon HD 6370M + 103c 1428 Radeon HD 6370M + 103c 142a Radeon HD 6370M + 103c 142b Radeon HD 6370M + 103c 143a Radeon HD 6370M + 103c 143c Radeon HD 6370M + 103c 1445 Radeon HD 6370M + 103c 162c Radeon HD 6370M + 103c 162d Radeon HD 6370M + 103c 162e Radeon HD 6370M + 103c 162f Radeon HD 6370M + 103c 1639 Radeon HD 6370M + 103c 163a Radeon HD 6370M + 103c 163b Radeon HD 6370M + 103c 163c Radeon HD 6370M + 103c 163d Radeon HD 6370M + 103c 163e Radeon HD 6370M + 103c 163f Radeon HD 6370M + 103c 1641 Radeon HD 6370M + 103c 1643 Radeon HD 6370M + 103c 3578 Radeon HD 6370M + 103c 357a Radeon HD 6370M + 103c 3673 Radeon HD 6370M + 103c 3675 Radeon HD 6370M + 1043 1c92 Radeon HD 6370M + 1043 84a1 Radeon HD 6370M + 1043 84ad Radeon HD 6370M + 104d 9081 Radeon HD 6370M + 1545 7350 Cedar [Radeon HD 7350] + 1558 4510 Radeon HD 6370M + 1558 5505 Radeon HD 6370M + 174b 5450 Cedar [Radeon HD 5450] + 17aa 21dd Radeon HD 6370M + 17aa 21e9 Radeon HD 6370M + 17aa 3971 Radeon HD 6370M + 17aa 3972 Radeon HD 7370M + 17aa 397a Radeon HD 6370M/7370M + 17aa 397b Radeon HD 6370M/7370M + 17aa 397f Radeon HD 7370M + 68e5 Robson LE [Radeon HD 6330M] + 1179 fd3c Radeon HD 6330M + 1179 fd50 Radeon HD 6330M + 1179 fd52 Radeon HD 6330M + 1179 fd63 Radeon HD 6330M + 1179 fd65 Radeon HD 6330M + 1179 fd73 Radeon HD 6330M + 1179 fd75 Radeon HD 6330M + 1179 fdd0 Radeon HD 6330M + 1179 fdd2 Radeon HD 6330M + 1179 fdea Radeon HD 6330M + 1179 fdf8 Radeon HD 6330M + 148c 5450 Cedar [Radeon HD 5450] + 148c 6350 Cedar [Radeon HD 6350] + 148c 7350 Cedar [Radeon HD 7350] + 148c 8350 Cedar [Radeon HD 8350] + 1545 7350 Cedar [Radeon HD 7350] + 68e8 Cedar + 68e9 Cedar [ATI FirePro (FireGL) Graphics Adapter] + 68f1 Cedar GL [FirePro 2460] + 68f2 Cedar GL [FirePro 2270] + 68f8 Cedar [Radeon HD 7300 Series] + 68f9 Cedar [Radeon HD 5000/6000/7350/8350 Series] + 1019 0001 Radeon HD 5450 + 1019 0002 Radeon HD 5450 + 1019 0019 Radeon HD 6350 + 1025 0518 Radeon HD 5450 + 1025 0519 Radeon HD 5450 + 1028 010e XPS 8300 + 1028 2126 Radeon HD 6350 + 103c 2126 Radeon HD 6350 + 103c 2aac Radeon HD 5450 + 103c 2aae Radeon HD 5450 + 103c 3580 Radeon HD 5450 + 1043 0386 Radeon HD 5450 + 1043 03c2 EAH5450 SILENT/DI/512MD2 (LP) + 1462 2130 Radeon HD 5450 + 1462 2131 Radeon HD 5450 + 1462 2133 Radeon HD 6350 + 1462 2180 Radeon HD 5450 + 1462 2181 Radeon HD 5450 + 1462 2182 Radeon HD 6350 + 1462 2183 Radeon HD 6350 + 1462 2230 Radeon HD 5450 + 1462 2231 Radeon HD 5450 + 1462 2495 Radeon HD 6350 + 148c 3001 Radeon HD 5530/6250 + 148c 3002 Radeon HD 6290 + 148c 3003 Radeon HD 6230 + 148c 3004 Radeon HD 6350 + 148c 7350 Radeon HD 7350 + 148c 8350 Radeon HD 8350 + 1545 7350 Radeon HD 7350 + 1642 3983 Radeon HD 5450 + 1642 3984 Radeon HD 6350 + 1642 3987 Radeon HD 6350 + 1642 3997 Radeon HD 5450 + 1642 3a05 Radeon HD 5450 + 1642 3b31 Radeon HD 6350A + 1682 3270 Radeon HD 7350 + 174b 3000 Radeon HD 6230 + 174b 3987 Radeon HD 6350 + 174b 5470 Radeon HD 5470 + 174b 5490 Radeon HD 5490 + 174b 5530 Radeon HD 5530 + 174b 6230 Radeon HD 6230 + 174b 6250 Radeon HD 6250 + 174b 6290 Radeon HD 6290 + 174b 6350 Radeon HD 6350 + 174b 7350 Radeon HD 7350 + 174b 8350 Radeon HD 8350 + 174b e127 Radeon HD 5450 + 174b e145 Radeon HD 5450 + 174b e153 Radeon HD 5450 + 1787 3000 Radeon HD 5470 + 1787 3001 Radeon HD 5530 + 1787 3002 Radeon HD 5490 + 17aa 3602 Radeon HD 5450 + 17aa 3603 Radeon HD 5450 + 17aa 360f Radeon HD 5450 + 17aa 3619 Radeon HD 5450 + 17af 3000 Radeon HD 6250 + 17af 3001 Radeon HD 6230 + 17af 3002 Radeon HD 6290 + 17af 3011 Radeon HD 5470 + 17af 3012 Radeon HD 5490 + 17af 3013 Radeon HD 5470 + 17af 3014 Radeon HD 6350 + 68fa Cedar [Radeon HD 7350/8350 / R5 220] + 1019 0019 Radeon HD 7350 + 1019 0021 Radeon HD 7350 + 1019 0022 Radeon HD 7350 + 1019 0026 Radeon HD 8350 + 103c 2adf Radeon HD 7350A + 103c 2ae8 Radeon HD 7350A + 1043 8350 Radeon HD 8350 + 1462 2128 Radeon HD 7350 + 1462 2184 Radeon HD 7350 + 1462 2186 Radeon HD 7350 + 1462 2495 Radeon HD 7350 + 1462 b490 Radeon HD 7350 + 1642 3985 Radeon HD 7350 + 174b 3510 Radeon HD 8350 + 174b 3521 Radeon R5 220 + 174b 3522 Radeon R5 220 + 174b 7350 Radeon HD 7350 + 174b 8153 Radeon HD 8350 + 174b e127 Radeon HD 7350 + 174b e153 Radeon HD 7350 + 174b e180 Radeon HD 7350 + 17af 3015 Radeon HD 7350 + 68fe Cedar LE + 6900 Topaz XT [Radeon R7 M260/M265 / M340/M360 / M440/M445 / 530/535 / 620/625 Mobile] + 1025 1056 Radeon R7 M360 / R8 M365DX + 1028 0640 Radeon R7 M260/M265 + 1028 0643 Radeon R7 M260/M265 + 1028 067f Radeon R7 M260 + 1028 0767 Radeon R7 M445 + 1028 0810 Radeon 530 + 1028 130a Radeon R7 M260 + 103c 2263 Radeon R7 M260 + 103c 2269 Radeon R7 M260 + 103c 22c6 Radeon R7 M260 + 103c 22c8 Radeon R7 M260 + 103c 2b45 Radeon R7 A360 + 103c 808c Radeon R7 M260 + 103c 8099 Radeon R7 M360 + 103c 80b5 Radeon R7 M360 + 103c 80b9 Radeon R7 M360 + 103c 811c Radeon R7 M340 + 103c 8226 Radeon R7 M440 + 10cf 1906 Radeon R7 M260 + 1170 9979 Radeon R7 M360 + 1179 f903 Radeon R7 M260 + 1179 f922 Radeon R7 M260 + 1179 f923 Radeon R7 M260 + 1179 f934 Radeon R7 M260 + 17aa 3822 Radeon R7 M360 + 17aa 3824 Radeon R7 M360 + 17aa 5021 Radeon R7 M260 + 6901 Topaz PRO [Radeon R5 M255] + 103c 1318 Radeon R6 M255DX + 6907 Meso XT [Radeon R5 M315] + 6921 Amethyst XT [Radeon R9 M295X] + 6929 Tonga XT GL [FirePro S7150] + 692b Tonga PRO GL [FirePro W7100] + 13cc 3d2b MXRT-7600 + 692f Tonga XTV GL [FirePro S7150V] + 6938 Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X] + 1043 04f5 Radeon R9 380X + 1043 04f7 Radeon R9 380X + 106b 013a Radeon R9 M295X Mac Edition + 1458 22c8 Radeon R9 380X + 148c 2350 Radeon R9 380X + 1682 9385 Radeon R9 380X + 174b e308 Radeon R9 380X Nitro 4G D5 + 17af 2006 Radeon R9 380X + 6939 Tonga PRO [Radeon R9 285/380] + 148c 9380 Radeon R9 380 +# Make naming scheme consistent + 174b e308 Radeon R9 380 Nitro 4G D5 + 694c Polaris 22 XT [Radeon RX Vega M GH] + 694e Polaris 22 XL [Radeon RX Vega M GL] + 694f Polaris 22 MGL XL [Radeon Pro WX Vega M GL] + 6980 Polaris12 + 6981 Lexa XT [Radeon PRO WX 3200] + 6985 Lexa XT [Radeon PRO WX 3100] + 6986 Polaris12 + 6987 Lexa [Radeon 540X/550X/630 / RX 640 / E9171 MCM] + 6995 Lexa XT [Radeon PRO WX 2100] + 699f Lexa PRO [Radeon 540/540X/550/550X / RX 540X/550/550X] + 1028 1720 Radeon RX 550X + 148c 2380 Lexa XL [Radeon RX 550] + 1da2 e367 Lexa PRO [Radeon RX 550] + 69a0 Vega 12 + 69a1 Vega 12 + 69a2 Vega 12 + 69a3 Vega 12 + 69af Vega 12 [Radeon Pro Vega 20] + 6fdf Polaris 20 XL [Radeon RX 580 2048SP] + 700f RS100 AGP Bridge + 7010 RS200/RS250 AGP Bridge + 7100 R520 [Radeon X1800 XT] + 7101 R520/M58 [Mobility Radeon X1800 XT] + 7102 R520/M58 [Mobility Radeon X1800] + 7104 R520 GL [FireGL V7200] + 13cc 3d0a MXRT-5100 + 7109 R520 [Radeon X1800 XL] + 1002 0322 All-in-Wonder X1800XL + 1002 0d02 Radeon X1800 CrossFire Edition + 710a R520 [Radeon X1800 GTO] + 1002 0b12 Radeon X1800 GTO² + 710b R520 [Radeon X1800 GTO] + 710e R520 GL [FireGL V7300] + 13cc 3d0c MXRT-5150 + 710f R520 GL [FireGL V7350] + 13cc 3d0e MXRT-7100 + 7120 R520 [Radeon X1800] (Secondary) + 7124 R520 GL [FireGL V7200] (Secondary) + 13cc 3d0b MXRT-5100 (Secondary) + 7129 R520 [Radeon X1800] (Secondary) + 1002 0323 All-In-Wonder X1800 XL (Secondary) + 1002 0d03 Radeon X1800 CrossFire Edition (Secondary) + 712e R520 GL [FireGL V7300] (Secondary) + 13cc 3d0d MXRT-5150 (Secondary) + 712f R520 GL [FireGL V7350] (Secondary) + 13cc 3d0f MXRT-7100 (Secondary) + 7140 RV515 [Radeon X1300/X1550/X1600 Series] + 7142 RV515 PRO [Radeon X1300/X1550 Series] + 1002 0322 All-in-Wonder 2006 PCI-E Edition + 1043 0142 EAX1300PRO/TD/256M + 7143 RV505 [Radeon X1300/X1550 Series] + 7145 RV515/M54 [Mobility Radeon X1400] + 17aa 2006 Thinkpad T60 model 2007 + 7146 RV515 [Radeon X1300/X1550] + 1002 0322 All-in-Wonder 2006 PCI-E Edition + 1545 1996 Radeon X1300 512MB PCI-e + 7147 RV505 [Radeon X1550 64-bit] + 7149 RV515/M52 [Mobility Radeon X1300] + 714a RV515/M52 [Mobility Radeon X1300] + 7152 RV515 GL [FireGL V3300] + 7153 RV515 GL [FireGL V3350] + 715f RV505 CE [Radeon X1550 64-bit] + 7162 RV515 PRO [Radeon X1300/X1550 Series] (Secondary) + 1002 0323 All-in-Wonder 2006 PCI-E Edition (Secondary) + 7163 RV505 [Radeon X1550 Series] (Secondary) + 7166 RV515 [Radeon X1300/X1550 Series] (Secondary) + 1002 0323 All-in-Wonder 2006 PCI-E Edition (Secondary) + 1545 1997 Radeon X1300 512MB PCI-e (Secondary) + 7167 RV515 [Radeon X1550 64-bit] (Secondary) + 7172 RV515 GL [FireGL V3300] (Secondary) + 7173 RV515 GL [FireGL V3350] (Secondary) + 7181 RV516 [Radeon X1600/X1650 Series] + 7183 RV516 [Radeon X1300/X1550 Series] + 7186 RV516/M64 [Mobility Radeon X1450] + 7187 RV516 [Radeon X1300/X1550 Series] + 7188 RV516/M64-S [Mobility Radeon X2300] + 103c 30c1 6910p + 718a RV516/M64 [Mobility Radeon X2300] + 718b RV516/M62 [Mobility Radeon X1350] + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 718c RV516/M62-CSP64 [Mobility Radeon X1350] + 718d RV516/M64-CSP128 [Mobility Radeon X1450] + 7193 RV516 [Radeon X1550 Series] + 7196 RV516/M62-S [Mobility Radeon X1350] + 719b RV516 GL [FireMV 2250] + 13cc 3d12 MXRT-1150 + 13cc 3d14 MXRT-2150 + 719f RV516 [Radeon X1550 Series] + 71a0 RV516 [Radeon X1300/X1550 Series] (Secondary) + 71a1 RV516 [Radeon X1600/X1650 Series] (Secondary) + 71a3 RV516 [Radeon X1300/X1550 Series] (Secondary) + 71a7 RV516 [Radeon X1300/X1550 Series] (Secondary) + 71bb RV516 GL [FireMV 2250] (Secondary) + 13cc 3d13 MXRT-1150 (Secondary) + 13cc 3d15 MXRT-2150 (Secondary) + 71c0 RV530 [Radeon X1600 XT/X1650 GTO] + 1002 e160 Radeon X1650 GTO + 174b e160 Radeon X1650 GTO + 71c1 RV535 [Radeon X1650 PRO] + 174b 0880 Radeon X1700 FSC + 71c2 RV530 [Radeon X1600 PRO] + 71c4 RV530/M56 GL [Mobility FireGL V5200] + 17aa 2007 ThinkPad T60p + 71c5 RV530/M56-P [Mobility Radeon X1600] + 103c 309f Compaq nx9420 Notebook + 103c 30a3 Compaq NW8440 + 1043 10b2 A6J-Q008 + 106b 0080 MacBook Pro + 71c6 RV530LE [Radeon X1600/X1650 PRO] + 71c7 RV535 [Radeon X1650 PRO] + 1787 3000 PowerColor X1650 PRO AGP + 71ce RV530 [Radeon X1300 XT/X1600 PRO] + 71d2 RV530 GL [FireGL V3400] + 13cc 3d08 MXRT-2100 + 71d4 RV530/M66 GL [Mobility FireGL V5250] + 71d5 RV530/M66-P [Mobility Radeon X1700] + 71d6 RV530/M66-XT [Mobility Radeon X1700] + 71de RV530/M66 [Mobility Radeon X1700/X2500] + 71e0 RV530 [Radeon X1600] (Secondary) + 174b e161 Radeon X1600 GTO (Secondary) + 71e1 RV535 [Radeon X1650 PRO] (Secondary) + 174b 0881 Radeon X1700 FSC (Secondary) + 71e2 RV530 [Radeon X1600] (Secondary) + 71e6 RV530 [Radeon X1650] (Secondary) + 71e7 RV535 [Radeon X1650 PRO] (Secondary) + 1787 3001 Radeon X1650 PRO AGP + 71f2 RV530 GL [FireGL V3400] (Secondary) + 13cc 3d09 MXRT-2100 (Secondary) + 7210 RV550/M71 [Mobility Radeon HD 2300] + 7211 RV550/M71 [Mobility Radeon X2300 HD] + 7240 R580+ [Radeon X1950 XTX] + 1002 0d02 Radeon X1950 CrossFire Edition + 7244 R580+ [Radeon X1950 XT] + 7248 R580 [Radeon X1950] + 7249 R580 [Radeon X1900 XT] + 1002 0412 All-In-Wonder X1900 + 1002 0b12 Radeon X1900 XT/XTX + 1002 0d02 Radeon X1900 CrossFire Edition + 1043 0160 Radeon X1900 XTX 512 MB GDDR3 + 724b R580 [Radeon X1900 GT] + 1002 0b12 Radeon X1900 (Primary) + 1002 0b13 Radeon X1900 (Secondary) + 724e R580 GL [FireGL V7350] + 7269 R580 [Radeon X1900 XT] (Secondary) + 726b R580 [Radeon X1900 GT] (Secondary) + 726e R580 [AMD Stream Processor] (Secondary) + 7280 RV570 [Radeon X1950 PRO] + 7288 RV570 [Radeon X1950 GT] + 7291 RV560 [Radeon X1650 XT] + 1462 0810 Radeon X1700 SE + 7293 RV560 [Radeon X1650 GT] + 72a0 RV570 [Radeon X1950 PRO] (Secondary) + 72a8 RV570 [Radeon X1950 GT] (Secondary) + 72b1 RV560 [Radeon X1650 XT] (Secondary) + 72b3 RV560 [Radeon X1650 GT] (Secondary) + 7300 Fiji [Radeon R9 FURY / NANO Series] + 1002 0b36 Radeon R9 FURY X / NANO + 1002 1b36 Radeon Pro Duo + 1043 049e Radeon R9 FURY + 1043 04a0 Radeon R9 FURY X + 174b e329 Radeon R9 FURY + 7310 Navi 10 + 7312 Navi 10 [Radeon Pro W5700] + 731f Navi 10 [Radeon RX 5600 OEM/5600 XT / 5700/5700 XT] + 7340 Navi 14 [Radeon RX 5500/5500M / Pro 5500M] + 7341 Navi 14 [Radeon Pro W5500] + 7347 Navi 14 [Radeon Pro W5500M] + 734f Navi 14 [Radeon Pro W5300M] + 7833 RS350 Host Bridge + 7834 RS350 [Radeon 9100 PRO/XT IGP] + 7835 RS350M [Mobility Radeon 9000 IGP] + 7838 RS350 AGP Bridge + 7910 RS690 Host Bridge + 1179 ff50 Satellite P305D-S8995E + 17f2 5000 KI690-AM2 Motherboard + 7911 RS690/RS740 Host Bridge + 1002 7910 RS690/RS740 Host Bridge + 7912 RS690/RS740 PCI to PCI Bridge (Internal gfx) + 7913 RS690 PCI to PCI Bridge (PCI Express Graphics Port 0) + 7915 RS690 PCI to PCI Bridge (PCI Express Port 1) + 7916 RS690 PCI to PCI Bridge (PCI Express Port 2) + 7917 RS690 PCI to PCI Bridge (PCI Express Port 3) + 1002 7910 RS690 PCI to PCI Bridge + 7919 RS690 HDMI Audio [Radeon Xpress 1200 Series] + 1179 7919 Satellite P305D-S8995E + 17f2 5000 KI690-AM2 Motherboard + 791e RS690 [Radeon X1200] + 1462 7327 K9AG Neo2 + 17f2 5000 KI690-AM2 Motherboard + 791f RS690M [Radeon Xpress 1200/1250/1270] + 1179 ff50 Satellite P305D-S8995E + 7930 RS600 Host Bridge + 7932 RS600 PCI to PCI Bridge (Internal gfx) + 7933 RS600 PCI to PCI Bridge (PCI Express Graphics Port 0) + 7935 RS600 PCI to PCI Bridge (PCI Express Port 1) + 7936 RS600 PCI to PCI Bridge (PCI Express Port 2) + 7937 RS690 PCI to PCI Bridge (PCI Express Port 3) + 793b RS600 HDMI Audio [Radeon Xpress 1250] + 793f RS690M [Radeon Xpress 1200/1250/1270] (Secondary) + 7941 RS600 [Radeon Xpress 1250] + 7942 RS600M [Radeon Xpress 1250] + 796e RS740 [Radeon 2100] + 105b 0e13 N15235/A74MX mainboard + 9400 R600 [Radeon HD 2900 PRO/XT] + 1002 2552 Radeon HD 2900 XT + 1002 3000 Radeon HD 2900 PRO + 1002 3142 HIS Radeon HD 2900XT 512MB GDDR3 VIVO PCIe + 9401 R600 [Radeon HD 2900 XT] + 9403 R600 [Radeon HD 2900 PRO] + 9405 R600 [Radeon HD 2900 GT] + 940a R600 GL [FireGL V8650] + 13cc 3d16 MXRT-7200 + 940b R600 GL [FireGL V8600] + 940f R600 GL [FireGL V7600] + 9440 RV770 [Radeon HD 4870] + 9441 R700 [Radeon HD 4870 X2] + 9442 RV770 [Radeon HD 4850] + 1002 0502 MSI Radeon HD 4850 512MB GDDR3 + 174b e810 Radeon HD 4850 512MB GDDR3 + 9443 R700 [Radeon HD 4850 X2] + 9444 RV770 GL [FirePro V8750] + 9446 RV770 GL [FirePro V7760] + 944a RV770/M98L [Mobility Radeon HD 4850] + 944b RV770/M98 [Mobility Radeon HD 4850 X2] + 944c RV770 LE [Radeon HD 4830] + 944e RV770 CE [Radeon HD 4710] + 174b 3261 Radeon HD 4810 + 9450 RV770 GL [FireStream 9270] + 9452 RV770 GL [FireStream 9250] + 9456 RV770 GL [FirePro V8700] + 945a RV770/M98-XT [Mobility Radeon HD 4870] + 9460 RV790 [Radeon HD 4890] + 9462 RV790 [Radeon HD 4860] + 946a RV770 GL [FirePro M7750] + 9480 RV730/M96 [Mobility Radeon HD 4650/5165] + 103c 3628 Mobility Radeon HD 4650 [dv6-1190en] + 9488 RV730/M96-XT [Mobility Radeon HD 4670] + 9489 RV730/M96 GL [Mobility FireGL V5725] + 9490 RV730 XT [Radeon HD 4670] + 174b e880 Radeon HD 4670 512MB GDDR3 Dual DVI-I/TVO + 9491 RV730/M96-CSP [Radeon E4690] + 9495 RV730 [Radeon HD 4600 AGP Series] + 1002 0028 Radeon HD 4650/4670 AGP + 1092 0028 Radeon HD 4670 AGP 512MB DDR2 + 1458 0028 Radeon HD 4650 AGP + 1682 0028 Radeon HD 4650 AGP + 174b 0028 Radeon HD 4650 AGP DDR2 + 9498 RV730 PRO [Radeon HD 4650] + 949c RV730 GL [FirePro V7750] + 13cc 3d1b MXRT-7300 + 949e RV730 GL [FirePro V5700] + 949f RV730 GL [FirePro V3750] + 94a0 RV740/M97 [Mobility Radeon HD 4830] + 94a1 RV740/M97-XT [Mobility Radeon HD 4860] + 94a3 RV740/M97 GL [FirePro M7740] + 94b3 RV740 PRO [Radeon HD 4770] + 94b4 RV740 PRO [Radeon HD 4750] + 94c1 RV610 [Radeon HD 2400 PRO/XT] + 1028 0211 Optiplex 755 + 1028 0d02 Optiplex 755 + 94c3 RV610 [Radeon HD 2400 PRO] + 1028 0302 Radeon HD 2400 Pro + 174b e400 Radeon HD 2400 PRO + 18bc 3550 Radeon HD 2400 PRO + 94c4 RV610 LE [Radeon HD 2400 PRO AGP] + 94c5 RV610 [Radeon HD 2400 LE] + 94c7 RV610 [Radeon HD 2350] + 94c8 RV610/M74 [Mobility Radeon HD 2400 XT] + 94c9 RV610/M72-S [Mobility Radeon HD 2400] + 1002 94c9 Radeon HD2400 + 94cb RV610 [Radeon E2400] + 94cc RV610 LE [Radeon HD 2400 PRO PCI] + 9500 RV670 [Radeon HD 3850 X2] + 9501 RV670 [Radeon HD 3870] + 174b e620 Radeon HD 3870 + 9504 RV670/M88 [Mobility Radeon HD 3850] + 9505 RV670 [Radeon HD 3690/3850] + 148c 3000 Radeon HD 3850 + 174b 3000 Radeon HD 3690/3850 + 1787 3000 Radeon HD 3690 + 9506 RV670/M88 [Mobility Radeon HD 3850 X2] + 9507 RV670 [Radeon HD 3830] + 9508 RV670/M88-XT [Mobility Radeon HD 3870] + 9509 RV670/M88 [Mobility Radeon HD 3870 X2] + 950f R680 [Radeon HD 3870 X2] + 9511 RV670 GL [FireGL V7700] + 9513 RV670 [Radeon HD 3850 X2] + 9515 RV670 PRO [Radeon HD 3850 AGP] + 9519 RV670 GL [FireStream 9170] + 9540 RV710 [Radeon HD 4550] + 954f RV710 [Radeon HD 4350/4550] + 1462 1618 R4350 MD512H (MS-V161) + 9552 RV710/M92 [Mobility Radeon HD 4330/4350/4550] + 1028 1103 M92 [Mobility Radeon HD 4330] +# GV-R435OC-512I/FF1 + 1458 21ac Radeon HD 4350 +# GV-R455HM-512I/F41 + 1458 21ed Radeon HD 4550 +# 113-100928-J01 + 148c 3000 Radeon HD 4350 Go! Green 512MB GDDR3 +# 113-2E172001-003 + 174b 3000 Radeon HD 4350/4550 HyperMemory DDR2 + 9553 RV710/M92 [Mobility Radeon HD 4530/4570/545v] + 1025 015e Mobility Radeon HD 4570 + 1025 017d Mobility Radeon HD 4570 + 1025 0205 Mobility Radeon HD 4570 / 545v + 1025 0206 Mobility Radeon HD 4570 + 1025 0237 Mobility Radeon HD 4570 + 1028 02be Mobility Radeon HD 4570 / 545v + 1028 02e8 Mobility Radeon HD 4530 + 103c 143c Mobility Radeon HD 545v + 103c 1446 Mobility Radeon HD 545v + 103c 3624 Mobility Radeon HD 4530 + 103c 3628 Mobility Radeon HD 4530 + 103c 3636 Mobility Radeon HD 4530 + 1043 1b32 Mobility Radeon HD 4570 + 1043 1b42 Mobility Radeon HD 4570 + 104d 9056 Mobility Radeon HD 4570 + 1179 ff82 Satellite L505-13T GPU (Mobility Radeon HD 5145) + 144d c07f Mobility Radeon HD 545v + 144d c571 Mobility Radeon HD 545v + 1462 1006 Mobility Radeon HD 545v + 17aa 2129 Mobility Radeon HD 545v + 17aa 215b Mobility Radeon HD 545v + 17aa 21bb Mobility Radeon HD 545v + 9555 RV710/M92 [Mobility Radeon HD 4350/4550] + 103c 1411 ProBook 4720s GPU (Mobility Radeon HD 4350) + 9557 RV711 GL [FirePro RG220] + 955f RV710/M92 [Mobility Radeon HD 4330] + 9580 RV630 [Radeon HD 2600 PRO] + 9581 RV630/M76 [Mobility Radeon HD 2600] + 9583 RV630/M76 [Mobility Radeon HD 2600 XT/2700] + 106b 0083 iMac 7,1 + 1734 1107 Mobility Radeon HD 2700 + 9586 RV630 XT [Radeon HD 2600 XT AGP] + 9587 RV630 PRO [Radeon HD 2600 PRO AGP] + 9588 RV630 XT [Radeon HD 2600 XT] + 1458 216c Radeon HD 2600 XT, 256MB GDDR3, 2x DVI, TV-out, PCIe (GV-RX26T256H) + 9589 RV630 PRO [Radeon HD 2600 PRO] +# Rebranded HD 2600 PRO + 1787 3000 Radeon HD 3610 + 958a RV630 [Radeon HD 2600 X2] + 958b RV630/M76 [Mobility Radeon HD 2600 XT] + 958c RV630 GL [FireGL V5600] + 13cc 3d18 MXRT-5200 + 958d RV630 GL [FireGL V3600] + 9591 RV635/M86 [Mobility Radeon HD 3650] + 1002 9591 Mobility Radeon HD 3650 + 9593 RV635/M86 [Mobility Radeon HD 3670] + 9595 RV635/M86 GL [Mobility FireGL V5700] + 9596 RV635 PRO [Radeon HD 3650 AGP] + 1043 0028 EAH3650 SILENT/HTDI/512M/A + 9597 RV635 PRO [Radeon HD 3650 AGP] + 9598 RV635 [Radeon HD 3650/3750/4570/4580] + 1002 9598 Mobility Radeon HD 3600 + 1043 01d6 EAH3650 Silent + 1043 3001 Radeon HD 4570 + 174b 3001 Radeon HD 3750 + 174b 4580 RV635 PRO [Radeon HD 4580] + 17af 3011 RV635 PRO [Radeon HD 4580] + 9599 RV635 PRO [Radeon HD 3650 AGP] + 95c0 RV620 PRO [Radeon HD 3470] + 1002 95c0 Mobility Radeon HD 3470 + 95c2 RV620/M82 [Mobility Radeon HD 3410/3430] + 95c4 RV620/M82 [Mobility Radeon HD 3450/3470] + 1002 95c4 Mobility Radeon HD 3400 + 95c5 RV620 LE [Radeon HD 3450] + 1028 0342 OptiPlex 980 + 95c6 RV620 LE [Radeon HD 3450 AGP] + 95c9 RV620 LE [Radeon HD 3450 PCI] + 95cc RV620 GL [FirePro V3700] + 95cd RV620 GL [FirePro 2450] + 95cf RV620 GL [FirePro 2260] + 960f RS780 HDMI Audio [Radeon 3000/3100 / HD 3200/3300] + 9610 RS780 [Radeon HD 3200] + 1458 d000 GA-MA78GM-S2H Motherboard + 9611 RS780C [Radeon 3100] + 9612 RS780M [Mobility Radeon HD 3200] + 9613 RS780MC [Mobility Radeon HD 3100] + 9614 RS780D [Radeon HD 3300] + 9616 RS780L [Radeon 3000] + 9640 Sumo [Radeon HD 6550D] + 9641 Sumo [Radeon HD 6620G] + 9642 SuperSumo [Radeon HD 6370D] + 9643 SuperSumo [Radeon HD 6380G] + 9644 SuperSumo [Radeon HD 6410D] + 9645 SuperSumo [Radeon HD 6410D] + 9647 Sumo [Radeon HD 6520G] + 9648 Sumo [Radeon HD 6480G] + 9649 SuperSumo [Radeon HD 6480G] + 964a Sumo [Radeon HD 6530D] + 964b Sumo + 964c Sumo + 964e Sumo + 964f Sumo + 970f RS880 HDMI Audio [Radeon HD 4200 Series] + 1019 2120 A785GM-M + 1043 83a2 M4A785TD Motherboard + 1043 843e M5A88-V EVO + 9710 RS880 [Radeon HD 4200] + 1019 2120 A785GM-M + 1043 83a2 M4A785TD Motherboard + 9712 RS880M [Mobility Radeon HD 4225/4250] + 103c 1609 ProLiant MicroServer N36L + 9713 RS880M [Mobility Radeon HD 4100] + 9714 RS880 [Radeon HD 4290] + 9715 RS880 [Radeon HD 4250] + 1043 843e M5A88-V EVO +# Radeon HD 6250 too? + 9802 Wrestler [Radeon HD 6310] + 174b 1001 PURE Fusion Mini + 9803 Wrestler [Radeon HD 6310] + 9804 Wrestler [Radeon HD 6250] + 9805 Wrestler [Radeon HD 6250] + 9806 Wrestler [Radeon HD 6320] + 9807 Wrestler [Radeon HD 6290] + 9808 Wrestler [Radeon HD 7340] + 9809 Wrestler [Radeon HD 7310] + 980a Wrestler [Radeon HD 7290] + 9830 Kabini [Radeon HD 8400 / R3 Series] + 9831 Kabini [Radeon HD 8400E] + 9832 Kabini [Radeon HD 8330] + 1849 9832 QC5000-ITX/PH + 9833 Kabini [Radeon HD 8330E] + 9834 Kabini [Radeon HD 8210] + 9835 Kabini [Radeon HD 8310E] + 9836 Kabini [Radeon HD 8280 / R3 Series] + 9837 Kabini [Radeon HD 8280E] + 9838 Kabini [Radeon HD 8240 / R3 Series] + 9839 Kabini [Radeon HD 8180] + 983d Temash [Radeon HD 8250/8280G] + 9840 Kabini HDMI/DP Audio + 1849 9840 QC5000-ITX/PH + 9850 Mullins [Radeon R3 Graphics] + 9851 Mullins [Radeon R4/R5 Graphics] + 1179 f928 Beema [Radeon R5 Graphics] + 9852 Mullins [Radeon R2 Graphics] + 9853 Mullins [Radeon R2 Graphics] + 9854 Mullins [Radeon R3E Graphics] + 9855 Mullins [Radeon R6 Graphics] + 9856 Mullins [Radeon R1E/R2E Graphics] + 9857 Mullins [Radeon APU XX-2200M with R2 Graphics] + 9858 Mullins + 9859 Mullins + 985a Mullins + 985b Mullins + 985c Mullins + 985d Mullins + 985e Mullins + 985f Mullins + 9874 Wani [Radeon R5/R6/R7 Graphics] + 1002 1871 Radeon R5 Graphics + 1002 1e20 Radeon R7 Graphics + 1028 06bd Radeon R6 Graphics + 103c 2b44 Radeon R6 Graphics + 103c 8221 Radeon R5 Graphics + 103c 8223 Radeon R5 Graphics + 103c 8238 Radeon R7 Graphics + 103c 8353 Radeon R7 Graphics + 1458 d000 Radeon R7 Graphics + 17aa 5113 Radeon R6 Graphics + 17aa 5116 Radeon R6 Graphics + 17aa 5118 Radeon R5 Graphics + 9890 Amur + 98c0 Nolan + 98e4 Stoney [Radeon R2/R3/R4/R5 Graphics] + 9900 Trinity [Radeon HD 7660G] + 103c 1985 Pavilion 17-e163sg Notebook PC +# AMD A10-5800K CPU + 9901 Trinity [Radeon HD 7660D] + 9902 Trinity HDMI Audio Controller + 103c 194e ProBook 455 G1 Notebook + 103c 1985 Pavilion 17-e163sg Notebook PC + 9903 Trinity [Radeon HD 7640G] + 103c 194e ProBook 455 G1 Notebook + 103c 1952 ProBook 455 G1 Notebook + 9904 Trinity [Radeon HD 7560D] + 9905 Trinity GL [FirePro A300] + 9906 Trinity GL [FirePro A320] + 9907 Trinity [Radeon HD 7620G] + 9908 Trinity [Radeon HD 7600G] + 9909 Trinity [Radeon HD 7500G] + 990a Trinity [Radeon HD 7500G] + 990b Richland [Radeon HD 8650G] + 990c Richland [Radeon HD 8670D] + 990d Richland [Radeon HD 8550G] + 990e Richland [Radeon HD 8570D] + 990f Richland [Radeon HD 8610G] + 9910 Trinity [Radeon HD 7660G] + 9913 Trinity [Radeon HD 7640G] + 9917 Trinity [Radeon HD 7620G] + 9918 Trinity [Radeon HD 7600G] + 9919 Trinity [Radeon HD 7500G] + 991e Bishop + 9920 Liverpool [Playstation 4 APU] + 9921 Liverpool HDMI/DP Audio Controller + 9922 Starshp + 9923 Starsha2 [Kingston/Clayton] + 9924 Gladius + 9925 Kingston/Clayton/Jupiter/Gladius/Montego HDMI Controller + 9926 Jupiter + 9990 Trinity 2 [Radeon HD 7520G] + 9991 Trinity 2 [Radeon HD 7540D] + 9992 Trinity 2 [Radeon HD 7420G] + 9993 Trinity 2 [Radeon HD 7480D] + 9994 Trinity 2 [Radeon HD 7400G] + 9995 Richland [Radeon HD 8450G] + 9996 Richland [Radeon HD 8470D] + 9997 Richland [Radeon HD 8350G] + 9998 Richland [Radeon HD 8370D] + 9999 Richland [Radeon HD 8510G] + 999a Richland [Radeon HD 8410G] + 999b Richland [Radeon HD 8310G] + 999c Richland [Radeon HD 8650D] +# AMD Quad-Core A8-Series APU A8-6500T with Radeon HD 8550D + 999d Richland [Radeon HD 8550D] + 99a0 Trinity 2 [Radeon HD 7520G] + 99a2 Trinity 2 [Radeon HD 7420G] + 99a4 Trinity 2 [Radeon HD 7400G] + aa00 R600 HDMI Audio [Radeon HD 2900 GT/PRO/XT] + aa01 RV635 HDMI Audio [Radeon HD 3650/3730/3750] + aa08 RV630 HDMI Audio [Radeon HD 2600 PRO/XT / HD 3610] + aa10 RV610 HDMI Audio [Radeon HD 2350 PRO / 2400 PRO/XT / HD 3410] + 174b aa10 Radeon HD 2400 PRO + 18bc aa10 Radeon HD 2400 PRO + aa18 RV670/680 HDMI Audio [Radeon HD 3690/3800 Series] + aa20 RV635 HDMI Audio [Radeon HD 3650/3730/3750] + aa28 RV620 HDMI Audio [Radeon HD 3450/3470/3550/3570] + aa30 RV770 HDMI Audio [Radeon HD 4850/4870] + 174b aa30 Radeon HD 4850 512MB GDDR3 PCI-E Dual Slot Fansink + aa38 RV710/730 HDMI Audio [Radeon HD 4000 series] + 103c 3628 dv6-1190en + aa50 Cypress HDMI Audio [Radeon HD 5830/5850/5870 / 6850/6870 Rebrand] + aa58 Juniper HDMI Audio [Radeon HD 5700 Series] +# 5500, 5600 and mobile 5700 series + aa60 Redwood HDMI Audio [Radeon HD 5000 Series] + 1025 033d Mobility Radeon HD 5650 + 1025 0347 Aspire 7740G + aa68 Cedar HDMI Audio [Radeon HD 5400/6300/7300 Series] + 1028 aa68 XPS 8300 + aa80 Cayman/Antilles HDMI Audio [Radeon HD 6930/6950/6970/6990] + aa88 Barts HDMI Audio [Radeon HD 6790/6850/6870 / 7720 OEM] + aa90 Turks HDMI Audio [Radeon HD 6500/6600 / 6700M Series] + 1028 04a3 Precision M4600 + aa98 Caicos HDMI Audio [Radeon HD 6450 / 7450/8450/8490 OEM / R5 230/235/235X OEM] + 174b aa98 Radeon HD 6450 1GB DDR3 + aaa0 Tahiti HDMI Audio [Radeon HD 7870 XT / 7950/7970] + aab0 Oland/Hainan/Cape Verde/Pitcairn HDMI Audio [Radeon HD 7000 Series] + aab8 Tiran HDMI Audio + aac0 Tobago HDMI Audio [Radeon R7 360 / R9 360 OEM] + aac8 Hawaii HDMI Audio [Radeon R9 290/290X / 390/390X] + aad8 Tonga HDMI Audio [Radeon R9 285/380] + 174b aad8 Radeon R9 285/380 HDMI Audio + aae0 Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] + aae8 Fiji HDMI/DP Audio [Radeon R9 Nano / FURY/FURY X] + aaf0 Ellesmere HDMI Audio [Radeon RX 470/480 / 570/580/590] + aaf8 Vega 10 HDMI Audio [Radeon Vega 56/64] + ab00 Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] + ab08 Polaris 22 HDMI Audio + ab10 Lexa HDMI Audio + ab18 Vega 12 HDMI Audio + ab20 Vega 20 HDMI Audio [Radeon VII] + ab38 Navi 10 HDMI Audio + ac00 Theater 506 World-Wide Analog Decoder + ac01 Theater 506 World-Wide Analog Decoder + ac02 TV Wonder HD 600 PCIe + ac03 Theater 506 PCIe + ac04 Theater 506 USB + ac05 Theater 506 USB + ac06 Theater 506 External USB + ac07 Theater 506 External USB + ac08 Theater 506A World-Wide Analog Decoder + Demodulator + ac09 Theater 506A World-Wide Analog Decoder + Demodulator + ac0a Theater 506A PCIe + ac0b Theater 506A PCIe + ac0c Theater 506A USB + ac0d Theater 506A USB + ac0e Theater 506A External USB + ac0f Theater 506A External USB + ac12 Theater HD T507 (DVB-T) TV tuner/capture device + cab0 RS100 Host Bridge + cab2 RS200 Host Bridge + cab3 RS250 Host Bridge + cbb2 RS200 Host Bridge +1003 ULSI Systems + 0201 US201 +1004 VLSI Technology Inc + 0005 82C592-FC1 + 0006 82C593-FC1 + 0007 82C594-AFC2 + 0008 82C596/7 [Wildcat] + 0009 82C597-AFC2 + 000c 82C541 [Lynx] + 000d 82C543 [Lynx] + 0101 82C532 + 0102 82C534 [Eagle] + 0103 82C538 + 0104 82C535 + 0105 82C147 + 0200 82C975 + 0280 82C925 + 0304 QSound ThunderBird PCI Audio + 1004 0304 QSound ThunderBird PCI Audio + 122d 1206 DSP368 Audio + 1483 5020 XWave Thunder 3D Audio + 0305 QSound ThunderBird PCI Audio Gameport + 1004 0305 QSound ThunderBird PCI Audio Gameport + 122d 1207 DSP368 Audio Gameport + 1483 5021 XWave Thunder 3D Audio Gameport + 0306 QSound ThunderBird PCI Audio Support Registers + 1004 0306 QSound ThunderBird PCI Audio Support Registers + 122d 1208 DSP368 Audio Support Registers + 1483 5022 XWave Thunder 3D Audio Support Registers + 0307 SAA7785 ThunderBird PCI Audio + 1004 0703 Philips Rhythmic Edge PSC703 + 1004 0705 Philips Seismic Edge PSC705 + 1004 0706 Philips Acoustic Edge PSC706 + 0308 SAA7785 ThunderBird PCI Audio Gameport + 0702 VAS96011 [Golden Gate II] + 0703 Tollgate +1005 Avance Logic Inc. [ALI] + 2064 ALG2032/2064 + 2128 ALG2364A + 2301 ALG2301 + 2302 ALG2302 + 2364 ALG2364 + 2464 ALG2364A + 2501 ALG2564A/25128A +1006 Reply Group +1007 NetFrame Systems Inc +1008 Epson +100a Phoenix Technologies +100b National Semiconductor Corporation + 0001 DP83810 + 0002 87415/87560 IDE + 000e 87560 Legacy I/O + 000f FireWire Controller + 0011 NS87560 National PCI System I/O + 0012 USB Controller + 0020 DP83815 (MacPhyter) Ethernet Controller + 103c 0024 Pavilion ze4400 builtin Network + 12d9 000c Aculab E1/T1 PMXc cPCI carrier card + 1385 f311 FA311 / FA312 (FA311 with WoL HW) + 1385 f312 FA312 (rev. A1) Fast Ethernet PCI Adapter + 0021 PC87200 PCI to ISA Bridge + 0022 DP83820 10/100/1000 Ethernet Controller + 1186 4900 DGE-500T + 1385 621a GA621 + 1385 622a GA622T + 0028 Geode GX2 Host Bridge + 002a CS5535 South Bridge + 002b CS5535 ISA bridge + 002d CS5535 IDE + 002e CS5535 Audio + 002f CS5535 USB + 0030 Geode GX2 Graphics Processor + 0035 DP83065 [Saturn] 10/100/1000 Ethernet Controller + 0500 SCx200 Bridge + 0501 SCx200 SMI + 0502 SCx200, SC1100 IDE controller + 100b 0502 IDE Controller + 0503 SCx200, SC1100 Audio Controller + 100b 0503 XpressAudio controller + 0504 SCx200 Video + 0505 SCx200 XBus + 0510 SC1100 Bridge + 100b 0500 GPIO and LPC support bridge + 0511 SC1100 SMI & ACPI + 100b 0501 SC1100 SMI & ACPI bridge + 0515 SC1100 XBus + 100b 0505 SC1100 PCI to XBus bridge + d001 87410 IDE +100c Tseng Labs Inc + 3202 ET4000/W32p rev A + 3205 ET4000/W32p rev B + 3206 ET4000/W32p rev C + 3207 ET4000/W32p rev D + 3208 ET6000 + 4702 ET6300 +100d AST Research Inc +100e Weitek + 9000 P9000 Viper + 9001 P9000 Viper + 9002 P9000 Viper + 9100 P9100 Viper Pro/SE +1010 Video Logic, Ltd. +1011 Digital Equipment Corporation + 0001 DECchip 21050 + 0002 DECchip 21040 [Tulip] + 0004 DECchip 21030 [TGA] + 0007 NVRAM [Zephyr NVRAM] + 0008 KZPSA [KZPSA] + 0009 DECchip 21140 [FasterNet] + 1025 0310 21140 Fast Ethernet + 10b8 2001 SMC9332BDT EtherPower 10/100 + 10b8 2002 SMC9332BVT EtherPower T4 10/100 + 10b8 2003 SMC9334BDT EtherPower 10/100 (1-port) + 1109 2400 ANA-6944A/TX Fast Ethernet + 1112 2300 RNS2300 Fast Ethernet + 1112 2320 RNS2320 Fast Ethernet + 1112 2340 RNS2340 Fast Ethernet + 1113 1207 EN-1207-TX Fast Ethernet + 1186 1100 DFE-500TX Fast Ethernet + 1186 1112 DFE-570TX Fast Ethernet + 1186 1140 DFE-660 Cardbus Ethernet 10/100 + 1186 1142 DFE-660 Cardbus Ethernet 10/100 + 11f6 0503 Freedomline Fast Ethernet + 1282 9100 AEF-380TXD Fast Ethernet + 1385 1100 FA310TX Fast Ethernet + 2646 0001 KNE100TX Fast Ethernet + 000a 21230 Video Codec + 000d PBXGB [TGA2] + 000f DEFPA FDDI PCI-to-PDQ Interface Chip [PFI] + 1011 def1 FDDI controller (DEFPA) + 103c def1 FDDI controller (3X-DEFPA) + 0014 DECchip 21041 [Tulip Pass 3] + 1186 0100 DE-530+ + 0016 DGLPB [OPPO] + 0017 PV-PCI Graphics Controller (ZLXp-L) + 0018 Memory Channel interface + 0019 DECchip 21142/43 + 1011 500a DE500A Fast Ethernet + 1011 500b DE500B Fast Ethernet + 1014 0001 10/100 EtherJet Cardbus + 1025 0315 ALN315 Fast Ethernet + 1033 800c PC-9821-CS01 100BASE-TX Interface Card + 1033 800d PC-9821NR-B06 100BASE-TX Interface Card + 103c 125a 10/100Base-TX (PCI) [A5506B] + 108d 0016 Rapidfire 2327 10/100 Ethernet + 108d 0017 GoCard 2250 Ethernet 10/100 Cardbus + 10b8 2005 SMC8032DT Extreme Ethernet 10/100 + 10b8 8034 SMC8034 Extreme Ethernet 10/100 + 10ef 8169 Cardbus Fast Ethernet + 1109 2a00 ANA-6911A/TX Fast Ethernet + 1109 2b00 ANA-6911A/TXC Fast Ethernet + 1109 3000 ANA-6922/TX Fast Ethernet + 1113 1207 Cheetah Fast Ethernet + 1113 2220 Cardbus Fast Ethernet + 115d 0002 Cardbus Ethernet 10/100 + 1179 0203 Fast Ethernet + 1179 0204 Cardbus Fast Ethernet + 1186 1100 DFE-500TX Fast Ethernet + 1186 1101 DFE-500TX Fast Ethernet + 1186 1102 DFE-500TX Fast Ethernet + 1186 1112 DFE-570TX Quad Fast Ethernet + 11f0 4235 21143 [FASTLine-II UTP 10/100] + 1259 2800 AT-2800Tx Fast Ethernet + 1266 0004 Eagle Fast EtherMAX + 12af 0019 NetFlyer Cardbus Fast Ethernet + 1374 0001 Cardbus Ethernet Card 10/100 + 1374 0002 Cardbus Ethernet Card 10/100 + 1374 0007 Cardbus Ethernet Card 10/100 + 1374 0008 Cardbus Ethernet Card 10/100 + 1385 2100 FA510 + 1395 0001 10/100 Ethernet CardBus PC Card + 13d1 ab01 EtherFast 10/100 Cardbus (PCMPC200) + 1498 000a TPMC880-10 10/100Base-T and 10Base2 PMC Ethernet Adapter + 1498 000b TPMC880-11 Single 10/100Base-T PMC Ethernet Adapter + 1498 000c TPMC880-12 Single 10Base2 PMC Ethernet Adapter + 14cb 0100 LNDL-100N 100Base-TX Ethernet PC Card + 1668 2000 FastNet Pro (PE2000) + 2646 0001 KNE100TX + 2646 0002 KNE-CB4TX + 8086 0001 EtherExpress PRO/100 Mobile CardBus 32 + 001a Farallon PN9000SX Gigabit Ethernet + 0021 DECchip 21052 + 0022 DECchip 21150 + 0023 DECchip 21150 + 0024 DECchip 21152 + 0025 DECchip 21153 + 0026 DECchip 21154 + 0034 56k Modem Cardbus + 1374 0003 56k Modem Cardbus + 0045 DECchip 21553 + 0046 DECchip 21554 + 0e11 4050 Smart Array 4200 Controller + 0e11 4051 Smart Array 4250ES Controller + 0e11 4058 Smart Array 431 Controller + 103c 10c2 NetRAID-4M + 12d9 000a IP Telephony card + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard + 9005 0364 5400S (Mustang) + 9005 0365 5400S (Mustang) + 9005 1364 Dell PowerEdge RAID Controller 2 + 9005 1365 Dell PowerEdge RAID Controller 2 + e4bf 1000 CC8-1-BLUES + 1065 StrongARM DC21285 + 1069 0020 DAC960P / DAC1164P +1012 Micronics Computers Inc +1013 Cirrus Logic + 0038 GD 7548 + 0040 GD 7555 Flat Panel GUI Accelerator + 004c GD 7556 Video/Graphics LCD/CRT Ctrlr + 00a0 GD 5430/40 [Alpine] + 00a2 GD 5432 [Alpine] + 00a4 GD 5434-4 [Alpine] + 00a8 GD 5434-8 [Alpine] + 00ac GD 5436 [Alpine] + 00b0 GD 5440 + 00b8 GD 5446 + 1af4 1100 QEMU Virtual Machine + 00bc GD 5480 + 1013 00bc CL-GD5480 + 00d0 GD 5462 + 00d2 GD 5462 [Laguna I] + 00d4 GD 5464 [Laguna] + 00d5 GD 5464 BD [Laguna] + 00d6 GD 5465 [Laguna] + 13ce 8031 Barco Metheus 2 Megapixel, Dual Head + 13cf 8031 Barco Metheus 2 Megapixel, Dual Head + 00e8 GD 5436U + 1100 CL 6729 + 1110 PD 6832 PCMCIA/CardBus Ctrlr + 1112 PD 6834 PCMCIA/CardBus Ctrlr + 1113 PD 6833 PCMCIA/CardBus Ctrlr + 1200 GD 7542 [Nordic] + 1202 GD 7543 [Viking] + 1204 GD 7541 [Nordic Light] + 4000 MD 5620 [CLM Data Fax Voice] + 4400 CD 4400 + 6001 CS 4610/11 [CrystalClear SoundFusion Audio Accelerator] + 1014 1010 CS4610 SoundFusion Audio Accelerator + 6003 CS 4614/22/24/30 [CrystalClear SoundFusion Audio Accelerator] + 1013 4280 Crystal SoundFusion PCI Audio Accelerator + 1014 0153 ThinkPad 600X/A20m + 153b 112e DMX XFire 1024 + 153b 1136 SiXPack 5.1+ + 1681 0050 Game Theater XP + 1681 a010 Gamesurround Fortissimo II + 1681 a011 Gamesurround Fortissimo III 7.1 + 5053 3357 Santa Cruz + 6004 CS 4614/22/24 [CrystalClear SoundFusion Audio Accelerator] + 6005 Crystal CS4281 PCI Audio + 1013 4281 Crystal CS4281 PCI Audio + 10cf 10a8 Crystal CS4281 PCI Audio + 10cf 10a9 Crystal CS4281 PCI Audio + 10cf 10aa Crystal CS4281 PCI Audio + 10cf 10ab Crystal CS4281 PCI Audio + 10cf 10ac Crystal CS4281 PCI Audio + 10cf 10ad Crystal CS4281 PCI Audio + 10cf 10b4 Crystal CS4281 PCI Audio + 1179 0001 Crystal CS4281 PCI Audio + 14c0 000c Crystal CS4281 PCI Audio +1014 IBM + 0002 PCI to MCA Bridge + 0005 Processor to I/O Controller [Alta Lite] + 0007 Processor to I/O Controller [Alta MP] + 000a PCI to ISA Bridge (IBM27-82376) [Fire Coral] + 0017 CPU to PCI Bridge + 0018 TR Auto LANstreamer + 001b GXT-150P + 001c Carrera + 001d SCSI-2 FAST PCI Adapter (82G2675) + 0020 GXT1000 Graphics Adapter + 0022 PCI to PCI Bridge (IBM27-82351) + 002d Processor to I/O Controller [Python] + 002e SCSI RAID Adapter [ServeRAID] + 1014 002e ServeRAID-3x + 1014 022e ServeRAID-4H + 0031 2 Port Serial Adapter +# AS400 iSeries PCI sync serial card + 1014 0031 2721 WAN IOA - 2 Port Sync Serial Adapter + 0036 PCI to 32-bit LocalBus Bridge [Miami] + 0037 PowerPC to PCI Bridge (IBM27-82660) + 003a CPU to PCI Bridge + 003c GXT250P/GXT255P Graphics Adapter + 003e 16/4 Token ring UTP/STP controller + 1014 003e Token-Ring Adapter + 1014 00cd Token-Ring Adapter + Wake-On-LAN + 1014 00ce 16/4 Token-Ring Adapter 2 + 1014 00cf 16/4 Token-Ring Adapter Special + 1014 00e4 High-Speed 100/16/4 Token-Ring Adapter + 1014 00e5 16/4 Token-Ring Adapter 2 + Wake-On-LAN + 1014 016d iSeries 2744 Card + 0045 SSA Adapter + 0046 MPIC interrupt controller + 0047 PCI to PCI Bridge + 0048 PCI to PCI Bridge + 0049 Warhead SCSI Controller + 004e ATM Controller (14104e00) + 004f ATM Controller (14104f00) + 0050 ATM Controller (14105000) + 0053 25 MBit ATM Controller + 0054 GXT500P/GXT550P Graphics Adapter + 0057 MPEG PCI Bridge + 0058 SSA Adapter [Advanced SerialRAID/X] + 005e GXT800P Graphics Adapter + 007c ATM Controller (14107c00) + 007d 3780IDSP [MWave] + 008b EADS PCI to PCI Bridge + 008e GXT3000P Graphics Adapter + 0090 GXT 3000P + 1014 008e GXT-3000P + 0091 SSA Adapter + 0095 20H2999 PCI Docking Bridge + 0096 Chukar chipset SCSI controller + 1014 0097 iSeries 2778 DASD IOA + 1014 0098 iSeries 2763 DASD IOA + 1014 0099 iSeries 2748 DASD IOA + 009f PCI 4758 Cryptographic Accelerator + 00a5 ATM Controller (1410a500) + 00a6 ATM 155MBPS MM Controller (1410a600) + 00b7 GXT2000P Graphics Adapter + 1092 00b8 FireGL1 AGP 32Mb + 00b8 GXT2000P Graphics Adapter + 00be ATM 622MBPS Controller (1410be00) + 00dc Advanced Systems Management Adapter (ASMA) + 00fc CPC710 Dual Bridge and Memory Controller (PCI-64) + 0105 CPC710 Dual Bridge and Memory Controller (PCI-32) + 010f Remote Supervisor Adapter (RSA) + 0142 Yotta Video Compositor Input + 1014 0143 Yotta Input Controller (ytin) + 0144 Yotta Video Compositor Output + 1014 0145 Yotta Output Controller (ytout) + 0156 405GP PLB to PCI Bridge + 015e 622Mbps ATM PCI Adapter + 0160 64bit/66MHz PCI ATM 155 MMF + 016e GXT4000P Graphics Adapter + 0170 GXT6000P Graphics Adapter + 1092 0172 Fire GL2 + 1092 0173 Fire GL3 + 1092 0174 Fire GL4 + 1092 0184 Fire GL4s + 017d GXT300P Graphics Adapter + 0180 Snipe chipset SCSI controller + 1014 0241 iSeries 2757 DASD IOA + 1014 0264 Quad Channel PCI-X U320 SCSI RAID Adapter (2780) + 0188 EADS-X PCI-X to PCI-X Bridge + 01a7 PCI-X to PCI-X Bridge + 01bd ServeRAID Controller + 1014 01bd ServeRAID 4Lx + 1014 01be ServeRAID-4M + 1014 01bf ServeRAID-4L + 1014 0208 ServeRAID-4Mx + 1014 020e ServeRAID-4Lx + 1014 022e ServeRAID-4H + 1014 0258 ServeRAID-5i + 1014 0259 ServeRAID-5i + 01c1 64bit/66MHz PCI ATM 155 UTP + 01e6 Cryptographic Accelerator + 01ef PowerPC 440GP PCI Bridge + 1734 102b PCEAS PCI-X Dual Port ESCON Adapter + 1734 10f8 PCEAT PCI-Express Dual Port ESCON Adapter + 01ff 10/100 Mbps Ethernet + 0219 Multiport Serial Adapter + 1014 021a Dual RVX + 1014 0251 Internal Modem/RVX + 1014 0252 Quad Internal Modem + 021b GXT6500P Graphics Adapter + 021c GXT4500P Graphics Adapter + 0233 GXT135P Graphics Adapter + 028c Citrine chipset SCSI controller + 1014 028d Dual Channel PCI-X DDR SAS RAID Adapter (572E) + 1014 02be Dual Channel PCI-X DDR U320 SCSI RAID Adapter (571B) + 1014 02c0 Dual Channel PCI-X DDR U320 SCSI Adapter (571A) + 1014 030d PCI-X DDR Auxiliary Cache Adapter (575B) + 02a1 Calgary PCI-X Host Bridge + 02bd Obsidian chipset SCSI controller + 1014 02c1 PCI-X DDR 3Gb SAS Adapter (572A/572C) + 1014 02c2 PCI-X DDR 3Gb SAS RAID Adapter (572B/571D) + 1014 0338 PCI-X DDR Auxiliary Cache Adapter (575C) + 0302 Winnipeg PCI-X Host Bridge + 0308 CalIOC2 PCI-E Root Port + 0311 FC 5740/1954 4-Port 10/100/1000 Base-TX PCI-X Adapter for POWER + 0314 ZISC 036 Neural accelerator card + 032d Axon - Cell Companion Chip + 1014 03a1 PCIe PowerXCell 8i Cell Accelerator Board + 0339 Obsidian-E PCI-E SCSI controller + 1014 030a PCIe 3Gb SAS RAID Adapter (574E) + 1014 033a PCIe 3Gb SAS Adapter (57B3) + 1014 035c PCIe x8 Internal 3Gb SAS adapter (57CC) + 1014 0360 PCI-E Auxiliary Cache Adapter (57B7) + 033d PCI-E IPR SAS Adapter (FPGA) + 1014 033c PCIe2 1.8GB Cache 6Gb SAS RAID Adapter Tri-port (57B5) + 1014 0353 PCIe2 3.1GB Cache 6Gb SAS RAID Enclosure (57C3) + 1014 0354 PCIe2 6Gb SAS Adapter Dual-port (57C4) + 1014 0356 PCIe2 1.8GB Cache 6Gb SAS RAID & SSD Adapter (574D) + 1014 035f PCIe2 6Gb SAS Adapter Quad-port (57B2) + 034a PCI-E IPR SAS Adapter (ASIC) + 1014 033b PCIe2 6Gb SAS RAID Adapter Quad-port (57B4) + 1014 0355 PCIe2 3.6GB Cache 6Gb SAS RAID Adapter Quad-port (57B1) + 1014 0357 PCIe2 6Gb SAS Adapter Quad-port (57C6) + 1014 035d PCIe3 1.8GB Cache RAID SAS Adapter Quad-port 6GB (57C8) + 1014 035e PCIe2 3.6GB Cache 6Gb SAS RAID Adapter Quad-port (57CE) + 1014 03fb PCIe3 28GB Cache RAID SAS Enclosure 6Gb x 16 (57D5) + 1014 03fe PCIe3 x8 Cache SAS RAID Internal Adapter 6Gb (57D8) + 1014 03ff PCIe3 x8 SAS RAID Internal Adapter 6Gb (57D7) + 1014 0474 PCIe3 x16 Cache SAS RAID Internal Adapter 6Gb (57EB) + 1014 0475 PCIe3 x16 SAS RAID Internal Adapter 6Gb (57EC) + 1014 0499 PCIe3 x16 Cache SAS RAID Internal Adapter 6Gb (57ED) + 1014 049a PCIe3 x16 SAS RAID Internal Adapter 6Gb (57EE) + 1014 04c7 PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCA) + 1014 04c8 PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CD2) + 1014 04c9 PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCD) + 03dc POWER8 Host Bridge (PHB3) + 044b GenWQE Accelerator Adapter + 04aa Flash Adapter 90 (PCIe2 0.9TB) + 04c1 POWER9 Host Bridge (PHB4) + 04da PCI-E IPR SAS+ Adapter (ASIC) + 1014 04fb PCIe3 x16 20GB Cache 12Gb Quad SAS RAID+ Adapter(580B) + 1014 04fc PCIe3 x8 12Gb Quad SAS RAID+ Adapter(580A) + 04ed Internal Shared Memory (ISM) virtual PCI device + 3022 QLA3022 Network Adapter + 4022 QLA3022 Network Adapter + ffff MPIC-2 interrupt controller +1015 LSI Logic Corp of Canada +1016 ICL Personal Systems +1017 SPEA Software AG + 5343 SPEA 3D Accelerator +1018 Unisys Systems +1019 Elitegroup Computer Systems +101a AT&T GIS (NCR) + 0005 100VG ethernet + 0007 BYNET BIC4G/2C/2G + 101a 0019 BYNET BIC2C + 101a 001c BYNET BIC2G + 101a 001f BYNET BIC4G + 0009 PQS Memory Controller + 000a BYNET BPCI Adapter + 000b BYNET 4 Port BYA Switch (BYA4P) + 000c BYNET 4 Port BYA Switch (BYA4G) + 0010 NCR AMC Memory Controller + 1dc1 BYNET BIC2M/BIC4M/BYA4M + 101a 0019 BIC2M + 101a 001f BIC4M + 101a 0ece BYA4M + 1fa8 BYNET Multi-port BIC Adapter (XBIC Based) + 101a 00c3 BYNET BIC2SE +101b Vitesse Semiconductor +# Maxim VSC452 Super BMC Controller with Video + 0452 VSC452 [SuperBMC] +101c Western Digital + 0193 33C193A + 0196 33C196A + 0197 33C197A + 0296 33C296A + 3193 7193 + 3197 7197 + 3296 33C296A + 4296 34C296 + 9710 Pipeline 9710 + 9712 Pipeline 9712 + c24a 90C +# ID for Newly Acquired Storage Products from Vitesse +101d Maxim Integrated Products +101e American Megatrends Inc. + 0009 MegaRAID 428 Ultra RAID Controller (rev 03) + 1960 MegaRAID + 101e 0471 MegaRAID 471 Enterprise 1600 RAID Controller + 101e 0475 MegaRAID 475 Express 500/500LC RAID Controller + 101e 0477 MegaRAID 477 Elite 3100 RAID Controller + 101e 0493 MegaRAID 493 Elite 1600 RAID Controller + 101e 0494 MegaRAID 494 Elite 1650 RAID Controller + 101e 0503 MegaRAID 503 Enterprise 1650 RAID Controller + 101e 0511 MegaRAID 511 i4 IDE RAID Controller + 101e 0522 MegaRAID 522 i4133 RAID Controller + 1028 0471 PowerEdge RAID Controller 3/QC + 1028 0475 PowerEdge RAID Controller 3/SC + 1028 0493 PowerEdge RAID Controller 3/DC + 1028 0511 PowerEdge Cost Effective RAID Controller ATA100/4Ch + 103c 60e7 NetRAID-1M + 103c 60e8 NetRaid 2M [AMI MegaRaid 493] + 9010 MegaRAID 428 Ultra RAID Controller + 9030 EIDE Controller + 9031 EIDE Controller + 9032 EIDE & SCSI Controller + 9033 SCSI Controller + 9040 Multimedia card + 9060 MegaRAID 434 Ultra GT RAID Controller + 9063 MegaRAC + 101e 0767 Dell Remote Assistant Card 2 +101f PictureTel +1020 Hitachi Computer Products +1021 OKI Electric Industry Co. Ltd. +1022 Advanced Micro Devices, Inc. [AMD] + 1100 K8 [Athlon64/Opteron] HyperTransport Technology Configuration + 1101 K8 [Athlon64/Opteron] Address Map + 1102 K8 [Athlon64/Opteron] DRAM Controller + 1103 K8 [Athlon64/Opteron] Miscellaneous Control + 1200 Family 10h Processor HyperTransport Configuration + 1201 Family 10h Processor Address Map + 1202 Family 10h Processor DRAM Controller + 1203 Family 10h Processor Miscellaneous Control + 1204 Family 10h Processor Link Control + 1300 Family 11h Processor HyperTransport Configuration + 1301 Family 11h Processor Address Map + 1302 Family 11h Processor DRAM Controller + 1303 Family 11h Processor Miscellaneous Control + 1304 Family 11h Processor Link Control + 1305 Griffin Function 5 + 1306 Griffin Function 6 + 1307 Griffin Function 7 + 1308 Kaveri Audio Controller + 1314 Wrestler/Bheem/Ontario/Krishna Audio Controller + 13e0 Ariel Root Complex + 13e1 Ariel IOMMU + 13e2 Ariel PCIe Dummy Host Bridge + 13e3 Ariel PCIe GPP Bridge + 13e4 Ariel PCIe Dummy Host Bridge + 13e5 Ariel Internal PCIe GPP Bridge 0 to Bus A + 13e6 Ariel Internal PCIe GPP Bridge 0 to Bus B + 13e7 Ariel SMBus Controller + 13e8 Ariel LPC Bridge + 13e9 Ariel Internal GPU + 13ea Ariel HD Audio Controller + 13eb Ariel HD Audio Coprocessor + 13ec Ariel Cryptographic Coprocessor + 13ed Ariel USB 3.1 Type C: Gen2 x 1port + DP Alt Mode + 13ee Ariel USB 3.1 Type A: Gen2 x 2 ports + 13ef Ariel ZCN/MP4 + 13f0 Ariel Device 24: Function 0 + 13f1 Ariel Device 24: Function 1 + 13f2 Ariel Device 24: Function 2 + 13f3 Ariel Device 24: Function 3 + 13f4 Ariel Device 24: Function 4 + 13f5 Ariel Device 24: Function 5 + 13f6 Ariel Device 24: Function 6 + 13f7 Ariel Device 24: Function 7 + 1400 Family 15h (Models 10h-1fh) Processor Function 0 + 1401 Family 15h (Models 10h-1fh) Processor Function 1 + 1402 Family 15h (Models 10h-1fh) Processor Function 2 + 1403 Family 15h (Models 10h-1fh) Processor Function 3 + 1404 Family 15h (Models 10h-1fh) Processor Function 4 + 1405 Family 15h (Models 10h-1fh) Processor Function 5 + 1410 Family 15h (Models 10h-1fh) Processor Root Complex + 103c 1985 Pavilion 17-e163sg Notebook PC + 1412 Family 15h (Models 10h-1fh) Processor Root Port + 1022 1234 Trinity A-series APU + 1413 Family 15h (Models 10h-1fh) Processor Root Port + 1414 Family 15h (Models 10h-1fh) Processor Root Port + 1022 1234 Trinity A-series APU + 1415 Family 15h (Models 10h-1fh) Processor Root Port + 1416 Family 15h (Models 10h-1fh) Processor Root Port + 1417 Family 15h (Models 10h-1fh) Processor Root Port + 1418 Family 15h (Models 10h-1fh) Processor Root Port + 1419 Family 15h (Models 10h-1fh) I/O Memory Management Unit + 141a Family 15h (Models 30h-3fh) Processor Function 0 + 141b Family 15h (Models 30h-3fh) Processor Function 1 + 141c Family 15h (Models 30h-3fh) Processor Function 2 + 141d Family 15h (Models 30h-3fh) Processor Function 3 + 141e Family 15h (Models 30h-3fh) Processor Function 4 + 141f Family 15h (Models 30h-3fh) Processor Function 5 + 1422 Family 15h (Models 30h-3fh) Processor Root Complex + 1423 Family 15h (Models 30h-3fh) I/O Memory Management Unit + 1424 Family 15h (Models 30h-3fh) Processor Root Port + 1425 Kaveri P2P Bridge for GFX PCIe Port [1:0] + 1426 Family 15h (Models 30h-3fh) Processor Root Port + 142e Liverpool Processor HT configuration + 142f Liverpool Processor Address Maps + 1430 Liverpool Processor DRAM configuration + 1431 Liverpool Processor Misc configuration + 1432 Liverpool Processor PM configuration + 1433 Liverpool Processor NB Performance Monitor + 1434 Liverpool Processor SPLL Configuration + 1436 Liverpool Processor Root Complex + 1437 Liverpool I/O Memory Management Unit + 1438 Liverpool UMI PCIe Dummy Host Bridge + 1439 Family 16h Processor Functions 5:1 + 143a Kingston/Clayton/Gladius/Montego Root Complex + 143b Kingston/Clayton/Gladius/Montego P2P Bridge for UMI Link + 1440 Matisse Device 24: Function 0 + 1441 Matisse Device 24: Function 1 + 1442 Matisse Device 24: Function 2 + 1443 Matisse Device 24: Function 3 + 1444 Matisse Device 24: Function 4 + 1445 Matisse Device 24: Function 5 + 1446 Matisse Device 24: Function 6 + 1447 Matisse Device 24: Function 7 + 1448 Renoir Device 24: Function 0 + 1449 Renoir Device 24: Function 1 + 144a Renoir Device 24: Function 2 + 144b Renoir Device 24: Function 3 + 144c Renoir Device 24: Function 4 + 144d Renoir Device 24: Function 5 + 144e Renoir Device 24: Function 6 + 144f Renoir Device 24: Function 7 + 1450 Family 17h (Models 00h-0fh) Root Complex + 1451 Family 17h (Models 00h-0fh) I/O Memory Management Unit + 1452 Family 17h (Models 00h-1fh) PCIe Dummy Host Bridge + 1453 Family 17h (Models 00h-0fh) PCIe GPP Bridge + 1454 Family 17h (Models 00h-0fh) Internal PCIe GPP Bridge 0 to Bus B + 1455 Zeppelin/Renoir PCIe Dummy Function + 1456 Family 17h (Models 00h-0fh) Platform Security Processor + 1457 Family 17h (Models 00h-0fh) HD Audio Controller + 145a Zeppelin/Raven/Raven2 PCIe Dummy Function + 145b Zeppelin Non-Transparent Bridge + 145c Family 17h (Models 00h-0fh) USB 3.0 Host Controller + 145d Zeppelin Switch Upstream (PCIE SW.US) + 145e Zeppelin Switch Downstream (PCIE SW.DS) + 145f Zeppelin USB 3.0 Host controller + 1460 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 0 + 1461 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 1 + 1462 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 2 + 1463 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 3 + 1464 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 4 + 1465 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 5 + 1466 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 6 + 1467 Family 17h (Models 00h-0fh) Data Fabric: Device 18h; Function 7 + 1468 Zeppelin Cryptographic Coprocessor NTBCCP + 1480 Starship/Matisse Root Complex + 1462 7c37 X570-A PRO motherboard + 1481 Starship/Matisse IOMMU + 1482 Starship/Matisse PCIe Dummy Host Bridge + 1483 Starship/Matisse GPP Bridge + 1484 Starship/Matisse Internal PCIe GPP Bridge 0 to bus[E:B] + 1485 Starship/Matisse Reserved SPP + 1486 Starship/Matisse Cryptographic Coprocessor PSPCPP + 1487 Starship/Matisse HD Audio Controller + 1462 9c37 X570-A PRO motherboard + 1488 Starship Reserved SSP + 1489 Starship Reserved SSP + 148a Starship/Matisse PCIe Dummy Function + 148b Starship/Matisse Non-Transparent Bridge + 148c Starship USB 3.0 Host Controller + 148d Starship/Matisse Switch Upstream (PCIE SW.US) + 148e Starship/Matisse Switch Downstream (PCIE SW.DS) + 148f Starship Reserved SSP + 1490 Starship Device 24; Function 0 + 1491 Starship Device 24; Function 1 + 1492 Starship Device 24; Function 2 + 1493 Starship Device 24; Function 3 + 1494 Starship Device 24; Function 4 + 1495 Starship Device 24; Function 5 + 1496 Starship Device 24; Function 6 + 1497 Starship Device 24; Function 7 + 1498 Starship/Matisse PTDMA + 1499 Starship/Matisse NVMe + 149a Starship PCIe GPP Bridge [1:0] + 149b Starship Reserved SSP + 149c Matisse USB 3.0 Host Controller + 1462 7c37 X570-A PRO motherboard + 1510 Family 14h Processor Root Complex + 174b 1001 PURE Fusion Mini + 1512 Family 14h Processor Root Port + 1513 Family 14h Processor Root Port + 1514 Family 14h Processor Root Port + 1515 Family 14h Processor Root Port + 1516 Family 14h Processor Root Port + 1530 Family 16h Processor Function 0 + 1531 Family 16h Processor Function 1 + 1532 Family 16h Processor Function 2 + 1533 Family 16h Processor Function 3 + 1534 Family 16h Processor Function 4 + 1535 Family 16h Processor Function 5 + 1536 Family 16h Processor Root Complex + 1849 1536 QC5000-ITX/PH + 1537 Kabini/Mullins PSP-Platform Security Processor + 1538 Family 16h Processor Function 0 + 1539 Kabini P2P Bridge for PCIe Ports[4:0] + 1540 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky HT Configuration + 1541 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Address Maps + 1542 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky DRAM Configuration + 1543 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Miscellaneous Configuration + 1544 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky PM Configuration + 1545 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky NB Performance Monitor + 1546 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Root Complex + 1547 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky IOMMU + 1548 Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky UMI PCIe Dummy Host Bridge + 1549 Kryptos/Cato/Garfield/Garfield+ P2P Bridge for PCIe Port [3:0] + 154a Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Audio Processor + 154b Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky Security Processor + 154d Kryptos/Cato/Garfield/Garfield+/Arlene/Pooky/Anubis HDMI Controller + 154f Anubis Audio Processor + 1550 Garfield+/Arlene/Pooky/Anubis SPLL Configuration + 1553 Arlene/Pooky P2P Bridge for PCIE (3:0) + 155b Anubis Root Complex + 155c Anubis IOMMU + 155d Anubis UMI PCIe Dummy Bridge + 155e Anubis P2P Bridge for PCIe Ports [4:0] + 1560 Anubis Security Processor + 1566 Family 16h (Models 30h-3fh) Processor Root Complex + 1567 Mullins IOMMU + 156b Family 16h (Models 30h-3fh) Host Bridge + 1570 Family 15h (Models 60h-6fh) Processor Function 0 + 1571 Family 15h (Models 60h-6fh) Processor Function 1 + 1572 Family 15h (Models 60h-6fh) Processor Function 2 + 1573 Family 15h (Models 60h-6fh) Processor Function 3 + 1574 Family 15h (Models 60h-6fh) Processor Function 4 + 1575 Family 15h (Models 60h-6fh) Processor Function 5 + 1576 Family 15h (Models 60h-6fh) Processor Root Complex + 1577 Family 15h (Models 60h-6fh) I/O Memory Management Unit + 1578 Carrizo Platform Security Processor + 1579 Carrizo Audio Processor + 157a Family 15h (Models 60h-6fh) Audio Controller + 157b Family 15h (Models 60h-6fh) Host Bridge + 157c Family 15h (Models 60h-6fh) Processor Root Port + 157d Carrizo Audio Dummy Host Bridge + 157e Carrizo Audio Controller + 1580 Family 16h (Models 30h-3fh) Processor Function 0 + 1581 Family 16h (Models 30h-3fh) Processor Function 1 + 1582 Family 16h (Models 30h-3fh) Processor Function 2 + 1583 Family 16h (Models 30h-3fh) Processor Function 3 + 1584 Family 16h (Models 30h-3fh) Processor Function 4 + 1585 Family 16h (Models 30h-3fh) Processor Function 5 + 1590 Amur/Nolan HT Configuration + 1591 Amur/Nolan Address Maps + 1592 Amur/Nolan DRAM Configuration + 1593 Amur/Nolan Miscellaneous Configuration + 1594 Amur/Nolan PM Configuration + 1595 Amur/Nolan NB Performance Monitor + 1596 Amur/Nolan Root Complex + 1597 Amur/Nolan IOMMU + 1598 Amur/Nolan Platform Security Processor + 1599 Amur/Nolan PCIe Dummy Host Bridge + 159d Amur Function 6: Gasket + 15b0 Stoney HT Configuration + 15b1 Stoney Address Maps + 15b2 Stoney DRAM Configuration + 15b3 Stoney Miscellaneous Configuration + 15b4 Stoney PM Configuration + 15b5 Stoney NB Performance Monitor + 15bc Stoney PCIe [GFX,GPP] Bridge [4:0] + 15be Stoney Audio Processor + 15d0 Raven/Raven2 Root Complex + 103c 8615 Pavilion Laptop 15-cw1xxx + 15d1 Raven/Raven2 IOMMU + 103c 8615 Pavilion Laptop 15-cw1xxx + 15d2 Raven/Raven2 PCIe Dummy Host Bridge + 15d3 Raven/Raven2 PCIe GPP Bridge [6:0] + 15d4 FireFlight USB 3.1 + 15d5 FireFlight USB 3.1 + 15da Raven/Raven2 PCIe Dummy Host Bridge + 15db Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus A + 15dc Raven/Raven2 Internal PCIe GPP Bridge 0 to Bus B + 15de Raven/Raven2/FireFlight HD Audio Controller + 15df Family 17h (Models 10h-1fh) Platform Security Processor + 15e0 Raven USB 3.1 + 103c 8615 Pavilion Laptop 15-cw1xxx + 15e1 Raven USB 3.1 + 103c 8615 Pavilion Laptop 15-cw1xxx + 15e2 Raven/Raven2/FireFlight/Renoir Audio Processor + 15e3 Family 17h (Models 10h-1fh) HD Audio Controller + 103c 8615 Pavilion Laptop 15-cw1xxx + 15e4 Raven/Raven2/Renoir Sensor Fusion Hub + 15e5 Raven2 USB 3.1 + 15e6 Raven/Raven2/Renoir Non-Sensor Fusion Hub KMDF driver + 1022 15e4 Raven/Raven2/Renoir Sensor Fusion Hub + 15e8 Raven/Raven2 Device 24: Function 0 + 15e9 Raven/Raven2 Device 24: Function 1 + 15ea Raven/Raven2 Device 24: Function 2 + 15eb Raven/Raven2 Device 24: Function 3 + 15ec Raven/Raven2 Device 24: Function 4 + 15ed Raven/Raven2 Device 24: Function 5 + 15ee Raven/Raven2 Device 24: Function 6 + 15ef Raven/Raven2 Device 24: Function 7 + 15f0 FireFlight Device 24: Function 0 + 15f1 FireFlight Device 24: Function 1 + 15f2 FireFlight Device 24: Function 2 + 15f3 FireFlight Device 24: Function 3 + 15f4 FireFlight Device 24: Function 4 + 15f5 FireFlight Device 24: Function 5 + 15f6 FireFlight Device 24: Function 6 + 15f7 FireFlight Device 24: Function 7 + 15f8 FireFlight Root Complex + 15f9 FireFlight IOMMU + 15fa FireFlight PCIe Dummy Host Bridge + 15fb FireFlight PCIe GPP Bride 3:0 + 15fc FireFlight PCIe Dummy Host Bridge + 15fd FireFlight Internal PCIe GPP Bridge 0 to Bus A + 15fe FireFlight Internal PCIe GPP Bridge 0 to Bus B + 15ff FireFlight Bus A; Device 0: Function 0: Internal GPU + 1600 Family 15h Processor Function 0 + 1601 Family 15h Processor Function 1 + 1602 Family 15h Processor Function 2 + 1603 Family 15h Processor Function 3 + 1604 Family 15h Processor Function 4 + 1605 Family 15h Processor Function 5 + 1606 Arden Security Processor + 1608 Arden Device 18h: Function 0 + 1609 Arden Device 18h: Function 1 + 160a Arden Device 18h: Function 2 + 160b Arden Device 18h: Function 3 + 160c Arden Device 18h: Function 4 + 160d Arden Device 18h: Function 5 + 160e Arden Device 18h: Function 6 + 160f Arden Device 18h: Function 7 + 1620 Anubis HT Configuration + 1621 Anubis Address Maps + 1622 Anubis DRAM Configuration + 1623 Anubis Miscellaneous Configuration + 1624 Anubis PM Configuration + 1625 Anubis NB Performance Monitor + 1626 Arden Root Complex + 1627 Arden IOMMU + 1628 Arden PCIe Dummy Host Bridge + 1629 Arden PCIe GPP Bridge + 162a Arden Internal PCIe GPP Bridge 0 to bus X + 162b Arden PCIe Non-Transparent Bridge + 1630 Renoir Root Complex + 1631 Renoir IOMMU + 1632 Renoir PCIe Dummy Host Bridge + 1633 Renoir PCIe GPP Bridge + 1634 Renoir PCIe GPP Bridge + 1635 Renoir Internal PCIe GPP Bridge to Bus + 1637 Renoir HD Audio Controller + 1639 Renoir USB 3.1 + 1641 Renoir 10GbE Controller Port 0 (XGBE0/1) + 1642 Renoir WLAN + 1643 Renoir BT + 1644 Renoir I2S + 1700 Family 12h/14h Processor Function 0 + 1701 Family 12h/14h Processor Function 1 + 1702 Family 12h/14h Processor Function 2 + 1703 Family 12h/14h Processor Function 3 + 1704 Family 12h/14h Processor Function 4 + 1705 Family 12h Processor Root Complex + 1706 Llano P2P Bridge to external GPU + 1707 Family 12h Processor Root Port + 1708 Family 12h Processor Root Port + 1709 Family 12h Processor Root Port + 170a Family 12h Processor Root Port + 170b Family 12h Processor Root Port + 170c Family 12h Processor Root Port + 170d Family 12h Processor Root Port + 1716 Family 12h/14h Processor Function 5 + 1718 Family 12h/14h Processor Function 6 + 1719 Family 12h/14h Processor Function 7 + 2000 79c970 [PCnet32 LANCE] + 1014 2000 NetFinity 10/100 Fast Ethernet + 1022 2000 PCnet - Fast 79C971 + 103c 104c Ethernet with LAN remote power Adapter + 103c 1064 Ethernet with LAN remote power Adapter + 103c 1065 Ethernet with LAN remote power Adapter + 103c 106c Ethernet with LAN remote power Adapter + 103c 106e Ethernet with LAN remote power Adapter + 103c 10ea Ethernet with LAN remote power Adapter + 1113 1220 EN1220 10/100 Fast Ethernet + 1259 2450 AT-2450 10/100 Fast Ethernet + 1259 2454 AT-2450v4 10Mb Ethernet Adapter + 1259 2700 AT-2700TX 10/100 Fast Ethernet + 1259 2701 AT-2700FX 100Mb Ethernet + 1259 2702 AT-2700FTX 10/100 Mb Fiber/Copper Fast Ethernet + 1259 2703 AT-2701FX + 1259 2704 AT-2701FTX 10/100 Mb Fiber/Copper Fast Ethernet + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1010 CP5/CR6 mainboard + 4c53 1020 VR6 mainboard + 4c53 1030 PC5 mainboard + 4c53 1040 CL7 mainboard + 4c53 1060 PC7 mainboard + 2001 79c978 [HomePNA] + 1092 0a78 Multimedia Home Network Adapter + 1668 0299 ActionLink Home Network Adapter + 2003 Am 1771 MBW [Alchemy] + 2020 53c974 [PCscsi] + 1af4 1100 QEMU Virtual Machine + 2040 79c974 + 2080 CS5536 [Geode companion] Host Bridge + 2081 Geode LX Video + 2082 Geode LX AES Security Block + 208f CS5536 GeodeLink PCI South Bridge + 2090 CS5536 [Geode companion] ISA + 2091 CS5536 [Geode companion] FLASH + 2093 CS5536 [Geode companion] Audio + 2094 CS5536 [Geode companion] OHC + 2095 CS5536 [Geode companion] EHC + 2096 CS5536 [Geode companion] UDC + 2097 CS5536 [Geode companion] UOC + 209a CS5536 [Geode companion] IDE + 3000 ELanSC520 Microcontroller + 43a0 Hudson PCI to PCI bridge (PCIE port 0) + 43a1 Hudson PCI to PCI bridge (PCIE port 1) + 43a2 Hudson PCI to PCI bridge (PCIE port 2) + 43a3 Hudson PCI to PCI bridge (PCIE port 3) + 43b0 X370 Series Chipset PCIe Upstream Port + 1849 43c6 Fatal1ty X370 Professional Gaming + 43b1 X399 Series Chipset PCIe Bridge + 43b4 300 Series Chipset PCIe Port + 43b5 X370 Series Chipset SATA Controller + 1849 43c8 Fatal1ty X370 Professional Gaming + 43b6 X399 Series Chipset SATA Controller + 43b7 300 Series Chipset SATA Controller + 43b9 X370 Series Chipset USB 3.1 xHCI Controller + 1849 43d0 Fatal1ty X370 Professional Gaming + 43ba X399 Series Chipset USB 3.1 xHCI Controller + 43bb 300 Series Chipset USB 3.1 xHCI Controller + 43c6 400 Series Chipset PCIe Bridge + 43c7 400 Series Chipset PCIe Port + 43c8 400 Series Chipset SATA Controller + 43d5 400 Series Chipset USB 3.1 XHCI Controller + 57a3 Matisse PCIe GPP Bridge + 57a4 Matisse PCIe GPP Bridge + 57ad Matisse Switch Upstream + 7006 AMD-751 [Irongate] System Controller + 7007 AMD-751 [Irongate] AGP Bridge + 700a AMD-IGR4 AGP Host to PCI Bridge + 700b AMD-IGR4 PCI to PCI Bridge + 700c AMD-760 MP [IGD4-2P] System Controller + 700d AMD-760 MP [IGD4-2P] AGP Bridge + 700e AMD-760 [IGD4-1P] System Controller + 700f AMD-760 [IGD4-1P] AGP Bridge + 7400 AMD-755 [Cobra] ISA + 7401 AMD-755 [Cobra] IDE + 7403 AMD-755 [Cobra] ACPI + 7404 AMD-755 [Cobra] USB + 7408 AMD-756 [Viper] ISA + 7409 AMD-756 [Viper] IDE + 740b AMD-756 [Viper] ACPI + 740c AMD-756 [Viper] USB + 7410 AMD-766 [ViperPlus] ISA + 7411 AMD-766 [ViperPlus] IDE + 7413 AMD-766 [ViperPlus] ACPI + 7414 AMD-766 [ViperPlus] USB + 7440 AMD-768 [Opus] ISA + 1043 8044 A7M-D Mainboard + 7441 AMD-768 [Opus] IDE + 7443 AMD-768 [Opus] ACPI + 1043 8044 A7M-D Mainboard + 7445 AMD-768 [Opus] Audio + 7446 AMD-768 [Opus] MC97 Modem + 7448 AMD-768 [Opus] PCI + 7449 AMD-768 [Opus] USB + 7450 AMD-8131 PCI-X Bridge + 7451 AMD-8131 PCI-X IOAPIC + 7454 AMD-8151 System Controller + 7455 AMD-8151 AGP Bridge + 7458 AMD-8132 PCI-X Bridge + 7459 AMD-8132 PCI-X IOAPIC + 7460 AMD-8111 PCI + 161f 3017 HDAMB + 7461 AMD-8111 USB + 7462 AMD-8111 Ethernet + 7463 AMD-8111 USB EHCI + 7464 AMD-8111 USB OHCI + 161f 3017 HDAMB + 7468 AMD-8111 LPC + 161f 3017 HDAMB + 7469 AMD-8111 IDE + 1022 2b80 AMD-8111 IDE [Quartet] + 161f 3017 HDAMB + 746a AMD-8111 SMBus 2.0 + 746b AMD-8111 ACPI + 161f 3017 HDAMB + 746d AMD-8111 AC97 Audio + 161f 3017 HDAMB + 746e AMD-8111 MC97 Modem + 756b AMD-8111 ACPI + 7800 FCH SATA Controller [IDE mode] + 7801 FCH SATA Controller [AHCI mode] + 103c 168b ProBook 4535s Notebook + 103c 194e ProBook 455 G1 Notebook + 1849 7801 QC5000-ITX/PH + 7802 FCH SATA Controller [RAID mode] + 7803 FCH SATA Controller [RAID mode] + 7804 FCH SATA Controller [AHCI mode] + 103c 1985 Pavilion 17-e163sg Notebook PC + 7805 FCH SATA Controller [RAID mode] + 7806 FCH SD Flash Controller + 7807 FCH USB OHCI Controller + 103c 194e ProBook 455 G1 Notebook + 103c 1985 Pavilion 17-e163sg Notebook PC + 1849 7807 QC5000-ITX/PH + 7808 FCH USB EHCI Controller + 103c 194e ProBook 455 G1 Notebook + 103c 1985 Pavilion 17-e163sg Notebook PC + 1849 7808 QC5000-ITX/PH + 7809 FCH USB OHCI Controller + 103c 194e ProBook 455 G1 Notebook + 780a Kabini/Mullins SATA Raid/AHCI Mode (DotHill driver) + 780b FCH SMBus Controller + 103c 194e ProBook 455 G1 Notebook + 103c 1985 Pavilion 17-e163sg Notebook PC + 1849 780b QC5000-ITX/PH + 780c FCH IDE Controller + 780d FCH Azalia Controller + 103c 194e ProBook 455 G1 Notebook + 103c 1985 Pavilion 17-e163sg Notebook PC + 1043 8444 F2A85-M Series + 1849 8892 QC5000-ITX/PH + 780e FCH LPC Bridge + 103c 194e ProBook 455 G1 Notebook + 103c 1985 Pavilion 17-e163sg Notebook PC + 1849 780e QC5000-ITX/PH + 780f FCH PCI Bridge + 7812 FCH USB XHCI Controller + 7813 FCH SD Flash Controller + 7814 FCH USB XHCI Controller + 103c 194e ProBook 455 G1 Notebook + 103c 1985 Pavilion 17-e163sg Notebook PC + 1849 7814 QC5000-ITX/PH + 7900 FCH SATA Controller [IDE mode] + 7901 FCH SATA Controller [AHCI mode] + 103c 8615 Pavilion Laptop 15-cw1xxx + 1462 7c37 X570-A PRO motherboard + 7902 FCH SATA Controller [RAID mode] + 7903 FCH SATA Controller [RAID mode] + 7904 FCH SATA Controller [AHCI mode] + 7906 FCH SD Flash Controller + 7908 FCH USB EHCI Controller + 790b FCH SMBus Controller + 103c 8615 Pavilion Laptop 15-cw1xxx + 1462 7c37 X570-A PRO motherboard + 790e FCH LPC Bridge + 103c 8615 Pavilion Laptop 15-cw1xxx + 1462 7c37 X570-A PRO motherboard + 790f FCH PCI Bridge + 7914 FCH USB XHCI Controller + 9600 RS780 Host Bridge + 1043 82ee M378A-CM Motherboard + 1043 82f1 M3A78-EH Motherboard + 9601 RS880 Host Bridge + 1019 2120 A785GM-M + 103c 1609 ProLiant MicroServer N36L + 1043 83a2 M4A785-M Mainboard + 1043 843e M5A88-V EVO + 9602 RS780/RS880 PCI to PCI bridge (int gfx) + 9603 RS780 PCI to PCI bridge (ext gfx port 0) + 103c 1609 ProLiant MicroServer N36L + 9604 RS780/RS880 PCI to PCI bridge (PCIE port 0) + 9605 RS780/RS880 PCI to PCI bridge (PCIE port 1) + 9606 RS780 PCI to PCI bridge (PCIE port 2) + 103c 1609 ProLiant MicroServer N36L + 9607 RS780/RS880 PCI to PCI bridge (PCIE port 3) + 9608 RS780/RS880 PCI to PCI bridge (PCIE port 4) + 9609 RS780/RS880 PCI to PCI bridge (PCIE port 5) + 960a RS780 PCI to PCI bridge (NB-SB link) + 960b RS780 PCI to PCI bridge (ext gfx port 1) +1023 Trident Microsystems + 0194 82C194 + 2000 4DWave DX + 2001 4DWave NX + 122d 1400 Trident PCI288-Q3DII (NX) + 2100 CyberBlade XP4m32 + 2200 XGI Volari XP5 + 8400 CyberBlade/i7 + 1023 8400 CyberBlade i7 AGP + 8420 CyberBlade/i7d + 0e11 b15a CyberBlade i7 AGP + 8500 CyberBlade/i1 + 8520 CyberBlade i1 + 0e11 b16e CyberBlade i1 AGP + 1023 8520 CyberBlade i1 AGP + 8620 CyberBlade/i1 + 1014 0502 ThinkPad R30/T30 + 1014 1025 Travelmate 352TE + 8820 CyberBlade XPAi1 + 9320 TGUI 9320 + 9350 GUI Accelerator + 9360 Flat panel GUI Accelerator + 9382 Cyber 9382 [Reference design] + 9383 Cyber 9383 [Reference design] + 9385 Cyber 9385 [Reference design] + 9386 Cyber 9386 + 9388 Cyber 9388 + 9397 Cyber 9397 + 939a Cyber 9397DVD + 9420 TGUI 9420 + 9430 TGUI 9430 + 9440 TGUI 9440 + 9460 TGUI 9460 + 9470 TGUI 9470 + 9520 Cyber 9520 + 9525 Cyber 9525 + 9540 Cyber 9540 + 9660 TGUI 9660/938x/968x + 9680 TGUI 9680 + 9682 TGUI 9682 + 9683 TGUI 9683 + 9685 ProVIDIA 9685 + 9750 3DImage 9750 + 1014 9750 3DImage 9750 + 1023 9750 3DImage 9750 + 9753 TGUI 9753 + 9754 TGUI 9754 + 9759 TGUI 975 + 9783 TGUI 9783 + 9785 TGUI 9785 + 9850 3DImage 9850 + 9880 Blade 3D PCI/AGP + 1023 9880 Blade 3D + 9910 CyberBlade/XP + 9930 CyberBlade/XPm + 9960 CyberBlade XP2 +1024 Zenith Data Systems +1025 Acer Incorporated [ALI] + 1435 M1435 + 1445 M1445 + 1449 M1449 + 1451 M1451 + 1461 M1461 + 1489 M1489 + 1511 M1511 + 1512 ALI M1512 Aladdin + 1513 M1513 + 1521 ALI M1521 Aladdin III CPU Bridge + 10b9 1521 ALI M1521 Aladdin III CPU Bridge + 1523 ALI M1523 ISA Bridge + 10b9 1523 ALI M1523 ISA Bridge + 1531 M1531 Northbridge [Aladdin IV/IV+] + 1533 M1533 PCI-to-ISA Bridge + 10b9 1533 ALI M1533 Aladdin IV/V ISA South Bridge + 1535 M1535 PCI Bridge + Super I/O + FIR + 1541 M1541 Northbridge [Aladdin V] + 10b9 1541 ALI M1541 Aladdin V/V+ AGP+PCI North Bridge + 1542 M1542 Northbridge [Aladdin V] + 1543 M1543 PCI-to-ISA Bridge + Super I/O + FIR + 1561 M1561 Northbridge [Aladdin 7] + 1621 M1621 Northbridge [Aladdin-Pro II] + 1631 M1631 Northbridge+3D Graphics [Aladdin TNT2] + 1641 M1641 Northbridge [Aladdin-Pro IV] + 1647 M1647 [MaGiK1] PCI North Bridge + 1671 M1671 Northbridge [ALADDiN-P4] + 1672 Northbridge [CyberALADDiN-P4] + 3141 M3141 + 3143 M3143 + 3145 M3145 + 3147 M3147 + 3149 M3149 + 3151 M3151 + 3307 M3307 MPEG-I Video Controller + 3309 M3309 MPEG-II Video w/ Software Audio Decoder + 3321 M3321 MPEG-II Audio/Video Decoder + 5212 M4803 + 5215 ALI PCI EIDE Controller + 5217 M5217H + 5219 M5219 + 5225 M5225 + 5229 M5229 + 5235 M5235 + 5237 M5237 PCI USB Host Controller + 5240 EIDE Controller + 5241 PCMCIA Bridge + 5242 General Purpose Controller + 5243 PCI to PCI Bridge Controller + 5244 Floppy Disk Controller + 5247 M1541 PCI to PCI Bridge + 5251 M5251 P1394 Controller + 5427 PCI to AGP Bridge + 5451 M5451 PCI AC-Link Controller Audio Device + 5453 M5453 PCI AC-Link Controller Modem Device + 7101 M7101 PCI PMU Power Management Controller + 10b9 7101 M7101 PCI PMU Power Management Controller +# should be 1022:9602 + 9602 AMD RS780/RS880 PCI to PCI bridge (int gfx) +1028 Dell + 0001 PowerEdge Expandable RAID Controller 2/Si + 1028 0001 PowerEdge 2400 + 0002 PowerEdge Expandable RAID Controller 3/Di + 1028 0002 PowerEdge 4400 + 1028 00d1 PERC 3/DiV [Viper] + 1028 00d9 PERC 3/DiL [Lexus] + 0003 PowerEdge Expandable RAID Controller 3/Si + 1028 0003 PowerEdge 2450 +# PowerEdge Codename Iguana + 0004 PowerEdge Expandable RAID Controller 3/Di [Iguana] + 1028 0004 PERC 3/DiF [Iguana] + 0006 PowerEdge Expandable RAID Controller 3/Di + 0007 Remote Access Card III + 0008 Remote Access Card III + 0009 Remote Access Card III: BMC/SMIC device not present + 000a PowerEdge Expandable RAID Controller 3/Di + 1028 0106 PERC 3/DiJ [Jaguar] + 1028 011b PERC 3/DiD [Dagger] + 1028 0121 PERC 3/DiB [Boxster] + 000c Embedded Remote Access or ERA/O + 000d Embedded Remote Access: BMC/SMIC device + 000e PowerEdge Expandable RAID controller 4/Di + 000f PowerEdge Expandable RAID controller 4/Di + 1028 014a PowerEdge 1750 + 0010 Remote Access Card 4 + 0011 Remote Access Card 4 Daughter Card + 0012 Remote Access Card 4 Daughter Card Virtual UART + 0013 PowerEdge Expandable RAID controller 4 + 1028 016c PowerEdge Expandable RAID Controller 4e/Si + 1028 016d PowerEdge Expandable RAID Controller 4e/Di + 1028 016e PowerEdge Expandable RAID Controller 4e/Di + 1028 016f PowerEdge Expandable RAID Controller 4e/Di + 1028 0170 PowerEdge Expandable RAID Controller 4e/Di + 0014 Remote Access Card 4 Daughter Card SMIC interface + 0015 PowerEdge Expandable RAID controller 5 + 1028 1f01 PERC 5/E Adapter RAID Controller + 1028 1f02 PERC 5/i Adapter RAID Controller + 1028 1f03 PERC 5/i Integrated RAID Controller + 0016 PowerEdge Expandable RAID controller S300 + 1028 1f24 PERC S300 Controller +# NV-RAM Adapter used in Dell DR appliances + 0073 NV-RAM Adapter +1029 Siemens Nixdorf IS +102a LSI Logic + 0000 HYDRA + 0010 ASPEN + 001f AHA-2940U2/U2W /7890/7891 SCSI Controllers + 9005 000f 2940U2W SCSI Controller + 9005 0106 2940U2W SCSI Controller + 9005 a180 2940U2W SCSI Controller + 00c5 AIC-7899 U160/m SCSI Controller + 1028 00c5 PowerEdge 2550/2650/4600 + 00cf AIC-7899P U160/m + 1028 0106 PowerEdge 4600 + 1028 0121 PowerEdge 2650 +102b Matrox Electronics Systems Ltd. +# DJ: I've a suspicion that 0010 is a duplicate of 0d10. + 0010 MGA-I [Impression?] + 0100 MGA 1064SG [Mystique] + 0518 MGA-II [Athena] + 0519 MGA 2064W [Millennium] + 051a MGA 1064SG [Mystique] + 102b 0100 MGA-1064SG Mystique + 102b 1100 MGA-1084SG Mystique + 102b 1200 MGA-1084SG Mystique + 1100 102b MGA-1084SG Mystique + 110a 0018 Scenic Pro C5 (D1025) + 051b MGA 2164W [Millennium II] + 102b 051b MGA-2164W Millennium II + 102b 1100 MGA-2164W Millennium II + 102b 1200 MGA-2164W Millennium II + 102b 2100 MGA-2164W Millennium II + 051e MGA 1064SG [Mystique] AGP + 051f MGA 2164W [Millennium II] AGP + 102b 2100 MGA-2164WA [Millennium II A] + 0520 MGA G200 + 102b dbc2 G200 Multi-Monitor + 102b dbc8 G200 Multi-Monitor + 102b dbe2 G200 Multi-Monitor + 102b dbe8 G200 Multi-Monitor + 102b ff03 Millennium G200 SD + 102b ff04 Marvel G200 + 0521 MGA G200 AGP + 1014 ff03 Millennium G200 AGP + 102b 48e9 Mystique G200 AGP + 102b 48f8 Millennium G200 SD AGP + 102b 4a60 Millennium G200 LE AGP + 102b 4a64 Millennium G200 AGP + 102b c93c Millennium G200 AGP + 102b c9b0 Millennium G200 AGP + 102b c9bc Millennium G200 AGP + 102b ca60 Millennium G250 LE AGP + 102b ca6c Millennium G250 AGP + 102b dbbc Millennium G200 AGP + 102b dbc2 Millennium G200 MMS (Dual G200) + 102b dbc3 G200 Multi-Monitor + 102b dbc8 Millennium G200 MMS (Dual G200) + 102b dbd2 G200 Multi-Monitor + 102b dbd3 G200 Multi-Monitor + 102b dbd4 G200 Multi-Monitor + 102b dbd5 G200 Multi-Monitor + 102b dbd8 G200 Multi-Monitor + 102b dbd9 G200 Multi-Monitor + 102b dbe2 Millennium G200 MMS (Quad G200) + 102b dbe3 G200 Multi-Monitor + 102b dbe8 Millennium G200 MMS (Quad G200) + 102b dbf2 G200 Multi-Monitor + 102b dbf3 G200 Multi-Monitor + 102b dbf4 G200 Multi-Monitor + 102b dbf5 G200 Multi-Monitor + 102b dbf8 G200 Multi-Monitor + 102b dbf9 G200 Multi-Monitor + 102b f806 Mystique G200 Video AGP + 102b ff00 MGA-G200 AGP + 102b ff02 Mystique G200 AGP + 102b ff03 Millennium G200A AGP + 102b ff04 Marvel G200 AGP + 110a 0032 MGA-G200 AGP + 0522 MGA G200e [Pilot] ServerEngines (SEP1) + 103c 31fa ProLiant DL140 G3 + 0525 MGA G400/G450 + 0e11 b16f MGA-G400 AGP + 102b 0328 Millennium G400 16Mb SDRAM + 102b 0338 Millennium G400 16Mb SDRAM + 102b 0378 Millennium G400 32Mb SDRAM + 102b 0541 Millennium G450 Dual Head + 102b 0542 Millennium G450 Dual Head LX + 102b 0543 Millennium G450 Single Head LX + 102b 0641 Millennium G450 32Mb SDRAM Dual Head + 102b 0642 Millennium G450 32Mb SDRAM Dual Head LX + 102b 0643 Millennium G450 32Mb SDRAM Single Head LX + 102b 07c0 Millennium G450 Dual Head LE + 102b 07c1 Millennium G450 SDR Dual Head LE + 102b 0d41 Millennium G450 Dual Head PCI + 102b 0d42 Millennium G450 Dual Head LX PCI + 102b 0d43 Millennium G450 32Mb Dual Head PCI + 102b 0e00 Marvel G450 eTV + 102b 0e01 Marvel G450 eTV + 102b 0e02 Marvel G450 eTV + 102b 0e03 Marvel G450 eTV + 102b 0f80 Millennium G450 Low Profile + 102b 0f81 Millennium G450 Low Profile + 102b 0f82 Millennium G450 Low Profile DVI + 102b 0f83 Millennium G450 Low Profile DVI + 102b 19d8 Millennium G400 16Mb SGRAM + 102b 19f8 Millennium G400 32Mb SGRAM + 102b 2159 Millennium G400 Dual Head 16Mb + 102b 2179 Millennium G400 MAX/Dual Head 32Mb + 102b 217d Millennium G400 Dual Head Max + 102b 23c0 Millennium G450 + 102b 23c1 Millennium G450 + 102b 23c2 Millennium G450 DVI + 102b 23c3 Millennium G450 DVI + 102b 2f58 Millennium G400 + 102b 2f78 Millennium G400 + 102b 3693 Marvel G400 AGP + 102b 5dd0 4Sight II + 102b 5f50 4Sight II + 102b 5f51 4Sight II + 102b 5f52 4Sight II + 102b 9010 Millennium G400 Dual Head + 1458 0400 GA-G400 + 1705 0001 Millennium G450 32MB SGRAM + 1705 0002 Millennium G450 16MB SGRAM + 1705 0003 Millennium G450 32MB + 1705 0004 Millennium G450 16MB + 0527 Parhelia + 102b 0840 Parhelia 128Mb + 102b 0850 Parhelia 256MB + 102b 0870 MED2mp-DVI + 102b 0880 P-256 Edge Overlap Controller + 0528 Parhelia + 102b 1020 Parhelia 128MB + 102b 1030 Parhelia 256 MB Dual DVI + 102b 1040 MED2mp-DVI + 102b 1050 Sono S20 + 102b 1060 PJ-30L + 102b 1070 PJ-40L + 102b 1421 MED5mp + 102b 1431 MED3mp-DVI + 102b 1451 MED5mp-DVI + 102b 1491 MED2mp-DVI + 102b 14b1 MED3mp-DVI + 102b 14c1 MED5mp-DVI + 102b 14e1 Parhelia PCI 256MB + 102b 14f1 Parhelia Precision SGT + 102b 1501 ATC-4MP + 102b 1511 ATC-4MP + 102b 1521 TheatreVUE T30 + 102b 1531 TheatreVUE T20 + 102b 1541 MED2mp-DVI + 102b 1551 MED3mp-DVI + 102b 1561 MED5mp-DVI + 102b 1571 Parhelia DL256 PCI + 102b 1591 Parhelia Precision SDT + 102b 15a1 MED4mp-DVI + 102b 2011 Parhelia HR256 + 102b 2021 QID Pro + 102b 2061 PJ-40LP + 102b 2081 EWS Quad + 102b 2411 PPX-OUT8 + 102b 2421 VPX-OUT8 + 102b 2441 PPX-OUT4 + 102b 2451 VPX-OUT4 + 102b 2491 LPX-OUT4 + 0530 MGA G200EV + 0532 MGA G200eW WPCM450 + 1028 0235 PowerEdge R710 MGA G200eW WPCM450 + 1028 0236 PowerEdge R610 MGA G200eW WPCM450 + 1028 0237 PowerEdge T610 MGA G200eW WPCM450 + 1028 0287 PowerEdge M610 MGA G200eW WPCM450 + 1028 028c PowerEdge R410 MGA G200eW WPCM450 + 1028 028d PowerEdge T410 MGA G200eW WPCM450 + 1028 029c PowerEdge M710 MGA G200eW WPCM450 + 1028 02a4 PowerEdge T310 MGA G200eW WPCM450 + 15d9 0605 X8SIL + 15d9 0624 X9SCM-F Motherboard + 15d9 066b X9SRL-F + 15d9 a811 H8DGU + 0533 MGA G200EH + 103c 3381 iLO4 + 0534 G200eR2 + 1028 04f7 PowerEdge R320 server + 0536 Integrated Matrox G200eW3 Graphics Controller + 0538 MGA G200eH3 + 1590 00e4 iLO5 VGA + 0540 M91XX + 102b 2080 M9140 LP PCIe x16 + 102b 20c0 Xenia + 102b 20c1 Xenia Pro + 102b 2100 M9120 PCIe x16 + 102b 2140 M9125 PCIe x16 + 102b 2180 M9120 Plus LP PCIe x16 + 102b 21c0 M9120 Plus LP PCIe x1 + 102b 2200 VDA1164 Output Board + 102b 2240 M9148 LP PCIe x16 + 102b 2241 M9138 LP PCIe x16 + 102b 2280 M9188 ATX PCIe x16 + 102b 22c0 M9128 LP PCIe x16 + 0550 SV2 + 102b 00c0 MURA-IPX-I4EF + 102b 00c1 MURA-IPX-I4DF + 102b 00c3 MURA-IPX-I4DHF + 102b 00c5 MURA-IPX-I4EHF + 0d10 MGA Ultima/Impression + 1000 MGA G100 [Productiva] + 102b ff01 Productiva G100 + 102b ff05 Productiva G100 Multi-Monitor + 1001 MGA G100 [Productiva] AGP + 102b 1001 MGA-G100 AGP + 102b ff00 MGA-G100 AGP + 102b ff01 MGA-G100 Productiva AGP + 102b ff03 Millennium G100 AGP + 102b ff04 MGA-G100 AGP + 102b ff05 MGA-G100 Productiva AGP Multi-Monitor + 110a 001e MGA-G100 AGP + 2007 MGA Mistral + 2527 Millennium G550 +# PCI\VEN_102B&DEV_2527&SUBSYS_0F42102B&REV_01 + 102b 0f42 Matrox G550 Low Profile PCI + 102b 0f83 Millennium G550 + 102b 0f84 Millennium G550 Dual Head DDR 32Mb + 102b 1e41 Millennium G550 + 102b 22c0 G550 PCIe + 102b 2300 Millennium G550 LP PCIE + 2537 Millennium P650/P750 + 102b 1820 Millennium P750 64MB + 102b 1830 Millennium P650 64MB + 102b 1850 RAD2mp + 102b 1860 RAD3mp + 102b 1880 Sono S10 + 102b 1c10 QID 128MB + 102b 2811 Millennium P650 Low-profile PCI 64MB + 102b 2821 Millennium P650 Low-profile PCI + 102b 2841 RAD PCI + 102b 2851 Spectrum PCI + 102b 2871 EpicA TC2 + 102b 2c11 QID Low-profile PCI + 102b 2c21 QID LP PCI LW + 102b 2c31 QID LP PCI + 102b 2c41 EpicA TC4 + 102b 3001 Extio F1400 + 102b 3011 Extio F1220 + 102b 3041 RG-200DL + 102b 3051 RG-400SL + 102b 3061 Extio F1420 + 102b 3081 Extio F1240 + 2538 Millennium P650 PCIe + 102b 0847 RAD PCIe + 102b 08c7 Millennium P650 PCIe 128MB + 102b 0907 Millennium P650 PCIe 64MB + 102b 0947 Parhelia APVe + 102b 0987 ATC PCIe 4MP + 102b 1047 Millennium P650 LP PCIe 128MB + 102b 1087 Millennium P650 LP PCIe 64MB + 102b 1801 Millennium P650 PCIe x1 + 102b 2538 Parhelia APVe + 102b 3007 QID Low-profile PCIe + 102b 3087 Aurora VX3mp + 102b 30c7 QID LP PCIe + 2539 Millennium P690 + 102b 0040 Millennium P690 PCIe x16 + 102b 0042 ONYX + 102b 0043 SPECTRA + 102b 0080 Millennium P690 Plus LP PCIe x16 + 102b 0081 Millennium P690 LP PCIe x16 + 102b 0082 RAD LPX PCIe x16 + 102b 00c0 Millennium P690 Plus LP PCI + 102b 00c2 Millennium P690 LP PCI + 102b 00c3 RAD LPX PCI + 102b 0101 Millennium P690 PCI + 102b 0140 Millennium P690 LP PCIe x1 + 102b 0180 Display Wall IP Decode 128 MB + 4164 Morphis QxT frame grabber + 43b4 Morphis Qxt encoding engine + 4510 Morphis COM port + 4536 VIA Framegrabber + 4686 Concord GX (customized Intel 82541) + 475b Solios eCL/XCL-B frame grabber + 475d Vio frame grabber family + 102b 4b90 Vio Duo frame grabber (single channel) + 102b 4b91 Vio Duo frame grabber + 102b 4b92 Vio Analog frame grabber + 102b 4b93 Vio SDI Frame Grabber + 102b 4b94 Vio DVI-A frame grabber + 475f Solios (single-Full) CL frame grabber + 102b 475f Solios eCL/XCL-F frame grabber + 102b 4d5f Solios eV-CL (single-Full) frame grabber + 102b 4e5f Solios eM-CL (single-Full) frame grabber + 47a1 Solios eA/XA frame grabber + 102b 4be0 Solios eA/XA (single) frame grabber + 102b 4be1 Solios eA/XA (dual) frame grabber + 102b 4be2 Solios eA/XA (quad) frame grabber + 47a2 Solios COM port + 47c1 Solios (dual-Base/single-Medium) CL frame grabber + 102b 0000 Solios frame grabber + 102b 4b80 Solios eCL/XCL (single-Medium) frame grabber + 102b 4b81 Solios eCL/XCL (dual-Base) frame grabber + 102b 4d80 Solios eV-CL (single-Medium) frame grabber + 102b 4d81 Solios eV-CL (dual-Base) frame grabber + 102b 4e80 Solios eM-CL (single-Medium) frame grabber + 102b 4e81 Solios eM-CL (dual-Base) frame grabber + 47c2 Solios COM port + 4949 Radient frame grabber family + 102b 0010 Radient eCL (Single-full) frame grabber + 102b 0011 Radient eCLV (Single-full) frame grabber + 102b 0020 Radient eCL (Dual-base) frame grabber + 102b 0030 Radient eCL (Dual-full) frame grabber + 102b 0040 Radient eCL (Quad-base) frame grabber + 102b 0050 Radient eCL (Golden) frame grabber + 102b 1010 Radient eV-CXP (quad CXP-6) frame grabber + 102b 1015 Radient eV-CXP (dual CXP-6) frame grabber + 102b 1020 Radient eV-CXP (quad CXP-3) frame grabber + 102b 1050 Radient eV-CXP (Golden) frame grabber + 4cdc Morphis JPEG2000 accelerator + 4f54 Morphis (e)Quad frame grabber + 4fc5 Morphis (e)Dual frame grabber + 5e10 Morphis aux I/O + 6573 Shark 10/100 Multiport SwitchNIC +102c Chips and Technologies + 00b8 F64310 + 00c0 F69000 HiQVideo + 102c 00c0 F69000 HiQVideo + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1010 CP5/CR6 mainboard + 4c53 1020 VR6 mainboard + 4c53 1030 PC5 mainboard + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard + 00d0 F65545 + 00d8 F65545 + 00dc F65548 + 00e0 F65550 + 00e4 F65554 + 00e5 F65555 HiQVPro + 0e11 b049 Armada 1700 Laptop Display Controller + 1179 0001 Satellite Pro/Satellite + 00f0 F68554 + 00f4 F68554 HiQVision + 00f5 F68555 + 0c30 F69030 + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard + 4c53 1080 CT8 mainboard +102d Wyse Technology Inc. + 50dc 3328 Audio +102e Olivetti Advanced Technology +102f Toshiba America + 0009 r4x00 + 000a TX3927 MIPS RISC PCI Controller + 0020 ATM Meteor 155 + 102f 00f8 ATM Meteor 155 + 0030 TC35815CF PCI 10/100 Mbit Ethernet Controller + 0031 TC35815CF PCI 10/100 Mbit Ethernet Controller with WOL + 0032 TC35815CF PCI 10/100 Mbit Ethernet Controller on TX4939 + 0105 TC86C001 [goku-s] IDE + 0106 TC86C001 [goku-s] USB 1.1 Host + 0107 TC86C001 [goku-s] USB Device Controller + 0108 TC86C001 [goku-s] I2C/SIO/GPIO Controller + 0180 TX4927/38 MIPS RISC PCI Controller + 0181 TX4925 MIPS RISC PCI Controller + 0182 TX4937 MIPS RISC PCI Controller + 01b4 Celleb platform IDE interface + 01b5 SCC USB 2.0 EHCI controller + 01b6 SCC USB 1.1 OHCI controller +1030 TMC Research +1031 Miro Computer Products AG + 5601 DC20 ASIC + 5607 Video I/O & motion JPEG compressor + 5631 Media 3D + 6057 MiroVideo DC10/DC30+ +1032 Compaq +1033 NEC Corporation + 0000 Vr4181A USB Host or Function Control Unit + 0001 PCI to 486-like bus Bridge + 0002 PCI to VL98 Bridge + 0003 ATM Controller + 0004 R4000 PCI Bridge + 0005 PCI to 486-like bus Bridge + 0006 PC-9800 Graphic Accelerator + 0007 PCI to UX-Bus Bridge + 0008 PC-9800 Graphic Accelerator + 0009 PCI to PC9800 Core-Graph Bridge + 0016 PCI to VL Bridge + 001a [Nile II] + 0021 Vrc4373 [Nile I] + 0029 PowerVR PCX1 + 002a PowerVR 3D + 002c Star Alpha 2 + 002d PCI to C-bus Bridge + 0035 OHCI USB Controller + 1033 0035 USB Controller + 103c 1293 USB add-in card + 103c 1294 USB 2.0 add-in card + 1179 0001 USB + 1186 0035 DUB-C2 USB 2.0 2-port 32-bit cardbus controller + 12ee 7000 Root Hub + 14c2 0105 PTI-205N USB 2.0 Host Controller + 1799 0001 Root Hub + 1931 000a GlobeTrotter Fusion Quad Lite (PPP data) + 1931 000b GlobeTrotter Fusion Quad Lite (GSM data) + 807d 0035 PCI-USB2 (OHCI subsystem) + 003b PCI to C-bus Bridge + 003e NAPCCARD Cardbus Controller + 0046 PowerVR PCX2 [midas] + 005a Vrc5074 [Nile 4] + 0063 uPD72862 [Firewarden] IEEE1394 OHCI 1.0 Link Controller + 0067 PowerVR Neon 250 Chipset + 1010 0020 PowerVR Neon 250 AGP 32Mb + 1010 0080 PowerVR Neon 250 AGP 16Mb + 1010 0088 PowerVR Neon 250 16Mb + 1010 0090 PowerVR Neon 250 AGP 16Mb + 1010 0098 PowerVR Neon 250 16Mb + 1010 00a0 PowerVR Neon 250 AGP 32Mb + 1010 00a8 PowerVR Neon 250 32Mb + 1010 0120 PowerVR Neon 250 AGP 32Mb + 0072 uPD72874 IEEE1394 OHCI 1.1 3-port PHY-Link Ctrlr + 0074 56k Voice Modem + 1033 8014 RCV56ACF 56k Voice Modem + 009b Vrc5476 + 00a5 VRC4173 + 00a6 VRC5477 AC97 + 00cd uPD72870 [Firewarden] IEEE1394a OHCI 1.0 Link/3-port PHY Controller + 12ee 8011 Root hub + 00ce uPD72871 [Firewarden] IEEE1394a OHCI 1.0 Link/1-port PHY Controller + 00df Vr4131 + 00e0 uPD72010x USB 2.0 Controller + 1186 f100 DUB-C2 USB 2.0 2-port 32-bit cardbus controller + 12ee 7001 Root hub + 14c2 0205 PTI-205N USB 2.0 Host Controller + 1799 0002 Root Hub + 807d 1043 PCI-USB2 (EHCI subsystem) + 00e7 uPD72873 [Firewarden] IEEE1394a OHCI 1.1 Link/2-port PHY Controller + 00f2 uPD72874 [Firewarden] IEEE1394a OHCI 1.1 Link/3-port PHY Controller + 00f3 uPD6113x Multimedia Decoder/Processor [EMMA2] + 010c VR7701 + 0125 uPD720400 PCI Express - PCI/PCI-X Bridge + 013a Dual Tuner/MPEG Encoder + 0194 uPD720200 USB 3.0 Host Controller + 1028 04a3 Precision M4600 + 1028 04b2 Vostro 3350 + 1028 04da Vostro 3750 + 1043 8413 P8P67 Deluxe Motherboard + 104d 907a Vaio VPCF1 + 1af4 1100 QEMU Virtual Machine + 1b96 0001 USB 3.0 PCIe Card + 01e7 uPD72873 [Firewarden] IEEE1394a OHCI 1.1 Link/2-port PHY Controller + 01f2 uPD72874 [Firewarden] IEEE1394a OHCI 1.1 Link/3-port PHY Controller +1034 Framatome Connectors USA Inc. +1035 Comp. & Comm. Research Lab +1036 Future Domain Corp. + 0000 TMC-18C30 [36C70] +1037 Hitachi Micro Systems +1038 AMP, Inc +1039 Silicon Integrated Systems [SiS] + 0001 AGP Port (virtual PCI-to-PCI bridge) + 0002 AGP Port (virtual PCI-to-PCI bridge) + 0003 AGP Port (virtual PCI-to-PCI bridge) + 0004 PCI-to-PCI bridge + 1039 0000 PCIe x16 port + 0006 85C501/2/3 + 0008 SiS85C503/5513 (LPC Bridge) + 0009 5595 Power Management Controller + 000a PCI-to-PCI bridge + 1039 0000 PCIe x1 port + 0016 SiS961/2/3 SMBus controller + 0018 SiS85C503/5513 (LPC Bridge) + 0163 163 802.11b/g Wireless LAN Adapter + 0180 RAID bus controller 180 SATA/PATA [SiS] + 0181 SATA + 0182 182 SATA/RAID Controller + 1734 1095 D2030-A1 + 0186 AHCI Controller (0106) + 0190 190 Ethernet Adapter + 0191 191 Gigabit Ethernet Adapter + 1043 8139 P5SD2-FM/S mainboard + 0200 5597/5598/6326 VGA + 1039 0000 SiS5597 SVGA (Shared RAM) + 0204 82C204 + 0205 SG86C205 + 0300 300/305 PCI/AGP VGA Display Adapter + 107d 2720 Leadtek WinFast VR300 + 0310 315H PCI/AGP VGA Display Adapter + 0315 315 PCI/AGP VGA Display Adapter + 0325 315PRO PCI/AGP VGA Display Adapter + 0330 330 [Xabre] PCI/AGP VGA Display Adapter + 0406 85C501/2 + 0496 85C496 + 0530 530 Host + 0540 540 Host + 0550 550 Host + 0597 5513C + 0601 85C601 + 0620 620 Host + 0630 630 Host + 0633 633 Host + 0635 635 Host + 0645 SiS645 Host & Memory & AGP Controller + 0646 SiS645DX Host & Memory & AGP Controller + 0648 645xx + 0649 SiS649 Host + 0650 650/M650 Host + 0651 651 Host + 0655 655 Host + 0660 660 Host + 0661 661FX/M661FX/M661MX Host + 0662 662 Host + 0671 671MX + 0730 730 Host + 0733 733 Host + 0735 735 Host + 0740 740 Host + 0741 741/741GX/M741 Host + 1849 0741 K7S41/K7S41GX motherboard + 0745 745 Host + 0746 746 Host + 0755 755 Host + 0760 760/M760 Host + 0761 761/M761 Host + 1734 1099 D2030-A1 Motherboard + 0900 SiS900 PCI Fast Ethernet + 1019 0a14 K7S5A motherboard + 1039 0900 SiS900 10/100 Ethernet Adapter onboard + 1043 8035 CUSI-FX motherboard + 1043 80a7 Motherboard P4S800D-X + 1462 0900 MS-6701 motherboard + 0961 SiS961 [MuTIOL Media IO] + 0962 SiS962 [MuTIOL Media IO] LPC Controller + 0963 SiS963 [MuTIOL Media IO] LPC Controller + 0964 SiS964 [MuTIOL Media IO] LPC Controller + 0965 SiS965 [MuTIOL Media IO] + 0966 SiS966 [MuTIOL Media IO] + 0968 SiS968 [MuTIOL Media IO] + 1180 SATA Controller / IDE mode + 1182 SATA Controller / RAID mode + 1039 0180 SiS 966 4-port SATA controller + 1183 SATA Controller / IDE mode + 1039 0180 SiS 966 4-port SATA controller + 1184 AHCI Controller / RAID mode + 1185 AHCI IDE Controller (0106) + 3602 83C602 + 5107 5107 + 5300 SiS540 PCI Display Adapter + 5315 550 PCI/AGP VGA Display Adapter + 5401 486 PCI Chipset + 5511 5511/5512 + 5513 5513 IDE Controller + 1019 0970 P6STP-FL motherboard + 1039 5513 SiS5513 EIDE Controller (A,B step) + 1043 8035 CUSI-FX motherboard + 1462 7010 MS-6701 motherboard + 1631 5513 GA-8SIML Rev1.0 Motherboard + 1734 1095 D2030-A1 Motherboard + 5517 5517 + 5571 5571 + 5581 5581 Pentium Chipset + 5582 5582 + 5591 5591/5592 Host + 5596 5596 Pentium Chipset + 5597 5597 [SiS5582] + 5600 5600 Host + 6204 Video decoder & MPEG interface + 6205 VGA Controller + 6236 6236 3D-AGP + 6300 630/730 PCI/AGP VGA Display Adapter + 1019 0970 P6STP-FL motherboard + 1043 8035 CUSI-FX motherboard + 104d 80e2 VAIO PCV-J200 + 6306 530/620 PCI/AGP VGA Display Adapter + 6325 65x/M650/740 PCI/AGP VGA Display Adapter + 1039 6325 SiS 651 onboard [Asus P4SC-EA] + 1631 1004 SiS 651C onboard [Gigabyte GA-8SIML Rev1.0] + 6326 86C326 5598/6326 + 1039 6326 SiS6326 GUI Accelerator + 1092 0a50 SpeedStar A50 + 1092 0a70 SpeedStar A70 + 1092 4910 SpeedStar A70 + 1092 4920 SpeedStar A70 + 10b0 6326 S6110-B (AGP) + 1569 6326 SiS6326 GUI Accelerator + 6330 661/741/760 PCI/AGP or 662/761Gx PCIE VGA Display Adapter + 1039 6330 [M]661xX/[M]741[GX]/[M]760 PCI/AGP VGA Adapter + 1043 8113 SiS Real 256E (ASUS P5S800-VM motherboard) + 1458 d000 SiS661FX GUI 2D/3D Accelerator + 1734 1099 D2030-A1 + 6350 770/670 PCIE VGA Display Adapter + 6351 771/671 PCIE VGA Display Adapter + 7001 USB 1.1 Controller + 1019 0a14 K7S5A motherboard + 1039 7000 Onboard USB Controller + 1462 5470 ECS K7SOM+ motherboard + 1462 7010 MS-6701 motherboard + 1734 1095 D2030-A1 Motherboard + 7002 USB 2.0 Controller + 1462 5470 K7SOM+ 5.2C Motherboard + 1462 7010 MS-6701 motherboard + 1509 7002 Onboard USB Controller + 1734 1095 D2030-A1 + 7007 FireWire Controller + 1462 701d MS-6701 + 7012 SiS7012 AC'97 Sound Controller + 1019 0f05 A928 (i-Buddie) + 1039 7012 SiS 7012 onboard [Asus P4SC-EA] AC'97 Sound Controller + 1043 818f A8S-X Motherboard + 13f6 0300 CMI9739(A) on ECS K7S series motherboard + 1462 5850 MSI 648 Max (MS-6585) + 1462 7010 MS-6701 motherboard + 15bd 1001 DFI 661FX motherboard + 1734 109f D2030-A1 Motherboard + 1849 7012 K7S41GX motherboard +# There are may be different modem codecs here (Intel537 compatible and incompatible) + 7013 AC'97 Modem Controller + 7016 SiS7016 PCI Fast Ethernet Adapter + 1039 7016 SiS7016 10/100 Ethernet Adapter + 7018 SiS PCI Audio Accelerator + 1014 01b6 SiS PCI Audio Accelerator + 1014 01b7 SiS PCI Audio Accelerator + 1019 7018 SiS PCI Audio Accelerator + 1025 000e SiS PCI Audio Accelerator + 1025 0018 SiS PCI Audio Accelerator + 1039 7018 SiS PCI Audio Accelerator + 1043 1453 SiS PCI Audio Accelerator + 1043 800b SiS PCI Audio Accelerator + 104d 80e2 VAIO PCV-J200 + 1054 7018 SiS PCI Audio Accelerator + 107d 5330 SiS PCI Audio Accelerator + 107d 5350 SiS PCI Audio Accelerator + 1170 3209 SiS PCI Audio Accelerator + 1462 400a SiS PCI Audio Accelerator + 14a4 2089 SiS PCI Audio Accelerator + 14cd 2194 SiS PCI Audio Accelerator + 14ff 1100 SiS PCI Audio Accelerator + 152d 8808 SiS PCI Audio Accelerator + 1558 1103 SiS PCI Audio Accelerator + 1558 2200 SiS PCI Audio Accelerator + 1563 7018 SiS PCI Audio Accelerator + 15c5 0111 SiS PCI Audio Accelerator + 270f a171 SiS PCI Audio Accelerator + a0a0 0022 SiS PCI Audio Accelerator + 7019 SiS7019 Audio Accelerator + 7502 Azalia Audio Controller + 1043 81a1 P5SD2-FM/S mainboard +103a Seiko Epson Corporation +103b Tatung Corp. Of America +103c Hewlett-Packard Company + 1005 A4977A Visualize EG + 1008 Visualize FX + 1028 Tach TL Fibre Channel Host Adapter + 1029 Tach XL2 Fibre Channel Host Adapter + 107e 000f Interphase 5560 Fibre Channel Adapter + 9004 9210 1Gb/2Gb Family Fibre Channel Controller + 9004 9211 1Gb/2Gb Family Fibre Channel Controller + 102a Tach TS Fibre Channel Host Adapter + 107e 000e Interphase 5540/5541 Fibre Channel Adapter + 9004 9110 1Gb/2Gb Family Fibre Channel Controller + 9004 9111 1Gb/2Gb Family Fibre Channel Controller + 1030 J2585A DeskDirect 10/100VG NIC + 1031 J2585B HP 10/100VG PCI LAN Adapter + 103c 1040 J2973A DeskDirect 10BaseT NIC + 103c 1041 J2585B DeskDirect 10/100VG NIC + 103c 1042 J2970A DeskDirect 10BaseT/2 NIC + 1040 J2973A DeskDirect 10BaseT NIC + 1041 J2585B DeskDirect 10/100 NIC + 1042 J2970A DeskDirect 10BaseT/2 NIC + 1048 Diva Serial [GSP] Multiport UART + 103c 1049 Tosca Console + 103c 104a Tosca Secondary + 103c 104b Maestro SP2 + 103c 1223 Superdome Console + 103c 1226 Keystone SP2 + 103c 1227 Powerbar SP2 + 103c 1282 Everest SP2 + 103c 1301 Diva RMP3 + 1054 PCI Local Bus Adapter + 1064 79C970 PCnet Ethernet Controller + 108b Visualize FXe + 10c1 NetServer Smart IRQ Router + 10ed TopTools Remote Control + 10f0 rio System Bus Adapter + 10f1 rio I/O Controller + 1219 NetServer PCI Hot-Plug Controller + 121a NetServer SMIC Controller + 121b NetServer Legacy COM Port Decoder + 121c NetServer PCI COM Port Decoder + 1229 zx1 System Bus Adapter + 122a zx1 I/O Controller + 122e PCI-X Local Bus Adapter + 127b sx1000 System Bus Adapter + 127c sx1000 I/O Controller + 128d Diva [GSP] Management Board + 1290 Auxiliary Diva Serial Port + 103c 1291 Diva SP2 + 1291 Auxiliary Diva Serial Port + 12b4 zx1 QuickSilver AGP8x Local Bus Adapter + 12eb sx2000 System Bus Adapter + 12ec sx2000 I/O Controller + 12ee PCI-X 2.0 Local Bus Adapter + 1302 RMP-3 Shared Memory Driver + 1303 RMP-3 (Remote Management Processor) + 22f6 iLO5 Virtual USB Controller + 1590 00e4 iLO5 Standard Virtual USB Controller + 2910 E2910A PCIBus Exerciser + 2925 E2925A 32 Bit, 33 MHzPCI Exerciser & Analyzer + 3206 Adaptec Embedded Serial ATA HostRAID + 3220 Smart Array P600 + 103c 3225 3 Gb/s SAS RAID + 3230 Smart Array Controller + 103c 3223 Smart Array P800 + 103c 3234 P400 SAS Controller + 103c 3235 P400i SAS Controller + 103c 3237 E500 SAS Controller + 103c 323d P700m SAS Controller + 3238 Smart Array E200i (SAS Controller) + 103c 3211 Smart Array E200i + 103c 3212 Smart Array E200 + 3239 Smart Array Gen9 Controllers + 103c 21bd P244br + 103c 21be P741m + 103c 21bf H240ar + 103c 21c0 P440ar + 103c 21c1 P840ar + 103c 21c2 P440 + 103c 21c3 P441 + 103c 21c4 Smart Array + 103c 21c5 P841 + 103c 21c6 H244br + 103c 21c7 H240 + 103c 21c8 H241 + 103c 21c9 Smart Array + 103c 21ca P246br + 103c 21cb P840 + 103c 21cc Smart Array + 103c 21cd P240nr + 103c 21ce H240nr + 323a Smart Array G6 controllers + 103c 3241 Smart Array P212 + 103c 3243 Smart Array P410 + 103c 3245 Smart Array P410i + 103c 3247 Smart Array P411 + 103c 3249 Smart Array P812 + 103c 324a Smart Array 712m (Mezzanine RAID controller) + 103c 324b Smart Array P711m (Mezzanine RAID controller) + 323b Smart Array Gen8 Controllers + 103c 3350 P222 + 103c 3351 P420 + 103c 3352 P421 + 103c 3354 P420i + 103c 3355 P220i + 323c Smart Array Gen8+ Controllers + 103c 1920 P430i + 103c 1921 P830i + 103c 1922 P430 + 103c 1923 P431 + 103c 1924 P830 + 103c 1925 Smart Array + 103c 1926 P731m + 103c 1928 P230i + 3300 Integrated Lights-Out Standard Virtual USB Controller + 103c 3304 iLO2 + 103c 3305 iLO2 + 103c 3309 iLO2 GXL/iLO3 GXE + 103c 330e iLO3 + 103c 3381 iLO4 + 3301 Integrated Lights-Out Standard Serial Port + 103c 3304 iLO2 + 103c 3305 iLO2 + 103c 330e iLO3 + 103c 3381 iLO4 +# Virtual serial port which is presented on a Java applet + 3302 Integrated Lights-Out Standard KCS Interface + 103c 3304 iLO2 + 103c 3305 iLO2 + 103c 330e iLO3 + 103c 3381 iLO4 + 3305 Integrated Lights-Out (iLO2) Controller + 3306 Integrated Lights-Out Standard Slave Instrumentation & System Support + 103c 330e iLO3 + 103c 3381 iLO4 + 1590 00e4 iLO5 + 3307 Integrated Lights-Out Standard Management Processor Support and Messaging +# HP DL380 G6 + 103c 3309 iLO 2 + 103c 330e iLO3 + 103c 3381 iLO4 + 3308 Integrated Lights-Out Standard MS Watchdog Timer + 103c 330e iLO3 + 103c 3381 iLO4 + 4030 zx2 System Bus Adapter + 4031 zx2 I/O Controller + 4037 PCIe Local Bus Adapter + 9602 AMD RS780/RS880 PCI to PCI bridge (int gfx) + 103c 1609 ProLiant MicroServer N36L +103e Solliday Engineering +103f Synopsys/Logic Modeling Group +1040 Accelgraphics Inc. +1041 Computrend +1042 Micron + 1000 PC Tech RZ1000 + 1001 PC Tech RZ1001 + 3000 Samurai_0 + 3010 Samurai_1 + 3020 Samurai_IDE +1043 ASUSTeK Computer Inc. + 0464 Radeon R9 270x GPU + 0521 RX580 [RX 580 Dual O8G] + 0675 ISDNLink P-IN100-ST-D + 0675 1704 ISDN Adapter (PCI Bus, D, C) + 0675 1707 ISDN Adapter (PCI Bus, DV, W) + 10cf 105e ISDN Adapter (PCI Bus, DV, W) +# Should be 1022:9602 + 9602 AMD RS780/RS880 PCI to PCI bridge (int gfx) + 1043 83a2 M4A785TD Motherboard +1044 Adaptec (formerly DPT) + 1012 Domino RAID Engine + a400 SmartCache/Raid I-IV Controller + a500 PCI Bridge + a501 SmartRAID V Controller + 1044 c001 PM1554U2 Ultra2 Single Channel + 1044 c002 PM1654U2 Ultra2 Single Channel + 1044 c003 PM1564U3 Ultra3 Single Channel + 1044 c004 PM1564U3 Ultra3 Dual Channel + 1044 c005 PM1554U2 Ultra2 Single Channel (NON ACPI) + 1044 c00a PM2554U2 Ultra2 Single Channel + 1044 c00b PM2654U2 Ultra2 Single Channel + 1044 c00c PM2664U3 Ultra3 Single Channel + 1044 c00d PM2664U3 Ultra3 Dual Channel + 1044 c00e PM2554U2 Ultra2 Single Channel (NON ACPI) + 1044 c00f PM2654U2 Ultra2 Single Channel (NON ACPI) + 1044 c014 PM3754U2 Ultra2 Single Channel (NON ACPI) + 1044 c015 PM3755U2B Ultra2 Single Channel (NON ACPI) + 1044 c016 PM3755F Fibre Channel (NON ACPI) + 1044 c01e PM3757U2 Ultra2 Single Channel + 1044 c01f PM3757U2 Ultra2 Dual Channel + 1044 c020 PM3767U3 Ultra3 Dual Channel + 1044 c021 PM3767U3 Ultra3 Quad Channel + 1044 c028 PM2865U3 Ultra3 Single Channel + 1044 c029 PM2865U3 Ultra3 Dual Channel + 1044 c02a PM2865F Fibre Channel + 1044 c03c 2000S Ultra3 Single Channel + 1044 c03d 2000S Ultra3 Dual Channel + 1044 c03e 2000F Fibre Channel + 1044 c046 3000S Ultra3 Single Channel + 1044 c047 3000S Ultra3 Dual Channel + 1044 c048 3000F Fibre Channel + 1044 c050 5000S Ultra3 Single Channel + 1044 c051 5000S Ultra3 Dual Channel + 1044 c052 5000F Fibre Channel + 1044 c05a 2400A UDMA Four Channel + 1044 c05b 2400A UDMA Four Channel DAC + 1044 c064 3010S Ultra3 Dual Channel + 1044 c065 3410S Ultra160 Four Channel + 1044 c066 3010S Fibre Channel + a511 SmartRAID V Controller + 1044 c032 ASR-2005S I2O Zero Channel + 1044 c035 ASR-2010S I2O Zero Channel + c066 3010S Ultra3 Dual Channel +1045 OPTi Inc. + a0f8 82C750 [Vendetta] USB Controller + c101 92C264 + c178 92C178 + c556 82X556 [Viper] + c557 82C557 [Viper-M] + c558 82C558 [Viper-M ISA+IDE] + c567 82C750 [Vendetta], device 0 + c568 82C750 [Vendetta], device 1 + c569 82C579 [Viper XPress+ Chipset] + c621 82C621 [Viper-M/N+] + c700 82C700 [FireStar] + c701 82C701 [FireStar Plus] + c814 82C814 [Firebridge 1] + c822 82C822 + c824 82C824 + c825 82C825 [Firebridge 2] + c832 82C832 + c861 82C861 OHCI USB Host + c881 82C881 [FireLink] 1394 OHCI Link Controller + c895 82C895 + c935 EV1935 ECTIVA MachOne PCIAudio + d568 82C825 [Firebridge 2] + d721 IDE [FireStar] +1046 IPC Corporation, Ltd. +1047 Genoa Systems Corp +1048 Elsa AG + 0c60 Gladiac MX + 0d22 Quadro4 900XGL [ELSA GLoria4 900XGL] + 1000 QuickStep 1000 + 3000 QuickStep 3000 + 8901 Gloria XL + 1048 0935 GLoria XL (Virge) +1049 Fountain Technologies, Inc. +# nee SGS Thomson Microelectronics +104a STMicroelectronics + 0000 STLS2F Host Bridge + 0008 STG 2000X + 0009 STG 1764X + 0010 STG4000 [3D Prophet Kyro Series] + 104a 4018 ST PowerVR Kyro (64MB AGP TVO) +# 64MB AGP + 1681 0010 PowerVR Kyro II [3D Prophet 4500] + 1681 0028 3D Prophet 4000XT + 1681 c010 3D Prophet 4500 TV-Out + 1681 c069 3D Prophet 4000XT + 0201 STPC Vega Northbridge + 0209 STPC Consumer/Industrial North- and Southbridge + 020a STPC Atlas/ConsumerS/Consumer IIA Northbridge + 020b STPC Consumer II ISA Bridge + 0210 STPC Atlas ISA Bridge + 021a STPC Consumer S Southbridge + 021b STPC Consumer IIA Southbridge + 0220 STPC Industrial PCI to PCCard bridge + 0228 STPC Atlas IDE + 0229 STPC Vega IDE + 0230 STPC Atlas/Vega OHCI USB Controller + 0238 STPC Vega LAN + 0500 ST70137 [Unicorn] ADSL DMT Transceiver + 104a 0500 BeWAN ADSL PCI st + 0564 STPC Client Northbridge + 0981 21x4x DEC-Tulip compatible 10/100 Ethernet + 1746 STG 1764X + 2774 21x4x DEC-Tulip compatible 10/100 Ethernet + 3520 MPEG-II decoder card + 55cc STPC Client Southbridge +104b BusLogic + 0140 BT-946C (old) [multimaster 01] + 1040 BT-946C (BA80C30) [MultiMaster 10] + 8130 Flashpoint LT +104c Texas Instruments + 0500 100 MBit LAN Controller + 0508 TMS380C2X Compressor Interface + 1000 Eagle i/f AS + 104c PCI1510 PC card Cardbus Controller + 3d04 TVP4010 [Permedia] + 3d07 TVP4020 [Permedia 2] + 1011 4d10 Comet + 1040 000f AccelStar II + 1040 0011 AccelStar II + 1048 0a31 WINNER 2000 + 1048 0a32 GLoria Synergy + 1048 0a34 GLoria Synergy + 1048 0a35 GLoria Synergy + 1048 0a36 GLoria Synergy + 1048 0a43 GLoria Synergy + 1048 0a44 GLoria Synergy + 107d 2633 WinFast 3D L2300 + 1092 0126 FIRE GL 1000 PRO + 1092 0127 FIRE GL 1000 PRO + 1092 0136 FIRE GL 1000 PRO + 1092 0141 FIRE GL 1000 PRO + 1092 0146 FIRE GL 1000 PRO + 1092 0148 FIRE GL 1000 PRO + 1092 0149 FIRE GL 1000 PRO + 1092 0152 FIRE GL 1000 PRO + 1092 0154 FIRE GL 1000 PRO + 1092 0155 FIRE GL 1000 PRO + 1092 0156 FIRE GL 1000 PRO + 1092 0157 FIRE GL 1000 PRO + 1097 3d01 Jeronimo Pro + 1102 100f Graphics Blaster Extreme + 3d3d 0100 Reference Permedia 2 3D + 8000 PCILynx/PCILynx2 IEEE 1394 Link Layer Controller + 105e 8003 FireBoard200 + 1443 8003 FireBoard200 + 1443 8005 FireBoard400 + 1443 8006 FireBoard400 + e4bf 1010 CF1-1-SNARE + e4bf 1020 CF1-2-SNARE + e4bf 1040 FireCompact400 + 8009 TSB12LV22 IEEE-1394 Controller + 104d 8032 8032 OHCI i.LINK (IEEE 1394) Controller + 1443 8010 FireBoard400-OHCI + 8017 PCI4410 FireWire Controller + 8019 TSB12LV23 IEEE-1394 Controller + 11bd 000a Studio DV500-1394 + 11bd 000e Studio DV + 1443 8010 FireBoard400-OHCI + e4bf 1010 CF2-1-CYMBAL + 8020 TSB12LV26 IEEE-1394 Controller (Link) + 1028 00d8 Precision 530 + 104d 80e2 VAIO PCV-J200 + 11bd 000f Studio DV500-1394 + 11bd 001c Excalibur 4.1 + 1443 8010 FireBoard400-OHCI + 8021 TSB43AA22 IEEE-1394 Controller (PHY/Link Integrated) + 104d 80df Vaio PCG-FX403 + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 8022 TSB43AB22 IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] + 104c 8023 TSB43AB22/A IEEE-1394a-2000 Controller (PHY/Link) + 8023 TSB43AB22A IEEE-1394a-2000 Controller (PHY/Link) [iOHCI-Lynx] + 1028 0168 Precision Workstation 670 Mainboard + 103c 088c NC8000 laptop + 1043 808b K8N4/A8N Series Mainboard + 1043 815b P5W DH Deluxe Motherboard + 1443 8023 FireCard400 + 8086 5044 Desktop Board DP35DP + 8024 TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link) + 107d 6620 Winfast DV2000 FireWire Controller + 1443 8024 FireBoard Blue + 1458 1000 Motherboard + 8025 TSB82AA2 IEEE-1394b Link Layer Controller + 1043 813c P5P series mainboard + 1443 8025 FireBoard800 + 1458 1000 GA-K8N Ultra-9 Mainboard + 1546 8025 FWB-PCI01 + 17fc 8025 GIC3800 + 8026 TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link) + 1025 0035 TravelMate 660 + 1025 003c Aspire 2001WLCi (Compaq CL50 motherboard) + 103c 0025 XE4500 Notebook + 103c 006a NX9500 + 1043 808d A7V333 mainboard. + 8027 PCI4451 IEEE-1394 Controller + 1028 00e5 Latitude C810 + 1028 00e6 PCI4451 IEEE-1394 Controller (Dell Inspiron 8100) + 8029 PCI4510 IEEE-1394 Controller + 1028 0163 Latitude D505 + 1028 0196 Inspiron 5160 + 1071 8160 MIM2900 + 802b PCI7410,7510,7610 OHCI-Lynx Controller + 1028 0139 Latitude D400 + 1028 014e PCI7410,7510,7610 OHCI-Lynx Controller (Latitude D800) + 802e PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller + 1028 018d Inspiron 700m/710m + 8031 PCIxx21/PCIxx11/PCIx515 PC Card Controller + 1025 0064 Extensa 3000 series laptop + 1025 0080 Aspire 5024WLMi + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 103c 308b MX6125 + 8032 OHCI Compliant IEEE 1394 Host Controller + 1025 0064 Extensa 3000 series laptop + 1025 0080 Aspire 5024WLMi + 103c 0934 Compaq nw8240/nx8220 + 103c 099c NX6110/NC6120 + 103c 308b MX6125 + 8033 PCIxx21/PCIxx11 Flash Media Controller + 1025 0064 Extensa 3000 series laptop + 1025 0080 Aspire 5024WLMi + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 103c 308b MX6125 + 8034 PCIxx21/PCIxx11 SD Host Controller + 1025 0080 Aspire 5024WLMi + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 103c 308b MX6125 + 8035 PCIxx21/PCIxx11 Smart Card Controller + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 8036 PCI6515 Cardbus Controller + 8038 PCI6515 SmartCard Controller + 8039 PCIxx12 Cardbus Controller + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 104d 902d VAIO VGN-NR120E + 803a PCIxx12 OHCI Compliant IEEE 1394 Host Controller + 103c 309f nx9420 + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 104d 902d VAIO VGN-NR120E + 803b PCIxx12 Flash Media Controller + 103c 309f nx9420 + 103c 30a3 Compaq nw8440 + 104d 8212 VAIO VGN-N21E + 104d 902d VAIO VGN-NR120E + 803c PCIxx12 SDA Standard Compliant SD Host Controller + 103c 309f nx9420 + 103c 30a3 Compaq nw8440 + 803d PCIxx12 GemCore based SmartCard controller + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 nc8430 + 103c 30aa nc6310 + 8101 TSB43DB42 IEEE-1394a-2000 Controller (PHY/Link) + 8201 PCI1620 Firmware Loading Function + 8204 PCI7410/7510/7610 PCI Firmware Loading Function + 1028 0139 Latitude D400 + 1028 014e Latitude D800 + 8231 XIO2000(A)/XIO2200A PCI Express-to-PCI Bridge + 5678 1234 DC-1394 PCIe + 8232 XIO3130 PCI Express Switch (Upstream) + 8233 XIO3130 PCI Express Switch (Downstream) + 8235 XIO2200A IEEE-1394a-2000 Controller (PHY/Link) + 5678 1234 DC-1394 PCIe + 823e XIO2213A/B/XIO2221 PCI Express to PCI Bridge [Cheetah Express] + 823f XIO2213A/B/XIO2221 IEEE-1394b OHCI Controller [Cheetah Express] + 1546 803c FWB-PCIE1X11B + 8240 XIO2001 PCI Express-to-PCI Bridge + 8241 TUSB73x0 SuperSpeed USB 3.0 xHCI Host Controller + 1014 04b2 S824 (8286-42A) + 8400 ACX 100 22Mbps Wireless Interface + 1186 3b00 DWL-650+ PC Card cardbus 22Mbs Wireless Adapter [AirPlus] + 1186 3b01 DWL-520+ 22Mbps PCI Wireless Adapter + 1395 2201 WL22-PC + 16ab 8501 WL-8305 IEEE802.11b+ Wireless LAN PCI Adapter + 8401 ACX 100 22Mbps Wireless Interface + 8888 Multicore DSP+ARM KeyStone II SOC + 9000 Wireless Interface (of unknown type) + 9065 TMS320DM642 + 9066 ACX 111 54Mbps Wireless Interface + 0308 3404 G-102 v1 802.11g Wireless Cardbus Adapter + 0308 3406 G-162 v2 802.11g Wireless Cardbus Adapter + 104c 9066 WL212 Sitecom Wireless Network PCI-Card 100M (Version 1) +# Found in Philips ADSL ANNEX A WLAN Router SNA6500/18 sold by Belgacom + 104c 9067 TNETW1130GVF + 104c 9096 Trendnet TEW-412PC Wireless PCI Adapter (Version A) + 1186 3b04 DWL-G520+ Wireless PCI Adapter + 1186 3b05 DWL-G650+ AirPlusG+ CardBus Wireless LAN + 1186 3b08 AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.B1) + 1385 4c00 WG311v2 802.11g Wireless PCI Adapter + 13d1 aba0 SWLMP-54108 108Mbps Wireless mini PCI card 802.11g+ + 14ea ab07 GW-NS54GM Wireless Cardbus Adapter + 16ec 010d USR5416 802.11g Wireless Turbo PCI Adapter + 16ec 010e USR5410 802.11g Wireless Cardbus Adapter + 1737 0033 WPC54G v2 802.11g Wireless-G Notebook Adapter + 17cf 0032 G-162 v1 802.11g Wireless Cardbus Adapter + 17cf 0033 Z-Com XG650 Wireless miniPCI 802.11b/g + 187e 340b G-302 v2 802.11g Wireless PCI Adapter + 187e 340c G-360 v2 802.11g Wireless PCI Adapter + a001 TDC1570 + a100 TDC1561 + a102 TNETA1575 HyperSAR Plus w/PCI Host i/f & UTOPIA i/f + a106 TMS320C6414 TMS320C6415 TMS320C6416 + 175c 5000 ASI50xx Audio Adapter + 175c 6400 ASI6400 Cobranet series + 175c 8700 ASI87xx Radio Tuner card + ac10 PCI1050 + ac11 PCI1053 + ac12 PCI1130 + ac13 PCI1031 + ac15 PCI1131 + ac16 PCI1250 + 1014 0092 ThinkPad 600 + ac17 PCI1220 + ac18 PCI1260 + ac19 PCI1221 + ac1a PCI1210 + ac1b PCI1450 + 0e11 b113 Armada M700 + 1014 0130 ThinkPad 600X/A21m/T20/T22 + ac1c PCI1225 + 0e11 b121 Armada E500 + 1028 0088 Latitude CPi A400XT + ac1d PCI1251A + ac1e PCI1211 + ac1f PCI1251B + ac20 TI 2030 + ac21 PCI2031 + ac22 PCI2032 PCI Docking Bridge + ac23 PCI2250 PCI-to-PCI Bridge + ac28 PCI2050 PCI-to-PCI Bridge + ac2c PCI2060 PCI-to-PCI Bridge + ac30 PCI1260 PC card Cardbus Controller + ac40 PCI4450 PC card Cardbus Controller + ac41 PCI4410 PC card Cardbus Controller + ac42 PCI4451 PC card Cardbus Controller + 1028 00e6 PCI4451 PC card CardBus Controller (Inspiron 8100) + ac44 PCI4510 PC card Cardbus Controller + 1028 0149 Inspiron 5100 + 1028 0163 Latitude D505 + 1028 0196 Inspiron 5160 + 1071 8160 MIM2000 + ac46 PCI4520 PC card Cardbus Controller + 1014 0552 ThinkPad + ac47 PCI7510 PC card Cardbus Controller + 1028 0139 Latitude D400 + 1028 013f Precision M60 + 1028 014e Latitude D800 + ac48 PCI7610 PC Card Cardbus Controller + ac49 PCI7410 PC Card Cardbus Controller + ac4a PCI7510/7610 CardBus Bridge + 1028 0139 Latitude D400 + 1028 014e Latitude D800 + ac4b PCI7610 SD/MMC controller + ac4c PCI7610 Memory Stick controller + ac50 PCI1410 PC card Cardbus Controller + ac51 PCI1420 PC card Cardbus Controller + 0e11 004e Evo N600c + 1014 0148 ThinkPad A20m + 1014 023b ThinkPad T23 + 1028 00b1 Latitude C600 + 1028 012a Latitude C640 + 1033 80cd Versa Note VXi + 10cf 1095 Lifebook S-4510/C6155 + e4bf 1000 CP2-2-HIPHOP + ac52 PCI1451 PC card Cardbus Controller + ac53 PCI1421 PC card Cardbus Controller + ac54 PCI1620 PC Card Controller + 103c 08b0 tc1100 tablet + ac55 PCI1520 PC card Cardbus Controller + 1014 0512 ThinkPad T30/T40 + 103c 0025 XE4500 Notebook + ac56 PCI1510 PC card Cardbus Controller + 1014 0512 ThinkPad R50e + 1014 0528 ThinkPad R40e + 17aa 2012 ThinkPad T60/R60 series + ac60 PCI2040 PCI to DSP Bridge Controller + 175c 5100 ASI51xx Audio Adapter + 175c 6100 ASI61xx Audio Adapter + 175c 6200 ASI62xx Audio Adapter + 175c 8800 ASI88xx Audio Adapter + 186f 3001 WR-G303 PCI radio receiver + 186f 3005 WR-G305 PCI radio receiver + 186f 3101 WR-G313 PCI radio receiver + 186f 3105 WR-G315 PCI radio receiver + ac8d PCI 7620 + ac8e PCI7420 CardBus Controller + 1028 018d Inspiron 700m/710m + ac8f PCI7420/7620 SD/MS-Pro Controller + 1028 018d Inspiron 700m/710m + b001 TMS320C6424 + fe00 FireWire Host Controller + fe03 12C01A FireWire Host Controller +104d Sony Corporation + 8004 DTL-H2500 [Playstation development board] + 8009 CXD1947Q i.LINK Controller + 800c DTL-H800 [PS1 sound development board] + 8039 CXD3222 i.LINK Controller + 8047 PS2 TOOL MRP + 8056 Rockwell HCF 56K modem + 808a Memory Stick Controller + 80ff PS2 Performance Analyzer + 814a PS2 Performance Analyzer + 8183 ATHENS [PS3 prototype developer interface card] + 81b0 BM-1 [PSP TOOL Board Management Device] + 81c3 VO-4 [PSP TOOL Video Output Device] + 81ce SxS Pro memory card + 81ff PS3 TOOL MRP + 8200 PS3 TOOL RSX Tracing FPGA + 820e CXD9208GP [PS3 PS2 emulation subsystem adapter] +# 2nd ID + 905c SxS Pro memory card +# 2nd ID + 907f SxS Pro+ memory card + 908f Aeolia ACPI + 909e Aeolia Ethernet Controller (Marvell Yukon 2 Family) + 909f Aeolia SATA AHCI Controller + 90a0 Aeolia SD/MMC Host Controller + 90a1 Aeolia PCI Express Glue and Miscellaneous Devices + 90a2 Aeolia DMA Controller + 90a3 Aeolia Memory (DDR3/SPM) + 90a4 Aeolia USB 3.0 xHCI Host Controller + 90bc SxS Pro+ memory card + 90c8 Belize ACPI + 90c9 Belize Ethernet Controller + 90ca Belize SATA AHCI Controller + 90cb Belize SD/MMC Host Controller + 90cc Belize PCI Express Glue and Miscellaneous Devices + 90cd Belize DMA Controller + 90ce Belize Memory (DDR3/SPM) + 90cf Belize USB 3.0 xHCI Host Controller + 90d7 Baikal ACPI + 90d8 Baikal Ethernet Controller + 90d9 Baikal SATA AHCI Controller + 90da Baikal SD/MMC Host Controller + 90db Baikal PCI Express Glue and Miscellaneous Devices + 90dc Baikal DMA Controller + 90dd Baikal Memory (DDR3/SPM) + 90de Baikal USB 3.0 xHCI Host Controller +104e Oak Technology, Inc + 0017 OTI-64017 + 0107 OTI-107 [Spitfire] + 0109 Video Adapter + 0111 OTI-64111 [Spitfire] + 0217 OTI-64217 + 0317 OTI-64317 +104f Co-time Computer Ltd +1050 Winbond Electronics Corp + 0000 NE2000 + 0001 W83769F + 0033 W89C33D 802.11 a/b/g BB/MAC + 0105 W82C105 + 0840 W89C840 + 1050 0001 W89C840 Ethernet Adapter + 1050 0840 W89C840 Ethernet Adapter + 0940 W89C940 + 5a5a W89C940F + 6692 W6692 + 1043 1702 ISDN Adapter (PCI Bus, D, W) + 1043 1703 ISDN Adapter (PCI Bus, DV, W) + 1043 1707 ISDN Adapter (PCI Bus, DV, W) + 144f 1702 ISDN Adapter (PCI Bus, D, W) + 144f 1703 ISDN Adapter (PCI Bus, DV, W) + 144f 1707 ISDN Adapter (PCI Bus, DV, W) + 9921 W99200F MPEG-1 Video Encoder + 9922 W99200F/W9922PF MPEG-1/2 Video Encoder + 9970 W9970CF +1051 Anigma, Inc. +1052 ?Young Micro Systems +1053 Young Micro Systems +1054 Hitachi, Ltd + 3009 2Gbps Fibre Channel to PCI HBA 3009 + 300a 4Gbps Fibre Channel to PCI-X HBA 300a + 300b 4Gbps Fibre Channel to PCI-X HBA 300b + 300f ColdFusion 3 Chipset Processor to I/O Controller + 3010 ColdFusion 3 Chipset Memory Controller Hub + 3011 ColdFusion 3e Chipset Processor to I/O Controller + 3012 ColdFusion 3e Chipset Memory Controller Hub + 3017 Unassigned Hitachi Shared FC Device 3017 + 301b Virtual VGA Device + 301d PCIe-to-PCIe Bridge with Virtualization IO Assist Feature + 3020 FIVE-EX based Fibre Channel to PCIe HBA + 302c M001 PCI Express Switch Upstream Port + 302d M001 PCI Express Switch Downstream Port + 3070 Hitachi FIVE-FX Fibre Channel to PCIe HBA + 3505 SH7751 PCI Controller (PCIC) + 350e SH7751R PCI Controller (PCIC) +1055 Microchip Technology / SMSC + 9130 SLC90E66 [Victory66] IDE + 9460 SLC90E66 [Victory66] ISA + 9462 SLC90E66 [Victory66] USB + 9463 SLC90E66 [Victory66] ACPI + e420 LAN9420/LAN9420i +1056 ICL +# Motorola made a mistake and used 1507 instead of 1057 in some chips. Please look at the 1507 entry as well when updating this. +1057 Motorola + 0001 MPC105 [Eagle] + 0002 MPC106 [Grackle] + 0003 MPC8240 [Kahlua] + 0004 MPC107 + 0006 MPC8245 [Unity] + 0008 MPC8540 + 0009 MPC8560 + 0012 MPC8548 [PowerQUICC III] + 0100 MC145575 [HFC-PCI] + 0431 KTI829c 100VG + 1073 Nokia N770 + 1219 Nokia N800 + 1801 DSP56301 Digital Signal Processor + 14fb 0101 Transas Radar Imitator Board [RIM] + 14fb 0102 Transas Radar Imitator Board [RIM-2] + 14fb 0202 Transas Radar Integrator Board [RIB-2] + 14fb 0611 1 channel CAN bus Controller [CanPci-1] + 14fb 0612 2 channels CAN bus Controller [CanPci-2] + 14fb 0613 3 channels CAN bus Controller [CanPci-3] + 14fb 0614 4 channels CAN bus Controller [CanPci-4] + 14fb 0621 1 channel CAN bus Controller [CanPci2-1] + 14fb 0622 2 channels CAN bus Controller [CanPci2-2] + 14fb 0810 Transas VTS Radar Integrator Board [RIB-4] + 175c 4200 ASI4215 Audio Adapter + 175c 4300 ASI43xx Audio Adapter + 175c 4400 ASI4401 Audio Adapter + ecc0 0010 Darla + ecc0 0020 Gina + ecc0 0030 Layla rev.0 + ecc0 0031 Layla rev.1 + ecc0 0040 Darla24 rev.0 + ecc0 0041 Darla24 rev.1 + ecc0 0050 Gina24 rev.0 + ecc0 0051 Gina24 rev.1 + ecc0 0070 Mona rev.0 + ecc0 0071 Mona rev.1 + ecc0 0072 Mona rev.2 + 18c0 MPC8265A/8266/8272 + 18c1 MPC8271/MPC8272 + 3052 SM56 Data Fax Modem + 3410 DSP56361 Digital Signal Processor + ecc0 0050 Gina24 rev.0 + ecc0 0051 Gina24 rev.1 + ecc0 0060 Layla24 + ecc0 0070 Mona rev.0 + ecc0 0071 Mona rev.1 + ecc0 0072 Mona rev.2 + ecc0 0080 Mia rev.0 + ecc0 0081 Mia rev.1 + ecc0 0090 Indigo + ecc0 00a0 Indigo IO + ecc0 00b0 Indigo DJ + ecc0 0100 3G + 4801 Raven + 4802 Falcon + 4803 Hawk + 4806 CPX8216 + 4d68 20268 + 5600 SM56 PCI Modem + 1057 0300 SM56 PCI Speakerphone Modem + 1057 0301 SM56 PCI Voice Modem + 1057 0302 SM56 PCI Fax Modem + 1057 5600 SM56 PCI Voice modem + 13d2 0300 SM56 PCI Speakerphone Modem + 13d2 0301 SM56 PCI Voice modem + 13d2 0302 SM56 PCI Fax Modem + 1436 0300 SM56 PCI Speakerphone Modem + 1436 0301 SM56 PCI Voice modem + 1436 0302 SM56 PCI Fax Modem + 144f 100c SM56 PCI Fax Modem + 1494 0300 SM56 PCI Speakerphone Modem + 1494 0301 SM56 PCI Voice modem + 14c8 0300 SM56 PCI Speakerphone Modem + 14c8 0302 SM56 PCI Fax Modem + 1668 0300 SM56 PCI Speakerphone Modem + 1668 0302 SM56 PCI Fax Modem + 5608 Wildcard X100P + 5803 MPC5200 + 5806 MCF54 Coldfire + 5808 MPC8220 + 5809 MPC5200B + 6400 MPC190 Security Processor (S1 family, encryption) + 6405 MPC184 Security Processor (S1 family) +1058 Electronics & Telecommunications RSH +1059 Kontron +105a Promise Technology, Inc. + 0d30 PDC20265 (FastTrak100 Lite/Ultra100) + 1043 8042 AV7266-E South Bridge Promise RAID + 105a 4d33 Ultra100 + 0d38 20263 + 105a 4d39 Fasttrak66 + 1275 20275 + 3318 PDC20318 (SATA150 TX4) + 3319 PDC20319 (FastTrak S150 TX4) + 105a 3319 FastTrak S150 TX4 4 port SATA PCI board + 8086 3427 S875WP1-E mainboard + 3371 PDC20371 (FastTrak S150 TX2plus) + 3373 PDC20378 (FastTrak 378/SATA 378) + 1043 80f5 K8V Deluxe/PC-DL Deluxe motherboard + 1462 590d KT6 Delta-FIS2R (MS-6590) + 1462 702e K8T NEO FIS2R motherboard + 3375 PDC20375 (SATA150 TX2plus) + 3376 PDC20376 (FastTrak 376) + 1043 809e A7V8X motherboard + 3515 PDC40719 [FastTrak TX4300/TX4310] + 3519 PDC40519 (FastTrak TX4200) + 3570 PDC20771 [FastTrak TX2300] + 3571 PDC20571 (FastTrak TX2200) + 3574 PDC20579 SATAII 150 IDE Controller + 3577 PDC40779 (SATA 300 779) + 3d17 PDC40718 (SATA 300 TX4) + 3d18 PDC20518/PDC40518 (SATAII 150 TX4) + 3d73 PDC40775 (SATA 300 TX2plus) + 3d75 PDC20575 (SATAII150 TX2plus) + 3f20 PDC42819 [FastTrak TX2650/TX4650] + 4302 80333 [SuperTrak EX4350] + 4d30 PDC20267 (FastTrak100/Ultra100) + 105a 4d33 Ultra100 + 105a 4d39 FastTrak100 + 8086 5744 S845WD1-E mainboard + 4d33 20246 + 105a 4d33 20246 IDE Controller + 4d38 PDC20262 (FastTrak66/Ultra66) + 105a 4d30 Ultra Device on SuperTrak + 105a 4d33 Ultra66 + 105a 4d39 FastTrak66 + 4d68 PDC20268 [Ultra100 TX2] + 105a 4d68 Ultra100 TX2 + 4d69 20269 + 105a 4d68 Ultra133TX2 + 5275 PDC20276 (MBFastTrak133 Lite) + 1043 807e A7V333 motherboard. + 105a 0275 SuperTrak SX6000 IDE + 105a 1275 MBFastTrak133 Lite (tm) Controller (RAID mode) + 1458 b001 MBUltra 133 + 5300 DC5300 + 6268 PDC20270 (FastTrak100 LP/TX2/TX4) + 105a 4d68 FastTrak100 TX2 + 6269 PDC20271 (FastTrak TX2000) + 105a 6269 FastTrak TX2/TX2000 + 6300 PDC81731 [FastTrak SX8300] + 6621 PDC20621 (FastTrak S150 SX4/FastTrak SX4000 lite) + 6622 PDC20621 [SATA150 SX4] 4 Channel IDE RAID Controller + 6624 PDC20621 [FastTrak SX4100] + 6626 PDC20618 (Ultra 618) + 6629 PDC20619 (FastTrak TX4000) + 7275 PDC20277 (SBFastTrak133 Lite) + 8002 SATAII150 SX8 + 8350 80333 [SuperTrak EX8350/EX16350], 80331 [SuperTrak EX8300/EX16300] + 8650 81384 [SuperTrak EX SAS and SATA RAID Controller] + 105a 4600 SuperTrak EX4650A + 105a 4601 SuperTrak EX4650 + 105a 4610 SuperTrak EX4650EL + 105a 8600 SuperTrak EX8650EL + 105a 8601 SuperTrak EX8650A + 105a 8602 SuperTrak EX8654 + 105a 8603 SuperTrak EX8658 + 105a 8604 SuperTrak EX8650 + 105a 8610 SuperTrak EX8650M + 105a a600 SuperTrak EX12650 + 105a b600 SuperTrak EX16650 + 105a b601 SuperTrak EX16654 + 105a b602 SuperTrak EX16658 + 8760 PM8010 [SuperTrak EX SAS and SATA 6G RAID Controller] + c350 80333 [SuperTrak EX12350] + e350 80333 [SuperTrak EX24350] +105b Foxconn International, Inc. +105c Wipro Infotech Limited +105d Number 9 Computer Company + 2309 Imagine 128 + 2339 Imagine 128-II + 105d 0000 Imagine 128 series 2 4Mb VRAM + 105d 0001 Imagine 128 series 2 4Mb VRAM + 105d 0002 Imagine 128 series 2 4Mb VRAM + 105d 0003 Imagine 128 series 2 4Mb VRAM + 105d 0004 Imagine 128 series 2 4Mb VRAM + 105d 0005 Imagine 128 series 2 4Mb VRAM + 105d 0006 Imagine 128 series 2 4Mb VRAM + 105d 0007 Imagine 128 series 2 4Mb VRAM + 105d 0008 Imagine 128 series 2e 4Mb DRAM + 105d 0009 Imagine 128 series 2e 4Mb DRAM + 105d 000a Imagine 128 series 2 8Mb VRAM + 105d 000b Imagine 128 series 2 8Mb H-VRAM + 11a4 000a Barco Metheus 5 Megapixel + 13cc 0000 Barco Metheus 5 Megapixel + 13cc 0004 Barco Metheus 5 Megapixel + 13cc 0005 Barco Metheus 5 Megapixel + 13cc 0006 Barco Metheus 5 Megapixel + 13cc 0008 Barco Metheus 5 Megapixel + 13cc 0009 Barco Metheus 5 Megapixel + 13cc 000a Barco Metheus 5 Megapixel + 13cc 000c Barco Metheus 5 Megapixel + 493d Imagine 128 T2R [Ticket to Ride] + 11a4 000a Barco Metheus 5 Megapixel, Dual Head + 11a4 000b Barco Metheus 5 Megapixel, Dual Head + 13cc 0002 Barco Metheus 4 Megapixel, Dual Head + 13cc 0003 Barco Metheus 5 Megapixel, Dual Head + 13cc 0007 Barco Metheus 5 Megapixel, Dual Head + 13cc 0008 Barco Metheus 5 Megapixel, Dual Head + 13cc 0009 Barco Metheus 5 Megapixel, Dual Head + 13cc 000a Barco Metheus 5 Megapixel, Dual Head + 5348 Revolution 4 + 105d 0037 Revolution IV-FP AGP (For SGI 1600SW) + 11a4 0028 PVS5600M + 11a4 0038 PVS5600D +105e Vtech Computers Ltd +105f Infotronic America Inc +1060 United Microelectronics [UMC] + 0001 UM82C881 + 0002 UM82C886 + 0101 UM8673F + 0881 UM8881 + 0886 UM8886F + 0891 UM8891A + 1001 UM886A + 673a UM8886BF + 673b EIDE Master/DMA + 8710 UM8710 + 886a UM8886A + 8881 UM8881F + 8886 UM8886F + 888a UM8886A + 8891 UM8891A + 9017 UM9017F + 9018 UM9018 + 9026 UM9026 + e881 UM8881N + e886 UM8886N + e88a UM8886N + e891 UM8891N +1061 I.I.T. + 0001 AGX016 + 0002 IIT3204/3501 +1062 Maspar Computer Corp +1063 Ocean Office Automation +1064 Alcatel + 1102 Dynamite 2840 (ADSL PCI modem) +1065 Texas Microsystems +1066 PicoPower Technology + 0000 PT80C826 + 0001 PT86C521 [Vesuvius v1] Host Bridge + 0002 PT86C523 [Vesuvius v3] PCI-ISA Bridge Master + 0003 PT86C524 [Nile] PCI-to-PCI Bridge + 0004 PT86C525 [Nile-II] PCI-to-PCI Bridge + 0005 National PC87550 System Controller + 8002 PT86C523 [Vesuvius v3] PCI-ISA Bridge Slave +1067 Mitsubishi Electric + 0301 AccelGraphics AccelECLIPSE + 0304 AccelGALAXY A2100 [OEM Evans & Sutherland] + 0308 Tornado 3000 [OEM Evans & Sutherland] + 1002 VG500 [VolumePro Volume Rendering Accelerator] +1068 Diversified Technology +1069 Mylex Corporation + 0001 DAC960P + 0002 DAC960PD + 0010 DAC960PG + 0020 DAC960LA + 0050 AcceleRAID 352/170/160 support Device + 1069 0050 AcceleRAID 352 support Device + 1069 0052 AcceleRAID 170 support Device + 1069 0054 AcceleRAID 160 support Device + b166 AcceleRAID 600/500/400/Sapphire support Device + 1014 0242 iSeries 2872 DASD IOA + 1014 0266 Dual Channel PCI-X U320 SCSI Adapter + 1014 0278 Dual Channel PCI-X U320 SCSI RAID Adapter + 1014 02d3 Dual Channel PCI-X U320 SCSI Adapter + 1014 02d4 Dual Channel PCI-X U320 SCSI RAID Adapter + 1069 0200 AcceleRAID 400, Single Channel, PCI-X, U320, SCSI RAID + 1069 0202 AcceleRAID Sapphire, Dual Channel, PCI-X, U320, SCSI RAID + 1069 0204 AcceleRAID 500, Dual Channel, Low-Profile, PCI-X, U320, SCSI RAID + 1069 0206 AcceleRAID 600, Dual Channel, PCI-X, U320, SCSI RAID + ba55 eXtremeRAID 1100 support Device + ba56 eXtremeRAID 2000/3000 support Device + 1069 0030 eXtremeRAID 3000 support Device + 1069 0040 eXtremeRAID 2000 support Device + ba57 eXtremeRAID 4000/5000 support Device + 1069 0072 eXtremeRAID 5000 support Device +106a Aten Research Inc +106b Apple Inc. + 0001 Bandit PowerPC host bridge + 0002 Grand Central I/O + 0003 Control Video + 0004 PlanB Video-In + 0007 O'Hare I/O + 000c DOS on Mac + 000e Hydra Mac I/O + 0010 Heathrow Mac I/O + 0017 Paddington Mac I/O + 0018 UniNorth FireWire + 0019 KeyLargo USB + 001e UniNorth Internal PCI + 001f UniNorth PCI + 0020 UniNorth AGP + 0021 UniNorth GMAC (Sun GEM) + 0022 KeyLargo Mac I/O + 0024 UniNorth/Pangea GMAC (Sun GEM) + 0025 KeyLargo/Pangea Mac I/O + 0026 KeyLargo/Pangea USB + 0027 UniNorth/Pangea AGP + 0028 UniNorth/Pangea PCI + 0029 UniNorth/Pangea Internal PCI + 002d UniNorth 1.5 AGP + 002e UniNorth 1.5 PCI + 002f UniNorth 1.5 Internal PCI + 0030 UniNorth/Pangea FireWire + 0031 UniNorth 2 FireWire + 106b 5811 iBook G4 2004 + 0032 UniNorth 2 GMAC (Sun GEM) + 0033 UniNorth 2 ATA/100 + 0034 UniNorth 2 AGP + 0035 UniNorth 2 PCI + 0036 UniNorth 2 Internal PCI + 003b UniNorth/Intrepid ATA/100 + 003e KeyLargo/Intrepid Mac I/O + 003f KeyLargo/Intrepid USB + 1af4 1100 QEMU Virtual Machine + 0040 K2 KeyLargo USB + 0041 K2 KeyLargo Mac/IO + 0042 K2 FireWire + 0043 K2 ATA/100 + 0045 K2 HT-PCI Bridge + 0046 K2 HT-PCI Bridge + 0047 K2 HT-PCI Bridge + 0048 K2 HT-PCI Bridge + 0049 K2 HT-PCI Bridge + 004a CPC945 HT Bridge + 004b U3 AGP + 004c K2 GMAC (Sun GEM) + 004f Shasta Mac I/O + 0050 Shasta IDE + 0051 Shasta (Sun GEM) + 0052 Shasta Firewire + 0053 Shasta PCI Bridge + 0054 Shasta PCI Bridge + 0055 Shasta PCI Bridge + 0056 U4 PCIe + 0057 U3 HT Bridge + 0058 U3L AGP Bridge + 0059 U3H AGP Bridge + 005b CPC945 PCIe Bridge + 0066 Intrepid2 AGP Bridge + 0067 Intrepid2 PCI Bridge + 0068 Intrepid2 PCI Bridge + 0069 Intrepid2 ATA/100 + 006a Intrepid2 Firewire + 006b Intrepid2 GMAC (Sun GEM) + 0074 U4 HT Bridge +# should be 14e4:1645 + 1645 Broadcom NetXtreme BCM5701 Gigabit Ethernet + 1801 T2 Bridge Controller + 1802 T2 Secure Enclave Processor + 1803 Apple Audio Device + 2001 S1X NVMe Controller + 2002 S3ELab NVMe Controller + 2003 S3X NVMe Controller + 2005 ANS2 NVMe Controller +106c Hynix Semiconductor + 8139 8139c 100BaseTX Ethernet Controller + 8801 Dual Pentium ISA/PCI Motherboard + 8802 PowerPC ISA/PCI Motherboard + 8803 Dual Window Graphics Accelerator + 8804 LAN Controller + 8805 100-BaseT LAN +106d Sequent Computer Systems +106e DFI, Inc +106f City Gate Development Ltd +1070 Daewoo Telecom Ltd +1071 Mitac + 8160 Mitac 8060B Mobile Platform +1072 GIT Co Ltd +1073 Yamaha Corporation + 0001 3D GUI Accelerator + 0002 YGV615 [RPA3 3D-Graphics Controller] + 0003 YMF-740 + 0004 YMF-724 + 1073 0004 YMF724-Based PCI Audio Adapter + 0005 DS1 Audio + 1073 0005 DS-XG PCI Audio CODEC + 0006 DS1 Audio + 0008 DS1 Audio + 1073 0008 DS-XG PCI Audio CODEC + 000a DS1L Audio + 1073 0004 DS-XG PCI Audio CODEC + 1073 000a DS-XG PCI Audio CODEC + 8086 4d55 DS-XG PCI Audio CODEC [Intel MU440EX] + 000c YMF-740C [DS-1L Audio Controller] + 107a 000c DS-XG PCI Audio CODEC + 000d YMF-724F [DS-1 Audio Controller] + 1073 000d DS-XG PCI Audio CODEC + 0010 YMF-744B [DS-1S Audio Controller] + 1073 0006 DS-XG PCI Audio CODEC + 1073 0010 DS-XG PCI Audio CODEC + 0012 YMF-754 [DS-1E Audio Controller] + 1073 0012 DS-XG PCI Audio Codec + 0020 DS-1 Audio + 1000 SW1000XG [XG Factory] + 2000 DS2416 Digital Mixing Card + 1073 2000 DS2416 Digital Mixing Card +1074 NexGen Microsystems + 4e78 82c500/1 +1075 Advanced Integrations Research +1076 Chaintech Computer Co. Ltd +1077 QLogic Corp. + 1016 ISP10160 Single Channel Ultra3 SCSI Processor + 1020 ISP1020 Fast-wide SCSI + 1022 ISP1022 Fast-wide SCSI + 1080 ISP1080 SCSI Host Adapter + 1216 ISP12160 Dual Channel Ultra3 SCSI Processor + 101e 8471 QLA12160 on AMI MegaRAID + 101e 8493 QLA12160 on AMI MegaRAID + 1240 ISP1240 SCSI Host Adapter + 1280 ISP1280 SCSI Host Adapter + 1634 FastLinQ QL45000 Series 40GbE Controller + 1077 e4f1 FastLinQ QL45212H 40GbE Adapter + 1077 e4f2 FastLinQ QL45211H 40GbE Adapter + 1077 e4f3 FastLinQ QL45412H 40GbE Adapter + 1077 e4f4 FastLinQ QL45411H 40GbE Adapter + 1644 FastLinQ QL45000 Series 100GbE Controller + 1077 e4f8 FastLinQ QL45611H 100GbE Adapter + 1654 FastLinQ QL45000 Series 50GbE Controller + 1077 0032 QL45212 Flex 50Gb 2-port Ethernet Adapter + 1590 0223 Synergy 6810C 25/50Gb Ethernet Adapter + 1590 0287 Synergy 6820C 25/50Gb CNA + 1656 FastLinQ QL45000 Series 25GbE Controller + 1077 0033 QL45214 Flex 25Gb 4-port Ethernet Adapter + 1077 02a7 QL45212-DE 25GbE Adapter + 1077 e4f6 FastLinQ QL45211H 25GbE Adapter + 1077 e4f7 FastLinQ QL45212H 25GbE Adapter + 1590 0245 10/20/25GbE 2P 4820c CNA + 165c FastLinQ QL45000 Series 10/25/40/50GbE Controller (FCoE) + 1077 0034 QL45262 Flex 50Gb 2-port Ethernet Adapter w/ iSCSI/FCoE + 1077 e4f1 FastLinQ QL45462H 40GbE FCoE Adapter + 1077 e4f2 FastLinQ QL45461H 40GbE FCoE Adapter + 1590 0245 10/20/25GbE 2P 4820c CNA FCoE + 165e FastLinQ QL45000 Series 10/25/40/50GbE Controller (iSCSI) + 1077 0034 QL45262 Flex 50Gb 2-port Ethernet Adapter w/ iSCSI/FCoE + 1077 e4f1 FastLinQ QL45462H 40GbE iSCSI Adapter + 1077 e4f2 FastLinQ QL45461H 40GbE iSCSI Adapter + 1590 0245 10/20/25GbE 2P 4820c CNA iSCSI + 1664 FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF) + 1077 e4f1 FastLinQ QL45462H 40GbE Adapter (SR-IOV VF) + 1077 e4f2 FastLinQ QL45461H 40GbE Adapter (SR-IOV VF) + 1077 e4f3 FastLinQ QL45412H 40GbE Adapter (SR-IOV VF) + 1077 e4f4 FastLinQ QL45411H 40GbE Adapter (SR-IOV VF) + 1077 e4f6 FastLinQ QL45211H 25GbE Adapter (SR-IOV VF) + 1077 e4f7 FastLinQ QL45212H 25GbE Adapter (SR-IOV VF) + 1077 e4f8 FastLinQ QL45611H 100GbE Adapter (SR-IOV VF) + 1590 0245 10/20/25GbE 2P 4820c CNA SRIOV + 2020 ISP2020A Fast!SCSI Basic Adapter + 2031 ISP8324-based 16Gb Fibre Channel to PCI Express Adapter + 103c 17e7 SN1000Q 16Gb Single Port Fibre Channel Adapter + 103c 17e8 SN1000Q 16Gb Dual Port Fibre Channel Adapter + 103c 1939 QMH2672 16Gb Dual Port Fibre Channel Adapter + 103c 8002 3830C 16G Fibre Channel Host Bus Adapter + 2071 ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter + 1077 0283 QLE2764 Quad Port 32Gb Fibre Channel to PCIe Adapter + 1077 029e QLE2694 Quad Port 16Gb Fibre Channel to PCIe Adapter + 1077 02a2 QLE2694L Quad Port 16Gb Fibre Channel to PCIe Adapter + 1077 02ad QLE2694U Quad Port 16/32Gb Fibre Channel to PCIe Adapter + 2081 ISP2814-based 64/32G Fibre Channel to PCIe Controller + 1077 02e1 QLE2874 Quad Port 64GFC PCIe Gen4 x16 Adapter + 1077 02e3 QLE2774 Quad Port 32GFC PCIe Gen4 x16 Adapter + 2100 QLA2100 64-bit Fibre Channel Adapter + 1077 0001 QLA2100 64-bit Fibre Channel Adapter + 2200 QLA2200 64-bit Fibre Channel Adapter + 1077 0002 QLA2200 + 2261 ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter + 1077 0299 QLE2740 Single Port 32Gb Fibre Channel to PCIe Adapter + 1077 029a QLE2742 Dual Port 32Gb Fibre Channel to PCIe Adapter + 1077 029b QLE2690 Single Port 16Gb Fibre Channel to PCIe Adapter + 1077 029c QLE2692 Dual Port 16Gb Fibre Channel to PCIe Adapter + 1077 02a7 QLE2690 Single Port 16Gb FC to PCIe Gen3 x8 Adapter + 1077 02a8 QLE2692 Dual Port 16Gb FC to PCIe Gen3 x8 Adapter + 1077 02ab QLE2740 Single Port 32Gb FC to PCIe Gen3 x8 Adapter + 1077 02ac QLE2742 Dual Port 32Gb FC to PCIe Gen3 x8 Adapter + 1077 02b8 2x16Gb QME2692 FC HBA + 1077 02b9 2x32Gb QME2742 FC HBA + 1590 00f9 StoreFabric SN1100Q 16Gb Single Port Fibre Channel Host Bus Adapter + 1590 00fa StoreFabric SN1100Q 16Gb Dual Port Fibre Channel Host Bus Adapter + 1590 0203 StoreFabric SN1600Q 32Gb Single Port Fibre Channel Host Bus Adapter + 1590 0204 StoreFabric SN1600Q 32Gb Dual Port Fibre Channel Host Bus Adapter + 1590 022d 5830C 32Gb Dual Port Fibre Channel Adapter + 2281 ISP2812-based 64/32G Fibre Channel to PCIe Controller + 1077 02e2 QLE2872 Dual Port 64GFC PCIe Gen4 x8 Adapter + 1077 02e4 QLE2772 Dual Port 32GFC PCIe Gen4 x8 Adapter + 1077 02ee QLE2870 Single Port 64GFC PCIe Gen4 x8 Adapter + 1077 02f0 QLE2770 Single Port 32GFC PCIe Gen4 x8 Adapter + 1590 02d3 SN1610Q - 1P Enhanced 32GFC Single Port Fibre Channel Host Bus Adapter + 1590 02d4 SN1610Q – 2P Enhanced 32GFC Dual Port Fibre Channel Host Bus Adapter + 2300 QLA2300 64-bit Fibre Channel Adapter + 2312 ISP2312-based 2Gb Fibre Channel to PCI-X HBA + 103c 0131 2Gb Fibre Channel - Single port [A7538A] + 103c 12ba 2Gb Fibre Channel - Dual port [A6826A] + 2322 ISP2322-based 2Gb Fibre Channel to PCI-X HBA + 2422 ISP2422-based 4Gb Fibre Channel to PCI-X HBA + 103c 12d7 4Gb Fibre Channel [AB379A] + 103c 12dd 4Gb Fibre Channel [AB429A] + 2432 ISP2432-based 4Gb Fibre Channel to PCI Express HBA + 103c 7040 FC1142SR 4Gb 1-port PCIe Fibre Channel Host Bus Adapter [HPAE311A] + 1077 0137 QLE2460 4 GB PCI-X Host-Bus-Adapter + 2532 ISP2532-based 8Gb Fibre Channel to PCI Express HBA + 1014 041e FC EN0Y/EN12 PCIe2 LP 8 Gb 4-port Fibre Channel Adapter for POWER + 103c 3262 StorageWorks 81Q + 103c 3263 StorageWorks 82Q + 1077 015c QLE2560 PCI Express to 8Gb FC Single Channel + 1077 015d QLE2562 PCI Express to 8Gb FC Dual Channel + 1077 015e QLE2564 PCI Express to 8Gb FC Quad Channel + 1077 0167 QME2572 Dual Port FC8 HBA Mezzanine + 1590 00fc StoreFabric 84Q 8Gb Quad Port Fibre Channel Host Bus Adapter + 2971 ISP2684 + 3022 ISP4022-based Ethernet NIC + 3032 ISP4032-based Ethernet IPv6 NIC + 4010 ISP4010-based iSCSI TOE HBA + 4022 ISP4022-based iSCSI TOE HBA + 4032 ISP4032-based iSCSI TOE IPv6 HBA + 5432 SP232-based 4Gb Fibre Channel to PCI Express HBA + 6312 SP202-based 2Gb Fibre Channel to PCI-X HBA + 6322 SP212-based 2Gb Fibre Channel to PCI-X HBA + 7220 IBA7220 InfiniBand HCA + 7322 IBA7322 QDR InfiniBand HCA + 8000 10GbE Converged Network Adapter (TCP/IP Networking) + 8001 10GbE Converged Network Adapter (FCoE) + 1014 03af FC 5708/5270 10 Gb FCoE PCIe Dual Port Adapter for POWER + 8020 cLOM8214 1/10GbE Controller + 1028 1f64 QMD8262-k 10G DP bNDC KR + 103c 3346 CN1000Q Dual Port Converged Network Adapter + 103c 3733 NC523SFP 10Gb 2-port Server Adapter + 1077 0203 8200 Series Single Port 10GbE Converged Network Adapter (TCP/IP Networking) + 1077 0207 8200 Series Dual Port 10GbE Converged Network Adapter (TCP/IP Networking) + 1077 020b 3200 Series Dual Port 10Gb Intelligent Ethernet Adapter + 1077 020c 3200 Series Quad Port 1Gb Intelligent Ethernet Adapter + 1077 020f 3200 Series Single Port 10Gb Intelligent Ethernet Adapter + 1077 0210 QME8242-k 10GbE Dual Port Mezzanine Card + 1077 0233 QME8262-k 10GbE Dual Port Mezzanine Card + 8021 8200 Series 10GbE Converged Network Adapter (FCoE) + 103c 3348 CN1000Q Dual Port Converged Network Adapter + 1077 0211 QME8242-k 10GbE Dual Port Mezzanine Card, FCoE + 8022 8200 Series 10GbE Converged Network Adapter (iSCSI) + 103c 3347 CN1000Q Dual Port Converged Network Adapter + 1077 0212 QME8242-k 10GbE Dual Port Mezzanine Card, iSCSI + 8030 ISP8324 1/10GbE Converged Network Controller + 1077 0243 8300 Series Single Port 10GbE Converged Network Adapter (TCP/IP Networking) + 1077 0246 8300 Series Dual Port 10GbE Converged Network Adapter (TCP/IP Networking) + 8031 8300 Series 10GbE Converged Network Adapter (FCoE) + 8032 8300 Series 10GbE Converged Network Adapter (iSCSI) + 8070 FastLinQ QL41000 Series 10/25/40/50GbE Controller + 1077 0001 10GE 2P QL41162HxRJ-DE Adapter + 1077 0002 10GE 2P QL41112HxCU-DE Adapter + 1077 0004 4x10GE QL41164HFCU CNA + 1077 0005 QLogic 4x10GE QL41164HMRJ CNA + 1077 0006 QLogic 4x10GE QL41164HMCU CNA + 1077 0007 QLogic 2x1GE+2x10GE QL41264HMCU CNA + 1077 0009 QLogic 2x1GE+2x10GE QL41162HMRJ CNA + 1077 000b 25GE 2P QL41262HxCU-DE Adapter + 1077 000f 2x25GE QL41262HMKR CNA + 1077 0010 2x25GE QL41232HMKR NIC + 1077 0011 FastLinQ QL41212HLCU 25GbE Adapter + 1077 0012 FastLinQ QL41112H 10GbE Adapter + 1077 0019 QL41232HOCU - Dual Port 25/10GbE SFP28 OCP Adapter + 1077 0039 QLogic QL41262 PCIe 25Gb 2-Port SFP28 Ethernet Adapter + 1077 0053 QLogic 2x25GE QL41232HQCU NIC + 1077 0054 2x10GE QL41132HQRJ NIC + 1077 0055 QLogic 2x10GE QL41132HQCU NIC + 1077 0056 2x10GE QL41132HxRJ NIC + 1077 0057 2x25GE QL41232HxCU NIC + 1077 0068 10GbE 2p SFP+ QL41132HLCU-HC Adapter + 1077 0069 10GbE 2p BASE-T QL41132HQRJ-HC OCP3 Adapter + 1077 0070 10GbE 2p BASE-T QL41132HLRJ-HC Adapter + 1077 0071 10GbE 2p SFP+ QL41132HQCU-HC OCP3 Adapter + 1077 0072 10GbE 4p SFP+ QL41134HLCU-HC Adapter + 1077 0073 10/25GbE 2p SFP28 QL41232HQCU-HC OCP3 Adapter + 1077 0074 10/25GbE 2p SFP28 QL41232HLCU-HC Adapter + 1590 021a 10GbE 2P QL41162HLRJ-HP Adapter + 1590 021b 10GbE 2P QL41162HLRJ-HP Adapter + 1590 021d 10/25GbE 2P QL41222HLCU-HP Adapter + 1590 021e 10/25GbE 2P QL41162HMRJ-HP Adapter + 1590 021f 10/25GbE 2P QL41262HMCU-HP Adapter + 1590 0220 10/25GbE 2P QL41122HLRJ-HP Adapter + 1590 02bd 10Gb 2P 524SFP+ NIC + 8080 FastLinQ QL41000 Series 10/25/40/50GbE Controller (FCoE) + 1077 0001 10GE 2P QL41162HxRJ-DE Adapter + 1077 0002 10GE 2P QL41112HxCU-DE Adapter + 1077 0004 4x10GE QL41164HFCU CNA + 1077 0005 QLogic 4x10GE QL41164HMRJ CNA + 1077 0006 QLogic 4x10GE QL41164HMCU CNA + 1077 0007 QLogic 2x1GE+2x10GE QL41264HMCU CNA + 1077 0009 QLogic 2x1GE+2x10GE QL41162HMRJ CNA + 1077 000b 25GE 2P QL41262HxCU-DE Adapter + 1077 000c QLogic 2x25GE QL41262HMCU CNA + 1077 000d FastLinQ QL41262H 25GbE FCoE Adapter + 1077 000e FastLinQ QL41162H 10GbE FCoE Adapter + 1077 000f 2x25GE QL41262HMKR CNA + 1590 021a 10GbE 2P QL41162HLRJ-HP Adapter + 1590 021b 10GbE 2P QL41162HLRJ-HP Adapter + 8084 FastLinQ QL41000 Series 10/25/40/50GbE Controller (iSCSI) + 1077 0001 10GE 2P QL41162HxRJ-DE Adapter + 1077 0002 10GE 2P QL41112HxCU-DE Adapter + 1077 0003 4x10GE QL41164HxRJ CNA + 1077 0004 4x10GE QL41164HFCU CNA + 1077 0005 QLogic 4x10GE QL41164HMRJ CNA + 1077 0006 QLogic 4x10GE QL41164HMCU CNA + 1077 0007 QLogic 2x25GE QL41262HMCU CNA + 1077 0009 QLogic 2x1GE+2x10GE QL41162HMRJ CNA + 1077 000b 25GE 2P QL41262HxCU-DE Adapter + 1077 000c QLogic 2x25GE QL41262HMCU CNA + 1077 000d FastLinQ QL41262H 25GbE iSCSI Adapter + 1077 000e FastLinQ QL41162H 10GbE iSCSI Adapter + 1077 000f 2x25GE QL41262HMKR CNA + 1590 021a 10GbE 2P QL41162HLRJ-HP Adapter + 1590 021b 10GbE 2P QL41162HLRJ-HP Adapter + 8090 FastLinQ QL41000 Series Gigabit Ethernet Controller (SR-IOV VF) + 1077 0001 25GE 2P QL41262HxCU-DE Adapter + 1077 0002 10GE 2P QL41112HxCU-DE Adapter + 1077 0003 4x10GE QL41164HxRJ CNA + 1077 0004 4x10GE QL41164HFCU CNA + 1077 0005 QLogic 4x10GE QL41164HMRJ CNA + 1077 0006 QLogic 4x10GE QL41164HMCU CNA + 1077 0007 QLogic 2x1GE+2x10GE QL41264HMCU CNA + 1077 0009 QLogic 2x1GE+2x10GE QL41162HMRJ CNA + 1077 000b 25GE 2P QL41262HxCU-DE Adapter + 1077 000c QLogic 2x25GE QL41262HMCU CNA + 1077 000d FastLinQ QL41262H 25GbE FCoE Adapter (SR-IOV VF) + 1077 000e FastLinQ QL41162H 10GbE iSCSI Adapter (SR-IOV VF) + 1077 000f 2x25GE QL41262HMKR CNA + 1077 0010 2x25GE QL41232HMKR NIC + 1077 0011 FastLinQ QL41212H 25GbE Adapter (SR-IOV VF) + 1077 0012 FastLinQ QL41112H 10GbE Adapter (SR-IOV VF) + 1077 0053 QLogic 2x25GE QL41232HQCU NIC + 1077 0054 QLogic 2x10GE QL41132HQRJ NIC + 1077 0055 QLogic 2x10GE QL41132HQCU NIC + 1077 0056 2x10GE QL41132HxRJ NIC + 1077 0057 2x25GE QL41232HxCU NIC + 1590 021a 10GbE 2P QL41162HLRJ-HP Adapter + 1590 021b 10GbE 2P QL41162HLRJ-HP Adapter + 1590 021e 10/25GbE 2P QL41162HMRJ-HP Adapter + 1590 021f 10/25GbE 2P QL41262HMCU-HP Adapter + 1590 02bd 10Gb 2P 524SFP+ NIC + 8430 ISP8324 1/10GbE Converged Network Controller (NIC VF) + 8431 8300 Series 10GbE Converged Network Adapter (FCoE VF) + 8432 ISP2432M-based 10GbE Converged Network Adapter (CNA) +1078 Cyrix Corporation + 0000 5510 [Grappa] + 0001 PCI Master + 0002 5520 [Cognac] + 0100 5530 Legacy [Kahlua] + 0101 5530 SMI [Kahlua] + 0102 5530 IDE [Kahlua] + 0103 5530 Audio [Kahlua] + 0104 5530 Video [Kahlua] + 0400 ZFMicro PCI Bridge + 0401 ZFMicro Chipset SMI + 0402 ZFMicro Chipset IDE + 0403 ZFMicro Expansion Bus +1079 I-Bus +107a NetWorth +# formerly Gateway 2000 / acquired by Acer Inc. +107b Gateway, Inc. +107c LG Electronics [Lucky Goldstar Co. Ltd] +107d LeadTek Research Inc. + 0000 P86C850 +107e Interphase Corporation + 0001 5515 ATM Adapter [Flipper] + 0002 100 VG AnyLan Controller + 0004 5526 Fibre Channel Host Adapter + 0005 x526 Fibre Channel Host Adapter + 0008 5525/5575 ATM Adapter (155 Mbit) [Atlantic] + 9003 5535-4P-BRI-ST + 9007 5535-4P-BRI-U + 9008 5535-1P-SR + 900c 5535-1P-SR-ST + 900e 5535-1P-SR-U + 9011 5535-1P-PRI + 9013 5535-2P-PRI + 9023 5536-4P-BRI-ST + 9027 5536-4P-BRI-U + 9031 5536-1P-PRI + 9033 5536-2P-PRI +107f Data Technology Corporation + 0802 SL82C105 +1080 Contaq Microsystems + 0600 82C599 + c691 Cypress CY82C691 + c693 82c693 +1081 Supermac Technology + 0d47 Radius PCI to NuBUS Bridge +1082 EFA Corporation of America +1083 Forex Computer Corporation + 0001 FR710 +1084 Parador +1086 J. Bond Computer Systems +1087 Cache Computer +1088 Microcomputer Systems (M) Son +1089 Data General Corporation +# Formerly Bit3 Computer Corp. +108a SBS Technologies + 0001 VME Bridge Model 617 + 0010 VME Bridge Model 618 + 0040 dataBLIZZARD + 3000 VME Bridge Model 2706 +108c Oakleigh Systems Inc. +108d Olicom + 0001 Token-Ring 16/4 PCI Adapter (3136/3137) + 0002 16/4 Token Ring + 0004 RapidFire OC-3139/3140 Token-Ring 16/4 PCI Adapter + 108d 0004 OC-3139/3140 RapidFire Token-Ring 16/4 Adapter + 0005 GoCard 3250 Token-Ring 16/4 CardBus PC Card + 0006 OC-3530 RapidFire Token-Ring 100 + 0007 RapidFire 3141 Token-Ring 16/4 PCI Fiber Adapter + 108d 0007 OC-3141 RapidFire Token-Ring 16/4 Adapter + 0008 RapidFire 3540 HSTR 100/16/4 PCI Adapter + 108d 0008 OC-3540 RapidFire HSTR 100/16/4 Adapter + 0011 OC-2315 + 0012 OC-2325 + 0013 OC-2183/2185 + 0014 OC-2326 + 0019 OC-2327/2250 10/100 Ethernet Adapter + 108d 0016 OC-2327 Rapidfire 10/100 Ethernet Adapter + 108d 0017 OC-2250 GoCard 10/100 Ethernet Adapter + 0021 OC-6151/6152 [RapidFire ATM 155] + 0022 ATM Adapter +108e Oracle/SUN + 0001 EBUS + 1000 EBUS + 1001 Happy Meal 10/100 Ethernet [hme] + 1100 RIO EBUS + 108e 1100 RIO EBUS on Blade 100 motherboard + 1101 RIO 10/100 Ethernet [eri] + 108e 1101 RIO GEM on Blade 100 motherboard + 1102 RIO 1394 + 108e 1102 RIO 1394 on Blade 100 motherboard + 1103 RIO USB + 108e 1103 RIO USB on Blade 100 motherboard + 1647 Broadcom 570x 10/100/1000 Ethernet [bge] + 1648 Broadcom 570x 10/100/1000 Ethernet [bge] + 16a7 Broadcom 570x 10/100/1000 Ethernet [bge] + 16a8 Broadcom 570x 10/100/1000 Ethernet [bge] + 2bad GEM 10/100/1000 Ethernet [ge] + 5000 Simba Advanced PCI Bridge + 108e 5000 Netra AX1105-500 + 5043 SunPCI Co-processor + 5ca0 Crypto Accelerator 6000 [mca] + 6300 Intel 21554 PCI-PCI bus bridge [db21554] + 6301 Intel 21554 PCI-PCI bus bridge [db21554] + 6302 Intel 21554 PCI-PCI bus bridge [db21554] + 6303 Intel 21554 PCI-PCI bus bridge [db21554] + 6310 Intel 21554 PCI-PCI bus bridge [db21554] + 6311 Intel 21554 PCI-PCI bus bridge [db21554] + 6312 Intel 21554 PCI-PCI bus bridge [db21554] + 6313 Intel 21554 PCI-PCI bus bridge [db21554] + 6320 Intel 21554 PCI-PCI bus bridge [db21554] + 6323 Intel 21554 PCI-PCI bus bridge [db21554] + 6330 Intel 21554 PCI-PCI bus bridge [db21554] + 6331 Intel 21554 PCI-PCI bus bridge [db21554] + 6332 Intel 21554 PCI-PCI bus bridge [db21554] + 6333 Intel 21554 PCI-PCI bus bridge [db21554] + 6340 Intel 21554 PCI-PCI bus bridge [db21554] + 6343 Intel 21554 PCI-PCI bus bridge [db21554] + 6350 Intel 21554 PCI-PCI bus bridge [db21554] + 6353 Intel 21554 PCI-PCI bus bridge [db21554] + 6722 Intel 21554 PCI-PCI bus bridge [db21554] + 676e SunPCiIII + 7063 SunPCiII / SunPCiIIpro + 8000 Psycho PCI Bus Module + 8001 Schizo PCI Bus Module + 8002 Schizo+ PCI Bus Module + 80f0 PCIe switch [px] + 80f8 PCIe switch [px] + 9010 PCIe/PCI bridge switch [pxb_plx] + 9020 PCIe/PCI bridge switch [pxb_plx] + 9102 Davicom Fast Ethernet driver for Davicom DM9102A [dmfe] + a000 Psycho UPA-PCI Bus Module [pcipsy] + a001 Psycho UPA-PCI Bus Module [pcipsy] + 108e a001 Ultra IIe on Blade 100 motherboard + a801 Schizo Fireplane-PCI bus bridge module [pcisch] + aaaa Multithreaded Shared 10GbE Ethernet Network Controller + abba Cassini 10/100/1000 + abcd Multithreaded 10-Gigabit Ethernet Network Controller + c416 Sun Fire System/System Controller Interface chip [sbbc] +108f Systemsoft +1090 Compro Computer Services, Inc. + 4610 PCI RTOM + 4620 GPIO HSD +1091 Intergraph Corporation + 0020 3D graphics processor + 0021 3D graphics processor w/Texturing + 0040 3D graphics frame buffer + 0041 3D graphics frame buffer + 0060 Proprietary bus bridge + 00e4 Powerstorm 4D50T + 0720 Motion JPEG codec + 0780 Intense3D Wildcat 3410 (MSMT496) + 07a0 Sun Expert3D-Lite Graphics Accelerator + 1091 Sun Expert3D Graphics Accelerator +1092 Diamond Multimedia Systems + 0028 Viper V770 + 1092 4a00 Viper V770 32MB + 00a0 Speedstar Pro SE + 00a8 Speedstar 64 + 0550 Viper V550 + 08d4 Supra 2260 Modem + 094c SupraExpress 56i Pro + 1001 Video Crunch It 1001 capture card + 1092 Viper V330 + 6120 Maximum DVD + 8810 Stealth SE + 8811 Stealth 64/SE + 8880 Stealth + 8881 Stealth + 88b0 Stealth 64 + 88b1 Stealth 64 + 88c0 Stealth 64 + 88c1 Stealth 64 + 88d0 Stealth 64 + 88d1 Stealth 64 + 88f0 Stealth 64 + 88f1 Stealth 64 + 9999 DMD-I0928-1 "Monster sound" sound chip +1093 National Instruments + 0160 PCI-DIO-96 + 0162 PCI-MIO-16XE-50 + 0fe1 PXI-8320 + 1150 PCI-6533 (PCI-DIO-32HS) + 1170 PCI-MIO-16XE-10 + 1180 PCI-MIO-16E-1 + 1190 PCI-MIO-16E-4 + 11b0 PXI-6070E + 11c0 PXI-6040E + 11d0 PXI-6030E + 1270 PCI-6032E + 1290 PCI-6704 + 12b0 PCI-6534 + 1310 PCI-6602 + 1320 PXI-6533 + 1330 PCI-6031E + 1340 PCI-6033E + 1350 PCI-6071E + 1360 PXI-6602 + 13c0 PXI-6508 + 1490 PXI-6534 + 14e0 PCI-6110 + 14f0 PCI-6111 + 1580 PXI-6031E + 15b0 PXI-6071E + 1710 PXI-6509 + 17c0 PXI-5690 + 17d0 PCI-6503 + 1870 PCI-6713 + 1880 PCI-6711 + 18b0 PCI-6052E + 18c0 PXI-6052E + 1920 PXI-6704 + 1930 PCI-6040E + 19c0 PCI-4472 + 1aa0 PXI-4110 + 1ad0 PCI-6133 + 1ae0 PXI-6133 + 1e30 PCI-6624 + 1e40 PXI-6624 + 1e50 PXI-5404 + 2410 PCI-6733 + 2420 PXI-6733 + 2430 PCI-6731 + 2470 PCI-4474 + 24a0 PCI-4065 + 24b0 PXI-4200 + 24f0 PXI-4472 + 2510 PCI-4472 + 2520 PCI-4474 + 27a0 PCI-6123 + 27b0 PXI-6123 + 2880 DAQCard-6601 + 2890 PCI-6036E + 28a0 PXI-4461 + 28b0 PCI-6013 + 28c0 PCI-6014 + 28d0 PCI-5122 + 28e0 PXI-5122 + 29f0 PXI-7334 + 2a00 PXI-7344 + 2a60 PCI-6023E + 2a70 PCI-6024E + 2a80 PCI-6025E + 2ab0 PXI-6025E + 2b10 PXI-6527 + 2b20 PCI-6527 + 2b80 PXI-6713 + 2b90 PXI-6711 + 2c60 PCI-6601 + 2c70 PXI-6601 + 2c80 PCI-6035E + 2c90 PCI-6703 + 2ca0 PCI-6034E + 2cb0 PCI-7344 + 2cc0 PXI-6608 + 2d20 PXI-5600 + 2db0 PCI-6608 + 2dc0 PCI-4070 + 2dd0 PXI-4070 + 2eb0 PXI-4472 + 2ec0 PXI-6115 + 2ed0 PCI-6115 + 2ee0 PXI-6120 + 2ef0 PCI-6120 + 2fd1 PCI-7334 + 2fd2 PCI-7350 + 2fd3 PCI-7342 + 2fd5 PXI-7350 + 2fd6 PXI-7342 + 7003 PCI-6551 + 7004 PXI-6551 + 700b PXI-5421 + 700c PCI-5421 + 701a VXIpc-87xB + 701b VXIpc-770 + 7023 PXI-2593 + 7027 PCI-MXI-2 Universal + 702c PXI-7831R + 702d PCI-7831R + 702e PXI-7811R + 702f PCI-7811R + 7030 PCI-CAN (Series 2) + 7031 PCI-CAN/2 (Series 2) + 7032 PCI-CAN/LS (Series 2) + 7033 PCI-CAN/LS2 (Series 2) + 7034 PCI-CAN/DS (Series 2) + 7035 PXI-8460 (Series 2, 1 port) + 7036 PXI-8460 (Series 2, 2 ports) + 7037 PXI-8461 (Series 2, 1 port) + 7038 PXI-8461 (Series 2, 2 ports) + 7039 PXI-8462 (Series 2) + 703f PXI-2566 + 7040 PXI-2567 + 7044 MXI-4 Connection Monitor + 7047 PXI-6653 + 704c PXI-2530 + 704f PXI-4220 + 7050 PXI-4204 + 7055 PXI-7830R + 7056 PCI-7830R + 705a PCI-CAN/XS (Series 2) + 705b PCI-CAN/XS2 (Series 2) + 705c PXI-8464 (Series 2, 1 port) + 705d PXI-8464 (Series 2, 2 ports) + 705e cRIO-9102 + 7060 PXI-5610 + 7064 PXI-1045 Trigger Routing Module + 7065 PXI-6652 + 7066 PXI-6651 + 7067 PXI-2529 + 7068 PCI-CAN/SW (Series 2) + 7069 PCI-CAN/SW2 (Series 2) + 706a PXI-8463 (Series 2, 1 port) + 706b PXI-8463 (Series 2, 2 ports) + 7073 PCI-6723 + 7074 PXI-7833R + 7075 PXI-6552 + 7076 PCI-6552 + 707c PXI-1428 + 707e PXI-4462 + 7080 PXI-8430/2 (RS-232) Interface + 7081 PXI-8431/2 (RS-485) Interface + 7083 PCI-7833R + 7085 PCI-6509 + 7086 PXI-6528 + 7087 PCI-6515 + 7088 PCI-6514 + 708c PXI-2568 + 708d PXI-2569 + 70a9 PCI-6528 + 70aa PCI-6229 + 70ab PCI-6259 + 70ac PCI-6289 + 70ad PXI-6251 + 70ae PXI-6220 + 70af PCI-6221 + 70b0 PCI-6220 + 70b1 PXI-6229 + 70b2 PXI-6259 + 70b3 PXI-6289 + 70b4 PCI-6250 + 70b5 PXI-6221 + 70b6 PCI-6280 + 70b7 PCI-6254 + 70b8 PCI-6251 + 70b9 PXI-6250 + 70ba PXI-6254 + 70bb PXI-6280 + 70bc PCI-6284 + 70bd PCI-6281 + 70be PXI-6284 + 70bf PXI-6281 + 70c0 PCI-6143 + 70c3 PCI-6511 + 70c4 PXI-7330 + 70c5 PXI-7340 + 70c6 PCI-7330 + 70c7 PCI-7340 + 70c8 PCI-6513 + 70c9 PXI-6515 + 70ca PCI-1405 + 70cc PCI-6512 + 70cd PXI-6514 + 70ce PXI-1405 + 70cf PCIe-GPIB + 70d0 PXI-2570 + 70d1 PXI-6513 + 70d2 PXI-6512 + 70d3 PXI-6511 + 70d4 PCI-6722 + 70d6 PXI-4072 + 70d7 PXI-6541 + 70d8 PXI-6542 + 70d9 PCI-6541 + 70da PCI-6542 + 70db PCI-8430/2 (RS-232) Interface + 70dc PCI-8431/2 (RS-485) Interface + 70dd PXI-8430/4 (RS-232) Interface + 70de PXI-8431/4 (RS-485) Interface + 70df PCI-8430/4 (RS-232) Interface + 70e0 PCI-8431/4 (RS-485) Interface + 70e1 PXI-2532 + 70e2 PXI-8430/8 (RS-232) Interface + 70e3 PXI-8431/8 (RS-485) Interface + 70e4 PCI-8430/8 (RS-232) Interface + 70e5 PCI-8431/8 (RS-485) Interface + 70e6 PXI-8430/16 (RS-232) Interface + 70e7 PCI-8430/16 (RS-232) Interface + 70e8 PXI-8432/2 (Isolated RS-232) Interface + 70e9 PXI-8433/2 (Isolated RS-485) Interface + 70ea PCI-8432/2 (Isolated RS-232) Interface + 70eb PCI-8433/2 (Isolated RS-485) Interface + 70ec PXI-8432/4 (Isolated RS-232) Interface + 70ed PXI-8433/4 (Isolated RS-485) Interface + 70ee PCI-8432/4 (Isolated RS-232) Interface + 70ef PCI-8433/4 (Isolated RS-485) Interface + 70f0 PXI-5922 + 70f1 PCI-5922 + 70f2 PCI-6224 + 70f3 PXI-6224 + 70f6 cRIO-9101 + 70f7 cRIO-9103 + 70f8 cRIO-9104 + 70ff PXI-6723 + 7100 PXI-6722 + 7104 PCIx-1429 + 7105 PCIe-1429 + 710a PXI-4071 + 710d PXI-6143 + 710e PCIe-GPIB + 710f PXI-5422 + 7110 PCI-5422 + 7111 PXI-5441 + 7119 PXI-6561 + 711a PXI-6562 + 711b PCI-6561 + 711c PCI-6562 + 7120 PCI-7390 + 7121 PXI-5122EX + 7122 PCI-5122EX + 7123 PXIe-5653 + 7124 PCI-6510 + 7125 PCI-6516 + 7126 PCI-6517 + 7127 PCI-6518 + 7128 PCI-6519 + 7137 PXI-2575 + 713c PXI-2585 + 713d PXI-2586 + 7142 PXI-4224 + 7144 PXI-5124 + 7145 PCI-5124 + 7146 PCI-6132 + 7147 PXI-6132 + 7148 PCI-6122 + 7149 PXI-6122 + 714c PXI-5114 + 714d PCI-5114 + 7150 PXI-2564 + 7152 PCI-5640R + 7156 PXI-1044 Trigger Routing Module + 715d PCI-1426 + 7167 PXI-5412 + 7168 PCI-5412 + 716b PCI-6230 + 716c PCI-6225 + 716d PXI-6225 + 716f PCI-4461 + 7170 PCI-4462 + 7171 PCI-6010 + 7174 PXI-8360 + 7177 PXI-6230 + 717d PCIe-6251 + 717f PCIe-6259 + 7187 PCI-1410 + 718b PCI-6521 + 718c PXI-6521 + 7191 PCI-6154 + 7193 PXI-7813R + 7194 PCI-7813R + 7195 PCI-8254R + 7197 PXI-5402 + 7198 PCI-5402 + 719f PCIe-6535 + 71a0 PCIe-6536 + 71a3 PXI-5650 + 71a4 PXI-5652 + 71a5 PXI-2594 + 71a7 PXI-2595 + 71a9 PXI-2596 + 71aa PXI-2597 + 71ab PXI-2598 + 71ac PXI-2599 + 71ad PCI-GPIB+ + 71ae PCIe-1430 + 71b7 PXI-1056 Trigger Routing Module + 71b8 PXI-1045 Trigger Routing Module + 71b9 PXI-1044 Trigger Routing Module + 71bb PXI-2584 + 71bc PCI-6221 (37-pin) + 71bf PCIe-1427 + 71c5 PCI-6520 + 71c6 PXI-2576 + 71c7 cRIO-9072 + 71dc PCI-1588 + 71e0 PCI-6255 + 71e1 PXI-6255 + 71e2 PXI-5406 + 71e3 PCI-5406 + 71fc PXI-4022 + 7209 PCI-6233 + 720a PXI-6233 + 720b PCI-6238 + 720c PXI-6238 + 7260 PXI-5142 + 7261 PCI-5142 + 726d PXI-5651 + 7273 PXI-4461 + 7274 PXI-4462 + 7279 PCI-6232 + 727a PXI-6232 + 727b PCI-6239 + 727c PXI-6239 + 727e SMBus Controller + 1093 75ac PXIe-8388 + 1093 75ad PXIe-8389 + 1093 7650 PXIe-8381 + 1093 8360 PXIe-8360 + 1093 8370 PXIe-8370 + 1093 8375 PXIe-8375 + 7281 PCI-6236 + 7282 PXI-6236 + 7283 PXI-2554 + 7288 PXIe-5611 + 7293 PCIe-8255R + 729d cRIO-9074 + 72a4 PCIe-4065 + 72a7 PCIe-6537 + 72a8 PXI-5152 + 72a9 PCI-5152 + 72aa PXI-5105 + 72ab PCI-5105 + 72b8 PXI-6682 + 72d0 PXI-2545 + 72d1 PXI-2546 + 72d2 PXI-2547 + 72d3 PXI-2548 + 72d4 PXI-2549 + 72d5 PXI-2555 + 72d6 PXI-2556 + 72d7 PXI-2557 + 72d8 PXI-2558 + 72d9 PXI-2559 + 72e8 PXIe-6251 + 72e9 PXIe-6259 + 72ef PXI-4498 + 72f0 PXI-4496 + 72fb PXIe-6672 + 730e PXI-4130 + 730f PXI-5922EX + 7310 PCI-5922EX + 731c PXI-2535 + 731d PXI-2536 + 7322 PXIe-6124 + 7327 PXI-6529 + 732c VXI-8360T + 7331 PXIe-5602 + 7332 PXIe-5601 + 7333 PXI-5900 + 7335 PXI-2533 + 7336 PXI-2534 + 7342 PXI-4461 + 7349 PXI-5154 + 734a PCI-5154 + 7357 PXI-4065 + 7359 PXI-4495 + 7370 PXI-4461 + 7373 sbRIO-9601 + 7374 IOtech-9601 + 7375 sbRIO-9602 + 7378 sbRIO-9641 + 737d PXI-5124EX + 7384 PXI-7851R + 7385 PXI-7852R + 7386 PCIe-7851R + 7387 PCIe-7852R + 7390 PXI-7841R + 7391 PXI-7842R + 7392 PXI-7853R + 7393 PCIe-7841R + 7394 PCIe-7842R + 7397 sbRIO-9611 + 7398 sbRIO-9612 + 7399 sbRIO-9631 + 739a sbRIO-9632 + 739b sbRIO-9642 + 73a1 PXIe-4498 + 73a2 PXIe-4496 + 73a5 PXIe-5641R + 73a7 PXI-8250 Chassis Monitor Module + 73a8 PXI-8511 CAN/LS + 73a9 PXI-8511 CAN/LS + 73aa PXI-8512 CAN/HS + 73ab PXI-8512 CAN/HS + 73ac PXI-8513 CAN/XS + 73ad PXI-8513 CAN/XS + 73af PXI-8516 LIN + 73b1 PXI-8517 FlexRay + 73b2 PXI-8531 CANopen + 73b3 PXI-8531 CANopen + 73b4 PXI-8532 DeviceNet + 73b5 PXI-8532 DeviceNet + 73b6 PCI-8511 CAN/LS + 73b7 PCI-8511 CAN/LS + 73b8 PCI-8512 CAN/HS + 73b9 PCI-8512 CAN/HS + 73ba PCI-8513 CAN/XS + 73bb PCI-8513 CAN/XS + 73bd PCI-8516 LIN + 73bf PCI-8517 FlexRay + 73c0 PCI-8531 CANopen + 73c1 PCI-8531 CANopen + 73c2 PCI-8532 DeviceNet + 73c3 PCI-8532 DeviceNet + 73c5 PXIe-2527 + 73c6 PXIe-2529 + 73c8 PXIe-2530 + 73c9 PXIe-2532 + 73ca PXIe-2569 + 73cb PXIe-2575 + 73cc PXIe-2593 + 73d5 PXI-7951R + 73d6 PXI-7952R + 73d7 PXI-7953R + 73e1 PXI-7854R + 73ec PXI-7954R + 73ed cRIO-9073 + 73f0 PXI-5153 + 73f1 PCI-5153 + 73f4 PXI-2515 + 73f6 cRIO-9111 + 73f7 cRIO-9112 + 73f8 cRIO-9113 + 73f9 cRIO-9114 + 73fa cRIO-9116 + 73fb cRIO-9118 + 7404 PXI-4132 + 7405 PXIe-6674T + 7406 PXIe-6674 + 740e PCIe-8430/16 (RS-232) Interface + 740f PCIe-8430/8 (RS-232) Interface + 7410 PCIe-8431/16 (RS-485) Interface + 7411 PCIe-8431/8 (RS-485) Interface + 7414 PCIe-GPIB+ + 741c PXI-5691 + 741d PXI-5695 + 743c CSC-3059 + 7448 PXI-2510 + 7454 PXI-2512 + 7455 PXI-2514 + 7456 PXIe-2512 + 7457 PXIe-2514 + 745a PXI-6682H + 745e PXI-5153EX + 745f PCI-5153EX + 7460 PXI-5154EX + 7461 PCI-5154EX + 746d PXIe-5650 + 746e PXIe-5651 + 746f PXIe-5652 + 7472 PXI-2800 + 7495 PXIe-5603 + 7497 PXIe-5605 + 74ae PXIe-2515 + 74b4 PXI-2531 + 74b5 PXIe-2531 + 74c1 PXIe-8430/16 (RS-232) Interface + 74c2 PXIe-8430/8 (RS-232) Interface + 74c3 PXIe-8431/16 (RS-485) Interface + 74c4 PXIe-8431/8 (RS-485) Interface + 74d5 PXIe-5630 + 74d9 PCIe-8432/2 (Isolated RS-232) Interface + 74da PCIe-8433/2 (Isolated RS-485) Interface + 74db PCIe-8432/4 (Isolated RS-232) Interface + 74dc PCIe-8433/4 (Isolated RS-485) Interface + 74e8 NI 9148 + 7515 PCIe-8430/2 (RS-232) Interface + 7516 PCIe-8430/4 (RS-232) Interface + 7517 PCIe-8431/2 (RS-485) Interface + 7518 PCIe-8431/4 (RS-485) Interface + 751b cRIO-9081 + 751c cRIO-9082 + 7528 PXIe-4497 + 7529 PXIe-4499 + 752a PXIe-4492 + 7539 NI 9157 + 753a NI 9159 + 7598 PXI-2571 + 75a4 PXI-4131A + 75b1 PCIe-7854R + 75ba PXI-2543 + 75bb PXIe-2543 + 75e5 PXI-6683 + 75e6 PXI-6683H + 75ef PXIe-5632 + 761c VXI-8360LT + 761f PXI-2540 + 7620 PXIe-2540 + 7621 PXI-2541 + 7622 PXIe-2541 + 7626 NI 9154 + 7627 NI 9155 + 7638 PXI-2720 + 7639 PXI-2722 + 763a PXIe-2725 + 763b PXIe-2727 + 763c PXI-4465 + 764b PXIe-2790 + 764c PXI-2520 + 764d PXI-2521 + 764e PXI-2522 + 764f PXI-2523 + 7654 PXI-2796 + 7655 PXI-2797 + 7656 PXI-2798 + 7657 PXI-2799 + 765d PXI-2542 + 765e PXIe-2542 + 765f PXI-2544 + 7660 PXIe-2544 + 766d PCIe-6535B + 766e PCIe-6536B + 766f PCIe-6537B + 76a3 PXIe-6535B + 76a4 PXIe-6536B + 76a5 PXIe-6537B + 783e PXI-8368 + 9020 PXI-2501 + 9030 PXI-2503 + 9040 PXI-2527 + 9050 PXI-2565 + 9060 PXI-2590 + 9070 PXI-2591 + 9080 PXI-2580 + 9090 PCI-4021 + 90a0 PXI-4021 + a001 PCI-MXI-2 + b001 PCI-1408 + b011 PXI-1408 + b021 PCI-1424 + b022 PXI-1424 + b031 PCI-1413 + b041 PCI-1407 + b051 PXI-1407 + b061 PCI-1411 + b071 PCI-1422 + b081 PXI-1422 + b091 PXI-1411 + b0b1 PCI-1409 + b0c1 PXI-1409 + b0e1 PCI-1428 + c4c4 PXIe/PCIe Device + 1093 728a PXIe-5421 + 1093 728b PXIe-5442 + 1093 728d PXIe-5451 + 1093 72a2 PXIe-5122 + 1093 72da PXIe-5422 + 1093 72f7 PXIe-6535 + 1093 72f8 PXIe-6536 + 1093 72f9 PXIe-6537 + 1093 7326 PCIe-6509 + 1093 736c PXIe-4140 + 1093 738b PXIe-5622 + 1093 73c4 PXIe-5450 + 1093 73c7 PXIe-6545 + 1093 73d4 PXIe-6544 + 1093 7425 PCIe-6320 + 1093 7427 PCIe-6321 + 1093 7428 PXIe-6323 + 1093 7429 PCIe-6323 + 1093 742a PXIe-6341 + 1093 742b PCIe-6341 + 1093 742c PXIe-6343 + 1093 742d PCIe-6343 + 1093 742f PCIe-6351 + 1093 7431 PCIe-6353 + 1093 7432 PXIe-6361 + 1093 7433 PCIe-6361 + 1093 7434 PXIe-6363 + 1093 7435 PCIe-6363 + 1093 7436 PXIe-6356 + 1093 7437 PXIe-6358 + 1093 7438 PXIe-6366 + 1093 7439 PXIe-6368 + 1093 7468 PXIe-5185 + 1093 7469 PXIe-5186 + 1093 7492 PXIe-4300 + 1093 7498 PXIe-6548 + 1093 7499 PXIe-6547 + 1093 74a8 PXIe-4330 + 1093 74a9 PXIe-4331 + 1093 74b1 PXIe-4154 + 1093 74b2 PXIe-4353 + 1093 74b6 PCIe-1433 + 1093 74cd PXIe-5643R + 1093 74d0 PXIe-7961R + 1093 74dd PXIe-6376 + 1093 74de PXIe-6378 + 1093 74e2 PXIe-7962R + 1093 74e3 PXIe-7965R + 1093 74e5 PXIe-4844 + 1093 74f3 PCIe-5140 + 1093 753c PXIe-1435 + 1093 7548 PXIe-5622 (25MHz DDC) + 1093 754d PCIe-5155 + 1093 7551 PXIe-6556 + 1093 7553 PCIe-1473R + 1093 7570 PCIe-1474R + 1093 7571 PXIe-1475R + 1093 7572 PXIe-1476R + 1093 75a2 PXIe-5693 + 1093 75a3 PXIe-5694 + 1093 75a5 PXIe-4141 + 1093 75ce PXIe-7966R + 1093 75cf PXIe-4357 + 1093 75d2 PXIe-RevB-5643R + 1093 75d3 PXIe-5644R + 1093 75ee PXIe-5645R + 1093 7613 PXIe-6555 + 1093 7619 PXIe-5185 + 1093 761a PXIe-5186 + 1093 7629 PXIe-4142 + 1093 762a PXIe-4143 + 1093 762b PXIe-4138 + 1093 762c PXIe-4144 + 1093 762d PXIe-4145 + 1093 762e PXIe-5606 + 1093 7644 PXIe-4841 + 1093 764a PCIe-8237R-S + 1093 7658 PXIe-5162 (4CH) + 1093 76ab PXIe-4322 + 1093 76ad PXIe-4112 + 1093 76ae PXIe-4113 + 1093 76b5 PXIe-7971R + 1093 76b6 PXIe-7972R + 1093 76b7 PXIe-7975R + 1093 76b8 PXIe-5696 + 1093 76b9 PXIe-5654 + 1093 76c8 PXIe-6614 + 1093 76c9 PXIe-6612 + 1093 76cb PXIe-5646R + 1093 76cc PXIe-5162 (2CH) + 1093 76ce CVS-1459 + 1093 76d0 PXIe-5160 (2CH) + 1093 76d1 PXIe-5160 (4CH) + 1093 76dc PXIe-4610 + 1093 76ec PXIe-2524 + 1093 76ed PXIe-2525 + 1093 76ee PXIe-2526 + 1093 76ef PXIe-2737 + 1093 76f0 PXIe-2738 + 1093 76f1 PXIe-2739 + 1093 76fb PCIe-1473R-LX110 + 1093 76fc PXIe-5105 + 1093 76fd PXIe-5114 + 1093 76fe PXIe-5644R + 1093 76ff PXIe-5644R + 1093 7700 PXIe-5644R + 1093 7701 PXIe-5645R + 1093 7702 PXIe-5645R + 1093 7703 PXIe-5645R + 1093 770c PXIe-4139 + 1093 7711 PXIe-4464 + 1093 7712 PXIe-4463 + 1093 7716 PCIe-6612 + 1093 771d Unconfigured CA4 Switch + 1093 771e PXIe-4339 + 1093 7735 cRIO-9033 + 1093 773e PXIe-5624R + 1093 774b cRIO-9031 + 1093 774d cRIO-9034 + 1093 7755 cRIO-9030 + 1093 7768 PXIe-2747 + 1093 7769 PXIe-2748 + 1093 776a PXIe-2746 + 1093 7777 PXIe-7976R + 1093 7782 PXIe-5646R + 1093 7783 PXIe-5646R + 1093 7784 PXIe-5646R + 1093 7790 PXIe-5170R (4CH) + 1093 7791 PXIe-5170R (8CH) + 1093 7793 PXIe-5171R (8CH) + 1093 77a5 PXIe-6345 + 1093 77a6 PXIe-6355 + 1093 77a7 PXIe-6365 + 1093 77a8 PXIe-6375 + 1093 77aa CVS-1458 + 1093 77ad IC-3173 + 1093 77b4 PXIe-7820R + 1093 77b5 PXIe-7821R + 1093 77b6 PXIe-7822R + 1093 77b9 cRIO-9038 + 1093 77ba PXIe-4136 + 1093 77bb PXIe-4137 + 1093 77c0 PXIe-5624R + 1093 77c1 PXIe-5624R + 1093 77c2 PXIe-5624R + 1093 77ca PXIe-6738 + 1093 77cb PXIe-6739 + 1093 77db cRIO-9035 + 1093 77dc cRIO-9036 + 1093 77dd cRIO-9039 + 1093 7802 PXIe-4302 + 1093 7803 PXIe-4303 + 1093 7805 PXIe-4305 + 1093 786f PXIe-4163 + 1093 788e PXIe-4304 + 1093 78f8 NI FlexRIO Module (KU035) + 1093 78f9 NI FlexRIO Module (KU040) + 1093 78fa NI FlexRIO Module (KU060) + 1093 78ff PXIe-4162 + 1093 7995 PXIe-7911R + 1093 7996 PXIe-7912R + 1093 7997 PXIe-7915R + 1093 79d3 NI FlexRIO PCIe Module (KU035) + 1093 79d4 NI FlexRIO PCIe Module (KU040) + 1093 79d5 NI FlexRIO PCIe Module (KU060) + c801 PCI-GPIB + c811 PCI-GPIB+ + c821 PXI-GPIB + c831 PMC-GPIB + c840 PCI-GPIB + d130 PCI-232/2 Interface + d140 PCI-232/4 Interface + d150 PCI-232/8 Interface + d160 PCI-485/2 Interface + d170 PCI-485/4 Interface + d190 PXI-8422/2 (Isolated RS-232) Interface + d1a0 PXI-8422/4 (Isolated RS-232) Interface + d1b0 PXI-8423/2 (Isolated RS-485) Interface + d1c0 PXI-8423/4 (Isolated RS-485) Interface + d1d0 PXI-8420/2 (RS-232) Interface + d1e0 PXI-8420/4 (RS-232) Interface + d1f0 PXI-8420/8 (RS-232) Interface + d1f1 PXI-8420/16 (RS-232) Interface + d230 PXI-8421/2 (RS-485) Interface + d240 PXI-8421/4 (RS-485) Interface + d250 PCI-232/2 (Isolated) Interface + d260 PCI-485/2 (Isolated) Interface + d270 PCI-232/4 (Isolated) Interface + d280 PCI-485/4 (Isolated) Interface + d290 PCI-485/8 Interface + d2a0 PXI-8421/8 (RS-485) Interface + d2b0 PCI-232/16 Interface + e111 PCI-CAN + e131 PXI-8461 (1 port) + e141 PCI-CAN/LS + e151 PXI-8460 (1 port) + e211 PCI-CAN/2 + e231 PXI-8461 (2 ports) + e241 PCI-CAN/LS2 + e251 PXI-8460 (2 ports) + e261 PCI-CAN/DS + e271 PXI-8462 + f110 VMEpc-650 + f120 VXIpc-650 + fe00 VXIpc-87x + fe41 VXIpc-860 + fe51 VXIpc-74x + fe61 VXIpc-850 + fe70 VXIpc-880 +1094 First International Computers [FIC] +# nee CMD Technology Inc +1095 Silicon Image, Inc. + 0240 Adaptec AAR-1210SA SATA HostRAID Controller + 0640 PCI0640 + 0643 PCI0643 + 0646 PCI0646 + 0647 PCI0647 + 0648 PCI0648 + 1043 8025 CUBX motherboard + 0649 SiI 0649 Ultra ATA/100 PCI to ATA Host Controller + 0e11 005d Integrated Ultra ATA-100 Dual Channel Controller + 0e11 007e Integrated Ultra ATA-100 IDE RAID Controller + 101e 0649 AMI MegaRAID IDE 100 Controller + 0650 PBC0650A + 0670 USB0670 + 1095 0670 USB0670 + 0673 USB0673 + 0680 PCI0680 Ultra ATA-133 Host Controller + 1095 0680 SiI 0680 ATA/133 Controller + 1095 3680 Winic W-680 (Silicon Image 680 based) + 3112 SiI 3112 [SATALink/SATARaid] Serial ATA Controller + 1095 3112 SiI 3112 SATALink Controller + 1095 6112 SiI 3112 SATARaid Controller + 9005 0250 SATAConnect 1205SA Host Controller + 3114 SiI 3114 [SATALink/SATARaid] Serial ATA Controller + 1043 8167 A8N-SLI Deluxe/Premium Mainboard + 1095 3114 SiI 3114 SATALink Controller + 1095 6114 SiI 3114 SATARaid Controller + 3124 SiI 3124 PCI-X Serial ATA Controller + 1095 3124 SiI 3124 PCI-X Serial ATA Controller + 3132 SiI 3132 Serial ATA Raid II Controller + 3512 SiI 3512 [SATALink/SATARaid] Serial ATA Controller + 1095 3512 SiI 3512 SATALink Controller + 1095 6512 SiI 3512 SATARaid Controller + 3531 SiI 3531 [SATALink/SATARaid] Serial ATA Controller + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] +1096 Alacron +1097 Appian Technology +1098 Quantum Designs (H.K.) Ltd + 0001 QD-8500 + 0002 QD-8580 +1099 Samsung Electronics Co., Ltd +109a Packard Bell +109b Gemlight Computer Ltd. +109c Megachips Corporation +109d Zida Technologies Ltd. +109e Brooktree Corporation + 0310 Bt848 Video Capture + 032e Bt878 Video Capture + 0350 Bt848 Video Capture + 0351 Bt849A Video capture + 0369 Bt878 Video Capture + 1002 0001 TV-Wonder + 1002 0003 TV-Wonder/VE + 036c Bt879(??) Video Capture + 13e9 0070 Win/TV (Video Section) + 036e Bt878 Video Capture + 0000 0001 Euresys Picolo PCIe + 0070 13eb WinTV Series + 0070 ff01 Viewcast Osprey 200 + 0071 0101 DigiTV PCI + 107d 6606 WinFast TV 2000 + 11bd 0012 PCTV pro (TV + FM stereo receiver) + 11bd 001c PCTV Sat (DBC receiver) + 127a 0001 Bt878 Mediastream Controller NTSC + 127a 0002 Bt878 Mediastream Controller PAL BG + 127a 0003 Bt878a Mediastream Controller PAL BG + 127a 0048 Bt878/832 Mediastream Controller + 144f 3000 MagicTView CPH060 - Video + 1461 0002 TV98 Series (TV/No FM/Remote) + 1461 0003 AverMedia UltraTV PCI 350 + 1461 0004 AVerTV WDM Video Capture + 1461 0761 AverTV DVB-T + 1461 0771 AverMedia AVerTV DVB-T 771 + 14f1 0001 Bt878 Mediastream Controller NTSC + 14f1 0002 Bt878 Mediastream Controller PAL BG + 14f1 0003 Bt878a Mediastream Controller PAL BG + 14f1 0048 Bt878/832 Mediastream Controller + 1822 0001 VisionPlus DVB card + 1851 1850 FlyVideo'98 - Video + 1851 1851 FlyVideo II + 1852 1852 FlyVideo'98 - Video (with FM Tuner) + 18ac d500 DViCO FusionHDTV5 Lite + 270f fc00 Digitop DTT-1000 +# Vendor/ID appear to be randomly chosen + aa00 1460 Spectra8 CardA Input0 +# Vendor/ID appear to be randomly chosen + aa01 1461 Spectra8 CardA Input1 +# Vendor/ID appear to be randomly chosen + aa02 1462 Spectra8 CardA Input2 +# Vendor/ID appear to be randomly chosen + aa03 1463 Spectra8 CardA Input3 +# Vendor/ID appear to be randomly chosen + aa04 1464 Spectra8 CardB Input0 +# Vendor/ID appear to be randomly chosen + aa05 1465 Spectra8 CardB Input1 +# Vendor/ID appear to be randomly chosen + aa06 1466 Spectra8 CardB Input2 +# Vendor/ID appear to be randomly chosen + aa07 1467 Spectra8 CardB Input3 +# Vendor/ID appear to be randomly chosen + aa08 1468 Spectra8 CardC Input0 +# Vendor/ID appear to be randomly chosen + aa09 1469 Spectra8 CardC Input1 +# Vendor/ID appear to be randomly chosen + aa0a 146a Spectra8 CardC Input2 +# Vendor/ID appear to be randomly chosen + aa0b 146b Spectra8 CardC Input3 +# Vendor/ID appear to be randomly chosen + aa0c 146c Spectra8 CardD Input0 +# Vendor/ID appear to be randomly chosen + aa0d 146d Spectra8 CardD Input1 +# Vendor/ID appear to be randomly chosen + aa0e 146e Spectra8 CardD Input2 +# Vendor/ID appear to be randomly chosen + aa0f 146f Spectra8 CardD Input3 + bd11 1200 PCTV pro (TV + FM stereo receiver) + 036f Bt879 Video Capture + 127a 0044 Bt879 Video Capture NTSC + 127a 0122 Bt879 Video Capture PAL I + 127a 0144 Bt879 Video Capture NTSC + 127a 0222 Bt879 Video Capture PAL BG + 127a 0244 Bt879a Video Capture NTSC + 127a 0322 Bt879 Video Capture NTSC + 127a 0422 Bt879 Video Capture NTSC + 127a 1122 Bt879 Video Capture PAL I + 127a 1222 Bt879 Video Capture PAL BG + 127a 1322 Bt879 Video Capture NTSC + 127a 1522 Bt879a Video Capture PAL I + 127a 1622 Bt879a Video Capture PAL BG + 127a 1722 Bt879a Video Capture NTSC + 14f1 0044 Bt879 Video Capture NTSC + 14f1 0122 Bt879 Video Capture PAL I + 14f1 0144 Bt879 Video Capture NTSC + 14f1 0222 Bt879 Video Capture PAL BG + 14f1 0244 Bt879a Video Capture NTSC + 14f1 0322 Bt879 Video Capture NTSC + 14f1 0422 Bt879 Video Capture NTSC + 14f1 1122 Bt879 Video Capture PAL I + 14f1 1222 Bt879 Video Capture PAL BG + 14f1 1322 Bt879 Video Capture NTSC + 14f1 1522 Bt879a Video Capture PAL I + 14f1 1622 Bt879a Video Capture PAL BG + 14f1 1722 Bt879a Video Capture NTSC + 1851 1850 FlyVideo'98 - Video + 1851 1851 FlyVideo II + 1852 1852 FlyVideo'98 - Video (with FM Tuner) + 0370 Bt880 Video Capture + 1851 1850 FlyVideo'98 + 1851 1851 FlyVideo'98 EZ - video + 1852 1852 FlyVideo'98 (with FM Tuner) + 0878 Bt878 Audio Capture + 0000 0001 Euresys Picolo PCIe + 0070 13eb WinTV Series + 0070 ff01 Viewcast Osprey 200 + 0071 0101 DigiTV PCI + 1002 0001 TV-Wonder + 1002 0003 TV-Wonder/VE + 11bd 0012 PCTV pro (TV + FM stereo receiver, audio section) + 11bd 001c PCTV Sat (DBC receiver) + 127a 0001 Bt878 Video Capture (Audio Section) + 127a 0002 Bt878 Video Capture (Audio Section) + 127a 0003 Bt878 Video Capture (Audio Section) + 127a 0048 Bt878 Video Capture (Audio Section) + 13e9 0070 Win/TV (Audio Section) + 144f 3000 MagicTView CPH060 - Audio + 1461 0002 Avermedia PCTV98 Audio Capture + 1461 0003 UltraTV PCI 350 + 1461 0004 AVerTV WDM Audio Capture + 1461 0761 AVerTV DVB-T + 1461 0771 AverMedia AVerTV DVB-T 771 + 14f1 0001 Bt878 Video Capture (Audio Section) + 14f1 0002 Bt878 Video Capture (Audio Section) + 14f1 0003 Bt878 Video Capture (Audio Section) + 14f1 0048 Bt878 Video Capture (Audio Section) + 1822 0001 VisionPlus DVB Card + 18ac d500 DViCO FusionHDTV5 Lite + 270f fc00 Digitop DTT-1000 + bd11 1200 PCTV pro (TV + FM stereo receiver, audio section) + 0879 Bt879 Audio Capture + 127a 0044 Bt879 Video Capture (Audio Section) + 127a 0122 Bt879 Video Capture (Audio Section) + 127a 0144 Bt879 Video Capture (Audio Section) + 127a 0222 Bt879 Video Capture (Audio Section) + 127a 0244 Bt879 Video Capture (Audio Section) + 127a 0322 Bt879 Video Capture (Audio Section) + 127a 0422 Bt879 Video Capture (Audio Section) + 127a 1122 Bt879 Video Capture (Audio Section) + 127a 1222 Bt879 Video Capture (Audio Section) + 127a 1322 Bt879 Video Capture (Audio Section) + 127a 1522 Bt879 Video Capture (Audio Section) + 127a 1622 Bt879 Video Capture (Audio Section) + 127a 1722 Bt879 Video Capture (Audio Section) + 14f1 0044 Bt879 Video Capture (Audio Section) + 14f1 0122 Bt879 Video Capture (Audio Section) + 14f1 0144 Bt879 Video Capture (Audio Section) + 14f1 0222 Bt879 Video Capture (Audio Section) + 14f1 0244 Bt879 Video Capture (Audio Section) + 14f1 0322 Bt879 Video Capture (Audio Section) + 14f1 0422 Bt879 Video Capture (Audio Section) + 14f1 1122 Bt879 Video Capture (Audio Section) + 14f1 1222 Bt879 Video Capture (Audio Section) + 14f1 1322 Bt879 Video Capture (Audio Section) + 14f1 1522 Bt879 Video Capture (Audio Section) + 14f1 1622 Bt879 Video Capture (Audio Section) + 14f1 1722 Bt879 Video Capture (Audio Section) + 0880 Bt880 Audio Capture + 2115 BtV 2115 Mediastream controller + 2125 BtV 2125 Mediastream controller + 2164 BtV 2164 + 2165 BtV 2165 + 8230 Bt8230 ATM Segment/Reassembly Ctrlr (SRC) + 8472 Bt8472 + 8474 Bt8474 +109f Trigem Computer Inc. +10a0 Meidensha Corporation +10a1 Juko Electronics Ind. Co. Ltd +10a2 Quantum Corporation +10a3 Everex Systems Inc +10a4 Globe Manufacturing Sales +10a5 Smart Link Ltd. + 3052 SmartPCI562 56K Modem + 5449 SmartPCI561 modem +10a6 Informtech Industrial Ltd. +10a7 Benchmarq Microelectronics +10a8 Sierra Semiconductor + 0000 STB Horizon 64 +10a9 Silicon Graphics Intl. Corp. + 0001 Crosstalk to PCI Bridge + 0002 Linc I/O controller + 0003 IOC3 I/O controller + 0004 O2 MACE + 0005 RAD Audio + 0006 HPCEX + 0007 RPCEX + 0008 DiVO VIP + 0009 AceNIC Gigabit Ethernet + 10a9 8002 AceNIC Gigabit Ethernet + 0010 AMP Video I/O + 0011 GRIP + 0012 SGH PSHAC GSN + 0208 SSIM1 SAS Adapter + 1001 Magic Carpet + 1002 Lithium + 1003 Dual JPEG 1 + 1004 Dual JPEG 2 + 1005 Dual JPEG 3 + 1006 Dual JPEG 4 + 1007 Dual JPEG 5 + 1008 Cesium + 100a IOC4 I/O controller + 1504 SSIM1 Fibre Channel Adapter + 2001 Fibre Channel + 2002 ASDE + 4001 TIO-CE PCI Express Bridge + 4002 TIO-CE PCI Express Port + 8001 O2 1394 + 8002 G-net NT +# PCIe x1 Low Profile + 802b REACT external interrupt controller +10aa ACC Microelectronics + 0000 ACCM 2188 + 2051 2051 CPU bridge + 5842 2051 ISA bridge +10ab Digicom +10ac Honeywell IAC +10ad Symphony Labs + 0001 W83769F + 0003 SL82C103 + 0005 SL82C105 + 0103 SL82c103 + 0105 SL82c105 + 0565 W83C553F/W83C554F +10ae Cornerstone Technology +10af Micro Computer Systems Inc +10b0 CardExpert Technology +10b1 Cabletron Systems Inc +10b2 Raytheon Company +10b3 Databook Inc + 3106 DB87144 + b106 DB87144 +10b4 STB Systems Inc + 1b1d Velocity 128 3D + 10b4 237e Velocity 4400 +10b5 PLX Technology, Inc. + 0001 i960 PCI bus interface + 0557 PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 9030 Digium Tormenta 2 T400P-SS7 or E400P-SS7 Quad T1 or E1 PCI card + 1000 PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 9030 ATCOM AT400P Quad T1 PCI card + 1024 Acromag, Inc. IndustryPack Carrier Card + 1042 Brandywine / jxi2, Inc. - PMC-SyncClock32, IRIG A & B, Nasa 36 + 106a Dual OX16C952 4 port serial adapter [Megawolf Romulus/4] + 1076 VScom 800 8 port serial adaptor + 1077 VScom 400 4 port serial adaptor + 1078 VScom 210 2 port serial and 1 port parallel adaptor + 1103 VScom 200 2 port serial adaptor + 1146 VScom 010 1 port parallel adaptor + 1147 VScom 020 2 port parallel adaptor + 2000 PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 9030 ATCOM AE400P Quad E1 PCI card + 2540 IXXAT CAN-Interface PC-I 04/PCI + 2724 Thales PCSM Security Card + 3376 Cosateq 4 Port CAN Card + 4000 PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 9030 Tormenta 3 Varion V400P/ATCOM TE400P Quad E1/T1/J1 PCI card + 4001 PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 9030 ATCOM A400PE Quad E1 PCI card + 4002 PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 9030 ATCOM A400PT Quad T1 PCI card + 6140 PCI6140 32-bit 33MHz PCI-to-PCI Bridge + 6150 PCI6150 32-bit 33MHz PCI-to-PCI Bridge + 6152 PCI6152 32-bit 66MHz PCI-to-PCI Bridge + 6154 PCI6154 64-bit 66MHz PCI-to-PCI Bridge + 6254 PCI6254 64-bit 66MHz PCI-to-PCI Bridge + 6466 PCI6466 64-bit 66MHz PCI-to-PCI Bridge + 6520 PCI6520 64-bit 133MHz PCI-X-to-PCI-X Bridge + 6540 PCI6540 64-bit 133MHz PCI-X-to-PCI-X Bridge + 1775 1100 CR11 Single Board Computer + 4c53 10e0 PSL09 PrPMC + 6541 PCI6540/6466 PCI-PCI bridge (non-transparent mode, primary side) + 1775 1100 CR11 Single Board Computer + 4c53 10e0 PSL09 PrPMC + 6542 PCI6540/6466 PCI-PCI bridge (non-transparent mode, secondary side) + 1775 1100 CR11 Single Board Computer + 4c53 10e0 PSL09 PrPMC + 8111 PEX 8111 PCI Express-to-PCI Bridge + 8112 PEX8112 x1 Lane PCI Express-to-PCI Bridge + 8114 PEX 8114 PCI Express-to-PCI/PCI-X Bridge + 8311 PEX8311 x1 Lane PCI Express-to-Generic Local Bus Bridge + 8505 PEX 8505 5-lane, 5-port PCI Express Switch + 8508 PEX 8508 8-lane, 5-port PCI Express Switch + 8509 PEX 8509 8-lane, 8-port PCI Express Switch + 8512 PEX 8512 12-lane, 5-port PCI Express Switch + 8516 PEX 8516 Versatile PCI Express Switch + 8517 PEX 8517 16-lane, 5-port PCI Express Switch + 8518 PEX 8518 16-lane, 5-port PCI Express Switch + 8524 PEX 8524 24-lane, 6-port PCI Express Switch + 8525 PEX 8525 24-lane, 5-port PCI Express Switch + 8532 PEX 8532 Versatile PCI Express Switch + 8533 PEX 8533 32-lane, 6-port PCI Express Switch + 8547 PEX 8547 48-lane, 3-port PCI Express Switch + 8548 PEX 8548 48-lane, 9-port PCI Express Switch + 8603 PEX 8603 3-lane, 3-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8604 PEX 8604 4-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8605 PEX 8605 PCI Express 4-port Gen2 Switch + 8606 PEX 8606 6 Lane, 6 Port PCI Express Gen 2 (5.0 GT/s) Switch + 8608 PEX 8608 8-lane, 8-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8609 PEX 8609 8-lane, 8-Port PCI Express Gen 2 (5.0 GT/s) Switch with DMA + 8612 PEX 8612 12-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8613 PEX 8613 12-lane, 3-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8614 PEX 8614 12-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8615 PEX 8615 12-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch with DMA + 8616 PEX 8616 16-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8617 PEX 8617 16-lane, 4-Port PCI Express Gen 2 (5.0 GT/s) Switch with P2P + 8618 PEX 8618 16-lane, 16-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8619 PEX 8619 16-lane, 16-Port PCI Express Gen 2 (5.0 GT/s) Switch with DMA + 8624 PEX 8624 24-lane, 6-Port PCI Express Gen 2 (5.0 GT/s) Switch [ExpressLane] + 13a3 1845 DX1845 Acceleration Card + 8625 PEX 8625 24-lane, 24-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8632 PEX 8632 32-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8636 PEX 8636 36-lane, 24-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8647 PEX 8647 48-Lane, 3-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8648 PEX 8648 48-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8649 PEX 8649 48-lane, 12-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8664 PEX 8664 64-lane, 16-Port PCI Express Gen 2 (5.0 GT/s) Switch + 8680 PEX 8680 80-lane, 20-Port PCI Express Gen 2 (5.0 GT/s) Multi-Root Switch + 8696 PEX 8696 96-lane, 24-Port PCI Express Gen 2 (5.0 GT/s) Multi-Root Switch + 8717 PEX 8717 16-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch with DMA + 8718 PEX 8718 16-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch + 8724 PEX 8724 24-Lane, 6-Port PCI Express Gen 3 (8 GT/s) Switch, 19 x 19mm FCBGA + 8732 PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch + 8734 PEX 8734 32-lane, 8-Port PCI Express Gen 3 (8.0GT/s) Switch + 8747 PEX 8747 48-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch + 8748 PEX 8748 48-Lane, 12-Port PCI Express Gen 3 (8 GT/s) Switch, 27 x 27mm FCBGA +# This is the Non-Transparent-Bridge Virtualized Port as presented by the PLX PEX 8732 chip, the physical bridges show up at 10b5:8732 + 87b0 PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch + 1093 7761 PXIe-8830mc + 9016 PLX 9016 8-port serial controller + 9030 PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 2695 Hilscher CIF50-PB/DPS Profibus + 10b5 2862 Alpermann+Velte PCL PCI LV (3V/5V): Timecode Reader Board + 10b5 2906 Alpermann+Velte PCI TS (3V/5V): Time Synchronisation Board + 10b5 2940 Alpermann+Velte PCL PCI D (3V/5V): Timecode Reader Board + 10b5 2977 IXXAT iPC-I XC16/PCI CAN Board + 10b5 2978 SH ARC-PCIu/SH ARC-PCI104/SH ARC-PCIe SOHARD ARCNET card + 10b5 3025 Alpermann+Velte PCL PCI L (3V/5V): Timecode Reader Board + 10b5 3068 Alpermann+Velte PCL PCI HD (3V/5V): Timecode Reader Board + 10b5 3463 Alpermann+Velte PCL PCI D (v2) (3V/5V): Timecode Reader Board + 10b5 3591 PLURA PCL PCI L (v2) (3.3V/5V): Time Code Reader Board + 12fe 0111 CPCI-ASIO4 (ESD 4-port Serial Interface Board) + 1369 9c01 VX222v2 + 1369 9d01 VX222-Mic + 1369 9d02 VX222-Mic + 1369 9e01 PCX924v2 + 1369 9f01 PCX924-Mic + 1369 9f02 PCX924-Mic + 1369 a001 PCX22v2 + 1369 a701 LCM220v2 + 1369 a801 LCM200 + 1397 3136 4xS0-ISDN PCI Adapter + 1397 3137 S2M-E1-ISDN PCI Adapter + 1518 0200 ThinkIO-C + 15ed 1002 MCCS 8-port Serial Hot Swap + 15ed 1003 MCCS 16-port Serial Hot Swap +# MIL-STD-1553B Board + e1c5 0001 TE1-PCI + e1c5 0005 TA1-PCI + e1c5 0006 TA1-PCI4 + 9036 9036 + 9050 PCI <-> IOBus Bridge + 10b5 1067 IXXAT CAN i165 + 10b5 114e Wasco WITIO PCI168extended + 10b5 1169 Wasco OPTOIO32standard 32 digital in, 32 digital out + 10b5 1172 IK220 (Heidenhain) + 10b5 2036 SatPak GPS + 10b5 2221 Alpermann+Velte PCL PCI LV: Timecode Reader Board + 10b5 2273 SH ARC-PCI SOHARD ARCNET card + 10b5 2431 Alpermann+Velte PCL PCI D: Timecode Reader Board + 10b5 2905 Alpermann+Velte PCI TS: Time Synchronisation Board + 10b5 3196 Goramo PLX200SYN sync serial card + 10b5 9050 PCI-I04 PCI Passive PC/CAN Interface + 1369 8901 PCX11+ PCI + 1369 8f01 VX222 + 1369 9401 PCX924 + 1369 9501 PCX22 + 1498 0362 TPMC866 8 Channel Serial Card + 1522 0001 RockForce 4 Port V.90 Data/Fax/Voice Modem + 1522 0002 RockForce 2 Port V.90 Data/Fax/Voice Modem + 1522 0003 RockForce 6 Port V.90 Data/Fax/Voice Modem + 1522 0004 RockForce 8 Port V.90 Data/Fax/Voice Modem + 1522 0010 RockForce2000 4 Port V.90 Data/Fax/Voice Modem + 1522 0020 RockForce2000 2 Port V.90 Data/Fax/Voice Modem + 15ed 1000 Macrolink MCCS 8-port Serial + 15ed 1001 Macrolink MCCS 16-port Serial + 15ed 1002 Macrolink MCCS 8-port Serial Hot Swap + 15ed 1003 Macrolink MCCS 16-port Serial Hot Swap + 5654 2036 OpenSwitch 6 Telephony card + 5654 3132 OpenSwitch 12 Telephony card + 5654 5634 OpenLine4 Telephony Card + d531 c002 PCIntelliCAN 2xSJA1000 CAN bus + d84d 4006 EX-4006 1P + d84d 4008 EX-4008 1P EPP/ECP + d84d 4014 EX-4014 2P + d84d 4018 EX-4018 3P EPP/ECP + d84d 4025 EX-4025 1S(16C550) RS-232 + d84d 4027 EX-4027 1S(16C650) RS-232 + d84d 4028 EX-4028 1S(16C850) RS-232 + d84d 4036 EX-4036 2S(16C650) RS-232 + d84d 4037 EX-4037 2S(16C650) RS-232 + d84d 4038 EX-4038 2S(16C850) RS-232 + d84d 4052 EX-4052 1S(16C550) RS-422/485 + d84d 4053 EX-4053 2S(16C550) RS-422/485 + d84d 4055 EX-4055 4S(16C550) RS-232 + d84d 4058 EX-4055 4S(16C650) RS-232 + d84d 4065 EX-4065 8S(16C550) RS-232 + d84d 4068 EX-4068 8S(16C650) RS-232 + d84d 4078 EX-4078 2S(16C552) RS-232+1P + 9052 PCI9052 PCI <-> IOBus Bridge + 9054 PCI9054 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 2455 Wessex Techology PHIL-PCI + 10b5 2696 Innes Corp AM Radcap card + 10b5 2717 Innes Corp Auricon card + 10b5 2844 Innes Corp TVS Encoder card + 12c7 4001 Intel Dialogic DM/V960-4T1 PCI + 12d9 0002 PCI Prosody Card rev 1.5 + 14b4 d100 Dektec DTA-100 + 14b4 d114 Dektec DTA-120 + 16df 0011 PIKA PrimeNet MM PCI + 16df 0012 PIKA PrimeNet MM cPCI 8 + 16df 0013 PIKA PrimeNet MM cPCI 8 (without CAS Signaling) + 16df 0014 PIKA PrimeNet MM cPCI 4 + 16df 0015 PIKA Daytona MM + 16df 0016 PIKA InLine MM + 9056 PCI9056 32-bit 66MHz PCI <-> IOBus Bridge + 10b5 2979 CellinkBlade 11 - CPCI board VoATM AAL1 + 10b5 3268 IXXAT iPC-I XC16/PCIe CAN Board + 10b5 3334 Cambridge Pixel HPx Radar Input Card + 10b5 3352 Alpermann+Velte PCL PCIe HD: Timecode Reader Board + 10b5 3353 Alpermann+Velte PCL PCIe D: Timecode Reader Board + 10b5 3354 Alpermann+Velte PCL PCIe LV: Timecode Reader Board + 10b5 3355 Alpermann+Velte PCL PCIe L: Timecode Reader Board + 10b5 3415 Alpermann+Velte PCIe TS: Time Synchronisation Board + 10b5 3493 Alpermann+Velte PCL PCIe 3G: Timecode Reader Board + 10b5 3565 Cambridge Pixel HPx Radar Output Card + 1369 c001 LX6464ES + 1369 c201 LX1616ES + 14b4 d10a DekTec DTA-110T + 14b4 d128 Dektec DTA-140 + 14b4 d140 Dektec DTA-140 + 1a0e 006f Dektec DTA-111 + 9060 PCI9060 32-bit 33MHz PCI <-> IOBus Bridge + 906d 9060SD + 125c 0640 Aries 16000P + 906e 9060ES + 9080 PCI9080 32-bit; 33MHz PCI <-> IOBus Bridge + 103c 10eb (Agilent) E2777B 83K Series Optical Communication Interface + 103c 10ec (Agilent) E6978-66442 PCI CIC + 10b5 1123 Sectra KK631 encryption board + 10b5 9080 9080 [real subsystem ID not set] + 12d9 0002 PCI Prosody Card + 12df 4422 4422PCI ["Do-All" Telemetry Data Acquisition System] + 1369 9601 PCX822np + 1369 a102 PCX822v2 + 1369 a201 PCX442 + 1369 a301 LCM440v2 + 1369 a401 VX822 + 1369 a402 VX822v2 + 1369 a901 LCM420 + 1369 aa01 VX820v2 + 1517 000b ECSG-1R3ADC-PMC Clock synthesizer + 9656 PCI9656 PCI <-> IOBus Bridge + 1517 000f ECDR-GC314-PMC Receiver + 1885 0700 Tsunami FPGA PMC with Altera Stratix S40 + 1885 0701 Tsunami FPGA PMC with Altera Stratix S30 + 9733 PEX 9733 33-lane, 9-port PCI Express Gen 3 (8.0 GT/s) Switch + 1d49 0001 ThinkSystem 1610-4P NVMe Switch Adapter + 1d49 0002 ThinkSystem 810-4P NVMe Switch Adapter + 9749 PEX 9749 49-lane, 13-port PCI Express Gen 3 (8.0 GT/s) Switch + 1d49 0004 ThinkSystem 1610-8P NVMe Switch Adapter + a100 Blackmagic Design DeckLink + bb04 B&B 3PCIOSD1A Isolated PCI Serial + c001 CronyxOmega-PCI (8-port RS232) + d00d PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 9030 Digium Tormenta 2 T400P or E400P Quad T1 or E1 PCI card + d33d PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 9030 Tormenta 3 Varion V401PT Quad T1/J1 PCI card + d44d PCI9030 32-bit 33MHz PCI <-> IOBus Bridge + 10b5 17f6 Allo CP100P/E 1-port E1/T1/J1 PCI/PCIe card + 10b5 17f7 Allo CP400P/E 4-port E1/T1/J1 PCI/PCIe card + 10b5 17f8 Allo CP200P/E 2-port E1/T1/J1 PCI/PCIe card + 10b5 9030 Tormenta 3 Varion V401PE Quad E1 PCI card +10b6 Madge Networks + 0001 Smart 16/4 PCI Ringnode + 0002 Smart 16/4 PCI Ringnode Mk2 + 10b6 0002 Smart 16/4 PCI Ringnode Mk2 + 10b6 0006 16/4 CardBus Adapter + 0003 Smart 16/4 PCI Ringnode Mk3 + 0e11 b0fd Compaq NC4621 PCI, 4/16, WOL + 10b6 0003 Smart 16/4 PCI Ringnode Mk3 + 10b6 0007 Presto PCI Plus Adapter + 0004 Smart 16/4 PCI Ringnode Mk1 + 0006 16/4 Cardbus Adapter + 10b6 0006 16/4 CardBus Adapter + 0007 Presto PCI Adapter + 10b6 0007 Presto PCI + 0009 Smart 100/16/4 PCI-HS Ringnode + 10b6 0009 Smart 100/16/4 PCI-HS Ringnode + 000a Token Ring 100/16/4 Ringnode/Ringrunner + 10b6 000a Token Ring 100/16/4 Ringnode/Ringrunner + 000b 16/4 CardBus Adapter Mk2 + 10b6 0008 16/4 CardBus Adapter Mk2 + 10b6 000b 16/4 Cardbus Adapter Mk2 + 000c RapidFire 3140V2 16/4 TR Adapter + 10b6 000c RapidFire 3140V2 16/4 TR Adapter + 1000 Collage 25/155 ATM Client Adapter + 1001 Collage 155 ATM Server Adapter +10b7 3Com Corporation + 0001 3c985 1000BaseSX (SX/TX) +# wrong ID? + 9850 0001 3c985B-SX + 0013 AR5212 802.11abg NIC (3CRDAG675) + 10b7 2031 3CRDAG675 11a/b/g Wireless PCI Adapter + 0910 3C910-A01 + 1006 MINI PCI type 3B Data Fax Modem + 1007 Mini PCI 56k Winmodem + 10b7 615b Mini PCI 56K Modem + 10b7 615c Mini PCI 56K Modem + 1201 3c982-TXM 10/100baseTX Dual Port A [Hydra] + 1202 3c982-TXM 10/100baseTX Dual Port B [Hydra] + 1700 3c940 10/100/1000Base-T [Marvell] + 1043 80eb A7V600/P4P800/K8V motherboard + 10b7 0010 3C940 Gigabit LOM Ethernet Adapter + 10b7 0020 3C941 Gigabit LOM Ethernet Adapter + 147b 1407 KV8-MAX3 motherboard + 3390 3c339 TokenLink Velocity + 3590 3c359 TokenLink Velocity XL + 10b7 3590 TokenLink Velocity XL Adapter (3C359/359B) + 4500 3c450 HomePNA [Tornado] + 5055 3c555 Laptop Hurricane + 5057 3c575 Megahertz 10/100 LAN CardBus [Boomerang] + 10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus PC Card + 5157 3cCFE575BT Megahertz 10/100 LAN CardBus [Cyclone] + 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card + 5257 3cCFE575CT CardBus [Cyclone] + 10b7 5c57 FE575C-3Com 10/100 LAN CardBus-Fast Ethernet + 5900 3c590 10BaseT [Vortex] + 5920 3c592 EISA 10mbps Demon/Vortex + 5950 3c595 100BaseTX [Vortex] + 5951 3c595 100BaseT4 [Vortex] + 5952 3c595 100Base-MII [Vortex] + 5970 3c597 EISA Fast Demon/Vortex + 5b57 3c595 Megahertz 10/100 LAN CardBus [Boomerang] + 10b7 5b57 3C575 Megahertz 10/100 LAN Cardbus PC Card + 6000 3CRSHPW796 [OfficeConnect Wireless CardBus] + 6001 3com 3CRWE154G72 [Office Connect Wireless LAN Adapter] + 6055 3c556 Hurricane CardBus [Cyclone] + 6056 3c556B CardBus [Tornado] + 10b7 6556 10/100 Mini PCI Ethernet Adapter + 6560 3cCFE656 CardBus [Cyclone] + 10b7 656a 3CCFEM656 10/100 LAN+56K Modem CardBus + 6561 3cCFEM656 10/100 LAN+56K Modem CardBus + 10b7 656b 3CCFEM656 10/100 LAN+56K Modem CardBus + 6562 3cCFEM656B 10/100 LAN+Winmodem CardBus [Cyclone] + 10b7 656b 3CCFEM656B 10/100 LAN+56K Modem CardBus + 6563 3cCFEM656B 10/100 LAN+56K Modem CardBus + 10b7 656b 3CCFEM656 10/100 LAN+56K Modem CardBus + 6564 3cXFEM656C 10/100 LAN+Winmodem CardBus [Tornado] + 7646 3cSOHO100-TX Hurricane + 7770 3CRWE777 PCI Wireless Adapter [Airconnect] + 7940 3c803 FDDILink UTP Controller + 7980 3c804 FDDILink SAS Controller + 7990 3c805 FDDILink DAS Controller + 80eb 3c940B 10/100/1000Base-T + 8811 Token ring + 9000 3c900 10BaseT [Boomerang] + 9001 3c900 10Mbps Combo [Boomerang] + 9004 3c900B-TPO Etherlink XL [Cyclone] + 10b7 9004 3C900B-TPO Etherlink XL TPO 10Mb + 9005 3c900B-Combo Etherlink XL [Cyclone] + 10b7 9005 3C900B-Combo Etherlink XL Combo + 9006 3c900B-TPC Etherlink XL [Cyclone] + 900a 3c900B-FL 10base-FL [Cyclone] + 9050 3c905 100BaseTX [Boomerang] + 9051 3c905 100BaseT4 [Boomerang] + 9054 3C905B-TX Fast Etherlink XL PCI + 10b7 9054 3C905B-TX Fast Etherlink XL PCI + 9055 3c905B 100BaseTX [Cyclone] + 1028 0080 3C905B Fast Etherlink XL 10/100 + 1028 0081 3C905B Fast Etherlink XL 10/100 + 1028 0082 3C905B Fast Etherlink XL 10/100 + 1028 0083 3C905B Fast Etherlink XL 10/100 + 1028 0084 3C905B Fast Etherlink XL 10/100 + 1028 0085 3C905B Fast Etherlink XL 10/100 + 1028 0086 3C905B Fast Etherlink XL 10/100 + 1028 0087 3C905B Fast Etherlink XL 10/100 + 1028 0088 3C905B Fast Etherlink XL 10/100 + 1028 0089 3C905B Fast Etherlink XL 10/100 + 1028 0090 3C905B Fast Etherlink XL 10/100 + 1028 0091 3C905B Fast Etherlink XL 10/100 + 1028 0092 3C905B Fast Etherlink XL 10/100 + 1028 0093 3C905B Fast Etherlink XL 10/100 + 1028 0094 3C905B Fast Etherlink XL 10/100 + 1028 0095 3C905B Fast Etherlink XL 10/100 + 1028 0096 3C905B Fast Etherlink XL 10/100 + 1028 0097 3C905B Fast Etherlink XL 10/100 + 1028 0098 3C905B Fast Etherlink XL 10/100 + 1028 0099 3C905B Fast Etherlink XL 10/100 + 10b7 9055 3C905B Fast Etherlink XL 10/100 + 9056 3c905B-T4 Fast EtherLink XL [Cyclone] + 9058 3c905B Deluxe Etherlink 10/100/BNC [Cyclone] + 905a 3c905B-FX Fast Etherlink XL FX 100baseFx [Cyclone] + 9200 3c905C-TX/TX-M [Tornado] + 1028 0095 3C920 Integrated Fast Ethernet Controller + 1028 0097 3C920 Integrated Fast Ethernet Controller + 1028 00b4 OptiPlex GX110 + 1028 00d8 Precision 530 + 1028 00fe Optiplex GX240 + 1028 012a 3C920 Integrated Fast Ethernet Controller [Latitude C640] + 10b7 1000 3C905CX-TX/TX-M Fast Etherlink for PC Management NIC + 10b7 7000 10/100 Mini PCI Ethernet Adapter + 10f1 2466 Tiger MPX S2466 (3C920 Integrated Fast Ethernet Controller) + 144d c005 X10 Laptop + 9201 3C920B-EMB Integrated Fast Ethernet Controller [Tornado] + 1043 80ab A7N8X Deluxe onboard 3C920B-EMB Integrated Fast Ethernet Controller + 9202 3Com 3C920B-EMB-WNM Integrated Fast Ethernet Controller + 9210 3C920B-EMB-WNM Integrated Fast Ethernet Controller + 9300 3CSOHO100B-TX 910-A01 [tulip] + 9800 3c980-TX Fast Etherlink XL Server Adapter [Cyclone] + 10b7 9800 3c980-TX Fast Etherlink XL Server Adapter + 9805 3c980-C 10/100baseTX NIC [Python-T] + 10b7 1201 EtherLink Server 10/100 Dual Port A + 10b7 1202 EtherLink Server 10/100 Dual Port B + 10b7 9805 3c980 10/100baseTX NIC [Python-T] + 10f1 2462 Thunder K7 S2462 + 9900 3C990-TX [Typhoon] + 9902 3CR990-TX-95 [Typhoon 56-bit] + 9903 3CR990-TX-97 [Typhoon 168-bit] + 9904 3C990B-TX-M/3C990BSVR [Typhoon2] + 10b7 1000 3CR990B-TX-M [Typhoon2] + 10b7 2000 3CR990BSVR [Typhoon2 Server] + 9905 3CR990-FX-95/97/95 [Typhon Fiber] + 10b7 1101 3CR990-FX-95 [Typhoon Fiber 56-bit] + 10b7 1102 3CR990-FX-97 [Typhoon Fiber 168-bit] + 10b7 2101 3CR990-FX-95 Server [Typhoon Fiber 56-bit] + 10b7 2102 3CR990-FX-97 Server [Typhoon Fiber 168-bit] + 9908 3CR990SVR95 [Typhoon Server 56-bit] + 9909 3CR990SVR97 [Typhoon Server 168-bit] + 990a 3C990SVR [Typhoon Server] + 990b 3C990SVR [Typhoon Server] +10b8 Standard Microsystems Corp [SMC] + 0005 83c170 EPIC/100 Fast Ethernet Adapter + 1055 e000 LANEPIC 10/100 [EVB171Q-PCI] + 1055 e002 LANEPIC 10/100 [EVB171G-PCI] + 10b8 a011 EtherPower II 10/100 + 10b8 a014 EtherPower II 10/100 + 10b8 a015 EtherPower II 10/100 + 10b8 a016 EtherPower II 10/100 + 10b8 a017 EtherPower II 10/100 + 0006 83c175 EPIC/100 Fast Ethernet Adapter + 1055 e100 LANEPIC Cardbus Fast Ethernet Adapter + 1055 e102 LANEPIC Cardbus Fast Ethernet Adapter + 1055 e300 LANEPIC Cardbus Fast Ethernet Adapter + 1055 e302 LANEPIC Cardbus Fast Ethernet Adapter + 10b8 a012 LANEPIC Cardbus Fast Ethernet Adapter + 13a2 8002 LANEPIC Cardbus Fast Ethernet Adapter + 13a2 8006 LANEPIC Cardbus Fast Ethernet Adapter + 1000 FDC 37c665 + 1001 FDC 37C922 + a011 83C170QF + b106 SMC34C90 +# Split off ALi Corporation in 2003 +10b9 ULi Electronics Inc. + 0101 CMI8338/C3DX PCI Audio Device + 0111 C-Media CMI8738/C3DX Audio Device (OEM) + 10b9 0111 C-Media CMI8738/C3DX Audio Device (OEM) + 0780 Multi-IO Card + 0782 Multi-IO Card + 1435 M1435 + 1445 M1445 + 1449 M1449 + 1451 M1451 + 1461 M1461 + 1489 M1489 + 1511 M1511 [Aladdin] + 1512 M1512 [Aladdin] + 1513 M1513 [Aladdin] + 1521 M1521 [Aladdin III] + 10b9 1521 ALI M1521 Aladdin III CPU Bridge + 1523 M1523 + 10b9 1523 ALI M1523 ISA Bridge + 1531 M1531 [Aladdin IV] + 1533 M1533/M1535/M1543 PCI to ISA Bridge [Aladdin IV/V/V+] + 1014 053b ThinkPad R40e + 10b9 1533 ALi M1533 Aladdin IV/V ISA Bridge + 1541 M1541 + 10b9 1541 ALI M1541 Aladdin V/V+ AGP System Controller + 1543 M1543 + 1563 M1563 HyperTransport South Bridge + 10b9 1563 ASRock 939Dual-SATA2 Motherboard + 1849 1563 ASRock 939Dual-SATA2 Motherboard + 1573 PCI to LPC Controller + 1575 M1575 South Bridge + 1621 M1621 + 1631 ALI M1631 PCI North Bridge Aladdin Pro III + 1632 M1632M Northbridge+Trident + 1641 ALI M1641 PCI North Bridge Aladdin Pro IV + 1644 M1644/M1644T Northbridge+Trident + 1646 M1646 Northbridge+Trident + 1647 M1647 Northbridge [MAGiK 1 / MobileMAGiK 1] + 1651 M1651/M1651T Northbridge [Aladdin-Pro 5/5M,Aladdin-Pro 5T/5TM] + 1671 M1671 Super P4 Northbridge [AGP4X,PCI and SDR/DDR] + 1672 M1672 Northbridge [CyberALADDiN-P4] + 1681 M1681 P4 Northbridge [AGP8X,HyperTransport and SDR/DDR] + 1687 M1687 K8 Northbridge [AGP8X and HyperTransport] + 1689 M1689 K8 Northbridge [Super K8 Single Chip] + 1695 M1695 Host Bridge + 1697 M1697 HTT Host Bridge + 3141 M3141 + 3143 M3143 + 3145 M3145 + 3147 M3147 + 3149 M3149 + 3151 M3151 + 3307 M3307 + 3309 M3309 + 3323 M3325 Video/Audio Decoder + 5212 M4803 + 5215 MS4803 + 5217 M5217H + 5219 M5219 + 5225 M5225 + 5228 M5228 ALi ATA/RAID Controller + 5229 M5229 IDE + 1014 050f ThinkPad R30 + 1014 053d ThinkPad R40e + 103c 0024 Pavilion ze4400 builtin IDE + 103c 0025 XE4500 Notebook + 1043 8053 A7A266 Motherboard IDE + 1849 5229 ASRock 939Dual-SATA2 Motherboard IDE (PATA) + 5235 M5225 + 5237 USB 1.1 Controller + 1014 0540 ThinkPad R40e + 103c 0024 Pavilion ze4400 builtin USB + 103c 0025 XE4500 Notebook + 104d 810f VAIO PCG-U1 USB/OHCI Revision 1.0 + 10b9 5237 ASRock 939Dual-SATA2 Motherboard + 1849 5237 ASRock 939Dual-SATA2 Motherboard + 5239 USB 2.0 Controller + 10b9 5239 ASRock 939Dual-SATA2 Motherboard + 1849 5239 ASRock 939Dual-SATA2 Motherboard + 5243 M1541 PCI to AGP Controller + 5246 AGP8X Controller + 5247 PCI to AGP Controller + 5249 M5249 HTT to PCI Bridge + 524b PCI Express Root Port + 524c PCI Express Root Port + 524d PCI Express Root Port + 524e PCI Express Root Port + 5251 M5251 P1394 OHCI 1.0 Controller + 5253 M5253 P1394 OHCI 1.1 Controller + 5261 M5261 Ethernet Controller + 5263 ULi 1689,1573 integrated ethernet. + 5281 ALi M5281 Serial ATA / RAID Host Controller + 5287 ULi 5287 SATA + 5288 ULi M5288 SATA + 1043 8056 A8R-MVP Mainboard + 5289 ULi 5289 SATA + 5450 Lucent Technologies Soft Modem AMR + 5451 M5451 PCI AC-Link Controller Audio Device + 1014 0506 ThinkPad R30 + 1014 053e ThinkPad R40e + 103c 0024 Pavilion ze4400 builtin Audio + 103c 0025 XE4500 Notebook + 5453 M5453 PCI AC-Link Controller Modem Device + 5455 M5455 PCI AC-Link Controller Audio Device + 10b9 5455 ASRock 939Dual-SATA2 Motherboard + 1849 0850 ASRock 939Dual-SATA2 Motherboard + 5457 M5457 AC'97 Modem Controller + 1014 0535 ThinkPad R40e + 103c 0024 Pavilion ze4400 builtin Modem Device + 103c 0025 XE4500 Notebook + 5459 SmartLink SmartPCI561 56K Modem + 545a SmartLink SmartPCI563 56K Modem + 5461 HD Audio Controller + 5471 M5471 Memory Stick Controller + 5473 M5473 SD-MMC Controller + 7101 M7101 Power Management Controller [PMU] + 1014 0510 ThinkPad R30 + 1014 053c ThinkPad R40e + 103c 0024 Pavilion ze4400 + 103c 0025 XE4500 Notebook + 1849 7101 ASRock 939Dual-SATA2 Motherboard +10ba Mitsubishi Electric Corp. + 0301 AccelGraphics AccelECLIPSE + 0304 AccelGALAXY A2100 [OEM Evans & Sutherland] + 0308 Tornado 3000 [OEM Evans & Sutherland] + 10dd 0024 Tornado 3000 + 1002 VG500 [VolumePro Volume Rendering Accelerator] +10bb Dapha Electronics Corporation +10bc Advanced Logic Research +10bd Surecom Technology + 0e34 NE-34 +10be Tseng Labs International Co. +10bf Most Inc +10c0 Boca Research Inc. +10c1 ICM Co., Ltd. +10c2 Auspex Systems Inc. +10c3 Samsung Semiconductors, Inc. +10c4 Award Software International Inc. +10c5 Xerox Corporation +10c6 Rambus Inc. +10c7 Media Vision +10c8 Neomagic Corporation + 0001 NM2070 [MagicGraph 128] + 0002 NM2090 [MagicGraph 128V] + 0003 NM2093 [MagicGraph 128ZV] + 0004 NM2160 [MagicGraph 128XD] + 1014 00ba MagicGraph 128XD + 1025 1007 MagicGraph 128XD + 1028 0074 MagicGraph 128XD + 1028 0075 MagicGraph 128XD + 1028 007d MagicGraph 128XD + 1028 007e MagicGraph 128XD + 1033 802f MagicGraph 128XD + 104d 801b MagicGraph 128XD + 104d 802f MagicGraph 128XD + 104d 830b MagicGraph 128XD + 10ba 0e00 MagicGraph 128XD + 10c8 0004 MagicGraph 128XD + 10cf 1029 MagicGraph 128XD + 10f7 8308 MagicGraph 128XD + 10f7 8309 MagicGraph 128XD + 10f7 830b MagicGraph 128XD + 10f7 830d MagicGraph 128XD + 10f7 8312 MagicGraph 128XD + 0005 NM2200 [MagicGraph 256AV] + 1014 00dd ThinkPad 570 + 1028 0088 Latitude CPi A + 0006 NM2360 [MagicMedia 256ZX] + 1014 0152 ThinkPad 600X + 0016 NM2380 [MagicMedia 256XL+] + 10c8 0016 MagicMedia 256XL+ + 0025 NM2230 [MagicGraph 256AV+] + 0083 NM2093 [MagicGraph 128ZV+] + 8005 NM2200 [MagicMedia 256AV Audio] + 0e11 b0d1 MagicMedia 256AV Audio Device on Discovery + 0e11 b126 MagicMedia 256AV Audio Device on Durango + 1014 00dd ThinkPad 390/i1720/i1721 + 1025 1003 MagicMedia 256AV Audio Device on TravelMate 720 + 1028 0088 Latitude CPi A + 1028 008f MagicMedia 256AV Audio Device on Colorado Inspiron + 103c 0007 MagicMedia 256AV Audio Device on Voyager II + 103c 0008 MagicMedia 256AV Audio Device on Voyager III + 103c 000d MagicMedia 256AV Audio Device on Omnibook 900 + 10c8 8005 MagicMedia 256AV Audio Device on FireAnt + 110a 8005 MagicMedia 256AV Audio Device + 14c0 0004 MagicMedia 256AV Audio Device + 8006 NM2360 [MagicMedia 256ZX Audio] + 8016 NM2380 [MagicMedia 256XL+ Audio] +10c9 Dataexpert Corporation +10ca Fujitsu Microelectr., Inc. +10cb Omron Corporation +# nee Mentor ARC Inc +10cc Mai Logic Incorporated + 0660 Articia S Host Bridge + 0661 Articia S PCI Bridge +10cd Advanced System Products, Inc + 1100 ASC1100 + 1200 ASC1200 [(abp940) Fast SCSI-II] + 1300 ASC1300 / ASC3030 [ABP940-U / ABP960-U / ABP3925] + 10cd 1310 ASC1300/3030 SCSI adapter + 1195 1320 Ultra-SCSI CardBus PC Card REX CB31 + 2300 ABP940-UW + 2500 ABP940-U2W + 2700 ABP3950-U3W +10ce Radius +# nee Citicorp TTI +10cf Fujitsu Limited. + 01ef PCEA4 PCI-Express Dual Port ESCON Adapter + 1414 On-board USB 1.1 companion controller + 1415 On-board USB 2.0 EHCI controller + 1422 E8410 nVidia graphics adapter + 142d HD audio (Realtek ALC262) + 1430 82566MM Intel 1Gb copper LAN interface + 1623 PCEA4 PCI-Express Dual Port ESCON Adapter + 2001 mb86605 + 200c MB86613L IEEE1394 OHCI 1.0 Controller + 2010 MB86613S IEEE1394 OHCI 1.1 Controller + 2019 MB86295S [CORAL P] + 201e MB86296S [CORAL PA] + 202b MB86297A [Carmine Graphics Controller] +10d1 FuturePlus Systems Corp. +10d2 Molex Incorporated +10d3 Jabil Circuit Inc +10d4 Hualon Microelectronics +10d5 Autologic Inc. +10d6 Cetia +10d7 BCM Advanced Research +10d8 Advanced Peripherals Labs +10d9 Macronix, Inc. [MXIC] + 0431 MX98715 + 0512 MX98713 + 0531 MX987x5 + 1186 1200 DFE-540TX ProFAST 10/100 Adapter + 8625 MX86250 + 8626 Macronix MX86251 + 3Dfx Voodoo Rush + 8888 MX86200 +10da Compaq IPG-Austin + 0508 TC4048 Token Ring 4/16 + 3390 Tl3c3x9 +10db Rohm LSI Systems, Inc. +10dc CERN/ECP/EDU + 0001 STAR/RD24 SCI-PCI (PMC) + 0002 TAR/RD24 SCI-PCI (PMC) + 0021 HIPPI destination + 0022 HIPPI source + 10dc ATT2C15-3 FPGA +10dd Evans & Sutherland + 0100 Lightning 1200 + 10dd 0023 Lightning 1200 15+16M +10de NVIDIA Corporation + 0008 NV1 [STG2000X-B Series] + 0009 NV1 [NV1 Series] + 0018 NV3 [Riva 128] + 0019 NV3 [Riva 128ZX] + 0020 NV4 [Riva TNT] + 1043 0200 V3400 TNT + 1048 0c18 Erazor II SGRAM + 1048 0c19 Erazor II + 1048 0c1b Erazor II + 1048 0c1c Erazor II + 1092 0550 Viper V550 + 1092 0552 Viper V550 + 1092 4804 Viper V550 + 1092 4808 Viper V550 + 1092 4810 Viper V550 + 1092 4812 Viper V550 + 1092 4815 Viper V550 + 1092 4820 Viper V550 with TV out + 1092 4822 Viper V550 + 1092 4904 Viper V550 + 1092 4914 Viper V550 + 1092 8225 Viper V550 + 10b4 273d Velocity 4400 + 10b4 273e Velocity 4400 + 10b4 2740 Velocity 4400 + 10de 0020 Riva TNT + 1102 1015 Graphics Blaster CT6710 + 1102 1016 Graphics Blaster RIVA TNT + 0028 NV5 [Riva TNT2 / TNT2 Pro] + 1043 0200 AGP-V3800 SGRAM + 1043 0201 AGP-V3800 SDRAM + 1043 0205 PCI-V3800 + 1043 4000 AGP-V3800PRO + 1048 0c21 Synergy II + 1048 0c28 Erazor III + 1048 0c29 Erazor III + 1048 0c2a Erazor III + 1048 0c2b Erazor III + 1048 0c31 Erazor III Pro + 1048 0c32 Erazor III Pro + 1048 0c33 Erazor III Pro + 1048 0c34 Erazor III Pro + 107d 2134 WinFast 3D S320 II + TV-Out + 1092 4804 Viper V770 + 1092 4a00 Viper V770 + 1092 4a02 Viper V770 Ultra + 1092 5a00 RIVA TNT2/TNT2 Pro + 1092 5a40 Viper V770D AGP + 1092 6a02 Viper V770 Ultra + 1092 7a02 Viper V770 Ultra + 10de 0005 RIVA TNT2 Pro + 10de 000f Compaq NVIDIA TNT2 Pro + 1102 1020 3D Blaster RIVA TNT2 + 1102 1026 3D Blaster RIVA TNT2 Digital + 1462 8806 MS-8806 AGPhantom Graphics Card + 14af 5810 Maxi Gamer Xentor + 0029 NV5 [Riva TNT2 Ultra] + 1043 0200 AGP-V3800 Deluxe + 1043 0201 AGP-V3800 Ultra SDRAM + 1043 0205 PCI-V3800 Ultra + 1048 0c2e Erazor III Ultra + 1048 0c2f Erazor III Ultra + 1048 0c30 Erazor III Ultra + 1102 1021 3D Blaster RIVA TNT2 Ultra + 1102 1029 3D Blaster RIVA TNT2 Ultra + 1102 102f 3D Blaster RIVA TNT2 Ultra + 14af 5820 Maxi Gamer Xentor 32 + 4843 4f34 Dynamite + 002a NV5 [Riva TNT2] + 002b NV5 [Riva TNT2] + 002c NV5 [Vanta / Vanta LT] + 1043 0200 AGP-V3800 Combat SDRAM + 1043 0201 AGP-V3800 Combat + 1048 0c20 TNT2 Vanta + 1048 0c21 TNT2 Vanta + 1048 0c25 TNT2 Vanta 16MB + 1092 6820 Viper V730 + 1102 1031 CT6938 VANTA 8MB + 1102 1034 CT6894 VANTA 16MB + 14af 5008 Maxi Gamer Phoenix 2 + 002d NV5 [Riva TNT2 Model 64 / Model 64 Pro] + 1043 0200 AGP-V3800M + 1043 0201 AGP-V3800M + 1048 0c3a Erazor III LT + 1048 0c3b Erazor III LT + 107d 2137 WinFast 3D S325 + 10de 0006 RIVA TNT2 Model 64/Model 64 Pro + 10de 001e M64 AGP4x + 1102 1023 CT6892 RIVA TNT2 Value + 1102 1024 CT6932 RIVA TNT2 Value 32Mb + 1102 102c CT6931 RIVA TNT2 Value [Jumper] + 1102 1030 CT6931 RIVA TNT2 Value +# S26361-D1243-V116 + 110a 006f GM1000-16 +# S26361-D1243-V216 + 110a 0081 GM1000-16 + 1462 8808 MSI-8808 + 14af 5620 Gamer Cougar Video Edition + 1554 1041 Pixelview RIVA TNT2 M64 + 1569 002d Palit Microsystems Daytona TNT2 M64 + 0034 MCP04 SMBus + 0035 MCP04 IDE + 0036 MCP04 Serial ATA Controller + 0037 MCP04 Ethernet Controller + 0038 MCP04 Ethernet Controller + 003a MCP04 AC'97 Audio Controller + 003b MCP04 USB Controller + 003c MCP04 USB Controller + 003d MCP04 PCI Bridge + 003e MCP04 Serial ATA Controller + 0040 NV40 [GeForce 6800 Ultra] + 0041 NV40 [GeForce 6800] + 1043 817b V9999 Gamer Edition + 107d 2992 WinFast A400 + 1458 310f Geforce 6800 GV-N6812 + 0042 NV40 [GeForce 6800 LE] + 107d 299b WinFast A400 LE + 0043 NV40 [GeForce 6800 XE] + 0044 NV40 [GeForce 6800 XT] + 0045 NV40 [GeForce 6800 GT] + 1043 817d V9999GT + 1458 3140 GV-N68T256D + 0047 NV40 [GeForce 6800 GS] + 1682 2109 GeForce 6800 GS + 0048 NV40 [GeForce 6800 XT] + 004e NV40GL [Quadro FX 4000] + 0050 CK804 ISA Bridge + 1043 815a K8N4/A8N Series Mainboard + 10f1 2865 Tomcat K8E (S2865) + 1458 0c11 GA-K8N Ultra-9 Mainboard + 1462 7100 MSI K8N Diamond + 1462 7125 K8N Neo4-F mainboard + 147b 1c1a KN8-Ultra Mainboard + 1565 3402 NF4 AM2L Mainboard + 0051 CK804 ISA Bridge + 1028 0225 PowerEdge T105 ISA Bridge + 0052 CK804 SMBus + 1028 0225 PowerEdge T105 SMBus + 1043 815a K8N4/A8N Series Mainboard + 10f1 2865 Tomcat K8E (S2865) + 1458 0c11 GA-K8N Ultra-9 Mainboard + 1462 7100 MSI K8N Diamond + 1462 7125 K8N Neo4-F mainboard + 147b 1c1a KN8-Ultra Mainboard + 1565 3402 NF4 AM2L Mainboard + 0053 CK804 IDE + 1043 815a K8N4/A8N Series Mainboard + 10f1 2865 Tomcat K8E (S2865) + 1458 5002 GA-K8N Ultra-9 Mainboard + 1462 7100 MSI K8N Diamond + 1462 7125 K8N Neo4-F mainboard + 147b 1c1a KN8-Ultra Mainboard + 1565 3402 NF4 AM2L Mainboard + 0054 CK804 Serial ATA Controller + 1028 0225 PowerEdge T105 Serial ATA + 1043 815a A8N Series Mainboard + 10f1 2865 Tomcat K8E (S2865) + 1458 b003 GA-K8N Ultra-9 Mainboard + 1462 7100 MSI K8N Diamond + 1462 7125 K8N Neo4-F mainboard + 147b 1c1a KN8-Ultra Mainboard + 1565 5401 NF4 AM2L Mainboard + 0055 CK804 Serial ATA Controller + 1028 0225 PowerEdge T105 Serial ATA + 1043 815a K8N4/A8N Series Mainboard + 10f1 2865 Tomcat K8E (S2865) + 1458 b003 GA-K8N Ultra-9 Mainboard + 1462 7125 K8N Neo4-F mainboard + 147b 1c1a KN8-Ultra Mainboard + 1565 5401 NF4 AM2L Mainboard + 0056 CK804 Ethernet Controller + 0057 CK804 Ethernet Controller + 1043 8141 K8N4/A8N Series Mainboard + 10de cb84 NF4 Lanparty + 10f1 2865 Tomcat K8E (S2865) + 1458 e000 GA-K8N Ultra-9 Mainboard + 1462 7100 MSI K8N Diamond + 1462 7125 K8N Neo4-F mainboard + 147b 1c1a KN8-Ultra Mainboard + 1565 2501 NF4 AM2L Mainboard + 0058 CK804 AC'97 Modem + 0059 CK804 AC'97 Audio Controller + 1043 812a K8N4/A8N Series Mainboard + 10f1 2865 Tomcat K8E (S2865) + 1462 7585 K8N Neo4-F mainboard + 147b 1c1a KN8-Ultra Mainboard + 1565 8211 NF4 AM2L Mainboard + 005a CK804 USB Controller + 1028 0225 PowerEdge T105 onboard USB + 1043 815a K8N4/A8N Series Mainboard + 10f1 2865 Tomcat K8E (S2865) + 1458 5004 GA-K8N Ultra-9 Mainboard + 1462 7100 MSI K8N Diamond + 1462 7125 K8N Neo4-F mainboard + 147b 1c1a KN8-Ultra Mainboard + 1565 3402 NF4 AM2L Mainboard + 005b CK804 USB Controller + 1028 0225 PowerEdge T105 onboard USB + 1043 815a K8N4/A8N Series Mainboard + 10f1 2865 Tomcat K8E (S2865) + 1458 5004 GA-K8N Ultra-9 Mainboard + 1462 7100 MSI K8N Diamond + 1462 7125 K8N Neo4-F mainboard + 147b 1c1a KN8-Ultra Mainboard + 1565 3402 NF4 AM2L Mainboard + 005c CK804 PCI Bridge + 005d CK804 PCIE Bridge + 005e CK804 Memory Controller + 1028 0225 PowerEdge T105 Memory Controller + 1043 815a A8N Series Mainboard + 10de 005e ECS Elitegroup NFORCE3-A939 motherboard. + 10f1 2865 Tomcat K8E (S2865) + 10f1 2891 Thunder K8SRE Mainboard + 1458 5000 GA-K8N Ultra-9 Mainboard + 1462 7100 K8N Diamond Mainboard + 1462 7125 K8N Neo4-F Mainboard + 147b 1c1a KN8-Ultra Mainboard + 1565 3402 NF4 AM2L Mainboard + 005f CK804 Memory Controller + 0060 nForce2 ISA Bridge + 1043 80ad A7N8X Mainboard + 147b 1c02 NF7-S/NF7 (nVidia-nForce2) 2.X + a0a0 03ba UK79G-1394 motherboard + 0064 nForce2 SMBus (MCP) + 147b 1c02 NF7-S/NF7 (nVidia-nForce2) 2.X + a0a0 03bb UK79G-1394 motherboard + 0065 nForce2 IDE + 10de 0c11 nForce 2 EIDE Controller + a0a0 03b2 UK79G-1394 motherboard + 0066 nForce2 Ethernet Controller + 1043 80a7 A7N8X Mainboard onboard nForce2 Ethernet + 10de 0c11 nForce MCP-T Networking Adapter + a0a0 03b3 UK79G-1394 motherboard + 0067 nForce2 USB Controller + 1043 0c11 A7N8X Mainboard + a0a0 03b4 UK79G-1394 motherboard + 0068 nForce2 USB Controller + 1043 0c11 A7N8X Mainboard + a0a0 03b4 UK79G-1394 motherboard + 006a nForce2 AC97 Audio Controler (MCP) + 1043 8095 nForce2 AC97 Audio Controller (MCP) + a0a0 0304 UK79G-1394 motherboard + 006b nForce Audio Processing Unit + 10de 006b nForce2 MCP Audio Processing Unit + a0a0 0304 UK79G-1394 motherboard + 006c nForce2 External PCI Bridge + 006d nForce2 PCI Bridge + 006e nForce2 FireWire (IEEE 1394) Controller + a0a0 0306 UK79G-1394 motherboard + 0080 MCP2A ISA bridge + 147b 1c09 NV7 Motherboard + 0084 MCP2A SMBus + 147b 1c09 NV7 Motherboard + 0085 MCP2A IDE + 147b 1c09 NV7 Motherboard + 0086 MCP2A Ethernet Controller + 0087 MCP2A USB Controller + 147b 1c09 NV7 Motherboard + 0088 MCP2A USB Controller + 147b 1c09 NV7 Motherboard + 008a MCP2S AC'97 Audio Controller + 147b 1c09 NV7 Motherboard + 008b MCP2A PCI Bridge + 008c MCP2A Ethernet Controller + 008e nForce2 Serial ATA Controller + 0090 G70 [GeForce 7800 GTX] + 0091 G70 [GeForce 7800 GTX] + 0092 G70 [GeForce 7800 GT] + 0093 G70 [GeForce 7800 GS] + 0095 G70 [GeForce 7800 SLI] + 0097 G70 [GeForce GTS 250] + 0098 G70M [GeForce Go 7800] + 0099 G70M [GeForce Go 7800 GTX] + 009d G70GL [Quadro FX 4500] + 00a0 NV0A [Aladdin TNT2 IGP] + 14af 5810 Maxi Gamer Xentor + 00c0 NV41 [GeForce 6800 GS] + 00c1 NV41 [GeForce 6800] + 00c2 NV41 [GeForce 6800 LE] + 00c3 NV41 [GeForce 6800 XT] + 00c5 NV41 + 00c6 NV41 + 00c7 NV41 + 00c8 NV41M [GeForce Go 6800] + 00c9 NV41M [GeForce Go 6800 Ultra] + 00cc NV41GLM [Quadro FX Go1400] + 00cd NV42GL [Quadro FX 3450/4000 SDI] + 10de 029b Quadro FX 3450 + 00ce NV41GL [Quadro FX 1400] + 00cf NV41 + 00d0 nForce3 LPC Bridge + 00d1 nForce3 Host Bridge + 00d2 nForce3 AGP Bridge + 00d3 CK804 Memory Controller + 00d4 nForce3 SMBus + 00d5 nForce3 IDE + 00d6 nForce3 Ethernet + 00d7 nForce3 USB 1.1 + 00d8 nForce3 USB 2.0 + 00d9 nForce3 Audio + 00da nForce3 Audio + 00dd nForce3 PCI Bridge + 00df CK8S Ethernet Controller + 1043 80a7 K8N-E + 105b 0c43 Winfast NF3250K8AA + 147b 1c0b NF8 Mainboard + 00e0 nForce3 250Gb LPC Bridge + 1043 813f K8N-E + 10de 0c11 Winfast NF3250K8AA + 1462 7030 K8N Neo-FSR v2.0 + 147b 1c0b NF8 Mainboard + 1849 00e0 Motherboard (one of many) + 00e1 nForce3 250Gb Host Bridge + 1043 813f K8N-E + 1462 7030 K8N Neo-FSR v2.0 + 147b 1c0b NF8 Mainboard + 1849 00e1 Motherboard (one of many) + 00e2 nForce3 250Gb AGP Host to PCI Bridge + 00e3 nForce3 Serial ATA Controller + 1043 813f K8N-E + 105b 0c43 Winfast NF3250K8AA + 147b 1c0b NF8 Mainboard + 1849 00e3 Motherboard (one of many) + 00e4 nForce 250Gb PCI System Management + 1043 813f K8N-E + 105b 0c43 Winfast NF3250K8AA + 1462 7030 K8N Neo-FSR v2.0 + 147b 1c0b NF8 Mainboard + 1849 00e4 Motherboard (one of many) + 00e5 CK8S Parallel ATA Controller (v2.5) + 1043 813f K8N-E + 105b 0c43 Winfast NF3250K8AA + 1462 7030 K8N Neo-FSR v2.0 + 147b 1c0b NF8 Mainboard + 1849 00e5 Motherboard (one of many) + f849 00e5 Motherboard (one of many) + 00e6 CK8S Ethernet Controller + 00e7 CK8S USB Controller + 1043 813f K8N-E + 105b 0c43 Winfast NF3250K8AA + 1462 7030 K8N Neo-FSR v2.0 + 147b 1c0b NF8 Mainboard + 1849 00e7 Motherboard (one of many) + 00e8 nForce3 EHCI USB 2.0 Controller + 1043 813f K8N-E + 105b 0c43 Winfast NF3250K8AA + 1462 7030 K8N Neo-FSR v2.0 + 147b 1c0b NF8 Mainboard + 1849 00e8 Motherboard (one of many) + 00ea nForce3 250Gb AC'97 Audio Controller + 1043 819d K8N-E + 105b 0c43 Winfast NF3250K8AA + 1462 b010 K8N Neo-FSR v2.0 + 147b 1c0b NF8 Mainboard + 00ed nForce3 250Gb PCI-to-PCI Bridge + 00ee nForce3 Serial ATA Controller 2 + 00f1 NV43 [GeForce 6600 GT] + 1043 81a6 N6600GT TD 128M AGP + 1043 81c6 N6600GT TD 128M AGP + 1458 3150 GV-N66T128VP + 1554 1191 PixelView PV-N43UA (128KD) + 1682 2119 GeForce 6600 GT AGP + 00f2 NV43 [GeForce 6600] + 1554 1194 PixelView PV-N43AT (256KD) + 1682 211c GeForce 6600 256MB DDR DUAL DVI TV + 00f3 NV43 [GeForce 6200] + 00f4 NV43 [GeForce 6600 LE] + 00f5 G71 [GeForce 7800 GS] + 00f6 NV43 [GeForce 6800 GS/XT] + 1682 217e XFX GeForce 6800 XTreme 256MB DDR3 AGP + 00f8 NV45GL [Quadro FX 3400/4400] + 00f9 NV40 [GeForce 6800 GT/GTO/Ultra] + 10de 00f9 NV40 [GeForce 6800 GT] + 1682 2120 GEFORCE 6800 GT PCI-E + 00fa NV39 [GeForce PCX 5750] + 00fb NV35 [GeForce PCX 5900] + 00fc NV37GL [Quadro FX 330/GeForce PCX 5300] + 00fd NV37GL [Quadro PCI-E Series] + 00fe NV38GL [Quadro FX 1300] + 00ff NV19 [GeForce PCX 4300] + 0100 NV10 [GeForce 256 SDR] + 1043 0200 AGP-V6600 SGRAM + 1043 0201 AGP-V6600 SDRAM + 1043 4008 AGP-V6600 SGRAM + 1043 4009 AGP-V6600 SDRAM + 1048 0c41 Erazor X + 1048 0c43 ERAZOR X PCI + 1048 0c48 Synergy Force + 1102 102d CT6941 GeForce 256 + 14af 5022 3D Prophet SE + 0101 NV10 [GeForce 256 DDR] + 1043 0202 AGP-V6800 DDR + 1043 400a AGP-V6800 DDR SGRAM + 1043 400b AGP-V6800 DDR SDRAM + 1048 0c42 Erazor X + 107d 2822 WinFast GeForce 256 + 1102 102e CT6970/CT6971 + 14af 5021 3D Prophet DDR-DVI + 0103 NV10GL [Quadro] + 1048 0c40 GLoria II-64 + 1048 0c44 GLoria II + 1048 0c45 GLoria II + 1048 0c4a GLoria II-64 Pro + 1048 0c4b GLoria II-64 Pro DVII + 10a9 9002 VPro VR3 + 0110 NV11 [GeForce2 MX/MX 400] + 1043 4015 AGP-V7100 Pro + 1043 4021 V7100 Deluxe Combo + 1043 4031 V7100 Pro with TV output + 1048 0c60 Gladiac MX + 1048 0c61 Gladiac 511PCI + 1048 0c63 Gladiac 511TV-OUT 32MB + 1048 0c64 Gladiac 511TV-OUT 64MB + 1048 0c65 Gladiac 511TWIN + 1048 0c66 Gladiac 311 + 10b0 0001 GeForce2 MX Jumbo TV + 10de 0091 Dell OEM GeForce 2 MX 400 + 10de 00a1 Apple OEM GeForce2 MX + 1462 8523 MS-8852 + 1462 8817 MSI GeForce2 MX400 Pro32S [MS-8817] + 14af 7102 3D Prophet II MX + 14af 7103 3D Prophet II MX Dual-Display + 1545 0023 Xtasy Rev. B2 + 1554 1081 MVGA-NVG11AM(400) + 0111 NV11 [GeForce2 MX200] + 0112 NV11M [GeForce2 Go] + 0113 NV11GL [Quadro2 MXR/EX/Go] + 1028 00e5 Quadro2 Go + 0140 NV43 [GeForce 6600 GT] + 1458 3125 GV-NX66T128D + 1458 3126 GV-NX66T256DE + 1462 8939 MS-8983 + 0141 NV43 [GeForce 6600] + 1043 81b0 EN6600 Silencer + 107d 593a LR2A22 128MB TV OUT + 107d 597b WINFAST PX6600 + 1458 3124 GV-NX66128DP Turbo Force Edition + 0142 NV43 [GeForce 6600 LE] + 0143 NV43 [GeForce 6600 VE] + 0144 NV43M [GeForce Go 6600] + 0145 NV43 [GeForce 6610 XL] + 0146 NV43M [GeForce Go6200 TE / 6600 TE] + 0147 NV43 [GeForce 6700 XL] + 0148 NV43M [GeForce Go 6600] + 0149 NV43M [GeForce Go 6600 GT] + 014a NV43 [Quadro NVS 440] + 014b NV43 + 014d NV43GL [Quadro FX 550] + 014e NV43GL [Quadro FX 540] + 014f NV43 [GeForce 6200] + 0150 NV15 [GeForce2 GTS/Pro] + 1043 4016 V7700 AGP Video Card + 1043 402a AGP-V7700 + 1048 0c50 Gladiac + 1048 0c52 Gladiac-64 + 107d 2840 WinFast GeForce2 GTS with TV output + 107d 2842 WinFast GeForce 2 Pro + 10de 002e GeForce2 GTS + 1462 815a MS-8815 + 1462 8831 Creative GeForce2 Pro + 0151 NV15 [GeForce2 Ti] + 1043 405f V7700Ti + 1462 5506 Creative 3D Blaster GeForce2 Titanium + 1462 8364 MS-8836 + 0152 NV15 [GeForce2 Ultra] + 1048 0c56 GLADIAC Ultra + 0153 NV15GL [Quadro2 Pro] + 0160 NV44 [GeForce 6500] + 0161 NV44 [GeForce 6200 TurboCache] + 0162 NV44 [GeForce 6200 SE TurboCache] + 0163 NV44 [GeForce 6200 LE] + 0164 NV44M [GeForce Go 6200] + 0165 NV44 [Quadro NVS 285] + 0166 NV44M [GeForce Go 6400] + 0167 NV44M [GeForce Go 6200] + 0168 NV44M [GeForce Go 6400] + 0169 NV44 [GeForce 6250] + 016a NV44 [GeForce 7100 GS] + 016d NV44 + 016e NV44 + 016f NV44 + 0170 NV17 [GeForce4 MX 460] + 1462 8630 MS-8863 + 0171 NV17 [GeForce4 MX 440] + 10b0 0002 Gainward Pro/600 TV + 10de 0008 Apple OEM GeForce4 MX 440 + 1462 8661 G4MX440-VTP + 1462 8730 MX440SES-T (MS-8873) + 1462 8743 MS-8874 + 1462 8852 GeForce4 MX440 PCI + 147b 8f00 Abit Siluro GeForce4MX440 + 0172 NV17 [GeForce4 MX 420] + 1462 8730 MS-8873 + 1462 8784 MS-8878 + 0173 NV17 [GeForce4 MX 440-SE] + 0174 NV17M [GeForce4 440 Go] + 0175 NV17M [GeForce4 420 Go] + 0176 NV17M [GeForce4 420 Go 32M] + 103c 08b0 tc1100 tablet + 144d c005 X10 Laptop + 4c53 1090 Cx9 / Vx9 mainboard + 0177 NV17M [GeForce4 460 Go] + 0178 NV17GL [Quadro4 550 XGL] + 0179 NV17M [GeForce4 440 Go 64M] + 10de 0179 GeForce4 MX (Mac) + 017a NV17GL [Quadro NVS] + 017b NV17GL [Quadro4 550 XGL] + 017c NV17GL [Quadro4 500 GoGL] + 017f NV17 + 0181 NV18 [GeForce4 MX 440 AGP 8x] + 1043 8063 GeForce4 MX 440 AGP 8X + 1043 806f V9180 Magic + 1462 8880 MS-StarForce GeForce4 MX 440 with AGP8X + 1462 8900 MS-8890 GeForce 4 MX440 AGP8X + 1462 9350 MSI GeForce4 MX T8X with AGP8X + 147b 8f0d Siluro GF4 MX-8X + 1554 1111 PixelView MVGA-NVG18A + 0182 NV18 [GeForce4 MX 440SE AGP 8x] + 0183 NV18 [GeForce4 MX 420 AGP 8x] + 0184 NV18 [GeForce4 MX] + 0185 NV18 [GeForce4 MX 4000] + 0186 NV18M [GeForce4 448 Go] + 0187 NV18M [GeForce4 488 Go] + 0188 NV18GL [Quadro4 580 XGL] + 0189 NV18 [GeForce4 MX with AGP8X (Mac)] + 018a NV18GL [Quadro NVS 280 SD] + 018b NV18GL [Quadro4 380 XGL] + 018c NV18GL [Quadro NVS 50 PCI] + 018d NV18M [GeForce4 448 Go] + 0190 G80 [GeForce 8800 GTS / 8800 GTX] + 0191 G80 [GeForce 8800 GTX] + 0192 G80 [GeForce 8800 GTS] + 0193 G80 [GeForce 8800 GTS] + 107d 20bd WinFast PX 8800 GTS TDH + 0194 G80 [GeForce 8800 Ultra] + 0197 G80GL [Tesla C870] + 019d G80GL [Quadro FX 5600] + 019e G80GL [Quadro FX 4600] + 01a0 nForce 220/420 NV1A [GeForce2 MX] + 01a4 nForce CPU bridge + 01ab nForce 420 Memory Controller (DDR) + 01ac nForce 220/420 Memory Controller + 01ad nForce 220/420 Memory Controller + 01b0 nForce Audio Processing Unit + 01b1 nForce AC'97 Audio Controller + 01b2 nForce ISA Bridge + 01b4 nForce PCI System Management + 01b7 nForce AGP to PCI Bridge + 01b8 nForce PCI-to-PCI bridge + 01bc nForce IDE + 01c1 nForce AC'97 Modem Controller + 01c2 nForce USB Controller + 01c3 nForce Ethernet Controller + 01d0 G72 [GeForce 7350 LE] + 01d1 G72 [GeForce 7300 LE] + 107d 5efa WinFast PX7300LE-TD128 + 107d 5efb WinFast PX7300LE-TD256 + 1462 0345 7300LE PCI Express Graphics Adapter + 01d2 G72 [GeForce 7550 LE] + 01d3 G72 [GeForce 7200 GS / 7300 SE] + 1043 8203 EN7300SE + 1043 8250 EN7200GS + 01d5 G72 + 01d6 G72M [GeForce Go 7200] + 01d7 G72M [Quadro NVS 110M/GeForce Go 7300] + 01d8 G72M [GeForce Go 7400] + 1028 01d7 XPS M1210 + 01d9 G72M [GeForce Go 7450] + 01da G72M [Quadro NVS 110M] + 01db G72M [Quadro NVS 120M] + 01dc G72GLM [Quadro FX 350M] + 01dd G72 [GeForce 7500 LE] + 01de G72GL [Quadro FX 350] + 10de 01dc Quadro FX Go350M + 01df G72 [GeForce 7300 GS] + 01e0 nForce2 IGP2 + 147b 1c09 NV7 Motherboard + 01e8 nForce2 AGP + 01ea nForce2 Memory Controller 0 + a0a0 03b9 UK79G-1394 motherboard + 01eb nForce2 Memory Controller 1 + a0a0 03b9 UK79G-1394 motherboard + 01ec nForce2 Memory Controller 2 + a0a0 03b9 UK79G-1394 motherboard + 01ed nForce2 Memory Controller 3 + a0a0 03b9 UK79G-1394 motherboard + 01ee nForce2 Memory Controller 4 + 10de 01ee MSI Delta-L nForce2 memory controller + a0a0 03b9 UK79G-1394 motherboard + 01ef nForce2 Memory Controller 5 + a0a0 03b9 UK79G-1394 motherboard + 01f0 NV1F C17 [GeForce4 MX IGP] + a0a0 03b5 UK79G-1394 motherboard + 0200 NV20 [GeForce3] + 1043 402f AGP-V8200 DDR + 1048 0c70 GLADIAC 920 + 0201 NV20 [GeForce3 Ti 200] + 0202 NV20 [GeForce3 Ti 500] + 1043 405b V8200 T5 + 1545 002f Xtasy 6964 + 0203 NV20GL [Quadro DCC] + 0211 NV48 [GeForce 6800] + 0212 NV48 [GeForce 6800 LE] + 0215 NV48 [GeForce 6800 GT] + 0218 NV48 [GeForce 6800 XT] + 0221 NV44A [GeForce 6200] + 1043 81e1 N6200/TD/256M/A + 3842 a341 256A8N341DX + 0222 NV44 [GeForce 6200 A-LE] + 0224 NV44 + 0240 C51PV [GeForce 6150] + 1043 81cd A8N-VM CSM + 1462 7207 K8NGM2 series + 0241 C51 [GeForce 6150 LE] + 0242 C51G [GeForce 6100] + 105b 0cad Winfast 6100K8MB + 0243 C51 PCI Express Bridge + 0244 C51 [GeForce Go 6150] + 103c 30b5 Presario V3242AU + 103c 30b7 Presario V6133CL + 10de 0244 GeForce Go 6150 + 0245 C51 [Quadro NVS 210S/GeForce 6150LE] + 0246 C51 PCI Express Bridge + 0247 C51 [GeForce Go 6100] + 1043 1382 MCP51 PCI-X GeForce Go 6100 + 0248 C51 PCI Express Bridge + 0249 C51 PCI Express Bridge + 024a C51 PCI Express Bridge + 024b C51 PCI Express Bridge + 024c C51 PCI Express Bridge + 024d C51 PCI Express Bridge + 024e C51 PCI Express Bridge + 024f C51 PCI Express Bridge + 0250 NV25 [GeForce4 Ti 4600] + 0251 NV25 [GeForce4 Ti 4400] + 1043 8023 v8440 GeForce 4 Ti4400 + 10de 0251 PNY GeForce4 Ti 4400 + 1462 8710 PNY GeForce4 Ti 4400 + 0252 NV25 [GeForce4 Ti] + 0253 NV25 [GeForce4 Ti 4200] + 107d 2896 WinFast A250 LE TD (Dual VGA/TV-out/DVI) + 147b 8f09 Siluro (Dual VGA/TV-out/DVI) + 0258 NV25GL [Quadro4 900 XGL] + 0259 NV25GL [Quadro4 750 XGL] + 025b NV25GL [Quadro4 700 XGL] + 0260 MCP51 LPC Bridge + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81bc A8N-VM CSM Mainboard + 1458 5001 GA-M55plus-S3G + 1462 7207 K8NGM2 series + 0261 MCP51 LPC Bridge + 105b 0cad Winfast 6100K8MB + 0262 MCP51 LPC Bridge + 0263 MCP51 LPC Bridge + 0264 MCP51 SMBus + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81bc A8N-VM CSM Mainboard + 105b 0cad Winfast 6100K8MB + 1462 7207 K8NGM2 series + 0265 MCP51 IDE + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81bc A8N-VM CSM Mainboard + 1462 7207 K8NGM2 series +# Foxconn has used a wrong vendor ID for this one + f05b 0cad Winfast 6100K8MB + 0266 MCP51 Serial ATA Controller + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81bc A8N-VM CSM Mainboard + 1462 7207 K8NGM2 series + 0267 MCP51 Serial ATA Controller + 103c 2a34 Pavilion a1677c + 1043 81bc A8N-VM CSM Mainboard + 1462 7207 K8NGM2 series + 0268 MCP51 Ethernet Controller + 0269 MCP51 Ethernet Controller + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 8141 A8N-VM CSM Mainboard + 1462 7207 K8NGM2 series + 026a MCP51 MCI + 026b MCP51 AC97 Audio Controller + 105b 0cad Winfast 6100K8MB + 026c MCP51 High Definition Audio + 103c 2a34 Pavilion a1677c + 103c 30b5 Presario V3242AU + 103c 30b7 Presario V6133CL + 10de cb84 ASUSTeK Computer Inc. A8N-VM CSM Mainboard + 1462 7207 K8NGM2 series + 026d MCP51 USB Controller + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81bc A8N-VM CSM Mainboard + 105b 0cad Winfast 6100K8MB + 1462 7207 K8NGM2 series + 026e MCP51 USB Controller + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81bc A8N-VM CSM Mainboard + 105b 0cad Winfast 6100K8MB + 1462 7207 K8NGM2 series + 026f MCP51 PCI Bridge + 103c 30b7 Presario V6133CL + 0270 MCP51 Host Bridge + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81bc A8N-VM CSM Mainboard + 105b 0cad Winfast 6100K8MB + 1458 5001 GA-M55plus-S3G + 1462 7207 K8NGM2 series + 0271 MCP51 PMU + 103c 30b5 Presario V3242AU + 103c 30b7 Presario V6133CL + 0272 MCP51 Memory Controller 0 + 103c 2a34 Pavilion a1677c + 105b 0cad Winfast 6100K8MB + 027e C51 Memory Controller 2 + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81cd A8N-VM CSM Mainboard + 1458 5000 GA-M55plus-S3G + 1462 7207 K8NGM2 series + 027f C51 Memory Controller 3 + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81cd A8N-VM CSM Mainboard + 1458 5000 GA-M55plus-S3G + 1462 7207 K8NGM2 series + 0280 NV28 [GeForce4 Ti 4800] + 0281 NV28 [GeForce4 Ti 4200 AGP 8x] + 0282 NV28 [GeForce4 Ti 4800 SE] + 0286 NV28M [GeForce4 Ti 4200 Go AGP 8x] + 0288 NV28GL [Quadro4 980 XGL] + 0289 NV28GL [Quadro4 780 XGL] + 028c NV28GLM [Quadro4 Go700] + 0290 G71 [GeForce 7900 GTX] + 0291 G71 [GeForce 7900 GT/GTO] + 10de 042b NX7900GTO-T2D512E [7900 GTO] + 0292 G71 [GeForce 7900 GS] + 0293 G71 [GeForce 7900 GX2] + 0294 G71 [GeForce 7950 GX2] + 0295 G71 [GeForce 7950 GT] + 1043 8225 GeForce 7950 GT + 107d 2a68 WinFast PX7950GT TDH + 1462 0663 NX7950GT-VT2D512EZ-HD + 0297 G71M [GeForce Go 7950 GTX] + 0298 G71M [GeForce Go 7900 GS] + 0299 G71M [GeForce Go 7900 GTX] + 029a G71GLM [Quadro FX 2500M] + 029b G71GLM [Quadro FX 1500M] + 029c G71GL [Quadro FX 5500] + 029d G71GL [Quadro FX 3500] + 1028 019b G71GLM [Quadro FX 3500M] + 029e G71GL [Quadro FX 1500] + 029f G71GL [Quadro FX 4500 X2] +# Xbox Graphics Processing Unit (Integrated). GeForce3 derivative (NV20 < NV2A < NV25). + 02a0 NV2A [XGPU] + 02a5 MCPX CPU Bridge + 02a6 MCPX Memory Controller + 02e0 G73 [GeForce 7600 GT] + 02e0 2249 GF 7600GT 560M 256MB DDR3 DUAL DVI TV + 02e1 G73 [GeForce 7600 GS] + 1682 222b PV-T73K-UAL3 (256MB) + 1682 2247 GF 7600GS 512MB DDR2 + 02e2 G73 [GeForce 7300 GT] + 02e3 G71 [GeForce 7900 GS] + 02e4 G71 [GeForce 7950 GT] + 1682 2271 PV-T71A-YDF7 (512MB) + 02f0 C51 Host Bridge + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81cd A8N-VM CSM Mainboard + 1462 7207 K8NGM2 series + 02f1 C51 Host Bridge + 1458 5000 GA-M55plus-S3G + 02f2 C51 Host Bridge + 02f3 C51 Host Bridge + 02f4 C51 Host Bridge + 02f5 C51 Host Bridge + 02f6 C51 Host Bridge + 02f7 C51 Host Bridge + 02f8 C51 Memory Controller 5 + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81cd A8N-VM CSM Mainboard + 1458 5000 GA-M55plus-S3G + 1462 7207 K8NGM2 series + 02f9 C51 Memory Controller 4 + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81cd A8N-VM CSM Mainboard + 1458 5000 GA-M55plus-S3G + 1462 7207 K8NGM2 series + 02fa C51 Memory Controller 0 + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81cd A8N-VM CSM Mainboard + 1458 5000 GA-M55plus-S3G + 1462 7207 K8NGM2 series + 02fb C51 PCI Express Bridge + 02fc C51 PCI Express Bridge + 103c 30b7 Presario V6133CL + 02fd C51 PCI Express Bridge + 103c 30b7 Presario V6133CL + 02fe C51 Memory Controller 1 + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81cd A8N-VM CSM Mainboard + 1458 5000 GA-M55plus-S3G + 1462 7207 K8NGM2 series + 02ff C51 Host Bridge + 103c 2a34 Pavilion a1677c + 103c 30b7 Presario V6133CL + 1043 81cd A8N-VM CSM Mainboard + 1458 5000 GA-M55plus-S3G + 1462 7207 K8NGM2 series + 0300 NV30 [GeForce FX] + 0301 NV30 [GeForce FX 5800 Ultra] + 0302 NV30 [GeForce FX 5800] + 0308 NV30GL [Quadro FX 2000] + 0309 NV30GL [Quadro FX 1000] + 0311 NV31 [GeForce FX 5600 Ultra] + 0312 NV31 [GeForce FX 5600] + 0314 NV31 [GeForce FX 5600XT] + 1043 814a V9560XT/TD + 0316 NV31M + 0318 NV31GL + 031a NV31M [GeForce FX Go5600] + 031b NV31M [GeForce FX Go5650] + 031c NV31GLM [Quadro FX Go700] + 0320 NV34 [GeForce FX 5200] + 0321 NV34 [GeForce FX 5200 Ultra] + 0322 NV34 [GeForce FX 5200] + 1043 02fb V9250 Magic + 1043 8180 V9520-X/TD/128M + 107d 2967 WinFast A340T 128MB + 1462 9110 MS-8911 (FX5200-TD128) + 1462 9171 MS-8917 (FX5200-T128) + 1462 9360 MS-8936 (FX5200-T128) + 1682 1351 GeForce FX 5200 + 0323 NV34 [GeForce FX 5200LE] + 0324 NV34M [GeForce FX Go5200 64M] + 1028 0196 Inspiron 5160 + 103c 006a Pavilion ZD7000 laptop + 1071 8160 MIM2000 + 0325 NV34M [GeForce FX Go5250] + 0326 NV34 [GeForce FX 5500] + 1458 310d GeForce FX 5500 128 MB + 1682 2034 GeForce 5500 256 MB + 0327 NV34 [GeForce FX 5100] + 0328 NV34M [GeForce FX Go5200 32M/64M] + 0329 NV34M [GeForce FX Go5200] + 10de 0010 Powerbook G4 + 032a NV34GL [Quadro NVS 280 PCI] + 032b NV34GL [Quadro FX 500/600 PCI] + 032c NV34M [GeForce FX Go5300 / Go5350] + 032d NV34M [GeForce FX Go5100] + 032e NV34 + 032f NV34 [GeForce FX 5200] + 0330 NV35 [GeForce FX 5900 Ultra] + 1043 8137 V9950 Ultra / 256 MB + 0331 NV35 [GeForce FX 5900] + 1043 8145 V9950GE + 0332 NV35 [GeForce FX 5900XT] + 0333 NV38 [GeForce FX 5950 Ultra] + 0334 NV35 [GeForce FX 5900ZT] + 1462 9373 FX5900ZT-VTD128 (MS-8937) + 0338 NV35GL [Quadro FX 3000] + 033f NV35GL [Quadro FX 700] + 0341 NV36 [GeForce FX 5700 Ultra] + 1462 9380 MS-8938 (FX5700U-TD128) + 0342 NV36 [GeForce FX 5700] + 0343 NV36 [GeForce FX 5700LE] + 0344 NV36 [GeForce FX 5700VE] + 0347 NV36M [GeForce FX Go5700] + 103c 006a NX9500 + 0348 NV36M [GeForce FX Go5700] + 034c NV36 [Quadro FX Go1000] + 034d NV36 + 034e NV36GL [Quadro FX 1100] + 0360 MCP55 LPC Bridge + 0361 MCP55 LPC Bridge + 1028 0221 PowerEdge R805 MCP55 LPC Bridge + 0362 MCP55 LPC Bridge + 147b 1c24 KN9 series mainboard + 0363 MCP55 LPC Bridge + 0364 MCP55 LPC Bridge + 1028 0221 PowerEdge R805 MCP55 LPC Bridge + 0365 MCP55 LPC Bridge + 0366 MCP55 LPC Bridge + 0367 MCP55 LPC Bridge + 0368 MCP55 SMBus Controller + 1028 020c PowerEdge M605 MCP55 SMBus + 1028 0221 PowerEdge R805 MCP55 SMBus + 147b 1c24 KN9 series mainboard + 0369 MCP55 Memory Controller + 147b 1c24 KN9 series mainboard + 036a MCP55 Memory Controller + 036b MCP55 SMU + 036c MCP55 USB Controller + 1028 020c PowerEdge M605 MCP55 USB Controller + 1028 0221 PowerEdge R805 MCP55 USB Controller + 147b 1c24 KN9 series mainboard + 036d MCP55 USB Controller + 1028 020c PowerEdge M605 MCP55 USB Controller + 1028 0221 PowerEdge R805 MCP55 USB Controller + 147b 1c24 KN9 series mainboard + 036e MCP55 IDE + 147b 1c24 KN9 series mainboard + 0370 MCP55 PCI bridge + 0371 MCP55 High Definition Audio + 147b 1c24 KN9 series mainboard + 0372 MCP55 Ethernet + 0373 MCP55 Ethernet + 147b 1c24 KN9 series mainboard + 0374 MCP55 PCI Express bridge + 0375 MCP55 PCI Express bridge + 0376 MCP55 PCI Express bridge + 0377 MCP55 PCI Express bridge + 0378 MCP55 PCI Express bridge + 037a MCP55 Memory Controller + 037e MCP55 SATA Controller + 037f MCP55 SATA Controller + 1028 0221 PowerEdge R805 MCP55 SATA Controller + 147b 1c24 KN9 series mainboard + 038b G73 [GeForce 7650 GS] + 0390 G73 [GeForce 7650 GS] + 0391 G73 [GeForce 7600 GT] + 1458 3427 GV-NX76T128D-RH + 1462 0452 NX7600GT-VT2D256E + 0392 G73 [GeForce 7600 GS] + 1462 0622 NX7600GS-T2D256EH + 0393 G73 [GeForce 7300 GT] + 10de 0412 NX7300GT-TD256EH + 1462 0412 NX7300GT-TD256EH + 0394 G73 [GeForce 7600 LE] + 0395 G73 [GeForce 7300 GT] + 0396 G73 + 0397 G73M [GeForce Go 7700] + 0398 G73M [GeForce Go 7600] + 1025 006c Aspire 9814WKMi + 0399 G73M [GeForce Go 7600 GT] + 039a G73M [Quadro NVS 300M] + 039b G73M [GeForce Go 7900 SE] + 039c G73GLM [Quadro FX 550M] + 10de 039c Quadro FX 560M + 039d G73 + 039e G73GL [Quadro FX 560] + 039f G73 + 03a0 C55 Host Bridge + 03a1 C55 Host Bridge + 03a2 C55 Host Bridge + 03a3 C55 Host Bridge + 03a4 C55 Host Bridge + 03a5 C55 Host Bridge + 03a6 C55 Host Bridge + 03a7 C55 Host Bridge + 03a8 C55 Memory Controller + 03a9 C55 Memory Controller + 03aa C55 Memory Controller + 03ab C55 Memory Controller + 03ac C55 Memory Controller + 03ad C55 Memory Controller + 03ae C55 Memory Controller + 03af C55 Memory Controller + 03b0 C55 Memory Controller + 03b1 C55 Memory Controller + 03b2 C55 Memory Controller + 03b3 C55 Memory Controller + 03b4 C55 Memory Controller + 03b5 C55 Memory Controller + 03b6 C55 Memory Controller + 03b7 C55 PCI Express bridge + 03b8 C55 PCI Express bridge + 03b9 C55 PCI Express bridge + 03ba C55 Memory Controller + 03bb C55 PCI Express bridge + 03bc C55 Memory Controller + 03d0 C61 [GeForce 6150SE nForce 430] + 1028 020e Inspiron 531 + 03d1 C61 [GeForce 6100 nForce 405] + 03d2 C61 [GeForce 6100 nForce 400] + 03d5 C61 [GeForce 6100 nForce 420] + 03d6 C61 [GeForce 7025 / nForce 630a] + 03e0 MCP61 LPC Bridge + 1028 020e Inspiron 531 + 1849 03e0 939NF6G-VSTA Board + 03e1 MCP61 LPC Bridge + 1043 83a4 M4N68T series motherboard + 03e2 MCP61 Host Bridge + 1043 83a4 M4N68T series motherboard + 03e3 MCP61 LPC Bridge + 03e4 MCP61 High Definition Audio + 03e5 MCP61 Ethernet + 03e6 MCP61 Ethernet + 03e7 MCP61 SATA Controller + 03e8 MCP61 PCI Express bridge + 1028 020e Inspiron 531 + 1849 03e8 939NF6G-VSTA Board + 03e9 MCP61 PCI Express bridge + 1028 020e Inspiron 531 + 1849 03e9 939NF6G-VSTA Board + 03ea MCP61 Memory Controller + 1028 020e Inspiron 531 + 1849 03ea 939NF6G-VSTA Board + 03eb MCP61 SMBus + 1028 020e Inspiron 531 + 1043 83a4 M4N68T series motherboard + 1849 03eb 939NF6G-VSTA Board + 03ec MCP61 IDE + 1025 0392 ET1350 + 1028 020e Inspiron 531 + 1043 83a4 M4N68T series motherboard + 1849 03ec 939NF6G-VSTA Board + 03ee MCP61 Ethernet + 03ef MCP61 Ethernet + 1025 8000 ET1350 + 1028 020e Inspiron 531 + 1043 83a4 M4N68T series motherboard + 1849 03ef 939NF6G-VSTA Board + 03f0 MCP61 High Definition Audio + 1028 020e Inspiron 531 + 1043 8415 M4N68T series motherboard + 1849 0888 939NF6G-VSTA Board + 03f1 MCP61 USB 1.1 Controller + 1028 020e Inspiron 531 + 1043 83a4 M4N68T series motherboard + 1849 03f1 939NF6G-VSTA Board + 03f2 MCP61 USB 2.0 Controller + 1028 020e Inspiron 531 + 1043 83a4 M4N68T series motherboard + 1849 03f2 939NF6G-VSTA Board + 03f3 MCP61 PCI bridge + 1028 020e Inspiron 531 + 1849 03f3 939NF6G-VSTA Board + 03f4 MCP61 SMU + 03f5 MCP61 Memory Controller + 1028 020e Inspiron 531 + 1043 83a4 M4N68T series motherboard + 1849 03eb 939NF6G-VSTA Board + 03f6 MCP61 SATA Controller + 1028 020e Inspiron 531 + 1043 83a4 M4N68T series motherboard + 1849 03f6 939NF6G-VSTA Board + 03f7 MCP61 SATA Controller + 0400 G84 [GeForce 8600 GTS] + 1043 8241 EN8600GTS + 0401 G84 [GeForce 8600 GT] + 0402 G84 [GeForce 8600 GT] + 1458 3455 GV-NX86T512H + 1462 0910 NX8600GT-T2D256EZ + 0403 G84 [GeForce 8600 GS] + 0404 G84 [GeForce 8400 GS] + 1462 1230 NX8400GS-TD256E + 0405 G84M [GeForce 9500M GS] + 0406 G84 [GeForce 8300 GS] + 0407 G84M [GeForce 8600M GT] + 0408 G84M [GeForce 9650M GS] + 0409 G84M [GeForce 8700M GT] + 040a G84GL [Quadro FX 370] + 040b G84GLM [Quadro NVS 320M] + 040c G84GLM [Quadro FX 570M] + 17aa 20d9 ThinkPad T61p + 040d G84GLM [Quadro FX 1600M] + 040e G84GL [Quadro FX 570] + 040f G84GL [Quadro FX 1700] + 0410 G92 [GeForce GT 330] + 0414 G92 [GeForce 9800 GT] + 0418 G92 [GeForce GT 330 OEM] + 0420 G86 [GeForce 8400 SE] + 0421 G86 [GeForce 8500 GT] + 1462 0960 NX8500GT-TD512EH/M2 + 0422 G86 [GeForce 8400 GS] + 0423 G86 [GeForce 8300 GS] + 0424 G86 [GeForce 8400 GS] + 0425 G86M [GeForce 8600M GS] + 1025 0121 Aspire 5920G + 1043 1514 F3SV + 0426 G86M [GeForce 8400M GT] + 0427 G86M [GeForce 8400M GS] + 103c 30cc Pavilion dv6700 + 103c 30cf Pavilion dv9668eg Laptop + 0428 G86M [GeForce 8400M G] + 0429 G86M [Quadro NVS 140M] + 17aa 20d8 ThinkPad T61 + 042a G86M [Quadro NVS 130M] + 042b G86M [Quadro NVS 135M] + 042c G86 [GeForce 9400 GT] + 042d G86GLM [Quadro FX 360M] + 042e G86M [GeForce 9300M G] + 042f G86 [Quadro NVS 290] + 0440 MCP65 LPC Bridge + 0441 MCP65 LPC Bridge + 0442 MCP65 LPC Bridge + 103c 30cf Pavilion dv9668eg Laptop + 0443 MCP65 LPC Bridge + 0444 MCP65 Memory Controller + 103c 30cf Pavilion dv9668eg Laptop + 0445 MCP65 Memory Controller + 0446 MCP65 SMBus + 103c 30cf Pavilion dv9668eg Laptop + 0447 MCP65 SMU + 103c 30cf Pavilion dv9500/9600/9700 series + 0448 MCP65 IDE + 103c 30cf Pavilion dv9668eg Laptop + 0449 MCP65 PCI bridge + 10de cb84 HP Pavilion dv9668eg Laptop + 044a MCP65 High Definition Audio + 103c 30cf Pavilion dv9668eg Laptop + 044b MCP65 High Definition Audio + 044c MCP65 AHCI Controller + 044d MCP65 AHCI Controller + 044e MCP65 AHCI Controller + 044f MCP65 AHCI Controller + 0450 MCP65 Ethernet + 103c 30cf Pavilion dv9668eg Laptop + 0451 MCP65 Ethernet + 0452 MCP65 Ethernet + 0453 MCP65 Ethernet + 0454 MCP65 USB 1.1 OHCI Controller + 103c 30cf Pavilion dv9668eg Laptop + 0455 MCP65 USB 2.0 EHCI Controller + 103c 30cf Pavilion dv9668eg Laptop + 0456 MCP65 USB Controller + 0457 MCP65 USB Controller + 0458 MCP65 PCI Express bridge + 10de 0000 MCP65 PCI Express bridge + 0459 MCP65 PCI Express bridge + 10de 0000 MCP65 PCI Express bridge + 045a MCP65 PCI Express bridge + 10de 0000 MCP65 PCI Express bridge + 045b MCP65 PCI Express bridge + 10de 0000 MCP65 PCI Express bridge + 045c MCP65 SATA Controller + 045d MCP65 SATA Controller + 103c 30cf Pavilion dv9668eg Laptop + 045e MCP65 SATA Controller + 045f MCP65 SATA Controller + 0531 C67 [GeForce 7150M / nForce 630M] + 0533 C67 [GeForce 7000M / nForce 610M] + 053a C68 [GeForce 7050 PV / nForce 630a] + 053b C68 [GeForce 7050 PV / nForce 630a] + 1043 8308 M2N68-AM Motherboard + 053e C68 [GeForce 7025 / nForce 630a] + 0541 MCP67 Memory Controller + 0542 MCP67 SMBus + 1043 8308 M2N68-AM Motherboard + 0543 MCP67 Co-processor + 0547 MCP67 Memory Controller + 1043 8308 M2N68-AM Motherboard + 1849 0547 ALiveNF7G-HDready + 0548 MCP67 ISA Bridge + 1043 8308 M2N68-AM Motherboard + 054c MCP67 Ethernet + 1043 8308 M2N68-AM Motherboard + 1849 054c ALiveNF7G-HDready, MCP67 Gigabit Ethernet + 054d MCP67 Ethernet + 054e MCP67 Ethernet + 054f MCP67 Ethernet + 0550 MCP67 AHCI Controller + 1043 8308 M2N68-AM Motherboard + 0554 MCP67 AHCI Controller + 1043 8308 M2N68-AM Motherboard + 0555 MCP67 SATA Controller + 1043 8308 M2N68-AM Motherboard + 055c MCP67 High Definition Audio + 1043 8290 M2N68-AM Motherboard + 055d MCP67 High Definition Audio + 055e MCP67 OHCI USB 1.1 Controller + 1043 8308 M2N68-AM Motherboard + 055f MCP67 EHCI USB 2.0 Controller + 1043 8308 M2N68-AM Motherboard + 0560 MCP67 IDE Controller + f043 8308 M2N68-AM Motherboard + 0561 MCP67 PCI Bridge + 0562 MCP67 PCI Express Bridge + 1849 0562 ALiveNF7G-HDready + 0563 MCP67 PCI Express Bridge + 0568 MCP78S [GeForce 8200] Memory Controller + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 0568 K10N78FullHD-hSLI R3.0 Memory Controller + 0569 MCP78S [GeForce 8200] PCI Express Bridge + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 0569 K10N78FullHD-hSLI R3.0 PCI Express Bridge + 056a MCP73 [nForce 630i] USB 2.0 Controller (EHCI) + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 056c MCP73 IDE Controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 056d MCP73 PCI Express bridge + 1019 297a MCP73PVT-SM + 10de cb73 MCP73 PCI Bridge + 056e MCP73 PCI Express bridge + 1019 297a MCP73PVT-SM + 10de 0000 MCP73 PCIe x16 port + 056f MCP73 PCI Express bridge + 1019 297a MCP73PVT-SM + 10de 0000 MCP73 PCIe x1 port + 05b1 NF200 PCIe 2.0 switch + 05b8 NF200 PCIe 2.0 switch for GTX 295 + 05be NF200 PCIe 2.0 switch for Quadro Plex S4 / Tesla S870 / Tesla S1070 / Tesla S2050 + 05e0 GT200b [GeForce GTX 295] + 05e1 GT200 [GeForce GTX 280] + 05e2 GT200 [GeForce GTX 260] + 05e3 GT200b [GeForce GTX 285] + 1682 2490 GX-285N-ZDF + 05e6 GT200b [GeForce GTX 275] + 05e7 GT200GL [Tesla C1060 / M1060] + 10de 0595 Tesla T10 Processor + 10de 068f Tesla T10 Processor + 10de 0697 Tesla M1060 + 10de 0714 Tesla M1060 + 10de 0743 Tesla M1060 + 05ea GT200 [GeForce GTX 260] + 05eb GT200 [GeForce GTX 295] + 05ed GT200GL [Quadro Plex 2200 D2] + 05f1 GT200 [GeForce GTX 280] + 05f2 GT200 [GeForce GTX 260] + 05f8 GT200GL [Quadro Plex 2200 S4] + 05f9 GT200GL [Quadro CX] + 05fd GT200GL [Quadro FX 5800] + 05fe GT200GL [Quadro FX 4800] + 05ff GT200GL [Quadro FX 3800] + 0600 G92 [GeForce 8800 GTS 512] + 0601 G92 [GeForce 9800 GT] + 0602 G92 [GeForce 8800 GT] + 0603 G92 [GeForce GT 230 OEM] + 0604 G92 [GeForce 9800 GX2] + 0605 G92 [GeForce 9800 GT] + 0606 G92 [GeForce 8800 GS] + 0607 G92 [GeForce GTS 240] + 0608 G92M [GeForce 9800M GTX] + 0609 G92M [GeForce 8800M GTS] + 106b 00a7 GeForce 8800 GS + 060a G92M [GeForce GTX 280M] + 060b G92M [GeForce 9800M GT] + 060c G92M [GeForce 8800M GTX] + 060d G92 [GeForce 8800 GS] + 060f G92M [GeForce GTX 285M] + 0610 G92 [GeForce 9600 GSO] + 1682 2385 GeForce 9600 GSO 768mb + 0611 G92 [GeForce 8800 GT] + 107d 2ab0 Winfast PX8800 GT PCI-E + 1462 1170 NX8800GT series model V117 2xDVI+TV + 19da 1040 ZT-88TES2P-FSP + 0612 G92 [GeForce 9800 GTX / 9800 GTX+] + 0613 G92 [GeForce 9800 GTX+] + 0614 G92 [GeForce 9800 GT] + 107d 2ab3 WinFast PX9800 GT (S-Fanpipe) + 0615 G92 [GeForce GTS 250] + 3842 1150 GeForce GTS 250 P/N 512-P3-1150-TR +# Overclocked + 3842 1151 GeForce GTS 250 P/N 512-P3-1151-TR + 3842 1155 GeForce GTS 250 P/N 01G-P3-1155-TR +# Overclocked + 3842 1156 GeForce GTS 250 P/N 01G-P3-1156-TR + 0617 G92M [GeForce 9800M GTX] + 0618 G92M [GeForce GTX 260M] + 0619 G92GL [Quadro FX 4700 X2] + 061a G92GL [Quadro FX 3700] + 061b G92GL [Quadro VX 200] + 061c G92GLM [Quadro FX 3600M] + 061d G92GLM [Quadro FX 2800M] + 061e G92GLM [Quadro FX 3700M] + 061f G92GLM [Quadro FX 3800M] + 0620 G94 [GeForce 9800 GT] + 0621 G94 [GeForce GT 230] + 0622 G94 [GeForce 9600 GT] + 107d 2ac1 WinFast PX9600GT 1024MB + 1458 3481 GV-NX96T512HP + 0623 G94 [GeForce 9600 GS] + 0624 G94 [GeForce 9600 GT Green Edition] + 0625 G94 [GeForce 9600 GSO 512] + 0626 G94 [GeForce GT 130] + 0627 G94 [GeForce GT 140] + 0628 G94M [GeForce 9800M GTS] + 062a G94M [GeForce 9700M GTS] + 062b G94M [GeForce 9800M GS] + 062c G94M [GeForce 9800M GTS] + 062d G94 [GeForce 9600 GT] + 062e G94 [GeForce 9600 GT] + 106b 0605 GeForce GT 130 + 062f G94 [GeForce 9800 S] + 0630 G94 [GeForce 9600 GT] + 0631 G94M [GeForce GTS 160M] + 0632 G94M [GeForce GTS 150M] + 0633 G94 [GeForce GT 220] + 0635 G94 [GeForce 9600 GSO] + 0637 G94 [GeForce 9600 GT] + 0638 G94GL [Quadro FX 1800] + 063a G94GLM [Quadro FX 2700M] + 063f G94 [GeForce 9600 GE] + 0640 G96C [GeForce 9500 GT] + 0641 G96C [GeForce 9400 GT] + 1682 4009 PV-T94G-ZAFG + 0642 G96 [D9M-10] + 0643 G96 [GeForce 9500 GT] + 0644 G96 [GeForce 9500 GS] + 174b 9600 Geforce 9500GS 512M DDR2 V/D/HDMI + 0645 G96C [GeForce 9500 GS] + 0646 G96C [GeForce GT 120] + 0647 G96CM [GeForce 9600M GT] + 0648 G96CM [GeForce 9600M GS] + 0649 G96CM [GeForce 9600M GT] + 1043 202d GeForce GT 220M + 064a G96M [GeForce 9700M GT] + 064b G96M [GeForce 9500M G] + 064c G96CM [GeForce 9650M GT] + 064e G96C [GeForce 9600 GSO / 9800 GT] + 0651 G96CM [GeForce G 110M] + 0652 G96CM [GeForce GT 130M] + 152d 0850 GeForce GT 240M LE + 0653 G96CM [GeForce GT 120M] + 0654 G96CM [GeForce GT 220M] + 1043 14a2 GeForce GT 320M + 1043 14d2 GeForce GT 320M + 0655 G96 [GeForce GT 120 Mac Edition] + 0656 G96 [GeForce GT 120 Mac Edition] + 0658 G96GL [Quadro FX 380] + 0659 G96CGL [Quadro FX 580] + 065a G96GLM [Quadro FX 1700M] + 065b G96C [GeForce 9400 GT] + 065c G96GLM [Quadro FX 770M] + 065d G96 [GeForce 9500 GA / 9600 GT / GTS 250] + 065f G96C [GeForce G210] + 06c0 GF100 [GeForce GTX 480] + 06c4 GF100 [GeForce GTX 465] + 06ca GF100M [GeForce GTX 480M] + 06cb GF100 [GeForce GTX 480] + 06cd GF100 [GeForce GTX 470] + 06d0 GF100GL + 06d1 GF100GL [Tesla C2050 / C2070] + 10de 0771 Tesla C2050 + 10de 0772 Tesla C2070 + 06d2 GF100GL [Tesla M2070] + 10de 0774 Tesla M2070 + 10de 0830 Tesla M2070 + 10de 0842 Tesla M2070 + 10de 088f Tesla X2070 + 10de 0908 Tesla M2070 + 06d8 GF100GL [Quadro 6000] + 06d9 GF100GL [Quadro 5000] + 06da GF100GLM [Quadro 5000M] + 06dc GF100GL [Quadro 6000] + 06dd GF100GL [Quadro 4000] + 06de GF100GL [Tesla T20 Processor] + 10de 0773 Tesla S2050 + 10de 082f Tesla M2050 + 10de 0840 Tesla X2070 + 10de 0842 Tesla M2050 + 10de 0846 Tesla M2050 + 10de 0866 Tesla M2050 + 10de 0907 Tesla M2050 + 10de 091e Tesla M2050 + 06df GF100GL [Tesla M2070-Q] + 10de 084d Tesla M2070-Q + 10de 087f Tesla M2070-Q + 06e0 G98 [GeForce 9300 GE] + 107d 5a96 Geforce 9300GE + 06e1 G98 [GeForce 9300 GS] + 06e2 G98 [GeForce 8400] + 06e3 G98 [GeForce 8300 GS] + 06e4 G98 [GeForce 8400 GS Rev. 2] + 1458 3475 GV-NX84S256HE [GeForce 8400 GS] + 06e5 G98M [GeForce 9300M GS] + 06e6 G98 [GeForce G 100] + 06e7 G98 [GeForce 9300 SE] + 06e8 G98M [GeForce 9200M GS] + 103c 360b GeForce 9200M GE + 06e9 G98M [GeForce 9300M GS] + 1043 19b2 U6V laptop + 06ea G98M [Quadro NVS 150M] + 06eb G98M [Quadro NVS 160M] + 06ec G98M [GeForce G 105M] + 06ed G98 [GeForce 9600 GT / 9800 GT] + 06ee G98 [GeForce 9600 GT / 9800 GT] + 06ef G98M [GeForce G 103M] + 06f1 G98M [GeForce G 105M] + 06f8 G98 [Quadro NVS 420] + 06f9 G98GL [Quadro FX 370 LP] + 06fa G98 [Quadro NVS 450] + 06fb G98GLM [Quadro FX 370M] + 06fd G98 [Quadro NVS 295] + 06ff G98 [HICx16 + Graphics] + 10de 0711 HICx8 + Graphics + 0751 MCP78S [GeForce 8200] Memory Controller + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 0751 K10N78FullHD-hSLI R3.0 Memory Controller + 0752 MCP78S [GeForce 8200] SMBus + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 0752 K10N78FullHD-hSLI R3.0 SMBus + 0753 MCP78S [GeForce 8200] Co-Processor + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 0753 K10N78FullHD-hSLI R3.0 Co-Processor + 0754 MCP78S [GeForce 8200] Memory Controller + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 0754 K10N78FullHD-hSLI R3.0 Memory Controller + 0759 MCP78S [GeForce 8200] IDE + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 0759 K10N78FullHD-hSLI R3.0 IDE + 075a MCP78S [GeForce 8200] PCI Bridge + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1849 075a K10N78FullHD-hSLI R3.0 PCI Bridge + 075b MCP78S [GeForce 8200] PCI Express Bridge + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 075b K10N78FullHD-hSLI R3.0 PCI Express Bridge + 075c MCP78S [GeForce 8200] LPC Bridge + 103c 2a9e Pavilion p6310f + 1462 7508 K9N2GM-FIH + 1849 075c K10N78FullHD-hSLI R3.0 LPC Bridge + 075d MCP78S [GeForce 8200] LPC Bridge + 1043 82e8 M3N72-D + 0760 MCP77 Ethernet + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 0760 K10N78FullHD-hSLI R3.0 Ethernet + 0761 MCP77 Ethernet + 0762 MCP77 Ethernet + 0763 MCP77 Ethernet + 0774 MCP72XE/MCP72P/MCP78U/MCP78S High Definition Audio + 103c 2a9e Pavilion p6310f +# has a Realtek ALC1200 HDAudio Codec + 1043 82fe M3N72-D + 1462 7508 K9N2GM-FIH + 1849 3662 K10N78FullHD-hSLI R3.0 High Definition Audio + 0778 MCP78S [GeForce 8200] PCI Express Bridge + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 0778 K10N78FullHD-hSLI R3.0 PCI Express Bridge + 077a MCP78S [GeForce 8200] PCI Bridge + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 077a K10N78FullHD-hSLI R3.0 PCI Bridge + 077b MCP78S [GeForce 8200] OHCI USB 1.1 Controller + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 077b K10N78FullHD-hSLI R3.0 OHCI USB 1.1 Controller + 077c MCP78S [GeForce 8200] EHCI USB 2.0 Controller + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 077c K10N78FullHD-hSLI R3.0 EHCI USB 2.0 Controller + 077d MCP78S [GeForce 8200] OHCI USB 1.1 Controller + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 077d K10N78FullHD-hSLI R3.0 OHCI USB 1.1 Controller + 077e MCP78S [GeForce 8200] EHCI USB 2.0 Controller + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1462 7508 K9N2GM-FIH + 1849 077e K10N78FullHD-hSLI R3.0 EHCI USB 2.0 Controller + 07c0 MCP73 Host Bridge + 1afa 7150 JW-IN7150-HD + 07c1 MCP73 Host Bridge + 1019 297a MCP73PVT-SM + 07c2 MCP73 Host Bridge + 07c3 MCP73 Host Bridge + 147b 1c3e I-N73V motherboard + 07c5 MCP73 Host Bridge + 07c8 MCP73 Memory Controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07cb nForce 610i/630i memory controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07cd nForce 610i/630i memory controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07ce nForce 610i/630i memory controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07cf nForce 610i/630i memory controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07d0 nForce 610i/630i memory controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07d1 nForce 610i/630i memory controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07d2 nForce 610i/630i memory controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07d3 nForce 610i/630i memory controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07d6 nForce 610i/630i memory controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07d7 MCP73 LPC Bridge + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07d8 MCP73 SMBus + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07d9 MCP73 Memory Controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 07da MCP73 Co-processor + 1afa 7150 JW-IN7150-HD + 07dc MCP73 Ethernet + 147b 1c3e I-N73V motherboard + 07dd MCP73 Ethernet + 07de MCP73 Ethernet + 07df MCP73 Ethernet + 07e0 C73 [GeForce 7150 / nForce 630i] + 1afa 7150 JW-IN7150-HD + 07e1 C73 [GeForce 7100 / nForce 630i] + 1019 297a MCP73PVT-SM + 07e2 C73 [GeForce 7050 / nForce 630i] + 07e3 C73 [GeForce 7050 / nForce 610i] + 147b 1c3e I-N73V motherboard + 07e5 C73 [GeForce 7100 / nForce 620i] + 07f0 MCP73 SATA Controller (IDE mode) + 147b 1c3e I-N73V motherboard + 07f4 GeForce 7100/nForce 630i SATA + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 07f8 MCP73 SATA RAID Controller + 147b 1c3e I-N73V motherboard + 07fc MCP73 High Definition Audio + 1019 297a MCP73PVT-SM + 10de 07fc MCP73 High Definition Audio + 147b 1c3e I-N73V motherboard + 07fe MCP73 OHCI USB 1.1 Controller + 1019 297a MCP73PVT-SM + 147b 1c3e I-N73V motherboard + 1afa 7150 JW-IN7150-HD + 0840 C77 [GeForce 8200M] + 0844 C77 [GeForce 9100M G] + 0845 C77 [GeForce 8200M G] + 0846 C77 [GeForce 9200] + 0847 C78 [GeForce 9100] + 103c 2a9e Pavilion p6310f + 0848 C77 [GeForce 8300] + 0849 C77 [GeForce 8200] + 1462 7508 K9N2GM-FIH + 1849 0849 K10N78FullHD-hSLI R3.0 GeForce 8200 + 084a C77 [nForce 730a] + 084b C77 [GeForce 8200] + 084c C77 [nForce 780a/980a SLI] + 084d C77 [nForce 750a SLI] + 1043 82e8 M3N72-D mGPU + 084f C77 [GeForce 8100 / nForce 720a] + 0860 C79 [GeForce 9300] + 0861 C79 [GeForce 9400] + 0862 C79 [GeForce 9400M G] + 0863 C79 [GeForce 9400M] + 106b 00aa MacBook5,1 + 0864 C79 [GeForce 9300] + 0865 C79 [GeForce 9300 / ION] + 0866 C79 [GeForce 9400M G] + 106b 00b1 GeForce 9400M + 0867 C79 [GeForce 9400] + 106b 00ad iMac 9,1 + 0868 C79 [nForce 760i SLI] + 0869 MCP7A [GeForce 9400] + 086a C79 [GeForce 9400] + 086c C79 [GeForce 9300 / nForce 730i] + 086d C79 [GeForce 9200] + 086e C79 [GeForce 9100M G] + 086f MCP79 [GeForce 8200M G] + 0870 C79 [GeForce 9400M] + 0871 C79 [GeForce 9200] + 0872 C79 [GeForce G102M] + 1043 19b4 GeForce G102M + 1043 1aa2 GeForce G102M + 1043 1c02 GeForce G102M + 1043 1c42 GeForce G205M + 0873 C79 [GeForce G102M] + 1043 19b4 GeForce G102M + 1043 1c12 GeForce G102M + 1043 1c52 GeForce G205M + 0874 C79 [ION] + 0876 C79 [GeForce 9400M / ION] + 087a C79 [GeForce 9400] + 087d C79 [ION] + 19da a123 IONITX-F-E + 087e C79 [ION LE] + 087f C79 [ION LE] + 08a0 MCP89 [GeForce 320M] + 08a2 MCP89 [GeForce 320M] + 08a3 MCP89 [GeForce 320M] + 08a4 MCP89 [GeForce 320M] + 08a5 MCP89 [GeForce 320M] + 0a20 GT216 [GeForce GT 220] + 1043 8311 ENGT220/DI/1GD3(LP)/V2 + 0a21 GT216M [GeForce GT 330M] + 0a22 GT216 [GeForce 315] + 0a23 GT216 [GeForce 210] + 0a26 GT216 [GeForce 405] + 0a27 GT216 [GeForce 405] + 0a28 GT216M [GeForce GT 230M] + 0a29 GT216M [GeForce GT 330M] + 0a2a GT216M [GeForce GT 230M] + 0a2b GT216M [GeForce GT 330M] + 0a2c GT216M [NVS 5100M] + 0a2d GT216M [GeForce GT 320M] + 0a30 GT216 [GeForce 505] + 0a32 GT216 [GeForce GT 415] + 0a34 GT216M [GeForce GT 240M] + 0a35 GT216M [GeForce GT 325M] + 0a38 GT216GL [Quadro 400] + 0a3c GT216GLM [Quadro FX 880M] + 0a60 GT218 [GeForce G210] + 0a62 GT218 [GeForce 205] + 0a63 GT218 [GeForce 310] + 0a64 GT218 [ION] + 0a65 GT218 [GeForce 210] + 1043 8334 EN210 SILENT + 1458 36a9 GV-N210D3-1GI (rev. 6.0/6.1) + 1462 8094 N210 [Geforce 210] PCIe graphics adapter + 0a66 GT218 [GeForce 310] + 0a67 GT218 [GeForce 315] + 0a68 GT218M [GeForce G 105M] + 0a69 GT218M [GeForce G 105M] + 0a6a GT218M [NVS 2100M] + 0a6c GT218M [NVS 3100M] + 1028 040b Latitude E6510 + 17aa 2142 ThinkPad T410 + 0a6e GT218M [GeForce 305M] + 0a6f GT218M [ION] + 0a70 GT218M [GeForce 310M] + 0a71 GT218M [GeForce 305M] + 0a72 GT218M [GeForce 310M] + 0a73 GT218M [GeForce 305M] + 0a74 GT218M [GeForce G210M] + 1b0a 903a GeForce G210 + 0a75 GT218M [GeForce 310M] + 0a76 GT218M [ION 2] + 0a78 GT218GL [Quadro FX 380 LP] + 0a7a GT218M [GeForce 315M] + 104d 907e GeForce 315M + 1179 fc50 GeForce 315M + 1179 fc61 GeForce 315M + 1179 fc71 GeForce 315M + 1179 fc90 GeForce 315M + 1179 fcc0 GeForce 315M + 1179 fcd0 GeForce 315M + 1179 fce2 GeForce 315M + 1179 fcf2 GeForce 315M + 1179 fd16 GeForce 315M + 1179 fd40 GeForce 315M + 1179 fd50 GeForce 315M + 1179 fd52 GeForce 315M + 1179 fd61 GeForce 315M + 1179 fd71 GeForce 315M + 1179 fd92 GeForce 315M + 1179 fd96 GeForce 315M + 1179 fdd0 GeForce 315M + 1179 fdd2 GeForce 315M + 1179 fdfe GeForce 315M + 144d c0a2 GeForce 315M + 144d c0b2 GeForce 315M + 144d c581 GeForce 315M + 144d c587 GeForce 315M + 144d c588 GeForce 315M + 144d c597 GeForce 315M + 144d c606 GeForce 315M + 1462 aa51 GeForce 405 + 1462 aa58 GeForce 405 + 1462 ac71 GeForce 405 + 1462 ac81 GeForce 315M + 1462 ac82 GeForce 405 + 1462 ae33 GeForce 405 + 1642 3980 GeForce 405 + 17aa 3950 GeForce 405M + 17aa 397d GeForce 405M + 1b0a 2091 GeForce 315M + 1b0a 90b4 GeForce 405 + 1bfd 0003 GeForce 405 + 1bfd 8006 GeForce 405 + 1bfd 8007 GeForce 315M + 0a7b GT218 [GeForce 505] + 0a7c GT218GLM [Quadro FX 380M] + 0a80 MCP79 Host Bridge + 0a81 MCP79 Host Bridge + 0a82 MCP79 Host Bridge + 0a83 MCP79 Host Bridge + 0a84 MCP79 Host Bridge + 0a85 MCP79 Host Bridge + 0a86 MCP79 Host Bridge + 0a87 MCP79 Host Bridge + 0a88 MCP79 Memory Controller + 0a89 MCP79 Memory Controller + 0a98 MCP79 Memory Controller + 10de cb79 iMac 9,1 + 0aa0 MCP79 PCI Express Bridge + 10de cb79 Apple iMac 9,1 + 0aa2 MCP79 SMBus + 10de cb79 Apple iMac 9,1 + 19da a123 IONITX-F-E + 0aa3 MCP79 Co-processor + 10de cb79 Apple iMac 9,1 + 19da a123 IONITX-F-E + 0aa4 MCP79 Memory Controller + 19da a123 IONITX-F-E + 0aa5 MCP79 OHCI USB 1.1 Controller + 10de cb79 Apple iMac 9,1 + 19da a123 IONITX-F-E + 0aa6 MCP79 EHCI USB 2.0 Controller + 10de cb79 Apple iMac 9,1 + 19da a123 IONITX-F-E + 0aa7 MCP79 OHCI USB 1.1 Controller + 10de cb79 Apple iMac 9,1 + 19da a123 IONITX-F-E + 0aa8 MCP79 OHCI USB 1.1 Controller + 0aa9 MCP79 EHCI USB 2.0 Controller + 10de cb79 Apple iMac 9,1 + 19da a123 IONITX-F-E + 0aaa MCP79 EHCI USB 2.0 Controller + 0aab MCP79 PCI Bridge + 10de cb79 Apple iMac 9,1 + 0aac MCP79 LPC Bridge + 0aad MCP79 LPC Bridge + 19da a123 IONITX-F-E + 0aae MCP79 LPC Bridge + 10de cb79 Apple iMac 9,1 + 0aaf MCP79 LPC Bridge + 0ab0 MCP79 Ethernet + 10de cb79 Apple iMac 9,1 + 19da a123 IONITX-F-E + 0ab1 MCP79 Ethernet + 0ab2 MCP79 Ethernet + 0ab3 MCP79 Ethernet + 0ab4 MCP79 SATA Controller + 19da a123 IONITX-F-E + 0ab5 MCP79 SATA Controller + 0ab6 MCP79 SATA Controller + 0ab7 MCP79 SATA Controller + 0ab8 MCP79 AHCI Controller + 0ab9 MCP79 AHCI Controller + 10de cb79 Apple iMac 9,1 + 0aba MCP79 AHCI Controller + 0abb MCP79 AHCI Controller + 0abc MCP79 RAID Controller + 0abd MCP79 RAID Controller + 0abe MCP79 RAID Controller + 0abf MCP79 RAID Controller + 0ac0 MCP79 High Definition Audio + 10de cb79 Apple iMac 9,1 + 0ac1 MCP79 High Definition Audio + 0ac2 MCP79 High Definition Audio + 0ac3 MCP79 High Definition Audio + 0ac4 MCP79 PCI Express Bridge + 10de cb79 Apple iMac 9,1 + 0ac5 MCP79 PCI Express Bridge + 0ac6 MCP79 PCI Express Bridge + 10de cb79 Apple iMac 9,1 + 0ac7 MCP79 PCI Express Bridge + 10de cb79 Apple iMac 9,1 + 0ac8 MCP79 PCI Express Bridge + 0ad0 MCP78S [GeForce 8200] SATA Controller (non-AHCI mode) + 1462 7508 K9N2GM-FIH + 1849 0ad0 K10N78FullHD-hSLI R3.0 IDE + 0ad4 MCP78S [GeForce 8200] AHCI Controller + 103c 2a9e Pavilion p6310f + 1043 82e8 M3N72-D + 1849 0ad4 K10N78FullHD-hSLI R3.0 AHCI Controller + 0ad8 MCP78S [GeForce 8200] SATA Controller (RAID mode) + 0be2 GT216 HDMI Audio Controller + 1043 8311 ENGT220/DI/1GD3(LP)/V2 + 0be3 High Definition Audio Controller + 1028 040b Latitude E6510 + 10de 066d G98 [GeForce 8400GS] + 1462 8094 N210 [Geforce 210] PCIe graphics adapter + 0be4 High Definition Audio Controller + 0be5 GF100 High Definition Audio Controller + 0be9 GF106 High Definition Audio Controller + 1558 8687 CLEVO/KAPOK W860CU + 3842 1452 GeForce GTS 450 + 0bea GF108 High Definition Audio Controller + 3842 1430 GeForce GT 430 + 0beb GF104 High Definition Audio Controller + 1462 2322 N460GTX Cyclone 1GD5/OC + 0bee GF116 High Definition Audio Controller + 0bf0 Tegra2 PCIe x4 Bridge + 0bf1 Tegra2 PCIe x2 Bridge + 0ca0 GT215 [GeForce GT 330] + 0ca2 GT215 [GeForce GT 320] + 0ca3 GT215 [GeForce GT 240] + 0ca4 GT215 [GeForce GT 340] + 0ca5 GT215 [GeForce GT 220] + 0ca7 GT215 [GeForce GT 330] + 0ca8 GT215M [GeForce GTS 260M] + 0ca9 GT215M [GeForce GTS 250M] + 0cac GT215 [GeForce GT 220/315] + 0caf GT215M [GeForce GT 335M] + 0cb0 GT215M [GeForce GTS 350M] + 0cb1 GT215M [GeForce GTS 360M] + 0cbc GT215GLM [Quadro FX 1800M] + 0d60 MCP89 HOST Bridge + 0d68 MCP89 Memory Controller + 0d69 MCP89 Memory Controller + 0d76 MCP89 PCI Express Bridge + 0d79 MCP89 SMBus + 0d7a MCP89 Co-Processor + 0d7b MCP89 Memory Controller + 0d7d MCP89 Ethernet + 0d80 MCP89 LPC Bridge + 0d85 MCP89 SATA Controller + 0d88 MCP89 SATA Controller (AHCI mode) + 0d89 MCP89 SATA Controller (AHCI mode) + 0d8d MCP89 SATA Controller (RAID mode) + 0d94 MCP89 High Definition Audio + 0d9c MCP89 OHCI USB 1.1 Controller + 0d9d MCP89 EHCI USB 2.0 Controller + 0dc0 GF106 [GeForce GT 440] + 0dc4 GF106 [GeForce GTS 450] + 0dc5 GF106 [GeForce GTS 450 OEM] + 0dc6 GF106 [GeForce GTS 450 OEM] + 0dcd GF106M [GeForce GT 555M] + 0dce GF106M [GeForce GT 555M] + 0dd1 GF106M [GeForce GTX 460M] + 1558 8687 CLEVO/KAPOK W860CU + 0dd2 GF106M [GeForce GT 445M] + 0dd3 GF106M [GeForce GT 435M] + 0dd6 GF106M [GeForce GT 550M] + 0dd8 GF106GL [Quadro 2000] + 10de 0914 Quadro 2000D + 0dda GF106GLM [Quadro 2000M] + 0de0 GF108 [GeForce GT 440] + 0de1 GF108 [GeForce GT 430] + 3842 1430 GeForce GT 430 + 0de2 GF108 [GeForce GT 420] + 0de3 GF108M [GeForce GT 635M] + 0de4 GF108 [GeForce GT 520] + 0de5 GF108 [GeForce GT 530] + 0de7 GF108 [GeForce GT 610] + 0de8 GF108M [GeForce GT 620M] + 0de9 GF108M [GeForce GT 620M/630M/635M/640M LE] + 1025 0692 GeForce GT 620M + 1025 0725 GeForce GT 620M + 1025 0728 GeForce GT 620M + 1025 072b GeForce GT 620M + 1025 072e GeForce GT 620M + 1025 0753 GeForce GT 620M + 1025 0754 GeForce GT 620M + 17aa 3977 GeForce GT 640M LE + 1b0a 2210 GeForce GT 635M + 0dea GF108M [GeForce 610M] + 17aa 365a GeForce 615 + 17aa 365b GeForce 615 + 17aa 365e GeForce 615 + 17aa 3660 GeForce 615 + 17aa 366c GeForce 615 + 0deb GF108M [GeForce GT 555M] + 0dec GF108M [GeForce GT 525M] + 0ded GF108M [GeForce GT 520M] + 0dee GF108M [GeForce GT 415M] + 0def GF108M [NVS 5400M] + 0df0 GF108M [GeForce GT 425M] + 0df1 GF108M [GeForce GT 420M] + 0df2 GF108M [GeForce GT 435M] + 0df3 GF108M [GeForce GT 420M] + 0df4 GF108M [GeForce GT 540M] + 152d 0952 GeForce GT 630M + 152d 0953 GeForce GT 630M + 0df5 GF108M [GeForce GT 525M] + 0df6 GF108M [GeForce GT 550M] + 0df7 GF108M [GeForce GT 520M] + 0df8 GF108GL [Quadro 600] + 0df9 GF108GLM [Quadro 500M] + 0dfa GF108GLM [Quadro 1000M] + 0dfc GF108GLM [NVS 5200M] + 0e08 GF119 HDMI Audio Controller + 1043 83a0 ENGT520 SILENT +# 1024MB with passive cooling (heatsink) + 10b0 104a Gainward GeForce GT 610 + 0e09 GF110 High Definition Audio Controller + 0e0a GK104 HDMI Audio Controller + 0e0b GK106 HDMI Audio Controller + 0e0c GF114 HDMI Audio Controller + 0e0f GK208 HDMI/DP Audio Controller + 0e12 TegraK1 PCIe x4 Bridge + 0e13 TegraK1 PCIe x1 Bridge + 0e1a GK110 High Definition Audio Controller + 0e1b GK107 HDMI Audio Controller + 103c 197b ZBook 15 + 1043 8428 GTX650-DC-1GD5 + 0e1c Tegra3+ PCIe x4 Bridge + 0e1d Tegra3+ PCIe x2 Bridge + 0e22 GF104 [GeForce GTX 460] + 1462 2322 N460GTX Cyclone 1GD5/OC + 0e23 GF104 [GeForce GTX 460 SE] + 0e24 GF104 [GeForce GTX 460 OEM] + 0e30 GF104M [GeForce GTX 470M] + 0e31 GF104M [GeForce GTX 485M] + 0e3a GF104GLM [Quadro 3000M] + 0e3b GF104GLM [Quadro 4000M] + 0f00 GF108 [GeForce GT 630] + 0f01 GF108 [GeForce GT 620] + 0f02 GF108 [GeForce GT 730] + 0f03 GF108 [GeForce GT 610] + 0f06 GF108 [GeForce GT 730] + 0fb0 GM200 High Definition Audio + 0fb8 GP108 High Definition Audio Controller + 0fb9 GP107GL High Definition Audio Controller + 0fba GM206 High Definition Audio Controller + 0fbb GM204 High Definition Audio Controller + 0fc0 GK107 [GeForce GT 640 OEM] + 0fc1 GK107 [GeForce GT 640] + 0fc2 GK107 [GeForce GT 630 OEM] + 0fc5 GK107 [GeForce GT 1030] + 0fc6 GK107 [GeForce GTX 650] + 1043 8428 GTX650-DC-1GD5 + 0fc8 GK107 [GeForce GT 740] + 0fc9 GK107 [GeForce GT 730] + 0fcd GK107M [GeForce GT 755M] + 0fce GK107M [GeForce GT 640M LE] + 0fd1 GK107M [GeForce GT 650M] + 1043 1597 GeForce GT 650M + 1043 15a7 GeForce GT 650M + 1043 2103 N56VZ + 1043 2105 GeForce GT 650M + 1043 2141 GeForce GT 650M + 0fd2 GK107M [GeForce GT 640M] + 1028 054f GeForce GT 640M + 1028 055f GeForce GT 640M + 1028 0595 GeForce GT 640M LE + 1028 05b2 GeForce GT 640M LE + 0fd3 GK107M [GeForce GT 640M LE] + 0fd4 GK107M [GeForce GTX 660M] + 0fd5 GK107M [GeForce GT 650M Mac Edition] + 0fd8 GK107M [GeForce GT 640M Mac Edition] + 0fd9 GK107M [GeForce GT 645M] + 0fdb GK107M + 0fdf GK107M [GeForce GT 740M] + 0fe0 GK107M [GeForce GTX 660M Mac Edition] + 0fe1 GK107M [GeForce GT 730M] + 0fe2 GK107M [GeForce GT 745M] + 0fe3 GK107M [GeForce GT 745M] + 103c 2b16 GeForce GT 745A + 17aa 3675 GeForce GT 745A + 0fe4 GK107M [GeForce GT 750M] + 0fe5 GK107 [GeForce K340 USM] + 0fe6 GK107 [GRID K1 NVS USM] +# GRID K1 USM + 0fe7 GK107GL [GRID K100 vGPU] + 10de 101e GRID K100 + 0fe9 GK107M [GeForce GT 750M Mac Edition] + 0fea GK107M [GeForce GT 755M Mac Edition] + 0fec GK107M [GeForce 710A] + 0fed GK107M [GeForce 820M] + 0fee GK107M [GeForce 810M] + 0fef GK107GL [GRID K340] + 0ff1 GK107 [NVS 1000] + 0ff2 GK107GL [GRID K1] + 0ff3 GK107GL [Quadro K420] + 0ff5 GK107GL [GRID K1 Tesla USM] + 0ff6 GK107GLM [Quadro K1100M] + 103c 197b ZBook 15 +# GRID K1 Quadro USM + 0ff7 GK107GL [GRID K140Q vGPU] + 10de 1037 GRID K140Q + 0ff8 GK107GLM [Quadro K500M] + 0ff9 GK107GL [Quadro K2000D] + 0ffa GK107GL [Quadro K600] + 0ffb GK107GLM [Quadro K2000M] + 0ffc GK107GLM [Quadro K1000M] + 0ffd GK107 [NVS 510] + 0ffe GK107GL [Quadro K2000] + 0fff GK107GL [Quadro 410] + 1001 GK110B [GeForce GTX TITAN Z] + 1003 GK110 [GeForce GTX Titan LE] + 1004 GK110 [GeForce GTX 780] + 3842 0784 GK110B [GeForce GTX 780 SC w/ ACX Cooler] + 3842 1784 GK110B [GeForce GTX 780 Dual FTW w/ ACX Cooler] + 3842 1788 GK110B [GeForce GTX 780 Dual Classified w/ ACX Cooler] + 1005 GK110 [GeForce GTX TITAN] + 1043 8451 GTXTITAN-6GD5 +# Reference Model + 10de 1035 GeForce GTX Titan +# 06G-P4-2790-KR + 3842 2790 GeForce GTX Titan +# 06G-P4-2791-KR + 3842 2791 GeForce GTX Titan SC +# 06G-P4-2793-KR + 3842 2793 GeForce GTX Titan SC Signature +# 06G-P4-2794-KR + 3842 2794 GeForce GTX Titan SC Hydro Copper +# 06G-P4-2795-KR + 3842 2795 GeForce GTX Titan SC Hydro Copper Signature + 1007 GK110 [GeForce GTX 780 Rev. 2] + 1008 GK110 [GeForce GTX 780 Ti 6GB] + 100a GK110B [GeForce GTX 780 Ti] + 100c GK110B [GeForce GTX TITAN Black] + 101e GK110GL [Tesla K20X] + 101f GK110GL [Tesla K20] + 1020 GK110GL [Tesla K20X] + 1021 GK110GL [Tesla K20Xm] + 1022 GK110GL [Tesla K20c] + 1023 GK110BGL [Tesla K40m] + 10de 097e 12GB Computational Accelerator + 1024 GK180GL [Tesla K40c] + 1026 GK110GL [Tesla K20s] + 1027 GK110BGL [Tesla K40st] + 1028 GK110GL [Tesla K20m] + 1029 GK110BGL [Tesla K40s] + 102a GK110BGL [Tesla K40t] + 102d GK210GL [Tesla K80] + 102e GK110BGL [Tesla K40d] + 102f GK110BGL [Tesla Stella Solo] + 103a GK110GL [Quadro K6000] + 103c GK110GL [Quadro K5200] + 103f GK110BGL [Tesla Stella SXM] + 1040 GF119 [GeForce GT 520] + 1043 83a0 ENGT520 SILENT + 1042 GF119 [GeForce 510] + 1045 GF119 + 1048 GF119 [GeForce 605] + 1049 GF119 [GeForce GT 620 OEM] + 104a GF119 [GeForce GT 610] +# 1024MB with passive cooling (heatsink) + 10b0 104a Gainward GeForce GT 610 + 104b GF119 [GeForce GT 625 OEM] + 104c GF119 [GeForce GT 705] + 104d GF119 [GeForce GT 710] + 1050 GF119M [GeForce GT 520M] + 1051 GF119M [GeForce GT 520MX] + 1052 GF119M [GeForce GT 520M] + 1054 GF119M [GeForce 410M] + 1055 GF119M [GeForce 410M] + 1056 GF119M [NVS 4200M] + 1057 GF119M [Quadro NVS 4200M] + 1058 GF119M [GeForce 610M] + 103c 2aed GeForce 610 + 103c 2af1 GeForce 610 + 1043 10ac GeForce GT 610M + 1043 10bc GeForce GT 610M + 1043 1652 GeForce GT 610M + 17aa 367a GeForce 610M + 17aa 3682 GeForce 800A + 17aa 3687 GeForce 800A + 17aa 3692 GeForce 705A + 17aa 3695 GeForce 800A + 17aa a117 GeForce 610M + 1059 GF119M [GeForce 610M] + 105a GF119M [GeForce 610M] + 1043 2111 GeForce GT 610M + 1043 2112 GeForce GT 610M + 105b GF119M [GeForce 705M] + 103c 2afb GeForce 705A + 17aa 309d GeForce 705A + 17aa 30b1 GeForce 800A + 17aa 30f3 GeForce 705A + 17aa 36a1 GeForce 800A + 107c GF119 [NVS 315] + 107d GF119 [NVS 310] + 1080 GF110 [GeForce GTX 580] + 1081 GF110 [GeForce GTX 570] + 10de 087e Leadtek WinFast GTX 570 + 1082 GF110 [GeForce GTX 560 Ti OEM] + 1084 GF110 [GeForce GTX 560 OEM] + 1086 GF110 [GeForce GTX 570 Rev. 2] + 1087 GF110 [GeForce GTX 560 Ti 448 Cores] + 1088 GF110 [GeForce GTX 590] + 1089 GF110 [GeForce GTX 580 Rev. 2] + 108b GF110 [GeForce GTX 580] + 108e GF110GL [Tesla C2090] + 1091 GF110GL [Tesla M2090] + 10de 088e Tesla X2090 + 10de 0891 Tesla X2090 + 10de 0974 Tesla X2090 + 10de 098d Tesla X2090 + 1094 GF110GL [Tesla M2075] + 10de 0888 Tesla M2075 + 1096 GF110GL [Tesla C2050 / C2075] + 10de 0910 Tesla C2075 + 10de 0911 Tesla C2050 + 109a GF100GLM [Quadro 5010M] + 109b GF100GL [Quadro 7000] + 10de 0918 Quadro 7000 + 10c0 GT218 [GeForce 9300 GS Rev. 2] + 10c3 GT218 [GeForce 8400 GS Rev. 3] + 10c5 GT218 [GeForce 405] + 10d8 GT218 [NVS 300] + 10ef GP102 HDMI Audio Controller + 10f0 GP104 High Definition Audio Controller + 10f1 GP106 High Definition Audio Controller + 10f7 TU102 High Definition Audio Controller + 10f8 TU104 HD Audio Controller + 10f9 TU106 High Definition Audio Controller + 1043 8673 TURBO-RTX2070-8G + 1140 GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M] + 1019 0799 GeForce 820M + 1019 999f GeForce GT 720M + 1025 0600 GeForce GT 620M + 1025 0606 GeForce GT 620M + 1025 064a GeForce GT 620M + 1025 064c GeForce GT 620M + 1025 067a GeForce GT 620M + 1025 0680 GeForce GT 620M + 1025 0686 GeForce 710M + 1025 0689 GeForce 710M + 1025 068b GeForce 710M + 1025 068d GeForce 710M + 1025 068e GeForce 710M + 1025 0691 GeForce 710M + 1025 0692 GeForce GT 620M + 1025 0694 GeForce GT 620M + 1025 0702 GeForce GT 620M + 1025 0719 GeForce GT 620M + 1025 0725 GeForce GT 620M + 1025 0728 GeForce GT 620M + 1025 072b GeForce GT 620M + 1025 072e GeForce GT 620M + 1025 0732 GeForce GT 620M + 1025 0763 GeForce GT 720M + 1025 0773 GeForce 710M + 1025 0774 GeForce 710M + 1025 0776 GeForce GT 720M + 1025 077a GeForce 710M + 1025 077b GeForce 710M + 1025 077c GeForce 710M + 1025 077d GeForce 710M + 1025 077e GeForce 710M + 1025 077f GeForce 710M + 1025 0781 GeForce GT 720M + 1025 0798 GeForce GT 720M + 1025 0799 GeForce GT 720M + 1025 079b GeForce GT 720M + 1025 079c GeForce GT 720M + 1025 0807 GeForce GT 720M + 1025 0821 GeForce GT 720M + 1025 0823 GeForce GT 720M + 1025 0830 GeForce GT 720M + 1025 0833 GeForce GT 720M + 1025 0837 GeForce GT 720M + 1025 083e GeForce 820M + 1025 0841 GeForce 710M + 1025 0854 GeForce 820M + 1025 0855 GeForce 820M + 1025 0856 GeForce 820M + 1025 0857 GeForce 820M + 1025 0858 GeForce 820M + 1025 0863 GeForce 820M + 1025 0868 GeForce 820M + 1025 0869 GeForce 810M + 1025 0873 GeForce 820M + 1025 0878 GeForce 820M + 1025 087b GeForce 820M + 1025 087c GeForce 810M + 1025 0881 GeForce 820M + 1025 088a GeForce 820M + 1025 089b GeForce 820M + 1025 090f GeForce 820M + 1025 0921 GeForce 820M + 1025 092e GeForce 810M + 1025 092f GeForce 820M + 1025 0932 GeForce 820M + 1025 093a GeForce 820M + 1025 093c GeForce 820M + 1025 093f GeForce 820M + 1025 0941 GeForce 820M + 1025 0945 GeForce 820M + 1025 0954 GeForce 820M + 1025 0965 GeForce 820M + 1028 054d GeForce GT 630M + 1028 054e GeForce GT 630M + 1028 0554 GeForce GT 620M + 1028 0557 GeForce GT 620M + 1028 0562 GeForce GT 625M + 1028 0565 GeForce GT 630M + 1028 0568 GeForce GT 630M + 1028 0590 GeForce GT 630M + 1028 0592 GeForce GT 625M + 1028 0594 GeForce GT 625M + 1028 0595 GeForce GT 625M + 1028 05a2 GeForce GT 625M + 1028 05b1 GeForce GT 625M + 1028 05b3 GeForce GT 625M + 1028 05da GeForce GT 630M + 1028 05de GeForce GT 720M + 1028 05e0 GeForce GT 720M + 1028 05e8 GeForce GT 630M + 1028 05f4 GeForce GT 720M + 1028 060f GeForce GT 720M + 1028 064e GeForce 820M + 1028 0652 GeForce 820M + 1028 0653 GeForce 820M + 1028 0655 GeForce 820M + 1028 065e GeForce 820M + 1028 0662 GeForce 820M + 1028 068d GeForce 820M + 1028 06ad GeForce 820M + 1028 06ae GeForce 820M + 1028 06af GeForce 820M + 1028 06b0 GeForce 820M + 1028 06c0 GeForce 820M + 1028 06c1 GeForce 820M + 103c 18ef GeForce GT 630M + 103c 18f9 GeForce GT 630M + 103c 18fb GeForce GT 630M + 103c 18fd GeForce GT 630M + 103c 18ff GeForce GT 630M + 103c 218a GeForce 820M + 103c 21bb GeForce 820M + 103c 21bc GeForce 820M + 103c 220e GeForce 820M + 103c 2210 GeForce 820M + 103c 2212 GeForce 820M + 103c 2214 GeForce 820M + 103c 2218 GeForce 820M + 103c 225b GeForce 820M + 103c 225d GeForce 820M + 103c 226d GeForce 820M + 103c 226f GeForce 820M + 103c 22d2 GeForce 820M + 103c 22d9 GeForce 820M + 103c 2335 GeForce 820M + 103c 2337 GeForce 820M + 103c 2aef GeForce GT 720A + 103c 2af9 GeForce 710A + 1043 10dd NVS 5200M + 1043 10ed NVS 5200M + 1043 11fd GeForce GT 720M + 1043 124d GeForce GT 720M + 1043 126d GeForce GT 720M + 1043 131d GeForce GT 720M + 1043 13fd GeForce GT 720M + 1043 14c7 GeForce GT 720M + 1043 1507 GeForce GT 620M + 1043 15ad GeForce 820M + 1043 15ed GeForce 820M + 1043 160d GeForce 820M + 1043 163d GeForce 820M + 1043 166d GeForce 820M + 1043 16cd GeForce 820M + 1043 16dd GeForce 820M + 1043 170d GeForce 820M + 1043 176d GeForce 820M + 1043 178d GeForce 820M + 1043 179d GeForce 820M + 1043 17dd GeForce 820M + 1043 2132 GeForce GT 620M + 1043 2136 NVS 5200M + 1043 21ba GeForce GT 720M + 1043 21fa GeForce GT 720M + 1043 220a GeForce GT 720M + 1043 221a GeForce GT 720M + 1043 223a GeForce GT 710M + 1043 224a GeForce GT 710M + 1043 227a GeForce 820M + 1043 228a GeForce 820M + 1043 232a GeForce 820M + 1043 233a GeForce 820M + 1043 235a GeForce 820M + 1043 236a GeForce 820M + 1043 238a GeForce 820M + 1043 8595 GeForce GT 720M + 1043 85ea GeForce GT 720M + 1043 85eb GeForce 820M + 1043 85ec GeForce 820M + 1043 85ee GeForce GT 720M + 1043 85f3 GeForce 820M + 1043 860e GeForce 820M + 1043 861a GeForce 820M + 1043 861b GeForce 820M + 1043 8628 GeForce 820M + 1043 8643 GeForce 820M + 1043 864c GeForce 820M + 1043 8652 GeForce 820M + 1043 8660 GeForce 820M + 1043 8661 GeForce 820M + 105b 0dac GeForce GT 720M + 105b 0dad GeForce GT 720M + 105b 0ef3 GeForce GT 720M + 1072 152d GeForce GT 720M + 10cf 17f5 GeForce GT 720M + 1179 fa01 GeForce 710M + 1179 fa02 GeForce 710M + 1179 fa03 GeForce 710M + 1179 fa05 GeForce 710M + 1179 fa11 GeForce 710M + 1179 fa13 GeForce 710M + 1179 fa18 GeForce 710M + 1179 fa19 GeForce 710M + 1179 fa21 GeForce 710M + 1179 fa23 GeForce 710M + 1179 fa2a GeForce 710M + 1179 fa32 GeForce 710M + 1179 fa33 GeForce 710M + 1179 fa36 GeForce 710M + 1179 fa38 GeForce 710M + 1179 fa42 GeForce 710M + 1179 fa43 GeForce 710M + 1179 fa45 GeForce 710M + 1179 fa47 GeForce 710M + 1179 fa49 GeForce 710M + 1179 fa58 GeForce 710M + 1179 fa59 GeForce 710M + 1179 fa88 GeForce 710M + 1179 fa89 GeForce 710M + 144d b092 GeForce GT 620M + 144d c0d5 GeForce GT 630M + 144d c0d7 GeForce GT 620M + 144d c0e2 NVS 5200M + 144d c0e3 NVS 5200M + 144d c0e4 NVS 5200M + 144d c10d GeForce 820M + 144d c652 GeForce GT 620M on NP300E5C series laptop + 144d c709 GeForce 710M + 144d c711 GeForce 710M + 144d c736 GeForce 710M + 144d c737 GeForce 710M + 144d c745 GeForce 820M + 144d c750 GeForce 820M + 1462 10b8 GeForce GT 710M + 1462 10e9 GeForce GT 720M + 1462 1116 GeForce 820M + 1462 aa33 GeForce 720M + 1462 aaa2 GeForce GT 720M + 1462 aaa3 GeForce 820M + 1462 acb2 GeForce GT 720M + 1462 acc1 GeForce GT 720M + 1462 ae61 GeForce 720M + 1462 ae65 GeForce GT 720M + 1462 ae6a GeForce 820M + 1462 ae71 GeForce GT 720M + 14c0 0083 GeForce 820M + 152d 0926 GeForce 620M + 152d 0982 GeForce GT 630M + 152d 0983 GeForce GT 630M + 152d 1005 GeForce GT 820M + 152d 1012 GeForce 710M + 152d 1019 GeForce 820M + 152d 1030 GeForce GT 630M + 152d 1055 GeForce 710M + 152d 1067 GeForce GT 720M + 152d 1072 GeForce GT 720M + 152d 1086 GeForce 820M + 152d 1092 GeForce 820M + 17aa 2200 NVS 5200M + 17aa 2213 GeForce GT 720M + 17aa 2220 GeForce GT 720M + 17aa 309c GeForce GT 720A + 17aa 30b4 GeForce 820A + 17aa 30b7 GeForce 720A + 17aa 30e4 GeForce 820A + 17aa 361b GeForce 820A + 17aa 361c GeForce 820A + 17aa 361d GeForce 820A + 17aa 3656 GeForce GT 620M + 17aa 365a GeForce 705M + 17aa 365e GeForce 800M + 17aa 3661 GeForce 820A + 17aa 366c GeForce 800M + 17aa 3685 GeForce 800M + 17aa 3686 GeForce 800M + 17aa 3687 GeForce 705A + 17aa 3696 GeForce 820A + 17aa 369b GeForce 820A + 17aa 369c GeForce 820A + 17aa 369d GeForce 820A + 17aa 369e GeForce 820A + 17aa 36a9 GeForce 820A + 17aa 36af GeForce 820A + 17aa 36b0 GeForce 820A + 17aa 36b6 GeForce 820A + 17aa 3800 GeForce GT 720M + 17aa 3801 GeForce GT 720M + 17aa 3802 GeForce GT 720M + 17aa 3803 GeForce GT 720M + 17aa 3804 GeForce GT 720M + 17aa 3806 GeForce GT 720M + 17aa 3808 GeForce GT 720M + 17aa 380d GeForce 820M + 17aa 380e GeForce 820M + 17aa 380f GeForce 820M + 17aa 3811 GeForce 820M + 17aa 3812 GeForce 820M + 17aa 3813 GeForce 820M + 17aa 3816 GeForce 820M + 17aa 3818 GeForce 820M + 17aa 381a GeForce 820M + 17aa 381c GeForce 820M + 17aa 3901 GeForce 610M / GT 620M + 17aa 3902 GeForce 710M + 17aa 3903 GeForce 610M/710M + 17aa 3904 GeForce GT 620M/625M + 17aa 3905 GeForce GT 720M + 17aa 3907 GeForce 820M + 17aa 3910 GeForce 720M + 17aa 3912 GeForce 720M + 17aa 3913 GeForce 820M + 17aa 3915 GeForce 820M + 17aa 3977 GeForce GT 720M + 17aa 3983 GeForce 610M + 17aa 5001 GeForce 610M + 17aa 5003 GeForce GT 720M + 17aa 5005 GeForce 705M + 17aa 500d GeForce GT 620M + 17aa 5014 GeForce 710M + 17aa 5017 GeForce 710M + 17aa 5019 GeForce 710M + 17aa 501a GeForce 710M + 17aa 501f GeForce GT 720M + 17aa 5025 GeForce 710M + 17aa 5027 GeForce 710M + 17aa 502a GeForce 710M + 17aa 502b GeForce GT 720M + 17aa 502d GeForce 710M + 17aa 502e GeForce GT 720M + 17aa 502f GeForce GT 720M + 17aa 5030 GeForce 705M + 17aa 5031 GeForce 705M + 17aa 5032 GeForce 820M + 17aa 5033 GeForce 820M + 17aa 503e GeForce 710M + 17aa 503f GeForce 820M + 17aa 5040 GeForce 820M + 1854 0177 GeForce 710M + 1854 0180 GeForce 710M + 1854 0190 GeForce GT 720M + 1854 0192 GeForce GT 720M + 1854 0224 GeForce 820M + 1b0a 01c0 GeForce 820M + 1b0a 20dd GeForce GT 620M + 1b0a 20df GeForce GT 620M + 1b0a 210e GeForce 820M + 1b0a 2202 GeForce GT 720M + 1b0a 90d7 GeForce 820M + 1b0a 90dd GeForce 820M + 1b50 5530 GeForce 820M + 1b6c 5531 GeForce GT 720M + 1bab 0106 GeForce 820M + 1d05 1013 GeForce 810M + 1180 GK104 [GeForce GTX 680] + 1043 83f1 GTX680-DC2-2GD5 + 3842 3682 GeForce GTX 680 Mac Edition + 1182 GK104 [GeForce GTX 760 Ti] + 1183 GK104 [GeForce GTX 660 Ti] + 1184 GK104 [GeForce GTX 770] + 1185 GK104 [GeForce GTX 660 OEM] + 10de 106f GK104 [GeForce GTX 760 OEM] + 1187 GK104 [GeForce GTX 760] + 1188 GK104 [GeForce GTX 690] + 1189 GK104 [GeForce GTX 670] + 10de 1074 GK104 [GeForce GTX 760 Ti OEM] + 118a GK104GL [GRID K520] + 118b GK104GL [GRID K2 GeForce USM] + 118c GK104 [GRID K2 NVS USM] +# GRID K2 USM + 118d GK104GL [GRID K200 vGPU] + 10de 101d GRID K200 + 118e GK104 [GeForce GTX 760 OEM] + 118f GK104GL [Tesla K10] + 1191 GK104 [GeForce GTX 760 Rev. 2] + 1193 GK104 [GeForce GTX 760 Ti OEM] + 1194 GK104GL [Tesla K8] + 1195 GK104 [GeForce GTX 660 Rev. 2] + 1198 GK104M [GeForce GTX 880M] + 1199 GK104M [GeForce GTX 870M] + 119a GK104M [GeForce GTX 860M] + 119d GK104M [GeForce GTX 775M Mac Edition] + 119e GK104M [GeForce GTX 780M Mac Edition] + 119f GK104M [GeForce GTX 780M] + 11a0 GK104M [GeForce GTX 680M] + 11a1 GK104M [GeForce GTX 670MX] + 11a2 GK104M [GeForce GTX 675MX Mac Edition] + 11a3 GK104M [GeForce GTX 680MX] + 106b 010d iMac 13,2 + 11a7 GK104M [GeForce GTX 675MX] + 11af GK104GLM [GRID IceCube] + 11b0 GK104GL [GRID K240Q / K260Q vGPU] + 10de 101a GRID K240Q + 10de 101b GRID K260Q + 11b1 GK104GL [GRID K2 Tesla USM] + 11b4 GK104GL [Quadro K4200] + 11b6 GK104GLM [Quadro K3100M] + 11b7 GK104GLM [Quadro K4100M] + 11b8 GK104GLM [Quadro K5100M] + 11b9 GK104GLM + 11ba GK104GL [Quadro K5000] + 11bb GK104GL [Quadro 4100] + 11bc GK104GLM [Quadro K5000M] + 11bd GK104GLM [Quadro K4000M] + 11be GK104GLM [Quadro K3000M] + 11bf GK104GL [GRID K2] + 11c0 GK106 [GeForce GTX 660] + 11c2 GK106 [GeForce GTX 650 Ti Boost] + 1043 845b GeForce GTX 650 Ti Boost DirectCU II OC + 1462 2874 GeForce GTX 650 Ti Boost TwinFrozr II OC + 1569 11c2 GeForce GTX 650 Ti Boost OC + 19da 1281 GeForce GTX 650 Ti Boost OC + 3842 3657 GeForce GTX 650 Ti Boost + 3842 3658 GeForce GTX 650 Ti Boost Superclocked + 11c3 GK106 [GeForce GTX 650 Ti OEM] + 10de 1030 GeForce GTX 650 Ti OEM + 11c4 GK106 [GeForce GTX 645 OEM] + 11c5 GK106 [GeForce GT 740] + 11c6 GK106 [GeForce GTX 650 Ti] + 11c7 GK106 [GeForce GTX 750 Ti] + 11c8 GK106 [GeForce GTX 650 OEM] + 11cb GK106 [GeForce GT 740] + 11e0 GK106M [GeForce GTX 770M] + 11e1 GK106M [GeForce GTX 765M] + 11e2 GK106M [GeForce GTX 765M] + 11e3 GK106M [GeForce GTX 760M] + 17aa 3683 GeForce GTX 760A + 11e7 GK106M + 11fa GK106GL [Quadro K4000] + 11fc GK106GLM [Quadro K2100M] + 1200 GF114 [GeForce GTX 560 Ti] + 1201 GF114 [GeForce GTX 560] + 1202 GF114 [GeForce GTX 560 Ti OEM] + 1203 GF114 [GeForce GTX 460 SE v2] + 1205 GF114 [GeForce GTX 460 v2] + 1206 GF114 [GeForce GTX 555] + 1207 GF114 [GeForce GT 645 OEM] + 1208 GF114 [GeForce GTX 560 SE] + 1210 GF114M [GeForce GTX 570M] + 1211 GF114M [GeForce GTX 580M] + 1212 GF114M [GeForce GTX 675M] + 1213 GF114M [GeForce GTX 670M] + 1241 GF116 [GeForce GT 545 OEM] + 1243 GF116 [GeForce GT 545] + 1244 GF116 [GeForce GTX 550 Ti] + 1245 GF116 [GeForce GTS 450 Rev. 2] + 1246 GF116M [GeForce GT 550M] + 1247 GF116M [GeForce GT 555M/635M] + 1043 1752 GeForce GT 555M + 1043 2050 GeForce GT 555M + 1043 2051 GeForce GT 555M + 1043 212a GeForce GT 635M + 1043 212b GeForce GT 635M + 1043 212c GeForce GT 635M + 152d 0930 GeForce GT 635M + 1248 GF116M [GeForce GT 555M/635M] + 152d 0930 GeForce GT 635M + 17c0 10e7 GeForce GT 555M + 17c0 10e8 GeForce GT 555M + 17c0 10ea GeForce GT 555M + 1854 0890 GeForce GT 555M + 1854 0891 GeForce GT 555M + 1854 1795 GeForce GT 555M + 1854 1796 GeForce GT 555M + 1854 3005 GeForce GT 555M + 1249 GF116 [GeForce GTS 450 Rev. 3] + 124b GF116 [GeForce GT 640 OEM] + 124d GF116M [GeForce GT 555M/635M] + 1028 0491 GeForce GT 555M + 1028 0570 GeForce GT 555M + 1028 0571 GeForce GT 555M + 1462 108d GeForce GT 555M + 1462 10cc GeForce GT 635M + 1251 GF116M [GeForce GT 560M] + 1280 GK208 [GeForce GT 635] + 1281 GK208 [GeForce GT 710] + 1282 GK208 [GeForce GT 640 Rev. 2] + 1284 GK208 [GeForce GT 630 Rev. 2] + 1286 GK208 [GeForce GT 720] + 1287 GK208B [GeForce GT 730] + 1288 GK208B [GeForce GT 720] + 1289 GK208 [GeForce GT 710] + 128b GK208B [GeForce GT 710] + 1043 85f7 GT710-SL-1GD5 + 1290 GK208M [GeForce GT 730M] + 103c 2afa GeForce GT 730A + 103c 2b04 GeForce GT 730A + 1043 13ad GeForce GT 730M + 1043 13cd GeForce GT 730M + 1291 GK208M [GeForce GT 735M] + 1292 GK208M [GeForce GT 740M] + 17aa 3675 GeForce GT 740A + 17aa 367c GeForce GT 740A + 17aa 3684 GeForce GT 740A + 1293 GK208M [GeForce GT 730M] + 1294 GK208M [GeForce GT 740M] + 1295 GK208M [GeForce 710M] + 103c 2b0d GeForce 710A + 103c 2b0f GeForce 710A + 103c 2b11 GeForce 710A + 103c 2b20 GeForce 810A + 103c 2b21 GeForce 810A + 103c 2b22 GeForce 810A + 17aa 367a GeForce 805A + 17aa 367c GeForce 710A + 1296 GK208M [GeForce 825M] + 1298 GK208M [GeForce GT 720M] + 1299 GK208BM [GeForce 920M] + 17aa 30bb GeForce 920A + 17aa 30df GeForce 920A + 17aa 36a7 GeForce 920A + 17aa 36af GeForce 920M + 129a GK208BM [GeForce 910M] + 12a0 GK208 + 12b9 GK208GLM [Quadro K610M] + 12ba GK208GLM [Quadro K510M] + 1340 GM108M [GeForce 830M] + 103c 2b2b GeForce 830A + 1341 GM108M [GeForce 840M] + 17aa 3697 GeForce 840A + 17aa 3699 GeForce 840A + 17aa 369c GeForce 840A + 1344 GM108M [GeForce 845M] + 1346 GM108M [GeForce 930M] + 1347 GM108M [GeForce 940M] + 1348 GM108M [GeForce 945M / 945A] + 1349 GM108M [GeForce 930M] + 134b GM108M [GeForce 940MX] + 134d GM108M [GeForce 940MX] + 17aa 2248 ThinkPad T570 + 134e GM108M [GeForce 930MX] + 134f GM108M [GeForce 920MX] + 137a GM108GLM [Quadro K620M / Quadro M500M] + 17aa 505a Quadro M500M + 137b GM108GLM [Quadro M520 Mobile] + 137d GM108M [GeForce 940A] + 1380 GM107 [GeForce GTX 750 Ti] + 1381 GM107 [GeForce GTX 750] + 1382 GM107 [GeForce GTX 745] + 1389 GM107GL [GRID M30] + 1390 GM107M [GeForce 845M] + 1391 GM107M [GeForce GTX 850M] + 17aa 3697 GeForce GTX 850A + 17aa a125 GeForce GTX 850A + 1392 GM107M [GeForce GTX 860M] + 1393 GM107M [GeForce 840M] + 1398 GM107M [GeForce 845M] + 1399 GM107M [GeForce 945M] + 139a GM107M [GeForce GTX 950M] + 17aa 362c GeForce GTX 950A + 17aa 362f GeForce GTX 950A + 17aa 363f GeForce GTX 950A + 17aa 3640 GeForce GTX 950A + 17aa 3647 GeForce GTX 950A + 17aa 36b9 GeForce GTX 950A + 139b GM107M [GeForce GTX 960M] + 1028 06e4 XPS 15 9550 + 103c 2b4c GeForce GTX 960A + 139c GM107M [GeForce 940M] + 139d GM107M [GeForce GTX 750 Ti] + 13b0 GM107GLM [Quadro M2000M] + 13b1 GM107GLM [Quadro M1000M] + 13b2 GM107GLM [Quadro M600M] + 13b3 GM107GLM [Quadro K2200M] + 13b4 GM107GLM [Quadro M620 Mobile] + 13b6 GM107GLM [Quadro M1200 Mobile] + 13b9 GM107GL [NVS 810] + 13ba GM107GL [Quadro K2200] + 13bb GM107GL [Quadro K620] + 13bc GM107GL [Quadro K1200] + 13bd GM107GL [Tesla M10] + 10de 110a GRID M40 + 10de 1160 Tesla M10 + 10de 11d2 GRID M10-8Q + 13c0 GM204 [GeForce GTX 980] + 1043 8504 GTX980-4GD5 + 13c1 GM204 + 13c2 GM204 [GeForce GTX 970] + 13c3 GM204 + 13d7 GM204M [GeForce GTX 980M] + 13d8 GM204M [GeForce GTX 970M] + 13d9 GM204M [GeForce GTX 965M] + 13da GM204M [GeForce GTX 980 Mobile] + 13e7 GM204GL [GeForce GTX 980 Engineering Sample] + 13f0 GM204GL [Quadro M5000] + 13f1 GM204GL [Quadro M4000] + 13f2 GM204GL [Tesla M60] + 10de 114d GRID M60-1Q + 10de 114e GRID M60-2Q + 10de 1150 GRID M60-8Q + 10de 11b0 GRID M60-4A + 13f3 GM204GL [Tesla M6] + 10de 1184 GRID M6-8Q + 13f8 GM204GLM [Quadro M5000M / M5000 SE] + 13f9 GM204GLM [Quadro M4000M] + 13fa GM204GLM [Quadro M3000M] + 10de 11c9 Quadro M3000 SE + 13fb GM204GLM [Quadro M5500] + 1401 GM206 [GeForce GTX 960] + 1402 GM206 [GeForce GTX 950] + 1406 GM206 [GeForce GTX 960 OEM] + 1407 GM206 [GeForce GTX 750 v2] + 1427 GM206M [GeForce GTX 965M] + 1430 GM206GL [Quadro M2000] + 1431 GM206GL [Tesla M4] + 1436 GM206GLM [Quadro M2200 Mobile] + 15f0 GP100GL [Quadro GP100] + 15f1 GP100GL + 15f7 GP100GL [Tesla P100 PCIe 12GB] + 15f8 GP100GL [Tesla P100 PCIe 16GB] + 15f9 GP100GL [Tesla P100 SXM2 16GB] + 1617 GM204M [GeForce GTX 980M] + 1618 GM204M [GeForce GTX 970M] + 1619 GM204M [GeForce GTX 965M] + 161a GM204M [GeForce GTX 980 Mobile] + 1667 GM204M [GeForce GTX 965M] + 1725 GP100 + 172e GP100 + 172f GP100 + 174d GM108M [GeForce MX130] + 174e GM108M [GeForce MX110] + 1789 GM107GL [GRID M3-3020] + 179c GM107 [GeForce 940MX] + 17c2 GM200 [GeForce GTX TITAN X] + 17c8 GM200 [GeForce GTX 980 Ti] + 17f0 GM200GL [Quadro M6000] + 10de 1141 VCA 6000 + 17f1 GM200GL [Quadro M6000 24GB] + 17fd GM200GL [Tesla M40] + 1ad6 TU102 USB 3.1 Host Controller + 1ad7 TU102 USB Type-C UCSI Controller + 1ad8 TU104 USB 3.1 Host Controller + 1ad9 TU104 USB Type-C UCSI Controller + 1ada TU106 USB 3.1 Host Controller + 1043 8673 TURBO-RTX2070-8G + 1adb TU106 USB Type-C UCSI Controller + 1043 8673 TURBO-RTX2070-8G + 1aeb TU116 High Definition Audio Controller + 1aed TU116 [GeForce GTX 1650 SUPER] + 1b00 GP102 [TITAN X] + 1b01 GP102 [GeForce GTX 1080 Ti 10GB] + 1b02 GP102 [TITAN Xp] + 1b04 GP102 + 1b06 GP102 [GeForce GTX 1080 Ti] + 1b07 GP102 [P102-100] + 1b30 GP102GL [Quadro P6000] + 1b38 GP102GL [Tesla P40] + 1b70 GP102GL + 1b78 GP102GL + 1b80 GP104 [GeForce GTX 1080] + 1b81 GP104 [GeForce GTX 1070] + 1b82 GP104 [GeForce GTX 1070 Ti] + 1b83 GP104 [GeForce GTX 1060 6GB] + 1b84 GP104 [GeForce GTX 1060 3GB] + 1b87 GP104 [P104-100] + 1ba0 GP104M [GeForce GTX 1080 Mobile] + 1ba1 GP104M [GeForce GTX 1070 Mobile] + 1458 1651 GeForce GTX 1070 Max-Q + 1462 11e8 GeForce GTX 1070 Max-Q + 1462 11e9 GeForce GTX 1070 Max-Q + 1558 9501 GeForce GTX 1070 Max-Q + 1ba2 GP104M [GeForce GTX 1070 Mobile] + 1ba9 GP104M + 1baa GP104M + 1bad GP104 [GeForce GTX 1070 Engineering Sample] + 1bb0 GP104GL [Quadro P5000] + 1bb1 GP104GL [Quadro P4000] + 1bb3 GP104GL [Tesla P4] + 1bb4 GP104GL [Tesla P6] + 1bb5 GP104GLM [Quadro P5200 Mobile] + 103c 842f P5200 [Zbook 17 G5 mobile workstation] + 1bb6 GP104GLM [Quadro P5000 Mobile] + 1bb7 GP104GLM [Quadro P4000 Mobile] + 1462 11e9 Quadro P4000 Max-Q + 1bb8 GP104GLM [Quadro P3000 Mobile] + 1bb9 GP104GLM [Quadro P4200 Mobile] + 103c 842f P4200 [Zbook 17 G5 mobile workstation] + 1bbb GP104GLM [Quadro P3200 Mobile] + 103c 842f P3200 [Zbook 17 G5 moble workstation] + 1bc7 GP104 [P104-101] + 1be0 GP104BM [GeForce GTX 1080 Mobile] + 1028 07c0 GeForce GTX 1080 Max-Q + 1458 355b GeForce GTX 1080 Max-Q + 1be1 GP104BM [GeForce GTX 1070 Mobile] + 1c00 GP106 + 1c01 GP106 + 1c02 GP106 [GeForce GTX 1060 3GB] + 1c03 GP106 [GeForce GTX 1060 6GB] + 1c04 GP106 [GeForce GTX 1060 5GB] + 1c06 GP106 [GeForce GTX 1060 6GB Rev. 2] + 1c07 GP106 [P106-100] + 1c09 GP106 [P106-090] + 1c20 GP106M [GeForce GTX 1060 Mobile] + 17aa 39b9 GeForce GTX 1060 Max-Q 3GB + 1c21 GP106M [GeForce GTX 1050 Ti Mobile] + 1c22 GP106M [GeForce GTX 1050 Mobile] + 1c23 GP106M [GeForce GTX 1060 Mobile Rev. 2] + 1414 0020 GTX 1060 Mobile + 1c2d GP106M + 1c30 GP106GL [Quadro P2000] + 1c31 GP106GL [Quadro P2200] + 1c35 GP106 + 1c60 GP106BM [GeForce GTX 1060 Mobile 6GB] + 103c 8390 GeForce GTX 1060 Max-Q 6GB + 1c61 GP106BM [GeForce GTX 1050 Ti Mobile] + 1c62 GP106BM [GeForce GTX 1050 Mobile] + 1c70 GP106GL + 1c81 GP107 [GeForce GTX 1050] + 1c82 GP107 [GeForce GTX 1050 Ti] + 1043 8613 PH-GTX1050TI-4G + 1458 3763 GV-N105TOC-4GD + 1c83 GP107 [GeForce GTX 1050 3GB] + 1c8c GP107M [GeForce GTX 1050 Ti Mobile] + 1c8d GP107M [GeForce GTX 1050 Mobile] + 1c8e GP107M + 1c8f GP107M [GeForce GTX 1050 Ti Max-Q] + 1c90 GP107M [GeForce MX150] + 1c91 GP107M [GeForce GTX 1050 3 GB Max-Q] + 1c92 GP107M [GeForce GTX 1050 Mobile] + 1c94 GP107M [GeForce MX350] + 1ca7 GP107GL + 1ca8 GP107GL + 1caa GP107GL + 1cb1 GP107GL [Quadro P1000] + 1cb2 GP107GL [Quadro P600] + 1cb3 GP107GL [Quadro P400] + 1cb6 GP107GL [Quadro P620] + 1cba GP107GLM [Quadro P2000 Mobile] + 103c 842c P2000 [Zbook 15 G5 mobile workstation] + 103c 842f P2000 [Zbook 17 G5 mobile workstation] + 1cbb GP107GLM [Quadro P1000 Mobile] + 103c 8429 P1000 [Zbook Studio G5 mobile workstation] + 103c 842c P1000 [Zbook 15 G5 mobile workstation] + 103c 842f P1000 [Zbook 17 G5 mobile workstation] + 103c 8451 P1000 [Zbook Studio x360 G5 mobile workstation] + 1cbc GP107GLM [Quadro P600 Mobile] + 1cbd GP107GLM [Quadro P620] + 1ccc GP107BM [GeForce GTX 1050 Ti Mobile] + 1ccd GP107BM [GeForce GTX 1050 Mobile] + 1d01 GP108 [GeForce GT 1030] + 1d10 GP108M [GeForce MX150] + 17aa 225e ThinkPad T480 + 1d11 GP108M [GeForce MX230] + 1d12 GP108M [GeForce MX150] + 1d72 1701 Mi Notebook Pro [GeForce MX150] + 1d13 GP108M [GeForce MX250] + 1d16 GP108M [GeForce MX330] + 1d33 GP108GLM [Quadro P500 Mobile] + 1d34 GP108GLM [Quadro P520] + 1d52 GP108BM [GeForce MX250] + 1d81 GV100 [TITAN V] + 1db1 GV100GL [Tesla V100 SXM2 16GB] + 1db2 GV100GL [Tesla V100 DGXS 16GB] + 1db3 GV100GL [Tesla V100 FHHL 16GB] + 1db4 GV100GL [Tesla V100 PCIe 16GB] + 1db5 GV100GL [Tesla V100 SXM2 32GB] + 1db6 GV100GL [Tesla V100 PCIe 32GB] + 1db7 GV100GL [Tesla V100 DGXS 32GB] + 1db8 GV100GL [Tesla V100 SXM3 32GB] + 10de 131d Tesla V100-SXM3-32GB-H + 1dba GV100GL [Quadro GV100] + 10de 12eb TITAN V CEO Edition + 1df5 GV100GL [Tesla V100 SXM2 16GB] + 1df6 GV100GL [Tesla V100S PCIe 32GB] + 1e02 TU102 [TITAN RTX] + 1e04 TU102 [GeForce RTX 2080 Ti] + 1e07 TU102 [GeForce RTX 2080 Ti Rev. A] + 1462 3715 RTX 2080 Ti GAMING X TRIO + 1e2d TU102B + 1e2e TU102B + 1e30 TU102GL [Quadro RTX 6000/8000] + 10de 129e Quadro RTX 8000 + 10de 12ba Quadro RTX 6000 + 1e38 TU102GL + 1e3c TU102GL + 1e3d TU102GL + 1e3e TU102GL + 1e78 TU102GL [Quadro RTX 6000/8000] + 10de 13d8 Quadro RTX 8000 + 10de 13d9 Quadro RTX 6000 + 1e81 TU104 [GeForce RTX 2080 SUPER] + 1e82 TU104 [GeForce RTX 2080] + 1e84 TU104 [GeForce RTX 2070 SUPER] + 1e87 TU104 [GeForce RTX 2080 Rev. A] + 1e89 TU104 [GeForce RTX 2060] + 1e90 TU104M [GeForce RTX 2080 Mobile] + 1eab TU104M + 1eae TU104M + 1eb0 TU104GL [Quadro RTX 5000] + 1eb1 TU104GL [Quadro RTX 4000] + 1eb5 TU104GLM [Quadro RTX 5000 Mobile / Max-Q] + 1eb6 TU104GLM [Quadro RTX 4000 Mobile / Max-Q] + 1eb8 TU104GL [Tesla T4] + 1eb9 TU104GL + 1ebe TU104GL + 1ec2 TU104 [GeForce RTX 2070 SUPER] + 1ec7 TU104 [GeForce RTX 2070 SUPER] + 1ed0 TU104BM [GeForce RTX 2080 Mobile] + 1f02 TU106 [GeForce RTX 2070] + 1043 8673 TURBO RTX 2070 + 1f04 TU106 + 1f06 TU106 [GeForce RTX 2060 SUPER] + 1f07 TU106 [GeForce RTX 2070 Rev. A] + 1f08 TU106 [GeForce RTX 2060 Rev. A] + 1f10 TU106M [GeForce RTX 2070 Mobile] + 1f11 TU106M [GeForce RTX 2060 Mobile] + 1f2e TU106M + 1f36 TU106GLM [Quadro RTX 3000 Mobile / Max-Q] + 1f42 TU106 [GeForce RTX 2060 SUPER] + 1f47 TU106 [GeForce RTX 2060 SUPER] + 1f50 TU106BM [GeForce RTX 2070 Mobile] + 1f51 TU106BM [GeForce RTX 2060 Mobile] + 1f81 TU117 + 1f82 TU117 [GeForce GTX 1650] + 1f91 TU117M [GeForce GTX 1650 Mobile / Max-Q] + 1f92 TU117M [GeForce GTX 1650 Mobile] + 1f96 TU117M [GeForce GTX 1650 Mobile / Max-Q] + 1fae TU117GL + 1fb8 TU117GLM [Quadro T2000 Mobile / Max-Q] + 1fb9 TU117GLM [Quadro T1000 Mobile] + 1fbf TU117GL + 2182 TU116 [GeForce GTX 1660 Ti] + 2183 TU116 + 2184 TU116 [GeForce GTX 1660] + 2187 TU116 [GeForce GTX 1650 SUPER] + 2191 TU116M [GeForce GTX 1660 Ti Mobile] + 21ae TU116GL + 21bf TU116GL + 21c4 TU116 [GeForce GTX 1660 SUPER] + 21d1 TU116BM [GeForce GTX 1660 Ti Mobile] +10df Emulex Corporation + 0720 OneConnect NIC (Skyhawk) + 103c 1934 FlexFabric 20Gb 2-port 650M Adapter + 103c 1935 FlexFabric 20Gb 2-port 650FLB Adapter + 103c 21d4 StoreFabric CN1200E 10Gb Converged Network Adapter + 103c 220a FlexFabric 10Gb 2-port 556FLR-SFP+ Adapter + 103c 803f Ethernet 10Gb 2-port 557SFP+ Adapter + 103c 8144 FlexFabric 10GB 2-port 556FLR-T Adapter + 17aa 1056 ThinkServer OCm14102-UX-L AnyFabric + 17aa 1057 ThinkServer OCm14104-UX-L AnyFabric + 17aa 1059 ThinkServer OCm14104-UT-L AnyFabric + 17aa 4014 ThinkServer OCm14102-NX-L AnyFabric + 0722 OneConnect iSCSI Initiator (Skyhawk) + 0723 OneConnect iSCSI Initiator + Target (Skyhawk) + 0724 OneConnect FCoE Initiator (Skyhawk) + 0728 OneConnect NIC (Skyhawk-VF) + 072a OneConnect iSCSI Initiator (Skyhawk-VF) + 072b OneConnect iSCSI Initiator + Target (Skyhawk-VF) + 072c OneConnect FCoE Initiator (Skyhawk-VF) + 1ae5 LP6000 Fibre Channel Host Adapter + e100 Proteus-X: LightPulse IOV Fibre Channel Host Adapter + e131 LightPulse 8Gb/s PCIe Shared I/O Fibre Channel Adapter + e180 Proteus-X: LightPulse IOV Fibre Channel Host Adapter + e200 LPe15000/LPe16000 Series 8Gb/16Gb Fibre Channel Adapter + 1014 03f1 PCIe2 2-Port 16Gb Fibre Channel Adapter for POWER (FC EL5B; CCIN 577F) + 1014 04e3 PCIe3 4-Port 10GbE SR Adapter for POWER (FC EN15/EN16; CCIN 2CE3) + 1014 04e4 PCIe3 4-Port 10GbE SFP+ Adapter for POWER (FC EN18; CCIN 2CE4) + 10df e280 LPe16002B-M6 2-Port 16Gb Fibre Channel Adapter + 10df e281 LPe16000B-M6 1-Port 16Gb Fibre Channel Adapter + 10df e282 Flex System FC5054 4-port 16Gb FC Adapter + e208 LightPulse 16Gb Fibre Channel Host Adapter (Lancer-VF) + e220 OneConnect NIC (Lancer) + 17aa 1054 ThinkServer LPm16002B-M6-L AnyFabric + 17aa 1055 ThinkServer LPm16004B-M8-L AnyFabric + e240 OneConnect iSCSI Initiator (Lancer) + e260 OneConnect FCoE Initiator (Lancer) + e268 OneConnect 10Gb FCoE Converged Network Adapter (Lancer-VF) + e300 LPe31000/LPe32000 Series 16Gb/32Gb Fibre Channel Adapter + 1014 0614 PCIe3 4-Port 16Gb Fibre Channel Adapter for POWER (FC EN1C/EN1D; CCIN 578E) + 1014 0615 PCIe3 2-Port 32Gb Fibre Channel Adapter for POWER (FC EN1A/EN1B; CCIN 578F) + 10df e300 LPe32002-M2 2-Port 32Gb Fibre Channel Adapter + 10df e301 LPe32000-M2 1-Port 32Gb Fibre Channel Adapter + 10df e310 LPe31002-M6 2-Port 16Gb Fibre Channel Adapter + 10df e311 LPe31000-M6 1-Port 16Gb Fibre Channel Adapter + 10df e312 LPe31004-M6 4-Port 16Gb Fibre Channel Adapter + 10df e320 LPe32002-M2-D 2-Port 32Gb Fibre Channel Adapter + 10df e321 LPe32000-M2-D 1-Port 32Gb Fibre Channel Adapter + 10df e322 LPe31002-M6-D 2-Port 16Gb Fibre Channel Adapter + 10df e323 LPe31000-M6-D 1-Port 16Gb Fibre Channel Adapter + 10df e324 LPm32002-D 2-Port 32Gb Fibre Channel Mezz Card + 10df e325 LPm31002-D 2-Port 16Gb Fibre Channel Mezz Card + 10df e330 LPe32002-M2-L 2-Port 32Gb PCIe Fibre Channel Adapter + 10df e331 LPe32000-M2-L 1-Port 32Gb PCIe Fibre Channel Adapter + 10df e332 LPe31002-M6-L 2-Port 16Gb PCIe Fibre Channel Adapter + 10df e333 LPe31000-M6-L 1-Port 16Gb PCIe Fibre Channel Adapter + 1590 0201 StoreFabric SN1600E 1-Port 32Gb Fibre Channel Adapter + 1590 0202 StoreFabric SN1600E 2-Port 32Gb Fibre Channel Adapter + 1590 0213 StoreFabric SN1200E 1-Port 16Gb Fibre Channel Adapter + 1590 0214 StoreFabric SN1200E 2-Port 16Gb Fibre Channel Adapter + 1590 022e Synergy 5330C 2-Port 32Gb Fibre Channel Mezz Card + f011 Saturn: LightPulse Fibre Channel Host Adapter + f015 Saturn: LightPulse Fibre Channel Host Adapter + f085 LP850 Fibre Channel Host Adapter + f095 LP952 Fibre Channel Host Adapter + f098 LP982 Fibre Channel Host Adapter + f0a1 Thor LightPulse Fibre Channel Host Adapter + f0a5 Thor LightPulse Fibre Channel Host Adapter + f0b5 Viper LightPulse Fibre Channel Host Adapter + f0d1 Helios LightPulse Fibre Channel Host Adapter + f0d5 Helios LightPulse Fibre Channel Host Adapter + f0e1 Zephyr LightPulse Fibre Channel Host Adapter + f0e5 Zephyr LightPulse Fibre Channel Host Adapter + f0f5 Neptune LightPulse Fibre Channel Host Adapter + f100 LPe12000 Series 8Gb Fibre Channel Adapter + 1014 038a 8Gb PCI Express Dual Port FC Adapter for POWER + 103c 3282 8Gb Dual-port PCI-e FC HBA + 10df f140 LPe12000-M8-L 1-Port 8Gb PCIe Fibre Channel Adapter + 10df f141 LPe12002-M8-L 2-Port 8Gb PCIe Fibre Channel Adapter + f111 Saturn-X LightPulse Fibre Channel Host Adapter + f112 Saturn-X LightPulse Fibre Channel Host Adapter + f180 LPSe12002 EmulexSecure Fibre Channel Adapter + f400 LPe35000/LPe36000 Series 32Gb/64Gb Fibre Channel Adapter + 10df f401 LPe35000-M2 1-Port 32Gb Fibre Channel Adapter + 10df f402 LPe35002-M2 2-Port 32Gb Fibre Channel Adapter + 10df f403 LPe36000-M64 1-Port 64Gb Fibre Channel Adapter + 10df f404 LPe36002-M64 2-Port 64Gb Fibre Channel Adapter + 10df f405 LPe35004-M2 4-Port 32Gb Fibre Channel Adapter + 10df f406 LPe35004-X6 4-Port Fibre Channel Adapter + 10df f410 LPe35002-M2-D 2-Port 32Gb Fibre Channel Adapter + 10df f411 LPe35000-M2-D 1-Port 32Gb Fibre Channel Adapter + 10df f418 LPe35000-M2-L 1-Port 32Gb PCIe Fibre Channel Adapter + 10df f419 LPe35002-M2-L 2-Port 32Gb PCIe Fibre Channel Adapter + 1590 02d5 StoreFabric SN1610E 1-Port 32Gb Fibre Channel Adapter + 1590 02d6 StoreFabric SN1610E 2-Port 32Gb Fibre Channel Adapter + f700 LP7000 Fibre Channel Host Adapter + f701 LP7000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) + f800 LP8000 Fibre Channel Host Adapter + f801 LP8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) + f900 LP9000 Fibre Channel Host Adapter + f901 LP9000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2) + f980 LP9802 Fibre Channel Host Adapter + f981 LP9802 Fibre Channel Host Adapter Alternate ID + f982 LP9802 Fibre Channel Host Adapter Alternate ID + fa00 Thor-X LightPulse Fibre Channel Host Adapter + fb00 Viper LightPulse Fibre Channel Host Adapter + fc00 Thor-X LightPulse Fibre Channel Host Adapter + 10df fc00 LP10000 LightPulse Fibre Channel Host Adapter + fc10 Helios-X LightPulse Fibre Channel Host Adapter + fc20 Zephyr-X LightPulse Fibre Channel Host Adapter + fc40 Saturn-X: LightPulse Fibre Channel Host Adapter + fc50 Proteus-X: LightPulse IOV Fibre Channel Host Adapter + fd00 Helios-X LightPulse Fibre Channel Host Adapter +# Also IBM FC 5759 / FC 1910 for POWER + 10df fd02 LightPulse LP11002 Dual-port 4Gigabit PCI Fibre Channel Adapter + fd11 Helios-X LightPulse Fibre Channel Host Adapter + fd12 Helios-X LightPulse Fibre Channel Host Adapter + fe00 Zephyr-X LightPulse Fibre Channel Host Adapter + fe05 Zephyr-X: LightPulse FCoE Adapter + fe11 Zephyr-X LightPulse Fibre Channel Host Adapter + fe12 Zephyr-X LightPulse FCoE Adapter + ff00 Neptune LightPulse Fibre Channel Host Adapter +10e0 Integrated Micro Solutions Inc. + 5026 IMS5026/27/28 + 5027 IMS5027 + 5028 IMS5028 + 8849 IMS8849 + 8853 IMS8853 + 9128 IMS9128 [Twin turbo 128] +10e1 Tekram Technology Co.,Ltd. + 0391 TRM-S1040 + 10e1 0391 DC-315U SCSI-3 Host Adapter + 690c DC-690c + dc29 DC-290 +10e2 Aptix Corporation +10e3 Tundra Semiconductor Corp. + 0000 CA91C042 [Universe] + 0108 Tsi108 Host Bridge for Single PowerPC + 0148 Tsi148 [Tempe] + 1775 1100 VR11 Single Board Computer + 0860 CA91C860 [QSpan] + 0862 CA91C862A [QSpan-II] + 8111 Tsi381 PCIe to PCI Bridge + 8260 CA91L8200B [Dual PCI PowerSpan II] + 8261 CA91L8260B [Single PCI PowerSpan II] + a108 Tsi109 Host Bridge for Dual PowerPC +10e4 Tandem Computers + 8029 Realtek 8029 Network Card +10e5 Micro Industries Corporation +10e6 Gainbery Computer Products Inc. +10e7 Vadem +10e8 Applied Micro Circuits Corp. + 1072 INES GPIB-PCI (AMCC5920 based) + 2011 Q-Motion Video Capture/Edit board + 4750 S5930 [Matchmaker] + 5920 S5920 + 8043 LANai4.x [Myrinet LANai interface chip] + 8062 S5933_PARASTATION + 807d S5933 [Matchmaker] + 8088 Kongsberg Spacetec Format Synchronizer + 8089 Kongsberg Spacetec Serial Output Board + 809c S5933_HEPC3 + 80b9 Harmonix Hi-Card P8 (4x active ISDN BRI) + 80d7 PCI-9112 + 80d8 PCI-7200 + 80d9 PCI-9118 + 80da PCI-9812 + 80fc APCI1500 Signal processing controller (16 dig. inputs + 16 dig. outputs) + 811a PCI-IEEE1355-DS-DE Interface + 814c Fastcom ESCC-PCI (Commtech, Inc.) + 8170 S5933 [Matchmaker] (Chipset Development Tool) + 81e6 Multimedia video controller + 828d APCI3001 Signal processing controller (up to 16 analog inputs) + 8291 Fastcom 232/8-PCI (Commtech, Inc.) + 82c4 Fastcom 422/4-PCI (Commtech, Inc.) + 82c5 Fastcom 422/2-PCI (Commtech, Inc.) + 82c6 Fastcom IG422/1-PCI (Commtech, Inc.) + 82c7 Fastcom IG232/2-PCI (Commtech, Inc.) + 82ca Fastcom 232/4-PCI (Commtech, Inc.) + 82db AJA HDNTV HD SDI Framestore + 82e2 Fastcom DIO24H-PCI (Commtech, Inc.) + 8406 PCIcanx/PCIcan CAN interface [Kvaser AB] + 8407 PCIcan II CAN interface (A1021, PCB-07, PCB-08) [Kvaser AB] + 8851 S5933 on Innes Corp FM Radio Capture card + e004 X-Gene PCIe bridge +10e9 Alps Electric Co., Ltd. +10ea Integraphics + 1680 IGA-1680 + 1682 IGA-1682 + 1683 IGA-1683 + 2000 CyberPro 2000 + 2010 CyberPro 2000A + 5000 CyberPro 5000 + 5050 CyberPro 5050 + 5202 CyberPro 5202 +# CyberPro5202 Audio Function + 5252 CyberPro5252 +10eb Artists Graphics + 0101 3GA + 8111 Twist3 Frame Grabber +10ec Realtek Semiconductor Co., Ltd. + 0139 RTL-8139/8139C/8139C+ Ethernet Controller + 5208 RTS5208 PCI Express Card Reader + 5209 RTS5209 PCI Express Card Reader + 5227 RTS5227 PCI Express Card Reader + 17aa 220e ThinkPad T440p + 17aa 2214 ThinkPad X240 + 5229 RTS5229 PCI Express Card Reader + 1025 0813 Aspire R7-571 + 103c 194e ProBook 455 G1 Notebook + 103c 1985 Pavilion 17-e163sg Notebook PC + 17aa 3832 Yoga 520 + 522a RTS522A PCI Express Card Reader + 103c 8079 EliteBook 840 G3 + 5249 RTS5249 PCI Express Card Reader + 103c 1909 ZBook 15 + 524a RTS524A PCI Express Card Reader + 5250 RTS5250 PCI Express Card Reader + 525a RTS525A PCI Express Card Reader + 1028 06dc Latitude E7470 + 1028 06e4 XPS 15 9550 + 17aa 224f ThinkPad X1 Carbon 5th Gen + 5260 RTS5260 PCI Express Card Reader + 5286 RTS5286 PCI Express Card Reader + 5287 RTL8411B PCI Express Card Reader + 5288 RTS5288 PCI Express Card Reader + 5289 RTL8411 PCI Express Card Reader + 1043 1457 K55A Laptop + 8029 RTL-8029(AS) + 10b8 2011 EZ-Card (SMC1208) + 10ec 8029 RTL-8029(AS) + 1113 1208 EN1208 + 1186 0300 DE-528 + 1259 2400 AT-2400 + 1af4 1100 QEMU Virtual Machine + 8125 RTL8125 2.5GbE Controller + 8129 RTL-8129 + 10ec 8129 RT8129 Fast Ethernet Adapter + 11ec 8129 RTL8111/8168 PCIe Gigabit Ethernet (misconfigured) + 8136 RTL810xE PCI Express Fast Ethernet controller + 103c 1985 RTL8106E on Pavilion 17-e163sg Notebook PC + 103c 2a8c Compaq 500B Microtower + 103c 2ab1 Pavilion p6774 + 103c 30cc Pavilion dv6700 + 1179 ff64 RTL8102E PCI-E Fast Ethernet NIC + 17c0 1053 RTL8101e Medion WIM 2210 Notebook PC [MD96850] + 8137 RTL8104E PCIe Fast Ethernet Controller + 8138 RT8139 (B/C) Cardbus Fast Ethernet Adapter + 10ec 8138 RT8139 (B/C) Fast Ethernet Adapter + 8139 RTL-8100/8101L/8139 PCI Fast Ethernet Adapter + 0357 000a TTP-Monitoring Card V2.0 + 1025 005a TravelMate 290 + 1025 8920 ALN-325 + 1025 8921 ALN-325 + 103c 006a NX9500 + 103c 2a20 Pavilion t3030.de Desktop PC + 103c 30d9 Presario C700 + 1043 1045 L8400B, L3C/S, X58LE notebook + 1043 8109 P5P800-MX Mainboard + 1071 8160 MIM2000 + 10bd 0320 EP-320X-R + 10ec 8139 RTL-8100/8101L/8139 PCI Fast Ethernet Adapter + 10f7 8338 Panasonic CF-Y5 laptop + 1113 ec01 LevelOne FNC-0107TX/FNC-0109TX + 1186 1104 DFE-520TX Fast Ethernet PCI Adapter (rev. D1) + 1186 1300 DFE-538TX + 1186 1320 SN5200 + 1186 8139 DRN-32TX + 11f6 8139 FN22-3(A) LinxPRO Ethernet Adapter + 1259 2500 AT-2500TX + 1259 2503 AT-2500TX/ACPI + 1385 f31d FA311 v2 + 1395 2100 AMB2100 + 1429 d010 ND010/ND012 + 1432 9130 EN-9130TX + 1436 8139 RT8139 + 144d c00c P30/P35 notebook + 1458 e000 GA-7VM400M/7VT600 Motherboard + 1462 0131 MS-1013 Notebook + 1462 217c Aspire L250 + 1462 788c 865PE Neo2-V Mainboard + 146c 1439 FE-1439TX + 1489 6001 GF100TXRII + 1489 6002 GF100TXRA + 149c 139a LFE-8139ATX + 149c 8139 LFE-8139TX + 14cb 0200 LNR-100 Family 10/100 Base-TX Ethernet + 1565 2300 P4TSV Onboard LAN (RTL8100B) + 1631 7003 Onboard RTL8111 on GA-8SIML Rev1.0 Mainboard + 1695 9001 Onboard RTL8101L 10/100 MBit + 16ec 00ff USR997900A + 1799 5000 F5D5000 PCI Card/Desktop Network PCI Card + 1799 5010 F5D5010 CardBus Notebook Network Card + 187e 3303 FN312 + 1904 8139 RTL8139D Fast Ethernet Adapter + 1af4 1100 QEMU Virtual Machine + 2646 0001 KNE120TX + 8e2e 7000 KF-230TX + 8e2e 7100 KF-230TX/2 + a0a0 0007 ALN-325C + 8167 RTL-8110SC/8169SC Gigabit Ethernet + 105b 0e10 RTL-8110SC-GR on a N15235/A74MX mainboard + 1458 e000 GA-MA69G-S3H Motherboard + 1462 235c P965 Neo MS-7235 mainboard + 1462 236c 945P Neo3-F motherboard + 8168 RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller + 1019 8168 RTL8111/8168 PCI Express Gigabit Ethernet controller + 1028 0283 Vostro 220 + 1028 04b2 Vostro 3350 + 1028 04da Vostro 3750 + 1028 06f2 Latitude 3470 + 1028 06f3 Latitude 3570 + 103c 1611 Pavilion DM1Z-3000 + 103c 1950 ProBook 450/455 + 103c 2a6f Asus IPIBL-LB Motherboard + 103c 8615 Pavilion Laptop 15-cw1xxx + 1043 11f5 Notebook motherboard (one of many models) + 1043 16d5 U6V/U31J laptop + 1043 81aa P5B + 1043 82c6 M3A78 Series Motherboard + 1043 83a3 M4A785/P7P55 Motherboard + 1043 8432 P8P67 and other motherboards + 1043 8505 P8 series motherboard + 105b 0d7c D270S/D250S Motherboard + 10ec 8168 RTL8111/8168 PCI Express Gigabit Ethernet controller + 144d c652 RTL8168 on a NP300E5C series laptop + 1458 e000 Onboard Ethernet + 1462 238c Onboard RTL8111b on MSI P965 Platinum Mainboard + 1462 345c RTL8111B on MS-7345 Motherboard + 1462 368c K9AG Neo2 + 1462 4180 Wind PC MS-7418 + 1462 7522 X58 Pro-E + 1462 7c37 X570-A PRO motherboard + 1775 11cc CC11/CL11 + 1849 8168 Motherboard (one of many) + 7470 3468 TG-3468 Gigabit PCI Express Network Adapter + 8086 2055 NUC Kit DN2820FYKH + 8086 d615 Desktop Board D510MO/D525MW + 8169 RTL8169 PCI Gigabit Ethernet Controller + 1025 0079 Aspire 5024WLMi + 10bd 3202 EP-320G-TX1 32-bit PCI Gigabit Ethernet Adapter + 10ec 8169 RTL8169/8110 Family PCI Gigabit Ethernet NIC + 1259 c107 CG-LAPCIGT + 1371 434e ProG-2000L + 1385 311a GA311 + 1385 5200 GA511 Gigabit PC Card + 1458 e000 GA-8I915ME-G Mainboard + 1462 030c K8N Neo-FSR v2.0 mainboard + 1462 065c Hetis 865GV-E (MS-7065) + 1462 702c K8T NEO 2 motherboard + 1462 7094 K8T Neo2-F V2.0 + 16ec 011f USR997903 + 1734 1091 D2030-A1 + a0a0 0449 AK86-L motherboard + 8171 RTL8191SEvA Wireless LAN Controller + 8172 RTL8191SEvB Wireless LAN Controller + 8173 RTL8192SE Wireless LAN Controller + 8174 RTL8192SE Wireless LAN Controller + 8176 RTL8188CE 802.11b/g/n WiFi Adapter + 1043 84b5 PCE-N10 + 1a3b 1139 AW-NE139H Half-size Mini PCIe Card + 8177 RTL8191CE PCIe Wireless Network Adapter + 8178 RTL8192CE PCIe Wireless Network Adapter + 8179 RTL8188EE Wireless Network Adapter + 103c 197d RTL8188EE mini-PCIe card + 8180 RTL8180L 802.11b MAC + 1385 4700 MA521 802.11b Wireless PC Card + 1737 0019 WPC11v4 802.11b Wireless-B Notebook Adapter + 8185 RTL-8185 IEEE 802.11a/b/g Wireless LAN Controller + 818b RTL8192EE PCIe Wireless Network Adapter + 8190 RTL8190 802.11n PCI Wireless Network Adapter + 8191 RTL8192CE PCIe Wireless Network Adapter + 8192 RTL8192E/RTL8192SE Wireless LAN Controller + 8193 RTL8192DE Wireless LAN Controller + 8196 RTL8196 Integrated PCI-e Bridge + 8197 SmartLAN56 56K Modem + 8199 RTL8187SE Wireless LAN Controller + 1462 6894 MN54G2 / MS-6894 Wireless Mini PCIe Card + 8723 RTL8723AE PCIe Wireless Network Adapter + 8812 RTL8812AE 802.11ac PCIe Wireless Network Adapter + 8813 RTL8813AE 802.11ac PCIe Wireless Network Adapter + 8821 RTL8821AE 802.11ac PCIe Wireless Network Adapter + b723 RTL8723BE PCIe Wireless Network Adapter + 10ec 8739 Dell Wireless 1801 + b822 RTL8822BE 802.11a/b/g/n/ac WiFi adapter + 103c 831b Realtek RTL8822BE 802.11ac 2 × 2 Wi-Fi + Bluetooth 4.2 Combo Adapter (MU-MIMO supported) + c821 RTL8821CE 802.11ac PCIe Wireless Network Adapter + c822 RTL8822CE 802.11ac PCIe Wireless Network Adapter + d723 RTL8723DE 802.11b/g/n PCIe Adapter +10ed Ascii Corporation + 7310 V7310 +10ee Xilinx Corporation + 0001 EUROCOM for PCI (ECOMP) + 0002 Octal E1/T1 for PCI ETP Card + 0007 Default PCIe endpoint ID + 0205 Wildcard TE205P + 0210 Wildcard TE210P + 0300 Spartan 3 Designs (Xilinx IP) + 0314 Wildcard TE405P/TE410P (1st Gen) + 0405 Wildcard TE405P (2nd Gen) + 0410 Wildcard TE410P (2nd Gen) + 0600 Xilinx 6 Designs (Xilinx IP) + 3fc0 RME Digi96 + 3fc1 RME Digi96/8 + 3fc2 RME Digi96/8 Pro + 3fc3 RME Digi96/8 Pad + 3fc4 RME Digi9652 (Hammerfall) + 3fc5 RME Hammerfall DSP + 3fc6 RME Hammerfall DSP MADI + 7038 FPGA Card XC7VX690T + 17aa 402f FPGA XC7VX690T-3FFG1157E + 8380 Ellips ProfiXpress Profibus Master + 8381 Ellips Santos Frame Grabber + d154 Copley Controls CAN card (PCI-CAN-02) +# SED is assigned Xilinx PCI device IDs ebf0 through ebff + ebf0 SED Systems Modulator/Demodulator + ebf1 SED Systems Audio Interface Card + ebf2 SED Systems Common PCI Interface + ebf3 SED Systems PCIe-AXI Bridge +10ef Racore Computer Products, Inc. + 8154 M815x Token Ring Adapter +10f0 Peritek Corporation +10f1 Tyan Computer + 2865 Tyan Thunder K8E S2865 + 5300 Tyan S5380 Mainboard +10f2 Achme Computer, Inc. +10f3 Alaris, Inc. +10f4 S-MOS Systems, Inc. +10f5 NKK Corporation + a001 NDR4000 [NR4600 Bridge] +10f6 Creative Electronic Systems SA +10f7 Matsushita Electric Industrial Co., Ltd. +10f8 Altos India Ltd +10f9 PC Direct +10fa Truevision + 000c TARGA 1000 +10fb Thesys Gesellschaft fuer Mikroelektronik mbH + 186f TH 6255 +10fc I-O Data Device, Inc. +# What's in the cardbus end of a Sony ACR-A01 card, comes with newer Vaio CD-RW drives + 0003 Cardbus IDE Controller + 0005 Cardbus SCSI CBSC II +10fd Soyo Computer, Inc +10fe Fast Multimedia AG +10ff NCube +1100 Jazz Multimedia +1101 Initio Corporation + 0002 INI-920 Ultra SCSI Adapter + 1060 INI-A100U2W + 1622 INI-1623 PCI SATA-II Controller + 9100 INI-9100/9100W + 9400 INI-940 Fast Wide SCSI Adapter + 9401 INI-935 Fast Wide SCSI Adapter + 9500 INI-950 SCSI Adapter + 9502 INI-950P Ultra Wide SCSI Adapter +1102 Creative Labs + 0002 EMU10k1 [Sound Blaster Live! Series] + 100a 1102 SB Live! 5.1 Digital OEM SB0220 EMU10K1-JFF + 1102 0020 CT4670/4850 SBLive! Value + 1102 0021 CT4620 SBLive! + 1102 002f M002/M003 Integrated SBLive! + 1102 100a SB0220/0229 SBLive! 5.1 Digital OEM + 1102 4001 E-mu APS + 1102 8022 CT4780 SBLive! Value + 1102 8023 CT4790 SoundBlaster PCI512 + 1102 8024 CT4760 SBLive! + 1102 8025 CT1140/SB0040 Integrated SBLive! + 1102 8026 CT4830 SBLive! Value + 1102 8027 CT4832 SBLive! Value + 1102 8028 CT4870 SBLive! Value + 1102 8029 CT4872 SBLive! Value + 1102 802a CT4890 SoundBlaster PCI256 + 1102 802b CT4891 SoundBlaster PCI256 + 1102 8031 CT4831 SBLive! Value + 1102 8032 CT4871 SBLive! Value + 1102 8033 CT4893 SoundBlaster PCI256 + 1102 8035 CT0060 SBLive! + 1102 8040 CT4760 SBLive! + 1102 8050 CT4750 SoundBlaster PCI512 + 1102 8051 CT4850 SBLive! Value + 1102 8061 SB060 SBLive! Player 5.1 + 1102 8062 SB0100 SBLive! 5.1 + 1102 8063 DXW Integrated SBLive! 5.1 + 1102 8064 SB0100/SB0102 SBLive! 5.1 + 1102 8065 SB0220/0222 SBLive! 5.1 Digital + 1102 8066 SB0228 SBLive! 5.1 Digital + 1102 8067 SB0220 SBLive! 5.1 + 1102 8068 CT0061 SBLive! + 1102 8069 SB0101 SBLive! 5.1 Value + 1102 806a SB0103 SBLive! 5.1 + 1102 806b SB0105 SBLive! 5.1 + 1102 806c SB0221 SBLive! 5.1 + 1102 8071 SB0150 SoundBlaster PCI512 +# EMU8008 PCI version of emu8000 chip + 0003 SB AWE64(D) + 0004 EMU10k2/CA0100/CA0102/CA10200 [Sound Blaster Audigy Series] + 1102 0040 SB0090 Audigy Player +# Probably an early engineering sample + 1102 0041 CT4820 SBLive!2 + 1102 0042 CT0070 Audigy + 1102 0043 CT0072 Audigy + 1102 0051 SB0090 Audigy Player/Platinum (EX) + 1102 0052 SB0162 Audigy ES + 1102 0053 CT0090/SB0092 Audigy Player/OEM + 1102 0054 SB0161 Audigy ES + 1102 0055 SB0192 Audigy + 1102 0056 SB0191 Audigy + 1102 0057 SB0091 Audigy + 1102 0058 SB0095 Audigy Player/OEM + 1102 0059 SB0230 Audigy + 1102 005a SB0231 Audigy + 1102 005b SB0232 Audigy + 1102 005c SB0238 Audigy + 1102 1002 SB0240 Audigy 2 Platinum 6.1 + 1102 1003 SB0350 Audigy 2 / SB0243 Audigy 2 OEM + 1102 1004 SB0242 Audigy 2 + 1102 1005 SB0280 Audigy 2 Platinum Ex + 1102 1006 SB0245 Audigy 2 OEM + 1102 1007 SB0240/SB0244 Audigy 2 Platinum + 1102 1008 SB0320 Audigy 2 + 1102 1009 SB0249 Audigy 2 OEM + 1102 100a SB0246 Audigy 2 + 1102 2001 SB0360 Audigy 2 ZS Platinum Pro + 1102 2002 SB0350 Audigy 2 ZS + 1102 2003 SB0352 Audigy 2 ZS + 1102 2004 SB0355 Audigy 2 ZS + 1102 2005 SB0359 Audigy 2 ZS + 1102 2006 SB035x Audigy 2 OEM + 1102 2007 SB0380 Audigy 4 Pro + 1102 4001 E-MU 1010 [MAEM8810] + 1102 4002 E-MU 0404 + 1102 4003 E-MU 1010 + 0005 EMU20k1 [Sound Blaster X-Fi Series] + 1102 0021 X-Fi Platinum + 1102 002c X-Fi XtremeGamer FATAL1TY PRO + 1102 1003 X-Fi XtremeMusic + 0006 EMU10k1X [SB Live! Value/OEM Series] + 0007 CA0106/CA0111 [SB Live!/Audigy/X-Fi Series] + 1102 0007 SBLive! 24bit + 1102 1001 SB0310 Audigy LS + 1102 1002 SB0312 Audigy LS + 1102 1006 SB0410 SBLive! 24-bit + 1102 100a SB0570 [SB Audigy SE] + 1102 1012 SB0790 X-Fi XA + 1102 1013 Soundblaster X-Fi Xtreme Audio + 1462 1009 K8N Diamond + 0008 CA0108/CA10300 [Sound Blaster Audigy Series] + 1102 0008 EMU0404 Digital Audio System + 1102 1001 SB0400 Audigy 2 Value + 1102 1021 SB0610 Audigy 4 Value + 1102 1022 SBxxx Audigy 2/4 Value + 1102 1023 SB0612 Audigy 2 LS + 1102 1024 SB1550 Audigy 5/Rx + 1102 1101 SBxxxx Audigy 2 SA + 1102 2001 SB0530 Audigy 2 ZS Notebook + 1102 2021 SBxxxx Audigy 4 Notebook + 1102 4002 E-MU 0404 + 1102 4003 E-MU 1010 + 1102 4004 EMU1010 Digital Audio System [MAEM8960] + 1102 4005 E-MU 0404 [MAEM8984] + 1102 4007 E-MU 1010 [MAEM8982] + 1102 4201 E-MU 0202 [MAEM8950] + 0009 CA0110 [Sound Blaster X-Fi Xtreme Audio] + 1102 0010 MB0820 Integrated + 1102 0018 SB1040 PCI Express + 000b EMU20k2 [Sound Blaster X-Fi Titanium Series] + 1102 0041 SB0880 [SoundBlaster X-Fi Titanium PCI-e] + 1102 0062 SB1270 [SoundBlaster X-Fi Titanium HD] + 0012 Sound Core3D [Sound Blaster Recon3D / Z-Series] + 1102 0010 SB1570 SB Audigy Fx + 4001 SB Audigy FireWire Port + 1102 0010 SB Audigy FireWire Port + 7002 SB Live! Game Port + 1102 0020 Gameport Joystick + 7003 SB Audigy Game Port + 1102 0040 SB Audigy Game Port + 1102 0060 SB Audigy2 MIDI/Game Port + 7004 [SB Live! Value] Input device controller + 7005 SB Audigy LS Game Port + 1102 1001 SB0310 Audigy LS MIDI/Game port + 1102 1002 SB0312 Audigy LS MIDI/Game port + 7006 [SB X-Fi Xtreme Audio] CA0110-IBG PCIe to PCI Bridge + 8938 Ectiva EV1938 + 1033 80e5 SlimTower-Jim (NEC) + 1071 7150 Mitac 7150 + 110a 5938 Siemens Scenic Mobile 510PIII + 13bd 100c Ceres-C (Sharp, Intel BX) + 13bd 100d Sharp, Intel Banister + 13bd 100e TwinHead P09S/P09S3 (Sharp) + 13bd f6f1 Marlin (Sharp) + 14ff 0e70 P88TE (TWINHEAD INTERNATIONAL Corp) + 14ff c401 Notebook 9100/9200/2000 (TWINHEAD INTERNATIONAL Corp) + 156d b400 G400 - Geo (AlphaTop (Taiwan)) + 156d b550 G560 (AlphaTop (Taiwan)) + 156d b560 G560 (AlphaTop (Taiwan)) + 156d b700 G700/U700 (AlphaTop (Taiwan)) + 156d b795 G795 (AlphaTop (Taiwan)) + 156d b797 G797 (AlphaTop (Taiwan)) +# nee Triones Technologies, Inc. +1103 HighPoint Technologies, Inc. + 0003 HPT343/345/346/363 + 0004 HPT366/368/370/370A/372/372N + 1103 0001 HPT370A + 1103 0004 HPT366 UDMA66 (r1) / HPT368 UDMA66 (r2) / HPT370 UDMA100 (r3) / HPT370 UDMA100 RAID (r4) + 1103 0005 HPT370 UDMA100 + 1103 0006 HPT302/302N + 0005 HPT372A/372N + 0006 HPT302/302N + 0007 HPT371/371N + 0008 HPT374 + 0009 HPT372N + 0620 RocketRAID 620 2 Port SATA-III Controller + 0622 RocketRAID 622 2 Port SATA-III Controller + 0640 RocketRAID 640 4 Port SATA-III Controller + 0641 RocketRAID 640L 4 Port SATA-III Controller + 0642 RocketRAID 642L SATA-III Controller (2 eSATA ports + 2 internal SATA ports) + 0644 RocketRAID 644 4 Port SATA-III Controller (eSATA) + 0645 RocketRAID 644L 4 Port SATA-III Controller (eSATA) + 0646 RocketRAID 644LS SATA-III Controller (4 eSATA devices connected by 1 SAS cable) + 1720 RocketRAID 1720 (2x SATA II RAID Controller) + 1740 RocketRAID 1740 + 1742 RocketRAID 1742 + 2210 RocketRAID 2210 SATA-II Controller + 11ab 11ab 88SX6042 + 2300 RocketRAID 230x 4 Port SATA-II Controller + 2310 RocketRAID 2310 4 Port SATA-II Controller + 2320 RocketRAID 2320 SATA-II Controller + 2322 RocketRAID 2322 SATA-II Controller + 2340 RocketRAID 2340 16 Port SATA-II Controller + 2640 RocketRAID 2640 SAS/SATA Controller + 2722 RocketRAID 2722 +# SFF-8087 Mini-SAS 16 port internal + 2740 RocketRAID 2740 +# SFF-8088 Mini-SAS 16 port external + 2744 RocketRaid 2744 +# SFF-8088 8 port external / SFF-8087 24 port internal + 2782 RocketRAID 2782 + 3120 RocketRAID 3120 + 3220 RocketRAID 3220 + 3320 RocketRAID 3320 + 4310 RocketRaid 4310 +1104 RasterOps Corp. +1105 Sigma Designs, Inc. + 1105 REALmagic Xcard MPEG 1/2/3/4 DVD Decoder + 8300 REALmagic Hollywood Plus DVD Decoder + 8400 EM840x REALmagic DVD/MPEG-2 Audio/Video Decoder + 8401 EM8401 REALmagic DVD/MPEG-2 A/V Decoder + 8470 EM8470 REALmagic DVD/MPEG-4 A/V Decoder + 8471 EM8471 REALmagic DVD/MPEG-4 A/V Decoder + 8475 EM8475 REALmagic DVD/MPEG-4 A/V Decoder + 1105 0001 REALmagic X-Card + 8476 EM8476 REALmagic DVD/MPEG-4 A/V Decoder + 127d 0000 CineView II + 8485 EM8485 REALmagic DVD/MPEG-4 A/V Decoder + 8486 EM8486 REALmagic DVD/MPEG-4 A/V Decoder +# Found in Cisco DMP-4305G + c621 EM8621L Digital Media Processor + c622 EM8622L MPEG-4.10 (H.264) and SMPTE 421M (VC-1) A/V Decoder +1106 VIA Technologies, Inc. + 0102 Embedded VIA Ethernet Controller + 0130 VT6305 1394.A Controller + 0198 P4X600 Host Bridge + 0204 K8M800 Host Bridge + 0208 PT890 Host Bridge + 0238 K8T890 Host Bridge + 0258 PT880 Host Bridge + 0259 CN333/CN400/PM880 Host Bridge + 0269 KT880 Host Bridge + 0282 K8T800Pro Host Bridge + 1043 80a3 A8V Deluxe + 0290 K8M890 Host Bridge + 0293 PM896 Host Bridge + 0296 P4M800 Host Bridge + 0305 VT8363/8365 [KT133/KM133] + 1019 0987 K7VZA Mainboard + 1043 8033 A7V Mainboard + 1043 803e A7V-E Mainboard + 1043 8042 A7V133/A7V133-C Mainboard + 147b a401 KT7/KT7-RAID/KT7A/KT7A-RAID Mainboard + 0308 PT880 Ultra/PT894 Host Bridge + 1043 8199 P4V800D-X Mainboard + 1849 0308 Motherboard + 0314 CN700/VN800/P4M800CE/Pro Host Bridge + 0324 CX700/VX700 Host Bridge + 0327 P4M890 Host Bridge + 0336 K8M890CE Host Bridge + 0340 PT900 Host Bridge + 0351 K8T890CF Host Bridge + 0353 VX800 Host Bridge + 0364 CN896/VN896/P4M900 Host Bridge + 1043 81ce P5VD2-VM mothervoard + 0391 VT8371 [KX133] + 0409 VX855/VX875 Host Bridge: Host Control + 0410 VX900 Host Bridge: Host Control + 0415 VT6415 PATA IDE Host Controller + 1043 838f Motherboard + 0501 VT8501 [Apollo MVP4] + 0505 VT82C505 +# Shares chip with :0576. The VT82C576M has :1571 instead of :0561. + 0561 VT82C576MV + 0571 VT82C586A/B/VT82C686/A/B/VT823x/A/C PIPC Bus Master IDE + 1019 0985 P6VXA Motherboard + 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) + 1043 8052 VT8233A Bus Master ATA100/66/33 IDE + 1043 808c A7V8X / A7V333 motherboard + 1043 80a1 A7V8X-X motherboard rev. 1.01 + 1043 80ed A7V600/K8V-X/A8V Deluxe motherboard + 1106 0571 VT82C586/B/VT82C686/A/B/VT8233/A/C/VT8235 PIPC Bus Master IDE + 1179 0001 Magnia Z310 + 1297 f641 FX41 motherboard + 1458 5002 GA-7VAX Mainboard + 1462 5901 KT6 Delta-FIS2R (MS-6590) + 1462 7020 K8T NEO 2 motherboard + 1462 7094 K8T Neo2-F V2.0 + 1462 7120 KT4AV motherboard + 1462 7181 K8MM3-V mainboard + 147b 1407 KV8-MAX3 motherboard +# probably all K7VT2/4*/6 + 1849 0571 K7VT series Motherboards + 0576 VT82C576 3V [Apollo Master] + 0581 CX700/VX700 RAID Controller +# Upgrade bios to get correct ID: 5324 instead of 0581 + 1106 0581 Wrong IDE ID + 0585 VT82C585VP [Apollo VP1/VPX] + 0586 VT82C586/A/B PCI-to-ISA [Apollo VP] + 1106 0000 MVP3 ISA Bridge + 0591 VT8237A SATA 2-Port Controller + 0595 VT82C595 [Apollo VP2] + 0596 VT82C596 ISA [Mobile South] + 1106 0000 VT82C596/A/B PCI to ISA Bridge + 1458 0596 VT82C596/A/B PCI to ISA Bridge + 0597 VT82C597 [Apollo VP3] + 0598 VT82C598 [Apollo MVP3] + 0601 VT8601 [Apollo ProMedia] + 0605 VT8605 [ProSavage PM133] + 103c 1254 D9840-60001 [Brio BA410 Motherboard] + 1043 802c CUV4X mainboard + 0680 VT82C680 [Apollo P6] + 0686 VT82C686 [Apollo Super South] + 1019 0985 P6VXA Motherboard + 103c 1256 D9840-60001 [Brio BA410 Motherboard] + 1043 802c CUV4X mainboard + 1043 8033 A7V Mainboard + 1043 803e A7V-E Mainboard + 1043 8040 A7M266 Mainboard + 1043 8042 A7V133/A7V133-C Mainboard + 1106 0000 VT82C686/A PCI to ISA Bridge + 1106 0686 VT82C686/A PCI to ISA Bridge + 1179 0001 Magnia Z310 + 147b a702 KG7-Lite Mainboard + 0691 VT82C693A/694x [Apollo PRO133x] + 1019 0985 P6VXA Motherboard + 1179 0001 Magnia Z310 + 1458 0691 VT82C691 Apollo Pro System Controller + 0693 VT82C693 [Apollo Pro Plus] + 0698 VT82C693A [Apollo Pro133 AGP] + 0709 VX11 Standard Host Bridge + 070a VX11 PCI Express Root Port + 070b VX11 PCI Express Root Port + 070c VX11 PCI Express Root Port + 070d VX11 PCI Express Root Port + 070e VX11 PCI Express Root Port + 0926 VT82C926 [Amazon] + 1000 VT82C570MV + 1106 VT82C570MV + 1122 VX800/VX820 Chrome 9 HC3 Integrated Graphics + 1204 K8M800 Host Bridge + 1208 PT890 Host Bridge + 1238 K8T890 Host Bridge + 1258 PT880 Host Bridge + 1259 CN333/CN400/PM880 Host Bridge + 1269 KT880 Host Bridge + 1282 K8T800Pro Host Bridge + 1290 K8M890 Host Bridge + 1293 PM896 Host Bridge + 1296 P4M800 Host Bridge + 1308 PT894 Host Bridge + 1314 CN700/VN800/P4M800CE/Pro Host Bridge + 1324 CX700/VX700 Host Bridge + 1327 P4M890 Host Bridge + 1336 K8M890CE Host Bridge + 1340 PT900 Host Bridge + 1351 VT3351 Host Bridge + 1353 VX800/VX820 Error Reporting + 1364 CN896/VN896/P4M900 Host Bridge + 1409 VX855/VX875 Error Reporting + 1410 VX900 Error Reporting + 1571 VT82C576M/VT82C586 + 1595 VT82C595/97 [Apollo VP2/97] + 1732 VT1732 [Envy24 II] PCI Multi-Channel Audio Controller + 2106 VIA Rhine Family Fast Ethernet Adapter (VT6105) + 2204 K8M800 Host Bridge + 2208 PT890 Host Bridge + 2238 K8T890 Host Bridge + 2258 PT880 Host Bridge + 2259 CN333/CN400/PM880 CPU Host Bridge + 2269 KT880 Host Bridge + 2282 K8T800Pro Host Bridge + 2290 K8M890 Host Bridge + 2293 PM896 Host Bridge + 2296 P4M800 Host Bridge + 2308 PT894 Host Bridge + 2314 CN700/VN800/P4M800CE/Pro Host Bridge + 2324 CX700/VX700 Host Bridge + 2327 P4M890 Host Bridge + 2336 K8M890CE Host Bridge + 2340 PT900 Host Bridge + 2351 VT3351 Host Bridge + 2353 VX800/VX820 Host Bus Control + 2364 CN896/VN896/P4M900 Host Bridge + 2409 VX855/VX875 Host Bus Control + 2410 VX900 CPU Bus Controller + 287a VT8251 PCI to PCI Bridge + 287b VT8251 Host Bridge + 287c VT8251 PCIE Root Port + 287d VT8251 PCIE Root Port + 287e VT8237/8251 Ultra VLINK Controller + 3022 CLE266 + 3038 VT82xx/62xx UHCI USB 1.1 Controller + 0925 1234 onboard UHCI USB 1.1 Controller + 1019 0985 P6VXA Motherboard + 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) + 1043 8080 A7V333 motherboard + 1043 808c VT6202 USB2.0 4 port controller + 1043 80a1 A7V8X-X motherboard + 1043 80ed A7V600/K8V-X/A8V Deluxe motherboard + 1179 0001 Magnia Z310 + 1458 5004 GA-7VAX Mainboard + 1462 5901 KT6 Delta-FIS2R (MS-6590) + 1462 7020 K8T NEO 2 motherboard + 1462 7094 K8T Neo2-F V2.0 + 1462 7120 KT4AV motherboard + 1462 7181 K8MM3-V mainboard + 147b 1407 KV8-MAX3 motherboard + 182d 201d CN-029 USB2.0 4 port PCI Card +# probably all K7VT2/4*/6 + 1849 3038 K7VT series Motherboards + 19da a179 ZBOX nano VD01 + 1af4 1100 QEMU Virtual Machine + 3040 VT82C586B ACPI + 3043 VT86C100A [Rhine] + 10bd 0000 VT86C100A Fast Ethernet Adapter + 1106 0100 VT86C100A Fast Ethernet Adapter + 1186 1400 DFE-530TX PCI Fast Ethernet Adapter (rev. A) + 3044 VT6306/7/8 [Fire II(M)] IEEE 1394 OHCI Controller + 0010 0001 IEEE 1394 4port DCST 1394-3+1B + 1025 005a TravelMate 290 + 103c 2a20 Pavilion t3030.de Desktop PC + 103c 2a3b Media Center PC m7590n + 1043 808a A8V/A8N/P4P800/P5SD2 series motherboard + 1043 81fe Motherboard + 1458 1000 GA-7VT600-1394 Motherboard + 1462 207d K8NGM2 series motherboard + 1462 217d Aspire L250 + 1462 590d KT6 Delta-FIS2R (MS-6590) + 1462 702d K8T NEO 2 motherboard + 1462 971d MS-6917 + 3050 VT82C596 Power Management + 3051 VT82C596 Power Management + 3053 VT6105M [Rhine-III] + 1186 1404 DFE-530TX PCI Fast Ethernet Adapter (rev. D) + 3057 VT82C686 [Apollo Super ACPI] + 1019 0985 P6VXA Motherboard + 1019 0987 K7VZA Motherboard + 1043 8033 A7V Mainboard + 1043 803e A7V-E Mainboard + 1043 8040 A7M266 Mainboard + 1043 8042 A7V133/A7V133-C Mainboard + 1179 0001 Magnia Z310 + 3058 VT82C686 AC97 Audio Controller + 0e11 0097 SoundMax Digital Integrated Audio + 0e11 b194 Soundmax integrated digital audio + 1019 0985 P6VXA Motherboard + 1019 0987 K7VZA Motherboard + 103c 1251 D9840-60001 [Brio BA410 Motherboard] + 1043 1106 A7V133/A7V133-C Mainboard + 1106 4511 Onboard Audio on EP7KXA + 1106 aa03 VT1612A AC'97 Audio Controller + 11d4 5348 AD1881A audio + 1458 7600 Onboard Audio + 1462 3091 MS-6309 Onboard Audio + 1462 3092 MS-6309 v2.x Mainboard (VIA VT1611A codec) + 1462 3300 MS-6330 Onboard Audio + 1462 3400 MS-6340 (VT8363) motherboard + 15dd 7609 Onboard Audio + 3059 VT8233/A/8235/8237 AC97 Audio Controller + 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) + 1019 1841 M811 (VT8367/VT8235/VT6103) [KT333] motherboard + 1019 1877 K8M800-M2 (V2.0) onboard audio + 1043 8095 A7V8X Motherboard (Realtek ALC650 codec) + 1043 80a1 A7V8X-X Motherboard + 1043 80b0 A7V600/K8V-X/K8V Deluxe motherboard (ADI AD1980 codec [SoundMAX]) + 1043 80f3 SK8V motherboard + 1043 810d P5VD1-X (AD1888 codec [SoundMax]) + 1043 812a A8V Deluxe motherboard (Realtek ALC850 codec) + 10ec 8168 High Definition Audio + 1106 3059 L7VMM2 Motherboard + 1106 4161 K7VT2 motherboard + 1106 4170 PCPartner P4M800-8237R Motherboard + 1106 4552 Soyo KT-600 Dragon Plus (Realtek ALC 650) + 1297 c160 FX41 motherboard (Realtek ALC650 codec) + 1413 147b KV8 Pro motherboard onboard audio + 1458 a002 GA-7VAX Onboard Audio (Realtek ALC650) + 1462 0080 K8T NEO 2 motherboard + 1462 3800 KT266 onboard audio + 1462 5901 KT6 Delta-FIS2R (MS-6590) + 1462 7181 K8MM3-V mainboard + 147b 1407 KV8-MAX3 motherboard + 1695 300c Realtek ALC655 audio on EP-8KRA series mainboard + 1849 0850 ASRock 775Dual-880 Pro onboard audio (Realtek ALC850) + 1849 9739 P4VT8 Mainboard (C-Media CMI9739A codec) +# probably all K7VT2/4*/6 + 1849 9761 K7VT series Motherboards + 4005 4710 MSI K7T266 Pro2-RU (MSI-6380 v2) onboard audio (Realtek/ALC 200/200P) + a0a0 01b6 AK77-8XN onboard audio + a0a0 0342 AK86-L motherboard + 3065 VT6102/VT6103 [Rhine-II] + 1043 80a1 A7V8X-X Motherboard + 1043 80ed A7V600-X Motherboard + 1106 0102 VT6102/6103 [Rhine II] Ethernet Controller + 1186 1400 DFE-530TX PCI Fast Ethernet Adapter (rev. A) + 1186 1401 DFE-530TX PCI Fast Ethernet Adapter (rev. B) + 1186 1402 DFE-530TX PCI Fast Ethernet Adapter (rev. B) + 13b9 1421 LD-10/100AL PCI Fast Ethernet Adapter (rev.B) + 1462 7061 MS-7061 + 1462 7181 K8MM3-V mainboard + 147b 1c09 NV7 Motherboard + 1695 3005 VT6103 +# probably all K7VT2/4*/6 + 1849 3065 K7VT series Motherboards +# This hosts more than just the Intel 537 codec, it also hosts PCtel (SIL33) and SmartLink (SIL34) codecs + 3068 AC'97 Modem Controller + 1462 309e MS-6309 Saturn Motherboard + 3074 VT8233 PCI to ISA Bridge + 1043 8052 VT8233A + 3091 VT8633 [Apollo Pro266] + 3099 VT8366/A/7 [Apollo KT266/A/333] + 1019 1841 M811 (VT8367/VT8235/VT6103) [KT333] motherboard + 1043 8064 A7V266-E Mainboard + 1043 807f A7V333 Mainboard + 1849 3099 K7VT2 motherboard + 3101 VT8653 Host Bridge + 3102 VT8662 Host Bridge + 3103 VT8615 Host Bridge + 3104 USB 2.0 + 0925 1234 onboard EHCI USB 2.0 Controller + 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) + 1043 808c A7V8X motherboard + 1043 80a1 A7V8X-X motherboard rev 1.01 + 1043 80ed A7V600/K8V-X/A8V Deluxe motherboard + 1106 3104 USB 2.0 Controller + 1297 f641 FX41 motherboard + 1458 5004 GA-7VAX Mainboard + 1462 5901 KT6 Delta-FIS2R (MS-6590) + 1462 7020 K8T NEO 2 motherboard + 1462 7094 K8T Neo2-F V2.0 + 1462 7120 KT4AV motherboard + 1462 7181 K8MM3-V mainboard + 147b 1407 KV8-MAX3 motherboard + 182d 201d CN-029 USB 2.0 4 port PCI Card +# probably all K7VT2/4*/6 + 1849 3104 K7VT series Motherboards + 19da a179 ZBOX nano VD01 + 3106 VT6105/VT6106S [Rhine-III] + 1106 0105 VT6106S [Rhine-III] + 1186 1403 DFE-530TX PCI Fast Ethernet Adapter (rev. C) + 1186 1405 DFE-520TX Fast Ethernet PCI Adapter + 1186 1406 DFE-530TX+ rev F2 + 1186 1407 DFE-538TX + 3108 K8M800/K8N800/K8N800A [S3 UniChrome Pro] + 3109 VT8233C PCI to ISA Bridge + 3112 VT8361 [KLE133] Host Bridge + 3113 VPX/VPX2 PCI to PCI Bridge Controller + 3116 VT8375 [KM266/KL266] Host Bridge + 1297 f641 FX41 motherboard + 3118 CN400/PM800/PM880/PN800/PN880 [S3 UniChrome Pro] + 3119 VT6120/VT6121/VT6122 Gigabit Ethernet Adapter + 3122 VT8623 [Apollo CLE266] integrated CastleRock graphics + 3123 VT8623 [Apollo CLE266] + 3128 VT8753 [P4X266 AGP] + 3133 VT3133 Host Bridge + 3142 VT6651 WiFi Adapter, 802.11b + 3147 VT8233A ISA Bridge + 1043 808c A7V333 motherboard + 3148 P4M266 Host Bridge + 3149 VIA VT6420 SATA RAID Controller + 1043 80ed A7V600/K8V Deluxe/K8V-X/A8V Deluxe motherboard + 1458 b003 GA-7VM400AM(F) Motherboard + 1462 5901 KT6 Delta-FIS2R (MS-6590) + 1462 7020 K8T Neo 2 Motherboard + 1462 7094 K8T Neo2-F V2.0 + 1462 7181 K8MM3-V mainboard + 147b 1407 KV8-MAX3 motherboard + 147b 1408 KV7 + 1849 3149 K7VT6 motherboard + a0a0 04ad AK86-L motherboard + 3156 P/KN266 Host Bridge + 3157 CX700/VX700 [S3 UniChrome Pro] + 3164 VT6410 ATA133 RAID controller + 1043 80f4 P4P800 Mainboard Deluxe ATX + 1462 7028 915P/G Neo2 + 3168 P4X333/P4X400/PT800 AGP Bridge + 1849 3168 P4VT8 Mainboard + 3177 VT8235 ISA Bridge + 1019 0a81 L7VTA v1.0 Motherboard (KT400-8235) + 1019 1841 M811 (VT8367/VT8235/VT6103) [KT333] motherboard + 1043 808c A7V8X motherboard + 1043 80a1 A7V8X-X motherboard + 1106 0000 KT4AV motherboard + 1297 f641 FX41 motherboard + 1458 5001 GA-7VAX Mainboard +# probably all K7VT2/4*/6 + 1849 3177 K7VT series Motherboards + 3178 ProSavageDDR P4N333 Host Bridge + 3188 VT8385 [K8T800 AGP] Host Bridge + 1043 80a3 K8V Deluxe/K8V-X motherboard + 147b 1407 KV8-MAX3 motherboard + 3189 VT8377 [KT400/KT600 AGP] Host Bridge + 1043 807f A7V8X motherboard + 1106 0000 KT4AV motherboard (KT400A) + 1458 5000 GA-7VAX Mainboard +# probably all K7VT2/4*/6 + 1849 3189 K7VT series Motherboards + 31b0 VX11 Standard Host Bridge + 31b1 VX11 Standard Host Bridge + 31b2 VX11 DRAM Controller + 31b3 VX11 Power Management Controller + 31b4 VX11 I/O APIC + 31b5 VX11 Scratch Device + 31b7 VX11 Standard Host Bridge + 31b8 VX11 PCI to PCI Bridge + 3204 K8M800 Host Bridge + 3205 VT8378 [KM400/A] Chipset Host Bridge + 1458 5000 GA-7VM400M Motherboard + 3208 PT890 Host Bridge + 3213 VPX/VPX2 PCI to PCI Bridge Controller + 3218 K8T800M Host Bridge + 3227 VT8237 ISA bridge [KT600/K8T800/K8T890 South] + 1043 80ed A7V600/K8V-X/A8V Deluxe motherboard + 1106 3227 DFI KT600-AL / Soltek SL-B9D-FGR Motherboard + 1458 5001 GA-7VT600 Motherboard + 147b 1407 KV8-MAX3 motherboard + 1849 3227 K7VT4 motherboard + 3230 K8M890CE/K8N890CE [Chrome 9] + 3238 K8T890 Host Bridge + 3249 VT6421 IDE/SATA Controller + 1106 3249 VT6421 IDE/SATA Controller + 324a CX700/VX700 PCI to PCI Bridge + 324b CX700/VX700 Host Bridge + 324e CX700/VX700 Internal Module Bus + 3253 VT6655 WiFi Adapter, 802.11a/b/g + 3258 PT880 Host Bridge + 3259 CN333/CN400/PM880 Host Bridge + 3260 VIA Chrome9 HC IGP + 3269 KT880 Host Bridge + 3282 K8T800Pro Host Bridge + 3287 VT8251 PCI to ISA Bridge + 3288 VT8237A/VT8251 HDA Controller + 19da a179 ZBOX VD01 + 3290 K8M890 Host Bridge + 3296 P4M800 Host Bridge + 3324 CX700/VX700 Host Bridge + 3327 P4M890 Host Bridge + 3336 K8M890CE Host Bridge + 3337 VT8237A PCI to ISA Bridge + 3340 PT900 Host Bridge + 3343 P4M890 [S3 UniChrome Pro] + 3344 CN700/P4M800 Pro/P4M800 CE/VN800 Graphics [S3 UniChrome Pro] + 3349 VT8251 AHCI/SATA 4-Port Controller + 3351 VT3351 Host Bridge + 3353 VX800 PCI to PCI Bridge + 3364 CN896/VN896/P4M900 Host Bridge + 3371 CN896/VN896/P4M900 [Chrome 9 HC] + 3372 VT8237S PCI to ISA Bridge + 337a VT8237A PCI to PCI Bridge + 337b VT8237A Host Bridge + 3403 VT6315 Series Firewire Controller + 1043 8374 M5A88-V EVO + 1043 8384 P8P67 Deluxe Motherboard + 3409 VX855/VX875 DRAM Bus Control + 3410 VX900 DRAM Bus Control + 19da a179 ZBOX nano VD01 + 3432 VL80x xHCI USB 3.0 Controller + 3456 VX11 Standard Host Bridge + 345b VX11 Miscellaneous Bus + 3483 VL805 USB 3.0 Host Controller + 3a01 VX11 Graphics [Chrome 645/640] + 4149 VIA VT6420 (ATA133) Controller + 4204 K8M800 Host Bridge + 4208 PT890 Host Bridge + 4238 K8T890 Host Bridge + 4258 PT880 Host Bridge + 4259 CN333/CN400/PM880 Host Bridge + 4269 KT880 Host Bridge + 4282 K8T800Pro Host Bridge + 4290 K8M890 Host Bridge + 4293 PM896 Host Bridge + 4296 P4M800 Host Bridge + 4308 PT894 Host Bridge + 4314 CN700/VN800/P4M800CE/Pro Host Bridge + 4324 CX700/VX700 Host Bridge + 4327 P4M890 Host Bridge + 4336 K8M890CE Host Bridge + 4340 PT900 Host Bridge + 4351 VT3351 Host Bridge + 4353 VX800/VX820 Power Management Control + 4364 CN896/VN896/P4M900 Host Bridge + 4409 VX855/VX875 Power Management Control + 4410 VX900 Power Management and Chip Testing Control + 19da a179 ZBOX nano VD01 + 5030 VT82C596 ACPI [Apollo PRO] + 5122 VX855/VX875 Chrome 9 HCM Integrated Graphics + 5208 PT890 I/O APIC Interrupt Controller + 5238 K8T890 I/O APIC Interrupt Controller + 5287 VT8251 Serial ATA Controller + 5290 K8M890 I/O APIC Interrupt Controller + 5308 PT894 I/O APIC Interrupt Controller + 5324 VX800 Serial ATA and EIDE Controller + 5327 P4M890 I/O APIC Interrupt Controller + 5336 K8M890CE I/O APIC Interrupt Controller + 5340 PT900 I/O APIC Interrupt Controller + 5351 VT3351 I/O APIC Interrupt Controller + 5353 VX800/VX820 APIC and Central Traffic Control + 5364 CN896/VN896/P4M900 I/O APIC Interrupt Controller + 5372 VT8237/8251 Serial ATA Controller + 5409 VX855/VX875 APIC and Central Traffic Control + 5410 VX900 APIC and Central Traffic Control + 6100 VT85C100A [Rhine II] + 6287 SATA RAID Controller + 6290 K8M890CE Host Bridge + 6327 P4M890 Security Device + 6353 VX800/VX820 Scratch Registers + 6364 CN896/VN896/P4M900 Security Device + 6409 VX855/VX875 Scratch Registers + 6410 VX900 Scratch Registers + 19da a179 ZBOX nano VD01 + 7122 VX900 Graphics [Chrome9 HD] + 7204 K8M800 Host Bridge + 7205 KM400/KN400/P4M800 [S3 UniChrome] + 1458 d000 Gigabyte GA-7VM400(A)M(F) Motherboard + 1462 7061 MS-7061 + 7208 PT890 Host Bridge + 7238 K8T890 Host Bridge + 7258 PT880 Host Bridge + 7259 CN333/CN400/PM880 Host Bridge + 7269 KT880 Host Bridge + 7282 K8T800Pro Host Bridge + 7290 K8M890 Host Bridge + 7293 PM896 Host Bridge + 7296 P4M800 Host Bridge + 7308 PT894 Host Bridge + 7314 CN700/VN800/P4M800CE/Pro Host Bridge + 7324 CX700/VX700 Host Bridge + 7327 P4M890 Host Bridge + 7336 K8M890CE Host Bridge + 7340 PT900 Host Bridge + 7351 VT3351 Host Bridge + 7353 VX800/VX820 North-South Module Interface Control + 7364 CN896/VN896/P4M900 Host Bridge + 7409 VX855/VX875 North-South Module Interface Control + 7410 VX900 North-South Module Interface Control + 19da a179 ZBOX nano VD01 + 8231 VT8231 [PCI-to-ISA Bridge] + 8235 VT8235 ACPI + 8305 VT8363/8365 [KT133/KM133 AGP] + 8324 CX700/VX700 PCI to ISA Bridge + 8353 VX800/VX820 Bus Control and Power Management + 8391 VT8371 [KX133 AGP] + 8400 MVP4 + 8409 VX855/VX875 Bus Control and Power Management + 8410 VX900 Bus Control and Power Management + 19da a179 ZBOX VD01 + 8500 KLE133/PLE133/PLE133T + 8501 VT8501 [Apollo MVP4 AGP] + 8596 VT82C596 [Apollo PRO AGP] + 8597 VT82C597 [Apollo VP3 AGP] + 8598 VT82C598/694x [Apollo MVP3/Pro133x AGP] + 1019 0985 P6VXA Motherboard + 8601 VT8601 [Apollo ProMedia AGP] + 8605 VT8605 [PM133 AGP] + 8691 VT82C691 [Apollo Pro] + 8693 VT82C693 [Apollo Pro Plus] PCI Bridge + 8a25 PL133/PL133T [S3 ProSavage] + 8a26 KL133/KL133A/KM133/KM133A [S3 ProSavage] + 8d01 PN133/PN133T [S3 Twister] + 8d04 KM266/P4M266/P4M266A/P4N266 [S3 ProSavageDDR] + 9001 VX900 Serial ATA Controller + 9082 Standard AHCI 1.0 SATA Controller + 9140 HDMI Audio Device + 9201 USB3.0 Controller + 9530 Secure Digital Memory Card Controller + 95d0 SDIO Host Controller + a208 PT890 PCI to PCI Bridge Controller + a238 K8T890 PCI to PCI Bridge Controller + a327 P4M890 PCI to PCI Bridge Controller + a353 VX8xx South-North Module Interface Control + a364 CN896/VN896/P4M900 PCI to PCI Bridge Controller + a409 VX855/VX875 USB Device Controller + a410 VX900 PCI Express Root Port 0 + b091 VT8633 [Apollo Pro266 AGP] + b099 VT8366/A/7 [Apollo KT266/A/333 AGP] + b101 VT8653 AGP Bridge + b102 VT8362 AGP Bridge + b103 VT8615 AGP Bridge + b112 VT8361 [KLE133] AGP Bridge + b113 VPX/VPX2 I/O APIC Interrupt Controller + b115 VT8363/8365 [KT133/KM133] PCI Bridge + b168 VT8235 PCI Bridge + b188 VT8237/8251 PCI bridge [K8M890/K8T800/K8T890 South] + 147b 1407 KV8-MAX3 motherboard + b198 VT8237/VX700 PCI Bridge + b213 VPX/VPX2 I/O APIC Interrupt Controller + b353 VX855/VX875/VX900 PCI to PCI Bridge + b410 VX900 PCI Express Root Port 1 + b999 [K8T890 North / VT8237 South] PCI Bridge + c208 PT890 PCI to PCI Bridge Controller + c238 K8T890 PCI to PCI Bridge Controller + c327 P4M890 PCI to PCI Bridge Controller + c340 PT900 PCI to PCI Bridge Controller + c353 VX800/VX820 PCI Express Root Port + c364 CN896/VN896/P4M900 PCI to PCI Bridge Controller + c409 VX855/VX875 EIDE Controller + c410 VX900 PCI Express Root Port 2 + d104 VT8237R USB UDCI Controller + d208 PT890 PCI to PCI Bridge Controller + d213 VPX/VPX2 PCI to PCI Bridge Controller + d238 K8T890 PCI to PCI Bridge Controller + d340 PT900 PCI to PCI Bridge Controller + d410 VX900 PCI Express Root Port 3 + e208 PT890 PCI to PCI Bridge Controller + e238 K8T890 PCI to PCI Bridge Controller + e340 PT900 PCI to PCI Bridge Controller + e353 VX800/VX820 PCI Express Root Port + e410 VX900 PCI Express Physical Layer Electrical Sub-block + f208 PT890 PCI to PCI Bridge Controller + f238 K8T890 PCI to PCI Bridge Controller + f340 PT900 PCI to PCI Bridge Controller + f353 VX800/VX820 PCI Express Root Port +1107 Stratus Computers + 0576 VIA VT82C570MV [Apollo] (Wrong vendor ID!) +1108 Proteon, Inc. + 0100 p1690plus_AA + 0101 p1690plus_AB + 0105 P1690Plus + 0108 P1690Plus + 0138 P1690Plus + 0139 P1690Plus + 013c P1690Plus + 013d P1690Plus +1109 Cogent Data Technologies, Inc. + 1400 EM110TX [EX110TX] +110a Siemens AG + 0002 Pirahna 2-port + 0005 Tulip controller, power management, switch extender + 0006 FSC PINC (I/O-APIC) + 0015 FSC Multiprocessor Interrupt Controller + 001d FSC Copernicus Management Controller + 007b FSC Remote Service Controller, mailbox device + 007c FSC Remote Service Controller, shared memory device + 007d FSC Remote Service Controller, SMIC device + 2101 HST SAPHIR V Primary PCI (ISDN/PMx) +# Superfastcom-PCI (Commtech, Inc.) or DSCC4 WAN Adapter + 2102 DSCC4 PEB/PEF 20534 DMA Supported Serial Communication Controller with 4 Channels + 2104 Eicon Diva 2.02 compatible passive ISDN card + 3141 SIMATIC NET CP 5611 / 5621 + 3142 SIMATIC NET CP 5613 / 5614 + 3143 SIMATIC NET CP 1613 + 4021 SIMATIC NET CP 5512 (Profibus and MPI Cardbus Adapter) + 4029 SIMATIC NET CP 5613 A2 + 110a 4029 SIMATIC NET CP 5613 A2 + 110a c029 SIMATIC NET CP 5614 A2 + 4035 SIMATIC NET CP 1613 A2 + 4036 SIMATIC NET CP 1616 + 4038 SIMATIC NET CP 1604 + 4069 SIMATIC NET CP 5623 + 110a 4069 SIMATIC NET CP 5623 + 110a c069 SIMATIC NET CP 5624 + 407c SIMATIC NET CP 5612 + 407d SIMATIC NET CP 5613 A3 + 407e SIMATIC NET CP 5622 + 4083 SIMATIC NET CP 5614 A3 + 4084 SIMATIC NET CP 1626 + 4942 FPGA I-Bus Tracer for MBD + 6120 SZB6120 +110b Chromatic Research Inc. + 0001 Mpact Media Processor + 0004 Mpact 2 +110c Mini-Max Technology, Inc. +110d Znyx Advanced Systems +110e CPU Technology +110f Ross Technology +1110 Powerhouse Systems + 6037 Firepower Powerized SMP I/O ASIC + 6073 Firepower Powerized SMP I/O ASIC +1111 Santa Cruz Operation +# Also claimed to be RNS or Rockwell International, current PCISIG records list Osicom +1112 Osicom Technologies Inc + 2200 FDDI Adapter + 2300 Fast Ethernet Adapter + 2340 4 Port Fast Ethernet Adapter + 2400 ATM Adapter +1113 Accton Technology Corporation + 1211 SMC2-1211TX + 103c 1207 EN-1207D Fast Ethernet Adapter + 1113 1211 EN-1207D Fast Ethernet Adapter + 1216 EN-1216 Ethernet Adapter + 1113 1216 EN1207F series PCI Fast Ethernet Adapter + 1113 2220 EN2220A Cardbus Fast Ethernet Adapter + 1113 2242 EN2242 10/100 Ethernet Mini-PCI Card + 111a 1020 SpeedStream 1020 PCI 10/100 Ethernet Adaptor [EN-1207F-TX ?] + 1217 EN-1217 Ethernet Adapter + 5105 10Mbps Network card + 9211 EN-1207D Fast Ethernet Adapter + 1113 9211 EN-1207D Fast Ethernet Adapter + 9511 21x4x DEC-Tulip compatible Fast Ethernet + d301 CPWNA100 (Philips wireless PCMCIA) + ec02 SMC 1244TX v3 + ee23 SMCWPCIT-G 108Mbps Wireless PCI adapter +1114 Atmel Corporation + 0506 at76c506 802.11b Wireless Network Adaptor +1115 3D Labs +1116 Data Translation + 0022 DT3001 + 0023 DT3002 + 0024 DT3003 + 0025 DT3004 + 0026 DT3005 + 0027 DT3001-PGL + 0028 DT3003-PGL + 0051 DT322 + 0060 DT340 + 0069 DT332 + 80c2 DT3162 +1117 Datacube, Inc + 9500 Max-1C SVGA card + 9501 Max-1C image processing +1118 Berg Electronics +1119 ICP Vortex Computersysteme GmbH + 0000 GDT 6000/6020/6050 + 0001 GDT 6000B/6010 + 0002 GDT 6110/6510 + 0003 GDT 6120/6520 + 0004 GDT 6530 + 0005 GDT 6550 + 0006 GDT 6117/6517 + 0007 GDT 6127/6527 + 0008 GDT 6537 + 0009 GDT 6557/6557-ECC + 000a GDT 6115/6515 + 000b GDT 6125/6525 + 000c GDT 6535 + 000d GDT 6555/6555-ECC + 0100 GDT 6117RP/6517RP + 0101 GDT 6127RP/6527RP + 0102 GDT 6537RP + 0103 GDT 6557RP + 0104 GDT 6111RP/6511RP + 0105 GDT 6121RP/6521RP + 0110 GDT 6117RD/6517RD + 0111 GDT 6127RD/6527RD + 0112 GDT 6537RD + 0113 GDT 6557RD + 0114 GDT 6111RD/6511RD + 0115 GDT 6121RD/6521RD + 0118 GDT 6118RD/6518RD/6618RD + 0119 GDT 6128RD/6528RD/6628RD + 011a GDT 6538RD/6638RD + 011b GDT 6558RD/6658RD + 0120 GDT 6117RP2/6517RP2 + 0121 GDT 6127RP2/6527RP2 + 0122 GDT 6537RP2 + 0123 GDT 6557RP2 + 0124 GDT 6111RP2/6511RP2 + 0125 GDT 6121RP2/6521RP2 + 0136 GDT 6113RS/6513RS + 0137 GDT 6123RS/6523RS + 0138 GDT 6118RS/6518RS/6618RS + 0139 GDT 6128RS/6528RS/6628RS + 013a GDT 6538RS/6638RS + 013b GDT 6558RS/6658RS + 013c GDT 6533RS/6633RS + 013d GDT 6543RS/6643RS + 013e GDT 6553RS/6653RS + 013f GDT 6563RS/6663RS + 0166 GDT 7113RN/7513RN/7613RN + 0167 GDT 7123RN/7523RN/7623RN + 0168 GDT 7118RN/7518RN/7518RN + 0169 GDT 7128RN/7528RN/7628RN + 016a GDT 7538RN/7638RN + 016b GDT 7558RN/7658RN + 016c GDT 7533RN/7633RN + 016d GDT 7543RN/7643RN + 016e GDT 7553RN/7653RN + 016f GDT 7563RN/7663RN + 01d6 GDT 4x13RZ + 01d7 GDT 4x23RZ + 01f6 GDT 8x13RZ + 01f7 GDT 8x23RZ + 01fc GDT 8x33RZ + 01fd GDT 8x43RZ + 01fe GDT 8x53RZ + 01ff GDT 8x63RZ + 0210 GDT 6519RD/6619RD + 0211 GDT 6529RD/6629RD + 0260 GDT 7519RN/7619RN + 0261 GDT 7529RN/7629RN + 02ff GDT MAXRP + 0300 GDT NEWRX + 0301 GDT NEWRX2 +111a Efficient Networks, Inc + 0000 155P-MF1 (FPGA) + 0002 155P-MF1 (ASIC) + 0003 ENI-25P ATM + 111a 0000 ENI-25p Miniport ATM Adapter + 0005 SpeedStream (LANAI) + 111a 0001 ENI-3010 ATM + 111a 0009 ENI-3060 ADSL (VPI=0) + 111a 0101 ENI-3010 ATM + 111a 0109 ENI-3060CO ADSL (VPI=0) + 111a 0809 ENI-3060 ADSL (VPI=0 or 8) + 111a 0909 ENI-3060CO ADSL (VPI=0 or 8) + 111a 0a09 ENI-3060 ADSL (VPI=<0..15>) + 0007 SpeedStream ADSL + 111a 1001 ENI-3061 ADSL [ASIC] + 1020 SpeedStream PCI 10/100 Network Card + 1203 SpeedStream 1023 Wireless PCI Adapter +111b Teledyne Electronic Systems +111c Tricord Systems Inc. + 0001 Powerbis Bridge +# now owned by Microchip Technology +111d Microsemi / PMC / IDT + 0001 IDT77201/77211 155Mbps ATM SAR Controller [NICStAR] + 0003 IDT77222/77252 155Mbps ATM MICRO ABR SAR Controller + 0004 IDT77V252 155Mbps ATM MICRO ABR SAR Controller + 0005 IDT77V222 155Mbps ATM MICRO ABR SAR Controller + 8018 PES12N3A 12-lane 3-Port PCI Express Switch + 801c PES24N3A PCI Express Switch + 8028 PES4T4 PCI Express Switch + 802b PES8T5A PCI Express Switch + 802c PES16T4 PCI Express Switch + 802d PES16T7 PCI Express Switch + 802e PES24T6 PCI Express Switch + 802f PES32T8 PCI Express Switch + 8032 PES48T12 PCI Express Switch + 8034 PES16/22/34H16 PCI Express Switch + 8035 PES32H8 PCI Express Switch + 8036 PES48H12 PCI Express Switch + 8037 PES64H16 PCI Express Switch + 8039 PES3T3 PCI Express Switch + 803a PES4T4 PCI Express Switch + 803c PES5T5 PCI Express Switch + 803d PES6T5 PCI Express Switch + 8048 PES8NT2 PCI Express Switch + 8049 PES8NT2 PCI Express Switch + 804a PES8NT2 PCI Express Internal NTB + 804b PES8NT2 PCI Express External NTB + 804c PES16NT2 PCI Express Switch + 804d PES16NT2 PCI Express Switch + 804e PES16NT2 PCI Express Internal NTB + 804f PES16NT2 PCI Express External NTB + 8058 PES12NT3 PCI Express Switch + 8059 PES12NT3 PCI Express Switch + 805a PES12NT3 PCI Express Internal NTB + 805b PES12NT3 PCI Express External NTB + 805c PES24NT3 PCI Express Switch + 805d PES24NT3 PCI Express Switch + 805e PES24NT3 PCI Express Internal NTB + 805f PES24NT3 PCI Express External NTB + 8060 PES16T4G2 PCI Express Gen2 Switch + 8061 PES12T3G2 PCI Express Gen2 Switch + 8068 PES6T6G2 PCI Express Gen2 Switch + 806a PES24T3G2 PCI Express Gen2 Switch + 14c1 000c 10G-PCIE2-8B2 + 806c PES16T4A/4T4G2 PCI Express Gen2 Switch + 806e PES24T6G2 PCI Express Gen2 Switch + 806f HIO524G2 PCI Express Gen2 Switch + 8077 89HPES64H16G2 64-Lane 16-Port PCIe Gen2 System Interconnect Switch + 8088 PES32NT8BG2 PCI Express Switch + 1093 752f PXIe-8383mc Device + 1093 7543 PXIe-8383mc System Host + 1093 755c PXIe-8364 + 1093 755d PXIe-8374 + 1093 75ff PXIe-8383mc DMA + 1093 7600 PXIe-8383mc DMA + 1093 7602 PXIe-8384 +# 32-lanes 24-ports Gen.2 + 808a 89HPES32NT24BG2 PCI Express Switch +# 32-lanes 24-ports Gen.2 + 808c 89HPES32NT24AG2 PCI Express Switch + 808e PES24NT24G2 PCI Express Switch + 808f 89HPES32NT8AG2 32-Lane 8-Port PCIe Gen2 System Interconnect Switch with Non-Transparent Bridging + 8090 89HPES16NT16G2 16-Lane 16-Port PCIe Gen2 System Interconnect Switch + 8092 89HPES12NT12G2 12-Lane 12-Port PCIe Gen2 System Interconnect Switch + 80cf F32P08xG3 [PCIe boot mode] + 80d2 F32P08xG3 NVMe controller +111e Eldec +111f Precision Digital Images + 4a47 Precision MX Video engine interface + 5243 Frame capture bus interface +# formerly EMC Corporation +1120 Dell EMC + 2306 Unity Fibre Channel Controller + 2501 Unity Ethernet Controller + 2505 Unity Fibre Channel Controller +1121 Zilog +1122 Multi-tech Systems, Inc. +1123 Excellent Design, Inc. +1124 Leutron Vision AG + 2581 Picport Monochrome +1125 Eurocore +1126 Vigra +1127 FORE Systems Inc + 0200 ForeRunner PCA-200 ATM + 0210 PCA-200PC + 0250 ATM + 0300 ForeRunner PCA-200EPC ATM + 0310 ATM + 0400 ForeRunnerHE ATM Adapter + 1127 0400 ForeRunnerHE ATM +1129 Firmworks +112a Hermes Electronics Company, Ltd. +# nee Linotype - Hell AG +112b Heidelberger Druckmaschinen AGHeidelberger Druckmaschinen AG +112c Zenith Data Systems +112d Ravicad +112e Infomedia Microelectronics Inc. +112f Dalsa Inc. + 0000 MVC IC-PCI + 0001 MVC IM-PCI Video frame grabber/processor + 0004 PCDig Digital Image Capture + 0008 PC-CamLink PCI framegrabber +1130 Computervision +1131 Philips Semiconductors + 1561 USB 1.1 Host Controller + 1775 c200 C2K onboard USB 1.1 host controller + 1562 USB 2.0 Host Controller + 1775 c200 C2K onboard USB 2.0 host controller + 3400 SmartPCI56(UCB1500) 56K Modem + 5400 TriMedia TM1000/1100 + 12ca 0000 BlueICE + 5402 TriMedia TM1300 + 1244 0f00 Fritz!Card DSL + 15eb 1300 DT1300 + 15eb 1302 DT1302 + 15eb 1304 DT1304 + 15eb 1305 DT1305 + 15eb 1306 PMCDT1306 + 15eb 1308 DT1308 + 15eb 1331 DT1301 with SAA7121 + 15eb 1337 DT1301 with SAA7127 + 15eb 2d3d X3D + 15eb 7022 PTM1300 + 5405 TriMedia TM1500 + 1136 0005 LCP-1500 + 5406 TriMedia TM1700 + 540b PNX1005 Media Processor + 1131 0020 PNXLite PCI Demo Board + 7130 SAA7130 Video Broadcast Decoder + 0000 4016 Behold TV 401 + 0000 4051 Behold TV 405 FM + 0000 5051 Behold TV 505 RDS + 0000 505b Behold TV 505 RDS + 102b 48d0 Matrox CronosPlus + 1048 226b ELSA EX-VISION 300TV + 107d 6655 WinFast DTV1000S + 1131 0000 SAA7130-based TV tuner card + 1131 2001 10MOONS PCI TV CAPTURE CARD + 1131 2005 Techcom (India) TV Tuner Card (SSD-TV-670) + 1458 9006 GT-PS700 DVB-S tuner + 1461 050c Nagase Sangyo TransGear 3000TV + 1461 10ff AVerMedia DVD EZMaker + 1461 2108 AverMedia AverTV/305 + 1461 2115 AverMedia AverTV Studio 305 + 153b 1152 Terratec Cinergy 200 TV + 185b c100 Compro VideoMate TV PVR/FM + 185b c901 Videomate DVB-T200 + 5168 0138 LifeView FlyVIDEO2000 + 5ace 5010 Behold TV 501 + 5ace 5050 Behold TV 505 FM + 7133 SAA7131/SAA7133/SAA7135 Video Broadcast Decoder + 0000 4091 Beholder BeholdTV 409 FM + 0000 5071 Behold TV 507 RDS + 0000 507b Behold TV 507 RDS + 0000 5201 Behold TV Columbus + 0070 6701 WinTV HVR-1110 + 1019 4cb5 Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) + 1043 0210 FlyTV mini Asus Digimatrix + 1043 4843 TV-FM 7133 + 1043 4845 TV-FM 7135 + 1043 4862 P7131 Dual + 1043 4876 My Cinema-P7131 Hybrid + 1131 0000 SAA713x-based TV tuner card + 1131 2001 Proteus Pro [philips reference design] + 1131 2018 Tiger reference design + 1131 4ee9 MonsterTV Mobile + 1131 7133 Pinnacle PCTV 301i + 11bd 002b PCTV Stereo + 11bd 002e PCTV 110i (saa7133) + 12ab 0800 PURPLE TV + 13c2 2804 Technotrend Budget T-3000 Hybrid + 1421 0335 Instant TV DVB-T Cardbus + 1421 1370 Instant TV (saa7135) + 1435 7330 VFG7330 + 1435 7350 VFG7350 + 1458 9001 GC-PTV-TAF Hybrid TV card + 1458 9002 GT-PTV-TAF-RH DVB-T/Analog TV/FM tuner + 1458 9003 GT-PTV-AF-RH Analog TV/FM tuner + 1458 9004 GT-P8000 DVB-T/Analog TV/FM tuner + 1458 9005 GT-P6000 Analog TV/FM tuner + 1458 9008 GT-P5100 Analog TV tuner + 1461 1044 AVerTVHD MCE A180 + 1461 4836 M10D Hybrid DVBT + 1461 861e M105 PAL/SECAM/NTSC/FM Tuner + 1461 a14b AVerTV Studio 509 + 1461 a836 M115 DVB-T, PAL/SECAM/NTSC Tuner + 1461 f01d DVB-T Super 007 + 1461 f31f Avermedia AVerTV GO 007 FM + 1461 f936 Hybrid+FM PCI (rev A16D) + 1462 6231 TV@nywhere Plus + 1489 0214 LifeView FlyTV Platinum FM + 14c0 1212 LifeView FlyTV Platinum Mini2 + 153b 1160 Cinergy 250 PCI TV + 153b 1162 Terratec Cinergy 400 mobile + 17de 7256 PlusTV All In One PI610 card + 17de 7350 ATSC 110 Digital / Analog HDTV Tuner + 17de 7352 ATSC 115 Digital / Analog HDTV Tuner + 185b c100 VideoMate TV + 185b c900 VideoMate T750 + 5168 0306 LifeView FlyDVB-T DUO + 5168 0319 LifeView FlyDVB Trio + 5168 0502 LifeView FlyDVB-T Duo CardBus + 5168 0520 LifeView FlyDVB Trio CardBus + 5168 1502 LifeView FlyTV CardBus + 5168 2502 LifeView FlyDVB-T CardBus + 5168 2520 LifeView FlyDVB-S Duo CardBus + 5168 3502 LifeView FlyDVB-T Hybrid CardBus + 5168 3520 LifeView FlyDVB Trio N CardBus + 5ace 5030 Behold TV 503 FM + 5ace 5090 Behold TV 509 FM + 5ace 6090 Behold TV 609 FM + 5ace 6091 Behold TV 609 FM + 5ace 6092 Behold TV 609 RDS + 5ace 6093 Behold TV 609 RDS + 5ace 6190 Behold TV M6 + 5ace 6191 Behold TV M63 + 5ace 6193 Behold TV M6 Extra + 5ace 6290 Behold TV H6 + 5ace 7090 Behold TV A7 + 5ace 7150 Behold TV H75 + 5ace 7151 Behold TV H75 + 5ace 7190 Behold TV H7 + 5ace 7191 Behold TV H7 + 5ace 7290 Behold TV T7 + 5ace 7591 Behold TV X7 + 5ace 7595 Behold TV X7 + 7134 SAA7134/SAA7135HL Video Broadcast Decoder + 0000 4036 Behold TV 403 + 0000 4037 Behold TV 403 FM + 0000 4071 Behold TV 407 FM + 1019 4cb4 Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) + 1043 0210 Digimatrix TV + 1043 4840 TV-FM 7134 + 1043 4842 TV-FM 7134 + 1131 0000 SAA713x-based TV tuner card + 1131 2004 EUROPA V3 reference design + 1131 4e85 SKNet Monster TV + 1131 6752 EMPRESS + 11bd 002b PCTV Stereo + 11bd 002d PCTV 300i DVB-T + PAL + 1461 2c00 AverTV Hybrid+FM PCI + 1461 9715 AVerTV Studio 307 + 1461 a70a Avermedia AVerTV 307 + 1461 a70b AverMedia M156 / Medion 2819 + 1461 d6ee Cardbus TV/Radio (E500) + 1471 b7e9 AVerTV Cardbus plus + 153b 1142 Terratec Cinergy 400 TV + 153b 1143 Terratec Cinergy 600 TV + 153b 1158 Terratec Cinergy 600 TV MK3 + 1540 9524 ProVideo PV952 + 16be 0003 Medion 7134 + 185b c200 Compro VideoMate Gold+ Pal + 185b c900 Videomate DVB-T300 + 1894 a006 KNC One TV-Station DVR + 1894 fe01 KNC One TV-Station RDS / Typhoon TV Tuner RDS + 5168 0138 FLY TV PRIME 34FM + 5168 0300 FlyDVB-S + 5ace 5070 Behold TV 507 FM + 5ace 6070 Behold TV 607 FM + 5ace 6071 Behold TV 607 FM + 5ace 6072 Behold TV 607 RDS + 5ace 6073 Behold TV 607 RDS + 7145 SAA7145 + 7146 SAA7146 + 110a 0000 Fujitsu/Siemens DVB-C card rev1.5 + 110a ffff Fujitsu/Siemens DVB-C card rev1.5 + 1124 2581 Leutron Vision PicPort + 1131 4f56 KNC1 DVB-S Budget + 1131 4f60 Fujitsu-Siemens Activy DVB-S Budget Rev AL + 1131 4f61 Activy DVB-S Budget Rev GR + 1131 5f61 Activy DVB-T Budget + 114b 2003 DVRaptor Video Edit/Capture Card + 1159 0040 MuTech M-Vision 500 (MV-500 rev. E) + 1159 0050 MuTech M-Vision 500 (MV-500 rev. F) + 11bd 0006 DV500 Overlay + 11bd 000a DV500 Overlay + 11bd 000f DV500 Overlay + 13c2 0000 Siemens/Technotrend/Hauppauge DVB card rev1.3 or rev1.5 + 13c2 0001 Technotrend/Hauppauge DVB card rev1.3 or rev1.6 + 13c2 0002 Technotrend/Hauppauge DVB card rev2.1 + 13c2 0003 Technotrend/Hauppauge DVB card rev2.1 + 13c2 0004 Technotrend/Hauppauge DVB card rev2.1 + 13c2 0006 Technotrend/Hauppauge DVB card rev1.3 or rev1.6 + 13c2 0008 Technotrend/Hauppauge DVB-T + 13c2 000a Octal/Technotrend DVB-C for iTV + 13c2 000e Technotrend/Hauppauge DVB card rev2.3 + 13c2 1003 Technotrend-Budget/Hauppauge WinTV-NOVA-S DVB card + 13c2 1004 Technotrend-Budget/Hauppauge WinTV-NOVA-C DVB card + 13c2 1005 Technotrend-Budget/Hauppauge WinTV-NOVA-T DVB card + 13c2 100c Technotrend-Budget/Hauppauge WinTV-NOVA-CI DVB card + 13c2 100f Technotrend-Budget/Hauppauge WinTV-NOVA-CI DVB card + 13c2 1010 DVB C-1500 + 13c2 1011 Technotrend-Budget/Hauppauge WinTV-NOVA-T DVB card + 13c2 1012 DVB T-1500 + 13c2 1013 SATELCO Multimedia DVB + 13c2 1016 WinTV-NOVA-SE DVB card + 13c2 1018 DVB S-1401 + 13c2 1019 S2-3200 + 13c2 1102 Technotrend/Hauppauge DVB card rev2.1 + 153b 1155 Cinergy 1200 DVB-S + 153b 1156 Cinergy 1200 DVB-C + 153b 1157 Cinergy 1200 DVB-T + 153b 1176 Cinergy 1200 DVB-C (MK3) + 1894 0020 KNC One DVB-C V1.0 + 1894 0023 TVStation DVB-C plus +# http://www.knc1.com/gb.htm + 1894 0054 TV-Station DVB-S + 7160 SAA7160 + 1458 9009 E8000 DVB-T/Analog TV/FM tuner + 1461 1455 AVerTV Hybrid Speedy PCI-E (H788) + 7162 SAA7162 + 11bd 0101 Pinnacle PCTV 7010iX TV Card + 7164 SAA7164 + 0070 8800 WinTV HVR-2250 + 0070 8810 WinTV HVR-2250 + 0070 8851 WinTV HVR-2250 + 0070 8853 WinTV HVR-2250 + 0070 8880 WinTV HVR-2250 + 0070 8891 WinTV HVR-2250 + 0070 88a0 WinTV HVR-2250 + 0070 88a1 WinTV HVR-2250 + 0070 8900 WinTV HVR-2200 + 0070 8901 WinTV HVR-2200 + 0070 8940 WinTV HVR-2200 (submodel 89619) + 0070 8951 WinTV HVR-2200 + 0070 8953 WinTV HVR-2200 + 0070 8980 WinTV HVR-2200 + 0070 8991 WinTV HVR-2200 + 0070 8993 WinTV HVR-2200 + 0070 89a0 WinTV HVR-2200 + 0070 89a1 WinTV HVR-2200 + 0070 f120 WinTV HVR-2205 + 0070 f123 WinTV HVR-2215 + 7231 SAA7231 + 5ace 8000 Behold TV H8 + 5ace 8001 Behold TV H8 + 5ace 8050 Behold TV H85 + 5ace 8051 Behold TV H85 + 5ace 8100 Behold TV A8 + 5ace 8101 Behold TV A8 + 5ace 8150 Behold TV A85 + 5ace 8151 Behold TV A85 + 5ace 8201 Behold TV T8 + 9730 SAA9730 Integrated Multimedia and Peripheral Controller + 1131 0000 Integrated Multimedia and Peripheral Controller +1132 Mitel Corp. +1133 Dialogic Corporation + 7701 Eiconcard C90 + 7711 Eiconcard C91 + 7901 EiconCard S90 + 7902 EiconCard S90 + 7911 EiconCard S91 + 7912 EiconCard S91 + 7921 Eiconcard S92 + 7941 EiconCard S94 + 7942 EiconCard S94 + 7943 EiconCard S94 + 7944 EiconCard S94 + 7945 Eiconcard S94 + 7948 Eiconcard S94 64bit/66MHz + 9711 Eiconcard S91 V2 + 9911 Eiconcard S91 V2 + 9941 Eiconcard S94 V2 + 9a41 Eiconcard S94 PCIe + b921 EiconCard P92 + b922 EiconCard P92 + b923 EiconCard P92 + e001 Diva Pro 2.0 S/T + e002 Diva 2.0 S/T PCI + e003 Diva Pro 2.0 U + e004 Diva 2.0 U PCI + e005 Diva 2.01 S/T PCI + e006 Diva CT S/T PCI + e007 Diva CT U PCI + e008 Diva CT Lite S/T PCI + e009 Diva CT Lite U PCI + e00a Diva ISDN+V.90 PCI + e00b Diva ISDN PCI 2.02 + e00c Diva 2.02 PCI U + e00d Diva Pro 3.0 PCI + e00e Diva ISDN+CT S/T PCI Rev 2 + e010 Diva Server BRI-2M PCI + 110a 0021 Fujitsu Siemens ISDN S0 + e011 Diva Server BRI S/T Rev 2 + e012 Diva Server 4BRI-8M PCI + e013 4BRI + 1133 1300 Diva V-4BRI-8 PCI v2 + 1133 e013 Diva 4BRI-8 PCI v2 + e014 Diva Server PRI-30M PCI + e015 Diva PRI PCI v2 + e016 Diva Server Voice 4BRI PCI + e017 Diva Server Voice 4BRI Rev 2 + 1133 e017 Diva Server Voice 4BRI-8M 2.0 PCI + e018 BRI + 1133 1800 Diva V-BRI-2 PCI v2 + 1133 e018 Diva BRI-2 PCI v2 + e019 Diva Server Voice PRI Rev 2 + 1133 e019 Diva Server Voice PRI 2.0 PCI + e01a Diva BRI-2FX PCI v2 + e01b Diva Server Voice BRI-2M 2.0 PCI + 1133 e01b Diva Server Voice BRI-2M 2.0 PCI + e01c PRI + 1133 1c01 Diva PRI/E1/T1-8 PCI v3 + 1133 1c02 Diva PRI/T1-24 PCI(e) v3 + 1133 1c03 Diva PRI/E1-30 PCI(e) v3 + 1133 1c04 Diva PRI/E1/T1-CTI PCI(e) v3 + 1133 1c05 Diva V-PRI/T1-24 PCI(e) v3 + 1133 1c06 Diva V-PRI/E1-30 PCI(e) v3 + 1133 1c07 Diva Server PRI/E1/T1-8 Cornet NQ + 1133 1c08 Diva Server PRI/T1-24 Cornet NQ + 1133 1c09 Diva Server PRI/E1-30 Cornet NQ + 1133 1c0a Diva Server PRI/E1/T1 Cornet NQ + 1133 1c0b Diva Server V-PRI/T1-24 Cornet NQ + 1133 1c0c Diva Server V-PRI/E1-30 Cornet NQ + e01e 2PRI + 1133 1e01 Diva 2PRI/E1/T1-60 PCI v1 + 1133 e01e Diva V-2PRI/E1/T1-60 PCI v1 + e020 4PRI + 1133 2001 Diva 4PRI/E1/T1-120 PCI v1 + 1133 e020 Diva V-4PRI/E1/T1-120 PCI v1 + e022 Analog-2 + 1133 2200 Diva V-Analog-2 PCI v1 + 1133 e022 Diva Analog-2 PCI v1 + e024 Analog-4 + 1133 2400 Diva V-Analog-4 PCI v1 + 1133 e024 Diva Analog-4 PCI v1 + e028 Analog-8 + 1133 2800 Diva V-Analog-8 PCI v1 + 1133 e028 Diva Analog-8 PCI v1 + e02a Diva IPM-300 PCI v1 + e02c Diva IPM-600 PCI v1 + e02e 4BRI + 1133 2e01 Diva V-4BRI-8 PCIe v2 + 1133 e02e Diva 4BRI-8 PCIe v2 + e032 BRI + 1133 3201 Diva V-BRI-2 PCIe v2 + 1133 e032 Diva BRI-2 PCIe v2 + e034 Diva BRI-CTI PCI v2 +1134 Mercury Computer Systems + 0001 Raceway Bridge + 0002 Dual PCI to RapidIO Bridge + 000b POET Serial RapidIO Bridge + 000d POET PSDMS Device +1135 Fuji Xerox Co Ltd + 0001 Printer controller +1136 Momentum Data Systems + 0002 PCI-JTAG +1137 Cisco Systems Inc + 0023 VIC 81 PCIe Upstream Port + 0040 VIC PCIe Upstream Port + 1137 004f VIC 1280 Dual 40Gb Mezzanine + 1137 0084 VIC 1240 Dual 40Gb MLOM + 1137 0085 VIC 1225 Dual 10Gb SFP+ PCIe + 1137 00cd VIC 1285 Dual 40Gb QSFP+ PCIe + 1137 00ce VIC 1225T Dual 10GBaseT PCIe + 1137 012a VIC M4308 Dual 40Gb + 1137 012c VIC 1340 Dual 40Gb MLOM + 1137 012e VIC 1227 Dual 10Gb SFP+ PCIe + 1137 0137 VIC 1380 Dual 40Gb Mezzanine + 1137 014d VIC 1385 Dual 40Gb PCIe + 0041 VIC PCIe Downstream Port + 0042 VIC Management Controller + 1137 0047 VIC P81E PCIe Management Controller + 1137 0085 VIC 1225 PCIe Management Controller + 1137 00cd VIC 1285 PCIe Management Controller + 1137 00ce VIC 1225T PCIe Management Controller + 1137 012e VIC 1227 PCIe Management Controller + 1137 014d VIC 1385 PCIe Management Controller + 0043 VIC Ethernet NIC + 1137 0047 VIC P81E PCIe Ethernet NIC + 1137 0048 VIC M81KR Mezzanine Ethernet NIC + 1137 004f VIC 1280 Mezzanine Ethernet NIC + 1137 0084 VIC 1240 MLOM Ethernet NIC + 1137 0085 VIC 1225 PCIe Ethernet NIC + 1137 00cd VIC 1285 PCIe Ethernet NIC + 1137 00ce VIC 1225T PCIe Ethernet NIC + 1137 012a VIC M4308 Ethernet NIC + 1137 012c VIC 1340 MLOM Ethernet NIC + 1137 012e VIC 1227 PCIe Ethernet NIC + 1137 0137 VIC 1380 Mezzanine Ethernet NIC + 1137 014d VIC 1385 PCIe Ethernet NIC + 1137 015d VIC 1387 MLOM Ethernet NIC + 1137 0215 VIC 1440 Mezzanine Ethernet NIC + 1137 0216 VIC 1480 MLOM Ethernet NIC + 1137 0217 VIC 1455 PCIe Ethernet NIC + 1137 0218 VIC 1457 MLOM Ethernet NIC + 1137 0219 VIC 1485 PCIe Ethernet NIC + 1137 021a VIC 1487 MLOM Ethernet NIC + 1137 024a VIC 1495 PCIe Ethernet NIC + 1137 024b VIC 1497 MLOM Ethernet NIC + 0044 VIC Ethernet NIC Dynamic + 1137 0047 VIC P81E PCIe Ethernet NIC Dynamic + 1137 0048 VIC M81KR Mezzanine Ethernet NIC Dynamic + 1137 004f VIC 1280 Mezzanine Ethernet NIC Dynamic + 1137 0084 VIC 1240 MLOM Ethernet NIC Dynamic + 1137 0085 VIC 1225 PCIe Ethernet NIC Dynamic + 1137 00cd VIC 1285 PCIe Ethernet NIC Dynamic + 1137 00ce VIC 1225T PCIe Ethernet NIC Dynamic + 1137 012a VIC M4308 Ethernet NIC Dynamic + 1137 012c VIC 1340 MLOM Ethernet NIC Dynamic + 1137 012e VIC 1227 PCIe Ethernet NIC Dynamic + 1137 0137 VIC 1380 Mezzanine Ethernet NIC Dynamic + 1137 014d VIC 1385 PCIe Ethernet NIC Dynamic + 0045 VIC FCoE HBA + 1137 0047 VIC P81E PCIe FCoE HBA + 1137 0048 VIC M81KR Mezzanine FCoE HBA + 1137 004f VIC 1280 Mezzanine FCoE HBA + 1137 0084 VIC 1240 MLOM FCoE HBA + 1137 0085 VIC 1225 PCIe FCoE HBA + 1137 00cd VIC 1285 PCIe FCoE HBA + 1137 00ce VIC 1225T PCIe FCoE HBA + 1137 012a VIC M4308 FCoE HBA + 1137 012c VIC 1340 MLOM FCoE HBA + 1137 012e VIC 1227 PCIe FCoE HBA + 1137 0137 VIC 1380 Mezzanine FCoE HBA + 1137 014d VIC 1385 PCIe FCoE HBA + 0046 VIC SCSI Controller + 1137 012a VIC M4308 SCSI Controller + 004e VIC 82 PCIe Upstream Port + 0071 VIC SR-IOV VF + 007a VIC 1300 PCIe Upstream Port + 1137 012a VIC M4308 Dual 40Gb + 1137 012c VIC 1340 Dual 40Gb MLOM + 1137 0137 VIC 1380 Dual 40Gb Mezzanine + 1137 014d VIC 1385 Dual 40Gb PCIe + 00cf VIC Userspace NIC + 1137 004f VIC 1280 Mezzanine Userspace NIC + 1137 0084 VIC 1240 MLOM Userspace NIC + 1137 0085 VIC 1225 PCIe Userspace NIC + 1137 00cd VIC 1285 PCIe Userspace NIC + 1137 00ce VIC 1225T PCIe Userspace NIC + 1137 012a VIC M4308 Userspace NIC + 1137 012c VIC 1340 MLOM Userspace NIC + 1137 012e VIC 1227 PCIe Userspace NIC + 1137 0137 VIC 1380 Mezzanine Userspace NIC + 023e 1GigE I350 LOM +1138 Ziatech Corporation + 8905 8905 [STD 32 Bridge] +1139 Dynamic Pictures, Inc + 0001 VGA Compatible 3D Graphics +113a FWB Inc +113b Network Computing Devices +113c Cyclone Microsystems, Inc. + 0000 PCI-9060 i960 Bridge + 0001 PCI-SDK [PCI i960 Evaluation Platform] + 0911 PCI-911 [i960Jx-based Intelligent I/O Controller] + 0912 PCI-912 [i960CF-based Intelligent I/O Controller] + 0913 PCI-913 + 0914 PCI-914 [I/O Controller w/ secondary PCI bus] +113d Leading Edge Products Inc +113e Sanyo Electric Co - Computer Engineering Dept +113f Equinox Systems, Inc. + 0808 SST-64P Adapter + 1010 SST-128P Adapter + 80c0 SST-16P DB Adapter + 80c4 SST-16P RJ Adapter + 80c8 SST-16P Adapter + 8888 SST-4P Adapter + 9090 SST-8P Adapter +1140 Intervoice Inc +1141 Crest Microsystem Inc +1142 Alliance Semiconductor Corporation + 3210 AP6410 + 6422 ProVideo 6422 + 6424 ProVideo 6424 + 6425 ProMotion AT25 + 643d ProMotion AT3D +1143 NetPower, Inc +1144 Cincinnati Milacron + 0001 Noservo controller +1145 Workbit Corporation + 8007 NinjaSCSI-32 Workbit + f007 NinjaSCSI-32 KME + f010 NinjaSCSI-32 Workbit + f012 NinjaSCSI-32 Logitec + f013 NinjaSCSI-32 Logitec + f015 NinjaSCSI-32 Melco + f020 NinjaSCSI-32 Sony PCGA-DVD51 + f021 NinjaPATA-32 Delkin Cardbus UDMA + f024 NinjaPATA-32 Delkin Cardbus UDMA + f103 NinjaPATA-32 Delkin Cardbus UDMA +1146 Force Computers +1147 Interface Corp +# Nee Schneider & Koch +1148 SysKonnect + 4000 FDDI Adapter + 0e11 b03b Netelligent 100 FDDI DAS Fibre SC + 0e11 b03c Netelligent 100 FDDI SAS Fibre SC + 0e11 b03d Netelligent 100 FDDI DAS UTP + 0e11 b03e Netelligent 100 FDDI SAS UTP + 0e11 b03f Netelligent 100 FDDI SAS Fibre MIC + 1148 5521 FDDI SK-5521 (SK-NET FDDI-UP) + 1148 5522 FDDI SK-5522 (SK-NET FDDI-UP DAS) + 1148 5541 FDDI SK-5541 (SK-NET FDDI-FP) + 1148 5543 FDDI SK-5543 (SK-NET FDDI-LP) + 1148 5544 FDDI SK-5544 (SK-NET FDDI-LP DAS) + 1148 5821 FDDI SK-5821 (SK-NET FDDI-UP64) + 1148 5822 FDDI SK-5822 (SK-NET FDDI-UP64 DAS) + 1148 5841 FDDI SK-5841 (SK-NET FDDI-FP64) + 1148 5843 FDDI SK-5843 (SK-NET FDDI-LP64) + 1148 5844 FDDI SK-5844 (SK-NET FDDI-LP64 DAS) + 4200 Token Ring adapter + 4300 SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) + 1148 9821 SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) + 1148 9822 SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) + 1148 9841 SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) + 1148 9842 SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) + 1148 9843 SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) + 1148 9844 SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) + 1148 9861 SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) + 1148 9862 SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) + 1148 9871 SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) + 1148 9872 SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) + 1259 2970 AT-2970SX Gigabit Ethernet Adapter + 1259 2971 AT-2970LX Gigabit Ethernet Adapter + 1259 2972 AT-2970TX Gigabit Ethernet Adapter + 1259 2973 AT-2971SX Gigabit Ethernet Adapter + 1259 2974 AT-2971T Gigabit Ethernet Adapter + 1259 2975 AT-2970SX/2SC Gigabit Ethernet Adapter + 1259 2976 AT-2970LX/2SC Gigabit Ethernet Adapter + 1259 2977 AT-2970TX/2TX Gigabit Ethernet Adapter + 4320 SK-98xx V2.0 Gigabit Ethernet Adapter [Marvell 88E8001] + 1148 0121 Marvell RDK-8001 Adapter + 1148 0221 Marvell RDK-8002 Adapter + 1148 0321 Marvell RDK-8003 Adapter + 1148 0421 Marvell RDK-8004 Adapter + 1148 0621 Marvell RDK-8006 Adapter + 1148 0721 Marvell RDK-8007 Adapter + 1148 0821 Marvell RDK-8008 Adapter + 1148 0921 Marvell RDK-8009 Adapter + 1148 1121 Marvell RDK-8011 Adapter + 1148 1221 Marvell RDK-8012 Adapter + 1148 3221 SK-9521 V2.0 10/100/1000Base-T Adapter + 1148 5021 SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter + 1148 5041 SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter + 1148 5043 SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter + 1148 5051 SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter + 1148 5061 SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter + 1148 5071 SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter + 1148 9521 SK-9521 10/100/1000Base-T Adapter + 1259 2916 AT-2916T + 4400 SK-9Dxx Gigabit Ethernet Adapter + 4500 SK-9Mxx Gigabit Ethernet Adapter + 9000 SK-9Sxx Gigabit Ethernet Server Adapter PCI-X [Marvell 88E8022] + 1148 2100 SK-9S21 10/100/1000Base-T Server Adapter, PCI-X, Copper RJ-45 + 1148 2200 SK-9S22 10/100/1000Base-T Dual Port Server Adapter, PCI-X, 2 Copper RJ-45 + 1148 2210 SK-9P22 10/100/1000 Base-T Dual Port PMC card + 1148 2220 TPMC-GBE-CO + 1148 8100 SK-9S81 1000Base-SX Server Adapter,PCI-X, Fiber SX/LC + 1148 8200 SK-9S82 1000Base-SX Dual Port Server Adapter, PCI-X, 2 Fiber SX/LC + 1148 8210 SK-9P82 1000 Base-SX Dual Port PMC card + 1148 8220 TPMC-GBE-FI + 1148 9100 SK-9S91 1000Base-LX Server Adapter,PCI-X, Fiber LX/LC + 1148 9200 SK-9S92 1000Base-LX Dual Port Server Adapter, PCI-X, 2 Fiber LX/LC + 1259 2973 AT-2971SX v2 Gigabit Adapter + 1259 2974 AT-2971T v2 Gigabit Adapter + 1259 2978 AT-2971LX Gigabit Adapter + 9843 [Fujitsu] Gigabit Ethernet + 9e00 SK-9E21D 10/100/1000Base-T Adapter, Copper RJ-45 + 1148 2100 SK-9E21 Server Adapter + 1148 21d0 SK-9E21D 10/100/1000Base-T Adapter + 1148 2200 SK-9E22 Server Adapter + 1148 8100 SK-9E81 Server Adapter + 1148 8200 SK-9E82 Server Adapter + 1148 9100 SK-9E91 Server Adapter + 1148 9200 SK-9E92 Server Adapter + 9e01 SK-9E21M 10/100/1000Base-T Adapter +1149 Win System Corporation +114a VMIC + 5565 GE-IP PCI5565,PMC5565 Reflective Memory Node + 5579 VMIPCI-5579 (Reflective Memory Card) + 5587 VMIPCI-5587 (Reflective Memory Card) + 6504 VMIC PCI 7755 FPGA + 7587 VMIVME-7587 +114b Canopus Co., Ltd +114c Annabooks +114d IC Corporation +114e Nikon Systems Inc +114f Digi International + 0002 AccelePort EPC + 0003 RightSwitch SE-6 + 0004 AccelePort Xem + 0005 AccelePort Xr + 0006 AccelePort Xr,C/X + 0009 AccelePort Xr/J + 000a AccelePort EPC/J + 000c DataFirePRIme T1 (1-port) + 000d SyncPort 2-Port (x.25/FR) + 0011 AccelePort 8r EIA-232 (IBM) + 0012 AccelePort 8r EIA-422 + 0013 AccelePort Xr + 0014 AccelePort 8r EIA-422 + 0015 AccelePort Xem + 0016 AccelePort EPC/X + 0017 AccelePort C/X + 001a DataFirePRIme E1 (1-port) + 001b AccelePort C/X (IBM) + 001c AccelePort Xr (SAIP) + 001d DataFire RAS T1/E1/PRI + 114f 0050 DataFire RAS E1 Adapter + 114f 0051 DataFire RAS Dual E1 Adapter + 114f 0052 DataFire RAS T1 Adapter + 114f 0053 DataFire RAS Dual T1 Adapter + 0023 AccelePort RAS + 0024 DataFire RAS B4 ST/U + 114f 0030 DataFire RAS BRI U Adapter + 114f 0031 DataFire RAS BRI S/T Adapter + 0026 AccelePort 4r 920 + 0027 AccelePort Xr 920 + 0028 ClassicBoard 4 + 0029 ClassicBoard 8 + 0034 AccelePort 2r 920 + 0035 DataFire DSP T1/E1/PRI cPCI + 0040 AccelePort Xp + 114f 0042 AccelePort 2p PCI + 114f 0043 AccelePort 4p PCI + 114f 0044 AccelePort 8p PCI + 114f 0045 AccelePort 16p PCI + 114f 004e AccelePort 32p PCI + 0042 AccelePort 2p + 0043 AccelePort 4p + 0044 AccelePort 8p + 0045 AccelePort 16p + 004e AccelePort 32p + 0070 Datafire Micro V IOM2 (Europe) + 0071 Datafire Micro V (Europe) + 0072 Datafire Micro V IOM2 (North America) + 0073 Datafire Micro V (North America) + 00b0 Digi Neo 4 + 00b1 Digi Neo 8 + 00c8 Digi Neo 2 DB9 + 00c9 Digi Neo 2 DB9 PRI + 00ca Digi Neo 2 RJ45 + 00cb Digi Neo 2 RJ45 PRI + 00cc Digi Neo 1 422 + 00cd Digi Neo 1 422 485 + 00ce Digi Neo 2 422 485 + 00d0 ClassicBoard 4 422 + 00d1 ClassicBoard 8 422 + 00f1 Digi Neo PCI-E 4 port + 00f4 Digi Neo 4 (IBM version) + 6001 Avanstar +1150 Thinking Machines Corp +1151 JAE Electronics Inc. +1152 Megatek +1153 Land Win Electronic Corp +1154 Melco Inc +1155 Pine Technology Ltd +1156 Periscope Engineering +1157 Avsys Corporation +1158 Voarx R & D Inc + 3011 Tokenet/vg 1001/10m anylan + 9050 Lanfleet/Truevalue + 9051 Lanfleet/Truevalue +1159 MuTech Corporation + 0001 MV-1000 + 0002 MV-1500 +115a Harlequin Ltd +115b Parallax Graphics +115c Photron Ltd. +115d Xircom + 0003 Cardbus Ethernet 10/100 + 1014 0181 10/100 EtherJet Cardbus Adapter + 1014 1181 10/100 EtherJet Cardbus Adapter + 1014 8181 10/100 EtherJet Cardbus Adapter + 1014 9181 10/100 EtherJet Cardbus Adapter + 115d 0181 Cardbus Ethernet 10/100 + 115d 0182 RealPort2 CardBus Ethernet 10/100 (R2BE-100) + 115d 1181 Cardbus Ethernet 10/100 + 1179 0181 Cardbus Ethernet 10/100 + 8086 8181 EtherExpress PRO/100 Mobile CardBus 32 Adapter + 8086 9181 EtherExpress PRO/100 Mobile CardBus 32 Adapter + 0005 Cardbus Ethernet 10/100 + 1014 0182 10/100 EtherJet Cardbus Adapter + 1014 1182 10/100 EtherJet Cardbus Adapter + 115d 0182 Cardbus Ethernet 10/100 + 115d 1182 Cardbus Ethernet 10/100 + 0007 Cardbus Ethernet 10/100 + 1014 0182 10/100 EtherJet Cardbus Adapter + 1014 1182 10/100 EtherJet Cardbus Adapter + 115d 0182 Cardbus Ethernet 10/100 + 115d 1182 Cardbus Ethernet 10/100 + 000b Cardbus Ethernet 10/100 + 1014 0183 10/100 EtherJet Cardbus Adapter + 115d 0183 Cardbus Ethernet 10/100 + 000c Mini-PCI V.90 56k Modem + 000f Cardbus Ethernet 10/100 + 1014 0183 10/100 EtherJet Cardbus Adapter + 115d 0183 Cardbus Ethernet 10/100 + 00d4 Mini-PCI K56Flex Modem + 0101 Cardbus 56k modem + 115d 1081 Cardbus 56k Modem + 0103 Cardbus Ethernet + 56k Modem + 1014 9181 Cardbus 56k Modem + 1115 1181 Cardbus Ethernet 100 + 56k Modem + 115d 1181 CBEM56G-100 Ethernet + 56k Modem + 8086 9181 PRO/100 LAN + Modem56 CardBus +115e Peer Protocols Inc +115f Maxtor Corporation +1160 Megasoft Inc +1161 PFU Limited +1162 OA Laboratory Co Ltd +1163 Rendition + 0001 Verite 1000 + 2000 Verite V2000/V2100/V2200 + 1092 2000 Stealth II S220 +1164 Advanced Peripherals Technologies +1165 Imagraph Corporation + 0001 Motion TPEG Recorder/Player with audio +# nee ServerWorks +1166 Broadcom + 0000 CMIC-LE + 0005 CNB20-LE Host Bridge + 0006 CNB20HE Host Bridge + 0007 CNB20-LE Host Bridge + 0008 CNB20HE Host Bridge + 0009 CNB20LE Host Bridge + 0010 CIOB30 + 0011 CMIC-HE + 0012 CMIC-WS Host Bridge (GC-LE chipset) + 0013 CNB20-HE Host Bridge + 0014 CMIC-LE Host Bridge (GC-LE chipset) + 0015 CMIC-GC Host Bridge + 0016 CMIC-GC Host Bridge + 0017 GCNB-LE Host Bridge + 0031 HT1100 HPX0 HT Host Bridge + 0036 BCM5785 [HT1000] PCI/PCI-X Bridge + 0101 CIOB-X2 PCI-X I/O Bridge + 0103 EPB PCI-Express to PCI-X Bridge + 0104 BCM5785 [HT1000] PCI/PCI-X Bridge + 0110 CIOB-E I/O Bridge with Gigabit Ethernet + 0130 BCM5780 [HT2000] PCI-X bridge + 0132 BCM5780 [HT2000] PCI-Express Bridge + 1166 0132 HT2000 PCI-Express bridge + 0140 HT2100 PCI-Express Bridge + 0141 HT2100 PCI-Express Bridge + 0142 HT2100 PCI-Express Bridge + 0144 HT2100 PCI-Express Bridge + 0200 OSB4 South Bridge + 0201 CSB5 South Bridge + 4c53 1080 CT8 mainboard + 0203 CSB6 South Bridge + 1734 1012 PRIMERGY RX/TX series + 0205 BCM5785 [HT1000] Legacy South Bridge + 0211 OSB4 IDE Controller + 0212 CSB5 IDE Controller + 1028 014a PowerEdge 1750 + 1028 810b PowerEdge 1650/2550 + 4c53 1080 CT8 mainboard + 0213 CSB6 RAID/IDE Controller + 1028 4134 PowerEdge 600SC + 1028 c134 Poweredge SC600 + 1734 1012 PRIMERGY RX/TX series onboard IDE + 0214 BCM5785 [HT1000] IDE + 1028 0205 PowerEdge 2970 HT1000 IDE + 0217 CSB6 IDE Controller + 1028 4134 Poweredge SC600 + 021b HT1100 HD Audio + 0220 OSB4/CSB5 OHCI USB Controller + 4c53 1080 CT8 mainboard + 0221 CSB6 OHCI USB Controller + 1734 1012 PRIMERGY RX/TX series onboard OHCI + 0223 BCM5785 [HT1000] USB + 1028 0205 PowerEdge 2970 HT1000 USB Controller + 1028 020b PowerEdge T605 HT1000 USB Controller + 0225 CSB5 LPC bridge + 0227 GCLE-2 Host Bridge + 1734 1012 PRIMERGY RX/TX series + 0230 CSB5 LPC bridge + 4c53 1080 CT8 mainboard + 0234 BCM5785 [HT1000] LPC + 1028 0205 PowerEdge 2970 HT1000 LPC + 1028 020b PowerEdge T605 HT1000 LPC + 0235 BCM5785 [HT1000] XIOAPIC0-2 + 0238 BCM5785 [HT1000] WDTimer + 0240 K2 SATA + 0241 RAIDCore RC4000 + 0242 RAIDCore BC4000 + 024a BCM5785 [HT1000] SATA (Native SATA Mode) + 1028 020b PowerEdge T605 onboard SATA Controller +# The device starts as 024A, and changes to 024B if set to PATA mode in BIOS + 024b BCM5785 [HT1000] SATA (PATA/IDE Mode) + 1028 0205 PowerEdge 2970 HT1000 SATA controller + 0406 HT1100 PCI-X Bridge + 0408 HT1100 Legacy Device + 040a HT1100 ISA-LPC Bridge + 1028 0223 PowerEdge R905 HT1100 ISA-LPC Bridge + 0410 HT1100 SATA Controller (Native SATA Mode) + 0411 HT1100 SATA Controller (PATA / IDE Mode) + 0412 HT1100 USB OHCI Controller + 0414 HT1100 USB EHCI Controller + 0416 HT1100 USB EHCI Controller (with Debug Port) + 0420 HT1100 PCI-Express Bridge + 0421 HT1100 SAS/SATA Controller + 0422 HT1100 PCI-Express Bridge +1167 Mutoh Industries Inc +1168 Thine Electronics Inc +1169 Centre for Development of Advanced Computing +# nee Polaris Communications +116a Luminex Software, Inc. + 6100 Bus/Tag Channel + 6800 Escon Channel + 7100 Bus/Tag Channel + 7800 Escon Channel +116b Connectware Inc +116c Intelligent Resources Integrated Systems +116d Martin-Marietta +116e Electronics for Imaging +116f Workstation Technology +1170 Inventec Corporation +1171 Loughborough Sound Images Plc +1172 Altera Corporation + 00a7 Stratix V + 0530 Stratix IV +1173 Adobe Systems, Inc +1174 Bridgeport Machines +1175 Mitron Computer Inc. +1176 SBE Incorporated +1177 Silicon Engineering +1178 Alfa, Inc. + afa1 Fast Ethernet Adapter +1179 Toshiba Corporation + 0102 Extended IDE Controller + 0103 EX-IDE Type-B + 010f NVMe Controller + 0110 NVMe SSD Controller Cx5 + 1028 1ffb Express Flash NVMe 960G (RI) U.2 (CD5) + 1028 1ffc Express Flash NVMe 1.92T (RI) U.2 (CD5) + 1028 1ffd Express Flash NVMe 3.84T (RI) U.2 (CD5) + 1028 1ffe Express Flash NVMe 7.68T (RI) U.2 (CD5) + 1179 0001 KIOXIA CM5-R series SSD + 1179 0021 KIOXIA CD5 series SSD + 1d49 4039 Thinksystem U.2 CM5 NVMe SSD + 1d49 403a Thinksystem AIC CM5 NVMe SSD + 0113 BG3 NVMe SSD Controller + 0115 XG4 NVMe SSD Controller + 0404 DVD Decoder card + 0406 Tecra Video Capture device + 0407 DVD Decoder card (Version 2) + 0601 CPU to PCI bridge + 1179 0001 Satellite Pro + 0602 PCI to ISA bridge + 0603 ToPIC95 PCI to CardBus Bridge for Notebooks + 0604 PCI-Docking Host bridge + 060a ToPIC95 + 1179 0001 Satellite Pro + 060f ToPIC97 + 1179 0001 Satellite 4010 + 0617 ToPIC100 PCI to Cardbus Bridge with ZV Support + 0618 CPU to PCI and PCI to ISA bridge + 0701 FIR Port Type-O + 0803 TC6371AF SD Host Controller + 0804 TC6371AF SmartMedia Controller + 0805 SD TypA Controller + 0d01 FIR Port Type-DO + 1179 0001 FIR Port Type-DO +117a A-Trend Technology +117b L G Electronics, Inc. +117c ATTO Technology, Inc. + 002c ExpressSAS R380 + 002d ExpressSAS R348 + 0030 Ultra320 SCSI Host Adapter + 117c 8013 ExpressPCI UL4D + 117c 8014 ExpressPCI UL4S + 117c 8027 ExpressPCI UL5D + 117c 802f ExpressPCI UL5D Low Profile + 0033 SAS Adapter + 0041 ExpressSAS R30F + 0042 ExpressSAS 6Gb/s SAS/SATA HBA + 117c 0042 ExpressSAS H680 + 117c 0043 ExpressSAS H608 + 117c 0044 ExpressSAS H60F + 117c 0045 ExpressSAS H6F0 + 117c 0046 ExpressSAS H644 + 117c 004f ExpressSAS M608 + 117c 0057 ExpressSAS M680 + 117c 0058 ExpressSAS M644 + 117c 0059 ExpressSAS W608 + 117c 005a ExpressSAS W680 + 117c 005b ExpressSAS W644 + 0049 ExpressSAS 6Gb SAS/SATA RAID Adapter + 117c 0049 ExpressSAS R680 + 117c 004a ExpressSAS R608 + 117c 004b ExpressSAS R60F + 117c 004c ExpressSAS R6F0 + 117c 004d ExpressSAS R644 + 117c 004e ExpressSAS R648 + 0064 Celerity FC 16Gb/s Gen 5 Fibre Channel HBA + 117c 0063 Celerity FC-161E + 117c 0064 Celerity FC-162E + 117c 0065 Celerity FC-164E + 0094 Celerity FC 16/32Gb/s Gen 6 Fibre Channel HBA + 117c 0094 Celerity FC-162P + 117c 00a0 Celerity FC-161P + 117c 00a1 Celerity FC-164P + 117c 00a2 Celerity FC-321E + 117c 00a3 Celerity FC-322E + 117c 00ac Celerity FC-324E + 8013 ExpressPCI UL4D + 8014 ExpressPCI UL4S + 8027 ExpressPCI UL5D + 8070 ExpressSAS 12Gb/s SAS/SATA HBA + 117c 0070 ExpressSAS H1280 + 117c 0071 ExpressSAS H1208 + 117c 0080 ExpressSAS H1244 + 8072 ExpressSAS 12Gb/s SAS/SATA HBA + 117c 0072 ExpressSAS H12F0 + 117c 0073 ExpressSAS H120F + 117c 0082 ExpressSAS H1288 +117d Becton & Dickinson +117e T/R Systems +117f Integrated Circuit Systems +1180 Ricoh Co Ltd + 0465 RL5c465 + 0466 RL5c466 + 0475 RL5c475 + 144d c006 vpr Matrix 170B4 CardBus bridge + 0476 RL5c476 II + 1014 0185 ThinkPad A/T/X Series + 1014 0555 ThinkPad X41 + 1014 056c ThinkPad Z60t + 1028 014f Latitude X300 laptop + 1028 0188 Inspiron 6000 laptop + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 1043 1017 X58LE + 1043 1237 A6J-Q008 + 1043 1967 V6800V + 1043 1987 A4K and Z81K notebooks, possibly others ( mid-2005 machines ) + 104d 80df Vaio PCG-FX403 + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 104d 814e VAIO GRZ390Z + 10f7 8338 Panasonic CF-Y5 laptop + 144d c005 X10 Laptop + 144d c00c P30/P35 notebook + 14ef 0220 PCD-RP-220S + 17aa 201c ThinkPad X60/X60s + 17aa 20c4 ThinkPad T61/R61 + 17aa 20c6 ThinkPad R61/T400 + 0477 RL5c477 + 0478 RL5c478 + 1014 0184 ThinkPad A30p + 0511 R5C511 + 0522 R5C522 IEEE 1394 Controller + 1014 01cf ThinkPad A30p + 1043 1967 V6800V + 0551 R5C551 IEEE 1394 Controller + 144d c006 vpr Matrix 170B4 + 0552 R5C552 IEEE 1394 Controller + 1014 0511 ThinkPad A/T/X Series + 1028 014f Latitude X300 laptop + 1028 0188 Inspiron 6000 laptop + 1043 1237 A6J-Q008 + 1043 1757 M2400N laptop + 144d c005 X10 Laptop + 144d c00c P30/P35 notebook + 17aa 201e ThinkPad X60/X60s + 0554 R5C554 + 0575 R5C575 SD Bus Host Adapter + 0576 R5C576 SD Bus Host Adapter + 0592 R5C592 Memory Stick Bus Host Adapter + 1025 0121 Aspire 5920G + 1028 01d7 XPS M1210 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 1521 HP EliteBook 8540w + 103c 30b5 Presario V3242AU + 103c 30b7 Presario V6133CL + 103c 30cc Pavilion dv6700 + 103c 30cf Pavilion dv95xx/96xx/97xx/98xx series + 1043 1017 X58LE + 1043 1237 A6J-Q008 + 1043 1967 V6800V + 104d 9035 VAIO VGN-FW11ZRU + 144d c018 X20 IV + 17aa 20ca ThinkPad T61/T400 + 0811 R5C811 + 0822 R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter + 1014 0556 ThinkPad X40 / X41 / X60s / Z60t + 1014 0598 ThinkPad Z60m + 1025 0121 Aspire 5920G + 1028 0188 Inspiron 6000 laptop + 1028 01a2 Inspiron 9200 + 1028 01d7 XPS M1210 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 03b5 Presario V3242AU + 103c 30b7 Presario V6133CL + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 103c 30cf Pavilion dv9668eg Laptop + 1043 1017 X58LE + 1043 1237 A6J-Q008 + 1043 1967 V6800V + 10f7 8338 Panasonic CF-Y5 laptop + 144d c018 X20 IV + 17aa 201d ThinkPad X60/X60s + 17aa 20c7 ThinkPad T61 + 17aa 20c8 ThinkPad T400/W500 + 0832 R5C832 IEEE 1394 Controller + 1025 0121 Aspire 5920G + 1028 01d7 XPS M1210 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 1028 024d Latitude E4300 + 103c 30b5 Presario V3242AU + 103c 30b7 Presario V6133CL + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 103c 30cf Pavilion dv9668eg Laptop + 17aa 20c5 ThinkPad R61 + 17aa 20c7 ThinkPad R61 + 0841 R5C841 CardBus/SD/SDIO/MMC/MS/MSPro/xD/IEEE1394 + 0843 R5C843 MMC Host Controller + 1025 0121 Aspire 5920G + 1028 01d7 XPS M1210 + 1028 01f3 Inspiron 1420 + 1028 01f5 Inspiron 1501 + 1028 024f Latitude e6500 + 103c 03b5 Presario V3242AU + 103c 1521 HP EliteBook 8540w + 103c 30b7 Presario V6133CL + 103c 30cf Pavilion dv9500/9600/9700 series + 1043 1017 X58LE + 1183 0843 Alienware Aurora m9700 + 0852 xD-Picture Card Controller + 1025 0121 Aspire 5920G + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30b5 Presario V3242AU + 103c 30b7 Presario V6133CL + 103c 30cc Pavilion dv6700 + 103c 30cf Pavilion dv9668eg Laptop + 1043 1967 V6800V + 1180 0852 Pavilion 2410us + 1324 10cf P7120 + 17aa 20cb ThinkPad T400 + e230 R5U2xx (R5U230 / R5U231 / R5U241) [Memory Stick Host Controller] + e476 CardBus bridge + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + e822 MMC/SD Host Controller + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 17aa 21cf ThinkPad T520 + e823 PCIe SDXC/MMC Host Controller + 17aa 21cf ThinkPad T520 + e832 R5C832 PCIe IEEE 1394 Controller + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 17aa 21cf ThinkPad T520 + e852 PCIe xD-Picture Card Controller +1181 Telmatics International +1183 Fujikura Ltd +1184 Forks Inc +1185 Dataworld International Ltd +1186 D-Link System Inc + 1002 DL10050 Sundance Ethernet + 1186 1002 DFE-550TX/FX + 1186 1012 DFE-580TX + 1025 AirPlus Xtreme G DWL-G650 Adapter + 1026 AirXpert DWL-AG650 Wireless Cardbus Adapter + 1043 AirXpert DWL-AG650 Wireless Cardbus Adapter + 1300 RTL8139 Ethernet + 1186 1300 DFE-538TX 10/100 Ethernet Adapter + 1186 1301 DFE-530TX+ 10/100 Ethernet Adapter + 1186 1303 DFE-528TX 10/100 Fast Ethernet PCI Adapter + 1340 DFE-690TXD CardBus PC Card + 1540 DFE-680TX + 1541 DFE-680TXD CardBus PC Card + 1561 DRP-32TXD Cardbus PC Card + 3300 DWL-510 / DWL-610 802.11b [Realtek RTL8180L] + 1186 3300 DWL-610 Wireless Cardbus Adapter + 1186 3301 DWL-510 Wireless PCI Adapter + 3a10 AirXpert DWL-AG650 Wireless Cardbus Adapter(rev.B) + 3a11 AirXpert DWL-AG520 Wireless PCI Adapter(rev.B) + 4000 DL2000-based Gigabit Ethernet + 4001 DGE-550SX PCI-X Gigabit Ethernet Adapter + 4200 DFE-520TX Fast Ethernet PCI Adapter + 1186 1103 DFE-520TX Fast Ethernet PCI Adapter (rev. C1) + 4300 DGE-528T Gigabit Ethernet Adapter + 1186 4300 DGE-528T PCI Gigabit Ethernet Adapter +# rev. B1; RealTek RTL8168E. + 1186 4b10 DGE-560T PCI Express (x1) Gigabit Ethernet Adapter + 4302 DGE-530T Gigabit Ethernet Adapter (rev.C1) [Realtek RTL8169] + 4b00 DGE-560T PCI Express Gigabit Ethernet Adapter + 4b01 DGE-530T Gigabit Ethernet Adapter (rev 11) + 4b02 DGE-560SX PCI Express Gigabit Ethernet Adapter + 4b03 DGE-550T Gigabit Ethernet Adapter V.B1 + 4c00 Gigabit Ethernet Adapter + 1186 4c00 DGE-530T Gigabit Ethernet Adapter + 8400 D-Link DWL-650+ CardBus PC Card +1187 Advanced Technology Laboratories, Inc. +1188 Shima Seiki Manufacturing Ltd. +1189 Matsushita Electronics Co Ltd +118a Hilevel Technology +118b Hypertec Pty Limited +118c Corollary, Inc + 0014 PCIB [C-bus II to PCI bus host bridge chip] + 1117 Intel 8-way XEON Profusion Chipset [Cache Coherency Filter] +118d BitFlow Inc + 0001 Raptor-PCI framegrabber + 0012 Model 12 Road Runner Frame Grabber + 0014 Model 14 Road Runner Frame Grabber + 0024 Model 24 Road Runner Frame Grabber + 0044 Model 44 Road Runner Frame Grabber + 0112 Model 12 Road Runner Frame Grabber + 0114 Model 14 Road Runner Frame Grabber + 0124 Model 24 Road Runner Frame Grabber + 0144 Model 44 Road Runner Frame Grabber + 0212 Model 12 Road Runner Frame Grabber + 0214 Model 14 Road Runner Frame Grabber + 0224 Model 24 Road Runner Frame Grabber + 0244 Model 44 Road Runner Frame Grabber + 0312 Model 12 Road Runner Frame Grabber + 0314 Model 14 Road Runner Frame Grabber + 0324 Model 24 Road Runner Frame Grabber + 0344 Model 44 Road Runner Frame Grabber +118e Hermstedt GmbH +118f Green Logic +1190 Tripace + c731 TP-910/920/940 PCI Ultra(Wide) SCSI Adapter +1191 Artop Electronic Corp + 0003 SCSI Cache Host Adapter + 0004 ATP8400 + 0005 ATP850UF + 0006 ATP860 NO-BIOS + 0007 ATP860 + 0008 ATP865 NO-ROM + 0009 ATP865 + 000a ATP867-A + 000b ATP867-B + 000d ATP8620 + 000e ATP8620 + 8002 AEC6710 SCSI-2 Host Adapter + 8010 AEC6712UW SCSI + 8020 AEC6712U SCSI + 8030 AEC6712S SCSI + 8040 AEC6712D SCSI + 8050 AEC6712SUW SCSI + 8060 AEC6712 SCSI + 8080 AEC67160 SCSI + 8081 AEC67160S SCSI + 808a AEC67162 2-ch. LVD SCSI +1192 Densan Company Ltd +1193 Zeitnet Inc. + 0001 1221 + 0002 1225 +1194 Toucan Technology +1195 Ratoc System Inc +1196 Hytec Electronics Ltd +1197 Gage Applied Sciences, Inc. + 010c CompuScope 82G 8bit 2GS/s Analog Input Card +1198 Lambda Systems Inc +1199 Attachmate Corporation + 0101 Advanced ISCA/PCI Adapter +119a Mind Share, Inc. +119b Omega Micro Inc. + 1221 82C092G +119c Information Technology Inst. +119d Bug, Inc. Sapporo Japan +119e Fujitsu Microelectronics Ltd. + 0001 FireStream 155 + 0003 FireStream 50 +119f Bull HN Information Systems + 1081 BXI Host Channel Adapter +# BXI stands for Bull eXascale Interconnect + 1101 BXI Host Channel Adapter v1.2 +# BXI stands for Bull eXascale Interconnect + 1121 BXI Host Channel Adapter v1.3 +11a0 Convex Computer Corporation +11a1 Hamamatsu Photonics K.K. +11a2 Sierra Research and Technology +11a3 Deuretzbacher GmbH & Co. Eng. KG +11a4 Barco Graphics NV +11a5 Microunity Systems Eng. Inc +11a6 Pure Data Ltd. +11a7 Power Computing Corp. +11a8 Systech Corp. +11a9 InnoSys Inc. + 4240 AMCC S933Q Intelligent Serial Card +11aa Actel +# Nee Galileo Technology, Inc. +11ab Marvell Technology Group Ltd. + 0146 GT-64010/64010A System Controller + 0f53 88E6318 Link Street network controller + 11ab MV88SE614x SATA II PCI-E controller + 138f W8300 802.11 Adapter (rev 07) + 1fa6 Marvell W8300 802.11 Adapter + 1186 3b08 AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.A1) + 1fa7 88W8310 and 88W8000G [Libertas] 802.11g client chipset + 1faa 88w8335 [Libertas] 802.11b/g Wireless + 1385 4e00 WG511v2 54 Mbps Wireless PC Card + 1385 6b00 WG311v3 802.11g Wireless PCI Adapter + 1737 0040 WPC54G v5 802.11g Wireless-G Notebook Adapter + 2211 88SB2211 PCI Express to PCI Bridge + 2a01 88W8335 [Libertas] 802.11b/g Wireless + 2a02 88W8361 [TopDog] 802.11n Wireless + 07d1 3b02 DIR-615 rev. A1 Mini PCI Wireless Module + 1385 7c00 WN511T RangeMax Next 300 Mbps Wireless PC Card + 1385 7c01 WN511T RangeMax Next 300 Mbps Wireless Notebook Adapter + 1385 7e00 WN311T RangeMax Next 300 Mbps Wireless PCI Adapter + 1799 801b F5D8011 v2 802.11n N1 Wireless Notebook Card + 2a08 88W8362e [TopDog] 802.11a/b/g/n Wireless + 2a0a 88W8363 [TopDog] 802.11n Wireless + 2a0c 88W8363 [TopDog] 802.11n Wireless + 2a24 88W8363 [TopDog] 802.11n Wireless + 2a2b 88W8687 [TopDog] 802.11b/g Wireless + 2a30 88W8687 [TopDog] 802.11b/g Wireless + 2a40 88W8366 [TopDog] 802.11n Wireless + 2a41 88W8366 [TopDog] 802.11n Wireless + 2a42 88W8366 [TopDog] 802.11n Wireless + 2a43 88W8366 [TopDog] 802.11n Wireless + 2a55 88W8864 [Avastar] 802.11ac Wireless + 2b36 88W8764 [Avastar] 802.11n Wireless + 2b38 88W8897 [AVASTAR] 802.11ac Wireless + 2b40 88W8964 [Avastar] 802.11ac Wireless + 4101 OLPC Cafe Controller Secure Digital Controller + 4320 88E8001 Gigabit Ethernet Controller + 1019 0f38 Marvell 88E8001 Gigabit Ethernet Controller (ECS) + 1019 8001 Marvell 88E8001 Gigabit Ethernet Controller (ECS) + 1043 173c Marvell 88E8001 Gigabit Ethernet Controller (Asus) + 1043 811a Marvell 88E8001 Gigabit Ethernet Controller (Asus) + 105b 0c19 Marvell 88E8001 Gigabit Ethernet Controller (Foxconn) + 10b8 b452 EZ Card 1000 (SMC9452TXV.2) + 11ab 0121 Marvell RDK-8001 + 11ab 0321 Marvell RDK-8003 + 11ab 1021 Marvell RDK-8010 + 11ab 4320 Marvell Yukon Gigabit Ethernet 10/100/1000Baset-T Constroller (Asus) + 11ab 5021 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (64 bit) + 11ab 9521 Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (32 bit) + 1458 e000 Marvell 88E8001 Gigabit Ethernet Controller (Gigabyte) + 147b 1406 Marvell 88E8001 Gigabit Ethernet Controller (Abit) + 15d4 0047 Marvell 88E8001 Gigabit Ethernet Controller (Iwill) + 1695 9025 Marvell 88E8001 Gigabit Ethernet Controller (Epox) + 17f2 1c03 Marvell 88E8001 Gigabit Ethernet Controller (Albatron) + 270f 2803 Marvell 88E8001 Gigabit Ethernet Controller (Chaintech) + 4340 88E8021 PCI-X IPMI Gigabit Ethernet Controller + 4341 88E8022 PCI-X IPMI Gigabit Ethernet Controller + 4342 88E8061 PCI-E IPMI Gigabit Ethernet Controller + 4343 88E8062 PCI-E IPMI Gigabit Ethernet Controller + 4344 88E8021 PCI-X IPMI Gigabit Ethernet Controller + 4345 88E8022 PCI-X IPMI Gigabit Ethernet Controller + 4346 88E8061 PCI-E IPMI Gigabit Ethernet Controller + 4347 88E8062 PCI-E IPMI Gigabit Ethernet Controller + 4c53 10d0 Telum ASLP10 PrAMC Gigabit Ethernet + 4350 88E8035 PCI-E Fast Ethernet Controller + 1179 0001 Marvell 88E8035 Fast Ethernet Controller (Toshiba) + 11ab 3521 Marvell RDK-8035 + 1854 000d Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 000e Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 000f Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 0011 Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 0012 Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 0016 Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 0017 Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 0018 Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 0019 Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 001c Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 001e Marvell 88E8035 Fast Ethernet Controller (LGE) + 1854 0020 Marvell 88E8035 Fast Ethernet Controller (LGE) + 4351 88E8036 PCI-E Fast Ethernet Controller + 107b 4009 Marvell 88E8036 Fast Ethernet Controller (Wistron) + 10f7 8338 Marvell 88E8036 Fast Ethernet Controller (Panasonic) + 1179 0001 Marvell 88E8036 Fast Ethernet Controller (Toshiba) + 1179 ff00 Marvell 88E8036 Fast Ethernet Controller (Compal) + 1179 ff10 Marvell 88E8036 Fast Ethernet Controller (Inventec) + 11ab 3621 Marvell RDK-8036 + 13d1 ac12 Abocom EFE3K - 10/100 Ethernet Expresscard + 161f 203d Marvell 88E8036 Fast Ethernet Controller (Arima) + 1854 000d Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 000e Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 000f Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 0011 Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 0012 Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 0016 Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 0017 Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 0018 Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 0019 Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 001c Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 001e Marvell 88E8036 Fast Ethernet Controller (LGE) + 1854 0020 Marvell 88E8036 Fast Ethernet Controller (LGE) + 4352 88E8038 PCI-E Fast Ethernet Controller + 4353 88E8039 PCI-E Fast Ethernet Controller + 104d 902d VAIO VGN-NR120E + 4354 88E8040 PCI-E Fast Ethernet Controller + 1028 022f Inspiron 1525 + 144d c06a R730 Laptop + 144d c072 Notebook N150P + 4355 88E8040T PCI-E Fast Ethernet Controller + 1179 ff50 Satellite P305D-S8995E + 4356 88EC033 PCI-E Fast Ethernet Controller + 4357 88E8042 PCI-E Fast Ethernet Controller + 435a 88E8048 PCI-E Fast Ethernet Controller + 4360 88E8052 PCI-E ASF Gigabit Ethernet Controller + 1043 8134 Marvell 88E8052 Gigabit Ethernet Controller (Asus) + 107b 4009 Marvell 88E8052 Gigabit Ethernet Controller (Wistron) + 11ab 5221 Marvell RDK-8052 + 1458 e000 Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte) + 1462 052c Marvell 88E8052 Gigabit Ethernet Controller (MSI) + 1849 8052 Marvell 88E8052 Gigabit Ethernet Controller (ASRock) + a0a0 0509 Marvell 88E8052 Gigabit Ethernet Controller (Aopen) + 4361 88E8050 PCI-E ASF Gigabit Ethernet Controller + 107b 3015 Marvell 88E8050 Gigabit Ethernet Controller (Gateway) + 11ab 5021 Marvell 88E8050 Gigabit Ethernet Controller (Intel) + 8086 3063 D925XCVLK mainboard + 8086 3439 Marvell 88E8050 Gigabit Ethernet Controller (Intel) + 4362 88E8053 PCI-E Gigabit Ethernet Controller + 103c 2a0d Marvell 88E8053 Gigabit Ethernet Controller (Asus) + 1043 8142 Marvell 88E8053 Gigabit Ethernet controller PCIe (Asus) + 109f 3197 Marvell 88E8053 Gigabit Ethernet Controller (Trigem) + 10f7 8338 Marvell 88E8053 Gigabit Ethernet Controller (Panasonic) + 10fd a430 Marvell 88E8053 Gigabit Ethernet Controller (SOYO) + 1179 0001 Marvell 88E8053 Gigabit Ethernet Controller (Toshiba) + 1179 ff00 Marvell 88E8053 Gigabit Ethernet Controller (Compal) + 1179 ff10 Marvell 88E8053 Gigabit Ethernet Controller (Inventec) + 11ab 5321 Marvell RDK-8053 + 1297 c240 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle) + 1297 c241 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle) + 1297 c242 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle) + 1297 c243 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle) + 1297 c244 Marvell 88E8053 Gigabit Ethernet Controller (Shuttle) + 13d1 ac11 EGE5K - Giga Ethernet Expresscard + 1458 e000 Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte) + 1462 058c Marvell 88E8053 Gigabit Ethernet Controller (MSI) + 14c0 0012 Marvell 88E8053 Gigabit Ethernet Controller (Compal) + 1558 04a0 Marvell 88E8053 Gigabit Ethernet Controller (Clevo) + 15bd 1003 Marvell 88E8053 Gigabit Ethernet Controller (DFI) + 161f 203c Marvell 88E8053 Gigabit Ethernet Controller (Arima) + 161f 203d Marvell 88E8053 Gigabit Ethernet Controller (Arima) + 1695 9029 Marvell 88E8053 Gigabit Ethernet Controller (Epox) + 17f2 2c08 Marvell 88E8053 Gigabit Ethernet Controller (Albatron) + 17ff 0585 Marvell 88E8053 Gigabit Ethernet Controller (Quanta) + 1849 8053 Marvell 88E8053 Gigabit Ethernet Controller (ASRock) + 1854 000b Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 000c Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 0010 Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 0013 Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 0014 Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 0015 Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 001a Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 001b Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 001d Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 001f Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 0021 Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 1854 0022 Marvell 88E8053 Gigabit Ethernet Controller (LGE) + 270f 2801 Marvell 88E8053 Gigabit Ethernet Controller (Chaintech) + a0a0 0506 Marvell 88E8053 Gigabit Ethernet Controller (Aopen) + 4363 88E8055 PCI-E Gigabit Ethernet Controller + 4364 88E8056 PCI-E Gigabit Ethernet Controller + 1043 81f8 Motherboard + 11ba 00ba 8056 Gigabit Ethernet Controller + 4365 88E8070 based Ethernet Controller + 4366 88EC036 PCI-E Gigabit Ethernet Controller + 4367 88EC032 Ethernet Controller + 4368 88EC034 Ethernet Controller + 4369 88EC042 Ethernet Controller + 436a 88E8058 PCI-E Gigabit Ethernet Controller + 11ab 00ba Imac 8,1 Wired Ethernet Adapter + 436b 88E8071 PCI-E Gigabit Ethernet Controller + 436c 88E8072 PCI-E Gigabit Ethernet Controller + 436d 88E8055 PCI-E Gigabit Ethernet Controller + 4370 88E8075 PCI-E Gigabit Ethernet Controller + 4380 88E8057 PCI-E Gigabit Ethernet Controller +# AVB = "Audio Video Bridging" + 4381 Yukon Optima 88E8059 [PCIe Gigabit Ethernet Controller with AVB] + 1259 2803 AT-2814FX + 1259 2804 AT-2874xx + 4611 GT-64115 System Controller + 4620 GT-64120/64120A/64121A System Controller + 4801 GT-48001 + 5005 Belkin F5D5005 Gigabit Desktop Network PCI Card + 5040 MV88SX5040 4-port SATA I PCI-X Controller + 5041 MV88SX5041 4-port SATA I PCI-X Controller + 5080 MV88SX5080 8-port SATA I PCI-X Controller + 5081 MV88SX5081 8-port SATA I PCI-X Controller + 5181 88f5181 [Orion-1] ARM SoC + 5182 88f5182 [Orion-NAS] ARM SoC + 5281 88f5281 [Orion-2] ARM SoC + 6041 MV88SX6041 4-port SATA II PCI-X Controller + 6042 88SX6042 PCI-X 4-Port SATA-II + 6081 MV88SX6081 8-port SATA II PCI-X Controller + 6101 88SE6101/6102 single-port PATA133 interface + 1043 82e0 P5K PRO Motherboard + 6121 88SE6111/6121 SATA II / PATA Controller +# 6111: 1 SATA port; 6121: 2 SATA ports + 11ab 6121 88SE6111/6121 1/2 port SATA II + 1 port PATA Controller + 6141 88SE614x SATA II PCI-E controller + 6145 88SE6145 SATA II PCI-E controller + 6180 88F6180 [Kirkwood] ARM SoC + 6192 88F6190/6192 [Kirkwood] ARM SoC + 6281 88F6281 [Kirkwood] ARM SoC +# This device ID was used for earlier chips. + 6381 MV78xx0 [Discovery Innovation] ARM SoC + 6440 88SE6440 SAS/SATA PCIe controller + 6450 64560 System Controller + 6460 MV64360/64361/64362 System Controller + 6480 MV64460/64461/64462 System Controller + 1775 c200 C2K CompactPCI single board computer + 6485 MV64460/64461/64462 System Controller, Revision B + 7042 88SX7042 PCI-e 4-port SATA-II + 16b8 434b Tempo SATA E4P + 7810 MV78100 [Discovery Innovation] ARM SoC + 7820 MV78200 [Discovery Innovation] ARM SoC + 7823 MV78230 [Armada XP] ARM SoC + 7846 88F6820 [Armada 385] ARM SoC + d40f Bobcat3 Ethernet Switch + f003 GT-64010 Primary Image Piranha Image Generator +11ac Canon Information Systems Research Aust. +11ad Lite-On Communications Inc + 0002 LNE100TX + 11ad 0002 LNE100TX + 11ad 0003 LNE100TX + 11ad f003 LNE100TX + 11ad ffff LNE100TX + 1385 f004 FA310TX + 2646 f002 KNE110TX EtheRx Fast Ethernet + c115 LNE100TX [Linksys EtherFast 10/100] + 11ad c001 LNE100TX [ver 2.0] + 2646 000b KNE111TX +11ae Aztech System Ltd +11af Avid Technology Inc. + 0001 Cinema + ee40 Digidesign Audiomedia III +11b0 V3 Semiconductor Inc. + 0002 V300PSC + 0292 V292PBC [Am29030/40 Bridge] + 0960 V96xPBC + 880a Deltacast Delta-HD-22 + c960 V96DPC +11b1 Apricot Computers +11b2 Eastman Kodak +11b3 Barr Systems Inc. +11b4 Leitch Technology International +11b5 Radstone Technology Plc +11b6 United Video Corp +11b7 Motorola +11b8 XPoint Technologies, Inc + 0001 Quad PeerMaster +11b9 Pathlight Technology Inc. + c0ed SSA Controller +11ba Videotron Corp +11bb Pyramid Technology +11bc Network Peripherals Inc + 0001 NP-PCI +11bd Pinnacle Systems Inc. + 002e PCTV 40i + 0040 Royal TS Function 1 + 11bd 0044 PCTV 2000i Dual DVB-T Pro PCI Tuner 1 + 11bd 0045 PCTV Dual Sat Pro PCI 4000i Tuner 1 + 0041 RoyalTS Function 2 + 11bd 0044 PCTV 2000i Dual DVB-T Pro PCI Tuner 2 + 11bd 0045 PCTV Dual Sat Pro PCI 4000i Tuner 2 + 0042 Royal TS Function 3 + 11bd 0044 PCTV 2000i Dual DVB-T Pro PCI Common + 11bd 0045 PCTV Dual Sat Pro PCI 4000i Common + 0051 PCTV HD 800i + bede AV/DV Studio Capture Card +11be International Microcircuits Inc +11bf Astrodesign, Inc. +11c0 Hewlett Packard +# nee Agere Systems nee Lucent Microelectronics +11c1 LSI Corporation + 0440 56k WinModem + 1033 8015 LT WinModem 56k Data+Fax+Voice+Dsvd + 1033 8047 LT WinModem 56k Data+Fax+Voice+Dsvd + 1033 804f LT WinModem 56k Data+Fax+Voice+Dsvd + 10cf 102c LB LT Modem V.90 56k + 10cf 104a BIBLO LT Modem 56k + 10cf 105f LB2 LT Modem V.90 56k + 1179 0001 Internal V.90 Modem + 11c1 0440 LT WinModem 56k Data+Fax+Voice+Dsvd + 122d 4101 MDP7800-U Modem + 122d 4102 MDP7800SP-U Modem + 13e0 0040 LT WinModem 56k Data+Fax+Voice+Dsvd + 13e0 0440 LT WinModem 56k Data+Fax+Voice+Dsvd + 13e0 0441 LT WinModem 56k Data+Fax+Voice+Dsvd + 13e0 0450 LT WinModem 56k Data+Fax+Voice+Dsvd + 13e0 f100 LT WinModem 56k Data+Fax+Voice+Dsvd + 13e0 f101 LT WinModem 56k Data+Fax+Voice+Dsvd + 144d 2101 LT56PV Modem + 149f 0440 LT WinModem 56k Data+Fax+Voice+Dsvd + 0441 56k WinModem + 1033 804d LT WinModem 56k Data+Fax + 1033 8065 LT WinModem 56k Data+Fax + 1092 0440 Supra 56i + 1179 0001 Internal V.90 Modem + 11c1 0440 LT WinModem 56k Data+Fax + 11c1 0441 LT WinModem 56k Data+Fax + 122d 4100 MDP7800-U Modem + 13e0 0040 LT WinModem 56k Data+Fax + 13e0 0100 LT WinModem 56k Data+Fax + 13e0 0410 LT WinModem 56k Data+Fax + 13e0 0420 TelePath Internet 56k WinModem + 13e0 0440 LT WinModem 56k Data+Fax + 13e0 0443 LT WinModem 56k Data+Fax + 13e0 f102 LT WinModem 56k Data+Fax + 1416 9804 CommWave 56k Modem + 141d 0440 LT WinModem 56k Data+Fax + 144f 0441 Lucent 56k V.90 DF Modem + 144f 0449 Lucent 56k V.90 DF Modem + 144f 110d Lucent Win Modem + 1468 0441 Presario 56k V.90 DF Modem + 1668 0440 Lucent Win Modem + 0442 56k WinModem + 11c1 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 11c1 0442 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 13e0 0412 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 13e0 0442 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 13fc 2471 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 144d 2104 LT56PT Modem + 144f 1104 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 149f 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 1668 0440 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 0443 LT WinModem + 0444 LT WinModem + 0445 LT WinModem + 8086 2203 PRO/100+ MiniPCI (probably an Ambit U98.003.C.00 combo card) + 8086 2204 PRO/100+ MiniPCI on Armada E500 + 0446 LT WinModem + 0447 LT WinModem + 0448 WinModem 56k + 1014 0131 Lucent Win Modem + 1033 8066 LT WinModem 56k Data+Fax+Voice+Dsvd + 13e0 0030 56k Voice Modem + 13e0 0040 LT WinModem 56k Data+Fax+Voice+Dsvd +# Actiontech eth+modem card as used by Dell &c. + 1668 2400 LT WinModem 56k (MiniPCI Ethernet+Modem) + 0449 L56xM+S [Mars-2] WinModem 56k + 0e11 b14d 56k V.90 Modem + 1014 018c ThinkPad 600X + 13e0 0020 LT WinModem 56k Data+Fax + 13e0 0041 TelePath Internet 56k WinModem + 1436 0440 Lucent Win Modem + 144f 0449 Lucent 56k V.90 DFi Modem + 1468 0410 IBM ThinkPad T23 + 1468 0440 Lucent Win Modem + 1468 0449 Presario 56k V.90 DFi Modem + 044a F-1156IV WinModem (V90, 56KFlex) + 10cf 1072 LB Global LT Modem + 13e0 0012 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 13e0 0042 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 144f 1005 LT WinModem 56k Data+Fax+Voice+VoiceView+Dsvd + 044b LT WinModem + 044c LT WinModem + 044d LT WinModem + 044e LT WinModem + 044f V90 WildWire Modem + 0450 LT WinModem + 1033 80a8 Versa Note Vxi + 144f 4005 Magnia SG20 + 1468 0450 Evo N600c + 0451 LT WinModem + 0452 LT WinModem + 0453 LT WinModem + 0454 LT WinModem + 0455 LT WinModem + 0456 LT WinModem + 0457 LT WinModem + 0458 LT WinModem + 0459 LT WinModem + 045a LT WinModem + 045c LT WinModem + 0461 V90 WildWire Modem + 0462 V90 WildWire Modem + 0480 Venus Modem (V90, 56KFlex) + 048c V.92 56K WinModem +# InPorte Home Internal 56k Modem/fax/answering machine/SMS Features + 048f V.92 56k WinModem + 0620 Lucent V.92 Data/Fax Modem + 2600 StarPro26XX family (SP2601, SP2603, SP2612) DSP + 5400 OR3TP12 FPSC + 5656 Venus Modem + 5801 USB + 5802 USS-312 USB Controller + 5803 USS-344S USB Controller + 5811 FW322/323 [TrueFire] 1394a Controller + 103c 2a34 Pavilion a1677c + 103c 2a6f Asus IPIBL-LB Motherboard + 103c 2a9e Pavilion p6310f + 1043 8294 LSI FW322/323 IEEE 1394a FireWire Controller + 11bd 000e LSI FW323 + 8086 524c D865PERL mainboard + 9005 0033 Adaptec AFW-2100 (HP) 2102900-R + dead 0800 FireWire Host Bus Adapter + 5901 FW643 [TrueFire] PCIe 1394b Controller + 11c1 5900 FW643 [TrueFire] PCIe 1394b Controller + 1443 0643 FireBoard800-e V.2 + 1546 0643 FWB-PCIE1X2x + 5903 FW533 [TrueFire] PCIe 1394a Controller + 8110 T8110 H.100/H.110 TDM switch + 12d9 000c E1/T1 PMXc cPCI carrier card + ab10 WL60010 Wireless LAN MAC + ab11 WL60040 Multimode Wireles LAN MAC + 11c1 ab12 WaveLAN 11abg Cardbus card (Model 1102) + 11c1 ab13 WaveLAN 11abg MiniPCI card (Model 0512) + 11c1 ab15 WaveLAN 11abg Cardbus card (Model 1106) + 11c1 ab16 WaveLAN 11abg MiniPCI card (Model 0516) + ab20 ORiNOCO PCI Adapter + ab21 Agere Wireless PCI Adapter + ab30 Hermes2 Mini-PCI WaveLAN a/b/g + 14cd 2012 Hermes2 Mini-PCI WaveLAN a/b/g + ed00 ET-131x PCI-E Ethernet Controller + ed01 ET-131x PCI-E Ethernet Controller +11c2 Sand Microelectronics +11c3 NEC Corporation +11c4 Document Technologies, Inc +11c5 Shiva Corporation +11c6 Dainippon Screen Mfg. Co. Ltd +11c7 D.C.M. Data Systems +11c8 Dolphin Interconnect Solutions AS + 0658 PSB32 SCI-Adapter D31x + d665 PSB64 SCI-Adapter D32x + d667 PSB66 SCI-Adapter D33x +11c9 Magma + 0010 16-line serial port w/- DMA + 0011 4-line serial port w/- DMA +11ca LSI Systems, Inc +11cb Specialix Research Ltd. + 2000 PCI_9050 + 11cb 0200 SX + 11cb b008 I/O8+ + 4000 SUPI_1 + 8000 T225 +11cc Michels & Kleberhoff Computer GmbH +11cd HAL Computer Systems, Inc. +11ce Netaccess +11cf Pioneer Electronic Corporation +11d0 Lockheed Martin Federal Systems-Manassas +11d1 Auravision + 01f7 VxP524 + 01f9 VxP951 +11d2 Intercom Inc. +11d3 Trancell Systems Inc +11d4 Analog Devices + 1535 Blackfin BF535 processor + 1805 SM56 PCI modem +11d5 Ikon Corporation + 0115 10115 + 0117 10117 +11d6 Tekelec Telecom +11d7 Trenton Technology, Inc. +11d8 Image Technologies Development +11d9 TEC Corporation +11da Novell +11db Sega Enterprises Ltd +11dc Questra Corporation +11dd Crosfield Electronics Limited +11de Zoran Corporation + 6017 miroVIDEO DC30 + 6057 ZR36057PQC Video cutting chipset + 1031 7efe DC10 Plus + 1031 fc00 MiroVIDEO DC50, Motion JPEG Capture/CODEC Board + 12f8 8a02 Tekram Video Kit + 13ca 4231 JPEG/TV Card + 6120 ZR36120 + 1328 f001 Cinemaster C DVD Decoder + 13c2 0000 MediaFocus Satellite TV Card + 1de1 9fff Video Kit C210 +11df New Wave PDG +11e0 Cray Communications A/S +11e1 GEC Plessey Semi Inc. +11e2 Samsung Information Systems America +11e3 Quicklogic Corporation + 0001 COM-ON-AIR Dosch&Amand DECT + 0560 QL5064 Companion Design Demo Board + 5030 PC Watchdog + 8417 QL5064 [QuickPCI] PCI v2.2 bridge for SMT417 Dual TMS320C6416T PMC Module +11e4 Second Wave Inc +11e5 IIX Consulting +11e6 Mitsui-Zosen System Research +11e7 Toshiba America, Elec. Company +11e8 Digital Processing Systems Inc. +11e9 Highwater Designs Ltd. +11ea Elsag Bailey +11eb Formation Inc. +11ec Coreco Inc + 000d Oculus-F/64P + 1800 Cobra/C6 +11ed Mediamatics +11ee Dome Imaging Systems Inc +11ef Nicolet Technologies B.V. +11f0 Compu-Shack + 4231 FDDI + 4232 FASTline UTP Quattro + 4233 FASTline FO + 4234 FASTline UTP + 4235 FASTline-II UTP + 4236 FASTline-II FO + 4731 GIGAline +11f1 Symbios Logic Inc +11f2 Picture Tel Japan K.K. +11f3 Keithley Metrabyte + 0011 KPCI-PIO24 +11f4 Kinetic Systems Corporation + 2915 CAMAC controller +11f5 Computing Devices International +11f6 Compex + 0112 ENet100VG4 + 0113 FreedomLine 100 + 1401 ReadyLink 2000 + 2011 RL100-ATX 10/100 + 11f6 2011 RL100-ATX + 2201 ReadyLink 100TX (Winbond W89C840) + 11f6 2011 ReadyLink 100TX + 9881 RL100TX Fast Ethernet +11f7 Scientific Atlanta +11f8 PMC-Sierra Inc. + 5220 BR522x [PMC-Sierra maxRAID SAS Controller] + 7364 PM7364 [FREEDM - 32 Frame Engine & Datalink Mgr] + 7375 PM7375 [LASAR-155 ATM SAR] + 7384 PM7384 [FREEDM - 84P672 Frm Engine & Datalink Mgr] + 8000 PM8000 [SPC - SAS Protocol Controller] + 8009 PM8009 SPCve 8x6G + 8018 PM8018 Adaptec SAS Adaptor ASA-70165H PCIe Gen3 x8 6 Gbps 16-lane 4x SFF-8644 + 8032 PM8032 Tachyon QE8 + 117c 003a Celerity FC-81EN Fibre Channel Adapter + 117c 003b Celerity FC-82EN Fibre Channel Adapter + 117c 003c Celerity FC-84EN Fibre Channel Adapter + 117c 403b ThunderLink FC 1082 Fibre Channel Adapter + 8053 PM8053 SXP 12G 24-port SAS/SATA expander + 8054 PM8054 SXP 12G 36-port SAS/SATA expander + 8055 PM8055 SXP 12G 48-port SAS/SATA expander + 8056 PM8056 SXP 12G 68-port SAS/SATA expander + 8060 PM8060 SRCv 12G eight-port SAS/SATA RoC + 8063 PM8063 SRCv 12G 16-port SAS/SATA RoC + 8070 PM8070 Tachyon SPCv 12G eight-port SAS/SATA controller + 8071 PM8071 Tachyon SPCve 12G eight-port SAS/SATA controller + 8072 PM8072 Tachyon SPCv 12G 16-port SAS/SATA controller + 8073 PM8073 Tachyon SPCve 12G 16-port SAS/SATA controller + 8531 PM8531 PFX 24xG3 Fanout PCIe Switches + 8546 PM8546 B-FEIP PSX 96xG3 PCIe Storage Switch +11f9 I-Cube Inc +11fa Kasan Electronics Company, Ltd. +11fb Datel Inc +11fc Silicon Magic +11fd High Street Consultants +11fe Pepperl+Fuchs Comtrol, Inc. + 0001 RocketPort PCI 32-port w/external I/F + 0002 RocketPort PCI 8-port w/external I/F + 0003 RocketPort PCI 16-port w/external I/F + 0004 RocketPort PCI 4-port w/Quad Cable + 0005 RocketPort PCI 8-port w/Octa Cable + 0006 RocketPort PCI 8-port w/RJ11 connectors + 0007 RocketPort PCI 4-port w/RJ45 connectors + 0008 RocketPort PCI 8-port w/DB78 SNI connector (Siemens) + 0009 RocketPort PCI 16-port w/DB78 SNI connector (Siemens) + 000a RocketPort PCI Plus 4-port w/Quad Cable + 000b RocketPort PCI Plus 8-port w/Octa Cable + 000c RocketModem II 6-port + 000d RocketModem 4-port + 000e RocketPort PCI Plus 2-port RS-232 w/DB9 connectors + 000f RocketPort PCI Plus 2-port SMPTE w/DB9 connectors + 0040 RocketPort INFINITY 8-port w/Octa Cable RJ45 + 0041 RocketPort INFINITY 32-port w/external I/F + 0042 RocketPort INFINITY 8-port w/external I/F + 0043 RocketPort INFINITY 16-port w/external I/F + 0044 RocketPort INFINITY 4-port w/Quad Cable DB + 0045 RocketPort INFINITY 8-port w/Octa Cable DB + 0046 RocketPort INFINITY 4-port w/external I/F + 0047 RocketPort INFINITY 4J (4-port) w/RJ45 connectors + 0048 RocketPort INFINITY 4J (4-port) w/RJ45 connectors + 004a RocketPort INFINITY Plus 4-port + 004b RocketPort INFINITY Plus 8-port + 004c RocketModem INFINITY III 8-port + 004d RocketModem INFINITY III 4-port + 004e RocketPort INFINITY Plus 2-port + 004f RocketPort INFINITY 2-port SMPTE w/DB9 connectors + 0050 RocketPort INFINITY Plus 4-port RJ45 + 0051 RocketPort INFINITY Plus 8-port RJ11 + 0052 RocketPort INFINITY 8-port SMPTE w/DB9 Connectors + 0060 RocketPort EXPRESS 8-port w/Octa Cable + 0061 RocketPort EXPRESS 32-port w/external I/F + 0062 RocketPort EXPRESS 8-Port w/external I/F + 0063 RocketPort EXPRESS 16-port w/external I/F + 0064 RocketPort EXPRESS 4-port w/Quad Cable + 0065 RocketPort EXPRESS 8-port w/Octa Cable + 0066 RocketPort EXPRESS 4-port w/external I/F + 0067 RocketPort EXPRESS 4J (4-port) w/RJ45 connectors + 0068 RocketPort EXPRESS 8J (8-port) w/RJ11 connectors + 006f RocketPort EXPRESS SMPTE 2-port + 0072 RocketPort EXPRESS SMPTE 8-port w/external I/F + 0801 RocketPort uPCI 32-port w/external I/F + 0802 RocketPort uPCI 8-port w/external I/F + 0803 RocketPort uPCI 16-port w/external I/F + 0805 RocketPort uPCI 8-port w/Octa Cable + 080b RocketPort Plus uPCI 8-port w/Octa Cable + 080c RocketModem III 8-port + 080d RocketModem III 4-port + 080e RocketPort uPCI 2-port RS232 w/DB9 connectors + 080f RocketPort uPCI SMPTE 2-port + 0810 RocketPort Plus uPCI 4J (4-port) w/RJ45 connectors + 0811 RocketPort Plus uPCI 8J (8-port) w/RJ11 connectors + 0812 RocketPort Plus uPCI 422 8-port + 0813 RocketModem IV uPCI 8-port + 0814 RocketModem IV uPCI 4-port + 0903 RocketPort Compact PCI 16 port w/external I/F +# 16954 UART + 8015 RocketPort 550 4-port + 8805 RocketPort uPCI 4-port w/Quad Cable + 880b RocketPort Plus uPCI 4-port w/Quad Cable + 8812 RocketPort Plus uPCI 4-port RS422 w/Quad Cable +11ff Scion Corporation + 0003 AG-5 +1200 CSS Corporation +1201 Vista Controls Corp +1202 Network General Corp. + 4300 Gigabit Ethernet Adapter + 1202 9841 SK-9841 LX + 1202 9842 SK-9841 LX dual link + 1202 9843 SK-9843 SX + 1202 9844 SK-9843 SX dual link +1203 Bayer Corporation, Agfa Division +1204 Lattice Semiconductor Corporation + 1965 SB6501 802.11ad Wireless Network Adapter +1205 Array Corporation +1206 Amdahl Corporation +1208 Parsytec GmbH + 4853 HS-Link Device +1209 SCI Systems Inc +120a Synaptel +120b Adaptive Solutions +120c Technical Corp. +120d Compression Labs, Inc. +120e Cyclades Corporation + 0100 Cyclom-Y below first megabyte + 0101 Cyclom-Y above first megabyte + 0102 Cyclom-4Y below first megabyte + 0103 Cyclom-4Y above first megabyte + 0104 Cyclom-8Y below first megabyte + 0105 Cyclom-8Y above first megabyte + 0200 Cyclades-Z below first megabyte + 0201 Cyclades-Z above first megabyte + 0300 PC300/RSV or /X21 (2 ports) + 0301 PC300/RSV or /X21 (1 port) + 0310 PC300/TE (2 ports) + 0311 PC300/TE (1 port) + 0320 PC300/TE-M (2 ports) + 0321 PC300/TE-M (1 port) + 0400 PC400 +120f Essential Communications + 0001 Roadrunner serial HIPPI +1210 Hyperparallel Technologies +1211 Braintech Inc +1213 Applied Intelligent Systems, Inc. +1214 Performance Technologies, Inc. +1215 Interware Co., Ltd +1216 Purup Prepress A/S +1217 O2 Micro, Inc. + 00f7 Firewire (IEEE 1394) + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 1179 ff50 Satellite P305D-S8995E + 10f7 1394 OHCI Compliant Host Controller + 11f7 OZ600 1394a-2000 Controller + 1028 04a3 Precision M4600 + 13f7 1394 OHCI Compliant Host Controller + 6729 OZ6729 + 673a OZ6730 + 6832 OZ6832/6833 CardBus Controller + 6836 OZ6836/6860 CardBus Controller + 6872 OZ6812 CardBus Controller + 6925 OZ6922 CardBus Controller + 6933 OZ6933/711E1 CardBus/SmartCardBus Controller + 1025 1016 Travelmate 612 TX + 6972 OZ601/6912/711E0 CardBus/SmartCardBus Controller + 1014 020c ThinkPad R30 + 1028 0152 Latitude D500 + 1179 0001 Magnia Z310 + 7110 OZ711Mx 4-in-1 MemoryCardBus Accelerator + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 1734 106c Amilo A1645 + 7112 OZ711EC1/M1 SmartCardBus/MemoryCardBus Controller + 7113 OZ711EC1 SmartCardBus Controller + 1025 0035 TravelMate 660 + 7114 OZ711M1/MC1 4-in-1 MemoryCardBus Controller + 7120 Integrated MMC/SD Controller + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 1179 ff50 Satellite P305D-S8995E + 7130 Integrated MS/xD Controller + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 1179 ff50 Satellite P305D-S8995E + 7134 OZ711MP1/MS1 MemoryCardBus Controller + 7135 Cardbus bridge + 7136 OZ711SP1 Memory CardBus Controller + 71e2 OZ711E2 SmartCardBus Controller + 7212 OZ711M2 4-in-1 MemoryCardBus Controller + 7213 OZ6933E CardBus Controller + 7223 OZ711M3/MC3 4-in-1 MemoryCardBus Controller + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 10cf 11c4 Lifebook P5020D Laptop + 7233 OZ711MP3/MS3 4-in-1 MemoryCardBus Controller + 8120 Integrated MMC/SD Controller + 8130 Integrated MS/MSPRO/xD Controller + 8220 OZ600FJ1/OZ900FJ1 SD/MMC Card Reader Controller + 8221 OZ600FJ0/OZ900FJ0/OZ600FJS SD/MMC Card Reader Controller + 8320 OZ600RJ1/OZ900RJ1 SD/MMC Card Reader Controller + 1028 04a3 Precision M4600 + 8321 OZ600RJ0/OZ900RJ0/OZ600RJS SD/MMC Card Reader Controller + 8330 OZ600 MS/xD Controller + 1028 04a3 Precision M4600 + 8331 O2 Flash Memory Card + 8520 SD/MMC Card Reader Controller + 8621 SD/MMC Card Reader Controller +1218 Hybricon Corp. +1219 First Virtual Corporation +121a 3Dfx Interactive, Inc. + 0001 Voodoo + 0002 Voodoo 2 + 0003 Voodoo Banshee + 1092 0003 Monster Fusion + 1092 4000 Monster Fusion + 1092 4002 Monster Fusion + 1092 4801 Monster Fusion AGP + 1092 4803 Monster Fusion AGP + 1092 8030 Monster Fusion + 1092 8035 Monster Fusion AGP + 10b0 0001 Dragon 4000 + 1102 1017 3D Blaster Banshee PCI (CT6760) + 1102 1018 3D Blaster Banshee VE + 121a 0001 Voodoo Banshee AGP + 121a 0003 Voodoo Banshee AGP SGRAM + 121a 0004 Voodoo Banshee + 139c 0016 Raven + 139c 0017 Raven + 14af 0002 Maxi Gamer Phoenix + 0004 Voodoo Banshee [Velocity 100] + 0005 Voodoo 3 + 121a 0004 Voodoo3 AGP + 121a 0030 Voodoo3 AGP + 121a 0031 Voodoo3 AGP + 121a 0034 Voodoo3 AGP + 121a 0036 Voodoo3 2000 PCI + 121a 0037 Voodoo3 AGP + 121a 0038 Voodoo3 AGP + 121a 003a Voodoo3 AGP + 121a 0044 Voodoo3 + 121a 004b Velocity 100 + 121a 004c Velocity 200 + 121a 004d Voodoo3 AGP + 121a 004e Voodoo3 AGP + 121a 0051 Voodoo3 AGP + 121a 0052 Voodoo3 AGP + 121a 0057 Voodoo3 3000 PCI + 121a 0060 Voodoo3 3500 TV (NTSC) + 121a 0061 Voodoo3 3500 TV (PAL) + 121a 0062 Voodoo3 3500 TV (SECAM) + 0009 Voodoo 4 / Voodoo 5 + 121a 0003 Voodoo5 PCI 5500 + 121a 0009 Voodoo5 AGP 5500/6000 + 0057 Voodoo 3/3000 [Avenger] +121b Advanced Telecommunications Modules +121c Nippon Texaco., Ltd +121d LiPPERT ADLINK Technology GmbH +121e CSPI + 0201 Myrinet 2000 Scalable Cluster Interconnect +121f Arcus Technology, Inc. +1220 Ariel Corporation + 1220 AMCC 5933 TMS320C80 DSP/Imaging board +1221 Contec Co., Ltd + 9172 PO-64L(PCI)H [Isolated Digital Output Board for PCI] + 91a2 PO-32L(PCI)H [Isolated Digital Output Board for PCI] + 91c3 DA16-16(LPCI)L [Un-insulated highly precise analog output board for Low Profile PCI] + b152 DIO-96D2-LPCI + c103 ADA16-32/2(PCI)F [High-Speed Analog I/O Board for PCI] +1222 Ancor Communications, Inc. +1223 Artesyn Communication Products + 0003 PM/Link + 0004 PM/T1 + 0005 PM/E1 + 0008 PM/SLS + 0009 BajaSpan Resource Target + 000a BajaSpan Section 0 + 000b BajaSpan Section 1 + 000c BajaSpan Section 2 + 000d BajaSpan Section 3 + 000e PM/PPC +1224 Interactive Images +1225 Power I/O, Inc. +1227 EIZO Rugged Solutions + 0006 Raptor GFX 8P + 0023 Raptor GFX [1100T] + 0045 Raptor 4000-L [Linux version] + 004a Raptor 4000-LR-L [Linux version] +1228 Norsk Elektro Optikk A/S +1229 Data Kinesis Inc. +122a Integrated Telecom +122b LG Industrial Systems Co., Ltd +122c Sican GmbH +122d Aztech System Ltd + 1206 368DSP + 1400 Trident PCI288-Q3DII (NX) + 50dc 3328 Audio + 122d 0001 3328 Audio + 80da 3328 Audio + 122d 0001 3328 Audio +122e Xyratex + 7722 Napatech XL1 + 7724 Napatech XL2/XA + 7729 Napatech XD +122f Andrew Corporation +1230 Fishcamp Engineering +1231 Woodward McCoach, Inc. + 04e1 Desktop PCI Telephony 4 + 05e1 Desktop PCI Telephony 5/6 + 0d00 LightParser + 0d02 LightParser 2 + 0d13 Desktop PCI L1/L3 Telephony +1232 GPT Limited +1233 Bus-Tech, Inc. +# nee Risq Modular Systems, Inc. +1235 SMART Modular Technologies +1236 Sigma Designs Corporation + 0000 RealMagic64/GX + 6401 REALmagic 64/GX (SD 6425) +1237 Alta Technology Corporation +1238 Adtran +1239 3DO Company +123a Visicom Laboratories, Inc. +123b Seeq Technology, Inc. +123c Century Systems, Inc. +123d Engineering Design Team, Inc. + 0000 EasyConnect 8/32 + 0002 EasyConnect 8/64 + 0003 EasyIO +123e Simutech, Inc. +# nee C-Cube Microsystems / acquired by Magnum Semiconductor +123f LSI Logic + 00e4 MPEG + 8120 DVxplore Codec + 10de 01e1 NVTV PAL + 10de 01e2 NVTV NTSC + 10de 01e3 NVTV PAL + 10de 0248 NVTV NTSC + 10de 0249 NVTV PAL + 11bd 0006 DV500 E4 + 11bd 000a DV500 E4 + 11bd 000f DV500 E4 + 1809 0016 Emuzed MAUI-III PCI PVR FM TV + 8888 Cinemaster C 3.0 DVD Decoder + 1002 0001 Cinemaster C 3.0 DVD Decoder + 1002 0002 Cinemaster C 3.0 DVD Decoder + 1328 0001 Cinemaster C 3.0 DVD Decoder +1240 Marathon Technologies Corp. +1241 DSC Communications +# Formerly Jaycor Networks, Inc. +1242 JNI Corporation + 1560 JNIC-1560 PCI-X Fibre Channel Controller + 1242 6562 FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter + 1242 656a FCX-6562 PCI-X Fibre Channel Adapter + 4643 FCI-1063 Fibre Channel Adapter + 6562 FCX2-6562 Dual Channel PCI-X Fibre Channel Adapter + 656a FCX-6562 PCI-X Fibre Channel Adapter +1243 Delphax +# Audio-Visuelles Marketing und Computersysteme +1244 AVM GmbH + 0700 B1 ISDN + 0800 C4 ISDN + 0a00 A1 ISDN [Fritz] + 1244 0a00 FRITZ!Card ISDN Controller + 0e00 Fritz!Card PCI v2.0 ISDN + 0e80 Fritz!Card PCI v2.1 ISDN + 1244 0e00 PSB 3100F (AVM KAFKA) [Fritz!Card PCI v2.1] + 1100 C2 ISDN + 1200 T1 ISDN + 2700 Fritz!Card DSL SL + 2900 Fritz!Card DSL v2.0 +1245 A.P.D., S.A. +1246 Dipix Technologies, Inc. +1247 Xylon Research, Inc. +1248 Central Data Corporation +1249 Samsung Electronics Co., Ltd. +124a AEG Electrocom GmbH +124b SBS/Greenspring Modular I/O + 0040 PCI-40A or cPCI-200 Quad IndustryPack carrier + 124b 9080 PCI9080 Bridge +124c Solitron Technologies, Inc. +124d Stallion Technologies, Inc. + 0000 EasyConnection 8/32 + 0002 EasyConnection 8/64 + 0003 EasyIO + 0004 EasyConnection/RA +124e Cylink +124f Infortrend Technology, Inc. + 0041 IFT-2000 Series RAID Controller +1250 Hitachi Microcomputer System Ltd +1251 VLSI Solutions Oy +1253 Guzik Technical Enterprises +1254 Linear Systems Ltd. + 0065 DVB Master FD + 007c DVB Master Quad/o +1255 Optibase Ltd + 1110 MPEG Forge + 1210 MPEG Fusion + 2110 VideoPlex + 2120 VideoPlex CC + 2130 VideoQuest +1256 Perceptive Solutions, Inc. + 4201 PCI-2220I + 4401 PCI-2240I + 5201 PCI-2000 +1257 Vertex Networks, Inc. +1258 Gilbarco, Inc. +# nee Allied Telesyn International +1259 Allied Telesis + 2560 AT-2560 Fast Ethernet Adapter (i82557B) + 2801 AT-2801FX (RTL-8139) + a117 RTL81xx Fast Ethernet + a11e RTL81xx Fast Ethernet + a120 21x4x DEC-Tulip compatible 10/100 Ethernet +125a ABB Power Systems +125b Asix Electronics Corporation + 1400 AX88141 Fast Ethernet Controller + 1186 1100 AX8814X Based PCI Fast Ethernet Adapter +125c Aurora Technologies, Inc. + 0101 Saturn 4520P + 0640 Aries 16000P +125d ESS Technology + 0000 ES336H Fax Modem (Early Model) + 1948 ES1948 Maestro-1 + 1968 ES1968 Maestro 2 + 1028 0085 ES1968 Maestro-2 PCI + 1033 8051 ES1968 Maestro-2 Audiodrive + 1969 ES1938/ES1946/ES1969 Solo-1 Audiodrive + 1014 0166 ES1969 SOLO-1 AudioDrive on IBM Aptiva Mainboard + 125d 8888 Solo-1 Audio Adapter + 125d 8898 ES1938S TTSOLO1-SL [TerraTec 128i PCI] + 153b 111b Terratec 128i PCI + 1978 ES1978 Maestro 2E + 0e11 b112 Armada M700/E500 + 1033 803c ES1978 Maestro-2E Audiodrive + 1033 8058 ES1978 Maestro-2E Audiodrive + 1092 4000 Monster Sound MX400 + 1179 0001 ES1978 Maestro-2E Audiodrive + 1988 ES1988 Allegro-1 + 0e11 0098 Evo N600c + 1092 4100 Sonic Impact S100 + 125d 0431 Allegro AudioDrive + 125d 1988 ESS Allegro-1 Audiodrive + 125d 1998 Allegro AudioDrive + 125d 1999 Allegro-1 AudioDrive + 1989 ESS Modem + 125d 1989 ESS Modem + 1998 ES1983S Maestro-3i PCI Audio Accelerator + 1028 00b1 Latitude C600 + 1028 00e5 Latitude C810 + 1028 00e6 ES1983S Maestro-3i (Dell Inspiron 8100) + 1999 ES1983S Maestro-3i PCI Modem Accelerator + 199a ES1983S Maestro-3i PCI Audio Accelerator + 199b ES1983S Maestro-3i PCI Modem Accelerator + 2808 ES336H Fax Modem (Later Model) + 2838 ES2838/2839 SuperLink Modem + 2898 ES2898 Modem + 125d 0424 ES56-PI Data Fax Modem + 125d 0425 ES56T-PI Data Fax Modem + 125d 0426 ES56V-PI Data Fax Modem + 125d 0427 VW-PI Data Fax Modem + 125d 0428 ES56ST-PI Data Fax Modem + 125d 0429 ES56SV-PI Data Fax Modem + 147a c001 ES56-PI Data Fax Modem + 148d 1030 HCF WV-PI56 [ESS ES56-PI Data Fax Modem] + 14fe 0428 ES56-PI Data Fax Modem + 14fe 0429 ES56-PI Data Fax Modem +125e Specialvideo Engineering SRL +125f Concurrent Technologies, Inc. +# 4 x serial ports, 2 x printer ports + 2071 CC PMC/232 +# 4 x serial ports, 2 x printer ports + 2084 CC PMC/23P +# 4 x serial ports, RS422 + 2091 CC PMC/422 +1260 Intersil Corporation + 3872 ISL3872 [Prism 3] + 1468 0202 LAN-Express IEEE 802.11b Wireless LAN + 3873 ISL3874 [Prism 2.5]/ISL3872 [Prism 3] + 10cf 1169 MBH7WM01-8734 802.11b Wireless Mini PCI Card [ISL3874] + 1186 3501 DWL-520 Wireless PCI Adapter (rev A or B) [ISL3874] + 1186 3700 DWL-520 Wireless PCI Adapter (rev E1) [ISL3872] + 1385 4105 MA311 802.11b wireless adapter [ISL3874] + 1668 0414 HWP01170-01 802.11b PCI Wireless Adapter + 16a5 1601 AIR.mate PC-400 PCI Wireless LAN Adapter + 1737 3874 WMP11 v1 802.11b Wireless-B PCI Adapter [ISL3874] + 4033 7033 PCW200 802.11b Wireless PCI Adapter [ISL3874] + 8086 2510 M3AWEB Wireless 802.11b MiniPCI Adapter + 8086 2513 Wireless 802.11b MiniPCI Adapter + 3877 ISL3877 [Prism Indigo] + 3886 ISL3886 [Prism Javelin/Prism Xbow] + 17cf 0037 XG-901 and clones Wireless Adapter + 3890 ISL3890 [Prism GT/Prism Duette]/ISL3886 [Prism Javelin/Prism Xbow] + 10b8 2802 SMC2802W V1 Wireless PCI Adapter [ISL3890] + 10b8 2835 SMC2835W Wireless Cardbus Adapter + 10b8 a835 SMC2835W V2 Wireless Cardbus Adapter + 1113 4203 WN4201B + 1113 8201 T-Com T-Sinus 154pcicard Wireless PCI Adapter + 1113 b301 T-Sinus 154card Cardbus + 1113 ee03 SMC2802W V2 Wireless PCI Adapter [ISL3886] + 1113 ee08 SMC2835W V3 EU Wireless Cardbus Adapter + 1186 3202 DWL-G650 A1 Wireless Adapter + 1259 c104 CG-WLCB54GT Wireless Adapter + 1260 0000 WG511 v1 54 Mbps Wireless PC Card + 1385 4800 WG511 v2/v3 54 Mbps Wireless PC Card + 16a5 1605 ALLNET ALL0271 Wireless PCI Adapter + 17cf 0014 XG-600 and clones Wireless Adapter + 17cf 0020 XG-900 and clones Wireless Adapter + 187e 3403 G-110 802.11g Wireless Cardbus Adapter + 8130 HMP8130 NTSC/PAL Video Decoder + 8131 HMP8131 NTSC/PAL Video Decoder +# This is probably more likely a HW fault, but I am keeping it for now --mj + ffff ISL3886IK + 1260 0000 Senao 3054MP+ (J) mini-PCI WLAN 802.11g adapter +1261 Matsushita-Kotobuki Electronics Industries, Ltd. +1262 ES Computer Company, Ltd. +1263 Sonic Solutions +1264 Aval Nagasaki Corporation +1265 Casio Computer Co., Ltd. +1266 Microdyne Corporation + 0001 NE10/100 Adapter (i82557B) + 1910 NE2000Plus (RT8029) Ethernet Adapter + 1266 1910 NE2000Plus Ethernet Adapter +1267 S. A. Telecommunications + 5352 PCR2101 + 5a4b Telsat Turbo +1268 Tektronix +1269 Thomson-CSF/TTM +126a Lexmark International, Inc. +126b Adax, Inc. +126c Northern Telecom + 1211 10/100BaseTX [RTL81xx] + 126c 802.11b Wireless Ethernet Adapter +126d Splash Technology, Inc. +126e Sumitomo Metal Industries, Ltd. +126f Silicon Motion, Inc. + 0501 SM501 VoyagerGX Rev. AA + 0510 SM501 VoyagerGX Rev. B + 0710 SM710 LynxEM + 0712 SM712 LynxEM+ + 0718 SM718 LynxSE+ + 0720 SM720 Lynx3DM + 0730 SM731 Cougar3DR + 0750 SM750 + 0810 SM810 LynxE + 0811 SM811 LynxE + 0820 SM820 Lynx3D + 0910 SM910 +1270 Olympus Optical Co., Ltd. +1271 GW Instruments +1272 Telematics International +1273 Hughes Network Systems + 0002 DirecPC +1274 Ensoniq + 1171 ES1373 / Creative Labs CT5803 [AudioPCI] + 1371 ES1371/ES1373 / Creative Labs CT2518 + 0e11 0024 AudioPCI on Motherboard Compaq Deskpro + 0e11 b1a7 ES1371, ES1373 AudioPCI + 1033 80ac ES1371, ES1373 AudioPCI + 1042 1854 Tazer + 107b 8054 Tabor2 + 1274 1371 Audio PCI 64V/128/5200 / Creative CT4810/CT5803/CT5806 [Sound Blaster PCI] + 1274 8001 CT4751 board + 1462 6470 ES1371, ES1373 AudioPCI On Motherboard MS-6147 1.1A + 1462 6560 ES1371, ES1373 AudioPCI On Motherboard MS-6156 1.10 + 1462 6630 ES1371, ES1373 AudioPCI On Motherboard MS-6163BX 1.0A + 1462 6631 ES1371, ES1373 AudioPCI On Motherboard MS-6163VIA 1.0A + 1462 6632 ES1371, ES1373 AudioPCI On Motherboard MS-6163BX 2.0A + 1462 6633 ES1371, ES1373 AudioPCI On Motherboard MS-6163VIA 2.0A + 1462 6820 ES1371, ES1373 AudioPCI On Motherboard MS-6182 1.00 + 1462 6822 ES1371, ES1373 AudioPCI On Motherboard MS-6182 1.00A + 1462 6830 ES1371, ES1373 AudioPCI On Motherboard MS-6183 1.00 + 1462 6880 ES1371, ES1373 AudioPCI On Motherboard MS-6188 1.00 + 1462 6900 ES1371, ES1373 AudioPCI On Motherboard MS-6190 1.00 + 1462 6910 ES1371, ES1373 AudioPCI On Motherboard MS-6191 + 1462 6930 ES1371, ES1373 AudioPCI On Motherboard MS-6193 + 1462 6990 ES1371, ES1373 AudioPCI On Motherboard MS-6199BX 2.0A + 1462 6991 ES1371, ES1373 AudioPCI On Motherboard MS-6199VIA 2.0A + 14a4 2077 ES1371, ES1373 AudioPCI On Motherboard KR639 + 14a4 2105 ES1371, ES1373 AudioPCI On Motherboard MR800 + 14a4 2107 ES1371, ES1373 AudioPCI On Motherboard MR801 + 14a4 2172 ES1371, ES1373 AudioPCI On Motherboard DR739 + 1509 9902 ES1371, ES1373 AudioPCI On Motherboard KW11 + 1509 9903 ES1371, ES1373 AudioPCI On Motherboard KW31 + 1509 9904 ES1371, ES1373 AudioPCI On Motherboard KA11 + 1509 9905 ES1371, ES1373 AudioPCI On Motherboard KC13 + 152d 8801 ES1371, ES1373 AudioPCI On Motherboard CP810E + 152d 8802 ES1371, ES1373 AudioPCI On Motherboard CP810 + 152d 8803 ES1371, ES1373 AudioPCI On Motherboard P3810E + 152d 8804 ES1371, ES1373 AudioPCI On Motherboard P3810-S + 152d 8805 ES1371, ES1373 AudioPCI On Motherboard P3820-S + 270f 2001 ES1371, ES1373 AudioPCI On Motherboard 6CTR + 270f 2200 ES1371, ES1373 AudioPCI On Motherboard 6WTX + 270f 3000 ES1371, ES1373 AudioPCI On Motherboard 6WSV + 270f 3100 ES1371, ES1373 AudioPCI On Motherboard 6WIV2 + 270f 3102 ES1371, ES1373 AudioPCI On Motherboard 6WIV + 270f 7060 ES1371, ES1373 AudioPCI On Motherboard 6ASA2 + 8086 4249 ES1371, ES1373 AudioPCI On Motherboard BI440ZX + 8086 424c ES1371, ES1373 AudioPCI On Motherboard BL440ZX + 8086 425a ES1371, ES1373 AudioPCI On Motherboard BZ440ZX + 8086 4341 ES1371, ES1373 AudioPCI On Motherboard Cayman + 8086 4343 ES1371, ES1373 AudioPCI On Motherboard Cape Cod + 8086 4541 D815EEA Motherboard + 8086 4649 ES1371, ES1373 AudioPCI On Motherboard Fire Island + 8086 464a ES1371, ES1373 AudioPCI On Motherboard FJ440ZX + 8086 4d4f ES1371, ES1373 AudioPCI On Motherboard Montreal + 8086 4f43 ES1371, ES1373 AudioPCI On Motherboard OC440LX + 8086 5243 ES1371, ES1373 AudioPCI On Motherboard RC440BX + 8086 5352 ES1371, ES1373 AudioPCI On Motherboard SunRiver + 8086 5643 ES1371, ES1373 AudioPCI On Motherboard Vancouver + 8086 5753 ES1371, ES1373 AudioPCI On Motherboard WS440BX + 5000 ES1370 [AudioPCI] + 5880 5880B / Creative Labs CT5880 + 1274 2000 Creative CT4810 [Sound Blaster AudioPCI 128] + 1274 2003 Creative SoundBlaster AudioPCI 128 + 1274 5880 Creative CT4750 [Sound Blaster PCI 128] + 1274 8001 Sound Blaster 16PCI 4.1ch + 1458 a000 5880 AudioPCI On Motherboard 6OXET + 1462 6880 5880 AudioPCI On Motherboard MS-6188 1.00 + 270f 2001 5880 AudioPCI On Motherboard 6CTR + 270f 2200 5880 AudioPCI On Motherboard 6WTX + 270f 7040 5880 AudioPCI On Motherboard 6ATA4 + 8001 CT5880 [AudioPCI] + 8002 5880A [AudioPCI] +1275 Network Appliance Corporation +1276 Switched Network Technologies, Inc. +1277 Comstream +1278 Transtech Parallel Systems Ltd. + 0701 TPE3/TM3 PowerPC Node + 0710 TPE5 PowerPC PCI board + 1100 PMC-FPGA02 + 1101 TS-C43 card with 4 ADSP-TS101 processors +1279 Transmeta Corporation + 0060 TM8000 Northbridge + 0061 TM8000 AGP bridge + 0295 Northbridge + 0395 LongRun Northbridge + 0396 SDRAM controller + 0397 BIOS scratchpad +127a Rockwell International + 1002 HCF 56k Data/Fax Modem + 1092 094c SupraExpress 56i PRO [Diamond SUP2380] + 122d 4002 HPG / MDP3858-U + 122d 4005 MDP3858-E + 122d 4007 MDP3858-A/-NZ + 122d 4012 MDP3858-SA + 122d 4017 MDP3858-W + 122d 4018 MDP3858-W + 127a 1002 Rockwell 56K D/F HCF Modem + 1003 HCF 56k Data/Fax Modem + 0e11 b0bc 229-DF Zephyr + 0e11 b114 229-DF Cheetah + 1033 802b 229-DF + 13df 1003 PCI56RX Modem + 13e0 0117 IBM + 13e0 0147 IBM F-1156IV+/R3 Spain V.90 Modem + 13e0 0197 IBM + 13e0 01c7 IBM F-1156IV+/R3 WW V.90 Modem + 13e0 01f7 IBM + 1436 1003 IBM + 1436 1103 IBM 5614PM3G V.90 Modem + 1436 1602 Compaq 229-DF Ducati + 1004 HCF 56k Data/Fax/Voice Modem + 1048 1500 MicroLink 56k Modem + 10cf 1059 Fujitsu 229-DFRT + 1005 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + 1005 127a AOpen FM56-P + 1033 8029 229-DFSV + 1033 8054 Modem + 10cf 103c Fujitsu + 10cf 1055 Fujitsu 229-DFSV + 10cf 1056 Fujitsu 229-DFSV + 122d 4003 MDP3858SP-U + 122d 4006 Packard Bell MDP3858V-E + 122d 4008 MDP3858SP-A/SP-NZ + 122d 4009 MDP3858SP-E + 122d 4010 MDP3858V-U + 122d 4011 MDP3858SP-SA + 122d 4013 MDP3858V-A/V-NZ + 122d 4015 MDP3858SP-W + 122d 4016 MDP3858V-W + 122d 4019 MDP3858V-SA + 13df 1005 PCI56RVP Modem + 13e0 0187 IBM + 13e0 01a7 IBM + 13e0 01b7 IBM DF-1156IV+/R3 Spain V.90 Modem + 13e0 01d7 IBM DF-1156IV+/R3 WW V.90 Modem + 1436 1005 IBM + 1436 1105 IBM + 1437 1105 IBM 5614PS3G V.90 Modem + 1022 HCF 56k Modem + 1436 1303 M3-5614PM3G V.90 Modem + 1023 HCF 56k Data/Fax Modem + 122d 4020 Packard Bell MDP3858-WE + 122d 4023 MDP3858-UE + 13e0 0247 IBM F-1156IV+/R6 Spain V.90 Modem + 13e0 0297 IBM + 13e0 02c7 IBM F-1156IV+/R6 WW V.90 Modem + 1436 1203 IBM + 1436 1303 IBM + 1024 HCF 56k Data/Fax/Voice Modem + 1025 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + 10cf 106a Fujitsu 235-DFSV + 122d 4021 Packard Bell MDP3858V-WE + 122d 4022 MDP3858SP-WE + 122d 4024 MDP3858V-UE + 122d 4025 MDP3858SP-UE + 1026 HCF 56k PCI Speakerphone Modem + 1032 HCF 56k Modem + 1033 HCF 56k Modem + 1034 HCF 56k Modem + 1035 HCF 56k PCI Speakerphone Modem + 1036 HCF 56k Modem + 1085 HCF 56k Volcano PCI Modem + 2004 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + 2005 HCF 56k Data/Fax Modem + 104d 8044 229-DFSV + 104d 8045 229-DFSV + 104d 8055 PBE/Aztech 235W-DFSV + 104d 8056 235-DFSV + 104d 805a Modem + 104d 805f Modem + 104d 8074 Modem + 2013 HSF 56k Data/Fax Modem + 1179 0001 Modem + 1179 ff00 Modem + 2014 HSF 56k Data/Fax/Voice Modem + 10cf 1057 Fujitsu Citicorp III + 122d 4050 MSP3880-U + 122d 4055 MSP3880-W + 2015 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + 10cf 1063 Fujitsu + 10cf 1064 Fujitsu + 1468 2015 Fujitsu + 2016 HSF 56k Data/Fax/Voice/Spkp Modem + 122d 4051 MSP3880V-W + 122d 4052 MSP3880SP-W + 122d 4054 MSP3880V-U + 122d 4056 MSP3880SP-U + 122d 4057 MSP3880SP-A + 4311 Riptide HSF 56k PCI Modem + 127a 4311 Ring Modular? Riptide HSF RT HP Dom + 13e0 0210 HP-GVC + 4320 Riptide PCI Audio Controller + 1235 4320 Riptide PCI Audio Controller + 4321 Riptide HCF 56k PCI Modem + 1235 4321 Hewlett Packard DF + 1235 4324 Hewlett Packard DF + 13e0 0210 Hewlett Packard DF + 144d 2321 Riptide + 4322 Riptide PCI Game Controller + 1235 4322 Riptide PCI Game Controller + 8234 RapidFire 616X ATM155 Adapter + 108d 0022 RapidFire 616X ATM155 Adapter + 108d 0027 RapidFire 616X ATM155 Adapter +127b Pixera Corporation +127c Crosspoint Solutions, Inc. +127d Vela Research +127e Winnov, L.P. + 0010 Videum 1000 Plus +127f Fujifilm +1280 Photoscript Group Ltd. +1281 Yokogawa Electric Corporation +1282 Davicom Semiconductor, Inc. + 6585 DM562P V90 Modem + 9009 Ethernet 100/10 MBit + 9100 21x4x DEC-Tulip compatible 10/100 Ethernet + 9102 21x4x DEC-Tulip compatible 10/100 Ethernet +# Subsystem ID is main ID reveresed. + 0291 8212 DM9102A (DM9102AE, SM9102AF) Ethernet 100/10 MBit + 9132 Ethernet 100/10 MBit +1283 Integrated Technology Express, Inc. + 673a IT8330G + 8152 IT8152F/G Advanced RISC-to-PCI Companion Chip + 8211 ITE 8211F Single Channel UDMA 133 + 1043 8138 P5GD1-VW Mainboard + 8212 IT8212 Dual channel ATA RAID controller + 1283 0001 IT/ITE8212 Dual channel ATA RAID controller + 8213 IT8213 IDE Controller + 1458 b000 GA-EG45M-DS2H Mainboard + 8330 IT8330G + 8872 IT887xF PCI to ISA I/O chip with SMB, GPIO, Serial or Parallel Port + 8888 IT8888F/G PCI to ISA Bridge with SMB [Golden Gate] + 8889 IT8889F PCI to ISA Bridge + 8892 IT8892E PCIe to PCI Bridge + 8893 IT8893E PCIe to PCI Bridge + e886 IT8330G +1284 Sahara Networks, Inc. +1285 Platform Technologies, Inc. + 0100 AGOGO sound chip (aka ESS Maestro 1) +1286 Mazet GmbH +1287 M-Pact, Inc. + 001e LS220D DVD Decoder + 001f LS220C DVD Decoder +1288 Timestep Corporation +1289 AVC Technology, Inc. +128a Asante Technologies, Inc. +128b Transwitch Corporation +128c Retix Corporation +128d G2 Networks, Inc. + 0021 ATM155 Adapter +128e Hoontech Corporation/Samho Multi Tech Ltd. + 0008 ST128 WSS/SB + 0009 ST128 SAM9407 + 000a ST128 Game Port + 000b ST128 MPU Port + 000c ST128 Ctrl Port +128f Tateno Dennou, Inc. +1290 Sord Computer Corporation +1291 NCS Computer Italia +1292 Tritech Microelectronics Inc + fc02 Pyramid3D TR25202 +1293 Media Reality Technology +1294 Rhetorex, Inc. +1295 Imagenation Corporation + 0800 PXR800 + 1000 PXD1000 +1296 Kofax Image Products +1297 Holco Enterprise Co, Ltd/Shuttle Computer +1298 Spellcaster Telecommunications Inc. +1299 Knowledge Technology Lab. +129a VMetro, inc. + 0615 PBT-615 PCI-X Bus Analyzer + 1100 PMC-FPGA05 + 1106 XMC-FPGA05F, PCI interface + 1107 XMC-FPGA05F, PCIe interface + 1108 XMC-FPGA05D, PCI interface + 1109 XMC-FPGA05D, PCIe interface +129b Image Access +129c Jaycor +129d Compcore Multimedia, Inc. +129e Victor Company of Japan, Ltd. +129f OEC Medical Systems, Inc. +12a0 Allen-Bradley Company +12a1 Simpact Associates, Inc. +12a2 Newgen Systems Corporation +12a3 Lucent Technologies + 8105 T8105 H100 Digital Switch +12a4 NTT Electronics Corporation +12a5 Vision Dynamics Ltd. +12a6 Scalable Networks, Inc. +12a7 AMO GmbH +12a8 News Datacom +12a9 Xiotech Corporation +12aa SDL Communications, Inc. +12ab YUAN High-Tech Development Co., Ltd. + 0000 MPG160/Kuroutoshikou ITVC15-STVLP + 0002 AU8830 [Vortex2] Based Sound Card With A3D Support + 0003 T507 (DVB-T) TV tuner/capture device + 2300 Club-3D Zap TV2100 + 3000 MPG-200C PCI DVD Decoder Card + 4789 MPC788 MiniPCI Hybrid TV Tuner + fff3 MPG600/Kuroutoshikou ITVC16-STVLP + ffff MPG600/Kuroutoshikou ITVC16-STVLP +12ac Measurex Corporation +12ad Multidata GmbH +12ae Alteon Networks Inc. + 0001 AceNIC Gigabit Ethernet + 1014 0104 Gigabit Ethernet-SX PCI Adapter + 12ae 0001 Gigabit Ethernet-SX (Universal) + 0002 AceNIC Gigabit Ethernet (Copper) + 10a9 8002 Acenic Gigabit Ethernet + 12ae 0002 Gigabit Ethernet-T (3C986-T) + 00fa Farallon PN9100-T Gigabit Ethernet +12af TDK USA Corp +12b0 Jorge Scientific Corp +12b1 GammaLink +12b2 General Signal Networks +12b3 Inter-Face Co Ltd +12b4 FutureTel Inc +12b5 Granite Systems Inc. +12b6 Natural Microsystems +12b7 Cognex Corporation +12b8 Korg +# Nee US Robotics +12b9 3Com Corp, Modem Division + 1006 WinModem + 12b9 005c USR 56k Internal Voice WinModem (Model 3472) + 12b9 005e USR 56k Internal WinModem (Models 662975) + 12b9 0062 USR 56k Internal Voice WinModem (Model 662978) + 12b9 0068 USR 56k Internal Voice WinModem (Model 5690) + 12b9 007a USR 56k Internal Voice WinModem (Model 662974) + 12b9 007f USR 56k Internal WinModem (Models 5698, 5699) + 12b9 0080 USR 56k Internal WinModem (Models 2975, 3528) + 12b9 0081 USR 56k Internal Voice WinModem (Models 2974, 3529) + 12b9 0091 USR 56k Internal Voice WinModem (Model 2978) + 1007 USR 56k Internal WinModem + 12b9 00a3 USR 56k Internal WinModem (Model 3595) + 12b9 00c4 U.S. Robotics V.92 Voice Faxmodem (2884A/B/C) + 1008 56K FaxModem Model 5610 + 12b9 00a2 USR 56k Internal FAX Modem (Model 2977) + 12b9 00aa USR 56k Internal Voice Modem (Model 2976) + 12b9 00ab USR 56k Internal Voice Modem (Model 5609) + 12b9 00ac USR 56k Internal Voice Modem (Model 3298) + 12b9 00ad USR 56k Internal FAX Modem (Model 5610) + 12b9 00d3 USR 56K Internal V92 FAX Modem (Model 5610) + 12b9 baba USR 56K Internal Voice Modem 3CP3298-DEL (Model 5601) [Hawk] +12ba BittWare, Inc. +12bb Nippon Unisoft Corporation +12bc Array Microsystems +12bd Computerm Corp. +12be Anchor Chips Inc. + 3041 AN3041Q CO-MEM + 3042 AN3042Q CO-MEM Lite + 12be 3042 Anchor Chips Lite Evaluation Board +12bf Fujifilm Microdevices +12c0 Infimed +12c1 GMM Research Corp +12c2 Mentec Limited +12c3 Holtek Microelectronics Inc + 0058 PCI NE2K Ethernet + 5598 PCI NE2K Ethernet +12c4 Connect Tech Inc + 0001 Blue HEAT/PCI 8 (RS232/CL/RJ11) + 0002 Blue HEAT/PCI 4 (RS232) + 0003 Blue HEAT/PCI 2 (RS232) + 0004 Blue HEAT/PCI 8 (UNIV, RS485) + 0005 Blue HEAT/PCI 4+4/6+2 (UNIV, RS232/485) + 0006 Blue HEAT/PCI 4 (OPTO, RS485) + 0007 Blue HEAT/PCI 2+2 (RS232/485) + 0008 Blue HEAT/PCI 2 (OPTO, Tx, RS485) + 0009 Blue HEAT/PCI 2+6 (RS232/485) + 000a Blue HEAT/PCI 8 (Tx, RS485) + 000b Blue HEAT/PCI 4 (Tx, RS485) + 000c Blue HEAT/PCI 2 (20 MHz, RS485) + 000d Blue HEAT/PCI 2 PTM + 0100 NT960/PCI + 0201 cPCI Titan - 2 Port + 0202 cPCI Titan - 4 Port + 0300 CTI PCI UART 2 (RS232) + 0301 CTI PCI UART 4 (RS232) + 0302 CTI PCI UART 8 (RS232) + 0310 CTI PCI UART 1+1 (RS232/485) + 0311 CTI PCI UART 2+2 (RS232/485) + 0312 CTI PCI UART 4+4 (RS232/485) + 0320 CTI PCI UART 2 + 0321 CTI PCI UART 4 + 0322 CTI PCI UART 8 + 0330 CTI PCI UART 2 (RS485) + 0331 CTI PCI UART 4 (RS485) + 0332 CTI PCI UART 8 (RS485) +12c5 Picture Elements Incorporated + 007e Imaging/Scanning Subsystem Engine + 007f Imaging/Scanning Subsystem Engine + 0081 PCIVST [Grayscale Thresholding Engine] + 0085 Video Simulator/Sender + 0086 THR2 Multi-scale Thresholder +12c6 Mitani Corporation +12c7 Dialogic Corp +# 12 Line, 6 port, CT-BUS/SC-BUS, loopstart FXO adaptor. + 0546 Springware D/120JCT-LS +# 24 Channel, 1 Port, CT-BUS/SC-BUS, T1/PRI adaptor. + 0647 Springware D/240JCT-T1 +# 4 Line, 4 port, CT-BUS/SC-BUS, loopstart FXO adaptor. Revision 01 + 0676 Springware D/41JCT-LS +# 48 Channel, 2 Port, CT-BUS/SC-BUS, T1/PRI adaptor. + 0685 Springware D/480JCT-2T1 +12c8 G Force Co, Ltd +12c9 Gigi Operations +12ca Integrated Computing Engines +12cb Antex Electronics Corporation + 0027 SC4 (StudioCard) + 002e StudioCard 2000 +12cc Pluto Technologies International +12cd Aims Lab +12ce Netspeed Inc. +12cf Prophet Systems, Inc. +12d0 GDE Systems, Inc. +12d1 PSITech +12d2 NVidia / SGS Thomson (Joint Venture) + 0008 NV1 + 0009 DAC64 + 0018 Riva128 + 1048 0c10 VICTORY Erazor + 107b 8030 STB Velocity 128 + 1092 0350 Viper V330 + 1092 1092 Viper V330 + 10b4 1b1b STB Velocity 128 + 10b4 1b1d STB Velocity 128 + 10b4 1b1e STB Velocity 128, PAL TV-Out + 10b4 1b20 STB Velocity 128 Sapphire + 10b4 1b21 STB Velocity 128 + 10b4 1b22 STB Velocity 128 AGP, NTSC TV-Out + 10b4 1b23 STB Velocity 128 AGP, PAL TV-Out + 10b4 1b27 STB Velocity 128 DVD + 10b4 1b88 MVP Pro 128 + 10b4 222a STB Velocity 128 AGP + 10b4 2230 STB Velocity 128 + 10b4 2232 STB Velocity 128 + 10b4 2235 STB Velocity 128 AGP + 2a15 54a3 3DVision-SAGP / 3DexPlorer 3000 + 0019 Riva128ZX + 0020 TNT + 0028 TNT2 + 0029 UTNT2 + 002c VTNT2 + 00a0 ITNT2 +12d3 Vingmed Sound A/S +12d4 Ulticom (Formerly DGM&S) + 0200 T1 Card +12d5 Equator Technologies Inc + 0003 BSP16 + 1000 BSP15 +12d6 Analogic Corp +12d7 Biotronic SRL +# acquired by Diodes Inc. +12d8 Pericom Semiconductor + 01a7 7C21P100 2-port PCI-X to PCI-X Bridge + 2304 PI7C9X2G304 EL/SL PCIe2 3-Port/4-Lane Packet Switch + 2404 PI7C9X2G404 EL/SL PCIe2 4-Port/4-Lane Packet Switch + 2608 PI7C9X2G608GP PCIe2 6-Port/8-Lane Packet Switch + 400a PI7C9X442SL PCI Express Bridge Port + 400e PI7C9X442SL USB OHCI Controller + 400f PI7C9X442SL USB EHCI Controller + 71e2 PI7C7300A/PI7C7300D PCI-to-PCI Bridge + 71e3 PI7C7300A/PI7C7300D PCI-to-PCI Bridge (Secondary Bus 2) + 8140 PI7C8140A PCI-to-PCI Bridge + 8148 PI7C8148A/PI7C8148B PCI-to-PCI Bridge + 8150 PCI to PCI Bridge + 8152 PI7C8152A/PI7C8152B/PI7C8152BI PCI-to-PCI Bridge + 8154 PI7C8154A/PI7C8154B/PI7C8154BI PCI-to-PCI Bridge + e110 PI7C9X110 PCI Express to PCI bridge + 1775 11cc CC11/CL11 CompactPCI Bridge + e111 PI7C9X111SL PCIe-to-PCI Reversible Bridge + e130 PCI Express to PCI-XPI7C9X130 PCI-X Bridge +12d9 Aculab PLC + 0002 PCI Prosody + 0004 cPCI Prosody + 0005 Aculab E1/T1 PCI card + 1078 Prosody X class e1000 device + 12d9 000d Prosody X PCI + 12d9 000e Prosody X cPCI +12da True Time Inc. +12db Annapolis Micro Systems, Inc +12dc Symicron Computer Communication Ltd. +12dd Management Graphics +12de Rainbow Technologies + 0200 CryptoSwift CS200 +12df SBS Technologies Inc +12e0 Chase Research + 0010 ST16C654 Quad UART + 0020 ST16C654 Quad UART + 0030 ST16C654 Quad UART +12e1 Nintendo Co, Ltd +12e2 Datum Inc. Bancomm-Timing Division +12e3 Imation Corp - Medical Imaging Systems +12e4 Brooktrout Technology Inc +12e5 Apex Semiconductor Inc +12e6 Cirel Systems +12e7 Sunsgroup Corporation +12e8 Crisc Corp +12e9 GE Spacenet +12ea Zuken +12eb Aureal Semiconductor + 0001 Vortex 1 + 104d 8036 AU8820 Vortex Digital Audio Processor + 1092 2000 Sonic Impact A3D + 1092 2100 Sonic Impact A3D + 1092 2110 Sonic Impact A3D + 1092 2200 Sonic Impact A3D + 122d 1002 AU8820 Vortex Digital Audio Processor + 12eb 0001 AU8820 Vortex Digital Audio Processor + 5053 3355 Montego + 50b2 1111 XLerate + 0002 Vortex 2 + 104d 8049 AU8830 Vortex 3D Digital Audio Processor + 104d 807b AU8830 Vortex 3D Digital Audio Processor + 1092 3000 Monster Sound II + 1092 3001 Monster Sound II + 1092 3002 Monster Sound II + 1092 3003 Monster Sound II + 1092 3004 Monster Sound II + 12eb 0002 AU8830 Vortex 3D Digital Audio Processor + 12eb 0088 AU8830 Vortex 3D Digital Audio Processor + 144d 3510 AU8830 Vortex 3D Digital Audio Processor + 5053 3356 Montego II + 0003 AU8810 Vortex Digital Audio Processor + 104d 8049 AU8810 Vortex Digital Audio Processor + 104d 8077 AU8810 Vortex Digital Audio Processor + 109f 1000 AU8810 Vortex Digital Audio Processor + 12eb 0003 AU8810 Vortex Digital Audio Processor + 1462 6780 AU8810 Vortex Digital Audio Processor + 14a4 2073 AU8810 Vortex Digital Audio Processor + 14a4 2091 AU8810 Vortex Digital Audio Processor + 14a4 2104 AU8810 Vortex Digital Audio Processor + 14a4 2106 AU8810 Vortex Digital Audio Processor + 8803 Vortex 56k Software Modem + 12eb 8803 Vortex 56k Software Modem +12ec 3A International, Inc. +12ed Optivision Inc. +12ee Orange Micro +12ef Vienna Systems +12f0 Pentek +12f1 Sorenson Vision Inc +12f2 Gammagraphx, Inc. +12f3 Radstone Technology +12f4 Megatel +12f5 Forks +12f6 Dawson France +12f7 Cognex +12f8 Electronic Design GmbH + 0002 VideoMaker +12f9 Four Fold Ltd +12fb Spectrum Signal Processing + 0001 PMC-MAI + 00f5 F5 Dakar + 02ad PMC-2MAI + 2adc ePMC-2ADC + 3100 PRO-3100 + 3500 PRO-3500 + 4d4f Modena + 8120 ePMC-8120 + da62 Daytona C6201 PCI (Hurricane) + db62 Ingliston XBIF + dc62 Ingliston PLX9054 + dd62 Ingliston JTAG/ISP + eddc ePMC-MSDDC + fa01 ePMC-FPGA +12fc Capital Equipment Corp +12fd I2S +12fe ESD Electronic System Design GmbH +12ff Lexicon +1300 Harman International Industries Inc +1302 Computer Sciences Corp +1303 Innovative Integration + 0030 X3-SDF 4-channel XMC acquisition board +1304 Juniper Networks +1305 Netphone, Inc +1306 Duet Technologies +# Nee ComputerBoards +1307 Measurement Computing + 0001 PCI-DAS1602/16 + 000b PCI-DIO48H + 000c PCI-PDISO8 + 000d PCI-PDISO16 + 000f PCI-DAS1200 + 0010 PCI-DAS1602/12 + 0014 PCI-DIO24H + 0015 PCI-DIO24H/CTR3 + 0016 PCI-DIO48H/CTR15 + 0017 PCI-DIO96H + 0018 PCI-CTR05 + 0019 PCI-DAS1200/JR + 001a PCI-DAS1001 + 001b PCI-DAS1002 + 001c PCI-DAS1602JR/16 + 001d PCI-DAS6402/16 + 001e PCI-DAS6402/12 + 001f PCI-DAS16/M1 + 0020 PCI-DDA02/12 + 0021 PCI-DDA04/12 + 0022 PCI-DDA08/12 + 0023 PCI-DDA02/16 + 0024 PCI-DDA04/16 + 0025 PCI-DDA08/16 + 0026 PCI-DAC04/12-HS + 0027 PCI-DAC04/16-HS + 0028 PCI-DIO24 + 0029 PCI-DAS08 + 002c PCI-INT32 + 0033 PCI-DUAL-AC5 + 0034 PCI-DAS-TC + 0035 PCI-DAS64/M1/16 + 0036 PCI-DAS64/M2/16 + 0037 PCI-DAS64/M3/16 + 004c PCI-DAS1000 + 004d PCI-QUAD04 + 0052 PCI-DAS4020/12 + 0053 PCIM-DDA06/16 + 0054 PCI-DIO96 + 005d PCI-DAS6023 + 005e PCI-DAS6025 + 005f PCI-DAS6030 + 0060 PCI-DAS6031 + 0061 PCI-DAS6032 + 0062 PCI-DAS6033 + 0063 PCI-DAS6034 + 0064 PCI-DAS6035 + 0065 PCI-DAS6040 + 0066 PCI-DAS6052 + 0067 PCI-DAS6070 + 0068 PCI-DAS6071 + 006f PCI-DAS6036 + 0070 PCI-DAC6702 + 0078 PCI-DAS6013 + 0079 PCI-DAS6014 + 0115 PCIe-DAS1602/16 +1308 Jato Technologies Inc. + 0001 NetCelerator Adapter + 1308 0001 NetCelerator Adapter +1309 AB Semiconductor Ltd +130a Mitsubishi Electric Microcomputer +130b Colorgraphic Communications Corp +130c Ambex Technologies, Inc +130d Accelerix Inc +130e Yamatake-Honeywell Co. Ltd +130f Advanet Inc +1310 Gespac +1311 Videoserver, Inc +1312 Acuity Imaging, Inc +1313 Yaskawa Electric Co. +1315 Wavesat +1316 Teradyne Inc +1317 ADMtek + 0981 21x4x DEC-Tulip compatible 10/100 Ethernet + 0985 NC100 Network Everywhere Fast Ethernet 10/100 + 1734 100c Scenic N300 ADMtek AN983 10/100 Mbps PCI Adapter + 1985 21x4x DEC-Tulip compatible 10/100 Ethernet + 1385 511a FA511 + 1395 2103 CB100-EZ (4-LED version) + 2850 HSP MicroModem 56 + 5120 ADM5120 OpenGate System-on-Chip + 8201 ADM8211 802.11b Wireless Interface + 10b8 2635 SMC2635W v1 802.11b Wireless Cardbus Adapter + 1317 8201 SMC2635W v2 802.11b Wireless Cardbus Adapter + 8211 ADM8211 802.11b Wireless Interface + 9511 21x4x DEC-Tulip compatible 10/100 Ethernet +1318 Packet Engines Inc. + 0911 GNIC-II PCI Gigabit Ethernet [Hamachi] +1319 Fortemedia, Inc + 0801 Xwave QS3000A [FM801] + 1319 1319 FM801 PCI Audio + 0802 Xwave QS3000A [FM801 game port] + 1319 1319 FM801 PCI Joystick + 1000 FM801 PCI Audio + 1001 FM801 PCI Joystick +131a Finisar Corp. +131c Nippon Electro-Sensory Devices Corp +131d Sysmic, Inc. +131e Xinex Networks Inc +131f Siig Inc + 1000 CyberSerial (1-port) 16550 + 1001 CyberSerial (1-port) 16650 + 1002 CyberSerial (1-port) 16850 + 1010 Duet 1S(16550)+1P + 1011 Duet 1S(16650)+1P + 1012 Duet 1S(16850)+1P + 1020 CyberParallel (1-port) + 1021 CyberParallel (2-port) + 1030 CyberSerial (2-port) 16550 + 1031 CyberSerial (2-port) 16650 + 1032 CyberSerial (2-port) 16850 + 1034 Trio 2S(16550)+1P + 1035 Trio 2S(16650)+1P + 1036 Trio 2S(16850)+1P + 1050 CyberSerial (4-port) 16550 + 1051 CyberSerial (4-port) 16650 + 1052 CyberSerial (4-port) 16850 + 2000 CyberSerial (1-port) 16550 + 2001 CyberSerial (1-port) 16650 + 2002 CyberSerial (1-port) 16850 + 2010 Duet 1S(16550)+1P + 2011 Duet 1S(16650)+1P + 2012 Duet 1S(16850)+1P + 2020 CyberParallel (1-port) + 2021 CyberParallel (2-port) + 2030 CyberSerial (2-port) 16550 + 131f 2030 PCI Serial Card + 2031 CyberSerial (2-port) 16650 + 2032 CyberSerial (2-port) 16850 + 2040 Trio 1S(16550)+2P + 2041 Trio 1S(16650)+2P + 2042 Trio 1S(16850)+2P + 2050 CyberSerial (4-port) 16550 + 2051 CyberSerial (4-port) 16650 + 2052 CyberSerial (4-port) 16850 + 2060 Trio 2S(16550)+1P + 2061 Trio 2S(16650)+1P + 2062 Trio 2S(16850)+1P + 2081 CyberSerial (8-port) ST16654 +1320 Crypto AG +1321 Arcobel Graphics BV +1322 MTT Co., Ltd +1323 Dome Inc +1324 Sphere Communications +1325 Salix Technologies, Inc +1326 Seachange international +1327 Voss scientific +1328 quadrant international +1329 Productivity Enhancement +132a Microcom Inc. +132b Broadband Technologies +132c Micrel Inc +132d Integrated Silicon Solution, Inc. +1330 MMC Networks +1331 RadiSys Corporation + 0030 ENP-2611 + 8200 82600 Host Bridge + 8201 82600 IDE + 8202 82600 USB + 8210 82600 PCI Bridge +1332 Micro Memory + 5415 MM-5415CN PCI Memory Module with Battery Backup + 5425 MM-5425CN PCI 64/66 Memory Module with Battery Backup + 6140 MM-6140D +1334 Redcreek Communications, Inc +1335 Videomail, Inc +1337 Third Planet Publishing +1338 BT Electronics +133a Vtel Corp +133b Softcom Microsystems +133c Holontech Corp +133d SS Technologies +133e Virtual Computer Corp +133f SCM Microsystems +1340 Atalla Corp +1341 Kyoto Microcomputer Co +1342 Promax Systems Inc +1343 Phylon Communications Inc +# nee Crucial Technology +1344 Micron Technology Inc + 5150 RealSSD P320h + 5151 RealSSD P320m + 5152 RealSSD P320s + 5153 RealSSD P325m + 5160 RealSSD P420h + 5161 RealSSD P420m + 5163 RealSSD P425m + 5180 9100 PRO NVMe SSD + 5181 9100 MAX NVMe SSD + 5190 9200 ECO NVMe SSD + 5191 9200 PRO NVMe SSD + 5192 9200 MAX NVMe SSD +1345 Arescom Inc +1347 Odetics +1349 Sumitomo Electric Industries, Ltd. +134a DTC Technology Corp. + 0001 Domex 536 + 0002 Domex DMX3194UP SCSI Adapter +134b ARK Research Corp. +134c Chori Joho System Co. Ltd +134d PCTel Inc + 2189 HSP56 MicroModem + 2486 2304WT V.92 MDC Modem + 7890 HSP MicroModem 56 + 134d 0001 PCT789 adapter + 7891 HSP MicroModem 56 + 134d 0001 HSP MicroModem 56 + 7892 HSP MicroModem 56 + 7893 HSP MicroModem 56 + 7894 HSP MicroModem 56 + 7895 HSP MicroModem 56 + 7896 HSP MicroModem 56 + 7897 HSP MicroModem 56 +134e CSTI +134f Algo System Co Ltd +1350 Systec Co. Ltd +1351 Sonix Inc +# nee Thales Idatys +1353 Vierling Communication SAS + 0002 Proserver + 0003 PCI-FUT + 0004 PCI-S0 + 0005 PCI-FUT-S0 +1354 Dwave System Inc +1355 Kratos Analytical Ltd +1356 The Logical Co +1359 Prisa Networks +135a Brain Boxes + 0a61 UC-324 [VELOCITY RS422/485] +135b Giganet Inc +135c Quatech Inc + 0010 QSC-100 + 0020 DSC-100 + 0030 DSC-200/300 + 0040 QSC-200/300 + 0050 ESC-100D + 0060 ESC-100M + 00f0 MPAC-100 Synchronous Serial Card (Zilog 85230) + 0170 QSCLP-100 + 0180 DSCLP-100 + 0190 SSCLP-100 + 01a0 QSCLP-200/300 + 01b0 DSCLP-200/300 + 01c0 SSCLP-200/300 + 0258 DSPSX-200/300 +135d ABB Network Partner AB +135e Sealevel Systems Inc + 5101 Route 56.PCI - Multi-Protocol Serial Interface (Zilog Z16C32) + 7101 Single Port RS-232/422/485/530 + 7201 Dual Port RS-232/422/485 Interface + 7202 Dual Port RS-232 Interface + 7401 Four Port RS-232 Interface + 7402 Four Port RS-422/485 Interface + 7801 Eight Port RS-232 Interface + 7804 Eight Port RS-232/422/485 Interface + 8001 8001 Digital I/O Adapter +135f I-Data International A-S +1360 Meinberg Funkuhren + 0101 PCI32 DCF77 Radio Clock + 0102 PCI509 DCF77 Radio Clock + 0103 PCI510 DCF77 Radio Clock + 0104 PCI511 DCF77 Radio Clock + 0105 PEX511 DCF77 Radio Clock (PCI Express) + 0106 PZF180PEX High Precision DCF77 Radio Clock (PCI Express) + 0201 GPS167PCI GPS Receiver + 0202 GPS168PCI GPS Receiver + 0203 GPS169PCI GPS Receiver + 0204 GPS170PCI GPS Receiver + 0205 GPS170PEX GPS Receiver (PCI Express) + 0206 GPS180PEX GPS Receiver (PCI Express) + 0207 GLN180PEX GPS/GLONASS receiver (PCI Express) + 0208 GPS180AMC GPS Receiver (PCI Express / MicroTCA / AdvancedMC) + 0209 GNS181PEX GPS/Galileo/GLONASS/BEIDOU receiver (PCI Express) + 0301 TCR510PCI IRIG Timecode Reader + 0302 TCR167PCI IRIG Timecode Reader + 0303 TCR511PCI IRIG Timecode Reader + 0304 TCR511PEX IRIG Timecode Reader (PCI Express) + 0305 TCR170PEX IRIG Timecode Reader (PCI Express) + 0306 TCR180PEX IRIG Timecode Reader (PCI Express) + 0501 PTP270PEX PTP/IEEE1588 slave card (PCI Express) + 0601 FRC511PEX Free Running Clock (PCI Express) +1361 Soliton Systems K.K. +1362 Fujifacom Corporation +1363 Phoenix Technology Ltd +1364 ATM Communications Inc +1365 Hypercope GmbH +1366 Teijin Seiki Co. Ltd +1367 Hitachi Zosen Corporation +1368 Skyware Corporation +1369 Digigram +136a High Soft Tech + 0004 HST Saphir VII mini PCI + 0007 HST Saphir III E MultiLink 4 + 0008 HST Saphir III E MultiLink 8 + 000a HST Saphir III E MultiLink 2 +136b Kawasaki Steel Corporation + ff01 KL5A72002 Motion JPEG +136c Adtek System Science Co Ltd +136d Gigalabs Inc +136f Applied Magic Inc +1370 ATL Products +1371 CNet Technology Inc + 434e GigaCard Network Adapter + 1371 434e N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) +1373 Silicon Vision Inc +1374 Silicom Ltd. + 0024 Silicom Dual port Giga Ethernet BGE Bypass Server Adapter + 0025 Silicom Quad port Giga Ethernet BGE Bypass Server Adapter + 0026 Silicom Dual port Fiber Giga Ethernet 546 Bypass Server Adapter + 0027 Silicom Dual port Fiber LX Giga Ethernet 546 Bypass Server Adapter + 0029 Silicom Dual port Copper Giga Ethernet 546GB Bypass Server Adapter + 002a Silicom Dual port Fiber Giga Ethernet 546 TAP/Bypass Server Adapter + 002b Silicom Dual port Copper Fast Ethernet 546 TAP/Bypass Server Adapter (PXE2TBI) + 002c Silicom Quad port Copper Giga Ethernet 546GB Bypass Server Adapter (PXG4BPI) + 002d Silicom Quad port Fiber-SX Giga Ethernet 546GB Bypass Server Adapter (PXG4BPFI) + 002e Silicom Quad port Fiber-LX Giga Ethernet 546GB Bypass Server Adapter (PXG4BPFI-LX) + 002f Silicom Dual port Fiber-SX Giga Ethernet 546GB Low profile Bypass Server Adapter (PXG2BPFIL) + 0030 Silicom Dual port Fiber-LX Giga Ethernet 546GB Low profile Bypass Server Adapter + 0031 Silicom Quad port Copper Giga Ethernet PCI-E Bypass Server Adapter + 0032 Silicom Dual port Copper Fast Ethernet 546 TAP/Bypass Server Adapter + 0034 Silicom Dual port Copper Giga Ethernet PCI-E BGE Bypass Server Adapter + 0035 Silicom Quad port Copper Giga Ethernet PCI-E BGE Bypass Server Adapter + 0036 Silicom Dual port Fiber Giga Ethernet PCI-E BGE Bypass Server Adapter + 0037 Silicom Dual port Copper Ethernet PCI-E Intel based Bypass Server Adapter + 0038 Silicom Quad port Copper Ethernet PCI-E Intel based Bypass Server Adapter + 0039 Silicom Dual port Fiber-SX Ethernet PCI-E Intel based Bypass Server Adapter + 003a Silicom Dual port Fiber-LX Ethernet PCI-E Intel based Bypass Server Adapter + 003b Silicom Dual port Fiber Ethernet PMC Intel based Bypass Server Adapter (PMCX2BPFI) + 003c Silicom Dual port Copper Ethernet PCI-X BGE based Bypass Server Adapter (PXG2BPRB) + 003d 2-port Copper GBE Bypass with Caviume 1010 PCI-X + 003e Silicom Dual port Fiber Giga Ethernet PCI-E 571 TAP/Bypass Server Adapter (PEG2TBFI) + 003f Silicom Dual port Copper Giga Ethernet PCI-X 546 TAP/Bypass Server Adapter (PXG2TBI) + 0040 Silicom Quad port Fiber-SX Giga Ethernet 571 Bypass Server Adapter (PEG4BPFI) + 0042 4-port Copper GBE PMC-X Bypass + 0043 Silicom Quad port Fiber-SX Giga Ethernet 546 Bypass Server Adapter (PXG4BPFID) + 0045 Silicom 6 port Copper Giga Ethernet 546 Bypass Server Adapter (PXG6BPI) + 0046 4-port bypass PCI-E w disconnect low profile + 0047 Silicom Dual port Fiber-SX Giga Ethernet 571 Bypass Disconnect Server Adapter (PEG2BPFID) + 004a Silicom Quad port Fiber-LX Giga Ethernet 571 Bypass Server Adapter (PEG4BPFI-LX) + 004d Dual port Copper Giga Ethernet PCI-E Bypass Server Adapter + 0401 Gigabit Ethernet ExpressModule Bypass Server Adapter + 0420 Gigabit Ethernet ExpressModule Bypass Server Adapter + 0460 Gigabit Ethernet Express Module Bypass Server Adapter + 0461 Gigabit Ethernet ExpressModule Bypass Server Adapter + 0462 Gigabit Ethernet ExpressModule Bypass Server Adapter + 0470 Octal-port Copper Gigabit Ethernet Express Module Bypass Server Adapter + 0482 Dual-port Fiber (SR) 10 Gigabit Ethernet ExpressModule Bypass Server Adapter + 0483 Dual-port Fiber (LR) 10 Gigabit Ethernet ExpressModule Bypass Server Adapter +1375 Argosystems Inc +1376 LMC +1377 Electronic Equipment Production & Distribution GmbH +1378 Telemann Co. Ltd +1379 Asahi Kasei Microsystems Co Ltd +137a Mark of the Unicorn Inc + 0001 PCI-324 Audiowire Interface +137b PPT Vision +137c Iwatsu Electric Co Ltd +137d Dynachip Corporation +137e Patriot Scientific Corporation +137f Japan Satellite Systems Inc +1380 Sanritz Automation Co Ltd +1381 Brains Co. Ltd +1382 Marian - Electronic & Software + 0001 ARC88 audio recording card + 2008 Prodif 96 Pro sound system + 2048 Prodif Plus sound system + 2088 Marc 8 Midi sound system + 20c8 Marc A sound system + 4008 Marc 2 sound system + 4010 Marc 2 Pro sound system + 4048 Marc 4 MIDI sound system + 4088 Marc 4 Digi sound system + 4248 Marc X sound system + 4424 TRACE D4 Sound System +1383 Controlnet Inc +1384 Reality Simulation Systems Inc +1385 Netgear + 006b WA301 802.11b Wireless PCI Adapter + 4100 MA301 802.11b Wireless PCI Adapter + 4601 WAG511 802.11a/b/g Dual Band Wireless PC Card + 620a GA620 Gigabit Ethernet + 630a GA630 Gigabit Ethernet +1386 Video Domain Technologies +1387 Systran Corp +1388 Hitachi Information Technology Co Ltd +1389 Applicom International + 0001 PCI1500PFB [Intelligent fieldbus adaptor] +138a Fusion Micromedia Corp + 003d VFS491 Validity Sensor +138b Tokimec Inc +138c Silicon Reality +138d Future Techno Designs pte Ltd +138e Basler GmbH +138f Patapsco Designs Inc +1390 Concept Development Inc +1391 Development Concepts Inc +1392 Medialight Inc +1393 Moxa Technologies Co Ltd + 0001 UC7000 Serial + 1020 CP-102 (2-port RS-232 PCI) + 1021 CP-102UL (2-port RS-232 Universal PCI) + 1022 CP-102U (2-port RS-232 Universal PCI) + 1023 CP-102UF + 1024 CP-102E (2-port RS-232 Smart PCI Express Serial Board) + 1025 CP-102EL (2-port RS-232 Smart PCI Express Serial Board) + 1040 Smartio C104H/PCI + 1041 CP104U (4-port RS-232 Universal PCI) + 1042 CP104JU (4-port RS-232 Universal PCI) + 1043 CP104EL (4-port RS-232 Smart PCI Express) + 1044 POS104UL (4-port RS-232 Universal PCI) + 1045 CP-104EL-A (4-port RS-232 PCI Express Serial Board) + 1080 CB108 (8-port RS-232 PC/104-plus Module) + 1140 CT-114 series + 1141 Industrio CP-114 + 1142 CB114 (4-port RS-232/422/485 PC/104-plus Module) + 1143 CP-114UL (4-port RS-232/422/485 Smart Universal PCI Serial Board) + 1144 CP-114EL (4-port RS-232/422/485 Smart PCI Express Serial Board) + 1180 CP118U (8-port RS-232/422/485 Smart Universal PCI) + 1181 CP118EL (8-port RS-232/422/485 Smart PCI Express) + 1182 CP-118EL-A (8-port RS-232/422/485 PCI Express Serial Board) + 1320 CP132 (2-port RS-422/485 PCI) + 1321 CP132U (2-Port RS-422/485 Universal PCI) + 1322 CP-132EL (2-port RS-422/485 Smart PCI Express Serial Board) + 1340 CP134U (4-Port RS-422/485 Universal PCI) + 1341 CB134I (4-port RS-422/485 PC/104-plus Module) + 1380 CP138U (8-port RS-232/422/485 Smart Universal PCI) + 1680 Smartio C168H/PCI + 1681 CP-168U V2 Smart Serial Board (8-port RS-232) + 1682 CP-168EL (8-port RS-232 Smart PCI Express) + 1683 CP-168EL-A (8-port RS-232 PCI Express Serial Board) + 2040 Intellio CP-204J + 2180 Intellio C218 Turbo PCI + 3200 Intellio C320 Turbo PCI +1394 Level One Communications + 0001 LXT1001 Gigabit Ethernet + 1186 4800 DGE-500SX + 1394 0001 NetCelerator Adapter +1395 Ambicom Inc +1396 Cipher Systems Inc +1397 Cologne Chip Designs GmbH + 08b4 ISDN network Controller [HFC-4S] + 1397 08b4 HFC-4S [Cologne Chip HFC-4S Eval. Board] + 1397 b51a HFC-4S [Allo.com BRI card] + 1397 b520 HFC-4S [IOB4ST] + 1397 b540 HFC-4S [Swyx SX2 QuadBri] + 1397 b550 HFC-4S [Junghanns.NET quadBRI] + 1397 b556 HFC-4S [Junghanns.NET duoBRI] + 1397 b559 HFC-4S [Junghanns.NET duoBRI miniPCI] + 1397 b560 HFC-4S [BeroNet BN4S0] + 1397 b566 HFC-4S [BeroNet BN2S0] + 1397 b567 HFC-4S [BeroNet BN1S0 miniPCI] + 1397 b568 HFC-4S [BeroNet BN4S0 miniPCI] + 1397 b569 HFC-4S [BeroNet BN2S0 miniPCI] + 1397 b620 HFC-4S + 1397 b752 HFC-4S [Junghanns.NET quadBRI PCIe] + 1397 b761 HFC-4S [BeroNet BN2S0 PCIe] + 1397 b762 HFC-4S [BeroNet BN4S0 PCIe] + 1397 e884 HFC-4S [OpenVox B200P] + 1397 e888 HFC-4S [OpenVox B200P / B400P] + 16b8 ISDN network Controller [HFC-8S] + 1397 16b8 HFC-8S [Cologne Chip HFC-8S Eval. Board] + 1397 b521 HFC-8S [IOB4ST Recording] + 1397 b522 HFC-8S [IOB8ST] + 1397 b552 HFC-8S [Junghanns.NET octoBRI] + 1397 b55b HFC-8S [Junghanns.NET octoBRI] + 1397 b562 HFC-8S [BeroNet BN8S0] + 1397 b56b HFC-8S [BeroNet BN8S0+] + 1397 b622 HFC-8S + 1397 e998 HFC-8S [OpenVox B800P] + 2bd0 ISDN network controller [HFC-PCI] + 0675 1704 ISDN Adapter (PCI Bus, D, C) + 0675 1708 ISDN Adapter (PCI Bus, D, C, ACPI) + 1397 2bd0 ISDN Board + e4bf 1000 CI1-1-Harp + 30b1 ISDN network Controller [HFC-E1] + 1397 30b1 HFC-E1 [Cologne Chip HFC-E1 Eval. Board] + 1397 b523 HFC-E1 [IOB1E1] + 1397 b543 HFC-E1 [Swyx SX2 SinglePRI V2] + 1397 b544 HFC-E1 [Swyx SX2 DualPRI V2] + 1397 b553 HFC-E1 [Junghanns.NET singleE1] + 1397 b554 HFC-E1 [Junghanns.NET doubleE1] + 1397 b555 HFC-E1 [Junghanns.NET doubleE1 2.0] + 1397 b55a HFC-E1 [Junghanns.NET singleE1 miniPCI] + 1397 b563 HFC-E1 [beroNet BN1E1] + 1397 b564 HFC-E1 [beroNet BN2E1] + 1397 b565 HFC-E1 [beroNet BN2E1+] + 1397 b56a HFC-E1 [beroNet BN1E1 miniPCI] + b700 ISDN network controller PrimuX S0 [HFC-PCI] + f001 GSM Network Controller [HFC-4GSM] +1398 Clarion co. Ltd +1399 Rios systems Co Ltd +139a Alacritech Inc + 0001 Quad Port 10/100 Server Accelerator + 0003 Single Port 10/100 Server Accelerator + 0005 Single Port Gigabit Server Accelerator +139b Mediasonic Multimedia Systems Ltd +139c Quantum 3d Inc +139d EPL limited +139e Media4 +139f Aethra s.r.l. +13a0 Crystal Group Inc +13a1 Kawasaki Heavy Industries Ltd +13a2 Ositech Communications Inc +13a3 Hifn Inc. + 0005 7751 Security Processor + 0006 6500 Public Key Processor + 0007 7811 Security Processor + 0012 7951 Security Processor + 0014 78XX Security Processor + 0016 8065 Security Processor + 0017 8165 Security Processor + 0018 8154 Security Processor + 001d 7956 Security Processor + 001f 7855 Security Processor + 0020 7955 Security Processor + 0026 8155 Security Processor + 002e 9630 Compression Processor + 002f 9725 Compression and Security Processor + 13a3 1600 DR1600 Acceleration Card + 13a3 1605 DR1605 Acceleration Card + 13a3 1610 DR1610 Acceleration Card + 13a3 1615 DR1615 Acceleration Card + 13a3 1620 DR1620 Acceleration Card + 13a3 1625 DR1625 Acceleration Card + 0033 8201 Acceleration Processor + 13a3 0036 DX1710 Acceleration Card + 0034 8202 Acceleration Processor + 13a3 0036 DX1720 Acceleration Card + 0035 8203 Acceleration Processor + 13a3 0036 DX1730 Acceleration Card + 0037 8204 Acceleration Processor + 13a3 0036 DX1740 Acceleration Card +13a4 Rascom Inc +13a5 Audio Digital Imaging Inc +13a6 Videonics Inc +13a7 Teles AG +13a8 Exar Corp. + 0152 XR17C/D152 Dual PCI UART + 0154 XR17C154 Quad UART + 0158 XR17C158 Octal UART + 0252 XR17V252 Dual UART PCI controller + 0254 XR17V254 Quad UART PCI controller + 0258 XR17V258 Octal UART PCI controller + 0352 XR17V3521 Dual PCIe UART +13a9 Siemens Medical Systems, Ultrasound Group +13aa Broadband Networks Inc +13ab Arcom Control Systems Ltd +13ac Motion Media Technology Ltd +13ad Nexus Inc +13ae ALD Technology Ltd +13af T.Sqware +13b0 Maxspeed Corp +13b1 Tamura corporation +13b2 Techno Chips Co. Ltd +13b3 Lanart Corporation +13b4 Wellbean Co Inc +13b5 ARM +13b6 Dlog GmbH +13b7 Logic Devices Inc +13b8 Nokia Telecommunications oy +13b9 Elecom Co Ltd +13ba Oxford Instruments +13bb Sanyo Technosound Co Ltd +13bc Bitran Corporation +13bd Sharp corporation +13be Miroku Jyoho Service Co. Ltd +13bf Sharewave Inc +13c0 Microgate Corporation + 0010 SyncLink Adapter v1 + 0020 SyncLink SCC Adapter + 0030 SyncLink Multiport Adapter + 0070 SyncLink GT Adapter + 0080 SyncLink GT4 Adapter + 00a0 SyncLink GT2 Adapter + 0210 SyncLink Adapter v2 +13c1 3ware Inc + 1000 5xxx/6xxx-series PATA-RAID + 1001 7xxx/8xxx-series PATA/SATA-RAID + 13c1 1001 7xxx/8xxx-series PATA/SATA-RAID + 1002 9xxx-series SATA-RAID + 1003 9550SX SATA-II RAID PCI-X + 1004 9650SE SATA-II RAID PCIe + 1005 9690SA SAS/SATA-II RAID PCIe + 1010 9750 SAS2/SATA-II RAID PCIe +13c2 Technotrend Systemtechnik GmbH + 000e Technotrend/Hauppauge DVB card rev2.3 + 1019 TTechnoTrend-budget DVB S2-3200 +13c3 Janz Computer AG +13c4 Phase Metrics +13c5 Alphi Technology Corp +13c6 Condor Engineering Inc + 0520 CEI-520 A429 Card + 0620 CEI-620 A429 Card + 0820 CEI-820 A429 Card + 0830 CEI-830 A429 Card + 1004 P-SER Multi-channel PMC to RS-485/422/232 adapter +13c7 Blue Chip Technology Ltd + 0adc PCI-ADC + 0b10 PCI-PIO + 0d10 PCI-DIO + 524c PCI-RLY + 5744 PCI-WDT +13c8 Apptech Inc +13c9 Eaton Corporation +13ca Iomega Corporation +13cb Yano Electric Co Ltd +13cc Metheus Corporation +13cd Compatible Systems Corporation +13ce Cocom A/S +13cf Studio Audio & Video Ltd +13d0 Techsan Electronics Co Ltd + 2103 B2C2 FlexCopII DVB chip / Technisat SkyStar2 DVB card + 2104 B2C2 FlexCopIII DVB chip / Technisat SkyStar2 DVB card (rev 01) + 2200 B2C2 FlexCopIII DVB chip / Technisat SkyStar2 DVB card +13d1 Abocom Systems Inc + ab02 ADMtek Centaur-C rev 17 [D-Link DFE-680TX] CardBus Fast Ethernet Adapter + ab03 21x4x DEC-Tulip compatible 10/100 Ethernet + ab06 RTL8139 [FE2000VX] CardBus Fast Ethernet Attached Port Adapter + ab08 21x4x DEC-Tulip compatible 10/100 Ethernet +13d2 Shark Multimedia Inc +13d4 Graphics Microsystems Inc +13d5 Media 100 Inc +13d6 K.I. Technology Co Ltd +13d7 Toshiba Engineering Corporation +13d8 Phobos corporation +13d9 Apex PC Solutions Inc +13da Intresource Systems pte Ltd +13db Janich & Klass Computertechnik GmbH +13dc Netboost Corporation +13dd Multimedia Bundle Inc +13de ABB Robotics Products AB +13df E-Tech Inc + 0001 PCI56RVP Modem + 13df 0001 PCI56RVP Modem +13e0 GVC Corporation +13e1 Silicom Multimedia Systems Inc +13e2 Dynamics Research Corporation +13e3 Nest Inc +13e4 Calculex Inc +13e5 Telesoft Design Ltd +13e6 Argosy research Inc +13e7 NAC Incorporated +13e8 Chip Express Corporation +13e9 Intraserver Technology Inc +13ea Dallas Semiconductor +13eb Hauppauge Computer Works Inc +13ec Zydacron Inc + 000a NPC-RC01 Remote control receiver +13ed Raytheion E-Systems +13ee Hayes Microcomputer Products Inc +13ef Coppercom Inc +13f0 Sundance Technology Inc / IC Plus Corp + 0200 IC Plus IP100A Integrated 10/100 Ethernet MAC + PHY + 1043 8213 NX1001 + 0201 ST201 Sundance Ethernet + 1021 TC902x Gigabit Ethernet + 1023 IP1000 Family Gigabit Ethernet + 1043 8180 NX1101 +13f1 Oce' - Technologies B.V. +13f2 Ford Microelectronics Inc +13f3 Mcdata Corporation +13f4 Troika Networks, Inc. + 1401 Zentai Fibre Channel Adapter +13f5 Kansai Electric Co. Ltd +13f6 C-Media Electronics Inc + 0011 CMI8738 + 0100 CM8338A + 13f6 ffff CMI8338/C3DX PCI Audio Device + 0101 CM8338B + 13f6 0101 CMI8338-031 PCI Audio Device + 0111 CMI8738/CMI8768 PCI Audio + 1019 0970 P6STP-FL motherboard + 1043 8035 CUSI-FX motherboard + 1043 8077 CMI8738 6-channel audio controller + 1043 80e2 CMI8738 6ch-MX + 13f6 0111 CMI8738/C3DX PCI Audio Device + 13f6 9761 Theatron Agrippa + 153b 1144 Aureon 5.1 + 153b 1170 Aureon 7.1 + 1681 a000 Gamesurround MUSE XL + 17ab 0604 PSC604 Dynamic Edge + 17ab 0605 PSC605 Sonic Edge + 17ab 7777 PSC605 Sonic Edge + 270f 1103 CT-7NJS Ultra motherboard + 270f f462 7NJL1 motherboard + 584d 3731 Digital X-Mystique + 584d 3741 X-Plosion 7.1 + 584d 3751 X-Raider 7.1 + 584d 3761 X-Mystique 7.1 LP + 584d 3771 X-Mystique 7.1 LP Value + 7284 8384 Striker 7.1 + 0211 CM8738 + 5011 CM8888 [Oxygen Express] + 13f6 5011 HDA Controller + 8788 CMI8788 [Oxygen HD Audio] + 1043 8269 Virtuoso 200 (Xonar D2) + 1043 8275 Virtuoso 100 (Xonar DX) + 1043 82b7 Virtuoso 200 (Xonar D2X) + 1043 8314 Virtuoso 200 (Xonar HDAV1.3) + 1043 8327 Virtuoso 100 (Xonar DX) + 1043 834f Virtuoso 100 (Xonar D1) + 1043 835c Virtuoso 100 (Xonar Essence STX) + 1043 835d Virtuoso 100 (Xonar ST) + 1043 835e Virtuoso 200 (Xonar HDAV1.3 Slim) + 1043 838e Virtuoso 66 (Xonar DS) + 1043 8428 Virtuoso 100 (Xonar Xense) + 1043 8467 CMI8786 (Xonar DG) + 1043 8521 CMI8786 (Xonar DGX) + 1043 8522 Xonar DSX + 1043 85f4 Virtuoso 100 (Xonar Essence STX II) + 13f6 8782 PCI 2.0 HD Audio + 13f6 ffff CMI8787-HG2PCI + 14c3 1710 HiFier Fantasia + 14c3 1711 HiFier Serenade + 14c3 1713 HiFier Serenade III + 1a58 0910 Barracuda AC-1 + 415a 5431 X-Meridian 7.1 + 5431 017a X-Meridian 7.1 2G + 584d 3781 HDA X-Purity 7.1 Platinum + 7284 9761 CLARO + 7284 9781 CLARO halo + 7284 9783 eCLARO + 7284 9787 CLARO II +13f7 Wildfire Communications +13f8 Ad Lib Multimedia Inc +13f9 NTT Advanced Technology Corp. +13fa Pentland Systems Ltd +13fb Aydin Corp +13fc Computer Peripherals International +13fd Micro Science Inc +13fe Advantech Co. Ltd + 1240 PCI-1240 4-channel stepper motor controller card + 1600 PCI-16xx series PCI multiport serial board (function 0) +# This board has two PCI functions, appears as two PCI devices + 1601 0002 PCI-1601 2-port unisolated RS-422/485 +# This board has two PCI functions, appears as two PCI devices + 1602 0002 PCI-1602 2-port isolated RS-422/485 + 1612 0004 PCI-1612 4-port RS-232/422/485 + 1603 PCI-1603 2-port isolated RS-232/current loop + 1604 PCI-1604 2-port RS-232 + 1680 PCI-1680 Rev.A1 2-port CAN-bus with isolation protection + 16ff PCI-16xx series PCI multiport serial board (function 1: RX/TX steering CPLD) + 1601 0000 PCI-1601 2-port unisolated RS-422/485 PCI communications card + 1602 0000 PCI-1602 2-port isolated RS-422/485 + 1612 0000 PCI-1612 4-port RS-232/422/485 + 1711 PCI-1711 16-channel data acquisition card 12-bit, 100kS/s + 1713 PCI-1713 32-channel isolated analog input card + 1733 PCI-1733 32-channel isolated digital input card + 1734 PCI-1734 32-channel isolated digital output card + 1752 PCI-1752 64-channel Isolated Digital Output Card + 1754 PCI-1754 64-channel Isolated Digital Input Card + 1756 PCI-1756 64-ch Isolated Digital I/O PCI Card + a004 PCI-1612 4-port RS-232/422/485 +# FPGA bridge to two SJA1000 + c302 MIOe-3680 2-Port CAN-Bus MIOe Module with Isolation Protection +13ff Silicon Spice Inc +1400 Artx Inc + 1401 9432 TX +1401 CR-Systems A/S +1402 Meilhaus Electronic GmbH + 0630 ME-630 + 0940 ME-94 + 0950 ME-95 + 0960 ME-96 + 1000 ME-1000 + 100a ME-1000 + 100b ME-1000 + 1400 ME-1400 + 140a ME-1400A + 140b ME-1400B + 140c ME-1400C + 140d ME-1400D + 140e ME-1400E + 14ea ME-1400EA + 14eb ME-1400EB + 1604 ME-1600/4U + 1608 ME-1600/8U + 160c ME-1600/12U + 160f ME-1600/16U + 168f ME-1600/16U8I + 4610 ME-4610 + 4650 ME-4650 + 4660 ME-4660 + 4661 ME-4660I + 4662 ME-4660 + 4663 ME-4660I + 4670 ME-4670 + 4671 ME-4670I + 4672 ME-4670S + 4673 ME-4670IS + 4680 ME-4680 + 4681 ME-4680I + 4682 ME-4680S + 4683 ME-4680IS + 6004 ME-6000/4 + 6008 ME-6000/8 + 600f ME-6000/16 + 6014 ME-6000I/4 + 6018 ME-6000I/8 + 601f ME-6000I/16 + 6034 ME-6000ISLE/4 + 6038 ME-6000ISLE/8 + 603f ME-6000ISLE/16 + 6044 ME-6000/4/DIO + 6048 ME-6000/8/DIO + 604f ME-6000/16/DIO + 6054 ME-6000I/4/DIO + 6058 ME-6000I/8/DIO + 605f ME-6000I/16/DIO + 6074 ME-6000ISLE/4/DIO + 6078 ME-6000ISLE/8/DIO + 607f ME-6000ISLE/16/DIO + 6104 ME-6100/4 + 6108 ME-6100/8 + 610f ME-6100/16 + 6114 ME-6100I/4 + 6118 ME-6100I/8 + 611f ME-6100I/16 + 6134 ME-6100ISLE/4 + 6138 ME-6100ISLE/8 + 613f ME-6100ISLE/16 + 6144 ME-6100/4/DIO + 6148 ME-6100/8/DIO + 614f ME-6100/16/DIO + 6154 ME-6100I/4/DIO + 6158 ME-6100I/8/DIO + 615f ME-6100I/16/DIO + 6174 ME-6100ISLE/4/DIO + 6178 ME-6100ISLE/8/DIO + 617f ME-6100ISLE/16/DIO + 6259 ME-6200I/9/DIO + 6359 ME-6300I/9/DIO + 810a ME-8100A + 810b ME-8100B + 820a ME-8200A + 820b ME-8200B +1403 Ascor Inc +1404 Fundamental Software Inc +1405 Excalibur Systems Inc +1406 Oce' Printing Systems GmbH +1407 Lava Computer mfg Inc + 0100 Lava Dual Serial + 0101 Lava Quatro A + 0102 Lava Quatro B + 0110 Lava DSerial-PCI Port A + 0111 Lava DSerial-PCI Port B + 0120 Quattro-PCI A + 0121 Quattro-PCI B + 0180 Lava Octo A + 0181 Lava Octo B + 0200 Lava Port Plus + 0201 Lava Quad A + 0202 Lava Quad B + 0220 Lava Quattro PCI Ports A/B + 0221 Lava Quattro PCI Ports C/D + 0400 Lava 8255-PIO-PCI + 0500 Lava Single Serial + 0520 Lava RS422-SS-PCI + 0600 Lava Port 650 + 8000 Lava Parallel + 8001 Dual parallel port controller A + 8002 Lava Dual Parallel port A + 8003 Lava Dual Parallel port B + 8800 BOCA Research IOPPAR +1408 Aloka Co. Ltd +1409 Timedia Technology Co Ltd + 7168 PCI2S550 (Dual 16550 UART) + 1409 0002 SER4036A3V (2x RS232 port) + 1409 4027 SER4027A (1x RS232 port) + 1409 4037 SER4037A(L) [SUNIX SUN1889] (2x RS232 port) +# Single DC-37 connector + 1409 4056 SER4056A (4x RS232) + 1409 5027 SER4027D + 1409 5037 SER4037D (2x RS232 port) +# Single DC-62 connector + 1409 5066 SER4066R (8x RS232) +# 4x 8p8c connectors + 1409 6056 SER4056D (4x RS232 port) + 7268 SUN1888 (Dual IEEE1284 parallel port) + 1409 0103 PAR4008A + 1409 0104 PAR4018A +140a DSP Research Inc +# Formerly RAMiX, GE Fanuc, GE Intelligent Platforms +140b Abaco Systems, Inc. +140c Elmic Systems Inc +140d Matsushita Electric Works Ltd +140e Goepel Electronic GmbH +140f Salient Systems Corp +1410 Midas lab Inc +1411 Ikos Systems Inc +# Nee IC Ensemble Inc. +1412 VIA Technologies Inc. + 1712 ICE1712 [Envy24] PCI Multi-Channel I/O Controller + 1412 1712 Hoontech ST Audio DSP 24 + 1412 d630 M-Audio Delta 1010 + 1412 d631 M-Audio Delta DiO + 1412 d632 M-Audio Delta 66 + 1412 d633 M-Audio Delta 44 + 1412 d634 M-Audio Delta Audiophile 2496 + 1412 d635 M-Audio Delta TDIF + 1412 d637 M-Audio Delta RBUS + 1412 d638 M-Audio Delta 410 + 1412 d63b M-Audio Delta 1010LT + 1412 d63c Digigram VX442 + 1416 1712 Hoontech ST Audio DSP 24 Media 7.1 + 153b 1115 EWS88 MT + 153b 1125 EWS88 MT (Master) + 153b 112b EWS88 D + 153b 112c EWS88 D (Master) + 153b 1130 EWX 24/96 + 153b 1138 DMX 6fire 24/96 + 153b 1151 PHASE88 + 16ce 1040 Edirol DA-2496 + 1724 VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller + 10b0 0200 Hollywood@Home 7.1 + 1412 1724 Albatron PX865PE 7.1 + 1412 3630 M-Audio Revolution 7.1 + 1412 3631 M-Audio Revolution 5.1 + 1412 3632 M-Audio Audiophile 192 + 153b 1145 Aureon 7.1 Space + 153b 1147 Aureon 5.1 Sky + 153b 1150 PHASE 22 + 153b 1153 Aureon 7.1 Universe + 17ab 1906 PSC 724 [Ultimate Edge] + 270f f641 ZNF3-150 + 270f f645 ZNF3-250 + 3130 4154 MAYA 44 MKII +1413 Addonics +1414 Microsoft Corporation + 0001 MN-120 (ADMtek Centaur-C based) + 0002 MN-130 (ADMtek Centaur-P based) + 5353 Hyper-V virtual VGA + 5801 XMA Decoder (Xenon) + 5802 SATA Controller - CdRom (Xenon) + 5803 SATA Controller - Disk (Xenon) + 5804 OHCI Controller 0 (Xenon) + 5805 EHCI Controller 0 (Xenon) + 5806 OHCI Controller 1 (Xenon) + 5807 EHCI Controller 1 (Xenon) + 580a Fast Ethernet Adapter (Xenon) + 580b Secure Flash Controller (Xenon) + 580d System Management Controller (Xenon) + 5811 Xenos GPU (Xenon) +1415 Oxford Semiconductor Ltd + 8401 OX9162 Mode 1 (8-bit bus) + 8403 OX9162 Mode 0 (parallel port) + 9500 OX16PCI954 (Quad 16950 UART) function 0 (Disabled) + 9501 OX16PCI954 (Quad 16950 UART) function 0 (Uart) + 12c4 0201 Titan/cPCI (2 port) + 12c4 0202 Titan/cPCI (4 port) + 12c4 0203 Titan/cPCI (8 port) + 12c4 0210 Titan/104-Plus (8 port, p1-4) + 131f 2050 CyberPro (4-port) +# Model IO1085, Part No: JJ-P46012 + 131f 2051 CyberSerial 4S Plus + 15ed 2000 MCCR Serial p0-3 of 8 + 15ed 2001 MCCR Serial p0-3 of 16 + 9505 OXuPCI952 (Dual 16C950 UART) + 950a EXSYS EX-41092 Dual 16950 Serial adapter + 950b OXCB950 Cardbus 16950 UART + 9510 OX16PCI954 (Quad 16950 UART) function 1 (Disabled) + 12c4 0200 Titan/cPCI (Unused) + 9511 OX16PCI954 (Quad 16950 UART) function 1 (8bit bus) + 12c4 0211 Titan/104-Plus (8 port, p5-8) + 15ed 2000 MCCR Serial p4-7 of 8 + 15ed 2001 MCCR Serial p4-15 of 16 + 9512 OX16PCI954 (Quad 16950 UART) function 1 (32bit bus) + 9513 OX16PCI954 (Quad 16950 UART) function 1 (parallel port) + 9521 OX16PCI952 (Dual 16950 UART) + 9523 OX16PCI952 Integrated Parallel Port + c158 OXPCIe952 Dual 16C950 UART + e4bf c504 CP4-SCAT Wireless Technologies Carrier Board + e4bf d551 DU1-MUSTANG Dual-Port RS-485 Interface + c308 EX-44016 16-port serial +1416 Multiwave Innovation pte Ltd +1417 Convergenet Technologies Inc +1418 Kyushu electronics systems Inc +1419 Excel Switching Corp +141a Apache Micro Peripherals Inc +141b Zoom Telephonics Inc +141d Digitan Systems Inc +141e Fanuc Ltd +141f Visiontech Ltd +1420 Psion Dacom plc + 8002 Gold Card NetGlobal 56k+10/100Mb CardBus (Ethernet part) + 8003 Gold Card NetGlobal 56k+10/100Mb CardBus (Modem part) +1421 Ads Technologies Inc +1422 Ygrec Systems Co Ltd +1423 Custom Technology Corp. +1424 Videoserver Connections +1425 Chelsio Communications Inc + 000b T210 Protocol Engine + 000c T204 Protocol Engine + 0022 10GbE Ethernet Adapter + 0030 T310 10GbE Single Port Adapter + 103c 705e PCIe 10GBase-SR [AD386A] + 0031 T320 10GbE Dual Port Adapter + 0032 T302 1GbE Dual Port Adapter + 0033 T304 1GbE Quad Port Adapter + 0034 B320 10GbE Dual Port Adapter + 0035 S310-CR 10GbE Single Port Adapter + 0036 S320-LP-CR 10GbE Dual Port Adapter + 0037 N320-G2-CR 10GbE Dual Port Adapter + 4001 T420-CR Unified Wire Ethernet Controller + 4002 T422-CR Unified Wire Ethernet Controller + 4003 T440-CR Unified Wire Ethernet Controller + 4004 T420-BCH Unified Wire Ethernet Controller + 4005 T440-BCH Unified Wire Ethernet Controller + 4006 T440-CH Unified Wire Ethernet Controller + 4007 T420-SO Unified Wire Ethernet Controller + 4008 T420-CX Unified Wire Ethernet Controller + 4009 T420-BT Unified Wire Ethernet Controller + 400a T404-BT Unified Wire Ethernet Controller + 400b B420-SR Unified Wire Ethernet Controller + 400c B404-BT Unified Wire Ethernet Controller + 400d T480 Unified Wire Ethernet Controller + 400e T440-LP-CR Unified Wire Ethernet Controller + 400f T440 [Amsterdam] Unified Wire Ethernet Controller + 4080 T480-4080 T480 Unified Wire Ethernet Controller + 4081 T440F-4081 T440-FCoE Unified Wire Ethernet Controller + 4082 T420-4082 Unified Wire Ethernet Controller + 4083 T420X-4083 Unified Wire Ethernet Controller + 4084 T440-4084 Unified Wire Ethernet Controller + 4085 T420-4085 SFP+ Unified Wire Ethernet Controller + 4086 T440-4086 10Gbase-T Unified Wire Ethernet Controller + 4087 T440T-4087 Unified Wire Ethernet Controller + 4088 T440-4088 Unified Wire Ethernet Controller + 4401 T420-CR Unified Wire Ethernet Controller + 4402 T422-CR Unified Wire Ethernet Controller + 4403 T440-CR Unified Wire Ethernet Controller + 4404 T420-BCH Unified Wire Ethernet Controller + 4405 T440-BCH Unified Wire Ethernet Controller + 4406 T440-CH Unified Wire Ethernet Controller + 4407 T420-SO Unified Wire Ethernet Controller + 4408 T420-CX Unified Wire Ethernet Controller + 4409 T420-BT Unified Wire Ethernet Controller + 440a T404-BT Unified Wire Ethernet Controller + 440b B420-SR Unified Wire Ethernet Controller + 440c B404-BT Unified Wire Ethernet Controller + 440d T480 Unified Wire Ethernet Controller + 440e T440-LP-CR Unified Wire Ethernet Controller + 440f T440 [Amsterdam] Unified Wire Ethernet Controller + 4480 T480-4080 T480 Unified Wire Ethernet Controller + 4481 T440F-4081 T440-FCoE Unified Wire Ethernet Controller + 4482 T420-4082 Unified Wire Ethernet Controller + 4483 T420X-4083 Unified Wire Ethernet Controller + 4484 T440-4084 Unified Wire Ethernet Controller + 4485 T420-4085 SFP+ Unified Wire Ethernet Controller + 4486 T440-4086 10Gbase-T Unified Wire Ethernet Controller + 4487 T440T-4087 Unified Wire Ethernet Controller + 4488 T440-4088 Unified Wire Ethernet Controller + 4501 T420-CR Unified Wire Storage Controller + 4502 T422-CR Unified Wire Storage Controller + 4503 T440-CR Unified Wire Storage Controller + 4504 T420-BCH Unified Wire Storage Controller + 4505 T440-BCH Unified Wire Storage Controller + 4506 T440-CH Unified Wire Storage Controller + 4507 T420-SO Unified Wire Storage Controller + 4508 T420-CX Unified Wire Storage Controller + 4509 T420-BT Unified Wire Storage Controller + 450a T404-BT Unified Wire Storage Controller + 450b B420-SR Unified Wire Storage Controller + 450c B404-BT Unified Wire Storage Controller + 450d T480 Unified Wire Storage Controller + 450e T440-LP-CR Unified Wire Storage Controller + 450f T440 [Amsterdam] Unified Wire Storage Controller + 4580 T480-4080 T480 Unified Wire Storage Controller + 4581 T440F-4081 T440-FCoE Unified Wire Storage Controller + 4582 T420-4082 Unified Wire Storage Controller + 4583 T420X-4083 Unified Wire Storage Controller + 4584 T440-4084 Unified Wire Storage Controller + 4585 T420-4085 SFP+ Unified Wire Storage Controller + 4586 T440-4086 10Gbase-T Unified Wire Storage Controller + 4587 T440T-4087 Unified Wire Storage Controller + 4588 T440-4088 Unified Wire Storage Controller + 4601 T420-CR Unified Wire Storage Controller + 4602 T422-CR Unified Wire Storage Controller + 4603 T440-CR Unified Wire Storage Controller + 4604 T420-BCH Unified Wire Storage Controller + 4605 T440-BCH Unified Wire Storage Controller + 4606 T440-CH Unified Wire Storage Controller + 4607 T420-SO Unified Wire Storage Controller + 4608 T420-CX Unified Wire Storage Controller + 4609 T420-BT Unified Wire Storage Controller + 460a T404-BT Unified Wire Storage Controller + 460b B420-SR Unified Wire Storage Controller + 460c B404-BT Unified Wire Storage Controller + 460d T480 Unified Wire Storage Controller + 460e T440-LP-CR Unified Wire Storage Controller + 460f T440 [Amsterdam] Unified Wire Storage Controller + 4680 T480-4080 T480 Unified Wire Storage Controller + 4681 T440F-4081 T440-FCoE Unified Wire Storage Controller + 4682 T420-4082 Unified Wire Storage Controller + 4683 T420X-4083 Unified Wire Storage Controller + 4684 T440-4084 Unified Wire Storage Controller + 4685 T420-4085 SFP+ Unified Wire Storage Controller + 4686 T440-4086 10Gbase-T Unified Wire Storage Controller + 4687 T440T-4087 Unified Wire Storage Controller + 4688 T440-4088 Unified Wire Storage Controller + 4701 T420-CR Unified Wire Ethernet Controller + 4702 T422-CR Unified Wire Ethernet Controller + 4703 T440-CR Unified Wire Ethernet Controller + 4704 T420-BCH Unified Wire Ethernet Controller + 4705 T440-BCH Unified Wire Ethernet Controller + 4706 T440-CH Unified Wire Ethernet Controller + 4707 T420-SO Unified Wire Ethernet Controller + 4708 T420-CX Unified Wire Ethernet Controller + 4709 T420-BT Unified Wire Ethernet Controller + 470a T404-BT Unified Wire Ethernet Controller + 470b B420-SR Unified Wire Ethernet Controller + 470c B404-BT Unified Wire Ethernet Controller + 470d T480 Unified Wire Ethernet Controller + 470e T440-LP-CR Unified Wire Ethernet Controller + 470f T440 [Amsterdam] Unified Wire Ethernet Controller + 4780 T480-4080 T480 Unified Wire Ethernet Controller + 4781 T440F-4081 T440-FCoE Unified Wire Ethernet Controller + 4782 T420-4082 Unified Wire Ethernet Controller + 4783 T420X-4083 Unified Wire Ethernet Controller + 4784 T440-4084 Unified Wire Ethernet Controller + 4785 T420-4085 SFP+ Unified Wire Ethernet Controller + 4786 T440-4086 10Gbase-T Unified Wire Ethernet Controller + 4787 T440T-4087 Unified Wire Ethernet Controller + 4788 T440-4088 Unified Wire Ethernet Controller + 4801 T420-CR Unified Wire Ethernet Controller [VF] + 4802 T422-CR Unified Wire Ethernet Controller [VF] + 4803 T440-CR Unified Wire Ethernet Controller [VF] + 4804 T420-BCH Unified Wire Ethernet Controller [VF] + 4805 T440-BCH Unified Wire Ethernet Controller [VF] + 4806 T440-CH Unified Wire Ethernet Controller [VF] + 4807 T420-SO Unified Wire Ethernet Controller [VF] + 4808 T420-CX Unified Wire Ethernet Controller [VF] + 4809 T420-BT Unified Wire Ethernet Controller [VF] + 480a T404-BT Unified Wire Ethernet Controller [VF] + 480b B420-SR Unified Wire Ethernet Controller [VF] + 480c B404-BT Unified Wire Ethernet Controller [VF] + 480d T480 Unified Wire Ethernet Controller [VF] + 480e T440-LP-CR Unified Wire Ethernet Controller [VF] + 480f T440 [Amsterdam] Unified Wire Ethernet Controller [VF] + 4880 T480-4080 T480 Unified Wire Ethernet Controller [VF] + 4881 T440F-4081 T440-FCoE Unified Wire Ethernet Controller [VF] + 4882 T420-4082 Unified Wire Ethernet Controller [VF] + 4883 T420X-4083 Unified Wire Ethernet Controller [VF] + 4884 T440-4084 Unified Wire Ethernet Controller [VF] + 4885 T420-4085 SFP+ Unified Wire Ethernet Controller [VF] + 4886 T440-4086 10Gbase-T Unified Wire Ethernet Controller [VF] + 4887 T440T-4087 Unified Wire Ethernet Controller [VF] + 4888 T440-4088 Unified Wire Ethernet Controller [VF] + 5001 T520-CR Unified Wire Ethernet Controller + 193d 1001 510F-B + 5002 T522-CR Unified Wire Ethernet Controller + 5003 T540-CR Unified Wire Ethernet Controller + 5004 T520-BCH Unified Wire Ethernet Controller + 5005 T540-BCH Unified Wire Ethernet Controller + 5006 T540-CH Unified Wire Ethernet Controller + 5007 T520-SO Unified Wire Ethernet Controller + 5008 T520-CX Unified Wire Ethernet Controller + 5009 T520-BT Unified Wire Ethernet Controller + 500a T504-BT Unified Wire Ethernet Controller + 500b B520-SR Unified Wire Ethernet Controller + 500c B504-BT Unified Wire Ethernet Controller + 500d T580-CR Unified Wire Ethernet Controller + 500e T540-LP-CR Unified Wire Ethernet Controller + 500f T540 [Amsterdam] Unified Wire Ethernet Controller + 5010 T580-LP-CR Unified Wire Ethernet Controller + 5011 T520-LL-CR Unified Wire Ethernet Controller + 5012 T560-CR Unified Wire Ethernet Controller + 5013 T580-CHR Unified Wire Ethernet Controller + 5014 T580-SO-CR Unified Wire Ethernet Controller + 5015 T502-BT Unified Wire Ethernet Controller + 5016 T580-OCP-SO Unified Wire Ethernet Controller + 5017 T520-OCP-SO Unified Wire Ethernet Controller + 5018 T540-BT Unified Wire Ethernet Controller + 5019 T540-LP-BT Unified Wire Ethernet Controller + 501a T540-SO-BT Unified Wire Ethernet Controller + 501b T540-SO-CR Unified Wire Ethernet Controller + 5080 T540-5080 Unified Wire Ethernet Controller + 5081 T540-5081 Unified Wire Ethernet Controller + 5082 T504-5082 Unified Wire Ethernet Controller + 5083 T540-5083 Unified Wire Ethernet Controller + 5084 T540-5084 Unified Wire Ethernet Controller + 5085 T580-5085 Unified Wire Ethernet Controller + 5086 T580-5086 Unified Wire Ethernet Controller + 5087 T580-5087 Unified Wire Ethernet Controller + 5088 T570-5088 Unified Wire Ethernet Controller + 5089 T520-5089 Unified Wire Ethernet Controller + 5090 T540-5090 Unified Wire Ethernet Controller + 5091 T522-5091 Unified Wire Ethernet Controller + 5092 T520-5092 Unified Wire Ethernet Controller + 5093 T580-5093 Unified Wire Ethernet Controller + 5094 T540-5094 Unified Wire Ethernet Controller + 5095 T540-5095 Unified Wire Ethernet Controller + 5096 T580-5096 Unified Wire Ethernet Controller + 5097 T520-5097 Unified Wire Ethernet Controller + 5098 T580-5098 Unified Wire Ethernet Controller + 5099 T580-5099 Unified Wire Ethernet Controller + 509a T520-509A Unified Wire Ethernet Controller + 509b T540-509B Unified Wire Ethernet Controller + 509c T520-509C Unified Wire Ethernet Controller + 509d T540-509D Unified Wire Ethernet Controller + 509e T520-509E Unified Wire Ethernet Controller + 509f T540-509F Unified Wire Ethernet Controller + 50a0 T540-50A0 Unified Wire Ethernet Controller + 50a1 T540-50A1 Unified Wire Ethernet Controller + 50a2 T580-50A2 Unified Wire Ethernet Controller + 50a3 T580-50A3 Unified Wire Ethernet Controller + 50a4 T540-50A4 Unified Wire Ethernet Controller + 50a5 T522-50A5 Unified Wire Ethernet Controller + 50a6 T522-50A6 Unified Wire Ethernet Controller + 50a7 T580-50A7 Unified Wire Ethernet Controller + 50a8 T580-50A8 Unified Wire Ethernet Controller + 50a9 T580-50A9 Unified Wire Ethernet Controller + 50aa T580-50AA Unified Wire Ethernet Controller + 50ab T520-50AB Unified Wire Ethernet Controller + 50ac T540-50AC Unified Wire Ethernet Controller + 50ad T520-50AD Unified Wire Ethernet Controller + 50ae T540-50AE Unified Wire Ethernet Controller + 50af T580-50AF Unified Wire Ethernet Controller + 50b0 T520-50B0 Unified Wire Ethernet Controller + 5401 T520-CR Unified Wire Ethernet Controller + 5402 T522-CR Unified Wire Ethernet Controller + 5403 T540-CR Unified Wire Ethernet Controller + 5404 T520-BCH Unified Wire Ethernet Controller + 5405 T540-BCH Unified Wire Ethernet Controller + 5406 T540-CH Unified Wire Ethernet Controller + 5407 T520-SO Unified Wire Ethernet Controller + 5408 T520-CX Unified Wire Ethernet Controller + 5409 T520-BT Unified Wire Ethernet Controller + 540a T504-BT Unified Wire Ethernet Controller + 540b B520-SR Unified Wire Ethernet Controller + 540c B504-BT Unified Wire Ethernet Controller + 540d T580-CR Unified Wire Ethernet Controller + 540e T540-LP-CR Unified Wire Ethernet Controller + 540f T540 [Amsterdam] Unified Wire Ethernet Controller + 5410 T580-LP-CR Unified Wire Ethernet Controller + 5411 T520-LL-CR Unified Wire Ethernet Controller + 5412 T560-CR Unified Wire Ethernet Controller + 5413 T580-CHR Unified Wire Ethernet Controller + 5414 T580-SO-CR Unified Wire Ethernet Controller + 5415 T502-BT Unified Wire Ethernet Controller + 5416 T580-OCP-SO Unified Wire Ethernet Controller + 5417 T520-OCP-SO Unified Wire Ethernet Controller + 5418 T540-BT Unified Wire Ethernet Controller + 5419 T540-LP-BT Unified Wire Ethernet Controller + 541a T540-SO-BT Unified Wire Ethernet Controller + 541b T540-SO-CR Unified Wire Ethernet Controller + 5480 T540-5080 Unified Wire Ethernet Controller + 5481 T540-5081 Unified Wire Ethernet Controller + 5482 T504-5082 Unified Wire Ethernet Controller + 5483 T540-5083 Unified Wire Ethernet Controller + 5484 T540-5084 Unified Wire Ethernet Controller + 5485 T580-5085 Unified Wire Ethernet Controller + 5486 T580-5086 Unified Wire Ethernet Controller + 5487 T580-5087 Unified Wire Ethernet Controller + 5488 T570-5088 Unified Wire Ethernet Controller + 5489 T520-5089 Unified Wire Ethernet Controller + 5490 T540-5090 Unified Wire Ethernet Controller + 5491 T522-5091 Unified Wire Ethernet Controller + 5492 T520-5092 Unified Wire Ethernet Controller + 5493 T580-5093 Unified Wire Ethernet Controller + 5494 T540-5094 Unified Wire Ethernet Controller + 5495 T540-5095 Unified Wire Ethernet Controller + 5496 T580-5096 Unified Wire Ethernet Controller + 5497 T520-5097 Unified Wire Ethernet Controller + 5498 T580-5098 Unified Wire Ethernet Controller + 5499 T580-5099 Unified Wire Ethernet Controller + 549a T520-509A Unified Wire Ethernet Controller + 549b T540-509B Unified Wire Ethernet Controller + 549c T520-509C Unified Wire Ethernet Controller + 549d T540-509D Unified Wire Ethernet Controller + 549e T520-509E Unified Wire Ethernet Controller + 549f T540-509F Unified Wire Ethernet Controller + 54a0 T540-50A0 Unified Wire Ethernet Controller + 54a1 T540-50A1 Unified Wire Ethernet Controller + 54a2 T580-50A2 Unified Wire Ethernet Controller + 54a3 T580-50A3 Unified Wire Ethernet Controller + 54a4 T540-50A4 Unified Wire Ethernet Controller + 54a5 T522-50A5 Unified Wire Ethernet Controller + 54a6 T522-50A6 Unified Wire Ethernet Controller + 54a7 T580-50A7 Unified Wire Ethernet Controller + 54a8 T580-50A8 Unified Wire Ethernet Controller + 54a9 T580-50A9 Unified Wire Ethernet Controller + 54aa T580-50AA Unified Wire Ethernet Controller + 54ab T520-50AB Unified Wire Ethernet Controller + 54ac T540-50AC Unified Wire Ethernet Controller + 54ad T520-50AD Unified Wire Ethernet Controller + 54ae T540-50AE Unified Wire Ethernet Controller + 54af T580-50AF Unified Wire Ethernet Controller + 54b0 T520-50B0 Unified Wire Ethernet Controller + 5501 T520-CR Unified Wire Storage Controller + 5502 T522-CR Unified Wire Storage Controller + 5503 T540-CR Unified Wire Storage Controller + 5504 T520-BCH Unified Wire Storage Controller + 5505 T540-BCH Unified Wire Storage Controller + 5506 T540-CH Unified Wire Storage Controller + 5507 T520-SO Unified Wire Storage Controller + 5508 T520-CX Unified Wire Storage Controller + 5509 T520-BT Unified Wire Storage Controller + 550a T504-BT Unified Wire Storage Controller + 550b B520-SR Unified Wire Storage Controller + 550c B504-BT Unified Wire Storage Controller + 550d T580-CR Unified Wire Storage Controller + 550e T540-LP-CR Unified Wire Storage Controller + 550f T540 [Amsterdam] Unified Wire Storage Controller + 5510 T580-LP-CR Unified Wire Storage Controller + 5511 T520-LL-CR Unified Wire Storage Controller + 5512 T560-CR Unified Wire Storage Controller + 5513 T580-CHR Unified Wire Storage Controller + 5514 T580-SO-CR Unified Wire Storage Controller + 5515 T502-BT Unified Wire Storage Controller + 5516 T580-OCP-SO Unified Wire Storage Controller + 5517 T520-OCP-SO Unified Wire Storage Controller + 5518 T540-BT Unified Wire Storage Controller + 5519 T540-LP-BT Unified Wire Storage Controller + 551a T540-SO-BT Unified Wire Storage Controller + 551b T540-SO-CR Unified Wire Storage Controller + 5580 T540-5080 Unified Wire Storage Controller + 5581 T540-5081 Unified Wire Storage Controller + 5582 T504-5082 Unified Wire Storage Controller + 5583 T540-5083 Unified Wire Storage Controller + 5584 T540-5084 Unified Wire Storage Controller + 5585 T580-5085 Unified Wire Storage Controller + 5586 T580-5086 Unified Wire Storage Controller + 5587 T580-5087 Unified Wire Storage Controller + 5588 T570-5088 Unified Wire Storage Controller + 5589 T520-5089 Unified Wire Storage Controller + 5590 T540-5090 Unified Wire Storage Controller + 5591 T522-5091 Unified Wire Storage Controller + 5592 T520-5092 Unified Wire Storage Controller + 5593 T580-5093 Unified Wire Storage Controller + 5594 T540-5094 Unified Wire Storage Controller + 5595 T540-5095 Unified Wire Storage Controller + 5596 T580-5096 Unified Wire Storage Controller + 5597 T520-5097 Unified Wire Storage Controller + 5598 T580-5098 Unified Wire Storage Controller + 5599 T580-5099 Unified Wire Storage Controller + 559a T520-509A Unified Wire Storage Controller + 559b T540-509B Unified Wire Storage Controller + 559c T520-509C Unified Wire Storage Controller + 559d T540-509D Unified Wire Storage Controller + 559e T520-509E Unified Wire Storage Controller + 559f T540-509F Unified Wire Storage Controller + 55a0 T540-50A0 Unified Wire Storage Controller + 55a1 T540-50A1 Unified Wire Storage Controller + 55a2 T580-50A2 Unified Wire Storage Controller + 55a3 T580-50A3 Unified Wire Storage Controller + 55a4 T540-50A4 Unified Wire Storage Controller + 55a5 T522-50A5 Unified Wire Storage Controller + 55a6 T522-50A6 Unified Wire Storage Controller + 55a7 T580-50A7 Unified Wire Storage Controller + 55a8 T580-50A8 Unified Wire Storage Controller + 55a9 T580-50A9 Unified Wire Storage Controller + 55aa T580-50AA Unified Wire Storage Controller + 55ab T520-50AB Unified Wire Storage Controller + 55ac T540-50AC Unified Wire Storage Controller + 55ad T520-50AD Unified Wire Storage Controller + 55ae T540-50AE Unified Wire Storage Controller + 55af T580-50AF Unified Wire Storage Controller + 55b0 T520-50B0 Unified Wire Storage Controller + 5601 T520-CR Unified Wire Storage Controller + 5602 T522-CR Unified Wire Storage Controller + 5603 T540-CR Unified Wire Storage Controller + 5604 T520-BCH Unified Wire Storage Controller + 5605 T540-BCH Unified Wire Storage Controller + 5606 T540-CH Unified Wire Storage Controller + 5607 T520-SO Unified Wire Storage Controller + 5608 T520-CX Unified Wire Storage Controller + 5609 T520-BT Unified Wire Storage Controller + 560a T504-BT Unified Wire Storage Controller + 560b B520-SR Unified Wire Storage Controller + 560c B504-BT Unified Wire Storage Controller + 560d T580-CR Unified Wire Storage Controller + 560e T540-LP-CR Unified Wire Storage Controller + 560f T540 [Amsterdam] Unified Wire Storage Controller + 5610 T580-LP-CR Unified Wire Storage Controller + 5611 T520-LL-CR Unified Wire Storage Controller + 5612 T560-CR Unified Wire Storage Controller + 5613 T580-CHR Unified Wire Storage Controller + 5614 T580-SO-CR Unified Wire Storage Controller + 5615 T502-BT Unified Wire Storage Controller + 5616 T580-OCP-SO Unified Wire Storage Controller + 5617 T520-OCP-SO Unified Wire Storage Controller + 5618 T540-BT Unified Wire Storage Controller + 5619 T540-LP-BT Unified Wire Storage Controller + 561a T540-SO-BT Unified Wire Storage Controller + 561b T540-SO-CR Unified Wire Storage Controller + 5680 T540-5080 Unified Wire Storage Controller + 5681 T540-5081 Unified Wire Storage Controller + 5682 T504-5082 Unified Wire Storage Controller + 5683 T540-5083 Unified Wire Storage Controller + 5684 T540-5084 Unified Wire Storage Controller + 5685 T580-5085 Unified Wire Storage Controller + 5686 T580-5086 Unified Wire Storage Controller + 5687 T580-5087 Unified Wire Storage Controller + 5688 T570-5088 Unified Wire Storage Controller + 5689 T520-5089 Unified Wire Storage Controller + 5690 T540-5090 Unified Wire Storage Controller + 5691 T522-5091 Unified Wire Storage Controller + 5692 T520-5092 Unified Wire Storage Controller + 5693 T580-5093 Unified Wire Storage Controller + 5694 T540-5094 Unified Wire Storage Controller + 5695 T540-5095 Unified Wire Storage Controller + 5696 T580-5096 Unified Wire Storage Controller + 5697 T520-5097 Unified Wire Storage Controller + 5698 T580-5098 Unified Wire Storage Controller + 5699 T580-5099 Unified Wire Storage Controller + 569a T520-509A Unified Wire Storage Controller + 569b T540-509B Unified Wire Storage Controller + 569c T520-509C Unified Wire Storage Controller + 569d T540-509D Unified Wire Storage Controller + 569e T520-509E Unified Wire Storage Controller + 569f T540-509F Unified Wire Storage Controller + 56a0 T540-50A0 Unified Wire Storage Controller + 56a1 T540-50A1 Unified Wire Storage Controller + 56a2 T580-50A2 Unified Wire Storage Controller + 56a3 T580-50A3 Unified Wire Storage Controller + 56a4 T540-50A4 Unified Wire Storage Controller + 56a5 T522-50A5 Unified Wire Storage Controller + 56a6 T522-50A6 Unified Wire Storage Controller + 56a7 T580-50A7 Unified Wire Storage Controller + 56a8 T580-50A8 Unified Wire Storage Controller + 56a9 T580-50A9 Unified Wire Storage Controller + 56aa T580-50AA Unified Wire Storage Controller + 56ab T520-50AB Unified Wire Storage Controller + 56ac T540-50AC Unified Wire Storage Controller + 56ad T520-50AD Unified Wire Storage Controller + 56ae T540-50AE Unified Wire Storage Controller + 56af T580-50AF Unified Wire Storage Controller + 56b0 T520-50B0 Unified Wire Storage Controller + 5701 T520-CR Unified Wire Ethernet Controller + 5702 T522-CR Unified Wire Ethernet Controller + 5703 T540-CR Unified Wire Ethernet Controller + 5704 T520-BCH Unified Wire Ethernet Controller + 5705 T540-BCH Unified Wire Ethernet Controller + 5706 T540-CH Unified Wire Ethernet Controller + 5707 T520-SO Unified Wire Ethernet Controller + 5708 T520-CX Unified Wire Ethernet Controller + 5709 T520-BT Unified Wire Ethernet Controller + 570a T504-BT Unified Wire Ethernet Controller + 570b B520-SR Unified Wire Ethernet Controller + 570c B504-BT Unified Wire Ethernet Controller + 570d T580-CR Unified Wire Ethernet Controller + 570e T540-LP-CR Unified Wire Ethernet Controller + 570f T540 [Amsterdam] Unified Wire Ethernet Controller + 5710 T580-LP-CR Unified Wire Ethernet Controller + 5711 T520-LL-CR Unified Wire Ethernet Controller + 5712 T560-CR Unified Wire Ethernet Controller + 5713 T580-CR Unified Wire Ethernet Controller + 5714 T580-SO-CR Unified Wire Ethernet Controller + 5715 T502-BT Unified Wire Ethernet Controller + 5780 T540-5080 Unified Wire Ethernet Controller + 5781 T540-5081 Unified Wire Ethernet Controller + 5782 T504-5082 Unified Wire Ethernet Controller + 5783 T540-5083 Unified Wire Ethernet Controller + 5784 T580-5084 Unified Wire Ethernet Controller + 5785 T580-5085 Unified Wire Ethernet Controller + 5786 T580-5086 Unified Wire Ethernet Controller + 5787 T580-5087 Unified Wire Ethernet Controller + 5788 T570-5088 Unified Wire Ethernet Controller + 5789 T520-5089 Unified Wire Ethernet Controller + 5790 T540-5090 Unified Wire Ethernet Controller + 5791 T522-5091 Unified Wire Ethernet Controller + 5792 T520-5092 Unified Wire Ethernet Controller + 5793 T580-5093 Unified Wire Ethernet Controller + 5794 T540-5094 Unified Wire Ethernet Controller + 5795 T540-5095 Unified Wire Ethernet Controller + 5796 T580-5096 Unified Wire Ethernet Controller + 5797 T520-5097 Unified Wire Ethernet Controller + 5801 T520-CR Unified Wire Ethernet Controller [VF] + 5802 T522-CR Unified Wire Ethernet Controller [VF] + 5803 T540-CR Unified Wire Ethernet Controller [VF] + 5804 T520-BCH Unified Wire Ethernet Controller [VF] + 5805 T540-BCH Unified Wire Ethernet Controller [VF] + 5806 T540-CH Unified Wire Ethernet Controller [VF] + 5807 T520-SO Unified Wire Ethernet Controller [VF] + 5808 T520-CX Unified Wire Ethernet Controller [VF] + 5809 T520-BT Unified Wire Ethernet Controller [VF] + 580a T504-BT Unified Wire Ethernet Controller [VF] + 580b B520-SR Unified Wire Ethernet Controller [VF] + 580c B504-BT Unified Wire Ethernet Controller [VF] + 580d T580-CR Unified Wire Ethernet Controller [VF] + 580e T540-LP-CR Unified Wire Ethernet Controller [VF] + 580f T540 [Amsterdam] Unified Wire Ethernet Controller [VF] + 5810 T580-LP-CR Unified Wire Ethernet Controller [VF] + 5811 T520-LL-CR Unified Wire Ethernet Controller [VF] + 5812 T560-CR Unified Wire Ethernet Controller [VF] + 5813 T580-CHR Unified Wire Ethernet Controller [VF] + 5814 T580-SO-CR Unified Wire Ethernet Controller [VF] + 5815 T502-BT Unified Wire Ethernet Controller [VF] + 5816 T580-OCP-SO Unified Wire Ethernet Controller [VF] + 5817 T520-OCP-SO Unified Wire Ethernet Controller [VF] + 5818 T540-BT Unified Wire Ethernet Controller [VF] + 5819 T540-LP-BT Unified Wire Ethernet Controller [VF] + 581a T540-SO-BT Unified Wire Ethernet Controller [VF] + 581b T540-SO-CR Unified Wire Ethernet Controller [VF] + 5880 T540-5080 Unified Wire Ethernet Controller [VF] + 5881 T540-5081 Unified Wire Ethernet Controller [VF] + 5882 T504-5082 Unified Wire Ethernet Controller [VF] + 5883 T540-5083 Unified Wire Ethernet Controller [VF] + 5884 T540-5084 Unified Wire Ethernet Controller [VF] + 5885 T580-5085 Unified Wire Ethernet Controller [VF] + 5886 T580-5086 Unified Wire Ethernet Controller [VF] + 5887 T580-5087 Unified Wire Ethernet Controller [VF] + 5888 T570-5088 Unified Wire Ethernet Controller [VF] + 5889 T520-5089 Unified Wire Ethernet Controller [VF] + 5890 T540-5090 Unified Wire Ethernet Controller [VF] + 5891 T522-5091 Unified Wire Ethernet Controller [VF] + 5892 T520-5092 Unified Wire Ethernet Controller [VF] + 5893 T580-5093 Unified Wire Ethernet Controller [VF] + 5894 T540-5094 Unified Wire Ethernet Controller [VF] + 5895 T540-5095 Unified Wire Ethernet Controller [VF] + 5896 T580-5096 Unified Wire Ethernet Controller [VF] + 5897 T520-5097 Unified Wire Ethernet Controller [VF] + 5898 T580-5098 Unified Wire Ethernet Controller [VF] + 5899 T580-5099 Unified Wire Ethernet Controller [VF] + 589a T520-509A Unified Wire Ethernet Controller [VF] + 589b T540-509B Unified Wire Ethernet Controller [VF] + 589c T520-509C Unified Wire Ethernet Controller [VF] + 589d T540-509D Unified Wire Ethernet Controller [VF] + 589e T520-509E Unified Wire Ethernet Controller [VF] + 589f T540-509F Unified Wire Ethernet Controller [VF] + 58a0 T540-50A0 Unified Wire Ethernet Controller [VF] + 58a1 T540-50A1 Unified Wire Ethernet Controller [VF] + 58a2 T580-50A2 Unified Wire Ethernet Controller [VF] + 58a3 T580-50A3 Unified Wire Ethernet Controller [VF] + 58a4 T540-50A4 Unified Wire Ethernet Controller [VF] + 58a5 T522-50A5 Unified Wire Ethernet Controller [VF] + 58a6 T522-50A6 Unified Wire Ethernet Controller [VF] + 58a7 T580-50A7 Unified Wire Ethernet Controller [VF] + 58a8 T580-50A8 Unified Wire Ethernet Controller [VF] + 58a9 T580-50A9 Unified Wire Ethernet Controller [VF] + 58aa T580-50AA Unified Wire Ethernet Controller [VF] + 58ab T520-50AB Unified Wire Ethernet Controller [VF] + 58ac T540-50AC Unified Wire Ethernet Controller [VF] + 58ad T520-50AD Unified Wire Ethernet Controller [VF] + 58ae T540-50AE Unified Wire Ethernet Controller [VF] + 58af T580-50AF Unified Wire Ethernet Controller [VF] + 58b0 T520-50B0 Unified Wire Ethernet Controller [VF] + 6001 T6225-CR Unified Wire Ethernet Controller + 6002 T6225-SO-CR Unified Wire Ethernet Controller + 6003 T6425-CR Unified Wire Ethernet Controller + 6004 T6425-SO-CR Unified Wire Ethernet Controller + 6005 T6225-OCP-SO Unified Wire Ethernet Controller + 6006 T62100-OCP-SO Unified Wire Ethernet Controller + 6007 T62100-LP-CR Unified Wire Ethernet Controller + 6008 T62100-SO-CR Unified Wire Ethernet Controller + 6009 T6210-BT Unified Wire Ethernet Controller + 600d T62100-CR Unified Wire Ethernet Controller + 6011 T6225-LL-CR Unified Wire Ethernet Controller + 6014 T61100-OCP-SO Unified Wire Ethernet Controller + 6015 T6201-BT Unified Wire Ethernet Controller + 6080 T6225-6080 Unified Wire Ethernet Controller + 6081 T62100-6081 Unified Wire Ethernet Controller + 6082 T6225-6082 Unified Wire Ethernet Controller + 6083 T62100-6083 Unified Wire Ethernet Controller + 6084 T64100-6084 Unified Wire Ethernet Controller + 6085 T6240-6085 Unified Wire Ethernet Controller + 6086 T6225-6086 Unified Wire Ethernet Controller + 6087 T6225-6087 Unified Wire Ethernet Controller + 6088 T62100-6088 Unified Wire Ethernet Controller + 6089 T62100-6089 Unified Wire Ethernet Controller + 608a T62100-608a Unified Wire Ethernet Controller + 6401 T6225-CR Unified Wire Ethernet Controller + 6402 T6225-SO-CR Unified Wire Ethernet Controller + 6403 T6425-CR Unified Wire Ethernet Controller + 6404 T6425-SO-CR Unified Wire Ethernet Controller + 6405 T6225-OCP-SO Unified Wire Ethernet Controller + 6406 T62100-OCP-SO Unified Wire Ethernet Controller + 6407 T62100-LP-CR Unified Wire Ethernet Controller + 6408 T62100-SO-CR Unified Wire Ethernet Controller + 6409 T6210-BT Unified Wire Ethernet Controller + 640d T62100-CR Unified Wire Ethernet Controller + 6411 T6225-LL-CR Unified Wire Ethernet Controller + 6414 T61100-OCP-SO Unified Wire Ethernet Controller + 6415 T6201-BT Unified Wire Ethernet Controller + 6480 T6225-6080 Unified Wire Ethernet Controller + 6481 T62100-6081 Unified Wire Ethernet Controller + 6482 T6225-6082 Unified Wire Ethernet Controller + 6483 T62100-6083 Unified Wire Ethernet Controller + 6484 T64100-6084 Unified Wire Ethernet Controller + 6485 T6240-6085 Unified Wire Ethernet Controller + 6486 T6225-6086 Unified Wire Ethernet Controller + 6487 T6225-6087 Unified Wire Ethernet Controller + 6488 T62100-6088 Unified Wire Ethernet Controller + 6489 T62100-6089 Unified Wire Ethernet Controller + 648a T62100-608a Unified Wire Ethernet Controller + 6501 T6225-CR Unified Wire Storage Controller + 6502 T6225-SO-CR Unified Wire Storage Controller + 6503 T6425-CR Unified Wire Storage Controller + 6504 T6425-SO-CR Unified Wire Storage Controller + 6505 T6225-OCP-SO Unified Wire Storage Controller + 6506 T62100-OCP-SO Unified Wire Storage Controller + 6507 T62100-LP-CR Unified Wire Storage Controller + 6508 T62100-SO-CR Unified Wire Storage Controller + 6509 T6210-BT Unified Wire Storage Controller + 650d T62100-CR Unified Wire Storage Controller + 6511 T6225-LL-CR Unified Wire Storage Controller + 6514 T61100-OCP-SO Unified Wire Storage Controller + 6515 T6201-BT Unified Wire Storage Controller + 6580 T6225-6080 Unified Wire Storage Controller + 6581 T62100-6081 Unified Wire Storage Controller + 6582 T6225-6082 Unified Wire Storage Controller + 6583 T62100-6083 Unified Wire Storage Controller + 6584 T64100-6084 Unified Wire Storage Controller + 6585 T6240-6085 Unified Wire Storage Controller + 6586 T6225-6086 Unified Wire Storage Controller + 6587 T6225-6087 Unified Wire Storage Controller + 6588 T62100-6088 Unified Wire Storage Controller + 6589 T62100-6089 Unified Wire Storage Controller + 658a T62100-608a Unified Wire Storage Controller + 6601 T6225-CR Unified Wire Storage Controller + 6602 T6225-SO-CR Unified Wire Storage Controller + 6603 T6425-CR Unified Wire Storage Controller + 6604 T6425-SO-CR Unified Wire Storage Controller + 6605 T6225-OCP-SO Unified Wire Storage Controller + 6606 T62100-OCP-SO Unified Wire Storage Controller + 6607 T62100-LP-CR Unified Wire Storage Controller + 6608 T62100-SO-CR Unified Wire Storage Controller + 6609 T6210-BT Unified Wire Storage Controller + 660d T62100-CR Unified Wire Storage Controller + 6611 T6225-LL-CR Unified Wire Storage Controller + 6614 T61100-OCP-SO Unified Wire Storage Controller + 6615 T6201-BT Unified Wire Storage Controller + 6680 T6225-6080 Unified Wire Storage Controller + 6681 T62100-6081 Unified Wire Storage Controller + 6682 T6225-6082 Unified Wire Storage Controller + 6683 T62100-6083 Unified Wire Storage Controller + 6684 T64100-6084 Unified Wire Storage Controller + 6685 T6240-6085 Unified Wire Storage Controller + 6686 T6225-6086 Unified Wire Storage Controller + 6687 T6225-6087 Unified Wire Storage Controller + 6688 T62100-6088 Unified Wire Storage Controller + 6689 T62100-6089 Unified Wire Storage Controller + 668a T62100-608a Unified Wire Storage Controller + 6801 T6225-CR Unified Wire Ethernet Controller [VF] + 6802 T6225-SO-CR Unified Wire Ethernet Controller [VF] + 6803 T6425-CR Unified Wire Ethernet Controller [VF] + 6804 T6425-SO-CR Unified Wire Ethernet Controller [VF] + 6805 T6225-OCP-SO Unified Wire Ethernet Controller [VF] + 6806 T62100-OCP-SO Unified Wire Ethernet Controller [VF] + 6807 T62100-LP-CR Unified Wire Ethernet Controller [VF] + 6808 T62100-SO-CR Unified Wire Ethernet Controller [VF] + 6809 T6210-BT Unified Wire Ethernet Controller [VF] + 680d T62100-CR Unified Wire Ethernet Controller [VF] + 6811 T6225-LL-CR Unified Wire Ethernet Controller [VF] + 6814 T61100-OCP-SO Unified Wire Ethernet Controller [VF] + 6815 T6201-BT Unified Wire Ethernet Controller [VF] + 6880 T6225-6080 Unified Wire Ethernet Controller [VF] + 6881 T62100-6081 Unified Wire Ethernet Controller [VF] + 6882 T6225-6082 Unified Wire Ethernet Controller [VF] + 6883 T62100-6083 Unified Wire Ethernet Controller [VF] + 6884 T64100-6084 Unified Wire Ethernet Controller [VF] + 6885 T6240-6085 Unified Wire Ethernet Controller [VF] + 6886 T6225-6086 Unified Wire Ethernet Controller [VF] + 6887 T6225-6087 Unified Wire Ethernet Controller [VF] + 6888 T62100-6088 Unified Wire Ethernet Controller [VF] + 6889 T62100-6089 Unified Wire Ethernet Controller [VF] + 688a T62100-608a Unified Wire Ethernet Controller [VF] + a000 PE10K Unified Wire Ethernet Controller +1426 Storage Technology Corp. +1427 Better On-Line Solutions +1428 Edec Co Ltd +1429 Unex Technology Corp. +142a Kingmax Technology Inc +142b Radiolan +142c Minton Optic Industry Co Ltd +142d Pix stream Inc +142e Vitec Multimedia + 4020 VM2-2 [Video Maker 2] MPEG1/2 Encoder + 4337 VM2-2-C7 [Video Maker 2 rev. C7] MPEG1/2 Encoder +142f Radicom Research Inc +1430 ITT Aerospace/Communications Division +1431 Gilat Satellite Networks +1432 Edimax Computer Co. + 9130 RTL81xx Fast Ethernet +1433 Eltec Elektronik GmbH +# Nee Real Time Devices US Inc. +1435 RTD Embedded Technologies, Inc. + 4520 PCI4520 + 6020 SPM6020 + 6030 SPM6030 + 6420 SPM186420 + 6430 SPM176430 + 6431 SPM176431 + 7520 DM7520 + 7540 SDM7540 + 7820 DM7820 +1436 CIS Technology Inc +1437 Nissin Inc Co +1438 Atmel-dream +1439 Outsource Engineering & Mfg. Inc +143a Stargate Solutions Inc +143b Canon Research Center, America +143c Amlogic Inc +143d Tamarack Microelectronics Inc +143e Jones Futurex Inc +143f Lightwell Co Ltd - Zax Division +1440 ALGOL Corp. +1441 AGIE Ltd +1442 Phoenix Contact GmbH & Co. +1443 Unibrain S.A. +1444 TRW +1445 Logical DO Ltd +1446 Graphin Co Ltd +1447 AIM GmBH +1448 Alesis Studio Electronics +1449 TUT Systems Inc +144a Adlink Technology + 6208 PCI-6208V + 7250 PCI-7250 + 7296 PCI-7296 + 7432 PCI-7432 + 7433 PCI-7433 + 7434 PCI-7434 + 7841 PCI-7841 + 8133 PCI-8133 + 8164 PCI-8164 + 8554 PCI-8554 + 9111 PCI-9111 + 9113 PCI-9113 + 9114 PCI-9114 +# 2-16 MB SRAM, 4x UART, I2C, misc I/O + a001 ADi-BSEC +# nee Loronix Information Systems Inc. +144b Verint Systems Inc. +144c Catalina Research Inc +144d Samsung Electronics Co Ltd + 1600 Apple PCIe SSD + a800 XP941 PCIe SSD + a802 NVMe SSD Controller SM951/PM951 + a804 NVMe SSD Controller SM961/PM961 + a808 NVMe SSD Controller SM981/PM981/PM983 + 1d49 403b Thinksystem U.2 PM983 NVMe SSD + a820 NVMe SSD Controller 171X + 1028 1f95 Express Flash NVMe XS1715 SSD 400GB + 1028 1f96 Express Flash NVMe XS1715 SSD 800GB + 1028 1f97 Express Flash NVMe XS1715 SSD 1600GB + 1028 1fa4 Express Flash NVMe SM1715 3.2TB SFF + 1028 1fa6 Express Flash NVMe SM1715 3.2TB AIC + 1028 1fba Express Flash NVMe SM1715 800GB SFF + 1028 1fbb Express Flash NVMe SM1715 1.6TB SFF + 1028 1fbc Express Flash NVMe SM1715 1.6TB AIC + a821 NVMe SSD Controller 172X + 1028 1fb7 Express Flash NVMe PM1725 3.2TB SFF + 1028 1fb8 Express Flash NVMe PM1725 3.2TB AIC + 1028 1fb9 Express Flash NVMe PM1725 6.4TB AIC + 1028 1fc1 Express Flash NVMe PM1725 800GB SFF + 1028 1fc2 Express Flash NVMe PM1725 1.6TB SFF + 1028 1fc4 Express Flash NVMe PM1725 1.6TB AIC + a822 NVMe SSD Controller 172Xa/172Xb + 1014 0621 PCIe3 1.6TB NVMe Flash Adapter II x8 + 1014 0622 PCIe3 3.2TB NVMe Flash Adapter II x8 + 1014 0629 PCIe3 6.4TB NVMe Flash Adapter II x8 + 1014 064a PCIe3 1.6TB NVMe Flash Adapter III x8 + 1014 064b PCIe3 3.2TB NVMe Flash Adapter III x8 + 1014 064c PCIe3 6.4TB NVMe Flash Adapter III x8 + 1028 1fd9 Express Flash PM1725a 800GB SFF + 1028 1fda Express Flash PM1725a 1.6TB SFF + 1028 1fdb Express Flash PM1725a 3.2TB SFF + 1028 1fdc Express Flash PM1725a 6.4TB SFF + 1028 1fdd Express Flash PM1725a 1.6TB AIC + 1028 1fde Express Flash PM1725a 3.2TB AIC + 1028 1fdf Express Flash PM1725a 6.4TB AIC + 1028 1ff3 Express Flash PM1725b 1.6TB SFF + 1028 1ff4 Express Flash PM1725b 3.2TB SFF + 1028 1ff5 Express Flash PM1725b 6.4TB SFF + 1028 1ff6 Express Flash PM1725b 12.8TB SFF + 1028 1ff7 Express Flash PM1725b 1.6TB AIC + 1028 1ff8 Express Flash PM1725b 3.2TB AIC + 1028 1ff9 Express Flash PM1725b 6.4TB AIC + 1028 1ffa Express Flash PM1725b 12.8TB AIC +144e OLITEC +144f Askey Computer Corp. +1450 Octave Communications Ind. +1451 SP3D Chip Design GmBH +1453 MYCOM Inc +1454 Altiga Networks +1455 Logic Plus Plus Inc +1456 Advanced Hardware Architectures +1457 Nuera Communications Inc +1458 Gigabyte Technology Co., Ltd +1459 DOOIN Electronics +145a Escalate Networks Inc +145b PRAIM SRL +145c Cryptek +145d Gallant Computer Inc +145e Aashima Technology B.V. +145f Baldor Electric Company + 0001 NextMove PCI +1460 DYNARC INC +1461 Avermedia Technologies Inc + a3ce M179 + a3cf M179 + a836 M115 DVB-T, PAL/SECAM/NTSC Tuner + e836 M115S Hybrid Analog/DVB PAL/SECAM/NTSC Tuner + f436 AVerTV Hybrid+FM +1462 Micro-Star International Co., Ltd. [MSI] + aaf0 Radeon RX 580 Gaming X 8G +1463 Fast Corporation +1464 Interactive Circuits & Systems Ltd +1465 GN NETTEST Telecom DIV. +1466 Designpro Inc. +1467 DIGICOM SPA +1468 AMBIT Microsystem Corp. +1469 Cleveland Motion Controls +# formerly IFR. +146a Aeroflex +# 1.5 GHz to 3.0 GHz x 1Hz + 3010 3010 RF Synthesizer + 3a11 3011A PXI RF Synthesizer +146b Parascan Technologies Ltd +146c Ruby Tech Corp. + 1430 FE-1430TX Fast Ethernet PCI Adapter +146d Tachyon, INC. +146e Williams Electronics Games, Inc. +146f Multi Dimensional Consulting Inc +1470 Bay Networks +1471 Integrated Telecom Express Inc +1472 DAIKIN Industries, Ltd +1473 ZAPEX Technologies Inc +1474 Doug Carson & Associates +1475 PICAZO Communications +1476 MORTARA Instrument Inc +1477 Net Insight +1478 DIATREND Corporation +1479 TORAY Industries Inc +147a FORMOSA Industrial Computing +147b ABIT Computer Corp. + 1084 IP35 [Dark Raider] +147c AWARE, Inc. +147d Interworks Computer Products +147e Matsushita Graphic Communication Systems, Inc. +147f NIHON UNISYS, Ltd. +1480 SCII Telecom +1481 BIOPAC Systems Inc +1482 ISYTEC - Integrierte Systemtechnik GmBH + 0001 PCI-16 Host Interface for ITC-16 +1483 LABWAY Corporation +1484 Logic Corporation +1485 ERMA - Electronic GmBH +1486 L3 Communications Telemetry & Instrumentation +1487 MARQUETTE Medical Systems +1489 KYE Systems Corporation +148a OPTO +148b INNOMEDIALOGIC Inc. +148c Tul Corporation / PowerColor +148d DIGICOM Systems, Inc. + 1003 HCF 56k Data/Fax Modem +148e OSI Plus Corporation +148f Plant Equipment, Inc. +1490 Stone Microsystems PTY Ltd. +1491 ZEAL Corporation +1492 Time Logic Corporation +1493 MAKER Communications +1494 WINTOP Technology, Inc. +1495 TOKAI Communications Industry Co. Ltd +1496 JOYTECH Computer Co., Ltd. +1497 SMA Regelsysteme GmBH + 1497 SMA Technologie AG +1498 TEWS Technologies GmbH + 0330 TPMC816 2 Channel CAN bus controller. + 035d TPMC861 4-Channel Isolated Serial Interface RS422/RS485 + 0385 TPMC901 Extended CAN bus with 2/4/6 CAN controller + 21cc TCP460 CompactPCI 16 Channel Serial Interface RS232/RS422 + 21cd TCP461 CompactPCI 8 Channel Serial Interface RS232/RS422 + 3064 TPCI100 (2 Slot IndustryPack PCI Carrier) + 30c8 TPCI200 4 Slot IndustryPack PCI Carrier + 70c8 TPCE200 4 Slot IndustryPack PCIe Carrier + 9177 TXMC375 8 channel RS232/RS422/RS485 programmable serial interface +1499 EMTEC CO., Ltd +149a ANDOR Technology Ltd +149b SEIKO Instruments Inc +149c OVISLINK Corp. +149d NEWTEK Inc + 0001 Video Toaster for PC +149e Mapletree Networks Inc. +149f LECTRON Co Ltd +14a0 SOFTING GmBH +14a1 Systembase Co Ltd +14a2 Millennium Engineering Inc +14a3 Maverick Networks +14a4 Lite-On Technology Corporation + 22f1 M8Pe Series NVMe SSD +# Wrong vendor ID used + 4318 Broadcom BCM4318 [AirForce One 54g] 802.11g WLAN Controller +14a5 XIONICS Document Technologies Inc +14a6 INOVA Computers GmBH & Co KG +14a7 MYTHOS Systems Inc +14a8 FEATRON Technologies Corporation +14a9 HIVERTEC Inc +14aa Advanced MOS Technology Inc +14ab Mentor Graphics Corp. +14ac Novaweb Technologies Inc +14ad Time Space Radio AB +14ae CTI, Inc +14af Guillemot Corporation + 7102 3D Prophet II MX +14b0 BST Communication Technology Ltd +14b1 Nextcom K.K. +14b2 ENNOVATE Networks Inc +14b3 XPEED Inc + 0000 DSL NIC +14b4 PHILIPS Business Electronics B.V. +14b5 Creamware GmBH + 0200 Scope + 0300 Pulsar + 0400 PulsarSRB + 0600 Pulsar2 + 0800 DSP-Board + 0900 DSP-Board + 0a00 DSP-Board + 0b00 DSP-Board +14b6 Quantum Data Corp. +14b7 PROXIM Inc + 0001 Symphony 4110 +14b8 Techsoft Technology Co Ltd +14b9 Cisco Aironet Wireless Communications + 0001 PC4800 + 0340 PC4800 + 0350 350 series 802.11b Wireless LAN Adapter + 4500 PC4500 + 4800 Cisco Aironet 340 802.11b Wireless LAN Adapter/Aironet PC4800 + a504 Cisco Aironet Wireless 802.11b + a505 Cisco Aironet CB20a 802.11a Wireless LAN Adapter + a506 Cisco Aironet Mini PCI b/g +14ba INTERNIX Inc. +# ARCNET interface card based on SMSC COM20022 chip and manufactured for SMSC Japan + 0600 ARC-PCI/22 +14bb SEMTECH Corporation +14bc Globespan Semiconductor Inc. + d002 Pulsar [PCI ADSL Card] + d00f Pulsar [PCI ADSL Card] +14bd CARDIO Control N.V. +14be L3 Communications +14bf SPIDER Communications Inc. +14c0 COMPAL Electronics Inc + 1201 X550 10Gb 2P RJ45 OCP Mezz +# now owned by CSP, Inc. +14c1 MYRICOM Inc. + 0008 Myri-10G Dual-Protocol NIC + 14c1 0008 10G-PCIE-8A + 14c1 0009 10G-PCIE-8A (MSI-X firmware) + 14c1 000a 10G-PCIE-8B + 8043 Myrinet 2000 Scalable Cluster Interconnect + 103c 1240 Myrinet M2L-PCI64/2-3.0 LANai 7.4 (HP OEM) +14c2 DTK Computer +14c3 MEDIATEK Corp. + 7630 MT7630e 802.11bgn Wireless Network Adapter +# MT7612E too? + 7662 MT7662E 802.11ac PCI Express Wireless Network Adapter +14c4 IWASAKI Information Systems Co Ltd +14c5 Automation Products AB +14c6 Data Race Inc +14c7 Modular Technology Holdings Ltd +14c8 Turbocomm Tech. Inc. +14c9 ODIN Telesystems Inc +14ca PE Logic Corp. +14cb Billionton Systems Inc +14cc NAKAYO Telecommunications Inc +14cd Universal Global Scientific Industrial Co.,Ltd + 0001 USI-1514-1GbaseT [OCP1] + 0002 USI-4227-SFP [OCP2] + 0003 USI-X557-10GbaseT [OCP3] +14ce Whistle Communications +14cf TEK Microsystems Inc. +14d0 Ericsson Axe R & D +14d1 Computer Hi-Tech Co Ltd +14d2 Titan Electronics Inc + 8001 VScom 010L 1 port parallel adaptor + 8002 VScom 020L 2 port parallel adaptor + 8010 VScom 100L 1 port serial adaptor + 8011 VScom 110L 1 port serial and 1 port parallel adaptor + 8020 VScom 200L 1 or 2 port serial adaptor + 8021 VScom 210L 2 port serial and 1 port parallel adaptor + 8028 VScom 200I/200I-SI 2-port serial adapter + 8040 VScom 400L 4 port serial adaptor + 8043 VScom 430L 4-port serial and 3-port parallel adapter + 8048 VScom 400I 4-port serial adapter + 8080 VScom 800L 8 port serial adaptor + 8088 VScom 800I 8-port serial adapter + a000 VScom 010H 1 port parallel adaptor + a001 VScom 100H 1 port serial adaptor + a003 VScom 400H 4 port serial adaptor + a004 VScom 400HF1 4 port serial adaptor + a005 VScom 200H 2 port serial adaptor + a007 VScom PCI800EH (PCIe) 8-port serial adapter Port 1-4 + a008 VScom PCI800EH (PCIe) 8-port serial adapter Port 5-8 + a009 VScom PCI400EH (PCIe) 4-port serial adapter + e001 VScom 010HV2 1 port parallel adaptor + e010 VScom 100HV2 1 port serial adaptor + e020 VScom 200HV2 2 port serial adaptor +14d3 CIRTECH (UK) Ltd + 0002 DTL-T14000 Rev. 1 [PS2 TOOL CD/DVD Emulator] + 0003 DTL-T14000 Rev. 2 [PS2 TOOL CD/DVD Emulator] + 0004 DTL-T14000 Rev. 3 [PS2 TOOL CD/DVD Emulator] +14d4 Panacom Technology Corp +14d5 Nitsuko Corporation +14d6 Accusys Inc + 6101 ACS-61xxx, PCIe to SAS/SATA RAID HBA + 6201 ACS-62xxx, External PCIe to SAS/SATA RAID controller +14d7 Hirakawa Hewtech Corp +14d8 HOPF Elektronik GmBH +# Formerly SiPackets, Inc., formerly API NetWorks, Inc., formerly Alpha Processor, Inc. +14d9 Alliance Semiconductor Corporation + 0010 AP1011/SP1011 HyperTransport-PCI Bridge [Sturgeon] + 9000 AS90L10204/10208 HyperTransport to PCI-X Bridge +14da National Aerospace Laboratories +14db AFAVLAB Technology Inc + 2120 TK9902 + 2182 AFAVLAB Technology Inc. 8-port serial card +14dc Amplicon Liveline Ltd + 0000 PCI230 + 0001 PCI242 + 0002 PCI244 + 0003 PCI247 + 0004 PCI248 + 0005 PCI249 + 0006 PCI260 + 0007 PCI224 + 0008 PCI234 + 0009 PCI236 + 000a PCI272 + 000b PCI215 +14dd Boulder Design Labs Inc +14de Applied Integration Corporation +14df ASIC Communications Corp +14e1 INVERTEX +14e2 INFOLIBRIA +14e3 AMTELCO +14e4 Broadcom Inc. and subsidiaries + 0576 BCM43224 802.11a/b/g/n + 0800 Sentry5 Chipcommon I/O Controller + 0804 Sentry5 PCI Bridge + 0805 Sentry5 MIPS32 CPU + 0806 Sentry5 Ethernet Controller + 080b Sentry5 Crypto Accelerator + 080f Sentry5 DDR/SDR RAM Controller + 0811 Sentry5 External Interface Core + 0816 BCM3302 Sentry5 MIPS32 CPU + 1570 720p FaceTime HD Camera + 1600 NetXtreme BCM5752 Gigabit Ethernet PCI Express + 1028 01c1 Precision 490 + 1028 01c2 Latitude D620 + 103c 3015 PCIe LAN on Motherboard + 107b 5048 E4500 Onboard + 1259 2705 AT-2711FX + 1601 NetXtreme BCM5752M Gigabit Ethernet PCI Express + 1604 BCM5745X NetXtreme-E Ethernet Partition + 1605 BCM5745X NetXtreme-E RDMA Partition + 1606 BCM5745X NetXtreme-E RDMA Virtual Function + 1609 BCM5745X NetXtreme-E Ethernet Virtual Function + 1612 BCM70012 Video Decoder [Crystal HD] + 1614 BCM57454 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet + 1615 BCM70015 Video Decoder [Crystal HD] + 1639 NetXtreme II BCM5709 Gigabit Ethernet + 1028 0235 PowerEdge R710 BCM5709 Gigabit Ethernet + 1028 0236 PowerEdge R610 BCM5709 Gigabit Ethernet + 1028 0237 PowerEdge T610 BCM5709 Gigabit Ethernet + 103c 7055 NC382i Integrated Multi-port PCI Express Gigabit Server Adapter + 103c 7059 NC382T PCIe Dual Port Multifunction Gigabit Server Adapter + 10a9 8027 Quad port Gigabit Ethernet Controller + 163a NetXtreme II BCM5709S Gigabit Ethernet + 1028 027b PowerEdge M805 Broadcom NetXtreme II BCM5709S + 1028 029c PowerEdge M710 BCM5709S Gigabit Ethernet + 103c 171d NC382m Dual Port 1GbE Multifunction BL-c Adapter + 103c 7056 NC382i Integrated Quad Port PCI Express Gigabit Server Adapter + 1259 2984 AT-2973SX + 163b NetXtreme II BCM5716 Gigabit Ethernet + 1028 028c PowerEdge R410 BCM5716 Gigabit Ethernet + 1028 028d PowerEdge T410 BCM5716 Gigabit Ethernet + 1028 02f1 PowerEdge R510 BCM5716 Gigabit Ethernet + 163c NetXtreme II BCM5716S Gigabit Ethernet + 163d NetXtreme II BCM57811 10-Gigabit Ethernet + 1043 858a PEB-10G/57811-1S + 163e NetXtreme II BCM57811 10 Gigabit Ethernet Multi Function + 163f NetXtreme II BCM57811 10-Gigabit Ethernet Virtual Function + 1641 NetXtreme BCM57787 Gigabit Ethernet PCIe + 1642 NetXtreme BCM57764 Gigabit Ethernet PCIe + 1643 NetXtreme BCM5725 Gigabit Ethernet PCIe + 1644 NetXtreme BCM5700 Gigabit Ethernet + 1014 0277 Broadcom Vigil B5700 1000Base-T + 1028 00d1 Broadcom BCM5700 + 1028 0106 Broadcom BCM5700 + 1028 0109 Broadcom BCM5700 1000Base-T + 1028 010a Broadcom BCM5700 1000BaseTX + 10b7 1000 3C996-T 1000Base-T + 10b7 1001 3C996B-T 1000Base-T + 10b7 1002 3C996C-T 1000Base-T + 10b7 1003 3C997-T 1000Base-T Dual Port + 10b7 1004 3C996-SX 1000Base-SX + 10b7 1005 3C997-SX 1000Base-SX Dual Port + 10b7 1008 3C942 Gigabit LOM (31X31) + 14e4 0002 NetXtreme 1000Base-SX + 14e4 0003 NetXtreme 1000Base-SX + 14e4 0004 NetXtreme 1000Base-T + 14e4 1028 NetXtreme 1000BaseTX + 14e4 1644 BCM5700 1000Base-T + 1645 NetXtreme BCM5701 Gigabit Ethernet + 0e11 007c NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T) + 0e11 007d NC6770 Gigabit Server Adapter (PCI-X, 1000-SX) + 0e11 0085 NC7780 Gigabit Server Adapter (embedded, WOL) + 0e11 0099 NC7780 Gigabit Server Adapter (embedded, WOL) + 0e11 009a NC7770 Gigabit Server Adapter (PCI-X, 10/100/1000-T) + 0e11 00c1 NC6770 Gigabit Server Adapter (PCI-X, 1000-SX) + 1028 0121 Broadcom BCM5701 1000Base-T + 103c 128a BCM5701 1000Base-T (HP, OEM 3COM) + 103c 128b 1000Base-SX (PCI) [A7073A] + 103c 12a4 Core Lan 1000Base-T + 103c 12c1 IOX Core Lan 1000Base-T [A7109AX] + 103c 1300 Core LAN/SCSI Combo [A6794A] + 10a9 8010 IO9/IO10 Gigabit Ethernet (Copper) + 10a9 8011 Gigabit Ethernet (Copper) + 10a9 8012 Gigabit Ethernet (Fiber) + 10b7 1004 3C996-SX 1000Base-SX + 10b7 1006 3C996B-T 1000Base-T + 10b7 1007 3C1000-T 1000Base-T + 10b7 1008 3C940-BR01 1000Base-T + 14e4 0001 BCM5701 1000Base-T + 14e4 0005 BCM5701 1000Base-T + 14e4 0006 BCM5701 1000Base-T + 14e4 0007 BCM5701 1000Base-SX + 14e4 0008 BCM5701 1000Base-T + 14e4 1645 NetXtreme BCM5701 Gigabit Ethernet + 14e4 8008 BCM5701 1000Base-T + 1646 NetXtreme BCM5702 Gigabit Ethernet + 0e11 00bb NC7760 1000BaseTX + 1028 0126 Broadcom BCM5702 1000BaseTX + 14e4 8009 BCM5702 1000BaseTX + 1647 NetXtreme BCM5703 Gigabit Ethernet + 0e11 0099 NC7780 1000BaseTX + 0e11 009a NC7770 1000BaseTX + 10a9 8010 IO9 Gigabit Ethernet (Copper) + 14e4 0009 BCM5703 1000BaseTX + 14e4 000a BCM5703 1000BaseSX + 14e4 000b BCM5703 1000BaseTX + 14e4 8009 BCM5703 1000BaseTX + 14e4 800a BCM5703 1000BaseTX + 1648 NetXtreme BCM5704 Gigabit Ethernet + 0e11 00cf NC7772 Gigabit Server Adapter (PCI-X, 10,100,1000-T) + 0e11 00d0 NC7782 Gigabit Server Adapter (PCI-X, 10,100,1000-T) + 0e11 00d1 NC7783 Gigabit Server Adapter (PCI-X, 10,100,1000-T) + 1028 014a PowerEdge 1750 + 1028 0170 PowerEdge 6850 Broadcom NetXtreme BCM5704 + 103c 310f NC7782 Gigabit Server Adapter (PCI-X, 10,100,1000-T) + 10a9 8013 Dual Port Gigabit Ethernet (PCI-X,Copper) + 10a9 8018 Dual Port Gigabit Ethernet (A330) + 10a9 801a Dual Port Gigabit Ethernet (IA-blade) + 10a9 801b Quad Port Gigabit Ethernet (PCI-E,Copper) + 10b7 2000 3C998-T Dual Port 10/100/1000 PCI-X + 10b7 3000 3C999-T Quad Port 10/100/1000 PCI-X + 1166 1648 NetXtreme CIOB-E 1000Base-T + 1734 100b PRIMERGY RX/TX series onboard LAN + 1649 NetXtreme BCM5704S_2 Gigabit Ethernet + 164a NetXtreme II BCM5706 Gigabit Ethernet + 103c 1709 NC371i Integrated PCI-X Multifunction Gigabit Server Adapter + 103c 3070 NC380T PCI Express Dual Port Multifunction Gigabit Server Adapter + 103c 3101 NC370T MultifuNCtion Gigabit Server Adapter + 103c 3106 NC370i Multifunction Gigabit Server Adapter + 164c NetXtreme II BCM5708 Gigabit Ethernet + 1028 01f0 PowerEdge R900 Broadcom NetXtreme II BCM5708 + 1028 0205 PowerEdge 2970 Broadcom NetXtreme II BCM5708 + 1028 020b PowerEdge T605 Broadcom NetXtreme II BCM5708 + 1028 0221 PowerEdge R805 Broadcom NetXtreme II BCM5708 + 1028 0223 PowerEdge R905 Broadcom NetXtreme II BCM5708 + 1028 1f12 PowerEdge R805/R905 Broadcom NetXtreme II BCM5708 + 103c 7037 NC373T PCI Express Multifunction Gigabit Server Adapter + 103c 7038 NC373i Integrated Multifunction Gigabit Server Adapter + 103c 7045 NC374m PCI Express Dual Port Multifunction Gigabit Server Adapter + 164d NetXtreme BCM5702FE Gigabit Ethernet + 164e NetXtreme II BCM57710 10-Gigabit PCIe [Everest] + 103c 171c NC532m Dual Port 10GbE Multifunction BL-C Adapter + 103c 7058 NC532i Dual Port 10GbE Multifunction BL-C Adapter + 164f NetXtreme II BCM57711 10-Gigabit PCIe + 1650 NetXtreme II BCM57711E 10-Gigabit PCIe + 103c 171c NC532m Dual Port 10GbE Multifunction BL-C Adapter + 103c 7058 NC532i Dual Port 10GbE Multifunction BL-C Adapter + 1653 NetXtreme BCM5705 Gigabit Ethernet + 0e11 00e3 NC7761 Gigabit Server Adapter + 1734 1073 Primergy Econel 200 D2020 mainboard + 1654 NetXtreme BCM5705_2 Gigabit Ethernet + 0e11 00e3 NC7761 Gigabit Server Adapter + 103c 3100 NC1020 ProLiant Gigabit Server Adapter 32 PCI + 103c 3226 NC150T 4-port Gigabit Combo Switch & Adapter + 1655 NetXtreme BCM5717 Gigabit Ethernet PCIe + 1656 NetXtreme BCM5718 Gigabit Ethernet PCIe + 1657 NetXtreme BCM5719 Gigabit Ethernet PCIe + 1014 0420 FC 5260/5899 4-port 1 GbE Adapter for Power + 103c 169d Ethernet 1Gb 4-port 331FLR Adapter + 103c 22be Ethernet 1Gb 4-port 331i Adapter + 103c 3383 Ethernet 1Gb 4-port 331T Adapter + 14e4 1904 4-port 1Gb Ethernet Adapter + 1659 NetXtreme BCM5721 Gigabit Ethernet PCI Express + 1014 02c6 eServer xSeries server mainboard + 1028 01e6 PowerEdge 860 + 1028 023c PowerEdge R200 Broadcom NetXtreme BCM5721 + 103c 170b NC320m PCI Express Dual Port Gigabit Server Adapter + 103c 7031 NC320T PCIe Gigabit Server Adapter + 103c 7032 NC320i PCIe Gigabit Server Adapter + 1734 1061 PRIMERGY RX/TX S2 series onboard LAN + 165a NetXtreme BCM5722 Gigabit Ethernet PCI Express +# Dual NIC server + 1014 0378 System x3350 (Machine type 4192) + 1028 020f PowerEdge R300 Broadcom NetXtreme 5722 + 1028 0210 PowerEdge T300 Broadcom NetXtreme 5722 + 1028 0225 PowerEdge T105 Broadcom NetXtreme 5722 + 103c 7051 NC105i PCIe Gigabit Server Adapter + 103c 7052 NC105T PCIe Gigabit Server Adapter + 165b NetXtreme BCM5723 Gigabit Ethernet PCIe + 103c 705d NC107i Integrated PCI Express Gigabit Server Adapter + 165c NetXtreme BCM5724 Gigabit Ethernet PCIe + 165d NetXtreme BCM5705M Gigabit Ethernet + 1028 865d Latitude D400 + 14e4 165d Dell Latitude D600 + 165e NetXtreme BCM5705M_2 Gigabit Ethernet + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 103c 099c NX6110/NC6120 + 10cf 1279 LifeBook E8010D + 165f NetXtreme BCM5720 2-port Gigabit Ethernet PCIe + 1028 04f7 PowerEdge R320 server + 1028 08fd PowerEdge R6515/R7515 LOM + 1028 08ff PowerEdge Rx5xx LOM Board + 1028 0900 PowerEdge C6525 LOM + 103c 1786 NC332T Adapter + 103c 193d NC332i Adapter + 103c 2133 NC332i Adapter + 103c 22e8 NC332i Adapter + 103c 22eb NC332i Adapter + 1662 NetXtreme II BCM57712 10 Gigabit Ethernet + 1663 NetXtreme II BCM57712 10 Gigabit Ethernet Multi Function + 1665 NetXtreme BCM5717 Gigabit Ethernet PCIe + 1668 NetXtreme BCM5714 Gigabit Ethernet + 103c 7039 NC324i PCIe Dual Port Gigabit Server Adapter + 1669 NetXtreme 5714S Gigabit Ethernet + 166a NetXtreme BCM5780 Gigabit Ethernet + 103c 7035 NC325i Integrated Dual port PCIe Express Gigabit Server Adapter + 166b NetXtreme BCM5780S Gigabit Ethernet + 166e 570x 10/100 Integrated Controller + 166f NetXtreme II BCM57712 10 Gigabit Ethernet Virtual Function + 1672 NetXtreme BCM5754M Gigabit Ethernet PCI Express + 1673 NetXtreme BCM5755M Gigabit Ethernet PCI Express + 1674 NetXtreme BCM5756ME Gigabit Ethernet PCI Express + 1677 NetXtreme BCM5751 Gigabit Ethernet PCI Express + 1028 0176 Dimension XPS Gen 4 + 1028 0177 Dimension 8400 + 1028 0179 Optiplex GX280 + 1028 0182 Latitude D610 + 1028 0187 Precision M70 + 1028 01a3 Latitude X1 + 1028 01a8 Precision 380 + 1028 01ad OptiPlex GX620 + 103c 3006 DC7100 SFF(DX878AV) + 1462 028c 915P/G Neo2 + 1734 105d Scenic W620 + 1678 NetXtreme BCM5715 Gigabit Ethernet + 103c 703e NC326i PCIe Dual Port Gigabit Server Adapter + 1679 NetXtreme BCM5715S Gigabit Ethernet + 103c 1707 NC326m PCIe Dual Port Adapter + 103c 170c NC325m PCIe Quad Port Adapter + 103c 703c NC326i PCIe Dual Port Gigabit Server Adapter + 167a NetXtreme BCM5754 Gigabit Ethernet PCI Express + 1028 01da OptiPlex 745 + 1028 01de Precision 390 + 1028 01df PowerEdge SC440 + 1028 0214 Precision T3400 + 1028 021e Precision T5400 + 167b NetXtreme BCM5755 Gigabit Ethernet PCI Express + 103c 280a DC5750 Microtower + 167d NetXtreme BCM5751M Gigabit Ethernet PCI Express + 1014 0577 ThinkPad X41 / Z60t + 103c 0934 nx8220 + 103c 0940 Compaq nw8240 Mobile Workstation + 103c 0944 Compaq nc6220 Notebook PC + 17aa 2081 ThinkPad R60e + 167e NetXtreme BCM5751F Fast Ethernet PCI Express + 167f NetLink BCM5787F Fast Ethernet PCI Express + 1680 NetXtreme BCM5761e Gigabit Ethernet PCIe + 1681 NetXtreme BCM5761 Gigabit Ethernet PCIe + 1682 NetXtreme BCM57762 Gigabit Ethernet PCIe + 106b 00f6 Thunderbolt to Gigabit Ethernet Adapter + 1683 NetXtreme BCM57767 Gigabit Ethernet PCIe + 1684 NetXtreme BCM5764M Gigabit Ethernet PCIe + 1685 NetXtreme II BCM57500S Gigabit Ethernet + 1686 NetXtreme BCM57766 Gigabit Ethernet PCIe + 1687 NetXtreme BCM5762 Gigabit Ethernet PCIe + 1688 NetXtreme BCM5761 10/100/1000BASE-T Ethernet + 1259 2708 AT-2712 FX +# The Broadcom 57800 device has two 1Gig ports and two 10Gig ports. The subsystem information can be used to differentiate. + 168a NetXtreme II BCM57800 1/10 Gigabit Ethernet + 1028 1f5c BCM57800 10-Gigabit Ethernet + 1028 1f5d BCM57800 10-Gigabit Ethernet + 1028 1f67 BCM57800 1-Gigabit Ethernet + 1028 1f68 BCM57800 1-Gigabit Ethernet + 168d NetXtreme II BCM57840 10/20 Gigabit Ethernet + 168e NetXtreme II BCM57810 10 Gigabit Ethernet + 1014 0492 PCIe2 2-port 10 GbE BaseT RJ45 Adapter (FC EN0W; CCIN 2CC4) + 103c 1798 Flex-10 10Gb 2-port 530FLB Adapter [Meru] + 103c 17a5 Flex-10 10Gb 2-port 530M Adapter + 103c 18d3 Ethernet 10Gb 2-port 530T Adapter + 103c 1930 FlexFabric 10Gb 2-port 534FLR-SFP+ Adapter + 103c 1931 StoreFabric CN1100R Dual Port Converged Network Adapter + 103c 1932 FlexFabric 10Gb 2-port 534FLB Adapter + 103c 1933 FlexFabric 10Gb 2-port 534M Adapter + 103c 193a FlexFabric 10Gb 2-port 533FLR-T Adapter + 103c 3382 Ethernet 10Gb 2-port 530FLR-SFP+ Adapter + 103c 339d Ethernet 10Gb 2-port 530SFP+ Adapter + 193d 1003 530F-B + 193d 1006 530F-L + 1690 NetXtreme BCM57760 Gigabit Ethernet PCIe + 1691 NetLink BCM57788 Gigabit Ethernet PCIe + 1028 04aa XPS 8300 + 1692 NetLink BCM57780 Gigabit Ethernet PCIe + 1025 033d Aspire 7740G + 1693 NetLink BCM5787M Gigabit Ethernet PCI Express + 1025 0121 Aspire 5920G + 103c 30c0 6710b + 17aa 20d5 ThinkPad R61 + 1694 NetLink BCM57790 Gigabit Ethernet PCIe + 1696 NetXtreme BCM5782 Gigabit Ethernet + 103c 12bc d530 CMT (DG746A) + 14e4 000d NetXtreme BCM5782 1000Base-T + 1698 NetLink BCM5784M Gigabit Ethernet PCIe + 1699 NetLink BCM5785 Gigabit Ethernet + 169a NetLink BCM5786 Gigabit Ethernet PCI Express + 169b NetLink BCM5787 Gigabit Ethernet PCI Express + 169c NetXtreme BCM5788 Gigabit Ethernet + 103c 308b MX6125 + 103c 30a1 NC2400 + 144d c018 X20 + 1462 590c KT6 Delta-FIS2R (MS-6590) + 169d NetLink BCM5789 Gigabit Ethernet PCI Express + 16a0 NetLink BCM5785 Fast Ethernet + 16a1 BCM57840 NetXtreme II 10 Gigabit Ethernet + 1043 866e PEB-10G/57840-2T 10GBase-T Network Adapter + 16a2 BCM57840 NetXtreme II 10/20-Gigabit Ethernet + 103c 1916 FlexFabric 20Gb 2-port 630FLB Adapter + 103c 1917 FlexFabric 20Gb 2-port 630M Adapter + 103c 2231 3820C 10/20Gb Converged Network Adapter + 103c 22fa FlexFabric 10Gb 2-port 536FLB Adapter + 16a3 NetXtreme BCM57786 Gigabit Ethernet PCIe + 16a4 BCM57840 NetXtreme II Ethernet Multi Function + 103c 1916 NPAR 20Gb 2-port 630FLB Adapter + 103c 1917 NPAR 20Gb 2-port 630M Adapter + 103c 2231 3820C 10/20Gb Converged Network Adapter (NPAR 1.5) + 103c 22fa FlexFabric 10Gb 2-port 536FLB Adapter (NPAR 1.5) +# The Broadcom 57800 device has two 1Gig ports and two 10Gig ports. The subsystem information can be used to differentiate. + 16a5 NetXtreme II BCM57800 1/10 Gigabit Ethernet Multi Function + 1028 1f5c NetXtreme II BCM57800 10-Gigabit Ethernet Multi Function + 1028 1f5d NetXtreme II BCM57800 10-Gigabit Ethernet Multi Function + 1028 1f67 NetXtreme II BCM57800 1-Gigabit Ethernet Multi Function + 1028 1f68 NetXtreme II BCM57800 1-Gigabit Ethernet Multi Function + 16a6 NetXtreme BCM5702X Gigabit Ethernet + 0e11 00bb NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T) + 1028 0126 BCM5702 1000Base-T + 14e4 000c BCM5702 1000Base-T + 14e4 8009 BCM5702 1000Base-T + 16a7 NetXtreme BCM5703X Gigabit Ethernet + 0e11 00ca NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T) + 0e11 00cb NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T) + 1014 026f eServer xSeries server mainboard + 14e4 0009 NetXtreme BCM5703 1000Base-T + 14e4 000a NetXtreme BCM5703 1000Base-SX + 14e4 000b NetXtreme BCM5703 1000Base-T + 14e4 800a NetXtreme BCM5703 1000Base-T + 16a8 NetXtreme BCM5704S Gigabit Ethernet + 103c 132b PCI-X 1000Mbps Dual-port Built-in + 10a9 8014 Dual Port Gigabit Ethernet (PCI-X,Fiber) + 10a9 801c Quad Port Gigabit Ethernet (PCI-E,Fiber) + 10b7 2001 3C998-SX Dual Port 1000-SX PCI-X +# The Broadcom 57800 device has two 1Gig ports and two 10Gig ports. The subsystem information can be used to differentiate. + 16a9 NetXtreme II BCM57800 1/10 Gigabit Ethernet Virtual Function + 1028 1f5c NetXtreme II BCM57800 10-Gigabit Ethernet Virtual Function + 1028 1f5d NetXtreme II BCM57800 10-Gigabit Ethernet Virtual Function + 1028 1f67 NetXtreme II BCM57800 1-Gigabit Ethernet Virtual Function + 1028 1f68 NetXtreme II BCM57800 1-Gigabit Ethernet Virtual Function + 16aa NetXtreme II BCM5706S Gigabit Ethernet + 103c 3102 NC370F MultifuNCtion Gigabit Server Adapter + 103c 310c NC370i Multifunction Gigabit Server Adapter + 16ab NetXtreme II BCM57840 10/20 Gigabit Ethernet Multi Function + 16ac NetXtreme II BCM5708S Gigabit Ethernet + 1014 0304 NetXtreme II BCM5708S Gigabit Ethernet + 1028 01bb PowerEdge 1955 Broadcom NetXtreme II BCM5708S + 1028 020c PowerEdge M605 Broadcom NetXtreme II BCM5708S + 103c 1706 NC373m Multifunction Gigabit Server Adapter + 103c 7038 NC373i PCI Express Multifunction Gigabit Server Adapter + 103c 703b NC373i Integrated Multifunction Gigabit Server Adapter + 103c 703d NC373F PCI Express Multifunction Gigabit Server Adapter + 16ad NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function + 103c 1916 FlexFabric 20Gb 2-port 630FLB Adapter + 103c 1917 FlexFabric 20Gb 2-port 630M Adapter + 103c 2231 3820C 10/20Gb Converged Network Adapter (SR-IOV VF) + 103c 22fa FlexFabric 10Gb 2-port 536FLB Adapter (SR-IOV VF) + 16ae NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function + 103c 1798 NPAR 10Gb 2-port 530FLB Adapter + 103c 17a5 NPAR 10Gb 2-port 530M Adapter + 103c 18d3 NPAR 10Gb 2-port 530T Adapter + 103c 1930 NPAR 10Gb 2-port 534FLR-SFP+ Adapter + 103c 1931 NPAR CN1100R Dual Port Converged Network Adapter + 103c 1932 NPAR 10Gb 2-port 534FLB Adapter + 103c 1933 NPAR 10Gb 2-port 534M Adapter + 103c 193a NPAR 10Gb 2-port 533FLR-T Adapter + 103c 3382 NPAR 10Gb 2-port 530FLR-SFP+ Adapter + 103c 339d NPAR 10Gb 2-port 530SFP+ Adapter + 16af NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function + 103c 1798 Flex-10 10Gb 2-port 530FLB Adapter + 103c 17a5 Flex-10 10Gb 2-port 530M Adapter + 103c 18d3 Ethernet 10Gb 2-port 530T Adapter + 103c 1930 FlexFabric 10Gb 2-port 534FLR-SFP+ Adapter + 103c 1931 StoreFabric CN1100R Dual Port Converged Network Adapter + 103c 1932 FlexFabric 10Gb 2-port 534FLB Adapter + 103c 1933 FlexFabric 10Gb 2-port 534M Adapter + 103c 193a FlexFabric 10Gb 2-port 533FLR-T Adapter + 103c 3382 Ethernet 10Gb 2-port 530FLR-SFP+ Adapter + 103c 339d Ethernet 10Gb 2-port 530SFP+ Adapter + 16b0 NetXtreme BCM57761 Gigabit Ethernet PCIe + 16b1 NetLink BCM57781 Gigabit Ethernet PCIe + 1849 96b1 Z77 Extreme4 motherboard + 16b2 NetLink BCM57791 Gigabit Ethernet PCIe + 16b3 NetXtreme BCM57786 Gigabit Ethernet PCIe + 16b4 NetXtreme BCM57765 Gigabit Ethernet PCIe + 16b5 NetLink BCM57785 Gigabit Ethernet PCIe + 16b6 NetLink BCM57795 Gigabit Ethernet PCIe + 16b7 NetXtreme BCM57782 Gigabit Ethernet PCIe + 16bc BCM57765/57785 SDXC/MMC Card Reader + 16be BCM57765/57785 MS Card Reader + 16bf BCM57765/57785 xD-Picture Card Reader + 16c1 NetXtreme-E RDMA Virtual Function + 16c6 NetXtreme BCM5702A3 Gigabit Ethernet + 10b7 1100 3C1000B-T 10/100/1000 PCI + 14e4 000c BCM5702 1000Base-T + 14e4 8009 BCM5702 1000Base-T + 16c7 NetXtreme BCM5703 Gigabit Ethernet + 0e11 00ca NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T) + 0e11 00cb NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T) + 103c 12c3 Combo FC/GigE-SX [A9782A] + 103c 12ca Combo FC/GigE-T [A9784A] + 103c 1321 Core I/O LAN/SCSI Combo [AB314A] + 14e4 0009 NetXtreme BCM5703 1000Base-T + 14e4 000a NetXtreme BCM5703 1000Base-SX + 16c8 BCM57301 NetXtreme-C 10Gb Ethernet Controller + 16c9 BCM57302 NetXtreme-C 10Gb/25Gb Ethernet Controller + 16ca BCM57304 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet Controller + 16cb NetXtreme-C Ethernet Virtual Function + 16cc BCM57417 NetXtreme-E Ethernet Partition + 16ce BCM57311 NetXtreme-C 10Gb RDMA Ethernet Controller + 16cf BCM57312 NetXtreme-C 10Gb/25Gb RDMA Ethernet Controller + 16d0 BCM57402 NetXtreme-E 10Gb Ethernet Controller + 16d1 BCM57404 NetXtreme-E 10Gb/25Gb Ethernet Controller + 16d2 BCM57406 NetXtreme-E 10GBASE-T Ethernet Controller + 16d3 NetXtreme-E Ethernet Virtual Function + 16d4 BCM57402 NetXtreme-E Ethernet Partition + 16d5 BCM57407 NetXtreme-E 10GBase-T Ethernet Controller + 16d6 BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller + 14e4 4120 NetXtreme E-Series Advanced Dual-port 10Gb SFP+ Ethernet Network Daughter Card + 152d 8b20 BCM57412 NetXtreme-E 10Gb RDMA Ethernet Controller + 152d 8b22 BCM57412 NetXtreme-E 25Gb RDMA Ethernet Controller + 16d7 BCM57414 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller + 14e4 1202 BCM957412M4122C OCP 1x25G Type1 wRoCE + 14e4 1402 BCM957414A4142CC 10Gb/25Gb Ethernet PCIe + 14e4 1404 BCM957414M4142C OCP 2x25G Type1 wRoCE + 14e4 4140 NetXtreme E-Series Advanced Dual-port 25Gb SFP28 Network Daughter Card + 1590 020e Ethernet 25Gb 2-port 631SFP28 Adapter + 1590 0211 Ethernet 25Gb 2-port 631FLR-SFP28 Adapter + 16d8 BCM57416 NetXtreme-E Dual-Media 10G RDMA Ethernet Controller + 1028 1feb NetXtreme-E 10Gb SFP+ Adapter + 14e4 4163 BCM957416M4163C OCP 2x10GBT Type1 wRoCE + 1590 020c Ethernet 10Gb 2-port 535T Adapter + 1590 0212 Ethernet 10Gb 2-port 535FLR-T Adapter + 16d9 BCM57417 NetXtreme-E 10GBASE-T RDMA Ethernet Controller + 108e 4866 Dual Port 10GBase-T Ethernet Controller + 16dc NetXtreme-E Ethernet Virtual Function + 16dd NetLink BCM5781 Gigabit Ethernet PCI Express + 16de BCM57412 NetXtreme-E Ethernet Partition + 16df BCM57314 NetXtreme-C 10Gb/25Gb/40Gb/50Gb RDMA Ethernet Controller + 16e1 NetXtreme-C Ethernet Virtual Function + 16e2 BCM57417 NetXtreme-E 10Gb/25Gb RDMA Ethernet Controller + 108e 4866 Dual Port 10Gb/25Gb SFP28 Ethernet Controller + 16e3 BCM57416 NetXtreme-E 10Gb RDMA Ethernet Controller + 16e5 NetXtreme-C RDMA Virtual Function + 16e7 BCM57404 NetXtreme-E Ethernet Partition + 16e8 BCM57406 NetXtreme-E Ethernet Partition + 16e9 BCM57407 NetXtreme-E 25Gb Ethernet Controller + 16ec BCM57414 NetXtreme-E Ethernet Partition + 16ed BCM57414 NetXtreme-E RDMA Partition + 16ee BCM57416 NetXtreme-E Ethernet Partition + 16ef BCM57416 NetXtreme-E RDMA Partition + 16f1 BCM57452 NetXtreme-E 10Gb/25Gb/40Gb/50Gb Ethernet + 16f3 NetXtreme BCM5727 Gigabit Ethernet PCIe + 16f7 NetXtreme BCM5753 Gigabit Ethernet PCI Express + 16fd NetXtreme BCM5753M Gigabit Ethernet PCI Express + 103c 309f Compaq nx9420 Notebook + 103c 30a3 Compaq nw8440 + 16fe NetXtreme BCM5753F Fast Ethernet PCI Express + 170c BCM4401-B0 100Base-TX + 1028 0188 Inspiron 6000 laptop + 1028 018d Inspiron 700m/710m + 1028 0196 Inspiron 5160 + 1028 01af Inspiron 6400 + 1028 01cd Inspiron 9400 Laptop + 1028 01d7 XPS M1210 + 1028 01d8 Inspiron E1405 + 103c 099c NX6110/NC6120 + 103c 30a2 NX7300 laptop + 14e4 170c HP Compaq 6720t Mobile Thin Client + 170d NetXtreme BCM5901 100Base-TX + 1014 0545 ThinkPad R40e + 170e NetXtreme BCM5901 100Base-TX + 1712 NetLink BCM5906 Fast Ethernet PCI Express + 1713 NetLink BCM5906M Fast Ethernet PCI Express + 1028 01f3 Inspiron 1420 + 1028 0209 XPS M1330 + 103c 30c0 Compaq 6710b + 17aa 3a23 IdeaPad S10e + 1750 BCM57508 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet + 1751 BCM57504 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet + 1752 BCM57502 NetXtreme-E 10Gb/25Gb/40Gb/50Gb Ethernet + 1806 BCM5750X NetXtreme-E Ethernet Virtual Function + 1807 BCM5750X NetXtreme-E RDMA Virtual Function + 3352 BCM3352 + 3360 BCM3360 + 4210 BCM4210 iLine10 HomePNA 2.0 + 4211 BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem + 4212 BCM4212 v.90 56k modem + 4220 802-11b/g Wireless PCI controller, packaged as a Linksys WPC54G ver 1.2 PCMCIA card + 4222 NetXtreme BCM5753M Gigabit Ethernet PCI Express + 4301 BCM4301 802.11b Wireless LAN Controller + 1028 0407 TrueMobile 1180 Onboard WLAN + 1043 0120 WL-103b Wireless LAN PC Card + 16a5 1602 B-300 802.11b Wireless CardBus Adapter + 1737 4301 WMP11 v2.7 802.11b Wireless-B PCI Adapter + 4305 BCM4307 V.90 56k Modem + 4306 BCM4306 802.11bg Wireless LAN controller + 4307 BCM4306 802.11bg Wireless LAN Controller + 4310 BCM4310 Chipcommon I/OController + 4311 BCM4311 802.11b/g WLAN + 1028 0007 Wireless 1390 WLAN Mini-Card + 1028 0008 Wireless 1390 WLAN ExpressCard + 103c 1363 BCM4311 802.11b/g Wireless LAN Controller + 103c 1364 BCM4311 802.11b/g Wireless LAN Controller + 103c 1365 BCM4311 802.11b/g Wireless LAN Controller + 103c 1374 BCM4311 802.11b/g Wireless LAN Controller + 103c 1375 BCM4311 802.11b/g Wireless LAN Controller + 103c 1376 BCM4311 802.11b/g Wireless LAN Controller + 103c 1377 BCM4311 802.11b/g Wireless LAN Controller + 103c 137f BCM4322 802.11a/b/g/n Wireless LAN Controller + 103c 1380 BCM4322 802.11a/b/g/n Wireless LAN Controller + 14e4 4311 BCM94311MCG + 4312 BCM4311 802.11a/b/g + 1028 0007 Wireless 1490 Dual Band WLAN Mini-Card + 1028 0008 Wireless 1490 Dual Band WLAN ExpressCard + 103c 135a Broadcom 802.11a/b/g WLAN + 103c 135f Broadcom 802.11a/b/g WLAN + 103c 1360 Broadcom 802.11a/b/g WLAN + 103c 1361 Broadcom 802.11a/b/g WLAN + 103c 1362 Broadcom 802.11a/b/g WLAN + 103c 1370 Broadcom 802.11a/b/g WLAN + 103c 1371 Broadcom 802.11a/b/g WLAN + 103c 1372 Broadcom 802.11a/b/g WLAN + 103c 1373 Broadcom 802.11a/b/g WLAN + 103c 30b5 Presario V3242AU + 106b 0089 AirPort Extreme + 1371 103c Broadcom 802.11 Multiband-netwerkadapter(6715s) + 4313 BCM4311 802.11a + 4315 BCM4312 802.11b/g LP-PHY + 1028 000b Wireless 1395 WLAN Mini-Card + 1028 000c Wireless 1397 WLAN Mini-Card + 103c 137c BCM4312 802.11b/g Wireless LAN Controller + 103c 137d BCM4312 802.11b/g Wireless LAN Controller + 103c 1507 U98Z049.00 Wireless Mini PCIe Card + 105b e003 T77H030.00 Wireless Mini PCIe Card + 105b e01b T77H106.00 Wireless Half-size Mini PCIe Card + 4318 BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller + 1028 0005 Wireless 1370 WLAN Mini-PCI Card + 1028 0006 Wireless 1370 WLAN PC Card + 103c 1355 Broadcom 802.11b/g WLAN + 103c 1356 Broadcom 802.11b/g WLAN + 103c 1357 Broadcom 802.11b/g WLAN + 1043 100f WL-138G v2 / WL-138gE / WL-100gE + 1043 120f A6U notebook embedded card + 1154 0355 Buffalo WLI2-PCI-G54S High Speed Mode Wireless Adapter + 1468 0311 Aspire 3022WLMi, 5024WLMi, 5020 + 1468 0312 TravelMate 2410 + 14e4 0449 Gateway 7510GX + 16ec 0119 U.S.Robotics Wireless MAXg PC Card + 1737 0042 WMP54GS v1.1 802.11g Wireless-G PCI Adapter with SpeedBooster + 1737 0048 WPC54G v3 802.11g Wireless-G Notebook Adapter + 1737 0049 WPC54GS v2 802.11g Wireless-G Notebook Adapter with SpeedBooster + 1799 7000 F5D7000 v4000 Wireless G Desktop Card + 1799 7001 F5D7001 v2000 Wireless G Plus Desktop Card + 1799 7010 F5D7010 v4000 Wireless G Notebook Card + 1799 7011 F5D7011 v2000 High-Speed Mode Wireless G Notebook Card + 4319 BCM4318 [AirForce 54g] 802.11a/b/g PCI Express Transceiver + 1028 0005 Wireless 1470 Dual Band WLAN Mini-PCI Card + 1028 0006 Wireless 1470 Dual Band WLAN PC Card + 103c 1358 Broadcom 802.11a/b/g WLAN + 103c 1359 Broadcom 802.11a/b/g WLAN + 103c 135a Broadcom 802.11a/b/g WLAN + 4320 BCM4306 802.11b/g Wireless LAN Controller + 1028 0001 TrueMobile 1300 WLAN Mini-PCI Card + 1028 0002 TrueMobile 1300 WLAN PC Card + 1028 0003 Wireless 1350 WLAN Mini-PCI Card + 1028 0004 Wireless 1350 WLAN PC Card + 103c 12f4 Broadcom 802.11b/g WLAN + 103c 12f8 Broadcom 802.11b/g WLAN + 103c 12fa Broadcom 802.11b/g WLAN + 103c 12fb Broadcom 802.11b/g WLAN + 1043 100f WL-100G + 1057 7025 WN825G + 106b 004e AirPort Extreme + 1154 0330 Buffalo WLI2-PCI-G54S High Speed Mode Wireless Desktop Adapter + 144f 7050 eMachines M6805 802.11g Built-in Wireless + 144f 7051 Sonnet Aria Extreme PCI + 1737 0013 WMP54G v1 802.11g PCI Adapter + 1737 0014 WMP54G v2 802.11g PCI Adapter + 1737 0015 WMP54GS v1.0 802.11g Wireless-G PCI Adapter with SpeedBooster + 1737 4320 WPC54G v1 / WPC54GS v1 802.11g Wireless-G Notebook Adapter + 1799 7000 F5D7000 v1000 Wireless G Desktop Card + 1799 7001 F5D7001 v1000 Wireless G Plus Desktop Card + 1799 7010 F5D7010 v1000 Wireless G Notebook Card + 1799 7011 F5D7011 v1000 High-Speed Mode Wireless G Notebook Card + 185f 1220 TravelMate 290E WLAN Mini-PCI Card + 4321 BCM4321 802.11a Wireless Network Controller + 4322 BCM4322 802.11bgn Wireless Network Controller + 4324 BCM4309 802.11abg Wireless Network Controller + 1028 0001 Truemobile 1400 + 1028 0002 TrueMobile 1400 Dual Band WLAN PC Card + 1028 0003 Truemobile 1450 MiniPCI + 1028 0004 Wireless 1450 Dual Band WLAN PC Card + 103c 12f9 Broadcom 802.11a/b/g WLAN + 103c 12fc Broadcom 802.11a/b/g WLAN + 4325 BCM4306 802.11bg Wireless Network Controller + 1414 0003 Wireless Notebook Adapter MN-720 + 1414 0004 Wireless PCI Adapter MN-730 + 4326 BCM4307 Chipcommon I/O Controller? + 4328 BCM4321 802.11a/b/g/n + 1028 0009 Wireless 1500 Draft 802.11n WLAN Mini-Card + 1028 000a Wireless 1500 Draft 802.11n WLAN Mini-card + 103c 1366 BCM4321 802.11a/b/g/n Wireless LAN Controller + 103c 1367 BCM4321 802.11a/b/g/n Wireless LAN Controller + 103c 1368 BCM4321 802.11a/b/g/n Wireless LAN Controller + 103c 1369 BCM4321 802.11a/b/g/n Wireless LAN Controller + 106b 0087 AirPort Extreme + 106b 0088 AirPort Extreme + 106b 008b AirPort Extreme + 106b 008c AirPort Extreme + 106b 0090 AirPort Extreme + 14e4 4328 BCM4328 802.11a/b/g/n + 1737 0066 WPC600N v1 802.11a/b/g/n Wireless-N CardBus Adapter + 1737 0068 WEC600N v1 802.11a/b/g/n Wireless-N ExpressCard + 4329 BCM4321 802.11b/g/n + 1385 7b00 WN511B RangeMax NEXT Wireless Notebook Adapter + 1385 7d00 WN311B RangeMax Next 270 Mbps Wireless PCI Adapter + 1737 0058 WPC300N v1 Wireless-N Notebook Adapter + 432a BCM4321 802.11an Wireless Network Controller + 432b BCM4322 802.11a/b/g/n Wireless LAN Controller + 1028 000d Wireless 1510 Wireless-N WLAN Mini-Card + 106b 008d AirPort Extreme + 106b 008e AirPort Extreme + 432c BCM4322 802.11b/g/n + 1799 d311 Dynex DX-NNBX 802.11n WLAN Cardbus Card + 432d BCM4322 802.11an Wireless Network Controller + 4331 BCM4331 802.11a/b/g/n + 106b 00d6 AirPort Extreme + 106b 00e4 AirPort Extreme + 106b 00ef AirPort Extreme + 106b 00f4 AirPort Extreme + 106b 00f5 AirPort Extreme + 106b 010e AirPort Extreme + 106b 010f AirPort Extreme + 4333 Serial (EDGE/GPRS modem part of Option GT Combo Edge) + 4344 EDGE/GPRS data and 802.11b/g combo cardbus [GC89] + 4350 BCM43222 Wireless Network Adapter + 4351 BCM43222 802.11abgn Wireless Network Adapter + 4353 BCM43224 802.11a/b/g/n + 1028 000e Wireless 1520 Half-size Mini PCIe Card + 103c 1509 WMIB-275N Half-size Mini PCIe Card + 106b 0093 AirPort Extreme + 106b 00d1 AirPort Extreme + 106b 00e9 AirPort Extreme + 14e4 04d8 Pegatron UPWL6024 + 4357 BCM43225 802.11b/g/n + 105b e021 T77H103.00 Wireless Half-size Mini PCIe Card + 4358 BCM43227 802.11b/g/n + 4359 BCM43228 802.11a/b/g/n + 1028 0011 Wireless 1530 Half-size Mini PCIe Card + 103c 182c BCM943228HM4L 802.11a/b/g/n 2x2 Wi-Fi Adapter + 4360 BCM4360 802.11ac Wireless Network Adapter + 4365 BCM43142 802.11b/g/n + 1028 0016 Wireless 1704 802.11n + BT 4.0 + 43a0 BCM4360 802.11ac Wireless Network Adapter + 43a1 BCM4360 802.11ac Wireless Network Adapter + 43a2 BCM4360 802.11ac Wireless Network Adapter + 43a3 BCM4350 802.11ac Wireless Network Adapter + 43a9 BCM43217 802.11b/g/n + 43aa BCM43131 802.11b/g/n + 43ae BCM43162 802.11ac Wireless Network Adapter + 43b1 BCM4352 802.11ac Wireless Network Adapter + 43ba BCM43602 802.11ac Wireless LAN SoC + 43bb BCM43602 802.11ac Wireless LAN SoC + 43bc BCM43602 802.11ac Wireless LAN SoC + 43d3 BCM43567 802.11ac Wireless Network Adapter + 43d9 BCM43570 802.11ac Wireless Network Adapter + 43dc BCM4355 802.11ac Wireless LAN SoC + 43df BCM4354 802.11ac Wireless LAN SoC + 43e9 BCM4358 802.11ac Wireless LAN SoC + 43ec BCM4356 802.11ac Wireless Network Adapter + 4401 BCM4401 100Base-T + 1025 0035 TravelMate 660 + 1025 0064 Extensa 3000 series laptop + 1028 8127 Dimension 2400 + 103c 08b0 tc1100 tablet + 1043 80a8 A7V8X motherboard + 4402 BCM4402 Integrated 10/100BaseT + 4403 BCM4402 V.90 56k Modem + 4410 BCM4413 iLine32 HomePNA 2.0 + 4411 BCM4413 V.90 56k modem + 4412 BCM4412 10/100BaseT + 4430 BCM44xx CardBus iLine32 HomePNA 2.0 + 4432 BCM4432 CardBus 10/100BaseT + 4464 BCM4364 802.11ac Wireless Network Adapter +# brcmfmac reports it as BCM4377/4 but macOS drivers call it BCM4377b + 4488 BCM4377b Wireless Network Adapter + 4610 BCM4610 Sentry5 PCI to SB Bridge + 4611 BCM4610 Sentry5 iLine32 HomePNA 1.0 + 4612 BCM4610 Sentry5 V.90 56k Modem + 4613 BCM4610 Sentry5 Ethernet Controller + 4614 BCM4610 Sentry5 External Interface + 4615 BCM4610 Sentry5 USB Controller + 4704 BCM4704 PCI to SB Bridge + 4705 BCM4704 Sentry5 802.11b Wireless LAN Controller + 4706 BCM4704 Sentry5 Ethernet Controller + 4707 BCM4704 Sentry5 USB Controller + 4708 BCM4704 Crypto Accelerator + 4710 BCM4710 Sentry5 PCI to SB Bridge + 4711 BCM47xx Sentry5 iLine32 HomePNA 2.0 + 4712 BCM47xx V.92 56k modem + 4713 Sentry5 Ethernet Controller + 4714 BCM47xx Sentry5 External Interface + 4715 BCM47xx Sentry5 USB / Ethernet Controller + 4716 BCM47xx Sentry5 USB Host Controller + 4717 BCM47xx Sentry5 USB Device Controller + 4718 Sentry5 Crypto Accelerator + 4719 BCM47xx/53xx RoboSwitch Core + 4720 BCM4712 MIPS CPU + 4727 BCM4313 802.11bgn Wireless Network Adapter + 1028 0010 Inspiron M5010 / XPS 8300 + 5365 BCM5365P Sentry5 Host Bridge + 5600 BCM5600 StrataSwitch 24+2 Ethernet Switch Controller + 5605 BCM5605 StrataSwitch 24+2 Ethernet Switch Controller + 5615 BCM5615 StrataSwitch 24+2 Ethernet Switch Controller + 5625 BCM5625 StrataSwitch 24+2 Ethernet Switch Controller + 5645 BCM5645 StrataSwitch 24+2 Ethernet Switch Controller + 5670 BCM5670 8-Port 10GE Ethernet Switch Fabric + 5680 BCM5680 G-Switch 8 Port Gigabit Ethernet Switch Controller + 5690 BCM5690 12-port Multi-Layer Gigabit Ethernet Switch + 5691 BCM5691 GE/10GE 8+2 Gigabit Ethernet Switch Controller + 5692 BCM5692 12-port Multi-Layer Gigabit Ethernet Switch + 5695 BCM5695 12-port + HiGig Multi-Layer Gigabit Ethernet Switch + 5698 BCM5698 12-port Multi-Layer Gigabit Ethernet Switch + 5820 BCM5820 Crypto Accelerator + 5821 BCM5821 Crypto Accelerator + 5822 BCM5822 Crypto Accelerator + 5823 BCM5823 Crypto Accelerator + 5824 BCM5824 Crypto Accelerator + 5840 BCM5840 Crypto Accelerator + 5841 BCM5841 Crypto Accelerator + 5850 BCM5850 Crypto Accelerator + 5e87 Valkyrie offload engine + 5e88 Viper Offload Engine + 8602 BCM7400/BCM7405 Serial ATA Controller + 9026 CN99xx [ThunderX2] Integrated USB 3.0 xHCI Host Controller + 9027 CN99xx [ThunderX2] Integrated AHCI/SATA 3 Host Controller + a8d8 BCM43224/5 Wireless Network Adapter + aa52 BCM43602 802.11ac Wireless LAN SoC + b302 BCM56302 StrataXGS 24x1GE 2x10GE Switch Controller + b334 BCM56334 StrataXGS 24x1GE 4x10GE Switch Controller + b370 BCM56370 Switch ASIC + b371 BCM56371 Switch ASIC + b372 BCM56372 Switch ASIC + b375 BCM56375 Switch ASIC + b376 BCM56376 Switch ASIC + b377 BCM56377 Switch ASIC + b379 Broadcom BCM56379 Switch ASIC + b470 BCM56470 SWITCH ASIC + b471 BCM56471 SWITCH ASIC + b472 BCM56472 SWITCH ASIC + b800 BCM56800 StrataXGS 10GE Switch Controller + b842 BCM56842 Trident 10GE Switch Controller +# Trident2 + b850 Broadcom BCM56850 Switch ASIC + b880 BCM56880 Switch ASIC +# Tomahawk + b960 Broadcom BCM56960 Switch ASIC +# Tomahawk4 + b990 BCM56990 Switch ASIC + d802 BCM58802 Stingray 50Gb Ethernet SoC + 14e4 8021 Stingray Dual-Port 25Gb Ethernet PCIe SmartNIC w16GB DRAM (Part No BCM958802A8046C) + 14e4 8023 PS410T-H04 NetXtreme-S 4x10G 10GBaseT PCIe SmartNIC + 14e4 8024 Stingray Dual-Port 25Gb Ethernet PCIe SmartNIC w4GB DRAM (Part No BCM958802A8044C) + 14e4 8028 Stingray Dual-Port 25Gb Ethernet PCIe SmartNIC w8GB DRAM (Part No BCM958802A8048C) + 1bb0 0021 HPE SimpliVity Accelerator + d804 BCM58804 Stingray 100Gb Ethernet SoC +14e5 Pixelfusion Ltd +14e6 SHINING Technology Inc +14e7 3CX +14e8 RAYCER Inc +14e9 GARNETS System CO Ltd +14ea Planex Communications, Inc + ab06 FNW-3603-TX CardBus Fast Ethernet + ab07 RTL81xx RealTek Ethernet + ab08 FNW-3602-TX CardBus Fast Ethernet +14eb SEIKO EPSON Corp +# nee ACQIRIS +14ec Agilent Technologies + 0000 Aciris Digitizer (malformed ID) +14ed DATAKINETICS Ltd +14ee MASPRO KENKOH Corp +14ef CARRY Computer ENG. CO Ltd +14f0 CANON RESEACH CENTRE FRANCE +14f1 Conexant Systems, Inc. + 1002 HCF 56k Modem + 1003 HCF 56k Modem + 1004 HCF 56k Modem + 1005 HCF 56k Modem + 1006 HCF 56k Modem + 1022 HCF 56k Modem + 1023 HCF 56k Modem + 1024 HCF 56k Modem + 1025 HCF 56k Modem + 1026 HCF 56k Modem + 1032 HCF 56k Modem + 1033 HCF 56k Data/Fax Modem + 1033 8077 NEC + 122d 4027 Dell Zeus - MDP3880-W(B) Data Fax Modem + 122d 4030 Dell Mercury - MDP3880-U(B) Data Fax Modem + 122d 4034 Dell Thor - MDP3880-W(U) Data Fax Modem + 13e0 020d Dell Copper + 13e0 020e Dell Silver + 13e0 0261 IBM + 13e0 0290 Compaq Goldwing + 13e0 02a0 IBM + 13e0 02b0 IBM + 13e0 02c0 Compaq Scooter + 13e0 02d0 IBM + 144f 1500 IBM P85-DF (1) + 144f 1501 IBM P85-DF (2) + 144f 150a IBM P85-DF (3) + 144f 150b IBM P85-DF Low Profile (1) + 144f 1510 IBM P85-DF Low Profile (2) + 1034 HCF 56k Data/Fax/Voice Modem + 1035 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + 10cf 1098 Fujitsu P85-DFSV + 1036 HCF 56k Data/Fax/Voice/Spkp Modem + 104d 8067 HCF 56k Modem + 122d 4029 MDP3880SP-W + 122d 4031 MDP3880SP-U + 13e0 0209 Dell Titanium + 13e0 020a Dell Graphite + 13e0 0260 Gateway Red Owl + 13e0 0270 Gateway White Horse + 1052 HCF 56k Data/Fax Modem (Worldwide) + 1053 HCF 56k Data/Fax Modem (Worldwide) + 1054 HCF 56k Data/Fax/Voice Modem (Worldwide) + 1055 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (Worldwide) + 1056 HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide) + 122d 4035 MDP3900V-W + 1057 HCF 56k Data/Fax/Voice/Spkp Modem (Worldwide) + 1059 HCF 56k Data/Fax/Voice Modem (Worldwide) + 1063 HCF 56k Data/Fax Modem + 1064 HCF 56k Data/Fax/Voice Modem + 1065 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + 1066 HCF 56k Data/Fax/Voice/Spkp Modem + 122d 4033 Dell Athena - MDP3900V-U + 1085 HCF V90 56k Data/Fax/Voice/Spkp PCI Modem + 10b6 CX06834-11 HCF V.92 56k Data/Fax/Voice/Spkp Modem + 1433 HCF 56k Data/Fax Modem + 1434 HCF 56k Data/Fax/Voice Modem + 1435 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + 1436 HCF 56k Data/Fax Modem + 1453 HCF 56k Data/Fax Modem + 13e0 0240 IBM + 13e0 0250 IBM + 144f 1502 IBM P95-DF (1) + 144f 1503 IBM P95-DF (2) + 1454 HCF 56k Data/Fax/Voice Modem + 1455 HCF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + 1456 HCF 56k Data/Fax/Voice/Spkp Modem + 122d 4035 Dell Europa - MDP3900V-W + 122d 4302 Dell MP3930V-W(C) MiniPCI + 1610 ADSL AccessRunner PCI Arbitration Device + 1611 AccessRunner PCI ADSL Interface Device + 1620 AccessRunner V2 PCI ADSL Arbitration Device + 1621 AccessRunner V2 PCI ADSL Interface Device + 1622 AccessRunner V2 PCI ADSL Yukon WAN Adapter + 1803 HCF 56k Modem + 0e11 0023 623-LAN Grizzly + 0e11 0043 623-LAN Yogi + 1811 MiniPCI Network Adapter + 1815 HCF 56k Modem + 0e11 0022 Grizzly + 0e11 0042 Yogi +# Integrated in CX86111/CX86113 processors + 1830 CX861xx Integrated Host Bridge + 2003 HSF 56k Data/Fax Modem + 2004 HSF 56k Data/Fax/Voice Modem + 2005 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + 2006 HSF 56k Data/Fax/Voice/Spkp Modem + 2013 HSF 56k Data/Fax Modem + 0e11 b195 Bear + 0e11 b196 Seminole 1 + 0e11 b1be Seminole 2 + 1025 8013 Acer + 1033 809d NEC + 1033 80bc NEC + 155d 6793 HP + 155d 8850 E Machines + 2014 HSF 56k Data/Fax/Voice Modem + 2015 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem + 2016 HSF 56k Data/Fax/Voice/Spkp Modem + 2043 HSF 56k Data/Fax Modem (WorldW SmartDAA) + 2044 HSF 56k Data/Fax/Voice Modem (WorldW SmartDAA) + 2045 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (WorldW SmartDAA) + 14f1 2045 Generic SoftK56 + 2046 HSF 56k Data/Fax/Voice/Spkp Modem (WorldW SmartDAA) + 2063 HSF 56k Data/Fax Modem (SmartDAA) + 2064 HSF 56k Data/Fax/Voice Modem (SmartDAA) + 2065 HSF 56k Data/Fax/Voice/Spkp (w/Handset) Modem (SmartDAA) + 2066 HSF 56k Data/Fax/Voice/Spkp Modem (SmartDAA) + 2093 HSF 56k Modem + 155d 2f07 Legend + 2143 HSF 56k Data/Fax/Cell Modem (Mob WorldW SmartDAA) + 2144 HSF 56k Data/Fax/Voice/Cell Modem (Mob WorldW SmartDAA) + 2145 HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob WorldW SmartDAA) + 2146 HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mob WorldW SmartDAA) + 2163 HSF 56k Data/Fax/Cell Modem (Mob SmartDAA) + 2164 HSF 56k Data/Fax/Voice/Cell Modem (Mob SmartDAA) + 2165 HSF 56k Data/Fax/Voice/Spkp (w/HS)/Cell Modem (Mob SmartDAA) + 2166 HSF 56k Data/Fax/Voice/Spkp/Cell Modem (Mob SmartDAA) + 2343 HSF 56k Data/Fax CardBus Modem (Mob WorldW SmartDAA) + 2344 HSF 56k Data/Fax/Voice CardBus Modem (Mob WorldW SmartDAA) + 2345 HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob WorldW SmartDAA) + 2346 HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mob WorldW SmartDAA) + 2363 HSF 56k Data/Fax CardBus Modem (Mob SmartDAA) + 2364 HSF 56k Data/Fax/Voice CardBus Modem (Mob SmartDAA) + 2365 HSF 56k Data/Fax/Voice/Spkp (w/HS) CardBus Modem (Mob SmartDAA) + 2366 HSF 56k Data/Fax/Voice/Spkp CardBus Modem (Mob SmartDAA) + 2443 HSF 56k Data/Fax Modem (Mob WorldW SmartDAA) + 104d 8075 Modem + 104d 8083 Modem + 104d 8097 Modem + 2444 HSF 56k Data/Fax/Voice Modem (Mob WorldW SmartDAA) + 2445 HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob WorldW SmartDAA) + 2446 HSF 56k Data/Fax/Voice/Spkp Modem (Mob WorldW SmartDAA) + 2463 HSF 56k Data/Fax Modem (Mob SmartDAA) + 2464 HSF 56k Data/Fax/Voice Modem (Mob SmartDAA) + 2465 HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob SmartDAA) + 2466 HSF 56k Data/Fax/Voice/Spkp Modem (Mob SmartDAA) + 2702 HSFi modem RD01-D270 + 1028 8d88 SmartHSFi V92 56K PCI Modem + 2f00 HSF 56k HSFi Modem + 13e0 8d84 IBM HSFi V.90 + 13e0 8d85 Compaq Stinger + 14f1 2004 Dynalink 56PMi + 2f02 HSF 56k HSFi Data/Fax + 2f11 HSF 56k HSFi Modem + 2f20 HSF 56k Data/Fax Modem + 14f1 200c Soft Data Fax Modem with SmartCP + 14f1 200f Dimension 3000 + 2f30 SoftV92 SpeakerPhone SoftRing Modem with SmartSP + 14f1 2014 Devolo MikroLink 56K Modem PCI + 2f50 Conexant SoftK56 Data/Fax Modem + 5b7a CX23418 Single-Chip MPEG-2 Encoder with Integrated Analog Video/Broadcast Audio Decoder + 0070 7444 WinTV HVR-1600 + 107d 6f34 WinFast DVR3100 H + 5854 3343 GoTView PCI DVD3 Hybrid + 8200 CX25850 + 8234 RS8234 ATM SAR Controller [ServiceSAR Plus] + 8800 CX23880/1/2/3 PCI Video and Audio Decoder + 0070 2801 Hauppauge WinTV 28xxx (Roslyn) models + 0070 3400 WinTV 34604 + 0070 3401 Hauppauge WinTV 34xxx models + 0070 6902 WinTV HVR-4000-HD + 0070 7801 WinTV HVR-1800 MCE + 0070 9001 Nova-T DVB-T + 0070 9200 Nova-SE2 DVB-S + 0070 9202 Nova-S-Plus DVB-S + 0070 9402 WinTV-HVR1100 DVB-T/Hybrid + 0070 9600 WinTV 88x Video + 0070 9802 WinTV-HVR1100 DVB-T/Hybrid (Low Profile) + 1002 00f8 ATI TV Wonder Pro + 1002 00f9 ATI TV Wonder + 1002 a101 HDTV Wonder + 1043 4823 PVR-416 + 107d 6611 Winfast TV 2000XP Expert + 107d 6613 Leadtek Winfast 2000XP Expert + 107d 6620 Leadtek Winfast DV2000 + 107d 663c Leadtek PVR 2000 + 107d 665f WinFast DTV1000-T + 10fc d003 IODATA GV-VCP3/PCI + 10fc d035 IODATA GV/BCTV7E + 1421 0334 Instant TV DVB-T PCI + 1461 000a AVerTV 303 (M126) + 1461 000b AverTV Studio 303 (M126) + 1461 8011 UltraTV Media Center PCI 550 + 1462 8606 MSI TV-@nywhere Master + 14c7 0107 GDI Black Gold + 14f1 0187 Conexant DVB-T reference design + 14f1 0342 Digital-Logic MICROSPACE Entertainment Center (MEC) + 153b 1166 Cinergy 1400 DVB-T + 1540 2580 Provideo PV259 + 1554 4811 PixelView + 1554 4813 Club 3D ZAP1000 MCE Edition + 17de 08a1 KWorld/VStream XPert DVB-T with cx22702 + 17de 08a6 KWorld/VStream XPert DVB-T + 17de 08b2 KWorld DVB-S 100 + 17de a8a6 digitalnow DNTV Live! DVB-T + 1822 0025 digitalnow DNTV Live! DVB-T Pro + 185b e000 VideoMate X500 + 18ac d500 FusionHDTV 5 Gold + 18ac d810 FusionHDTV 3 Gold-Q + 18ac d820 FusionHDTV 3 Gold-T + 18ac db00 FusionHDTV DVB-T1 + 18ac db11 FusionHDTV DVB-T Plus + 18ac db50 FusionHDTV DVB-T Dual Digital + 5654 2388 GoTView PCI Hybrid TV Tuner Card + 7063 3000 pcHDTV HD3000 HDTV + 7063 5500 pcHDTV HD-5500 + 8801 CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] + 0070 2801 Hauppauge WinTV 28xxx (Roslyn) models + 185b e000 VideoMate X500 + 5654 2388 GoTView PCI Hybrid Audio AVStream Device + 7063 5500 pcHDTV HD-5500 + 8802 CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] + 0070 2801 Hauppauge WinTV 28xxx (Roslyn) models + 0070 6902 WinTV HVR-4000-HD + 0070 9002 Nova-T DVB-T Model 909 + 0070 9402 WinTV-HVR1100 DVB-T/Hybrid + 0070 9600 WinTV 88x MPEG Encoder + 1043 4823 PVR-416 + 107d 663c Leadtek PVR 2000 + 107d 665f WinFast DTV1000-T + 14f1 0187 Conexant DVB-T reference design + 17de 08a1 XPert DVB-T PCI BDA DVBT 23880 Transport Stream Capture + 17de 08a6 KWorld/VStream XPert DVB-T + 18ac d500 DViCO FusionHDTV5 Gold + 18ac d810 DViCO FusionHDTV3 Gold-Q + 18ac d820 DViCO FusionHDTV3 Gold-T + 18ac db00 DVICO FusionHDTV DVB-T1 + 18ac db10 DVICO FusionHDTV DVB-T Plus + 5654 2388 GoTView PCI Hybrid TS Capture Device + 7063 3000 pcHDTV HD3000 HDTV + 7063 5500 pcHDTV HD-5500 + 8804 CX23880/1/2/3 PCI Video and Audio Decoder [IR Port] + 0070 6902 WinTV HVR-4000-HD + 0070 9002 Nova-T DVB-T Model 909 + 0070 9402 WinTV-HVR1100 DVB-T/Hybrid + 7063 5500 pcHDTV HD-5500 + 8811 CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] + 0070 3400 WinTV 34604 + 0070 3401 Hauppauge WinTV 34xxx models + 0070 6902 WinTV HVR-4000-HD + 0070 9402 WinTV-HVR1100 DVB-T/Hybrid + 0070 9600 WinTV 88x Audio + 1462 8606 MSI TV-@nywhere Master + 18ac d500 DViCO FusionHDTV5 Gold + 18ac d810 DViCO FusionHDTV3 Gold-Q + 18ac d820 DViCO FusionHDTV3 Gold-T + 18ac db00 DVICO FusionHDTV DVB-T1 + 5654 2388 GoTView PCI Hybrid Audio Capture Device + 8852 CX23885 PCI Video and Audio Decoder + 0070 8010 WinTV HVR-1400 ExpressCard + 0070 f038 WinTV HVR-5525 + 107d 6f22 WinFast PxTV1200 + 12ab d585 PE988J Hybrid ATSC/QAM PCI-E AVS Video Capture (SoftEncoder) + 13c2 3013 TT-budget CT2-4500 CI + 1461 c039 AVerTV Hybrid Express (A577) + 153b 117e Cinergy T PCIe Dual + 18ac db78 FusionHDTV DVB-T Dual Express + 4254 0950 S950 + 4254 0952 S952 + 4254 0982 T982 + 4254 9580 T9580 + 4254 980c T980C + 8880 CX23887/8 PCIe Broadcast Audio and Video Decoder with 3D Comb + 0070 2259 WinTV HVR-1250 + 0070 6a18 WinTV-quadHD + 0070 c108 WinTV-HVR-4400-HD model 1278 + 1461 3100 CE310B SD PCIe Video Capture Card + 5654 2389 GoTView X5 DVD Hybrid PCI-E + 5654 2390 GoTView X5 3D HYBRID PCI-E +14f2 MOBILITY Electronics + 0120 EV1000 bridge + 0121 EV1000 Parallel port + 0122 EV1000 Serial port + 0123 EV1000 Keyboard controller + 0124 EV1000 Mouse controller +14f3 BroadLogic + 2030 2030 DVB-S Satellite Receiver + 2035 2035 DVB-S Satellite Receiver + 2050 2050 DVB-T Terrestrial (Cable) Receiver + 2060 2060 ATSC Terrestrial (Cable) Receiver +14f4 TOKYO Electronic Industry CO Ltd +14f5 SOPAC Ltd +14f6 COYOTE Technologies LLC +14f7 WOLF Technology Inc +14f8 AUDIOCODES Inc + 2077 TP-240 dual span E1 VoIP PCI card +14f9 AG COMMUNICATIONS +14fa WANDEL & GOLTERMANN +14fb TRANSAS MARINE (UK) Ltd +14fc Quadrics Ltd + 0000 QsNet Elan3 Network Adapter + 0001 QsNetII Elan4 Network Adapter + 0002 QsNetIII Elan5 Network Adapter +14fd JAPAN Computer Industry Inc +14fe ARCHTEK TELECOM Corp +14ff TWINHEAD INTERNATIONAL Corp +1500 DELTA Electronics, Inc + 1360 RTL81xx RealTek Ethernet +1501 BANKSOFT CANADA Ltd +1502 MITSUBISHI ELECTRIC LOGISTICS SUPPORT Co Ltd +1503 KAWASAKI LSI USA Inc +1504 KAISER Electronics +1505 ITA INGENIEURBURO FUR TESTAUFGABEN GmbH +1506 CHAMELEON Systems Inc +# Should be HTEC Ltd, but there are no known HTEC chips and 1507 is already used by mistake by Motorola (see vendor ID 1057). +1507 Motorola ?? / HTEC + 0001 MPC105 [Eagle] + 0002 MPC106 [Grackle] + 0003 MPC8240 [Kahlua] + 0100 MC145575 [HFC-PCI] + 0431 KTI829c 100VG + 4801 Raven + 4802 Falcon + 4803 Hawk + 4806 CPX8216 +1508 HONDA CONNECTORS/MHOTRONICS Inc +1509 FIRST INTERNATIONAL Computer Inc +150a FORVUS RESEARCH Inc +150b YAMASHITA Systems Corp +150c KYOPAL CO Ltd +150d WARPSPPED Inc +150e C-PORT Corp +150f INTEC GmbH +1510 BEHAVIOR TECH Computer Corp +1511 CENTILLIUM Technology Corp +1512 ROSUN Technologies Inc +1513 Raychem +1514 TFL LAN Inc +1515 Advent design +1516 MYSON Technology Inc + 0800 MTD-8xx 100/10M Ethernet PCI Adapter + 0803 SURECOM EP-320X-S 100/10M Ethernet PCI Adapter + 1320 10bd SURECOM EP-320X-S 100/10M Ethernet PCI Adapter + 0891 MTD-8xx 100/10M Ethernet PCI Adapter +1517 ECHOTEK Corp +# old ID, now 1059 +1518 Kontron +1519 TELEFON AKTIEBOLAGET LM Ericsson +151a Globetek + 1002 PCI-1002 + 1004 PCI-1004 + 1008 PCI-1008 +151b COMBOX Ltd +151c DIGITAL AUDIO LABS Inc + 0003 Prodif T 2496 + 4000 Prodif 88 +151d Fujitsu Computer Products Of America +151e MATRIX Corp +151f TOPIC SEMICONDUCTOR Corp + 0000 TP560 Data/Fax/Voice 56k modem +1520 CHAPLET System Inc +1521 BELL Corp +1522 MainPine Ltd + 0100 PCI <-> IOBus Bridge + 1522 0200 RockForceDUO 2 Port V.92/V.44 Data/Fax/Voice Modem + 1522 0300 RockForceQUATRO 4 Port V.92/V.44 Data/Fax/Voice Modem + 1522 0400 RockForceDUO+ 2 Port V.92/V.44 Data/Fax/Voice Modem + 1522 0500 RockForceQUATRO+ 4 Port V.92/V.44 Data/Fax/Voice Modem + 1522 0600 RockForce+ 2 Port V.90 Data/Fax/Voice Modem + 1522 0700 RockForce+ 4 Port V.90 Data/Fax/Voice Modem + 1522 0800 RockForceOCTO+ 8 Port V.92/V.44 Data/Fax/Voice Modem + 1522 0c00 RockForceDUO+ 2 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem + 1522 0d00 RockForceQUATRO+ 4 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem + 1522 1d00 RockForceOCTO+ 8 Port V.92/V.44 Data, V.34 Super-G3 Fax, Voice Modem + 1522 2000 RockForceD1 1 Port V.90 Data Modem + 1522 2100 RockForceF1 1 Port V.34 Super-G3 Fax Modem + 1522 2200 RockForceD2 2 Port V.90 Data Modem + 1522 2300 RockForceF2 2 Port V.34 Super-G3 Fax Modem + 1522 2400 RockForceD4 4 Port V.90 Data Modem + 1522 2500 RockForceF4 4 Port V.34 Super-G3 Fax Modem + 1522 2600 RockForceD8 8 Port V.90 Data Modem + 1522 2700 RockForceF8 8 Port V.34 Super-G3 Fax Modem + 1522 3000 IQ Express D1 - 1 Port V.92 Data Modem + 1522 3100 IQ Express F1 - 1 Port V.34 Super-G3 Fax Modem + 1522 3200 IQ Express D2 - 2 Port V.92 Data Modem + 1522 3300 IQ Express F2 - 2 Port V.34 Super-G3 Fax Modem + 1522 3400 IQ Express D4 - 4 Port V.92 Data Modem + 1522 3500 IQ Express F4 - 4 Port V.34 Super-G3 Fax Modem + 1522 3c00 IQ Express D8 - 8 Port V.92 Data Modem + 1522 3d00 IQ Express F8 - 8 Port V.34 Super-G3 Fax Modem + 4000 PCI Express UART + 1522 4001 IQ Express 1-port V.34 Super-G3 Fax + 1522 4002 IQ Express 2-port V.34 Super-G3 Fax + 1522 4004 IQ Express 4-port V.34 Super-G3 Fax + 1522 4008 IQ Express 8-port V.34 Super-G3 Fax + 1522 4100 IQ Express SideBand +1523 MUSIC Semiconductors +1524 ENE Technology Inc + 0510 CB710 Memory Card Reader Controller + 103c 006a NX9500 + 0520 FLASH memory: ENE Technology Inc: + 0530 ENE PCI Memory Stick Card Reader Controller + 0550 ENE PCI Secure Digital Card Reader Controller + 0551 SD/MMC Card Reader Controller + 0610 PCI Smart Card Reader Controller + 0720 Memory Stick Card Reader Controller + 0730 ENE PCI Memory Stick Card Reader Controller + 0750 ENE PCI SmartMedia / xD Card Reader Controller + 0751 ENE PCI Secure Digital / MMC Card Reader Controller + 1211 CB1211 Cardbus Controller + 1225 CB1225 Cardbus Controller + 1410 CB1410 Cardbus Controller + 1025 003c CL50 motherboard + 1025 005a TravelMate 290 + 103c 30d5 530 Laptop + 1411 CB-710/2/4 Cardbus Controller + 103c 006a NX9500 + 1412 CB-712/4 Cardbus Controller + 1420 CB1420 Cardbus Controller + 1421 CB-720/2/4 Cardbus Controller + 1422 CB-722/4 Cardbus Controller +1525 IMPACT Technologies +1526 ISS, Inc +1527 SOLECTRON +1528 ACKSYS +1529 AMERICAN MICROSystems Inc +152a QUICKTURN DESIGN Systems +152b FLYTECH Technology CO Ltd +152c MACRAIGOR Systems LLC +152d QUANTA Computer Inc +152e MELEC Inc +152f PHILIPS - CRYPTO +1530 ACQIS Technology Inc +1531 CHRYON Corp +1532 ECHELON Corp + 0020 LonWorks PCLTA-20 PCI LonTalk Adapter +1533 BALTIMORE +1534 ROAD Corp +1535 EVERGREEN Technologies Inc +1536 ACTIS Computer +1537 DATALEX COMMUNCATIONS +1538 ARALION Inc + 0303 ARS106S Ultra ATA 133/100/66 Host Controller +1539 ATELIER INFORMATIQUES et ELECTRONIQUE ETUDES S.A. +153a ONO SOKKI +153b TERRATEC Electronic GmbH + 1144 Aureon 5.1 +# Terratec seems to use several IDs for the same card. + 1147 Aureon 5.1 Sky + 1158 Philips Semiconductors SAA7134 (rev 01) [Terratec Cinergy 600 TV] +153c ANTAL Electronic +153d FILANET Corp +153e TECHWELL Inc +153f MIPS Technologies, Inc. + 0001 SOC-it 101 System Controller +1540 PROVIDEO MULTIMEDIA Co Ltd +1541 MACHONE Communications +# nee VIVID Technology Inc. +1542 Concurrent Real-Time + 9260 RCIM-II Real-Time Clock & Interrupt Module + 9271 RCIM-III Real-Time Clock & Interrupt Module (PCIe) + 9272 Pulse Width Modulator Card + 9277 5 Volt Delta Sigma Converter Card + 9278 10 Volt Delta Sigma Converter Card + 9287 Analog Output Card + 9290 FPGA Card + 9300 Universal Exhaust Gas Oxygen Sensor Simulator + 9310 Digital Programmable Resistor + 9350 Analog Input Card +1543 SILICON Laboratories + 3052 Intel 537 [Winmodem] + 4c22 Si3036 MC'97 DAA +1544 DCM DATA Systems +1545 VISIONTEK +1546 IOI Technology Corp +1547 MITUTOYO Corp +1548 JET PROPULSION Laboratory +1549 INTERCONNECT Systems Solutions +154a MAX Technologies Inc +154b COMPUTEX Co Ltd +154c VISUAL Technology Inc +154d PAN INTERNATIONAL Industrial Corp +154e SERVOTEST Ltd +154f STRATABEAM Technology +1550 OPEN NETWORK Co Ltd +1551 SMART Electronic DEVELOPMENT GmBH +1552 RACAL AIRTECH Ltd +1553 CHICONY Electronics Co Ltd +1554 PROLINK Microsystems Corp +1555 GESYTEC GmBH +1556 PLDA + 1100 PCI Express Core Reference Design + 110f PCI Express Core Reference Design Virtual Function + 1110 XpressRich Reference Design + 1113 XpressSwitch + be00 PCI Express Bridge +1557 MEDIASTAR Co Ltd +1558 CLEVO/KAPOK Computer +1559 SI LOGIC Ltd +155a INNOMEDIA Inc +155b PROTAC INTERNATIONAL Corp +155c Cemax-Icon Inc +155d Mac System Co Ltd +155e LP Elektronik GmbH +155f Perle Systems Ltd +1560 Terayon Communications Systems +1561 Viewgraphics Inc +1562 Symbol Technologies +1563 A-Trend Technology Co Ltd +1564 Yamakatsu Electronics Industry Co Ltd +1565 Biostar Microtech Int'l Corp +1566 Ardent Technologies Inc +1567 Jungsoft +1568 DDK Electronics Inc +1569 Palit Microsystems Inc. +156a Avtec Systems +156b 2wire Inc +156c Vidac Electronics GmbH +156d Alpha-Top Corp +156e Alfa Inc +156f M-Systems Flash Disk Pioneers Ltd +1570 Lecroy Corp +1571 Contemporary Controls + a001 CCSI PCI20-485 ARCnet + a002 CCSI PCI20-485D ARCnet + a003 CCSI PCI20-485X ARCnet + a004 CCSI PCI20-CXB ARCnet + a005 CCSI PCI20-CXS ARCnet + a006 CCSI PCI20-FOG-SMA ARCnet + a007 CCSI PCI20-FOG-ST ARCnet + a008 CCSI PCI20-TB5 ARCnet + a009 CCSI PCI20-5-485 5Mbit ARCnet + a00a CCSI PCI20-5-485D 5Mbit ARCnet + a00b CCSI PCI20-5-485X 5Mbit ARCnet + a00c CCSI PCI20-5-FOG-ST 5Mbit ARCnet + a00d CCSI PCI20-5-FOG-SMA 5Mbit ARCnet + a201 CCSI PCI22-485 10Mbit ARCnet + a202 CCSI PCI22-485D 10Mbit ARCnet + a203 CCSI PCI22-485X 10Mbit ARCnet + a204 CCSI PCI22-CHB 10Mbit ARCnet + a205 CCSI PCI22-FOG_ST 10Mbit ARCnet + a206 CCSI PCI22-THB 10Mbit ARCnet +1572 Otis Elevator Company +1573 Lattice - Vantis +1574 Fairchild Semiconductor +1575 Voltaire Advanced Data Security Ltd +1576 Viewcast COM +1578 HITT + 4d34 VPMK4 [Video Processor Mk IV] + 5615 VPMK3 [Video Processor Mk III] +1579 Dual Technology Corp +157a Japan Elecronics Ind Inc +157b Star Multimedia Corp +157c Eurosoft (UK) + 8001 Fix2000 PCI Y2K Compliance Card +157d Gemflex Networks +157e Transition Networks +157f PX Instruments Technology Ltd +1580 Primex Aerospace Co +1581 SEH Computertechnik GmbH +1582 Cytec Corp +1583 Inet Technologies Inc +1584 Uniwill Computer Corp +1585 Logitron +1586 Lancast Inc +1587 Konica Corp +1588 Solidum Systems Corp +1589 Atlantek Microsystems Pty Ltd + 0008 Leutron Vision PicPortExpress CL + 0009 Leutron Vision PicPortExpress CL Stereo +158a Digalog Systems Inc +158b Allied Data Technologies +158c Hitachi Semiconductor & Devices Sales Co Ltd +158d Point Multimedia Systems +158e Lara Technology Inc +158f Ditect Coop +# formerly 3PAR Inc. +1590 Hewlett Packard Enterprise + 0001 Eagle Cluster Manager + 0002 Osprey Cluster Manager + 0003 Harrier Cluster Manager + a01d FC044X Fibre Channel HBA +1591 ARN +1592 Syba Tech Ltd + 0781 Multi-IO Card + 0782 Parallel Port Card 2xEPP + 0783 Multi-IO Card + 0785 Multi-IO Card + 0786 Multi-IO Card + 0787 Multi-IO Card + 0788 Multi-IO Card + 078a Multi-IO Card +1593 Bops Inc +1594 Netgame Ltd +1595 Diva Systems Corp +1596 Folsom Research Inc +1597 Memec Design Services +1598 Granite Microsystems +1599 Delta Electronics Inc +159a General Instrument +159b Faraday Technology Corp + 4321 StorLink SL3516 (Gemini) Host Bridge +159c Stratus Computer Systems +159d Ningbo Harrison Electronics Co Ltd +159e A-Max Technology Co Ltd +159f Galea Network Security +15a0 Compumaster SRL +15a1 Geocast Network Systems +15a2 Catalyst Enterprises Inc + 0001 TA700 PCI Bus Analyzer/Exerciser +15a3 Italtel +15a4 X-Net OY +15a5 Toyota Macs Inc +15a6 Sunlight Ultrasound Technologies Ltd +15a7 SSE Telecom Inc +15a8 Shanghai Communications Technologies Center +15aa Moreton Bay +15ab Bluesteel Networks Inc +15ac North Atlantic Instruments + 6893 3U OpenVPX Multi-function I/O Board [Model 68C3] +15ad VMware + 0405 SVGA II Adapter + 0710 SVGA Adapter + 0720 VMXNET Ethernet Controller + 0740 Virtual Machine Communication Interface + 0770 USB2 EHCI Controller + 0774 USB1.1 UHCI Controller + 0778 USB3 xHCI 0.96 Controller + 0779 USB3 xHCI 1.0 Controller + 0790 PCI bridge + 07a0 PCI Express Root Port + 07b0 VMXNET3 Ethernet Controller + 07c0 PVSCSI SCSI Controller + 07e0 SATA AHCI controller + 0801 Virtual Machine Interface + 15ad 0800 Hypervisor ROM Interface + 0820 Paravirtual RDMA controller + 1977 HD Audio Controller +15ae Amersham Pharmacia Biotech +15b0 Zoltrix International Ltd +15b1 Source Technology Inc +15b2 Mosaid Technologies Inc +15b3 Mellanox Technologies + 0191 MT25408 [ConnectX IB Flash Recovery] + 01f6 MT27500 Family [ConnectX-3 Flash Recovery] + 01f8 MT27520 Family [ConnectX-3 Pro Flash Recovery] + 01ff MT27600 Family [Connect-IB Flash Recovery] + 0209 MT27700 Family [ConnectX-4 Flash Recovery] + 020b MT27710 Family [ConnectX-4 Lx Flash Recovery] + 020d MT28800 Family [ConnectX-5 Flash Recovery] + 020f MT28908A0 Family [ConnectX-6 Flash Recovery] + 0210 MT28908A0 Family [ConnectX-6 Secure Flash Recovery] + 0211 MT416842 Family [BlueField SoC Flash Recovery] + 0212 MT2892 Family [ConnectX-6 Dx Flash Recovery] + 0213 MT2892 Family [ConnectX-6 Dx Secure Flash Recovery] + 0214 MT42822 Family [BlueField-2 SoC Flash Recovery] + 0215 MT42822 Family [BlueField-2 Secure Flash Recovery] + 0216 MT2894 Family [ConnectX-6 Lx Flash Recovery] + 0217 MT2894 Family [ConnectX-6 Lx Secure Flash Recovery] + 024e MT53100 [Spectrum-2, Flash recovery mode] + 024f MT53100 [Spectrum-2, Secure Flash recovery mode] + 0250 Spectrum-3, Flash recovery mode + 0251 Spectrum-3, Secure Flash recovery mode + 0252 Amos chiplet + 0254 Spectrum-4, Flash recovery mode + 0255 Spectrum-4, Secure Flash recovery mode + 0256 Ofek chiplet + 0257 Quantum-2 in Flash Recovery Mode + 0262 MT27710 [ConnectX-4 Lx Programmable] EN + 0263 MT27710 [ConnectX-4 Lx Programmable Virtual Function] EN + 0264 Innova-2 Flex Burn image + 0281 NPS-600 Flash Recovery + 0538 MT2910 Family [ConnectX-7 Flash Recovery] + 0539 MT2910 Family [ConnectX-7 Secure Flash Recovery] + 1002 MT25400 Family [ConnectX-2 Virtual Function] + 1003 MT27500 Family [ConnectX-3] + 1014 04b5 PCIe3 40GbE RoCE Converged Host Bus Adapter for Power + 103c 1777 InfiniBand FDR/EN 10/40Gb Dual Port 544FLR-QSFP Adapter (Rev Cx) + 103c 17c9 Infiniband QDR/Ethernet 10Gb 2-port 544i Adapter + 103c 18ce InfiniBand QDR/EN 10Gb Dual Port 544M Adapter + 103c 18cf InfiniBand FDR/EN 10/40Gb Dual Port 544M Adapter + 103c 18d6 InfiniBand FDR/EN 10/40Gb Dual Port 544QSFP Adapter + 15b3 0025 ConnectX-3 IB QDR Dual Port Mezzanine Card + 15b3 0026 ConnectX-3 IB FDR Dual Port Mezzanine Card + 15b3 0028 ConnectX-3 VPI Dual QSFP+ Port QDR Infiniband 40Gb/s or 10Gb Ethernet + 15b3 0059 ConnectX-3 VPI IB FDR/40 GbE Single Port QSFP+ Mezzanine Card + 15b3 0064 ConnectX-3 EN 10/40 GbE Single Port QSFP+ Adapter (MCX313A-BCBT) + 15b3 0065 ConnectX-3 VPI IB FDR/40 GbE Dual Port QSFP+ Adapter + 15b3 0066 ConnectX-3 IB FDR10 Dual Port Mezzanine Card + 15b3 0067 ConnectX-3 VPI IB FDR/40 GbE Single Port QSFP+ Adapter + 15b3 0071 ConnectX-3 VPI IB FDR/40 GbE Dual Port QSFP+ Mezzanine Card +# SVID = 15B3 SSID = 0078 + 15b3 0078 ConnectX-3 10 GbE Dual Port KR Mezzanine Card + 15b3 0079 ConnectX-3 40 GbE Dual Port QSFP+ Adapter +# SVID = 15B3 SSID = 0080 + 15b3 0080 ConnectX-3 10 GbE Dual Port SFP+ Adapter + 1004 MT27500/MT27520 Family [ConnectX-3/ConnectX-3 Pro Virtual Function] + 1005 MT27510 Family + 1006 MT27511 Family + 1007 MT27520 Family [ConnectX-3 Pro] + 1014 04eb 2-Port 10GbE NIC and RoCE SR PCIe3 + 103c 22f3 InfiniBand FDR/Ethernet 10Gb/40Gb 2-port 544+QSFP Adapter + 103c 22f4 InfiniBand FDR/Ethernet 10Gb/40Gb 2-port 544+FLR-QSFP Adapter + 103c 801f Ethernet 10G 2-port 546SFP+ Adapter + 117c 0090 FastFrame NQ41 + 117c 0091 FastFrame NQ42 + 117c 0092 FastFrame NQ11 + 117c 0093 FastFrame NQ12 + 15b3 0006 Mellanox Technologies ConnectX-3 Pro Stand-up dual-port 40GbE MCX314A-BCCT + 15b3 0078 ConnectX-3 Pro 10 GbE Dual Port KR Mezzanine Card + 15b3 0079 ConnectX-3 Pro 40 GbE Dual Port QSFP+ Adapter + 15b3 0080 ConnectX-3 Pro 10 GbE Dual Port SFP+ Adapter + 193d 1002 520F-B + 1009 MT27530 Family + 100a MT27531 Family + 100b MT27540 Family + 100c MT27541 Family + 100d MT27550 Family + 100e MT27551 Family + 100f MT27560 Family + 1010 MT27561 Family + 1011 MT27600 [Connect-IB] + 1012 MT27600 Family [Connect-IB Virtual Function] + 1013 MT27700 Family [ConnectX-4] + 1014 04f7 PCIe3 2-port 100 GbE (NIC and RoCE) QSFP28 Adapter for Power + 15b3 0003 Mellanox Technologies ConnectX-4 Stand-up single-port 40GbE MCX413A-BCAT + 15b3 0005 Mellanox Technologies ConnectX-4 Stand-up single-port 40GbE MCX415A-BCAT + 15b3 0006 MCX416A-BCAT, ConnectX-4 EN, 40/56GbE 2P, PCIe3.0 x16 + 15b3 0007 ConnectX-4 EN network interface card, 40/56GbE dual-port QSFP28, PCIe3.0 x16, tall bracket + 15b3 0008 ConnectX-4 Stand-up dual-port 100GbE MCX416A-CCAT + 15b3 0033 ConnectX-4 VPI IB EDR/100 GbE Single Port QSFP28 Adapter + 15b3 0034 ConnectX-4 VPI IB EDR/100 GbE Dual Port QSFP28 Adapter + 15b3 0050 ConnectX-4 100 GbE Dual Port QSFP28 Adapter + 1014 MT27700 Family [ConnectX-4 Virtual Function] + 1015 MT27710 Family [ConnectX-4 Lx] + 15b3 0001 ConnectX-4 Lx EN network interface card, 25GbE single-port SFP28, PCIe3.0 x8, tall bracket, ROHS R6 + 15b3 0003 Stand-up ConnectX-4 Lx EN, 25GbE dual-port SFP28, PCIe3.0 x8, MCX4121A-ACAT + 15b3 0004 ConnectX-4 Lx Stand-up dual-port 10GbE MCX4121A-XCAT + 15b3 0005 Mellanox Technologies ConnectX-4 Lx Stand-up single-port 40GbE MCX4131A-BCAT + 15b3 0020 MCX4411A-ACQN, ConnectX-4 Lx EN OCP, 1x25Gb + 15b3 0021 MCX4421A-ACQN ConnectX-4 Lx EN OCP,2x25G + 15b3 0025 ConnectX-4 Lx 25 GbE Dual Port SFP28 rNDC + 193d 100a 620F-B + 1016 MT27710 Family [ConnectX-4 Lx Virtual Function] + 1017 MT27800 Family [ConnectX-5] + 15b3 0006 ConnectX®-5 EN network interface card, 100GbE single-port QSFP28, PCIe3.0 x16, tall bracket; MCX515A-CCAT + 15b3 0020 ConnectX®-5 EN network interface card, 10/25GbE dual-port SFP28, PCIe3.0 x8, tall bracket ; MCX512A-ACAT + 15b3 0068 ConnectX®-5 EN network interface card for OCP2.0, Type 1, with host management, 25GbE dual-port SFP28, PCIe3.0 x8, no bracket Halogen free ; MCX542B-ACAN + 1018 MT27800 Family [ConnectX-5 Virtual Function] + 1019 MT28800 Family [ConnectX-5 Ex] + 15b3 0008 ConnectX-5 Ex EN network interface card, 100GbE dual-port QSFP28, PCIe4.0 x16, tall bracket; MCX516A-CDAT + 101a MT28800 Family [ConnectX-5 Ex Virtual Function] + 101b MT28908 Family [ConnectX-6] + 101c MT28908 Family [ConnectX-6 Virtual Function] + 101d MT2892 Family [ConnectX-6 Dx] + 101e ConnectX Family mlx5Gen Virtual Function + 101f MT2894 Family [ConnectX-6 Lx] + 1020 MT28860 + 1021 MT2910 Family [ConnectX-7] + 1974 MT28800 Family [ConnectX-5 PCIe Bridge] + 1975 MT416842 Family [BlueField SoC PCIe Bridge] + 1976 MT28908 Family [ConnectX-6 PCIe Bridge] + 1977 MT2892 Family [ConnectX-6 Dx PCIe Bridge] + 1978 MT42822 Family [BlueField-2 SoC PCIe Bridge] + 4117 MT27712A0-FDCF-AE + 1bd4 0039 SN10XMP2P25 + 1bd4 004d SN10XMP2P25,YZPC-01191-101 + 5274 MT21108 InfiniBridge + 5a44 MT23108 InfiniHost + 5a45 MT23108 [Infinihost HCA Flash Recovery] + 5a46 MT23108 PCI Bridge + 5e8c MT24204 [InfiniHost III Lx HCA] + 5e8d MT25204 [InfiniHost III Lx HCA Flash Recovery] + 6001 NVMe SNAP Controller + 6274 MT25204 [InfiniHost III Lx HCA] + 6278 MT25208 InfiniHost III Ex (Tavor compatibility mode) + 6279 MT25208 [InfiniHost III Ex HCA Flash Recovery] + 6282 MT25208 [InfiniHost III Ex] + 6340 MT25408A0-FCC-SI ConnectX, Dual Port 10Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 2.5GT/s Interface + 634a MT25408A0-FCC-DI ConnectX, Dual Port 20Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 2.5GT/s Interface + 1014 1014 4X InfiniBand DDR Expansion Card (CFFh) for IBM BladeCenter + 6368 MT25448 [ConnectX EN 10GigE, PCIe 2.0 2.5GT/s] + 6372 MT25458 ConnectX EN 10GBASE-T PCIe 2.5 GT/s + 6732 MT25408A0-FCC-GI ConnectX, Dual Port 20Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface + 673c MT25408A0-FCC-QI ConnectX, Dual Port 40Gb/s InfiniBand / 10GigE Adapter IC with PCIe 2.0 x8 5.0GT/s Interface + 1014 0415 PCIe2 2-port 4X InfiniBand QDR Adapter for Power + 1014 0487 GX++ 1-port 4X IB QDR Adapter for Power 795 + 103c 1782 4X QDR InfiniBand Mezzanine HCA for c-Class BladeSystem + 15b3 0021 HP InfiniBand 4X QDR CX-2 PCI-e G2 Dual Port HCA + 6746 MT26438 [ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virtualization+] + 103c 1781 NC543i 1-port 4x QDR IB/Flex-10 10Gb Adapter + 103c 3349 NC543i 2-port 4xQDR IB/10Gb Adapter + 6750 MT26448 [ConnectX EN 10GigE, PCIe 2.0 5GT/s] + 1014 0416 PCIe2 2-Port 10GbE RoCE SFP+ Adapter + 1014 0461 PCIe2 2-Port 10GbE RoCE SR Adapter + 15b3 0018 HP 10 GbE PCI-e G2 Dual-Port NIC (rev C1) +# FC EC26 + 15b3 6572 IBM Flex System EN4132 2-port 10Gb RoCE Adapter + 675a MT26458 ConnectX EN 10GBASE-T PCIe Gen2 5.0 GT/s + 6764 MT26468 [ConnectX EN 10GigE, PCIe 2.0 5GT/s Virtualization+] + 103c 3313 NC542m Dual Port Flex-10 10GbE BLc Adapter + 676e MT26478 [ConnectX EN 40GigE, PCIe 2.0 5GT/s] + 6778 MT26488 [ConnectX VPI PCIe 2.0 5GT/s - IB DDR / 10GigE Virtualization+] + 7101 NPS-400 configuration and management interface + 7102 NPS-400 network interface PF + 7103 NPS-400 network interface VF + 7121 NPS-600 configuration and management interface + 7122 NPS-600 network interface PF + 7123 NPS-600 network interface VF + 8200 Innova-2 Flex Shell Logic + a2d0 MT416842 BlueField SoC Crypto enabled + a2d1 MT416842 BlueField SoC Crypto disabled + a2d2 MT416842 BlueField integrated ConnectX-5 network controller + a2d3 MT416842 BlueField multicore SoC family VF + a2d4 MT42822 BlueField-2 SoC Crypto enabled + a2d5 MT42822 BlueField-2 SoC Crypto disabled + a2d6 MT42822 BlueField-2 integrated ConnectX-6 Dx network controller + c2d2 MT416842 BlueField SoC management interfac + c2d3 MT42822 BlueField-2 SoC Management Interface +# SwitchX-2, 40GbE switch + c738 MT51136 + c739 MT51136 GW + c838 MT52236 + c839 MT52236 router + caf1 ConnectX-4 CAPI Function +# Spectrum, 100GbE Switch + cb84 MT52100 + cf08 Switch-IB2 + cf6c MT53100 [Spectrum-2] + cf70 Spectrum-3 + cf80 Spectrum-4 + d2f0 Quantum HDR (200Gbps) switch + d2f2 Quantum-2 NDR (400Gbps) switch +15b4 CCI/TRIAD +15b5 Cimetrics Inc +15b6 Texas Memory Systems Inc + 0001 XP15 DSP Accelerator + 0002 XP30 DSP Accelerator + 0003 XP00 Data Acquisition Device + 0004 XP35 DSP Accelerator + 0007 XP100 DSP Accelerator [XP100-T0] + 0008 XP100 DSP Accelerator [XP100-T1] + 0009 XP100 DSP Accelerator [XP100-E0] + 000a XP100 DSP Accelerator [XP100-E1] + 000e XP100 DSP Accelerator [XP100-0] + 000f XP100 DSP Accelerator [XP100-1] + 0010 XP100 DSP Accelerator [XP100-P0] + 0011 XP100 DSP Accelerator [XP100-P1] + 0012 XP100 DSP Accelerator [XP100-P2] + 0013 XP100 DSP Accelerator [XP100-P3] + 0014 RamSan Flash SSD + 0015 ZBox +15b7 Sandisk Corp + 2001 Skyhawk Series NVME SSD + 5001 WD Black NVMe SSD + 5002 WD Black 2018/PC SN720 NVMe SSD + 5003 WD Black 2018/PC SN520 NVMe SSD +15b8 ADDI-DATA GmbH + 1001 APCI1516 SP controller (16 digi outputs) + 1003 APCI1032 SP controller (32 digi inputs w/ opto coupler) + 1004 APCI2032 SP controller (32 digi outputs) + 1005 APCI2200 SP controller (8/16 digi outputs (relay)) + 1006 APCI1564 SP controller (32 digi ins, 32 digi outs) + 100a APCI1696 SP controller (96 TTL I/Os) + 3001 APCI3501 SP controller (analog output board) + 300f APCI3600 Noise and vibration measurement board + 7001 APCI7420 2-port Serial Controller + 7002 APCI7300 Serial Controller +15b9 Maestro Digital Communications +15ba Impacct Technology Corp +15bb Portwell Inc +15bc Agilent Technologies + 0100 HPFC-5600 Tachyon DX2+ FC + 0103 QX4 PCI Express quad 4-gigabit Fibre Channel controller + 0105 Celerity FC-44XS/FC-42XS/FC-41XS/FC-44ES/FC-42ES/FC-41ES + 117c 0022 Celerity FC-42XS Fibre Channel Adapter + 117c 0025 Celerity FC-44ES Fibre Channel Adapter + 117c 0026 Celerity FC-42ES Fibre Channel Adapter + 1100 E8001-66442 PCI Express CIC + 2922 64 Bit, 133MHz PCI-X Exerciser & Protocol Checker + 2928 64 Bit, 66MHz PCI Exerciser & Analyzer + 2929 64 Bit, 133MHz PCI-X Analyzer & Exerciser +15bd DFI Inc +15be Sola Electronics +15bf High Tech Computer Corp (HTC) +15c0 BVM Ltd +15c1 Quantel +15c2 Newer Technology Inc +15c3 Taiwan Mycomp Co Ltd +15c4 EVSX Inc +15c5 Procomp Informatics Ltd + 8010 1394b - 1394 Firewire 3-Port Host Adapter Card +15c6 Technical University of Budapest +15c7 Tateyama System Laboratory Co Ltd + 0349 Tateyama C-PCI PLC/NC card Rev.01A +15c8 Penta Media Co Ltd +15c9 Serome Technology Inc +15ca Bitboys OY +15cb AG Electronics Ltd +15cc Hotrail Inc +15cd Dreamtech Co Ltd +15ce Genrad Inc +15cf Hilscher GmbH + 0000 CIFX 50E-DP(M/S) +15d1 Infineon Technologies AG +15d2 FIC (First International Computer Inc) +15d3 NDS Technologies Israel Ltd +15d4 Iwill Corp +15d5 Tatung Co +15d6 Entridia Corp +15d7 Rockwell-Collins Inc +15d8 Cybernetics Technology Co Ltd +15d9 Super Micro Computer Inc +15da Cyberfirm Inc +15db Applied Computing Systems Inc +15dc Litronic Inc + 0001 Argus 300 PCI Cryptography Module +15dd Sigmatel Inc +15de Malleable Technologies Inc +15df Infinilink Corp +15e0 Cacheflow Inc +15e1 Voice Technologies Group Inc +15e2 Quicknet Technologies Inc + 0500 PhoneJack-PCI +15e3 Networth Technologies Inc +15e4 VSN Systemen BV +15e5 Valley technologies Inc +15e6 Agere Inc +15e7 Get Engineering Corp +15e8 National Datacomm Corp + 0130 Wireless PCI Card + 0131 NCP130A2 Wireless NIC +15e9 Pacific Digital Corp + 1841 ADMA-100 DiscStaQ ATA Controller +15ea Tokyo Denshi Sekei K.K. +15eb DResearch Digital Media Systems GmbH +15ec Beckhoff GmbH + 3101 FC3101 Profibus DP 1 Channel PCI + 5102 FC5102 +15ed Macrolink Inc +15ee In Win Development Inc +15ef Intelligent Paradigm Inc +15f0 B-Tree Systems Inc +15f1 Times N Systems Inc +15f2 Diagnostic Instruments Inc +15f3 Digitmedia Corp +15f4 Valuesoft +15f5 Power Micro Research +15f6 Extreme Packet Device Inc +15f7 Banctec +15f8 Koga Electronics Co +15f9 Zenith Electronics Corp +15fa J.P. Axzam Corp +15fb Zilog Inc +15fc Techsan Electronics Co Ltd +15fd N-CUBED.NET +15fe Kinpo Electronics Inc +15ff Fastpoint Technologies Inc +1600 Northrop Grumman - Canada Ltd +1601 Tenta Technology +1602 Prosys-tec Inc +1603 Nokia Wireless Communications +1604 Central System Research Co Ltd +1605 Pairgain Technologies +1606 Europop AG +1607 Lava Semiconductor Manufacturing Inc +1608 Automated Wagering International +1609 Scimetric Instruments Inc +1612 Telesynergy Research Inc. +1618 Stone Ridge Technology + 0001 RDX 11 + 0002 HFT-01 + 0400 FarSync T2P (2 port X.21/V.35/V.24) + 0440 FarSync T4P (4 port X.21/V.35/V.24) + 0610 FarSync T1U (1 port X.21/V.35/V.24) + 0620 FarSync T2U (2 port X.21/V.35/V.24) + 0640 FarSync T4U (4 port X.21/V.35/V.24) + 1610 FarSync TE1 (T1,E1) + 2610 FarSync DSL-S1 (SHDSL) + 3640 FarSync T4E (4-port X.21/V.35/V.24) + 4620 FarSync T2Ue PCI Express (2-port X.21/V.35/V.24) + 4640 FarSync T4Ue PCI Express (4-port X.21/V.35/V.24) +1619 FarSite Communications Ltd + 0400 FarSync T2P (2 port X.21/V.35/V.24) + 0440 FarSync T4P (4 port X.21/V.35/V.24) + 0610 FarSync T1U (1 port X.21/V.35/V.24) + 0620 FarSync T2U (2 port X.21/V.35/V.24) + 0640 FarSync T4U (4 port X.21/V.35/V.24) + 1610 FarSync TE1 (T1,E1) + 1612 FarSync TE1 PCI Express (T1,E1) + 2610 FarSync DSL-S1 (SHDSL) + 3640 FarSync T4E (4-port X.21/V.35/V.24) + 4620 FarSync T2Ue PCI Express (2-port X.21/V.35/V.24) + 4640 FarSync T4Ue PCI Express (4-port X.21/V.35/V.24) + 5621 FarSync T2Ee PCI Express (2 port X.21/V.35/V.24) + 5641 FarSync T4Ee PCI Express (4 port X.21/V.35/V.24) + 6620 FarSync T2U-PMC PCI Express (2 port X.21/V.35/V.24) +161f Rioworks +1621 Lynx Studio Technology, Inc. + 0020 LynxTWO-A + 0021 LynxTWO-B + 0022 LynxTWO-C + 0023 Lynx L22 + 0024 Lynx AES16 + 0025 Lynx AES16-SRC + 0028 Lynx AES16e +1626 TDK Semiconductor Corp. + 8410 RTL81xx Fast Ethernet +1629 Kongsberg Spacetec AS + 1003 Format synchronizer v3.0 + 1006 Format synchronizer, model 10500 + 1007 Format synchronizer, model 21000 + 2002 Fast Universal Data Output + 3100 IO31000 Frame Synchronizer and I/O + 3200 IO32000 Frame Synchronizer and I/O + 4002 High Rate Demodulator + 5001 High Rate FEC + 6001 High Rate Demodulator and FEC +1631 Packard Bell B.V. +1638 Standard Microsystems Corp [SMC] + 1100 SMC2602W EZConnect / Addtron AWA-100 / Eumitcom PCI WL11000 +163c Smart Link Ltd. + 3052 SmartLink SmartPCI562 56K Modem + 5449 SmartPCI561 Modem +1641 MKNet Corp. +1642 Bitland(ShenZhen) Information Technology Co., Ltd. +# nee Brocade Communications Systems, Inc. +1657 Cavium QLogic + 0013 425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA + 103c 1742 82B 8Gbps dual port FC HBA + 103c 1744 42B 4Gbps dual port FC HBA + 1657 0014 425/825 4Gbps/8Gbps PCIe dual port FC HBA + 0014 1010/1020/1007/1741 10Gbps CNA + 1657 0014 1010/1020/1007/1741 10Gbps CNA - FCOE + 1657 0015 1010/1020/1007/1741 10Gbps CNA - LL + 0017 415/815/41B/81B 4Gbps/8Gbps PCIe single port FC HBA + 103c 1741 41B 4Gbps single port FC HBA + 103c 1743 81B 8Gbps single port FC HBA + 1657 0014 415/815 4Gbps/8Gbps single port PCIe FC HBA + 0021 804 8Gbps FC HBA for HP Bladesystem c-class + 0022 BR-1860 Fabric Adapter + 1657 0022 10Gbps CNA - FCOE + 1657 0023 10Gbps CNA - LL + 1657 0024 16Gbps FC HBA +# Mezz card for IBM + 0023 1867/1869 16Gbps FC HBA +# Same Device_ID used for 410 (1port) and 420 (2 port) HBAs. + 0646 400 4Gbps PCIe FC HBA +165a Epix Inc + c100 PIXCI(R) CL1 Camera Link Video Capture Board [custom QL5232] + d200 PIXCI(R) D2X Digital Video Capture Board [custom QL5232] + d300 PIXCI(R) D3X Digital Video Capture Board [custom QL5232] + eb01 PIXCI(R) EB1 PCI Camera Link Video Capture Board +# Gidel Reconfigurable Computing +165c Gidel Ltd. + 5361 PROCStarII60-1 + 5362 PROCStarII60-2 + 5364 PROCStarII60-4 + 5435 ProcSparkII + 5661 ProcE60 + 56e1 ProcE180 + 5911 ProcStarIII110-1 + 5912 ProcStarIII110-2 + 5913 ProcStarIII110-3 + 5914 ProcStarIII110-4 + 5921 ProcStarIII150-1 + 5922 ProcStarIII150-2 + 5923 ProcStarIII150-3 + 5924 ProcStarIII150-4 + 5931 ProcStarIII260-1 + 5932 ProcStarIII260-2 + 5933 ProcStarIII260-3 + 5934 ProcStarIII260-4 + 5941 ProcStarIII340-1 + 5942 ProcStarIII340-2 + 5943 ProcStarIII340-3 + 5944 ProcStarIII340-4 + 5a01 ProceIII80 + 5a11 ProceIII110 + 5a21 ProceIII150 + 5a31 ProceIII260 + 5a41 ProceIII340 + 5b51 ProceIV360 + 5b61 ProceIV530 + 5b71 ProceIV820 + 5c01 ProcStarIV80-1 + 5c02 ProcStarIV80-2 + 5c03 ProcStarIV80-3 + 5c04 ProcStarIV80-4 + 5c11 ProcStarIV110-1 + 5c12 ProcStarIV110-2 + 5c13 ProcStarIV110-3 + 5c14 ProcStarIV110-4 + 5c51 ProcStarIV360-1 + 5c52 ProcStarIV360-2 + 5c53 ProcStarIV360-3 + 5c54 ProcStarIV360-4 + 5c61 ProcStarIV530-1 + 5c62 ProcStarIV530-2 + 5c63 ProcStarIV530-3 + 5c64 ProcStarIV530-4 + 5c71 ProcStarIV820-1 + 5c72 ProcStarIV820-2 + 5c73 ProcStarIV820-3 + 5c74 ProcStarIV820-4 + 5d01 Proc10480 + 5d11 Proc104110 + 5f01 ProceV_A3 + 5f11 ProceV_A7 + 5f21 ProceV_AB + 5f31 ProceV_D5 + 5f41 ProceV_D8 + 6732 Proc6M + 6832 Proc12M + 7101 Proc10a_27 + 7111 Proc10a_48 + 7121 Proc10a_66 + 7141 Proc10a_115 + 7181 Proc10a_27S + 7191 Proc10a_48S + 71a1 Proc10a_66S + 71b1 Proc10A + 72b1 HawkEye + 73b1 Proc10s +165d Hsing Tech. Enterprise Co., Ltd. +165f Linux Media Labs, LLC + 1020 LMLM4 MPEG-4 encoder +1661 Worldspace Corp. +1668 Actiontec Electronics Inc + 0100 Mini-PCI bridge +# Formerly SiByte, Inc. +166d Broadcom Corporation + 0001 SiByte BCM1125/1125H/1250 System-on-a-Chip PCI + 0002 SiByte BCM1125H/1250 System-on-a-Chip HyperTransport + 0012 SiByte BCM1280/BCM1480 System-on-a-Chip PCI-X + 0014 Sibyte BCM1280/BCM1480 System-on-a-Chip HyperTransport +1677 Bernecker + Rainer + 104e 5LS172.6 B&R Dual CAN Interface Card + 12d7 5LS172.61 B&R Dual CAN Interface Card + 20ad 5ACPCI.MFIO-K01 Profibus DP / K-Feldbus / COM +1678 NetEffect + 0100 NE020 10Gb Accelerated Ethernet Adapter (iWARP RNIC) +1679 Tokyo Electron Device Ltd. + 3000 SD Standard host controller [Ellen] +167b ZyDAS Technology Corp. + 2102 ZyDAS ZD1202 + 187e 3406 ZyAIR B-122 CardBus 11Mbs Wireless LAN Card + 187e 3407 ZyAIR B-320 802.11b Wireless PCI Adapter + 2116 ZD1212B Wireless Adapter +167d Samsung Electro-Mechanics Co., Ltd. + a000 MagicLAN SWL-2210P 802.11b [Intersil ISL3874] +167e ONNTO Corp. +1681 Hercules +1682 XFX Pine Group Inc. + c580 Radeon RX 580 +1688 CastleNet Technology Inc. + 1170 WLAN 802.11b card +# nee Atheros Communications, Inc. +168c Qualcomm Atheros + 0007 AR5210 Wireless Network Adapter [AR5000 802.11a] + 1737 0007 WPC54A Wireless PC Card + 1b47 0100 Harmony 8450CN Wireless CardBus Module + 1b47 0110 Skyline 4030 / Harmony 8450 802.11a Wireless CardBus Adapter + 8086 2501 PRO/Wireless 5000 LAN PCI Adapter Module + 0011 AR5211 Wireless Network Adapter [AR5001A 802.11a] + 0012 AR5211 Wireless Network Adapter [AR5001X 802.11ab] + 1186 3a03 AirPro DWL-A650 Wireless Cardbus Adapter (rev.B) + 1186 3a04 AirPro DWL-AB650 Multimode Wireless Cardbus Adapter + 1186 3a05 AirPro DWL-AB520 Multimode Wireless PCI Adapter + 126c 8031 2201 Mobile Adapter + 1385 4400 WAB501 802.11ab Wireless CardBus Card + 1b47 aa00 8460 802.11ab Wireless CardBus Adapter + 0013 AR5212/5213/2414 Wireless Network Adapter + 0308 3402 AG-100 802.11ag Wireless Cardbus Adapter + 0308 3405 G-102 v2 802.11g Wireless Cardbus Adapter + 0308 3408 G-170S 802.11g Wireless CardBus Adapter + 0e11 00e5 NC6000/NC8000 laptop + 10b7 6002 3CRWE154A72 802.11abg Cardbus Adapter + 1113 d301 Philips CPWNA100 Wireless CardBus adapter + 1113 ee23 SMCWPCIT-G 108Mbps Wireless PCI adapter + 1154 033b Buffalo WLI-CB-AMG54 + 1154 034e Buffalo WLI-CB-AG108HP 802.11abg Cardbus Adapter + 1186 3202 DWL-G650 (Rev B3,B5) Wireless cardbus adapter + 1186 3203 AirPlus DWL-G520 Wireless PCI Adapter (rev. A) + 1186 3a07 AirXpert DWL-AG650 Wireless Cardbus Adapter + 1186 3a08 AirXpert DWL-AG520 Wireless PCI Adapter + 1186 3a12 D-Link AirPlus DWL-G650 Wireless Cardbus Adapter(rev.C) + 1186 3a13 AirPlus DWL-G520 Wireless PCI Adapter (rev. B) + 1186 3a14 AirPremier AG DWL-AG530 Wireless PCI Adapter (rev.A) + 1186 3a17 D-Link AirPremier DWL-G680 Wireless Cardbus Adapter + 1186 3a18 D-Link AirPremier DWL-G550 Wireless PCI Adapter + 1186 3a1a WNA-2330 802.11bg Wireless CardBus Adapter + 1186 3a63 D-Link AirPremier DWL-AG660 Wireless Cardbus Adapter + 1186 3a93 Conceptronic C54I Wireless 801.11g PCI card + 1186 3a94 Conceptronic C54C 802.11g Wireless Cardbus Adapter + 1186 3ab0 Allnet ALL0281 Wireless PCI Card + 1385 4600 WAG511 802.11a/b/g Dual Band Wireless PC Card + 1385 4610 WAG511 802.11a/b/g Dual Band Wireless PC Card + 1385 4900 WG311v1 802.11g Wireless PCI Adapter + 1385 4a00 WAG311 802.11a/g Wireless PCI Adapter + 1385 4b00 WG511T 108 Mbps Wireless PC Card (rev.A/B) + 1385 4d00 WG311T 108 Mbps Wireless PCI Adapter (rev.A2) + 1385 4f00 WG511U Double 108 Mbps Wireless PC Card + 1385 5a00 WG311T (rev.A3 v1h3/v1h4) 108 Mbps Wireless PCI Adapter [AR2412] + 1385 5b00 WG511T 108 Mbps Wireless PC Card (rev.C) + 1385 5d00 WPN511 RangeMax Wireless PC Card + 1458 e911 GN-WIAG02 + 1468 0403 U10H014 802.11g Cardbus Adapter + 1468 0408 ThinkPad 11b/g Wireless LAN Mini PCI Adapter + 14b7 0a10 8480-WD 802.11abg Cardbus Adapter + 14b7 0a60 8482-WD ORiNOCO 11a/b/g Wireless PCI Adapter + 14b7 aa30 8800-FC 802.11bg Cardbus Adapter + 14b7 aa40 8470-WD 802.11bg Cardbus Adapter + 14b9 cb21 CB21 802.11a/b/g Cardbus Adapter + 1668 1026 IBM HighRate 11 a/b/g Wireless CardBus Adapter + 168c 0013 AirPlus XtremeG DWL-G650 Wireless PCMCIA Adapter + 168c 1025 DWL-G650B2 Wireless CardBus Adapter + 168c 1027 Engenius NL-3054CB ARIES b/g CardBus Adapter + 168c 1042 Ubiquiti Networks SuperRange a/b/g Cardbus Adapter + 168c 1051 EZ Connect g 802.11g 108Mbps Wireless PCI Adapter + 168c 2026 Netgate 5354MP ARIES a(108Mb turbo)/b/g MiniPCI Adapter + 168c 2027 D-Link AirPlus DWL-G520 Wireless PCI Adapter (rev. A) + 168c 2041 Engenius 5354MP Plus ARIES2 b/g MiniPCI Adapter + 168c 2042 Engenius 5354MP Plus ARIES2 a/b/g MiniPCI Adapter + 168c 2051 TRENDnet TEW-443PI Wireless PCI Adapter + 16a5 160a BWP712 802.11bg Wireless CardBus Adapter + 16ab 7302 Trust Speedshare Turbo Pro Wireless PCI Adapter + 1737 0017 WPC55AG + 1737 0026 WMP55AG v1.1 + 1737 0035 WPC55AG v1.2 802.11abg Cardbus Adapter + 1737 0036 WMP55AG v1.2 802.11abg PCI Adapter + 1799 3000 F6D3000 Dual-Band Wireless A+G Desktop Card + 1799 3010 F6D3010 Dual-Band Wireless A+G Notebook Card + 17cf 0042 Z-COMAX Highpower XG-622H (400mw) 802.11b/g mini-PCI Adapter + 185f 1012 CM9 Wireless a/b/g MiniPCI Adapter + 185f 2012 Wistron NeWeb WLAN a+b+g model CB9 + a727 6801 3CRXJK10075 OfficeConnect Wireless 108Mbps 11g XJACK PC Card + 001a AR2413/AR2414 Wireless Network Adapter [AR5005G(S) 802.11bg] + 1052 168c Sweex Wireless Lan PC Card 54Mbps + 1113 ee20 SMC Wireless CardBus Adapter 802.11g (SMCWCB-G EU) + 1113 ee24 SMC Wireless PCI Card WPCI-G + 1186 3a15 AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.D1) + 1186 3a16 AirPlus G DWL-G510 Wireless PCI Adapter(rev.B) + 1186 3a1c WNA-1330 Notebook Adapter + 1186 3a1d WDA-1320 Desktop Adapter + 1186 3a23 AirPlus G DWL-G520+A Wireless PCI Adapter + 1186 3a24 AirPlus G DWL-G650+A Wireless Cardbus Adapter + 1186 3b08 AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.C1) + 168c 001a Belkin FD7000 + 168c 1052 TP-Link TL-WN510G Wireless CardBus Adapter + 168c 2052 Compex Wireless 802.11 b/g MiniPCI Adapter, Rev A1 [WLM54G] + 16ec 0122 Wireless PCI Adapter Model 5418 + 1737 0053 WPC54G v7 802.11g Wireless-G Notebook Adapter + 1799 700c F5D7000 v5000 Wireless G Desktop Card + 1799 701d F5D7010 v5000 Wireless G Notebook Card + 17f9 0008 DX-WGNBC 802.11bg Wireless CardBus Adapter + 17f9 0018 DX-WGDTC 802.11bg Wireless PCI Adapter + 001b AR5413/AR5414 Wireless Network Adapter [AR5006X(S) 802.11abg] +# Atheros AR5414 32-bit mini-PCI type IIIB + 0777 1107 UB5 802.11a Wireless Mini PCI Adapter + 0777 3002 XR2 802.11g Wireless Mini PCI Adapter + 0777 3005 XR5 802.11a Wireless Mini PCI Adapter + 0777 3009 XR9 900MHz Wireless Mini PCI Adapter + 1154 034e WLI-CB-AG108HP 802.11abg Wireless CardBus Adapter + 1186 3a19 D-Link AirPremier AG DWL-AG660 Wireless Cardbus Adapter + 1186 3a22 AirPremier AG DWL-AG530 Wireless PCI Adapter (rev.B) + 11ad 5001 WN5301A 802.11bg Wireless PCI Adapter + 1458 e901 GN-WI01HT Wireless a/b/g MiniPCI Adapter + 168c 001b Wireless LAN PCI LiteOn + 168c 1062 IPN-W100CB 802.11abg Wireless CardBus Adapter + 168c 2062 EnGenius EMP-8602 (400mw) or Compex WLM54AG (SuperAG) + 168c 2063 EnGenius EMP-8602 (400mw) or Compex WLM54AG + 17f9 000b WL-711A 802.11abg Wireless CardBus Adapter + 17f9 000c WPIA-112AG 802.11abg Wireless PCI Adapter + 17f9 000d PC-686X 802.11abg Wireless Mini PCI Adapter + 185f 1600 DCMA-82 High Power WLAN 802.11a/b/g mini-PCI Module (Super A/G, eXtended Range, 400mW) + 1948 3aba RBTBJ-AW 802.11abg Wireless Cardbus Adapter + a727 6804 Wireless 11a/b/g PC Card with XJACK(r) Antenna + 001c AR242x / AR542x Wireless Network Adapter (PCI-Express) + 0777 3006 SRX 802.11abg Wireless ExpressCard Adapter + 103c 137a AR5BXB63 (Foxconn) 802.11bg Mini PCIe NIC + 106b 0086 AirPort Extreme + 144f 7106 WLL3140 (Toshiba PA3501U-1MPC) 802.11bg Wireless Mini PCIe Card + 144f 7128 WLL3141 (Toshiba PA3613U-1MPC) 802.11bg Wireless Mini PCIe Card + 1468 0428 AR5BXB63 802.11bg NIC + 1468 042a AR5007EG 802.11bg NIC + 147b 1033 AirPace Wi-Fi + 168c 001c AR242x 802.11abg NIC (PCI Express) + 168c 3061 AR5006EGS 802.11bg NIC (2.4GHz, PCI Express) + 168c 3062 AR5006EXS 802.11abg NIC (2.4/5.0GHz, PCI Express) + 168c 3063 AR5006EX 802.11abg NIC (2.4/5.0GHz, PCI Express) + 168c 3065 AR5006EG 802.11bg NIC (2.4GHz, PCI Express) + 168c 3067 AR242x 802.11abg Wireless PCI Express Adapter (rev 01) + 1a3b 1026 AW-GE780 802.11bg Wireless Mini PCIe Card + 001d AR2417 Wireless Network Adapter [AR5007G 802.11bg] + 1799 720b F5D7000 v8000 Wireless G Desktop Card + 1799 721b F5D7010 v8000 Wireless G Notebook Card +# the name AR5005VL is used for some AR5513 based designs + 0020 AR5513 802.11abg Wireless NIC + 0308 3407 M-102 802.11g Wireless Cardbus Adapter + 1186 3a67 DWL-G650M Super G MIMO Wireless Notebook Adapter + 1186 3a68 DWL-G520M Wireless 108G MIMO Desktop Adapter + 187e 340e M-302 802.11g Wireless PCI Adapter + 1976 2003 TEW-601PC 802.11g Wireless CardBus Adapter + 0023 AR5416 Wireless Network Adapter [AR5008 802.11(a)bgn] + 0308 340b NWD-170N 802.11bgn Wireless CardBus Adapter + 1154 0365 Buffalo WLP-CB-AG300 802.11abgn Cardbus Adapter + 1154 0367 WLI-CB-AG301N 802.11abgn Wireless CardBus Adapter + 1186 3a6a DWA-642 802.11n RangeBooster N CardBus Adapter + 1186 3a6b DWA-547 802.11n RangeBooster N 650 DeskTop Adapter + 1186 3a6d DWA-552 802.11n Xtreme N Desktop Adapter (rev A1) + 1186 3a76 DWA-645 802.11n RangeBooster N 650 Notebook Adapter (rev A1) + 1737 0059 WPC300N v2 Wireless-N Notebook Adapter + 1737 0069 WPC100 v1 802.11n RangePlus Wireless Notebook Adapter + 1737 0072 WMP110 v1 802.11n RangePlus Wireless PCI Adapter + 1799 8011 F5D8011 v1 802.11n N1 Wireless Notebook Card + 187e 3411 NWD-370N 802.11n Wireless PCI Adapter + 1976 2008 TEW-621PC 802.11bgn Wireless CardBus Adapter + 0024 AR5418 Wireless Network Adapter [AR5008E 802.11(a)bgn] (PCI-Express) + 106b 0087 AirPort Extreme + 1186 3a70 DWA-556 Xtreme N PCI Express Desktop Adapter + 0027 AR9160 Wireless Network Adapter [AR9001 802.11(a)bgn] + 0777 4082 SR71-A 802.11abgn Wireless Mini PCI Adapter + 0029 AR922X Wireless Network Adapter + 0777 4005 SR71-15 802.11an Mini PCI Adapter + 1186 3a7a DWA-552 802.11n Xtreme N Desktop Adapter (rev A2) + 1186 3a7d DWA-552 802.11n Xtreme N Desktop Adapter (rev A3) + 168c 0029 AR922X Wireless Network Adapter + 168c 2096 Compex WLM200NX / Wistron DNMA-92 + 002a AR928X Wireless Network Adapter (PCI-Express) + 0777 4f05 SR71-X 802.11abgn Wireless ExpressCard Adapter [AR9280] + 103c 3041 AR5BHB92-H 802.11abgn Wireless Half-size Mini PCIe Card [AR9280] + 103c 3042 AzureWave AW-NE773 802.11abgn Wireless Half-size Mini PCIe Card [AR9280] + 105b e006 T77H053.00 802.11bgn Wireless Mini PCIe Card [AR9281] + 105b e01f T77H047.31 802.11bgn Wireless Half-size Mini PCIe Card [AR9283] + 106b 008f AirPort Extreme + 11ad 6600 WN6600A 802.11bgn Wireless Mini PCIe Card [AR9281] + 144f 7141 WLL6080 802.11bgn Wireless Mini PCIe Card [AR9281] + 168c 0203 DW1525 802.11abgn WLAN PCIe Card [AR9280] + 1a32 0303 EM303 802.11bgn Wireless Mini PCIe Card [AR9281] + 1a32 0306 EM306 802.11bgn Wireless Half-size Mini PCIe Card [AR9283] + 1a3b 1067 AW-NE771 802.11bgn Wireless Mini PCIe Card [AR9281] + 1a3b 1071 AW-NE772 802.11abgn Wireless Mini PCIe Card [AR9280] + 1a3b 1081 AW-NE773 802.11abgn Wireless Half-size Mini PCIe Card [AR9280] + 002b AR9285 Wireless Network Adapter (PCI-Express) + 1028 0204 Wireless 1502 802.11bgn Half-size Mini PCIe Card + 1028 0205 Wireless 1702 802.11bgn Half-size Mini PCIe Card [AR9002WB-1NGCD] + 103c 303f U98Z062.10 802.11bgn Wireless Half-size Mini PCIe Card + 103c 3040 U98Z062.12 802.11bgn Wireless Half-size Mini PCIe Card + 105b e017 T77H126.00 802.11bgn Wireless Half-size Mini PCIe Card + 105b e023 T77H121.04 802.11bgn Wireless Half-size Mini PCIe Card + 105b e025 T77H121.05 802.11bgn Wireless Half-size Mini PCIe Card + 1113 e811 WN7811A (Toshiba PA3722U-1MPC) 802.11bgn Wireless Half-size Mini PCIe Card + 185f 30af DNXA-95 802.11bgn Wireless Half-size Mini PCIe Card + 1931 0023 Option GTM67x PCIe WiFi Adapter + 1a3b 1089 AW-NE785 / AW-NE785H 802.11bgn Wireless Full or Half-size Mini PCIe Card + 1a3b 2c37 AW-NB037H 802.11bgn Wireless Half-size Mini PCIe Card [AR9002WB-1NGCD] + 1b9a 0401 XW204E 802.11bgn Wireless Half-size Mini PCIe Card + 1b9a 0c03 WB214E 802.11bgn Wireless Half-size Mini PCIe Card [AR9002WB-1NGCD] + 002c AR2427 802.11bg Wireless Network Adapter (PCI-Express) + 002d AR9227 Wireless Network Adapter + 002e AR9287 Wireless Network Adapter (PCI-Express) + 105b e034 T77H167.00 + 0030 AR93xx Wireless Network Adapter + 103c 1627 AR9380/HB112 802.11abgn 3×3 Wi-Fi Adapter + 106b 009a AirPort Extreme + 1186 3a7e DWA-566 Wireless N 300 Dual Band PCIe Desktop Adapter + 1a56 2000 Killer Wireless-N 1102 Half-size Mini PCIe Card [AR9382] + 1a56 2001 Killer Wireless-N 1103 Half-size Mini PCIe Card [AR9380] + 0032 AR9485 Wireless Network Adapter + 1028 0208 Wireless 1506 WLAN Half Mini-Card + 103c 1838 AR9485/HB125 802.11bgn 1×1 Wi-Fi Adapter + 105b e044 Unex DHXA-225 + 144d 410e AR9485WB-EG 802.11b/g/n mini-PCIe card on a series 3 laptop + 1a3b 1186 AW-NE186H + 0033 AR958x 802.11abgn Wireless Network Adapter + 168c a120 AR9582 802.11a/n WLAN Mini-PCIe Adapter + 0034 AR9462 Wireless Network Adapter + 1028 020b Wireless 1601 802.11abgn Adapter + 1028 0300 Wireless 1802 802.11abgn Adapter + 1a56 2003 Killer Wireless-N 1202 Half-size Mini PCIe Card + 0036 QCA9565 / AR9565 Wireless Network Adapter + 0037 AR9485 Wireless Network Adapter +# Also used as Gigabyte GC-WB150 on a PCIe-to-mini-PCIe converter + 1a3b 2100 AW-NB100H 802.11n Wireless Mini PCIe Card + 003c QCA986x/988x 802.11ac Wireless Network Adapter + 003e QCA6174 802.11ac Wireless Network Adapter + 1a56 143a Killer 1435 Wireless-AC + 1a56 1525 Killer N1525 Wireless-AC + 0040 QCA9980/9990 802.11ac Wireless Network Adapter + 0041 QCA6164 802.11ac Wireless Network Adapter + 0042 QCA9377 802.11ac Wireless Network Adapter + 0046 QCA9984 802.11ac Wave 2 Wireless Network Adapter + 0050 QCA9887 802.11ac Wireless Network Adapter + 0207 AR5210 Wireless Network Adapter [AR5000 802.11a] + 1014 AR5212 802.11abg NIC + 1014 058a ThinkPad 11a/b/g Wireless LAN Mini Express Adapter (AR5BXB6) + 9013 AR5002X Wireless Network Adapter + ff19 AR5006X Wireless Network Adapter + ff1b AR2425 Wireless Network Adapter [AR5007EG 802.11bg] + ff1c AR5008 Wireless Network Adapter + ff1d AR922x Wireless Network Adapter +# Found in "AVM Fritz!Box FON WLAN 7270v3" + 168c ee1c AR9220-AC1A [AVM Fritz!Box FON WLAN 7270 v3] +1695 EPoX Computer Co., Ltd. +169c Netcell Corporation + 0044 Revolution Storage Processing Card +# The right ID is 196d, but they got it nibble-swapped in 2202. +169d Club-3D VB (Wrong ID) +16a5 Tekram Technology Co.,Ltd. +16ab Global Sun Technology Inc + 1100 GL24110P + 1101 PLX9052 PCMCIA-to-PCI Wireless LAN + 1102 PCMCIA-to-PCI Wireless Network Bridge + 8501 WL-8305 Wireless LAN PCI Adapter +16ae SafeNet Inc + 0001 SafeXcel 1140 + 000a SafeXcel 1841 + 1141 SafeXcel 1141 +# misused vendor ID 0001 + 0001 0001 SafeXcel 1141 v. 1.1 + 1841 SafeXcel 1842 +16af SparkLAN Communications, Inc. +16b4 Aspex Semiconductor Ltd +16b8 Sonnet Technologies, Inc. +16be Creatix Polymedia GmbH +16c3 Synopsys, Inc. + abcd DWC_usb3 / PCIe bridge + abce DWC_usb3 + abcf DWC_usb31 + edda EPMockUp +16c6 Micrel-Kendin + 8695 Centaur KS8695 ARM processor + 8842 KSZ8842-PMQL 2-Port Ethernet Switch +16c8 Octasic Inc. +16c9 EONIC B.V. The Netherlands +16ca CENATEK Inc + 0001 Rocket Drive DL +# nee Innocore Gaming Ltd., nee Densitron Gaming Ltd., a division of Densitron Technologies +16cd Advantech Co. Ltd + 0101 DirectPCI SRAM for DPX-11x series + 0102 DirectPCI SRAM for DPX-S/C/E-series + 0103 DirectPCI ROM for DPX-11x series + 0104 DirectPCI ROM for DPX-S/C/E-series + 0105 DirectPCI I/O for DPX-114/DPX-115 + 0106 DirectPCI I/O for DPX-116 + 0107 DirectPCI I/O for DPX-116U + 0108 DirectPCI I/O for DPX-117 + 0109 DirectPCI I/O for DPX-112 + 010a DirectPCI I/O for DPX-C/E-series + 010b DirectPCI I/O for DPX-S series +16ce Roland Corp. +16d5 Acromag, Inc. + 0504 PMC-DX504 Reconfigurable FPGA with LVDS I/O + 0520 PMC520 Serial Communication, 232 Octal + 0521 PMC521 Serial Communication, 422/485 Octal + 1020 PMC-AX1020 Reconfigurable FPGA with A/D & D/A + 1065 PMC-AX1065 Reconfigurable FPGA with A/D & D/A + 2004 PMC-DX2004 Reconfigurable FPGA with LVDS I/O + 2020 PMC-AX2020 Reconfigurable FPGA with A/D & D/A + 2065 PMC-AX2065 Reconfigurable FPGA with A/D & D/A + 3020 PMC-AX3020 Reconfigurable FPGA with A/D & D/A + 3065 PMC-AX3065 Reconfigurable FPGA with A/D & D/A + 4243 PMC424, APC424, AcPC424 Digital I/O and Counter Timer Module + 4248 PMC464, APC464, AcPC464 Digital I/O and Counter Timer Module + 424b PMC-DX2002 Reconfigurable FPGA with Differential I/O + 4253 PMC-DX503 Reconfigurable FPGA with TTL and Differential I/O + 4312 PMC-CX1002 Reconfigurable Conduction-Cooled FPGA Virtex-II with Differential I/O + 4313 PMC-CX1003 Reconfigurable Conduction-Cooled FPGA Virtex-II with CMOS and Differential I/O + 4322 PMC-CX2002 Reconfigurable Conduction-Cooled FPGA Virtex-II with Differential I/O + 4323 PMC-CX2003 Reconfigurable Conduction-Cooled FPGA Virtex-II with CMOS and Differential I/O + 4350 PMC-DX501 Reconfigurable Digital I/O Module + 4353 PMC-DX2003 Reconfigurable FPGA with TTL and Differential I/O + 4357 PMC-DX502 Reconfigurable Differential I/O Module + 4457 PMC730, APC730, AcPC730 Multifunction Module + 4471 XMC730 Multi-function I/O module with front I/O + 4473 XMC730CC Multi-function I/O module with rear I/O Conduction-cooled + 464d PMC408 32-Channel Digital Input/Output Module + 4850 PMC220-16 12-Bit Analog Output Module + 4a42 PMC483, APC483, AcPC483 Counter Timer Module + 4a50 PMC484, APC484, AcPC484 Counter Timer Module + 4a56 PMC230 16-Bit Analog Output Module + 4b47 PMC330, APC330, AcPC330 Analog Input Module, 16-bit A/D + 4c40 PMC-LX40 Reconfigurable Virtex-4 FPGA with plug-in I/O + 4c60 PMC-LX60 Reconfigurable Virtex-4 FPGA with plug-in I/O + 4d4d PMC341, APC341, AcPC341 Analog Input Module, Simultaneous Sample & Hold + 4d4e PMC482, APC482, AcPC482 Counter Timer Board + 524d PMC-DX2001 Reconfigurable FPGA with TTL I/O + 5335 PMC-SX35 Reconfigurable Virtex-4 FPGA with plug-in I/O + 5456 PMC470 48-Channel Digital Input/Output Module + 5601 PMC-VLX85 Reconfigurable Virtex-5 FPGA with plug-in I/O + 5602 PMC-VLX110 Reconfigurable Virtex-5 FPGA with plug-in I/O + 5603 PMC-VSX95 Reconfigurable Virtex-5 FPGA with plug-in I/O + 5604 PMC-VLX155 Reconfigurable Virtex-5 FPGA with plug-in I/O + 5605 PMC-VFX70 Reconfigurable Virtex-5 FPGA with plug-in I/O + 5606 PMC-VLX155-1M Reconfigurable Virtex-5 FPGA with plug-in I/O + 5701 PMC-SLX150: Reconfigurable Spartan-6 FPGA with plug-in I/O + 5702 PMC-SLX150-1M: Reconfigurable Spartan-6 FPGA with plug-in I/O + 5801 XMC-VLX85 Reconfigurable Virtex-5 FPGA with plug-in I/O + 5802 XMC-VLX110 Reconfigurable Virtex-5 FPGA with plug-in I/O + 5803 XMC-VSX95 Reconfigurable Virtex-5 FPGA with plug-in I/O + 5804 XMC-VLX155 Reconfigurable Virtex-5 FPGA with plug-in I/O + 5807 XMC-SLX150: Reconfigurable Spartan-6 FPGA with plug-in I/O + 5808 XMC-SLX150-1M: Reconfigurable Spartan-6 FPGA with plug-in I/O + 5901 APCe8650 PCI Express IndustryPack Carrier Card + 6301 XMC Module with user-configurable Virtex-6 FPGA, 240k logic cells, SFP front I/O + 6302 XMC Module with user-configurable Virtex-6 FPGA, 365k logic cells, SFP front I/O + 6303 XMC Module with user-configurable Virtex-6 FPGA, 240k logic cells, no front I/O + 6304 XMC Module with user-configurable Virtex-6 FPGA, 365k logic cells, no front I/O + 7000 XMC-7K325F: User-configurable Kintex-7 FPGA, 325k logic cells plus SFP front I/O + 7001 XMC-7K410F: User-configurable Kintex-7 FPGA, 410k logic cells plus SFP front I/O + 7002 XMC-7K325AX: User-Configurable Kintex-7 FPGA, 325k logic cells with AXM Plug-In I/O + 7003 XMC-7K410AX: User-Configurable Kintex-7 FPGA, 410k logic cells with AXM Plug-In I/O + 7004 XMC-7K325CC: User-Configurable Kintex-7 FPGA, 325k logic cells, conduction-cooled + 7005 XMC-7K410CC: User-Configurable Kintex-7 FPGA, 410k logic cells, conduction-cooled + 7006 XMC-7A200: User-Configurable Artix-7 FPGA, 200k logic cells with Plug-In I/O + 7007 XMC-7A200CC: User-Configurable Conduction-Cooled Artix-7 FPGA, with 200k logic cells + 7011 AP440-1: 32-Channel Isolated Digital Input Module + 7012 AP440-2: 32-Channel Isolated Digital Input Module + 7013 AP440-3: 32-Channel Isolated Digital Input Module + 7014 AP445: 32-Channel Isolated Digital Output Module + 7015 AP471 48-Channel TTL Level Digital Input/Output Module + 7016 AP470 48-Channel TTL Level Digital Input/Output Module + 7017 AP323 16-bit, 20 or 40 Channel Analog Input Module + 7018 AP408: 32-Channel Digital I/O Module + 7019 AP341 14-bit, 16-Channel Simultaneous Conversion Analog Input Module + 701a AP220-16 12-Bit, 16-Channel Analog Output Module + 701b AP231-16 16-Bit, 16-Channel Analog Output Module + 701c AP225 12-Bit, 16-Channel Analog Output Module with Waveform Memory + 701d AP235 16-Bit, 16-Channel Analog Output Module with Waveform Memory + 7021 APA7-201 Reconfigurable Artix-7 FPGA module 48 TTL channels + 7022 APA7-202 Reconfigurable Artix-7 FPGA module 24 RS485 channels + 7023 APA7-203 Reconfigurable Artix-7 FPGA module 24 TTL & 12 RS485 channels + 7024 APA7-204 Reconfigurable Artix-7 FPGA module 24 LVDS channels + 7027 AP418 16-Channel High Voltage Digital Input/Output Module + 7029 AP342 14-bit, 12-Channel Isolated Simultaneous Conversion Analog Input Module + 702a AP226 12-Bit, 8-Channel Isolated Analog Output Module + 702b AP236 16-Bit, 8-Channel Isolated Analog Output Module + 7031 AP441-1: 32-Channel Isolated Digital Input Module + 7032 AP441-2: 32-Channel Isolated Digital Input Module + 7033 AP441-3: 32-Channel Isolated Digital Input Module + 7042 AP482 Counter Timer Module with TTL Level Input/Output + 7043 AP483 Counter Timer Module with TTL Level and RS422 Input/Output + 7044 AP484 Counter Timer Module with RS422 Input/Output + 7051 APA7-501 Reconfigurable Artix-7 52,160 Cell FPGA module 48 TTL channels + 7052 APA7-502 Reconfigurable Artix-7 52,160 Cell FPGA module 24 RS485 channels + 7053 APA7-503 Reconfigurable Artix-7 52,160 Cell FPGA module 24 TTL & 12 RS485 channels + 7054 APA7-504 Reconfigurable Artix-7 52,160 Cell FPGA module 24 LVDS channels +16da Advantech Co., Ltd. + 0011 INES GPIB-PCI +16df PIKA Technologies Inc. +16e2 Geotest-MTS +16e3 European Space Agency + 1e0f LEON2FT Processor +16e5 Intellon Corp. + 6000 INT6000 Ethernet-to-Powerline Bridge [HomePlug AV] + 6300 INT6300 Ethernet-to-Powerline Bridge [HomePlug AV] +16ec U.S. Robotics + 00ed USR997900 + 0116 USR997902 10/100/1000 Mbps PCI Network Card + 2f00 USR5660A (USR265660A, USR5660A-BP) 56K PCI Faxmodem + 3685 Wireless Access PCI Adapter Model 022415 + 4320 USR997904 10/100/1000 64-bit NIC (Marvell Yukon) + ab06 USR997901A 10/100 Cardbus NIC +16ed Sycron N. V. + 1001 UMIO communication card +16f2 ETAS GmbH + 0200 I/O board + 16f2 0010 ES53xx I/O board +16f3 Jetway Information Co., Ltd. +16f4 Vweb Corp + 8000 VW2010 +16f6 VideoTele.com, Inc. +1702 Internet Machines Corporation (IMC) +1705 Digital First, Inc. +170b NetOctave + 0100 NSP2000-SSL crypto accelerator +170c YottaYotta Inc. +1719 EZChip Technologies + 1000 NPA Access Network Processor Family +# Seems to be a 2nd ID for Vitesse Semiconductor +1725 Vitesse Semiconductor + 7174 VSC7174 PCI/PCI-X Serial ATA Host Bus Controller +172a Accelerated Encryption + 13c8 AEP SureWare Runner 1000V3 +# nee Fujitsu Siemens Computers GmbH +1734 Fujitsu Technology Solutions +1735 Aten International Co. Ltd. +1737 Linksys + 0029 WPG54G ver. 4 PCI Card + 1032 Gigabit Network Adapter + 1737 0015 EG1032 v2 Instant Gigabit Network Adapter + 1737 0024 EG1032 v3 Instant Gigabit Network Adapter + 1064 Gigabit Network Adapter + 1737 0016 EG1064 v2 Instant Gigabit Network Adapter + ab08 21x4x DEC-Tulip compatible 10/100 Ethernet + ab09 21x4x DEC-Tulip compatible 10/100 Ethernet +173b Altima (nee Broadcom) + 03e8 AC1000 Gigabit Ethernet + 03e9 AC1001 Gigabit Ethernet + 03ea AC9100 Gigabit Ethernet + 173b 0001 AC1002 + 03eb AC1003 Gigabit Ethernet +1743 Peppercon AG + 8139 ROL/F-100 Fast Ethernet Adapter with ROL +1745 ViXS Systems, Inc. + 2020 XCode II Series + 2100 XCode 2100 Series +1749 RLX Technologies +174b PC Partner Limited / Sapphire Technology +174d WellX Telecom SA +175c AudioScience Inc +175e Sanera Systems, Inc. +1760 TEDIA spol. s r. o. + 0101 PCD-7004 Digital Bi-Directional Ports PCI Card + 0102 PCD-7104 Digital Input & Output PCI Card + 0121 PCT-7303A PC card with IRC counters + 0122 PCT-7408A PC card with counters and timers + 0123 PCT-7424 PCI card with standard counters + 0214 PCT-7424C (F0) PC card with standard counters + 0215 PCT-7424C (F1) PC card with standard counters + 0216 PCT-7424E (F0) PC card with standard counters + 0217 PCT-7424E (F1) PC card with standard counters + 0303 PCD-7006C Digital Input & Output PCI Card + ff00 CTU CAN FD PCIe Card +1761 Pickering Interfaces Ltd +1771 InnoVISION Multimedia Ltd. +1775 General Electric +177d Cavium, Inc. + 0001 Nitrox XL N1 + 0003 Nitrox XL N1 Lite + 0004 Octeon (and older) FIPS + 0005 Octeon CN38XX Network Processor Pass 3.x + 0006 RoHS + 0010 Nitrox XL NPX + 0020 Octeon CN31XX Network Processor + 0030 Octeon CN30XX Network Processor + 0040 Octeon CN58XX Network Processor + 0050 Octeon CN57XX Network Processor (CN54XX/CN55XX/CN56XX) + 0070 Octeon CN50XX Network Processor + 0080 Octeon CN52XX Network Processor + 0090 Octeon II CN63XX Network Processor + 0091 Octeon II CN68XX Network Processor + 0092 Octeon II CN65XX Network Processor + 0093 Octeon II CN61XX Network Processor + 0094 Octeon Fusion CNF71XX Cell processor + 0095 Octeon III CN78XX Network Processor + 0096 Octeon III CN70XX Network Processor + 9700 Octeon III CN73XX Network Processor + 9702 CN23XX [LiquidIO II] Intelligent Adapter + 177d 0003 CN2350 [LiquidIO II] 2-port 10GbE Intelligent adapter +# This was changed during the production phase to 10GbE adapter. + 177d 0004 CN2350 [LiquidIO II] 2-port 10GbE Intelligent adapter + 177d 0005 CN2360 [LiquidIO II] 2-port 10GbE Intelligent adapter + 177d 0006 CN2360 [LiquidIO II] 2-port 25GbE Intelligent adapter + 177d 0007 CN2350 [LiquidIO II] 2-port 25GbE Intelligent adapter + 177d 0008 CN2350 [LiquidIO II] 2-port 10GbE SFP+ Intelligent adapter + 177d 0009 CN2360 [LiquidIO II] 2-port 10GbE SFP+ Intelligent adapter + 177d 000a CN2350 [LiquidIO II] 2-port 10GBASE-T Intelligent adapter + 177d 000b CN2360 [LiquidIO II] 2-port 10GBASE-T Intelligent adapter + 9703 CN23XX [LiquidIO II] NVMe Controller + 9712 CN23XX [LiquidIO II] SRIOV Virtual Function + 177d 0003 CN2350 [LiquidIO II] 2-port 10GbE SRIOV Virtual Function + 177d 0004 CN2350 [LiquidIO II] 2-port 10GbE SRIOV Virtual Function + 177d 0005 CN2360 [LiquidIO II] 2-port 10GbE SRIOV Virtual Function + 177d 0006 CN2360 [LiquidIO II] 2-port 25GbE SRIOV Virtual Function + 177d 0007 CN2350 [LiquidIO II] 2-port 25GbE SRIOV Virtual Function + 9713 CN23XX [LiquidIO II] NVMe SRIOV Virtual Function + 9800 Octeon Fusion CNF75XX Processor + a001 ThunderX MRML(Master RML Bridge to RSL devices) + a002 THUNDERX PCC Bridge + 177d a102 CN88XX PCC Bridge + a008 THUNDERX SMMU + 177d a108 CN88XX SMMU + a009 THUNDERX Generic Interrupt Controller + a00a THUNDERX GPIO Controller + a00b THUNDERX MPI / SPI Controller + a00c THUNDERX MIO-PTP Controller + a00d THUNDERX MIX Network Controller + a00e THUNDERX Reset Controller + a00f THUNDERX UART Controller + a010 THUNDERX eMMC/SD Controller + a011 THUNDERX MIO-BOOT Controller + a012 THUNDERX TWSI / I2C Controller + a013 THUNDERX CCPI (Multi-node connect) + a014 THUNDERX Voltage Regulator Module + a015 THUNDERX PCIe Switch Logic Interface + a016 THUNDERX Key Memory + a017 THUNDERX GTI (Global System Timers) + a018 THUNDERX Random Number Generator + a019 THUNDERX DFA + a01a THUNDERX Zip Coprocessor + a01b THUNDERX xHCI USB Controller + a01c THUNDERX AHCI SATA Controller + 177d a11c CN88XX AHCI SATA Controller + a01d THUNDERX RAID Coprocessor + a01e THUNDERX Network Interface Controller + a01f THUNDERX Traffic Network Switch + a020 THUNDERX PEM (PCI Express Interface) + a021 THUNDERX L2C (Level-2 Cache Controller) + a022 THUNDERX LMC (DRAM Controller) + a023 THUNDERX OCLA (On-Chip Logic Analyzer) + a024 THUNDERX OSM + a025 THUNDERX GSER (General Serializer/Deserializer) + a026 THUNDERX BGX (Common Ethernet Interface) + a027 THUNDERX IOBN + a029 THUNDERX NCSI (Network Controller Sideband Interface) + a02a ThunderX SGPIO (Serial GPIO controller for SATA disk lights) + a02b THUNDERX SMI / MDIO Controller + a02c THUNDERX DAP (Debug Access Port) + a02d THUNDERX PCIERC (PCIe Root Complex) + a02e ThunderX L2C-TAD (Level 2 cache tag and data) + a02f THUNDERX L2C-CBC + a030 THUNDERX L2C-MCI + a031 THUNDERX MIO-FUS (Fuse Access Controller) + a032 THUNDERX FUSF (Fuse Controller) + a033 THUNDERX Random Number Generator virtual function + a034 THUNDERX Network Interface Controller virtual function + a035 THUNDERX Parallel Bus + a036 ThunderX RAD (RAID acceleration engine) virtual function + a037 THUNDERX ZIP virtual function + a040 THUNDERX CPT Cryptographic Accelerator + a100 THUNDERX CN88XX 48 core SoC + a200 OCTEON TX CN81XX/CN80XX + a300 OCTEON TX CN83XX + af00 CN99xx [ThunderX2] Integrated PCI Host bridge + af84 CN99xx [ThunderX2] Integrated PCI Express RP Bridge +1787 Hightech Information System Ltd. +1789 Ennyah Technologies Corp. +# also used by Struck Innovative Systeme for joint developments +1796 Research Centre Juelich + 0001 SIS1100 [Gigabit link] + 0002 HOTlink + 0003 Counter Timer + 0004 CAMAC Controller + 0005 PROFIBUS + 0006 AMCC HOTlink + 0007 LVD Cable Bus + 0008 100MHz, 64bit Sequence Generator based on VirtexII + 0009 double 14bit-ADC + 000a SIS1100 with N110 TDC + 000b double 14bit-ADC with memory + 000d Synchronisation Slave + 000e SIS1100-eCMC + 000f TDC (GPX) + 0010 PCIe Counter Timer + 0011 SIS1100-e single link + 0012 SIS1100-e quad link + 0013 4x2.5GHz SFP to 4 lane PCIe bridge + 0014 SIS1100 with GPX piggy back + 0015 SIS8100 [Gigabit link, MicroTCA] + 0016 SIS1100e with 4 lanes + 0017 Quad 14bit, 50MHz ADC with 2.5GHz SFP + 0018 SIS8300 4-lane PCI Express, Micro TCA for Physics ADC + 0019 SIS SIS8300-Lx MTCA.4 Digitizer + 001a 100MHz, 64bit Sequence Generator based on VirtexII + 001c Quad 16bit, 150MHz ADC with 2.5GHz SFP + 0030 100MHz, 64bit Sequence Generator based on Spartan6 + 0031 200MHz 64bit Sequence Generator based on Spartan7 +# nee Techwell, Inc. +1797 Intersil Techwell + 5864 TW5864 multimedia video controller + 6801 TW6802 multimedia video card + 6802 TW6802 multimedia other device + 6810 TW6816 multimedia video controller + 6811 TW6816 multimedia video controller + 6812 TW6816 multimedia video controller + 6813 TW6816 multimedia video controller +# port 5 of 8 + 6814 TW6816 multimedia video controller +# port 6 of 8 + 6815 TW6816 multimedia video controller +# port 7 of 8 + 6816 TW6816 multimedia video controller +# channel 8 of 8 + 6817 TW6816 multimedia video controller +# Example MuniPCI-E card: http://www.commell.com.tw/product/surveillance/MPX-6864.htm + 6864 TW6864 multimedia video controller +1799 Belkin + 6001 F5D6001 Wireless PCI Card [Realtek RTL8180] + 6020 F5D6020 v3000 Wireless PCMCIA Card [Realtek RTL8180] + 6060 F5D6060 Wireless PDA Card + 700f F5D7000 v7000 Wireless G Desktop Card [Realtek RTL8185] + 701f F5D7010 v7000 Wireless G Notebook Card [Realtek RTL8185] +179a id Quantique + 0001 Quantis PCI 16Mbps +179c Data Patterns + 0557 DP-PCI-557 [PCI 1553B] + 0566 DP-PCI-566 [Intelligent PCI 1553B] + 1152 DP-cPCI-1152 (8-channel Isolated ADC Module) + 5031 DP-CPCI-5031-Synchro Module +# cPCI Carrier for Mezzanine Modules + 5112 DP-cPCI-5112 [MM-Carrier] + 5121 DP-CPCI-5121-IP Carrier + 5211 DP-CPCI-5211-IP Carrier + 5679 AGE Display Module +17a0 Genesys Logic, Inc + 7163 GL9701 PCIe to PCI Bridge + 8083 GL880 USB 1.1 UHCI controller + 8084 GL880 USB 2.0 EHCI controller + 9750 GL9750 SD Host Controller +17aa Lenovo + 402b Intel 82599ES 10Gb 2-port Server Adapter X520-2 +17ab Phillips Components +17af Hightech Information System Ltd. +17b3 Hawking Technologies + ab08 PN672TX 10/100 Ethernet +17b4 Indra Networks, Inc. + 0011 WebEnhance 100 GZIP Compression Card + 0012 WebEnhance 200 GZIP Compression Card + 0015 WebEnhance 300 GZIP Compression Card + 0016 StorCompress 300 GZIP Compression Card + 0017 StorSecure 300 GZIP Compression and AES Encryption Card +17c0 Wistron Corp. +17c2 Newisys, Inc. +# nee Airgo Networks, Inc. +17cb Qualcomm + 0001 AGN100 802.11 a/b/g True MIMO Wireless Card + 1385 5c00 WGM511 Pre-N 802.11g Wireless CardBus Adapter + 1737 0045 WMP54GX v1 802.11g Wireless-G PCI Adapter with SRX + 0002 AGN300 802.11 a/b/g True MIMO Wireless Card + 1385 6d00 WPNT511 RangeMax 240 Mbps Wireless CardBus Adapter + 1737 0054 WPC54GX4 v1 802.11g Wireless-G Notebook Adapter with SRX400 + 0400 Datacenter Technologies QDF2432 PCI Express Root Port + 0401 Datacenter Technologies QDF2400 PCI Express Root Port +17cc NetChip Technology, Inc + 2280 USB 2.0 +17cd Cadence Design Systems, Inc. +17cf Z-Com, Inc. +17d3 Areca Technology Corp. + 1110 ARC-1110 4-Port PCI-X to SATA RAID Controller + 1120 ARC-1120 8-Port PCI-X to SATA RAID Controller + 1130 ARC-1130 12-Port PCI-X to SATA RAID Controller + 1160 ARC-1160 16-Port PCI-X to SATA RAID Controller + 1170 ARC-1170 24-Port PCI-X to SATA RAID Controller + 1201 ARC-1200 2-Port PCI-Express to SATA II RAID Controller + 1203 ARC-1203 2/4/8 Port PCIe 2.0 to SATA 6Gb RAID Controller + 1210 ARC-1210 4-Port PCI-Express to SATA RAID Controller + 1214 ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller + 17d3 1214 ARC-1214 4-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller + 17d3 1224 ARC-1224 8-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller + 17d3 1264 ARC-1264 12/16 Port PCIe 2.0 to SATA 6Gb RAID Controller + 17d3 1284 ARC-1284 24 Port PCIe 2.0 to SATA 6Gb RAID Controller + 1220 ARC-1220 8-Port PCI-Express to SATA RAID Controller + 1222 ARC-1222 8-Port PCI-Express to SAS/SATA II RAID Controller + 1230 ARC-1230 12-Port PCI-Express to SATA RAID Controller + 1260 ARC-1260 16-Port PCI-Express to SATA RAID Controller + 1280 ARC-1280/1280ML 24-Port PCI-Express to SATA II RAID Controller + 17d3 1221 ARC-1221 8-Port PCI-Express to SATA RAID Controller + 1300 ARC-1300ix-16 16-Port PCI-Express to SAS Non-RAID Host Adapter + 1320 ARC-1320 8/16 Port PCIe 2.0 to SAS/SATA 6Gb Non-RAID Host Adapter + 1330 ARC-1330 16 Port PCIe 3.0 to SAS/SATA 12Gb Non-RAID Host Adapter + 1680 ARC-1680 series PCIe to SAS/SATA 3Gb RAID Controller + 17d3 1212 ARC-1212 4-Port PCIe to SAS/SATA II RAID Controller + 17d3 1222 ARC-1222 8-Port PCIe to SAS/SATA 3Gb RAID Controller + 17d3 1680 ARC-1680 8/12/16/24 Port PCIe to SAS/SATA 3Gb RAID Controller + 1880 ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller + 17d3 1213 ARC-1213 4-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller + 17d3 1215 ARC-1215 4-Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller + 17d3 1216 ARC-1216 4-Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller + 17d3 1223 ARC-1223 8-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller + 17d3 1225 ARC-1225 8-Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller + 17d3 1226 ARC-1226 8-Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller + 17d3 1880 ARC-1880 8/12/16/24 Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller + 17d3 1882 ARC-1882 8/12/16/24 Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller + 17d3 1883 ARC-1883 8/12/16/24 Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller + 1884 ARC-1884 series PCIe 3.0 to SAS/SATA 12/6Gb RAID Controller + 188a ARC-1886 series PCIe 4.0 to NVMe/SAS/SATA 16/12/6Gb RAID Controller +# nee Neterion Inc., previously S2io Inc. +17d5 Exar Corp. + 5731 Xframe 10-Gigabit Ethernet PCI-X + 5732 Xframe II 10-Gigabit Ethernet PCI-X 2.0 + 5831 Xframe 10-Gigabit Ethernet PCI-X + 103c 12d5 PCI-X 133MHz 10GbE SR Fiber + 10a9 8020 Single Port 10-Gigabit Ethernet (PCI-X, Fiber) + 10a9 8024 Single Port 10-Gigabit Ethernet (PCI-X, Fiber) + 5832 Xframe II 10-Gigabit Ethernet PCI-X 2.0 + 103c 1337 PCI-X 266MHz 10GigE SR [AD385A] + 10a9 8021 Single Port 10-Gigabit Ethernet II (PCI-X, Fiber) + 17d5 6020 Xframe II SR + 17d5 6021 Xframe II SR, Low Profile + 17d5 6022 Xframe E SR + 17d5 6420 Xframe II LR + 17d5 6421 Xframe II LR, Low Profile + 17d5 6422 Xframe E LR + 17d5 6c20 Xframe II CX4 + 17d5 6c21 Xframe II CX4, Low Profile + 17d5 6c22 Xframe E CX4 + 5833 X3100 Series 10 Gigabit Ethernet PCIe + 17d5 6030 X3110 Single Port SR + 17d5 6031 X3120 Dual Port SR + 17d5 6430 X3110 Single Port LR + 17d5 6431 X3120 Dual Port LR + 17d5 7030 X3110 Single Port LRM + 17d5 7031 X3120 Dual Port LRM + 17d5 7430 X3110 Single Port 10GBase-T + 17d5 7431 X3120 Dual Port 10GBase-T + 17d5 7830 X3110 Single Port 10GBase-CR + 17d5 7831 X3120 Dual Port 10GBase-CR +17db Cray Inc + 0101 XT Series [Seastar] 3D Toroidal Router +17de KWorld Computer Co. Ltd. +17df Dini Group + 1864 Virtex4 PCI Board w/ QL5064 Bridge [DN7000K10PCI/DN8000K10PCI/DN8000K10PSX/NOTUS] + 1865 Virtex4 ASIC Emulator [DN8000K10PCIe] + 1866 Virtex4 ASIC Emulator Cable Connection [DN8000K10PCI] + 1867 Virtex4 ASIC Emulator Cable Connection [DN8000K10PCIe] + 1868 Virtex4 ASIC Emulator [DN8000K10PCIe-8] + 1900 Virtex5 PCIe ASIC Emulator [DN9000K10PCIe8T/DN9002K10PCIe8T/DN9200K10PCIe8T/DN7006K10PCIe8T/DN7406K10PCIe8T] + 1901 Virtex5 PCIe ASIC Emulator Large BARs [DN9000K10PCIe8T/DN9002K10PCIe8T/DN9200K10PCIe8T/DN7006K10PCIe8T/DN7406K10PCIe8T] + 1902 Virtex5 PCIe ASIC Emulator Low Power [Interceptor] + 1903 Spartan6 PCIe FPGA Accelerator Board [DNBFCS12PCIe] + 1904 Virtex6 PCIe ASIC Emulation Board [DNDUALV6_PCIe4] + 1905 Virtex6 PCIe ASIC Emulation Board [DNV6F6PCIe] + 1906 Virtex6 PCIe ASIC Emulation Board [DN2076K10] + 1907 Virtex6 PCIe ASIC Emulation Board [DNV6F2PCIe] + 1908 Virtex6 PCIe ASIC Emulation Board Large BARs[DNV6F2PCIe] + 1909 Kintex7 PCIe FPGA Accelerator Board [DNK7F5PCIe] + 190a Virtex7 PCIe ASIC Emulation Board [DNV7F1A] + 190b Stratix5 PCIe ASIC Emulation Board [DNS5GXF2] + 190c Virtex7 PCIe ASIC Emulation Board [DNV7F2A] + 190d Virtex7 PCIe ASIC Emulation Board [DNV7F4A] + 190e Virtex7 PCIe ASIC Emulation Board [DNV7F2B] + 190f KintexUS PCIe MainRef Design [DNPCIE_40G_KU_LL] + 1910 VirtexUS ASIC Emulation Board [DNVUF4A] + 1911 VirtexUS PCIe ASIC Emulation Board [DNVU_F2PCIe] + 1912 KintexUS PCIe MainRef Design [DNPCIe_40G_KU_LL_QSFP] + 1913 VirtexUS ASIC Emulation Board [DNVUF1A] + 1914 VirtexUS ASIC Emulation Board [DNVUF2A] + 1915 Arria10 PCIe MainRef Design [DNPCIe_80G_A10_LL] + 1916 VirtexUS PCIe Accelerator Board [DNVUF2_HPC_PCIe] + 1917 UltrascalePlus PCIe Accelerator Board [DNPCIe_400G_VU_LL] + 1918 VirtexUS+ ASIC Emulation Board [DNVUPF4A] + 1919 UltrascalePlus PCIe Accelerator Board [DNPCIe_400G_VUP_HBM_LL] + 1a00 Virtex6 PCIe DMA Netlist Design + 1a01 Virtex6 PCIe Darklite Design [DNPCIe_HXT_10G_LL] + 1a02 Virtex7 PCIe DMA Netlist Design + 1a03 Kintex7 PCIe Darklite Design [DNPCIe_K7_10G_LL] + 1a05 Stratix5 PCIe Darklite Design [DNS5GX_F2] + 1a06 VirtexUS PCIe DMA Netlist Design + 1a07 KintexUS PCIe Darklite Design [DNPCIe_40G_KU_LL] + 1a08 KintexUS PCIe Darklite Design [DNPCIe_40G_KU_LL_QSFP] + 1a09 Arria10 PCIe Darklite Design [DNPCIe_80G_A10_LL] + 1a0a VirtexUS PCIe Darklite Design [DNVUF2_HPC_PCIe] + 1a0b UltrascalePlus PCIe Darklite Design [DNPCIe_400G_VU_LL] + 1a0c KintexUS PCIe DRAM Packet Capture Design [DNPCIe_40G_KU_LL] + 1a0d KintexUS PCIe DRAM Packet Capture Design [DNPCIe_40G_KU_LL_2QSFP] + 1a0e UltrascalePlus PCIe Darklite Design [DNPCIe_400G_VUP_HBM_LL] +17e4 Sectra AB + 0001 KK671 Cardbus encryption board + 0002 KK672 Cardbus encryption board +# nee Entropic Communications Inc. +17e6 MaxLinear + 0010 EN2010 [c.Link] MoCA Network Controller (Coax, PCI interface) + 0011 EN2010 [c.Link] MoCA Network Controller (Coax, MPEG interface) + 0021 EN2210 [c.Link] MoCA Network Controller (Coax) + 0025 EN2510 [c.Link] MoCA Network Controller (Coax, PCIe interface) + 0027 EN2710 [c.Link] MoCA 2.0 Network Controller (Coax, PCIe interface) + 3700 MoCA 2.0 Network Controller (Coax, PCIe interface) + 3710 MoCA 2.5 Network Controller (Coax, PCIe interface) +17ee Connect Components Ltd +17f2 Albatron Corp. +17f3 RDC Semiconductor, Inc. + 1010 R1010 IDE Controller + 1011 R1011 IDE Controller + 1012 R1012 IDE Controller + 1031 PCI/PCI-X to PCI-E Bridge + 2012 M2012/R3308 VGA-compatible graphics adapter + 6020 R6020 North Bridge + 6021 R6021 Host Bridge + 6030 R6030 ISA Bridge + 6031 R6031 ISA Bridge + 6040 R6040 MAC Controller + 6060 R6060 USB 1.1 Controller + 6061 R6061 USB 2.0 Controller +17f7 Topdek Semiconductor Inc. +17f9 Gemtek Technology Co., Ltd +17fc IOGEAR, Inc. +17fe InProComm Inc. + 2120 IPN 2120 802.11b + 1737 0020 WMP11 v4 802.11b Wireless-B PCI Adapter + 2220 IPN 2220 802.11g + 1468 0305 T60N871 802.11g Mini PCI Wireless Adapter + 1737 0029 WPC54G v4 802.11g Wireless-G Notebook Adapter +17ff Benq Corporation +1800 Qualcore Logic Inc. + 1100 Nanospeed Trading Gateway +1803 ProdaSafe GmbH +1804 Ralink corp. (wrong ID) + 3060 RT3060 Wireless 802.11n 1T/1R +1805 Euresys S.A. +1809 Lumanate, Inc. +180c IEI Integration Corp +1813 Ambient Technologies Inc + 4000 HaM controllerless modem + 16be 0001 V9x HAM Data Fax Modem + 4100 HaM plus Data Fax Modem + 16be 0002 V9x HAM 1394 +1814 Ralink corp. + 0101 Wireless PCI Adapter RT2400 / RT2460 + 1043 0127 WiFi-b add-on Card + 1371 0010 Minitar MNW2BPCI Wireless PCI Card + 1462 6828 PC11B2 (MS-6828) Wireless 11b PCI Card + 0200 RT2500 802.11g PCI [PC54G2] + 0201 RT2500 Wireless 802.11bg + 1043 130f WL-130g + 1186 3c00 DWL-G650X Wireless 11g CardBus Adapter + 1371 001e CWC-854 Wireless-G CardBus Adapter + 1371 001f CWM-854 Wireless-G Mini PCI Adapter + 1371 0020 CWP-854 Wireless-G PCI Adapter + 1458 e381 GN-WMKG 802.11b/g Wireless CardBus Adapter + 1458 e931 GN-WIKG 802.11b/g mini-PCI Adapter + 1462 6833 Unknown 802.11g mini-PCI Adapter + 1462 6835 Wireless 11G CardBus CB54G2 + 1737 0032 WMP54G v4.0 PCI Adapter + 1799 700a F5D7000 v2000/v3000 Wireless G Desktop Card + 1799 701a F5D7010 v2000/v3000 Wireless G Notebook Card + 1814 2560 RT2500 Wireless 802.11bg + 182d 9073 WL-115 Wireless Network PCI Adapter + 185f 22a0 CN-WF513 Wireless Cardbus Adapter + 18eb 5312 WL531P IEEE 802.11g PCI Card-EU + 1948 3c00 C54RC v1 Wireless 11g CardBus Adapter + 1948 3c01 C54Ri v1 Wireless 11g PCI Adapter + 0300 Wireless Adapter Canyon CN-WF511 + 0301 RT2561/RT61 802.11g PCI + 1186 3c08 AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.E1) + 1186 3c09 DWL-G510 Rev C + 13d1 abe3 miniPCI Pluscom 802.11 a/b/g + 1458 e933 GN-WI01GS + 1458 e934 GN-WP01GS + 1462 b833 MP54G5 (MS-6833B) + 1737 0055 WMP54G v4.1 + 1799 700e F5D7000 v6000 Wireless G Desktop Card + 1799 701e F5D7010 v6000 Wireless G Notebook Card + 17f9 0012 AWLC3026T 802.11g Wireless CardBus Adapter + 1814 2561 EW-7108PCg/EW-7128g + 0302 RT2561/RT61 rev B 802.11g + 1186 3a71 DWA-510 Wireless G Desktop Adapter + 1186 3c08 AirPlus G DWL-G630 Wireless Cardbus Adapter (rev.E2) + 1186 3c09 AirPlus G DWL-G510 Wireless Network Adapter (Rev.C) + 1462 b834 PC54G3 Wireless 11g PCI Card + 1948 3c23 C54RC v2 Wireless 11g CardBus Adapter + 1948 3c24 C54Ri v2 Wireless 11g PCI Adapter + 0401 RT2600 802.11 MIMO + 1737 0052 WPC54GR v1 802.11g Wireless-G Notebook Adapter with RangeBooster + 17f9 0011 WPCR-137G 802.11bg Wireless CardBus Adapter + 17f9 0016 WPIR-119GH 802.11bg Wireless Desktop Adapter + 0601 RT2800 802.11n PCI + 1799 801c F5D8011 v3 802.11n N1 Wireless Notebook Card + 187e 3412 NWD-310N 802.11n Wireless PCI Adapter + 0681 RT2890 Wireless 802.11n PCIe + 1458 e939 GN-WS30N-RH 802.11bgn Mini PCIe Card + 0701 RT2760 Wireless 802.11n 1T/2R + 1737 0074 WMP110 v2 802.11n RangePlus Wireless PCI Adapter + 0781 RT2790 Wireless 802.11n 1T/2R PCIe + 1814 2790 RT2790 Wireless 802.11n 1T/2R PCIe + 3060 RT3060 Wireless 802.11n 1T/1R + 1186 3c04 DWA-525 Wireless N 150 Desktop Adapter (rev.A1) + 3062 RT3062 Wireless 802.11n 2T/2R + 3090 RT3090 Wireless 802.11n 1T/1R PCIe + 13bd 1057 GN-WS32L-RH Half-size Mini PCIe Card + 3091 RT3091 Wireless 802.11n 1T/2R PCIe + 3092 RT3092 Wireless 802.11n 2T/2R PCIe + 3290 RT3290 Wireless 802.11n 1T/1R PCIe + 103c 18ec Ralink RT3290LE 802.11bgn 1x1 Wi-Fi and Bluetooth 4.0 Combo Adapter + 3298 RT3290 Bluetooth + 103c 18ec Ralink RT3290LE 802.11bgn 1x1 Wi-Fi and Bluetooth 4.0 Combo Adapter + 3592 RT3592 Wireless 802.11abgn 2T/2R PCIe + 359f RT3592 PCIe Wireless Network Adapter + 5360 RT5360 Wireless 802.11n 1T/1R + 1186 3c05 DWA-525 Wireless N 150 Desktop Adapter (rev.A2) + 20f4 703a TEW-703PI N150 Wireless PCI Adapter + 5362 RT5362 PCI 802.11n Wireless Network Adapter + 5390 RT5390 Wireless 802.11n 1T/1R PCIe + 103c 1636 U98Z077.00 Half-size Mini PCIe Card + 5392 RT5392 PCIe Wireless Network Adapter + 539b RT5390R 802.11bgn PCIe Wireless Network Adapter + 539f RT5390 [802.11 b/g/n 1T1R G-band PCI Express Single Chip] + 103c 1637 Pavilion DM1Z-3000 PCIe wireless card + 5592 RT5592 PCIe Wireless Network Adapter + e932 RT2560F 802.11 b/g PCI +1815 Devolo AG +1820 InfiniCon Systems Inc. +1822 Twinhan Technology Co. Ltd + 4e35 Mantis DTV PCI Bridge Controller [Ver 1.0] +182d SiteCom Europe BV +# HFC-based ISDN card + 3069 ISDN PCI DC-105V2 + 9790 WL-121 Wireless Network Adapter 100g+ [Ver.3] +182e Raza Microelectronics, Inc. + 0008 XLR516 Processor +# Strange vendor ID used by BCM5785 when in RAID mode +182f Broadcom +# HT1000 uses 3 IDs 1166:024a (Native SATA Mode), 1166:024b (PATA/IDE Mode), 182f:000b (RAID Mode) depends on SATA BIOS setting + 000b BCM5785 [HT1000] SATA (RAID Mode) +1830 Credence Systems Corporation + 8000 CPIn + 8001 CPId + 8002 CPIx + 8003 CPIq +183b MikroM GmbH + 08a7 MVC100 DVI + 08a8 MVC101 SDI + 08a9 MVC102 DVI+Audio + 08b0 MVC200-DC +1846 Alcatel-Lucent +1849 ASRock Incorporation +184a Thales Computers + 1100 MAX II cPLD +1850 Advantest Corporation + 0048 EK220-66401 Computer Interface Card +1851 Microtune, Inc. +1852 Anritsu Corp. +1853 SMSC Automotive Infotainment System Group +1854 LG Electronics, Inc. +185b Compro Technology, Inc. + 1489 VideoMate Vista T100 +185f Wistron NeWeb Corp. +1864 SilverBack + 2110 ISNAP 2110 +1867 Topspin Communications + 5a44 MT23108 InfiniHost HCA + 5a45 MT23108 InfiniHost HCA flash recovery + 5a46 MT23108 InfiniHost HCA bridge + 6278 MT25208 InfiniHost III Ex (Tavor compatibility mode) + 6282 MT25208 InfiniHost III Ex +186c Humusoft, s.r.o. + 0612 AD612 Data Acquisition Device + 0614 MF614 Multifunction I/O Card + 0622 AD622 Data Acquisition Device + 0624 MF624 Multifunction I/O PCI Card + 0625 MF625 3-phase Motor Driver + 0634 MF634 Multifunction I/O PCIe Card + 0644 MF644 Multifunction I/O Thb Card +186f WiNRADiO Communications +1876 L-3 Communications + a101 VigraWATCH PCI + a102 VigraWATCH PMC + a103 Vigra I/O +187e ZyXEL Communications Corporation + 3403 ZyAir G-110 802.11g + 340e M-302 802.11g XtremeMIMO +1885 Avvida Systems Inc. +1888 Varisys Ltd + 0301 VMFX1 FPGA PMC module + 0601 VSM2 dual PMC carrier + 0710 VS14x series PowerPC PCI board + 0720 VS24x series PowerPC PCI board +188a Ample Communications, Inc +1890 Egenera, Inc. +1894 KNC One +1896 B&B Electronics Manufacturing Company, Inc. + 4202 MIport 3PCIU2 2-port Serial + 4204 MIport 3PCIU4 4-port Serial + 4208 MIport 3PCIU8 8-port Serial + 4211 MIport 3PCIOU1 1-port Isolated Serial + 4212 MIport 3PCIOU2 2-port Isolated Serial + 4214 MIport 3PCIOU4 4-port Isolated Serial + bb10 3PCI2 2-Port Serial + bb11 3PCIO1 1-Port Isolated Serial +1897 AMtek +18a1 Astute Networks Inc. +18a2 Stretch Inc. + 0002 VRC6016 16-Channel PCIe DVR Card +18a3 AT&T +18ac DViCO Corporation + d500 FusionHDTV 5 + d800 FusionHDTV 3 Gold + d810 FusionHDTV 3 Gold-Q + d820 FusionHDTV 3 Gold-T + db30 FusionHDTV DVB-T Pro + db40 FusionHDTV DVB-T Hybrid + db78 FusionHDTV DVB-T Dual Express +18b8 Ammasso + b001 AMSO 1100 iWARP/RDMA Gigabit Ethernet Coprocessor +# formally Info-Tek Corp. +18bc GeCube Technologies, Inc. +18c3 Micronas Semiconductor Holding AG + 0720 nGene PCI-Express Multimedia Controller + 1461 032e Hybrid M779 PCI-E +# Nee Octigabay System +18c8 Cray Inc +18c9 ARVOO Engineering BV +18ca XGI Technology Inc. (eXtreme Graphics Innovation) + 0020 Z7/Z9 (XG20 core) + 0021 Z9s/Z9m (XG21 core) + 0027 Z11/Z11M + 0040 Volari V3XT/V5/V8 + 0047 Volari 8300 (chip: XP10, codename: XG47) +# should be 182d +18d2 Sitecom Europe BV (Wrong ID) +# Sitecom HFC-S based ISDN controller card DC-105v2 + 3069 DC-105v2 ISDN controller +18d4 Celestica +18d8 Dialogue Technology Corp. +18dd Artimi Inc + 4c6f Artimi RTMI-100 UWB adapter +18df LeWiz Communications +18e6 MPL AG + 0001 OSCI [Octal Serial Communication Interface] +18eb Advance Multimedia Internet Technology, Inc. +18ec Cesnet, z.s.p.o. + 6d05 ML555 + 18ec 0100 NIC (ethernet interfaces) + 18ec 0200 NIC (szedata2) 4x1G + 18ec 0201 NIC (szedata2) 2x10G + 18ec 0300 NIFIC (szedata2) 4x1G + 18ec 0302 NIFIC (szedata2) 2x10G + 18ec 4200 Flexible FlowMon (szedata2) 1x10G + 18ec ff00 Testing design + 18ec ff01 Boot design + c006 COMBO6 + 18ec d001 COMBO-4MTX + 18ec d002 COMBO-4SFP + 18ec d003 COMBO-4SFPRO + 18ec d004 COMBO-2XFP + c032 COMBO-LXT110 + 18ec 0100 NIC (ethernet interfaces) + 18ec 0200 NIC (szedata2) 4x1G + 18ec 0201 NIC (szedata2) 2x10G + 18ec 0300 NIFIC (szedata2) 4x1G + 18ec 0302 NIFIC (szedata2) 2x10G + 18ec 4200 Flexible FlowMon (szedata2) 1x10G + 18ec ff00 Testing design + 18ec ff01 Boot design + c045 COMBO6E + c050 COMBO-PTM + c058 COMBO6X + 18ec d001 COMBO-4MTX + 18ec d002 COMBO-4SFP + 18ec d003 COMBO-4SFPRO + 18ec d004 COMBO-2XFP + c132 COMBO-LXT155 + 18ec 0100 NIC (ethernet interfaces) + 18ec 0200 NIC (szedata2) 4x1G + 18ec 0201 NIC (szedata2) 2x10G + 18ec 0300 NIFIC (szedata2) 4x1G + 18ec 0302 NIFIC (szedata2) 2x10G + 18ec 4200 Flexible FlowMon (szedata2) 1x10G + 18ec ff00 Testing design + 18ec ff01 Boot design + c232 COMBO-FXT100 + 18ec 0100 NIC (ethernet interfaces) + 18ec 0200 NIC (szedata2) 4x1G + 18ec 0201 NIC (szedata2) 2x10G + 18ec 0300 NIFIC (szedata2) 4x1G + 18ec 0302 NIFIC (szedata2) 2x10G + 18ec 4200 Flexible FlowMon (szedata2) 1x10G + 18ec ff00 Testing design + 18ec ff01 Boot design +18ee Chenming Mold Ind. Corp. +18f1 Spectrum GmbH +18f4 Napatech A/S + 0031 NT20X Network Adapter + 0051 NT20X Capture Card + 0061 NT20E Capture Card + 0064 NT20E Inline Card + 0071 NT4E Capture Card + 0074 NT4E Inline Card + 0081 NT4E 4-port Expansion Card + 0091 NT20X Capture Card [New Rev] + 00a1 NT4E-STD Capture Card + 00a4 NT4E-STD Inline Card +# 8 x 1 Gbps / 10 Gbps PCIe Optical Bypass Adapter + 00b1 NTBPE Optical Bypass Adapter + 00c5 NT20E2 Network Adapter 2x10Gb + 00d5 NT40E2-4 Network Adapter 4x10Gb + 00e5 NT40E2-1 Network Adapter 1x40Gb +# 4-Port Adapter for 1 GbE In-Line Bypass Applications + 00f5 NT4E2-4T-BP Network Adapter 4x1Gb with Electrical Bypass + 0105 NT4E2-4-PTP Network Adapter 4x1Gb + 0115 NT20E2-PTP Network Adapter 2x10Gb + 0125 NT4E2-4-PTP Network Adapter 4x1Gb + 0135 NT20E2-PTP Network Adapter 2x10Gb + 0145 NT40E3-4-PTP Network Adapter 4x10Gb + 0155 NT100E3-1-PTP Network Adapter 1x100Gb + 0165 NT80E3-2-PTP Network Adapter 2x40Gb + 0175 NT20E3-2-PTP Network Adapter 2x10Gb + 0185 NT40A01 Network Adapter + 01a5 NT200A01 Network Adapter + 01c5 NT200A02 Network Adapter +18f6 NextIO + 1000 [Nexsis] Switch Virtual P2P PCIe Bridge + 1001 [Texsis] Switch Virtual P2P PCIe Bridge + 1050 [Nexsis] Switch Virtual P2P PCI Bridge + 1051 [Texsis] Switch Virtual P2P PCI Bridge + 2000 [Nexsis] Switch Integrated Mgmt. Endpoint + 2001 [Texsis] Switch Integrated Mgmt. Endpoint +18f7 Commtech, Inc. + 0001 ESCC-PCI-335 Serial PCI Adapter [Fastcom] + 0002 422/4-PCI-335 Serial PCI Adapter [Fastcom] + 0003 232/4-1M-PCI Serial PCI Adapter [Fastcom] + 0004 422/2-PCI-335 Serial PCI Adapter [Fastcom] + 0005 IGESCC-PCI-ISO/1 Serial PCI Adapter [Fastcom] + 000a 232/4-PCI-335 Serial PCI Adapter [Fastcom] + 000b 232/8-PCI-335 Serial PCI Adapter [Fastcom] + 000f FSCC Serial PCI Adapter [Fastcom] + 0010 GSCC Serial PCI Adapter [Fastcom] + 0011 QSSB Serial PCI Adapter [Fastcom] + 0014 SuperFSCC Serial PCI Adapter [Fastcom] + 0015 SuperFSCC-104-LVDS Serial PC/104+ Adapter [Fastcom] + 0016 FSCC-232 RS-232 Serial PCI Adapter [Fastcom] +# Software UARTs + 0017 SuperFSCC-104 Serial PC/104+ Adapter [Fastcom] +# Software UARTs + 0018 SuperFSCC/4 Serial PCI Adapter [Fastcom] +# Software UARTs + 0019 SuperFSCC Serial PCI Adapter [Fastcom] + 001a SuperFSCC-LVDS Serial PCI Adapter [Fastcom] +# Software UARTs + 001b FSCC/4 Serial PCI Adapter [Fastcom] +# RS-644 Only + 001c SuperFSCC/4-LVDS Serial PCI Adapter [Fastcom] +# Software UARTs + 001d FSCC Serial PCI Adapter [Fastcom] + 001e SuperFSCC/4 Serial PCIe Adapter [Fastcom] + 001f SuperFSCC/4 Serial cPCI Adapter [Fastcom] + 0020 422/4-PCIe Serial PCIe Adapter [Fastcom] + 0021 422/8-PCIe Serial PCIe Adapter [Fastcom] +# RS-644 Only + 0022 SuperFSCC/4-LVDS Serial PCIe Adapter [Fastcom] +# Software UARTs + 0023 SuperFSCC/4 Serial cPCI Adapter [Fastcom] +# RS-644 Only, Software UARTs + 0025 SuperFSCC/4-LVDS Serial PCI Adapter [Fastcom] +# RS-644 Only, Software UARTs + 0026 SuperFSCC-LVDS Serial PCI Adapter [Fastcom] +# Software UARTs + 0027 FSCC/4 Serial PCIe Adapter [Fastcom] +18fb Resilience Corporation +1904 Hangzhou Silan Microelectronics Co., Ltd. + 2031 SC92031 PCI Fast Ethernet Adapter + 8139 RTL8139D [Realtek] PCI 10/100BaseTX ethernet adaptor +1905 Micronas USA, Inc. +1912 Renesas Technology Corp. + 0002 SH7780 PCI Controller (PCIC) + 0011 SH7757 PCIe End-Point [PBI] + 0012 SH7757 PCIe-PCI Bridge [PPB] + 0013 SH7757 PCIe Switch [PS] + 0014 uPD720201 USB 3.0 Host Controller + 0015 uPD720202 USB 3.0 Host Controller + 001a SH7758 PCIe-PCI Bridge [PPB] + 001b SH7758 PCIe End-Point [PBI] + 001d SH7758 PCIe Switch [PS] +1919 Soltek Computer Inc. +1923 Sangoma Technologies Corp. + 0040 A200/Remora FXO/FXS Analog AFT card + 0100 A104d QUAD T1/E1 AFT card + 0300 A101 single-port T1/E1 + 0400 A104u Quad T1/E1 AFT +1924 Solarflare Communications + 0703 SFC4000 rev A net [Solarstorm] + 10b8 0102 SMC10GPCIe-10BT (A2) [TigerCard] + 10b8 0103 SMC10GPCIe-10BT (A3) [TigerCard] + 10b8 0201 SMC10GPCIe-XFP (A1) [TigerCard] + 1924 0101 SFE4001-A1 + 1924 0102 SFE4001-A2 + 1924 0103 SFE4001-A3 + 1924 0201 SFE4002-A1 + 1924 0301 SFE4003-A1 + 1924 0302 SFE4003-A2 + 1924 0303 SFE4003-A3 + 1924 0304 SFE4003-A4 + 1924 0500 SFE4005-A0 + 0710 SFC4000 rev B [Solarstorm] + 10b8 0103 SMC10GPCIe-10BT (A3) [TigerCard] + 10b8 0201 SMC10GPCIe-XFP (A1) [TigerCard] + 1924 0102 SFE4001-A2 + 1924 0103 SFE4001-A3 + 1924 0201 SFE4002-A1 + 1924 0302 SFE4003-A2 + 1924 0303 SFE4003-A3 + 1924 0304 SFE4003-A4 + 1924 0500 SFE4005-A0 + 1924 5102 SFN4111T-A2 + 1924 5103 SFN4111T-R3 + 1924 5104 SFN4111T-R4 + 1924 5105 SFN4111T-R5 + 1924 5201 SFN4112F-R1 + 1924 5202 SFN4112F-R2 + 0803 SFC9020 10G Ethernet Controller + 1014 0478 2-port 10GbE Low-Latency (R7) + 1014 0479 2-port 10GbE OpenOnload (R7) + 1014 04a7 Solarflare 10Gb Low-latency Dual-port HBA (R7) + 1014 04a8 Solarflare 10Gb Dual-port HBA (R7) + 103c 2132 Ethernet 10Gb 2-port 570FLR-SFP+ Adapter (R1) + 103c 2136 Ethernet 10Gb 2-port 570SFP+ Adapter (R7) + 1924 1201 SFA6902F-R1 SFP+ AOE Adapter + 1924 6200 SFN5122F-R0 SFP+ Server Adapter + 1924 6201 SFN5122F-R1 SFP+ Server Adapter + 1924 6202 SFN5122F-R2 SFP+ Server Adapter + 1924 6204 SFN5122F-R4 SFP+ Server Adapter + 1924 6205 SFN5122F-R5 SFP+ Server Adapter + 1924 6206 SFN5122F-R6 SFP+ Server Adapter + 1924 6207 SFN5122F-R7 SFP+ Server Adapter + 1924 6210 SFN5322F-R0 SFP+ Precision Time Synchronization Server Adapter + 1924 6211 SFN5322F-R1 SFP+ Precision Time Synchronization Server Adapter + 1924 6217 SFN5322F-R7 SFP+ Precision Time Synchronization Server Adapter + 1924 6227 SFN6122F-R7 SFP+ Server Adapter + 1924 6237 SFN6322F-R7 SFP+ Precision Time Synchronization Server Adapter + 1924 6501 SFN5802K-R1 Mezzanine Adapter + 1924 6511 SFN5814H-R1 Mezzanine Adapter + 1924 6521 SFN5812H-R1 Mezzanine Adapter + 1924 6562 SFN6832F-R2 SFP+ Mezzanine Adapter + 1924 6a05 SFN5112F-R5 SFP+ Server Adapter + 1924 6a06 SFN5112F-R6 SFP+ Server Adapter + 1924 7206 SFN5162F-R6 SFP+ Server Adapter + 1924 7207 SFN5162F-R7 SFP+ Server Adapter + 1924 7a06 SFN5152F-R6 SFP+ Server Adapter + 1924 7a07 SFN5152F-R7 SFP+ Server Adapter + 0813 SFL9021 10GBASE-T Ethernet Controller + 1924 6100 SFN5121T-R0 10GBASE-T Server Adapter + 1924 6102 SFN5121T-R2 10GBASE-T Server Adapter + 1924 6103 SFN5121T-R3 10GBASE-T Server Adapter + 1924 6104 SFN5121T-R4 10GBASE-T Server Adapter + 1924 6902 SFN5111T-R2 10GBASE-T Server Adapter + 1924 6904 SFN5111T-R4 10GBASE-T Server Adapter + 1924 7104 SFN5161T-R4 10GBASE-T Server Adapter + 1924 7904 SFN5151T-R4 10GBASE-T Server Adapter + 0903 SFC9120 10G Ethernet Controller + 1014 04cc SFN7122F-R2 2x10GbE SFP+ Flareon Ultra + 1924 8002 SFN7122F-R1 SFP+ Server Adapter + 1924 8003 SFN7x41Q-R1 Flareon Ultra 7000 Series 10/40G Adapter + 1924 8006 SFN7022F-R1 SFP+ Server Adapter + 1924 8007 SFN7322F-R2 Precision Time SFP+ Server Adapter + 1924 8009 SFN7x22F-R2 Flareon Ultra 7000 Series 10G Adapter + 1924 800a SFN7x02F-R2 Flareon 7000 Series 10G Adapter + 1924 800c SFN7x22F-R3 Flareon Ultra 7000 Series 10G Adapter + 1924 800d SFN7x02F-R3 Flareon 7000 Series 10G Adapter + 1924 8010 SFA7942Q-R1 QSFP+ AOE Adapter + 1924 8015 SFA7942Q-A5-0-R1 QSFP+ AOE Adapter + 0923 SFC9140 10/40G Ethernet Controller + 1924 800b SFN7x42Q-R1 Flareon Ultra 7000 Series 10/40G Adapter + 1924 800e SFN7x42Q-R2 Flareon Ultra 7000 Series 10/40G Adapter + 1924 800f SFN7xx4F-R1 Flareon Ultra 7000 Series 10G Adapter + 0a03 SFC9220 10/40G Ethernet Controller + 1924 8011 SFN8022-R1 8000 Series 10G Adapter + 1924 8012 SFN8522-R1 8000 Series 10G Adapter + 1924 8013 SFN8042-R1 8000 Series 10/40G Adapter + 1924 8014 SFN8542-R1 8000 Series 10/40G Adapter + 1924 8016 SFN8022-R2 8000 Series 10G Adapter + 1924 8017 SFN8522-R2 8000 Series 10G Adapter + 1924 8018 SFN8042-R2 8000 Series 10/40G Adapter + 1924 8019 SFN8542-R2 8000 Series 10/40G Adapter + 1924 801a SFN8722-R1 8000 Series OCP 10G Adapter + 1924 801b SFN8522-R3 8000 Series 10G Adapter + 1924 801c SFN8042-R3 8000 Series 10/40G Adapter + 1924 8021 SFN8041-R1 8000 Series 10/40G Adapter + 0b03 XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller + 1924 801d x2522-R1 2000 Series 10/25G Adapter + 1924 801e x2542-R1 2000 Series 40/100G Adapter + 1924 8022 XtremeScale X2522 10G Network Adapter + 1924 8024 XtremeScale X2562 OCP 3.0 Dual Port SFP28 + 1924 8027 XtremeScale X2541 PCIe Single Port QSFP28 + 1924 8028 XtremeScale X2522-25G Network Adapter + 1924 802a XtremeScale X2542 PCIe Dual Port QSFP28 + 1924 802b XtremeScale X2552 OCP 2.0 Dual Port SFP28 + 1924 802c XtremeScale X2522-25G PCIe Dual Port SFP28 + 1924 802d XtremeScale X2562 OCP 3.0 Dual Port SFP28 + 1803 SFC9020 10G Ethernet Controller (Virtual Function) + 1813 SFL9021 10GBASE-T Ethernet Controller (Virtual Function) + 1903 SFC9120 10G Ethernet Controller (Virtual Function) + 1923 SFC9140 10/40G Ethernet Controller (Virtual Function) + 1a03 SFC9220 10/40G Ethernet Controller (Virtual Function) + 1b03 XtremeScale SFC9250 10/25/40/50/100G Ethernet Controller (Virtual Function) + 6703 SFC4000 rev A iSCSI/Onload [Solarstorm] + 10b8 0102 SMC10GPCIe-10BT (A2) [TigerCard] + 10b8 0103 SMC10GPCIe-10BT (A3) [TigerCard] + 10b8 0201 SMC10GPCIe-XFP (A1) [TigerCard] + 1924 0101 SFE4001-A1 + 1924 0102 SFE4001-A2 + 1924 0103 SFE4001-A3 + 1924 0201 SFE4002-A1 + 1924 0301 SFE4003-A1 + 1924 0302 SFE4003-A2 + 1924 0303 SFE4003-A3 + 1924 0304 SFE4003-A4 + 1924 0500 SFE4005-A0 + c101 EF1-21022T [EtherFabric] +192a BiTMICRO Networks Inc. + 0008 RAMPART +192e TransDimension +1931 Option N.V. + 000c Qualcomm MSM6275 UMTS chip +1932 DiBcom +193c MAXIM Integrated Products +193d Hangzhou H3C Technologies Co., Ltd. +193f AHA Products Group + 0001 AHA36x-PCIX + 0360 AHA360-PCIe + 0363 AHA363-PCIe + 0364 AHA364-PCIe + 0367 AHA367-PCIe + 0370 AHA370-PCIe + 0604 AHA604 + 0605 AHA605 + 3641 AHA3641 + 3642 AHA3642 + 6101 AHA6101 + 6102 AHA6102 +1942 ClearSpeed Technology plc + e511 Advance X620 accelerator card + e521 Advance e620 accelerator card +1947 C-guys, Inc. + 4743 CG200 Dual SD/SDIO Host controller device +1948 Alpha Networks Inc. +194a DapTechnology B.V. + 1111 FireSpy3850 + 1112 FireSpy450b + 1113 FireSpy450bT + 1114 FireSpy850 + 1115 FireSpy850bT + 1200 FireTrac 3460bT + 1201 FireTrac 3460bT (fallback firmware) + 1202 FireTrac 3460bT + 1203 FireTrac 3460bT (fallback firmware) +# nee Curtis, Inc. +1954 One Stop Systems, Inc. +1957 Freescale Semiconductor Inc + 0012 MPC8548E + 0013 MPC8548 + 0014 MPC8543E + 0015 MPC8543 + 0018 MPC8547E + 0019 MPC8545E + 001a MPC8545 + 0020 MPC8568E + 0021 MPC8568 + 0022 MPC8567E + 0023 MPC8567 + 0030 MPC8533E + 0031 MPC8533 + 0032 MPC8544E + 0033 MPC8544 + 0040 MPC8572E + 0041 MPC8572 + 0050 MPC8536E + 0051 MPC8536 + 0052 MPC8535E + 0053 MPC8535 + 0060 MPC8569 + 0061 MPC8569E + 0070 P2020E + 0071 P2020 + 0078 P2010E + 0079 P2010 + 0080 MPC8349E + 0081 MPC8349 + 0082 MPC8347E TBGA + 0083 MPC8347 TBGA + 0084 MPC8347E PBGA + 110a 4074 SIMATIC NET CP 1628 + 0085 MPC8347 PBGA + 110a 4046 SIMATIC NET CP 1623 + 0086 MPC8343E + 0087 MPC8343 + 00b4 MPC8315E + 00b6 MPC8314E + 1a56 1101 Killer Xeno Pro Gigabit Ethernet Controller + 00c2 MPC8379E + 00c3 MPC8379 + 00c4 MPC8378E + 00c5 MPC8378 + 00c6 MPC8377E + 00c7 MPC8377 + 0100 P1020E + 0101 P1020 + 0102 P1021E + 0103 P1021 + 0108 P1011E + 0109 P1011 + 010a P1012E + 010b P1012 + 0110 P1022E + 0111 P1022 + 1c7f 5200 EB5200 + 0118 P1013E + 0119 P1013 + 0128 P1010 + 0400 P4080E + 0401 P4080 + 0408 P4040E + 0409 P4040 + 041f P3041 + 0440 T4240 with security + 0441 T4240 without security + 0446 T4160 with security + 0447 T4160 without security + 0830 T2080 with security + 0831 T2080 without security + 0838 T2081 with security + 0839 T2081 without security + 580c MPC5121e + 7010 MPC8641 PCI Host Bridge + 7011 MPC8641D PCI Host Bridge + 7018 MPC8610 + c006 MPC8308 + 1a56 1201 Killer E2100 Gigabit Ethernet Controller +# PCIe interface for emulator + fc02 RedStone +# CFI device over PCIe + fc03 CFI +1958 Faster Technology, LLC. +1959 PA Semi, Inc + a000 PA6T Core + a001 PWRficient Host Bridge + a002 PWRficient PCI-Express Port + a003 PWRficient SMBus Controller + a004 PWRficient 16550 UART + a005 PWRficient Gigabit Ethernet + a006 PWRficient 10-Gigabit Ethernet + a007 PWRficient DMA Controller + a008 PWRficient LPC/Localbus Interface + a009 PWRficient L2 Cache + a00a PWRficient DDR2 Memory Controller + a00b PWRficient SERDES + a00c PWRficient System/Debug Controller + a00d PWRficient PCI-Express Internal Endpoint +1966 Orad Hi-Tec Systems + 1975 DVG64 family + 1977 DVG128 family +# nee Atheros Communications, Inc. nee Attansic Technology Corp. +1969 Qualcomm Atheros + 1026 AR8121/AR8113/AR8114 Gigabit or Fast Ethernet + 1043 8304 P5KPL-CM Motherboard + 1048 Attansic L1 Gigabit Ethernet + 1043 8226 P5B-MX/WiFi-AP, P5KPL-VM Motherboard + 1062 AR8132 Fast Ethernet + 1063 AR8131 Gigabit Ethernet + 1458 e000 GA-G31M-ES2L Motherboard + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 1066 Attansic L2c Gigabit Ethernet + 1067 Attansic L1c Gigabit Ethernet + 1073 AR8151 v1.0 Gigabit Ethernet + 1083 AR8151 v2.0 Gigabit Ethernet + 1090 AR8162 Fast Ethernet + 1043 108d VivoBook X202E, X202EV + 1091 AR8161 Gigabit Ethernet + 1043 1477 N56VZ + 10a0 QCA8172 Fast Ethernet + 10a1 QCA8171 Gigabit Ethernet + 2048 Attansic L2 Fast Ethernet + 2060 AR8152 v1.1 Fast Ethernet + 2062 AR8152 v2.0 Fast Ethernet + 1043 8468 Eee PC 1015PX +# E2200, E2201, E2205 + e091 Killer E220x Gigabit Ethernet Controller + e0a1 Killer E2400 Gigabit Ethernet Controller + e0b1 Killer E2500 Gigabit Ethernet Controller +196a Sensory Networks Inc. + 0101 NodalCore C-1000 Content Classification Accelerator + 0102 NodalCore C-2000 Content Classification Accelerator + 0105 NodalCore C-3000 Content Classification Accelerator +196d Club-3D BV +196e PNY +1971 AGEIA Technologies, Inc. + 1011 Physics Processing Unit [PhysX] + 1043 0001 PhysX P1 +# nee Eberspaecher Electronics +1974 Star Electronics GmbH & Co. KG + 0009 FlexCard PMC-II + 0011 FlexCard PMC-II Ethernet +1976 TRENDnet +1977 Parsec +197b JMicron Technology Corp. + 0250 JMC250 PCI Express Gigabit Ethernet Controller + 0260 JMC260 PCI Express Fast Ethernet Controller + 0368 JMB368 IDE controller + 2360 JMB360 AHCI Controller + 2361 JMB361 AHCI/IDE + 1462 7235 P965 Neo MS-7235 mainboard + 2362 JMB362 SATA Controller + 1043 8460 P8P67 Deluxe Motherboard + 2363 JMB363 SATA/IDE Controller + 1043 81e4 P5B [JMB363] + 1458 b000 Motherboard + 1849 2363 Motherboard (one of many) + 2364 JMB364 AHCI Controller + 2365 JMB365 AHCI/IDE + 2366 JMB366 AHCI/IDE + 2368 JMB368 IDE controller + 2369 JMB369 Serial ATA Controller + 2380 IEEE 1394 Host Controller + 2381 Standard SD Host Controller + 2382 SD/MMC Host Controller + 2383 MS Host Controller + 2384 xD Host Controller + 2386 Standard SD Host Controller + 2387 SD/MMC Host Controller + 2388 MS Host Controller + 2389 xD Host Controller + 2391 Standard SD Host Controller + 2392 SD/MMC Host Controller + 2393 MS Host Controller + 2394 xD Host Controller +1982 Distant Early Warning Communications Inc + 1600 OX16C954 HOST-A + 16ff OX16C954 HOST-B +1987 Phison Electronics Corporation + 5007 E7 NVMe Controller + 5012 E12 NVMe Controller + 5016 E16 PCIe4 NVMe Controller +1989 Montilio Inc. + 0001 RapidFile Bridge + 8001 RapidFile +198a Nallatech Ltd. +1993 Innominate Security Technologies AG +1999 A-Logics + a900 AM-7209 Video Processor +199a Pulse-LINK, Inc. +199d Xsigo Systems + 8209 Virtual NIC Device + 890a Virtual HBA Device +199f Auvitek + 8501 AU85X1 PCI REV1.1 + 8521 AU8521 TV card +# nee ServerEngines Corp. +19a2 Emulex Corporation + 0120 x1 PCIe Gen2 Bridge[Pilot4] + 0200 BladeEngine 10Gb PCI-E iSCSI adapter + 0201 BladeEngine 10Gb PCIe Network Adapter + 0211 BladeEngine2 10Gb Gen2 PCIe Network Adapter + 0212 BladeEngine2 10Gb Gen2 PCIe iSCSI Adapter + 0221 BladeEngine3 10Gb Gen2 PCIe Network Adapter + 0222 BladeEngine3 10Gb Gen2 PCIe iSCSI Adapter + 0700 OneConnect OCe10100/OCe10102 Series 10 GbE + 103c 1747 NC550SFP DualPort 10GbE Server Adapter + 103c 1749 NC550SFP Dual Port Server Adapter + 103c 174a NC551m Dual Port FlexFabric 10Gb Adapter + 103c 174b StorageWorks NC550 DualPort Converged Network Adapter + 103c 3314 NC551i Dual Port FlexFabric 10Gb Adapter + 0702 OneConnect 10Gb iSCSI Initiator + 0704 OneConnect OCe10100/OCe10102 Series 10 GbE CNA + 10df e602 OneConnect OCe10100 10Gb CNA + 10df e630 OneConnect OCe10102-FM-E / OCe10102-FX-E for EMC VNX Symmetrix + 0710 OneConnect 10Gb NIC (be3) +# FC 5287 / FC 5284; CCIN 5287 + 1014 03d0 PCIe2 2-port 10GbE SR Adapter for POWER +# FC 5288 / FC 5286; CCIN 5288 + 1014 03d1 PCIe2 2-port 10GbE SFP+ Copper Adapter for POWER + 1014 0409 Integrated Multifunction Card with Dual 10GbE SR Optical + Dual 1GbE for Power 750/760 + 1014 040a Integrated Multifunction Card with Dual 10GbE SR Copper + Dual 1GbE for Power 750/760 + 103c 3315 NC553i 10Gb 2-port FlexFabric Converged Network Adapter + 103c 3340 NC552SFP 2-port 10Gb Server Adapter + 103c 3341 NC552m 10Gb 2-port FlexFabric Converged Network Adapter + 103c 3345 NC553m 10Gb 2-port FlexFabric Converged Network Adapter + 103c 337b NC554FLB 10Gb 2-port FlexFabric Converged Network Adapter + 10df e733 Flex System EN4054 4-port 10Gb Ethernet Mezzanine Adapter + 0712 OneConnect 10Gb iSCSI Initiator (be3) + 0714 OneConnect 10Gb FCoE Initiator (be3) + 103c 3315 NC553i 10Gb 2-port FlexFabric Converged Network Adapter + 103c 337b NC554FLB 10Gb 2-port FlexFabric Converged Network Adapter + 0800 ServerView iRMC HTI +19a8 DAQDATA GmbH +19ac Kasten Chase Applied Research + 0001 ACA2400 Crypto Accelerator +19ae Progeny Systems Corporation + 0520 4135 HFT Interface Controller + 0521 Decimator +19ba ZyXEL Communications Corp. + 2330 ZyWALL Turbo Card +19c1 Exegy Inc. +# nee NextNet Wireless +19d1 Motorola Expedience +19d4 Quixant Limited +19da ZOTAC International (MCO) Ltd. +19de Pico Computing +19e2 Vector Informatik GmbH +19e3 DDRdrive LLC + 5801 DDRdrive X1 + 5808 DDRdrive X8 + dd52 DDRdrive X1-30 +19e5 Huawei Technologies Co., Ltd. +# subvendor + 0123 ES3000 V3 NVMe PCIe SSD + 19e5 3022 NVMe SSD ES3600P V3 800GB 2.5" U.2 + 19e5 3023 NVMe SSD ES3600P V3 1200GB 2.5" U.2 + 19e5 3024 NVMe SSD ES3600P V3 1600GB 2.5" U.2 + 19e5 3025 NVMe SSD ES3600P V3 2000GB 2.5" U.2 + 19e5 3026 NVMe SSD ES3600P V3 3200GB 2.5" U.2 + 19e5 3033 NVMe SSD ES3600C V3 1200GB HHHL AIC + 19e5 3034 NVMe SSD ES3600C V3 1600GB HHHL AIC + 19e5 3036 NVMe SSD ES3600C V3 3200GB HHHL AIC + 0200 Hi1822 Family (2*100GE) + 19e5 d139 Hi1822 SP572 (2*100GE) + 0202 Hi1822 Family (2*32G FC) + 19e5 d302 Hi1822 SP521 (2*32G FC) + 19e5 d304 Hi1822 SP526 (2*32G FC) + 0203 Hi1822 Family (2*16G FC) + 19e5 d301 Hi1822 SP520 (2*16G FC) + 19e5 d305 Hi1822 SP525 (2*16G FC) + 0205 Hi1822 Family (2*100GE) + 19e5 df27 Hi1822 MZ731 MEZZ (2*100GE) + 0206 Hi1822 Family (2*25GE) + 19e5 d138 Hi1822 SP582 (2*25GE) + 0210 Hi1822 Family (4*25GE) + 19e5 df2e Hi1822 MZ532 MEZZ (4*25GE) + 0211 Hi1822 Family (4*25GE) + 19e5 d12f Hi1822 SP571 (4*25GE) + 19e5 d137 Hi1822 SP581 (4*25GE) + 0212 Hi1822 Family (2*8G FC) + 19e5 d303 Hi1822 SP522 (2*8G FC) + 19e5 d306 Hi1822 SP523 (2*8G FC) + 1710 iBMA Virtual Network Adapter + 1711 Hi1710 [iBMC Intelligent Management system chip w/VGA support] + 1822 Hi1822 Family (4*25GE) + 19e5 d129 Hi1822 SP570 (4*25GE) + 19e5 d136 Hi1822 SP580 (4*25GE) + 371e Hi1822 Family Virtual Bridge + 375e Hi1822 Family Virtual Function + 379e Hi1822 Family Virtual Function + a120 HiSilicon PCIe Root Port with Gen4 + a121 HiSilicon PCI-PCI Bridge + a122 HiSilicon Embedded DMA Engine + a124 HiSilicon Internal SDI Function Engine + a125 HiSilicon SDI Network Controller + a126 HiSilicon SDI NVMe Storage Controller + a127 HiSilicon SDI Accelerator + a12a HiSilicon Add-on PCI-PCI Bridge + a220 HNS GE Network Controller + a221 HNS GE/10GE/25GE Network Controller + a222 HNS GE/10GE/25GE RDMA Network Controller + a224 HNS GE/10GE/25GE/50GE RDMA Network Controller + a226 HNS GE/10GE/25GE/50GE/100GE RDMA Network Controller + a22a HiSilicon Network For SDI + a22e HNS Network Controller (Virtual Function) + a22f HNS RDMA Network Controller (Virtual Function) + a230 HiSilicon SAS 3.0 HBA + a235 HiSilicon AHCI HBA + a238 HiSilicon USB 3.0 Host Controller + a239 HiSilicon USB 2.0 2-port Host Controller + a23a HiSilicon USB 2.0 Host Controller + a23b HiSilicon USB 1.1 Host Controller + a250 HiSilicon ZIP Engine + a251 HiSilicon ZIP Engine(Virtual Function) + a255 HiSilicon SEC Engine + a256 HiSilicon SEC Engine(Virtual Function) + a258 HiSilicon HPRE Engine + a259 HiSilicon HPRE Engine(Virtual Function) + a25a HiSilicon RDE Engine + a25b HiSilicon RDE Engine(Virtual Function) +19e7 NET (Network Equipment Technologies) + 1001 STIX DSP Card + 1002 STIX - 1 Port T1/E1 Card + 1003 STIX - 2 Port T1/E1 Card + 1004 STIX - 4 Port T1/E1 Card + 1005 STIX - 4 Port FXS Card +19ee Netronome Systems, Inc. +19f1 BFG Tech +19ff Eclipse Electronic Systems, Inc. +1a03 ASPEED Technology, Inc. + 1150 AST1150 PCI-to-PCI Bridge + 2000 ASPEED Graphics Family + 15d9 0832 X10SRL-F +1a05 deltaww +1a07 Kvaser AB + 0006 CAN interface PC104+ HS/HS + 0007 CAN interface PCIcanx II HS or HS/HS + 0008 CAN interface PCIEcan HS or HS/HS + 0009 CAN interface PCI104 HS/HS +1a08 Sierra semiconductor + 0000 SC15064 +1a0e DekTec Digital Video B.V. + 083f DTA-2111 VHF/UHF Modulator +1a17 Force10 Networks, Inc. + 8002 PB-10GE-2P 10GbE Security Card +1a1d GFaI e.V. + 1a17 Meta Networks MTP-1G IDPS NIC +1a1e 3Leaf Systems, Inc. +1a22 Ambric Inc. +1a29 Fortinet, Inc. + 4338 CP8 Content Processor ASIC + 4e36 NP6 Network Processor + 4e37 NP7 Network Processor +1a2b Ascom AG + 0000 GESP v1.2 + 0001 GESP v1.3 + 0002 ECOMP v1.3 + 0005 ETP v1.4 + 000a ETP-104 v1.1 + 000e DSLP-104 v1.1 +# nee Metalink Ltd. +1a30 Lantiq + 0680 MtW8171 [Hyperion II] + 0700 Wave300 PSB8224 [Hyperion III] + 0710 Wave300 PSB8231 [Hyperion III] +1a32 Quanta Microsystems, Inc +1a3b AzureWave + 1112 AR9285 Wireless Network Adapter (PCI-Express) +1a41 Tilera Corp. + 0001 TILE64 processor + 0002 TILEPro processor + 0200 TILE-Gx processor + 0201 TILE-Gx Processor Virtual Function + 2000 TILE-Gx PCI Express Root Port +1a4a SLAC National Accelerator Lab TID-AIR + 1000 MCOR Power Supply Controller + 1010 AMC EVR - Stockholm Timing Board + 1020 Cluster On Board (COB) Ethernet Switch + 2000 PGPCard - 4 Lane + 2001 PGPCard - 8 Lane Plus EVR + 2010 PCI-Express EVR +# PC-260-101-03 + 2020 PGP-GEN3 PCIe + 2030 AXI Stream DAQ PCIe card +1a51 Hectronic AB +1a55 Rohde & Schwarz DVS GmbH + 0010 SDStationOEM + 0011 SDStationOEM II + 0020 Centaurus + 0021 Centaurus II + 0022 Centaurus II LT + 0030 CLIPSTER-VPU 1.x (Hugo) + 0040 Hydra Cinema (JPEG) + 0050 CLIPSTER-VPU 2.x (DigiLab) + 0060 CLIPSTER-DCI 2.x (HydraX) + 0061 Atomix + 0062 Atomix LT + 0063 Atomix HDMI + 0064 Atomix STAN + 0065 Atomix HDMI STAN + 0070 RED Rocket + 0090 CinePlay +1a56 Bigfoot Networks, Inc. +1a57 Highly Reliable Systems +1a58 Razer USA Ltd. +1a5d Celoxica +1a5e Aprius Inc. +1a5f System TALKS Inc. +1a68 VirtenSys Limited +1a71 XenSource, Inc. +1a73 Violin Memory, Inc + 0001 Mozart [Memory Appliance 1010] +1a76 Wavesat +1a77 Lightfleet Corporation +1a78 Virident Systems Inc. + 0031 FlashMAX Drive + 1a78 0034 FlashMAX PCIe SSD [rev 3] + 1a78 0037 FlashMAX PCIe SSD [rev 3D] + 1a78 0038 FlashMAX PCIe SSD [rev 4] + 1a78 0039 FlashMAX PCIe SSD [rev 4D] + 0040 FlashMAX II + 0041 FlashMAX II + 0042 FlashMAX II + 0050 FlashMAX III +1a84 Commex Technologies + 0001 Vulcan SP HT6210 10-Gigabit Ethernet (rev 02) +1a88 MEN Mikro Elektronik + 4d45 Multifunction IP core +1a8a StarBridge, Inc. +1a8c Verigy Pte. Ltd. + 1100 E8001-66443 PCI Express CIC +1a8e DRS Technologies + 2090 Model 2090 PCI Express +1aa8 Ciprico, Inc. + 0009 RAIDCore Controller + 000a RAIDCore Controller +1aae Global Velocity, Inc. +1ab4 Distributed Management Task Force, Inc. (DMTF) +1ab6 CalDigit, Inc. + 6201 RAID Card +# Parallels VM virtual devices +1ab8 Parallels, Inc. + 4000 Virtual Machine Communication Interface + 4005 Accelerated Virtual Video Adapter + 4006 Memory Ballooning Controller +1ab9 Espia Srl +1ac8 Aeroflex Gaisler +1acc Point of View BV +1ad7 Spectracom Corporation + 8000 TSync-PCIe Time Code Processor + 9100 TPRO-PCI-66U Timecode Reader/Generator +1ade Spin Master Ltd. + 1501 Swipetech barcode scanner + 3038 PCIe Video Bridge + 13c2 3016 TT-budget S2-4200 Twin + 4254 0552 S952 v3 +1ae0 Google, Inc. + 0042 Compute Engine Virtual Ethernet [gVNIC] +1ae3 SANBlaze Technology, Inc. +1ae7 First Wise Media GmbH + 0520 HFC-S PCI A [X-TENSIONS XC-520] +1ae8 Silicon Software GmbH + 0a40 microEnable IV-BASE x1 + 0a41 microEnable IV-FULL x1 + 0a44 microEnable IV-FULL x4 + 0e44 microEnable IV-GigE x4 +1ae9 Wilocity Ltd. + 0101 Wil6200 PCI Express Upstream Port + 0200 Wil6200 PCI Express Port + 0201 Wil6200 Wireless PCI Express Port + 0301 Wil6200 802.11ad Wireless Network Adapter + 0302 Wil6200 802.11ad Wireless Network Adapter + 0310 Wil6200 802.11ad Wireless Network Adapter +1aea Alcor Micro + 6601 AU6601 PCI-E Flash card reader controller + 6621 AU6621 PCI-E Flash card reader controller + 6625 AU6625 PCI-E Flash card reader controller +1aec Wolfson Microelectronics +# nee Fusion-io +1aed SanDisk + 1003 ioDimm3 (v1.2) + 1005 ioDimm3 + 1014 03c3 High IOPS SSD PCIe Adapter + 103c 176f 1.28TB MLC PCIe ioDrive Duo + 103c 1770 5.2TB MLC PCIe ioDrive Octal + 103c 178b 160GB SLC PCIe ioDrive + 103c 178c 320GB MLC PCIe ioDrive + 103c 178d 320GB SLC PCIe ioDrive Duo + 103c 178e 640GB MLC PCIe ioDrive Duo + 1006 ioXtreme + 1007 ioXtreme Pro + 1008 ioXtreme-2 + 2001 ioDrive2 + 3001 ioMemory FHHL + 3002 ioMemory HHHL + 3003 ioMemory Mezzanine +1aee Caustic Graphics Inc. +# nee Qumranet, Inc. +1af4 Red Hat, Inc. + 1000 Virtio network device + 1001 Virtio block device + 1002 Virtio memory balloon + 1003 Virtio console + 1004 Virtio SCSI + 1005 Virtio RNG + 1009 Virtio filesystem +# virtio 1.0 + 1041 Virtio network device +# virtio 1.0 + 1042 Virtio block device +# virtio 1.0 + 1043 Virtio console +# virtio 1.0 + 1044 Virtio RNG +# virtio 1.0 + 1045 Virtio memory balloon +# virtio 1.0 + 1048 Virtio SCSI +# virtio 1.0 + 1049 Virtio filesystem +# virtio 1.0 + 1050 Virtio GPU +# virtio 1.0 + 1052 Virtio input + 1110 Inter-VM shared memory + 1af4 1100 QEMU Virtual Machine +1af5 Netezza Corp. +1afa J & W Electronics Co., Ltd. +1b03 Magnum Semiconductor, Inc, + 6100 DXT/DXTPro Multiformat Broadcast HD/SD Encoder/Decoder/Transcoder + 7000 D7 Multiformat Broadcast HD/SD Encoder/Decoder/Transcoder +1b08 MSC Technologies GmbH +1b0a Pegatron +1b13 Jaton Corp +1b1a K&F Computing Research Co. + 0e70 GRAPE +1b21 ASMedia Technology Inc. + 0611 ASM1061 SATA IDE Controller + 0612 ASM1062 Serial ATA Controller + 1849 0612 Motherboard + 1042 ASM1042 SuperSpeed USB Host Controller + 1043 8488 P8B WS Motherboard + 1849 1042 Motherboard + 1080 ASM1083/1085 PCIe to PCI Bridge + 1849 1080 Motherboard + 1142 ASM1042A USB 3.0 Host Controller + 1184 ASM1184e PCIe Switch Port + 1849 1184 ASM1184e PCIe Switch + 1242 ASM1142 USB 3.1 Host Controller + 1343 ASM1143 USB 3.1 Host Controller + 2142 ASM2142 USB 3.1 Host Controller +1b26 Netcope Technologies, a.s. + c132 COMBO-LXT155 + c1c0 NFB-100G1-e0 + c1c1 NFB-100G1-e1 + c250 NFB-200G2-master + c251 NFB-200G2-slave + c2c0 NFB-100G2-e0 + c2c1 NFB-100G2-e1 + cb20 COMBO-20G + cb40 COMBO-40G + cb80 NFB-40G2 +1b2c Opal-RT Technologies Inc. +1b36 Red Hat, Inc. + 0001 QEMU PCI-PCI bridge + 0002 QEMU PCI 16550A Adapter + 1af4 1100 QEMU Virtual Machine + 0003 QEMU PCI Dual-port 16550A Adapter + 1af4 1100 QEMU Virtual Machine + 0004 QEMU PCI Quad-port 16550A Adapter + 1af4 1100 QEMU Virtual Machine + 0005 QEMU PCI Test Device + 1af4 1100 QEMU Virtual Machine + 0006 PCI Rocker Ethernet switch device + 0007 PCI SD Card Host Controller Interface + 0008 QEMU PCIe Host bridge + 0009 QEMU PCI Expander bridge + 000a PCI-PCI bridge (multiseat) + 000b QEMU PCIe Expander bridge + 000c QEMU PCIe Root port + 000d QEMU XHCI Host Controller + 0100 QXL paravirtual graphic card + 1af4 1100 QEMU Virtual Machine +1b37 Signal Processing Devices Sweden AB + 0001 ADQ214 + 0003 ADQ114 + 0005 ADQ112 + 000e ADQ108 + 000f ADQDSP + 0014 ADQ412 + 0015 ADQ212 + 001b SDR14 + 001c ADQ1600 + 001e ADQ208 + 001f DSU + 0020 ADQ14 + 0023 ADQ7 + 0026 ADQ8 + 2014 TX320 + 2019 S6000 +# now owned by HGST (a Western Digital subsidiary) +1b39 sTec, Inc. + 0001 S1120 PCIe Accelerator SSD +1b3a Westar Display Technologies + 7589 HRED J2000 - JPEG 2000 Video Codec Device +1b3e Teradata Corp. + 1fa8 BYNET BIC2SE/X + 1b3e 00a3 BYNET BIC2SX + 1b3e 00c3 BYNET BIC2SE +1b40 Schooner Information Technology, Inc. +# also used by some PROXIM (14b7) devices erroneously +1b47 Numascale AS + 0601 NumaChip N601 + 0602 NumaChip N602 +1b4b Marvell Technology Group Ltd. + 0640 88SE9128 SATA III 6Gb/s RAID Controller + 9120 88SE9120 SATA 6Gb/s Controller + 9123 88SE9123 PCIe SATA 6.0 Gb/s controller + dc93 600e DC-6xxe series SATA 6G controller + 9125 88SE9125 PCIe SATA 6.0 Gb/s controller + 9128 88SE9128 PCIe SATA 6 Gb/s RAID controller + 9130 88SE9128 PCIe SATA 6 Gb/s RAID controller with HyperDuo + 1043 8438 P8P67 Deluxe Motherboard + 9172 88SE9172 SATA 6Gb/s Controller + 9178 88SE9170 PCIe SATA 6Gb/s Controller + 917a 88SE9172 SATA III 6Gb/s RAID Controller + 9183 88SS9183 PCIe SSD Controller + 9192 88SE9172 SATA III 6Gb/s RAID Controller + 91a0 88SE912x SATA 6Gb/s Controller [IDE mode] + 91a4 88SE912x IDE Controller + 9220 88SE9220 PCIe 2.0 x2 2-port SATA 6 Gb/s RAID Controller + 9230 88SE9230 PCIe SATA 6Gb/s Controller + 1028 1fd6 BOSS-S1 Adapter + 1028 1fdf BOSS-S1 Modular + 1028 1fe2 BOSS-S1 Adapter + 1028 2010 BOSS-S2 Adapter + 1d49 0300 ThinkSystem M.2 with Mirroring Enablement Kit + 9235 88SE9235 PCIe 2.0 x2 4-port SATA 6 Gb/s Controller + 9445 88SE9445 PCIe 2.0 x4 4-Port SAS/SATA 6 Gbps RAID Controller + 9480 88SE9480 SAS/SATA 6Gb/s RAID controller + 9485 88SE9485 SAS/SATA 6Gb/s controller +1b55 NetUP Inc. + 18f6 Dual DVB Universal CI card + 18f7 Dual DVB Universal CI card rev 1.4 + 2a2c Dual DVB-S2-CI card + e2e4 Dual DVB-T/C-CI RF card +# 2xHDMI and 2xHD-SDI inputs + e5f4 MPEG2 and H264 Encoder-Transcoder + f1c4 Dual ASI-RX/TX-CI card +1b66 DELTACAST + 0007 DELTA-3G-elp-d +1b6f Etron Technology, Inc. + 7023 EJ168 USB 3.0 Host Controller + 7052 EJ188/EJ198 USB 3.0 Host Controller + 1849 7052 QC5000-ITX/PH +1b73 Fresco Logic + 1000 FL1000G USB 3.0 Host Controller + 1d5c 1000 Anker USB 3.0 Express Card + 1009 FL1009 USB 3.0 Host Controller + 1100 FL1100 USB 3.0 Host Controller + 16b8 6e31 Allegro Pro USB 3.0 PCIe +1b74 OpenVox Communication Co. Ltd. + 0115 D115P/D115E Single-port E1/T1 card + d130 D130P/D130E Single-port E1/T1 card (3rd GEN) + d210 D210P/D210E Dual-port E1/T1 card(2nd generation) + d230 D230 Dual-port E1/T1 card (2nd generation) + d410 D410/430 Quad-port E1/T1 card + d430 D410/430 Quad-port E1/T1 card +1b79 Absolute Analysis +1b85 OCZ Technology Group, Inc. + 1041 RevoDrive 3 X2 PCI-Express SSD 240 GB (Marvell Controller) + 6018 RD400/400A SSD + 8788 RevoDrive Hybrid +1b94 Signatec / Dynamic Signals Corp + e400 PX14400 Dual Xilinx Virtex5 based Digitizer +1b96 Western Digital +1b9a XAVi Technologies Corp. +1baa QNAP Systems, Inc. +1bad ReFLEX CES + c001 XpressGXA10-LP1150 + c002 XpressGXA10-LP1151 +1bb0 SimpliVity Corporation + 0002 OmniCube Accelerator OA-3000 + 0010 OmniCube Accelerator OA-3000-2 +1bb1 Seagate Technology PLC + 005d Nytro PCIe Flash Storage + 1bb1 6501 Nytro XP6500-8A1536 1.5TB +# 2TB Nytro PCIe controller + 1bb1 6502 Nytro XP6500-8A2048 +# 4TB Nytro PCIe controller + 1bb1 6503 Nytro XP6500-8A4096 +# 2GB DRAM variant of Nytro card + 1bb1 6511 Nytro XH6550-2GB DRAM +# 8GB variant of Nytro PCIe controller + 1bb1 6512 Nytro XH6550-8GB DRAM +# 1.5 TB Nytro PCIe controller + 1bb1 6521 Nytro XP6500-8A1536 1.5TB +# 2TB Nytro PCIe controller + 1bb1 6522 Nytro XP6500-8A2048 +# 4TB Nytro PCIe controller + 1bb1 6523 Nytro XP6500-8A4096 + 0100 Nytro Flash Storage + 1bb1 0101 Nytro XF1440 + 1bb1 0103 Nytro 5000 + 1bb1 0105 Nytro 5020 + 1bb1 0106 Nytro 5020 TCG +# Larkspur 2.5" + 1bb1 0107 Nytro 5320 +# Larkspur 2.5" TCG + 1bb1 0108 Nytro 5320 TCG + 1bb1 0121 Nytro XM1440 + 1bb1 0123 Nytro 5000 +# Kiowa M.2 + 1bb1 0125 Nytro 5020 +# Kiowa M.2 TCG + 1bb1 0126 Nytro 5020 +# Larkspur M.2 22110mm + 1bb1 0127 Nytro 5320 M.2 +# Larkspur M.2 22110mm TCG + 1bb1 0128 Nytro 5320 M.2 TCG +# Larkspur M.2 2280mm + 1bb1 0131 Nytro 5320 M.2 +# Larkspur M.2 2280mm TCG + 1bb1 0132 Nytro 5320 M.2 TCG +# Larkspur E1.S + 1bb1 0141 Nytro 5320 E1.S +# Larkspur E1.S TCG + 1bb1 0142 Nytro 5320 E1.S TCG +# Kersey 2.5" + 1bb1 0151 Nytro 5520 +# Kersey 2.5" TCG + 1bb1 0152 Nytro 5520 TCG + 1bb1 01a1 Nytro XP7102 +1bb3 Bluecherry + 4304 BC-04120A MPEG4 4 port video encoder / decoder + 4309 BC-08240A MPEG4 4 port video encoder / decoder + 4310 BC-16480A MPEG4 16 port video encoder / decoder + 4e04 BC-04120A 4 port MPEG4 video encoder / decoder + 4e09 BC-08240A 8 port MPEG4 video encoder / decoder + 4e10 BC-16480A 16 port MPEG4 video encoder / decoder + 5304 BC-H04120A 4 port H.264 video and audio encoder / decoder + 5308 BC-H08240A 8 port H.264 video and audio encoder / decoder + 5310 BC-H16480A 16 port H.264 video and audio encoder / decoder +1bb5 Quantenna Communications, Inc. +1bbf Maxeler Technologies Ltd. + 0003 MAX3 + 0004 MAX4 +1bcf NEC Corporation + 001c Vector Engine 1.0 +1bd0 Astronics Corporation + 1001 Mx5 PMC/XMC Databus Interface Card + 1002 PM1553-5 (PC/104+ MIL-STD-1553 Interface Card) + 1004 AB3000 Series Rugged Computer + 1005 PE1000 (Multi-Protocol PCIe/104 Interface Card) + 1101 OmniBus II PCIe Multi-Protocol Interface Card + 1102 OmniBusBox II Multi-Protocol Interface Core + 1103 OmniBus II cPCIe/PXIe Multi-Protocol Interface Card +1bd4 Inspur Electronic Information Industry Co., Ltd. +1bee IXXAT Automation GmbH + 0003 CAN-IB200/PCIe +1bef Lantiq + 0011 MIPS SoC PCI Express Port +1bf4 VTI Instruments Corporation + 0001 SentinelEX + 7011 RX0xxx +1bfd EeeTOP +1c09 CSP, Inc. + 4254 10G-PCIE3-8D-2S + 4255 10G-PCIE3-8D-Q + 4256 10G-PCIE3-8D-2S + 4258 10G-PCIE3-8E-2S Network Adapter + 4260 10G-PCIE3-8E-4S Network Adapter + 4261 10G-PCIE3-8E-4S Network Adapter + 4262 10G-PCIE3-8E-4S Network Adapter + 4263 10G-PCIE3-8E-4S Network Adapter + 4264 10G-PCIE3-8E-2S Network Adapter + 4265 10G-PCIE3-8E-2S Network Adapter + 5000 25G-PCIE3-8A-2S Security Intelligent Adapter + 5001 25G-PCIE3-8B-2S Security Intelligent Adapter +1c1c Symphony + 0001 82C101 +1c1f SoftLab-NSK +1c28 Lite-On IT Corp. / Plextor + 0122 M6e PCI Express SSD [Marvell 88SS9183] +# previously Fiberblaze +1c2c Silicom Denmark + 000a Capture + 000f SmartNIC + 00a0 FBC4G Capture 4x1Gb [Herculaneum] + 00a1 FBC4XG Capture 4x10Gb [Ancona] + 00a2 FBC8XG Capture 8x10Gb [Livorno] + 00a3 FBC2XG Capture 2x10Gb [Genoa] + 00a4 FBC4XGG3 Capture 4x10Gb [Livigno] + 00a5 FBC2XLG Capture 2x40Gb [Livorno] + 00a6 FBC1CG Capture 1x100Gb + 00a9 FBC2XGHH Capture 2x10Gb [Latina] + 00ad FBC2CGG3HL Capture 2x100Gb [Padua] + 00af Capture slave device + 00e0 PacketMover 2x100Gb [Savona] + 00e1 PacketMover 2x100Gb [Tivoli] + 00e3 PacketMover 2x10Gb [Tivoli] + 00e5 PacketMover 2x10Gb [Corfu] + a000 FBC2CGG3 Capture 2x40Gb [Mango_02] + a001 FBC2CGG3 Capture 2x100Gb [Mango_02] + a003 FBC2CGG3 Capture 16x10Gb [Mango] + a007 FBC2CGG3 Capture 2x40Gb [Mango] + a008 FBC2CGG3 Capture 2x25Gb [Mango] + a009 FBC2CGG3 Capture 16x10Gb [Mango] + a00a FBC2CGG3 Capture 8x10Gb [Mango] + a00e FB2CG Capture 2x100Gb [Savona] + a00f FB2CG Capture 2x40Gb [Savona] + a011 FB2CG Capture 2x25Gb [Savona] + a012 FB2CG Capture 8x10Gb [Savona] +# Used on V120 VME Crate Controller +1c32 Highland Technology, Inc. +1c33 Daktronics, Inc +1c36 Annapurna Labs Ltd. + 0001 Gigabit Ethernet Adapter + 0002 SFP+ 10G Ethernet Adapter +1c3b Accensus, LLC + 0200 Telas2 +# http://www.accensusllc.com/accensustelas2.html + 0300 Telas 2.V +1c44 Enmotus Inc + 8000 8000 Storage IO Controller +# A Western Digital Subsidiary +1c58 HGST, Inc. + 0003 Ultrastar SN100 Series NVMe SSD + 1014 04f5 PCIe3 1.6TB NVMe Flash Adapter + 1014 04f6 PCIe3 3.2TB NVMe Flash Adapter + 1c58 0003 Ultrastar SN100/SN150 NVMe SSD + 0023 Ultrastar SN200 Series NVMe SSD + 1c58 8823 Ultrastar Memory (ME200) +1c5c SK hynix + 1283 PC300 NVMe Solid State Drive 256GB + 1284 PC300 NVMe Solid State Drive 512GB + 1285 PC300 NVMe Solid State Drive 1TB + 1504 SC300 512GB M.2 2280 SATA Solid State Drive +1c5f Beijing Memblaze Technology Co. Ltd. + 000d PBlaze5 520/526 AIC + 003d PBlaze5 920/926 AIC + 010d PBlaze5 520/526 U.2 + 013d PBlaze5 920/926 U.2 + 0540 PBlaze4 NVMe SSD + 0550 PBlaze5 700/900 + 0555 PBlaze5 510/516 + 0557 PBlaze5 910/916 +# http://www.nicevt.ru/ (in Russian) +1c63 Science and Research Centre of Computer Technology (JSC "NICEVT") +# http://www.radiotec.ru/catalog.php?cat=jr8&art=14109 + 0008 K1927BB1Ya [EC8430] Angara Interconnection Network Adapter +1c7e TTTech Computertechnik AG + 0200 zFAS Debug Port +1c7f Elektrobit Austria GmbH + 5100 EB5100 +1c8a TSF5 Corporation + 0001 Hunter PCI Express +1c8c Mobiveil, Inc. +1cb0 Shannon Systems + d000 Venice NVMe SSD + 1cb0 2f10 Venice-E Series U.2 SSD + 1cb0 2f11 Venice Series U.2 SSD + 1cb0 2f12 Venice-X Series U.2 SSD + 1cb0 af10 Venice-E Series AIC SSD + 1cb0 af11 Venice Series AIC SSD + 1cb0 af12 Venice-X Series AIC SSD +1cb1 Collion UG & Co.KG +1cb5 Focusrite Audio Engineering Ltd + 0002 Clarett +1cb8 Dawning Information Industry Co., Ltd. +1cc1 ADATA Technology Co., Ltd. + 8201 XPG SX8200 Pro PCIe Gen3x4 M.2 2280 Solid State Drive +1cc4 Union Memory (Shenzhen) + 17ab NVMe 256G SSD device +1cc5 Embedded Intelligence, Inc. + 0100 CAN-PCIe-02 +1cc7 Radian Memory Systems Inc. + 0200 RMS-200 + 0250 RMS-250 +1ccf Zoom Corporation + 0001 TAC-2 Thunderbolt Audio Converter +1cd2 SesKion GmbH + 0301 Simulyzer-RT CompactPCI Serial DIO-1 card + 0302 Simulyzer-RT CompactPCI Serial PSI5-ECU-1 card + 0303 Simulyzer-RT CompactPCI Serial PSI5-SIM-1 card + 0304 Simulyzer-RT CompactPCI Serial PWR-ANA-1 card + 0305 Simulyzer-RT CompactPCI Serial CAN-1 card +# supports 8x CAN (-FD) interfaces + 0306 Simulyzer-RT CompactPCI Serial CAN-2 card (CAN-FD) +1cd7 Nanjing Magewell Electronics Co., Ltd. + 0010 Pro Capture Endpoint + 0014 PRO CAPTURE AIO 4K PLUS + 0017 PRO CAPTURE AIO 4K +1cdd secunet Security Networks AG +1ce4 Exablaze + 0001 ExaNIC X4 + 0002 ExaNIC X2 + 0003 ExaNIC X10 + 0004 ExaNIC X10-GM + 0005 ExaNIC X40 + 0006 ExaNIC X10-HPT + 0007 ExaNIC X40 + 0008 ExaNIC V5P + 0009 ExaNIC X25 + 000a ExaNIC X100 + 000b ExaNIC V9P + 0100 ExaDISK FX1 +1cf0 Akitio +1cf7 Subspace Dynamics +1d00 Pure Storage +1d05 Tongfang Hongkong Limited +1d0f Amazon.com, Inc. + cd01 NVMe SSD Controller + ec20 Elastic Network Adapter (ENA) + efa0 Elastic Fabric Adapter (EFA) +1d17 Zhaoxin + 070f ZX-100 PCI Express Root Port + 0710 ZX-100/ZX-200 PCI Express Root Port + 0711 ZX-100/ZX-200 PCI Express Root Port + 0712 ZX-100/ZX-200 PCI Express Root Port + 0713 ZX-100/ZX-200 PCI Express Root Port + 0714 ZX-100/ZX-200 PCI Express Root Port + 0715 ZX-100/ZX-200 PCI Express Root Port + 0716 ZX-D PCI Express Root Port + 0717 ZX-D/ZX-E PCI Express Root Port + 0718 ZX-D/ZX-E PCI Express Root Port + 0719 ZX-D/ZX-E PCI Express Root Port + 071a ZX-D/ZX-E PCI Express Root Port + 071b ZX-D/ZX-E PCI Express Root Port + 071c ZX-D/ZX-E PCI Express Root Port + 071d ZX-D/ZX-E PCI Express Root Port + 071e ZX-D/ZX-E PCI Express Root Port + 071f ZX-200 Upstream Port of PCI Express Switch + 0720 ZX-200 PCIE RC6 controller + 0721 ZX-200 Downstream Port of PCI Express Switch + 0722 ZX-200 PCIE P2C bridge + 1000 ZX-D Standard Host Bridge + 1001 ZX-D/ZX-E Miscellaneous Bus + 1003 ZX-E Standard Host Bridge + 3001 ZX-100 Standard Host Bridge + 300a ZX-100 Miscellaneous Bus + 3038 ZX-100/ZX-200/ZX-E Standard Universal PCI to USB Host Controller + 3104 ZX-100/ZX-200/ZX-E Standard Enhanced PCI to USB Host Controller + 31b0 ZX-100/ZX-D Standard Host Bridge + 31b1 ZX-100/ZX-D Standard Host Bridge + 31b2 ZX-100/ZX-D DRAM Controller + 31b3 ZX-100/ZX-D Power Management Controller + 31b4 ZX-100/ZX-D I/O APIC + 31b5 ZX-100/ZX-D Scratch Device + 31b7 ZX-100/ZX-D/ZX-E Standard Host Bridge + 31b8 ZX-100/ZX-D PCI to PCI Bridge + 3288 ZX-100/ZX-D/ZX-E High Definition Audio Controller + 345b ZX-100/ZX-D/ZX-E Miscellaneous Bus + 3a02 ZX-100 C-320 GPU + 3a03 ZX-D C-860 GPU + 3a04 ZX-E C-960 GPU + 9002 ZX-100/ZX-200 EIDE Controller + 9003 ZX-100/ZX-E EIDE Controller + 9045 ZX-100/ZX-D/ZX-E RAID Accelerator 0 + 9046 ZX-D/ZX-E RAID Accelerator 1 + 9083 ZX-100/ZX-200/ZX-E StorX AHCI Controller + 9084 ZX-100 StorX AHCI Controller + 9100 ZX-200 Cross bus + 9101 ZX-200 Traffic Controller + 9141 ZX-100 High Definition Audio Controller + 9142 ZX-D High Definition Audio Controller + 9144 ZX-E High Definition Audio Controller + 9180 ZX-200 Networking Gigabit Ethernet Adapter + 9202 ZX-100 USB eXtensible Host Controller + 9203 ZX-200 USB eXtensible Host Controller + 9204 ZX-E USB eXtensible Host Controller + 9286 ZX-D eMMC Host Controller + 9300 ZX-D/ZX-E eSPI Host Controller + 95d0 ZX-100 Universal SD Host Controller + f410 ZX-100/ZX-D/ZX-E PCI Com Port +1d18 RME + 0001 Fireface UFX+ +1d1d CNEX Labs + 1f1f QEMU NVM Express LightNVM Controller + 2807 8800 series NVMe SSD +# CEM Solutions Pvt. Ltd. +1d21 Allo +1d22 Baidu Technology + 1380 Cloud Storage Device +1d26 Kalray Inc. + 0040 Turbocard2 Accelerator + 0080 Open Network Interface Card 80G + 00c0 Turbocard3 Accelerator + 0140 Open Network Interface Card 40G + e004 AB01/EMB01 Development Board +1d37 NovaSparks + 0013 PM3 + 0014 PM4 + 0015 PM4edge + 0016 PM4edge User Device +1d40 Techman Electronics (Changshu) Co., Ltd. +1d44 DPT + a400 PM2x24/PM3224 +1d49 Lenovo +1d4c Diamanti, Inc. +1d5c Fantasia Trading LLC +1d61 Technobox, Inc. +1d62 Nebbiolo Technologies +1d65 Imagine Communications Corp. + 04de Taurus/McKinley +1d6a Aquantia Corp. + 0001 AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + 07b1 AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + 08b1 AQC108 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + 11b1 AQC111 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + 12b1 AQC112 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + 87b1 AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + d107 AQC107 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] + 1043 8741 XG-C100C + d108 AQC108 NBase-T/IEEE 802.3bz Ethernet Controller [AQtion] +1d6c Atomic Rules LLC + 1001 A5PL-E1 + 1002 A5PL-E7 + 1003 S5PEDS-AB + 1004 KC705-K325 + 1005 ZC706-Z045 + 1006 KCU105-KU040 + 1007 XUSP3S-VU095 [Jasper] + 1008 XUSPL4-VU065 [Mustang UltraScale] + 1009 XUSPL4-VU3P [Mustang UltraScale+] + 100a A10PL4-A10GX115 + 100b K35-2SFP + 100c K35-4SFP + 100d AR-ARKA-FX0 [Arkville 32B DPDK Data Mover] + 1d6c 2001 DPDK-Aware Virtual Function [Arkville VF] + 100e AR-ARKA-FX1 [Arkville 64B DPDK Data Mover] + 1d6c 2001 DPDK-Aware Virtual Function [Arkville VF] + 100f AR-ARKA-FX1 [Arkville 64B DPDK Data Mover for Versal] + 1010 AR-ARKA-FX1 [Arkville 64B DPDK Data Mover for Agilex] + 1011 AR-MAN-U50 [Manitou Class Accelerator for U50] + 1012 AR-MAN-U200 [Manitou Class Accelerator for U200] + 1013 AR-MAN-U250 [Manitou Class Accelerator for U250] + 1014 AR-MAN-U280 [Manitou Class Accelerator for U280] + 4200 A5PL-E1-10GETI [10 GbE Ethernet Traffic Instrument] +1d72 Xiaomi +1d78 DERA +1d7c Aerotech, Inc. +1d82 NETINT Technologies Inc. + 0101 Codensity D400 SSD + 0102 Codensity D408 PCIe Gen4 NVMe SSD + 0202 Codensity T408 Video Encoding-Decoding Accelerator +1d87 Fuzhou Rockchip Electronics Co., Ltd + 0100 RK3399 PCI Express Root Port + 1808 RK1808 Neural Network Processor Card +1d8f Enyx +1d93 YADRO (KNS Group) +1d94 Chengdu Haiguang IC Design Co., Ltd. + 1450 Root Complex + 1451 I/O Memory Management Unit + 1452 PCIe Dummy Host Bridge + 1453 PCIE GPP Bridge + 1454 Internal PCIe GPP Bridge 0 to Bus B + 1455 PCIe Dummy Function + 1456 PSPCCP Command DMA Processor + 1458 10 Gb Ethernet Controller Port 0/Port1 + 1459 10 Gb Ethernet Controller Port 2/Port3 + 145a PCIe Dummy Function + 145b PCIE Non-Transparent Bridge + 145c USB3 XHCI + 145d Switch upstream in PCIe + 145e Switch downstream in PCIe + 145f USB 3.0 Host controller + 1460 Data Fabric: Device 18h; Function 0 + 1461 Data Fabric: Device 18h; Function 1 + 1462 Data Fabric: Device 18h; Function 2 + 1463 Data Fabric: Device 18h; Function 3 + 1464 Data Fabric: Device 18h; Function 4 + 1465 Data Fabric: Device 18h; Function 5 + 1466 Data Fabric: Device 18h; Function 6 + 1467 Data Fabric: Device 18h; Function 7 + 1468 NTBCCP + 7901 FCH SATA Controller [AHCI mode] + 7904 FCH SATA Controller [AHCI mode] + 7906 FCH SD Flash Controller + 790b FCH SMBus Controller + 790e FCH LPC Bridge +1d95 Graphcore Ltd + 0001 Colossus GC2 [C2] + 0002 Colossus GC1 [S1] +1d9b Facebook, Inc. + 0010 Networking DOM Engine + 0011 IO Bridge +1da1 Teko Telecom S.r.l. +1da2 Sapphire Technology Limited +1da3 Habana Labs Ltd. + 0001 HL-1000 AI Inference Accelerator [Goya] +# PCIe accelerator card for Deep Learning training tasks + 1000 HL-2000 AI Training Accelerator [Gaudi] +1dbb NGD Systems, Inc. +1dbf Guizhou Huaxintong Semiconductor Technology Co., Ltd + 0401 StarDragon4800 PCI Express Root Port +1dc5 FADU Inc. +1dd8 Pensando Systems Inc + 1000 DSC Capri Upstream Port + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB + 1001 DSC Virtual Downstream Port + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB + 1002 DSC Ethernet Controller + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB + 1003 DSC Ethernet Controller VF + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB + 1004 DSC Management Controller + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB + 1007 DSC Storage Accelerator + 1dd8 4000 Naples 100Gb 2-port QSFP28 x16 8GB + 1dd8 4001 Naples 100Gb 2-port QSFP28 x16 4GB + 1dd8 4002 Naples 25Gb 2-port SFP28 x8 4GB +1de0 Groq + 0000 Q100 Tensor Streaming Processor +1de1 Tekram Technology Co.,Ltd. + 0391 TRM-S1040 [DC-315 / DC-395 series] + 2020 DC-390 + 690c 690c + dc29 DC290 +1de5 Eideticom, Inc + 1000 IO Memory Controller + 2000 NoLoad Hardware Development Kit +1def Ampere Computing, LLC + e005 eMAG PCI Express Root Port 0 + e006 eMAG PCI Express Root Port 1 + e007 eMAG PCI Express Root Port 2 + e008 eMAG PCI Express Root Port 3 + e009 eMAG PCI Express Root Port 4 + e00a eMAG PCI Express Root Port 5 + e00b eMAG PCI Express Root Port 6 + e00c eMAG PCI Express Root Port 7 +1df3 Ethernity Networks + 0201 ACE-NIC40 Programmable Network Accelerator + 1df3 0001 ENA1040 + 1df3 0002 ENA1044 + 1df3 0003 ENA1044S + 0202 ACE-NIC50 Programmable Network Accelerator + 1df3 0001 ENA2050F + 1df3 0002 ENA2050FS + 0203 ACE-NIC100 Programmable Network Accelerator + 1df3 0000 Maintenance Mode + 1df3 0001 ENA2080F + 1df3 0002 ENA2080FS + 1df3 0003 ENA2100F + 1df3 0004 ENA2040F + 0204 ACE-NIC-NID Programmable Network Accelerator + 1df3 0001 ENA1020Z + 1df3 0002 ENA1020ZS +1df7 opencpi.org + 0001 ml605 + 0002 alst4 + 0003 alst4x +1dfc JSC NT-COM + 1181 TDM 8 Port E1/T1/J1 Adapter +1e17 Arnold & Richter Cine Technik GmbH & Co. Betriebs KG +1e24 Squirrels Research Labs + 0101 Acorn CLE-101 + 0215 Acorn CLE-215 + 021f Acorn CLE-215+ + 1525 Xilinx BCU-1525 +# VU33P FPGA Accelerator + 1533 ForestKitten 33 +# JungleCat VU33P Module + 1633 JCM33 +# JungleCat VU35P Module + 1635 JCM35 +1e26 Fujitsu Client Computing Limited +# nee Thinci, Inc +1e38 Blaize, Inc +1e3d Burlywood, Inc +1e49 Yangtze Memory Technologies Co.,Ltd +1e4c GSI Technology +# Associative Processing Unit chip + 0010 Gemini [ Lida ] + 1e4c 0120 SE120 +1e57 Beijing Panyi Technology Co., Ltd + 0100 The device has already been deleted. + 0000 0100 PY8800 64GB Accelerator +1e6b Axiado Corp. +1e89 ID Quantique SA + 0002 Quantis-PCIe-40M + 0003 Quantis-PCIe-240M +# nee Tumsan Oy +1fc0 Ascom (Finland) Oy + 0300 E2200 Dual E1/Rawpipe Card + 0301 C5400 SHDSL/E1 Card +# nee PathScale, Inc +1fc1 QLogic, Corp. + 000d IBA6110 InfiniBand HCA + 0010 IBA6120 InfiniBand HCA +1fc9 Tehuti Networks Ltd. + 3009 10-Giga TOE SmartNIC + 3010 10-Giga TOE SmartNIC + 0000 3002 10-Giga TOE Single Port XFP SmartNIC + 0000 3004 10-Giga TOE Single Port SFP+ SmartNIC + 0000 3008 10-Giga TOE Single Port CX4 SmartNIC + 3014 10-Giga TOE SmartNIC 2-Port + 0000 3003 10-Giga TOE Dual Port XFP Low Profile SmartNIC + 0000 3005 10-Giga TOE Dual Port SFP+ Low Profile SmartNIC + 0000 3014 10-Giga TOE Dual Port CX4 Low Profile SmartNIC + 3110 10-Giga TOE Single Port SmartNIC + 0000 3004 10-Giga TOE Single Port SFP+ SmartNIC + 3114 10-Giga TOE Dual Port Low Profile SmartNIC + 0000 3005 10-Giga TOE Dual Port SFP+ Low Profile SmartNIC + 0000 3011 10-Giga TOE Dual Port SFP+/CX4 Low Profile SmartNIC + 0000 3012 10-Giga TOE Dual Port CX4/SFP+ Low Profile SmartNIC + 0000 3014 10-Giga TOE Dual Port CX4 Low Profile SmartNIC + 3310 10-Giga TOE SFP+ Single Port SmartNIC + 0000 3004 10-Giga TOE Single Port SFP+ SmartNIC + 3314 10-Giga TOE Dual Port Low Profile SmartNIC + 0000 3005 10-Giga TOE Dual Port SFP+ Low Profile SmartNIC + 0000 3011 10-Giga TOE Dual Port SFP+/CX4 Low Profile SmartNIC + 0000 3012 10-Giga TOE Dual Port CX4/SFP+ Low Profile SmartNIC + 0000 3014 10-Giga TOE Dual Port CX4 Low Profile SmartNIC + 4010 TN4010 Clean SROM + 4020 TN9030 10GbE CX4 Ethernet Adapter + 180c 2040 Mustang-200 10GbE Ethernet Adapter + 4022 TN9310 10GbE SFP+ Ethernet Adapter + 1043 8709 XG-C100F 10GbE SFP+ Ethernet Adapter + 1186 4d00 DXE-810S 10GbE SFP+ Ethernet Adapter + 1432 8103 10 Gigabit Ethernet SFP+ PCI Express Adapter + 1fc9 3015 Ethernet Adapter + 4024 TN9210 10GBase-T Ethernet Adapter + 4025 TN9510 10GBase-T/NBASE-T Ethernet Adapter + 105a 7203 SANLink3 NBase-T1 + 1186 2900 DXE-810T 10GBase-T Ethernet Adapter + 1432 8102 10 Gigabit Ethernet PCI Express Adapter + 1fc9 3015 Ethernet Adapter + 4026 TN9610 10GbE SFP+ Ethernet Adapter + 4c52 1000 LREC6860AF 10 Gigabit Ethernet Adapter + 4027 TN9710P 10GBase-T/NBASE-T Ethernet Adapter + 1154 0368 LGY-PCIE-MG + 1432 8104 10 Gigabit Ethernet PCI Express Adapter + 1546 4027 GE10-PCIE4XG202P 10Gbase-T/NBASE-T Ethernet Adapter + 1baa 3310 PCIe Expansion Card + 1fc9 3015 Ethernet Adapter + 4c52 1001 LREC6860BT 10 Gigabit Ethernet Adapter + 4527 TN9710Q 5GBase-T/NBASE-T Ethernet Adapter +1fcc StreamLabs + f416 MS416 + fb01 MH4LM +1fce Cognio Inc. + 0001 Spectrum Analyzer PC Card (SAgE) +1fd4 SUNIX Co., Ltd. + 0001 Matrix multiport serial adapter + 1999 Multiport serial controller +2000 Smart Link Ltd. + 2800 SmartPCI2800 V.92 PCI Soft DFT +2001 Temporal Research Ltd +2003 Smart Link Ltd. + 8800 LM-I56N +2004 Smart Link Ltd. +2048 Beijing SpaceControl Technology Co.Ltd +20f4 TRENDnet +2116 ZyDAS Technology Corp. +21c3 21st Century Computer Corp. +22b8 Flex-Logix Technologies + 22a0 Flex Logix InferX X1 Inference Accelerator +22db Missing Link Electronics, Inc. +2304 Colorgraphic Communications Corp. +2348 Racore + 2010 8142 100VG/AnyLAN +2646 Kingston Technology Company, Inc. +270b Xantel Corporation +270f Chaintech Computer Co. Ltd +2711 AVID Technology Inc. +2955 Connectix Virtual PC + 6e61 OHCI USB 1.1 controller +2a15 3D Vision(???) +2bd8 ROPEX Industrie-Elektronik GmbH +3000 Hansol Electronics Inc. +3112 Satelco Ingenieria S.A. +3130 AUDIOTRAK +3142 Post Impression Systems. +31ab Zonet + 1faa ZEW1602 802.11b/g Wireless Adapter +3388 Hint Corp + 0013 HiNT HC4 PCI to ISDN bridge, Multimedia audio controller + 0014 HiNT HC4 PCI to ISDN bridge, Network controller + 0020 HB6 Universal PCI-PCI bridge (transparent mode) + 0021 HB6 Universal PCI-PCI bridge (non-transparent mode) + 1775 c200 C2K CompactPCI interface bridge + 1775 ce90 CE9 + 4c53 1050 CT7 mainboard + 4c53 1080 CT8 mainboard + 4c53 1090 Cx9 mainboard + 4c53 10a0 CA3/CR3 mainboard + 4c53 3010 PPCI mezzanine (32-bit PMC) + 4c53 3011 PPCI mezzanine (64-bit PMC) + 4c53 4000 PMCCARR1 carrier board + 0022 HiNT HB4 PCI-PCI Bridge (PCI6150) + 0026 HB2 PCI-PCI Bridge + 1014 AudioTrak Maya + 1018 Audiotrak INCA88 + 1019 Miditrak 2120 + 101a E.Band [AudioTrak Inca88] + 101b E.Band [AudioTrak Inca88] + 8011 VXPro II Chipset + 3388 8011 VXPro II Chipset CPU to PCI Bridge + 8012 VXPro II Chipset + 3388 8012 VXPro II Chipset PCI to ISA Bridge + 8013 VXPro II IDE + 3388 8013 VXPro II Chipset EIDE Controller + a103 Blackmagic Design DeckLink HD Pro +3411 Quantum Designs (H.K.) Inc +3442 Bihl+Wiedemann GmbH + 1783 AS-i 3.0 cPCI Master + 1922 AS-i 3.0 PCI Master +3475 Arastra Inc. +3513 ARCOM Control Systems Ltd +37d9 ITD Firm ltd. + 1138 SCHD-PH-8 Phase detector +# 12-ch Relay Actuator Card + 1140 VR-12-PCI +# multiport serial board + 1141 PCI-485(422) + 1142 PCI-CAN2 +3842 eVga.com. Corp. +38ef 4Links +3d3d 3DLabs + 0001 GLINT 300SX + 0002 GLINT 500TX + 0000 0000 GLoria L + 0003 GLINT Delta + 0000 0000 GLoria XL + 0004 Permedia + 0005 Permedia + 0006 GLINT MX + 0000 0000 GLoria XL + 1048 0a42 GLoria XXL + 0007 3D Extreme + 0008 GLINT Gamma G1 + 1048 0a42 GLoria XXL + 0009 Permedia II 2D+3D + 1040 0011 AccelStar II + 1048 0a42 GLoria XXL + 13e9 1000 6221L-4U + 3d3d 0100 AccelStar II 3D Accelerator + 3d3d 0111 Permedia 3:16 + 3d3d 0114 Santa Ana + 3d3d 0116 Oxygen GVX1 + 3d3d 0119 Scirocco + 3d3d 0120 Santa Ana PCL + 3d3d 0125 Oxygen VX1 + 3d3d 0127 Permedia3 Create! + 000a GLINT R3 + 3d3d 0121 Oxygen VX1 + 000c GLINT R3 [Oxygen VX1] + 3d3d 0144 Oxygen VX1-4X AGP [Permedia 4] + 000d GLint R4 rev A + 000e GLINT Gamma G2 + 0011 GLint R4 rev B + 0012 GLint R5 rev A + 0013 GLint R5 rev B + 0020 VP10 visual processor + 0022 VP10 visual processor + 0024 VP9 visual processor + 002c Wildcat Realizm 100/200 + 0030 Wildcat Realizm 800 + 0032 Wildcat Realizm 500 + 0100 Permedia II 2D+3D + 07a1 Wildcat III 6210 + 07a2 Sun XVR-500 Graphics Accelerator + 07a3 Wildcat IV 7210 + 1004 Permedia + 3d04 Permedia + ffff Glint VGA +4005 Avance Logic Inc. + 0300 ALS300 PCI Audio Device + 0308 ALS300+ PCI Audio Device + 0309 PCI Input Controller + 1064 ALG-2064 + 2064 ALG-2064i + 2128 ALG-2364A GUI Accelerator + 2301 ALG-2301 + 2302 ALG-2302 + 2303 AVG-2302 GUI Accelerator + 2364 ALG-2364A + 2464 ALG-2464 + 2501 ALG-2564A/25128A + 4000 ALS4000 Audio Chipset + 4005 4000 ALS4000 Audio Chipset + 4710 ALC200/200P +4033 Addtron Technology Co, Inc. + 1360 RTL8139 Ethernet +4040 NetXen Incorporated + 0001 NXB-10GXSR 10-Gigabit Ethernet PCIe Adapter with SR-XFP optical interface + 103c 7047 NC510F PCIe 10-Gigabit Server Adapter + 0002 NXB-10GCX4 10-Gigabit Ethernet PCIe Adapter with CX4 copper interface + 103c 7048 NC510c PCIe 10-Gigabit Server Adapter + 0003 NXB-4GCU Quad Gigabit Ethernet PCIe Adapter with 1000-BASE-T interface + 0004 BladeCenter-H 10-Gigabit Ethernet High Speed Daughter Card + 0005 NetXen Dual Port 10GbE Multifunction Adapter for c-Class + 103c 170e NC512m Dual Port 10GbE Multifunction BL-C Adapter + 0024 XG Mgmt + 0025 XG Mgmt + 0100 NX3031 Multifunction 1/10-Gigabit Server Adapter + 103c 171b NC522m Dual Port 10GbE Multifunction BL-c Adapter + 103c 1740 NC375T PCI Express Quad Port Gigabit Server Adapter + 103c 3251 NC375i 1G w/NC524SFP 10G Module + 103c 705a NC375i Integrated Quad Port Multifunction Gigabit Server Adapter + 103c 705b NC522SFP Dual Port 10GbE Server Adapter + 152d 896b TG20 Dual Port 10GbE Server/Storage Adapter + 4040 0124 NX3031 Quad Port Gigabit Server Adapter + 4040 0126 Dual Port SFP+ 10GbE Server Adapter +4143 Digital Equipment Corp +4144 Alpha Data + 0044 ADM-XRCIIPro +4150 ONA Electroerosion + 0001 PCI32TLITE FILSTRUP1 PCI to VME Bridge Controller + 0006 PCI32TLITE UART 16550 Opencores + 0007 PCI32TLITE CAN Controller Opencores +415a Auzentech, Inc. +416c Aladdin Knowledge Systems + 0100 AladdinCARD + 0200 CPC +4254 DVBSky +4321 Tata Power Strategic Electronics Division +4348 WCH.CN + 2273 CH351 PCI Dual Serial Port Controller + 3253 CH352 PCI Dual Serial Port Controller + 3453 CH353 PCI Quad Serial Port Controller + 5053 CH352 PCI Serial and Parallel Port Controller + 7053 CH353 PCI Dual Serial and Parallel Ports Controller + 7073 CH356 PCI Quad Serial and Parallel Ports Controller + 7173 CH355 PCI Quad Serial Port Controller +434e CAST Navigation LLC +4444 Internext Compression Inc + 0016 iTVC16 (CX23416) Video Decoder + 0070 0003 WinTV PVR 250 + 0070 0009 WinTV PVR 150 + 0070 0801 WinTV PVR 150 + 0070 0807 WinTV PVR 150 + 0070 4001 WinTV PVR 250 + 0070 4009 WinTV PVR 250 + 0070 4801 WinTV PVR 250 + 0070 4803 WinTV PVR 250 + 0070 8003 WinTV PVR 150 + 0070 8801 WinTV PVR 150 + 0070 c801 WinTV PVR 150 + 0070 e807 WinTV PVR 500 (1st unit) + 0070 e817 WinTV PVR 500 (2nd unit) + 0070 ff92 WiNTV PVR-550 + 0270 0801 WinTV PVR 150 + 104d 013d ENX-26 TV Encoder + 10fc d038 GV-MVP/RX2W (1st unit) + 10fc d039 GV-MVP/RX2W (2nd unit) + 12ab fff3 MPG600 + 12ab ffff MPG600 + 1461 c00a M113 PCI Analog TV (PAL/SECAM, Philips FQ1216MK3 tuner) + 1461 c00b M113 PCI Analog TV (PAL/SECAM+FM, Philips FM1216MK3 tuner) + 1461 c00c M113 PCI Analog TV (NTSC, JAPAN version, Philips FI1286MK2 tuner) + 1461 c010 M113 PCI Analog TV (NTSC, Philips FI1236MK3 tuner) + 1461 c011 M113 PCI Analog TV (NTSC+FM, Philips FM1236MK3 tuner) + 1461 c018 M113 PCI Analog TV (NTSC, Philips FQ1236MK5 tuner) + 1461 c019 UltraTV 1500 MCE, a.k.a. M113 PCI Analog TV (NTSC+FM, Philips FQ1236MK5 tuner) + 1461 c01a M113 PCI Analog TV (PAL/SECAM, Philips FQ1216MK5 tuner) + 1461 c01b M113 PCI Analog TV (PAL/SECAM+FM, Philips FM1216MK5 tuner) + 1461 c030 M113 PCI Analog TV (NTSC-J, Partsnic tuner) + 1461 c031 M113 PCI Analog TV (NTSC-J+FM, Partsnic tuner) + 1461 c032 M113 PCI Analog TV (PAL/SECAM, Partsnic tuner) + 1461 c033 M113 PCI Analog TV (PAL/SECAM+FM, Partsnic tuner) + 1461 c034 M113 PCI Analog TV (NTSC, Partsnic tuner) + 1461 c035 M113 PCI Analog TV (NTSC+FM, Partsnic tuner) + 1461 c03f C115 PCI video capture card (no tuner) + 1461 c136 M104 mini-PCI Analog TV + 1461 c20a M755 AVerTV Video Capture (PAL/SECAM, Philips FQ1216MK3 tuner) + 1461 c218 M755 AVerTV Video Capture (NTSC, Philips FQ1236MK5 tuner) + 1461 c219 M755 AVerTV Video Capture (NTSC+FM, Philips FQ1236MK5 tuner) + 1461 c21a M755 AVerTV Video Capture (PAL/SECAM, Philips FQ1216MK5 tuner) + 1461 c21b M755 AVerTV Video Capture (PAL/SECAM+FM, Philips FM1216MK5 tuner) + 1461 c230 M755 AVerTV Video Capture (NTSC-J, Partsnic tuner) + 1461 c231 M755 AVerTV Video Capture (NTSC-J+FM, Partsnic tuner) + 1461 c232 M755 AVerTV Video Capture (PAL/SECAM, Partsnic tuner) + 1461 c233 M755 AVerTV Video Capture (PAL/SECAM+FM, Partsnic tuner) + 1461 c234 M755 AVerTV Video Capture (NTSC, Partsnic tuner) + 1461 c235 M755 AVerTV Video Capture (NTSC+FM, Partsnic tuner) + 1461 c337 E106 AVerMedia AVerTV Video Capture + 1461 c439 M116 AVerMedia AVerTV MCE 116 Plus (NTSC/PAL/SECAM+FM+REMOTE, Xceive 2028 tuner) + 1461 c5ff C755 AVerTV Video Capture card (no tuner) + 1461 c6ff C115 PCI video capture card (no tuner) + 1461 c739 M785 AVerMedia PCI Analog TV (NTSC/PAL/SECAM+FM, Xceive 2028 tuner) + 9005 0092 VideOh! AVC-2010 + 9005 0093 VideOh! AVC-2410 + 0803 iTVC15 (CX23415) Video Decoder + 0070 4000 WinTV PVR-350 + 0070 4001 WinTV PVR-250 + 0070 4800 WinTV PVR-350 (V1) + 12ab 0000 MPG160 + 1461 a3ce M179 + 1461 a3cf M179 +4468 Bridgeport machines +4594 Cogetec Informatique Inc +45fb Baldor Electric Company +4624 Budker Institute of Nuclear Physics + adc1 ADC200ME High speed ADC + de01 DL200ME High resolution delay line PCI based card + de02 DL200ME Middle resolution delay line PCI based card +# Can't find any information on this company +4651 TXIC +4680 Umax Computer Corp +4843 Hercules Computer Technology Inc +4916 RedCreek Communications Inc + 1960 RedCreek PCI adapter +4943 Growth Networks +494f ACCES I/O Products, Inc. + 0508 PCI-IDO-16A FET Output Card + 0518 PCI-IDO-32A FET Output Card + 0520 PCI-IDO-48 FET Output Card + 0521 PCI-IDO-48A FET Output Card + 0703 PCIe-RO-4 Electromechanical Relay Output Card + 07d0 PCIe-IDO-24 FET Output Card + 0920 PCI-IDI-48 Isolated Digital Input Card + 0bd0 PCIe-IDI-24 Isolated Digital Input Card + 0c50 PCI-DIO-24H 1x 8255 Digital Input / Output Card + 0c51 PCI-DIO-24D 1x 8255 Digital Input / Output Card + 0c52 PCIe-DIO-24 1x 8255 Digital Input / Output Card + 0c53 PCIe-DIO-24H 8255 Digital Input / Output Card + 0c57 mPCIe-DIO-24 8255 Digital Input / Output Card + 0c60 PCI-DIO-48H 8255 Digital Input / Output Card + 0c61 PCIe-DIO-48 8255 Digital Input / Output Card + 0c62 P104-DIO-48 8255 Digital Input / Output Card + 0c68 PCI-DIO-72 8255 Digital Input / Output Card + 0c69 P104-DIO-96 8255 Digital Input / Output Card + 0c70 PCI-DIO-96 8255 Digital Input / Output Card + 0c78 PCI-DIO-120 8255 Digital Input / Output Card + 0dc8 PCI-IDIO-16 Isolated Digital Input / FET Output Card + 0e50 PCI-DIO-24S 8255 Digital Input / Output Card + 0e51 PCI-DIO-24H(C) 8255 Digital Input / Output Card + 0e52 PCI-DIO-24D(C) 8255 Digital Input / Output Card + 0e53 PCIe-DIO-24S 8255 Digital Input / Output Card + 0e54 PCIe-DIO-24HS 8255 Digital Input / Output Card + 0e55 PCIe-DIO-24DC 8255 Digital Input / Output Card + 0e56 PCIe-DIO-24DCS 8255 Digital Input / Output Card + 0e57 mPCIe-DIO-24S 8255 Digital Input / Output Card + 0e60 PCI-DIO-48S 2x 8255 Digital Input / Output Card + 0e61 PCIe-DIO-48S 2x 8255 Digital Input / Output Card + 0e62 P104-DIO-48S 2x 8255 Digital Input / Output Card + 0f00 PCI-IIRO-8 Isolated Digital / Relay Output Card + 0f01 LPCI-IIRO-8 Isolated Digital / Relay Output Card + 0f02 PCIe-IIRO-8 Isolated Digital / Relay Output Card + 0f08 PCI-IIRO-16 Isolated Digital / Relay Output Card + 0f09 PCIe-IIRO-16 Isolated Digital / Relay Output Card + 0fc0 PCIe-IDIO-12 Isolated Digital Input / FET Output Card + 0fc1 PCIe-IDI-12 Isolated Digital Input Card + 0fc2 PCIe-IDO-12 FET Output Card + 0fd0 PCIe-IDIO-24 Isolated Digital Input / FET Output Card + 1050 PCI-422/485-2 2x RS422/RS484 Card + 1051 PCIe-COM-2SRJ 2x RS422/RS484 Card w/RJ45 Connectors + 1052 104I-COM-2S 2x RS422/RS484 PCI/104 Board + 1053 mPCIe-COM-2S 2x RS422/RS484 PCI Express Mini Card + 1058 PCI-COM422/4 4x RS422 Card + 1059 PCI-COM485/4 4x RS485 Card + 105a PCIe-COM422-4 4x RS422 Card + 105b PCIe-COM485-4 4x RS485 Card + 105c PCIe-COM-4SRJ 4x RS422/RS485 Card w/RJ45 Connectors + 105d 104I-COM-4S 4x RS422/RS484 PCI/104 Board + 105e mPCIe-COM-4S 4x RS422/RS484 PCI Express Mini Card + 1068 PCI-COM422/8 8x RS422 Card + 1069 PCI-COM485/8 8x RS485 Card + 106a PCIe-COM422-8 8x RS422 Card + 106b PCIe-COM485-8 8x RS485 Card + 106c 104I-COM-8S 8x RS422/RS485 PCI/104 Board + 1088 PCI-COM232/1 1x RS232 Card + 1090 PCI-COM232/2 2x RS232 Card + 1091 PCIe-COM232-2RJ 2x RS232 Card w/RJ45 Connectors + 1093 mPCIe-COM232-2 2x RS232 PCI Express Mini Card + 1098 PCIe-COM232-4 4x RS232 Card + 1099 PCIe-COM232-4RJ 4x RS232 Card w/RJ45 Connectors + 109b mPCIe-COM232-4 4x RS232 PCI Express Mini Card + 10a8 P104-COM232-8 8x RS232 PC-104+ Board + 10a9 PCIe-COM232-8 8x RS232 Card + 10c9 PCI-COM-1S 1x RS422/RS485 Card + 10d0 PCI-COM2S 2x RS422/RS485 Card + 10d1 PCIe-COM-2SMRJ 2x RS232/RS422/RS485 Card w/RJ45 Connectors + 10d2 104I-COM-2SM 2x RS232/RS422/RS485 PCI/104 Board + 10d3 mPCIe-COM-2SM 2x RS232/RS422/RS485 PCI Express Mini Card + 10d8 PCI-COM-4SM 4x RS232/RS422/RS485 Card + 10d9 PCIe-COM-4SM 4x RS232/RS422/RS485 Card + 10da PCIe-COM-4SMRJ 4x RS232/RS422/RS485 Card w/RJ45 Connectors + 10db 104I-COM-4SM 4x RS232/RS422/RS485 PCI/104 Board + 10dc mPCIe-COM-4SM 4x RS232/RS422/RS485 PCI Express Mini Card + 10e8 PCI-COM-8SM 8x RS232/RS422/RS485 Card + 10e9 PCIe-COM-8SM 8x RS232/RS422/RS485 Card + 10ea 104I-COM-8SM 8x RS232/RS422/RS485 PCI-104 Board + 1108 mPCIe-ICM485-1 1x Isolated RS485 PCI Express Mini Card + 1110 mPCIe-ICM422-2 2x Isolated RS422 PCI Express Mini Card + 1111 mPCIe-ICM485-2 2x Isolated RS485 PCI Express Mini Card + 1118 mPCIe-ICM422-4 4x Isolated RS422 PCI Express Mini Card + 1119 mPCIe-ICM485-4 4x Isolated RS485 PCI Express Mini Card + 1148 PCI-ICM-1S 1x Isolated RS422/RS485 Card + 1150 PCI-ICM-2S 2x Isolated RS422/RS485 Card + 1152 PCIe-ICM-2S 2x Isolated RS422/RS485 Card + 1158 PCI-ICM422/4 4x Isolated RS422 Card + 1159 PCI-ICM485/4 4x Isolated RS485 Card + 115a PCIe-ICM-4S 4x Isolated RS422/RS485 Card + 1190 PCIe-ICM232-2 2x Isolated RS232 Card + 1191 mPCIe-ICM232-2 2x Isolated RS232 PCI Express Mini Card + 1198 PCIe-ICM232-4 4x Isolated RS232 Card + 1199 mPCIe-ICM232-4 4x Isolated RS422 PCI Express Mini Card + 11d0 PCIe-ICM-2SM 2x Isolated RS232/RS422/RS485 Card + 11d8 PCIe-ICM-4SM 4x Isolated RS232/RS422/RS485 Card + 1250 PCI-WDG-2S Watchdog and 2x Serial Card + 12d0 PCI-WDG-IMPAC + 2230 PCI-QUAD-8 8x Quadrature Input Card + 2231 PCI-QUAD-4 4x Quadrature Input Card + 22c0 PCI-WDG-CSM Watchdog Card + 25c0 P104-WDG-E Watchdog PC/104+ Board + 2c50 PCI-DIO-96CT 96x Digital Input / Output Card + 2c58 PCI-DIO-96C3 96x Digital Input / Output Card w/3x 8254 Counter Card + 2ee0 PCIe-DIO24S-CTR12 24x Digital Input / Output Card w/4x 8254 Counter Card + 2fc0 P104-WDG-CSM Watchdog PC/104+ Board + 2fc1 P104-WDG-CSMA Advanced Watchdog PC/104+ Board + 5ed0 PCI-DAC + 6c90 PCI-DA12-2 2x 12-bit Analog Output Card + 6c98 PCI-DA12-4 4x 12-bit Analog Output Card + 6ca0 PCI-DA12-6 6x 12-bit Analog Output Card + 6ca8 PCI-DA12-8 8x 12-bit Analog Output Card + 6ca9 PCI-DA12-8V + 6cb0 PCI-DA12-16 16x 12-bit Analog Output Card + 6cb1 PCI-DA12-16V + 8ef0 P104-FAS16-16 + aca8 PCI-AI12-16 12-bit 100kHz Analog Input Card + aca9 PCI-AI12-16A 12-bit 100kHz Analog Input w/FIFO Card + eca8 PCI-AIO12-16 12-bit 100kHz Analog Input w/2x Analog Output and FIFO Card + ecaa PCI-A12-16A 12-bit 100kHz Analog Input w/2x Analog Output and FIFO Card + ece8 LPCI-A16-16A 16-bit 500kHz Analog Input low-profile Card + ece9 LPCI-AIO16A 16-bit 500kHz Analog Input low-profile Card +4978 Axil Computer Inc +4a14 NetVin + 5000 NV5000SC + 4a14 5000 RT8029-Based Ethernet Adapter +4b10 Buslogic Inc. +4c48 LUNG HWA Electronics +4c52 LR-Link +4c53 SBS Technologies + 0000 PLUSTEST device + 4c53 3000 PLUSTEST card (PC104+) + 4c53 3001 PLUSTEST card (PMC) + 0001 PLUSTEST-MM device + 4c53 3002 PLUSTEST-MM card (PMC) +4ca1 Seanix Technology Inc +4d51 MediaQ Inc. + 0200 MQ-200 +4d54 Microtechnica Co Ltd +4d56 MATRIX VISION GmbH + 0000 [mvHYPERION-CLe/CLb] CameraLink PCI Express x1 Frame Grabber + 0001 [mvHYPERION-CLf/CLm] CameraLink PCI Express x4 Frame Grabber + 0010 [mvHYPERION-16R16/-32R16] 16 Video Channel PCI Express x4 Frame Grabber + 0020 [mvHYPERION-HD-SDI] HD-SDI PCI Express x4 Frame Grabber + 0030 [mvHYPERION-HD-SDI-Merger] HD-SDI PCI Express x4 Frame Grabber +4ddc ILC Data Device Corp + 0100 DD-42924I5-300 (ARINC 429 Data Bus) + 0300 SB-3620 Motion Feedback Device + 0340 SB-3623 Motion Feedback Device + 0400 SB-3622 Motion Feedback Device + 0500 SB-3621 Motion Feedback Device + 0510 SB-3624 Motion Feedback Device + 0801 BU-65570I1 MIL-STD-1553 Test and Simulation + 0802 BU-65570I2 MIL-STD-1553 Test and Simulation + 0811 BU-65572I1 MIL-STD-1553 Test and Simulation + 0812 BU-65572I2 MIL-STD-1553 Test and Simulation + 0881 BU-65570T1 MIL-STD-1553 Test and Simulation + 0882 BU-65570T2 MIL-STD-1553 Test and Simulation + 0891 BU-65572T1 MIL-STD-1553 Test and Simulation + 0892 BU-65572T2 MIL-STD-1553 Test and Simulation + 0901 BU-65565C1 MIL-STD-1553 Data Bus + 0902 BU-65565C2 MIL-STD-1553 Data Bus + 0903 BU-65565C3 MIL-STD-1553 Data Bus + 0904 BU-65565C4 MIL-STD-1553 Data Bus + 0b01 BU-65569I1 MIL-STD-1553 Data Bus + 0b02 BU-65569I2 MIL-STD-1553 Data Bus + 0b03 BU-65569I3 MIL-STD-1553 Data Bus + 0b04 BU-65569I4 MIL-STD-1553 Data Bus + 0d01 SB-3641 Motion Feedback Device + 0d10 SB-365x Motion Feedback Device + 2f00 SB-3642 Motion Feedback Device + 3000 SB-3644 Motion Feedback Device +5045 University of Toronto + 4243 BLASTbus PCI Interface Card v1 +5046 GemTek Technology Corporation + 1001 PCI Radio +5053 Voyetra Technologies + 2010 Daytona Audio Adapter +50b2 TerraTec Electronic GmbH +5136 S S Technologies +5143 Qualcomm Inc +5145 Ensoniq (Old) + 3031 Concert AudioPCI +5168 Animation Technologies Inc. + 0300 FlyDVB-S + 0301 FlyDVB-T +5301 Alliance Semiconductor Corp. + 0001 ProMotion aT3D +5333 S3 Graphics Ltd. + 0551 Plato/PX (system) + 5631 86c325 [ViRGE] + 8800 86c866 [Vision 866] + 8801 86c964 [Vision 964] + 8810 86c764_0 [Trio 32 vers 0] + 8811 86c764/765 [Trio32/64/64V+] + 8812 86cM65 [Aurora64V+] + 8813 86c764_3 [Trio 32/64 vers 3] + 8814 86c767 [Trio 64UV+] + 8815 86cM65 [Aurora 128] + 883d 86c988 [ViRGE/VX] + 8870 FireGL + 8880 86c868 [Vision 868 VRAM] vers 0 + 8881 86c868 [Vision 868 VRAM] vers 1 + 8882 86c868 [Vision 868 VRAM] vers 2 + 8883 86c868 [Vision 868 VRAM] vers 3 + 88b0 86c928 [Vision 928 VRAM] vers 0 + 88b1 86c928 [Vision 928 VRAM] vers 1 + 88b2 86c928 [Vision 928 VRAM] vers 2 + 88b3 86c928 [Vision 928 VRAM] vers 3 + 88c0 86c864 [Vision 864 DRAM] vers 0 + 88c1 86c864 [Vision 864 DRAM] vers 1 + 88c2 86c864 [Vision 864-P DRAM] vers 2 + 88c3 86c864 [Vision 864-P DRAM] vers 3 + 88d0 86c964 [Vision 964 VRAM] vers 0 + 88d1 86c964 [Vision 964 VRAM] vers 1 + 88d2 86c964 [Vision 964-P VRAM] vers 2 + 88d3 86c964 [Vision 964-P VRAM] vers 3 + 88f0 86c968 [Vision 968 VRAM] rev 0 + 88f1 86c968 [Vision 968 VRAM] rev 1 + 88f2 86c968 [Vision 968 VRAM] rev 2 + 88f3 86c968 [Vision 968 VRAM] rev 3 + 8900 86c755 [Trio 64V2/DX] + 5333 8900 86C775 Trio64V2/DX + 8901 86c775/86c785 [Trio 64V2/DX or /GX] + 5333 8901 86C775 Trio64V2/DX, 86C785 Trio64V2/GX + 8902 Plato/PX + 8903 Trio 3D business multimedia + 8904 86c365, 86c366 [Trio 3D] + 1014 00db Integrated Trio3D + 4843 314a Terminator 128/3D GLH + 5333 8904 86C365 Trio3D AGP + 8905 Trio 64V+ family + 8906 Trio 64V+ family + 8907 Trio 64V+ family + 8908 Trio 64V+ family + 8909 Trio 64V+ family + 890a Trio 64V+ family + 890b Trio 64V+ family + 890c Trio 64V+ family + 890d Trio 64V+ family + 890e Trio 64V+ family + 890f Trio 64V+ family + 8a01 86c375 [ViRGE/DX] or 86c385 [ViRGE/GX] + 0e11 b032 ViRGE/GX + 10b4 1617 Nitro 3D + 10b4 1717 Nitro 3D + 5333 8a01 ViRGE/DX + 8a10 ViRGE/GX2 + 1092 8a10 Stealth 3D 4000 + 8a13 86c360 [Trio 3D/1X], 86c362, 86c368 [Trio 3D/2X] + 5333 8a13 Trio3D/2X + 8a20 86c794 [Savage 3D] + 5333 8a20 86C391 Savage3D + 8a21 86c390 [Savage 3D/MV] + 5333 8a21 86C390 Savage3D/MV + 8a22 Savage 4 + 1033 8068 Savage 4 + 1033 8069 Savage 4 + 1033 8110 Savage 4 LT + 105d 0018 SR9 8Mb SDRAM + 105d 002a SR9 Pro 16Mb SDRAM + 105d 003a SR9 Pro 32Mb SDRAM + 105d 092f SR9 Pro+ 16Mb SGRAM + 1092 4207 Stealth III S540 + 1092 4800 Stealth III S540 + 1092 4807 SpeedStar A90 + 1092 4808 Stealth III S540 + 1092 4809 Stealth III S540 + 1092 480e Stealth III S540 + 1092 4904 Stealth III S520 + 1092 4905 SpeedStar A200 + 1092 4a09 Stealth III S540 + 1092 4a0b Stealth III S540 Xtreme + 1092 4a0f Stealth III S540 + 1092 4e01 Stealth III S540 + 1102 101d 3d Blaster Savage 4 + 1102 101e 3d Blaster Savage 4 + 5333 8100 86C394-397 Savage4 SDRAM 100 + 5333 8110 86C394-397 Savage4 SDRAM 110 + 5333 8125 86C394-397 Savage4 SDRAM 125 + 5333 8143 86C394-397 Savage4 SDRAM 143 + 5333 8a22 86C394-397 Savage4 + 5333 8a2e 86C394-397 Savage4 32bit + 5333 9125 86C394-397 Savage4 SGRAM 125 + 5333 9143 86C394-397 Savage4 SGRAM 143 + 8a23 Savage 4 + 8a25 ProSavage PM133 + 0303 0303 D9840-60001 [Brio BA410 Motherboard] + 8a26 ProSavage KM133 + 8c00 ViRGE/M3 + 8c01 ViRGE/MX + 1179 0001 ViRGE/MX + 8c02 ViRGE/MX+ + 8c03 ViRGE/MX+MV + 8c10 86C270-294 [SavageMX-MV] + 8c11 82C270-294 [SavageMX] + 8c12 86C270-294 [SavageIX-MV] + 1014 017f ThinkPad T20/T22 + 1179 0001 86C584 SuperSavage/IXC Toshiba + 8c13 86C270-294 [SavageIX] + 1179 0001 Magnia Z310 + 8c22 SuperSavage MX/128 + 8c24 SuperSavage MX/64 + 8c26 SuperSavage MX/64C + 8c2a SuperSavage IX/128 SDR + 8c2b SuperSavage IX/128 DDR + 8c2c SuperSavage IX/64 SDR + 8c2d SuperSavage IX/64 DDR + 8c2e SuperSavage IX/C SDR + 1014 01fc ThinkPad T23 + 8c2f SuperSavage IX/C DDR + 8d01 86C380 [ProSavageDDR K4M266] + 8d02 VT8636A [ProSavage KN133] AGP4X VGA Controller (TwisterK) + 8d03 VT8751 [ProSavageDDR P4M266] + 8d04 VT8375 [ProSavage8 KM266/KL266] + 8e00 DeltaChrome + 8e26 ProSavage + 8e40 2300E Graphics Processor + 8e48 Matrix [Chrome S25 / S27] + 5333 0130 Chrome S27 256M DDR2 + 9043 Chrome 430 GT + 9045 Chrome 430 ULP / 435 ULP / 440 GTX + 9060 Chrome 530 GT + 9102 86C410 [Savage 2000] + 1092 5932 Viper II Z200 + 1092 5934 Viper II Z200 + 1092 5952 Viper II Z200 + 1092 5954 Viper II Z200 + 1092 5a35 Viper II Z200 + 1092 5a37 Viper II Z200 + 1092 5a55 Viper II Z200 + 1092 5a57 Viper II Z200 + ca00 SonicVibes +5431 AuzenTech, Inc. +544c Teralogic Inc + 0350 TL880-based HDTV/ATSC tuner +544d TBS Technologies + 6178 DVB Tuner PCIe Card + 544d 6904 TBS6904 DVB-S2 Quad Tuner PCIe Card + 544d 6905 TBS6905 DVB-S2 Quad Tuner PCIe Card + 6205 0001 TBS6205 DVB-T2/T/C Quad TV Tuner PCIe Card + 6209 0001 TBS6209 DVB-T2/C2/T/C/ISDB-T OctaTV Tuner +5452 SCANLAB AG + 3443 RTC4 +5455 Technische Universitaet Berlin + 4458 S5933 +5456 GoTView +5519 Cnet Technologies, Inc. +5544 Dunord Technologies + 0001 I-30xx Scanner Interface +5555 Genroco, Inc + 0003 TURBOstor HFP-832 [HiPPI NIC] + 3b00 Epiphan DVI2PCIe video capture card +5646 Vector Fabrics BV +5654 VoiceTronix Pty Ltd +5678 Dawicontrol Computersysteme GmbH +5700 Netpower +# alternately Extreme Engineering Solutions, Inc. +5845 X-ES, Inc. +584d AuzenTech Co., Ltd. +5851 Exacq Technologies + 8008 tDVR8008 8-port video capture card + 8016 tDVR8016 16-chan video capture card + 8032 tDVR8032 32-chan video capture card +5853 XenSource, Inc. + 0001 Xen Platform Device + c000 Citrix XenServer PCI Device for Windows Update +# Virtual device surfaced in guests to provide HID events. + c110 Virtualized HID +# Device surfaced in guests to provide 2d graphics capabilities + c147 Virtualized Graphics Device + c200 XCP-ng Project PCI Device for Windows Update +5854 GoTView +5ace Beholder International Ltd. +6205 TBS Technologies (wrong ID) +6209 TBS Technologies (wrong ID) +631c SmartInfra Ltd + 1652 PXI-1652 Signal Generator + 2504 PXI-2504 Signal Interrogator +6356 UltraStor +6374 c't Magazin fuer Computertechnik + 6773 GPPCI +6409 Logitec Corp. +6549 Teradici Corp. + 1200 TERA1200 PC-over-IP Host +6666 Decision Computer International Co. + 0001 PCCOM4 + 0002 PCCOM8 + 0004 PCCOM2 + 0101 PCI 8255/8254 I/O Card + 0200 12-bit AD/DA Card + 0201 14-bit AD/DA Card + 1011 Industrial Card + 1021 8 photo couple 8 relay Card + 1022 4 photo couple 4 relay Card + 1025 16 photo couple 16 relay Card + 4000 WatchDog Card +6688 Zycoo Co., Ltd + 1200 CooVox TDM Analog Module + 1400 CooVOX TDM GSM Module + 1600 CooVOX TDM E1/T1 Module + 1800 CooVOX TDM BRI Module +# nee Qumranet +6900 Red Hat, Inc. +7063 pcHDTV + 2000 HD-2000 + 3000 HD-3000 + 5500 HD5500 HDTV +7284 HT OMEGA Inc. +7357 IOxOS Technologies SA + 7910 7910 [Althea] +7401 EndRun Technologies + e100 PTP3100 PCIe PTP Slave Clock +7470 TP-LINK Technologies Co., Ltd. +7604 O.N. Electronic Co Ltd. +7bde MIDAC Corporation +7fed PowerTV +8008 Quancom Electronic GmbH + 0010 WDOG1 [PCI-Watchdog 1] + 0011 PWDOG2 [PCI-Watchdog 2] + 0015 Clock77/PCI & Clock77/PCIe (DCF-77 receiver) +# Wrong ID used in subsystem ID of AsusTek PCI-USB2 PCI card. +807d Asustek Computer, Inc. +8086 Intel Corporation + 0007 82379AB + 0008 Extended Express System Support Controller + 0039 21145 Fast Ethernet + 0040 Core Processor DRAM Controller + 0041 Core Processor PCI Express x16 Root Port + 0042 Core Processor Integrated Graphics Controller + 0043 Core Processor Secondary PCI Express Root Port + 0044 Core Processor DRAM Controller + 1025 0347 Aspire 7740G + 1025 0487 TravelMate 5742 + 1028 040a Latitude E6410 + 144d c06a R730 Laptop + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + e4bf 50c1 PC1-GROOVE + 0045 Core Processor PCI Express x16 Root Port + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 0046 Core Processor Integrated Graphics Controller + 1028 040a Latitude E6410 + 144d c06a R730 Laptop + 17c0 10d9 Medion Akoya E7214 Notebook PC [MD98410] + e4bf 50c1 PC1-GROOVE + 0047 Core Processor Secondary PCI Express Root Port + 0048 Core Processor DRAM Controller + 0049 Core Processor PCI Express x16 Root Port + 004a Core Processor Integrated Graphics Controller + 004b Core Processor Secondary PCI Express Root Port + 0050 Core Processor Thermal Management Controller + 0069 Core Processor DRAM Controller + 0082 Centrino Advanced-N 6205 [Taylor Peak] + 8086 1301 Centrino Advanced-N 6205 AGN + 8086 1306 Centrino Advanced-N 6205 ABG + 8086 1307 Centrino Advanced-N 6205 BG + 8086 1321 Centrino Advanced-N 6205 AGN + 8086 1326 Centrino Advanced-N 6205 ABG + 0083 Centrino Wireless-N 1000 [Condor Peak] + 8086 1205 Centrino Wireless-N 1000 BGN + 8086 1206 Centrino Wireless-N 1000 BG + 8086 1225 Centrino Wireless-N 1000 BGN + 8086 1226 Centrino Wireless-N 1000 BG + 8086 1305 Centrino Wireless-N 1000 BGN + 8086 1306 Centrino Wireless-N 1000 BG + 8086 1325 Centrino Wireless-N 1000 BGN + 8086 1326 Centrino Wireless-N 1000 BG + 0084 Centrino Wireless-N 1000 [Condor Peak] + 8086 1215 Centrino Wireless-N 1000 BGN + 8086 1216 Centrino Wireless-N 1000 BG + 8086 1315 Centrino Wireless-N 1000 BGN + 8086 1316 Centrino Wireless-N 1000 BG + 0085 Centrino Advanced-N 6205 [Taylor Peak] + 8086 1311 Centrino Advanced-N 6205 (802.11a/b/g/n) + 8086 1316 Centrino Advanced-N 6205 ABG + 0087 Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] + 8086 1301 Centrino Advanced-N + WiMAX 6250 2x2 AGN + 8086 1306 Centrino Advanced-N + WiMAX 6250 2x2 ABG + 8086 1321 Centrino Advanced-N + WiMAX 6250 2x2 AGN + 8086 1326 Centrino Advanced-N + WiMAX 6250 2x2 ABG + 0089 Centrino Advanced-N + WiMAX 6250 [Kilmer Peak] + 8086 1311 Centrino Advanced-N + WiMAX 6250 2x2 AGN + 8086 1316 Centrino Advanced-N + WiMAX 6250 2x2 ABG + 008a Centrino Wireless-N 1030 [Rainbow Peak] + 8086 5305 Centrino Wireless-N 1030 BGN + 8086 5307 Centrino Wireless-N 1030 BG + 8086 5325 Centrino Wireless-N 1030 BGN + 8086 5327 Centrino Wireless-N 1030 BG + 008b Centrino Wireless-N 1030 [Rainbow Peak] + 8086 5315 Centrino Wireless-N 1030 BGN + 8086 5317 Centrino Wireless-N 1030 BG + 0090 Centrino Advanced-N 6230 [Rainbow Peak] + 8086 5211 Centrino Advanced-N 6230 AGN + 8086 5215 Centrino Advanced-N 6230 BGN + 8086 5216 Centrino Advanced-N 6230 ABG + 0091 Centrino Advanced-N 6230 [Rainbow Peak] + 8086 5201 Centrino Advanced-N 6230 AGN + 8086 5205 Centrino Advanced-N 6230 BGN + 8086 5206 Centrino Advanced-N 6230 ABG + 8086 5207 Centrino Advanced-N 6230 BG + 8086 5221 Centrino Advanced-N 6230 AGN + 8086 5225 Centrino Advanced-N 6230 BGN + 8086 5226 Centrino Advanced-N 6230 ABG + 0100 2nd Generation Core Processor Family DRAM Controller + 1028 04aa XPS 8300 + 1043 844d P8P67/P8H67 Series Motherboard + 0101 Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port + 1028 04b2 Vostro 3350 + 106b 00dc MacBookPro8,2 [Core i7, 15", 2011] + 144d c652 NP300E5C series laptop + 0102 2nd Generation Core Processor Family Integrated Graphics Controller + 1028 04aa XPS 8300 + 1043 0102 P8H67 Series Motherboard + 0104 2nd Generation Core Processor Family DRAM Controller + 1028 04a3 Precision M4600 + 1028 04b2 Vostro 3350 + 1028 04da Vostro 3750 + 106b 00dc MacBookPro8,2 [Core i7, 15", 2011] + 144d c652 NP300E5C series laptop + 17aa 21cf ThinkPad T520 + 0105 Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port + 106b 00dc MacBookPro8,2 [Core i7, 15", 2011] + 0106 2nd Generation Core Processor Family Integrated Graphics Controller + 0108 Xeon E3-1200 Processor Family DRAM Controller + 0109 Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port + 010a Xeon E3-1200 Processor Family Integrated Graphics Controller + 010b Xeon E3-1200/2nd Generation Core Processor Family Integrated Graphics Controller + 010c Xeon E3-1200/2nd Generation Core Processor Family DRAM Controller + 010d Xeon E3-1200/2nd Generation Core Processor Family PCI Express Root Port + 010e Xeon E3-1200/2nd Generation Core Processor Family Integrated Graphics Controller + 0112 2nd Generation Core Processor Family Integrated Graphics Controller + 0116 2nd Generation Core Processor Family Integrated Graphics Controller + 1028 04da Vostro 3750 + 144d c652 integrated HD 3000 graphics controller on NP300E5C series laptop + 0122 2nd Generation Core Processor Family Integrated Graphics Controller + 0126 2nd Generation Core Processor Family Integrated Graphics Controller + 1028 04cc Vostro 3350 + 17aa 21ce ThinkPad T420 + 17aa 21cf ThinkPad T520 + 0150 Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller + 1043 84ca P8 series motherboard + 1458 d000 Ivy Bridge GT1 [HD Graphics] + 15d9 0624 X9SCM-F Motherboard + 1849 0150 Motherboard + 0151 Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port + 1043 1477 N56VZ + 1043 844d P8 series motherboard + 1043 84ca P8H77-I Motherboard + 8086 2010 Server Board S1200BTS + 0152 Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller + 1043 84ca P8H77-I Motherboard + 0153 3rd Gen Core Processor Thermal Subsystem + 1043 1517 Zenbook Prime UX31A + 0154 3rd Gen Core processor DRAM Controller + 1025 0806 Aspire E1-470G + 1025 0813 Aspire R7-571 + 103c 17f6 ProBook 4540s + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 10cf 16bf LIFEBOOK E752 + 0155 Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port + 8086 2010 Server Board S1200BTS + 0156 3rd Gen Core processor Graphics Controller + 1043 108d VivoBook X202EV + 0158 Xeon E3-1200 v2/Ivy Bridge DRAM Controller + 1043 844d P8 series motherboard + 8086 2010 Server Board S1200BT Family + 0159 Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port + 015a Xeon E3-1200 v2/Ivy Bridge Graphics Controller + 015c Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller + 015d Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port + 1043 844d P8 series motherboard + 015e Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller + 0162 Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller + 1043 84ca P8 series motherboard + 1849 0162 Motherboard + 0166 3rd Gen Core processor Graphics Controller + 1043 1517 Zenbook Prime UX31A + 1043 2103 N56VZ + 10cf 16c1 LIFEBOOK E752 + 016a Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller + 1043 844d P8B WS Motherboard + 0172 Xeon E3-1200 v2/3rd Gen Core processor Graphics Controller + 0176 3rd Gen Core processor Graphics Controller + 02a4 Comet Lake SPI (flash) Controller + 02a6 Comet Lake North Peak + 02d3 Comet Lake SATA AHCI Controller + 02e0 Comet Lake Management Engine Interface + 02e8 Serial IO I2C Host Controller + 02f0 Wireless-AC 9462 + 02f9 Comet Lake Thermal Subsytem + 02fc Comet Lake Integrated Sensor Solution + 0309 80303 I/O Processor PCI-to-PCI Bridge + 030d 80312 I/O Companion Chip PCI-to-PCI Bridge + 0326 6700/6702PXH I/OxAPIC Interrupt Controller A + 103c 3208 ProLiant DL140 G2 + 1775 1100 CR11/VR11 Single Board Computer + 0327 6700PXH I/OxAPIC Interrupt Controller B + 103c 3208 ProLiant DL140 G2 + 1775 1100 CR11/VR11 Single Board Computer + 0329 6700PXH PCI Express-to-PCI Bridge A + 032a 6700PXH PCI Express-to-PCI Bridge B + 032c 6702PXH PCI Express-to-PCI Bridge A + 0330 80332 [Dobson] I/O processor (A-Segment Bridge) + 0331 80332 [Dobson] I/O processor (A-Segment IOAPIC) + 0332 80332 [Dobson] I/O processor (B-Segment Bridge) + 0333 80332 [Dobson] I/O processor (B-Segment IOAPIC) + 0334 80332 [Dobson] I/O processor (ATU) + 0335 80331 [Lindsay] I/O processor (PCI-X Bridge) + 0336 80331 [Lindsay] I/O processor (ATU) + 0340 41210 [Lanai] Serial to Parallel PCI Bridge (A-Segment Bridge) + 0341 41210 [Lanai] Serial to Parallel PCI Bridge (B-Segment Bridge) + 0370 80333 Segment-A PCIe Express to PCI-X bridge + 0371 80333 A-Bus IOAPIC + 0372 80333 Segment-B PCIe Express to PCI-X bridge + 0373 80333 B-Bus IOAPIC + 0374 80333 Address Translation Unit + 0402 Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller + 0406 Haswell Integrated Graphics Controller + 040a Xeon E3-1200 v3 Processor Integrated Graphics Controller + 0412 Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller + 17aa 309f ThinkCentre M83 + 0416 4th Gen Core Processor Integrated Graphics Controller + 17aa 220e ThinkPad T440p + 041a Xeon E3-1200 v3 Processor Integrated Graphics Controller + 041e 4th Generation Core Processor Family Integrated Graphics Controller + 0434 DH89XXCC Series QAT + 0435 DH895XCC Series QAT + 0436 DH8900CC Null Device + 0438 DH8900CC Series Gigabit Network Connection + 043a DH8900CC Series Gigabit Fiber Network Connection + 043c DH8900CC Series Gigabit Backplane Network Connection + 0440 DH8900CC Series Gigabit SFP Network Connection + 0442 DH89XXCC Series QAT Virtual Function + 0443 DH895XCC Series QAT Virtual Function + 0482 82375EB/SB PCI to EISA Bridge + 0483 82424TX/ZX [Saturn] CPU to PCI bridge + 0484 82378ZB/IB, 82379AB (SIO, SIO.A) PCI to ISA Bridge + 0486 82425EX/ZX [Aries] PCIset with ISA bridge + 04a3 82434LX/NX [Mercury/Neptune] Processor to PCI bridge + 04d0 82437FX [Triton FX] + 0500 E8870 Processor bus control + 0501 E8870 Memory controller +# and registers common to both SPs + 0502 E8870 Scalability Port 0 +# and global performance monitoring + 0503 E8870 Scalability Port 1 + 0510 E8870IO Hub Interface Port 0 registers (8-bit compatibility port) + 0511 E8870IO Hub Interface Port 1 registers + 0512 E8870IO Hub Interface Port 2 registers + 0513 E8870IO Hub Interface Port 3 registers + 0514 E8870IO Hub Interface Port 4 registers + 0515 E8870IO General SIOH registers + 0516 E8870IO RAS registers + 0530 E8870SP Scalability Port 0 registers + 0531 E8870SP Scalability Port 1 registers + 0532 E8870SP Scalability Port 2 registers + 0533 E8870SP Scalability Port 3 registers + 0534 E8870SP Scalability Port 4 registers + 0535 E8870SP Scalability Port 5 registers +# (bi-interleave 0) and global registers that are neither per-port nor per-interleave + 0536 E8870SP Interleave registers 0 and 1 +# (bi-interleave 1) + 0537 E8870SP Interleave registers 2 and 3 + 0600 RAID Controller + 8086 0136 SRCU31L + 8086 01af SRCZCR + 8086 01c1 ICP Vortex GDT8546RZ + 8086 01f7 SCRU32 +# uninitialized SRCU32 RAID Controller + 061f 80303 I/O Processor + 0700 CE Media Processor A/V Bridge + 0701 CE Media Processor NAND Flash Controller + 0703 CE Media Processor Media Control Unit 1 + 0704 CE Media Processor Video Capture Interface + 0707 CE Media Processor SPI Slave + 0708 CE Media Processor 4100 + 0800 Moorestown SPI Ctrl 0 + 0801 Moorestown SPI Ctrl 1 + 0802 Moorestown I2C 0 + 0803 Moorestown I2C 1 + 0804 Moorestown I2C 2 + 0805 Moorestown Keyboard Ctrl + 0806 Moorestown USB Ctrl + 0807 Moorestown SD Host Ctrl 0 + 0808 Moorestown SD Host Ctrl 1 + 0809 Moorestown NAND Ctrl + 080a Moorestown Audio Ctrl + 080b Moorestown ISP + 080c Moorestown Security Controller + 080d Moorestown External Displays + 080e Moorestown SCU IPC + 080f Moorestown GPIO Controller + 0810 Moorestown Power Management Unit + 0811 Moorestown OTG Ctrl + 0812 Moorestown SPI Ctrl 2 + 0813 Moorestown SC DMA + 0814 Moorestown LPE DMA + 0815 Moorestown SSP0 + 0817 Medfield Serial IO I2C Controller #3 + 0818 Medfield Serial IO I2C Controller #4 + 0819 Medfield Serial IO I2C Controller #5 + 081a Medfield GPIO Controller [Core] + 081b Medfield Serial IO HSUART Controller #1 + 081c Medfield Serial IO HSUART Controller #2 + 081d Medfield Serial IO HSUART Controller #3 + 081e Medfield Serial IO HSUART DMA Controller + 081f Medfield GPIO Controller [AON] + 0820 Medfield SD Host Controller + 0821 Medfield SDIO Controller #1 + 0822 Medfield SDIO Controller #2 + 0823 Medfield eMMC Controller #0 + 0824 Medfield eMMC Controller #1 + 0827 Medfield Serial IO DMA Controller + 0828 Medfield Power Management Unit + 0829 Medfield USB Device Controller (OTG) + 082a Medfield SCU IPC + 082c Medfield Serial IO I2C Controller #0 + 082d Medfield Serial IO I2C Controller #1 + 082e Medfield Serial IO I2C Controller #2 + 0885 Centrino Wireless-N + WiMAX 6150 + 8086 1305 Centrino Wireless-N + WiMAX 6150 BGN + 8086 1307 Centrino Wireless-N + WiMAX 6150 BG + 8086 1325 Centrino Wireless-N + WiMAX 6150 BGN + 8086 1327 Centrino Wireless-N + WiMAX 6150 BG + 0886 Centrino Wireless-N + WiMAX 6150 + 8086 1315 Centrino Wireless-N + WiMAX 6150 BGN + 8086 1317 Centrino Wireless-N + WiMAX 6150 BG + 0887 Centrino Wireless-N 2230 + 8086 4062 Centrino Wireless-N 2230 BGN + 8086 4462 Centrino Wireless-N 2230 BGN + 0888 Centrino Wireless-N 2230 + 8086 4262 Centrino Wireless-N 2230 BGN + 088e Centrino Advanced-N 6235 + 8086 4060 Centrino Advanced-N 6235 AGN + 8086 4460 Centrino Advanced-N 6235 AGN + 088f Centrino Advanced-N 6235 + 8086 4260 Centrino Advanced-N 6235 AGN + 0890 Centrino Wireless-N 2200 + 8086 4022 Centrino Wireless-N 2200 BGN + 8086 4422 Centrino Wireless-N 2200 BGN + 8086 4822 Centrino Wireless-N 2200 BGN + 0891 Centrino Wireless-N 2200 + 8086 4222 Centrino Wireless-N 2200 BGN + 0892 Centrino Wireless-N 135 + 8086 0062 Centrino Wireless-N 135 BGN + 8086 0462 Centrino Wireless-N 135 BGN + 0893 Centrino Wireless-N 135 + 8086 0262 Centrino Wireless-N 135 BGN + 0894 Centrino Wireless-N 105 + 8086 0022 Centrino Wireless-N 105 BGN + 8086 0422 Centrino Wireless-N 105 BGN + 8086 0822 Centrino Wireless-N 105 BGN + 0895 Centrino Wireless-N 105 + 8086 0222 Centrino Wireless-N 105 BGN + 0896 Centrino Wireless-N 130 + 8086 5005 Centrino Wireless-N 130 BGN + 8086 5007 Centrino Wireless-N 130 BG + 8086 5025 Centrino Wireless-N 130 BGN + 8086 5027 Centrino Wireless-N 130 BG + 0897 Centrino Wireless-N 130 + 8086 5015 Centrino Wireless-N 130 BGN + 8086 5017 Centrino Wireless-N 130 BG + 08a7 Quark SoC X1000 SDIO / eMMC Controller + 08ae Centrino Wireless-N 100 + 8086 1005 Centrino Wireless-N 100 BGN + 8086 1007 Centrino Wireless-N 100 BG + 8086 1025 Centrino Wireless-N 100 BGN + 8086 1027 Centrino Wireless-N 100 BG + 08af Centrino Wireless-N 100 + 8086 1015 Centrino Wireless-N 100 BGN + 8086 1017 Centrino Wireless-N 100 BG + 08b1 Wireless 7260 +# Wilkins Peak 2 + 8086 4020 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 402a Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4060 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4062 Wireless-N 7260 +# Wilkins Peak 2 + 8086 406a Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4070 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4072 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4160 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4162 Wireless-N 7260 +# Wilkins Peak 2 + 8086 4170 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4420 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4460 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4462 Wireless-N 7260 +# Wilkins Peak 2 + 8086 446a Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4470 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4472 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4560 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4570 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 486e Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4870 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4a6c Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4a6e Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4a70 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4c60 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4c70 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 5070 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 5072 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 5170 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 5770 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 c020 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c02a Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c060 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c062 Wireless-N 7260 +# Wilkins Peak 2 + 8086 c06a Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c070 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 c072 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 c160 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c162 Wireless-N 7260 +# Wilkins Peak 2 + 8086 c170 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 c360 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c420 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c460 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c462 Wireless-N 7260 +# Wilkins Peak 2 + 8086 c470 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 c472 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 c560 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c570 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 c760 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c770 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 cc60 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 cc70 Dual Band Wireless-AC 7260 + 08b2 Wireless 7260 +# Wilkins Peak 2 + 8086 4220 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4260 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4262 Wireless-N 7260 +# Wilkins Peak 2 + 8086 426a Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4270 Wireless-N 7260 +# Wilkins Peak 2 + 8086 4272 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 4360 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 4370 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 c220 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c260 Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c262 Wireless-N 7260 +# Wilkins Peak 2 + 8086 c26a Dual Band Wireless-N 7260 +# Wilkins Peak 2 + 8086 c270 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 c272 Dual Band Wireless-AC 7260 +# Wilkins Peak 2 + 8086 c370 Dual Band Wireless-AC 7260 + 08b3 Wireless 3160 +# Wilkins Peak 1 + 8086 0060 Dual Band Wireless-N 3160 +# Wilkins Peak 1 + 8086 0062 Wireless-N 3160 +# Wilkins Peak 1 + 8086 0070 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 0072 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 0170 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 0172 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 0260 Dual Band Wireless-N 3160 +# Wilkins Peak 1 + 8086 0470 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 0472 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 1070 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 1170 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 8060 Dual Band Wireless N-3160 +# Wilkins Peak 1 + 8086 8062 Wireless N-3160 +# Wilkins Peak 1 + 8086 8070 Dual Band Wireless AC 3160 +# Wilkins Peak 1 + 8086 8072 Dual Band Wireless AC 3160 +# Wilkins Peak 1 + 8086 8170 Dual Band Wireless AC 3160 +# Wilkins Peak 1 + 8086 8172 Dual Band Wireless AC 3160 +# Wilkins Peak 1 + 8086 8470 Dual Band Wireless AC 3160 +# Wilkins Peak 1 + 8086 8570 Dual Band Wireless AC 3160 + 08b4 Wireless 3160 +# Wilkins Peak 1 + 8086 0270 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 0272 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 0370 Dual Band Wireless-AC 3160 +# Wilkins Peak 1 + 8086 8260 Dual Band Wireless AC 3160 +# Wilkins Peak 1 + 8086 8270 Dual Band Wireless AC 3160 +# Wilkins Peak 1 + 8086 8272 Dual Band Wireless AC 3160 +# Wilkins Peak 1 + 8086 8370 Dual Band Wireless AC 3160 +# PowerVR SGX 545 + 08cf Atom Processor Z2760 Integrated Graphics Controller + 0934 Quark SoC X1000 I2C Controller and GPIO Controller + 0935 Quark SoC X1000 SPI Controller + 0936 Quark SoC X1000 HS-UART + 0937 Quark SoC X1000 10/100 Ethernet MAC + 0939 Quark SoC X1000 USB EHCI Host Controller / USB 2.0 Device + 093a Quark SoC X1000 USB OHCI Host Controller + 0953 PCIe Data Center SSD + 8086 3702 DC P3700 SSD + 8086 3703 DC P3700 SSD [2.5" SFF] + 8086 3704 DC P3500 SSD [Add-in Card] + 8086 3705 DC P3500 SSD [2.5" SFF] + 8086 3709 DC P3600 SSD [Add-in Card] + 8086 370a DC P3600 SSD [2.5" SFF] + 8086 370d SSD 750 Series [Add-in Card] + 8086 370e SSD 750 Series [2.5" SFF] + 0958 Quark SoC X1000 Host Bridge + 095a Wireless 7265 +# Stone Peak 2 AC + 8086 1010 Dual Band Wireless-AC 7265 +# Stone Peak 2 AGN + 8086 5000 Dual Band Wireless-N 7265 +# Stone Peak 2 BGN + 8086 5002 Wireless-N 7265 +# Stone Peak 2 AGN + 8086 500a Dual Band Wireless-N 7265 +# Stone Peak 2 AC + 8086 5010 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 5012 Dual Band Wireless-AC 7265 +# Stone Peak 2 AGN + 8086 5020 Dual Band Wireless-N 7265 +# Stone Peak 2 AGN + 8086 502a Dual Band Wireless-N 7265 +# Maple Peak AC + 8086 5090 Dual Band Wireless-AC 7265 +# Stone Peak 2 AGN + 8086 5100 Dual Band Wireless-AC 7265 +# Stone Peak 2 BGN + 8086 5102 Wireless-N 7265 +# Stone Peak 2 AGN + 8086 510a Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 5110 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 5112 Dual Band Wireless-AC 7265 +# Maple Peak AC + 8086 5190 Dual Band Wireless-AC 7265 +# Stone Peak 2 AGN + 8086 5400 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 5410 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 5412 Dual Band Wireless-AC 7265 +# Stone Peak 2 AGN + 8086 5420 Dual Band Wireless-N 7265 +# Maple Peak AC + 8086 5490 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 5510 Dual Band Wireless-AC 7265 +# Maple Peak AC + 8086 5590 Dual Band Wireless-AC 7265 +# Stone Peak 2 AGN + 8086 9000 Dual Band Wireless-AC 7265 +# Stone Peak 2 AGN + 8086 900a Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 9010 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 9012 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 9110 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 9112 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 9210 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 9310 Dual Band Wireless-AC 7265 +# Stone Peak 2 AGN + 8086 9400 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 9410 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 9510 Dual Band Wireless-AC 7265 + 095b Wireless 7265 +# Stone Peak 2 AGN + 8086 5200 Dual Band Wireless-N 7265 +# Stone Peak 2 BGN + 8086 5202 Wireless-N 7265 +# Stone Peak 2 AGN + 8086 520a Dual Band Wireless-N 7265 +# Stone Peak 2 AC + 8086 5210 Dual Band Wireless-AC 7265 +# Stone Peak 2 AC + 8086 5212 Dual Band Wireless-AC 7265 +# Maple Peak AC + 8086 5290 Dual Band Wireless-AC 7265 +# Stone Peak 2 BGN + 8086 5302 Wireless-N 7265 +# Stone Peak 2 AC + 8086 5310 Dual Band Wireless-AC 7265 +# Stone Peak 2 AGN + 8086 9200 Dual Band Wireless-AC 7265 + 095e Quark SoC X1000 Legacy Bridge + 0960 80960RP (i960RP) Microprocessor/Bridge + 0962 80960RM (i960RM) Bridge + 0964 80960RP (i960RP) Microprocessor/Bridge + 0a03 Haswell-ULT Thermal Subsystem + 0a04 Haswell-ULT DRAM Controller + 17aa 2214 ThinkPad X240 + 0a06 Haswell-ULT Integrated Graphics Controller + 0a0c Haswell-ULT HD Audio Controller + 17aa 2214 ThinkPad X240 + 0a16 Haswell-ULT Integrated Graphics Controller + 17aa 2214 ThinkPad X240 + 0a22 Haswell-ULT Integrated Graphics Controller + 0a26 Haswell-ULT Integrated Graphics Controller + 0a2a Haswell-ULT Integrated Graphics Controller + 0a2e Haswell-ULT Integrated Graphics Controller + 0a53 DC P3520 SSD + 0a54 NVMe Datacenter SSD [3DNAND, Beta Rock Controller] + 1028 1fe1 Express Flash NVMe 1TB 2.5" U.2 (P4500) + 1028 1fe2 Express Flash NVMe 2TB 2.5" U.2 (P4500) + 1028 1fe3 Express Flash NVMe 4TB 2.5" U.2 (P4500) + 1028 1fe4 Express Flash NVMe 4TB HHHL AIC (P4500) + 1028 1fee Express Flash NVMe 1.6TB 2.5" U.2 (P4610) + 1028 1fef Express Flash NVMe 3.2TB 2.5" U.2 (P4610) + 1028 1ff0 Express Flash NVMe 6.4TB 2.5" U.2 (P4610) + 1028 1fff Express Flash NVMe 8.0TB 2.5" U.2 (P4510) + 1028 2003 Express Flash NVMe 1.0 TB 2.5" U.2 (P4510) + 1028 2004 Express Flash NVMe 2.0TB 2.5" U.2 (P4510) + 1028 2005 Express Flash NVMe 4.0TB 2.5" U.2 (P4510) + 108e 4870 NVMe PCIe 3.0 SSD 6.4TB AIC (P4608) + 108e 4871 NVMe PCIe 3.0 SSD 6.4TB 2.5-inch (P4600) + 108e 4879 NVMe PCIe 3.0 SSD v2 6.4TB AIC (P4618) + 108e 487a NVMe PCIe 3.0 SSD v2 6.4TB 2.5-inch (P4610) + 1137 0227 NVMe Datacenter SSD [3DNAND] 1.6TB 2.5" U.2 (P4600) + 1137 0228 NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4600) + 1137 0229 NVMe Datacenter SSD [3DNAND] 3.2TB 2.5" U.2 (P4600) + 1137 022b NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4500) + 1137 022c NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4500) + 1137 022d NVMe Datacenter SSD [3DNAND] 4.0TB 2.5" U.2 (P4500) + 1137 0231 NVMe Datacenter SSD [3DNAND] 0.5TB 2.5" U.2 (P4501) + 1137 0232 NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4501) + 1137 0233 NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4501) + 1137 0258 NVMe Datacenter SSD [3DNAND] 1.6TB 2.5" U.2 (P4610) + 1137 025a NVMe Datacenter SSD [3DNAND] 3.2TB 2.5" U.2 (P4610) + 1137 025b NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4510) + 1137 025c NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4510) + 1137 025d NVMe Datacenter SSD [3DNAND] 4.0TB 2.5" U.2 (P4510) + 1137 025e NVMe Datacenter SSD [3DNAND] 8.0TB 2.5" U.2 (P4510) + 1590 025d NVMe Datacenter SSD [3DNAND] 1.0TB 2.5" U.2 (P4500) + 1590 025e NVMe Datacenter SSD [3DNAND] 2.0TB 2.5" U.2 (P4500) + 1590 025f NVMe Datacenter SSD [3DNAND] 4.0TB 2.5" U.2 (P4500) + 1590 0262 NVMe Datacenter SSD [3DNAND] 1.6TB 2.5" U.2 (P4600) + 1590 0264 NVMe Datacenter SSD [3DNAND] 3.2TB 2.5" U.2 (P4600) + 1590 0265 NVMe Datacenter SSD [3DNAND] 6.4TB 2.5" U.2 (P4600) + 1590 026c NVMe Datacenter SSD [3DNAND] 4.0TB AIC (P4500) + 1d49 4702 Thinksystem Intel P4500 NVMe U.2 + 1d49 4704 Thinksystem Intel P4500 NVMe AIC + 1d49 4712 Thinksystem Intel P4600 NVMe U.2 + 1d49 4714 Thinksystem Intel P4600 NVMe AIC + 1d49 4802 Thinksystem U.2 P4510 NVMe SSD + 1d49 4812 Thinksystem U.2 P4610 NVMe SSD + 8086 4308 Intel SSD D5-P4320 and D5-P4326 + 8086 4702 NVMe Datacenter SSD [3DNAND] SE 2.5" U.2 (P4500) + 8086 4704 NVMe Datacenter SSD [3DNAND] SE AIC (P4500) + 8086 4712 NVMe Datacenter SSD [3DNAND] ME 2.5" U.2 (P4600) + 8086 4714 NVMe Datacenter SSD [3DNAND] ME AIC (P4600) + 8086 4802 NVMe Datacenter SSD [3DNAND] SE 2.5" U.2 (P4510) + 8086 4804 NVMe Datacenter SSD [3DNAND] SE AIC (P4510) + 8086 4805 NVMe Datacenter SSD [3DNAND] SE M.2 (P4511) + 8086 4812 NVMe Datacenter SSD [3DNAND] ME 2.5" U.2 (P4610) + 8086 4814 NVMe Datacenter SSD [3DNAND] ME AIC (P4610) + 0a55 NVMe DC SSD [3DNAND, Beta Rock Controller] + 1028 1fe5 Express Flash NVMe 1.6TB 2.5" U.2 (P4600) + 1028 1fe6 Express Flash NVMe 2TB 2.5" U.2 (P4600) + 1028 1fe7 Express Flash NVMe 3.2TB 2.5" U.2 (P4600) + 1028 1fe8 Express Flash NVMe 2.0TB HHHL AIC (P4600) + 1028 1fe9 Express Flash NVMe 4.0TB HHHL AIC (P4600) + 0be0 Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0be1 Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 105b 0d7c D270S/D250S Motherboard + 0be2 Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0be3 Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0be4 Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0be5 Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0be6 Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0be7 Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0be8 Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0be9 Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0bea Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0beb Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0bec Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0bed Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0bee Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0bef Atom Processor D2xxx/N2xxx Integrated Graphics Controller + 0bf0 Atom Processor D2xxx/N2xxx DRAM Controller + 0bf1 Atom Processor D2xxx/N2xxx DRAM Controller + 0bf2 Atom Processor D2xxx/N2xxx DRAM Controller + 0bf3 Atom Processor D2xxx/N2xxx DRAM Controller + 0bf4 Atom Processor D2xxx/N2xxx DRAM Controller + 0bf5 Atom Processor D2xxx/N2xxx DRAM Controller + 105b 0d7c D270S/D250S Motherboard + 0bf6 Atom Processor D2xxx/N2xxx DRAM Controller + 0bf7 Atom Processor D2xxx/N2xxx DRAM Controller + 0c00 4th Gen Core Processor DRAM Controller + 17aa 309f ThinkCentre M83 + 0c01 Xeon E3-1200 v3/4th Gen Core Processor PCI Express x16 Controller + 0c04 Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller + 103c 1909 ZBook 15 + 17aa 220e ThinkPad T440p + 0c05 Xeon E3-1200 v3/4th Gen Core Processor PCI Express x8 Controller + 0c08 Xeon E3-1200 v3 Processor DRAM Controller + 0c09 Xeon E3-1200 v3/4th Gen Core Processor PCI Express x4 Controller + 0c0c Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller + 17aa 220e ThinkPad T440p + 17aa 309f ThinkCentre M83 + 0c46 Atom Processor S1200 PCI Express Root Port 1 + 0c47 Atom Processor S1200 PCI Express Root Port 2 + 0c48 Atom Processor S1200 PCI Express Root Port 3 + 0c49 Atom Processor S1200 PCI Express Root Port 4 + 0c4e Atom Processor S1200 NTB Primary + 0c50 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device + 0c51 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device + 0c52 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device + 0c53 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QuickData Technology Device + 0c54 Atom Processor S1200 Internal + 0c55 Atom Processor S1200 DFX 1 + 0c56 Atom Processor S1200 DFX 2 + 0c59 Atom Processor S1200 SMBus 2.0 Controller 0 + 0c5a Atom Processor S1200 SMBus 2.0 Controller 1 + 0c5b Atom Processor S1200 SMBus Controller 2 + 0c5c Atom Processor S1200 SMBus Controller 3 + 0c5d Atom Processor S1200 SMBus Controller 4 + 0c5e Atom Processor S1200 SMBus Controller 5 + 0c5f Atom Processor S1200 UART + 0c60 Atom Processor S1200 Integrated Legacy Bus + 0c70 Atom Processor S1200 Internal + 0c71 Atom Processor S1200 Internal + 0c72 Atom Processor S1200 Internal + 0c73 Atom Processor S1200 Internal + 0c74 Atom Processor S1200 Internal + 0c75 Atom Processor S1200 Internal + 0c76 Atom Processor S1200 Internal + 0c77 Atom Processor S1200 Internal + 0c78 Atom Processor S1200 Internal + 0c79 Atom Processor S1200 Internal + 0c7a Atom Processor S1200 Internal + 0c7b Atom Processor S1200 Internal + 0c7c Atom Processor S1200 Internal + 0c7d Atom Processor S1200 Internal + 0c7e Atom Processor S1200 Internal + 0c7f Atom Processor S1200 Internal + 0cf8 Ethernet Controller X710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + 8086 0000 Ethernet Controller X710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + 8086 0001 Ethernet Controller X710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + 0d00 Crystal Well DRAM Controller + 0d01 Crystal Well PCI Express x16 Controller + 0d04 Crystal Well DRAM Controller + 0d05 Crystal Well PCI Express x8 Controller + 0d09 Crystal Well PCI Express x4 Controller + 0d0c Crystal Well HD Audio Controller + 0d16 Crystal Well Integrated Graphics Controller + 0d26 Crystal Well Integrated Graphics Controller + 0d36 Crystal Well Integrated Graphics Controller + 0d4c Ethernet Connection (11) I219-LM + 0d4d Ethernet Connection (11) I219-V + 0d4e Ethernet Connection (10) I219-LM + 0d4f Ethernet Connection (10) I219-V + 0d53 Ethernet Connection (12) I219-LM + 0d55 Ethernet Connection (12) I219-V + 0d58 Ethernet Controller XXV710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + 8086 0000 Ethernet Controller XXV710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + 8086 0001 Ethernet Controller XXV710 Intel(R) FPGA Programmable Acceleration Card N3000 for Networking + 0e00 Xeon E7 v2/Xeon E5 v2/Core i7 DMI2 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e01 Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port in DMI2 Mode + 0e02 Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 1a + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 0e03 Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 1b + 0e04 Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2a + 0e05 Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2b + 0e06 Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2c + 0e07 Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 2d + 0e08 Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3a + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 0e09 Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3b + 0e0a Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3c + 0e0b Xeon E7 v2/Xeon E5 v2/Core i7 PCI Express Root Port 3d + 0e10 Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers + 0e13 Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers + 0e17 Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers + 0e18 Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers + 0e1c Xeon E7 v2/Xeon E5 v2/Core i7 IIO Configuration Registers + 0e1d Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe + 0e1e Xeon E7 v2/Xeon E5 v2/Core i7 UBOX Registers + 0e1f Xeon E7 v2/Xeon E5 v2/Core i7 UBOX Registers + 0e20 Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 0 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e21 Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 1 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e22 Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 2 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e23 Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 3 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e24 Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 4 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e25 Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 5 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e26 Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 6 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e27 Xeon E7 v2/Xeon E5 v2/Core i7 Crystal Beach DMA Channel 7 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e28 Xeon E7 v2/Xeon E5 v2/Core i7 VTd/Memory Map/Misc + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e29 Xeon E7 v2/Xeon E5 v2/Core i7 Memory Hotplug + 0e2a Xeon E7 v2/Xeon E5 v2/Core i7 IIO RAS + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 15d9 066b X9SRL-F + 0e2c Xeon E7 v2/Xeon E5 v2/Core i7 IOAPIC + 15d9 066b X9SRL-F + 0e2e Xeon E7 v2/Xeon E5 v2/Core i7 CBDMA + 0e2f Xeon E7 v2/Xeon E5 v2/Core i7 CBDMA + 0e30 Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 0 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 0e32 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 0 + 0e33 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 1 + 0e34 Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 0e36 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 0e37 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring + 0e38 Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 1 + 0e3a Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 2 + 0e3e Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring + 0e3f Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Performance Ring Monitoring + 0e40 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 2 + 0e41 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers + 0e43 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 2 + 0e44 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 2 + 0e45 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register + 0e47 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register + 0e60 Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 1 + 0e68 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Target Address/Thermal Registers + 0e6a Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers + 0e6b Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers + 0e6c Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers + 0e6d Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder Registers + 0e71 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 RAS Registers + 0e74 Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe + 0e75 Xeon E7 v2/Xeon E5 v2/Core i7 R2PCIe + 0e77 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers + 0e79 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 RAS Registers + 0e7d Xeon E7 v2/Xeon E5 v2/Core i7 UBOX Registers + 0e7f Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers + 0e80 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 0 + 0e81 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Ring Registers + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 0e83 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 0 + 0e84 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 0 + 0e85 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register + 0e87 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Registers + 0e90 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 1 + 0e93 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link 1 + 0e94 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Reut 1 + 0e95 Xeon E7 v2/Xeon E5 v2/Core i7 QPI Link Agent Register + 0ea0 Xeon E7 v2/Xeon E5 v2/Core i7 Home Agent 0 + 1028 04f7 Xeon E5 v2 on PowerEdge R320 server + 0ea8 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Target Address/Thermal Registers + 0eaa Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers + 0eab Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers + 0eac Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers + 0ead Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder Registers + 0eae Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers + 0eaf Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers + 0eb0 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 0 + 0eb1 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 1 + 0eb2 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 0 + 0eb3 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 1 + 0eb4 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 2 + 0eb5 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 Thermal Control 3 + 0eb6 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 2 + 0eb7 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 1 Channel 0-3 ERROR Registers 3 + 0ebc Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers + 0ebe Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers + 0ebf Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO Registers + 0ec0 Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 0 + 0ec1 Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 1 + 0ec2 Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 2 + 0ec3 Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 3 + 0ec4 Xeon E7 v2/Xeon E5 v2/Core i7 Power Control Unit 4 + 0ec8 Xeon E7 v2/Xeon E5 v2/Core i7 System Address Decoder + 0ec9 Xeon E7 v2/Xeon E5 v2/Core i7 Broadcast Registers + 0eca Xeon E7 v2/Xeon E5 v2/Core i7 Broadcast Registers + 0ed8 Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0ed9 Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0edc Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0edd Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0ede Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0edf Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0ee0 Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0ee1 Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0ee2 Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0ee3 Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0ee4 Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0ee5 Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0ee6 Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0ee7 Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0ee8 Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0ee9 Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0eea Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0eeb Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0eec Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0eed Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0eee Xeon E7 v2/Xeon E5 v2/Core i7 Unicast Registers + 0ef0 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 0 + 0ef1 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 1 + 0ef2 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 0 + 0ef3 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 1 + 0ef4 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 2 + 0ef5 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 Thermal Control 3 + 0ef6 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 2 + 0ef7 Xeon E7 v2/Xeon E5 v2/Core i7 Integrated Memory Controller 0 Channel 0-3 ERROR Registers 3 + 0ef8 Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0ef9 Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0efa Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0efb Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0efc Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0efd Xeon E7 v2/Xeon E5 v2/Core i7 DDRIO + 0f00 Atom Processor Z36xxx/Z37xxx Series SoC Transaction Register + 0f04 Atom Processor Z36xxx/Z37xxx Series High Definition Audio Controller + 0f06 Atom Processor Z36xxx/Z37xxx Series LPIO1 DMA Controller + 0f08 Atom Processor Z36xxx/Z37xxx Series LPIO1 PWM Controller + 0f09 Atom Processor Z36xxx/Z37xxx Series LPIO1 PWM Controller + 0f0a Atom Processor Z36xxx/Z37xxx Series LPIO1 HSUART Controller #1 + 0f0c Atom Processor Z36xxx/Z37xxx Series LPIO1 HSUART Controller #2 + 0f0e Atom Processor Z36xxx/Z37xxx Series LPIO1 SPI Controller + 0f12 Atom Processor E3800 Series SMBus Controller + 0f14 Atom Processor Z36xxx/Z37xxx Series SDIO Controller + 0f15 Atom Processor Z36xxx/Z37xxx Series SDIO Controller + 0f16 Atom Processor Z36xxx/Z37xxx Series SDIO Controller + 0f18 Atom Processor Z36xxx/Z37xxx Series Trusted Execution Engine + 0f1c Atom Processor Z36xxx/Z37xxx Series Power Control Unit + 0f20 Atom Processor E3800 Series SATA IDE Controller + 0f21 Atom Processor E3800 Series SATA IDE Controller + 0f22 Atom Processor E3800 Series SATA AHCI Controller + 0f23 Atom Processor E3800 Series SATA AHCI Controller + 0f28 Atom Processor Z36xxx/Z37xxx Series LPE Audio Controller + 0f31 Atom Processor Z36xxx/Z37xxx Series Graphics & Display + 0f34 Atom Processor Z36xxx/Z37xxx Series USB EHCI + 0f35 Atom Processor Z36xxx/Z37xxx, Celeron N2000 Series USB xHCI + 1025 0936 Aspire ES1 + 0f37 Atom Processor Z36xxx/Z37xxx Series OTG USB Device + 0f38 Atom Processor Z36xxx/Z37xxx Series Camera ISP + 0f40 Atom Processor Z36xxx/Z37xxx Series LPIO2 DMA Controller + 0f41 Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #1 + 0f42 Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #2 + 0f43 Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #3 + 0f44 Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #4 + 0f45 Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #5 + 0f46 Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #6 + 0f47 Atom Processor Z36xxx/Z37xxx Series LPIO2 I2C Controller #7 + 0f48 Atom Processor E3800 Series PCI Express Root Port 1 + 0f4a Atom Processor E3800 Series PCI Express Root Port 2 + 0f4c Atom Processor E3800 Series PCI Express Root Port 3 + 0f4e Atom Processor E3800 Series PCI Express Root Port 4 + 0f50 Atom Processor E3800 Series eMMC 4.5 Controller + 1000 82542 Gigabit Ethernet Controller (Fiber) + 0e11 b0df NC6132 Gigabit Ethernet Adapter (1000-SX) + 0e11 b0e0 NC6133 Gigabit Ethernet Adapter (1000-LX) + 0e11 b123 NC6134 Gigabit Ethernet Adapter (1000-LX) + 1014 0119 Netfinity Gigabit Ethernet SX Adapter + 8086 1000 PRO/1000 Gigabit Server Adapter + 1001 82543GC Gigabit Ethernet Controller (Fiber) + 0e11 004a NC6136 Gigabit Server Adapter + 1014 01ea Netfinity Gigabit Ethernet SX Adapter + 8086 1002 PRO/1000 F Server Adapter + 8086 1003 PRO/1000 F Server Adapter + 1002 Pro 100 LAN+Modem 56 Cardbus II + 8086 200e Pro 100 LAN+Modem 56 Cardbus II + 8086 2013 Pro 100 SR Mobile Combo Adapter + 8086 2017 Pro 100 S Combo Mobile Adapter + 1004 82543GC Gigabit Ethernet Controller (Copper) + 0e11 0049 NC7132 Gigabit Upgrade Module + 0e11 b1a4 NC7131 Gigabit Server Adapter + 1014 10f2 Gigabit Ethernet Server Adapter + 8086 1004 PRO/1000 T Server Adapter + 8086 2004 PRO/1000 T Server Adapter + 1008 82544EI Gigabit Ethernet Controller (Copper) + 1014 0269 iSeries 1000/100/10 Ethernet Adapter + 1028 011b PowerEdge 1650/2550 + 1028 011c PRO/1000 XT Network Connection + 8086 1107 PRO/1000 XT Server Adapter + 8086 2107 PRO/1000 XT Server Adapter + 8086 2110 PRO/1000 XT Desktop Adapter + 8086 3108 PRO/1000 XT Network Connection + 1009 82544EI Gigabit Ethernet Controller (Fiber) + 1014 0268 iSeries Gigabit Ethernet Adapter + 8086 1109 PRO/1000 XF Server Adapter + 8086 2109 PRO/1000 XF Server Adapter + 100a 82540EM Gigabit Ethernet Controller + 100c 82544GC Gigabit Ethernet Controller (Copper) + 8086 1112 PRO/1000 T Desktop Adapter + 8086 2112 PRO/1000 T Desktop Adapter + 100d 82544GC Gigabit Ethernet Controller (LOM) + 1028 0123 PRO/1000 XT Network Connection + 1079 891f 82544GC Based Network Connection + 4c53 1080 CT8 mainboard + 8086 110d 82544GC Based Network Connection + 100e 82540EM Gigabit Ethernet Controller + 1014 0265 PRO/1000 MT Network Connection + 1014 0267 PRO/1000 MT Network Connection + 1014 026a PRO/1000 MT Network Connection + 1028 002e Optiplex GX260 + 1028 0134 PowerEdge 600SC + 1028 0151 Optiplex GX270 + 107b 8920 PRO/1000 MT Desktop Adapter + 1af4 1100 QEMU Virtual Machine + 8086 001e PRO/1000 MT Desktop Adapter + 8086 002e PRO/1000 MT Desktop Adapter + 8086 1376 PRO/1000 GT Desktop Adapter + 8086 1476 PRO/1000 GT Desktop Adapter + 100f 82545EM Gigabit Ethernet Controller (Copper) + 1014 0269 iSeries 1000/100/10 Ethernet Adapter + 1014 028e PRO/1000 MT Network Connection + 15ad 0750 PRO/1000 MT Single Port Adapter + 8086 1000 PRO/1000 MT Network Connection + 8086 1001 PRO/1000 MT Server Adapter + 1010 82546EB Gigabit Ethernet Controller (Copper) + 0e11 00db NC7170 Gigabit Server Adapter + 1014 027c PRO/1000 MT Dual Port Network Adapter + 15ad 0760 PRO/1000 MT Dual Port Adapter + 18fb 7872 RESlink-X + 1fc1 0026 Niagara 2260 Bypass Card + 4c53 1080 CT8 mainboard + 4c53 10a0 CA3/CR3 mainboard + 8086 1011 PRO/1000 MT Dual Port Server Adapter + 8086 1012 PRO/1000 MT Dual Port Server Adapter + 8086 101a PRO/1000 MT Dual Port Network Connection + 8086 3424 SE7501HG2 Mainboard + 1011 82545EM Gigabit Ethernet Controller (Fiber) + 1014 0268 iSeries Gigabit Ethernet Adapter + 8086 1002 PRO/1000 MF Server Adapter + 8086 1003 PRO/1000 MF Server Adapter (LX) + 1012 82546EB Gigabit Ethernet Controller (Fiber) + 0e11 00dc NC6170 Gigabit Server Adapter + 8086 1012 PRO/1000 MF Dual Port Server Adapter + 1013 82541EI Gigabit Ethernet Controller + 8086 0013 PRO/1000 MT Network Connection + 8086 1013 PRO/1000 MT Network Connection + 8086 1113 PRO/1000 MT Desktop Adapter + 1014 82541ER Gigabit Ethernet Controller + 8086 0014 PRO/1000 MT Desktop Connection + 8086 1014 PRO/1000 MT Network Connection + 1015 82540EM Gigabit Ethernet Controller (LOM) + 8086 1015 PRO/1000 MT Mobile Connection + 1016 82540EP Gigabit Ethernet Controller (Mobile) + 1014 052c PRO/1000 MT Mobile Connection + 1179 0001 PRO/1000 MT Mobile Connection + 8086 1016 PRO/1000 MT Mobile Connection + 1017 82540EP Gigabit Ethernet Controller + 8086 1017 PR0/1000 MT Desktop Connection + 1018 82541EI Gigabit Ethernet Controller + 8086 1018 PRO/1000 MT Mobile Connection + 1019 82547EI Gigabit Ethernet Controller + 1458 1019 GA-8IPE1000 Pro2 motherboard (865PE) + 1458 e000 Intel Gigabit Ethernet (Kenai II) + 8086 1019 PRO/1000 CT Desktop Connection + 8086 301f D865PERL mainboard + 8086 3025 D875PBZ motherboard + 8086 302c D865GBF Mainboard + 8086 3427 S875WP1-E mainboard + 101a 82547EI Gigabit Ethernet Controller (Mobile) + 8086 101a PRO/1000 CT Mobile Connection + 101d 82546EB Gigabit Ethernet Controller + 8086 1000 PRO/1000 MT Quad Port Server Adapter + 101e 82540EP Gigabit Ethernet Controller (Mobile) + 1014 0549 Thinkpad + 1179 0001 PRO/1000 MT Mobile Connection + 8086 101e PRO/1000 MT Mobile Connection + 1026 82545GM Gigabit Ethernet Controller + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 8086 1000 PRO/1000 MT Server Connection + 8086 1001 PRO/1000 MT Server Adapter + 8086 1002 PRO/1000 MT Server Adapter + 8086 1003 PRO/1000 GT Server Adapter + 8086 1026 PRO/1000 MT Server Connection + 1027 82545GM Gigabit Ethernet Controller + 103c 3103 NC310F PCI-X Gigabit Server Adapter + 8086 1001 PRO/1000 MF Server Adapter(LX) + 8086 1002 PRO/1000 MF Server Adapter(LX) + 8086 1003 PRO/1000 MF Server Adapter(LX) + 8086 1027 PRO/1000 MF Server Adapter + 1028 82545GM Gigabit Ethernet Controller + 8086 1028 PRO/1000 MB Server Connection + 1029 82559 Ethernet Controller + 1030 82559 InBusiness 10/100 + 1031 82801CAM (ICH3) PRO/100 VE (LOM) Ethernet Controller + 1014 0209 ThinkPad A/T/X Series + 104d 80e7 Vaio PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 104d 813c Vaio PCG-GRV616G + 107b 5350 EtherExpress PRO/100 VE + 1179 0001 EtherExpress PRO/100 VE + 144d c000 EtherExpress PRO/100 VE + 144d c001 EtherExpress PRO/100 VE + 144d c003 EtherExpress PRO/100 VE + 144d c006 vpr Matrix 170B4 + 1032 82801CAM (ICH3) PRO/100 VE Ethernet Controller + 1033 82801CAM (ICH3) PRO/100 VM (LOM) Ethernet Controller + 1034 82801CAM (ICH3) PRO/100 VM Ethernet Controller + 1035 82801CAM (ICH3)/82562EH (LOM) Ethernet Controller + 1036 82801CAM (ICH3) 82562EH Ethernet Controller + 1037 82801CAM (ICH3) Chipset Ethernet Controller + 1038 82801CAM (ICH3) PRO/100 VM (KM) Ethernet Controller + 0e11 0098 Evo N600c + 1039 82801DB PRO/100 VE (LOM) Ethernet Controller + 1014 0267 NetVista A30p + 114a 0582 PC8 onboard ethernet ETH1 + 103a 82801DB PRO/100 VE (CNR) Ethernet Controller + 103b 82801DB PRO/100 VM (LOM) Ethernet Controller + 103c 82801DB PRO/100 VM (CNR) Ethernet Controller + 103d 82801DB PRO/100 VE (MOB) Ethernet Controller + 1014 0522 ThinkPad R40 + 1028 2002 Latitude D500 + 8086 103d 82562EZ 10/100 Ethernet Controller + 103e 82801DB PRO/100 VM (MOB) Ethernet Controller + 1040 536EP Data Fax Modem + 16be 1040 V.9X DSP Data Fax Modem + 1043 PRO/Wireless LAN 2100 3B Mini PCI Adapter + 103c 08b0 tc1100 tablet + 8086 2522 Samsung X10/P30 integrated WLAN + 8086 2527 MIM2000/Centrino + 8086 2561 Dell Latitude D800 + 8086 2581 Toshiba Satellite M10 + 1048 82597EX 10GbE Ethernet Controller + 8086 a01f PRO/10GbE LR Server Adapter + 8086 a11f PRO/10GbE LR Server Adapter + 1049 82566MM Gigabit Network Connection + 103c 30c1 Compaq 6910p + 17aa 20b9 ThinkPad T61/R61 + 104a 82566DM Gigabit Network Connection + 104b 82566DC Gigabit Network Connection + 104c 82562V 10/100 Network Connection + 104d 82566MC Gigabit Network Connection + 104e Ethernet Controller X710 for 10 Gigabit SFP+ + 104f Ethernet Controller X710 for 10 Gigabit backplane + 1050 82562EZ 10/100 Ethernet Controller + 1014 0287 ThinkCentre S50 + 1028 019d Dimension 3000 + 1462 728c 865PE Neo2 (MS-6728) + 1462 758c MS-6758 (875P Neo) + 8086 3020 D865PERL mainboard + 8086 302f Desktop Board D865GBF + 8086 3427 S875WP1-E mainboard + 1051 82801EB/ER (ICH5/ICH5R) integrated LAN Controller + 1052 PRO/100 VM Network Connection + 1053 PRO/100 VM Network Connection + 1054 PRO/100 VE Network Connection + 1055 PRO/100 VM Network Connection + 1056 PRO/100 VE Network Connection + 1057 PRO/100 VE Network Connection + 1059 82551QM Ethernet Controller + 105b 82546GB Gigabit Ethernet Controller (Copper) + 105e 82571EB/82571GB Gigabit Ethernet Controller D0/D1 (copper applications) + 103c 7044 NC360T PCI Express Dual Port Gigabit Server Adapter + 103c 704e Dual Port 1000Base-T (PCIe) [AD337A] + 1775 1100 CR11/VR11 Single Board Computer + 1775 6003 Telum GE-QT + 18df 1214 2x 1GbE, PCIe x1, dual Intel 82571EB chips + 8086 005e PRO/1000 PT Dual Port Server Connection + 8086 105e PRO/1000 PT Dual Port Network Connection + 8086 10d5 82571PT Gigabit PT Quad Port Server ExpressModule + 8086 115e PRO/1000 PT Dual Port Server Adapter + 8086 125e PRO/1000 PT Dual Port Server Adapter + 8086 135e PRO/1000 PT Dual Port Server Adapter + 105f 82571EB Gigabit Ethernet Controller + 103c 704f Dual Port 1000Base-SX (PCIe) [AD338A] + 8086 005a PRO/1000 PF Dual Port Server Adapter + 8086 115f PRO/1000 PF Dual Port Server Adapter + 8086 125f PRO/1000 PF Dual Port Server Adapter + 8086 135f PRO/1000 PF Dual Port Server Adapter + 1060 82571EB Gigabit Ethernet Controller + 8086 0060 PRO/1000 PB Dual Port Server Connection + 8086 1060 PRO/1000 PB Dual Port Server Connection + 1064 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller + 1043 80f8 P5GD1-VW Mainboard + 1065 82562ET/EZ/GT/GZ - PRO/100 VE Ethernet Controller + 1066 82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller + 1067 82562 EM/EX/GX - PRO/100 VM Ethernet Controller + 1068 82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller Mobile + 103c 30d5 530 Laptop + 1069 82562EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller Mobile + 106a 82562G - PRO/100 VE (LOM) Ethernet Controller + 106b 82562G - PRO/100 VE Ethernet Controller Mobile + 1075 82547GI Gigabit Ethernet Controller + 1028 0165 PowerEdge 750 + 8086 0075 PRO/1000 CT Network Connection + 8086 1075 PRO/1000 CT Network Connection + 1076 82541GI Gigabit Ethernet Controller + 1028 0165 PRO/1000 MT Network Connection + 1028 016d PRO/1000 MT Network Connection + 1028 019a PRO/1000 MT Network Connection + 1028 106d PRO/1000 MT Network Connection + 8086 0076 PRO/1000 MT Network Connection + 8086 1076 PRO/1000 MT Network Connection + 8086 1176 PRO/1000 MT Desktop Adapter + 8086 1276 PRO/1000 MT Network Adapter + 1077 82541GI Gigabit Ethernet Controller + 1179 0001 PRO/1000 MT Mobile Connection + 8086 0077 PRO/1000 MT Mobile Connection + 8086 1077 PRO/1000 MT Mobile Connection + 1078 82541ER Gigabit Ethernet Controller + 8086 1078 82541ER-based Network Connection + 1079 82546GB Gigabit Ethernet Controller + 103c 12a6 Dual Port 1000Base-T [A9900A] + 103c 12cf Core Dual Port 1000Base-T [AB352A] + 1775 10d0 V5D Single Board Computer Gigabit Ethernet + 1775 ce90 CE9 + 1fc1 0027 Niagara 2261 Failover NIC + 4c53 1090 Cx9 / Vx9 mainboard + 4c53 10b0 CL9 mainboard + 8086 0079 PRO/1000 MT Dual Port Network Connection + 8086 1079 PRO/1000 MT Dual Port Network Connection + 8086 1179 PRO/1000 MT Dual Port Server Adapter + 8086 117a PRO/1000 MT Dual Port Server Adapter + 107a 82546GB Gigabit Ethernet Controller + 103c 12a8 Dual Port 1000base-SX [A9899A] + 8086 107a PRO/1000 MF Dual Port Server Adapter + 8086 127a PRO/1000 MF Dual Port Server Adapter + 107b 82546GB Gigabit Ethernet Controller + 8086 007b PRO/1000 MB Dual Port Server Connection + 8086 107b PRO/1000 MB Dual Port Server Connection + 107c 82541PI Gigabit Ethernet Controller + 8086 1376 PRO/1000 GT Desktop Adapter + 8086 1476 PRO/1000 GT Desktop Adapter + 107d 82572EI Gigabit Ethernet Controller (Copper) + 8086 1082 PRO/1000 PT Server Adapter + 8086 1084 PRO/1000 PT Server Adapter + 8086 1092 PRO/1000 PT Server Adapter + 107e 82572EI Gigabit Ethernet Controller (Fiber) + 8086 1084 PRO/1000 PF Server Adapter + 8086 1085 PRO/1000 PF Server Adapter + 8086 1094 PRO/1000 PF Server Adapter + 107f 82572EI Gigabit Ethernet Controller + 1080 FA82537EP 56K V.92 Data/Fax Modem PCI + 1081 631xESB/632xESB LAN Controller Copper + 1082 631xESB/632xESB LAN Controller fiber + 1083 631xESB/632xESB LAN Controller SERDES + 1084 631xESB/632xESB IDE Redirection + 1085 631xESB/632xESB Serial Port Redirection + 1086 631xESB/632xESB IPMI/KCS0 + 1087 631xESB/632xESB UHCI Redirection + 1089 631xESB/632xESB BT + 108a 82546GB Gigabit Ethernet Controller + 8086 108a PRO/1000 P Dual Port Server Adapter + 8086 118a PRO/1000 P Dual Port Server Adapter + 108b 82573V Gigabit Ethernet Controller (Copper) + 1462 176c on board on MSI 945P - NEO (MS-7176) + 108c 82573E Gigabit Ethernet Controller (Copper) + 108e 82573E KCS (Active Management) + 108f Active Management Technology - SOL + 1091 PRO/100 VM Network Connection + 1092 PRO/100 VE Network Connection + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 1093 PRO/100 VM Network Connection + 1094 PRO/100 VE Network Connection + 1095 PRO/100 VE Network Connection + 1096 80003ES2LAN Gigabit Ethernet Controller (Copper) + 15d9 1096 Motherboard + 15d9 8680 X7DVL-E-O motherboard + 8086 3476 S5000PSLSATA Server Board + 1097 631xESB/632xESB DPT LAN Controller (Fiber) + 1098 80003ES2LAN Gigabit Ethernet Controller (Serdes) + 1099 82546GB Gigabit Ethernet Controller (Copper) + 8086 1099 PRO/1000 GT Quad Port Server Adapter + 109a 82573L Gigabit Ethernet Controller + 1179 ff10 PRO/1000 PL + 17aa 2001 ThinkPad T60 + 17aa 207e ThinkPad X60/X60s + 8086 109a PRO/1000 PL Network Connection + 8086 309c Desktop Board D945GTP + 8086 30a5 Desktop Board D975XBX + 109b 82546GB PRO/1000 GF Quad Port Server Adapter + 109e 82597EX 10GbE Ethernet Controller + 8086 a01f PRO/10GbE CX4 Server Adapter + 8086 a11f PRO/10GbE CX4 Server Adapter + 10a0 82571EB PRO/1000 AT Quad Port Bypass Adapter + 10a1 82571EB PRO/1000 AF Quad Port Bypass Adapter + 10a4 82571EB Gigabit Ethernet Controller + 8086 10a4 PRO/1000 PT Quad Port Server Adapter + 8086 11a4 PRO/1000 PT Quad Port Server Adapter + 10a5 82571EB Gigabit Ethernet Controller (Fiber) + 8086 10a5 PRO/1000 PF Quad Port Server Adapter + 8086 10a6 PRO/1000 PF Quad Port Server Adapter + 10a6 82599EB 10-Gigabit Dummy Function + 10a7 82575EB Gigabit Network Connection + 8086 10a8 82575EB Gigabit Riser Card + 10a9 82575EB Gigabit Backplane Connection + 10b0 82573L PRO/1000 PL Network Connection + 10b2 82573V PRO/1000 PM Network Connection + 10b3 82573E PRO/1000 PM Network Connection + 10b4 82573L PRO/1000 PL Network Connection + 10b5 82546GB Gigabit Ethernet Controller (Copper) + 103c 3109 NC340T PCI-X Quad-port Gigabit Server Adapter + 8086 1099 PRO/1000 GT Quad Port Server Adapter + 8086 1199 PRO/1000 GT Quad Port Server Adapter + 10b6 82598 10GbE PCI-Express Ethernet Controller + 10b9 82572EI Gigabit Ethernet Controller (Copper) + 103c 704a 110T PCIe Gigabit Server Adapter + 8086 1083 PRO/1000 PT Desktop Adapter + 8086 1093 PRO/1000 PT Desktop Adapter + 10ba 80003ES2LAN Gigabit Ethernet Controller (Copper) + 10bb 80003ES2LAN Gigabit Ethernet Controller (Serdes) + 10bc 82571EB/82571GB Gigabit Ethernet Controller (Copper) + 1014 0368 4-Port 10/100/1000 Base-TX PCI Express Adapter for POWER + 103c 704b NC364T PCI Express Quad Port Gigabit Server Adapter +# 375-3481-01 REV:50 + 108e 11bc Quad Port Adapter + 8086 10bc PRO/1000 PT Quad Port LP Server Adapter + 8086 11bc PRO/1000 PT Quad Port LP Server Adapter (Kirkwood Low Profile) + 10bd 82566DM-2 Gigabit Network Connection + 1028 0211 OptiPlex 755 + 10bf 82567LF Gigabit Network Connection + 10c0 82562V-2 10/100 Network Connection + 1028 020d Inspiron 530 + 10c2 82562G-2 10/100 Network Connection + 10c3 82562GT-2 10/100 Network Connection + 10c4 82562GT 10/100 Network Connection + 10c5 82562G 10/100 Network Connection + 10c6 82598EB 10-Gigabit AF Dual Port Network Connection + 8086 a05f 10-Gigabit XF SR Dual Port Server Adapter + 8086 a15f 10-Gigabit XF SR Dual Port Server Adapter + 10c7 82598EB 10-Gigabit AF Network Connection + 1014 037f 10-Gigabit XF SR Server Adapter + 1014 0380 10-Gigabit XF LR Server Adapter + 8086 a05f 10-Gigabit XF SR Server Adapter + 8086 a15f 10-Gigabit XF SR Server Adapter + 8086 a16f 10-Gigabit XF SR Server Adapter + 10c8 82598EB 10-Gigabit AT Network Connection + 8086 a10c 10-Gigabit AT Server Adapter + 8086 a11c 10-Gigabit AT Server Adapter + 8086 a12c 10-Gigabit AT Server Adapter + 10c9 82576 Gigabit Network Connection + 103c 31ef NC362i Integrated Dual port Gigabit Server Adapter + 103c 323f NC362i Integrated Dual port Gigabit Server Adapter + 10a9 8028 UV-BaseIO dual-port GbE + 13a3 0037 DS4100 Secure Multi-Gigabit Server Adapter with Compression + 15d9 a811 H8DGU + 8086 a01c Gigabit ET Dual Port Server Adapter + 8086 a03c Gigabit ET Dual Port Server Adapter + 8086 a04c Gigabit ET Dual Port Server Adapter + 10ca 82576 Virtual Function + 10cb 82567V Gigabit Network Connection + 10cc 82567LM-2 Gigabit Network Connection + 10cd 82567LF-2 Gigabit Network Connection + 10ce 82567V-2 Gigabit Network Connection + 10d3 82574L Gigabit Network Connection + 103c 1785 NC112i 1-port Ethernet Server Adapter + 103c 3250 NC112T PCI Express single Port Gigabit Server Adapter + 1043 8369 Motherboard + 1093 76e9 PCIe-8233 Ethernet Adapter + 10a9 8029 Prism XL Single Port Gigabit Ethernet + 15d9 0605 X8SIL + 15d9 060a X7SPA-H/X7SPA-HF Motherboard + 15d9 060d C7SIM-Q Motherboard + 8086 0001 Gigabit CT2 Desktop Adapter + 8086 3578 Server Board S1200BTLR + 8086 357a Server Board S1200BTS + 8086 a01f Gigabit CT Desktop Adapter + e4bf 50c1 PC1-GROOVE + e4bf 50c2 PC2-LIMBO + 10d4 Matrox Concord GE (customized Intel 82574) + 10d5 82571PT Gigabit PT Quad Port Server ExpressModule + 10d6 82575GB Gigabit Network Connection + 8086 10d6 Gigabit VT Quad Port Server Adapter + 8086 145a Gigabit VT Quad Port Server Adapter + 8086 147a Gigabit VT Quad Port Server Adapter + 10d8 82599EB 10 Gigabit Unprogrammed + 10d9 82571EB Dual Port Gigabit Mezzanine Adapter + 103c 1716 NC360m Dual Port 1GbE BL-c Adapter + 10da 82571EB Quad Port Gigabit Mezzanine Adapter + 103c 1717 NC364m Quad Port 1GbE BL-c Adapter + 10db 82598EB 10-Gigabit Dual Port Network Connection + 10dd 82598EB 10-Gigabit AT CX4 Network Connection + 10de 82567LM-3 Gigabit Network Connection + 10df 82567LF-3 Gigabit Network Connection + 10e1 82598EB 10-Gigabit AF Dual Port Network Connection + 8086 a15f 10-Gigabit SR Dual Port Express Module + 10e2 82575GB Gigabit Network Connection + 8086 10e2 Gigabit VT Quad Port Server Adapter + 10e5 82567LM-4 Gigabit Network Connection + 10e6 82576 Gigabit Network Connection + 8086 a01f Gigabit EF Dual Port Server Adapter + 8086 a02f Gigabit EF Dual Port Server Adapter + 10e7 82576 Gigabit Network Connection + 103c 31ff NC362i Integrated Dual Port BL-c Gigabit Server Adapter + 10e8 82576 Gigabit Network Connection + 8086 a02b Gigabit ET Quad Port Server Adapter + 8086 a02c Gigabit ET Quad Port Server Adapter + 10ea 82577LM Gigabit Network Connection + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + e4bf 50c1 PC1-GROOVE + 10eb 82577LC Gigabit Network Connection + 10ec 82598EB 10-Gigabit AT CX4 Network Connection + 8086 a01f 10-Gigabit CX4 Dual Port Server Adapter + 8086 a11f 10-Gigabit CX4 Dual Port Server Adapter + 10ed 82599 Ethernet Controller Virtual Function + 10ef 82578DM Gigabit Network Connection + 1028 02da OptiPlex 980 + 15d9 060d C7SIM-Q Motherboard + 10f0 82578DC Gigabit Network Connection + 10f1 82598EB 10-Gigabit AF Dual Port Network Connection + 8086 a20f 10-Gigabit AF DA Dual Port Server Adapter + 8086 a21f 10-Gigabit AF DA Dual Port Server Adapter + 10f4 82598EB 10-Gigabit AF Network Connection + 8086 106f 10-Gigabit XF LR Server Adapter + 8086 a06f 10-Gigabit XF LR Server Adapter + 10f5 82567LM Gigabit Network Connection + 17aa 20ee ThinkPad T400 + 10f6 82574L Gigabit Network Connection + 10f7 10 Gigabit BR KX4 Dual Port Network Connection + 108e 7b12 Sun Dual 10GbE PCIe 2.0 FEM + 8086 000d Ethernet Mezzanine Adapter X520-KX4-2 + 10f8 82599 10 Gigabit Dual Port Backplane Connection + 1028 1f63 10GbE 2P X520k bNDC + 103c 17d2 Ethernet 10Gb 2-port 560M Adapter + 103c 18d0 Ethernet 10Gb 2-port 560FLB Adapter + 1059 0111 T4007 10GbE interface + 1059 0130 T4009 10GbE interface + 8086 000c Ethernet X520 10GbE Dual Port KX4-KR Mezz + 10f9 82599 10 Gigabit Dual Port Network Connection + 10fb 82599ES 10-Gigabit SFI/SFP+ Network Connection + 1028 1f72 Ethernet 10G 4P X520/I350 rNDC + 103c 17d0 Ethernet 10Gb 2-port 560FLR-SFP+ Adapter + 103c 17d2 Ethernet 10Gb 2-port 560M Adapter + 103c 17d3 Ethernet 10Gb 2-port 560SFP+ Adapter + 103c 211b Ethernet 10Gb 1-port P560FLR-SFP+ Adapter + 103c 2147 Ethernet 10Gb 1-port 561i Adapter + 103c 2159 Ethernet 10Gb 2-port 562i Adapter + 108e 7b11 Ethernet Server Adapter X520-2 + 1170 004c 82599 DP 10G Mezzanine Adapter + 15d9 0611 AOC-STGN-I2S [REV 1.01] + 1734 11a9 10 Gigabit Dual Port Network Connection + 17aa 1071 ThinkServer X520-2 AnyFabric + 17aa 4007 82599ES 10-Gigabit SFI/SFP+ Network Connection + 17aa 402b 82599ES 10Gb 2-port Server Adapter X520-DA2 + 17aa 402f FPGA Card XC7VX690T-3FFG1157E + 18d4 0c09 82599ES 10Gb 2-port SFP+ OCP Mezz Card MOP81-I-10GS2 + 193d 1004 560F-B + 1bd4 001b 10G SFP+ DP ER102Fi4 Rack Adapter + 1bd4 002f 10G SFP+ DP EP102Fi4A Adapter + 1bd4 0032 10G SFP+ DP EP102Fi4 Adapter + 8086 0002 Ethernet Server Adapter X520-DA2 + 8086 0003 Ethernet Server Adapter X520-2 + 8086 0006 Ethernet Server Adapter X520-1 + 8086 0008 Ethernet OCP Server Adapter X520-2 + 8086 000a Ethernet Server Adapter X520-1 + 8086 000c Ethernet Server Adapter X520-2 + 8086 10a6 82599ES 10Gb 2 port Server Adapter X520-DA2 + 8086 7a11 Ethernet Server Adapter X520-2 + 8086 7a12 Ethernet Server Adapter X520-2 + 10fc 82599 10 Gigabit Dual Port Network Connection + 10fe 82552 10/100 Network Connection + 1107 PRO/1000 MF Server Adapter (LX) + 1130 82815 815 Chipset Host Bridge and Memory Controller Hub + 1025 1016 Travelmate 612 TX + 1043 8027 TUSL2-C Mainboard + 104d 80df Vaio PCG-FX403 + 8086 4532 Desktop Board D815EEA2/D815EFV + 8086 4557 D815EGEW Mainboard + 1131 82815 815 Chipset AGP Bridge + 1132 82815 Chipset Graphics Controller (CGC) + 1025 1016 Travelmate 612 TX + 103c 2001 e-pc 40 + 104d 80df Vaio PCG-FX403 + 8086 4532 Desktop Board D815EEA2/D815EFV + 8086 4541 D815EEA Motherboard + 8086 4557 D815EGEW Mainboard + 1161 82806AA PCI64 Hub Advanced Programmable Interrupt Controller + 8086 1161 82806AA PCI64 Hub APIC + 1162 Xscale 80200 Big Endian Companion Chip + 1190 Merrifield SD/SDIO/eMMC Controller + 1191 Merrifield Serial IO HSUART Controller + 1192 Merrifield Serial IO HSUART DMA Controller + 1194 Merrifield Serial IO SPI Controller + 1195 Merrifield Serial IO I2C Controller + 1196 Merrifield Serial IO I2C Controller + 1199 Merrifield GPIO Controller + 119e Merrifield USB Device Controller (OTG) + 11a0 Merrifield SCU IPC + 11a1 Merrifield Power Management Unit + 11a2 Merrifield Serial IO DMA Controller + 11a5 Merrifield Serial IO PWM Controller + 11c3 Quark SoC X1000 PCIe Root Port 0 + 11c4 Quark SoC X1000 PCIe Root Port 1 + 1200 IXP1200 Network Processor + 172a 0000 AEP SSL Accelerator + 1209 8255xER/82551IT Fast Ethernet Controller + 140b 0610 PMC610 quad Ethernet board + 1af4 1100 QEMU Virtual Machine + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard + 4c53 1070 PC6 mainboard + 1221 82092AA PCI to PCMCIA Bridge + 1222 82092AA IDE Controller + 1223 SAA7116 + 1225 82452KX/GX [Orion] + 1226 82596 PRO/10 PCI + 1227 82865 EtherExpress PRO/100A + 1228 82556 EtherExpress PRO/100 Smart + 1229 82557/8/9/0/1 Ethernet Pro 100 + 0e11 3001 82559 Fast Ethernet LOM with Alert on LAN* + 0e11 3002 82559 Fast Ethernet LOM with Alert on LAN* + 0e11 3003 82559 Fast Ethernet LOM with Alert on LAN* + 0e11 3004 82559 Fast Ethernet LOM with Alert on LAN* + 0e11 3005 82559 Fast Ethernet LOM with Alert on LAN* + 0e11 3006 82559 Fast Ethernet LOM with Alert on LAN* + 0e11 3007 82559 Fast Ethernet LOM with Alert on LAN* + 0e11 b01e NC3120 Fast Ethernet NIC + 0e11 b01f NC3122 Fast Ethernet NIC (dual port) + 0e11 b02f NC1120 Ethernet NIC + 0e11 b04a Netelligent 10/100TX NIC with Wake on LAN + 0e11 b0c6 NC3161 Fast Ethernet NIC (embedded, WOL) + 0e11 b0c7 NC3160 Fast Ethernet NIC (embedded) + 0e11 b0d7 NC3121 Fast Ethernet NIC (WOL) + 0e11 b0dd NC3131 Fast Ethernet NIC (dual port) + 0e11 b0de NC3132 Fast Ethernet Module (dual port) + 0e11 b0e1 NC3133 Fast Ethernet Module (100-FX) + 0e11 b134 NC3163 Fast Ethernet NIC (embedded, WOL) + 0e11 b13c NC3162 Fast Ethernet NIC (embedded) + 0e11 b144 NC3123 Fast Ethernet NIC (WOL) + 0e11 b163 NC3134 Fast Ethernet NIC (dual port) + 0e11 b164 NC3135 Fast Ethernet Upgrade Module (dual port) + 0e11 b1a4 NC7131 Gigabit Server Adapter + 1014 005c 82558B Ethernet Pro 10/100 + 1014 01bc 82559 Fast Ethernet LAN On Motherboard + 1014 01f1 10/100 Ethernet Server Adapter + 1014 01f2 10/100 Ethernet Server Adapter + 1014 0207 Ethernet Pro/100 S + 1014 0232 10/100 Dual Port Server Adapter + 1014 023a ThinkPad R30 + 1014 105c Netfinity 10/100 + 1014 2205 ThinkPad A22p + 1014 305c 10/100 EtherJet Management Adapter + 1014 405c 10/100 EtherJet Adapter with Alert on LAN + 1014 505c 10/100 EtherJet Secure Management Adapter + 1014 605c 10/100 EtherJet Secure Management Adapter + 1014 705c 10/100 Netfinity 10/100 Ethernet Security Adapter + 1014 805c 10/100 Netfinity 10/100 Ethernet Security Adapter + 1028 009b 10/100 Ethernet Server Adapter + 1028 00ce 10/100 Ethernet Server Adapter + 1033 8000 PC-9821X-B06 + 1033 8016 PK-UG-X006 + 1033 801f PK-UG-X006 + 1033 8026 PK-UG-X006 + 1033 8063 82559-based Fast Ethernet Adapter + 1033 8064 82559-based Fast Ethernet Adapter + 103c 10c0 NetServer 10/100TX + 103c 10c3 NetServer 10/100TX + 103c 10ca NetServer 10/100TX + 103c 10cb NetServer 10/100TX + 103c 10e3 NetServer 10/100TX + 103c 10e4 NetServer 10/100TX + 103c 1200 NetServer 10/100TX + 108e 10cf EtherExpress PRO/100(B) + 10c3 1100 SmartEther100 SC1100 + 10cf 1115 8255x-based Ethernet Adapter (10/100) + 10cf 1143 8255x-based Ethernet Adapter (10/100) + 110a 008b 82551QM Fast Ethernet Multifuction PCI/CardBus Controller + 114a 0582 PC8 onboard ethernet ETH2 + 1179 0001 8255x-based Ethernet Adapter (10/100) + 1179 0002 PCI FastEther LAN on Docker + 1179 0003 8255x-based Fast Ethernet + 1259 2560 AT-2560 100 + 1259 2561 AT-2560 100 FX Ethernet Adapter + 1266 0001 NE10/100 Adapter + 13e9 1000 6221L-4U + 144d 2501 SEM-2000 MiniPCI LAN Adapter + 144d 2502 SEM-2100IL MiniPCI LAN Adapter + 1668 1100 EtherExpress PRO/100B (TX) (MiniPCI Ethernet+Modem) + 1775 1100 CR11/VR11 Single Board Computer + 1775 ce90 CE9 + 1af4 1100 QEMU Virtual Machine + 4c53 1080 CT8 mainboard + 4c53 10e0 PSL09 PrPMC + 8086 0001 EtherExpress PRO/100B (TX) + 8086 0002 EtherExpress PRO/100B (T4) + 8086 0003 EtherExpress PRO/10+ + 8086 0004 EtherExpress PRO/100 WfM + 8086 0005 82557 10/100 + 8086 0006 82557 10/100 with Wake on LAN + 8086 0007 82558 10/100 Adapter + 8086 0008 82558 10/100 with Wake on LAN + 8086 0009 82558B PRO/100+ PCI (TP) + 8086 000a EtherExpress PRO/100+ Management Adapter + 8086 000b EtherExpress PRO/100+ + 8086 000c EtherExpress PRO/100+ Management Adapter + 8086 000d EtherExpress PRO/100+ Alert On LAN II* Adapter + 8086 000e EtherExpress PRO/100+ Management Adapter with Alert On LAN* + 8086 000f EtherExpress PRO/100 Desktop Adapter + 8086 0010 EtherExpress PRO/100 S Management Adapter + 8086 0011 EtherExpress PRO/100 S Management Adapter + 8086 0012 EtherExpress PRO/100 S Advanced Management Adapter (D) + 8086 0013 EtherExpress PRO/100 S Advanced Management Adapter (E) + 8086 0030 EtherExpress PRO/100 Management Adapter with Alert On LAN* GC + 8086 0031 EtherExpress PRO/100 Desktop Adapter + 8086 0040 EtherExpress PRO/100 S Desktop Adapter + 8086 0041 EtherExpress PRO/100 S Desktop Adapter + 8086 0042 EtherExpress PRO/100 Desktop Adapter + 8086 0050 EtherExpress PRO/100 S Desktop Adapter + 8086 1009 EtherExpress PRO/100+ Server Adapter + 8086 100c EtherExpress PRO/100+ Server Adapter (PILA8470B) + 8086 1012 EtherExpress PRO/100 S Server Adapter (D) + 8086 1013 EtherExpress PRO/100 S Server Adapter (E) + 8086 1015 EtherExpress PRO/100 S Dual Port Server Adapter + 8086 1017 EtherExpress PRO/100+ Dual Port Server Adapter + 8086 1030 EtherExpress PRO/100+ Management Adapter with Alert On LAN* G Server + 8086 1040 EtherExpress PRO/100 S Server Adapter + 8086 1041 EtherExpress PRO/100 S Server Adapter + 8086 1042 EtherExpress PRO/100 Server Adapter + 8086 1050 EtherExpress PRO/100 S Server Adapter + 8086 1051 EtherExpress PRO/100 Server Adapter + 8086 1052 EtherExpress PRO/100 Server Adapter + 8086 10f0 EtherExpress PRO/100+ Dual Port Adapter + 8086 1229 82557/8/9 [Ethernet Pro 100] + 8086 2009 EtherExpress PRO/100 S Mobile Adapter + 8086 200d EtherExpress PRO/100 Cardbus + 8086 200e EtherExpress PRO/100 LAN+V90 Cardbus Modem + 8086 200f EtherExpress PRO/100 SR Mobile Adapter + 8086 2010 EtherExpress PRO/100 S Mobile Combo Adapter + 8086 2013 EtherExpress PRO/100 SR Mobile Combo Adapter + 8086 2016 EtherExpress PRO/100 S Mobile Adapter + 8086 2017 EtherExpress PRO/100 S Combo Mobile Adapter + 8086 2018 EtherExpress PRO/100 SR Mobile Adapter + 8086 2019 EtherExpress PRO/100 SR Combo Mobile Adapter + 8086 2101 EtherExpress PRO/100 P Mobile Adapter + 8086 2102 EtherExpress PRO/100 SP Mobile Adapter + 8086 2103 EtherExpress PRO/100 SP Mobile Adapter + 8086 2104 EtherExpress PRO/100 SP Mobile Adapter + 8086 2105 EtherExpress PRO/100 SP Mobile Adapter + 8086 2106 EtherExpress PRO/100 P Mobile Adapter + 8086 2107 EtherExpress PRO/100 Network Connection + 8086 2108 EtherExpress PRO/100 Network Connection + 8086 2200 EtherExpress PRO/100 P Mobile Combo Adapter + 8086 2201 EtherExpress PRO/100 P Mobile Combo Adapter + 8086 2202 EtherExpress PRO/100 SP Mobile Combo Adapter + 8086 2203 EtherExpress PRO/100+ MiniPCI + 8086 2204 EtherExpress PRO/100+ MiniPCI + 8086 2205 EtherExpress PRO/100 SP Mobile Combo Adapter + 8086 2206 EtherExpress PRO/100 SP Mobile Combo Adapter + 8086 2207 EtherExpress PRO/100 SP Mobile Combo Adapter + 8086 2208 EtherExpress PRO/100 P Mobile Combo Adapter + 8086 2402 EtherExpress PRO/100+ MiniPCI + 8086 2407 EtherExpress PRO/100+ MiniPCI + 8086 2408 EtherExpress PRO/100+ MiniPCI + 8086 2409 EtherExpress PRO/100+ MiniPCI + 8086 240f EtherExpress PRO/100+ MiniPCI + 8086 2410 EtherExpress PRO/100+ MiniPCI + 8086 2411 EtherExpress PRO/100+ MiniPCI + 8086 2412 EtherExpress PRO/100+ MiniPCI + 8086 2413 EtherExpress PRO/100+ MiniPCI + 8086 3000 82559 Fast Ethernet LAN on Motherboard + 8086 3001 82559 Fast Ethernet LOM with Basic Alert on LAN* + 8086 3002 82559 Fast Ethernet LOM with Alert on LAN II* + 8086 3006 EtherExpress PRO/100 S Network Connection + 8086 3007 EtherExpress PRO/100 S Network Connection + 8086 3008 EtherExpress PRO/100 Network Connection + 8086 3010 EtherExpress PRO/100 S Network Connection + 8086 3011 EtherExpress PRO/100 S Network Connection + 8086 3012 EtherExpress PRO/100 Network Connection + 8086 301a S845WD1-E mainboard + 8086 3411 SDS2 Mainboard + 122d 430FX - 82437FX TSC [Triton I] + 122e 82371FB PIIX ISA [Triton I] + 1230 82371FB PIIX IDE [Triton I] + 1231 DSVD Modem + 1234 430MX - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX) + 1235 430MX - 82437MX Mob. System Ctrlr (MTSC) & 82438MX Data Path (MTDP) + 1237 440FX - 82441FX PMC [Natoma] + 1af4 1100 Qemu virtual machine + 1239 82371FB PIIX IDE Interface + 123b 82380PB PCI to PCI Docking Bridge + 123c 82380AB (MISA) Mobile PCI-to-ISA Bridge + 123d 683053 Programmable Interrupt Device + 123e 82466GX (IHPC) Integrated Hot-Plug Controller (hidden mode) + 123f 82466GX Integrated Hot-Plug Controller (IHPC) + 1240 82752 (752) AGP Graphics Accelerator + 124b 82380FB (MPCI2) Mobile Docking Controller + 1250 430HX - 82439HX TXC [Triton II] + 1360 82806AA PCI64 Hub PCI Bridge + 1361 82806AA PCI64 Hub Controller (HRes) + 8086 1361 82806AA PCI64 Hub Controller (HRes) + 8086 8000 82806AA PCI64 Hub Controller (HRes) + 1460 82870P2 P64H2 Hub PCI Bridge + 1461 82870P2 P64H2 I/OxAPIC + 15d9 3480 P4DP6 + 4c53 1090 Cx9/Vx9 mainboard + 1462 82870P2 P64H2 Hot Plug Controller + 1501 82567V-3 Gigabit Network Connection + 1502 82579LM Gigabit Network Connection (Lewisville) + 1028 04a3 Precision M4600 + 17aa 21ce ThinkPad T520 + 8086 3578 Server Board S1200BTLR + 8086 357a Server Board S1200BTS + 1503 82579V Gigabit Network Connection + 1043 849c P8P67 Deluxe Motherboard + 10cf 161c LIFEBOOK E752 + 1507 Ethernet Express Module X520-P2 + 1508 82598EB Gigabit BX Network Connection + 1509 82580 Gigabit Network Connection + 150a 82576NS Gigabit Network Connection + 150b 82598EB 10-Gigabit AT2 Server Adapter + 8086 a10c 82598EB 10-Gigabit AT2 Server Adapter + 8086 a11c 82598EB 10-Gigabit AT2 Server Adapter + 8086 a12c 82598EB 10-Gigabit AT2 Server Adapter + 150c 82583V Gigabit Network Connection + 150d 82576 Gigabit Backplane Connection + 8086 a10c Gigabit ET Quad Port Mezzanine Card + 150e 82580 Gigabit Network Connection + 103c 1780 NC365T 4-port Ethernet Server Adapter + 8086 12a1 Ethernet Server Adapter I340-T4 + 8086 12a2 Ethernet Server Adapter I340-T4 + 150f 82580 Gigabit Fiber Network Connection + 1510 82580 Gigabit Backplane Connection + 1511 82580 Gigabit SFP Connection + 1513 CV82524 Thunderbolt Controller [Light Ridge 4C 2010] + 1514 Ethernet X520 10GbE Dual Port KX4 Mezz + 8086 000b Ethernet X520 10GbE Dual Port KX4 Mezz + 1515 X540 Ethernet Controller Virtual Function + 1516 82580 Gigabit Network Connection + 8086 12b1 Ethernet Server Adapter I340-T2 + 8086 12b2 Ethernet Server Adapter I340-T2 + 1517 82599ES 10 Gigabit Network Connection + 1137 006a UCS CNA M61KR-I Intel Converged Network Adapter + 1518 82576NS SerDes Gigabit Network Connection + 151a DSL2310 Thunderbolt Controller [Eagle Ridge 2C 2011] + 151b CVL2510 Thunderbolt Controller [Light Peak 2C 2010] + 151c 82599 10 Gigabit TN Network Connection + 108e 7b13 Dual 10GBASE-T LP + 1520 I350 Ethernet Controller Virtual Function + 1521 I350 Gigabit Network Connection + 1028 0602 Gigabit 2P I350-t LOM + 1028 0693 Gigabit 2P I350-t LOM + 1028 06e2 Gigabit 2P I350-t LOM + 1028 0757 Gigabit I350-t LOM + 1028 075a Gigabit I350-t LOM + 1028 1f60 Gigabit 4P I350-t rNDC + 1028 1f62 Gigabit 4P X540/I350 rNDC + 1028 1fa8 Ethernet 10G 4P X550/I350 rNDC + 1028 1fa9 Ethernet 10G 4P X550 rNDC + 1028 1faa Gigabit 4P X550/I350 rNDC + 1028 ff9a Gigabit 4P X710/I350 rNDC + 103c 17d1 Ethernet 1Gb 4-port 366FLR Adapter + 103c 2003 Ethernet 1Gb 2-port 367i Adapter + 103c 2226 Ethernet 1Gb 1-port 364i Adapter + 103c 337f Ethernet 1Gb 2-port 361i Adapter + 103c 3380 Ethernet 1Gb 4-port 366i Adapter + 103c 339e Ethernet 1Gb 2-port 361T Adapter + 103c 8157 Ethernet 1Gb 4-port 366T Adapter + 108e 7b16 Quad Port GbE PCIe 2.0 ExpressModule, UTP + 108e 7b18 Quad Port GbE PCIe 2.0 Low Profile Adapter, UTP + 1093 7648 PCIe-8237R Ethernet Adapter + 1093 7649 PCIe-8236 Ethernet Adapter + 1093 76b1 PCIe-8237R-S Ethernet Adapter + 1093 775b PCIe-8237 Ethernet Adapter + 10a9 802a UV2-BaseIO dual-port GbE + 1137 023e 1GigE I350 LOM + 15d9 0652 Dual Port i350 GbE MicroLP [AOC-CGP-i2] + 17aa 1074 ThinkServer I350-T4 AnyFabric + 17aa 4005 I350 Gigabit Network Connection + 18d4 0c07 I350 1Gb 2-port RJ45 OCP Mezz Card MOP41-I-1GT2 + 193d 1005 360T-B + 193d 1007 360T-L + 1bd4 001d 1G base-T QP EP014Ti1 Adapter + 1bd4 0035 1G base-T QP EP014Ti1 Adapter + 8086 0001 Ethernet Server Adapter I350-T4 + 8086 0002 Ethernet Server Adapter I350-T2 + 8086 0003 Ethernet Network Adapter I350-T4 for OCP NIC 3.0 + 8086 00a1 Ethernet Server Adapter I350-T4 + 8086 00a2 Ethernet Server Adapter I350-T2 + 8086 00a3 Ethernet Network Adapter I350-T4 for OCP NIC 3.0 + 8086 00aa Ethernet Network Adapter I350-T4 for OCP NIC 3.0 + 8086 5001 Ethernet Server Adapter I350-T4 + 8086 5002 Ethernet Server Adapter I350-T2 + 8086 5003 Ethernet 1G 4P I350-t OCP + 1522 I350 Gigabit Fiber Network Connection + 108e 7b17 Quad Port GbE PCIe 2.0 ExpressModule, MMF + 108e 7b19 Dual Port GbE PCIe 2.0 Low Profile Adapter, MMF + 8086 0002 Ethernet Server Adapter I350-T2 + 8086 0003 Ethernet Server Adapter I350-F4 + 8086 0004 Ethernet Server Adapter I350-F2 + 8086 0005 Ethernet Server Adapter I350-F1 + 8086 00a2 Ethernet Server Adapter I350-T2 + 8086 00a3 Ethernet Server Adapter I350-F4 + 8086 00a4 Ethernet Server Adapter I350-F2 + 1523 I350 Gigabit Backplane Connection + 1028 0060 Gigabit 2P I350 LOM + 1028 1f9b Gigabit 4P I350-t bNDC + 103c 1784 Ethernet 1Gb 2-port 361FLB Adapter + 103c 18d1 Ethernet 1Gb 2-port 361FLB Adapter + 103c 1989 Ethernet 1Gb 2-port 363i Adapter + 103c 339f Ethernet 1Gb 4-port 366M Adapter + 8086 1f52 1GbE 4P I350 Mezz + 1524 I350 Gigabit Connection + 1525 82567V-4 Gigabit Network Connection + 1526 82576 Gigabit Network Connection + 8086 a05c Gigabit ET2 Quad Port Server Adapter + 8086 a06c Gigabit ET2 Quad Port Server Adapter + 1527 82580 Gigabit Fiber Network Connection + 8086 0001 Ethernet Server Adapter I340-F4 + 8086 0002 Ethernet Server Adapter I340-F4 + 1528 Ethernet Controller 10-Gigabit X540-AT2 + 1028 1f61 Ethernet 10G 4P X540/I350 rNDC + 103c 192d 561FLR-T 2-port 10Gb Ethernet Adapter + 103c 2004 Ethernet 10Gb 2-port 561i Adapter + 103c 211a Ethernet 10Gb 2-port 561T Adapter + 108e 4853 Ethernet Controller 10-Gigabit X540-AT2 + 108e 7b14 Sun Dual Port 10 GbE PCIe 2.0 ExpressModule, Base-T + 108e 7b15 Sun Dual Port 10 GbE PCIe 2.0 Low Profile Adapter, Base-T + 1137 00bf Ethernet Converged Network Adapter X540-T2 + 1170 0052 Ethernet Controller 10-Gigabit X540-AT2 + 17aa 1073 ThinkServer X540-T2 AnyFabric + 17aa 4006 Ethernet Controller 10-Gigabit X540-AT2 + 1bd4 001a 10G base-T DP ER102Ti3 Rack Adapter + 1bd4 0033 10G base-T DP EP102Ti3 Adapter + 1bd4 0034 10G base-T DP EP102Ti3A Adapter + 8086 0001 Ethernet Converged Network Adapter X540-T2 + 8086 0002 Ethernet Converged Network Adapter X540-T1 + 8086 001a Ethernet Converged Network Adapter X540-T2 + 8086 00a2 Ethernet Converged Network Adapter X540-T1 + 8086 1f61 Ethernet 10G 4P X540/I350 rNDC + 8086 5003 Ethernet 10G 2P X540-t Adapter + 8086 5004 Ethernet 10G 2P X540-t Adapter + 1529 82599 10 Gigabit Dual Port Network Connection with FCoE + 152a 82599 10 Gigabit Dual Port Backplane Connection with FCoE + 152e 82599 Virtual Function + 152f I350 Virtual Function + 1530 X540 Virtual Function + 1531 I210 Gigabit Unprogrammed + 1533 I210 Gigabit Network Connection + 103c 0003 Ethernet I210-T1 GbE NIC + 1059 0180 RD10019 1GbE interface + 1093 7706 Compact Vision System Ethernet Adapter + 10a9 802c UV300 BaseIO single-port GbE + 10a9 802d UV3000 BaseIO GbE Network + 17aa 1100 ThinkServer Ethernet Server Adapter + 8086 0001 Ethernet Server Adapter I210-T1 + 8086 0002 Ethernet Server Adapter I210-T1 + 1536 I210 Gigabit Fiber Network Connection + 1537 I210 Gigabit Backplane Connection + 1059 0110 T4005 1GbE interface + 1059 0111 T4007 1GbE interface + 1059 0120 T4008 1GbE interface + 1059 0130 T4009 1GbE interface + 1059 0140 T2035 1GbE interface + 1059 0150 RD-01068 1GbE interface + 1059 0170 RD-01213 10GbE interface + 1538 I210 Gigabit Network Connection + 1539 I211 Gigabit Network Connection + 153a Ethernet Connection I217-LM + 103c 1909 ZBook 15 + 17aa 220e ThinkPad T440p + 17aa 309f ThinkCentre M83 + 153b Ethernet Connection I217-V + 1547 DSL3510 Thunderbolt Controller [Cactus Ridge 4C 2012] + 1548 DSL3310 Thunderbolt Controller [Cactus Ridge 2C 2012] + 1549 DSL2210 Thunderbolt Controller [Port Ridge 1C 2011] + 154a Ethernet Server Adapter X520-4 + 8086 011a Ethernet Converged Network Adapter X520-4 + 8086 011b Ethernet Converged Network Adapter X520-4 + 8086 011c Ethernet Converged Network Adapter X520-4 + 154c Ethernet Virtual Function 700 Series + 154d Ethernet 10G 2P X520 Adapter + 8086 7b11 10GbE 2P X520 Adapter + 1557 82599 10 Gigabit Network Connection + 17aa 4008 82599EN 10 Gigabit Network Connection + 1bd4 001c 10G SFP+ SP ER101Fi4 Rack Adapter + 1bd4 0030 10G SFP+ SP EP101Fi4A Adapter + 8086 0001 Ethernet OCP Server Adapter X520-1 + 1558 Ethernet Converged Network Adapter X520-Q1 + 8086 011a Ethernet Converged Network Adapter X520-Q1 + 8086 011b Ethernet Converged Network Adapter X520-Q1 + 1559 Ethernet Connection I218-V + 155a Ethernet Connection I218-LM + 17aa 2214 ThinkPad X240 + 155c Ethernet Server Bypass Adapter + 8086 0001 Ethernet Server Bypass Adapter X540-T2 + 155d Ethernet Server Bypass Adapter + 8086 0001 Ethernet Server Bypass Adapter X520-SR2 + 8086 0002 Ethernet Server Bypass Adapter X520-LR2 + 1560 Ethernet Controller X540 + 1563 Ethernet Controller 10G X550T + 1028 1fa8 Ethernet 10G 4P X550/I350 rNDC + 1028 1fa9 Ethernet 10G 4P X550 rNDC + 1137 02b2 X550-TX 10 Gig LOM + 1137 02b3 X550-TX 10 Gig LOM + 1170 0001 Intel Ethernet Controller X550-T2 OCP card + 14c0 1201 X550 10Gb 2P RJ45 OCP Mezz + 1590 00d1 Ethernet 10Gb 2-port 562T Adapter + 1590 00d2 Ethernet 10Gb 2-port 562FLR-T Adapter + 16b8 7217 Twin10G Thunderbolt 3 Edition + 18d4 0c08 X550 10Gb 2-port RJ45 OCP Mezz Card MOP81-I-10GT2 + 193d 1008 560T-B + 193d 1009 560T-L + 193d 1011 UN-NIC-ETH563T-sL-2P + 8086 0001 Ethernet Converged Network Adapter X550-T2 + 8086 001a Ethernet Converged Network Adapter X550-T2 + 8086 001b Ethernet Server Adapter X550-T2 for OCP + 8086 001d Ethernet 10G 2P X550-t Adapter + 8086 0022 Ethernet Converged Network Adapter X550-T2 + 1564 X550 Virtual Function + 1565 X550 Virtual Function + 1566 DSL4410 Thunderbolt NHI [Redwood Ridge 2C 2013] + 1567 DSL4410 Thunderbolt Bridge [Redwood Ridge 2C 2013] + 1568 DSL4510 Thunderbolt NHI [Redwood Ridge 4C 2013] + 1569 DSL4510 Thunderbolt Bridge [Redwood Ridge 4C 2013] + 156a DSL5320 Thunderbolt 2 NHI [Falcon Ridge 2C 2013] + 156b DSL5320 Thunderbolt 2 Bridge [Falcon Ridge 2C 2013] + 156c DSL5520 Thunderbolt 2 NHI [Falcon Ridge 4C 2013] + 156d DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013] + 156f Ethernet Connection I219-LM + 1028 06dc Latitude E7470 + 103c 8079 EliteBook 840 G3 + 1570 Ethernet Connection I219-V + 1571 Ethernet Virtual Function 700 Series + 1572 Ethernet Controller X710 for 10GbE SFP+ + 1028 0000 Ethernet 10G X710 rNDC + 1028 1f99 Ethernet 10G 4P X710/I350 rNDC + 1028 1f9c Ethernet 10G 4P X710 SFP+ rNDC + 103c 0000 Ethernet 10Gb 562SFP+ Adapter + 103c 22fc Ethernet 10Gb 2-port 562FLR-SFP+ Adapter + 103c 22fd Ethernet 10Gb 2-port 562SFP+ Adapter + 1137 0000 Ethernet Converged NIC X710-DA + 1137 013b Ethernet Converged NIC X710-DA4 + 1137 020a Ethernet Converged NIC X710-DA2 + 1590 0000 Ethernet Controller X710 for 10GbE SFP+ + 1590 0225 Ethernet 10GbE 4P 563SFP+ Adapter + 1590 022f Ethernet 10Gb 2-port 564i Communication Board + 17aa 0000 ThinkServer X710 AnyFabric for 10GbE SFP+ + 17aa 4001 ThinkServer X710-4 AnyFabric for 10GbE SFP+ + 17aa 4002 ThinkServer X710-2 AnyFabric for 10GbE SFP+ + 19e5 d11c Ethernet 2-port X710 10Gb SFP+ Adapter SP330 + 8086 0000 Ethernet Converged Network Adapter X710 + 8086 0001 Ethernet Converged Network Adapter X710-4 + 8086 0002 Ethernet Converged Network Adapter X710-4 + 8086 0004 Ethernet Converged Network Adapter X710-4 + 8086 0005 Ethernet 10G 4P X710 Adapter + 8086 0006 Ethernet 10G 2P X710 Adapter + 8086 0007 Ethernet Converged Network Adapter X710-2 + 8086 0008 Ethernet Converged Network Adapter X710-2 + 8086 0009 Ethernet Controller X710 for 10GbE SFP+ + 8086 000a Ethernet Controller X710 for 10GbE SFP+ + 8086 000b Ethernet Server Adapter X710-DA2 for OCP + 8086 000d Ethernet Controller X710 for 10GbE SFP+ + 8086 000e Ethernet Server Adapter OCP X710-2 + 8086 000f Ethernet Server Adapter OCP X710-2 + 8086 0010 Ethernet Converged Network Adapter X710 + 8086 0011 Ethernet Network Adapter X710-2 for OCP NIC 3.0 + 8086 0012 Ethernet Network Adapter X710-4 for OCP NIC 3.0 + 8086 0013 Ethernet 10G 2P X710 OCP + 8086 0014 Ethernet 10G 4P X710 OCP + 8086 0015 Ethernet Server Adapter X710-DA2 for OCP + 8086 00a1 Ethernet Network Adapter X710-2 for OCP NIC 3.0 + 8086 00a2 Ethernet Network Adapter X710-4 for OCP NIC 3.0 + 8086 4005 Ethernet Controller X710 for 10GbE SFP+ + 8086 4006 Ethernet Controller X710 for 10GbE SFP+ + 8086 4007 Ethernet Controller X710 for 10GbE SFP+ + 1574 Ethernet Controller XL710 Emulation + 1575 DSL6340 Thunderbolt 3 NHI [Alpine Ridge 2C 2015] + 1576 DSL6340 Thunderbolt 3 Bridge [Alpine Ridge 2C 2015] + 1577 DSL6540 Thunderbolt 3 NHI [Alpine Ridge 4C 2015] + 1578 DSL6540 Thunderbolt 3 Bridge [Alpine Ridge 4C 2015] + 157b I210 Gigabit Network Connection + 157c I210 Gigabit Backplane Connection + 157d DSL5110 Thunderbolt 2 NHI (Low Power) [Win Ridge 2C 2014] + 157e DSL5110 Thunderbolt 2 Bridge (Low Power) [Win Ridge 2C 2014] + 1580 Ethernet Controller XL710 for 40GbE backplane + 1581 Ethernet Controller X710 for 10GbE backplane + 1028 0000 Ethernet 10G X710-k bNDC + 1028 1f98 Ethernet 10G 4P X710-k bNDC + 1028 1f9e Ethernet 10G 2P X710-k bNDC + 1059 0150 RD-01068 10GbE-KR interface + 1059 0170 RD-01213 10GbE interface + 1590 0000 Ethernet 2-port 563i Adapter + 1590 00f8 Ethernet 2-port 563i Adapter + 8086 0000 Ethernet Converged Network Adapter XL710-Q2 + 1583 Ethernet Controller XL710 for 40GbE QSFP+ + 1028 0000 Ethernet 40G 2P XL710 QSFP+ rNDC + 1028 1f9f Ethernet 40G 2P XL710 QSFP+ rNDC + 108e 0000 10 Gb/40 Gb Ethernet Adapter + 108e 7b1b 10 Gb/40 Gb Ethernet Adapter + 108e 7b1d 10Gb/40Gb Ethernet Adapter + 1137 0000 Ethernet Converged NIC XL710-QDA2 + 1137 013c Ethernet Converged NIC XL710-QDA2 + 8086 0000 Ethernet Converged Network Adapter XL710-Q2 + 8086 0001 Ethernet Converged Network Adapter XL710-Q2 + 8086 0002 Ethernet Converged Network Adapter XL710-Q2 + 8086 0003 Ethernet I/O Module XL710-Q2 + 8086 0004 Ethernet Server Adapter XL710-Q2OCP + 8086 0006 Ethernet Converged Network Adapter XL710-Q2 + 1584 Ethernet Controller XL710 for 40GbE QSFP+ + 8086 0000 Ethernet Converged Network Adapter XL710-Q1 + 8086 0001 Ethernet Converged Network Adapter XL710-Q1 + 8086 0002 Ethernet Converged Network Adapter XL710-Q1 + 8086 0003 Ethernet I/O Module XL710-Q1 + 8086 0004 Ethernet Server Adapter XL710-Q1OCP + 1585 Ethernet Controller X710 for 10GbE QSFP+ + 1586 Ethernet Controller X710 for 10GBASE-T + 108e 0000 Ethernet Controller X710 for 10GBASE-T + 108e 4857 Ethernet Controller X710 for 10GBASE-T + 1587 Ethernet Controller XL710 for 20GbE backplane + 103c 0000 Ethernet 10/20Gb 2-port 660FLB Adapter + 103c 22fe Ethernet 10/20Gb 2-port 660FLB Adapter + 1588 Ethernet Controller XL710 for 20GbE backplane + 103c 0000 Ethernet 10/20Gb 2-port 660M Adapter + 103c 22ff Ethernet 10/20Gb 2-port 660M Adapter + 1137 0000 Ethernet Network Adapter XXV710 + 1137 02b4 Ethernet Network Adapter XXV710 OCP 2.0 + 1589 Ethernet Controller X710/X557-AT 10GBASE-T + 108e 0000 Quad Port 10GBase-T Adapter + 108e 7b1c Quad Port 10GBase-T Adapter + 8086 0000 Ethernet Converged Network Adapter X710-T + 8086 0001 Ethernet Converged Network Adapter X710-T4 + 8086 0002 Ethernet Converged Network Adapter X710-T4 + 8086 0003 Ethernet Converged Network Adapter X710-T + 8086 00a0 Ethernet Converged Network Adapter X710-T4 + 8086 1003 Ethernet Converged Network Adapter X710-T + 158a Ethernet Controller XXV710 for 25GbE backplane + 1590 0000 10/25Gb Ethernet Adapter + 1590 0286 Synergy 4610C 10/25Gb Ethernet Adapter + 8086 0000 Ethernet Controller XXV710 for 25GbE backplane + 8086 000a Ethernet 25G 2P XXV710 Mezz + 158b Ethernet Controller XXV710 for 25GbE SFP28 + 1137 0000 Ethernet Network Adapter XXV710 + 1137 0225 Ethernet Network Adapter XXV710 + 1137 02b4 Ethernet Network Adapter XXV710 OCP 2.0 +# UEFI PXE Disabled + 1374 0230 Single Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G1I71) +# With UEFI PXE Enabled + 1374 0231 Single Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G1I71EU) +# UEFI PXE Disabled + 1374 0234 Dual Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G2I71) +# With UEFI PXE Enabled + 1374 0235 Dual Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G2I71EU) +# PCIe x8 Bifurcated as x4x4, UEFI PXE Disabled, low profile + 1374 0238 Quad Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G4I71L) +# PCIe x8 Bifurcated as x4x4, UEFI PXE Enabled, low profile + 1374 0239 Quad Port 25 Gigabit Ethernet PCI Express Server Adapter (PE325G4I71LEU) +# PCIe x16 Bifurcated as x8x8, UEFI PXE Disabled, low profile + 1374 023a Quad Port 25 Gigabit Ethernet PCI Express Server Adapter (PE31625G4I71L) +# PCIe x16 Bifurcated as x8x8, UEFI PXE Enabled, low profile + 1374 023b Quad Port 25 Gigabit Ethernet PCI Express Server Adapter (PE31625G4I71LEU) + 1590 0000 Ethernet Network Adapter XXV710-2 + 1590 0253 Ethernet 10/25/Gb 2-port 661SFP28 Adapter + 8086 0000 Ethernet Network Adapter XXV710 + 8086 0001 Ethernet Network Adapter XXV710-2 + 8086 0002 Ethernet Network Adapter XXV710-2 + 8086 0003 Ethernet Network Adapter XXV710-1 + 8086 0004 Ethernet Network Adapter XXV710-1 + 8086 0005 Ethernet Network Adapter OCP XXV710-2 + 8086 0006 Ethernet Network Adapter OCP XXV710-2 + 8086 0007 Ethernet Network Adapter OCP XXV710-1 + 8086 0008 Ethernet Network Adapter OCP XXV710-1 + 8086 0009 Ethernet 25G 2P XXV710 Adapter + 8086 000a Ethernet 25G 2P XXV710 OCP + 8086 4001 Ethernet Network Adapter XXV710-2 + 1591 Ethernet Controller E810-C for backplane + 1592 Ethernet Controller E810-C for QSFP + 8086 0002 Ethernet Network Adapter E810-C-Q2 + 8086 0004 Ethernet Network Adapter E810-C-Q2 + 8086 0005 Ethernet Network Adapter E810-C-Q1 for OCP3.0 + 8086 0006 Ethernet Network Adapter E810-C-Q2 for OCP3.0 + 8086 0009 Ethernet Network Adapter E810-C-Q1 + 1593 Ethernet Controller E810-C for SFP + 8086 0002 Ethernet Network Adapter E810-L-2 + 8086 0005 Ethernet Network Adapter E810-XXV-4 + 8086 0006 Ethernet Network Adapter E810-XXV-4 + 8086 0007 Ethernet Network Adapter E810-XXV-4 + 8086 0008 Ethernet Network Adapter E810-XXV-2 + 8086 0009 Ethernet Network Adapter E810-XXV-2 for OCP 2.0 + 15a0 Ethernet Connection (2) I218-LM + 15a1 Ethernet Connection (2) I218-V + 15a2 Ethernet Connection (3) I218-LM + 15a3 Ethernet Connection (3) I218-V + 15a4 Ethernet Switch FM10000 Host Interface + 15a5 Ethernet Switch FM10000 Host Virtual Interface + 15a8 Ethernet Connection X552 Virtual Function + 15a9 X552 Virtual Function + 15aa Ethernet Connection X552 10 GbE Backplane + 1059 0120 T4008 10GbE interface + 15ab Ethernet Connection X552 10 GbE Backplane + 1059 0150 RD-01068 10GbE interface + 1059 0170 RD-01213 10GbE interface + 15ac Ethernet Connection X552 10 GbE SFP+ + 1059 0160 RD-01167 10GbE interface + 15ad Ethernet Connection X552/X557-AT 10GBASE-T + 15ae Ethernet Connection X552 1000BASE-T + 15b0 Ethernet Connection X552 Backplane + 15b4 X553 Virtual Function + 15b5 DSL6340 USB 3.1 Controller [Alpine Ridge] + 15b6 DSL6540 USB 3.1 Controller [Alpine Ridge] + 15b7 Ethernet Connection (2) I219-LM + 15b8 Ethernet Connection (2) I219-V + 15b9 Ethernet Connection (3) I219-LM + 15bb Ethernet Connection (7) I219-LM + 15bc Ethernet Connection (7) I219-V + 15bd Ethernet Connection (6) I219-LM + 15be Ethernet Connection (6) I219-V + 15bf JHL6240 Thunderbolt 3 NHI (Low Power) [Alpine Ridge LP 2016] + 15c0 JHL6240 Thunderbolt 3 Bridge (Low Power) [Alpine Ridge LP 2016] + 15c1 JHL6240 Thunderbolt 3 USB 3.1 Controller (Low Power) [Alpine Ridge LP 2016] + 15c2 Ethernet Connection X553 Backplane + 15c3 Ethernet Connection X553 Backplane + 15c4 Ethernet Connection X553 10 GbE SFP+ + 15c5 X553 Virtual Function + 15c6 Ethernet Connection X553 1GbE + 15c7 Ethernet Connection X553 1GbE + 15c8 Ethernet Connection X553/X557-AT 10GBASE-T + 15ce Ethernet Connection X553 10 GbE SFP+ + 15d0 Ethernet SDI Adapter + 8086 0001 Ethernet SDI Adapter FM10420-100GbE-QDA2 + 8086 0002 Ethernet SDI Adapter FM10840-MTP2 + 15d1 Ethernet Controller 10G X550T + 8086 0002 Ethernet Converged Network Adapter X550-T1 + 8086 001b Ethernet Server Adapter X550-T1 for OCP + 8086 0021 Ethernet Converged Network Adapter X550-T1 + 8086 00a2 Ethernet Converged Network Adapter X550-T1 + 15d2 JHL6540 Thunderbolt 3 NHI (C step) [Alpine Ridge 4C 2016] + 15d3 JHL6540 Thunderbolt 3 Bridge (C step) [Alpine Ridge 4C 2016] + 15d4 JHL6540 Thunderbolt 3 USB Controller (C step) [Alpine Ridge 4C 2016] + 15d5 Ethernet SDI Adapter FM10420-25GbE-DA2 + 8086 0001 Intel(R) Ethernet SDI Adapter FM10420-25GbE-DA2 + 15d6 Ethernet Connection (5) I219-V + 15d7 Ethernet Connection (4) I219-LM + 15d8 Ethernet Connection (4) I219-V + 17aa 2247 ThinkPad T570 + 17aa 224f ThinkPad X1 Carbon 5th Gen + 17aa 225d ThinkPad T480 + 15d9 JHL6340 Thunderbolt 3 NHI (C step) [Alpine Ridge 2C 2016] + 15da JHL6340 Thunderbolt 3 Bridge (C step) [Alpine Ridge 2C 2016] + 15db JHL6340 Thunderbolt 3 USB 3.1 Controller (C step) [Alpine Ridge 2C 2016] + 15df Ethernet Connection (8) I219-LM + 15e0 Ethernet Connection (8) I219-V + 15e1 Ethernet Connection (9) I219-LM + 15e2 Ethernet Connection (9) I219-V + 15e3 Ethernet Connection (5) I219-LM + 15e4 Ethernet Connection X553 1GbE + 15e5 Ethernet Connection X553 1GbE + 15e7 JHL7540 Thunderbolt 3 Bridge [Titan Ridge 2C 2018] + 15e8 JHL7540 Thunderbolt 3 NHI [Titan Ridge 2C 2018] + 15e9 JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 2C 2018] + 15ea JHL7540 Thunderbolt 3 Bridge [Titan Ridge 4C 2018] + 15eb JHL7540 Thunderbolt 3 NHI [Titan Ridge 4C 2018] + 15ec JHL7540 Thunderbolt 3 USB Controller [Titan Ridge 4C 2018] + 15ef JHL7540 Thunderbolt 3 Bridge [Titan Ridge DD 2018] + 15f0 JHL7540 Thunderbolt 3 USB Controller [Titan Ridge DD 2018] + 15f4 Ethernet Connection (15) I219-LM + 15f5 Ethernet Connection (15) I219-V + 15f6 I210 Gigabit Ethernet Connection + 15f9 Ethernet Connection (14) I219-LM + 15fa Ethernet Connection (14) I219-V + 15fb Ethernet Connection (13) I219-LM + 15fc Ethernet Connection (13) I219-V + 15ff Ethernet Controller X710 for 10GBASE-T + 1137 0000 X710TLG GbE RJ45 PCIe NIC + 1137 02c1 X710T2LG 2x10 GbE RJ45 PCIe NIC + 1137 02c2 X710T4LG 4x10 GbE RJ45 PCIe NIC + 8086 0000 Ethernet Network Adapter X710-TL + 8086 0001 Ethernet Network Adapter X710-T4L + 8086 0002 Ethernet Network Adapter X710-T4L + 8086 0003 Ethernet Network Adapter X710-T2L + 8086 0004 Ethernet Network Adapter X710-T2L + 8086 0005 Ethernet 10G 2P X710-T2L-t Adapter + 8086 0006 Ethernet 10G 4P X710-T4L-t Adapter + 8086 0007 Ethernet 10G 2P X710-T2L-t OCP + 8086 0008 Ethernet 10G 4P X710-T4L-t OCP + 8086 0009 Ethernet Network Adapter X710-T4L for OCP 3.0 + 8086 000a Ethernet Network Adapter X710-T4L for OCP 3.0 + 8086 000b Ethernet Network Adapter X710-T2L for OCP 3.0 + 8086 000c Ethernet Network Adapter X710-T2L for OCP 3.0 + 8086 000f Ethernet Network Adapter X710-T2L for OCP 3.0 + 1600 Broadwell-U Host Bridge -OPI + 1601 Broadwell-U PCI Express x16 Controller + 1602 Broadwell-U Integrated Graphics + 1603 Broadwell-U Processor Thermal Subsystem + 1604 Broadwell-U Host Bridge -OPI + 1605 Broadwell-U PCI Express x8 Controller + 1606 HD Graphics + 1607 Broadwell-U CHAPS Device + 1608 Broadwell-U Host Bridge -OPI + 1609 Broadwell-U x4 PCIe + 160a Broadwell-U Integrated Graphics + 160b Broadwell-U Integrated Graphics + 160c Broadwell-U Audio Controller + 160d Broadwell-U Integrated Graphics + 160e Broadwell-U Integrated Graphics + 160f Broadwell-U SoftSKU + 1610 Broadwell-U Host Bridge - DMI + 1612 HD Graphics 5600 + 1614 Broadwell-U Host Bridge - DMI + 1616 HD Graphics 5500 + 103c 2216 ZBook 15u G2 Mobile Workstation + 1618 Broadwell-U Host Bridge - DMI + 161a Broadwell-U Integrated Graphics + 161b Broadwell-U Integrated Graphics + 161d Broadwell-U Integrated Graphics + 161e HD Graphics 5300 + 1622 Iris Pro Graphics 6200 + 1626 HD Graphics 6000 + 162a Iris Pro Graphics P6300 + 162b Iris Graphics 6100 + 162d Broadwell-U Integrated Graphics + 162e Broadwell-U Integrated Graphics + 1632 Broadwell-U Integrated Graphics + 1636 Broadwell-U Integrated Graphics + 163a Broadwell-U Integrated Graphics + 163b Broadwell-U Integrated Graphics + 163d Broadwell-U Integrated Graphics + 163e Broadwell-U Integrated Graphics + 1889 Ethernet Adaptive Virtual Function + 18a0 C4xxx Series QAT + 18a1 C4XXX Series QAT Virtual Function + 1900 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + 1901 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x16) + 1902 HD Graphics 510 + 1903 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem + 1028 06dc Latitude E7470 + 1028 06e4 XPS 15 9550 + 17aa 225d ThinkPad T480 + 1904 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + 1028 06dc Latitude E7470 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 17aa 382a B51-80 Laptop + 1905 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x8) + 1906 HD Graphics 510 + 17aa 382a B51-80 Laptop + 1908 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + 1909 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor PCIe Controller (x4) + 190c Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + 190f Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + 1910 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + 1028 06e4 XPS 15 9550 + 1911 Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th/8th Gen Core Processor Gaussian Mixture Model + 17aa 2247 ThinkPad T570 + 17aa 224f ThinkPad X1 Carbon 5th Gen + 17aa 225d ThinkPad T480 + 1912 HD Graphics 530 + 1916 Skylake GT2 [HD Graphics 520] + 1028 06dc Latitude E7470 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 1918 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + 1919 Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Imaging Unit + 191b HD Graphics 530 + 1028 06e4 XPS 15 9550 + 191d HD Graphics P530 + 191e HD Graphics 515 + 191f Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Host Bridge/DRAM Registers + 1921 HD Graphics 520 + 1926 Iris Graphics 540 + 1927 Iris Graphics 550 + 192b Iris Graphics 555 + 192d Iris Graphics P555 + 1932 Iris Pro Graphics 580 + 193a Iris Pro Graphics P580 + 193b Iris Pro Graphics 580 + 193d Iris Pro Graphics P580 + 1960 80960RP (i960RP) Microprocessor + 101e 0431 MegaRAID 431 RAID Controller + 101e 0438 MegaRAID 438 Ultra2 LVD RAID Controller + 101e 0466 MegaRAID 466 Express Plus RAID Controller + 101e 0467 MegaRAID 467 Enterprise 1500 RAID Controller + 101e 0490 MegaRAID 490 Express 300 RAID Controller + 101e 0762 MegaRAID 762 Express RAID Controller + 101e 09a0 PowerEdge Expandable RAID Controller 2/SC + 1028 0467 PowerEdge Expandable RAID Controller 2/DC + 1028 1111 PowerEdge Expandable RAID Controller 2/SC + 103c 03a2 MegaRAID + 103c 10c6 MegaRAID 438, NetRAID-3Si + 103c 10c7 MegaRAID T5, Integrated NetRAID + 103c 10cc MegaRAID, Integrated NetRAID + 103c 10cd NetRAID-1Si + 105a 0000 SuperTrak + 105a 2168 SuperTrak Pro + 105a 5168 SuperTrak66/100 + 1111 1111 MegaRAID 466, PowerEdge Expandable RAID Controller 2/SC + 1111 1112 PowerEdge Expandable RAID Controller 2/SC + 113c 03a2 MegaRAID + e4bf 1010 CG1-RADIO + e4bf 1020 CU2-QUARTET + e4bf 1040 CU1-CHORUS + e4bf 3100 CX1-BAND + 1962 80960RM (i960RM) Microprocessor + 105a 0000 SuperTrak SX6000 I2O CPU + 1964 80960RN (i960RN) Microprocessor + 1980 Atom Processor C3000 Series System Agent + 19a1 Atom Processor C3000 Series Error Registers + 19a2 Atom Processor C3000 Series Root Complex Event Collector + 19a3 Atom Processor C3000 Series Integrated QAT Root Port + 19a4 Atom Processor C3000 Series PCI Express Root Port #0 + 19a5 Atom Processor C3000 Series PCI Express Root Port #1 + 19a6 Atom Processor C3000 Series PCI Express Root Port #2 + 19a7 Atom Processor C3000 Series PCI Express Root Port #3 + 19a8 Atom Processor C3000 Series PCI Express Root Port #4 + 19a9 Atom Processor C3000 Series PCI Express Root Port #5 + 19aa Atom Processor C3000 Series PCI Express Root Port #6 + 19ab Atom Processor C3000 Series PCI Express Root Port #7 + 19ac Atom Processor C3000 Series SMBus Contoller - Host + 19b0 Atom Processor C3000 Series SATA Controller 0 + 19b1 Atom Processor C3000 Series SATA Controller 0 + 19b2 Atom Processor C3000 Series SATA Controller 0 + 19b3 Atom Processor C3000 Series SATA Controller 0 + 19b4 Atom Processor C3000 Series SATA Controller 0 + 19b5 Atom Processor C3000 Series SATA Controller 0 + 19b6 Atom Processor C3000 Series SATA Controller 0 + 19b7 Atom Processor C3000 Series SATA Controller 0 + 19be Atom Processor C3000 Series SATA Controller 0 + 19bf Atom Processor C3000 Series SATA Controller 0 + 19c0 Atom Processor C3000 Series SATA Controller 1 + 19c1 Atom Processor C3000 Series SATA Controller 1 + 19c2 Atom Processor C3000 Series SATA Controller 1 + 19c3 Atom Processor C3000 Series SATA Controller 1 + 19c4 Atom Processor C3000 Series SATA Controller 1 + 19c5 Atom Processor C3000 Series SATA Controller 1 + 19c6 Atom Processor C3000 Series SATA Controller 1 + 19c7 Atom Processor C3000 Series SATA Controller 1 + 19ce Atom Processor C3000 Series SATA Controller 1 + 19cf Atom Processor C3000 Series SATA Controller 1 + 19d0 Atom Processor C3000 Series USB 3.0 xHCI Controller + 19d1 Atom Processor C3000 Series Integrated LAN Root Port #0 + 19d2 Atom Processor C3000 Series Integrated LAN Root Port #1 + 19d3 Atom Processor C3000 Series ME HECI 1 + 19d4 Atom Processor C3000 Series ME HECI 2 + 19d5 Atom Processor C3000 Series ME KT Controller + 19d6 Atom Processor C3000 Series ME HECI 3 + 19d8 Atom Processor C3000 Series HSUART Controller + 19dc Atom Processor C3000 Series LPC or eSPI + 19dd Atom Processor C3000 Series Primary to Side Band (P2SB) Bridge + 19de Atom Processor C3000 Series Power Management Controller + 19df Atom Processor C3000 Series SMBus controller + 19e0 Atom Processor C3000 Series SPI Controller + 19e2 Atom Processor C3000 Series QuickAssist Technology + 1a1c Ethernet Connection (17) I219-LM + 1a1d Ethernet Connection (17) I219-V + 1a1e Ethernet Connection (16) I219-LM + 1a1f Ethernet Connection (16) I219-V + 1a21 82840 840 [Carmel] Chipset Host Bridge (Hub A) + 1a23 82840 840 [Carmel] Chipset AGP Bridge + 1a24 82840 840 [Carmel] Chipset PCI Bridge (Hub B) + 1a30 82845 845 [Brookdale] Chipset Host Bridge + 1028 010e Optiplex GX240 + 147b 0505 BL7 motherboard + 15d9 3280 Supermicro P4SBE Mainboard + 1a31 82845 845 [Brookdale] Chipset AGP Bridge + 1a38 5000 Series Chipset DMA Engine + 15d9 8680 X7DVL-E-O motherboard + 8086 3476 S5000PSLSATA Server Board + 1a48 82597EX 10GbE Ethernet Controller + 8086 a01f PRO/10GbE SR Server Adapter + 8086 a11f PRO/10GbE SR Server Adapter + 1b48 82597EX 10GbE Ethernet Controller + 8086 a01f PRO/10GbE LR Server Adapter + 8086 a11f PRO/10GbE LR Server Adapter + 1c00 6 Series/C200 Series Chipset Family Desktop SATA Controller (IDE mode, ports 0-3) + 1c01 6 Series/C200 Series Chipset Family Mobile SATA Controller (IDE mode, ports 0-3) + 1c02 6 Series/C200 Series Chipset Family 6 port Desktop SATA AHCI Controller + 1028 04aa XPS 8300 + 1043 844d P8 series motherboard + 8086 7270 Server Board S1200BT Family + 1c03 6 Series/C200 Series Chipset Family 6 port Mobile SATA AHCI Controller + 1028 04a3 Precision M4600 + 1028 04b2 Vostro 3350 + 1028 04da Vostro 3750 + 17aa 21cf ThinkPad T520 + 8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011] + 1c04 6 Series/C200 Series Desktop SATA RAID Controller + 103c 3118 Smart Array B110i SATA RAID Controller + 1c05 6 Series/C200 Series Mobile SATA RAID Controller + 1c06 Z68 Express Chipset SATA RAID Controller + 1c08 6 Series/C200 Series Chipset Family Desktop SATA Controller (IDE mode, ports 4-5) + 1c09 6 Series/C200 Series Chipset Family Mobile SATA Controller (IDE mode, ports 4-5) + 1c10 6 Series/C200 Series Chipset Family PCI Express Root Port 1 + 1028 04aa XPS 8300 + 1028 04da Vostro 3750 + 1043 844d P8 series motherboard + 17aa 21cf ThinkPad T520 + 8086 7270 Server Board S1200BTS / Apple MacBook Pro 8,1/8,2 + 1c12 6 Series/C200 Series Chipset Family PCI Express Root Port 2 + 1028 04aa XPS 8300 + 17aa 21cf ThinkPad T520 + 8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011] + 1c14 6 Series/C200 Series Chipset Family PCI Express Root Port 3 + 1028 04da Vostro 3750 + 8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011] + 1c16 6 Series/C200 Series Chipset Family PCI Express Root Port 4 + 1028 04aa XPS 8300 + 17aa 21cf ThinkPad T520 + 1c18 6 Series/C200 Series Chipset Family PCI Express Root Port 5 + 1028 04da Vostro 3750 + 17aa 21cf ThinkPad T520 + 8086 7270 Server Board S1200BTS + 1c1a 6 Series/C200 Series Chipset Family PCI Express Root Port 6 + 1028 04da Vostro 3750 + 1043 844d P8 series motherboard + 1c1c 6 Series/C200 Series Chipset Family PCI Express Root Port 7 + 1c1e 6 Series/C200 Series Chipset Family PCI Express Root Port 8 + 1043 844d P8 series motherboard + 1c20 6 Series/C200 Series Chipset Family High Definition Audio Controller + 1028 0490 Alienware M17x R3 + 1028 04a3 Precision M4600 + 1028 04aa XPS 8300 + 1028 04b2 Vostro 3350 + 1028 04da Vostro 3750 + 1043 8418 P8P67 Deluxe Motherboard + 1043 841b P8H67 Series Motherboard + 17aa 21cf ThinkPad T520 +# Realtek ALC888 audio codec + 8086 2008 DQ67SW board + 8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011] + 1c22 6 Series/C200 Series Chipset Family SMBus Controller + 1028 04a3 Precision M4600 + 1028 04aa XPS 8300 + 1028 04b2 Vostro 3350 + 1028 04da Vostro 3750 + 1043 844d P8 series motherboard + 17aa 21cf ThinkPad T520 + 8086 7270 Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2 + 1c24 6 Series/C200 Series Chipset Family Thermal Management Controller + 1c25 6 Series/C200 Series Chipset Family DMI to PCI Bridge + 1c26 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 + 1028 04a3 Precision M4600 + 1028 04aa XPS 8300 + 1028 04b2 Vostro 3350 + 1028 04da Vostro 3750 + 1043 844d P8 series motherboard + 17aa 21cf ThinkPad T520 + 8086 7270 Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2 + 1c27 6 Series/C200 Series Chipset Family USB Universal Host Controller #1 + 8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011] + 1c2c 6 Series/C200 Series Chipset Family USB Universal Host Controller #5 + 8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011] + 1c2d 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 + 1028 04a3 Precision M4600 + 1028 04aa XPS 8300 + 1028 04b2 Vostro 3350 + 1028 04da Vostro 3750 + 1043 844d P8 series motherboard + 17aa 21cf ThinkPad T520 + 8086 7270 Server Board S1200BT Family / Apple MacBook Pro 8,1/8,2 + 1c33 6 Series/C200 Series Chipset Family LAN Controller + 1c35 6 Series/C200 Series Chipset Family VECI Controller + 1c3a 6 Series/C200 Series Chipset Family MEI Controller #1 + 1028 04a3 Precision M4600 + 1028 04aa XPS 8300 + 1028 04b2 Vostro 3350 + 1028 04da Vostro 3750 + 1043 844d P8 series motherboard + 17aa 21cf ThinkPad T520 + 8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011] + 1c3b 6 Series/C200 Series Chipset Family MEI Controller #2 + 1c3c 6 Series/C200 Series Chipset Family IDE-r Controller + 1c3d 6 Series/C200 Series Chipset Family KT Controller + 1c40 6 Series/C200 Series Chipset Family LPC Controller + 1c41 Mobile SFF 6 Series Chipset Family LPC Controller + 1c42 6 Series/C200 Series Chipset Family LPC Controller + 1c43 Mobile 6 Series Chipset Family LPC Controller + 1c44 Z68 Express Chipset LPC Controller + 1c45 6 Series/C200 Series Chipset Family LPC Controller + 1c46 P67 Express Chipset LPC Controller + 1043 844d P8P67 Deluxe Motherboard + 1c47 UM67 Express Chipset LPC Controller + 1c48 6 Series/C200 Series Chipset Family LPC Controller + 1c49 HM65 Express Chipset LPC Controller + 8086 7270 Apple MacBookPro8,2 [Core i7, 15", 2011] + 1c4a H67 Express Chipset LPC Controller + 1028 04aa XPS 8300 + 1043 844d P8H67 Series Motherboard + 1c4b HM67 Express Chipset LPC Controller + 1028 04b2 Vostro 3350 + 1028 04da Vostro 3750 + 1c4c Q65 Express Chipset LPC Controller + 1c4d QS67 Express Chipset LPC Controller + 1c4e Q67 Express Chipset LPC Controller + 1c4f QM67 Express Chipset LPC Controller + 1028 04a3 Precision M4600 + 17aa 21cf ThinkPad T520 + 1c50 B65 Express Chipset LPC Controller + 1c51 6 Series/C200 Series Chipset Family LPC Controller + 1c52 C202 Chipset LPC Controller + 8086 7270 Server Board S1200BTS + 1c53 6 Series/C200 Series Chipset Family LPC Controller + 1c54 C204 Chipset LPC Controller + 1c55 6 Series/C200 Series Chipset Family LPC Controller + 1c56 C206 Chipset LPC Controller + 1043 844d P8B WS Motherboard + 1c57 6 Series/C200 Series Chipset Family LPC Controller + 1c58 Upgraded B65 Express Chipset LPC Controller + 1c59 Upgraded HM67 Express Chipset LPC Controller + 1c5a Upgraded Q67 Express Chipset LPC Controller + 1c5b 6 Series/C200 Series Chipset Family LPC Controller + 1c5c H61 Express Chipset LPC Controller + 1c5d 6 Series/C200 Series Chipset Family LPC Controller + 1c5e 6 Series/C200 Series Chipset Family LPC Controller + 1c5f 6 Series/C200 Series Chipset Family LPC Controller + 1d00 C600/X79 series chipset 4-Port SATA IDE Controller + 1d02 C600/X79 series chipset 6-Port SATA AHCI Controller + 1028 04f7 C602J on PowerEdge R320 server + 1d04 C600/X79 series chipset SATA RAID Controller + 1d06 C600/X79 series chipset SATA Premium RAID Controller + 1d08 C600/X79 series chipset 2-Port SATA IDE Controller + 1d10 C600/X79 series chipset PCI Express Root Port 1 + 1028 04f7 C602J on PowerEdge R320 server + 1d11 C600/X79 series chipset PCI Express Root Port 1 + 1d12 C600/X79 series chipset PCI Express Root Port 2 + 1d13 C600/X79 series chipset PCI Express Root Port 2 + 1d14 C600/X79 series chipset PCI Express Root Port 3 + 1d15 C600/X79 series chipset PCI Express Root Port 3 + 1d16 C600/X79 series chipset PCI Express Root Port 4 + 1d17 C600/X79 series chipset PCI Express Root Port 4 + 1d18 C600/X79 series chipset PCI Express Root Port 5 + 1028 04f7 C602J on PowerEdge R320 server + 1d19 C600/X79 series chipset PCI Express Root Port 5 + 1d1a C600/X79 series chipset PCI Express Root Port 6 + 1d1b C600/X79 series chipset PCI Express Root Port 6 + 1d1c C600/X79 series chipset PCI Express Root Port 7 + 1d1d C600/X79 series chipset PCI Express Root Port 7 + 1d1e C600/X79 series chipset PCI Express Root Port 8 + 1028 04f7 C602J on PowerEdge R320 server + 1d1f C600/X79 series chipset PCI Express Root Port 8 + 1d20 C600/X79 series chipset High Definition Audio Controller + 1d22 C600/X79 series chipset SMBus Host Controller + 15d9 066b X9SRL-F + 1d24 C600/X79 series chipset Thermal Management Controller + 15d9 066b X9SRL-F + 1d25 C600/X79 series chipset DMI to PCI Bridge + 1d26 C600/X79 series chipset USB2 Enhanced Host Controller #1 + 1028 04f7 C602J on PowerEdge R320 server + 15d9 066b X9SRL-F + 1d2d C600/X79 series chipset USB2 Enhanced Host Controller #2 + 1028 04f7 C602J on PowerEdge R320 server + 15d9 066b X9SRL-F + 1d33 C600/X79 series chipset LAN Controller + 1d35 C600/X79 series chipset VECI Controller + 1d3a C600/X79 series chipset MEI Controller #1 + 1028 04f7 C602J on PowerEdge R320 server + 15d9 066b X9SRL-F + 1d3b C600/X79 series chipset MEI Controller #2 + 1028 04f7 C602J on PowerEdge R320 server + 15d9 066b X9SRL-F + 1d3c C600/X79 series chipset IDE-r Controller + 1d3d C600/X79 series chipset KT Controller + 1d3e C600/X79 series chipset PCI Express Virtual Root Port + 1028 04f7 C602J on PowerEdge R320 server + 1d3f C608/C606/X79 series chipset PCI Express Virtual Switch Port + 1d40 C600/X79 series chipset LPC Controller + 1d41 C600/X79 series chipset LPC Controller + 1028 04f7 C602J on PowerEdge R320 server + 15d9 066b X9SRL-F + 1d50 C608 chipset Dual 4-Port SATA/SAS Storage Control Unit + 1d54 C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit + 1d55 C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit + 1d58 C606 chipset Dual 4-Port SATA/SAS Storage Control Unit + 1d59 C604/X79 series chipset 4-Port SATA/SAS Storage Control Unit + 1d5a C600/X79 series chipset Dual 4-Port SATA Storage Control Unit + 1d5b C602 chipset 4-Port SATA Storage Control Unit + 1d5c C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit + 1d5d C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit + 1d5e C600/X79 series chipset Dual 4-Port SATA Storage Control Unit + 1d5f C600/X79 series chipset 4-Port SATA Storage Control Unit + 1d60 C608 chipset Dual 4-Port SATA/SAS Storage Control Unit + 1d64 C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit + 1d65 C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit + 1d68 C606 chipset Dual 4-Port SATA/SAS Storage Control Unit + 1d69 C604/X79 series chipset 4-Port SATA/SAS Storage Control Unit + 1d6a C600/X79 series chipset Dual 4-Port SATA Storage Control Unit + 1d6b C602 chipset 4-Port SATA Storage Control Unit + 0497 1028 Dell Precision T3600 + 1d6c C600/X79 series chipset Dual 4-Port SATA/SAS Storage Control Unit + 1d6d C600/X79 series chipset 4-Port SATA/SAS Storage Control Unit + 1d6e C600/X79 series chipset Dual 4-Port SATA Storage Control Unit + 1d6f C600/X79 series chipset 4-Port SATA Storage Control Unit + 1d70 C600/X79 series chipset SMBus Controller 0 + 1d71 C608/C606/X79 series chipset SMBus Controller 1 + 1d72 C608 chipset SMBus Controller 2 + 1d74 C608/C606/X79 series chipset PCI Express Upstream Port + 1d76 C600/X79 series chipset Multi-Function Glue + 1e00 7 Series/C210 Series Chipset Family 4-port SATA Controller [IDE mode] + 1e01 7 Series Chipset Family 4-port SATA Controller [IDE mode] + 144d c652 NP300E5C series laptop + 1e02 7 Series/C210 Series Chipset Family 6-port SATA Controller [AHCI mode] + 1043 84ca P8 series motherboard + 1849 1e02 Motherboard + 1e03 7 Series Chipset Family 6-port SATA Controller [AHCI mode] + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 10cf 16e2 LIFEBOOK E752 + 144d c652 NP300E5C series laptop + 1e04 7 Series/C210 Series Chipset Family SATA Controller [RAID mode] + 1e05 7 Series Chipset SATA Controller [RAID mode] + 1e06 7 Series/C210 Series Chipset Family SATA Controller [RAID mode] + 1e07 7 Series Chipset Family SATA Controller [RAID mode] + 1e08 7 Series/C210 Series Chipset Family 2-port SATA Controller [IDE mode] + 1e09 7 Series Chipset Family 2-port SATA Controller [IDE mode] + 144d c652 NP300E5C series laptop + 1e0e 7 Series/C210 Series Chipset Family SATA Controller [RAID mode] + 1e10 7 Series/C216 Chipset Family PCI Express Root Port 1 + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 1043 84ca P8H77-I Motherboard + 10cf 16e9 LIFEBOOK E752 + 144d c652 NP300E5C series laptop + 1849 1e10 Motherboard + 1e12 7 Series/C210 Series Chipset Family PCI Express Root Port 2 + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 1e14 7 Series/C210 Series Chipset Family PCI Express Root Port 3 + 10cf 16e9 LIFEBOOK E752 + 1e16 7 Series/C216 Chipset Family PCI Express Root Port 4 + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 144d c652 NP300E5C series laptop + 1849 1618 Z77 Extreme4 motherboard + 1e18 7 Series/C210 Series Chipset Family PCI Express Root Port 5 + 1043 84ca P8H77-I Motherboard + 1849 1e18 Motherboard + 1e1a 7 Series/C210 Series Chipset Family PCI Express Root Port 6 + 1849 1e1a Motherboard + 1e1c 7 Series/C210 Series Chipset Family PCI Express Root Port 7 + 1e1e 7 Series/C210 Series Chipset Family PCI Express Root Port 8 + 10cf 16e9 LIFEBOOK E752 + 1849 1e1e Motherboard + 1e20 7 Series/C216 Chipset Family High Definition Audio Controller + 1028 054b XPS One 2710 + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 1043 8415 P8H77-I Motherboard + 1043 8445 P8Z77-V LX Motherboard + 10cf 1757 LIFEBOOK E752 + 144d c652 NP300E5C series laptop + 1849 1898 Z77 Extreme4 motherboard + 1e22 7 Series/C216 Chipset Family SMBus Controller + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 1043 84ca P8 series motherboard + 10cf 16e6 LIFEBOOK E752 + 144d c652 NP300E5C series laptop + 1849 1e22 Motherboard + 1e24 7 Series/C210 Series Chipset Family Thermal Management Controller + 1043 1517 Zenbook Prime UX31A + 1e25 7 Series/C210 Series Chipset Family DMI to PCI Bridge + 1e26 7 Series/C216 Chipset Family USB Enhanced Host Controller #1 + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 1043 84ca P8 series motherboard + 10cf 16e8 LIFEBOOK E752 + 144d c652 NP300E5C series laptop + 1849 1e26 Motherboard + 1e2d 7 Series/C216 Chipset Family USB Enhanced Host Controller #2 + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 1043 84ca P8 series motherboard + 10cf 16e8 LIFEBOOK E752 + 144d c652 NP300E5C series laptop + 1849 1e2d Motherboard + 1e31 7 Series/C210 Series Chipset Family USB xHCI Host Controller + 103c 179b Elitebook 8470p + 103c 17ab ProBook 6570b + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 1043 84ca P8 series motherboard + 10cf 16ee LIFEBOOK E752 + 17aa 21f3 ThinkPad T430 + 1849 1e31 Motherboard + 1e33 7 Series/C210 Series Chipset Family LAN Controller + 1e3a 7 Series/C216 Chipset Family MEI Controller #1 + 1043 108d VivoBook X202EV + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 1043 84ca P8 series motherboard + 10cf 16ea LIFEBOOK E752 + 144d c652 NP300E5C series laptop + 1849 1e3a Motherboard + 1e3b 7 Series/C210 Series Chipset Family MEI Controller #2 + 1e3c 7 Series/C210 Series Chipset Family IDE-r Controller + 1e3d 7 Series/C210 Series Chipset Family KT Controller + 1e41 7 Series Chipset Family LPC Controller + 1e42 7 Series Chipset Family LPC Controller + 1e43 7 Series Chipset Family LPC Controller + 1e44 Z77 Express Chipset LPC Controller + 1043 84ca P8 series motherboard + 1849 1e44 Motherboard + 1e45 7 Series Chipset Family LPC Controller + 1e46 Z75 Express Chipset LPC Controller + 1e47 Q77 Express Chipset LPC Controller + 1e48 Q75 Express Chipset LPC Controller + 1e49 B75 Express Chipset LPC Controller + 1e4a H77 Express Chipset LPC Controller + 1043 84ca P8H77-I Motherboard + 1e4b 7 Series Chipset Family LPC Controller + 1e4c 7 Series Chipset Family LPC Controller + 1e4d 7 Series Chipset Family LPC Controller + 1e4e 7 Series Chipset Family LPC Controller + 1e4f 7 Series Chipset Family LPC Controller + 1e50 7 Series Chipset Family LPC Controller + 1e51 7 Series Chipset Family LPC Controller + 1e52 7 Series Chipset Family LPC Controller + 1e53 C216 Series Chipset LPC Controller + 1e54 7 Series Chipset Family LPC Controller + 1e55 QM77 Express Chipset LPC Controller + 1e56 QS77 Express Chipset LPC Controller + 1e57 HM77 Express Chipset LPC Controller + 1e58 UM77 Express Chipset LPC Controller + 1e59 HM76 Express Chipset LPC Controller + 1043 1477 N56VZ + 1043 1517 Zenbook Prime UX31A + 10cf 16e0 LIFEBOOK E752 + 1e5a 7 Series Chipset Family LPC Controller + 1e5b UM77 Express Chipset LPC Controller + 1e5c 7 Series Chipset Family LPC Controller + 1e5d HM75 Express Chipset LPC Controller + 144d c652 NP300E5C series laptop + 1e5e HM70 Express Chipset LPC Controller + 1043 108d VivoBook X202EV + 1e5f NM70 Express Chipset LPC Controller + 1f00 Atom processor C2000 SoC Transaction Router + 1f01 Atom processor C2000 SoC Transaction Router + 1f02 Atom processor C2000 SoC Transaction Router + 1f03 Atom processor C2000 SoC Transaction Router + 1f04 Atom processor C2000 SoC Transaction Router + 1f05 Atom processor C2000 SoC Transaction Router + 1f06 Atom processor C2000 SoC Transaction Router + 1f07 Atom processor C2000 SoC Transaction Router + 1f08 Atom processor C2000 SoC Transaction Router + 1f09 Atom processor C2000 SoC Transaction Router + 1f0a Atom processor C2000 SoC Transaction Router + 1f0b Atom processor C2000 SoC Transaction Router + 1f0c Atom processor C2000 SoC Transaction Router + 1f0d Atom processor C2000 SoC Transaction Router + 1f0e Atom processor C2000 SoC Transaction Router + 1f0f Atom processor C2000 SoC Transaction Router + 1f10 Atom processor C2000 PCIe Root Port 1 + 1f11 Atom processor C2000 PCIe Root Port 2 + 1f12 Atom processor C2000 PCIe Root Port 3 + 1f13 Atom processor C2000 PCIe Root Port 4 + 1f14 Atom processor C2000 RAS + 1f15 Atom processor C2000 SMBus 2.0 + 1f16 Atom processor C2000 RCEC + 1f18 Atom processor C2000 QAT + 1f19 Atom processor C2000 QAT + 1f20 Atom processor C2000 4-Port IDE SATA2 Controller + 1f21 Atom processor C2000 4-Port IDE SATA2 Controller + 1f22 Atom processor C2000 AHCI SATA2 Controller + 1f23 Atom processor C2000 AHCI SATA2 Controller + 1f24 Atom processor C2000 RAID SATA2 Controller + 1f25 Atom processor C2000 RAID SATA2 Controller + 1f26 Atom processor C2000 RAID SATA2 Controller + 1f27 Atom processor C2000 RAID SATA2 Controller + 1f2c Atom processor C2000 USB Enhanced Host Controller + 1f2e Atom processor C2000 RAID SATA2 Controller + 1f2f Atom processor C2000 RAID SATA2 Controller + 1f30 Atom processor C2000 2-Port IDE SATA3 Controller + 1f31 Atom processor C2000 2-Port IDE SATA3 Controller + 1f32 Atom processor C2000 AHCI SATA3 Controller + 1f33 Atom processor C2000 AHCI SATA3 Controller + 1f34 Atom processor C2000 RAID SATA3 Controller + 1f35 Atom processor C2000 RAID SATA3 Controller + 1f36 Atom processor C2000 RAID SATA3 Controller + 1f37 Atom processor C2000 RAID SATA3 Controller + 1f38 Atom processor C2000 PCU + 1f39 Atom processor C2000 PCU + 1f3a Atom processor C2000 PCU + 1f3b Atom processor C2000 PCU + 1f3c Atom processor C2000 PCU SMBus + 1f3d Atom Processor C2000 PECI SMBus + 1f3e Atom processor C2000 RAID SATA3 Controller + 1f3f Atom processor C2000 RAID SATA3 Controller + 1f40 Ethernet Connection I354 1.0 GbE Backplane + 1028 05f1 Ethernet Connection I354 1.0 GbE Backplane + 1f41 Ethernet Connection I354 + 1f42 Atom processor C2000 GbE + 1f44 Atom processor C2000 GbE Virtual Function + 1f45 Ethernet Connection I354 2.5 GbE Backplane + 2014 Sky Lake-E Ubox Registers + 2015 Sky Lake-E Ubox Registers + 2016 Sky Lake-E Ubox Registers + 2018 Sky Lake-E M2PCI Registers + 201a Sky Lake-E Non-Transparent Bridge Registers + 201c Sky Lake-E Non-Transparent Bridge Registers + 201d Volume Management Device NVMe RAID Controller + 2020 Sky Lake-E DMI3 Registers + 15d9 095d X11SPM-TF + 2021 Sky Lake-E CBDMA Registers + 2024 Sky Lake-E MM/Vt-d Configuration Registers + 2025 Sky Lake-E RAS + 2026 Sky Lake-E IOAPIC + 2030 Sky Lake-E PCI Express Root Port A + 2031 Sky Lake-E PCI Express Root Port B + 2032 Sky Lake-E PCI Express Root Port C + 2033 Sky Lake-E PCI Express Root Port D + 2034 Sky Lake-E VT-d + 2035 Sky Lake-E RAS Configuration Registers + 2036 Sky Lake-E IOxAPIC Configuration Registers + 2040 Sky Lake-E Integrated Memory Controller + 2041 Sky Lake-E Integrated Memory Controller + 2042 Sky Lake-E Integrated Memory Controller + 2043 Sky Lake-E Integrated Memory Controller + 2044 Sky Lake-E Integrated Memory Controller + 2045 Sky Lake-E LM Channel 1 + 2046 Sky Lake-E LMS Channel 1 + 2047 Sky Lake-E LMDP Channel 1 + 2048 Sky Lake-E DECS Channel 2 + 2049 Sky Lake-E LM Channel 2 + 204a Sky Lake-E LMS Channel 2 + 204b Sky Lake-E LMDP Channel 2 + 204c Sky Lake-E M3KTI Registers + 204d Sky Lake-E M3KTI Registers + 204e Sky Lake-E M3KTI Registers + 2054 Sky Lake-E CHA Registers + 2055 Sky Lake-E CHA Registers + 2056 Sky Lake-E CHA Registers + 2057 Sky Lake-E CHA Registers + 2058 Sky Lake-E KTI 0 + 2059 Sky Lake-E UPI Registers + 2066 Sky Lake-E Integrated Memory Controller + 2068 Sky Lake-E DDRIO Registers + 2069 Sky Lake-E DDRIO Registers + 206a Sky Lake-E IOxAPIC Configuration Registers + 206e Sky Lake-E DDRIO Registers + 206f Sky Lake-E DDRIO Registers + 2078 Sky Lake-E PCU Registers + 207a Sky Lake-E PCU Registers + 2080 Sky Lake-E PCU Registers + 2081 Sky Lake-E PCU Registers + 2082 Sky Lake-E PCU Registers + 2083 Sky Lake-E PCU Registers + 2084 Sky Lake-E PCU Registers + 2085 Sky Lake-E PCU Registers + 2086 Sky Lake-E PCU Registers + 2088 Sky Lake-E DDRIO Registers + 208d Sky Lake-E CHA Registers + 208e Sky Lake-E CHA Registers + 2241 Larrabee + 2250 Xeon Phi coprocessor 5100 series + 225c Xeon Phi coprocessor SE10/7120 series + 225d Xeon Phi coprocessor 3120 series + 225e Xeon Phi coprocessor 31S1 + 2262 Xeon Phi coprocessor 7220 + 2280 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SoC Transaction Register + 2284 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series High Definition Audio Controller + 2286 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO1 DMA Controller + 228a Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO1 HSUART Controller #1 + 228c Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO1 HSUART Controller #2 + 2292 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx SMBus Controller + 2294 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series MMC Controller + 2295 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SDIO Controller + 2296 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SD Controller + 2298 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Trusted Execution Engine + 229c Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCU + 22a3 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SATA Controller + 22a4 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series SATA AHCI Controller + 22a8 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Low Power Engine Audio + 22b0 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Integrated Graphics Controller + 22b1 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Integrated Graphics Controller + 22b5 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series USB xHCI Controller + 22b8 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Imaging Unit + 22c0 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 DMA Controller + 22c1 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #1 + 22c2 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #2 + 22c3 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #3 + 22c4 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #4 + 22c5 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #5 + 22c6 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #6 + 22c7 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series LPIO2 I2C Controller #7 + 22c8 Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCI Express Port #1 + 22ca Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCI Express Port #2 + 22cc Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCI Express Port #3 + 22ce Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series PCI Express Port #4 + 22dc Atom/Celeron/Pentium Processor x5-E8000/J3xxx/N3xxx Series Power Management Controller + 2310 DH89xxCC LPC Controller + 2323 DH89xxCC 4 Port SATA AHCI Controller + 2330 DH89xxCC SMBus Controller + 2331 DH89xxCC Chap Counter + 2332 DH89xxCC Thermal Subsystem + 2334 DH89xxCC USB2 Enhanced Host Controller #1 + 2335 DH89xxCC USB2 Enhanced Host Controller #1 + 2342 DH89xxCC PCI Express Root Port #1 + 2343 DH89xxCC PCI Express Root Port #1 + 2344 DH89xxCC PCI Express Root Port #2 + 2345 DH89xxCC PCI Express Root Port #2 + 2346 DH89xxCC PCI Express Root Port #3 + 2347 DH89xxCC PCI Express Root Port #3 + 2348 DH89xxCC PCI Express Root Port #4 + 2349 DH89xxCC PCI Express Root Port #4 + 2360 DH89xxCC Watchdog Timer + 2364 DH89xxCC MEI 0 + 2365 DH89xxCC MEI 1 + 2390 DH895XCC Series LPC Controller + 23a1 DH895XCC Series 2-Port SATA Controller [IDE Mode] + 23a3 DH895XCC Series 4-Port SATA Controller [AHCI Mode] + 23a6 DH895XCC Series 2-Port SATA Controller [IDE Mode] + 23b0 DH895XCC Series SMBus Controller + 23b1 DH895XCC Series CHAP Counter + 23b2 DH895XCC Series Thermal Management Controller + 23b4 DH895XCC Series USB2 Enhanced Host Controller #1 + 23b5 DH895XCC Series USB2 Enhanced Host Controller #1 + 23c2 DH895XCC Series PCI Express Root Port #1 + 23c3 DH895XCC Series PCI Express Root Port #1 + 23c4 DH895XCC Series PCI Express Root Port #2 + 23c5 DH895XCC Series PCI Express Root Port #2 + 23c6 CDH895XCC Series PCI Express Root Port #3 + 23c7 DH895XCC Series PCI Express Root Port #3 + 23c8 DH895XCC Series PCI Express Root Port #4 + 23c9 DH895XCC Series PCI Express Root Port #4 + 23e0 DH895XCC Series Watchdog Timer + 23e4 DH895XCC Series MEI Controller #1 + 23e5 DH895XCC Series MEI Controller #2 + 2410 82801AA ISA Bridge (LPC) + 2411 82801AA IDE Controller + 2412 82801AA USB Controller + 2413 82801AA SMBus Controller + 2415 82801AA AC'97 Audio Controller + 1028 0095 Precision Workstation 220 Integrated Digital Audio + 1028 00b4 OptiPlex GX110 + 110a 0051 Activy 2xx + 11d4 0040 SoundMAX Integrated Digital Audio + 11d4 0048 SoundMAX Integrated Digital Audio + 11d4 5340 SoundMAX Integrated Digital Audio + 1734 1025 Activy 3xx + 1af4 1100 QEMU Virtual Machine + 2416 82801AA AC'97 Modem Controller + 2418 82801AA PCI Bridge + 2420 82801AB ISA Bridge (LPC) + 2421 82801AB IDE Controller + 2422 82801AB USB Controller + 2423 82801AB SMBus Controller + 2425 82801AB AC'97 Audio Controller + 11d4 0040 SoundMAX Integrated Digital Audio + 11d4 0048 SoundMAX Integrated Digital Audio + 2426 82801AB AC'97 Modem Controller + 2428 82801AB PCI Bridge + 2440 82801BA ISA Bridge (LPC) + 8086 5744 S845WD1-E + 2442 82801BA/BAM UHCI USB 1.1 Controller #1 + 1014 01c6 Netvista A40/A40p + 1025 1016 Travelmate 612 TX + 1028 00c7 Dimension 8100 + 1028 00d8 Precision 530 + 1028 010e Optiplex GX240 + 103c 126f e-pc 40 + 1043 8027 TUSL2-C Mainboard + 104d 80df Vaio PCG-FX403 + 147b 0505 BL7 motherboard + 147b 0507 TH7II-RAID + 8086 4532 Desktop Board D815EEA2/D815EFV + 8086 4557 D815EGEW Mainboard + 8086 5744 S845WD1-E mainboard + 2443 82801BA/BAM SMBus Controller + 1014 01c6 Netvista A40/A40p + 1025 1016 Travelmate 612 TX + 1028 00c7 Dimension 8100 + 1028 00d8 Precision 530 + 1028 010e Optiplex GX240 + 103c 126f e-pc 40 + 1043 8027 TUSL2-C Mainboard + 104d 80df Vaio PCG-FX403 + 147b 0505 BL7 motherboard + 147b 0507 TH7II-RAID + 15d9 3280 Supermicro P4SBE Mainboard + 8086 4532 Desktop Board D815EEA2/D815EFV + 8086 4557 D815EGEW Mainboard + 8086 5744 S845WD1-E mainboard + 2444 82801BA/BAM UHCI USB 1.1 Controller #2 + 1025 1016 Travelmate 612 TX + 1028 00c7 Dimension 8100 + 1028 00d8 Precision 530 + 1028 010e Optiplex GX240 + 103c 126f e-pc 40 + 1043 8027 TUSL2-C Mainboard + 104d 80df Vaio PCG-FX403 + 147b 0505 BL7 motherboard + 147b 0507 TH7II-RAID + 8086 4532 Desktop Board D815EEA2/D815EFV + 8086 5744 S845WD1-E mainboard + 2445 82801BA/BAM AC'97 Audio Controller + 0e11 000b Compaq Deskpro EN Audio + 0e11 0088 Evo D500 + 1014 01c6 Netvista A40/A40p + 1025 1016 Travelmate 612 TX + 1028 00d8 Precision 530 + 103c 126f e-pc 40 + 104d 80df Vaio PCG-FX403 + 1462 3370 STAC9721 AC + 147b 0505 BL7 motherboard + 147b 0507 TH7II-RAID + 8086 4557 D815EGEW Mainboard + 8086 4656 Desktop Board D815EFV + 2446 82801BA/BAM AC'97 Modem Controller + 1025 1016 Travelmate 612 TX + 104d 80df Vaio PCG-FX403 + 2448 82801 Mobile PCI Bridge + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 103c 0934 Compaq nw8240 Mobile Workstation + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 103c 309f Compaq nx9420 Notebook + 103c 30a3 Compaq nw8440 + 103c 30c1 Compaq 6910p + 1043 1017 X58LE + 104d 902d VAIO VGN-NR120E + 105b 0d7c D270S/D250S Motherboard + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 144d c00c P30 notebook + 144d c06a R730 Laptop + 144d c072 Notebook N150P + 1458 5000 GA-D525TUD + 1734 1055 Amilo M1420 + 17aa 2013 ThinkPad R60e + 17aa 20ae ThinkPad T61/R61 + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + 8086 544b Desktop Board D425KT + e4bf cc47 CCG-RUMBA + 2449 82801BA/BAM/CA/CAM Ethernet Controller + 0e11 0012 EtherExpress PRO/100 VM + 0e11 0091 EtherExpress PRO/100 VE + 1014 01ce EtherExpress PRO/100 VE + 1014 01dc EtherExpress PRO/100 VE + 1014 01eb EtherExpress PRO/100 VE + 1014 01ec EtherExpress PRO/100 VE + 1014 0202 EtherExpress PRO/100 VE + 1014 0205 EtherExpress PRO/100 VE + 1014 0217 EtherExpress PRO/100 VE + 1014 0234 EtherExpress PRO/100 VE + 1014 023d EtherExpress PRO/100 VE + 1014 0244 EtherExpress PRO/100 VE + 1014 0245 EtherExpress PRO/100 VE + 1014 0265 PRO/100 VE Desktop Connection + 1014 0267 PRO/100 VE Desktop Connection + 1014 026a PRO/100 VE Desktop Connection + 109f 315d EtherExpress PRO/100 VE + 109f 3181 EtherExpress PRO/100 VE + 1179 ff01 PRO/100 VE Network Connection + 1186 7801 EtherExpress PRO/100 VE + 144d 2602 HomePNA 1M CNR + 1af4 1100 QEMU Virtual Machine + 8086 3010 EtherExpress PRO/100 VE + 8086 3011 EtherExpress PRO/100 VM + 8086 3012 82562EH based Phoneline + 8086 3013 EtherExpress PRO/100 VE + 8086 3014 EtherExpress PRO/100 VM + 8086 3015 82562EH based Phoneline + 8086 3016 EtherExpress PRO/100 P Mobile Combo + 8086 3017 EtherExpress PRO/100 P Mobile + 8086 3018 EtherExpress PRO/100 + 244a 82801BAM IDE U100 Controller + 1025 1016 Travelmate 612TX + 104d 80df Vaio PCG-FX403 + 244b 82801BA IDE U100 Controller + 1014 01c6 Netvista A40/A40p + 1028 00c7 Dimension 8100 + 1028 00d8 Precision 530 + 1028 010e Optiplex GX240 + 103c 126f e-pc 40 + 1043 8027 TUSL2-C Mainboard + 147b 0505 BL7 motherboard + 147b 0507 TH7II-RAID + 15d9 3280 Supermicro P4SBE Mainboard + 8086 4532 Desktop Board D815EEA2/D815EFV + 8086 4557 D815EGEW Mainboard + 8086 5744 S845WD1-E mainboard + 244c 82801BAM ISA Bridge (LPC) + 244e 82801 PCI Bridge + 1014 0267 NetVista A30p + 1028 020d Inspiron 530 + 1028 0211 Optiplex 755 + 1028 02da OptiPlex 980 + 1028 04f7 PowerEdge R320 server + 103c 2a3b Pavilion A1512X + 103c 2a6f Asus IPIBL-LB Motherboard + 103c 31fe ProLiant DL140 G3 + 103c 330b ProLiant ML150 G6 Server +# same ID possibly also on other ASUS boards + 1043 8277 P5K PRO Motherboard + 1043 844d P8 series motherboard + 1043 8534 ASUS B85-PLUS + 1458 5000 Motherboard + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7418 Wind PC MS-7418 + 15d9 060d C7SIM-Q Motherboard + 15d9 9680 X7DBN Motherboard + 1775 11cc CC11/CL11 + 8086 7270 Server Board S1200BTS + 2450 82801E ISA Bridge (LPC) + 2452 82801E USB Controller + 2453 82801E SMBus Controller + 2459 82801E Ethernet Controller 0 + 245b 82801E IDE U100 Controller + 245d 82801E Ethernet Controller 1 + 245e 82801E PCI Bridge + 2480 82801CA LPC Interface Controller + 2482 82801CA/CAM USB Controller #1 + 0e11 0030 Evo N600c + 1014 0220 ThinkPad A/T/X Series + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 8086 3424 SE7501HG2 Mainboard + 8086 4541 Latitude C640 + 2483 82801CA/CAM SMBus Controller + 1014 0220 ThinkPad A/T/X Series + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 2484 82801CA/CAM USB Controller #2 + 0e11 0030 Evo N600c + 1014 0220 ThinkPad A/T/X Series + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 2485 82801CA/CAM AC'97 Audio Controller + 1013 5959 Crystal WMD Audio Codec + 1014 0222 ThinkPad A30/A30p/T23 + 1014 0508 ThinkPad T30 + 1014 051c ThinkPad A/T/X Series + 1043 1583 L3C (SPDIF) + 1043 1623 L2B (no SPDIF) + 1043 1643 L3F + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 144d c006 vpr Matrix 170B4 + 2486 82801CA/CAM AC'97 Modem Controller + 1014 0223 ThinkPad A/T/X Series + 1014 0503 ThinkPad R31 + 1014 051a ThinkPad A/T/X Series + 101f 1025 620 Series + 1043 1496 PCtel HSP56 MR + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 134d 4c21 Dell Inspiron 2100 internal modem + 144d 2115 vpr Matrix 170B4 internal modem + 14f1 5421 MD56ORD V.92 MDC Modem + 2487 82801CA/CAM USB Controller #3 + 0e11 0030 Evo N600c + 1014 0220 ThinkPad A/T/X Series + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 15d9 3480 P4DP6 + 8086 1958 vpr Matrix 170B4 + 248a 82801CAM IDE U100 Controller + 0e11 0030 Evo N600c + 1014 0220 ThinkPad A/T/X Series + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 8086 1958 vpr Matrix 170B4 + 8086 4541 Latitude C640 + 248b 82801CA Ultra ATA Storage Controller + 15d9 3480 P4DP6 + 248c 82801CAM ISA Bridge (LPC) + 24c0 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge + 1014 0267 NetVista A30p + 1462 5800 845PE Max (MS-6580) + 24c1 82801DBL (ICH4-L) IDE Controller + 24c2 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1 + 1014 0267 NetVista A30p + 1014 052d ThinkPad + 1025 005a TravelMate 290 + 1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M) + 1028 0126 Optiplex GX260 + 1028 0160 Dimension 2400 + 1028 0163 Latitude D505 + 1028 018d Inspiron 700m/710m + 1028 0196 Inspiron 5160 + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 103c 08b0 tc1100 tablet + 1043 8089 P4B533 + 1071 8160 MIM2000 + 114a 0582 PC8 onboard USB 1.x + 144d c005 X10 Laptop + 144d c00c P30/P35 notebook + 1462 5800 845PE Max (MS-6580) + 1509 2990 Averatec 5110H laptop + 1734 1004 D1451 Mainboard (SCENIC N300, i845GV) + 1734 1055 Amilo M1420 + 4c53 1090 Cx9 / Vx9 mainboard + 8086 24c2 Latitude X300 + 8086 4541 Latitude D400/D500 + e4bf 0cc9 CC9-SAMBA + e4bf 0cd2 CD2-BEBOP + 24c3 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller + 1014 0267 NetVista A30p + 1014 052d ThinkPad + 1025 005a TravelMate 290 + 1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M) + 1028 0126 Optiplex GX260 + 1028 014f Latitude X300 + 1028 0160 Dimension 2400 + 1028 018d Inspiron 700m/710m + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 103c 08b0 tc1100 tablet + 1071 8160 MIM2000 + 114a 0582 PC8 onboard SMbus + 144d c005 X10 Laptop + 144d c00c P30/P35 notebook + 1458 24c2 GA-8PE667 Ultra + 1462 5800 845PE Max (MS-6580) + 1734 1004 D1451 Mainboard (SCENIC N300, i845GV) + 1734 1055 Amilo M1420 + 4c53 1090 Cx9 / Vx9 mainboard + e4bf 0cc9 CC9-SAMBA + e4bf 0cd2 CD2-BEBOP + 24c4 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2 + 1014 0267 NetVista A30p + 1014 052d ThinkPad + 1025 005a TravelMate 290 + 1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M) + 1028 0126 Optiplex GX260 + 1028 0160 Dimension 2400 + 1028 0163 Latitude D505 + 1028 018d Inspiron 700m/710m + 1028 0196 Inspiron 5160 + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 103c 08b0 tc1100 tablet + 1043 8089 P4B533 + 1071 8160 MIM2000 + 144d c00c P30/P35 notebook + 1462 5800 845PE Max (MS-6580) + 1509 2990 Averatec 5110H + 1734 1004 D1451 Mainboard (SCENIC N300, i845GV) + 4c53 1090 Cx9 / Vx9 mainboard + 8086 24c2 Latitude X300 + 8086 4541 Latitude D400/D500 + e4bf 0cc9 CC9-SAMBA + e4bf 0cd2 CD2-BEBOP + 24c5 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller + 0e11 00b8 Analog Devices Inc. codec [SoundMAX] + 1014 0267 NetVista A30p + 1014 0537 ThinkPad T4x Series + 1014 055f Thinkpad R50e model 1634 + 1025 005a TravelMate 290 + 1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M) + 1028 0139 Latitude D400 + 1028 014f Latitude X300 + 1028 0152 Latitude D500 + 1028 0160 Dimension 2400 + 1028 0163 Latitude D505 + 1028 018d Inspiron 700m/710m [SigmaTel STAC9750,51] + 1028 0196 Inspiron 5160 + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 103c 08b0 tc1100 tablet + 1043 1713 M2400N/M6800N laptop + 1043 80b0 P4B533 + 1071 8160 MIM2000 + 1179 0201 Toshiba Tecra M1 + 144d c005 X10 Laptop + 144d c00c P30/P35 notebook + 1458 a002 GA-8PE667 Ultra + 1462 5800 845PE Max (MS-6580) + 1734 1005 D1451 (SCENIC N300, i845GV) Sigmatel STAC9750T + 1734 1055 Amilo M1420 + 24c6 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller + 1014 0524 ThinkPad T4x Series + 1014 0525 ThinkPad + 1014 0559 ThinkPad R50e + 1025 003c Aspire 2001WLCi (Compal CL50 motherboard) implementation + 1025 005a TravelMate 290 + 1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M) + 1028 0196 Inspiron 5160 + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 103c 08b0 tc1100 tablet + 1043 1716 M2400N laptop + 1043 1826 M6800N + 1071 8160 MIM2000 + 134d 4c21 Latitude D500 + 144d 2115 X10 Laptop + 144d c00c P30/P35 notebook +# Conexant HSF Softmodem (CXT22) + 14f1 5422 D480 MDC V.9x Modem + 24c7 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3 + 1014 0267 NetVista A30p + 1014 052d ThinkPad + 1025 005a TravelMate 290 + 1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M) + 1028 0126 Optiplex GX260 + 1028 0160 Dimension 2400 + 1028 0163 Latitude D505 + 1028 018d Inspiron 700m/710m + 1028 0196 Inspiron 5160 + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 103c 08b0 tc1100 tablet + 1043 8089 P4B533 + 1071 8160 MIM2000 + 144d c00c P30/P35 notebook + 1462 5800 845PE Max (MS-6580) + 1509 2990 Averatec 5110H + 1734 1004 D1451 Mainboard (SCENIC N300, i845GV) + 4c53 1090 Cx9 / Vx9 mainboard + 8086 24c2 Latitude X300 + 8086 4541 Latitude D400/D500 + e4bf 0cc9 CC9-SAMBA + e4bf 0cd2 CD2-BEBOP + 24ca 82801DBM (ICH4-M) IDE Controller + 1014 052d ThinkPad + 1025 005a TravelMate 290 + 1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M) + 1028 014f Latitude X300 + 1028 0163 Latitude D505 + 1028 018d Inspiron 700m/710m + 1028 0196 Inspiron 5160 + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 103c 08b0 tc1100 tablet + 1071 8160 MIM2000 + 144d c005 X10 Laptop + 144d c00c P30/P35 notebook + 1734 1055 Amilo M1420 + 8086 4541 Latitude D400/D500 + 24cb 82801DB (ICH4) IDE Controller + 1014 0267 NetVista A30p + 1028 0126 Optiplex GX260 + 1028 0160 Dimension 2400 + 1043 8089 P4B533 + 114a 0582 PC8 onboard IDE + 1458 24c2 GA-8PE667 Ultra + 1462 5800 845PE Max (MS-6580) + 1734 1004 D1451 Mainboard (SCENIC N300, i845GV) + 4c53 1090 Cx9 / Vx9 mainboard + e4bf 0cc9 CC9-SAMBA + e4bf 0cd2 CD2-BEBOP + 24cc 82801DBM (ICH4-M) LPC Interface Bridge + 144d c00c P30 notebook + 1734 1055 Amilo M1420 + 24cd 82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller + 1014 0267 NetVista A30p + 1014 052e ThinkPad + 1025 005a TravelMate 290 + 1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M) + 1028 011d Latitude D600 + 1028 0126 Optiplex GX260 + 1028 0139 Latitude D400 + 1028 0152 Latitude D500 + 1028 0160 Dimension 2400 + 1028 0163 Latitude D505 + 1028 018d Inspiron 700m/710m + 1028 0196 Inspiron 5160 + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 103c 08b0 tc1100 tablet + 1043 8089 P4B533 + 1071 8160 MIM2000 + 114a 0582 PC8 onboard USB 2.0 + 1179 ff00 Satellite 2430 + 144d c005 X10 Laptop + 144d c00c P30/P35 notebook + 1462 3981 845PE Max (MS-6580) + 1509 1968 Averatec 5110H + 1734 1004 D1451 Mainboard (SCENIC N300, i845GV) + 1734 1055 Amilo M1420 + 1af4 1100 QEMU Virtual Machine + 4c53 1090 Cx9 / Vx9 mainboard + 8086 24c2 Latitude X300 + e4bf 0cc9 CC9-SAMBA + e4bf 0cd2 CD2-BEBOP + 24d0 82801EB/ER (ICH5/ICH5R) LPC Interface Bridge + 24d1 82801EB (ICH5) SATA Controller + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 1028 019a PowerEdge SC1425 + 103c 12bc d530 CMT (DG746A) + 103c 3208 ProLiant DL140 G2 + 1043 80a6 P4P800 series motherboard + 1458 24d1 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 1462 7650 Hetis 865GV-E (MS-7065) + 1565 5200 P4TSV Motherboard (865G) + 15d9 4580 P4SCE Mainboard + 8086 3427 S875WP1-E mainboard + 8086 4246 Desktop Board D865GBF + 8086 4c43 Desktop Board D865GLC + 8086 524c D865PERL mainboard + 24d2 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1 + 1014 0287 ThinkCentre S50 + 1014 02dd eServer xSeries server mainboard + 1014 02ed eServer xSeries server mainboard + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 1028 016c PowerEdge 1850 onboard UHCI + 1028 016d PowerEdge 2850 onboard UHCI + 1028 0170 PowerEdge 6850 onboard UHCI + 1028 0183 PowerEdge 1800 + 1028 019a PowerEdge SC1425 + 103c 006a NX9500 + 103c 12bc d530 CMT (DG746A) + 103c 3208 ProLiant DL140 G2 + 1043 80a6 P4P800/P5P800 series motherboard + 1458 24d2 GA-8IPE1000/8KNXP motherboard + 1462 7280 865PE Neo2 (MS-6728) + 1565 3101 P4TSV Motherboard (865G) + 15d9 4580 P4SCE Mainboard + 1734 101c PRIMERGY RX/TX series onboard UHCI + 8086 3427 S875WP1-E mainboard + 8086 4246 Desktop Board D865GBF + 8086 4c43 Desktop Board D865GLC + 8086 524c D865PERL mainboard + 24d3 82801EB/ER (ICH5/ICH5R) SMBus Controller + 1014 0287 ThinkCentre S50 + 1014 02dd eServer xSeries server mainboard + 1014 02ed eServer xSeries server mainboard + 1028 0156 Precision 360 + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 103c 12bc d330 uT + 103c 3208 ProLiant DL140 G2 + 1043 80a6 P4P800/P5P800 series motherboard + 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 1462 7650 Hetis 865GV-E (MS-7065) + 1565 3101 P4TSV Motherboard (865G) + 15d9 4580 P4SCE Mainboard + 1734 101c PRIMERGY RX/TX S2 series SMBus + 8086 3427 S875WP1-E mainboard + 8086 4246 Desktop Board D865GBF + 8086 4c43 Desktop Board D865GLC + 8086 524c D865PERL mainboard + 24d4 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2 + 1014 0287 ThinkCentre S50 + 1014 02dd eServer xSeries server mainboard + 1014 02ed eServer xSeries server mainboard + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 1028 016c PowerEdge 1850 onboard UHCI + 1028 016d PowerEdge 2850 onboard UHCI + 1028 0170 PowerEdge 6850 onboard UHCI + 1028 0183 PowerEdge 1800 + 1028 019a PowerEdge SC1425 + 103c 006a NX9500 + 103c 12bc d530 CMT (DG746A) + 103c 3208 ProLiant DL140 G2 + 1043 80a6 P4P800/P5P800 series motherboard + 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 1462 7650 Hetis 865GV-E (MS-7065) + 1565 3101 P4TSV Motherboard (865G) + 15d9 4580 P4SCE Mainboard + 1734 101c PRIMERGY RX/TX S2 series onboard UHCI + 8086 3427 S875WP1-E mainboard + 8086 4246 Desktop Board D865GBF + 8086 4c43 Desktop Board D865GLC + 8086 524c D865PERL mainboard + 24d5 82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller + 100a 147b Abit IS7-E motherboard + 1014 0287 ThinkCentre S50 + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 103c 006a NX9500 + 103c 12bc d330 uT + 1043 80f3 P4P800 series motherboard + 1043 810f P5P800-MX Mainboard + 1458 a002 GA-8IPE1000/8KNXP motherboard + 1462 0080 865PE Neo2-V (MS-6788) Mainboard + 1462 7280 865PE Neo2 (MS-6728) + 1462 7650 Hetis 865GV-E (MS-7065) + 8086 a000 D865PERL mainboard + 8086 e000 D865PERL mainboard + 8086 e001 Desktop Board D865GBF + 8086 e002 SoundMax Integrated Digital Audio + 24d6 82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller + 103c 006a NX9500 + 24d7 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #3 + 1014 0287 ThinkCentre S50 + 1014 02ed xSeries server mainboard + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 1028 016c PowerEdge 1850 onboard UHCI + 1028 016d PowerEdge 2850 onboard UHCI + 1028 0170 PowerEdge 6850 onboard UHCI + 1028 0183 PowerEdge 1800 + 103c 006a NX9500 + 103c 12bc d530 CMT (DG746A) + 1043 80a6 P4P800/P5P800 series motherboard + 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 1462 7650 Hetis 865GV-E (MS-7065) + 1565 3101 P4TSV Motherboard (865G) + 15d9 4580 P4SCE Mainboard + 1734 101c PRIMERGY RX/TX S2 series onboard UHCI + 8086 3427 S875WP1-E mainboard + 8086 4246 Desktop Board D865GBF + 8086 4c43 Desktop Board D865GLC + 8086 524c D865PERL mainboard + 24db 82801EB/ER (ICH5/ICH5R) IDE Controller + 1014 0287 ThinkCentre S50 + 1014 02dd eServer xSeries server mainboard + 1014 02ed eServer xSeries server mainboard + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 1028 016c PowerEdge 1850 IDE Controller + 1028 016d PowerEdge 2850 IDE Controller + 1028 0170 PowerEdge 6850 IDE Controller + 1028 019a PowerEdge SC1425 + 103c 006a NX9500 + 103c 12bc d530 CMT (DG746A) + 1043 80a6 P4P800/P5P800 series motherboard + 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 1462 7580 MSI 875P + 1462 7650 Hetis 865GV-E (MS-7065) + 1565 3101 P4TSV Motherboard (865G) + 15d9 4580 P4SCE Mainboard + 1734 101c PRIMERGY RX/TX S2 series onboard IDE + 8086 24db P4C800 Mainboard + 8086 3427 S875WP1-E mainboard + 8086 4246 Desktop Board D865GBF + 8086 4c43 Desktop Board D865GLC + 8086 524c D865PERL mainboard + 24dc 82801EB (ICH5) LPC Interface Bridge + 24dd 82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller + 1014 0287 ThinkCentre S50 + 1014 02dd eServer xSeries server mainboard + 1014 02ed eServer xSeries server mainboard + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 1028 016c PowerEdge 1850 onboard EHCI + 1028 016d PowerEdge 2850 onboard EHCI + 1028 0170 PowerEdge 6850 onboard EHCI + 1028 0183 PowerEdge 1800 + 1028 019a PowerEdge SC1425 + 103c 006a NX9500 + 103c 12bc d530 CMT (DG746A) + 103c 3208 ProLiant DL140 G2 + 1043 80a6 P4P800/P5P800 series motherboard + 1458 5006 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 1462 7650 Hetis 865GV-E (MS-7065) + 8086 3427 S875WP1-E mainboard + 8086 4246 Desktop Board D865GBF + 8086 4c43 Desktop Board D865GLC + 8086 524c D865PERL mainboard + 24de 82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4 + 1014 0287 ThinkCentre S50 + 1014 02ed xSeries server mainboard + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 1043 80a6 P4P800/P5P800 series motherboard + 1458 24d2 GA-8IPE1000 Pro2 motherboard (865PE) + 1462 7280 865PE Neo2 (MS-6728) + 1462 7650 Hetis 865GV-E (MS-7065) + 1565 3101 P4TSV Motherboard (865G) + 15d9 4580 P4SCE Mainboard + 1734 101c PRIMERGY RX/TX S2 series onboard UHCI + 8086 3427 S875WP1-E mainboard + 8086 4246 Desktop Board D865GBF + 8086 4c43 Desktop Board D865GLC + 8086 524c D865PERL mainboard + 24df 82801ER (ICH5R) SATA Controller + 1028 0168 Precision Workstation 670 Mainboard + 24f0 Omni-Path HFI Silicon 100 Series [discrete] + 10a9 802e Omni-path HFI 100 Series, 1-port A-board + 10a9 802f Omni-path HFI 100 Series, 2-port A-board + 10a9 8030 Omni-path HFI 100 Series, 1-port B-board + 10a9 8031 Omni-path HFI 100 Series, 2-port B-board + 1590 00e7 100Gb 1-port OP101 QSFP28 x8 PCIe Gen3 with Intel Omni-Path Adapter + 1590 00e8 100Gb 1-port OP101 QSFP28 x16 PCIe Gen3 with Intel Omni-Path Adapter + 1590 021c Apollo 100Gb 1-port Intel Omni-Path Architecture 860z Mezzanine FIO Adapter + 15d9 0934 Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, SIOM Module + 15d9 099b Omni-path HFI Mezz AOC, 1 Port, PCIe x16. + 1cb8 0001 Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, TC4600 QSFP28 + 1cb8 0002 Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, TC6600 Fixed Port + 1cb8 0003 Omni-Path HFI Adapter 100 Series, 2 Port, 2 PCIe x16, Earth Simulation QSFP28 + 1cb8 0004 Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, TC4600E QSFP28 + 8086 2628 Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16 + 8086 2629 Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x8 + 8086 262a Omni-Path HFI Adapter 100 Series, 2 Ports, Split PCIe x16 + 8086 262d Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, IO Module AHWKPTP100HF + 24f1 Omni-Path HFI Silicon 100 Series [integrated] + 24f3 Wireless 8260 +# Snow Field Peak AC + 8086 0010 Dual Band Wireless-AC 8260 + 8086 1010 Dual Band Wireless-AC 8260 + 24f4 Wireless 8260 +# Snow Field Peak AC + 8086 0030 Dual Band Wireless-AC 8260 + 24fb Dual Band Wireless-AC 3168NGW [Stone Peak] + 24fd Wireless 8265 / 8275 +# Windstorm Peak + 8086 0010 Dual Band Wireless-AC 8265 + 8086 0150 Dual Band Wireless-AC 8265 + 8086 1010 Dual Band Wireless-AC 8265 + 8086 1130 Dual Band Wireless-AC 8265 + 2500 82820 820 (Camino) Chipset Host Bridge (MCH) + 1028 0095 Precision Workstation 220 Chipset + 1043 801c P3C-2000 system chipset + 2501 82820 820 (Camino) Chipset Host Bridge (MCH) + 1043 801c P3C-2000 system chipset + 250b 82820 820 (Camino) Chipset Host Bridge + 250f 82820 820 (Camino) Chipset AGP Bridge + 2520 82805AA MTH Memory Translator Hub + 2521 82804AA MRH-S Memory Repeater Hub for SDRAM + 2526 Wireless-AC 9260 + 2530 82850 850 (Tehama) Chipset Host Bridge (MCH) + 1028 00c7 Dimension 8100 + 147b 0507 TH7II-RAID + 2531 82860 860 (Wombat) Chipset Host Bridge (MCH) + 1028 00d8 Precision 530 + 2532 82850 850 (Tehama) Chipset AGP Bridge + 2533 82860 860 (Wombat) Chipset AGP Bridge + 2534 82860 860 (Wombat) Chipset PCI Bridge + 2540 E7500 Memory Controller Hub + 15d9 3480 P4DP6 + 2541 E7500/E7501 Host RASUM Controller + 15d9 3480 P4DP6 + 4c53 1090 Cx9 / Vx9 mainboard + 8086 3424 SE7501HG2 Mainboard + 2543 E7500/E7501 Hub Interface B PCI-to-PCI Bridge + 2544 E7500/E7501 Hub Interface B RASUM Controller + 4c53 1090 Cx9 / Vx9 mainboard + 2545 E7500/E7501 Hub Interface C PCI-to-PCI Bridge + 2546 E7500/E7501 Hub Interface C RASUM Controller + 2547 E7500/E7501 Hub Interface D PCI-to-PCI Bridge + 2548 E7500/E7501 Hub Interface D RASUM Controller + 254c E7501 Memory Controller Hub + 4c53 1090 Cx9 / Vx9 mainboard + 8086 3424 SE7501HG2 Mainboard + 2550 E7505 Memory Controller Hub + 2551 E7505/E7205 Series RAS Controller + 2552 E7505/E7205 PCI-to-AGP Bridge + 2553 E7505 Hub Interface B PCI-to-PCI Bridge + 2554 E7505 Hub Interface B PCI-to-PCI Bridge RAS Controller + 255d E7205 Memory Controller Hub + 2560 82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface + 1028 0126 Optiplex GX260 + 1458 2560 GA-8PE667 Ultra + 1462 5800 845PE Max (MS-6580) + 2561 82845G/GL[Brookdale-G]/GE/PE Host-to-AGP Bridge + 2562 82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device + 0e11 00b9 Evo D510 SFF + 1014 0267 NetVista A30p + 1028 0160 Dimension 2400 + 1734 1003 D1521 Mainboard (Fujitsu-Siemens) + 1734 1004 D1451 Mainboard (SCENIC N300, i845GV) + 2570 82865G/PE/P DRAM Controller/Host-Hub Interface + 103c 006a NX9500 + 103c 12bc d330 uT + 1043 80f2 P4P800/P5P800 series motherboard + 1458 2570 GA-8IPE1000 Pro2 motherboard (865PE) + 2571 82865G/PE/P AGP Bridge + 2572 82865G Integrated Graphics Controller + 1014 0287 ThinkCentre S50 + 1028 019d Dimension 3000 + 103c 12bc D530 sff(dc578av) + 1043 80a5 P5P800-MX Mainboard + 1462 7650 Hetis 865GV-E (MS-7065) + 1734 101b Fujitsu-Siemens Scenic E300 i865GV + 8086 4246 Desktop Board D865GBF + 8086 4c43 Desktop Board D865GLC + 2573 82865G/PE/P PCI to CSA Bridge + 2576 82865G/PE/P Processor to I/O Memory Interface + 2578 82875P/E7210 Memory Controller Hub + 1458 2578 GA-8KNXP motherboard (875P) + 1462 7580 MS-6758 (875P Neo) + 15d9 4580 P4SCE Motherboard + 2579 82875P Processor to AGP Controller + 257b 82875P/E7210 Processor to PCI to CSA Bridge + 257e 82875P/E7210 Processor to I/O Memory Interface + 2580 82915G/P/GV/GL/PL/910GL Memory Controller Hub + 1458 2580 GA-8I915ME-G Mainboard + 1462 7028 915P/G Neo2 + 1734 105b Scenic W620 + 2581 82915G/P/GV/GL/PL/910GL PCI Express Root Port + 2582 82915G/GV/910GL Integrated Graphics Controller + 1028 1079 Optiplex GX280 + 103c 3006 DC7100 SFF(DX878AV) + 1043 2582 P5GD1-VW Mainboard + 1458 2582 GA-8I915ME-G Mainboard + 1734 105b Scenic W620 + 1849 2582 ASRock P4Dual-915GL + 2584 82925X/XE Memory Controller Hub + 1028 0177 Dimension 8400 + 2585 82925X/XE PCI Express Root Port + 2588 E7220/E7221 Memory Controller Hub + 2589 E7220/E7221 PCI Express Root Port + 258a E7221 Integrated Graphics Controller + 2590 Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller + 1014 0575 ThinkPad X41 / Z60t + 1028 0182 Latitude C610 + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 104d 81b7 Vaio VGN-S3XP + a304 81b7 Vaio VGN-S3XP + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 2591 Mobile 915GM/PM Express PCI Express Root Port + 103c 0934 Compaq nw8240 Mobile Workstation + 2592 Mobile 915GM/GMS/910GML Express Graphics Controller + 1014 0582 ThinkPad X41 + 103c 099c NX6110/NC6120 + 103c 308a NC6220 + 1043 1881 GMA 900 915GM Integrated Graphics + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 25a1 6300ESB LPC Interface Controller + 25a2 6300ESB PATA Storage Controller + 1734 1073 Primergy Econel 200 D2020 mainboard + 1775 10d0 V5D Single Board Computer IDE + 1775 1100 CR11/VR11 Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10e0 PSL09 PrPMC + 25a3 6300ESB SATA Storage Controller + 1734 1073 Primergy Econel 200 D2020 mainboard + 1775 1100 CR11/VR11 Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10d0 Telum ASLP10 Processor AMC + 4c53 10e0 PSL09 PrPMC + 25a4 6300ESB SMBus Controller + 1734 1073 Primergy Econel 200 D2020 mainboard + 1775 10d0 V5D Single Board Computer + 1775 1100 CR11/VR11 Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10d0 Telum ASLP10 Processor AMC + 4c53 10e0 PSL09 PrPMC + 25a6 6300ESB AC'97 Audio Controller + 1775 1100 CR11/VR11 Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 25a7 6300ESB AC'97 Modem Controller + 25a9 6300ESB USB Universal Host Controller + 1734 1073 Primergy Econel 200 D2020 mainboard + 1775 10d0 V5D Single Board Computer USB + 1775 1100 CR11/VR11 Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10d0 Telum ASLP10 Processor AMC + 4c53 10e0 PSL09 PrPMC + 25aa 6300ESB USB Universal Host Controller + 1734 1073 Primergy Econel 200 D2020 mainboard + 1775 1100 CR11/VR11 Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10d0 Telum ASLP10 Processor AMC + 4c53 10e0 PSL09 PrPMC + 25ab 6300ESB Watchdog Timer + 1734 1073 Primergy Econel 200 D2020 mainboard + 1775 10d0 V5D Single Board Computer + 1775 1100 CR11/VR11 Single Board Computer + 1775 ce90 CE9 + 1af4 1100 QEMU Virtual Machine + 4c53 10b0 CL9 mainboard + 4c53 10d0 Telum ASLP10 Processor AMC + 4c53 10e0 PSL09 PrPMC + 25ac 6300ESB I/O Advanced Programmable Interrupt Controller + 1734 1073 Primergy Econel 200 D2020 mainboard + 1775 10d0 V5D Single Board Computer + 1775 1100 CR11/VR11 Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10d0 Telum ASLP10 Processor AMC + 4c53 10e0 PSL09 PrPMC + 25ad 6300ESB USB2 Enhanced Host Controller + 1734 1073 Primergy Econel 200 D2020 mainboard + 1775 10d0 V5D Single Board Computer USB 2.0 + 1775 1100 CR11/VR11 Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10d0 Telum ASLP10 Processor AMC + 4c53 10e0 PSL09 PrPMC + 25ae 6300ESB 64-bit PCI-X Bridge + 25b0 6300ESB SATA RAID Controller + 1775 1100 CR11/VR11 Single Board Computer + 4c53 10d0 Telum ASLP10 Processor AMC + 4c53 10e0 PSL09 PrPMC + 25c0 5000X Chipset Memory Controller Hub + 25d0 5000Z Chipset Memory Controller Hub + 25d4 5000V Chipset Memory Controller Hub + 15d9 8680 X7DVL-E-O motherboard + 25d8 5000P Chipset Memory Controller Hub + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 25e2 5000 Series Chipset PCI Express x4 Port 2 + 25e3 5000 Series Chipset PCI Express x4 Port 3 + 25e4 5000 Series Chipset PCI Express x4 Port 4 + 25e5 5000 Series Chipset PCI Express x4 Port 5 + 25e6 5000 Series Chipset PCI Express x4 Port 6 + 25e7 5000 Series Chipset PCI Express x4 Port 7 + 25f0 5000 Series Chipset FSB Registers + 1028 01bb PowerEdge 1955 FSB Registers + 103c 31fd ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 25f1 5000 Series Chipset Reserved Registers + 103c 31fd ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 25f3 5000 Series Chipset Reserved Registers + 103c 31fd ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 25f5 5000 Series Chipset FBD Registers + 103c 31fd ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 25f6 5000 Series Chipset FBD Registers + 103c 31fd ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 25f7 5000 Series Chipset PCI Express x8 Port 2-3 + 25f8 5000 Series Chipset PCI Express x8 Port 4-5 + 25f9 5000 Series Chipset PCI Express x8 Port 6-7 + 25fa 5000X Chipset PCI Express x16 Port 4-7 + 2600 E8500/E8501 Hub Interface 1.5 + 1028 0170 PowerEdge 6850 Hub Interface + 2601 E8500/E8501 PCI Express x4 Port D + 2602 E8500/E8501 PCI Express x4 Port C0 + 2603 E8500/E8501 PCI Express x4 Port C1 + 2604 E8500/E8501 PCI Express x4 Port B0 + 2605 E8500/E8501 PCI Express x4 Port B1 + 2606 E8500/E8501 PCI Express x4 Port A0 + 2607 E8500/E8501 PCI Express x4 Port A1 + 2608 E8500/E8501 PCI Express x8 Port C + 2609 E8500/E8501 PCI Express x8 Port B + 260a E8500/E8501 PCI Express x8 Port A + 260c E8500/E8501 IMI Registers + 2610 E8500/E8501 FSB Registers + 2611 E8500/E8501 Address Mapping Registers + 2612 E8500/E8501 RAS Registers + 2613 E8500/E8501 Reserved Registers + 2614 E8500/E8501 Reserved Registers + 2615 E8500/E8501 Miscellaneous Registers + 2617 E8500/E8501 Reserved Registers + 2618 E8500/E8501 Reserved Registers + 2619 E8500/E8501 Reserved Registers + 261a E8500/E8501 Reserved Registers + 261b E8500/E8501 Reserved Registers + 261c E8500/E8501 Reserved Registers + 261d E8500/E8501 Reserved Registers + 261e E8500/E8501 Reserved Registers + 2620 E8500/E8501 eXternal Memory Bridge + 1028 0170 PowerEdge 6850 Memory Bridge + 2621 E8500/E8501 XMB Miscellaneous Registers + 1028 0170 PowerEdge 6850 XMB Registers + 2622 E8500/E8501 XMB Memory Interleaving Registers + 1028 0170 PowerEdge 6850 Memory Interleaving Registers + 2623 E8500/E8501 XMB DDR Initialization and Calibration + 1028 0170 PowerEdge 6850 DDR Initialization and Calibration + 2624 E8500/E8501 XMB Reserved Registers + 1028 0170 PowerEdge 6850 Reserved Registers + 2625 E8500/E8501 XMB Reserved Registers + 1028 0170 PowerEdge 6850 Reserved Registers + 2626 E8500/E8501 XMB Reserved Registers + 1028 0170 PowerEdge 6850 Reserved Registers + 2627 E8500/E8501 XMB Reserved Registers + 1028 0170 PowerEdge 6850 Reserved Registers + 2640 82801FB/FR (ICH6/ICH6R) LPC Interface Bridge + 1462 7028 915P/G Neo2 + 1734 105c Scenic W620 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 2641 82801FBM (ICH6M) LPC Interface Bridge + 1014 0568 ThinkPad X41 + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 2642 82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge + 2651 82801FB/FW (ICH6/ICH6W) SATA Controller + 1028 0179 Optiplex GX280 + 1043 2601 P5GD1-VW Mainboard + 1734 105c Scenic W620 + 8086 4147 D915GAG Motherboard + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 2652 82801FR/FRW (ICH6R/ICH6RW) SATA Controller + 1028 0177 Dimension 8400 + 1462 7028 915P/G Neo2 + 2653 82801FBM (ICH6M) SATA Controller + 1014 056a ThinkPad X41 + 2658 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1 + 1014 0565 ThinkPad X41 + 1028 0177 Dimension 8400 + 1028 0179 Optiplex GX280 + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 1043 80a6 P5GD1-VW Mainboard + 1458 2558 GA-8I915ME-G Mainboard + 1462 7028 915P/G Neo2 + 1734 105c Scenic W620 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 2659 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2 + 1014 0565 ThinkPad X41 + 1028 0177 Dimension 8400 + 1028 0179 Optiplex GX280 + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 1043 80a6 P5GD1-VW Mainboard + 1458 2659 GA-8I915ME-G Mainboard + 1462 7028 915P/G Neo2 + 1734 105c Scenic W620 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 265a 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3 + 1014 0565 ThinkPad X41 + 1028 0177 Dimension 8400 + 1028 0179 Optiplex GX280 + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 1043 80a6 P5GD1-VW Mainboard + 1458 265a GA-8I915ME-G Mainboard + 1462 7028 915P/G Neo2 + 1734 105c Scenic W620 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 265b 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4 + 1014 0565 ThinkPad X41 + 1028 0177 Dimension 8400 + 1028 0179 Optiplex GX280 + 103c 099c NX6110/NC6120 + 1043 80a6 P5GD1-VW Mainboard + 1458 265a GA-8I915ME-G Mainboard + 1462 7028 915P/G Neo2 + 1734 105c Scenic W620 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 265c 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller + 1014 0566 ThinkPad X41 + 1028 0177 Dimension 8400 + 1028 0179 Optiplex GX280 + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 1043 80a6 P5GD1-VW Mainboard + 1458 5006 GA-8I915ME-G Mainboard + 1462 7028 915P/G Neo2 + 1734 105c Scenic W620 + 8086 265c Dimension 3100 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 2660 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1 + 103c 0934 Compaq nw8240 Mobile Workstation + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 2662 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2 + 103c 0934 Compaq nw8240 Mobile Workstation + 103c 0944 Compaq nc6220 Notebook PC + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 2664 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 2666 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 2668 82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller + 1014 05b7 ThinkPad Z60t +# based on the PTGD1-LA motherboard + 103c 2a09 PufferM-UL8E + 1043 1173 A6VC + 1043 814e P5GD1-VW Mainboard + 1462 7028 915P/G Neo2 + 1af4 1100 QEMU Virtual Machine + 266a 82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller + 1014 056b ThinkPad X41 + 1028 0177 Dimension 8400 + 1028 0179 Optiplex GX280 + 1043 80a6 P5GD1-VW Mainboard + 1458 266a GA-8I915ME-G Mainboard + 1462 7028 915P/G Neo2 + 1734 105c Scenic W620 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 266c 82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller + 266d 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller + 1025 006a Conexant AC'97 CoDec (in Acer TravelMate 2410 serie laptop) + 103c 0934 Compaq nw8240/nx8220 + 103c 099c NX6110/NC6120 + 266e 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller + 1014 0581 ThinkPad X41 (Analog Devices AD1981B codec) + 1025 006a Realtek ALC 655 codec (in Acer TravelMate 2410 serie laptop) + 1028 0177 Dimension 8400 + 1028 0179 Optiplex GX280 + 1028 0182 Latitude D610 Laptop + 1028 0187 Precision M70 Laptop + 1028 0188 Inspiron 6000 laptop + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq NC6220 + 103c 099c NX6110/NC6120 + 103c 3006 DC7100 SFF(DX878AV) + 1458 a002 GA-8I915ME-G Mainboard + 152d 0745 Packard Bell A8550 Laptop + 1734 105a Scenic W620 + 266f 82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller + 1028 0177 Dimension 8400 + 103c 0934 Compaq nw8240/nx8220 + 103c 0944 Compaq nc6220 Notebook PC + 103c 099c NX6110/NC6120 + 1043 80a6 P5GD1-VW Mainboard + 1458 266f GA-8I915ME-G Mainboard + 1462 7028 915P/G Neo2 + 1734 105c Scenic W620 + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 2670 631xESB/632xESB/3100 Chipset LPC Interface Controller + 103c 31fe ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 2680 631xESB/632xESB/3100 Chipset SATA IDE Controller + 2681 631xESB/632xESB SATA AHCI Controller + 103c 31fe ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 2682 631xESB/632xESB SATA RAID Controller + 103c 31fe Adaptec Serial ATA HostRAID + 2683 631xESB/632xESB SATA RAID Controller + 2688 631xESB/632xESB/3100 Chipset UHCI USB Controller #1 + 1028 01bb PowerEdge 1955 onboard USB + 1028 01f0 PowerEdge R900 onboard USB + 103c 31fe ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 2689 631xESB/632xESB/3100 Chipset UHCI USB Controller #2 + 1028 01bb PowerEdge 1955 onboard USB + 1028 01f0 PowerEdge R900 onboard USB + 103c 31fe ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 268a 631xESB/632xESB/3100 Chipset UHCI USB Controller #3 + 1028 01f0 PowerEdge R900 onboard USB + 103c 31fe ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 268b 631xESB/632xESB/3100 Chipset UHCI USB Controller #4 + 1028 01f0 PowerEdge R900 onboard USB + 15d9 8680 X7DVL-E-O motherboard + 8086 3476 S5000PSLSATA Server Board + 268c 631xESB/632xESB/3100 Chipset EHCI USB2 Controller + 1028 01bb PowerEdge 1955 onboard USB + 1028 01f0 PowerEdge R900 onboard USB + 103c 31fe ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 2690 631xESB/632xESB/3100 Chipset PCI Express Root Port 1 + 103c 31fe ProLiant DL140 G3 + 15d9 9680 X7DBN Motherboard + 2692 631xESB/632xESB/3100 Chipset PCI Express Root Port 2 + 103c 31fe ProLiant DL140 G3 + 2694 631xESB/632xESB/3100 Chipset PCI Express Root Port 3 + 2696 631xESB/632xESB/3100 Chipset PCI Express Root Port 4 + 2698 631xESB/632xESB AC '97 Audio Controller + 2699 631xESB/632xESB AC '97 Modem Controller + 269a 631xESB/632xESB High Definition Audio Controller + 269b 631xESB/632xESB/3100 Chipset SMBus Controller + 103c 31fe ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 8086 3476 S5000PSLSATA Server Board + 269e 631xESB/632xESB IDE Controller + 103c 31fe ProLiant DL140 G3 + 15d9 8680 X7DVL-E-O motherboard + 15d9 9680 X7DBN Motherboard + 2700 Optane SSD 900P Series + 8086 3900 900P Series [Add-in Card] + 8086 3901 900P Series [2.5" SFF] + 2701 NVMe Datacenter SSD [Optane] + 1028 2000 Express Flash NVMe [Optane] 375GB 2.5" U.2 (P4800X) + 1028 2001 Express Flash NVMe [Optane] 750GB 2.5" U.2 (P4800X) + 1028 2002 Express Flash NVMe [Optane] 750GB AIC (P4800X) + 1028 200a Express Flash NVMe [Optane] 375GB AIC (P4800X) + 8086 3904 NVMe Datacenter SSD [Optane] x4 AIC (P4800X) + 8086 3905 NVMe Datacenter SSD [Optane] 15mm 2.5" U.2 (P4800X) + 2723 Wi-Fi 6 AX200 + 8086 2723 Wireless AX200 + 2770 82945G/GZ/P/PL Memory Controller Hub + 1028 01ad OptiPlex GX620 + 103c 2a3b Pavilion A1512X + 1043 817a P5LD2-VM Mainboard + 107b 5048 E4500 + 1462 7418 Wind PC MS-7418 + 1849 2770 ConRoe1333-D667 + 8086 544e DeskTop Board D945GTP + 2771 82945G/GZ/P/PL PCI Express Root Port + 2772 82945G/GZ Integrated Graphics Controller + 103c 2a3b Pavilion A1512X + 1462 7418 Wind PC MS-7418 + 1849 2772 ConRoe1333-D667 + 8086 544e DeskTop Board D945GTP + 8086 d605 Desktop Board D945GCCR + 2774 82955X Memory Controller Hub + 2775 82955X PCI Express Root Port + 2776 82945G/GZ Integrated Graphics Controller + 2778 E7230/3000/3010 Memory Controller Hub + 1028 01df PowerEdge SC440 + 1028 01e6 PowerEdge 860 + 2779 E7230/3000/3010 PCI Express Root Port + 277a 82975X/3010 PCI Express Root Port + 277c 82975X Memory Controller Hub + 1043 8178 P5WDG2 WS Professional motherboard + 277d 82975X PCI Express Root Port + 2782 82915G Integrated Graphics Controller + 1043 2582 P5GD1-VW Mainboard + 1734 105b Scenic W620 + 2792 Mobile 915GM/GMS/910GML Express Graphics Controller + 1014 0582 ThinkPad X41 + 103c 099c NX6110/NC6120 + 103c 308a Compaq nc6220 Notebook PC + 1043 1881 GMA 900 915GM Integrated Graphics + e4bf 0ccd CCD-CALYPSO + e4bf 0cd3 CD3-JIVE + e4bf 58b1 XB1 + 27a0 Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub + 1025 006c 9814 WKMI + 1028 01d7 XPS M1210 + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 103c 30d5 530 Laptop + 1043 1237 A6J-Q008 + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 17aa 2015 ThinkPad T60 + 17aa 2017 ThinkPad R60/T60/X60 series + 27a1 Mobile 945GM/PM/GMS, 943/940GML and 945GT Express PCI Express Root Port + 103c 309f Compaq nx9420 Notebook + 103c 30a3 Compaq nw8440 + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 27a2 Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller + 103c 30a1 NC2400 + 103c 30d5 530 Laptop + 17aa 201a ThinkPad R60/T60/X60 series + 9902 1584 CCE MPL-D10H120F + 27a6 Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller + 103c 30a1 NC2400 + 103c 30d5 530 Laptop + 1775 11cc CC11/CL11 integrated graphics (secondary) + 17aa 201a ThinkPad R60/T60/X60 series + 27ac Mobile 945GSE Express Memory Controller Hub + 1775 11cc CC11/CL11 + 27ad Mobile 945GSE Express PCI Express Root Port + 27ae Mobile 945GSE Express Integrated Graphics Controller + 1775 11cc CC11/CL11 integrated graphics (primary) + 27b0 82801GH (ICH7DH) LPC Interface Bridge + 103c 2a3b Pavilion A1512X + 8086 544e DeskTop Board D945GTP + 27b8 82801GB/GR (ICH7 Family) LPC Interface Bridge + 1028 01e6 PowerEdge 860 + 103c 2a8c Compaq 500B Microtower + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM Motherboard + 107b 5048 E4500 + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 8086 544e DeskTop Board D945GTP + 27b9 82801GBM (ICH7-M) LPC Interface Bridge + 1028 01d7 XPS M1210 + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 103c 30d5 530 Laptop + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 10f7 8338 Panasonic CF-Y5 laptop + 17aa 2009 ThinkPad R60/T60/X60 series + 27bc NM10 Family LPC Controller + 1043 83ad Eee PC 1015PX + 105b 0d7c D270S/D250S Motherboard + 144d c072 Notebook N150P + 1458 5001 GA-D525TUD + 8086 4f4d DeskTop Board D510MO + 8086 544b Desktop Board D425KT + 27bd 82801GHM (ICH7-M DH) LPC Interface Bridge + 1025 006c 9814 WKMI + 27c0 NM10/ICH7 Family SATA Controller [IDE mode] + 1028 01ad OptiPlex GX620 + 1028 01df PowerEdge SC440 + 1028 01e6 PowerEdge 860 + 103c 2a8c Compaq 500B Microtower + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM Motherboard + 107b 5048 E4500 + 1462 2310 MSI Hetis 945 + 1462 7236 945P Neo3-F Rev. 2.2 motherboard + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 8086 544b Desktop Board D425KT + 8086 544e DeskTop Board D945GTP + 27c1 NM10/ICH7 Family SATA Controller [AHCI mode] + 1028 01df PowerEdge SC440 + 103c 2a3b Pavilion A1512X + 1043 83ad Eee PC 1015PX + 105b 0d7c D270S/D250S Motherboard + 144d c072 Notebook N150P + 1458 b005 GA-D525TUD + 1775 11cc CC11/CL11 + 8086 4f4d DeskTop Board D510MO + 8086 5842 DeskTop Board D975XBX + 27c3 82801GR/GDH (ICH7R/ICH7DH) SATA Controller [RAID mode] + 1775 11cc CC11/CL11 + 8086 544e DeskTop Board D945GTP + 27c4 82801GBM/GHM (ICH7-M Family) SATA Controller [IDE mode] + 1025 006c 9814 WKMI + 1028 01d7 XPS M1210 + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 17aa 200e ThinkPad T60 + 27c5 82801GBM/GHM (ICH7-M Family) SATA Controller [AHCI mode] + 103c 309f Compaq nx9420 Notebook + 103c 30a3 Compaq nw8440 + 103c 30d5 530 Laptop + 17aa 200d ThinkPad R60/T60/X60 series + 27c6 82801GHM (ICH7-M DH) SATA Controller [RAID mode] + 27c8 NM10/ICH7 Family USB UHCI Controller #1 + 1025 006c 9814 WKMI + 1028 01ad OptiPlex GX620 + 1028 01d7 XPS M1210 + 1028 01df PowerEdge SC440 + 1028 01e6 PowerEdge 860 + 103c 2a3b Pavilion A1512X + 103c 2a8c Compaq 500B Microtower + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 103c 30d5 530 Laptop + 1043 1237 A6J-Q008 + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM, P5LD2-VM Mainboard + 1043 83ad Eee PC 1015PX + 105b 0d7c D270S/D250S Motherboard + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 107b 5048 E4500 + 144d c072 Notebook N150P + 1458 5004 GA-D525TUD + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 200a ThinkPad R60/T60/X60 series + 8086 4f4d DeskTop Board D510MO + 8086 544b Desktop Board D425KT + 8086 544e DeskTop Board D945GTP + 27c9 NM10/ICH7 Family USB UHCI Controller #2 + 1025 006c 9814 WKMI + 1028 01ad OptiPlex GX620 + 1028 01d7 XPS M1210 + 1028 01df PowerEdge SC440 + 1028 01e6 PowerEdge 860 + 103c 2a3b Pavilion A1512X + 103c 2a8c Compaq 500B Microtower + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 1043 1237 A6J-Q008 + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM, P5LD2-VM Mainboard + 1043 83ad Eee PC 1015PX + 105b 0d7c D270S/D250S Motherboard + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 107b 5048 E4500 + 144d c072 Notebook N150P + 1458 5004 GA-D525TUD + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 200a ThinkPad R60/T60/X60 series + 8086 4f4d DeskTop Board D510MO + 8086 544b Desktop Board D425KT + 8086 544e DeskTop Board D945GTP + 27ca NM10/ICH7 Family USB UHCI Controller #3 + 1025 006c 9814 WKMI + 1028 01ad OptiPlex GX620 + 1028 01d7 XPS M1210 + 1028 01df PowerEdge SC440 + 1028 01e6 PowerEdge 860 + 103c 2a3b Pavilion A1512X + 103c 2a8c Compaq 500B Microtower + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 1043 1237 A6J-Q008 + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM, P5LD2-VM Mainboard + 1043 83ad Eee PC 1015PX + 105b 0d7c D270S/D250S Motherboard + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 107b 5048 E4500 + 144d c072 Notebook N150P + 1458 5004 GA-D525TUD + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 200a ThinkPad R60/T60/X60 series + 8086 4f4d DeskTop Board D510MO + 8086 544e DeskTop Board D945GTP + 27cb NM10/ICH7 Family USB UHCI Controller #4 + 1025 006c 9814 WKMI + 1028 01ad OptiPlex GX620 + 1028 01d7 XPS M1210 + 1028 01df PowerEdge SC440 + 103c 2a3b Pavilion A1512X + 103c 2a8c Compaq 500B Microtower + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 1043 1237 A6J-Q008 + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM, P5LD2-VM Mainboard + 1043 83ad Eee PC 1015PX + 105b 0d7c D270S/D250S Motherboard + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 107b 5048 E4500 + 144d c072 Notebook N150P + 1458 5004 GA-D525TUD + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 200a ThinkPad R60/T60/X60 series + 8086 4f4d DeskTop Board D510MO + 8086 544e DeskTop Board D945GTP + 27cc NM10/ICH7 Family USB2 EHCI Controller + 1025 006c 9814 WKMI + 1028 01ad OptiPlex GX620 + 1028 01d7 XPS M1210 + 1028 01df PowerEdge SC440 + 1028 01e6 PowerEdge 860 + 103c 2a3b Pavilion A1512X + 103c 2a8c Compaq 500B Microtower + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 103c 30d5 530 Laptop + 1043 1237 A6J-Q008 + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM, P5LD2-VM Mainboard + 1043 83ad Eee PC 1015PX + 105b 0d7c D270S/D250S Motherboard + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 144d c072 Notebook N150P + 1458 5006 GA-D525TUD + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 200b ThinkPad R60/T60/X60 series + 8086 4f4d DeskTop Board D510MO + 8086 544b Desktop Board D425KT + 8086 544e DeskTop Board D945GTP + 27d0 NM10/ICH7 Family PCI Express Port 1 + 103c 309f Compaq nx9420 Notebook + 103c 30a3 Compaq nw8440 + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 144d c072 Notebook N150P + 1458 5001 GA-D525TUD + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 2011 ThinkPad R60e + 8086 544b Desktop Board D425KT + 27d2 NM10/ICH7 Family PCI Express Port 2 + 103c 309f Compaq nx9420 Notebook + 103c 30a3 Compaq nw8440 + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 144d c072 Notebook N150P + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 2011 ThinkPad R60e + 8086 544b Desktop Board D425KT + 27d4 NM10/ICH7 Family PCI Express Port 3 + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 144d c072 Notebook N150P + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 2011 ThinkPad R60e + 8086 544b Desktop Board D425KT + 27d6 NM10/ICH7 Family PCI Express Port 4 + 103c 30a3 Compaq nw8440 + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 144d c072 Notebook N150P + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 2011 ThinkPad R60e + 8086 544b Desktop Board D425KT + 27d8 NM10/ICH7 Family High Definition Audio Controller + 1025 006c 9814 WKMI + 1028 01d7 XPS M1210 + 103c 2a3b Pavilion A1512X + 103c 2a8c Compaq 500B Microtower + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 103c 30d5 530 Laptop + 1043 1123 A6J-Q008 + 1043 13c4 G2P + 1043 817f P5LD2-VM Mainboard (Realtek ALC 882 codec) + 1043 8249 P5B-MX/WiFi-AP + 1043 8290 P5KPL-VM Motherboard + 1043 82ea P5KPL-CM Motherboard + 1043 8437 Eee PC 1015PX + 105b 0d7c D270S/D250S Motherboard + 1071 8207 Medion MIM 2240 Notebook PC [MD98100] + 107b 5048 E4500 + 10f7 8338 Panasonic CF-Y5 laptop + 1179 ff10 Toshiba Satellite A100-796 audio (Realtek ALC861) + 1179 ff31 AC97 Data Fax SoftModem with SmartCP + 1447 1043 Asus A8JP (Analog Devices AD1986A) + 144d c072 Notebook N150P + 1458 a002 GA-D525TUD (Realtek ALC887) + 1458 a102 GA-8I945PG-RH Mainboard + 1462 7418 Wind PC MS-7418 + 152d 0753 Softmodem + 1734 10ad Conexant softmodem SmartCP + 17aa 2010 ThinkPad R60/T60/X60 series + 17aa 3802 3000 C200 audio [Realtek ALC861VD] + 8086 1112 DeskTop Board D945GTP + 8086 27d8 DeskTop Board D945GTP + 8086 d618 DeskTop Board D510MO + 8384 7680 STAC9221 HD Audio Codec + 27da NM10/ICH7 Family SMBus Controller + 1025 006c 9814 WKMI + 1028 01ad OptiPlex GX620 + 1028 01d7 XPS M1210 + 1028 01df PowerEdge SC440 + 1028 01e6 PowerEdge 860 + 103c 2a3b Pavilion A1512X + 103c 2a8c Compaq 500B Microtower + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM Motherboard + 105b 0d7c D270S/D250S Motherboard + 1071 8209 Medion MIM 2240 Notebook PC [MD98100] + 10f7 8338 Panasonic CF-Y5 laptop + 144d c072 Notebook N150P + 1458 5001 GA-8I945PG-RH/GA-D525TUD Mainboard + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 200f ThinkPad R60/T60/X60 series + 8086 4f4d DeskTop Board D510MO + 8086 544b Desktop Board D425KT + 8086 544e DeskTop Board D945GTP + 8086 5842 DeskTop Board D975XBX + 27dc NM10/ICH7 Family LAN Controller + 103c 2a3b Pavilion A1512X + 8086 308d DeskTop Board D945GTP + 27dd 82801G (ICH7 Family) AC'97 Modem Controller + 27de 82801G (ICH7 Family) AC'97 Audio Controller + 1028 01ad OptiPlex GX620 + 1462 7267 Realtek ALC883 Audio Controller + 1775 11cc CC11 integrated audio (AD1981BL codec) + 27df 82801G (ICH7 Family) IDE Controller + 1028 01df PowerEdge SC440 + 1028 01e6 PowerEdge 860 + 103c 2a3b Pavilion A1512X + 103c 2a8c Compaq 500B Microtower + 103c 309f Compaq nx9420 Notebook + 103c 30a1 NC2400 + 103c 30a3 Compaq nw8440 + 103c 30d5 530 Laptop + 1043 1237 A6J-Q008 + 1043 8179 P5B-MX/WiFi-AP, P5KPL-VM Motherboard + 107b 5048 E4500 + 10f7 8338 Panasonic CF-Y5 laptop + 1462 7418 Wind PC MS-7418 + 1775 11cc CC11/CL11 + 17aa 200c ThinkPad R60/T60/X60 series + 8086 544e DeskTop Board D945GTP + 27e0 82801GR/GH/GHM (ICH7 Family) PCI Express Port 5 + 1775 11cc CC11/CL11 + 27e2 82801GR/GH/GHM (ICH7 Family) PCI Express Port 6 + 1775 11cc CC11/CL11 + 280b Intel(R) Display Audio + 2810 82801HB/HR (ICH8/R) LPC Interface Controller + 1043 81ec P5B + 2811 82801HEM (ICH8M-E) LPC Interface Controller + 103c 30c1 Compaq 6910p + 17aa 20b6 ThinkPad T61/R61 + e4bf cc47 CCG-RUMBA + 2812 82801HH (ICH8DH) LPC Interface Controller + 2814 82801HO (ICH8DO) LPC Interface Controller + 2815 82801HM (ICH8M) LPC Interface Controller + 1025 0121 Aspire 5920G + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30cc Pavilion dv6700 + 103c 30d9 Presario C700 + 1043 1017 X58LE + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 17aa 20a5 ThinkPad R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + 2820 82801H (ICH8 Family) 4 port SATA Controller [IDE mode] + 1028 01da OptiPlex 745 + 1462 7235 P965 Neo MS-7235 mainboard + 2821 82801HR/HO/HH (ICH8R/DO/DH) 6 port SATA Controller [AHCI mode] + 2822 SATA Controller [RAID mode] + 1028 020d Inspiron 530 + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 2823 C610/X99 series chipset sSATA Controller [RAID mode] + 2824 82801HB (ICH8) 4 port SATA Controller [AHCI mode] + 1043 81ec P5B + 2825 82801HR/HO/HH (ICH8R/DO/DH) 2 port SATA Controller [IDE mode] + 1028 01da OptiPlex 745 + 1462 7235 P965 Neo MS-7235 mainboard + 2826 C600/X79 series chipset SATA RAID Controller + 1d49 0100 Intel RSTe SATA Software RAID + 1d49 0101 Intel RSTe SATA Software RAID + 1d49 0102 Intel RSTe SATA Software RAID + 1d49 0103 Intel RSTe SATA Software RAID + 1d49 0104 Intel RSTe SATA Software RAID + 1d49 0105 Intel RSTe SATA Software RAID + 2827 C610/X99 series chipset sSATA Controller [RAID mode] + 2828 82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [IDE mode] + 1028 01f3 Inspiron 1420 + 103c 30c0 Compaq 6710b + 17aa 20a8 ThinkPad R61 + e4bf cc47 CCG-RUMBA + 2829 82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] + 1025 0121 Aspire 5920G + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 103c 30d9 Presario C700 + 1043 1017 X58LE + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 17aa 20a7 ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 282a 82801 Mobile SATA Controller [RAID mode] + 1028 040b Latitude E6510 + e4bf 50c1 PC1-GROOVE + 2830 82801H (ICH8 Family) USB UHCI Controller #1 + 1025 0121 Aspire 5920G + 1028 01da OptiPlex 745 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 103c 30d9 Presario C700 + 1043 1017 X58LE + 1043 81ec P5B + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 1462 7235 P965 Neo MS-7235 mainboard + 17aa 20aa ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 2831 82801H (ICH8 Family) USB UHCI Controller #2 + 1025 0121 Aspire 5920G + 1028 01da OptiPlex 745 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 103c 30d9 Presario C700 + 1043 1017 X58LE + 1043 81ec P5B + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 1462 7235 P965 Neo MS-7235 mainboard + 17aa 20aa ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 2832 82801H (ICH8 Family) USB UHCI Controller #3 + 1025 0121 Aspire 5920G + 1028 01da OptiPlex 745 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 103c 30d9 Presario C700 + 1043 1017 X58LE + 1043 81ec P5B + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 17aa 20aa ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 2833 82801H (ICH8 Family) USB UHCI Controller #4 + 1043 81ec P5B + 2834 82801H (ICH8 Family) USB UHCI Controller #4 + 1025 0121 Aspire 5920G + 1028 01da OptiPlex 745 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 1043 1017 X58LE + 1043 81ec P5B + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 1462 7235 P965 Neo MS-7235 mainboard + 17aa 20aa ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 2835 82801H (ICH8 Family) USB UHCI Controller #5 + 1025 0121 Aspire 5920G + 1028 01da OptiPlex 745 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 1043 1017 X58LE + 1043 81ec P5B + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 17aa 20aa Thinkpad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 2836 82801H (ICH8 Family) USB2 EHCI Controller #1 + 1025 0121 Aspire 5920G + 1028 01da OptiPlex 745 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 103c 30d9 Presario C700 + 1043 1017 X58LE + 1043 81ec P5B + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 1462 7235 P965 Neo MS-7235 mainboard + 17aa 20ab ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 283a 82801H (ICH8 Family) USB2 EHCI Controller #2 + 1025 0121 Aspire 5920G + 1028 01da OptiPlex 745 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 1043 1017 X58LE + 1043 81ec P5B + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 17aa 20ab ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 283e 82801H (ICH8 Family) SMBus Controller + 1025 0121 Aspire 5920G + 1028 01da OptiPlex 745 + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30d9 Presario C700 + 1043 1017 X58LE + 1043 81ec P5B + 104d 9005 Vaio VGN-FZ260E + 104d 9008 Vaio VGN-SZ79SN_C + 104d 902d VAIO VGN-NR120E + 1462 7235 P965 Neo MS-7235 mainboard + 17aa 20a9 ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 283f 82801H (ICH8 Family) PCI Express Port 1 + 1028 01da OptiPlex 745 + 103c 30c1 Compaq 6910p + 1043 1017 X58LE + 104d 902d VAIO VGN-NR120E + 17aa 20ad ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + 2841 82801H (ICH8 Family) PCI Express Port 2 + 103c 30c1 Compaq 6910p + 1043 1017 X58LE + 104d 902d VAIO VGN-NR120E + 17aa 20ad ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + 2843 82801H (ICH8 Family) PCI Express Port 3 + 1043 1017 X58LE + 104d 902d VAIO VGN-NR120E + 17aa 20ad ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + 2845 82801H (ICH8 Family) PCI Express Port 4 + 1043 1017 X58LE + 17aa 20ad ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + 2847 82801H (ICH8 Family) PCI Express Port 5 + 1028 01da OptiPlex 745 + 103c 30c1 Compaq 6910p + 17aa 20ad ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + 2849 82801H (ICH8 Family) PCI Express Port 6 + 284b 82801H (ICH8 Family) HD Audio Controller + 1025 011f Realtek ALC268 audio codec + 1025 0121 Aspire 5920G + 1025 0145 Realtek ALC889 (Aspire 8920G w. Dolby Theater) + 1028 01da OptiPlex 745 + 1028 01f3 Inspiron 1420 + 1028 01f9 Latitude D630 + 1028 01ff Precision M4300 + 1028 022f Inspiron 1525 + 1028 0256 Studio 1735 + 103c 2802 Compaq dc7700p + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 1043 1339 M51S series + 1043 17f3 X58LE + 1043 81ec P5B + 104d 9005 Vaio VGN-FZ260E + 104d 9008 Vaio VGN-SZ79SN_C + 104d 9016 Sony VAIO VGN-AR51M + 104d 902d VAIO VGN-NR120E + 14f1 5051 Presario C700 + 17aa 20ac ThinkPad T61/R61 + 17c0 4088 Medion WIM 2210 Notebook PC [MD96850] + 8384 7616 Dell Vostro 1400 + e4bf cc47 CCG-RUMBA + 284f 82801H (ICH8 Family) Thermal Reporting Device + 2850 82801HM/HEM (ICH8M/ICH8M-E) IDE Controller + 1025 0121 Aspire 5920G + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 103c 30d9 Presario C700 + 1043 1017 X58LE + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 17aa 20a6 ThinkPad T61/R61 + 17c0 4083 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 28c0 Volume Management Device NVMe RAID Controller + 2912 82801IH (ICH9DH) LPC Interface Controller + 2914 82801IO (ICH9DO) LPC Interface Controller + 1028 0211 Optiplex 755 + 2916 82801IR (ICH9R) LPC Interface Controller + 1028 020d Inspiron 530 + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard + 1462 7345 MS-7345 Motherboard + 8086 5044 Desktop Board DP35DP + 2917 ICH9M-E LPC Interface Controller + 17aa 20f5 ThinkPad T400 + e4bf cc4d CCM-BOOGIE + 2918 82801IB (ICH9) LPC Interface Controller + 1028 0236 PowerEdge R610 82801IB (ICH9) LPC Interface Controller + 1462 7360 G33/P35 Neo + 1af4 1100 QEMU Virtual Machine + 2919 ICH9M LPC Interface Controller + 2920 82801IR/IO/IH (ICH9R/DO/DH) 4 port SATA Controller [IDE mode] + 1028 020d Inspiron 530 + 1028 020f PowerEdge R300 onboard SATA Controller + 1028 0210 PowerEdge T300 onboard SATA Controller + 1028 0211 Optiplex 755 + 1028 023c PowerEdge R200 onboard SATA Controller + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801IR [ICH9R] + 2921 82801IB (ICH9) 2 port SATA Controller [IDE mode] + 1028 0235 PowerEdge R710 SATA IDE Controller + 1028 0236 PowerEdge R610 SATA IDE Controller + 1028 0237 PowerEdge T610 SATA IDE Controller + 1462 7360 G33/P35 Neo + 2922 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode] + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801IR [ICH9R] + 1af4 1100 QEMU Virtual Machine + 8086 5044 Desktop Board DP35DP + 2923 82801IB (ICH9) 4 port SATA Controller [AHCI mode] + 2925 82801IR/IO (ICH9R/DO) SATA Controller [RAID mode] + 1734 10e0 System Board D2542 + 8086 2925 System Board D2542 + 2926 82801I (ICH9 Family) 2 port SATA Controller [IDE mode] + 1028 020d Inspiron 530 + 1028 020f PowerEdge R300 onboard SATA Controller + 1028 0210 PowerEdge T300 onboard SATA Controller + 1028 0211 Optiplex 755 + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801IR [ICH9R] + 1462 7360 G33/P35 Neo + 2928 82801IBM/IEM (ICH9M/ICH9M-E) 2 port SATA Controller [IDE mode] + 2929 82801IBM/IEM (ICH9M/ICH9M-E) 4 port SATA Controller [AHCI mode] + 103c 3628 dv6-1190en + 17aa 20f8 ThinkPad T400 + e4bf cc4d CCM-BOOGIE + 292c 82801IEM (ICH9M-E) SATA Controller [RAID mode] + 292d 82801IBM/IEM (ICH9M/ICH9M-E) 2 port SATA Controller [IDE mode] + e4bf cc4d CCM-BOOGIE + 2930 82801I (ICH9 Family) SMBus Controller + 1028 020d Inspiron 530 + 1028 0211 Optiplex 755 + 103c 2a6f Asus IPIBL-LB Motherboard + 103c 3628 dv6-1190en + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7360 G33/P35 Neo + 17aa 20f9 ThinkPad T400 + 1af4 1100 QEMU Virtual Machine + 8086 5044 Desktop Board DP35DP + e4bf cc4d CCM-BOOGIE + 2932 82801I (ICH9 Family) Thermal Subsystem + 103c 3628 dv6-1190en + 2934 82801I (ICH9 Family) USB UHCI Controller #1 + 1028 020d Inspiron 530 + 1028 020f PowerEdge R300 onboard UHCI + 1028 0210 PowerEdge T300 onboard UHCI + 1028 0211 Optiplex 755 + 1028 0235 PowerEdge R710 USB UHCI Controller + 1028 0236 PowerEdge R610 USB UHCI Controller + 1028 0237 PowerEdge T610 USB UHCI Controller + 1028 023c PowerEdge R200 onboard UHCI + 1028 0287 PowerEdge M610 onboard UHCI + 1028 029c PowerEdge M710 USB UHCI Controller + 1028 2011 Optiplex 755 + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7360 G33/P35 Neo + 17aa 20f0 ThinkPad T400 + 1af4 1100 QEMU Virtual Machine + 8086 5044 Desktop Board DP35DP + e4bf cc4d CCM-BOOGIE + 2935 82801I (ICH9 Family) USB UHCI Controller #2 + 1028 020d Inspiron 530 + 1028 020f PowerEdge R300 onboard UHCI + 1028 0210 PowerEdge T300 onboard UHCI + 1028 0211 Optiplex 755 + 1028 0235 PowerEdge R710 USB UHCI Controller + 1028 0236 PowerEdge R610 USB UHCI Controller + 1028 0237 PowerEdge T610 USB UHCI Controller + 1028 023c PowerEdge R200 onboard UHCI + 1028 0287 PowerEdge M610 onboard UHCI + 1028 029c PowerEdge M710 USB UHCI Controller + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7360 G33/P35 Neo + 17aa 20f0 ThinkPad T400 + 1af4 1100 QEMU Virtual Machine + 8086 5044 Desktop Board DP35DP + e4bf cc4d CCM-BOOGIE + 2936 82801I (ICH9 Family) USB UHCI Controller #3 + 1028 020d Inspiron 530 + 1028 020f PowerEdge R300 onboard UHCI + 1028 0210 PowerEdge T300 onboard UHCI + 1028 0211 Optiplex 755 + 1028 0237 PowerEdge T610 USB UHCI Controller + 1028 023c PowerEdge R200 onboard UHCI + 1028 0287 PowerEdge M610 onboard UHCI + 1028 029c PowerEdge M710 USB UHCI Controller + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7360 G33/P35 Neo + 17aa 20f0 ThinkPad T400 + 1af4 1100 QEMU Virtual Machine + 8086 5044 Desktop Board DP35DP + e4bf cc4d CCM-BOOGIE + 2937 82801I (ICH9 Family) USB UHCI Controller #4 + 1028 020d Inspiron 530 + 1028 0211 Optiplex 755 + 1028 0235 PowerEdge R710 USB UHCI Controller + 1028 0236 PowerEdge R610 USB UHCI Controller + 1028 0237 PowerEdge T610 USB UHCI Controller + 1028 0287 PowerEdge M610 onboard UHCI + 1028 029c PowerEdge M710 USB UHCI Controller + 1028 2011 Optiplex 755 + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7360 G33/P35 Neo + 17aa 20f0 ThinkPad T400 + 1af4 1100 QEMU Virtual Machine + 8086 2937 Optiplex 755 + 8086 2942 828011 (ICH9 Family ) USB UHCI Controller + 8086 5044 Desktop Board DP35DP + e4bf cc4d CCM-BOOGIE + 2938 82801I (ICH9 Family) USB UHCI Controller #5 + 1028 020d Inspiron 530 + 1028 0211 Optiplex 755 + 1028 0235 PowerEdge R710 USB UHCI Controller + 1028 0236 PowerEdge R610 USB UHCI Controller + 1028 0237 PowerEdge T610 USB UHCI Controller + 1028 0287 PowerEdge M610 onboard UHCI + 1028 029c PowerEdge M710 USB UHCI Controller + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7360 G33/P35 Neo + 17aa 20f0 ThinkPad T400 + 1af4 1100 QEMU Virtual Machine + 8086 2938 Optiplex 755 + 8086 5044 Desktop Board DP35DP + e4bf cc4d CCM-BOOGIE + 2939 82801I (ICH9 Family) USB UHCI Controller #6 + 1028 020d Inspiron 530 + 1028 0210 PowerEdge T300 onboard UHCI + 1028 0237 PowerEdge T610 USB UHCI Controller + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7360 G33/P35 Neo + 17aa 20f0 ThinkPad T400 + 1af4 1100 QEMU Virtual Machine + 8086 5044 Desktop Board DP35DP + e4bf cc4d CCM-BOOGIE + 293a 82801I (ICH9 Family) USB2 EHCI Controller #1 + 1028 020d Inspiron 530 + 1028 020f PowerEdge R300 onboard EHCI + 1028 0210 PowerEdge T300 onboard EHCI + 1028 0211 Optiplex 755 + 1028 0235 PowerEdge R710 USB EHCI Controller + 1028 0236 PowerEdge R610 USB EHCI Controller + 1028 0237 PowerEdge T610 USB EHCI Controller + 1028 023c PowerEdge R200 onboard EHCI + 1028 0287 PowerEdge M610 onboard EHCI + 1028 029c PowerEdge M710 USB EHCI Controller + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7360 G33/P35 Neo + 17aa 20f1 ThinkPad T400 + 1af4 1100 QEMU Virtual Machine + 8086 5044 Desktop Board DP35DP + e4bf cc4d CCM-BOOGIE + 293c 82801I (ICH9 Family) USB2 EHCI Controller #2 + 1028 020d Inspiron 530 + 1028 0211 Optiplex 755 + 1028 0235 PowerEdge R710 USB EHCI Controller + 1028 0236 PowerEdge R610 USB EHCI Controller + 1028 0237 PowerEdge T610 USB EHCI Controller + 1028 0287 PowerEdge M610 onboard EHCI + 1028 029c PowerEdge M710 USB EHCI Controller + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7360 G33/P35 Neo + 17aa 20f1 ThinkPad T400 + 1af4 1100 QEMU Virtual Machine + 8086 293c Optiplex 755 + 8086 5044 Desktop Board DP35DP + e4bf cc4d CCM-BOOGIE + 293e 82801I (ICH9 Family) HD Audio Controller + 1028 020d Inspiron 530 + 1028 0211 Optiplex 755 + 103c 2a6f Asus IPIBL-LB Motherboard + 103c 3628 dv6-1190en + 1043 829f P5K PRO Motherboard: 82801IR [ICH9R] + 1462 735a MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 1462 7360 G33/P35 Neo + 17aa 20f2 ThinkPad T400 + 1af4 1100 QEMU Virtual Machine + 8086 293e Optiplex 755 + 8086 2940 Optiplex 755 + e4bf cc4d CCM-BOOGIE + 2940 82801I (ICH9 Family) PCI Express Port 1 + 1028 020d Inspiron 530 + 1028 0211 Optiplex 755 + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 8086 2940 Optiplex 755 + 2942 82801I (ICH9 Family) PCI Express Port 2 + 1028 020d Inspiron 530 + 2944 82801I (ICH9 Family) PCI Express Port 3 + 1028 020d Inspiron 530 + 103c 2a6f Asus IPIBL-LB Motherboard + 2946 82801I (ICH9 Family) PCI Express Port 4 + 1028 020d Inspiron 530 + 2948 82801I (ICH9 Family) PCI Express Port 5 + 1028 020d Inspiron 530 + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 294a 82801I (ICH9 Family) PCI Express Port 6 + 1028 020d Inspiron 530 + 1043 8277 P5K PRO Motherboard: 82801IR [ICH9R] + 1462 7345 MS-7345 Motherboard: Intel 82801I/IR [ICH9/ICH9R] + 294c 82566DC-2 Gigabit Network Connection + 17aa 302e 82566DM-2 Gigabit Network Connection + 2970 82946GZ/PL/GL Memory Controller Hub + 1043 823b P5B-MX/WiFi-AP + 2971 82946GZ/PL/GL PCI Express Root Port + 2972 82946GZ/GL Integrated Graphics Controller + 1043 823b P5B-MX/WiFi-AP + 2973 82946GZ/GL Integrated Graphics Controller + 2974 82946GZ/GL HECI Controller + 2975 82946GZ/GL HECI Controller + 2976 82946GZ/GL PT IDER Controller + 2977 82946GZ/GL KT Controller + 2980 82G35 Express DRAM Controller + 2981 82G35 Express PCI Express Root Port + 2982 82G35 Express Integrated Graphics Controller + 2983 82G35 Express Integrated Graphics Controller + 2984 82G35 Express HECI Controller + 2990 82Q963/Q965 Memory Controller Hub + 1028 01da OptiPlex 745 + 2991 82Q963/Q965 PCI Express Root Port + 2992 82Q963/Q965 Integrated Graphics Controller + 2993 82Q963/Q965 Integrated Graphics Controller + 2994 82Q963/Q965 HECI Controller + 2995 82Q963/Q965 HECI Controller + 2996 82Q963/Q965 PT IDER Controller + 2997 82Q963/Q965 KT Controller + 29a0 82P965/G965 Memory Controller Hub + 1043 81ea P5B + 1462 7276 MS-7276 [G965MDH] + 29a1 82P965/G965 PCI Express Root Port + 29a2 82G965 Integrated Graphics Controller + 1462 7276 MS-7276 [G965MDH] + 29a3 82G965 Integrated Graphics Controller + 29a4 82P965/G965 HECI Controller + 29a5 82P965/G965 HECI Controller + 29a6 82P965/G965 PT IDER Controller + 29a7 82P965/G965 KT Controller + 29b0 82Q35 Express DRAM Controller + 1028 0211 OptiPlex 755 + 29b1 82Q35 Express PCI Express Root Port + 1028 0211 OptiPlex 755 + 29b2 82Q35 Express Integrated Graphics Controller + 1028 0211 OptiPlex 755 + 29b3 82Q35 Express Integrated Graphics Controller + 1028 0211 OptiPlex 755 + 29b4 82Q35 Express MEI Controller + 1028 0211 OptiPlex 755 + 29b5 82Q35 Express MEI Controller + 29b6 82Q35 Express PT IDER Controller + 1028 0211 OptiPlex 755 + 29b7 82Q35 Express Serial KT Controller + 1028 0211 OptiPlex 755 + 29c0 82G33/G31/P35/P31 Express DRAM Controller + 1028 020d Inspiron 530 + 103c 2a6f Asus IPIBL-LB Motherboard + 1043 8276 P5K PRO Motherboard: Intel 82P35 Northbridge + 1043 82b0 P5KPL-VM Motherboard + 1462 7345 MS-7345 Motherboard: Intel 82G33/P35 Northbridge + 1462 7360 G33/P35 Neo + 1af4 1100 QEMU Virtual Machine + 8086 5044 Desktop Board DP35DP + 29c1 82G33/G31/P35/P31 Express PCI Express Root Port + 1028 020d Inspiron 530 + 1043 8276 P5K PRO Motherboard: Intel 82P35 Northbridge + 29c2 82G33/G31 Express Integrated Graphics Controller + 1028 020d Inspiron 530 + 1043 82b0 P5KPL-VM Motherboard + 29c3 82G33/G31 Express Integrated Graphics Controller + 1028 020d Inspiron 530 + 1043 82b0 P5KPL-VM Motherboard + 29c4 82G33/G31/P35/P31 Express MEI Controller + 8086 5044 Desktop Board DP35DP + 29c5 82G33/G31/P35/P31 Express MEI Controller + 29c6 82G33/G31/P35/P31 Express PT IDER Controller + 29c7 82G33/G31/P35/P31 Express Serial KT Controller + 29cf Virtual HECI Controller + 29d0 82Q33 Express DRAM Controller + 29d1 82Q33 Express PCI Express Root Port + 29d2 82Q33 Express Integrated Graphics Controller + 29d3 82Q33 Express Integrated Graphics Controller + 29d4 82Q33 Express MEI Controller + 29d5 82Q33 Express MEI Controller + 29d6 82Q33 Express PT IDER Controller + 29d7 82Q33 Express Serial KT Controller + 29e0 82X38/X48 Express DRAM Controller + 29e1 82X38/X48 Express Host-Primary PCI Express Bridge + 29e4 82X38/X48 Express MEI Controller + 29e5 82X38/X48 Express MEI Controller + 29e6 82X38/X48 Express PT IDER Controller + 29e7 82X38/X48 Express Serial KT Controller + 29e9 82X38/X48 Express Host-Secondary PCI Express Bridge + 29f0 3200/3210 Chipset DRAM Controller + 29f1 3200/3210 Chipset Host-Primary PCI Express Bridge + 29f4 3200/3210 Chipset MEI Controller + 29f5 3200/3210 Chipset MEI Controller + 29f6 3200/3210 Chipset PT IDER Controller + 29f7 3200/3210 Chipset Serial KT Controller + 29f9 3210 Chipset Host-Secondary PCI Express Bridge + 2a00 Mobile PM965/GM965/GL960 Memory Controller Hub + 1025 0121 Aspire 5920G + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30c1 Compaq 6910p + 103c 30cc Pavilion dv6700 + 103c 30d9 Presario C700 + 1043 1017 X58LE + 104d 9005 Vaio VGN-FZ260E + 104d 902d VAIO VGN-NR120E + 17aa 20b1 ThinkPad T61 + 17aa 20b3 ThinkPad T61/R61 + 17c0 4082 Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 2a01 Mobile PM965/GM965/GL960 PCI Express Root Port + 2a02 Mobile GM965/GL960 Integrated Graphics Controller (primary) + 1028 01f3 Inspiron 1420 + 1028 01f9 Latitude D630 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30d9 Presario C700 + 1043 14e2 X58LE + 104d 902d VAIO VGN-NR120E + 17aa 20b5 GM965 [X3100] on ThinkPad T61/R61 + 17c0 4082 GM965 on Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 2a03 Mobile GM965/GL960 Integrated Graphics Controller (secondary) + 1028 01f3 Inspiron 1420 + 1028 022f Inspiron 1525 + 103c 30c0 Compaq 6710b + 103c 30d9 Presario C700 + 1043 14e2 X58LE + 104d 902d VAIO VGN-NR120E + 17aa 20b5 GM965 [X3100] on ThinkPad T61/R61 + 17c0 4082 GM965 on Medion WIM 2210 Notebook PC [MD96850] + e4bf cc47 CCG-RUMBA + 2a04 Mobile PM965/GM965 MEI Controller + 103c 30c1 Compaq 6910p + 2a05 Mobile PM965/GM965 MEI Controller + 2a06 Mobile PM965/GM965 PT IDER Controller + 103c 30c1 Compaq 6910p + 2a07 Mobile PM965/GM965 KT Controller + 103c 30c1 Compaq 6910p + 2a10 Mobile GME965/GLE960 Memory Controller Hub + e4bf cc47 CCG-RUMBA + 2a11 Mobile GME965/GLE960 PCI Express Root Port + 2a12 Mobile GME965/GLE960 Integrated Graphics Controller + e4bf cc47 CCG-RUMBA + 2a13 Mobile GME965/GLE960 Integrated Graphics Controller + e4bf cc47 CCG-RUMBA + 2a14 Mobile GME965/GLE960 MEI Controller + 2a15 Mobile GME965/GLE960 MEI Controller + 2a16 Mobile GME965/GLE960 PT IDER Controller + 2a17 Mobile GME965/GLE960 KT Controller + 2a40 Mobile 4 Series Chipset Memory Controller Hub + 17aa 20e0 ThinkPad T400 + e4bf cc4d CCM-BOOGIE + 2a41 Mobile 4 Series Chipset PCI Express Graphics Port + e4bf cc4d CCM-BOOGIE + 2a42 Mobile 4 Series Chipset Integrated Graphics Controller + 17aa 2112 ThinkPad T400 + e4bf cc4d CCM-BOOGIE + 2a43 Mobile 4 Series Chipset Integrated Graphics Controller + 17aa 2112 ThinkPad T400 + e4bf cc4d CCM-BOOGIE + 2a44 Mobile 4 Series Chipset MEI Controller + 17aa 20e6 ThinkPad T400 + 2a45 Mobile 4 Series Chipset MEI Controller + 2a46 Mobile 4 Series Chipset PT IDER Controller + 2a47 Mobile 4 Series Chipset AMT SOL Redirection + 2a50 Cantiga MEI Controller + 2a51 Cantiga MEI Controller + 2a52 Cantiga PT IDER Controller + 2a53 Cantiga AMT SOL Redirection + 2b00 Xeon Processor E7 Product Family System Configuration Controller 1 + 2b02 Xeon Processor E7 Product Family System Configuration Controller 2 + 2b04 Xeon Processor E7 Product Family Power Controller + 2b08 Xeon Processor E7 Product Family Caching Agent 0 + 2b0c Xeon Processor E7 Product Family Caching Agent 1 + 2b10 Xeon Processor E7 Product Family QPI Home Agent 0 + 2b13 Xeon Processor E7 Product Family Memory Controller 0c + 2b14 Xeon Processor E7 Product Family Memory Controller 0a + 2b16 Xeon Processor E7 Product Family Memory Controller 0b + 2b18 Xeon Processor E7 Product Family QPI Home Agent 1 + 2b1b Xeon Processor E7 Product Family Memory Controller 1c + 2b1c Xeon Processor E7 Product Family Memory Controller 1a + 2b1e Xeon Processor E7 Product Family Memory Controller 1b + 2b20 Xeon Processor E7 Product Family Last Level Cache Coherence Engine 0 + 2b22 Xeon Processor E7 Product Family System Configuration Controller 3 + 2b24 Xeon Processor E7 Product Family Last Level Cache Coherence Engine 1 + 2b28 Xeon Processor E7 Product Family Last Level Cache Coherence Engine 2 + 2b2a Xeon Processor E7 Product Family System Configuration Controller 4 + 2b2c Xeon Processor E7 Product Family Last Level Cache Coherence Engine 3 + 2b30 Xeon Processor E7 Product Family Last Level Cache Coherence Engine 4 + 2b34 Xeon Processor E7 Product Family Last Level Cache Coherence Engine 5 + 2b38 Xeon Processor E7 Product Family Last Level Cache Coherence Engine 6 + 2b3c Xeon Processor E7 Product Family Last Level Cache Coherence Engine 7 + 2b40 Xeon Processor E7 Product Family QPI Router Port 0-1 + 2b42 Xeon Processor E7 Product Family QPI Router Port 2-3 + 2b44 Xeon Processor E7 Product Family QPI Router Port 4-5 + 2b46 Xeon Processor E7 Product Family QPI Router Port 6-7 + 2b48 Xeon Processor E7 Product Family Test and Debug 0 + 2b4c Xeon Processor E7 Product Family Test and Debug 1 + 2b50 Xeon Processor E7 Product Family QPI Physical Port 0: REUT control/status + 2b52 Xeon Processor E7 Product Family QPI Physical Port 0: Misc. control/status + 2b54 Xeon Processor E7 Product Family QPI Physical Port 1: REUT control/status + 2b56 Xeon Processor E7 Product Family QPI Physical Port 1: Misc. control/status + 2b58 Xeon Processor E7 Product Family QPI Physical Port 2: REUT control/status + 2b5a Xeon Processor E7 Product Family QPI Physical Port 2: Misc. control/status + 2b5c Xeon Processor E7 Product Family QPI Physical Port 3: REUT control/status + 2b5e Xeon Processor E7 Product Family QPI Physical Port 3: Misc. control/status + 2b60 Xeon Processor E7 Product Family SMI Physical Port 0: REUT control/status + 2b62 Xeon Processor E7 Product Family SMI Physical Port 0: Misc control/status + 2b64 Xeon Processor E7 Product Family SMI Physical Port 1: REUT control/status + 2b66 Xeon Processor E7 Product Family SMI Physical Port 1: Misc control/status + 2b68 Xeon Processor E7 Product Family Last Level Cache Coherence Engine 8 + 2b6c Xeon Processor E7 Product Family Last Level Cache Coherence Engine 9 + 2c01 Xeon 5500/Core i7 QuickPath Architecture System Address Decoder + 2c10 Xeon 5500/Core i7 QPI Link 0 + 2c11 Xeon 5500/Core i7 QPI Physical 0 + 2c14 Xeon 5500/Core i7 QPI Link 1 + 2c15 Xeon 5500/Core i7 QPI Physical 1 + 2c18 Xeon 5500/Core i7 Integrated Memory Controller + 2c19 Xeon 5500/Core i7 Integrated Memory Controller Target Address Decoder + 2c1a Xeon 5500/Core i7 Integrated Memory Controller RAS Registers + 2c1c Xeon 5500/Core i7 Integrated Memory Controller Test Registers + 2c20 Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Control Registers + 2c21 Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Address Registers + 2c22 Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Rank Registers + 2c23 Xeon 5500/Core i7 Integrated Memory Controller Channel 0 Thermal Control Registers + 2c28 Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Control Registers + 2c29 Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Address Registers + 2c2a Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Rank Registers + 2c2b Xeon 5500/Core i7 Integrated Memory Controller Channel 1 Thermal Control Registers + 2c30 Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Control Registers + 2c31 Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Address Registers + 2c32 Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Rank Registers + 2c33 Xeon 5500/Core i7 Integrated Memory Controller Channel 2 Thermal Control Registers + 2c40 Xeon 5500/Core i7 QuickPath Architecture Generic Non-Core Registers + 2c41 Xeon 5500/Core i7 QuickPath Architecture Generic Non-Core Registers + 2c50 Core Processor QuickPath Architecture Generic Non-Core Registers + 2c51 Core Processor QuickPath Architecture Generic Non-Core Registers + 2c52 Core Processor QuickPath Architecture Generic Non-Core Registers + 2c53 Core Processor QuickPath Architecture Generic Non-Core Registers + 2c54 Core Processor QuickPath Architecture Generic Non-Core Registers + 2c55 Core Processor QuickPath Architecture Generic Non-Core Registers + 2c56 Core Processor QuickPath Architecture Generic Non-Core Registers + 2c57 Core Processor QuickPath Architecture Generic Non-Core Registers + 2c58 Xeon C5500/C3500 QPI Generic Non-core Registers + 2c59 Xeon C5500/C3500 QPI Generic Non-core Registers + 2c5a Xeon C5500/C3500 QPI Generic Non-core Registers + 2c5b Xeon C5500/C3500 QPI Generic Non-core Registers + 2c5c Xeon C5500/C3500 QPI Generic Non-core Registers + 2c5d Xeon C5500/C3500 QPI Generic Non-core Registers + 2c5e Xeon C5500/C3500 QPI Generic Non-core Registers + 2c5f Xeon C5500/C3500 QPI Generic Non-core Registers + 2c61 Core Processor QuickPath Architecture Generic Non-core Registers + 2c62 Core Processor QuickPath Architecture Generic Non-core Registers + 2c70 Xeon 5600 Series QuickPath Architecture Generic Non-core Registers + 2c81 Core Processor QuickPath Architecture System Address Decoder + 2c90 Core Processor QPI Link 0 + 2c91 Core Processor QPI Physical 0 + 2c98 Core Processor Integrated Memory Controller + 2c99 Core Processor Integrated Memory Controller Target Address Decoder + 2c9a Core Processor Integrated Memory Controller Test Registers + 2c9c Core Processor Integrated Memory Controller Test Registers + 2ca0 Core Processor Integrated Memory Controller Channel 0 Control Registers + 2ca1 Core Processor Integrated Memory Controller Channel 0 Address Registers + 2ca2 Core Processor Integrated Memory Controller Channel 0 Rank Registers + 2ca3 Core Processor Integrated Memory Controller Channel 0 Thermal Control Registers + 2ca8 Core Processor Integrated Memory Controller Channel 1 Control Registers + 2ca9 Core Processor Integrated Memory Controller Channel 1 Address Registers + 2caa Core Processor Integrated Memory Controller Channel 1 Rank Registers + 2cab Core Processor Integrated Memory Controller Channel 1 Thermal Control Registers + 2cc1 Xeon C5500/C3500 QPI System Address Decoder + 2cd0 Xeon C5500/C3500 QPI Link 0 + 2cd1 Xeon C5500/C3500 QPI Physical 0 + 2cd4 Xeon C5500/C3500 QPI Link 1 + 2cd5 Xeon C5500/C3500 QPI Physical 1 + 2cd8 Xeon C5500/C3500 Integrated Memory Controller Registers + 2cd9 Xeon C5500/C3500 Integrated Memory Controller Target Address Decoder + 2cda Xeon C5500/C3500 Integrated Memory Controller RAS Registers + 2cdc Xeon C5500/C3500 Integrated Memory Controller Test Registers + 2ce0 Xeon C5500/C3500 Integrated Memory Controller Channel 0 Control + 2ce1 Xeon C5500/C3500 Integrated Memory Controller Channel 0 Address + 2ce2 Xeon C5500/C3500 Integrated Memory Controller Channel 0 Rank + 2ce3 Xeon C5500/C3500 Integrated Memory Controller Channel 0 Thermal Control + 2ce8 Xeon C5500/C3500 Integrated Memory Controller Channel 1 Control + 2ce9 Xeon C5500/C3500 Integrated Memory Controller Channel 1 Address + 2cea Xeon C5500/C3500 Integrated Memory Controller Channel 1 Rank + 2ceb Xeon C5500/C3500 Integrated Memory Controller Channel 1 Thermal Control + 2cf0 Xeon C5500/C3500 Integrated Memory Controller Channel 2 Control + 2cf1 Xeon C5500/C3500 Integrated Memory Controller Channel 2 Address + 2cf2 Xeon C5500/C3500 Integrated Memory Controller Channel 2 Rank + 2cf3 Xeon C5500/C3500 Integrated Memory Controller Channel 2 Thermal Control + 2d01 Core Processor QuickPath Architecture System Address Decoder + 2d10 Core Processor QPI Link 0 + 2d11 1st Generation Core i3/5/7 Processor QPI Physical 0 + 2d12 1st Generation Core i3/5/7 Processor Reserved + 2d13 1st Generation Core i3/5/7 Processor Reserved + 2d81 Xeon 5600 Series QuickPath Architecture System Address Decoder + 2d90 Xeon 5600 Series QPI Link 0 + 2d91 Xeon 5600 Series QPI Physical 0 + 2d92 Xeon 5600 Series Mirror Port Link 0 + 2d93 Xeon 5600 Series Mirror Port Link 1 + 2d94 Xeon 5600 Series QPI Link 1 + 2d95 Xeon 5600 Series QPI Physical 1 + 2d98 Xeon 5600 Series Integrated Memory Controller Registers + 2d99 Xeon 5600 Series Integrated Memory Controller Target Address Decoder + 2d9a Xeon 5600 Series Integrated Memory Controller RAS Registers + 2d9c Xeon 5600 Series Integrated Memory Controller Test Registers + 2da0 Xeon 5600 Series Integrated Memory Controller Channel 0 Control + 2da1 Xeon 5600 Series Integrated Memory Controller Channel 0 Address + 2da2 Xeon 5600 Series Integrated Memory Controller Channel 0 Rank + 2da3 Xeon 5600 Series Integrated Memory Controller Channel 0 Thermal Control + 2da8 Xeon 5600 Series Integrated Memory Controller Channel 1 Control + 2da9 Xeon 5600 Series Integrated Memory Controller Channel 1 Address + 2daa Xeon 5600 Series Integrated Memory Controller Channel 1 Rank + 2dab Xeon 5600 Series Integrated Memory Controller Channel 1 Thermal Control + 2db0 Xeon 5600 Series Integrated Memory Controller Channel 2 Control + 2db1 Xeon 5600 Series Integrated Memory Controller Channel 2 Address + 2db2 Xeon 5600 Series Integrated Memory Controller Channel 2 Rank + 2db3 Xeon 5600 Series Integrated Memory Controller Channel 2 Thermal Control + 2e00 4 Series Chipset DRAM Controller + 2e01 4 Series Chipset PCI Express Root Port + 2e02 4 Series Chipset Integrated Graphics Controller + 2e03 4 Series Chipset Integrated Graphics Controller + 2e04 4 Series Chipset HECI Controller + 2e05 4 Series Chipset HECI Controller + 2e06 4 Series Chipset PT IDER Controller + 2e07 4 Series Chipset Serial KT Controller + 2e10 4 Series Chipset DRAM Controller + 2e11 4 Series Chipset PCI Express Root Port + 2e12 4 Series Chipset Integrated Graphics Controller + 17aa 3048 ThinkCentre M6258 + 2e13 4 Series Chipset Integrated Graphics Controller + 2e14 4 Series Chipset HECI Controller + 2e15 4 Series Chipset HECI Controller + 2e16 4 Series Chipset PT IDER Controller + 2e17 4 Series Chipset Serial KT Controller + 2e20 4 Series Chipset DRAM Controller + 1028 0283 Vostro 220 + 1043 82d3 P5Q Deluxe Motherboard + 1458 5000 GA-EP45-DS5/GA-EG45M-DS2H Motherboard + 2e21 4 Series Chipset PCI Express Root Port + 1043 82d3 P5Q Deluxe Motherboard + 1458 5000 GA-EP45-DS5 Motherboard + 2e22 4 Series Chipset Integrated Graphics Controller + 1458 d000 GA-EG45M-DS2H Mainboard + 2e23 4 Series Chipset Integrated Graphics Controller + 1458 d000 GA-EG45M-DS2H Mainboard + 2e24 4 Series Chipset HECI Controller + 2e25 4 Series Chipset HECI Controller + 2e26 4 Series Chipset PT IDER Controller + 2e27 4 Series Chipset Serial KT Controller + 2e29 4 Series Chipset PCI Express Root Port + 2e30 4 Series Chipset DRAM Controller + 103c 2a8c Compaq 500B Microtower + 2e31 4 Series Chipset PCI Express Root Port + 2e32 4 Series Chipset Integrated Graphics Controller + 103c 2a8c Compaq 500B Microtower + 2e33 4 Series Chipset Integrated Graphics Controller + 2e34 4 Series Chipset HECI Controller + 2e35 4 Series Chipset HECI Controller + 2e36 4 Series Chipset PT IDER Controller + 2e37 4 Series Chipset Serial KT Controller + 2e40 4 Series Chipset DRAM Controller + 2e41 4 Series Chipset PCI Express Root Port + 2e42 4 Series Chipset Integrated Graphics Controller + 2e43 4 Series Chipset Integrated Graphics Controller + 2e44 4 Series Chipset HECI Controller + 2e45 4 Series Chipset HECI Controller + 2e46 4 Series Chipset PT IDER Controller + 2e47 4 Series Chipset Serial KT Controller + 2e50 CE Media Processor CE3100 + 2e52 CE Media Processor Clock and Reset Controller + 2e58 CE Media Processor Interrupt Controller + 2e5a CE Media Processor CE3100 A/V Bridge + 2e5b Graphics Media Accelerator 500 Graphics + 2e5c CE Media Processor Video Decoder + 2e5d CE Media Processor Transport Stream Interface + 2e5e CE Media Processor Transport Stream Processor 0 + 2e5f CE Media Processor Audio DSP + 2e60 CE Media Processor Audio Interfaces + 2e61 CE Media Processor Video Display Controller + 2e62 CE Media Processor Video Processing Unit + 2e63 CE Media Processor HDMI Tx Interface + 2e65 CE Media Processor Expansion Bus Interface + 2e66 CE Media Processor UART + 2e67 CE Media Processor General Purpose I/Os + 2e68 CE Media Processor I2C Interface + 2e69 CE Media Processor Smart Card Interface + 2e6a CE Media Processor SPI Master Interface + 2e6e CE Media Processor Gigabit Ethernet Controller + 2e6f CE Media Processor Media Timing Unit + 2e70 CE Media Processor USB + 2e71 CE Media Processor SATA + 2e73 CE Media Processor CE3100 PCI Express + 2e90 4 Series Chipset DRAM Controller + 2e91 4 Series Chipset PCI Express Root Port + 2e92 4 Series Chipset Integrated Graphics Controller + 2e93 4 Series Chipset Integrated Graphics Controller + 2e94 4 Series Chipset HECI Controller + 2e95 4 Series Chipset HECI Controller + 2e96 4 Series Chipset PT IDER Controller + 2f00 Xeon E7 v3/Xeon E5 v3/Core i7 DMI2 + 2f01 Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 0 + 2f02 Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 1 + 2f03 Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 1 + 2f04 Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 + 2f05 Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 + 2f06 Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 + 2f07 Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 + 2f08 Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 + 2f09 Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 + 2f0a Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 + 2f0b Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 + 2f0d Haswell Xeon Non-Transparent Bridge (Back-to-back) + 2f0e Haswell Xeon Non-Transparent Bridge (Primary Side) + 2f0f Haswell Xeon Non-Transparent Bridge (Secondary Side) + 2f10 Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f11 Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f12 Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f13 Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f14 Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f15 Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f16 Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f17 Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f18 Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f19 Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f1a Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f1b Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f1c Xeon E7 v3/Xeon E5 v3/Core i7 IIO Debug + 2f1d Xeon E7 v3/Xeon E5 v3/Core i7 PCIe Ring Interface + 2f1e Xeon E7 v3/Xeon E5 v3/Core i7 Scratchpad & Semaphore Registers + 2f1f Xeon E7 v3/Xeon E5 v3/Core i7 Scratchpad & Semaphore Registers + 2f20 Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 0 + 2f21 Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 1 + 2f22 Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 2 + 2f23 Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 3 + 2f24 Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 4 + 2f25 Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 5 + 2f26 Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 6 + 2f27 Xeon E7 v3/Xeon E5 v3/Core i7 DMA Channel 7 + 2f28 Xeon E7 v3/Xeon E5 v3/Core i7 Address Map, VTd_Misc, System Management + 2f29 Xeon E7 v3/Xeon E5 v3/Core i7 Hot Plug + 2f2a Xeon E7 v3/Xeon E5 v3/Core i7 RAS, Control Status and Global Errors + 2f2c Xeon E7 v3/Xeon E5 v3/Core i7 I/O APIC + 2f2e Xeon E7 v3/Xeon E5 v3/Core i7 RAID 5/6 + 2f2f Xeon E7 v3/Xeon E5 v3/Core i7 RAID 5/6 + 2f30 Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 0 + 2f32 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 + 2f33 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 + 2f34 Xeon E7 v3/Xeon E5 v3/Core i7 PCIe Ring Interface + 2f36 Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 0 & 1 Monitoring + 2f37 Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 0 & 1 Monitoring + 2f38 Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 1 + 2f39 Xeon E7 v3/Xeon E5 v3/Core i7 I/O Performance Monitoring + 2f3a Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 + 2f3e Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 2 Monitoring + 2f3f Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 2 Monitoring + 2f40 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 + 2f41 Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 2 Monitoring + 2f43 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 + 2f45 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 Debug + 2f46 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 Debug + 2f47 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 2 Debug + 2f60 Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 1 + 2f68 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Target Address, Thermal & RAS Registers + 2f6a Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder + 2f6b Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder + 2f6c Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder + 2f6d Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel Target Address Decoder + 2f6e Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Channel 2/3 Broadcast + 2f6f Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Global Broadcast + 2f70 Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 0 Debug + 2f71 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Target Address, Thermal & RAS Registers + 2f76 Xeon E7 v3/Xeon E5 v3/Core i7 E3 QPI Link Debug + 2f78 Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 1 Debug + 2f79 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Target Address, Thermal & RAS Registers + 2f7d Xeon E7 v3/Xeon E5 v3/Core i7 Scratchpad & Semaphore Registers + 2f7e Xeon E7 v3/Xeon E5 v3/Core i7 E3 QPI Link Debug + 2f80 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 + 2f81 Xeon E7 v3/Xeon E5 v3/Core i7 R3 QPI Link 0 & 1 Monitoring + 2f83 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 + 2f85 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 Debug + 2f86 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 Debug + 2f87 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 0 Debug + 2f88 Xeon E7 v3/Xeon E5 v3/Core i7 VCU + 2f8a Xeon E7 v3/Xeon E5 v3/Core i7 VCU + 2f90 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 + 2f93 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 + 2f95 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 Debug + 2f96 Xeon E7 v3/Xeon E5 v3/Core i7 QPI Link 1 Debug + 2f98 Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + 2f99 Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + 2f9a Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + 2f9c Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + 2fa0 Xeon E7 v3/Xeon E5 v3/Core i7 Home Agent 0 + 2fa8 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Target Address, Thermal & RAS Registers + 2faa Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder + 2fab Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder + 2fac Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder + 2fad Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel Target Address Decoder + 2fae Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Channel 0/1 Broadcast + 2faf Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO Global Broadcast + 2fb0 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 0 Thermal Control + 2fb1 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 1 Thermal Control + 2fb2 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 0 ERROR Registers + 2fb3 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 1 ERROR Registers + 2fb4 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 2 Thermal Control + 2fb5 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 3 Thermal Control + 2fb6 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 2 ERROR Registers + 2fb7 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 0 Channel 3 ERROR Registers + 2fb8 Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 + 2fb9 Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 + 2fba Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 + 2fbb Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 2 & 3 + 2fbc Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 + 2fbd Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 + 2fbe Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 + 2fbf Xeon E7 v3/Xeon E5 v3/Core i7 DDRIO (VMSE) 0 & 1 + 2fc0 Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + 2fc1 Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + 2fc2 Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + 2fc3 Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + 2fc4 Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + 2fc5 Xeon E7 v3/Xeon E5 v3/Core i7 Power Control Unit + 2fd0 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 0 Thermal Control + 2fd1 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 1 Thermal Control + 2fd2 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 0 ERROR Registers + 2fd3 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 1 ERROR Registers + 2fd4 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 2 Thermal Control + 2fd5 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 3 Thermal Control + 2fd6 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 2 ERROR Registers + 2fd7 Xeon E7 v3/Xeon E5 v3/Core i7 Integrated Memory Controller 1 Channel 3 ERROR Registers + 2fe0 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fe1 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fe2 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fe3 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fe4 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fe5 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fe6 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fe7 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fe8 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fe9 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fea Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2feb Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fec Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fed Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fee Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2fef Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2ff0 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2ff1 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2ff2 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2ff3 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2ff4 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2ff5 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2ff6 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2ff7 Xeon E7 v3/Xeon E5 v3/Core i7 Unicast Registers + 2ff8 Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent + 2ff9 Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent + 2ffa Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent + 2ffb Xeon E7 v3/Xeon E5 v3/Core i7 Buffered Ring Agent + 2ffc Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers + 2ffd Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers + 2ffe Xeon E7 v3/Xeon E5 v3/Core i7 System Address Decoder & Broadcast Registers + 3165 Wireless 3165 +# Stone Peak 1x1 + 8086 4010 Dual Band Wireless AC 3165 +# Stone Peak 1x1 + 8086 4210 Dual Band Wireless AC 3165 + 3166 Dual Band Wireless-AC 3165 Plus Bluetooth + 3184 UHD Graphics 605 + 3185 UHD Graphics 605 + 318c Celeron/Pentium Silver Processor Dynamic Platform and Thermal Framework Processor Participant + 318e Celeron/Pentium Silver Processor NorthPeak + 3192 Gemini Lake P2SB + 3197 Celeron/Pentium Silver Processor PCI-default ISA-bridge + 319a Celeron/Pentium Silver Processor Trusted Execution Engine Interface + 31a2 Celeron/Pentium Silver Processor Integrated Sensor Solution + 31ac Celeron/Pentium Silver Processor Serial IO I2C Host Controller + 31ae Celeron/Pentium Silver Processor Serial IO I2C Host Controller + 31bc Celeron/Pentium Silver Processor Serial IO UART Host Controller + 31be Celeron/Pentium Silver Processor Serial IO UART Host Controller + 31c0 Celeron/Pentium Silver Processor Serial IO UART Host Controller + 31c2 Celeron/Pentium Silver Processor Serial IO SPI Host Controller + 31c4 Celeron/Pentium Silver Processor Serial IO SPI Host Controller + 31c6 Celeron/Pentium Silver Processor Serial IO SPI Host Controller + 31cc Celeron/Pentium Silver Processor SDA Standard Compliant SD Host Controller + 31d4 Celeron/Pentium Silver Processor Gaussian Mixture Model + 31d6 Gemini Lake PCI Express Root Port + 31d7 Gemini Lake PCI Express Root Port + 31d8 Gemini Lake PCI Express Root Port + 31d9 Gemini Lake PCI Express Root Port + 31da Gemini Lake PCI Express Root Port + 31db Gemini Lake PCI Express Root Port + 31ee Celeron/Pentium Silver Processor Serial IO UART Host Controller + 31f0 Gemini Lake Host Bridge + 3200 GD31244 PCI-X SATA HBA + 1775 c200 C2K onboard SATA host bus adapter + 3310 IOP348 I/O Processor + 1054 3030 HRA380 Hitachi RAID Adapter to PCIe + 1054 3034 HRA381 Hitachi RAID Adapter to PCIe + 3313 IOP348 I/O Processor (SL8e) in IOC Mode SAS/SATA + 331b IOP348 I/O Processor (SL8x) in IOC Mode SAS/SATA + 3331 IOC340 I/O Controller (VV8e) SAS/SATA + 3339 IOC340 I/O Controller (VV8x) SAS/SATA + 3340 82855PM Processor to I/O Controller + 1014 0529 Thinkpad T40 series + 1025 005a TravelMate 290 + 103c 088c NC8000 laptop + 103c 0890 NC6000 laptop + 103c 08b0 tc1100 tablet + 144d c005 X10 Laptop + 144d c00c P30/P35 notebook + 3341 82855PM Processor to AGP Controller + 144d c00c P30 notebook + 3363 IOC340 I/O Controller in IOC Mode SAS/SATA + 3382 81342 [Chevelon] I/O Processor (ATUe) + 33c3 IOP348 I/O Processor (SL8De) in IOC Mode SAS/SATA + 33cb IOP348 I/O Processor (SL8Dx) in IOC Mode SAS/SATA + 3400 5520/5500/X58 I/O Hub to ESI Port + 3401 5520/5500/X58 I/O Hub to ESI Port + 3402 5520/5500/X58 I/O Hub to ESI Port + 3403 5500 I/O Hub to ESI Port + 1028 0236 PowerEdge R610 I/O Hub to ESI Port + 1028 0287 PowerEdge M610 I/O Hub to ESI Port + 1028 028c PowerEdge R410 I/O Hub to ESI Port + 1028 028d PowerEdge T410 I/O Hub to ESI Port + 103c 330b ProLiant ML150 G6 Server + 3404 5520/5500/X58 I/O Hub to ESI Port + 3405 5520/5500/X58 I/O Hub to ESI Port + 3406 5520 I/O Hub to ESI Port + 103c 330b ProLiant G6 series + 3407 5520/5500/X58 I/O Hub to ESI Port + 3408 5520/5500/X58 I/O Hub PCI Express Root Port 1 + 103c 330b ProLiant G6 series + 3409 5520/5500/X58 I/O Hub PCI Express Root Port 2 + 340a 5520/5500/X58 I/O Hub PCI Express Root Port 3 + 103c 330b ProLiant ML150 G6 Server + 340b 5520/X58 I/O Hub PCI Express Root Port 4 + 340c 5520/X58 I/O Hub PCI Express Root Port 5 + 340d 5520/X58 I/O Hub PCI Express Root Port 6 + 340e 5520/5500/X58 I/O Hub PCI Express Root Port 7 + 103c 330b ProLiant ML150 G6 Server + 340f 5520/5500/X58 I/O Hub PCI Express Root Port 8 + 3410 7500/5520/5500/X58 I/O Hub PCI Express Root Port 9 + 3411 7500/5520/5500/X58 I/O Hub PCI Express Root Port 10 + 3418 7500/5520/5500/X58 Physical Layer Port 0 + 3419 7500/5520/5500 Physical Layer Port 1 + 3420 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 + 3421 7500/5520/5500/X58 I/O Hub PCI Express Root Port 0 + 3422 7500/5520/5500/X58 I/O Hub GPIO and Scratch Pad Registers + 103c 330b ProLiant G6 series + 3423 7500/5520/5500/X58 I/O Hub Control Status and RAS Registers + 103c 330b ProLiant G6 series + 3425 7500/5520/5500/X58 Physical and Link Layer Registers Port 0 + 3426 7500/5520/5500/X58 Routing and Protocol Layer Registers Port 0 + 3427 7500/5520/5500 Physical and Link Layer Registers Port 1 + 3428 7500/5520/5500 Routing & Protocol Layer Register Port 1 + 3429 5520/5500/X58 Chipset QuickData Technology Device + 342a 5520/5500/X58 Chipset QuickData Technology Device + 342b 5520/5500/X58 Chipset QuickData Technology Device + 342c 5520/5500/X58 Chipset QuickData Technology Device + 342d 7500/5520/5500/X58 I/O Hub I/OxAPIC Interrupt Controller + 342e 7500/5520/5500/X58 I/O Hub System Management Registers + 103c 330b ProLiant G6 series + 342f 7500/5520/5500/X58 Trusted Execution Technology Registers + 3430 5520/5500/X58 Chipset QuickData Technology Device + 3431 5520/5500/X58 Chipset QuickData Technology Device + 3432 5520/5500/X58 Chipset QuickData Technology Device + 3433 5520/5500/X58 Chipset QuickData Technology Device + 3438 7500/5520/5500/X58 I/O Hub Throttle Registers + 3482 Ice Lake-LP LPC Controller + 34a3 Ice Lake-LP SMBus Controller + 34a4 Ice Lake-LP SPI Controller + 34a8 Ice Lake-LP Serial IO UART Controller #0 + 34a9 Ice Lake-LP Serial IO UART Controller #1 + 34aa Ice Lake-LP Serial IO SPI Controller #0 + 34ab Ice Lake-LP Serial IO SPI Controller #1 + 34b0 Ice Lake-LP PCI Express Root Port #9 + 34bc Ice Lake-LP PCI Express Root Port #5 + 34c5 Ice Lake-LP Serial IO I2c Controller #4 + 34c6 Ice Lake-LP Serial IO I2c Controller #5 + 34c8 Smart Sound Technology Audio Controller + 34d3 Ice Lake-LP SATA Controller [AHCI mode] + 34e0 Management Engine Interface + 34e8 Ice Lake-LP Serial IO I2C Controller #0 + 34e9 Ice Lake-LP Serial IO I2C Controller #1 + 34ea Ice Lake-LP Serial IO I2C Controller #2 + 34eb Ice Lake-LP Serial IO I2C Controller #3 + 34ed Ice Lake-LP USB 3.1 xHCI Host Controller + 34f0 Killer Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW) + 34f8 Ice Lake-LP SD Controller + 3500 6311ESB/6321ESB PCI Express Upstream Port + 103c 31fe ProLiant DL140 G3 + 15d9 9680 X7DBN Motherboard + 3501 6310ESB PCI Express Upstream Port + 3504 6311ESB/6321ESB I/OxAPIC Interrupt Controller + 3505 6310ESB I/OxAPIC Interrupt Controller + 350c 6311ESB/6321ESB PCI Express to PCI-X Bridge + 103c 31fe ProLiant DL140 G3 + 15d9 9680 X7DBN Motherboard + 350d 6310ESB PCI Express to PCI-X Bridge + 3510 6311ESB/6321ESB PCI Express Downstream Port E1 + 103c 31fe ProLiant DL140 G3 + 15d9 9680 X7DBN Motherboard + 3511 6310ESB PCI Express Downstream Port E1 + 3514 6311ESB/6321ESB PCI Express Downstream Port E2 + 3515 6310ESB PCI Express Downstream Port E2 + 3518 6311ESB/6321ESB PCI Express Downstream Port E3 + 15d9 9680 X7DBN Motherboard + 3519 6310ESB PCI Express Downstream Port E3 + 3575 82830M/MG/MP Host Bridge + 0e11 0030 Evo N600c + 1014 021d ThinkPad A/T/X Series + 104d 80e7 VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP + 3576 82830M/MP AGP Bridge + 3577 82830M/MG Integrated Graphics Controller + 1014 0513 ThinkPad A/T/X Series + 3578 82830M/MG/MP Host Bridge + 3580 82852/82855 GM/GME/PM/GMV Processor to I/O Controller + 1014 055c ThinkPad R50e + 1025 0064 Extensa 3000 series laptop + 1028 0139 Latitude D400 + 1028 014f Latitude X300 + 1028 0152 Latitude D500 + 1028 0163 Latitude D505 + 1028 018d Inspiron 700m/710m + 1028 0196 Inspiron 5160 + 114a 0582 PC8 + 1734 1055 Amilo M1420 + 1775 10d0 V5D Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10e0 PSL09 PrPMC + e4bf 0cc9 CC9-SAMBA + e4bf 0cd2 CD2-BEBOP + 3581 82852/82855 GM/GME/PM/GMV Processor to AGP Controller + 1734 1055 Amilo M1420 + 3582 82852/855GM Integrated Graphics Device + 1014 0562 ThinkPad R50e + 1028 0139 Latitude D400 + 1028 014f Latitude X300 + 1028 0152 Latitude D500 + 1028 0163 Latitude D505 + 1028 018d Inspiron 700m/710m + 114a 0582 PC8 integrated graphics + 1775 10d0 V5D Single Board Computer VGA + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10e0 PSL09 PrPMC + e4bf 0cc9 CC9-SAMBA + e4bf 0cd2 CD2-BEBOP + 3584 82852/82855 GM/GME/PM/GMV Processor to I/O Controller + 1014 055d ThinkPad R50e + 1025 0064 Extensa 3000 series laptop + 1028 0139 Latitude D400 + 1028 014f Latitude X300 + 1028 0152 Latitude D500 + 1028 0163 Latitude D505 + 1028 018d Inspiron 700m/710m + 1028 0196 Inspiron 5160 + 114a 0582 PC8 + 1734 1055 Amilo M1420 + 1775 10d0 V5D Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10e0 PSL09 PrPMC + 3585 82852/82855 GM/GME/PM/GMV Processor to I/O Controller + 1014 055e ThinkPad R50e + 1025 0064 Extensa 3000 series laptop + 1028 0139 Latitude D400 + 1028 014f Latitude X300 + 1028 0152 Latitude D500 + 1028 0163 Latitude D505 + 1028 018d Inspiron 700m/710m + 1028 0196 Inspiron 5160 + 114a 0582 PC8 + 1734 1055 Amilo M1420 + 1775 10d0 V5D Single Board Computer + 1775 ce90 CE9 + 4c53 10b0 CL9 mainboard + 4c53 10e0 PSL09 PrPMC + 358c 82854 GMCH + 358e 82854 GMCH Integrated Graphics Device + 3590 E7520 Memory Controller Hub + 1014 02dd eServer xSeries server mainboard + 1028 016c PowerEdge 1850 Memory Controller Hub + 1028 016d PowerEdge 2850 Memory Controller Hub + 1028 019a PowerEdge SC1425 + 1734 103e PRIMERGY RX/TX S2 series + 1775 1100 CR11/VR11 Single Board Computer + 4c53 10d0 Telum ASLP10 Processor AMC + 3591 E7525/E7520 Error Reporting Registers + 1014 02dd eServer xSeries server mainboard + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 103c 3208 ProLiant DL140 G2 + 4c53 10d0 Telum ASLP10 Processor AMC + 3592 E7320 Memory Controller Hub + 1734 1073 Primergy Econel 200 D2020 mainboard + 3593 E7320 Error Reporting Registers + 1734 1073 Primergy Econel 200 D2020 mainboard + 3594 E7520 DMA Controller + 1775 1100 CR11/VR11 Single Board Computer + 4c53 10d0 Telum ASLP10 Processor AMC + 3595 E7525/E7520/E7320 PCI Express Port A + 1775 1100 CR11/VR11 Single Board Computer + 3596 E7525/E7520/E7320 PCI Express Port A1 + 3597 E7525/E7520 PCI Express Port B + 1775 1100 CR11/VR11 Single Board Computer + 3598 E7520 PCI Express Port B1 + 1775 1100 CR11/VR11 Single Board Computer + 3599 E7520 PCI Express Port C + 1775 1100 CR11/VR11 Single Board Computer + 359a E7520 PCI Express Port C1 + 359b E7525/E7520/E7320 Extended Configuration Registers + 1014 02dd eServer xSeries server mainboard + 359e E7525 Memory Controller Hub + 1028 0168 Precision Workstation 670 Mainboard + 1028 0169 Precision 470 + 35b0 3100 Chipset Memory I/O Controller Hub + 35b1 3100 DRAM Controller Error Reporting Registers + 35b5 3100 Chipset Enhanced DMA Controller + 35b6 3100 Chipset PCI Express Port A + 35b7 3100 Chipset PCI Express Port A1 + 35c8 3100 Extended Configuration Test Overflow Registers + 3600 7300 Chipset Memory Controller Hub + 3604 7300 Chipset PCI Express Port 1 + 3605 7300 Chipset PCI Express Port 2 + 3606 7300 Chipset PCI Express Port 3 + 3607 7300 Chipset PCI Express Port 4 + 3608 7300 Chipset PCI Express Port 5 + 3609 7300 Chipset PCI Express Port 6 + 360a 7300 Chipset PCI Express Port 7 + 360b 7300 Chipset QuickData Technology Device + 360c 7300 Chipset FSB Registers + 1028 01f0 PowerEdge R900 7300 Chipset FSB Registers + 360d 7300 Chipset Snoop Filter Registers + 360e 7300 Chipset Debug and Miscellaneous Registers + 360f 7300 Chipset FBD Branch 0 Registers + 3610 7300 Chipset FBD Branch 1 Registers + 3700 Xeon C5500/C3500 DMI + 3701 Xeon C5500/C3500 DMI + 3702 Xeon C5500/C3500 DMI + 3703 Xeon C5500/C3500 DMI + 3704 Xeon C5500/C3500 DMI + 3705 Xeon C5500/C3500 DMI + 3706 Xeon C5500/C3500 DMI + 3707 Xeon C5500/C3500 DMI + 3708 Xeon C5500/C3500 DMI + 3709 Xeon C5500/C3500 DMI + 370a Xeon C5500/C3500 DMI + 370b Xeon C5500/C3500 DMI + 370c Xeon C5500/C3500 DMI + 370d Xeon C5500/C3500 DMI + 370e Xeon C5500/C3500 DMI + 370f Xeon C5500/C3500 DMI + 3710 Xeon C5500/C3500 CB3 DMA + 3711 Xeon C5500/C3500 CB3 DMA + 3712 Xeon C5500/C3500 CB3 DMA + 3713 Xeon C5500/C3500 CB3 DMA + 3714 Xeon C5500/C3500 CB3 DMA + 3715 Xeon C5500/C3500 CB3 DMA + 3716 Xeon C5500/C3500 CB3 DMA + 3717 Xeon C5500/C3500 CB3 DMA + 3718 Xeon C5500/C3500 CB3 DMA + 3719 Xeon C5500/C3500 CB3 DMA + 371a Xeon C5500/C3500 QPI Link + 371b Xeon C5500/C3500 QPI Routing and Protocol + 371d Xeon C5500/C3500 QPI Routing and Protocol + 3720 Xeon C5500/C3500 PCI Express Root Port 0 + 3721 Xeon C5500/C3500 PCI Express Root Port 1 + 3722 Xeon C5500/C3500 PCI Express Root Port 2 + 3723 Xeon C5500/C3500 PCI Express Root Port 3 + 3724 Xeon C5500/C3500 PCI Express Root Port 4 + 3725 Xeon C5500/C3500 NTB Primary + 3726 Xeon C5500/C3500 NTB Primary + 3727 Xeon C5500/C3500 NTB Secondary + 3728 Xeon C5500/C3500 Core + 3729 Xeon C5500/C3500 Core + 372a Xeon C5500/C3500 Core + 372b Xeon C5500/C3500 Core + 372c Xeon C5500/C3500 Reserved + 373f Xeon C5500/C3500 IOxAPIC + 37c8 C62x Chipset QuickAssist Technology + 37cc Ethernet Connection X722 + 37cd Ethernet Virtual Function 700 Series + 37ce Ethernet Connection X722 for 10GbE backplane + 1590 0215 Ethernet 10Gb 2-port 568i Adapter + 17aa 4023 Intel Ethernet Connection X722 for 10GbE backplane + 17aa 4025 Ethernet Connection X722 for 10GbE backplane + 37cf Ethernet Connection X722 for 10GbE QSFP+ + 37d0 Ethernet Connection X722 for 10GbE SFP+ + 17aa 4020 Intel Ethernet Connection X722 for 10G SFP+ + 17aa 4021 Intel Ethernet Connection X722 for 10G SFP+ + 17aa 4022 Ethernet Connection X722 for 10GbE SFP+ + 8086 0001 Ethernet Network Adapter X722-2 + 8086 0002 Ethernet Network Adapter X722-2 + 8086 0003 Ethernet Network Adapter X722-4 + 8086 0004 Ethernet Network Adapter X722-4 + 37d1 Ethernet Connection X722 for 1GbE + 14cd 0010 88E1514 Ethernet OCP 2x1G RJ45 Phy Card [USI-1514-1GbaseT] + 1590 0216 Ethernet 1Gb 2-port 368i Adapter + 1590 0217 Ethernet 1Gb 2-port 368FLR-MMT Adapter + 1590 0247 Ethernet 1Gb 4-port 369i Adapter + 17aa 4020 Ethernet Connection X722 for 1GbE + 17aa 4021 Ethernet Connection X722 for 1GbE + 17aa 4022 Ethernet Connection X722 for 1GbE + 17aa 4024 Ethernet Connection X722 for 1GbE + 37d2 Ethernet Connection X722 for 10GBASE-T + 1059 0180 RD10019 10GbE interface + 1170 37d2 Ethernet Connection X722 for 10GBASE-T + 14cd 0030 Ethernet OCP 2x10G RJ45 Phy Card [USI-X557-10GbaseT] + 1590 0218 Ethernet 10Gb 2-port 568FLR-MMT Adapter + 17aa 4020 Ethernet Connection X722 for 10GBASE-T + 17aa 4021 Ethernet Connection X722 for 10GBASE-T + 17aa 4022 Ethernet Connection X722 for 10GBASE-T + 17aa 4024 Ethernet Connection X722 for 10GBASE-T + 17aa 4025 Ethernet Connection X722 for 10GBASE-T + 37d3 Ethernet Connection X722 for 10GbE SFP+ + 1590 0219 Ethernet 10Gb 2-port 568FLR-MMSFP+ Adapter + 17aa 4020 Ethernet Connection X722 for 10GbE SFP+ + 17aa 4021 Ethernet Connection X722 for 10GbE SFP+ + 17aa 4025 Ethernet Connection X722 for 10GbE SFP+ + 37d4 Ethernet Connection X722 for 10GbE QSFP+ + 37d9 X722 Hyper-V Virtual Function + 3a00 82801JD/DO (ICH10 Family) 4-port SATA IDE Controller + 3a02 82801JD/DO (ICH10 Family) SATA AHCI Controller + 3a05 82801JD/DO (ICH10 Family) SATA RAID Controller + 3a06 82801JD/DO (ICH10 Family) 2-port SATA IDE Controller + 3a14 82801JDO (ICH10DO) LPC Interface Controller + 3a16 82801JIR (ICH10R) LPC Interface Controller + 1028 028c PowerEdge R410 LPC Interface Controller + 1028 028d PowerEdge T410 LPC Interface Controller + 103c 330b ProLiant G6 series + 1043 82d4 P5Q Deluxe Motherboard + 1458 5001 GA-EP45-DS5 Motherboard + 3a18 82801JIB (ICH10) LPC Interface Controller + 3a1a 82801JD (ICH10D) LPC Interface Controller + 3a20 82801JI (ICH10 Family) 4 port SATA IDE Controller #1 + 1028 028c PowerEdge R410 SATA IDE Controller + 1028 028d PowerEdge T410 SATA IDE Controller + 3a22 82801JI (ICH10 Family) SATA AHCI Controller + 103c 330b ProLiant G6 series + 1043 82d4 P5Q Deluxe Motherboard + 1458 b005 GA-EP45-DS5/GA-EG45M-DS2H Motherboard + 3a25 82801JIR (ICH10R) SATA RAID Controller + 1028 028c PERC S100 Controller (PE R410) + 1028 028d PERC S100 Controller (PE T410) + 1028 02f1 PERC S100 Controller (PE R510) + 3a26 82801JI (ICH10 Family) 2 port SATA IDE Controller #2 + 1028 028c PowerEdge R410 SATA IDE Controller + 1028 028d PowerEdge T410 SATA IDE Controller + 3a30 82801JI (ICH10 Family) SMBus Controller + 1043 82d4 P5Q Deluxe Motherboard + 1458 5001 GA-EP45-DS5/GA-EG45M-DS2H Motherboard + 3a32 82801JI (ICH10 Family) Thermal Subsystem + 3a34 82801JI (ICH10 Family) USB UHCI Controller #1 + 1028 028c PowerEdge R410 USB UHCI Controller + 1028 028d PowerEdge T410 USB UHCI Controller + 103c 330b ProLiant G6 series + 1043 82d4 P5Q Deluxe Motherboard + 1458 5004 GA-EP45-DS5 Motherboard + 3a35 82801JI (ICH10 Family) USB UHCI Controller #2 + 1028 028c PowerEdge R410 USB UHCI Controller + 1028 028d PowerEdge T410 USB UHCI Controller + 103c 330b ProLiant G6 series + 1043 82d4 P5Q Deluxe Motherboard + 1458 5004 GA-EP45-DS5 Motherboard + 3a36 82801JI (ICH10 Family) USB UHCI Controller #3 + 1028 028c PowerEdge R410 USB UHCI Controller + 1028 028d PowerEdge T410 USB UHCI Controller + 103c 330b ProLiant G6 series + 1043 82d4 P5Q Deluxe Motherboard + 1458 5004 GA-EP45-DS5 Motherboard + 3a37 82801JI (ICH10 Family) USB UHCI Controller #4 + 1028 028c PowerEdge R410 USB UHCI Controller + 1028 028d PowerEdge T410 USB UHCI Controller + 103c 330b ProLiant G6 series + 1043 82d4 P5Q Deluxe Motherboard + 1458 5004 Motherboard + 3a38 82801JI (ICH10 Family) USB UHCI Controller #5 + 1028 028c PowerEdge R410 USB UHCI Controller + 1028 028d PowerEdge T410 USB UHCI Controller + 103c 330b ProLiant ML150 G6 Server + 1043 82d4 P5Q Deluxe Motherboard + 1458 5004 Motherboard + 3a39 82801JI (ICH10 Family) USB UHCI Controller #6 + 1028 028c PowerEdge R410 USB UHCI Controller + 1028 028d PowerEdge T410 USB UHCI Controller + 103c 330b ProLiant ML150 G6 Server + 1043 82d4 P5Q Deluxe Motherboard + 1458 5004 Motherboard + 3a3a 82801JI (ICH10 Family) USB2 EHCI Controller #1 + 1028 028c PowerEdge R410 USB EHCI Controller + 1028 028d PowerEdge T410 USB EHCI Controller + 103c 330b ProLiant G6 series + 1043 82d4 P5Q Deluxe Motherboard + 1458 5006 GA-EP45-DS5 Motherboard + 3a3c 82801JI (ICH10 Family) USB2 EHCI Controller #2 + 1028 028c PowerEdge R410 USB EHCI Controller + 1028 028d PowerEdge T410 USB EHCI Controller + 103c 330b ProLiant G6 series + 1043 82d4 P5Q Deluxe Motherboard + 1458 5006 Motherboard + 3a3e 82801JI (ICH10 Family) HD Audio Controller + 1043 8311 P5Q Deluxe Motherboard + 1458 a002 GA-EP45-UD3R Motherboard + 1458 a102 GA-EP45-DS5/GA-EG45M-DS2H Motherboard + 3a40 82801JI (ICH10 Family) PCI Express Root Port 1 + 1028 028c PowerEdge R410 PCI Express Port 1 + 1028 028d PowerEdge T410 PCI Express Port 1 + 103c 330b ProLiant ML150 G6 Server + 1043 82d4 P5Q Deluxe Motherboard + 1043 82ea P6T DeLuxe Motherboard + 1458 5001 GA-EP45-DS5/GA-EG45M-DS2H Motherboard + 3a42 82801JI (ICH10 Family) PCI Express Port 2 + 3a44 82801JI (ICH10 Family) PCI Express Root Port 3 + 1043 82ea P6T DeLuxe Motherboard + 3a46 82801JI (ICH10 Family) PCI Express Root Port 4 + 1043 82ea P6T DeLuxe Motherboard + 1458 5001 GA-EP45-DS5 Motherboard + 3a48 82801JI (ICH10 Family) PCI Express Root Port 5 + 103c 330b ProLiant ML150 G6 Server + 1043 82ea P6T Deluxe Motherboard + 1458 5001 GA-EP45-DS5 Motherboard + 3a4a 82801JI (ICH10 Family) PCI Express Root Port 6 + 103c 330b ProLiant ML150 G6 Server + 1043 82d4 P5Q Deluxe Motherboard + 1043 82ea P6T DeLuxe Motherboard + 1458 5001 GA-EP45-DS5/GA-EG45M-DS2H Motherboard + 3a4c 82801JI (ICH10 Family) Gigabit Ethernet Controller + 3a51 82801JDO (ICH10DO) VECI Controller + 3a55 82801JD/DO (ICH10 Family) Virtual SATA Controller + 3a60 82801JD/DO (ICH10 Family) SMBus Controller + 3a62 82801JD/DO (ICH10 Family) Thermal Subsystem + 3a64 82801JD/DO (ICH10 Family) USB UHCI Controller #1 + 3a65 82801JD/DO (ICH10 Family) USB UHCI Controller #2 + 3a66 82801JD/DO (ICH10 Family) USB UHCI Controller #3 + 3a67 82801JD/DO (ICH10 Family) USB UHCI Controller #4 + 3a68 82801JD/DO (ICH10 Family) USB UHCI Controller #5 + 3a69 82801JD/DO (ICH10 Family) USB UHCI Controller #6 + 3a6a 82801JD/DO (ICH10 Family) USB2 EHCI Controller #1 + 3a6c 82801JD/DO (ICH10 Family) USB2 EHCI Controller #2 + 3a6e 82801JD/DO (ICH10 Family) HD Audio Controller + 3a70 82801JD/DO (ICH10 Family) PCI Express Port 1 + 3a72 82801JD/DO (ICH10 Family) PCI Express Port 2 + 3a74 82801JD/DO (ICH10 Family) PCI Express Port 3 + 3a76 82801JD/DO (ICH10 Family) PCI Express Port 4 + 3a78 82801JD/DO (ICH10 Family) PCI Express Port 5 + 3a7a 82801JD/DO (ICH10 Family) PCI Express Port 6 + 3a7c 82801JD/DO (ICH10 Family) Gigabit Ethernet Controller + 3b00 5 Series/3400 Series Chipset LPC Interface Controller + 3b01 Mobile 5 Series Chipset LPC Interface Controller + 3b02 P55 Chipset LPC Interface Controller + 3b03 PM55 Chipset LPC Interface Controller + 3b04 5 Series Chipset LPC Interface Controller + 3b05 Mobile 5 Series Chipset LPC Interface Controller + 3b06 H55 Chipset LPC Interface Controller + 3b07 QM57 Chipset LPC Interface Controller + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + e4bf 50c1 PC1-GROOVE + 3b08 H57 Chipset LPC Interface Controller + 3b09 HM55 Chipset LPC Interface Controller + 1025 0347 Aspire 7740G + 144d c06a R730 Laptop + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 3b0a Q57 Chipset LPC Interface Controller + 1028 02da OptiPlex 980 + 15d9 060d C7SIM-Q Motherboard + 3b0b HM57 Chipset LPC Interface Controller + 3b0c 5 Series Chipset LPC Interface Controller + 3b0d 5 Series/3400 Series Chipset LPC Interface Controller + 3b0e 5 Series/3400 Series Chipset LPC Interface Controller + 3b0f QS57 Chipset LPC Interface Controller + 3b10 5 Series/3400 Series Chipset LPC Interface Controller + 3b11 5 Series/3400 Series Chipset LPC Interface Controller + 3b12 3400 Series Chipset LPC Interface Controller + 3b13 5 Series/3400 Series Chipset LPC Interface Controller + 3b14 3420 Chipset LPC Interface Controller + 15d9 0605 X8SIL + 3b15 5 Series/3400 Series Chipset LPC Interface Controller + 3b16 3450 Chipset LPC Interface Controller + 3b17 5 Series/3400 Series Chipset LPC Interface Controller + 3b18 5 Series/3400 Series Chipset LPC Interface Controller + 3b19 5 Series/3400 Series Chipset LPC Interface Controller + 3b1a 5 Series/3400 Series Chipset LPC Interface Controller + 3b1b 5 Series/3400 Series Chipset LPC Interface Controller + 3b1c 5 Series/3400 Series Chipset LPC Interface Controller + 3b1d 5 Series/3400 Series Chipset LPC Interface Controller + 3b1e 5 Series/3400 Series Chipset LPC Interface Controller + 3b1f 5 Series/3400 Series Chipset LPC Interface Controller + 3b20 5 Series/3400 Series Chipset 4 port SATA IDE Controller + 3b21 5 Series/3400 Series Chipset 2 port SATA IDE Controller + 3b22 5 Series/3400 Series Chipset 6 port SATA AHCI Controller + 1028 02da OptiPlex 980 + 15d9 0605 X8SIL + 15d9 060d C7SIM-Q Motherboard + 3b23 5 Series/3400 Series Chipset 4 port SATA AHCI Controller + 3b25 5 Series/3400 Series Chipset SATA RAID Controller + 103c 3118 Smart Array B110i SATA RAID Controller + 3b26 5 Series/3400 Series Chipset 2 port SATA IDE Controller + 3b28 5 Series/3400 Series Chipset 4 port SATA IDE Controller + 144d c06a R730 Laptop + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 3b29 5 Series/3400 Series Chipset 4 port SATA AHCI Controller + 1025 0347 Aspire 7740G + 144d c06a R730 Laptop + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 3b2c 5 Series/3400 Series Chipset SATA RAID Controller + 3b2d 5 Series/3400 Series Chipset 2 port SATA IDE Controller + 144d c06a R730 Laptop + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + e4bf 50c1 PC1-GROOVE + 3b2e 5 Series/3400 Series Chipset 4 port SATA IDE Controller + e4bf 50c1 PC1-GROOVE + 3b2f 5 Series/3400 Series Chipset 6 port SATA AHCI Controller + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + e4bf 50c1 PC1-GROOVE + 3b30 5 Series/3400 Series Chipset SMBus Controller + 1025 0347 Aspire 7740G + 1028 02da OptiPlex 980 + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 1043 3838 P7P55-M Motherboard + 1043 8383 P7P55-M Motherboard + 144d c06a R730 Laptop + 15d9 0605 X8SIL + 15d9 060d C7SIM-Q Motherboard + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + e4bf 50c1 PC1-GROOVE + 3b32 5 Series/3400 Series Chipset Thermal Subsystem + 1025 0347 Aspire 7740G + 1028 040a Latitude E6410 + 144d c06a R730 Laptop + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 3b34 5 Series/3400 Series Chipset USB2 Enhanced Host Controller + 1025 0347 Aspire 7740G + 1028 02da OptiPlex 980 + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 144d c06a R730 Laptop + 15d9 0605 X8SIL + 15d9 060d C7SIM-Q Motherboard + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + e4bf 50c1 PC1-GROOVE + 3b36 5 Series/3400 Series Chipset USB Universal Host Controller + 3b37 5 Series/3400 Series Chipset USB Universal Host Controller + 3b38 5 Series/3400 Series Chipset USB Universal Host Controller + 3b39 5 Series/3400 Series Chipset USB Universal Host Controller + 3b3a 5 Series/3400 Series Chipset USB Universal Host Controller + 3b3b 5 Series/3400 Series Chipset USB Universal Host Controller + 3b3c 5 Series/3400 Series Chipset USB2 Enhanced Host Controller + 1025 0347 Aspire 7740G + 1028 02da OptiPlex 980 + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 144d c06a R730 Laptop + 15d9 0605 X8SIL + 15d9 060d C7SIM-Q Motherboard + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + e4bf 50c1 PC1-GROOVE + 3b3e 5 Series/3400 Series Chipset USB Universal Host Controller + 3b3f 5 Series/3400 Series Chipset USB Universal Host Controller + 3b40 5 Series/3400 Series Chipset USB Universal Host Controller + 3b41 5 Series/3400 Series Chipset LAN Controller + 3b42 5 Series/3400 Series Chipset PCI Express Root Port 1 + 1028 02da OptiPlex 980 + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 144d c06a R730 Laptop + 15d9 060d C7SIM-Q Motherboard + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 3b44 5 Series/3400 Series Chipset PCI Express Root Port 2 + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 15d9 060d C7SIM-Q Motherboard + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 3b46 5 Series/3400 Series Chipset PCI Express Root Port 3 + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 144d c06a R730 Laptop + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 3b48 5 Series/3400 Series Chipset PCI Express Root Port 4 + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 144d c06a R730 Laptop + 3b4a 5 Series/3400 Series Chipset PCI Express Root Port 5 + 1028 02da OptiPlex 980 + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + 3b4c 5 Series/3400 Series Chipset PCI Express Root Port 6 + 3b4e 5 Series/3400 Series Chipset PCI Express Root Port 7 + 3b50 5 Series/3400 Series Chipset PCI Express Root Port 8 + 3b53 5 Series/3400 Series Chipset VECI Controller + 3b56 5 Series/3400 Series Chipset High Definition Audio + 1025 0347 Aspire 7740G + 1028 02da OptiPlex 980 + 1028 040a Latitude E6410 + 1028 040b Latitude E6510 + 1043 1373 G73-series gaming laptop + 144d c06a R730 Laptop + 15d9 060d C7SIM-Q Motherboard + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + e4bf 50c1 PC1-GROOVE + 3b57 5 Series/3400 Series Chipset High Definition Audio + 3b64 5 Series/3400 Series Chipset HECI Controller + 1025 0347 Aspire 7740G + 15d9 060d C7SIM-Q Motherboard + 17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410] + e4bf 50c1 PC1-GROOVE + 3b65 5 Series/3400 Series Chipset HECI Controller + 3b66 5 Series/3400 Series Chipset PT IDER Controller + 3b67 5 Series/3400 Series Chipset KT Controller + e4bf 50c1 PC1-GROOVE + 3c00 Xeon E5/Core i7 DMI2 + 3c01 Xeon E5/Core i7 DMI2 in PCI Express Mode + 3c02 Xeon E5/Core i7 IIO PCI Express Root Port 1a + 3c03 Xeon E5/Core i7 IIO PCI Express Root Port 1b + 3c04 Xeon E5/Core i7 IIO PCI Express Root Port 2a + 3c05 Xeon E5/Core i7 IIO PCI Express Root Port 2b + 3c06 Xeon E5/Core i7 IIO PCI Express Root Port 2c + 3c07 Xeon E5/Core i7 IIO PCI Express Root Port 2d + 3c08 Xeon E5/Core i7 IIO PCI Express Root Port 3a in PCI Express Mode + 3c09 Xeon E5/Core i7 IIO PCI Express Root Port 3b + 3c0a Xeon E5/Core i7 IIO PCI Express Root Port 3c + 3c0b Xeon E5/Core i7 IIO PCI Express Root Port 3d + 3c0d Xeon E5/Core i7 Non-Transparent Bridge + 3c0e Xeon E5/Core i7 Non-Transparent Bridge + 3c0f Xeon E5/Core i7 Non-Transparent Bridge + 3c20 Xeon E5/Core i7 DMA Channel 0 + 3c21 Xeon E5/Core i7 DMA Channel 1 + 3c22 Xeon E5/Core i7 DMA Channel 2 + 3c23 Xeon E5/Core i7 DMA Channel 3 + 3c24 Xeon E5/Core i7 DMA Channel 4 + 3c25 Xeon E5/Core i7 DMA Channel 5 + 3c26 Xeon E5/Core i7 DMA Channel 6 + 3c27 Xeon E5/Core i7 DMA Channel 7 + 3c28 Xeon E5/Core i7 Address Map, VTd_Misc, System Management + 3c2a Xeon E5/Core i7 Control Status and Global Errors + 3c2c Xeon E5/Core i7 I/O APIC + 3c2e Xeon E5/Core i7 DMA + 3c2f Xeon E5/Core i7 DMA + 3c40 Xeon E5/Core i7 IIO Switch and IRP Performance Monitor + 3c43 Xeon E5/Core i7 Ring to PCI Express Performance Monitor + 3c44 Xeon E5/Core i7 Ring to QuickPath Interconnect Link 0 Performance Monitor + 3c45 Xeon E5/Core i7 Ring to QuickPath Interconnect Link 1 Performance Monitor + 3c46 Xeon E5/Core i7 Processor Home Agent Performance Monitoring + 3c71 Xeon E5/Core i7 Integrated Memory Controller RAS Registers + 3c80 Xeon E5/Core i7 QPI Link 0 + 3c83 Xeon E5/Core i7 QPI Link Reut 0 + 3c84 Xeon E5/Core i7 QPI Link Reut 0 + 3c90 Xeon E5/Core i7 QPI Link 1 + 3c93 Xeon E5/Core i7 QPI Link Reut 1 + 3c94 Xeon E5/Core i7 QPI Link Reut 1 + 3ca0 Xeon E5/Core i7 Processor Home Agent + 3ca8 Xeon E5/Core i7 Integrated Memory Controller Registers + 3caa Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 0 + 3cab Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 1 + 3cac Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 2 + 3cad Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 3 + 3cae Xeon E5/Core i7 Integrated Memory Controller Target Address Decoder 4 + 3cb0 Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 0 + 3cb1 Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 1 + 3cb2 Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 0 + 3cb3 Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 1 + 3cb4 Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 2 + 3cb5 Xeon E5/Core i7 Integrated Memory Controller Channel 0-3 Thermal Control 3 + 3cb6 Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 2 + 3cb7 Xeon E5/Core i7 Integrated Memory Controller ERROR Registers 3 + 3cb8 Xeon E5/Core i7 DDRIO + 3cc0 Xeon E5/Core i7 Power Control Unit 0 + 3cc1 Xeon E5/Core i7 Power Control Unit 1 + 3cc2 Xeon E5/Core i7 Power Control Unit 2 + 3cd0 Xeon E5/Core i7 Power Control Unit 3 + 3ce0 Xeon E5/Core i7 Interrupt Control Registers + 3ce3 Xeon E5/Core i7 Semaphore and Scratchpad Configuration Registers + 3ce4 Xeon E5/Core i7 R2PCIe + 3ce6 Xeon E5/Core i7 QuickPath Interconnect Agent Ring Registers + 3ce8 Xeon E5/Core i7 Unicast Register 0 + 3ce9 Xeon E5/Core i7 Unicast Register 5 + 3cea Xeon E5/Core i7 Unicast Register 1 + 3ceb Xeon E5/Core i7 Unicast Register 6 + 3cec Xeon E5/Core i7 Unicast Register 3 + 3ced Xeon E5/Core i7 Unicast Register 7 + 3cee Xeon E5/Core i7 Unicast Register 4 + 3cef Xeon E5/Core i7 Unicast Register 8 + 3cf4 Xeon E5/Core i7 Integrated Memory Controller System Address Decoder 0 + 3cf5 Xeon E5/Core i7 Integrated Memory Controller System Address Decoder 1 + 3cf6 Xeon E5/Core i7 System Address Decoder + 3e10 8th Gen Core 4-core Processor Host Bridge/DRAM Registers [Coffee Lake H] + 3e18 8th Gen Core 4-core Workstation Processor Host Bridge/DRAM Registers [Coffee Lake S] + 3e1f 8th Gen Core 4-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S] + 1458 5000 Z370 AORUS Gaming K3-CF + 3e30 8th Gen Core 8-core Desktop Processor Host Bridge/DRAM Registers [Coffee Lake S] + 3e33 8th/9th Gen Core Processor Host Bridge/DRAM Registers [Coffee Lake] + 3e34 Coffee Lake HOST and DRAM Controller + 3e81 8th Gen Core Processor PCIe Controller (x16) + 3e85 8th Gen Core Processor PCIe Controller (x8) + 3e89 8th Gen Core Processor PCIe Controller (x4) + 3e91 8th Gen Core Processor Gaussian Mixture Model + 3e92 UHD Graphics 630 (Desktop) + 3e93 UHD Graphics 610 + 3e96 HD Graphics P630 + 3e98 UHD Graphics 630 (Desktop 9 Series) + 3e9b UHD Graphics 630 (Mobile) + 3ea0 UHD Graphics 620 (Whiskey Lake) + 1028 089e Inspiron 5482 + 3ea5 Iris Plus Graphics 655 + 3ec2 8th Gen Core Processor Host Bridge/DRAM Registers + 1043 8694 PRIME H310M-D + 3ec4 8th Gen Core Processor Host Bridge/DRAM Registers + 3ec6 8th Gen Core Processor Host Bridge/DRAM Registers + 3eca 8th Gen Core Processor Host Bridge/DRAM Registers + 3ed0 8th Gen Core Processor Host Bridge/DRAM Registers + 4000 5400 Chipset Memory Controller Hub + 4001 5400 Chipset Memory Controller Hub + 4003 5400 Chipset Memory Controller Hub + 4021 5400 Chipset PCI Express Port 1 + 4022 5400 Chipset PCI Express Port 2 + 4023 5400 Chipset PCI Express Port 3 + 4024 5400 Chipset PCI Express Port 4 + 4025 5400 Chipset PCI Express Port 5 + 4026 5400 Chipset PCI Express Port 6 + 4027 5400 Chipset PCI Express Port 7 + 4028 5400 Chipset PCI Express Port 8 + 4029 5400 Chipset PCI Express Port 9 + 402d 5400 Chipset IBIST Registers + 402e 5400 Chipset IBIST Registers + 402f 5400 Chipset QuickData Technology Device + 4030 5400 Chipset FSB Registers + 4031 5400 Chipset CE/SF Registers + 4032 5400 Chipset IOxAPIC + 4035 5400 Chipset FBD Registers + 4036 5400 Chipset FBD Registers + 4100 Moorestown Graphics and Video + 4108 Atom Processor E6xx Integrated Graphics Controller + 4109 Atom Processor E6xx Integrated Graphics Controller + 410a Atom Processor E6xx Integrated Graphics Controller + 410b Atom Processor E6xx Integrated Graphics Controller + 410c Atom Processor E6xx Integrated Graphics Controller + 410d Atom Processor E6xx Integrated Graphics Controller + 410e Atom Processor E6xx Integrated Graphics Controller + 410f Atom Processor E6xx Integrated Graphics Controller + 4114 Atom Processor E6xx PCI Host Bridge #1 + 4115 Atom Processor E6xx PCI Host Bridge #2 + 4116 Atom Processor E6xx PCI Host Bridge #3 + 4117 Atom Processor E6xx PCI Host Bridge #4 + 4220 PRO/Wireless 2200BG [Calexico2] Network Connection + 103c 0934 Compaq nw8240/nx8220 + 103c 12f6 nc6120/nc6220/nw8240/nx8220 + 8086 2701 WM3B2200BG Mini-PCI Card + 8086 2712 IBM ThinkPad R50e + 8086 2721 Dell B130 laptop integrated WLAN + 8086 2722 Dell Latitude D600 + 8086 2731 Samsung P35 integrated WLAN + 4222 PRO/Wireless 3945ABG [Golan] Network Connection + 103c 135c PRO/Wireless 3945ABG [Golan] Network Connection + 8086 1000 PRO/Wireless 3945ABG Network Connection + 8086 1001 WM3945ABG MOW2 + 8086 1005 PRO/Wireless 3945BG Network Connection + 8086 1034 PRO/Wireless 3945BG Network Connection + 8086 1044 PRO/Wireless 3945BG Network Connection + 8086 1c00 PRO/Wireless 3945ABG Network Connection + 4223 PRO/Wireless 2915ABG [Calexico2] Network Connection + 1000 8086 mPCI 3B Americas/Europe ZZA + 1001 8086 mPCI 3B Europe ZZE + 1002 8086 mPCI 3B Japan ZZJ + 1003 8086 mPCI 3B High-Band ZZH + 103c 1351 Compaq nc6220 + 4224 PRO/Wireless 2915ABG [Calexico2] Network Connection + 4227 PRO/Wireless 3945ABG [Golan] Network Connection + 8086 1010 ThinkPad R60e + 8086 1011 ThinkPad T60/R60e/X60s/R61 + 8086 1014 PRO/Wireless 3945BG Network Connection + 4229 PRO/Wireless 4965 AG or AGN [Kedron] Network Connection + 8086 1100 Vaio VGN-SZ79SN_C + 8086 1101 PRO/Wireless 4965 AG or AGN + 422b Centrino Ultimate-N 6300 + 8086 1101 Centrino Ultimate-N 6300 3x3 AGN + 8086 1121 Centrino Ultimate-N 6300 3x3 AGN + 422c Centrino Advanced-N 6200 + 8086 1301 Centrino Advanced-N 6200 2x2 AGN + 8086 1306 Centrino Advanced-N 6200 2x2 ABG + 8086 1307 Centrino Advanced-N 6200 2x2 BG + 8086 1321 Centrino Advanced-N 6200 2x2 AGN + 8086 1326 Centrino Advanced-N 6200 2x2 ABG + 4230 PRO/Wireless 4965 AG or AGN [Kedron] Network Connection + 8086 1110 Lenovo ThinkPad T51 + 8086 1111 Lenovo ThinkPad T61 + 4232 WiFi Link 5100 + 8086 1201 WiFi Link 5100 AGN + 8086 1204 WiFi Link 5100 AGN + 8086 1205 WiFi Link 5100 BGN + 8086 1206 WiFi Link 5100 ABG + 8086 1221 WiFi Link 5100 AGN + 8086 1224 WiFi Link 5100 AGN + 8086 1225 WiFi Link 5100 BGN + 8086 1226 WiFi Link 5100 ABG + 8086 1301 WiFi Link 5100 AGN + 8086 1304 WiFi Link 5100 AGN + 8086 1305 WiFi Link 5100 BGN + 8086 1306 WiFi Link 5100 ABG + 8086 1321 WiFi Link 5100 AGN + 8086 1324 WiFi Link 5100 AGN + 8086 1325 WiFi Link 5100 BGN + 8086 1326 WiFi Link 5100 ABG + 4235 Ultimate N WiFi Link 5300 + 4236 Ultimate N WiFi Link 5300 + 4237 PRO/Wireless 5100 AGN [Shiloh] Network Connection + 8086 1211 WiFi Link 5100 AGN + 8086 1214 WiFi Link 5100 AGN + 8086 1215 WiFi Link 5100 BGN + 8086 1216 WiFi Link 5100 ABG + 8086 1311 WiFi Link 5100 AGN + 8086 1314 WiFi Link 5100 AGN + 8086 1315 WiFi Link 5100 BGN + 8086 1316 WiFi Link 5100 ABG + 4238 Centrino Ultimate-N 6300 + 8086 1111 Centrino Ultimate-N 6300 3x3 AGN + 4239 Centrino Advanced-N 6200 + 8086 1311 Centrino Advanced-N 6200 2x2 AGN + 8086 1316 Centrino Advanced-N 6200 2x2 ABG + 423a PRO/Wireless 5350 AGN [Echo Peak] Network Connection + 423b PRO/Wireless 5350 AGN [Echo Peak] Network Connection + 423c WiMAX/WiFi Link 5150 + 8086 1201 WiMAX/WiFi Link 5150 AGN + 8086 1206 WiMAX/WiFi Link 5150 ABG + 8086 1221 WiMAX/WiFi Link 5150 AGN + 8086 1301 WiMAX/WiFi Link 5150 AGN + 8086 1306 WiMAX/WiFi Link 5150 ABG + 8086 1321 WiMAX/WiFi Link 5150 AGN + 423d WiMAX/WiFi Link 5150 + 8086 1211 WiMAX/WiFi Link 5150 AGN + 8086 1216 WiMAX/WiFi Link 5150 ABG + 8086 1311 WiMAX/WiFi Link 5150 AGN + 8086 1316 WiMAX/WiFi Link 5150 ABG + 444e Turbo Memory Controller + 467f Volume Management Device NVMe RAID Controller + 4c3d Volume Management Device NVMe RAID Controller + 5001 LE80578 + 5002 LE80578 Graphics Processor Unit + 5009 LE80578 Video Display Controller + 500d LE80578 Expansion Bus + 500e LE80578 UART Controller + 500f LE80578 General Purpose IO + 5010 LE80578 I2C Controller + 5012 LE80578 Serial Peripheral Interface Bus + 5020 EP80579 Memory Controller Hub + 5021 EP80579 DRAM Error Reporting Registers + 5023 EP80579 EDMA Controller + 5024 EP80579 PCI Express Port PEA0 + 5025 EP80579 PCI Express Port PEA1 + 5028 EP80579 S-ATA IDE + 5029 EP80579 S-ATA AHCI + 502a EP80579 S-ATA Reserved + 502b EP80579 S-ATA Reserved + 502c EP80579 Integrated Processor ASU + 502d EP80579 Integrated Processor with QuickAssist ASU + 502e EP80579 Reserved + 502f EP80579 Reserved + 5030 EP80579 Reserved + 5031 EP80579 LPC Bus + 5032 EP80579 SMBus Controller + 5033 EP80579 USB 1.1 Controller + 5035 EP80579 USB 2.0 Controller + 5037 EP80579 PCI-PCI Bridge (transparent mode) + 5039 EP80579 Controller Area Network (CAN) interface #1 + 503a EP80579 Controller Area Network (CAN) interface #2 + 503b EP80579 Synchronous Serial Port (SPP) + 503c EP80579 IEEE 1588 Hardware Assist + 503d EP80579 Local Expansion Bus + 503e EP80579 Global Control Unit (GCU) + 503f EP80579 Reserved + 5040 EP80579 Integrated Processor Gigabit Ethernet MAC + 5041 EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC + 5042 EP80579 Reserved + 5043 EP80579 Reserved + 5044 EP80579 Integrated Processor Gigabit Ethernet MAC + 5045 EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC + 5046 EP80579 Reserved + 5047 EP80579 Reserved + 5048 EP80579 Integrated Processor Gigabit Ethernet MAC + 5049 EP80579 Integrated Processor with QuickAssist Gigabit Ethernet MAC + 504a EP80579 Reserved + 504b EP80579 Reserved + 504c EP80579 Integrated Processor with QuickAssist TDM + 5200 EtherExpress PRO/100 Intelligent Server PCI Bridge + 5201 EtherExpress PRO/100 Intelligent Server Fast Ethernet Controller + 8086 0001 EtherExpress PRO/100 Server Ethernet Adapter + 530d 80310 (IOP) IO Processor + 5845 QEMU NVM Express Controller + 1af4 1100 QEMU Virtual Machine + 5900 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + 5901 Xeon E3-1200 v6/7th Gen Core Processor PCIe Controller (x16) + 5902 HD Graphics 610 + 5904 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + 17aa 2247 ThinkPad T570 + 17aa 224f ThinkPad X1 Carbon 5th Gen + 5905 Xeon E3-1200 v6/7th Gen Core Processor PCIe Controller (x8) + 5909 Xeon E3-1200 v6/7th Gen Core Processor PCIe Controller (x4) + 590c Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + 590f Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + 1462 7a68 B250 KRAIT GAMING (MS-7A68) + 5910 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + 5911 Xeon E3-1200 v6/7th Gen Core Processor Gaussian Mixture Model + 5912 HD Graphics 630 + 5914 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + 17aa 225d ThinkPad T480 + 5916 HD Graphics 620 + 17aa 2248 ThinkPad T570 + 17aa 224f ThinkPad X1 Carbon 5th Gen + 5917 UHD Graphics 620 + 17aa 225e ThinkPad T480 + 5918 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + 591b HD Graphics 630 + 591c UHD Graphics 615 + 591d HD Graphics P630 + 591e HD Graphics 615 + 591f Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers + 5923 HD Graphics 635 + 5926 Iris Plus Graphics 640 + 5927 Iris Plus Graphics 650 + 5a84 Celeron N3350/Pentium N4200/Atom E3900 Series Integrated Graphics Controller + 5a85 HD Graphics 500 + 5a88 Celeron N3350/Pentium N4200/Atom E3900 Series Imaging Unit + 5a98 Celeron N3350/Pentium N4200/Atom E3900 Series Audio Cluster + 5a9a Celeron N3350/Pentium N4200/Atom E3900 Series Trusted Execution Engine + 5aa2 Celeron N3350/Pentium N4200/Atom E3900 Series Integrated Sensor Hub + 5aa8 Celeron N3350/Pentium N4200/Atom E3900 Series USB xHCI + 5aac Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #1 + 5aae Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #2 + 5ab0 Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #3 + 5ab2 Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #4 + 5ab4 Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #5 + 5ab6 Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #6 + 5ab8 Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #7 + 5aba Celeron N3350/Pentium N4200/Atom E3900 Series I2C Controller #8 + 5abc Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller #1 + 5abe Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller #2 + 5ac0 Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller #3 + 5ac2 Celeron N3350/Pentium N4200/Atom E3900 Series SPI Controller #1 + 5ac4 Celeron N3350/Pentium N4200/Atom E3900 Series SPI Controller #2 + 5ac6 Celeron N3350/Pentium N4200/Atom E3900 Series SPI Controller #3 + 5ac8 Celeron N3350/Pentium N4200/Atom E3900 Series PWM Pin Controller + 5aca Celeron N3350/Pentium N4200/Atom E3900 Series SDXC/MMC Host Controller + 5acc Celeron N3350/Pentium N4200/Atom E3900 Series eMMC Controller + 5ad0 Celeron N3350/Pentium N4200/Atom E3900 Series SDIO Controller + 5ad4 Celeron N3350/Pentium N4200/Atom E3900 Series SMBus Controller + 5ad6 Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port B #1 + 5ad7 Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port B #2 + 5ad8 Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port A #1 + 5ad9 Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port A #2 + 5ada Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port A #3 + 5adb Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port A #4 + 5ae3 Celeron N3350/Pentium N4200/Atom E3900 Series SATA AHCI Controller + 5ae8 Celeron N3350/Pentium N4200/Atom E3900 Series Low Pin Count Interface + 5aee Celeron N3350/Pentium N4200/Atom E3900 Series HSUART Controller #4 + 5af0 Celeron N3350/Pentium N4200/Atom E3900 Series Host Bridge + 65c0 5100 Chipset Memory Controller Hub + 65e2 5100 Chipset PCI Express x4 Port 2 + 65e3 5100 Chipset PCI Express x4 Port 3 + 65e4 5100 Chipset PCI Express x4 Port 4 + 65e5 5100 Chipset PCI Express x4 Port 5 + 65e6 5100 Chipset PCI Express x4 Port 6 + 65e7 5100 Chipset PCI Express x4 Port 7 + 65f0 5100 Chipset FSB Registers + 1028 020f PowerEdge R300 + 1028 0210 PowerEdge T300 + 65f1 5100 Chipset Reserved Registers + 1028 0210 PowerEdge T300 + 65f3 5100 Chipset Reserved Registers + 65f5 5100 Chipset DDR Channel 0 Registers + 65f6 5100 Chipset DDR Channel 1 Registers + 65f7 5100 Chipset PCI Express x8 Port 2-3 + 65f8 5100 Chipset PCI Express x8 Port 4-5 + 65f9 5100 Chipset PCI Express x8 Port 6-7 + 65fa 5100 Chipset PCI Express x16 Port 4-7 + 65ff 5100 Chipset DMA Engine + 6f00 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2 + 15d9 0832 X10SRL-F + 6f01 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 0 + 6f02 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 1 + 6f03 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 1 + 6f04 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 + 6f05 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 + 6f06 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 + 6f07 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 2 + 6f08 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 + 6f09 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 + 6f0a Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 + 6f0b Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI Express Root Port 3 + 6f10 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f11 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f12 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f13 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f14 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f15 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f16 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f17 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f18 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f19 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f1a Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f1b Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f1c Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Debug + 6f1d Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R2PCIe Agent + 6f1e Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox + 6f1f Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox + 6f20 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 0 + 15d9 0832 X10SRL-F + 6f21 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 1 + 15d9 0832 X10SRL-F + 6f22 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 2 + 15d9 0832 X10SRL-F + 6f23 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 3 + 15d9 0832 X10SRL-F + 6f24 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 4 + 15d9 0832 X10SRL-F + 6f25 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 5 + 15d9 0832 X10SRL-F + 6f26 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 6 + 15d9 0832 X10SRL-F + 6f27 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Crystal Beach DMA Channel 7 + 15d9 0832 X10SRL-F + 6f28 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Map/VTd_Misc/System Management + 15d9 0832 X10SRL-F + 6f29 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO Hot Plug + 15d9 0832 X10SRL-F + 6f2a Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IIO RAS/Control Status/Global Errors + 15d9 0832 X10SRL-F + 6f2c Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC + 15d9 0832 X10SRL-F + 6f30 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0 + 6f32 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 + 6f33 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 + 6f34 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R2PCIe Agent + 6f36 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1 + 6f37 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1 + 6f38 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 + 6f39 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D IO Performance Monitoring + 6f3a Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 + 6f3e Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2 + 6f3f Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2 + 6f40 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 + 6f41 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 2 + 6f43 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 + 6f45 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug + 6f46 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug + 6f47 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug + 6f50 Xeon Processor D Family QuickData Technology Register DMA Channel 0 + 6f51 Xeon Processor D Family QuickData Technology Register DMA Channel 1 + 6f52 Xeon Processor D Family QuickData Technology Register DMA Channel 2 + 6f53 Xeon Processor D Family QuickData Technology Register DMA Channel 3 + 6f54 Xeon Processor D Family QuickAssist Technology + 6f55 Xeon Processor D Family QuickAssist Technology Virtual Fuction + 6f60 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 + 6f68 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS + 6f6a Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder + 6f6b Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder + 6f6c Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder + 6f6d Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder + 6f6e Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Broadcast + 6f6f Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Global Broadcast + 6f70 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0 Debug + 6f71 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Target Address/Thermal/RAS + 6f76 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link Debug + 6f78 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1 Debug + 6f79 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS + 6f7d Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Ubox + 6f7e Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link Debug + 6f80 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 + 6f81 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D R3 QPI Link 0/1 + 6f83 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 + 6f85 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug + 6f86 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug + 6f87 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 0 Debug + 6f88 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6f8a Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6f90 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 + 6f93 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 + 6f95 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 Debug + 6f96 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 1 Debug + 6f98 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6f99 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6f9a Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6f9c Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fa0 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 0 + 6fa8 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Target Address/Thermal/RAS + 6faa Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder + 6fab Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder + 6fac Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder + 6fad Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel Target Address Decoder + 6fae Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Broadcast + 6faf Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Global Broadcast + 6fb0 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 0 Thermal Control + 6fb1 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 1 Thermal Control + 6fb2 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 0 Error + 6fb3 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 1 Error + 6fb4 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 2 Thermal Control + 6fb5 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 3 Thermal Control + 6fb6 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 2 Error + 6fb7 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 0 - Channel 3 Error + 6fb8 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface + 6fb9 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface + 6fba Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface + 6fbb Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 2/3 Interface + 6fbc Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface + 6fbd Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface + 6fbe Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface + 6fbf Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DDRIO Channel 0/1 Interface + 6fc0 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fc1 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fc2 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fc3 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fc4 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fc5 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fc6 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fc7 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fc8 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fc9 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fca Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fcb Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fcc Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fcd Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fce Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fcf Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Power Control Unit + 6fd0 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 0 Thermal Control + 6fd1 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 1 Thermal Control + 6fd2 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 0 Error + 6fd3 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 1 Error + 6fd4 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 2 Thermal Control + 6fd5 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 3 Thermal Control + 6fd6 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 2 Error + 6fd7 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Memory Controller 1 - Channel 3 Error + 6fe0 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fe1 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fe2 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fe3 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fe4 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fe5 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fe6 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fe7 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fe8 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fe9 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fea Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6feb Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fec Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fed Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fee Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6fef Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6ff0 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6ff1 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6ff8 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6ff9 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6ffa Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6ffb Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6ffc Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6ffd Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 6ffe Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Caching Agent + 7000 82371SB PIIX3 ISA [Natoma/Triton II] + 1af4 1100 Qemu virtual machine + 7010 82371SB PIIX3 IDE [Natoma/Triton II] + 1af4 1100 Qemu virtual machine + 7020 82371SB PIIX3 USB [Natoma/Triton II] + 1af4 1100 QEMU Virtual Machine + 7030 430VX - 82437VX TVX [Triton VX] + 7050 Intercast Video Capture Card + 7051 PB 642365-003 (Business Video Conferencing Card) + 7100 430TX - 82439TX MTXC + 7110 82371AB/EB/MB PIIX4 ISA + 15ad 1976 Virtual Machine Chipset + 7111 82371AB/EB/MB PIIX4 IDE + 15ad 1976 Virtual Machine Chipset + 7112 82371AB/EB/MB PIIX4 USB + 15ad 1976 Virtual Machine Chipset + 1af4 1100 QEMU Virtual Machine + 7113 82371AB/EB/MB PIIX4 ACPI + 15ad 1976 Virtual Machine Chipset + 1af4 1100 Qemu virtual machine + 7120 82810 GMCH (Graphics Memory Controller Hub) + 4c53 1040 CL7 mainboard + 4c53 1060 PC7 mainboard + 7121 82810 (CGC) Chipset Graphics Controller + 4c53 1040 CL7 mainboard + 4c53 1060 PC7 mainboard + 8086 4341 Cayman (CA810) Mainboard + 7122 82810 DC-100 (GMCH) Graphics Memory Controller Hub + 7123 82810 DC-100 (CGC) Chipset Graphics Controller + 7124 82810E DC-133 (GMCH) Graphics Memory Controller Hub + 1028 00b4 OptiPlex GX110 + 7125 82810E DC-133 (CGC) Chipset Graphics Controller + 1028 00b4 OptiPlex GX110 + 7126 82810 DC-133 System and Graphics Controller + 7128 82810-M DC-100 System and Graphics Controller + 712a 82810-M DC-133 System and Graphics Controller + 7180 440LX/EX - 82443LX/EX Host bridge + 7181 440LX/EX - 82443LX/EX AGP bridge + 7190 440BX/ZX/DX - 82443BX/ZX/DX Host bridge + 0e11 0500 Armada 1750 Laptop System Chipset + 0e11 b110 Armada M700/E500 + 1028 008e PowerEdge 1300 mainboard + 1043 803b CUBX-L/E Mainboard + 1179 0001 Toshiba Tecra 8100 Laptop System Chipset + 15ad 1976 Virtual Machine Chipset + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard + 7191 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge + 1028 008e PowerEdge 1300 mainboard + 7192 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) + 0e11 0460 Armada 1700 Laptop System Chipset + 1179 0001 Satellite 4010 + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 8086 7190 Dell PowerEdge 350 + 7194 82440MX Host Bridge + 1033 0000 Versa Note Vxi + 4c53 10a0 CA3/CR3 mainboard + 7195 82440MX AC'97 Audio Controller + 1033 80cc Versa Note VXi + 10cf 1099 QSound_SigmaTel Stac97 PCI Audio + 11d4 0040 SoundMAX Integrated Digital Audio + 11d4 0048 SoundMAX Integrated Digital Audio + 7196 82440MX AC'97 Modem Controller + 7198 82440MX ISA Bridge + 7199 82440MX EIDE Controller + 719a 82440MX USB Universal Host Controller + 719b 82440MX Power Management Controller + 71a0 440GX - 82443GX Host bridge + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard + 71a1 440GX - 82443GX AGP bridge + 71a2 440GX - 82443GX Host bridge (AGP disabled) + 4c53 1000 CC7/CR7/CP7/VC7/VP7/VR7 mainboard + 7360 XMM7360 LTE Advanced Modem + 7600 82372FB PIIX5 ISA + 7601 82372FB PIIX5 IDE + 7602 82372FB PIIX5 USB + 7603 82372FB PIIX5 SMBus + 7800 82740 (i740) AGP Graphics Accelerator + 003d 0008 Starfighter AGP + 003d 000b Starfighter AGP + 1092 0100 Stealth II G460 + 10b4 201a Lightspeed 740 + 10b4 202f Lightspeed 740 + 8086 0000 Terminator 2x/i + 8086 0100 Intel740 Graphics Accelerator + 8002 Trusted Execution Technology Registers + 8003 Trusted Execution Technology Registers + 8100 US15W/US15X SCH [Poulsbo] Host Bridge + 8101 US15L/UL11L SCH [Poulsbo] Host Bridge + 8108 US15W/US15X SCH [Poulsbo] Graphics Controller + 8109 US15L/UL11L SCH [Poulsbo] Graphics Controller + 8110 US15W/US15X/US15L/UL11L SCH [Poulsbo] PCI Express Port 1 + 8112 US15W/US15X/US15L/UL11L SCH [Poulsbo] PCI Express Port 2 + 8114 US15W/US15X/US15L/UL11L SCH [Poulsbo] USB UHCI Controller #1 + 8115 US15W/US15X/US15L/UL11L SCH [Poulsbo] USB UHCI Controller #2 + 8116 US15W/US15X/US15L/UL11L SCH [Poulsbo] USB UHCI Controller #3 + 8117 US15W/US15X/US15L/UL11L SCH [Poulsbo] USB EHCI Controller + 8118 US15W/US15X/US15L/UL11L SCH [Poulsbo] USB Client Controller + 8119 US15W/US15X/US15L/UL11L SCH [Poulsbo] LPC Bridge + 811a US15W/US15X/US15L/UL11L SCH [Poulsbo] IDE Controller + 811b US15W/US15X/US15L/UL11L SCH [Poulsbo] HD Audio Controller + 811c US15W/US15X/US15L/UL11L SCH [Poulsbo] SDIO/MMC Controller #1 + 811d US15W/US15X/US15L/UL11L SCH [Poulsbo] SDIO/MMC Controller #2 + 811e US15W/US15X/US15L/UL11L SCH [Poulsbo] SDIO/MMC Controller #3 + 8180 Atom Processor E6xx PCI Express Port 3 + 8181 Atom Processor E6xx PCI Express Port 4 + 8182 Atom Processor E6xx Integrated Graphics Controller + 8183 Atom Processor E6xx Configuration Unit + 8184 Atom Processor E6xx PCI Express Port 1 + 8185 Atom Processor E6xx PCI Express Port 2 + 8186 Atom Processor E6xx LPC Bridge + 84c4 450KX/GX [Orion] - 82454KX/GX PCI bridge + 84c5 450KX/GX [Orion] - 82453KX/GX Memory controller + 84ca 450NX - 82451NX Memory & I/O Controller + 84cb 450NX - 82454NX/84460GX PCI Expander Bridge + 84e0 460GX - 84460GX System Address Controller (SAC) + 84e1 460GX - 84460GX System Data Controller (SDC) + 84e2 460GX - 84460GX AGP Bridge (GXB function 2) + 84e3 460GX - 84460GX Memory Address Controller (MAC) + 84e4 460GX - 84460GX Memory Data Controller (MDC) + 84e6 460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB) + 84ea 460GX - 84460GX AGP Bridge (GXB function 1) + 8500 IXP4XX Network Processor (IXP420/421/422/425/IXC1100) + 1993 0ded mGuard-PCI AV#2 + 1993 0dee mGuard-PCI AV#1 + 1993 0def mGuard-PCI AV#0 + 87c0 UHD Graphics 617 + 8800 Platform Controller Hub EG20T PCI Express Port + 8801 Platform Controller Hub EG20T Packet Hub + 8802 Platform Controller Hub EG20T Gigabit Ethernet Controller + 8803 Platform Controller Hub EG20T General Purpose IO Controller + 8804 Platform Controller Hub EG20T USB OHCI Controller #4 + 8805 Platform Controller Hub EG20T USB OHCI Controller #5 + 8806 Platform Controller Hub EG20T USB OHCI Controller #6 + 8807 Platform Controller Hub EG20T USB2 EHCI Controller #2 + 8808 Platform Controller Hub EG20T USB Client Controller + 8809 Platform Controller Hub EG20T SDIO Controller #1 + 880a Platform Controller Hub EG20T SDIO Controller #2 + 880b Platform Controller Hub EG20T SATA AHCI Controller + 880c Platform Controller Hub EG20T USB OHCI Controller #1 + 880d Platform Controller Hub EG20T USB OHCI Controller #2 + 880e Platform Controller Hub EG20T USB OHCI Controller #3 + 880f Platform Controller Hub EG20T USB2 EHCI Controller #1 + 8810 Platform Controller Hub EG20T DMA Controller #1 + 8811 Platform Controller Hub EG20T UART Controller 0 + 8812 Platform Controller Hub EG20T UART Controller 1 + 8813 Platform Controller Hub EG20T UART Controller 2 + 8814 Platform Controller Hub EG20T UART Controller 3 + 8815 Platform Controller Hub EG20T DMA Controller #2 + 8816 Platform Controller Hub EG20T Serial Peripheral Interface Bus + 8817 Platform Controller Hub EG20T I2C Controller + 8818 Platform Controller Hub EG20T Controller Area Network (CAN) Controller + 8819 Platform Controller Hub EG20T IEEE 1588 Hardware Assist + 8a0d Ice Lake Thunderbolt 3 NHI #1 + 8a13 Ice Lake Thunderbolt 3 USB Controller + 8a17 Ice Lake Thunderbolt 3 NHI #0 + 8a1d Ice Lake Thunderbolt 3 PCI Express Root Port #0 + 8a1f Ice Lake Thunderbolt 3 PCI Express Root Port #1 + 8a21 Ice Lake Thunderbolt 3 PCI Express Root Port #2 + 8a23 Ice Lake Thunderbolt 3 PCI Express Root Port #3 + 8a52 Iris Plus Graphics G7 + 8c00 8 Series/C220 Series Chipset Family 4-port SATA Controller 1 [IDE mode] + 8c01 8 Series Chipset Family 4-port SATA Controller 1 [IDE mode] - Mobile + 8c02 8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] + 17aa 309f ThinkCentre M83 + 8c03 8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] + 103c 1909 ZBook 15 + 17aa 220e ThinkPad T440p + 8c04 8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + 8c05 8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + 8c06 8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + 8c07 8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + 8c08 8 Series/C220 Series Chipset Family 2-port SATA Controller 2 [IDE mode] + 8c09 8 Series/C220 Series Chipset Family 2-port SATA Controller 2 [IDE mode] + 8c0e 8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + 8c0f 8 Series/C220 Series Chipset Family SATA Controller 1 [RAID mode] + 8c10 8 Series/C220 Series Chipset Family PCI Express Root Port #1 + 17aa 220e ThinkPad T440p + 8c11 8 Series/C220 Series Chipset Family PCI Express Root Port #1 + 8c12 8 Series/C220 Series Chipset Family PCI Express Root Port #2 + 17aa 220e ThinkPad T440p + 8c13 8 Series/C220 Series Chipset Family PCI Express Root Port #2 + 8c14 8 Series/C220 Series Chipset Family PCI Express Root Port #3 + 8c15 8 Series/C220 Series Chipset Family PCI Express Root Port #3 + 8c16 8 Series/C220 Series Chipset Family PCI Express Root Port #4 + 8c17 8 Series/C220 Series Chipset Family PCI Express Root Port #4 + 8c18 8 Series/C220 Series Chipset Family PCI Express Root Port #5 + 8c19 8 Series/C220 Series Chipset Family PCI Express Root Port #5 + 8c1a 8 Series/C220 Series Chipset Family PCI Express Root Port #6 + 8c1b 8 Series/C220 Series Chipset Family PCI Express Root Port #6 + 8c1c 8 Series/C220 Series Chipset Family PCI Express Root Port #7 + 8c1d 8 Series/C220 Series Chipset Family PCI Express Root Port #7 + 8c1e 8 Series/C220 Series Chipset Family PCI Express Root Port #8 + 8c1f 8 Series/C220 Series Chipset Family PCI Express Root Port #8 + 8c20 8 Series/C220 Series Chipset High Definition Audio Controller + 103c 1909 ZBook 15 + 17aa 220e ThinkPad T440p + 17aa 309f ThinkCentre M83 + 8c21 8 Series/C220 Series Chipset High Definition Audio Controller + 8c22 8 Series/C220 Series Chipset Family SMBus Controller + 103c 1909 ZBook 15 + 17aa 220e ThinkPad T440p + 17aa 309f ThinkCentre M83 + 8c23 8 Series Chipset Family CHAP Counters + 8c24 8 Series Chipset Family Thermal Management Controller + 8c26 8 Series/C220 Series Chipset Family USB EHCI #1 + 103c 1909 ZBook 15 + 17aa 220e ThinkPad T440p + 17aa 2210 ThinkPad T540p + 17aa 309f ThinkCentre M83 + 2210 17aa ThinkPad T540p + 8c2d 8 Series/C220 Series Chipset Family USB EHCI #2 + 103c 1909 ZBook 15 + 17aa 220e ThinkPad T440p + 17aa 309f ThinkCentre M83 + 8c31 8 Series/C220 Series Chipset Family USB xHCI + 103c 1909 ZBook 15 + 17aa 220e ThinkPad T440p + 17aa 309f ThinkCentre M83 + 8c33 8 Series/C220 Series Chipset Family LAN Controller + 8c34 8 Series/C220 Series Chipset Family NAND Controller + 8c3a 8 Series/C220 Series Chipset Family MEI Controller #1 + 103c 1909 ZBook 15 + 17aa 220e ThinkPad T440p + 17aa 309f ThinkCentre M83 + 8c3b 8 Series/C220 Series Chipset Family MEI Controller #2 + 8c3c 8 Series/C220 Series Chipset Family IDE-r Controller + 8c3d 8 Series/C220 Series Chipset Family KT Controller + 8c40 8 Series/C220 Series Chipset Family LPC Controller + 8c41 8 Series Chipset Family Mobile Super SKU LPC Controller + 8c42 8 Series/C220 Series Chipset Family Desktop Super SKU LPC Controller + 8c43 8 Series/C220 Series Chipset Family LPC Controller + 8c44 Z87 Express LPC Controller + 8c45 8 Series/C220 Series Chipset Family LPC Controller + 8c46 Z85 Express LPC Controller + 8c47 8 Series/C220 Series Chipset Family LPC Controller + 8c48 8 Series/C220 Series Chipset Family LPC Controller + 8c49 HM86 Express LPC Controller + 8c4a H87 Express LPC Controller + 8c4b HM87 Express LPC Controller + 8c4c Q85 Express LPC Controller + 17aa 309f ThinkCentre M83 + 8c4d 8 Series/C220 Series Chipset Family LPC Controller + 8c4e Q87 Express LPC Controller + 8c4f QM87 Express LPC Controller + 103c 1909 ZBook 15 + 17aa 220e ThinkPad T440p + 8c50 B85 Express LPC Controller + 8c51 8 Series/C220 Series Chipset Family LPC Controller + 8c52 C222 Series Chipset Family Server Essential SKU LPC Controller + 8c53 8 Series/C220 Series Chipset Family LPC Controller + 8c54 C224 Series Chipset Family Server Standard SKU LPC Controller + 8c55 8 Series/C220 Series Chipset Family LPC Controller + 8c56 C226 Series Chipset Family Server Advanced SKU LPC Controller + 8c57 8 Series/C220 Series Chipset Family LPC Controller + 8c58 8 Series/C220 Series Chipset Family WS SKU LPC Controller + 8c59 8 Series/C220 Series Chipset Family LPC Controller + 8c5a 8 Series/C220 Series Chipset Family LPC Controller + 8c5b 8 Series/C220 Series Chipset Family LPC Controller + 8c5c H81 Express LPC Controller + 8c5d 8 Series/C220 Series Chipset Family LPC Controller + 8c5e 8 Series/C220 Series Chipset Family LPC Controller + 8c5f 8 Series/C220 Series Chipset Family LPC Controller + 8c80 9 Series Chipset Family SATA Controller [IDE Mode] + 8c81 9 Series Chipset Family SATA Controller [IDE Mode] + 8c82 9 Series Chipset Family SATA Controller [AHCI Mode] + 8c83 9 Series Chipset Family SATA Controller [AHCI Mode] + 8c84 9 Series Chipset Family SATA Controller [RAID Mode] + 8c85 9 Series Chipset Family SATA Controller [RAID Mode] + 8c86 9 Series Chipset Family SATA Controller [RAID Mode] + 8c87 9 Series Chipset Family SATA Controller [RAID Mode] + 8c88 9 Series Chipset Family SATA Controller [IDE Mode] + 8c89 9 Series Chipset Family SATA Controller [IDE Mode] + 8c8e 9 Series Chipset Family SATA Controller [RAID Mode] + 8c8f 9 Series Chipset Family SATA Controller [RAID Mode] + 8c90 9 Series Chipset Family PCI Express Root Port 1 + 8c92 9 Series Chipset Family PCI Express Root Port 2 + 8c94 9 Series Chipset Family PCI Express Root Port 3 + 8c96 9 Series Chipset Family PCI Express Root Port 4 + 8c98 9 Series Chipset Family PCI Express Root Port 5 + 8c9a 9 Series Chipset Family PCI Express Root Port 6 + 8c9c 9 Series Chipset Family PCI Express Root Port 7 + 8c9e 9 Series Chipset Family PCI Express Root Port 8 + 8ca0 9 Series Chipset Family HD Audio Controller + 8ca2 9 Series Chipset Family SMBus Controller + 8ca4 9 Series Chipset Family Thermal Controller + 8ca6 9 Series Chipset Family USB EHCI Controller #1 + 8cad 9 Series Chipset Family USB EHCI Controller #2 + 8cb1 9 Series Chipset Family USB xHCI Controller + 8cb3 9 Series Chipset Family LAN Controller + 8cba 9 Series Chipset Family ME Interface #1 + 8cbb 9 Series Chipset Family ME Interface #2 + 8cbc 9 Series Chipset Family IDE-R Controller + 8cbd 9 Series Chipset Family KT Controller + 8cc1 9 Series Chipset Family LPC Controller + 8cc2 9 Series Chipset Family LPC Controller + 8cc3 HM97 Chipset LPC Controller + 8cc4 Z97 Chipset LPC Controller + 8cc5 QM97 Chipset LPC Controller + 8cc6 H97 Chipset LPC Controller + 8d00 C610/X99 series chipset 4-port SATA Controller [IDE mode] + 8d02 C610/X99 series chipset 6-Port SATA Controller [AHCI mode] + 8d04 C610/X99 series chipset SATA Controller [RAID mode] + 8d06 C610/X99 series chipset SATA Controller [RAID mode] + 17aa 1031 ThinkServer RAID 110i + 8d08 C610/X99 series chipset 2-port SATA Controller [IDE mode] + 8d0e C610/X99 series chipset SATA Controller [RAID mode] + 8d10 C610/X99 series chipset PCI Express Root Port #1 + 8d11 C610/X99 series chipset PCI Express Root Port #1 + 8d12 C610/X99 series chipset PCI Express Root Port #2 + 8d13 C610/X99 series chipset PCI Express Root Port #2 + 8d14 C610/X99 series chipset PCI Express Root Port #3 + 8d15 C610/X99 series chipset PCI Express Root Port #3 + 8d16 C610/X99 series chipset PCI Express Root Port #4 + 8d17 C610/X99 series chipset PCI Express Root Port #4 + 8d18 C610/X99 series chipset PCI Express Root Port #5 + 8d19 C610/X99 series chipset PCI Express Root Port #5 + 8d1a C610/X99 series chipset PCI Express Root Port #6 + 8d1b C610/X99 series chipset PCI Express Root Port #6 + 8d1c C610/X99 series chipset PCI Express Root Port #7 + 8d1d C610/X99 series chipset PCI Express Root Port #7 + 8d1e C610/X99 series chipset PCI Express Root Port #8 + 8d1f C610/X99 series chipset PCI Express Root Port #8 + 8d20 C610/X99 series chipset HD Audio Controller + 8d21 C610/X99 series chipset HD Audio Controller + 8d22 C610/X99 series chipset SMBus Controller + 15d9 0832 X10SRL-F + 8d24 C610/X99 series chipset Thermal Subsystem + 8d26 C610/X99 series chipset USB Enhanced Host Controller #1 + 15d9 0832 X10SRL-F + 8d2d C610/X99 series chipset USB Enhanced Host Controller #2 + 15d9 0832 X10SRL-F + 8d31 C610/X99 series chipset USB xHCI Host Controller + 15d9 0832 X10SRL-F + 8d33 C610/X99 series chipset LAN Controller + 8d34 C610/X99 series chipset NAND Controller + 8d3a C610/X99 series chipset MEI Controller #1 + 15d9 0832 X10SRL-F + 8d3b C610/X99 series chipset MEI Controller #2 + 15d9 0832 X10SRL-F + 8d3c C610/X99 series chipset IDE-r Controller + 8d3d C610/X99 series chipset KT Controller + 8d40 C610/X99 series chipset LPC Controller + 8d41 C610/X99 series chipset LPC Controller + 8d42 C610/X99 series chipset LPC Controller + 8d43 C610/X99 series chipset LPC Controller + 8d44 C610/X99 series chipset LPC Controller + 15d9 0832 X10SRL-F + 8d45 C610/X99 series chipset LPC Controller + 8d46 C610/X99 series chipset LPC Controller + 8d47 C610/X99 series chipset LPC Controller + 8d48 C610/X99 series chipset LPC Controller + 8d49 C610/X99 series chipset LPC Controller + 8d4a C610/X99 series chipset LPC Controller + 8d4b C610/X99 series chipset LPC Controller + 8d4c C610/X99 series chipset LPC Controller + 8d4d C610/X99 series chipset LPC Controller + 8d4e C610/X99 series chipset LPC Controller + 8d4f C610/X99 series chipset LPC Controller + 8d60 C610/X99 series chipset sSATA Controller [IDE mode] + 8d62 C610/X99 series chipset sSATA Controller [AHCI mode] + 8d64 C610/X99 series chipset sSATA Controller [RAID mode] + 8d66 C610/X99 series chipset sSATA Controller [RAID mode] + 8d68 C610/X99 series chipset sSATA Controller [IDE mode] + 8d6e C610/X99 series chipset sSATA Controller [RAID mode] + 8d7c C610/X99 series chipset SPSR + 15d9 0832 X10SRL-F + 8d7d C610/X99 series chipset MS SMBus 0 + 8d7e C610/X99 series chipset MS SMBus 1 + 8d7f C610/X99 series chipset MS SMBus 2 + 9000 IXP2000 Family Network Processor + 9001 IXP2400 Network Processor + 9002 IXP2300 Network Processor + 9004 IXP2800 Network Processor + 9621 Integrated RAID + 9622 Integrated RAID + 9641 Integrated RAID + 96a1 Integrated RAID + 9a0b Volume Management Device NVMe RAID Controller + 9b41 UHD Graphics + 9c00 8 Series SATA Controller 1 [IDE mode] + 9c01 8 Series SATA Controller 1 [IDE mode] + 9c02 8 Series SATA Controller 1 [AHCI mode] + 9c03 8 Series SATA Controller 1 [AHCI mode] + 17aa 2214 ThinkPad X240 + 9c04 8 Series SATA Controller 1 [RAID mode] + 9c05 8 Series SATA Controller 1 [RAID mode] + 9c06 8 Series SATA Controller 1 [RAID mode] + 9c07 8 Series SATA Controller 1 [RAID mode] + 9c08 8 Series SATA Controller 2 [IDE mode] + 9c09 8 Series SATA Controller 2 [IDE mode] + 9c0a 8 Series SATA Controller [Reserved] + 9c0b 8 Series SATA Controller [Reserved] + 9c0c 8 Series SATA Controller [Reserved] + 9c0d 8 Series SATA Controller [Reserved] + 9c0e 8 Series SATA Controller 1 [RAID mode] + 9c0f 8 Series SATA Controller 1 [RAID mode] + 9c10 8 Series PCI Express Root Port 1 + 9c11 8 Series PCI Express Root Port 1 + 9c12 8 Series PCI Express Root Port 2 + 9c13 8 Series PCI Express Root Port 2 + 9c14 8 Series PCI Express Root Port 3 + 9c15 8 Series PCI Express Root Port 3 + 9c16 8 Series PCI Express Root Port 4 + 9c17 8 Series PCI Express Root Port 4 + 9c18 8 Series PCI Express Root Port 5 + 9c19 8 Series PCI Express Root Port 5 + 9c1a 8 Series PCI Express Root Port 6 + 9c1b 8 Series PCI Express Root Port 6 + 9c1c 8 Series PCI Express Root Port 7 + 9c1d 8 Series PCI Express Root Port 7 + 9c1e 8 Series PCI Express Root Port 8 + 9c1f 8 Series PCI Express Root Port 8 + 9c20 8 Series HD Audio Controller + 17aa 2214 ThinkPad X240 + 9c21 8 Series HD Audio Controller + 9c22 8 Series SMBus Controller + 17aa 2214 ThinkPad X240 + 9c23 8 Series CHAP Counters + 9c24 8 Series Thermal + 9c26 8 Series USB EHCI #1 + 17aa 220c T440s + 17aa 2214 ThinkPad X240 + 9c2d 8 Series USB EHCI #2 + 9c31 8 Series USB xHCI HC + 17aa 2214 ThinkPad X240 + 8086 7270 Apple MacBookAir6,2 / MacBookPro11,1 + 9c35 8 Series SDIO Controller + 9c36 8 Series Audio DSP Controller + 9c3a 8 Series HECI #0 + 17aa 2214 ThinkPad X240 + 9c3b 8 Series HECI #1 + 9c3c 8 Series HECI IDER + 9c3d 8 Series HECI KT + 9c40 8 Series LPC Controller + 9c41 8 Series LPC Controller + 9c42 8 Series LPC Controller + 9c43 8 Series LPC Controller + 17aa 2214 ThinkPad X240 + 9c44 8 Series LPC Controller + 9c45 8 Series LPC Controller + 9c46 8 Series LPC Controller + 9c47 8 Series LPC Controller + 9c60 8 Series Low Power Sub-System DMA + 9c61 8 Series I2C Controller #0 + 9c62 8 Series I2C Controller #1 + 9c63 8 Series UART Controller #0 + 9c64 8 Series UART Controller #1 + 9c65 8 Series SPI Controller #0 + 9c66 8 Series SPI Controller #1 + 9c83 Wildcat Point-LP SATA Controller [AHCI Mode] + 9c85 Wildcat Point-LP SATA Controller [RAID Mode] + 9c87 Wildcat Point-LP SATA Controller [RAID Mode] + 9c8f Wildcat Point-LP SATA Controller [RAID Mode] + 9c90 Wildcat Point-LP PCI Express Root Port #1 + 9c92 Wildcat Point-LP PCI Express Root Port #2 + 9c94 Wildcat Point-LP PCI Express Root Port #3 + 9c96 Wildcat Point-LP PCI Express Root Port #4 + 9c98 Wildcat Point-LP PCI Express Root Port #5 + 9c9a Wildcat Point-LP PCI Express Root Port #6 + 9ca0 Wildcat Point-LP High Definition Audio Controller + 9ca2 Wildcat Point-LP SMBus Controller + 9ca4 Wildcat Point-LP Thermal Management Controller + 9ca6 Wildcat Point-LP USB EHCI Controller + 9cb1 Wildcat Point-LP USB xHCI Controller + 9cb5 Wildcat Point-LP Secure Digital IO Controller + 9cb6 Wildcat Point-LP Smart Sound Technology Controller + 9cba Wildcat Point-LP MEI Controller #1 + 9cbb Wildcat Point-LP MEI Controller #2 + 9cbc Wildcat Point-LP IDE-r Controller + 9cbd Wildcat Point-LP KT Controller + 9cc1 Wildcat Point-LP LPC Controller + 9cc2 Wildcat Point-LP LPC Controller + 9cc3 Wildcat Point-LP LPC Controller + 9cc5 Wildcat Point-LP LPC Controller + 9cc6 Wildcat Point-LP LPC Controller + 9cc7 Wildcat Point-LP LPC Controller + 9cc9 Wildcat Point-LP LPC Controller + 9ce0 Wildcat Point-LP Serial IO DMA Controller + 9ce1 Wildcat Point-LP Serial IO I2C Controller #0 + 9ce2 Wildcat Point-LP Serial IO I2C Controller #1 + 9ce3 Wildcat Point-LP Serial IO UART Controller #0 + 9ce4 Wildcat Point-LP Serial IO UART Controller #1 + 9ce5 Wildcat Point-LP Serial IO GSPI Controller #0 + 9ce6 Wildcat Point-LP Serial IO GSPI Controller #1 + 9d03 Sunrise Point-LP SATA Controller [AHCI mode] + 1028 06dc Latitude E7470 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 17aa 225d ThinkPad T480 + 17aa 382a B51-80 Laptop + 9d10 Sunrise Point-LP PCI Express Root Port #1 + 9d11 Sunrise Point-LP PCI Express Root Port #2 + 9d12 Sunrise Point-LP PCI Express Root Port #3 + 9d13 Sunrise Point-LP PCI Express Root Port #4 + 9d14 Sunrise Point-LP PCI Express Root Port #5 + 17aa 382a B51-80 Laptop + 9d15 Sunrise Point-LP PCI Express Root Port #6 + 17aa 382a B51-80 Laptop + 9d16 Sunrise Point-LP PCI Express Root Port #7 + 9d17 Sunrise Point-LP PCI Express Root Port #8 + 9d18 Sunrise Point-LP PCI Express Root Port #9 + 17aa 382a B51-80 Laptop + 9d19 Sunrise Point-LP PCI Express Root Port #10 + 9d1a Sunrise Point-LP PCI Express Root Port #11 + 9d21 Sunrise Point-LP PMC + 1028 06dc Latitude E7470 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 17aa 224f ThinkPad X1 Carbon 5th Gen + 17aa 225d ThinkPad T480 + 17aa 382a B51-80 Laptop + 9d23 Sunrise Point-LP SMBus + 1028 06dc Latitude E7470 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 17aa 2247 ThinkPad T570 + 17aa 224f ThinkPad X1 Carbon 5th Gen + 17aa 225d ThinkPad T480 + 17aa 382a B51-80 Laptop + 9d27 Sunrise Point-LP Serial IO UART Controller #0 + 9d28 Sunrise Point-LP Serial IO UART Controller #1 + 9d29 Sunrise Point-LP Serial IO SPI Controller #0 + 9d2a Sunrise Point-LP Serial IO SPI Controller #1 + 9d2d Sunrise Point-LP Secure Digital IO Controller + 9d2f Sunrise Point-LP USB 3.0 xHCI Controller + 1028 06dc Latitude E7470 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 17aa 2247 ThinkPad T570 + 17aa 225d ThinkPad T480 + 17aa 382a B51-80 Laptop + 9d31 Sunrise Point-LP Thermal subsystem + 1028 06dc Latitude E7470 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 17aa 2247 ThinkPad T570 + 17aa 224f ThinkPad X1 Carbon 5th Gen + 17aa 225d ThinkPad T480 + 17aa 382a B51-80 Laptop + 9d35 Sunrise Point-LP Integrated Sensor Hub + 9d3a Sunrise Point-LP CSME HECI #1 + 1028 06dc Latitude E7470 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 17aa 2247 ThinkPad T570 + 17aa 224f ThinkPad X1 Carbon 5th Gen + 17aa 225d ThinkPad T480 + 17aa 382a B51-80 Laptop + 9d3d Sunrise Point-LP Active Management Technology - SOL + 103c 8079 EliteBook 840 G3 + 9d43 Sunrise Point-LP LPC Controller + 17aa 382a B51-80 Laptop + 9d48 Sunrise Point-LP LPC Controller + 1028 06dc Latitude E7470 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 9d4e Sunrise Point LPC Controller/eSPI Controller + 17aa 225d ThinkPad T480 + 9d50 Sunrise Point LPC Controller + 9d56 Sunrise Point-LP LPC Controller + 9d58 Sunrise Point-LP LPC Controller + 17aa 2247 ThinkPad T570 + 17aa 224f ThinkPad X1 Carbon 5th Gen + 9d60 Sunrise Point-LP Serial IO I2C Controller #0 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 17aa 225d ThinkPad T480 + 8086 9d60 100 Series PCH/Sunrise Point PCH I2C0 [Skylake/Kaby Lake LPSS I2C] + 9d61 Sunrise Point-LP Serial IO I2C Controller #1 + 9d62 Sunrise Point-LP Serial IO I2C Controller #2 + 9d63 Sunrise Point-LP Serial IO I2C Controller #3 + 9d64 Sunrise Point-LP Serial IO I2C Controller #4 + 9d65 Sunrise Point-LP Serial IO I2C Controller #5 + 9d66 Sunrise Point-LP Serial IO UART Controller #2 + 9d70 Sunrise Point-LP HD Audio + 1028 06dc Latitude E7470 + 1028 06f3 Latitude 3570 + 103c 8079 EliteBook 840 G3 + 17aa 382a B51-80 Laptop + 9d71 Sunrise Point-LP HD Audio + 17aa 224f ThinkPad X1 Carbon 5th Gen + 17aa 225d ThinkPad T480 + 9d84 Cannon Point-LP LPC Controller + 1028 089e Inspiron 5482 + 9da3 Cannon Point-LP SMBus Controller + 9da4 Cannon Point-LP SPI Controller + 9db0 Cannon Point-LP PCI Express Root Port #9 + 9db1 Cannon Point-LP PCI Express Root Port #10 + 9db2 Cannon Point-LP PCI Express Root Port #1 + 9db4 Cannon Point-LP PCI Express Root Port #13 + 1028 089e Inspiron 5482 + 9db6 Cannon Point-LP PCI Express Root Port #15 + 9db8 Cannon Point-LP PCI Express Root Port #1 + 9dbc Cannon Point-LP PCI Express Root Port #5 + 9dbe Cannon Point-LP PCI Express Root Port #7 + 9dbf Cannon Point PCI Express Root Port #8 + 9dc5 Cannon Point-LP Serial IO I2C Host Controller + 9dc8 Cannon Point-LP High Definition Audio Controller + 1028 089e Inspiron 5482 + 9dd3 Cannon Point-LP SATA Controller [AHCI Mode] + 9de0 Cannon Point-LP MEI Controller #1 + 9de3 Cannon Point-LP Keyboard and Text (KT) Redirection + 9de8 Cannon Point-LP Serial IO I2C Controller #0 + 1028 089e Inspiron 5482 + 9de9 Cannon Point-LP Serial IO I2C Controller #1 + 1028 089e Inspiron 5482 + 9ded Cannon Point-LP USB 3.1 xHCI Controller + 9def Cannon Point-LP Shared SRAM + 9df0 Cannon Point-LP CNVi [Wireless-AC] + 9df5 BayHubTech Integrated SD controller + 9df9 Cannon Point-LP Thermal Controller + 9dfc Cannon Point-LP Integrated Sensor Hub + a000 Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge + 1458 5000 GA-D525TUD + 8086 4f4d DeskTop Board D510MO + 8086 544b Desktop Board D425KT + a001 Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller + 1458 d000 GA-D525TUD + 8086 4f4d DeskTop Board D510MO + 8086 544b Desktop Board D425KT + a002 Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller + a003 Atom Processor D4xx/D5xx/N4xx/N5xx CHAPS counter + a010 Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge + 1043 83ac Eee PC 1015PX + 144d c072 Notebook N150P + a011 Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller + 1043 83ac Eee PC 1015PX + 144d c072 Notebook N150P + a012 Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller + 1043 83ac Eee PC 1015PX + 144d c072 Notebook N150P + a013 Atom Processor D4xx/D5xx/N4xx/N5xx CHAPS counter + a102 Q170/Q150/B150/H170/H110/Z170/CM236 Chipset SATA Controller [AHCI Mode] + a103 HM170/QM170 Chipset SATA Controller [AHCI Mode] + 1028 06e4 XPS 15 9550 + a105 Sunrise Point-H SATA Controller [RAID mode] + a106 Q170/H170/Z170/CM236 Chipset SATA Controller [RAID Mode] + a107 HM170/QM170 Chipset SATA Controller [RAID Mode] + a10f Sunrise Point-H SATA Controller [RAID mode] + a110 100 Series/C230 Series Chipset Family PCI Express Root Port #1 + a111 100 Series/C230 Series Chipset Family PCI Express Root Port #2 + a112 100 Series/C230 Series Chipset Family PCI Express Root Port #3 + a113 100 Series/C230 Series Chipset Family PCI Express Root Port #4 + a114 100 Series/C230 Series Chipset Family PCI Express Root Port #5 + a115 100 Series/C230 Series Chipset Family PCI Express Root Port #6 + a116 100 Series/C230 Series Chipset Family PCI Express Root Port #7 + a117 100 Series/C230 Series Chipset Family PCI Express Root Port #8 + a118 100 Series/C230 Series Chipset Family PCI Express Root Port #9 + a119 100 Series/C230 Series Chipset Family PCI Express Root Port #10 + a11a 100 Series/C230 Series Chipset Family PCI Express Root Port #11 + a11b 100 Series/C230 Series Chipset Family PCI Express Root Port #12 + a11c 100 Series/C230 Series Chipset Family PCI Express Root Port #13 + a11d 100 Series/C230 Series Chipset Family PCI Express Root Port #14 + a11e 100 Series/C230 Series Chipset Family PCI Express Root Port #15 + a11f 100 Series/C230 Series Chipset Family PCI Express Root Port #16 + a120 100 Series/C230 Series Chipset Family P2SB + a121 100 Series/C230 Series Chipset Family Power Management Controller + 1028 06e4 XPS 15 9550 + a122 Sunrise Point-H cAVS + a123 100 Series/C230 Series Chipset Family SMBus + 1028 06e4 XPS 15 9550 + a124 100 Series/C230 Series Chipset Family SPI Controller + a125 100 Series/C230 Series Chipset Family Gigabit Ethernet Controller + a126 100 Series/C230 Series Chipset Family Trace Hub + a127 100 Series/C230 Series Chipset Family Serial IO UART #0 + a128 100 Series/C230 Series Chipset Family Serial IO UART #1 + a129 100 Series/C230 Series Chipset Family Serial IO GSPI #0 + a12a 100 Series/C230 Series Chipset Family Serial IO GSPI #1 + a12f 100 Series/C230 Series Chipset Family USB 3.0 xHCI Controller + 1028 06e4 XPS 15 9550 + a130 100 Series/C230 Series Chipset Family USB Device Controller (OTG) + a131 100 Series/C230 Series Chipset Family Thermal Subsystem + 1028 06e4 XPS 15 9550 + a133 Sunrise Point-H Northpeak ACPI Function + a135 100 Series/C230 Series Chipset Family Integrated Sensor Hub + a13a 100 Series/C230 Series Chipset Family MEI Controller #1 + 1028 06e4 XPS 15 9550 + a13b 100 Series/C230 Series Chipset Family MEI Controller #2 + a13c 100 Series/C230 Series Chipset Family IDE Redirection + a13d 100 Series/C230 Series Chipset Family KT Redirection + a13e 100 Series/C230 Series Chipset Family MEI Controller #3 + a140 Sunrise Point-H LPC Controller + a141 Sunrise Point-H LPC Controller + a142 Sunrise Point-H LPC Controller + a143 H110 Chipset LPC/eSPI Controller + a144 H170 Chipset LPC/eSPI Controller + a145 Z170 Chipset LPC/eSPI Controller + a146 Q170 Chipset LPC/eSPI Controller + a147 Q150 Chipset LPC/eSPI Controller + a148 B150 Chipset LPC/eSPI Controller + a149 C236 Chipset LPC/eSPI Controller + a14a C232 Chipset LPC/eSPI Controller + a14b Sunrise Point-H LPC Controller + a14c Sunrise Point-H LPC Controller + a14d QM170 Chipset LPC/eSPI Controller + a14e HM170 Chipset LPC/eSPI Controller + 1028 06e4 XPS 15 9550 + a14f Sunrise Point-H LPC Controller + a150 CM236 Chipset LPC/eSPI Controller + a151 Sunrise Point-H LPC Controller + a152 HM175 Chipset LPC/eSPI Controller + a153 QM175 Chipset LPC/eSPI Controller + a154 CM238 Chipset LPC/eSPI Controller + a155 Sunrise Point-H LPC Controller + a156 Sunrise Point-H LPC Controller + a157 Sunrise Point-H LPC Controller + a158 Sunrise Point-H LPC Controller + a159 Sunrise Point-H LPC Controller + a15a Sunrise Point-H LPC Controller + a15b Sunrise Point-H LPC Controller + a15c Sunrise Point-H LPC Controller + a15d Sunrise Point-H LPC Controller + a15e Sunrise Point-H LPC Controller + a15f Sunrise Point-H LPC Controller + a160 100 Series/C230 Series Chipset Family Serial IO I2C Controller #0 + 1028 06e4 XPS 15 9550 + a161 100 Series/C230 Series Chipset Family Serial IO I2C Controller #1 + 1028 06e4 XPS 15 9550 + a162 100 Series/C230 Series Chipset Family Serial IO I2C Controller #2 + a163 100 Series/C230 Series Chipset Family Serial IO I2C Controller #3 + a166 100 Series/C230 Series Chipset Family Serial IO UART Controller #2 + a167 100 Series/C230 Series Chipset Family PCI Express Root Port #17 + a168 100 Series/C230 Series Chipset Family PCI Express Root Port #18 + a169 100 Series/C230 Series Chipset Family PCI Express Root Port #19 + a16a 100 Series/C230 Series Chipset Family PCI Express Root Port #20 + a170 100 Series/C230 Series Chipset Family HD Audio Controller + 1028 06e4 XPS 15 9550 + a171 CM238 HD Audio Controller + a182 C620 Series Chipset Family SATA Controller [AHCI mode] + a186 C620 Series Chipset Family SATA Controller [RAID mode] + a190 C620 Series Chipset Family PCI Express Root Port #1 + a191 C620 Series Chipset Family PCI Express Root Port #2 + a192 C620 Series Chipset Family PCI Express Root Port #3 + a193 C620 Series Chipset Family PCI Express Root Port #4 + a194 C620 Series Chipset Family PCI Express Root Port #5 + a195 C620 Series Chipset Family PCI Express Root Port #6 + a196 C620 Series Chipset Family PCI Express Root Port #7 + a197 C620 Series Chipset Family PCI Express Root Port #8 + a198 C620 Series Chipset Family PCI Express Root Port #9 + a199 C620 Series Chipset Family PCI Express Root Port #10 + a19a C620 Series Chipset Family PCI Express Root Port #11 + a19b C620 Series Chipset Family PCI Express Root Port #12 + a19c C620 Series Chipset Family PCI Express Root Port #13 + a19d C620 Series Chipset Family PCI Express Root Port #14 + a19e C620 Series Chipset Family PCI Express Root Port #15 + a19f C620 Series Chipset Family PCI Express Root Port #16 + a1a0 C620 Series Chipset Family P2SB + a1a1 C620 Series Chipset Family Power Management Controller + 15d9 095d X11SPM-TF + a1a2 C620 Series Chipset Family cAVS + a1a3 C620 Series Chipset Family SMBus + 15d9 095d X11SPM-TF + a1a4 C620 Series Chipset Family SPI Controller + 15d9 095d X11SPM-TF + a1a6 C620 Series Chipset Family Trace Hub + a1af C620 Series Chipset Family USB 3.0 xHCI Controller + 15d9 095d X11SPM-TF + a1b1 C620 Series Chipset Family Thermal Subsystem + 15d9 095d X11SPM-TF + a1ba C620 Series Chipset Family MEI Controller #1 + 15d9 095d X11SPM-TF + a1bb C620 Series Chipset Family MEI Controller #2 + 15d9 095d X11SPM-TF + a1bc C620 Series Chipset Family IDE Redirection + a1bd C620 Series Chipset Family KT Redirection + a1be C620 Series Chipset Family MEI Controller #3 + 15d9 095d X11SPM-TF + a1c1 C621 Series Chipset LPC/eSPI Controller + a1c2 C622 Series Chipset LPC/eSPI Controller + 15d9 095d X11SPM-TF + a1c3 C624 Series Chipset LPC/eSPI Controller + a1c4 C625 Series Chipset LPC/eSPI Controller + a1c5 C626 Series Chipset LPC/eSPI Controller + a1c6 C627 Series Chipset LPC/eSPI Controller + a1c7 C628 Series Chipset LPC/eSPI Controller + a1d2 C620 Series Chipset Family SSATA Controller [AHCI mode] + a1d6 C620 Series Chipset Family SSATA Controller [RAID mode] + a1e7 C620 Series Chipset Family PCI Express Root Port #17 + a1e8 C620 Series Chipset Family PCI Express Root Port #18 + a1e9 C620 Series Chipset Family PCI Express Root Port #19 + a1ea C620 Series Chipset Family PCI Express Root Port #20 + a1ec C620 Series Chipset Family MROM 0 + a1ed C620 Series Chipset Family MROM 1 + a1f8 Lewisburg IE: HECI #1 + a1f9 Lewisburg IE: HECI #2 + a1fa Lewisburg IE: IDE-r + a1fb Lewisburg IE: KT Controller + a1fc Lewisburg IE: HECI #3 + a202 Lewisburg SATA Controller [AHCI mode] + a206 Lewisburg SATA Controller [RAID mode] + a223 Lewisburg SMBus + a224 Lewisburg SPI Controller + a242 Lewisburg LPC or eSPI Controller + a243 Lewisburg LPC or eSPI Controller + a252 Lewisburg SSATA Controller [AHCI mode] + a256 Lewisburg SSATA Controller [RAID mode] + a282 200 Series PCH SATA controller [AHCI mode] + a286 200 Series PCH SATA controller [RAID mode] + a290 200 Series PCH PCI Express Root Port #1 + a291 200 Series PCH PCI Express Root Port #2 + a292 200 Series PCH PCI Express Root Port #3 + a293 200 Series PCH PCI Express Root Port #4 + a294 200 Series PCH PCI Express Root Port #5 + a295 200 Series PCH PCI Express Root Port #6 + a296 200 Series PCH PCI Express Root Port #7 + a297 200 Series PCH PCI Express Root Port #8 + a298 200 Series PCH PCI Express Root Port #9 + a299 200 Series PCH PCI Express Root Port #10 + a29a 200 Series PCH PCI Express Root Port #11 + a29b 200 Series PCH PCI Express Root Port #12 + a29c 200 Series PCH PCI Express Root Port #13 + a29d 200 Series PCH PCI Express Root Port #14 + a29e 200 Series PCH PCI Express Root Port #15 + a29f 200 Series PCH PCI Express Root Port #16 + a2a0 200 Series/Z370 Chipset Family P2SB + a2a1 200 Series/Z370 Chipset Family Power Management Controller + a2a3 200 Series/Z370 Chipset Family SMBus Controller + a2a4 200 Series/Z370 Chipset Family SPI Controller + a2a5 200 Series/Z370 Chipset Family Gigabit Ethernet Controller + a2a6 200 Series/Z370 Chipset Family Trace Hub + a2a7 200 Series/Z370 Chipset Family Serial IO UART Controller #0 + a2a8 200 Series/Z370 Chipset Family Serial IO UART Controller #1 + a2a9 200 Series/Z370 Chipset Family Serial IO SPI Controller #0 + a2aa 200 Series/Z370 Chipset Family Serial IO SPI Controller #1 + a2af 200 Series/Z370 Chipset Family USB 3.0 xHCI Controller + a2b1 200 Series PCH Thermal Subsystem + a2ba 200 Series PCH CSME HECI #1 + a2bb 200 Series PCH CSME HECI #2 + a2c4 200 Series PCH LPC Controller (H270) + a2c5 200 Series PCH LPC Controller (Z270) + a2c6 200 Series PCH LPC Controller (Q270) + a2c7 200 Series PCH LPC Controller (Q250) + a2c8 200 Series PCH LPC Controller (B250) + a2c9 Z370 Chipset LPC/eSPI Controller + a2d2 X299 Chipset LPC/eSPI Controller + a2d3 C422 Chipset LPC/eSPI Controller + a2e0 200 Series PCH Serial IO I2C Controller #0 + a2e1 200 Series PCH Serial IO I2C Controller #1 + a2e2 200 Series PCH Serial IO I2C Controller #2 + a2e3 200 Series PCH Serial IO I2C Controller #3 + a2e6 200 Series PCH Serial IO UART Controller #2 + a2e7 200 Series PCH PCI Express Root Port #17 + a2e8 200 Series PCH PCI Express Root Port #18 + a2e9 200 Series PCH PCI Express Root Port #19 + a2ea 200 Series PCH PCI Express Root Port #20 + a2eb 200 Series PCH PCI Express Root Port #21 + a2ec 200 Series PCH PCI Express Root Port #22 + a2ed 200 Series PCH PCI Express Root Port #23 + a2ee 200 Series PCH PCI Express Root Port #24 + a2f0 200 Series PCH HD Audio + a304 H370 Chipset LPC/eSPI Controller + a305 Z390 Chipset LPC/eSPI Controller + a306 Q370 Chipset LPC/eSPI Controller + a309 Cannon Point-LP LPC Controller + a30c QM370 Chipset LPC/eSPI Controller + a323 Cannon Lake PCH SMBus Controller + a324 Cannon Lake PCH SPI Controller + a328 Cannon Lake PCH Serial IO UART Host Controller + a32c Cannon Lake PCH PCI Express Root Port #21 + a32d Cannon Lake PCH PCI Express Root Port #22 + a32e Cannon Lake PCH PCI Express Root Port #23 + a32f Cannon Lake PCH PCI Express Root Port #24 + a330 Cannon Lake PCH PCI Express Root Port #9 + a331 Cannon Lake PCH PCI Express Root Port #10 + a332 Cannon Lake PCH PCI Express Root Port #11 + a333 Cannon Lake PCH PCI Express Root Port #12 + a334 Cannon Lake PCH PCI Express Root Port #13 + a335 Cannon Lake PCH PCI Express Root Port #14 + a336 Cannon Lake PCH PCI Express Root Port #15 + a337 Cannon Lake PCH PCI Express Root Port #16 + a338 Cannon Lake PCH PCI Express Root Port #1 + a339 Cannon Lake PCH PCI Express Root Port #2 + a33a Cannon Lake PCH PCI Express Root Port #3 + a33b Cannon Lake PCH PCI Express Root Port #4 + a33c Cannon Lake PCH PCI Express Root Port #5 + a33d Cannon Lake PCH PCI Express Root Port #6 + a33e Cannon Lake PCH PCI Express Root Port #7 + a33f Cannon Lake PCH PCI Express Root Port #8 + a340 Cannon Lake PCH PCI Express Root Port #17 + a341 Cannon Lake PCH PCI Express Root Port #18 + a342 Cannon Lake PCH PCI Express Root Port #19 + a343 Cannon Lake PCH PCI Express Root Port #20 + a348 Cannon Lake PCH cAVS + a352 Cannon Lake PCH SATA AHCI Controller + a353 Cannon Lake Mobile PCH SATA AHCI Controller + a360 Cannon Lake PCH HECI Controller + a363 Cannon Lake PCH Active Management Technology - SOL + a364 Cannon Lake PCH HECI Controller #2 + a368 Cannon Lake PCH Serial IO I2C Controller #0 + a369 Cannon Lake PCH Serial IO I2C Controller #1 + a36a Cannon Lake PCH Serial IO I2C Controller #2 + a36b Cannon Lake PCH Serial IO I2C Controller #3 + a36d Cannon Lake PCH USB 3.1 xHCI Host Controller + a36f Cannon Lake PCH Shared SRAM + a370 Wireless-AC 9560 [Jefferson Peak] + a379 Cannon Lake PCH Thermal Controller + a620 6400/6402 Advanced Memory Buffer (AMB) + abc0 Omni-Path Fabric Switch Silicon 100 Series + b152 21152 PCI-to-PCI Bridge + 8086 b152 21152 PCI-to-PCI Bridge +# observed, and documented in Intel revision note; new mask of 1011:0026 + b154 21154 PCI-to-PCI Bridge + b555 21555 Non transparent PCI-to-PCI Bridge + 12c7 5005 SS7HD PCI Adaptor Card + 12c7 5006 SS7HDC cPCI Adaptor Card + 12d9 000a PCI VoIP Gateway + 4c53 1050 CT7 mainboard + 4c53 1051 CE7 mainboard + e4bf 1000 CC8-1-BLUES + d130 Core Processor DMI + 15d9 0605 X8SIL + d131 Core Processor DMI + 1028 02da OptiPlex 980 + 15d9 060d C7SIM-Q Motherboard + d132 Core Processor DMI + 1028 040b Latitude E6510 + d133 Core Processor DMI + d134 Core Processor DMI + d135 Core Processor DMI + d136 Core Processor DMI + d137 Core Processor DMI + d138 Core Processor PCI Express Root Port 1 + 1028 02da OptiPlex 980 + 1028 040b Latitude E6510 + 15d9 060d C7SIM-Q Motherboard + d139 Core Processor PCI Express Root Port 2 + d13a Core Processor PCI Express Root Port 3 + d13b Core Processor PCI Express Root Port 4 + d150 Core Processor QPI Link + d151 Core Processor QPI Routing and Protocol Registers + d155 Core Processor System Management Registers + d156 Core Processor Semaphore and Scratchpad Registers + d157 Core Processor System Control and Status Registers + d158 Core Processor Miscellaneous Registers + f1a5 SSD 600P Series + f1a6 SSD Pro 7600p/760p/E 6100p Series + f1a8 SSD 660P Series +8088 Beijing Wangxun Technology Co., Ltd. + 0101 WX1860A2 Gigabit Ethernet Controller + 8088 0201 Dual-Port Ethernet Network Adaptor SF200T + 0102 WX1860A2S Gigabit Ethernet Controller + 8088 0210 Dual-Port Ethernet Network Adaptor SF200T-S + 0103 WX1860A4 Gigabit Ethernet Controller + 8088 0401 Qual-Port Ethernet Network Adaptor SF400T + 8088 0440 Qual-Port Ethernet Network Adaptor SF400-OCP + 0104 WX1860A4S Gigabit Ethernet Controller + 8088 0410 Qual-Port Ethernet Network Adaptor SF400T-S + 0105 WX1860AL2 Gigabit Ethernet Controller + 8088 0202 Dual-Port Ethernet Network Adaptor SF200HT + 0106 WX1860AL2S Gigabit Ethernet Controller + 8088 0220 Dual-Port Ethernet Network Adaptor SF200HT-S + 0107 WX1860AL4 Gigabit Ethernet Controller + 8088 0402 Qual-Port Ethernet Network Adaptor SF400HT + 0108 WX1860AL4S Gigabit Ethernet Controller + 8088 0420 Qual-Port Ethernet Network Adaptor SF400HT-S + 1001 Ethernet Controller RP1000 for 10GbE SFP+ + 8088 0000 Ethernet Network Adaptor RP1000 for 10GbE SFP+ + 2001 Ethernet Controller RP2000 for 10GbE SFP+ + 8088 2000 Ethernet Network Adaptor RP2000 for 10GbE SFP+ +80ee InnoTek Systemberatung GmbH + beef VirtualBox Graphics Adapter + cafe VirtualBox Guest Service +8322 Sodick America Corp. +8384 SigmaTel +8401 TRENDware International Inc. +8686 ScaleMP + 1010 vSMP Foundation controller [vSMP CTL] + 1011 vSMP Foundation MEX/FLX controller [vSMP CTL] +8800 Trigem Computer Inc. + 2008 Video assistant component +8866 T-Square Design Inc. +8888 Silicon Magic +8912 TRX +# 8c4a is not Winbond but there is a board misprogrammed +8c4a Winbond + 1980 W89C940 misprogrammed [ne2k] +8e0e Computone Corporation +8e2e KTI + 3000 ET32P2 +9004 Adaptec + 0078 AHA-2940U_CN + 1078 AIC-7810 + 1160 AIC-1160 [Family Fibre Channel Adapter] + 2178 AIC-7821 + 3860 AHA-2930CU + 3b78 AHA-4844W/4844UW + 5075 AIC-755x + 5078 AIC-7850T/7856T [AVA-2902/4/6 / AHA-2910] + 9004 7850 AIC-7850T/7856T [AVA-290x / AHA-2910] + 5175 AIC-755x + 5178 AIC-7851 + 5275 AIC-755x + 5278 AIC-7852 + 5375 AIC-755x + 5378 AIC-7850 + 5475 AIC-755x + 5478 AIC-7850 + 5575 AVA-2930 + 5578 AIC-7855 + 5647 ANA-7711 TCP Offload Engine + 9004 7710 ANA-7711F TCP Offload Engine - Optical + 9004 7711 ANA-7711LP TCP Offload Engine - Copper + 5675 AIC-755x + 5678 AIC-7856 + 5775 AIC-755x + 5778 AIC-7850 + 5800 AIC-5800 + 5900 ANA-5910/5930/5940 ATM155 & 25 LAN Adapter + 5905 ANA-5910A/5930A/5940A ATM Adapter + 6038 AIC-3860 + 6075 AIC-1480 / APA-1480 + 9004 7560 AIC-1480 / APA-1480 Cardbus + 6078 AIC-7860 + 6178 AIC-7861 + 9004 7861 AHA-2940AU Single + 6278 AIC-7860 + 6378 AIC-7860 + 6478 AIC-786x + 6578 AIC-786x + 6678 AIC-786x + 6778 AIC-786x + 6915 ANA620xx/ANA69011A + 9004 0008 ANA69011A/TX 10/100 + 9004 0009 ANA69011A/TX 10/100 + 9004 0010 ANA62022 2-port 10/100 + 9004 0018 ANA62044 4-port 10/100 + 9004 0019 ANA62044 4-port 10/100 + 9004 0020 ANA62022 2-port 10/100 + 9004 0028 ANA69011A/TX 10/100 + 9004 8008 ANA69011A/TX 64 bit 10/100 + 9004 8009 ANA69011A/TX 64 bit 10/100 + 9004 8010 ANA62022 2-port 64 bit 10/100 + 9004 8018 ANA62044 4-port 64 bit 10/100 + 9004 8019 ANA62044 4-port 64 bit 10/100 + 9004 8020 ANA62022 2-port 64 bit 10/100 + 9004 8028 ANA69011A/TX 64 bit 10/100 + 7078 AHA-294x / AIC-7870 + 7178 AIC-7870P/7871 [AHA-2940/W/S76] + 7278 AHA-3940/3940W / AIC-7872 + 7378 AHA-3985 / AIC-7873 + 7478 AHA-2944/2944W / AIC-7874 + 7578 AHA-3944/3944W / AIC-7875 + 7678 AHA-4944W/UW / AIC-7876 + 7710 ANA-7711F Network Accelerator Card (NAC) - Optical + 7711 ANA-7711C Network Accelerator Card (NAC) - Copper + 7778 AIC-787x + 7810 AIC-7810 + 7815 AIC-7815 RAID+Memory Controller IC + 9004 7815 ARO-1130U2 RAID Controller + 9004 7840 AIC-7815 RAID+Memory Controller IC + 7850 AIC-7850 + 7855 AHA-2930 + 7860 AIC-7860 + 7870 AIC-7870 + 7871 AHA-2940 + 7872 AHA-3940 + 7873 AHA-3980 + 7874 AHA-2944 + 7880 AIC-7880P + 7890 AIC-7890 + 7891 AIC-789x + 7892 AIC-789x + 7893 AIC-789x + 7894 AIC-789x + 7895 AHA-2940U/UW / AHA-39xx / AIC-7895 + 9004 7890 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B + 9004 7891 AHA-2940U/2940UW Dual + 9004 7892 AHA-3940AU/AUW/AUWD/UWD + 9004 7894 AHA-3944AUWD + 9004 7895 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B + 9004 7896 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B + 9004 7897 AHA-2940U/2940UW Dual AHA-394xAU/AUW/AUWD AIC-7895B + 7896 AIC-789x + 7897 AIC-789x + 8078 AIC-7880U + 9004 7880 AIC-7880P Ultra/Ultra Wide SCSI Chipset + 8178 AIC-7870P/7881U [AHA-2940U/UW/D/S76] + 9004 7881 AHA-2940UW SCSI Host Adapter + 8278 AHA-3940U/UW/UWD / AIC-7882U + 8378 AHA-3940U/UW / AIC-7883U + 8478 AHA-2944UW / AIC-7884U + 8578 AHA-3944U/UWD / AIC-7885 + 8678 AHA-4944UW / AIC-7886 + 8778 AHA-2940UW Pro / AIC-788x + 9004 7887 2940UW Pro Ultra-Wide SCSI Controller + 8878 AHA-2930UW / AIC-7888 + 9004 7888 AHA-2930UW SCSI Controller + 8b78 ABA-1030 + ec78 AHA-4944W/UW +# Acquired by Microchip Technology +9005 Adaptec + 0010 AHA-2940U2/U2W + 9005 2180 AHA-2940U2 SCSI Controller + 9005 8100 AHA-2940U2B SCSI Controller + 9005 a100 AHA-2940U2B SCSI Controller + 9005 a180 AIC-3860Q [AHA-2940U2W/GE] SCSI Controller + 9005 e100 AHA-2950U2B SCSI Controller + 0011 AHA-2930U2 + 0013 78902 + 9005 0003 AAA-131U2 Array1000 1 Channel RAID Controller + 9005 000f AIC7890_ARO + 001f AHA-2940U2/U2W / 7890/7891 + 9005 000f 2940U2W SCSI Controller + 9005 a180 2940U2W SCSI Controller + 0020 AIC-7890 + 002f AIC-7890 + 0030 AIC-7890 + 003f AIC-7890 + 0050 AHA-3940U2x/395U2x + 9005 f500 AHA-3950U2B + 9005 ffff AHA-3950U2B + 0051 AHA-3950U2D + 9005 b500 AHA-3950U2D + 0053 AIC-7896 SCSI Controller + 9005 ffff AIC-7896 SCSI Controller mainboard implementation + 005f AIC-7896U2/7897U2 + 0080 AIC-7892A U160/m + 0e11 e2a0 Compaq 64-Bit/66MHz Wide Ultra3 SCSI Adapter + 9005 6220 AHA-29160C + 9005 62a0 29160N Ultra160 SCSI Controller + 9005 e220 29160LP Low Profile Ultra160 SCSI Controller + 9005 e2a0 29160 Ultra160 SCSI Controller + 0081 AIC-7892B U160/m + 9005 62a1 19160 Ultra160 SCSI Controller + 0083 AIC-7892D U160/m + 008f AIC-7892P U160/m + 1179 0001 Magnia Z310 + 15d9 9005 Onboard SCSI Host Adapter + 0092 AVC-2010 [VideoH!] + 0093 AVC-2410 [VideoH!] + 00c0 AHA-3960D / AIC-7899A U160/m + 0e11 f620 Compaq 64-Bit/66MHz Dual Channel Wide Ultra3 SCSI Adapter + 9005 f620 AHA-3960D U160/m + 00c1 AIC-7899B U160/m + 00c3 AIC-7899D U160/m + 00c5 RAID subsystem HBA + 1028 00c5 PowerEdge 2400,2500,2550,4400 + 00cf AIC-7899P U160/m + 1028 00ce PowerEdge 1400 + 1028 00d1 PowerEdge 2550 + 1028 00d9 PowerEdge 2500 + 10f1 2462 Thunder K7 S2462 + 15d9 9005 Onboard SCSI Host Adapter + 8086 3411 SDS2 Mainboard + 0241 Serial ATA II RAID 1420SA + 0242 Serial ATA II RAID 1220SA + 0243 Serial ATA II RAID 1430SA + 0244 eSATA II RAID 1225SA + 0250 ServeRAID Controller + 1014 0279 ServeRAID 6M + 1014 028c ServeRAID 6i/6i+ + 1014 028e ServeRAID 7k + 0279 ServeRAID 6M + 0283 AAC-RAID + 9005 0283 Catapult + 0284 AAC-RAID + 9005 0284 Tomcat + 0285 AAC-RAID + 0e11 0295 SATA 6Ch (Bearcat) + 1014 02f2 ServeRAID 8i + 1028 0287 PowerEdge Expandable RAID Controller 320/DC + 1028 0291 CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) + 103c 3227 AAR-2610SA + 108e 0286 Sun StorageTek SAS RAID HBA, Internal + 108e 0287 STK RAID EXT + 108e 7aac STK RAID REM + 108e 7aae STK RAID EX + 15d9 02b5 SMC AOC-USAS-S4i + 15d9 02b6 SMC AOC-USAS-S8i + 15d9 02c9 SMC AOC-USAS-S4iR + 15d9 02ca SMC AOC-USAS-S8iR + 15d9 02d2 SMC AOC-USAS-S8i-LP + 15d9 02d3 SMC AOC-USAS-S8iR-LP + 17aa 0286 Legend S220 (Legend Crusader) + 17aa 0287 Legend S230 (Legend Vulcan) + 9005 0285 2200S (Vulcan) + 9005 0286 2120S (Crusader) + 9005 0287 2200S (Vulcan-2m) + 9005 0288 3230S (Harrier) + 9005 0289 3240S (Tornado) +# Some early versions reported 2020S + 9005 028a ASR-2020ZCR +# Some early versions reported 2025S + 9005 028b ASR-2025ZCR (Terminator) + 9005 028e ASR-2020SA (Skyhawk) + 9005 028f ASR-2025SA + 9005 0290 AAR-2410SA PCI SATA 4ch (Jaguar II) + 9005 0292 AAR-2810SA PCI SATA 8ch (Corsair-8) + 9005 0293 AAR-21610SA PCI SATA 16ch (Corsair-16) + 9005 0294 ESD SO-DIMM PCI-X SATA ZCR (Prowler) + 9005 0296 ASR-2240S + 9005 0297 ASR-4005SAS + 9005 0298 ASR-4000 + 9005 0299 ASR-4800SAS + 9005 029a 4805SAS + 9005 02a4 ICP ICP9085LI + 9005 02a5 ICP ICP5085BR + 9005 02b5 ASR5800 + 9005 02b6 ASR5805 + 9005 02b7 ASR5808 + 9005 02b8 ICP5445SL + 9005 02b9 ICP5085SL + 9005 02ba ICP5805SL + 9005 02bb 3405 + 9005 02bc 3805 + 9005 02bd 31205 + 9005 02be 31605 + 9005 02bf ICP ICP5045BL + 9005 02c0 ICP ICP5085BL + 9005 02c1 ICP ICP5125BR + 9005 02c2 ICP ICP5165BR + 9005 02c3 51205 + 9005 02c4 51605 + 9005 02c5 ICP ICP5125SL + 9005 02c6 ICP ICP5165SL + 9005 02c7 3085 + 9005 02c8 ICP5805BL + 9005 02ce 51245 + 9005 02cf 51645 + 9005 02d0 52445 + 9005 02d1 5405 + 9005 02d4 ASR-2045 + 9005 02d5 ASR-2405 + 9005 02d6 ASR-2445 + 9005 02d7 ASR-2805 + 9005 02d8 5405G + 9005 02d9 5445G + 9005 02da 5805G + 9005 02db 5085G + 9005 02dc 51245G + 9005 02dd 51645G + 9005 02de 52445G + 9005 02df ASR-2045G + 9005 02e0 ASR-2405G + 9005 02e1 ASR-2445G + 9005 02e2 ASR-2805G + 0286 AAC-RAID (Rocket) + 1014 034d 8s + 1014 9540 ServeRAID 8k/8k-l4 + 1014 9580 ServeRAID 8k/8k-l8 + 9005 028c ASR-2230S + ASR-2230SLP PCI-X (Lancer) + 9005 028d ASR-2130S + 9005 029b ASR-2820SA + 9005 029c ASR-2620SA + 9005 029d ASR-2420SA + 9005 029e ICP ICP9024R0 + 9005 029f ICP ICP9014R0 + 9005 02a0 ICP ICP9047MA + 9005 02a1 ICP ICP9087MA + 9005 02a2 3800 + 9005 02a3 ICP ICP5445AU + 9005 02a4 ICP ICP9085LI + 9005 02a5 ICP ICP5085BR + 9005 02a6 ICP9067MA + 9005 02a7 3805 + 9005 02a8 3400 + 9005 02a9 ICP ICP5085AU + 9005 02aa ICP ICP5045AU + 9005 02ac 1800 + 9005 02b3 2400 + 9005 02b4 ICP ICP5045AL + 9005 0800 Callisto + 028b Series 6 - 6G SAS/PCIe 2 + 9005 0200 Series 6 Entry Level - ASR-6405E - 4 internal 6G SAS ports + 9005 0201 Series 6 Entry Level - ASR-6805E - 8 internal 6G SAS ports + 9005 0300 Series 6 - ASR-6405 - 4 internal 6G SAS ports + 9005 0301 Series 6 - ASR-6805 - 8 internal 6G SAS ports + 9005 0302 Series 6 - ASR-6445 - 4 internal and 4 external 6G SAS ports + 9005 0310 Series 6 Connectors on Top - ASR-6405T - 4 internal 6G SAS ports + 9005 0311 Series 6 Connectors on Top - ASR-6805T - 8 internal 6G SAS + 9005 0400 Series 6 - ASR-61205 - 12 internal 6G SAS ports + 9005 0401 Series 6 - ASR-61605 - 16 internal 6G SAS ports + 9005 0403 Series 6 - ASR-62405 - 24 internal 6G SAS ports + 028c Series 7 6G SAS/PCIe 3 + 9005 0500 Series 7 - ASR-7805 - 8 internal 6G SAS Port/PCIe 3.0 + 9005 0501 Series 7 - ASR-71605 - 16 internal 6G SAS Port/PCIe 3.0 + 9005 0502 Series 7 - ASR-71685 - 16 internal 8 external 6G SAS Port/PCIe 3.0 + 9005 0503 Series 7 - ASR-72405 - 24 internal 0 external 6G SAS Port/PCIe 3.0 + 9005 0504 Series 7 - ASR-7885 - 8 internal 8 external 6G SAS Port/PCIe 3.0 + 9005 0505 Series 7 Entry Level - ASR-71685E - 16 internal 8 external 6G SAS Port/PCIe 3.0 + 9005 0506 Series 7 Entry Level - ASR-72405E - 24 internal 0 external 6G SAS Port/PCIe 3.0 + 028d Series 8 12G SAS/PCIe 3 + 9005 0550 Series 8 - ASR-82405 - 24 internal 0 external 12G SAS Port/PCIe 3.0 + 9005 0551 Series 8 - ASR-81605 - 16 internal 0 external 12G SAS Port/PCIe 3.0 + 9005 0552 Series 8 - ASR-8805 - 8 internal 0 external 12G SAS Port/PCIe 3.0 + 9005 0553 Series 8 - ASR-8085 - 0 internal 8 external 12G SAS Port/PCIe 3.0 + 9005 0554 Series 8 - ASR-8885 - 8 internal 8 external 12G SAS Port/PCIe 3.0 + 028f Smart Storage PQI 12G SAS/PCIe 3 + 103c 0600 Smart Array P408i-p SR Gen10 + 103c 0601 Smart Array P408e-p SR Gen10 + 103c 0602 Smart Array P408i-a SR Gen10 + 103c 0603 Smart Array P408i-c SR Gen10 + 103c 0650 Smart Array E208i-p SR Gen10 + 103c 0651 Smart Array E208e-p SR Gen10 + 103c 0652 Smart Array E208i-c SR Gen10 + 103c 0654 Smart Array E208i-a SR Gen10 + 103c 0655 Smart Array P408e-m SR Gen10 + 103c 0700 Smart Array P204i-c SR Gen10 + 103c 0701 Smart Array P204i-b SR Gen10 + 103c 1100 Smart Array P816i-a SR Gen10 + 103c 1101 Smart Array P416ie-m SR G10 + 105b 1211 HBA 8238-16i + 105b 1321 HBA 8242-24i + 13fe 8312 SKY-9200 MIC-8312BridgeB + 152d 8a22 QS-8204-8i + 152d 8a23 QS-8238-16i + 152d 8a24 QS-8236-16i + 152d 8a36 QS-8240-24i + 152d 8a37 QS-8242-24i + 193d 8460 HBA H460-M1 + 193d 8461 HBA H460-B1 + 193d c460 RAID P460-M2 + 193d c461 RAID P460-B2 + 193d f460 RAID P460-M4 + 193d f461 RAID P460-B4 + 19e5 d227 SmartROC-HD SR465C-M 4G + 19e5 d228 SmartROC SR455C-M 2G + 19e5 d229 SmartIOC SR155-M + 19e5 d22a SmartIOC-HD SR765-M + 19e5 d22b SmartROC-e SR455C-ME 4G + 19e5 d22c SmartROC SR455C-M 4G + 1bd4 0045 SMART-HBA 8242-24i + 1bd4 0046 RAID 8236-16i + 1bd4 0047 RAID 8240-24i + 1bd4 0048 SMART-HBA 8238-16i + 1bd4 004a PM8222-SHBA + 1bd4 004b RAID PM8204-2GB + 1bd4 004c RAID PM8204-4GB + 1bd4 004f PM8222-HBA + 9005 0608 SmartRAID 3162-8i /e + 9005 0800 SmartRAID 3154-8i + 9005 0801 SmartRAID 3152-8i + 9005 0802 SmartRAID 3151-4i + 9005 0803 SmartRAID 3101-4i + 9005 0804 SmartRAID 3154-8e + 9005 0805 SmartRAID 3102-8i + 9005 0806 SmartRAID 3100 + 9005 0807 SmartRAID 3162-8i + 9005 0900 SmartHBA 2100-8i + 9005 0901 SmartHBA 2100-4i + 9005 0902 HBA 1100-8i + 9005 0903 HBA 1100-4i + 9005 0904 SmartHBA 2100-8e + 9005 0905 HBA 1100-8e + 9005 0906 SmartHBA 2100-4i4e + 9005 0907 HBA 1100 + 9005 0908 SmartHBA 2100 + 9005 090a SmartHBA 2100A-8i + 9005 1200 SmartRAID 3154-24i + 9005 1201 SmartRAID 3154-8i16e + 9005 1202 SmartRAID 3154-8i8e + 9005 1280 HBA 1100-16i + 9005 1281 HBA 1100-16e + 9005 1300 HBA 1100-8i8e + 9005 1301 HBA 1100-24i + 9005 1302 SmartHBA 2100-8i8e + 9005 1303 SmartHBA 2100-24i + 9005 1380 SmartRAID 3154-16i + 0410 AIC-9410W SAS (Razor HBA RAID) + 9005 0410 ASC-48300(Spirit RAID) + 9005 0411 ASC-58300 (Oakmont RAID) + 0412 AIC-9410W SAS (Razor HBA non-RAID) + 9005 0412 ASC-48300 (Spirit non-RAID) + 9005 0413 ASC-58300 (Oakmont non-RAID) + 0415 ASC-58300 SAS (Razor-External HBA RAID) + 0416 ASC-58300 SAS (Razor-External HBA non-RAID) + 041e AIC-9410W SAS (Razor ASIC non-RAID) + 041f AIC-9410W SAS (Razor ASIC RAID) + 9005 041f AIC-9410W SAS (Razor ASIC RAID) + 042f VSC7250/7251 SAS (Aurora ASIC non-RAID) + 0430 AIC-9405W SAS (Razor-Lite HBA RAID) + 9005 0430 ASC-44300 (Spirit-Lite RAID) + 0432 AIC-9405W SAS (Razor-Lite HBA non-RAID) + 9005 0432 ASC-44300 (Spirit-Lite non-RAID) + 043e AIC-9405W SAS (Razor-Lite ASIC non-RAID) + 043f AIC-9405W SAS (Razor-Lite ASIC RAID) + 0450 ASC-1405 Unified Serial HBA + 0500 Obsidian chipset SCSI controller + 1014 02c1 PCI-X DDR 3Gb SAS Adapter (572A/572C) + 1014 02c2 PCI-X DDR 3Gb SAS RAID Adapter (572B/572D) + 0503 Scamp chipset SCSI controller + 1014 02bf Quad Channel PCI-X DDR U320 SCSI RAID Adapter (571E) + 1014 02c3 PCI-X DDR 3Gb SAS RAID Adapter (572F) + 1014 02d5 Quad Channel PCI-X DDR U320 SCSI RAID Adapter (571F) + 0910 AUA-3100B + 091e AUA-3100B + 8000 ASC-29320A U320 + 800f AIC-7901 U320 + 8010 ASC-39320 U320 + 8011 ASC-39320D + 0e11 00ac ASC-39320D U320 + 9005 0041 ASC-39320D U320 + 8012 ASC-29320 U320 + 8013 ASC-29320B U320 + 8014 ASC-29320LP U320 + 8015 ASC-39320B U320 + 8016 ASC-39320A U320 + 8017 ASC-29320ALP U320 + 9005 0044 ASC-29320ALP PCIx U320 + 9005 0045 ASC-29320LPE PCIe U320 + 801c ASC-39320D U320 + 801d AIC-7902B U320 + 1014 02cc ServeRAID 7e + 801e AIC-7901A U320 + 801f AIC-7902 U320 + 1734 1011 PRIMERGY RX300 onboard SCSI + 8080 ASC-29320A U320 w/HostRAID + 8081 PMC-Sierra PM8001 SAS HBA [Series 6H] + 8088 PMC-Sierra PM8018 SAS HBA [Series 7H] + 8089 PMC-Sierra PM8019 SAS encryption HBA [Series 7He] + 808f AIC-7901 U320 w/HostRAID + 1028 0168 Precision Workstation 670 Mainboard + 8090 ASC-39320 U320 w/HostRAID + 8091 ASC-39320D U320 w/HostRAID + 8092 ASC-29320 U320 w/HostRAID + 8093 ASC-29320B U320 w/HostRAID + 8094 ASC-29320LP U320 w/HostRAID + 8095 ASC-39320(B) U320 w/HostRAID + 8096 ASC-39320A U320 w/HostRAID + 8097 ASC-29320ALP U320 w/HostRAID + 809c ASC-39320D(B) U320 w/HostRAID + 809d AIC-7902(B) U320 w/HostRAID + 1014 02cc ServeRAID 7e + 809e AIC-7901A U320 w/HostRAID + 809f AIC-7902 U320 w/HostRAID +907f Atronics + 2015 IDE-2015PL +919a Gigapixel Corp +9412 Holtek + 6565 6565 +9413 Softlogic Co., Ltd. + 6010 SOLO6010 MPEG-4 Video encoder/decoder + 6110 SOLO6110 H.264 Video encoder/decoder +9618 JusonTech Corporation + 0001 JusonTech Gigabit Ethernet Controller +9699 Omni Media Technology Inc + 6565 6565 +# nee Netmos Technology +9710 MosChip Semiconductor Technology Ltd. + 9250 PCI-to-PCI bridge [MCS9250] + 9805 PCI 1 port parallel adapter + 9815 PCI 9815 Multi-I/O Controller + 1000 0020 2P0S (2 port parallel adaptor) + 9820 PCI 9820 Multi-I/O Controller + 9835 PCI 9835 Multi-I/O Controller + 1000 0002 2S (16C550 UART) + 1000 0012 1P2S + 9845 PCI 9845 Multi-I/O Controller +# Serial ports at BAR0-3 + 1000 0004 0P4S (4 port 16550A serial card) + 1000 0006 0P6S (6 port 16550a serial card) +# Serial ports at BAR0-3, Parallel port at BAR4 + 1000 0014 1P4S (1 Parallel / 4 16550A Serial Port Adapter) + 9855 PCI 9855 Multi-I/O Controller +# Parallel port at BAR0. Serial ports at BAR2-5 + 1000 0014 1P4S +# Parallel ports at BAR0,BAR2. Serial ports at BAR4-5 + 1000 0022 2P2S (2 Parallel / 2 16550A Serial Port Adapter) + 9865 PCI 9865 Multi-I/O Controller + 9900 MCS9900 Multi-I/O Controller + 9901 PCIe 9901 Multi-I/O Controller + 9904 4-Port PCIe Serial Adapter +# 2-port Serial 1-port Parallel Adaptor + 9912 PCIe 9912 Multi-I/O Controller + 9922 MCS9922 PCIe Multi-I/O Controller + 9990 MCS9990 PCIe to 4‐Port USB 2.0 Host Controller +# Subsystem ID on a 3c985B-SX network card +9850 3Com (wrong ID) +9902 Stargen Inc. + 0001 SG2010 PCI over Starfabric Bridge + 0002 SG2010 PCI to Starfabric Gateway + 0003 SG1010 Starfabric Switch and PCI Bridge +a0a0 AOPEN Inc. +a0f1 UNISYS Corporation +a200 NEC Corporation +a259 Hewlett Packard +a25b Hewlett Packard GmbH PL24-MKT +a304 Sony +a727 3Com Corporation + 0013 3CRPAG175 Wireless PC Card + 6803 3CRDAG675B Wireless 11a/b/g Adapter +aa00 iTuner +aa01 iTuner +aa02 iTuner +aa03 iTuner +aa04 iTuner +aa05 iTuner +aa06 iTuner +aa07 iTuner +aa08 iTuner +aa09 iTuner +aa0a iTuner +aa0b iTuner +aa0c iTuner +aa0d iTuner +aa0e iTuner +aa0f iTuner +aa42 Scitex Digital Video +aa55 Ncomputing X300 PCI-Engine +aaaa Adnaco Technology Inc. + 0001 H1 PCIe over fiber optic host controller + 0002 R1BP1 PCIe over fiber optic expansion chassis +abcd Vadatech Inc. +ac1e Digital Receiver Technology Inc +ac3d Actuality Systems +ad00 Alta Data Technologies LLC +aecb Adrienne Electronics Corporation + 6250 VITC/LTC Timecode Reader card [PCI-VLTC/RDR] +affe Sirrix AG security technologies + 01e1 PCI1E1 1-port ISDN E1 interface + 02e1 PCI2E1 2-port ISDN E1 interface + 450e PCI4S0EC 4-port ISDN S0 interface + dead Sirrix.PCI4S0 4-port ISDN S0 interface +b100 OpenVox Communication Co. Ltd. +# Not registered officially +b10b Uakron PCI Project +b1b3 Shiva Europe Limited +b1d9 ATCOM Technology co., LTD. +# Pinnacle should be 11bd, but they got it wrong several times --mj +bd11 Pinnacle Systems, Inc. (Wrong ID) +bdbd Blackmagic Design + a106 Multibridge Extreme + a117 Intensity Pro + a11a DeckLink HD Extreme 2 + a11b DeckLink SDI/Duo/Quad + a11c DeckLink HD Extreme 3 + a11d DeckLink Studio + a11e DeckLink Optical Fibre + a120 Decklink Studio 2 + a121 DeckLink HD Extreme 3D/3D+ + a124 Intensity Extreme + a126 Intensity Shuttle + a127 UltraStudio Express + a129 UltraStudio Mini Recorder + a12a UltraStudio Mini Monitor + a12d UltraStudio 4K + a12e DeckLink 4K Extreme + a12f DeckLink Mini Monitor + a130 DeckLink Mini Recorder + a132 UltraStudio 4K + a136 DeckLink 4K Extreme 12G + a137 DeckLink Studio 4K + a138 Decklink SDI 4K + a139 Intensity Pro 4K + a13b DeckLink Micro Recorder + a13d DeckLink 4K Pro + a13e UltraStudio 4K Extreme + a13f DeckLink Quad 2 + a140 DeckLink Duo 2 + a141 UltraStudio 4K Extreme 3 + a142 UltraStudio HD Mini + a143 DeckLink Mini Recorder 4K + a144 DeckLink Mini Monitor 4K + a148 DeckLink SDI Micro + a14b DeckLink 8K Pro + a14e DeckLink Quad HDMI Recorder + a1ff eGPU RX580 +c001 TSI Telsys +c0a9 Micron/Crucial Technology + 2263 P1 NVMe PCIe SSD +c0de Motorola +c0fe Motion Engineering, Inc. +ca3b Cambrionix Ltd. +ca50 Varian Australia Pty Ltd +cace CACE Technologies, Inc. + 0001 TurboCap Port A + 0002 TurboCap Port B + 0023 AirPcap N +caed Canny Edge +cafe Chrysalis-ITS + 0003 Luna K3 Hardware Security Module + 0006 Luna PCI-e 3000 Hardware Security Module + 0007 Luna K6 Hardware Security Module + 0008 Luna K7 Hardware Security Module +cc53 ScaleFlux Inc. +cccc Catapult Communications +ccec Curtiss-Wright Controls Embedded Computing +cddd Tyzx, Inc. + 0101 DeepSea 1 High Speed Stereo Vision Frame Grabber + 0200 DeepSea 2 High Speed Stereo Vision Frame Grabber +ceba KEBA AG +d161 Digium, Inc. + 0120 Wildcard TE120P single-span T1/E1/J1 card + 0205 Wildcard TE205P/TE207P dual-span T1/E1/J1 card 5.0V + 0210 Wildcard TE210P/TE212P dual-span T1/E1/J1 card 3.3V + 0220 Wildcard TE220 dual-span T1/E1/J1 card 3.3V (PCI-Express) + 0405 Wildcard TE405P/TE407P quad-span T1/E1/J1 card 5.0V + 0410 Wildcard TE410P/TE412P quad-span T1/E1/J1 card 3.3V + 0420 Wildcard TE420P quad-span T1/E1/J1 card 3.3V (PCI-Express) + 0800 Wildcard TDM800P 8-port analog card + 1205 Wildcard TE205P/TE207P dual-span T1/E1/J1 card 5.0V (u1) + 1220 Wildcard TE220 dual-span T1/E1/J1 card 3.3V (PCI-Express) (5th gen) + 1405 Wildcard TE405P/TE407P quad-span T1/E1/J1 card 5.0V (u1) + 1410 Wildcard TE410P quad-span T1/E1/J1 card 3.3V (5th Gen) + 1420 Wildcard TE420 quad-span T1/E1/J1 card 3.3V (PCI-Express) (5th gen) + 1820 Wildcard TE820 octal-span T1/E1/J1 card 3.3V (PCI-Express) + 2400 Wildcard TDM2400P 24-port analog card + 3400 Wildcard TC400P transcoder base card + 8000 Wildcard TE121 single-span T1/E1/J1 card (PCI-Express) + 8001 Wildcard TE122 single-span T1/E1/J1 card + 8002 Wildcard AEX800 8-port analog card (PCI-Express) + 8003 Wildcard AEX2400 24-port analog card (PCI-Express) + 8004 Wildcard TCE400P transcoder base card + 8005 Wildcard TDM410 4-port analog card + 8006 Wildcard AEX410 4-port analog card (PCI-Express) + 8007 Hx8 Series 8-port Base Card + 8008 Hx8 Series 8-port Base Card (PCI-Express) + 800a Wildcard TE133 single-span T1/E1/J1 card (PCI Express) + 800b Wildcard TE134 single-span T1/E1/J1 card + 800c Wildcard A8A 8-port analog card + 800d Wildcard A8B 8-port analog card (PCI-Express) + 800e Wildcard TE235/TE435 quad-span T1/E1/J1 card (PCI-Express) + 800f Wildcard A4A 4-port analog card + 8010 Wildcard A4B 4-port analog card (PCI-Express) + 8013 Wildcard TE236/TE436 quad-span T1/E1/J1 card + b410 Wildcard B410 quad-BRI card +d209 Ultimarc + 1500 PAC Drive + 15a2 SpinTrak + 1601 AimTrak +d4d4 Dy4 Systems Inc + 0601 PCI Mezzanine Card +d531 I+ME ACTIA GmbH +d84d Exsys +dada Datapath Limited + 0133 VisionRGB-X2 + 0139 VisionRGB-E1 + 0144 VisionSD8 + 0150 VisionRGB-E2 + 0151 VisionSD4+1 + 0159 VisionAV + 0161 DGC161 + 0165 DGC165 + 0167 DGC167 + 0168 DGC168 + 1139 VisionRGB-E1S + 1150 VisionRGB-E2S + 1151 VisionSD4+1S + 1153 VisionDVI-DL + 1154 VisionSDI2 +db10 Diablo Technologies +dc93 Dawicontrol GmbH +dcba Dynamic Engineering + 0046 PCIe Altera Cyclone IV +# VPX format Receiver Controller Board + 0047 VPX-RCB +# PMC Format FPGA design with 8 high speed UART channels + 0048 PMC-Biserial-III-BAE9 + 004e PC104p-Biserial-III-NVY5 + 004f PC104p-Biserial-III-NVY6 + 0052 PCIeBiSerialDb37 BA22 LVDS IO +# 8 port 16550 compatible UART, PMC format, RS-232 IO, RTS, CTS, DTR, DSR supported + 0066 PMC-OctalUART-232 +dd01 Digital Devices GmbH + 0003 Octopus DVB Adapter + dd01 0001 Octopus DVB adapter + dd01 0002 Octopus LE DVB adapter + dd01 0003 Octopus OEM + dd01 0004 Octopus V3 DVB adapter + dd01 0010 Octopus Mini + dd01 0020 Cine S2 V6 DVB adapter + dd01 0021 Cine S2 V6.5 DVB adapter + dd01 0030 Cine CT V6.1 DVB adapter + dd01 db03 Mystique SaTiX-S2 V3 DVB adapter + 0006 Cine V7 + 0007 Max + dd01 0023 Max S8 4/8 + 0011 Octopus CI DVB Adapter + dd01 0040 Octopus CI + dd01 0041 Octopus CI Single + 0201 Resi DVB-C Modulator + dd01 0001 Resi DVB-C Modulator +dead Indigita Corporation +deaf Middle Digital Inc. + 9050 PC Weasel Virtual VGA + 9051 PC Weasel Serial Port + 9052 PC Weasel Watchdog Timer +# formerly SoftHard Technology Ltd. +deda XIMEA + 4001 CB or MX camera + 4021 MT camera +e000 Winbond + e000 W89C940 +e159 Tiger Jet Network Inc. + 0001 Tiger3XX Modem/ISDN interface + 0059 0001 128k ISDN-S/T Adapter + 0059 0003 128k ISDN-U Adapter + 00a7 0001 TELES.S0/PCI 2.x ISDN Adapter + 8086 0003 Digium X100P/X101P analogue PSTN FXO interface + b100 0003 OpenVox A400P 4-port analog card + b1d9 0003 AX400P 4-port analog card + 0002 Tiger100APC ISDN chipset +e1c5 Elcus +e4bf EKF Elektronik GmbH + 0ccd CCD-CALYPSO + 0cd1 CD1-OPERA + 0cd2 CD2-BEBOP + 0cd3 CD3-JIVE + 50c1 PC1-GROOVE + 50c2 PC2-LIMBO + 53c1 SC1-ALLEGRO + cc47 CCG-RUMBA + cc4d CCM-BOOGIE +e4e4 Xorcom +e55e Essence Technology, Inc. +ea01 Eagle Technology + 000a PCI-773 Temperature Card + 0032 PCI-730 & PC104P-30 Card + 003e PCI-762 Opto-Isolator Card + 0041 PCI-763 Reed Relay Card + 0043 PCI-769 Opto-Isolator Reed Relay Combo Card + 0046 PCI-766 Analog Output Card + 0052 PCI-703 Analog I/O Card + 0800 PCI-800 Digital I/O Card +# The main chip of all these devices is by Xilinx -> It could also be a Xilinx ID. +ea60 RME + 9896 Digi32 + 9897 Digi32 Pro + 9898 Digi32/8 +eabb Aashima Technology B.V. +eace Endace Measurement Systems, Ltd + 3100 DAG 3.10 OC-3/OC-12 + 3200 DAG 3.2x OC-3/OC-12 + 320e DAG 3.2E Fast Ethernet + 340e DAG 3.4E Fast Ethernet + 341e DAG 3.41E Fast Ethernet + 3500 DAG 3.5 OC-3/OC-12 + 351c DAG 3.5ECM Fast Ethernet + 360d DAG 3.6D DS3 + 360e DAG 3.6E Fast Ethernet + 368e DAG 3.6E Gig Ethernet + 3707 DAG 3.7T T1/E1/J1 + 370d DAG 3.7D DS3/E3 + 378e DAG 3.7G Gig Ethernet + 3800 DAG 3.8S OC-3/OC-12 + 4100 DAG 4.10 OC-48 + 4110 DAG 4.11 OC-48 + 4220 DAG 4.2 OC-48 + 422e DAG 4.2GE Gig Ethernet + 4230 DAG 4.2S OC-48 + 423e DAG 4.2GE Gig Ethernet + 4300 DAG 4.3S OC-48 + 430e DAG 4.3GE Gig Ethernet + 452e DAG 4.5G2 Gig Ethernet + 454e DAG 4.5G4 Gig Ethernet + 45b8 DAG 4.5Z8 Gig Ethernet + 45be DAG 4.5Z2 Gig Ethernet + 520e DAG 5.2X 10G Ethernet + 521a DAG 5.2SXA 10G Ethernet/OC-192 + 5400 DAG 5.4S-12 OC-3/OC-12 + 5401 DAG 5.4SG-48 Gig Ethernet/OC-3/OC-12/OC-48 + 540a DAG 5.4GA Gig Ethernet + 541a DAG 5.4SA-12 OC-3/OC-12 + 542a DAG 5.4SGA-48 Gig Ethernet/OC-3/OC-12/OC-48 + 6000 DAG 6.0SE 10G Ethernet/OC-192 + 6100 DAG 6.1SE 10G Ethernet/OC-192 + 6200 DAG 6.2SE 10G Ethernet/OC-192 + 7100 DAG 7.1S OC-3/OC-12 + 7400 DAG 7.4S OC-3/OC-12 + 7401 DAG 7.4S48 OC-48 + 752e DAG 7.5G2 Gig Ethernet + 754e DAG 7.5G4 Gig Ethernet + 8100 DAG 8.1X 10G Ethernet + 8101 DAG 8.1SX 10G Ethernet/OC-192 + 8102 DAG 8.1X 10G Ethernet + 820e DAG 8.2X 10G Ethernet + 820f DAG 8.2X 10G Ethernet (2nd bus) + 8400 DAG 8.4I Infiniband x4 SDR + 8500 DAG 8.5I Infiniband x4 DDR + 9200 DAG 9.2SX2 10G Ethernet + 920e DAG 9.2X2 10G Ethernet + 9540 DAG 9.5G4 Gig Ethernet + 954f DAG 9.5G4F Gig Ethernet + a120 DAG 10X2-P 10G Ethernet + a12e DAG 10X2-S 10G Ethernet + a140 DAG 10X4-P 10/40G Ethernet + a14e DAG 10X4-S 10/40G Ethernet + eace vDAG virtual device +ec80 Belkin Corporation + ec00 F5D6000 +ecc0 Echo Digital Audio Corporation +edd8 ARK Logic Inc + a091 1000PV [Stingray] + a099 2000PV [Stingray] + a0a1 2000MT + a0a9 2000MI +# Found on M2N68-AM Motherboard +f043 ASUSTeK Computer Inc. (Wrong ID) +f05b Foxconn International, Inc. (Wrong ID) +f15e SiFive, Inc. +f1d0 AJA Video + c0fe Xena HS/HD-R + c0ff Kona/Xena 2 + cafe Kona SD + cfee Xena LS/SD-22-DA/SD-DA + dafe Corvid 1 + daff KONA LHi + db00 IoExpress + db01 Corvid22 + db02 Kona 3G + db03 Corvid 3G + db04 Kona 3G QUAD + db05 Kona LHe+ + db06 IoXT + db07 Kona 3G P2P + db08 Kona 3G QUAD P2P + db09 Corvid 24 + db11 T-Tap + dcaf Kona HD + dfee Xena HD-DA + eb07 Io4K + eb0a Io4K UFC + eb0b Kona 4 + eb0c Kona 4 UFC + eb0d Corvid 88 + eb0e Corvid 44 + eb16 Corvid HEVC + 10cf 1049 Corvid HEVC M31 + eb18 Corvid HB-R + eb1a Kona IP 1SFP + eb1c Kona IP 2SFP + eb1d Io4KPlus + eb1e IoIP + eb1f Kona 5 + eb23 Kona 1 + eb24 Kona HDMI + eb25 Corvid 44 12g + efac Xena SD-MM/SD-22-MM + facd Xena HD-MM +f5f5 F5 Networks, Inc. +# Subsystem ID for PATA controller on nForce motherboard +f849 ASRock Incorporation (Wrong ID) +fa57 Interagon AS + 0001 PMC [Pattern Matching Chip] +fab7 Fabric7 Systems, Inc. +febd Ultraview Corp. +# Nee Epigram +feda Broadcom Inc + a0fa BCM4210 iLine10 HomePNA 2.0 + a10e BCM4230 iLine10 HomePNA 2.0 +fede Fedetec Inc. + 0003 TABIC PCI v3 +fffd XenSource, Inc. + 0101 PCI Event Channel Controller +# Used in some old VMWare products before they got a real ID assigned +fffe VMWare Inc (temporary ID) + 0710 Virtual SVGA +ffff Illegal Vendor ID + + +# List of known device classes, subclasses and programming interfaces + +# Syntax: +# C class class_name +# subclass subclass_name <-- single tab +# prog-if prog-if_name <-- two tabs + +C 00 Unclassified device + 00 Non-VGA unclassified device + 01 VGA compatible unclassified device +C 01 Mass storage controller + 00 SCSI storage controller + 01 IDE interface + 00 ISA Compatibility mode-only controller + 05 PCI native mode-only controller + 0a ISA Compatibility mode controller, supports both channels switched to PCI native mode + 0f PCI native mode controller, supports both channels switched to ISA compatibility mode + 80 ISA Compatibility mode-only controller, supports bus mastering + 85 PCI native mode-only controller, supports bus mastering + 8a ISA Compatibility mode controller, supports both channels switched to PCI native mode, supports bus mastering + 8f PCI native mode controller, supports both channels switched to ISA compatibility mode, supports bus mastering + 02 Floppy disk controller + 03 IPI bus controller + 04 RAID bus controller + 05 ATA controller + 20 ADMA single stepping + 30 ADMA continuous operation + 06 SATA controller + 00 Vendor specific + 01 AHCI 1.0 + 02 Serial Storage Bus + 07 Serial Attached SCSI controller + 01 Serial Storage Bus + 08 Non-Volatile memory controller + 01 NVMHCI + 02 NVM Express + 80 Mass storage controller +C 02 Network controller + 00 Ethernet controller + 01 Token ring network controller + 02 FDDI network controller + 03 ATM network controller + 04 ISDN controller + 05 WorldFip controller + 06 PICMG controller + 07 Infiniband controller + 08 Fabric controller + 80 Network controller +C 03 Display controller + 00 VGA compatible controller + 00 VGA controller + 01 8514 controller + 01 XGA compatible controller + 02 3D controller + 80 Display controller +C 04 Multimedia controller + 00 Multimedia video controller + 01 Multimedia audio controller + 02 Computer telephony device + 03 Audio device + 80 Multimedia controller +C 05 Memory controller + 00 RAM memory + 01 FLASH memory + 80 Memory controller +C 06 Bridge + 00 Host bridge + 01 ISA bridge + 02 EISA bridge + 03 MicroChannel bridge + 04 PCI bridge + 00 Normal decode + 01 Subtractive decode + 05 PCMCIA bridge + 06 NuBus bridge + 07 CardBus bridge + 08 RACEway bridge + 00 Transparent mode + 01 Endpoint mode + 09 Semi-transparent PCI-to-PCI bridge + 40 Primary bus towards host CPU + 80 Secondary bus towards host CPU + 0a InfiniBand to PCI host bridge + 80 Bridge +C 07 Communication controller + 00 Serial controller + 00 8250 + 01 16450 + 02 16550 + 03 16650 + 04 16750 + 05 16850 + 06 16950 + 01 Parallel controller + 00 SPP + 01 BiDir + 02 ECP + 03 IEEE1284 + fe IEEE1284 Target + 02 Multiport serial controller + 03 Modem + 00 Generic + 01 Hayes/16450 + 02 Hayes/16550 + 03 Hayes/16650 + 04 Hayes/16750 + 04 GPIB controller + 05 Smard Card controller + 80 Communication controller +C 08 Generic system peripheral + 00 PIC + 00 8259 + 01 ISA PIC + 02 EISA PIC + 10 IO-APIC + 20 IO(X)-APIC + 01 DMA controller + 00 8237 + 01 ISA DMA + 02 EISA DMA + 02 Timer + 00 8254 + 01 ISA Timer + 02 EISA Timers + 03 HPET + 03 RTC + 00 Generic + 01 ISA RTC + 04 PCI Hot-plug controller + 05 SD Host controller + 06 IOMMU + 80 System peripheral +C 09 Input device controller + 00 Keyboard controller + 01 Digitizer Pen + 02 Mouse controller + 03 Scanner controller + 04 Gameport controller + 00 Generic + 10 Extended + 80 Input device controller +C 0a Docking station + 00 Generic Docking Station + 80 Docking Station +C 0b Processor + 00 386 + 01 486 + 02 Pentium + 10 Alpha + 20 Power PC + 30 MIPS + 40 Co-processor +C 0c Serial bus controller + 00 FireWire (IEEE 1394) + 00 Generic + 10 OHCI + 01 ACCESS Bus + 02 SSA + 03 USB controller + 00 UHCI + 10 OHCI + 20 EHCI + 30 XHCI + 80 Unspecified + fe USB Device + 04 Fibre Channel + 05 SMBus + 06 InfiniBand + 07 IPMI Interface + 00 SMIC + 01 KCS + 02 BT (Block Transfer) + 08 SERCOS interface + 09 CANBUS +C 0d Wireless controller + 00 IRDA controller + 01 Consumer IR controller + 10 RF controller + 11 Bluetooth + 12 Broadband + 20 802.1a controller + 21 802.1b controller + 80 Wireless controller +C 0e Intelligent controller + 00 I2O +C 0f Satellite communications controller + 01 Satellite TV controller + 02 Satellite audio communication controller + 03 Satellite voice communication controller + 04 Satellite data communication controller +C 10 Encryption controller + 00 Network and computing encryption device + 10 Entertainment encryption device + 80 Encryption controller +C 11 Signal processing controller + 00 DPIO module + 01 Performance counters + 10 Communication synchronizer + 20 Signal processing management + 80 Signal processing controller +C 12 Processing accelerators + 00 Processing accelerators +# For the class of PCI attached devices which perform a function of Deep Learning Neural Network inference acceleration + 01 AI Inference Accelerator +C 13 Non-Essential Instrumentation +C 40 Coprocessor +C ff Unassigned class diff --git a/hwdb.d/pnp_id_registry.html b/hwdb.d/pnp_id_registry.html new file mode 100644 index 00000000..faaa308b --- /dev/null +++ b/hwdb.d/pnp_id_registry.html @@ -0,0 +1,2464 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CompanyPNP IDApproved on Date
21ST CENTURY ENTERTAINMENTBUT04/25/2002
2-Tel B.VTTL03/20/1999
3Com CorporationTCM11/29/1996
3D PerceptionTDP05/16/2002
3MVSD10/16/1998
3NOD Digital Technology Co. Ltd.NOD12/11/2014
A D S ExportsNGS07/16/1998
A Plus Info CorporationAPI11/29/1996
A&R Cambridge Ltd.ACG06/13/2007
A/Vaux ElectronicsAVX08/29/2012
A+V LinkAPV01/27/2010
Aashima Technology B.V.TRU05/08/1998
Aava Mobile OyAAM08/13/2013
ABBAHOME INC.ABA11/08/1999
Abeam Tech Ltd.MEG11/29/1996
Ably-Tech CorporationATC11/29/1996
AboCom System Inc.ABC03/28/1997
ACC MicroelectronicsWTC11/29/1996
Access Works Comm IncAWC11/29/1996
Acco UK Ltd.PKA05/12/2003
Accton Technology CorporationACC11/29/1996
AcculogicACU11/29/1996
AccuScene Corporation LtdASL06/13/2007
Ace CAD Enterprise Company LtdANT11/29/1996
Acer IncCHE11/29/1996
Acer LabsALI11/29/1996
Acer Netxus IncANX11/29/1996
Acer TechnologiesACR11/29/1996
AcksysACK11/29/1996
Acnhor DatacommADC11/29/1996
AconCAL11/29/1996
Acrolink IncALK03/12/1997
Acroloop Motion Control Systems IncACM03/26/1998
ACT Labs LtdLAB09/02/1997
Actek Engineering Pty LtdACE11/29/1996
Actiontec Electric IncAEI11/29/1996
ActivCard S.AACV05/08/1998
Aculab LtdACB11/29/1996
Acutec Ltd.ALM11/08/1999
AD electronicsGLE04/19/2000
Ad Lib MultiMedia IncADM04/23/1998
Adaptec IncADP11/29/1996
Adax IncADX11/29/1996
ADC-CentreRSH11/08/1999
Add Value Enterpises (Asia) Pte LtdAVE01/10/1999
Addi-Data GmbHADA11/29/1996
ADI Systems IncADI11/29/1996
ADPM Synthesis sasDPM08/10/2000
Adrienne Electronics CorporationAXB10/07/1997
AdtekADT11/29/1996
Adtek System Science Company LtdADK11/29/1996
ADTI Media, IncFLE09/15/2009
Adtran IncAND11/29/1996
Advan Int'l CorporationAGM05/26/1998
Advance Computer CorporationAVN06/10/2010
Advanced Digital SystemsMSM11/29/1996
Advanced Electronic Designs, Inc.AED07/12/2004
Advanced EngineeringRJS06/25/1998
Advanced GravisGRV11/29/1996
Advanced Integ. Research IncAIR11/29/1996
Advanced LogicALR11/29/1996
Advanced Micro Devices IncADV11/29/1996
Advanced Micro Peripherals LtdEVE11/18/2011
Advanced Optics Electronics, Inc.AOE04/20/2004
Advanced Peripheral Devices IncADD11/29/1996
Advanced Research TechnologyABV01/16/1997
Advanced Signal Processing TechnologiesPSA09/13/1999
Advantech Co., Ltd.AHC06/13/2007
Aerodata Holdings LtdADH11/11/1997
Aetas Peripheral InternationalAEP11/08/1999
Aethra Telecomunicazioni S.r.l.AET12/13/1996
Agentur ChairosCHS03/15/2001
Agilent TechnologiesAGT10/08/2001
Ahead SystemsASI11/29/1996
AIMS Lab IncAIM03/13/1998
Airlib, IncAYR02/21/2000
Aironet Wireless Communications, IncAWL08/11/1998
Aiwa Company LtdAIW11/29/1996
AJA Video Systems, Inc.AJA10/11/2007
AKAMI Electric Co.,LtdAKE09/03/2010
Akebia LtdAKB11/29/1996
AKIA CorporationAKI12/23/1998
AL SystemsALH01/20/1999
Alacron IncALA11/29/1996
Alana TechnologiesALN01/13/2000
AlcatelAOT11/06/2001
Alcatel BellABE11/29/1996
AldebbaronADB03/15/2001
Alenco BVALE05/20/2014
ALEXON Co.,Ltd.ALX09/13/1999
Alfa IncAFA11/29/1996
Algolith Inc.ALO05/02/2005
AlgolTek, Inc.AGO10/23/2013
Alien Internet ServicesAIS06/21/2001
Allen Bradley CompanyABD11/29/1996
Alliance Semiconductor CorporationALL11/29/1996
Allied Telesis KKATI11/29/1996
Allied Telesyn International (Asia) Pte LtdATA11/10/1997
Allied Telesyn Int'lATK11/29/1996
Allion Computer Inc.ACO10/23/2000
Alpha DataXAD10/08/2009
Alpha Telecom IncATD09/26/1997
Alpha-Top CorporationATP12/04/1996
AlphaView LCDALV11/01/2008
Alpine Electronics, Inc.APE01/22/2013
Alps Electric Company LtdALP11/29/1996
Alps Electric IncAUI11/29/1996
Alta Research CorporationARC11/29/1996
Altec CorporationALC08/04/1998
Altec LansingALJ01/13/2000
ALTINEX, INC.AIX04/24/2001
Altmann IndustrieelektronikAIE11/29/1996
Altos Computer SystemsACS11/29/1996
Altos India LtdAIL11/29/1996
Alvedon Computers LtdCNC11/06/1998
Ambient Technologies, Inc.AMB05/16/1999
AltraALT11/29/1996
Amdek CorporationAMD11/29/1996
America OnLineAOL11/29/1996
American Biometric CompanyYOW05/16/1999
American ExpressAXP07/16/1999
American MagneticsAXI03/15/2001
American Megatrends IncAMI11/29/1996
American Nuclear Systems IncMCA02/12/1997
American Power ConversionCNB03/15/2001
American Power ConversionAPC11/29/1996
Amimon LTD.AMN06/13/2007
Amino Technologies PLC and Amino Communications LimitedAMO12/09/2011
AMiT LtdAKL12/02/1997
AMP IncAMP11/29/1996
Amptron International Inc.AII05/24/2000
AMT International IndustryAMT11/29/1996
AmTRAN Technology Co., Ltd.AMR06/10/2013
AMX LLCAMX07/06/2008
AnakronANA11/08/1999
Analog & Digital Devices Tel. IncADN03/14/1997
Analog Devices IncADS11/29/1996
Analog Way SASANW01/22/2014
Analogix Semiconductor, IncANL10/10/2005
Anchor Bay Technologies, Inc.ABT02/14/2006
Anatek Electronics Inc.AAE05/25/2004
Ancor Communications IncACI11/29/1996
AncotANC11/29/1996
Anderson Multimedia Communications (HK) LimitedAML01/03/2003
Andrew Network ProductionANP11/29/1996
Anigma IncANI11/29/1996
Anko Electronic Company LtdANK03/24/1998
Ann Arbor TechnologiesAAT04/24/2001
an-najah universityBBB03/15/2001
Anorad CorporationANO01/13/2000
ANR LtdANR11/29/1996
Ansel Communication CompanyANS11/29/1996
Antex Electronics CorporationAEC11/29/1996
AOpen Inc.AOA11/06/2001
AP Designs LtdAPX12/08/1997
Apache Micro Peripherals IncDNG11/11/1997
Aplicom OyAPL05/02/2005
Appian Tech IncAPN11/29/1996
Apple Computer IncAPP11/29/1996
AppliAdataAPD11/29/1996
Applied Creative TechnologyACT11/29/1996
Applied Memory TechAPM11/29/1996
Apricot ComputersACL11/29/1996
Aprilia s.p.a.APR02/22/1999
ArchiTek CorporationATJ01/22/2014
Archtek Telecom CorporationACH01/15/1997
Arcus Technology LtdATL11/29/1996
AREC Inc.ARD07/08/2013
Arescom IncARS11/29/1996
ArgolisAGL03/15/2001
Argosy Research IncARI02/24/1997
Argus Electronics Co., LTDARG06/04/2004
Ariel CorporationACA12/13/1996
ArimaARM04/07/2004
Arithmos, Inc.ADE07/16/1999
Ark Logic IncARK11/29/1996
Arlotto Comnet IncARL04/29/1997
ARMSTEL, Inc.AMS 02/25/2011
Arnos Insturments & Computer SystemsAIC11/29/1996
ARRIS Group, Inc. ARR01/27/2015
ART s.r.l.IMB01/27/2012
Artish Graphics IncAGI11/29/1996
ArvanicsNPA03/05/2015
Asahi Kasei Microsystems Company LtdAKM11/29/1996
Asante Tech IncASN11/29/1996
Ascom Business SystemsHER01/20/1999
Ascom Strategic Technology UnitASC11/29/1996
ASEM S.p.A.ASM03/15/2001
ASEM S.p.A.AEM11/29/1996
AseV Display LabsASE10/16/1998
Ashton Bentley ConceptsASH09/20/2013
Asia Microelectronic Development IncAMA09/24/1997
Ask A/SASK11/29/1996
Askey Computer CorporationDYN07/22/1997
ASP Microelectronics LtdASP11/29/1996
Askey Computer CorporationAKY04/02/1997
Aspen Tech IncACP11/29/1996
AST Research IncAST11/29/1996
Astec IncJAC11/29/1996
ASTRA Security Products LtdADL07/30/1997
ASTRO DESIGN, INC.ATO06/06/2003
Asuscom Network IncASU11/29/1996
AT&TATT11/29/1996
AT&T Global Info SolutionsGIS11/29/1996
AT&T MicroelectronicsHSM11/29/1996
AT&T MicroelectronicsTME11/29/1996
AT&T ParadynePDN11/29/1996
Atelier Vision CorporationAVJ02/24/2015
Athena Informatica S.R.L.ATH01/29/1997
Athena Smartcard Solutions Ltd.ATN09/13/1999
Athenix CorporationATX11/29/1996
ATI Tech IncBUJ11/29/1996
AtlantisCFG11/29/1996
ATM LtdATM11/29/1996
Atom Komplex PryladAKP10/23/2000
Attachmate CorporationAMC11/29/1996
Attero Tech, LLCFWA04/20/2010
Audio Processing Technology LtdAPT03/18/1997
AudioScienceASX11/29/1996
August Home, Inc.AUG06/11/2014
Auravision CorporationAVC11/29/1996
Aureal SemiconductorAUR11/29/1996
Autologic IncAPS11/29/1996
automated computer control systemsCLT09/13/1999
Autotime CorporationAUT10/08/2001
Auvidea GmbHAUV04/21/2014
Avalue Technology Inc.AVL11/18/2011
Avance Logic IncALS11/29/1996
Avaya CommunicationAVA03/15/2001
AvencallAEN01/27/2012
AVer Information Inc.AVR05/07/2010
Avid Electronics CorporationAVD11/29/1996
AVM GmbHAVM11/29/1996
Avolites LtdAAA02/17/2012
Avocent CorporationAVO10/23/2000
Avtek (Electronics) Pty LtdAVT11/29/1996
AWETA BVACD01/20/1998
AxelAXL11/29/1996
AXIOMTEK CO., LTD.AXC05/02/2005
Axonic Labs LLCAXO06/21/2012
Axtend Technologies IncAXT12/01/1997
Axxon Computer CorporationAXX11/29/1996
AXYZ Automation Services, IncAXY08/11/1998
Aydin DisplaysAYD06/13/2007
AZ Middelheim - RadiotherapyAZM11/14/2003
Aztech Systems LtdAZT11/29/1996
B&BhBBH01/17/2003
B.& V. s.r.l.SMR03/21/1997
B.F. Engineering CorporationBFE11/29/1996
B.U.G., Inc.BUG08/30/2011
Bang & OlufsenBNO05/16/2003
Banksia Tech Pty LtdBNK11/29/1996
BanyanBAN11/29/1996
BARCBRC08/10/2000
Barco Display SystemsBDS09/13/1999
Barco GmbHBCD03/07/2011
Barco Graphics N.VBGB11/29/1996
Barco, N.V.BPS09/12/2000
Barco, N.V.DDS10/23/2000
Baug & OlufsenBEO11/29/1996
Beaver Computer CorporatonBCC11/29/1996
Beckhoff AutomationBEC04/25/2002
Beckworth Enterprises IncBEI07/16/1997
Beijing Aerospace Golden Card Electronic Engineering Co.,Ltd.AGC06/21/2001
Beijing AnHeng SecoTech Information Technology Co., Ltd.AHS03/24/2015
Beijing ANTVR Technology Co., Ltd.ANV08/24/2015
Beijing Northern Radiantelecom Co.NRT03/20/1999
Beko Elektronik A.S.BEK06/15/2005
Beltronic Industrieelektronik GmbHBEL09/05/2006
Benson Medical Instruments CompanyBMI12/04/1996
Bernecker & Rainer Ind-Eletronik GmbHBUR11/29/1996
Best BuyINZ06/04/2004
Best BuyVPR05/16/2002
Best PowerBPU11/29/1996
Biamp Systems CorporationBIA05/14/2015
BICC Data Networks LtdICC11/29/1996
Big Island CommunicationsBIC05/13/1997
Billion Electric Company LtdBIL12/11/1996
BioLink TechnologiesBLN08/10/2000
BioLink Technologies International, Inc.BIO05/24/2000
BIOMED LabBML05/22/1997
Biomedical Systems LaboratoryBSL10/16/1997
BIOMEDISYSBMS05/24/2000
Biometric Access CorporationBAC05/19/1998
BioTao LtdBTO03/21/2012
Bit 3 ComputerBIT11/29/1996
Bit 3 ComputerBTC11/29/1996
Bitfield OyBTF11/29/1996
BitHeadz, Inc.BHZ09/29/2003
Bitworks Inc.BWK07/10/2003
Blackmagic DesignBMD09/13/2012
Blonder Tongue Labs, Inc.BDR09/16/2008
Bloomberg L.P.BLP09/16/2008
Boca Research IncZZZ02/13/1997
Boca Research IncBRI11/29/1996
BodySound Technologies, Inc.BST03/12/2008
Boeckeler Instruments IncBII10/17/1996
Booria CAD/CAM systemsBCS05/11/2005
BOSBOS07/03/1997
Bose CorporationBSE09/05/2006
Boulder Nonlinear SystemsBNS03/12/2008
Braemac Pty LtdBRA11/18/2010
Braemar IncBRM10/07/1997
Brahler ICSBDO06/04/1998
Brain Boxes LimitedBBL10/02/2001
Bridge Information Co., LtdBRG08/11/1998
BRIGHTSIGN, LLCBSN02/28/2012
Brilliant TechnologyBTE11/29/1996
Broadata Communications Inc. BCI11/19/2013
BroadcomBCM04/01/2004
BROTHER INDUSTRIES,LTD.BRO02/21/2000
BTC Korea Co., LtdNFC02/25/2002
Budzetron IncBGT11/29/1996
BullBUL02/03/1998
Bull ABBNE10/06/1998
BusicomBLI08/11/1998
BusTech IncBTI11/29/1996
BusTekBUS11/29/1996
Butterfly CommunicationsFLY05/05/1997
Buxco ElectronicsBXE11/29/1996
byd:sign corporationBYD04/10/2008
C3PO S.L.XMM03/03/1998
CA & F ElettronicaCAC05/16/1999
Cabletime LtdCBT05/04/2010
Cabletron System IncCSI11/29/1996
CacheCCI11/29/1996
CalCompCAG11/29/1996
CalCompCDP11/29/1996
Calibre UK LtdCUK09/15/2005
California Institute of TechnologyCSO03/20/1999
Cambridge AudioCAM08/09/2008
Cambridge Electronic Design LtdCED11/29/1996
Cambridge Research Systems LtdCMR04/25/2002
Canon IncCNN11/29/1996
Canon Inc.CAI11/06/2001
Canonical Ltd.UBU05/24/2013
Canopus Company LtdCAN11/29/1996
Capella Microsystems Inc.CPM05/09/2012
Capetronic USA IncCCP11/29/1996
Capstone Visua lProduct Development DJE10/09/2008
Cardinal Company LtdCAR11/29/1996
Cardinal Technical IncCRD11/29/1996
CardLogixCLX03/15/2001
Carina System Co., Ltd.CKJ09/03/2010
Carl Zeiss AGCZE06/03/2009
CASIO COMPUTER CO.,LTDCAS10/06/1998
Castles Automation Co., LtdCAA01/13/2000
Cavium Networks, IncCAV02/02/2011
C-C-C Group PlcFVX05/04/1998
CCL/ITRICCL03/31/1997
C-Cube MicrosystemsCCC11/29/1996
C-DACCEP11/29/1996
Cebra Tech A/SCBR11/29/1996
Cefar Digital VisionCEF02/19/1997
Centurion Technologies P/LCEN10/23/2000
Century CorporationTCE11/29/1996
Cerevo Inc.CRV07/13/2010
CeronixCER09/02/2008
Ceton CorporationTOM05/08/2014
CH ProductsCHP04/24/1997
ChangHong Electric Co.,LtdCHD11/30/2001
Chase Research PLCCHA11/29/1996
Cherry GmbHCHY05/16/1999
Chi Mei Optoelectronics corp.CMO03/15/2001
CHIC TECHNOLOGY CORP.CHM07/16/1999
Chicony Electronics Company LtdCEC11/29/1996
Chimei Innolux CorporationCMN09/02/2010
China Hualu Group Co., Ltd.HLG05/13/2013
Chloride-R&DCHL11/29/1996
Christie Digital Systems IncCDG04/24/2001
Chromatec Video Products LtdCVP08/09/2013
Chrontel IncCHI11/29/1996
Chunghwa Picture Tubes,LTD.CHT03/15/2001
Chunghwa Telecom Co., Ltd.CTE05/16/2002
Chunichi Denshi Co.,LTD.KCD12/23/2010
Chuomusen Co., Ltd. QQQ08/07/2002
Chyron CorpCGS11/13/2008
Cine-talCNE06/13/2007
Cipher Systems IncPTG11/29/1996
Ciprico IncCIP11/29/1996
Ciprico IncCPC11/29/1996
Cirel SystemesFPX11/29/1996
Cirque CorporationCRQ11/29/1996
Cirrus Logic IncCIR11/29/1996
Cirrus Logic IncCLI11/29/1996
Cirtech (UK) LtdSNS08/20/1997
CIS Technology IncWSC11/29/1996
Cisco Systems IncCIS11/29/1996
Citicom Infotech Private LimitedCIL08/10/2000
Citifax LimitedCIT07/16/1997
Citron GmbHCIN07/28/2005
Clarion Company LtdCLA11/29/1996
Clarity Visual SystemsCVS01/13/2000
Classe AudioCLE02/16/2006
Clevo CompanyCLV01/30/1998
Clinton Electronics Corp.PPM10/01/2003
Clone ComputersCLO11/29/1996
Cloudium Systems Ltd.CSL02/14/2013
CMC LtdCMC11/29/1996
C-Media ElectronicsCMI11/29/1996
CNet Technical IncJQE11/29/1996
COBY Electronics Co., LtdCOB06/13/2007
CODAN Pty. Ltd.COD10/23/2000
Codec Inc.COI11/30/2001
Codenoll Technical CorporationCDN11/29/1996
COINT Multimedia SystemsCNT03/20/1999
Colin.deCDE01/18/2005
Colorado MicroDisplay, Inc.CMD03/20/1999
Colorado Video, Inc.CVI08/15/2012
COM 1MVX11/29/1996
Comex Electronics ABCMX05/28/2004
Comm. Intelligence CorporationCIC11/29/1996
COMMAT L.t.d.CLD08/10/2000
Communications Specialies, Inc.SDH09/06/2005
Communications Supply Corporation (A division of WESCO)INX11/07/2012
Compal Electronics IncCPL11/29/1996
Compaq Computer CompanyCPQ11/29/1996
Compound PhotonicsCPP10/01/2013
CompuAddCPD11/29/1996
CompuMaster SrlCMS02/22/1999
Computer Diagnostic SystemsCDS03/15/2001
Computer Peripherals IncCPI11/29/1996
Computer Technology CorporationCTP03/26/1998
ComputerBoards IncCBI02/03/1998
Computerm CorporationCTM11/29/1996
Computone ProductsCTN11/29/1996
ComrexCOX10/18/2011
Comtec Systems Co., Ltd.CTS04/25/2002
Comtime GmbHCMM09/23/2002
Comtrol CorporationCOM11/29/1996
Concept Development IncCDI11/29/1996
Concept Solutions & EngineeringCSE12/11/1996
Concepts IncDCI11/29/1996
Conexant SystemsCXT01/20/1999
congatec AGCGT06/16/2011
Connect Int'l A/SCNI11/29/1996
Connectware IncCWR11/29/1996
CONRAC GmbHCRC04/20/2004
Consultancy in Advanced TechnologyCAT09/19/1997
Consumer Electronics AssociationCEA09/05/2006
CONTEC CO.,LTD.CCJ08/10/2000
Contec Company LtdCON11/29/1996
Contemporary Research Corp.CRH02/24/2015
Control4 CorporationCTR05/28/2014
Convergent Data DevicesCDD02/27/2004
Convergent Design Inc.CDV09/05/2006
Core Dynamics CorporationCDC11/29/1996
Corion Industrial CorporationART11/29/1996
Core Technology IncCOT04/19/2000
CoreLogicCLG11/27/1998
Cornerstone ImagingCRN11/29/1996
Corollary IncCOR12/13/1996
Cosmic Engineering Inc.CSM04/18/2012
CoStar CorporationCOS11/29/1996
CoSystems IncCTA10/24/1998
Covia Inc.CVA05/11/2010
cPATHCPT03/09/1998
CRALTECH ELECTRONICA, S.L.CRA03/24/2015
Cray CommunicationsCDK11/29/1996
CRE Technology CorporationIOA06/30/1997
Creative Labs IncCRE11/29/1996
Creative Logic  CRL10/16/1997
Creative Technology LtdCTL11/29/1996
Creatix Polymedia GmbHCTX11/29/1996
Crescendo Communication IncCRS11/29/1996
Cresta Systems IncCSD08/01/1997
Crestron Electronics, Inc.CEI05/08/2006
Crio Inc.CRI09/13/1999
Cromack Industries IncCII01/22/1997
Crystal ComputerXTL11/29/1996
Crystal SemiconductorCSC11/29/1996
CrystaLake MultimediaCLM11/29/1996
CSS LaboratoriesCSS01/02/1997
CSTI IncCST11/29/1996
CTC Communication Development Company LtdCTC10/21/1997
Cubix CorporationCUB11/29/1996
Curtiss-Wright Controls, Inc.CWC04/05/2013
CyberlabsCYL04/14/1998
CyberVisionCYB05/13/1997
CyberwareCYW02/21/2000
Cybex Computer Products CorporationCBX11/08/1999
Cyclades CorporationCYD05/07/2001
Cylink CorporationCYC11/29/1996
Cyrix CorporationCYX10/21/1997
Cyrix CorporationCRX03/21/1997
Cytechinfo IncCYT03/13/1998
Cyviz ASCYV04/25/2002
D&M Holdings Inc, Professional Business CompanyDMP09/05/2006
D.N.S. CorporationOPI11/29/1996
DA2 Technologies CorporationDDA03/13/2006
DA2 Technologies IncDAW09/06/2005
Daewoo Electronics Company LtdDWE11/29/1996
Dai Telecom S.p.A.TLT06/04/2003
Daintelecom Co., LtdDIN11/08/1999
DAIS SET Ltd.DAI02/21/2000
DaktronicsDAK06/23/2004
Dale Computer CorporationDCC11/29/1996
Dancall Telecom A/SDCT08/12/1997
Danelec Marine A/SDAN12/24/2009
Danka Data DevicesDDD11/29/1996
Daou Tech IncDAU11/29/1996
DATHCA03/15/2001
Data Apex LtdDAX11/29/1996
Data Display AGDDI07/17/2002
Data Expert CorporationDXP11/29/1996
Data Export CorporationEXP11/29/1996
Data Modul AGDMO12/03/2013
Data Price InformaticaEBH05/24/2001
Data Race IncDRI07/30/1997
Data Ray Corp.DRC11/30/2001
Data TranslationDTX11/29/1996
Data VideoDVT02/13/2007
Databook IncDBK11/29/1996
Datacast LLCDCD12/02/1997
Datacommunicatie Tron B.V.TRN11/29/1996
Datacube IncDQB11/29/1996
Datadesk Technologies IncDDT11/27/1998
Datakey IncDKY04/06/1998
Datalogic CorporationLJX11/29/1996
Datang Telephone CoDTN09/23/1998
Dataq Instruments IncDII11/29/1996
Datasat Digital EntertainmentDDE11/18/2011
Datatronics Technology IncDCV01/02/1997
Datel IncDAT11/29/1996
Datenerfassungs- und InformationssystemeMSD03/16/1998
Davicom Semiconductor IncDAV01/15/1997
DAVIS ASDAS02/03/1998
DB Networks IncDBN12/01/1997
DBA Hans WedemeyerHWC03/20/1999
DCM Data ProductsDCM11/29/1996
Dearborn Group TechnologyDGT11/11/1997
DECIMATOR DESIGN PTY LTDDXD03/06/2012
Decros LtdDCR11/29/1996
Deep Video Imaging LtdMLD08/14/2003
DEI Holdings dba Definitive TechnologyDFT12/09/2011
Deico ElectronicsDEI11/29/1996
Dell IncDLL03/27/2009
Dell Inc.DEL12/09/2009
Delphi Automotive LLPDPH10/15/2013
Delta Electronics IncDPC11/29/1996
Delta Information Systems, IncDDV01/03/2012
DELTATEC DTA03/13/2009
Deltec CorporationFPS11/29/1996
DENON, Ltd.DON04/01/2004
Dension Audio SystemsDHD03/04/2013
Densitron Computers LtdDEN09/13/1999
Design & Test Technology, Inc.DTT09/30/2010
Design TechnologyLPI11/29/1996
Deterministic Networks Inc.DNI04/19/2000
Deutsche Telekom Berkom GmbHBCQ08/12/1997
Deutsche Thomson OHGDTO06/14/2007
Devolo AGDVL05/30/2002
Dextera Labs IncDXL12/09/2009
DFIDFI11/29/1996
DH PrintDHP11/29/1996
DiademDIA11/29/1996
Diagsoft IncDGS11/29/1996
Dialogue Technology CorporationDCO06/16/2004
Diamond Computer Systems IncDCS11/29/1996
Diamond Lane Comm. CorporationDLC11/29/1996
DiConDNV12/15/2004
Dictaphone CorporationDVD04/03/1998
Diebold Inc.DBD09/05/2006
Digatron Industrie Elektronik GmbHDAE02/24/1997
DIGI InternationalDGI11/29/1996
DigiBoard IncDBI11/29/1996
Digicom S.p.A.DIG11/29/1996
Digicom Systems IncDMB03/13/1998
Digicorp European sales S.A.DGP05/22/1997
Digiital Arts IncDGA06/14/2007
Digipronix Control SystemsDXC07/16/1999
Digital Acoustics CorporationDAC05/24/2000
Digital Audio Labs IncDAL11/29/1996
Digital Communications AssociationDCA11/29/1996
Digital DiscoverySHR09/24/1997
Schneider Electric Japan Holdings, Ltd.PRF01/02/2003
Digital Equipment CorporationDEC11/29/1996
Digital Processing SystemsDPS11/29/1996
Digital Projection LimitedDPL07/09/2002
DIGITAL REFLECTION INC.DRD02/21/2000
Digital Video SystemDVS11/29/1996
DigiTalk Pro AVDPA10/23/2000
Digital-Logic GmbHDLG09/02/2003
Digitan Systems IncDSI11/29/1996
Digitelec Informatique Park CaderaDLT11/29/1996
Dimension Technologies, Inc.DTE05/03/2010
Dimond Multimedia Systems IncDMM11/29/1996
Diseda S.A.DIS11/29/1996
Distributed Management Task Force, Inc. (DMTF) DMT03/31/2009
Diversified Technology, Inc.DTI11/29/1996
D-Link Systems IncABO11/29/1996
D-Link Systems IncDLK11/29/1996
DNA Enterprises, Inc.DNA09/01/1998
DO NOT USE - AUOAUO09/16/2008
DO NOT USE - LPLLPL09/16/2008
DO NOT USE - PHIPHI11/29/1996
DO NOT USE - PTWPTW09/09/2009
DO NOT USE - PVCPVC09/09/2009
DO NOT USE - RTKRTK09/09/2009
DO NOT USE - SEGSEG09/09/2009
DO NOT USE - TNJTNJ09/09/2009
DO NOT USE - UNDUND11/29/1996
DO NOT USE - UNEUNE11/29/1996
DO NOT USE - UNFUNF11/29/1996
DO NOT USE - WANWAN09/09/2009
DO NOT USE - XERXER09/09/2009
DO NOT USE - XOCXOC09/09/2009
Doble Engineering CompanyDBL11/29/1996
DocuPointDPI11/29/1996
Dolby Laboratories Inc. DLB01/27/2010
Dolman Technologies Group IncDOL11/11/1997
Domain Technology IncDSP11/29/1996
DOME imaging systemsDMS10/23/2000
Dome Imaging SystemsDOM11/29/1996
Dongguan Alllike Electronics Co., Ltd.AIK04/11/2015
Dosch & Amand GmbH & Company KGDUA12/02/1997
Dotronic Mikroelektronik GmbHDOT06/28/2002
dPict Imaging, Inc.DIM02/12/2008
DpiX, Inc.DPX09/23/1998
DPTDPT11/29/1996
Dr. Bott KGDRB04/25/2002
Dr. Neuhous Telekommunikation GmbHDNT11/29/1996
Dragon Information TechnologyDIT11/29/1996
DRS Defense Solutions, LLCDRS10/18/2011
DS Multimedia Pte LtdDSD02/14/2006
DSM Digital Services GmbHDSM11/29/1996
dSPACE GmbHDCE12/16/1996
DTC Tech CorporationDTC11/29/1996
DugoTech Co., LTDDGK06/14/2007
Dune Microsystems CorporationDMC11/29/1996
Dycam IncDYC01/08/1998
Dymo-CoStar CorporationDYM12/28/1998
Dynamic Controls LtdDCL05/24/2000
Dynax Electronics (HK) LtdDTK11/29/1996
Dynax Electronics (HK) LtdDYX11/29/1996
e.Digital CorporationEDC10/23/2000
E.E.P.D. GmbHEEP06/14/2007
Eagle TechnologyEGL11/29/1996
Eastman Kodak CompanyKOD05/24/2000
Eastman Kodak CompanyEKC11/29/1996
Easytel oyTWI07/16/1999
EBS Euchner Büro- und Schulsysteme GmbHEBS02/05/2013
Echo Speech CorporationECO11/29/1996
Eclipse Tech IncETI11/29/1996
E-Cmos Tech CorporationECM11/29/1996
Eden Sistemas de Computacao S/AESC11/29/1996
Edimax Tech. Company LtdEDI11/29/1996
EDMIEDM07/16/1998
Edsun LaboratoriesELI11/29/1996
EE Solutions, Inc.EES04/16/2003
EEH Datalink GmbHEEH07/03/1997
Efficient NetworksENI11/29/1996
Egenera, Inc.EGN10/08/2002
Eicon Technology CorporationEIC11/29/1996
EIZO GmbH Display Technologies EGD02/13/2009
Eizo Nanao CorporationENC12/28/1998
EKSEN YAZILIMEKS04/25/2002
ELAD srlELA04/25/2002
ELAN MICROELECTRONICS CORPORATIONETD11/03/2009
ELAN MICROELECTRONICS CORPORATIONTSH11/14/2014
Elbit Systems of AmericaESA06/15/2009
ELCON Systemtechnik GmbHESG07/16/1999
ELEA CardWareLXS06/25/1998
Elecom Company LtdECP11/29/1996
Elecom Company LtdELE11/29/1996
Electro Cam Corp.ECA08/10/2000
Electro Scientific IndELC11/29/1996
Electronic MeasurementsMMM11/29/1996
Electronic Trade Solutions LtdETS08/20/2002
Electronic-Design GmbHEDG08/12/1997
Electrosonic LtdELL09/13/1999
Element Labs, Inc.ELT10/11/2007
Elgato Systems LLCEGA02/08/2011
Elitegroup Computer Systems Company LtdECS11/29/1996
Elitegroup Computer Systems Company LtdUEG11/29/1996
Elmeg GmbH KommunikationstechnikELG11/29/1996
Elmic Systems IncELM11/29/1996
ELMO COMPANY, LIMITEDEMO06/26/2012
Elo TouchSystems IncELO11/29/1996
Elonex PLCELX11/29/1996
El-PUSK Co., Ltd.LPE08/14/2001
ELSA GmbHELS11/29/1996
ELTEC Elektronik AGEAG11/25/2014
Embedded computing inc ltdEMB02/25/2002
Embedded Solution TechnologyEST05/24/2000
Embrionix Design Inc.EMD07/24/2013
Emcore CorporationEMK05/31/2012
Emerging Display Technologies CorpEDT08/18/2009
EMG Consultants IncEMG11/29/1996
EMiNE TECHNOLOGY COMPANY, LTD.EME06/16/2005
EmpacEPC12/04/1996
Emulex CorporationEMU11/29/1996
Enciris TechnologiesECI11/01/2008
Enciris Technologies ECT11/01/2008
ENE Technology Inc.ENE03/15/2001
e-Net IncDTL10/16/1997
EnhansoftEHN11/16/2010
ENIDAN Technologies LtdEND04/19/2000
Ensemble Designs, IncESD12/09/2009
Ensoniq CorporationENS11/29/1996
Enterprise Comm. & Computing IncENT11/29/1996
Envision Peripherals, IncEPI02/22/1999
Eon Instrumentation, Inc. EON01/15/2015
EPiCON Inc.EPN09/23/1998
Epiphan Systems Inc. EPH 03/14/2011
Epson ResearchEHJ11/29/1996
Equinox Systems IncEQX11/29/1996
Equipe Electronics Ltd.EQP07/14/2005
Ergo ElectronicsEGO11/29/1996
Ergo SystemERG11/29/1996
Ericsson Mobile Communications ABERI10/22/1997
Ericsson Mobile Networks B.V.EUT04/14/1998
Ericsson, Inc.ERN09/23/1998
ES&SESK11/08/1999
eSATURNUSESN02/21/2012
Escort Insturments CorporationERT05/02/1997
ESS Technology IncESS11/29/1996
ESSential Comm. CorporationECC11/29/1996
Esterline TechnologiesESL01/06/2012
Esterline Belgium BVBAESB01/15/2015
E-Systems IncESY11/29/1996
ET&T Technology Company LtdEEE05/04/1998
E-Tech IncETT11/29/1996
eTEK Labs Inc.ETK07/16/1998
Etherboot ProjectETH07/09/2010
Eugene Chukhlomin Sole Proprietorship, d.b.a. ECK05/03/2008
Euraplan GmbHERP11/29/1996
Evans and Sutherland ComputerEAS01/28/2003
EverexEVX11/29/1996
Everton Technology Company LtdETC04/10/1997
Evertz Microsystems Ltd.ETL06/14/2007
eviateg GmbHEVI02/21/2000
Ex Machina IncEMI11/29/1996
Exacom SAYHW11/29/1996
Exatech Computadores & Servicos LtdaEXT09/23/1998
Excel Company LtdECL05/27/1997
Excession AudioEXC11/06/1998
EXFO Electro Optical EngineeringXFO04/29/1998
Exide ElectronicsEXI11/29/1996
Extended Systems, Inc.ESI07/16/1999
Exterity LtdEXY02/12/2009
Extraordinary Technologies PTY LimitedCRO04/11/2005
Exxact GmbHEXX11/29/1996
eyefactive GmbhEYF07/07/2015
eyevis GmbHEYE11/18/2011
EzE TechnologiesEZE02/21/2005
F.J. Tieman BVFJT06/25/1998
Fairfield IndustriesFFI11/29/1996
Fantalooks Co., Ltd.FAN03/12/2014
Fanuc LTDFNC01/29/1997
Farallon ComputingFAR11/29/1996
FARO TechnologiesFRO09/21/2012
Faroudja LaboratoriesFLI06/02/2004
Fast Multimedia AGFMA11/29/1996
FastPoint Technologies, Inc.FTI06/21/2001
Feature Integration Technology Inc.FIT08/11/2009
Fellowes & QuestecFEL11/29/1996
Fellowes, Inc.FMI07/05/2001
Fen Systems Ltd.FEN05/04/2010
Ferranti Int'LFER11/29/1996
Ferrari Electronic GmbHTLA12/04/1996
FHLPFHL11/29/1996
Fibernet Research IncFRI11/29/1996
Finecom Co., Ltd.FIN11/27/1998
Fingerprint Cards ABFPC06/14/2013
First Industrial Computer IncPCG11/29/1996
First International Computer IncLEO09/19/1997
First International Computer LtdFCG04/10/1997
First Virtual CorporationFVC11/29/1996
Flat Connections IncFWR11/29/1996
FlightSafety InternationalSSD08/10/2000
FLY-IT SimulatorsFIS09/08/1997
FocalTech Systems Co., Ltd.FTS07/23/2013
Focus Enhancements, Inc.FCS12/12/2002
Fokus Technologies GmbHFOK10/22/2013
FOR-A Company LimitedFOA12/06/2008
Force ComputersFRC11/29/1996
Ford Microelectronics IncFMC03/11/1997
Fore Systems IncFSI11/29/1996
Forefront Int'l LtdFIL11/29/1996
Formosa Industrial Computing IncFIC11/29/1996
Formoza-AltairFMZ04/25/2003
Forth Dimension Displays LtdFDD07/07/2015
Forvus Research IncFRE04/24/1997
Foss TecatorFOS10/22/1997
Founder Group Shenzhen Co.FZC11/08/1999
Fountain Technologies IncFTN11/29/1996
Fraunhofer Heinrich-Hertz-InstituteHHI07/27/2012
Freedom Scientific BLVFRD06/15/2007
FREEMARS Heavy IndustriesTCX03/15/2001
Frontline Test Equipment Inc.FTE01/20/1999
FTG Data SystemsFTG11/29/1996
Fuji XeroxFXX11/29/1996
FUJIFILM CorporationFFC08/22/2011
Fujitsu Display Technologies Corp.FDT10/23/2002
Fujitsu General Limited.FGL02/21/2000
Fujitsu LtdFUJ11/29/1996
Fujitsu Microelect LtdFML11/29/1996
Fujitsu Peripherals LtdFPE08/19/1997
Fujitsu Siemens Computers GmbHFUS01/13/2000
Fujitsu SpainFJS11/29/1996
Fujitsu Takamisawa Component LimitedFJC05/16/1999
FUJITSU TEN LIMITEDFTL12/20/2011
Funai Electric Co., Ltd.FNI01/18/2005
Furukawa Electric Company LtdFCB11/29/1996
FURUNO ELECTRIC CO., LTD.FEC11/29/1996
Future Designs, Inc.FDI09/29/2014
Future DomainFDC11/29/1996
Future Systems Consulting KKFSC11/29/1996
Futuretouch CorporationFTC11/29/1996
FZI Forschungszentrum InformatikFZI08/12/1997
G&W Instruments GmbHSPH02/25/2002
G. Diehl ISDN GmbHGDI11/29/1996
Gadget Labs LLCGLS11/29/1996
Gage Applied Sciences IncGAG11/29/1996
GAI-Tronics, A Hubbell CompanyHUB03/26/2009
Galil Motion ControlGAL11/29/1996
Garmin InternationalGRM12/09/2011
Garnet System Company LtdGTM11/29/1996
Gateway 2000GWY11/29/1996
Gateway Comm. IncGCI11/29/1996
Gateworks CorporationGWK07/31/2013
Gaudi Co., Ltd.GAU03/31/2003
GCC Technologies IncGCC06/05/1997
GDSGDS06/23/2004
GE Fanuc Embedded SystemsGEF06/14/2007
Abaco Systems, Inc.GEH09/03/2010
Gefen Inc.GFN10/11/2007
Gem PlusGEM02/27/1998
GEMINI 2000 LtdGMN10/23/2000
General DatacomGDC11/29/1996
General Dynamics C4 SystemsGED01/09/2013
General Information SystemsGML01/13/2000
General Inst. CorporationGIC11/29/1996
General Standards CorporationGSC07/16/1998
General Touch Technology Co., Ltd.GTT11/21/2002
Genesys ATE IncGEN11/29/1996
Genesys LogicGLM11/08/1999
Gennum CorporationGND09/05/2006
GEO SenseGEO11/29/1996
Geotest Marvin Test Systems IncGTS02/24/1998
GERMANEERS GmbHGER12/20/2011
GES Singapore Pte LtdGES03/15/2001
Getac Technology CorporationGET05/11/2010
GFMesstechnik GmbHGFM03/15/2001
GI Provision LtdGIP02/08/2012
Global Data SAPST11/29/1996
Global Village CommunicationGVL11/29/1996
GMK Electronic Design GmbHGMK01/18/2008
GMM Research IncGMM11/29/1996
GMX IncGMX11/29/1996
GN Nettest IncGNN07/30/1997
GOEPEL electronic GmbHGOE06/24/2013
Goldmund - Digital Audio SAGLD02/06/2012
GOLD RAIN ENTERPRISES CORP.GRE06/04/2003
Goldstar Company LtdGSM11/29/1996
GoldtouchGTI08/06/1997
Google Inc.GGL05/26/2010
GoPro, Inc.GPR01/15/2015
Granch LtdGRH09/23/2002
Grand Junction NetworksGJN11/29/1996
Grandstream Networks, Inc.GSN03/03/2014
Graphic SystemTechnologyGST11/29/1996
Graphica ComputerGRA11/29/1996
Graphtec CorporationGTC11/29/1996
Grass Valley Germany GmbHTGV06/14/2007
Grey Cell Systems LtdGCS04/29/1997
Grossenbacher Systeme AGGSY04/19/2000
G-Tech CorporationGTK11/29/1996
Guillemont InternationalGIM10/29/1997
GUNZE LimitedGZE05/02/2005
Gunze LtdGNZ11/29/1996
Guntermann & Drunck GmbHGUD03/10/2003
Guzik Technical EnterprisesGUZ11/29/1996
GVC CorporationGVC11/29/1996
H.P.R. Electronics GmbHHPR08/29/2007
Hagiwara Sys-Com Company LtdHSC11/29/1996
GW InstrumentsGWI11/29/1996
Haider electronicsHAE07/05/2001
Haivision Systems Inc.HAI11/15/2007
HalberthalHAL02/10/1998
Hall ResearchHRI05/10/2012
HAMAMATSU PHOTONICS K.K.HPK12/20/2006
Hampshire Company, Inc.HTI01/20/1999
Hanchang System CorporationHAN06/21/2003
HannStar Display CorpHSD08/11/2009
HannStar Display CorpHSP08/11/2009
HardCom Elektronik & DatateknikHDC04/14/1998
Harman International Industries, IncHII01/09/2015
Harris & Jeffries IncHJI11/29/1996
Harris Canada IncHWA03/13/1998
Harris CorporationHAR12/20/2011
Harris SemiconductorHRS01/02/1997
Hauppauge Computer Works IncHCW11/29/1996
Hayes Microcomputer Products IncHAY11/29/1996
HCL America IncHCL11/29/1996
HCL PeripheralsHCM10/02/2001
HD-INFO d.o.o.HDI10/08/2001
Headplay, Inc.HPI04/30/2007
Heng Yu Technology (HK) LimitedHYT10/23/2000
HerculesHRC03/15/2001
HERCULESHRT03/15/2001
HETEC Datensysteme GmbHHET02/03/2004
Hewlett PackardHWP03/15/2001
Hewlett PackardHPD05/02/1997
Hewlett-Packard Co.HPC08/10/2000
Hewlett-Packard Co.HPQ07/12/2004
Hexium Ltd.HXM04/15/2008
Hibino CorporationHIB07/09/2003
Highwater Designs LtdHWD11/29/1996
Hikom Co., Ltd.HIK10/13/2003
Hilevel TechnologyHIL11/29/1996
HIRAKAWA HEWTECH CORP. HHC05/20/2008
Hitachi America LtdHIT11/29/1996
Hitachi Consumer Electronics Co., LtdHCE05/15/2009
Hitachi Information Technology Co., Ltd.HIC04/19/2000
Hitachi LtdHTC11/29/1996
Hitachi Maxell, Ltd.MXL01/13/2000
Hitachi Micro Systems Europe LtdHEL07/09/1997
Hitex Systementwicklung GmbHHTX01/30/1998
hmk Daten-System-Technik BmbHHMK09/30/1997
HOB Electronic GmbHHOB11/29/1996
Holoeye Photonics AGHOL02/02/2005
Holografika kft.HDV03/31/2005
Holtek Microelectronics IncHTK11/29/1996
Home Row IncINC11/29/1996
HON HAI PRECISON IND.CO.,LTD.FOX08/02/2010
HONKO MFG. CO., LTD.HKA12/01/2004
Hope Industrial Systems, Inc.HIS01/13/2014
Horner Electric IncAPG11/29/1996
Horsent Technology Co., Ltd.HST04/11/2015
Hosiden CorporationHOE08/05/1997
HTBLuVA MödlingHTL02/17/2014
Hualon Microelectric CorporationHMC11/29/1996
HUALONG TECHNOLOGY CO., LTDEBT06/15/2007
Hughes Network SystemsHNS11/29/1996
HUMAX Co., Ltd.HMX02/14/2006
HYC CO., LTD.HYO04/12/2006
Hydis Technologies.Co.,LTDHYD11/22/2010
Hynix SemiconductorHYV11/29/2008
Hypercope Gmbh AachenHYC12/01/1997
Hypertec Pty LtdHYR11/29/1996
Hyphen LtdHYP11/29/1996
I&T Telecom.ITT11/08/1999
I/OTech IncIOT11/29/1996
IAT Germany GmbHIAT11/29/1996
IBM BrasilIBM11/29/1996
IBM CorporationCDT11/29/1996
IBP Instruments GmbHIBP09/23/1998
IBR GmbHIBR01/16/1998
IC EnsembleICE09/19/1997
ICA IncICA05/20/2002
ICCC A/SICX11/29/1996
ICD IncICD06/09/1997
ICET S.p.A.ARE05/16/1999
ICP Electronics, Inc./iEi Technology Corp.ICP09/07/2012
ICSLIUC08/14/1997
Icuiti CorporationXTD06/14/2007
Icuiti CorporationIWR03/06/2007
Id3 SemiconductorsISC03/15/2001
IDE AssociatesIDE11/29/1996
IDEO Product DevelopmentIDO09/30/1997
idex displaysDEX04/25/2002
IDEXX LabsIDX11/29/1996
IDK CorporationIDK04/16/2003
Idneo TechnologiesIDN07/05/2012
IDTECHITS06/17/2002
IEEIEE06/21/2001
IGM CommuniIGM11/29/1996
IINFRA Co., LtdIIN05/09/2003
Iiyama North AmericaIVM11/29/1996
Ikegami Tsushinki Co. Ltd. IKE11/14/2014
Ikos Systems IncIKS11/29/1996
ILCIND06/16/2004
Image Logic CorporationILC11/29/1996
Image Stream MedicalISM05/27/2010
IMAGENICS Co., Ltd.IMG09/05/2006
IMAGEQUEST Co., LtdIQT10/08/2002
ImagraphIME12/04/1996
ImagraphIMA11/29/1996
ImasDe Canarias S.A.IMD07/03/1997
IMC NetworksIMC11/29/1996
Immersion CorporationIMM07/16/1997
IMP Electronics Ltd.HUM06/16/2004
ImpinjIMP08/14/2012
Impossible ProductionIMN08/10/2000
In Focus Systems IncIFS11/29/1996
In4S IncALD12/05/1997
INBINE.CO.LTDIBI11/06/2001
Indtek Co., Ltd.INK03/26/2007
IneoQuest Technologies, IncIQI02/18/2011
Industrial Products Design, Inc.IPD07/16/1999
Ines GmbHINS11/29/1996
Infineon Technologies AGIFX04/19/2000
Infinite ZIFZ01/04/2012
Informatik Information TechnologiesIIT08/14/2013
InformtechIFT11/29/1996
Infotek Communication IncICI11/29/1996
Infotronic America, Inc.ITR06/21/2001
Inframetrics IncINF11/29/1996
Ingram MacrotronVSN08/10/2000
Ingram Macrotron GermanyVID05/24/2000
InHand ElectronicsIHE04/20/2010
Initio CorporationINI11/29/1996
Inmax Technology CorporationIMT02/12/2003
Innolab Pte LtdINO01/20/1999
InnoLux Display CorporationINL12/15/2004
InnoMedia IncINM11/29/1996
Innotech CorporationILS10/23/2000
Innovate LtdATE11/29/1996
Innovent Systems, Inc.INN04/19/2000
Innoware IncWII01/30/1998
Inovatec S.p.A.inu03/15/2001
Inside ContactlessICV11/04/2010
Inside Out NetworksION12/28/1998
Insignia Solutions IncISG11/29/1996
INSIS Co., LTD.ISR02/12/2003
Institut f r angewandte Funksystemtechnik GmbHIAF03/20/1999
Integraph CorporationING11/29/1996
Integrated Business SystemsIBC11/29/1996
Integrated Device Technology, Inc.IDP01/27/2010
Integrated Tech Express IncITE11/29/1996
Integrated Tech Express IncSRC11/29/1996
integrated Technology Express IncITX06/25/1997
Integration Associates, Inc.IAI03/17/2004
Intel CorpICO08/10/2000
Intelligent InstrumentationIII11/29/1996
Intelligent Platform Management Interface (IPMI) forum (Intel, HP, NEC, Dell)IPI05/24/2000
Intelliworxx, Inc.IWX05/16/1999
Intellix Corp.SVC01/18/2008
Interaction Systems, IncTCH03/20/1999
Interactive Computer Products IncPEN01/15/1997
Intercom IncITC11/29/1996
Interdigital Sistemas de InformacaoIDS10/28/1997
Interface CorporationFBI11/29/1996
Interface SolutionsISI11/29/1996
Intergate Pty LtdIGC11/29/1996
Interlace Engineering CorporationIEC11/29/1996
Interlink ElectronicsIEI10/16/1998
International Datacasting CorporationIDC02/25/1997
International Display TechnologyIDT05/16/2002
International Integrated Systems,Inc.(IISI)ISY08/10/2000
International Microsystems IncIMI11/29/1996
International Power TechnologiesIPT04/11/1997
Internet Technology CorporationITD12/05/1997
Interphase CorporationINP11/29/1996
Interphase CorporationINT11/29/1996
Intersil CorporationLSD03/14/2012
Intersolve TechnologiesIST03/20/1999
Inter-TelITL03/21/1997
Intertex Data ABIXD11/29/1996
Intervoice IncIVI11/29/1996
Intevac Photonics Inc.IVS02/16/2011
Intracom SAICM08/03/1998
Intrada-SDD LtdSDD11/21/2007
IntreSource Systems Pte LtdISP08/27/1997
Intuitive Surgical, Inc.SRG02/16/2006
Inventec CorporationINA09/13/2013
Inventec Electronics (M) Sdn. Bhd.INE07/21/1998
Inviso, Inc.INV10/23/2000
I-O Data Device IncIOD11/29/1996
i-O Display SystemIOS03/15/2001
IomegaIOM11/29/1996
IP Power Technologies GmbH IPP12/06/2010
IP3 Technology Ltd.IPQ11/11/2013
IPC CorporationIPC11/29/1996
IPM Industria Politecnica Meridionale SpAIPM09/23/1998
IPS, Inc. (Intellectual Property Solutions, Inc.)IPS09/05/2001
IPWireless, IncIPW03/15/2001
ISIC Innoscan Industrial Computers A/SIIC07/23/2003
Isolation SystemsISL11/29/1996
ISS IncISS11/29/1996
Itausa Export North AmericaITA11/29/1996
Ithaca PeripheralsIPR07/01/1997
ITK Telekommunikation AGITK11/29/1996
ITM inc.ITM04/24/2001
IT-PRO Consulting und Systemhaus GmbHITP10/23/2000
Jace Tech IncJCE11/29/1996
Jaeik Information & Communication Co., Ltd.JIC10/23/2000
Jan Strapko - FOTOXFG05/07/2001
Janich & Klass Computertechnik GmbHJUK10/08/2002
Janz Automationssysteme AGJAS11/03/2009
Japan Aviation Electronics Industry, LimitedJAE03/15/2001
Japan Digital Laboratory Co.,Ltd.JDL04/19/2000
Japan Display Inc.JDI04/18/2013
Jaton CorporationJAT09/24/1997
JET POWER TECHNOLOGY CO., LTD.JET03/15/2001
Jetway Information Co., LtdJWY09/22/2003
jetway security micro,incJTY11/11/2009
Jiangsu Shinco Electronic Group Co., LtdSHI08/10/2004
Jones Futurex IncJFX11/29/1996
Jongshine Tech IncLTI11/29/1996
Josef Heim KGHKG11/29/1996
JPC Technology LimitedJPC10/23/2000
JS DigiTech, IncJSD10/23/2000
JS MotorsportsJTS12/05/1997
JunnilaTPJ03/15/2001
Jupiter SystemsJUP09/05/2006
Jupiter Systems, Inc.JSI06/14/2007
JVCJVC10/23/2000
JVC KENWOOD CorporationJKC03/08/2012
JWSpencer & Co.JWS07/16/1999
Kansai Electric Company LtdSGE12/04/1996
Kaohsiung Opto Electronics Americas, Inc.HIQ03/14/2012
Karn Solutions Ltd.KSL05/08/2006
KarnaKAR02/21/2000
Katron Tech IncKTN11/29/1996
Kayser-Threde GmbHKTG11/29/1996
KDDI Technology CorporationKDT05/22/2012
KDEKDE08/14/2001
KDS USAKDS11/29/1996
KEISOKU GIKEN Co.,Ltd.KGL04/17/2012
Kensington Microware LtdKML11/29/1996
Kenwood CorporationKWD02/22/2008
KEPSEPS11/29/1996
Kesa CorporationKES11/29/1996
Key Tech IncKEY11/29/1996
Key Tronic CorporationKTK11/29/1996
Keycorp LtdKCL05/20/1997
KeyViewKVX08/13/2012
Kidboard IncKBI04/24/1997
KIMIN Electronics Co., Ltd.KME02/15/2011
Kinetic Systems CorporationKSC11/29/1996
King Phoenix CompanyKPC11/29/1996
King Tester CorporationKSX07/16/1998
Kingston Tech CorporationKTC11/29/1996
Kionix, Inc.KIO12/23/2013
KiSS Technology A/SKIS06/16/2005
Klos Technologies, Inc.PVP08/10/2000
Kobil Systems GmbHKBL03/15/2001
Kobil Systems GmbHKOB03/15/2001
Kodiak TechKDK11/29/1996
Kofax Image ProductsKFX11/29/1996
Kollmorgen Motion Technologies GroupKOL11/29/1996
KOLTER ELECTRONICKOE03/15/2001
Komatsu Forest KFE 04/20/2010
Konica corporationKNC08/05/1997
Konica Technical IncKTI11/29/1996
Kontron ElectronikTWE11/29/1996
Kontron Embedded Modules GmbHKEM08/29/2007
Kontron Europe GmbHKEU02/20/2014
Korea Data Systems Co., Ltd.KDM12/18/2003
KOUZIRO Co.,Ltd.KOU07/27/2012
KOWA Company,LTD. KOW03/12/2008
Kramer Electronics Ltd. InternationalKMR07/10/2013
Krell Industries Inc.KRL08/03/2004
Kroma TelecomKRM05/05/2010
Kroy LLCKRY07/16/1998
K-TechKTE03/31/2003
KUPA China Shenzhen Micro Technology Co., Ltd. Gold InstituteKSG04/22/2014
Kurta CorporationKUR11/29/1996
Kvaser ABKVA01/24/1997
KYE Syst CorporationKYE11/29/1996
Kyocera CorporationKYC11/29/1996
Kyushu Electronics Systems IncKEC01/12/1998
K-Zone InternationalKZN06/21/2001
K-Zone International co. Ltd.KZI08/10/2000
L-3 CommunicationsLLL05/11/2010
La Commande ElectroniqueLCE11/29/1996
Labcal TechnologiesLCT11/08/1999
Labtec IncLTC12/08/1997
Labway CorporationLWC12/04/1996
LaCieLAC12/28/1998
Laguna SystemsLAG11/29/1996
Land Computer Company LtdLND11/29/1996
LANETCO InternationalLNT05/02/2003
Lanier WorldwideLWW11/29/1996
Lars Haagh ApSLHA01/09/1997
LASAT Comm. A/SLAS11/29/1996
Laser MasterLMT11/29/1996
Laserdyne TechnologiesLDN10/16/2013
Lasergraphics, Inc.LGX02/21/2000
Latitude Comm.LCM11/29/1996
Lava Computer MFG IncLAV04/14/1997
LCILCC08/10/2000
Lectron Company LtdLEC03/27/1997
Leda Media ProductsLMP05/11/1998
Legerity, IncLEG01/18/2005
Leitch Technology International Inc.LTV12/09/2003
LenovoLNV07/14/2005
Lenovo Beijing Co. Ltd.LIN05/22/2012
Lenovo Group LimitedLEN06/03/2005
Lexical LtdLEX11/29/1996
LEXICONLCN03/01/2005
Leutron VisionPRS11/29/1996
Lexmark Int'l IncLMI11/29/1996
LG Semicom Company LtdLGS11/29/1996
LGICMAN02/21/2000
LifeSize CommunicationsLSC02/14/2006
Lighthouse Technologies LimitedLHT05/04/2010
Lightware Visual EngineeringLWR02/04/2009
Lightware, IncLTW10/16/1998
Lightwell Company LtdLZX12/02/1997
Likom Technology Sdn. Bhd.LKM04/23/1998
Linear Systems Ltd.LNR10/11/2007
Link Tech IncLNK11/29/1996
Linked IP GmbHLIP07/19/2010
Lisa Draexlmaier GmbHFGD02/22/1999
Litelogic Operations LtdLOL12/09/2011
Lite-On Communication IncLCI11/29/1996
Lithics Silicon TechnologyLIT03/15/2001
Litronic IncLTN02/03/1998
Locamation B.V.LOC01/09/2004
Loewe Opta GmbHLOE05/02/2005
Logic LtdLGC04/02/1994
Logical SolutionsLSL11/29/1996
Logicode Technology IncLOG11/29/1996
Logitech IncLGI11/29/1996
LogiDataTech Electronic GmbHLDT03/15/2001
Logos Design A/SSGO04/24/2001
Long Engineering Design IncLED11/29/1996
Longshine Electronics CompanyLCS11/29/1996
Loughborough Sound ImagesLSI11/29/1996
LSI Japan Company LtdLSJ11/29/1996
LSI Systems IncLSY11/29/1996
LTS Scale LLCLTS11/15/2007
LubosoftLBO04/24/2001
Lucent TechnologiesLUC04/19/2000
Lucent TechnologiesLMG01/13/1997
Lucidity Technology Company LtdLTK05/18/1998
Lumagen, Inc.LUM08/12/2004
Lung Hwa Electronics Company LtdLHE06/12/1998
LuxeonLXN03/15/2001
Luxxell Research IncLUX06/09/1997
LVI Low Vision International ABLVI01/21/2011
LXCO Technologies AGLXC01/11/2012
MAC System Company LtdMAC09/26/1997
Mac-Eight Co., LTD.MEJ01/19/2011
Macraigor Systems IncOCD03/23/1998
Macrocad Development Inc.VHI04/19/2000
Macronix IncMXI11/29/1996
Madge NetworksMDG11/29/1996
Maestro Pty LtdMAE12/04/1996
MAG InnoVisionMAG11/29/1996
Magic LeapMLP11/14/2014
Magni Systems IncMCP11/29/1996
MagTek Inc.EKA02/14/2006
Magus Data TechMDT11/29/1996
Mainpine LimitedMPN06/30/2007
Mainpine LimitedMUK09/13/1999
Many CNC System Co., Ltd.PAK03/12/2004
Maple Research Inst. Company LtdMPL11/29/1996
MARANTZ JAPAN, INC.MJI10/23/2000
Marconi Instruments LtdMIL11/29/1996
Marconi Simulation & Ty-Coch Way TrainingMRC11/29/1996
Marina CommunicaitonsMCR11/29/1996
Mark LevinsonMLN02/28/2005
Mark of the Unicorn IncMTU03/21/1997
Marseille, Inc.MNI02/27/2013
Marshall ElectronicsMBM03/13/2006
Mars-Tech CorporationMTC11/29/1996
Maruko & Company LtdMRK11/29/1996
MASPRO DENKOH Corp.MSR10/25/2012
Mass Inc.MAS02/25/2002
Matelect Ltd.MEQ05/30/2002
MatroxMTX11/29/1996
Mat's ComputersMCQ07/22/2004
Matsushita Communication Industrial Co., Ltd.WPA03/15/2001
Matsushita Electric Ind. Company LtdMAT11/29/1996
MaxCom Technical IncMTI11/29/1996
MaxData Computer AGVOB02/21/2000
MaxData Computer GmbH & Co.KGMXD04/19/2000
Maxpeed CorporationMXP02/19/1997
Maxtech CorporationMXT11/29/1996
MaxVision CorporationMXV07/16/1999
Maygay Machines, LtdDJP08/10/2000
Maynard ElectronicsMAY11/29/1996
MAZeT GmbHMAZ08/11/1998
MBCMBC11/29/1996
McDATA CorporationMCD11/29/1996
McIntosh Laboratory Inc.MLI01/18/2008
MCM Industrial Technology GmbHMIT10/29/2004
MEC Electronics GmbHCEM04/19/2000
Medar IncMDR12/11/1996
Media Technologies Ltd.MTB01/05/2009
Media Tek Inc.MKC06/14/2007
Media Vision IncMVI11/29/1996
Media4 IncMDA03/20/1997
Mediacom Technologies Pte LtdOWL11/29/1996
Mediaedge CorporationMEK11/19/2013
MediaFire Corp.MFR12/28/1998
MediasonicFTR11/29/1996
MediaTec GmbHMTE12/13/1996
Mediatek CorporationMDK03/13/1997
Mediatrix Peripherals IncMPI04/24/1997
Medikro OyMRO09/19/1997
Mega System Technologies IncMEC12/29/1997
Mega System Technologies, Inc.MGA12/28/1998
Megasoft IncMSK11/29/1996
Megatech R & D CompanyMGT11/29/1996
Meld TechnologyMEP08/16/2012
MEN Mikroelectronik Nueruberg GmbHMEN05/23/1997
Mentor Graphics CorporationMGC07/30/2009
MEPCORLD03/15/2001
MEPhIPPD11/27/1998
Merging TechnologiesMRT11/29/1996
Meridian Audio LtdMAL02/04/2009
Messeltronik Dresden GmbHMED11/29/1996
MET Development IncMDV11/29/1996
Meta Watch LtdMTA08/29/2013
Metheus CorporationMET11/29/1996
Metricom IncMCM11/29/1996
Metronics IncQCH11/29/1996
Mettler ToledoNET11/29/1996
Metz-Werke GmbH & Co KGMCE06/30/2005
M-G Technology LtdMGL10/29/1997
Micom Communications IncMIC05/05/1997
Micomsoft Co., Ltd.MSX04/10/2008
Micro Computer SystemsMCS11/29/1996
Micro Design IncMDI01/20/1998
Micro Display Systems IncMDS11/29/1996
Micro FirmwareMFI12/30/1997
Micro IndustriesMCC04/21/2003
Micro Solutions, Inc.BPD04/19/2000
Micro Systemation ABMSA11/08/1999
Micro Technical Company LtdJMT11/29/1996
Microbus PLCMBD08/13/2002
MicrocomMNP11/29/1996
MicroDatec GmbHMDX09/13/1999
MicroDisplay CorporationMRD06/14/2007
Microdyne IncMDY12/18/1996
MicroField Graphics IncMFG11/29/1996
MicrolabMPJ05/23/1997
MicrolineLAF09/13/1999
Micrologica AGMLG10/06/1998
Micromed Biotecnologia LtdMMD12/11/1996
Micromedia AGMMA04/24/1997
Micron Electronics IncMCN02/20/1997
Micronics ComputersMCI11/29/1996
micronpc.comMIP08/10/2000
Micronyx IncMYX11/29/1996
Micropix Technologies, Ltd.MPX10/08/2001
MicroSlate Inc.MSL05/16/1999
MicrosoftPNP03/05/2004
MicrosoftMSH11/29/1996
MicrosoftPNG11/29/1996
MicroSoftWareWBN01/14/1998
MicrostepMSI11/29/1996
MicrotecMCT11/29/1996
Micro-Tech Hearing InstrumentsMTH12/15/1997
MICROTEK Inc.MKT07/14/2005
Microtek International Inc.MTK02/25/2002
MicroTouch Systems IncMSY08/10/2000
MicrovisionMVS02/13/2009
Microvitec PLCMVD11/29/1996
Microway IncMWY11/29/1996
Midori ElectronicsMDC11/29/1996
Mikroforum Ring 3SFT11/02/2004
Milestone EPEMLS08/11/1998
Millennium Engineering IncMLM11/29/1996
Millogic Ltd.MLL01/09/2014
Millson Custom Solutions Inc.MCX10/17/2013
Miltope CorporationVTM09/23/2009
Mimio – A Newell Rubbermaid CompanyMIM07/31/2012
MindTech Display Co. LtdMTD06/14/2007
MindTribe Product Engineering, Inc.FTW02/14/2011
Mini Micro Methods LtdMNC11/29/1996
Minicom Digital SignageMIN08/13/2010
MiniMan IncMMN11/29/1996
Minnesota Mining and ManufacturingMMF03/15/2001
Miranda Technologies IncMRA11/29/1996
MiratelMRL10/16/1998
Miro Computer Prod.MIR11/29/1996
miro DisplaysMID03/20/1999
Mistral Solutions [P] Ltd.MSP09/23/1998
Mitec IncMII11/29/1996
Mitel CorporationMTL08/01/1997
Mitron computer IncMTR11/29/1996
Mitsubishi Electric CorporationMEL11/29/1996
Mitsubishi Electric Engineering Co., Ltd.MEE10/03/2005
Mitsumi Company LtdKMC11/29/1996
MJS DesignsMJS11/29/1996
MK Seiko Co., Ltd.MKS06/18/2013
M-Labs LimitedOHW11/27/2013
MMS ElectronicsMMS02/24/1998
Modesto PC IncFST02/27/1997
MODISMDD11/08/1999
Modular Industrial Solutions IncMIS11/29/1996
Modular TechnologyMOD06/09/1997
Momentum Data SystemsMOM01/18/2008
Monorail IncMNL02/18/1997
MonydataMYA11/29/1996
Moreton BayMBV01/13/2000
Moses CorporationMOS11/29/1996
Mosgi CorporationMSV11/29/1996
Motion Computing Inc.MCO05/30/2002
MotiumMTM06/19/2012
motorolaMSU03/15/2001
Motorola Communications IsraelMCL07/02/2002
Motorola Computer GroupMCG08/14/1997
Motorola UDSMOT11/29/1996
Mouse Systems CorporationMSC11/29/1996
M-Pact IncMPC11/29/1996
mps Software GmbHMPS11/29/1996
MS TelematicaMST04/28/1997
MSC Vertriebs GmbHMEX06/04/2012
MSI GmbHMSG09/13/1999
M-Systems Flash Disk PioneersMSF12/17/1997
Mtron Storage Technology Co., Ltd.MTN06/17/2008
Multi-Dimension InstituteMUD10/23/2000
MultimaxMMI11/29/1996
Multi-Tech SystemsMTS11/29/1996
Multiwave Innovation Pte LtdMWI11/29/1996
Mutoh America IncMAI09/13/1999
mwareMWR04/24/2001
Mylex CorporationMLX11/29/1996
Myriad Solutions LtdMYR11/29/1996
Myse TechnologyWYS11/29/1996
N*Able Technologies IncNBL04/28/1998
NAD ElectronicsNAD06/14/2007
Naitoh Densei CO., LTD.NDK04/12/2006
Najing CEC Panda FPD Technology CO. ltdNCP02/24/2015
Nakano Engineering Co.,Ltd.NAK07/22/2009
Nakayo Relecommunications, Inc.NYC08/10/2000
Nanomach AnstaltSCS11/29/1996
Nasa Ames Research CenterADR11/29/1996
National DataComm CorporaitonNDC11/29/1996
National Display SystemsNDI08/08/2003
National Instruments CorporationNIC11/29/1996
National Key Lab. on ISNNBS07/16/1998
National Semiconductor CorporationNSC11/29/1996
National Semiconductor Japan LtdTTB04/14/1997
National Transcomm. LtdNTL11/29/1996
Nationz Technologies Inc.ZIC03/12/2009
Natural Micro SystemNMS11/29/1996
NaturalPoint Inc.NAT09/03/2010
Navatek Engineering CorporationNVT03/02/1998
Navico, Inc.NME11/28/2012
Navigation CorporationNAV02/22/1999
Naxos TecnologiaNAX12/12/1997
NCR CorporationDUN04/25/2002
NCR CorporationNCC11/29/1996
NCR ElectronicsNCR11/29/1996
NDF Special Light Products B.V.NDF09/18/2014
NDS LtdDMV06/25/1997
NEC CorporationNEC05/24/2000
NEC CustomTechnica, Ltd.NCT10/23/2002
NEC-Mitsubishi Electric Visual Systems CorporationNMV02/25/2002
NEO TELECOM CO.,LTD.NEO11/08/1999
NeomagicNMX11/29/1996
NeoTech S.R.LNTC11/11/1997
Netaccess IncNTX02/07/1997
NetComm LtdNCL11/29/1996
NetVision CorporationNVC11/29/1996
Network AlchemyNAL09/30/1997
Network DesignersNDL11/29/1996
Network GeneralNGC08/26/1997
Network Info TechnologyNIT11/29/1996
Network Peripherals IncNPI11/29/1996
Network Security Technology CoNST02/22/1999
Networth IncNTW11/29/1996
NeuroSky, Inc.NSA08/28/2013
NEUROTEC - EMPRESA DE PESQUISA E DESENVOLVIMENTO EM BIOMEDICINANEU03/15/2001
New Tech Int'l CompanyNTI11/29/1996
NewCom IncNCI01/09/1997
Newisys, Inc.NWS10/08/2002
Newport Systems SolutionsNSS11/29/1996
NexgenNXG11/29/1996
Nexgen Mediatech Inc.,NEX11/11/2003
Nexiq Technologies, Inc.NXQ10/08/2001
Next Level CommunicationsNLC11/29/1996
NextCom K.K.NXC11/29/1996
NingBo Bestwinning Technology CO., LtdNBT09/05/2006
NINGBO BOIGLE DIGITAL TECHNOLOGY CO.,LTDBOI11/25/2009
Nippon Avionics Co.,LtdAVI10/23/2000
NIPPONDENCHI CO,.LTDGSB05/24/2000
NISSEI ELECTRIC CO.,LTDNSI01/13/2000
Nissei Electric CompanyNIS11/29/1996
Nits Technology Inc.NTS12/19/2006
Nixdorf CompanyNCA11/29/1996
NNCNNC11/29/1996
Nokia DataNDS11/29/1996
Nokia Display ProductsNOK11/29/1996
Nokia Mobile PhonesNMP11/29/1996
Norand CorporationNOR03/19/1997
Norcent Technology, Inc.NCE06/20/2007
NordicEye ABNOE09/23/2009
North Invent A/SNOI05/04/2010
Northgate Computer SystemsNCS11/29/1996
Not Limited IncNOT01/30/1998
NovaWeb Technologies IncNWP06/12/1998
Novell IncNVL11/29/1996
Nspire System Inc.NSP02/13/2007
N-trig Innovative Technologies, Inc.NTR10/03/2005
NTT Advanced Technology CorporationNTT08/19/2004
NU Inc.NUI08/29/2007
NU Technology, Inc.NUG04/16/2004
Number Five SoftwareNFS02/22/1999
Nutech Marketing PTLKNX11/29/1996
NuVision US, Inc.NVI09/05/2006
Nuvoton Technology Corporation NTN10/09/2008
NvidiaNVD11/29/1996
N-VisionJEN10/23/2000
NXP Semiconductors bv.NXP06/14/2007
NW Computer EngineeringNWC02/03/1997
Oak Tech IncOAK11/29/1996
Oasys Technology CompanyOAS11/29/1996
OBJIX Multimedia CorporationOMC11/29/1996
OCTAL S.A.PCB02/24/1998
Oculus VR, Inc.OVR10/19/2012
OdracODR06/21/2001
Office Depot, Inc.ATV06/13/2007
OKI Electric Industrial Company LtdOKI11/29/1996
Oksori Company LtdOQI11/29/1996
Oksori Company LtdOSR11/29/1996
OlfanOCN11/29/1996
Olicom A/SOLC11/29/1996
Olidata S.p.A.OLD03/13/2006
Olitec S.A.OLT11/29/1996
Olitec S.A.OLV11/29/1996
OlivettiOLI11/29/1996
OLYMPUS CORPORATIONOLY05/02/2005
OmniTekOTK09/19/2013
OmnitelOMN04/28/1998
Omron CorporationOMR11/29/1996
On Systems IncONS11/29/1996
Oneac CorporationONE04/14/1998
ONKYO CorporationONK06/16/2005
OnLive, IncONL09/03/2010
OOO TechnoinvestTIV08/05/1997
Opcode IncOPC11/29/1996
Open Connect SolutionsOCS09/13/1999
OPEN Networks LtdONW04/25/2003
Open Stack, Inc.OSI07/22/2013
OPPO Digital, Inc.OPP06/19/2012
OPTi IncOPT11/29/1996
Optibase TechnologiesOBS11/01/2010
Optical Systems Design Pty LtdOSD06/03/2013
Option Industrial ComputersOIC05/07/2001
Option InternationalOIN10/23/2000
Option InternationalOIM01/30/1997
OPTI-UPS CorporationOSP07/01/1997
Optivision IncOPV11/29/1996
OPTO22, Inc.OTT10/06/1998
Optoma Corporation           OTM04/20/2010
Optum Engineering Inc.OEI08/02/2010
Orchid TechnologyOTI11/29/1996
ORGA Kartensysteme GmbHORG10/24/1998
Orion Communications Co., Ltd.TOP04/30/2007
ORION ELECTRIC CO., LTD.ORN01/19/2005
ORION ELECTRIC CO.,LTDOEC01/13/2000
OSAKA Micro Computer, Inc.OSA09/05/2003
OSR Open Systems Resources, Inc.ORI01/20/1999
OSRAMOOS04/25/2002
OUK Company LtdOUK11/29/1996
outsidetheboxstuff.comOTB09/03/2010
Oxus Research S.A.OXU11/29/1996
OZ CorporationOZC08/07/2012
Pacific Avionics CorporationPAC11/29/1996
Pacific CommWare IncPCW11/29/1996
Pacific Image Electronics Company LtdPIE10/21/1997
Packard Bell ElectronicsPBL11/29/1996
Packard Bell NECPBN11/29/1996
PACSGEAR, Inc.PGI08/13/2012
Padix Co., Inc.QFF09/13/1999
Pan Jit International Inc.PJT08/03/2004
PanasonicMDO11/29/1996
Panasonic Avionics CorporationPLF08/13/2010
Panasonic Industry CompanyMEI11/29/1996
Panelview, Inc.PNL08/04/2003
Pantel IncPTL11/29/1996
PAR Tech Inc.PTA01/26/2011
Parade Technologies, Ltd.PRT04/06/2012
Paradigm Advanced Research CentrePGM06/16/2005
Parallan Comp IncPAR11/29/1996
Parallax GraphicsPLX11/29/1996
Parc d'Activite des BellevuesRCE11/29/1996
ParrotPOT11/25/2014
Pathlight Technology IncPTH11/29/1996
PC XpertenPCX02/24/1998
PCBANK21PCK02/13/2007
PCM Systems CorporationPCM03/25/1997
PC-Tel IncPCT05/02/1997
PD Systems International LtdPDS03/20/1999
PDTS - Prozessdatentechnik und SystemePDT02/10/1998
Pegatron CorporationPEG08/27/2013
PEI Electronics IncPEI04/06/1998
Penta Studiotechnik GmbHPVM05/05/2010
pentel.co.,ltdPCL02/25/2002
Peppercon AGPEP04/12/2006
Perceptive Pixel Inc.PPX05/04/2010
Perceptive Signal TechnologiesPER05/13/1997
PerCommPRC04/24/2001
Performance Concepts Inc.,PCO09/24/2002
Performance TechnologiesIPN02/24/2004
Perle Systems LimitedPSL02/22/1999
Perpetual Technologies, LLCPON01/13/2000
Peter Antesberger MesstechnikPAM04/28/1998
Peus-Systems GmbHPSD11/29/1996
Philips BU Add On CardPCA11/29/1996
Philips Communication SystemsPHS11/29/1996
Philips Consumer Electronics CompanyPHL11/29/1996
Philips Medical Systems Boeblingen GmbHPHE04/20/2010
Philips SemiconductorsPSC11/29/1996
Phoenix ContactPXC02/27/2008
Phoenix Technologies, Ltd.PNX11/08/1999
Phoenixtec Power Company LtdPPC05/16/1999
Photonics Systems Inc.PHO06/03/2002
PhotoTelesisRSC03/16/1998
Phylon CommunicationsPHY11/29/1996
PicProPPR10/18/2004
Pijnenburg Beheer N.V.PHC04/24/2001
Pioneer Computer IncPCI11/29/1996
Pioneer Electronic CorporationPIO07/16/1997
Pitney BowesPBV09/13/1999
Pitney BowesPBI11/29/1996
Pixel QiPQI06/24/2009
Pixel VisionPVN11/29/1996
PIXELA CORPORATIONPXE11/21/2007
Pixie Tech IncPIX11/29/1996
Plain Tree Systems IncPTS11/29/1996
Planar Systems, Inc.PNR08/11/2003
PLUS Vision Corp.PLV07/05/2001
PMC Consumer Electronics LtdPMC12/11/1996
pmns GmbHSPR10/08/2002
Point Multimedia SystemPMM06/09/1997
Polycom Inc.PLY06/19/2002
PolyComp (PTY) Ltd.POL02/14/2006
Polycow ProductionsCOW03/15/2001
Portalis LCPOR11/01/2008
Poso International B.V.ARO08/01/1997
POTRANS Electrical Corp.PEC07/16/1999
PowerCom Technology Company LtdPCC09/02/1997
Powermatic Data SystemsCPX11/29/1996
Practical Electronic ToolsPET02/22/1999
Practical PeripheralsPPI11/29/1996
Practical Solutions Pte., Ltd.PSE10/06/1998
Praim S.R.L.PRD11/29/1996
Primax Electric LtdPEL11/29/1996
Prime Systems, Inc.SYX10/21/2003
Prime view international Co., LtdPVI07/06/2009
Princeton Graphic SystemsPGS11/29/1996
Prism, LLCPIM07/24/2007
Priva Hortimation BVPRI10/22/1997
PRO/AUTOMATIONPRA07/16/1999
Procomp USA IncPCP11/29/1996
Prodea Systems Inc.PSY02/04/2013
Prodrive B.V.PDV01/18/2005
ProjectaPJA01/29/1997
Projectavision IncDHT01/14/1998
Projectiondesign ASPJD09/23/2002
PROLINK Microsystems Corp.PLM02/25/2002
Pro-Log CorporationPLC11/29/1996
Promate Electronic Co., Ltd.PMT01/13/2003
PrometheusPRM11/29/1996
Promise Technology IncPTI01/02/1997
Promotion and Display Technology Ltd.PAD04/24/2001
Promotion and Display Technology Ltd.TEL04/24/2001
propagamma kommunikationPGP04/19/2000
ProsumPSM11/29/1996
ProteonPRO11/29/1996
Proview Global Co., LtdPVG10/08/2002
Proxim IncPXM09/19/1997
Proxima CorporationPRX11/29/1996
PS Technology CorporationPTC01/29/1997
Psion Dacom Plc.PDM11/08/1999
PSI-Perceptive Solutions IncPSI11/29/1996
PT Hartono Istana TeknologiPLT05/05/2010
Pulse-Eight LtdPUL09/12/2012
Pure Data IncPDR11/29/1996
Purup Prepress ASPPP11/29/1996
Qingdao Haier Electronics Co., Ltd.HRE04/12/2006
Q-LogicQLC11/29/1996
Qtronix CorporationQTR11/29/1996
QuadramDHQ11/29/1996
QuadramQDM11/29/1996
Quadrant Components IncQCL04/03/1997
QuakeCom Company LtdQCC03/23/1998
Qualcomm IncQCP05/16/1999
Quanta Computer IncQCI11/29/1996
Quanta Display Inc.QDS04/25/2002
QuantumQTM11/29/1996
Quantum 3D IncQTD05/23/1997
Quantum Data IncorporatedQDI03/15/2001
QuarticsQVU11/04/2010
Quatographic AGQUA01/13/2000
Questech LtdQTH01/13/2000
Questra ConsultingQUE01/30/1998
Quick CorporationQCK11/29/1996
Quickflex, IncQFI08/04/1998
Quicknet Technologies IncQTI11/29/1996
R SquaredRSQ11/08/1999
R.P.T.IntergroupsRPT11/29/1996
Racal Interlan IncRII11/29/1996
Racal-Airtech Software Forge LtdTSF11/29/1996
Racore Computer Products IncRAC11/29/1996
Radicom Research IncRRI12/02/1997
Radio Consult SRLRCN09/24/2002
RADIODATA GmbHRDN07/25/2012
RadioLAN IncRLN11/29/1996
Radiospire Networks, Inc.RSN06/14/2007
Radisys CorporationRAD11/29/1996
Radius IncRDS03/07/1997
RAFI GmbH & Co. KGRFI08/24/2015
Rainbow Displays, Inc.RDI09/23/1998
Rainbow TechnologiesRNB11/29/1996
Raintree SystemsRTS10/02/2001
Rainy OrchardBOB02/21/2000
Rampage Systems IncRSI11/29/1996
Rancho Tech IncRAN11/29/1996
Rancho Tech IncRTI11/29/1996
Rapid Tech CorporationRSX11/29/1996
Raritan Computer, IncRMC11/27/1998
Raritan, Inc.RAR06/14/2007
RAScom IncRAS11/29/1996
RATOC Systems, Inc.REX01/06/2012
Raylar Design, Inc.RAY01/13/2000
RC InternationalRCI11/29/1996
Reach Technology IncRCH02/09/1998
Reakin Technolohy CorporationRKC03/15/2001
Real DREA11/15/2007
Realtek Semiconductor Company LtdRTL11/29/1996
Realtek Semiconductor Corp.ALG10/25/2002
Realvision IncRVI11/29/1996
ReComREC05/16/1999
Red Wing CorporationRWC01/08/1998
Redfox Technologies Inc.RFX01/14/2014
Reflectivity, Inc.REF04/19/2000
Rehan Electronics Ltd.REH02/15/2012
Relia TechnologiesRTC11/29/1996
Reliance Electric Ind CorporationREL11/29/1996
Renesas Technology Corp.REN06/14/2007
Rent-A-TechRAT02/22/1999
Research Electronics Development IncRED12/02/1997
Research MachinesRMP11/29/1996
ResMed Pty LtdRES02/21/2000
Resonance Technology, Inc.RET02/09/2011
Restek Electric Company LtdWTS11/29/1996
Reveal Computer ProdRVL11/29/1996
Revolution Display, Inc.REV03/19/2014
RGB SpectrumRGB11/14/2012
RGB Systems, Inc. dba Extron ElectronicsEXN07/06/2008
RICOH COMPANY, LTD.RIC05/13/2010
RightHand TechnologiesRHD05/01/2012
Rios Systems Company LtdRIO11/29/1996
Ritech IncRIT04/14/1998
Rivulet CommunicationsRIV07/19/2007
Robert Bosch GmbHBSG05/15/2014
Robert Gray CompanyGRY03/31/1998
Robertson Geologging LtdRGL08/10/2000
Robust Electronics GmbH ROB01/18/2008
Rockwell Automation/IntecolorRAI03/13/1998
Rockwell CollinsRCO09/10/2010
Rockwell Collins / Airshow SystemsASY12/02/2004
Rockwell Collins, Inc.COL06/14/2007
Rockwell InternationalROK11/29/1996
Rockwell Semiconductor SystemsRSS11/29/1996
Rogen Tech Distribution IncMAX11/29/1996
Rohde & SchwarzROS01/20/2012
Rohm Co., Ltd.ROH06/16/2004
Rohm Company LtdRHM05/13/1997
Roland CorporationRJA11/29/1996
RoomPro TechnologiesRPI07/09/2010
Roper International LtdROP05/16/1999
Roper MobileRMT07/02/2010
Ross Video LtdRSV06/11/2012
Royal InformationTRL11/29/1996
Rozsnyó, s.r.o.RZS03/24/2014
RSI Systems IncRVC04/28/1998
RUNCO InternationalRUN04/01/2004
S&K ElectronicsSNK02/21/2000
S3 IncTLV01/07/1997
S3 IncSIM11/29/1996
S3 IncSSS11/29/1996
Saab AerotechSAE06/14/2007
Sage IncSAI07/16/1997
SAGEMSGM09/05/2003
SAIT-DevlonicsSDK11/29/1996
Saitek LtdSAK05/16/1999
Salt Internatioinal Corp.SLT09/05/2006
Samsung Electric CompanySAM11/29/1996
Samsung Electro-Mechanics Company LtdSKT11/29/1996
Samsung Electronics AmericaSTN08/10/2000
Samsung Electronics America IncKYK02/24/1998
Samsung Electronic Co.SSE08/10/2000
Samsung Electronics Company LtdSEM11/29/1996
Samtron Displays IncSDI11/29/1996
SANKEN ELECTRIC CO., LTDJSK09/13/1999
Sankyo Seiki Mfg.co., LtdSSJ01/28/2003
Sanritz Automation Co.,Ltd.SAA02/25/2002
SANTAK CORP.STK11/27/1998
Santec CorporationSOC01/12/2015
Sanyo Electric Co.,Ltd.SAN11/08/1999
Sanyo Electric Company LtdSCD11/29/1996
Sanyo Electric Company LtdSIB11/29/1996
Sanyo Electric Company LtdTSC11/29/1996
Sanyo IconICN11/29/1996
Sapience CorporationSPN11/29/1996
SAT (Societe Anonyme)SDA11/29/1996
SBS Technologies (Canada), Inc. (was Avvida Systems, Inc.)AVV12/17/2002
SBS-or Industrial Computers GmbHSBS12/28/1998
Scan Group LtdSGI11/29/1996
Scanport, Inc.SCN08/05/2002
SCD TechKFC10/23/2002
Sceptre Tech IncSPT11/29/1996
SchlumbergerSMB07/16/1999
Schlumberger CardsSCH04/28/1998
Schlumberger Technology CorporateSLR08/10/2000
Schneider & KochSKD11/29/1996
Schneider Electric S.A.MGE11/29/1996
Schnick-Schnack-Systems GmbHSLS05/06/2009
SCI Systems Inc.REM08/10/2000
SCM Microsystems IncSCM11/29/1996
Scriptel CorporationSCP06/14/2007
SDR SystemsSDR03/15/2001
SDS TechnologiesSTY11/08/1999
SDX Business Systems LtdSDX11/29/1996
Seanix Technology IncNIX04/09/2007
Seanix Technology Inc.SEA02/24/1998
SedlbauerSAG11/29/1996
SeeColor CorporationSEE11/29/1996
SeeCubic B.V.SCB11/02/2012
SeeReal Technologies GmbHSRT06/27/2005
Seiko Epson CorporationSEC11/29/1996
Seiko Instruments Information Devices IncSID12/16/1996
Seiko Instruments USA IncSIU11/29/1996
Seitz & Associates IncSEI01/30/1998
Sejin Electron IncSJE08/20/1997
SELEX GALILEOSXG10/01/2012
Semtech CorporationSTH11/30/2001
SendTek CorporationSET11/08/1999
Senseboard Technologies ABSBT09/03/2002
SencoreSEN05/23/1997
Sentelic CorporationSTU07/27/2012
SEOS LtdSEO02/20/2003
Sentronic International Corp.SNC10/23/2000
SEP Eletronica Ltda.SEP05/07/2001
Sequent Computer Systems IncSQT11/29/1996
Session Control LLCSES09/03/2010
SetredSRD09/05/2006
SEVIT Co., Ltd.SVT06/25/2002
SGEGSVA02/21/2000
Seyeon Tech Company LtdSYT12/02/1997
SGS Thomson MicroelectronicsSTM11/11/1997
Shadow SystemsOYO11/29/1996
Shanghai Bell Telephone Equip Mfg CoSBC04/30/1998
Shanghai Guowei Science and Technology Co., Ltd.SGW01/28/2011
SHANGHAI SVA-DAV ELECTRONICS CO., LTDXQU07/24/2003
Sharedware LtdSWL08/11/1998
Shark Multimedia IncSMM11/29/1996
SharkTec A/SDFK02/14/2006
Sharp CorporationSHP11/29/1996
SHARP TAKAYA ELECTRONIC INDUSTRY CO.,LTD.SXT06/24/2010
Shenzhen ChuangZhiCheng Technology Co., Ltd.CZC10/23/2013
Shenzhen Inet Mobile Internet Technology Co., LTDIXN11/04/2014
Shenzhen MTC Co., LtdSZM08/09/2013
Shenzhen Ramos Digital Technology Co., LtdRMS10/29/2014
Shenzhen South-Top Computer Co., Ltd.SSL12/06/2013
Shenzhen three Connaught Information Technology Co., Ltd. (3nod Group)AZH09/17/2013
Shenzhen Zhuona Technology Co., Ltd.XYE10/01/2013
Shenzhen ZhuoYi HengTong Computer Technology LimitedHTR12/13/2013
Shenzhen Zowee Technology Co., LTDZWE05/26/2015
Sherwood Digital Electronics CorporationSDE11/29/1996
ShibaSoku Co., Ltd.SHC05/26/2005
Shin Ho TechSHT11/29/1996
Shlumberger LtdSLB11/29/1996
Shuttle TechSAT11/29/1996
Sichuan Changhong Electric CO, LTD.CHG02/26/2003
Sichuang Changhong CorporationCHO11/30/2001
SiemensSIE11/29/1996
Siemens AGSDT02/14/2006
SIEMENS AGSIA03/15/2001
Siemens Microdesign GmbHSNI11/29/1996
Siemens Nixdorf Info SystemsSNP11/29/1996
Sierra Semiconductor IncSSC11/29/1996
Sierra Wireless Inc.SWI07/10/2003
Sigma Designs IncSIG11/29/1996
Sigma Designs, Inc.SGD02/14/2006
Sigmacom Co., Ltd.SCL04/25/2002
SigmaTel IncSTL03/03/1997
SignetDXS10/23/2000
SII Ido-Tsushin IncSTE04/03/1997
Silcom Manufacturing Tech IncSMT11/29/1996
Silex technology, Inc.SXD03/12/2009
Silicom Multimedia Systems IncSMS12/04/1996
Silicon Graphics IncSGX11/29/1996
Silicon Image, Inc.SII01/13/2000
Silicon Integrated Systems CorporationSIS11/29/1996
Silicon Laboratories, IncSIL07/16/1998
Silicon Library Inc.SLH11/01/2008
Silicon Optix CorporationSOI07/28/2005
Silitek CorporationSLK07/16/1997
SIM2 Multimedia S.P.A.SPU09/05/2002
Simple ComputingSMP11/29/1996
Simplex Time Recorder Co.SPX03/15/2001
Singular Technology Co., Ltd.SIN11/08/1999
SINOSUN TECHNOLOGY CO., LTDSNO06/27/2005
Sirius Technologies Pty LtdSIR03/13/1998
sisel muhendislikFUN04/25/2002
SITECSYSTEM CO., LTD.STS03/16/2005
SitintelSIT11/29/1996
SKYDATA S.P.A.SKY09/19/1997
Smart Card TechnologySCT08/10/2000
SMART Modular TechnologiesSMA04/04/1997
Smart Silicon Systems Pty LtdSPL08/10/2000
Smart Tech IncSTI11/29/1996
SMART Technologies Inc.SBI06/14/2007
SMK CORPORATIONSMK02/21/2000
Snell & WilcoxSNW04/25/2002
SOBO VISIONMVM06/14/2007
Socionext Inc.SCX05/14/2015
Sodeman Lancom IncLAN11/29/1996
SODIFF E&T CO., Ltd.SDF06/01/2007
Soft & Hardware development Goldammer GmbHSHG11/29/1996
Softbed - Consulting & Development LtdSBD12/23/1997
Software CaféSWC11/29/1996
Software Technologies Group,Inc.SWT11/29/2008
Solitron Technologies IncSOL11/29/1996
Solomon Technology CorporationSLM01/16/1998
SolutionInsideSXL05/08/2001
SOMELEC Z.I. Du Vert GalantaONX11/29/1996
SonitronixHON02/03/2011
Sonix Comm. LtdSNX11/29/1996
SonySNY11/29/1996
SonySON11/29/1996
Sony Ericsson Mobile Communications Inc.SER04/16/2004
SORCUS Computer GmbHSCO01/13/2000
Sorcus Computer GmbHSOR11/29/1996
SORD Computer CorporationSCC11/29/1996
Sotec Company LtdSOT05/21/1997
South Mountain Technologies, LTDFRS02/14/2006
SOYO Group, IncSOY12/18/2006
SPACE-I Co., Ltd.SPI05/11/2005
SpaceLabs Medical IncSMI11/29/1996
SPEA Software AGSPE11/29/1996
SpeakerCraftSPK04/20/2010
SpecialixSLX11/29/1996
Spectragraphics CorporationSGC11/29/1996
Spectrum Signal Proecessing IncSSP11/29/1996
SR-Systems e.K.SRS11/19/2012
S-S Technology IncSSI11/29/1996
ST Electronics Systems Assembly Pte LtdSTA12/28/1998
STAC ElectronicsSTC11/29/1996
Standard Microsystems CorporationSMC11/29/1996
Star Paging Telecom Tech (Shenzhen) Co. Ltd.STT09/23/1998
Starflight ElectronicsSTF05/23/1997
Stargate TechnologySGT11/29/1996
StarLeafSLF11/01/2010
Starlight Networks IncSTR11/29/1996
Starwin Inc.STW04/24/2001
StaticSWS05/16/1999
STB Systems IncSTB11/29/1996
STD Computer IncSTD11/29/1996
StereoGraphics Corp.STG10/02/2001
ST-EricssonSTX12/09/2011
STMicroelectronicsSMO06/14/2007
Stollmann E+V GmbHSTO03/27/1997
Stores Automated Systems IncSAS03/19/1997
Storm TechnologyEZP10/17/1996
StreamPlay LtdSTP02/04/2009
Stryker CommunicationsSYK10/10/2005
Subspace Comm. IncSUB11/29/1996
Sumitomo Metal Industries, Ltd.SML09/13/1999
Summagraphics CorporationSUM11/29/1996
Sun CorporationSCE11/29/1996
Sun Electronics CorporationSUN11/29/1996
Sun MicrosystemsSVI01/13/2003
SUNNY ELEKTRONIKSNN11/14/2014
SunRiver Data SystemSDS11/29/1996
Super Gate Technology Company LtdSGL12/30/1997
SuperNet IncSNT04/23/1998
Supra CorporationSUP11/29/1996
Surenam Computer CorporationSUR11/29/1996
Surf Communication Solutions LtdSRF03/23/1998
SVD ComputerSVD04/14/1998
SVSISVS08/09/2008
SY Electronics LtdSYE09/20/2010
Sylvania Computer ProductsSYL06/12/1998
Symbios Logic IncSLI11/29/1996
Symbol TechnologiesISA06/02/1997
Symicron Computer Communications Ltd.SYM11/29/1996
Synaptics IncSYN11/29/1996
Synopsys IncSPS11/29/1996
Syntax-BrillianSXB05/08/2006
SYPRO Co LtdSYP11/27/1998
Sysgration LtdSYS04/28/1997
Syslogic Datentechnik AGSLC01/20/1999
Sysmate CompanySME09/02/1997
Sysmate CorporationSIC05/05/1997
SysmicSYC11/29/1996
Systec Computer GmbHSGZ10/02/1997
System CraftSCI11/29/1996
system elektronik GmbHSEB04/19/2000
Systeme Lauer GmbH&Co KGSLA03/20/1999
Systems EnhancementUPS11/29/1996
SystemSoft CorporationSST11/29/1996
Systran CorporationSCR11/29/1996
SYVAX IncSYV11/29/1996
T+A elektroakustik GmbHTUA 01/05/2011
Taicom Data Systems Co., Ltd.TCD10/08/2001
Taicom International IncTMR11/29/1996
Taiko Electric Works.LTDTKC03/15/2001
Taiwan Video & Monitor CorporationTVM11/29/1996
Takahata Electronics Co.,Ltd.KTD07/22/2009
Tamura Seisakusyo LtdTAM07/17/1997
TandbergTAA10/21/2003
Tandberg Data Display ASTDD11/29/1996
Tandem Computer Europe IncTDM11/29/1996
Tandon CorporationTCC11/29/1996
Tandy ElectronicsTDY11/29/1996
Taskit Rechnertechnik GmbHTAS12/15/1997
Tatung Company of America IncTCS11/29/1996
Tatung UK LtdVIB07/16/1999
Taugagreining hfNRV11/29/1996
Taxan (Europe) LtdTAX03/13/1997
TDK USA CorporationPMD11/29/1996
TDTTDT11/29/1996
TDVision Systems, Inc.TDV01/18/2008
TEAC System CorporationTEA11/29/1996
TEC CORPORATIONCET07/16/1998
TEAC America IncTCJ11/29/1996
Tech Source Inc.TEZ08/14/2013
Techmedia Computer Systems CorporationTMC02/10/1998
Technical Concepts LtdTCL11/29/1996
Technical Illusions Inc.TIL02/14/2014
TechniSat Digital GmbHTSD07/14/2005
Technology Nexus Secure Open Systems ABNXS05/08/1998
Technology Power Enterprises IncTPE11/29/1996
TechnoTrend Systemtechnik GmbHTTS11/29/1996
Tecmar IncTEC11/29/1996
Tecnetics (PTY) LtdTCN11/29/1996
TECNIMAGEN SATNM05/02/2005
TecnovisionTVD03/13/2006
Tectona SoftSolutions (P) Ltd.,RXT06/02/2004
Teknor Microsystem IncTKN11/29/1996
Tekram Technology Company LtdTRM11/29/1996
Tektronix IncTEK05/16/1999
TEKWorx LimitedTWX12/24/2009
Telecom Technology Centre Co. Ltd.TCT07/16/1999
Telecommunications Techniques CorporationTTC11/29/1996
Teleforce.,co,ltdTLF11/19/2012
Teleliaison IncTAT04/29/1997
Telelink AGTLK09/01/1998
Teleprocessing Systeme GmbHTPS01/24/1997
Teles AGTAG11/29/1996
Teleste Educational OYTLS11/29/1996
TeleVideo SystemsTSI11/29/1996
Telia ProSoft ABPFT09/13/1999
TelindusTLD11/29/1996
Telxon CorporationTLX11/29/1996
Tennyson Tech Pty LtdTNY11/29/1996
TeradiciTDC10/11/2007
TerraTec Electronic GmbHTER03/21/1997
Texas InsturmentsTXN11/29/1996
Texas MicrosystemTMI11/29/1996
Textron Defense SystemTXT11/29/1996
The Concept Keyboard Company LtdCKC06/02/1997
The Linux FoundationLNX04/04/2014
The Moving Pixel CompanyPXL11/24/2003
The NTI GroupITN11/29/1996
The OPEN GroupTOG09/13/1999
The Panda ProjectPAN11/29/1996
The Phoenix Research Group IncPRG09/19/1997
The Software Group LtdTSG11/29/1996
Thermotrex CorporationTMX11/29/1996
ThinklogicalTLL06/01/2015
Thomas-Conrad CorporationTCO11/29/1996
Thomson Consumer ElectronicsTCR08/20/1998
Thruput LtdTPT06/16/2010
Thundercom Holdings Sdn. Bhd.THN03/21/1997
Tidewater AssociationTWA11/29/1996
Time Management, Inc.TMM03/20/1999
TimeKeeping Systems, Inc.TKS08/31/1998
Times (Shanghai) Computer Co., Ltd.TPD12/12/2013
TIPTEL AGTIP02/24/1998
Tixi.Com GmbHTIX10/16/1998
T-Metrics Inc.TMT02/21/2000
TNC Industrial Company LtdTNC02/27/1998
Todos Data System ABTAB08/20/1997
TOEI Electronics Co., Ltd.TOE10/02/2001
TONNATON03/14/2012
Top Victory Electronics ( Fujian ) Company LtdTPV05/16/1999
TOPRE CORPORATIONTPK02/13/2009
Topro Technology IncTPR05/08/1998
Topson Technology Co., Ltd.TTA09/23/1998
TORNADO CompanySFM04/15/1997
Torus Systems LtdTGS11/29/1996
Torus Systems LtdTRS11/29/1996
Toshiba America Info Systems IncTAI11/29/1996
Toshiba America Info Systems IncTSB11/29/1996
Toshiba CorporationTOS11/29/1996
Toshiba CorporationTTP07/07/2015
Toshiba Global Commerce Solutions, Inc.TGC06/26/2012
Toshiba Matsushita Display Technology Co., LtdLCD05/24/2000
TOSHIBA PERSONAL COMPUTER SYSTEM CORPRATIONPCS06/22/2010
TOSHIBA TELI CORPORATIONTLI01/18/2008
Totoku Electric Company LtdTTK11/29/1996
Tottori Sanyo ElectricTSE11/29/1996
Tottori SANYO Electric Co., Ltd.TSL11/06/2001
Touch Panel Systems CorporationTPC09/02/1997
TouchKo, Inc.TKO01/12/2006
Touchstone TechnologyTOU05/07/2001
TouchSystemsTSY01/18/2008
TOWITOKO electronics GmbHTWK04/14/1998
Transtex SACSB03/15/2001
Transtream IncTST04/29/1997
TRANSVIDEOTSV05/04/2010
TremetricsTRE04/24/1997
Tremon Enterprises Company LtdRDM11/29/1996
Trenton Terminals IncTTI11/29/1996
Trex EnterprisesTRX02/21/2000
Tribe Computer Works IncOZO11/29/1996
Tricord SystemsTRI11/29/1996
Tri-Data Systems IncTDS11/29/1996
TRIDELITY Display Solutions GmbHTTY07/19/2010
Trident Microsystem IncTRD11/29/1996
Trident Microsystems LtdTMS07/15/2002
TriGem Computer IncTGI11/29/1996
TriGem Computer,Inc.TGM07/05/2001
Trigem KinfoCommTIC02/26/2003
Trioc ABTRC01/13/2000
Triple S Engineering IncTBB09/26/1997
Tritec Electronic AGTRT01/11/2012
TriTech Microelectronics InternationalTRA01/24/1997
Triumph Board a.s.TRB 09/27/2013
Trivisio Prototyping GmbHTRV11/18/2011
Trixel LtdTXL08/10/2000
Trtheim TechnologyMKV03/17/1997
TruevisionTVI11/29/1996
TTE, Inc.TTE01/18/2005
Tulip Computers Int'l B.V.TCI11/29/1996
Turbo Communication, IncTBC09/01/1998
Turtle Beach SystemTBS11/29/1996
Tut SystemsTUT08/19/1997
TV Interactive CorporationTVR11/29/1996
TV One LtdTVO09/02/2008
TV1 GmbHTVV02/06/2012
TVS Electronics LimitedTVS05/20/2008
Twinhead International CorporationTWH11/29/1996
Tyan Computer CorporationTYN11/29/1996
U. S. Electronics Inc.USE10/28/2013
U.S. Naval Research LabNRL11/29/1996
U.S. NavyTSP10/17/2002
U.S. Digital CorporationUSD11/29/1996
U.S. Robotics IncUSR11/29/1996
Ubinetics Ltd.UBL05/23/2002
Ueda Japan Radio Co., Ltd.UJR07/09/2003
UFO Systems IncUFO11/29/1996
Ultima Associates Pte LtdUAS01/02/1997
Ultima Electronics CorporationUEC09/01/1998
Ultra Network TechULT11/29/1996
Umezawa Giken Co.,LtdUMG04/10/2008
Ungermann-Bass IncUBI11/29/1996
UnicateUNY07/21/1998
Uniden CorporationUDN10/18/2004
Uniform Industrial CorporationUIC11/29/1996
Uniform Industry Corp.UNI11/06/2001
UNIGRAF-USAUFG10/09/2008
Unisys CorporationUNB11/29/1996
Unisys CorporationUNC11/29/1996
Unisys CorporationUNM11/29/1996
Unisys CorporationUNO11/29/1996
Unisys CorporationUNS11/29/1996
Unisys CorporationUNT11/29/1996
Unisys DSDUNA11/29/1996
Uni-Take Int'l Inc.WKH06/17/2002
United Microelectr CorporationUMC11/29/1996
UnitopUNP11/06/2001
Universal Electronics IncUEI08/20/1997
Universal Empowering TechnologiesUET09/26/1997
Universal MultimediaUMM10/08/2001
Universal Scientific Industrial Co., Ltd.USI11/04/2003
University CollegeJGD11/29/1996
Uniwill Computer Corp.UWC04/16/2004
Up to Date TechUTD11/29/1996
UPPIUPP04/14/1998
Ups Manufactoring s.r.l.RUP03/15/2001
USC Information Sciences InstituteASD04/08/1997
Utimaco Safeware AGUSA05/04/1998
Vaddio, LLCVAD11/30/2012
VademVDM11/29/1996
VAIO CorporationVAI04/18/2014
Valence Computing CorporationVAL11/29/1996
Valley Board LtdaVBT03/15/2001
ValleyBoard Ltda.VLB04/05/1998
Valve CorporationVLV03/06/2013
VanErum GroupITI10/01/2013
Varian Australia Pty LtdVAR04/19/2000
VATIV TechnologiesVTV04/12/2006
VBrick Systems Inc.VBR08/19/2009
VCONEXVCX06/15/2005
VDC Display SystemsVDC04/29/2009
Vector Informatik GmbHVEC09/10/1997
Vector Magnetics, LLCVCM04/12/2006
VektrexVEK12/13/1996
VeriFone IncVFI05/29/1998
Vermont MicrosystemsVMI11/29/1996
Vestax CorporationVTX02/14/2012
Vestel Elektronik Sanayi ve Ticaret A. S.VES09/19/1997
Via Mons Ltd.VIM08/29/2012
VIA Tech IncVIA11/29/1996
Victor Company of Japan, LimitedVCJ02/06/2009
Victor Data SystemsVDA05/24/2000
Victron B.V.VIC11/29/1996
Video & Display Oriented CorporationVDO11/29/1996
Video Computer S.p.A.URD02/24/1998
Video International Inc.JWD02/21/2000
Video Products IncVPI05/04/2010
VideoLan TechnologiesVLT10/17/1997
VideoServerVSI06/25/1997
Videotechnik BreithauptVTB07/23/2013
VIDEOTRON CORP.VTN05/04/2010
Vidisys GmbH & CompanyVDS11/29/1996
Viditec, Inc.VDT11/08/1999
ViewSonic CorporationVSC11/29/1996
Viewteck Co., Ltd.VTK10/08/2001
Viking ConnectorsVIK11/29/1996
Vinca CorporationVNC11/29/1996
Vinci LabsNHT03/03/2006
Vine Micros LimitedVML06/16/2004
Vine Micros LtdVIN04/19/2000
Virtual Computer CorporationVCC11/29/1996
Virtual Resources CorporationVRC11/29/1996
Vision QuestVQ@10/26/2009
Vision Systems GmbHVSP11/29/1996
VisioneerVIS11/29/1996
Visitech ASVIT09/05/2006
Vislink International LtdVLK08/27/2012
VistaCom IncVCI11/29/1996
Visual Interface, IncVIR11/27/1998
Vivid Technology Pte LtdVTL11/29/1996
VIZIO, IncVIZ06/06/2012
VLSI Tech IncVTI11/29/1996
VMware Inc.,VMW10/18/2011
Voice Technologies Group IncVTG04/24/1997
Vortex Computersysteme GmbHGDT11/29/1996
VPixx Technologies Inc.VPX12/05/2013
VRmagic Holding AGVRM04/12/2013
V-Star Electronics Inc.VSR02/21/2000
VTech Computers LtdVTS11/29/1996
VTel CorporationVTC11/29/1996
Vutrix (UK) LtdVUT07/22/2003
Vweb Corp.VWB03/12/2004
Wacom TechWAC11/29/1996
Wallis Hamilton IndustriesJPW07/16/1999
Wanlida Group Co., Ltd.MLT04/24/2014
Wave AccessWAL12/13/1996
Wave SystemsAWS11/29/1996
Wave Systems CorporationWVM12/05/1997
WavephoreWAV11/29/1996
Way2Call CommunicationsSEL03/20/1997
WB Systemtechnik GmbHWBS09/08/1997
W-DEVWEL 11/01/2010
Wearnes Peripherals International (Pte) LtdWPI03/31/1998
Wearnes Thakral PteWTK11/29/1996
WebGear IncWEB01/30/1998
Westermo Teleindustri ABWMO01/13/2000
Western DigitalWDC11/29/1996
Westinghouse Digital ElectronicsWDE05/23/2003
WEY Design AGWEY10/18/2004
Whistle CommunicationsWHI10/24/1998
Wildfire Communications IncWLD02/13/1997
WillNet Inc.WNI04/19/2000
Winbond Electronics CorporationWEC11/29/1996
Diebold Nixdorf Systems GmbHWNX09/20/2004
Winmate Communication IncWMT03/15/2001
Winnov L.P.WNV03/07/1997
WiNRADiO CommunicationsWRC09/11/1997
Wintop Technology IncWIN12/29/1996
Wipotec Wiege- und Positioniersysteme GmbHWWP04/08/2014
WIPRO Information Technology LtdWIL11/29/1996
Wipro InfotechWIP01/09/2004
Wireless And Smart Products Inc.WSP03/20/1999
Wisecom IncWCI11/29/1996
Wistron CorporationWST09/03/2010
Wolfson Microelectronics LtdWML07/30/1997
WolfVision GmbHWVV09/18/2012
Woodwind Communications Systems IncWCS11/29/1996
Wooyoung Image & Information Co.,Ltd.WYT01/18/2008
WorkStation TechWTI11/29/1996
World Wide Video, Inc.WWV10/24/1998
Woxter Technology Co. LtdWXT09/03/2010
X-10 (USA) IncXTN02/24/1997
X2E GmbHXTE09/23/2009
XAC Automation CorpXAC02/22/1999
XDM Ltd.XDM11/22/2010
Xedia CorporationMAD11/29/1996
Xilinx, Inc.XLX08/01/2007
Xinex Networks IncXIN02/07/1997
Xiotech CorporationXIO05/29/1998
Xircom IncXRC11/29/1996
Xitel Pty ltdXIT11/29/1996
Xirocm IncXIR11/29/1996
XN Technologies, Inc.XNT07/14/2003
XOCECOUHB11/27/1998
XORO ELECTRONICS (CHENGDU) LIMITEDXRO05/23/2005
XS Technologies IncXST01/20/1998
Xscreen ASXSN02/14/2006
XSYSXSY04/23/1998
Yamaha CorporationYMH11/29/1996
Xycotec Computer GmbHXYC09/03/2002
Yasuhiko Shirai Melco IncBUF11/29/1996
Y-E Data IncYED11/29/1996
Yokogawa Electric CorporationYHQ11/29/1996
Ypoaz Systems IncTPZ11/29/1996
Z MicrosystemsZMZ08/10/2005
Z3 TechnologyZTT12/14/2010
Zalman Tech Co., Ltd.ZMT05/07/2007
Zandar Technologies plcZAN12/03/2003
ZeeVee, Inc.ZAZ01/18/2008
Zebra Technologies International, LLCZBR09/15/2003
Zefiro AcousticsZAX11/29/1996
ZeitControl cardsystems GmbHZCT01/20/1999
ZENIC Inc.ZEN04/17/2015
Zenith Data SystemsZDS11/29/1996
Zenith Data SystemsZGT11/29/1996
Zenith Data SystemsZSE11/29/1996
Zetinet IncZNI11/29/1996
Zhejiang Tianle Digital Electric Co., Ltd. TLE01/17/2014
Zhong Shan City Richsound Electronic Industrial Ltd. RSR01/27/2015
Znyx Adv. SystemsZNX11/29/1996
Zoom Telephonics IncZTI11/29/1996
Zoran CorporationZRN03/31/2005
Zowie Intertainment, IncZOW02/22/1999
ZT Group Int'l Inc.ZTM06/14/2007
ZTE CorporationZTE09/03/2010
Zuniq Data CorporationSIX11/29/1996
Zydacron IncZYD04/10/1997
ZyDAS Technology CorporationZTC05/24/2000
Zypcom IncZYP03/19/1997
Zytex ComputersZYT11/29/1996
Zytor CommunicationsHPA07/02/2010
Alpha Electronics CompanyAEJ11/29/1996
BOEBOE12/02/2004
Chaplet Systems IncFIR11/29/1996
Chenming Mold Ind. Corp.CMG11/14/2003
coolux GmbHCOO09/30/2010
Data General CorporationDGC11/29/1996
ExabyteEXA11/29/1996
Herolab GmbHHRL03/17/1998
Hitachi Computer Products IncHCP11/29/1996
Integrated Circuit SystemsICS11/29/1996
IrdataIRD04/24/2001
Jewell Instruments, LLCJWL06/21/2001
MultiQ Products ABMQP03/20/1999
Ncast CorporationNAC02/14/2006
ODME Inc.ODM09/23/1998
PhotomatrixPMX11/29/1996
Quantum Solutions, Inc.QSI01/13/2000
Red Hat, Inc.RHT02/17/2011
ZyxelZYX11/29/1996
Carrera Computer IncJAZ01/01/1994
Chunghwa Picture Tubes, LTDCGA01/01/1994
eMicro CorporationEMC01/01/1994
Hisense Electric Co., Ltd.HEC01/01/1994
PanaScopePNS01/01/1994
SpinCore Technologies, IncSPC01/01/1994
Sensics, Inc.SVR08/27/2015
IAdea CorporationIAD09/10/2015
Express Industrial, Ltd.ELU09/10/2015
Hewlett Packard Enterprise HPE09/22/2015
Klipsch Group, Inc KGI09/22/2015
Tek GearTKG10/16/2015
HangZhou ZMCHIVINZMC10/16/2015
HTC CorportationHVR10/16/2015
Zebax TechnologiesZBX10/16/2015
Guangzhou Shirui Electronics Co., Ltd.SWO10/16/2015
Picturall Ltd.PIC11/13/2015
Guangzhou Teclast Information Technology LimitedSKM11/18/2015
GreenArrays, Inc.GAC11/18/2015
Thales AvionicsTAV11/18/2015
Explorer Inc.EXR11/18/2015
Avegant CorporationAVG12/02/2015
MicroImage Video SystemsMIV12/08/2015
ASUSTek COMPUTER INCAUS12/21/2015
Synthetel CorporationSTQ12/21/2015
HP Inc.HPN12/21/2015
MicroTechnica Co.,Ltd.MTJ01/04/2016
Gechic CorporationGEC01/04/2016
MPL AG, Elektronik-UnternehmenMEU01/15/2016
Display Solution AGDSA02/03/2016
UEFI ForumPRP02/03/2016
Taitex CorporationTTX02/03/2016
EchoStar CorporationECH02/26/2016
TCL CorporationTOL03/30/2016
ADDER TECHNOLOGY LTDADZ03/30/2016
HKC OVERSEAS LIMITEDHKC03/30/2016
KEYENCE CORPORATIONKYN03/30/2016
TETRADYNE CO., LTD.TET04/27/2016
Abaco Systems, Inc.ABS04/27/2016
Meta CompanyMVN05/25/2016
Eizo Rugged SolutionsERS05/25/2016
VersaLogic CorporationVLC05/25/2016
CYPRESS SEMICONDUCTOR CORPORATIONCYP05/25/2016
MILDEF ABMDF06/23/2016
FOVE INCFOV07/01/2016
INNESNES07/01/2016
Hoffmann + Krippner GmbHHUK07/01/2016
Axell CorporationAXE08/03/2016
UltiMachineUMT08/11/2016
TPK Holding Co., LtdKPT08/16/2016
AAEON Technology Inc.AAN09/01/2016
Six15 TechnologiesTDG09/14/2016
Inlife-Handnet Co., Ltd.IVR01/19/2017
VR Technology Holdings Limited DSJ01/19/2017
Pimax Tech. CO., LTD PVR02/07/2017
Total Vision LTD TVL02/07/2017
Shanghai Lexiang Technology Limited DPN02/07/2017
Black Box CorporationBBX02/28/2017
TRAPEZE GROUP TRP02/28/2017
Pabian Embedded Systems PMS02/28/2017
Televic Conference TCF02/28/2017
Shanghai Chai Ming Huang Info&Tech Co, Ltd HYL02/28/2017
Techlogix NetworxTLN02/28/2017
G2TOUCH KOREAGGT05/25/2017
MediCapture, Inc.MVR05/25/2017
HOYA Corporation PENTAX Lifecare DivisionPNT05/25/2017
christmann informationstechnik + medien GmbH & Co. KGCHR05/25/2017
TencentTEN06/20/2017
VRstudios, Inc.VRS06/22/2017
Extreme Engineering Solutions, Inc.XES06/22/2017
NewTekNTK06/22/2017
BlueBox Video LimitedBBV06/22/2017
Televés, S.A.TEV06/22/2017
Avatron Software Inc.AVS08/23/2017
Positivo Tecnologia S.A.POS09/01/2017
VRgineers, Inc.VRG09/07/2017
Noritake Itron CorporationNRI11/13/2017
Matrix Orbital CorporationMOC11/13/2017
Elegant InventionEIN03/29/2018
Immersive Audio Technologies FranceIMF03/29/2018
Lightspace TechnologiesLSP03/29/2018
PixelNext IncPXN03/29/2018
VRSHOW Technology LimitedTSW03/29/2018
SONOVE GmbHSNV03/29/2018
Silex InsideSXI03/29/2018
Huawei Technologies Co., Inc. HWV04/25/2018
Varjo TechnologiesVRT11/17/2017
Japan E.M.Solutions Co., Ltd.JEM05/24/2018
QD Laser, Inc.QDL05/31/2018
VADATECH INCVAT07/09/2018
Medicaroid CorporationMCJ08/20/2018
Razer Taiwan Co. Ltd.RZR08/20/2018
GIGA-BYTE TECHNOLOGY CO., LTD.GBT09/05/2018
Kontron GmbHKOM09/05/2018
Convergent Engineering, Inc.CIE09/05/2018
WyreStorm Technologies LLC WYR09/05/2018
Astro HQ LLCAHQ 09/05/2018
QSC, LLCQSC01/18/2019
Dimension Engineering LLCDMN02/06/2019
Shenzhen Dlodlo Technologies Co., Ltd.DLO04/29/2019
LENOVO BEIJING CO. LTD.VLM05/21/2019
Cammegh LimitedCRW06/18/2019
Beihai Century Joint Innovation Technology Co.,LtdLHC09/10/2019
Findex, Inc.FDX10/22/2019
Express Luck, Inc.ELD10/22/2019
LLC SKTB “SKIT”SKI10/22/2019
WOLF Advanced TechnologyWLF10/22/2019
BILD INNOVATIVE TECHNOLOGY LLCBLD10/22/2019
MIMO MonitorsMMT10/22/2019
IcronICR10/22/2019
TECNART CO.,LTD.PIS10/22/2019
Moxa Inc.MHQ10/22/2019
Disguise TechnologiesDSG10/22/2019
+ + \ No newline at end of file diff --git a/hwdb.d/sdio.ids b/hwdb.d/sdio.ids new file mode 100644 index 00000000..9c706c0e --- /dev/null +++ b/hwdb.d/sdio.ids @@ -0,0 +1,95 @@ +# +# List of SDIO ID's +# + +# Vendors and devices. Please keep sorted. + +# Syntax: +# vendor vendor_name +# device device_name <-- single tab + +0020 ST-Ericsson + 2280 CW1200 +0089 Intel Corp. +0092 C-guys, Inc. + 0001 SD-Link11b WiFi Card (TI ACX100) + 0004 EW-CG1102GC + 0005 SD FM Radio 2 + 5544 SD FM Radio +0097 Texas Instruments, Inc. + 4076 WL1271 +0098 Toshiba Corp. + 0001 SD BT Card 1 + 0002 SD BT Card 2 + 0003 SD BT Card 3 +0104 Socket Communications, Inc. + 005e SD Scanner + 00c5 Bluetooth SDIO Card +0271 Atheros Communications, Inc. + 0108 AR6001 + 0109 AR6001 + 010a AR6001 + 010b AR6001 +0296 GCT Semiconductor, Inc. + 5347 GDM72xx WiMAX +02d0 Broadcom Corp. + 044b Nintendo Wii WLAN daughter card + a887 BCM43143 WLAN card + a9a6 BCM43438 combo WLAN and Bluetooth Low Energy (BLE) # As in RPi3B + 4324 BCM43241 WLAN card + 4329 BCM4329 WLAN card + 4330 BCM4330 WLAN card + 4334 BCM4334 WLAN card + a94c BCM43340 WLAN card + a94d BCM43341 WLAN card + 4335 BCM4335/BCM4339 WLAN card + a962 BCM43362 WLAN card + 4354 BCM4354 WLAN card +02db SyChip Inc. + 0002 Pegasus WLAN SDIO Card (6060SD) +02df Marvell Technology Group Ltd. + 9103 Libertas + 9104 SD8688 WLAN + 9105 SD8688 BT + 9116 SD8786 WLAN + 9119 SD8787 WLAN + 911a SD8787 BT + 911b SD8787 BT AMP + 9129 SD8797 WLAN + 912a SD8797 BT + 912e SD8897 BT + 912d SD8897 WLAN +02fe Spectec Computer Co., Ltd + 2128 SDIO WLAN Card (SDW820) +032a Cambridge Silicon Radio + 0001 UniFi 1 + 0002 UniFi 2 + 0007 UniFi 3 + 0008 UniFi 4 +037a MediaTek Inc. + 5911 Spectec WLAN-11b/g +039a Siano Mobile Silicon +0501 Globalsat Technology Co. + f501 SD-501 GPS Card +104c Texas Instruments, Inc. + 9066 WL1251 +1180 Ricoh Co., Ltd + e823 MMC card reader +13d1 AboCom Systems, Inc. + ac02 SDW11G + +# List of known interface classes +# +# Syntax: +# C class class_name + +C 00 Non-standard SDIO interface +C 01 UART standard interface +C 02 Bluetooth Type-A standard interface +C 03 Bluetooth Type-B standard interface +C 04 GPS standard interface +C 05 Camera standard interface +C 06 PHS standard interface +C 07 WLAN interface +C 08 Embedded SDIO-ATA standard interface +C 09 Bluetooth AMP standard interface diff --git a/hwdb.d/usb.ids b/hwdb.d/usb.ids new file mode 100644 index 00000000..ad555749 --- /dev/null +++ b/hwdb.d/usb.ids @@ -0,0 +1,21826 @@ +# +# List of USB ID's +# +# Maintained by Stephen J. Gowdy +# If you have any new entries, please submit them via +# http://www.linux-usb.org/usb-ids.html +# or send entries as patches (diff -u old new) in the +# body of your email (a bot will attempt to deal with it). +# The latest version can be obtained from +# http://www.linux-usb.org/usb.ids +# +# Version: 2020.01.09 +# Date: 2020-01-09 20:34:06 +# + +# Vendors, devices and interfaces. Please keep sorted. + +# Syntax: +# vendor vendor_name +# device device_name <-- single tab +# interface interface_name <-- two tabs + +0001 Fry's Electronics + 7778 Counterfeit flash drive [Kingston] +0002 Ingram +0003 Club Mac +0004 Nebraska Furniture Mart +0011 Unknown + 7788 counterfeit flash drive +0053 Planex + 5301 GW-US54ZGL 802.11bg +0078 Microntek + 0006 Joystick +0079 DragonRise Inc. + 0006 PC TWIN SHOCK Gamepad + 0011 Gamepad + 1800 Mayflash Wii U Pro Game Controller Adapter [DirectInput] + 181b Venom Arcade Joystick + 1843 Mayflash GameCube Controller Adapter + 1844 Mayflash GameCube Controller +0080 Assmann Electronic GmbH + a001 Digitus DA-71114 SATA +0085 Boeye Technology Co., Ltd. + 0600 eBook Reader +0105 Trust International B.V. + 145f NW-3100 802.11b/g 54Mbps Wireless Network Adapter [zd1211] +0127 IBP + 0002 HDM Interface + 0127 ibp +0145 Unknown + 0112 Card Reader +017c MLK + 145f Trust Deskset +0200 TP-Link + 0201 MA180 UMTS Modem +0204 Chipsbank Microelectronics Co., Ltd + 6025 CBM2080 / CBM2090 Flash drive controller + 6026 CBM1180 Flash drive controller +0218 Hangzhou Worlde + 0301 MIDI Port +02ad HUMAX Co., Ltd. + 138c PVR Mass Storage +0303 Mini Automation Controller +0324 OCZ Technology Inc + bc06 OCZ ATV USB 2.0 Flash Drive + bc08 OCZ Rally2/ATV USB 2.0 Flash Drive +0325 OCZ Technology Inc + ac02 ATV Turbo / Rally2 Dual Channel USB 2.0 Flash Drive +0386 LTS + 0001 PSX for USB Converter +03d9 Shenzhen Sinote Tech-Electron Co., Ltd + 0499 SE340D PC Remote Control +03da Bernd Walter Computer Technology + 0002 HD44780 LCD interface +03e7 Intel + 2150 Myriad VPU [Movidius Neural Compute Stick] + 2485 Movidius MyriadX + f63b Myriad VPU [Movidius Neural Compute Stick] +03e8 EndPoints, Inc. + 0004 SE401 Webcam + 0008 101 Ethernet [klsi] + 0015 ATAPI Enclosure + 2123 SiPix StyleCam Deluxe + 8004 Aox 99001 +03e9 Thesys Microelectronics +03ea Data Broadcasting Corp. +03eb Atmel Corp. + 0902 4-Port Hub + 2002 Mass Storage Device + 2015 at90usbkey sample firmware (HID keyboard) + 2018 at90usbkey sample firmware (CDC ACM) + 2019 stk525 sample firmware (microphone) + 201c at90usbkey sample firmware (HID mouse) + 201d at90usbkey sample firmware (HID generic) + 2022 at90usbkey sample firmware (composite device) + 2040 LUFA Test PID + 2041 LUFA Mouse Demo Application + 2042 LUFA Keyboard Demo Application + 2043 LUFA Joystick Demo Application + 2044 LUFA CDC Demo Application + 2045 LUFA Mass Storage Demo Application + 2046 LUFA Audio Output Demo Application + 2047 LUFA Audio Input Demo Application + 2048 LUFA MIDI Demo Application + 2049 Stripe Snoop Magnetic Stripe Reader + 204a LUFA CDC Class Bootloader + 204b LUFA USB to Serial Adapter Project + 204c LUFA RNDIS Demo Application + 204d LUFA Combined Mouse and Keyboard Demo Application + 204e LUFA Dual CDC Demo Application + 204f LUFA Generic HID Demo Application + 2060 Benito Programmer Project + 2061 LUFA Combined Mass Storage and Keyboard Demo Application + 2062 LUFA Combined CDC and Mouse Demo Application + 2063 LUFA Datalogger Device + 2064 Interfaceless Control-Only LUFA Devices + 2065 LUFA Test and Measurement Demo Application + 2066 LUFA Multiple Report HID Demo + 2068 LUFA Virtual Serial/Mass Storage Demo + 2069 LUFA Webserver Project + 2103 JTAG ICE mkII + 2104 AVR ISP mkII + 2105 AVRONE! + 2106 STK600 development board + 2107 AVR Dragon + 2109 STK541 ZigBee Development Board + 210a AT86RF230 [RZUSBSTICK] transceiver + 210d XPLAIN evaluation kit (CDC ACM) + 2110 AVR JTAGICE3 Debugger and Programmer + 2111 Xplained Pro board debugger and programmer + 2122 XMEGA-A1 Explained evaluation kit + 2140 AVR JTAGICE3 (v3.x) Debugger and Programmer + 2141 ICE debugger + 2145 ATMEGA328P-XMINI (CDC ACM) + 2310 EVK11xx evaluation board + 2404 The Micro + 2fe4 ATxmega32A4U DFU bootloader + 2fe6 Cactus V6 (DFU) + 2fea Cactus RF60 (DFU) + 2fee atmega8u2 DFU bootloader + 2fef atmega16u2 DFU bootloader + 2ff0 atmega32u2 DFU bootloader + 2ff1 at32uc3a3 DFU bootloader + 2ff3 atmega16u4 DFU bootloader + 2ff4 atmega32u4 DFU bootloader + 2ff6 at32uc3b0/1 DFU bootloader + 2ff7 at90usb82 DFU bootloader + 2ff8 at32uc3a0/1 DFU bootloader + 2ff9 at90usb646/647 DFU bootloader + 2ffa at90usb162 DFU bootloader + 2ffb at90usb AVR DFU bootloader + 2ffd at89c5130/c5131 DFU bootloader + 2fff at89c5132/c51snd1c DFU bootloader + 3301 at43301 4-Port Hub + 3312 4-Port Hub + 4102 AirVast W-Buddie WN210 + 5601 at76c510 Prism-II 802.11b Access Point + 5603 Cisco 7920 WiFi IP Phone + 6119 AT91SAM CDC Demo Application + 6124 at91sam SAMBA bootloader + 6127 AT91SAM HID Keyboard Demo Application + 6129 AT91SAM Mass Storage Demo Application + 6200 AT91SAM HID Mouse Demo Application + 7603 D-Link DWL-120 802.11b Wireless Adapter [Atmel at76c503a] + 7604 at76c503a 802.11b Adapter + 7605 at76c503a 802.11b Adapter + 7606 at76c505 802.11b Adapter + 7611 at76c510 rfmd2948 802.11b Access Point + 7613 WL-1130 USB + 7614 AT76c505a Wireless Adapter + 7615 AT76C505AMX Wireless Adapter + 7617 AT76C505AS Wireless Adapter + 7800 Mini Album + 800c Airspy HF+ + ff02 WootingTwo + ff07 Tux Droid fish dongle +03ec Iwatsu America, Inc. +03ed Mitel Corp. +03ee Mitsumi + 0000 CD-R/RW Drive + 2501 eHome Infrared Receiver + 2502 eHome Infrared Receiver + 5609 Japanese Keyboard + 641f WIF-0402C Bluetooth Adapter + 6438 Bluetooth Device + 6440 WML-C52APR Bluetooth Adapter + 6901 SmartDisk FDD + 6902 Floppy Disk Drive + 7500 CD-R/RW + ffff Dongle with BlueCore in DFU mode +03f0 HP, Inc + 0004 DeskJet 895c + 0011 OfficeJet G55 + 0012 DeskJet 1125C Printer Port + 0024 KU-0316 Keyboard + 002a LaserJet P1102 + 0053 DeskJet 2620 All-in-One Printer + 0101 ScanJet 4100c + 0102 PhotoSmart S20 + 0104 DeskJet 880c/970c + 0105 ScanJet 4200c + 0107 CD-Writer Plus + 010c Multimedia Keyboard Hub + 0111 G55xi Printer/Scanner/Copier + 0117 LaserJet 3200 + 011c hn210w 802.11b Adapter + 011d Bluetooth 1.2 Interface [Broadcom BCM2035] + 0121 HP 39g+ [F2224A], 39gs [F2223A], 40gs [F2225A], 48gII [F2226A], 49g+ [F2228A], 50g [F2229A, NW240AA] + 0122 HID Internet Keyboard + 0125 DAT72 Tape + 0139 Barcode Scanner 4430 + 0201 ScanJet 6200c + 0202 PhotoSmart S20 + 0204 DeskJet 815c + 0205 ScanJet 3300c + 0207 CD-Writer Plus 8200e + 020c Multimedia Keyboard + 0211 OfficeJet G85 + 0212 DeskJet 1220C + 0217 LaserJet 2200 + 0218 APOLLO P2500/2600 + 0221 StreamSmart 400 [F2235AA] + 0223 Digital Drive Flash Reader + 022a Laserjet CP1525nw + 0241 Link-5 micro dongle + 0304 DeskJet 810c/812c + 0305 ScanJet 4300c + 0307 CD-Writer+ CD-4e + 0311 OfficeJet G85xi + 0312 Color Inkjet CP1700 + 0314 designjet 30/130 series + 0317 LaserJet 1200 + 0324 SK-2885 keyboard + 034a Elite Keyboard + 0401 ScanJet 5200c + 0404 DeskJet 830c/832c + 0405 ScanJet 3400cse + 0411 OfficeJet G95 + 0412 Printing Support + 0417 LaserJet 1200 series + 0423 HS-COMBO Cardreader + 042a LaserJet M1132 MFP + 0441 Prime [NW280AA, G8X92AA] + 0504 DeskJet 885c + 0505 ScanJet 2100c + 0507 DVD+RW + 050c 5219 Wireless Keyboard + 0511 OfficeJet K60 + 0512 DeckJet 450 + 0517 LaserJet 1000 + 051d Bluetooth Interface + 052a LaserJet M1212nf MFP + 0601 ScanJet 6300c + 0604 DeskJet 840c + 0605 ScanJet 2200c + 0610 Z24i Monitor Hub + 0611 OfficeJet K60xi + 0612 business inkjet 3000 + 0624 Bluetooth Dongle + 0641 X1200 Optical Mouse + 0701 ScanJet 5300c/5370c + 0704 DeskJet 825c + 0705 ScanJet 4400c + 070c Personal Media Drive + 0711 OfficeJet K80 + 0712 DeskJet 1180c + 0714 Printing Support + 0741 Prime Wireless Kit [FOK65AA] + 0801 ScanJet 7400c + 0804 DeskJet 816c + 0805 HP4470C + 0811 OfficeJet K80xi + 0817 LaserJet 3300 + 0901 ScanJet 2300c + 0904 DeskJet 845c + 0912 Printing Support + 0917 LaserJet 3330 + 0924 Modular Smartcard Keyboard + 0941 X500 Optical Mouse + 094a Optical Mouse [672662-001] + 0a01 ScanJet 2400c + 0a17 color LaserJet 3700 + 0b01 ScanJet 82x0C + 0b0c Wireless Keyboard and Optical Mouse receiver + 0b17 LaserJet 2300d + 0c17 LaserJet 1010 + 0c24 Bluetooth Dongle + 0d12 OfficeJet 9100 series + 0d17 LaserJet 1012 + 0d4a SK-2025 Keyboard + 0e17 LaserJet 1015 + 0f0c Wireless Keyboard and Optical Mouse receiver + 0f11 OfficeJet V40 + 0f12 Printing Support + 0f17 LaserJet 1150 + 0f2a LaserJet 400 color M451dn + 1001 Photo Scanner 1000 + 1002 PhotoSmart 140 series + 1004 DeskJet 970c/970cse + 1005 ScanJet 5400c + 1011 OfficeJet V40xi + 1016 Jornada 548 / iPAQ HW6515 Pocket PC + 1017 LaserJet 1300 + 1024 Smart Card Keyboard + 1027 Virtual keyboard and mouse + 102a LaserJet Professional P 1102w + 1102 PhotoSmart 240 series + 1104 DeskJet 959c + 1105 ScanJet 5470c/5490c + 1111 OfficeJet v60 + 1116 Jornada 568 Pocket PC + 1117 LaserJet 1300n + 1151 PSC-750xi Printer/Scanner/Copier + 1198 HID-compliant mouse + 1202 PhotoSmart 320 series + 1204 DeskJet 930c + 1205 ScanJet 4500C/5550C + 1211 OfficeJet v60xi + 1217 LaserJet 2300L + 1227 Virtual CD-ROM + 1302 PhotoSmart 370 series + 1305 ScanJet 4570c + 1311 OfficeJet V30 + 1312 DeskJet 460 + 1317 LaserJet 1005 + 1327 iLO Virtual Hub + 134a Optical Mouse + 1405 ScanJet 3670 + 1411 PSC 750 + 1424 f2105 Monitor Hub + 1502 PhotoSmart 420 series + 1504 DeskJet 920c + 150c Mood Lighting (Microchip Technology Inc.) + 1511 PSC 750xi + 1512 Printing Support + 1517 color LaserJet 3500 + 1524 Smart Card Keyboard - KR + 1539 Mini Magnetic Stripe Reader + 1541 Prime [G8X92AA] + 154a Laser Mouse + 1602 PhotoSmart 330 series + 1604 DeskJet 940c + 1605 ScanJet 5530C PhotoSmart + 1611 psc 780 + 1617 LaserJet 3015 + 161d Wireless Rechargeable Optical Mouse (HID) + 1624 Smart Card Keyboard - JP + 1702 PhotoSmart 380 series + 1704 DeskJet 948C + 1705 ScanJet 5590 + 1711 psc 780xi + 1712 Printing Support + 1717 LaserJet 3020 + 171d Bluetooth 2.0 Interface [Broadcom BCM2045] + 1801 Inkjet P-2000U + 1802 PhotoSmart 470 series + 1804 DeskJet 916C + 1805 ScanJet 7650 + 1811 PSC 720 + 1812 OfficeJet Pro K550 + 1817 LaserJet 3030 + 181d Bluetooth 2.0 Interface + 1902 PhotoSmart A430 series + 1904 DeskJet 3820 + 1911 OfficeJet V45 + 1917 LaserJet 3380 + 1a02 PhotoSmart A510 series + 1a11 OfficeJet 5100 series + 1a17 color LaserJet 4650 + 1b02 PhotoSmart A610 series + 1b04 DeskJet 3810 + 1b05 ScanJet 4850C/4890C + 1b07 Premium Starter Webcam + 1c02 PhotoSmart A710 series + 1c17 Color LaserJet 2550l + 1d02 PhotoSmart A310 series + 1d17 LaserJet 1320 + 1d24 Barcode scanner + 1e02 PhotoSmart A320 Printer series + 1e11 PSC-950 + 1e17 LaserJet 1160 series + 1f02 PhotoSmart A440 Printer series + 1f11 PSC 920 + 1f12 OfficeJet Pro K5300 + 1f17 color LaserJet 5550 + 1f1d un2400 Gobi Wireless Modem + 2001 Floppy + 2002 Hub + 2004 DeskJet 640c + 2005 ScanJet 3570c + 2012 OfficeJet Pro K5400 + 201d un2400 Gobi Wireless Modem (QDL mode) + 2039 Cashdrawer + 2102 PhotoSmart 7345 + 2104 DeskJet 630c + 2112 OfficeJet Pro L7500 + 211d Sierra MC5725 [ev2210] + 2202 PhotoSmart 7600 series + 2205 ScanJet 3500c + 2212 OfficeJet Pro L7600 + 2217 color LaserJet 9500 MFP + 222a LaserJet Pro MFP M125nw + 2302 PhotoSmart 7600 series + 2304 DeskJet 656c + 2305 ScanJet 3970c + 2311 OfficeJet d series + 2312 OfficeJet Pro L7700 + 2317 LaserJet 4350 + 231d Broadcom 2070 Bluetooth Combo + 2402 PhotoSmart 7700 series + 2404 Deskjet F2280 series + 2405 ScanJet 4070 PhotoSmart + 2417 LaserJet 4250 + 241d Gobi 2000 Wireless Modem (QDL mode) + 2424 LP1965 19" Monitor Hub + 2502 PhotoSmart 7700 series + 2504 DeskJet F4200 series + 2505 ScanJet 3770 + 2512 OfficeJet Pro L7300 / Compaq LA2405 series monitor + 2514 4-port hub + 2517 LaserJet 2410 + 251d Gobi 2000 Wireless Modem + 2524 LP3065 30" Monitor Hub + 2602 PhotoSmart A520 series + 2605 ScanJet 3800c + 2611 OfficeJet 7100 series + 2617 Color LaserJet 2820 series + 2624 Pole Display (HP522 2 x 20 Line Display) + 2702 PhotoSmart A620 series + 2704 DeskJet 915 + 2717 Color LaserJet 2830 + 2724 Magnetic Stripe Reader IDRA-334133-HP + 2805 Scanjet G2710 + 2811 PSC-2100 + 2817 Color LaserJet 2840 + 2902 PhotoSmart A820 series + 2911 PSC 2200 + 2917 LaserJet 2420 + 2a11 PSC 2150 series + 2a17 LaserJet 2430 + 2a1d Integrated Module with Bluetooth 2.1 Wireless technology + 2b11 PSC 2170 series + 2b17 LaserJet 1020 + 2b4a Business Slim Keyboard + 2c12 Officejet J4680 + 2c17 LaserJet 1022 + 2c24 Logitech M-UAL-96 Mouse + 2d05 Scanjet 7000 + 2d11 OfficeJet 6110 + 2d17 Printing Support + 2e11 PSC 1000 + 2e17 LaserJet 2600n + 2e24 LP2275w Monitor Hub + 2f11 PSC 1200 + 2f17 Color LaserJet 2605dn + 2f24 LP2475w Monitor Hub + 3002 PhotoSmart P1000 + 3004 DeskJet 980c + 3005 ScanJet 4670v + 3011 PSC 1100 series + 3017 Printing Support + 304a Slim Keyboard + 3102 PhotoSmart P1100 Printer w/ Card Reader + 3104 DeskJet 960c + 3111 OfficeJet 4100 series + 3117 EWS 2605dtn + 311d Atheros AR9285 Malbec Bluetooth Adapter + 3202 PhotoSmart 1215 + 3207 4 GB flash drive + 3211 OfficeJet 4105 series + 3217 LaserJet 3050 + 3302 PhotoSmart 1218 + 3304 DeskJet 990c + 3307 v125w Stick + 3312 OfficeJet J6410 + 3317 LaserJet 3052 + 3402 PhotoSmart 1115 + 3404 DeskJet 6122 + 3417 LaserJet 3055 + 3502 PhotoSmart 230 + 3504 DeskJet 6127c + 3511 PSC 2300 + 3517 LaserJet 3390 + 3602 PhotoSmart 1315 + 3611 PSC 2410 PhotoSmart + 3612 Officejet Pro 8000 A809 + 3617 Color LaserJet 2605 + 3711 PSC 2500 + 3717 EWS UPD + 3724 Webcam + 3802 PhotoSmart 100 + 3807 c485w Flash Drive + 3817 LaserJet P2015 series + 3902 PhotoSmart 130 + 3912 Officejet Pro 8500 + 3917 LaserJet P2014 + 3a02 PhotoSmart 7150 + 3a11 OfficeJet 5500 series + 3a17 Printing Support + 3a1d hs2340 HSPA+ mobile broadband + 3b02 PhotoSmart 7150~ + 3b05 Scanjet N8460 + 3b11 PSC 1300 series + 3b17 LaserJet M1005 MFP + 3b2a Color LaserJet MFP M277dw + 3c02 PhotoSmart 7350 + 3c05 Scanjet Professional 1000 Mobile Scanner + 3c11 PSC 1358 + 3c17 EWS UPD + 3d02 PhotoSmart 7350~ + 3d11 OfficeJet 4215 + 3d17 LaserJet P1005 + 3e02 PhotoSmart 7550 + 3e17 LaserJet P1006 + 3f02 PhotoSmart 7550~ + 3f11 PSC-1315/PSC-1317 + 4002 PhotoSmart 635/715/720/735/935/E337 (storage) + 4004 CP1160 + 4102 PhotoSmart 618 + 4105 ScanJet 4370 + 4111 OfficeJet 7200 series + 4117 LaserJet 1018 + 4202 PhotoSmart 812 + 4205 ScanJet G3010 + 4211 OfficeJet 7300 series + 4217 EWS CM1015 + 4302 PhotoSmart 850 (ptp) + 4305 ScanJet G3110 + 4311 OfficeJet 7400 series + 4317 Color LaserJet CM1017 + 4402 PhotoSmart 935 (ptp) + 4417 EWS UPD + 4502 PhotoSmart 945 (PTP mode) + 4505 ScanJet G4010 + 4507 External HDD + 4511 PhotoSmart 2600 + 4512 E709n [Officejet 6500 Wireless] + 4517 EWS UPD + 4605 ScanJet G4050 + 4611 PhotoSmart 2700 + 4717 Color LaserJet CP1215 + 4811 PSC 1600 + 4911 PSC 2350 + 4b11 OfficeJet 6200 + 4c11 PSC 1500 series + 4c17 EWS UPD + 4d11 PSC 1400 + 4d17 EWS UPD + 4e11 PhotoSmart 2570 series + 4f11 OfficeJet 5600 (USBHUB) + 4f17 Color LaserJet CM1312 MFP + 5004 DeskJet 995c + 5011 PhotoSmart 3100 series + 5017 EWS UPD + 5111 PhotoSmart 3200 series + 5211 PhotoSmart 3300 series + 5307 v165w Stick + 5311 OfficeJet 6300 + 5312 Officejet Pro 8500A + 5317 Color LaserJet CP2025 series + 5411 OfficeJet 4300 + 5511 DeskJet F300 series + 5611 PhotoSmart C3180 + 5617 LaserJet M1120 MFP + 5711 PhotoSmart C4100 series + 5717 LaserJet M1120n MFP + 5811 PhotoSmart C5100 series + 5817 LaserJet M1319f MFP + 581d lt4112 Gobi 4G Module Network Device + 5911 PhotoSmart C6180 + 5912 Officejet Pro 8600 + 5a11 PhotoSmart C7100 series + 5b11 OfficeJet J2100 series + 5b12 Officejet Pro 8100 + 5c11 PhotoSmart C4200 Printer series + 5c12 OfficeJet 6700 + 5c17 LaserJet P2055 series + 5d11 PhotoSmart C5200 series + 5e11 PhotoSmart D7400 series + 6004 DeskJet 5550 + 6102 Hewlett Packard Digital Camera + 6104 DeskJet 5650c + 6117 color LaserJet 3550 + 6202 PhotoSmart 215 + 6204 DeskJet 5150c + 6217 Color LaserJet 4700 + 6302 PhotoSmart 318/612 + 6317 Color LaserJet 4730mfp + 6402 PhotoSmart 715 (ptp) + 6411 PhotoSmart C8100 series + 6417 LaserJet 5200 + 6502 PhotoSmart 120 (ptp) + 6511 PhotoSmart C7200 series + 6602 PhotoSmart 320 + 6611 PhotoSmart C4380 series + 6617 LaserJet 5200L + 6702 PhotoSmart 720 (ptp) + 6717 Color LaserJet 3000 + 6802 PhotoSmart 620 (ptp) + 6811 PhotoSmart D5300 series + 6817 Color LaserJet 3800 + 6911 PhotoSmart D7200 series + 6917 Color LaserJet 3600 + 6a02 PhotoSmart 735 (ptp) + 6a11 PhotoSmart C6200 series + 6a17 LaserJet 4240 + 6b02 PhotoSmart R707 (PTP mode) + 6b11 Photosmart C4500 series + 6c11 Photosmart C4480 + 6c17 Color LaserJet 4610 + 6f17 Color LaserJet CP6015 series + 7004 DeskJet 3320c + 7102 PhotoSmart 635 (PTP mode) + 7104 DeskJet 3420c + 7117 CM8060 Color MFP with Edgeline Technology + 7202 PhotoSmart 43x (ptp) + 7204 DeskJet 36xx + 7217 LaserJet M5035 MFP + 7302 PhotoSmart M307 (PTP mode) + 7304 DeskJet 35xx + 7311 Photosmart Premium C309 + 7317 LaserJet P3005 + 7404 Printing Support + 7417 LaserJet M4345 MFP + 7504 Printing Support + 7517 LaserJet M3035 MFP + 7604 DeskJet 3940 + 7611 DeskJet F2492 All-in-One + 7617 LaserJet P3004 + 7702 PhotoSmart R817 (PTP mode) + 7704 DeskJet D4100 + 7717 CM8050 Color MFP with Edgeline Technology + 7804 DeskJet D1360 + 7817 Color LaserJet CP3505 + 7917 LaserJet M5025 MFP + 7a02 PhotoSmart M415 (PTP mode) + 7a04 DeskJet D2460 + 7a17 LaserJet M3027 MFP + 7b02 PhotoSmart M23 (PTP mode) + 7b17 Color LaserJet CP4005 + 7c17 Color LaserJet CM6040 series + 7d04 DeskJet F2100 Printer series + 7d17 Color LaserJet CM4730 MFP + 7e04 DeskJet F4100 Printer series + 8017 LaserJet P4515 + 8104 Printing Support + 8117 LaserJet P4015 + 811c Ethernet HN210E + 8204 Printing Support + 8207 FHA-3510 2.4GHz Wireless Optical Mobile Mouse + 8217 LaserJet P4014 + 8317 LaserJet M9050 MFP + 8404 DeskJet 6800 series + 8417 LaserJet M9040 MFP + 8504 DeskJet 6600 series + 8604 DeskJet 5440 + 8607 Optical Mobile Mouse + 8704 DeskJet 5940 + 8711 Deskjet 2050 J510 + 8804 DeskJet 6980 series + 8904 DeskJet 6940 series + 8911 Deskjet 1050 J410 + 8c07 Digital Stereo Headset + 8c11 Deskjet F4500 series + 9002 PhotoSmart M437 + 9102 PhotoSmart M537 + 9207 HD-4110 Webcam + 9302 PhotoSmart R930 series + 9402 PhotoSmart R837 + 942a LaserJet Pro M12a + 9502 PhotoSmart R840 series + 952a LaserJet Pro M12w + 9602 PhotoSmart M730 series + 9702 PhotoSmart R740 series + 9802 PhotoSmart Mz60 series + 9902 PhotoSmart M630 series + 9a02 PhotoSmart E330 series + 9b02 PhotoSmart M540 series + 9b07 Portable Drive + 9c02 PhotoSmart M440 series + a004 DeskJet 5850c + a011 Deskjet 3050A + a407 Wireless Optical Comfort Mouse + b002 PhotoSmart 7200 series + b102 PhotoSmart 7200 series + b107 v255w/c310w Flash Drive + b116 Webcam + b202 PhotoSmart 7600 series + b302 PhotoSmart 7600 series + b402 PhotoSmart 7700 series + b502 PhotoSmart 7700 series + b602 PhotoSmart 7900 series + b702 PhotoSmart 7900 series + b802 PhotoSmart 7400 series + b902 PhotoSmart 7800 series + ba02 PhotoSmart 8100 series + bb02 PhotoSmart 8400 series + bc02 PhotoSmart 8700 series + bd02 PhotoSmart Pro B9100 series + bef4 NEC Picty760 + c002 PhotoSmart 7800 series + c102 PhotoSmart 8000 series + c111 Deskjet 1510 + c202 PhotoSmart 8200 series + c302 DeskJet D2300 + c402 PhotoSmart D5100 series + c502 PhotoSmart D6100 series + c602 PhotoSmart D7100 series + c702 PhotoSmart D7300 series + c802 PhotoSmart D5060 Printer + d104 Bluetooth Dongle + d507 39gII [NW249AA] + efbe NEC Picty900 + f0be NEC Picty920 + f1be NEC Picty800 +03f1 Genoa Technology +03f2 Oak Technology, Inc. +03f3 Adaptec, Inc. + 0020 AWN-8020 WLAN [Intersil PRISM 2.5] + 0080 AVC-1100 Audio Capture + 0083 AVC-2200 Device + 0087 AVC-2210 Loader + 0088 AVC-2210 Device + 008b AVC-2310 Loader + 008c AVC-2310 Device + 0094 eHome Infrared Receiver + 009b AVC-1410 GameBridge TV NTSC + 2000 USBXchange + 2001 USBXchange Adapter + 2002 USB2-Xchange + 2003 USB2-Xchange Adapter + 4000 4-port hub + adcc Composite Device Support +03f4 Diebold, Inc. +03f5 Siemens Electromechanical +03f8 Epson Imaging Technology Center +03f9 KeyTronic Corp. + 0100 KT-2001 Keyboard + 0101 Keyboard + 0102 Keyboard Mouse +03fb OPTi, Inc. +03fc Elitegroup Computer Systems +03fd Xilinx, Inc. + 0008 Platform Cable USB II + 0050 dfu downloader +03fe Farallon Comunications +0400 National Semiconductor Corp. + 05dc Rigol Technologies DS1000USB Oscilloscope + 0807 Bluetooth Dongle + 080a Bluetooth Device + 09c4 Rigol Technologies DG1022 Arbitrary Waveform Generator + 1000 Mustek BearPaw 1200 Scanner + 1001 Mustek BearPaw 2400 Scanner + 1237 Hub + a000 Smart Display Reference Device + c359 Logitech Harmony + c35b Printing Support + c55d Rigol Technologies DS5000USB Oscilloscope +0401 National Registry, Inc. +0402 ALi Corp. + 5462 M5462 IDE Controller + 5602 M5602 Video Camera Controller + 5603 M5603 Video Camera Controller + 5606 M5606 Video Camera Controller [UVC] + 5621 M5621 High-Speed IDE Controller + 5623 M5623 Scanner Controller + 5627 Welland ME-740PS USB2 3.5" Power Saving Enclosure + 5632 M5632 Host-to-Host Link + 5635 M5635 Flash Card Reader + 5636 USB 2.0 Storage Device + 5637 M5637 IDE Controller + 5642 Storage Device + 5661 M5661 MP3 player + 5667 M5667 MP3 player + 9665 Gateway Webcam +0403 Future Technology Devices International, Ltd + 0000 H4SMK 7 Port Hub / Bricked Counterfeit FT232 Serial (UART) IC + 0232 Serial Converter + 1060 JTAG adapter + 1234 IronLogic RFID Adapter [Z-2 USB] + 1235 Iron Logic Z-397 RS-485/422 converter + 6001 FT232 Serial (UART) IC + 6002 Lumel PD12 + 6007 Serial Converter + 6008 Serial Converter + 6009 Serial Converter + 6010 FT2232C/D/H Dual UART/FIFO IC + 6011 FT4232H Quad HS USB-UART/FIFO IC + 6014 FT232H Single HS USB-UART/FIFO IC + 6015 Bridge(I2C/SPI/UART/FIFO) + 6f70 HB-RF-USB + 8028 Dev board JTAG (FT232H based) + 8040 4 Port Hub + 8070 7 Port Hub + 8140 Vehicle Explorer Interface + 8210 MGTimer - MGCC (Vic) Timing System + 8348 FT232BM [SIENNA Serial Interface] + 8370 7 Port Hub + 8371 PS/2 Keyboard And Mouse + 8372 FT8U100AX Serial Port + 87d0 Cressi Dive Computer Interface + 8a28 Rainforest Automation ZigBee Controller + 8a98 TIAO Multi-Protocol Adapter + 8b28 Alpermann+Velte TCI70 + 8b29 Alpermann+Velte TC60 CLS + 8b2a Alpermann+Velte Rubidium Q1 + 8b2b Alpermann+Velte TCD + 8b2c Alpermann+Velte TCC70 + 9090 SNAP Stick 200 + 9132 LCD and Temperature Interface + 9133 CallerID + 9135 Rotary Pub alarm + 9136 Pulsecounter + 9e90 Marvell OpenRD Base/Client + 9f80 Ewert Energy Systems CANdapter + a6d0 Texas Instruments XDS100v2 JTAG / BeagleBone A3 + a951 HCP HIT GSM/GPRS modem [Cinterion MC55i] + a9a0 FT2232D - Dual UART/FIFO IC - FTDI + abb8 Lego Mindstorms NXTCam + b0c0 microSensys RFID device + b0c1 microSensys RFID device + b0c2 iID contactless RFID device + b0c3 iID contactless RFID device + b0c4 RFID device + b0c5 RFID device + b810 US Interface Navigator (CAT and 2nd PTT lines) + b811 US Interface Navigator (WKEY and FSK lines) + b812 US Interface Navigator (RS232 and CONFIG lines) + b9b0 Fujitsu SK-16FX-100PMC V1.1 + baf8 Amontec JTAGkey + bcd8 Stellaris Development Board + bcd9 Stellaris Evaluation Board + bcda Stellaris ICDI Board + bd90 PICAXE Download Cable [AXE027] + bdc8 Egnite GmbH - JTAG/RS-232 adapter + bfd8 OpenDCC + bfd9 OpenDCC (Sniffer) + bfda OpenDCC (Throttle) + bfdb OpenDCC (Gateway) + bfdc OpenDCC (GBM) + c580 HID UNIKEY dongle [F-Response] + c630 lcd2usb interface + c631 i2c-tiny-usb interface + c632 xu1541 c64 floppy drive interface + c633 TinyCrypt dongle + c634 glcd2usb interface + c7d0 RR-CirKits LocoBuffer-USB + c8b8 Alpermann+Velte MTD TCU + c8b9 Alpermann+Velte MTD TCU 1HE + c8ba Alpermann+Velte Rubidium H1 + c8bb Alpermann+Velte Rubidium H3 + c8bc Alpermann+Velte Rubidium S1 + c8bd Alpermann+Velte Rubidium T1 + c8be Alpermann+Velte Rubidium D1 + c8bf Alpermann+Velte TC60 RLV + cc48 Tactrix OpenPort 1.3 Mitsubishi + cc49 Tactrix OpenPort 1.3 Subaru + cc4a Tactrix OpenPort 1.3 Universal + cff8 Amontec JTAGkey + d010 SCS PTC-IIusb + d011 SCS Position-Tracker/TNC + d012 SCS DRAGON 1 + d013 SCS DRAGON 1 + d388 Xsens converter + d389 Xsens Wireless Receiver + d38a Xsens serial converter + d38b Xsens serial converter + d38c Xsens Wireless Receiver + d38d Xsens Awinda Station + d38e Xsens serial converter + d38f Xsens serial converter + d491 Zolix Omni 1509 monochromator + d578 Accesio USB-COM-4SM + d6f8 UNI Black BOX + d738 Propox JTAGcable II + d739 Propox ISPcable III + d9a9 Actisense USG-1 NMEA Serial Gateway + d9aa Actisense NGT-1 NMEA2000 PC Interface + d9ab Actisense NGT-1 NMEA2000 Gateway + daf4 Qundis Serial Infrared Head + e0d0 Total Phase Aardvark I2C/SPI Host Adapter + e521 EVER Sinline XL Series UPS + e6c8 PYRAMID Computer GmbH LCD + e700 Elster Unicom III Optical Probe + e729 Segway Robotic Mobility Platforms 200 + e888 Expert ISDN Control USB + e889 USB-RS232 OptoBridge + e88a Expert mouseCLOCK USB II + e88b Precision Clock MSF USB + e88c Expert mouseCLOCK USB II HBG + e8d8 Aaronia AG Spectran Spectrum Analyzer + e8dc Aaronia AG UBBV Preamplifier + ea90 Eclo 1-Wire Adapter + ecd9 miControl miCan-Stick + ed71 HAMEG HO870 Serial Port + ed72 HAMEG HO720 Serial Port + ed73 HAMEG HO730 Serial Port + ed74 HAMEG HO820 Serial Port + ef10 FT1245BL + f070 Serial Converter 422/485 [Vardaan VEUSB422R3] + f0c8 SPROG Decoder Programmer + f0c9 SPROG-DCC CAN-USB + f0e9 Tagsys L-P101 + f0ee Tagsys Medio P200x + f1a0 Asix PRESTO Programmer + f208 Papenmeier Braille-Display + f3c0 4N-GALAXY Serial Converter + f458 ABACUS ELECTRICS Optical Probe + f608 CTI USB-485-Mini + f60b CTI USB-Nano-485 + f680 Suunto Sports Instrument + f758 GW Instek GDS-8x0 Oscilloscope + f7c0 ZeitControl Cardsystems TagTracer MIFARE + f850 USB-UIRT (Universal Infrared Receiver+Transmitter) + f918 Ant8 Logic Probe + fa00 Matrix Orbital USB Serial + fa01 Matrix Orbital MX2 or MX3 + fa02 Matrix Orbital MX4 or MX5 + fa03 Matrix Orbital VK/LK202 Family + fa04 Matrix Orbital VK/LK204 Family + fa20 Ross-Tech HEX-USB + fc08 Crystalfontz CFA-632 USB LCD + fc09 Crystalfontz CFA-634 USB LCD + fc0b Crystalfontz CFA-633 USB LCD + fc0c Crystalfontz CFA-631 USB LCD + fc0d Crystalfontz CFA-635 USB LCD + fc82 SEMC DSS-20/DSS-25 SyncStation + fd48 ShipModul MiniPlex-4xUSB NMEA Multiplexer + fd49 ShipModul MiniPlex-4xUSB-AIS NMEA Multiplexer + fd4b ShipModul MiniPlex NMEA Multiplexer + ff08 ToolHouse LoopBack Adapter + ff18 ScienceScope Logbook ML + ff19 Logbook Bus + ff1a Logbook Bus + ff1b Logbook Bus + ff1c ScienceScope Logbook LS + ff1d ScienceScope Logbook HS + ff1e Logbook Bus + ff1f Logbook Bus +0404 NCR Corp. + 0202 78XX Scanner + 0203 78XX Scanner - Embedded System + 0310 K590 Printer, Self-Service + 0311 7167 Printer, Receipt/Slip + 0312 7197 Printer Receipt + 0320 5932-USB Keyboard + 0321 5953-USB Dynakey + 0322 5932-USB Enhanced Keyboard + 0323 5932-USB Enhanced Keyboard, Flash-Recovery/Download + 0324 5953-USB Enhanced Dynakey + 0325 5953-USB Enhanced Dynakey Flash-Recovery/Download + 0328 K016: USB-MSR ISO 3-track MSR: POS Standard (See HID pages) + 0329 K018: USB-MSR JIS 2-Track MSR: POS Standard + 032a K016: USB-MSR ISO 3-Track MSR: HID Keyboard Mode + 032b K016/K018: USB-MSR Flash-Recovery/Download +0405 Synopsys, Inc. +0406 Fujitsu-ICL Computers +0407 Fujitsu Personal Systems, Inc. +0408 Quanta Computer, Inc. + 0103 FV TouchCam N1 (Audio) + 030c HP Webcam + 03b2 HP Webcam + 03f4 HP Webcam + 1030 FV TouchCam N1 (Video) + 3000 Optical dual-touch panel + 3001 Optical Touch Screen + a060 HD Webcam +0409 NEC Corp. + 0011 PC98 Series Layout Keyboard Mouse + 0012 ATerm IT75DSU ISDN TA + 0014 Japanese Keyboard + 0019 109 Japanese Keyboard with Bus-Powered Hub + 001a PC98 Series Layout Keyboard with Bus-Powered Hub + 0025 Mini Keyboard with Bus-Powered Hub + 0027 MultiSync Monitor + 002c Clik!-USB Drive + 0034 109 Japanese Keyboard with One-touch start buttons + 003f Wireless Keyboard with One-touch start buttons + 0040 Floppy + 004e SuperScript 1400 Series + 004f Wireless Keyboard with One-touch start buttons + 0050 7-port hub + 0058 HighSpeed Hub + 0059 HighSpeed Hub + 005a HighSpeed Hub + 006a Conceptronic USB Harddisk Box + 007d MINICUBE2 + 007e PG-FP5 Flash Memory Programmer + 0081 SuperScript 1400 Series + 0082 SuperScript 1400 Series + 0094 Japanese Keyboard with One-touch start buttons + 0095 Japanese Keyboard + 00a9 AtermIT21L 128K Support Standard + 00aa AtermITX72 128K Support Standard + 00ab AtermITX62 128K Support Standard + 00ac AtermIT42 128K Support Standard + 00ae INSMATEV70G-MAX Standard + 00af AtermITX70 128K Support Standard + 00b0 AtermITX80 128K Support Standard + 00b2 AtermITX80D 128K Support Standard + 00c0 Wireless Remocon + 00f7 Smart Display PK-SD10 + 011d e228 Mobile Phone + 0203 HID Audio Controls + 021d Aterm WL54SU2 802.11g Wireless Adapter [Atheros AR5523] + 0248 Aterm PA-WL54GU + 0249 Aterm WL300NU-G + 02b4 Aterm WL300NU-AG + 02b6 Aterm WL300NU-GS 802.11n Wireless Adapter + 02bc Computer Monitor + 0300 LifeTouch Note + 0301 LifeTouch Note (debug mode) + 55aa Hub + 55ab Hub [iMac/iTouch kbd] + 8010 Intellibase Hub + 8011 Intellibase Hub + efbe P!cty 900 [HP DJ] + f0be P!cty 920 [HP DJ 812c] +040a Kodak Co. + 0001 DVC-323 + 0002 DVC-325 + 0100 DC-220 + 0110 DC-260 + 0111 DC-265 + 0112 DC-290 + 0120 DC-240 + 0121 DC-240 (PTP firmware) + 0130 DC-280 + 0131 DC-5000 + 0132 DC-3400 + 0140 DC-4800 + 0160 DC4800 + 0170 DX3900 + 0200 Digital Camera + 0300 EZ-200 + 0400 MC3 + 0402 Digital Camera + 0403 Z7590 + 0500 DX3500 + 0510 DX3600 + 0525 DX3215 + 0530 DX3700 + 0535 EasyShare CX4230 Camera + 0540 LS420 + 0550 DX4900 + 0555 DX4330 + 0560 CX4200 + 0565 CX4210 + 0566 CX4300 + 0567 LS753 + 0568 LS443 + 0569 LS663 + 0570 DX6340 + 0571 CX6330 + 0572 DX6440 + 0573 CX6230 + 0574 CX6200 + 0575 DX6490 + 0576 DX4530 + 0577 DX7630 + 0578 CX7300/CX7310 + 0579 CX7220 + 057a CX7330 + 057b CX7430 + 057c CX7530 + 057d DX7440 + 057e C300 + 057f DX7590 + 0580 Z730 + 0581 Digital Camera + 0582 Digital Camera + 0583 Digital Camera + 0584 CX6445 + 0585 Digital Camera + 0586 CX7525 + 0587 Digital Camera + 0588 Digital Camera + 0589 EasyShare C360 + 058a C310 + 058b Digital Camera + 058c C330 + 058d C340 + 058e V530 + 058f V550 + 0590 Digital Camera + 0591 Digital Camera + 0592 Digital Camera + 0593 Digital Camera + 0594 Digital Camera + 0595 Digital Camera + 0596 Digital Camera + 0597 Digital Camera + 0598 EASYSHARE M1033 digital camera + 0599 Digital Camera + 059a Digital Camera + 059b Digital Camera + 059c Digital Camera + 059d Digital Camera + 059e Digital Camera + 059f Digital Camera + 05a0 Digital Camera + 05a1 Digital Camera + 05a2 Digital Camera + 05a3 Digital Camera + 05a4 Digital Camera + 05a5 Digital Camera + 05a6 Digital Camera + 05a7 Digital Camera + 05a8 Digital Camera + 05a9 Digital Camera + 05aa Digital Camera + 05ab Digital Camera + 05ac Digital Camera + 05ad Digital Camera + 05ae Digital Camera + 05af Digital Camera + 05b0 Digital Camera + 05b1 Digital Camera + 05b2 Digital Camera + 05b3 EasyShare Z710 Camera + 05b4 Digital Camera + 05b5 Digital Camera + 05b6 Digital Camera + 05b7 Digital Camera + 05b8 Digital Camera + 05b9 Digital Camera + 05ba Digital Camera + 05bb Digital Camera + 05bc Digital Camera + 05bd Digital Camera + 05be Digital Camera + 05bf Digital Camera + 05c0 Digital Camera + 05c1 Digital Camera + 05c2 Digital Camera + 05c3 Digital Camera + 05c4 Digital Camera + 05c5 Digital Camera + 05c8 EASYSHARE Z1485 IS Digital Camera + 05d3 EasyShare M320 Camera + 05d4 EasyShare C180 Digital Camera + 1001 EasyShare SV811 Digital Picture Frame + 4000 InkJet Color Printer + 4021 Photo Printer 6800 + 4022 1400 Digital Photo Printer + 402b Photo Printer 6850 + 402e 605 Photo Printer + 4034 805 Photo Printer + 4035 7000 Photo Printer + 4037 7010 Photo Printer + 4038 7015 Photo Printer + 404d 8810 Photo Printer + 404f 305 Photo Printer + 4056 ESP 7200 Series AiO + 4109 EasyShare Printer Dock Series 3 + 410d EasyShare G600 Printer Dock + 5010 Wireless Adapter + 5012 DBT-220 Bluetooth Adapter + 6001 i30 + 6002 i40 + 6003 i50 + 6004 i60 + 6005 i80 + 6029 i900 + 602a i900 +040b Weltrend Semiconductor + 0a68 Func MS-3 gaming mouse [WT6573F MCU] + 2367 Human Interface Device [HP CalcPad 200 Calculator and Numeric Keypad] + 6510 Weltrend Bar Code Reader + 6520 Xploder Xbox Memory Unit (8MB) + 6533 Speed-Link Competition Pro + 6543 Manhattan Magnetic Card Strip Reader +040c VTech Computers, Ltd +040d VIA Technologies, Inc. + 3184 VNT VT6656 USB-802.11 Wireless LAN Adapter + 340f Audinst HUD-mx2 + 6205 USB 2.0 Card Reader +040e MCCI +040f Echo Speech Corp. +0411 BUFFALO INC. (formerly MelCo., Inc.) + 0001 LUA-TX Ethernet [pegasus] + 0005 LUA-TX Ethernet + 0006 WLI-USB-L11 Wireless LAN Adapter + 0009 LUA2-TX Ethernet + 000b WLI-USB-L11G-WR Wireless LAN Adapter + 000d WLI-USB-L11G Wireless LAN Adapter + 0012 LUA-KTX Ethernet + 0013 USB2-IDE Adapter + 0016 WLI-USB-S11 802.11b Adapter + 0018 USB2-IDE Adapter + 001c USB-IDE Bridge: DUB-PxxG + 0027 WLI-USB-KS11G 802.11b Adapter + 002a SMSC USB97C202 "HD-HB300V2-EU" + 003d LUA-U2-KTX Ethernet + 0044 WLI-USB-KB11 Wireless LAN Adapter + 004b WLI-USB-G54 802.11g Adapter [Broadcom 4320 USB] + 004d WLI-USB-B11 Wireless LAN Adapter + 0050 WLI2-USB2-G54 Wireless LAN Adapter + 005e WLI-U2-KG54-YB WLAN + 0065 Python2 WDM Encoder + 0066 WLI-U2-KG54 WLAN + 0067 WLI-U2-KG54-AI WLAN + 006e LUA-U2-GT 10/100/1000 Ethernet Adapter + 0089 RUF-C/U2 Flash Drive + 008b Nintendo Wi-Fi + 0091 WLI-U2-KAMG54 Wireless LAN Adapter + 0092 WLI-U2-KAMG54 Bootloader + 0097 WLI-U2-KG54-BB + 00a9 WLI-U2-AMG54HP Wireless LAN Adapter + 00aa WLI-U2-AMG54HP Bootloader + 00b3 PC-OP-RS1 RemoteStation + 00bc WLI-U2-KG125S 802.11g Adapter [Broadcom 4320 USB] + 00ca 802.11n Network Adapter + 00cb WLI-U2-G300N 802.11n Adapter + 00d8 WLI-U2-SG54HP + 00d9 WLI-U2-G54HP + 00da WLI-U2-KG54L 802.11bg [ZyDAS ZD1211B] + 00db External Hard Drive HD-PF32OU2 [Buffalo Ministation] + 00e8 WLI-UC-G300N Wireless LAN Adapter [Ralink RT2870] + 00f9 Portable DVD Writer (DVSM-PL58U2) + 0105 External Hard Drive HD-CEU2 [Drive Station] + 012c SATA Bridge + 012e WLI-UC-AG300N Wireless LAN Adapter + 0148 WLI-UC-G300HP Wireless LAN Adapter + 0150 WLP-UC-AG300 Wireless LAN Adapter + 0157 External Hard Drive HD-PEU2 + 0158 WLI-UC-GNHP Wireless LAN Adapter + 015d WLI-UC-GN Wireless LAN Adapter [Ralink RT3070] + 016f WLI-UC-G301N Wireless LAN Adapter [Ralink RT3072] + 017f Sony UWA-BR100 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] + 019e WLI-UC-GNP Wireless LAN Adapter + 01a1 MiniStation Metro + 01a2 WLI-UC-GNM Wireless LAN Adapter [Ralink RT8070] + 01ba SATA Bridge + 01dc Ultra-Slim Portable DVD Writer (DVSM-PC58U2V) + 01de External Hard Drive HD-PCTU3 [Buffalo MiniStation] + 01ea SATA Bridge + 01ee WLI-UC-GNM2 Wireless LAN Adapter [Ralink RT3070] + 01f1 SATA Adapter [HD-LBU3] + 01fd WLI-UC-G450 Wireless LAN Adapter + 027e HD-LCU3 +0412 Award Software International +0413 Leadtek Research, Inc. + 1310 WinFast TV - NTSC + FM + 1311 WinFast TV - NTSC + MTS + FM + 1312 WinFast TV - PAL BG + FM + 1313 WinFast TV - PAL BG+TXT + FM + 1314 WinFast TV Audio - PHP PAL I + 1315 WinFast TV Audio - PHP PAL I+TXT + 1316 WinFast TV Audio - PHP PAL DK + 1317 WinFast TV Audio - PHP PAL DK+TXT + 1318 WinFast TV - PAL I/DK + FM + 1319 WinFast TV - PAL N + FM + 131a WinFast TV Audio - PHP SECAM LL + 131b WinFast TV Audio - PHP SECAM LL+TXT + 131c WinFast TV Audio - PHP SECAM DK + 131d WinFast TV - SECAM DK + TXT + FM + 131e WinFast TV - NTSC Japan + FM + 1320 WinFast TV - NTSC + 1321 WinFast TV - NTSC + MTS + 1322 WinFast TV - PAL BG + 1323 WinFast TV - PAL BG+TXT + 1324 WinFast TV Audio - PHP PAL I + 1325 WinFast TV Audio - PHP PAL I+TXT + 1326 WinFast TV Audio - PHP PAL DK + 1327 WinFast TV Audio - PHP PAL DK+TXT + 1328 WinFast TV - PAL I/DK + 1329 WinFast TV - PAL N + 132a WinFast TV Audio - PHP SECAM LL + 132b WinFast TV Audio - PHP SECAM LL+TXT + 132c WinFast TV Audio - PHP SECAM DK + 132d WinFast TV - SECAM DK + TXT + 132e WinFast TV - NTSC Japan + 6023 EMP Audio Device + 6024 WinFast PalmTop/Novo TV Video + 6025 WinFast DTV Dongle (cold state) + 6026 WinFast DTV Dongle (warm state) + 6029 WinFast DTV Dongle Gold + 6125 WinFast DTV Dongle + 6126 WinFast DTV Dongle BDA Driver + 6a03 RTL2832 [WinFast DTV Dongle Mini] + 6f00 WinFast DTV Dongle (STK7700P based) +0414 Giga-Byte Technology Co., Ltd +0416 Winbond Electronics Corp. + 0035 W89C35 802.11bg WLAN Adapter + 0101 Hub + 0961 AVL Flash Card Reader + 3810 Smart Card Controller + 3811 Generic Controller - Single interface + 3812 Smart Card Controller_2Interface + 3813 Panel Display + 5011 Virtual Com Port + 5518 4-Port Hub + 551a PC Sync Keypad + 551b PC Async Keypad + 551c Sync Tenkey + 551d Async Tenkey + 551e Keyboard + 551f Keyboard w/ Sys and Media + 5521 Keyboard + 6481 16-bit Scanner + 7721 Memory Stick Reader/Writer + 7722 Memory Stick Reader/Writer + 7723 SD Card Reader + c141 Barcode Scanner +0417 Symbios Logic +0418 AST Research +0419 Samsung Info. Systems America, Inc. + 0001 IrDA Remote Controller / Creative Cordless Mouse + 0600 Desktop Wireless 6000 + 2694 Laila + 3001 Xerox P1202 Laser Printer + 3003 Olivetti PG L12L + 3201 Docuprint P8ex + 3404 SCX-5x12 series + 3406 MFP 830 series + 3407 ML-912 + 3601 InkJet Color Printer + 3602 InkJet Color Printer + 4602 Remote NDIS Network Device + 8001 Hub + 8002 SyncMaster HID Monitor Control + aa03 SDAS-3 MP3 Player +041a Phoenix Technologies, Ltd +041b d'TV +041d S3, Inc. +041e Creative Technology, Ltd + 0414 HS-720 Headset + 1002 Nomad II + 1003 Blaster GamePad Cobra + 1050 GamePad Cobra + 1053 Mouse Gamer HD7600L + 200c MuVo V100 + 2020 Zen X-Fi 2 + 2029 ZiiO + 2801 Prodikeys PC-MIDI multifunction keyboard + 3000 SoundBlaster Extigy + 3002 SB External Composite Device + 3010 SoundBlaster MP3+ + 3014 SB External Composite Device + 3015 Sound Blaster Digital Music LX + 3020 SoundBlaster Audigy 2 NX + 3030 SB External Composite Device + 3040 SoundBlaster Live! 24-bit External SB0490 + 3060 Sound Blaster Audigy 2 ZS External + 3061 SoundBlaster Audigy 2 ZS Video Editor + 3090 Sound Blaster Digital Music SX + 30d0 Xmod + 30d3 Sound Blaster Play! + 3100 IR Receiver (SB0540) + 3121 WoW tap chat + 3220 Sound Blaster Tactic(3D) Sigma sound card + 3232 Sound Blaster Premium HD [SBX] + 3237 SB X-Fi Surround 5.1 Pro + 3f00 E-Mu Xboard 25 MIDI Controller + 3f02 E-Mu 0202 + 3f04 E-Mu 0404 + 3f07 E-Mu Xmidi 1x1 + 3f0e Xmidi 1x1 Tab + 4003 VideoBlaster Webcam Go Plus [W9967CF] + 4004 Nomad II MG + 4005 Webcam Blaster Go ES + 4007 Go Mini + 400a PC-Cam 300 + 400b PC-Cam 600 + 400c Webcam 5 [pwc] + 400d Webcam PD1001 + 400f PC-CAM 550 (Composite) + 4011 Webcam PRO eX + 4012 PC-CAM350 + 4013 PC-Cam 750 + 4015 CardCam Value + 4016 CardCam + 4017 Webcam Mobile [PD1090] + 4018 Webcam Vista [PD1100] + 4019 Audio Device + 401a Webcam Vista [PD1100] + 401c Webcam NX [PD1110] + 401d Webcam NX Ultra + 401e Webcam NX Pro + 401f Webcam Notebook [PD1171] + 4020 Webcam NX + 4021 Webcam NX Ultra + 4022 Webcam NX Pro + 4028 Vista Plus cam [VF0090] + 4029 Webcam Live! + 402f DC-CAM 3000Z + 4034 Webcam Instant + 4035 Webcam Instant + 4036 Webcam Live!/Live! Pro + 4037 Webcam Live! + 4038 ORITE CCD Webcam [PC370R] + 4039 Webcam Live! Effects + 403a Webcam NX Pro 2 + 403b Creative Webcam Vista [VF0010] + 403c Webcam Live! Ultra + 403d Webcam Notebook Ultra + 403e Webcam Vista Plus + 4041 Webcam Live! Motion + 4043 Vibra Plus Webcam + 4045 Live! Cam Voice + 4049 Live! Cam Voice + 4051 Live! Cam Notebook Pro [VF0250] + 4052 Live! Cam Vista IM + 4053 Live! Cam Video IM + 4054 Live! Cam Video IM + 4055 Live! Cam Video IM Pro + 4056 Live! Cam Video IM Pro + 4057 Live! Cam Optia + 4058 Live! Cam Optia AF + 405f WebCam Vista (VF0330) + 4061 Live! Cam Notebook Pro [VF0400] + 4063 Live! Cam Video IM Pro + 4068 Live! Cam Notebook [VF0470] + 406c Live! Cam Sync [VF0520] + 4083 Live! Cam Socialize [VF0640] + 4087 Live! Cam Socialize HD 1080 [VF0680] + 4088 Live! Cam Chat HD [VF0700] + 4095 Live! Cam Sync HD [VF0770] + 4097 Live! Cam Chat HD [VF0700] + 4100 Nomad Jukebox 2 + 4101 Nomad Jukebox 3 + 4102 NOMAD MuVo^2 + 4106 Nomad MuVo + 4107 NOMAD MuVo + 4108 Nomad Jukebox Zen + 4109 Nomad Jukebox Zen NX + 410b Nomad Jukebox Zen USB 2.0 + 410c Nomad MuVo NX + 410f NOMAD MuVo^2 (Flash) + 4110 Nomad Jukebox Zen Xtra + 4111 Dell Digital Jukebox + 4116 MuVo^2 + 4117 Nomad MuVo TX + 411b Zen Touch + 411c Nomad MuVo USB 2.0 + 411d Zen + 411e Zen Micro + 4120 Nomad MuVo TX FM + 4123 Zen Portable Media Center + 4124 MuVo^2 FM (uHDD) + 4126 Dell DJ (2nd gen) + 4127 Dell DJ + 4128 NOMAD Jukebox Zen Xtra (mtp) + 412b MuVo N200 with FM radio + 412f Dell Digital Jukebox 2.Gen + 4130 Zen Micro (mtp) + 4131 DAP-HD0014 [Zen Touch] (MTP) + 4133 Mass Storage Device + 4134 Zen Neeon + 4136 Zen Sleek + 4137 Zen Sleek (mtp) + 4139 Zen Nano Plus + 413c Zen MicroPhoto + 4150 Zen V (MTP) + 4151 Zen Vision:M (mtp) + 4152 Zen V Plus + 4153 Zen Vision W + 4154 Zen Stone + 4155 Zen Stone plus + 4157 Zen (MTP) + 500f Broadband Blaster 8012U-V + 5015 TECOM Bluetooth Device + ffff Webcam Live! Ultra +041f LCS Telegraphics +0420 Chips and Technologies + 1307 Celly SIM Card Reader +0421 Nokia Mobile Phones + 0001 E61i (PC Suite mode) + 0018 6288 GSM Smartphone + 0019 6288 GSM Smartphone (imaging mode) + 001a 6288 GSM Smartphone (file transfer mode) + 0024 5610 XpressMusic (Storage mode) + 0025 5610 XpressMusic (PC Suite mode) + 0028 5610 XpressMusic (Imaging mode) + 002d 6120 Phone (Mass storage mode) + 002e 6120 Phone (Media-Player mode) + 002f 6120 Phone (PC-Suite mode) + 0042 E51 (PC Suite mode) + 0064 3109c GSM Phone + 006b 5310 Xpress Music (PC Suite mode) + 006c 5310 Xpress music (Storage mode) + 006d N95 (Storage mode) + 006e N95 (Multimedia mode) + 006f N95 (Printing mode) + 0070 N95 (PC Suite mode) + 0096 N810 Internet Tablet + 00aa E71 (Mass storage mode) + 00ab E71 (PC Suite mode) + 00e4 E71 (Media transfer mode) + 0103 ADL Flashing Engine AVALON Parent + 0104 ADL Re-Flashing Engine Parent + 0105 Nokia Firmware Upgrade Mode + 0106 ROM Parent + 010d E75 (Storage Mode) + 010e E75 (PC Suite mode) + 010f E75 (Media transfer mode) + 0110 E75 (Imaging Mode) + 0154 5800 XpressMusic (PC Suite mode) + 0155 5800 XpressMusic (Multimedia mode) + 0156 5800 XpressMusic (Storage mode) + 0157 5800 XpressMusic (Imaging mode) + 0199 6700 Classic (msc) + 019a 6700 Classic (PC Suite) + 019b 6700 Classic (mtp) + 01b0 6303 classic Phone (PC Suite mode) + 01b1 6303 classic Phone (Mass storage mode) + 01b2 6303 classic Phone (Printing and media mode) + 01c7 N900 (Storage Mode) + 01c8 N900 (PC-Suite Mode) + 0228 5530 XpressMusic + 023a 6730 Classic + 026a N97 (mass storage) + 026b N97 (Multimedia) + 026c N97 (PC Suite) + 026d N97 (Pictures) + 0295 660i/6600i Slide Phone (Mass Storage) + 0297 660i/6600i Slide Phone (Still Image) + 02e1 5230 (Storage mode) + 02e2 5230 (Multimedia mode) + 02e3 5230 (PC-Suite mode) + 02e4 5230 (Imaging mode) + 0360 C1-01 Ovi Suite Mode + 0396 C7-00 (Modem mode) + 03a4 C5 (Storage mode) + 03c0 C7-00 (Mass storage mode) + 03c1 C7-00 (Media transfer mode) + 03c2 Sim + 03cd C7-00 (Nokia Suite mode) + 03d1 N950 + 0400 7600 Phone Parent + 0401 6650 GSM Phone + 0402 6255 Phone Parent + 0404 5510 + 0405 9500 GSM Communicator + 0407 Music Player HDR-1(tm) + 040b N-Gage GSM Phone + 040d 6620 Phone Parent + 040e 6651 Phone Parent + 040f 6230 GSM Phone + 0410 6630 Imaging Smartphone + 0411 7610 Phone Parent + 0413 6260 Phone Parent + 0414 7370 + 0415 9300 GSM Smartphone + 0416 6170 Phone Parent + 0417 7270 Phone Parent + 0418 E70 (PC Suite mode) + 0419 E60 (PC Suite mode) + 041a 9500 GSM Communicator (RNDIS) + 041b 9300 GSM Smartphone (RNDIS) + 041c 7710 Phone Parent + 041d 6670 Phone Parent + 041e 6680 + 041f 6235 Phone Parent + 0421 3230 Phone Parent + 0422 6681 Phone Parent + 0423 6682 Phone Parent + 0428 6230i Modem + 0429 6230i MultiMedia Card + 0431 770 Internet Tablet + 0432 N90 Phone Parent + 0435 E70 (IP Passthrough/RNDIS mode) + 0436 E60 (IP Passthrough/RNDIS mode) + 0437 6265 Phone Parent + 043a N70 USB Phone Parent + 043b 3155 Phone Parent + 043c 6155 Phone Parent + 043d 6270 Phone Parent + 0443 N70 Phone Parent + 0444 N91 + 044c NM850iG Phone Parent + 044d E61 (PC Suite mode) + 044e E61 (Data Exchange mode) + 044f E61 (IP Passthrough/RNDIS mode) + 0453 9300 Phone Parent + 0456 6111 Phone Parent + 0457 6111 Phone (Printing mode) + 045a 6280 Phone Parent + 045d 6282 Phone Parent + 046e 6110 Navigator + 0471 6110 Navigator + 0485 MTP Device + 04b9 5300 + 04bc 5200 (Nokia mode) + 04bd 5200 (Storage mode) + 04be 5200 (MTP mode) + 04c3 N800 Internet Tablet + 04ce E90 Communicator (PC Suite mode) + 04cf E90 Communicator (Storage mode) + 04f0 Nokia N95 (PC Suite mode) + 04f9 6300 (PC Suite mode) + 0508 E65 (PC Suite mode) + 0509 E65 (Storage mode) + 0518 N9 Phone + 054d C2-01 + 0600 Digital Pen SU-1B + 0610 CS-15 (Internet Stick 3G modem) + 0661 Lumia 620/920 + 0662 301 Dual SIM (Mass Storage) + 0663 301 Dual SIM + 069a 130 [RM-1035] (Charging only) + 06fc Lumia 640 Phone + 0720 X (RM-980) + 0800 Connectivity Cable DKU-5 + 0801 Data Cable DKU-6 + 0802 CA-42 Phone Parent +0422 ADI Systems, Inc. +0423 Computer Access Technology Corp. + 000a NetMate Ethernet + 000c NetMate2 Ethernet + 000d USB Chief Analyzer + 0100 Generic Universal Protocol Analyzer + 0101 UPA USBTracer + 0200 Generic 10K Universal Protocol Analyzer + 020a PETracer ML + 0300 Generic Universal Protocol Analyzer + 0301 2500H Tracer Trainer + 030a PETracer x1 + 1237 Andromeda Hub +0424 Microchip Technology, Inc. (formerly SMSC) + 0001 Integrated Hub + 0140 LPC47M14x hub + 0acd Sitecom Internal Multi Memory reader/writer MD-005 + 0fdc Floppy + 10cd Sitecom Internal Multi Memory reader/writer MD-005 + 2020 USB Hub + 20cd Sitecom Internal Multi Memory reader/writer MD-005 + 20fc 6-in-1 Card Reader + 2134 Hub + 2228 9-in-2 Card Reader + 223a 8-in-1 Card Reader + 2503 USB 2.0 Hub + 2507 hub + 2512 USB 2.0 Hub + 2513 2.0 Hub + 2514 USB 2.0 Hub + 2517 Hub + 2524 USB MultiSwitch Hub + 2602 USB 2.0 Hub + 2640 USB 2.0 Hub + 2660 Hub + 2744 Hub + 274d HTC Hub Controller + 2807 Hub + 3fcc RME MADIface + 4041 Hub and media card controller + 4060 Ultra Fast Media Reader + 4064 Ultra Fast Media Reader + 4712 USB4712 high-speed hub + 4713 USB4715 high-speed hub (2 ports disabled) + 4714 USB4715 high-speed hub (1 port disabled) + 4715 USB4715 high-speed hub + 4910 USB491x hub integrated functions (primary) + 4912 USB4912 high-speed hub (1 port disabled) + 4914 USB4914 high-speed hub + 4916 USB4916 high-speed hub + 4920 USB491x hub integrated functions (secondary) + 4925 USB4925 high-speed hub (primary upstream) + 4927 USB4927 high-speed hub (primary upstream) + 4931 USB4925/4927 high-speed hub (secondary upstream) + 4940 USB47xx/49xx hub integrated WinUSB + 4942 USB47xx/49xx hub integrated I2S audio port + 4943 USB47xx/49xx hub integrated I2S audio + HID port + 4944 USB47xx/49xx hub integrated serial port + 4946 USB47xx/49xx hub integrated serial + I2S audio port + 4947 USB47xx/49xx hub integrated serial + I2S audio + HID port + 494a USB47xx/49xx hub integrated WinUSB + I2S audio port + 494b USB47xx/49xx hub integrated WinUSB + I2S audio + HID port + 494c USB47xx/49xx hub integrated WinUSB + serial port + 494e USB47xx/49xx hub integrated WinUSB + serial + I2S audio port + 494f USB47xx/49xx hub integrated WinUSB + serial + I2S audio + HID port + 5434 Hub + 5534 Hub + 5744 Hub + 5807 Hub + 7500 LAN7500 Ethernet 10/100/1000 Adapter + 9500 LAN9500/LAN9500i + 9512 SMC9512/9514 USB Hub + 9514 SMC9514 Hub + 9904 LAN9512/LAN9514 Ethernet 10/100 Adapter (SAL10) + 9e00 LAN9500A/LAN9500Ai + a700 2 Port Hub + ec00 SMSC9512/9514 Fast Ethernet Adapter +0425 Motorola Semiconductors HK, Ltd + 0101 G-Tech Wireless Mouse & Keyboard + f102 G-Tech U+P Wireless Mouse +0426 Integrated Device Technology, Inc. + 0426 WDM Driver +0427 Motorola Electronics Taiwan, Ltd +0428 Advanced Gravis Computer Tech, Ltd + 4001 GamePad Pro +0429 Cirrus Logic +042a Ericsson Austrian, AG +042b Intel Corp. + 9316 8x931Hx Customer Hub +042c Innovative Semiconductors, Inc. +042d Micronics +042e Acer, Inc. + 0380 MP3 Player +042f Molex, Inc. +0430 Sun Microsystems, Inc. + 0002 109 Keyboard + 0005 Type 6 Keyboard + 000a 109 Japanese Keyboard + 000b 109 Japanese Keyboard + 0082 109 Japanese Keyboard + 0083 109 Japanese Keyboard + 00a2 Type 7 Keyboard + 0100 3-button Mouse + 0502 Panasonic CF-19 HID Touch Panel + 100e 24.1" LCD Monitor v4 / FID-638 Mouse + 36ba Bus Powered Hub + a101 remote key/mouse for P3 chip + a102 remote key/mouse/storage for P3 chip + a103 remote storage for P3 chip + a111 remote keyboard for P4 chip + a112 remote mouse for P4 chip + a113 remote storage for P4 chip + a4a2 Ethernet (RNDIS and CDC ethernet) + cdab Raritan KVM dongle +0431 Itac Systems, Inc. + 0100 Mouse-Trak 3-button Track Ball +0432 Unisys Corp. + 0031 Document Processor +0433 Alps Electric, Inc. + 1101 IBM Game Controller + abab Keyboard +0434 Samsung Info. Systems America, Inc. +0435 Hyundai Electronics America +0436 Taugagreining HF + 0005 CameraMate (DPCM_USB) +0437 Framatome Connectors USA +0438 Advanced Micro Devices, Inc. + 7900 Root Hub +0439 Voice Technologies Group +043d Lexmark International, Inc. + 0001 Laser Printer + 0002 Optra E310 Printer + 0003 Laser Printer + 0004 Laser Printer + 0005 Laser Printer + 0006 Laser Printer + 0007 Laser Printer + 0008 Inkjet Color Printer + 0009 Optra S2450 Printer + 000a Laser Printer + 000b Inkjet Color Printer + 000c Optra E312 Printer + 000d Laser Printer + 000e Laser Printer + 000f Laser Printer + 0010 Laser Printer + 0011 Laser Printer + 0012 Inkjet Color Printer + 0013 Inkjet Color Printer + 0014 InkJet Color Printer + 0015 InkJet Color Printer + 0016 Z12 Color Jetprinter + 0017 Z32 printer + 0018 Z52 Printer + 0019 Forms Printer + 001a Z65 Printer + 001b InkJet Photo Printer + 001c Kodak Personal Picture Maker 200 Printer + 001d InkJet Color Printer + 001e InkJet Photo Printer + 001f Kodak Personal Picture Maker 200 Card Reader + 0020 Z51 Printer + 0021 Z33 Printer + 0022 InkJet Color Printer + 0023 Laser Printer + 0024 Laser Printer + 0025 InkJet Color Printer + 0026 InkJet Color Printer + 0027 InkJet Color Printer + 0028 InkJet Color Printer + 0029 Scan Print Copy + 002a Scan Print Copy + 002b Scan Print Copy + 002c Scan Print Copy + 002d X70/X73 Scan/Print/Copy + 002e Scan Print Copy + 002f Scan Print Copy + 0030 Scan Print Copy + 0031 Scan Print Copy + 0032 Scan Print Copy + 0033 Scan Print Copy + 0034 Scan Print Copy + 0035 Scan Print Copy + 0036 Scan Print Copy + 0037 Scan Print Copy + 0038 Scan Print Copy + 0039 Scan Print Copy + 003a Scan Print Copy + 003b Scan Print Copy + 003c Scan Print Copy + 003d X83 Scan/Print/Copy + 003e Scan Print Copy + 003f Scan Print Copy + 0040 Scan Print Copy + 0041 Scan Print Copy + 0042 Scan Print Copy + 0043 Scan Print Copy + 0044 Scan Print Copy + 0045 Scan Print Copy + 0046 Scan Print Copy + 0047 Scan Print Copy + 0048 Scan Print Copy + 0049 Scan Print Copy + 004a Scan Print Copy + 004b Scan Print Copy + 004c Scan Print Copy + 004d Laser Printer + 004e Laser Printer + 004f InkJet Color Printer + 0050 InkJet Color Printer + 0051 Laser Printer + 0052 Laser Printer + 0053 InkJet Color Printer + 0054 InkJet Color Printer + 0057 Z35 Printer + 0058 Laser Printer + 005a X63 + 005c InkJet Color Printer + 0060 X74/X75 Scanner + 0061 X74 Hub + 0065 X5130 + 0069 X74/X75 Printer + 006d X125 + 006e C510 + 0072 X6170 Printer + 0073 InkJet Color Printer + 0078 InkJet Color Printer + 0079 InkJet Color Printer + 007a Generic Hub + 007b InkJet Color Printer + 007c X1110/X1130/X1140/X1150/X1170/X1180/X1185 + 007d Photo 3150 + 008a 4200 series + 008b InkJet Color Printer + 008c to CF/SM/SD/MS Card Reader + 008e InkJet Color Printer + 008f X422 + 0091 Laser Printer E232 + 0093 X5250 + 0095 E220 Printer + 0096 2200 series + 0097 P6250 + 0098 7100 series + 009e P910 series Human Interface Device + 009f InkJet Color Printer + 00a9 IBM Infoprint 1410 MFP + 00ab InkJet Color Printer + 00b2 3300 series + 00b8 7300 series + 00b9 8300 series + 00ba InkJet Color Printer + 00bb 2300 series + 00bd Printing Support + 00be Printing Support + 00bf Printing Support + 00c0 6300 series + 00c1 4300 series + 00c7 Printing Support + 00c8 Printing Support + 00c9 Printing Support + 00cb Printing Support + 00cc E120(n) + 00d0 9300 series + 00d3 X340 Scanner + 00d4 X342n Scanner + 00d5 Printing Support + 00d6 X340 Scanner + 00e8 X642e + 00e9 2400 series + 00f6 3400 series + 00f7 InkJet Color Printer + 00ff InkJet Color Printer + 010b 2500 series + 010d 3500-4500 series + 010f 6500 series + 0142 X3650 (Printer, Scanner, Copier) + 01fa S310 series + 4303 Xerox WorkCentre Pro 412 +043e LG Electronics USA, Inc. + 3001 AN-WF100 802.11abgn Wireless Adapter [Broadcom BCM4323] + 3004 TWFM-B003D 802.11abgn Wireless Module [Broadcom BCM43236B] + 3101 AN-WF500 802.11abgn + BT Wireless Adapter [Broadcom BCM43242] + 42bd Flatron 795FT Plus Monitor + 4a4d Flatron 915FT Plus Monitor + 7001 MF-PD100 Soul Digital MP3 Player + 7013 MP3 Player + 70d7 Mouse Scanner LSM-150 [LG Smart Scan Mouse] + 70f5 External HDD + 8484 LPC-U30 Webcam II + 8585 LPC-UC35 Webcam + 8888 Electronics VCS Camera II(LPC-U20) + 9800 Remote Control Receiver_iMON + 9803 eHome Infrared Receiver + 9804 DMB Receiver Control + 9c01 LGE Sync +043f RadiSys Corp. +0440 Eizo Nanao Corp. +0441 Winbond Systems Lab. + 1456 Hub +0442 Ericsson, Inc. + abba Bluetooth Device +0443 Gateway, Inc. + 000e Multimedia Keyboard + 002e Millennium Keyboard +0445 Lucent Technologies, Inc. +0446 NMB Technologies Corp. + 6781 Keyboard with PS/2 Mouse Port + 6782 Keyboard +0447 Momentum Microsystems +0449 Duta Multi Robotik + 0128 Menengah + 0210 Dasar + 0612 Lanjutan +044a Shamrock Tech. Co., Ltd +044b WSI +044c CCL/ITRI +044d Siemens Nixdorf AG +044e Alps Electric Co., Ltd + 1104 Japanese Keyboard + 2002 MD-5500 Printer + 2014 Bluetooth Device + 3001 UGTZ4 Bluetooth + 3002 Bluetooth Device + 3003 Bluetooth Device + 3004 Bluetooth Adapter + 3005 Integrated Bluetooth Device + 3006 Bluetooth Adapter + 3007 Bluetooth Controller (ALPS/UGX) + 300c Bluetooth Controller (ALPS/UGPZ6) + 300d Bluetooth Controller (ALPS/UGPZ6) + 3010 Bluetooth Adapter + 3017 BCM2046 Bluetooth Device + ffff Compaq Bluetooth Multiport Module +044f ThrustMaster, Inc. + 0400 HOTAS Cougar + 0402 HOTAS Warthog Joystick + 0404 HOTAS Warthog Throttle + 044f GP XID + 0f00 Steering Wheel for Xbox + 0f03 Steering Wheel for Xbox + 0f07 Controller for Xbox + 0f0c Xbox Memory Unit (8MB) + 0f10 Modena GT Wheel + a003 Rage 3D Game Pad + a01b PK-GP301 Driving Wheel + a0a0 Top Gun Joystick + a0a1 Top Gun Joystick (rev2) + a0a3 Fusion Digital GamePad + a201 PK-GP201 PlayStick + b108 T-Flight Hotas X Flight Stick + b10a T.16000M Joystick + b203 360 Modena Pro Wheel + b300 Firestorm Dual Power + b303 FireStorm Dual Analog 2 + b304 Firestorm Dual Power + b307 vibrating Upad + b30b Wireless VibrationPad + b315 Firestorm Dual Analog 3 + b323 Dual Trigger 3-in-1 (PC Mode) + b324 Dual Trigger 3-in-1 (PS3 Mode) + b326 Gamepad GP XID + b351 F16 MFD 1 + b352 F16 MFD 2 + b365 UbiSoft UbiConnect + b603 force feedback Wheel + b605 force feedback Racing Wheel + b651 Ferrari GT Rumble Force Wheel + b653 RGT Force Feedback Clutch Racing Wheel + b654 Ferrari GT Force Feedback Wheel + b678 T.Flight Rudder Pedals + b679 T-Rudder + b687 TWCS Throttle + b700 Tacticalboard +0450 DFI, Inc. +0451 Texas Instruments, Inc. + 1234 Bluetooth Device + 1428 Hub + 1446 TUSB2040/2070 Hub + 16a6 BM-USBD1 BlueRobin RF heart rate sensor receiver + 2036 TUSB2036 Hub + 2046 TUSB2046 Hub + 2077 TUSB2077 Hub + 2f90 SM-USB-DIG + 3410 TUSB3410 Microcontroller + 3f00 OMAP1610 + 3f02 SMC WSKP100 Wi-Fi Phone + 505f TUSB5052 Serial + 5153 TUSB5052 Hub + 5409 Frontier Labs NEX IA+ Digital Audio Player + 6000 AU5 ADSL Modem (pre-reenum) + 6001 AU5 ADSL Modem + 6060 RNDIS/BeWAN ADSL2+ + 6070 RNDIS/BeWAN ADSL2+ + 625f TUSB6250 ATA Bridge + 8041 Hub + 8042 Hub + 8043 Hub + 8140 TUSB8041 4-Port Hub + 8142 TUSB8041 4-Port Hub + 926b TUSB9260 Boot Loader + bef3 CC1352R1 Launchpad + dbc0 Device Bay Controller + e001 GraphLink [SilverLink] + e003 TI-84 Plus Calculator + e004 TI-89 Titanium Calculator + e008 TI-84 Plus Silver Calculator + e00e TI-89 Titanium Presentation Link + e00f TI-84 Plus Presentation Link + e010 TI SmartPad Keyboard + e011 Nspire CAS+ prototype + e012 TI-Nspire Calculator + e013 Network Bridge + e01c Data Collection Sled [Nspire Lab Cradle, Nspire Datatracker Cradle] + e01f Python Adapter (firmware install mode) + e020 Python Adapter + e022 Nspire CX II + f430 MSP-FET430UIF JTAG Tool + f432 eZ430 Development Tool + ffff Bluetooth Device +0452 Mitsubishi Electronics America, Inc. + 0021 HID Monitor Controls + 0050 Diamond Pro 900u CRT Monitor + 0051 Integrated Hub + 0100 Control Panel for Leica TCS SP5 +0453 CMD Technology + 6781 NMB Keyboard + 6783 Chicony Composite Keyboard +0454 Vobis Microcomputer AG +0455 Telematics International, Inc. +0456 Analog Devices, Inc. + f000 FT2232 JTAG ICE [gnICE] + f001 FT2232H Hi-Speed JTAG ICE [gnICE+] +0457 Silicon Integrated Systems Corp. + 0150 Super Talent 1GB Flash Drive + 0151 Super Flash 1GB / GXT 64MB Flash Drive + 0162 SiS162 usb Wireless LAN Adapter + 0163 SiS163U 802.11 Wireless LAN Adapter + 0817 SiS-184-ASUS-4352.17 touch panel + 10e1 HID Touch Controller + 5401 Wireless Adapter RO80211GS-USB +0458 KYE Systems Corp. (Mouse Systems) + 0001 Mouse + 0002 Genius NetMouse Pro + 0003 Genius NetScroll+ + 0006 Easy Mouse+ + 000b NetMouse Wheel(P+U) + 000c TACOMA Fingerprint V1.06.01 + 000e Genius NetScroll Optical + 0013 TACOMA Fingerprint Mouse V1.06.01 + 001a Genius WebScroll+ + 002e NetScroll + Traveler / NetScroll 110 + 0036 Pocket Mouse LE + 0039 NetScroll+ Superior + 003a NetScroll+ Mini Traveler / Genius NetScroll 120 + 004c Slimstar Pro Keyboard + 0056 Ergo 300 Mouse + 0057 Enhanced Gaming Device + 0059 Enhanced Laser Device + 005a Enhanced Device + 005b Enhanced Device + 005c Enhanced Laser Gaming Device + 005d Enhanced Device + 0061 Bluetooth Dongle + 0066 Genius Traveler 1000 Wireless Mouse + 0072 Navigator 335 + 0083 Bluetooth Dongle + 0087 Ergo 525V Laser Mouse + 0089 Genius Traveler 350 + 00ca Pen Mouse + 0100 EasyPen Tablet + 0101 CueCat + 011b NetScroll T220 + 0186 Genius DX-120 Mouse + 1001 Joystick + 1002 Game Pad + 1003 Genius VideoCam + 1004 Flight2000 F-23 Joystick + 100a Aashima Technology Trust Sight Fighter Vibration Feedback Joystick + 2001 ColorPage-Vivid Pro Scanner + 2004 ColorPage-HR6 V1 Scanner + 2005 ColorPage-HR6/Vivid3 + 2007 ColorPage-HR6 V2 Scanner + 2008 ColorPage-HR6 V2 Scanner + 2009 ColorPage-HR6A Scanner + 2011 ColorPage-Vivid3x Scanner + 2012 Plustek Scanner + 2013 ColorPage-HR7 Scanner + 2014 ColorPage-Vivid4 + 2015 ColorPage-HR7LE Scanner + 2016 ColorPage-HR6X Scanner + 2017 ColorPage-Vivid3xe + 2018 ColorPage-HR7X + 2019 ColorPage-HR6X Slim + 201a ColorPage-Vivid4xe + 201b ColorPage-Vivid4x + 201c ColorPage-HR8 + 201d ColorPage-Vivid 1200 X + 201e ColorPage-Slim 1200 + 201f ColorPage-Vivid 1200 XE + 2020 ColorPage-Slim 1200 USB2 + 2021 ColorPage-SF600 + 3017 SPEED WHEEL 3 Vibration + 3018 Wireless 2.4Ghz Game Pad + 3019 10-Button USB Joystick with Vibration + 301a MaxFire G-12U Vibration + 301c Genius MaxFighter F-16U + 301d Genius MaxFire MiniPad + 400f Genius TVGo DVB-T02Q MCE + 4012 TVGo DVB-T03 [AF9015] + 5003 G-pen 560 Tablet + 5004 G-pen Tablet + 5005 Genius EasyPen M406 + 5012 Genius EasyPen M406W + 5014 Genius EasyPen 340 + 505e Genius iSlim 330 + 6001 GF3000F Ethernet Adapter + 7004 VideoCAM Express V2 + 7006 Dsc 1.3 Smart Camera Device + 7007 VideoCAM Web + 7009 G-Shot G312 Still Camera Device + 700c VideoCAM Web V3 + 700d G-Shot G511 Composite Device + 700f VideoCAM Web + 7012 WebCAM USB2.0 + 7014 VideoCAM Live V3 + 701c G-Shot G512 Still Camera + 7020 Sim 321C + 7025 Eye 311Q Camera + 7029 Genius Look 320s (SN9C201 + HV7131R) + 702f Genius Slim 322 + 7035 i-Look 325T Camera + 7045 Genius Look 1320 V2 + 704c Genius i-Look 1321 + 704d Slim 1322AF + 7055 Slim 2020AF camera + 705a Asus USB2.0 Webcam + 705c Genius iSlim 1300AF + 7061 Genius iLook 1321 V2 + 7066 Acer Crystal Eye Webcam + 7067 Genius iSlim 1300AF V2 + 7068 Genius eFace 1325R + 706d Genius iSlim 2000AF V2 + 7076 Genius FaceCam 312 + 7079 FaceCam 2025R + 707f TVGo DVB-T03 [RTL2832] + 7088 WideCam 1050 + 7089 Genius FaceCam 320 + 708c Genius WideCam F100 +0459 Adobe Systems, Inc. +045a SONICblue, Inc. + 07da Supra Express 56K modem + 0b4a SupraMax 2890 56K Modem [Lucent Atlas] + 0b68 SupraMax 56K Modem + 5001 Rio 600 MP3 Player + 5002 Rio 800 MP3 Player + 5003 Nike Psa/Play MP3 Player + 5005 Rio S10 MP3 Player + 5006 Rio S50 MP3 Player + 5007 Rio S35 MP3 Player + 5008 Rio 900 MP3 Player + 5009 Rio S30 MP3 Player + 500d Fuse MP3 Player + 500e Chiba MP3 Player + 500f Cali MP3 Player + 5010 Rio S11 MP3 Player + 501c Virgin MPF-1000 + 501d Rio Fuse + 501e Rio Chiba + 501f Rio Cali + 503f Cali256 MP3 Player + 5202 Rio Riot MP3 Player + 5210 Rio Karma Music Player + 5220 Rio Nitrus MP3 Player + 5221 Rio Eigen +045b Hitachi, Ltd + 0053 RX610 RX-Stick + 0229 mSATA Adapter [renkforce Pi-102] +045d Nortel Networks, Ltd +045e Microsoft Corp. + 0007 SideWinder Game Pad + 0008 SideWinder Precision Pro + 0009 IntelliMouse + 000b Natural Keyboard Elite + 000e SideWinder® Freestyle Pro + 0014 Digital Sound System 80 + 001a SideWinder Precision Racing Wheel + 001b SideWinder Force Feedback 2 Joystick + 001c Internet Keyboard Pro + 001d Natural Keyboard Pro + 001e IntelliMouse Explorer + 0023 Trackball Optical + 0024 Trackball Explorer + 0025 IntelliEye Mouse + 0026 SideWinder GamePad Pro + 0027 SideWinder PnP GamePad + 0028 SideWinder Dual Strike + 0029 IntelliMouse Optical + 002b Internet Keyboard Pro + 002d Internet Keyboard + 002f Integrated Hub + 0033 Sidewinder Strategic Commander + 0034 SideWinder Force Feedback Wheel + 0038 SideWinder Precision 2 + 0039 IntelliMouse Optical + 003b SideWinder Game Voice + 003c SideWinder Joystick + 0040 Wheel Mouse Optical + 0047 IntelliMouse Explorer 3.0 + 0048 Office Keyboard 1.0A + 0053 Optical Mouse + 0059 Wireless IntelliMouse Explorer + 005c Office Keyboard (106/109) + 005f Wireless MultiMedia Keyboard + 0061 Wireless MultiMedia Keyboard (106/109) + 0063 Wireless Natural MultiMedia Keyboard + 0065 Wireless Natural MultiMedia Keyboard (106/109) + 006a Wireless Optical Mouse (IntelliPoint) + 006d eHome Remote Control Keyboard keys + 006e MN-510 802.11b Wireless Adapter [Intersil ISL3873B] + 006f Smart Display Reference Device + 0070 Wireless MultiMedia Keyboard + 0071 Wireless MultiMedia Keyboard (106/109) + 0072 Wireless Natural MultiMedia Keyboard + 0073 Wireless Natural MultiMedia Keyboard (106/109) + 0079 IXI Ogo CT-17 handheld device + 007a 10/100 USB NIC + 007d Notebook Optical Mouse + 007e Wireless Transceiver for Bluetooth + 0080 Digital Media Pro Keyboard + 0083 Basic Optical Mouse + 0084 Basic Optical Mouse + 008a Wireless Optical Desktop Receiver 2.0A + 008b Dual Receiver Wireless Mouse (IntelliPoint) + 008c Wireless Intellimouse Explorer 2.0 + 0095 IntelliMouse Explorer 4.0 (IntelliPoint) + 009c Wireless Transceiver for Bluetooth 2.0 + 009d Wireless Optical Desktop 3.0 + 00a0 eHome Infrared Receiver + 00a4 Compact Optical Mouse, model 1016 + 00b0 Digital Media Pro Keyboard + 00b4 Digital Media Keyboard 1.0A + 00b9 Wireless Optical Mouse 3.0 + 00bb Fingerprint Reader + 00bc Fingerprint Reader + 00bd Fingerprint Reader + 00c2 MN-710 802.11g Wireless Adapter [Intersil ISL3886] + 00c9 MTP Device + 00ca Fingerprint Reader + 00cb Basic Optical Mouse v2.0 + 00ce Generic PPC Flash device + 00d1 Optical Mouse with Tilt Wheel + 00da eHome Infrared Receiver + 00db Natural Ergonomic Keyboard 4000 V1.0 + 00dd Comfort Curve Keyboard 2000 V1.0 + 00e1 Wireless Laser Mouse 6000 Receiver + 00f4 LifeCam VX-6000 (SN9C20x + OV9650) + 00f5 LifeCam VX-3000 + 00f6 Comfort Optical Mouse 1000 + 00f7 LifeCam VX-1000 + 00f8 LifeCam NX-6000 + 00f9 Wireless Desktop Receiver 3.1 + 0202 Xbox Controller + 0280 Xbox Memory Unit (8MB) + 0283 Xbox Communicator + 0284 Xbox DVD Playback Kit + 0285 Xbox Controller S + 0288 Xbox Controller S Hub + 0289 Xbox Controller S + 028b Xbox360 DVD Emulator + 028d Xbox360 Memory Unit 64MB + 028e Xbox360 Controller + 028f Xbox360 Wireless Controller + 0290 Xbox360 Performance Pipe (PIX) + 0291 Xbox 360 Wireless Receiver for Windows + 0292 Xbox360 Wireless Networking Adapter + 029c Xbox360 HD-DVD Drive + 029d Xbox360 HD-DVD Drive + 029e Xbox360 HD-DVD Memory Unit + 02a0 Xbox360 Big Button IR + 02a1 Xbox 360 Wireless Receiver for Windows + 02a8 Xbox360 Wireless N Networking Adapter [Atheros AR7010+AR9280] + 02ad Xbox NUI Audio + 02ae Xbox NUI Camera + 02b0 Xbox NUI Motor + 02b6 Xbox360 Bluetooth Wireless Headset + 02bb Kinect Audio + 02be Kinect for Windows NUI Audio + 02bf Kinect for Windows NUI Camera + 02c2 Kinect for Windows NUI Motor + 02d1 Xbox One Controller + 02d5 Xbox One Digital TV Tuner + 02dd Xbox One Controller (Firmware 2015) + 02e3 Xbox One Elite Controller + 02e6 Wireless XBox Controller Dongle + 02ea Xbox One S Controller + 02fd Xbox One S Controller [Bluetooth] + 0400 Windows Powered Pocket PC 2002 + 0401 Windows Powered Pocket PC 2002 + 0402 Windows Powered Pocket PC 2002 + 0403 Windows Powered Pocket PC 2002 + 0404 Windows Powered Pocket PC 2002 + 0405 Windows Powered Pocket PC 2002 + 0406 Windows Powered Pocket PC 2002 + 0407 Windows Powered Pocket PC 2002 + 0408 Windows Powered Pocket PC 2002 + 0409 Windows Powered Pocket PC 2002 + 040a Windows Powered Pocket PC 2002 + 040b Windows Powered Pocket PC 2002 + 040c Windows Powered Pocket PC 2002 + 040d Windows Powered Pocket PC 2002 + 040e Windows Powered Pocket PC 2002 + 040f Windows Powered Pocket PC 2002 + 0410 Windows Powered Pocket PC 2002 + 0411 Windows Powered Pocket PC 2002 + 0412 Windows Powered Pocket PC 2002 + 0413 Windows Powered Pocket PC 2002 + 0414 Windows Powered Pocket PC 2002 + 0415 Windows Powered Pocket PC 2002 + 0416 Windows Powered Pocket PC 2002 + 0417 Windows Powered Pocket PC 2002 + 0432 Windows Powered Pocket PC 2003 + 0433 Windows Powered Pocket PC 2003 + 0434 Windows Powered Pocket PC 2003 + 0435 Windows Powered Pocket PC 2003 + 0436 Windows Powered Pocket PC 2003 + 0437 Windows Powered Pocket PC 2003 + 0438 Windows Powered Pocket PC 2003 + 0439 Windows Powered Pocket PC 2003 + 043a Windows Powered Pocket PC 2003 + 043b Windows Powered Pocket PC 2003 + 043c Windows Powered Pocket PC 2003 + 043d Becker Traffic Assist Highspeed 7934 + 043e Windows Powered Pocket PC 2003 + 043f Windows Powered Pocket PC 2003 + 0440 Windows Powered Pocket PC 2003 + 0441 Windows Powered Pocket PC 2003 + 0442 Windows Powered Pocket PC 2003 + 0443 Windows Powered Pocket PC 2003 + 0444 Windows Powered Pocket PC 2003 + 0445 Windows Powered Pocket PC 2003 + 0446 Windows Powered Pocket PC 2003 + 0447 Windows Powered Pocket PC 2003 + 0448 Windows Powered Pocket PC 2003 + 0449 Windows Powered Pocket PC 2003 + 044a Windows Powered Pocket PC 2003 + 044b Windows Powered Pocket PC 2003 + 044c Windows Powered Pocket PC 2003 + 044d Windows Powered Pocket PC 2003 + 044e Windows Powered Pocket PC 2003 + 044f Windows Powered Pocket PC 2003 + 0450 Windows Powered Pocket PC 2003 + 0451 Windows Powered Pocket PC 2003 + 0452 Windows Powered Pocket PC 2003 + 0453 Windows Powered Pocket PC 2003 + 0454 Windows Powered Pocket PC 2003 + 0455 Windows Powered Pocket PC 2003 + 0456 Windows Powered Pocket PC 2003 + 0457 Windows Powered Pocket PC 2003 + 0458 Windows Powered Pocket PC 2003 + 0459 Windows Powered Pocket PC 2003 + 045a Windows Powered Pocket PC 2003 + 045b Windows Powered Pocket PC 2003 + 045c Windows Powered Pocket PC 2003 + 045d Windows Powered Pocket PC 2003 + 045e Windows Powered Pocket PC 2003 + 045f Windows Powered Pocket PC 2003 + 0460 Windows Powered Pocket PC 2003 + 0461 Windows Powered Pocket PC 2003 + 0462 Windows Powered Pocket PC 2003 + 0463 Windows Powered Pocket PC 2003 + 0464 Windows Powered Pocket PC 2003 + 0465 Windows Powered Pocket PC 2003 + 0466 Windows Powered Pocket PC 2003 + 0467 Windows Powered Pocket PC 2003 + 0468 Windows Powered Pocket PC 2003 + 0469 Windows Powered Pocket PC 2003 + 046a Windows Powered Pocket PC 2003 + 046b Windows Powered Pocket PC 2003 + 046c Windows Powered Pocket PC 2003 + 046d Windows Powered Pocket PC 2003 + 046e Windows Powered Pocket PC 2003 + 046f Windows Powered Pocket PC 2003 + 0470 Windows Powered Pocket PC 2003 + 0471 Windows Powered Pocket PC 2003 + 0472 Windows Powered Pocket PC 2003 + 0473 Windows Powered Pocket PC 2003 + 0474 Windows Powered Pocket PC 2003 + 0475 Windows Powered Pocket PC 2003 + 0476 Windows Powered Pocket PC 2003 + 0477 Windows Powered Pocket PC 2003 + 0478 Windows Powered Pocket PC 2003 + 0479 Windows Powered Pocket PC 2003 + 047a Windows Powered Pocket PC 2003 + 047b Windows Powered Pocket PC 2003 + 04c8 Windows Powered Smartphone 2002 + 04c9 Windows Powered Smartphone 2002 + 04ca Windows Powered Smartphone 2002 + 04cb Windows Powered Smartphone 2002 + 04cc Windows Powered Smartphone 2002 + 04cd Windows Powered Smartphone 2002 + 04ce Windows Powered Smartphone 2002 + 04d7 Windows Powered Smartphone 2003 + 04d8 Windows Powered Smartphone 2003 + 04d9 Windows Powered Smartphone 2003 + 04da Windows Powered Smartphone 2003 + 04db Windows Powered Smartphone 2003 + 04dc Windows Powered Smartphone 2003 + 04dd Windows Powered Smartphone 2003 + 04de Windows Powered Smartphone 2003 + 04df Windows Powered Smartphone 2003 + 04e0 Windows Powered Smartphone 2003 + 04e1 Windows Powered Smartphone 2003 + 04e2 Windows Powered Smartphone 2003 + 04e3 Windows Powered Smartphone 2003 + 04e4 Windows Powered Smartphone 2003 + 04e5 Windows Powered Smartphone 2003 + 04e6 Windows Powered Smartphone 2003 + 04e7 Windows Powered Smartphone 2003 + 04e8 Windows Powered Smartphone 2003 + 04e9 Windows Powered Smartphone 2003 + 04ea Windows Powered Smartphone 2003 + 04ec Windows Phone (Zune) + 063e Zune HD Media Player + 0640 KIN Phone + 0641 KIN Phone + 0642 KIN Phone + 0707 Wireless Laser Mouse 8000 + 0708 Transceiver v 3.0 for Bluetooth + 070a Charon Bluetooth Dongle (DFU) + 070f LifeChat LX-3000 Headset + 0710 Zune Media Player + 0713 Wireless Presenter Mouse 8000 + 0719 Xbox 360 Wireless Adapter + 071f Mouse/Keyboard 2.4GHz Transceiver V2.0 + 0721 LifeCam NX-3000 (UVC-compliant) + 0723 LifeCam VX-7000 (UVC-compliant) + 0724 SideWinder Mouse + 0728 LifeCam VX-5000 + 0730 Digital Media Keyboard 3000 + 0734 Wireless Optical Desktop 700 + 0736 Sidewinder X5 Mouse + 0737 Compact Optical Mouse 500 + 0745 Nano Transceiver v1.0 for Bluetooth + 074a LifeCam VX-500 [1357] + 0750 Wired Keyboard 600 + 0752 Wired Keyboard 400 + 075d LifeCam Cinema + 0761 LifeCam VX-2000 + 0765 Xbox360 Slim Internal Wireless Module (1400) [Marvell 88W8786U] + 0766 LifeCam VX-800 + 0768 Sidewinder X4 + 076c Comfort Mouse 4500 + 076d LifeCam HD-5000 + 0770 LifeCam VX-700 + 0772 LifeCam Studio + 0779 LifeCam HD-3000 + 077f LifeChat LX-6000 Headset + 0780 Comfort Curve Keyboard 3000 + 0797 Optical Mouse 200 + 0799 Surface Pro embedded keyboard + 07a5 Wireless Receiver 1461C + 07b2 2.4GHz Transceiver v8.0 used by mouse Wireless Desktop 900 + 07b6 Comfort Curve Keyboard 3000 + 07b9 Wired Keyboard 200 + 07c6 RTL8153 GigE [Surface Dock Ethernet] + 07ca Surface Pro 3 Docking Station Audio Device + 07cd Surface Keyboard + 07f8 Wired Keyboard 600 (model 1576) + 07fd Nano Transceiver 1.1 + 0900 Surface Dock Hub + 0901 Surface Dock Hub + 0902 Surface Dock Hub + 0903 Surface Dock Hub + 0904 Surface Dock Extender + 0905 Surface Dock Audio + 090b Hub + 090c SD Card + 091a Hub + 09c0 Surface Type Cover + 0a00 Lumia 950 Dual SIM (RM-1118) + 930a ISOUSB.SYS Intel 82930 Isochronous IO Test Board + ffca Catalina + fff8 Keyboard + ffff Windows CE Mass Storage +0460 Ace Cad Enterprise Co., Ltd + 0004 Tablet (5x3.75) + 0006 LCD Tablet (12x9) + 0008 Tablet (3x2.25) +0461 Primax Electronics, Ltd + 0010 HP PR1101U / Primax PMX-KPR1101U Keyboard + 0300 G2-300 Scanner + 0301 G2E-300 Scanner + 0302 G2-300 #2 Scanner + 0303 G2E-300 #2 Scanner + 0340 Colorado 9600 Scanner + 0341 Colorado 600u Scanner + 0345 Visioneer 6200 Scanner + 0346 Memorex Maxx 6136u Scanner + 0347 Primascan Colorado 2600u/Visioneer 4400 Scanner + 0360 Colorado 19200 Scanner + 0361 Colorado 1200u Scanner + 0363 VistaScan Astra 3600(ENG) + 0364 LG Electronics Scanworks 600U Scanner + 0365 VistaScan Astra 3600(ENG) + 0366 6400 + 0367 VistaScan Astra 3600(ENG) + 0371 Visioneer Onetouch 8920 Scanner + 0374 UMAX Astra 2500 + 0375 VistaScan Astra 3600(ENG) + 0377 Medion MD 5345 Scanner + 0378 VistaScan Astra 3600(ENG) + 037b Medion MD 6190 Scanner + 037c VistaScan Astra 3600(ENG) + 0380 G2-600 Scanner + 0381 ReadyScan 636i Scanner + 0382 G2-600 #2 Scanner + 0383 G2E-600 Scanner + 038a UMAX Astra 3000/3600 + 038b Xerox 2400 Onetouch + 038c UMAX Astra 4100 + 0392 Medion/Lifetec/Tevion/Cytron MD 6190 + 03a8 9420M + 0813 IBM UltraPort Camera + 0815 Micro Innovations IC200 Webcam + 0819 Fujifilm IX-30 Camera [webcam mode] + 081a Fujifilm IX-30 Camera [storage mode] + 081c Elitegroup ECS-C11 Camera + 081d Elitegroup ECS-C11 Storage + 0a00 Micro Innovations Web Cam 320 + 4d01 Comfort Keyboard / Kensington Orbit Elite + 4d02 Mouse-in-a-Box + 4d03 Kensington Mouse-in-a-box + 4d04 Mouse + 4d06 Balless Mouse (HID) + 4d0f HP Optical Mouse + 4d15 Dell Optical Mouse + 4d17 Optical Mouse + 4d20 HP Optical Mouse + 4d2a PoPo Elixir Mouse (HID) + 4d2b Wireless Laser Mini Mouse (HID) + 4d2c PoPo Mini Pointer Mouse (HID) + 4d2e Optical Mobile Mouse (HID) + 4d51 0Y357C PMX-MMOCZUL (B) [Dell Laser Mouse] + 4d62 HP Laser Mobile Mini Mouse + 4d75 Rocketfish RF-FLBTAD Bluetooth Adapter + 4d81 Dell N889 Optical Mouse + 4d91 Laser mouse M-D16DL + 4d92 Optical mouse M-D17DR + 4db1 Dell Laptop Integrated Webcam 2Mpix + 4de3 HP 5-Button Optical Comfort Mouse + 4de7 webcam + 4e04 Lenovo Keyboard KB1021 +0463 MGE UPS Systems + 0001 UPS + ffff UPS +0464 AMP/Tycoelectronics Corp. +0467 AT&T Paradyne +0468 Wieson Technologies Co., Ltd +046a Cherry GmbH + 0001 Keyboard + 0003 My3000 Hub + 0004 CyBoard Keyboard + 0005 XX33 SmartCard Reader Keyboard + 0008 Wireless Keyboard and Mouse + 0010 SmartBoard XX44 + 0011 G83 (RS 6000) Keyboard + 0021 CyMotion Expert Combo + 0023 Keyboard + 0027 CyMotion Master Solar Keyboard + 002a Wireless Mouse & Keyboard + 002d SmartTerminal XX44 + 003c Raptor Gaming Keyboard + 003d Raptor Gaming Keyboard Integrated Hub + 003e SmartTerminal ST-2xxx + 0041 G86 6240 Keyboard + 0080 eHealth Terminal ST 1503 + 0081 eHealth Keyboard G87 1504 + 00a1 SmartCard Reader Keyboard KC 1000 SC + 0106 R-300 Wireless Mouse Receiver + 010d MX-Board 3.0 Keyboard + b090 Keyboard + b091 Mouse +046b American Megatrends, Inc. + 0001 Keyboard + 0101 PS/2 Keyboard, Mouse & Joystick Ports + 0301 USB 1.0 Hub + 0500 Serial & Parallel Ports + ff10 Virtual Keyboard and Mouse +046c Toshiba Corp., Digital Media Equipment +046d Logitech, Inc. + 0082 Acer Aspire 5672 Webcam + 0200 WingMan Extreme Joystick + 0203 M2452 Keyboard + 0242 Chillstream for Xbox 360 + 0301 M4848 Mouse + 0401 HP PageScan + 0402 NEC PageScan + 040f Logitech/Storm PageScan + 0430 Mic (Cordless) + 0801 QuickCam Home + 0802 Webcam C200 + 0804 Webcam C250 + 0805 Webcam C300 + 0807 Webcam B500 + 0808 Webcam C600 + 0809 Webcam Pro 9000 + 080a Portable Webcam C905 + 080f Webcam C120 + 0810 QuickCam Pro + 0819 Webcam C210 + 081a Webcam C260 + 081b Webcam C310 + 081d HD Webcam C510 + 0820 QuickCam VC + 0821 HD Webcam C910 + 0823 HD Webcam B910 + 0825 Webcam C270 + 0826 HD Webcam C525 + 0828 HD Webcam B990 + 082b Webcam C170 + 082c HD Webcam C615 + 082d HD Pro Webcam C920 + 0830 QuickClip + 0836 B525 HD Webcam + 0837 BCC950 ConferenceCam + 0840 QuickCam Express + 0843 Webcam C930e + 0850 QuickCam Web + 085c C922 Pro Stream Webcam + 0870 QuickCam Express + 0890 QuickCam Traveler + 0892 OrbiCam + 0894 CrystalCam + 0895 QuickCam for Dell Notebooks + 0896 OrbiCam + 0897 QuickCam for Dell Notebooks + 0899 QuickCam for Dell Notebooks + 089d QuickCam E2500 series + 08a0 QuickCam IM + 08a1 QuickCam IM with sound + 08a2 Labtec Webcam Pro + 08a3 QuickCam QuickCam Chat + 08a6 QuickCam IM + 08a7 QuickCam Image + 08a9 Notebook Deluxe + 08aa Labtec Notebooks + 08ac QuickCam Cool + 08ad QuickCam Communicate STX + 08ae QuickCam for Notebooks + 08af QuickCam Easy/Cool + 08b0 QuickCam 3000 Pro [pwc] + 08b1 QuickCam Notebook Pro + 08b2 QuickCam Pro 4000 + 08b3 QuickCam Zoom + 08b4 QuickCam Zoom + 08b5 QuickCam Sphere + 08b9 QuickCam IM + 08bd Microphone (Pro 4000) + 08c0 QuickCam Pro 3000 + 08c1 QuickCam Fusion + 08c2 QuickCam PTZ + 08c3 Camera (Notebooks Pro) + 08c5 QuickCam Pro 5000 + 08c6 QuickCam for DELL Notebooks + 08c7 QuickCam OEM Cisco VT Camera II + 08c9 QuickCam Ultra Vision + 08ca Mic (Fusion) + 08cb Mic (Notebooks Pro) + 08cc Mic (PTZ) + 08ce QuickCam Pro 5000 + 08cf QuickCam UpdateMe + 08d0 QuickCam Express + 08d7 QuickCam Communicate STX + 08d8 QuickCam for Notebook Deluxe + 08d9 QuickCam IM/Connect + 08da QuickCam Messanger + 08dd QuickCam for Notebooks + 08e0 QuickCam Express + 08e1 Labtec Webcam + 08f0 QuickCam Messenger + 08f1 QuickCam Express + 08f2 Microphone (Messenger) + 08f3 QuickCam Express + 08f4 Labtec Webcam + 08f5 QuickCam Messenger Communicate + 08f6 QuickCam Messenger Plus + 0900 ClickSmart 310 + 0901 ClickSmart 510 + 0903 ClickSmart 820 + 0905 ClickSmart 820 + 0910 QuickCam Cordless + 0920 QuickCam Express + 0921 Labtec Webcam + 0922 QuickCam Live + 0928 QuickCam Express + 0929 Labtec Webcam Pro + 092a QuickCam for Notebooks + 092b Labtec Webcam Plus + 092c QuickCam Chat + 092d QuickCam Express / Go + 092e QuickCam Chat + 092f QuickCam Express Plus + 0950 Pocket Camera + 0960 ClickSmart 420 + 0970 Pocket750 + 0990 QuickCam Pro 9000 + 0991 QuickCam Pro for Notebooks + 0992 QuickCam Communicate Deluxe + 0994 QuickCam Orbit/Sphere AF + 09a1 QuickCam Communicate MP/S5500 + 09a2 QuickCam Communicate Deluxe/S7500 + 09a4 QuickCam E 3500 + 09a5 Quickcam 3000 For Business + 09a6 QuickCam Vision Pro + 09b0 Acer OrbiCam + 09b2 Fujitsu Webcam + 09c0 QuickCam for Dell Notebooks Mic + 09c1 QuickCam Deluxe for Notebooks + 0a01 USB Headset + 0a02 Premium Stereo USB Headset 350 + 0a03 Logitech USB Microphone + 0a04 V20 portable speakers (USB powered) + 0a07 Z-10 Speakers + 0a0b ClearChat Pro USB + 0a0c Clear Chat Comfort USB Headset + 0a13 Z-5 Speakers + 0a14 USB Headset + 0a15 G35 Headset + 0a17 G330 Headset + 0a1f G930 + 0a29 H600 [Wireless Headset] + 0a37 USB Headset H540 + 0a38 Headset H340 + 0a44 Headset H390 + 0a45 960 Headset + 0a4d G430 Surround Sound Gaming Headset + 0a5b G933 Wireless Headset Dongle + 0a66 [G533 Wireless Headset Dongle] + 0b02 C-UV35 [Bluetooth Mini-Receiver] (HID proxy mode) + 8801 Video Camera + b014 Bluetooth Mouse M336/M337/M535 + b305 BT Mini-Receiver + bfe4 Premium Optical Wheel Mouse + c000 N43 [Pilot Mouse] + c001 N48/M-BB48/M-UK96A [FirstMouse Plus] + c002 M-BA47 [MouseMan Plus] + c003 MouseMan + c004 WingMan Gaming Mouse + c005 WingMan Gaming Wheel Mouse + c00b MouseMan Wheel + c00c Optical Wheel Mouse + c00d MouseMan Wheel+ + c00e M-BJ58/M-BJ69 Optical Wheel Mouse + c00f MouseMan Traveler/Mobile + c011 Optical MouseMan + c012 Mouseman Dual Optical + c014 Corded Workstation Mouse + c015 Corded Workstation Mouse + c016 Optical Wheel Mouse + c018 Optical Wheel Mouse + c019 Optical Tilt Wheel Mouse + c01a M-BQ85 Optical Wheel Mouse + c01b MX310 Optical Mouse + c01c Optical Mouse + c01d MX510 Optical Mouse + c01e MX518 Optical Mouse + c024 MX300 Optical Mouse + c025 MX500 Optical Mouse + c030 iFeel Mouse + c031 iFeel Mouse+ + c032 MouseMan iFeel + c033 iFeel MouseMan+ + c034 MouseMan Optical + c035 Mouse + c036 Mouse + c037 Mouse + c038 Mouse + c03d M-BT96a Pilot Optical Mouse + c03e Premium Optical Wheel Mouse (M-BT58) + c03f M-BT85 [UltraX Optical Mouse] + c040 Corded Tilt-Wheel Mouse + c041 G5 Laser Mouse + c042 G3 Laser Mouse + c043 MX320/MX400 Laser Mouse + c044 LX3 Optical Mouse + c045 Optical Mouse + c046 RX1000 Laser Mouse + c047 Laser Mouse M-UAL120 + c048 G9 Laser Mouse + c049 G5 Laser Mouse + c050 RX 250 Optical Mouse + c051 G3 (MX518) Optical Mouse + c053 Laser Mouse + c054 Bluetooth mini-receiver + c058 M115 Mouse + c05a M90/M100 Optical Mouse + c05b M-U0004 810-001317 [B110 Optical USB Mouse] + c05d Optical Mouse + c05f M115 Optical Mouse + c061 RX1500 Laser Mouse + c062 M-UAS144 [LS1 Laser Mouse] + c063 DELL Laser Mouse + c064 M110 corded optical mouse (M-B0001) + c066 G9x Laser Mouse + c068 G500 Laser Mouse + c069 M-U0007 [Corded Mouse M500] + c06a USB Optical Mouse + c06b G700 Wireless Gaming Mouse + c06c Optical Mouse + c077 M105 Optical Mouse + c07c M-R0017 [G700s Rechargeable Gaming Mouse] + c07d G502 Mouse + c07e G402 Gaming Mouse + c080 G303 Gaming Mouse + c083 G403 Prodigy Gaming Mouse + c084 G203 Gaming Mouse + c101 UltraX Media Remote + c110 Harmony 785/880/885 Remote + c111 Harmony 525 Remote + c112 Harmony 890 Remote + c11f Harmony 900/1100 Remote + c121 Harmony One Remote + c122 Harmony 650/700 Remote + c124 Harmony 300/350 Remote + c125 Harmony 200 Remote + c126 Harmony Link + c129 Harmony Hub + c12b Harmony Touch/Ultimate Remote + c201 WingMan Extreme Joystick with Throttle + c202 WingMan Formula + c207 WingMan Extreme Digital 3D + c208 WingMan Gamepad Extreme + c209 WingMan Gamepad + c20a WingMan RumblePad + c20b WingMan Action Pad + c20c WingMan Precision + c20d WingMan Attack 2 + c20e WingMan Formula GP + c211 iTouch Cordless Receiver + c212 WingMan Extreme Digital 3D + c213 J-UH16 (Freedom 2.4 Cordless Joystick) + c214 ATK3 (Attack III Joystick) + c215 Extreme 3D Pro + c216 F310 Gamepad [DirectInput Mode] + c218 F510 Gamepad [DirectInput Mode] + c219 F710 Gamepad [DirectInput Mode] + c21a Precision Gamepad + c21c G13 Advanced Gameboard + c21d F310 Gamepad [XInput Mode] + c21e F510 Gamepad [XInput Mode] + c21f F710 Wireless Gamepad [XInput Mode] + c221 G11/G15 Keyboard / Keyboard + c222 G15 Keyboard / LCD + c223 G11/G15 Keyboard / USB Hub + c225 G11/G15 Keyboard / G keys + c226 G15 Refresh Keyboard + c227 G15 Refresh Keyboard + c228 G19 Gaming Keyboard + c229 G19 Gaming Keyboard Macro Interface + c22a Gaming Keyboard G110 + c22b Gaming Keyboard G110 G-keys + c22d G510 Gaming Keyboard + c22e G510 Gaming Keyboard onboard audio + c231 G13 Virtual Mouse + c245 G400 Optical Mouse + c246 Gaming Mouse G300 + c248 G105 Gaming Keyboard + c24a G600 Gaming Mouse + c24c G400s Optical Mouse + c24d G710 Gaming Keyboard + c24e G500s Laser Gaming Mouse + c281 WingMan Force + c283 WingMan Force 3D + c285 WingMan Strike Force 3D + c286 Force 3D Pro + c287 Flight System G940 + c291 WingMan Formula Force + c293 WingMan Formula Force GP + c294 Driving Force + c295 Momo Force Steering Wheel + c298 Driving Force Pro + c299 G25 Racing Wheel + c29b G27 Racing Wheel + c29c Speed Force Wireless Wheel for Wii + c2a0 Wingman Force Feedback Mouse + c2a1 WingMan Force Feedback Mouse + c2ab G13 Joystick + c301 iTouch Keyboard + c302 iTouch Pro Keyboard + c303 iTouch Keyboard + c305 Internet Keyboard + c307 Internet Keyboard + c308 Internet Navigator Keyboard + c309 Y-BF37 [Internet Navigator Keyboard] + c30a iTouch Composite + c30b NetPlay Keyboard + c30c Internet Keys (X) + c30d Internet Keys + c30e UltraX Keyboard (Y-BL49) + c30f Logicool HID-Compliant Keyboard (106 key) + c311 Y-UF49 [Internet Pro Keyboard] + c312 DeLuxe 250 Keyboard + c313 Internet 350 Keyboard + c315 Classic Keyboard 200 + c316 HID-Compliant Keyboard + c317 Wave Corded Keyboard + c318 Illuminated Keyboard + c31a Comfort Wave 450 + c31b Compact Keyboard K300 + c31c Keyboard K120 + c31d Media Keyboard K200 + c31f Comfort Keyboard K290 + c326 Washable Keyboard K310 + c328 Corded Keyboard K280e + c332 G502 Proteus Spectrum Optical Mouse + c335 G910 Orion Spectrum Mechanical Keyboard + c33a G413 Gaming Keyboard + c401 TrackMan Marble Wheel + c402 Marble Mouse (2-button) + c403 Turbo TrackMan Marble FX + c404 TrackMan Wheel + c408 Marble Mouse (4-button) + c501 Cordless Mouse Receiver + c502 Cordless Mouse & iTouch Keys + c503 Cordless Mouse+Keyboard Receiver + c504 Cordless Mouse+Keyboard Receiver + c505 Cordless Mouse+Keyboard Receiver + c506 MX700 Cordless Mouse Receiver + c508 Cordless Trackball + c509 Cordless Keyboard & Mouse + c50a Cordless Mouse + c50b Cordless Desktop Optical + c50c Cordless Desktop S510 + c50d Cordless Mouse + c50e Cordless Mouse Receiver + c510 Cordless Mouse + c512 LX-700 Cordless Desktop Receiver + c513 MX3000 Cordless Desktop Receiver + c514 Cordless Mouse + c515 Cordless 2.4 GHz Presenter Presentation remote control + c517 LX710 Cordless Desktop Laser + c518 MX610 Laser Cordless Mouse + c51a MX Revolution/G7 Cordless Mouse + c51b V220 Cordless Optical Mouse for Notebooks + c521 Cordless Mouse Receiver + c525 MX Revolution Cordless Mouse + c526 Nano Receiver + c529 Logitech Keyboard + Mice + c52b Unifying Receiver + c52d R700 Remote Presenter receiver + c52e MK260 Wireless Combo Receiver + c52f Unifying Receiver + c531 C-U0007 [Unifying Receiver] + c532 Unifying Receiver + c534 Unifying Receiver + c603 3Dconnexion Spacemouse Plus XT + c605 3Dconnexion CADman + c606 3Dconnexion Spacemouse Classic + c621 3Dconnexion Spaceball 5000 + c623 3Dconnexion Space Traveller 3D Mouse + c625 3Dconnexion Space Pilot 3D Mouse + c626 3Dconnexion Space Navigator 3D Mouse + c627 3Dconnexion Space Explorer 3D Mouse + c628 3Dconnexion Space Navigator for Notebooks + c629 3Dconnexion SpacePilot Pro 3D Mouse + c62b 3Dconnexion Space Mouse Pro + c640 NuLOOQ navigator + c702 Cordless Presenter + c703 Elite Keyboard Y-RP20 + Mouse MX900 (Bluetooth) + c704 diNovo Wireless Desktop + c705 MX900 Bluetooth Wireless Hub (C-UJ16A) + c707 Bluetooth wireless hub + c708 Bluetooth wireless hub + c709 BT Mini-Receiver (HCI mode) + c70a MX5000 Cordless Desktop + c70b BT Mini-Receiver (HID proxy mode) + c70c BT Mini-Receiver (HID proxy mode) + c70d Bluetooth wireless hub + c70e MX1000 Bluetooth Laser Mouse + c70f Bluetooth wireless hub + c712 Bluetooth wireless hub + c714 diNovo Edge Keyboard + c715 Bluetooth wireless hub + c71a Bluetooth wireless hub + c71d Bluetooth wireless hub + c71f diNovo Mini Wireless Keyboard + c720 Bluetooth wireless hub + ca03 MOMO Racing + ca04 Formula Vibration Feedback Wheel + ca84 Cordless Controller for Xbox + ca88 Thunderpad for Xbox + ca8a Precision Vibration Feedback Wheel for Xbox + caa3 DriveFX Racing Wheel + cab1 Cordless Keyboard for Wii HID Receiver + d001 QuickCam Pro + f301 Controller +046e Behavior Tech. Computer Corp. + 0100 Keyboard + 3001 Mass Storage Device + 3002 Mass Storage Device + 3003 Mass Storage Device + 3005 Mass Storage Device + 3008 Mass Storage Device + 5250 KeyMaestro Multimedia Keyboard + 5273 KeyMaestro Multimedia Keyboard + 52e6 Cordless Mouse + 5308 KeyMaestro Keyboard + 5408 KeyMaestro Multimedia Keyboard/Hub + 5500 Portable Keyboard 86+9 keys (Model 6100C US) + 5550 5 button optical mouse model M873U + 5720 Smart Card Reader + 6782 BTC 7932 mouse+keyboard +046f Crystal Semiconductor +0471 Philips (or NXP) + 0101 DSS350 Digital Speaker System + 0104 DSS330 Digital Speaker System [uda1321] + 0105 UDA1321 + 014f GoGear SA9200 + 0160 MP3 Player + 0161 MP3 Player + 0163 GoGear SA1100 + 0164 GoGear SA1110/02 + 0165 GoGear SA1330 + 0201 Hub + 0222 Creative Nomad Jukebox + 0302 PCA645VC Webcam [pwc] + 0303 PCA646VC Webcam [pwc] + 0304 Askey VC010 Webcam [pwc] + 0307 PCVC675K Webcam [pwc] + 0308 PCVC680K Webcam [pwc] + 030b PC VGA Camera (Vesta Fun) + 030c PCVC690K Webcam [pwc] + 0310 PCVC730K Webcam [pwc] + 0311 PCVC740K ToUcam Pro [pwc] + 0312 PCVC750K Webcam [pwc] + 0314 DMVC 1000K + 0316 DMVC 2000K Video Capture + 0321 FunCam + 0322 DMVC1300K PC Camera + 0325 SPC 200NC PC Camera + 0326 SPC 300NC PC Camera + 0327 Webcam SPC 6000 NC (Webcam w/ mic) + 0328 SPC 700NC PC Camera + 0329 SPC 900NC PC Camera / ORITE CCD Webcam(PC370R) + 032d SPC 210NC PC Camera + 032e SPC 315NC PC Camera + 0330 SPC 710NC PC Camera + 0331 SPC 1300NC PC Camera + 0332 SPC 1000NC PC Camera + 0333 SPC 620NC PC Camera + 0334 SPC 520/525NC PC Camera + 0401 Semiconductors CICT Keyboard + 0402 PS/2 Mouse on Semiconductors CICT Keyboard + 0406 15 inch Detachable Monitor + 0407 10 inch Mobile Monitor + 0408 SG3WA1/74 802.11b WLAN Adapter [Atmel AT76C503A] + 0471 Digital Speaker System + 0601 OVU1020 IR Dongle (Kbd+Mouse) + 0602 ATI Remote Wonder II Input Device + 0603 ATI Remote Wonder II Controller + 0608 eHome Infrared Receiver + 060a TSU9600 Remote Control + 060c Consumer Infrared Transceiver (HP) + 060d Consumer Infrared Transceiver (SRM5100) + 060e RF Dongle + 060f Consumer Infrared Transceiver + 0613 Infrared Transceiver + 0617 IEEE802.15.4 RF Dongle + 0619 TSU9400 Remote Control + 0666 Hantek DDS-3005 Arbitrary Waveform Generator + 0700 Semiconductors CICT Hub + 0701 150P1 TFT Display + 0809 AVNET Bluetooth Device + 0811 JR24 CDRW + 0814 DCCX38/P data cable + 0815 eHome Infrared Receiver + 0844 SA2111/02 1GB Flash Audio Player + 084a GoGear SA3125 + 084e GoGear SA60xx (mtp) + 0888 Hantek DDS-3005 Arbitrary Waveform Generator + 1103 Digital Speaker System + 1120 Creative Rhomba MP3 player + 1125 Nike psa[128max Player + 1137 HDD065 MP3 player + 1201 Arima Bluetooth Device + 1230 Wireless Adapter 11g + 1232 SNU6500 Wireless Adapter + 1233 Wireless Adapter Bootloader Download + 1236 SNU5600 802.11bg + 1237 TalkTalk SNU5630NS/05 802.11bg + 1552 ISP 1581 Hi-Speed USB MPEG2 Encoder Reference Kit + 1801 Diva MP3 player + 200a Wireless Network Adapter + 200f 802.11n Wireless Adapter + 2021 SDE3273FC/97 2.5" SATA HDD Enclosure [INIC-1608L] + 2022 GoGear SA52XX + 2034 Webcam SPC530NC + 2036 Webcam SPC1030NC + 203f TSU9200 Remote Control + 2046 TSU9800 Remote Control + 204e GoGear RaGa (SA1942/02) + 205e TSU9300 Remote Control + 206c MCE IR Receiver - Spinel plusf0r ASUS + 2070 GoGear Mix + 2076 GoGear Aria + 2079 GoGear Opus + 2088 MCE IR Receiver with ALS- Spinel plus for ASUS + 209e PTA01 Wireless Adapter + 20b6 GoGear Vibe + 20d0 SPZ2000 Webcam [PixArt PAC7332] + 20e3 GoGear Raga + 20e4 GoGear ViBE 8GB + 2160 Mio LINK Heart Rate Monitor + 21e0 GoGEAR Raga + 262c SPC230NC Webcam + 485d Senselock SenseIV v2.x + df55 LPCXpresso LPC-Link +0472 Chicony Electronics Co., Ltd + 0065 PFU-65 Keyboard [Chicony] + b086 Asus USB2.0 Webcam + b091 Webcam +0473 Sanyo Information Business Co., Ltd +0474 Sanyo Electric Co., Ltd + 0110 Digital Voice Recorder R200 + 0217 Xacti J2 + 022f C5 Digital Media Camera (mass storage mode) + 0230 C5 Digital Media Camera (PictBridge mode) + 0231 C5 Digital Media Camera (PC control mode) + 0401 Optical Drive + 0701 SCP-4900 Cellphone + 071f Usb Com Port Enumerator + 0722 W33SA Camera +0475 Relisys/Teco Information System + 0100 NEC Petiscan + 0103 Eclipse 1200U/Episode + 0210 Scorpio Ultra 3 +0476 AESP +0477 Seagate Technology, Inc. +0478 Connectix Corp. + 0001 QuickCam + 0002 QuickClip + 0003 QuickCam Pro +0479 Advanced Peripheral Laboratories +047a Semtech Corp. + 0004 ScreenCoder UR7HCTS2-USB +047b Silitek Corp. + 0001 Keyboard + 0002 Keyboard and Mouse + 0011 SK-1688U Keyboard + 00f9 SK-1789u Keyboard + 0101 BlueTooth Keyboard and Mouse + 020b SK-3105 SmartCard Reader + 050e Internet Compact Keyboard + 1000 Trust Office Scan USB 19200 + 1002 HP ScanJet 4300c Parallel Port +047c Dell Computer Corp. + ffff UPS Tower 500W LV +047d Kensington + 1001 Mouse*in*a*Box + 1002 Expert Mouse Pro + 1003 Orbit TrackBall + 1004 MouseWorks + 1005 TurboBall + 1006 TurboRing + 1009 Orbit TrackBall for Mac + 1012 PocketMouse + 1013 Mouse*in*a*Box Optical Pro + 1014 Expert Mouse Pro Wireless + 1015 Expert Mouse + 1016 ADB/USB Orbit + 1018 Studio Mouse + 101d Mouse*in*a*Box Optical Pro + 101e Studio Mouse Wireless + 101f PocketMouse Pro + 1020 Expert Mouse Trackball + 1021 Expert Mouse Wireless + 1022 Orbit Optical + 1023 Pocket Mouse Pro Wireless + 1024 PocketMouse + 1025 Mouse*in*a*Box Optical Elite Wireless + 1026 Pocket Mouse Pro + 1027 StudioMouse + 1028 StudioMouse Wireless + 1029 Mouse*in*a*Box Optical Elite + 102a Mouse*in*a*Box Optical + 102b PocketMouse + 102c Iridio + 102d Pilot Optical + 102e Pilot Optical Pro + 102f Pilot Optical Pro Wireless + 1042 Ci25m Notebook Optical Mouse [Diamond Eye Precision] + 1043 Ci65m Wireless Notebook Optical Mouse + 104a PilotMouse Mini Retractable + 105d PocketMouse Bluetooth + 105e Bluetooth EDR Dongle + 1061 PocketMouse Grip + 1062 PocketMouse Max + 1063 PocketMouse Max Wireless + 1064 PocketMouse 2.0 Wireless + 1065 PocketMouse 2.0 + 1066 PocketMouse Max Glow + 1067 ValueMouse + 1068 ValueOpt White + 1069 ValueOpt Black + 106a PilotMouse Laser Wireless Mini + 106b PilotMouse Laser - 3 Button + 106c PilotMouse Laser - Gaming + 106d PilotMouse Laser - Wired + 106e PilotMouse Micro Laser + 1070 ValueOpt Travel + 1071 ValueOpt RF TX + 1072 PocketMouse Colour + 1073 PilotMouse Laser - 6 Button + 1074 PilotMouse Laser Wireless Mini + 1075 SlimBlade Presenter Media Mouse + 1076 SlimBlade Media Mouse + 1077 SlimBlade Presenter Mouse + 1152 Bluetooth EDR Dongle + 2002 Optical Elite Wireless + 2010 Wireless Presentation Remote + 2012 Wireless Presenter with Laser Pointer + 2021 PilotBoard Wireless + 2030 PilotBoard Wireless + 2034 SlimBlade Media Notebook Set + 2041 SlimBlade Trackball + 2048 Orbit Trackball with Scroll Ring + 4003 Gravis Xterminator Digital Gamepad + 4005 Gravis Eliminator GamePad Pro + 4006 Gravis Eliminator AfterShock + 4007 Gravis Xterminator Force + 4008 Gravis Destroyer TiltPad + 5001 Cabo I Camera + 5002 VideoCam CABO II + 5003 VideoCam +047e Agere Systems, Inc. (Lucent) + 0300 ORiNOCO Card + 1001 USS720 Parallel Port + 2892 Systems Soft Modem + bad1 Lucent 56k Modem + f101 Atlas Modem +047f Plantronics, Inc. + 0101 Bulk Driver + 0301 Bulk Driver + 0411 Savi Office Base Station + 0ca1 USB DSP v4 Audio Interface + 4254 BUA-100 Bluetooth Adapter + ac01 Savi 7xx + ad01 GameCom 777 5.1 Headset + af01 DA80 + c008 Audio 655 DSP + c00e Blackwire C310 headset +0480 Toshiba America Inc + 0001 InTouch Module + 0004 InTouch Module + 0011 InTouch Module + 0014 InTouch Module + 0100 Stor.E Slim USB 3.0 + 0200 External Disk + 0820 Canvio Advance Disk + 0821 Canvio Advance 2TB model DTC920 + a006 External Disk 1.5TB + a007 External Disk USB 3.0 + a009 Stor.E Basics + a00d STOR.E BASICS 500GB + a100 Canvio Alu 2TB 2.5" Black External Disk Model HDTH320EK3CA + a102 Canvio Alu 2TB 2.5" Black External Disk Model HDTH320EK3CA + a202 Canvio Basics HDD + a208 Canvio Basics 2TB USB 3.0 Portable Hard Drive + b001 Stor.E Partner + b207 Canvio Ready + d000 External Disk 2TB Model DT01ABA200 + d010 External Disk 3TB + d011 Canvio Desk +0481 Zenith Data Systems +0482 Kyocera Corp. + 000e FS-1020D Printer + 000f FS-1920 Mono Printer + 0015 FS-1030D printer + 0100 Finecam S3x + 0101 Finecam S4 + 0103 Finecam S5 + 0105 Finecam L3 + 0106 Finecam + 0107 Digital Camera Device + 0108 Digital Camera Device + 0203 AH-K3001V + 0204 iBurst Terminal + 0408 FS-1320D Printer + 0640 ECOSYS M6026cdn + 069b ECOSYS M2635dn +0483 STMicroelectronics + 0137 BeWAN ADSL USB ST (blue or green) + 0138 Unicorn II (ST70138B + MTC-20174TQ chipset) + 0adb Android Debug Bridge (ADB) device + 0afb Android Fastboot device + 1307 Cytronix 6in1 Card Reader + 163d Cool Icam Digi-MP3 + 2015 TouchChip® Fingerprint Reader + 2016 Fingerprint Reader + 2017 Biometric Smart Card Reader + 2018 BioSimKey + 2302 Portable Flash Device (PFD) + 3744 ST-LINK/V1 + 3747 ST Micro Connect Lite + 3748 ST-LINK/V2 + 374b ST-LINK/V2.1 + 374d STLINK-V3 Loader + 374e STLINK-V3 + 374f STLINK-V3 + 3752 ST-LINK/V2.1 + 3753 STLINK-V3 + 4810 ISDN adapter + 481d BT Digital Access adapter + 5000 ST Micro/Ergenic ERG BT-002 Bluetooth Adapter + 5001 ST Micro Bluetooth Device + 5710 Joystick in FS Mode + 5720 Mass Storage Device + 5721 Interrupt Demo + 5722 Bulk Demo + 5730 Audio Speaker + 5731 Microphone + 5740 Virtual COM Port + 5750 LED badge -- mini LED display -- 11x44 + 7270 ST Micro Serial Bridge + 7554 56k SoftModem + 8213 ThermaData Logger Cradle + 8259 Probe + 91d1 Sensor Hub + a171 ThermaData WiFi + df11 STM Device in DFU Mode + ff10 Swann ST56 Modem +0484 Specialix +0485 Nokia Monitors +0486 ASUS Computers, Inc. + 0185 EeePC T91MT HID Touch Panel +0487 Stewart Connector +0488 Cirque Corp. +0489 Foxconn / Hon Hai + 0502 SmartMedia Card Reader Firmware Loader + 0503 SmartMedia Card Reader + d00c Rollei Compactline (Storage Mode) + d00e Rollei Compactline (Video Mode) + e000 T-Com TC 300 + e003 Pirelli DP-L10 + e00d Broadcom Bluetooth 2.1 Device + e00f Foxconn T77H114 BCM2070 [Single-Chip Bluetooth 2.1 + EDR Adapter] + e011 Acer Bluetooth module + e016 Ubee PXU1900 WiMAX Adapter [Beceem BCSM250] + e02c Atheros AR5BBU12 Bluetooth Device + e032 Broadcom BCM20702 Bluetooth + e042 Broadcom BCM20702 Bluetooth + e04d Atheros AR3012 Bluetooth + e055 BCM43142A0 broadcom bluetooth +048a S-MOS Systems, Inc. +048c Alps Electric Ireland, Ltd +048d Integrated Technology Express, Inc. + 1165 IT1165 Flash Controller + 1172 Flash Drive + 1336 SD/MMC Cardreader + 1345 Multi Cardreader + 9006 IT9135 BDA Afatech DVB-T HDTV Dongle + 9009 Zolid HD DVD Maker + 9135 Zolid Mini DVB-T Stick + 9306 IT930x DVB stick + 9503 ITE it9503 feature-limited DVB-T transmission chip [ccHDtv] + 9507 ITE it9507 full featured DVB-T transmission chip [ccHDtv] + 9910 IT9910 chipset based grabber + ff59 Hdmi-CEC Bridge +048f Eicon Tech. +0490 United Microelectronics Corp. +0491 Capetronic + 0003 Taxan Monitor Control +0492 Samsung SemiConductor, Inc. + 0140 MP3 player + 0141 MP3 Player +0493 MAG Technology Co., Ltd +0495 ESS Technology, Inc. +0496 Micron Electronics +0497 Smile International + c001 Camera Device +0498 Capetronic (Kaohsiung) Corp. +0499 Yamaha Corp. + 1000 UX256 MIDI I/F + 1001 MU1000 + 1002 MU2000 + 1003 MU500 + 1004 UW500 + 1005 MOTIF6 + 1006 MOTIF7 + 1007 MOTIF8 + 1008 UX96 MIDI I/F + 1009 UX16 MIDI I/F + 100a EOS BX + 100c UC-MX + 100d UC-KX + 100e S08 + 100f CLP-150 + 1010 CLP-170 + 1011 P-250 + 1012 TYROS + 1013 PF-500 + 1014 S90 + 1015 MOTIF-R + 1016 MDP-5 + 1017 CVP-204 + 1018 CVP-206 + 1019 CVP-208 + 101a CVP-210 + 101b PSR-1100 + 101c PSR-2100 + 101d CLP-175 + 101e PSR-K1 + 101f EZ-J24 + 1020 EZ-250i + 1021 MOTIF ES 6 + 1022 MOTIF ES 7 + 1023 MOTIF ES 8 + 1024 CVP-301 + 1025 CVP-303 + 1026 CVP-305 + 1027 CVP-307 + 1028 CVP-309 + 1029 CVP-309GP + 102a PSR-1500 + 102b PSR-3000 + 102e ELS-01/01C + 1030 PSR-295/293 + 1031 DGX-205/203 + 1032 DGX-305 + 1033 DGX-505 + 1037 PSR-E403 + 103c MOTIF-RACK ES + 1054 S90XS Keyboard/Music Synthesizer + 160f P-105 + 1613 Clavinova CLP535 + 1617 PSR-E353 digital keyboard + 1704 Steinberg UR44 + 2000 DGP-7 + 2001 DGP-5 + 3001 YST-MS55D USB Speaker + 3003 YST-M45D USB Speaker + 4000 NetVolante RTA54i Broadband&ISDN Router + 4001 NetVolante RTW65b Broadband Wireless Router + 4002 NetVolante RTW65i Broadband&ISDN Wireless Router + 4004 NetVolante RTA55i Broadband VoIP Router + 5000 CS1D + 5001 DSP1D + 5002 DME32 + 5003 DM2000 + 5004 02R96 + 5005 ACU16-C + 5006 NHB32-C + 5007 DM1000 + 5008 01V96 + 5009 SPX2000 + 500a PM5D + 500b DME64N + 500c DME24N + 6001 CRW2200UX Lightspeed 2 External CD-RW Drive + 7000 DTX + 7010 UB99 +049a Gandalf Technologies, Ltd +049b Curtis Computer Products +049c Acer Advanced Labs, Inc. + 0002 Keyboard (???) +049d VLSI Technology +049f Compaq Computer Corp. + 0002 InkJet Color Printer + 0003 iPAQ PocketPC + 000e Internet Keyboard + 0012 InkJet Color Printer + 0018 PA-1/PA-2 MP3 Player + 0019 InkJet Color Printer + 001a S4 100 Scanner + 001e IJ650 Inkjet Printer + 001f WL215 Adapter + 0021 S200 Scanner + 0027 Bluetooth Multiport Module by Compaq + 002a 1400P Inkjet Printer + 002b A3000 + 002c Lexmark X125 + 0032 802.11b Adapter [ipaq h5400] + 0033 Wireless LAN MultiPort W100 [Intersil PRISM 2.5] + 0036 Bluetooth Multiport Module + 0051 KU-0133 Easy Access Interner Keyboard + 0076 Wireless LAN MultiPort W200 + 0080 GPRS Multiport + 0086 Bluetooth Device + 504a Personal Jukebox PJB100 + 505a Linux-USB "CDC Subset" Device, or Itsy (experimental) + 8511 iPAQ Networking 10/100 Ethernet [pegasus2] +04a0 Digital Equipment Corp. +04a1 SystemSoft Corp. + fff0 Telex Composite Device +04a2 FirePower Systems +04a3 Trident Microsystems, Inc. +04a4 Hitachi, Ltd + 0004 DVD-CAM DZ-MV100A Camcorder + 001e DVDCAM USB HS Interface +04a5 Acer Peripherals Inc. (now BenQ Corp.) + 0001 Keyboard + 0002 API Ergo K/B + 0003 API Generic K/B Mouse + 12a6 AcerScan C310U + 1a20 Prisa 310U + 1a2a Prisa 620U + 2022 Prisa 320U/340U + 2040 Prisa 620UT + 205e ScanPrisa 640BU + 2060 Prisa 620U+/640U + 207e Prisa 640BU + 209e ScanPrisa 640BT + 20ae S2W 3000U + 20b0 S2W 3300U/4300U + 20be Prisa 640BT + 20c0 Prisa 1240UT + 20de S2W 4300U+ + 20f8 Benq 5000 + 20fc Benq 5000 + 20fe SW2 5300U + 2137 Benq 5150/5250 + 2202 Benq 7400UT + 2311 Benq 5560 + 3003 Benq Webcam + 3008 Benq 1500 + 300a Benq 3410 + 300c Benq 1016 + 3019 Benq DC C40 + 4000 P30 Composite Device + 4013 BenQ-Siemens EF82/SL91 + 4044 BenQ-Siemens SF71 + 4045 BenQ-Siemens E81 + 4048 BenQ M7 + 6001 Mass Storage Device + 6002 Mass Storage Device + 6003 ATA/ATAPI Adapter + 6004 Mass Storage Device + 6005 Mass Storage Device + 6006 Mass Storage Device + 6007 Mass Storage Device + 6008 Mass Storage Device + 6009 Mass Storage Device + 600a Mass Storage Device + 600b Mass Storage Device + 600c Mass Storage Device + 600d Mass Storage Device + 600e Mass Storage Device + 600f Mass Storage Device + 6010 Mass Storage Device + 6011 Mass Storage Device + 6012 Mass Storage Device + 6013 Mass Storage Device + 6014 Mass Storage Device + 6015 Mass Storage Device + 6125 MP3 Player + 6180 MP3 Player + 6200 MP3 Player + 7500 Hi-Speed Mass Storage Device + 9000 AWL300 Wireless Adapter + 9001 AWL400 Wireless Adapter + 9213 Kbd Hub +04a6 Nokia Display Products + 00b9 Audio + 0180 Hub Type P + 0181 HID Monitor Controls +04a7 Visioneer + 0100 StrobePro + 0101 Strobe Pro Scanner (1.01) + 0102 StrobePro Scanner + 0211 OneTouch 7600 Scanner + 0221 OneTouch 5300 Scanner + 0223 OneTouch 8200 + 0224 OneTouch 4800 USB/Microtek Scanport 3000 + 0225 VistaScan Astra 3600(ENG) + 0226 OneTouch 5300 USB + 0229 OneTouch 7100 + 022a OneTouch 6600 + 022c OneTouch 9000/9020 + 0231 6100 Scanner + 0311 6200 EPP/USB Scanner + 0321 OneTouch 8100 EPP/USB Scanner + 0331 OneTouch 8600 EPP/USB Scanner + 0341 6400 + 0361 VistaScan Astra 3600(ENG) + 0362 OneTouch 9320 + 0371 OneTouch 8700/8920 + 0380 OneTouch 7700 + 0382 Photo Port 7700 + 0390 9650 + 03a0 Xerox 4800 One Touch + 0410 OneTouch Pro 8800/8820 + 0421 9450 USB + 0423 9750 Scanner + 0424 Strobe XP 450 + 0425 Strobe XP 100 + 0426 Strobe XP 200 + 0427 Strobe XP 100 + 0444 OneTouch 7300 + 0445 CardReader 100 + 0446 Xerox DocuMate 510 + 0447 XEROX DocuMate 520 + 0448 XEROX DocuMate 250 + 0449 Xerox DocuMate 252 + 044a Xerox 6400 + 044c Xerox DocuMate 262 + 0474 Strobe XP 300 + 0475 Xerox DocuMate 272 + 0478 Strobe XP 220 + 0479 Strobe XP 470 + 047a 9450 + 047b 9650 + 047d 9420 + 0480 9520 + 048f Strobe XP 470 + 0491 Strobe XP 450 + 0493 9750 + 0494 Strobe XP 120 + 0497 Patriot 430 + 0498 Patriot 680 + 0499 Patriot 780 + 049b Strobe XP 100 + 04a0 7400 + 04ac Xerox Travel Scanner 100 + 04bb strobe 400 scanner + 04cd Xerox Travel Scanner 150 +04a8 Multivideo Labs, Inc. + 0101 Hub + 0303 Peripheral Switch + 0404 Peripheral Switch +04a9 Canon, Inc. + 1005 BJ Printer Hub + 1035 PD Printer Storage + 1050 BJC-8200 + 1051 BJC-3000 Color Printer + 1052 BJC-6100 + 1053 BJC-6200 + 1054 BJC-6500 + 1055 BJC-85 + 1056 BJC-2110 Color Printer + 1057 LR1 + 105a BJC-55 + 105b S600 Printer + 105c S400 + 105d S450 Printer + 105e S800 + 1062 S500 Printer + 1063 S4500 + 1064 S300 Printer + 1065 S100 + 1066 S630 + 1067 S900 + 1068 S9000 + 1069 S820 + 106a S200 Printer + 106b S520 Printer + 106d S750 Printer + 106e S820D + 1070 S530D + 1072 I850 Printer + 1073 I550 Printer + 1074 S330 Printer + 1076 i70 + 1077 i950 + 107a S830D + 107b i320 + 107c i470D + 107d i9100 + 107e i450 + 107f i860 + 1082 i350 + 1084 i250 + 1085 i255 + 1086 i560 + 1088 i965 + 108a i455 + 108b i900D + 108c i475D + 108d PIXMA iP2000 + 108f i80 + 1090 i9900 Photo Printer + 1091 PIXMA iP1500 + 1093 PIXMA iP4000 + 1094 PIXMA iP3000x Printer + 1095 PIXMA iP6000D + 1097 PIXMA iP5000 + 1098 PIXMA iP1000 + 1099 PIXMA iP8500 + 109c PIXMA iP4000R + 109d iP90 + 10a0 PIXMA iP1600 Printer + 10a2 iP4200 + 10a4 iP5200R + 10a5 iP5200 + 10a7 iP6210D + 10a8 iP6220D + 10a9 iP6600D + 10b6 PIXMA iP4300 Printer + 10b7 PIXMA iP5300 Printer + 10c2 PIXMA iP1800 Printer + 10c4 Pixma iP4500 Printer + 10c9 PIXMA iP4600 Printer + 10ca PIXMA iP3600 Printer + 10e3 PIXMA iX6850 Printer + 1404 W6400PG + 1405 W8400PG + 150f BIJ2350 PCL + 1510 BIJ1350 PCL + 1512 BIJ1350D PCL + 1601 DR-2080C Scanner + 1607 DR-6080 Scanner + 1608 DR-2580C Scanner + 1609 DR-3080CII + 160a DR-2050C Scanner + 1700 PIXMA MP110 Scanner + 1701 PIXMA MP130 Scanner + 1702 MP410 Composite + 1703 MP430 Composite + 1704 MP330 Composite + 1706 PIXMA MP750 Scanner + 1707 PIXMA MP780/MP790 + 1708 PIXMA MP760/MP770 + 1709 PIXMA MP150 Scanner + 170a PIXMA MP170 Scanner + 170b PIXMA MP450 Scanner + 170c PIXMA MP500 Scanner + 170d PIXMA MP800 Scanner + 170e PIXMA MP800R + 1710 MP950 + 1712 PIXMA MP530 + 1713 PIXMA MP830 Scanner + 1714 MP160 + 1715 PIXMA MP180 + 1716 PIXMA MP460 + 1717 PIXMA MP510 + 1718 PIXMA MP600 + 1719 PIXMA MP600R + 171a PIXMA MP810 + 171b PIXMA MP960 + 171c PIXMA MX7600 + 1721 PIXMA MP210 + 1722 PIXMA MP220 + 1723 PIXMA MP470 + 1724 PIXMA MP520 series + 1725 PIXMA MP610 + 1726 PIXMA MP970 + 1727 PIXMA MX300 + 1728 PIXMA MX310 series + 1729 PIXMA MX700 + 172b MP140 ser + 172c PIXMA MX850 + 172d PIXMA MP980 + 172e PIXMA MP630 + 172f PIXMA MP620 + 1730 PIXMA MP540 + 1731 PIXMA MP480 + 1732 PIXMA MP240 + 1733 PIXMA MP260 + 1734 PIXMA MP190 + 1735 PIXMA MX860 + 1736 PIXMA MX320 series + 1737 PIXMA MX330 + 173a PIXMA MP250 + 173b PIXMA MP270 All-In-One Printer + 173c PIXMA MP490 + 173d PIXMA MP550 + 173e PIXMA MP560 + 173f PIXMA MP640 + 1740 PIXMA MP990 + 1741 PIXMA MX340 + 1742 PIXMA MX350 + 1743 PIXMA MX870 + 1746 PIXMA MP280 + 1747 PIXMA MP495 + 1748 PIXMA MG5100 Series + 1749 PIXMA MG5200 Series + 174a PIXMA MG6100 Series + 174b PIXMA MG8100 Series + 174d PIXMA MX360 + 174e PIXMA MX410 + 174f PIXMA MX420 + 1750 PIXMA MX880 Series + 1752 PIXMA MG3100 Series + 1753 PIXMA MG4100 Series + 1754 PIXMA MG5300 Series + 1755 PIXMA MG6200 Series + 1756 PIXMA MG8200 Series + 1757 PIXMA MP493 + 1759 PIXMA MX370 Series + 175b PIXMA MX430 Series + 175c PIXMA MX510 Series + 175d PIXMA MX710 Series + 175e PIXMA MX890 Series + 175f PIXMA MP230 + 1762 PIXMA MG3200 Series + 1763 PIXMA MG4200 Series + 1764 PIXMA MG5400 Series + 1765 PIXMA MG6300 Series + 1766 PIXMA MX390 Series + 1768 PIXMA MX450 Series + 1769 PIXMA MX520 Series + 176a PIXMA MX720 Series + 176b PIXMA MX920 Series + 176d PIXMA MG2500 Series + 176e PIXMA MG3500 Series + 176f PIXMA MG6500 Series + 1770 PIXMA MG6400 Series + 1771 PIXMA MG5500 Series + 1772 PIXMA MG7100 Series + 1774 PIXMA MX470 Series + 1775 PIXMA MX530 Series + 177c PIXMA MG7500 Series + 177e PIXMA MG6600 Series + 177f PIXMA MG5600 Series + 1780 PIXMA MG2900 Series + 1787 PIXMA MX490 Series + 178a PIXMA MG3600 Series + 178d PIXMA MG6853 + 180b PIXMA MG3000 series + 1900 CanoScan LiDE 90 + 1901 CanoScan 8800F + 1904 CanoScan LiDE 100 + 1905 CanoScan LiDE 200 + 1906 CanoScan 5600F + 1907 CanoScan LiDE 700F + 1909 CanoScan LiDE 110 + 190a CanoScan LiDE 210 + 190d CanoScan 9000F Mark II + 190e CanoScan LiDE 120 + 190f CanoScan LiDE 220 + 2200 CanoScan LiDE 25 + 2201 CanoScan FB320U + 2202 CanoScan FB620U + 2204 CanoScan FB630U + 2205 CanoScan FB1210U + 2206 CanoScan N650U/N656U + 2207 CanoScan 1220U + 2208 CanoScan D660U + 220a CanoScan D2400UF + 220b CanoScan D646U + 220c CanoScan D1250U2 + 220d CanoScan N670U/N676U/LiDE 20 + 220e CanoScan N1240U/LiDE 30 + 220f CanoScan 8000F + 2210 CanoScan 9900F + 2212 CanoScan 5000F + 2213 CanoScan LiDE 50/LiDE 35/LiDE 40 + 2214 CanoScan LiDE 80 + 2215 CanoScan 3000/3000F/3000ex + 2216 CanoScan 3200F + 2217 CanoScan 5200F + 2219 CanoScan 9950F + 221b CanoScan 4200F + 221c CanoScan LiDE 60 + 221e CanoScan 8400F + 221f CanoScan LiDE 500F + 2220 CanoScan LIDE 25 + 2224 CanoScan LiDE 600F + 2225 CanoScan LiDE 70 + 2228 CanoScan 4400F + 2229 CanoScan 8600F + 2602 MultiPASS C555 + 2603 MultiPASS C755 + 260a LBP810 + 260e LBP-2000 + 2610 MPC600F + 2611 SmartBase MPC400 + 2612 MultiPASS C855 + 2617 LBP1210 + 261a iR1600 + 261b iR1610 + 261c iC2300 + 261f MPC200 Printer + 2621 iR2000 + 2622 iR2010 + 2623 FAX-B180C + 2629 FAXPHONE L75 + 262b LaserShot LBP-1120 Printer + 262c imageCLASS D300 + 262d iR C3200 + 262f PIXMA MP730 + 2630 PIXMA MP700 + 2631 LASER CLASS 700 + 2632 FAX-L2000 + 2633 LASERCLASS 500 + 2634 PC-D300/FAX-L400/ICD300 + 2635 MPC190 + 2637 iR C6800 + 2638 iR C3100 + 263c PIXMA MP360 + 263d PIXMA MP370 + 263e PIXMA MP390 + 263f PIXMA MP375R + 2646 MF5530 Scanner Device V1.9.1 + 2647 MF5550 Composite + 264c PIXMA MP740 + 264d PIXMA MP710 + 264e MF5630 + 264f MF5650 (FAX) + 2650 iR 6800C EUR + 2651 iR 3100C EUR + 2655 FP-L170/MF350/L380/L398 + 2656 iR1510-1670 CAPT Printer + 2659 MF8100 + 265b CAPT Printer + 265c iR C3220 + 265d MF5730 + 265e MF5750 + 265f MF5770 + 2660 MF3110 + 2663 iR3570/iR4570 + 2664 iR2270/iR2870 + 2665 iR C2620 + 2666 iR C5800 + 2667 iR85PLUS + 2669 iR105PLUS + 266a CAPT Device + 266b iR8070 + 266c iR9070 + 266d iR 5800C EUR + 266e CAPT Device + 266f iR2230 + 2670 iR3530 + 2671 iR5570/iR6570 + 2672 iR C3170 + 2673 iR 3170C EUR + 2674 FAX-L120 + 2675 iR2830 + 2676 LBP2900 + 2677 iR C2570 + 2678 iR 2570C EUR + 2679 CAPT Device + 267a iR2016 + 267b iR2020 + 267d MF7100 series + 2684 MF3200 series + 2686 MF6500 series + 2687 iR4530 + 2688 LBP3460 + 2689 FAX-L180/L380S/L398S + 268a LC310/L390/L408S + 268c iR C6870 + 268d iR 6870C EUR + 268e iR C5870 + 268f iR 5870C EUR + 2691 iR7105 + 26a3 MF4100 series + 26b0 MF4600 series + 26b4 MF4010 series + 26b5 MF4200 series + 26b6 FAX-L140/L130 + 26da LBP3010B printer + 26e6 iR1024 + 271a LBP6000 + 2736 I-SENSYS MF4550d + 2737 MF4410 + 3041 PowerShot S10 + 3042 CanoScan FS4000US Film Scanner + 3043 PowerShot S20 + 3044 EOS D30 + 3045 PowerShot S100 + 3046 IXY Digital + 3047 Digital IXUS + 3048 PowerShot G1 + 3049 PowerShot Pro90 IS + 304a CP-10 + 304b IXY Digital 300 + 304c PowerShot S300 + 304d Digital IXUS 300 + 304e PowerShot A20 + 304f PowerShot A10 + 3050 PowerShot unknown 1 + 3051 PowerShot S110 + 3052 Digital IXUS V + 3055 PowerShot G2 + 3056 PowerShot S40 + 3057 PowerShot S30 + 3058 PowerShot A40 + 3059 PowerShot A30 + 305b ZR45MC Digital Camcorder + 305c PowerShot unknown 2 + 3060 EOS D60 + 3061 PowerShot A100 + 3062 PowerShot A200 + 3063 CP-100 + 3065 PowerShot S200 + 3066 Digital IXUS 330 + 3067 MV550i Digital Video Camera + 3069 PowerShot G3 + 306a Digital unknown 3 + 306b MVX2i Digital Video Camera + 306c PowerShot S45 + 306d PowerShot S45 PtP Mode + 306e PowerShot G3 (normal mode) + 306f PowerShot G3 (ptp) + 3070 PowerShot S230 + 3071 PowerShot S230 (ptp) + 3072 PowerShot SD100 / Digital IXUS II (ptp) + 3073 PowerShot A70 (ptp) + 3074 PowerShot A60 (ptp) + 3075 IXUS 400 Camera + 3076 PowerShot A300 + 3077 PowerShot S50 + 3078 ZR70MC Digital Camcorder + 307a MV650i (normal mode) + 307b MV630i Digital Video Camera + 307c CP-200 + 307d CP-300 + 307f Optura 20 + 3080 MVX150i (normal mode) / Optura 20 (normal mode) + 3081 Optura 10 + 3082 MVX100i / Optura 10 + 3083 EOS 10D + 3084 EOS 300D / EOS Digital Rebel + 3085 PowerShot G5 + 3087 Elura 50 (PTP mode) + 3088 Elura 50 (normal mode) + 308d MVX3i + 308e FV M1 (normal mode) / MVX 3i (normal mode) / Optura Xi (normal mode) + 3093 Optura 300 + 3096 IXY DV M2 (normal mode) / MVX 10i (normal mode) + 3099 EOS 300D (ptp) + 309a PowerShot A80 + 309b Digital IXUS (ptp) + 309c PowerShot S1 IS + 309d Powershot Pro 1 + 309f Camera + 30a0 Camera + 30a1 Camera + 30a2 Camera + 30a8 Elura 60E/Optura 40 (ptp) + 30a9 MVX25i (normal mode) / Optura 40 (normal mode) + 30b1 PowerShot S70 (normal mode) / PowerShot S70 (PTP mode) + 30b2 PowerShot S60 (normal mode) / PowerShot S60 (PTP mode) + 30b3 PowerShot G6 (normal mode) / PowerShot G6 (PTP mode) + 30b4 PowerShot S500 + 30b5 PowerShot A75 + 30b6 Digital IXUS II2 / Digital IXUS II2 (PTP mode) / PowerShot SD110 (PTP mode) / PowerShot SD110 Digital ELPH + 30b7 PowerShot A400 / PowerShot A400 (PTP mode) + 30b8 PowerShot A310 / PowerShot A310 (PTP mode) + 30b9 Powershot A85 + 30ba PowerShot S410 Digital Elph + 30bb PowerShot A95 + 30bd CP-220 + 30be CP-330 + 30bf Digital IXUS 40 + 30c0 Digital IXUS 30 (PTP mode) / PowerShot SD200 (PTP mode) + 30c1 Digital IXUS 50 (normal mode) / IXY Digital 55 (normal mode) / PowerShot A520 (PTP mode) / PowerShot SD400 (normal mode) + 30c2 PowerShot A510 (normal mode) / PowerShot A510 (PTP mode) + 30c4 Digital IXUS i5 (normal mode) / IXY Digital L2 (normal mode) / PowerShot SD20 (normal mode) + 30ea EOS 1D Mark II (PTP mode) + 30eb EOS 20D + 30ec EOS 20D (ptp) + 30ee EOS 350D + 30ef EOS 350D (ptp) + 30f0 PowerShot S2 IS (PTP mode) + 30f2 Digital IXUS 700 (normal mode) / Digital IXUS 700 (PTP mode) / IXY Digital 600 (normal mode) / PowerShot SD500 (normal mode) / PowerShot SD500 (PTP mode) + 30f4 PowerShot SD30 / Ixus iZoom / IXY DIGITAL L3 + 30f5 SELPHY CP500 + 30f6 SELPHY CP400 + 30f8 Powershot A430 + 30f9 PowerShot A410 (PTP mode) + 30fa PowerShot S80 + 30fc PowerShot A620 (PTP mode) + 30fd PowerShot A610 (normal mode)/PowerShot A610 (PTP mode) + 30fe Digital IXUS 65 (PTP mode)/PowerShot SD630 (PTP mode) + 30ff Digital IXUS 55 (PTP mode)/PowerShot SD450 (PTP mode) + 3100 PowerShot TX1 + 310b SELPHY CP600 + 310e Digital IXUS 50 (PTP mode) + 310f PowerShot A420 + 3110 EOS Digital Rebel XTi + 3115 PowerShot SD900 / Digital IXUS 900 Ti / IXY DIGITAL 1000 + 3116 Digital IXUS 750 / PowerShot SD550 (PTP mode) + 3117 PowerShot A700 + 3119 PowerShot SD700 IS / Digital IXUS 800 IS / IXY Digital 800 IS + 311a PowerShot S3 IS + 311b PowerShot A540 + 311c PowerShot SD600 DIGITAL ELPH / DIGITAL IXUS 60 / IXY DIGITAL 70 + 3125 PowerShot G7 + 3126 PowerShot A530 + 3127 SELPHY CP710 + 3128 SELPHY CP510 + 312d Elura 100 + 3136 PowerShot SD800 IS / Digital IXUS 850 IS / IXY DIGITAL 900 IS + 3137 PowerShot SD40 / Digital IXUS i7 IXY / DIGITAL L4 + 3138 PowerShot A710 IS + 3139 PowerShot A640 + 313a PowerShot A630 + 3141 SELPHY ES1 + 3142 SELPHY CP730 + 3143 SELPHY CP720 + 3145 EOS 450D + 3146 EOS 40D + 3147 EOS 1Ds Mark III + 3148 PowerShot S5 IS + 3149 PowerShot A460 + 314b PowerShot SD850 IS DIGITAL ELPH / Digital IXUS 950 IS / IXY DIGITAL 810 IS + 314c PowerShot A570 IS + 314d PowerShot A560 + 314e PowerShot SD750 DIGITAL ELPH / DIGITAL IXUS 75 / IXY DIGITAL 90 + 314f PowerShot SD1000 DIGITAL ELPH / DIGITAL IXUS 70 / IXY DIGITAL 10 + 3150 PowerShot A550 + 3155 PowerShot A450 + 315a PowerShot G9 + 315b PowerShot A650 IS + 315d PowerShot A720 + 315e PowerShot SX100 IS + 315f PowerShot SD950 IS DIGITAL ELPH / DIGITAL IXUS 960 IS / IXY DIGITAL 2000 IS + 3160 Digital IXUS 860 IS + 3170 SELPHY CP750 + 3171 SELPHY CP740 + 3172 SELPHY CP520 + 3173 PowerShot SD890 IS DIGITAL ELPH / Digital IXUS 970 IS / IXY DIGITAL 820 IS + 3174 PowerShot SD790 IS DIGITAL ELPH / Digital IXUS 90 IS / IXY DIGITAL 95 IS + 3175 IXY Digital 25 IS + 3176 PowerShot A590 + 3177 PowerShot A580 + 317a PC1267 [Powershot A470] + 3184 Digital IXUS 80 IS (PTP mode) + 3185 SELPHY ES2 + 3186 SELPHY ES20 + 318d PowerShot SX100 IS + 318e PowerShot A1000 IS + 318f PowerShot G10 + 3191 PowerShot A2000 IS + 3192 PowerShot SX110 IS + 3193 PowerShot SD990 IS DIGITAL ELPH / Digital IXUS 980 IS / IXY DIGITAL 3000 IS + 3195 PowerShot SX1 IS + 3196 PowerShot SD880 IS DIGITAL ELPH / Digital IXUS 870 IS / IXY DIGITAL 920 IS + 3199 EOS 5D Mark II + 319a EOS 7D + 319b EOS 50D + 31aa SELPHY CP770 + 31ab SELPHY CP760 + 31ad PowerShot E1 + 31af SELPHY ES3 + 31b0 SELPHY ES30 + 31b1 SELPHY CP530 + 31bc PowerShot D10 + 31bd PowerShot SD960 IS DIGITAL ELPH / Digital IXUS 110 IS / IXY DIGITAL 510 IS + 31be PowerShot A2100 IS + 31bf PowerShot A480 + 31c0 PowerShot SX200 IS + 31c1 PowerShot SD970 IS DIGITAL ELPH / Digital IXUS 990 IS / IXY DIGITAL 830 IS + 31c2 PowerShot SD780 IS DIGITAL ELPH / Digital IXUS 100 IS / IXY DIGITAL 210 IS + 31c3 PowerShot A1100 IS + 31c4 PowerShot SD1200 IS DIGITAL ELPH / Digital IXUS 95 IS / IXY DIGITAL 110 IS + 31cf EOS Rebel T1i / EOS 500D / EOS Kiss X3 + 31dd SELPHY CP780 + 31df PowerShot G11 + 31e0 PowerShot SX120 IS + 31e1 PowerShot S90 + 31e4 PowerShot SX20 IS + 31e5 Digital IXUS 200 IS + 31e6 PowerShot SD940 IS DIGITAL ELPH / Digital IXUS 120 IS / IXY DIGITAL 220 IS + 31e7 SELPHY CP790 + 31ea EOS Rebel T2i / EOS 550D / EOS Kiss X4 + 31ee SELPHY ES40 + 31ef PowerShot A495 + 31f0 PowerShot A490 + 31f1 PowerShot A3100 IS / PowerShot A3150 IS + 31f2 PowerShot A3000 IS + 31f3 PowerShot Digital ELPH SD1400 IS + 31f4 PowerShot SD1300 IS / IXUS 105 + 31f5 Powershot SD3500 IS / IXUS 210 IS + 31f6 PowerShot SX210 IS + 31f7 Powershot SD4000 IS / IXUS 300 HS / IXY 30S + 31f8 Powershot SD4500 IS / IXUS 1000 HS / IXY 50S + 31ff Digital IXUS 55 + 3209 Vixia HF S21 A + 320f PowerShot G12 + 3210 Powershot SX30 IS + 3211 PowerShot SX130 IS + 3212 Powershot S95 + 3214 SELPHY CP800 + 3215 EOS 60D + 3218 EOS 600D / Rebel T3i (ptp) + 3219 EOS 1D X + 3223 PowerShot A3300 IS + 3224 PowerShot A3200 IS + 3225 PowerShot ELPH 500 HS / IXUS 310 HS + 3226 PowerShow A800 + 3227 PowerShot ELPH 100 HS / IXUS 115 HS + 3228 PowerShot SX230 HS + 3229 PowerShot ELPH 300 HS / IXUS 220 HS + 322a PowerShot A2200 + 322b Powershot A1200 + 322c PowerShot SX220 HS + 3233 PowerShot G1 X + 3234 PowerShot SX150 IS + 3235 PowerShot ELPH 510 HS / IXUS 1100 HS + 3236 PowerShot S100 + 3237 PowerShot ELPH 310 HS / IXUS 230 HS + 3238 PowerShot SX40 HS + 323a EOS 5D Mark III + 323b EOS Rebel T4i + 323d EOS M + 323e PowerShot A1300 + 323f PowerShot A810 + 3240 PowerShot ELPH 320 HS / IXUS 240 HS + 3241 PowerShot ELPH 110 HS / IXUS 125 HS + 3242 PowerShot D20 + 3243 PowerShot A4000 IS + 3244 PowerShot SX260 HS + 3245 PowerShot SX240 HS + 3246 PowerShot ELPH 530 HS / IXUS 510 HS + 3247 PowerShot ELPH 520 HS / IXUS 500 HS + 3248 PowerShot A3400 IS + 3249 PowerShot A2400 IS + 324a PowerShot A2300 + 3250 EOS 6D + 3252 EOS 1D C + 3253 EOS 70D + 3255 SELPHY CP900 + 3256 SELPHY CP810 + 3258 PowerShot G15 + 3259 PowerShot SX50 HS + 325a PowerShot SX160 IS + 325b PowerShot S110 + 325c PowerShot SX500 IS + 325e PowerShot N + 325f PowerShot SX280 HS + 3260 PowerShot SX270 HS + 3261 PowerShot A3500 IS + 3262 PowerShot A2600 + 3263 PowerShot SX275 HS + 3264 PowerShot A1400 + 3265 Powershot ELPH 130 IS / IXUS 140 + 3266 Powershot ELPH 120 IS / IXUS 135 + 3268 PowerShot ELPH 330 HS / IXUS 255 HS + 326f EOS 7D Mark II + 3270 EOS 100D + 3271 PowerShot A2500 + 3272 EOS 700D + 3274 PowerShot G16 + 3275 PowerShot S120 + 3276 PowerShot SX170 IS + 3277 PowerShot SX510 HS + 3278 PowerShot S200 + 327a SELPHY CP910 + 327b SELPHY CP820 + 327d Powershot ELPH 115 IS / IXUS 132 + 327f EOS Rebel T5 / EOS 1200D / EOS Kiss X70 + 3284 PowerShot D30 + 3285 PowerShot SX700 HS + 3286 PowerShot SX600 HS + 3287 PowerShot ELPH 140 IS / IXUS 150 + 3288 Powershot ELPH 135 / IXUS 145 + 3289 PowerShot ELPH 340 HS / IXUS 265 HS + 328a PowerShot ELPH 150 IS / IXUS 155 + 328b PowerShot N Facebook(R) Ready + 3299 EOS M3 + 329a PowerShot SX60 HS + 329b PowerShot SX520 HS + 329c PowerShot SX400 IS + 329d PowerShot G7 X + 329f PowerShot SX530 HS + 32a0 EOS M10 + 32a6 PowerShot SX710 HS + 32a7 PowerShot SX610 HS + 32a8 PowerShot G3 X + 32aa Powershot ELPH 160 / IXUS 160 + 32ab PowerShot ELPH 350HS / IXUS 275 HS + 32ac PowerShot ELPH 170 IS / IXUS 170 + 32ad PowerShot SX410 IS + 32b1 SELPHY CP1200 + 32b2 PowerShot G9 X + 32b3 PowerShot G5 X + 32b4 EOS Rebel T6 + 32bb EOS M5 + 32bf PowerShot SX420 IS + 32c1 PowerShot ELPH 180 / IXUS 175 + 32c2 PowerShot SX720 HS + 32c5 EOS M6 + 32cc EOS 200D + 32d1 EOS M100 + 32d2 EOS M50 + 32d4 Powershot ELPH 185 / IXUS 185 / IXY 200 + 32d5 PowerShot SX430 IS + 32db SELPHY CP1300 +04aa DaeWoo Telecom, Ltd +04ab Chromatic Research +04ac Micro Audiometrics Corp. +04ad Dooin Electronics + 2501 Bluetooth Device +04af Winnov L.P. +04b0 Nikon Corp. + 0102 Coolpix 990 + 0103 Coolpix 880 + 0104 Coolpix 995 + 0106 Coolpix 775 + 0107 Coolpix 5000 + 0108 Coolpix 2500 + 0109 Coolpix 2500 (ptp) + 010a Coolpix 4500 + 010b Coolpix 4500 (ptp) + 010d Coolpix 5700 (ptp) + 010e Coolpix 4300 (storage) + 010f Coolpix 4300 (ptp) + 0110 Coolpix 3500 (Sierra Mode) + 0111 Coolpix 3500 (ptp) + 0112 Coolpix 885 (ptp) + 0113 Coolpix 5000 (ptp) + 0114 Coolpix 3100 (storage) + 0115 Coolpix 3100 (ptp) + 0117 Coolpix 2100 (ptp) + 0119 Coolpix 5400 (ptp) + 011d Coolpix 3700 (ptp) + 0121 Coolpix 3200 (ptp) + 0122 Coolpix 2200 (ptp) + 0124 Coolpix 8400 (mass storage mode) + 0125 Coolpix 8400 (ptp) + 0126 Coolpix 8800 + 0129 Coolpix 4800 (ptp) + 012c Coolpix 4100 (storage) + 012d Coolpix 4100 (ptp) + 012e Coolpix 5600 (ptp) + 0130 Coolpix 4600 (ptp) + 0135 Coolpix 5900 (ptp) + 0136 Coolpix 7900 (storage) + 0137 Coolpix 7900 (ptp) + 013a Coolpix 100 (storage) + 013b Coolpix 100 (ptp) + 0141 Coolpix P2 (storage) + 0142 Coolpix P2 (ptp) + 0163 Coolpix P5100 (ptp) + 0169 Coolpix P50 (ptp) + 0202 Coolpix SQ (ptp) + 0203 Coolpix 4200 (mass storage mode) + 0204 Coolpix 4200 (ptp) + 0205 Coolpix 5200 (storage) + 0206 Coolpix 5200 (ptp) + 0301 Coolpix 2000 (storage) + 0302 Coolpix 2000 (ptp) + 0317 Coolpix L20 (ptp) + 0402 DSC D100 (ptp) + 0403 D2H (mass storage mode) + 0404 D2H SLR (ptp) + 0405 D70 (mass storage mode) + 0406 DSC D70 (ptp) + 0408 D2X SLR (ptp) + 0409 D50 digital camera + 040a D50 (ptp) + 040c D2Hs + 040e DSC D70s (ptp) + 040f D200 (mass storage mode) + 0410 D200 (ptp) + 0413 D40 (mass storage mode) + 041e D60 digital camera (mass storage mode) + 0422 D700 (ptp) + 0423 D5000 + 0424 D3000 + 0425 D300S + 0428 D7000 + 0429 D5100 + 042a D800 (ptp) + 0430 D7100 + 043f D5600 + 0f03 PD-10 Wireless Printer Adapter + 4000 Coolscan LS 40 ED + 4001 LS 50 ED/Coolscan V ED + 4002 Super Coolscan LS-5000 ED +04b1 Pan International +04b3 IBM Corp. + 3003 Rapid Access III Keyboard + 3004 Media Access Pro Keyboard + 300a Rapid Access IIIe Keyboard + 3016 UltraNav Keyboard Hub + 3018 UltraNav Keyboard + 301a 2-port low-power hub + 301b SK-8815 Keyboard + 301c Enhanced Performance Keyboard + 3020 Enhanced Performance Keyboard + 3025 NetVista Full Width Keyboard + 3100 NetVista Mouse + 3103 ScrollPoint Pro Mouse + 3104 ScrollPoint Wireless Mouse + 3105 ScrollPoint Optical (HID) + 3107 ThinkPad 800dpi Optical Travel Mouse + 3108 800dpi Optical Mouse w/ Scroll Point + 3109 Optical ScrollPoint Pro Mouse + 310b Red Wheel Mouse + 310c Wheel Mouse + 4427 Portable CD ROM + 4482 Serial Converter + 4484 SMSC USB20H04 3-Port Hub [ThinkPad X4 UltraBase, Wistron S Note-3 Media Slice] + 4485 ThinkPad Dock Hub + 4524 40 Character Vacuum Fluorescent Display + 4525 Double sided CRT + 4535 4610 Suremark Printer + 4550 NVRAM (128 KB) + 4554 Cash Drawer + 4580 Hub w/ NVRAM + 4581 4800-2xx Hub w/ Cash Drawer + 4604 Keyboard w/ Card Reader + 4671 4820 LCD w/ MSR/KB +04b4 Cypress Semiconductor Corp. + 0001 Mouse + 0002 CY7C63x0x Thermometer + 0033 Mouse + 0060 Wireless optical mouse + 0100 Cino FuzzyScan F760-B + 0101 Keyboard/Hub + 0102 Keyboard with APM + 0130 MyIRC Remote Receiver + 0306 Telephone Receiver + 0407 Optical Skype Mouse + 0bad MetaGeek Wi-Spy + 1002 CY7C63001 R100 FM Radio + 1006 Human Interface Device + 2050 hub + 2830 Opera1 DVB-S (cold state) + 3813 NANO BIOS Programmer + 4235 Monitor 02 Driver + 4381 SCAPS USC-1 Scanner Controller + 4611 Storage Adapter FX2 (CY) + 4616 Flash Disk (TPP) + 4624 DS-Xtreme Flash Card + 5201 Combi Keyboard-Hub (Hub) + 5202 Combi Keyboard-Hub (Keyboard) + 5500 HID->COM RS232 Adapter + 5a9b Dacal CD/DVD Library D-101/DC-300/DC-016RW + 6370 ViewMate Desktop Mouse CC2201 + 6502 CY4609 + 6506 CY4603 + 650a CY4613 + 6560 CY7C65640 USB-2.0 "TetraHub" + 6570 Unprogrammed CY7C65632/34 hub HX2VL + 6572 Unprogrammed CY7C65642 hub + 6830 CY7C68300A EZ-USB AT2 USB 2.0 to ATA/ATAPI + 6831 Storage Adapter ISD-300LP (CY) + 7417 Wireless PC Lock/Ultra Mouse + 8329 USB To keyboard/Mouse Converter + 8613 CY7C68013 EZ-USB FX2 USB 2.0 Development Kit + 8614 DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + 861f Anysee E30 USB 2.0 DVB-T Receiver + bca1 Barcode Reader + cc04 Centor USB RACIA-ALVAR USB PORT + cc06 Centor-P RACIA-ALVAR USB PORT + d5d5 CY7C63x0x Zoltrix Z-Boxer GamePad + de61 Barcode Reader + de64 Barcode Reader + f000 CY30700 Licorice evaluation board + f111 CY8CKIT-002 PSoC MiniProg3 Rev A Program and debug kit + f115 PSoC FirstTouch Programmer + f231 DELLY Changer 4in1 universal IR remote + f232 Mono embedded computer + fd13 Programmable power socket +04b5 ROHM LSI Systems USA, LLC + 3064 Hantek DSO-3064 +04b6 Hint Corp. +04b7 Compal Electronics, Inc. +04b8 Seiko Epson Corp. + 0001 Stylus Color 740 / Photo 750 + 0002 ISD Smart Cable for Mac + 0003 ISD Smart Cable + 0004 Printer + 0005 Printer + 0006 Printer + 0007 Printer + 0015 Stylus Photo R3000 + 0101 GT-7000U [Perfection 636] + 0102 GT-2200 + 0103 GT-6600U [Perfection 610] + 0104 GT-7600UF [Perfection 1200U/1200U Photo] + 0105 Stylus Scan 2000 + 0106 Stylus Scan 2500 + 0107 ES-2000 [Expression 1600U] + 0108 CC-700 + 0109 ES-8500 [Expression 1640 XL] + 010a GT-8700/GT-8700F [Perfection 1640SU/1640SU PHOTO] + 010b GT-7700U [Perfection 1240U] + 010c GT-6700U [Perfection 640] + 010d CC-500L + 010e ES-2200 [Perfection 1680] + 010f GT-7200U [Perfection 1250/1250 PHOTO] + 0110 GT-8200U/GT-8200UF [Perfection 1650/1650 PHOTO] + 0112 GT-9700F [Perfection 2450 PHOTO] + 0114 Perfection 660 + 0116 GT-9400UF [Perfection 3170] + 0118 GT-F600 [Perfection 4180] + 0119 GT-X750 [Perfection 4490 Photo] + 011a CC-550L [1000 ICS] + 011b GT-9300UF [Perfection 2400 PHOTO] + 011c GT-9800F [Perfection 3200] + 011d GT-7300U [Perfection 1260/1260 PHOTO] + 011e GT-8300UF [Perfection 1660 PHOTO] + 011f GT-8400UF [Perfection 1670/1670 PHOTO] + 0120 GT-7400U [Perfection 1270] + 0121 GT-F500/GT-F550 [Perfection 2480/2580 PHOTO] + 0122 GT-F520/GT-F570 [Perfection 3590 PHOTO] + 0126 ES-7000H [GT-15000] + 0128 GT-X700 [Perfection 4870] + 0129 ES-10000G [Expression 10000XL] + 012a GT-X800 [Perfection 4990 PHOTO] + 012b ES-H300 [GT-2500] + 012c GT-X900 [Perfection V700/V750 Photo] + 012d GT-F650 [GT-S600/Perfection V10/V100] + 012e GT-F670 [Perfection V200 Photo] + 012f GT-F700 [Perfection V350] + 0130 GT-X770 [Perfection V500] + 0131 GT-F720 [GT-S620/Perfection V30/V300 Photo] + 0133 GT-1500 [GT-D1000] + 0135 GT-X970 + 0136 ES-D400 [GT-S80] + 0137 ES-D200 [GT-S50] + 0138 ES-H7200 [GT-20000] + 013a GT-X820 [Perfection V600 Photo] + 0142 GT-F730 [GT-S630/Perfection V33/V330 Photo] + 0143 GT-S55 + 0144 GT-S85 + 0151 Perfection V800 Photo + 0202 Receipt Printer M129C/TM-T70 + 0401 CP 800 Digital Camera + 0402 PhotoPC 850z + 0403 PhotoPC 3000z + 0509 JVC PIX-MC10 + 0601 Stylus Photo 875DC Card Reader + 0602 Stylus Photo 895 Card Reader + 0801 CC-600PX [Stylus CX5200/CX5400/CX6600] + 0802 CC-570L [Stylus CX3100/CX3200] + 0803 Printer (Composite Device) + 0804 Storage Device + 0805 Stylus CX6300/CX6400 + 0806 PM-A850 [Stylus Photo RX600/610] + 0807 Stylus Photo RX500/510 + 0808 Stylus CX5200/CX5300/CX5400 + 0809 Storage Device + 080a F-3200 + 080c ME100 [Stylus CX1500] + 080d Stylus CX4500/4600 + 080e PX-A550 [CX-3500/3600/3650 MFP] + 080f Stylus Photo RX420/RX425/RX430 + 0810 PM-A900 [Stylus Photo RX700] + 0811 PM-A870 [Stylus Photo RX620/RX630] + 0812 MFP Composite Device + 0813 Stylus CX6500/6600 + 0814 PM-A700 + 0815 LP-A500 [AcuLaser CX1] + 0816 Printer (Composite Device) + 0817 LP-M5500/LP-M5500F + 0818 Stylus CX3700/CX3800/DX3800 + 0819 PX-A650 [Stylus CX4700/CX4800/DX4800/DX4850] + 081a PM-A750 [Stylus Photo RX520/RX530] + 081b MFP Composite Device + 081c PM-A890 [Stylus Photo RX640/RX650] + 081d PM-A950 + 081e MFP Composite Device + 081f Stylus CX7700/7800 + 0820 Stylus CX4100/CX4200/DX4200 + 0821 Stylus CX5700F/CX5800F + 0822 Storage Device + 0823 MFP Composite Device + 0824 Storage Device + 0825 MFP Composite Device + 0826 Storage Device + 0827 PM-A820 [Stylus Photo RX560/RX580/RX585/RX590] + 0828 PM-A970 + 0829 PM-T990 + 082a PM-A920 + 082b Stylus CX5900/CX5000/DX5000/DX5050 + 082c Storage Device + 082d Storage Device + 082e PX-A720 [Stylus CX5900/CX6000/DX6000] + 082f PX-A620 [Stylus CX3900/DX4000/DX4050] + 0830 ME 200 [Stylus CX2800/CX2900] + 0831 Stylus CX6900F/CX7000F/DX7000F + 0832 MFP Composite Device + 0833 LP-M5600 + 0834 LP-M6000 + 0835 AcuLaser CX21 + 0836 PM-T960 + 0837 PM-A940 [Stylus Photo RX680/RX685/RX690] + 0838 PX-A640 [CX7300/CX7400/DX7400] + 0839 PX-A740 [CX8300/CX8400/DX8400] + 083a PX-FA700 [CX9300F/CX9400Fax/DX9400F] + 083b MFP Composite Device + 083c PM-A840S [Stylus Photo RX595/RX610] + 083d MFP Composite Device + 083e MFP Composite Device + 083f Stylus CX4300/CX4400/CX5500/CX5600/DX4400/DX4450 + 0841 PX-401A [ME 300/Stylus NX100] + 0843 LP-M5000 + 0844 EP-901A/EP-901F [Artisan 800/Stylus Photo PX800FW] + 0846 EP-801A [Artisan 700/Stylus Photo PX700W/TX700W] + 0847 PX-601F [ME Office 700FW/Stylus Office BX600FW/TX600FW] + 0848 ME Office 600F/Stylus Office BX300F/TX300F + 0849 Stylus SX205 + 084a PX-501A [Stylus NX400] + 084d PX-402A [Stylus SX115/Stylus NX110 Series] + 084f ME OFFICE 510 + 0850 EP-702A [Stylus Photo PX650/TX650 Series] + 0851 Stylus SX410 + 0852 EP-802A [Artisan 710 Series/Stylus Photo PX710W/TX720W Series] + 0853 EP-902A [Artisan 810 Series/Stylus Photo PX810FW Series] + 0854 ME OFFICE 650FN Series/Stylus Office BX310FN/TX520FN Series + 0855 PX-602F [Stylus Office BX610FW/TX620FW Series] + 0856 PX-502A [Stylus SX515W] + 085c ME 320/330 Series [Stylus SX125] + 085d PX-603F [ME OFFICE 960FWD Series/Stylus Office BX625FWD/TX620FWD Series] + 085e PX-503A [ME OFFICE 900WD Series/Stylus Office BX525WD] + 085f Stylus Office BX320FW/TX525FW Series + 0860 EP-903A/EP-903F [Artisan 835/Stylus Photo PX820FWD Series] + 0861 EP-803A/EP-803AW [Artisan 725/Stylus Photo PX720WD/TX720WD Series] + 0862 EP-703A [Stylus Photo PX660 Series] + 0863 ME OFFICE 620F Series/Stylus Office BX305F/BX305FW/TX320F + 0864 ME OFFICE 560W Series + 0865 ME OFFICE 520 Series + 0866 AcuLaser MX20DN/MX20DNF/MX21DNF + 0869 PX-1600F + 086a PX-673F [Stylus Office BX925FWD] + 0870 Stylus Office BX305FW Plus + 0871 K200 Series + 0872 K300 Series + 0873 L200 Series + 0878 EP-704A + 0879 EP-904A/EP-904F [Artisan 837/Stylus Photo PX830FWD Series] + 087b EP-804A/EP-804AR/EP-804AW [Stylus Photo PX730WD/Artisan 730 Series] + 087c PX-1700F + 087d PX-B750F/WP-4525 Series + 087f PX-403A + 0880 PX-434A [Stylus NX330 Series] + 0881 PX-404A [ME OFFICE 535] + 0883 ME 340 Series/Stylus NX130 Series + 0884 Stylus NX430W Series + 0885 Stylus NX230/SX235W Series + 088f Stylus Office BX635FWD + 0890 ME OFFICE 940FW Series/Stylus Office BX630FW Series + 0891 Stylus Office BX535WD + 0892 Stylus Office BX935FWD + 0893 EP-774A + 1114 XP-440 [Expression Home Small-in-One Printer] + 1129 ET-4750 [WorkForce ET-4750 EcoTank All-in-One] +04b9 Rainbow Technologies, Inc. + 0300 SafeNet USB SuperPro/UltraPro + 1000 iKey 1000 Token + 1001 iKey 1200 Token + 1002 iKey Token + 1003 iKey Token + 1004 iKey Token + 1005 iKey Token + 1006 iKey Token + 1200 iKey 2000 Token + 1201 iKey Token + 1202 iKey 2032 Token + 1203 iKey Token + 1204 iKey Token + 1205 iKey Token + 1206 iKey 4000 Token + 1300 iKey 3000 Token + 1301 iKey 3000 + 1302 iKey Token + 1303 iKey Token + 1304 iKey Token + 1305 iKey Token + 1306 iKey Token + 8000 SafeNet Sentinel Hardware Key +04ba Toucan Systems, Ltd +04bb I-O Data Device, Inc. + 0101 USB2-IDE/ATAPI Bridge Adapter + 0201 USB2-IDE/ATAPI Bridge Adapter + 0204 DVD Multi-plus unit iU-CD2 + 0206 DVD Multi-plus unit DVR-UEH8 + 0301 Storage Device + 0314 USB-SSMRW SD-card + 0319 USB2-IDE/ATAPI Bridge Adapter + 031a USB2-IDE/ATAPI Bridge Adapter + 031b USB2-IDE/ATAPI Bridge Adapter + 031e USB-SDRW SD-card + 0502 Nogatech Live! (BT) + 0528 GV-USB Video Capture + 0901 USB ETT + 0904 ET/TX Ethernet [pegasus] + 0913 ET/TX-S Ethernet [pegasus2] + 0919 USB WN-B11 + 0922 IOData AirPort WN-B11/USBS 802.11b + 0930 ETG-US2 + 0937 WN-WAG/USL Wireless LAN Adapter + 0938 WN-G54/USL Wireless LAN Adapter + 093b WN-GDN/USB + 093f WNGDNUS2 802.11n + 0944 WHG-AGDN/US Wireless LAN Adapter + 0945 WN-GDN/US3 Wireless LAN Adapter + 0947 WN-G150U Wireless LAN Adapter + 0948 WN-G300U Wireless LAN Adapter + 0a03 Serial USB-RSAQ1 + 0a07 USB2-iCN Adapter + 0a08 USB2-iCN Adapter + 0c01 FM-10 Pro Disk +04bd Toshiba Electronics Taiwan Corp. +04be Telia Research AB +04bf TDK Corp. + 0100 MediaReader CF + 0115 USB-PDC Adapter UPA9664 + 0116 USB-cdmaOne Adapter UCA1464 + 0117 USB-PHS Adapter UHA6400 + 0118 USB-PHS Adapter UPA6400 + 0135 MediaReader Dual + 0202 73S1121F Smart Card Reader- + 0309 Bluetooth USB dongle + 030a IBM Bluetooth Ultraport Module + 030b Bluetooth Device + 030c Ultraport Bluetooth Device + 0310 Integrated Bluetooth + 0311 Integrated Bluetooth Device + 0317 Bluetooth UltraPort Module from IBM + 0318 IBM Integrated Bluetooth + 0319 Bluetooth Adapter + 0320 Bluetooth Adapter + 0321 Bluetooth Device + 0a28 INDI AV-IN Device +04c1 U.S. Robotics (3Com) + 0020 56K Voice Pro + 0022 56K Voice Pro + 007e ISDN TA + 0082 OfficeConnect Analog Modem + 008f Pro ISDN TA + 0097 OfficeConnect Analog + 009d HomeConnect Webcam [vicam] + 00a9 ISDN Pro TA-U + 00b9 HomeConnect IDSL Modem + 3021 56k Voice FaxModem Pro +04c2 Methode Electronics Far East PTE, Ltd +04c3 Maxi Switch, Inc. + 1102 Mouse + 2102 Mouse +04c4 Lockheed Martin Energy Research +04c5 Fujitsu, Ltd + 1029 fi-4010c Scanner + 1033 fi-4110CU + 1041 fi-4120c Scanner + 1042 fi-4220c Scanner + 105b AH-F401U Air H device + 1084 PalmSecure Sensor V2 + 1096 fi-5110EOX + 1097 fi-5110C + 10ae fi-4120C2 + 10af fi-4220C2 + 10c7 fi-60f scanner + 10e0 fi-5120c Scanner + 10e1 fi-5220C + 10e7 fi-5900C + 10fe S500 + 1104 KD02906 Line Thermal Printer + 114f fi-6130 + 1150 fi-6230 + 11f3 fi-6130Z + 125a PalmSecure Sensor Device - MP + 132e fi-7160 + 200f Sigma DP2 (Mass Storage) + 2010 Sigma DP2 (PictBridge) + 201d SATA 3.0 6Gbit/s Adaptor [GROOVY] +04c6 Toshiba America Electronic Components +04c7 Micro Macro Technologies +04c8 Konica Corp. + 0720 Digital Color Camera + 0721 e-miniD Camera + 0722 e-mini + 0723 KD-200Z Camera + 0726 KD-310Z Camera + 0728 Revio C2 Mass Storage Device + 0729 Revio C2 Digital Camera + 072c Revio KD20M + 072d Revio KD410Z +04ca Lite-On Technology Corp. + 004b Keyboard + 004f SK-9020 keyboard + 1766 HID Monitor Controls + 2004 Bluetooth 4.0 [Broadcom BCM20702A0] + 2006 Broadcom BCM43142A0 Bluetooth Device + 2007 Broadcom BCM43142A0 Bluetooth Device + 3005 Atheros Bluetooth + 300b Atheros AR3012 Bluetooth + 300d Atheros AR3012 Bluetooth + 300f Atheros AR3012 Bluetooth + 3014 Qualcomm Atheros Bluetooth + 7022 HP HD Webcam + 7025 HP HD Webcam + 7046 TOSHIBA Web Camera - HD + 9304 Hub + f01c TT1280DA DVB-T TV Tuner +04cb Fuji Photo Film Co., Ltd + 0100 FinePix 30i/40i/50i, A101/201, 1300/2200, 1400/2400/2600/2800/4500/4700/4800/4900/6800/6900 Zoom + 0103 FinePix NX-500/NX-700 printer + 0104 FinePix A101, 2600/2800/4800/6800 Zoom (PC CAM) + 0108 FinePix F601 Zoom (DSC) + 0109 FinePix F601 Zoom (PC CAM) + 010a FinePix S602 (Pro) Zoom (DSC) + 010b FinePix S602 (Pro) Zoom (PC CAM) + 010d FinePix S2 pro + 010e FinePix F402 Zoom (DSC) + 010f FinePix F402 Zoom (PC CAM) + 0110 FinePix M603 Zoom (DSC) + 0111 FinePix M603 Zoom (PC CAM) + 0112 FinePix A202, A200 Zoom (DSC) + 0113 FinePix A202, A200 Zoom (PC CAM) + 0114 FinePix F401 Zoom (DSC) + 0115 FinePix F401 Zoom (PC CAM) + 0116 FinePix A203 Zoom (DSC) + 0117 FinePix A203 Zoom (PC CAM) + 0118 FinePix A303 Zoom (DSC) + 0119 FinePix A303 Zoom (PC CAM) + 011a FinePix S304/3800 Zoom (DSC) + 011b FinePix S304/3800 Zoom (PC CAM) + 011c FinePix A204/2650 Zoom (DSC) + 011d FinePix A204/2650 Zoom (PC CAM) + 0120 FinePix F700 Zoom (DSC) + 0121 FinePix F700 Zoom (PC CAM) + 0122 FinePix F410 Zoom (DSC) + 0123 FinePix F410 Zoom (PC CAM) + 0124 FinePix A310 Zoom (DSC) + 0125 FinePix A310 Zoom (PC CAM) + 0126 FinePix A210 Zoom (DSC) + 0127 FinePix A210 Zoom (PC CAM) + 0128 FinePix A205(S) Zoom (DSC) + 0129 FinePix A205(S) Zoom (PC CAM) + 012a FinePix F610 Zoom (DSC) + 012b FinePix Digital Camera 030513 + 012c FinePix S7000 Zoom (DSC) + 012d FinePix S7000 Zoom (PC CAM) + 012f FinePix Digital Camera 030731 + 0130 FinePix S5000 Zoom (DSC) + 0131 FinePix S5000 Zoom (PC CAM) + 013b FinePix Digital Camera 030722 + 013c FinePix S3000 Zoom (DSC) + 013d FinePix S3000 Zoom (PC CAM) + 013e FinePix F420 Zoom (DSC) + 013f FinePix F420 Zoom (PC CAM) + 0142 FinePix S7000 Zoom (PTP) + 0148 FinePix A330 Zoom (DSC) + 0149 FinePix A330 Zoom (UVC) + 014a FinePix A330 Zoom (PTP) + 014b FinePix A340 Zoom (DSC) + 014c FinePix A340 Zoom (UVC) + 0159 FinePix F710 Zoom (DSC) + 0165 FinePix S3500 Zoom (DSC) + 0168 FinePix E500 Zoom (DSC) + 0169 FinePix E500 Zoom (UVC) + 016b FinePix E510 Zoom (DSC) + 016c FinePix E510 Zoom (PC CAM) + 016e FinePix S5500 Zoom (DSC) + 016f FinePix S5500 Zoom (UVC) + 0171 FinePix E550 Zoom (DSC) + 0172 FinePix E550 Zoom (UVC) + 0177 FinePix F10 (DSC) + 0179 Finepix F10 (PTP) + 0186 FinePix S5200/S5600 Zoom (DSC) + 0188 FinePix S5200/S5600 Zoom (PTP) + 018e FinePix S9500 Zoom (DSC) + 018f FinePix S9500 Zoom (PTP) + 0192 FinePix E900 Zoom (DSC) + 0193 FinePix E900 Zoom (PTP) + 019b FinePix F30 (PTP) + 01af FinePix A700 (PTP) + 01bf FinePix F6000fd/S6500fd Zoom (PTP) + 01c0 FinePix F20 (PTP) + 01c1 FinePix F31fd (PTP) + 01c3 FinePix S5 Pro + 01c4 FinePix S5700 Zoom (PTP) + 01c5 FinePix F40fd (PTP) + 01c6 FinePix A820 Zoom (PTP) + 01d2 FinePix A800 Zoom (PTP) + 01d3 FinePix A920 (PTP) + 01d4 FinePix F50fd (PTP) + 01d5 FinePix F47 (PTP) + 01f7 FinePix J250 (PTP) + 01fd A160 + 023e FinePix AX300 + 0240 FinePix S2950 Digital Camera + 0241 FinePix S3200 Digital Camera + 0278 FinePix JV300 + 02c5 FinePix S9900W Digital Camera (PTP) + 5006 ASK-300 +04cc ST-Ericsson + 1122 Hub + 1520 USB 2.0 Hub (Avocent KVM) + 1521 USB 2.0 Hub + 1a62 GW Instek GSP-830 Spectrum Analyzer (HID) + 2323 Ux500 serial debug port + 2533 NFC device (PN533) + 8116 Camera +04cd Tatung Co. Of America +04ce ScanLogic Corp. + 0002 SL11R-IDE IDE Bridge + 0100 USB2PRN Printer Class + 0300 Phantom 336CX - C3 scanner + 04ce SL11DEMO, VID: 0x4ce, PID: 0x4ce + 07d1 SL11R, VID: 0x4ce, PID: 0x07D1 +04cf Myson Century, Inc. + 0022 OCZ Alchemy Series Elixir II Keyboard + 0800 MTP800 Mass Storage Device + 8810 CS8810 Mass Storage Device + 8811 CS8811 Mass Storage Device + 8813 CS8813 Mass Storage Device + 8818 USB2.0 to ATAPI Bridge Controller + 8819 USB 2.0 SD/MMC Reader + 9920 CS8819A2-114 Mass Storage Device +04d0 Digi International +04d1 ITT Canon +04d2 Altec Lansing Technologies + 0070 ADA70 Speakers + 0305 Non-Compliant Audio Device + 0311 ADA-310 Speakers + 2060 Claritel-i750 - vp + ff05 ADA-305 Speakers + ff47 Lansing HID Audio Controls + ff49 Lansing HID Audio Controls +04d3 VidUS, Inc. +04d4 LSI Logic, Inc. +04d5 Forte Technologies, Inc. +04d6 Mentor Graphics +04d7 Oki Semiconductor + 1be4 Bluetooth Device +04d8 Microchip Technology, Inc. + 0002 PicoLCD 20x2 + 0003 PICkit 2 Microcontroller Programmer + 000a CDC RS-232 Emulation Demo + 000b PIC18F2550 (32K Flashable 10 Channel, 10 Bit A/D USB Microcontroller) + 0032 PICkit1 + 0033 PICkit2 + 0036 PICkit Serial Analyzer + 00e0 PIC32 Starter Board + 04cd 28Cxxx EEPROM Programmer + 0a04 AGP LIN Serial Analyzer + 8000 In-Circuit Debugger + 8001 ICD2 in-circuit debugger + 8101 PIC24F Starter Kit + 8107 Microstick II + 8108 ChipKit Pro MX7 (PIC32MX) + 9004 Microchip REAL ICE + 900a PICkit3 + 9012 PICkit4 + 9015 ICD 4 In-Circuit Debugger + c001 PicoLCD 20x4 + e11c TL866CS EEPROM Programmer [MiniPRO] + edb4 micro PLC (ATSAMD51G19A) [Black Brix ECU II] + edb5 ATMEGA32U4 [Black Brix ECU] + f2c4 Macareux-labs Hygrometry Temperature Sensor + f2f7 Yepkit YKUSH + f3aa Macareux-labs Usbce Bootloader mode + f437 SBE Tech Ultrasonic Anemometer + f4b5 SmartScope + f5fe TrueRNG + f8da Hughski Ltd. ColorHug + f8e8 Harmony 300/350 Remote + f91c SPROG IIv3 + faff Dangerous Prototypes BusPirate v4 Bootloader mode + fb00 Dangerous Prototypes BusPirate v4 + fbb2 GCUSB-nStep stepper motor controller + fbba DiscFerret Magnetic Disc Analyser (bootloader mode) + fbbb DiscFerret Magnetic Disc Analyser (active mode) + fc1e Bachrus Speedometer Interface + fc92 Open Bench Logic Sniffer + ffee Devantech USB-ISS + ffef PICoPLC [APStech] +04d9 Holtek Semiconductor, Inc. + 0022 Portable Keyboard + 048e Optical Mouse + 0499 Optical Mouse + 1135 Mouse [MGK-15BU/MLK-15BU] + 1203 Keyboard + 1400 PS/2 keyboard + mouse controller + 1503 Keyboard + 1603 Keyboard + 1702 Keyboard LKS02 + 1818 Keyboard [Diatec Filco Majestouch 2] + 2011 Keyboard [Diatec Filco Majestouch 1] + 2013 Keyboard [Das Keyboard] + 2206 Fujitsu Siemens Mouse Esprimo Q + 2221 Keyboard + 2323 Keyboard + 2519 Shenzhen LogoTech 2.4GHz receiver + 2832 HT82A832R Audio MCU + 2834 HT82A834R Audio MCU + 4545 Keyboard [Diatec Majestouch 2 Tenkeyless] + a01c wireless multimedia keyboard with trackball [Trust ADURA 17911] + a050 Chatman V1 + a052 USB-zyTemp + a055 Keyboard + a096 Keyboard + a09f E-Signal LUOM G10 Mechanical Gaming Mouse + a100 Mouse [HV-MS735] + a11b Mouse [MX-3200] + e002 MCU +04da Panasonic (Matsushita) + 0901 LS-120 Camera + 0912 SDR-S10 + 0b01 CD-R/RW Drive + 0b03 SuperDisk 240MB + 0d01 CD-R Drive KXL-840AN + 0d09 CD-R Drive KXL-RW32AN + 0d0a CD-R Drive KXL-CB20AN + 0d0d CDRCB03 + 0d0e DVD-ROM & CD-R/RW + 0d14 DVD-RAM MLT08 + 0f07 KX-MB2030 Multifunction Laser Printer + 0f40 Printer + 104d Elite Panaboard UB-T880 (HID) + 104e Elite Panaboard Pen Adaptor (HID) + 1500 MFSUSB Driver + 1800 DY-WL10 802.11abgn Adapter [Broadcom BCM4323] + 1b00 MultiMediaCard + 2121 EB-VS6 + 2316 DVC Mass Storage Device + 2317 DVC USB-SERIAL Driver for WinXP + 2318 NV-GS11/230/250 (webcam mode) + 2319 NV-GS15 (webcam mode) + 231a NV-GS11/230/250 (DV mode) + 231d DVC Web Camera Device + 231e DVC DV Stream Device + 2372 Lumix Camera (Storage mode) + 2374 Lumix Camera (PTP mode) + 2451 HDC-SD9 + 245b HC-X920K (3MOS Full HD video camcorder) + 2477 SDR-H85 Camcorder (PC mode) + 2478 SDR-H85 Camcorder (recorder mode - SD card) + 2479 SDR-H85 Camcorder (recorder mode - HDD) + 2497 HDC-TM700 + 250c Gobi Wireless Modem (QDL mode) + 250d Gobi Wireless Modem + 3904 N5HBZ0000055 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] + 3908 N5HBZ0000062 802.11abgn Wireless Adapter [Atheros AR9374v1.1] + 3c04 JT-P100MR-20 [ePassport Reader] +04db Hypertec Pty, Ltd +04dc Huan Hsin Holdings, Ltd +04dd Sharp Corp. + 13a6 MFC2000 + 6006 AL-1216 + 6007 AL-1045 + 6008 AL-1255 + 6009 AL-1530CS + 600a AL-1540CS + 600b AL-1456 + 600c AL-1555 + 600d AL-1225 + 600e AL-1551CS + 600f AR-122E + 6010 AR-152E + 6011 AR-157E + 6012 SN-1045 + 6013 SN-1255 + 6014 SN-1456 + 6015 SN-1555 + 6016 AR-153E + 6017 AR-122E N + 6018 AR-153E N + 6019 AR-152E N + 601a AR-157E N + 601b AL-1217 + 601c AL-1226 + 601d AR-123E + 6021 IS01 + 7002 DVC Ver.1.0 + 7004 VE-CG40U Digital Still Camera + 7005 VE-CG30 Digital Still Camera + 7007 VL-Z7S Digital Camcorder + 8004 Zaurus SL-5000D/SL-5500 PDA + 8005 Zaurus A-300 + 8006 Zaurus SL-B500/SL-5600 PDA + 8007 Zaurus C-700 PDA + 9009 AR-M160 + 9014 IM-DR80 Portable NetMD Player + 9031 Zaurus C-750/C-760/C-860/SL-C3000 PDA + 9032 Zaurus SL-6000 + 903a GSM GPRS + 9050 Zaurus C-860 PDA + 9056 Viewcam Z + 9073 AM-900 + 9074 GSM GPRS + 90a9 Sharp Composite + 90d0 USB-to-Serial Comm. Port + 90f2 Sharp 3G GSM USB Control + 9120 WS004SH + 9122 WS007SH + 9123 W-ZERO3 ES Smartphone + 91a3 922SH Internet Machine + 939a IS03 +04de MindShare, Inc. +04df Interlink Electronics +04e1 Iiyama North America, Inc. + 0201 Monitor Hub +04e2 Exar Corp. + 1410 XR21V1410 USB-UART IC +04e3 Zilog, Inc. +04e4 ACC Microelectronics +04e5 Promise Technology +04e6 SCM Microsystems, Inc. + 0001 E-USB ATA Bridge + 0002 eUSCSI SCSI Bridge + 0003 eUSB SmartMedia Card Reader + 0005 eUSB SmartMedia/CompactFlash Card Reader + 0006 eUSB SmartMedia Card Reader + 0007 Hifd + 0009 eUSB ATA/ATAPI Adapter + 000a eUSB CompactFlash Adapter + 000b eUSCSI Bridge + 000c eUSCSI Bridge + 000d Dazzle MS + 0012 Dazzle SD/MMC + 0101 eUSB ATA Bridge (Sony Spressa USB CDRW) + 0311 Dazzle DM-CF + 0312 Dazzle DM-SD/MMC + 0313 Dazzle SM + 0314 Dazzle MS + 0322 e-Film Reader-5 + 0325 eUSB ORCA Quad Reader + 0327 Digital Media Reader + 03fe DMHS2 DFU Adapter + 0406 eUSB SmartDM Reader + 04e6 eUSB DFU Adapter + 04e7 STCII DFU Adapter + 04e8 eUSBDM DFU Adapter + 04e9 DM-E DFU Adapter + 0500 Veridicom 5thSense Fingerprint Sensor and eUSB SmartCard + 0701 DCS200 Loader Device + 0702 DVD Creation Station 200 + 0703 DVC100 Loader Device + 0704 Digital Video Creator 100 + 1001 SCR300 Smart Card Reader + 1010 USBAT-2 CompactFlash Card Reader + 1014 e-Film Reader-3 + 1020 USBAT ATA/ATAPI Adapter + 2007 RSA SecurID ComboReader + 2009 Citibank Smart Card Reader + 200a Reflex v.2 Smart Card Reader + 200d STR391 Reader + 5111 SCR331-DI SmartCard Reader + 5113 SCR333 SmartCard Reader + 5114 SCR331-DI SmartCard Reader + 5115 SCR335 SmartCard Reader + 5116 SCR331-LC1 / SCR3310 SmartCard Reader + 5117 SCR3320 - Smart Card Reader + 5118 Expresscard SIM Card Reader + 5119 SCR3340 - ExpressCard54 Smart Card Reader + 511b SmartCard Reader + 511d SCR3311 Smart Card Reader + 5120 SCR331-DI SmartCard Reader + 5121 SDI010 Smart Card Reader + 5151 SCR338 Keyboard Smart Card Reader + 5292 SCL011 RFID reader + 5410 SCR35xx Smart Card Reader + 5591 SCL3711-NFC&RW + 5810 uTrust 2700 R Smart Card Reader + e000 SCRx31 Reader + e001 SCR331 SmartCard Reader + e003 SPR532 PinPad SmartCard Reader +04e7 Elo TouchSystems + 0001 TouchScreen + 0002 Touchmonitor Interface 2600 Rev 2 + 0004 4000U CarrollTouch® Touchmonitor Interface + 0007 2500U IntelliTouch® Touchmonitor Interface + 0008 3000U AccuTouch® Touchmonitor Interface + 0009 4000U CarrollTouch® Touchmonitor Interface + 0020 Touchscreen Interface (2700) + 0021 Touchmonitor Interface + 0030 4500U CarrollTouch® Touchmonitor Interface + 0032 Touchmonitor Interface + 0033 Touchmonitor Interface + 0041 5010 Surface Capacitive Touchmonitor Interface + 0042 Touchmonitor Interface + 0050 2216 AccuTouch® Touchmonitor Interface + 0071 Touchmonitor Interface + 0072 Touchmonitor Interface + 0081 Touchmonitor Interface + 0082 Touchmonitor Interface + 00ff Touchmonitor Interface +04e8 Samsung Electronics Co., Ltd + 0001 Printer Bootloader + 0100 Kingston Flash Drive (128MB) + 0110 Connect3D Flash Drive + 0111 Connect3D Flash Drive + 0300 E2530 / GT-C3350 Phones (Mass storage mode) + 1003 MP3 Player and Recorder + 1006 SDC-200Z + 130c NX100 + 1323 WB700 Camera + 1f05 S2 Portable [JMicron] (500GB) + 1f06 HX-MU064DA portable harddisk + 2018 WIS09ABGN LinkStick Wireless LAN Adapter + 2035 Digital Photo Frame Mass Storage + 2036 Digital Photo Frame Mini Monitor + 3004 ML-4600 + 3005 Docuprint P1210 + 3008 ML-6060 laser printer + 300c ML-1210 Printer + 300e Laser Printer + 3104 ML-3550N + 3210 ML-5200A Laser Printer + 3226 Laser Printer + 3228 Laser Printer + 322a Laser Printer + 322c Laser Printer + 3230 ML-1440 + 3232 Laser Printer + 3236 ML-1450 + 3238 ML-1430 + 323a ML-1710 Printer + 323b Phaser 3130 + 323c Laser Printer + 323d Phaser 3120 + 323e Laser Printer + 3240 Laser Printer + 3242 ML-1510 Laser Printer + 3248 Color Laser Printer + 324a Laser Printer + 324c ML-1740 Printer + 324d Phaser 3121 + 3256 ML-1520 Laser Printer + 325b Xerox Phaser 3117 Laser Printer + 325f Phaser 3425 Laser Printer + 3260 CLP-510 Color Laser Printer + 3268 ML-1610 Mono Laser Printer + 326c ML-2010P Mono Laser Printer + 3276 ML-3050/ML-3051 Laser Printer + 327e ML-2510 Series + 328e CLP-310 Color Laser Printer + 3292 ML-1640 Series Laser Printer + 3296 ML-2580N Mono Laser Printer + 3297 ML-191x/ML-252x Laser Printer + 329f CLP-325 Color Laser Printer + 3301 ML-1660 Series + 330c ML-1865 + 330f ML-216x Series Laser Printer + 3310 ML-331x Series Laser Printer + 3315 ML-2540 Series Laser Printer + 331e M262x/M282x Xpress Series Laser Printer + 3409 SCX-4216F Scanner + 340c SCX-5x15 series + 340d SCX-6x20 series + 340e MFP 560 series + 340f Printing Support + 3412 SCX-4x20 series + 3413 SCX-4100 Scanner + 3415 Composite Device + 3419 Composite Device + 341a Printing Support + 341b SCX-4200 series + 341c Composite Device + 341d Composite Device + 341f Composite Device + 3420 Composite Device + 3426 SCX-4500 Laser Printer + 342d SCX-4x28 Series + 344f SCX-3400 Series + 347e C48x Series Color Laser Multifunction Printer + 3605 InkJet Color Printer + 3606 InkJet Color Printer + 3609 InkJet Color Printer + 3902 InkJet Color Printer + 3903 Xerox WorkCentre XK50cx + 390f InkJet Color Printer + 3911 SCX-1020 series + 4005 GT-S8000 Jet (msc) + 4f1f GT-S8000 Jet (mtp) + 5000 YP-MF series + 5001 YP-100 + 5002 YP-30 + 5003 YP-700 + 5004 YP-30 + 5005 YP-300 + 5006 YP-750 + 500d MP3 Player + 5010 Yepp YP-35 + 5011 YP-780 + 5013 YP-60 + 5015 yepp upgrade + 501b MP3 Player + 5021 Yepp YP-ST5 + 5026 YP-MT6V + 5027 YP-T7 + 502b YP-F1 + 5032 YP-J70 + 503b YP-U1 MP3 Player + 503d YP-T7F + 5041 YP-Z5 + 5050 YP-U2 MP3 Player + 5051 YP-F2R + 5055 YP-T9 + 507d YP-U3 (mtp) + 507f YP-T9J + 5080 Yepp YP-K3 (msc) + 5081 Yepp YP-K3 (mtp) + 5082 YP-P2 (msc) + 5083 YP-P2 (mtp) + 508a YP-T10 + 508b YP-S5 MP3 Player + 508c YP-S5 + 5090 YP-S3 (msc) + 5091 YP-S3 (mtp) + 5092 YP-U4 (msc) + 5093 YP-U4 (mtp) + 5095 YP-S2 + 510f YP-R1 + 5119 Yepp YP-P3 + 511c YP-Q2 + 5121 YP-U5 + 5123 Yepp YP-M1 + 5a00 YP-NEU + 5a01 YP-NDU + 5a03 Yepp MP3 Player + 5a04 YP-800 + 5a08 YP-90 + 5a0f Meizu M6 MiniPlayer + 5b01 Memory Stick Reader/Writer + 5b02 Memory Stick Reader/Writer + 5b03 Memory Stick Reader/Writer + 5b04 Memory Stick Reader/Writer + 5b05 Memory Stick Reader/Writer + 5b11 SEW-2001u Card + 5f00 NEXiO Sync + 5f01 NEXiO Sync + 5f02 NEXiO Sync + 5f03 NEXiO Sync + 5f04 NEXiO Sync + 5f05 STORY Station 1TB + 6032 G2 Portable hard drive + 6033 G2 Portable device + 6034 G2 Portable hard drive + 60b3 M2 Portable Hard Drive + 60c4 M2 Portable Hard Drive USB 3.0 + 6124 D3 Station External Hard Drive + 6125 D3 Station External Hard Drive + 61b5 M3 Portable Hard Drive 2TB + 61b6 M3 Portable Hard Drive 1TB + 61b7 M3 Portable Hard Drive 4TB + 61f3 Portable SSD T3 (MU-PT250B, MU-PT500B) + 61f5 Portable SSD T5 + 6601 Mobile Phone + 6602 Galaxy + 6603 Galaxy + 6611 MITs Sync + 6613 MITs Sync + 6615 MITs Sync + 6617 MITs Sync + 6619 MITs Sync + 661b MITs Sync + 661e Handheld + 6620 Handheld + 6622 Handheld + 6624 Handheld + 662e MITs Sync + 6630 MITs Sync + 6632 MITs Sync + 663e D900e/B2100 Phone + 663f SGH-E720/SGH-E840 + 6640 Usb Modem Enumerator + 6651 i8510 Innov8 + 6702 X830 + 6708 U600 Phone + 6709 U600 + 6734 Juke + 6759 D900e/B2100 Media Player + 675a D900e/B2100 Mass Storage + 675b D900e Camera + 6772 Standalone LTE device (Trial) + 6795 S5230 + 6802 Standalone HSPA device + 6806 Composite LTE device (Trial) + 6807 Composite HSPA device + 681c Galaxy Portal/Spica/S + 681d Galaxy Portal/Spica Android Phone + 6843 E2530 Phone (Samsung Kies mode) + 684e Wave (GT-S8500) + 685b GT-I9100 Phone [Galaxy S II] (mass storage mode) + 685c GT-I9250 Phone [Galaxy Nexus] (Mass storage mode) + 685d GT-I9100 Phone [Galaxy S II] (Download mode) + 685e GT-I9100 / GT-C3350 Phones (USB Debugging mode) + 6860 Galaxy series, misc. (MTP mode) + 6863 Galaxy series, misc. (tethering mode) + 6864 GT-I9070 (network tethering, USB debugging enabled) + 6865 Galaxy (PTP mode) + 6866 Galaxy (debugging mode) + 6868 Escape Composite driver for Android Phones: Modem+Diagnostic+ADB + 6875 GT-B3710 Standalone LTE device (Commercial) + 6876 GT-B3710 LTE Modem + 6877 Galaxy S + 687a GT-E2370 mobile phone + 6888 GT-B3730 Composite LTE device (Commercial) + 6889 GT-B3730 Composite LTE device (Commercial) + 689a LTE Storage Driver [CMC2xx] + 689e GT-S5670 [Galaxy Fit] + 68aa Reality + 7011 SEW-2003U Card + 7021 Bluetooth Device + 7061 eHome Infrared Receiver + 7080 Anycall SCH-W580 + 7081 Human Interface Device + 7301 Fingerprint Device + 8001 Handheld + d003 GT-I9003 + e020 SERI E02 SCOM 6200 UMTS Phone + e021 SERI E02 SCOM 6200 Virtual UARTs + e022 SERI E02 SCOM 6200 Flash Load Disk + f000 Intensity 3 (Mass Storage Mode) + ff30 SG_iMON +04e9 PC-Tel, Inc. +04ea Brooktree Corp. +04eb Northstar Systems, Inc. + e004 eHome Infrared Transceiver +04ec Tokyo Electron Device, Ltd +04ed Annabooks +04ef Pacific Electronic International, Inc. +04f0 Daewoo Electronics Co., Ltd +04f1 Victor Company of Japan, Ltd + 0001 GC-QX3 Digital Still Camera + 0004 GR-DVL815U Digital Video Camera + 0006 DV Camera Storage + 0008 GZ-MG30AA/MC500E Digital Video Camera + 0009 GR-DX25EK Digital Video Camera + 000a GR-D72 Digital Video Camera + 1001 GC-A50 Camera Device + 3008 MP-PRX1 Ethernet + 3009 MP-XP7250 WLAN Adapter +04f2 Chicony Electronics Co., Ltd + 0001 KU-8933 Keyboard + 0002 NT68P81 Keyboard + 0110 KU-2971 Keyboard + 0111 KU-9908 Keyboard + 0112 KU-8933 Keyboard with PS/2 Mouse port + 0116 KU-2971/KU-0325 Keyboard + 0200 KBR-0108 + 0201 Gaming Keyboard KPD0250 + 0220 Wireless HID Receiver + 0402 Genius LuxeMate i200 Keyboard + 0403 KU-0420 keyboard + 0418 KU-0418 Tactical Pad + 0618 RG-0618U Wireless HID Receiver & KG-0609 Wireless Keyboard with Touchpad + 0718 wired mouse + 0760 Acer KU-0760 Keyboard + 0833 KU-0833 Keyboard + 0841 HP Multimedia Keyboard + 0860 2.4G Multimedia Wireless Kit + 1061 HP KG-1061 Wireless Keyboard+Mouse + 1121 Periboard 717 Mini Wireless Keyboard + a001 E-Video DC-100 Camera + a120 ORITE CCD Webcam(PC370R) + a121 ORITE CCD Webcam(PC370R) + a122 ORITE CCD Webcam(PC370R) + a123 ORITE CCD Webcam(PC370R) + a124 ORITE CCD Webcam(PC370R) + a128 PC Camera (SN9C202 + OV7663 + EEPROM) + a133 Gateway Webcam + a136 LabTec Webcam 5500 + a147 Medion Webcam + a204 DSC WIA Device (1300) + a208 DSC WIA Device (2320) + a209 Labtec DC-2320 + a20a DSC WIA Device (3310) + a20c DSC WIA Device (3320) + a210 Audio Device + b008 USB 2.0 Camera + b009 Integrated Camera + b010 Integrated Camera + b012 1.3 MPixel UVC Webcam + b013 USB 2.0 Camera + b015 VGA 24fps UVC Webcam + b016 VGA 30fps UVC Webcam + b018 2M UVC Webcam + b021 ViewSonic 1.3M, USB2.0 Webcam + b022 Gateway USB 2.0 Webcam + b023 Gateway USB 2.0 Webcam + b024 USB 2.0 Webcam + b025 Camera + b027 Gateway USB 2.0 Webcam + b028 VGA UVC Webcam + b029 1.3M UVC Webcam + b036 Asus Integrated 0.3M UVC Webcam + b044 Acer CrystalEye Webcam + b057 integrated USB webcam + b059 CKF7037 HP webcam + b064 CNA7137 Integrated Webcam + b070 Camera + b071 2.0M UVC Webcam / CNF7129 + b083 CKF7063 Webcam (HP) + b091 Webcam + b104 CNF7069 Webcam + b107 CNF7070 Webcam + b14c CNF8050 Webcam + b159 CNF8243 Webcam + b15c Sony Vaio Integrated Camera + b175 4-Port Hub + b1aa Webcam-101 + b1ac HP Laptop Integrated Webcam [2 MP Fixed] + b1b4 Lenovo Integrated Camera + b1b9 Asus Integrated Webcam + b1cf Lenovo Integrated Camera + b1d6 CNF9055 Toshiba Webcam + b1d8 1.3M Webcam + b1e4 Toshiba Integrated Webcam + b213 Fujitsu Integrated Camera + b217 Lenovo Integrated Camera (0.3MP) + b221 integrated camera + b230 Integrated HP HD Webcam + b257 Lenovo Integrated Camera + b26b Sony Visual Communication Camera + b272 Lenovo EasyCamera + b2b0 Camera + b2b9 Lenovo Integrated Camera UVC + b2da thinkpad t430s camera + b2db Thinkpad T430 camera + b2ea Integrated Camera [ThinkPad] + b2f4 HP Webcam-50 + b330 Asus 720p CMOS webcam + b354 UVC 1.00 device HD UVC WebCam + b394 Integrated Camera + b3eb HP 720p HD Monitor Webcam + b3f6 HD WebCam (Acer) + b3fd HD WebCam (Asus N-series) + b40e HP Truevision HD camera + b444 Lenovo Integrated Webcam + b563 Integrated Camera + b5ce Integrated Camera + b5cf Integrated IR Camera + b5db HP Webcam + b604 Integrated Camera (1280x720@30) +04f3 Elan Microelectronics Corp. + 000a Touchscreen + 0103 ActiveJet K-2024 Multimedia Keyboard + 016f Touchscreen + 01a4 Wireless Keyboard + 0201 Touchscreen + 0210 Optical Mouse + 0212 Laser Mouse + 0214 Lynx M9 Optical Mouse + 0230 3D Optical Mouse + 0232 Mouse + 0234 Optical Mouse + 0235 Optical Mouse + 02f4 2.4G Cordless Mouse + 0381 Touchscreen + 04a0 Dream Cheeky Stress/Panic Button + 2234 Touchscreen +04f4 Harting Elektronik, Inc. +04f5 Fujitsu-ICL Systems, Inc. +04f6 Norand Corp. +04f7 Newnex Technology Corp. +04f8 FuturePlus Systems +04f9 Brother Industries, Ltd + 0002 HL-1050 Laser Printer + 0005 Printer + 0006 HL-1240 Laser Printer + 0007 HL-1250 Laser Printer + 0008 HL-1270 Laser Printer + 0009 Printer + 000a P2500 series + 000b Printer + 000c Printer + 000d HL-1440 Laser Printer + 000e HL-1450 series + 000f HL-1470N series + 0010 Printer + 0011 Printer + 0012 Printer + 0013 Printer + 0014 Printer + 0015 Printer + 0016 Printer + 0017 Printer + 0018 Printer + 001a HL-1430 Laser Printer + 001c Printer + 001e Printer + 0020 HL-5130 series + 0021 HL-5140 series + 0022 HL-5150D series + 0023 HL-5170DN series + 0024 Printer + 0025 Printer + 0027 HL-2030 Laser Printer + 0028 Printer + 0029 Printer + 002a HL-52x0 series + 002b HL-5250DN Printer + 002c Printer + 002d Printer + 0039 HL-5340 series + 0041 HL-2250DN Laser Printer + 0042 HL-2270DW Laser Printer + 0100 MFC8600/9650 series + 0101 MFC9600/9870 series + 0102 MFC9750/1200 series + 0104 MFC-8300J + 0105 MFC-9600J + 0106 MFC-7300C + 0107 MFC-7400C + 0108 MFC-9200C + 0109 MFC-830 + 010a MFC-840 + 010b MFC-860 + 010c MFC-7400J + 010d MFC-9200J + 010e MFC-3100C Scanner + 010f MFC-5100C + 0110 MFC-4800 Scanner + 0111 MFC-6800 + 0112 DCP1000 Port(FaxModem) + 0113 MFC-8500 + 0114 MFC9700 Port(FaxModem) + 0115 MFC-9800 Scanner + 0116 DCP1400 Scanner + 0119 MFC-9660 + 011a MFC-9860 + 011b MFC-9880 + 011c MFC-9760 + 011d MFC-9070 + 011e MFC-9180 + 011f MFC-9160 + 0120 MFC580 Port(FaxModem) + 0121 MFC-590 + 0122 MFC-5100J + 0124 MFC-4800J + 0125 MFC-6800J + 0127 MFC-9800J + 0128 MFC-8500J + 0129 Imagistics 2500 (MFC-8640D clone) + 012b MFC-9030 + 012e FAX4100e IntelliFax 4100e + 012f FAX-4750e + 0130 FAX-5750e + 0132 MFC-5200C RemovableDisk + 0135 MFC-100 Scanner + 0136 MFC-150CL Scanner + 013c MFC-890 Port + 013d MFC-5200J + 013e MFC-4420C RemovableDisk + 013f MFC-4820C RemovableDisk + 0140 DCP-8020 + 0141 DCP-8025D + 0142 MFC-8420 + 0143 MFC-8820D + 0144 DCP-4020C RemovableDisk + 0146 MFC-3220C + 0147 FAX-1820C Printer + 0148 MFC-3320CN + 0149 FAX-1920CN Printer + 014a MFC-3420C + 014b MFC-3820CN + 014c DCP-3020C + 014d FAX-1815C Printer + 014e MFC-8820J + 014f DCP-8025J + 0150 MFC-8220 Port(FaxModem) + 0151 MFC-8210J + 0153 DCP-1000J + 0157 MFC-3420J Printer + 0158 MFC-3820JN Port(FaxModem) + 015d MFC Composite Device + 015e DCP-8045D + 015f MFC-8440 + 0160 MFC-8840D + 0161 MFC-210C + 0162 MFC-420CN Remote Setup Port + 0163 MFC-410CN RemovableDisk + 0165 MFC-620CN + 0166 MFC-610CLN RemovableDisk + 0168 MFC-620CLN + 0169 DCP-110C RemovableDisk + 016b DCP-310CN RemovableDisk + 016c FAX-2440C Printer + 016d MFC-5440CN + 016e MFC-5840CN Remote Setup Port + 0170 FAX-1840C Printer + 0171 FAX-1835C Printer + 0172 FAX-1940CN Printer + 0173 MFC-3240C Remote Setup Port + 0174 MFC-3340CN RemovableDisk + 017b Imagistics sx2100 + 0180 MFC-7420 + 0181 MFC-7820N Port(FaxModem) + 0182 DCP-7010 + 0183 DCP-7020 + 0184 DCP-7025 Printer + 0185 MFC-7220 Printer + 0186 Composite Device + 0187 FAX-2820 Printer + 0188 FAX-2920 Printer + 018a MFC-9420CN + 018c DCP-115C + 018d DCP-116C + 018e DCP-117C + 018f DCP-118C + 0190 DCP-120C + 0191 DCP-315CN + 0192 DCP-340CW + 0193 MFC-215C + 0194 MFC-425CN + 0195 MFC-820CW Remote Setup Port + 0196 MFC-820CN Remote Setup Port + 0197 MFC-640CW + 019a MFC-840CLN Remote Setup Port + 01a2 MFC-8640D + 01a3 Composite Device + 01a4 DCP-8065DN Printer + 01a5 MFC-8460N Port(FaxModem) + 01a6 MFC-8860DN Port(FaxModem) + 01a7 MFC-8870DW Printer + 01a8 DCP-130C + 01a9 DCP-330C + 01aa DCP-540CN + 01ab MFC-240C + 01ae DCP-750CW RemovableDisk + 01af MFC-440CN + 01b0 MFC-660CN + 01b1 MFC-665CW + 01b2 MFC-845CW + 01b4 MFC-460CN + 01b5 MFC-630CD + 01b6 MFC-850CDN + 01b7 MFC-5460CN + 01b8 MFC-5860CN + 01ba MFC-3360C + 01bd MFC-8660DN + 01be DCP-750CN RemovableDisk + 01bf MFC-860CDN + 01c0 DCP-128C + 01c1 DCP-129C + 01c2 DCP-131C + 01c3 DCP-329C + 01c4 DCP-331C + 01c5 MFC-239C + 01c9 DCP-9040CN + 01ca MFC-9440CN + 01cb DCP-9045CDN + 01cc MFC-9840CDW + 01ce DCP-135C + 01cf DCP-150C + 01d0 DCP-350C + 01d1 DCP-560CN + 01d2 DCP-770CW + 01d3 DCP-770CN + 01d4 MFC-230C + 01d5 MFC-235C + 01d6 MFC-260C + 01d7 MFC-465CN + 01d8 MFC-680CN + 01d9 MFC-685CW + 01da MFC-885CW + 01db MFC-480CN + 01dc MFC-650CD + 01dd MFC-870CDN + 01de MFC-880CDN + 01df DCP-155C + 01e0 MFC-265C + 01e1 DCP-153C + 01e2 DCP-157C + 01e3 DCP-353C + 01e4 DCP-357C + 01e7 MFC-7340 + 01e9 DCP-7040 + 01ea DCP-7030 + 01eb MFC-7320 + 01ec MFC-9640CW + 01f4 MFC-5890CN + 020a MFC-8670DN + 020c DCP-9042CDN + 020d MFC-9450CDN + 0216 MFC-8880DN + 0217 MFC-8480DN + 0219 MFC-8380DN + 021a MFC-8370DN + 021b DCP-8070D + 021c MFC-9320CW + 021d MFC-9120CN + 021e DCP-9010CN + 021f DCP-8085DN + 0220 MFC-9010CN + 0222 DCP-195C + 0223 DCP-365CN + 0224 DCP-375CW + 0225 DCP-395CN + 0227 DCP-595CN + 0228 MFC-255CW + 0229 MFC-295CN + 022a MFC-495CW + 022b MFC-495CN + 022c MFC-795CW + 022d MFC-675CD + 022e MFC-695CDN + 022f MFC-735CD + 0230 MFC-935CDN + 0234 DCP-373CW + 0235 DCP-377CW + 0236 DCP-390CN + 0239 MFC-253CW + 023a MFC-257CW + 023e DCP-197C + 023f MFC-8680DN + 0240 MFC-J950DN + 0248 DCP-7055 scanner/printer + 024e MFC-7460DN + 0253 DCP-J125 + 0254 DCP-J315W + 0255 DCP-J515W + 0256 DCP-J515N + 0257 DCP-J715W + 0258 DCP-J715N + 0259 MFC-J220 + 025a MFC-J410 + 025b MFC-J265W + 025c MFC-J415W + 025d MFC-J615W + 025e MFC-J615N + 025f MFC-J700D + 0260 MFC-J800D + 0261 MFC-J850DN + 026b MFC-J630W + 026d MFC-J805D + 026e MFC-J855DN + 026f MFC-J270W + 0270 MFC-7360N + 0273 DCP-7057 scanner/printer + 0276 MFC-5895CW + 0278 MFC-J410W + 0279 DCP-J525W + 027a DCP-J525N + 027b DCP-J725DW + 027c DCP-J725N + 027d DCP-J925DW + 027e MFC-J955DN + 027f MFC-J280W + 0280 MFC-J435W + 0281 MFC-J430W + 0282 MFC-J625DW + 0283 MFC-J825DW + 0284 MFC-J825N + 0285 MFC-J705D + 0287 MFC-J860DN + 0288 MFC-J5910DW + 0289 MFC-J5910CDW + 028a DCP-J925N + 028d MFC-J835DW + 028f MFC-J425W + 0290 MFC-J432W + 0291 DCP-8110DN + 0292 DCP-8150DN + 0293 DCP-8155DN + 0294 DCP-8250DN + 0295 MFC-8510DN + 0296 MFC-8520DN + 0298 MFC-8910DW + 0299 MFC-8950DW + 029a MFC-8690DW + 029c MFC-8515DN + 029e MFC-9125CN + 029f MFC-9325CW + 02a0 DCP-J140W + 02a5 MFC-7240 + 02a6 FAX-2940 + 02a7 FAX-2950 + 02a8 MFC-7290 + 02ab FAX-2990 + 02ac DCP-8110D + 02ad MFC-9130CW + 02ae MFC-9140CDN + 02af MFC-9330CDW + 02b0 MFC-9340CDW + 02b1 DCP-9020CDN + 02b2 MFC-J810DN + 02b3 MFC-J4510DW + 02b4 MFC-J4710DW + 02b5 DCP-8112DN + 02b6 DCP-8152DN + 02b7 DCP-8157DN + 02b8 MFC-8512DN + 02ba MFC-8912DW + 02bb MFC-8952DW + 02bc DCP-J540N + 02bd DCP-J740N + 02be MFC-J710D + 02bf MFC-J840N + 02c0 DCP-J940N + 02c1 MFC-J960DN + 02c2 DCP-J4110DW + 02c3 MFC-J4310DW + 02c4 MFC-J4410DW + 02c5 MFC-J4610DW + 02c6 DCP-J4210N + 02c7 MFC-J4510N + 02c8 MFC-J4910CDW + 02c9 MFC-J4810DN + 02ca MFC-8712DW + 02cb MFC-8710DW + 02cc MFC-J2310 + 02cd MFC-J2510 + 02ce DCP-7055W + 02cf DCP-7057W + 02d0 DCP-1510 + 02d1 MFC-1810 + 02d3 DCP-9020CDW + 02d4 MFC-8810DW + 02dd DCP-J4215N + 02de DCP-J132W + 02df DCP-J152W + 02e0 DCP-J152N + 02e1 DCP-J172W + 02e2 DCP-J552DW + 02e3 DCP-J552N + 02e4 DCP-J752DW + 02e5 DCP-J752N + 02e6 DCP-J952N + 02e7 MFC-J245 + 02e8 MFC-J470DW + 02e9 MFC-J475DW + 02ea MFC-J285DW + 02eb MFC-J650DW + 02ec MFC-J870DW + 02ed MFC-J870N + 02ee MFC-J720D + 02ef MFC-J820DN + 02f0 MFC-J980DN + 02f1 MFC-J890DN + 02f2 MFC-J6520DW + 02f3 MFC-J6570CDW + 02f4 MFC-J6720DW + 02f5 MFC-J6920DW + 02f6 MFC-J6970CDW + 02f7 MFC-J6975CDW + 02f8 MFC-J6770CDW + 02f9 DCP-J132N + 02fa MFC-J450DW + 02fb MFC-J875DW + 02fc DCP-J100 + 02fd DCP-J105 + 02fe MFC-J200 + 02ff MFC-J3520 + 0300 MFC-J3720 + 030f DCP-L8400CDN + 0310 DCP-L8450CDW + 0311 MFC-L8600CDW + 0312 MFC-L8650CDW + 0313 MFC-L8850CDW + 0314 MFC-L9550CDW + 0318 MFC-7365DN + 0320 MFC-L2740DW + 0321 DCP-L2500D + 0322 DCP-L2520DW + 0324 DCP-L2520D + 0326 DCP-L2540DN + 0328 DCP-L2540DW + 0329 DCP-L2560DW + 0330 HL-L2380DW + 0331 MFC-L2700DW + 0335 FAX-L2700DN + 0337 MFC-L2720DW + 0338 MFC-L2720DN + 0339 DCP-J4120DW + 033a MFC-J4320DW + 033c MFC-J2320 + 033d MFC-J4420DW + 0340 MFC-J4620DW + 0341 MFC-J2720 + 0342 MFC-J4625DW + 0343 MFC-J5320DW + 0346 MFC-J5620DW + 0347 MFC-J5720DW + 0349 DCP-J4220N + 034b MFC-J4720N + 034e MFC-J5720CDW + 034f MFC-J5820DN + 0350 MFC-J5620CDW + 0351 DCP-J137N + 0353 DCP-J557N + 0354 DCP-J757N + 0355 DCP-J957N + 0356 MFC-J877N + 0357 MFC-J727D + 0358 MFC-J987DN + 0359 MFC-J827DN + 035a MFC-J897DN + 035b DCP-1610W + 035c DCP-1610NW + 035d MFC-1910W + 035e MFC-1910NW + 0360 DCP-1618W + 0361 MFC-1919NW + 0364 MFC-J5625DW + 0365 MFC-J4520DW + 0366 MFC-J5520DW + 0367 DCP-7080D + 0368 DCP-7080 + 0369 DCP-7180DN + 036a DCP-7189DW + 036b MFC-7380 + 036c MFC-7480D + 036d MFC-7880DN + 036e MFC-7889DW + 036f DCP-9022CDW + 0370 MFC-9142CDN + 0371 MFC-9332CDW + 0372 MFC-9342CDW + 0373 MFC-L2700D + 0376 DCP-1600 + 0377 MFC-1900 + 0378 DCP-1608 + 0379 DCP-1619 + 037a MFC-1906 + 037b MFC-1908 + 037c ADS-2000e + 037d ADS-2100e + 037e ADS-2500We + 037f ADS-2600We + 0380 DCP-J562DW + 0381 DCP-J562N + 0383 DCP-J962N + 0384 MFC-J480DW + 0385 MFC-J485DW + 0386 MFC-J460DW + 0388 MFC-J680DW + 0389 MFC-J880DW + 038a MFC-J885DW + 038b MFC-J880N + 038c MFC-J730DN + 038d MFC-J990DN + 038e MFC-J830DN + 038f MFC-J900DN + 0390 MFC-J5920DW + 0392 MFC-L2705DW + 0393 DCP-T300 + 0394 DCP-T500W + 0395 DCP-T700W + 0396 MFC-T800W + 0397 DCP-J963N + 03b3 MFC-J6925DW + 03b4 MFC-J6573CDW + 03b5 MFC-J6973CDW + 03b6 MFC-J6990CDW + 03bb MFC-L2680W + 03bc MFC-L2700DN + 03bd DCP-J762N + 1000 Printer + 1002 Printer + 2002 PTUSB Printing + 2004 PT-2300/2310 p-Touch Laber Printer + 2007 PT-2420PC P-touch Label Printer + 2015 QL-500 P-touch label printer + 2016 QL-550 P-touch label printer + 201a PT-18R P-touch label printer + 201b QL-650TD P-touch Label Printer + 2027 QL-560 P-touch Label Printer + 2028 QL-570 P-touch Label Printer + 202b PT-7600 P-touch Label Printer + 2041 PT-2730 P-touch Label Printer + 2061 PT-P700 P-touch Label Printer + 2064 PT-P700 P-touch Label Printer RemovableDisk + 209b QL-800 P-touch Label Printer + 209c QL-810W P-touch Label Printer + 209d QL-820NWB P-touch Label Printer + 2100 Card Reader Writer + 2102 Sewing machine + 60a0 ADS-2000 + 60a1 ADS-2100 + 60a4 ADS-2500W + 60a5 ADS-2600W + 60a6 ADS-1000W + 60a7 ADS-1100W + 60a8 ADS-1500W + 60a9 ADS-1600W +04fa Dallas Semiconductor + 2490 DS1490F 2-in-1 Fob, 1-Wire adapter + 4201 DS4201 Audio DAC +04fb Biostar Microtech International Corp. +04fc Sunplus Technology Co., Ltd + 0003 CM1092 / Wintech CM-5098 Optical Mouse + 0005 USB OpticalWheel Mouse + 0013 ViewMate Desktop Mouse CC2201 + 0015 ViewMate Desktop Mouse CC2201 + 00d3 00052486 / Laser Mouse M1052 [hama] + 0171 SPCA1527A/SPCA1528 SD card camera (Mass Storage mode) + 0201 SPCP825 RS232C Adapter + 0232 Fingerprint + 0538 Wireless Optical Mouse 2.4G [Bright] + 0561 Flexcam 100 + 05d8 Wireless keyboard/mouse + 05da SPEEDLINK SNAPPY Wireless Mouse Nano + 0c15 SPIF215A SATA bridge + 0c25 SATALink SPIF225A + 1528 SPCA1527A/SPCA1528 SD card camera (webcam mode) + 1533 Mass Storage + 2080 ASUS Webcam + 500c CA500C Digital Camera + 504a Aiptek Mini PenCam 1.3 + 504b Aiptek Mega PockerCam 1.3/Maxell MaxPocket LE 1.3 + 5330 Digitrex 2110 + 5331 Vivitar Vivicam 10 + 5360 Sunplus Generic Digital Camera + 5563 Digital Media Player MP3/WMA [The Sharper Image] + 5720 Card Reader Driver + 6333 Siri A9 UVC chipset + 7333 Finet Technology Palmpix DC-85 + 757a Aiptek, MP315 MP3 Player + ffff PureDigital Ritz Disposable +04fd Soliton Systems, K.K. + 0003 Smart Card Reader II +04fe PFU, Ltd + 0006 Happy Hacking Keyboard Lite2 +04ff E-CMOS Corp. +0500 Siam United Hi-Tech + 0001 DART Keyboard Mouse + 0002 DART-2 Keyboard +0501 Fujikura DDK, Ltd +0502 Acer, Inc. + 0001 Handheld + 0736 Handheld + 15b1 PDA n311 + 1631 c10 Series + 1632 c20 Series + 16e1 n10 Handheld Sync + 16e2 n20 Pocket PC Sync + 16e3 n30 Handheld Sync + 2008 Liquid Gallant Duo E350 (preloader) + 3202 Liquid + 3203 Liquid (Debug mode) + 3230 BeTouch E120 + 3317 Liquid + 3325 Iconia tablet A500 + 3341 Iconia tablet A500 + 33c3 Liquid Gallant Duo E350 + 33c4 Liquid Gallant Duo E350 (debug mode) + 33c7 Liquid Gallant Duo E350 (USB tethering) + 33c8 Liquid Gallant Duo E350 (debug mode, USB tethering) + d001 Divio NW801/DVC-V6+ Digital Camera +0503 Hitachi America, Ltd +0504 Hayes Microcomputer Products +0506 3Com Corp. + 009d HomeConnect Camera + 00a0 3CREB96 Bluetooth Adapter + 00a1 Bluetooth Device + 00a2 Bluetooth Device + 00df 3Com Home Connect lite + 0100 HomeConnect ADSL Modem Driver + 03e8 3C19250 Ethernet [klsi] + 0a01 3CRSHEW696 Wireless Adapter + 0a11 3CRWE254G72 802.11g Adapter + 11f8 HomeConnect 3C460 + 2922 HomeConnect Cable Modem External with + 3021 U.S.Robotics 56000 Voice FaxModem Pro + 4601 3C460B 10/100 Ethernet Adapter + f002 3CP4218 ADSL Modem (pre-init) + f003 3CP4218 ADSL Modem + f100 3CP4218 ADSL Modem (pre-init) +0507 Hosiden Corp. + 0011 Konami ParaParaParadise Controller +0508 Clarion Co., Ltd +0509 Aztech Systems, Ltd + 0801 ADSL Modem + 0802 ADSL Modem (RFC1483) + 0806 DSL Modem + 080f Binatone ADSL500 Modem Network Interface + 0812 Pirelli ADSL Modem Network Interface +050a Cinch Connectors +050b Cable System International +050c InnoMedia, Inc. +050d Belkin Components + 0004 Direct Connect + 0012 F8T012 Bluetooth Adapter + 0013 F8T013 Bluetooth Adapter + 0017 B8T017 Bluetooth+EDR 2.1 / F4U017 USB 2.0 7-port Hub + 003a Universal Media Reader + 0050 F5D6050 802.11b Wireless Adapter v2000 [Atmel at76c503a] + 0081 F8T001v2 Bluetooth + 0083 Bluetooth Device + 0084 F8T003v2 Bluetooth + 0102 Flip KVM + 0103 F5U103 Serial Adapter [etek] + 0106 VideoBus II Adapter, Video + 0108 F1DE108B KVM + 0109 F5U109/F5U409 PDA Adapter + 0115 SCSI Adapter + 0119 F5U120-PC Dual PS/2 Ports / F5U118-UNV ADB Adapter + 0121 F5D5050 100Mbps Ethernet + 0122 Ethernet Adapter + 0131 Bluetooth Device with trace filter + 016a Bluetooth Mini Dongle + 0200 Nostromo SpeedPad n52te Gaming Keyboard + 0201 Peripheral Switch + 0208 USBView II Video Adapter [nt1004] + 0210 F5U228 Hi-Speed USB 2.0 DVD Creator + 0211 F5U211 USB 2.0 15-in-1 Media Reader & Writer + 0224 F5U224 USB 2.0 4-Port Hub + 0234 F5U234 USB 2.0 4-Port Hub + 0237 F5U237 USB 2.0 7-Port Hub + 0240 F5U240 USB 2.0 CF Card Reader + 0249 USB 2 Flash Media Device + 0257 F5U257 Serial + 0304 FSU304 USB 2.0 - 4 Ports Hub + 0307 USB 2.0 - 7 ports Hub [FSU307] + 038c F2CU038 HDMI Adapter + 0409 F5U409 Serial + 0416 Staples 12416 7 port desktop hub + 0551 F6C550-AVR UPS + 065a F8T065BF Mini Bluetooth 4.0 Adapter + 0706 2-N-1 7-Port Hub (Lower half) + 0802 Nostromo n40 Gamepad + 0803 Nostromo 1745 GamePad + 0805 Nostromo N50 GamePad + 0815 Nostromo n52 HID SpeedPad Mouse Wheel + 0826 ErgoFit Wireless Optical Mouse (HID) + 0980 HID UPS Battery + 1004 F9L1004 802.11n Surf N300 XR Wireless Adapter [Realtek RTL8192CU] + 1102 F7D1102 N150/Surf Micro Wireless Adapter v1000 [Realtek RTL8188CUS] + 1103 F9L1103 N750 DB 802.11abgn 2x3:3 [Ralink RT3573] + 1106 F9L1106v1 802.11a/b/g/n/ac Wireless Adapter [Broadcom BCM43526] + 1109 F9L1109v1 802.11a/b/g/n/ac Wireless Adapter [Realtek RTL8812AU] + 110a F9L1101v2 802.11abgn Wireless Adapter [Realtek RTL8192DU] + 11f2 ISY Wireless Micro Adapter IWL 2000 [RTL8188CUS] + 1202 F5U120-PC Parallel Printer Port + 1203 F5U120-PC Serial Port + 2103 F7D2102 802.11n N300 Micro Wireless Adapter v3000 [Realtek RTL8192CU] + 21f1 N300 WLAN N Adapter [ISY] + 21f2 RTL8192CU 802.11n WLAN Adapter [ISY IWL 4000] + 258a F5U258 Host to Host cable + 3101 F1DF102U/F1DG102U Flip Hub + 3201 F1DF102U/F1DG102U Flip KVM + 4050 ZD1211B + 5055 F5D5055 Gigabit Network Adapter [AX88xxx] + 6050 F6D6050 802.11abgn Wireless Adapter [Broadcom BCM4323] + 6051 F5D6051 802.11b Wireless Network Adapter [ZyDAS ZD1201] + 615a F7D4101 / F9L1101v1 802.11abgn Wireless Adapter [Broadcom BCM4323] + 7050 F5D7050 Wireless G Adapter v1000/v2000 [Intersil ISL3887] + 7051 F5D7051 802.11g Adapter v1000 [Broadcom 4320 USB] + 705a F5D7050 Wireless G Adapter v3000 [Ralink RT2571W] + 705b Wireless G Adapter + 705c F5D7050 Wireless G Adapter v4000 [Zydas ZD1211B] + 705e F5D7050 Wireless G Adapter v5000 [Realtek RTL8187B] + 706a 2-N-1 7-Port Hub (Upper half) + 8053 F5D8053 N Wireless USB Adapter v1000/v4000 [Ralink RT2870] + 805c F5D8053 N Wireless Adapter v3000 [Ralink RT2870] + 805e F5D8053 N Wireless USB Adapter v5000 [Realtek RTL8192U] + 815c F5D8053 N Wireless USB Adapter v3000 [Ralink RT2870] + 815f F5D8053 N Wireless USB Adapter v6000 [Realtek RTL8192SU] + 825a F5D8055 N+ Wireless Adapter v1000 [Ralink RT2870] + 825b F5D8055 N+ Wireless Adapter v2000 [Ralink RT3072] + 845a F7D2101 802.11n Surf & Share Wireless Adapter v1000 [Realtek RTL8192SU] + 905b F5D9050 Wireless G+ MIMO Network Adapter v3000 [Ralink RT2573] + 905c F5D9050 Wireless G+ MIMO Network Adapter v4000 [Ralink RT2573] + 935a F6D4050 N150 Enhanced Wireless Network Adapter v1000 [Ralink RT3070] + 935b F6D4050 N150 Enhanced Wireless Network Adapter v2000 [Ralink RT3070] + 945a F7D1101 v1 Basic Wireless Adapter [Realtek RTL8188SU] + 945b F7D1101 v2 Basic Wireless Adapter [Ralink RT3370] + d321 Dynex DX-NUSB 802.11bgn Wireless Adapter [Broadcom BCM43231] +050e Neon Technology, Inc. +050f KC Technology, Inc. + 0001 Hub + 0003 KC82C160S Hub + 0180 KC-180 IrDA Dongle + 0190 KC2190 USB Host-to-Host cable +0510 Sejin Electron, Inc. + 0001 Keyboard + 1000 Keyboard with PS/2 Mouse Port + e001 Mouse +0511 N'Able (DataBook) Technologies, Inc. + 002b AOC DVB +0512 Hualon Microelectronics Corp. +0513 digital-X, Inc. +0514 FCI Electronics +0515 ACTC +0516 Longwell Electronics +0517 Butterfly Communications +0518 EzKEY Corp. + 0001 USB to PS2 Adaptor v1.09 + 0002 EZ-9900C Keyboard +0519 Star Micronics Co., Ltd + 0003 TSP100ECO/TSP100II + c002 Xlive Bluetooth XBM-100S MP3 Player +051a WYSE Technology + a005 Smart Display Version 9973 +051b Silicon Graphics +051c Shuttle, Inc. + 0005 VFD Module + c001 eHome Infrared Receiver + c002 eHome Infrared Receiver +051d American Power Conversion + 0001 UPS + 0002 Uninterruptible Power Supply + 0003 UPS +051e Scientific Atlanta, Inc. +051f IO Systems (Elite Electronics), Inc. +0520 Taiwan Semiconductor Manufacturing Co. +0521 Airborn Connectors +0522 Advanced Connectek, Inc. +0523 ATEN GmbH +0524 Sola Electronics +0525 Netchip Technology, Inc. + 100d RFMD Bluetooth Device + 1080 NET1080 USB-USB Bridge + 1200 SSDC Adapter II + 1265 File-backed Storage Gadget + 3424 Lumidigm Venus fingerprint sensor + a0f0 Cambridge Electronic Devices Power1401 mk 2 + a140 USB Clik! 40 + a141 (OME) PocketZip 40 MP3 Player Driver + a220 GVC Bluetooth Wireless Adapter + a4a0 Linux-USB "Gadget Zero" + a4a1 Linux-USB Ethernet Gadget + a4a2 Linux-USB Ethernet/RNDIS Gadget + a4a3 Linux-USB user-mode isochronous source/sink + a4a4 Linux-USB user-mode bulk source/sink + a4a5 Pocketbook Pro 903 / Mobius 2 Action Cam + a4a6 Linux-USB Serial Gadget + a4a7 Linux-USB Serial Gadget (CDC ACM mode) + a4a8 Linux-USB Printer Gadget + a4a9 Linux-USB OBEX Gadget + a4aa Linux-USB CDC Composite Gadge (Ethernet and ACM) +0526 Temic MHS S.A. +0527 ALTRA +0528 ATI Technologies, Inc. + 7561 TV Wonder + 7562 TV Wonder, Edition (FN5) + 7563 TV Wonder, Edition (FI) + 7564 TV Wonder, Edition (FQ) + 7565 TV Wonder, Edition (NTSC+) + 7566 TV Wonder, Edition (FN5) + 7567 TV Wonder, Edition (FI) + 7568 TV Wonder, Edition (FQ) + 7569 Live! Pro (A) + 756a Live! Pro Audio (O) +0529 Aladdin Knowledge Systems + 0001 HASP copy protection dongle + 030b eToken R1 v3.1.3.x + 0313 eToken R1 v3.2.3.x + 031b eToken R1 v3.3.3.x + 0323 eToken R1 v3.4.3.x + 0412 eToken R2 v2.2.4.x + 041a eToken R2 v2.2.4.x + 0422 eToken R2 v2.4.4.x + 042a eToken R2 v2.5.4.x + 050c eToken Pro v4.1.5.x + 0514 eToken Pro v4.2.5.4 + 0600 eToken Pro 64k (4.2) + 0620 Token JC +052a Crescent Heart Software +052b Tekom Technologies, Inc. + 0102 Ca508A HP1020 Camera v.1.3.1.6 + 0801 Yakumo MegaImage 37 + 1512 Yakumo MegaImage IV + 1513 Aosta CX100 Webcam + 1514 Aosta CX100 Webcam Storage + 1905 Yakumo MegaImage 47 + 1911 Yakumo MegaImage 47 SL + 2202 WDM Still Image Capture + 2203 Sound Vision Stream Driver + 3a06 DigiLife DDV-5120A + d001 P35U Camera Capture +052c Canon Information Systems, Inc. +052d Avid Electronics Corp. +052e Standard Microsystems Corp. +052f Unicore Software, Inc. +0530 American Microsystems, Inc. +0531 Wacom Technology Corp. +0532 Systech Corp. +0533 Alcatel Mobile Phones +0534 Motorola, Inc. +0535 LIH TZU Electric Co., Ltd +0536 Hand Held Products (Welch Allyn, Inc.) + 01a0 PDT +0537 Inventec Corp. +0538 Caldera International, Inc. (SCO) +0539 Shyh Shiun Terminals Co., Ltd +053a PrehKeyTec GmbH + 0b00 Hub + 0b01 Preh MCI 3100 +053b Global Village Communication +053c Institut of Microelectronic & Mechatronic Systems +053d Silicon Architect +053e Mobility Electronics +053f Synopsys, Inc. +0540 UniAccess AB + 0101 Panache Surf ISDN TA +0541 Sirf Technology, Inc. +0543 ViewSonic Corp. + 00fe G773 Monitor Hub + 00ff P815 Monitor Hub + 0bf2 airpanel V150 Wireless Smart Display + 0bf3 airpanel V110 Wireless Smart Display + 0ed9 Color Pocket PC V35 + 0f01 airsync Wi-Fi Wireless Adapter + 1527 Color Pocket PC V36 + 1529 Color Pocket PC V37 + 152b Color Pocket PC V38 + 152e Pocket PC + 1921 Communicator Pocket PC + 1922 Smartphone + 1923 Pocket PC V30 + 1a11 Wireless 802.11g Adapter + 1e60 TA310 - ATSC/NTSC/PAL Driver(PCM4) + 4153 ViewSonic G773 Control (?) +0544 Cristie Electronics, Ltd +0545 Xirlink, Inc. + 7333 Trution Web Camera + 8002 IBM NetCamera + 8009 Veo PC Camera + 800c Veo Stingray + 800d Veo PC Camera + 8080 IBM C-It Webcam + 808a Veo PC Camera + 808b Veo Stingray + 808d Veo PC Camera + 810a Veo Advanced Connect Webcam + 810b Veo PC Camera + 810c Veo PC Camera + 8135 Veo Mobile/Advanced Web Camera + 813a Veo PC Camera + 813b Veo PC Camera + 813c Veo Mobile/Advanced Web Camera + 8333 Veo Stingray/Connect Web Camera + 888c eVision 123 digital camera + 888d eVision 123 digital camera +0546 Polaroid Corp. + 0daf PDC 2300Z + 1bed PDC 1320 Camera + 3097 PDC 310 + 3155 PDC 3070 Camera + 3187 Digital Camera + 3191 Ion 80 Camera + 3273 PDC 2030 Camera + 3304 a500 Digital Camera + dccf Sound Vision Stream Driver +0547 Anchor Chips, Inc. + 0001 ICSI Bluetooth Device + 0080 I3SYSTEM HYUNY + 1002 Python2 WDM Encoder + 1006 Hantek DSO-2100 UF + 2131 AN2131 EZUSB Microcontroller + 2235 AN2235 EZUSB-FX Microcontroller + 2710 EZ-Link Loader (EZLNKLDR.SYS) + 2720 AN2720 USB-USB Bridge + 2727 Xircom PGUNET USB-USB Bridge + 2750 EZ-Link (EZLNKUSB.SYS) + 2810 Cypress ATAPI Bridge + 4018 AmScope MU1803 + 4d90 AmScope MD1900 camera + 6010 AmScope MU1000 camera + 6510 Touptek UCMOS05100KPA + 7000 PowerSpec MCE460 Front Panel LED Display + 7777 Bluetooth Device + 9999 AN2131 uninitialized (?) +0548 Tyan Computer Corp. + 1005 EZ Cart II GameBoy Flash Programmer +0549 Pixera Corp. +054a Fujitsu Microelectronics, Inc. +054b New Media Corp. +054c Sony Corp. + 0001 HUB + 0002 Standard HUB + 0010 Cyber-shot, Mavica (msc) + 0014 Nogatech USBVision (SY) + 0022 Storage Adapter V2 (TPP) + 0023 CD Writer + 0024 Mavica CD-1000 Camera + 0025 NW-MS7 Walkman MemoryStick Reader + 002b Portable USB Harddrive V2 + 002c USB Floppy Disk Drive + 002d MSAC-US1 MemoryStick Reader + 002e HandyCam MemoryStick Reader + 0030 Storage Adapter V2 (TPP) + 0032 MemoryStick MSC-U01 Reader + 0035 Network Walkman (E) + 0036 Net MD + 0037 MG Memory Stick Reader/Writer + 0038 Clie PEG-S300/D PalmOS PDA + 0039 Network Walkman (MS) + 003c VAIO-MX LCD Control + 0045 Digital Imaging Video + 0046 Network Walkman + 0049 UP-D895 + 004a Memory Stick Hi-Fi System + 004b Memory Stick Reader/Writer + 004e DSC-xxx (ptp) + 0056 MG Memory Stick Reader/Writer + 0058 Clie PEG-N7x0C PalmOS PDA Mass Storage + 0066 Clie PEG-N7x0C/PEG-T425 PalmOS PDA Serial + 0067 CMR-PC3 Webcam + 0069 Memorystick MSC-U03 Reader + 006c FeliCa S310 [PaSoRi] + 006d Clie PEG-T425 PDA Mass Storage + 006f Network Walkman (EV) + 0073 Storage CRX1750U + 0075 Net MD + 0076 Storage Adapter ACR-U20 + 007c Net MD + 007f IC Recorder (MS) + 0080 Net MD + 0081 Net MD + 0084 Net MD + 0085 Net MD + 0086 Net MD + 008b Micro Vault 64M Mass Storage + 0095 Clie s360 + 0099 Clie NR70 PDA Mass Storage + 009a Clie NR70 PDA Serial + 00ab Visual Communication Camera (PCGA-UVC10) + 00af DPP-EX Series Digital Photo Printer + 00bf IC Recorder (S) + 00c0 Handycam DCR-30 + 00c6 Net MD + 00c7 Net MD + 00c8 MZ-N710 Minidisc Walkman + 00c9 Net MD + 00ca MZ-DN430 Minidisc Walkman + 00cb MSAC-US20 Memory Stick Reader + 00da Clie nx60 + 00e8 Network Walkman (MS) + 00e9 Handheld + 00eb Net MD + 0101 Net MD + 0103 IC Recorder (ST) + 0105 Micro Vault Hub + 0107 VCC-U01 Visual Communication Camera + 0110 Digital Imaging Video + 0113 Net MD + 0116 IC Recorder (P) + 0144 Clie PEG-TH55 PDA + 0147 Visual Communication Camera (PCGA-UVC11) + 014c Aiwa AM-NX9 Net MD Music Recorder MDLP + 014d Memory Stick Reader/Writer + 0154 Eyetoy Audio Device + 0155 Eyetoy Video Device + 015f IC Recorder (BM) + 0169 Clie PEG-TJ35 PDA Serial + 016a Clie PEG-TJ35 PDA Mass Storage + 016b Mobile HDD + 016d IC Recorder (SX) + 016e DPP-EX50 Digital Photo Printer + 0171 Fingerprint Sensor 3500 + 017e Net MD + 017f Hi-MD WALKMAN + 0180 Net MD + 0181 Hi-MD WALKMAN + 0182 Net MD + 0183 Hi-MD WALKMAN + 0184 Net MD + 0185 Hi-MD WALKMAN + 0186 Net MD + 0187 Hi-MD MZ-NH600 WALKMAN + 0188 Net MD + 018a Net MD + 018b Hi-MD SOUND GATE + 019e Micro Vault 1.0G Mass Storage + 01ad ATRAC HDD PA + 01bb FeliCa S320 [PaSoRi] + 01bd MRW62E Multi-Card Reader/Writer + 01c3 NW-E55 Network Walkman + 01c6 MEMORY P-AUDIO + 01c7 Printing Support + 01c8 PSP Type A + 01c9 PSP Type B + 01d0 DVD+RW External Drive DRU-700A + 01d5 IC RECORDER + 01de VRD-VC10 [Video Capture] + 01e7 UP-D897 + 01e8 UP-DR150 Photo Printer + 01e9 Net MD + 01ea Hi-MD WALKMAN + 01ee IC RECORDER + 01fa IC Recorder (P) + 01fb NW-E405 Network Walkman + 020f Device + 0210 ATRAC HDD PA + 0219 Net MD + 021a Hi-MD WALKMAN + 021b Net MD + 021c Hi-MD WALKMAN + 021d Net MD + 0226 UP-CR10L + 0227 Printing Support + 022c Net MD + 022d Hi-MD AUDIO + 0233 ATRAC HDD PA + 0236 Mobile HDD + 023b DVD+RW External Drive DRU-800UL + 023c Net MD + 023d Hi-MD WALKMAN + 0243 MicroVault Flash Drive + 024b Vaio VGX Mouse + 0257 IFU-WLM2 USB Wireless LAN Module (Wireless Mode) + 0258 IFU-WLM2 USB Wireless LAN Module (Memory Mode) + 0259 IC RECORDER + 0267 Tachikoma Device + 0268 Batoh Device / PlayStation 3 Controller + 0269 HDD WALKMAN + 026a HDD WALKMAN + 0271 IC Recorder (P) + 027c NETWORK WALKMAN + 027e SONY Communicator + 027f IC RECORDER + 0286 Net MD + 0287 Hi-MD WALKMAN + 0290 VGP-UVC100 Visual Communication Camera + 029b PRS-500 eBook reader + 02a5 MicroVault Flash Drive + 02af Handycam DCR-DVD306E + 02c4 Device + 02d1 DVD RW + 02d2 PSP Slim + 02d8 SBAC-US10 SxS PRO memory card reader/writer + 02e1 FeliCa S330 [PaSoRi] + 02ea PlayStation 3 Memory Card Adaptor + 02f9 DSC-H9 + 0317 WALKMAN + 031a Walkman NWD-B103F + 031e PRS-300/PRS-505 eBook reader + 0325 NWZ-A818 + 033e DSC-W120/W290 + 0346 Handycam DCR-SR55E + 0348 HandyCam HDR-TG3E + 035b Walkman NWZ-A828 + 035c NWZ-A726/A728/A729 + 035f UP-DR200 Photo Printer + 0382 Memory Stick PRO-HG Duo Adaptor (MSAC-UAH1) + 0385 Walkman NWZ-E436F + 0387 IC Recorder (P) + 03bc Webbie HD - MHS-CM1 + 03cc SD Card Reader + 03d1 DPF-X95 + 03d3 DR-BT100CX + 03d5 PlayStation Move motion controller + 03fc WALKMAN [NWZ-E345] + 03fd Walkman NWZ-E443 + 042f PlayStation Move navigation controller + 0440 DSC-H55 + 0485 MHS-PM5 HD camcorder + 04cb WALKMAN NWZ-E354 + 0541 DSC-HX100V [Cybershot Digital Still Camera] + 05c4 DualShock 4 [CUH-ZCT1x] + 0689 Walkman NWZ-B173F + 06bb WALKMAN NWZ-F805 + 06c3 RC-S380 + 07c4 ILCE-6000 (aka Alpha-6000) in Mass Storage mode + 082f Walkman NWZW Series + 0847 WG-C10 Portable Wireless Server + 0884 MDR-ZX770BN [Wireless Noise Canceling Stereo Headset] + 088c Portable Headphone Amplifier + 08b7 ILCE-6000 (aka Alpha-6000) in MTP mode + 094e ILCE-6000 (aka Alpha-6000) in PC Remote mode + 0994 ILCE-6000 (aka Alpha-6000) in charging mode + 09cc DualShock 4 [CUH-ZCT2x] + 0ba0 Dualshock4 Wireless Adaptor + 0bb5 Headset MDR-1000X + 0c02 ILCE-7M3 [A7III] in Mass Storage mode + 0c03 ILCE-7M3 [A7III] in MTP mode + 0c34 ILCE-7M3 [A7III] in PC Remote mode + 0cda PlayStation Classic controller + 1000 Wireless Buzz! Receiver +054d Try Corp. +054e Proside Corp. +054f WYSE Technology Taiwan +0550 Fuji Xerox Co., Ltd + 0002 InkJet Color Printer + 0004 InkJet Color Printer + 0005 InkJet Color Printer + 000b Workcentre 24 + 014e CM215b Printer + 0165 DocuPrint M215b +0551 CompuTrend Systems, Inc. +0552 Philips Monitors +0553 STMicroelectronics Imaging Division (VLSI Vision) + 0001 TerraCAM + 0002 CPiA Webcam + 0100 STV0672 Camera + 0140 Video Camera + 0150 CDE CAM 100 + 0151 Digital Blue QX5 Microscope + 0200 Dual-mode Camera0 + 0201 Dual-mode Camera1 + 0202 STV0680 Camera + 0674 Multi-mode Camera + 0679 NMS Video Camera (Webcam) + 1002 Che-ez! Splash +0554 Dictaphone Corp. +0555 ANAM S&T Co., Ltd +0556 Asahi Kasei Microsystems Co., Ltd + 0001 AK5370 I/F A/D Converter +0557 ATEN International Co., Ltd + 2001 UC-1284 Printer Port + 2002 10Mbps Ethernet [klsi] + 2004 UC-100KM PS/2 Mouse and Keyboard adapter + 2006 UC-1284B Printer Port + 2007 UC-110T 100Mbps Ethernet [pegasus] + 2008 UC-232A Serial Port [pl2303] + 2009 UC-210T Ethernet + 2011 UC-2324 4xSerial Ports [mos7840] + 2202 CS124U Miniview II KVM Switch + 2212 Keyboard/Mouse + 2213 CS682 2-Port USB 2.0 DVI KVM Switch + 2221 Winbond Hermon + 2404 4-port switch + 2600 IDE Bridge + 2701 CE700A KVM Extender + 4000 DSB-650 10Mbps Ethernet [klsi] + 7000 Hub + 7820 UC-2322 2xSerial Ports [mos7820] + 8021 Hub +0558 Truevision, Inc. + 1009 GW Instek GDS-1000 Oscilloscope + 100a GW Instek GDS-1000A Oscilloscope + 2009 GW Instek GDS-2000 Oscilloscope +0559 Cadence Design Systems, Inc. +055a Kenwood USA +055b KnowledgeTek, Inc. +055c Proton Electronic Ind. +055d Samsung Electro-Mechanics Co. + 0001 Keyboard + 0bb1 Bluetooth Device + 1030 Optical Wheel Mouse (OMS3CB/OMGB30) + 1031 Optical Wheel Mouse (OMA3CB/OMGI30) + 1040 Mouse HID Device + 1050 E-Mail Optical Wheel Mouse (OMS3CE) + 1080 Optical Wheel Mouse (OMS3CH) + 2020 Floppy Disk Drive + 6780 Keyboard V1 + 6781 Keyboard Mouse + 8001 E.M. Hub + 9000 AnyCam [pwc] + 9001 MPC-C30 AnyCam Premium for Notebooks [pwc] + a000 SWL-2100U + a010 WLAN Adapter(SWL-2300) + a011 Boot Device + a012 WLAN Adapter(SWL-2300) + a013 WLAN Adapter(SWL-2350) + a230 Boot Device + b000 11Mbps WLAN Mini Adapter + b230 Netopia 802.11b WLAN Adapter + b231 LG Wireless LAN 11b Adapter +055e CTX Opto-Electronics Corp. +055f Mustek Systems, Inc. + 0001 ScanExpress 1200 CU + 0002 ScanExpress 600 CU + 0003 ScanExpress 1200 USB + 0006 ScanExpress 1200 UB + 0007 ScanExpress 1200 USB Plus + 0008 ScanExpress 1200 CU Plus + 0010 BearPaw 1200F + 0210 ScanExpress A3 USB + 0218 BearPaw 2400 TA + 0219 BearPaw 2400 TA Plus + 021a BearPaw 2448 TA Plus + 021b BearPaw 1200 CU Plus + 021c BearPaw 1200 CU Plus + 021d BearPaw 2400 CU Plus + 021e BearPaw 1200 TA/CS + 021f SNAPSCAN e22 + 0400 BearPaw 2400 TA Pro + 0401 P 3600 A3 Pro + 0408 BearPaw 2448 CU Pro + 0409 BearPaw 2448 TA Pro + 040b ScanExpress A3 USB 1200 PRO + 0501 ScanExpress A3 2400 Pro + 0873 ScanExpress 600 USB + 1000 BearPaw 4800 TA Pro + a350 gSmart 350 Camera + a800 MDC 800 Camera + b500 MDC 3000 Camera + c005 PC CAM 300A + c200 gSmart 300 + c211 Kowa Bs888e Microcamera + c220 gSmart mini + c230 Digicam 330K + c232 MDC3500 Camera + c360 DV 4000 Camera + c420 gSmart mini 2 Camera + c430 gSmart LCD 2 Camera + c440 DV 3000 Camera + c520 gSmart mini 3 Camera + c530 gSmart LCD 2 Camera + c540 gSmart D30 Camera + c630 MDC 4000 Camera + c631 MDC 4000 Camera + c650 MDC 5500Z Camera + d001 WCam 300 + d003 WCam 300A + d004 WCam 300AN +0560 Interface Corp. +0561 Oasis Design, Inc. +0562 Telex Communications, Inc. + 0001 Enhanced Microphone + 0002 Telex Microphone +0563 Immersion Corp. +0564 Kodak Digital Product Center, Japan Ltd. (formerly Chinon Industries Inc.) +0565 Peracom Networks, Inc. + 0001 Serial Port [etek] + 0002 Enet Ethernet [klsi] + 0003 @Home Networks Ethernet [klsi] + 0005 Enet2 Ethernet [klsi] + 0041 Peracom Remote NDIS Ethernet Adapter +0566 Monterey International Corp. + 0110 ViewMate Desktop Mouse CC2201 + 1001 ViewMate Desktop Mouse CC2201 + 1002 ViewMate Desktop Mouse CC2201 + 1003 ViewMate Desktop Mouse CC2201 + 1004 ViewMate Desktop Mouse CC2201 + 1005 ViewMate Desktop Mouse CC2201 + 1006 ViewMate Desktop Mouse CC2201 + 1007 ViewMate Desktop Mouse CC2201 + 2800 MIC K/B + 2801 MIC K/B Mouse + 2802 Kbd Hub + 3002 Keyboard + 3004 Genius KB-29E + 3027 Sun-Flex ProTouch + 3107 Keyboard + 3132 Optical mouse M-DY4DR / M-DY6DR + 4006 FID 638 Mouse (Sun Microsystems) +0567 Xyratex International, Ltd +0568 Quartz Ingenierie +0569 SegaSoft +056a Wacom Co., Ltd + 0000 PenPartner + 0001 PenPartner 4x5 + 0002 PenPartner 6x8 + 0003 PTU-600 [Cintiq Partner] + 0010 ET-0405 [Graphire] + 0011 ET-0405A [Graphire2 (4x5)] + 0012 ET-0507A [Graphire2 (5x7)] + 0013 CTE-430 [Graphire3 (4x5)] + 0014 CTE-630 [Graphire3 (6x8)] + 0015 CTE-440 [Graphire4 (4x5)] + 0016 CTE-640 [Graphire4 (6x8)] + 0017 CTE-450 [Bamboo Fun (small)] + 0018 CTE-650 [Bamboo Fun (medium)] + 0019 CTE-631 [Bamboo One] + 0020 GD-0405 [Intuos (4x5)] + 0021 GD-0608 [Intuos (6x8)] + 0022 GD-0912 [Intuos (9x12)] + 0023 GD-1212 [Intuos (12x12)] + 0024 GD-1218 [Intuos (12x18)] + 0026 PTH-450 [Intuos5 touch (S)] + 0027 PTH-650 [Intuos5 touch (M)] + 0028 PTH-850 [Intuos5 touch (L)] + 0029 PTK-450 [Intuos5 (S)] + 002a PTK-650 [Intuos5 (M)] + 0030 PL400 + 0031 PL500 + 0032 PL600 + 0033 PL600SX + 0034 PL550 + 0035 PL800 + 0037 PL700 + 0038 PL510 + 0039 DTU-710 + 003a DTI-520 + 003b Integrated Hub + 003f DTZ-2100 [Cintiq 21UX] + 0041 XD-0405-U [Intuos2 (4x5)] + 0042 XD-0608-U [Intuos2 (6x8)] + 0043 XD-0912-U [Intuos2 (9x12)] + 0044 XD-1212-U [Intuos2 (12x12)] + 0045 XD-1218-U [Intuos2 (12x18)] + 0047 Intuos2 6x8 + 0057 DTK-2241 + 0059 DTH-2242 tablet + 005b DTH-2200 [Cintiq 22HD Touch] tablet + 005d DTH-2242 touchscreen + 005e DTH-2200 [Cintiq 22HD Touch] touchscreen + 0060 FT-0405 [Volito, PenPartner, PenStation (4x5)] + 0061 FT-0203 [Volito, PenPartner, PenStation (2x3)] + 0062 CTF-420 [Volito2] + 0063 CTF-220 [BizTablet] + 0064 CTF-221 [PenPartner2] + 0065 MTE-450 [Bamboo] + 0069 CTF-430 [Bamboo One] + 006a CTE-460 [Bamboo One Pen (S)] + 006b CTE-660 [Bamboo One Pen (M)] + 0081 CTE-630BT [Graphire Wireless (6x8)] + 0084 ACK-40401 [Wireless Accessory Kit] + 0090 TPC90 + 0093 TPC93 + 0097 TPC97 + 009a TPC9A + 00b0 PTZ-430 [Intuos3 (4x5)] + 00b1 PTZ-630 [Intuos3 (6x8)] + 00b2 PTZ-930 [Intuos3 (9x12)] + 00b3 PTZ-1230 [Intuos3 (12x12)] + 00b4 PTZ-1231W [Intuos3 (12x19)] + 00b5 PTZ-631W [Intuos3 (6x11)] + 00b7 PTZ-431W [Intuos3 (4x6)] + 00b8 PTK-440 [Intuos4 (4x6)] + 00b9 PTK-640 [Intuos4 (6x9)] + 00ba PTK-840 [Intuos4 (8x13)] + 00bb PTK-1240 [Intuos4 (12x19)] + 00c0 DTF-521 + 00c4 DTF-720 + 00c5 DTZ-2000W [Cintiq 20WSX] + 00c6 DTZ-1200W [Cintiq 12WX] + 00c7 DTU-1931 + 00cc DTK-2100 [Cintiq 21UX] + 00ce DTU-2231 + 00d0 CTT-460 [Bamboo Touch] + 00d1 CTH-460 [Bamboo Pen & Touch] + 00d2 CTH-461 [Bamboo Fun/Craft/Comic Pen & Touch (S)] + 00d3 CTH-661 [Bamboo Fun/Comic Pen & Touch (M)] + 00d4 CTL-460 [Bamboo Pen (S)] + 00d5 CTL-660 [Bamboo Pen (M)] + 00d6 CTH-460 [Bamboo Pen & Touch] + 00d7 CTH-461 [Bamboo Fun/Craft/Comic Pen & Touch (S)] + 00d8 CTH-661 [Bamboo Fun/Comic Pen & Touch (M)] + 00d9 CTT-460 [Bamboo Touch] + 00da CTH-461SE [Bamboo Pen & Touch Special Edition (S)] + 00db CTH-661SE [Bamboo Pen & Touch Special Edition (M)] + 00dc CTT-470 [Bamboo Touch] + 00dd CTL-470 [Bamboo Connect] + 00de CTH-470 [Bamboo Fun Pen & Touch] + 00df CTH-670 [Bamboo Create/Fun] + 00e2 TPCE2 + 00e3 TPCE3 + 00e5 TPCE5 + 00e6 TPCE6 + 00ec TPCEC + 00ed TPCED + 00ef TPCEF + 00f0 DTU-1631 + 00f4 DTK-2400 [Cintiq 24HD] tablet + 00f6 DTH-2400 [Cintiq 24HD touch] touchscreen + 00f8 DTH-2400 [Cintiq 24HD touch] tablet + 00fa DTK-2200 [Cintiq 22HD] tablet + 00fb DTU-1031 + 0100 TPC100 + 0101 TPC101 + 010d TPC10D + 010e TPC10E + 010f TPC10F + 0116 TPC116 + 012c TPC12C + 0221 MDP-123 [Inkling] + 0300 CTL-471 [Bamboo Splash, One by Wacom (S)] + 0301 CTL-671 [One by Wacom (M)] + 0302 CTH-480 [Intuos Pen & Touch (S)] + 0303 CTH-680 [Intuos Pen & Touch (M)] + 0304 DTK-1300 [Cintiq 13HD] + 0307 DTH-A1300 [Cintiq Companion Hybrid] tablet + 0309 DTH-A1300 [Cintiq Companion Hybrid] touchscreen + 030e CTL-480 [Intuos Pen (S)] + 0314 PTH-451 [Intuos pro (S)] + 0315 PTH-651 [Intuos pro (M)] + 0317 PTH-851 [Intuos pro (L)] + 0318 CTH-301 [Bamboo] + 0319 CTH-300 [Bamboo Pad wireless] + 0323 CTL-680 [Intuos Pen (M)] + 032a DTK-2700 [Cintiq 27QHD] + 032b DTH-2700 [Cintiq 27QHD touch] tablet + 032c DTH-2700 [Cintiq 27QHD touch] touchscreen + 032f DTU-1031X + 0331 ACK-411050 [ExpressKey Remote] + 0333 DTH-1300 [Cintiq 13HD Touch] tablet + 0335 DTH-1300 [Cintiq 13HD Touch] touchscreen + 0336 DTU-1141 + 033b CTL-490 [Intuos Draw (S)] + 033c CTH-490 [Intuos Art/Photo/Comic (S)] + 033d CTL-690 [Intuos Draw (M)] + 033e CTH-690 [Intuos Art (M)] + 0343 DTK-1651 + 0347 Integrated Hub + 0348 Integrated Hub + 034a DTH-W1320 [MobileStudio Pro 13] touchscreen + 034b DTH-W1620 [MobileStudio Pro 16] touchscreen + 034d DTH-W1320 [MobileStudio Pro 13] tablet + 034e DTH-W1620 [MobileStudio Pro 16] tablet + 034f DTH-1320 [Cintiq Pro 13] tablet + 0350 DTH-1620 [Cintiq Pro 16] tablet + 0351 DTH-2420 [Cintiq Pro 24 PT] tablet + 0352 DTH-3220 [Cintiq Pro 32] tablet + 0353 DTH-1320 [Cintiq Pro 13] touchscreen + 0354 DTH-1620 [Cintiq Pro 16] touchscreen + 0355 DTH-2420 [Cintiq Pro 24 PT] touchscreen + 0356 DTH-3220 [Cintiq Pro 32] touchscreen + 0357 PTH-660 [Intuos Pro (M)] + 0358 PTH-860 [Intuos Pro (L)] + 0359 DTU-1141B + 035a DTH-1152 tablet + 0368 DTH-1152 touchscreen + 0374 CTL-4100 [Intuos (S)] + 0375 CTL-6100 [Intuos (M)] + 0376 CTL-4100WL [Intuos BT (S)] + 0378 CTL-6100WL [Intuos BT (M)] + 037a CTL-472 [One by Wacom (S)] + 037b CTL-672 [One by Wacom (M)] + 037c DTK-2420 [Cintiq Pro 24 P] + 037d DTH-2452 tablet + 037e DTH-2452 touchscreen + 0382 DTK-2451 tablet + 038a DTH-3220 [Cintiq Pro 32] internal hub + 038d DTH-3220 [Cintiq Pro 32] internal hub + 038e DTH-3220 [Cintiq Pro 32] external hub + 038f DTH-3220 [Cintiq Pro 32] internal hub + 0390 DTK-1660 [Cintiq 16] + 0400 PenPartner 4x5 + 4001 TPC4001 + 4004 TPC4004 + 4850 PenPartner 6x8 + 5000 TPC5000 + 5002 TPC5002 + 5010 TPC5010 +056b Decicon, Inc. +056c eTEK Labs + 0006 KwikLink Host-Host Connector + 8007 Kwik232 Serial Port + 8100 KwikLink Host-Host Connector + 8101 KwikLink USB-USB Bridge +056d EIZO Corp. + 0000 Hub + 0001 Monitor + 0002 HID Monitor Controls + 0003 Device Bay Controller +056e Elecom Co., Ltd + 0002 29UO Mouse + 0057 Micro Grast Pop M-PGDL + 005c Micro Grast Pop M-PG2DL + 005d Micro Grast Fit M-FGDL + 005e Micro Grast Fit M-FG2DL + 0062 Optical mouse M-D18DR + 0063 Laser mouse M-SODL + 0069 Laser mouse M-GE1UL + 0071 Laser mouse M-GE3DL + 0072 Laser mouse M-LS6UL + 0073 Laser mouse M-LS7UL + 0074 Optical mouse M-FW1UL + 0075 Laser mouse M-FW2DL + 0077 Laser mouse M-LY2UL + 0079 Laser mouse M-D21DL + 007b Laser mouse M-D20DR + 007c Laser Bluetooth mouse M-BT5BL + 007e Option mouse M-M8UR + 007f Option mouse M-M9UR + 0081 Option mouse M-DY6DR + 0082 Laser mouse M-D22DR + 0088 Micro Grast2 Bit M-BG3DL + 0089 Micro Grast2 Pop M-PG3DL + 008c M-NE3DL Mouse + 008d ORIME M-NE4DR + 008f M-BT8BL Bluetooth Mouse + 0092 Wireless BlueLED Mouse (M-BL2DB) + 009c IR Mouse M-IR02DR + 009d IR Mouse M-IR03DR + 009f BlueLED Mouse M-HS1DB + 00a1 IR Mouse M-IR05DR + 00a4 Blue LED Mouse M-BL06DB + 00a5 M-NV1BR Bluetooth Mouse + 00a7 Blue LED Mouse M-BL08DB + 2003 JC-U3613M + 2004 JC-U3613M + 200c LD-USB/TX + 2012 JC-U4013S Gamepad + 4002 Laneed 100Mbps Ethernet LD-USB/TX [pegasus] + 4005 LD-USBL/TX + 400b LD-USB/TX + 4010 LD-USB20 + 5003 UC-SGT + 5004 UC-SGT + 6008 Flash Disk + abc1 LD-USB/TX +056f Korea Data Systems Co., Ltd + cd00 CDM-751 CD organizer +0570 Epson America +0571 Interex, Inc. + 0002 echoFX InterView Lite +0572 Conexant Systems (Rockwell), Inc. + 0001 Ezcam II Webcam + 0002 Ezcam II Webcam + 0040 Wondereye CP-115 Webcam + 0041 Webcam Notebook + 0042 Webcam Notebook + 0320 DVBSky T330 DVB-T2/C tuner + 1232 V.90 modem + 1234 Typhoon Redfun Modem V90 56k + 1252 HCF V90 Data Fax Voice Modem + 1253 Zoom V.92 Faxmodem + 1300 SoftK56 Data Fax Voice CARP + 1301 Modem Enumerator + 1328 TrendNet TFM-561 modem + 1804 HP Dock Audio + 2000 SoftGate 802.11 Adapter + 2002 SoftGate 802.11 Adapter + 262a tm5600 Video & Audio Grabber Capture + 680c DVBSky T680C DVB-T2/C tuner + 6831 DVBSky S960 DVB-S2 tuner + 8390 WinFast PalmTop/Novo TV Video + 8392 WinFast PalmTop/Novo TV Video + 960c DVBSky S960C DVB-S2 tuner + c686 Geniatech T220A DVB-T2 TV Stick + c688 Geniatech T230 DVB-T2 TV Stick + cafc CX861xx ROM Boot Loader + cafd CX82310 ROM Boot Loader + cafe AccessRunner ADSL Modem + cb00 ADSL Modem + cb01 ADSL Modem + cb06 StarModem Network Interface +0573 Zoran Co. Personal Media Division (Nogatech) + 0003 USBGear USBG-V1 + 0400 D-Link V100 + 0600 Dazzle USBVision (1006) + 1300 leadtek USBVision (1006) + 2000 X10 va10a Wireless Camera + 2001 Dazzle EmMe (2001) + 2101 Zoran Co. PMD (Nogatech) AV-grabber Manhattan + 2d00 Osprey 50 + 2d01 Hauppauge USB-Live Model 600 + 3000 Dazzle MicroCam (NTSC) + 3001 Dazzle MicroCam (PAL) + 4000 Nogatech TV! (NTSC) + 4001 Nogatech TV! (PAL) + 4002 Nogatech TV! (PAL-I-) + 4003 Nogatech TV! (MF-) + 4008 Nogatech TV! (NTSC) (T) + 4009 Nogatech TV! (PAL) (T) + 4010 Nogatech TV! (NTSC) (A) + 4100 USB-TV FM (NTSC) + 4110 PNY USB-TV (NTSC) FM + 4400 Nogatech TV! Pro (NTSC) + 4401 Nogatech TV! Pro (PAL) + 4450 PixelView PlayTv-USB PRO (PAL) FM + 4451 Nogatech TV! Pro (PAL+) + 4452 Nogatech TV! Pro (PAL-I+) + 4500 Nogatech TV! Pro (NTSC) + 4501 Nogatech TV! Pro (PAL) + 4550 ZTV ZT-721 2.4GHz A/V Receiver + 4551 Dazzle TV! Pro Audio (P+) + 4d00 Hauppauge WinTV-USB USA + 4d01 Hauppauge WinTV-USB + 4d02 Hauppauge WinTV-USB UK + 4d03 Hauppauge WinTV-USB France + 4d04 Hauppauge WinTV (PAL D/K) + 4d10 Hauppauge WinTV-USB with FM USA radio + 4d11 Hauppauge WinTV-USB (PAL) with FM radio + 4d12 Hauppauge WinTV-USB UK with FM Radio + 4d14 Hauppauge WinTV (PAL D/K FM) + 4d20 Hauppauge WinTV-USB II (PAL) with FM radio + 4d21 Hauppauge WinTV-USB II (PAL) + 4d22 Hauppauge WinTV-USB II (PAL) Model 566 + 4d23 Hauppauge WinTV-USB France 4D23 + 4d24 Hauppauge WinTV Pro (PAL D/K) + 4d25 Hauppauge WinTV-USB Model 40209 rev B234 + 4d26 Hauppauge WinTV-USB Model 40209 rev B243 + 4d27 Hauppauge WinTV-USB Model 40204 Rev B281 + 4d28 Hauppauge WinTV-USB Model 40204 rev B283 + 4d29 Hauppauge WinTV-USB Model 40205 rev B298 + 4d2a Hauppague WinTV-USB Model 602 Rev B285 + 4d2b Hauppague WinTV-USB Model 602 Rev B282 + 4d2c Hauppauge WinTV Pro (PAL/SECAM) + 4d30 Hauppauge WinTV-USB FM Model 40211 Rev B123 + 4d31 Hauppauge WinTV-USB III (PAL) with FM radio Model 568 + 4d32 Hauppauge WinTV-USB III (PAL) FM Model 573 + 4d34 Hauppauge WinTV Pro (PAL D/K FM) + 4d35 Hauppauge WinTV-USB III (PAL) FM Model 597 + 4d36 Hauppauge WinTV Pro (PAL B/G FM) + 4d37 Hauppauge WinTV-USB Model 40219 rev E189 + 4d38 Hauppauge WinTV Pro (NTSC FM) +0574 City University of Hong Kong +0575 Philips Creative Display Solutions +0576 BAFO/Quality Computer Accessories +0577 ELSA +0578 Intrinsix Corp. +0579 GVC Corp. +057a Samsung Electronics America +057b Y-E Data, Inc. + 0000 FlashBuster-U Floppy + 0001 Tri-Media Reader Floppy + 0006 Tri-Media Reader Card Reader + 0010 Memory Stick Reader Writer + 0020 HEXA Media Drive 6-in-1 Card Reader Writer + 0030 Memory Card Viewer (TV) +057c AVM GmbH + 0b00 ISDN-Controller B1 Family + 0c00 ISDN-Controller FRITZ!Card + 1000 ISDN-Controller FRITZ!Card v2.0 + 1900 ISDN-Controller FRITZ!Card v2.1 + 2000 ISDN-Connector FRITZ!X + 2200 BlueFRITZ! + 2300 Teledat X130 DSL + 2800 Teledat 2a/b / X120 / NetXXL ISDN Terminal Adapter + 3200 Teledat X130 DSL + 3500 FRITZ!Card DSL SL + 3701 FRITZ!Box SL + 3702 FRITZ!Box + 3800 BlueFRITZ! Bluetooth Stick + 3a00 FRITZ!Box Fon + 3c00 FRITZ!Box WLAN + 3d00 FRITZ!Box Fon WLAN 7050/7140/7170/IAD3331 + 3e01 FRITZ!Box (Annex A) + 4001 FRITZ!Box Fon (Annex A) + 4101 FRITZ!Box WLAN (Annex A) + 4201 FRITZ!Box Fon WLAN (Annex A) + 4601 Eumex 5520PC (WinXP/2000) + 4602 Eumex 400 (WinXP/2000) + 4701 AVM FRITZ!Box Fon ata + 5401 Eumex 300 IP + 5601 AVM Fritz!WLAN [Texas Instruments TNETW1450] + 6201 AVM Fritz!WLAN v1.1 [Texas Instruments TNETW1450] + 62ff AVM Fritz!WLAN USB (in CD-ROM-mode) + 8401 Fritz!WLAN N [Atheros AR9001U] + 8402 Fritz!WLAN N 2.4 [Atheros AR9001U] + 8403 Fritz!WLAN N v2 [Atheros AR9271] + 84ff AVM Fritz!WLAN USB N (in CD-ROM-mode) + 8501 FRITZ WLAN N v2 [RT5572/rt2870.bin] +057d Shark Multimedia, Inc. +057e Nintendo Co., Ltd + 0305 Broadcom BCM2045A Bluetooth Radio [Nintendo Wii] + 0306 Wii Remote Controller RVL-003 + 0337 Wii U GameCube Controller Adapter + 2006 Joy-Con L + 2007 Joy-Con R +057f QuickShot, Ltd + 6238 USB StrikePad +0580 Denron, Inc. +0581 Racal Data Group +0582 Roland Corp. + 0000 UA-100(G) + 0002 UM-4/MPU-64 MIDI Interface + 0003 SoundCanvas SC-8850 + 0004 U-8 + 0005 UM-2(C/EX) + 0007 SoundCanvas SC-8820 + 0008 PC-300 + 0009 UM-1(E/S/X) + 000b SK-500 + 000c SC-D70 + 0010 EDIROL UA-5 + 0011 Edirol UA-5 Sound Capture + 0012 XV-5050 + 0013 XV-5050 + 0014 EDIROL UM-880 MIDI I/F (native) + 0015 EDIROL UM-880 MIDI I/F (generic) + 0016 EDIROL SD-90 + 0017 EDIROL SD-90 + 0018 UA-1A + 001b MMP-2 + 001c MMP-2 + 001d V-SYNTH + 001e V-SYNTH + 0023 EDIROL UM-550 + 0024 EDIROL UM-550 + 0025 EDIROL UA-20 + 0026 EDIROL UA-20 + 0027 EDIROL SD-20 + 0028 EDIROL SD-20 + 0029 EDIROL SD-80 + 002a EDIROL SD-80 + 002b EDIROL UA-700 + 002c EDIROL UA-700 + 002d XV-2020 Synthesizer + 002e XV-2020 Synthesizer + 002f VariOS + 0030 VariOS + 0033 EDIROL PCR + 0034 EDIROL PCR + 0035 M-1000 + 0037 Digital Piano + 0038 Digital Piano + 003b BOSS GS-10 + 003c BOSS GS-10 + 0040 GI-20 + 0041 GI-20 + 0042 RS-70 + 0043 RS-70 + 0044 EDIROL UA-1000 + 0047 EDIROL UR-80 WAVE + 0048 EDIROL UR-80 MIDI + 0049 EDIROL UR-80 WAVE + 004a EDIROL UR-80 MIDI + 004b EDIROL M-100FX + 004c EDIROL PCR-A WAVE + 004d EDIROL PCR-A MIDI + 004e EDIROL PCR-A WAVE + 004f EDIROL PCR-A MIDI + 0050 EDIROL UA-3FX + 0052 EDIROL UM-1SX + 0054 Digital Piano + 0060 EXR Series + 0064 EDIROL PCR-1 WAVE + 0065 EDIROL PCR-1 MIDI + 0066 EDIROL PCR-1 WAVE + 0067 EDIROL PCR-1 MIDI + 006a SP-606 + 006b SP-606 + 006d FANTOM-X + 006e FANTOM-X + 0073 EDIROL UA-25 + 0074 EDIROL UA-25 + 0075 BOSS DR-880 + 0076 BOSS DR-880 + 007a RD + 007b RD + 007d EDIROL UA-101 + 0080 G-70 + 0081 G-70 + 0084 V-SYNTH XT + 0089 BOSS GT-PRO + 008b EDIROL PC-50 + 008c EDIROL PC-50 + 008d EDIROL UA-101 USB1 + 0092 EDIROL PC-80 WAVE + 0093 EDIROL PC-80 MIDI + 0096 EDIROL UA-1EX + 009a EDIROL UM-3EX + 009d EDIROL UM-1 + 00a0 MD-P1 + 00a2 Digital Piano + 00a3 EDIROL UA-4FX + 00a6 Juno-G + 00a9 MC-808 + 00ad SH-201 + 00b2 VG-99 + 00b3 VG-99 + 00b7 BK-7m/VIMA JM-5/8 + 00c2 SonicCell + 00c4 EDIROL M-16DX + 00c5 SP-555 + 00c7 V-Synth GT + 00d1 Music Atelier + 00d3 M-380/400 + 00da BOSS GT-10 + 00db BOSS GT-10 Guitar Effects Processor + 00dc BOSS GT-10B + 00de Fantom G + 00e6 EDIROL UA-25EX (Advanced mode) + 00e7 EDIROL UA-25EX + 00e9 UA-1G + 00eb VS-100 + 00f6 GW-8/AX-Synth + 00f8 JUNO Series + 00fc VS-700C + 00fd VS-700 + 00fe VS-700 M1 + 00ff VS-700 M2 + 0100 VS-700 + 0101 VS-700 M2 + 0102 VB-99 + 0104 UM-1G + 0106 UM-2G + 0108 UM-3G + 0109 eBand JS-8 + 010d A-500S + 010f A-PRO + 0110 A-PRO + 0111 GAIA SH-01 + 0113 ME-25 + 0114 SD-50 + 0116 WAVE/MP3 RECORDER R-05 + 0117 VS-20 + 0119 OCTAPAD SPD-30 + 011c Lucina AX-09 + 011e BR-800 + 0120 OCTA-CAPTURE + 0121 OCTA-CAPTURE + 0123 JUNO-Gi + 0124 M-300 + 0127 GR-55 + 012a UM-ONE + 012b DUO-CAPTURE + 012f QUAD-CAPTURE + 0130 MICRO BR BR-80 + 0132 TRI-CAPTURE + 0134 V-Mixer + 0138 Boss RC-300 (Audio mode) + 0139 Boss RC-300 (Storage mode) + 013a JUPITER-80 + 013e R-26 + 0145 SPD-SX + 014b eBand JS-10 + 014d GT-100 + 0150 TD-15 + 0151 TD-11 + 0154 JUPITER-50 + 0156 A-Series + 0158 TD-30 + 0159 DUO-CAPTURE EX + 015b INTEGRA-7 + 015d R-88 + 0505 EDIROL UA-101 +0583 Padix Co., Ltd (Rockfire) + 0001 4 Axis 12 button +POV + 0002 4 Axis 12 button +POV + 2030 RM-203 USB Nest [mode 1] + 2031 RM-203 USB Nest [mode 2] + 2032 RM-203 USB Nest [mode 3] + 2033 RM-203 USB Nest [mode 4] + 2050 PX-205 PSX Bridge + 205f PSX/USB converter + 206f USB, 2-axis 8-button gamepad + 3050 QF-305u Gamepad + 3379 Rockfire X-Force + 337f Rockfire USB RacingStar Vibra + 509f USB,4-Axis,12-Button with POV + 5259 Rockfire USB SkyShuttle Vibra + 525f USB Vibration Pad + 5308 USB Wireless VibrationPad + 5359 Rockfire USB SkyShuttle Pro + 535f USB,real VibrationPad + 5659 Rockfire USB SkyShuttle Vibra + 565f USB VibrationPad + 6009 Revenger + 600f USB,GameBoard II + 6258 USB, 4-axis, 6-button joystick w/view finder + 6889 Windstorm Pro + 688f QF-688uv Windstorm Pro Joystick + 7070 QF-707u Bazooka Joystick + a000 MaxFire G-08XU Gamepad + a015 4-Axis,16-Button with POV + a019 USB, Vibration ,4-axis, 8-button joystick w/view finder + a020 USB,4-Axis,10-Button with POV + a021 USB,4-Axis,12-Button with POV + a022 USB,4-Axis,14-Button with POV + a023 USB,4-Axis,16-Button with POV + a024 4axis,12button vibrition audio gamepad + a025 4axis,12button vibrition audio gamepad + a130 USB Wireless 2.4GHz Gamepad + a131 USB Wireless 2.4GHz Joystick + a132 USB Wireless 2.4GHz Wheelpad + a133 USB Wireless 2.4GHz Wheel&Gamepad + a202 ForceFeedbackWheel + a209 MetalStrike FF + b000 USB,4-Axis,12-Button with POV + b001 USB,4-Axis,12-Button with POV + b002 Vibration,12-Button USB Wheel + b005 USB,12-Button Wheel + b008 USB Wireless 2.4GHz Wheel + b009 USB,12-Button Wheel + b00a PSX/USB converter + b00b PSX/USB converter + b00c PSX/USB converter + b00d PSX/USB converter + b00e 4-Axis,12-Button with POV + b00f USB,5-Axis,10-Button with POV + b010 MetalStrike Pro + b012 Wireless MetalStrike + b013 USB,Wiress 2.4GHZ Joystick + b016 USB,5-Axis,10-Button with POV + b018 TW6 Wheel + ff60 USB Wireless VibrationPad +0584 RATOC System, Inc. + 0008 Fujifilm MemoryCard ReaderWriter + 0220 U2SCX SCSI Converter + 0304 U2SCX-LVD (SCSI Converter) + b000 REX-USB60 + b020 REX-USB60F +0585 FlashPoint Technology, Inc. + 0001 Digital Camera + 0002 Digital Camera + 0003 Digital Camera + 0004 Digital Camera + 0005 Digital Camera + 0006 Digital Camera + 0007 Digital Camera + 0008 Digital Camera + 0009 Digital Camera + 000a Digital Camera + 000b Digital Camera + 000c Digital Camera + 000d Digital Camera + 000e Digital Camera + 000f Digital Camera +0586 ZyXEL Communications Corp. + 0025 802.11b/g/n USB Wireless Network Adapter + 0100 omni.net + 0102 omni.net II ISDN TA [HFC-S] + 0110 omni.net Plus + 1000 omni.net LCD Plus - ISDN TA + 1500 Omni 56K Plus + 2011 Scorpion-980N keyboard + 3304 LAN Modem + 3309 ADSL Modem Prestige 600 series + 330a ADSL Modem Interface + 330e USB Broadband ADSL Modem Rev 1.10 + 3400 ZyAIR B-220 IEEE 802.11b Adapter + 3401 ZyAIR G-220 802.11bg + 3402 ZyAIR G-220F 802.11bg + 3403 AG-200 802.11abg Wireless Adapter [Atheros AR5523] + 3407 G-200 v2 802.11bg + 3408 G-260 802.11bg + 3409 AG-225H 802.11bg + 340a M-202 802.11bg + 340c G-270S 802.11bg Wireless Adapter [Atheros AR5523] + 340f G-220 v2 802.11bg + 3410 ZyAIR G-202 802.11bg + 3412 802.11bg + 3413 ZyAIR AG-225H v2 802.11bg + 3415 G-210H 802.11g Wireless Adapter + 3416 NWD-210N 802.11b/g/n-draft wireless adapter + 3417 NWD271N 802.11n Wireless Adapter [Atheros AR9001U-(2)NG] + 3418 NWD211AN 802.11abgn Wireless Adapter [Ralink RT2870] + 3419 G-220 v3 802.11bg Wireless Adapter [ZyDAS ZD1211B] + 341a NWD-270N Wireless N-lite USB Adapter + 341e NWD2105 802.11bgn Wireless Adapter [Ralink RT3070] + 341f NWD2205 802.11n Wireless N Adapter [Realtek RTL8192CU] + 3425 NWD6505 802.11a/b/g/n/ac Wireless Adapter [MediaTek MT7610U] + 343e N220 802.11bgn Wireless Adapter +0587 America Kotobuki Electronics Industries, Inc. +0588 Sapien Design +0589 Victron +058a Nohau Corp. +058b Infineon Technologies + 0015 Flash Loader utility + 001c Flash Drive + 0041 Flash Loader utility +058c In Focus Systems + 0007 Flash + 0008 LP130 + 000a LP530 + 0010 Projector + 0011 Projector + 0012 Projector + 0013 Projector + 0014 Projector + 0015 Projector + 0016 Projector + 0017 Projector + 0018 Projector + 0019 Projector + 001a Projector + 001b Projector + 001c Projector + 001d Projector + 001e Projector + 001f Projector + ffe5 IN34 Projector + ffeb Projector IN76 +058d Micrel Semiconductor +058e Tripath Technology, Inc. +058f Alcor Micro Corp. + 1234 Flash Drive + 2412 SCard R/W CSR-145 + 2802 Monterey Keyboard + 5492 Hub + 6232 Hi-Speed 16-in-1 Flash Card Reader/Writer + 6254 USB Hub + 6331 SD/MMC/MS Card Reader + 6332 Multi-Function Card Reader + 6335 SD/MMC Card Reader + 6360 Multimedia Card Reader + 6361 Multimedia Card Reader + 6362 Flash Card Reader/Writer + 6364 AU6477 Card Reader Controller + 6366 Multi Flash Reader + 6377 AU6375 4-LUN card reader + 6386 Memory Card + 6387 Flash Drive + 6390 USB 2.0-IDE bridge + 6391 IDE Bridge + 9213 MacAlly Kbd Hub + 9215 AU9814 Hub + 9254 Hub + 9310 Mass Storage (UID4/5A & UID7A) + 9320 Micro Storage Driver for Win98 + 9321 Micro Storage Driver for Win98 + 9330 SD Reader + 9331 Micro Storage Driver for Win98 + 9340 Delkin eFilm Reader-32 + 9350 Delkin eFilm Reader-32 + 9360 8-in-1 Media Card Reader + 9361 Multimedia Card Reader + 9368 Multimedia Card Reader + 9380 Flash Drive + 9381 Flash Drive + 9382 Acer/Sweex Flash drive + 9384 qdi U2Disk T209M + 9410 Keyboard + 9472 Keyboard Hub + 9510 ChunghwaTL USB02 Smartcard Reader + 9520 Watchdata W 1981 + 9540 AU9540 Smartcard Reader + 9720 USB-Serial Adapter + a014 Asus Integrated Webcam + b002 Acer Integrated Webcam +0590 Omron Corp. + 0004 Cable Modem + 000b MR56SVS + 0028 HJ-720IT / HEM-7080IT-E / HEM-790IT +0591 Questra Consulting +0592 Powerware Corp. + 0002 UPS (X-Slot) +0593 Incite +0594 Princeton Graphic Systems +0595 Zoran Microelectronics, Ltd + 1001 Digitrex DSC-1300/DSC-2100 (mass storage mode) + 2002 DIGITAL STILL CAMERA 6M 4X + 4343 Digital Camera EX-20 DSC +0596 MicroTouch Systems, Inc. + 0001 Touchscreen + 0002 Touch Screen Controller + 0500 PCT Multitouch HID Controller + 0543 DELL XPS touchscreen +0597 Trisignal Communications +0598 Niigata Canotec Co., Inc. +0599 Brilliance Semiconductor, Inc. +059a Spectrum Signal Processing, Inc. +059b Iomega Corp. + 0001 Zip 100 (Type 1) + 000b Zip 100 (Type 2) + 0021 Win98 Disk Controller + 0030 Zip 250 (Ver 1) + 0031 Zip 100 (Type 3) + 0032 Zip 250 (Ver 2) + 0034 Zip 100 Driver + 0037 Zip 750 MB + 0040 SCSI Bridge + 0042 Rev 70 GB + 0050 Zip CD 650 Writer + 0053 CDRW55292EXT CD-RW External Drive + 0056 External CD-RW Drive Enclosure + 0057 Mass Storage Device + 005d Mass Storage Device + 005f CDRW64892EXT3-C CD-RW 52x24x52x External Drive + 0060 PCMCIA PocketZip Dock + 0061 Varo PocketZip 40 MP3 Player + 006d HipZip MP3 Player + 0070 eGo Portable Hard Drive + 007c Ultra Max USB/1394 + 007d HTC42606 0G9AT00 [Iomega HDD] + 007e Mini 256MB/512MB Flash Drive [IOM2D5] + 00db FotoShow Zip 250 Driver + 0150 Mass Storage Device + 015d Super DVD Writer + 0173 Hi-Speed USB-to-IDE Bridge Controller + 0174 Hi-Speed USB-to-IDE Bridge Controller + 0176 Hi-Speed USB-to-IDE Bridge Controller + 0177 Hi-Speed USB-to-IDE Bridge Controller + 0178 Hi-Speed USB-to-IDE Bridge Controller + 0179 Hi-Speed USB-to-IDE Bridge Controller + 017a HDD + 017b HDD/1394A + 017c HDD/1394B + 0251 Optical + 0252 Optical + 0275 ST332082 0A + 0278 LDHD-UPS [Professional Desktop Hard Drive eSATA / USB2.0] + 027a LPHD250-U [Portable Hard Drive Silver Series 250 Go] + 0470 Prestige Portable Hard Drive + 047a Select Portable Hard Drive + 0571 Prestige Portable Hard Drive + 0579 eGo Portable Hard Drive + 1052 DVD+RW External Drive +059c A-Trend Technology Co., Ltd +059d Advanced Input Devices +059e Intelligent Instrumentation +059f LaCie, Ltd + 0201 StudioDrive USB2 + 0202 StudioDrive USB2 + 0203 StudioDrive USB2 + 0211 PocketDrive + 0212 PocketDrive + 0213 PocketDrive USB2 + 0323 LaCie d2 Drive USB2 + 0421 Big Disk G465 + 0525 BigDisk Extreme 500 + 0641 Mobile Hard Drive + 0829 BigDisk Extreme+ + 1004 Little Disk 20 GB + 100c Rugged Triple Interface Mobile Hard Drive + 1010 Desktop Hard Drive + 1016 Desktop Hard Drive + 1018 Desktop Hard Drive + 1019 Desktop Hard Drive + 1021 Little Disk + 1027 iamaKey V2 + 102a Rikiki Hard Drive + 1049 rikiki Harddrive + 1052 P'9220 Mobile Drive + 1061 Rugged USB3-FW + 1064 Rugged 16 and 32 GB + 106b Rugged Mini HDD + 106d Porsche Design Mobile Drive + 106e Porsche Design Desktop Drive + a601 HardDrive + a602 CD R/W +05a0 Vetronix Corp. +05a1 USC Corp. +05a2 Fuji Film Microdevices Co., Ltd +05a3 ARC International + 8388 Marvell 88W8388 802.11a/b/g WLAN + 9230 Camera + 9320 Camera + 9331 Camera + 9422 Camera + 9520 Camera +05a4 Ortek Technology, Inc. + 1000 WKB-1000S Wireless Ergo Keyboard with Touchpad + 2000 WKB-2000 Wireless Keyboard with Touchpad + 9720 Keyboard Mouse + 9722 Keyboard + 9731 MCK-600W/MCK-800USB Keyboard + 9783 Wireless Keypad + 9837 Targus Number Keypad + 9862 Targus Number Keypad (Composite Device) + 9881 IR receiver [VRC-1100 Vista MCE Remote Control] +05a5 Sampo Technology Corp. +05a6 Cisco Systems, Inc. + 0001 CVA124 Cable Voice Adapter (WDM) + 0002 CVA122 Cable Voice Adapter (WDM) + 0003 CVA124E Cable Voice Adapter (WDM) + 0004 CVA122E Cable Voice Adapter (WDM) + 0a00 Integrated Management Controller Hub + 0a01 Virtual Keyboard/Mouse + 0a02 Virtual Mass Storage + 0a03 Virtual Ethernet/RNDIS +05a7 Bose Corp. + 4000 Bluetooth Headset + 4001 Bluetooth Headset in DFU mode + 4002 Bluetooth Headset Series 2 + 4003 Bluetooth Headset Series 2 in DFU mode + bc50 SoundLink Wireless Mobile speaker + bc51 SoundLink Wireless Mobile speaker in DFU mode +05a8 Spacetec IMC Corp. +05a9 OmniVision Technologies, Inc. + 0511 OV511 Webcam + 0518 OV518 Webcam + 0519 OV519 Microphone + 1550 VEHO Filmscanner + 2640 OV2640 Webcam + 2643 Monitor Webcam + 264b Monitor Webcam + 2800 SuperCAM + 4519 Webcam Classic + 7670 OV7670 Webcam + 8065 GAIA Sensor FPGA Demo Board + 8519 OV519 Webcam + a511 OV511+ Webcam + a518 D-Link DSB-C310 Webcam +05aa Utilux South China, Ltd +05ab In-System Design + 0002 Parallel Port + 0030 Storage Adapter V2 (TPP) + 0031 ATA Bridge + 0060 USB 2.0 ATA Bridge + 0061 Storage Adapter V3 (TPP-I) + 0101 Storage Adapter (TPP) + 0130 Compact Flash and Microdrive Reader (TPP) + 0200 USS725 ATA Bridge + 0201 Storage Adapter (TPP) + 0202 ATA Bridge + 0300 Portable Hard Drive (TPP) + 0301 Portable Hard Drive V2 + 0350 Portable Hard Drive (TPP) + 0351 Portable Hard Drive V2 + 081a ATA Bridge + 0cda ATA Bridge for CD-R/RW + 1001 BAYI Printer Class Support + 5700 Storage Adapter V2 (TPP) + 5701 USB Storage Adapter V2 + 5901 Smart Board (TPP) + 5a01 ATI Storage Adapter (TPP) + 5d01 DataBook Adapter (TPP) +05ac Apple, Inc. + 0201 USB Keyboard [Alps or Logitech, M2452] + 0202 Keyboard [ALPS] + 0205 Extended Keyboard [Mitsumi] + 0206 Extended Keyboard [Mitsumi] + 020b Pro Keyboard [Mitsumi, A1048/US layout] + 020c Extended Keyboard [Mitsumi] + 020d Pro Keyboard [Mitsumi, A1048/JIS layout] + 020e Internal Keyboard/Trackpad (ANSI) + 020f Internal Keyboard/Trackpad (ISO) + 0214 Internal Keyboard/Trackpad (ANSI) + 0215 Internal Keyboard/Trackpad (ISO) + 0216 Internal Keyboard/Trackpad (JIS) + 0217 Internal Keyboard/Trackpad (ANSI) + 0218 Internal Keyboard/Trackpad (ISO) + 0219 Internal Keyboard/Trackpad (JIS) + 021a Internal Keyboard/Trackpad (ANSI) + 021b Internal Keyboard/Trackpad (ISO) + 021c Internal Keyboard/Trackpad (JIS) + 021d Aluminum Mini Keyboard (ANSI) + 021e Aluminum Mini Keyboard (ISO) + 021f Aluminum Mini Keyboard (JIS) + 0220 Aluminum Keyboard (ANSI) + 0221 Aluminum Keyboard (ISO) + 0222 Aluminum Keyboard (JIS) + 0223 Internal Keyboard/Trackpad (ANSI) + 0224 Internal Keyboard/Trackpad (ISO) + 0225 Internal Keyboard/Trackpad (JIS) + 0229 Internal Keyboard/Trackpad (ANSI) + 022a Internal Keyboard/Trackpad (MacBook Pro) (ISO) + 022b Internal Keyboard/Trackpad (MacBook Pro) (JIS) + 0230 Internal Keyboard/Trackpad (MacBook Pro 4,1) (ANSI) + 0231 Internal Keyboard/Trackpad (MacBook Pro 4,1) (ISO) + 0232 Internal Keyboard/Trackpad (MacBook Pro 4,1) (JIS) + 0236 Internal Keyboard/Trackpad (ANSI) + 0237 Internal Keyboard/Trackpad (ISO) + 0238 Internal Keyboard/Trackpad (JIS) + 023f Internal Keyboard/Trackpad (ANSI) + 0240 Internal Keyboard/Trackpad (ISO) + 0241 Internal Keyboard/Trackpad (JIS) + 0242 Internal Keyboard/Trackpad (ANSI) + 0243 Internal Keyboard/Trackpad (ISO) + 0244 Internal Keyboard/Trackpad (JIS) + 0245 Internal Keyboard/Trackpad (ANSI) + 0246 Internal Keyboard/Trackpad (ISO) + 0247 Internal Keyboard/Trackpad (JIS) + 024a Internal Keyboard/Trackpad (MacBook Air) (ISO) + 024d Internal Keyboard/Trackpad (MacBook Air) (ISO) + 0250 Aluminium Keyboard (ISO) + 0252 Internal Keyboard/Trackpad (ANSI) + 0253 Internal Keyboard/Trackpad (ISO) + 0254 Internal Keyboard/Trackpad (JIS) + 0259 Internal Keyboard/Trackpad + 0263 Apple Internal Keyboard / Trackpad (MacBook Retina) + 0267 Magic Keyboard A1644 + 0269 Magic Mouse 2 (Lightning connector) + 0273 Internal Keyboard/Trackpad (ISO) + 0301 USB Mouse [Mitsumi, M4848] + 0302 Optical Mouse [Fujitsu] + 0304 Mighty Mouse [Mitsumi, M1152] + 0306 Optical USB Mouse [Fujitsu] + 030a Internal Trackpad + 030b Internal Trackpad + 030d Magic Mouse + 030e MC380Z/A [Magic Trackpad] + 1000 Bluetooth HCI MacBookPro (HID mode) + 1001 Keyboard Hub [ALPS] + 1002 Extended Keyboard Hub [Mitsumi] + 1003 Hub in Pro Keyboard [Mitsumi, A1048] + 1006 Hub in Aluminum Keyboard + 1008 Mini DisplayPort to Dual-Link DVI Adapter + 1101 Speakers + 1105 Audio in LED Cinema Display + 1107 Thunderbolt Display Audio + 1112 FaceTime HD Camera (Display) + 1201 3G iPod + 1202 iPod 2G + 1203 iPod 4.Gen Grayscale 40G + 1204 iPod [Photo] + 1205 iPod Mini 1.Gen/2.Gen + 1206 iPod '06' + 1207 iPod '07' + 1208 iPod '08' + 1209 iPod Video + 120a iPod Nano + 1223 iPod Classic/Nano 3.Gen (DFU mode) + 1224 iPod Nano 3.Gen (DFU mode) + 1225 iPod Nano 4.Gen (DFU mode) + 1227 Mobile Device (DFU Mode) + 1231 iPod Nano 5.Gen (DFU mode) + 1240 iPod Nano 2.Gen (DFU mode) + 1242 iPod Nano 3.Gen (WTF mode) + 1243 iPod Nano 4.Gen (WTF mode) + 1245 iPod Classic 3.Gen (WTF mode) + 1246 iPod Nano 5.Gen (WTF mode) + 1255 iPod Nano 4.Gen (DFU mode) + 1260 iPod Nano 2.Gen + 1261 iPod Classic + 1262 iPod Nano 3.Gen + 1263 iPod Nano 4.Gen + 1265 iPod Nano 5.Gen + 1266 iPod Nano 6.Gen + 1267 iPod Nano 7.Gen + 1281 Apple Mobile Device [Recovery Mode] + 1290 iPhone + 1291 iPod Touch 1.Gen + 1292 iPhone 3G + 1293 iPod Touch 2.Gen + 1294 iPhone 3GS + 1296 iPod Touch 3.Gen (8GB) + 1297 iPhone 4 + 1299 iPod Touch 3.Gen + 129a iPad + 129c iPhone 4(CDMA) + 129e iPod Touch 4.Gen + 129f iPad 2 + 12a0 iPhone 4S + 12a2 iPad 2 (3G; 64GB) + 12a3 iPad 2 (CDMA) + 12a4 iPad 3 (wifi) + 12a5 iPad 3 (CDMA) + 12a6 iPad 3 (3G, 16 GB) + 12a8 iPhone5/5C/5S/6 + 12a9 iPad 2 + 12aa iPod Touch 5.Gen [A1421] + 12ab iPad 4/Mini1 + 1300 iPod Shuffle + 1301 iPod Shuffle 2.Gen + 1302 iPod Shuffle 3.Gen + 1303 iPod Shuffle 4.Gen + 1401 Modem + 1402 Ethernet Adapter [A1277] + 1500 SuperDrive [A1379] + 8005 OHCI Root Hub Simulation + 8006 EHCI Root Hub Simulation + 8007 XHCI Root Hub USB 2.0 Simulation + 8202 HCF V.90 Data/Fax Modem + 8203 Bluetooth HCI + 8204 Built-in Bluetooth 2.0+EDR HCI + 8205 Bluetooth HCI + 8206 Bluetooth HCI + 820a Bluetooth HID Keyboard + 820b Bluetooth HID Mouse + 820f Bluetooth HCI + 8213 Bluetooth Host Controller + 8215 Built-in Bluetooth 2.0+EDR HCI + 8216 Bluetooth USB Host Controller + 8217 Bluetooth USB Host Controller + 8218 Bluetooth Host Controller + 821a Bluetooth Host Controller + 821f Built-in Bluetooth 2.0+EDR HCI + 8240 Built-in IR Receiver + 8241 Built-in IR Receiver + 8242 Built-in IR Receiver + 8281 Bluetooth Host Controller + 8286 Bluetooth Host Controller + 828c Bluetooth Host Controller + 8290 Bluetooth Host Controller + 8300 Built-in iSight (no firmware loaded) + 8403 Internal Memory Card Reader + 8404 Internal Memory Card Reader + 8501 Built-in iSight [Micron] + 8502 Built-in iSight + 8505 Built-in iSight + 8507 Built-in iSight + 8508 iSight in LED Cinema Display + 8509 FaceTime HD Camera + 850a FaceTime Camera + 8510 FaceTime HD Camera (Built-in) + 911c Hub in A1082 [Cinema HD Display 23"] + 9127 Hub in Thunderbolt Display + 912f Hub in 30" Cinema Display + 9215 Studio Display 15" + 9217 Studio Display 17" + 9218 Cinema Display 23" + 9219 Cinema Display 20" + 921c A1082 [Cinema HD Display 23"] + 921e Cinema Display 24" + 9221 30" Cinema Display + 9226 LED Cinema Display + 9227 Thunderbolt Display + 9232 Cinema HD Display 30" + ffff Bluetooth in DFU mode - Driver +05ad Y.C. Cable U.S.A., Inc. +05ae Synopsys, Inc. +05af Jing-Mold Enterprise Co., Ltd + 0806 HP SK806A Keyboard + 0809 Wireless Keyboard and Mouse + 0821 IDE to + 3062 Cordless Keyboard + 9167 KB 9151B - 678 + 9267 KB 9251B - 678 Mouse +05b0 Fountain Technologies, Inc. +05b1 First International Computer, Inc. + 1389 Bluetooth Wireless Adapter +05b4 LG Semicon Co., Ltd + 4857 M-Any DAH-210 + 6001 HYUNDAI GDS30C6001 SSFDC / MMC I/F Controller +05b5 Dialogic Corp. +05b6 Proxima Corp. +05b7 Medianix Semiconductor, Inc. +05b8 Agiler, Inc. + 3002 Scroll Mouse + 3223 ISY Wireless Presenter +05b9 Philips Research Laboratories +05ba DigitalPersona, Inc. + 0007 Fingerprint Reader + 0008 Fingerprint Reader + 000a Fingerprint Reader +05bb Grey Cell Systems +05bc 3G Green Green Globe Co., Ltd + 0004 Trackball +05bd RAFI GmbH & Co. KG +05be Tyco Electronics (Raychem) +05bf S & S Research +05c0 Keil Software +05c1 Kawasaki Microelectronics, Inc. +05c2 Media Phonics (Suisse) S.A. +05c5 Digi International, Inc. + 0002 AccelePort USB 2 + 0004 AccelePort USB 4 + 0008 AccelePort USB 8 +05c6 Qualcomm, Inc. + 0114 Select RW-200 CDMA Wireless Modem + 1000 Mass Storage Device + 3100 CDMA Wireless Modem/Phone + 3196 CDMA Wireless Modem + 3197 CDMA Wireless Modem/Phone + 6000 Siemens SG75 + 6503 AnyData APE-540H + 6613 Onda H600/N501HS ZTE MF330 + 6764 A0001 Phone [OnePlus One] + 9000 SIMCom SIM5218 modem + 9001 Gobi Wireless Modem + 9002 Gobi Wireless Modem + 9003 Quectel UC20 + 9008 Gobi Wireless Modem (QDL mode) + 9018 Qualcomm HSUSB Device + 9025 Qualcomm HSUSB Device + 9201 Gobi Wireless Modem (QDL mode) + 9202 Gobi Wireless Modem + 9203 Gobi Wireless Modem + 9205 Gobi 2000 + 9211 Acer Gobi Wireless Modem (QDL mode) + 9212 Acer Gobi Wireless Modem + 9214 Acer Gobi 2000 Wireless Modem (QDL mode) + 9215 Acer Gobi 2000 Wireless Modem + 9221 Gobi Wireless Modem (QDL mode) + 9222 Gobi Wireless Modem + 9224 Sony Gobi 2000 Wireless Modem (QDL mode) + 9225 Sony Gobi 2000 Wireless Modem + 9231 Gobi Wireless Modem (QDL mode) + 9234 Top Global Gobi 2000 Wireless Modem (QDL mode) + 9235 Top Global Gobi 2000 Wireless Modem + 9244 Samsung Gobi 2000 Wireless Modem (QDL mode) + 9245 Samsung Gobi 2000 Wireless Modem + 9264 Asus Gobi 2000 Wireless Modem (QDL mode) + 9265 Asus Gobi 2000 Wireless Modem + 9274 iRex Technologies Gobi 2000 Wireless Modem (QDL mode) + 9275 iRex Technologies Gobi 2000 Wireless Modem +05c7 Qtronix Corp. + 0113 PC Line Mouse + 1001 Lynx Mouse + 2001 Keyboard + 2011 SCorpius Keyboard + 6001 Ten-Keypad +05c8 Cheng Uei Precision Industry Co., Ltd (Foxlink) + 0103 FO13FF-65 PC-CAM + 010b Webcam (UVC) + 021a HP Webcam + 0318 Webcam + 0361 SunplusIT INC. HP Truevision HD Webcam + 036e Webcam + 0403 Webcam + 041b HP 2.0MP High Definition Webcam +05c9 Semtech Corp. +05ca Ricoh Co., Ltd + 0101 RDC-5300 Camera + 0325 Caplio GX (ptp) + 032d Caplio GX 8 (ptp) + 032f Caplio R3 (ptp) + 03a1 IS200e + 0403 Printing Support + 0405 Type 101 + 0406 Type 102 + 1803 V5 camera [R5U870] + 1810 Pavilion Webcam [R5U870] + 1812 Pavilion Webcam + 1814 HD Webcam + 1815 Dell Laptop Integrated Webcam + 1820 Integrated Webcam + 1830 Visual Communication Camera VGP-VCC2 [R5U870] + 1832 Visual Communication Camera VGP-VCC3 [R5U870] + 1833 Visual Communication Camera VGP-VCC2 [R5U870] + 1834 Visual Communication Camera VGP-VCC2 [R5U870] + 1835 Visual Communication Camera VGP-VCC5 [R5U870] + 1836 Visual Communication Camera VGP-VCC4 [R5U870] + 1837 Visual Communication Camera VGP-VCC4 [R5U870] + 1839 Visual Communication Camera VGP-VCC6 [R5U870] + 183a Visual Communication Camera VGP-VCC7 [R5U870] + 183b Visual Communication Camera VGP-VCC8 [R5U870] + 183d Sony Vaio Integrated Webcam + 183e Visual Communication Camera VGP-VCC9 [R5U870] + 1841 Fujitsu F01/ Lifebook U810 [R5U870] + 1870 Webcam 1000 + 18b0 Sony Vaio Integrated Webcam + 18b1 Sony Vaio Integrated Webcam + 18b3 Sony Vaio Integrated Webcam + 18b5 Sony Vaio Integrated Webcam + 2201 RDC-7 Camera + 2202 Caplio RR30 + 2203 Caplio 300G + 2204 Caplio G3 + 2205 Caplio RR30 / Medion MD 6126 Camera + 2206 Konica DG-3Z + 2207 Caplio Pro G3 + 2208 Caplio G4 + 2209 Caplio 400G wide + 220a KONICA MINOLTA DG-4Wide + 220b Caplio RX + 220c Caplio GX + 220d Caplio R1/RZ1 + 220e Sea & Sea 5000G + 220f Rollei dr5 / Rollei dr5 (PTP mode) + 2211 Caplio R1S + 2212 Caplio R1v Camera + 2213 Caplio R2 + 2214 Caplio GX 8 + 2215 DSC 725 + 2216 Caplio R3 + 2222 RDC-i500 +05cb PowerVision Technologies, Inc. + 1483 PV8630 interface (scanners, webcams) +05cc ELSA AG + 2100 MicroLink ISDN Office + 2219 MicroLink ISDN + 2265 MicroLink 56k + 2267 MicroLink 56k (V.250) + 2280 MicroLink 56k Fun + 3000 Micolink USB2Ethernet [pegasus] + 3100 AirLancer USB-11 + 3363 MicroLink ADSL Fun +05cd Silicom, Ltd +05ce sci-worx GmbH +05cf Sung Forn Co., Ltd +05d0 GE Medical Systems Lunar +05d1 Brainboxes, Ltd + 0003 Bluetooth Adapter BL-554 +05d2 Wave Systems Corp. +05d3 Tohoku Ricoh Co., Ltd +05d5 Super Gate Technology Co., Ltd +05d6 Philips Semiconductors, CICT +05d7 Thomas & Betts Corp. + 0099 10Mbps Ethernet [klsi] +05d8 Ultima Electronics Corp. + 4001 Artec Ultima 2000 + 4002 Artec Ultima 2000 (GT6801 based)/Lifetec LT9385/ScanMagic 1200 UB Plus Scanner + 4003 Artec E+ 48U + 4004 Artec E+ Pro + 4005 MEM48U + 4006 TRUST EASY WEBSCAN 19200 + 4007 TRUST 240H EASY WEBSCAN GOLD + 4008 Trust Easy Webscan 19200 + 4009 Umax Astraslim + 4013 IT Scan 1200 + 8105 Artec T1 USB TVBOX (cold) + 8106 Artec T1 USB TVBOX (warm) + 8107 Artec T1 USB TVBOX with AN2235 (cold) + 8108 Artec T1 USB TVBOX with AN2235 (warm) + 8109 Artec T1 USB2.0 TVBOX (cold +05d9 Axiohm Transaction Solutions + a225 A225 Printer + a758 A758 Printer + a794 A794 Printer +05da Microtek International, Inc. + 0091 ScanMaker X6u + 0093 ScanMaker V6USL + 0094 Phantom 336CX/C3 + 0099 ScanMaker X6/X6U + 009a Phantom C6 + 00a0 Phantom 336CX/C3 (#2) + 00a3 ScanMaker V6USL + 00ac ScanMaker V6UL + 00b6 ScanMaker V6UPL + 00ef ScanMaker V6UPL + 1006 Jenoptik JD350 entrance + 1011 NHJ Che-ez! Kiss Digital Camera + 1018 Digital Dream Enigma 1.3 + 1020 Digital Dream l'espion xtra + 1025 Take-it Still Camera Device + 1026 Take-it + 1043 Take-It 1300 DSC Bulk Driver + 1045 Take-it D1 + 1047 Take-it Camera Composite Device + 1048 Take-it Q3 + 1049 3M Still Camera Device + 1051 Camcorder Series + 1052 Mass Storage Device + 1053 Take-it DV Composite Device + 1054 Mass Storage Device + 1055 Digital Camera Series(536) + 1056 Mass Storage Device + 1057 Take-it DSC Camera Device(536) + 1058 Mass Storage Device + 1059 Camcorder DSC Series + 1060 Microtek Take-it MV500 + 2007 ArtixScan DI 1210 + 200c 1394_USB2 Scanner + 200e ArtixScan DI 810 + 2017 UF ICE Scanner + 201c 4800 Scanner + 201d ArtixScan DI 1610 + 201f 4800 Scanner-ICE + 202e ArtixScan DI 2020 + 208b ScanMaker 6800 + 208f ArtixScan DI 2010 + 209e ScanMaker 4700LP + 20a7 ScanMaker 5600 + 20b0 ScanMaker X12USL + 20b1 ScanMaker 8700 + 20b4 ScanMaker 4700 + 20bd ScanMaker 5700 + 20c9 ScanMaker 6700 + 20d2 Microtek ArtixScan 1800f + 20d6 PS4000 + 20de ScanMaker 9800XL + 20e0 ScanMaker 9700XL + 20ed ScanMaker 4700 + 20ee Micortek ScanMaker X12USL + 2838 RT2832U + 3008 Scanner + 300a 4800 ICE Scanner + 300b 4800 Scanner + 300f MiniScan C5 + 3020 4800dpi Scanner + 3021 1200dpi Scanner + 3022 Scanner 4800dpi + 3023 USB1200II Scanner + 3025 ScanMaker S460 + 30c1 USB600 Scanner + 30ce ScanMaker 3800 + 30cf ScanMaker 4800 + 30d4 USB1200 Scanner + 30d8 Scanner + 30d9 USB2400 Scanner + 30e4 ScanMaker 4100 + 30e5 USB3200 Scanner + 30e6 ScanMaker i320 + 40b3 ScanMaker 3600 + 40b8 ScanMaker 3700 + 40c7 ScanMaker 4600 + 40ca ScanMaker 3600 + 40cb ScanMaker 3700 + 40dd ScanMaker 3750i + 40ff ScanMaker 3600 + 5003 Goya + 5013 3200 Scanner + 6072 XT-3500 A4 HD Scanner + 80a3 ScanMaker V6USL (#2) + 80ac ScanMaker V6UL/SpicyU +05db Sun Corp. (Suntac?) + 0003 SUNTAC U-Cable type D2 + 0005 SUNTAC U-Cable type P1 + 0009 SUNTAC Slipper U + 000a SUNTAC Ir-Trinity + 000b SUNTAC U-Cable type A3 + 0011 SUNTAC U-Cable type A4 +05dc Lexar Media, Inc. + 0001 jumpSHOT CompactFlash Reader + 0002 JumpShot + 0003 JumpShot + 0080 Jumpdrive Secure 64MB + 0081 RBC Compact Flash Drive + 00a7 JumpDrive Impact + 0100 JumpDrive PRO + 0200 JumpDrive 2.0 Pro + 0300 Jumpdrive Geysr + 0301 JumpDrive Classic + 0302 JD Micro + 0303 JD Micro Pro + 0304 JD Secure II + 0310 JumpDrive + 0311 JumpDrive Classic + 0312 JD Micro + 0313 JD Micro Pro + 0320 JumpDrive + 0321 JD Micro + 0322 JD Micro Pro + 0323 UFC + 0330 JumpDrive Expression + 0340 JumpDrive TAD + 0350 Express Card + 0400 UFDC + 0401 UFDC + 0403 Locked B Device + 0405 Locked C Device + 0407 Locked D Device + 0409 Locked E Device + 040b Locked F Device + 040d Locked G Device + 040f Locked H Device + 0410 JumpDrive + 0411 JumpDrive + 0413 Locked J Device + 0415 Locked K Device + 0417 Locked L Device + 0419 Locked M Device + 041b Locked N Device + 041d Locked O Device + 041f Locked P Device + 0420 JumpDrive + 0421 JumpDrive + 0423 Locked R Device + 0425 Locked S Device + 0427 Locked T Device + 0429 Locked U Device + 042b Locked V Device + 042d Locked W Device + 042f Locked X Device + 0431 Locked Y Device + 0433 Locked Z Device + 4d02 MP3 Player + 4d12 MP3 Player + 4d30 MP3 Player + a209 JumpDrive S70 + a300 JumpDrive2 + a400 JumpDrive trade; Pro 40-501 + a410 JumpDrive 128MB/256MB + a411 JumpDrive Traveler + a420 JumpDrive Pro + a421 JumpDrive Pro II + a422 JumpDrive Micro Pro + a430 JumpDrive Secure + a431 JumpDrive Secure II + a432 JumpDrive Classic + a440 JumpDrive Lightning + a450 JumpDrive TouchGuard + a460 JD Mercury + a501 JumpDrive Classic + a510 JumpDrive Sport + a530 JumpDrive Expression + a531 JumpDrive Secure II + a560 JumpDrive FireFly + a701 JumpDrive FireFly + a731 JumpDrive FireFly + a762 JumpDrive FireFly + a768 JumpDrive Retrax + a790 JumpDrive 2GB + a811 16GB Gizmo! + a813 16gB flash thumb drive + a815 JumpDrive V10 + a81d LJDTT16G [JumpDrive 16GB] + a833 JumpDrive S23 64GB + a838 JumpDrive Tough + b002 USB CF Reader + b018 Multi-Card Reader + b047 SDHC Reader [RW047-7000] + b051 microSD RDR UHS-I Card Reader [LRWM03U-7000] + ba02 Workflow CFR1 + ba0a Workflow DD512 + c753 JumpDrive TwistTurn + c75c JumpDrive V10 +05dd Delta Electronics, Inc. + ff31 AWU-120 + ff32 FriendlyNET AeroLAN AL2011 + ff35 PCW 100 - Wireless 802.11b Adapter + ff91 2Wire PC Port Phoneline 10Mbps Adapter +05df Silicon Vision, Inc. +05e0 Symbol Technologies + 0700 Bar Code Scanner (CS1504) + 0800 Spectrum24 Wireless LAN Adapter + 1200 Bar Code Scanner + 1701 Bar Code Scanner (CDC) + 1900 SNAPI Imaging Device + 2000 MC3090 Rugged Mobile Computer + 200d MC70 Rugged Mobile Computer +05e1 Syntek Semiconductor Co., Ltd + 0100 802.11g + Bluetooth Wireless Adapter + 0408 STK1160 Video Capture Device + 0500 DC-112X Webcam + 0501 DC-1125 Webcam + 0890 STK011 Camera + 0892 STK013 Camera + 0895 STK016 Camera + 0896 STK017 Camera + 2010 ARCTIC Sound P261 Headphones +05e2 ElecVision, Inc. +05e3 Genesys Logic, Inc. + 000a Keyboard with PS/2 Port + 000b Mouse + 0100 Nintendo Game Boy Advance SP + 0120 Pacific Image Electronics PrimeFilm 1800u slide/negative scanner + 0131 CF/SM Reader/Writer + 0142 Multiple Slides Scanner-3600 + 0143 Multiple Frames Film Scanner-36series + 0145 Reflecta CrystalScan 7200 Photo-Scanner + 0180 Plustek Scanner + 0182 Wize Media 1000 + 0189 ScanJet 4600 series + 018a Xerox 6400 + 0300 GLUSB98PT Parallel Port + 0301 USB2LPT Cable Release2 + 0406 Hub + 0501 GL620USB Host-Host interface + 0502 GL620USB-A GeneLink USB-USB Bridge + 0503 Webcam + 0504 HID Keyboard Filter + 0604 USB 1.1 Hub + 0605 USB 2.0 Hub + 0606 USB 2.0 Hub / D-Link DUB-H4 USB 2.0 Hub + 0607 Logitech G110 Hub + 0608 Hub + 0610 4-port hub + 0612 Hub + 0616 hub + 0660 USB 2.0 Hub + 0700 SIIG US2256 CompactFlash Card Reader + 0701 USB 2.0 IDE Adapter + 0702 USB 2.0 IDE Adapter [GL811E] + 0703 Card Reader + 0704 Card Reader + 0705 Card Reader + 0706 Card Reader + 0707 Card Reader + 0708 Card Reader + 0709 Card Reader + 070a Pen Flash + 070b DMHS1B Rev 3 DFU Adapter + 070e USB 2.0 Card Reader + 070f Pen Flash + 0710 USB 2.0 33-in-1 Card Reader + 0711 Card Reader + 0712 Delkin Mass Storage Device + 0715 USB 2.0 microSD Reader + 0716 USB 2.0 Multislot Card Reader/Writer + 0717 All-in-1 Card Reader + 0718 IDE/SATA Adapter + 0719 SATA adapter + 0722 SD/MMC card reader + 0723 GL827L SD/MMC/MS Flash Card Reader + 0726 SD Card Reader + 0727 microSD Reader/Writer + 0731 GL3310 SATA 3Gb/s Bridge Controller + 0732 All-in-One Cardreader + 0736 microSD Reader/Writer + 0738 Card reader + 0741 microSD Card Reader + 0743 SDXC and microSDXC CardReader + 0745 Logilink CR0012 + 0748 All-in-One Cardreader + 0751 microSD Card Reader + 0760 USB 2.0 Card Reader/Writer + 0761 Genesys Mass Storage Device + 0780 USBFS DFU Adapter + 07a0 Pen Flash + 0880 Wasp (SL-6612) + 0927 Card Reader + 1205 Afilias Optical Mouse H3003 / Trust Optical USB MultiColour Mouse MI-2330 + a700 Pen Flash + f102 VX7012 TV Box + f103 VX7012 TV Box + f104 VX7012 TV Box + fd21 3M TL20 Temperature Logger + fe00 Razer Mouse +05e4 Red Wing Corp. +05e5 Fuji Electric Co., Ltd +05e6 Keithley Instruments +05e8 ICC, Inc. +05e9 Kawasaki LSI + 0008 KL5KUSB101B Ethernet [klsi] + 0009 Sony 10Mbps Ethernet [pegasus] + 000c USB-to-RS-232 + 000d USB-to-RS-232 + 0014 RS-232 J104 + 0040 Ethernet Adapter + 2008 Ethernet Adapter +05eb FFC, Ltd +05ec COM21, Inc. +05ee Cytechinfo Inc. +05ef AVB, Inc. [anko?] + 020a Top Shot Pegasus Joystick + 8884 Mag Turbo Force Wheel + 8888 Top Shot Force Feedback Racing Wheel +05f0 Canopus Co., Ltd + 0101 DA-Port DAC +05f1 Compass Communications +05f2 Dexin Corp., Ltd + 0010 AQ Mouse +05f3 PI Engineering, Inc. + 0007 Kinesis Advantage PRO MPC/USB Keyboard + 0081 Kinesis Integrated Hub + 00ff VEC Footpedal + 0203 Y-mouse Keyboard & Mouse Adapter + 020b PS2 Adapter + 0232 X-Keys Switch Interface, Programming Mode + 0261 X-Keys Switch Interface, SPLAT Mode + 0264 X-Keys Switch Interface, Composite Mode +05f5 Unixtar Technology, Inc. +05f6 AOC International +05f7 RFC Distribution(s) PTE, Ltd +05f9 PSC Scanning, Inc. + 1104 Magellan 2200VS + 1206 Gryphon series (OEM mode) + 2202 Point of Sale Handheld Scanner + 2206 Gryphon series (keyboard emulation mode) + 220c Datalogic Gryphon GD4430 + 2601 Datalogic Magellan 1000i Barcode Scanner + 2602 Datalogic Magellan 1100i Barcode Scanner + 4204 Gryphon series (RS-232 emulation mode) + 5204 Datalogic Gryphon GFS4170 (config mode) +05fa Siemens Telecommunications Systems, Ltd + 3301 Keyboard with PS/2 Mouse Port + 3302 Keyboard + 3303 Keyboard with PS/2 Mouse Port +05fc Harman + 0001 Soundcraft Si Multi Digital Card + 0010 Soundcraft Si MADI combo card + 7849 Harman/Kardon SoundSticks +05fd InterAct, Inc. + 0239 SV-239 HammerHead Digital + 0251 Raider Pro + 0253 ProPad 8 Digital + 0286 SV-286 Cyclone Digital + 107a PowerPad Pro X-Box pad + 262a 3dfx HammerHead FX + 262f HammerHead Fx + daae Game Shark + dbae Datel XBoxMC +05fe Chic Technology Corp. + 0001 Mouse + 0003 Cypress USB Mouse + 0005 Viewmaster 4D Browser Mouse + 0007 Twinhead Mouse + 0009 Inland Pro 4500/5000 Mouse + 0011 Browser Mouse + 0014 Gamepad + 1010 Optical Wireless + 2001 Microsoft Wireless Receiver 700 +05ff LeCroy Corp. +0600 Barco Display Systems +0601 Jazz Hipster Corp. + 0003 Internet Security Co., Ltd. SecureKey +0602 Vista Imaging, Inc. + 1001 ViCam Webcam +0603 Novatek Microelectronics Corp. + 00f1 Keyboard (Labtec Ultra Flat Keyboard) + 00f2 Keyboard (Labtec Ultra Flat Keyboard) + 6871 Mouse + 8611 NTK96550 based camera +0604 Jean Co., Ltd +0605 Anchor C&C Co., Ltd +0606 Royal Information Electronics Co., Ltd +0607 Bridge Information Co., Ltd +0608 Genrad Ads +0609 SMK Manufacturing, Inc. + 031d eHome Infrared Receiver + 0322 eHome Infrared Receiver + 0334 eHome Infrared Receiver + ff12 SMK Bluetooth Device +060a Worthington Data Solutions, Inc. +060b Solid Year + 0001 MacAlly Keyboard + 0230 KSK-8003 UX Keyboard + 0540 DeltaCo TB-106U Keyboard + 1006 Japanese Keyboard - 260U + 2101 Keyboard + 2231 KSK-6001 UELX Keyboard + 2270 Gigabyte K8100 Aivia Gaming Keyboard + 5253 Thermaltake MEKA G-Unit Gaming Keyboard + 5811 ACK-571U Wireless Keyboard + 5903 Japanese Keyboard - 595U + 6001 SolidTek USB 2p HUB + 6002 SolidTek USB Keyboard + 6003 Japanese Keyboard - 600HM + 6231 Thermaltake eSPORTS Meka Keyboard + 8007 P-W1G1F12 VER:1 [Macally MegaCam] + a001 Maxwell Compact Pc PM3 +060c EEH Datalink GmbH +060d Auctor Corp. +060e Transmonde Technologies, Inc. +060f Joinsoon Electronics Mfg. Co., Ltd +0610 Costar Electronics, Inc. +0611 Totoku Electric Co., Ltd +0613 TransAct Technologies, Inc. +0614 Bio-Rad Laboratories +0615 Quabbin Wire & Cable Co., Inc. +0616 Future Techno Designs PVT, Ltd +0617 Swiss Federal Insitute of Technology + 000a Thymio-II + 000c Thymio-II Wireless +0618 MacAlly + 0101 Mouse +0619 Seiko Instruments, Inc. + 0101 SLP-100 Driver + 0102 SLP-200 Driver + 0103 SLP-100N Driver + 0104 SLP-200N Driver + 0105 SLP-240 Driver + 0501 SLP-440 Driver + 0502 SLP-450 Driver +061a Veridicom International, Inc. + 0110 5thSense Fingerprint Sensor + 0200 FPS200 Fingerprint Sensor + 8200 VKI-A Fingerprint Sensor/Flash Storage (dumb) + 9200 VKI-B Fingerprint Sensor/Flash Storage (smart) +061b Promptus Communications, Inc. +061c Act Labs, Ltd +061d Quatech, Inc. + c020 SSU-100 +061e Nissei Electric Co. + 0001 nissei 128DE-USB - + 0010 nissei 128DE-PNA - +0620 Alaris, Inc. + 0004 QuickVideo weeCam + 0007 QuickVideo weeCam + 000a QuickVideo weeCam + 000b QuickVideo weeCam +0621 ODU-Steckverbindungssysteme GmbH & Co. KG +0622 Iotech, Inc. +0623 Littelfuse, Inc. +0624 Avocent Corp. + 0248 Virtual Hub + 0249 Virtual Keyboard/Mouse + 0251 Virtual Mass Storage + 0294 Dell 03R874 KVM dongle + 0402 Cisco Virtual Keyboard and Mouse + 0403 Cisco Virtual Mass Storage +0625 TiMedia Technology Co., Ltd +0626 Nippon Systems Development Co., Ltd +0627 Adomax Technology Co., Ltd +0628 Tasking Software, Inc. +0629 Zida Technologies, Ltd +062a MosArt Semiconductor Corp. + 0000 Optical mouse + 0001 Notebook Optical Mouse + 0102 Wireless Keyboard/Mouse Combo [MK1152WC] + 0201 Defender Office Keyboard (K7310) S Zodiak KM-9010 + 0252 Emerge Uni-retractable Laser Mouse + 2410 Wireless PS3 gamepad + 3286 Nano Receiver [Sandstrom Laser Mouse SMWLL11] + 4101 Wireless Keyboard/Mouse + 6301 Trust Wireless Optical Mouse MI-4150K + 9003 VoIP Conference Hub (A16GH) + 9004 USR9602 USB Internet Mini Phone +062b Greatlink Electronics Taiwan, Ltd +062c Institute for Information Industry +062d Taiwan Tai-Hao Enterprises Co., Ltd +062e Mainsuper Enterprises Co., Ltd +062f Sin Sheng Terminal & Machine, Inc. +0631 JUJO Electronics Corp. +0633 Cyrix Corp. +0634 Micron Technology, Inc. + 0655 Embedded Mass Storage Drive [RealSSD] +0635 Methode Electronics, Inc. +0636 Sierra Imaging, Inc. + 0003 Vivicam 35Xx +0638 Avision, Inc. + 0268 iVina 1200U Scanner + 026a Minolta Dimage Scan Dual II AF-2820U (2886) + 0a10 iVina FB1600/UMAX Astra 4500 + 0a13 AV600U + 0a15 Konica Minolta SC-110 + 0a16 Konica Minolta SC-215 + 0a30 UMAX Astra 6700 Scanner + 0a41 Avision AM3000/MF3000 Series + 0f01 fi-4010CU +# typo? + 4004 Minolta Dimage Scan Elite II AF-2920 (2888) +0639 Chrontel, Inc. +063a Techwin Corp. +063b Taugagreining HF +063c Yamaichi Electronics Co., Ltd (Sakura) +063d Fong Kai Industrial Co., Ltd +063e RealMedia Technology, Inc. +063f New Technology Cable, Ltd +0640 Hitex Development Tools + 0026 LPC-Stick +0641 Woods Industries, Inc. +0642 VIA Medical Corp. +0644 TEAC Corp. + 0000 Floppy + 0200 All-In-One Multi-Card Reader CA200/B/S + 1000 CD-ROM Drive + 800d TASCAM Portastudio DP-01FX + 800e TASCAM US-122L + 801d TASCAM DR-100 + 8021 TASCAM US-122mkII + d001 CD-R/RW Unit + d002 CD-R/RW Unit + d010 CD-RW/DVD Unit +0645 Who? Vision Systems, Inc. +0646 UMAX +0647 Acton Research Corp. + 0100 ARC SpectraPro UV/VIS/IR Monochromator/Spectrograph + 0101 ARC AM-VM Mono Airpath/Vacuum Monochromator/Spectrograph + 0102 ARC Inspectrum Mono + 0103 ARC Filterwheel + 03e9 Inspectrum 128x1024 F VIS Spectrograph + 03ea Inspectrum 256x1024 F VIS Spectrograph + 03eb Inspectrum 128x1024 B VIS Spectrograph + 03ec Inspectrum 256x1024 B VIS Spectrograph +0648 Inside Out Networks +0649 Weli Science Co., Ltd +064b Analog Devices, Inc. (White Mountain DSP) + 0165 Blackfin 535 [ADZS HPUSB ICE] +064c Ji-Haw Industrial Co., Ltd +064d TriTech Microelectronics, Ltd +064e Suyin Corp. + 2100 Sony Visual Communication Camera + 9700 Asus Integrated Webcam + a100 Acer OrbiCam + a101 Acer CrystalEye Webcam + a102 Acer/Lenovo Webcam [CN0316] + a103 Acer/HP Integrated Webcam [CN0314] + a110 HP Webcam + a114 Lemote Webcam + a116 UVC 1.3MPixel WebCam + a136 Asus Integrated Webcam [CN031B] + a219 1.3M WebCam (notebook emachines E730, Acer sub-brand) + c107 HP webcam [dv6-1190en] + c335 HP TrueVision HD + d101 Acer CrystalEye Webcam + d213 UVC HD Webcam + d217 HP TrueVision HD + e201 Lenovo Integrated Webcam + e203 Lenovo Integrated Webcam + e258 HP TrueVision HD Integrated Webcam + e263 HP TrueVision HD Integrated Webcam + f102 Lenovo Integrated Webcam [R5U877] + f103 Lenovo Integrated Webcam [R5U877] + f209 HP Webcam + f300 UVC 0.3M Webcam +064f WIBU-Systems AG + 03e9 CmStick (MSD, article no. 1001-xx-xxx) + 03f2 CmStick/M (MSD, article no. 1010-xx-xxx) + 03f3 CmStick/M (MSD, article no. 1011-xx-xxx) + 0bd7 Wibu-Box/U (article no. 3031-xx-xxx) + 0bd8 Wibu-Box/RU (article no. 3032-xx-xxx) + 2af9 CmStick (HID, article no. 1001-xx-xxx) + 2b03 CmStick/M (HID, article no. 1011-xx-xxx) + 5213 CmStick/M (COMPOSITE, article no. 1011-xx-xxx) +0650 Dynapro Systems +0651 Likom Technology Sdn. Bhd. +0652 Stargate Solutions, Inc. +0653 CNF, Inc. +0654 Granite Microsystems, Inc. + 0005 Device Bay Controller + 0006 Hub + 0007 Device Bay Controller + 0016 Hub +0655 Space Shuttle Hi-Tech Co., Ltd +0656 Glory Mark Electronic, Ltd +0657 Tekcon Electronics Corp. +0658 Sigma Designs, Inc. + 0200 Aeotec Z-Stick Gen5 (ZW090) - UZB +0659 Aethra +065a Optoelectronics Co., Ltd + 0001 Opticon OPR-2001 / NLV-1001 (keyboard mode) + 0009 NLV-1001 (serial mode) / OPN-2001 [Opticon] +065b Tracewell Systems +065e Silicon Graphics +065f Good Way Technology Co., Ltd & GWC technology Inc. +0660 TSAY-E (BVI) International, Inc. +0661 Hamamatsu Photonics K.K. +0662 Kansai Electric Co., Ltd +0663 Topmax Electronic Co., Ltd + 0103 CobraPad +0664 ET&T Technology Co., Ltd. + 0301 Groovy Technology Corp. GTouch Touch Screen + 0302 Groovy Technology Corp. GTouch Touch Screen + 0303 Groovy Technology Corp. GTouch Touch Screen + 0304 Groovy Technology Corp. GTouch Touch Screen + 0305 Groovy Technology Corp. GTouch Touch Screen + 0306 Groovy Technology Corp. GTouch Touch Screen + 0307 Groovy Technology Corp. GTouch Touch Screen + 0309 Groovy Technology Corp. GTouch Touch Screen +0665 Cypress Semiconductor + 5161 USB to Serial +0667 Aiwa Co., Ltd + 0fa1 TD-U8000 Tape Drive +0668 WordWand +0669 Oce' Printing Systems GmbH +066a Total Technologies, Ltd +066b Linksys, Inc. + 0105 SCM eUSB SmartMedia Card Reader + 010a Melco MCR-U2 SmartMedia / CompactFlash Reader + 200c USB10TX + 2202 USB10TX Ethernet [pegasus] + 2203 USB100TX Ethernet [pegasus] + 2204 USB100TX HomePNA Ethernet [pegasus] + 2206 USB Ethernet [pegasus] + 2207 HomeLink Phoneline 10M Network Adapter + 2211 WUSB11 802.11b Adapter + 2212 WUSB11v2.5 802.11b Adapter + 2213 WUSB12v1.1 802.11b Adapter + 2219 Instant Wireless Network Adapter + 400b USB10TX +066d Entrega, Inc. +066e Acer Semiconductor America, Inc. +066f SigmaTel, Inc. + 003b MP3 Player + 003e MP3 Player + 003f MP3 Player + 0040 MP3 Player + 0041 MP3 Player + 0042 MP3 Player + 0043 MP3 Player + 004b A-Max PA11 MP3 Player + 3400 STMP3400 D-Major MP3 Player + 3410 STMP3410 D-Major MP3 Player + 3500 Player Recovery Device + 3780 STMP3780/i.MX23 SystemOnChip in RecoveryMode + 4200 STIr4200 IrDA Bridge + 4210 STIr4210 IrDA Bridge + 8000 MSCN MP3 Player + 8001 SigmaTel MSCN Audio Player + 8004 MSCNMMC MP3 Player + 8008 i-Bead 100 MP3 Player + 8020 MP3 Player + 8034 MP3 Player + 8036 MP3 Player + 8038 MP3 Player + 8056 MP3 Player + 8060 MP3 Player + 8066 MP3 Player + 807e MP3 Player + 8092 MP3 Player + 8096 MP3 Player + 809a MP3 Player + 80aa MP3 Player + 80ac MP3 Player + 80b8 MP3 Player + 80ba MP3 Player + 80bc MP3 Player + 80bf MP3 Player + 80c5 MP3 Player + 80c8 MP3 Player + 80ca MP3 Player + 80cc MP3 Player + 8104 MP3 Player + 8106 MP3 Player + 8108 MP3 Player + 810a MP3 Player + 810c MP3 Player + 8122 MP3 Player + 8124 MP3 Player + 8126 MP3 Player + 8128 MP3 Player + 8134 MP3 Player + 8136 MP3 Player + 8138 MP3 Player + 813a MP3 Player + 813e MP3 Player + 8140 MP3 Player + 8142 MP3 Player + 8144 MP3 Player + 8146 MP3 Player + 8148 MP3 Player + 814c MP3 Player + 8201 MP3 Player + 8202 Jens of Sweden / I-BEAD 150M/150H MP3 player + 8203 MP3 Player + 8204 MP3 Player + 8205 MP3 Player + 8206 Digital MP3 Music Player + 8207 MP3 Player + 8208 MP3 Player + 8209 MP3 Player + 820a MP3 Player + 820b MP3 Player + 820c MP3 Player + 820d MP3 Player + 820e MP3 Player + 820f MP3 Player + 8210 MP3 Player + 8211 MP3 Player + 8212 MP3 Player + 8213 MP3 Player + 8214 MP3 Player + 8215 MP3 Player + 8216 MP3 Player + 8217 MP3 Player + 8218 MP3 Player + 8219 MP3 Player + 821a MP3 Player + 821b MP3 Player + 821c MP3 Player + 821d MP3 Player + 821e MP3 Player + 821f MP3 Player + 8220 MP3 Player + 8221 MP3 Player + 8222 MP3 Player + 8223 MP3 Player + 8224 MP3 Player + 8225 MP3 Player + 8226 MP3 Player + 8227 MP3 Player + 8228 MP3 Player + 8229 MP3 Player + 8230 MP3 Player + 829c MP3 Player + 82e0 MP3 Player + 8320 TrekStor i.Beat fun + 835d MP3 Player + 9000 MP3 Player + 9001 MP3 Player + 9002 MP3 Player +0670 Sequel Imaging + 0001 Calibrator + 0005 Enable Cable +0672 Labtec, Inc. + 1041 LCS1040 Speaker System + 5000 SpaceBall 4000 FLX +0673 HCL + 5000 Keyboard +0674 Key Mouse Electronic Enterprise Co., Ltd +0675 DrayTek Corp. + 0110 Vigor 128 ISDN TA + 0530 Vigor530 IEEE 802.11G Adapter (ISL3880+NET2280) + 0550 Vigor550 + 1688 miniVigor 128 ISDN TA [HFC-S] + 6694 miniVigor 128 ISDN TA +0676 Teles AG +0677 Aiwa Co., Ltd + 07d5 TM-ED1285(USB) + 0fa1 TD-U8000 Tape Drive +0678 ACard Technology Corp. +067b Prolific Technology, Inc. + 0000 PL2301 USB-USB Bridge + 0001 PL2302 USB-USB Bridge + 0307 Motorola Serial Adapter + 04bb PL2303 Serial (IODATA USB-RSAQ2) + 0600 IDE Bridge + 0610 Onext EG210U MODEM + 0611 AlDiga AL-11U Quad-band GSM/GPRS/EDGE modem + 2303 PL2303 Serial Port + 2305 PL2305 Parallel Port + 2306 Raylink Bridge Controller + 2307 PL2307 USB-ATAPI4 Bridge + 2313 FITEL PHS U Cable Adaptor + 2315 Flash Disk Embedded Hub + 2316 Flash Disk Security Device + 2317 Mass Storage Device + 2501 PL2501 USB-USB Bridge (USB 2.0) + 2506 Kaser 8gB micro hard drive + 2507 PL2507 Hi-speed USB to IDE bridge controller + 2515 Flash Disk Embedded Hub + 2517 Flash Disk Mass Storage Device + 2528 Storage device (8gB thumb drive) + 25a1 PL25A1 Host-Host Bridge + 2773 PL2773 SATAII bridge controller + 3400 Hi-Speed Flash Disk with TruePrint AES3400 + 3500 Hi-Speed Flash Disk with TruePrint AES3500 + 3507 PL3507 ATAPI6 Bridge + aaa0 Prolific Pharos + aaa2 PL2303 Serial Adapter (IODATA USB-RSAQ3) + aaa3 PL2303x Serial Adapter +067c Efficient Networks, Inc. + 1001 Siemens SpeedStream 100MBps Ethernet + 1022 Siemens SpeedStream 1022 802.11b Adapter + 1023 SpeedStream Wireless + 4020 SpeedStream 4020 ATM/ADSL Installer + 4031 Efficient ADSL Modem + 4032 SpeedStream 4031 ATM/ADSL Installer + 4033 SpeedStream 4031 ATM/ADSL Installer + 4060 Alcatel Speedstream 4060 ADSL Modem + 4062 Efficient Networks 4060 Loader + 5667 Efficient Networks Virtual Bus for ADSL Modem + c031 SpeedStream 4031 ATM/ADSL Installer + c032 SpeedStream 4031 ATM/ADSL Installer + c033 SpeedStream 4031 ATM/ADSL Installer + c060 SpeedStream 4060 Miniport ATM/ADSL Adapter + d667 Efficient Networks Virtual Bus for ADSL Modem + e240 Speedstream Ethernet Adapter E240 + e540 Speedstream Ethernet Adapter E240 +067d Hohner Corp. +067e Intermec Technologies Corp. + 0801 HID Keyboard, Barcode scanner + 0803 VCP, Barcode scanner + 0805 VCP + UVC, Barcode scanner + 1001 Mobile Computer +067f Virata, Ltd + 4552 DSL-200 ADSL Modem + 6542 DSL Modem + 6549 DSL Modem + 7541 DSL Modem +0680 Realtek Semiconductor Corp., CPP Div. (Avance Logic) + 0002 Arowana Optical Wheel Mouse MSOP-01 +0681 Siemens Information and Communication Products + 0001 Dect Base + 0002 Gigaset 3075 Passive ISDN + 0005 ID-Mouse with Fingerprint Reader + 0012 I-Gate 802.11b Adapter + 001b WLL013 + 001d Hipath 1000 + 0022 Gigaset SX353 ISDN + 0026 DECT Data - Gigaset M34 + 002b A-100-I ADSL Modem + 002e ADSL Router_S-141 + 0034 GSM module MC35/ES75 USB Modem + 3c06 54g USB Network Adapter +0682 Victor Company of Japan, Ltd +0684 Actiontec Electronics, Inc. +0685 ZD Incorporated + 7000 HSDPA Modem +0686 Minolta Co., Ltd + 2001 PagePro 4110W + 2004 PagePro 1200W + 2005 Magicolor 2300 DL + 3001 PagePro 4100 + 3005 PagePro 1250E + 3006 PagePro 1250W + 3009 Magicolor 2300W + 300b PagePro 1350W + 300c PagePro 1300W + 302e Develop D 1650iD PCL + 3034 Develop D 2050iD PCL + 4001 Dimage 2300 + 4003 Dimage 2330 Zoom Camera + 4004 Dimage Scan Elite II AF-2920 (2888) + 4005 Minolta DiMAGE E201 Mass Storage Device + 4006 Dimage 7 Camera + 4007 Dimage S304 Camera + 4008 Dimage 5 Camera + 4009 Dimage X Camera + 400a Dimage S404 Camera + 400b Dimage 7i Camera + 400c Dimage F100 Camera + 400d Dimage Scan Dual III AF-2840 (2889) + 400e Dimage Scan Elite 5400 (2890) + 400f Dimage 7Hi Camera + 4010 Dimage Xi Camera + 4011 Dimage F300 Camera + 4012 Dimage F200 Camera + 4014 Dimage S414 Camera + 4015 Dimage XT Camera [storage] + 4016 Dimage XT Camera [remote mode] + 4017 Dimage E223 + 4018 Dimage Z1 Camera + 4019 Dimage A1 Camera [remote mode] + 401a Dimage A1 Camera [storage] + 401c Dimage X20 Camera + 401e Dimage E323 Camera +068a Pertech, Inc. +068b Potrans International, Inc. +068e CH Products, Inc. + 00d3 OEM 3 axis 5 button joystick + 00e2 HFX OEM Joystick + 00f0 Multi-Function Panel + 00f1 Pro Throttle + 00f2 Flight Sim Pedals + 00f3 Fighterstick + 00f4 Combatstick + 00fa Ch Throttle Quadrant + 00ff Flight Sim Yoke + 0500 GameStick 3D + 0501 CH Pro Pedals + 0504 F-16 Combat Stick +0690 Golden Bridge Electech, Inc. +0693 Hagiwara Sys-Com Co., Ltd + 0002 FlashGate SmartMedia Card Reader + 0003 FlashGate CompactFlash Card Reader + 0005 FlashGate + 0006 SM PCCard R/W and SPD + 0007 FlashGate ME (Authenticated) + 000a SDCard/MMC Reader/Writer +0694 Lego Group + 0001 Mindstorms Tower + 0002 Mindstorms NXT + 0005 Mindstorms EV3 + 0006 Mindstorms EV3 Firmware Update +0698 Chuntex (CTX) + 1786 1300ex Monitor + 2003 CTX M730V built in Camera + 9999 VLxxxx Monitor+Hub +0699 Tektronix, Inc. + 0347 AFG 3022B + 036a TDS 2024B +069a Askey Computer Corp. + 0001 VC010 Webcam [pwc] + 0303 Cable Modem + 0311 ADSL Router Remote NDIS Device + 0318 Remote NDIS Device + 0319 220V Remote NDIS Device + 0320 IEEE 802.11b Wireless LAN Card + 0321 Dynalink WLL013 / Compex WLU11A 802.11b Adapter + 0402 Scientific Atlanta WebSTAR 100 & 200 series Cable Modem + 0811 BT Virtual Bus for Helium + 0821 BT Voyager 1010 802.11b Adapter + 4402 Scientific Atlanta WebSTAR 2000 series Cable Modem + 4403 Scientific Atlanta WebSTAR 300 series Cable Modem + 4501 Scientific-Atlanta WebSTAR 2000 series Cable Modem +069b Thomson, Inc. + 0704 DCM245 Cable Modem + 0705 THG540K Cable Modem + 0709 Lyra PDP2424 + 070c MP3 Player + 070d MP3 Player + 070e MP3 Player + 070f RCA Lyra RD1071 MP3 Player + 0731 Lyra M200E256 + 0761 RCA H100A + 0778 PEARL USB Device + 2220 RCA Kazoo RD1000 MP3 Player + 300a RCA Lyra MP3 Player + 3012 MP3 Player + 3013 MP3 Player + 5557 RCA CDS6300 +069d Hughes Network Systems (HNS) + 0001 Satellite Receiver Device + 0002 Satellite Device +069e Welcat Inc. + 0005 Marx CryptoBox v1.2 +069f Allied Data Technologies BV + 0010 Tornado Speakerphone FaxModem 56.0 + 0011 Tornado Speakerphone FaxModem 56.0 + 1000 ADT VvBus for CopperJet + 1004 CopperJet 821 RouterPlus +06a2 Topro Technology, Inc. + 0033 USB Mouse +06a3 Saitek PLC + 0006 Cyborg Gold Joystick + 0109 P880 Pad + 0160 ST290 Pro + 0200 Xbox Adrenalin Hub + 0241 Xbox Adrenalin Gamepad + 0255 X52 Flight Controller + 040b P990 Dual Analog Pad + 040c P2900 Wireless Pad + 0422 ST90 Joystick + 0460 ST290 Pro Flight Stick + 0463 ST290 + 0464 Cyborg Evo + 0471 Cyborg Graphite Stick + 0501 R100 Sports Wheel + 0502 ST200 Stick + 0506 R220 Digital Wheel + 051e Cyborg Digital II Stick + 052d P750 Gamepad + 053c X45 Flight Controller + 053f X36F Flightstick + 056c P2000 Tilt Pad + 056f P2000 Tilt Pad + 05d2 PC Dash 2 + 075c X52 Flight Controller + 0762 Saitek X52 Pro Flight Control System + 0763 Pro Flight Rudder Pedals + 0764 Flight Pro Combat Rudder + 0805 R440 Force Wheel + 0b4e Pro Flight Backlit Information Panel + 0bac Pro Flight Yoke + 0c2d Pro Flight Quadrant + 0d05 Pro Flight Radio Panel + 0d06 Flight Pro Multi Panel + 0d67 Pro Flight Switch Panel + 1003 GM2 Action Pad + 1009 Action Pad + 100a SP550 Pad and Joystick Combo + 100b SP550 Pad + 1509 P3000 Wireless Pad + 1589 P3000 Wireless Pad + 2541 X45 Flight Controller + 3509 P3000 RF GamePad + 353e Cyborg Evo Wireless + 3589 P3000 Wireless Pad + 35be Cyborg Evo + 5509 P3000 Wireless Pad + 712c Pro Flight Yoke integrated hub + 8000 Gamers' Keyboard + 801e Cyborg 3D Digital Stick II + 8020 Eclipse Keyboard + 8021 Eclipse II Keyboard + 802d P750 Pad + 803f X36 Flight Controller + 806f P2000 Tilt Pad + 80c0 Pro Gamer Command Unit + 80c1 Cyborg Command Pad Unit + a2ae Pro Flight Instrument Panel + a502 Gaming Mouse + f518 P3200 Rumble Force Game Pad + ff04 R440 Force Wheel + ff0c Cyborg Force Rumble Pad + ff0d P2600 Rumble Force Pad + ff12 Cyborg 3D Force Stick + ff17 ST 330 Rumble Force Stick + ff52 Cyborg 3D Rumble Force Joystick + ffb5 Cyborg Evo Force Joystick +06a4 Xiamen Doowell Electron Co., Ltd +06a5 Divio + 0000 Typhoon Webcam 100k [nw8000] + d001 ProLink DS3303u Webcam + d800 Chicony TwinkleCam + d820 Wize Media 1000 +06a7 MicroStore, Inc. +06a8 Topaz Systems, Inc. + 0042 SignatureGem 1X5 Pad + 0043 SignatureGem 1X5-HID Pad +06a9 Westell + 0005 WireSpeed Dual Connect Modem + 0006 WireSpeed Dual Connect Modem + 000a WireSpeed Dual Connect Modem + 000b WireSpeed Dual Connect Modem + 000e A90-211WG-01 802.11g Adapter [Intersil ISL3887] +06aa Sysgration, Ltd +06ac Fujitsu Laboratories of America, Inc. +06ad Greatland Electronics Taiwan, Ltd +06ae Professional Multimedia Testing Centre +06af Harting, Inc. of North America +06b8 Pixela Corp. +06b9 Alcatel Telecom + 0120 SpeedTouch 120g 802.11g Wireless Adapter [Intersil ISL3886] + 0121 SpeedTouch 121g Wireless Dongle + 2001 SPEED TOUCH Card + 4061 SpeedTouch ISDN or ADSL Modem + 4062 SpeedTouch ISDN or ADSL router + a5a5 DynaMiTe Modem +06ba Smooth Cord & Connector Co., Ltd +06bb EDA, Inc. +06bc Oki Data Corp. + 000b Okipage 14ex Printer + 0027 Okipage 14e + 00f7 OKI B4600 Mono Printer + 015e OKIPOS 411/412 POS Printer + 01c9 OKI B430 Mono Printer + 020b OKI ES4140 Mono Printer + 02bb OKI PT390 POS Printer + 0a91 B2500MFP (printer+scanner) + 3801 B6100 Laser Printer +06bd AGFA-Gevaert NV + 0001 SnapScan 1212U + 0002 SnapScan 1236U + 0100 SnapScan Touch + 0101 SNAPSCAN ELITE + 0200 ScanMaker 8700 + 02bf DUOSCAN f40 + 0400 CL30 + 0401 Mass Storage + 0403 ePhoto CL18 Camera + 0404 ePhoto CL20 Camera + 2061 SnapScan 1212U (?) + 208d Snapscan e40 + 208f SnapScan e50 + 2091 SnapScan e20 + 2093 SnapScan e10 + 2095 SnapScan e25 + 2097 SnapScan e26 + 20fd SnapScan e52 + 20ff SnapScan e42 +06be AME Optimedia Technology Co., Ltd + 0800 Optimedia Camera + 1005 Dazzle DPVM! (1005) + d001 P35U Camera Capture +06bf Leoco Corp. +06c2 Phidgets Inc. (formerly GLAB) + 0030 PhidgetRFID + 0031 RFID reader + 0038 4-Motor PhidgetServo v3.0 + 0039 1-Motor PhidgetServo v3.0 + 003a 8-Motor PhidgetAvancedServo + 0040 PhidgetInterface Kit 0-0-4 + 0044 PhidgetInterface Kit 0-16-16 + 0045 PhidgetInterface Kit 8-8-8 + 0048 PhidgetStepper (Under Development) + 0049 PhidgetTextLED Ver 1.0 + 004a PhidgetLED Ver 1.0 + 004b PhidgetEncoder Ver 1.0 + 0051 PhidgetInterface Kit 0-5-7 (Custom) + 0052 PhidgetTextLCD + 0053 PhidgetInterfaceKit 0-8-8 + 0058 PhidgetMotorControl Ver 1.0 + 0070 PhidgetTemperatureSensor Ver 1.0 + 0071 PhidgetAccelerometer Ver 1.0 + 0072 PhidgetWeightSensor Ver 1.0 + 0073 PhidgetHumiditySensor + 0074 PhidgetPHSensor + 0075 PhidgetGyroscope +06c4 Bizlink International Corp. +06c5 Hagenuk, GmbH +06c6 Infowave Software, Inc. +06c8 SIIG, Inc. +06c9 Taxan (Europe), Ltd + 0005 Monitor Control + 0007 Monitor Control + 0009 Monitor Control +06ca Newer Technology, Inc. + 2003 uSCSI +06cb Synaptics, Inc. + 0001 TouchPad + 0002 Integrated TouchPad + 0003 cPad + 0005 Touchpad/FPS + 0006 TouchScreen + 0007 USB Styk + 0008 WheelPad + 0009 Composite TouchPad and TrackPoint + 000e HID Device + 0010 Wireless TouchPad + 0013 DisplayPad + 2970 touchpad +06cc Terayon Communication Systems + 0101 Cable Modem + 0102 Cable Modem + 0103 Cable Modem + 0104 Cable Modem + 0304 Cable Modem +06cd Keyspan + 0101 USA-28 PDA [no firmware] + 0102 USA-28X PDA [no firmware] + 0103 USA-19 PDA [no firmware] + 0104 PDA [prerenum] + 0105 USA-18X PDA [no firmware] + 0106 USA-19W PDA [no firmware] + 0107 USA-19 PDA + 0108 USA-19W PDA + 0109 USA-49W serial adapter [no firmware] + 010a USA-49W serial adapter + 010b USA-19Qi serial adapter [no firmware] + 010c USA-19Qi serial adapter + 010d USA-19Q serial Adapter (no firmware) + 010e USA-19Q serial Adapter + 010f USA-28 PDA + 0110 USA-28Xb PDA + 0111 USA-18 serial Adapter + 0112 USA-18X PDA + 0113 USA-28Xb PDA [no firmware] + 0114 USA-28Xa PDA [no firmware] + 0115 USA-28Xa PDA + 0116 USA-18XA serial Adapter (no firmware) + 0117 USA-18XA serial Adapter + 0118 USA-19QW PDA [no firmware] + 0119 USA-19QW PDA + 011a USA-49Wlc serial adapter [no firmware] + 011b MPR Serial Preloader (MPRQI) + 011c MPR Serial (MPRQI) + 011d MPR Serial Preloader (MPRQ) + 011e MPR Serial (MPRQ) + 0121 USA-19hs serial adapter + 012a USA-49Wlc serial adapter + 0201 UIA-10 Digital Media Remote [Cypress AN2131SC] + 0202 UIA-11 Digital Media Remote +06ce Contec + 8311 COM-1(USB)H +06cf SpheronVR AG + 1010 PanoCam 10 + 1012 PanoCam 12/12X +06d0 LapLink, Inc. + 0622 LapLink Gold USB-USB Bridge [net1080] +06d1 Daewoo Electronics Co., Ltd +06d3 Mitsubishi Electric Corp. + 0284 FX-USB-AW/-BD RS482 Converters + 0380 CP8000D Port + 0381 CP770D Port + 0385 CP900D Port + 0387 CP980D Port + 038b CP3020D Port + 038c CP900DW(ID) Port + 0393 CP9500D/DW Port + 0394 CP9000D/DW Port + 0398 P93D + 03a1 CP9550D/DW Port + 03a5 CP9550DW-S + 03a9 CP-9600DW + 03aa CP3020DA + 03ad CP-9800D/DW + 03ae CP-9800DW-S + 3b10 P95D + 3b21 CP-9810D/DW + 3b30 CP-D70DW / CP-D707DW + 3b31 CP-K60DW-S + 3b36 CP-D80DW + 3b50 CP-W5000DW + 3b60 CP-D90DW +06d4 Cisco Systems +06d5 Toshiba + 4000 Japanese Keyboard +06d6 Aashima Technology B.V. + 0025 Gamepad + 0026 Predator TH 400 Gamepad + 002d Trust PowerC@m 350FT + 002e Trust PowerC@m 350FS + 0030 Trust 710 LCD POWERC@M ZOOM - MSD + 0031 Trust 610/710 LCD POWERC@M ZOOM + 003a Trust PowerC@m 770Z (mass storage mode) + 003b Trust PowerC@m 770Z (webcam mode) + 003c Trust 910z PowerC@m + 003f Trust 735S POWERC@M ZOOM, WDM DSC Bulk Driver + 0050 Trust 738AV LCD PV Digital Camera + 0062 TRUST 782AV LCD P. V. Video Capture + 0066 TRUST Digital PCTV and Movie Editor + 0067 Trust 350FS POWERC@M FLASH + 006b TRUST AUDIO VIDEO EDITOR +06d7 Network Computing Devices (NCD) +06d8 Technical Marketing Research, Inc. +06da Phoenixtec Power Co., Ltd + 0002 UPS + 0003 1300VA UPS +06db Paradyne +06dc Foxlink Image Technology Co., Ltd + 0012 Scan 1200c Scanner + 0014 Prolink Winscan Pro 2448U +06de Heisei Electronics Co., Ltd +06e0 Multi-Tech Systems, Inc. + 0319 MT9234ZBA-USB MultiModem ZBA + f101 MT5634ZBA-USB MultiModemUSB (old firmware) + f103 MT5634MU MultiMobileUSB + f104 MT5634ZBA-USB MultiModemUSB (new firmware) + f107 MT5634ZBA-USB-V92 MultiModemUSB + f120 MT9234ZBA-USB-CDC-ACM-XR MultiModem ZBA CDC-ACM-XR +06e1 ADS Technologies, Inc. + 0008 UBS-10BT Ethernet [klsi] + 0009 UBS-10BT Ethernet + 0833 Mass Storage Device + a155 FM Radio Receiver/Instant FM Music (RDX-155-EF) + a160 Instant Video-To-Go RDX-160 (no firmware) + a161 Instant Video-To-Go RDX-160 + a190 Instand VCD Capture + a191 Instant VideoXpress + a337 Mini DigitalTV + a701 DVD Xpress + a708 saa7114H video input card (Instant VideoMPX) + b337 Mini DigitalTV + b701 DVD Xpress B +06e4 Alcatel Microelectronics +06e6 Tiger Jet Network, Inc. + 0200 Internet Phone + 0201 Internet Phone + 0202 Composite Device + 0203 Internet Phone + 0210 Composite Device + 0211 Internet Phone + 0212 Internet Phone + 031c Internet Phone + 031d Internet Phone + 031e Internet Phone + 3200 Composite Device + 3201 Internet Phone + 3202 Composite Device + 3203 Composite Device + 7200 Composite Device + 7210 Composite Device + 7250 Composite Device + 825c Internet Phone + 831c Internet Phone + 831d Composite Device + 831e Composite Device + b200 Composite Device + b201 Composite Device + b202 Internet Phone + b210 Internet Phone + b211 Composite Device + b212 Composite Device + b250 Composite Device + b251 Internet Phone + b252 Internet Phone + c200 Internet Phone + c201 Internet Phone + c202 Composite Device + c203 Internet Phone + c210 Personal PhoneGateway + c211 Personal PhoneGateway + c212 Personal PhoneGateway + c213 PPG Device + c25c Composite Device + c290 PPG Device + c291 PPG Device + c292 PPG Device + c293 Personal PhoneGateway + c31c Composite Device + c39c Personal PhoneGateway + c39d PPG Device + c39e PPG Device + c39f PPG Device + c700 Internet Phone + c701 Internet Phone + c702 Composite Device + c703 Internet Phone + c710 VoIP Combo Device + c711 VoIP Combo + c712 VoIP Combo Device + c713 VoIP Combo Device + cf00 Composite Device + cf01 Internet Phone + cf02 Internet Phone + cf03 Composite Device + d210 Personal PhoneGateway + d211 PPG Device + d212 PPG Device + d213 Personal PhoneGateway + d700 Composite Device + d701 Composite Device + d702 Internet Phone + d703 Composite Device + d710 VoIP Combo + d711 VoIP Combo Device + d712 VoIP Combo + d713 VoIP Combo + df00 Composite Device + df01 Composite Device + df02 Internet Phone + df03 Internet Phone + f200 Internet Phone + f201 Internet Phone + f202 Composite Device + f203 Composite Device + f210 Internet Phone + f250 Composite Device + f252 Internet Phone + f310 Internet Phone + f350 Composite Device +06ea Sirius Technologies + 0001 NetCom Roadster II 56k + 0002 Roadster II 56k +06eb PC Expert Tech. Co., Ltd +06ef I.A.C. Geometrische Ingenieurs B.V. +06f0 T.N.C Industrial Co., Ltd + de01 DualCam Video Camera + de02 DualCam Still Camera +06f1 Opcode Systems, Inc. + a011 SonicPort + a021 SonicPort Optical +06f2 Emine Technology Co. + 0011 KVM Switch Keyboard +06f6 Wintrend Technology Co., Ltd +06f7 Wailly Technology Ltd + 0003 USB->Din 4 Adaptor +06f8 Guillemot Corp. + 3002 Hercules Blog Webcam + 3004 Hercules Classic Silver + 3005 Hercules Dualpix Exchange + 3007 Hercules Dualpix Chat and Show + 3020 Hercules Webcam EC300 + a300 Dual Analog Leader GamePad + b000 Hercules DJ Console + b121 Hercules P32 DJ + c000 Hercules Muse Pocket + d002 Hercules DJ Console + e000 HWGUSB2-54 WLAN + e010 HWGUSB2-54-LB + e020 HWGUSB2-54V2-AP + e031 Hercules HWNUm-300 Wireless N mini [Realtek RTL8191SU] + e032 HWGUm-54 [Hercules Wireless G Ultra Mini Key] + e033 Hercules HWNUp-150 802.11n Wireless N Pico [Realtek RTL8188CUS] +06f9 ASYST electronic d.o.o. +06fa HSD S.r.L +06fc Motorola Semiconductor Products Sector +06fd Boston Acoustics + 0101 Audio Device + 0102 Audio Device + 0201 2-piece Audio Device +06fe Gallant Computer, Inc. +0701 Supercomal Wire & Cable SDN. BHD. +0703 Bvtech Industry, Inc. +0705 NKK Corp. +0706 Ariel Corp. +0707 Standard Microsystems Corp. + 0100 2202 Ethernet [klsi] + 0200 2202 Ethernet [pegasus] + 0201 EZ Connect USB Ethernet + ee04 SMCWUSB32 802.11b Wireless LAN Card + ee06 SMC2862W-G v1 EZ Connect 802.11g Adapter [Intersil ISL3886] + ee13 SMC2862W-G v2 EZ Connect 802.11g Adapter [Intersil ISL3887] +0708 Putercom Co., Ltd + 047e USB-1284 BRIDGE +0709 Silicon Systems, Ltd (SSL) +070a Oki Electric Industry Co., Ltd + 4002 Bluetooth Device + 4003 Bluetooth Device +070d Comoss Electronic Co., Ltd +070e Excel Cell Electronic Co., Ltd +0710 Connect Tech, Inc. + 0001 WhiteHeat (fake ID) + 8001 WhiteHeat +0711 Magic Control Technology Corp. + 0100 Hub + 0180 IRXpress Infrared Device + 0181 IRXpress Infrared Device + 0200 BAY-3U1S1P Serial Port + 0210 MCT1S Serial Port + 0230 MCT-232 Serial Port + 0231 PS/2 Mouse Port + 0232 Serial On Port + 0240 PS/2 to USB Converter + 0300 BAY-3U1S1P Parallel Port + 0302 Parallel Port + 0900 SVGA Adapter + 5001 Trigger UV-002BD[Startech USBVGAE] + 5100 Magic Control Technology Corp. (USB2VGA dongle) +0713 Interval Research Corp. +0714 NewMotion, Inc. + 0003 ADB converter +0717 ZNK Corp. +0718 Imation Corp. + 0002 SuperDisk 120MB + 0003 SuperDisk 120MB (Authenticated) + 0060 Flash Drive + 0061 Flash Drive + 0062 Flash Drive + 0063 Swivel Flash Drive + 0064 Flash Drive + 0065 Flash Drive + 0066 Flash Drive + 0067 Flash Drive + 0068 Flash Drive + 0084 Flash Drive Mini + 043c Flash drive 16GB [Nano Pro] + 0582 Revo Flash Drive + 0622 TDK Trans-It 4GB + 0624 TDK Trans-It 16GB + 1120 RDX External dock (redbud) + 4006 8x Slim DVD Multi-Format Recorder External + d000 Disc Stakka CD/DVD Manager +0719 Tremon Enterprises Co., Ltd +071b Domain Technologies, Inc. + 0002 DTI-56362-USB Digital Interface Unit + 0101 Audio4-USB DSP Data Acquisition Unit + 0184 Archos 2 8GB EM184RB + 0201 Audio4-5410 DSP Data Acquisition Unit + 0301 SB-USB JTAG Emulator + 3203 Rockchip Media Player + 32bb Music Mediatouch +071c Xionics Document Technologies, Inc. +071d Eicon Networks Corp. + 1000 Diva 2.01 S/T [PSB2115F] + 1003 Diva ISDN 2.0 + 1005 Diva ISDN 4.0 [HFC-S] + 2000 Teledat Surf +071e Ariston Technologies +0720 Keyence Corp. + 8001 LJ-V7001 +0723 Centillium Communications Corp. + 0002 Palladia 300/400 Adsl Modem +0726 Vanguard International Semiconductor-America +0729 Amitm + 1000 USC-1000 Serial Port +072e Sunix Co., Ltd +072f Advanced Card Systems, Ltd + 0001 AC1030-based SmartCard Reader + 0008 ACR 80 Smart Card Reader + 0100 AET65 + 0101 AET65 + 0102 AET62 + 0103 AET62 + 0901 ACR1281U-C4 (BSI) + 1000 PLDT Drive + 1001 PLDT Drive + 2011 ACR88U + 2100 ACR128U + 2200 ACR122U + 220a ACR1281U-C5 (BSI) + 220c ACR1283 Bootloader + 220f ACR1281U-C2 (qPBOC) + 2211 ACR1261 1S Dual Reader + 2214 ACR1222 1SAM PICC Reader + 2215 ACR1281 2S CL Reader + 221a ACR1251U-A1 + 221b ACR1251U-C + 2224 ACR1281 1S Dual Reader + 222b ACR1222U-C8 + 222c ACR1283L-D2 + 222d [OEM Reader] + 222e ACR123U + 2242 ACR1251 1S Dual Reader + 8002 AET63 BioTRUSTKey + 8003 ACR120 + 8103 ACR120 + 8201 APG8201 + 8900 ACR89U-A1 + 8901 ACR89U-A2 + 8902 ACR89U-A3 + 9000 ACR38 AC1038-based Smart Card Reader + 9006 CryptoMate + 90cc ACR38 SmartCard Reader + 90ce [OEM Reader] + 90cf ACR38 SAM Smart Card Reader + 90d0 PertoSmart EMV - Card Reader + 90d2 ACR83U + 90d8 ACR3801 + 90db CryptoMate64 + b000 ACR3901U + b100 ACR39U + b101 ACR39K + b102 ACR39T + b103 ACR39F + b104 ACR39U-SAM + b106 ACOS5T2 + b200 ACOS5T1 + b301 ACR32-A1 +0731 Susteen, Inc. + 0528 SonyEricsson DCU-11 Cable +0732 Goldfull Electronics & Telecommunications Corp. +0733 ViewQuest Technologies, Inc. + 0101 Digital Video Camera + 0110 VQ110 Video Camera + 0401 CS330 Webcam + 0402 M-318B Webcam + 0430 Intel Pro Share Webcam + 0630 VQ630 Dual Mode Digital Camera(Bulk) + 0631 Hercules Dualpix + 0780 Smart Cam Deluxe(composite) + 1310 Epsilon 1.3/Jenoptik JD C1.3/UMAX AstraPix 470 (mass storage mode) + 1311 Epsilon 1.3/Jenoptik JD C1.3/UMAX AstraPix 470 (PC Cam mode) + 1314 Mercury 2.1MEG Deluxe Classic Cam + 2211 Jenoptik jdc 21 LCD Camera + 2221 Mercury Digital Pro 3.1p + 3261 Concord 3045 spca536a Camera + 3281 Cyberpix S550V +0734 Lasat Communications A/S + 0001 560V Modem + 0002 Lasat 560V Modem + 043a DVS Audio + 043b 3DeMon USB Capture +0735 Asuscom Network + 2100 ISDN Adapter + 2101 ISDN Adapter + 6694 ISDNlink 128K + c541 ISDN TA 280 +0736 Lorom Industrial Co., Ltd +0738 Mad Catz, Inc. + 4507 XBox Device + 4516 XBox Device + 4520 XBox Device + 4526 XBox Device + 4536 XBox Device + 4540 XBox Device + 4556 XBox Device + 4566 XBox Device + 4576 XBox Device + 4586 XBox Device + 4588 XBox Device + 8818 Street Fighter IV Arcade FightStick (PS3) +073a Chaplet Systems, Inc. + 2230 infrared dongle for remote +073b Suncom Technologies +073c Industrial Electronic Engineers, Inc. + 0305 Pole Display (PC305-3415 2 x 20 Line Display) + 0322 Pole Display (PC322-3415 2 x 20 Line Display) + 0324 Pole Display (LB324-USB 4 x 20 Line Display) + 0330 Pole Display (P330-3415 2 x 20 Line Display) + 0424 Pole Display (SP324-4415 4 x 20 Line Display) + 0450 Pole Display (L450-USB Graphic Line Display) + 0505 Pole Display (SPC505-3415 2 x 20 Line Display) + 0522 Pole Display (SPC522-3415 2 x 20 Line Display) + 0624 Pole Display (SP324-3415 4 x 20 Line Display) +073d Eutron S.p.a. + 0005 Crypto Token + 0007 CryptoIdentity CCID + 0025 SmartKey 3 + 0c00 Pocket Reader + 0d00 StarSign Bio Token 3.0 EU +073e NEC, Inc. + 0301 Game Pad +0742 Stollmann + 2008 ISDN TA [HFC-S] + 2009 ISDN TA [HFC-S] + 200a ISDN TA [HFC-S] +0745 Syntech Information Co., Ltd +0746 Onkyo Corp. + 5500 SE-U55 Audio Device +0747 Labway Corp. +0748 Strong Man Enterprise Co., Ltd +0749 EVer Electronics Corp. +074a Ming Fortune Industry Co., Ltd +074b Polestar Tech. Corp. +074c C-C-C Group PLC +074d Micronas GmbH + 3553 Composite USB-Device + 3554 Composite USB-Device + 3556 Composite USB-Device +074e Digital Stream Corp. + 0001 PS/2 Adapter + 0002 PS/2 Adapter +0755 Aureal Semiconductor +0757 Network Technologies, Inc. +0758 Carl Zeiss Microscopy GmbH +075b Sophisticated Circuits, Inc. + 0001 Kick-off! Watchdog +0763 M-Audio + 0115 O2 / KeyRig 25 + 0117 Trigger Finger + 0119 MidAir + 0150 M-Audio Uno + 0160 M-Audio 1x1 + 0192 M-Audio Keystation 88es + 0193 ProKeys 88 + 0194 ProKeys 88sx + 0195 Oxygen 8 v2 + 0196 Oxygen 49 + 0197 Oxygen 61 + 0198 Axiom 25 + 0199 Axiom 49 + 019a Axiom 61 + 019b KeyRig 49 + 019c KeyStudio + 1001 MidiSport 2x2 + 1002 MidiSport 2x2 + 1003 MidiSport 2x2 + 1010 MidiSport 1x1 + 1011 MidiSport 1x1 + 1014 M-Audio Keystation Loader + 1015 M-Audio Keystation + 1020 Midisport 4x4 + 1021 MidiSport 4x4 + 1030 M-Audio MIDISPORT 8x8 + 1031 MidiSport 8x8/s Loader + 1033 MidiSport 8x8/s + 1040 M-Audio MidiSport 2x4 Loader + 1041 M-Audio MidiSport 2x4 + 1110 MidiSport 1x1 + 2001 M Audio Quattro + 2002 M Audio Duo + 2003 M Audio AudioPhile + 2004 M-Audio MobilePre + 2006 M-Audio Transit + 2007 M-Audio Sonica Theater + 2008 M-Audio Ozone + 200d M-Audio OmniStudio + 200f M-Audio MobilePre + 2010 M-Audio Fast Track + 2012 M-Audio Fast Track Pro + 2013 M-Audio JamLab + 2015 M-Audio RunTime DFU + 2016 M-Audio RunTime DFU + 2019 M-Audio Ozone Academic + 201a M-Audio Micro + 201b M-Audio RunTime DFU + 201d M-Audio Producer + 2024 M-Audio Fast Track MKII + 2080 M-Audio Fast Track Ultra + 2081 M-Audio RunTime DFU / Fast Track Ultra 8R + 2803 M-Audio Audiophile DFU + 2804 M-Audio MobilePre DFU + 2806 M-Audio Transit DFU + 2815 M-Audio DFU + 2816 M-Audio DFU + 281b M-Audio DFU + 2880 M-Audio DFU + 2881 M-Audio DFU +0764 Cyber Power System, Inc. + 0005 Cyber Power UPS + 0501 CP1500 AVR UPS + 0601 PR1500LCDRT2U UPS +0765 X-Rite, Inc. + 5001 Huey PRO Colorimeter + 5010 X-Rite Pantone Color Sensor + 5020 i1 Display Pro + 6003 ColorMunki Smile + d094 X-Rite DTP94 [Quato Silver Haze Pro] +0766 Jess-Link Products Co., Ltd + 001b Packard Bell Go + 0204 TopSpeed Cyberlink Remote Control +0767 Tokheim Corp. +0768 Camtel Technology Corp. + 0006 Camtel Technology USB TV Genie Pro FM Model TVB330 + 0023 eHome Infrared Receiver +0769 Surecom Technology Corp. + 11f2 EP-9001-g 802.11g 54M WLAN Adapter + 11f3 RT2570 + 11f7 802.11g 54M WLAN Adapter + 31f3 RT2573 +076a Smart Technology Enablers, Inc. +076b OmniKey AG + 0596 CardMan 2020 + 1021 CardMan 1021 + 1221 CardMan 1221 + 1784 CardMan 6020 + 3021 CardMan 3121 + 3022 CardMan 3021 + 3610 CardMan 3620 + 3621 CardMan 3621 + 3821 CardMan 3821 + 4321 CardMan 4321 + 5121 CardMan 5121 + 5125 CardMan 5125 + 5321 CardMan 5321 + 5340 CardMan 5021 CL + 6622 CardMan 6121 + a011 CCID Smart Card Reader Keyboard + a021 CCID Smart Card Reader + a022 CardMan Smart@Link + c000 CardMan 3x21 CS + c001 CardMan 5121 CS +076c Partner Tech +076d Denso Corp. +076e Kuan Tech Enterprise Co., Ltd +076f Jhen Vei Electronic Co., Ltd +0770 Welch Allyn, Inc - Medical Division +0771 Observator Instruments BV + 4455 OMC45III + ae0f OMC45III +0772 Your data Our Care +0774 AmTRAN Technology Co., Ltd +0775 Longshine Electronics Corp. +0776 Inalways Corp. +0777 Comda Enterprise Corp. +0778 Volex, Inc. +0779 Fairchild Semiconductor +077a Sankyo Seiki Mfg. Co., Ltd +077b Linksys + 08be BEFCMU10 v4 Cable Modem + 2219 WUSB11 V2.6 802.11b Adapter + 2226 USB200M 100baseTX Adapter + 2227 Network Everywhere NWU11B +077c Forward Electronics Co., Ltd + 0005 NEC Keyboard +077d Griffin Technology + 0223 IMic Audio In/Out + 0405 iMate, ADB Adapter + 0410 PowerMate + 041a PowerWave + 04aa SoundKnob + 07af iMic + 1016 AirClick + 627a Radio SHARK +077f Well Excellent & Most Corp. +0780 Sagem Monetel GmbH + 1202 ORGA 900 Smart Card Terminal Virtual Com Port + 1302 ORGA 6000 Smart Card Terminal Virtual Com Port + 1303 ORGA 6000 Smart Card Terminal USB RNDIS + df55 ORGA 900/6000 Smart Card Terminal DFU +0781 SanDisk Corp. + 0001 SDDR-05a ImageMate CompactFlash Reader + 0002 SDDR-31 ImageMate II CompactFlash Reader + 0005 SDDR-05b (CF II) ImageMate CompactFlash Reader + 0100 ImageMate SDDR-12 + 0200 SDDR-09 (SSFDC) ImageMate SmartMedia Reader [eusb] + 0400 SecureMate SD/MMC Reader + 0621 SDDR-86 Imagemate 6-in-1 Reader + 0720 Sansa C200 series in recovery mode + 0729 Sansa E200 series in recovery mode + 0810 SDDR-75 ImageMate CF-SM Reader + 0830 ImageMate CF/MMC/SD Reader + 1234 Cruzer Mini Flash Drive + 5150 SDCZ2 Cruzer Mini Flash Drive (thin) + 5151 Cruzer Micro Flash Drive + 5153 Cruzer Flash Drive + 5204 Cruzer Crossfire + 5402 U3 Cruzer Micro + 5406 Cruzer Micro U3 + 5408 Cruzer Titanium U3 + 540e Cruzer Contour Flash Drive + 5530 Cruzer + 5567 Cruzer Blade + 556b Cruzer Edge + 556c Ultra + 556d Memory Vault + 5571 Cruzer Fit + 5575 Cruzer Glide + 5576 Cruzer Facet + 5577 Cruzer Pop (8GB) + 557d Cruzer Force (64GB) + 5580 SDCZ80 Flash Drive + 5581 Ultra + 5583 Ultra Fit + 5590 Ultra Dual + 5591 Ultra Flair + 5e10 Encrypted + 6100 Ultra II SD Plus 2GB + 7100 Cruzer Mini + 7101 Pen Flash + 7102 Cruzer Mini + 7103 Cruzer Mini + 7104 Cruzer Micro Mini 256MB Flash Drive + 7105 Cruzer Mini + 7106 Cruzer Mini + 7112 Cruzer Micro 128MB Flash Drive + 7113 Cruzer Micro 256MB Flash Drive + 7114 Cruzer Mini + 7115 Cruzer Mini + 7301 Sansa e100 series (mtp) + 7302 Sansa e100 series (msc) + 7400 Sansa M200 series (mtp) + 7401 Sansa M200 series (msc) + 7420 Sansa E200 series (mtp) + 7421 Sansa E200 Series (msc) + 7422 Sansa E200 series v2 (mtp) + 7423 Sansa E200 series v2 (msc) + 7430 Sansa M200 series + 7431 Sansa M200 series V4 (msc) + 7432 Sansa Clip (mtp) + 7433 Sansa Clip (msc) + 7434 Sansa Clip V2 (mtp) + 7435 Sansa Clip V2 (msc) + 7450 Sansa C250 + 7451 Sansa C240 + 7460 Sansa Express + 7480 Sansa Connect + 7481 Sansa Connect (in recovery mode) + 74b0 Sansa View (msc) + 74b1 Sansa View (mtp) + 74c0 Sansa Fuze (mtp) + 74c1 Sansa Fuze (msc) + 74c2 Sansa Fuze V2 (mtp) + 74c3 Sansa Fuze V2 (msc) + 74d0 Sansa Clip+ (mtp) + 74d1 Sansa Clip+ (msc) + 74e5 Sansa Clip Zip + 8181 Pen Flash + 8183 Hi-Speed Mass Storage Device + 8185 SDCZ2 Cruzer Mini Flash Drive (older, thick) + 8888 Card Reader + 8889 SDDR-88 Imagemate 8-in-1 Reader + 8919 Card Reader + 8989 ImageMate 12-in-1 Reader + 9191 ImageMate CF + 9219 Card Reader + 9292 ImageMate CF Reader/Writer + 9393 ImageMate SD-MMC + 9595 ImageMate xD-SM + 9797 ImageMate MS-PRO + 9919 Card Reader + 9999 SDDR-99 5-in-1 Reader + a7c1 Storage device (SD card reader) + a7e8 SDDR-113 MicroMate SDHC Reader + b2b3 SDDR-103 MobileMate SD+ Reader + b4b5 SDDR-89 V4 ImageMate 12-in-1 Reader + b6ba CF SDDR-289 +0782 Trackerball +0783 C3PO + 0003 LTC31 SmartCard Reader + 0006 LTC31v2 + 0009 KBR36 + 0010 LTC32 +0784 Vivitar, Inc. + 0100 Vivicam 2655 + 1310 Vivicam 3305 + 1688 Vivicam 3665 + 1689 Gateway DC-M42/Labtec DC-505/Vivitar Vivicam 3705 + 2620 AOL Photocam Plus + 2888 Polaroid DC700 + 3330 Nytec ND-3200 Camera + 4300 Traveler D1 + 5260 Werlisa Sport PX 100 / JVC GC-A33 Camera + 5300 Pretec dc530 +0785 NTT-ME + 0001 MN128mini-V ISDN TA + 0003 MN128mini-J ISDN TA +0789 Logitec Corp. + 0026 LHD Device + 0033 DVD Multi-plus unit LDR-H443SU2 + 0063 LDR Device + 0064 LDR-R Device + 00b3 DVD Multi-plus unit LDR-H443U2 + 0105 LAN-TX/U1H2 10/100 Ethernet Adapter [pegasus II] + 010c Realtek RTL8187 Wireless 802.11g 54Mbps Network Adapter + 0160 LAN-GTJ/U2A + 0162 LAN-WN22/U2 Wireless LAN Adapter + 0163 LAN-WN12/U2 Wireless LAN Adapter + 0164 LAN-W150/U2M Wireless LAN Adapter + 0166 LAN-W300N/U2 Wireless LAN Adapter + 0168 LAN-W150N/U2 Wireless LAN Adapter + 0170 LAN-W300AN/U2 Wireless LAN Adapter +078b Happ Controls, Inc. + 0010 Driving UGCI + 0020 Flying UGCI + 0030 Fighting UGCI +078c GTCO/CalComp + 0090 Tablet Adapter + 0100 Tablet Adapter + 0200 Tablet Adapter + 0300 Tablet Adapter + 0400 Digitizer (Whiteboard) +078e Brincom, Inc. +0790 Pro-Image Manufacturing Co., Ltd +0791 Copartner Wire and Cable Mfg. Corp. +0792 Axis Communications AB +0793 Wha Yu Industrial Co., Ltd +0794 ABL Electronics Corp. +0795 RealChip, Inc. +0796 Certicom Corp. +0797 Grandtech Semiconductor Corp. + 6801 Flatbed Scanner + 6802 InkJet Color Printer + 8001 SmartCam + 801a Typhoon StyloCam + 801c Meade Binoculars/Camera + 8901 ScanHex SX-35a + 8909 ScanHex SX-35b + 8911 ScanHex SX-35c +0798 Optelec + 0001 Braille Voyager + 0640 BC640 + 0680 BC680 +0799 Altera + 7651 Programming Unit +079b Sagem + 0024 MSO300/MSO301 Fingerprint Sensor + 0026 MSO350/MSO351 Fingerprint Sensor & SmartCard Reader + 0027 USB-Serial Controller + 002f Mobile + 0030 Mobile Communication Device + 0042 Mobile + 0047 CBM/MSO1300 Fingerprint Sensor + 004a XG-760A 802.11bg + 004b Wi-Fi 11g adapter + 0052 MSO1350 Fingerprint Sensor & SmartCard Reader + 0056 Agfa AP1100 Photo Printer + 005d Mobile Mass Storage + 0062 XG-76NA 802.11bg + 0078 Laser Pro Monochrome MFP +079d Alfadata Computer Corp. + 0201 GamePort Adapter +07a1 Digicom S.p.A. + d952 Palladio USB V.92 Modem +07a2 National Technical Systems +07a3 Onnto Corp. +07a4 Be, Inc. +07a6 ADMtek, Inc. + 07c2 AN986A Ethernet + 0986 AN986 Pegasus Ethernet + 8266 Infineon WildCard-USB Wireless LAN Adapter + 8511 ADM8511 Pegasus II Ethernet + 8513 AN8513 Ethernet + 8515 AN8515 Ethernet +07aa Corega K.K. + 0001 Ether USB-T Ethernet [klsi] + 0004 FEther USB-TX Ethernet [pegasus] + 000c WirelessLAN USB-11 + 000d FEther USB-TXS + 0011 Wireless LAN USB-11 mini + 0012 Stick-11 802.11b Adapter + 0017 FEther USB2-TX + 0018 Wireless LAN USB-11 mini 2 + 001a ULUSB-11 Key + 001c CG-WLUSB2GT 802.11g Wireless Adapter [Intersil ISL3880] + 0020 CG-WLUSB2GTST 802.11g Wireless Adapter [Intersil ISL3887] + 002e CG-WLUSB2GPX [Ralink RT2571W] + 002f CG-WLUSB2GNL + 0031 CG-WLUSB2GS 802.11bg [Atheros AR5523] + 003c CG-WLUSB2GNL + 003f CG-WLUSB300AGN + 0041 CG-WLUSB300GNS + 0042 CG-WLUSB300GNM + 0043 CG-WLUSB300N rev A2 [Realtek RTL8192U] + 0047 CG-WLUSBNM + 0051 CG-WLUSB300NM + 7613 Stick-11 V2 802.11b Adapter + 9601 FEther USB-TXC +07ab Freecom Technologies + fc01 IDE bridge + fc02 Cable II USB-2 + fc03 USB2-IDE IDE bridge + fcd6 Freecom HD Classic + fcf6 DataBar + fcf8 Freecom Classic SL Network Drive + fcfe Hard Drive 80GB +07af Microtech + 0004 SCSI-DB25 SCSI Bridge [shuttle] + 0005 SCSI-HD50 SCSI Bridge [shuttle] + 0006 CameraMate SmartMedia and CompactFlash Card Reader [eusb/shuttle] + fc01 Freecom USB-IDE +07b0 Trust Technologies + 0001 ISDN TA + 0002 ISDN TA128 Plus + 0003 ISDN TA128 Deluxe + 0005 ISDN TA128 SE + 0006 ISDN TA 128 [HFC-S] + 0007 ISDN TA [HFC-S] + 0008 ISDN TA +07b1 IMP, Inc. +07b2 Motorola BCS, Inc. + 0100 SURFboard Voice over IP Cable Modem + 0900 SURFboard Gateway + 0950 SURFboard SBG950 Gateway + 1000 SURFboard SBG1000 Gateway + 4100 SurfBoard SB4100 Cable Modem + 4200 SurfBoard SB4200 Cable Modem + 4210 SurfBoard 4210 Cable Modem + 4220 SURFboard SB4220 Cable Modem + 4500 CG4500 Communications Gateway + 450b CG4501 Communications Gateway + 450e CG4500E Communications Gateway + 5100 SurfBoard SB5100 Cable Modem + 5101 SurfBoard SB5101 Cable Modem + 5120 SurfBoard SB5120 Cable Modem (RNDIS) + 5121 Surfboard 5121 Cable Modem + 7030 WU830G 802.11bg Wireless Adapter [Envara WiND512] +07b3 Plustek, Inc. + 0001 OpticPro 1212U Scanner + 0003 Scanner + 0010 OpticPro U12 Scanner + 0011 OpticPro U24 Scanner + 0013 OpticPro UT12 Scanner + 0014 Scanner + 0015 OpticPro U24 Scanner + 0017 OpticPro UT12/16/24 Scanner + 0204 Scanner + 0400 OpticPro 1248U Scanner + 0401 OpticPro 1248U Scanner #2 + 0403 OpticPro U16B Scanner + 0404 Scanner + 0405 A8 Namecard-s Controller + 0406 A8 Namecard-D Controller + 0410 Scanner + 0412 Scanner + 0413 OpticSlim 1200 Scanner + 0601 OpticPro ST24 Scanner + 0800 OpticPro ST48 Scanner + 0900 OpticBook 3600 Scanner + 090c OpticBook 3600 Plus Scanner + 0a06 TVcam VD100 + 0b00 SmartPhoto F50 + 0c00 OpticPro ST64 Scanner + 0c03 OpticPro ST64+ Scanner + 0c04 Optic Film 7200i scanner + 0c0c PL806 Scanner + 0c26 OpticBook 4600 Scanner + 0c2b Mobile Office D428 Scanner + 0e08 OpticBook A300 Scanner + 1300 OpticBook 3800 Scanner + 1301 OpticBook 4800 Scanner +07b4 Olympus Optical Co., Ltd + 0100 Camedia C-2100/C-3000 Ultra Zoom Camera + 0102 Camedia E-10/C-220/C-50 Camera + 0105 Camedia C-310Z/C-700/C-750UZ/C-755/C-765UZ/C-3040/C-4000/C-5050Z/D-560/C-3020Z Zoom Camera + 0109 C-370Z/C-500Z/D-535Z/X-450 + 010a MAUSB-10 xD and SmartMedia Card Reader + 0112 MAUSB-100 xD Card Reader + 0113 Mju 500 / Stylus Digital Camera (PTP) + 0114 C-350Z Camera + 0118 Mju Mini Digital/Mju Digital 500 Camera / Stylus 850 SW + 0125 Tough TG-1 Camera + 0126 VR340/D750 Digital Camera + 0184 P-S100 port + 0202 Foot Switch RS-26 + 0203 Digital Voice Recorder DW-90 + 0206 Digital Voice Recorder DS-330 + 0207 Digital Voice Recorder & Camera W-10 + 0209 Digital Voice Recorder DM-20 + 020b Digital Voice Recorder DS-4000 + 020d Digital Voice Recorder VN-240PC + 0211 Digital Voice Recorder DS-2300 + 0218 Foot Switch RS-28 + 0244 Digital Voice Recorder VN-8500PC + 024f Digital Voice Recorder DS-7000 + 0280 m:robe 100 +07b5 Mega World International, Ltd + 0017 Joystick + 0213 Thrustmaster Firestorm Digital 3 Gamepad + 0312 Gamepad + 9902 GamePad +07b6 Marubun Corp. +07b7 TIME Interconnect, Ltd +07b8 AboCom Systems Inc + 110c XX1 + 1201 IEEE 802.11b Adapter + 200c XX2 + 2573 Wireless LAN Card + 2770 802.11n/b/g Mini Wireless LAN USB2.0 Adapter + 2870 802.11n/b/g Wireless LAN USB2.0 Adapter + 3070 802.11n/b/g Mini Wireless LAN USB2.0 Adapter + 3071 802.11n/b/g Mini Wireless LAN USB2.0 Adapter + 3072 802.11n/b/g Mini Wireless LAN USB2.0 Adapter + 4000 DU-E10 Ethernet [klsi] + 4002 DU-E100 Ethernet [pegasus] + 4003 1/10/100 Ethernet Adapter + 4004 XX4 + 4007 XX5 + 400b XX6 + 400c XX7 + 401a RTL8151 + 4102 USB 1.1 10/100M Fast Ethernet Adapter + 4104 XX9 + 420a UF200 Ethernet + 5301 GW-US54ZGL 802.11bg + 6001 WUG2690 802.11bg Wireless Module [ZyDAS ZD1211+AL2230] + 8188 AboCom Systems Inc [WN2001 Prolink Wireless-N Nano Adapter] + a001 WUG2200 802.11g Wireless Adapter [Envara WiND512] + abc1 DU-E10 Ethernet [pegasus] + b000 BWU613 + b02a AboCom Bluetooth Device + b02b Bluetooth dongle + b02c BCM92045DG-Flash with trace filter + b02d BCM92045DG-Flash with trace filter + b02e BCM92045DG-Flash with trace filter + b030 BCM92045DG-Flash with trace filter + b031 BCM92045DG-Flash with trace filter + b032 BCM92045DG-Flash with trace filter + b033 BCM92045DG-Flash with trace filter + b21a WUG2400 802.11g Wireless Adapter [Texas Instruments TNETW1450] + b21b HWU54DM + b21c RT2573 + b21d RT2573 + b21e RT2573 + b21f WUG2700 + d011 MP3 Player + e001 Mass Storage Device + e002 Mass Storage Device + e003 Mass Storage Device + e004 Mass Storage Device + e005 Mass Storage Device + e006 Mass Storage Device + e007 Mass Storage Device + e008 Mass Storage Device + e009 Mass Storage Device + e00a Mass Storage Device + e4f0 Card Reader Driver + f101 DSB-560 Modem [atlas] +07bc Canon Computer Systems, Inc. +07bd Webgear, Inc. +07be Veridicom +07c0 Code Mercenaries Hard- und Software GmbH + 1113 JoyWarrior24F8 + 1116 JoyWarrior24F14 + 1121 The Claw + 1500 IO-Warrior 40 + 1501 IO-Warrior 24 + 1502 IO-Warrior 48 + 1503 IO-Warrior 28 + 1511 IO-Warrior 24 Power Vampire + 1512 IO-Warrior 24 Power Vampire +07c1 Keisokugiken + 0068 HKS-0200 USBDAQ +07c4 Datafab Systems, Inc. + 0102 USB to LS120 + 0103 USB to IDE + 1234 USB to ATAPI + a000 CompactFlash Card Reader + a001 CompactFlash & SmartMedia Card Reader [eusb] + a002 Disk Drive + a003 Datafab-based Reader + a004 USB to MMC Class Drive + a005 CompactFlash & SmartMedia Card Reader + a006 SmartMedia Card Reader + a007 Memory Stick Class Drive + a103 MDSM-B reader + a107 USB to Memory Stick (LC1) Drive + a109 LC1 CompactFlash & SmartMedia Card Reader + a10b USB to CF+MS(LC1) + a200 DF-UT-06 Hama MMC/SD Reader + a400 CompactFlash & Microdrive Reader + a600 Card Reader + a604 12-in-1 Card Reader + ad01 Mass Storage Device + ae01 Mass Storage Device + af01 Mass Storage Device + b000 USB to CF(LC1) + b001 USB to CF+PCMCIA + b004 MMC/SD Reader + b006 USB to PCMCIA + b00a USB to CF+SD Drive(LC1) + b00b USB to Memory Stick(LC1) + c010 Kingston FCR-HS2/ATA Card Reader +07c5 APG Cash Drawer + 0500 Cash Drawer +07c6 ShareWave, Inc. + 0002 Bodega Wireless Access Point + 0003 Bodega Wireless Network Adapter +07c7 Powertech Industrial Co., Ltd +07c8 B.U.G., Inc. + 0202 MN128-SOHO PAL +07c9 Allied Telesyn International + b100 AT-USB100 +07ca AVerMedia Technologies, Inc. + 0002 AVerTV PVR USB/EZMaker Pro Device + 0026 AVerTV + 0337 A867 DVB-T dongle + 0837 H837 Hybrid ATSC/QAM + 1228 MPEG-2 Capture Device (M038) + 1830 AVerTV Volar Video Capture (H830) + 3835 AVerTV Volar Green HD (A835B) + 850a AverTV Volar Black HD (A850) + 850b AverTV Red HD+ (A850T) + a309 AVerTV DVB-T (A309) + a801 AVerTV DVB-T (A800) + a815 AVerTV DVB-T Volar X (A815) + a827 AVerTV Hybrid Volar HX (A827) + a867 AVerTV DVB-T (A867) + b300 A300 DVB-T TV receiver + b800 MR800 FM Radio + e880 MPEG-2 Capture Device (E880) + e882 MPEG-2 Capture Device (E882) +07cb Kingmax Technology, Inc. +07cc Carry Computer Eng., Co., Ltd + 0000 CF Card Reader + 0001 Reader (UICSE) + 0002 Reader (UIS) + 0003 SM Card Reader + 0004 SM/CF/PCMCIA Card Reader + 0005 Reader (UISA2SE) + 0006 SM/CF/PCMCIA Card Reader + 0007 Reader (UISA6SE) + 000c SM/CF Card Reader + 000d SM/CF Card Reader + 000e Reader (UISDA) + 000f Reader (UICLIK) + 0010 Reader (UISMA) + 0012 Reader (UISC6SE-FLASH) + 0014 Litronic Fortezza Reader + 0030 Mass Storage (UISDMC12S) + 0040 Mass Storage (UISDMC13S) + 0100 Reader (UID) + 0101 Reader (UIM) + 0102 Reader (UISDMA) + 0103 Reader (UISDMC) + 0104 Reader (UISDM) + 0200 6-in-1 Card Reader + 0201 Mass Storage (UISDMC1S & UISDMC3S) + 0202 Mass Storage (UISDMC5S) + 0203 Mass Storage (UISMC5S) + 0204 Mass Storage (UIM4/5S & UIM7S) + 0205 Mass Storage (UIS4/5S & UIS7S) + 0206 Mass Storage (UISDMC10S & UISDMC11S) + 0207 Mass Storage (UPIDMA) + 0208 Mass Storage (UCFC II) + 0210 Mass Storage (UPIXXA) + 0213 Mass Storage (UPIDA) + 0214 Mass Storage (UPIMA) + 0215 Mass Storage (UPISA) + 0217 Mass Storage (UPISDMA) + 0223 Mass Storage (UCIDA) + 0224 Mass Storage (UCIMA) + 0225 Mass Storage (UIS7S) + 0227 Mass Storage (UCIDMA) + 0234 Mass Storage (UIM7S) + 0235 Mass Storage (UIS4S-S) + 0237 Velper (UISDMC4S) + 0300 6-in-1 Card Reader + 0301 6-in-1 Card Reader + 0303 Mass Storage (UID10W) + 0304 Mass Storage (UIM10W) + 0305 Mass Storage (UIS10W) + 0308 Mass Storage (UIC10W) + 0309 Mass Storage (UISC3W) + 0310 Mass Storage (UISDMA2W) + 0311 Mass Storage (UISDMC14W) + 0320 Mass Storage (UISDMC4W) + 0321 Mass Storage (UISDMC37W) + 0330 WINTERREADER Reader + 0350 9-in-1 Card Reader + 0500 Mass Storage + 0501 Mass Storage +07cd Elektor + 0001 USBuart Serial Port +07cf Casio Computer Co., Ltd + 1001 QV-8000SX/5700/3000EX Digicam; Exilim EX-M20 + 1003 Exilim EX-S500 + 1004 Exilim EX-Z120 + 1011 USB-CASIO PC CAMERA + 1116 EXILIM EX-Z19 + 1125 Exilim EX-H10 Digital Camera (mass storage mode) + 1133 Exilim EX-Z350 Digital Camera (mass storage mode) + 1225 Exilim EX-H10 Digital Camera (PictBridge mode) + 1233 Exilim EX-Z350 Digital Camera (PictBridge mode) + 2002 E-125 Cassiopeia Pocket PC + 3801 WMP-1 MP3-Watch + 4001 Label Printer KL-P1000 + 4007 CW50 Device + 4104 Cw75 Device + 4107 CW-L300 Device + 4500 LV-20 Digital Camera + 6101 fx-9750gII + 6102 fx-CP400 + 6801 PL-40R + 6802 MIDI Keyboard +07d0 Dazzle + 0001 Digital Video Creator I + 0002 Global Village VideoFX Grabber + 0003 Fusion Model DVC-50 Rev 1 (NTSC) + 0004 DVC-800 (PAL) Grabber + 0005 Fusion Video and Audio Ports + 0006 DVC 150 Loader Device + 0007 DVC 150 + 0327 Fusion Digital Media Reader + 1001 DM-FLEX DFU Adapter + 1002 DMHS2 DFU Adapter + 1102 CF Reader/Writer + 1103 SD Reader/Writer + 1104 SM Reader/Writer + 1105 MS Reader/Writer + 1106 xD/SM Reader/Writer + 1202 MultiSlot Reader/Writer + 2000 FX2 DFU Adapter + 2001 eUSB CompactFlash Reader + 4100 Kingsun SF-620 Infrared Adapter + 4101 Connectivity Cable (CA-42 clone) + 4959 Kingsun KS-959 Infrared Adapter +07d1 D-Link System + 13ec VvBus for Helium 2xx + 13ed VvBus for Helium 2xx + 13f1 DSL-302G Modem + 13f2 DSL-502G Router + 3300 DWA-130 802.11n Wireless N Adapter(rev.E) [Realtek RTL8191SU] + 3302 DWA-130 802.11n Wireless N Adapter(rev.C2) [Realtek RTL8191SU] + 3303 DWA-131 802.11n Wireless N Nano Adapter(rev.A1) [Realtek RTL8192SU] + 3304 FR-300USB 802.11bgn Wireless Adapter + 3a07 WUA-2340 RangeBooster G Adapter(rev.A) [Atheros AR5523] + 3a08 WUA-2340 RangeBooster G Adapter(rev.A) (no firmware) [Atheros AR5523] + 3a09 DWA-160 802.11abgn Xtreme N Dual Band Adapter(rev.A2) [Atheros AR9170+AR9104] + 3a0d DWA-120 802.11g Wireless 108G Adapter [Atheros AR5523] + 3a0f DWA-130 802.11n Wireless N Adapter(rev.D) [Atheros AR9170+AR9102] + 3a10 DWA-126 802.11n Wireless Adapter [Atheros AR9271] + 3b01 AirPlus G DWL-G122 Wireless Adapter(rev.D) [Marvell 88W8338+88W8010] + 3b10 DWA-142 RangeBooster N Adapter [Marvell 88W8362+88W8060] + 3b11 DWA-130 802.11n Wireless N Adapter(rev.A1) [Marvell 88W8362+88W8060] + 3c03 AirPlus G DWL-G122 Wireless Adapter(rev.C1) [Ralink RT2571W] + 3c04 WUA-1340 + 3c05 EH103 Wireless G Adapter + 3c06 DWA-111 802.11bg Wireless Adapter [Ralink RT2571W] + 3c07 DWA-110 Wireless G Adapter(rev.A1) [Ralink RT2571W] + 3c09 DWA-140 RangeBooster N Adapter(rev.B1) [Ralink RT2870] + 3c0a DWA-140 RangeBooster N Adapter(rev.B2) [Ralink RT3072] + 3c0b DWA-110 Wireless G Adapter(rev.B) [Ralink RT2870] + 3c0d DWA-125 Wireless N 150 Adapter(rev.A1) [Ralink RT3070] + 3c0e WUA-2340 RangeBooster G Adapter(rev.B) [Ralink RT2070] + 3c0f AirPlus G DWL-G122 Wireless Adapter(rev.E1) [Ralink RT2070] + 3c10 DWA-160 802.11abgn Xtreme N Dual Band Adapter(rev.A1) [Atheros AR9170+AR9104] + 3c11 DWA-160 Xtreme N Dual Band USB Adapter(rev.B) [Ralink RT2870] + 3c13 DWA-130 802.11n Wireless N Adapter(rev.B) [Ralink RT2870] + 3c15 DWA-140 RangeBooster N Adapter(rev.B3) [Ralink RT2870] + 3c16 DWA-125 Wireless N 150 Adapter(rev.A2) [Ralink RT3070] + 3e02 DWM-156 3.75G HSUPA Adapter + 5100 Remote NDIS Device + a800 DWM-152 3.75G HSUPA Adapter + f101 DBT-122 Bluetooth + fc01 DBT-120 Bluetooth Adapter +07d2 Aptio Products, Inc. +07d3 Cyberdata Corp. +07d5 Radiant Systems +07d7 GCC Technologies, Inc. +07da Arasan Chip Systems +07de Diamond Multimedia + 2820 VC500 Video Capture Dongle +07df David Electronics Co., Ltd +07e0 NCP engineering GmbH + 4742 VPN GovNet Box +07e1 Ambient Technologies, Inc. + 5201 V.90 Modem +07e2 Elmeg GmbH & Co., Ltd +07e3 Planex Communications, Inc. +07e4 Movado Enterprise Co., Ltd + 0967 SCard R/W CSR-145 + 0968 SCard R/W CSR-145 +07e5 QPS, Inc. + 05c2 IDE-to-USB2.0 PCA + 5c01 Que! CDRW +07e6 Allied Cable Corp. +07e7 Mirvo Toys, Inc. +07e8 Labsystems +07ea Iwatsu Electric Co., Ltd +07eb Double-H Technology Co., Ltd +07ec Taiyo Electric Wire & Cable Co., Ltd +07ee Torex Retail (formerly Logware) + 0002 Cash Drawer I/F +07ef STSN + 0001 Internet Access Device +07f2 Microcomputer Applications, Inc. + 0001 KEYLOK II +07f6 Circuit Assembly Corp. +07f7 Century Corp. + 0005 ScanLogic/Century Corporation uATA + 011e Century USB Disk Enclosure +07f9 Dotop Technology, Inc. +07fa DrayTek Corp. + 0778 miniVigor 128 ISDN TA + 0846 ISDN TA [HFC-S] + 0847 ISDN TA [HFC-S] + 1012 BeWAN ADSL USB ST (grey) + 1196 BWIFI-USB54AR 802.11bg + a904 BeWAN ADSL + a905 BeWAN ADSL ST +07fc Thomann + 1113 SWISSONIC EasyKeys61 Midikeyboard +07fd Mark of the Unicorn + 0000 FastLane MIDI Interface + 0001 MIDI Interface + 0002 MOTU Audio for 64 bit +07ff Unknown + 00ff Portable Hard Drive +0801 MagTek + 0001 Mini Swipe Reader (Keyboard Emulation) + 0002 Mini Swipe Reader + 0003 Magstripe Insert Reader +0802 Mako Technologies, LLC +0803 Zoom Telephonics, Inc. + 1300 V92 Faxmodem + 3095 V.92 56K Mini External Modem Model 3095 + 4310 4410a Wireless-G Adapter [Intersil ISL3887] + 4410 4410b Wireless-G Adapter [ZyDAS ZD1211B] + 5241 Cable Modem + 5551 DSL Modem + 9700 2986L FaxModem + 9800 Cable Modem + a312 Wireless-G +0809 Genicom Technology, Inc. +080a Evermuch Technology Co., Ltd +080b Cross Match Technologies + 0002 Fingerprint Scanner (After ReNumeration) + 0010 300LC Series Fingerprint Scanner (Before ReNumeration) +080c Datalogic S.p.A. + 0300 Gryphon D120 Barcode Scanner + 0400 Gryphon D120 Barcode Scanner + 0500 Gryphon D120 Barcode Scanner + 0600 Gryphon M100 Barcode Scanner +080d Teco Image Systems Co., Ltd + 0102 Hercules Scan@home 48 + 0104 3.2Slim + 0110 UMAX AstraSlim 1200 Scanner +0810 Personal Communication Systems, Inc. + 0001 Dual PSX Adaptor + 0002 Dual PCS Adaptor + 0003 PlayStation Gamepad + e001 Twin controller + e501 SNES Gamepad +0813 Mattel, Inc. + 0001 Intel Play QX3 Microscope + 0002 Dual Mode Camera Plus +0819 eLicenser + 0101 License Management and Copy Protection +081a MG Logic + 1000 Duo Pen Tablet +081b Indigita Corp. + 0600 Storage Adapter + 0601 Storage Adapter +081c Mipsys +081e AlphaSmart, Inc. + df00 Handheld +0822 Reudo Corp. + 2001 IRXpress Infrared Device +0825 GC Protronics +0826 Data Transit +0827 BroadLogic, Inc. +0828 Sato Corp. +0829 DirecTV Broadband, Inc. (Telocity) +082d Handspring + 0100 Visor + 0200 Treo + 0300 Treo 600 + 0400 Handheld + 0500 Handheld + 0600 Handheld +0830 Palm, Inc. + 0001 m500 + 0002 m505 + 0003 m515 + 0004 Handheld + 0005 Handheld + 0006 Handheld + 0010 Handheld + 0011 Handheld + 0012 Handheld + 0013 Handheld + 0014 Handheld + 0020 i705 + 0021 Handheld + 0022 Handheld + 0023 Handheld + 0024 Handheld + 0030 Handheld + 0031 Tungsten W + 0032 Handheld + 0033 Handheld + 0034 Handheld + 0040 m125 + 0041 Handheld + 0042 Handheld + 0043 Handheld + 0044 Handheld + 0050 m130 + 0051 Handheld + 0052 Handheld + 0053 Handheld + 0054 Handheld + 0060 Tungsten C/E/T/T2/T3 / Zire 71 + 0061 Lifedrive / Treo 650/680 / Tunsten E2/T5/TX / Centro / Zire 21/31/72 / Z22 + 0062 Handheld + 0063 Handheld + 0064 Handheld + 0070 Zire + 0071 Handheld + 0072 Handheld + 0080 Serial Adapter [for Palm III] + 0081 Handheld + 0082 Handheld + 00a0 Treo 800w + 0101 Pre +0832 Kouwell Electronics Corp. + 5850 Cable +0833 Sourcenext Corp. + 012e KeikaiDenwa 8 with charger + 039f KeikaiDenwa 8 +0835 Action Star Enterprise Co., Ltd +0836 TrekStor + 2836 i.Beat mood +0839 Samsung Techwin Co., Ltd + 0005 Digimax Camera + 0008 Digimax 230 Camera + 0009 Digimax 340 + 000a Digimax 410 + 000e Digimax 360 + 0010 Digimax 300 + 1003 Digimax 210SE + 1005 Digimax 220 + 1009 Digimax V4 + 1012 6500 Document Camera + 1058 S730 Camera + 1064 Digimax D830 Camera + 1542 Digimax 50 Duo + 3000 Digimax 35 MP3 +083a Accton Technology Corp. + 1046 10/100 Ethernet [pegasus] + 1060 HomeLine Adapter + 1f4d SMC8013WG Broadband Remote NDIS Device + 3046 10/100 Series Adapter + 3060 1/10/100 Adapter + 3501 2664W + 3502 WN3501D Wireless Adapter + 3503 T-Sinus 111 Wireless Adapter + 4501 T-Sinus 154data + 4502 Siemens S30853-S1016-R107 802.11g Wireless Adapter [Intersil ISL3886] + 4505 SMCWUSB-G 802.11bg + 4507 SMCWUSBT-G2 802.11g Wireless Adapter [Atheros AR5523] + 4521 Siemens S30863-S1016-R107-2 802.11g Wireless Adapter [Intersil ISL3887] + 4531 T-Com Sinus 154 data II [Intersil ISL3887] + 5046 SpeedStream 10/100 Ethernet [pegasus] + 5501 Wireless Adapter 11g + 6500 Cable Modem + 6618 802.11n Wireless Adapter + 7511 Arcadyan 802.11N Wireless Adapter + 7512 Arcadyan 802.11N Wireless Adapter + 7522 Arcadyan 802.11N Wireless Adapter + 8522 Arcadyan 802.11N Wireless Adapter + 8541 WN4501F 802.11g Wireless Adapter [Intersil ISL3887] + a512 Arcadyan 802.11N Wireless Adapter + a618 SMCWUSBS-N EZ Connect N Draft 11n Wireless Adapter [Ralink RT2870] + a701 SMCWUSBS-N3 EZ Connect N Wireless Adapter [Ralink RT3070] + b004 CPWUE001 USB/Ethernet Adapter + b522 SMCWUSBS-N2 EZ Connect N Wireless Adapter [Ralink RT2870] + bb01 BlueExpert Bluetooth Device + c003 802.11b Wireless Adapter + c501 Zoom 4410 Wireless-G [Intersil ISL3887] + c561 802.11a/g Wireless Adapter + d522 Speedport W 102 Stick IEEE 802.11n USB 2.0 Adapter + e501 ZD1211B + e503 Arcadyan WN4501 802.11b/g + e506 WUS-201 802.11bg + f501 802.11g Wireless Adapter + f502 802.11g Wireless Adapter + f522 Arcadyan WN7512 802.11n +083f Global Village + b100 TelePort V.90 Fax/Modem +0840 Argosy Research, Inc. + 0060 Storage Adapter Bridge Module +0841 Rioport.com, Inc. + 0001 Rio 500 +0844 Welland Industrial Co., Ltd +0846 NetGear, Inc. + 1001 EA101 10 Mbps 10BASE-T Ethernet [Kawasaki LSI KL5KLUSB101B] + 1002 Ethernet + 1020 FA101 Fast Ethernet USB 1.1 + 1040 FA120 Fast Ethernet USB 2.0 [Asix AX88172 / AX8817x] + 1100 Managed Switch M4100 series, M5300 series, M7100 series + 4110 MA111(v1) 802.11b Wireless [Intersil Prism 3.0] + 4200 WG121(v1) 54 Mbps Wireless [Intersil ISL3886] + 4210 WG121(v2) 54 Mbps Wireless [Intersil ISL3886] + 4220 WG111(v1) 54 Mbps Wireless [Intersil ISL3886] + 4230 MA111(v2) 802.11b Wireless [SIS SIS 162] + 4240 WG111(v1) rev 2 54 Mbps Wireless [Intersil ISL3887] + 4260 WG111v3 54 Mbps Wireless [realtek RTL8187B] + 4300 WG111U Double 108 Mbps Wireless [Atheros AR5004X / AR5005UX] + 4301 WG111U (no firmware) Double 108 Mbps Wireless [Atheros AR5004X / AR5005UX] + 5f00 WPN111 802.11g Wireless Adapter [Atheros AR5523] + 6a00 WG111v2 54 Mbps Wireless [RealTek RTL8187L] + 7100 WN121T RangeMax Next Wireless-N [Marvell TopDog] + 9000 WN111(v1) RangeMax Next Wireless [Marvell 88W8362+88W8060] + 9001 WN111(v2) RangeMax Next Wireless [Atheros AR9170+AR9101] + 9010 WNDA3100v1 802.11abgn [Atheros AR9170+AR9104] + 9011 WNDA3100v2 802.11abgn [Broadcom BCM4323] + 9012 WNDA4100 802.11abgn 3x3:3 [Ralink RT3573] + 9014 WNDA3100v3 802.11abgn 2x2:2 [MediaTek MT7632U] + 9018 WNDA3200 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] + 9020 WNA3100(v1) Wireless-N 300 [Broadcom BCM43231] + 9021 WNA3100M(v1) Wireless-N 300 [Realtek RTL8192CU] + 9030 WNA1100 Wireless-N 150 [Atheros AR9271] + 9040 WNA1000 Wireless-N 150 [Atheros AR9170+AR9101] + 9041 WNA1000M 802.11bgn [Realtek RTL8188CUS] + 9042 On Networks N150MA 802.11bgn [Realtek RTL8188CUS] + 9043 WNA1000Mv2 802.11bgn [Realtek RTL8188CUS?] + 9050 A6200 802.11a/b/g/n/ac Wireless Adapter [Broadcom BCM43526] + 9051 A6200v2 802.11a/b/g/n/ac (2x2) Wireless Adapter [Realtek RTL8812AU] + 9052 A6100 AC600 DB Wireless Adapter [Realtek RTL8811AU] + a001 PA101 10 Mbps HPNA Home Phoneline RJ-1 + f001 On Networks N300MA 802.11bgn [Realtek RTL8192CU] +084d Minton Optic Industry Co., Inc. + 0001 Jenoptik JD800i + 0003 S-Cam F5/D-Link DSC-350 Digital Camera + 0011 Argus DC3500 Digital Camera + 0014 Praktica DC 32 + 0019 Praktica DPix3000 + 0025 Praktica DC 60 + 1001 ScanHex SX-35d +084e KB Gear + 0001 JamCam Camera + 1001 Jam Studio Tablet + 1002 Pablo Tablet +084f Empeg + 0001 Empeg-Car Mark I/II Player +0850 Fast Point Technologies, Inc. +0851 Macronix International Co., Ltd + 1542 SiPix Blink + 1543 Maxell WS30 Slim Digital Camera, or Pandigital PI8004W01 digital photo frame + a168 MXIC +0852 CSEM +0853 Topre Corporation + 0100 HHKB Professional +0854 ActiveWire, Inc. + 0100 I/O Board + 0101 I/O Board, rev1 +0856 B&B Electronics + ac01 uLinks USOTL4 RS422/485 Adapter +0858 Hitachi Maxell, Ltd + 3102 Bluetooth Device + ffff Maxell module with BlueCore in DFU mode +0859 Minolta Systems Laboratory, Inc. +085a Xircom + 0001 Portstation Dual Serial Port + 0003 Portstation Paraller Port + 0008 Ethernet + 0009 Ethernet + 000b Portstation Dual PS/2 Port + 0021 1 port to Serial Converter + 0022 Parallel Port + 0023 2 port to Serial Converter + 0024 Parallel Port + 0026 PortGear SCSI + 0027 1 port to Serial Converter + 0028 PortGear to SCSI Converter + 0032 PortStation SCSI Module + 003c Bluetooth Adapter + 0299 Colorvision, Inc. Monitor Spyder + 8021 1 port to Serial + 8023 2 port to Serial + 8027 PGSDB9 Serial Port +085c ColorVision, Inc. + 0100 Spyder 1 + 0200 Spyder 2 + 0300 Spyder 3 + 0400 Spyder 4 +0862 Teletrol Systems, Inc. +0863 Filanet Corp. +0864 NetGear, Inc. + 4100 MA101 802.11b Adapter + 4102 MA101 802.11b Adapter +0867 Data Translation, Inc. + 9812 ECON Data acquisition unit + 9816 DT9816 ECON data acquisition module + 9836 DT9836 data acquisition card +086a Emagic Soft- und Hardware GmbH + 0001 Unitor8 + 0002 AMT8 + 0003 MT4 +086c DeTeWe - Deutsche Telephonwerke AG & Co. + 1001 Eumex 504PC ISDN TA + 1002 Eumex 504PC (FlashLoad) + 1003 TA33 ISDN TA + 1004 TA33 (FlashLoad) + 1005 Eumex 604PC HomeNet + 1006 Eumex 604PC HomeNet (FlashLoad) + 1007 Eumex 704PC DSL + 1008 Eumex 704PC DSL (FlashLoad) + 1009 Eumex 724PC DSL + 100a Eumex 724PC DSL (FlashLoad) + 100b OpenCom 30 + 100c OpenCom 30 (FlashLoad) + 100d BeeTel Home 100 + 100e BeeTel Home 100 (FlashLoad) + 1011 USB2DECT + 1012 USB2DECT (FlashLoad) + 1013 Eumex 704PC LAN + 1014 Eumex 704PC LAN (FlashLoad) + 1019 Eumex 504 SE + 101a Eumex 504 SE (Flash-Mode) + 1021 OpenCom 40 + 1022 OpenCom 40 (FlashLoad) + 1023 OpenCom 45 + 1024 OpenCom 45 (FlashLoad) + 1025 Sinus 61 data + 1029 dect BOX + 102c Eumex 604PC HomeNet [FlashLoad] + 1030 Eumex 704PC DSL [FlashLoad] + 1032 OpenCom 40 [FlashLoad] + 1033 OpenCom 30 plus + 1034 OpenCom 30 plus (FlashLoad) + 1041 Eumex 220PC + 1042 Eumex 220PC (FlashMode) + 1055 Eumex 220 Version 2 ISDN TA + 1056 Eumex 220 Version 2 ISDN TA (Flash-Mode) + 2000 OpenCom 1000 +086e System TALKS, Inc. + 1920 SGC-X2UL +086f MEC IMEX, Inc. +0870 Metricom + 0001 Ricochet GS +0871 SanDisk, Inc. + 0001 SDDR-01 Compact Flash Reader + 0002 SDDR-31 Compact Flash Reader + 0005 SDDR-05 Compact Flash Reader +0873 Xpeed, Inc. +0874 A-Tec Subsystem, Inc. +0879 Comtrol Corp. +087c Adesso/Kbtek America, Inc. +087d Jaton Corp. + 5704 Ethernet +087e Fujitsu Computer Products of America +087f QualCore Logic Inc. +0880 APT Technologies, Inc. +0883 Recording Industry Association of America (RIAA) +0885 Boca Research, Inc. +0886 XAC Automation Corp. + 0630 Intel PC Camera CS630 +0887 Hannstar Electronics Corp. +088a TechTools + 1002 DigiView DV3100 +088b MassWorks, Inc. + 4944 MassWorks ID-75 TouchScreen +088c Swecoin AB + 2030 Ticket Printer TTP 2030 +088e iLok + 5036 Portable secure storage for software licenses +0892 DioGraphy, Inc. + 0101 Smartdio Reader/Writer +0894 TSI Incorporated + 0010 Remote NDIS Network Device +0897 Lauterbach + 0001 ICE In-Circuit Emulator + 0002 Power Debug/Power Debug II + 0004 PowerDebug + 0005 PowerDebug PRO +089c United Technologies Research Cntr. +089d Icron Technologies Corp. +089e NST Co., Ltd +089f Primex Aerospace Co. +08a5 e9, Inc. +08a6 Toshiba TEC + 0051 B-SV4 +08a8 Andrea Electronics +08a9 CWAV Inc. + 0005 USBee ZX + 0009 USBee SX + 0012 USBee AX-Standard + 0013 USBee AX-Plus + 0014 USBee AX-Pro + 0015 USBee DX +08ac Macraigor Systems LLC + 2024 usbWiggler +08ae Macally (Mace Group, Inc.) +08b0 Metrohm + 0006 814 Sample Processor + 0015 857 Titrando + 001a 852 Titrando +08b4 Sorenson Vision, Inc. +08b7 NATSU + 0001 Playstation adapter +08b8 J. Gordon Electronic Design, Inc. + 01f4 USBSIMM1 +08b9 RadioShack Corp. (Tandy) +08bb Texas Instruments + 2702 PCM2702 16-bit stereo audio DAC + 2704 PCM2704 16-bit stereo audio DAC + 2705 PCM2705 stereo audio DAC + 2706 PCM2706 stereo audio DAC + 2707 PCM2707 stereo audio DAC + 27c4 PCM2704C stereo audio DAC + 27c5 PCM2705C stereo audio DAC + 27c6 PCM2706C stereo audio DAC + 27c7 PCM2707C stereo audio DAC + 2900 PCM2900 Audio Codec + 2901 PCM2901 Audio Codec + 2902 PCM2902 Audio Codec + 2904 PCM2904 Audio Codec + 2910 PCM2912 Audio Codec + 2912 PCM2912A Audio Codec + 29b0 PCM2900B Audio CODEC + 29b2 PCM2902 Audio CODEC + 29b3 PCM2903B Audio CODEC + 29b6 PCM2906B Audio CODEC + 29c0 PCM2900C Audio CODEC + 29c2 PCM2902C Audio CODEC + 29c3 PCM2903C Audio CODEC + 29c6 PCM2906C Audio CODEC +08bd Citizen Watch Co., Ltd + 0208 CLP-521 Label Printer + 1100 X1-USB Floppy +08c3 Precise Biometrics + 0001 100 SC + 0002 100 A + 0003 100 SC BioKeyboard + 0006 100 A BioKeyboard + 0100 100 MC ISP + 0101 100 MC FingerPrint and SmartCard Reader + 0300 100 AX + 0400 100 SC + 0401 150 MC + 0402 200 MC FingerPrint and SmartCard Reader + 0404 100 SC Upgrade + 0405 150 MC Upgrade + 0406 100 MC Upgrade +08c4 Proxim, Inc. + 0100 Skyline 802.11b Wireless Adapter + 02f2 Farallon Home Phoneline Adapter +08c7 Key Nice Enterprise Co., Ltd +08c8 2Wire, Inc. +08c9 Nippon Telegraph and Telephone Corp. +08ca Aiptek International, Inc. + 0001 Tablet + 0010 Tablet + 0020 APT-6000U Tablet + 0021 APT-2 Tablet + 0022 Tablet + 0023 Tablet + 0024 Tablet + 0100 Pen Drive + 0102 DualCam + 0103 Pocket DV Digital Camera + 0104 Pocket DVII + 0105 Mega DV(Disk) + 0106 Pocket DV3100+ + 0107 Pocket DV3100 + 0109 Nisis DV4 Digital Camera + 010a Trust 738AV LCD PV Mass Storage + 0111 PenCam VGA Plus + 2008 Mini PenCam 2 + 2010 Pocket CAM 3 Mega (webcam) + 2011 Pocket CAM 3 Mega (storage) + 2016 PocketCam 2 Mega + 2018 Pencam SD 2M + 2019 Pencam SD 2M (mass storage mode) + 2020 Slim 3000F + 2022 Slim 3200 + 2024 Pocket DV3500 + 2028 Pocket Cam4M + 2040 Pocket DV4100M + 2042 Pocket DV5100M Composite Device + 2043 Pocket DV5100M (Disk) + 2060 Pocket DV5300 +08cd Jue Hsun Ind. Corp. +08ce Long Well Electronics Corp. +08cf Productivity Enhancement Products +08d1 smartBridges, Inc. + 0001 smartNIC Ethernet [catc] + 0003 smartNIC 2 PnP Ethernet +08d3 Virtual Ink +08d4 Fujitsu Siemens Computers + 0009 SCR SmartCard Reader +08d8 IXXAT Automation GmbH + 0002 USB-to-CAN compact + 0003 USB-to-CAN II + 0100 USB-to-CAN +08d9 Increment P Corp. +08dd Billionton Systems, Inc. + 0112 Wireless LAN Adapter + 0113 Wireless LAN Adapter + 0986 USB-100N Ethernet [pegasus] + 0987 USBLP-100 HomePNA Ethernet [pegasus] + 0988 USBEL-100 Ethernet [pegasus] + 1986 10/100 LAN Adapter + 2103 DVB-T TV-Tuner Card-R + 8511 USBE-100 Ethernet [pegasus2] + 90ff USB2AR Ethernet +08de ??? + 7a01 802.11b Adapter +08df Spyrus, Inc. + 0001 Rosetta Token V1 + 0002 Rosetta Token V2 + 0003 Rosetta Token V3 + 0a00 Lynks Interface +08e3 Olitec, Inc. + 0002 USB-RS232 Bridge + 0100 Interface ADSL + 0101 Interface ADSL + 0102 ADSL + 0301 RNIS ISDN TA [HFC-S] +08e4 Pioneer Corp. + 0184 DDJ-WeGO + 0185 DDJ-WeGO2 +08e5 Litronic +08e6 Gemalto (was Gemplus) + 0001 GemPC-Touch 430 + 0430 GemPC430 SmartCard Reader + 0432 GemPC432 SmartCard Reader + 0435 GemPC435 SmartCard Reader + 0437 GemPC433 SL SmartCard Reader + 1359 UA SECURE STORAGE TOKEN + 2202 Gem e-Seal Pro Token + 3437 GemPC Twin SmartCard Reader + 3438 GemPC Key SmartCard Reader + 3478 PinPad Smart Card Reader + 34ec Compact Smart Card Reader Writer + 4433 GemPC433-Swap + 5501 GemProx-PU Contactless Smart Card Reader + 5503 Prox-DU Contactless Interface + ace0 UA HYBRID TOKEN +08e7 Pan-International Wire & Cable +08e8 Integrated Memory Logic +08e9 Extended Systems, Inc. + 0100 XTNDAccess IrDA Dongle +08ea Ericsson, Inc., Blue Ridge Labs + 00c9 ADSL Modem HM120dp Loader + 00ca ADSL WAN Modem HM120dp + 00ce HM230d Virtual Bus for Helium + abba USB Driver for Bluetooth Wireless Technology + abbb Bluetooth Device in DFU State +08ec M-Systems Flash Disk Pioneers + 0001 TravelDrive 2C + 0002 TravelDrive 2C + 0005 TravelDrive 2C + 0008 TravelDrive 2C + 0010 DiskOnKey + 0011 DiskOnKey + 0012 TravelDrive 2C + 0014 TravelDrive 2C + 0015 Kingston DataTraveler ELITE + 0016 Kingston DataTraveler U3 + 0020 TravelDrive Intuix U3 2GB + 0021 TravelDrive + 0022 TravelDrive + 0023 TravelDrive + 0024 TravelDrive + 0025 TravelDrive + 0026 TravelDrive + 0027 TravelDrive + 0028 TravelDrive + 0029 TravelDrive + 0030 TravelDrive + 0822 TravelDrive 2C + 0832 Hi-Speed Mass Storage Device + 0834 M-Disk 220 + 0998 Kingston Data Traveler2.0 Disk Driver + 0999 Kingston Data Traveler2.0 Disk Driver + 1000 TravelDrive 2C + 2000 TravelDrive 2C + 2038 TravelDrive + 2039 TravelDrive + 204a TravelDrive + 204b TravelDrive +08ed MediaTek Inc. + 0002 CECT M800 memory card +08ee CCSI/Hesso +08f0 Corex Technologies + 0005 CardScan 800c +08f1 CTI Electronics Corp. +08f2 Gotop Information Inc. + 007f Super Q2 Tablet +08f5 SysTec Co., Ltd +08f6 Logic 3 International, Ltd +08f7 Vernier + 0001 LabPro + 0002 EasyTemp/Go!Temp + 0003 Go!Link + 0004 Go!Motion +08f8 Keen Top International Enterprise Co., Ltd +08f9 Wipro Technologies +08fa Caere +08fb Socket Communications +08fc Sicon Cable Technology Co., Ltd +08fd Digianswer A/S + 0001 Bluetooth Device +08ff AuthenTec, Inc. + 1600 AES1600 + 1610 AES1600 + 1660 AES1660 Fingerprint Sensor + 1680 AES1660 Fingerprint Sensor + 168f AES1660 Fingerprint Sensor + 2500 AES2501 + 2501 AES2501 + 2502 AES2501 + 2503 AES2501 + 2504 AES2501 + 2505 AES2501 + 2506 AES2501 + 2507 AES2501 + 2508 AES2501 + 2509 AES2501 + 250a AES2501 + 250b AES2501 + 250c AES2501 + 250d AES2501 + 250e AES2501 + 250f AES2501 + 2510 AES2510 + 2550 AES2550 Fingerprint Sensor + 2580 AES2501 Fingerprint Sensor + 2588 AES2501 + 2589 AES2501 + 258a AES2501 + 258b AES2501 + 258c AES2501 + 258d AES2501 + 258e AES2501 + 258f AES2501 + 2660 AES2660 Fingerprint Sensor + 2680 AES2660 Fingerprint Sensor + 268f AES2660 Fingerprint Sensor + 2810 AES2810 + 3400 AES3400 TruePrint Sensor + 3401 AES3400 Sensor + 3402 AES3400 Sensor + 3403 AES3400 Sensor + 3404 AES3400 TruePrint Sensor + 3405 AES3400 TruePrint Sensor + 3406 AES3400 TruePrint Sensor + 3407 AES3400 TruePrint Sensor + 4902 BioMV with TruePrint AES3500 + 4903 BioMV with TruePrint AES3400 + 5500 AES4000 + 5501 AES4000 TruePrint Sensor + 5503 AES4000 TruePrint Sensor + 5505 AES4000 TruePrint Sensor + 5507 AES4000 TruePrint Sensor + 55ff AES4000 TruePrint Sensor. + 5700 AES3500 Fingerprint Reader + 5701 AES3500 TruePrint Sensor + 5702 AES3500 TruePrint Sensor + 5703 AES3500 TruePrint Sensor + 5704 AES3500-BZ TruePrint Sensor + 5705 AES3500-BZ TruePrint Sensor + 5706 AES3500-BZ TruePrint Sensor + 5707 AES3500-BZ TruePrint Sensor + 5710 AES3500 TruePrint Sensor + 5711 AES3500 TruePrint Sensor + 5712 AES3500 TruePrint Sensor + 5713 AES3500 TruePrint Sensor + 5714 AES3500-BZ TruePrint Sensor + 5715 AES3500-BZ TruePrint Sensor + 5716 AES3500-BZ TruePrint Sensor + 5717 AES3500-BZ TruePrint Sensor + 5730 AES3500 TruePrint Sensor + 5731 AES3500 TruePrint Sensor + 5732 AES3500 TruePrint Sensor + 5733 AES3500 TruePrint Sensor + 5734 AES3500-BZ TruePrint Sensor + 5735 AES3500-BZ TruePrint Sensor + 5736 AES3500-BZ TruePrint Sensor + 5737 AES3500-BZ TruePrint Sensor + afe3 FingerLoc Sensor Module (Anchor) + afe4 FingerLoc Sensor Module (Anchor) + afe5 FingerLoc Sensor Module (Anchor) + afe6 FingerLoc Sensor Module (Anchor) + fffd AES2510 Sensor (USB Emulator) + ffff Sensor (Emulator) +0900 Pinnacle Systems, Inc. +0901 VST Technologies + 0001 Hard Drive Adapter (TPP) + 0002 SigmaDrive Adapter (TPP) +0906 Faraday Technology Corp. +0908 Siemens AG + 01f4 SIMATIC NET CP 5711 + 01fe SIMATIC NET PC Adapter A2 + 04b1 MediSET + 04b2 NC interface + 04b3 keyboard front panel Cockpit + 04b4 SCR_CCID + 2701 ShenZhen SANZHAI Technology Co.,Ltd Spy Pen VGA +0909 Audio-Technica Corp. +090a Trumpion Microelectronics, Inc. + 1001 T33520 Flash Card Controller + 1100 Comotron C3310 MP3 player + 1200 MP3 player + 1540 Digitex Container Flash Disk +090b Neurosmith +090c Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.) + 0371 Silicon Motion SM371 Camera + 0373 Silicon Motion Camera + 037a Silicon Motion Camera + 037b Silicon Motion Camera + 037c 300k Pixel Camera + 1000 Flash Drive + 1132 5-in-1 Card Reader + 337b Silicon Motion Camera + 3710 Silicon Motion Camera + 3720 Silicon Motion Camera + 37bc HP Webcam-101 Integrated Camera + 37c0 Silicon Motion Camera + 6000 SD/SDHC Card Reader (SG365 / FlexiDrive XC+) + 6200 microSD card reader + 71b3 SM731 Camera + 837b Silicon Motion Camera + 937b Silicon Motion Camera + b370 Silicon Motion SM370 Camera + b371 Silicon Motion SM371 Camera + f37d Endoscope camera +090d Multiport Computer Vertriebs GmbH +090e Shining Technology, Inc. +090f Fujitsu Devices, Inc. +0910 Alation Systems, Inc. +0911 Philips Speech Processing + 149a SpeechMike II Pro Plus LFH5276 + 2512 SpeechMike Pro +0912 Voquette, Inc. +0915 GlobeSpan, Inc. + 0001 DSL Modem + 0002 ADSL ATM Modem + 0005 LAN Modem + 2000 802.11 Adapter + 2002 802.11 Adapter + 8000 ADSL LAN Modem + 8005 DSL-302G Modem + 8101 ADSL WAN Modem + 8102 DSL-200 ADSL Modem + 8103 DSL-200 ADSL Modem + 8104 DSL-200 Modem + 8400 DSL Modem + 8401 DSL Modem + 8402 DSL Modem + 8500 DSL Modem + 8501 DSL Modem +0917 SmartDisk Corp. + 0001 eFilm Reader-11 SM/CF + 0002 eFilm Reader-11 SM + 0003 eFilm Reader-11 CF + 0200 FireFly + 0201 FireLite + 0202 STORAGE ADAPTER (FirePower) + 0204 FlashTrax Storage + 0205 STORAGE ADAPTER (CrossFire) + 0206 FireFly 20G HDD + 0207 FireLite + 020f STORAGE ADAPTER (FireLite) + da01 eFilm Reader-11 Test + ffff eFilm Reader-11 (Class/PDR) +0919 Tiger Electronics + 0100 Fast Flicks Digital Camera +091e Garmin International + 0003 GPS (various models) + 0004 iQue 3600 + 0200 Data Card Programmer (install) + 086e Forerunner 735XT + 097f Forerunner 235 + 1200 Data Card Programmer + 21a5 etrex Cx (msc) + 2236 nuvi 360 + 2271 Edge 605/705 + 2295 Colorado 300 + 22b6 eTrex Vista HCx (Mass Storage mode) + 231b Oregon 400t + 2353 Nüvi 205T + 2380 Oregon series + 23cc nüvi 1350 + 2459 GPSmap 62/78 series + 2491 Edge 800 + 2519 eTrex 30 + 2535 Edge 800 + 253c GPSmap 62sc + 255b Nuvi 2505LM + 26a1 Nuvi 55 + 47fb nuviCam +0920 Echelon Co. + 7500 Network Interface +0921 GoHubs, Inc. + 1001 GoCOM232 Serial +0922 Dymo-CoStar Corp. + 0007 LabelWriter 330 + 0009 LabelWriter 310 + 0019 LabelWriter 400 + 001a LabelWriter 400 Turbo + 0020 LabelWriter 450 + 1001 LabelManager PnP + 8004 M25 Digital Postal Scale +0923 IC Media Corp. + 010f SIIG MobileCam +0924 Xerox + 23dd DocuPrint M760 (X760_USB) + 3ce8 Phaser 3428 Printer + 3cea Phaser 3125 + 3cec Phaser 3250 + 3d5b Phaser 6115MFP TWAIN Scanner + 3d6d WorkCentre 6015N/NI + 420f WorkCentre PE220 Series + 421f M20 Scanner + 423b Printing Support + 4274 Xerox Phaser 3635MFPX + ffef WorkCenter M15 + fffb DocuPrint M750 (X750_USB) +0925 Lakeview Research + 0005 Gamtec.,Ltd SmartJoy PLUS Adapter + 03e8 Wii Classic Controller Adapter + 3881 Saleae Logic + 8101 Phidgets, Inc., 1-Motor PhidgetServo v2.0 + 8104 Phidgets, Inc., 4-Motor PhidgetServo v2.0 + 8800 WiseGroup Ltd, MP-8800 Quad Joypad + 8866 WiseGroup Ltd, MP-8866 Dual Joypad +0927 Summus, Ltd +0928 PLX Technology, Inc. (formerly Oxford Semiconductor, Ltd) + 8000 Firmware uploader + ffff Blank Oxford Device +0929 American Biometric Co. +092a Toshiba Information & Industrial Sys. And Services +092b Sena Technologies, Inc. +092f Northern Embedded Science/CAVNEX + 0004 JTAG-4 + 0005 JTAG-5 +0930 Toshiba Corp. + 0009 Gigabeat F/X (HDD audio player) + 000c Gigabeat F (mtp) + 0010 Gigabeat S (mtp) + 01bf 2.5"External Hard Disk + 0200 Integrated Bluetooth (Taiyo Yuden) + 021c Atheros AR3012 Bluetooth + 0301 PCX1100U Cable Modem (WDM) + 0302 PCX2000 Cable Modem (WDM) + 0305 Cable Modem PCX3000 + 0307 Cable Modem PCX2500 + 0308 PCX2200 Cable Modem (WDM) + 0309 PCX5000 Cable Modem (WDM) + 030b Cable Modem PCX2600 + 0501 Bluetooth Controller + 0502 Integrated Bluetooth + 0503 Bluetooth Controller + 0505 Integrated Bluetooth + 0506 Integrated Bluetooth + 0507 Bluetooth Adapter + 0508 Integrated Bluetooth HCI + 0509 BT EDR Dongle + 0706 PocketPC e740 + 0707 Pocket PC e330 Series + 0708 Pocket PC e350 Series + 0709 Pocket PC e750 Series + 070a Pocket PC e400 Series + 070b Pocket PC e800 Series + 0a07 WLM-10U1 802.11abgn Wireless Adapter [Ralink RT3572] + 0a08 WLM-20U2/GN-1080 802.11abgn Wireless Adapter [Atheros AR7010+AR9280] + 0a0b WLU5053 802.11abgn Wireless Module [Broadcom BCM43236B] + 0a13 AX88179 Gigabit Ethernet [Toshiba] + 0b05 PX1220E-1G25 External hard drive + 0b09 PX1396E-3T01 External hard drive + 0b1a STOR.E ALU 2S + 1300 Wireless Broadband (CDMA EV-DO) SM-Bus Minicard Status Port + 1301 Wireless Broadband (CDMA EV-DO) Minicard Status Port + 1302 Wireless Broadband (3G HSDPA) SM-Bus Minicard Status Port + 1303 Wireless Broadband (3G HSDPA) Minicard Status Port + 1308 Broadband (3G HSDPA) SM-Bus Minicard Diagnostics Port + 130b F3507g Mobile Broadband Module + 130c F3607gw Mobile Broadband Module + 1311 F3607gw v2 Mobile Broadband Module + 1400 Memory Stick 2GB + 642f TravelDrive + 6506 TravelDrive 2C + 6507 TravelDrive 2C + 6508 TravelDrive 2C + 6509 TravelDrive 2C + 6510 TravelDrive 2C + 6517 TravelDrive 2C + 6518 TravelDrive 2C + 6519 Kingston DataTraveler 2.0 USB Stick + 651a TravelDrive 2C + 651b TravelDrive 2C + 651c TravelDrive 2C + 651d TravelDrive 2C + 651e TravelDrive 2C + 651f TravelDrive 2C + 6520 TravelDrive 2C + 6521 TravelDrive 2C + 6522 TravelDrive 2C + 6523 TravelDrive + 6524 TravelDrive + 6525 TravelDrive + 6526 TravelDrive + 6527 TravelDrive + 6528 TravelDrive + 6529 TravelDrive + 652a TravelDrive + 652b TravelDrive + 652c TravelDrive + 652d TravelDrive + 652f TravelDrive + 6530 TravelDrive + 6531 TravelDrive + 6532 256M Stick + 6533 512M Stick + 6534 TravelDrive + 653c Kingston DataTraveler 2.0 Stick (512M) + 653d Kingston DataTraveler 2.0 Stick (1GB) + 653e Flash Memory + 6540 TransMemory Flash Memory + 6544 TransMemory-Mini / Kingston DataTraveler 2.0 Stick + 6545 Kingston DataTraveler 102/2.0 / HEMA Flash Drive 2 GB / PNY Attache 4GB Stick +0931 Harmonic Data Systems, Ltd +0932 Crescentec Corp. + 0300 VideoAdvantage + 0302 Syntek DC-112X + 0320 VideoAdvantage + 0482 USB2.0 TVBOX + 1100 DC-1100 Video Enhamcement Device + 1112 Veo Web Camera + a311 Video Enhancement Device +0933 Quantum Corp. +0934 Spirent Communications +0936 NuTesla + 000a Moebius + 000b iMoebius + 000c Rhythmedics 6 BioData Integrator + 000d Hypurius + 000e Millennius + 000f Purius + 0030 Composite Device, Mass Storage Device (Flash Drive) amd HID + 003c Rhythmedics HID Bootloader +0939 Lumberg, Inc. + 0b15 Toshiba Stor.E Alu 2 +093a Pixart Imaging, Inc. + 0007 CMOS 100K-R Rev. 1.90 + 010e Digital camera, CD302N/Elta Medi@ digi-cam/HE-501A + 010f Argus DC-1610/DC-1620/Emprex PCD3600/Philips P44417B keychain camera/Precision Mini,Model HA513A/Vivitar Vivicam 55 + 020f Bullet Line Photo Viewer + 050f Mars-Semi Pc-Camera + 2460 Q-TEC WEBCAM 100 + 2468 SoC PC-Camera + 2470 SoC PC-Camera + 2471 SoC PC-Camera + 2500 USB Optical Mouse + 2510 Optical Mouse + 2521 Optical Mouse + 2600 Typhoon Easycam USB 330K (newer)/Typhoon Easycam USB 2.0 VGA 1.3M/Sansun SN-508 + 2601 SPC 610NC Laptop Camera + 2603 PAC7312 Camera + 2608 PAC7311 Trust WB-3300p + 260e PAC7311 Gigaware VGA PC Camera:Trust WB-3350p:SIGMA cam 2350 + 260f PAC7311 SnakeCam + 2621 PAC731x Trust Webcam + 2622 Webcam Genius + 2624 Webcam +093b Plextor Corp. + 0010 Storage Adapter + 0011 PlexWriter 40/12/40U + 0041 PX-708A DVD RW + 0042 PX-712UF DVD RW + a002 ConvertX M402U XLOADER + a003 ConvertX AV100U A/V Capture Audio + a004 ConvertX TV402U XLOADER + a005 ConvertX TV100U A/V Capture + a102 ConvertX M402U A/V Capture + a104 ConvertX PX-TV402U/NA +093c Intrepid Control Systems, Inc. + 0601 ValueCAN + 0701 NeoVI Blue vehicle bus interface +093d InnoSync, Inc. +093e J.S.T. Mfg. Co., Ltd +093f Olympia Telecom Vertriebs GmbH +0940 Japan Storage Battery Co., Ltd +0941 Photobit Corp. +0942 i2Go.com, LLC +0943 HCL Technologies India Private, Ltd +0944 KORG, Inc. + 0001 PXR4 4-Track Digital Recorder + 0020 KAOSS Pad KP3 Dynamic Effect/Sampler + 0023 KAOSSILATOR PRO Dynamic Phrase Synthesizer + 010d nanoKEY MIDI keyboard + 010e nanoPAD pad controller + 010f nanoKONTROL studio controller + 0117 nanoKONTROL2 MIDI Controller + 0f03 K-Series K61P MIDI studio controller +0945 Pasco Scientific +0948 Kronauer music in digital + 0301 USB Pro (24/48) + 0302 USB Pro (24/96 playback) + 0303 USB Pro (24/96 record) + 0304 USB Pro (16/48) + 1105 USB One +094b Linkup Systems Corp. + 0001 neonode N2 +094d Cable Television Laboratories +094f Yano + 0101 U640MO-03 + 05fc METALWEAR-HDD +0951 Kingston Technology + 0008 Ethernet + 000a KNU101TX 100baseTX Ethernet + 1600 DataTraveler II Pen Drive + 1601 DataTraveler II+ Pen Drive + 1602 DataTraveler Mini + 1603 DataTraveler 1GB/2GB Pen Drive + 1606 Eee PC 701 SD Card Reader [ENE UB6225] + 1607 DataTraveler 100 + 160b DataTraveler 2.0 (2GB) + 160d DataTraveler Vault Privacy + 160e DT110P/1GB Capless + 1613 DataTraveler DT101C Flash Drive + 1616 DataTraveler Locker 4GB + 161a Dell HyperVisor internal flash drive + 1621 DataTraveler 150 (32GB) + 1624 DataTraveler G2 + 1625 DataTraveler 101 II + 162a DataTraveler 112 4GB Pen Drive + 162b DataTraveler HyperX 3.0 + 162d DataTraveler 102 + 1630 DataTraveler 200 (32GB) + 1642 DT101 G2 + 1643 DataTraveler G3 + 1653 Data Traveler 100 G2 8 GiB + 1656 DataTraveler Ultimate G2 + 1660 Data Traveller 108 + 1665 Digital DataTraveler SE9 64GB + 1666 DataTraveler 100 G3/G4/SE9 G2 + 1689 DataTraveler SE9 + 168a DataTraveler Micro + 168c DT Elite 3.0 + 16b3 HyperX Savage +0954 RPM Systems Corp. +0955 NVIDIA Corp. + 7018 T186 [Tegra Parker] + 701a U-Boot running on Tegra + 7020 L4T (Linux for Tegra) running on Tegra + 7030 T30 [Tegra 3] recovery mode + 7100 Tegra Device + 7140 T124 [Tegra K1/Logan 32-bit] + 7210 SHIELD Controller + 7721 T210 [Tegra Erista] + 7820 T20 [Tegra 2] recovery mode + b400 SHIELD (debug) + b401 SHIELD + cf05 SHIELD Tablet (debug) + cf06 SHIELD Tablet + cf07 SHIELD Tablet + cf08 SHIELD Tablet + cf09 SHIELD Tablet +0956 BSquare Corp. +0957 Agilent Technologies, Inc. + 0200 E-Video DC-350 Camera + 0202 E-Video DC-350 Camera + 0407 33220A Waveform Generator + 0518 82357B GPIB Interface + 0a07 34411A Multimeter + 1507 33210A Waveform Generator + 1745 Test and Measurement Device (IVI) + 2918 U2702A oscilloscope + fb18 LC Device +0958 CompuLink Research, Inc. +0959 Cologne Chip AG + 2bd0 Intelligent ISDN (Ver. 3.60.04) [HFC-S] +095a Portsmith + 3003 Express Ethernet +095b Medialogic Corp. +095c K-Tec Electronics +095d Polycom, Inc. + 0001 Polycom ViaVideo +0964 BITRAN +0967 Acer NeWeb Corp. + 0204 WarpLink 802.11b Adapter +0968 Catalyst Enterprises, Inc. +096e Feitian Technologies, Inc. + 0005 ePass2000 + 0120 Microcosm Ltd Dinkey + 0305 ePass2000Auto + 0309 ePass3000GM + 0401 ePass3000 + 0702 ePass3003 + 0703 ePass3003Auto + 0802 ePass2000 (G&D STARCOS SPK 2.4) + 0807 ePass2003 +0971 Gretag-Macbeth AG + 2000 i1 Pro + 2001 i1 Monitor + 2003 Eye-One display + 2005 Huey + 2007 ColorMunki Photo +0973 Schlumberger + 0001 e-gate Smart Card +0974 Datagraphix, a business unit of Anacomp +0975 OL'E Communications, Inc. +0976 Adirondack Wire & Cable +0977 Lightsurf Technologies +0978 Beckhoff GmbH +0979 Jeilin Technology Corp., Ltd + 0222 Keychain Display + 0224 JL2005A Toy Camera + 0226 JL2005A Toy Camera + 0227 JL2005B/C/D Toy Camera +097a Minds At Work LLC + 0001 Digital Wallet +097b Knudsen Engineering, Ltd +097c Marunix Co., Ltd +097d Rosun Technologies, Inc. +097e Biopac Systems Inc. + 0035 MP35 v1.0 +097f Barun Electronics Co., Ltd +0981 Oak Technology, Ltd +0984 Apricorn + 0040 SATA Wire (2.5") + 0200 Hard Drive Storage (TPP) +0985 cab Produkttechnik GmbH & Co KG + 0045 Mach4/200 Label Printer + 00a3 A3/200 or A3/300 Label Printer +0986 Matsushita Electric Works, Ltd. +098c Vitana Corp. +098d INDesign +098e Integrated Intellectual Property, Inc. +098f Kenwood TMI Corp. +0993 Gemstar eBook Group, Ltd + 0001 REB1100 eBook Reader + 0002 eBook +0996 Integrated Telecom Express, Inc. +099a Zippy Technology Corp. + 0638 Sanwa Supply Inc. Small Keyboard + 610c EL-610 Super Mini Electron luminescent Keyboard + 713a WK-713 Multimedia Keyboard + 7160 Hyper Slim Keyboard +099e Trimble Navigation, Ltd +09a3 PairGain Technologies +09a4 Contech Research, Inc. +09a5 VCON Telecommunications +09a6 Poinchips + 8001 Mass Storage Device +09a7 Data Transmission Network Corp. +09a8 Lin Shiung Enterprise Co., Ltd +09a9 Smart Card Technologies Co., Ltd +09aa Intersil Corp. + 1000 Prism GT 802.11b/g Adapter + 3642 Prism 2.x 802.11b Adapter +09ab Japan Cash Machine Co., Ltd. +09ae Tripp Lite +09b2 Franklin Electronic Publishers, Inc. + 0001 eBookman Palm Computer +09b3 Altius Solutions, Inc. +09b4 MDS Telephone Systems +09b5 Celltrix Technology Co., Ltd +09bc Grundig + 0002 MPaxx MP150 MP3 Player +09be MySmart.Com + 0001 MySmartPad +09bf Auerswald GmbH & Co. KG + 00c0 COMpact 2104 ISDN PBX + 00db COMpact 4410/2206 ISDN + 00dc COMpact 4406 DSL (PBX) + 00dd COMpact 2204 (PBX) + 00de COMpact 2104 (Rev.2 PBX) + 00e0 COMmander Business (PBX) + 00e2 COMmander Basic.2 (PBX) + 00f1 COMfort 2000 (System telephone) + 00f2 COMfort 1200 (System telephone) + 00f5 COMfortel 2500 (System telephone) + 8000 COMpact 2104 DSL (DSL modem) + 8001 COMpact 4406 DSL (DSL modem) + 8002 Analog/ISDN Converter (Line converter) + 8005 WG-640 (Automatic event dialer) +09c0 Genpix Electronics, LLC + 0136 Axon CNS, MultiClamp 700B + 0202 8PSK DVB-S tuner + 0203 Skywalker-1 DVB-S tuner + 0204 Skywalker-CW3K DVB-S tuner + 0205 Skywalker-CW3K DVB-S tuner + 0206 Skywalker-2 DVB-S tuner +09c1 Arris Interactive LLC + 1337 TOUCHSTONE DEVICE +09c2 Nisca Corp. +09c3 ActivCard, Inc. + 0007 Reader V2 + 0008 ZFG-9800-AC SmartCard Reader + 0014 ActivIdentity ActivKey SIM USB Token +09c4 ACTiSYS Corp. + 0011 ACT-IR2000U IrDA Dongle +09c5 Memory Corp. +09ca BMC Messsysteme GmbH + 5544 PIO +09cb FLIR Systems + 1001 Network Adapter + 1002 Ex-Series RNDIS interface + 1004 Ex-Series UVC interface + 1005 Ex-Series RNDIS and UVC interface + 1006 Ex-Series RNDIS and MSD interface + 1007 Ex-Series UVC and MSD interface + 1008 Serial Port + 1996 FLIR ONE Camera +09cc Workbit Corp. + 0404 BAFO USB-ATA/ATAPI Bridge Controller +09cd Psion Dacom Home Networks, Ltd + 2001 Psion WaveFinder DAB radio receiver +09ce City Electronics, Ltd +09cf Electronics Testing Center, Taiwan +09d1 NeoMagic, Inc. +09d2 Vreelin Engineering, Inc. +09d3 Com One + 0001 ISDN TA / Light Rider 128K + 000b Bluetooth Adapter class 1 [BlueLight] +09d7 NovAtel Inc. + 0100 NovAtel FlexPack GPS receiver +09d8 ELATEC + 0406 TWN4 MIFARE NFC +09d9 KRF Tech, Ltd +09da A4Tech Co., Ltd. + 0006 Optical Mouse WOP-35 / Trust 450L Optical Mouse + 000a Optical Mouse Opto 510D / OP-620D + 000e X-F710F Optical Mouse 3xFire Gaming Mouse + 0018 Trust Human Interface Device + 001a Wireless Mouse & RXM-15 Receiver + 002a Wireless Optical Mouse NB-30 + 022b Wireless Mouse (Battery Free) + 024f RF Receiver and G6-20D Wireless Optical Mouse + 0260 KV-300H Isolation Keyboard + 032b Wireless Mouse (Battery Free) + 1068 Bloody A90 Mouse + 8090 X-718BK Oscar Optical Gaming Mouse + 9033 X-718BK Optical Mouse + 9066 F3 V-Track Gaming Mouse + 9090 XL-730K / XL-750BK / XL-755BK Mice +09db Measurement Computing Corp. + 0075 MiniLab 1008 + 0076 PMD-1024 + 007a PMD-1208LS + 0081 USB-1616FS + 0082 USB-1208FS + 0088 USB-1616FS internal hub +09dc Aimex Corp. +09dd Fellowes, Inc. +09df Addonics Technologies Corp. +09e1 Intellon Corp. + 5121 MicroLink dLAN +09e5 Jo-Dan International, Inc. +09e6 Silutia, Inc. +09e7 Real 3D, Inc. +09e8 AKAI Professional M.I. Corp. + 0062 MPD16 MIDI Pad Controller Unit + 006d EWI electronic wind instrument + 0071 MPK25 MIDI Keyboard + 0076 LPK25 MIDI Keyboard +09e9 Chen-Source, Inc. +09eb IM Networks, Inc. + 4331 iRhythm Tuner Remote +09ef Xitel + 0101 MD-Port DG2 MiniDisc Interface +09f3 GoFlight, Inc. + 0018 GF-46 Multi-Mode Display Module + 0028 RP-48 Combination Pushbutton-Rotary Module + 0048 LGTII - Landing Gear and Trim Control Module + 0064 MCPPro - Airliner Mode Control Panel (Autopilot) + 0300 EFIS - Electronic Flight Information System +09f5 AresCom + 0168 Network Adapter + 0188 LAN Adapter + 0850 Adapter +09f6 RocketChips, Inc. +09f7 Edu-Science (H.K.), Ltd +09f8 SoftConnex Technologies, Inc. +09f9 Bay Associates +09fa Mtek Vision +09fb Altera + 6001 Blaster +09ff Gain Technology Corp. +0a00 Liquid Audio +0a01 ViA, Inc. +0a05 Unknown Manufacturer + 0001 Hub + 7211 hub +0a07 Ontrak Control Systems Inc. + 0064 ADU100 Data Acquisition Interface + 0078 ADU120 Data Acquisition Interface + 0082 ADU130 Data Acquisition Interface + 00c8 ADU200 Relay I/O Interface + 00d0 ADU208 Relay I/O Interface + 00da ADU218 Solid-State Relay I/O Interface +0a0b Cybex Computer Products Co. +0a0d Servergy, Inc + 2514 CTS-1000 Internal Hub +0a11 Xentec, Inc. +0a12 Cambridge Silicon Radio, Ltd + 0001 Bluetooth Dongle (HCI mode) + 0002 Frontline Test Equipment Bluetooth Device + 0003 Nanosira + 0004 Nanosira WHQL Reference Radio + 0005 Nanosira-Multimedia + 0006 Nanosira-Multimedia WHQL Reference Radio + 0007 Nanosira3-ROM + 0008 Nanosira3-ROM + 0009 Nanosira4-EDR WHQL Reference Radio + 000a Nanosira4-EDR-ROM + 000b Nanosira5-ROM + 0042 SPI Converter + 0043 Bluetooth Device + 0100 Casira with BlueCore2-External Module + 0101 Casira with BlueCore2-Flash Module + 0102 Casira with BlueCore3-Multimedia Module + 0103 Casira with BlueCore3-Flash Module + 0104 Casira with BlueCore4-External Module + 0105 Casira with BlueCore4-Multimedia Module + 1000 Bluetooth Dongle (HID proxy mode) + 1010 Bluetooth Device + 1011 Bluetooth Device + 1012 Bluetooth Device + ffff USB Bluetooth Device in DFU State +0a13 Telebyte, Inc. +0a14 Spacelabs Medical, Inc. +0a15 Scalar Corp. +0a16 Trek Technology (S) PTE, Ltd + 1111 ThumbDrive + 8888 IBM USB Memory Key + 9988 Trek2000 TD-G2 +0a17 Pentax Corp. + 0004 Optio 330 + 0006 Optio S / S4 + 0007 Optio 550 + 0009 Optio 33WR + 000a Optio 555 + 000c Optio 43WR (mass storage mode) + 000d Optio 43WR + 0015 Optio S40/S5i + 003b Optio 50 (mass storage mode) + 003d Optio S55 + 0041 Optio S5z + 0043 *ist DL + 0047 Optio S60 + 0052 Optio 60 Digital Camera + 006e K10D + 0070 K100D + 0093 K200D + 00a7 Optio E50 + 1001 EI2000 Camera powered by Digita! +0a18 Heidelberger Druckmaschinen AG +0a19 Hua Geng Technologies, Inc. +0a21 Medtronic Physio Control Corp. + 8001 MMT-7305WW [Medtronic Minimed CareLink] +0a22 Century Semiconductor USA, Inc. +0a27 Datacard Group + 0102 SP35 +0a2c AK-Modul-Bus Computer GmbH + 0008 GPIO Ports +0a34 TG3 Electronics, Inc. + 0101 TG82tp + 0110 Deck 82-key backlit keyboard +0a35 Radikal Technologies + 002a SAC - Software Assigned Controller + 008a SAC Hub +0a39 Gilat Satellite Networks, Ltd +0a3a PentaMedia Co., Ltd + 0163 KN-W510U 1.0 Wireless LAN Adapter +0a3c NTT DoCoMo, Inc. +0a3d Varo Vision +0a3f Swissonic AG +0a43 Boca Systems, Inc. +0a46 Davicom Semiconductor, Inc. + 0268 ST268 + 6688 ZT6688 Fast Ethernet Adapter + 8515 ADMtek ADM8515 NIC + 9000 DM9000E Fast Ethernet Adapter + 9601 DM9601 Fast Ethernet Adapter +0a47 Hirose Electric +0a48 I/O Interconnect + 3233 Multimedia Card Reader + 3239 Multimedia Card Reader + 3258 Dane Elec zMate SD Reader + 3259 Dane Elec zMate CF Reader + 5000 MediaGear xD-SM + 500a Mass Storage Device + 500f Mass Storage Device + 5010 Mass Storage Device + 5011 Mass Storage Device + 5014 Mass Storage Device + 5020 Mass Storage Device + 5021 Mass Storage Device + 5022 Mass Storage Device + 5023 Mass Storage Device + 5024 Mass Storage Device + 5025 Mass Storage Device +0a4a Ploytec GmbH +0a4b Fujitsu Media Devices, Ltd +0a4c Computex Co., Ltd + 15d9 OPTICAL MOUSE +0a4d Evolution Electronics, Ltd + 0064 MK-225 Driver + 0065 MK-225C Driver + 0066 MK-225C Driver + 0067 MK-425C Driver + 0078 MK-37 Driver + 0079 MK-37C Driver + 007a MK-37C Driver + 008c TerraTec MIDI MASTER + 008d MK-249C Driver + 008e MK-249C MIDI Keyboard + 008f MK-449C Driver + 0090 Keystation 49e Driver + 0091 Keystation 61es Driver + 00a0 MK-361 Driver + 00a1 MK-361C Driver + 00a2 MK-361C Driver + 00a3 MK-461C MIDI Keyboard + 00b5 Keystation Pro 88 Driver + 00d2 E-Keys Driver + 00f0 UC-16 Driver + 00f1 X-Session Driver + 00f5 UC-33e MIDI Controller +0a4e Steinberg Soft-und Hardware GmbH +0a4f Litton Systems, Inc. +0a50 Mimaki Engineering Co., Ltd +0a51 Sony Electronics, Inc. +0a52 Jebsee Electronics Co., Ltd +0a53 Portable Peripheral Co., Ltd + 1000 Scanner + 2000 Q-Scan A6 Scanner + 2001 Q-Scan A6 Scanner + 2013 Media Drive A6 Scanner + 2014 Media Drive A6 Scanner + 2015 BizCardReader 600C + 2016 BizCardReader 600C + 202a Scanshell-CSSN + 3000 Q-Scan A8 Scanner + 3002 Q-Scan A8 Reader + 3015 BizCardReader 300G + 302a LM9832 - PA570 Mini Business Card Scanner [Targus] + 5001 BizCardReader 900C +0a5a Electronics For Imaging, Inc. +0a5b EAsics NV +0a5c Broadcom Corp. + 0201 iLine10(tm) Network Adapter + 2000 Bluetooth Device + 2001 Bluetooth Device + 2009 BCM2035 Bluetooth + 200a BCM2035 Bluetooth dongle + 200f Bluetooth Controller + 201d Bluetooth Device + 201e IBM Integrated Bluetooth IV + 2020 Bluetooth dongle + 2021 BCM2035B3 Bluetooth Adapter + 2033 BCM2033 Bluetooth + 2035 BCM2035 Bluetooth + 2038 Blutonium Device + 2039 BCM2045 Bluetooth + 2045 Bluetooth Controller + 2046 Bluetooth Device + 2047 Bluetooth Device + 205e Bluetooth Device + 2100 Bluetooth 2.0+eDR dongle + 2101 BCM2045 Bluetooth + 2102 ANYCOM Blue USB-200/250 + 2110 BCM2045B (BDC-2) [Bluetooth Controller] + 2111 ANYCOM Blue USB-UHE 200/250 + 2120 2045 Bluetooth 2.0 USB-UHE Device with trace filter + 2121 BCM2210 Bluetooth + 2122 Bluetooth 2.0+EDR dongle + 2123 Bluetooth dongle + 2130 2045 Bluetooth 2.0 USB-UHE Device with trace filter + 2131 2045 Bluetooth 2.0 Device with trace filter + 2145 BCM2045B (BDC-2.1) [Bluetooth Controller] + 2148 BCM92046DG-CL1ROM Bluetooth 2.1 Adapter + 2150 BCM2046 Bluetooth Device + 2151 Bluetooth + 2154 BCM92046DG-CL1ROM Bluetooth 2.1 UHE Dongle + 216a BCM43142A0 Bluetooth + 216c BCM43142A0 Bluetooth Device + 216d BCM43142A0 Bluetooth 4.0 + 216f BCM20702A0 Bluetooth + 217d HP Bluethunder + 217f BCM2045B (BDC-2.1) + 2198 Bluetooth 3.0 Device + 219b Bluetooth 2.1 Device + 21b1 HP Bluetooth Module + 21b4 BCM2070 Bluetooth 2.1 + EDR + 21b9 BCM2070 Bluetooth 2.1 + EDR + 21ba BCM2070 Bluetooth 2.1 + EDR + 21bb BCM2070 Bluetooth 2.1 + EDR + 21bc BCM2070 Bluetooth 2.1 + EDR + 21bd BCM2070 Bluetooth 2.1 + EDR + 21d7 BCM43142 Bluetooth 4.0 + 21e1 HP Portable SoftSailing + 21e3 HP Portable Valentine + 21e6 BCM20702 Bluetooth 4.0 [ThinkPad] + 21e8 BCM20702A0 Bluetooth 4.0 + 21f1 HP Portable Bumble Bee + 22be BCM2070 Bluetooth 3.0 + HS + 4500 BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth) + 4502 Keyboard (Boot Interface Subclass) + 4503 Mouse (Boot Interface Subclass) + 5800 BCM5880 Secure Applications Processor + 5801 BCM5880 Secure Applications Processor with fingerprint swipe sensor + 5802 BCM5880 Secure Applications Processor with fingerprint touch sensor + 5803 BCM5880 Secure Applications Processor with secure keyboard + 5804 BCM5880 Secure Applications Processor with fingerprint swipe sensor + 6300 Pirelli Remote NDIS Device + 6410 BCM20703A1 Bluetooth 4.1 + LE + bd11 BCM4320 802.11bg Wireless Adapter + bd12 BCM4326U 802.11bg Wireless Adapter + bd13 BCM4323 802.11abgn Wireless Adapter + bd16 BCM4319 802.11bgn Wireless Adapter + bd17 BCM43236 802.11abgn Wireless Adapter + bd1d BCM43526 802.11a/b/g/n/ac (2x2) Wireless Adapter + bd1e BCM43143 802.11bgn (1x1) Wireless Adapter + bd1f BCM43242 802.11abgn Wireless Adapter + d11b Eminent EM4045 [Broadcom 4320 USB] +0a5d Diatrend Corp. +0a5f Zebra + 0009 LP2844 Printer + 0081 GK420t Label Printer + 008b HC100 wristbands Printer + 008c ZP 450 Printer + 00d1 Zebra GC420d Label Printer + 930a Printer +0a62 MPMan + 0010 MPMan MP-F40 MP3 Player +0a66 ClearCube Technology +0a67 Medeli Electronics Co., Ltd +0a68 Comaide Corp. +0a69 Chroma ate, Inc. +0a6b Green House Co., Ltd + 0001 Compact Flash R/W with MP3 player + 000f FlashDisk +0a6c Integrated Circuit Systems, Inc. +0a6d UPS Manufacturing +0a6e Benwin +0a6f Core Technology, Inc. + 0400 Xanboo +0a70 International Game Technology +0a71 VIPColor Technologies USA, Inc. + 0001 VP485 Printer +0a72 Sanwa Denshi +0a73 Mackie Designs + 0002 XD-2 [Spike] +0a7d NSTL, Inc. +0a7e Octagon Systems Corp. +0a80 Rexon Technology Corp., Ltd +0a81 Chesen Electronics Corp. + 0101 Keyboard + 0103 Keyboard + 0203 Mouse + 0205 PS/2 Keyboard+Mouse Adapter + 0701 USB Missile Launcher + ff01 Wireless Missile Launcher +0a82 Syscan + 4600 TravelScan 460/464 +0a83 NextComm, Inc. +0a84 Maui Innovative Peripherals +0a85 Idexx Labs +0a86 NITGen Co., Ltd +0a89 Aktiv + 0001 Guardant Stealth/Net + 0002 Guardant ID + 0003 Guardant Stealth 2 + 0004 Rutoken + 0005 Guardant Fidus + 0006 Guardant Stealth 3 + 0007 Guardant Stealth 2 + 0008 Guardant Stealth 3 Sign/Time + 0009 Guardant Code + 000a Guardant Sign Pro + 000b Guardant Sign Pro HID + 000c Guardant Stealth 3 Sign/Time + 000d Guardant Code HID + 000f Guardant System Firmware Update + 0020 Rutoken S + 0025 Rutoken lite + 0026 Rutoken lite HID + 002a Rutoken Mass Storage + 002b Guardant Mass Storage + 0030 Rutoken ECP + 0040 Rutoken ECP HID + 0060 Rutoken Magistra + 0061 Rutoken Magistra + 0069 Reader + 0080 Rutoken PinPad Ex + 0081 Rutoken PinPad In + 0082 Rutoken PinPad 2 +0a8d Picturetel +0a8e Japan Aviation Electronics Industry, Ltd + 2011 Filter Driver For JAE XMC R/W +0a90 Candy Technology Co., Ltd +0a91 Globlink Technology, Inc. + 3801 Targus PAKP003 Mouse +0a92 EGO SYStems, Inc. + 0011 SYS WaveTerminal U2A + 0021 GIGAPort + 0031 GIGAPortAG + 0053 AudioTrak Optoplay + 0061 Waveterminal U24 + 0071 MAYA EX7 + 0091 Maya 44 + 00b1 MAYA EX5 + 1000 MIDI Mate + 1010 RoMI/O + 1020 M4U + 1030 M8U + 1090 KeyControl49 + 10a0 KeyControl25 +0a93 C Technologies AB + 0002 C-Pen 10 + 0005 MyPen Light + 000d Input Pen + 0010 C-Pen 20 + 0a93 PayPen +0a94 Intersense +0aa3 Lava Computer Mfg., Inc. +0aa4 Develco Elektronik +0aa5 First International Digital + 0002 irock! 500 Series + 0801 MP3 Player +0aa6 Perception Digital, Ltd + 0101 Hercules Jukebox + 1501 Store 'n' Go HD Drive +0aa7 Wincor Nixdorf International GmbH + 0100 POS Keyboard, TA58P-USB + 0101 POS Keyboard, TA85P-USB + 0102 POS Keyboard, TA59-USB + 0103 POS Keyboard, TA60-USB + 0104 SNIkey Keyboard, SNIKey-KB-USB + 0200 Operator Display, BA63-USB + 0201 Operator Display, BA66-USB + 0202 Operator Display & Scanner, XiCheck-BA63 + 0203 Operator Display & Scanner, XiCheck-BA66 + 0204 Graphics Operator Display, BA63GV + 0300 POS Printer (printer class mode), TH210 + 0301 POS Printer (native mode), TH210 + 0302 POS Printer (printer class mode), TH220 + 0303 POS Printer (native mode), TH220 + 0304 POS Printer, TH230 + 0305 Lottery Printer, XiPrintPlus + 0306 POS Printer (printer class mode), TH320 + 0307 POS Printer (native mode), TH320 + 0308 POS Printer (printer class mode), TH420 + 0309 POS Printer (native mode), TH420 + 030a POS Printer, TH200B + 0400 Lottery Scanner, Xiscan S + 0401 Lottery Scanner, Xiscan 3 + 0402 Programmable Magnetic Swipe Card Reader, MSRP-USB + 0500 IDE Adapter + 0501 Hub Printer Interface + 0502 Hub SNIKey Keyboard + 4304 Banking Printer TP07 + 4305 Banking Printer TP07c + 4500 WN Central Special Electronics +0aa8 TriGem Computer, Inc. + 0060 TG 11Mbps WLAN Mini Adapter + 1001 DreamComboM4100 + 3002 InkJet Color Printer + 8001 TG_iMON + 8002 TG_KLOSS + a001 TG_X2 + a002 TGVFD_KLOSS + ffda iMON_VFD +0aa9 Baromtec Co. + f01b Medion MD 6242 MP3 Player +0aaa Japan CBM Corp. +0aab Vision Shape Europe SA +0aac iCompression, Inc. +0aad Rohde & Schwarz GmbH & Co. KG + 0003 NRP-Z21 + 000c NRP-Z11 + 0013 NRP-Z22 + 0014 NRP-Z23 + 0015 NRP-Z24 + 0016 NRP-Z51 + 0017 NRP-Z52 + 0018 NRP-Z55 + 0019 NRP-Z56 + 0021 NRP-Z91 + 0023 NRP-Z81 + 002c NRP-Z31 + 002d NRP-Z37 + 002f NRP-Z27 + 0051 NRP-Z28 + 0052 NRP-Z98 + 0062 NRP-Z92 + 0070 NRP-Z57 + 0083 NRP-Z85 + 0095 NRP-Z86 + 0117 HMF / HMP / HMS-X / HMO series Oscilloscopes + 0118 HMF / HMP / HMS-X / HMO series Oscilloscopes + 0119 HMF / HMP / HMS-X / HMO series Oscilloscopes +0aae NEC infrontia Corp. (Nitsuko) +0aaf Digitalway Co., Ltd +0ab0 Arrow Strong Electronics Co., Ltd +0ab1 FEIG ELECTRONIC GmbH + 0002 OBID RFID-Reader + 0004 OBID classic-pro +0aba Ellisys + 8001 Tracker 110 Protocol Analyzer + 8002 Explorer 200 Protocol Analyzer +0abe Stereo-Link + 0101 SL1200 DAC +0abf Diolan + 3370 I2C/SPI Adapter - U2C-12 +0ac3 Sanyo Semiconductor Company Micro +0ac4 Leco Corp. +0ac5 I & C Corp. +0ac6 Singing Electrons, Inc. +0ac7 Panwest Corp. +0ac8 Z-Star Microelectronics Corp. + 0301 Web Camera + 0302 ZC0302 Webcam + 0321 Vimicro generic vc0321 Camera + 0323 Luxya WC-1200 USB 2.0 Webcam + 0328 A4Tech PK-130MG + 0336 Elecom UCAM-DLQ30 + 301b ZC0301 Webcam + 303b ZC0303 Webcam + 305b ZC0305 Webcam + 307b USB 1.1 Webcam + 332d Vega USB 2.0 Camera + 3343 Sirius USB 2.0 Camera + 3370 Traveler TV 6500 SF Dia-scanner + 3420 Venus USB2.0 Camera + c001 Sony embedded vimicro Camera + c002 Visual Communication Camera VGP-VCC1 + c302 Vega USB 2.0 Camera + c303 Saturn USB 2.0 Camera + c326 Namuga 1.3M Webcam + c33f Webcam + c429 Lenovo ThinkCentre Web Camera + c42d Lenovo IdeaCentre Web Camera +0ac9 Micro Solutions, Inc. + 0000 Backpack CD-ReWriter + 0001 BACKPACK 2 Cable + 0010 BACKPACK + 0011 Backpack 40GB Hard Drive + 0110 BACKPACK + 0111 BackPack + 1234 BACKPACK +0aca OPEN Networks Ltd + 1060 OPEN NT1 Plus II +0acc Koga Electronics Co. +0acd ID Tech + 0300 IDT1221U RS-232 Adapter + 0401 Spectrum III Hybrid Smartcard Reader + 0630 Spectrum III Mag-Only Insert Reader (SPT3-355 Series) USB-CDC + 0810 SecurePIN (IDPA-506100Y) PIN Pad + 2030 ValueMag Magnetic Stripe Reader + 3710 ViVOpay Kiosk III +0ace ZyDAS + 1201 ZD1201 802.11b + 1211 ZD1211 802.11g + 1215 ZD1211B 802.11g + 1221 ZD1221 802.11n + 1602 ZyXEL Omni FaxModem 56K + 1608 ZyXEL Omni FaxModem 56K UNO + 1611 ZyXEL Omni FaxModem 56K Plus + 2011 Virtual media for 802.11bg + 20ff Virtual media for 802.11bg + a211 ZD1211 802.11b/g Wireless Adapter + b215 802.11bg +0acf Intoto, Inc. +0ad0 Intellix Corp. +0ad1 Remotec Technology, Ltd +0ad2 Service & Quality Technology Co., Ltd +0ada Data Encryption Systems Ltd. + 0005 DK2 +0ae3 Allion Computer, Inc. +0ae4 Taito Corp. +0ae7 Neodym Systems, Inc. +0ae8 System Support Co., Ltd +0ae9 North Shore Circuit Design L.L.P. +0aea SciEssence, LLC +0aeb TTP Communications, Ltd +0aec Neodio Technologies Corp. + 2101 SmartMedia Card Reader + 2102 CompactFlash Card Reader + 2103 MMC/SD Card Reader + 2104 MemoryStick Card Reader + 2201 SmartMedia+CompactFlash Card Reader + 2202 SmartMedia+MMC/SD Card Reader + 2203 SmartMedia+MemoryStick Card Reader + 2204 CompactFlash+MMC/SD Card Reader + 2205 CompactFlash+MemoryStick Card Reader + 2206 MMC/SD+MemoryStick Card Reader + 2301 SmartMedia+CompactFlash+MMC/SD Card Reader + 2302 SmartMedia+CompactFlash+MemoryStick Card Reader + 2303 SmartMedia+MMC/SD+MemoryStick Card Reader + 2304 CompactFlash+MMC/SD+MemoryStick Card Reader + 3016 MMC/SD+Memory Stick Card Reader + 3050 ND3050 8-in-1 Card Reader + 3060 1.1 FS Card Reader + 3101 MMC/SD Card Reader + 3102 MemoryStick Card Reader + 3201 MMC/SD+MemoryStick Card Reader + 3216 HS Card Reader + 3260 7-in-1 Card Reader + 5010 ND5010 Card Reader +0af0 Option + 5000 UMTS Card + 6000 GlobeTrotter 3G datacard + 6300 GT 3G Quad UMTS/GPRS Card + 6600 GlobeTrotter 3G+ datacard + 6711 GlobeTrotter Express 7.2 v2 + 6971 Globetrotter HSDPA Modem + 7251 Globetrotter HSUPA Modem (aka iCON HSUPA E) + 7501 Globetrotter HSUPA Modem (icon 411 aka "Vodafone K3760") + 7601 Globetrotter MO40x 3G Modem (GTM 382) + 7701 Globetrotter HSUPA Modem (aka icon 451) + d055 Globetrotter GI0505 [iCON 505] +0af6 Silver I Co., Ltd +0af7 B2C2, Inc. + 0101 Digital TV USB Receiver (DVB-S/T/C / ATSC) +0af9 Hama, Inc. + 0010 USB SightCam 100 + 0011 Micro Innovations IC50C Webcam +0afa DMC Co., Ltd. + 07d2 Controller Board for Projected Capacitive Touch Screen DUS3000 +0afc Zaptronix Ltd +0afd Tateno Dennou, Inc. +0afe Cummins Engine Co. +0aff Jump Zone Network Products, Inc. +0b00 INGENICO +0b05 ASUSTek Computer, Inc. + 0001 MeMO Pad HD 7 (CD-ROM mode) + 0301 MyPal A696 GPS PDA + 1101 Mass Storage (UISDMC4S) + 1706 WL-167G v1 802.11g Adapter [Ralink RT2571] + 1707 WL-167G v1 802.11g Adapter [Ralink RT2571] + 1708 Mass Storage Device + 170b Multi card reader + 170c WL-159g 802.11bg [ZyDAS ZD1211B+AL2230] + 170d 802.11b/g Wireless Network Adapter + 1712 BT-183 Bluetooth 2.0+EDR adapter + 1715 2045 Bluetooth 2.0 Device with trace filter + 1716 Bluetooth Device + 1717 WL169gE 802.11g Adapter [Broadcom 4320 USB] + 171b A9T wireless 802.11bg + 171c 802.11b/g Wireless Network Adapter + 171f My Cinema U3000 Mini [DiBcom DiB7700P] + 1723 WL-167G v2 802.11g Adapter [Ralink RT2571W] + 1724 RT2573 + 1726 Laptop OLED Display + 172a 802.11n Network Adapter + 172b 802.11n Network Adapter + 1731 802.11n Network Adapter + 1732 802.11n Network Adapter + 1734 AF-200 + 173c BT-183 Bluetooth 2.0 + 173f My Cinema U3100 Mini + 1742 802.11n Network Adapter + 1743 Xonar U1 Audio Station + 1751 BT-253 Bluetooth Adapter + 175b Laptop OLED Display + 1760 802.11n Network Adapter + 1761 USB-N11 802.11n Network Adapter [Ralink RT2870] + 1774 Gobi Wireless Modem (QDL mode) + 1776 Gobi Wireless Modem + 1779 My Cinema U3100 Mini Plus [AF9035A] + 1784 USB-N13 802.11n Network Adapter (rev. A1) [Ralink RT3072] + 1786 USB-N10 802.11n Network Adapter [Realtek RTL8188SU] + 1788 BT-270 Bluetooth Adapter + 1791 WL-167G v3 802.11n Adapter [Realtek RTL8188SU] + 179d USB-N53 802.11abgn Network Adapter [Ralink RT3572] + 179e Eee Note EA800 (network mode) + 179f Eee Note EA800 (tablet mode) + 17a0 Xonar U3 sound card + 17a1 Eee Note EA800 (mass storage mode) + 17ab USB-N13 802.11n Network Adapter (rev. B1) [Realtek RTL8192CU] + 17ba N10 Nano 802.11n Network Adapter [Realtek RTL8192CU] + 17c7 WL-330NUL + 17c9 USB-AC53 802.11a/b/g/n/ac Wireless Adapter [Broadcom BCM43526] + 17cb Broadcom BCM20702A0 Bluetooth + 17d1 AC51 802.11a/b/g/n/ac Wireless Adapter [Mediatek MT7610U] + 17d2 USB-AC56 802.11a/b/g/n/ac Wireless Adapter [Realtek RTL8812AU] + 17d3 USB-N10 v2 802.11b/g/n Wireless Adapter [MediaTek MT7601U] + 17db USB-AC50 802.11a/b/g/n/ac (1x1) Wireless Adapter [MediaTek MT7610U] + 17e8 USB-N14 802.11b/g/n (2x2) Wireless Adapter [Ralink RT5372] + 17eb USB-AC55 802.11a/b/g/n/ac Wireless Adapter [MediaTek MT7612U] + 180a Broadcom BCM20702 Single-Chip Bluetooth 4.0 + LE + 1817 USB-AC68 802.11a/b/g/n/ac (4x4) Wireless Adapter [Realtek RTL8814AU] + 1825 Qualcomm Bluetooth 4.1 + 4c80 Transformer Pad TF300TG + 4c90 Transformer Pad Infinity TF700 + 4c91 Transformer Pad Infinity TF700 (Debug mode) + 4ca0 Transformer Pad TF701T + 4ca1 Transformer Pad TF701T (Debug mode) + 4d00 Transformer Prime TF201 + 4d01 Transformer Prime TF201 (debug mode) + 4daf Transformer Pad Infinity TF700 (Fastboot) + 5410 MeMO Pad HD 7 (MTP mode) + 5412 MeMO Pad HD 7 (PTP mode) + 550f Fonepad 7 + 6101 Cable Modem + 620a Remote NDIS Device + 7772 Zenfone GO (ZB500KL) (MTP mode) + 7773 Zenfone GO (ZB500KL) (Debug, MTP mode) + 7774 Zenfone GO (ZB500KL) (RNDIS mode) + 7775 Zenfone GO (ZB500KL) (Debug, RNDIS mode) + 7776 Zenfone GO (ZB500KL) (PTP mode) + 7777 Zenfone GO (ZB500KL) (Debug, PTP mode) + b700 Broadcom Bluetooth 2.1 +0b0b Datamax-O'Neil + 106e Datamax E-4304 +0b0c Todos AB + 0009 Todos Argos Mini II Smart Card Reader + 001e e.dentifier2 (ABN AMRO electronic banking card reader NL) + 002e C200 smartcard controller (Nordea card reader) + 003f Todos C400 smartcard controller (Handelsbanken card reader) + 0050 Argos Mini II Smart Card Reader (CCID) +0b0d ProjectLab + 0000 CenturyCD +0b0e GN Netcom + 0348 Jabra UC VOICE 550a MS + 034c Jabra UC Voice 750 MS + 0410 Jabra SPEAK 410 + 0420 Jabra SPEAK 510 + 094d GN Netcom / Jabra REVO Wireless + 1017 Jabra PRO 930 + 1022 Jabra PRO 9450, Type 9400BS (DECT Headset) + 1041 Jabra PRO 9460 + 1900 Jabra Biz 1900 + 2007 GN 2000 Stereo Corded Headset + 620c Jabra BT620s + 9330 Jabra GN9330 Headset +0b0f AVID Technology +0b10 Pcally +0b11 I Tech Solutions Co., Ltd +0b1e Electronic Warfare Assoc., Inc. (EWA) + 8007 Blackhawk USB560-BP JTAG Emulator +0b1f Insyde Software Corp. +0b20 TransDimension, Inc. +0b21 Yokogawa Electric Corp. +0b22 Japan System Development Co., Ltd +0b23 Pan-Asia Electronics Co., Ltd +0b24 Link Evolution Corp. +0b27 Ritek Corp. +0b28 Kenwood Corp. +0b2c Village Center, Inc. +0b30 PNY Technologies, Inc. + 0006 SM Media-Shuttle Card Reader +0b33 Contour Design, Inc. + 0020 ShuttleXpress + 0030 ShuttlePro v2 + 0401 RollerMouse Free 2 + 0700 RollerMouse Pro +0b37 Hitachi ULSI Systems Co., Ltd +0b38 Gear Head + 0003 Keyboard + 0010 107-Key Keyboard +0b39 Omnidirectional Control Technology, Inc. + 0001 Composite USB PS2 Converter + 0109 USB TO Ethernet + 0421 Serial + 0801 USB-Parallel Bridge + 0901 OCT To Fast Ethernet Converter + 0c03 LAN DOCK Serial Converter +0b3a IPaxess +0b3b Tekram Technology Co., Ltd + 0163 TL-WN320G 1.0 WLAN Adapter + 1601 Allnet 0193 802.11b Adapter + 1602 ZyXEL ZyAIR B200 802.11b Adapter + 1612 AIR.Mate 2@net 802.11b Adapter + 1613 802.11b Wireless LAN Adapter + 1620 Allnet Wireless Network Adapter [Envara WiND512] + 1630 QuickWLAN 802.11bg + 5630 802.11bg + 6630 ZD1211 +0b3c Olivetti Techcenter + a010 Simple_Way Printer/Scanner/Copier + c000 Olicard 100 + c700 Olicard 100 (Mass Storage mode) +0b3e Kikusui Electronics Corp. +0b41 Hal Corp. + 0011 Crossam2+USB IR commander +0b43 Play.com, Inc. + 0003 PS2 Controller Converter + 0005 GameCube Adaptor +0b47 Sportbug.com, Inc. +0b48 TechnoTrend AG + 1003 Technotrend/Hauppauge USB-Nova + 1004 TT-PCline + 1005 Technotrend/Hauppauge USB-Nova + 1006 Technotrend/Hauppauge DEC3000-s + 1007 TT-micro plus Device + 1008 Technotrend/Hauppauge DEC2000-t + 1009 Technotrend/Hauppauge DEC2540-t + 3001 DVB-S receiver + 3002 DVB-C receiver + 3003 DVB-T receiver + 3004 TT TV-Stick + 3005 TT TV-Stick (8kB EEPROM) + 3006 TT-connect S-2400 DVB-S receiver + 3007 TT-connect S2-3600 + 3008 TT-connect + 3009 TT-connect S-2400 DVB-S receiver (8kB EEPROM) + 300a TT-connect S2-3650 CI + 300b TT-connect C-3650 CI + 300c TT-connect T-3650 CI + 300d TT-connect CT-3650 CI + 300e TT-connect C-2400 + 3011 TT-connect S2-4600 + 3012 TT-connect CT2-4650 CI + 3014 TT-TVStick CT2-4400 + 3015 TT-connect CT2-4650 CI + 3017 TT-connect S2-4650 CI +0b49 ASCII Corp. + 064f Trance Vibrator +0b4b Pine Corp. Ltd. + 0100 D'music MP3 Player +0b4d Graphtec America, Inc. + 110a Graphtec CC200-20 +0b4e Musical Electronics, Ltd + 6500 MP3 Player + 8028 MP3 Player + 8920 MP3 Player +0b50 Dumpries Co., Ltd +0b51 Comfort Keyboard Co. + 0020 Comfort Keyboard +0b52 Colorado MicroDisplay, Inc. +0b54 Sinbon Electronics Co., Ltd +0b56 TYI Systems, Ltd +0b57 Beijing HanwangTechnology Co., Ltd +0b59 Lake Communications, Ltd +0b5a Corel Corp. +0b5f Green Electronics Co., Ltd +0b60 Nsine, Ltd +0b61 NEC Viewtechnology, Ltd +0b62 Orange Micro, Inc. + 000b Bluetooth Device + 0059 iBOT2 Webcam +0b63 ADLink Technology, Inc. +0b64 Wonderful Wire Cable Co., Ltd +0b65 Expert Magnetics Corp. +0b66 Cybiko Inc. + 0041 Xtreme +0b67 Fairbanks Scales + 555e SCB-R9000 +0b69 CacheVision +0b6a Maxim Integrated Products + a132 WUP-005 [Nintendo Wii U Pro Controller] +0b6f Nagano Japan Radio Co., Ltd +0b70 PortalPlayer, Inc. + 00ba iRiver H10 20GB +0b71 SHIN-EI Sangyo Co., Ltd +0b72 Embedded Wireless Technology Co., Ltd +0b73 Computone Corp. +0b75 Roland DG Corp. +0b79 Sunrise Telecom, Inc. +0b7a Zeevo, Inc. + 07d0 Bluetooth Dongle +0b7b Taiko Denki Co., Ltd +0b7c ITRAN Communications, Ltd +0b7d Astrodesign, Inc. +0b81 id3 Technologies + 0001 Biothentic II smartcard reader with fingerprint sensor + 0002 DFU-Enabled Devices (DFU) + 0012 BioPAD biometric module (DFU + CDC) + 0102 Certis V1 fingerprint reader + 0103 Certis V2 fingerprint reader + 0200 CL1356T / CL1356T5 / CL1356A smartcard readers (CCID) + 0201 CL1356T / CL1356T5 / CL1356A smartcard readers (DFU + CCID) + 0220 CL1356A FFPJP smartcard reader (CCID + HID) + 0221 CL1356A smartcard reader (DFU + CCID + HID) +0b84 Rextron Technology, Inc. +0b85 Elkat Electronics, Sdn., Bhd. +0b86 Exputer Systems, Inc. + 5100 XMC5100 Zippy Drive + 5110 XMC5110 Flash Drive + 5200 XMC5200 Zippy Drive + 5201 XMC5200 Zippy Drive + 5202 XMC5200 Zippy Drive + 5280 XMC5280 Storage Drive + fff0 ISP5200 Debugger +0b87 Plus-One I & T, Inc. +0b88 Sigma Koki Co., Ltd, Technology Center +0b89 Advanced Digital Broadcast, Ltd +0b8c SMART Technologies Inc. + 0001 Interactive Whiteboard Controller (SB6) (HID) + 00c3 Sympodium ID350 +0b95 ASIX Electronics Corp. + 1720 10/100 Ethernet + 1780 AX88178 + 1790 AX88179 Gigabit Ethernet + 7720 AX88772 + 772a AX88772A Fast Ethernet + 772b AX88772B + 7e2b AX88772B Fast Ethernet Controller +0b96 Sewon Telecom +0b97 O2 Micro, Inc. + 7732 Smart Card Reader + 7761 Oz776 1.1 Hub + 7762 Oz776 SmartCard Reader + 7772 OZ776 CCID Smartcard Reader +0b98 Playmates Toys, Inc. +0b99 Audio International, Inc. +0b9b Dipl.-Ing. Stefan Kunde + 4012 Reflex RC-controller Interface +0b9d Softprotec Co. +0b9f Chippo Technologies +0baf U.S. Robotics + 00e5 USR6000 + 00eb USR1120 802.11b Adapter + 00ec 56K Faxmodem + 00f1 SureConnect ADSL ATM Adapter + 00f2 SureConnect ADSL Loader + 00f5 SureConnect ADSL ATM Adapter + 00f6 SureConnect ADSL Loader + 00f7 SureConnect ADSL ATM Adapter + 00f8 SureConnect ADSL Loader + 00f9 SureConnect ADSL ATM Adapter + 00fa SureConnect ADSL Loader + 00fb SureConnect ADSL Ethernet/USB Router + 0111 USR5420 802.11g Adapter [Broadcom 4320 USB] + 0118 U5 802.11g Adapter + 011b Wireless MAXg Adapter [Broadcom 4320] + 0121 USR5423 802.11bg Wireless Adapter [ZyDAS ZD1211B] + 0303 USR5637 56K Faxmodem + 6112 FaxModem Model 5633 +0bb0 Concord Camera Corp. + 0100 Sound Vision Stream + 5007 3340z/Rollei DC3100 +0bb1 Infinilink Corp. +0bb2 Ambit Microsystems Corp. + 0302 U10H010 802.11b Wireless Adapter [Intersil PRISM 3] + 6098 USB Cable Modem +0bb3 Ofuji Technology +0bb4 HTC (High Tech Computer Corp.) + 0001 Android Phone via mass storage [Wiko Cink Peax 2] + 00ce mmO2 XDA GSM/GPRS Pocket PC + 00cf SPV C500 Smart Phone + 0a01 PocketPC Sync + 0a02 Himalaya GSM/GPRS Pocket PC + 0a03 PocketPC Sync + 0a04 PocketPC Sync + 0a05 PocketPC Sync + 0a06 PocketPC Sync + 0a07 Magician PocketPC SmartPhone / O2 XDA + 0a08 PocketPC Sync + 0a09 PocketPC Sync + 0a0a PocketPC Sync + 0a0b PocketPC Sync + 0a0c PocketPC Sync + 0a0d PocketPC Sync + 0a0e PocketPC Sync + 0a0f PocketPC Sync + 0a10 PocketPC Sync + 0a11 PocketPC Sync + 0a12 PocketPC Sync + 0a13 PocketPC Sync + 0a14 PocketPC Sync + 0a15 PocketPC Sync + 0a16 PocketPC Sync + 0a17 PocketPC Sync + 0a18 PocketPC Sync + 0a19 PocketPC Sync + 0a1a PocketPC Sync + 0a1b PocketPC Sync + 0a1c PocketPC Sync + 0a1d PocketPC Sync + 0a1e PocketPC Sync + 0a1f PocketPC Sync + 0a20 PocketPC Sync + 0a21 PocketPC Sync + 0a22 PocketPC Sync + 0a23 PocketPC Sync + 0a24 PocketPC Sync + 0a25 PocketPC Sync + 0a26 PocketPC Sync + 0a27 PocketPC Sync + 0a28 PocketPC Sync + 0a29 PocketPC Sync + 0a2a PocketPC Sync + 0a2b PocketPC Sync + 0a2c PocketPC Sync + 0a2d PocketPC Sync + 0a2e PocketPC Sync + 0a2f PocketPC Sync + 0a30 PocketPC Sync + 0a31 PocketPC Sync + 0a32 PocketPC Sync + 0a33 PocketPC Sync + 0a34 PocketPC Sync + 0a35 PocketPC Sync + 0a36 PocketPC Sync + 0a37 PocketPC Sync + 0a38 PocketPC Sync + 0a39 PocketPC Sync + 0a3a PocketPC Sync + 0a3b PocketPC Sync + 0a3c PocketPC Sync + 0a3d PocketPC Sync + 0a3e PocketPC Sync + 0a3f PocketPC Sync + 0a40 PocketPC Sync + 0a41 PocketPC Sync + 0a42 PocketPC Sync + 0a43 PocketPC Sync + 0a44 PocketPC Sync + 0a45 PocketPC Sync + 0a46 PocketPC Sync + 0a47 PocketPC Sync + 0a48 PocketPC Sync + 0a49 PocketPC Sync + 0a4a PocketPC Sync + 0a4b PocketPC Sync + 0a4c PocketPC Sync + 0a4d PocketPC Sync + 0a4e PocketPC Sync + 0a4f PocketPC Sync + 0a50 SmartPhone (MTP) + 0a51 SPV C400 / T-Mobile SDA GSM/GPRS Pocket PC + 0a52 SmartPhone Sync + 0a53 SmartPhone Sync + 0a54 SmartPhone Sync + 0a55 SmartPhone Sync + 0a56 SmartPhone Sync + 0a57 SmartPhone Sync + 0a58 SmartPhone Sync + 0a59 SmartPhone Sync + 0a5a SmartPhone Sync + 0a5b SmartPhone Sync + 0a5c SmartPhone Sync + 0a5d SmartPhone Sync + 0a5e SmartPhone Sync + 0a5f SmartPhone Sync + 0a60 SmartPhone Sync + 0a61 SmartPhone Sync + 0a62 SmartPhone Sync + 0a63 SmartPhone Sync + 0a64 SmartPhone Sync + 0a65 SmartPhone Sync + 0a66 SmartPhone Sync + 0a67 SmartPhone Sync + 0a68 SmartPhone Sync + 0a69 SmartPhone Sync + 0a6a SmartPhone Sync + 0a6b SmartPhone Sync + 0a6c SmartPhone Sync + 0a6d SmartPhone Sync + 0a6e SmartPhone Sync + 0a6f SmartPhone Sync + 0a70 SmartPhone Sync + 0a71 SmartPhone Sync + 0a72 SmartPhone Sync + 0a73 SmartPhone Sync + 0a74 SmartPhone Sync + 0a75 SmartPhone Sync + 0a76 SmartPhone Sync + 0a77 SmartPhone Sync + 0a78 SmartPhone Sync + 0a79 SmartPhone Sync + 0a7a SmartPhone Sync + 0a7b SmartPhone Sync + 0a7c SmartPhone Sync + 0a7d SmartPhone Sync + 0a7e SmartPhone Sync + 0a7f SmartPhone Sync + 0a80 SmartPhone Sync + 0a81 SmartPhone Sync + 0a82 SmartPhone Sync + 0a83 SmartPhone Sync + 0a84 SmartPhone Sync + 0a85 SmartPhone Sync + 0a86 SmartPhone Sync + 0a87 SmartPhone Sync + 0a88 SmartPhone Sync + 0a89 SmartPhone Sync + 0a8a SmartPhone Sync + 0a8b SmartPhone Sync + 0a8c SmartPhone Sync + 0a8d SmartPhone Sync + 0a8e SmartPhone Sync + 0a8f SmartPhone Sync + 0a90 SmartPhone Sync + 0a91 SmartPhone Sync + 0a92 SmartPhone Sync + 0a93 SmartPhone Sync + 0a94 SmartPhone Sync + 0a95 SmartPhone Sync + 0a96 SmartPhone Sync + 0a97 SmartPhone Sync + 0a98 SmartPhone Sync + 0a99 SmartPhone Sync + 0a9a SmartPhone Sync + 0a9b SmartPhone Sync + 0a9c SmartPhone Sync + 0a9d SmartPhone Sync + 0a9e SmartPhone Sync + 0a9f SmartPhone Sync + 0b03 Ozone Mobile Broadband + 0b04 Hermes / TyTN / T-Mobile MDA Vario II / O2 Xda Trion + 0b05 P3600 + 0b06 Athena / Advantage x7500 / Dopod U1000 / T-Mobile AMEO + 0b0c Elf / Touch / P3450 / T-Mobile MDA Touch / O2 Xda Nova / Dopod S1 + 0b1f Sony Ericsson XPERIA X1 + 0b2f Rhodium + 0b51 Qtek 8310 mobile phone [Tornado Noble] + 0bce Vario MDA + 0c01 Dream / ADP1 / G1 / Magic / Tattoo + 0c02 Dream / ADP1 / G1 / Magic / Tattoo (Debug) + 0c03 Android Phone [Fairphone First Edition (FP1)] + 0c13 Diamond + 0c1f Sony Ericsson XPERIA X1 + 0c5f Snap + 0c86 Sensation + 0c87 Desire (debug) + 0c8d EVO 4G (debug) + 0c91 Vision + 0c94 Vision + 0c97 Legend + 0c99 Desire (debug) + 0c9e Incredible + 0ca2 Desire HD (debug mode) + 0ca5 Android Phone [Evo Shift 4G] + 0cae T-Mobile MyTouch 4G Slide [Doubleshot] + 0de5 One (M7) + 0dea M7_UL [HTC One] + 0f25 One M8 + 0f63 Desire 610 Via MTP + 0f64 Desire 601 + 0fb4 Remote NDIS based Device + 0ff8 Desire HD (Tethering Mode) + 0ff9 Desire / Desire HD / Hero / Thunderbolt (Charge Mode) + 0ffe Desire HD (modem mode) + 0fff Android Fastboot Bootloader + 2008 Android Phone via MTP [Wiko Cink Peax 2] + 200b Android Phone via PTP [Wiko Cink Peax 2] +0bb5 Murata Manufacturing Co., Ltd +0bb6 Network Alchemy +0bb7 Joytech Computer Co., Ltd +0bb8 Hitachi Semiconductor and Devices Sales Co., Ltd +0bb9 Eiger M&C Co., Ltd +0bba ZAccess Systems +0bbb General Meters Corp. +0bbc Assistive Technology, Inc. +0bbd System Connection, Inc. +0bc0 Knilink Technology, Inc. +0bc1 Fuw Yng Electronics Co., Ltd +0bc2 Seagate RSS LLC + 0502 ST3300601CB-RK 300 GB External Hard Drive + 0503 ST3250824A [Barracuda 7200.9] + 2000 Storage Adapter V3 (TPP) + 2100 FreeAgent Go + 2200 FreeAgent Go FW + 2300 Expansion Portable + 231a Expansion Portable + 2320 USB 3.0 bridge [Portable Expansion Drive] + 2321 Expansion Portable + 2322 SRD0NF1 Expansion Portable (STEA) + 2340 FreeAgent External Hard Drive + 3000 FreeAgent Desktop + 3008 FreeAgent Desk 1TB + 3101 FreeAgent XTreme 640GB + 3312 SRD00F2 Expansion Desktop Drive (STBV) + 3320 SRD00F2 [Expansion Desktop Drive] + 3322 SRD0NF2 [Expansion Desktop Drive] + 3332 Expansion + 5020 FreeAgent GoFlex + 5021 FreeAgent GoFlex USB 2.0 + 5030 FreeAgent GoFlex Upgrade Cable STAE104 + 5031 FreeAgent GoFlex USB 3.0 + 5032 SATA cable + 5070 FreeAgent GoFlex Desk + 5071 FreeAgent GoFlex Desk + 50a1 FreeAgent GoFlex Desk + 50a5 FreeAgent GoFlex Desk USB 3.0 + 5121 FreeAgent GoFlex + 5161 FreeAgent GoFlex dock + 6126 Maxtor D3 Station 5TB + 61b6 Maxtor HX-M101TCB/GM [M3 Portable 1TB] + 61b7 Maxtor M3 Portable + a003 Backup Plus + a0a1 Backup Plus Desktop + a0a4 Backup Plus Desktop Drive + ab00 Slim Portable Drive + ab1e Backup Plus Portable Drive + ab20 Backup Plus Portable Drive + ab21 Backup Plus Slim + ab24 Backup Plus Portable Drive + ab26 Backup Plus Slim Portable Drive 1 TB + ab31 Backup Plus Desktop Drive (5TB) + ab34 Backup Plus + ab38 Backup Plus Hub +0bc3 IPWireless, Inc. + 0001 UMTS-TDD (TD-CDMA) modem +0bc4 Microcube Corp. +0bc5 JCN Co., Ltd +0bc6 ExWAY, Inc. +0bc7 X10 Wireless Technology, Inc. + 0001 ActiveHome (ACPI-compliant) + 0002 Firecracker Interface (ACPI-compliant) + 0003 VGA Video Sender (ACPI-compliant) + 0004 X10 Receiver + 0005 Wireless Transceiver (ACPI-compliant) + 0006 Wireless Transceiver (ACPI-compliant) + 0007 Wireless Transceiver (ACPI-compliant) + 0008 Wireless Transceiver (ACPI-compliant) + 0009 Wireless Transceiver (ACPI-compliant) + 000a Wireless Transceiver (ACPI-compliant) + 000b Transceiver (ACPI-compliant) + 000c Transceiver (ACPI-compliant) + 000d Transceiver (ACPI-compliant) + 000e Transceiver (ACPI-compliant) + 000f Transceiver (ACPI-compliant) +0bc8 Telmax Communications +0bc9 ECI Telecom, Ltd +0bca Startek Engineering, Inc. +0bcb Perfect Technic Enterprise Co., Ltd +0bd7 Andrew Pargeter & Associates + a021 Amptek DP4 multichannel signal analyzer +0bda Realtek Semiconductor Corp. + 0103 USB 2.0 Card Reader + 0104 Mass Storage Device + 0106 Mass Storage Device + 0107 Mass Storage Device + 0108 Mass Storage Device + 0109 microSDXC Card Reader [Hama 00091047] + 0111 RTS5111 Card Reader Controller + 0113 Mass Storage Device + 0115 Mass Storage Device (Multicard Reader) + 0116 RTS5116 Card Reader Controller + 0117 Mass Storage Device + 0118 Mass Storage Device + 0119 Storage Device (SD card reader) + 0129 RTS5129 Card Reader Controller + 0138 RTS5138 Card Reader Controller + 0139 RTS5139 Card Reader Controller + 0151 Mass Storage Device (Multicard Reader) + 0152 Mass Storage Device + 0153 3-in-1 (SD/SDHC/SDXC) Card Reader + 0156 Mass Storage Device + 0157 Mass Storage Device + 0158 USB 2.0 multicard reader + 0159 RTS5159 Card Reader Controller + 0161 Mass Storage Device + 0168 Mass Storage Device + 0169 Mass Storage Device + 0171 Mass Storage Device + 0176 Mass Storage Device + 0178 Mass Storage Device + 0179 RTL8188ETV Wireless LAN 802.11n Network Adapter + 0184 RTS5182 Card Reader + 0186 Card Reader + 0301 multicard reader + 0307 Card Reader + 0326 Card reader + 1724 RTL8723AU 802.11n WLAN Adapter + 2831 RTL2831U DVB-T + 2832 RTL2832U DVB-T + 2838 RTL2838 DVB-T + 5401 RTL 8153 USB 3.0 hub with gigabit ethernet + 570c Asus laptop camera + 5730 HP 2.0MP High Definition Webcam + 5751 Integrated Webcam + 5775 HP "Truevision HD" laptop camera + 57b3 Acer 640 × 480 laptop camera + 57da Built-In Video Camera + 58c8 Integrated Webcam HD + 8150 RTL8150 Fast Ethernet Adapter + 8151 RTL8151 Adapteon Business Mobile Networks BV + 8152 RTL8152 Fast Ethernet Adapter + 8153 RTL8153 Gigabit Ethernet Adapter + 8171 RTL8188SU 802.11n WLAN Adapter + 8172 RTL8191SU 802.11n WLAN Adapter + 8174 RTL8192SU 802.11n WLAN Adapter + 8176 RTL8188CUS 802.11n WLAN Adapter + 8178 RTL8192CU 802.11n WLAN Adapter + 8179 RTL8188EUS 802.11n Wireless Network Adapter + 817f RTL8188RU 802.11n WLAN Adapter + 8187 RTL8187 Wireless Adapter + 8189 RTL8187B Wireless 802.11g 54Mbps Network Adapter + 818b RTL8192EU 802.11b/g/n WLAN Adapter + 8192 RTL8191SU 802.11n Wireless Adapter + 8193 RTL8192DU 802.11an WLAN Adapter + 8197 RTL8187B Wireless Adapter + 8198 RTL8187B Wireless Adapter + 8199 RTL8187SU 802.11g WLAN Adapter + 8812 RTL8812AU 802.11a/b/g/n/ac 2T2R DB WLAN Adapter + 8813 RTL8814AU 802.11a/b/g/n/ac Wireless Adapter + a811 RTL8811AU 802.11a/b/g/n/ac WLAN Adapter +0bdb Ericsson Business Mobile Networks BV + 1000 BV Bluetooth Device + 1002 Bluetooth Device 1.2 + 1049 C3607w Mobile Broadband Module + 1900 F3507g Mobile Broadband Module + 1902 F3507g v2 Mobile Broadband Module + 1904 F3607gw Mobile Broadband Module + 1905 F3607gw v2 Mobile Broadband Module + 1906 F3607gw v3 Mobile Broadband Module + 1909 F3307 v2 Mobile Broadband Module + 190a F3307 Mobile Broadband Module + 190b C3607w v2 Mobile Broadband Module + 1926 H5321 gw Mobile Broadband Driver +0bdc Y Media Corp. +0bdd Orange PCS +0be2 Kanda Tsushin Kogyo Co., Ltd +0be3 TOYO Corp. +0be4 Elka International, Ltd +0be5 DOME imaging systems, Inc. +0be6 Dong Guan Humen Wonderful Wire Cable Factory +0bed MEI + 1100 CASHFLOW SC + 1101 Series 2000 Combo Acceptor +0bee LTK Industries, Ltd +0bef Way2Call Communications +0bf0 Pace Micro Technology PLC +0bf1 Intracom S.A. + 0001 netMod Driver Ver 2.4.17 (CAPI) + 0002 netMod Driver Ver 2.4 (CAPI) + 0003 netMod Driver Ver 2.4 (CAPI) +0bf2 Konexx +0bf6 Addonics Technologies, Inc. + 0103 Storage Device + 1234 Storage Device + a000 Cable 205 (TPP) + a001 Cable 205 + a002 IDE Bridge +0bf7 Sunny Giken, Inc. +0bf8 Fujitsu Siemens Computers + 1001 Fujitsu Pocket Loox 600 PDA + 1006 SmartCard Reader 2A + 1007 Connect2Air E-5400 802.11g Wireless Adapter + 1009 Connect2Air E-5400 D1700 802.11g Wireless Adapter [Intersil ISL3887] + 100c Keyboard FSC KBPC PX + 100f miniCard D2301 802.11bg Wireless Module [SiS 163U] + 1017 Keyboard KB SCR + 101f Fujitsu Full HD Pro Webcam +0bfd Kvaser AB + 0004 USBcan II + 000b Leaf Light HS + 000e Leaf SemiPro HS +0c00 FireFly Mouse Mat + 1607 Apex M500 +0c04 MOTO Development Group, Inc. +0c05 Appian Graphics +0c06 Hasbro Games, Inc. +0c07 Infinite Data Storage, Ltd +0c08 Agate + 0378 Q 16MB Storage Device +0c09 Comjet Information System + a5a5 Litto Version USB2.0 +0c0a Highpoint Technologies, Inc. +0c0b Dura Micro, Inc. (Acomdata) + 27cb 6-in-1 Flash Reader and Writer + 27d7 Multi Memory reader/writer MD-005 + 27da Multi Memory reader/writer MD-005 + 27dc Multi Memory reader/writer MD-005 + 27e7 3,5'' HDD case MD-231 + 27ee 3,5'' HDD case MD-231 + 2814 3,5'' HDD case MD-231 + 2815 3,5'' HDD case MD-231 + 281d 3,5'' HDD case MD-231 + 5fab Storage Adaptor + a109 CF/SM Reader and Writer + a10c SD/MS Reader and Writer + b001 USB 2.0 Mass Storage IDE adapter + b004 MMC/SD Reader and Writer +0c12 Zeroplus + 0005 PSX Vibration Feedback Converter + 0030 PSX Vibration Feedback Converter + 700e Logic Analyzer (LAP-C-16032) + 8801 Xbox Controller + 8802 Xbox Controller + 8809 Red Octane Ignition Xbox DDR Pad + 880a Pelican Eclipse PL-2023 + 8810 Xbox Controller + 9902 VibraX +0c15 Iris Graphics +0c16 Gyration, Inc. + 0002 RF Technology Receiver + 0003 RF Technology Receiver + 0008 RF Technology Receiver + 0080 eHome Infrared Receiver + 0081 eHome Infrared Receiver +0c17 Cyberboard A/S +0c18 SynerTek Korea, Inc. +0c19 cyberPIXIE, Inc. +0c1a Silicon Motion, Inc. +0c1b MIPS Technologies +0c1c Hang Zhou Silan Electronics Co., Ltd +0c22 Tally Printer Corp. +0c23 Lernout + Hauspie +0c24 Taiyo Yuden + 0001 Bluetooth Adaptor + 0002 Bluetooth Device2 + 0005 Bluetooth Device(BC04-External) + 000b Bluetooth Device(BC04-External) + 000c Bluetooth Adaptor + 000e Bluetooth Device(BC04-External) + 000f Bluetooth Device (V2.0+EDR) + 0010 Bluetooth Device(BC04-External) + 0012 Bluetooth Device(BC04-External) + 0018 Bluetooth Device(BC04-External) + 0019 Bluetooth Device + 0021 Bluetooth Device (V2.1+EDR) + 0c24 Bluetooth Device(SAMPLE) + ffff Bluetooth module with BlueCore in DFU mode +0c25 Sampo Corp. + 0310 Scream Cam +0c26 Prolific Technology Inc. + 0018 USB-Serial Controller [Icom Inc. OPC-478UC] +0c27 RFIDeas, Inc + 3bfa pcProx Card Reader +0c2e Metrologic Instruments + 0007 Metrologic MS7120 Barcode Scanner (IBM SurePOS mode) + 0200 MS7120 Barcode Scanner + 0204 Metrologic MS7120 Barcode Scanner (keyboard mode) + 0206 Metrologic MS4980 Barcode Scanner + 0700 Metrologic MS7120 Barcode Scanner (uni-directional serial mode) + 0720 Metrologic MS7120 Barcode Scanner (bi-directional serial mode) + 0b61 Vuquest 3310g + 0b6a Vuquest 3310 Area-Imaging Scanner + 0b81 Barcode scanner Voyager 1400g Series +0c30 Mutoh Industries Ltd + 6010 Kona 1400 Cutting Plotter +0c35 Eagletron, Inc. +0c36 E Ink Corp. +0c37 e.Digital +0c38 Der An Electric Wire & Cable Co., Ltd +0c39 IFR +0c3a Furui Precise Component (Kunshan) Co., Ltd +0c3b Komatsu, Ltd +0c3c Radius Co., Ltd +0c3d Innocom, Inc. +0c3e Nextcell, Inc. +0c44 Motorola iDEN + 0021 iDEN P2k0 Device + 0022 iDEN P2k1 Device + 03a2 iDEN Smartphone + 41d9 i1 phone +0c45 Microdia + 0011 EBUDDY + 0520 MaxTrack Wireless Mouse + 1018 Compact Flash storage memory card reader + 1020 Mass Storage Reader + 1028 Mass Storage Reader + 1030 Mass Storage Reader + 1031 Sonix Mass Storage Device + 1032 Mass Storage Reader + 1033 Sonix Mass Storage Device + 1034 Mass Storage Reader + 1035 Mass Storage Reader + 1036 Mass Storage Reader + 1037 Sonix Mass Storage Device + 1050 CF Card Reader + 1058 HDD Reader + 1060 iFlash SM-Direct Card Reader + 1061 Mass Storage Reader + 1062 Mass Storage Reader + 1063 Sonix Mass Storage Device + 1064 Mass Storage Reader + 1065 Mass Storage Reader + 1066 Mass Storage Reader + 1067 Mass Storage Reader + 1158 A56AK + 184c VoIP Phone + 6001 Genius VideoCAM NB + 6005 Sweex Mini Webcam + 6007 VideoCAM Eye + 6009 VideoCAM ExpressII + 600d TwinkleCam USB camera + 6011 PC Camera (SN9C102) + 6019 PC Camera (SN9C102) + 6024 VideoCAM ExpressII + 6025 VideoCAM ExpressII + 6028 Typhoon Easycam USB 330K (older) + 6029 Triplex i-mini PC Camera + 602a Meade ETX-105EC Camera + 602b VideoCAM NB 300 + 602c Clas Ohlson TWC-30XOP Webcam + 602d VideoCAM ExpressII + 602e VideoCAM Messenger + 6030 VideoCAM ExpressII + 603f VideoCAM ExpressII + 6040 CCD PC Camera (PC390A) + 606a CCD PC Camera (PC390A) + 607a CCD PC Camera (PC390A) + 607b Win2 PC Camera + 607c CCD PC Camera (PC390A) + 607e CCD PC Camera (PC390A) + 6080 Audio (Microphone) + 6082 VideoCAM Look + 6083 VideoCAM Look + 608c VideoCAM Look + 608e VideoCAM Look + 608f PC Camera (SN9C103 + OV7630) + 60a8 VideoCAM Look + 60aa VideoCAM Look + 60ab PC Camera + 60af VideoCAM Look + 60b0 Genius VideoCam Look + 60c0 PC Camera with Mic (SN9C105) + 60c8 Win2 PC Camera + 60cc PC Camera with Mic (SN9C105) + 60ec PC Camera with Mic (SN9C105) + 60ef Win2 PC Camera + 60fa PC Camera with Mic (SN9C105) + 60fb Composite Device + 60fc PC Camera with Mic (SN9C105) + 60fe Audio (Microphone) + 6108 Win2 PC Camera + 6122 PC Camera (SN9C110) + 6123 PC Camera (SN9C110) + 6128 PC Camera (SN9C325 + OM6802) + 612a PC Camera (SN9C325) + 612c PC Camera (SN9C110) + 612e PC Camera (SN9C110) + 612f PC Camera (SN9C110) + 6130 PC Camera (SN9C120) + 6138 Win2 PC Camera + 613a PC Camera (SN9C120) + 613b Win2 PC Camera + 613c PC Camera (SN9C120) + 613e PC Camera (SN9C120) + 6143 PC Camera (SN9C120 + SP80708) + 6240 PC Camera (SN9C201 + MI1300) + 6242 PC Camera (SN9C201 + MI1310) + 6243 PC Camera (SN9C201 + S5K4AAFX) + 6248 PC Camera (SN9C201 + OV9655) + 624b PC Camera (SN9C201 + CX1332) + 624c PC Camera (SN9C201 + MI1320) + 624e PC Camera (SN9C201 + SOI968) + 624f PC Camera (SN9C201 + OV9650) + 6251 PC Camera (SN9C201 + OV9650) + 6253 PC Camera (SN9C201 + OV9650) + 6260 PC Camera (SN9C201 + OV7670ISP) + 6262 PC Camera (SN9C201 + OM6802) + 6270 PC Camera (SN9C201 + MI0360/MT9V011 or MI0360SOC/MT9V111) U-CAM PC Camera NE878, Whitcom WHC017, ... + 627a PC Camera (SN9C201 + S5K53BEB) + 627b PC Camera (SN9C201 + OV7660) + 627c PC Camera (SN9C201 + HV7131R) + 627f PC Camera (SN9C201 + OV965x + EEPROM) + 6280 PC Camera with Microphone (SN9C202 + MI1300) + 6282 PC Camera with Microphone (SN9C202 + MI1310) + 6283 PC Camera with Microphone (SN9C202 + S5K4AAFX) + 6288 PC Camera with Microphone (SN9C202 + OV9655) + 628a PC Camera with Microphone (SN9C202 + ICM107) + 628b PC Camera with Microphone (SN9C202 + CX1332) + 628c PC Camera with Microphone (SN9C202 + MI1320) + 628e PC Camera with Microphone (SN9C202 + SOI968) + 628f PC Camera with Microphone (SN9C202 + OV9650) + 62a0 PC Camera with Microphone (SN9C202 + OV7670ISP) + 62a2 PC Camera with Microphone (SN9C202 + OM6802) + 62b0 PC Camera with Microphone (SN9C202 + MI0360/MT9V011 or MI0360SOC/MT9V111) + 62b3 PC Camera with Microphone (SN9C202 + OV9655) + 62ba PC Camera with Microphone (SN9C202 + S5K53BEB) + 62bb PC Camera with Microphone (SN9C202 + OV7660) + 62bc PC Camera with Microphone (SN9C202 + HV7131R) + 62be PC Camera with Microphone (SN9C202 + OV7663) + 62c0 Sonix USB 2.0 Camera + 62e0 MSI Starcam Racer + 6300 PC Microscope camera + 6310 Sonix USB 2.0 Camera + 6340 Camera + 6341 Defender G-Lens 2577 HD720p Camera + 63e0 Sonix Integrated Webcam + 63f1 Integrated Webcam + 63f8 Sonix Integrated Webcam + 6409 Webcam + 6413 Integrated Webcam + 6417 Integrated Webcam + 6419 Integrated Webcam + 641d 1.3 MPixel Integrated Webcam + 6433 Laptop Integrated Webcam HD (Composite Device) + 643f Dell Integrated HD Webcam + 644d 1.3 MPixel Integrated Webcam + 6480 Sonix 1.3 MP Laptop Integrated Webcam + 648b Integrated Webcam + 64bd Sony Visual Communication Camera + 64d0 Integrated Webcam + 64d2 Integrated Webcam + 651b HP Webcam + 6705 Integrated HD Webcam + 6710 Integrated Webcam + 7401 TEMPer Temperature Sensor + 7402 TEMPerHUM Temperature & Humidity Sensor + 7403 Foot Switch + 7404 Foot switch FS1-P + 8000 DC31VC + 8006 Dual Mode Camera (8006 VGA) + 800a Vivitar Vivicam3350B +0c46 WaveRider Communications, Inc. +0c4a ALGE-TIMING GmbH + 0889 Timy + 088a Timy 2 +0c4b Reiner SCT Kartensysteme GmbH + 0100 cyberJack e-com/pinpad + 0300 cyberJack pinpad(a) + 0400 cyberJack e-com(a) + 0401 cyberJack pinpad(a2) + 0500 cyberJack RFID standard dual interface smartcard reader + 0501 cyberJack RFID comfort dual interface smartcard reader + 0502 cyberJack compact + 0504 cyberJack go / go plus + 0505 cyberJack wave + 9102 cyberJack RFID basis contactless smartcard reader +0c4c Needham's Electronics + 0021 EMP-21 Universal Programmer +0c52 Sealevel Systems, Inc. + 2101 SeaLINK+232 + 2102 SeaLINK+485 + 2103 SeaLINK+232I + 2104 SeaLINK+485I + 2211 SeaPORT+2/232 (Port 1) + 2212 SeaPORT+2/485 (Port 1) + 2213 SeaPORT+2 (Port 1) + 2221 SeaPORT+2/232 (Port 2) + 2222 SeaPORT+2/485 (Port 2) + 2223 SeaPORT+2 (Port 2) + 2411 SeaPORT+4/232 (Port 1) + 2412 SeaPORT+4/485 (Port 1) + 2413 SeaPORT+4 (Port 1) + 2421 SeaPORT+4/232 (Port 2) + 2422 SeaPORT+4/485 (Port 2) + 2423 SeaPORT+4 (Port 2) + 2431 SeaPORT+4/232 (Port 3) + 2432 SeaPORT+4/485 (Port 3) + 2433 SeaPORT+4 (Port 3) + 2441 SeaPORT+4/232 (Port 4) + 2442 SeaPORT+4/485 (Port 4) + 2443 SeaPORT+4 (Port 4) + 2811 SeaLINK+8/232 (Port 1) + 2812 SeaLINK+8/485 (Port 1) + 2813 SeaLINK+8 (Port 1) + 2821 SeaLINK+8/232 (Port 2) + 2822 SeaLINK+8/485 (Port 2) + 2823 SeaLINK+8 (Port 2) + 2831 SeaLINK+8/232 (Port 3) + 2832 SeaLINK+8/485 (Port 3) + 2833 SeaLINK+8 (Port 3) + 2841 SeaLINK+8/232 (Port 4) + 2842 SeaLINK+8/485 (Port 4) + 2843 SeaLINK+8 (Port 4) + 2851 SeaLINK+8/232 (Port 5) + 2852 SeaLINK+8/485 (Port 5) + 2853 SeaLINK+8 (Port 5) + 2861 SeaLINK+8/232 (Port 6) + 2862 SeaLINK+8/485 (Port 6) + 2863 SeaLINK+8 (Port 6) + 2871 SeaLINK+8/232 (Port 7) + 2872 SeaLINK+8/485 (Port 7) + 2873 SeaLINK+8 (Port 7) + 2881 SeaLINK+8/232 (Port 8) + 2882 SeaLINK+8/485 (Port 8) + 2883 SeaLINK+8 (Port 8) + 9020 SeaLINK+422 + a02a SeaLINK+8 (Port 1+2) + a02b SeaLINK+8 (Port 3+4) + a02c SeaLINK+8 (Port 5+6) + a02d SeaLINK+8 (Port 7+8) +0c53 ViewPLUS, Inc. +0c54 Glory, Ltd +0c55 Spectrum Digital, Inc. + 0510 Spectrum Digital XDS510 JTAG Debugger + 0540 SPI540 + 5416 TMS320C5416 DSK + 6416 TMS320C6416 DDB +0c56 Billion Bright, Ltd +0c57 Imaginative Design Operation Co., Ltd +0c58 Vidar Systems Corp. +0c59 Dong Guan Shinko Wire Co., Ltd +0c5a TRS International Mfg., Inc. +0c5e Xytronix Research & Design +0c60 Apogee Electronics Corp. + 0001 MiniMe + 0002 MiniDAC + 0003 ONE + 0004 GiO + 0007 Duet + 0009 Jam + 000a Jam Bootloader + 000b MiC + 000c MiC Bootloader + 8007 Duet DFU Mode +0c62 Chant Sincere Co., Ltd +0c63 Toko, Inc. +0c64 Signality System Engineering Co., Ltd +0c65 Eminence Enterprise Co., Ltd +0c66 Rexon Electronics Corp. +0c67 Concept Telecom, Ltd +0c6a ACS + 0005 Color 320 x 240 LCD Display Terminal with Touchscreen +0c6c JETI Technische Instrumente GmbH + 04b2 Specbos 1201 +0c70 MCT Elektronikladen + 0000 USB08 Development board + 0747 Eye Movement Recorder [Visagraph]/[ReadAlyzer] +0c72 PEAK System + 000c PCAN-USB + 000d PCAN Pro +0c74 Optronic Laboratories Inc. + 0002 OL 700-30 Goniometer +0c76 JMTek, LLC. + 0001 Mass Storage Controller + 0002 Mass Storage Controller + 0003 USBdisk + 0004 Mass Storage Controller + 0005 Transcend Flash disk + 0006 Transcend JetFlash + 0007 Mass Storage Device + 1600 Ion Quick Play LP turntable + 1605 SSS Headphone Set + 1607 audio controller +0c77 Sipix Group, Ltd + 1001 SiPix Web2 + 1002 SiPix SC2100 + 1010 SiPix Snap + 1011 SiPix Blink 2 + 1015 SiPix CAMeleon +0c78 Detto Corp. +0c79 NuConnex Technologies Pte., Ltd +0c7a Wing-Span Enterprise Co., Ltd +0c86 NDA Technologies, Inc. +0c88 Kyocera Wireless Corp. + 0021 Handheld + 17da Qualcomm Kyocera CDMA Technologies MSM +0c89 Honda Tsushin Kogyo Co., Ltd +0c8a Pathway Connectivity, Inc. +0c8b Wavefly Corp. +0c8c Coactive Networks +0c8d Tempo +0c8e Cesscom Co., Ltd + 6000 Luxian Series +0c8f Applied Microsystems +0c94 Cryptera + a000 EPP 1217 +0c98 Berkshire Products, Inc. + 1140 USB PC Watchdog +0c99 Innochips Co., Ltd +0c9a Hanwool Robotics Corp. +0c9b Jobin Yvon, Inc. +0c9d SemTek + 0170 3873 Manual Insert card reader +0ca2 Zyfer +0ca3 Sega Corp. +0ca4 ST&T Instrument Corp. +0ca5 BAE Systems Canada, Inc. +0ca6 Castles Technology Co., Ltd + 0010 EZUSB PC/SC Smart Card Reader + 0050 EZ220PU Reader Controller + 1077 Bludrive Family Smart Card Reader + 107e Reader Controller + 2010 myPad110 PC/SC Smart Card Reader + 3050 EZ710 Smart Card Reader +0ca7 Information Systems Laboratories +0cad Motorola CGISS + 1007 APX Series Consolette + 1020 MOTOTRBO Series Radio (Portable) + 1030 APX Series Radio (Portable) + 1031 APX Series Radio (Mobile) + 1602 IMPRES Battery Data Reader + 9001 PowerPad Pocket PC Device +0cae Ascom Business Systems, Ltd +0caf Buslink + 2507 Hi-Speed USB-to-IDE Bridge Controller + 2515 Flash Disk Embedded Hub + 2516 Flash Disk Security Device + 2517 Flash Disk Mass Storage Device + 25c7 Hi-Speed USB-to-IDE Bridge Controller + 3a00 Hard Drive + 3a20 Mass Storage Device + 3acd Mass Storage Device +0cb0 Flying Pig Systems +0cb1 Innovonics, Inc. +0cb6 Celestix Networks, Pte., Ltd +0cb7 Singatron Enterprise Co., Ltd +0cb8 Opticis Co., Ltd +0cba Trust Electronic (Shanghai) Co., Ltd +0cbb Shanghai Darong Electronics Co., Ltd +0cbc Palmax Technology Co., Ltd + 0101 Pocket PC P6C + 0201 Personal Digital Assistant + 0301 Personal Digital Assistant P6M+ + 0401 Pocket PC +0cbd Pentel Co., Ltd (Electronics Equipment Div.) +0cbe Keryx Technologies, Inc. +0cbf Union Genius Computer Co., Ltd +0cc0 Kuon Yi Industrial Corp. +0cc1 Given Imaging, Ltd +0cc2 Timex Corp. +0cc3 Rimage Corp. +0cc4 emsys GmbH +0cc5 Sendo +0cc6 Intermagic Corp. +0cc8 Technotools Corp. +0cc9 BroadMAX Technologies, Inc. +0cca Amphenol +0ccb SKNet Co., Ltd +0ccc Domex Technology Corp. +0ccd TerraTec Electronic GmbH + 0012 PHASE 26 + 0013 PHASE 26 + 0014 PHASE 26 + 0015 Flash Update for TerraTec PHASE 26 + 0021 Cameo Grabster 200 + 0023 Mystify Claw + 0028 Aureon 5.1 MkII + 0032 MIDI HUBBLE + 0035 Miditech Play'n Roll + 0036 Cinergy 250 Audio + 0037 Cinergy 250 Audio + 0038 Cinergy T² DVB-T Receiver + 0039 Grabster AV 400 + 003b Cinergy 400 + 003c Grabster AV 250 + 0042 Cinergy Hybrid T XS + 0043 Cinergy T XS + 004e Cinergy T XS + 004f Cinergy Analog XS + 0055 Cinergy T XE (Version 1, AF9005) + 005c Cinergy T² + 0069 Cinergy T XE (Version 2, AF9015) + 006b Cinergy HT PVR (EU) + 0072 Cinergy Hybrid T + 0077 Aureon Dual USB + 0078 Cinergy T XXS + 0086 Cinergy Hybrid XE + 008e Cinergy HTC XS + 0096 Grabby + 0097 Cinergy T RC MKII + 0099 AfaTech 9015 [Cinergy T Stick Dual] + 00a5 Cinergy Hybrid Stick + 00a9 RTL2838 DVB-T COFDM Demodulator [TerraTec Cinergy T Stick Black] + 00b3 NOXON DAB/DAB+ Stick + 00e0 NOXON DAB/DAB+ Stick V2 + 0102 Cinergy S2 Stick + 0105 Cinergy S2 Box + 10a7 TerraTec G3 +0cd4 Bang Olufsen + 0101 BeolinkPC2 +0cd5 LabJack Corporation + 0003 U3 + 0009 UE9 +0cd6 Scheidt & Bachmann + 000c S&B TPU + 000e S&B BKV + 0011 Money Coin Unit +0cd7 NewChip S.r.l. +0cd8 JS Digitech, Inc. + 2007 Smart Card Reader/JSTU-9700 +0cd9 Hitachi Shin Din Cable, Ltd +0cde Z-Com + 0001 XI-750 802.11b Wireless Adapter [Atmel AT76C503A] + 0002 XI-725/726 Prism2.5 802.11b Adapter + 0003 Sagem 802.11b Dongle + 0004 Sagem 802.11b Dongle + 0005 XI-735 Prism3 802.11b Adapter + 0006 XG-300 802.11b Adapter + 0008 XG-703A 802.11g Wireless Adapter [Intersil ISL3887] + 0009 (ZD1211)IEEE 802.11b+g Adapter + 0011 ZD1211 + 0012 AR5523 + 0013 AR5523 driver (no firmware) + 0014 NB 802.11g Wireless LAN Adapter(3887A) + 0015 XG-705A 802.11g Wireless Adapter [Intersil ISL3887] + 0016 NB 802.11g Wireless LAN Adapter(3887A) + 0018 NB 802.11a/b/g Wireless LAN Adapter(3887A) + 001a 802.11bg + 001c 802.11b/g Wireless Network Adapter + 0020 AG-760A 802.11abg Wireless Adapter [ZyDAS ZD1211B] + 0022 802.11b/g/n Wireless Network Adapter + 0023 UB81 802.11bgn + 0025 802.11b/g/n USB Wireless Network Adapter + 0026 UB82 802.11abgn + 0027 Sphairon Homelink 1202 802.11n Wireless Adapter [Atheros AR9170] +0ce5 Validation Technologies International + 0003 Matrix +0ce9 Pico Technology + 1001 PicoScope3000 series PC Oscilloscope + 1007 PicoScope 2000 series PC Oscilloscope + 1008 PicoScope 5000 series PC Oscilloscope + 1009 PicoScope 4000 series PC Oscilloscope + 100e PicoScope 6000 series PC Oscilloscope + 1012 PicoScope 3000A series PC Oscilloscope + 1016 PicoScope 2000A series PC Oscilloscope + 1018 PicoScope 4000A series PC Oscilloscope + 1200 PicoScope 2000 series PC Oscilloscope + 1201 PicoScope 3000 series PC Oscilloscope + 1202 PicoScope 4000 series PC Oscilloscope + 1203 PicoScope 5000 series PC Oscilloscope + 1204 PicoScope 6000 series PC Oscilloscope + 1211 PicoScope 3000 series PC Oscilloscope + 1212 PicoScope 4000 series PC Oscilloscope +0cf1 e-Conn Electronic Co., Ltd +0cf2 ENE Technology, Inc. + 6220 SD Card Reader (SG361) + 6225 SD card reader (UB6225) + 6230 SD Card Reader (UB623X) + 6250 SD card reader (UB6250) +0cf3 Qualcomm Atheros Communications + 0001 AR5523 + 0002 AR5523 (no firmware) + 0003 AR5523 + 0004 AR5523 (no firmware) + 0005 AR5523 + 0006 AR5523 (no firmware) + 1001 Thomson TG121N [Atheros AR9001U-(2)NG] + 1002 TP-Link TL-WN821N v2 / TL-WN822N v1 802.11n [Atheros AR9170] + 1006 TP-Link TL-WN322G v3 / TL-WN422G v2 802.11g [Atheros AR9271] + 1010 3Com 3CRUSBN275 802.11abgn Wireless Adapter [Atheros AR9170] + 20ff AR7010 (no firmware) + 3000 AR3011 Bluetooth (no firmware) + 3002 AR3011 Bluetooth + 3004 AR3012 Bluetooth 4.0 + 3005 AR3011 Bluetooth + 3007 AR3012 Bluetooth 4.0 (no firmware) + 3008 Bluetooth (AR3011) + 311f AR3012 Bluetooth + 7015 TP-Link TL-WN821N v3 / TL-WN822N v2 802.11n [Atheros AR7010+AR9287] + 9170 AR9170 802.11n + 9271 AR9271 802.11n + b002 Ubiquiti WiFiStation 802.11n [Atheros AR9271] + b003 Ubiquiti WiFiStationEXT 802.11n [Atheros AR9271] + e006 Dell Wireless 1802 Bluetooth 4.0 LE +0cf4 Fomtex Corp. +0cf5 Cellink Co., Ltd +0cf6 Compucable Corp. +0cf7 ishoni Networks +0cf8 Clarisys, Inc. + 0750 Claritel-i750 - vp +0cf9 Central System Research Co., Ltd +0cfa Inviso, Inc. +0cfc Minolta-QMS, Inc. + 2301 Magicolor 2300 DL + 2350 Magicolor 2350EN/3300 + 3100 Magicolor 3100 + 7300 Magicolor 5450/5550 +0cff SAFA MEDIA Co., Ltd. + 0320 SR-380N +0d06 telos EDV Systementwicklung GmbH +0d08 UTStarcom + 0602 DV007 [serial] + 0603 DV007 [storage] +0d0b Contemporary Controls +0d0c Astron Electronics Co., Ltd +0d0d MKNet Corp. +0d0e Hybrid Networks, Inc. +0d0f Feng Shin Cable Co., Ltd +0d10 Elastic Networks + 0001 StormPort (WDM) +0d11 Maspro Denkoh Corp. +0d12 Hansol Electronics, Inc. +0d13 BMF Corp. +0d14 Array Comm, Inc. +0d15 OnStream b.v. +0d16 Hi-Touch Imaging Technologies Co., Ltd + 0001 PhotoShuttle + 0002 Photo Printer 730 series + 0004 Photo Printer 63xPL/PS + 000e P910L + 0100 Photo Printer 63xPL/PS + 0102 Photo Printer 64xPS + 0103 Photo Printer 730 series + 0104 Photo Printer 63xPL/PS + 0105 Photo Printer 64xPS + 0200 Photo Printer 64xDL +0d17 NALTEC, Inc. +0d18 coaXmedia +0d19 Hank Connection Industrial Co., Ltd +0d28 NXP + 0204 ARM mbed +0d32 Leo Hui Electric Wire & Cable Co., Ltd +0d33 AirSpeak, Inc. +0d34 Rearden Steel Technologies +0d35 Dah Kun Co., Ltd +0d3a Posiflex Technologies, Inc. + 0206 Series 3xxx Cash Drawer + 0207 Series 3xxx Cash Drawer + 0500 Magnetic Stripe Reader +0d3c Sri Cable Technology, Ltd +0d3d Tangtop Technology Co., Ltd + 0001 HID Keyboard + 0040 PS/2 Adapter +0d3e Fitcom, inc. +0d3f MTS Systems Corp. +0d40 Ascor, Inc. +0d41 Ta Yun Terminals Industrial Co., Ltd +0d42 Full Der Co., Ltd +0d46 Kobil Systems GmbH + 2012 KAAN Standard Plus (Smartcard reader) + 3003 mIDentity Light / KAAN SIM III + 3014 Smart Token + 4000 mIDentity (mass storage) + 4001 mIDentity Basic/Classic (composite device) + 4081 mIDentity Basic/Classic (installationless) +0d48 Promethean Limited + 0001 ACTIVboard + 0004 ACTIVboard + 0100 Audio +0d49 Maxtor + 3000 Drive + 3010 3000LE Drive + 3100 Hi-Speed USB-IDE Bridge Controller + 3200 Personal Storage 3200 + 5000 5000XT Drive + 5010 5000LE Drive + 5020 Mobile Hard Disk Drive + 7000 OneTouch + 7010 OneTouch + 7100 OneTouch II 300GB External Hard Disk + 7310 OneTouch 4 + 7410 Mobile Hard Disk Drive (1TB) + 7450 Basics Portable USB Device +0d4a NF Corp. +0d4b Grape Systems, Inc. +0d4c Tedas AG +0d4d Coherent, Inc. +0d4e Agere Systems Netherland BV + 047a WLAN Card + 1000 Wireless Card Model 0801 + 1001 Wireless Card Model 0802 +0d4f EADS Airbus France +0d50 Cleware GmbH + 0011 USB-Temp2 Thermometer + 0040 F4 foot switch +0d51 Volex (Asia) Pte., Ltd +0d53 HMI Co., Ltd +0d54 Holon Corp. +0d55 ASKA Technologies, Inc. +0d56 AVLAB Technology, Inc. +0d57 Solomon Microtech, Ltd +0d5c SMC Networks, Inc. + a001 SMC2662W (v1) EZ Connect 802.11b Wireless Adapter [Atmel AT76C503A] + a002 SMC2662W v2 / SMC2662W-AR / Belkin F5D6050 [Atmel at76c503a] +0d5e Myacom, Ltd + 2346 BT Digital Access adapter +0d5f CSI, Inc. +0d60 IVL Technologies, Ltd +0d61 Meilu Electronics (Shenzhen) Co., Ltd +0d62 Darfon Electronics Corp. + 0003 Smartcard Reader + 0004 Keyboard + 001b Keyboard + 001c Benq X120 Internet Keyboard Pro + 0306 M530 Mouse + 0800 Magic Wheel + 2021 AM805 Keyboard + 2026 TECOM Bluetooth Device + 2050 Mouse + 2106 Dell L20U Multimedia Keyboard + a100 Optical Mouse +0d63 Fritz Gegauf AG +0d64 DXG Technology Corp. + 0105 Dual Mode Digital Camera 1.3M + 0107 Horus MT-409 Camera + 0108 Dual Mode Digital Camera + 0202 Dual Mode Video Camera Device + 0303 DXG-305V Camera + 1001 SiPix Stylecam/UMAX AstraPix 320s + 1002 Fashion Cam 01 Dual-Mode DSC (Video Camera) + 1003 Fashion Cam Dual-Mode DSC (Controller) + 1021 D-Link DSC 350F + 1208 Dual Mode Still Camera Device + 2208 Mass Storage + 3105 Dual Mode Digital Camera Disk + 3108 Digicam Mass Storage Device + 5566 Contour Roam Model 1600 +0d65 KMJP Co., Ltd +0d66 TMT +0d67 Advanet, Inc. +0d68 Super Link Electronics Co., Ltd +0d69 NSI +0d6a Megapower International Corp. +0d6b And-Or Logic +0d70 Try Computer Co., Ltd +0d71 Hirakawa Hewtech Corp. +0d72 Winmate Communication, Inc. +0d73 Hit's Communications, Inc. +0d76 MFP Korea, Inc. +0d77 Power Sentry/Newpoint +0d78 Japan Distributor Corp. +0d7a MARX Datentechnik GmbH + 0001 CrypToken +0d7b Wellco Technology Co., Ltd +0d7c Taiwan Line Tek Electronic Co., Ltd +0d7d Phison Electronics Corp. + 0100 PS1001/1011/1006/1026 Flash Disk + 0110 Gigabyte FlexDrive + 0120 Disk Pro 64MB + 0124 GIGABYTE Disk + 0240 I/O-Magic/Transcend 6-in-1 Card Reader + 110e NEC uPD720121/130 USB-ATA/ATAPI Bridge + 1240 Apacer 6-in-1 Card Reader 2.0 + 1270 Wolverine SixPac 6000 + 1300 Flash Disk + 1320 PS2031 Flash Disk + 1400 Attache 256MB USB 2.0 Flash Drive + 1420 PS2044 Pen Drive + 1470 Vosonic X's-Drive II+ VP2160 + 1620 USB Disk Pro + 1900 USB Thumb Drive +0d7e American Computer & Digital Components + 2507 Hi-Speed USB-to-IDE Bridge Controller + 2517 Hi-Speed Mass Storage Device + 25c7 Hi-Speed USB-to-IDE Bridge Controller +0d7f Essential Reality LLC + 0100 P5 Glove glove controller +0d80 H.R. Silvine Electronics, Inc. +0d81 TechnoVision +0d83 Think Outside, Inc. +0d87 Dolby Laboratories Inc. +0d89 Oz Software +0d8a King Jim Co., Ltd + 0101 TEPRA PRO +0d8b Ascom Telecommunications, Ltd +0d8c C-Media Electronics, Inc. + 0001 Audio Device + 0002 Composite Device + 0003 Sound Device + 0005 Blue Snowball + 0006 Storm HP-USB500 5.1 Headset + 000c Audio Adapter + 000d Composite Device + 000e Audio Adapter (Planet UP-100, Genius G-Talk) + 0014 Audio Adapter (Unitek Y-247A) + 001f CM108 Audio Controller + 0102 CM106 Like Sound Device + 0103 CM102-A+/102S+ Audio Controller + 0104 CM103+ Audio Controller + 0105 CM108 Audio Controller + 0107 CM108 Audio Controller + 010f CM108 Audio Controller + 0115 CM108 Audio Controller + 0139 Multimedia Headset [Gigaware by Ignition L.P.] + 013c CM108 Audio Controller + 0201 CM6501 + 5000 Mass Storage Controller + 5200 Mass Storage Controller(0D8C,5200) + b213 USB Phone CM109 (aka CT2000,VPT1000) +0d8d Promotion & Display Technology, Ltd + 0234 V-234 Composite Device + 0550 V-550 Composite Device + 0551 V-551 Composite Device + 0552 V-552 Composite Device + 0651 V-651 Composite Device + 0652 V-652 Composite Device + 0653 V-653 Composite Device + 0654 V-654 Composite Device + 0655 V-655 Composite Device + 0656 V-656 Composite Device + 0657 V-657 Composite Device + 0658 V-658 Composite Device + 0659 V-659 Composite Device + 0660 V-660 Composite Device + 0661 V-661 Composite Device + 0662 V-662 Composite Device + 0850 V-850 Composite Device + 0851 V-851 Composite Device + 0852 V-852 Composite Device + 0901 V-901 Composite Device + 0902 V-902 Composite Device + 0903 V-903 Composite Device + 4754 Voyager DMP Composite Device + bb00 Bloomberg Composite Device + bb01 Bloomberg Composite Device + bb02 Bloomberg Composite Device + bb03 Bloomberg Composite Device + bb04 Bloomberg Composite Device + bb05 Bloomberg Composite Device + fffe Global Tuner Composite Device + ffff Voyager DMP Composite Device +0d8e Global Sun Technology, Inc. + 0163 802.11g 54 Mbps Wireless Dongle + 1621 802.11b Wireless Adapter + 3762 Cohiba 802.11g Wireless Mini adapter [Intersil ISL3887] + 3763 802.11g Wireless dongle + 7100 802.11b Adapter + 7110 WL-210 / WU210P 802.11b Wireless Adapter [Atmel AT76C503A] + 7605 TRENDnet TEW-224UB 802.11b Wireless Adapter [Atmel AT76C503A] + 7801 AR5523 + 7802 AR5523 (no firmware) + 7811 AR5523 + 7812 AR5523 (no firmware) + 7a01 PRISM25 802.11b Adapter +0d8f Pitney Bowes +0d90 Sure-Fire Electrical Corp. +0d96 Skanhex Technology, Inc. + 0000 Jenoptik JD350 video + 3300 SX330z Camera + 4100 SX410z Camera + 4102 MD 9700 Camera + 4104 Jenoptik JD-4100z3s + 410a Medion 9801/Novatech SX-410z + 5200 SX-520z Camera +0d97 Santa Barbara Instrument Group + 0001 SBIG Astronomy Camera (without firmware) + 0101 SBIG Astronomy Camera (with firmware) +0d98 Mars Semiconductor Corp. + 0300 Avaya Wireless Card + 1007 Discovery Kids Digital Camera +0d99 Trazer Technologies, Inc. +0d9a RTX AS + 0001 Bluetooth Device +0d9b Tat Shing Electrical Co. +0d9c Chee Chen Hi-Technology Co., Ltd +0d9d Sanwa Supply, Inc. +0d9e Avaya + 0300 Wireless Card +0d9f Powercom Co., Ltd + 0001 Uninterruptible Power Supply + 0002 Black Knight PRO / WOW Uninterruptible Power Supply (Cypress HID->COM RS232) + 00a2 Imperial Uninterruptible Power Supply (HID PDC) + 00a3 Smart King PRO Uninterruptible Power Supply (HID PDC) + 00a4 WOW Uninterruptible Power Supply (HID PDC) + 00a5 Vanguard Uninterruptible Power Supply (HID PDC) + 00a6 Black Knight PRO Uninterruptible Power Supply (HID PDC) +0da0 Danger Research +0da1 Suzhou Peter's Precise Industrial Co., Ltd +0da2 Land Instruments International, Ltd +0da3 Nippon Electro-Sensory Devices Corp. +0da4 Polar Electro Oy + 0001 Interface + 0008 Loop +0da7 IOGear, Inc. +0da8 softDSP Co., Ltd + 0001 SDS 200A Oscilloscope +0dab Cubig Group + 0100 DVR/CVR-M140 MP3 Player +0dad Westover Scientific +0db0 Micro Star International + 1020 PC2PC WLAN Card + 1967 Bluetooth Dongle + 3713 Primo 73 + 3801 Motorola Bluetooth 2.1+EDR Device + 3870 MS-3870 802.11bgn Wireless Module [Ralink RT3070] + 3871 MS-3871 802.11bgn Wireless Module [Ralink RT8070] + 4011 Medion Flash XL V2.0 Card Reader + 4023 Lexar Mobile Card Reader + 4600 802.11b/g Turbo Wireless Adapter + 5501 Mass Storage Device + 5502 Mass Storage Device + 5513 MP3 Player + 5515 MP3 Player + 5516 MP3 Player + 5580 Mega Sky 580 DVB-T Tuner [M902x] + 5581 Mega Sky 580 DVB-T Tuner [GL861] + 6823 UB11B/MS-6823 802.11b Wi-Fi adapter + 6826 IEEE 802.11g Wireless Network Adapter + 6855 Bluetooth Device + 6861 MSI-6861 802.11g WiFi adapter + 6865 RT2570 + 6869 RT2570 + 6874 RT2573 + 6877 RT2573 + 6881 Bluetooth Class I EDR Device + 688a Bluetooth Class I EDR Device + 6899 802.11bgn 1T1R Mini Card Wireless Adapter + 6970 MS-6970 BToes Bluetooth adapter + 697a Bluetooth Dongle + 6982 Medion Flash XL Card Reader + a861 RT2573 + a874 RT2573 + a970 Bluetooth dongle + a97a Bluetooth EDR Device + b970 Bluetooth EDR Device + b97a Bluetooth EDR Device +0db1 Wen Te Electronics Co., Ltd +0db2 Shian Hwi Plug Parts, Plastic Factory +0db3 Tekram Technology Co., Ltd +0db4 Chung Fu Chen Yeh Enterprise Corp. +0db5 Access IS + 0139 Barcode Module - CDC serial + 013a Barcode Module - Virtual Keyboard + 013b Barcode Module - HID + 0160 NFC and Smartcard Module (NSM) +0db7 ELCON Systemtechnik + 0002 Goldpfeil P-LAN +0dba Digidesign + 1000 Mbox 1 [Mbox] + 3000 Mbox 2 + b011 Eleven Rack +0dbc A&D Medical + 0003 AND Serial Cable [AND Smart Cable] +0dbe Jiuh Shiuh Precision Industry Co., Ltd +0dbf Jess-Link International + 0002 SmartDongle Security Key + 0200 HDD Storage Solution + 021b USB-2.0 IDE Adapter + 0300 Storage Adapter + 0333 Storage Adapter + 0502 FSC Storagebird XL hard disk + 0707 ZIV Drive +0dc0 G7 Solutions (formerly Great Notions) +0dc1 Tamagawa Seiki Co., Ltd +0dc3 Athena Smartcard Solutions, Inc. + 0801 ASEDrive III + 0802 ASEDrive IIIe + 1104 ASEDrive IIIe KB + 1701 ASEKey + 1702 ASEKey +0dc4 inXtron, Inc. + 0040 Mass Storage Device + 0041 Mass Storage Device + 0042 Mass Storage Device + 0101 Hi-Speed Mass Storage Device + 0209 SK-3500 S2 + 020a Oyen Digital MiniPro 2.5" hard drive enclosure +0dc5 SDK Co., Ltd +0dc6 Precision Squared Technology Corp. + 2301 Wireless Touchpad Keyboard +0dc7 First Cable Line, Inc. +0dcd NetworkFab Corp. + 0001 Remote Interface Adapter + 0002 High Bandwidth Codec +0dd0 Access Solutions + 1002 Triple Talk Speech Synthesizer +0dd1 Contek Electronics Co., Ltd +0dd2 Power Quotient International Co., Ltd + 0003 Mass Storage (P) +0dd3 MediaQ +0dd4 Custom Engineering SPA +0dd5 California Micro Devices +0dd7 Kocom Co., Ltd +0dd8 Netac Technology Co., Ltd + 1060 USB-CF-Card + e007 OnlyDisk U222 Pendrive + f607 OnlyDisk U208 1G flash drive [U-SAFE] +0dd9 HighSpeed Surfing +0dda Integrated Circuit Solution, Inc. + 0001 Multi-Card Reader 6in1 + 0002 Multi-Card Reader 7in1 + 0003 Flash Disk + 0005 Internal Multi-Card Reader 6in1 + 0008 SD single card reader + 0009 MS single card reader + 000a MS+SD Dual Card Reader + 000b SM single card reader + 0101 All-In-One Card Reader + 0102 All-In-One Card Reader + 0301 MP3 Player + 0302 Multi-Card MP3 Player + 1001 Multi-Flash Disk + 2001 Multi-Card Reader + 2002 Q018 default PID + 2003 Multi-Card Reader + 2005 Datalux DLX-1611 16in1 Card Reader + 2006 All-In-One Card Reader + 2007 USB to ATAPI bridge + 2008 All-In-One Card Reader + 2013 SD/MS Combo Card Reader + 2014 SD/MS Single Card Reader + 2023 card reader SD/MS DEMO board with ICSI brand name (MaskROM version) + 2024 card reader SD/MS DEMO board with Generic brand name (MaskROM version) + 2026 USB2.0 Card Reader + 2027 USB 2.0 Card Reader + 2315 UFD MP3 player (model 2) + 2318 UFD MP3 player (model 1) + 2321 UFD MP3 player +0ddb Tamarack, Inc. +0ddd Datelink Technology Co., Ltd +0dde Ubicom, Inc. +0de0 BD Consumer Healthcare +0de7 USBmicro + 0191 U401 Interface card + 01a5 U421 interface card + 01c3 U451 relay interface card +0dea UTECH Electronic (D.G.) Co., Ltd. +0ded Novasonics +0dee Lifetime Memory Products + 4010 Storage Adapter +0def Full Rise Electronic Co., Ltd +0df4 NET&SYS + 0201 MNG-2005 +0df6 Sitecom Europe B.V. + 0001 C-Media VOIP Device + 0004 Bluetooth 2.0 Adapter 100m + 0007 Bluetooth 2.0 Adapter 10m + 000b Bluetooth 2.0 Adapter DFU + 000d WL-168 Wireless Network Adapter 54g + 0017 WL-182 Wireless-N Network USB Card + 0019 Bluetooth 2.0 adapter 10m CN-512v2 001 + 001a Bluetooth 2.0 adapter 100m CN-521v2 001 + 002b WL-188 Wireless Network 300N USB Adapter + 002c WL-301 Wireless Network 300N USB Adapter + 002d WL-302 Wireless Network 300N USB dongle + 0036 WL-603 Wireless Adapter + 0039 WL-315 Wireless-N USB Adapter + 003b WL-321 Wireless USB Gaming Adapter 300N + 003c WL-323 Wireless-N USB Adapter + 003d WL-324 Wireless USB Adapter 300N + 003e WL-343 Wireless USB Adapter 150N X1 + 003f WL-608 Wireless USB Adapter 54g + 0040 WL-344 Wireless Adapter 300N X2 [Ralink RT3071] + 0041 WL-329 Wireless Dualband USB adapter 300N + 0042 WL-345 Wireless USB adapter 300N X3 + 0045 WL-353 Wireless USB Adapter 150N Nano + 0047 WL-352v1 Wireless USB Adapter 300N 002 + 0048 WL-349v1 Wireless Adapter 150N 002 [Ralink RT3070] + 0049 WL-356 Wireless Adapter 300N + 004a WL-358v1 Wireless Micro USB Adapter 300N X3 002 + 004b WL-349v3 Wireless Micro Adapter 150N X1 [Realtek RTL8192SU] + 004c WL-352 802.11n Adapter [Realtek RTL8191SU] + 0050 WL-349v4 Wireless Micro Adapter 150N X1 [Ralink RT3370] + 0056 LN-031 10/100/1000 Ethernet Adapter + 005d WLA-2000 v1.001 WLAN [RTL8191SU] + 0060 WLA-4000 802.11bgn [Ralink RT3072] + 0062 WLA-5000 802.11abgn [Ralink RT3572] + 006f WLA-5100 + 0072 AX88179 Gigabit Ethernet [Sitecom] + 061c LN-028 Network USB 2.0 Adapter + 214a IDE/SATA Combo Adapter [CN-330] + 21f4 44 St Bluetooth Device + 2200 Sitecom bluetooth2.0 class 2 dongle CN-512 + 2208 Sitecom bluetooth2.0 class 2 dongle CN-520 + 2209 Sitecom bluetooth2.0 class 1 dongle CN-521 + 3068 DC-104v2 ISDN Adapter [HFC-S] + 9071 WL-113 rev 1 Wireless Network USB Adapter + 9075 WL-117 Hi-Speed USB Adapter + 90ac WL-172 Wireless Network USB Adapter 54g Turbo + 9712 WL-113 rev 2 Wireless Network USB Adapter +0df7 Mobile Action Technology, Inc. + 0620 MA-620 Infrared Adapter + 0700 MA-700 Bluetooth Adapter + 0720 MA-720 Bluetooth Adapter + 0722 Bluetooth Dongle + 0730 MA-730/MA-730G Bluetooth Adapter + 0800 Data Cable + 0820 Data Cable + 0900 MA i-gotU Travel Logger GPS + 1800 Generic Card Reader + 1802 Card Reader +0dfa Toyo Communication Equipment Co., Ltd +0dfc GeneralTouch Technology Co., Ltd + 0001 Touchscreen + 0101 5-point Touch Screen +0e03 Nippon Systemware Co., Ltd +0e08 Winbest Technology Co., Ltd +0e0b Amigo Technology Inc. + 9031 802.11n Wireless USB Card + 9041 802.11n Wireless USB Card +0e0c Gesytec + 0101 LonUSB LonTalk Network Adapter +0e0d PicoQuant GmbH + 0003 PicoHarp 300 +0e0f VMware, Inc. + 0001 Device + 0002 Virtual USB Hub + 0003 Virtual Mouse + 0004 Virtual CCID + 0005 Virtual Mass Storage + 0006 Virtual Keyboard + 8001 Root Hub + 8002 Root Hub + 8003 Root Hub + f80a Smoker FX2 +0e16 JMTek, LLC +0e17 Walex Electronic, Ltd +0e1a Unisys +0e1b Crewave +0e20 Pegasus Technologies Ltd. + 0101 NoteTaker + 0200 Seiko Instruments InkLink Handwriting System +0e21 Cowon Systems, Inc. + 0300 iAudio CW200 + 0400 MP3 Player + 0500 iAudio M3 + 0510 iAudio X5, subpack USB port + 0513 iAudio X5, side USB port + 0520 iAudio M5, side USB port + 0601 iAudio G3 + 0681 iAUDIO E2 + 0700 iAudio U3 + 0751 iAudio 7 + 0760 iAUDIO U5 / iAUDIO G2 + 0800 Cowon D2 (UMS mode) + 0801 Cowon D2 (MTP mode) + 0910 iAUDIO 9 + 0920 J3 +0e22 Symbian Ltd. +0e23 Liou Yuane Enterprise Co., Ltd +0e25 VinChip Systems, Inc. +0e26 J-Phone East Co., Ltd +0e30 HeartMath LLC +0e34 Micro Computer Control Corp. +0e35 3Pea Technologies, Inc. +0e36 TiePie engineering + 0009 Handyscope HS3 + 000b Handyscope HS4 + 000f Handyscope HS4-DIFF (br) + 0010 Handyscope HS2 + 0011 TiePieSCOPE HS805 (br) + 0012 TiePieSCOPE HS805 + 0013 Handyprobe HP3 + 0014 Handyprobe HP3 + 0018 Handyprobe HP2 + 001b Handyscope HS5 + 0042 TiePieSCOPE HS801 + 00fd USB To Parallel adapter + 00fe USB To Parallel adapter +0e38 Stratitec, Inc. +0e39 Smart Modular Technologies, Inc. + 0137 Bluetooth Device +0e3a Neostar Technology Co., Ltd + 1100 CW-1100 Wireless Network Adapter +0e3b Mansella, Ltd +0e41 Line6, Inc. + 4147 TonePort GX + 414d Pod HD500 + 4156 POD HD Desktop + 4250 BassPODxt + 4252 BassPODxt Pro + 4642 BassPODxt Live + 4650 PODxt Live + 4750 GuitarPort + 5044 PODxt + 5050 PODxt Pro + 534d SeaMonkey +0e44 Sun-Riseful Technology Co., Ltd. +0e48 Julia Corp., Ltd + 0100 CardPro SmartCard Reader +0e4a Shenzhen Bao Hing Electric Wire & Cable Mfr. Co. +0e4c Radica Games, Ltd + 1097 Gamester Controller + 2390 Games Jtech Controller + 7288 funkey reader +0e50 TechnoData Interware + 0001 Matrix USB-Key + 0002 Matrixlock Dongle (HID) +0e55 Speed Dragon Multimedia, Ltd + 110a Tanic S110-SG1 + ISSC IS1002N [Slow Infra-Red (SIR) & Bluetooth 1.2 (Class 2) Adapter] + 110b MS3303H USB-to-Serial Bridge +0e56 Kingston Technology Company, Inc. + 6021 K-PEX 100 +0e5a Active Co., Ltd +0e5b Union Power Information Industrial Co., Ltd +0e5c Bitland Information Technology Co., Ltd + 6118 LCD Device + 6119 remote receive and control device + 6441 C-Media Sound Device +0e5d Neltron Industrial Co., Ltd +0e5e Conwise Technology Co., Ltd. + 6622 CW6622 +0e66 Hawking Technologies + 0001 HWUN1 Hi-Gain Wireless-300N Adapter w/ Upgradable Antenna [Ralink RT2870] + 0003 HWDN1 Hi-Gain Wireless-300N Dish Adapter [Ralink RT2870] + 0009 HWUN2 Hi-Gain Wireless-150N Adapter w/ Upgradable Antenna [Ralink RT2770] + 000b HWDN2 Hi-Gain Wireless-150N Dish Adapter [Ralink RT2770] + 0013 HWUN3 Hi-Gain Wireless-N Adapter [Ralink RT3070] + 0015 HWDN2 Rev. E Hi-Gain Wireless-150N Dish Adapter [Realtek RTL8191SU] + 0017 HAWNU1 Hi-Gain Wireless-150N Network Adapter with Range Amplifier [Ralink RT3070] + 0018 Wireless-N Network Adapter [Ralink RT2870] + 400b UF100 10/100 Network Adapter + 400c UF100 Ethernet [pegasus2] +0e67 Fossil, Inc. + 0002 Wrist PDA +0e6a Megawin Technology Co., Ltd + 0101 MA100 [USB-UART Bridge IC] + 030b Truly Ergonomic Computer Keyboard (Device Firmware Update mode) + 030c Truly Ergonomic Computer Keyboard + 6001 GEMBIRD Flexible keyboard KB-109F-B-DE + 7f5c BPF-015 Key Chain Photo Frame +0e6f Logic3 + 0003 Freebird wireless Controller + 0005 Eclipse wireless Controller + 0006 Edge wireless Controller + 0128 Wireless PS3 Controller +0e70 Tokyo Electronic Industry Co., Ltd +0e72 Hsi-Chin Electronics Co., Ltd +0e75 TVS Electronics, Ltd +0e79 Archos, Inc. + 1106 Pocket Media Assistant - PMA400 + 1204 Gmini XS 200 + 1306 504 Portable Multimedia Player + 1330 5 Tablet + 1332 5 IMT + 1416 32 IT + 1417 A43 IT + 14ad 97 Titanium HD + 150e 80 G9 + 3001 40 Titanium +0e7b On-Tech Industry Co., Ltd +0e7e Gmate, Inc. + 0001 Yopy 3000 PDA + 1001 YP3X00 PDA +0e82 Ching Tai Electric Wire & Cable Co., Ltd +0e83 Shin An Wire & Cable Co. +0e8c Well Force Electronic Co., Ltd +0e8d MediaTek Inc. + 0003 MT6227 phone + 0004 MT6227 phone + 0023 S103 + 00a5 GSM modem [Medion Surfstick Model:S4222] + 1806 Samsung SE-208 Slim Portable DVD Writer + 1836 Samsung SE-S084 Super WriteMaster Slim External DVD writer + 1956 Samsung SE-506 Portable BluRay Disc Writer + 2000 MT65xx Preloader + 3329 Qstarz BT-Q1000XT + 763e MT7630e Bluetooth Adapter +0e8f GreenAsia Inc. + 0003 MaxFire Blaze2 + 0012 Joystick/Gamepad + 0016 4 port USB 1.1 hub UH-174 + 0020 USB to PS/2 Adapter + 0021 Multimedia Keyboard Controller + 0022 multimedia keyboard controller + 0201 SmartJoy Frag Xpad/PS2 adaptor + 300a steering Wheel +0e90 WiebeTech, LLC + 0100 Storage Adapter V1 +0e91 VTech Engineering Canada, Ltd +0e92 C's Glory Enterprise Co., Ltd +0e93 eM Technics Co., Ltd +0e95 Future Technology Co., Ltd +0e96 Aplux Communications, Ltd + c001 TRUST 380 USB2 SPACEC@M +0e97 Fingerworks, Inc. + 0908 Composite HID (Keyboard and Mouse) +0e98 Advanced Analogic Technologies, Inc. +0e99 Parallel Dice Co., Ltd +0e9a TA HSING Industries, Ltd +0e9b ADTEC Corp. +0e9c Streamzap, Inc. + 0000 Streamzap Remote Control +0e9f Tamura Corp. +0ea0 Ours Technology, Inc. + 2126 7-in-1 Card Reader + 2153 SD Card Reader Key + 2168 Transcend JetFlash 2.0 / Astone USB Drive / Intellegent Stick 2.0 + 6803 OTI-6803 Flash Disk + 6808 OTI-6808 Flash Disk + 6828 OTI-6828 Flash Disk + 6858 OTi-6858 serial adapter +0ea6 Nihon Computer Co., Ltd +0ea7 MSL Enterprises Corp. +0ea8 CenDyne, Inc. +0ead Humax Co., Ltd +0eb0 NovaTech + 9020 NovaTech NV-902W + 9021 RT2573 +0eb1 WIS Technologies, Inc. + 6666 WinFast WalkieTV TV Loader + 6668 WinFast WalkieTV TV Loader + 7007 WinFast WalkieTV WDM Capture +0eb2 Y-S Electronic Co., Ltd +0eb3 Saint Technology Corp. +0eb7 Endor AG +0eb8 Mettler Toledo + 2200 Ariva Scale + f000 PS60 Scale +0ebb Thermo Fisher Scientific + 0002 FT-IR Spectrometer +0ebe VWeb Corp. +0ebf Omega Technology of Taiwan, Inc. +0ec0 LHI Technology (China) Co., Ltd +0ec1 Abit Computer Corp. +0ec2 Sweetray Industrial, Ltd +0ec3 Axell Co., Ltd +0ec4 Ballracing Developments, Ltd +0ec5 GT Information System Co., Ltd +0ec6 InnoVISION Multimedia, Ltd +0ec7 Theta Link Corp. + 1008 So., Show 301 Digital Camera +0ecd Lite-On IT Corp. + 1400 CD\RW 40X + a100 LDW-411SX DVD/CD Rewritable Drive +0ece TaiSol Electronics Co., Ltd +0ecf Phogenix Imaging, LLC +0ed1 WinMaxGroup + 6660 Flash Disk 64M-C + 6680 Flash Disk 64M-B + 7634 MP3 Player +0ed2 Kyoto Micro Computer Co., Ltd +0ed3 Wing-Tech Enterprise Co., Ltd +0ed5 Fiberbyte + e000 USB-inSync Device + f000 Fiberbyte USB-inSync Device + f201 Fiberbyte USB-inSync DAQ-2500X +0eda Noriake Itron Corp. +0edf e-MDT Co., Ltd + 2060 FID irock! 100 Series +0ee0 Shima Seiki Mfg., Ltd +0ee1 Sarotech Co., Ltd +0ee2 AMI Semiconductor, Inc. +0ee3 ComTrue Technology Corp. + 1000 Image Tank 1.5 +0ee4 Sunrich Technology, Ltd + 0690 SATA 3 Adapter +0eee Digital Stream Technology, Inc. + 8810 Mass Storage Drive +0eef D-WAV Scientific Co., Ltd + 0001 eGalax TouchScreen + 0002 Touchscreen Controller(Professional) + 7200 Touchscreen Controller + a802 eGalaxTouch EXC7920 +0ef0 Hitachi Cable, Ltd +0ef1 Aichi Micro Intelligent Corp. +0ef2 I/O Magic Corp. +0ef3 Lynn Products, Inc. +0ef4 DSI Datotech +0ef5 PointChips + 2202 Flash Disk + 2366 Flash Disk +0ef6 Yield Microelectronics Corp. +0ef7 SM Tech Co., Ltd (Tulip) +0efd Oasis Semiconductor +0efe Wem Technology, Inc. +0f03 Unitek UPS Systems + 0001 Alpha 1200Sx +0f06 Visual Frontier Enterprise Co., Ltd +0f08 CSL Wire & Plug (Shen Zhen) Co. +0f0c CAS Corp. +0f0d Hori Co., Ltd + 0011 Real Arcade Pro 3 +0f0e Energy Full Corp. +0f0f Silego Technology Inc + 0006 GreenPak Universal Dev Board (Active Mode) + 8006 GreenPak Universal Dev Board (Reset Mode) +0f11 LD Didactic GmbH + 1000 CASSY-S + 1010 Pocket-CASSY + 1020 Mobile-CASSY + 1080 Joule and Wattmeter + 1081 Digital Multimeter P + 1090 UMI P + 1100 X-Ray Apparatus + 1101 X-Ray Apparatus + 1200 VideoCom + 2000 COM3LAB + 2010 Terminal Adapter + 2020 Network Analyser + 2030 Converter Control Unit + 2040 Machine Test System +0f12 Mars Engineering Corp. +0f13 Acetek Technology Co., Ltd +0f14 Ingenico + 0012 Vital'Act 3S + 0038 XIRING Smart Card Terminal LEO V2 +0f18 Finger Lakes Instrumentation + 0002 CCD + 0006 Focuser + 0007 Filter Wheel + 000a ProLine CCD + 000b Color Filter Wheel 4 + 000c PDF2 + 000d Guider +0f19 Oracom Co., Ltd +0f1b Onset Computer Corp. +0f1c Funai Electric Co., Ltd +0f1d Iwill Corp. +0f21 IOI Technology Corp. +0f22 Senior Industries, Inc. +0f23 Leader Tech Manufacturer Co., Ltd +0f24 Flex-P Industries, Snd., Bhd. +0f2d ViPower, Inc. +0f2e Geniality Maple Technology Co., Ltd +0f2f Priva Design Services +0f30 Jess Technology Co., Ltd + 001c PS3 Guitar Controller Dongle + 0110 Dual Analog Rumble Pad + 0111 Colour Rumble Pad + 0208 Xbox & PC Gamepad +0f31 Chrysalis Development +0f32 YFC-BonEagle Electric Co., Ltd +0f37 Kokuyo Co., Ltd +0f38 Nien-Yi Industrial Corp. +0f39 TG3 Electronics + 0876 Keyboard [87 Francium Pro] + 1086 DK2108SZ Keyboard [Ducky Zero] +0f3d Airprime, Incorporated + 0112 CDMA 1xEVDO PC Card, PC 5220 +0f41 RDC Semiconductor Co., Ltd +0f42 Nital Consulting Services, Inc. +0f44 Polhemus + ef11 Patriot (firmware not loaded) + ef12 Patriot + ff11 Liberty (firmware not loaded) + ff12 Liberty +0f4b St. John Technology Co., Ltd +0f4c WorldWide Cable Opto Corp. +0f4d Microtune, Inc. + 1000 Bluetooth Dongle +0f4e Freedom Scientific +0f52 Wing Key Electrical Co., Ltd +0f53 Dongguan White Horse Cable Factory, Ltd +0f54 Kawai Musical Instruments Mfg. Co., Ltd + 0101 MP6 Stage Piano +0f55 AmbiCom, Inc. +0f5c Prairiecomm, Inc. +0f5d NewAge International, LLC + 9455 Compact Drive +0f5f Key Technology Corp. +0f60 NTK, Ltd +0f61 Varian, Inc. +0f62 Acrox Technologies Co., Ltd + 1001 Targus Mini Trackball Optical Mouse +0f63 LeapFrog Enterprises + 0010 Leapster Explorer + 0022 Leap Reader + 0500 Fly Fusion + 0600 Leap Port Turbo + 0700 POGO + 0800 Didj + 0900 TAGSchool + 0a00 Leapster 2 + 0b00 Crammer + 0c00 Tag Jr + 0d00 My Pal Scout + 0e00 Tag32 + 0f00 Tag64 + 1000 Kiwi16 + 1100 Leapster L2x + 1111 Fly Fusion + 1300 Didj UK/France (Leapster Advance) +0f68 Kobe Steel, Ltd +0f69 Dionex Corp. +0f6a Vibren Technologies, Inc. +0f6e INTELLIGENT SYSTEMS + 0100 GameBoy Color Emulator + 0201 GameBoy Advance Flash Gang Writer + 0202 GameBoy Advance Capture + 0300 Gamecube DOL Viewer + 0400 NDS Emulator + 0401 NDS UIC + 0402 NDS Writer + 0403 NDS Capture + 0404 NDS Emulator (Lite) +0f73 DFI +0f78 Guntermann & Drunck GmbH +0f7c DQ Technology, Inc. +0f7d NetBotz, Inc. +0f7e Fluke Corp. +0f88 VTech Holdings, Ltd + 3012 RT2570 + 3014 ZD1211B +0f8b Yazaki Corp. +0f8c Young Generation International Corp. +0f8d Uniwill Computer Corp. +0f8e Kingnet Technology Co., Ltd +0f8f Soma Networks +0f97 CviLux Corp. +0f98 CyberBank Corp. +0f9c Hyun Won, Inc. + 0301 M-Any Premium DAH-610 MP3/WMA Player + 0332 mobiBLU DAH-1200 MP3/Ogg Player +0f9e Lucent Technologies +0fa3 Starconn Electronic Co., Ltd +0fa4 ATL Technology +0fa5 Sotec Co., Ltd +0fa7 Epox Computer Co., Ltd +0fa8 Logic Controls, Inc. +0faf Winpoint Electronic Corp. +0fb0 Haurtian Wire & Cable Co., Ltd +0fb1 Inclose Design, Inc. +0fb2 Juan-Chern Industrial Co., Ltd +0fb6 Heber Ltd + 3fc3 Firefly X10i I/O Board (with firmware) + 3fc4 Firefly X10i I/O Board (without firmware) +0fb8 Wistron Corp. + 0002 eHome Infrared Receiver +0fb9 AACom Corp. +0fba San Shing Electronics Co., Ltd +0fbb Bitwise Systems, Inc. +0fc1 Mitac Internatinal Corp. +0fc2 Plug and Jack Industrial, Inc. +0fc5 Delcom Engineering + 1222 I/O Development Board +0fc6 Dataplus Supplies, Inc. +0fca Research In Motion, Ltd. + 0001 Blackberry Handheld + 0004 Blackberry Handheld + 0006 Blackberry Pearl + 0008 Blackberry Pearl + 8001 Blackberry Handheld + 8004 Blackberry + 8007 Blackberry Handheld + 8010 Blackberry Playbook (Connect to Windows mode) + 8011 Blackberry Playbook (Connect to Mac mode) + 8020 Blackberry Playbook (CD-Rom mode) + 8037 Blackberry PRIV +0fce Sony Ericsson Mobile Communications AB + 0076 W910i (Multimedia mode) + 00af V640i Phone [PTP Camera] + 00d4 C902 [MTP] + 00d9 C702 Phone + 0112 W995 Walkman Phone + 014e J108i Cedar (MTP mode) + 015a Xperia Pro [Media Transfer Protocol] + 0166 Xperia Mini Pro + 0167 ST15i (Xperia mini) + 0169 Xperia S + 0172 Xperia P + 0177 Xperia Ion [Mass Storage] + 0188 ST26i + 019c C6833 + 019e C6903 + 01a5 SO-04F + 01a7 D5503 + 01ba D6603 [Xperia Z3] + 01bb D5803 [Xperia Z3 Compact] (MTP mode) + 0dde Xperia Mini Pro Bootloader + 1010 WMC Modem + 10af V640i Phone [PictBridge] + 10d4 C902 Phone [PictBridge] + 2105 W715 Phone + 2137 Xperia X10 mini (USB debug) + 2138 Xperia X10 mini pro (Debug) + 2149 Xperia X8 (debug) + 214e J108i Cedar (Windows-driver mode) + 3137 Xperia X10 mini + 3138 Xperia X10 mini pro + 3149 Xperia X8 + 514f Xperia arc S [Adb-Enable Mode] + 5169 Xperia S [Adb-Enable Mode] + 5177 Xperia Ion [Debug Mode] + 518c C1605 [Xperia E dual] MTD mode + 51a7 D5503 (Xperia Z1 Compact) + 614f Xperia X12 (debug mode) + 6166 Xperia Mini Pro + 618c C1605 [Xperia E dual] MSC mode + 715a Xperia Pro [Tethering] + 7166 Xperia Mini Pro (Tethering mode) + 7177 Xperia Ion [Tethering] + 8004 9000 Phone [Mass Storage] + adde C2005 (Xperia M dual) in service mode + d008 V800-Vodafone 802SE Phone + d016 K750i Phone + d017 K608i Phone + d019 VDC EGPRS Modem + d025 520 WMC Data Modem + d028 W800i + d038 W850i Phone + d039 K800i (phone mode) + d041 K510i Phone + d042 W810i Phone + d043 V630i Phone + d046 K610i Phone + d065 W960i Phone (PC Suite) + d076 W910i (Phone mode) + d089 W580i Phone (mass storage) + d0a1 K810 + d0af V640i Phone + d0cf MD300 Mobile Broadband Modem + d0d4 C902 Phone [Modem] + d0e1 MD400 Mobile Broadband Modem + d12a U100i Yari Phone + d12e Xperia X10 + d14e J108i Cedar (modem mode) + e000 K810 (PictBridge mode) + e039 K800i (msc mode) + e042 W810i Phone + e043 V630i Phone [Mass Storage] + e075 K850i + e076 W910i (Mass storage) + e089 W580i Phone + e090 W200 Phone (Mass Storage) + e0a1 K810 (Mass Storage mode) + e0a3 W660i + e0af V640i Phone [Mass Storage] + e0d4 C902 Phone [Mass Storage] + e0ef C905 Phone [Mass Storage] + e0f3 W595 + e105 W705 + e112 W995 Phone (Mass Storage) + e12e X10i Phone + e133 Vivaz + e14e J108i Cedar (mass-storage mode) + e14f Xperia Arc/X12 + e15a Xperia Pro [Mass Storage Class] + e161 Xperia Ray + e166 Xperia Mini Pro + e167 XPERIA mini + e19b C2005 [Xperia M dual] (Mass Storage) + e1a9 D5303 + e1aa D2303 + e1ad D5103 + e1b0 D6708 + e1b5 D2004 + e1ba D6683 + e1bb SO-02G + e1bc D2203 + e1c0 SGP621 + e1c2 D2533 + e1c9 E6553 + e1cf SGP771 + f0fa MN800 / Smartwatch 2 (DFU mode) +0fcf Dynastream Innovations, Inc. + 1003 ANT Development Board + 1004 ANTUSB Stick + 1006 ANT Development Board + 1008 ANTUSB2 Stick + 1009 ANTUSB-m Stick +0fd0 Tulip Computers B.V. +0fd1 Giant Electronics Ltd. +0fd2 Seac Banche + 0001 RDS 6000 +0fd4 Tenovis GmbH & Co., KG +0fd5 Direct Access Technology, Inc. +0fd9 Elgato Systems GmbH + 0011 EyeTV Diversity + 0018 EyeTV Hybrid + 0020 EyeTV DTT Deluxe + 0021 EyeTV DTT + 002a EyeTV Sat + 002c EyeTV DTT Deluxe v2 + 0033 Video Capture + 0037 Video Capture v2 +0fda Quantec Networks GmbH + 0100 quanton flight control +0fdc Micro Plus +0fde Oregon Scientific + ca01 WMRS200 weather station + ca05 CM160 +0fe0 Osterhout Design Group + 0100 Bluetooth Mouse + 0101 Bluetooth IMU + 0200 Bluetooth Keypad +0fe2 Air Techniques +0fe4 IN-Tech Electronics, Ltd +0fe5 Greenconn (U.S.A.), Inc. +0fe6 ICS Advent + 8101 DM9601 Fast Ethernet Adapter + 811e Parallel Adapter + 9700 DM9601 Fast Ethernet Adapter +0fe9 DVICO + 4020 TViX M-6500 + 9010 FusionRemote IR receiver + db00 FusionHDTV DVB-T (MT352+LgZ201) (uninitialized) + db01 FusionHDTV DVB-T (MT352+LgZ201) (initialized) + db10 FusionHDTV DVB-T (MT352+Thomson7579) (uninitialized) + db11 FusionHDTV DVB-T (MT352+Thomson7579) (initialized) + db78 FusionHDTV DVB-T Dual Digital 4 (ZL10353+xc2028/xc3028) (initialized) +0fea United Computer Accessories +0feb CRS Electronic Co., Ltd +0fec UMC Electronics Co., Ltd +0fed Access Co., Ltd +0fee Xsido Corp. +0fef MJ Research, Inc. +0ff6 Core Valley Co., Ltd +0ff7 CHI SHING Computer Accessories Co., Ltd +0ffc Clavia DMI AB + 0021 Nord Stage 2 +0ffd EarlySense + ff00 OEM +0fff Aopen, Inc. +1000 Speed Tech Corp. + 153b TerraTec Electronic GmbH +1001 Ritronics Components (S) Pte., Ltd +1003 Sigma Corp. + 0003 SD14 + 0100 SD9/SD10 +1004 LG Electronics, Inc. + 1fae U8120 3G Cellphone + 6000 Various Mobile Phones + 6005 T5100 + 6018 GM360/GD510/GW520/KP501 + 618e Ally/Optimus One/Vortex (debug mode) + 618f Ally/Optimus One + 61c5 P880 / Charge only + 61c6 Vortex (msc) + 61cc Optimus S + 61da G2 Android Phone [tethering mode] + 61f1 Optimus Android Phone [LG Software mode] + 61f9 Optimus (Various Models) MTP Mode + 61fc Optimus 3 + 61fe Optimus Android Phone [USB tethering mode] + 627f G3 (VS985) Android Phone (MTP/Download mode) + 6300 G2/Optimus Android Phone [Charge mode] + 631c G2/Optimus Android Phone [MTP mode] + 631d Optimus Android Phone (Camera/PTP Mode) + 631e G2/Optimus Android Phone [Camera/PTP mode] + 631f Optimus Android Phone (Charge Mode) + 633a Ultimate 2 Android Phone L41C + 633e G2/G3 Android Phone [MTP/PTP/Download mode] + 6344 G2 Android Phone [tethering mode] + 6356 Optimus Android Phone [Virtual CD mode] + 6800 CDMA Modem + 7000 LG LDP-7024D(LD)USB + 91c8 P880 / USB tethering + a400 Renoir (KC910) +1005 Apacer Technology, Inc. + 1001 MP3 Player + 1004 MP3 Player + 1006 MP3 Player + b113 Handy Steno/AH123 / Handy Steno 2.0/HT203 + b223 CD-RW + 6in1 Card Reader Digital Storage / Converter +1006 iRiver, Ltd. + 3001 iHP-100 + 3002 iHP-120/140 MP3 Player + 3003 H320/H340 + 3004 H340 (mtp) +1009 Emuzed, Inc. + 000e eHome Infrared Receiver + 0013 Angel MPEG Device + 0015 Lumanate Wave PAL SECAM DVBT Device + 0016 Lumanate Wave NTSC/ATSC Combo Device +100a AV Chaseway, Ltd + 2402 MP3 Player + 2404 MP3 Player + 2405 MP3 Player + 2406 MP3 Player + a0c0 MP3 Player +100b Chou Chin Industrial Co., Ltd +100d Netopia, Inc. + 3342 Cayman 3352 DSL Modem + 3382 3380 Series Network Interface + 6072 DSL Modem + 9031 Motorola 802.11n Dualband USB Wireless Adapter + 9032 Motorola 802.11n 5G USB Wireless Adapter + cb01 Cayman 3341 Ethernet DSL Router +1010 Fukuda Denshi Co., Ltd +1011 Mobile Media Tech. + 0001 AccFast Mp3 +1012 SDKM Fibres, Wires & Cables Berhad +1013 TST-Touchless Sensor Technology AG +1014 Densitron Technologies PLC +1015 Softronics Pty., Ltd +1016 Xiamen Hung's Enterprise Co., Ltd +1017 Speedy Industrial Supplies, Pte., Ltd +1019 Elitegroup Computer Systems (ECS) + 0c55 Flash Reader, Desknote UCR-61S2B + 0f38 Infrared Receiver +1020 Labtec + 0006 Wireless Keyboard + 000a Wireless Optical Mouse + 0106 Wireless Optical Mouse +1022 Shinko Shoji Co., Ltd +1025 Hyper-Paltek + 005e USB DVB-T device + 005f USB DVB-T device + 0300 MP3 Player + 0350 MP3 Player +1026 Newly Corp. +1027 Time Domain +1028 Inovys Corp. +1029 Atlantic Coast Telesys +102a Ramos Technology Co., Ltd +102b Infotronic America, Inc. +102c Etoms Electronics Corp. + 6151 Q-Cam Sangha CIF + 6251 Q-Cam VGA +102d Winic Corp. +1031 Comax Technology, Inc. +1032 C-One Technology Corp. +1033 Nucam Corp. + 0068 3,5'' HDD case MD-231 +1038 SteelSeries ApS + 0100 Ideazon Zboard + 1361 Ideazon Sensei +1039 devolo AG + 0824 1866 802.11bg [Texas Instruments TNETW1450] + 2140 dsl+ 1100 duo +103a PSA + f000 Actia Evo XS +103d Stanton + 0100 ScratchAmp + 0101 ScratchAmp +1043 iCreate Technologies Corp. + 160f Wireless Network Adapter + 4901 AV-836 Video Capture Device + 8006 Flash Disk 32-256 MB + 8012 Flash Disk 256 MB +1044 Chu Yuen Enterprise Co., Ltd + 7001 Gigabyte U7000 DVB-T tuner + 7002 Gigabyte U8000 DVB-T tuner + 7004 Gigabyte U7100 DVB-T tuner + 7005 Gigabyte U7200 DVB-T tuner [AF9035] + 7006 Gigabyte U6000 DVB-T tuner [em2863] + 8001 GN-54G + 8002 GN-BR402W + 8003 GN-WLBM101 + 8004 GN-WLBZ101 802.11b Adapter + 8005 GN-WLBZ201 802.11b Adapter + 8006 GN-WBZB-M 802.11b Adapter + 8007 GN-WBKG + 8008 GN-WB01GS + 800a GN-WI05GS + 800b GN-WB30N 802.11n WLAN Card + 800c GN-WB31N 802.11n USB WLAN Card + 800d GN-WB32L 802.11n USB WLAN Card +1046 Winbond Electronics Corp. [hex] + 6694 Generic W6694 USB + 8901 Bluetooth Device + 9967 W9967CF/W9968CF Webcam IC +1048 Targus Group International + 2010 4-Port hub +104b Mylex / Buslogic +104c AMCO TEC International, Inc. +104d Newport Corporation + 1003 Model-52 LED Light Source Power Supply and Driver +104f WB Electronics + 0001 Infinity Phoenix + 0002 Smartmouse + 0003 FunProgrammer + 0004 Infinity Unlimited + 0006 Infinity Smart + 0007 Infinity Smart module + 0008 Infinity CryptoKey + 0009 RE-BL PlayStation 3 IR-to-Bluetooth converter +1050 Yubico.com + 0010 Yubikey (v1 or v2) + 0110 Yubikey NEO(-N) OTP + 0111 Yubikey NEO(-N) OTP+CCID + 0112 Yubikey NEO(-N) CCID + 0113 Yubikey NEO(-N) U2F + 0114 Yubikey NEO(-N) OTP+U2F + 0115 Yubikey NEO(-N) U2F+CCID + 0116 Yubikey NEO(-N) OTP+U2F+CCID + 0120 Yubikey Touch U2F Security Key + 0200 Gnubby U2F + 0211 Gnubby + 0401 Yubikey 4 OTP + 0402 Yubikey 4 U2F + 0403 Yubikey 4 OTP+U2F + 0404 Yubikey 4 CCID + 0405 Yubikey 4 OTP+CCID + 0406 Yubikey 4 U2F+CCID + 0407 Yubikey 4 OTP+U2F+CCID + 0410 Yubikey plus OTP+U2F +1053 Immanuel Electronics Co., Ltd +1054 BMS International Beheer N.V. + 5004 DSL 7420 Loader + 5005 DSL 7420 LAN Modem +1055 Complex Micro Interconnection Co., Ltd +1056 Hsin Chen Ent Co., Ltd +1057 ON Semiconductor +1058 Western Digital Technologies, Inc. + 0200 FireWire USB Combo + 0400 External HDD + 0500 hub + 0701 WD Passport (WDXMS) + 0702 WD Passport (WDXMS) + 0704 My Passport Essential (WDME) + 0705 My Passport Elite (WDML) + 070a My Passport Essential (WDBAAA), My Passport for Mac (WDBAAB), My Passport Essential SE (WDBABM), My Passport SE for Mac (WDBABW) + 070b My Passport Elite (WDBAAC) + 070c My Passport Studio (WDBAAE) + 071a My Passport Essential (WDBAAA) + 071d My Passport Studio (WDBALG) + 0730 My Passport Essential (WDBACY) + 0732 My Passport Essential SE (WDBGYS) + 0740 My Passport Essential (WDBACY) + 0741 My Passport Ultra + 0742 My Passport Essential SE (WDBGYS) + 0748 My Passport (WDBKXH, WDBY8L) + 07a8 My Passport (WDBBEP), My Passport for Mac (WDBLUZ) + 07ae My Passport Edge for Mac (WDBJBH) + 07ba PiDrive (WDLB) + 0810 My Passport Ultra (WDBZFP) + 0816 My Passport Air (WDBBLW) + 0820 My Passport Ultra (WDBMWV, WDBZFP) + 0822 My Passport Ultra (WDBBUZ) + 0824 My Passport Slim (WDBPDZ) + 0830 My Passport Ultra (WDBZFP) + 0837 My Passport Ultra (WDBBKD) + 0900 MyBook Essential External HDD + 0901 My Book Essential Edition (Green Ring) (WDG1U) + 0902 My Book Pro Edition (WDG1T) + 0903 My Book Premium Edition + 0905 My Book Pro Edition II (WD10000C033-001) + 0910 My Book Essential Edition (Green Ring) (WDG1U) + 1001 Elements Desktop (WDE1U) + 1003 WD Elements Desktop (WDE1UBK) + 1010 Elements Portable (WDBAAR) + 1021 Elements Desktop (WDBAAU) + 1023 Elements SE Portable (WDBABV) + 1042 Elements SE Portable (WDBPCK) + 1048 Elements Portable (WDBU6Y) + 1078 Elements Portable (WDBUZG) + 107c Elements Desktop (WDBWLG) + 10a2 Elements SE Portable (WDBPCK) + 10a8 Elements Portable (WDBUZG) + 10b8 Elements Portable (WDBU6Y, WDBUZG) + 1100 My Book Essential Edition 2.0 (WDH1U) + 1102 My Book Home Edition (WDH1CS) + 1103 My Book Studio + 1104 My Book Mirror Edition (WDH2U) + 1105 My Book Studio II + 1110 My Book Essential (WDBAAF), My Book for Mac (WDBAAG) + 1111 My Book Elite (WDBAAH) + 1112 My Book Studio (WDBAAJ), My Book Studio LX (WDBACH) + 1123 My Book 3.0 (WDBABP) + 1130 My Book Essential (WDBACW) + 1140 My Book Essential (WDBACW) + 1230 My Book (WDBFJK) + 1235 My Book (WDBFJK0040HBK) + 2599 My Passport Ultra (WD40NMZW) + 259d My Passport Ultra (WDBBKD) + 259f My Passport Ultra (WD10JMVW) + 25a1 Elements / My Passport (WD20NMVW) + 25a2 Elements 25A2 + 25a3 Elements Desktop (WDBWLG) + 25e2 My Passport (WD40NMZW) + 30a0 SATA adapter cable +1059 Giesecke & Devrient GmbH + 000b StarSign Bio Token 3.0 +105b Foxconn International, Inc. + e065 BCM43142A0 Bluetooth module +105c Hong Ji Electric Wire & Cable (Dongguan) Co., Ltd +105d Delkin Devices, Inc. +105e Valence Semiconductor Design, Ltd +105f Chin Shong Enterprise Co., Ltd +1060 Easthome Industrial Co., Ltd +1063 Motorola Electronics Taiwan, Ltd [hex] + 1555 MC141555 Hub + 4100 SB4100 USB Cable Modem +1065 CCYU Technology + 0020 USB-DVR2 Dev Board + 2136 EasyDisk ED1064 +1068 Micropi Elettronica + 0001 CPUSB - V 1.8 - software-rights management key +106a Loyal Legend, Ltd +106c Curitel Communications, Inc. + 1101 CDMA 2000 1xRTT USB modem (HX-550C) + 1102 Packet Service + 1103 Packet Service Diagnostic Serial Port (WDM) + 1104 Packet Service Diagnostic Serial Port (WDM) + 1105 Composite Device + 1106 Packet Service Diagnostic Serial Port (WDM) + 1301 Composite Device + 1302 Packet Service Diagnostic Serial Port (WDM) + 1303 Packet Service + 1304 Packet Service + 1401 Composite Device + 1402 Packet Service + 1403 Packet Service Diagnostic Serial Port (WDM) + 1501 Packet Service + 1502 Packet Service Diagnostic Serial Port (WDM) + 1503 Packet Service + 1601 Packet Service + 1602 Packet Service Diagnostic Serial Port (WDM) + 1603 Packet Service + 2101 AudioVox 8900 Cell Phone + 2102 Packet Service + 2103 Packet Service Diagnostic Serial Port (WDM) + 2301 Packet Service + 2302 Packet Service Diagnostic Serial Port (WDM) + 2303 Packet Service + 2401 Packet Service Diagnostic Serial Port (WDM) + 2402 Packet Service + 2403 Packet Service Diagnostic Serial Port (WDM) + 2501 Packet Service + 2502 Packet Service Diagnostic Serial Port (WDM) + 2503 Packet Service + 2601 Packet Service + 2602 Packet Service Diagnostic Serial Port (WDM) + 2603 Packet Service + 3701 Broadband Wireless modem + 3702 Pantech PX-500 + 3714 PANTECH USB MODEM [UM175] + 3716 UMW190 Modem + 3721 Option Beemo (GI0801) LTE surfstick + 3b14 Option Beemo (GI0801) LTE surfstick + 3eb4 Packet Service Diagnostic Serial Port (WDM) + 4101 Packet Service Diagnostic Serial Port (WDM) + 4102 Packet Service + 4301 Composite Device + 4302 Packet Service Diagnostic Serial Port (WDM) + 4401 Composite Device + 4402 Packet Service + 4501 Packet Service + 4502 Packet Service Diagnostic Serial Port (WDM) + 4601 Composite Device + 4602 Packet Service Diagnostic Serial Port (WDM) + 5101 Packet Service + 5102 Packet Service Diagnostic Serial Port (WDM) + 5301 Packet Service Diagnostic Serial Port (WDM) + 5302 Packet Service + 5401 Packet Service + 5402 Packet Service Diagnostic Serial Port (WDM) + 5501 Packet Service Diagnostic Serial Port (WDM) + 5502 Packet Service + 5601 Packet Service Diagnostic Serial Port (WDM) + 5602 Packet Service + 7101 Composite Device + 7102 Packet Service + a000 Packet Service + a001 Packet Service Diagnostic Serial Port (WDM) + c100 Packet Service + c200 Packet Service + c500 Packet Service Diagnostic Serial Port (WDM) + e200 Packet Service +106d San Chieh Manufacturing, Ltd +106e ConectL +106f Money Controls + 0009 CT10x Coin Transaction + 000a CR10x Coin Recycler + 000c Xchange +1076 GCT Semiconductor, Inc. + 0031 Bluetooth Device + 0032 Bluetooth Device + 8002 LU150 LTE Modem [Yota LU150] +107b Gateway, Inc. + 3009 eHome Infrared Transceiver + 55b2 WBU-110 802.11b Wireless Adapter [Intersil PRISM 3] + 55f2 WGU-210 802.11g Adapter [Intersil ISL3886] +107d Arlec Australia, Ltd +107e Midoriya Electric Co., Ltd +107f KidzMouse, Inc. +1082 Shin-Etsukaken Co., Ltd +1083 Canon Electronics, Inc. + 160c CR-55 + 160f DR-1210C + 1614 DR-4010C + 1617 DR-2510C + 1618 DR-X10C + 161a CR-25 + 161b DR-2010C Scanner + 161d DR-3010C + 1620 DR-7090C + 1622 DR-9050C + 1623 DR-7550C + 1624 DR-6050C + 1626 DR-6010C + 162c P-150 Scanner + 1638 DR-6030C + 1639 CR-135i + 163e DR-M160 + 163f DR-M140 + 1640 DR-C125 + 1641 DR-P215 + 1648 FSU-201 + 164a DR-C130 + 164b DR-P208 + 164f DR-G1130 + 1650 DR-G1100 + 1651 DR-C120 + 1654 DR-F120 + 1657 DR-M1060 + 1658 DR-C225 + 1659 DR-P215II + 165d DR-P208II +1084 Pantech Co., Ltd +108a Chloride Power Protection +108b Grand-tek Technology Co., Ltd + 0005 HID Keyboard/Mouse PS/2 Translator +108c Robert Bosch GmbH +108e Lotes Co., Ltd. +1091 Numerik Jena + 8101 Absoflex +1099 Surface Optics Corp. +109a DATASOFT Systems GmbH +109b Hisense + 9118 Medion P4013 Mobile +109f eSOL Co., Ltd + 3163 Trigem Mobile SmartDisplay84 + 3164 Trigem Mobile SmartDisplay121 +10a0 Hirotech, Inc. +10a3 Mitsubishi Materials Corp. +10a9 SK Teletech Co., Ltd + 1102 Sky Love Actually IM-U460K + 1104 Sky Vega IM-A650S + 1105 VEGA Android composite + 1106 VEGA Android composite + 1107 VEGA Android composite + 1108 VEGA Android composite + 1109 VEGA Android composite + 6021 SIRIUS alpha + 6031 Pantech Android composite + 6032 Pantech Android composite + 6033 Pantech Android composite + 6034 Pantech Android composite + 6035 Pantech Android composite + 6036 Pantech Android composite + 6037 Pantech Android composite + 6050 Pantech Android composite + 6051 Pantech Android composite + 6052 Pantech Android composite + 6053 Pantech Android composite + 6054 Pantech Android composite + 6055 Pantech Android composite + 6056 Pantech Android composite + 6057 Pantech Android composite + 6058 Pantech Android composite + 6059 Pantech Android composite + 6080 MHS291LVW LTE Modem [Verizon Jetpack 4G LTE Mobile Hotspot MHS291L] (Zero CD Mode) + 6085 MHS291LVW LTE Modem [Verizon Jetpack 4G LTE Mobile Hotspot MHS291L] (Modem Mode) + 7031 Pantech Android composite + 7032 Pantech Android composite + 7033 Pantech Android composite + 7034 Pantech Android composite + 7035 Pantech Android composite + 7036 Pantech Android composite + 7037 Pantech Android composite +10aa Cables To Go +10ab USI Co., Ltd + 1002 Bluetooth Device + 1003 BC02-EXT in DFU + 1005 Bluetooth Adptr + 1006 BC04-EXT in DFU + 10c5 Sony-Ericsson / Samsung DataCable +10ac Honeywell, Inc. +10ae Princeton Technology Corp. +10af Liebert Corp. + 0000 UPS + 0001 PowerSure PSA UPS + 0002 PowerSure PST UPS + 0003 PowerSure PSP UPS + 0004 PowerSure PSI UPS + 0005 UPStation GXT 2U UPS + 0006 UPStation GXT UPS + 0007 Nfinity Power Systems UPS + 0008 PowerSure Interactive UPS +10b5 Comodo (PLX?) + 9060 Test Board +10b8 DiBcom + 0bb8 DVB-T reference design (MOD300) (cold) + 0bb9 DVB-T reference design (MOD300) (warm) + 0bc6 DVB-T reference design (MOD3000P) (cold) + 0bc7 DVB-T reference design (MOD3000P) (warm) +10bb TM Technology, Inc. +10bc Dinging Technology Co., Ltd +10bd TMT Technology, Inc. + 1427 Ethernet +10bf SmartHome + 0001 SmartHome PowerLinc +10c3 Universal Laser Systems, Inc. + 00a4 ULS PLS Series Laser Engraver Firmware Loader + 00a5 ULS Print Support +10c4 Silicon Labs + 0002 F32x USBXpress Device + 0003 CommandIR + 800a SPORTident + 800b AES + 8030 K4JRG Ham Radio devices + 8044 USB Debug Adapter + 804e Software Bisque Paramount ME + 80a9 CP210x to UART Bridge Controller + 80c4 Infrared Thermometer Adapter + 80ca ATM2400 Sensor Device + 813f tams EasyControl + 8149 West Mountain Radio Computerized Battery Analyzer + 814a West Mountain Radio RIGblaster P&P + 814b West Mountain Radio RIGtalk + 818a Silicon Labs FM Radio Reference Design + 81e8 Zephyr BioHarness + 834b Infrared Online Sensor Adapter + 834e Infrared Sensor Adapter + 8460 Sangoma Wanpipe VoiceTime + 8461 Sangoma U100 + 8470 Juniper Networks BX Series System Console + 8477 Balluff RFID Reader + 8496 SiLabs Cypress FW downloader + 8497 SiLabs Cypress EVB + 84fb Infrared Blackbody Adapter + 8508 RS485 Adapter + 8605 dilitronics ESoLUX solar lighting controller + 8660 Netronics CANdoISO + 86bc C8051F34x AudioDelay [AD-340] + 8789 C8051F34x Extender & EDID MGR [EMX-DVI] + 87be C8051F34x HDMI Audio Extractor [EMX-HD-AUD] + 8863 C8051F34x Bootloader + 8897 C8051F38x HDMI Splitter [UHBX] + 88c9 AES HID device + 8918 C8051F38x HDMI Audio Extractor [VSA-HA-DP] + 8973 C8051F38x HDMI Extender [UHBX-8X] + 89c6 SPORTident HID device + 89e1 C8051F38x HDMI Extender [UHBX-SW3-WP] + 89fb Qivicon ZigBee Stick + 8a3c C8051F38x HDBaseT Receiver [UHBX-R-XT] + 8a6c C8051F38x 4K HDMI Audio Extractor [EMX-AMP] + 8acb C8051F38x HDBaseT Wall Plate Receiver with IR, RS-232, and PoH [UHBX-R-WP] + 8af8 C8051F38x 4K HDMI Audio Extractor w/Audio Amplifier, HDBT Input, Line Audio Input RS-232 Ports and IP Control [VSA-X21] + 8b8c C8051F38x 4K HDMI Audio Extractor w/Audio Amplifier, HDBT Input, Line Audio Input RS-232 Ports and IP Control [SC-3H] + 8db5 C8051F38x CATx HDMI Receiver with USB [EX-HDU-R] + 8db6 C8051F38x CATx HDMI Receiver + ea60 CP210x UART Bridge + ea61 CP210x UART Bridge + ea63 CP210x UART Bridge + ea70 CP2105 Dual UART Bridge + ea71 CP2108 Quad UART Bridge + ea80 CP2110 HID UART Bridge + ea90 CP2112 HID I2C Bridge + ea91 CP2112 HID SMBus/I2C Bridge for CP2614 Evaluation Kit + ea93 CP2112 HID SMBus/I2C Bridge for CP2615 Evaluation Kit + eab0 CP2114 I2S Audio Bridge + eac0 CP2614 MFi Accessory Digital Audio Bridge + eac1 CP2615 I2S Audio Bridge + eac9 EFM8UB1 Bootloader + eaca EFM8UB2 Bootloader + eacb EFM8UB3 Bootloader +10c5 Sanei Electric, Inc. + 819a FM Radio +10c6 Intec, Inc. +10cb Eratech +10cc GBM Connector Co., Ltd + 1101 MP3 Player +10cd Kycon, Inc. +10ce Silicon Labs + 0007 Shinko/Sinfonia CHC-S1245 + 000e Shinko/Sinfonia CHC-S2145 + 0019 Shinko/Sinfonia CHC-S6145 + 001d Shinko/Sinfonia CHC-S6245 + 001e Ciaat Brava 21 + ea6a MobiData EDGE USB Modem +10cf Velleman Components, Inc. + 2011 R-Engine MPEG2 encoder/decoder + 5500 8055 Experiment Interface Board (address=0) + 5501 8055 Experiment Interface Board (address=1) + 5502 8055 Experiment Interface Board (address=2) + 5503 8055 Experiment Interface Board (address=3) +10d1 Hottinger Baldwin Measurement + 0101 USB-Module for Spider8, CP32 + 0202 CP22 - Communication Processor + 0301 CP42 - Communication Processor +10d2 RayComposer - R. Adams + 5243 RayComposer +10d4 Man Boon Manufactory, Ltd +10d5 Uni Class Technology Co., Ltd + 0004 PS/2 Converter + 5552 KVM Human Interface Composite Device (Keyboard/Mouse ports) + 55a2 2Port KVMSwitcher +10d6 Actions Semiconductor Co., Ltd + 0c02 BioniQ 1001 Tablet + 1000 MP3 Player + 1100 MPMan MP-Ki 128 MP3 Player/Recorder + 1101 D-Wave 2GB MP4 Player / AK1025 MP3/MP4 Player + 2200 Acer MP-120 MP3 player + 8888 ADFU Device + ff51 ADFU Device + ff61 MP4 Player + ff66 Craig 2GB MP3/Video Player +10de Authenex, Inc. +10df In-Win Development, Inc. + 0500 iAPP CR-e500 Card reader +10e0 Post-Op Video, Inc. +10e1 CablePlus, Ltd +10e2 Nada Electronics, Ltd +10ec Vast Technologies, Inc. +10f0 Nexio Co., Ltd + 2002 iNexio Touchscreen controller +10f1 Importek + 1a08 Internal Webcam + 1a1e Laptop Integrated Webcam 1.3M + 1a2a Laptop Integrated Webcam + 1a2e HP Truevision HD Integrated Webcam +10f5 Turtle Beach + 0200 Audio Advantage Roadie +10fb Pictos Technologies, Inc. +10fd Anubis Electronics, Ltd + 7e50 FlyCam Usb 100 + 804d Typhoon Webshot II Webcam [zc0301] + 8050 FlyCAM-USB 300 XP2 + de00 WinFast WalkieTV WDM Capture Driver. +10fe Thrane & Thrane + 000c TT-3750 BGAN-XL Radio Module +1100 VirTouch, Ltd + 0001 VTPlayer VTP-1 Braille Mouse +1101 EasyPass Industrial Co., Ltd + 0001 FSK Electronics Super GSM Reader +1108 Brightcom Technologies, Ltd +110a Moxa Technologies Co., Ltd. + 1250 UPort 1250 2-Port RS-232/422/485 + 1251 UPort 1250I 2-Port RS-232/422/485 with Isolation + 1410 UPort 1410 4-Port RS-232 + 1450 UPort 1450 4-Port RS-232/422/485 + 1451 UPort 1450I 4-Port RS-232/422/485 with Isolation + 1613 UPort 1610-16 16-Port RS-232 + 1618 UPort 1610-8 8-Port RS-232 + 1653 UPort 1650-16 16-Port RS-232/422/485 + 1658 UPort 1650-8 8-Port RS-232/422/485 +1110 Analog Devices Canada, Ltd (Allied Telesyn) + 5c01 Huawei MT-882 Remote NDIS Network Device + 6489 ADSL ETH/USB RTR + 9000 ADSL LAN Adapter + 9001 ADSL Loader + 900f AT-AR215 DSL Modem + 9010 AT-AR215 DSL Modem + 9021 ADSL WAN Adapter + 9022 ADSL Loader + 9023 ADSL WAN Adapter + 9024 ADSL Loader + 9031 ADSL LAN Adapter + 9032 ADSL Loader +1111 Pandora International Ltd. + 8888 Evolution Device +1112 YM ELECTRIC CO., Ltd +1113 Medion AG + a0a2 Active Sync device +111e VSO Electric Co., Ltd +112a RedRat + 0001 RedRat3 IR Transceiver + 0005 RedRat3II IR Transceiver +112e Master Hill Electric Wire and Cable Co., Ltd +112f Cellon International, Inc. +1130 Tenx Technology, Inc. + 0001 BlyncLight + 0002 iBuddy + 0202 Rocket Launcher + 6604 MCE IR-Receiver + 660c Foot Pedal/Thermometer + 6626 Key + 6806 Keychain photo frame + c301 Digital Photo viewer [Wallet Pix] + f211 TP6911 Audio Headset +1131 Integrated System Solution Corp. + 1001 KY-BT100 Bluetooth Adapter + 1002 Bluetooth Device + 1003 Bluetooth Device + 1004 Bluetooth Device +1132 Toshiba Corp., Digital Media Equipment [hex] + 4331 PDR-M4/M5/M70 Digital Camera + 4332 PDR-M60 Digital Camera + 4333 PDR-M2300/PDR-M700 + 4334 PDR-M65 + 4335 PDR-M61 + 4337 PDR-M11 + 4338 PDR-M25 +1136 CTS Electronincs + 3131 CTS LS515 +113c Arin Tech Co., Ltd +113d Mapower Electronics Co., Ltd +113f Integrated Biometrics, LLC + 1020 Watson Two-Finger Roll Scanner + 1100 Columbo Single-Finger Scanner +1141 V One Multimedia, Pte., Ltd +1142 CyberScan Technologies, Inc. + 0709 Cyberview High Speed Scanner +1145 Japan Radio Company + 0001 AirH PHONE AH-J3001V/J3002V +1146 Shimane SANYO Electric Co., Ltd. +1147 Ever Great Electric Wire and Cable Co., Ltd +114b Sphairon Access Systems GmbH + 0110 Turbolink UB801R WLAN Adapter + 0150 Turbolink UB801RE Wireless 802.11g 54Mbps Network Adapter [RTL8187] +114c Tinius Olsen Testing Machine Co., Inc. +114d Alpha Imaging Technology Corp. +114f Wavecom + 1234 Fastrack Xtend FXT001 Modem +115b Salix Technology Co., Ltd. +1162 Secugen Corp. +1163 DeLorme Publishing, Inc. + 0100 Earthmate GPS (orig) + 0200 Earthmate GPS (LT-20, LT-40) + 2020 Earthmate GPS (PN-40) +1164 YUAN High-Tech Development Co., Ltd + 0300 ELSAVISION 460D + 0601 Analog TV Tuner + 0900 TigerBird BMP837 USB2.0 WDM Encoder + 0bc7 Digital TV Tuner + 521b MC521A mini Card ATSC Tuner + 6601 Digital TV Tuner Card [RTL2832U] +1165 Telson Electronics Co., Ltd +1166 Bantam Interactive Technologies +1167 Salient Systems Corp. +1168 BizConn International Corp. +116e Gigastorage Corp. +116f Silicon 10 Technology Corp. + 0005 Flash Card Reader + c108 Flash Card Reader + c109 Flash Card Reader +1175 Shengyih Steel Mold Co., Ltd +117d Santa Electronic, Inc. +117e JNC, Inc. +1182 Venture Corp., Ltd +1183 Compaq Computer Corp. [hex] (Digital Dream ??) + 0001 DigitalDream l'espion XS + 19c7 ISDN TA + 4008 56k FaxModem + 504a PJB-100 Personal Jukebox +1184 Kyocera Elco Corp. +1188 Bloomberg L.P. +1189 Acer Communications & Multimedia + 0893 EP-1427X-2 Ethernet Adapter [Acer] +118f You Yang Technology Co., Ltd +1190 Tripace +1191 Loyalty Founder Enterprise Co., Ltd +1196 Yankee Robotics, LLC + 0010 Trifid Camera without code + 0011 Trifid Camera +1197 Technoimagia Co., Ltd +1198 StarShine Technology Corp. +1199 Sierra Wireless, Inc. + 0019 AC595U + 0021 AC597E + 0024 MC5727 CDMA modem + 0110 Composite Device + 0112 CDMA 1xEVDO PC Card, AirCard 580 + 0120 AC595U + 0218 MC5720 Wireless Modem + 6467 MP Series Network Adapter + 6468 MP Series Network Adapter + 6469 MP Series Network Adapter + 6802 MC8755 Device + 6803 MC8765 Device + 6804 MC8755 Device + 6805 MC8765 Device + 6812 MC8775 Device + 6820 AC875 Device + 6832 MC8780 Device + 6833 MC8781 Device + 683a MC8785 Device + 683c Mobile Broadband 3G/UMTS (MC8790 Device) + 6850 AirCard 880 Device + 6851 AirCard 881 Device + 6852 AirCard 880E Device + 6853 AirCard 881E Device + 6854 AirCard 885 Device + 6856 ATT "USB Connect 881" + 6870 MC8780 Device + 6871 MC8781 Device + 6893 MC8777 Device + 68a3 MC8700 Modem + 68aa 4G LTE adapter + 9000 Gobi 2000 Wireless Modem (QDL mode) + 9001 Gobi 2000 Wireless Modem + 9002 Gobi 2000 Wireless Modem + 9003 Gobi 2000 Wireless Modem + 9004 Gobi 2000 Wireless Modem + 9005 Gobi 2000 Wireless Modem + 9006 Gobi 2000 Wireless Modem + 9007 Gobi 2000 Wireless Modem + 9008 Gobi 2000 Wireless Modem + 9009 Gobi 2000 Wireless Modem + 900a Gobi 2000 Wireless Modem + 9013 Sierra Wireless Gobi 3000 Modem device (MC8355) + 9055 Gobi 9x15 Multimode 3G/4G LTE Modem (NAT mode) + 9057 Gobi 9x15 Multimode 3G/4G LTE Modem (IP passthrough mode) +119a ZHAN QI Technology Co., Ltd +119b ruwido austria GmbH + 0400 Infrared Keyboard V2.01 +11a0 Chipcon AS + eb11 CC2400EB 2.0 ZigBee Sniffer +11a3 Technovas Co., Ltd + 8031 MP3 Player + 8032 MP3 Player +11aa GlobalMedia Group, LLC + 1518 iREZ K2 +11ab Exito Electronics Co., Ltd +11ac Nike + 6565 FuelBand +11b0 ATECH FLASH TECHNOLOGY + 6208 PRO-28U +11be R&D International NV + f0a0 Martin Maxxyz DMX +11c0 Betop + 5506 Gamepad +11c5 Inmax + 0521 IMT-0521 Smartcard Reader +11ca VeriFone Inc + 0207 PIN Pad VX 810 + 0220 PIN Pad VX 805 +11db Topfield Co., Ltd. + 1000 PVR + 1100 PVR +11e6 K.I. Technology Co. Ltd. +11f5 Siemens AG + 0001 SX1 + 0003 Mobile phone USB cable + 0004 X75 + 0005 SXG75/EF81 + 0008 UMTS/HSDPA Data Card + 0101 RCU Connect +11f6 Prolific + 2001 Willcom WSIM +11f7 Alcatel (?) + 02df Serial cable (v2) for TD-10 Mobile Phone +1203 TSC Auto ID Technology Co., Ltd + 0140 TTP-245C +1209 Generic + 0001 pid.codes Test PID + 01c0 Input Club Kiibohd Device + 01cb Input Club Kiibohd Device Bootloader + 0256 Schwalm & Tate LLC pISO Raspberry Pi Hat + 053a Hackerspace San Salvador HSSV SAMR21-Mote + 0cbd Andrzej Szombierski kuku.eu.org keyboard + 0d32 ODrive Robotics ODrive v3 + 1001 InterBiometrics Hub + 1002 InterBiometrics Relais + 1003 InterBiometrics IBSecureCam-P + 1004 InterBiometrics IBSecureCam-O + 1005 InterBiometrics IBSecureCam-N + 1006 InterBiometrics Mini IO-Board + 1007 e-radionica.com Croduino SAMD + 1986 dgrubb Jaguar Tap + 1ab5 Arachnid Labs Tsunami + 1ab6 Arachnid Labs Tsunami Bootloader + 2000 Zygmunt Krynicki Lantern Brightness Sensor + 2001 OSHEC Pi-pilot opensource and openhardware autopilot system + 2002 Peter Lawrence PIC16F1-USB-DFU-Bootloader + 2003 Peter Lawrence SAMDx1-USB-DFU-Bootloader + 2004 GCBASIC Serial CDC Stack + 2005 GCBASIC OakTree Stack + 2006 GCBASIC Simulation Stack + 2016 Cupkee + 2017 Benjamin Shockley Mini SAM + 2020 Captain Credible Gate Crystal + 2048 Housedillon.com MRF49XA Transciever + 2100 TinyFPGA B1 and B2 Boards + 2101 TinyFPGA A-Series Programmer + 2200 Dygma Shortcut Bootloader + 2201 Dygma Shortcut Keyboard + 2222 LabConnect Signalgenerator + 2300 Keyboardio Model 01 Bootloader + 2301 Keyboardio Model 01 + 2323 bytewerk.org candleLight + 2327 K.T.E.C. Bootloader Device + 2328 K.T.E.C. Keyboard Device + 2333 Kai Ryu Kimera + 2334 Kai Ryu Staryu + 2335 Portwell Sense8 + 2336 Portwell Sense8 + 2337 /Dev /Net + 2342 Andreas Bogk Big Red Button + 2345 VV-Soft Simple Generic HID IO + 2357 KarolKucza TinyPassword + 2400 phooky Snap-Pad + 2488 Peter Lawrence CMSIS-DAP Dapper Miser + 2552 ProjectIota Electrolink + 2600 Majenko Technologies chipKIT Lenny + 2635 Sevinz GameBot + 2800 Entropic Engineering Triangulation + 2801 Entropic Engineering Object Manipulation + 2a00 mooware Wii adapter + 2a01 mooware SNES adapter + 3000 lloyd3000 + 3100 OpenSimHardware Pedals & Buttons Controller + 317e Codecrete Wirekite + 3210 OSH Lab, LLC Magic Keys + 3333 LabConnect Digitalnetzteil + 3690 Kigakudoh TouchMIDI32 + 4096 CynaraKrewe Cynara + 414c Adi Linden + 414d Adi Linden + 4242 Komakallio Astrophotography Community KomaHub Remote Power Switch + 4256 CuVoodoo BusVoodoo multi-protocol debugging adapter + 4321 mooltipass Offline Password Keeper Bootloader + 4322 mooltipass Arduino Sketch + 4356 CuVoodoo firmware + 4443 j1rie IRMP_STM32 Bootloader + 4444 j1rie IRMP_STM32 + 4545 SlothCo Enterprises Teletype Adapter + 4646 SmartPID SPC1000 + 4748 Kate Gray GHETT-iO Bootloader + 4750 Chris Pavlina (c4757p) C4-x computer (development interface) + 4757 Chris Pavlina (c4757p) WCP52 Gain/Phase Analyzer + 4801 Wojciech Krutnik NVMemProg + 4c60 MightyPork GEX module + 4c61 MightyPork GEX wireless dongle + 4d53 mindsensors.com NXTCam5 + 5038 frotz.net mdebug rswd protocol + 5039 frotz.net lpcboot protocol + 5050 trebb ISO50 + 5222 telavivmakers attami + 53c0 SatoshiLabs TREZOR Bootloader + 53c1 SatoshiLabs TREZOR + 5432 Open Programmer + 5457 Openlab.Taipei Taiwanduino + 571c StreetoArcade PancadariaStick + 5a22 ikari_01 sd2snes + 6000 Pulsar Heavy Industries Cenx4 + 600d Makdaam N93 Interface + 6464 Electric Exploits Shinewave + 6502 jj1bdx avrhwrng v2rev1 + 6570 Iowa Scaled Engineering, LLC CKT-AVRPROGRAMMER + 6666 Talpa Chen VSFLogic + 6667 SensePost Universal Serial aBUSe - Generic HID + 6742 NPK Cubitel Atomic Force Microscope + 6809 Tach Radio Doppelganger + 6948 MySensors Sensebender Gateway BootLoader + 6949 MySensors Sensebender Gateway + 6bcf blaste Gameboy Cart Flasher + 7000 Secalot Dongle + 7001 Secalot Bootloader + 70b1 Sutajio Ko-Usagi (Kosagi) Tomu + 7331 Dangerous Prototypes Bus Pirate Next Gen CDC + 7332 Dangerous Prototypes Bus Pirate Next Gen Logic Analyzer + 7401 Beststream-jp Tool_CDC + 7530 PotentialLabs Refflion - IoT Development Board - Bootloader + 7531 PotentialLabs Refflion - IoT Development Board - Sketch + 7551 The Tessel Project Tessel 2 + 7777 circuitvalley IO Board V3 + 7778 circuitvalley IO Board V3 Bootloader + 7bd0 pokey9000 Tiny Bit Dingus + 8000 Autonomii NODii 2 + 8086 MisfitTech Nano Zero Bootloader + 8087 MisfitTech Nano Zero + 8123 Danyboard M0 bootloader + 812a Danyboard M0 + 813a MickMad HACK Bootloader + 813b MickMad HACK Sketch + 8242 Tom Wimmenhove Electronics NBS-DAC 192/24 UAC1 + 8243 Tom Wimmenhove Electronics NBS-DAC 192/24 UAC2 + 8472 Shantea Controls OpenDeck + 8661 ProgHQ TL866 programmer + 8844 munia.io MUNIA + 8888 Blinkinlabs POV Pendant + 8889 Blinkinlabs POV Pendant (bootloader) + 8b00 ReSwitched Libtransistor Serial Console + 9021 Connected Community Hackerspace ESPlant + 9317 Sutajio Ko-Usagi (Kosagi) Palawan-Tx + 9999 Sandeepan Sengupta CodeBridge Infineo + 9db5 PD Buddy Sink + a033 area0x33 Memtype + a100 KB LES Narsil analog breakout + a10c KB LES Aminoacid Synthesizer + a1e5 Atreus Keyboards Atreus Keyboard + a3a4 MK::Box MK::Kbd + a3a5 MK::Box MK::Kbd Bootloader + a55a Forever Young Software ATTINY2313 + a602 Robotips RTBoard + a7ea area3001 Knixx SW04 + a800 sowbug.com WebLight + a8b0 Intelectron BootWare + a8b1 Intelectron FrameWare + aa00 Serg Oskin LinuxCNC HID Extender + aa0b Open Bionics + ab3d 3DArtists Alligator board + abba CoinWISE SafeWISE + abc0 Omzlo controller + abcd Sandeepan Sengupta CodeBridge + abd1 OpenMV Cam + acdc Gediminas Zukaitis midi-grid + ace5 SimAces Panel Ace + aced Open Lighting Project Ja Rule Device + acee Open Lighting Project Ja Rule Bootloader + adb0 tibounise ADB converter + adda MicroPython Boards + b007 Konsgn Global_Boot + b00b CrapLab Random Device + b010 IObitZ CodeBridge + b01d WyoLum VeloKey + b058 Model B, LLC Holoseat + b0b0 Monero Hardware Monero Bootloader + b100 ptrandem iBizi + b101 IObitZ Infineo + b195 flehrad Big Switch PCB + bab1 ElectronicCats Meow Meow + babe brunofreitas.com STM32 HID Bootloader + bad1 Gregory POTEAU CommLinkUSB + bad2 Gregory POTEAU XLinkUSB + bade Semarme SemarmeHID + bb00 keyplus split keyboard firmware + bb01 keyplus xusb bootloader + bb02 keyplus nRF24 wireless keyboard dongle + bb03 keyplus nrf24lu1p-512 bootloader + bb05 keyplus kp_boot_32u4 bootloader + beba serasidis.gr STM32 HID Bootloader + beef Modal MC-USB + c001 Cynteract Alpha + c0c0 Geppetto_Electronics Orthrus + c0c1 Michael Bemmerl cookie-mouse + c0ca Jean THOMAS DirtyJTAG + c0d3 Samy Kamkar USBdriveby + c0da Monero Hardware Monero Firmware + c0de KMRH Labs SBL Brain + c0f5 unethi PERswitch + c1aa Proyecto CIAA Computadora Industrial Abierta Argentina + c1b1 Chibitronics Love-to-Code + c311 bg nerilex GB-USB-Link + ca1c KnightOS Generic Hub + ca1d KnightOS MTP Device + caea Open Music Kontrollers Chimaera + cafe ii iigadget + cc14 trebb NaN-15 + cc86 Manfred's Technologies Anastasia Bootloader + ceb0 KG4LNE GE-FlashUSB + cf20 Smart Citizen SCK 2.0 + d00d Monero Hardware Monero Developer + d017 empiriKit empiriKit Controller + d11d Koi Science DI-Lambda AVR + d3d8 Duet3d Duet 0.8.5 + d706 SkyBean SkyDrop + da42 Devan Lai dap42 debug access probe + daa0 darknao btClubSportWheel + dada Rebel Technology OWL + db42 Devan Lai dapboot DFU bootloader + dc21 FPGA-Computer Dual Charger + dddd Stephan Electronics OpenCVMeter + dead chaosfield.at AVR-Ruler + deaf CrapLab 4chord MIDI + ded1 ManCave Made Quark One + df00 D.F.Mac. @TripArts Music mi:muz:tuch + df01 D.F.Mac. @TripArts Music mi:muz:can + df02 D.F.Mac. @TripArts Music mi:muz:can-lite + e116 Elijah Motornyy open-oscilloscope-stm32f3 + e1ec FreeSRP + e4ee trebb keytee + e500 GitleMikkelsen Helios Laser DAC + eaea Pinscape Controller + eb01 RobotMaker.club EB1 + eba7 VictorGrigoryev USBscope + ee00 Explore Embedded SODA(SWD OpenSource Debug Adapter) + ee02 Explore Embedded Explore M3 VCOM + ee03 Explore Embedded Explore M3 DFU + ee2c jaka USB2RS485 + effa EffigyLabs atmega32u4-USB-LUFA-Bootloader + effe EffigyLabs Control Pedal + f000 Uniti ARC + f00d RomanStepanov Shifter/Pedals Adapter + f12e Michael Bemmerl Feuermelder + f16a uri_ba Cougar TQS adapter + f16c uri_ba adapter for Vipercore's FCC3 Force Sensing Module + f380 Windsor Schmidt MD-380 Open Radio Firmware + f3fc dRonin Flight controller-Lumenier Lux + f49a TimVideos.us & HDMI2USB.tv Projects FPGA Programmer & UART Bridge (PIC based Firmware) + fa11 moonglow OpenXHC + fa57 3DRacers Pilot Board + fa58 3DRacers Pilot Board (Bootloader) + fab1 PAP Mechatronic Technology LamDiNao + face Protean Synth Craft + fade Open Collector dude + feed ProgramGyar AVR-IR Sender + ffff Life2Device Smart House +120e Hudson Soft Co., Ltd +120f Magellan + 524e RoadMate 1475T + 5260 Triton Handheld GPS Receiver (300/400/500/1500/2000) +1210 DigiTech + 0016 RP500 Guitar Multi-Effects Processor + 001b RP155 Guitar Multi-Effects Processor + 001c RP255 Guitar Multi-Effects Processor +121e Jungsoft Co., Ltd + 3403 Muzio JM250 Audio Player +1220 TC Electronic + 000a Hall of Fame Reverb + 002a Polytune + 0032 Ditto X2 Looper + 0039 Alter Ego X4 Vintage Echo +1221 Unknown manufacturer + 3234 Disk (Thumb drive) +1223 SKYCABLE ENTERPRISE. CO., LTD. +1228 Datapaq Limited + 0012 Q18 Data Logger + 0015 TPaq21/MPaq21 Datalogger + 584c XL2 Logger +1230 Chipidea-Microelectronica, S.A. +1233 Denver Electronics + 5677 FUSB200 mp3 player +1234 Brain Actuated Technologies + 0000 Neural Impulse Actuator Prototype 1.0 [NIA] + 4321 Human Interface Device + ed02 Emotiv EPOC Developer Headset Wireless Dongle +1235 Focusrite-Novation + 0001 ReMOTE Audio/XStation First Edition + 0002 Speedio + 0003 RemoteSL + ZeroSL + 0004 ReMOTE LE + 0005 XIOSynth [First Edition] + 0006 XStation + 0007 XIOSynth + 0008 ReMOTE SL Compact + 0009 nIO + 000a Nocturn + 000b ReMOTE SL MkII + 000c ZeRO MkII + 000e Launchpad + 0010 Saffire 6 + 0011 Ultranova + 0012 Nocturn Keyboard + 0013 VRM Box + 0014 VRM Box Audio Class (2-out) + 0015 Dicer + 0016 Ultranova + 0018 Twitch + 0019 Impulse 25 + 001a Impulse 49 + 001b Impulse 61 + 4661 ReMOTE25 + 8000 Scarlett 18i6 + 8002 Scarlett 8i6 + 8006 Focusrite Scarlett 2i2 + 8008 Saffire 6 + 800a Scarlett 2i4 + 800c Scarlett 18i20 + 800e iTrack Solo + 8010 Forte + 8012 Scarlett 6i6 + 8014 Scarlett 18i8 + 8016 Focusrite Scarlett 2i2 + 8203 Focusrite Scarlett 6i6 + 8204 Scarlett 18i8 2nd Gen +1241 Belkin + 0504 Wireless Trackball Keyboard + 1111 Mouse + 1122 Typhoon Stream Optical Mouse USB+PS/2 + 1155 Memorex Optical ScrollPro Mouse SE MX4600 + 1166 MI-2150 Trust Mouse + 1177 Mouse [HT82M21A] + 1503 Keyboard + 1603 Keyboard + f767 Keyboard +124a AirVast + 168b PRISM3 WLAN Adapter + 4017 PC-Chips 802.11b Adapter + 4023 WM168g 802.11bg Wireless Adapter [Intersil ISL3886] + 4025 IOGear GWU513 v2 802.11bg Wireless Adapter [Intersil ISL3887] +124b Nyko (Honey Bee) + 4d01 Airflo EX Joystick +124c MXI - Memory Experts International, Inc. + 3200 Stealth MXP 1GB +125c Apogee Inc. + 0010 Alta series CCD +125f A-DATA Technology Co., Ltd. + 312a Superior S102 + 312b Superior S102 Pro + a15a DashDrive Durable HD710 portable HDD various size + a22a DashDrive Elite HE720 500GB + a91a Portable HDD CH91 + c08a C008 Flash Drive + c81a Flash drive + c93a 4GB Pen Drive + c96a C906 Flash Drive + cb10 Dash Drive UV100 + cb20 DashDrive UV110 +1260 Standard Microsystems Corp. + ee22 SMC2862W-G v3 EZ Connect 802.11g Adapter [Intersil ISL3887] +1264 Covidien Energy-based Devices +1266 Pirelli Broadband Solutions + 6302 Fastweb DRG A226M ADSL Router +1267 Logic3 / SpectraVideo plc + 0103 G-720 Keyboard + 0201 Mouse + 0210 LG Optical Mouse 3D-310 + a001 JP260 PC Game Pad + c002 Wireless Optical Mouse +126c Aristocrat Technologies +126d Bel Stewart +126e Strobe Data, Inc. +126f TwinMOS + 0163 Storage device (2gB thumb drive) + 1325 Mobile Disk + 2168 Mobile Disk III + a006 G240 802.11bg +1274 Ensoniq +1275 Xaxero Marine Software Engineering, Ltd. + 0002 WeatherFax 2000 Demodulator + 0080 SkyEye Weather Satellite Receiver +1278 Starlight Xpress + 0105 SXV-M5 + 0107 SXV-M7 + 0109 SXV-M9 + 0110 SXVF-H16 + 0115 SXVF-H5 + 0119 SXV-H9 + 0135 SXVF-H35 + 0136 SXVF-H36 + 0200 SXV interface for paraller MX cameras + 0305 SXV-M5C + 0307 SXV-M7C + 0319 SXV-H9C + 0325 SXV-M25C + 0326 SXVR-M26C + 0507 Lodestar autoguider + 0517 CoStar +1283 zebris Medical GmbH + 0100 USB-RS232 Adaptor + 0110 CMS20 + 0111 CMS 10 + 0112 CMS 05 + 0114 ARCUS digma PC-Interface + 0115 SAM Axioquick recorder + 0116 SAM Axioquick recorder + 0120 emed-X + 0121 emed-AT + 0130 PDM + 0150 CMS10GI (Golf) +1286 Marvell Semiconductor, Inc. + 00bc Marvell JTAG Probe + 1fab 88W8338 [Libertas] 802.11g + 2001 88W8388 802.11a/b/g WLAN + 2006 88W8362 802.11n WLAN + 203c K30326 802.11bgn Wireless Module [Marvell 88W8786U] + 8001 BLOB boot loader firmware +1291 Qualcomm Flarion Technologies, Inc. / Leadtek Research, Inc. + 0010 FDM 2xxx Flash-OFDM modem + 0011 LR7F06/LR7F14 Flash-OFDM modem +1292 Innomedia + 0258 Creative Labs VoIP Blaster + 4154 Retro Link Atari cable +1293 Belkin Components [hex] + 0002 F5U002 Parallel Port [uss720] + 2101 104-key keyboard +1294 RISO KAGAKU CORP. + 1320 Webmail Notifier +1297 DekTec + 020f DTU-215 Multi-Standard Modulator +129b CyberTAN Technology + 160b Siemens S30853-S1031-R351 802.11g Wireless Adapter [Atheros AR5523] + 160c Siemens S30853-S1038-R351 802.11g Wireless Adapter [Atheros AR5523] + 1666 TG54USB 802.11bg + 1667 802.11bg + 1828 Gigaset USB Adapter 300 +12a7 Trendchip Technologies Corp. +12ab Honey Bee Electronic International Ltd. +12b8 Zhejiang Xinya Electronic Technology Co., Ltd. +12b9 E28 +12ba Licensed by Sony Computer Entertainment America + 0032 Wireless Stereo Headset + 0042 Wireless Stereo Headset + 00ff Rocksmith Guitar Adapter + 0100 RedOctane Guitar for PlayStation(R)3 + 0120 RedOctane Drum Kit for PlayStation(R)3 + 0200 Harmonix Guitar for PlayStation(R)3 + 0210 Harmonix Drum Kit for PlayStation(R)3 +12bd Gembird + d012 JPD Shockforce gamepad + d015 Generic 4-button NES USB Controller +12c4 Autocue Group Ltd + 0006 Teleprompter Two-button Hand Control (v1) + 0008 Teleprompter Foot Control (v1) +12cf DEXIN + 0170 Tt eSPORTS BLACK Gaming mouse + 600b Cougar 600M Gaming Mouse +12d1 Huawei Technologies Co., Ltd. + 1001 E161/E169/E620/E800 HSDPA Modem + 1003 E220 HSDPA Modem / E230/E270/E870 HSDPA/HSUPA Modem + 1004 E220 (bis) + 1009 U120 + 1010 ETS2252+ CDMA Fixed Wireless Terminal + 1021 U8520 + 1035 U8120 + 1037 Ideos + 1038 Ideos (debug mode) + 1039 Ideos (tethering mode) + 1052 MT7-L09 + 1404 EM770W miniPCI WCDMA Modem + 1406 E1750 + 140b EC1260 Wireless Data Modem HSD USB Card + 140c E180v + 1412 EC168c + 1436 Broadband stick + 1446 HSPA modem + 1465 K3765 HSPA + 14ac E815 + 14c3 K5005 Vodafone LTE/UMTS/GSM Modem/Networkcard + 14c8 K5005 Vodafone LTE/UMTS/GSM MOdem/Networkcard + 14c9 K3770 3G Modem + 14cf K3772 + 14d1 K3770 3G Modem (Mass Storage Mode) + 14db E353/E3131 + 14dc E33372 LTE/UMTS/GSM HiLink Modem/Networkcard + 14f1 Gobi 3000 HSPA+ Modem + 14fe Modem (Mass Storage Mode) + 1501 Pulse + 1505 E398 LTE/UMTS/GSM Modem/Networkcard + 1506 Modem/Networkcard + 150a E398 LTE/UMTS/GSM Modem/Networkcard + 1520 K3765 HSPA + 1521 K4505 HSPA+ + 155a R205 Mobile WiFi (CD-ROM mode) + 1575 K5150 LTE modem + 15bb ME936 LTE/HSDPA+ 4G modem + 15c1 ME906s LTE M.2 Module + 15ca E3131 3G/UMTS/HSPA+ Modem (Mass Storage Mode) + 1805 AT&T Go Phone U2800A phone + 1c05 Broadband stick (modem on) + 1c0b E173s 3G broadband stick (modem off) + 1c20 R205 Mobile WiFi (Charging) + 1d50 ET302s TD-SCDMA/TD-HSDPA Mobile Broadband + 1f01 E353/E3131 (Mass storage mode) + 1f16 K5150 LTE modem (Mass Storage Mode) + 380b WiMAX USB modem(s) +12d2 LINE TECH INDUSTRIAL CO., LTD. +12d6 EMS Dr. Thomas Wuensche + 0444 CPC-USB/ARM7 + 0888 CPC-USB/M16C +12d7 BETTER WIRE FACTORY CO., LTD. +12d8 Araneus Information Systems Oy + 0001 Alea I True Random Number Generator +12e6 Waldorf Music GmbH + 0013 Blofeld +12ef Tapwave, Inc. + 0100 Tapwave Handheld [Tapwave Zodiac] +12f2 ViewPlus Technologies, Inc. + 000a Braille embosser [SpotDot Emprint] +12f5 Dynamic System Electronics Corp. +12f7 Memorex Products, Inc. + 1a00 TD Classic 003B + 1e23 TravelDrive 2007 Flash Drive +12fd AIN Comm. Technology Co., Ltd + 1001 AWU2000b 802.11b Stick +12ff Fascinating Electronics, Inc. + 0101 Advanced RC Servo Controller +1307 Transcend Information, Inc. + 0163 256MB/512MB/1GB Flash Drive + 0165 2GB/4GB/8GB Flash Drive + 0190 Ut190 8 GB Flash Drive with MicroSD reader + 0310 SD/MicroSD CardReader [hama]/IT1327E [Basic Line flash drive] + 0330 63-in-1 Multi-Card Reader/Writer + 0361 CR-75: 51-in-1 Card Reader/Writer [Sakar] + 1169 TS2GJF210 JetFlash 210 2GB + 1171 Fingerprint Reader +1308 Shuttle, Inc. + 0003 VFD Module + c001 eHome Infrared Transceiver +1310 Roper + 0001 Class 1 Bluetooth Dongle +1312 ICS Electronics +1313 ThorLabs + 0010 LC1 Linear Camera (Jungo) + 0011 SP1 Spectrometer (Jungo) + 0012 SP2 Spectrometer (Jungo) + 0110 LC1 Linear Camera (VISA) + 0111 SP1 Spectrometer (VISA) + 0112 SP2 Spectrometer (VISA) + 8001 TXP-Series Slot (TXP5001, TXP5004) + 8012 BC106 Camera Beam Profiler + 8013 WFS10 Wavefront Sensor + 8017 BC206 Camera Beam Profiler + 8019 BP2 Multi Slit Beam Profiler + 8020 PM300 Optical Power Meter + 8021 PM300E Optical Power and Energy Meter + 8022 PM320E Optical Power and Energy Meter + 8030 ER100 Extinction Ratio Meter + 8070 PM100D + 8072 PM100USB Power and Energy Meter Interface + 8078 PM100D Compact Power and Energy Meter Console + 8080 CCS100 - Compact Spectrometer +131d Natural Point + 0155 TrackIR 3 Pro Head Tracker + 0156 TrackIR 4 Pro Head Tracker + 0158 TrackIR 5 Pro Head Tracker +1325 ams AG + 4002 I2C Dongle +132a Envara Inc. + 1502 WiND 802.11abg / 802.11bg WLAN +132b Konica Minolta + 0000 Dimage A2 Camera + 0001 Minolta DiMAGE A2 (ptp) + 0003 Dimage Xg Camera + 0006 Dimage Z2 Camera + 0007 Minolta DiMAGE Z2 (PictBridge mode) + 0008 Dimage X21 Camera + 000a Dimage Scan Dual IV AF-3200 (2891) + 000b Dimage Z10 Camera + 000d Dimage X50 Camera [storage?] + 000f Dimage X50 Camera [p2p?] + 0010 Dimage G600 Camera + 0012 Dimage Scan Elite 5400 II (2892) + 0013 Dimage X31 Camera + 0015 Dimage G530 Camera + 0017 Dimage Z3 Camera + 0018 Minolta DiMAGE Z3 (PictBridge mode) + 0019 Dimage A200 Camera + 0021 Dimage Z5 Camera + 0022 Minolta DiMAGE Z5 (PictBridge mode) + 002c Dynax 5D camera + 2001 Magicolor 2400w + 2004 Magicolor 5430DL + 2005 Magicolor 2430 DL + 2029 Magicolor 5440DL + 2030 PagePro 1350E(N) + 2033 PagePro 1400W + 2043 Magicolor 2530DL + 2045 Magicolor 2500W + 2049 Magicolor 2490MF +133e Kemper Digital GmbH + 0815 Virus TI Desktop +1342 Mobility + 0200 EasiDock 200 Hub + 0201 EasiDock 200 Keyboard and Mouse Port + 0202 EasiDock 200 Serial Port + 0203 EasiDock 200 Printer Port + 0204 Ethernet + 0304 EasiDock Ethernet +1343 Citizen Systems + 0002 CW-01 + 0003 CX / DNP DS40 + 0004 CX-W / DNP DS80 / Mitsubishi CP3800 + 0005 CY / DNP DSRX1 + 0006 CW-02 + 0007 DNP DS80DX + 0008 CX2 / DNP DS620 +1345 Sino Lite Technology Corp. + 001c Xbox Controller Hub + 6006 Defender Wireless Controller +1347 Moravian Instruments + 0400 G2CCD USB 1.1 obsolete + 0401 G2CCD-S with Sony ICX285 CCD + 0402 G2CCD2 + 0403 G2/G3CCD-I KAI CCD + 0404 G2/G3/G4 CCD-F KAF CCD + 0405 Gx CCD-I CCD + 0406 Gx CCD-F CCD + 0410 G1-0400 CCD + 0411 G1-0800 CCD + 0412 G1-0300 CCD + 0413 G1-2000 CCD + 0414 G1-1400 CCD + 0415 G1-1200 CCD + 04b0 Gx CCD-B CCD + 04b1 Gx CCD-BI CCD +1348 Katsuragawa Electric Co., Ltd. +134c PanJit International Inc. + 0001 Touch Panel Controller + 0002 Touch Panel Controller + 0003 Touch Panel Controller + 0004 Touch Panel Controller +134e Digby's Bitpile, Inc. DBA D Bit +1357 P&E Microcomputer Systems + 0089 OpenSDA - CDC Serial Port + 0503 USB-ML-12 HCS08/HCS12 Multilink + 0504 DEMOJM +135f Control Development Inc. + 0110 Linear Spectrograph + 0111 Spectrograph - Renumerated + 0200 Linear Spectrograph + 0201 Spectrograph - Renumerated + 0240 MPP Spectrograph +1366 SEGGER + 0101 J-Link PLUS +136b STEC +136e Andor Technology Ltd. + 0012 iXon Ultra CCD + 0014 Zyla 5.5 sCMOS camera +1370 Swissbit + 0323 Swissmemory cirrusWHITE + 6828 Victorinox Flash Drive +1371 CNet Technology Inc. + 0001 CNUSB-611AR Wireless Adapter-G [AT76C503] + 0002 CNUSB-611AR Wireless Adapter-G [AT76C503] (FiberLine WL-240U) + 0013 CNUSB-611 Wireless Adapter [AT76C505] + 0014 CNUSB-611 Wireless Adapter [AT76C505] (FiberLine WL-240U) + 5743 CNUSB-611 (D) Wireless Adapter [AT76C503] + 9022 CWD-854 [RT2573] + 9032 CWD-854 rev F + 9401 CWD-854 Wireless 802.11g 54Mbps Network Adapter [RTL8187] +1376 Vimtron Electronics Co., Ltd. +1377 Sennheiser electronic GmbH & Co. KG + 4000 HDVD800 +137b SCAPS GmbH + 0002 SCAPS USC-2 Scanner Controller +1385 Netgear, Inc + 4250 WG111T + 4251 WG111T (no firmware) + 5f00 WPN111 RangeMax(TM) Wireless USB 2.0 Adapter + 5f01 WPN111 (no firmware) + 5f02 WPN111 (no firmware) + 6e00 WPNT121 802.11g 240Mbps Wireless Adapter [Airgo AGN300] +138a Validity Sensors, Inc. + 0001 VFS101 Fingerprint Reader + 0005 VFS301 Fingerprint Reader + 0007 VFS451 Fingerprint Reader + 0008 VFS300 Fingerprint Reader + 0010 VFS Fingerprint sensor + 0011 VFS5011 Fingerprint Reader + 0015 VFS 5011 fingerprint sensor + 0017 VFS 5011 fingerprint sensor + 0018 Fingerprint scanner + 003c VFS471 Fingerprint Reader + 003d VFS491 + 003f VFS495 Fingerprint Reader + 0050 Swipe Fingerprint Sensor + 0090 VFS7500 Touch Fingerprint Sensor + 0091 VFS7552 Touch Fingerprint Sensor +138e Jungo LTD + 9000 Raisonance S.A. STM32 ARM evaluation board / RLink dongle +1390 TOMTOM B.V. + 0001 GO 520 T/GO 630/ONE XL (v9) + 5454 Blue & Me 2 + 7474 GPS Sport Watch [Runner, Multi-Sport] + a001 Bandit Action Camera Batt-Stick +1391 IdealTEK, Inc. + 1000 URTC-1000 +1395 Sennheiser Communications + 0025 Headset [PC 8] + 0046 PXC 550 + 3556 USB Headset +1397 BEHRINGER International GmbH + 00bc BCF2000 +1398 Q-tec + 2103 USB 2.0 Storage Device +13ad Baltech + 9999 Card reader +13b0 PerkinElmer Optoelectronics + 000a Alesis Photon X25 MIDI Controller +13b1 Linksys + 000a WUSB54G v2 802.11g Adapter [Intersil ISL3887] + 000b WUSB11 v4.0 802.11b Adapter [ALi M4301] + 000c WUSB54AG 802.11a/g Adapter [Intersil ISL3887] + 000d WUSB54G v4 802.11g Adapter [Ralink RT2500USB] + 000e WUSB54GS v1 802.11g Adapter [Broadcom 4320 USB] + 0011 WUSB54GP v4.0 802.11g Adapter [Ralink RT2500USB] + 0014 WUSB54GS v2 802.11g Adapter [Broadcom 4320 USB] + 0018 USB200M 10/100 Ethernet Adapter + 001a HU200TS Wireless Adapter + 001e WUSBF54G 802.11bg + 0020 WUSB54GC v1 802.11g Adapter [Ralink RT73] + 0022 WUSB54GX4 802.11g 240Mbps Wireless Adapter [Airgo AGN300] + 0023 WUSB54GR + 0024 WUSBF54G v1.1 802.11bg + 0026 WUSB54GSC v1 802.11g Adapter [Broadcom 4320 USB] + 0028 WUSB200 802.11g Adapter [Ralink RT2671] + 0029 WUSB300N 802.11bgn Wireless Adapter [Marvell 88W8362+88W8060] + 002f AE1000 v1 802.11n [Ralink RT3572] + 0031 AM10 v1 802.11n [Ralink RT3072] + 0039 AE1200 802.11bgn Wireless Adapter [Broadcom BCM43235] + 003a AE2500 802.11abgn Wireless Adapter [Broadcom BCM43236] + 003b AE3000 802.11abgn (3x3) Wireless Adapter [Ralink RT3573] + 003e AE6000 802.11a/b/g/n/ac Wireless Adapter [MediaTek MT7610U] + 003f WUSB6300 802.11a/b/g/n/ac Wireless Adapter [Realtek RTL8812AU] + 0041 Gigabit Ethernet Adapter + 0042 WUSB6100M 802.11a/b/g/n/ac Wireless Adapter + 13b1 WUSB200: Wireless-G Business Network Adapter with Rangebooster +13b2 Alesis + 0030 Multimix 8 +13b3 Nippon Dics Co., Ltd. +13ba PCPlay + 0001 Konig Electronic CMP-KEYPAD12 Numeric Keypad + 0017 PS/2 Keyboard+Mouse Adapter + 0018 Barcode PCP-BCG4209 +13be Ricoh Printing Systems, Ltd. +13ca JyeTai Precision Industrial Co., Ltd. +13cf Wisair Ltd. + 1200 Olidata Wireless Multimedia Adapter +13d0 Techsan Electronics Co., Ltd. + 2282 TechniSat DVB-PC TV Star 2 +13d1 A-Max Technology Macao Commercial Offshore Co. Ltd. + 7019 MD 82288 + abe6 Wireless 802.11g 54Mbps Network Adapter [RTL8187] +13d2 Shark Multimedia + 0400 Pocket Ethernet [klsi] +13d3 IMC Networks + 3201 VisionDTV USB-Ter/HAMA USB DVB-T device cold + 3202 VisionDTV USB-Ter/HAMA USB DVB-T device warm + 3203 DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + 3204 DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + 3205 DNTV Live! Tiny USB2 BDA (No Remote) + 3206 DNTV Live! Tiny USB2 BDA (No Remote) + 3207 DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + 3208 DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + 3209 DTV-DVB UDST7022BDA DVB-S Box(Without HID) + 3211 DTV-DVB Hybrid Analog/Capture / Pinnacle PCTV 310e + 3212 DTV-DVB UDTT704C - DVBT/NTSC/PAL Driver(PCM4) + 3213 DTV-DVB UDTT704D - DVBT/NTSC/PAL Driver (PCM4) + 3214 DTV-DVB UDTT704F -(MiniCard) DVBT/NTSC/PAL Driver(Without HID) + 3215 DTV-DVB UDAT7240 - ATSC/NTSC/PAL Driver(PCM4) + 3216 DTV-DVB UDTT 7047-USB 2.0 DVB-T Driver + 3217 Digital-TV Receiver. + 3219 DTV-DVB UDTT7049 - DVB-T Driver(Without HID) + 3220 DTV-DVB UDTT 7047M-USB 2.0 DVB-T Driver + 3223 DNTV Live! Tiny USB2 BDA (No Remote) + 3224 DNTV Live! Tiny USB2 BDA (No Remote) + 3226 DigitalNow TinyTwin DVB-T Receiver + 3234 DVB-T FTA Half Minicard [RTL2832U] + 3236 DTV-DVB UDTT 7047A-USB 2.0 DVB-T Driver + 3237 DTV-DVB UDTT 704J - dual DVB-T Driver + 3239 DTV-DVB UDTT704D - DVBT/NTSC/PAL Driver(Without HID) + 3240 DTV-DVB UDXTTM6010 - A/D Driver(Without HID) + 3241 DTV-DVB UDXTTM6010 - A/D Driver(Without HID) + 3242 DTV-DVB UDAT7240LP - ATSC/NTSC/PAL Driver(Without HID) + 3243 DTV-DVB UDXTTM6010 - A/D Driver(Without HID) + 3244 DTV-DVB UDTT 7047Z-USB 2.0 DVB-T Driver + 3247 AW-NU222 802.11bgn Wireless Module [Ralink RT2770+RT2720] + 3249 Internal Bluetooth + 3250 Broadcom Bluetooth 2.1 + 3262 802.11 n/g/b Wireless LAN USB Adapter + 3273 802.11 n/g/b Wireless LAN USB Mini-Card + 3274 DVB-T Dongle [RTL2832U] + 3282 DVB-T + GPS Minicard [RTL2832U] + 3284 Wireless LAN USB Mini-Card + 3304 Asus Integrated Bluetooth module [AR3011] + 3306 Mediao 802.11n WLAN [Realtek RTL8191SU] + 3315 Bluetooth module + 3327 AW-NU137 802.11bgn Wireless Module [Atheros AR9271] + 3362 Atheros AR3012 Bluetooth 4.0 Adapter + 3375 Atheros AR3012 Bluetooth 4.0 Adapter + 3392 Azurewave 43228+20702 + 3394 Bluetooth + 3474 Atheros AR3012 Bluetooth + 5070 Webcam + 5111 Integrated Webcam + 5115 Integrated Webcam + 5116 Integrated Webcam + 5122 2M Integrated Webcam + 5126 PC Cam + 5130 Integrated Webcam + 5134 Integrated Webcam + 5702 UVC VGA Webcam + 5710 UVC VGA Webcam + 5716 UVC VGA Webcam + 7020 DTV-DVB UDST7020BDA DVB-S Box(DVBS for MCE2005) + 7022 DTV-DVB UDST7022BDA DVB-S Box(Without HID) +13d7 Guidance Software, Inc. + 0001 T5 PATA forensic bridge + 000c T8-R2 forensic bridge +13dc ALEREON, INC. +13dd i.Tech Dynamic Limited +13e1 Kaibo Wire & Cable (Shenzhen) Co., Ltd. +13e5 Rane + 0001 SL-1 + 0003 TTM 57SL +13e6 TechnoScope Co., Ltd. +13ea Hengstler + 0001 C-56 Thermal Printer +13ec Zydacron + 0006 HID Remote Control +13ee MosArt + 0001 Optical Mouse + 0003 Optical Mouse +13fd Initio Corporation + 0840 INIC-1618L SATA + 0841 Samsung SE-T084M DVD-RW + 0940 ASUS SBW-06D2X-U + 1040 INIC-1511L PATA Bridge + 1340 Hi-Speed USB to SATA Bridge + 160f RocketFish SATA Bridge [INIC-1611] + 1640 INIC-1610L SATA Bridge + 1669 INIC-1609PN + 1840 INIC-1608 SATA bridge + 1e40 INIC-1610P SATA bridge + 2040 Samsung Writemaster external DVD writer + 3940 external DVD burner ECD819-SU3 + 3e40 ZALMAN ZM-VE350 +13fe Kingston Technology Company Inc. + 1a00 512MB/1GB Flash Drive + 1a23 512MB Flash Drive + 1d00 DataTraveler 2.0 1GB/4GB Flash Drive / Patriot Xporter 4GB Flash Drive + 1e00 Flash Drive 2 GB [ICIDU 2 GB] + 1e50 U3 Smart Drive + 1f00 Kingston DataTraveler / Patriot Xporter + 1f23 PS2232 flash drive controller + 2240 microSD card reader + 3100 2/4 GB stick + 3123 Verbatim STORE N GO 4GB + 3600 flash drive (4GB, EMTEC) + 3800 Rage XT Flash Drive + 3e00 Flash Drive + 4100 Flash drive + 5000 USB flash drive (32 GB SHARKOON Accelerate) + 5100 Flash Drive + 5200 DataTraveler R3.0 +1400 Axxion Group Corp. +1402 Bowe Bell & Howell +1403 Sitronix + 0001 Digital Photo Frame + 0003 Digital Photo Frame (DPF-1104) +1409 IDS Imaging Development Systems GmbH + 1000 generic (firmware not loaded yet) + 1485 uEye UI1485 +140e Telechips, Inc. + b011 TCC780X-based player (USB Boot mode) + b021 TCC77X-based players (USB Boot mode) +1410 Novatel Wireless + 1110 Merlin S620 + 1120 Merlin EX720 + 1130 Merlin S720 + 1400 Merlin U730/U740 (Vodafone) + 1410 Merlin U740 (non-Vodafone) + 1430 Merlin XU870 + 1450 Merlin X950D + 2110 Ovation U720/MCD3000 + 2410 Expedite EU740 + 2420 Expedite EU850D/EU860D/EU870D + 4100 U727 + 4400 Ovation MC930D/MC950D + 9010 Expedite E362 + a001 Gobi Wireless Modem + a008 Gobi Wireless Modem (QDL mode) + b001 Ovation MC551 +1415 Nam Tai E&E Products Ltd. or OmniVision Technologies, Inc. + 0000 Sony SingStar USBMIC + 0020 Sony Wireless SingStar + 2000 Sony Playstation Eye +1419 ABILITY ENTERPRISE CO., LTD. +1421 Sensor Technology + 0605 Sentech Camera +1424 Posnet Polska S.A. + 1001 Temo + 1002 Thermal + 1003 Neo + 1004 Combo DF + 1005 Thermal-A + 1006 Thermal FV + 1007 Bingo HS + 1008 Thermal HS FV + 1009 Thermal FV EJ + 100a Thermal HD + 100b Thermal + 100c Neo + 100d Ergo + 100e Trio + 1010 Thermal HS FV EJ + 1011 Neo EJ + 1012 Thermal-A + 1013 Thermal-A EJ + 1014 Mobile + 1015 Temo HS + 1016 Mobile HS + 1017 TH230+ FV EJ + 1018 4610-1NR FV EJ +1429 Vega Technologies Industrial (Austria) Co. +142a Thales E-Transactions + 0003 Artema Hybrid + 0005 Artema Modular + 0043 medCompact +142b Arbiter Systems, Inc. + 03a5 933A Portable Power Sentinel +1430 RedOctane + 0150 wireless receiver for skylanders wii + 4734 Guitar Hero4 hub + 474b Guitar Hero MIDI interface +1431 Pertech Resources, Inc. +1435 Wistron NeWeb + 0427 UR054g 802.11g Wireless Adapter [Intersil ISL3887] + 0711 UR055G 802.11bg + 0804 AR9170+AR9104 802.11abgn Wireless Adapter + 0826 AR5523 + 0827 AR5523 (no firmware) + 0828 AR5523 + 0829 AR5523 (no firmware) +1436 Denali Software, Inc. +143c Altek Corporation +1443 Digilent + 0007 Development board JTAG +1446 X.J.GROUP + 6a73 Stamps.com Model 510 5LB Scale + 6a78 DYMO Endicia 75lb Digital Scale +1451 Force Dimension + 0301 haptic device + 0302 haptic device + 0400 haptic device + 0401 delta.x haptic device + 0402 omega.x haptic device + 0403 sigma.x haptic device + 0404 haptic controller + 0405 dedicated haptic device + 0406 dedicated haptic device + 0407 dedicated haptic device + 0408 dedicated haptic device +1452 Dai Nippon Printing, Inc + 8b01 DS620 +1453 Radio Shack + 4026 26-183 Serial Cable +1456 Extending Wire & Cable Co., Ltd. +1457 First International Computer, Inc. + 5117 OpenMoko Neo1973 kernel usbnet (g_ether, CDC Ethernet) mode + 5118 OpenMoko Neo1973 Debug board (V2+) + 5119 OpenMoko Neo1973 u-boot cdc_acm serial port + 511a HXD8 u-boot usbtty CDC ACM Mode + 511b SMDK2440 u-boot usbtty CDC ACM mode + 511c SMDK2443 u-boot usbtty CDC ACM mode + 511d QT2410 u-boot usbtty CDC ACM mode + 5120 OpenMoko Neo1973 u-boot usbtty generic serial + 5121 OpenMoko Neo1973 kernel mass storage (g_storage) mode + 5122 OpenMoko Neo1973 / Neo Freerunner kernel cdc_ether USB network + 5123 OpenMoko Neo1973 internal USB CSR4 module + 5124 OpenMoko Neo1973 Bluetooth Device ID service +145f Trust + 0106 K56 V92 Modem + 013d PC Camera (SN9C201 + OV7660) + 013f Megapixel Auto Focus Webcam + 0142 WB-6250X Webcam + 015a WB-8300X 2MP Webcam + 0161 15901 802.11bg Wireless Adapter [Realtek RTL8187L] + 0167 Widescreen 3MP Webcam + 0176 Isla Keyboard +1460 Tatung Co. + 9150 eHome Infrared Transceiver +1461 Staccato Communications +1462 Micro Star International + 5512 MegaStick-1 Flash Stick + 8807 DIGIVOX mini III [af9015] +1472 Huawei-3Com + 0007 Aolynk WUB300g [ZyDAS ZD1211] + 0009 Aolynk WUB320g +147a Formosa Industrial Computing, Inc. + e015 eHome Infrared Receiver + e016 eHome Infrared Receiver + e017 eHome Infrared Receiver + e018 eHome Infrared Receiver + e02c Infrared Receiver + e03a eHome Infrared Receiver + e03c eHome Infrared Receiver + e03d 2 Channel Audio + e03e Infrared Receiver [IR605A/Q] +147e Upek + 1000 Biometric Touchchip/Touchstrip Fingerprint Sensor + 1001 TCS5B Fingerprint sensor + 1002 Biometric Touchchip/Touchstrip Fingerprint Sensor + 2016 Biometric Touchchip/Touchstrip Fingerprint Sensor + 2020 TouchChip Fingerprint Coprocessor (WBF advanced mode) + 3000 TCS1C EIM/Cypress Fingerprint sensor + 3001 TCS1C EIM/STM32 Fingerprint sensor +147f Hama GmbH & Co., KG +1482 Vaillant + 1005 VRD PC-Interface +1484 Elsa AG [hex] + 1746 Ecomo 19H99 Monitor + 7616 Elsa Hub +1485 Silicom + 0001 U2E + 0002 Psion Gold Port Ethernet +1487 DSP Group, Ltd. +148e EVATRONIX SA +148f Ralink Technology, Corp. + 1000 Motorola BC4 Bluetooth 3.0+HS Adapter + 1706 RT2500USB Wireless Adapter + 2070 RT2070 Wireless Adapter + 2570 RT2570 Wireless Adapter + 2573 RT2501/RT2573 Wireless Adapter + 2671 RT2601/RT2671 Wireless Adapter + 2770 RT2770 Wireless Adapter + 2870 RT2870 Wireless Adapter + 3070 RT2870/RT3070 Wireless Adapter + 3071 RT3071 Wireless Adapter + 3072 RT3072 Wireless Adapter + 3370 RT3370 Wireless Adapter + 3572 RT3572 Wireless Adapter + 3573 RT3573 Wireless Adapter + 5370 RT5370 Wireless Adapter + 5372 RT5372 Wireless Adapter + 5572 RT5572 Wireless Adapter + 7601 MT7601U Wireless Adapter + 760b MT7601U Wireless Adapter + 761a MT7610U ("Archer T2U" 2.4G+5G WLAN Adapter + 9020 RT2500USB Wireless Adapter + 9021 RT2501USB Wireless Adapter +1491 Futronic Technology Co. Ltd. + 0020 FS81 Fingerprint Scanner Module + 0088 Fingerprint Scanner Model FS88 +1493 Suunto + 0010 Bluebird [Ambit] + 0019 Duck [Ambit2] + 001a Colibri [Ambit2 S] + 001b Emu [Ambit3 Peak] + 001c Finch [Ambit3 Sport] + 001d Greentit [Ambit2 R] + 001e Ibisbill [Ambit3 Run] +1497 Panstrong Company Ltd. +1498 Microtek International Inc. + a090 DVB-T Tuner +149a Imagination Technologies + 2107 DBX1 DSP core +14aa WideView Technology Inc. + 0001 Avermedia AverTV DVBT USB1.1 (cold) + 0002 Avermedia AverTV DVBT USB1.1 (warm) + 0201 AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0 (cold) + 0221 WT-220U DVB-T dongle + 022b WT-220U DVB-T dongle + 0301 AVermedia/Yakumo/Hama/Typhoon DVB-T USB2.0 (warm) +14ad CTK Corporation +14ae Printronix Inc. +14af ATP Electronics Inc. +14b0 StarTech.com Ltd. +14b2 Ralink Technology, Corp. + 3a93 Topcom 802.11bg Wireless Adapter [Atheros AR5523] + 3a95 Toshiba WUS-G06G-JT 802.11bg Wireless Adapter [Atheros AR5523] + 3a98 Airlink101 AWLL4130 802.11bg Wireless Adapter [Atheros AR5523] + 3c02 Conceptronic C54RU v2 802.11bg Wireless Adapter [Ralink RT2571] + 3c05 rt2570 802.11g WLAN + 3c06 Conceptronic C300RU v1 802.11bgn Wireless Adapter [Ralink RT2870] + 3c07 802.11n adapter + 3c09 802.11n adapter + 3c22 Conceptronic C54RU v3 802.11bg Wireless Adapter [Ralink RT2571W] + 3c23 Airlink101 AWLL6080 802.11bgn Wireless Adapter [Ralink RT2870] + 3c24 NEC NP01LM 802.11abg Wireless Adapter [Ralink RT2571W] + 3c25 DrayTek Vigor N61 802.11bgn Wireless Adapter [Ralink RT2870] + 3c27 Airlink101 AWLL6070 802.11bgn Wireless Adapter [Ralink RT2770] + 3c28 Conceptronic C300RU v2 802.11bgn Wireless Adapter [Ralink RT2770] + 3c2b NEC NP02LM 802.11bgn Wireless Adapter [Ralink RT3072] + 3c2c Keebox W150NU 802.11bgn Wireless Adapter [Ralink RT3070] +14c0 Rockwell Automation, Inc. +14c2 Gemlight Computer, Ltd + 0250 Storage Adapter V2 + 0350 Storage Adapter V2 +14c8 Zytronic + 0005 Touchscreen Controller +14cd Super Top + 1212 microSD card reader (SY-T18) + 121c microSD card reader + 121f microSD CardReader SY-T18 + 123a SD/MMC/RS-MMC Card Reader + 125c SD card reader + 127b SDXC Reader + 6116 M6116 SATA Bridge + 6600 M110E PATA bridge + 6700 Card Reader + 6900 Card Reader + 8123 SD MMC Reader + 8125 SD MMC Reader + 8601 4-Port hub + 8608 Hub [Super Top] +14d8 JAMER INDUSTRIES CO., LTD. +14dd Raritan Computer, Inc. + 1007 D2CIM-VUSB KVM connector +14e0 WiNRADiO Communications + 0501 WR-G528e 'CHEETAH' +14e1 Dialogue Technology Corp. + 5000 PenMount 5000 Touch Controller +14e5 SAIN Information & Communications Co., Ltd. +14ea Planex Communications + ab10 GW-US54GZ + ab11 GU-1000T + ab13 GW-US54Mini 802.11bg +14ed Shure Inc. + 29b6 X2u Adapter +14f7 TechniSat Digital GmbH + 0001 SkyStar 2 HD CI + 0002 SkyStar 2 HD CI + 0003 CableStar Combo HD CI + 0004 AirStar TeleStick 2 + 0500 DVB-PC TV Star HD +1500 Ellisys +1501 Pine-Tum Enterprise Co., Ltd. +1509 First International Computer, Inc. + 0a01 LI-3100 Area Meter + 0a02 LI-7000 CO2/H2O Gas Analyzer + 0a03 C-DiGit Blot Scanner + 9242 eHome Infrared Transceiver +1513 medMobile + 0444 medMobile +1514 Actel + 2003 FlashPro3 Programmer + 2004 FlashPro3 Programmer + 2005 FlashPro3 Programmer +1516 CompUSA + 1603 Flash Drive + 8628 Pen Drive +1518 Cheshire Engineering Corp. + 0001 HDReye High Dynamic Range Camera + 0002 HDReye (before firmware loads) +1519 Comneon + 0020 HSIC Device +151f Opal Kelly Incorporated + 0020 XEM3001v1 + 0021 XEM3001v2 + 0022 XEM3010 + 0023 XEM3005 + 0028 XEM3050 + 002b XEM5010 + 002c XEM6001 + 002d XEM6010-LX45 + 002e XEM6010-LX150 + 0030 XEM6006-LX16 + 0033 XEM6002-LX9 + 0034 XEM7001-A15 + 0036 XEM7010-A50 + 0037 XEM7010-A200 + 0120 ZEM4310 + 0121 XEM6310-LX45 + 0122 XEM6310-LX150 + 0123 XEM6310MT-LX45T + 0125 XEM7350-K70T + 0126 XEM7350-K160T + 0127 XEM7350-K410T + 0128 XEM6310MT-LX150T + 0129 ZEM5305-A2 + 012b XEM7360-K160T + 012c XEM7360-K410T + 012d ZEM5310-A4 + 0130 XEM7310-A75 + 0131 XEM7310-A200 +1520 Bitwire Corp. +1524 ENE Technology Inc + 6680 UTS 6680 +1527 Silicon Portals + 0200 YAP Phone (no firmware) + 0201 YAP Phone +1529 UBIQUAM Co., Ltd. + 3100 CDMA 1xRTT USB Modem (U-100/105/200/300/520) +152a Thesycon Systemsoftware & Consulting GmbH + 8350 NET Gmbh iCube Camera + 8400 INI DVS128 + 840d INI DAViS + 841a INI DAViS FX3 +152b MIR Srl + 0001 spirobank II + 0002 spirolab III + 0003 MiniSpir + 0004 Oxi + 0005 spiros II + 0006 smiths spirobank II + 0007 smiths spirobank G-USB + 0008 smiths MiniSpir + 0009 spirobank G-USB + 000a smiths Oxi + 000b smiths spirolab III + 000c chorus III + 000d spirolab III Bw + 000e spirolab III + 000f easySpiro + 0010 Spirotel converter + 0011 spirobank + 0012 spiro3 Zimmer + 0013 spirotel serial + 0014 spirotel II + 0015 spirodoc +152d JMicron Technology Corp. / JMicron USA Technology Corp. + 0539 JMS539/567 SuperSpeed SATA II/III 3.0G/6.0G Bridge + 0551 JMS551 SuperSpeed two ports SATA 3Gb/s bridge + 0561 JMS551 - Sharkoon SATA QuickPort Duo + 0567 JMS567 SATA 6Gb/s bridge + 0578 JMS567 SATA 6Gb/s bridge + 0770 Alienware Integrated Webcam + 1561 JMS561U two ports SATA 6Gb/s bridge + 2329 JM20329 SATA Bridge + 2335 ATA/ATAPI Bridge + 2336 Hard Disk Drive + 2337 ATA/ATAPI Bridge + 2338 JM20337 Hi-Speed USB to SATA & PATA Combo Bridge + 2339 JM20339 SATA Bridge + 2352 ATA/ATAPI Bridge + 2509 JMS539, JMS551 SATA 3Gb/s bridge + 2551 JMS551 SATA 3Gb/s bridge + 2561 CEB-2235S-U3 external RAID box + 2566 JMS566 SATA 3Gb/s bridge + 2590 JMS567 SATA 6Gb/s bridge + 3562 JMS567 SATA 6Gb/s bridge + 3569 JMS566 SATA 3Gb/s bridge +152e LG (HLDS) + 2507 PL-2507 IDE Controller + e001 GSA-5120D DVD-RW +1532 Razer USA, Ltd + 0001 RZ01-020300 Optical Mouse [Diamondback] + 0003 Krait Mouse + 0007 DeathAdder Mouse + 0013 Orochi mouse + 0015 Naga Mouse + 0016 DeathAdder Mouse + 0017 RZ01-0035 Laser Gaming Mouse [Imperator] + 001c RZ01-0036 Optical Gaming Mouse [Abyssus] + 0024 Mamba + 002e RZ01-0058 Gaming Mouse [Naga] + 002f Imperator 2012 + 0036 RZ01-0075, Gaming Mouse [Naga Hex] + 0042 Abyssus 2014 + 0043 DeathAdder Chroma + 0044 Mamba Chroma (Wired) + 0045 Mamba Chroma (Wireless) + 0046 Mamba 2015 Tournament Edition [RZ01-01370100-R3] + 0048 Orochi (Wired) + 0101 Copperhead Mouse + 0102 Tarantula Keyboard + 0109 Lycosa Keyboard + 010d BlackWidow Ultimate 2012 + 0113 RZ07-0074 Gaming Keypad [Orbweaver] + 0118 RZ03-0080, Gaming Keyboard [Deathstalker] + 011a BlackWidow Ultimate 2013 + 011b BlackWidow Classic + 0203 BlackWidow Chroma + 0205 Blade Stealth + 0208 Tartarus + 0209 BlackWidow Tournament Edition Chroma + 0214 BlackWidow Ultimate 2016 + 0216 BlackWidow X Chroma + 021a BlackWidow X Tournament Edition Chroma + 0220 Blade Stealth (2016) + 0300 RZ06-0063 Motion Sensing Controllers [Hydra] + 0c00 Firefly +153b TerraTec Electronic GmbH + 1181 Cinergy S2 PCIe Dual Port 1 + 1182 Cinergy S2 PCIe Dual Port 2 +1546 U-Blox AG + 01a4 Antaris 4 + 01a5 [u-blox 5] + 01a6 [u-blox 6] + 01a7 [u-blox 7] + 01a8 [u-blox 8] + 1102 LISA-U2 +1547 SG Intec Ltd & Co KG + 1000 SG-Lock[U2] +154a Celectronic GmbH + 8180 CARD STAR/medic2 +154b PNY + 0010 USB 2.0 Flash Drive + 0048 Flash Drive + 004d 8 GB Flash Drive + 0053 Flash Drive + 0057 32GB Micro Slide Attache Flash Drive + 005b Flash Drive + 0062 Flash Drive + 007a Classic Attache Flash Drive + 6545 FD Device + fa05 Flash Drive +154d ConnectCounty Holdings Berhad +154e D&M Holdings, Inc. (Denon/Marantz) + 3000 Marantz RC9001 Remote Control +154f SNBC CO., Ltd +1554 Prolink Microsystems Corp. + 5010 PV-D231U(RN)-F [PixelView PlayTV SBTVD Full-Seg] +1557 OQO + 0002 model 01 WiFi interface + 0003 model 01 Bluetooth interface + 0a80 Gobi Wireless Modem (QDL mode) + 7720 model 01+ Ethernet + 8150 model 01 Ethernet interface +1568 Sunf Pu Technology Co., Ltd +156f Quantum Corporation +1570 ALLTOP TECHNOLOGY CO., LTD. +157b Ketron SRL +157e TRENDnet + 3006 TEW-444UB EU [TRENDnet] + 3007 TEW-444UB EU (no firmware) + 300a TEW-429UB 802.11bg + 300b TEW-429UB 802.11bg + 300c TEW-429UF A1 802.11bg Wireless Adapter [ZyDAS ZD1211B] + 300d TEW-429UB C1 802.11bg + 300e SMC SMCWUSB-N 802.11bgn 2x2:2 Wireless Adapter [Ralink RT2870] + 3012 TEW-604UB 802.11bg Wireless Adapter [Atheros AR5523] + 3013 TEW-645UB 802.11bgn 1x2:2 Wireless Adapter [Ralink RT2770] + 3204 Allnet ALL0298 v2 802.11bg + 3205 Allnet ALL0283 [AR5523] + 3206 Allnet ALL0283 [AR5523](no firmware) + 3207 TEW-509UB A1 802.11abg Wireless Adapter [ZyDAS ZD1211] + 3208 TEW-509UB 1.1R 802.11abg Wireless Adapter +1582 Fiberline + 6003 WL-430U 802.11bg +1587 SMA Technologie AG +158d Oakley Inc. +158e JDS Uniphase Corporation (JDSU) + 0820 SmartPocket Class Device +1598 Kunshan Guoji Electronics Co., Ltd. +15a2 Freescale Semiconductor, Inc. + 0038 9S08JS Bootloader + 003b USB2CAN Application for ColdFire DEMOJM board + 0042 OSBDM - Debug Port + 004f i.MX28 SystemOnChip in RecoveryMode + 0052 i.MX50 SystemOnChip in RecoveryMode + 0054 i.MX 6Dual/6Quad SystemOnChip in RecoveryMode + 0061 i.MX 6Solo/6DualLite SystemOnChip in RecoveryMode +15a4 Afatech Technologies, Inc. + 1000 AF9015/AF9035 DVB-T stick + 1001 AF9015/AF9035 DVB-T stick + 1336 SDHC/MicroSD/MMC/MS/M2/CF/XD Flash Card Reader + 9015 AF9015 DVB-T USB2.0 stick + 9016 AF9015 DVB-T USB2.0 stick +15a8 Teams Power Limited +15a9 Gemtek + 0002 SparkLAN WL-682 802.11bg Wireless Adapter [Intersil ISL3887] + 0004 WUBR-177G [Ralink RT2571W] + 0006 Wireless 11n USB Adapter + 0010 802.11n USB Wireless Card + 0012 WUBR-208N 802.11abgn Wireless Adapter [Ralink RT2870] + 002d WLTUBA-107 [Yota 4G LTE] +15aa Gearway Electronics (Dong Guan) Co., Ltd. +15ad VMware Inc. +15ba Olimex Ltd. + 0003 OpenOCD JTAG + 0004 OpenOCD JTAG TINY + 002a ARM-USB-TINY-H JTAG interface + 002b ARM-USB-OCD-H JTAG+RS232 +15c0 XL Imaging + 0001 2M pixel Microscope Camera + 0002 3M pixel Microscope Camera + 0003 1.3M pixel Microscope Camera (mono) + 0004 1.3M pixel Microscope Camera (colour) + 0005 3M pixel Microscope Camera (Mk 2) + 0006 2M pixel Microscope Camera (with capture button) + 0007 3M pixel Microscope Camera (with capture button) + 0008 1.3M pixel Microscope Camera (colour, with capture button) + 0009 1.3M pixel Microscope Camera (colour, with capture button) + 000a 2M pixel Microscope Camera (Mk 2) + 0010 1.3M pixel "Tinycam" + 0101 3M pixel Microscope Camera +15c2 SoundGraph Inc. + 0036 LC16M VFD Display/IR Receiver + 0038 GD01 MX LCD Display/IR Receiver + 0042 Antec Veris Multimedia Station E-Z IR Receiver + ffda iMON PAD Remote Controller + ffdc iMON PAD Remote Controller +15c5 Advance Multimedia Internet Technology Inc. (AMIT) + 0008 WL532U 802.11g Adapter +15c6 Laboratoires MXM + 1000 DigistimSP (cold) + 1001 DigistimSP (warm) + 1002 DigimapSP USB (cold) + 1003 DigimapSP USB (warm) + 1004 DigistimSP (cold) + 1005 DigistimSP (warm) + 1100 Odyssee (cold) + 1101 Odyssee (warm) + 1200 Digispy +15c8 KTF Technologies + 3201 EVER EV-W100/EV-W250 +15c9 D-Box Technologies +15ca Textech International Ltd. + 00c3 Mini Optical Mouse + 0101 MIDI Interface cable + 1806 MIDI Interface cable +15d5 Coulomb Electronics Ltd. +15d9 Trust International B.V. + 0a33 Optical Mouse + 0a37 Mouse + 0a41 MI-2540D [Optical mouse] + 0a4c USB+PS/2 Optical Mouse + 0a4d Optical Mouse + 0a4f Optical Mouse +15dc Hynix Semiconductor Inc. +15e0 Seong Ji Industrial Co., Ltd. +15e1 RSA + 2007 RSA SecurID (R) Authenticator +15e4 Numark + 0024 Mixtrack + 0140 ION VCR 2 PC / Video 2 PC +15e8 SohoWare + 9100 NUB100 Ethernet [pegasus] + 9110 10/100 USB Ethernet +15e9 Pacific Digital Corp. + 04ce MemoryFrame MF-570 + 1968 MemoryFrame MF-570 + 1969 Digital Frame +15ec Belcarra Technologies Corp. +15f4 HanfTek + 0001 HanfTek UMT-010 USB2.0 DVB-T (cold) + 0025 HanfTek UMT-010 USB2.0 DVB-T (warm) + 0135 Astrometa T2hybrid +1604 Tascam + 8000 US-428 Audio/Midi Controller (without fw) + 8001 US-428 Audio/Midi Controller + 8004 US-224 Audio/Midi Controller (without fw) + 8005 US-224 Audio/Midi Controller + 8006 US-122 Audio/Midi Interface (without fw) + 8007 US-122 Audio/Midi Interface +1605 ACCES I/O Products, Inc. + 0001 DIO-32 (No Firmware Yet) +1606 Umax + 0002 Astra 1236U Scanner + 0010 Astra 1220U + 0030 Astra 1600U/2000U + 0050 Scanner + 0060 Astra 3400/3450 + 0070 Astra 4400/4450 + 0130 Astra 2100U + 0160 Astra 5400U + 0170 Uniscan D50 + 0230 Astra 2200/2200SU + 0350 Astra 4800/4850 Scanner + 1030 Astra 4000U + 1220 Genesys Logic Scanner Controller NT5.0 + 2010 AstraCam Digital Camera + 2020 AstraCam 1000 + 2030 AstraCam 1800 Digital Camera +1608 Inside Out Networks [hex] + 0001 EdgePort/4 Serial Port + 0002 Edgeport/8 + 0003 Rapidport/4 + 0004 Edgeport/4 + 0005 Edgeport/2 + 0006 Edgeport/4i + 0007 Edgeport/2i + 0008 Edgeport/8 + 000c Edgeport/421 + 000d Edgeport/21 + 000e Edgeport/4 + 000f Edgeport/8 + 0010 Edgeport/2 + 0011 Edgeport/4 + 0012 Edgeport/416 + 0014 Edgeport/8i + 0018 Edgeport/412 + 0019 Edgeport/412 + 001a Edgeport/2+2i + 0101 Edgeport/4 + 0105 Edgeport/2 + 0106 Edgeport/4i + 0107 Edgeport/2i + 010c Edgeport/421 + 010d Edgeport/21 + 0110 Edgeport/2 + 0111 Edgeport/4 + 0112 Edgeport/416 + 0114 Edgeport/8i + 0201 Edgeport/4 + 0203 Rapidport/4 + 0204 Edgeport/4 + 0205 Edgeport/2 + 0206 Edgeport/4i + 0207 Edgeport/2i + 020c Edgeport/421 + 020d Edgeport/21 + 020e Edgeport/4 + 020f Edgeport/8 + 0210 Edgeport/2 + 0211 Edgeport/4 + 0212 Edgeport/416 + 0214 Edgeport/8i + 0215 Edgeport/1 + 0216 EPOS/44 + 0217 Edgeport/42 + 021a Edgeport/2+2i + 021b Edgeport/2c + 021c Edgeport/221c + 021d Edgeport/22c + 021e Edgeport/21c + 021f Edgeport/62 + 0240 Edgeport/1 + 0241 Edgeport/1i + 0242 Edgeport/4s + 0243 Edgeport/8s + 0244 Edgeport/8 + 0245 Edgeport/22c + 0301 Watchport/P + 0302 Watchport/M + 0303 Watchport/W + 0304 Watchport/T + 0305 Watchport/H + 0306 Watchport/E + 0307 Watchport/L + 0308 Watchport/R + 0309 Watchport/A + 030a Watchport/D + 030b Watchport/D + 030c Power Management Port + 030e Power Management Port + 030f Watchport/G + 0310 Watchport/Tc + 0311 Watchport/Hc + 1403 MultiTech Systems MT4X56 Modem + 1a17 Agilent Technologies (E6473) +160a VIA Technologies, Inc. + 3184 VIA VNT-6656 [WiFi 802.11b/g USB Dongle] +160e INRO + 0001 E2USBKey +1614 Amoi Electronics + 0404 WMA9109 UMTS Phone + 0600 Vodafone VDA GPS / Toschiba Protege G710 + 0804 WP-S1 Phone +1617 Sony Corp. + 2002 NVX-P1 Personal Navigation System +1619 L & K Precision Technology Co., Ltd. +161c Digitech Systems + 0002 DTC-02U [Digi Touch Controller] +1621 Wionics Research +1628 Stonestreet One, Inc. +162a Airgo Networks Inc. +162f WiQuest Communications, Inc. +1630 2Wire, Inc. + 0005 802.11g Wireless Adapter [Intersil ISL3886] + 0011 PC Port 10 Mps Adapter + ff81 802.11b Wireless Adapter [Lucent/Agere Hermes I] +1631 Good Way Technology + 6200 GWUSB2E + c019 RT2573 +1645 Entrega [hex] + 0001 1S Serial Port + 0002 2S Serial Port + 0003 1S25 Serial Port + 0004 4S Serial Port + 0005 E45 Ethernet [klsi] + 0006 Parallel Port + 0007 U1-SC25 SCSI + 0008 Ethernet + 0016 Bi-directional to Parallel Printer Converter + 0080 1 port to Serial Converter + 0081 1 port to Serial Converter + 0093 1S9 Serial Port + 8000 EZ-USB + 8001 1 port to Serial + 8002 2x Serial Port + 8003 1 port to Serial + 8004 2U4S serial/usb hub + 8005 Ethernet + 8080 1 port to Serial + 8081 1 port to Serial + 8093 PortGear Serial Port +1649 SofTec Microsystems + 0102 uDART In-Circuit Debugger + 0200 SpYder USBSPYDER08 +164a ChipX +164c Matrix Vision GmbH + 0101 mvBlueFOX camera (no firmware) + 0103 mvBlueFOX camera + 0201 mvBlueLYNX-X intelligent camera (bootloader) + 0203 mvBlueLYNX-X intelligent camera +1657 Struck Innovative Systeme GmbH + 3150 SIS3150 USB2.0 to VME interface +165b Frontier Design Group + 8101 Tranzport Control Surface + fad1 Alphatrack Control Surface +165c Kondo Kagaku + 0002 Serial Adapter + 0006 FT232 [ICS adapter HS] + 0008 FT232 [Dual adapter HS] +1660 Creatix Polymedia GmbH +1667 GIGA-TMS INC. + 0005 PCR330A RFID Reader (125 kHz, keyboard emulation) +1668 Actiontec Electronics, Inc. [hex] + 0009 Gateway + 0333 Modem + 0358 InternetPhoneWizard + 0405 Gateway + 0408 Prism2.5 802.11b Adapter + 0413 Gateway + 0421 Prism2.5 802.11b Adapter + 0441 IBM Integrated Bluetooth II + 0500 BTM200B BlueTooth Adapter + 1050 802UIG-1 802.11g Wireless Mini Adapter [Intersil ISL3887] + 1200 802AIN Wireless N Network Adapter [Atheros AR9170+AR9101] + 1441 IBM Integrated Bluetooth II + 2441 BMDC-2 IBM Bluetooth III w.56k + 3441 IBM Integrated Bluetooth III + 6010 Gateway + 6097 802.11b Wireless Adapter + 6106 802UI3(B) 802.11b Wireless Adapter [Intersil PRISM 3] + 7605 UAT1 Wireless Ethernet Adapter +1669 PiKRON Ltd. [hex] + 1001 uLan2USB Converter - PS1 protocol +166a Clipsal + 0101 C-Bus Multi-room Audio Matrix Switcher + 0201 C-Bus Pascal Automation Controller + 0301 C-Bus Wireless PC Interface + 0303 C-Bus interface + 0304 C-Bus Black and White Touchscreen + 0305 C-Bus Spectrum Colour Touchscreen + 0401 C-Bus Architectural Dimmer +1677 China Huada Integrated Circuit Design (Group) Co., Ltd. (CIDC Group) + 0103 Token +1679 Total Phase + 2001 Beagle Protocol Analyzer + 2002 Cheetah SPI Host Adapter +1680 Golden Bridge Electech Inc. + a332 DVB-T Dongle [RTL2832U] +1681 Prevo Technologies, Inc. + 0001 Tuner's Dashboard + 0002 DocuBrain(R) Tubachron + 0003 DocuBrain(R) I2C + 0004 DocuBrain(R) WWVB Receiver + 0005 DocuBrain(R) WWVB Transmitter +1682 Maxwise Production Enterprise Ltd. +1684 Godspeed Computer Corp. +1685 Delock + 0200 Infrared adapter +1686 ZOOM Corporation + 0045 H4 Digital Recorder +1687 Kingmax Digital Inc. + 5289 FlashDisk + 6211 FlashDisk + 6213 FlashDisk +1688 Saab AB +1689 Razer USA, Ltd + fd00 Onza Tournament Edition controller +168c Atheros Communications + 0001 AR5523 + 0002 AR5523 (no firmware) +1690 Askey Computer Corp. [hex] + 0001 Arcaze Gamepad + 0101 Creative Modem Blaster DE5670 + 0102 V1456 VQE-R2 Modem [conexant] + 0103 1456 VQE-R3 Modem [conexant] + 0104 HCF V90 Data Fax RTAD Modem + 0107 HCF V.90 Data,Fax,RTAD Modem + 0109 MagicXpress V.90 Pocket Modem [conexant] + 0203 Voyager ADSL Modem Loader + 0204 Voyager ADSL Modem + 0205 DSL Modem + 0206 GlobeSpan ADSL WAN Modem + 0208 DSL Modem + 0209 Voyager 100 ADSL Modem + 0211 Globespan Virata ADSL LAN Modem + 0212 DSL Modem + 0213 HM121d DSL Modem + 0214 HM121d DSL Modem + 0215 Voyager 105 ADSL Modem + 0701 WLAN + 0710 SMCWUSBT-G + 0711 SMCWUSBT-G (no firmware) + 0712 AR5523 + 0713 AR5523 (no firmware) + 0715 Name: Voyager 1055 Laptop 802.11g Adapter [Broadcom 4320] + 0722 RT2573 + 0726 Wi-Fi Wireless LAN Adapter + 0740 802.11n Wireless LAN Card + 0901 Voyager 205 ADSL Router + 2000 naturaSign Pad Standard + 2001 naturaSign Pad Standard + fe12 Bootloader +1696 Hitachi Video and Information System, Inc. +1697 VTec Test, Inc. +16a5 Shenzhen Zhengerya Cable Co., Ltd. +16a6 Unigraf + 3000 VTG-3xxx Video Test Generator family + 4000 VTG-4xxx Video Test Generator family + 5000 VTG-5xxx Video Test Generator family + 5001 VTG-5xxx Special (update) mode of VTG-5xxx family +16ab Global Sun Technology + 7801 AR5523 + 7802 AR5523 (no firmware) + 7811 AR5523 + 7812 AR5523 (no firmware) +16ac Dongguan ChingLung Wire & Cable Co., Ltd. +16b4 iStation + 0801 U43 +16b5 Persentec, Inc. + 0002 Otto driving companion +16c0 Van Ooijen Technische Informatica + 03e8 free for internal lab use 1000 + 03e9 free for internal lab use 1001 + 03ea free for internal lab use 1002 + 03eb free for internal lab use 1003 + 03ec free for internal lab use 1004 + 03ed free for internal lab use 1005 + 03ee free for internal lab use 1006 + 03ef free for internal lab use 1007 + 03f0 free for internal lab use 1008 + 03f1 free for internal lab use 1009 + 0477 Teensy Rebootor + 0478 Teensy Halfkay Bootloader + 0479 Teensy Debug + 047a Teensy Serial + 047b Teensy Serial+Debug + 047c Teensy Keyboard + 047d Teensy Keyboard+Debug + 047e Teensy Mouse + 047f Teensy Mouse+Debug + 0480 Teensy RawHID + 0481 Teensy RawHID+Debug + 0482 Teensyduino Keyboard+Mouse+Joystick + 0483 Teensyduino Serial + 0484 Teensyduino Disk + 0485 Teensyduino MIDI + 0486 Teensyduino RawHID + 0487 Teensyduino Serial+Keyboard+Mouse+Joystick + 0488 Teensyduino Flight Sim Controls + 05dc shared ID for use with libusb + 05dd BlackcatUSB2 + 05df HID device except mice, keyboards, and joysticks + 05e1 Free shared USB VID/PID pair for CDC devices + 05e4 Free shared USB VID/PID pair for MIDI devices + 06b4 USB2LPT with 2 interfaces + 06b5 USB2LPT with 3 interfaces (native, HID, printer) + 074e DSP-Weuffen USB-HPI-Programmer + 074f DSP-Weuffen USB2-HPI-Programmer + 0762 Osmocom SIMtrace + 076b OpenPCD 13.56MHz RFID Reader + 076c OpenPICC 13.56MHz RFID Simulator (native) + 08ac OpenBeacon USB stick + 08ca Alpermann+Velte Universal Display + 08cb Alpermann+Velte Studio Clock + 08cc Alpermann+Velte SAM7S MT Boot Loader + 08cd Alpermann+Velte SAM7X MT Boot Loader + 0a32 jbmedia Light-Manager Pro + 27d8 libusb-bound devices + 27d9 HID device except mice, keyboards, and joysticks + 27da Mouse + 27db Keyboard + 27dc Joystick + 27dd CDC-ACM class devices (modems) + 27de MIDI class devices + 294a Eye Movement Recorder [Visagraph] + 294b Eye Movement Recorder [ReadAlyzer] +16ca Wireless Cables, Inc. + 1502 Bluetooth Dongle +16cc silex technology, Inc. +16d0 MCS + 0436 Xylanta Ltd, XSP Device + 0498 Braintechnology USB-LPS + 0504 RETRO Innovations ZoomFloppy + 054b GrauTec ReelBox OLED Display (external) + 05be EasyLogic Board + 06cc Trinamic TMCM-3110 + 06f9 Gabotronics Xminilab + 0753 Digistump DigiSpark + 075c AB-1.x UAC1 [Audio Widget] + 075d AB-1.x UAC2 [Audio Widget] + 080a S2E1 Interface + 0870 Kaufmann Automotive GmbH, RKS+CAN Interface + 0b03 AIS Receiver [dAISy] + 0bd4 codesrc SCSI2SD +16d1 Suprema Inc. + 0401 SUP-SFR400(A) BioMini Fingerprint Reader +16d3 Frontline Test Equipment, Inc. +16d5 AnyDATA Corporation + 6202 CDMA/UMTS/GPRS modem + 6501 CDMA 2000 1xRTT/EV-DO Modem + 6502 CDMA/UMTS/GPRS modem + 6603 ADU-890WH modem +16d6 JABLOCOM s.r.o. + 8000 GDP-04 desktop phone + 8001 EYE-02 + 8003 GDP-04 modem + 8004 Bootloader + 8005 GDP-04i + 8007 BTP-06 modem +16d8 CMOTECH Co., Ltd. + 5141 CMOTECH CDMA Technologies modem + 5533 CCU-550 CDMA EV-DO modem + 5543 CDMA 2000 1xRTT/1xEVDO modem + 6280 CMOTECH CDMA Technologies modem + 6803 CNU-680 CDMA EV-DO modem + 8001 Gobi 2000 Wireless Modem (QDL mode) + 8002 Gobi 2000 Wireless Modem +16dc Wiener, Plein & Baus + 0001 CC + 000b VM + 0010 PL512 Power Supply System + 0011 MARATON Power Supply System + 0012 MPOD Multi Channel Power Supply System + 0015 CML Control, Measurement and Data Logging System +16de Telemecanique +16df King Billion Electronics Co., Ltd. +16f0 GN ReSound A/S + 0001 Speedlink Programming Interface + 0003 Airlink Wireless Programming Interface +16f5 Futurelogic Inc. +1706 BlueView Technologies, Inc. +1707 ARTIMI +170b Swissonic + 0011 MIDI-USB 1x1 +170d Avnera +1711 Leica Microsystems + 0101 DFC-365FX camera + 3020 IC80 HD Camera +1724 Meyer Instruments (MIS) + 0115 PAXcam5 +1725 Vitesse Semiconductor +1726 Axesstel, Inc. + 1000 wireless modem + 2000 wireless modem + 3000 wireless modem +172f Waltop International Corp. + 0022 Tablet + 0024 Tablet + 0025 Tablet + 0026 Tablet + 0031 Slim Tablet 12.1" + 0032 Slim Tablet 5.8" + 0034 Slim Tablet 12.1" + 0038 Genius G-Pen F509 + 0500 Media Tablet 14.1" + 0501 Media Tablet 10.6" + 0502 Sirius Battery Free Tablet +1733 Cellink Technology Co., Ltd + 0101 RF Wireless Optical Mouse OP-701 +1736 CANON IMAGING SYSTEM TECHNOLOGIES INC. +1737 Linksys + 0039 USB1000 Gigabit Notebook Adapter + 0070 WUSB100 v1 RangePlus Wireless Network Adapter [Ralink RT2870] + 0071 WUSB600N v1 Dual-Band Wireless-N Network Adapter [Ralink RT2870] + 0073 WUSB54GC v2 802.11g Adapter [Realtek RTL8187B] + 0075 WUSB54GSC v2 802.11g Adapter [Broadcom 4326U] + 0077 WUSB54GC v3 802.11g Adapter [Ralink RT2070L] + 0078 WUSB100 v2 RangePlus Wireless Network Adapter [Ralink RT3070] + 0079 WUSB600N v2 Dual-Band Wireless-N Network Adapter [Ralink RT3572] +173a Roche + 2198 Accu-Chek Mobile + 21ca ACCU-CHEK Mobile Model U1 +173d QSENN + 0002 GP-K7000 keyboard +1740 Senao + 0100 EUB1200AC AC1200 DB Wireless Adapter [Realtek RTL8812AU] + 0600 EUB600v1 802.11abgn Wireless Adapter [Ralink RT3572] + 0605 LevelOne WUA-0605 N_Max Wireless USB Adapter + 0615 LevelOne WUA-0615 N_Max Wireless USB Adapter + 1000 NUB-350 802.11g Wireless Adapter [Intersil ISL3887] + 2000 NUB-8301 802.11bg + 3701 EUB-3701 EXT 802.11g Wireless Adapter [Ralink RT2571W] + 9603 RTL8188S WLAN Adapter + 9701 EnGenius 802.11n Wireless USB Adapter + 9702 EnGenius 802.11n Wireless USB Adapter + 9703 EnGenius 802.11n Wireless USB Adapter + 9705 EnGenius 802.11n Wireless USB Adapter + 9706 EUB9706 802.11n Wireless Adapter [Ralink RT3072] + 9801 EUB9801 802.11abgn Wireless Adapter [Ralink RT3572] +1743 General Atomics +1748 MQP Electronics + 0101 Packet-Master USB12 +174c ASMedia Technology Inc. + 07d1 Transcend ESD400 Portable SSD (USB 3.0) + 1153 ASM1153 SATA 3Gb/s bridge + 2074 ASM1074 High-Speed hub + 3074 ASM1074 SuperSpeed hub + 5106 ASM1051 SATA 3Gb/s bridge + 5136 ASM1053 SATA 3Gb/s bridge + 51d6 ASM1051W SATA 3Gb/s bridge + 55aa Name: ASM1051E SATA 6Gb/s bridge, ASM1053E SATA 6Gb/s bridge, ASM1153 SATA 3Gb/s bridge, ASM1153E SATA 6Gb/s bridge +174f Syntek + 1105 SM-MS/Pro-MMC-XD Card Reader + 110b HP Webcam + 1403 Integrated Webcam + 1404 USB Camera device, 1.3 MPixel Web Cam + 5212 USB 2.0 UVC PC Camera + 5a11 PC Camera + 5a31 Sonix USB 2.0 Camera + 5a35 Sonix 1.3MPixel USB 2.0 Camera + 6a31 Web Cam - Asus A8J, F3S, F5R, VX2S, V1S + 6a33 Web Cam - Asus F3SA, F9J, F9S + 6a51 2.0MPixel Web Cam - Asus Z96J, Z96S, S96S + 6a54 Web Cam + 6d51 2.0Mpixel Web Cam - Eurocom D900C + 8a12 Syntek 0.3MPixel USB 2.0 UVC PC Camera + 8a33 Syntek USB 2.0 UVC PC Camera + a311 1.3MPixel Web Cam - Asus A3A, A6J, A6K, A6M, A6R, A6T, A6V, A7T, A7sv, A7U + a312 1.3MPixel Web Cam + a821 Web Cam - Packard Bell BU45, PB Easynote MX66-208W + aa11 Web Cam +1753 GERTEC Telecomunicacoes Ltda. + c901 PPC900 Pinpad Terminal +1756 ENENSYS Technologies + 0006 DiviPitch +1759 LucidPort Technology, Inc. +1761 ASUSTek Computer, Inc. (wrong ID) + 0b05 802.11n Network Adapter (wrong ID - swapped vendor and device) +1772 System Level Solutions, Inc. +1776 Arowana + 501c 300K CMOS Camera +177f Sweex + 0004 MM004V5 Photo Key Chain (Digital Photo Frame) 1.5" + 0153 LW153 802.11n Adapter [ralink rt3070] + 0154 LW154 802.11bgn (1x1:1) Wireless Adapter [Realtek RTL8188SU] + 0313 LW313 802.11n Adapter [ralink rt2770 + rt2720] +1781 Multiple Vendors + 083e MetaGeek Wi-Spy + 083f MetaGeek Wi-Spy 2.4x + 0938 Iguanaworks USB IR Transceiver + 0a96 raphnet.net usb_game12 + 0a97 raphnet.net SNES mouse adapter + 0a98 raphnet.net USBTenki + 0a99 raphnet.net NES + 0a9a raphnet.net Gamecube/N64 controller + 0a9b raphnet.net DB9Joy + 0a9c raphnet.net Intellivision + 0a9d raphnet.net 4nes4snes + 0a9e raphnet.net Megadrive multitap + 0a9f raphnet.net MultiDB9joy + 0c30 Telldus TellStick + 0c31 Telldus TellStick Duo + 0c9f USBtiny + 1eef OpenAPC SecuKey + 1ef0 E1701 Modular Controller Card + 1ef1 E1701 Modular Controller Card +1782 Spreadtrum Communications Inc. +1784 TopSeed Technology Corp. + 0001 eHome Infrared Transceiver + 0004 RF Combo Device + 0006 eHome Infrared Transceiver + 0007 eHome Infrared Transceiver + 0008 eHome Infrared Transceiver + 000a eHome Infrared Transceiver + 0011 eHome Infrared Transceiver +1787 ATI AIB +1788 ShenZhen Litkconn Technology Co., Ltd. +1796 Printrex, Inc. +1797 JALCO CO., LTD. +1799 Thales Norway A/S + 7051 Belkin F5D7051 802.11g Adapter v1000 [Broadcom 4320] + 8051 Belkin F5D8051 v2 802.11bgn Wireless Adapter [Marvell 88W8362] +179d Ricavision International, Inc. + 0010 Internal Infrared Transceiver +17a0 Samson Technologies Corp. + 0001 C01U condenser microphone + 0002 Q1U dynamic microphone + 0100 C03U multi-pattern microphone + 0101 UB1 boundary microphone + 0120 Meteorite condenser microphone + 0200 StudioDock monitors (internal hub) + 0201 StudioDock monitors (audio) + 0210 StudioGT monitors + 0301 Q2U handheld microphone with XLR + 0302 GoMic compact condenser microphone + 0303 C01U Pro condenser microphone + 0304 Q2U handheld mic with XLR + 0305 GoMic compact condenser mic + 0310 Meteor condenser microphone +17a4 Concept2 + 0001 Performance Monitor 3 + 0002 Performance Monitor 4 +17a5 Advanced Connection Technology Inc. +17a7 MICOMSOFT CO., LTD. +17a8 Kamstrup A/S + 0001 Optical Eye/3-wire + 0005 M-Bus Master MultiPort 250D +17b3 Grey Innovation + 0004 Linux-USB Midi Gadget +17b5 Lunatone + 0010 MFT Sensor +17ba SAURIS GmbH + 0001 SAU510-USB [no firmware] + 0510 SAU510-USB and SAU510-USB plus JTAG Emulators + 0511 SAU510-USB Iso Plus JTAG Emulator + 0520 SAU510-USB Nano JTAG Emulator + 1511 Onboard Emulator on SAUModule development kit +17c3 Singim International Corp. +17cc Native Instruments + 041c Audio 2 DJ + 0808 Maschine Controller + 0815 Audio Kontrol 1 + 0839 Audio 4 DJ + 0d8d Guitarrig Mobile + 1915 Session I/O + 1940 RigKontrol3 + 1969 RigKontrol2 + 1978 Audio 8 DJ + 2280 Medion MDPNA1500 in card reader mode + 2305 Traktor Kontrol X1 + 4711 Kore Controller + 4712 Kore Controller 2 + baff Traktor Kontrol S4 +17cf Hip Hing Cable & Plug Mfy. Ltd. +17d0 Sanford L.P. +17d3 Korea Techtron Co., Ltd. +17e9 DisplayLink + 0051 USB VGA Adaptor + 030b HP T100 + 0377 Plugable UD-160-A (M) + 0378 Plugable UGA-2K-A + 0379 Plugable UGA-125 + 037a Plugable UGA-165 + 037b Plugable USB-VGA-165 + 037c Plugable DC-125 + 037d Plugable USB2-HDMI-165 + 410a HDMI Adapter + 430a HP Port Replicator (Composite Device) + 4312 S2340T +17eb Cornice, Inc. +17ef Lenovo + 1000 Hub + 1003 Integrated Smart Card Reader + 1004 Integrated Webcam + 1008 Hub + 100a ThinkPad Mini Dock Plus Series 3 + 304b AX88179 Gigabit Ethernet [ThinkPad OneLink GigaLAN] + 3815 ChipsBnk 2GB USB Stick + 4802 Lenovo Vc0323+MI1310_SOC Camera + 4807 UVC Camera + 480c Integrated Webcam + 480d Integrated Webcam [R5U877] + 480e Integrated Webcam [R5U877] + 480f Integrated Webcam [R5U877] + 4810 Integrated Webcam [R5U877] + 4811 Integrated Webcam [R5U877] + 4812 Integrated Webcam [R5U877] + 4813 Integrated Webcam [R5U877] + 4814 Integrated Webcam [R5U877] + 4815 Integrated Webcam [R5U877] + 4816 Integrated Webcam + 481c Integrated Webcam + 481d Integrated Webcam + 6004 ISD-V4 Tablet Pen + 6007 Smartcard Keyboard + 6009 ThinkPad Keyboard with TrackPoint + 6014 Mini Wireless Keyboard N5901 + 6025 ThinkPad Travel Mouse + 7203 Ethernet adapter [U2L 100P-Y1] + 7423 IdeaPad A1 Tablet + 7435 A789 (Mass Storage mode, with debug) + 743a A789 (Mass Storage mode) + 7497 A789 (MTP mode) + 7498 A789 (MTP mode, with debug) + 749a A789 (PTP mode) + 749b A789 (PTP mode, with debug) +17f4 WaveSense + aaaa Jazz Blood Glucose Meter +17f5 K.K. Rocky +17f6 Unicomp, Inc + 0709 Model M Keyboard +1809 Advantech + 4604 USB-4604 + 4761 USB-4761 Portable Data Acquisition Module +1822 Twinhan + 3201 VisionDTV USB-Ter/HAMA USB DVB-T device cold + 3202 VisionDTV USB-Ter/HAMA USB DVB-T device warm +1831 Gwo Jinn Industries Co., Ltd. +1832 Huizhou Shenghua Industrial Co., Ltd. +183d VIVOphone + 0010 VoiceKey +1843 Vaisala +1849 ASRock Incorporation +1852 GYROCOM C&C Co., LTD + 7922 Audiotrak DR.DAC2 DX [GYROCOM C&C] +1854 Memory Devices Ltd. +185b Compro + 3020 K100 Infrared Receiver + 3082 K100 Infrared Receiver v2 + d000 Compro Videomate DVB-U2000 - DVB-T USB cold + d001 Compro Videomate DVB-U2000 - DVB-T USB warm +1861 Tech Technology Industrial Company +1862 Teridian Semiconductor Corp. +1870 Nexio Co., Ltd + 0001 iNexio Touchscreen controller +1871 Aveo Technology Corp. + 0101 UVC camera (Bresser microscope) + 0141 Camera + 0d01 USB2.0 Camera +1873 Navilock + ee93 EasyLogger +187c Alienware Corporation + 0511 AlienFX Mobile lighting + 0600 Dual Compatible Game Pad +187f Siano Mobile Silicon + 0010 Stallar Board + 0100 Stallar Board + 0200 Nova A + 0201 Nova B + 0202 Nice + 0300 Vega + 0301 VeNice +1892 Vast Technologies, Inc. +1894 Topseed + 5632 Atek Tote Remote + 5641 TSAM-004 Presentation Remote +1897 Evertop Wire Cable Co. +189f 3Shape A/S + 0002 Legato2 3D Scanner +18a4 CSSN + 0001 Snapshell IDR +18a5 Verbatim, Ltd + 0214 Portable Hard Drive + 0216 External Hard Drive + 0218 External Hard Drive + 0224 Store 'n' Go Micro Plus + 0227 Pocket Hard Drive + 022b Portable Hard Drive (Store'n'Go) + 0237 Portable Harddrive + 0243 Flash Drive (Store'n'Go) + 0302 Flash Drive + 0304 Store 'n' Go + 4123 Store N Go +18b1 Petalynx + 0037 Maxter Remote Control +18b4 e3C Technologies + 1001 DUTV007 + 1002 EC168 (v5) based USB DVB-T receiver + 1689 DUTV009 + fffa EC168 (v2) based USB DVB-T receiver + fffb EC168 (v3) based USB DVB-T receiver +18b6 Mikkon Technology Limited +18b7 Zotek Electronic Co., Ltd. +18c5 AMIT Technology, Inc. + 0002 CG-WLUSB2GO + 0008 CG-WLUSB2GNR Corega Wireless USB Adapter + 0012 CG-WLUSB10 Corega Wireless USB Adapter +18cd Ecamm + cafe Pico iMage +18d1 Google Inc. + 0001 Onda V972 (storage access) + 0003 Android-powered device using AllWinner Technology SoC + 0006 Onda V972 MTP + 0008 Onda V972 PTP (camera) + 0d02 Celkon A88 + 2d00 Android-powered device in accessory mode + 2d01 Android-powered device in accessory mode with ADB support + 4e11 Nexus One + 4e12 Nexus One (debug) + 4e13 Nexus One (tether) + 4e20 Nexus S (fastboot) + 4e21 Nexus S + 4e22 Nexus S (debug) + 4e24 Nexus S (tether) + 4e30 Galaxy Nexus (fastboot) + 4e40 Nexus 7 (fastboot) + 4e41 Nexus 7 (MTP) + 4e42 Nexus 7 (debug) + 4e43 Nexus 7 (PTP) + 4e44 Nexus 7 2012 (PTP) + 4ee0 Nexus 4 (bootloader) + 4ee1 Nexus Device (MTP) + 4ee2 Nexus Device (debug) + 4ee3 Nexus 4/5/7/10 (tether) + 4ee4 Nexus 4/5/7/10 (debug + tether) + 4ee5 Nexus 4 (PTP) + 4ee6 Nexus 4/5 (PTP + debug) + 7102 Toshiba Thrive tablet + b004 Pandigital / B&N Novel 9" tablet + d001 Nexus 4 (fastboot) + d002 Nexus 4 (debug) + d109 LG G2x MTP + d10a LG G2x MTP (debug) +18d5 Starline International Group Limited +18d9 Kaba + 01a0 B-Net 91 07 +18dc LKC Technologies, Inc. +18dd Planon System Solutions Inc. + 1000 DocuPen RC800 +18e3 Fitipower Integrated Technology Inc + 7102 Multi Card Reader (Internal) + 9101 All-in-1 Card Reader + 9102 Multi Card Reader + 9512 Webcam +18e8 Qcom + 6144 LR802UA 802.11b Wireless Adapter [ALi M4301AU] + 6196 RT2573 + 6229 RT2573 + 6232 Wireless 802.11g 54Mbps Network Adapter [RTL8187] +18ea Matrox Graphics, Inc. + 0002 DualHead2Go [Analog Edition] + 0004 TripleHead2Go [Digital Edition] +18ec Arkmicro Technologies Inc. + 3118 USB to IrDA adapter [ARK3116T] + 3188 ARK3188 UVC Webcam + 3299 Webcam Carrefour + 3366 Bresser Biolux NV +18f8 [Maxxter] + 0f99 Optical gaming mouse +18fb Scriptel Corporation + 01c0 ST1501-STN + 01c1 ST1526-STN + 01c2 ST1501-PYJ + 01c3 ST1501B-PYJ + 01c4 ST1501-PUN + 01c5 ST1401-STN + 01c7 ST1526-PYJ + 01c8 ST1501-ECA + 01c9 ST1476-STN + 01cb ST1571-STN + 0200 ST1500 + 0201 ST1550 + 0202 ST1525 + 0204 ST1400 + 0206 ST1475 + 0207 ST1570 +18fd FineArch Inc. +1901 GE Healthcare + 0015 Nemo Tracker +1908 GEMBIRD + 1320 PhotoFrame PF-15-1 +190d Motorola GSG +1914 Alco Digital Devices Limited +1915 Nordic Semiconductor ASA + 000c Wireless Desktop nRF24L01 CX-1766 + 2233 Linksys WUSB11 v2.8 802.11b Adapter [Atmel AT76C505] + 2234 Linksys WUSB54G v1 OEM 802.11g Adapter [Intersil ISL3886] + 2235 Linksys WUSB54GP v1 OEM 802.11g Adapter [Intersil ISL3886] + 2236 Linksys WUSB11 v3.0 802.11b Adapter [Intersil PRISM 3] +191c Innovative Technology LTD + 4104 Banknote validator NV-150 +1923 FitLinxx + 0002 Personal SyncPoint +1926 NextWindow + 0003 1900 HID Touchscreen + 0006 1950 HID Touchscreen + 0064 1950 HID Touchscreen + 0065 1950 HID Touchscreen + 0066 1950 HID Touchscreen + 0067 1950 HID Touchscreen + 0068 1950 HID Touchscreen + 0069 1950 HID Touchscreen + 0071 1950 HID Touchscreen + 0072 1950 HID Touchscreen + 0073 1950 HID Touchscreen + 0074 1950 HID Touchscreen + 0075 1950 HID Touchscreen + 0076 1950 HID Touchscreen + 0077 1950 HID Touchscreen + 0078 1950 HID Touchscreen + 0079 1950 HID Touchscreen + 007a 1950 HID Touchscreen + 007e 1950 HID Touchscreen + 007f 1950 HID Touchscreen + 0080 1950 HID Touchscreen + 0081 1950 HID Touchscreen + 0082 1950 HID Touchscreen + 0083 1950 HID Touchscreen + 0084 1950 HID Touchscreen + 0085 1950 HID Touchscreen + 0086 1950 HID Touchscreen + 0087 1950 HID Touchscreen + 0dc2 HID Touchscreen +192f Avago Technologies, Pte. + 0000 Mouse + 0416 ADNS-5700 Optical Mouse Controller (3-button) + 0616 ADNS-5700 Optical Mouse Controller (5-button) +1930 Shenzhen Xianhe Technology Co., Ltd. +1931 Ningbo Broad Telecommunication Co., Ltd. +1934 Feature Integration Technology Inc. (Fintek) + 0602 F71610 or F71612 Consumer Infrared Receiver/Transceiver + 0702 Integrated Consumer Infrared Receiver/Transceiver + 5168 F71610A or F71612A Consumer Infrared Receiver/Transceiver +1938 Meinberg Funkuhren GmbH & Co. KG + 0501 TCR51USB IRIG Time Code Reader +1941 Dream Link + 8021 WH1080 Weather Station / USB Missile Launcher +1943 Sensoray Co., Inc. + 2250 Model 2250 MPEG and JPEG Capture Card + 2253 Model 2253 Audio/Video Codec Card + 2255 Model 2255 4 Channel Capture Card + 2257 Model 2257 4 Channel Capture Card + a250 Model 2250 MPEG and JPEG Capture Card (cold) + a253 Model 2253 Audio/Video Codec Card (cold) +1949 Lab126, Inc. + 0002 Amazon Kindle + 0004 Amazon Kindle 3/4/Paperwhite + 0006 Kindle Fire + 0008 Amazon Kindle Fire HD 8.9" +194f PreSonus Audio Electronics, Inc. + 0101 AudioBox 22 VSL + 0102 AudioBox 44 VSL + 0103 AudioBox 1818 VSL + 0301 AudioBox +1951 Hyperstone AG +1953 Ironkey Inc. + 0202 S200 2GB Rev. 1 +1954 Radiient Technologies +195d Itron Technology iONE + 7002 Libra-Q11 IR remote + 7006 Libra-Q26 / 1.0 Remote + 7777 Scorpius wireless keyboard + 7779 Scorpius-P20MT +1965 Uniden Corporation + 0016 HomePatrol-1 +1967 CASIO HITACHI Mobile Communications Co., Ltd. +196b Wispro Technology Inc. +1970 Dane-Elec Corp. USA + 0000 Z Mate 16GB +1975 Dongguan Guneetal Wire & Cable Co., Ltd. +1976 Chipsbrand Microelectronics (HK) Co., Ltd. + 6025 Flash Drive 512 MB +1977 T-Logic + 0111 TL203 MP3 Player and Voice Recorder +197d Leuze electronic + 0222 BCL 508i +1989 Nuconn Technology Corp. +198f Beceem Communications Inc. + 0210 BCS200 WiMAX Adapter + 0220 BCSM250 WiMAX Adapter +1990 Acron Precision Industrial Co., Ltd. +1995 Trillium Technology Pty. Ltd. + 3202 REC-ADPT-USB (recorder) + 3203 REC-A-ADPT-USB (recorder) +1996 PixeLINK + 3010 Camera Release 4 + 3011 OEM Camera + 3012 e-ImageData Corp. ScanPro +199b MicroStrain, Inc. + 3065 3DM-GX3-25 Orientation Sensor +199e The Imaging Source Europe GmbH + 8101 DFx 21BU04 Camera +199f Benica Corporation +19a8 Biforst Technology Inc. +19ab Bodelin + 1000 ProScope HR +19af S Life + 6611 Celestia VoIP Phone +19b2 Batronix + 0010 BX32 Batupo + 0011 BX32P Barlino + 0012 BX40 Bagero + 0013 BX48 Batego +19b4 Celestron + 0002 SkyScout Personal Planetarium + 0101 Handheld Digital Microscope 44302 +19b5 B & W Group +19b6 Infotech Logistic, LLC +19b9 Data Robotics + 8d20 Drobo Elite +19c2 Futuba + 6a11 MDM166A Fluorescent Display +19ca Mindtribe + 0001 Sandio 3D HID Mouse +19cf Parrot SA +19d2 ZTE WCDMA Technologies MSM + 0001 CDMA Wireless Modem + 0002 MF632/ONDA ET502HS/MT505UP + 0007 TU25 WiMAX Adapter [Beceem BCS200] + 0031 MF110/MF627/MF636 + 0063 K3565-Z HSDPA + 0064 MF627 AU + 0083 MF190 + 0103 MF112 + 0104 K4505-Z + 0146 MF 195E (HSPA+ Modem) + 0167 MF820 4G LTE + 0172 AX226 WIMAX MODEM (After Modeswitch) + 0325 LTE4G O2 ZTE MF821D LTE/UMTS/GSM Modem/Networkcard + 0326 LTE4G O2 ZTE MF821D LTE/UMTS/GSM Modem/Networkcard + 1008 K3570-Z + 1010 K3571-Z + 1017 K5006-Z vodafone LTE/UMTS/GSM Modem/Networkcard + 1018 K5006-Z vodafone LTE/UMTS/GSM Modem/Networkcard + 1203 MF691 [ T-Mobile webConnect Rocket 2.0] + 1217 MF652 + 1218 MF652 + 2000 MF627/MF628/MF628+/MF636+ HSDPA/HSUPA + fff2 Gobi Wireless Modem (QDL mode) + fff3 Gobi Wireless Modem +19db KFI Printers + 02f1 NAUT324C +19e1 WeiDuan Electronic Accessory (S.Z.) Co., Ltd. +19e8 Industrial Technology Research Institute +19ef Pak Heng Technology (Shenzhen) Co., Ltd. +19f7 RODE Microphones + 0001 Podcaster +19fa Gampaq Co.Ltd + 0703 Steering Wheel +19ff Dynex + 0102 1.3MP Webcam + 0201 Rocketfish Wireless 2.4G Laser Mouse + 0238 DX-WRM1401 Mouse +1a08 Bellwood International, Inc. +1a0a USB-IF non-workshop + badd USB OTG Compliance test device +1a12 KES Co., Ltd. +1a1d Veho + 0407 Mimi WiFi speakers +1a25 Amphenol East Asia Ltd. +1a2a Seagate Branded Solutions +1a2c China Resource Semico Co., Ltd + 0021 Keyboard + 0024 Multimedia Keyboard +1a32 Quanta Microsystems, Inc. + 0304 802.11n Wireless LAN Card +1a34 ACRUX + 0802 Gamepad +1a36 Biwin Technology Ltd. +1a40 Terminus Technology Inc. + 0101 Hub + 0201 FE 2.1 7-port Hub +1a41 Action Electronics Co., Ltd. +1a44 VASCO Data Security International + 0001 Digipass 905 SmartCard Reader +1a4a Silicon Image +1a4b SafeBoot International B.V. +1a5a Tandberg Data +1a61 Abbott Diabetes Care + 3410 CoPilot System Cable +1a6a Spansion Inc. +1a6d SamYoung Electronics Co., Ltd +1a6e Global Unichip Corp. +1a6f Sagem Orga GmbH +1a72 Physik Instrumente + 1008 E-861 PiezoWalk NEXACT Controller +1a79 Bayer Health Care LLC + 6002 Contour + 7410 Contour Next +1a7b Lumberg Connect GmbH & Co. KG +1a7c Evoluent + 0068 VerticalMouse 3 + 0168 VerticalMouse 3 Wireless + 0191 VerticalMouse 4 +1a81 Holtek Semiconductor, Inc. + 2203 Laser Gaming mouse + 2204 Optical Mouse + 2205 Laser Mouse +1a86 QinHeng Electronics + 5512 CH341 in EPP/MEM/I2C mode, EPP/I2C adapter + 5523 CH341 in serial mode, usb to serial port converter + 5584 CH341 in parallel mode, usb to printer port converter + 7523 HL-340 USB-Serial adapter + 752d CH345 MIDI adapter + 7584 CH340S + e008 HID-based serial adapater +1a89 Dynalith Systems Co., Ltd. +1a8b SGS Taiwan Ltd. +1a8d BandRich, Inc. + 1002 BandLuxe 3.5G HSDPA Adapter + 1009 BandLuxe 3.5G HSPA Adapter + 100d 4G LTE adapter +1a98 Leica Camera AG +1aa4 Data Drive Thru, Inc. +1aa5 UBeacon Technologies, Inc. +1aa6 eFortune Technology Corp. +1aad KeeTouch + 0001 Touchscreen +1ab1 Rigol Technologies + 0588 DS1000 SERIES +1acb Salcomp Plc +1acc Midiplus Co, Ltd. + 0103 AudioLink plus 4x4 2.9.28 +1ad1 Desay Wire Co., Ltd. +1ad4 APS + 0002 KM290-HRS +1adb SEL C662 Serial Cable +1ae4 ic-design Reinhard Gottinger GmbH +1ae7 X-TENSIONS + 0381 VS-DVB-T 380U (af9015 based) + 2001 SpeedLink Snappy Mic webcam (SL-6825-SBK) + 9003 SpeedLink Vicious And Devine Laplace webcam, white (VD-1504-SWT) + 9004 SpeedLink Vicious And Devine Laplace webcam, black (VD-1504-SBK) +1aed High Top Precision Electronic Co., Ltd. +1aef Conntech Electronic (Suzhou) Corporation +1af1 Connect One Ltd. +1afe A. Eberle GmbH & Co. KG + 0001 PQ Box 100 +1b04 Meilhaus Electronic GmbH + 0630 ME-630 + 0940 ME-94 + 0950 ME-95 + 0960 ME-96 + 1000 ME-1000 + 100a ME-1000 + 100b ME-1000 + 1400 ME-1400 + 140a ME-1400A + 140b ME-1400B + 140c ME-1400C + 140d ME-1400D + 140e ME-1400E + 14ea ME-1400EA + 14eb ME-1400EB + 1604 ME-1600/4U + 1608 ME-1600/8U + 160c ME-1600/12U + 160f ME-1600/16U + 168f ME-1600/16U8I + 4610 ME-4610 + 4650 ME-4650 + 4660 ME-4660 + 4661 ME-4660I + 4662 ME-4660 + 4663 ME-4660I + 4670 ME-4670 + 4671 ME-4670I + 4672 ME-4670S + 4673 ME-4670IS + 4680 ME-4680 + 4681 ME-4680I + 4682 ME-4680S + 4683 ME-4680IS + 6004 ME-6000/4 + 6008 ME-6000/8 + 600f ME-6000/16 + 6014 ME-6000I/4 + 6018 ME-6000I/8 + 601f ME-6000I/16 + 6034 ME-6000ISLE/4 + 6038 ME-6000ISLE/8 + 603f ME-6000ISLE/16 + 6044 ME-6000/4/DIO + 6048 ME-6000/8/DIO + 604f ME-6000/16/DIO + 6054 ME-6000I/4/DIO + 6058 ME-6000I/8/DIO + 605f ME-6000I/16/DIO + 6074 ME-6000ISLE/4/DIO + 6078 ME-6000ISLE/8/DIO + 607f ME-6000ISLE/16/DIO + 6104 ME-6100/4 + 6108 ME-6100/8 + 610f ME-6100/16 + 6114 ME-6100I/4 + 6118 ME-6100I/8 + 611f ME-6100I/16 + 6134 ME-6100ISLE/4 + 6138 ME-6100ISLE/8 + 613f ME-6100ISLE/16 + 6144 ME-6100/4/DIO + 6148 ME-6100/8/DIO + 614f ME-6100/16/DIO + 6154 ME-6100I/4/DIO + 6158 ME-6100I/8/DIO + 615f ME-6100I/16/DIO + 6174 ME-6100ISLE/4/DIO + 6178 ME-6100ISLE/8/DIO + 617f ME-6100ISLE/16/DIO + 6259 ME-6200I/9/DIO + 6359 ME-6300I/9/DIO + 810a ME-8100A + 810b ME-8100B + 820a ME-8200A + 820b ME-8200B +1b0e BLUTRONICS S.r.l. + 1078 BLUDRIVE II CCID + 1079 BLUDRIVE II CCID + 1080 WRITECHIP II CCID +1b1c Corsair + 0890 Flash Padlock + 0a00 SP2500 Speakers + 0a60 Vengeance K60 Keyboard + 0c04 Link Cooling Node + 1a01 Flash Voyager GT + 1a03 Voyager 3.0 + 1a09 Voyager GT 3.0 + 1a0a Survivor Stealth Flash Drive + 1a0b Flash Voyager LS + 1a15 Voyager Slider Flash Drive + 1a90 Flash Voyager GT + 1ab1 Voyager + 1b04 Raptor K50 Keyboard + 1b07 Vengeance K65 Gaming Keyboard + 1b08 Vengeance K95 Keyboard + 1b09 Vengeance K70R keyboard + 1b11 K95 RGB Mechanical Gaming Keyboard + 1b13 Vengeance K70RGB keyboard + 1c00 Controller for Corsair Link + 1c0c RM850i Power Supply +1b1f eQ-3 Entwicklung GmbH + c00f HM-CFG-USB/HM-CFG-USB-2 [HomeMatic Configuration adapter] +1b20 MStar Semiconductor, Inc. +1b22 WiLinx Corp. +1b26 Cellex Power Products, Inc. +1b27 Current Electronics Inc. +1b28 NAVIsis Inc. +1b32 Ugobe Life Forms, Inc. + 0064 Pleo robotic dinosaur +1b36 ViXS Systems, Inc. +1b3b iPassion Technology Inc. + 2933 PC Camera/Webcam controller + 2935 PC Camera/Webcam controller + 2936 PC Camera/Webcam controller + 2937 PC Camera/Webcam controller + 2938 PC Camera/Webcam controller + 2939 PC Camera/Webcam controller + 2950 PC Camera/Webcam controller + 2951 PC Camera/Webcam controller + 2952 PC Camera/Webcam controller + 2953 PC Camera/Webcam controller + 2955 PC Camera/Webcam controller + 2956 PC Camera/Webcam controller + 2957 PC Camera/Webcam controller + 2958 PC Camera/Webcam controller + 2959 PC Camera/Webcam controller + 2960 PC Camera/Webcam controller + 2961 PC Camera/Webcam controller + 2962 PC Camera/Webcam controller + 2963 PC Camera/Webcam controller + 2965 PC Camera/Webcam controller + 2966 PC Camera/Webcam controller + 2967 PC Camera/Webcam controller + 2968 PC Camera/Webcam controller + 2969 PC Camera/Webcam controller +1b3f Generalplus Technology Inc. + 0c52 808 Camera #9 (mass storage mode) + 2002 808 Camera #9 (web-cam mode) +1b47 Energizer Holdings, Inc. + 0001 CHUSB Duo Charger (NiMH AA/AAA USB smart charger) +1b48 Plastron Precision Co., Ltd. +1b52 ARH Inc. + 2101 FXMC Neural Network Controller + 2102 FXMC Neural Network Controller V2 + 2103 FXMC Neural Network Controller V3 + 4101 Passport Reader CLR device + 4201 Passport Reader PRM device + 4202 Passport Reader PRM extension device + 4203 Passport Reader PRM DSP device + 4204 Passport Reader PRMC device + 4205 Passport Reader CSHR device + 4206 Passport Reader PRMC V2 device + 4301 Passport Reader MRZ device + 4302 Passport Reader MRZ DSP device + 4303 Passport Reader CSLR device + 4401 Card Reader + 4501 Passport Reader RFID device + 4502 Passport Reader RFID AIG device + 6101 Neural Network Controller + 6202 Fingerprint Reader device + 6203 Fingerprint Scanner device + 8101 Camera V1 + 8102 Recovery / Camera V2 + 8103 Camera V3 +1b59 K.S. Terminals Inc. +1b5a Chao Zhou Kai Yuan Electric Co., Ltd. +1b65 The Hong Kong Standards and Testing Centre Ltd. +1b71 Fushicai + 3002 USBTV007 Video Grabber [EasyCAP] +1b72 ATERGI TECHNOLOGY CO., LTD. +1b73 Fresco Logic + 1000 xHC1 Controller +1b75 Ovislink Corp. + 3072 AirLive WN-360USB adapter + 8171 WN-370USB 802.11bgn Wireless Adapter [Realtek RTL8188SU] + 8187 AirLive WL-1600USB 802.11g Adapter [Realtek RTL8187L] + 9170 AirLive X.USB 802.11abgn [Atheros AR9170+AR9104] + a200 AirLive WN-200USB wireless 11b/g/n dongle +1b76 Legend Silicon Corp. +1b80 Afatech + c810 MC810 [af9015] + d393 DVB-T receiver [RTL2832U] + d396 UB396-T [RTL2832U] + d397 DVB-T receiver [RTL2832U] + d398 DVB-T receiver [RTL2832U] + d700 FM Radio SnapMusic Mobile 700 (FM700) + e297 Conceptronic DVB-T CTVDIGRCU V3.0 + e383 DVB-T UB383-T [af9015] + e385 DVB-T UB385-T [af9015] + e386 DVB-T UB385-T [af9015] + e399 DVB-T KWorld PlusTV 399U [af9015] + e39a DVB-T395U [af9015] + e39b DVB-T395U [af9015] + e401 Sveon STV22 DVB-T [af9015] + e409 IT9137FN Dual DVB-T [KWorld UB499-2T] +1b86 Dongguan Guanshang Electronics Co., Ltd. +1b88 ShenMing Electron (Dong Guan) Co., Ltd. +1b8c Altium Limited +1b8d e-MOVE Technology Co., Ltd. +1b8e Amlogic, Inc. +1b8f MA LABS, Inc. +1b96 N-Trig + 0001 Duosense Transparent Electromagnetic Digitizer +1b98 YMax Communications Corp. +1b99 Shenzhen Yuanchuan Electronic +1ba1 JINQ CHERN ENTERPRISE CO., LTD. +1ba2 Lite Metals & Plastic (Shenzhen) Co., Ltd. +1ba4 Ember Corporation + 0001 InSight USB Link +1ba6 Abilis Systems +1ba8 China Telecommunication Technology Labs +1bad Harmonix Music + 0002 Guitar for Xbox 360 + 0003 Drum Kit for Xbox 360 +1bae Vuzix Corporation + 0002 VR920 Immersive Eyewear +1bbb T & A Mobile Phones + 011e Alcatel One Touch L100V / Telekom Speedstick LTE II + f017 Alcatel One Touch L100V / Telekom Speedstick LTE II +1bc4 Ford Motor Co. +1bc5 AVIXE Technology (China) Ltd. +1bc7 Telit Wireless Solutions + 0020 HE863 + 0021 HE910 + 0023 HE910-D ECM + 1003 UC864-E + 1004 UC864-G + 1005 CC864-DUAL + 1006 CC864-SINGLE + 1010 DE910-DUAL + 1011 CE910-DUAL + 1200 LE920 +1bce Contac Cable Industrial Limited +1bcf Sunplus Innovation Technology Inc. + 0005 Optical Mouse + 0007 Optical Mouse + 053a Targa Silvercrest OMC807-C optische Funkmaus + 05c5 SPRF2413A [2.4GHz Wireless Keyboard/Mouse Receiver] + 05cf Micro keyboard & mouse receiver + 0c31 SPIF30x Serial-ATA bridge + 2880 Dell HD Webcam + 2885 ASUS Webcam + 2888 HP Universal Camera + 28a2 Dell Integrated Webcam + 28a6 DELL XPS Integrated Webcam + 28ae Laptop Integrated Webcam HD + 28bd Dell Integrated HD Webcam + 2985 Laptop Integrated Webcam HD + 2b83 Laptop Integrated Webcam FHD +1bd0 Hangzhou Riyue Electronic Co., Ltd. +1bd5 BG Systems, Inc. +1bde P-TWO INDUSTRIES, INC. +1bef Shenzhen Tongyuan Network-Communication Cables Co., Ltd +1bf0 RealVision Inc. +1bf5 Extranet Systems Inc. +1bf6 Orient Semiconductor Electronics, Ltd. +1bfd TouchPack + 1268 Touch Screen + 1368 Touch Screen + 1568 Capacitive Touch Screen + 1668 IR Touch Screen + 1688 Resistive Touch Screen + 2968 Touch Screen + 5968 Touch Screen + 6968 Touch Screen +1c02 Kreton Corporation +1c04 QNAP System Inc. +1c0c Ionics EMS, Inc. + 0102 Plug Computer +1c0d Relm Wireless +1c10 Lanterra Industrial Co., Ltd. +1c13 ALECTRONIC LIMITED +1c1a Datel Electronics Ltd. +1c1b Volkswagen of America, Inc. +1c1f Goldvish S.A. +1c20 Fuji Electric Device Technology Co., Ltd. +1c21 ADDMM LLC +1c22 ZHONGSHAN CHIANG YU ELECTRIC CO., LTD. +1c26 Shanghai Haiying Electronics Co., Ltd. +1c27 HuiYang D & S Cable Co., Ltd. +1c29 Elster GmbH + 0001 ExMFE5 Simulator + 10fc enCore device +1c31 LS Cable Ltd. +1c34 SpringCard + 7241 Prox'N'Roll RFID Scanner +1c37 Authorizer Technologies, Inc. +1c3d NONIN MEDICAL INC. +1c3e Wep Peripherals +1c40 EZPrototypes + 0533 TiltStick + 0534 i2c-tiny-usb interface + 0535 glcd2usb interface + 0536 Swiss ColorPAL +1c49 Cherng Weei Technology Corp. +1c4f SiGma Micro + 0002 Keyboard TRACER Gamma Ivory + 0003 HID controller + 000e Genius KB-120 Keyboard + 0026 Keyboard + 3000 Micro USB Web Camera + 3002 WebCam SiGma Micro +1c6b Philips & Lite-ON Digital Solutions Corporation + a222 DVD Writer Slimtype eTAU108 +1c6c Skydigital Inc. +1c73 AMT + 861f Anysee E30 USB 2.0 DVB-T Receiver +1c77 Kaetat Industrial Co., Ltd. +1c78 Datascope Corp. +1c79 Unigen Corporation +1c7a LighTuning Technology Inc. + 0801 Fingerprint Reader +1c7b LUXSHARE PRECISION INDUSTRY (SHENZHEN) CO., LTD. +1c83 Schomaecker GmbH + 0001 RS150 V2 +1c87 2N TELEKOMUNIKACE a.s. +1c88 Somagic, Inc. + 0007 SMI Grabber (EasyCAP DC60+ clone) (no firmware) [SMI-2021CBE] + 003c SMI Grabber (EasyCAP DC60+ clone) [SMI-2021CBE] +1c89 HONGKONG WEIDIDA ELECTRON LIMITED +1c8e ASTRON INTERNATIONAL CORP. +1c98 ALPINE ELECTRONICS, INC. +1c9e OMEGA TECHNOLOGY + 6061 WL-72B 3.5G MODEM +1ca0 ACCARIO Inc. +1ca1 Symwave + 18ab SATA bridge +1cac Kinstone + a332 C8 Webcam + b288 C18 Webcam +1cb3 Aces Electronic Co., Ltd. +1cb4 OPEX CORPORATION +1cb6 IdeaCom Technology Inc. + 6681 IDC6681 +1cbe Luminary Micro Inc. + 00fd In-Circuit Debug Interface + 00ff Stellaris ROM DFU Bootloader + 0166 CANAL USB2CAN +1cbf FORTAT SKYMARK INDUSTRIAL COMPANY +1cc0 PlantSense +1cca NextWave Broadband Inc. +1ccd Bodatong Technology (Shenzhen) Co., Ltd. +1cd4 adp corporation +1cd5 Firecomms Ltd. +1cd6 Antonio Precise Products Manufactory Ltd. +1cde Telecommunications Technology Association (TTA) +1cdf WonTen Technology Co., Ltd. +1ce0 EDIMAX TECHNOLOGY CO., LTD. +1ce1 Amphenol KAE +1cf1 Dresden Elektronik + 0001 Sensor Terminal Board + 0004 Wireless Handheld Terminal + 0017 deRFusbSniffer 2.4 GHz + 0018 deRFusb24E001 + 0019 deRFusb14E001 + 001a deRFusb23E00 + 001b deRFusb13E00 + 001c deRFnode + 001d deRFnode / gateway + 0022 deUSB level shifter + 0023 deRFusbSniffer Sub-GHz + 0025 deRFusb23E06 + 0027 deRFusb13E06 +1cfc ANDES TECHNOLOGY CORPORATION +1cfd Flextronics Digital Design Japan, LTD. +1d03 iCON + 0028 iCreativ MIDI Controller +1d07 Solid-Motion +1d08 NINGBO HENTEK DRAGON ELECTRONICS CO., LTD. +1d09 TechFaith Wireless Technology Limited + 1026 HSUPA Modem FLYING-LARK46-VER0.07 [Flying Angel] +1d0a Johnson Controls, Inc. The Automotive Business Unit +1d0b HAN HUA CABLE & WIRE TECHNOLOGY (J.X.) CO., LTD. +1d0f Sonix Technology Co., Ltd. +1d14 ALPHA-SAT TECHNOLOGY LIMITED +1d17 C-Thru Music Ltd. + 0001 AXiS-49 Harmonic Table MIDI Keyboard +1d19 Dexatek Technology Ltd. + 1101 DK DVB-T Dongle + 1102 DK mini DVB-T Dongle + 1103 DK 5217 DVB-T Dongle + 6105 Video grabber + 8202 DK DVBC/T DONGLE +1d1f Diostech Co., Ltd. +1d20 SAMTACK INC. +1d27 ASUS +1d34 Dream Cheeky + 0001 Dream Cheeky Fidget + 0004 Dream Cheeky Webmail Notifier + 0008 Dream Cheeky button + 000a Dream Cheeky Mailbox Friends Alert + 000d Dream Cheeky Big Red Button + 0013 Dream Cheeky LED Message Board +1d45 Touch + 1d45 Foxlink Optical touch sensor +1d4d PEGATRON CORPORATION + 0002 Ralink RT2770/2720 802.11b/g/n Wireless LAN Mini-USB Device + 000c Ralink RT3070 802.11b/g/n Wireless Lan USB Device + 000e Ralink RT3070 802.11b/g/n Wireless Lan USB Device +1d50 OpenMoko, Inc. + 1db5 IDBG (DFU) + 1db6 IDBG + 5117 Neo1973/FreeRunner kernel usbnet (g_ether, CDC Ethernet) mode + 5118 Neo1973/FreeRunner Debug board (V2+) + 5119 Neo1973/FreeRunner u-boot cdc_acm serial port + 511a HXD8 u-boot usbtty CDC ACM Mode + 511b SMDK2440 u-boot usbtty CDC ACM mode + 511c SMDK2443 u-boot usbtty CDC ACM mode + 511d QT2410 u-boot usbtty CDC ACM mode + 5120 Neo1973/FreeRunner u-boot usbtty generic serial + 5121 Neo1973/FreeRunner kernel mass storage (g_storage) mode + 5122 Neo1973/FreeRunner kernel cdc_ether USB network + 5123 Neo1973/FreeRunner internal USB CSR4 module + 5124 Neo1973/FreeRunner Bluetooth Device ID service + 5300 Rockbox + 6000 Ubertooth Zero + 6001 Ubertooth Zero (DFU) + 6002 Ubertooth One + 6003 Ubertooth One (DFU) + 6004 LeoLipo + 6005 LED Flower S + 6006 LED Cube + 6007 LED Flower + 6008 Kisbee 802.15.4 transceiver + 6009 Adjacent Reality Tracker + 600a AVR Programmer + 600b Hypna Go Go + 600c CatNip LPC1343 development board + 600d Enhanced RoboBrrd Brain board + 600e OpenRISC Ordb2a-ep4ce22 development board + 600f Paparazzi Lisa/M (DFU) + 6010 OpenPipe: OSHW Bagpipes MIDI controller + 6011 LeoLipo (DFU) + 6012 Universal C64 Cartridge + 6013 DiscFerret magnetic disc analyser (bootloader) + 6014 DiscFerret magnetic disc analyser + 6015 Smoothieboard + 6016 phInterface + 6017 Black Magic Debug Probe (DFU) + 6018 Black Magic Debug Probe (Application) + 6019 4pi 5 axis motion controller + 601a Paparazzi Lisa/M + 601b IST-2 chronograph for bullet speeds + 601c EPOSMote II + 601e 5x5 STM32 prototyping board + 601f uNSF + 6020 Toad3 + 6021 AlphaSphere + 6022 LightPack + 6023 Pixelkit + 6024 Illucia + 6025 Keyglove (HID) + 6027 Key64 Keyboard + 6028 Teensy 2.0 Development Board [ErgoDox Keyboard] + 602a Marlin 2.0 (Mass Storage) + 602b FPGALink + 602c 5nes5snes (5x8) + 602d 5nes5snes (4x12) + 602e Flexibity + 602f K-copter + 6030 USB-oscope + 6031 Handmade GSM GPS tracker + 6033 frobiac / adnw keyboard + 6034 Tiflomag Ergo 2 + 6035 FreeLaserTag Gun + 6036 FreeLaserTag Big Brother + 6037 FreeLaserTag Node + 6038 Monaka + 6039 eXtreme Feedback Device + 603a TiLDA + 603b Raspiface + 603c Paparazzi (bootloader) + 603d Paparazzi (Serial) + 603e Paparazzi (Mass Storage) + 603f airGuitar + 6040 moco + 6041 AlphaSphere (bootloader) + 6042 Dspace robot controller + 6043 pc-power + 6044 open-usb-can (DFU) + 6045 open-usb-can + 6046 mimus-weigand + 6047 RfCat Chronos Dongle + 6048 RfCat Dons Dongle + 6049 RfCat Chronos bootloader + 604a RfCat Dons bootloader + 604b HackRF Jawbreaker Software-Defined Radio + 604c Makibox A6 + 604d Paella Pulse height analyzer + 604e Miniscope v2b + 604f Miniscope v2c + 6050 GoodFET + 6051 pinocc.io + 6052 APB Team Robotic Development Board + 6053 Darkgame Controller + 6054 Satlab/AAUSAT3 BlueBox + 6056 The Glitch + 605b RfCat YARD Stick One + 605c YARD Stick One bootloader + 605d Funky Sensor v2 + 605e Blinkiverse Analog LED Fader + 605f Small DIP package Cypress FX2 + 6060 Data logger using the Cypress FX2 + 6061 Power Manager + 6063 CPC FPGA + 6064 CPC FPGA (DFU) + 6065 CPC FPGA (Serial) + 6066 Nuand BladeRF + 6067 Orbotron 9000 (Serial) + 6068 Orbotron 9000 (HID) + 6069 xser (DFU) + 606a xser (legacy) + 606b S08-245, urJtag compatible firmware for S08JS + 606c Blinkytape full-color light tape + 606d TinyG open source motion controller + 606e Reefangel Evolution 1.0 + 6070 Open Pinball Project + 6071 The Glitch HID + 6072 The Glitch Disk + 6073 The Glitch Serial + 6074 The Glitch MIDI + 6075 The Glitch RawHID + 6076 Vultureprog BIOS chip programmer + 6077 PaintDuino + 6078 DTplug + 607a Fadecandy + 607b RCDongle for IR remote control + 607c OpenVizsla USB sniffer/analyzer + 607d Spark Core Arduino-compatible board with WiFi + 607f Spark Core Arduino-compatible board with WiFi (bootloader) + 6080 arcin arcade controller + 6081 BladeRF (bootloader) + 6082 Facecandy (DFU) + 6083 LightUp (bootloader) + 6084 arcin arcade controller (DFU) + 6085 IRKit for controlloing home electronics from iOS devices + 6086 OneRNG entropy device + 6088 picp PIC16F145x based PIC16F145x programmer + 6089 Great Scott Gadgets HackRF One SDR + 608a BLEduino + 608b Loctronix ASR-2300 SDR/motion sensing module + 608c Fx2lafw + 608d Fx2lafw + 608e Fx2lafw + 608f Fx2lafw + 6090 Fx2lafw + 6091 Fx2lafw + 6092 Fx2lafw + 6093 Fx2lafw + 6094 Fx2lafw + 6095 Fx2lafw + 6096 LightUp (sketch) + 6097 Tessel JavaScript enabled Microcontroller with built-in WiFi + 6098 RFIDler + 6099 RASDR Radio Astronomy SDR Rx Interface + 609a RASDR Radio Astronomy SDR Tx Interface + 609b RASDR Radio Astronomy SDR (bootloader) + 609c antiAFK keyboard + 609d PIC16F145x bootloader + 609e Clyde Lamp by Fabule (bootloader) + 609f Clyde Lamp by Fabule (sketch) + 60a0 Smoothiepanel robotic control interface + 60a1 Airspy + 60a2 barebox (DFU) + 60a3 keyboard (bootloader) + 60a4 Papilio Duo (AVR) + 60a5 Papilio Duo (FPGA) + 60a6 HydraBus/HydraNFC (bootloader) + 60a7 HydraBus/HydraNFC + 60a8 reserved + 60a9 Blinky Light Controller (DFU) + 60aa Blinky Light Controller + 60ab AllPixel + 60ac OpenBLT generic microcontroller (bootloader) + 60b0 Waterott Arduino based Clock (caterina bootloader) + 60b1 Drinkbot (processing) + 60b2 Drinkbot (OTG-tablet support) + 60b3 calc.pw password generator device (standard) + 60b4 calc.pw password generator device (enhanced) + 60b5 TimVideos' HDMI2USB (FX2) - Unconfigured device + 60b6 TimVideos' HDMI2USB (FX2) - Firmware load/upgrade + 60b7 TimVideos' HDMI2USB (FX2) - HDMI/DVI Capture Device + 60b8 TimVideos' HDMI2USB (Soft+UTMI) - Unconfigured device + 60b9 TimVideos' HDMI2USB (Soft+UTMI) - Firmware upgrade + 60ba TimVideos' HDMI2USB (Soft+UTMI) - HDMI/DVI Capture Device + 60bc Simple CC25xx programmer / serial board + 60bd Open Source control interface for multimedia applications + 60be Pixelmatix Aurora (bootloader) + 60bf Pixelmatix Aurora + 60c1 BrewBit Model-T pOSHW temperature controller for homebrewers (bootloader) + 60c2 BrewBit Model-T pOSHW temperature controller for homebrewers + 60c3 X Antenna Tracker arduino board + 60c6 USBtrng hardware random number generator + 60c7 Zubax GNSS positioning module for light UAV systems + 60c8 Xlink data transfer and control system for Commodore C64 + 60c9 random number generator + 60ca FinalKey password manager + 60cb PteroDAQ Data Acquisition on FRDM-KL25Z and future boards + 60cc LamDiNao + 60de Cryptech.is random number generator + 60df Numato Opsis HDMI2USB board (unconfigured) + 60e0 Numato Opsis HDMI2USB board (JTAG Programming Mode) + 60e1 Numato Opsis HDMI2USB board (User Mode) + 60e2 Osmocom SIMtrace 2 (DFU) + 60e3 Osmocom SIMtrace 2 + 60e4 3D printed racing game - (Catalina CDC bootloader) + 60e5 3D printed racing game + 60e6 replacement for GoodFET/FaceDancer - GreatFet + 60e7 replacement for GoodFET/FaceDancer - GreatFet target + 60e8 Alpen Clack keyboard + 60e9 keyman64 keyboard itercepter + 60ea Wiggleport FPGA-based I/O board + 60ec Duet 3D Printer Controller + 60f0 UDAD-T1 data aquisition device (boot) + 60f1 UDAD-T1 data aquisition device + 60f2 UDAD-T2 data aquisition device (boot) + 60f3 UDAD-T2 data aquisition device + 60f4 Uniti ARC motor controller + 60f5 EightByEight Blinky Badge (DFU) + 60f6 EightByEight Blinky Badge + 60f7 cardio NFC/RFID card reader (bootloader) + 60f8 cardio NFC/RFID card reader + 60fc OnlyKey Two-factor Authentication and Password Solution + 6100 overlay64 video overlay module + 6104 ScopeFun open source instrumentation + 6108 Myriad-RF LimeSDR + 610c Magic Keys (boot) + 610d Magic Keys + 8085 Box0 (box0-v5) + cc15 rad1o badge for CCC congress 2015 +1d57 Xenta + 0005 Wireless Receiver (Keyboard and Mouse) + 0006 Wireless Receiver (RC Laser Pointer) + 000c Optical Mouse + 2400 Wireless Mouse Receiver + 32da 2.4GHz Receiver (Keyboard and Mouse) + 83d0 Click-mouse! + ac01 Wireless Receiver (Keyboard and Mouse) + ad02 SE340D PC Remote Control + af01 AUVIO Universal Remote Receiver for PlayStation 3 +1d5b Smartronix, Inc. +1d5c Fresco Logic + 2000 FL2000/FL2000DX VGA/DVI/HDMI Adapter +1d6b Linux Foundation + 0001 1.1 root hub + 0002 2.0 root hub + 0003 3.0 root hub + 0100 PTP Gadget + 0101 Audio Gadget + 0102 EEM Gadget + 0103 NCM (Ethernet) Gadget + 0104 Multifunction Composite Gadget + 0105 FunctionFS Gadget + 0200 Qemu Audio Device +1d90 Citizen + 201e PPU-700 +1d9d Sigma Sport + 1010 Docking Station Topline 2009 + 1011 Docking Station Topline 2012 +1de1 Actions Microelectronics Co. + 1101 Generic Display Device (Mass storage mode) + c101 Generic Display Device +1e0e Qualcomm / Option + f000 iCON 210 UMTS Surfstick +1e10 Point Grey Research, Inc. + 2004 Sony 1.3MP 1/3" ICX445 IIDC video camera [Chameleon] +1e17 Mirion Technologies Dosimetry Services Division + 0001 instadose dosimeter +1e1d Kanguru Solutions + 0165 Secure Pen drive + 1101 FlashBlu Flash Drive +1e1f INVIA +1e29 Festo AG & Co. KG + 0101 CPX Adapter + 0102 CPX Adapter >=HW10.09 [CP2102] + 0401 iL3-TP [AT90USB646] + 0402 FTDI232 [EasyPort] + 0403 FTDI232 [EasyPort Mini] + 0404 FTDI232 [Netzteil-GL] + 0405 FTDI232 [MotorPrüfstand] + 0406 STM32F103 [EasyKit] + 0407 LPC2378 [Robotino] + 0408 LPC2378 [Robotino-Arm] + 0409 LPC2378 [Robotino-Arm Bootloader] + 040a LPC2378 [Robotino Bootloader] + 040b LPC2378 [Robotino XT] + 040c LPC2378 [Robotino XT Bootloader] + 040d LPC2378 [Robotino 3] + 040e LPC2378 [Robotino 3 Bootloader] + 0501 CP2102 [CMSP] + 0601 CMMP-AS +1e3d Chipsbank Microelectronics Co., Ltd + 2093 CBM209x Flash Drive (OEM) + 4082 CBM4082 SD Card Reader +1e41 Cleverscope + 0001 CS328A PC Oscilloscope +1e4e Cubeternet + 0100 WebCam + 0102 GL-UPC822 UVC WebCam +1e54 TypeMatrix + 2030 2030 USB Keyboard +1e68 TrekStor GmbH & Co. KG + 001b DataStation maxi g.u + 0050 DataStation maxi light +1e71 NZXT + 0001 Avatar Optical Mouse +1e74 Coby Electronics Corporation + 2211 MP300 + 2647 2 GB 2 Go Video MP3 Player [MP601-2G] + 2659 Coby 4GB Go Video MP3 Player [MP620-4G] + 4641 A8705 MP3/Video Player + 6511 MP705-8G MP3 player + 6512 MP705-4G + 7111 MP957 Music and Video Player +1e7d ROCCAT + 2c24 Pyra Mouse (wired) + 2ced Kone Mouse + 2cf6 Pyra Mouse (wireless) + 2d50 Kova+ Mouse + 2d51 Kone+ Mouse + 2e22 Kone XTD Mouse + 30d4 Arvo Keyboard +1ea7 SHARKOON Technologies GmbH + 0066 [Mediatrack Edge Mini Keyboard] + 2007 SHARK ZONE K30 Illuminated Gaming Keyboard +1ebb NuCORE Technology, Inc. +1eda AirTies Wireless Networks + 2012 Air2210 54 Mbps Wireless Adapter + 2210 Air2210 54 Mbps Wireless Adapter + 2310 Air2310 150 Mbps Wireless Adapter + 2410 Air2410 300 Mbps Wireless Adapter +1edb Blackmagic design + bd3b Intensity Shuttle +1ee8 ONDA COMMUNICATION S.p.a. + 0014 MT833UP +1ef6 EADS Deutschland GmbH + 2233 Cassidian NH90 STTE + 5064 FDR Interface + 5523 Cassidian SSDC Adapter II + 5545 Cassidian SSDC Adapter III + 5648 RIU CSMU/BSD + 564a Cassidian RIU CSMU/BSD Simulator +1f28 Cal-Comp + 0020 CDMA USB Modem A600 + 0021 CD INSTALLER USB Device +1f3a Onda (unverified) + efe8 V972 tablet in flashing mode +1f44 The Neat Company + 0001 NM-1000 scanner +1f48 H-TRONIC GmbH + 0627 Data capturing system + 0628 Data capturing and control module +1f4d G-Tek Electronics Group + b803 Lifeview LV5TDLX DVB-T [RTL2832U] + d220 Geniatech T220 DVB-T2 TV Stick +1f6f Aliph + 0023 Jawbone Jambox + 8000 Jawbone Jambox - Updating +1f75 Innostor Technology Corporation + 0888 IS888 SATA Storage Controller + 0902 IS902 UFD controller +1f82 TANDBERG + 0001 PrecisionHD Camera +1f84 Alere, Inc. +1f87 Stantum + 0002 Multi-touch HID Controller +1f9b Ubiquiti Networks, Inc. + 0241 AirView2-EXT +1fab Samsung Opto-Electroncs Co., Ltd. + 104d ES65 +1fbd Delphin Technology AG + 0001 Expert Key - Data aquisition system +1fc9 NXP Semiconductors + 0003 LPC1343 + 010b PR533 + 012b i.MX 8M Dual/8M QuadLite/8M Quad Serial Downloader +1fde ILX Lightwave Corporation + 0001 UART Bridge +1fe7 Vertex Wireless Co., Ltd. + 1000 VW100 series CDMA EV-DO Rev.A modem +1ff7 CVT Electronics.Co.,Ltd + 0013 CVTouch Screen (HID) + 001a Human Interface Device +1fff Ideofy Inc. +2001 D-Link Corp. + 0001 DWL-120 WIRELESS ADAPTER + 0201 DHN-120 10Mb Home Phoneline Adapter + 1a00 DUB-E100 Fast Ethernet Adapter(rev.A) [ASIX AX88172] + 1a02 DUB-E100 Fast Ethernet Adapter(rev.C1) [ASIX AX88772] + 200c 10/100 Ethernet + 3200 DWL-120 802.11b Wireless Adapter(rev.E1) [Atmel at76c503a] + 3301 DWA-130 802.11n Wireless N Adapter(rev.C1) [Realtek RTL8192U] + 3306 DWL-G122 Wireless Adapter(rev.F1) [Realtek RTL8188SU] + 3308 DWA-121 802.11n Wireless N 150 Pico Adapter [Realtek RTL8188CUS] + 3309 DWA-135 802.11n Wireless N Adapter(rev.A1) [Realtek RTL8192CU] + 330a DWA-133 802.11n Wireless N Adapter [Realtek RTL8192CU] + 3500 Elitegroup Computer Systems WLAN card WL-162 + 3700 DWL-122 802.11b [Intersil Prism 3] + 3701 DWL-G120 Spinnaker 802.11g [Intersil ISL3886] + 3702 DWL-120 802.11b Wireless Adapter(rev.F) [Intersil ISL3871] + 3703 AirPlus G DWL-G122 Wireless Adapter(rev.A1) [Intersil ISL3880] + 3704 AirPlus G DWL-G122 Wireless Adapter(rev.A2) [Intersil ISL3887] + 3705 AirPlus G DWL-G120 Wireless Adapter(rev.C) [Intersil ISL3887] + 3761 IEEE 802.11g USB2.0 Wireless Network Adapter-PN + 3a00 DWL-AG132 [Atheros AR5523] + 3a01 DWL-AG132 (no firmware) [Atheros AR5523] + 3a02 DWL-G132 [Atheros AR5523] + 3a03 DWL-G132 (no firmware) [Atheros AR5523] + 3a04 DWL-AG122 [Atheros AR5523] + 3a05 DWL-AG122 (no firmware) [Atheros AR5523] + 3a80 AirPlus Xtreme G DWL-G132 Wireless Adapter + 3a81 predator Bootloader Download + 3a82 AirPremier AG DWL-AG132 Wireless Adapter + 3a83 predator Bootloader Download + 3b00 AirPlus DWL-120+ Wireless Adapter [Texas Instruments ACX100USB] + 3b01 WLAN Boot Device + 3c00 AirPlus G DWL-G122 Wireless Adapter(rev.B1) [Ralink RT2571] + 3c01 AirPlus AG DWL-AG122 Wireless Adapter + 3c02 AirPlus G DWL-G122 Wireless Adapter + 3c05 DUB-E100 Fast Ethernet Adapter(rev.B1) [ASIX AX88772] + 3c15 DWA-140 RangeBooster N Adapter(rev.B3) [Ralink RT5372] + 3c17 DWA-123 Wireless N 150 Adapter(rev.A1) [Ralink RT3370] + 3c19 DWA-125 Wireless N 150 Adapter(rev.A3) [Ralink RT5370] + 3c1a DWA-160 802.11abgn Xtreme N Dual Band Adapter(rev.B2) [Ralink RT5572] + 3c1b DWA-127 Wireless N 150 High-Gain Adapter(rev.A1) [Ralink RT3070] + 4000 DSB-650C Ethernet [klsi] + 4001 DSB-650TX Ethernet [pegasus] + 4002 DSB-650TX Ethernet [pegasus] + 4003 DSB-650TX-PNA Ethernet [pegasus] + 400b 10/100 Ethernet + 4102 10/100 Ethernet + 5100 DSL-200 ADSL ATM Modem + 5102 DSL-200 ADSL Loader + 5b00 Remote NDIS Network Device + 9414 Cable Modem + 9b00 Broadband Cable Modem Remote NDIS Device + abc1 DSB-650 Ethernet [pegasus] + f013 DLink 7 port USB2.0 Hub + f103 DUB-H7 7-port USB 2.0 hub + f10d Accent Communications Modem + f110 DUB-AV300 A/V Capture + f111 DBT-122 Bluetooth adapter + f112 DUB-T210 Audio Device + f116 Formosa 2 + f117 Formosa 3 + f118 Formosa 4 +2002 DAP Technologies +2003 detectomat + ea61 dc3500 +200c Reloop + 100b Play audio soundcard +2013 PCTV Systems + 0245 PCTV 73ESE + 0246 PCTV 74E + 0248 PCTV 282E + 024f nanoStick T2 290e +2019 PLANEX + 3220 GW-US11S WLAN [Atmel AT76C503A] + 4901 GW-USSuper300 802.11bgn Wireless Adapter [Realtek RTL8191SU] + 4903 GW-USFang300 802.11abgn Wireless Adapter [Realtek RTL8192DU] + 4904 GW-USUltra300 802.11abgn Wireless Adapter [Realtek RTL8192DU] + 5303 GW-US54GXS 802.11bg + 5304 GWUS300 802.11n + ab01 GW-US54HP + ab24 GW-US300MiniS + ab25 GW-USMini2N 802.11n Wireless Adapter [Ralink RT2870] + ab28 GW-USNano + ab29 GW-USMicro300 + ab2a GW-USNano2 802.11n Wireless Adapter [Realtek RTL8188CUS] + ab2b GW-USEco300 802.11bgn Wireless Adapter [Realtek RTL8192CU] + ab2c GW-USDual300 802.11abgn Wireless Adapter [Realtek RTL8192DU] + ab50 GW-US54Mini2 + c002 GW-US54SG + c007 GW-US54GZL + ed02 GW-USMM + ed06 GW-US300MiniW 802.11bgn Wireless Adapter + ed10 GW-US300Mini2 + ed14 GW-USMicroN + ed16 GW-USMicroN2W 802.11bgn Wireless Adapter [Realtek RTL8188SU] + ed17 GW-USValue-EZ 802.11n Wireless Adapter [Realtek RTL8188CUS] + ed18 GW-USHyper300 / GW-USH300N 802.11bgn Wireless Adapter [Realtek RTL8191SU] +203d Encore Electronics Inc. + 1480 ENUWI-N3 [802.11n Wireless N150 Adapter] +2040 Hauppauge + 0c80 Windham + 0c90 Windham + 1700 CataMount + 1800 Okemo A + 1801 Okemo B + 2000 Tiger Minicard + 2009 Tiger Minicard R2 + 200a Tiger Minicard + 2010 Tiger Minicard + 2011 WinTV MiniCard [Dell Digital TV Receiver] + 2019 Tiger Minicard + 2400 WinTV PVR USB2 (Model 24019) + 4700 WinTV Nova-S-USB2 + 4902 HD PVR + 4903 HS PVR + 4982 HD PVR + 5500 Windham + 5510 Windham + 5520 Windham + 5530 Windham + 5580 Windham + 5590 Windham + 6500 WinTV HVR-900 + 6502 WinTV HVR-900 + 6503 WinTV HVR-930 + 6513 WinTV HVR-980 + 7050 Nova-T Stick + 7060 Nova-T Stick 2 + 7070 Nova-T Stick 3 + 7240 WinTV HVR-850 + 8400 WinTV Nova-T-500 + 9300 WinTV NOVA-T USB2 (cold) + 9301 WinTV NOVA-T USB2 (warm) + 9941 WinTV Nova-T-500 + 9950 WinTV Nova-T-500 + b910 Windham + b980 Windham + b990 Windham + c000 Windham + c010 Windham +2047 Texas Instruments + 0200 MSP430 USB HID Bootstrap Loader + 0855 Invensense Embedded MotionApp HID Sensor + 0964 Inventio Software MSP430 +2058 Nano River Technology + 2058 ViperBoard I2C, SPI, GPIO interface +2077 Taicang T&W Electronics Co. Ltd + 9002 W1M100 HSPA/WCDMA Module +2080 Barnes & Noble + 0001 nook + 0002 NOOKcolor + 0003 NOOK Simple Touch + 0004 NOOK Tablet +2086 SIMPASS +2087 Cando + 0a01 Multi Touch Panel + 0a02 Multi Touch Panel + 0b03 Multi Touch Panel +20a0 Clay Logic + 4123 IKALOGIC SCANALOGIC 2 + 414a MDE SPI Interface + 415a OpenPilot + 415b CopterControl + 415c PipXtreme +20b1 XMOS Ltd + 10ad XUSB Loader + f7d1 XTAG2 - JTAG Adapter +20b3 Hanvon + 0a18 10.1 Touch screen overlay +20b7 Qi Hardware + 0713 Milkymist JTAG/serial + 1540 ben-wpan, AT86RF230-based + 1db5 IDBG in DFU mode + 1db6 IDBG in normal mode + c25b C2 Dongle + cb72 ben-wpan, cntr +20ce Minicircuits + 0012 RF Sythesizer 250-4200MHz model SSG-4000LH + 0021 RF Switch Matrix + 0022 I/O Controller +20df Simtec Electronics + 0001 Entropy Key [UDEKEY01] +20f1 NET New Electronic Technology GmbH + 0101 iCube3 Camera +20f4 TRENDnet + 648b TEW-648UBM 802.11n 150Mbps Micro Wireless N Adapter [Realtek RTL8188CUS] +20f7 XIMEA + 3001 MQ or MD camera + 3002 MU camera + 3021 MJ camera + 30b3 MQ in U3V mode or MC camera + a003 MU camera +2100 RT Systems + 9e52 Yaesu VX-7 + 9e54 CT29B Radio Cable + 9e57 RTS01 Radio Cable + 9e5d K4Y Radio Cable + 9e5f FT232RL [RTS05 Serial Cable] +2101 ActionStar + 0201 SIIG 4-to-2 Printer Switch +2109 VIA Labs, Inc. + 0700 VL700 SATA 3Gb/s bridge + 0701 VL701 SATA 3Gb/s bridge + 0810 VL81x Hub + 0811 Hub + 0812 VL812 Hub + 2811 Hub + 2812 VL812 Hub + 3431 Hub + 8110 Hub +2113 Softkinetic + 0137 DepthSense 311 (3D) + 0145 DepthSense 325 + 8000 DepthSense 311 (Color) +2149 Advanced Silicon S.A. + 211b Touchscreen Controller + 2703 TS58xxA/TC56xxA [CoolTouch] +2162 Creative (?) + 2031 Network Blaster Wireless Adapter + 500c DE5771 Modem Blaster + 8001 Broadxent BritePort DSL Bridge 8010U +2184 GW Instek + 0005 GDS-3000 Oscilloscope + 0006 GDS-3000 Oscilloscope + 0011 AFG Function Generator (CDC) +21a1 Emotiv Systems Pty. Ltd. + 0001 EPOC Consumer Headset Wireless Dongle +21d6 Agecodagis SARL + 0002 Seismic recorder [Tellus] +2207 Fuzhou Rockchip Electronics Company + 0010 GoClever Tab R83 + 0011 SmartTab + 281a RK2818 in Mask ROM mode + 290a RK2918 in Mask ROM mode + 292a RK2928 in Mask ROM mode + 292c RK3026 in Mask ROM mode + 300a RK3066 in Mask ROM mode + 300b RK3168 in Mask ROM mode + 301a RK3036 in Mask ROM mode + 310a RK3066B in Mask ROM mode + 310b RK3188 in Mask ROM mode + 310c RK3126/RK3128 in Mask ROM mode + 310d RK3126 in Mask ROM mode + 320a RK3288 in Mask ROM mode + 320b RK3228/RK3229 in Mask ROM mode + 320c RK3328 in Mask ROM mode + 330a RK3368 in Mask ROM mode + 330c RK3399 in Mask ROM mode +2222 MacAlly + 0004 iWebKey Keyboard + 2520 Mini Tablet + 4050 AirStick joystick +2227 SAMWOO Enterprise + 3105 SKYDATA SKD-U100 +2232 Silicon Motion + 1005 WebCam SCB-0385N + 1028 WebCam SC-03FFL11939N + 1029 WebCam SC-13HDL11939N + 1037 WebCam SC-03FFM12339N +2233 RadioShack Corporation + 6323 USB Electronic Scale +2237 Kobo Inc. + 4161 eReader White +224f APDM + 0001 Access Point + 0002 Docking Station + 0004 V2 Opal ACM + 0005 V2 Opal + 0006 V2 Docking Station + 0007 V2 Access Point ACM + 0008 V2 Access Point +225d Morpho + 0001 FINGER VP Multimodal Biometric Sensor + 0008 CBM-E3 Fingerprint Sensor + 0009 CBM Fingerprint Sensor [CBM-V3] + 000a MSO1300-E3 Fingerprint Sensor + 000b MSO1300 Fingerprint Sensor [MSO1300-V3] + 000c MSO1350-E3 Fingerprint Sensor & SmartCard Reader + 000d MSO1350 Fingerprint Sensor & SmartCard Reader [MSO1350-V3] + 000e MorphoAccess SIGMA Biometric Access Control Terminal +228d 8D Technologies inc. + 0001 Terminal Bike Key Reader +22a6 Pie Digital, Inc. + ffff PieKey "beta" 4GB model 4E4F41482E4F5247 (SM3251Q BB) +22b8 Motorola PCS + 0001 Wally 2.2 chipset + 0002 Wally 2.4 chipset + 0005 V.60c/V.60i GSM Phone + 0830 2386C-HT820 + 0833 2386C-HT820 [Flash Mode] + 0850 Bluetooth Device + 1001 Patriot 1.0 (GSM) chipset + 1002 Patriot 2.0 chipset + 1005 T280e GSM/GPRS Phone + 1101 Patriot 1.0 (TDMA) chipset + 1801 Rainbow chipset flash + 2035 Bluetooth Device + 2805 GSM Modem + 2821 T720 GSM Phone + 2822 V.120e GSM Phone + 2823 Flash Interface + 2a01 MSM6050 chipset + 2a02 CDMA modem + 2a03 MSM6050 chipset flash + 2a21 V710 GSM Phone (P2K) + 2a22 V710 GSM Phone (AT) + 2a23 MSM6100 chipset flash + 2a41 MSM6300 chipset + 2a42 Usb Modem + 2a43 MSM6300 chipset flash + 2a61 E815 GSM Phone (P2K) + 2a62 E815 GSM Phone (AT) + 2a63 MSM6500 chipset flash + 2a81 MSM6025 chipset + 2a83 MSM6025 chipset flash + 2ac1 MSM6100 chipset + 2ac3 MSM6100 chipset flash + 2d78 XT300[SPICE] + 3001 A835/E1000 GSM Phone (P2K) + 3002 A835/E1000 GSM Phone (AT) + 3801 C350L/C450 (P2K) + 3802 C330/C350L/C450/EZX GSM Phone (AT) + 3803 Neptune LT chipset flash + 4001 OMAP 1.0 chipset + 4002 A920/A925 UMTS Phone + 4003 OMAP 1.0 chipset flash + 4008 OMAP 1.0 chipset RDL + 41d6 Droid X (Windows media mode) + 41d9 Droid/Milestone + 41db Droid/Milestone (Debug mode) + 41de Droid X (PC mode) + 4204 MPx200 Smartphone + 4214 MPc GSM + 4224 MPx220 Smartphone + 4234 MPc CDMA + 4244 MPx100 Smartphone + 4285 Droid X (Mass storage) + 4801 Neptune LTS chipset + 4803 Neptune LTS chipset flash + 4810 Triplet GSM Phone (storage) + 4901 Triplet GSM Phone (P2K) + 4902 Triplet GSM Phone (AT) + 4903 Neptune LTE chipset flash + 4a01 Neptune LTX chipset + 4a03 Neptune LTX chipset flash + 4a32 L6-imode Phone + 5801 Neptune ULS chipset + 5803 Neptune ULS chipset flash + 5901 Neptune VLT chipset + 5903 Neptune VLT chipset flash + 6001 Dalhart EZX + 6003 Dalhart flash + 6004 EZX GSM Phone (CDC Net) + 6006 MOTOROKR E6 + 6008 Dalhart RDL + 6009 EZX GSM Phone (P2K) + 600a Dalhart EZX config 17 + 600b Dalhart EZX config 18 + 600c EZX GSM Phone (USBLAN) + 6021 JUIX chipset + 6023 JUIX chipset flash + 6026 Flash RAM Downloader/miniOS + 6027 USBLAN + 604c EZX GSM Phone (Storage) + 6101 Talon integrated chipset + 6401 Argon chipset + 6403 Argon chipset flash + 6415 ROKR Z6 (MTP mode) + 6604 Washington CDMA Phone + 6631 CDC Modem + 7001 Q Smartphone + fe01 StarTAC III MS900 +22b9 eTurboTouch Technology, Inc. + 0006 Touch Screen +22ba Technology Innovation Holdings, Ltd +22e0 secunet Security Networks AG + 0002 SINA Flash Drive + 0003 SINA ID Token A +2304 Pinnacle Systems, Inc. + 0109 Studio PCTV USB (SECAM) + 0110 Studio PCTV USB (PAL) + 0111 Miro PCTV USB + 0112 Studio PCTV USB (NTSC) with FM radio + 0201 Systems MovieBox Device + 0204 MovieBox USB_B + 0205 DVC 150B + 0206 Systems MovieBox Deluxe Device + 0207 Dazzle DVC90 Video Device + 0208 Studio PCTV USB2 + 020e PCTV 200e + 020f PCTV 400e BDA Device + 0210 Studio PCTV USB (PAL) with FM radio + 0212 Studio PCTV USB (NTSC) + 0213 500-USB Device + 0214 Studio PCTV USB (PAL) with FM radio + 0216 PCTV 60e + 0219 PCTV 260e + 021a Dazzle DVC100 Audio Device + 021b Dazzle DVC130/DVC170 + 021d Dazzle DVC130 + 021e Dazzle DVC170 + 021f PCTV Sat HDTV Pro BDA Device + 0222 PCTV Sat Pro BDA Device + 0223 DazzleTV Sat BDA Device + 0225 Remote Kit Infrared Transceiver + 0226 PCTV 330e + 0227 PCTV for Mac, HD Stick + 0228 PCTV DVB-T Flash Stick + 0229 PCTV Dual DVB-T 2001e + 022a PCTV 160e + 022b PCTV 71e [Afatech AF9015] + 0232 PCTV 170e + 0236 PCTV 72e [DiBcom DiB7000PC] + 0237 PCTV 73e [DiBcom DiB7000PC] + 023a PCTV 801e + 023b PCTV 801e SE + 023d PCTV 340e + 023e PCTV 340e SE + 0300 Studio Linx Video input cable (NTSC) + 0301 Studio Linx Video input cable (PAL) + 0302 Dazzle DVC120 + 0419 PCTV Bungee USB (PAL) with FM radio + 061d PCTV Deluxe (NTSC) Device + 061e PCTV Deluxe (PAL) Device +2318 Shining Technologies, Inc. [hex] + 0011 CitiDISK Jr. IDE Enclosure +2341 Arduino SA + 0001 Uno (CDC ACM) + 0010 Mega 2560 (CDC ACM) + 003b Serial Adapter (CDC ACM) + 003f Mega ADK (CDC ACM) + 0042 Mega 2560 R3 (CDC ACM) + 0043 Uno R3 (CDC ACM) + 0044 Mega ADK R3 (CDC ACM) + 0045 Serial R3 (CDC ACM) + 8036 Leonardo (CDC ACM, HID) +2357 TP-Link + 0100 TL-WN8200ND [Realtek RTL8192CU] + 0101 RTL8812AU Archer T4U 802.11ac + 0103 Archer T4UH wireless Realtek 8812AU + 0105 Archer T1U 802.11a/n/ac Wireless Adapter [MediaTek MT7610U] + 0106 Archer T9UH v1 [Realtek RTL8814AU] + 0107 TL-WN821N Version 5 RTL8192EU + 0108 TL-WN822N Version 4 RTL8192EU + 0109 TL WN823N RTL8192EU + 010c TL-WN722N v2 + 010e TL-WN722N v2 + 0200 MA 180 Zero CD + 0201 HSUPA Modem MA180 +2373 Pumatronix Ltda + 0001 5 MegaPixel Digital Still Camera [DSC5M] +2375 Digit@lway, Inc. + 0001 Digital Audio Player +2406 SANHO Digital Electronics Co., Ltd. + 6688 PD7X Portable Storage +2443 Aessent Technology Ltd + 00dc aes220 FPGA Mini-Module +2478 Tripp-Lite + 2008 U209-000-R Serial Port +248a Maxxter + 8366 Wireless Optical Mouse ACT-MUSW-002 +249c M2Tech s.r.l. +24e1 Paratronic + 3001 Adp-usb + 3005 Radius +2516 Cooler Master Co., Ltd. + 0003 Storm Xornet + 0004 Storm QuickFire Rapid Mechanical Keyboard + 0006 Storm Recon + 0007 Storm Sentinel Advance II + 0009 Storm Quick Fire PRO + 0011 Storm Quick Fire TK + 0017 CM Storm Quick Fire Stealth + 0020 QuickFire Rapid-i Keyboard + 0027 CM Storm Coolermaster Novatouch TKL + 002d Alcor mouse + 0047 MasterKeys Pro L + 9494 Sirus Headset +2548 Pulse-Eight + 1001 CEC Adapter + 1002 CEC Adapter +2632 TwinMOS + 3209 7-in-1 Card Reader +2639 Xsens + 0001 MTi-10 IMU + 0002 MTi-20 VRU + 0003 MTi-30 AHRS + 0011 MTi-100 IMU + 0012 MTi-200 VRU + 0013 MTi-300 AHRS + 0017 MTi-G 7xx GNSS/INS + 0100 Body Pack + 0101 Awinda Station + 0102 Awinda Dongle + 0103 Sync Station + 0200 MTw + d00d Wireless Receiver +2650 Electronics For Imaging, Inc. [hex] +2659 Sundtek + 1101 TNT DVB-T/DAB/DAB+/FM + 1201 FM Transmitter/Receiver + 1202 MediaTV Analog/FM/DVB-T + 1203 MediaTV Analog/FM/DVB-T MiniPCIe + 1204 MediaTV Analog/FM/ATSC + 1205 SkyTV Ultimate V + 1206 MediaTV DVB-T MiniPCIe + 1207 Sundtek HD Capture + 1208 Sundtek SkyTV Ultimate III + 1209 MediaTV Analog/FM/ATSC MiniPCIe + 1210 MediaTV Pro III (EU) + 1211 MediaTV Pro III (US) + 1212 MediaTV Pro III MiniPCIe (EU) + 1213 MediaTV Pro III MiniPCIe (US) +2676 Basler AG + ba02 ace +2717 Xiaomi Inc. + 0011 100Mbps Network Card Adapter + 0360 Mi3W + 0368 Mi4 LTE + 3801 Mi ANC & Type-C In-Ear Earphones + 4106 MediaTek MT7601U [MI WiFi] + ff08 Redmi Note 3 (ADB Interface) + ff10 Mi/Redmi series (PTP) + ff18 Mi/Redmi series (PTP + ADB) + ff40 Mi/Redmi series (MTP) + ff48 Mi/Redmi series (MTP + ADB) + ff60 redmi prime 2 + ff68 Mi-4c + ff80 Mi/Redmi series (RNDIS) + ff88 Mi/Redmi series (RNDIS + ADB) +2730 Citizen + 200f CT-S310 Label printer +2735 DigitalWay + 0003 MPIO HS100 + 1001 MPIO FY200 + 1002 MPIO FL100 + 1003 MPIO FD100 + 1004 MPIO HD200 + 1005 MPIO HD300 + 1006 MPIO FG100 + 1007 MPIO FG130 + 1008 MPIO FY300 + 1009 MPIO FY400 + 100a MPIO FL300 + 100b MPIO HS200 + 100c MPIO FL350 + 100d MPIO FY500 + 100e MPIO FY500 + 100f MPIO FY600 + 1012 MPIO FL400 + 1013 MPIO HD400 + 1014 MPIO HD400 + 1016 MPIO FY700 + 1017 MPIO FY700 + 1018 MPIO FY800 + 1019 MPIO FY800 + 101a MPIO FY900 + 101b MPIO FY900 + 102b MPIO FL500 + 102c MPIO FL500 + 103f MPIO FY570 + 1040 MPIO FY570 + 1041 MPIO FY670 + 1042 MPIO FY670 + 1043 HCT HMD-180A + 1044 HCT HMD-180A +273f Hughski Limited + 1000 ColorHug bootloader + 1001 ColorHug + 1002 ColorHug+ + 1003 ColorHug+ Bootloader + 1004 ColorHug2 + 1005 ColorHug2 bootloader +2770 NHJ, Ltd + 0a01 ScanJet 4600 series + 905c Che-Ez Snap SNAP-U/Digigr8/Soundstar TDC-35 + 9060 A130 + 9120 Che-ez! Snap / iClick Tiny VGA Digital Camera + 9130 TCG 501 + 913c Argus DC-1730 + 9150 Mini Cam + 9153 iClick 5X + 915d Cyberpix S-210S / Little Tikes My Real Digital Camera + 930b CCD Webcam(PC370R) + 930c CCD Webcam(PC370R) +27b8 ThingM + 01ed blink(1) +27c6 Shenzhen Goodix Technology Co.,Ltd. + 5117 Fingerprint Reader + 5201 Fingerprint Reader + 5301 Fingerprint Reader + 530c Fingerprint Reader + 5385 Fingerprint Reader + 538c Fingerprint Reader + 5395 Fingerprint Reader + 5584 Fingerprint Reader + 55b4 Fingerprint Reader + 5740 Fingerprint Reader +2821 ASUSTek Computer Inc. + 0161 WL-161 802.11b Wireless Adapter [SiS 162U] + 160f WL-160g 802.11g Wireless Adapter [Envara WiND512] + 3300 WL-140 / Hawking HWU36D 802.11b Wireless Adapter [Intersil PRISM 3] +2899 Toptronic Industrial Co., Ltd + 012c Camera Device +289b Dracal/Raphnet technologies + 0001 Gamecube/N64 controller v2.2 + 0002 2nes2snes + 0003 4nes4snes + 0004 Gamecube/N64 controller v2.3 + 0005 Saturn (Joystick mode) + 0006 Saturn (Mouse mode) + 0007 Famicom controller + 0008 Dreamcast (Joystick mode) + 0009 Dreamcast (Mouse mode) + 000a Dreamcast (Keyboard mode) + 000b Gamecube/N64 controller v2.9 (Keyboard mode) + 000c Gamecube/N64 controller v2.9 (Joystick mode) + 0100 Dual-relay board + 0500 Energy meter + 0502 Precision barometer +28de Valve Software + 1102 Wired Controller + 1142 Wireless Steam Controller + 2000 Lighthouse FPGA RX + 2101 Watchman Dongle +2931 Jolla Oy + 0a01 Jolla Phone MTP + 0a02 Jolla Phone Developer + 0a05 Jolla PC connection + 0afe Jolla charging only +2939 Zaber Technologies Inc. + 4959 A-MCB2 + 495a X-MCB1 + 495b X-MCB2 +2a03 dog hunter AG + 0001 Linino ONE (bootloader) + 0036 Arduino Leonardo (bootloader) + 0037 Arduino Micro (bootloader) + 0038 Arduino Robot Control (bootloader) + 0039 Arduino Robot Motor (bootloader) + 003a Arduino Micro ADK rev3 (bootloader) + 003b Arduino Serial + 003c Arduino Explora (bootloader) + 003d Arduino Due (usb2serial) + 003e Arduino Due + 0041 Arduino Yun (bootloader) + 0042 Arduino Mega 2560 Rev3 + 0043 Arduino Uno Rev3 + 004d Arduino Zero Pro (bootloader) + 8001 Linino ONE (CDC ACM) + 8036 Arduino Leonardo (CDC ACM) + 8037 Arduino Micro (CDC ACM) + 8038 Arduino Robot Control (CDC ACM) + 8039 Arduino Robot Motor (CDC ACM) + 803a Arduino Micro ADK rev3 (CDC ACM) + 803c Arduino Explora (CDC ACM) + 8041 Arduino Yun (CDC ACM) + 804d Arduino Zero Pro (CDC ACM) +2a37 RTD Embedded Technologies, Inc. + 5110 UPS35110/UPS25110 +2a45 Meizu Corp. + 0001 MX Phone (BICR) + 0c02 MX Phone (MTP & ADB) + 0c03 MX Phone (BICR & ADB) + 2008 MX Phone (MTP) + 200a MX Phone (MTP & ACM & ADB) + 200b MX Phone (PTP) + 200c MX Phone (PTP & ADB) + 2012 MX Phone (MTP & ACM) +2ac7 Ultrahaptics Ltd. + 0101 Evaluation Kit [Dragonfly] + 0102 UHDK5 + 0104 Touchbase + 0110 STRATOS Explore + 0111 STRATOS Explore DFU + 0112 STRATOS Inspire + 0113 STRATOS Inspire DFU + ffff DFU +2b24 KeepKey LLC + 0001 Bitcoin hardware wallet +2c02 Planex Communications + 14ea GW-US11H WLAN +2c1a Dolphin Peripherals + 0000 Wireless Optical Mouse +2c7c Quectel Wireless Solutions Co., Ltd. + 0121 EC21 LTE modem + 0125 EC25 LTE modem + 0191 EG91 LTE modem + 0195 EG95 LTE modem + 0296 BG96 CAT-M1/NB-IoT modem + 0306 EG06/EP06/EM06 LTE-A modem + 0435 AG35 LTE modem +2cdc Sea & Sun Technology GmbH + f232 CTD48Mc CTD Probe +2dcf Dialog Semiconductor + c952 Audio Class 2.0 Devices +2fb2 Fujitsu, Ltd +3016 Boundary Devices, LLC + 0001 Nitrogen Bootloader +30a4 Blues Wireless + 0001 Notecard +30c2 UNPARALLEL Innovation, Lda + 1388 SPL Meter +30ee Fujitsu Connected Technologies Limited + 1001 F-01L +3125 Eagletron + 0001 TrackerPod Camera Stand +3136 Navini Networks +3176 Whanam Electronics Co., Ltd +3195 Link Instruments + f190 MSO-19 + f280 MSO-28 + f281 MSO-28 +3275 VidzMedia Pte Ltd + 4fb1 MonsterTV P2H +3333 InLine + 3333 2 port KVM switch model 60652K +3334 AEI + 1701 Fast Ethernet +3340 Yakumo + 043a Mio A701 DigiWalker PPCPhone + 0e3a Pocket PC 300 GPS SL / Typhoon MyGuide 3500 + a0a3 deltaX 5 BT (D) PDA +3344 Leaguer Microelectronics (LME) + 3744 OEM PC Remote +3504 Micro Star + f110 Security Key +3538 Power Quotient International Co., Ltd + 0001 Travel Flash + 0015 Mass Storge Device + 0022 Hi-Speed Mass Storage Device + 0042 Cool Drive U339 Flash Disk + 0054 Flash Drive (2GB) +3579 DIVA + 6901 Media Reader +357d Sharkoon + 7788 QuickPort XT +3636 InVibro +3838 WEM + 0001 5-in-1 Card Reader +3923 National Instruments Corp. + 12c0 DAQPad-6020E + 12d0 DAQPad-6507 + 12e0 NI 4350 + 12f0 NI 5102 + 1750 DAQPad-6508 + 17b0 USB-ISA-Bridge + 1820 DAQPad-6020E (68 pin I/O) + 1830 DAQPad-6020E (BNC) + 1f00 DAQPad-6024E + 1f10 DAQPad-6024E + 1f20 DAQPad-6025E + 1f30 DAQPad-6025E + 1f40 DAQPad-6036E + 1f50 DAQPad-6036E + 2f80 DAQPad-6052E + 2f90 DAQPad-6052E + 702b GPIB-USB-B + 703c USB-485 RS485 Cable + 709b GPIB-USB-HS + 7254 NI MIO (data acquisition card) firmware updater + 729e USB-6251 (OEM) data acquisition card +40bb I-O Data + 0a09 USB2.0-SCSI Bridge USB2-SC +4101 i-rocks + 1301 IR-2510 usb phone +4102 iRiver, Ltd. + 1001 iFP-100 series mp3 player + 1003 iFP-300 series mp3 player + 1005 iFP-500 series mp3 player + 1007 iFP-700 series mp3/ogg vorbis player + 1008 iFP-800 series mp3/ogg vorbis player + 100a iFP-1000 series mp3/ogg vorbis player + 1014 T20 series mp3/ogg vorbis player (ums firmware) + 1019 T30 + 1034 T60 + 1040 M1Player + 1041 E100 (ums) + 1101 iFP-100 series mp3 player (ums firmware) + 1103 iFP-300 series mp3 player (ums firmware) + 1105 iFP-500 series mp3 player (ums firmware) + 1113 T10 (alternate) + 1117 T10 + 1119 T30 series mp3/ogg/wma player + 1141 E100 (mtp) + 2002 H10 6GB + 2101 H10 20GB (mtp) + 2102 H10 5GB (mtp) + 2105 H10 5/6GB (mtp) +413c Dell Computer Corp. + 0000 DRAC 5 Virtual Keyboard and Mouse + 0001 DRAC 5 Virtual Media + 0058 Port Replicator + 1001 Keyboard Hub + 1002 Keyboard Hub + 1003 Keyboard Hub + 1005 Multimedia Pro Keyboard Hub + 2001 Keyboard HID Support + 2002 SK-8125 Keyboard + 2003 Keyboard + 2005 RT7D50 Keyboard + 2010 Keyboard + 2011 Multimedia Pro Keyboard + 2100 SK-3106 Keyboard + 2101 SmartCard Reader Keyboard + 2105 Model L100 Keyboard + 2106 Dell QuietKey Keyboard + 2500 DRAC4 Remote Access Card + 2513 internal USB Hub of E-Port Replicator + 3010 Optical Wheel Mouse + 3012 Optical Wheel Mouse + 3016 Optical 5-Button Wheel Mouse + 3200 Mouse + 4001 Axim X5 + 4002 Axim X3 + 4003 Axim X30 + 4004 Axim Sync + 4005 Axim Sync + 4006 Axim Sync + 4007 Axim Sync + 4008 Axim Sync + 4009 Axim Sync + 4011 Axim X51v + 5103 AIO Printer A940 + 5105 AIO Printer A920 + 5107 AIO Printer A960 + 5109 Photo AIO Printer 922 + 5110 Photo AIO Printer 962 + 5111 Photo AIO Printer 942 + 5112 Photo AIO Printer 924 + 5113 Photo AIO Printer 944 + 5114 Photo AIO Printer 964 + 5115 Photo AIO Printer 926 + 5116 AIO Printer 946 + 5117 Photo AIO Printer 966 + 5118 AIO 810 + 5124 Laser MFP 1815 + 5128 Photo AIO 928 + 5200 Laser Printer + 5202 Printing Support + 5203 Printing Support + 5210 Printing Support + 5211 1110 Laser Printer + 5220 Laser MFP 1600n + 5225 Printing Support + 5226 Printing Support + 5300 Laser Printer + 5400 Laser Printer + 5401 Laser Printer + 5513 WLA3310 Wireless Adapter [Intersil ISL3887] + 5601 Laser Printer 3100cn + 5602 Laser Printer 3000cn + 5631 Laser Printer 5100cn + 5905 Printing Support + 8000 BC02 Bluetooth Adapter + 8010 TrueMobile Bluetooth Module in + 8100 TrueMobile 1180 802.11b Adapter [Intersil PRISM 3] + 8102 TrueMobile 1300 802.11g Wireless Adapter [Intersil ISL3880] + 8103 Wireless 350 Bluetooth + 8104 Wireless 1450 Dual-band (802.11a/b/g) Adapter [Intersil ISL3887] + 8105 U2 in HID - Driver + 8106 Wireless 350 Bluetooth Internal Card in + 8110 Wireless 3xx Bluetooth Internal Card + 8111 Wireless 3xx Bluetooth Internal Card in + 8114 Wireless 5700 Mobile Broadband (CDMA EV-DO) Minicard Modem + 8115 Wireless 5500 Mobile Broadband (3G HSDPA) Minicard Modem + 8116 Wireless 5505 Mobile Broadband (3G HSDPA) Minicard Modem + 8117 Wireless 5700 Mobile Broadband (CDMA EV-DO) Expresscard Modem + 8118 Wireless 5510 Mobile Broadband (3G HSDPA) Expresscard Status Port + 8120 Bluetooth adapter + 8121 Eastfold in HID + 8122 Eastfold in DFU + 8123 eHome Infrared Receiver + 8124 eHome Infrared Receiver + 8126 Wireless 355 Bluetooth + 8127 Wireless 355 Module with Bluetooth 2.0 + EDR Technology. + 8128 Wireless 5700-Sprint Mobile Broadband (CDMA EV-DO) Mini-Card Status Port + 8129 Wireless 5700-Telus Mobile Broadband (CDMA EV-DO) Mini-Card Status Port + 8131 Wireless 360 Bluetooth 2.0 + EDR module. + 8133 Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port + 8134 Wireless 5720 Sprint Mobile Broadband (EVDO Rev-A) Minicard Status Port + 8135 Wireless 5720 TELUS Mobile Broadband (EVDO Rev-A) Minicard Diagnostics Port + 8136 Wireless 5520 Cingular Mobile Broadband (3G HSDPA) Minicard Diagnostics Port + 8137 Wireless 5520 Voda L Mobile Broadband (3G HSDPA) Minicard Status Port + 8138 Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard EAP-SIM Port + 8140 Wireless 360 Bluetooth + 8142 Mobile 360 in DFU + 8147 F3507g Mobile Broadband Module + 8156 Wireless 370 Bluetooth Mini-card + 8157 Integrated Keyboard + 8158 Integrated Touchpad / Trackstick + 8160 Wireless 365 Bluetooth + 8161 Integrated Keyboard + 8162 Integrated Touchpad [Synaptics] + 8171 Gobi Wireless Modem (QDL mode) + 8172 Gobi Wireless Modem + 8183 F3607gw Mobile Broadband Module + 8184 F3607gw v2 Mobile Broadband Module + 8185 Gobi 2000 Wireless Modem (QDL mode) + 8186 Gobi 2000 Wireless Modem + 8187 DW375 Bluetooth Module + 8501 Bluetooth Adapter + 9500 USB CP210x UART Bridge Controller [DW700] + a001 Hub + a005 Internal 2.0 Hub + a700 Hub (in 1905FP LCD Monitor) +4146 USBest Technology + 9281 Iomega Micro Mini 128MB Flash Drive + ba01 Intuix Flash Drive +4168 Targus + 1010 Wireless Compact Laser Mouse +4242 USB Design by Example + 4201 Buttons and Lights HID device + 4220 Echo 1 Camera +4255 GoPro + 1000 9FF2 [Digital Photo Display] + 2000 HD2-14 [Hero 2 Camera] +4317 Broadcom Corp. + 0700 U.S. Robotics USR5426 802.11g Adapter + 0701 U.S. Robotics USR5425 Wireless MAXg Adapter + 0711 Belkin F5D7051 v3000 802.11g + 0720 Dynex DX-BUSB +4348 WinChipHead + 5523 USB->RS 232 adapter with Prolifec PL 2303 chipset + 5537 13.56Mhz RFID Card Reader and Writer + 5584 CH34x printer adapter cable +4572 Shuttle, Inc. + 4572 Shuttle PN31 Remote +4586 Panram + 1026 Crystal Bar Flash Drive +4670 EMS Production + 9394 Game Cube USB Memory Adaptor 64M +4752 Miditech + 0011 Midistart-2 +4757 GW Instek + 2009 PEL-2000 Series Electronic Load (CDC) + 2010 PEL-2000 Series Electronic Load (CDC) +4766 Aceeca + 0001 MEZ1000 RDA +4855 Memorex + 7288 Ultra Traveldrive 160G 2.5" HDD +4971 SimpleTech + cb01 SP-U25/120G + ce17 1TB SimpleDrive II USB External Hard Drive +4d46 Musical Fidelity + 0001 V-Link + 0002 V-DAC II +5032 Grandtec + 0bb8 Grandtec USB1.1 DVB-T (cold) + 0bb9 Grandtec USB1.1 DVB-T (warm) + 0fa0 Grandtec USB1.1 DVB-T (cold) + 0fa1 Grandtec USB1.1 DVB-T (warm) +5041 Linksys (?) + 2234 WUSB54G v1 802.11g Adapter [Intersil ISL3886] + 2235 WUSB54GP v1 802.11g Adapter [Intersil ISL3886] +50c2 Averatec (?) + 4013 WLAN Adapter +5173 Sweex + 1809 ZD1211 +5219 I-Tetra + 1001 Cetus CDC Device +5345 Owon + 1234 PDS6062T Oscilloscope +534c SatoshiLabs + 0001 Bitcoin Wallet [TREZOR] +5354 Meyer Instruments (MIS) + 0017 PAXcam2 +544d Transmeta Corp. +5543 UC-Logic Technology Corp. + 0002 SuperPen WP3325U Tablet + 0003 Tablet WP4030U + 0004 Tablet WP5540U + 0005 Tablet WP8060U + 0041 Genius PenSketch 6x8 Tablet + 0042 Tablet PF1209 + 0064 Aiptek HyperPen 10000U +5555 Epiphan Systems Inc. + 1110 VGA2USB + 1120 KVM2USB + 2222 DVI2USB + 3333 VGA2USB Pro + 3337 KVM2USB Pro + 3340 VGA2USB LR + 3344 KVM2USB LR + 3411 DVI2USB Solo + 3422 DVI2USB Duo +55aa OnSpec Electronic, Inc. + 0015 Hard Drive + 0102 SuperDisk + 0103 IDE Hard Drive + 0201 DDI to Reader-19 + 1234 ATAPI Bridge + a103 Sandisk SDDR-55 SmartMedia Card Reader + b000 USB to CompactFlash Card Reader + b004 OnSpec MMC/SD Reader/Writer + b00b USB to Memory Stick Card Reader + b00c USB to SmartMedia Card Reader + b012 Mitsumi FA402M 8-in-2 Card Reader + b200 Compact Flash Reader + b204 MMC/ SD Reader + b207 Memory Stick Reader +5654 Gotview + ca42 MasterHD 3 +5656 Uni-Trend Group Limited + 0832 UT2000/UT3000 Digital Storage Oscilloscope +595a IRTOUCHSYSTEMS Co. Ltd. + 0001 Touchscreen +5986 Acer, Inc + 0100 Orbicam + 0101 USB2.0 Camera + 0102 Crystal Eye Webcam + 01a6 Lenovo Integrated Webcam + 01a7 Lenovo Integrated Webcam + 01a9 Lenovo Integrated Webcam + 0200 OrbiCam + 0203 BisonCam NB Pro 1300 + 0241 BisonCam, NB Pro + 02d0 Lenovo Integrated Webcam [R5U877] + 03d0 Lenovo Integrated Webcam [R5U877] +59e3 Nonolith Labs +5a57 Zinwell + 0260 RT2570 + 0280 802.11a/b/g/n USB Wireless LAN Card + 0282 802.11b/g/n USB Wireless LAN Card + 0283 802.11b/g/n USB Wireless LAN Card + 0284 802.11a/b/g/n USB Wireless LAN Card + 0290 ZW-N290 802.11n [Realtek RTL8192SU] + 5257 Metronic 495257 wifi 802.11ng +6000 Beholder International Ltd. + dec0 TV Wander + dec1 TV Voyage +601a Ingenic Semiconductor Ltd. + 4740 XBurst Jz4740 boot mode +6189 Sitecom + 182d USB 2.0 Ethernet + 2068 USB to serial cable (v2) +6244 LightingSoft AG + 0101 Intelligent Usb Dmx Interface SIUDI5A + 0201 Intelligent Usb Dmx Interface SIUDI5C + 0300 Intelligent Usb Dmx Interface SIUDI6 Firmware download + 0301 Intelligent Usb Dmx Interface SIUDI6C + 0302 Intelligent Usb Dmx Interface SIUDI6A + 0303 Intelligent Usb Dmx Interface SIUDI6D + 0400 Touch Sensitive Intelligent Control Keypad STICK1A + 0401 Touch Sensitive Intelligent Control Keypad STICK1A + 0410 Intelligent Usb Dmx Interface SIUDI7 Firmware Download + 0411 Intelligent Usb Dmx Interface SIUDI7A + 0420 Intelligent Usb Dmx Interface SIUDI8A Firmware Download + 0421 Intelligent Usb Dmx Interface SIUDI8A + 0430 Intelligent Usb Dmx Interface SIUDI8C Firmware Download + 0431 Intelligent Usb Dmx Interface SIUDI8C + 0440 Intelligent Usb Dmx Interface SIUDI9A Firmware Download + 0441 Intelligent Usb Dmx Interface SIUDI9A + 0450 Intelligent Usb Dmx Interface SIUDI9C Firmware Download + 0451 Intelligent Usb Dmx Interface SIUDI9C + 0460 Touch Sensitive Intelligent Control Keypad STICK2 Firmware download + 0461 Touch Sensitive Intelligent Control Keypad STICK2 + 0470 Touch Sensitive Intelligent Control Keypad STICK1B Firmware download + 0471 Touch Sensitive Intelligent Control Keypad STICK1B + 0480 Touch Sensitive Intelligent Control Keypad STICK3 Firmware download + 0481 Touch Sensitive Intelligent Control Keypad STICK3 + 0490 Intelligent Usb Dmx Interface SIUDI9D Firmware Download + 0491 Intelligent Usb Dmx Interface SIUDI9D + 0500 Touch Sensitive Intelligent Control Keypad STICK2B Firmware download + 0501 Touch Sensitive Intelligent Control Keypad STICK2B +6253 TwinHan Technology Co., Ltd + 0100 Ir reciver f. remote control +636c CoreLogic, Inc. +6472 Unknown (Sony?) + 01c8 PlayStation Portable [Mass Storage] +6547 Arkmicro Technologies Inc. + 0232 ARK3116 Serial +6615 IRTOUCHSYSTEMS Co. Ltd. + 0001 Touchscreen +6666 Prototype product Vendor ID + 0667 WiseGroup Smart Joy PSX, PS-PC Smart JoyPad + 2667 JCOP BlueZ Smartcard reader + 8802 SmartJoy Dual Plus PS2 converter + 8804 WiseGroup SuperJoy Box 5 +6677 WiseGroup, Ltd. + 8802 SmartJoy Dual Plus PS2 converter + 8811 Deluxe Dance Mat +6891 3Com + a727 3CRUSB10075 802.11bg [ZyDAS ZD1211] +695c Opera1 + 3829 Opera1 DVB-S (warm state) +6993 Yealink Network Technology Co., Ltd. + b001 VoIP Phone +6a75 Shanghai Jujo Electronics Co., Ltd +7104 CME (Central Music Co.) + 2202 UF5/UF6/UF7/UF8 MIDI Master Keyboard +726c StackFoundry LLC + 2149 EntropyKing Random Number Generator +734c TBS Technologies China + 5920 Q-Box II DVB-S2 HD + 5928 Q-Box II DVB-S2 HD +7373 Beijing STONE Technology Co. Ltd. + 5740 Intelligent TFT-LCD Module +7392 Edimax Technology Co., Ltd + 7711 EW-7711UTn nLite Wireless Adapter [Ralink RT2870] + 7717 EW-7717UN 802.11n Wireless Adapter [Ralink RT2870] + 7718 EW-7718UN 802.11n Wireless Adapter [Ralink RT2870] + 7722 EW-7722UTn 802.11n Wireless Adapter [Ralink RT307x] + 7811 EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS] +8086 Intel Corp. + 0001 AnyPoint (TM) Home Network 1.6 Mbps Wireless Adapter + 0044 CPU DRAM Controller + 0046 HD Graphics + 0100 Personal Audio Player 3000 + 0101 Personal Audio Player 3000 + 0110 Easy PC Camera + 0120 PC Camera CS120 + 0180 WiMAX Connection 2400m + 0181 WiMAX Connection 2400m + 0182 WiMAX Connection 2400m + 0186 WiMAX Connection 2400m + 0188 WiMAX Connection 2400m + 0200 AnyPoint(TM) Wireless II Network 11Mbps Adapter [Atmel AT76C503A] + 0431 Intel Pro Video PC Camera + 0510 Digital Movie Creator + 0630 Pocket PC Camera + 0780 CS780 Microphone Input + 07d3 BLOB boot loader firmware + 0dad Cherry MiniatureCard Keyboard + 1010 AnyPoint(TM) Home Network 10 Mbps Phoneline Adapter + 110a Bluetooth Controller from (Ericsson P4A) + 110b Bluetooth Controller from (Intel/CSR) + 1110 PRO/Wireless LAN Module + 1111 PRO/Wireless 2011B 802.11b Adapter [Intersil PRISM 2.5] + 1134 Hollister Mobile Monitor + 1139 In-Target Probe (ITP) + 1234 Prototype Reader/Writer + 1403 WiMAX Connection 2400m + 1405 WiMAX Connection 2400m + 1406 WiMAX Connection 2400m + 2448 82801 PCI Bridge + 3100 PRO/DSL 3220 Modem - WAN + 3101 PRO/DSL 3220 Modem + 3240 AnyPoint® 3240 Modem - WAN + 3241 AnyPoint® 3240 Modem + 8602 Miniature Card Slot + 9303 Intel 8x930Hx Hub + 9500 CE 9500 DVB-T + 9890 82930 Test Board + beef SCM Miniature Card Reader/Writer + c013 Wireless HID Station + f001 XScale PXA27x Bulverde flash + f1a5 Z-U130 [Value Solid State Drive] +8087 Intel Corp. + 0020 Integrated Rate Matching Hub + 0024 Integrated Rate Matching Hub +80ee VirtualBox + 0021 USB Tablet +8282 Keio + 3201 Retro Adapter + 3301 Retro Adapter Mouse +8341 EGO Systems, Inc. + 2000 Flashdisk +8564 Transcend Information, Inc. + 1000 JetFlash + 4000 RDF8 +8644 Intenso GmbG + 8003 Micro Line + 800b Micro Line (4GB) +8e06 CH Products, Inc. + f700 DT225 Trackball +9016 Sitecom + 182d WL-022 802.11b Adapter +9022 TeVii Technology Ltd. + d630 DVB-S S630 + d650 DVB-S2 S650 + d660 DVB-S2 S660 +9148 GeoLab, Ltd +# All of GeoLab's devices share the same ID 0004. + 0004 R3 Compatible Device +9710 MosChip Semiconductor + 7703 MCS7703 Serial Port Adapter + 7705 MCS7705 Parallel port adapter + 7715 MCS7715 Parallel and serial port adapter + 7717 MCS7717 3-port hub with serial and parallel adapter + 7720 MCS7720 Dual serial port adapter + 7730 MCS7730 10/100 Mbps Ethernet adapter + 7780 MCS7780 4Mbps Fast IrDA Adapter + 7830 MCS7830 10/100 Mbps Ethernet adapter + 7832 MCS7832 10/100 Mbps Ethernet adapter + 7840 MCS7820/MCS7840 2/4 port serial adapter +9849 Bestmedia CD Recordable GmbH & Co. KG + 0701 Platinum MyDrive HP +9999 Odeon + 0001 JAF Mobile Phone Flasher Interface +99fa Grandtec + 8988 V.cap Camera Device +9ac4 J. Westhues + 4b8f ProxMark-3 RFID Instrument +9e88 Marvell Semiconductor, Inc. + 9e8f Plug Computer Basic [SheevaPlug] +a128 AnMo Electronics Corp. / Dino-Lite (?) + 0610 Dino-Lite Digital Microscope (SN9C201 + HV7131R) + 0611 Dino-Lite Digital Microscope (SN9C201 + HV7131R) + 0612 Dino-Lite Digital Microscope (SN9C120 + HV7131R) + 0613 Dino-Lite Digital Microscope (SN9C201 + HV7131R) + 0614 Dino-Lite Digital Microscope (SN9C201 + MI1310/MT9M111) + 0615 Dino-Lite Digital Microscope (SN9C201 + MI1310/MT9M111) + 0616 Dino-Lite Digital Microscope (SN9C120 + HV7131R) + 0617 Dino-Lite Digital Microscope (SN9C201 + MI1310/MT9M111) + 0618 Dino-Lite Digital Microscope (SN9C201 + HV7131R) +a168 AnMo Electronics Corporation + 0610 Dino-Lite Digital Microscope + 0611 Dino-Lite Digital Microscope + 0613 Dino-Lite Digital Microscope + 0614 Dino-Lite Pro Digital Microscope + 0615 Dino-Lite Pro Digital Microscope + 0617 Dino-Lite Pro Digital Microscope + 0618 Dino-Lite Digital Microscope +a600 Asix + e110 OK1ZIA Davac 4.x +a727 3Com + 6893 3CRUSB20075 OfficeConnect Wireless 108Mbps 11g Adapter [Atheros AR5523] + 6895 AR5523 + 6897 AR5523 +aaaa MXT + 8815 microSD CardReader +abcd Unknown + cdee Petcam +b58e Blue Microphones + 9e84 Yeti Stereo Microphone +c216 Card Device Expert Co., LTD + 0180 MSR90 MagStripe reader +c251 Keil Software, Inc. + 2710 ULink +cace CACE Technologies Inc. + 0002 AirPCAP Classic 802.11 packet capture adapter + 0300 AirPcap NX [Atheros AR9001U-(2)NG] +cd12 SMART TECHNOLOGY INDUSTRIAL LTD. +d208 Ultimarc + 0310 Mini-PAC Arcade Control Interface +d209 Ultimarc + 0301 I-PAC Arcade Control Interface + 0501 Ultra-Stik Ultimarc Ultra-Stik Player 1 +d904 LogiLink + 0003 Laser Mouse (ID0009A) +e4e4 Xorcom Ltd. + 1130 Astribank series + 1131 Astribank series + 1132 Astribank series + 1140 Astribank series + 1141 Astribank series + 1142 Astribank series + 1150 Astribank series + 1151 Astribank series + 1152 Astribank series + 1160 Astribank 2 series + 1161 Astribank 2 series + 1162 Astribank 2 series +eb03 MakingThings + 0920 Make Controller Kit +eb1a eMPIA Technology, Inc. + 17de KWorld V-Stream XPERT DTV - DVB-T USB cold + 17df KWorld V-Stream XPERT DTV - DVB-T USB warm + 2571 M035 Compact Web Cam + 2710 SilverCrest Webcam + 2750 ECS Elitegroup G220 integrated Webcam + 2761 EeePC 701 integrated Webcam + 2776 Combined audio and video input device + 2800 Terratec Cinergy 200 + 2801 GrabBeeX+ Video Encoder + 2863 Video Grabber + 2870 Pinnacle PCTV Stick + 2881 EM2881 Video Controller + 50a3 Gadmei UTV380 TV Box + 50a6 Gadmei UTV330 TV Box + e355 KWorld DVB-T 355U Digital TV Dongle +eb2a KWorld +ef18 SMART TECHNOLOGY INDUSTRIAL LTD. +f003 Hewlett Packard + 6002 PhotoSmart C500 +f182 Leap Motion + 0003 Controller +f4ec Atten Electronics / Siglent Technologies + ee38 Digital Storage Oscilloscope +f4ed Shenzhen Siglent Co., Ltd. + ee37 SDG1010 Waveform Generator + ee3a SDG1010 Waveform Generator (TMC mode) +f766 Hama + 0001 PC-Gamepad "Greystorm" +fc08 Conrad Electronic SE + 0101 MIDI Cable UA0037 +ffee FNK Tech + 0100 Card Reader Controller RTS5101/RTS5111/RTS5116 + +# List of known device classes, subclasses and protocols + +# Syntax: +# C class class_name +# subclass subclass_name <-- single tab +# protocol protocol_name <-- two tabs + +C 00 (Defined at Interface level) +C 01 Audio + 01 Control Device + 02 Streaming + 03 MIDI Streaming +C 02 Communications + 01 Direct Line + 02 Abstract (modem) + 00 None + 01 AT-commands (v.25ter) + 02 AT-commands (PCCA101) + 03 AT-commands (PCCA101 + wakeup) + 04 AT-commands (GSM) + 05 AT-commands (3G) + 06 AT-commands (CDMA) + fe Defined by command set descriptor + ff Vendor Specific (MSFT RNDIS?) + 03 Telephone + 04 Multi-Channel + 05 CAPI Control + 06 Ethernet Networking + 07 ATM Networking + 08 Wireless Handset Control + 09 Device Management + 0a Mobile Direct Line + 0b OBEX + 0c Ethernet Emulation + 07 Ethernet Emulation (EEM) +C 03 Human Interface Device + 00 No Subclass + 00 None + 01 Keyboard + 02 Mouse + 01 Boot Interface Subclass + 00 None + 01 Keyboard + 02 Mouse +C 05 Physical Interface Device +C 06 Imaging + 01 Still Image Capture + 01 Picture Transfer Protocol (PIMA 15470) +C 07 Printer + 01 Printer + 00 Reserved/Undefined + 01 Unidirectional + 02 Bidirectional + 03 IEEE 1284.4 compatible bidirectional + ff Vendor Specific +C 08 Mass Storage + 01 RBC (typically Flash) + 00 Control/Bulk/Interrupt + 01 Control/Bulk + 50 Bulk-Only + 02 SFF-8020i, MMC-2 (ATAPI) + 03 QIC-157 + 04 Floppy (UFI) + 00 Control/Bulk/Interrupt + 01 Control/Bulk + 50 Bulk-Only + 05 SFF-8070i + 06 SCSI + 00 Control/Bulk/Interrupt + 01 Control/Bulk + 50 Bulk-Only +C 09 Hub + 00 Unused + 00 Full speed (or root) hub + 01 Single TT + 02 TT per port +C 0a CDC Data + 00 Unused + 30 I.430 ISDN BRI + 31 HDLC + 32 Transparent + 50 Q.921M + 51 Q.921 + 52 Q.921TM + 90 V.42bis + 91 Q.932 EuroISDN + 92 V.120 V.24 rate ISDN + 93 CAPI 2.0 + fd Host Based Driver + fe CDC PUF + ff Vendor specific +C 0b Chip/SmartCard +C 0d Content Security +C 0e Video + 00 Undefined + 01 Video Control + 02 Video Streaming + 03 Video Interface Collection +C 58 Xbox + 42 Controller +C dc Diagnostic + 01 Reprogrammable Diagnostics + 01 USB2 Compliance +C e0 Wireless + 01 Radio Frequency + 01 Bluetooth + 02 Ultra WideBand Radio Control + 03 RNDIS + 02 Wireless USB Wire Adapter + 01 Host Wire Adapter Control/Data Streaming + 02 Device Wire Adapter Control/Data Streaming + 03 Device Wire Adapter Isochronous Streaming +C ef Miscellaneous Device + 01 ? + 01 Microsoft ActiveSync + 02 Palm Sync + 02 ? + 01 Interface Association + 02 Wire Adapter Multifunction Peripheral + 03 ? + 01 Cable Based Association + 05 USB3 Vision +C fe Application Specific Interface + 01 Device Firmware Update + 02 IRDA Bridge + 03 Test and Measurement + 01 TMC + 02 USB488 +C ff Vendor Specific Class + ff Vendor Specific Subclass + ff Vendor Specific Protocol + +# List of Audio Class Terminal Types + +# Syntax: +# AT terminal_type terminal_type_name + +AT 0100 USB Undefined +AT 0101 USB Streaming +AT 01ff USB Vendor Specific +AT 0200 Input Undefined +AT 0201 Microphone +AT 0202 Desktop Microphone +AT 0203 Personal Microphone +AT 0204 Omni-directional Microphone +AT 0205 Microphone Array +AT 0206 Processing Microphone Array +AT 0300 Output Undefined +AT 0301 Speaker +AT 0302 Headphones +AT 0303 Head Mounted Display Audio +AT 0304 Desktop Speaker +AT 0305 Room Speaker +AT 0306 Communication Speaker +AT 0307 Low Frequency Effects Speaker +AT 0400 Bidirectional Undefined +AT 0401 Handset +AT 0402 Headset +AT 0403 Speakerphone, no echo reduction +AT 0404 Echo-suppressing speakerphone +AT 0405 Echo-canceling speakerphone +AT 0500 Telephony Undefined +AT 0501 Phone line +AT 0502 Telephone +AT 0503 Down Line Phone +AT 0600 External Undefined +AT 0601 Analog Connector +AT 0602 Digital Audio Interface +AT 0603 Line Connector +AT 0604 Legacy Audio Connector +AT 0605 SPDIF interface +AT 0606 1394 DA stream +AT 0607 1394 DV stream soundtrack +AT 0700 Embedded Undefined +AT 0701 Level Calibration Noise Source +AT 0702 Equalization Noise +AT 0703 CD Player +AT 0704 DAT +AT 0705 DCC +AT 0706 MiniDisc +AT 0707 Analog Tape +AT 0708 Phonograph +AT 0709 VCR Audio +AT 070a Video Disc Audio +AT 070b DVD Audio +AT 070c TV Tuner Audio +AT 070d Satellite Receiver Audio +AT 070e Cable Tuner Audio +AT 070f DSS Audio +AT 0710 Radio Receiver +AT 0711 Radio Transmitter +AT 0712 Multitrack Recorder +AT 0713 Synthesizer + +# List of HID Descriptor Types + +# Syntax: +# HID descriptor_type descriptor_type_name + +HID 21 HID +HID 22 Report +HID 23 Physical + +# List of HID Descriptor Item Types +# Note: 2 bits LSB encode data length following + +# Syntax: +# R item_type item_type_name + +R 04 Usage Page +R 08 Usage +R 14 Logical Minimum +R 18 Usage Minimum +R 24 Logical Maximum +R 28 Usage Maximum +R 34 Physical Minimum +R 38 Designator Index +R 44 Physical Maximum +R 48 Designator Minimum +R 54 Unit Exponent +R 58 Designator Maximum +R 64 Unit +R 74 Report Size +R 78 String Index +R 80 Input +R 84 Report ID +R 88 String Minimum +R 90 Output +R 94 Report Count +R 98 String Maximum +R a0 Collection +R a4 Push +R a8 Delimiter +R b0 Feature +R b4 Pop +R c0 End Collection + +# List of Physical Descriptor Bias Types + +# Syntax: +# BIAS item_type item_type_name + +BIAS 0 Not Applicable +BIAS 1 Right Hand +BIAS 2 Left Hand +BIAS 3 Both Hands +BIAS 4 Either Hand + +# List of Physical Descriptor Item Types + +# Syntax: +# PHY item_type item_type_name + +PHY 00 None +PHY 01 Hand +PHY 02 Eyeball +PHY 03 Eyebrow +PHY 04 Eyelid +PHY 05 Ear +PHY 06 Nose +PHY 07 Mouth +PHY 08 Upper Lip +PHY 09 Lower Lip +PHY 0a Jaw +PHY 0b Neck +PHY 0c Upper Arm +PHY 0d Elbow +PHY 0e Forearm +PHY 0f Wrist +PHY 10 Palm +PHY 11 Thumb +PHY 12 Index Finger +PHY 13 Middle Finger +PHY 14 Ring Finger +PHY 15 Little Finger +PHY 16 Head +PHY 17 Shoulder +PHY 18 Hip +PHY 19 Waist +PHY 1a Thigh +PHY 1b Knee +PHY 1c calf +PHY 1d Ankle +PHY 1e Foot +PHY 1f Heel +PHY 20 Ball of Foot +PHY 21 Big Toe +PHY 22 Second Toe +PHY 23 Third Toe +PHY 24 Fourth Toe +PHY 25 Fifth Toe +PHY 26 Brow +PHY 27 Cheek + +# List of HID Usages + +# Syntax: +# HUT hi _usage_page hid_usage_page_name +# hid_usage hid_usage_name + +HUT 00 Undefined +HUT 01 Generic Desktop Controls + 000 Undefined + 001 Pointer + 002 Mouse + 004 Joystick + 005 Gamepad + 006 Keyboard + 007 Keypad + 008 Multi-Axis Controller + 030 Direction-X + 031 Direction-Y + 032 Direction-Z + 033 Rotate-X + 034 Rotate-Y + 035 Rotate-Z + 036 Slider + 037 Dial + 038 Wheel + 039 Hat Switch + 03a Counted Buffer + 03b Byte Count + 03c Motion Wakeup + 03d Start + 03e Select + 040 Vector-X + 041 Vector-Y + 042 Vector-Z + 043 Vector-X relative Body + 044 Vector-Y relative Body + 045 Vector-Z relative Body + 046 Vector + 080 System Control + 081 System Power Down + 082 System Sleep + 083 System Wake Up + 084 System Context Menu + 085 System Main Menu + 086 System App Menu + 087 System Menu Help + 088 System Menu Exit + 089 System Menu Select + 08a System Menu Right + 08b System Menu Left + 08c System Menu Up + 08d System Menu Down + 090 Direction Pad Up + 091 Direction Pad Down + 092 Direction Pad Right + 093 Direction Pad Left +HUT 02 Simulation Controls + 000 Undefined + 001 Flight Simulation Device + 002 Automobile Simulation Device + 003 Tank Simulation Device + 004 Spaceship Simulation Device + 005 Submarine Simulation Device + 006 Sailing Simulation Device + 007 Motorcycle Simulation Device + 008 Sports Simulation Device + 009 Airplane Simualtion Device + 00a Helicopter Simulation Device + 00b Magic Carpet Simulation Device + 00c Bicycle Simulation Device + 020 Flight Control Stick + 021 Flight Stick + 022 Cyclic Control + 023 Cyclic Trim + 024 Flight Yoke + 025 Track Control + 0b0 Aileron + 0b1 Aileron Trim + 0b2 Anti-Torque Control + 0b3 Autopilot Enable + 0b4 Chaff Release + 0b5 Collective Control + 0b6 Dive Break + 0b7 Electronic Countermeasures + 0b8 Elevator + 0b9 Elevator Trim + 0ba Rudder + 0bb Throttle + 0bc Flight COmmunications + 0bd Flare Release + 0be Landing Gear + 0bf Toe Break + 0c0 Trigger + 0c1 Weapon Arm + 0c2 Weapons Select + 0c3 Wing Flaps + 0c4 Accelerator + 0c5 Brake + 0c6 Clutch + 0c7 Shifter + 0c8 Steering + 0c9 Turret Direction + 0ca Barrel Elevation + 0cb Drive Plane + 0cc Ballast + 0cd Bicylce Crank + 0ce Handle Bars + 0cf Front Brake + 0d0 Rear Brake +HUT 03 VR Controls + 000 Unidentified + 001 Belt + 002 Body Suit + 003 Flexor + 004 Glove + 005 Head Tracker + 006 Head Mounted Display + 007 Hand Tracker + 008 Oculometer + 009 Vest + 00a Animatronic Device + 020 Stereo Enable + 021 Display Enable +HUT 04 Sport Controls + 000 Unidentified + 001 Baseball Bat + 002 Golf Club + 003 Rowing Machine + 004 Treadmill + 030 Oar + 031 Slope + 032 Rate + 033 Stick Speed + 034 Stick Face Angle + 035 Stick Heel/Toe + 036 Stick Follow Through + 038 Stick Type + 039 Stick Height + 047 Stick Temp + 050 Putter + 051 1 Iron + 052 2 Iron + 053 3 Iron + 054 4 Iron + 055 5 Iron + 056 6 Iron + 057 7 Iron + 058 8 Iron + 059 9 Iron + 05a 10 Iron + 05b 11 Iron + 05c Sand Wedge + 05d Loft Wedge + 05e Power Wedge + 05f 1 Wood + 060 3 Wood + 061 5 Wood + 062 7 Wood + 063 9 Wood +HUT 05 Game Controls + 000 Undefined + 001 3D Game Controller + 002 Pinball Device + 003 Gun Device + 020 Point Of View + 021 Turn Right/Left + 022 Pitch Right/Left + 023 Roll Forward/Backward + 024 Move Right/Left + 025 Move Forward/Backward + 026 Move Up/Down + 027 Lean Right/Left + 028 Lean Forward/Backward + 029 Height of POV + 02a Flipper + 02b Secondary Flipper + 02c Bump + 02d New Game + 02e Shoot Ball + 02f Player + 030 Gun Bolt + 031 Gun Clip + 032 Gun Selector + 033 Gun Single Shot + 034 Gun Burst + 035 Gun Automatic + 036 Gun Safety + 037 Gamepad Fire/Jump + 038 Gamepad Fun + 039 Gamepad Trigger +HUT 07 Keyboard + 000 No Event + 001 Keyboard ErrorRollOver + 002 Keyboard POSTfail + 003 Keyboard Error Undefined + 004 A + 005 B + 006 C + 007 D + 008 E + 009 F + 00a G + 00b H + 00c I + 00d J + 00e K + 00f L + 010 M + 011 N + 012 O + 013 P + 014 Q + 015 R + 016 S + 017 T + 018 U + 019 V + 01a W + 01b X + 01c Y + 01d Z + 01e 1 and ! (One and Exclamation) + 01f 2 and @ (2 and at) + 020 3 and # (3 and Hash) + 021 4 and $ (4 and Dollar Sign) + 022 5 and % (5 and Percent Sign) + 023 6 and ^ (6 and circumflex) + 024 7 and & (Seven and Ampersand) + 025 8 and * (Eight and asterisk) + 026 9 and ( (Nine and Parenthesis Left) + 027 0 and ) (Zero and Parenthesis Right) + 028 Return (Enter) + 029 Escape + 02a Delete (Backspace) + 02b Tab + 02c Space Bar + 02d - and _ (Minus and underscore) + 02e = and + (Equal and Plus) + 02f [ and { (Bracket and Braces Left) + 030 ] and } (Bracket and Braces Right) + 031 \ and | (Backslash and Bar) + 032 # and ~ (Hash and Tilde, Non-US Keyboard near right shift) + 033 ; and : (Semicolon and Colon) + 034 ´ and " (Accent Acute and Double Quotes) + 035 ` and ~ (Accent Grace and Tilde) + 036 , and < (Comma and Less) + 037 . and > (Period and Greater) + 038 / and ? (Slash and Question Mark) + 039 Caps Lock + 03a F1 + 03b F2 + 03c F3 + 03d F4 + 03e F5 + 03f F6 + 040 F7 + 041 F8 + 042 F9 + 043 F10 + 044 F11 + 045 F12 + 046 Print Screen + 047 Scroll Lock + 048 Pause + 049 Insert + 04a Home + 04b Page Up + 04c Delete Forward (without Changing Position) + 04d End + 04e Page Down + 04f Right Arrow + 050 Left Arrow + 051 Down Arrow + 052 Up Arrow + 053 Num Lock and Clear + 054 Keypad / (Division Sign) + 055 Keypad * (Multiplication Sign) + 056 Keypad - (Subtraction Sign) + 057 Keypad + (Addition Sign) + 058 Keypad Enter + 059 Keypad 1 and END + 05a Keypad 2 and Down Arrow + 05b Keypad 3 and Page Down + 05c Keypad 4 and Left Arrow + 05d Keypad 5 (Tactilei Raised) + 05f Keypad 6 and Right Arrow + 060 Keypad 7 and Home + 061 Keypad 8 and Up Arrow + 062 Keypad 8 and Page Up + 063 Keypad . (decimal delimiter) and Delete + 064 \ and | (Backslash and Bar, UK and Non-US Keyboard near left shift) + 065 Keyboard Application (Windows Key for Win95 or Compose) + 066 Power (not a key) + 067 Keypad = (Equal Sign) + 068 F13 + 069 F14 + 06a F15 + 06b F16 + 06c F17 + 06d F18 + 06e F19 + 06f F20 + 070 F21 + 071 F22 + 072 F23 + 073 F24 + 074 Execute + 075 Help + 076 Menu + 077 Select + 078 Stop + 079 Again + 07a Undo + 07b Cut + 07c Copy + 07d Paste + 07e Find + 07f Mute + 080 Volume Up + 081 Volume Down + 082 Locking Caps Lock + 083 Locking Num Lock + 084 Locking Scroll Lock + 085 Keypad Comma + 086 Keypad Equal Sign (AS/400) + 087 International 1 (PC98) + 088 International 2 (PC98) + 089 International 3 (PC98) + 08a International 4 (PC98) + 08b International 5 (PC98) + 08c International 6 (PC98) + 08d International 7 (Toggle Single/Double Byte Mode) + 08e International 8 + 08f International 9 + 090 LANG 1 (Hangul/English Toggle, Korea) + 091 LANG 2 (Hanja Conversion, Korea) + 092 LANG 3 (Katakana, Japan) + 093 LANG 4 (Hiragana, Japan) + 094 LANG 5 (Zenkaku/Hankaku, Japan) + 095 LANG 6 + 096 LANG 7 + 097 LANG 8 + 098 LANG 9 + 099 Alternate Erase + 09a SysReq/Attention + 09b Cancel + 09c Clear + 09d Prior + 09e Return + 09f Separator + 0a0 Out + 0a1 Open + 0a2 Clear/Again + 0a3 CrSel/Props + 0a4 ExSel + 0e0 Control Left + 0e1 Shift Left + 0e2 Alt Left + 0e3 GUI Left + 0e4 Control Right + 0e5 Shift Right + 0e6 Alt Rigth + 0e7 GUI Right +HUT 08 LEDs + 000 Undefined + 001 NumLock + 002 CapsLock + 003 Scroll Lock + 004 Compose + 005 Kana + 006 Power + 007 Shift + 008 Do not disturb + 009 Mute + 00a Tone Enabke + 00b High Cut Filter + 00c Low Cut Filter + 00d Equalizer Enable + 00e Sound Field ON + 00f Surround On + 010 Repeat + 011 Stereo + 012 Sampling Rate Detect + 013 Spinning + 014 CAV + 015 CLV + 016 Recording Format Detect + 017 Off-Hook + 018 Ring + 019 Message Waiting + 01a Data Mode + 01b Battery Operation + 01c Battery OK + 01d Battery Low + 01e Speaker + 01f Head Set + 020 Hold + 021 Microphone + 022 Coverage + 023 Night Mode + 024 Send Calls + 025 Call Pickup + 026 Conference + 027 Stand-by + 028 Camera On + 029 Camera Off + 02a On-Line + 02b Off-Line + 02c Busy + 02d Ready + 02e Paper-Out + 02f Paper-Jam + 030 Remote + 031 Forward + 032 Reverse + 033 Stop + 034 Rewind + 035 Fast Forward + 036 Play + 037 Pause + 038 Record + 039 Error + 03a Usage Selected Indicator + 03b Usage In Use Indicator + 03c Usage Multi Indicator + 03d Indicator On + 03e Indicator Flash + 03f Indicator Slow Blink + 040 Indicator Fast Blink + 041 Indicator Off + 042 Flash On Time + 043 Slow Blink On Time + 044 Slow Blink Off Time + 045 Fast Blink On Time + 046 Fast Blink Off Time + 047 Usage Color Indicator + 048 Indicator Red + 049 Indicator Green + 04a Indicator Amber + 04b Generic Indicator + 04c System Suspend + 04d External Power Connected +HUT 09 Buttons + 000 No Button Pressed + 001 Button 1 (Primary) + 002 Button 2 (Secondary) + 003 Button 3 (Tertiary) + 004 Button 4 + 005 Button 5 +HUT 0a Ordinal + 001 Instance 1 + 002 Instance 2 + 003 Instance 3 +HUT 0b Telephony + 000 Unassigned + 001 Phone + 002 Answering Machine + 003 Message Controls + 004 Handset + 005 Headset + 006 Telephony Key Pad + 007 Programmable Button + 020 Hook Switch + 021 Flash + 022 Feature + 023 Hold + 024 Redial + 025 Transfer + 026 Drop + 027 Park + 028 Forward Calls + 029 Alternate Function + 02a Line + 02b Speaker Phone + 02c Conference + 02d Ring Enable + 02e Ring Select + 02f Phone Mute + 030 Caller ID + 050 Speed Dial + 051 Store Number + 052 Recall Number + 053 Phone Directory + 070 Voice Mail + 071 Screen Calls + 072 Do Not Disturb + 073 Message + 074 Answer On/Offf + 090 Inside Dial Tone + 091 Outside Dial Tone + 092 Inside Ring Tone + 093 Outside Ring Tone + 094 Priority Ring Tone + 095 Inside Ringback + 096 Priority Ringback + 097 Line Busy Tone + 098 Recorder Tone + 099 Call Waiting Tone + 09a Confirmation Tone 1 + 09b Confirmation Tone 2 + 09c Tones Off + 09d Outside Ringback + 0b0 Key 1 + 0b1 Key 2 + 0b3 Key 3 + 0b4 Key 4 + 0b5 Key 5 + 0b6 Key 6 + 0b7 Key 7 + 0b8 Key 8 + 0b9 Key 9 + 0ba Key Star + 0bb Key Pound + 0bc Key A + 0bd Key B + 0be Key C + 0bf Key D +HUT 0c Consumer + 000 Unassigned + 001 Consumer Control + 002 Numeric Key Pad + 003 Programmable Buttons + 020 +10 + 021 +100 + 022 AM/PM + 030 Power + 031 Reset + 032 Sleep + 033 Sleep After + 034 Sleep Mode + 035 Illumination + 036 Function Buttons + 040 Menu + 041 Menu Pick + 042 Menu Up + 043 Menu Down + 044 Menu Left + 045 Menu Right + 046 Menu Escape + 047 Menu Value Increase + 048 Menu Value Decrease + 060 Data on Screen + 061 Closed Caption + 062 Closed Caption Select + 063 VCR/TV + 064 Broadcast Mode + 065 Snapshot + 066 Still + 080 Selection + 081 Assign Selection + 082 Mode Step + 083 Recall Last + 084 Enter Channel + 085 Order Movie + 086 Channel + 087 Media Selection + 088 Media Select Computer + 089 Media Select TV + 08a Media Select WWW + 08b Media Select DVD + 08c Media Select Telephone + 08d Media Select Program Guide + 08e Media Select Video Phone + 08f Media Select Games + 090 Media Select Messages + 091 Media Select CD + 092 Media Select VCR + 093 Media Select Tuner + 094 Quit + 095 Help + 096 Media Select Tape + 097 Media Select Cable + 098 Media Select Satellite + 099 Media Select Security + 09a Media Select Home + 09b Media Select Call + 09c Channel Increment + 09d Channel Decrement + 09e Media Select SAP + 0a0 VCR Plus + 0a1 Once + 0a2 Daily + 0a3 Weekly + 0a4 Monthly + 0b0 Play + 0b1 Pause + 0b2 Record + 0b3 Fast Forward + 0b4 Rewind + 0b5 Scan Next Track + 0b6 Scan Previous Track + 0b7 Stop + 0b8 Eject + 0b9 Random Play + 0ba Select Disc + 0bb Enter Disc + 0bc Repeat + 0bd Tracking + 0be Track Normal + 0bf Slow Tracking + 0c0 Frame Forward + 0c1 Frame Back + 0c2 Mark + 0c3 Clear Mark + 0c4 Repeat from Mark + 0c5 Return to Mark + 0c6 Search Mark Forward + 0c7 Search Mark Backward + 0c8 Counter Reset + 0c9 Show Counter + 0ca Tracking Increment + 0cb Tracking Decrement + 0cc Stop/Eject + 0cd Play/Pause + 0ce Play/Skip + 0e0 Volume + 0e1 Balance + 0e2 Mute + 0e3 Bass + 0e4 Treble + 0e5 Bass Boost + 0e6 Surround Mode + 0e7 Loudness + 0e8 MPX + 0e9 Volume Increment + 0ea Volume Decrement + 0f0 Speed Select + 0f1 Playback Speed + 0f2 Standard Play + 0f3 Long Play + 0f4 Extended Play + 0f5 Slow + 100 Fan Enable + 101 Fan Speed + 102 Light Enable + 103 Light Illumination Level + 104 Climate Control Enable + 105 Room Temperature + 106 Security Enable + 107 Fire Alarm + 108 Police Alarm + 150 Balance Right + 151 Balance Left + 152 Bass Increment + 153 Bass Decrement + 154 Treble Increment + 155 Treble Decrement + 160 Speaker System + 161 Channel Left + 162 Channel Right + 163 Channel Center + 164 Channel Front + 165 Channel Center Front + 166 Channel Side + 167 Channel Surround + 168 Channel Low Frequency Enhancement + 169 Channel Top + 16a Channel Unknown + 170 Sub-Channel + 171 Sub-Channel Increment + 172 Sub-Channel Decrement + 173 Alternative Audio Increment + 174 Alternative Audio Decrement + 180 Application Launch Buttons + 181 AL Launch Button Configuration Tool + 182 AL Launch Button Configuration + 183 AL Consumer Control Configuration + 184 AL Word Processor + 185 AL Text Editor + 186 AL Spreadsheet + 187 AL Graphics Editor + 188 AL Presentation App + 189 AL Database App + 18a AL Email Reader + 18b AL Newsreader + 18c AL Voicemail + 18d AL Contacts/Address Book + 18e AL Calendar/Schedule + 18f AL Task/Project Manager + 190 AL Log/Jounal/Timecard + 191 AL Checkbook/Finance + 192 AL Calculator + 193 AL A/V Capture/Playback + 194 AL Local Machine Browser + 195 AL LAN/Wan Browser + 196 AL Internet Browser + 197 AL Remote Networking/ISP Connect + 198 AL Network Conference + 199 AL Network Chat + 19a AL Telephony/Dialer + 19b AL Logon + 19c AL Logoff + 19d AL Logon/Logoff + 19e AL Terminal Local/Screensaver + 19f AL Control Panel + 1a0 AL Command Line Processor/Run + 1a1 AL Process/Task Manager + 1a2 AL Select Task/Application + 1a3 AL Next Task/Application + 1a4 AL Previous Task/Application + 1a5 AL Preemptive Halt Task/Application + 200 Generic GUI Application Controls + 201 AC New + 202 AC Open + 203 AC CLose + 204 AC Exit + 205 AC Maximize + 206 AC Minimize + 207 AC Save + 208 AC Print + 209 AC Properties + 21a AC Undo + 21b AC Copy + 21c AC Cut + 21d AC Paste + 21e AC Select All + 21f AC Find + 220 AC Find and Replace + 221 AC Search + 222 AC Go To + 223 AC Home + 224 AC Back + 225 AC Forward + 226 AC Stop + 227 AC Refresh + 228 AC Previous Link + 229 AC Next Link + 22b AC History + 22c AC Subscriptions + 22d AC Zoom In + 22e AC Zoom Out + 22f AC Zoom + 230 AC Full Screen View + 231 AC Normal View + 232 AC View Toggle + 233 AC Scroll Up + 234 AC Scroll Down + 235 AC Scroll + 236 AC Pan Left + 237 AC Pan Right + 238 AC Pan + 239 AC New Window + 23a AC Tile Horizontally + 23b AC Tile Vertically + 23c AC Format +HUT 0d Digitizer + 000 Undefined + 001 Digitizer + 002 Pen + 003 Light Pen + 004 Touch Screen + 005 Touch Pad + 006 White Board + 007 Coordinate Measuring Machine + 008 3D Digitizer + 009 Stereo Plotter + 00a Articulated Arm + 00b Armature + 00c Multiple Point Digitizer + 00d Free Space Wand + 020 Stylus + 021 Puck + 022 Finger + 030 Tip Pressure + 031 Barrel Pressure + 032 In Range + 033 Touch + 034 Untouch + 035 Tap + 036 Quality + 037 Data Valid + 038 Transducer Index + 039 Tablet Function Keys + 03a Program Change Keys + 03b Battery Strength + 03c Invert + 03d X Tilt + 03e Y Tilt + 03f Azimuth + 040 Altitude + 041 Twist + 042 Tip Switch + 043 Secondary Tip Switch + 044 Barrel Switch + 045 Eraser + 046 Tablet Pick + 047 Confidence + 048 Width + 049 Height + 051 Contact ID + 052 Input Mode + 053 Device Index + 054 Contact Count + 055 Maximum Contact Number +HUT 0f PID Page + 000 Undefined + 001 Physical Interface Device + 020 Normal + 021 Set Effect Report + 022 Effect Block Index + 023 Parameter Block Offset + 024 ROM Flag + 025 Effect Type + 026 ET Constant Force + 027 ET Ramp + 028 ET Custom Force Data + 030 ET Square + 031 ET Sine + 032 ET Triangle + 033 ET Sawtooth Up + 034 ET Sawtooth Down + 040 ET Spring + 041 ET Damper + 042 ET Inertia + 043 ET Friction + 050 Duration + 051 Sample Period + 052 Gain + 053 Trigger Button + 054 Trigger Repeat Interval + 055 Axes Enable + 056 Direction Enable + 057 Direction + 058 Type Specific Block Offset + 059 Block Type + 05A Set Envelope Report + 05B Attack Level + 05C Attack Time + 05D Fade Level + 05E Fade Time + 05F Set Condition Report + 060 CP Offset + 061 Positive Coefficient + 062 Negative Coefficient + 063 Positive Saturation + 064 Negative Saturation + 065 Dead Band + 066 Download Force Sample + 067 Isoch Custom Force Enable + 068 Custom Force Data Report + 069 Custom Force Data + 06A Custom Force Vendor Defined Data + 06B Set Custom Force Report + 06C Custom Force Data Offset + 06D Sample Count + 06E Set Periodic Report + 06F Offset + 070 Magnitude + 071 Phase + 072 Period + 073 Set Constant Force Report + 074 Set Ramp Force Report + 075 Ramp Start + 076 Ramp End + 077 Effect Operation Report + 078 Effect Operation + 079 Op Effect Start + 07A Op Effect Start Solo + 07B Op Effect Stop + 07C Loop Count + 07D Device Gain Report + 07E Device Gain + 07F PID Pool Report + 080 RAM Pool Size + 081 ROM Pool Size + 082 ROM Effect Block Count + 083 Simultaneous Effects Max + 084 Pool Alignment + 085 PID Pool Move Report + 086 Move Source + 087 Move Destination + 088 Move Length + 089 PID Block Load Report + 08B Block Load Status + 08C Block Load Success + 08D Block Load Full + 08E Block Load Error + 08F Block Handle + 090 PID Block Free Report + 091 Type Specific Block Handle + 092 PID State Report + 094 Effect Playing + 095 PID Device Control Report + 096 PID Device Control + 097 DC Enable Actuators + 098 DC Disable Actuators + 099 DC Stop All Effects + 09A DC Device Reset + 09B DC Device Pause + 09C DC Device Continue + 09F Device Paused + 0A0 Actuators Enabled + 0A4 Safety Switch + 0A5 Actuator Override Switch + 0A6 Actuator Power + 0A7 Start Delay + 0A8 Parameter Block Size + 0A9 Device Managed Pool + 0AA Shared Parameter Blocks + 0AB Create New Effect Report + 0AC RAM Pool Available +HUT 10 Unicode +HUT 14 Alphanumeric Display + 000 Undefined + 001 Alphanumeric Display + 020 Display Attributes Report + 021 ASCII Character Set + 022 Data Read Back + 023 Font Read Back + 024 Display Control Report + 025 Clear Display + 026 Display Enable + 027 Screen Saver Delay + 028 Screen Saver Enable + 029 Vertical Scroll + 02a Horizontal Scroll + 02b Character Report + 02c Display Data + 02d Display Status + 02e Stat Not Ready + 02f Stat Ready + 030 Err Not a loadable Character + 031 Err Font Data Cannot Be Read + 032 Cursur Position Report + 033 Row + 034 Column + 035 Rows + 036 Columns + 037 Cursor Pixel Positioning + 038 Cursor Mode + 039 Cursor Enable + 03a Cursor Blink + 03b Font Report + 03c Font Data + 03d Character Width + 03e Character Height + 03f Character Spacing Horizontal + 040 Character Spacing Vertical + 041 Unicode Character Set +HUT 80 USB Monitor + 001 Monitor Control + 002 EDID Information + 003 VDIF Information + 004 VESA Version +HUT 81 USB Monitor Enumerated Values +HUT 82 Monitor VESA Virtual Controls + 001 Degauss + 010 Brightness + 012 Contrast + 016 Red Video Gain + 018 Green Video Gain + 01a Blue Video Gain + 01c Focus + 020 Horizontal Position + 022 Horizontal Size + 024 Horizontal Pincushion + 026 Horizontal Pincushion Balance + 028 Horizontal Misconvergence + 02a Horizontal Linearity + 02c Horizontal Linearity Balance + 030 Vertical Position + 032 Vertical Size + 034 Vertical Pincushion + 036 Vertical Pincushion Balance + 038 Vertical Misconvergence + 03a Vertical Linearity + 03c Vertical Linearity Balance + 040 Parallelogram Balance (Key Distortion) + 042 Trapezoidal Distortion (Key) + 044 Tilt (Rotation) + 046 Top Corner Distortion Control + 048 Top Corner Distortion Balance + 04a Bottom Corner Distortion Control + 04c Bottom Corner Distortion Balance + 056 Horizontal Moire + 058 Vertical Moire + 05e Input Level Select + 060 Input Source Select + 06c Red Video Black Level + 06e Green Video Black Level + 070 Blue Video Black Level + 0a2 Auto Size Center + 0a4 Polarity Horizontal Sychronization + 0a6 Polarity Vertical Synchronization + 0aa Screen Orientation + 0ac Horizontal Frequency in Hz + 0ae Vertical Frequency in 0.1 Hz + 0b0 Settings + 0ca On Screen Display (OSD) + 0d4 Stereo Mode +HUT 84 Power Device Page + 000 Undefined + 001 iName + 002 Present Status + 003 Changed Status + 004 UPS + 005 Power Supply + 010 Battery System + 011 Battery System ID + 012 Battery + 013 Battery ID + 014 Charger + 015 Charger ID + 016 Power Converter + 017 Power Converter ID + 018 Outlet System + 019 Outlet System ID + 01a Input + 01b Input ID + 01c Output + 01d Output ID + 01e Flow + 01f Flow ID + 020 Outlet + 021 Outlet ID + 022 Gang + 023 Gang ID + 024 Power Summary + 025 Power Summary ID + 030 Voltage + 031 Current + 032 Frequency + 033 Apparent Power + 034 Active Power + 035 Percent Load + 036 Temperature + 037 Humidity + 038 Bad Count + 040 Config Voltage + 041 Config Current + 042 Config Frequency + 043 Config Apparent Power + 044 Config Active Power + 045 Config Percent Load + 046 Config Temperature + 047 Config Humidity + 050 Switch On Control + 051 Switch Off Control + 052 Toggle Control + 053 Low Voltage Transfer + 054 High Voltage Transfer + 055 Delay Before Reboot + 056 Delay Before Startup + 057 Delay Before Shutdown + 058 Test + 059 Module Reset + 05a Audible Alarm Control + 060 Present + 061 Good + 062 Internal Failure + 063 Voltage out of range + 064 Frequency out of range + 065 Overload + 066 Over Charged + 067 Over Temperature + 068 Shutdown Requested + 069 Shutdown Imminent + 06a Reserved + 06b Switch On/Off + 06c Switchable + 06d Used + 06e Boost + 06f Buck + 070 Initialized + 071 Tested + 072 Awaiting Power + 073 Communication Lost + 0fd iManufacturer + 0fe iProduct + 0ff iSerialNumber +HUT 85 Battery System Page + 000 Undefined + 001 SMB Battery Mode + 002 SMB Battery Status + 003 SMB Alarm Warning + 004 SMB Charger Mode + 005 SMB Charger Status + 006 SMB Charger Spec Info + 007 SMB Selector State + 008 SMB Selector Presets + 009 SMB Selector Info + 010 Optional Mfg. Function 1 + 011 Optional Mfg. Function 2 + 012 Optional Mfg. Function 3 + 013 Optional Mfg. Function 4 + 014 Optional Mfg. Function 5 + 015 Connection to SMBus + 016 Output Connection + 017 Charger Connection + 018 Battery Insertion + 019 Use Next + 01a OK to use + 01b Battery Supported + 01c SelectorRevision + 01d Charging Indicator + 028 Manufacturer Access + 029 Remaining Capacity Limit + 02a Remaining Time Limit + 02b At Rate + 02c Capacity Mode + 02d Broadcast To Charger + 02e Primary Battery + 02f Charge Controller + 040 Terminate Charge + 041 Terminate Discharge + 042 Below Remaining Capacity Limit + 043 Remaining Time Limit Expired + 044 Charging + 045 Discharging + 046 Fully Charged + 047 Fully Discharged + 048 Conditioning Flag + 049 At Rate OK + 04a SMB Error Code + 04b Need Replacement + 060 At Rate Time To Full + 061 At Rate Time To Empty + 062 Average Current + 063 Max Error + 064 Relative State Of Charge + 065 Absolute State Of Charge + 066 Remaining Capacity + 067 Full Charge Capacity + 068 Run Time To Empty + 069 Average Time To Empty + 06a Average Time To Full + 06b Cycle Count + 080 Batt. Pack Model Level + 081 Internal Charge Controller + 082 Primary Battery Support + 083 Design Capacity + 084 Specification Info + 085 Manufacturer Date + 086 Serial Number + 087 iManufacturerName + 088 iDeviceName + 089 iDeviceChemistry + 08a Manufacturer Data + 08b Rechargeable + 08c Warning Capacity Limit + 08d Capacity Granularity 1 + 08e Capacity Granularity 2 + 08f iOEMInformation + 0c0 Inhibit Charge + 0c1 Enable Polling + 0c2 Reset To Zero + 0d0 AC Present + 0d1 Battery Present + 0d2 Power Fail + 0d3 Alarm Inhibited + 0d4 Thermistor Under Range + 0d5 Thermistor Hot + 0d6 Thermistor Cold + 0d7 Thermistor Over Range + 0d8 Voltage Out Of Range + 0d9 Current Out Of Range + 0da Current Not Regulated + 0db Voltage Not Regulated + 0dc Master Mode + 0f0 Charger Selector Support + 0f1 Charger Spec + 0f2 Level 2 + 0f3 Level 3 +HUT 86 Power Pages +HUT 87 Power Pages +HUT 8c Bar Code Scanner Page (POS) +HUT 8d Scale Page (POS) +HUT 90 Camera Control Page +HUT 91 Arcade Control Page +HUT f0 Cash Device + 0f1 Cash Drawer + 0f2 Cash Drawer Number + 0f3 Cash Drawer Set + 0f4 Cash Drawer Status +HUT ff Vendor Specific + +# List of Languages + +# Syntax: +# L language_id language_name +# dialect_id dialect_name + +L 0001 Arabic + 01 Saudi Arabia + 02 Iraq + 03 Egypt + 04 Libya + 05 Algeria + 06 Morocco + 07 Tunesia + 08 Oman + 09 Yemen + 0a Syria + 0b Jordan + 0c Lebanon + 0d Kuwait + 0e U.A.E + 0f Bahrain + 10 Qatar +L 0002 Bulgarian +L 0003 Catalan +L 0004 Chinese + 01 Traditional + 02 Simplified + 03 Hongkong SAR, PRC + 04 Singapore + 05 Macau SAR +L 0005 Czech +L 0006 Danish +L 0007 German + 01 German + 02 Swiss + 03 Austrian + 04 Luxembourg + 05 Liechtenstein +L 0008 Greek +L 0009 English + 01 US + 02 UK + 03 Australian + 04 Canadian + 05 New Zealand + 06 Ireland + 07 South Africa + 08 Jamaica + 09 Carribean + 0a Belize + 0b Trinidad + 0c Zimbabwe + 0d Philippines +L 000a Spanish + 01 Castilian + 02 Mexican + 03 Modern + 04 Guatemala + 05 Costa Rica + 06 Panama + 07 Dominican Republic + 08 Venzuela + 09 Colombia + 0a Peru + 0b Argentina + 0c Ecuador + 0d Chile + 0e Uruguay + 0f Paraguay + 10 Bolivia + 11 El Salvador + 12 Honduras + 13 Nicaragua + 14 Puerto Rico +L 000b Finnish +L 000c French + 01 French + 02 Belgian + 03 Canadian + 04 Swiss + 05 Luxembourg + 06 Monaco +L 000d Hebrew +L 000e Hungarian +L 000f Idelandic +L 0010 Italian + 01 Italian + 02 Swiss +L 0011 Japanese +L 0012 Korean + 01 Korean +L 0013 Dutch + 01 Dutch + 02 Belgian +L 0014 Norwegian + 01 Bokmal + 02 Nynorsk +L 0015 Polish +L 0016 Portuguese + 01 Portuguese + 02 Brazilian +L 0017 forgotten +L 0018 Romanian +L 0019 Russian +L 001a Serbian + 01 Croatian + 02 Latin + 03 Cyrillic +L 001b Slovak +L 001c Albanian +L 001d Swedish + 01 Swedish + 02 Finland +L 001e Thai +L 001f Turkish +L 0020 Urdu + 01 Pakistan + 02 India +L 0021 Indonesian +L 0022 Ukrainian +L 0023 Belarusian +L 0024 Slovenian +L 0025 Estonian +L 0026 Latvian +L 0027 Lithuanian + 01 Lithuanian +L 0028 forgotten +L 0029 Farsi +L 002a Vietnamese +L 002b Armenian +L 002c Azeri + 01 Cyrillic + 02 Latin +L 002d Basque +L 002e forgotten +L 002f Macedonian +L 0036 Afrikaans +L 0037 Georgian +L 0038 Faeroese +L 0039 Hindi +L 003e Malay + 01 Malaysia + 02 Brunei Darassalam +L 003f Kazak +L 0041 Awahili +L 0043 Uzbek + 01 Latin + 02 Cyrillic +L 0044 Tatar +L 0045 Bengali +L 0046 Punjabi +L 0047 Gujarati +L 0048 Oriya +L 0049 Tamil +L 004a Telugu +L 004b Kannada +L 004c Malayalam +L 004d Assamese +L 004e Marathi +L 004f Sanskrit +L 0057 Konkani +L 0058 Manipuri +L 0059 Sindhi +L 0060 Kashmiri + 02 India +L 0061 Nepali + 02 India + +# HID Descriptor bCountryCode +# HID Specification 1.11 (2001-06-27) page 23 +# +# Syntax: +# HCC country_code keymap_type + +HCC 00 Not supported +HCC 01 Arabic +HCC 02 Belgian +HCC 03 Canadian-Bilingual +HCC 04 Canadian-French +HCC 05 Czech Republic +HCC 06 Danish +HCC 07 Finnish +HCC 08 French +HCC 09 German +HCC 10 Greek +HCC 11 Hebrew +HCC 12 Hungary +HCC 13 International (ISO) +HCC 14 Italian +HCC 15 Japan (Katakana) +HCC 16 Korean +HCC 17 Latin American +HCC 18 Netherlands/Dutch +HCC 19 Norwegian +HCC 20 Persian (Farsi) +HCC 21 Poland +HCC 22 Portuguese +HCC 23 Russia +HCC 24 Slovakia +HCC 25 Spanish +HCC 26 Swedish +HCC 27 Swiss/French +HCC 28 Swiss/German +HCC 29 Switzerland +HCC 30 Taiwan +HCC 31 Turkish-Q +HCC 32 UK +HCC 33 US +HCC 34 Yugoslavia +HCC 35 Turkish-F + +# List of Video Class Terminal Types + +# Syntax: +# VT terminal_type terminal_type_name + +VT 0100 USB Vendor Specific +VT 0101 USB Streaming +VT 0200 Input Vendor Specific +VT 0201 Camera Sensor +VT 0202 Sequential Media +VT 0300 Output Vendor Specific +VT 0301 Generic Display +VT 0302 Sequential Media +VT 0400 External Vendor Specific +VT 0401 Composite Video +VT 0402 S-Video +VT 0403 Component Video diff --git a/man/.dir-locals.el b/man/.dir-locals.el new file mode 100644 index 00000000..c252bd37 --- /dev/null +++ b/man/.dir-locals.el @@ -0,0 +1,14 @@ +; special .c mode with reduced indentation for man pages +((c-mode . ((fill-column . 80) + (c-basic-offset . 2) + (eval . (c-set-offset 'substatement-open 0)) + (eval . (c-set-offset 'statement-case-open 0)) + (eval . (c-set-offset 'case-label 0)) + (eval . (c-set-offset 'arglist-intro '++)) + (eval . (c-set-offset 'arglist-close 0)))) + (nxml-mode . ((nxml-child-indent . 2) + (fill-column . 109))) + (meson-mode . ((meson-indent-basic . 8))) + (nil . ((indent-tabs-mode . nil) + (tab-width . 8) + (fill-column . 79)))) diff --git a/man/50-xdg-data-dirs.sh b/man/50-xdg-data-dirs.sh new file mode 100755 index 00000000..89e9fbb5 --- /dev/null +++ b/man/50-xdg-data-dirs.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# set the default value +XDG_DATA_DIRS="${XDG_DATA_DIRS:-/usr/local/share/:/usr/share}" + +# add a directory if it exists +if [[ -d /opt/foo/share ]]; then + XDG_DATA_DIRS=/opt/foo/share:${XDG_DATA_DIRS} +fi + +# write our output +echo XDG_DATA_DIRS=$XDG_DATA_DIRS diff --git a/man/90-rearrange-path.py b/man/90-rearrange-path.py new file mode 100755 index 00000000..7537d5e9 --- /dev/null +++ b/man/90-rearrange-path.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +""" + +Proof-of-concept systemd environment generator that makes sure that bin dirs +are always after matching sbin dirs in the path. +(Changes /sbin:/bin:/foo/bar to /bin:/sbin:/foo/bar.) + +This generator shows how to override the configuration possibly created by +earlier generators. It would be easier to write in bash, but let's have it +in Python just to prove that we can, and to serve as a template for more +interesting generators. + +""" + +import os +import pathlib + +def rearrange_bin_sbin(path): + """Make sure any pair of …/bin, …/sbin directories is in this order + + >>> rearrange_bin_sbin('/bin:/sbin:/usr/sbin:/usr/bin') + '/bin:/sbin:/usr/bin:/usr/sbin' + """ + items = [pathlib.Path(p) for p in path.split(':')] + for i in range(len(items)): + if 'sbin' in items[i].parts: + ind = items[i].parts.index('sbin') + bin = pathlib.Path(*items[i].parts[:ind], 'bin', *items[i].parts[ind+1:]) + if bin in items[i+1:]: + j = i + 1 + items[i+1:].index(bin) + items[i], items[j] = items[j], items[i] + return ':'.join(p.as_posix() for p in items) + +if __name__ == '__main__': + path = os.environ['PATH'] # This should be always set. + # If it's not, we'll just crash, we is OK too. + new = rearrange_bin_sbin(path) + if new != path: + print('PATH={}'.format(new)) diff --git a/man/binfmt.d.xml b/man/binfmt.d.xml new file mode 100644 index 00000000..8caeb56a --- /dev/null +++ b/man/binfmt.d.xml @@ -0,0 +1,74 @@ + + + + + + + + binfmt.d + systemd + + + + binfmt.d + 5 + + + + binfmt.d + Configure additional binary formats for + executables at boot + + + + /etc/binfmt.d/*.conf + /run/binfmt.d/*.conf + /usr/lib/binfmt.d/*.conf + + + + Description + + At boot, + systemd-binfmt.service8 + reads configuration files from the above directories to register + in the kernel additional binary formats for executables. + + + + Configuration Format + + Each file contains a list of binfmt_misc kernel binary format rules. Consult the kernel's binfmt-misc.rst documentation + file for more information on registration of additional binary formats and how to write rules. + + Empty lines and lines beginning with ; and # are ignored. + Note that this means you may not use ; and # as delimiter in + binary format rules. + + + + + + Example + + /etc/binfmt.d/wine.conf example: + + # Start WINE on Windows executables +:DOSWin:M::MZ::/usr/bin/wine: + + + + + See Also + + systemd1, + systemd-binfmt.service8, + systemd-delta1, + wine8 + + + + diff --git a/man/bootctl.xml b/man/bootctl.xml new file mode 100644 index 00000000..c038c468 --- /dev/null +++ b/man/bootctl.xml @@ -0,0 +1,222 @@ + + + + + + + bootctl + systemd + + + + bootctl + 1 + + + + bootctl + Control the firmware and boot manager settings + + + + + bootctl + OPTIONS + COMMAND + + + + + Description + + bootctl can check the EFI boot loader status, list available boot loaders and boot loader + entries, and install, update, or remove the + systemd-boot7 boot loader on the + current system. + + + + Commands + + + + + + Shows brief information about the system firmware, the boot loader that was used to boot the + system, the boot loaders currently available in the ESP, the boot loaders listed in the firmware's list of boot + loaders and the current default boot loader entry. If no command is specified, this is the implied + default. + + + + + + Installs systemd-boot into the EFI system partition. A copy of + systemd-boot will be stored as the EFI default/fallback loader at + ESP/EFI/BOOT/BOOT*.EFI. The boot loader is then added + to the top of the firmware's boot loader list. + + + + + + Updates all installed versions of + systemd-boot7, if the + available version is newer than the version installed in the EFI system partition. This also includes the EFI + default/fallback loader at ESP/EFI/BOOT/BOOT*.EFI. The boot + loader is then added to end of the firmware's boot loader list if missing. + + + + + + Removes all installed versions of systemd-boot from the EFI system partition + and the firmware's boot loader list. + + + + + + Checks whether systemd-boot is installed in the ESP. Note that a + single ESP might host multiple boot loaders; this hence checks whether + systemd-boot is one (of possibly many) installed boot loaders — and neither + whether it is the default nor whether it is registered in any EFI variables. + + + + + + Generates a random seed and stores it in the EFI System Partition, for use by the + systemd-boot boot loader. Also, generates a random 'system token' and stores it + persistently as an EFI variable, if one has not been set before. If the boot loader finds the random + seed in the ESP and the system token in the EFI variable it will derive a random seed to pass to the + OS and a new seed to store in the ESP from the combination of both. The random seed passed to the OS + is credited to the kernel's entropy pool by the system manager during early boot, and permits + userspace to boot up with an entropy pool fully initialized very early on. Also see + systemd-boot-system-token.service8. + + See Random Seeds for further + information. + + + + VALUE + + When called without the optional argument, prints the current value of the + SystemdOptions EFI variable. When called with an argument, sets the + variable to that value. See + systemd1 + for the meaning of that variable. + + + + + + Shows all available boot loader entries implementing the Boot Loader + Specification, as well as any other entries discovered or automatically generated by the boot + loader. + + + + ID + ID + + Sets the default boot loader entry. Takes a single boot loader entry ID string as argument. The + command will set the default entry only for the next boot, the + will set it persistently for all future boots. + + + + + + + Options + The following options are understood: + + + + + Path to the EFI System Partition (ESP). If not specified, /efi/, + /boot/, and /boot/efi/ are checked in turn. It is + recommended to mount the ESP to /efi/, if possible. + + + + + Path to the Extended Boot Loader partition, as defined in the Boot Loader Specification. If not + specified, /boot/ is checked. It is recommended to mount the Extended Boot + Loader partition to /boot/, if possible. + + + + + + This option modifies the behaviour of status. Only prints the path + to the EFI System Partition (ESP) to standard output and exits. + + + + + + This option modifies the behaviour of status. Only prints the path + to the Extended Boot Loader partition if it exists, and the path to the ESP otherwise to standard + output and exit. This command is useful to determine where to place boot loader entries, as they are + preferably placed in the Extended Boot Loader partition if it exists and in the ESP otherwise. + + Boot Loader Specification Type #1 entries should generally be placed in the directory + $(bootctl -x)/loader/entries/. Existence of that directory may also be used as + indication that boot loader entry support is available on the system. Similarly, Boot Loader + Specification Type #2 entries should be placed in the directory $(bootctl + -x)/EFI/Linux/. + + Note that this option (similar to the option mentioned + above), is available independently from the boot loader used, i.e. also without + systemd-boot being installed. + + + + + Do not touch the firmware's boot loader list stored in EFI variables. + + + + + Ignore failure when the EFI System Partition cannot be found, or when EFI variables + cannot be written. Currently only applies to random seed operations. + + + + + + + + + + Exit status + On success, 0 is returned, a non-zero failure code otherwise. + + + + Environment + If $SYSTEMD_RELAX_ESP_CHECKS=1 is set the validation checks for the ESP are + relaxed, and the path specified with may refer to any kind of file system on + any kind of partition. + + Similarly, $SYSTEMD_RELAX_XBOOTLDR_CHECKS=1 turns off some validation checks for + the Extended Boot Loader partition. + + + + See Also + + systemd-boot7, + Boot Loader Specification, + Boot Loader Interface, + systemd-boot-system-token.service8 + + + diff --git a/man/bootup.xml b/man/bootup.xml new file mode 100644 index 00000000..28f14891 --- /dev/null +++ b/man/bootup.xml @@ -0,0 +1,356 @@ + + + + + + + + bootup + systemd + + + + bootup + 7 + + + + bootup + System bootup process + + + + Description + + A number of different components are involved in the boot of a Linux system. Immediately after + power-up, the system firmware will do minimal hardware initialization, and hand control over to a boot + loader (e.g. + systemd-boot7 or + GRUB) stored on a persistent storage device. This + boot loader will then invoke an OS kernel from disk (or the network). On systems using EFI or other types + of firmware, this firmware may also load the kernel directly. + + The kernel (optionally) mounts an in-memory file system, often generated by + dracut8, + which looks for the root file system. Nowadays this is usually implemented as an initramfs — a compressed + archive which is extracted when the kernel boots up into a lightweight in-memory file system based on + tmpfs, but in the past normal file systems using an in-memory block device (ramdisk) were used, and the + name "initrd" is still used to describe both concepts. It's the boot loader or the firmware that loads + both the kernel and initrd/initramfs images into memory, but the kernel which interprets it as a file + system. systemd1 may + be used to manage services in the initrd, similarly to the real system. + + After the root file system is found and mounted, the initrd hands over control to the host's system + manager (such as + systemd1) stored in + the root file system, which is then responsible for probing all remaining hardware, mounting all + necessary file systems and spawning all configured services. + + On shutdown, the system manager stops all services, unmounts + all file systems (detaching the storage technologies backing + them), and then (optionally) jumps back into the initrd code which + unmounts/detaches the root file system and the storage it resides + on. As a last step, the system is powered down. + + Additional information about the system boot process may be + found in + boot7. + + + + System Manager Bootup + + At boot, the system manager on the OS image is responsible + for initializing the required file systems, services and drivers + that are necessary for operation of the system. On + systemd1 + systems, this process is split up in various discrete steps which + are exposed as target units. (See + systemd.target5 + for detailed information about target units.) The boot-up process + is highly parallelized so that the order in which specific target + units are reached is not deterministic, but still adheres to a + limited amount of ordering structure. + + When systemd starts up the system, it will activate all + units that are dependencies of default.target + (as well as recursively all dependencies of these dependencies). + Usually, default.target is simply an alias of + graphical.target or + multi-user.target, depending on whether the + system is configured for a graphical UI or only for a text + console. To enforce minimal ordering between the units pulled in, + a number of well-known target units are available, as listed on + systemd.special7. + + The following chart is a structural overview of these + well-known units and their position in the boot-up logic. The + arrows describe which units are pulled in and ordered before which + other units. Units near the top are started before units nearer to + the bottom of the chart. + + + cryptsetup-pre.target + | +(various low-level v + API VFS mounts: (various cryptsetup devices...) + mqueue, configfs, | | + debugfs, ...) v | + | cryptsetup.target | + | (various swap | | remote-fs-pre.target + | devices...) | | | | + | | | | | v + | v local-fs-pre.target | | | (network file systems) + | swap.target | | v v | + | | v | remote-cryptsetup.target | + | | (various low-level (various mounts and | | | + | | services: udevd, fsck services...) | | remote-fs.target + | | tmpfiles, random | | | / + | | seed, sysctl, ...) v | | / + | | | local-fs.target | | / + | | | | | | / + \____|______|_______________ ______|___________/ | / + \ / | / + v | / + sysinit.target | / + | | / + ______________________/|\_____________________ | / + / | | | \ | / + | | | | | | / + v v | v | | / + (various (various | (various | |/ + timers...) paths...) | sockets...) | | + | | | | | | + v v | v | | +timers.target paths.target | sockets.target | | + | | | | v | + v \_______ | _____/ rescue.service | + \|/ | | + v v | + basic.target rescue.target | + | | + ________v____________________ | + / | \ | + | | | | + v v v | + display- (various system (various system | + manager.service services services) | + | required for | | + | graphical UIs) v v + | | multi-user.target +emergency.service | | | + | \_____________ | _____________/ + v \|/ +emergency.target v + graphical.target + + Target units that are commonly used as boot targets are + emphasized. These units are good choices as + goal targets, for example by passing them to the + systemd.unit= kernel command line option (see + systemd1) + or by symlinking default.target to them. + + + timers.target is pulled-in by + basic.target asynchronously. This allows + timers units to depend on services which become only available + later in boot. + + + + User manager startup + + The system manager starts the user@uid.service unit + for each user, which launches a separate unprivileged instance of systemd for each + user — the user manager. Similarly to the system manager, the user manager starts units which are pulled + in by default.target. The following chart is a structural overview of the well-known + user units. For non-graphical sessions, default.target is used. Whenever the user + logs into a graphical session, the login manager will start the + graphical-session.target target that is used to pull in units required for the + grahpical session. A number of targets (shown on the right side) are started when specific hardware is + available to the user. + + + (various (various (various + timers...) paths...) sockets...) (sound devices) + | | | | + v v v v + timers.target paths.target sockets.target sound.target + | | | + \______________ _|_________________/ (bluetooth devices) + \ / | + V v + basic.target bluetooth.target + | + __________/ \_______ (smartcard devices) + / \ | + | | v + | v smartcard.target + v graphical-session-pre.target + (various user services) | (printers) + | v | + | (services for the graphical sesion) v + | | printer.target + v v + default.target graphical-session.target + + + + + Bootup in the Initial RAM Disk (initrd) + The initial RAM disk implementation (initrd) can be set up + using systemd as well. In this case, boot up inside the initrd + follows the following structure. + + systemd detects that it is run within an initrd by checking + for the file /etc/initrd-release. + The default target in the initrd is + initrd.target. The bootup process begins + identical to the system manager bootup (see above) until it + reaches basic.target. From there, systemd + approaches the special target initrd.target. + + Before any file systems are mounted, it must be determined whether + the system will resume from hibernation or proceed with normal boot. + This is accomplished by systemd-hibernate-resume@.service + which must be finished before local-fs-pre.target, + so no filesystems can be mounted before the check is complete. + + When the root device becomes available, + initd-root-device.target is reached. + If the root device can be mounted at + /sysroot, the + sysroot.mount unit becomes active and + initrd-root-fs.target is reached. The service + initrd-parse-etc.service scans + /sysroot/etc/fstab for a possible + /usr mount point and additional entries + marked with the x-initrd.mount option. All + entries found are mounted below /sysroot, and + initrd-fs.target is reached. The service + initrd-cleanup.service isolates to the + initrd-switch-root.target, where cleanup + services can run. As the very last step, the + initrd-switch-root.service is activated, + which will cause the system to switch its root to + /sysroot. + + + : (beginning identical to above) + : + v + basic.target + | emergency.service + ______________________/| | + / | v + | initrd-root-device.target emergency.target + | | + | v + | sysroot.mount + | | + | v + | initrd-root-fs.target + | | + | v + v initrd-parse-etc.service + (custom initrd | + services...) v + | (sysroot-usr.mount and + | various mounts marked + | with fstab option + | x-initrd.mount...) + | | + | v + | initrd-fs.target + \______________________ | + \| + v + initrd.target + | + v + initrd-cleanup.service + isolates to + initrd-switch-root.target + | + v + ______________________/| + / v + | initrd-udevadm-cleanup-db.service + v | + (custom initrd | + services...) | + \______________________ | + \| + v + initrd-switch-root.target + | + v + initrd-switch-root.service + | + v + Transition to Host OS + + + + System Manager Shutdown + + System shutdown with systemd also consists of various target + units with some minimal ordering structure applied: + + (conflicts with (conflicts with + all system all file system + services) mounts, swaps, + | cryptsetup + | devices, ...) + | | + v v + shutdown.target umount.target + | | + \_______ ______/ + \ / + v + (various low-level + services) + | + v + final.target + | + _____________________________________/ \_________________________________ + / | | \ + | | | | + v v v v +systemd-reboot.service systemd-poweroff.service systemd-halt.service systemd-kexec.service + | | | | + v v v v + reboot.target poweroff.target halt.target kexec.target + + Commonly used system shutdown targets are emphasized. + + Note that + systemd-halt.service8, + systemd-reboot.service, systemd-poweroff.service and + systemd-kexec.service will transition the system and server manager (PID 1) into the second + phase of system shutdown (implemented in the systemd-shutdown binary), which will unmount any + remaining file systems, kill any remaining processes and release any other remaining resources, in a simple and + robust fashion, without taking any service or unit concept into account anymore. At that point, regular + applications and resources are generally terminated and released already, the second phase hence operates only as + safety net for everything that couldn't be stopped or released for some reason during the primary, unit-based + shutdown phase described above. + + + + See Also + + systemd1, + boot7, + systemd.special7, + systemd.target5, + systemd-halt.service8, + dracut8 + + + + diff --git a/man/busctl.xml b/man/busctl.xml new file mode 100644 index 00000000..2f7eb999 --- /dev/null +++ b/man/busctl.xml @@ -0,0 +1,517 @@ + + + + + + + + busctl + systemd + + + + busctl + 1 + + + + busctl + Introspect the bus + + + + + busctl + OPTIONS + COMMAND + NAME + + + + + Description + + busctl may be used to + introspect and monitor the D-Bus bus. + + + + Commands + + The following commands are understood: + + + + list + + Show all peers on the bus, by their service + names. By default, shows both unique and well-known names, but + this may be changed with the and + switches. This is the default + operation if no command is specified. + + + + status SERVICE + + Show process information and credentials of a + bus service (if one is specified by its unique or well-known + name), a process (if one is specified by its numeric PID), or + the owner of the bus (if no parameter is + specified). + + + + monitor SERVICE + + Dump messages being exchanged. If + SERVICE is specified, show messages + to or from this peer, identified by its well-known or unique + name. Otherwise, show all messages on the bus. Use + CtrlC + to terminate the dump. + + + + capture SERVICE + + Similar to monitor but + writes the output in pcap format (for details, see the Libpcap + File Format description). Make sure to redirect + standard output to a file. Tools like + wireshark1 + may be used to dissect and view the resulting + files. + + + + tree SERVICE + + Shows an object tree of one or more + services. If SERVICE is specified, + show object tree of the specified services only. Otherwise, + show all object trees of all services on the bus that acquired + at least one well-known name. + + + + introspect SERVICE OBJECT INTERFACE + + Show interfaces, methods, properties and + signals of the specified object (identified by its path) on + the specified service. If the interface argument is passed, the + output is limited to members of the specified + interface. + + + + call SERVICE OBJECT INTERFACE METHOD SIGNATURE ARGUMENT + + Invoke a method and show the response. Takes a + service name, object path, interface name and method name. If + parameters shall be passed to the method call, a signature + string is required, followed by the arguments, individually + formatted as strings. For details on the formatting used, see + below. To suppress output of the returned data, use the + option. + + + + emit OBJECT INTERFACE SIGNAL SIGNATURE ARGUMENT + + Emit a signal. Takes a object path, interface name and method name. If parameters + shall be passed, a signature string is required, followed by the arguments, individually formatted as + strings. For details on the formatting used, see below. To specify the destination of the signal, + use the option. + + + + get-property SERVICE OBJECT INTERFACE PROPERTY + + Retrieve the current value of one or more + object properties. Takes a service name, object path, + interface name and property name. Multiple properties may be + specified at once, in which case their values will be shown one + after the other, separated by newlines. The output is, by + default, in terse format. Use for a + more elaborate output format. + + + + set-property SERVICE OBJECT INTERFACE PROPERTY SIGNATURE ARGUMENT + + Set the current value of an object + property. Takes a service name, object path, interface name, + property name, property signature, followed by a list of + parameters formatted as strings. + + + + help + + Show command syntax help. + + + + + + Options + + The following options are understood: + + + + + + Connect to the bus specified by + ADDRESS instead of using suitable + defaults for either the system or user bus (see + and + options). + + + + + + When showing the list of peers, show a + column containing the names of containers they belong to. + See + systemd-machined.service8. + + + + + + + When showing the list of peers, show only + "unique" names (of the form + :number.number). + + + + + + + The opposite of — + only "well-known" names will be shown. + + + + + + When showing the list of peers, show only + peers which have actually not been activated yet, but may be + started automatically if accessed. + + + + + + + When showing messages being exchanged, show only the + subset matching MATCH. + See + sd_bus_add_match3. + + + + + + + + When used with the capture command, + specifies the maximum bus message size to capture + ("snaplen"). Defaults to 4096 bytes. + + + + + + + + When used with the tree command, shows a + flat list of object paths instead of a tree. + + + + + + + + + When used with the call command, + suppresses display of the response message payload. Note that even + if this option is specified, errors returned will still be + printed and the tool will indicate success or failure with + the process exit code. + + + + + + + + When used with the call or + get-property command, shows output in a + more verbose format. + + + + + + + + When used with the introspect call, dump the XML description received from + the D-Bus org.freedesktop.DBus.Introspectable.Introspect call instead of the + normal output. + + + + + MODE + + + When used with the call or get-property command, shows output + formatted as JSON. Expects one of short (for the shortest possible output without any + redundant whitespace or line breaks) or pretty (for a pretty version of the same, with + indentation and line breaks). Note that transformation from D-Bus marshalling to JSON is done in a loss-less + way, which means type information is embedded into the JSON object tree. + + + + + + + + Equivalent to when invoked interactively from a terminal. Otherwise + equivalent to , in particular when the output is piped to some other + program. + + + + + BOOL + + + When used with the call command, + specifies whether busctl shall wait for + completion of the method call, output the returned method + response data, and return success or failure via the process + exit code. If this is set to no, the + method call will be issued but no response is expected, the + tool terminates immediately, and thus no response can be + shown, and no success or failure is returned via the exit + code. To only suppress output of the reply message payload, + use above. Defaults to + yes. + + + + + BOOL + + + When used with the call or emit command, specifies + whether the method call should implicitly activate the + called service, should it not be running yet but is + configured to be auto-started. Defaults to + yes. + + + + + BOOL + + + When used with the call command, + specifies whether the services may enforce interactive + authorization while executing the operation, if the security + policy is configured for this. Defaults to + yes. + + + + + SECS + + + When used with the call command, + specifies the maximum time to wait for method call + completion. If no time unit is specified, assumes + seconds. The usual other units are understood, too (ms, us, + s, min, h, d, w, month, y). Note that this timeout does not + apply if is used, as the + tool does not wait for any reply message then. When not + specified or when set to 0, the default of + 25s is assumed. + + + + + BOOL + + + Controls whether credential data reported by + list or status shall + be augmented with data from + /proc. When this is turned on, the data + shown is possibly inconsistent, as the data read from + /proc might be more recent than the rest of + the credential information. Defaults to yes. + + + + + BOOL + + + Controls whether to wait for the specified AF_UNIX bus socket to appear in the + file system before connecting to it. Defaults to off. When enabled, the tool will watch the file system until + the socket is created and then connect to it. + + + + + SERVICE + + + Takes a service name. When used with the emit command, a signal is + emitted to the specified service. + + + + + + + + + + + + + + + + + Parameter Formatting + + The call and + set-property commands take a signature string + followed by a list of parameters formatted as string (for details + on D-Bus signature strings, see the Type + system chapter of the D-Bus specification). For simple + types, each parameter following the signature should simply be the + parameter's value formatted as string. Positive boolean values may + be formatted as true, yes, + on, or 1; negative boolean + values may be specified as false, + no, off, or + 0. For arrays, a numeric argument for the + number of entries followed by the entries shall be specified. For + variants, the signature of the contents shall be specified, + followed by the contents. For dictionaries and structs, the + contents of them shall be directly specified. + + For example, + s jawoll is the formatting + of a single string jawoll. + + + as 3 hello world foobar + is the formatting of a string array with three entries, + hello, world and + foobar. + + + a{sv} 3 One s Eins Two u 2 Yes b true + is the formatting of a dictionary + array that maps strings to variants, consisting of three + entries. The string One is assigned the + string Eins. The string + Two is assigned the 32-bit unsigned + integer 2. The string Yes is assigned a + positive boolean. + + Note that the call, + get-property, introspect + commands will also generate output in this format for the returned + data. Since this format is sometimes too terse to be easily + understood, the call and + get-property commands may generate a more + verbose, multi-line output when passed the + option. + + + + Examples + + + Write and Read a Property + + The following two commands first write a property and then + read it back. The property is found on the + /org/freedesktop/systemd1 object of the + org.freedesktop.systemd1 service. The name of + the property is LogLevel on the + org.freedesktop.systemd1.Manager + interface. The property contains a single string: + + # busctl set-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager LogLevel s debug +# busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager LogLevel +s "debug" + + + + + Terse and Verbose Output + + The following two commands read a property that contains + an array of strings, and first show it in terse format, followed + by verbose format: + + $ busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager Environment +as 2 "LANG=en_US.UTF-8" "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin" +$ busctl get-property --verbose org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager Environment +ARRAY "s" { + STRING "LANG=en_US.UTF-8"; + STRING "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"; +}; + + + + Invoking a Method + + The following command invokes the + StartUnit method on the + org.freedesktop.systemd1.Manager + interface of the + /org/freedesktop/systemd1 object + of the org.freedesktop.systemd1 + service, and passes it two strings + cups.service and + replace. As a result of the method + call, a single object path parameter is received and + shown: + + # busctl call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager StartUnit ss "cups.service" "replace" +o "/org/freedesktop/systemd1/job/42684" + + + + + See Also + + + dbus-daemon1, + D-Bus, + sd-bus3, + systemd1, + machinectl1, + wireshark1 + + + diff --git a/man/coredump.conf.xml b/man/coredump.conf.xml new file mode 100644 index 00000000..81cdc338 --- /dev/null +++ b/man/coredump.conf.xml @@ -0,0 +1,138 @@ + + + + + + + coredump.conf + systemd + + + + coredump.conf + 5 + + + + coredump.conf + coredump.conf.d + Core dump storage configuration files + + + + /etc/systemd/coredump.conf + /etc/systemd/coredump.conf.d/*.conf + /run/systemd/coredump.conf.d/*.conf + /usr/lib/systemd/coredump.conf.d/*.conf + + + + Description + + These files configure the behavior of + systemd-coredump8, + a handler for core dumps invoked by the kernel. Whether systemd-coredump is used + is determined by the kernel's + kernel.core_pattern sysctl8 + setting. See + systemd-coredump8 + and + core5 + pages for the details. + + + + + + Options + + All options are configured in the + [Coredump] section: + + + + + Storage= + + Controls where to store cores. One of none, + external, and journal. When + none, the core dumps may be logged (including the backtrace if + possible), but not stored permanently. When external (the + default), cores will be stored in /var/lib/systemd/coredump/. + When journal, cores will be stored in the journal and rotated + following normal journal rotation patterns. + + When cores are stored in the journal, they might be + compressed following journal compression settings, see + journald.conf5. + When cores are stored externally, they will be compressed + by default, see below. + + + + Compress= + + Controls compression for external + storage. Takes a boolean argument, which defaults to + yes. + + + + + ProcessSizeMax= + + The maximum size in bytes of a core + which will be processed. Core dumps exceeding this size + may be stored, but the backtrace will not be generated. + + + Setting Storage=none and ProcessSizeMax=0 + disables all coredump handling except for a log entry. + + + + + ExternalSizeMax= + JournalSizeMax= + + The maximum (uncompressed) size in bytes of a + core to be saved. + + + + MaxUse= + KeepFree= + + Enforce limits on the disk space taken up by + externally stored core dumps. makes + sure that old core dumps are removed as soon as the total disk + space taken up by core dumps grows beyond this limit (defaults + to 10% of the total disk size). + controls how much disk space to keep free at least (defaults + to 15% of the total disk size). Note that the disk space used + by core dumps might temporarily exceed these limits while + core dumps are processed. Note that old core dumps are also + removed based on time via + systemd-tmpfiles8. Set + either value to 0 to turn off size-based + clean-up. + + + + The defaults for all values are listed as comments in the + template /etc/systemd/coredump.conf file that + is installed by default. + + + + See Also + + systemd-journald.service8, + coredumpctl1, + systemd-tmpfiles8 + + + + diff --git a/man/coredumpctl.xml b/man/coredumpctl.xml new file mode 100644 index 00000000..4e99bc0d --- /dev/null +++ b/man/coredumpctl.xml @@ -0,0 +1,340 @@ + + + + + + + + coredumpctl + systemd + + + + coredumpctl + 1 + + + + coredumpctl + Retrieve and process saved core dumps and metadata + + + + + coredumpctl + OPTIONS + COMMAND + PID|COMM|EXE|MATCH + + + + + Description + + coredumpctl is a tool that can be used to retrieve and process core + dumps and metadata which were saved by + systemd-coredump8. + + + + + Commands + + The following commands are understood: + + + + list + + List core dumps captured in the journal + matching specified characteristics. If no command is + specified, this is the implied default. + + The output is designed to be human readable and contains list contains + a table with the following columns: + + + TIME + The timestamp of the crash, as reported by the kernel. + + + + + PID + The identifier of the process that crashed. + + + + + UID + GID + The user and group identifiers of the process that crashed. + + + + + SIGNAL + The signal that caused the process to crash, when applicable. + + + + + COREFILE + Information whether the coredump was stored, and whether + it is still accessible: none means the core was + not stored, - means that it was not available (for + example because the process was not terminated by a signal), + present means that the core file is accessible by the + current user, journal means that the core was stored + in the journal, truncated is the + same as one of the previous two, but the core was too large and was not + stored in its entirety, error means that the core file + cannot be accessed, most likely because of insufficient permissions, and + missing means that the core was stored in a file, but + this file has since been removed. + + + + EXE + The full path to the executable. For backtraces of scripts + this is the name of the interpreter. + + + + It's worth noting that different restrictions apply to + data saved in the journal and core dump files saved in + /var/lib/systemd/coredump, see overview in + systemd-coredump8. + Thus it may very well happen that a particular core dump is still listed + in the journal while its corresponding core dump file has already been + removed. + + + + info + + Show detailed information about the last core dump + or core dumps matching specified characteristics + captured in the journal. + + + + dump + + Extract the last core dump matching specified + characteristics. The core dump will be written on standard + output, unless an output file is specified with + . + + + + debug + + Invoke a debugger on the last core dump + matching specified characteristics. By default, + gdb1 + will be used. This may be changed using the + option or the $SYSTEMD_DEBUGGER environment + variable. + + + + + + + + Options + + The following options are understood: + + + + + + + + + + Do not print column headers. + + + + + + + + Show information of a single core dump only, instead of listing + all known core dumps. + + + + + + + Only print entries which are since the specified date. + + + + + + + Only print entries which are until the specified date. + + + + + + + Reverse output so that the newest entries are displayed first. + + + + + FIELD + FIELD + + Print all possible data values the specified + field takes in matching core dump entries of the + journal. + + + + FILE + FILE + + Write the core to . + + + + + DEBUGGER + + Use the given debugger for the debug + command. If not given and $SYSTEMD_DEBUGGER is unset, then + gdb1 + will be used. + + + + DIR + DIR + + Use the journal files in the specified . + + + + + + + + Suppresses informational messages about lack + of access to journal files and possible in-flight coredumps. + + + + + + + Matching + + A match can be: + + + + PID + + Process ID of the + process that dumped + core. An integer. + + + + COMM + + Name of the executable (matches + ). Must not contain slashes. + + + + + EXE + + Path to the executable (matches + ). Must contain at least one + slash. + + + + MATCH + + General journalctl match filter, must contain an equals + sign (=). See + journalctl1. + + + + + + + Exit status + On success, 0 is returned; otherwise, a non-zero failure + code is returned. Not finding any matching core dumps is treated as + failure. + + + + + Environment + + + + $SYSTEMD_DEBUGGER + Use the given debugger for the debug + command. See the option. + + + + + + Examples + + + List all the core dumps of a program named foo + + # coredumpctl list foo + + + + Invoke gdb on the last core dump + + # coredumpctl debug + + + + Show information about a process that dumped core, + matching by its PID 6654 + + # coredumpctl info 6654 + + + + Extract the last core dump of /usr/bin/bar to a file named + <filename index="false">bar.coredump</filename> + + # coredumpctl -o bar.coredump dump /usr/bin/bar + + + + + See Also + + systemd-coredump8, + coredump.conf5, + systemd-journald.service8, + gdb1 + + + + diff --git a/man/crypttab.xml b/man/crypttab.xml new file mode 100644 index 00000000..e4b1e43e --- /dev/null +++ b/man/crypttab.xml @@ -0,0 +1,470 @@ + + + + + + + + crypttab + systemd + + + + crypttab + 5 + + + + crypttab + Configuration for encrypted block devices + + + + /etc/crypttab + + + + Description + + The /etc/crypttab file describes + encrypted block devices that are set up during system boot. + + Empty lines and lines starting with the # + character are ignored. Each of the remaining lines describes one + encrypted block device. Fields are delimited by white space. + + Each line is in the formname encrypted-device password options + The first two fields are mandatory, the remaining two are + optional. + + Setting up encrypted block devices using this file supports + three encryption modes: LUKS, TrueCrypt and plain. See + cryptsetup8 + for more information about each mode. When no mode is specified in + the options field and the block device contains a LUKS signature, + it is opened as a LUKS device; otherwise, it is assumed to be in + raw dm-crypt (plain mode) format. + + The first field contains the name of the resulting encrypted + block device; the device is set up within + /dev/mapper/. + + The second field contains a path to the underlying block + device or file, or a specification of a block device via + UUID= followed by the UUID. + + The third field specifies the encryption password. If the + field is not present or the password is set to + none or -, the password has + to be manually entered during system boot. Otherwise, the field is + interpreted as an absolute path to a file containing the encryption + password. For swap encryption, /dev/urandom + or the hardware device /dev/hw_random can be + used as the password file; using /dev/random + may prevent boot completion if the system does not have enough + entropy to generate a truly random encryption key. + + The fourth field, if present, is a comma-delimited list of + options. The following options are recognized: + + + + + + + Specifies the cipher to use. See + cryptsetup8 + for possible values and the default value of this option. A + cipher with unpredictable IV values, such as + aes-cbc-essiv:sha256, is + recommended. + + + + + + Allow discard requests to be passed through the encrypted block + device. This improves performance on SSD storage but has security implications. + + + + + + + Specifies the hash to use for password + hashing. See + cryptsetup8 + for possible values and the default value of this + option. + + + + + + Use a detached (separated) metadata device or + file where the LUKS header is stored. This option is only + relevant for LUKS devices. See + cryptsetup8 + for possible values and the default value of this + option. + + + + + + Specifies the number of bytes to skip at the + start of the key file. See + cryptsetup8 + for possible values and the default value of this + option. + + + + + + Specifies the maximum number of bytes to read + from the key file. See + cryptsetup8 + for possible values and the default value of this option. This + option is ignored in plain encryption mode, as the key file + size is then given by the key size. + + + + + + Specifies the key slot to compare the + passphrase or key against. If the key slot does not match the + given passphrase or key, but another would, the setup of the + device will fail regardless. This option implies + . See + cryptsetup8 + for possible values. The default is to try all key slots in + sequential order. + + + + + + Specifies the timeout for the device on + which the key file resides and falls back to a password if + it could not be mounted. See + systemd-cryptsetup-generator8 + for key files on external devices. + + + + + + + Force LUKS mode. When this mode is used, the + following options are ignored since they are provided by the + LUKS header on the device: , + , + . + + + + + + Marks this cryptsetup device as requiring network. It will be + started after the network is available, similarly to + systemd.mount5 + units marked with . The service unit to set up this device + will be ordered between remote-fs-pre.target and + remote-cryptsetup.target, instead of + cryptsetup-pre.target and + cryptsetup.target. + + Hint: if this device is used for a mount point that is specified in + fstab5, + the option should also be used for the mount + point. Otherwise, a dependency loop might be created where the mount point + will be pulled in by local-fs.target, while the + service to configure the network is usually only started after + the local file system has been mounted. + + + + + + + This device will not be added to cryptsetup.target. + This means that it will not be automatically unlocked on boot, unless something else pulls + it in. In particular, if the device is used for a mount point, it'll be unlocked + automatically during boot, unless the mount point itself is also disabled with + . + + + + + + This device will not be a hard dependency of + cryptsetup.target. It'll still be pulled in and started, but the system + will not wait for the device to show up and be unlocked, and boot will not fail if this is + unsuccessful. Note that other units that depend on the unlocked device may still fail. In + particular, if the device is used for a mount point, the mount point itself also needs to + have the option, or the boot will fail if the device is not unlocked + successfully. + + + + + + Start offset in the backend device, in 512-byte sectors. This + option is only relevant for plain devices. + + + + + + Force plain encryption mode. + + + + + + Set up the encrypted block device in read-only + mode. + + + + + + Perform encryption using the same cpu that IO was submitted on. The default is to use + an unbound workqueue so that encryption work is automatically balanced between available CPUs. + This requires kernel 4.0 or newer. + + + + + + + Disable offloading writes to a separate thread after encryption. There are some + situations where offloading write bios from the encryption threads to a single thread degrades + performance significantly. The default is to offload write bios to the same thread because it benefits + CFQ to have writes submitted using the same context. + This requires kernel 4.0 or newer. + + + + + + + How many 512-byte sectors of the encrypted data to skip at the + beginning. This is different from the option with respect + to the sector numbers used in initialization vector (IV) calculation. Using + will shift the IV calculation by the same negative + amount. Hence, if is given, + sector n will get a sector number of 0 for the IV + calculation. Using causes sector + n to also be the first sector of the mapped device, but + with its number for IV generation being n. + + This option is only relevant for plain devices. + + + + + + + Specifies the key size in bits. See + cryptsetup8 + for possible values and the default value of this + option. + + + + + + Specifies the sector size in bytes. See + cryptsetup8 + for possible values and the default value of this + option. + + + + + + The encrypted block device will be used as a + swap device, and will be formatted accordingly after setting + up the encrypted block device, with + mkswap8. + This option implies . + + WARNING: Using the option will + destroy the contents of the named partition during every boot, + so make sure the underlying block device is specified + correctly. + + + + + + Use TrueCrypt encryption mode. When this mode + is used, the following options are ignored since they are + provided by the TrueCrypt header on the device or do not + apply: + , + , + , + , + . + + When this mode is used, the passphrase is read from the + key file given in the third field. Only the first line of this + file is read, excluding the new line character. + + Note that the TrueCrypt format uses both passphrase and + key files to derive a password for the volume. Therefore, the + passphrase and all key files need to be provided. Use + to provide the absolute path + to all key files. When using an empty passphrase in + combination with one or more key files, use + /dev/null as the password file in the third + field. + + + + + + Use the hidden TrueCrypt volume. This option + implies . + + This will map the hidden volume that is inside of the + volume provided in the second field. Please note that there is + no protection for the hidden volume if the outer volume is + mounted instead. See + cryptsetup8 + for more information on this limitation. + + + + + + Specifies the absolute path to a key file to + use for a TrueCrypt volume. This implies + and can be used more than once to + provide several key files. + + See the entry for on the + behavior of the passphrase and key files when using TrueCrypt + encryption mode. + + + + + + Use TrueCrypt in system encryption mode. This + option implies . + + + + + + Check for a VeraCrypt volume. VeraCrypt is a fork of + TrueCrypt that is mostly compatible, but uses different, stronger key + derivation algorithms that cannot be detected without this flag. + Enabling this option could substantially slow down unlocking, because + VeraCrypt's key derivation takes much longer than TrueCrypt's. This + option implies . + + + + + + Specifies the timeout for querying for a + password. If no unit is specified, seconds is used. Supported + units are s, ms, us, min, h, d. A timeout of 0 waits + indefinitely (which is the default). + + + + + + The encrypted block device will be prepared + for using it as /tmp; it will be + formatted using + mke2fs8. + This option implies . + + WARNING: Using the option will + destroy the contents of the named partition during every boot, + so make sure the underlying block device is specified + correctly. + + + + + + Specifies the maximum number of times the user + is queried for a password. The default is 3. If set to 0, the + user is queried for a password indefinitely. + + + + + + If the encryption password is read from + console, it has to be entered twice to prevent + typos. + + + + + + Specifies how long systemd should wait for a device to show up + before giving up on the entry. The argument is a time in seconds or explicitly + specified units of + s, + min, + h, + ms. + + + + + + At early boot and when the system manager configuration is + reloaded, this file is translated into native systemd units by + systemd-cryptsetup-generator8. + + + + Example + + /etc/crypttab example + Set up four encrypted block devices. One using LUKS for + normal storage, another one for usage as a swap device and two + TrueCrypt volumes. + + luks UUID=2505567a-9e27-4efe-a4d5-15ad146c258b +swap /dev/sda7 /dev/urandom swap +truecrypt /dev/sda2 /etc/container_password tcrypt +hidden /mnt/tc_hidden /dev/null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile +external /dev/sda3 keyfile:LABEL=keydev keyfile-timeout=10s + + + + + See Also + + systemd1, + systemd-cryptsetup@.service8, + systemd-cryptsetup-generator8, + fstab5, + cryptsetup8, + mkswap8, + mke2fs8 + + + + diff --git a/man/custom-entities.ent.in b/man/custom-entities.ent.in new file mode 100644 index 00000000..85805777 --- /dev/null +++ b/man/custom-entities.ent.in @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/man/custom-html.xsl b/man/custom-html.xsl new file mode 100644 index 00000000..fccaf51f --- /dev/null +++ b/man/custom-html.xsl @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + .html# + + + + + + + + + + http://man7.org/linux/man-pages/man + + / + + . + + .html + + + + + + + + + http://linux.die.net/man/ + + / + + + + + + + + + + https://git.zx2c4.com/WireGuard/about/src/tools/ + + . + + + + + + + + + + https://www.mankier.com/ + + / + + + + + + + + + + https://www.archlinux.org/ + + / + + . + + .html + + + + + + + + + https://www.freebsd.org/cgi/man.cgi? + + ( + + ) + + + + + + + + + http://dbus.freedesktop.org/doc/ + + . + + .html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ¶ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + + index.html + + Index + · + + + systemd.directives.html + + Directives + + + + systemd + + +
+
+ + + " + + " + + + + + +
diff --git a/man/custom-man.xsl b/man/custom-man.xsl new file mode 100644 index 00000000..d9af519d --- /dev/null +++ b/man/custom-man.xsl @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + .TH " + + + + + + " " + + " "" "systemd + + " " + + " + + + + + + + + " + + " + + + diff --git a/man/daemon.xml b/man/daemon.xml new file mode 100644 index 00000000..52b38836 --- /dev/null +++ b/man/daemon.xml @@ -0,0 +1,741 @@ + + + + + + + + daemon + systemd + + + + daemon + 7 + + + + daemon + Writing and packaging system daemons + + + + Description + + A daemon is a service process that runs in the background + and supervises the system or provides functionality to other + processes. Traditionally, daemons are implemented following a + scheme originating in SysV Unix. Modern daemons should follow a + simpler yet more powerful scheme (here called "new-style" + daemons), as implemented by + systemd1. + This manual page covers both schemes, and in particular includes + recommendations for daemons that shall be included in the systemd + init system. + + + SysV Daemons + + When a traditional SysV daemon starts, it should execute + the following steps as part of the initialization. Note that + these steps are unnecessary for new-style daemons (see below), + and should only be implemented if compatibility with SysV is + essential. + + + Close all open file descriptors except + standard input, output, and error (i.e. the first three file + descriptors 0, 1, 2). This ensures that no accidentally passed + file descriptor stays around in the daemon process. On Linux, + this is best implemented by iterating through + /proc/self/fd, with a fallback of + iterating from file descriptor 3 to the value returned by + getrlimit() for + RLIMIT_NOFILE. + + Reset all signal handlers to their default. + This is best done by iterating through the available signals + up to the limit of _NSIG and resetting + them to SIG_DFL. + + Reset the signal mask + using + sigprocmask(). + + Sanitize the environment block, removing or + resetting environment variables that might negatively impact + daemon runtime. + + Call fork(), to create a + background process. + + In the child, call + setsid() to detach from any terminal and + create an independent session. + + In the child, call fork() again, to ensure that the daemon can + never re-acquire a terminal again. (This relevant if the program — and all its dependencies — does + not carefully specify `O_NOCTTY` on each and every single `open()` call that might potentially open a + TTY device node.) + + Call exit() in the first + child, so that only the second child (the actual daemon + process) stays around. This ensures that the daemon process is + re-parented to init/PID 1, as all daemons should + be. + + In the daemon process, connect + /dev/null to standard input, output, and + error. + + In the daemon process, reset the umask to 0, + so that the file modes passed to open(), + mkdir() and suchlike directly control the + access mode of the created files and + directories. + + In the daemon process, change the current + directory to the root directory (/), in order to avoid that + the daemon involuntarily blocks mount points from being + unmounted. + + In the daemon process, write the daemon PID + (as returned by getpid()) to a PID file, + for example /run/foobar.pid (for a + hypothetical daemon "foobar") to ensure that the daemon cannot + be started more than once. This must be implemented in + race-free fashion so that the PID file is only updated when it + is verified at the same time that the PID previously stored in + the PID file no longer exists or belongs to a foreign + process. + + In the daemon process, drop privileges, if + possible and applicable. + + From the daemon process, notify the original + process started that initialization is complete. This can be + implemented via an unnamed pipe or similar communication + channel that is created before the first + fork() and hence available in both the + original and the daemon process. + + Call exit() in the + original process. The process that invoked the daemon must be + able to rely on that this exit() happens + after initialization is complete and all external + communication channels are established and + accessible. + + + The BSD daemon() function should not + be used, as it implements only a subset of these steps. + + A daemon that needs to provide compatibility with SysV + systems should implement the scheme pointed out above. However, + it is recommended to make this behavior optional and + configurable via a command line argument to ease debugging as + well as to simplify integration into systems using + systemd. + + + + New-Style Daemons + + Modern services for Linux should be implemented as + new-style daemons. This makes it easier to supervise and control + them at runtime and simplifies their implementation. + + For developing a new-style daemon, none of the + initialization steps recommended for SysV daemons need to be + implemented. New-style init systems such as systemd make all of + them redundant. Moreover, since some of these steps interfere + with process monitoring, file descriptor passing and other + functionality of the init system, it is recommended not to + execute them when run as new-style service. + + Note that new-style init systems guarantee execution of daemon processes in a clean process context: it is + guaranteed that the environment block is sanitized, that the signal handlers and mask is reset and that no + left-over file descriptors are passed. Daemons will be executed in their own session, with standard input + connected to /dev/null and standard output/error connected to the + systemd-journald.service8 + logging service, unless otherwise configured. The umask is reset. + + + It is recommended for new-style daemons to implement the + following: + + + If SIGTERM is received, + shut down the daemon and exit cleanly. + + If SIGHUP is received, + reload the configuration files, if this + applies. + + Provide a correct exit code from the main + daemon process, as this is used by the init system to detect + service errors and problems. It is recommended to follow the + exit code scheme as defined in the LSB + recommendations for SysV init + scripts. + + If possible and applicable, expose the + daemon's control interface via the D-Bus IPC system and grab a + bus name as last step of initialization. + + For integration in systemd, provide a + .service unit file that carries + information about starting, stopping and otherwise maintaining + the daemon. See + systemd.service5 + for details. + + As much as possible, rely on the init system's + functionality to limit the access of the daemon to files, + services and other resources, i.e. in the case of systemd, + rely on systemd's resource limit control instead of + implementing your own, rely on systemd's privilege dropping + code instead of implementing it in the daemon, and similar. + See + systemd.exec5 + for the available controls. + + If D-Bus is used, make your daemon + bus-activatable by supplying a D-Bus service activation + configuration file. This has multiple advantages: your daemon + may be started lazily on-demand; it may be started in parallel + to other daemons requiring it — which maximizes + parallelization and boot-up speed; your daemon can be + restarted on failure without losing any bus requests, as the + bus queues requests for activatable services. See below for + details. + + If your daemon provides services to other + local processes or remote clients via a socket, it should be + made socket-activatable following the scheme pointed out + below. Like D-Bus activation, this enables on-demand starting + of services as well as it allows improved parallelization of + service start-up. Also, for state-less protocols (such as + syslog, DNS), a daemon implementing socket-based activation + can be restarted without losing a single request. See below + for details. + + If applicable, a daemon should notify the init + system about startup completion or status updates via the + sd_notify3 + interface. + + Instead of using the + syslog() call to log directly to the + system syslog service, a new-style daemon may choose to simply + log to standard error via fprintf(), + which is then forwarded to syslog by the init system. If log + levels are necessary, these can be encoded by prefixing + individual log lines with strings like + <4> (for log level 4 "WARNING" in the + syslog priority scheme), following a similar style as the + Linux kernel's printk() level system. For + details, see + sd-daemon3 + and + systemd.exec5. + + As new-style daemons are invoked without a controlling TTY (but as their own session + leaders) care should be taken to always specify `O_NOCTTY` on `open()` calls that possibly reference + a TTY device node, so that no controlling TTY is accidentally acquired. + + + + These recommendations are similar but not identical to the + Apple + MacOS X Daemon Requirements. + + + + + Activation + + New-style init systems provide multiple additional + mechanisms to activate services, as detailed below. It is common + that services are configured to be activated via more than one + mechanism at the same time. An example for systemd: + bluetoothd.service might get activated either + when Bluetooth hardware is plugged in, or when an application + accesses its programming interfaces via D-Bus. Or, a print server + daemon might get activated when traffic arrives at an IPP port, or + when a printer is plugged in, or when a file is queued in the + printer spool directory. Even for services that are intended to be + started on system bootup unconditionally, it is a good idea to + implement some of the various activation schemes outlined below, + in order to maximize parallelization. If a daemon implements a + D-Bus service or listening socket, implementing the full bus and + socket activation scheme allows starting of the daemon with its + clients in parallel (which speeds up boot-up), since all its + communication channels are established already, and no request is + lost because client requests will be queued by the bus system (in + case of D-Bus) or the kernel (in case of sockets) until the + activation is completed. + + + Activation on Boot + + Old-style daemons are usually activated exclusively on + boot (and manually by the administrator) via SysV init scripts, + as detailed in the LSB + Linux Standard Base Core Specification. This method of + activation is supported ubiquitously on Linux init systems, both + old-style and new-style systems. Among other issues, SysV init + scripts have the disadvantage of involving shell scripts in the + boot process. New-style init systems generally employ updated + versions of activation, both during boot-up and during runtime + and using more minimal service description files. + + In systemd, if the developer or administrator wants to + make sure that a service or other unit is activated + automatically on boot, it is recommended to place a symlink to + the unit file in the .wants/ directory of + either multi-user.target or + graphical.target, which are normally used + as boot targets at system startup. See + systemd.unit5 + for details about the .wants/ directories, + and + systemd.special7 + for details about the two boot targets. + + + + + Socket-Based Activation + + In order to maximize the possible parallelization and + robustness and simplify configuration and development, it is + recommended for all new-style daemons that communicate via + listening sockets to employ socket-based activation. In a + socket-based activation scheme, the creation and binding of the + listening socket as primary communication channel of daemons to + local (and sometimes remote) clients is moved out of the daemon + code and into the init system. Based on per-daemon + configuration, the init system installs the sockets and then + hands them off to the spawned process as soon as the respective + daemon is to be started. Optionally, activation of the service + can be delayed until the first inbound traffic arrives at the + socket to implement on-demand activation of daemons. However, + the primary advantage of this scheme is that all providers and + all consumers of the sockets can be started in parallel as soon + as all sockets are established. In addition to that, daemons can + be restarted with losing only a minimal number of client + transactions, or even any client request at all (the latter is + particularly true for state-less protocols, such as DNS or + syslog), because the socket stays bound and accessible during + the restart, and all requests are queued while the daemon cannot + process them. + + New-style daemons which support socket activation must be + able to receive their sockets from the init system instead of + creating and binding them themselves. For details about the + programming interfaces for this scheme provided by systemd, see + sd_listen_fds3 + and + sd-daemon3. + For details about porting existing daemons to socket-based + activation, see below. With minimal effort, it is possible to + implement socket-based activation in addition to traditional + internal socket creation in the same codebase in order to + support both new-style and old-style init systems from the same + daemon binary. + + systemd implements socket-based activation via + .socket units, which are described in + systemd.socket5. + When configuring socket units for socket-based activation, it is + essential that all listening sockets are pulled in by the + special target unit sockets.target. It is + recommended to place a + WantedBy=sockets.target directive in the + [Install] section to automatically add such a + dependency on installation of a socket unit. Unless + DefaultDependencies=no is set, the necessary + ordering dependencies are implicitly created for all socket + units. For more information about + sockets.target, see + systemd.special7. + It is not necessary or recommended to place any additional + dependencies on socket units (for example from + multi-user.target or suchlike) when one is + installed in sockets.target. + + + + Bus-Based Activation + + When the D-Bus IPC system is used for communication with + clients, new-style daemons should employ bus activation so that + they are automatically activated when a client application + accesses their IPC interfaces. This is configured in D-Bus + service files (not to be confused with systemd service unit + files!). To ensure that D-Bus uses systemd to start-up and + maintain the daemon, use the SystemdService= + directive in these service files to configure the matching + systemd service for a D-Bus service. e.g.: For a D-Bus service + whose D-Bus activation file is named + org.freedesktop.RealtimeKit.service, make + sure to set + SystemdService=rtkit-daemon.service in that + file to bind it to the systemd service + rtkit-daemon.service. This is needed to + make sure that the daemon is started in a race-free fashion when + activated via multiple mechanisms simultaneously. + + + + Device-Based Activation + + Often, daemons that manage a particular type of hardware + should be activated only when the hardware of the respective + kind is plugged in or otherwise becomes available. In a + new-style init system, it is possible to bind activation to + hardware plug/unplug events. In systemd, kernel devices + appearing in the sysfs/udev device tree can be exposed as units + if they are tagged with the string systemd. + Like any other kind of unit, they may then pull in other units + when activated (i.e. plugged in) and thus implement device-based + activation. systemd dependencies may be encoded in the udev + database via the SYSTEMD_WANTS= property. See + systemd.device5 + for details. Often, it is nicer to pull in services from devices + only indirectly via dedicated targets. Example: Instead of + pulling in bluetoothd.service from all the + various bluetooth dongles and other hardware available, pull in + bluetooth.target from them and + bluetoothd.service from that target. This + provides for nicer abstraction and gives administrators the + option to enable bluetoothd.service via + controlling a bluetooth.target.wants/ + symlink uniformly with a command like enable + of + systemctl1 + instead of manipulating the udev ruleset. + + + + Path-Based Activation + + Often, runtime of daemons processing spool files or + directories (such as a printing system) can be delayed until + these file system objects change state, or become non-empty. + New-style init systems provide a way to bind service activation + to file system changes. systemd implements this scheme via + path-based activation configured in .path + units, as outlined in + systemd.path5. + + + + Timer-Based Activation + + Some daemons that implement clean-up jobs that are + intended to be executed in regular intervals benefit from + timer-based activation. In systemd, this is implemented via + .timer units, as described in + systemd.timer5. + + + + Other Forms of Activation + + Other forms of activation have been suggested and + implemented in some systems. However, there are often simpler or + better alternatives, or they can be put together of combinations + of the schemes above. Example: Sometimes, it appears useful to + start daemons or .socket units when a + specific IP address is configured on a network interface, + because network sockets shall be bound to the address. However, + an alternative to implement this is by utilizing the Linux + IP_FREEBIND socket option, as accessible + via FreeBind=yes in systemd socket files (see + systemd.socket5 + for details). This option, when enabled, allows sockets to be + bound to a non-local, not configured IP address, and hence + allows bindings to a particular IP address before it actually + becomes available, making such an explicit dependency to the + configured address redundant. Another often suggested trigger + for service activation is low system load. However, here too, a + more convincing approach might be to make proper use of features + of the operating system, in particular, the CPU or I/O scheduler + of Linux. Instead of scheduling jobs from userspace based on + monitoring the OS scheduler, it is advisable to leave the + scheduling of processes to the OS scheduler itself. systemd + provides fine-grained access to the CPU and I/O schedulers. If a + process executed by the init system shall not negatively impact + the amount of CPU or I/O bandwidth available to other processes, + it should be configured with + CPUSchedulingPolicy=idle and/or + IOSchedulingClass=idle. Optionally, this may + be combined with timer-based activation to schedule background + jobs during runtime and with minimal impact on the system, and + remove it from the boot phase itself. + + + + + Integration with systemd + + + Writing systemd Unit Files + + When writing systemd unit files, it is recommended to + consider the following suggestions: + + + If possible, do not use the + Type=forking setting in service files. But + if you do, make sure to set the PID file path using + PIDFile=. See + systemd.service5 + for details. + + If your daemon registers a D-Bus name on the + bus, make sure to use Type=dbus in the + service file if possible. + + Make sure to set a good human-readable + description string with + Description=. + + Do not disable + DefaultDependencies=, unless you really + know what you do and your unit is involved in early boot or + late system shutdown. + + Normally, little if any dependencies should + need to be defined explicitly. However, if you do configure + explicit dependencies, only refer to unit names listed on + systemd.special7 + or names introduced by your own package to keep the unit file + operating system-independent. + + Make sure to include an + [Install] section including installation + information for the unit file. See + systemd.unit5 + for details. To activate your service on boot, make sure to + add a WantedBy=multi-user.target or + WantedBy=graphical.target directive. To + activate your socket on boot, make sure to add + WantedBy=sockets.target. Usually, you also + want to make sure that when your service is installed, your + socket is installed too, hence add + Also=foo.socket in your service file + foo.service, for a hypothetical program + foo. + + + + + + Installing systemd Service Files + + At the build installation time (e.g. make + install during package build), packages are + recommended to install their systemd unit files in the directory + returned by pkg-config systemd + --variable=systemdsystemunitdir (for system services) + or pkg-config systemd + --variable=systemduserunitdir (for user services). + This will make the services available in the system on explicit + request but not activate them automatically during boot. + Optionally, during package installation (e.g. rpm + -i by the administrator), symlinks should be created + in the systemd configuration directories via the + enable command of the + systemctl1 + tool to activate them automatically on boot. + + Packages using + autoconf1 + are recommended to use a configure script + excerpt like the following to determine the + unit installation path during source + configuration: + + PKG_PROG_PKG_CONFIG +AC_ARG_WITH([systemdsystemunitdir], + [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],, + [with_systemdsystemunitdir=auto]) +AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [ + def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) + + AS_IF([test "x$def_systemdsystemunitdir" = "x"], + [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"], + [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])]) + with_systemdsystemunitdir=no], + [with_systemdsystemunitdir="$def_systemdsystemunitdir"])]) +AS_IF([test "x$with_systemdsystemunitdir" != "xno"], + [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])]) +AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"]) + + This snippet allows automatic + installation of the unit files on systemd + machines, and optionally allows their + installation even on machines lacking + systemd. (Modification of this snippet for the + user unit directory is left as an exercise for the + reader.) + + Additionally, to ensure that + make distcheck continues to + work, it is recommended to add the following + to the top-level Makefile.am + file in + automake1-based + projects: + + AM_DISTCHECK_CONFIGURE_FLAGS = \ + --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir) + + Finally, unit files should be installed in the system with an automake excerpt like the following: + + if HAVE_SYSTEMD +systemdsystemunit_DATA = \ + foobar.socket \ + foobar.service +endif + + In the + rpm8 + .spec file, use snippets like the following + to enable/disable the service during + installation/deinstallation. This makes use of the RPM macros + shipped along systemd. Consult the packaging guidelines of your + distribution for details and the equivalent for other package + managers. + + At the top of the file: + + BuildRequires: systemd +%{?systemd_requires} + + And as scriptlets, further down: + + %post +%systemd_post foobar.service foobar.socket + +%preun +%systemd_preun foobar.service foobar.socket + +%postun +%systemd_postun + + If the service shall be restarted during upgrades, replace + the %postun scriptlet above with the + following: + + %postun +%systemd_postun_with_restart foobar.service + + Note that %systemd_post and + %systemd_preun expect the names of all units + that are installed/removed as arguments, separated by spaces. + %systemd_postun expects no arguments. + %systemd_postun_with_restart expects the + units to restart as arguments. + + To facilitate upgrades from a package version that shipped + only SysV init scripts to a package version that ships both a + SysV init script and a native systemd service file, use a + fragment like the following: + + %triggerun -- foobar < 0.47.11-1 +if /sbin/chkconfig --level 5 foobar ; then + /bin/systemctl --no-reload enable foobar.service foobar.socket >/dev/null 2>&1 || : +fi + + Where 0.47.11-1 is the first package version that includes + the native unit file. This fragment will ensure that the first + time the unit file is installed, it will be enabled if and only + if the SysV init script is enabled, thus making sure that the + enable status is not changed. Note that + chkconfig is a command specific to Fedora + which can be used to check whether a SysV init script is + enabled. Other operating systems will have to use different + commands here. + + + + + Porting Existing Daemons + + Since new-style init systems such as systemd are compatible + with traditional SysV init systems, it is not strictly necessary + to port existing daemons to the new style. However, doing so + offers additional functionality to the daemons as well as + simplifying integration into new-style init systems. + + To port an existing SysV compatible daemon, the following + steps are recommended: + + + If not already implemented, add an optional + command line switch to the daemon to disable daemonization. This + is useful not only for using the daemon in new-style init + systems, but also to ease debugging. + + If the daemon offers interfaces to other + software running on the local system via local + AF_UNIX sockets, consider implementing + socket-based activation (see above). Usually, a minimal patch is + sufficient to implement this: Extend the socket creation in the + daemon code so that + sd_listen_fds3 + is checked for already passed sockets first. If sockets are + passed (i.e. when sd_listen_fds() returns a + positive value), skip the socket creation step and use the + passed sockets. Secondly, ensure that the file system socket + nodes for local AF_UNIX sockets used in the + socket-based activation are not removed when the daemon shuts + down, if sockets have been passed. Third, if the daemon normally + closes all remaining open file descriptors as part of its + initialization, the sockets passed from the init system must be + spared. Since new-style init systems guarantee that no left-over + file descriptors are passed to executed processes, it might be a + good choice to simply skip the closing of all remaining open + file descriptors if sockets are passed. + + Write and install a systemd unit file for the + service (and the sockets if socket-based activation is used, as + well as a path unit file, if the daemon processes a spool + directory), see above for details. + + If the daemon exposes interfaces via D-Bus, + write and install a D-Bus activation file for the service, see + above for details. + + + + + Placing Daemon Data + + It is recommended to follow the general guidelines for + placing package files, as discussed in + file-hierarchy7. + + + + See Also + + systemd1, + sd-daemon3, + sd_listen_fds3, + sd_notify3, + daemon3, + systemd.service5, + file-hierarchy7 + + + + diff --git a/man/dnssec-trust-anchors.d.xml b/man/dnssec-trust-anchors.d.xml new file mode 100644 index 00000000..8b6394e9 --- /dev/null +++ b/man/dnssec-trust-anchors.d.xml @@ -0,0 +1,171 @@ + + + + + + + dnssec-trust-anchors.d + systemd + + + + dnssec-trust-anchors.d + 5 + + + + dnssec-trust-anchors.d + systemd.positive + systemd.negative + DNSSEC trust anchor configuration files + + + + /etc/dnssec-trust-anchors.d/*.positive + /run/dnssec-trust-anchors.d/*.positive + /usr/lib/dnssec-trust-anchors.d/*.positive + /etc/dnssec-trust-anchors.d/*.negative + /run/dnssec-trust-anchors.d/*.negative + /usr/lib/dnssec-trust-anchors.d/*.negative + + + + Description + + The DNSSEC trust anchor configuration files define positive + and negative trust anchors + systemd-resolved.service8 + bases DNSSEC integrity proofs on. + + + + Positive Trust Anchors + + Positive trust anchor configuration files contain DNSKEY and + DS resource record definitions to use as base for DNSSEC integrity + proofs. See RFC 4035, + Section 4.4 for more information about DNSSEC trust + anchors. + + Positive trust anchors are read from files with the suffix + .positive located in + /etc/dnssec-trust-anchors.d/, + /run/dnssec-trust-anchors.d/ and + /usr/lib/dnssec-trust-anchors.d/. These + directories are searched in the specified order, and a trust + anchor file of the same name in an earlier path overrides a trust + anchor files in a later path. To disable a trust anchor file + shipped in /usr/lib/dnssec-trust-anchors.d/ + it is sufficient to provide an identically-named file in + /etc/dnssec-trust-anchors.d/ or + /run/dnssec-trust-anchors.d/ that is either + empty or a symlink to /dev/null ("masked"). + + Positive trust anchor files are simple text files resembling + DNS zone files, as documented in RFC 1035, Section + 5. One DS or DNSKEY resource record may be listed per + line. Empty lines and lines starting with a semicolon + (;) are ignored and considered comments. A DS + resource record is specified like in the following example: + + . IN DS 19036 8 2 49aac11d7b6f6446702e54a1607371607a1a41855200fd2ce1cdde32f24e8fb5 + + The first word specifies the domain, use + . for the root domain. The domain may be + specified with or without trailing dot, which is considered + equivalent. The second word must be IN the + third word DS. The following words specify the + key tag, signature algorithm, digest algorithm, followed by the + hex-encoded key fingerprint. See RFC 4034, + Section 5 for details about the precise syntax and meaning + of these fields. + + Alternatively, DNSKEY resource records may be used to define + trust anchors, like in the following example: + + . IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0= + + The first word specifies the domain again, the second word + must be IN, followed by + DNSKEY. The subsequent words encode the DNSKEY + flags, protocol and algorithm fields, followed by the key data + encoded in Base64. See RFC 4034, + Section 2 for details about the precise syntax and meaning + of these fields. + + If multiple DS or DNSKEY records are defined for the same + domain (possibly even in different trust anchor files), all keys + are used and are considered equivalent as base for DNSSEC + proofs. + + Note that systemd-resolved will + automatically use a built-in trust anchor key for the Internet + root domain if no positive trust anchors are defined for the root + domain. In most cases it is hence unnecessary to define an + explicit key with trust anchor files. The built-in key is disabled + as soon as at least one trust anchor key for the root domain is + defined in trust anchor files. + + It is generally recommended to encode trust anchors in DS + resource records, rather than DNSKEY resource records. + + If a trust anchor specified via a DS record is found revoked + it is automatically removed from the trust anchor database for the + runtime. See RFC + 5011 for details about revoked trust anchors. Note that + systemd-resolved will not update its trust + anchor database from DNS servers automatically. Instead, it is + recommended to update the resolver software or update the new + trust anchor via adding in new trust anchor files. + + The current DNSSEC trust anchor for the Internet's root + domain is available at the IANA + Trust Anchor and Keys page. + + + + Negative Trust Anchors + + Negative trust anchors define domains where DNSSEC validation shall be turned + off. Negative trust anchor files are found at the same location as positive trust anchor files, + and follow the same overriding rules. They are text files with the + .negative suffix. Empty lines and lines whose first character is + ; are ignored. Each line specifies one domain name which is the root of a DNS + subtree where validation shall be disabled. + + Negative trust anchors are useful to support private DNS + subtrees that are not referenced from the Internet DNS hierarchy, + and not signed. + + RFC + 7646 for details on negative trust anchors. + + If no negative trust anchor files are configured a built-in + set of well-known private DNS zone domains is used as negative + trust anchors. + + It is also possibly to define per-interface negative trust + anchors using the DNSSECNegativeTrustAnchors= + setting in + systemd.network5 + files. + + + + See Also + + systemd1, + systemd-resolved.service8, + resolved.conf5, + systemd.network5 + + + + diff --git a/man/environment.d.xml b/man/environment.d.xml new file mode 100644 index 00000000..69c156aa --- /dev/null +++ b/man/environment.d.xml @@ -0,0 +1,101 @@ + + + + + + + + environment.d + systemd + + + + environment.d + 5 + + + + environment.d + Definition of user session environment + + + + ~/.config/environment.d/*.conf + /etc/environment.d/*.conf + /run/environment.d/*.conf + /usr/lib/environment.d/*.conf + /etc/environment + + + + Description + + The environment.d directories contain a list of "global" environment + variable assignments for the user environment. + systemd-environment-d-generator8 + parses them and updates the environment exported by the systemd user instance to the services it + starts. + + It is recommended to use numerical prefixes for file names to simplify ordering. + + For backwards compatibility, a symlink to /etc/environment is + installed, so this file is also parsed. + + + + + + Configuration Format + + The configuration files contain a list of + KEY=VALUE environment + variable assignments, separated by newlines. The right hand side of these assignments may + reference previously defined environment variables, using the ${OTHER_KEY} + and $OTHER_KEY format. It is also possible to use + + ${FOO:-DEFAULT_VALUE} + to expand in the same way as ${FOO} unless the + expansion would be empty, in which case it expands to DEFAULT_VALUE, + and use + ${FOO:+ALTERNATE_VALUE} + to expand to ALTERNATE_VALUE as long as + ${FOO} would have expanded to a non-empty value. + No other elements of shell syntax are supported. + + Each KEY must be a valid variable name. Empty lines + and lines beginning with the comment character # are ignored. + + + Example + + Setup environment to allow access to a program installed in + <filename index="false">/opt/foo</filename> + + /etc/environment.d/60-foo.conf: + + + FOO_DEBUG=force-software-gl,log-verbose + PATH=/opt/foo/bin:$PATH + LD_LIBRARY_PATH=/opt/foo/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} + XDG_DATA_DIRS=/opt/foo/share:${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/} + + + + + + + See Also + + systemd1, + systemd-environment-d-generator8, + systemd.environment-generator7 + + + + diff --git a/man/file-hierarchy.xml b/man/file-hierarchy.xml new file mode 100644 index 00000000..497cb580 --- /dev/null +++ b/man/file-hierarchy.xml @@ -0,0 +1,792 @@ + + + + + + + + file-hierarchy + systemd + + + + file-hierarchy + 7 + + + + file-hierarchy + File system hierarchy overview + + + + Description + + Operating systems using the + systemd1 system and service + manager are organized based on a file system hierarchy inspired by UNIX, more specifically the hierarchy described + in the File System Hierarchy + specification and hier7, with various + extensions, partially documented in the XDG Base Directory + Specification and XDG User + Directories. This manual page describes a more generalized, though minimal and modernized subset of these + specifications that defines more strictly the suggestions and restrictions systemd makes on the file system + hierarchy. + + Many of the paths described here can be queried + with the + systemd-path1 + tool. + + + + General Structure + + + + / + The file system root. Usually writable, but + this is not required. Possibly a temporary file system + (tmpfs). Not shared with other hosts + (unless read-only). + + + + /boot/ + The boot partition used for bringing up the + system. On EFI systems, this is possibly the EFI System + Partition (ESP), also see + systemd-gpt-auto-generator8. + This directory is usually strictly local to the host, and + should be considered read-only, except when a new kernel or + boot loader is installed. This directory only exists on + systems that run on physical or emulated hardware that + requires boot loaders. + + + + /efi/ + If the boot partition /boot/ is maintained separately from the EFI System + Partition (ESP), the latter is mounted here. Tools that need to operate on the EFI system partition should look + for it at this mount point first, and fall back to /boot/ — if the former doesn't qualify + (for example if it is not a mount point or does not have the correct file system type + MSDOS_SUPER_MAGIC). + + + + /etc/ + System-specific configuration. This directory + may or may not be read-only. Frequently, this directory is + pre-populated with vendor-supplied configuration files, but + applications should not make assumptions about this directory + being fully populated or populated at all, and should fall + back to defaults if configuration is + missing. + + + + /home/ + The location for normal user's home + directories. Possibly shared with other systems, and never + read-only. This directory should only be used for normal + users, never for system users. This directory and possibly the + directories contained within it might only become available or + writable in late boot or even only after user authentication. + This directory might be placed on limited-functionality + network file systems, hence applications should not assume the + full set of file API is available on this directory. + Applications should generally not reference this directory + directly, but via the per-user $HOME + environment variable, or via the home directory field of the + user database. + + + + /root/ + The home directory of the root user. The root + user's home directory is located outside of + /home/ in order to make sure the root user + may log in even without /home/ being + available and mounted. + + + + /srv/ + The place to store general server payload, + managed by the administrator. No restrictions are made how + this directory is organized internally. Generally writable, + and possibly shared among systems. This directory might become + available or writable only very late during + boot. + + + + /tmp/ + The place for small temporary files. This directory is usually mounted as a + tmpfs instance, and should hence not be used for larger files. (Use + /var/tmp/ for larger files.) Since the directory is accessible to other users of + the system, it is essential that this directory is only written to with the mkstemp3, + mkdtemp3 and + related calls. This directory is usually flushed at boot-up. Also, files that are not accessed within + a certain time are usually automatically deleted. If applications find the environment variable + $TMPDIR set, they should prefer using the directory specified in it over directly + referencing /tmp/ (see environ7 and + IEEE + Std 1003.1 for details). For further details about this directory, see Using /tmp/ And /var/tmp/ + Safely. + + + + + + + Runtime Data + + + + /run/ + A tmpfs file system for + system packages to place runtime data in. This directory is + flushed on boot, and generally writable for privileged + programs only. Always writable. + + + + /run/log/ + Runtime system logs. System components may + place private logs in this directory. Always writable, even + when /var/log/ might not be accessible + yet. + + + + /run/user/ + Contains per-user runtime directories, each + usually individually mounted tmpfs + instances. Always writable, flushed at each reboot and when + the user logs out. User code should not reference this + directory directly, but via the + $XDG_RUNTIME_DIR environment variable, as + documented in the XDG + Base Directory Specification. + + + + + + Vendor-supplied Operating System Resources + + + + + /usr/ + Vendor-supplied operating system resources. + Usually read-only, but this is not required. Possibly shared + between multiple hosts. This directory should not be modified + by the administrator, except when installing or removing + vendor-supplied packages. + + + + /usr/bin/ + Binaries and executables for user commands + that shall appear in the $PATH search path. + It is recommended not to place binaries in this directory that + are not useful for invocation from a shell (such as daemon + binaries); these should be placed in a subdirectory of + /usr/lib/ instead. + + + + /usr/include/ + C and C++ API header files of system + libraries. + + + + /usr/lib/ + Static, private vendor data that is compatible + with all architectures (though not necessarily + architecture-independent). Note that this includes internal + executables or other binaries that are not regularly invoked + from a shell. Such binaries may be for any architecture + supported by the system. Do not place public libraries in this + directory, use $libdir (see below), + instead. + + + + /usr/lib/arch-id/ + Location for placing dynamic libraries into, also + called $libdir. The architecture identifier + to use is defined on Multiarch + Architecture Specifiers (Tuples) list. Legacy + locations of $libdir are + /usr/lib/, + /usr/lib64/. This directory should not be + used for package-specific data, unless this data is + architecture-dependent, too. To query + $libdir for the primary architecture of the + system, invoke: + # systemd-path system-library-arch + + + + + /usr/share/ + Resources shared between multiple packages, + such as documentation, man pages, time zone information, fonts + and other resources. Usually, the precise location and format + of files stored below this directory is subject to + specifications that ensure interoperability. + + + + /usr/share/doc/ + Documentation for the operating system or + system packages. + + + + /usr/share/factory/etc/ + Repository for vendor-supplied default + configuration files. This directory should be populated with + pristine vendor versions of all configuration files that may + be placed in /etc/. This is useful to + compare the local configuration of a system with vendor + defaults and to populate the local configuration with + defaults. + + + + /usr/share/factory/var/ + + Similar to + /usr/share/factory/etc/, but for vendor + versions of files in the variable, persistent data directory + /var/. + + + + + + + Persistent Variable System Data + + + + /var/ + Persistent, variable system data. Must be + writable. This directory might be pre-populated with + vendor-supplied data, but applications should be able to + reconstruct necessary files and directories in this + subhierarchy should they be missing, as the system might start + up without this directory being populated. Persistency is + recommended, but optional, to support ephemeral systems. This + directory might become available or writable only very late + during boot. Components that are required to operate during + early boot hence shall not unconditionally rely on this + directory. + + + + /var/cache/ + Persistent system cache data. System + components may place non-essential data in this directory. + Flushing this directory should have no effect on operation of + programs, except for increased runtimes necessary to rebuild + these caches. + + + + /var/lib/ + Persistent system data. System components may + place private data in this directory. + + + + /var/log/ + Persistent system logs. System components may + place private logs in this directory, though it is recommended + to do most logging via the + syslog3 + and + sd_journal_print3 + calls. + + + + /var/spool/ + Persistent system spool data, such as printer + or mail queues. + + + + /var/tmp/ + The place for larger and persistent temporary files. In contrast to + /tmp/, this directory is usually mounted from a persistent physical file system + and can thus accept larger files. (Use /tmp/ for smaller files.) This directory + is generally not flushed at boot-up, but time-based cleanup of files that have not been accessed for + a certain time is applied. The same security restrictions as with /tmp/ apply, + and hence only mkstemp3, + mkdtemp3 or + similar calls should be used to make use of this directory. If applications find the environment + variable $TMPDIR set, they should prefer using the directory specified in it over + directly referencing /var/tmp/ (see environ7 for + details). For further details about this directory, see Using /tmp/ And /var/tmp/ + Safely. + + + + + + + Virtual Kernel and API File Systems + + + + /dev/ + The root directory for device nodes. Usually, + this directory is mounted as a devtmpfs + instance, but might be of a different type in + sandboxed/containerized setups. This directory is managed + jointly by the kernel and + systemd-udevd8, + and should not be written to by other components. A number of + special purpose virtual file systems might be mounted below + this directory. + + + + /dev/shm/ + Place for POSIX shared memory segments, as + created via + shm_open3. + This directory is flushed on boot, and is a + tmpfs file system. Since all users have + write access to this directory, special care should be taken + to avoid name clashes and vulnerabilities. For normal users, + shared memory segments in this directory are usually deleted + when the user logs out. Usually, it is a better idea to use + memory mapped files in /run/ (for system + programs) or $XDG_RUNTIME_DIR (for user + programs) instead of POSIX shared memory segments, since these + directories are not world-writable and hence not vulnerable to + security-sensitive name clashes. + + + + /proc/ + A virtual kernel file system exposing the + process list and other functionality. This file system is + mostly an API to interface with the kernel and not a place + where normal files may be stored. For details, see + proc5. + A number of special purpose virtual file systems might be + mounted below this directory. + + + + /proc/sys/ + A hierarchy below /proc/ + that exposes a number of kernel tunables. The primary way to + configure the settings in this API file tree is via + sysctl.d5 + files. In sandboxed/containerized setups, this directory is + generally mounted read-only. + + + + /sys/ + A virtual kernel file system exposing + discovered devices and other functionality. This file system + is mostly an API to interface with the kernel and not a place + where normal files may be stored. In sandboxed/containerized + setups, this directory is generally mounted read-only. A number + of special purpose virtual file systems might be mounted below + this directory. + + + + + + + Compatibility Symlinks + + + + /bin/ + /sbin/ + /usr/sbin/ + + These compatibility symlinks point to + /usr/bin/, ensuring that scripts and + binaries referencing these legacy paths correctly find their + binaries. + + + + /lib/ + + This compatibility symlink points to + /usr/lib/, ensuring that programs + referencing this legacy path correctly find their + resources. + + + + /lib64/ + + On some architecture ABIs, this compatibility + symlink points to $libdir, ensuring that + binaries referencing this legacy path correctly find their + dynamic loader. This symlink only exists on architectures + whose ABI places the dynamic loader in this + path. + + + + /var/run/ + + This compatibility symlink points to + /run/, ensuring that programs referencing + this legacy path correctly find their runtime + data. + + + + + + + Home Directory + + User applications may want to place files and directories in + the user's home directory. They should follow the following basic + structure. Note that some of these directories are also + standardized (though more weakly) by the XDG + Base Directory Specification. Additional locations for + high-level user resources are defined by xdg-user-dirs. + + + + ~/.cache/ + + Persistent user cache data. User programs may + place non-essential data in this directory. Flushing this + directory should have no effect on operation of programs, + except for increased runtimes necessary to rebuild these + caches. If an application finds + $XDG_CACHE_HOME set, it should use the + directory specified in it instead of this + directory. + + + + ~/.config/ + + Application configuration and state. When a + new user is created, this directory will be empty or not exist + at all. Applications should fall back to defaults should their + configuration or state in this directory be missing. If an + application finds $XDG_CONFIG_HOME set, it + should use the directory specified in it instead of this + directory. + + + + ~/.local/bin/ + + Executables that shall appear in the user's + $PATH search path. It is recommended not to + place executables in this directory that are not useful for + invocation from a shell; these should be placed in a + subdirectory of ~/.local/lib/ instead. + Care should be taken when placing architecture-dependent + binaries in this place, which might be problematic if the home + directory is shared between multiple hosts with different + architectures. + + + + ~/.local/lib/ + + Static, private vendor data that is compatible + with all architectures. + + + + ~/.local/lib/arch-id/ + + Location for placing public dynamic libraries. + The architecture identifier to use is defined on Multiarch + Architecture Specifiers (Tuples) + list. + + + + ~/.local/share/ + + Resources shared between multiple packages, + such as fonts or artwork. Usually, the precise location and + format of files stored below this directory is subject to + specifications that ensure interoperability. If an application + finds $XDG_DATA_HOME set, it should use the + directory specified in it instead of this + directory. + + + + + + + Unprivileged Write Access + + Unprivileged processes generally lack write access to most + of the hierarchy. + + The exceptions for normal users are + /tmp/, + /var/tmp/, + /dev/shm/, as well as the home directory + $HOME (usually found below + /home/) and the runtime directory + $XDG_RUNTIME_DIR (found below + /run/user/) of the user, which are all + writable. + + For unprivileged system processes, only + /tmp/, + /var/tmp/ and + /dev/shm/ are writable. If an + unprivileged system process needs a private writable directory in + /var/ or /run/, it is + recommended to either create it before dropping privileges in the + daemon code, to create it via + tmpfiles.d5 + fragments during boot, or via the + StateDirectory= and RuntimeDirectory= + directives of service units (see + systemd.unit5 + for details). + + + + Node Types + + Unix file systems support different types of file nodes, + including regular files, directories, symlinks, character and + block device nodes, sockets and FIFOs. + + It is strongly recommended that /dev/ is + the only location below which device nodes shall be placed. + Similarly, /run/ shall be the only location to + place sockets and FIFOs. Regular files, directories and symlinks + may be used in all directories. + + + + System Packages + + Developers of system packages should follow strict rules + when placing their own files in the file system. The following + table lists recommended locations for specific types of files + supplied by the vendor. + + + System Package Vendor Files Locations + + + + + + Directory + Purpose + + + + + /usr/bin/ + Package executables that shall appear in the $PATH executable search path, compiled for any of the supported architectures compatible with the operating system. It is not recommended to place internal binaries or binaries that are not commonly invoked from the shell in this directory, such as daemon binaries. As this directory is shared with most other packages of the system, special care should be taken to pick unique names for files placed here, that are unlikely to clash with other package's files. + + + /usr/lib/arch-id/ + Public shared libraries of the package. As above, be careful with using too generic names, and pick unique names for your libraries to place here to avoid name clashes. + + + /usr/lib/package/ + Private static vendor resources of the package, including private binaries and libraries, or any other kind of read-only vendor data. + + + /usr/lib/arch-id/package/ + Private other vendor resources of the package that are architecture-specific and cannot be shared between architectures. Note that this generally does not include private executables since binaries of a specific architecture may be freely invoked from any other supported system architecture. + + + /usr/include/package/ + Public C/C++ APIs of public shared libraries of the package. + + + +
+ + Additional static vendor files may be installed in the + /usr/share/ hierarchy to the locations + defined by the various relevant specifications. + + During runtime, and for local configuration and state, + additional directories are defined: + + + System Package Variable Files Locations + + + + + + Directory + Purpose + + + + + /etc/package/ + System-specific configuration for the package. It is recommended to default to safe fallbacks if this configuration is missing, if this is possible. Alternatively, a tmpfiles.d5 fragment may be used to copy or symlink the necessary files and directories from /usr/share/factory/ during boot, via the L or C directives. + + + /run/package/ + Runtime data for the package. Packages must be able to create the necessary subdirectories in this tree on their own, since the directory is flushed automatically on boot. Alternatively, a tmpfiles.d5 fragment may be used to create the necessary directories during boot, or the RuntimeDirectory= directive of service units may be used to create them at service startup (see systemd.unit5 for details). + + + /run/log/package/ + Runtime log data for the package. As above, the package needs to make sure to create this directory if necessary, as it will be flushed on every boot. + + + /var/cache/package/ + Persistent cache data of the package. If this directory is flushed, the application should work correctly on next invocation, though possibly slowed down due to the need to rebuild any local cache files. The application must be capable of recreating this directory should it be missing and necessary. To create an empty directory, a tmpfiles.d5 fragment or the CacheDirectory= directive of service units (see systemd.unit5) may be used. + + + /var/lib/package/ + Persistent private data of the package. This is the primary place to put persistent data that does not fall into the other categories listed. Packages should be able to create the necessary subdirectories in this tree on their own, since the directory might be missing on boot. To create an empty directory, a tmpfiles.d5 fragment or the StateDirectory= directive of service units (see systemd.unit5) may be used. + + + /var/log/package/ + Persistent log data of the package. As above, the package should make sure to create this directory if necessary, possibly using tmpfiles.d5 or LogsDirectory= (see systemd.unit5), as it might be missing. + + + /var/spool/package/ + Persistent spool/queue data of the package. As above, the package should make sure to create this directory if necessary, as it might be missing. + + + +
+
+ + + User Packages + + Programs running in user context should follow strict rules + when placing their own files in the user's home directory. The + following table lists recommended locations in the home directory + for specific types of files supplied by the vendor if the + application is installed in the home directory. (Note, however, + that user applications installed system-wide should follow the + rules outlined above regarding placing vendor files.) + + + User Package Vendor File Locations + + + + + + Directory + Purpose + + + + + ~/.local/bin/ + Package executables that shall appear in the $PATH executable search path. It is not recommended to place internal executables or executables that are not commonly invoked from the shell in this directory, such as daemon executables. As this directory is shared with most other packages of the user, special care should be taken to pick unique names for files placed here, that are unlikely to clash with other package's files. + + + ~/.local/lib/arch-id/ + Public shared libraries of the package. As above, be careful with using too generic names, and pick unique names for your libraries to place here to avoid name clashes. + + + ~/.local/lib/package/ + Private, static vendor resources of the package, compatible with any architecture, or any other kind of read-only vendor data. + + + ~/.local/lib/arch-id/package/ + Private other vendor resources of the package that are architecture-specific and cannot be shared between architectures. + + + +
+ + Additional static vendor files may be installed in the + ~/.local/share/ hierarchy to the locations + defined by the various relevant specifications. + + During runtime, and for local configuration and state, + additional directories are defined: + + + User Package Variable File Locations + + + + + + Directory + Purpose + + + + + ~/.config/package/ + User-specific configuration and state for the package. It is required to default to safe fallbacks if this configuration is missing. + + + $XDG_RUNTIME_DIR/package/ + User runtime data for the package. + + + ~/.cache/package/ + Persistent cache data of the package. If this directory is flushed, the application should work correctly on next invocation, though possibly slowed down due to the need to rebuild any local cache files. The application must be capable of recreating this directory should it be missing and necessary. + + + +
+
+ + + See Also + + systemd1, + hier7, + systemd-path1, + systemd-gpt-auto-generator8, + sysctl.d5, + tmpfiles.d5, + pkg-config1, + systemd.unit5 + + + +
diff --git a/man/glib-event-glue.c b/man/glib-event-glue.c new file mode 100644 index 00000000..5201234d --- /dev/null +++ b/man/glib-event-glue.c @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: MIT */ + +#include +#include +#include + +typedef struct SDEventSource { + GSource source; + GPollFD pollfd; + sd_event *event; +} SDEventSource; + +static gboolean event_prepare(GSource *source, gint *timeout_) { + return sd_event_prepare(((SDEventSource *)source)->event) > 0; +} + +static gboolean event_check(GSource *source) { + return sd_event_wait(((SDEventSource *)source)->event, 0) > 0; +} + +static gboolean event_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { + return sd_event_dispatch(((SDEventSource *)source)->event) > 0; +} + +static void event_finalize(GSource *source) { + sd_event_unref(((SDEventSource *)source)->event); +} + +static GSourceFuncs event_funcs = { + .prepare = event_prepare, + .check = event_check, + .dispatch = event_dispatch, + .finalize = event_finalize, +}; + +GSource *g_sd_event_create_source(sd_event *event) { + SDEventSource *source; + + source = (SDEventSource *)g_source_new(&event_funcs, sizeof(SDEventSource)); + + source->event = sd_event_ref(event); + source->pollfd.fd = sd_event_get_fd(event); + source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; + + g_source_add_poll((GSource *)source, &source->pollfd); + + return (GSource *)source; +} diff --git a/man/halt.xml b/man/halt.xml new file mode 100644 index 00000000..75604b83 --- /dev/null +++ b/man/halt.xml @@ -0,0 +1,158 @@ + + + + + + + + halt + systemd + + + + halt + 8 + + + + halt + poweroff + reboot + Halt, power-off or reboot the machine + + + + + halt + OPTIONS + + + poweroff + OPTIONS + + + reboot + OPTIONS + + + + + Description + + halt, poweroff, + reboot may be used to halt, power-off or reboot + the machine. + + + + + Options + + The following options are understood: + + + + + + + + + + + + Halt the machine, regardless of which one of + the three commands is invoked. + + + + + + + Power-off the machine, regardless of which one + of the three commands is invoked. + + + + + + Reboot the machine, regardless of which one of + the three commands is invoked. + + + + + + + Force immediate halt, power-off, or reboot. When + specified once, this results in an immediate but clean shutdown + by the system manager. When specified twice, this results in an + immediate shutdown without contacting the system manager. See the + description of in + systemctl1 + for more details. + + + + + + + Only write wtmp shutdown entry, do not + actually halt, power-off, reboot. + + + + + + + Do not write wtmp shutdown + entry. + + + + + + + Don't sync hard disks/storage media before + halt, power-off, reboot. + + + + + + Do not send wall message before halt, + power-off, reboot. + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + Notes + + These commands are implemented in a way that preserves compatibility with + the original SysV commands. + systemctl1 + verbs halt, poweroff, + reboot provide the same functionality with some additional + features. + + + + See Also + + systemd1, + systemctl1, + shutdown8, + wall1 + + + + diff --git a/man/hostname.xml b/man/hostname.xml new file mode 100644 index 00000000..bb880c33 --- /dev/null +++ b/man/hostname.xml @@ -0,0 +1,71 @@ + + + + + + + hostname + systemd + + + + hostname + 5 + + + + hostname + Local hostname configuration file + + + + /etc/hostname + + + + Description + + The /etc/hostname file configures the + name of the local system that is set during boot using the + sethostname2 + system call. It should contain a single newline-terminated + hostname string. Comments (lines starting with a `#') are ignored. + The hostname may be a free-form string up to 64 characters in length; + however, it is recommended that it consists only of 7-bit ASCII lower-case + characters and no spaces or dots, and limits itself to the format allowed + for DNS domain name labels, even though this is not a strict + requirement. + + You may use + hostnamectl1 + to change the value of this file during runtime from the command + line. Use + systemd-firstboot1 + to initialize it on mounted (but not booted) system images. + + + + History + + The simple configuration file format of + /etc/hostname originates from Debian + GNU/Linux. + + + + See Also + + systemd1, + sethostname2, + hostname1, + hostname7, + machine-id5, + machine-info5, + hostnamectl1, + systemd-hostnamed.service8, + systemd-firstboot1 + + + + diff --git a/man/hostnamectl.xml b/man/hostnamectl.xml new file mode 100644 index 00000000..03293382 --- /dev/null +++ b/man/hostnamectl.xml @@ -0,0 +1,224 @@ + + + + + + + + hostnamectl + systemd + + + + hostnamectl + 1 + + + + hostnamectl + Control the system hostname + + + + + hostnamectl + OPTIONS + COMMAND + + + + + Description + + hostnamectl may be used to query and + change the system hostname and related settings. + + This tool distinguishes three different hostnames: the + high-level "pretty" hostname which might include all kinds of + special characters (e.g. "Lennart's Laptop"), the static hostname + which is used to initialize the kernel hostname at boot (e.g. + "lennarts-laptop"), and the transient hostname which is a fallback + value received from network configuration. If a static hostname is + set, and is valid (something other than localhost), then the + transient hostname is not used. + + Note that the pretty hostname has little restrictions on the characters and length used, while the static and + transient hostnames are limited to the usually accepted characters of Internet domain names, and 64 characters at + maximum (the latter being a Linux limitation). + + The static hostname is stored in + /etc/hostname, see + hostname5 + for more information. The pretty hostname, chassis type, and icon + name are stored in /etc/machine-info, see + machine-info5. + + Use + systemd-firstboot1 + to initialize the system host name for mounted (but not booted) + system images. + + + + Commands + + The following commands are understood: + + + + status + + Show current system hostname and related information. If no command is specified, + this is the implied default. + + + + set-hostname NAME + + Set the system hostname to NAME. By default, this will alter the + pretty, the static, and the transient hostname alike; however, if one or more of , + , are used, only the selected hostnames are changed. If + the pretty hostname is being set, and static or transient are being set as well, the specified hostname will be + simplified in regards to the character set used before the latter are updated. This is done by removing special + characters and spaces. This ensures that the pretty and the static hostname are always closely related while + still following the validity rules of the specific name. This simplification of the hostname string is not done + if only the transient and/or static host names are set, and the pretty host name is left untouched. + + Pass the empty string as the + hostname to reset the selected hostnames to their default + (usually localhost). + + + + set-icon-name NAME + + Set the system icon name to + NAME. The icon name is used by some + graphical applications to visualize this host. The icon name + should follow the Icon + Naming Specification. + + Pass an empty string to reset the icon name to the + default value, which is determined from chassis type (see + below) and possibly other parameters. + + + + set-chassis TYPE + + Set the chassis type to + TYPE. The chassis type is used by + some graphical applications to visualize the host or alter + user interaction. Currently, the following chassis types are + defined: + desktop, + laptop, + convertible, + server, + tablet, + handset, + watch, + embedded, + as well as the special chassis types + vm and + container for virtualized systems that lack + an immediate physical chassis. + + Pass an empty string to reset the chassis type to the + default value which is determined from the firmware and + possibly other parameters. + + + + + set-deployment ENVIRONMENT + + Set the deployment environment description. + ENVIRONMENT must be a single word + without any control characters. One of the following is + suggested: + development, + integration, + staging, + production. + + + Pass an empty string to reset to the default empty + value. + + + + + set-location LOCATION + + Set the location string for the system, if it + is known. LOCATION should be a + human-friendly, free-form string describing the physical + location of the system, if it is known and applicable. This + may be as generic as Berlin, Germany or as + specific as Left Rack, 2nd Shelf. + + Pass an empty string to reset to the default empty + value. + + + + + + + Options + + The following options are understood: + + + + + + Do not query the user for authentication for + privileged operations. + + + + + + + + If status is invoked (or no explicit command is given) and one of these + switches is specified, hostnamectl will print out just this selected hostname. + + If used with set-hostname, only the selected hostname(s) will be updated. When more + than one of these switches are specified, all the specified hostnames will be updated. + + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + See Also + + systemd1, + hostname1, + hostname5, + machine-info5, + systemctl1, + systemd-hostnamed.service8, + systemd-firstboot1 + + + + diff --git a/man/html.in b/man/html.in new file mode 100755 index 00000000..bc9a668c --- /dev/null +++ b/man/html.in @@ -0,0 +1,12 @@ +#!/bin/sh +set -e + +if [ -z "$1" ]; then + echo "Use: $0 page-name (with no section suffix)" + exit 1 +fi + +target="man/$1.html" +ninja -C "@BUILD_ROOT@" "$target" +set -x +exec xdg-open "@BUILD_ROOT@/$target" diff --git a/man/hwdb.xml b/man/hwdb.xml new file mode 100644 index 00000000..7ba52360 --- /dev/null +++ b/man/hwdb.xml @@ -0,0 +1,132 @@ + + + + + + + hwdb + systemd + + + + hwdb + 7 + + + + hwdb + Hardware Database + + + Description + The hardware database is a key-value store for associating modalias-like keys to + udev-property-like values. It is used primarily by udev to add the relevant properties + to matching devices, but it can also be queried directly. + + + Hardware Database Files + The hwdb files are read from the files located in the + system hwdb directory /usr/lib/udev/hwdb.d and + the local administration directory /etc/udev/hwdb.d. + All hwdb files are collectively sorted and processed in lexical order, + regardless of the directories in which they live. However, files with + identical filenames replace each other. Files in /etc + have the highest priority and take precedence over files with the same + name in /usr/lib. This can be used to override a + system-supplied hwdb file with a local file if needed; + a symlink in /etc with the same name as a hwdb file in + /usr/lib, pointing to /dev/null, + disables that hwdb file entirely. hwdb files must have the extension + .hwdb; other extensions are ignored. + + Each hwdb file contains data records consisting of matches and associated + key-value pairs. Every record in the hwdb starts with one or more match strings, + specifying a shell glob to compare the lookup string against. Multiple match lines + are specified in consecutive lines. Every match line is compared individually, and + they are combined by OR. Every match line must start at the first character of the + line. + + The match lines are followed by one or more key-value pair lines, which are + recognized by a leading space character. The key name and value are separated by + =. An empty line signifies the end of a record. Lines beginning + with # are ignored. + + In case multiple records match a given lookup string, the key-value pairs + from all records are combined. If a key is specified multiple times, the value + from the record with the highest priority is used (each key can have only a single + value). The priority is higher when the record is in a file that sorts later + lexicographically, and in case of records in the same file, later records have + higher priority. + + The content of all hwdb files is read by + systemd-hwdb8 + and compiled to a binary database located at /etc/udev/hwdb.bin, + or alternatively /usr/lib/udev/hwdb.bin if you want ship the + compiled database in an immutable image. During runtime, only the binary database + is used. + + + + Examples + + + General syntax of hwdb files + + # /usr/lib/udev/hwdb.d/example.hwdb +# Comments can be placed before any records. This is a good spot +# to describe what that file is used for, what kind of properties +# it defines, and the ordering convention. + +# A record with three matches and one property +mouse:*:name:*Trackball*: +mouse:*:name:*trackball*: +mouse:*:name:*TrackBall*: + ID_INPUT_TRACKBALL=1 + +# A record with a single match and five properties +mouse:usb:v046dp4041:name:Logitech MX Master: + MOUSE_DPI=1000@166 + MOUSE_WHEEL_CLICK_ANGLE=15 + MOUSE_WHEEL_CLICK_ANGLE_HORIZONTAL=26 + MOUSE_WHEEL_CLICK_COUNT=24 + MOUSE_WHEEL_CLICK_COUNT_HORIZONTAL=14 + + + + + Overriding of properties + + # /usr/lib/udev/hwdb.d/60-keyboard.hwdb +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn* + KEYBOARD_KEY_a1=help + KEYBOARD_KEY_a2=setup + KEYBOARD_KEY_a3=battery + +evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pn123* + KEYBOARD_KEY_a2=wlan + +# /etc/udev/hwdb.d/70-keyboard.hwdb +# disable wlan key on all at keyboards +evdev:atkbd:* + KEYBOARD_KEY_a2=reserved + + If the hwdb consists of those two files, a keyboard with the lookup string + evdev:atkbd:dmi:bvnAcer:bdXXXXX:bd08/05/2010:svnAcer:pn123 + will match all three records, and end up with the following properties: + + KEYBOARD_KEY_a1=help +KEYBOARD_KEY_a2=reserved +KEYBOARD_KEY_a3=battery + + + + + See Also + + + systemd-hwdb8 + + + + diff --git a/man/id128-app-specific.c b/man/id128-app-specific.c new file mode 100644 index 00000000..b81e50ff --- /dev/null +++ b/man/id128-app-specific.c @@ -0,0 +1,11 @@ +#include +#include + +#define OUR_APPLICATION_ID SD_ID128_MAKE(c2,73,27,73,23,db,45,4e,a6,3b,b9,6e,79,b5,3e,97) + +int main(int argc, char *argv[]) { + sd_id128_t id; + sd_id128_get_machine_app_specific(OUR_APPLICATION_ID, &id); + printf("Our application ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id)); + return 0; +} diff --git a/man/inotify-watch-tmp.c b/man/inotify-watch-tmp.c new file mode 100644 index 00000000..ca790f0a --- /dev/null +++ b/man/inotify-watch-tmp.c @@ -0,0 +1,56 @@ +#include +#include +#include + +#include + +#define _cleanup_(f) __attribute__((cleanup(f))) + +static int inotify_handler(sd_event_source *source, + const struct inotify_event *event, + void *userdata) { + + const char *desc = NULL; + + sd_event_source_get_description(source, &desc); + + if (event->mask & IN_Q_OVERFLOW) + printf("inotify-handler <%s>: overflow\n", desc); + else if (event->mask & IN_CREATE) + printf("inotify-handler <%s>: create on %s\n", desc, event->name); + else if (event->mask & IN_DELETE) + printf("inotify-handler <%s>: delete on %s\n", desc, event->name); + else if (event->mask & IN_MOVED_TO) + printf("inotify-handler <%s>: moved-to on %s\n", desc, event->name); + + /* Terminate the program if an "exit" file appears */ + if ((event->mask & (IN_CREATE|IN_MOVED_TO)) && + strcmp(event->name, "exit") == 0) + sd_event_exit(sd_event_source_get_event(source), 0); + + return 1; +} + +int main(int argc, char **argv) { + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(sd_event_source_unrefp) sd_event_source *source1 = NULL, *source2 = NULL; + + const char *path1 = argc > 1 ? argv[1] : "/tmp"; + const char *path2 = argc > 2 ? argv[2] : NULL; + + /* Note: failure handling is omitted for brevity */ + + sd_event_default(&event); + + sd_event_add_inotify(event, &source1, path1, + IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_TO, + inotify_handler, NULL); + if (path2) + sd_event_add_inotify(event, &source2, path2, + IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_TO, + inotify_handler, NULL); + + sd_event_loop(event); + + return 0; +} diff --git a/man/journal-iterate-poll.c b/man/journal-iterate-poll.c new file mode 100644 index 00000000..100d07e2 --- /dev/null +++ b/man/journal-iterate-poll.c @@ -0,0 +1,25 @@ +#include +#include +#include + +int wait_for_changes(sd_journal *j) { + uint64_t t; + int msec; + struct pollfd pollfd; + + sd_journal_get_timeout(j, &t); + if (t == (uint64_t) -1) + msec = -1; + else { + struct timespec ts; + uint64_t n; + clock_gettime(CLOCK_MONOTONIC, &ts); + n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; + msec = t > n ? (int) ((t - n + 999) / 1000) : 0; + } + + pollfd.fd = sd_journal_get_fd(j); + pollfd.events = sd_journal_get_events(j); + poll(&pollfd, 1, msec); + return sd_journal_process(j); +} diff --git a/man/journal-iterate-unique.c b/man/journal-iterate-unique.c new file mode 100644 index 00000000..fcf92e7b --- /dev/null +++ b/man/journal-iterate-unique.c @@ -0,0 +1,25 @@ +#include +#include +#include + +int main(int argc, char *argv[]) { + sd_journal *j; + const void *d; + size_t l; + int r; + + r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); + if (r < 0) { + fprintf(stderr, "Failed to open journal: %s\n", strerror(-r)); + return 1; + } + r = sd_journal_query_unique(j, "_SYSTEMD_UNIT"); + if (r < 0) { + fprintf(stderr, "Failed to query journal: %s\n", strerror(-r)); + return 1; + } + SD_JOURNAL_FOREACH_UNIQUE(j, d, l) + printf("%.*s\n", (int) l, (const char*) d); + sd_journal_close(j); + return 0; +} diff --git a/man/journal-iterate-wait.c b/man/journal-iterate-wait.c new file mode 100644 index 00000000..0a23569f --- /dev/null +++ b/man/journal-iterate-wait.c @@ -0,0 +1,39 @@ +#include +#include +#include + +int main(int argc, char *argv[]) { + int r; + sd_journal *j; + r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); + if (r < 0) { + fprintf(stderr, "Failed to open journal: %s\n", strerror(-r)); + return 1; + } + for (;;) { + const void *d; + size_t l; + r = sd_journal_next(j); + if (r < 0) { + fprintf(stderr, "Failed to iterate to next entry: %s\n", strerror(-r)); + break; + } + if (r == 0) { + /* Reached the end, let's wait for changes, and try again */ + r = sd_journal_wait(j, (uint64_t) -1); + if (r < 0) { + fprintf(stderr, "Failed to wait for changes: %s\n", strerror(-r)); + break; + } + continue; + } + r = sd_journal_get_data(j, "MESSAGE", &d, &l); + if (r < 0) { + fprintf(stderr, "Failed to read message field: %s\n", strerror(-r)); + continue; + } + printf("%.*s\n", (int) l, (const char*) d); + } + sd_journal_close(j); + return 0; +} diff --git a/man/journal-remote.conf.xml b/man/journal-remote.conf.xml new file mode 100644 index 00000000..ab3dfd01 --- /dev/null +++ b/man/journal-remote.conf.xml @@ -0,0 +1,100 @@ + + + + + + + + journal-remote.conf + systemd + + + + journal-remote.conf + 5 + + + + journal-remote.conf + journal-remote.conf.d + Configuration files for the service accepting remote journal uploads + + + + /etc/systemd/journal-remote.conf + /etc/systemd/journal-remote.conf.d/*.conf + /run/systemd/journal-remote.conf.d/*.conf + /usr/lib/systemd/journal-remote.conf.d/*.conf + + + + Description + + These files configure various parameters of + systemd-journal-remote.service8. + See + systemd.syntax5 + for a general description of the syntax. + + + + + + Options + + All options are configured in the + [Remote] section: + + + + Seal= + + Periodically sign the data in the journal using Forward Secure Sealing. + + + + + SplitMode= + + One of host or none. + + + + + ServerKeyFile= + + SSL key in PEM format. + + + + ServerCertificateFile= + + SSL certificate in PEM format. + + + + TrustedCertificateFile= + + SSL CA certificate. + + + + + + + + See Also + + systemd-journal-remote.service8, + systemd1, + systemd-journald.service8 + + + + diff --git a/man/journal-upload.conf.xml b/man/journal-upload.conf.xml new file mode 100644 index 00000000..f2721a75 --- /dev/null +++ b/man/journal-upload.conf.xml @@ -0,0 +1,90 @@ + + + + + + + journal-upload.conf + systemd + + + + journal-upload.conf + 5 + + + + journal-upload.conf + journal-upload.conf.d + Configuration files for the journal upload service + + + + /etc/systemd/journal-upload.conf + /etc/systemd/journal-upload.conf.d/*.conf + /run/systemd/journal-upload.conf.d/*.conf + /usr/lib/systemd/journal-upload.conf.d/*.conf + + + + Description + + These files configure various parameters of + systemd-journal-upload.service8. + See + systemd.syntax5 + for a general description of the syntax. + + + + + + Options + + All options are configured in the [Upload] section: + + + + URL= + + The URL to upload the journal entries to. See the description + of option in + systemd-journal-upload8 + for the description of possible values. There is no default value, so either this + option or the command-line option must be always present to make an upload. + + + + ServerKeyFile= + + SSL key in PEM format. + + + + ServerCertificateFile= + + SSL CA certificate in PEM format. + + + + TrustedCertificateFile= + + SSL CA certificate. + + + + + + + + See Also + + systemd-journal-upload.service8, + systemd1, + systemd-journald.service8 + + + + diff --git a/man/journalctl.xml b/man/journalctl.xml new file mode 100644 index 00000000..f6703b06 --- /dev/null +++ b/man/journalctl.xml @@ -0,0 +1,1029 @@ + + + + + + + + journalctl + systemd + + + + journalctl + 1 + + + + journalctl + Query the systemd journal + + + + + journalctl + OPTIONS + MATCHES + + + + + Description + + journalctl may be used to query the + contents of the + systemd1 + journal as written by + systemd-journald.service8. + + If called without parameters, it will show the full + contents of the journal, starting with the oldest entry + collected. + + If one or more match arguments are passed, the output is + filtered accordingly. A match is in the format + FIELD=VALUE, + e.g. _SYSTEMD_UNIT=httpd.service, referring + to the components of a structured journal entry. See + systemd.journal-fields7 + for a list of well-known fields. If multiple matches are + specified matching different fields, the log entries are + filtered by both, i.e. the resulting output will show only + entries matching all the specified matches of this kind. If two + matches apply to the same field, then they are automatically + matched as alternatives, i.e. the resulting output will show + entries matching any of the specified matches for the same + field. Finally, the character + may appear + as a separate word between other terms on the command line. This + causes all matches before and after to be combined in a + disjunction (i.e. logical OR). + + It is also possible to filter the entries by specifying an + absolute file path as an argument. The file path may be a file or + a symbolic link and the file must exist at the time of the query. If a + file path refers to an executable binary, an _EXE= + match for the canonicalized binary path is added to the query. If a + file path refers to an executable script, a _COMM= + match for the script name is added to the query. If a file path + refers to a device node, _KERNEL_DEVICE= matches for + the kernel name of the device and for each of its ancestor devices is + added to the query. Symbolic links are dereferenced, kernel names are + synthesized, and parent devices are identified from the environment at + the time of the query. In general, a device node is the best proxy for + an actual device, as log entries do not usually contain fields that + identify an actual device. For the resulting log entries to be correct + for the actual device, the relevant parts of the environment at the time + the entry was logged, in particular the actual device corresponding to + the device node, must have been the same as those at the time of the + query. Because device nodes generally change their corresponding devices + across reboots, specifying a device node path causes the resulting + entries to be restricted to those from the current boot. + + Additional constraints may be added using options + , , etc., to + further limit what entries will be shown (logical AND). + + Output is interleaved from all accessible journal files, + whether they are rotated or currently being written, and + regardless of whether they belong to the system itself or are + accessible user journals. + + The set of journal files which will be used can be + modified using the , + , , and + options, see below. + + All users are granted access to their private per-user + journals. However, by default, only root and users who are + members of a few special groups are granted access to the system + journal and the journals of other users. Members of the groups + systemd-journal, adm, and + wheel can read all journal files. Note + that the two latter groups traditionally have additional + privileges specified by the distribution. Members of the + wheel group can often perform administrative + tasks. + + The output is paged through less by + default, and long lines are "truncated" to screen width. The + hidden part can be viewed by using the left-arrow and + right-arrow keys. Paging can be disabled; see the + option and the "Environment" section + below. + + When outputting to a tty, lines are colored according to + priority: lines of level ERROR and higher are colored red; lines + of level NOTICE and higher are highlighted; lines of level DEBUG + are colored lighter grey; other lines are displayed normally. + + + + Options + + The following options are understood: + + + + + + + + Ellipsize fields when they do not fit in + available columns. The default is to show full fields, + allowing them to wrap or be truncated by the pager, if one + is used. + + The old options + / are not useful + anymore, except to undo . + + + + + + + + Show all fields in full, even if they include unprintable characters or are very long. By + default, fields with unprintable characters are abbreviated as "blob data". (Note that the pager may escape + unprintable characters again.) + + + + + + + Show only the most recent journal entries, + and continuously print new entries as they are appended to + the journal. + + + + + + + Immediately jump to the end of the journal + inside the implied pager tool. This implies + to guarantee that the pager will not + buffer logs of unbounded size. This may be overridden with + an explicit with some other numeric + value, while will disable this cap. + Note that this option is only supported for the + less1 + pager. + + + + + + + Show the most recent journal events and + limit the number of events shown. If + is used, this option is + implied. The argument is a positive integer or + all to disable line limiting. The default + value is 10 if no argument is given. + + + + + + Show all stored output lines, even in follow + mode. Undoes the effect of . + + + + + + + + Reverse output so that the newest entries + are displayed first. + + + + + + + Controls the formatting of the journal + entries that are shown. Takes one of the following + options: + + + + + + + is the default and generates an output that is + mostly identical to the formatting of classic syslog + files, showing one line per journal entry. + + + + + + + + + is very similar, but shows timestamps in the format the and + options accept. Unlike the timestamp information shown in + output mode this mode includes weekday, year and timezone information in the + output, and is locale-independent. + + + + + + + + + is very similar, but shows ISO 8601 wallclock + timestamps. + + + + + + + + + as for but includes full + microsecond precision. + + + + + + + + + is very similar, but shows classic syslog timestamps + with full microsecond precision. + + + + + + + + + is very similar, but shows monotonic timestamps + instead of wallclock timestamps. + + + + + + + + + is very similar, but shows seconds passed since January 1st 1970 UTC instead of wallclock + timestamps ("UNIX time"). The time is shown with microsecond accuracy. + + + + + + + + + shows the full-structured entry items with all + fields. + + + + + + + + + serializes the journal into a binary (but mostly + text-based) stream suitable for backups and network + transfer (see + Journal Export Format + for more information). To import the binary stream back + into native journald format use + systemd-journal-remote8. + + + + + + + + + formats entries as JSON objects, separated by newline characters (see Journal JSON Format for more + information). Field values are generally encoded as JSON strings, with three exceptions: + + Fields larger than 4096 bytes are encoded as null values. (This + may be turned off by passing , but be aware that this may allocate overly long + JSON objects.) + + Journal entries permit non-unique fields within the same log entry. JSON does not allow + non-unique fields within objects. Due to this, if a non-unique field is encountered a JSON array is + used as field value, listing all field values as elements. + + Fields containing non-printable or non-UTF8 bytes are encoded as arrays containing + the raw bytes individually formatted as unsigned numbers. + + + Note that this encoding is reversible (with the exception of the size limit). + + + + + + + + + formats entries as JSON data structures, but + formats them in multiple lines in order to make them + more readable by humans. + + + + + + + + + formats entries as JSON data structures, but wraps + them in a format suitable for + Server-Sent Events. + + + + + + + + + + formats entries as JSON data structures, but prefixes them with an ASCII Record Separator + character (0x1E) and suffixes them with an ASCII Line Feed character (0x0A), in accordance with JavaScript Object Notation (JSON) Text Sequences + (application/json-seq). + + + + + + + + + + generates a very terse output, only showing the + actual message of each journal entry with no metadata, + not even a timestamp. + + + + + + + + + similar to short-full, but prefixes the unit and + user unit names instead of the traditional syslog + identifier. Useful when using templated instances, as it + will include the arguments in the unit names. + + + + + + + + + + A comma separated list of the fields which should be included in the output. This only has an + effect for the output modes which would normally show all fields (, + , , , and + ). The __CURSOR, __REALTIME_TIMESTAMP, + __MONOTONIC_TIMESTAMP, and _BOOT_ID fields are always + printed. + + + + + + Express time in Coordinated Universal Time + (UTC). + + + + + + Don't show the hostname field of log messages originating from the local host. This switch only + has an effect on the family of output modes (see above). + + + + + + + Augment log lines with explanation texts from + the message catalog. This will add explanatory help texts to + log messages in the output where this is available. These + short help texts will explain the context of an error or log + event, possible solutions, as well as pointers to support + forums, developer documentation, and any other relevant + manuals. Note that help texts are not available for all + messages, but only for selected ones. For more information on + the message catalog, please refer to the + Message Catalog Developer Documentation. + + Note: when attaching journalctl + output to bug reports, please do not use + . + + + + + + + + Suppresses all informational messages + (i.e. "-- Logs begin at …", "-- Reboot --"), + any warning messages regarding + inaccessible system journals when run as a normal + user. + + + + + + + Show entries interleaved from all available + journals, including remote ones. + + + + + + + Show messages from a specific boot. This will + add a match for _BOOT_ID=. + + The argument may be empty, in which case logs for the + current boot will be shown. + + If the boot ID is omitted, a positive + offset will look up the boots + starting from the beginning of the journal, and an + equal-or-less-than zero offset will + look up boots starting from the end of the journal. Thus, + 1 means the first boot found in the + journal in chronological order, 2 the + second and so on; while -0 is the last + boot, -1 the boot before last, and so + on. An empty offset is equivalent + to specifying -0, except when the current + boot is not the last boot (e.g. because + was specified to look at logs + from a different machine). + + If the 32-character ID is + specified, it may optionally be followed by + offset which identifies the boot + relative to the one given by boot + ID. Negative values mean earlier + boots and positive values mean later boots. If + offset is not specified, a value of + zero is assumed, and the logs for the boot given by + ID are shown. + + The special argument all can be + used to negate the effect of an earlier use of + . + + + + + + + Show a tabular list of boot numbers (relative to + the current boot), their IDs, and the timestamps of the first + and last message pertaining to the boot. + + + + + + + Show only kernel messages. This implies + and adds the match + _TRANSPORT=kernel. + + + + + + + Show messages for the specified syslog + identifier + SYSLOG_IDENTIFIER. + + This parameter can be specified multiple + times. + + + + + + + Show messages for the specified systemd unit + UNIT (such as a service unit), or + for any of the units matched by + PATTERN. If a pattern is + specified, a list of unit names found in the journal is + compared with the specified pattern and all that match are + used. For each unit name, a match is added for messages from + the unit + (_SYSTEMD_UNIT=UNIT), + along with additional matches for messages from systemd and + messages about coredumps for the specified unit. A match + is also added for _SYSTEMD_SLICE=UNIT, + such that if the provided UNIT is a + systemd.slice5 + unit, all logs of the children of the slice will be logged. + + + This parameter can be specified multiple times. + + + + + + + Show messages for the specified user session + unit. This will add a match for messages from the unit + (_SYSTEMD_USER_UNIT= and + _UID=) and additional matches for messages + from session systemd and messages about coredumps for the + specified unit. A match + is also added for _SYSTEMD_USER_SLICE=UNIT, + such that if the provided UNIT is a + systemd.slice5 + unit, all logs of the children of the unit will be logged. + + This parameter can be specified multiple times. + + + + + + + + Filter output by message priorities or + priority ranges. Takes either a single numeric or textual log + level (i.e. between 0/emerg and + 7/debug), or a range of numeric/text log + levels in the form FROM..TO. The log levels are the usual + syslog log levels as documented in + syslog3, + i.e. emerg (0), + alert (1), crit (2), + err (3), warning (4), + notice (5), info (6), + debug (7). If a single log level is + specified, all messages with this log level or a lower (hence + more important) log level are shown. If a range is specified, + all messages within the range are shown, including both the + start and the end value of the range. This will add + PRIORITY= matches for the specified + priorities. + + + + + + + Filter output to entries where the MESSAGE= + field matches the specified regular expression. PERL-compatible regular expressions + are used, see + pcre2pattern3 + for a detailed description of the syntax. + + If the pattern is all lowercase, matching is case insensitive. + Otherwise, matching is case sensitive. This can be overridden with the + option, see below. + + + + + + + Make pattern matching case sensitive or case insenstive. + + + + + + + + Start showing entries from the location in the + journal specified by the passed cursor. + + + + + + If FILE exists and contains a + cursor, start showing entries after this location. + Otherwise the show entries according the other given options. At the end, + write the cursor of the last entry to FILE. Use + this option to continually read the journal by sequentially calling + journalctl. + + + + + + Start showing entries from the location in the + journal after the location specified by + the passed cursor. The cursor is shown when the + option is used. + + + + + + + The cursor is shown after the last entry after + two dashes: + -- cursor: s=0639… + The format of the cursor is private + and subject to change. + + + + + + + + + Start showing entries on or newer than the specified date, or on or older than the specified + date, respectively. Date specifications should be of the format 2012-10-30 18:17:16. If the + time part is omitted, 00:00:00 is assumed. If only the seconds component is omitted, + :00 is assumed. If the date component is omitted, the current day is assumed. Alternatively + the strings yesterday, today, tomorrow are understood, + which refer to 00:00:00 of the day before the current day, the current day, or the day after the current day, + respectively. now refers to the current time. Finally, relative times may be specified, + prefixed with - or +, referring to times before or after the current + time, respectively. For complete time and date specification, see + systemd.time7. Note that + prints timestamps that follow precisely this format. + + + + + + + + + Print all possible data values the specified + field can take in all entries of the journal. + + + + + + + Print all field names currently used in all entries of the journal. + + + + + + + Show messages from system services and the + kernel (with ). Show messages from + service of current user (with ). If + neither is specified, show all messages that the user can see. + + + + + + + + Show messages from a running, local + container. Specify a container name to connect to. + + + + + + + + Takes a directory path as argument. If + specified, journalctl will operate on the specified journal + directory DIR instead of the + default runtime and system journal paths. + + + + + + Takes a file glob as an argument. If + specified, journalctl will operate on the specified journal + files matching GLOB instead of the + default runtime and system journal paths. May be specified + multiple times, in which case files will be suitably + interleaved. + + + + + + Takes a directory path as an argument. If + specified, journalctl will operate on journal directories and catalog file hierarchy + underneath the specified directory instead of the root + directory (e.g. will create + ROOT/var/lib/systemd/catalog/database, + and journal files under ROOT/run/journal + or ROOT/var/log/journal will be displayed). + + + + + + + Instead of showing journal contents, show + internal header information of the journal fields + accessed. + + + + + + Shows the current disk usage of all journal + files. This shows the sum of the disk usage of all archived + and active journal files. + + + + + + + + Removes the oldest archived journal files until the disk space they use falls below the + specified size (specified with the usual K, M, G and + T suffixes), or all archived journal files contain no data older than the specified timespan + (specified with the usual s, m, h, + days, months, weeks and years + suffixes), or no more than the specified number of separate journal files remain. Note that running + has only an indirect effect on the output shown by + , as the latter includes active journal files, while the vacuuming operation only + operates on archived journal files. Similarly, might not actually reduce the + number of journal files to below the specified number, as it will not remove active journal + files. + + , and + may be combined in a single invocation to enforce any combination of a size, a time and a number of files limit + on the archived journal files. Specifying any of these three parameters as zero is equivalent to not enforcing + the specific limit, and is thus redundant. + + These three switches may also be combined with into one command. If so, all + active files are rotated first, and the requested vacuuming operation is executed right after. The rotation has + the effect that all currently active files are archived (and potentially new, empty journal files opened as + replacement), and hence the vacuuming operation has the greatest effect as it can take all log data written so + far into account. + + + + + + List the contents of the message catalog as a + table of message IDs, plus their short description strings. + + + If any 128-bit-IDs are + specified, only those entries are shown. + + + + + + + Show the contents of the message catalog, with + entries separated by a line consisting of two dashes and the + ID (the format is the same as .catalog + files). + + If any 128-bit-IDs are + specified, only those entries are shown. + + + + + + + Update the message catalog index. This command + needs to be executed each time new catalog files are + installed, removed, or updated to rebuild the binary catalog + index. + + + + + + Instead of showing journal contents, generate + a new key pair for Forward Secure Sealing (FSS). This will + generate a sealing key and a verification key. The sealing key + is stored in the journal data directory and shall remain on + the host. The verification key should be stored + externally. Refer to the option in + journald.conf5 + for information on Forward Secure Sealing and for a link to a + refereed scholarly paper detailing the cryptographic theory it + is based on. + + + + + + When is passed + and Forward Secure Sealing (FSS) has already been configured, + recreate FSS keys. + + + + + + Specifies the change interval for the sealing + key when generating an FSS key pair with + . Shorter intervals increase CPU + consumption but shorten the time range of undetectable journal + alterations. Defaults to 15min. + + + + + + Check the journal file for internal + consistency. If the file has been generated with FSS enabled and + the FSS verification key has been specified with + , authenticity of the journal file + is verified. + + + + + + Specifies the FSS verification key to use for + the operation. + + + + + + Asks the journal daemon to write all yet + unwritten journal data to the backing file system and + synchronize all journals. This call does not return until the + synchronization operation is complete. This command guarantees + that any log messages written before its invocation are safely + stored on disk at the time it returns. + + + + + + Asks the journal daemon to flush any log data stored in + /run/log/journal/ into /var/log/journal/, if persistent + storage is enabled. This call does not return until the operation is complete. Note that this call is + idempotent: the data is only flushed from /run/log/journal/ into + /var/log/journal once during system runtime (but see + below), and this command exits cleanly without executing any + operation if this has already happened. This command effectively guarantees that all data is flushed + to /var/log/journal at the time it returns. + + + + + + Asks the journal daemon for the reverse operation to : if + requested the daemon will write further log data to /run/log/journal/ and stops + writing to /var/log/journal/. A subsequent call to + causes the log output to switch back to /var/log/journal/, see + above. + + + + + + Similar to but executes no operation if the root file + system and /var/lib/journal/ reside on the same mount point. This operation is + used during system shutdown in order to make the journal daemon stop writing data to + /var/log/journal/ in case that directory is located on a mount point that needs + to be unmounted. + + + + + + Asks the journal daemon to rotate journal files. This call does not return until the rotation + operation is complete. Journal file rotation has the effect that all currently active journal files are marked + as archived and renamed, so that they are never written to in future. New (empty) journal files are then + created in their place. This operation may be combined with , + and into a single command, see + above. + + + + + + + + + + Exit status + + On success, 0 is returned; otherwise, a non-zero failure + code is returned. + + + + + + Examples + + Without arguments, all collected logs are shown + unfiltered: + + journalctl + + With one match specified, all entries with a field matching + the expression are shown: + + journalctl _SYSTEMD_UNIT=avahi-daemon.service +journalctl _SYSTEMD_CGROUP=/user.slice/user-42.slice/session-c1.scope + + If two different fields are matched, only entries matching + both expressions at the same time are shown: + + journalctl _SYSTEMD_UNIT=avahi-daemon.service _PID=28097 + + If two matches refer to the same field, all entries matching + either expression are shown: + + journalctl _SYSTEMD_UNIT=avahi-daemon.service _SYSTEMD_UNIT=dbus.service + + If the separator + is used, two + expressions may be combined in a logical OR. The following will + show all messages from the Avahi service process with the PID + 28097 plus all messages from the D-Bus service (from any of its + processes): + + journalctl _SYSTEMD_UNIT=avahi-daemon.service _PID=28097 + _SYSTEMD_UNIT=dbus.service + + To show all fields emitted by a unit and about + the unit, option / should be used. + journalctl -u name + expands to a complex filter similar to + _SYSTEMD_UNIT=name.service + + UNIT=name.service _PID=1 + + OBJECT_SYSTEMD_UNIT=name.service _UID=0 + + COREDUMP_UNIT=name.service _UID=0 MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1 + + (see systemd.journal-fields5 + for an explanation of those patterns). + + + Show all logs generated by the D-Bus executable: + + journalctl /usr/bin/dbus-daemon + + Show all kernel logs from previous boot: + + journalctl -k -b -1 + + Show a live log display from a system service + apache.service: + + journalctl -f -u apache + + + + + See Also + + systemd1, + systemd-journald.service8, + systemctl1, + coredumpctl1, + systemd.journal-fields7, + journald.conf5, + systemd.time7, + systemd-journal-remote.service8, + systemd-journal-upload.service8 + + + diff --git a/man/journald.conf.xml b/man/journald.conf.xml new file mode 100644 index 00000000..7155bf7f --- /dev/null +++ b/man/journald.conf.xml @@ -0,0 +1,429 @@ + + + + + + + journald.conf + systemd + + + + journald.conf + 5 + + + + journald.conf + journald.conf.d + Journal service configuration files + + + + /etc/systemd/journald.conf + /etc/systemd/journald.conf.d/*.conf + /run/systemd/journald.conf.d/*.conf + /usr/lib/systemd/journald.conf.d/*.conf + + + + Description + + These files configure various parameters of the systemd journal service, + systemd-journald.service8. + See + systemd.syntax5 + for a general description of the syntax. + + + + + + + Options + + All options are configured in the + [Journal] section: + + + + + Storage= + + Controls where to store journal data. One of + volatile, + persistent, + auto and + none. If + volatile, journal + log data will be stored only in memory, i.e. below the + /run/log/journal hierarchy (which is + created if needed). If persistent, data + will be stored preferably on disk, i.e. below the + /var/log/journal hierarchy (which is + created if needed), with a fallback to + /run/log/journal (which is created if + needed), during early boot and if the disk is not writable. + auto is similar to + persistent but the directory + /var/log/journal is not created if + needed, so that its existence controls where log data goes. + none turns off all storage, all log data + received will be dropped. Forwarding to other targets, such as + the console, the kernel log buffer, or a syslog socket will + still work however. Defaults to + auto. + + + + Compress= + + Can take a boolean value. If enabled (the + default), data objects that shall be stored in the journal + and are larger than the default threshold of 512 bytes are + compressed before they are written to the file system. It + can also be set to a number of bytes to specify the + compression threshold directly. Suffixes like K, M, and G + can be used to specify larger units. + + + + Seal= + + Takes a boolean value. If enabled (the + default), and a sealing key is available (as created by + journalctl1's + command), Forward Secure Sealing + (FSS) for all persistent journal files is enabled. FSS is + based on Seekable Sequential Key + Generators by G. A. Marson and B. Poettering + (doi:10.1007/978-3-642-40203-6_7) and may be used to protect + journal files from unnoticed alteration. + + + + SplitMode= + + Controls whether to split up journal files per user, either uid or + none. Split journal files are primarily useful for access control: on UNIX/Linux access + control is managed per file, and the journal daemon will assign users read access to their journal files. If + uid, all regular users (with UID outside the range of system users, dynamic service users, + and the nobody user) will each get their own journal files, and system users will log to the system journal. + See Users, Groups, UIDs and GIDs on systemd systems + for more details about UID ranges. + If none, journal files are not split up by user and all messages are + instead stored in the single system journal. In this mode unprivileged users generally do not have access to + their own log data. Note that splitting up journal files by user is only available for journals stored + persistently. If journals are stored on volatile storage (see Storage= above), only a single + journal file is used. Defaults to uid. + + + + RateLimitIntervalSec= + RateLimitBurst= + + Configures the rate limiting that is applied + to all messages generated on the system. If, in the time + interval defined by RateLimitIntervalSec=, + more messages than specified in + RateLimitBurst= are logged by a service, + all further messages within the interval are dropped until the + interval is over. A message about the number of dropped + messages is generated. This rate limiting is applied + per-service, so that two services which log do not interfere + with each other's limits. Defaults to 10000 messages in 30s. + The time specification for + RateLimitIntervalSec= may be specified in the + following units: s, min, + h, ms, + us. To turn off any kind of rate limiting, + set either value to 0. + + If a service provides rate limits for itself through + LogRateLimitIntervalSec= and/or LogRateLimitBurst= + in systemd.exec5, + those values will override the settings specified here. + + + + + SystemMaxUse= + SystemKeepFree= + SystemMaxFileSize= + SystemMaxFiles= + RuntimeMaxUse= + RuntimeKeepFree= + RuntimeMaxFileSize= + RuntimeMaxFiles= + + Enforce size limits on the journal files + stored. The options prefixed with System + apply to the journal files when stored on a persistent file + system, more specifically + /var/log/journal. The options prefixed + with Runtime apply to the journal files + when stored on a volatile in-memory file system, more + specifically /run/log/journal. The former + is used only when /var is mounted, + writable, and the directory + /var/log/journal exists. Otherwise, only + the latter applies. Note that this means that during early + boot and if the administrator disabled persistent logging, + only the latter options apply, while the former apply if + persistent logging is enabled and the system is fully booted + up. journalctl and + systemd-journald ignore all files with + names not ending with .journal or + .journal~, so only such files, located in + the appropriate directories, are taken into account when + calculating current disk usage. + + SystemMaxUse= and + RuntimeMaxUse= control how much disk space + the journal may use up at most. + SystemKeepFree= and + RuntimeKeepFree= control how much disk + space systemd-journald shall leave free for other uses. + systemd-journald will respect both limits + and use the smaller of the two values. + + The first pair defaults to 10% and the second to 15% of + the size of the respective file system, but each value is + capped to 4G. If the file system is nearly full and either + SystemKeepFree= or + RuntimeKeepFree= are violated when + systemd-journald is started, the limit will be raised to the + percentage that is actually free. This means that if there was + enough free space before and journal files were created, and + subsequently something else causes the file system to fill up, + journald will stop using more space, but it will not be + removing existing files to reduce the footprint again, + either. Also note that only archived files are deleted to reduce the + space occupied by journal files. This means that, in effect, there might + still be more space used than SystemMaxUse= or + RuntimeMaxUse= limit after a vacuuming operation is + complete. + + SystemMaxFileSize= and + RuntimeMaxFileSize= control how large + individual journal files may grow at most. This influences + the granularity in which disk space is made available through + rotation, i.e. deletion of historic data. Defaults to one + eighth of the values configured with + SystemMaxUse= and + RuntimeMaxUse=, so that usually seven + rotated journal files are kept as history. + + Specify values in bytes or use K, M, G, T, P, E as + units for the specified sizes (equal to 1024, 1024², … bytes). + Note that size limits are enforced synchronously when journal + files are extended, and no explicit rotation step triggered by + time is needed. + + SystemMaxFiles= and + RuntimeMaxFiles= control how many + individual journal files to keep at most. Note that only + archived files are deleted to reduce the number of files until + this limit is reached; active files will stay around. This + means that, in effect, there might still be more journal files + around in total than this limit after a vacuuming operation is + complete. This setting defaults to 100. + + + + MaxFileSec= + + The maximum time to store entries in a single + journal file before rotating to the next one. Normally, + time-based rotation should not be required as size-based + rotation with options such as + SystemMaxFileSize= should be sufficient to + ensure that journal files do not grow without bounds. However, + to ensure that not too much data is lost at once when old + journal files are deleted, it might make sense to change this + value from the default of one month. Set to 0 to turn off this + feature. This setting takes time values which may be suffixed + with the units year, + month, week, + day, h or + m to override the default time unit of + seconds. + + + + MaxRetentionSec= + + The maximum time to store journal entries. + This controls whether journal files containing entries older + than the specified time span are deleted. Normally, time-based + deletion of old journal files should not be required as + size-based deletion with options such as + SystemMaxUse= should be sufficient to + ensure that journal files do not grow without bounds. However, + to enforce data retention policies, it might make sense to + change this value from the default of 0 (which turns off this + feature). This setting also takes time values which may be + suffixed with the units year, + month, week, + day, h or + m to override the default time unit of + seconds. + + + + SyncIntervalSec= + + The timeout before synchronizing journal files + to disk. After syncing, journal files are placed in the + OFFLINE state. Note that syncing is unconditionally done + immediately after a log message of priority CRIT, ALERT or + EMERG has been logged. This setting hence applies only to + messages of the levels ERR, WARNING, NOTICE, INFO, DEBUG. The + default timeout is 5 minutes. + + + + ForwardToSyslog= + ForwardToKMsg= + ForwardToConsole= + ForwardToWall= + + Control whether log messages received by the journal daemon shall be forwarded to a + traditional syslog daemon, to the kernel log buffer (kmsg), to the system console, or sent as wall + messages to all logged-in users. These options take boolean arguments. If forwarding to syslog is + enabled but nothing reads messages from the socket, forwarding to syslog has no effect. By default, + only forwarding to wall is enabled. These settings may be overridden at boot time with the kernel + command line options systemd.journald.forward_to_syslog, + systemd.journald.forward_to_kmsg, + systemd.journald.forward_to_console, and + systemd.journald.forward_to_wall. If the option name is specified without + = and the following argument, true is assumed. Otherwise, the argument is parsed + as a boolean. + + When forwarding to the console, the TTY to log to can be changed with + TTYPath=, described below. + + When forwarding to the kernel log buffer (kmsg), make sure to select a suitably large size for + the log buffer, and ensure the kernel's rate-limiting applied to userspace processes is turned + off. Specifically, add log_buf_len=8M and printk.devkmsg=on (or + similar) to the kernel command line. + + + + MaxLevelStore= + MaxLevelSyslog= + MaxLevelKMsg= + MaxLevelConsole= + MaxLevelWall= + + Controls the maximum log level of messages + that are stored in the journal, forwarded to syslog, kmsg, the + console or wall (if that is enabled, see above). As argument, + takes one of + emerg, + alert, + crit, + err, + warning, + notice, + info, + debug, + or integer values in the range of 0–7 (corresponding to the + same levels). Messages equal or below the log level specified + are stored/forwarded, messages above are dropped. Defaults to + debug for MaxLevelStore= + and MaxLevelSyslog=, to ensure that the all + messages are stored in the journal and forwarded to syslog. + Defaults to + notice for MaxLevelKMsg=, + info for MaxLevelConsole=, + and emerg for + MaxLevelWall=. These settings may be + overridden at boot time with the kernel command line options + systemd.journald.max_level_store=, + systemd.journald.max_level_syslog=, + systemd.journald.max_level_kmsg=, + systemd.journald.max_level_console=, + systemd.journald.max_level_wall=. + + + + + ReadKMsg= + + Takes a boolean value. If enabled (the + default), journal reads /dev/kmsg + messages generated by the kernel. + + + + TTYPath= + + Change the console TTY to use if + ForwardToConsole=yes is used. Defaults to + /dev/console. + + + + LineMax= + + The maximum line length to permit when converting stream logs into record logs. When a systemd + unit's standard output/error are connected to the journal via a stream socket, the data read is split into + individual log records at newline (\n, ASCII 10) and NUL characters. If no such delimiter is + read for the specified number of bytes a hard log record boundary is artificially inserted, breaking up overly + long lines into multiple log records. Selecting overly large values increases the possible memory usage of the + Journal daemon for each stream client, as in the worst case the journal daemon needs to buffer the specified + number of bytes in memory before it can flush a new log record to disk. Also note that permitting overly large + line maximum line lengths affects compatibility with traditional log protocols as log records might not fit + anymore into a single AF_UNIX or AF_INET datagram. Takes a size in + bytes. If the value is suffixed with K, M, G or T, the specified size is parsed as Kilobytes, Megabytes, + Gigabytes, or Terabytes (with the base 1024), respectively. Defaults to 48K, which is relatively large but + still small enough so that log records likely fit into network datagrams along with extra room for + metadata. Note that values below 79 are not accepted and will be bumped to 79. + + + + + + + + Forwarding to traditional syslog daemons + + + Journal events can be transferred to a different logging daemon + in two different ways. With the first method, messages are + immediately forwarded to a socket + (/run/systemd/journal/syslog), where the + traditional syslog daemon can read them. This method is + controlled by the ForwardToSyslog= option. With a + second method, a syslog daemon behaves like a normal journal + client, and reads messages from the journal files, similarly to + journalctl1. + With this, messages do not have to be read immediately, + which allows a logging daemon which is only started late in boot + to access all messages since the start of the system. In + addition, full structured meta-data is available to it. This + method of course is available only if the messages are stored in + a journal file at all. So it will not work if + Storage=none is set. It should be noted that + usually the second method is used by syslog + daemons, so the Storage= option, and not the + ForwardToSyslog= option, is relevant for them. + + + + + See Also + + systemd1, + systemd-journald.service8, + journalctl1, + systemd.journal-fields7, + systemd-system.conf5 + + + + diff --git a/man/kernel-command-line.xml b/man/kernel-command-line.xml new file mode 100644 index 00000000..848f5ec4 --- /dev/null +++ b/man/kernel-command-line.xml @@ -0,0 +1,460 @@ + + + + + + + + kernel-command-line + systemd + + + + kernel-command-line + 7 + + + + kernel-command-line + Kernel command line parameters + + + + /proc/cmdline + + + + Description + + The kernel, the initial RAM disk (initrd) and basic userspace functionality may be configured at + boot via kernel command line arguments. In addition, various systemd tools look at the EFI variable + SystemdOptions (if available). Both sources are combined, but the kernel command line + has higher priority. Please note that the EFI variable is only used by systemd tools, and is + ignored by the kernel and other user space tools, so it is not a replacement for the kernel + command line. + + For command line parameters understood by the kernel, please + see + kernel-parameters.html + and + bootparam7. + + For command line parameters understood by the initial RAM + disk, please see + dracut.cmdline7, + or the documentation of the specific initrd implementation of your + installation. + + + + Core OS Command Line Arguments + + + + systemd.unit= + rd.systemd.unit= + systemd.dump_core + systemd.early_core_pattern= + systemd.crash_chvt + systemd.crash_shell + systemd.crash_reboot + systemd.confirm_spawn + systemd.service_watchdogs + systemd.show_status + systemd.status_unit_format= + systemd.log_target= + systemd.log_level= + systemd.log_location= + systemd.log_color + systemd.default_standard_output= + systemd.default_standard_error= + systemd.setenv= + systemd.machine_id= + systemd.unified_cgroup_hierarchy + systemd.legacy_systemd_cgroup_controller + + Parameters understood by the system and service + manager to control system behavior. For details, see + systemd1. + + + + + systemd.mask= + systemd.wants= + systemd.debug_shell + + Additional parameters understood by + systemd-debug-generator8, + to mask or start specific units at boot, or invoke a debug + shell on tty9. + + + + + systemd.run= + systemd.run_success_action= + systemd.run_failure_action= + + Additional parameters understood by + systemd-run-generator8, to + run a command line specified on the kernel command line as system service after booting up. + + + + + systemd.early_core_pattern= + + During early boot, the generation of core dump files is disabled until a core dump handler (if any) + takes over. This parameter allows to specifies an absolute path where core dump files should be stored until + a handler is installed. The path should be absolute and may contain specifiers, see + core5 for details. + + + + + systemd.restore_state= + + This parameter is understood by several system tools + to control whether or not they should restore system state + from the previous boot. For details, see + systemd-backlight@.service8 + and + systemd-rfkill.service8. + + + + + + systemd.volatile= + + This parameter controls whether the system shall boot up in volatile mode. Takes a boolean argument, or + the special value state. If false (the default), normal boot mode is selected, the root + directory and /var are mounted as specified on the kernel command line or + /etc/fstab, or otherwise configured. If true, full state-less boot mode is selected. In + this case the root directory is mounted as volatile memory file system (tmpfs), and only + /usr is mounted from the file system configured as root device, in read-only mode. This + enables fully state-less boots were the vendor-supplied OS is used as shipped, with only default + configuration and no stored state in effect, as /etc and /var (as + well as all other resources shipped in the root file system) are reset at boot and lost on shutdown. If this + setting is set to state the root file system is mounted read-only, however + /var is mounted as a volatile memory file system (tmpfs), so that the + system boots up with the normal configuration applied, but all state reset at boot and lost at shutdown. If + this setting is set to overlay the root file system is set up as + overlayfs mount combining the read-only root directory with a writable + tmpfs, so that no modifications are made to disk, but the file system may be modified + nonetheless with all changes being lost at reboot. For details, see + systemd-volatile-root.service8 + and + systemd-fstab-generator8. + + + + + quiet + + Parameter understood by both the kernel and the system + and service manager to control console log verbosity. For + details, see + systemd1. + + + + + debug + + Parameter understood by both the kernel and the system + and service manager to control console log verbosity. For + details, see + systemd1. + + + + + -b + rd.emergency + emergency + rd.rescue + rescue + single + s + S + 1 + 2 + 3 + 4 + 5 + + Parameters understood by the system and service + manager, as compatibility and convenience options. For details, see + systemd1. + + + + + locale.LANG= + locale.LANGUAGE= + locale.LC_CTYPE= + locale.LC_NUMERIC= + locale.LC_TIME= + locale.LC_COLLATE= + locale.LC_MONETARY= + locale.LC_MESSAGES= + locale.LC_PAPER= + locale.LC_NAME= + locale.LC_ADDRESS= + locale.LC_TELEPHONE= + locale.LC_MEASUREMENT= + locale.LC_IDENTIFICATION= + + Parameters understood by the system and service + manager to control locale and language settings. For + details, see + systemd1. + + + + + fsck.mode= + fsck.repair= + + + Parameters understood by the file system checker + services. For details, see + systemd-fsck@.service8. + + + + + quotacheck.mode= + + + Parameter understood by the file quota checker + service. For details, see + systemd-quotacheck.service8. + + + + + systemd.journald.forward_to_syslog= + systemd.journald.forward_to_kmsg= + systemd.journald.forward_to_console= + systemd.journald.forward_to_wall= + + + Parameters understood by the journal service. For + details, see + systemd-journald.service8. + + + + + vconsole.keymap= + vconsole.keymap_toggle= + vconsole.font= + vconsole.font_map= + vconsole.font_unimap= + + + Parameters understood by the virtual console setup logic. For details, see + vconsole.conf5. + + + + + udev.log_priority= + rd.udev.log_priority= + udev.children_max= + rd.udev.children_max= + udev.exec_delay= + rd.udev.exec_delay= + udev.event_timeout= + rd.udev.event_timeout= + net.ifnames= + net.naming-scheme= + + + Parameters understood by the device event managing + daemon. For details, see + systemd-udevd.service8. + + + + + plymouth.enable= + + + May be used to disable the Plymouth boot splash. For + details, see + plymouth8. + + + + + luks= + rd.luks= + luks.crypttab= + rd.luks.crypttab= + luks.name= + rd.luks.name= + luks.uuid= + rd.luks.uuid= + luks.options= + rd.luks.options= + luks.key= + rd.luks.key= + + + Configures the LUKS full-disk encryption logic at + boot. For details, see + systemd-cryptsetup-generator8. + + + + + fstab= + rd.fstab= + + + Configures the /etc/fstab logic + at boot. For details, see + systemd-fstab-generator8. + + + + + root= + rootfstype= + rootflags= + ro + rw + + + Configures the root file system and its file system + type and mount options, as well as whether it shall be + mounted read-only or read-write initially. For details, + see + systemd-fstab-generator8. + + + + + mount.usr= + mount.usrfstype= + mount.usrflags= + + + Configures the /usr file system (if required) and + its file system type and mount options. For details, see + systemd-fstab-generator8. + + + + + roothash= + systemd.verity= + rd.systemd.verity= + systemd.verity_root_data= + systemd.verity_root_hash= + + Configures the integrity protection root hash for the root file system, and other related + parameters. For details, see + systemd-veritysetup-generator8. + + + + + systemd.gpt_auto= + rd.systemd.gpt_auto= + + + Configures whether GPT based partition auto-discovery + shall be attempted. For details, see + systemd-gpt-auto-generator8. + + + + + systemd.default_timeout_start_sec= + + + Overwrites the default start job timeout DefaultTimeoutStartSec= at boot. For details, + see systemd-system.conf5. + + + + + systemd.watchdog_device= + + + Overwrites the watchdog device path WatchdogDevice=. For details, see + systemd-system.conf5. + + + + + modules_load= + rd.modules_load= + + + Load a specific kernel module early at boot. For + details, see + systemd-modules-load.service8. + + + + + resume= + resumeflags= + + + Enables resume from hibernation using the specified + device and mount options. All + fstab5-like + paths are supported. For details, see + systemd-hibernate-resume-generator8. + + + + + systemd.firstboot= + + Takes a boolean argument, defaults to on. If off, + systemd-firstboot.service8 + will not query the user for basic system settings, even if the system boots up for the first time and the + relevant settings are not initialized yet. + + + + + + + See Also + + systemd1, + systemd-system.conf5, + bootparam7, + dracut.cmdline7, + systemd-debug-generator8, + systemd-fsck@.service8, + systemd-quotacheck.service8, + systemd-journald.service8, + systemd-vconsole-setup.service8, + systemd-udevd.service8, + plymouth8, + systemd-cryptsetup-generator8, + systemd-veritysetup-generator8, + systemd-fstab-generator8, + systemd-gpt-auto-generator8, + systemd-volatile-root.service8, + systemd-modules-load.service8, + systemd-backlight@.service8, + systemd-rfkill.service8, + systemd-hibernate-resume-generator8, + systemd-firstboot.service8, + bootctl1 + + + + diff --git a/man/kernel-install.xml b/man/kernel-install.xml new file mode 100644 index 00000000..34bb5d2f --- /dev/null +++ b/man/kernel-install.xml @@ -0,0 +1,240 @@ + + + + + + + + kernel-install + systemd + + + + kernel-install + 8 + + + + kernel-install + Add and remove kernel and initramfs images to and from /boot + + + + + kernel-install + COMMAND + OPTIONS + KERNEL-VERSION + KERNEL-IMAGE + INITRD-FILE + + + + + Description + kernel-install is used to install and remove kernel and initramfs images to and + from the boot loader partition, referred to as $BOOT here. It will usually be one of + /boot, /efi, or /boot/efi, see below. + + + kernel-install will execute the files + located in the directory /usr/lib/kernel/install.d/ + and the local administration directory /etc/kernel/install.d/. + All files are collectively sorted and executed in lexical order, regardless of the directory in + which they live. However, files with identical filenames replace each other. + Files in /etc/kernel/install.d/ take precedence over files with the same name + in /usr/lib/kernel/install.d/. This can be used to override a system-supplied + executables with a local file if needed; a symbolic link in /etc/kernel/install.d/ + with the same name as an executable in /usr/lib/kernel/install.d/, + pointing to /dev/null, disables the executable entirely. Executables must have the + extension .install; other extensions are ignored. + + An executable should return 0 on success. It may also + return 77 to cause the whole operation to terminate + (executables later in lexical order will be skipped). + + + + Commands + The following commands are understood: + + + add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE ...] + + This command expects a kernel version string and a path to a kernel image file as + arguments. kernel-install calls the executables from + /usr/lib/kernel/install.d/*.install and + /etc/kernel/install.d/*.install with the following arguments: + + add KERNEL-VERSION $BOOT/MACHINE-ID/KERNEL-VERSION/ KERNEL-IMAGE [INITRD-FILE ...] + + + Three default plugins execute the following operations in this case: + + + 00-entry-directory.install creates the directory + $BOOT/MACHINE-ID/KERNEL-VERSION/ + if $BOOT/MACHINE-ID/ already exists. + + + 50-depmod.install runs + depmod8 for the + KERNEL-VERSION. + + 90-loaderentry.install copies KERNEL-IMAGE + to + $BOOT/MACHINE-ID/KERNEL-VERSION/linux. + If an INITRD-FILE is provided, it also copies INITRD-FILE + to + $BOOT/MACHINE-ID/KERNEL_VERSION/INITRD-FILE. + It also creates a boot loader entry according to the Boot Loader Specification in + $BOOT/loader/entries/MACHINE-ID-KERNEL-VERSION.conf. + The title of the entry is the PRETTY_NAME parameter specified in + /etc/os-release or /usr/lib/os-release (if the former is + missing), or "Linux KERNEL-VERSION", if unset. + + If the entry directory + $BOOT/MACHINE-ID/KERNEL-VERSION/ + does not exist, this plugin does nothing. + + + + + remove KERNEL-VERSION + + This command expects a kernel version string as single argument. This calls executables from + /usr/lib/kernel/install.d/*.install and + /etc/kernel/install.d/*.install with the following arguments: + + remove KERNEL-VERSION $BOOT/MACHINE-ID/KERNEL-VERSION/ + + + Afterwards, kernel-install removes the directory + $BOOT/MACHINE-ID/KERNEL-VERSION/ + and its contents. + + Two default plugins execute the following operations in this case: + + + + 50-depmod.install removes the files generated by depmod for this kernel again. + + 90-loaderentry.install removes the file + $BOOT/loader/entries/MACHINE-ID-KERNEL-VERSION.conf. + + + + + + + + + + The <varname>$BOOT</varname> partition + The partition where the kernels and Boot + Loader Specification snippets are located is called $BOOT. + kernel-install determines the location of this partition by checking + /efi/, /boot/, and /boot/efi + in turn. The first location where $BOOT/loader/entries/ or + $BOOT/$MACHINE_ID/ exists is used. + + + + Options + The following options are understood: + + + + + + + Output additional information about operations being performed. + + + + + + + + + Environment variables + If is used, $KERNEL_INSTALL_VERBOSE=1 will be set for + the plugins. They may output additional logs in this case. + + + + Exit status + If every executable returns 0 or 77, 0 is returned, and a non-zero failure code otherwise. + + + + Files + + + + /usr/lib/kernel/install.d/*.install + /etc/kernel/install.d/*.install + + + Drop-in files which are executed by kernel-install. + + + + + /etc/kernel/cmdline + /proc/cmdline + + + Read by 90-loaderentry.install. The content of the file + /etc/kernel/cmdline specifies the kernel command line to use. If that file does not + exist, /proc/cmdline is used. + + + + + /etc/kernel/tries + + + Read by 90-loaderentry.install. If this file exists a numeric value is read from + it and the naming of the generated entry file is slightly altered to include it as + $BOOT/loader/entries/MACHINE-ID-KERNEL-VERSION+TRIES.conf. This + is useful for boot loaders such as + systemd-boot7 which + implement boot attempt counting with a counter embedded in the entry file name. + + + + + /etc/machine-id + + + The content of the file specifies the machine identification MACHINE-ID. + + + + + /etc/os-release + /usr/lib/os-release + + + The content of the file specifies the operating system title PRETTY_NAME. + + + + + + + See Also + + machine-id5, + os-release5, + depmod8, + systemd-boot7, + Boot Loader Specification + + + + diff --git a/man/less-variables.xml b/man/less-variables.xml new file mode 100644 index 00000000..08e513c9 --- /dev/null +++ b/man/less-variables.xml @@ -0,0 +1,97 @@ + + + + + + Environment + + + + $SYSTEMD_PAGER + + Pager to use when is not given; overrides + $PAGER. If neither $SYSTEMD_PAGER nor $PAGER are set, a + set of well-known pager implementations are tried in turn, including + less1 and + more1, until one is found. If + no pager implementation is discovered no pager is invoked. Setting this environment variable to an empty string + or the value cat is equivalent to passing . + + + + $SYSTEMD_LESS + + Override the options passed to less (by default + FRSXMK). + + Users might want to change two options in particular: + + + + + + This option instructs the pager to exit immediately when + CtrlC is pressed. To allow + less to handle CtrlC + itself to switch back to the pager command prompt, unset this option. + + If the value of $SYSTEMD_LESS does not include K, + and the pager that is invoked is less, + CtrlC will be ignored by the + executable, and needs to be handled by the pager. + + + + + + This option instructs the pager to not send termcap initialization and deinitialization + strings to the terminal. It is set by default to allow command output to remain visible in the + terminal even after the pager exits. Nevertheless, this prevents some pager functionality from + working, in particular paged output cannot be scrolled with the mouse. + + + + See + less1 + for more discussion. + + + + $SYSTEMD_LESSCHARSET + + Override the charset passed to less (by default utf-8, if + the invoking terminal is determined to be UTF-8 compatible). + + + + $SYSTEMD_COLORS + + The value must be a boolean. Controls whether colorized output should be + generated. This can be specified to override the decision that systemd makes based + on $TERM and what the console is connected to. + + + + + + + $SYSTEMD_URLIFY + + The value must be a boolean. Controls whether clickable links should be generated in + the output for terminal emulators supporting this. This can be specified to override the decision that + systemd makes based on $TERM and other conditions. + + + + + diff --git a/man/libsystemd-pkgconfig.xml b/man/libsystemd-pkgconfig.xml new file mode 100644 index 00000000..e378c4dd --- /dev/null +++ b/man/libsystemd-pkgconfig.xml @@ -0,0 +1,13 @@ + + + + + + Notes + + These APIs are implemented as a shared + library, which can be compiled and linked to with the + libsystemd pkg-config1 + file. + diff --git a/man/libudev.xml b/man/libudev.xml new file mode 100644 index 00000000..c35bc292 --- /dev/null +++ b/man/libudev.xml @@ -0,0 +1,96 @@ + + +%entities; +]> + + + + + + libudev + systemd + + + + libudev + 3 + + + + libudev + API for enumerating and introspecting local devices + + + + + #include <libudev.h> + + + + pkg-config --cflags --libs libudev + + + + + Description + + libudev.h provides APIs to introspect + and enumerate devices on the local system. + + All functions require a libudev context to operate. This + context can be create via + udev_new3. + It is used to track library state and link objects together. No + global state is used by libudev, everything is always linked to + a udev context. + + + + To introspect a local device on a system, a udev device + object can be created via + udev_device_new_from_syspath3 + and friends. The device object allows one to query current state, + read and write attributes and lookup properties of the device in + question. + + To enumerate local devices on the system, an enumeration + object can be created via + udev_enumerate_new3. + + To monitor the local system for hotplugged or unplugged + devices, a monitor can be created via + udev_monitor_new_from_netlink3. + + Whenever libudev returns a list of objects, the + udev_list_entry3 + API should be used to iterate, access and modify those lists. + + Furthermore, libudev also exports legacy APIs that should + not be used by new software (and as such are not documented as + part of this manual). This includes the hardware database known + as udev_hwdb (please use the new + sd-hwdb3 + API instead) and the udev_queue object to + query the udev daemon (which should not be used by new software + at all). + + + + See Also + + udev_new3, + udev_device_new_from_syspath3, + udev_enumerate_new3, + udev_monitor_new_from_netlink3, + udev_list_entry3, + systemd1, + sd-device3, + sd-hwdb3, + pkg-config1 + + + + diff --git a/man/loader.conf.xml b/man/loader.conf.xml new file mode 100644 index 00000000..14f84c13 --- /dev/null +++ b/man/loader.conf.xml @@ -0,0 +1,203 @@ + + + + + + + loader.conf + systemd + + + + loader.conf + 5 + + + + loader.conf + Configuration file for systemd-boot + + + + ESP/loader/loader.conf, + ESP/loader/entries/*.conf + + + + + Description + + + systemd-boot7 + will read ESP/loader/loader.conf and any files with the + .conf extension under + ESP/loader/entries/ on the EFI system partition (ESP). + + + Each configuration file must consist of an option name, followed by + whitespace, and the option value. # may be used to start + a comment line. Empty and comment lines are ignored. + + Boolean arguments may be written as + yes/y/true/1 or + no/n/false/0. + + + + + Options + + The following configuration options in loader.conf are understood: + + + + default + + A glob pattern to select the default entry. The default entry + may be changed in the boot menu itself, in which case the name of the + selected entry will be stored as an EFI variable, overriding this option. + + + + + timeout + + How long the boot menu should be shown before the default + entry is booted, in seconds. This may be changed in the boot menu itself and + will be stored as an EFI variable in that case, overriding this option. + + + If the timeout is disabled, the default entry will be booted + immediately. The menu can be shown by pressing and holding a key before + systemd-boot is launched. + + + + + console-mode + + This option configures the resolution of the console. Takes a + number or one of the special values listed below. The following values may be + used: + + + + 0 + + Standard UEFI 80x25 mode + + + + + 1 + + 80x50 mode, not supported by all devices + + + + + 2 + + the first non-standard mode provided by the device + firmware, if any + + + + + auto + + Pick a suitable mode automatically using heuristics + + + + + max + + Pick the highest-numbered available mode + + + + + keep + + Keep the mode selected by firmware (the default) + + + + + + + + + editor + + Takes a boolean argument. Enable (the default) or disable the + editor. The editor should be disabled if the machine can be accessed by + unauthorized persons. + + + + auto-entries + + Takes a boolean argument. Enable (the default) or disable + entries for other boot entries found on the boot partition. In particular, + this may be useful when loader entries are created to show replacement + descriptions for those entries. + + + + auto-firmware + + Takes a boolean argument. Enable (the default) or disable + the "Reboot into firmware" entry. + + + + random-seed-mode + + Takes one of off, with-system-token and + always. If off no random seed data is read off the ESP, nor + passed to the OS. If with-system-token (the default) + systemd-boot will read a random seed from the ESP (from the file + /loader/random-seed) only if the LoaderSystemToken EFI + variable is set, and then derive the random seed to pass to the OS from the combination. If + always the boot loader will do so even if LoaderSystemToken is + not set. This mode is useful in environments where protection against OS image reuse is not a + concern, and the random seed shall be used even with no further setup in place. User bootctl + random-seed to initialize both the random seed file in the ESP and the system token EFI + variable. + + See Random Seeds for further + information. + + + + + + Example + + # /boot/efi/loader/loader.conf +timeout 0 +default 01234567890abcdef1234567890abdf0-* +editor no + + + The menu will not be shown by default (the menu can still be shown by + pressing and holding a key during boot). One of the entries with files with a + name starting with 01234567890abcdef1234567890abdf0- will be + selected by default. If more than one entry matches, the one with the highest + priority will be selected (generally the one with the highest version number). + The editor will be disabled, so it is not possible to alter the kernel command + line. + + + + See Also + + systemd-boot7, + bootctl1 + + + diff --git a/man/locale.conf.xml b/man/locale.conf.xml new file mode 100644 index 00000000..a92cf50a --- /dev/null +++ b/man/locale.conf.xml @@ -0,0 +1,127 @@ + + + + + + + locale.conf + systemd + + + + locale.conf + 5 + + + + locale.conf + Configuration file for locale settings + + + + /etc/locale.conf + + + + Description + + The /etc/locale.conf file configures + system-wide locale settings. It is read at early boot by + systemd1. + + The basic file format of locale.conf is + a newline-separated list of environment-like shell-compatible + variable assignments. It is possible to source the configuration + from shell scripts, however, beyond mere variable assignments, no + shell features are supported, allowing applications to read the + file without implementing a shell compatible execution + engine. + + Note that the kernel command line options + locale.LANG=, + locale.LANGUAGE=, + locale.LC_CTYPE=, + locale.LC_NUMERIC=, + locale.LC_TIME=, + locale.LC_COLLATE=, + locale.LC_MONETARY=, + locale.LC_MESSAGES=, + locale.LC_PAPER=, + locale.LC_NAME=, + locale.LC_ADDRESS=, + locale.LC_TELEPHONE=, + locale.LC_MEASUREMENT=, + locale.LC_IDENTIFICATION= may be + used to override the locale settings at boot. + + The locale settings configured in + /etc/locale.conf are system-wide and are + inherited by every service or user, unless overridden or unset by + individual programs or individual users. + + Depending on the operating system, other configuration files + might be checked for locale configuration as well, however only as + fallback. + + /etc/locale.conf is usually created and updated + using + systemd-localed.service8. + localectl1 + may be used to alter the settings in this file during runtime from + the command line. Use + systemd-firstboot1 + to initialize them on mounted (but not booted) system images. + + + + Options + + The following locale settings may be set using + /etc/locale.conf: + LANG=, + LANGUAGE=, + LC_CTYPE=, + LC_NUMERIC=, + LC_TIME=, + LC_COLLATE=, + LC_MONETARY=, + LC_MESSAGES=, + LC_PAPER=, + LC_NAME=, + LC_ADDRESS=, + LC_TELEPHONE=, + LC_MEASUREMENT=, + LC_IDENTIFICATION=. + Note that LC_ALL may not be configured in this + file. For details about the meaning and semantics of these + settings, refer to + locale7. + + + + Example + + + German locale with English messages + + /etc/locale.conf: + + LANG=de_DE.UTF-8 +LC_MESSAGES=en_US.UTF-8 + + + + + + See Also + + systemd1, + locale7, + localectl1, + systemd-localed.service8, + systemd-firstboot1 + + + + diff --git a/man/localectl.xml b/man/localectl.xml new file mode 100644 index 00000000..5efb5fec --- /dev/null +++ b/man/localectl.xml @@ -0,0 +1,209 @@ + + + + + + + + localectl + systemd + + + + localectl + 1 + + + + localectl + Control the system locale and keyboard layout settings + + + + + localectl + OPTIONS + COMMAND + + + + + Description + + localectl may be used to query and change + the system locale and keyboard layout settings. It communicates with + systemd-localed8 + to modify files such as /etc/locale.conf and + /etc/vconsole.conf. + + The system locale controls the language settings of system + services and of the UI before the user logs in, such as the + display manager, as well as the default for users after + login. + + The keyboard settings control the keyboard layout used on + the text console and of the graphical UI before the user logs in, + such as the display manager, as well as the default for users + after login. + + Note that the changes performed using this tool might require + the initramfs to be rebuilt to take effect during early system boot. + The initramfs is not rebuilt automatically by localectl. + + + Note that + systemd-firstboot1 + may be used to initialize the system locale for mounted (but not booted) + system images. + + + + Commands + + The following commands are understood: + + + + status + + Show current settings of the system locale and keyboard mapping. + If no command is specified, this is the implied default. + + + + set-locale LOCALE + set-locale VARIABLE=LOCALE… + + Set the system locale. This takes one locale such as en_US.UTF-8, or takes one or more + locale assignments such as LANG=de_DE.utf8, LC_MESSAGES=en_GB.utf8, and so on. If + one locale without variable name is provided, then LANG= locale variable will be set. See + locale7 + for details on the available settings and their meanings. Use + list-locales for a list of available + locales (see below). + + + + list-locales + + List available locales useful for + configuration with + set-locale. + + + + set-keymap MAP [TOGGLEMAP] + + Set the system keyboard mapping for the + console and X11. This takes a mapping name (such as "de" or + "us"), and possibly a second one to define a toggle keyboard + mapping. Unless is passed, the + selected setting is also applied as the default system + keyboard mapping of X11, after converting it to the closest + matching X11 keyboard mapping. Use + list-keymaps for a list of available + keyboard mappings (see below). + + + + list-keymaps + + List available keyboard mappings for the + console, useful for configuration with + set-keymap. + + + + set-x11-keymap LAYOUT [MODEL [VARIANT [OPTIONS]]] + + Set the system default keyboard mapping for + X11 and the virtual console. This takes a keyboard mapping + name (such as de or us), + and possibly a model, variant, and options, see + kbd4 + for details. Unless is passed, + the selected setting is also applied as the system console + keyboard mapping, after converting it to the closest matching + console keyboard mapping. + + + + list-x11-keymap-models + list-x11-keymap-layouts + list-x11-keymap-variants [LAYOUT] + list-x11-keymap-options + + List available X11 keymap models, layouts, + variants and options, useful for configuration with + set-keymap. The command + list-x11-keymap-variants optionally takes a + layout parameter to limit the output to the variants suitable + for the specific layout. + + + + + + + Options + + The following options are understood: + + + + + + Do not query the user for authentication for + privileged operations. + + + + + + If set-keymap or + set-x11-keymap is invoked and this option + is passed, then the keymap will not be converted from the + console to X11, or X11 to console, + respectively. + + + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + + + See Also + + systemd1, + locale7, + locale.conf5, + vconsole.conf5, + loadkeys1, + kbd4, + + The XKB Configuration Guide + , + systemctl1, + systemd-localed.service8, + systemd-firstboot1, + mkinitrd8 + + + + diff --git a/man/localtime.xml b/man/localtime.xml new file mode 100644 index 00000000..0f1652ee --- /dev/null +++ b/man/localtime.xml @@ -0,0 +1,69 @@ + + + + + + + localtime + systemd + + + + localtime + 5 + + + + localtime + Local timezone configuration file + + + + /etc/localtime -> ../usr/share/zoneinfo/… + + + + Description + + The /etc/localtime file configures the + system-wide timezone of the local system that is used by + applications for presentation to the user. It should be an + absolute or relative symbolic link pointing to + /usr/share/zoneinfo/, followed by a timezone + identifier such as Europe/Berlin or + Etc/UTC. The resulting link should lead to the + corresponding binary + tzfile5 + timezone data for the configured timezone. + + Because the timezone identifier is extracted from the + symlink target name of /etc/localtime, this + file may not be a normal file or hardlink. + + The timezone may be overridden for individual programs by + using the $TZ environment variable. See + environ7. + + You may use + timedatectl1 + to change the settings of this file from the command line during + runtime. Use + systemd-firstboot1 + to initialize the time zone on mounted (but not booted) system + images. + + + + See Also + + systemd1, + tzset3, + localtime3, + timedatectl1, + systemd-timedated.service8, + systemd-firstboot1 + + + + diff --git a/man/loginctl.xml b/man/loginctl.xml new file mode 100644 index 00000000..05a4c75c --- /dev/null +++ b/man/loginctl.xml @@ -0,0 +1,429 @@ + + + + + + + + loginctl + systemd + + + + loginctl + 1 + + + + loginctl + Control the systemd login manager + + + + + loginctl + OPTIONS + COMMAND + NAME + + + + + Description + + loginctl may be used to introspect and + control the state of the + systemd1 + login manager + systemd-logind.service8. + + + + Commands + + The following commands are understood: + + Session Commands + + + list-sessions + + List current sessions. + + + + session-status ID… + + Show terse runtime status information about + one or more sessions, followed by the most recent log data + from the journal. Takes one or more session identifiers as + parameters. If no session identifiers are passed, the status of + the caller's session is shown. This function is intended to + generate human-readable output. If you are looking for + computer-parsable output, use show-session + instead. + + + + show-session ID… + + Show properties of one or more sessions or the + manager itself. If no argument is specified, properties of the + manager will be shown. If a session ID is specified, + properties of the session are shown. By default, empty + properties are suppressed. Use to show + those too. To select specific properties to show, use + . This command is intended to be + used whenever computer-parsable output is required. Use + session-status if you are looking for + formatted human-readable output. + + + + activate ID + + Activate a session. This brings a session into + the foreground if another session is currently in the + foreground on the respective seat. Takes a session identifier + as argument. If no argument is specified, the session of the + caller is put into foreground. + + + + lock-session ID… + unlock-session ID… + + Activates/deactivates the screen lock on one + or more sessions, if the session supports it. Takes one or + more session identifiers as arguments. If no argument is + specified, the session of the caller is locked/unlocked. + + + + + lock-sessions + unlock-sessions + + Activates/deactivates the screen lock on all + current sessions supporting it. + + + + terminate-session ID… + + Terminates a session. This kills all processes + of the session and deallocates all resources attached to the + session. + + + + kill-session ID… + + Send a signal to one or more processes of the + session. Use to select which + process to kill. Use to select the + signal to send. + + + + User Commands + + list-users + + List currently logged in users. + + + + + user-status USER… + + Show terse runtime status information about + one or more logged in users, followed by the most recent log + data from the journal. Takes one or more user names or numeric + user IDs as parameters. If no parameters are passed, the status + is shown for the user of the session of the caller. This + function is intended to generate human-readable output. If you + are looking for computer-parsable output, use + show-user instead. + + + + show-user USER… + + Show properties of one or more users or the + manager itself. If no argument is specified, properties of the + manager will be shown. If a user is specified, properties of + the user are shown. By default, empty properties are + suppressed. Use to show those too. To + select specific properties to show, use + . This command is intended to be + used whenever computer-parsable output is required. Use + user-status if you are looking for + formatted human-readable output. + + + + enable-linger USER… + disable-linger USER… + + Enable/disable user lingering for one or more + users. If enabled for a specific user, a user manager is + spawned for the user at boot and kept around after logouts. + This allows users who are not logged in to run long-running + services. Takes one or more user names or numeric UIDs as + argument. If no argument is specified, enables/disables + lingering for the user of the session of the caller. + + See also KillUserProcesses= setting in + logind.conf5. + + + + + terminate-user USER… + + Terminates all sessions of a user. This kills + all processes of all sessions of the user and deallocates all + runtime resources attached to the user. + + + + kill-user USER… + + Send a signal to all processes of a user. Use + to select the signal to send. + + + + + Seat Commands + + list-seats + + List currently available seats on the local + system. + + + + seat-status NAME… + + Show terse runtime status information about + one or more seats. Takes one or more seat names as parameters. + If no seat names are passed the status of the caller's + session's seat is shown. This function is intended to generate + human-readable output. If you are looking for + computer-parsable output, use show-seat + instead. + + + + show-seat NAME… + + Show properties of one or more seats or the + manager itself. If no argument is specified, properties of the + manager will be shown. If a seat is specified, properties of + the seat are shown. By default, empty properties are + suppressed. Use to show those too. To + select specific properties to show, use + . This command is intended to be + used whenever computer-parsable output is required. Use + seat-status if you are looking for + formatted human-readable output. + + + + attach NAME DEVICE… + + Persistently attach one or more devices to a + seat. The devices should be specified via device paths in the + /sys file system. To create a new seat, + attach at least one graphics card to a previously unused seat + name. Seat names may consist only of a–z, A–Z, 0–9, + - and _ and must be + prefixed with seat. To drop assignment of a + device to a specific seat, just reassign it to a different + seat, or use flush-devices. + + + + + flush-devices + + Removes all device assignments previously + created with attach. After this call, only + automatically generated seats will remain, and all seat + hardware is assigned to them. + + + + terminate-seat NAME… + + Terminates all sessions on a seat. This kills + all processes of all sessions on the seat and deallocates all + runtime resources attached to them. + + + + + + + Options + + The following options are understood: + + + + + + Do not query the user for authentication for + privileged operations. + + + + + + + When showing session/user/seat properties, + limit display to certain properties as specified as argument. + If not specified, all set properties are shown. The argument + should be a property name, such as + Sessions. If specified more than once, all + properties with the specified names are + shown. + + + + + + When showing session/user/seat properties, + only print the value, and skip the property name and + =. + + + + + + + When showing session/user/seat properties, + show all properties regardless of whether they are set or + not. + + + + + + + Do not ellipsize process tree entries. + + + + + + + When used with + kill-session, choose which processes to + kill. Must be one of , or + to select whether to kill only the leader + process of the session or all processes of the session. If + omitted, defaults to . + + + + + + + When used with kill-session + or kill-user, choose which signal to send + to selected processes. Must be one of the well known signal + specifiers, such as SIGTERM, + SIGINT or SIGSTOP. + If omitted, defaults to + SIGTERM. + + + + + + + When used with user-status + and session-status, controls the number of + journal lines to show, counting from the most recent ones. + Takes a positive integer argument. Defaults to 10. + + + + + + + + When used with user-status + and session-status, controls the formatting + of the journal entries that are shown. For the available + choices, see + journalctl1. + Defaults to short. + + + + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + Examples + + + Querying user status + + $ loginctl user-status +fatima (1005) + Since: Sat 2016-04-09 14:23:31 EDT; 54min ago + State: active + Sessions: 5 *3 + Unit: user-1005.slice + ├─user@1005.service + … + ├─session-3.scope + … + └─session-5.scope + ├─3473 login -- fatima + └─3515 -zsh + +Apr 09 14:40:30 laptop login[2325]: pam_unix(login:session): + session opened for user fatima by LOGIN(uid=0) +Apr 09 14:40:30 laptop login[2325]: LOGIN ON tty3 BY fatima + + + There are two sessions, 3 and 5. Session 3 is a graphical session, + marked with a star. The tree of processing including the two corresponding + scope units and the user manager unit are shown. + + + + + + + See Also + + systemd1, + systemctl1, + systemd-logind.service8, + logind.conf5 + + + + diff --git a/man/logind.conf.xml b/man/logind.conf.xml new file mode 100644 index 00000000..4cbfd09c --- /dev/null +++ b/man/logind.conf.xml @@ -0,0 +1,346 @@ + + +%entities; +]> + + + + + logind.conf + systemd + + + + logind.conf + 5 + + + + logind.conf + logind.conf.d + Login manager configuration files + + + + /etc/systemd/logind.conf + /etc/systemd/logind.conf.d/*.conf + /run/systemd/logind.conf.d/*.conf + /usr/lib/systemd/logind.conf.d/*.conf + + + + Description + + These files configure various parameters of the systemd login manager, + systemd-logind.service8. See + systemd.syntax5 + for a general description of the syntax. + + + + + + Options + + All options are configured in the + [Login] section: + + + + + NAutoVTs= + + Takes a positive integer. Configures how many + virtual terminals (VTs) to allocate by default that, when + switched to and are previously unused, + autovt services are automatically spawned + on. These services are instantiated from the template unit + autovt@.service for the respective VT TTY + name, for example, autovt@tty4.service. + By default, autovt@.service is linked to + getty@.service. In other words, login + prompts are started dynamically as the user switches to unused + virtual terminals. Hence, this parameter controls how many + login gettys are available on the VTs. If a + VT is already used by some other subsystem (for example, a + graphical login), this kind of activation will not be + attempted. Note that the VT configured in + ReserveVT= is always subject to this kind + of activation, even if it is not one of the VTs configured + with the NAutoVTs= directive. Defaults to + 6. When set to 0, automatic spawning of + autovt services is + disabled. + + + + ReserveVT= + + Takes a positive integer. Identifies one + virtual terminal that shall unconditionally be reserved for + autovt@.service activation (see above). + The VT selected with this option will be marked busy + unconditionally, so that no other subsystem will allocate it. + This functionality is useful to ensure that, regardless of how + many VTs are allocated by other subsystems, one login + getty is always available. Defaults to 6 + (in other words, there will always be a + getty available on Alt-F6.). When set to 0, + VT reservation is disabled. + + + + KillUserProcesses= + + Takes a boolean argument. Configures whether the processes of a + user should be killed when the user logs out. If true, the scope unit + corresponding to the session and all processes inside that scope will be + terminated. If false, the scope is "abandoned", see + systemd.scope5, + and processes are not killed. Defaults to &KILL_USER_PROCESSES;, + but see the options KillOnlyUsers= and + KillExcludeUsers= below. + + In addition to session processes, user process may run under the user + manager unit user@.service. Depending on the linger + settings, this may allow users to run processes independent of their login + sessions. See the description of enable-linger in + loginctl1. + + + Note that setting KillUserProcesses=yes + will break tools like + screen1 + and + tmux1, + unless they are moved out of the session scope. See example in + systemd-run1. + + + + + KillOnlyUsers= + KillExcludeUsers= + + These settings take space-separated lists of usernames that override + the KillUserProcesses= setting. A user name may be added to + KillExcludeUsers= to exclude the processes in the session scopes of + that user from being killed even if KillUserProcesses=yes is set. If + KillExcludeUsers= is not set, the root user is + excluded by default. KillExcludeUsers= may be set to an empty value + to override this default. If a user is not excluded, KillOnlyUsers= + is checked next. If this setting is specified, only the session scopes of those users + will be killed. Otherwise, users are subject to the + KillUserProcesses=yes setting. + + + + IdleAction= + + Configures the action to take when the system + is idle. Takes one of + ignore, + poweroff, + reboot, + halt, + kexec, + suspend, + hibernate, + hybrid-sleep, + suspend-then-hibernate, and + lock. + Defaults to ignore. + + Note that this requires that user sessions correctly + report the idle status to the system. The system will execute + the action after all sessions report that they are idle, no + idle inhibitor lock is active, and subsequently, the time + configured with IdleActionSec= (see below) + has expired. + + + + + IdleActionSec= + + Configures the delay after which the action + configured in IdleAction= (see above) is + taken after the system is idle. + + + + InhibitDelayMaxSec= + + Specifies the maximum time a system shutdown + or sleep request is delayed due to an inhibitor lock of type + delay being active before the inhibitor is + ignored and the operation executes anyway. Defaults to + 5. + + + + UserStopDelaySec= + + Specifies how long to keep the user record and per-user service + user@.service around for a user after they logged out fully. If set to zero, the per-user + service is terminated immediately when the last session of the user has ended. If this option is configured to + non-zero rapid logout/login cycles are sped up, as the user's service manager is not constantly restarted. If + set to infinity the per-user service for a user is never terminated again after first login, + and continues to run until system shutdown. Defaults to 10s. + + + + HandlePowerKey= + HandleSuspendKey= + HandleHibernateKey= + HandleLidSwitch= + HandleLidSwitchExternalPower= + HandleLidSwitchDocked= + + Controls how logind shall handle the + system power and sleep keys and the lid switch to trigger + actions such as system power-off or suspend. Can be one of + ignore, + poweroff, + reboot, + halt, + kexec, + suspend, + hibernate, + hybrid-sleep, + suspend-then-hibernate, and + lock. + If ignore, logind will never handle these + keys. If lock, all running sessions will be + screen-locked; otherwise, the specified action will be taken + in the respective event. Only input devices with the + power-switch udev tag will be watched for + key/lid switch events. HandlePowerKey= + defaults to poweroff. + HandleSuspendKey= and + HandleLidSwitch= default to + suspend. + HandleLidSwitchExternalPower= is completely + ignored by default (for backwards compatibility) — an explicit + value must be set before it will be used to determine + behaviour. HandleLidSwitchDocked= defaults + to ignore. + HandleHibernateKey= defaults to + hibernate. If the system is inserted in a + docking station, or if more than one display is connected, the + action specified by HandleLidSwitchDocked= + occurs; if the system is on external power the action (if any) + specified by HandleLidSwitchExternalPower= + occurs; otherwise the HandleLidSwitch= + action occurs. + + A different application may disable logind's handling of system power and + sleep keys and the lid switch by taking a low-level inhibitor lock + (handle-power-key, handle-suspend-key, + handle-hibernate-key, handle-lid-switch). + This is most commonly used by graphical desktop environments + to take over suspend and hibernation handling, and to use their own configuration + mechanisms. If a low-level inhibitor lock is taken, logind will not take any + action when that key or switch is triggered and the Handle*= + settings are irrelevant. + + + + PowerKeyIgnoreInhibited= + SuspendKeyIgnoreInhibited= + HibernateKeyIgnoreInhibited= + LidSwitchIgnoreInhibited= + + Controls whether actions that systemd-logind + takes when the power and sleep keys and the lid switch are triggered are subject + to high-level inhibitor locks ("shutdown", "sleep", "idle"). Low level inhibitor + locks (handle-power-key, handle-suspend-key, + handle-hibernate-key, handle-lid-switch), + are always honored, irrespective of this setting. + + These settings take boolean arguments. If no, the + inhibitor locks taken by applications are respected. If yes, + "shutdown", "sleep", and "idle" inhibitor locks are ignored. + PowerKeyIgnoreInhibited=, + SuspendKeyIgnoreInhibited=, and + HibernateKeyIgnoreInhibited= default to no. + LidSwitchIgnoreInhibited= defaults to yes. + This means that when systemd-logind is handling events by + itself (no low level inhibitor locks are taken by another application), the lid + switch does not respect suspend blockers by default, but the power and sleep keys + do. + + + + HoldoffTimeoutSec= + + Specifies the timeout after system startup or + system resume in which systemd will hold off on reacting to + lid events. This is required for the system to properly + detect any hotplugged devices so systemd can ignore lid events + if external monitors, or docks, are connected. If set to 0, + systemd will always react immediately, possibly before the + kernel fully probed all hotplugged devices. This is safe, as + long as you do not care for systemd to account for devices + that have been plugged or unplugged while the system was off. + Defaults to 30s. + + + + RuntimeDirectorySize= + + Sets the size limit on the + $XDG_RUNTIME_DIR runtime directory for each + user who logs in. Takes a size in bytes, optionally suffixed + with the usual K, G, M, and T suffixes, to the base 1024 + (IEC). Alternatively, a numerical percentage suffixed by + % may be specified, which sets the size + limit relative to the amount of physical RAM. Defaults to 10%. + Note that this size is a safety limit only. As each runtime + directory is a tmpfs file system, it will only consume as much + memory as is needed. + + + + InhibitorsMax= + + Controls the maximum number of concurrent inhibitors to permit. Defaults to 8192 + (8K). + + + + SessionsMax= + + Controls the maximum number of concurrent user sessions to manage. Defaults to 8192 + (8K). Depending on how the pam_systemd.so module is included in the PAM stack + configuration, further login sessions will either be refused, or permitted but not tracked by + systemd-logind. + + + + RemoveIPC= + + Controls whether System V and POSIX IPC objects belonging to the user shall be removed when the + user fully logs out. Takes a boolean argument. If enabled, the user may not consume IPC resources after the + last of the user's sessions terminated. This covers System V semaphores, shared memory and message queues, as + well as POSIX shared memory and message queues. Note that IPC objects of the root user and other system users + are excluded from the effect of this setting. Defaults to yes. + + + + + + + See Also + + systemd1, + systemd-logind.service8, + loginctl1, + systemd-system.conf5 + + + + diff --git a/man/machine-id.xml b/man/machine-id.xml new file mode 100644 index 00000000..ebee065a --- /dev/null +++ b/man/machine-id.xml @@ -0,0 +1,169 @@ + + + + + + + machine-id + systemd + + + + machine-id + 5 + + + + machine-id + Local machine ID configuration file + + + + /etc/machine-id + + + + Description + + The /etc/machine-id file contains the unique machine ID of + the local system that is set during installation or boot. The machine ID is a single + newline-terminated, hexadecimal, 32-character, lowercase ID. When decoded from + hexadecimal, this corresponds to a 16-byte/128-bit value. This ID may not be all + zeros. + + The machine ID is usually generated from a random source during system + installation or first boot and stays constant for all subsequent boots. Optionally, + for stateless systems, it is generated during runtime during early boot if necessary. + + + The machine ID may be set, for example when network booting, with the + systemd.machine_id= kernel command line parameter or by passing the + option to systemd. An ID is specified in this manner + has higher priority and will be used instead of the ID stored in + /etc/machine-id. + + The machine ID does not change based on local or network configuration or when + hardware is replaced. Due to this and its greater length, it is a more useful + replacement for the + gethostid3 + call that POSIX specifies. + + This machine ID adheres to the same format and logic as the + D-Bus machine ID. + + This ID uniquely identifies the host. It should be considered "confidential", and must not be exposed in + untrusted environments, in particular on the network. If a stable unique identifier that is tied to the machine is + needed for some application, the machine ID or any part of it must not be used directly. Instead the machine ID + should be hashed with a cryptographic, keyed hash function, using a fixed, application-specific key. That way the + ID will be properly unique, and derived in a constant way from the machine ID but there will be no way to retrieve + the original machine ID from the application-specific one. The + sd_id128_get_machine_app_specific3 + API provides an implementation of such an algorithm. + + + + Initialization + + Each machine should have a non-empty ID in normal operation. The ID of each + machine should be unique. To achieve those objectives, + /etc/machine-id can be initialized in a few different ways. + + + For normal operating system installations, where a custom image is created for a + specific machine, /etc/machine-id should be populated during + installation. + + + systemd-machine-id-setup1 + may be used by installer tools to initialize the machine ID at install time, but + /etc/machine-id may also be written using any other means. + + + For operating system images which are created once and used on multiple + machines, for example for containers or in the cloud, + /etc/machine-id should be an empty file in the generic file + system image. An ID will be generated during boot and saved to this file if + possible. Having an empty file in place is useful because it allows a temporary file + to be bind-mounted over the real file, in case the image is used read-only. + + systemd-firstboot1 + may be used to initialize /etc/machine-id on mounted (but not + booted) system images. + + When a machine is booted with + systemd1 + the ID of the machine will be established. If systemd.machine_id= + or options (see first section) are specified, this + value will be used. Otherwise, the value in /etc/machine-id will + be used. If this file is empty or missing, systemd will attempt + to use the D-Bus machine ID from /var/lib/dbus/machine-id, the + value of the kernel command line option container_uuid, the KVM DMI + product_uuid or the devicetree vm,uuid + (on KVM systems), and finally a randomly generated UUID. + + After the machine ID is established, + systemd1 + will attempt to save it to /etc/machine-id. If this fails, it + will attempt to bind-mount a temporary file over /etc/machine-id. + It is an error if the file system is read-only and does not contain a (possibly empty) + /etc/machine-id file. + + systemd-machine-id-commit.service8 + will attempt to write the machine ID to the file system if + /etc/machine-id or /etc are read-only during + early boot but become writable later on. + + + + Relation to OSF UUIDs + + Note that the machine ID historically is not an OSF UUID as + defined by RFC + 4122, nor a Microsoft GUID; however, starting with systemd + v30, newly generated machine IDs do qualify as v4 UUIDs. + + In order to maintain compatibility with existing + installations, an application requiring a UUID should decode the + machine ID, and then apply the following operations to turn it + into a valid OSF v4 UUID. With id being an + unsigned character array: + + /* Set UUID version to 4 --- truly random generation */ +id[6] = (id[6] & 0x0F) | 0x40; +/* Set the UUID variant to DCE */ +id[8] = (id[8] & 0x3F) | 0x80; + + (This code is inspired by + generate_random_uuid() of + drivers/char/random.c from the Linux kernel + sources.) + + + + + History + + The simple configuration file format of + /etc/machine-id originates in the + /var/lib/dbus/machine-id file introduced by + D-Bus. In fact, this latter file might be a symlink to + /etc/machine-id. + + + + See Also + + systemd1, + systemd-machine-id-setup1, + gethostid3, + hostname5, + machine-info5, + os-release5, + sd-id1283, + sd_id128_get_machine3, + systemd-firstboot1 + + + + diff --git a/man/machine-info.xml b/man/machine-info.xml new file mode 100644 index 00000000..4fb27abe --- /dev/null +++ b/man/machine-info.xml @@ -0,0 +1,159 @@ + + + + + + + machine-info + systemd + + + + machine-info + 5 + + + + machine-info + Local machine information file + + + + /etc/machine-info + + + + Description + + The /etc/machine-info file contains + machine metadata. + + The basic file format of machine-info + is a newline-separated list of environment-like shell-compatible + variable assignments. It is possible to source the configuration + from shell scripts, however, beyond mere variable assignments no + shell features are supported, allowing applications to read the + file without implementing a shell compatible execution + engine. + + /etc/machine-info contains metadata + about the machine that is set by the user or administrator. + + Depending on the operating system other configuration files + might be checked for machine information as well, however only as + fallback. + + You may use + hostnamectl1 + to change the settings of this file from the command line. + + + + Options + + The following machine metadata parameters may be set using + /etc/machine-info: + + + + + PRETTY_HOSTNAME= + + A pretty human-readable UTF-8 machine + identifier string. This should contain a name like + Lennart's Laptop which is useful to present + to the user and does not suffer by the syntax limitations of + internet domain names. If possible, the internet hostname as + configured in /etc/hostname should be + kept similar to this one. Example: if this value is + Lennart's Computer an Internet hostname of + lennarts-computer might be a good choice. + If this parameter is not set, an application should fall back + to the Internet host name for presentation + purposes. + + + + ICON_NAME= + + An icon identifying this machine according to + the XDG + Icon Naming Specification. If this parameter is not + set, an application should fall back to + computer or a similar icon + name. + + + + CHASSIS= + + The chassis type. Currently, the following + chassis types are defined: + desktop, + laptop, + convertible, + server, + tablet, + handset, + watch, and + embedded, + as well as the special chassis types + vm and + container for + virtualized systems that lack an immediate physical chassis. + Note that many systems allow detection of the chassis type + automatically (based on firmware information or suchlike). + This setting (if set) shall take precedence over automatically + detected information and is useful to override misdetected + configuration or to manually configure the chassis type where + automatic detection is not available. + + + + DEPLOYMENT= + + Describes the system deployment environment. + One of the following is suggested: + development, + integration, + staging, + production. + + + + + LOCATION= + + Describes the system location if applicable + and known. Takes a human-friendly, free-form string. This may + be as generic as Berlin, Germany or as + specific as Left Rack, 2nd Shelf. + + + + + + + Example + + PRETTY_HOSTNAME="Lennart's Tablet" +ICON_NAME=computer-tablet +CHASSIS=tablet +DEPLOYMENT=production + + + + See Also + + systemd1, + os-release5, + hostname5, + machine-id5, + hostnamectl1, + systemd-hostnamed.service8 + + + + diff --git a/man/machinectl.xml b/man/machinectl.xml new file mode 100644 index 00000000..e1a2da30 --- /dev/null +++ b/man/machinectl.xml @@ -0,0 +1,1007 @@ + + + + + + + + machinectl + systemd + + + + machinectl + 1 + + + + machinectl + Control the systemd machine manager + + + + + machinectl + OPTIONS + COMMAND + NAME + + + + + Description + + machinectl may be used to introspect and + control the state of the + systemd1 + virtual machine and container registration manager + systemd-machined.service8. + + machinectl may be used to execute + operations on machines and images. Machines in this sense are + considered running instances of: + + + Virtual Machines (VMs) that virtualize hardware + to run full operating system (OS) instances (including their kernels) + in a virtualized environment on top of the host OS. + + Containers that share the hardware and + OS kernel with the host OS, in order to run + OS userspace instances on top the host OS. + + The host system itself. + + + Machines are identified by names that follow the same rules + as UNIX and DNS host names. For details, see below. + + Machines are instantiated from disk or file system images that + frequently — but not necessarily — carry the same name as machines running + from them. Images in this sense may be: + + + Directory trees containing an OS, including the + top-level directories /usr, + /etc, and so on. + + btrfs subvolumes containing OS trees, similar to regular directory trees. + + Binary "raw" disk image files containing MBR or GPT partition tables and Linux file + systems. + + Similarly, block devices containing MBR or GPT partition tables and file systems. + + The file system tree of the host OS itself. + + + + + + Commands + + The following commands are understood: + + Machine Commands + + + list + + List currently running (online) virtual + machines and containers. To enumerate machine images that can + be started, use list-images (see + below). Note that this command hides the special + .host machine by default. Use the + switch to show it. + + + + status NAME… + + Show runtime status information about + one or more virtual machines and containers, followed by the + most recent log data from the journal. This function is + intended to generate human-readable output. If you are looking + for computer-parsable output, use show + instead. Note that the log data shown is reported by the + virtual machine or container manager, and frequently contains + console output of the machine, but not necessarily journal + contents of the machine itself. + + + + show [NAME…] + + Show properties of one or more registered virtual machines or containers or the manager + itself. If no argument is specified, properties of the manager will be shown. If a NAME is specified, + properties of this virtual machine or container are shown. By default, empty properties are suppressed. Use + to show those too. To select specific properties to show, use + . This command is intended to be used whenever computer-parsable output is + required, and does not print the control group tree or journal entries. Use status if you + are looking for formatted human-readable output. + + + + start NAME… + + Start a container as a system service, using + systemd-nspawn1. + This starts systemd-nspawn@.service, + instantiated for the specified machine name, similar to the + effect of systemctl start on the service + name. systemd-nspawn looks for a container + image by the specified name in + /var/lib/machines/ (and other search + paths, see below) and runs it. Use + list-images (see below) for listing + available container images to start. + + Note that + systemd-machined.service8 + also interfaces with a variety of other container and VM + managers, systemd-nspawn is just one + implementation of it. Most of the commands available in + machinectl may be used on containers or VMs + controlled by other managers, not just + systemd-nspawn. Starting VMs and container + images on those managers requires manager-specific + tools. + + To interactively start a container on the command line + with full access to the container's console, please invoke + systemd-nspawn directly. To stop a running + container use machinectl poweroff. + + + + login [NAME] + + Open an interactive terminal login session in + a container or on the local host. If an argument is supplied, + it refers to the container machine to connect to. If none is + specified, or the container name is specified as the empty + string, or the special machine name .host + (see below) is specified, the connection is made to the local + host instead. This will create a TTY connection to a specific + container or the local host and asks for the execution of a + getty on it. Note that this is only supported for containers + running + systemd1 + as init system. + + This command will open a full login prompt on the + container or the local host, which then asks for username and + password. Use shell (see below) or + systemd-run1 + with the switch to directly invoke + a single command, either interactively or in the + background. + + + + shell [[NAME@]NAME [PATH [ARGUMENTS…]]] + + Open an interactive shell session in a + container or on the local host. The first argument refers to + the container machine to connect to. If none is specified, or + the machine name is specified as the empty string, or the + special machine name .host (see below) is + specified, the connection is made to the local host + instead. This works similar to login but + immediately invokes a user process. This command runs the + specified executable with the specified arguments, or the + default shell for the user if none is specified, or + /bin/sh if no default shell is found. By default, + , or by prefixing the machine name with + a username and an @ character, a different + user may be selected. Use to set + environment variables for the executed process. + + Note that machinectl shell does not propagate the exit code/status of the invoked + shell process. Use systemd-run instead if that information is required (see below). + + When using the shell command without + arguments, (thus invoking the executed shell or command on the + local host), it is in many ways similar to a su1 + session, but, unlike su, completely isolates + the new session from the originating session, so that it + shares no process or session properties, and is in a clean and + well-defined state. It will be tracked in a new utmp, login, + audit, security and keyring session, and will not inherit any + environment variables or resource limits, among other + properties. + + Note that systemd-run1 + with its switch may be used in place of the machinectl shell + command, and allows non-interactive operation, more detailed and low-level configuration of the invoked unit, + as well as access to runtime and exit code/status information of the invoked shell process. In particular, use + systemd-run's switch to propagate exit status information of the + invoked process. Use systemd-run's switch for acquiring an + interactive shell, similar to machinectl shell. In general, systemd-run + is preferable for scripting purposes. However, note that systemd-run might require higher + privileges than machinectl shell. + + + + enable NAME… + disable NAME… + + Enable or disable a container as a system + service to start at system boot, using + systemd-nspawn1. + This enables or disables + systemd-nspawn@.service, instantiated for + the specified machine name, similar to the effect of + systemctl enable or systemctl + disable on the service name. + + + + poweroff NAME… + + Power off one or more containers. This will + trigger a reboot by sending SIGRTMIN+4 to the container's init + process, which causes systemd-compatible init systems to shut + down cleanly. Use stop as alias for poweroff. + This operation does not work on containers that do not run a + systemd1-compatible + init system, such as sysvinit. Use + terminate (see below) to immediately + terminate a container or VM, without cleanly shutting it + down. + + + + reboot NAME… + + Reboot one or more containers. This will + trigger a reboot by sending SIGINT to the container's init + process, which is roughly equivalent to pressing Ctrl+Alt+Del + on a non-containerized system, and is compatible with + containers running any system manager. + + + + terminate NAME… + + Immediately terminates a virtual machine or + container, without cleanly shutting it down. This kills all + processes of the virtual machine or container and deallocates + all resources attached to that instance. Use + poweroff to issue a clean shutdown + request. + + + + kill NAME… + + Send a signal to one or more processes of the + virtual machine or container. This means processes as seen by + the host, not the processes inside the virtual machine or + container. Use to select which + process to kill. Use to select the + signal to send. + + + + bind NAME PATH [PATH] + + Bind mounts a file or directory from the host into the specified container. The first path + argument is the source file or directory on the host, the second path argument is the destination file or + directory in the container. When the latter is omitted, the destination path in the container is the same as + the source path on the host. When combined with the switch, a ready-only bind + mount is created. When combined with the switch, the destination path is first created + before the mount is applied. Note that this option is currently only supported for + systemd-nspawn1 containers, + and only if user namespacing () is not used. This command supports bind + mounting directories, regular files, device nodes, AF_UNIX socket nodes, as well as + FIFOs. + + + + copy-to NAME PATH [PATH] + + Copies files or directories from the host + system into a running container. Takes a container name, + followed by the source path on the host and the destination + path in the container. If the destination path is omitted, the + same as the source path is used. + + If host and container share the same user and group namespace, file ownership by numeric user ID and + group ID is preserved for the copy, otherwise all files and directories in the copy will be owned by the root + user and group (UID/GID 0). + + + + copy-from NAME PATH [PATH] + + Copies files or directories from a container + into the host system. Takes a container name, followed by the + source path in the container the destination path on the host. + If the destination path is omitted, the same as the source path + is used. + + If host and container share the same user and group namespace, file ownership by numeric user ID and + group ID is preserved for the copy, otherwise all files and directories in the copy will be owned by the root + user and group (UID/GID 0). + + + + Image Commands + + + list-images + + Show a list of locally installed container and + VM images. This enumerates all raw disk images and container + directories and subvolumes in + /var/lib/machines/ (and other search + paths, see below). Use start (see above) to + run a container off one of the listed images. Note that, by + default, containers whose name begins with a dot + (.) are not shown. To show these too, + specify . Note that a special image + .host always implicitly exists and refers + to the image the host itself is booted from. + + + + image-status [NAME…] + + Show terse status information about one or + more container or VM images. This function is intended to + generate human-readable output. Use + show-image (see below) to generate + computer-parsable output instead. + + + + show-image [NAME…] + + Show properties of one or more registered + virtual machine or container images, or the manager itself. If + no argument is specified, properties of the manager will be + shown. If a NAME is specified, properties of this virtual + machine or container image are shown. By default, empty + properties are suppressed. Use to show + those too. To select specific properties to show, use + . This command is intended to be + used whenever computer-parsable output is required. Use + image-status if you are looking for + formatted human-readable output. + + + + clone NAME NAME + + Clones a container or VM image. The arguments specify the name of the image to clone and the + name of the newly cloned image. Note that plain directory container images are cloned into btrfs subvolume + images with this command, if the underlying file system supports this. Note that cloning a container or VM + image is optimized for file systems that support copy-on-write, and might not be efficient on others, due to + file system limitations. + + Note that this command leaves host name, machine ID and + all other settings that could identify the instance + unmodified. The original image and the cloned copy will hence + share these credentials, and it might be necessary to manually + change them in the copy. + + If combined with the switch a read-only cloned image is + created. + + + + rename NAME NAME + + Renames a container or VM image. The + arguments specify the name of the image to rename and the new + name of the image. + + + + read-only NAME [BOOL] + + Marks or (unmarks) a container or VM image + read-only. Takes a VM or container image name, followed by a + boolean as arguments. If the boolean is omitted, positive is + implied, i.e. the image is marked read-only. + + + + remove NAME… + + Removes one or more container or VM images. + The special image .host, which refers to + the host's own directory tree, may not be + removed. + + + + set-limit [NAME] BYTES + + Sets the maximum size in bytes that a specific + container or VM image, or all images, may grow up to on disk + (disk quota). Takes either one or two parameters. The first, + optional parameter refers to a container or VM image name. If + specified, the size limit of the specified image is changed. If + omitted, the overall size limit of the sum of all images stored + locally is changed. The final argument specifies the size + limit in bytes, possibly suffixed by the usual K, M, G, T + units. If the size limit shall be disabled, specify + - as size. + + Note that per-container size limits are only supported on btrfs file systems. + + + + clean + + Remove hidden VM or container images (or all). This command removes all hidden machine images + from /var/lib/machines, i.e. those whose name begins with a dot. Use machinectl + list-images --all to see a list of all machine images, including the hidden ones. + + When combined with the switch removes all images, not just hidden ones. This + command effectively empties /var/lib/machines. + + Note that commands such as machinectl pull-tar or machinectl + pull-raw usually create hidden, read-only, unmodified machine images from the downloaded image first, + before cloning a writable working copy of it, in order to avoid duplicate downloads in case of images that are + reused multiple times. Use machinectl clean to remove old, hidden images created this + way. + + + + + Image Transfer Commands + + + pull-tar URL [NAME] + + Downloads a .tar + container image from the specified URL, and makes it available + under the specified local machine name. The URL must be of + type http:// or + https://, and must refer to a + .tar, .tar.gz, + .tar.xz or .tar.bz2 + archive file. If the local machine name is omitted, it + is automatically derived from the last component of the URL, + with its suffix removed. + + The image is verified before it is made available, unless + is specified. + Verification is done either via an inline signed file with the name + of the image and the suffix .sha256 or via + separate SHA256SUMS and + SHA256SUMS.gpg files. + The signature files need to be made available on the same web + server, under the same URL as the .tar file. + With , only the SHA256 checksum + for the file is verified, based on the .sha256 + suffixed file or the SHA256SUMS file. + With , the sha checksum file is + first verified with the inline signature in the + .sha256 file or the detached GPG signature file + SHA256SUMS.gpg. + The public key for this verification step needs to be available in + /usr/lib/systemd/import-pubring.gpg or + /etc/systemd/import-pubring.gpg. + + The container image will be downloaded and stored in a + read-only subvolume in + /var/lib/machines/ that is named after + the specified URL and its HTTP etag. A writable snapshot is + then taken from this subvolume, and named after the specified + local name. This behavior ensures that creating multiple + container instances of the same URL is efficient, as multiple + downloads are not necessary. In order to create only the + read-only image, and avoid creating its writable snapshot, + specify - as local machine name. + + Note that the read-only subvolume is prefixed with + .tar-, and is thus not shown by + list-images, unless + is passed. + + Note that pressing C-c during execution of this command + will not abort the download. Use + cancel-transfer, described + below. + + + + pull-raw URL [NAME] + + Downloads a .raw + container or VM disk image from the specified URL, and makes + it available under the specified local machine name. The URL + must be of type http:// or + https://. The container image must either + be a .qcow2 or raw disk image, optionally + compressed as .gz, + .xz, or .bz2. If the + local machine name is omitted, it is automatically + derived from the last component of the URL, with its suffix + removed. + + Image verification is identical for raw and tar images + (see above). + + If the downloaded image is in + .qcow2 format it is converted into a raw + image file before it is made available. + + Downloaded images of this type will be placed as + read-only .raw file in + /var/lib/machines/. A local, writable + (reflinked) copy is then made under the specified local + machine name. To omit creation of the local, writable copy + pass - as local machine name. + + Similar to the behavior of pull-tar, + the read-only image is prefixed with + .raw-, and thus not shown by + list-images, unless + is passed. + + Note that pressing C-c during execution of this command + will not abort the download. Use + cancel-transfer, described + below. + + + + import-tar FILE [NAME] + import-raw FILE [NAME] + Imports a TAR or RAW container or VM image, + and places it under the specified name in + /var/lib/machines/. When + import-tar is used, the file specified as + the first argument should be a tar archive, possibly compressed + with xz, gzip or bzip2. It will then be unpacked into its own + subvolume in /var/lib/machines. When + import-raw is used, the file should be a + qcow2 or raw disk image, possibly compressed with xz, gzip or + bzip2. If the second argument (the resulting image name) is + not specified, it is automatically derived from the file + name. If the filename is passed as -, the + image is read from standard input, in which case the second + argument is mandatory. + + Optionally, the switch may be used to create a read-only container or VM + image. No cryptographic validation is done when importing the images. + + Much like image downloads, ongoing imports may be listed + with list-transfers and aborted with + cancel-transfer. + + + + import-fs DIRECTORY [NAME] + + Imports a container image stored in a local directory into + /var/lib/machines/, operates similar to import-tar or + import-raw, but the first argument is the source directory. If supported, this command will + create btrfs snapshot or subvolume for the new image. + + + + export-tar NAME [FILE] + export-raw NAME [FILE] + Exports a TAR or RAW container or VM image and + stores it in the specified file. The first parameter should be + a VM or container image name. The second parameter should be a + file path the TAR or RAW image is written to. If the path ends + in .gz, the file is compressed with gzip, if + it ends in .xz, with xz, and if it ends in + .bz2, with bzip2. If the path ends in + neither, the file is left uncompressed. If the second argument + is missing, the image is written to standard output. The + compression may also be explicitly selected with the + switch. This is in particular + useful if the second parameter is left unspecified. + + Much like image downloads and imports, ongoing exports + may be listed with list-transfers and + aborted with + cancel-transfer. + + Note that, currently, only directory and subvolume images + may be exported as TAR images, and only raw disk images as RAW + images. + + + + list-transfers + + Shows a list of container or VM image + downloads, imports and exports that are currently in + progress. + + + + cancel-transfer ID… + + Aborts a download, import or export of the + container or VM image with the specified ID. To list ongoing + transfers and their IDs, use + list-transfers. + + + + + + + + Options + + The following options are understood: + + + + + + + When showing machine or image properties, + limit the output to certain properties as specified by the + argument. If not specified, all set properties are shown. The + argument should be a property name, such as + Name. If specified more than once, all + properties with the specified names are + shown. + + + + + + + When showing machine or image properties, show + all properties regardless of whether they are set or + not. + + When listing VM or container images, do not suppress + images beginning in a dot character + (.). + + When cleaning VM or container images, remove all images, not just hidden ones. + + + + + + When printing properties with show, only print the value, + and skip the property name and =. + + + + + + + Do not ellipsize process tree entries. + + + + + + + When used with kill, choose + which processes to kill. Must be one of + , or to select + whether to kill only the leader process of the machine or all + processes of the machine. If omitted, defaults to + . + + + + + + + When used with kill, choose + which signal to send to selected processes. Must be one of the + well-known signal specifiers, such as + SIGTERM, SIGINT or + SIGSTOP. If omitted, defaults to + SIGTERM. + + + + + + When used with the shell command, chooses the user ID to + open the interactive shell session as. If the argument to the shell + command also specifies a user name, this option is ignored. If the name is not specified + in either way, root will be used by default. Note that this switch is + not supported for the login command (see below). + + + + + + + When used with the shell command, sets an environment + variable to pass to the executed shell. Takes an environment variable name and value, + separated by =. This switch may be used multiple times to set multiple + environment variables. Note that this switch is not supported for the + login command (see below). + + + + + + When used with bind, creates the destination file or directory before + applying the bind mount. Note that even though the name of this option suggests that it is suitable only for + directories, this option also creates the destination file node to mount over if the object to mount is not + a directory, but a regular file, device node, socket or FIFO. + + + + + + When used with bind, creates a read-only bind mount. + + When used with clone, import-raw or import-tar a + read-only container or VM image is created. + + + + + + + When used with status, + controls the number of journal lines to show, counting from + the most recent ones. Takes a positive integer argument. + Defaults to 10. + + + + + + + + When used with status, + controls the formatting of the journal entries that are shown. + For the available choices, see + journalctl1. + Defaults to short. + + + + + + When downloading a container or VM image, + specify whether the image shall be verified before it is made + available. Takes one of no, + checksum and signature. + If no, no verification is done. If + checksum is specified, the download is + checked for integrity after the transfer is complete, but no + signatures are verified. If signature is + specified, the checksum is verified and the image's signature + is checked against a local keyring of trustable vendors. It is + strongly recommended to set this option to + signature if the server and protocol + support this. Defaults to + signature. + + + + + + When downloading a container or VM image, and + a local copy by the specified local machine name already + exists, delete it first and replace it by the newly downloaded + image. + + + + + + When used with the + or commands, specifies the + compression format to use for the resulting file. Takes one of + uncompressed, xz, + gzip, bzip2. By default, + the format is determined automatically from the image file + name passed. + + + + + + When used with the + command, limits the number of ip addresses output for every machine. + Defaults to 1. All addresses can be requested with all + as argument to . If the argument to + is less than the actual number + of addresses, ...follows the last address. + If multiple addresses are to be written for a given machine, every + address except the first one is on a new line and is followed by + , if another address will be output afterwards. + + + + + + + Suppresses additional informational output while running. + + + + + + + + + Connect to + systemd-machined.service8 + running in a local container, to perform the specified operation within + the container. + + + + + + + + + + + + Machine and Image Names + + The machinectl tool operates on machines + and images whose names must be chosen following strict + rules. Machine names must be suitable for use as host names + following a conservative subset of DNS and UNIX/Linux + semantics. Specifically, they must consist of one or more + non-empty label strings, separated by dots. No leading or trailing + dots are allowed. No sequences of multiple dots are allowed. The + label strings may only consist of alphanumeric characters as well + as the dash and underscore. The maximum length of a machine name + is 64 characters. + + A special machine with the name .host + refers to the running host system itself. This is useful for execution + operations or inspecting the host system as well. Note that + machinectl list will not show this special + machine unless the switch is specified. + + Requirements on image names are less strict, however, they must be + valid UTF-8, must be suitable as file names (hence not be the + single or double dot, and not include a slash), and may not + contain control characters. Since many operations search for an + image by the name of a requested machine, it is recommended to name + images in the same strict fashion as machines. + + A special image with the name .host + refers to the image of the running host system. It hence + conceptually maps to the special .host machine + name described above. Note that machinectl + list-images will not show this special image either, unless + is specified. + + + + Files and Directories + + Machine images are preferably stored in + /var/lib/machines/, but are also searched for + in /usr/local/lib/machines/ and + /usr/lib/machines/. For compatibility reasons, + the directory /var/lib/container/ is + searched, too. Note that images stored below + /usr are always considered read-only. It is + possible to symlink machines images from other directories into + /var/lib/machines/ to make them available for + control with machinectl. + + Note that some image operations are only supported, efficient or atomic on btrfs file systems. + + Disk images are understood by + systemd-nspawn1 + and machinectl in three formats: + + + A simple directory tree, containing the files + and directories of the container to boot. + + Subvolumes (on btrfs file systems), which are + similar to the simple directories, described above. However, + they have additional benefits, such as efficient cloning and + quota reporting. + + "Raw" disk images, i.e. binary images of disks + with a GPT or MBR partition table. Images of this type are + regular files with the suffix + .raw. + + + See + systemd-nspawn1 + for more information on image formats, in particular its + and + options. + + + + Examples + + Download an Ubuntu image and open a shell in it + + # machinectl pull-tar https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-root.tar.gz +# systemd-nspawn -M trusty-server-cloudimg-amd64-root + + This downloads and verifies the specified + .tar image, and then uses + systemd-nspawn1 + to open a shell in it. + + + + Download a Fedora image, set a root password in it, start + it as service + + # machinectl pull-raw --verify=no https://dl.fedoraproject.org/pub/fedora/linux/releases/27/CloudImages/x86_64/images/Fedora-Cloud-Base-27-1.6.x86_64.raw.xz +# systemd-nspawn -M Fedora-Cloud-Base-27-1.6.x86_64 +# passwd +# exit +# machinectl start Fedora-Cloud-Base-27-1.6.x86_64 +# machinectl login Fedora-Cloud-Base-27-1.6.x86_64 + + This downloads the specified .raw + image with verification disabled. Then, a shell is opened in it + and a root password is set. Afterwards the shell is left, and + the machine started as system service. With the last command a + login prompt into the container is requested. + + + + Exports a container image as tar file + + # machinectl export-tar fedora myfedora.tar.xz + + Exports the container fedora as an + xz-compressed tar file myfedora.tar.xz into the + current directory. + + + + Create a new shell session + + # machinectl shell --uid=lennart + + This creates a new shell session on the local host for + the user ID lennart, in a su1-like + fashion. + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + + + See Also + + systemd1, + systemd-machined.service8, + systemd-nspawn1, + systemd.special7, + tar1, + xz1, + gzip1, + bzip21 + + + + diff --git a/man/man.in b/man/man.in new file mode 100755 index 00000000..75680b86 --- /dev/null +++ b/man/man.in @@ -0,0 +1,16 @@ +#!/bin/sh +set -e + +if [ -z "$1" ]; then + echo "Use: $0 page-name (with no section suffix)" + exit 1 +fi + +page="$(echo "$1" | sed 's/\./\\./')" +target=$(ninja -C "@BUILD_ROOT@" -t query man/man | grep -E -m1 "man/$page\.[0-9]$" | awk '{print $2}') +if [ -z "$target" ]; then + echo "Cannot find page $1" + exit 1 +fi +ninja -C "@BUILD_ROOT@" "$target" +exec man "@BUILD_ROOT@/$target" diff --git a/man/meson.build b/man/meson.build new file mode 100644 index 00000000..8021aded --- /dev/null +++ b/man/meson.build @@ -0,0 +1,217 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +# This is lame, I know, but meson has no other include mechanism +subdir('rules') + +want_man = get_option('man') +want_html = get_option('html') +xsltproc = find_program('xsltproc', + required : want_man == 'true' or want_html == 'true') +want_man = want_man != 'false' and xsltproc.found() +want_html = want_html != 'false' and xsltproc.found() + +xsltproc_flags = [ + '--nonet', + '--xinclude', + '--maxdepth', '9000', + '--stringparam', 'man.output.quietly', '1', + '--stringparam', 'funcsynopsis.style', 'ansi', + '--stringparam', 'man.authors.section.enabled', '0', + '--stringparam', 'man.copyright.section.enabled', '0', + '--stringparam', 'systemd.version', '@0@'.format(meson.project_version()), + '--path', + '@0@:@1@'.format(meson.current_build_dir(), meson.current_source_dir())] + +custom_man_xsl = files('custom-man.xsl') +custom_html_xsl = files('custom-html.xsl') +xslt_cmd = [xsltproc, '-o', '@OUTPUT0@'] + xsltproc_flags + +custom_entities_ent = configure_file( + input : 'custom-entities.ent.in', + output : 'custom-entities.ent', + configuration : conf) + +man_pages = [] +html_pages = [] +source_xml_files = [] +foreach tuple : xsltproc.found() ? manpages : [] + stem = tuple[0] + section = tuple[1] + aliases = tuple[2] + condition = tuple[3] + + xml = stem + '.xml' + html = stem + '.html' + man = stem + '.' + section + + manaliases = [] + htmlaliases = [] + foreach alias : aliases + manaliases += alias + '.' + section + htmlaliases += alias + '.html' + endforeach + + mandirn = join_paths(get_option('mandir'), 'man' + section) + + if condition == '' or conf.get(condition) == 1 + p1 = custom_target( + man, + input : xml, + output : [man] + manaliases, + command : xslt_cmd + [custom_man_xsl, '@INPUT@'], + depend_files : custom_entities_ent, + install : want_man, + install_dir : mandirn) + man_pages += p1 + + p2 = [] + foreach htmlalias : htmlaliases + link = custom_target( + htmlalias, + output : htmlalias, + command : ['ln', '-fs', html, '@OUTPUT@']) + if want_html + dst = join_paths(docdir, 'html', htmlalias) + cmd = 'ln -fs @0@ $DESTDIR@1@'.format(html, dst) + meson.add_install_script('sh', '-c', cmd) + p2 += link + endif + html_pages += link + endforeach + + p3 = custom_target( + html, + input : xml, + output : html, + command : xslt_cmd + [custom_html_xsl, '@INPUT@'], + depend_files : custom_entities_ent, + depends : p2, + install : want_html, + install_dir : join_paths(docdir, 'html')) + html_pages += p3 + + source_xml_files += files(tuple[0] + '.xml') + else + message('Skipping @0@.@1@ because @2@ is false'.format(stem, section, condition)) + endif +endforeach + +############################################################ + +have_lxml = run_command(xml_helper_py).returncode() == 0 +if not have_lxml + message('python-lxml not available, not making man page indices') +endif + +systemd_directives_xml = custom_target( + 'systemd.directives.xml', + input : source_xml_files, + output : 'systemd.directives.xml', + command : [make_directive_index_py, '@OUTPUT@'] + source_xml_files) + +nonindex_xml_files = source_xml_files + [systemd_directives_xml] +systemd_index_xml = custom_target( + 'systemd.index.xml', + input : nonindex_xml_files, + output : 'systemd.index.xml', + command : [make_man_index_py, '@OUTPUT@'] + nonindex_xml_files) + +foreach tuple : xsltproc.found() ? [['systemd.directives', '7', systemd_directives_xml], + ['systemd.index', '7', systemd_index_xml]] : [] + stem = tuple[0] + section = tuple[1] + xml = tuple[2] + + html = stem + '.html' + man = stem + '.' + section + + mandirn = join_paths(get_option('mandir'), 'man' + section) + + p1 = custom_target( + man, + input : xml, + output : man, + command : xslt_cmd + [custom_man_xsl, '@INPUT@'], + install : want_man and have_lxml, + install_dir : mandirn) + man_pages += p1 + + p2 = [] + if html == 'systemd.index.html' + htmlalias = 'index.html' + link = custom_target( + htmlalias, + input : p2, + output : htmlalias, + command : ['ln', '-fs', html, '@OUTPUT@']) + if want_html + dst = join_paths(docdir, 'html', htmlalias) + cmd = 'ln -fs @0@ $DESTDIR@1@'.format(html, dst) + meson.add_install_script('sh', '-c', cmd) + p2 += link + endif + html_pages += link + endif + + p3 = custom_target( + html, + input : xml, + output : html, + command : xslt_cmd + [custom_html_xsl, '@INPUT@'], + depend_files : custom_entities_ent, + depends : p2, + install : want_html and have_lxml, + install_dir : join_paths(docdir, 'html')) + html_pages += p3 +endforeach + +# Cannot use run_target because those targets are used in depends +# Also see https://github.com/mesonbuild/meson/issues/368. +man = custom_target( + 'man', + output : 'man', + depends : man_pages, + command : ['echo']) + +html = custom_target( + 'html', + output : 'html', + depends : html_pages, + command : ['echo']) + +run_target( + 'doc-sync', + depends : man_pages + html_pages, + command : ['rsync', '-rlv', + '--delete-excluded', + '--include=man', + '--include=*.html', + '--exclude=*', + '--omit-dir-times', + meson.current_build_dir(), + get_option('www-target')]) + +############################################################ + +if git.found() + custom_target( + 'update-man-rules', + output : 'update-man-rules', + command : ['sh', '-c', + 'cd @0@ && '.format(meson.build_root()) + + 'python3 @0@/tools/make-man-rules.py $(git ls-files ":/man/*.xml") >t && '.format(project_source_root) + + 'mv t @0@/rules/meson.build'.format(meson.current_source_dir())], + depend_files : custom_entities_ent) +endif + +############################################################ + +configure_file( + input : 'man.in', + output : 'man', + configuration : substs) + +configure_file( + input : 'html.in', + output : 'html', + configuration : substs) diff --git a/man/modules-load.d.xml b/man/modules-load.d.xml new file mode 100644 index 00000000..d126634e --- /dev/null +++ b/man/modules-load.d.xml @@ -0,0 +1,76 @@ + + + + + + + + modules-load.d + systemd + + + + modules-load.d + 5 + + + + modules-load.d + Configure kernel modules to load at boot + + + + /etc/modules-load.d/*.conf + /run/modules-load.d/*.conf + /usr/lib/modules-load.d/*.conf + + + + Description + + systemd-modules-load.service8 + reads files from the above directories which contain kernel + modules to load during boot in a static list. Each configuration + file is named in the style of + /etc/modules-load.d/program.conf. + Note that it is usually a better idea to rely on the automatic + module loading by PCI IDs, USB IDs, DMI IDs or similar triggers + encoded in the kernel modules themselves instead of static + configuration like this. In fact, most modern kernel modules are + prepared for automatic loading already. + + + + Configuration Format + + The configuration files should simply contain a list of + kernel module names to load, separated by newlines. Empty lines + and lines whose first non-whitespace character is # or ; are + ignored. + + + + + + Example + + /etc/modules-load.d/virtio-net.conf example: + + # Load virtio-net.ko at boot +virtio-net + + + + + See Also + + systemd1, + systemd-modules-load.service8, + systemd-delta1, + modprobe8 + + + + diff --git a/man/networkctl.xml b/man/networkctl.xml new file mode 100644 index 00000000..0502ab75 --- /dev/null +++ b/man/networkctl.xml @@ -0,0 +1,337 @@ + + + + + + + + networkctl + systemd + + + + networkctl + 1 + + + + networkctl + Query the status of network links + + + + + networkctl + OPTIONS + COMMAND + LINK + + + + + Description + + networkctl may be used to introspect the + state of the network links as seen by + systemd-networkd. Please refer to + systemd-networkd.service8 + for an introduction to the basic concepts, functionality, and + configuration syntax. + + + + Commands + + The following commands are understood: + + + + + list + PATTERN… + + + + Show a list of existing links and their status. If one ore more + PATTERNs are specified, only links matching one of them are shown. + If no further arguments are specified shows all links, + otherwise just the specified links. Produces output similar to: + + IDX LINK TYPE OPERATIONAL SETUP + 1 lo loopback carrier unmanaged + 2 eth0 ether routable configured + 3 virbr0 ether no-carrier unmanaged + 4 virbr0-nic ether off unmanaged + +4 links listed. + + The operational status is one of the following: + + + off + + the device is powered down + + + + no-carrier + + the device is powered up, but it does not yet have a carrier + + + + dormant + + the device has a carrier, but is not yet ready for normal traffic + + + + degraded-carrier + + for bond or bridge master, one of the bonding or bridge slave network interfaces is + in off, no-carrier, or dormant state + + + + carrier + + the link has a carrier, or for bond or bridge master, all bonding or bridge slave + network interfaces are enslaved to the master. + + + + degraded + + the link has carrier and addresses valid on the local link configured + + + + enslaved + + the link has carrier and is enslaved to bond or bridge master network interface + + + + routable + + the link has carrier and routable address configured + + + + + + The setup status is one of the following: + + + pending + + udev is still processing the link, we don't yet know if we will manage it + + + + failed + + networkd failed to manage the link + + + + configuring + + in the process of retrieving configuration or configuring the link + + + + configured + + link configured successfully + + + + unmanaged + + networkd is not handling the link + + + + linger + + the link is gone, but has not yet been dropped by networkd + + + + + + + + + + status + PATTERN… + + + + Show information about the specified links: type, state, kernel module driver, hardware and + IP address, configured DNS servers, etc. If one ore more PATTERNs are + specified, only links matching one of them are shown. + + When no links are specified, an overall network status is shown. Also see the option + . + + Produces output similar to: + +● State: routable + Address: 10.193.76.5 on eth0 + 192.168.122.1 on virbr0 + 169.254.190.105 on eth0 + fe80::5054:aa:bbbb:cccc on eth0 + Gateway: 10.193.11.1 (CISCO SYSTEMS, INC.) on eth0 + DNS: 8.8.8.8 + 8.8.4.4 + + + + + + + lldp + PATTERN… + + + + Show discovered LLDP (Link Layer Discovery Protocol) neighbors. If one or more + PATTERNs are specified only neighbors on those interfaces are shown. + Otherwise shows discovered neighbors on all interfaces. Note that for this feature to work, + LLDP= must be turned on for the specific interface, see + systemd.network5 for + details. + + Produces output similar to: + LINK CHASSIS ID SYSTEM NAME CAPS PORT ID PORT DESCRIPTION +enp0s25 00:e0:4c:00:00:00 GS1900 ..b........ 2 Port #2 + +Capability Flags: +o - Other; p - Repeater; b - Bridge; w - WLAN Access Point; r - Router; +t - Telephone; d - DOCSIS cable device; a - Station; c - Customer VLAN; +s - Service VLAN, m - Two-port MAC Relay (TPMR) + +1 neighbors listed. + + + + + + label + + + Show numerical address labels that can be used for address selection. + This is the same information that + ip-addrlabel8 + shows. See RFC 3484 + for a discussion of address labels. + + Produces output similar to: + Prefix/Prefixlen Label + ::/0 1 + fc00::/7 5 + fec0::/10 11 + 2002::/16 2 + 3ffe::/16 12 + 2001:10::/28 7 + 2001::/32 6 +::ffff:0.0.0.0/96 4 + ::/96 3 + ::1/128 0 + + + + + + delete + + Deletes virtual netdevs. Takes interface name or index number. + + + + + renew + + Renew dynamic configurations e.g. addresses received from DHCP server. + Takes interface name or index number. + + + + + reconfigure + + Reconfigure network interfaces. Takes interface name or index number. + + + + + reload + + Reload .netdev and .network files. + If a new .netdev file is found, then the corresponding netdev is created. + Note that even if an existing .netdev is modified or removed, + systemd-networkd does not update or remove the netdev. + If a new, modified or removed .network file is found, then all interfaces + which match the file are reconfigured. + + + + + + + Options + + The following options are understood: + + + + + + + + + + Show all links with status. + + + + + + + + + + + Show link statistics with status. + + + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code otherwise. + + + + See Also + + systemd-networkd.service8, + systemd.network5, + systemd.netdev5, + ip8 + + + diff --git a/man/networkd.conf.xml b/man/networkd.conf.xml new file mode 100644 index 00000000..2041ddd4 --- /dev/null +++ b/man/networkd.conf.xml @@ -0,0 +1,169 @@ + + + + + + + + networkd.conf + systemd + + + + networkd.conf + 5 + + + + networkd.conf + networkd.conf.d + Global Network configuration files + + + + /etc/systemd/networkd.conf + /etc/systemd/networkd.conf.d/*.conf + /usr/lib/systemd/networkd.conf.d/*.conf + + + + Description + + These configuration files control global network parameters. + Currently the DHCP Unique Identifier (DUID). + + + + + + + [Network] Section Options + + The following options are available in the [Network] section: + + + + SpeedMeter= + Takes a boolean. If set to yes, then systemd-networkd + measures the traffic of each interface, and + networkctl status INTERFACE shows the measured speed. + Defaults to no. + + + + SpeedMeterIntervalSec= + Specifies the time interval to calculate the traffic speed of each interface. + If SpeedMeter=no, the value is ignored. Defaults to 10sec. + + + + + + [DHCP] Section Options + + This section configures the DHCP Unique Identifier (DUID) value used by DHCP + protocol. DHCPv6 client protocol sends the DHCP Unique Identifier and the interface + Identity Association Identifier (IAID) to a DHCP server when acquiring a dynamic IPv6 + address. DHCPv4 client protocol sends IAID and DUID to the DHCP server when acquiring + a dynamic IPv4 address if . IAID and DUID allows + a DHCP server to uniquely identify the machine and the interface requesting a DHCP IP. + To configure IAID and ClientIdentifier, see + systemd.network5. + + + The following options are understood: + + + + DUIDType= + Specifies how the DUID should be generated. See + RFC 3315 + for a description of all the options. + + The following values are understood: + + + + If DUIDType=vendor, then the DUID value will be generated using + 43793 as the vendor identifier (systemd) and hashed contents of + machine-id5. + This is the default if DUIDType= is not specified. + + + + + + If DUIDType=uuid, and DUIDRawData= is not set, + then the product UUID is used as a DUID value. If a system does not have valid product UUID, then + an application-specific + machine-id5 + is used as a DUID value. About the application-specific machine ID, see + sd_id128_get_machine_app_specific3. + + + + + + + If link-layer-time or link-layer is specified, + then the MAC address of the interface is used as a DUID value. The value link-layer-time + can take additional time value after a colon, e.g. link-layer-time:2018-01-23 12:34:56 UTC. + The default time value is 2000-01-01 00:00:00 UTC. + + + + + + In all cases, DUIDRawData= can be used to override the + actual DUID value that is used. + + + + DUIDRawData= + Specifies the DHCP DUID value as a single newline-terminated, hexadecimal string, with each + byte separated by :. The DUID that is sent is composed of the DUID type specified by + DUIDType= and the value configured here. + + The DUID value specified here overrides the DUID that + systemd-networkd.service8 + generates from the machine ID. To configure DUID per-network, see + systemd.network5. + The configured DHCP DUID should conform to the specification in + RFC 3315, + RFC 6355. To configure IAID, see + systemd.network5 + . + + + A <option>DUIDType=vendor</option> with a custom value + + DUIDType=vendor +DUIDRawData=00:00:ab:11:f9:2a:c2:77:29:f9:5c:00 + + This specifies a 14 byte DUID, with the type DUID-EN (00:02), enterprise number + 43793 (00:00:ab:11), and identifier value f9:2a:c2:77:29:f9:5c:00. + + + + + + + + + See Also + + systemd1, + systemd.network5, + systemd-networkd.service8, + machine-id5, + sd_id128_get_machine_app_specific3 + + + + diff --git a/man/nss-myhostname.xml b/man/nss-myhostname.xml new file mode 100644 index 00000000..908c91eb --- /dev/null +++ b/man/nss-myhostname.xml @@ -0,0 +1,122 @@ + + + + + + + + nss-myhostname + systemd + + + + nss-myhostname + 8 + + + + nss-myhostname + libnss_myhostname.so.2 + Provide hostname resolution for the locally + configured system hostname. + + + + libnss_myhostname.so.2 + + + + Description + + nss-myhostname is a plug-in module for the GNU Name Service Switch (NSS) functionality of + the GNU C Library (glibc), primarily providing hostname resolution for the locally configured + system hostname as returned by + gethostname2. The precise + hostnames resolved by this module are: + + + The local, configured hostname is resolved to + all locally configured IP addresses ordered by their scope, or + — if none are configured — the IPv4 address 127.0.0.2 (which + is on the local loopback) and the IPv6 address ::1 (which is the + local host). + + The hostnames localhost and + localhost.localdomain (as well as any hostname + ending in .localhost or .localhost.localdomain) + are resolved to the IP addresses 127.0.0.1 and ::1. + + The hostname _gateway is + resolved to all current default routing gateway addresses, + ordered by their metric. This assigns a stable hostname to the + current gateway, useful for referencing it independently of the + current network configuration state. + + + Various software relies on an always-resolvable local + hostname. When using dynamic hostnames, this is traditionally + achieved by patching /etc/hosts at the same + time as changing the hostname. This is problematic since it + requires a writable /etc file system and is + fragile because the file might be edited by the administrator at + the same time. With nss-myhostname enabled, + changing /etc/hosts is unnecessary, and on + many systems, the file becomes entirely optional. + + To activate the NSS modules, add myhostname to the line starting with + hosts: in /etc/nsswitch.conf. + + It is recommended to place myhostname last in the nsswitch.conf' + hosts: line to make sure that this mapping is only used as fallback, and that any DNS or + /etc/hosts based mapping takes precedence. + + + + Example + + Here is an example /etc/nsswitch.conf file that enables + nss-myhostname correctly: + + +passwd: compat mymachines systemd +group: compat mymachines systemd +shadow: compat + +hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname +networks: files + +protocols: db files +services: db files +ethers: db files +rpc: db files + +netgroup: nis + + To test, use glibc's getent tool: + + $ getent ahosts `hostname` +::1 STREAM omega +::1 DGRAM +::1 RAW +127.0.0.2 STREAM +127.0.0.2 DGRAM +127.0.0.2 RAW + + In this case, the local hostname is omega. + + + + + See Also + + systemd1, + nss-systemd8, + nss-resolve8, + nss-mymachines8, + nsswitch.conf5, + getent1 + + + + diff --git a/man/nss-mymachines.xml b/man/nss-mymachines.xml new file mode 100644 index 00000000..40b0abee --- /dev/null +++ b/man/nss-mymachines.xml @@ -0,0 +1,160 @@ + + + + + + + + nss-mymachines + systemd + + + + nss-mymachines + 8 + + + + nss-mymachines + libnss_mymachines.so.2 + Provide hostname resolution for local + container instances. + + + + libnss_mymachines.so.2 + + + + Description + + nss-mymachines is a plug-in module for the GNU Name Service Switch (NSS) functionality of + the GNU C Library (glibc), providing hostname resolution for the names of containers running + locally that are registered with + systemd-machined.service8. The + container names are resolved to the IP addresses of the specific container, ordered by their scope. This + functionality only applies to containers using network namespacing (see the description of + in + systemd-nspawn1). + Note that the name that is resolved is the one registered with systemd-machined, which + may be different than the hostname configured inside of the container. + + The module also provides name resolution for user and group identifiers mapped to containers. All names from + the range allocated to a given container container are exposed on the host as + vu-container-uid and + vg-container-gid (see example below). This + functionality only applies to containers using user namespacing (see the description of + in + systemd-nspawn1). + + To activate the NSS module, add mymachines to the lines starting with + hosts:, passwd: and group: in + /etc/nsswitch.conf. + + It is recommended to place mymachines after the files or + compat entry of the /etc/nsswitch.conf lines to make sure that its mappings + are preferred over other resolvers such as DNS, but so that /etc/hosts, + /etc/passwd and /etc/group based mappings take precedence. + + + + Configuration in <filename>/etc/nsswitch.conf</filename> + + Here is an example /etc/nsswitch.conf file that enables + nss-mymachines correctly: + + + passwd: compat mymachines systemd +group: compat mymachines systemd +shadow: compat + +hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname +networks: files + +protocols: db files +services: db files +ethers: db files +rpc: db files + +netgroup: nis + + + + + Mappings provided by <filename>nss-mymachines</filename> + + The container rawhide is spawned using + systemd-nspawn1: + + + # systemd-nspawn -M rawhide --boot --network-veth --private-users=pick +Spawning container rawhide on /var/lib/machines/rawhide. +Selected user namespace base 20119552 and range 65536. +... + +$ machinectl --max-addresses=3 +MACHINE CLASS SERVICE OS VERSION ADDRESSES +rawhide container systemd-nspawn fedora 30 169.254.40.164 fe80::94aa:3aff:fe7b:d4b9 + +$ getent passwd vu-rawhide-0 vu-rawhide-81 +vu-rawhide-0:*:20119552:65534:vu-rawhide-0:/:/usr/sbin/nologin +vu-rawhide-81:*:20119633:65534:vu-rawhide-81:/:/usr/sbin/nologin + +$ getent group vg-rawhide-0 vg-rawhide-81 +vg-rawhide-0:*:20119552: +vg-rawhide-81:*:20119633: + +$ ps -o user:15,pid,tty,command -e|grep '^vu-rawhide' +vu-rawhide-0 692 ? /usr/lib/systemd/systemd +vu-rawhide-0 731 ? /usr/lib/systemd/systemd-journald +vu-rawhide-192 734 ? /usr/lib/systemd/systemd-networkd +vu-rawhide-193 738 ? /usr/lib/systemd/systemd-resolved +vu-rawhide-0 742 ? /usr/lib/systemd/systemd-logind +vu-rawhide-81 744 ? /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only +vu-rawhide-0 746 ? /usr/sbin/sshd -D ... +vu-rawhide-0 752 ? /usr/lib/systemd/systemd --user +vu-rawhide-0 753 ? (sd-pam) +vu-rawhide-0 1628 ? login -- zbyszek +vu-rawhide-1000 1630 ? /usr/lib/systemd/systemd --user +vu-rawhide-1000 1631 ? (sd-pam) +vu-rawhide-1000 1637 pts/8 -zsh + +$ ping -c1 rawhide +PING rawhide(fe80::94aa:3aff:fe7b:d4b9%ve-rawhide (fe80::94aa:3aff:fe7b:d4b9%ve-rawhide)) 56 data bytes +64 bytes from fe80::94aa:3aff:fe7b:d4b9%ve-rawhide (fe80::94aa:3aff:fe7b:d4b9%ve-rawhide): icmp_seq=1 ttl=64 time=0.045 ms +... +$ ping -c1 -4 rawhide +PING rawhide (169.254.40.164) 56(84) bytes of data. +64 bytes from 169.254.40.164 (169.254.40.164): icmp_seq=1 ttl=64 time=0.064 ms +... + +# machinectl shell rawhide /sbin/ip a +Connected to machine rawhide. Press ^] three times within 1s to exit session. +1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 + ... +2: host0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 + link/ether 96:aa:3a:7b:d4:b9 brd ff:ff:ff:ff:ff:ff link-netnsid 0 + inet 169.254.40.164/16 brd 169.254.255.255 scope link host0 + valid_lft forever preferred_lft forever + inet6 fe80::94aa:3aff:fe7b:d4b9/64 scope link + valid_lft forever preferred_lft forever +Connection to machine rawhide terminated. + + + + + See Also + + systemd1, + systemd-machined.service8, + machinectl1, + nss-systemd8, + nss-resolve8, + nss-myhostname8, + nsswitch.conf5, + getent1 + + + + diff --git a/man/nss-resolve.xml b/man/nss-resolve.xml new file mode 100644 index 00000000..e4ea4e18 --- /dev/null +++ b/man/nss-resolve.xml @@ -0,0 +1,92 @@ + + + + + + + + nss-resolve + systemd + + + + nss-resolve + 8 + + + + nss-resolve + libnss_resolve.so.2 + Provide hostname resolution via systemd-resolved.service + + + + libnss_resolve.so.2 + + + + Description + + nss-resolve is a plug-in module for the GNU Name Service Switch (NSS) functionality of the + GNU C Library (glibc) enabling it to resolve host names via the + systemd-resolved8 local network + name resolution service. It replaces the nss-dns plug-in module that traditionally resolves + hostnames via DNS. + + To activate the NSS module, add resolve to the line starting with + hosts: in /etc/nsswitch.conf. Specifically, it is recommended to place + resolve early in /etc/nsswitch.conf's hosts: line (but + after the files or mymachines entries), right before the + dns entry if it exists, followed by [!UNAVAIL=return], to ensure DNS queries + are always routed via + systemd-resolved8 if it is + running, but are routed to nss-dns if this service is not available. + + Note that systemd-resolved will synthesize DNS resource + records in a few cases, for example for localhost and the + current hostname, see + systemd-resolved8 + for the full list. This duplicates the functionality of + nss-myhostname8, + but it is still recommended (see examples below) to keep + nss-myhostname configured in + /etc/nsswitch.conf, to keep those names resolveable if + systemd-resolved is not running. + + + + Example + + Here is an example /etc/nsswitch.conf file that enables nss-resolve + correctly: + + +passwd: compat mymachines systemd +group: compat mymachines systemd +shadow: compat + +hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname +networks: files + +protocols: db files +services: db files +ethers: db files +rpc: db files + +netgroup: nis + + + + See Also + + systemd1, + systemd-resolved8, + nss-systemd8, + nss-myhostname8, + nss-mymachines8, + nsswitch.conf5 + + + + diff --git a/man/nss-systemd.xml b/man/nss-systemd.xml new file mode 100644 index 00000000..8fde1186 --- /dev/null +++ b/man/nss-systemd.xml @@ -0,0 +1,85 @@ + + + + + + + + nss-systemd + systemd + + + + nss-systemd + 8 + + + + nss-systemd + libnss_systemd.so.2 + Provide UNIX user and group name resolution for dynamic users and groups. + + + + libnss_systemd.so.2 + + + + Description + + nss-systemd is a plug-in module for the GNU Name Service Switch (NSS) functionality of the + GNU C Library (glibc), providing UNIX user and group name resolution for dynamic users and + groups allocated through the DynamicUser= option in systemd unit files. See + systemd.exec5 for details on + this option. + + This module also ensures that the root and nobody users and groups (i.e. the users/groups with the UIDs/GIDs + 0 and 65534) remain resolvable at all times, even if they aren't listed in /etc/passwd or + /etc/group, or if these files are missing. + + To activate the NSS module, add systemd to the lines starting with + passwd: and group: in /etc/nsswitch.conf. + + It is recommended to place systemd after the files or + compat entry of the /etc/nsswitch.conf lines so that + /etc/passwd and /etc/group based mappings take precedence. + + + + Example + + Here is an example /etc/nsswitch.conf file that enables + nss-systemd correctly: + + + passwd: compat mymachines systemd +group: compat mymachines systemd +shadow: compat + +hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname +networks: files + +protocols: db files +services: db files +ethers: db files +rpc: db files + +netgroup: nis + + + + + See Also + + systemd1, + systemd.exec5, + nss-resolve8, + nss-myhostname8, + nss-mymachines8, + nsswitch.conf5, + getent1 + + + + diff --git a/man/os-release.xml b/man/os-release.xml new file mode 100644 index 00000000..5a5e318f --- /dev/null +++ b/man/os-release.xml @@ -0,0 +1,371 @@ + + + + + + + os-release + systemd + + + + os-release + 5 + + + + os-release + Operating system identification + + + + /etc/os-release + /usr/lib/os-release + + + + Description + + The /etc/os-release and + /usr/lib/os-release files contain operating + system identification data. + + The basic file format of os-release is + a newline-separated list of environment-like shell-compatible + variable assignments. It is possible to source the configuration + from shell scripts, however, beyond mere variable assignments, no + shell features are supported (this means variable expansion is + explicitly not supported), allowing applications to read the file + without implementing a shell compatible execution engine. Variable + assignment values must be enclosed in double or single quotes if + they include spaces, semicolons or other special characters + outside of A–Z, a–z, 0–9. Shell special characters ("$", quotes, + backslash, backtick) must be escaped with backslashes, following + shell style. All strings should be in UTF-8 format, and + non-printable characters should not be used. It is not supported + to concatenate multiple individually quoted strings. Lines + beginning with "#" shall be ignored as comments. Blank lines are + permitted and ignored. + + The file /etc/os-release takes + precedence over /usr/lib/os-release. + Applications should check for the former, and exclusively use its + data if it exists, and only fall back to + /usr/lib/os-release if it is missing. + Applications should not read data from both files at the same + time. /usr/lib/os-release is the recommended + place to store OS release information as part of vendor trees. + /etc/os-release should be a relative symlink + to /usr/lib/os-release, to provide + compatibility with applications only looking at + /etc. A relative symlink instead of an + absolute symlink is necessary to avoid breaking the link in a + chroot or initrd environment such as dracut. + + os-release contains data that is + defined by the operating system vendor and should generally not be + changed by the administrator. + + As this file only encodes names and identifiers it should + not be localized. + + The /etc/os-release and + /usr/lib/os-release files might be symlinks + to other files, but it is important that the file is available + from earliest boot on, and hence must be located on the root file + system. + + For a longer rationale for os-release + please refer to the Announcement of /etc/os-release. + + + + Options + + The following OS identifications parameters may be set using + os-release: + + + + + NAME= + + A string identifying the operating system, + without a version component, and suitable for presentation to + the user. If not set, defaults to + NAME=Linux. Example: + NAME=Fedora or NAME="Debian + GNU/Linux". + + + + VERSION= + + A string identifying the operating system + version, excluding any OS name information, possibly including + a release code name, and suitable for presentation to the + user. This field is optional. Example: + VERSION=17 or VERSION="17 (Beefy + Miracle)". + + + + ID= + + A lower-case string (no spaces or other + characters outside of 0–9, a–z, ".", "_" and "-") identifying + the operating system, excluding any version information and + suitable for processing by scripts or usage in generated + filenames. If not set, defaults to + ID=linux. Example: + ID=fedora or + ID=debian. + + + + ID_LIKE= + + A space-separated list of operating system + identifiers in the same syntax as the ID= + setting. It should list identifiers of operating systems that + are closely related to the local operating system in regards + to packaging and programming interfaces, for example listing + one or more OS identifiers the local OS is a derivative from. + An OS should generally only list other OS identifiers it + itself is a derivative of, and not any OSes that are derived + from it, though symmetric relationships are possible. Build + scripts and similar should check this variable if they need to + identify the local operating system and the value of + ID= is not recognized. Operating systems + should be listed in order of how closely the local operating + system relates to the listed ones, starting with the closest. + This field is optional. Example: for an operating system with + ID=centos, an assignment of + ID_LIKE="rhel fedora" would be appropriate. + For an operating system with ID=ubuntu, an + assignment of ID_LIKE=debian is + appropriate. + + + + VERSION_CODENAME= + + + A lower-case string (no spaces or other characters outside of + 0–9, a–z, ".", "_" and "-") identifying the operating system + release code name, excluding any OS name information or + release version, and suitable for processing by scripts or + usage in generated filenames. This field is optional and may + not be implemented on all systems. + Examples: + VERSION_CODENAME=buster, + VERSION_CODENAME=xenial + + + + + VERSION_ID= + + A lower-case string (mostly numeric, no spaces + or other characters outside of 0–9, a–z, ".", "_" and "-") + identifying the operating system version, excluding any OS + name information or release code name, and suitable for + processing by scripts or usage in generated filenames. This + field is optional. Example: VERSION_ID=17 + or VERSION_ID=11.04. + + + + PRETTY_NAME= + + A pretty operating system name in a format + suitable for presentation to the user. May or may not contain + a release code name or OS version of some kind, as suitable. + If not set, defaults to + PRETTY_NAME="Linux". Example: + PRETTY_NAME="Fedora 17 (Beefy + Miracle)". + + + + ANSI_COLOR= + + A suggested presentation color when showing + the OS name on the console. This should be specified as string + suitable for inclusion in the ESC [ m ANSI/ECMA-48 escape code + for setting graphical rendition. This field is optional. + Example: ANSI_COLOR="0;31" for red, or + ANSI_COLOR="1;34" for light + blue. + + + + CPE_NAME= + + A CPE name for the operating system, in URI + binding syntax, following the + Common + Platform Enumeration Specification as proposed by the + NIST. This field is optional. Example: + CPE_NAME="cpe:/o:fedoraproject:fedora:17" + + + + + HOME_URL= + DOCUMENTATION_URL= + SUPPORT_URL= + BUG_REPORT_URL= + PRIVACY_POLICY_URL= + + Links to resources on the Internet related to + the operating system. + HOME_URL= should refer to the homepage of + the operating system, or alternatively some homepage of the + specific version of the operating system. + DOCUMENTATION_URL= should refer to the main + documentation page for this operating system. + SUPPORT_URL= should refer to the main + support page for the operating system, if there is any. This + is primarily intended for operating systems which vendors + provide support for. BUG_REPORT_URL= should + refer to the main bug reporting page for the operating system, + if there is any. This is primarily intended for operating + systems that rely on community QA. + PRIVACY_POLICY_URL= should refer to the + main privacy policy page for the operating system, if there is + any. These settings are optional, and providing only some of + these settings is common. These URLs are intended to be + exposed in "About this system" UIs behind links with captions + such as "About this Operating System", "Obtain Support", + "Report a Bug", or "Privacy Policy". The values should be in + RFC3986 + format, and should be http: or + https: URLs, and possibly + mailto: or tel:. Only + one URL shall be listed in each setting. If multiple resources + need to be referenced, it is recommended to provide an online + landing page linking all available resources. Examples: + HOME_URL="https://fedoraproject.org/" and + BUG_REPORT_URL="https://bugzilla.redhat.com/" + + + + BUILD_ID= + + A string uniquely identifying the system image + used as the origin for a distribution (it is not updated with + system updates). The field can be identical between different + VERSION_IDs as BUILD_ID is an only a unique identifier to a + specific version. Distributions that release each update as a + new version would only need to use VERSION_ID as each build is + already distinct based on the VERSION_ID. This field is + optional. Example: BUILD_ID="2013-03-20.3" + or BUILD_ID=201303203. + + + + + + VARIANT= + + + A string identifying a specific variant or edition of the + operating system suitable for presentation to the user. This + field may be used to inform the user that the configuration of + this system is subject to a specific divergent set of rules or + default configuration settings. This field is optional and may + not be implemented on all systems. + Examples: + VARIANT="Server Edition", + VARIANT="Smart Refrigerator Edition" + Note: this field is for display purposes only. The + VARIANT_ID field should be used for making + programmatic decisions. + + + + + VARIANT_ID= + + + A lower-case string (no spaces or other characters outside of + 0–9, a–z, ".", "_" and "-"), identifying a specific variant or + edition of the operating system. This may be interpreted by + other packages in order to determine a divergent default + configuration. This field is optional and may not be + implemented on all systems. + Examples: + VARIANT_ID=server, + VARIANT_ID=embedded + + + + + LOGO= + + + A string, specifying the name of an icon as defined by + freedesktop.org Icon Theme Specification. This can be + used by graphical applications to display an operating + system's or distributor's logo. This field is optional and + may not necessarily be implemented on all systems. + Examples: + LOGO=fedora-logo, + LOGO=distributor-logo-opensuse + + + + + + If you are reading this file from C code or a shell script + to determine the OS or a specific version of it, use the + ID and VERSION_ID fields, + possibly with ID_LIKE as fallback for + ID. When looking for an OS identification + string for presentation to the user use the + PRETTY_NAME field. + + Note that operating system vendors may choose not to provide + version information, for example to accommodate for rolling + releases. In this case, VERSION and + VERSION_ID may be unset. Applications should + not rely on these fields to be set. + + Operating system vendors may extend the file + format and introduce new fields. It is highly + recommended to prefix new fields with an OS specific + name in order to avoid name clashes. Applications + reading this file must ignore unknown fields. Example: + DEBIAN_BTS="debbugs://bugs.debian.org/" + + + + Example + + NAME=Fedora +VERSION="17 (Beefy Miracle)" +ID=fedora +VERSION_ID=17 +PRETTY_NAME="Fedora 17 (Beefy Miracle)" +ANSI_COLOR="0;34" +CPE_NAME="cpe:/o:fedoraproject:fedora:17" +HOME_URL="https://fedoraproject.org/" +BUG_REPORT_URL="https://bugzilla.redhat.com/" + + + + See Also + + systemd1, + lsb_release1, + hostname5, + machine-id5, + machine-info5 + + + + diff --git a/man/pam_systemd.xml b/man/pam_systemd.xml new file mode 100644 index 00000000..470c1a4c --- /dev/null +++ b/man/pam_systemd.xml @@ -0,0 +1,316 @@ + + + + + + + + pam_systemd + systemd + + + + pam_systemd + 8 + + + + pam_systemd + Register user sessions in the systemd login manager + + + + pam_systemd.so + + + + Description + + pam_systemd registers user sessions with + the systemd login manager + systemd-logind.service8, + and hence the systemd control group hierarchy. + + On login, this module — in conjunction with systemd-logind.service — ensures the + following: + + + If it does not exist yet, the user runtime directory /run/user/$UID is + either created or mounted as new tmpfs file system with quota applied, and its ownership + changed to the user that is logging in. + + The $XDG_SESSION_ID environment variable is initialized. If auditing is + available and pam_loginuid.so was run before this module (which is highly recommended), the + variable is initialized from the auditing session id (/proc/self/sessionid). Otherwise, an + independent session counter is used. + + A new systemd scope unit is created for the session. If this is the first concurrent session of + the user, an implicit per-user slice unit below user.slice is automatically created and the + scope placed into it. An instance of the system service user@.service, which runs the + systemd user manager instance, is started. + + + On logout, this module ensures the following: + + + If enabled in + logind.conf + 5 (KillUserProcesses=), all processes of the session are + terminated. If the last concurrent session of a user ends, the user's systemd instance will be terminated too, + and so will the user's slice unit. + + If the last concurrent session of a user ends, + the user runtime directory /run/user/$UID and all its + contents are removed, too. + + + If the system was not booted up with systemd as init system, + this module does nothing and immediately returns + PAM_SUCCESS. + + + + + Options + + The following options are understood: + + + + + class= + + Takes a string argument which sets the session class. The XDG_SESSION_CLASS + environment variable (see below) takes precedence. One of user, greeter, + lock-screen or background. See + sd_session_get_class3 for + details about the session class. + + + + type= + + Takes a string argument which sets the session type. The XDG_SESSION_TYPE + environment variable (see below) takes precedence. One of unspecified, + tty, x11, wayland or mir. See + sd_session_get_type3 for + details about the session type. + + + + desktop= + + Takes a single, short identifier string for the desktop environment. The + XDG_SESSION_DESKTOP environment variable (see below) takes precedence. This may be used to + indicate the session desktop used, where this applies and if this information is available. For example: + GNOME, or KDE. It is recommended to use the same identifiers and + capitalization as for $XDG_CURRENT_DESKTOP, as defined by the Desktop Entry + Specification. (However, note that the option only takes a single item, and not a colon-separated list + like $XDG_CURRENT_DESKTOP.) See + sd_session_get_desktop3 for + further details. + + + + debug= + + Takes an optional boolean argument. If yes or without the argument, the module will log + debugging information as it operates. + + + + + + Module Types Provided + + Only is provided. + + + + Environment + + The following environment variables are initialized by the module and available to the processes of the + user's session: + + + + $XDG_SESSION_ID + + A short session identifier, suitable to be used in filenames. The string itself should be + considered opaque, although often it is just the audit session ID as reported by + /proc/self/sessionid. Each ID will be assigned only once during machine uptime. It may + hence be used to uniquely label files or other resources of this session. Combine this ID with the boot + identifier, as returned by + sd_id128_get_boot3, for a + globally unique identifier for the current session. + + + + $XDG_RUNTIME_DIR + + Path to a user-private user-writable directory + that is bound to the user login time on the machine. It is + automatically created the first time a user logs in and + removed on the user's final logout. If a user logs in twice at + the same time, both sessions will see the same + $XDG_RUNTIME_DIR and the same contents. If + a user logs in once, then logs out again, and logs in again, + the directory contents will have been lost in between, but + applications should not rely on this behavior and must be able + to deal with stale files. To store session-private data in + this directory, the user should include the value of + $XDG_SESSION_ID in the filename. This + directory shall be used for runtime file system objects such + as AF_UNIX sockets, FIFOs, PID files and + similar. It is guaranteed that this directory is local and + offers the greatest possible file system feature set the + operating system provides. For further details, see the XDG + Base Directory Specification. $XDG_RUNTIME_DIR + is not set if the current user is not the original user of the session. + + + + + The following environment variables are read by the module and may be used by the PAM service to pass + metadata to the module. If these variables are not set when the PAM module is invoked but can be determined + otherwise they are set by the module, so that these variables are initialized for the session and applications if + known at all. + + + + $XDG_SESSION_TYPE + + The session type. This may be used instead of type= on the module parameter + line, and is usually preferred. + + + + $XDG_SESSION_CLASS + + The session class. This may be used instead of class= on the module parameter + line, and is usually preferred. + + + + $XDG_SESSION_DESKTOP + + The desktop identifier. This may be used instead of desktop= on the module + parameter line, and is usually preferred. + + + + $XDG_SEAT + + The seat name the session shall be registered + for, if any. + + + + $XDG_VTNR + + The VT number the session shall be registered + for, if any. (Only applies to seats with a VT available, such + as seat0) + + + + If not set, pam_systemd will initialize + $XDG_SEAT and $XDG_VTNR + based on the $DISPLAY variable (if the latter is set). + + + + Session limits + + PAM modules earlier in the stack, that is those that come before pam_systemd.so, + can set session scope limits using the PAM context objects. The data for these objects is provided as NUL-terminated C strings + and maps directly to the respective unit resource control directives. Note that these limits apply to individual sessions of the user, + they do not apply to all user processes as a combined whole. In particular, the per-user user@.service unit instance, + which runs the systemd --user manager process and its children, and is tracked outside of any session, being shared + by all the user's sessions, is not covered by these limits. + + + See + systemd.resource-control5 for more information about the resources. + Also, see pam_set_data3 for additional information about how to set + the context objects. + + + + + systemd.memory_max + + Sets unit MemoryMax=. + + + + systemd.tasks_max + + Sets unit TasksMax=. + + + + systemd.cpu_weight + + Sets unit CPUWeight=. + + + + systemd.io_weight + + Sets unit IOWeight=. + + + + systemd.runtime_max_sec + + Sets unit RuntimeMaxSec=. + + + + Example data as can be provided from an another PAM module: + +pam_set_data(handle, "systemd.memory_max", (void *)"200M", cleanup); +pam_set_data(handle, "systemd.tasks_max", (void *)"50", cleanup); +pam_set_data(handle, "systemd.cpu_weight", (void *)"100", cleanup); +pam_set_data(handle, "systemd.io_weight", (void *)"340", cleanup); +pam_set_data(handle, "systemd.runtime_max_sec", (void *)"3600", cleanup); + + + + + + + Example + + #%PAM-1.0 +auth required pam_unix.so +auth required pam_nologin.so +account required pam_unix.so +password required pam_unix.so +session required pam_unix.so +session required pam_loginuid.so +session required pam_systemd.so + + + + See Also + + systemd1, + systemd-logind.service8, + logind.conf5, + loginctl1, + pam.conf5, + pam.d5, + pam8, + pam_loginuid8, + systemd.scope5, + systemd.slice5, + systemd.service5 + + + + diff --git a/man/portablectl.xml b/man/portablectl.xml new file mode 100644 index 00000000..88cf36ae --- /dev/null +++ b/man/portablectl.xml @@ -0,0 +1,400 @@ + + + + + + + + portablectl + systemd + + + + portablectl + 1 + + + + portablectl + Attach, detach or inspect portable service images + + + + + portablectl + OPTIONS + COMMAND + NAME + + + + + Description + + portablectl may be used to attach, detach or inspect portable service images. It's + primarily a command interfacing with + systemd-portabled.service8. + + Portable service images contain an OS file system tree along with + systemd1 unit file + information. A service image may be "attached" to the local system. If attached, a set of unit files are copied + from the image to the host, and extended with RootDirectory= or RootImage= + assignments (in case of service units) pointing to the image file or directory, ensuring the services will run + within the file system context of the image. + + Portable service images are an efficient way to bundle multiple related services and other units together, + and transfer them as a whole between systems. When these images are attached the local system the contained units + may run in most ways like regular system-provided units, either with full privileges or inside strict sandboxing, + depending on the selected configuration. + + Specifically portable service images may be of the following kind: + + + Directory trees containing an OS, including the top-level directories /usr/, + /etc/, and so on. + + btrfs subvolumes containing OS trees, similar to normal directory trees. + + Binary "raw" disk images containing MBR or GPT partition tables and Linux file system + partitions. (These must be regular files, with the .raw suffix.) + + + + + + Commands + + The following commands are understood: + + + + + list + + List available portable service images. This will list all portable service images discovered + in the portable image search paths (see below), along with brief metadata and state information. Note that many + of the commands below may both operate on images inside and outside of the search paths. This command is hence + mostly a convenience option, the commands are generally not restricted to what this list + shows. + + + + attach IMAGE [PREFIX…] + + Attach a portable service image to the host system. Expects a file system path to a portable + service image file or directory as first argument. If the specified path contains no slash character + (/) it is understood as image filename that is searched for in the portable service image + search paths (see below). To reference a file in the current working directory prefix the filename with + ./ to avoid this search path logic. + + When a portable service is attached four operations are executed: + + + + All unit files of types .service, .socket, + .target, .timer and .path which match the + indicated unit file name prefix are copied from the image to the host's + /etc/systemd/system.attached/ directory (or + /run/systemd/system.attached/ — depending whether is + specified, see above), which is included in the built-in unit search path of the system service + manager. + + For unit files of type .service a drop-in is added to these copies that + adds RootDirectory= or RootImage= settings (see + systemd.unit5 for + details), that ensures these services are run within the file system of the originating portable service + image. + + A second drop-in is created: the "profile" drop-in, that may contain additional security + settings (and other settings). A number of profiles are available by default but administrators may define + their own ones. See below. + + If the portable service image file is not already in the search path (see below), a symbolic + link to it is created in /etc/portables/ or + /run/portables/, to make sure it is included in it. + + + By default all unit files whose names start with a prefix generated from the image's file name are copied + out. Specifically, the prefix is determined from the image file name with any suffix such as + .raw removed, truncated at the first occurrence of and underscore character + (_), if there is one. The underscore logic is supposed to be used to versioning so that the + an image file foobar_47.11.raw will result in a unit file matching prefix of + foobar. This prefix is then compared with all unit files names contained in the image in + the usual directories, but only unit file names where the prefix is followed by -, + . or @ are considered. Example: if a portable service image file is named + foobar_47.11.raw then by default all its unit files with names such as + foobar-quux-waldi.service, foobar.service or + foobar@.service will be considered. It's possible to override the matching prefix: all + strings listed on the command line after the image file name are considered prefixes, overriding the implicit + logic where the prefix is derived from the image file name. + + By default, after the unit files are attached the service manager's configuration is reloaded, except + when is specified (see above). This ensures that the new units made available to + the service manager are seen by it. + + + + + detach IMAGE + + Detaches a portable service image from the host. This undoes the operations executed by the + attach command above, and removes the unit file copies, drop-ins and image symlink + again. This command expects an image name or path as parameter. Note that if a path is specified only the last + component of it (i.e. the file or directory name itself, not the path to it) is used for finding matching unit + files. This is a convencience feature to allow all arguments passed as attach also to + detach. + + + + inspect IMAGE [PREFIX…] + + Extracts various metadata from a portable service image and presents it to the + caller. Specifically, the + os-release5 file of the + image is retrieved as well as all matching unit files. By default a short summary showing the most relevant + metadata in combination with a list of matching unit files is shown (that is the unit files + attach would install to the host system). If combined with (see + above), the os-release data and the units files' contents is displayed unprocessed. This + command is useful to determine whether an image qualifies as portable service image, and which unit files are + included. This command expects the path to the image as parameter, optionally followed by a list of unit file + prefixes to consider, similar to the attach command described above. + + + + + is-attached IMAGE + + Determines whether the specified image is currently attached or not. Unless combined with the + switch this will show a short state identifier for the image. Specifically: + + + Image attachment states + + + + + + State + Description + + + + + + The image is currently not attached. + + + + The image is currently attached, i.e. its unit files have been made available to the host system. + + + + Like , but the unit files have been made available transiently only, i.e. the attach command has been invoked with the option. + + + + The image is currently attached, and at least one unit file associated with it has been enabled. + + + + Like , but the unit files have been made available transiently only, i.e. the attach command has been invoked with the option. + + + + The image is currently attached, and at least one unit file associated with it is running. + + + + The image is currently attached transiently, and at least one unit file associated with it is running. + + + +
+ +
+
+ + + read-only IMAGE [BOOL] + + Marks or (unmarks) a portable service image read-only. Takes an image name, followed by a + boolean as arguments. If the boolean is omitted, positive is implied, i.e. the image is marked + read-only. + + + + remove IMAGE… + + Removes one or more portable service images. Note that this command will only remove the + specified image path itself — it refers to a symbolic link then the symbolic link is removed and not the + image it points to. + + + + set-limit [IMAGE] BYTES + + Sets the maximum size in bytes that a specific portable service image, or all images, may grow + up to on disk (disk quota). Takes either one or two parameters. The first, optional parameter refers to a + portable service image name. If specified, the size limit of the specified image is changed. If omitted, the + overall size limit of the sum of all images stored locally is changed. The final argument specifies the size + limit in bytes, possibly suffixed by the usual K, M, G, T units. If the size limit shall be disabled, specify + - as size. + + Note that per-image size limits are only supported on btrfs file systems. Also, depending on + BindPaths= settings in the portable service's unit files directories from the host might be + visible in the image environment during runtime which are not affected by this setting, as only the image + itself is counted against this limit. + + +
+ +
+ + + Options + + The following options are understood: + + + + + + + Suppresses additional informational output while running. + + + + PROFILE + PROFILE + + When attaching an image, select the profile to use. By default the default + profile is used. For details about profiles, see below. + + + + + + When attaching an image, select whether to prefer copying or symlinking of files installed into + the host system. Takes one of copy (to prefer copying of files), symlink + (to prefer creation of symbolic links) or auto for an intermediary mode where security + profile drop-ins are symlinked while unit files are copied. Note that this option expresses a preference only, + in cases where symbolic links cannot be created — for example when the image operated on is a raw disk image, + and hence not directly referentiable from the host file system — copying of files is used + unconditionally. + + + + + + When specified the unit and drop-in files are placed in + /run/systemd/system.attached/ instead of + /etc/systemd/system.attached/. Images attached with this option set hence remain attached + only until the next reboot, while they are normally attached persistently. + + + + + + Don't reload the service manager after attaching or detaching a portable service + image. Normally the service manager is reloaded to ensure it is aware of added or removed unit + files. + + + + + + When inspecting portable service images, show the (unprocessed) contents of the metadata files + pulled from the image, instead of brief summaries. Specifically, this will show the + os-release5 and unit file + contents of the image. + + + + + + + + + + + + + + + Files and Directories + + Portable service images are preferably stored in /var/lib/portables/, but are also + searched for in /etc/portables/, /run/systemd/portables/, + /usr/local/lib/portables/ and /usr/lib/portables/. It's recommended not + to place image files directly in /etc/portables/ or + /run/systemd/portables/ (as these are generally not suitable for storing large or non-textual + data), but use these directories only for linking images located elsewhere into the image search path. + + When a portable service image is attached, matching unit files are copied onto the host into the + /etc/systemd/system.attached/ and /run/systemd/system.attached/ + directories. When an image is detached, the unit files are removed again from these directories. + + + + Profiles + + When portable service images are attached a "profile" drop-in is linked in, which may be used to enforce + additional security (and other) restrictions locally. Four profile drop-ins are defined by default, and shipped in + /usr/lib/systemd/portable/profile/. Additional, local profiles may be defined by placing them + in /etc/systemd/portable/profile/. The default profiles are: + + + Profiles + + + + + + Name + Description + + + + + default + This is the default profile if no other profile name is set via the (see above). It's fairly restrictive, but should be useful for common, unprivileged system workloads. This includes write access to the logging framework, as well as IPC access to the D-Bus system. + + + nonetwork + Very similar to default, but networking is turned off for any services of the portable service image. + + + strict + A profile with very strict settings. This profile excludes IPC (D-Bus) and network access. + + + trusted + A profile with very relaxed settings. In this profile the services run with full privileges. + + + +
+ + For details on this profiles, and their effects please have a look at their precise definitions, + e.g. /usr/lib/systemd/portable/profile/default/service.conf and similar. +
+ + + Exit status + + On success, 0 is returned, a non-zero failure code otherwise. + + + + + + See Also + + systemd1, + systemd-portabled.service8 + + + +
diff --git a/man/print-unit-path.c b/man/print-unit-path.c new file mode 100644 index 00000000..23b58a26 --- /dev/null +++ b/man/print-unit-path.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include + +#include +#define _cleanup_(f) __attribute__((cleanup(f))) + +/* This is equivalent to: + * busctl call org.freedesktop.systemd1 /org/freedesktop/systemd1 \ + * org.freedesktop.systemd1.Manager GetUnitByPID $$ + * + * Compile with 'cc -lsystemd print-unit-path.c' + */ + +#define DESTINATION "org.freedesktop.systemd1" +#define PATH "/org/freedesktop/systemd1" +#define INTERFACE "org.freedesktop.systemd1.Manager" +#define MEMBER "GetUnitByPID" + +static int log_error(int error, const char *message) { + fprintf(stderr, "%s: %s\n", message, strerror(-error)); + return error; +} + +static int print_unit_path(sd_bus *bus) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + r = sd_bus_message_new_method_call(bus, &m, + DESTINATION, PATH, INTERFACE, MEMBER); + if (r < 0) + return log_error(r, "Failed to create bus message"); + + r = sd_bus_message_append(m, "u", (unsigned) getpid()); + if (r < 0) + return log_error(r, "Failed to append to bus message"); + + r = sd_bus_call(bus, m, -1, &error, &reply); + if (r < 0) + return log_error(r, "Call failed"); + + const char *ans; + r = sd_bus_message_read(reply, "o", &ans); + if (r < 0) + return log_error(r, "Failed to read reply"); + + printf("Unit path is \"%s\".\n", ans); + + return 0; +} + +int main(int argc, char **argv) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_error(r, "Failed to acquire bus"); + + print_unit_path(bus); +} diff --git a/man/pstore.conf.xml b/man/pstore.conf.xml new file mode 100644 index 00000000..2b9c8b1a --- /dev/null +++ b/man/pstore.conf.xml @@ -0,0 +1,89 @@ + + + + + + + pstore.conf + systemd + + + + pstore.conf + 5 + + + + pstore.conf + pstore.conf.d + PStore configuration file + + + + + /etc/systemd/pstore.conf + /etc/systemd/pstore.conf.d/* + + + + + Description + + This file configures the behavior of + systemd-pstore8, + a tool for archiving the contents of the persistent storage filesystem, + pstore. + + + + + + + Options + + All options are configured in the + [PStore] section: + + + + + Storage= + + Controls where to archive (i.e. copy) files from the pstore filesystem. One of none, + external, and journal. When + none, the tool exits without processing files in the pstore filesystem. + When external (the default), files are archived into /var/lib/systemd/pstore/, + and logged into the journal. + When journal, pstore file contents are logged only in the journal. + + + + + + Unlink= + + Controls whether or not files are removed from pstore after processing. + Takes a boolean value. When true, a pstore file is removed from the pstore once it has been + archived (either to disk or into the journal). When false, processing of pstore files occurs + normally, but the files remain in the pstore. + The default is true in order to maintain the pstore in a nearly empty state, so that the pstore + has storage available for the next kernel error event. + + + + + The defaults for all values are listed as comments in the + template /etc/systemd/pstore.conf file that + is installed by default. + + + + See Also + + systemd-journald.service8, + + + + diff --git a/man/resolvectl.xml b/man/resolvectl.xml new file mode 100644 index 00000000..594e22c0 --- /dev/null +++ b/man/resolvectl.xml @@ -0,0 +1,447 @@ + + + + + + + + resolvectl + systemd + + + + resolvectl + 1 + + + + resolvectl + resolvconf + Resolve domain names, IPV4 and IPv6 addresses, DNS resource records, and services; introspect and reconfigure the DNS resolver + + + + + resolvectl + OPTIONS + COMMAND + NAME + + + + + Description + + resolvectl may be used to resolve domain names, IPv4 and IPv6 addresses, DNS resource + records and services with the + systemd-resolved.service8 + resolver service. By default, the specified list of parameters will be resolved as hostnames, retrieving their IPv4 + and IPv6 addresses. If the parameters specified are formatted as IPv4 or IPv6 operation the reverse operation is + done, and a hostname is retrieved for the specified addresses. + + The program's output contains information about the protocol used for the look-up and on which network + interface the data was discovered. It also contains information on whether the information could be + authenticated. All data for which local DNSSEC validation succeeds is considered authenticated. Moreover all data + originating from local, trusted sources is also reported authenticated, including resolution of the local host + name, the localhost host name or all data from /etc/hosts. + + + + Commands + + + + query HOSTNAME|ADDRESS… + + Resolve domain names, IPv4 and IPv6 addresses. + + + + service + [[NAME] TYPE] + DOMAIN + + Resolve DNS-SD and + SRV services, depending on the specified list of parameters. + If three parameters are passed the first is assumed to be the DNS-SD service name, the second the SRV service type, + and the third the domain to search in. In this case a full DNS-SD style SRV and TXT lookup is executed. If only two + parameters are specified, the first is assumed to be the SRV service type, and the second the domain to look in. In + this case no TXT RR is requested. Finally, if only one parameter is specified, it is assumed to be a domain name, + that is already prefixed with an SRV type, and an SRV lookup is done (no TXT). + + + + openpgp EMAIL@DOMAIN… + + Query PGP keys stored as OPENPGPKEY + resource records. Specified e-mail addresses are converted to the corresponding DNS domain name, and any + OPENPGPKEY keys are printed. + + + + tlsa + [FAMILY] + DOMAIN[:PORT]… + + Query TLS public keys stored as TLSA + resource records. A query will be performed for each of the specified names prefixed with the port and family + (_port._family.domain). + The port number may be specified after a colon (:), otherwise 443 will be used + by default. The family may be specified as the first argument, otherwise tcp will be used. + + + + status [LINK…] + + Shows the global and per-link DNS settings currently in effect. If no command is specified, + this is the implied default. + + + + statistics + + Shows general resolver statistics, including information whether DNSSEC is + enabled and available, as well as resolution and validation statistics. + + + + reset-statistics + + Resets the statistics counters shown in statistics to zero. + This operation requires root privileges. + + + + flush-caches + + Flushes all DNS resource record caches the service maintains locally. This is mostly equivalent + to sending the SIGUSR2 to the systemd-resolved + service. + + + + reset-server-features + + Flushes all feature level information the resolver learnt about specific servers, and ensures + that the server feature probing logic is started from the beginning with the next look-up request. This is + mostly equivalent to sending the SIGRTMIN+1 to the systemd-resolved + service. + + + + dns [LINK [SERVER…]] + domain [LINK [DOMAIN…]] + default-route [LINK [BOOL…]] + llmnr [LINK [MODE]] + mdns [LINK [MODE]] + dnssec [LINK [MODE]] + dnsovertls [LINK [MODE]] + nta [LINK [DOMAIN…]] + + + Get/set per-interface DNS configuration. These commands may be used to configure various DNS + settings for network interfaces. These commands may be used to inform + systemd-resolved or systemd-networkd about per-interface DNS + configuration determined through external means. The dns command expects IPv4 or + IPv6 address specifications of DNS servers to use. The domain command expects + valid DNS domains, possibly prefixed with ~, and configures a per-interface + search or route-only domain. The default-route command expects a boolean + parameter, and configures whether the link may be used as default route for DNS lookups, i.e. if it + is suitable for lookups on domains no other link explicitly is configured for. The + llmnr, mdns, dnssec and + dnsovertls commands may be used to configure the per-interface LLMNR, + MulticastDNS, DNSSEC and DNSOverTLS settings. Finally, nta command may be used + to configure additional per-interface DNSSEC NTA domains. + + Commands dns, domain and nta can take + a single empty string argument to clear their respective value lists. + + For details about these settings, their possible values and their effect, see the + corresponding settings in + systemd.network5. + + + + + revert LINK + + Revert the per-interface DNS configuration. If the DNS configuration is reverted all + per-interface DNS setting are reset to their defaults, undoing all effects of dns, + domain, default-route, llmnr, + mdns, dnssec, dnsovertls, + nta. Note that when a network interface disappears all configuration is lost + automatically, an explicit reverting is not necessary in that case. + + + + + + + Options + + + + + + By default, when resolving a hostname, both IPv4 and IPv6 + addresses are acquired. By specifying only IPv4 addresses are requested, by specifying + only IPv6 addresses are requested. + + + + + INTERFACE + INTERFACE + + Specifies the network interface to execute the query on. This may either be specified as numeric + interface index or as network interface string (e.g. en0). Note that this option has no + effect if system-wide DNS configuration (as configured in /etc/resolv.conf or + /etc/systemd/resolve.conf) in place of per-link configuration is used. + + + + PROTOCOL + PROTOCOL + + Specifies the network protocol for the query. May be one of dns + (i.e. classic unicast DNS), llmnr (Link-Local Multicast Name Resolution), + llmnr-ipv4, llmnr-ipv6 (LLMNR via the indicated underlying IP + protocols), mdns (Multicast DNS), + mdns-ipv4, mdns-ipv6 (MDNS via the indicated underlying IP protocols). + By default the lookup is done via all protocols suitable for the lookup. If used, limits the set of + protocols that may be used. Use this option multiple times to enable resolving via multiple protocols at the + same time. The setting llmnr is identical to specifying this switch once with + llmnr-ipv4 and once via llmnr-ipv6. Note that this option does not force + the service to resolve the operation with the specified protocol, as that might require a suitable network + interface and configuration. + The special value help may be used to list known values. + + + + + TYPE + TYPE + CLASS + CLASS + + Specifies the DNS resource record type (e.g. A, AAAA, MX, …) and class (e.g. IN, ANY, …) to + look up. If these options are used a DNS resource record set matching the specified class and type is + requested. The class defaults to IN if only a type is specified. + The special value help may be used to list known values. + + + + + BOOL + + Takes a boolean parameter. If true (the default), when doing a service lookup with + the hostnames contained in the SRV resource records are resolved as well. + + + + BOOL + + Takes a boolean parameter. If true (the default), when doing a DNS-SD service lookup with + the TXT service metadata record is resolved as well. + + + + BOOL + + Takes a boolean parameter. If true (the default), DNS CNAME or DNAME redirections are + followed. Otherwise, if a CNAME or DNAME record is encountered while resolving, an error is + returned. + + + + BOOL + + Takes a boolean parameter. If true (the default), any specified single-label hostnames will be + searched in the domains configured in the search domain list, if it is non-empty. Otherwise, the search domain + logic is disabled. + + + + =payload|packet + + Dump the answer as binary data. If there is no argument or if the argument is + payload, the payload of the packet is exported. If the argument is + packet, the whole packet is dumped in wire format, prefixed by + length specified as a little-endian 64-bit number. This format allows multiple packets + to be dumped and unambiguously parsed. + + + + BOOL + + Takes a boolean parameter. If true (the default), column headers and meta information about the + query response are shown. Otherwise, this output is suppressed. + + + + + + + + + + Compatibility with <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry> + + resolvectl is a multi-call binary. When invoked as resolvconf + (generally achieved by means of a symbolic link of this name to the resolvectl binary) it + is run in a limited resolvconf8 + compatibility mode. It accepts mostly the same arguments and pushes all data into + systemd-resolved.service8, + similar to how and commands operate. Note that + systemd-resolved.service is the only supported backend, which is different from other + implementations of this command. Note that not all operations supported by other implementations are supported + natively. Specifically: + + + + + Registers per-interface DNS configuration data with + systemd-resolved. Expects a network interface name as only command line argument. Reads + resolv.conf5 compatible DNS + configuration data from its standard input. Relevant fields are nameserver and + domain/search. This command is mostly identical to invoking + resolvectl with a combination of and + commands. + + + + + Unregisters per-interface DNS configuration data with systemd-resolved. This + command is mostly identical to invoking resolvectl revert. + + + + + + When specified and will not complain about missing + network interfaces and will silently execute no operation in that case. + + + + + + This switch for "exclusive" operation is supported only partially. It is mapped to an + additional configured search domain of ~. — i.e. ensures that DNS traffic is preferably + routed to the DNS servers on this interface, unless there are other, more specific domains configured on other + interfaces. + + + + + + + These switches are not supported and are silently ignored. + + + + + + + + + + + + + + + + These switches are not supported and the command will fail if used. + + + + + See resolvconf8 for details on this command line options. + + + + Examples + + + Retrieve the addresses of the <literal>www.0pointer.net</literal> domain + + $ resolvectl query www.0pointer.net +www.0pointer.net: 2a01:238:43ed:c300:10c3:bcf3:3266:da74 + 85.214.157.71 + +-- Information acquired via protocol DNS in 611.6ms. +-- Data is authenticated: no + + + + + Retrieve the domain of the <literal>85.214.157.71</literal> IP address + + $ resolvectl query 85.214.157.71 +85.214.157.71: gardel.0pointer.net + +-- Information acquired via protocol DNS in 1.2997s. +-- Data is authenticated: no + + + + + Retrieve the MX record of the <literal>yahoo.com</literal> domain + + $ resolvectl --legend=no -t MX query yahoo.com +yahoo.com. IN MX 1 mta7.am0.yahoodns.net +yahoo.com. IN MX 1 mta6.am0.yahoodns.net +yahoo.com. IN MX 1 mta5.am0.yahoodns.net + + + + + Resolve an SRV service + + $ resolvectl service _xmpp-server._tcp gmail.com +_xmpp-server._tcp/gmail.com: alt1.xmpp-server.l.google.com:5269 [priority=20, weight=0] + 173.194.210.125 + alt4.xmpp-server.l.google.com:5269 [priority=20, weight=0] + 173.194.65.125 + … + + + + + Retrieve a PGP key + + $ resolvectl openpgp zbyszek@fedoraproject.org +d08ee310438ca124a6149ea5cc21b6313b390dce485576eff96f8722._openpgpkey.fedoraproject.org. IN OPENPGPKEY + mQINBFBHPMsBEACeInGYJCb+7TurKfb6wGyTottCDtiSJB310i37/6ZYoeIay/5soJjlMyf + MFQ9T2XNT/0LM6gTa0MpC1st9LnzYTMsT6tzRly1D1UbVI6xw0g0vE5y2Cjk3xUwAynCsSs + … + + + + + Retrieve a TLS key (<literal>tcp</literal> and + <literal>:443</literal> could be skipped) + + $ resolvectl tlsa tcp fedoraproject.org:443 +_443._tcp.fedoraproject.org IN TLSA 0 0 1 19400be5b7a31fb733917700789d2f0a2471c0c9d506c0e504c06c16d7cb17c0 + -- Cert. usage: CA constraint + -- Selector: Full Certificate + -- Matching type: SHA-256 + + + + + + See Also + + systemd1, + systemd-resolved.service8, + systemd.dnssd5, + systemd-networkd.service8, + resolvconf8 + + + diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml new file mode 100644 index 00000000..81800014 --- /dev/null +++ b/man/resolved.conf.xml @@ -0,0 +1,274 @@ + + + + + + + resolved.conf + systemd + + + + resolved.conf + 5 + + + + resolved.conf + resolved.conf.d + Network Name Resolution configuration files + + + + /etc/systemd/resolved.conf + /etc/systemd/resolved.conf.d/*.conf + /run/systemd/resolved.conf.d/*.conf + /usr/lib/systemd/resolved.conf.d/*.conf + + + + Description + + These configuration files control local DNS and LLMNR + name resolution. + + + + + + + Options + + The following options are available in the [Resolve] section: + + + + + DNS= + A space-separated list of IPv4 and IPv6 addresses to use as system DNS servers. DNS requests + are sent to one of the listed DNS servers in parallel to suitable per-link DNS servers acquired from + systemd-networkd.service8 or + set at runtime by external applications. For compatibility reasons, if this setting is not specified, the DNS + servers listed in /etc/resolv.conf are used instead, if that file exists and any servers + are configured in it. This setting defaults to the empty list. + + + + FallbackDNS= + A space-separated list of IPv4 and IPv6 addresses to use as the fallback DNS servers. Any + per-link DNS servers obtained from + systemd-networkd.service8 + take precedence over this setting, as do any servers set via DNS= above or + /etc/resolv.conf. This setting is hence only used if no other DNS server information is + known. If this option is not given, a compiled-in list of DNS servers is used instead. + + + + Domains= + A space-separated list of domains. These domains are used as search suffixes when resolving + single-label host names (domain names which contain no dot), in order to qualify them into fully-qualified + domain names (FQDNs). Search domains are strictly processed in the order they are specified, until the name + with the suffix appended is found. For compatibility reasons, if this setting is not specified, the search + domains listed in /etc/resolv.conf are used instead, if that file exists and any domains + are configured in it. This setting defaults to the empty list. + + Specified domain names may optionally be prefixed with ~. In this case they do not + define a search path, but preferably direct DNS queries for the indicated domains to the DNS servers configured + with the system DNS= setting (see above), in case additional, suitable per-link DNS servers + are known. If no per-link DNS servers are known using the ~ syntax has no effect. Use the + construct ~. (which is composed of ~ to indicate a routing domain and + . to indicate the DNS root domain that is the implied suffix of all DNS domains) to use the + system DNS server defined with DNS= preferably for all domains. + + + + LLMNR= + Takes a boolean argument or + resolve. Controls Link-Local Multicast Name + Resolution support (RFC 4795) on + the local host. If true, enables full LLMNR responder and + resolver support. If false, disables both. If set to + resolve, only resolution support is enabled, + but responding is disabled. Note that + systemd-networkd.service8 + also maintains per-link LLMNR settings. LLMNR will be + enabled on a link only if the per-link and the + global setting is on. + + + + MulticastDNS= + Takes a boolean argument or + resolve. Controls Multicast DNS support (RFC 6762) on + the local host. If true, enables full Multicast DNS responder and + resolver support. If false, disables both. If set to + resolve, only resolution support is enabled, + but responding is disabled. Note that + systemd-networkd.service8 + also maintains per-link Multicast DNS settings. Multicast DNS will be + enabled on a link only if the per-link and the + global setting is on. + + + + DNSSEC= + Takes a boolean argument or + allow-downgrade. If true all DNS lookups are + DNSSEC-validated locally (excluding LLMNR and Multicast + DNS). If the response to a lookup request is detected to be invalid + a lookup failure is returned to applications. Note that + this mode requires a DNS server that supports DNSSEC. If the + DNS server does not properly support DNSSEC all validations + will fail. If set to allow-downgrade DNSSEC + validation is attempted, but if the server does not support + DNSSEC properly, DNSSEC mode is automatically disabled. Note + that this mode makes DNSSEC validation vulnerable to + "downgrade" attacks, where an attacker might be able to + trigger a downgrade to non-DNSSEC mode by synthesizing a DNS + response that suggests DNSSEC was not supported. If set to + false, DNS lookups are not DNSSEC validated. + + Note that DNSSEC validation requires retrieval of + additional DNS data, and thus results in a small DNS look-up + time penalty. + + DNSSEC requires knowledge of "trust anchors" to prove + data integrity. The trust anchor for the Internet root domain + is built into the resolver, additional trust anchors may be + defined with + dnssec-trust-anchors.d5. + Trust anchors may change at regular intervals, and old trust + anchors may be revoked. In such a case DNSSEC validation is + not possible until new trust anchors are configured locally or + the resolver software package is updated with the new root + trust anchor. In effect, when the built-in trust anchor is + revoked and DNSSEC= is true, all further + lookups will fail, as it cannot be proved anymore whether + lookups are correctly signed, or validly unsigned. If + DNSSEC= is set to + allow-downgrade the resolver will + automatically turn off DNSSEC validation in such a case. + + Client programs looking up DNS data will be informed + whether lookups could be verified using DNSSEC, or whether the + returned data could not be verified (either because the data + was found unsigned in the DNS, or the DNS server did not + support DNSSEC or no appropriate trust anchors were known). In + the latter case it is assumed that client programs employ a + secondary scheme to validate the returned DNS data, should + this be required. + + It is recommended to set DNSSEC= to + true on systems where it is known that the DNS server supports + DNSSEC correctly, and where software or trust anchor updates + happen regularly. On other systems it is recommended to set + DNSSEC= to + allow-downgrade. + + In addition to this global DNSSEC setting + systemd-networkd.service8 + also maintains per-link DNSSEC settings. For system DNS + servers (see above), only the global DNSSEC setting is in + effect. For per-link DNS servers the per-link + setting is in effect, unless it is unset in which case the + global setting is used instead. + + Site-private DNS zones generally conflict with DNSSEC + operation, unless a negative (if the private zone is not + signed) or positive (if the private zone is signed) trust + anchor is configured for them. If + allow-downgrade mode is selected, it is + attempted to detect site-private DNS zones using top-level + domains (TLDs) that are not known by the DNS root server. This + logic does not work in all private zone setups. + + Defaults to allow-downgrade + + + + + DNSOverTLS= + + Takes a boolean argument or opportunistic. + If true all connections to the server will be encrypted. Note that + this mode requires a DNS server that supports DNS-over-TLS and has + a valid certificate for it's IP. If the DNS server does not support + DNS-over-TLS all DNS requests will fail. When set to opportunistic + DNS request are attempted to send encrypted with DNS-over-TLS. + If the DNS server does not support TLS, DNS-over-TLS is disabled. + Note that this mode makes DNS-over-TLS vulnerable to "downgrade" + attacks, where an attacker might be able to trigger a downgrade + to non-encrypted mode by synthesizing a response that suggests + DNS-over-TLS was not supported. If set to false, DNS lookups + are send over UDP. + + Note that DNS-over-TLS requires additional data to be + send for setting up an encrypted connection, and thus results + in a small DNS look-up time penalty. + + Note that in opportunistic mode the + resolver is not capable of authenticating the server, so it is + vulnerable to "man-in-the-middle" attacks. + + In addition to this global DNSOverTLS setting + systemd-networkd.service8 + also maintains per-link DNSOverTLS settings. For system DNS + servers (see above), only the global DNSOverTLS setting is in + effect. For per-link DNS servers the per-link + setting is in effect, unless it is unset in which case the + global setting is used instead. + + Defaults to off. + + + + + Cache= + Takes a boolean or no-negative as argument. If yes (the default), resolving a domain name + which already got queried earlier will return the previous result as long as it is still valid, and thus does + not result in a new network request. Be aware that turning off caching comes at a performance penalty, which + is particularly high when DNSSEC is used. + If no-negative, only positive answers are cached. + + Note that caching is turned off implicitly if the configured DNS server is on a host-local IP address + (such as 127.0.0.1 or ::1), in order to avoid duplicate local caching. + + + + DNSStubListener= + Takes a boolean argument or one of udp and tcp. If + udp, a DNS stub resolver will listen for UDP requests on address 127.0.0.53 + port 53. If tcp, the stub will listen for TCP requests on the same address and port. If + yes (the default), the stub listens for both UDP and TCP requests. If no, the stub + listener is disabled. + + Note that the DNS stub listener is turned off implicitly when its listening address and port are already + in use. + + + + ReadEtcHosts= + Takes a boolean argument. If yes (the default), the DNS stub resolver will read + /etc/hosts, and try to resolve hosts or address by using the entries in the file before + sending query to DNS servers. + + + + + + + See Also + + systemd1, + systemd-resolved.service8, + systemd-networkd.service8, + dnssec-trust-anchors.d5, + resolv.conf4 + + + + diff --git a/man/rules/meson.build b/man/rules/meson.build new file mode 100644 index 00000000..20c3d09d --- /dev/null +++ b/man/rules/meson.build @@ -0,0 +1,948 @@ +# Do not edit. Generated by make-man-rules.py. +# Update with: +# ninja -C build man/update-man-rules +manpages = [ +['binfmt.d', '5', [], 'ENABLE_BINFMT'], + ['bootctl', '1', [], 'ENABLE_EFI'], + ['bootup', '7', [], ''], + ['busctl', '1', [], ''], + ['coredump.conf', '5', ['coredump.conf.d'], 'ENABLE_COREDUMP'], + ['coredumpctl', '1', [], 'ENABLE_COREDUMP'], + ['crypttab', '5', [], 'HAVE_LIBCRYPTSETUP'], + ['daemon', '7', [], ''], + ['dnssec-trust-anchors.d', + '5', + ['systemd.negative', 'systemd.positive'], + 'ENABLE_RESOLVE'], + ['environment.d', '5', [], 'ENABLE_ENVIRONMENT_D'], + ['file-hierarchy', '7', [], ''], + ['halt', '8', ['poweroff', 'reboot'], ''], + ['hostname', '5', [], ''], + ['hostnamectl', '1', [], 'ENABLE_HOSTNAMED'], + ['hwdb', '7', [], 'ENABLE_HWDB'], + ['journal-remote.conf', '5', ['journal-remote.conf.d'], 'HAVE_MICROHTTPD'], + ['journal-upload.conf', '5', ['journal-upload.conf.d'], 'HAVE_MICROHTTPD'], + ['journalctl', '1', [], ''], + ['journald.conf', '5', ['journald.conf.d'], ''], + ['kernel-command-line', '7', [], ''], + ['kernel-install', '8', [], ''], + ['libudev', '3', [], ''], + ['loader.conf', '5', [], 'ENABLE_EFI'], + ['locale.conf', '5', [], ''], + ['localectl', '1', [], 'ENABLE_LOCALED'], + ['localtime', '5', [], ''], + ['loginctl', '1', [], 'ENABLE_LOGIND'], + ['logind.conf', '5', ['logind.conf.d'], 'ENABLE_LOGIND'], + ['machine-id', '5', [], ''], + ['machine-info', '5', [], ''], + ['machinectl', '1', [], 'ENABLE_MACHINED'], + ['modules-load.d', '5', [], 'HAVE_KMOD'], + ['networkctl', '1', [], 'ENABLE_NETWORKD'], + ['networkd.conf', '5', ['networkd.conf.d'], 'ENABLE_NETWORKD'], + ['nss-myhostname', '8', ['libnss_myhostname.so.2'], 'ENABLE_NSS_MYHOSTNAME'], + ['nss-mymachines', '8', ['libnss_mymachines.so.2'], 'ENABLE_NSS_MYMACHINES'], + ['nss-resolve', '8', ['libnss_resolve.so.2'], 'ENABLE_NSS_RESOLVE'], + ['nss-systemd', '8', ['libnss_systemd.so.2'], 'ENABLE_NSS_SYSTEMD'], + ['os-release', '5', [], ''], + ['pam_systemd', '8', [], 'HAVE_PAM'], + ['portablectl', '1', [], 'ENABLE_PORTABLED'], + ['pstore.conf', '5', ['pstore.conf.d'], 'ENABLE_PSTORE'], + ['resolvectl', '1', ['resolvconf'], 'ENABLE_RESOLVE'], + ['resolved.conf', '5', ['resolved.conf.d'], 'ENABLE_RESOLVE'], + ['runlevel', '8', [], ''], + ['sd-bus-errors', + '3', + ['SD_BUS_ERROR_ACCESS_DENIED', + 'SD_BUS_ERROR_ADDRESS_IN_USE', + 'SD_BUS_ERROR_AUTH_FAILED', + 'SD_BUS_ERROR_BAD_ADDRESS', + 'SD_BUS_ERROR_DISCONNECTED', + 'SD_BUS_ERROR_FAILED', + 'SD_BUS_ERROR_FILE_EXISTS', + 'SD_BUS_ERROR_FILE_NOT_FOUND', + 'SD_BUS_ERROR_INCONSISTENT_MESSAGE', + 'SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED', + 'SD_BUS_ERROR_INVALID_ARGS', + 'SD_BUS_ERROR_INVALID_SIGNATURE', + 'SD_BUS_ERROR_IO_ERROR', + 'SD_BUS_ERROR_LIMITS_EXCEEDED', + 'SD_BUS_ERROR_MATCH_RULE_INVALID', + 'SD_BUS_ERROR_MATCH_RULE_NOT_FOUND', + 'SD_BUS_ERROR_NAME_HAS_NO_OWNER', + 'SD_BUS_ERROR_NOT_SUPPORTED', + 'SD_BUS_ERROR_NO_MEMORY', + 'SD_BUS_ERROR_NO_NETWORK', + 'SD_BUS_ERROR_NO_REPLY', + 'SD_BUS_ERROR_NO_SERVER', + 'SD_BUS_ERROR_PROPERTY_READ_ONLY', + 'SD_BUS_ERROR_SERVICE_UNKNOWN', + 'SD_BUS_ERROR_TIMEOUT', + 'SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN', + 'SD_BUS_ERROR_UNKNOWN_INTERFACE', + 'SD_BUS_ERROR_UNKNOWN_METHOD', + 'SD_BUS_ERROR_UNKNOWN_OBJECT', + 'SD_BUS_ERROR_UNKNOWN_PROPERTY'], + ''], + ['sd-bus', '3', [], ''], + ['sd-daemon', + '3', + ['SD_ALERT', + 'SD_CRIT', + 'SD_DEBUG', + 'SD_EMERG', + 'SD_ERR', + 'SD_INFO', + 'SD_NOTICE', + 'SD_WARNING'], + ''], + ['sd-event', '3', [], ''], + ['sd-id128', + '3', + ['SD_ID128_CONST_STR', + 'SD_ID128_FORMAT_STR', + 'SD_ID128_FORMAT_VAL', + 'SD_ID128_MAKE', + 'SD_ID128_MAKE_STR', + 'SD_ID128_NULL', + 'SD_ID128_UUID_FORMAT_STR', + 'sd_id128_equal', + 'sd_id128_is_null', + 'sd_id128_t'], + ''], + ['sd-journal', '3', [], ''], + ['sd-login', '3', [], 'HAVE_PAM'], + ['sd_booted', '3', [], ''], + ['sd_bus_add_match', + '3', + ['sd_bus_add_match_async', + 'sd_bus_match_signal', + 'sd_bus_match_signal_async'], + ''], + ['sd_bus_add_object_vtable', + '3', + ['SD_BUS_METHOD', + 'SD_BUS_METHOD_WITH_NAMES', + 'SD_BUS_METHOD_WITH_NAMES_OFFSET', + 'SD_BUS_METHOD_WITH_OFFSET', + 'SD_BUS_PARAM', + 'SD_BUS_PROPERTY', + 'SD_BUS_SIGNAL', + 'SD_BUS_SIGNAL_WITH_NAMES', + 'SD_BUS_VTABLE_END', + 'SD_BUS_VTABLE_START', + 'SD_BUS_WRITABLE_PROPERTY', + 'sd_bus_add_fallback_vtable'], + ''], + ['sd_bus_attach_event', '3', ['sd_bus_detach_event', 'sd_bus_get_event'], ''], + ['sd_bus_close', '3', ['sd_bus_flush'], ''], + ['sd_bus_creds_get_pid', + '3', + ['sd_bus_creds_get_audit_login_uid', + 'sd_bus_creds_get_audit_session_id', + 'sd_bus_creds_get_cgroup', + 'sd_bus_creds_get_cmdline', + 'sd_bus_creds_get_comm', + 'sd_bus_creds_get_description', + 'sd_bus_creds_get_egid', + 'sd_bus_creds_get_euid', + 'sd_bus_creds_get_exe', + 'sd_bus_creds_get_fsgid', + 'sd_bus_creds_get_fsuid', + 'sd_bus_creds_get_gid', + 'sd_bus_creds_get_owner_uid', + 'sd_bus_creds_get_ppid', + 'sd_bus_creds_get_selinux_context', + 'sd_bus_creds_get_session', + 'sd_bus_creds_get_sgid', + 'sd_bus_creds_get_slice', + 'sd_bus_creds_get_suid', + 'sd_bus_creds_get_supplementary_gids', + 'sd_bus_creds_get_tid', + 'sd_bus_creds_get_tid_comm', + 'sd_bus_creds_get_tty', + 'sd_bus_creds_get_uid', + 'sd_bus_creds_get_unique_name', + 'sd_bus_creds_get_unit', + 'sd_bus_creds_get_user_slice', + 'sd_bus_creds_get_user_unit', + 'sd_bus_creds_get_well_known_names', + 'sd_bus_creds_has_bounding_cap', + 'sd_bus_creds_has_effective_cap', + 'sd_bus_creds_has_inheritable_cap', + 'sd_bus_creds_has_permitted_cap'], + ''], + ['sd_bus_creds_new_from_pid', + '3', + ['sd_bus_creds_get_augmented_mask', + 'sd_bus_creds_get_mask', + 'sd_bus_creds_ref', + 'sd_bus_creds_unref', + 'sd_bus_creds_unrefp'], + ''], + ['sd_bus_default', + '3', + ['sd_bus_default_system', + 'sd_bus_default_user', + 'sd_bus_open', + 'sd_bus_open_system', + 'sd_bus_open_system_machine', + 'sd_bus_open_system_remote', + 'sd_bus_open_system_with_description', + 'sd_bus_open_user', + 'sd_bus_open_user_with_description', + 'sd_bus_open_with_description'], + ''], + ['sd_bus_error', + '3', + ['SD_BUS_ERROR_MAKE_CONST', + 'SD_BUS_ERROR_NULL', + 'sd_bus_error_copy', + 'sd_bus_error_free', + 'sd_bus_error_get_errno', + 'sd_bus_error_has_name', + 'sd_bus_error_is_set', + 'sd_bus_error_move', + 'sd_bus_error_set', + 'sd_bus_error_set_const', + 'sd_bus_error_set_errno', + 'sd_bus_error_set_errnof', + 'sd_bus_error_set_errnofv', + 'sd_bus_error_setf'], + ''], + ['sd_bus_error_add_map', + '3', + ['SD_BUS_ERROR_END', 'SD_BUS_ERROR_MAP', 'sd_bus_error_map'], + ''], + ['sd_bus_get_fd', '3', ['sd_bus_get_events', 'sd_bus_get_timeout'], ''], + ['sd_bus_get_n_queued_read', '3', ['sd_bus_get_n_queued_write'], ''], + ['sd_bus_is_open', '3', ['sd_bus_is_ready'], ''], + ['sd_bus_message_append', '3', ['sd_bus_message_appendv'], ''], + ['sd_bus_message_append_array', + '3', + ['sd_bus_message_append_array_iovec', + 'sd_bus_message_append_array_memfd', + 'sd_bus_message_append_array_space'], + ''], + ['sd_bus_message_append_basic', '3', [], ''], + ['sd_bus_message_append_string_memfd', + '3', + ['sd_bus_message_append_string_iovec', 'sd_bus_message_append_string_space'], + ''], + ['sd_bus_message_append_strv', '3', [], ''], + ['sd_bus_message_copy', '3', [], ''], + ['sd_bus_message_get_cookie', '3', ['sd_bus_message_get_reply_cookie'], ''], + ['sd_bus_message_get_monotonic_usec', + '3', + ['sd_bus_message_get_realtime_usec', 'sd_bus_message_get_seqnum'], + ''], + ['sd_bus_message_get_signature', + '3', + ['sd_bus_message_has_signature', 'sd_bus_message_is_empty'], + ''], + ['sd_bus_message_get_type', + '3', + ['sd_bus_message_is_method_call', + 'sd_bus_message_is_method_error', + 'sd_bus_message_is_signal'], + ''], + ['sd_bus_message_new', + '3', + ['SD_BUS_MESSAGE_METHOD_CALL', + 'SD_BUS_MESSAGE_METHOD_ERROR', + 'SD_BUS_MESSAGE_METHOD_RETURN', + 'SD_BUS_MESSAGE_SIGNAL', + 'sd_bus_message_get_bus', + 'sd_bus_message_ref', + 'sd_bus_message_unref', + 'sd_bus_message_unrefp'], + ''], + ['sd_bus_message_new_method_call', + '3', + ['sd_bus_message_new_method_return'], + ''], + ['sd_bus_message_new_method_error', + '3', + ['sd_bus_message_new_method_errno', + 'sd_bus_message_new_method_errnof', + 'sd_bus_message_new_method_errorf'], + ''], + ['sd_bus_message_new_signal', '3', [], ''], + ['sd_bus_message_read', '3', ['sd_bus_message_readv'], ''], + ['sd_bus_message_read_array', '3', [], ''], + ['sd_bus_message_read_basic', '3', [], ''], + ['sd_bus_message_rewind', '3', [], ''], + ['sd_bus_message_set_destination', + '3', + ['sd_bus_message_get_destination', + 'sd_bus_message_get_interface', + 'sd_bus_message_get_member', + 'sd_bus_message_get_path', + 'sd_bus_message_get_sender', + 'sd_bus_message_set_sender'], + ''], + ['sd_bus_message_set_expect_reply', + '3', + ['sd_bus_message_get_auto_start', + 'sd_bus_message_get_expect_reply', + 'sd_bus_message_set_auto_start'], + ''], + ['sd_bus_message_skip', '3', [], ''], + ['sd_bus_message_verify_type', '3', [], ''], + ['sd_bus_negotiate_fds', + '3', + ['sd_bus_negotiate_creds', 'sd_bus_negotiate_timestamp'], + ''], + ['sd_bus_new', + '3', + ['sd_bus_close_unref', + 'sd_bus_close_unrefp', + 'sd_bus_flush_close_unref', + 'sd_bus_flush_close_unrefp', + 'sd_bus_ref', + 'sd_bus_unref', + 'sd_bus_unrefp'], + ''], + ['sd_bus_path_encode', + '3', + ['sd_bus_path_decode', 'sd_bus_path_decode_many', 'sd_bus_path_encode_many'], + ''], + ['sd_bus_process', '3', [], ''], + ['sd_bus_reply_method_error', + '3', + ['sd_bus_reply_method_errno', + 'sd_bus_reply_method_errnof', + 'sd_bus_reply_method_errorf'], + ''], + ['sd_bus_request_name', + '3', + ['sd_bus_release_name', + 'sd_bus_release_name_async', + 'sd_bus_request_name_async'], + ''], + ['sd_bus_set_close_on_exit', '3', ['sd_bus_get_close_on_exit'], ''], + ['sd_bus_set_connected_signal', '3', ['sd_bus_get_connected_signal'], ''], + ['sd_bus_set_description', + '3', + ['sd_bus_get_allow_interactive_authorization', + 'sd_bus_get_description', + 'sd_bus_set_allow_interactive_authorization', + 'sd_bus_set_anonymous', + 'sd_bus_set_trusted'], + ''], + ['sd_bus_set_sender', '3', ['sd_bus_get_sender'], ''], + ['sd_bus_set_watch_bind', '3', ['sd_bus_get_watch_bind'], ''], + ['sd_bus_slot_ref', + '3', + ['sd_bus_slot_get_bus', 'sd_bus_slot_unref', 'sd_bus_slot_unrefp'], + ''], + ['sd_bus_slot_set_description', '3', ['sd_bus_slot_get_description'], ''], + ['sd_bus_slot_set_destroy_callback', + '3', + ['sd_bus_destroy_t', + 'sd_bus_slot_get_destroy_callback', + 'sd_bus_track_get_destroy_callback', + 'sd_bus_track_set_destroy_callback'], + ''], + ['sd_bus_slot_set_floating', '3', ['sd_bus_slot_get_floating'], ''], + ['sd_bus_slot_set_userdata', '3', ['sd_bus_slot_get_userdata'], ''], + ['sd_bus_track_add_name', + '3', + ['sd_bus_track_add_sender', + 'sd_bus_track_contains', + 'sd_bus_track_count', + 'sd_bus_track_count_name', + 'sd_bus_track_count_sender', + 'sd_bus_track_first', + 'sd_bus_track_next', + 'sd_bus_track_remove_name', + 'sd_bus_track_remove_sender'], + ''], + ['sd_bus_track_new', + '3', + ['sd_bus_track_get_bus', + 'sd_bus_track_get_recursive', + 'sd_bus_track_get_userdata', + 'sd_bus_track_ref', + 'sd_bus_track_set_recursive', + 'sd_bus_track_set_userdata', + 'sd_bus_track_unref', + 'sd_bus_track_unrefp'], + ''], + ['sd_bus_wait', '3', [], ''], + ['sd_event_add_child', + '3', + ['sd_event_child_handler_t', 'sd_event_source_get_child_pid'], + ''], + ['sd_event_add_defer', + '3', + ['sd_event_add_exit', 'sd_event_add_post', 'sd_event_handler_t'], + ''], + ['sd_event_add_inotify', + '3', + ['sd_event_inotify_handler_t', 'sd_event_source_get_inotify_mask'], + ''], + ['sd_event_add_io', + '3', + ['sd_event_io_handler_t', + 'sd_event_source', + 'sd_event_source_get_io_events', + 'sd_event_source_get_io_fd', + 'sd_event_source_get_io_fd_own', + 'sd_event_source_get_io_revents', + 'sd_event_source_set_io_events', + 'sd_event_source_set_io_fd', + 'sd_event_source_set_io_fd_own'], + ''], + ['sd_event_add_signal', + '3', + ['sd_event_signal_handler_t', 'sd_event_source_get_signal'], + ''], + ['sd_event_add_time', + '3', + ['sd_event_source_get_time', + 'sd_event_source_get_time_accuracy', + 'sd_event_source_get_time_clock', + 'sd_event_source_set_time', + 'sd_event_source_set_time_accuracy', + 'sd_event_time_handler_t'], + ''], + ['sd_event_exit', '3', ['sd_event_get_exit_code'], ''], + ['sd_event_get_fd', '3', [], ''], + ['sd_event_new', + '3', + ['sd_event', + 'sd_event_default', + 'sd_event_get_tid', + 'sd_event_ref', + 'sd_event_unref', + 'sd_event_unrefp'], + ''], + ['sd_event_now', '3', [], ''], + ['sd_event_run', '3', ['sd_event_loop'], ''], + ['sd_event_set_watchdog', '3', ['sd_event_get_watchdog'], ''], + ['sd_event_source_get_event', '3', [], ''], + ['sd_event_source_get_pending', '3', [], ''], + ['sd_event_source_set_description', + '3', + ['sd_event_source_get_description'], + ''], + ['sd_event_source_set_destroy_callback', + '3', + ['sd_event_destroy_t', 'sd_event_source_get_destroy_callback'], + ''], + ['sd_event_source_set_enabled', + '3', + ['SD_EVENT_OFF', + 'SD_EVENT_ON', + 'SD_EVENT_ONESHOT', + 'sd_event_source_get_enabled'], + ''], + ['sd_event_source_set_floating', '3', ['sd_event_source_get_floating'], ''], + ['sd_event_source_set_prepare', '3', [], ''], + ['sd_event_source_set_priority', + '3', + ['SD_EVENT_PRIORITY_IDLE', + 'SD_EVENT_PRIORITY_IMPORTANT', + 'SD_EVENT_PRIORITY_NORMAL', + 'sd_event_source_get_priority'], + ''], + ['sd_event_source_set_userdata', '3', ['sd_event_source_get_userdata'], ''], + ['sd_event_source_unref', + '3', + ['sd_event_source_disable_unref', + 'sd_event_source_disable_unrefp', + 'sd_event_source_ref', + 'sd_event_source_unrefp'], + ''], + ['sd_event_wait', + '3', + ['SD_EVENT_ARMED', + 'SD_EVENT_EXITING', + 'SD_EVENT_FINISHED', + 'SD_EVENT_INITIAL', + 'SD_EVENT_PENDING', + 'SD_EVENT_PREPARING', + 'SD_EVENT_RUNNING', + 'sd_event_dispatch', + 'sd_event_get_iteration', + 'sd_event_get_state', + 'sd_event_prepare'], + ''], + ['sd_get_seats', + '3', + ['sd_get_machine_names', 'sd_get_sessions', 'sd_get_uids'], + 'HAVE_PAM'], + ['sd_id128_get_machine', + '3', + ['sd_id128_get_boot', + 'sd_id128_get_boot_app_specific', + 'sd_id128_get_invocation', + 'sd_id128_get_machine_app_specific'], + ''], + ['sd_id128_randomize', '3', [], ''], + ['sd_id128_to_string', '3', ['sd_id128_from_string'], ''], + ['sd_is_fifo', + '3', + ['sd_is_mq', + 'sd_is_socket', + 'sd_is_socket_inet', + 'sd_is_socket_sockaddr', + 'sd_is_socket_unix', + 'sd_is_special'], + ''], + ['sd_journal_add_match', + '3', + ['sd_journal_add_conjunction', + 'sd_journal_add_disjunction', + 'sd_journal_flush_matches'], + ''], + ['sd_journal_enumerate_fields', + '3', + ['SD_JOURNAL_FOREACH_FIELD', 'sd_journal_restart_fields'], + ''], + ['sd_journal_get_catalog', '3', ['sd_journal_get_catalog_for_message_id'], ''], + ['sd_journal_get_cursor', '3', ['sd_journal_test_cursor'], ''], + ['sd_journal_get_cutoff_realtime_usec', + '3', + ['sd_journal_get_cutoff_monotonic_usec'], + ''], + ['sd_journal_get_data', + '3', + ['SD_JOURNAL_FOREACH_DATA', + 'sd_journal_enumerate_data', + 'sd_journal_get_data_threshold', + 'sd_journal_restart_data', + 'sd_journal_set_data_threshold'], + ''], + ['sd_journal_get_fd', + '3', + ['SD_JOURNAL_APPEND', + 'SD_JOURNAL_INVALIDATE', + 'SD_JOURNAL_NOP', + 'sd_journal_get_events', + 'sd_journal_get_timeout', + 'sd_journal_process', + 'sd_journal_reliable_fd', + 'sd_journal_wait'], + ''], + ['sd_journal_get_realtime_usec', '3', ['sd_journal_get_monotonic_usec'], ''], + ['sd_journal_get_usage', '3', [], ''], + ['sd_journal_has_runtime_files', '3', ['sd_journal_has_persistent_files'], ''], + ['sd_journal_next', + '3', + ['SD_JOURNAL_FOREACH', + 'SD_JOURNAL_FOREACH_BACKWARDS', + 'sd_journal_next_skip', + 'sd_journal_previous', + 'sd_journal_previous_skip'], + ''], + ['sd_journal_open', + '3', + ['SD_JOURNAL_CURRENT_USER', + 'SD_JOURNAL_LOCAL_ONLY', + 'SD_JOURNAL_OS_ROOT', + 'SD_JOURNAL_RUNTIME_ONLY', + 'SD_JOURNAL_SYSTEM', + 'sd_journal', + 'sd_journal_close', + 'sd_journal_open_directory', + 'sd_journal_open_directory_fd', + 'sd_journal_open_files', + 'sd_journal_open_files_fd'], + ''], + ['sd_journal_print', + '3', + ['SD_JOURNAL_SUPPRESS_LOCATION', + 'sd_journal_perror', + 'sd_journal_printv', + 'sd_journal_send', + 'sd_journal_sendv'], + ''], + ['sd_journal_query_unique', + '3', + ['SD_JOURNAL_FOREACH_UNIQUE', + 'sd_journal_enumerate_unique', + 'sd_journal_restart_unique'], + ''], + ['sd_journal_seek_head', + '3', + ['sd_journal_seek_cursor', + 'sd_journal_seek_monotonic_usec', + 'sd_journal_seek_realtime_usec', + 'sd_journal_seek_tail'], + ''], + ['sd_journal_stream_fd', '3', [], ''], + ['sd_listen_fds', + '3', + ['SD_LISTEN_FDS_START', 'sd_listen_fds_with_names'], + ''], + ['sd_login_monitor_new', + '3', + ['sd_login_monitor', + 'sd_login_monitor_flush', + 'sd_login_monitor_get_events', + 'sd_login_monitor_get_fd', + 'sd_login_monitor_get_timeout', + 'sd_login_monitor_unref', + 'sd_login_monitor_unrefp'], + 'HAVE_PAM'], + ['sd_machine_get_class', '3', ['sd_machine_get_ifindices'], ''], + ['sd_notify', + '3', + ['sd_notifyf', 'sd_pid_notify', 'sd_pid_notify_with_fds', 'sd_pid_notifyf'], + ''], + ['sd_pid_get_owner_uid', + '3', + ['sd_peer_get_cgroup', + 'sd_peer_get_machine_name', + 'sd_peer_get_owner_uid', + 'sd_peer_get_session', + 'sd_peer_get_slice', + 'sd_peer_get_unit', + 'sd_peer_get_user_slice', + 'sd_peer_get_user_unit', + 'sd_pid_get_cgroup', + 'sd_pid_get_machine_name', + 'sd_pid_get_session', + 'sd_pid_get_slice', + 'sd_pid_get_unit', + 'sd_pid_get_user_slice', + 'sd_pid_get_user_unit'], + 'HAVE_PAM'], + ['sd_seat_get_active', + '3', + ['sd_seat_can_graphical', + 'sd_seat_can_multi_session', + 'sd_seat_can_tty', + 'sd_seat_get_sessions'], + 'HAVE_PAM'], + ['sd_session_is_active', + '3', + ['sd_session_get_class', + 'sd_session_get_desktop', + 'sd_session_get_display', + 'sd_session_get_remote_host', + 'sd_session_get_remote_user', + 'sd_session_get_seat', + 'sd_session_get_service', + 'sd_session_get_state', + 'sd_session_get_tty', + 'sd_session_get_type', + 'sd_session_get_uid', + 'sd_session_get_vt', + 'sd_session_is_remote'], + 'HAVE_PAM'], + ['sd_uid_get_state', + '3', + ['sd_uid_get_display', + 'sd_uid_get_seats', + 'sd_uid_get_sessions', + 'sd_uid_is_on_seat'], + 'HAVE_PAM'], + ['sd_watchdog_enabled', '3', [], ''], + ['shutdown', '8', [], ''], + ['sysctl.d', '5', [], ''], + ['systemctl', '1', [], ''], + ['systemd-analyze', '1', [], ''], + ['systemd-ask-password-console.service', + '8', + ['systemd-ask-password-console.path', + 'systemd-ask-password-wall.path', + 'systemd-ask-password-wall.service'], + ''], + ['systemd-ask-password', '1', [], ''], + ['systemd-backlight@.service', '8', ['systemd-backlight'], 'ENABLE_BACKLIGHT'], + ['systemd-binfmt.service', '8', ['systemd-binfmt'], 'ENABLE_BINFMT'], + ['systemd-bless-boot-generator', '8', [], 'ENABLE_EFI'], + ['systemd-bless-boot.service', '8', [], 'ENABLE_EFI'], + ['systemd-boot-check-no-failures.service', '8', [], ''], + ['systemd-boot-system-token.service', '8', [], 'ENABLE_EFI'], + ['systemd-boot', '7', ['sd-boot'], 'ENABLE_EFI'], + ['systemd-cat', '1', [], ''], + ['systemd-cgls', '1', [], ''], + ['systemd-cgtop', '1', [], ''], + ['systemd-coredump', + '8', + ['systemd-coredump.socket', 'systemd-coredump@.service'], + 'ENABLE_COREDUMP'], + ['systemd-cryptsetup-generator', '8', [], 'HAVE_LIBCRYPTSETUP'], + ['systemd-cryptsetup@.service', + '8', + ['systemd-cryptsetup'], + 'HAVE_LIBCRYPTSETUP'], + ['systemd-debug-generator', '8', [], ''], + ['systemd-delta', '1', [], ''], + ['systemd-detect-virt', '1', [], ''], + ['systemd-environment-d-generator', + '8', + ['30-systemd-environment-d-generator'], + 'ENABLE_ENVIRONMENT_D'], + ['systemd-escape', '1', [], ''], + ['systemd-firstboot', '1', ['systemd-firstboot.service'], 'ENABLE_FIRSTBOOT'], + ['systemd-fsck@.service', + '8', + ['systemd-fsck', 'systemd-fsck-root.service'], + ''], + ['systemd-fstab-generator', '8', [], ''], + ['systemd-getty-generator', '8', [], ''], + ['systemd-gpt-auto-generator', '8', [], ''], + ['systemd-halt.service', + '8', + ['systemd-kexec.service', + 'systemd-poweroff.service', + 'systemd-reboot.service', + 'systemd-shutdown'], + ''], + ['systemd-hibernate-resume-generator', '8', [], 'ENABLE_HIBERNATE'], + ['systemd-hibernate-resume@.service', + '8', + ['systemd-hibernate-resume'], + 'ENABLE_HIBERNATE'], + ['systemd-hostnamed.service', '8', ['systemd-hostnamed'], 'ENABLE_HOSTNAMED'], + ['systemd-hwdb', '8', [], 'ENABLE_HWDB'], + ['systemd-id128', '1', [], ''], + ['systemd-importd.service', '8', ['systemd-importd'], 'ENABLE_IMPORTD'], + ['systemd-inhibit', '1', [], ''], + ['systemd-initctl.service', + '8', + ['systemd-initctl', 'systemd-initctl.socket'], + ''], + ['systemd-journal-gatewayd.service', + '8', + ['systemd-journal-gatewayd', 'systemd-journal-gatewayd.socket'], + 'HAVE_MICROHTTPD'], + ['systemd-journal-remote.service', + '8', + ['systemd-journal-remote', 'systemd-journal-remote.socket'], + 'HAVE_MICROHTTPD'], + ['systemd-journal-upload.service', + '8', + ['systemd-journal-upload'], + 'HAVE_MICROHTTPD'], + ['systemd-journald.service', + '8', + ['systemd-journald', + 'systemd-journald-audit.socket', + 'systemd-journald-dev-log.socket', + 'systemd-journald.socket'], + ''], + ['systemd-localed.service', '8', ['systemd-localed'], 'ENABLE_LOCALED'], + ['systemd-logind.service', '8', ['systemd-logind'], 'ENABLE_LOGIND'], + ['systemd-machine-id-commit.service', '8', [], ''], + ['systemd-machine-id-setup', '1', [], ''], + ['systemd-machined.service', '8', ['systemd-machined'], 'ENABLE_MACHINED'], + ['systemd-makefs@.service', + '8', + ['systemd-growfs', + 'systemd-growfs@.service', + 'systemd-makefs', + 'systemd-mkswap@.service'], + ''], + ['systemd-modules-load.service', '8', ['systemd-modules-load'], 'HAVE_KMOD'], + ['systemd-mount', '1', ['systemd-umount'], ''], + ['systemd-networkd-wait-online.service', + '8', + ['systemd-networkd-wait-online'], + 'ENABLE_NETWORKD'], + ['systemd-networkd.service', '8', ['systemd-networkd'], 'ENABLE_NETWORKD'], + ['systemd-notify', '1', [], ''], + ['systemd-nspawn', '1', [], ''], + ['systemd-path', '1', [], ''], + ['systemd-portabled.service', '8', ['systemd-portabled'], 'ENABLE_PORTABLED'], + ['systemd-pstore', '8', ['systemd-pstore.service'], 'ENABLE_PSTORE'], + ['systemd-quotacheck.service', + '8', + ['systemd-quotacheck'], + 'ENABLE_QUOTACHECK'], + ['systemd-random-seed.service', + '8', + ['systemd-random-seed'], + 'ENABLE_RANDOMSEED'], + ['systemd-rc-local-generator', '8', [], ''], + ['systemd-remount-fs.service', '8', ['systemd-remount-fs'], ''], + ['systemd-resolved.service', '8', ['systemd-resolved'], 'ENABLE_RESOLVE'], + ['systemd-rfkill.service', + '8', + ['systemd-rfkill', 'systemd-rfkill.socket'], + 'ENABLE_RFKILL'], + ['systemd-run-generator', '8', [], ''], + ['systemd-run', '1', [], ''], + ['systemd-sleep.conf', '5', ['sleep.conf.d'], ''], + ['systemd-socket-activate', '1', [], ''], + ['systemd-socket-proxyd', '8', [], ''], + ['systemd-suspend.service', + '8', + ['systemd-hibernate.service', + 'systemd-hybrid-sleep.service', + 'systemd-sleep', + 'systemd-suspend-then-hibernate.service'], + ''], + ['systemd-sysctl.service', '8', ['systemd-sysctl'], ''], + ['systemd-system-update-generator', '8', [], ''], + ['systemd-system.conf', + '5', + ['system.conf.d', 'systemd-user.conf', 'user.conf.d'], + ''], + ['systemd-sysusers', '8', ['systemd-sysusers.service'], ''], + ['systemd-sysv-generator', '8', [], 'HAVE_SYSV_COMPAT'], + ['systemd-time-wait-sync.service', + '8', + ['systemd-time-wait-sync'], + 'ENABLE_TIMESYNCD'], + ['systemd-timedated.service', '8', ['systemd-timedated'], 'ENABLE_TIMEDATED'], + ['systemd-timesyncd.service', '8', ['systemd-timesyncd'], 'ENABLE_TIMESYNCD'], + ['systemd-tmpfiles', + '8', + ['systemd-tmpfiles-clean.service', + 'systemd-tmpfiles-clean.timer', + 'systemd-tmpfiles-setup-dev.service', + 'systemd-tmpfiles-setup.service'], + ''], + ['systemd-tty-ask-password-agent', '1', [], ''], + ['systemd-udev-settle.service', '8', [], ''], + ['systemd-udevd.service', + '8', + ['systemd-udevd', + 'systemd-udevd-control.socket', + 'systemd-udevd-kernel.socket'], + ''], + ['systemd-update-done.service', '8', ['systemd-update-done'], ''], + ['systemd-update-utmp.service', + '8', + ['systemd-update-utmp', 'systemd-update-utmp-runlevel.service'], + 'ENABLE_UTMP'], + ['systemd-user-sessions.service', '8', ['systemd-user-sessions'], 'HAVE_PAM'], + ['systemd-vconsole-setup.service', + '8', + ['systemd-vconsole-setup'], + 'ENABLE_VCONSOLE'], + ['systemd-veritysetup-generator', '8', [], 'HAVE_LIBCRYPTSETUP'], + ['systemd-veritysetup@.service', + '8', + ['systemd-veritysetup'], + 'HAVE_LIBCRYPTSETUP'], + ['systemd-volatile-root.service', '8', ['systemd-volatile-root'], ''], + ['systemd', '1', ['init'], ''], + ['systemd.automount', '5', [], ''], + ['systemd.device', '5', [], ''], + ['systemd.dnssd', '5', [], 'ENABLE_RESOLVE'], + ['systemd.environment-generator', '7', [], 'ENABLE_ENVIRONMENT_D'], + ['systemd.exec', '5', [], ''], + ['systemd.generator', '7', [], ''], + ['systemd.journal-fields', '7', [], ''], + ['systemd.kill', '5', [], ''], + ['systemd.link', '5', [], ''], + ['systemd.mount', '5', [], ''], + ['systemd.net-naming-scheme', '7', [], ''], + ['systemd.netdev', '5', [], 'ENABLE_NETWORKD'], + ['systemd.network', '5', [], 'ENABLE_NETWORKD'], + ['systemd.nspawn', '5', [], ''], + ['systemd.offline-updates', '7', [], ''], + ['systemd.path', '5', [], ''], + ['systemd.preset', '5', [], ''], + ['systemd.resource-control', '5', [], ''], + ['systemd.scope', '5', [], ''], + ['systemd.service', '5', [], ''], + ['systemd.slice', '5', [], ''], + ['systemd.socket', '5', [], ''], + ['systemd.special', '7', [], ''], + ['systemd.swap', '5', [], ''], + ['systemd.syntax', '7', [], ''], + ['systemd.target', '5', [], ''], + ['systemd.time', '7', [], ''], + ['systemd.timer', '5', [], ''], + ['systemd.unit', '5', [], ''], + ['sysusers.d', '5', [], 'ENABLE_SYSUSERS'], + ['telinit', '8', [], ''], + ['timedatectl', '1', [], 'ENABLE_TIMEDATECTL'], + ['timesyncd.conf', '5', ['timesyncd.conf.d'], 'ENABLE_TIMESYNCD'], + ['tmpfiles.d', '5', [], ''], + ['udev', '7', [], ''], + ['udev.conf', '5', [], ''], + ['udev_device_get_syspath', + '3', + ['udev_device_get_action', + 'udev_device_get_devnode', + 'udev_device_get_devnum', + 'udev_device_get_devpath', + 'udev_device_get_devtype', + 'udev_device_get_driver', + 'udev_device_get_is_initialized', + 'udev_device_get_parent', + 'udev_device_get_parent_with_subsystem_devtype', + 'udev_device_get_subsystem', + 'udev_device_get_sysname', + 'udev_device_get_sysnum', + 'udev_device_get_udev'], + ''], + ['udev_device_has_tag', + '3', + ['udev_device_get_devlinks_list_entry', + 'udev_device_get_properties_list_entry', + 'udev_device_get_property_value', + 'udev_device_get_sysattr_list_entry', + 'udev_device_get_sysattr_value', + 'udev_device_get_tags_list_entry', + 'udev_device_set_sysattr_value'], + ''], + ['udev_device_new_from_syspath', + '3', + ['udev_device_new_from_device_id', + 'udev_device_new_from_devnum', + 'udev_device_new_from_environment', + 'udev_device_new_from_subsystem_sysname', + 'udev_device_ref', + 'udev_device_unref'], + ''], + ['udev_enumerate_add_match_subsystem', + '3', + ['udev_enumerate_add_match_is_initialized', + 'udev_enumerate_add_match_parent', + 'udev_enumerate_add_match_property', + 'udev_enumerate_add_match_sysattr', + 'udev_enumerate_add_match_sysname', + 'udev_enumerate_add_match_tag', + 'udev_enumerate_add_nomatch_subsystem', + 'udev_enumerate_add_nomatch_sysattr'], + ''], + ['udev_enumerate_new', + '3', + ['udev_enumerate_ref', 'udev_enumerate_unref'], + ''], + ['udev_enumerate_scan_devices', + '3', + ['udev_enumerate_add_syspath', + 'udev_enumerate_get_list_entry', + 'udev_enumerate_get_udev', + 'udev_enumerate_scan_subsystems'], + ''], + ['udev_list_entry', + '3', + ['udev_list_entry_get_by_name', + 'udev_list_entry_get_name', + 'udev_list_entry_get_next', + 'udev_list_entry_get_value'], + ''], + ['udev_monitor_filter_update', + '3', + ['udev_monitor_filter_add_match_subsystem_devtype', + 'udev_monitor_filter_add_match_tag', + 'udev_monitor_filter_remove'], + ''], + ['udev_monitor_new_from_netlink', + '3', + ['udev_monitor_ref', 'udev_monitor_unref'], + ''], + ['udev_monitor_receive_device', + '3', + ['udev_monitor_enable_receiving', + 'udev_monitor_get_fd', + 'udev_monitor_get_udev', + 'udev_monitor_set_receive_buffer_size'], + ''], + ['udev_new', '3', ['udev_ref', 'udev_unref'], ''], + ['udevadm', '8', [], ''], + ['user@.service', '5', ['user-runtime-dir@.service'], ''], + ['vconsole.conf', '5', [], 'ENABLE_VCONSOLE'] +] +# Really, do not edit. diff --git a/man/runlevel.xml b/man/runlevel.xml new file mode 100644 index 00000000..87e2ed23 --- /dev/null +++ b/man/runlevel.xml @@ -0,0 +1,163 @@ + + + + + + + + runlevel + systemd + + + + runlevel + 8 + + + + runlevel + Print previous and current SysV runlevel + + + + + runlevel + options + + + + + Overview + + "Runlevels" are an obsolete way to start and stop groups of + services used in SysV init. systemd provides a compatibility layer + that maps runlevels to targets, and associated binaries like + runlevel. Nevertheless, only one runlevel can + be "active" at a given time, while systemd can activate multiple + targets concurrently, so the mapping to runlevels is confusing + and only approximate. Runlevels should not be used in new code, + and are mostly useful as a shorthand way to refer the matching + systemd targets in kernel boot parameters. + + + Mapping between runlevels and systemd targets + + + + + + Runlevel + Target + + + + + 0 + poweroff.target + + + 1 + rescue.target + + + 2, 3, 4 + multi-user.target + + + 5 + graphical.target + + + 6 + reboot.target + + + +
+
+ + + Description + + runlevel prints the previous and current + SysV runlevel if they are known. + + The two runlevel characters are separated by a single space + character. If a runlevel cannot be determined, N is printed + instead. If neither can be determined, the word "unknown" is + printed. + + Unless overridden in the environment, this will check the + utmp database for recent runlevel changes. + + + + Options + + The following option is understood: + + + + + + + + + + + + + Exit status + + If one or both runlevels could be determined, 0 is returned, + a non-zero failure code otherwise. + + + + + Environment + + + + $RUNLEVEL + + If $RUNLEVEL is set, + runlevel will print this value as current + runlevel and ignore utmp. + + + + $PREVLEVEL + + If $PREVLEVEL is set, + runlevel will print this value as previous + runlevel and ignore utmp. + + + + + + Files + + + + /run/utmp + + The utmp database runlevel reads the previous and current runlevel + from. + + + + + + See Also + + systemd1, + systemd.target5, + systemctl1 + + + +
diff --git a/man/sd-bus-errors.xml b/man/sd-bus-errors.xml new file mode 100644 index 00000000..e5590c81 --- /dev/null +++ b/man/sd-bus-errors.xml @@ -0,0 +1,275 @@ + + + + + + + + sd-bus-errors + systemd + + + + sd-bus-errors + 3 + + + + sd-bus-errors + SD_BUS_ERROR_FAILED + SD_BUS_ERROR_NO_MEMORY + SD_BUS_ERROR_SERVICE_UNKNOWN + SD_BUS_ERROR_NAME_HAS_NO_OWNER + SD_BUS_ERROR_NO_REPLY + SD_BUS_ERROR_IO_ERROR + SD_BUS_ERROR_BAD_ADDRESS + SD_BUS_ERROR_NOT_SUPPORTED + SD_BUS_ERROR_LIMITS_EXCEEDED + SD_BUS_ERROR_ACCESS_DENIED + SD_BUS_ERROR_AUTH_FAILED + SD_BUS_ERROR_NO_SERVER + SD_BUS_ERROR_TIMEOUT + SD_BUS_ERROR_NO_NETWORK + SD_BUS_ERROR_ADDRESS_IN_USE + SD_BUS_ERROR_DISCONNECTED + SD_BUS_ERROR_INVALID_ARGS + SD_BUS_ERROR_FILE_NOT_FOUND + SD_BUS_ERROR_FILE_EXISTS + SD_BUS_ERROR_UNKNOWN_METHOD + SD_BUS_ERROR_UNKNOWN_OBJECT + SD_BUS_ERROR_UNKNOWN_INTERFACE + SD_BUS_ERROR_UNKNOWN_PROPERTY + SD_BUS_ERROR_PROPERTY_READ_ONLY + SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN + SD_BUS_ERROR_INVALID_SIGNATURE + SD_BUS_ERROR_INCONSISTENT_MESSAGE + SD_BUS_ERROR_MATCH_RULE_NOT_FOUND + SD_BUS_ERROR_MATCH_RULE_INVALID + SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED + + Standard D-Bus error names + + + + + #include <systemd/sd-bus.h> + +#define SD_BUS_ERROR_FAILED "org.freedesktop.DBus.Error.Failed" +#define SD_BUS_ERROR_NO_MEMORY "org.freedesktop.DBus.Error.NoMemory" +#define SD_BUS_ERROR_SERVICE_UNKNOWN "org.freedesktop.DBus.Error.ServiceUnknown" +#define SD_BUS_ERROR_NAME_HAS_NO_OWNER "org.freedesktop.DBus.Error.NameHasNoOwner" +#define SD_BUS_ERROR_NO_REPLY "org.freedesktop.DBus.Error.NoReply" +#define SD_BUS_ERROR_IO_ERROR "org.freedesktop.DBus.Error.IOError" +#define SD_BUS_ERROR_BAD_ADDRESS "org.freedesktop.DBus.Error.BadAddress" +#define SD_BUS_ERROR_NOT_SUPPORTED "org.freedesktop.DBus.Error.NotSupported" +#define SD_BUS_ERROR_LIMITS_EXCEEDED "org.freedesktop.DBus.Error.LimitsExceeded" +#define SD_BUS_ERROR_ACCESS_DENIED "org.freedesktop.DBus.Error.AccessDenied" +#define SD_BUS_ERROR_AUTH_FAILED "org.freedesktop.DBus.Error.AuthFailed" +#define SD_BUS_ERROR_NO_SERVER "org.freedesktop.DBus.Error.NoServer" +#define SD_BUS_ERROR_TIMEOUT "org.freedesktop.DBus.Error.Timeout" +#define SD_BUS_ERROR_NO_NETWORK "org.freedesktop.DBus.Error.NoNetwork" +#define SD_BUS_ERROR_ADDRESS_IN_USE "org.freedesktop.DBus.Error.AddressInUse" +#define SD_BUS_ERROR_DISCONNECTED "org.freedesktop.DBus.Error.Disconnected" +#define SD_BUS_ERROR_INVALID_ARGS "org.freedesktop.DBus.Error.InvalidArgs" +#define SD_BUS_ERROR_FILE_NOT_FOUND "org.freedesktop.DBus.Error.FileNotFound" +#define SD_BUS_ERROR_FILE_EXISTS "org.freedesktop.DBus.Error.FileExists" +#define SD_BUS_ERROR_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod" +#define SD_BUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject" +#define SD_BUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface" +#define SD_BUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty" +#define SD_BUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly" +#define SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN "org.freedesktop.DBus.Error.UnixProcessIdUnknown" +#define SD_BUS_ERROR_INVALID_SIGNATURE "org.freedesktop.DBus.Error.InvalidSignature" +#define SD_BUS_ERROR_INCONSISTENT_MESSAGE "org.freedesktop.DBus.Error.InconsistentMessage" +#define SD_BUS_ERROR_MATCH_RULE_NOT_FOUND "org.freedesktop.DBus.Error.MatchRuleNotFound" +#define SD_BUS_ERROR_MATCH_RULE_INVALID "org.freedesktop.DBus.Error.MatchRuleInvalid" +#define SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED \ + "org.freedesktop.DBus.Error.InteractiveAuthorizationRequired" + + + + + + Description + + In addition to the error names user programs define, D-Bus + knows a number of generic, standardized error names that are + listed below. + + In addition to this list, in sd-bus, the special error + namespace System.Error. is used to map + arbitrary Linux system errors (as defined by errno3) + to D-Bus errors and back. For example, the error + EUCLEAN is mapped to + System.Error.EUCLEAN and back. + + + + + SD_BUS_ERROR_FAILED + A generic error indication. See the error + message for further details. This error name should be + avoided, in favor of a more expressive error + name. + + + + SD_BUS_ERROR_NO_MEMORY + A memory allocation failed, and the requested + operation could not be completed. + + + + SD_BUS_ERROR_SERVICE_UNKNOWN + The contacted bus service is unknown and + cannot be activated. + + + + SD_BUS_ERROR_NAME_HAS_NO_OWNER + The specified bus service name currently has + no owner. + + + SD_BUS_ERROR_NO_REPLY + A message did not receive a reply. This error + is usually generated after a timeout. + + + SD_BUS_ERROR_IO_ERROR + Generic input/output error, for example when + accessing a socket or other I/O context. + + + SD_BUS_ERROR_BAD_ADDRESS + The specified D-Bus bus address string is + malformed. + + + SD_BUS_ERROR_NOT_SUPPORTED + The requested operation is not supported on + the local system. + + + SD_BUS_ERROR_LIMITS_EXCEEDED + Some limited resource has been + exhausted. + + + SD_BUS_ERROR_ACCESS_DENIED + Access to a resource has been denied due to security restrictions. + + + SD_BUS_ERROR_AUTH_FAILED + Authentication did not complete successfully. + + + SD_BUS_ERROR_NO_SERVER + Unable to connect to the specified server. + + + SD_BUS_ERROR_TIMEOUT + An operation timed out. Note that method calls + which timeout generate a + SD_BUS_ERROR_NO_REPLY. + + + SD_BUS_ERROR_NO_NETWORK + No network available to execute requested network operation on. + + + SD_BUS_ERROR_ADDRESS_IN_USE + The specified network address is already being listened on. + + + SD_BUS_ERROR_DISCONNECTED + The connection has been terminated. + + + SD_BUS_ERROR_INVALID_ARGS + One or more invalid arguments have been passed. + + + SD_BUS_ERROR_FILE_NOT_FOUND + The requested file could not be found. + + + SD_BUS_ERROR_FILE_EXISTS + The requested file already exists. + + + SD_BUS_ERROR_UNKNOWN_METHOD + The requested method does not exist in the selected interface. + + + SD_BUS_ERROR_UNKNOWN_OBJECT + The requested object does not exist in the selected service. + + + SD_BUS_ERROR_UNKNOWN_INTERFACE + The requested interface does not exist on the selected object. + + + SD_BUS_ERROR_UNKNOWN_PROPERTY + The requested property does not exist in the selected interface. + + + SD_BUS_ERROR_PROPERTY_READ_ONLY + A write operation was requested on a read-only property. + + + SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN + The requested PID is not known. + + + SD_BUS_ERROR_INVALID_SIGNATURE + The specified message signature is not + valid. + + + + SD_BUS_ERROR_INCONSISTENT_MESSAGE + The passed message does not validate + correctly. + + + SD_BUS_ERROR_MATCH_RULE_NOT_FOUND + The specified match rule does not exist. + + + SD_BUS_ERROR_MATCH_RULE_INVALID + The specified match rule is invalid. + + + SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED + Access to the requested operation is not + permitted. However, it might be available after interactive + authentication. This is usually returned by method calls + supporting a framework for additional interactive + authorization, when interactive authorization was not enabled + with the + sd_bus_message_set_allow_interactive_authorization3 + for the method call message. + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_error3, + sd_bus_message_set_allow_interactive_authorization3, + errno3, + strerror3 + + + + diff --git a/man/sd-bus.xml b/man/sd-bus.xml new file mode 100644 index 00000000..e9a66d87 --- /dev/null +++ b/man/sd-bus.xml @@ -0,0 +1,111 @@ + + + + + + + + sd-bus + systemd + + + + sd-bus + 3 + + + + sd-bus + A lightweight D-Bus IPC client library + + + + + #include <systemd/sd-bus.h> + + + + pkg-config --cflags --libs libsystemd + + + + + + Description + + sd-bus.h provides an implementation of a D-Bus IPC client. See + + for more information about D-Bus IPC. + + + See + sd_bus_add_match3, +sd_bus_add_object_vtable3, +sd_bus_attach_event3, +sd_bus_creds_get_pid3, +sd_bus_creds_new_from_pid3, +sd_bus_close3, +sd_bus_default3, +sd-bus-errors3, +sd_bus_error3, +sd_bus_error_add_map3, +sd_bus_get_fd3, +sd_bus_get_n_queued_read3, +sd_bus_message_append3, +sd_bus_message_append_array3, +sd_bus_message_append_basic3, +sd_bus_message_append_string_memfd3, +sd_bus_message_append_strv3, +sd_bus_message_copy3, +sd_bus_message_get_cookie3, +sd_bus_message_get_monotonic_usec3, +sd_bus_message_get_signature3, +sd_bus_message_get_type3, +sd_bus_message_new3, +sd_bus_message_new_method_call3, +sd_bus_message_new_method_error3, +sd_bus_message_new_signal3, +sd_bus_message_read3, +sd_bus_message_read_array3, +sd_bus_message_read_basic3, +sd_bus_message_rewind3, +sd_bus_message_set_destination3, +sd_bus_message_set_expect_reply3, +sd_bus_message_skip3, +sd_bus_message_verify_type3, +sd_bus_negotiate_fds3, +sd_bus_new3, +sd_bus_path_encode3, +sd_bus_process3, +sd_bus_reply_method_error3, +sd_bus_request_name3, +sd_bus_set_connected_signal3, +sd_bus_set_description3, +sd_bus_set_sender3, +sd_bus_set_watch_bind3 +sd_bus_set_close_on_exit3 +sd_bus_slot_set_description3, +sd_bus_slot_set_destroy_callback3, +sd_bus_slot_set_floating3, +sd_bus_slot_set_userdata3, +sd_bus_track_add_name3, +sd_bus_track_new3 + + for more information about the functions available. + + + + + + See Also + + systemd1, + sd-event3, + busctl1, + dbus-daemon1, + dbus-send1 + + + + diff --git a/man/sd-daemon.xml b/man/sd-daemon.xml new file mode 100644 index 00000000..84deda18 --- /dev/null +++ b/man/sd-daemon.xml @@ -0,0 +1,117 @@ + + + + + + + + sd-daemon + systemd + + + + sd-daemon + 3 + + + + sd-daemon + SD_EMERG + SD_ALERT + SD_CRIT + SD_ERR + SD_WARNING + SD_NOTICE + SD_INFO + SD_DEBUG + APIs for + new-style daemons + + + + + #include <systemd/sd-daemon.h> + + + + pkg-config --cflags --libs libsystemd + + + + + + Description + + sd-daemon.h provides APIs for new-style + daemons, as implemented by the + systemd1 + service manager. + + See + sd_listen_fds3, + sd_notify3, + sd_booted3, + sd_is_fifo3, + sd_watchdog_enabled3 + for more information about the functions implemented. In addition + to these functions, a couple of logging prefixes are defined as + macros: + + #define SD_EMERG "<0>" /* system is unusable */ +#define SD_ALERT "<1>" /* action must be taken immediately */ +#define SD_CRIT "<2>" /* critical conditions */ +#define SD_ERR "<3>" /* error conditions */ +#define SD_WARNING "<4>" /* warning conditions */ +#define SD_NOTICE "<5>" /* normal but significant condition */ +#define SD_INFO "<6>" /* informational */ +#define SD_DEBUG "<7>" /* debug-level messages */ + + These prefixes are intended to be used in conjunction with + stderr-based logging as implemented by systemd. If a systemd + service definition file is configured with + StandardError=journal, + StandardError=syslog or + StandardError=kmsg, these prefixes can be used + to encode a log level in lines printed. This is similar to the + kernel printk()-style logging. See + klogctl2 + for more information. + + The log levels are identical to + syslog3's + log level system. To use these prefixes simply prefix every line + with one of these strings. A line that is not prefixed will be + logged at the default log level SD_INFO. + + + Hello World + + A daemon may log with the log level NOTICE by issuing this + call: + + fprintf(stderr, SD_NOTICE "Hello World!\n"); + + + + + + + See Also + + systemd1, + sd_listen_fds3, + sd_notify3, + sd_booted3, + sd_is_fifo3, + sd_watchdog_enabled3, + daemon7, + systemd.service5, + systemd.socket5, + fprintf3, + pkg-config1 + + + + diff --git a/man/sd-event.xml b/man/sd-event.xml new file mode 100644 index 00000000..afdafff5 --- /dev/null +++ b/man/sd-event.xml @@ -0,0 +1,162 @@ + + + + + + + + sd-event + systemd + + + + sd-event + 3 + + + + sd-event + A generic event loop implementation + + + + + #include <systemd/sd-event.h> + + + + pkg-config --cflags --libs libsystemd + + + + + + Description + + sd-event.h provides a generic event + loop implementation, based on Linux epoll7. + + + See + sd_event_new3, + sd_event_run3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_unref3, + sd_event_source_set_priority3, + sd_event_source_set_enabled3, + sd_event_source_set_userdata3, + sd_event_source_get_event3, + sd_event_source_get_pending3, + sd_event_source_set_description3, + sd_event_source_set_prepare3, + sd_event_wait3, + sd_event_get_fd3, + sd_event_set_watchdog3, + sd_event_exit3, + sd_event_now3 + for more information about the functions available. + + The event loop design is targeted on running a separate + instance of the event loop in each thread; it has no concept of + distributing events from a single event loop instance onto + multiple worker threads. Dispatching events is strictly ordered + and subject to configurable priorities. In each event loop + iteration a single event source is dispatched. Each time an event + source is dispatched the kernel is polled for new events, before + the next event source is dispatched. The event loop is designed to + honor priorities and provide fairness within each priority. It is + not designed to provide optimal throughput, as this contradicts + these goals due the limitations of the underlying epoll7 + primitives. + + The event loop implementation provides the following features: + + + I/O event sources, based on epoll7's + file descriptor watching, including edge triggered events (EPOLLET). See sd_event_add_io3. + + Timer event sources, based on timerfd_create2, + supporting the CLOCK_MONOTONIC, + CLOCK_REALTIME, + CLOCK_BOOTIME clocks, as well as the + CLOCK_REALTIME_ALARM and + CLOCK_BOOTTIME_ALARM clocks that can resume + the system from suspend. When creating timer events a required + accuracy parameter may be specified which allows coalescing of + timer events to minimize power consumption. See sd_event_add_time3. + + UNIX process signal events, based on + signalfd2, + including full support for real-time signals, and queued parameters. See sd_event_add_signal3. + + Child process state change events, based on + waitid2. See sd_event_add_child3. + + Static event sources, of three types: defer, + post and exit, for invoking calls in each event loop, after + other event sources or at event loop termination. See + sd_event_add_defer3. + + Event sources may be assigned a 64bit priority + value, that controls the order in which event sources are + dispatched if multiple are pending simultaneously. See + sd_event_source_set_priority3. + + The event loop may automatically send watchdog + notification messages to the service manager. See + sd_event_set_watchdog3. + + The event loop may be integrated into foreign + event loops, such as the GLib one. See + sd_event_get_fd3 + for an example. + + + + + + + + See Also + + systemd1, + sd_event_new3, + sd_event_run3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_unref3, + sd_event_source_set_priority3, + sd_event_source_set_enabled3, + sd_event_source_set_userdata3, + sd_event_source_get_event3, + sd_event_source_get_pending3, + sd_event_source_set_description3, + sd_event_source_set_prepare3, + sd_event_wait3, + sd_event_get_fd3, + sd_event_set_watchdog3, + sd_event_exit3, + sd_event_now3, + epoll7, + timerfd_create2, + signalfd2, + waitid2 + + + + diff --git a/man/sd-id128.xml b/man/sd-id128.xml new file mode 100644 index 00000000..22d5e0e3 --- /dev/null +++ b/man/sd-id128.xml @@ -0,0 +1,168 @@ + + + + + + + + sd-id128 + systemd + + + + sd-id128 + 3 + + + + sd-id128 + sd_id128_t + SD_ID128_MAKE + SD_ID128_MAKE_STR + SD_ID128_NULL + SD_ID128_CONST_STR + SD_ID128_FORMAT_STR + SD_ID128_UUID_FORMAT_STR + SD_ID128_FORMAT_VAL + sd_id128_equal + sd_id128_is_null + APIs for processing 128-bit IDs + + + + + #include <systemd/sd-id128.h> + + + + pkg-config --cflags --libs libsystemd + + + + + + Description + + sd-id128.h provides APIs to process and + generate 128-bit ID values. The 128-bit ID values processed and + generated by these APIs are a generalization of OSF UUIDs as + defined by RFC + 4122 but use a simpler string format. These functions + impose no structure on the used IDs, much unlike OSF UUIDs or + Microsoft GUIDs, but are fully compatible with those types of IDs. + + + See + sd_id128_to_string3, + sd_id128_randomize3 + and + sd_id128_get_machine3 + for more information about the implemented functions. + + A 128-bit ID is implemented as the following + union type: + + typedef union sd_id128 { + uint8_t bytes[16]; + uint64_t qwords[2]; +} sd_id128_t; + + This union type allows accessing the 128-bit ID as 16 + separate bytes or two 64-bit words. It is generally safer to + access the ID components by their 8-bit array to avoid endianness + issues. This union is intended to be passed call-by-value (as + opposed to call-by-reference) and may be directly manipulated by + clients. + + A couple of macros are defined to denote and decode 128-bit + IDs: + + SD_ID128_MAKE() may be used to denote a + constant 128-bit ID in source code. A commonly used idiom is to + assign a name to a 128-bit ID using this macro: + + #define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) + + SD_ID128_NULL may be used to refer to the 128bit ID consisting of only NUL + bytes. + + SD_ID128_MAKE_STR() is similar to SD_ID128_MAKE(), but creates a + const char* expression that can be conveniently used in message formats and such: + + #include <stdio.h> +#define SD_MESSAGE_COREDUMP_STR SD_ID128_MAKE_STR(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) + +int main(int argc, char **argv) { + puts("Match for coredumps: MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR); +} + + + SD_ID128_CONST_STR() may be used to + convert constant 128-bit IDs into constant strings for output. The + following example code will output the string + "fc2e22bc6ee647b6b90729ab34a250b1": + int main(int argc, char *argv[]) { + puts("Match for coredumps: %s", SD_ID128_CONST_STR(SD_MESSAGE_COREDUMP)); +} + + SD_ID128_FORMAT_STR() and + SD_ID128_FORMAT_VAL() may be used to format a + 128-bit ID in a + printf3 + format string, as shown in the following example: + + int main(int argc, char *argv[]) { + sd_id128_t id; + id = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07); + printf("The ID encoded in this C file is " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(id)); + return 0; +} + + SD_ID128_UUID_FORMAT_STR() is similar to + SD_ID128_FORMAT_STR() but includes separating hyphens to conform to the + "canonical representation". + + + Use sd_id128_equal() to compare two 128-bit IDs: + + int main(int argc, char *argv[]) { + sd_id128_t a, b, c; + a = SD_ID128_MAKE(ee,89,be,71,bd,6e,43,d6,91,e6,c5,5d,eb,03,02,07); + b = SD_ID128_MAKE(f2,28,88,9c,5f,09,44,15,9d,d7,04,77,58,cb,e7,3e); + c = a; + assert(sd_id128_equal(a, c)); + assert(!sd_id128_equal(a, b)); + return 0; +} + + Use sd_id128_is_null() to check if an 128bit ID consists of only NUL bytes: + + int main(int argc, char *argv[]) { + assert(sd_id128_is_null(SD_ID128_NULL)); +} + + Note that new, randomized IDs may be generated with + systemd-id1281's + new command. + + + + + + See Also + + systemd1, + sd_id128_to_string3, + sd_id128_randomize3, + sd_id128_get_machine3, + printf3, + journalctl1, + sd-journal7, + pkg-config1, + machine-id5 + + + + diff --git a/man/sd-journal.xml b/man/sd-journal.xml new file mode 100644 index 00000000..a3ee1ea9 --- /dev/null +++ b/man/sd-journal.xml @@ -0,0 +1,118 @@ + + + + + + + + sd-journal + systemd + + + + sd-journal + 3 + + + + sd-journal + APIs for submitting and querying log entries to and + from the journal + + + + + #include <systemd/sd-journal.h> + + + + pkg-config --cflags --libs libsystemd + + + + + + Description + + sd-journal.h provides APIs to submit + and query log entries. The APIs exposed act both as client for the + systemd-journald.service8 + journal service and as parser for the journal files on disk. + + + See + sd_journal_print3, + sd_journal_stream_fd3, + sd_journal_open3, + sd_journal_next3, + sd_journal_get_realtime_usec3, + sd_journal_add_match3, + sd_journal_seek_head3, + sd_journal_enumerate_fields3, + sd_journal_get_cursor3, + sd_journal_get_cutoff_realtime_usec3, + sd_journal_get_cutoff_monotonic_usec3, + sd_journal_get_usage3, + sd_journal_get_catalog3, + sd_journal_get_fd3, + sd_journal_has_runtime_files3 + and + sd_journal_has_persistent_files3 + for more information about the functions implemented. + + Command line access for submitting entries to the journal is + available with the + systemd-cat1 + tool. Command line access for querying entries from the journal is + available with the + journalctl1 + tool. + + + + Thread safety + + Functions that operate on sd_journal objects are thread agnostic — given + sd_journal pointer may only be used from one specific thread at all times (and it has to + be the very same one during the entire lifetime of the object), but multiple, independent threads may use multiple, + independent objects safely. Other functions — those that are used to send entries to the journal, like + sd_journal_print3 and similar, + or those that are used to retrieve global information like + sd_journal_stream_fd3 and + sd_journal_get_catalog_for_message_id3 + — are fully thread-safe and may be called from multiple threads in parallel. + + + + + + See Also + + systemd1, + sd_journal_print3, + sd_journal_stream_fd3, + sd_journal_open3, + sd_journal_next3, + sd_journal_get_data3, + sd_journal_get_realtime_usec3, + sd_journal_add_match3, + sd_journal_seek_head3, + sd_journal_enumerate_fields3, + sd_journal_get_cursor3, + sd_journal_get_cutoff_realtime_usec3, + sd_journal_get_cutoff_monotonic_usec3, + sd_journal_get_usage3, + sd_journal_get_fd3, + sd_journal_query_unique3, + sd_journal_get_catalog3, + sd_journal_has_runtime_files3, + sd_journal_has_persistent_files3, + journalctl1, + sd-id1283, + pkg-config1 + + + + diff --git a/man/sd-login.xml b/man/sd-login.xml new file mode 100644 index 00000000..2787bd74 --- /dev/null +++ b/man/sd-login.xml @@ -0,0 +1,248 @@ + + + + + + + + sd-login + systemd + + + + sd-login + 3 + + + + sd-login + APIs for + tracking logins + + + + + #include <systemd/sd-login.h> + + + + pkg-config --cflags --libs libsystemd + + + + + Description + + sd-login.h provides APIs to introspect + and monitor seat, login session and user status information on the + local system. + + Note that these APIs only allow purely passive access and + monitoring of seats, sessions and users. To actively make changes + to the seat configuration, terminate login sessions, or switch + session on a seat you need to utilize the D-Bus API of + systemd-logind, instead. + + These functions synchronously access data in + /proc, /sys/fs/cgroup + and /run. All of these are virtual file + systems, hence the runtime cost of the accesses is relatively + cheap. + + It is possible (and often a very good choice) to mix calls + to the synchronous interface of sd-login.h + with the asynchronous D-Bus interface of systemd-logind. However, + if this is done you need to think a bit about possible races since + the stream of events from D-Bus and from + sd-login.h interfaces such as the login + monitor are asynchronous and not ordered against each + other. + + If the functions return string arrays, these are generally + NULL terminated and need to be freed by the + caller with the libc + free3 + call after use, including the strings referenced therein. + Similarly, individual strings returned need to be freed, as + well. + + As a special exception, instead of an empty string array + NULL may be returned, which should be treated + equivalent to an empty string array. + + See + sd_pid_get_session3, + sd_uid_get_state3, + sd_session_is_active3, + sd_seat_get_active3, + sd_get_seats3, + sd_login_monitor_new3 + for more information about the functions + implemented. + + + + Definition of Terms + + + + seat + + A seat consists of all hardware devices assigned to a specific + workplace. It consists of at least one graphics device, and usually also includes + keyboard, mouse. It can also include video cameras, sound cards and more. Seats + are identified by seat names, which are strings (<= 255 characters), that start + with the four characters seat followed by at least one + character from the range [a-zA-Z0-9], _ and + -. They are suitable for use as file names. Seat names may or + may not be stable and may be reused if a seat becomes available again. + + + + + session + + A session is defined by the time a user is logged in until they + log out. A session is bound to one or no seats (the latter for 'virtual' ssh + logins). Multiple sessions can be attached to the same seat, but only one of them + can be active, the others are in the background. A session is identified by a + short string. + + + systemd1 + ensures that audit sessions are identical to systemd sessions, and uses the audit + session ID as session ID in systemd (if auditing is enabled). In general the + session identifier is a short string consisting only of [a-zA-Z0-9], + _ and -, suitable for use as a file name. + Session IDs are unique on the local machine and are + never reused as long as the machine is online. A user (the way we know it on UNIX) + corresponds to the person using a computer. A single user can have multiple + sessions open at the same time. A user is identified by a numeric user id (UID) or + a user name (a string). A multi-session system allows multiple user sessions on + the same seat at the same time. A multi-seat system allows multiple independent + seats that can be individually and simultaneously used by different users. + + + + + All hardware devices that are eligible to being assigned to a seat, are assigned + to one. A device can be assigned to only one seat at a time. If a device is not + assigned to any particular other seat it is implicitly assigned to the special default + seat called seat0. + + Note that hardware like printers, hard disks or network cards is generally not + assigned to a specific seat. They are available to all seats equally. (Well, with one + exception: USB sticks can be assigned to a seat.) + + seat0 always exists. + + + + udev Rules + + Assignment of hardware devices to seats is managed inside the udev database, via + settings on the devices: + + + + Tag seat + + When set, a device is eligible to be assigned to a seat. This tag + is set for graphics devices, mice, keyboards, video cards, sound cards and + more. Note that some devices like sound cards consist of multiple subdevices + (i.e. a PCM for input and another one for output). This tag will be set only for + the originating device, not for the individual subdevices. A UI for configuring + assignment of devices to seats should enumerate and subscribe to all devices with + this tag set and show them in the UI. Note that USB hubs can be assigned to a seat + as well, in which case all (current and future) devices plugged into it will also + be assigned to the same seat (unless they are explicitly assigned to another + seat). + + + + + Tag master-of-seat + + When set, this device is enough for a seat to be considered + existent. This tag is usually set for the framebuffer device of graphics cards. A + seat hence consists of an arbitrary number of devices marked with the + seat tag, but (at least) one of these devices needs to be + tagged with master-of-seat before the seat is actually + considered to be around. + + + + Property ID_SEAT + + This property specifies the name of the seat a specific device is + assigned to. If not set the device is assigned to seat0. Also, + to speed up enumeration of hardware belonging to a specific seat, the seat is also + set as tag on the device. I.e. if the property + ID_SEAT=seat-waldo is set for a device, the tag + seat-waldo will be set as well. Note that if a device is + assigned to seat0, it will usually not carry such a tag and you + need to enumerate all devices and check the ID_SEAT property + manually. Again, if a device is assigned to seat0 this is visible on the device in + two ways: with a property ID_SEAT=seat0 and with no property + ID_SEAT set for it at all. + + + + Property ID_AUTOSEAT + + When set to 1, this device automatically + generates a new and independent seat, which is named after the path of the + device. This is set for specialized USB hubs like the Plugable devices, which when + plugged in should create a hotplug seat without further configuration. + + + + + Property ID_FOR_SEAT + + When creating additional (manual) seats starting from a graphics + device this is a good choice to name the seat after. It is created from the path + of the device. This is useful in UIs for configuring seats: as soon as you create + a new seat from a graphics device, read this property and prefix it with + seat- and use it as name for the seat. + + + + A seat exists only and exclusively because a properly tagged device with the + right ID_SEAT property exists. Besides udev rules there is no + persistent data about seats stored on disk. + + Note that + systemd-logind8 + manages ACLs on a number of device classes, to allow user code to access the device + nodes attached to a seat as long as the user has an active session on it. This is + mostly transparent to applications. As mentioned above, for certain user software it + might be a good idea to watch whether they can access device nodes instead of thinking + about seats. + + + + + + See Also + + systemd1, + sd_pid_get_session3, + sd_uid_get_state3, + sd_session_is_active3, + sd_seat_get_active3, + sd_get_seats3, + sd_login_monitor_new3, + sd-daemon3, + pkg-config1 + + + + Multi-Seat on Linux + for an introduction to multi-seat support on Linux and the background for this set of APIs. + + + + diff --git a/man/sd_booted.xml b/man/sd_booted.xml new file mode 100644 index 00000000..6a6a6206 --- /dev/null +++ b/man/sd_booted.xml @@ -0,0 +1,68 @@ + + + + + + + + sd_booted + systemd + + + + sd_booted + 3 + + + + sd_booted + Test whether the system is running the systemd init system + + + + + #include <systemd/sd-daemon.h> + + + int sd_booted + void + + + + + + Description + sd_booted() checks whether the system + was booted up using the systemd init system. + + + + Return Value + + On failure, this call returns a negative errno-style error + code. If the system was booted up with systemd as init system, + this call returns a positive return value, zero otherwise. + + + + Notes + + + + Internally, this function checks whether the directory + /run/systemd/system/ exists. A simple check + like this can also be implemented trivially in shell or any other + language. + + + + See Also + + systemd1, + sd-daemon3 + + + + diff --git a/man/sd_bus_add_match.xml b/man/sd_bus_add_match.xml new file mode 100644 index 00000000..a1065443 --- /dev/null +++ b/man/sd_bus_add_match.xml @@ -0,0 +1,173 @@ + + + + + + + + + sd_bus_add_match + systemd + + + + sd_bus_add_match + 3 + + + + sd_bus_add_match + sd_bus_add_match_async + sd_bus_match_signal + sd_bus_match_signal_async + + Add a match rule for incoming message dispatching + + + + + #include <systemd/sd-bus.h> + + + typedef int (*sd_bus_message_handler_t) + sd_bus_message *m + void *userdata + sd_bus_error *ret_error + + + + int sd_bus_add_match + sd_bus *bus + sd_bus_slot **slot + const char *match + sd_bus_message_handler_t callback + void *userdata + + + + int sd_bus_add_match_async + sd_bus *bus + sd_bus_slot **slot + const char *match + sd_bus_message_handler_t callback + sd_bus_message_handler_t install_callback + void *userdata + + + + int sd_bus_match_signal + sd_bus *bus + sd_bus_slot **slot + const char *sender + const char *path + const char *interface + const char *member + sd_bus_message_handler_t callback + void *userdata + + + + int sd_bus_match_signal_async + sd_bus *bus + sd_bus_slot **slot + const char *sender + const char *path + const char *interface + const char *member + sd_bus_message_handler_t callback + sd_bus_message_handler_t install_callback + void *userdata + + + + + + + Description + + sd_bus_add_match() installs a match rule for messages received on the specified bus + connection object bus. The syntax of the match rule expression passed in + match is described in the D-Bus Specification. The specified handler + function callback is called for eaching incoming message matching the specified expression, + the userdata parameter is passed as-is to the callback function. The match is installed + synchronously when connected to a bus broker, i.e. the call sends a control message requested the match to be added + to the broker and waits until the broker confirms the match has been installed successfully. + + sd_bus_add_match_async() operates very similar to + sd_bus_match_signal(), however it installs the match asynchronously, in a non-blocking + fashion: a request is sent to the broker, but the call does not wait for a response. The + install_callback function is called when the response is later received, with the response + message from the broker as parameter. If this function is specified as NULL a default + implementation is used that terminates the bus connection should installing the match fail. + + sd_bus_match_signal() is very similar to sd_bus_add_match(), but + only matches signals, and instead of a match expression accepts four parameters: sender (the + service name of the sender), path (the object path of the emitting object), + interface (the interface the signal belongs to), member (the signal + name), from which the match string is internally generated. Optionally, these parameters may be specified as + NULL in which case the relevant field of incoming signals is not tested. + + sd_bus_match_signal_async() combines the signal matching logic of + sd_bus_match_signal() with the asynchronous behaviour of + sd_bus_add_match_async(). + + On success, and if non-NULL, the slot return parameter will be + set to a slot object that may be used as a reference to the installed match, and may be utilized to remove it again + at a later time with + sd_bus_slot_unref3. If specified + as NULL the lifetime of the match is bound to the lifetime of the bus object itself, and the + match is generally not removed independently. See + sd_bus_slot_set_floating3 for + details. + + The message m passed to the callback is only borrowed, that is, the callback should + not call sd_bus_message_unref3 + on it. If the callback wants to hold on to the message beyond the lifetime of the callback, it needs to call + sd_bus_message_ref3 to create a + new reference. + + If an error occurs during the callback invocation, the callback should return a negative error number + (optionally, a more precise error may be returned in ret_error, as well). If it wants other + callbacks that match the same rule to be called, it should return 0. Otherwise it should return a positive integer. + + + If the bus refers to a direct connection (i.e. not a bus connection, as set with + sd_bus_set_bus_client3) the + match is only installed on the client side, and the synchronous and asynchronous functions operate the same. + + + + Return Value + + + On success, sd_bus_add_match() and the other calls return 0 or a positive integer. On + failure, they return a negative errno-style error code. + + + + + Notes + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_slot_unref3, + sd_bus_message_ref3, + sd_bus_set_bus_client3, + sd_bus_slot_set_floating3 + + + + diff --git a/man/sd_bus_add_object_vtable.xml b/man/sd_bus_add_object_vtable.xml new file mode 100644 index 00000000..9d7e30a5 --- /dev/null +++ b/man/sd_bus_add_object_vtable.xml @@ -0,0 +1,473 @@ + + + + + + + + sd_bus_add_object_vtable + systemd + + + + sd_bus_add_object_vtable + 3 + + + + sd_bus_add_object_vtable + sd_bus_add_fallback_vtable + SD_BUS_VTABLE_START + SD_BUS_VTABLE_END + SD_BUS_METHOD_WITH_NAMES_OFFSET + SD_BUS_METHOD_WITH_NAMES + SD_BUS_METHOD_WITH_OFFSET + SD_BUS_METHOD + SD_BUS_SIGNAL_WITH_NAMES + SD_BUS_SIGNAL + SD_BUS_WRITABLE_PROPERTY + SD_BUS_PROPERTY + SD_BUS_PARAM + + Declare properties and methods for a D-Bus path + + + + + #include <systemd/sd-bus-vtable.h> + + + typedef int (*sd_bus_message_handler_t) + sd_bus_message *m + void *userdata + sd_bus_error *ret_error + + + + typedef int (*sd_bus_property_get_t) + sd_bus *bus + const char *path + const char *interface + const char *property + sd_bus_message *reply + void *userdata + sd_bus_error *ret_error + + + + typedef int (*sd_bus_property_set_t) + sd_bus *bus + const char *path + const char *interface + const char *property + sd_bus_message *value + void *userdata + sd_bus_error *ret_error + + + + typedef int (*sd_bus_object_find_t) + const char *path + const char *interface + void *userdata + void **ret_found + sd_bus_error *ret_error + + + + int sd_bus_add_object_vtable + sd_bus *bus + sd_bus_slot **slot + const char *path + const char *interface + const sd_bus_vtable *vtable + void *userdata + + + + int sd_bus_add_fallback_vtable + sd_bus *bus + sd_bus_slot **slot + const char *prefix + const char *interface + const sd_bus_vtable *vtable + sd_bus_object_find_t find + void *userdata + + + + SD_BUS_VTABLE_START(flags) + + + SD_BUS_VTABLE_END + + + SD_BUS_METHOD_WITH_NAMES_OFFSET( + member, + signature, + in_names, + result, + out_names, + handler, + offset, + flags) + + + + SD_BUS_METHOD_WITH_NAMES( + member, + signature, + in_names, + result, + out_names, + handler, + flags) + + + + SD_BUS_METHOD_WITH_OFFSET( + member, + signature, + result, + handler, + offset, + flags) + + + + SD_BUS_METHOD( + member, + signature, + result, + handler, + flags) + + + + SD_BUS_SIGNAL_WITH_NAMES( + member, + signature, + names, + flags) + + + + SD_BUS_SIGNAL( + member, + signature, + flags) + + + + SD_BUS_WRITABLE_PROPERTY( + member, + signature, + get, + set, + offset, + flags) + + + + SD_BUS_PROPERTY( + member, + signature, + get, + offset, + flags) + + + + SD_BUS_PARAM(name) + + + + + + Description + + sd_bus_add_object_vtable() is used to declare attributes for the path object + path path connected to the bus connection bus under the + interface interface. The table vtable may contain property + declarations using SD_BUS_PROPERTY() or + SD_BUS_WRITABLE_PROPERTY(), method declarations using + SD_BUS_METHOD(), SD_BUS_METHOD_WITH_NAMES(), + SD_BUS_METHOD_WITH_OFFSET(), or + SD_BUS_METHOD_WITH_NAMES_OFFSET(), and signal declarations using + SD_BUS_SIGNAL_WITH_NAMES() or SD_BUS_SIGNAL(), see below. The + userdata parameter contains a pointer that will be passed to various callback + functions. It may be specified as NULL if no value is necessary. + + sd_bus_add_fallback_vtable() is similar to + sd_bus_add_object_vtable(), but is used to register "fallback" attributes. When + looking for an attribute declaration, bus object paths registered with + sd_bus_add_object_vtable() are checked first. If no match is found, the fallback + vtables are checked for each prefix of the bus object path, i.e. with the last slash-separated components + successively removed. This allows the vtable to be used for an arbitrary number of dynamically created + objects. + + Parameter find is a function which is used to locate the target object + based on the bus object path path. It must return 1 and + set the ret_found output parameter if the object is found, return + 0 if the object was not found, and return a negative errno-style error code or + initialize the error structure ret_error on error. The pointer passed in + ret_found will be used as the userdata parameter for the + callback functions (offset by the offset offsets as specified in the vtable + entries). + + For both functions, a match slot is created internally. If the output parameter + slot is NULL, a "floating" slot object is created, see + sd_bus_slot_set_floating3. + Otherwise, a pointer to the slot object is returned. In that case, the reference to the slot object + should be dropped when the vtable is not needed anymore, see + sd_bus_slot_unref3. + + + + The <structname>sd_bus_vtable</structname> array + + The array consists of the structures of type sd_bus_vtable, but it + should never be filled in manually, but through one of the following macros: + + + + SD_BUS_VTABLE_START() + SD_BUS_VTABLE_END + + Those must always be the first and last element. + + + + SD_BUS_METHOD_WITH_NAMES_OFFSET() + SD_BUS_METHOD_WITH_NAMES() + SD_BUS_METHOD_WITH_OFFSET() + SD_BUS_METHOD() + + Declare a D-Bus method with the name member, parameter + signature signature, result signature result. + Parameters in_names and out_names specify the + argument names of the input and output arguments in the function signature. The handler function + handler must be of type sd_bus_message_handler_t. + It will be called to handle the incoming messages that call this method. It receives a pointer that + is the userdata parameter passed to the registration function offset by + offset bytes. This may be used to pass pointers to different fields in + the same data structure to different methods in the same + vtable. in_names and out_names should be + created using the SD_BUS_PARAM() macro, see below. Parameter + flags is a combination of flags, see below. + + SD_BUS_METHOD_WITH_NAMES(), + SD_BUS_METHOD_WITH_OFFSET(), and SD_BUS_METHOD() are + variants which specify zero offset (userdata parameter is passed with + no change), leave the names unset (i.e. no parameter names), or both. + + + + + SD_BUS_SIGNAL_WITH_NAMES() + SD_BUS_SIGNAL() + + Declare a D-Bus signal with the name member, + parameter signature signature, and argument names + names. names should be + created using the SD_BUS_PARAM() macro, see below. + Parameter flags is a combination of flags, see below. + + + Equivalent to SD_BUS_SIGNAL_WITH_NAMES() with the + names parameter unset (i.e. no parameter names). + + + + + SD_BUS_WRITABLE_PROPERTY() + SD_BUS_PROPERTY() + + Declare a D-Bus property with the name member and value + signature signature. Parameters get and + set are the getter and setter methods. They are called with a pointer + that is the userdata parameter passed to the registration function + offset by offset bytes. This may be used pass pointers to different + fields in the same data structure to different setters and getters in the same vtable. Parameter + flags is a combination of flags, see below. + + The setter and getter methods may be omitted (specified as NULL), if the + property has one of the basic types or as in case of read-only properties. In + those cases, the userdata and offset + parameters must together point to valid variable of the corresponding type. A default setter and + getters will be provided, which simply copy the argument between this variable and the message. + + + SD_BUS_PROPERTY() is used to define a read-only property. + + + + + SD_BUS_PARAM() + Parameter names should be wrapped in this macro, see the example below. + + + + + + + Flags + + The flags parameter is used to specify a combination of + D-Bus annotations. + + + + + SD_BUS_VTABLE_DEPRECATED + + Mark this vtable entry as deprecated using the + org.freedesktop.DBus.Deprecated annotation in introspection data. If + specified for SD_BUS_VTABLE_START(), the annotation is applied to the + enclosing interface. + + + + SD_BUS_VTABLE_HIDDEN + + Make this vtable entry hidden. It will not be shown in introspection data. If + specified for SD_BUS_VTABLE_START(), all entries in the array are hidden. + + + + + + SD_BUS_VTABLE_UNPRIVILEGED + + Mark this vtable entry as unprivileged. If not specified, the + org.freedesktop.systemd1.Privileged annotation with value + true will be shown in introspection data. + + + + + SD_BUS_VTABLE_METHOD_NO_REPLY + + Mark his vtable entry as a method that will not return a reply using the + org.freedesktop.DBus.Method.NoReply annotation in introspection data. + + + + + SD_BUS_VTABLE_PROPERTY_CONST + SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE + SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION + + Those three flags correspond to different values of the + org.freedesktop.DBus.Property.EmitsChangedSignal annotation, which specifies + whether the org.freedesktop.DBus.Properties.PropertiesChanged signal is + emitted whenever the property changes. SD_BUS_VTABLE_PROPERTY_CONST corresponds to + const and means that the property never changes during the lifetime of the + object it belongs to, so no signal needs to be emitted. + SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE corresponds to true and means + that the signal is emitted. SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION corresponds to + invalidates and means that the signal is emitted, but the value is not included + in the signal. + + + + + SD_BUS_VTABLE_PROPERTY_EXPLICIT + + Mark this vtable property entry as requiring explicit request to for the value to + be shown (generally because the value is large or slow to calculate). This entry cannot be combined + with SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE, and will not be shown in property listings by + default (e.g. busctl introspect). This corresponds to the + org.freedesktop.systemd1.Explicit annotation in introspection data. + + + + + + + + Examples + + + Create a simple listener on the bus + + + + This creates a simple client on the bus (the user bus, when run as normal user). + We may use the D-Bus org.freedesktop.DBus.Introspectable.Introspect + call to acquire the XML description of the interface: + + + + + + + Return Value + + On success, sd_bus_add_object_vtable and + sd_bus_add_fallback_vtable calls return 0 or a positive integer. On failure, they + return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + One of the required parameters is NULL or invalid. A reserved + D-Bus interface was passed as the interface parameter. + + + + -ENOPKG + + The bus cannot be resolved. + + + + -ECHILD + + The bus was created in a different process. + + + + -ENOMEM + + Memory allocation failed. + + + + -EPROTOTYPE + + sd_bus_add_object_vtable and + sd_bus_add_fallback_vtable have been both called + for the same bus object path, which is not allowed. + + + + -EEXIST + + This vtable has already been registered for this + interface and path. + + + + + + + + + + See Also + + + sd-bus3, + busctl1 + + + diff --git a/man/sd_bus_attach_event.xml b/man/sd_bus_attach_event.xml new file mode 100644 index 00000000..2a207d28 --- /dev/null +++ b/man/sd_bus_attach_event.xml @@ -0,0 +1,119 @@ + + + + + + + + sd_bus_attach_event + systemd + + + + sd_bus_attach_event + 3 + + + + sd_bus_attach_event + sd_bus_detach_event + sd_bus_get_event + + Attach a bus connection object to an event loop + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_attach_event + sd_bus *bus + sd_event *e + int priority + + + + int sd_bus_detach_event + sd_bus *bus + + + + sd_event *sd_bus_get_event + sd_bus *bus + + + + + + Description + + sd_bus_attach_event() attaches the specified bus connection object to an + sd-event3 event loop object at + the specified priority (see + sd_event_source_set_priority3 + for details on event loop priorities). When a bus connection object is attached to an event loop incoming messages + will be automatically read and processed, and outgoing messages written, whenever the event loop is run. When the + event loop is about to terminate, the bus connection is automatically flushed and closed (see + sd_bus_set_close_on_exit3 for + details on this). By default bus connection objects are not attached to any event loop. When a bus connection + object is attached to one it is not necessary to invoke + sd_bus_wait3 or + sd_bus_process3 as this + functionality is handled automatically by the event loop. + + sd_bus_detach_event() detaches a bus object from its event loop. + + The sd_bus_get_event() returns the event loop object the specified bus object is + currently attached to, or NULL if it is currently not attached to any. + + Note that sd_bus_attach_event() is only one of three supported ways to implement I/O + event handling for bus connections. Alternatively use + sd_bus_get_fd3 for hooking up a + bus connection object with external or manual event loops. Or use + sd_bus_wait3 as a simple + synchronous, blocking I/O waiting call. + + + + Return Value + + On success, sd_bus_attach_event() and sd_bus_detach_event() return + 0 or a positive integer. On failure, they return a negative errno-style error code. + + sd_bus_get_event() returns an event loop object or NULL. + + + Errors + + Returned errors may indicate the following problems: + + + + -ECHILD + + The bus connection has been created in a different process. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd-event3, + sd_event_source_set_priority3, + sd_bus_set_close_on_exit3, + sd_bus_wait3, + sd_bus_get_fd3 + + + + diff --git a/man/sd_bus_close.xml b/man/sd_bus_close.xml new file mode 100644 index 00000000..d81c5938 --- /dev/null +++ b/man/sd_bus_close.xml @@ -0,0 +1,98 @@ + + + + + + + + sd_bus_close + systemd + + + + sd_bus_close + 3 + + + + sd_bus_close + sd_bus_flush + + Close and flush a bus connection + + + + + #include <systemd/sd-bus.h> + + + void sd_bus_close + sd_bus *bus + + + + int sd_bus_flush + sd_bus *bus + + + + + + Description + + sd_bus_close() disconnects the specified bus connection. When this call is invoked and + the specified bus object refers to an active connection it is immediately terminated. No further messages may be + sent or received on it. Any messages queued in the bus object (both incoming and outgoing) are released. If + invoked on NULL bus object or when the bus connection is already closed this function executes + no operation. This call does not free or unreference the bus object itself. Use + sd_bus_unref3 for that. + + sd_bus_flush() synchronously writes out all outgoing queued message on a bus connection + if there are any. This function call may block if the peer is not processing bus messages quickly. + + Before a program exits it is usually a good idea to flush any pending messages with + sd_bus_flush() and then close connections with sd_bus_close() to ensure + that no unwritten messages are lost, no further messages may be queued and all incoming but unprocessed messages + are released. After both operations have been done, it is a good idea to also drop any remaining references to the + bus object so that it may be freed. Since these three operations are frequently done together a helper call + sd_bus_flush_close_unref3 is + provided that combines them into one. + + + + Return Value + + On success, sd_bus_flush() returns 0 or a positive integer. On failure, it returns a + negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ECHILD + + The bus connection has been created in a different process. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_unref3, + sd_bus_set_close_on_exit3 + + + + diff --git a/man/sd_bus_creds_get_pid.xml b/man/sd_bus_creds_get_pid.xml new file mode 100644 index 00000000..a7690d58 --- /dev/null +++ b/man/sd_bus_creds_get_pid.xml @@ -0,0 +1,527 @@ + + + + + + + + sd_bus_creds_get_pid + systemd + + + + sd_bus_creds_get_pid + 3 + + + + sd_bus_creds_get_pid + sd_bus_creds_get_ppid + sd_bus_creds_get_tid + sd_bus_creds_get_uid + sd_bus_creds_get_euid + sd_bus_creds_get_suid + sd_bus_creds_get_fsuid + sd_bus_creds_get_gid + sd_bus_creds_get_egid + sd_bus_creds_get_sgid + sd_bus_creds_get_fsgid + sd_bus_creds_get_supplementary_gids + sd_bus_creds_get_comm + sd_bus_creds_get_tid_comm + sd_bus_creds_get_exe + sd_bus_creds_get_cmdline + sd_bus_creds_get_cgroup + sd_bus_creds_get_unit + sd_bus_creds_get_slice + sd_bus_creds_get_user_unit + sd_bus_creds_get_user_slice + sd_bus_creds_get_session + sd_bus_creds_get_owner_uid + sd_bus_creds_has_effective_cap + sd_bus_creds_has_permitted_cap + sd_bus_creds_has_inheritable_cap + sd_bus_creds_has_bounding_cap + sd_bus_creds_get_selinux_context + sd_bus_creds_get_audit_session_id + sd_bus_creds_get_audit_login_uid + sd_bus_creds_get_tty + sd_bus_creds_get_unique_name + sd_bus_creds_get_well_known_names + sd_bus_creds_get_description + + Retrieve fields from a credentials object + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_creds_get_pid + sd_bus_creds *c + pid_t *pid + + + + int sd_bus_creds_get_ppid + sd_bus_creds *c + pid_t *ppid + + + + int sd_bus_creds_get_tid + sd_bus_creds *c + pid_t *tid + + + + int sd_bus_creds_get_uid + sd_bus_creds *c + uid_t *uid + + + + int sd_bus_creds_get_euid + sd_bus_creds *c + uid_t *uid + + + + int sd_bus_creds_get_suid + sd_bus_creds *c + uid_t *uid + + + + int sd_bus_creds_get_fsuid + sd_bus_creds *c + uid_t *uid + + + + int sd_bus_creds_get_gid + sd_bus_creds *c + gid_t *gid + + + + int sd_bus_creds_get_egid + sd_bus_creds *c + gid_t *gid + + + + int sd_bus_creds_get_sgid + sd_bus_creds *c + gid_t *gid + + + + int sd_bus_creds_get_fsgid + sd_bus_creds *c + gid_t *gid + + + + int sd_bus_creds_get_supplementary_gids + sd_bus_creds *c + const gid_t **gids + + + + int sd_bus_creds_get_comm + sd_bus_creds *c + const char **comm + + + + int sd_bus_creds_get_tid_comm + sd_bus_creds *c + const char **comm + + + + int sd_bus_creds_get_exe + sd_bus_creds *c + const char **exe + + + + int sd_bus_creds_get_cmdline + sd_bus_creds *c + char ***cmdline + + + + int sd_bus_creds_get_cgroup + sd_bus_creds *c + const char **cgroup + + + + int sd_bus_creds_get_unit + sd_bus_creds *c + const char **unit + + + + int sd_bus_creds_get_slice + sd_bus_creds *c + const char **slice + + + + int sd_bus_creds_get_user_unit + sd_bus_creds *c + const char **unit + + + + int sd_bus_creds_get_user_slice + sd_bus_creds *c + const char **slice + + + + int sd_bus_creds_get_session + sd_bus_creds *c + const char **slice + + + + int sd_bus_creds_get_owner_uid + sd_bus_creds *c + uid_t *uid + + + + int sd_bus_creds_has_effective_cap + sd_bus_creds *c + int capability + + + + int sd_bus_creds_has_permitted_cap + sd_bus_creds *c + int capability + + + + int sd_bus_creds_has_inheritable_cap + sd_bus_creds *c + int capability + + + + int sd_bus_creds_has_bounding_cap + sd_bus_creds *c + int capability + + + + int sd_bus_creds_get_selinux_context + sd_bus_creds *c + const char **context + + + + int sd_bus_creds_get_audit_session_id + sd_bus_creds *c + uint32_t *sessionid + + + + int sd_bus_creds_get_audit_login_uid + sd_bus_creds *c + uid_t *loginuid + + + + int sd_bus_creds_get_tty + sd_bus_creds *c + const char **tty + + + + int sd_bus_creds_get_unique_name + sd_bus_creds *c + const char **name + + + + int sd_bus_creds_get_well_known_names + sd_bus_creds *c + char ***name + + + + int sd_bus_creds_get_description + sd_bus_creds *c + const char **name + + + + + + + Description + + These functions return credential information from an + sd_bus_creds object. Credential objects may + be created with + sd_bus_creds_new_from_pid3, + in which case they describe the credentials of the process + identified by the specified PID, with + sd_bus_get_name_creds3, + in which case they describe the credentials of a bus peer + identified by the specified bus name, with + sd_bus_get_owner_creds3, + in which case they describe the credentials of the creator of a + bus, or with + sd_bus_message_get_creds3, + in which case they describe the credentials of the sender of the + message. + + Not all credential fields are part of every + sd_bus_creds object. Use + sd_bus_creds_get_mask3 + to determine the mask of fields available. + + sd_bus_creds_get_pid() will retrieve + the PID (process identifier). Similarly, + sd_bus_creds_get_ppid() will retrieve the + parent PID. Note that PID 1 has no parent process, in which case + -ENXIO is returned. + + sd_bus_creds_get_tid() will retrieve the + TID (thread identifier). + + sd_bus_creds_get_uid() will retrieve + the numeric UID (user identifier). Similarly, + sd_bus_creds_get_euid() returns the effective + UID, sd_bus_creds_get_suid() the saved UID + and sd_bus_creds_get_fsuid() the file system + UID. + + sd_bus_creds_get_gid() will retrieve the + numeric GID (group identifier). Similarly, + sd_bus_creds_get_egid() returns the effective + GID, sd_bus_creds_get_sgid() the saved GID + and sd_bus_creds_get_fsgid() the file system + GID. + + sd_bus_creds_get_supplementary_gids() + will retrieve the supplementary GIDs list. + + sd_bus_creds_get_comm() will retrieve the + comm field (truncated name of the executable, as stored in + /proc/pid/comm). + + + sd_bus_creds_get_tid_comm() will retrieve + the comm field of the thread (as stored in + /proc/pid/task/tid/comm). + + + sd_bus_creds_get_exe() will retrieve the path to the program executable (as + stored in the /proc/pid/exe link, but with the + (deleted) suffix removed). Note that kernel threads do not have an executable path, in which + case -ENXIO is returned. Note that this property should not be used for more than explanatory + information, in particular it should not be used for security-relevant decisions. That's because the + executable might have been replaced or removed by the time the value can be processed. Moreover, the + kernel exports this information in an ambiguous way (i.e. a deleted executable cannot be safely + distinguished from one whose name suffix is (deleted). + + sd_bus_creds_get_cmdline() will + retrieve an array of command line arguments (as stored in + /proc/pid/cmdline). Note + that kernel threads do not have a command line, in which case + -ENXIO is returned. + + sd_bus_creds_get_cgroup() will retrieve + the control group path. See cgroups.txt. + + + sd_bus_creds_get_unit() will retrieve + the systemd unit name (in the system instance of systemd) that the + process is a part of. See + systemd.unit5. For + processes that are not part of a unit, returns -ENXIO. + + + sd_bus_creds_get_user_unit() will + retrieve the systemd unit name (in the user instance of systemd) + that the process is a part of. See + systemd.unit5. For + processes that are not part of a user unit, returns -ENXIO. + + + sd_bus_creds_get_slice() will retrieve + the systemd slice (a unit in the system instance of systemd) that + the process is a part of. See + systemd.slice5. Similarly, + sd_bus_creds_get_user_slice() retrieves the + systemd slice of the process, in the user instance of systemd. + + + sd_bus_creds_get_session() will + retrieve the identifier of the login session that the process is + a part of. Please note the login session may be limited to a stub + process or two. User processes may instead be started from their + systemd user manager, e.g. GUI applications started using DBus + activation, as well as service processes which are shared between + multiple logins of the same user. For processes that are not part + of a session, returns -ENXIO. + + sd_bus_creds_get_owner_uid() will + retrieve the numeric UID (user identifier) of the user who owns + the user unit or login session that the process is a part of. See + systemd-logind.service8. + For processes that are not part of a user unit or session, returns + -ENXIO. + + + sd_bus_creds_has_effective_cap() will check whether the capability specified by + capability was set in the effective capabilities mask. A positive return value means that it + was set, zero means that it was not set, and a negative return value indicates an error. See capabilities7 and the + AmbientCapabilities= and CapabilityBoundingSet= settings in + systemd.exec5. + + + sd_bus_creds_has_permitted_cap() is + similar to sd_bus_creds_has_effective_cap(), + but will check the permitted capabilities mask. + + sd_bus_creds_has_inheritable_cap() is + similar to sd_bus_creds_has_effective_cap(), + but will check the inheritable capabilities mask. + + sd_bus_creds_has_bounding_cap() is + similar to sd_bus_creds_has_effective_cap(), + but will check the bounding capabilities mask. + + sd_bus_creds_get_selinux_context() will + retrieve the SELinux security context (label) of the process. + + sd_bus_creds_get_audit_session_id() + will retrieve the audit session identifier of the process. Returns + -ENXIO for processes that are not part of an audit session. + + sd_bus_creds_get_audit_login_uid() will + retrieve the audit user login identifier (the identifier of the + user who is "responsible" for the session). Returns -ENXIO for + processes that are not part of an audit session. + + sd_bus_creds_get_tty() will retrieve + the controlling TTY, without the prefixing "/dev/". Returns -ENXIO + for processes that have no controlling TTY. + + sd_bus_creds_get_unique_name() will + retrieve the D-Bus unique name. See The + D-Bus specification. + + sd_bus_creds_get_well_known_names() will + retrieve the set of D-Bus well-known names. See The + D-Bus specification. + + sd_bus_creds_get_description() will + retrieve a descriptive name of the bus connection of the + peer. This name is useful to discern multiple bus connections by + the same peer, and may be altered by the peer with the + sd_bus_set_description3 + call. + + All functions that take a const + char** parameter will store the answer there as an + address of a NUL-terminated string. It will be valid as long as + c remains valid, and should not be freed or + modified by the caller. + + All functions that take a char*** + parameter will store the answer there as an address of an array + of strings. Each individual string is NUL-terminated, and the + array is NULL-terminated as a whole. It will be valid as long as + c remains valid, and should not be freed or + modified by the caller. + + + + Return Value + + On success, these calls return 0 or a positive integer. On + failure, these calls return a negative errno-style error code. + + + + Errors + + Returned errors may indicate the following problems: + + + + -ENODATA + + The given field is not available in the credentials object + c. + + + + + -ENXIO + + The given field is not specified for the described process or peer. This will be + returned by sd_bus_creds_get_unit(), + sd_bus_creds_get_slice(), sd_bus_creds_get_user_unit(), + sd_bus_creds_get_user_slice(), and + sd_bus_creds_get_session() if the process is not part of a systemd system + unit, systemd user unit, systemd slice, or logind session. It will be returned by + sd_bus_creds_get_owner_uid() if the process is not part of a systemd user unit + or logind session. It will also be returned by sd_bus_creds_get_exe() and + sd_bus_creds_get_cmdline() for kernel threads (since these are not started + from an executable binary, nor have a command line), and by + sd_bus_creds_get_audit_session_id() and + sd_bus_creds_get_audit_login_uid() when the process is not part of an audit + session, and sd_bus_creds_get_tty() if the process has no controlling + TTY. + + + + -EINVAL + + Specified pointer parameter is NULL. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_creds_new_from_pid2, + fork2, + execve2, + credentials7, + free3, + proc5, + systemd.journal-fields7 + + + + diff --git a/man/sd_bus_creds_new_from_pid.xml b/man/sd_bus_creds_new_from_pid.xml new file mode 100644 index 00000000..f5ee01ca --- /dev/null +++ b/man/sd_bus_creds_new_from_pid.xml @@ -0,0 +1,315 @@ + + + + + + + + sd_bus_creds_new_from_pid + systemd + + + + sd_bus_creds_new_from_pid + 3 + + + + sd_bus_creds_new_from_pid + sd_bus_creds_get_mask + sd_bus_creds_get_augmented_mask + sd_bus_creds_ref + sd_bus_creds_unref + sd_bus_creds_unrefp + + Retrieve credentials object for the specified PID + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_creds_new_from_pid + pid_t pid + uint64_t creds_mask + sd_bus_creds **ret + + + + uint64_t sd_bus_creds_get_mask + sd_bus_creds *c + + + + uint64_t sd_bus_creds_get_augmented_mask + sd_bus_creds *c + + + + sd_bus_creds *sd_bus_creds_ref + sd_bus_creds *c + + + + sd_bus_creds *sd_bus_creds_unref + sd_bus_creds *c + + + + void sd_bus_creds_unrefp + sd_bus_creds **c + + + + + SD_BUS_CREDS_PID, + SD_BUS_CREDS_PPID, + SD_BUS_CREDS_TID, + SD_BUS_CREDS_UID, + SD_BUS_CREDS_EUID, + SD_BUS_CREDS_SUID, + SD_BUS_CREDS_FSUID, + SD_BUS_CREDS_GID, + SD_BUS_CREDS_EGID, + SD_BUS_CREDS_SGID, + SD_BUS_CREDS_FSGID, + SD_BUS_CREDS_SUPPLEMENTARY_GIDS, + SD_BUS_CREDS_COMM, + SD_BUS_CREDS_TID_COMM, + SD_BUS_CREDS_EXE, + SD_BUS_CREDS_CMDLINE, + SD_BUS_CREDS_CGROUP, + SD_BUS_CREDS_UNIT, + SD_BUS_CREDS_SLICE, + SD_BUS_CREDS_USER_UNIT, + SD_BUS_CREDS_USER_SLICE, + SD_BUS_CREDS_SESSION, + SD_BUS_CREDS_OWNER_UID, + SD_BUS_CREDS_EFFECTIVE_CAPS, + SD_BUS_CREDS_PERMITTED_CAPS, + SD_BUS_CREDS_INHERITABLE_CAPS, + SD_BUS_CREDS_BOUNDING_CAPS, + SD_BUS_CREDS_SELINUX_CONTEXT, + SD_BUS_CREDS_AUDIT_SESSION_ID, + SD_BUS_CREDS_AUDIT_LOGIN_UID, + SD_BUS_CREDS_TTY, + SD_BUS_CREDS_UNIQUE_NAME, + SD_BUS_CREDS_WELL_KNOWN_NAMES, + SD_BUS_CREDS_DESCRIPTION, + SD_BUS_CREDS_AUGMENT, + _SD_BUS_CREDS_ALL + + + + + Description + + sd_bus_creds_new_from_pid() creates a + new credentials object and fills it with information about the + process pid. The pointer to this object + will be stored in the ret pointer. Note that + credential objects may also be created and retrieved via + sd_bus_get_name_creds3, + sd_bus_get_owner_creds3 + and + sd_bus_message_get_creds3. + + The information that will be stored is determined by + creds_mask. It may contain a subset of ORed + constants SD_BUS_CREDS_PID, + SD_BUS_CREDS_PPID, + SD_BUS_CREDS_TID, + SD_BUS_CREDS_UID, + SD_BUS_CREDS_EUID, + SD_BUS_CREDS_SUID, + SD_BUS_CREDS_FSUID, + SD_BUS_CREDS_GID, + SD_BUS_CREDS_EGID, + SD_BUS_CREDS_SGID, + SD_BUS_CREDS_FSGID, + SD_BUS_CREDS_SUPPLEMENTARY_GIDS, + SD_BUS_CREDS_COMM, + SD_BUS_CREDS_TID_COMM, + SD_BUS_CREDS_EXE, + SD_BUS_CREDS_CMDLINE, + SD_BUS_CREDS_CGROUP, + SD_BUS_CREDS_UNIT, + SD_BUS_CREDS_SLICE, + SD_BUS_CREDS_USER_UNIT, + SD_BUS_CREDS_USER_SLICE, + SD_BUS_CREDS_SESSION, + SD_BUS_CREDS_OWNER_UID, + SD_BUS_CREDS_EFFECTIVE_CAPS, + SD_BUS_CREDS_PERMITTED_CAPS, + SD_BUS_CREDS_INHERITABLE_CAPS, + SD_BUS_CREDS_BOUNDING_CAPS, + SD_BUS_CREDS_SELINUX_CONTEXT, + SD_BUS_CREDS_AUDIT_SESSION_ID, + SD_BUS_CREDS_AUDIT_LOGIN_UID, + SD_BUS_CREDS_TTY, + SD_BUS_CREDS_UNIQUE_NAME, + SD_BUS_CREDS_WELL_KNOWN_NAMES, and + SD_BUS_CREDS_DESCRIPTION. Use the special + value _SD_BUS_CREDS_ALL to request all + supported fields. The SD_BUS_CREDS_AUGMENT + constant may not be ORed into the mask for invocations of + sd_bus_creds_new_from_pid(). + + Fields can be retrieved from the credentials object using + sd_bus_creds_get_pid3 + and other functions which correspond directly to the constants + listed above. + + A mask of fields which were actually successfully retrieved + can be retrieved with + sd_bus_creds_get_mask(). If the credentials + object was created with + sd_bus_creds_new_from_pid(), this will be a + subset of fields requested in creds_mask. + + + Similar to sd_bus_creds_get_mask(), the + function sd_bus_creds_get_augmented_mask() + returns a bitmask of field constants. The mask indicates which + credential fields have been retrieved in a non-atomic fashion. For + credential objects created via + sd_bus_creds_new_from_pid(), this mask will be + identical to the mask returned by + sd_bus_creds_get_mask(). However, for + credential objects retrieved via + sd_bus_get_name_creds(), this mask will be set + for the credential fields that could not be determined atomically + at peer connection time, and which were later added by reading + augmenting credential data from + /proc. Similarly, for credential objects + retrieved via sd_bus_get_owner_creds(), the + mask is set for the fields that could not be determined atomically + at bus creation time, but have been augmented. Similarly, for + credential objects retrieved via + sd_bus_message_get_creds(), the mask is set + for the fields that could not be determined atomically at message + sending time, but have been augmented. The mask returned by + sd_bus_creds_get_augmented_mask() is always a + subset of (or identical to) the mask returned by + sd_bus_creds_get_mask() for the same + object. The latter call hence returns all credential fields + available in the credential object, the former then marks the + subset of those that have been augmented. Note that augmented + fields are unsuitable for authorization decisions, as they may be + retrieved at different times, thus being subject to races. Hence, + augmented fields should be used exclusively for informational + purposes. + + + sd_bus_creds_ref() creates a new + reference to the credentials object c. This + object will not be destroyed until + sd_bus_creds_unref() has been called as many + times plus once more. Once the reference count has dropped to zero, + c cannot be used anymore, so further + calls to sd_bus_creds_ref(c) or + sd_bus_creds_unref(c) are illegal. + + sd_bus_creds_unref() destroys a reference + to c. + + sd_bus_creds_unrefp() is similar to + sd_bus_creds_unref() but takes a pointer to a + pointer to an sd_bus_creds object. This call is useful in + conjunction with GCC's and LLVM's Clean-up + Variable Attribute. Note that this function is defined as + inline function. + + sd_bus_creds_ref(), + sd_bus_creds_unref() and + sd_bus_creds_unrefp() execute no operation if + the passed in bus credentials object is + NULL. + + + + + Return Value + + On success, sd_bus_creds_new_from_pid() + returns 0 or a positive integer. On failure, it returns a negative + errno-style error code. + + sd_bus_creds_get_mask() returns the + mask of successfully acquired fields. + + sd_bus_creds_get_augmented_mask() + returns the mask of fields that have been augmented from data in + /proc, and are thus not suitable for + authorization decisions. + + sd_bus_creds_ref() always returns the + argument. + + sd_bus_creds_unref() always returns + NULL. + + + + Reference ownership + + Function sd_bus_creds_new_from_pid() + creates a new object and the caller owns the sole reference. When + not needed anymore, this reference should be destroyed with + sd_bus_creds_unref3. + + + + Errors + + Returned errors may indicate the following problems: + + + + + -ESRCH + + Specified pid could not be found. + + + + -EINVAL + + Specified parameter is invalid (NULL in case of output + parameters). + + + + -ENOMEM + + Memory allocation failed. + + + + -EOPNOTSUPP + + One of the requested fields is unknown to the local system. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_creds_get_pid3, + sd_bus_get_name_creds3, + sd_bus_get_owner_creds3, + sd_bus_message_get_creds3 + + + + diff --git a/man/sd_bus_default.xml b/man/sd_bus_default.xml new file mode 100644 index 00000000..51c27f04 --- /dev/null +++ b/man/sd_bus_default.xml @@ -0,0 +1,322 @@ + + + + + + + + sd_bus_default + systemd + + + + sd_bus_default + 3 + + + + sd_bus_default + sd_bus_default_user + sd_bus_default_system + + sd_bus_open + sd_bus_open_with_description + sd_bus_open_user + sd_bus_open_user_with_description + sd_bus_open_system + sd_bus_open_system_with_description + sd_bus_open_system_remote + sd_bus_open_system_machine + + Acquire a connection to a system or user bus + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_default + sd_bus **bus + + + + int sd_bus_default_user + sd_bus **bus + + + + int sd_bus_default_system + sd_bus **bus + + + + int sd_bus_open + sd_bus **bus + + + + int sd_bus_open_with_description + sd_bus **bus + const char *description + + + + int sd_bus_open_user + sd_bus **bus + + + + int sd_bus_open_user_with_description + sd_bus **bus + const char *description + + + + int sd_bus_open_system + sd_bus **bus + + + + int sd_bus_open_system_with_description + sd_bus **bus + const char *description + + + + int sd_bus_open_system_remote + sd_bus **bus + const char *host + + + + int sd_bus_open_system_machine + sd_bus **bus + const char *machine + + + + + + + Description + + sd_bus_default() acquires a bus + connection object to the user bus when invoked in user context, or + to the system bus otherwise. The connection object is associated + with the calling thread. Each time the function is invoked from + the same thread, the same object is returned, but its reference + count is increased by one, as long as at least one reference is + kept. When the last reference to the connection is dropped (using + the + sd_bus_unref3 + call), the connection is terminated. Note that the connection is + not automatically terminated when the associated thread ends. It + is important to drop the last reference to the bus connection + explicitly before the thread ends, as otherwise, the connection will + leak. Also, queued but unread or unwritten messages keep the + bus referenced, see below. + + sd_bus_default_user() returns a user + bus connection object associated with the calling thread. + sd_bus_default_system() is similar, but + connects to the system bus. Note that + sd_bus_default() is identical to these two + calls, depending on the execution context. + + sd_bus_open() creates a new, + independent bus connection to the user bus when invoked in user + context, or the system bus + otherwise. sd_bus_open_user() is similar, but + connects only to the user bus. + sd_bus_open_system() does the same, but + connects to the system bus. In contrast to + sd_bus_default(), + sd_bus_default_user(), and + sd_bus_default_system(), these calls return + new, independent connection objects that are not associated with + the invoking thread and are not shared between multiple + invocations. It is recommended to share connections per thread to + efficiently make use the available resources. Thus, it is + recommended to use sd_bus_default(), + sd_bus_default_user() and + sd_bus_default_system() to connect to the + user or system buses. + + sd_bus_open_with_description(), + sd_bus_open_user_with_description(), and + sd_bus_open_system_with_description() are similar to + sd_bus_open(), sd_bus_open_user(), and + sd_bus_open_system(), but allow a description string to be set, see + sd_bus_set_description3. + description may be NULL, in which case this function + is equivalent to sd_bus_open(). This description string is used in log + messages about the bus object, and including a "name" for the bus makes them easier to + understand. Some messages are emitted during bus initialization, hence using this function is + prefereable to setting the description later with + sd_bus_open_with_description(). The argument is copied internally and will + not be referenced after the function returns. + + If the $DBUS_SESSION_BUS_ADDRESS environment + variable is set + (cf. environ7), + it will be used as the address of the user bus. This variable can + contain multiple addresses separated by ;. If + this variable is not set, a suitable default for the default user + D-Bus instance will be used. + + If the $DBUS_SYSTEM_BUS_ADDRESS + environment variable is set, it will be used as the address of the + system bus. This variable uses the same syntax as + $DBUS_SESSION_BUS_ADDRESS. If this variable is + not set, a suitable default for the default system D-Bus instance + will be used. + + sd_bus_open_system_remote() connects to the system bus on + the specified host using + ssh1. + host consists of an optional user name followed by the + @ symbol, and the hostname, optionally followed by a + : and a port, optionally followed by a + / and a machine name. If the machine name is given, a connection + is created to the system bus in the specified container on the remote machine, and + otherwise a connection to the system bus on the specified host is created. + + Note that entering a container is a privileged operation, and will likely only + work for the root user on the remote machine. + + sd_bus_open_system_machine() connects + to the system bus in the specified machine, + where machine is the name of a local + container. See + machinectl1 + for more information about the "machine" concept. Note that + connections into local containers are only available to privileged + processes at this time. + + These calls allocate a bus connection object and initiate + the connection to a well-known bus of some form. An alternative to + using these high-level calls is to create an unconnected bus + object with + sd_bus_new3 + and to connect it with + sd_bus_start3. + + + + + + Reference ownership + The functions sd_bus_open(), + sd_bus_open_user(), + sd_bus_open_system(), + sd_bus_open_system_remote(), and + sd_bus_open_system_machine() return a new + connection object and the caller owns the sole reference. When not + needed anymore, this reference should be destroyed with + sd_bus_unref3. + + + The functions sd_bus_default(), + sd_bus_default_user() and + sd_bus_default_system() do not necessarily + create a new object, but increase the connection reference of an + existing connection object by one. Use + sd_bus_unref3 + to drop the reference. + + Queued but unwritten/unread messages keep a reference to their bus connection object. For this reason, even + if an application dropped all references to a bus connection, it might not get destroyed right away. Until all + incoming queued messages are read, and until all outgoing unwritten messages are written, the bus object will stay + alive. sd_bus_flush() may be used to write all outgoing queued messages so they drop their + references. To flush the unread incoming messages, use sd_bus_close(), which will also close + the bus connection. When using the default bus logic, it is a good idea to first invoke + sd_bus_flush() followed by sd_bus_close() when a thread or process + terminates, and thus its bus connection object should be freed. + + Normally, slot objects (as created by + sd_bus_add_match3 and similar + calls) keep a reference to their bus connection object, too. Thus, as long as a bus slot object remains referenced + its bus object will remain allocated too. Optionally, bus slot objects may be placed in "floating" mode. When in + floating mode the life cycle of the bus slot object is bound to the bus object, i.e. when the bus object is freed + the bus slot object is automatically unreferenced too. The floating state of a slot object may be controlled + explicitly with + sd_bus_slot_set_floating3, + though usually floating bus slot objects are created by passing NULL as the + slot parameter of sd_bus_add_match() and related calls, thus indicating + that the caller is not directly interested in referencing and managing the bus slot object. + + The life cycle of the default bus connection should be the + responsibility of the code that creates/owns the thread the + default bus connection object is associated with. Library code + should neither call sd_bus_flush() nor + sd_bus_close() on default bus objects unless + it does so in its own private, self-allocated thread. Library code + should not use the default bus object in other threads unless it + is clear that the program using it will life cycle the bus + connection object and flush and close it before exiting from the + thread. In libraries where it is not clear that the calling + program will life cycle the bus connection object, it is hence + recommended to use sd_bus_open_system() + instead of sd_bus_default_system() and + related calls. + + + + Return Value + + On success, these calls return 0 or a positive + integer. On failure, these calls return a negative + errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -EINVAL + + The specified parameters are invalid. + + + + -ENOMEM + + Memory allocation failed. + + + + -ESOCKTNOSUPPORT + + The protocol version required to connect to the selected bus is not + supported. + + + + In addition, any further connection-related errors may be by returned. See + sd_bus_send3. + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_new3, + sd_bus_ref3, + sd_bus_unref3, + ssh1, + systemd-machined.service8, + machinectl1 + + + + diff --git a/man/sd_bus_error.xml b/man/sd_bus_error.xml new file mode 100644 index 00000000..8616f7ee --- /dev/null +++ b/man/sd_bus_error.xml @@ -0,0 +1,367 @@ + + + + + + + + sd_bus_error + systemd + + + + sd_bus_error + 3 + + + + sd_bus_error + SD_BUS_ERROR_MAKE_CONST + SD_BUS_ERROR_NULL + sd_bus_error_free + sd_bus_error_set + sd_bus_error_setf + sd_bus_error_set_const + sd_bus_error_set_errno + sd_bus_error_set_errnof + sd_bus_error_set_errnofv + sd_bus_error_get_errno + sd_bus_error_copy + sd_bus_error_move + sd_bus_error_is_set + sd_bus_error_has_name + + sd-bus error handling + + + + + #include <systemd/sd-bus.h> + + typedef struct { + const char *name; + const char *message; + … +} sd_bus_error; + + + SD_BUS_ERROR_MAKE_CONST(name, message) + + + SD_BUS_ERROR_NULL + + + + void sd_bus_error_free + sd_bus_error *e + + + + int sd_bus_error_set + sd_bus_error *e + const char *name + const char *message + + + + int sd_bus_error_setf + sd_bus_error *e + const char *name + const char *format + … + + + + int sd_bus_error_set_const + sd_bus_error *e + const char *name + const char *message + + + + int sd_bus_error_set_errno + sd_bus_error *e + int error + + + + int sd_bus_error_set_errnof + sd_bus_error *e + int error + const char *format + … + + + + int sd_bus_error_set_errnofv + sd_bus_error *e + int error + const char *format + va_list ap + + + + int sd_bus_error_get_errno + const sd_bus_error *e + + + + int sd_bus_error_copy + sd_bus_error *dst + const sd_bus_error *e + + + + int sd_bus_error_move + sd_bus_error *dst + sd_bus_error *e + + + + int sd_bus_error_is_set + const sd_bus_error *e + + + + int sd_bus_error_has_name + const sd_bus_error *e + const char *name + + + + + + + Description + + The sd_bus_error structure carries + information about a D-Bus error condition. The functions described + below may be used to set and query fields in this structure. The + name field contains a short identifier + of an error. It should follow the rules for error names described + in the D-Bus specification, subsection Valid + Names. A number of common, standardized error names are + described in + sd-bus-errors3, + but additional domain-specific errors may be defined by + applications. The message field usually + contains a human-readable string describing the details, but might + be NULL. An unset sd_bus_error structure + should have both fields initialized to NULL. Set an error + structure to SD_BUS_ERROR_NULL in order to + reset both fields to NULL. When no longer necessary, resources + held by the sd_bus_error structure should + be destroyed with sd_bus_error_free(). + + sd_bus_error_set() sets an error + structure to the specified name and message strings. The strings + will be copied into internal, newly allocated memory. It is + essential to free the error structure again when it is not + required anymore (see above). The function will return an + errno-like negative value (see errno3) + determined from the specified error name. Various well-known + D-Bus errors are converted to well-known errno + counterparts, and the other ones to -EIO. See + sd-bus-errors3 + for a list of well-known error names. Additional error mappings + may be defined with + sd_bus_error_add_map3. If + e is NULL, no error structure is initialized, + but the error is still converted into an + errno-style error. If + name is NULL, it is + assumed that no error occurred, and 0 is returned. This means that + this function may be conveniently used in a + return statement. If + message is NULL, no message is set. This + call can fail if no memory may be allocated for the name and + message strings, in which case an + SD_BUS_ERROR_NO_MEMORY error might be set + instead and -ENOMEM be returned. Do not use this call on error + structures that are already initialized. If you intend to reuse an + error structure, free the old data stored in it with + sd_bus_error_free() first. + + sd_bus_error_setf() is similar to + sd_bus_error_set(), but takes a printf3 + format string and corresponding arguments to generate the + message field. + + sd_bus_error_set_const() is similar to + sd_bus_error_set(), but the string parameters + are not copied internally, and must hence remain constant and + valid for the lifetime of e. Use this call + to avoid memory allocations when setting error structures. Since + this call does not allocate memory, it will not fail with an + out-of-memory condition as + sd_bus_error_set() can, as described + above. Alternatively, the + SD_BUS_ERROR_MAKE_CONST() macro may be used + to generate a literal, constant bus error structure + on-the-fly. + + sd_bus_error_set_errno() will set + name from an + errno-like value that is converted to a D-Bus + error. strerror_r3 + will be used to set message. Well-known + D-Bus error names will be used for name + if applicable, otherwise a name in the + System.Error. namespace will be generated. The + sign of the specified error number is ignored. The absolute value + is used implicitly. The call always returns a negative value, for + convenient usage in return statements. This + call might fail due to lack of memory, in which case an + SD_BUS_ERROR_NO_MEMORY error is set instead, + and -ENOMEM is returned. + + sd_bus_error_set_errnof() is similar to + sd_bus_error_set_errno(), but in addition to + error, takes a printf3 + format string and corresponding arguments. The + message field will be generated from + format and the arguments. + + sd_bus_error_set_errnofv() is similar to + sd_bus_error_set_errnof(), but takes the + format string parameters as va_arg3 + parameter list. + + sd_bus_error_get_errno() converts the + name field of an error structure to an + errno-like (positive) value using the same + rules as sd_bus_error_set(). If + e is NULL, 0 will be + returned. + + sd_bus_error_copy() will initialize + dst using the values in + e. If the strings in + e were set using + sd_bus_error_set_const(), they will be shared. + Otherwise, they will be copied. Returns a converted + errno-like, negative error code. + + sd_bus_error_move() is similar to sd_bus_error_copy(), but will + move any error information from e into dst, resetting the + former. This function cannot fail, as no new memory is allocated. Note that if e is not set + (or NULL) dst is initializated to + SD_BUS_ERROR_NULL. Moreover, if dst is NULL no + operation is executed on it and and resources held by e are freed and reset. Returns a + converted errno-like, negative error code. + + sd_bus_error_is_set() will return a + non-zero value if e is + non-NULL and an error has been set, + false otherwise. + + sd_bus_error_has_name() will return a + non-zero value if e is + non-NULL and an error with the same + name has been set, + false otherwise. + + sd_bus_error_free() will destroy + resources held by e. The parameter itself + will not be deallocated, and must be free3d + by the caller if necessary. The function may also be called safely + on unset errors (error structures with both fields set to NULL), + in which case it performs no operation. This call will reset the + error structure after freeing the data, so that all fields are set + to NULL. The structure may be reused afterwards. + + + + Return Value + + The functions sd_bus_error_set(), + sd_bus_error_setf(), and + sd_bus_error_set_const(), when successful, + return the negative errno value corresponding to the + name parameter. The functions + sd_bus_error_set_errno(), + sd_bus_error_set_errnof() and + sd_bus_error_set_errnofv(), when successful, + return the negative value of the error + parameter. If an error occurs, one of the negative error values + listed below will be returned. + + sd_bus_error_get_errno() returns + false when e is + NULL, and a positive errno value mapped from + e->name otherwise. + + sd_bus_error_copy() and sd_bus_error_move() return 0 or a positive + integer on success, and a negative error value converted from the error name otherwise. + + sd_bus_error_is_set() returns a + non-zero value when e and the + name field are + non-NULL, zero otherwise. + + sd_bus_error_has_name() returns a + non-zero value when e is + non-NULL and the + name field is equal to + name, zero otherwise. + + + + Reference ownership + sd_bus_error is not reference + counted. Users should destroy resources held by it by calling + sd_bus_error_free(). Usually, error structures + are allocated on the stack or passed in as function parameters, + but they may also be allocated dynamically, in which case it is + the duty of the caller to free3 + the memory held by the structure itself after freeing its contents + with sd_bus_error_free(). + + + Errors + + Returned errors may indicate the following problems: + + + + + -EINVAL + + Error was already set in sd_bus_error structure when one + the error-setting functions was called. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd-bus-errors3, + sd_bus_error_add_map3, + errno3, + strerror_r3 + + + + diff --git a/man/sd_bus_error_add_map.xml b/man/sd_bus_error_add_map.xml new file mode 100644 index 00000000..1dfc7259 --- /dev/null +++ b/man/sd_bus_error_add_map.xml @@ -0,0 +1,139 @@ + + + + + + + + sd_bus_error_add_map + systemd + + + + sd_bus_error_add_map + 3 + + + + sd_bus_error_add_map + sd_bus_error_map + SD_BUS_ERROR_MAP + SD_BUS_ERROR_END + + Additional sd-dbus error mappings + + + + + #include <systemd/sd-bus.h> + + typedef struct { + const char *name; + int code; + … +} sd_bus_error_map; + + + + + SD_BUS_ERROR_MAP(name, code) + + + SD_BUS_ERROR_MAP_END + + + + int sd_bus_error_add_map + const sd_bus_map *map + + + + + + Description + + The sd_bus_error_add_map() call may be + used to register additional mappings for converting D-Bus errors + to Linux errno-style errors. The mappings + defined with this call are consulted by calls such as + sd_bus_error_set3 + or + sd_bus_error_get_errno3. By + default, a number of generic, standardized mappings are known, as + documented in + sd-bus-errors3. Use + this call to add further, application-specific mappings. + + The function takes a pointer to an array of + sd_bus_error_map structures. A reference + to the specified array is added to the lookup tables for error + mappings. Note that the structure is not copied, and that it is hence + essential that the array stays available and constant during the + entire remaining runtime of the process. + + The mapping array should be put together with a series of + SD_BUS_ERROR_MAP() macro invocations that + take a literal name string and a (positive) + errno-style error number. The last entry of the + array should be an invocation of the + SD_BUS_ERROR_MAP_END macro. The array should not be + put together without use of these two macros. + + Note that the call is idempotent: it is safe to invoke it + multiple times with the parameter, which will only add the passed + mapping array once. + + Note that the memory allocated by this call is not intended + to be freed during the lifetime of the process. It should not be + freed explicitly. + + + + Return Value + + sd_bus_error_add_map() returns a + positive value when the new array was added to the lookup + tables. It returns zero when the same array was already added + before. On error, a negative errno-style error + code is returned. See below for known error codes. + + + Errors + + Returned errors may indicate the following problems: + + + + + -EINVAL + + The specified mapping array is invalid. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_error3, + sd-bus-errors3, + errno3, + strerror_r3 + + + + diff --git a/man/sd_bus_get_fd.xml b/man/sd_bus_get_fd.xml new file mode 100644 index 00000000..6a022b1a --- /dev/null +++ b/man/sd_bus_get_fd.xml @@ -0,0 +1,160 @@ + + + + + + + + + sd_bus_get_fd + systemd + + + + sd_bus_get_fd + 3 + + + + sd_bus_get_fd + sd_bus_get_events + sd_bus_get_timeout + + Get the file descriptor, I/O events and time-out to wait for from a message bus object + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_get_fd + sd_bus *bus + + + + int sd_bus_get_events + sd_bus *bus + + + + int sd_bus_get_timeout + sd_bus *bus + uint64_t *timeout_usec + + + + + + Description + + sd_bus_get_fd() returns the file descriptor used to communicate from a message bus + object. This descriptor can be used with poll3 or a similar + function to wait for I/O events on the specified bus connection object. If the bus object was configured with the + sd_bus_set_fd3 function, then + the input_fd file descriptor used in that call is returned. + + sd_bus_get_events() returns the I/O events to wait for, suitable for passing to + poll() or a similar call. Returns a combination of POLLIN, + POLLOUT, … events, or negative on error. + + sd_bus_get_timeout() returns the time-out in µs to pass to to + poll() or a similar call when waiting for events on the specified bus connection. The returned + time-out may be zero, in which case a subsequent I/O polling call should be invoked in non-blocking mode. The + returned timeout may be UINT64_MAX in which case the I/O polling call may block indefinitely, + without any applied time-out. Note that the returned time-out should be considered only a maximum sleeping time. It + is permissible (and even expected) that shorter time-outs are used by the calling program, in case other event + sources are polled in the same event loop. Note that the returned time-value is relative and specified in + microseconds. When converting this value in order to pass it as third argument to poll() + (which expects milliseconds), care should be taken to use a division that rounds up to ensure the I/O polling + operation doesn't sleep for shorter than necessary, which might result in unintended busy looping (alternatively, + use ppoll3 + instead of plain poll(), which understands time-outs with nano-second granularity). + + These three functions are useful to hook up a bus connection object with an external or manual event loop + involving poll() or a similar I/O polling call. Before each invocation of the I/O polling + call, all three functions should be invoked: the file descriptor returned by sd_bus_get_fd() + should be polled for the events indicated by sd_bus_get_events(), and the I/O call should + block for that up to the time-out returned by sd_bus_get_timeout(). After each I/O polling + call the bus connection needs to process incoming or outgoing data, by invoking + sd_bus_process3. + + Note that these function are only one of three supported ways to implement I/O event handling for bus + connections. Alternatively use + sd_bus_attach_event3 to attach a + bus connection to an sd-event3 + event loop. Or use sd_bus_wait3 + as a simple synchronous, blocking I/O waiting call. + + + + Return Value + + sd_bus_get_fd() returns the file descriptor used for communication, or a negative + errno-style error code on error. + + sd_bus_get_events() returns the I/O event mask to use for I/O event watching, or a + negative errno-style error code on error. + + sd_bus_get_timeout() returns zero or positive on success, or a negative + errno-style error code on error. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + An invalid bus object was passed. + + + + -ECHILD + + The bus connection was allocated in a parent process and is being reused in a child + process after fork(). + + + + -ENOTCONN + + The bus connection has been terminated. + + + + -EPERM + + Two distinct file descriptors were passed for input and output using + sd_bus_set_fd(), which sd_bus_get_fd() cannot + return. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_set_fd3, + sd_bus_process3, + sd_bus_attach_event3, + sd_bus_wait3, + poll3 + + + + diff --git a/man/sd_bus_get_n_queued_read.xml b/man/sd_bus_get_n_queued_read.xml new file mode 100644 index 00000000..f949c936 --- /dev/null +++ b/man/sd_bus_get_n_queued_read.xml @@ -0,0 +1,100 @@ + + + + + + + + sd_bus_get_fd + systemd + + + + sd_bus_get_n_queued_read + 3 + + + + sd_bus_get_n_queued_read + sd_bus_get_n_queued_write + + Get the number of pending bus messages in the read and write queues of a bus connection object + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_get_n_queued_read + sd_bus *bus + uint64_t *ret + + + + int sd_bus_get_n_queued_write + sd_bus *bus + uint64_t *ret + + + + + + Description + + + sd_bus_get_n_queued_read() may be used to query the number of bus messages in the read queue + of a bus connection object. The read queue contains all messages read from the transport medium (e.g. network + socket) but not yet processed locally. The function expects two arguments: the bus object to query, and a pointer + to a 64bit counter variable to write the current queue size to. Use sd_bus_process() in + order to process queued messages, i.e. to reduce the size of the read queue (as well as, in fact, the write + queue, see below). + + + + Similarly, sd_bus_get_n_queued_write() may be used to query the number of currently pending + bus messages in the write queue of a bus connection object. The write queue contains all messages enqueued into + the connection with a call such as sd_bus_send() but not yet written to the transport + medium. The expected arguments are similar to sd_bus_get_n_queued_read(). Here too, use + sd_bus_process() to reduce the size of the write queue. Alternatively, use + sd_bus_flush() to synchronously write out any pending bus messages until the write queue is + empty. + + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style + error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ECHILD + + The bus connection was created in a different process. + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_process3, + sd_bus_send3, + sd_bus_flush3 + + + + diff --git a/man/sd_bus_is_open.xml b/man/sd_bus_is_open.xml new file mode 100644 index 00000000..d993142c --- /dev/null +++ b/man/sd_bus_is_open.xml @@ -0,0 +1,103 @@ + + + + + + + + sd_bus_is_open + systemd + + + + sd_bus_is_open + 3 + + + + sd_bus_is_open + sd_bus_is_ready + + Check whether the a bus connection is open or ready. + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_is_open + sd_bus *bus + + + + int sd_bus_is_ready + sd_bus *bus + + + + + + + Description + + sd_bus_is_open() checks whether the specified bus connection is open, i.e. in the + process of being established, already established or in the process of being torn down. It returns zero when the + connection has not been started yet + (i.e. sd_bus_start3 or some + equivalent call has not been invoked yet), or is fully terminated again (for example after + sd_bus_close3), it returns + positive otherwise. + + sd_bus_is_ready() checks whether the specified connection is fully established, + i.e. completed the connection and authentication phases of the protocol and received the + Hello() method call response, and is not in the process of being torn down again. It returns + zero outside of this state, and positive otherwise. Effectively, this function returns positive while regular + messages can be sent or received on the connection. + + To be notified when the connection is fully established, use + sd_bus_set_connected_signal3 and + install a match for the Connected() signal on the + org.freedesktop.DBus.Local interface. To be notified when the connection is torn down again, + install a match for the Disconnected() signal on the + org.freedesktop.DBus.Local interface. + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style + error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ECHILD + + The bus connection has been created in a different process. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_start3, + sd_bus_close3, + sd_bus_set_connected_signal3 + + + + diff --git a/man/sd_bus_message_append.xml b/man/sd_bus_message_append.xml new file mode 100644 index 00000000..b87468e3 --- /dev/null +++ b/man/sd_bus_message_append.xml @@ -0,0 +1,249 @@ + + + + + + + + sd_bus_message_append + systemd + + + + sd_bus_message_append + 3 + + + + sd_bus_message_append + sd_bus_message_appendv + + Attach fields to a D-Bus message based on a type + string + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_append + sd_bus_message *m + const char *types + … + + + + int sd_bus_message_appendv + sd_bus_message *m + const char *types + va_list ap + + + + + + + Description + + The sd_bus_message_append() function + appends a sequence of fields to the D-Bus message object + m. The type string + types describes the types of the field + arguments that follow. For each type specified in the type string, + one or more arguments need to be specified, in the same order as + declared in the type string. + + The type string is composed of the elements shown in the + table below. It contains zero or more single "complete types". + Each complete type may be one of the basic types or a fully + described container type. A container type may be a structure with + the contained types, a variant, an array with its element type, or + a dictionary entry with the contained types. The type string is + NUL-terminated. + + In case of a basic type, one argument of the corresponding + type is expected. + + A structure is denoted by a sequence of complete types + between ( and ). This + sequence cannot be empty — it must contain at least one type. + Arguments corresponding to this nested sequence follow the same + rules as if they were not nested. + + A variant is denoted by v. Corresponding + arguments must begin with a type string denoting a complete type, + and following that, arguments corresponding to the specified type. + + + An array is denoted by a followed by a + complete type. Corresponding arguments must begin with the number of + entries in the array, followed by the entries themselves, + matching the element type of the array. + + A dictionary is an array of dictionary entries, denoted by + a followed by a pair of complete types between + { and }. The first of those + types must be a basic type. Corresponding arguments must begin + with the number of dictionary entries, followed by a pair of + values for each entry matching the element type of + the dictionary entries. + + The sd_bus_message_appendv() is equivalent to the + sd_bus_message_append(), except that it is called with + a va_list instead of a variable number of arguments. This + function does not call the va_end() macro. Because it + invokes the va_arg() macro, the value of + ap is undefined after the call. + + For further details on the D-Bus type system, please consult + the D-Bus + Specification. + + + Item type specifiers + + + + + + + + + + a + SD_BUS_TYPE_ARRAY + array + determined by array type and size + int, followed by array contents + + + + v + SD_BUS_TYPE_VARIANT + variant + determined by the type argument + signature string, followed by variant contents + + + + ( + SD_BUS_TYPE_STRUCT_BEGIN + array start + determined by the nested types + structure contents + + + ) + SD_BUS_TYPE_STRUCT_END + array end + + + + { + SD_BUS_TYPE_DICT_ENTRY_BEGIN + dictionary entry start + determined by the nested types + dictionary contents + + + } + SD_BUS_TYPE_DICT_ENTRY_END + dictionary entry end + + + +
+ + For types "s" and "g" (unicode string or signature), the pointer may be + NULL, which is equivalent to an empty string. See + sd_bus_message_append_basic3 + for the precise interpretation of those and other types. + +
+ + + Types String Grammar + + types ::= complete_type* +complete_type ::= basic_type | variant | structure | array | dictionary +basic_type ::= "y" | "n" | "q" | "u" | "i" | "x" | "t" | "d" | + "b" | "h" | + "s" | "o" | "g" +variant ::= "v" +structure ::= "(" complete_type+ ")" +array ::= "a" complete_type +dictionary ::= "a" "{" basic_type complete_type "}" + + + + + Examples + + Append a single basic type (the string a string): + + + sd_bus_message *m; +… +sd_bus_message_append(m, "s", "a string"); + + Append all types of integers: + + uint8_t y = 1; +int16_t n = 2; +uint16_t q = 3; +int32_t i = 4; +uint32_t u = 5; +int32_t x = 6; +uint32_t t = 7; +double d = 8.0; +sd_bus_message_append(m, "ynqiuxtd", y, n, q, i, u, x, t, d); + + Append a structure composed of a string and a D-Bus path: + + sd_bus_message_append(m, "(so)", "a string", "/a/path"); + + + Append an array of UNIX file descriptors: + + sd_bus_message_append(m, "ah", 3, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO); + + + Append a variant, with the real type "g" (signature), + and value "sdbusisgood": + + sd_bus_message_append(m, "v", "g", "sdbusisgood"); + + Append a dictionary containing the mapping {1=>"a", 2=>"b", 3=>""}: + + + sd_bus_message_append(m, "a{is}", 3, 1, "a", 2, "b", 3, NULL); + + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a negative + errno-style error code. + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_append_basic3, + sd_bus_message_append_array3 + + + +
diff --git a/man/sd_bus_message_append_array.xml b/man/sd_bus_message_append_array.xml new file mode 100644 index 00000000..b9595d6a --- /dev/null +++ b/man/sd_bus_message_append_array.xml @@ -0,0 +1,178 @@ + + + + + + + + sd_bus_message_append_array + systemd + + + + sd_bus_message_append_array + 3 + + + + sd_bus_message_append_array + sd_bus_message_append_array_memfd + sd_bus_message_append_array_iovec + sd_bus_message_append_array_space + + Append an array of fields to a D-Bus + message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_append_array + sd_bus_message *m + char type + char void *ptr + size_t size + + + + int sd_bus_message_append_array_memfd + sd_bus_message *m + char type + int memfd + uint64_t offset + uint64_t size + + + + int sd_bus_message_append_array_iovec + sd_bus_message *m + char type + const struct iovec *iov + unsigned n + + + + int sd_bus_message_append_array_space + char type + size_t size + void **ptr + + + + + + Description + + The sd_bus_message_append_array() + function appends an array to a D-Bus message + m. A container will be opened, the array + contents appended, and the container closed. The parameter + type determines how the pointer + p is interpreted. + type must be one of the "trivial" types + y, n, q, + i, u, x, + t, d (but not + b), as defined by the Basic + Types section of the D-Bus specification, and listed in + sd_bus_message_append_basic3. + Pointer p must point to an array of size + size bytes containing items of the + respective type. Size size must be a + multiple of the size of the type type. As a + special case, p may be + NULL, if size is 0. + The memory pointed to by p is copied into + the memory area containing the message and stays in possession of + the caller. The caller may hence freely change the data after this + call without affecting the message the array was appended + to. + + The sd_bus_message_append_array_memfd() + function appends an array of a trivial type to message + m, similar to + sd_bus_message_append_array(). The contents + of the memory file descriptor memfd + starting at the specified offset and of the specified size is + used as the contents of the array. The offset and size must be a + multiple of the size of the type + type. However, as a special exception, if + the offset is specified as zero and the size specified as + UINT64_MAX the full memory file descriptor contents is used. The + memory file descriptor is sealed by this call if it has not been + sealed yet, and cannot be modified after this call. See + memfd_create2 + for details about memory file descriptors. Appending arrays with + memory file descriptors enables efficient zero-copy data transfer, + as the memory file descriptor may be passed as-is to the + destination, without copying the memory in it to the destination + process. Not all protocol transports support passing memory file + descriptors between participants, in which case this call will + automatically fall back to copying. Also, as memory file + descriptor passing is inefficient for smaller amounts of data, + copying might still be enforced even where memory file descriptor + passing is supported. + + The sd_bus_message_append_array_iovec() + function appends an array of a trivial type to the message + m, similar to + sd_bus_message_append_array(). Contents of + the I/O vector array iov are used as the + contents of the array. The total size of + iov payload (the sum of + iov_len fields) must be a multiple of + the size of the type type. The + iov argument must point to + n I/O vector structures. Each structure may + have the iov_base field set, in which + case the memory pointed to will be copied into the message, or + unset (set to zero), in which case a block of zeros of length + iov_len bytes will be inserted. The + memory pointed at by iov may be changed + after this call. + + The sd_bus_message_append_array_space() + function appends space for an array of a trivial type to message + m. It behaves the same as + sd_bus_message_append_array(), but instead of + copying items to the message, it returns a pointer to the + destination area to the caller in pointer + p. The caller should subsequently write the + array contents to this memory. Modifications to the memory + pointed to should only occur until the next operation on the bus + message is invoked. Most importantly, the memory should not be + altered anymore when another field has been added to the message + or the message has been sealed. + + + + Return Value + + On success, these calls return 0 or a positive integer. On failure, they return a negative + errno-style error code. + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_append3, + sd_bus_message_append_basic3, + memfd_create2, + The D-Bus specification + + + + diff --git a/man/sd_bus_message_append_basic.xml b/man/sd_bus_message_append_basic.xml new file mode 100644 index 00000000..a180046b --- /dev/null +++ b/man/sd_bus_message_append_basic.xml @@ -0,0 +1,261 @@ + + + + + + + + sd_bus_message_append_basic + systemd + + + + sd_bus_message_append_basic + 3 + + + + sd_bus_message_append_basic + + Attach a single field to a message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_append_basic + sd_bus_message *m + char type + const void *p + + + + + + Description + + sd_bus_message_append_basic() appends a + single field to the message m. The + parameter type determines how the pointer + p is interpreted. + type must be one of the basic types as + defined by the Basic + Types section of the D-Bus specification, and listed in + the table below. + + + + Item type specifiers + + + + + + + + + + Specifier + Constant + Description + Size + Expected C Type + + + + + y + SD_BUS_TYPE_BYTE + unsigned integer + 1 byte + uint8_t + + + + b + SD_BUS_TYPE_BOOLEAN + boolean + 4 bytes + int + + + + n + SD_BUS_TYPE_INT16 + signed integer + 2 bytes + int16_t + + + + q + SD_BUS_TYPE_UINT16 + unsigned integer + 2 bytes + uint16_t + + + + i + SD_BUS_TYPE_INT32 + signed integer + 4 bytes + int32_t + + + + u + SD_BUS_TYPE_UINT32 + unsigned integer + 4 bytes + uint32_t + + + + x + SD_BUS_TYPE_INT64 + signed integer + 8 bytes + int64_t + + + + t + SD_BUS_TYPE_UINT64 + unsigned integer + 8 bytes + uint64_t + + + + d + SD_BUS_TYPE_DOUBLE + floating-point + 8 bytes + double + + + + s + SD_BUS_TYPE_STRING + Unicode string + variable + char[] + + + + o + SD_BUS_TYPE_OBJECT_PATH + object path + variable + char[] + + + + g + SD_BUS_TYPE_SIGNATURE + signature + variable + char[] + + + + h + SD_BUS_TYPE_UNIX_FD + UNIX file descriptor + 4 bytes + int + + + +
+ + The value of the parameter is copied into a memory area held + by the message object, stays in the possession of the caller and + may hence be freely changed after this call without affecting the + bus message it has been added to. If type + is h (UNIX file descriptor), the descriptor is + duplicated by this call and the passed descriptor stays in + possession of the caller. + + For types s, o, and + g, the parameter p is + interpreted as a pointer to a NUL-terminated + character sequence. As a special case, a NULL + pointer is interpreted as an empty string. The string should be + valid Unicode string encoded as UTF-8. In case of the two latter + types, the additional requirements for a D-Bus object path or + type signature should be satisfied. Those requirements should be + verified by the recipient of the message. + +
+ + + Return Value + + On success, this call returns 0 or a positive integer. On + failure, it returns a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -EINVAL + + Specified parameter is invalid. + + + + + -EPERM + + Message has been sealed. + + + + + -ESTALE + + Message is in invalid state. + + + + + -ENXIO + + Message cannot be appended to. + + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_read_basic3, + sd_bus_message_append3, + The D-Bus specification + + + +
diff --git a/man/sd_bus_message_append_string_memfd.xml b/man/sd_bus_message_append_string_memfd.xml new file mode 100644 index 00000000..c59b8a42 --- /dev/null +++ b/man/sd_bus_message_append_string_memfd.xml @@ -0,0 +1,119 @@ + + + + + + + + sd_bus_message_append_string_memfd + systemd + + + + sd_bus_message_append_string_memfd + 3 + + + + sd_bus_message_append_string_memfd + sd_bus_message_append_string_iovec + sd_bus_message_append_string_space + + Attach a string to a message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_append_string_memfd + sd_bus_message *m + int memfd + + + + int sd_bus_message_append_string_iovec + sd_bus_message *m + const struct iovec *iov + unsigned n + + + + int sd_bus_message_append_string_space + sd_bus_message *m + size_t size + char **s + + + + + + Description + + The functions + sd_bus_message_append_string_memfd and + sd_bus_message_append_string_iovec can be + used to append a single string (item of type s) + to message m. + + In case of + sd_bus_message_append_string_memfd, the + contents of memfd are the string. They must + satisfy the same constraints as described for the + s type in + sd_bus_message_append_basic3. + + In case of + sd_bus_message_append_string_iovec, the + payload of iov is the string. It must + satisfy the same constraints as described for the + s type in + sd_bus_message_append_basic3. + + The iov argument must point to + n struct iovec + structures. Each structure may have the + iov_base field set, in which case the + memory pointed to will be copied into the message, or unset, in + which case a block of spaces (ASCII 32) of length + iov_len will be inserted. The + memory pointed at by iov may be changed + after this call. + + The + sd_bus_message_append_string_space function appends + space for a string to message m. It behaves + similar to sd_bus_message_append_basic with + type s, but instead of copying a string into + the message, it returns a pointer to the destination area to + the caller in pointer p. Space for the string + of length size plus the terminating + NUL is allocated. + + + + Return Value + + On success, those calls return 0 or a positive integer. On failure, they return a negative + errno-style error code. + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_append_basic3, + The D-Bus specification + + + + diff --git a/man/sd_bus_message_append_strv.xml b/man/sd_bus_message_append_strv.xml new file mode 100644 index 00000000..2ce32163 --- /dev/null +++ b/man/sd_bus_message_append_strv.xml @@ -0,0 +1,81 @@ + + + + + + + + sd_bus_message_append_strv + systemd + + + + sd_bus_message_append_strv + 3 + + + + sd_bus_message_append_strv + + Attach an array of strings to a message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_append_strv + sd_bus_message *m + char **l + + + + + + Description + + The sd_bus_message_append function can be + used to append an array of strings to message + m. The parameter l + shall point to a NULL-terminated array of pointers + to NUL-terminated strings. Each string must + satisfy the same constraints as described for the + s type in + sd_bus_message_append_basic3. + + + The memory pointed at by p and the + contents of the strings themselves are copied into the memory area + containing the message and may be changed after this call. Note + that the signature of l parameter is to be + treated as const char *const *, and the contents + will not be modified. + + + + Return Value + + On success, this call returns 0 or a positive integer. On failure, a negative errno-style error + code is returned. + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_append3, + sd_bus_message_append_array3, + The D-Bus specification + + + + diff --git a/man/sd_bus_message_copy.xml b/man/sd_bus_message_copy.xml new file mode 100644 index 00000000..cd8ad72e --- /dev/null +++ b/man/sd_bus_message_copy.xml @@ -0,0 +1,111 @@ + + + + + + + + sd_bus_message_copy + systemd + + + + sd_bus_message_copy + 3 + + + + sd_bus_message_copy + + Copy the contents of one message to another + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_copy + sd_bus_message *m + sd_bus_message *source + int all + + + + + + Description + + sd_bus_message_copy() copies the contents from + message source to m. If + all is false, a single complete type is copied + (basic or container). If all is true, the contents + are copied until the end of the currently open container or the end + of source. + + + + Return Value + + On success, this call returns true if anything was copied, and false if + there was nothing to copy. On failure, it returns a negative errno-style error + code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -EINVAL + + source or m are + NULL. + + + + -EPERM + + Message m has been sealed or source + has not been sealed. + + + + -ESTALE + + Destination message is in invalid state. + + + + + -ENXIO + + Destination message cannot be appended to. + + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_append3 + + + + diff --git a/man/sd_bus_message_get_cookie.xml b/man/sd_bus_message_get_cookie.xml new file mode 100644 index 00000000..7b9408c0 --- /dev/null +++ b/man/sd_bus_message_get_cookie.xml @@ -0,0 +1,107 @@ + + + + + + + + sd_bus_message_get_cookie + systemd + + + + sd_bus_message_get_cookie + 3 + + + + sd_bus_message_get_cookie + sd_bus_message_get_reply_cookie + Returns the transaction cookie of a message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_get_cookie + sd_bus_message *message + uint64_t *cookie + + + + int sd_bus_message_get_reply_cookie + sd_bus_message *message + uint64_t *cookie + + + + + + Description + + sd_bus_message_get_cookie() returns the + transaction cookie of a message. The cookie uniquely identifies a + message within each bus peer, but is not globally unique. It is + assigned when a message is sent. + + sd_bus_message_get_reply_cookie() + returns the transaction cookie of the message the specified + message is a response to. When a reply message is generated for a + method call message, its cookie is copied over into this field. + Note that while every message that is transferred is identified by + a cookie, only response messages carry a reply cookie + field. + + Both functions take a message object as first parameter and + a place to store the 64-bit cookie in. + + + + Return Value + + On success, these calls return 0 or a positive integer. On failure, they return a negative + errno-style error code. + + On success, the cookie/reply cookie is returned in the specified 64-bit unsigned integer + variable. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + A specified parameter is invalid. + + + + -ENODATA + + No cookie has been assigned to this message. This either indicates that the + message has not been sent yet and hence has no cookie assigned, or that the message is not a method + response message and hence carries a reply cookie field. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_new3 + + + + diff --git a/man/sd_bus_message_get_monotonic_usec.xml b/man/sd_bus_message_get_monotonic_usec.xml new file mode 100644 index 00000000..958b8325 --- /dev/null +++ b/man/sd_bus_message_get_monotonic_usec.xml @@ -0,0 +1,141 @@ + + + + + + + + sd_bus_message_get_monotonic_usec + systemd + + + + sd_bus_message_get_monotonic_usec + 3 + + + + sd_bus_message_get_monotonic_usec + sd_bus_message_get_realtime_usec + sd_bus_message_get_seqnum + Retrieve the sender timestamps and sequence number of a message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_get_monotonic_usec + sd_bus_message *message + uint64_t *usec + + + + int sd_bus_message_get_realtime_usec + sd_bus_message *message + uint64_t *usec + + + + int sd_bus_message_get_seqnum + sd_bus_message *message + uint64_t *seqnum + + + + + + Description + + sd_bus_message_get_monotonic_usec() + returns the monotonic timestamp of the time the message was sent. + This value is in microseconds since the + CLOCK_MONOTONIC epoch, see + clock_gettime2 + for details. + + Similarly, + sd_bus_message_get_realtime_usec() returns + the realtime (wallclock) timestamp of the time the message was + sent. This value is in microseconds since Jan 1st, 1970, i.e. in + the CLOCK_REALTIME clock. + + sd_bus_message_get_seqnum() returns the + kernel-assigned sequence number of the message. The kernel assigns + a global, monotonically increasing sequence number to all messages + transmitted on the local system, at the time the message was sent. + This sequence number is useful for determining message send order, + even across different buses of the local system. The sequence + number combined with the boot ID of the system (as returned by + sd_id128_get_boot3) + is a suitable globally unique identifier for bus messages. + + Note that the sending order and receiving order of messages + might differ, in particular for broadcast messages. This means + that the sequence number and the timestamps of messages a client + reads are not necessarily monotonically increasing. + + These timestamps and the sequence number are attached to + each message by the kernel and cannot be manipulated by the + sender. + + Note that these timestamps are only available on some bus + transports, and only after support for them has been negotiated + with the + sd_bus_negotiate_timestamp3 + call. + + + + Return Value + + On success, these calls return 0 or a positive integer. On + failure, these calls return a negative errno-style error + code. + + On success, the timestamp or sequence number is returned in + the specified 64-bit unsigned integer variable. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + A specified parameter is invalid. + + + + -ENODATA + + No timestamp or sequence number information is attached to the passed message. This + error is returned if the underlying transport does not support timestamping or assigning of + sequence numbers, or if this feature has not been negotiated with + sd_bus_negotiate_timestamp3. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_new3, + sd_bus_negotiate_timestamp3, + clock_gettime2, + sd_id128_get_boot3 + + + + diff --git a/man/sd_bus_message_get_signature.xml b/man/sd_bus_message_get_signature.xml new file mode 100644 index 00000000..e3f41346 --- /dev/null +++ b/man/sd_bus_message_get_signature.xml @@ -0,0 +1,111 @@ + + + + + + + sd_bus_message_get_signature + systemd + + + + sd_bus_message_get_signature + 3 + + + + sd_bus_message_get_signature + sd_bus_message_is_empty + sd_bus_message_has_signature + + Query bus message signature + + + + + #include <systemd/sd-bus.h> + + + const char* sd_bus_message_get_signature + sd_bus_message *message + int complete + + + + int sd_bus_message_is_empty + sd_bus_message *message + + + + int sd_bus_message_has_signature + sd_bus_message *message + const char *signature + + + + + + + Description + + sd_bus_message_get_signature() returns the signature of message + message. If complete is true, the signature of the + whole message is returned, and just the signature of the currently open container otherwise. + + + sd_bus_message_is_empty() returns true if the message is empty, + i.e. when its signature is empty. + + sd_bus_message_has_signature() returns true if the signature of the + message message matches given signature. Parameter + signature may be NULL, this is treated the same as + an empty string, which is equivalent to calling sd_bus_message_is_empty(). + + + + + Return Value + + On success, sd_bus_message_get_signature() returns + the signature, and NULL on error. + + The other functions return 0 or a positive integer on success. On failure, they return a + negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The message parameter is NULL. + + + + + NULL + + The message parameter is NULL. + + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_new3 + + + + diff --git a/man/sd_bus_message_get_type.xml b/man/sd_bus_message_get_type.xml new file mode 100644 index 00000000..d8a45ce7 --- /dev/null +++ b/man/sd_bus_message_get_type.xml @@ -0,0 +1,129 @@ + + + + + + + + sd_bus_message_get_type + systemd + + + + sd_bus_message_get_type + 3 + + + + sd_bus_message_get_type + sd_bus_message_is_signal + sd_bus_message_is_method_call + sd_bus_message_is_method_error + + Query bus message addressing metadata + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_get_type + sd_bus_message *message + uint8_t *type + + + + int sd_bus_message_is_signal + sd_bus_message *message + const char *interface + const char *member + + + + int sd_bus_message_is_method_call + sd_bus_message *message + const char *interface + const char *member + + + + int sd_bus_message_is_method_error + sd_bus_message *message + const char *name + + + + + + + Description + + sd_bus_message_get_type() returns the type of a message in the output + parameter type, one of SD_BUS_MESSAGE_METHOD_CALL, + SD_BUS_MESSAGE_METHOD_RETURN, + SD_BUS_MESSAGE_METHOD_ERROR, SD_BUS_MESSAGE_SIGNAL. + This type is either specified as a parameter when the message is created using + sd_bus_set_message_new3, + or is set automatically when the message is created using + sd_bus_set_message_new_signal3, + sd_bus_set_message_new_method_call3, + sd_bus_set_message_new_method_error3 + and similar functions. + + + sd_bus_message_is_signal() checks if message m + is a signal message. If interface is non-null, it also checks if the + message has the same interface set. If member is non-null, it also checks + if the message has the same member set. Also see + sd_bus_set_message_new_signal3. It returns true when all checks pass. + + sd_bus_message_is_method_call() checks if message m + is a method call message. If interface is non-null, it also checks if the + message has the same interface set. If member is non-null, it also checks + if the message has the same member set. Also see + sd_bus_set_message_new_method_call3. It returns true when all checks pass. + + sd_bus_message_is_method_error() checks if message m + is an error reply message. If name is non-null, it also checks if the + message has the same error identifier set. Also see + sd_bus_set_message_new_method_error3. It returns true when all checks pass. + + + + Return Value + + On success, those functions return 0 or a positive + integer. On failure, it returns a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The message parameter or the output parameter are + NULL. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_new3, + sd_bus_message_set_destination3 + + + + diff --git a/man/sd_bus_message_new.xml b/man/sd_bus_message_new.xml new file mode 100644 index 00000000..efe650de --- /dev/null +++ b/man/sd_bus_message_new.xml @@ -0,0 +1,189 @@ + + + + + + + sd_bus_message_new + systemd + + + + sd_bus_message_new + 3 + + + + sd_bus_message_new + sd_bus_message_ref + sd_bus_message_unref + sd_bus_message_unrefp + SD_BUS_MESSAGE_METHOD_CALL + SD_BUS_MESSAGE_METHOD_RETURN + SD_BUS_MESSAGE_METHOD_ERROR + SD_BUS_MESSAGE_SIGNAL + sd_bus_message_get_bus + + Create a new bus message object and create or destroy references to it + + + + + #include <systemd/sd-bus.h> + + enum { + SD_BUS_MESSAGE_METHOD_CALL, + SD_BUS_MESSAGE_METHOD_RETURN, + SD_BUS_MESSAGE_METHOD_ERROR, + SD_BUS_MESSAGE_SIGNAL, +}; + + + int sd_bus_message_new + sd_bus *bus + sd_bus_message **m + uint8_t type + + + + sd_bus_message *sd_bus_message_ref + sd_bus_message *m + + + + sd_bus_message *sd_bus_message_unref + sd_bus_message *m + + + + void sd_bus_message_unrefp + sd_bus_message **mp + + + + sd_bus *sd_bus_message_get_bus + sd_bus_message *m + + + + + + Description + + sd_bus_message_new() creates a new bus message object attached to the + bus bus and returns it in the output parameter m. + This object is reference-counted, and will be destroyed when all references are gone. Initially, + the caller of this function owns the sole reference to the message object. Note that the message + object holds a reference to the bus object, so the bus object will not be destroyed as long as + the message exists. + + Note: this is a low-level call. In most cases functions like + sd_bus_message_new_method_call3, + sd_bus_message_new_method_error3, + sd_bus_message_new_method_return3, + and sd_bus_message_new_signal3 + that create a message of a certain type and initialize various fields are easier to use. + + The type parameter specifies the type of the message. It must be + one of SD_BUS_MESSAGE_METHOD_CALL — a method call, + SD_BUS_MESSAGE_METHOD_RETURN — a method call reply, + SD_BUS_MESSAGE_METHOD_ERROR — an error reply to a method call, + SD_BUS_MESSAGE_SIGNAL — a broadcast message with no reply. + + + The flag to allow interactive authorization is initialized based on the current value set + in the bus object, see + sd_bus_set_allow_interactive_authorization3. + This may be changed using + sd_bus_message_set_allow_interactive_authorization3. + + + sd_bus_message_ref() increases the reference counter of + m by one. + + sd_bus_message_unref() decreases the reference counter of + m by one. Once the reference count has dropped to zero, message object is + destroyed and cannot be used anymore, so further calls to + sd_bus_message_ref() or sd_bus_message_unref() are + illegal. + + sd_bus_message_unrefp() is similar to + sd_bus_message_unref() but takes a pointer to a + pointer to an sd_bus_message object. This call is useful in + conjunction with GCC's and LLVM's Clean-up + Variable Attribute. See + sd_bus_new3 + for an example how to use the cleanup attribute. + + sd_bus_message_ref() and sd_bus_message_unref() + execute no operation if the passed in bus object address is + NULL. sd_bus_message_unrefp() will first dereference + its argument, which must not be NULL, and will execute no operation if + that is NULL. + + + sd_bus_message_get_bus() returns the bus object that message + m is attached to. + + + + Return Value + + On success, sd_bus_message_new() returns 0 or a positive integer. On + failure, it returns a negative errno-style error code. + + sd_bus_message_ref() always returns the argument. + + + sd_bus_message_unref() always returns + NULL. + + sd_bus_message_get_bus() always returns the bus object. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + Specified type is invalid. + + + + -ENOTCONN + + The bus parameter bus is NULL or + the bus is not connected. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_new3, + sd_bus_message_new_method_call3, + sd_bus_message_new_method_error3, + sd_bus_message_new_method_return3, + sd_bus_message_new_signal3 + + + + diff --git a/man/sd_bus_message_new_method_call.xml b/man/sd_bus_message_new_method_call.xml new file mode 100644 index 00000000..0d181ed8 --- /dev/null +++ b/man/sd_bus_message_new_method_call.xml @@ -0,0 +1,166 @@ + + + + + + + + sd_bus_message_new_method_call + systemd + + + + sd_bus_message_new_method_call + 3 + + + + sd_bus_message_new_method_call + sd_bus_message_new_method_return + + Create a method call message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_new_method_call + sd_bus *bus + sd_bus_message **m + const char *destination + const char *path + const char *interface + const char *member + + + + int sd_bus_message_new_method_return + sd_bus_message *call + sd_bus_message **m + + + + + + Description + + The sd_bus_message_new_method_call() function creates a new bus + message object that encapsulates a D-Bus method call, and returns it in the + m output parameter. The call will be made on the destination + destination, path path, on the interface + interface, member member. + + Briefly, the destination is a dot-separated name that identifies a + service connected to the bus. The path is a slash-separated identifier of + an object within the destination that resembles a file system path. The meaning of this path is + defined by the destination. The interface is a dot-separated name that + resembles a Java interface name that identifies a group of methods and signals supported by the + object identified by path. Methods and signals are collectively called + members and are identified by a simple name composed of ASCII letters, + numbers, and underscores. See the D-Bus Tutorial for an + in-depth explanation. + + The destination parameter may be NULL. The + interface parameter may be NULL, if the destination + has only a single member with the given name and there is no ambiguity if the interface name is + omitted. + + The sd_bus_message_new_method_call() function creates a new bus + message object that is a reply to the method call call and returns it in + the m output parameter. The call parameter must be + a method call message. The sender of call is used as the destination. + + + + + Return Value + + This function returns 0 if the message object was successfully created, and a negative + errno-style error code otherwise. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The output parameter m is + NULL. + + The destination parameter is non-null and is not a valid D-Bus + service name (org.somewhere.Something), the path + parameter is not a valid D-Bus path (/an/object/path), the + interface parameter is non-null and is not a valid D-Bus interface + name (an.interface.name), or the member parameter + is not a valid D-Bus member (Name). + + The call parameter is not a method call object. + + + + + -ENOTCONN + + The bus parameter bus is NULL or + the bus is not connected. + + + + -ENOMEM + + Memory allocation failed. + + + + -EPERM + + + The call parameter is not sealed. + + + + + -EOPNOTSUPP + + + The call message does not have a cookie. + + + + + + + + + + Examples + + + Make a call to a D-Bus method that takes a single parameter + + + This defines a minimally useful program that will open a connection to the bus, create a + message object, send it, wait for the reply, and finally extract and print the answer. It does + error handling and proper memory management. + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_path_encode3 + + + + diff --git a/man/sd_bus_message_new_method_error.xml b/man/sd_bus_message_new_method_error.xml new file mode 100644 index 00000000..0c471c53 --- /dev/null +++ b/man/sd_bus_message_new_method_error.xml @@ -0,0 +1,187 @@ + + + + + + + + sd_bus_message_new_method_error + systemd + + + + sd_bus_message_new_method_error + 3 + + + + sd_bus_message_new_method_error + sd_bus_message_new_method_errorf + sd_bus_message_new_method_errno + sd_bus_message_new_method_errnof + + Create a an error reply for a method call + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_new_method_error + sd_bus_message *call + sd_bus_message **m + const sd_bus_error *e + + + + int sd_bus_message_new_method_errorf + sd_bus_message *call + sd_bus_message **m + const char *name + const char *format + … + + + + int sd_bus_message_new_method_errno + sd_bus_message *call + sd_bus_message **m + int error + const sd_bus_error *p + + + + int sd_bus_message_new_method_errnof + sd_bus_message *call + sd_bus_message **m + int error + const char *format + … + + + + + + Description + + The sd_bus_message_new_method_error() function creates + a new bus message object that is an error reply to the + call message, and returns it in the + m output parameter. The error information from error + e is appended: the name field of + e is used as the error identifier in the reply header (for + example an error name such as + org.freedesktop.DBus.Error.NotSupported or the equivalent + symbolic SD_BUS_ERROR_NOT_SUPPORTED), and the + message field is set as the human readable error message + string if present. The error e must have the + name field set, see + sd_bus_error_is_set3. + + + The sd_bus_message_new_method_errorf() function + creates an error reply similarly to + sd_bus_message_new_method_error(), but instead of a ready + error structure, it takes an error identifier string name, + plus a printf3 + format string format and corresponding arguments. An error + reply is sent with the error identifier name and the + formatted string as the message. name and + format must not be NULL. + + + The sd_bus_message_new_method_errno() function creates + an error reply similarly to + sd_bus_message_new_method_error(), but in addition to the + error structure p, it takes an + errno3 + error value in parameter error. If the error + p is set (see + sd_bus_error_is_set3), + it is used in the reply. Otherwise, error is translated to + an error identifier and used to create a new error structure using + sd_bus_error_set_errno3 + and that is used in the reply. (If error is zero, no error + is actually set, and an error reply with no information is created.) + + The sd_bus_message_new_method_errnof() function + creates an error reply similarly to + sd_bus_message_new_method_error(). It takes an + errno3 + error value in parameter error, plus a printf3 + format string format and corresponding arguments. + %m may be used in the format string to refer to the error + string corresponding to the specified errno code. The error message is initialized + using the error identifier generated from error and the + formatted string. (If error is zero, no error is actually + set, and an error reply with no information is created.) + + + + Return Value + + These functions return 0 if the error reply was successfully created, and a + negative errno-style error code otherwise. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The call message call or the output + parameter m are NULL. + + Message call is not a method call + message. + + The error error parameter to + sd_bus_message_new_method_error is not set, see + sd_bus_error_is_set3. + + + + + + -EPERM + + Message call has been sealed. + + + + + -ENOTCONN + + The bus to which message call is + attached is not connected. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-bus3 + + + + diff --git a/man/sd_bus_message_new_signal.xml b/man/sd_bus_message_new_signal.xml new file mode 100644 index 00000000..61619304 --- /dev/null +++ b/man/sd_bus_message_new_signal.xml @@ -0,0 +1,120 @@ + + + + + + + + sd_bus_message_new_signal + systemd + + + + sd_bus_message_new_signal + 3 + + + + sd_bus_message_new_signal + + Create a signal message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_new_signal + sd_bus *bus + sd_bus_message **m + const char *path + const char *interface + const char *member + + + + + + Description + + The sd_bus_message_new_signal() function creates a new bus message + object that encapsulates a D-Bus signal, and returns it in the m output + parameter. The signal will be sent to path path, on the interface + interface, member member. When this message is + sent, no reply is expected. See + sd_bus_message_new_call1 + for a short description of the meaning of the path, + interface, and member parameters. + + + + + Return Value + + This function returns 0 if the message object was successfully created, and a negative + errno-style error code otherwise. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The output parameter m is + NULL. + + The path parameter is not a valid D-Bus path + (/an/object/path), the interface parameter is not + a valid D-Bus interface name (an.interface.name), or the + member parameter is not a valid D-Bus member + (Name). + + + + -ENOTCONN + + The bus parameter bus is NULL or + the bus is not connected. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + Examples + + + Send a simple signal + + + + This function in systemd sources is used to emit the + UnitFilesChanged signal when the unit files have been changed. + + + + + + See Also + + + systemd1, + sd-bus3 + + + + diff --git a/man/sd_bus_message_read.xml b/man/sd_bus_message_read.xml new file mode 100644 index 00000000..526fb0e7 --- /dev/null +++ b/man/sd_bus_message_read.xml @@ -0,0 +1,227 @@ + + + + + + + + sd_bus_message_read + systemd + + + + sd_bus_message_read + 3 + + + + sd_bus_message_read + sd_bus_message_readv + + Read a sequence of values from a message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_read + sd_bus_message *m + char char *types + ... + + + + int sd_bus_message_readv + sd_bus_message *m + char char *types + va_list ap + + + + + + Description + + sd_bus_message_read() reads a sequence of fields from + the D-Bus message object m and advances the read position + in the message. The type string types describes the types + of items expected in the message and the field arguments that follow. The type + string may be NULL or empty, in which case nothing is + read. + + The type string is composed of the elements described in + sd_bus_message_append3, + i.e. basic and container types. It must contain zero or more single "complete + types". The type string is NUL-terminated. + + For each type specified in the type string, one or more arguments need to be specified + after the types parameter, in the same order. The arguments must be + pointers to appropriate types (a pointer to int8_t for a y in + the type string, a pointer to int32_t for an i, a pointer to + const char* for an s, ...) which are set based on the values in + the message. As an exception, in case or array and variant types, the first argument is an + "input" argument that further specifies how the message should be read. See the table below for + a complete list of allowed arguments and their types. Note that, if the basic type is a pointer + (e.g., const char * in the case of a string), the argument is a pointer to a + pointer, and also the pointer value that is written is only borrowed and the contents must be + copied if they are to be used after the end of the messages lifetime. + + Each argument may also be NULL, in which case the value is read and + ignored. + + + Item type specifiers + + + + + + + + + + Specifier + Constant + Description + Type of the first argument + Types of the subsequent arguments, if any + + + + + + + + a + SD_BUS_TYPE_ARRAY + array + int, which specifies the expected length n of the array + n sets of arguments appropriate for the array element type + + + + v + SD_BUS_TYPE_VARIANT + variant + signature string + arguments appropriate for the types specified by the signature + + + + ( + SD_BUS_TYPE_STRUCT_BEGIN + array start + arguments appropriate for the structure elements + + + ) + SD_BUS_TYPE_STRUCT_END + array end + + + + { + SD_BUS_TYPE_DICT_ENTRY_BEGIN + dictionary entry start + arguments appropriate for the first type in the pair + arguments appropriate for the second type in the pair + + + } + SD_BUS_TYPE_DICT_ENTRY_END + dictionary entry end + + + +
+ + If objects of the specified types are not present at the current position + in the message, an error is returned. + + + The sd_bus_message_readv() is equivalent to the + sd_bus_message_read(), except that it is called with a + va_list instead of a variable number of arguments. This + function does not call the va_end() macro. Because it + invokes the va_arg() macro, the value of + ap is undefined after the call. +
+ + + Return Value + + On success, sd_bus_message_read() and + sd_bus_message_readv() return 0 or a positive integer. On failure, they return a + negative errno-style error code. + + + + + + + + Examples + + Read a single basic type (a 64-bit integer): + + + sd_bus_message *m; +int64_t x; + +sd_bus_message_read(m, "x", &x); + + Read all types of integers: + + uint8_t y; +int16_t n; +uint16_t q; +int32_t i; +uint32_t u; +int32_t x; +uint32_t t; +double d; + +sd_bus_message_read(m, "ynqiuxtd", &y, &n, &q, &i, &u, &x, &t, &d); + + Read a structure composed of a string and a D-Bus path: + + const char *s, *p; + +sd_bus_message_read(m, "(so)", &s, &p); + + + Read a variant, with the real type "gt" (signature, unsigned integer): + + + const char *s; +uint64_t *v; + +sd_bus_message_read(m, "v", "gt", &s, &v); + + Read a dictionary containing three pairs of type {integer=>string}: + + + int i, j, k; +const char *s, *t, *u; + +sd_bus_message_read(m, "a{is}", 3, &i, &s, &j, &t, &k, &u); + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_read_basic3, + sd_bus_message_skip3, + sd_bus_message_append3 + + + +
diff --git a/man/sd_bus_message_read_array.xml b/man/sd_bus_message_read_array.xml new file mode 100644 index 00000000..117afa9e --- /dev/null +++ b/man/sd_bus_message_read_array.xml @@ -0,0 +1,108 @@ + + + + + + + + sd_bus_message_read_array + systemd + + + + sd_bus_message_read_array + 3 + + + + sd_bus_message_read_array + + Access an array of elements in a message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_read_array + sd_bus_message *m + char type + const void **ptr + size_t *size + + + + + + Description + + sd_bus_message_read_array() gives access to an element array in + message m. The "read pointer" in the message must be right before an + array of type type. As a special case, type may be + NUL, in which case any type is acceptable. A pointer to the array data is + returned in the parameter ptr and the size of array data (in bytes) is + returned in the parameter size. If size is 0, a + valid non-null pointer will be returned, but it may not be dereferenced. The data is aligned as + appropriate for the data type. The data is part of the message — it may not be modified and is + valid only as long as the message is referenced. After this function returns, the "read pointer" + points at the next element after the array. + + + + Return Value + + + On success, sd_bus_message_read_array() returns 0 or + a positive integer. On failure, it returns a negative errno-style error + code. + + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + Specified type is invalid or the message parameter or one of the output + parameters are NULL. + + + + -EOPNOTSUPP + + The byte order in the message is different than native byte + order. + + + + -EPERM + + The message is not sealed. + + + + -EBADMSG + + The message cannot be parsed. + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_read3 + + + + diff --git a/man/sd_bus_message_read_basic.xml b/man/sd_bus_message_read_basic.xml new file mode 100644 index 00000000..101f5d21 --- /dev/null +++ b/man/sd_bus_message_read_basic.xml @@ -0,0 +1,235 @@ + + + + + + + + + sd_bus_message_read_basic + systemd + + + + sd_bus_message_read_basic + 3 + + + + sd_bus_message_read_basic + + Read a basic type from a message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_read_basic + sd_bus_message *m + char type + void *p + + + + + + Description + + + sd_bus_message_read_basic() reads a basic type from a + message and advances the read position in the message. The set of basic + types and their ascii codes passed in type are + described in the D-Bus + Specification. + + + + If p is not NULL, it should contain + a pointer to an appropriate object. For example, if type + is 'y', the object passed in p + should have type uint8_t *. If type is + 's', the object passed in p should + have type const char **. Note that, if the basic type is a pointer + (e.g., const char * in the case of a string), the pointer is only + borrowed and the contents must be copied if they are to be used after the end + of the messages lifetime. Similarly, during the lifetime of such a pointer, the + message must not be modified. See the table below for a complete list of allowed + types. + + + + Item type specifiers + + + + + + + + + Specifier + Constant + Description + Expected C Type + + + + + y + SD_BUS_TYPE_BYTE + unsigned integer + uint8_t * + + + + b + SD_BUS_TYPE_BOOLEAN + boolean + int * + + + + n + SD_BUS_TYPE_INT16 + signed integer + int16_t * + + + + q + SD_BUS_TYPE_UINT16 + unsigned integer + uint16_t * + + + + i + SD_BUS_TYPE_INT32 + signed integer + int32_t * + + + + u + SD_BUS_TYPE_UINT32 + unsigned integer + uint32_t * + + + + x + SD_BUS_TYPE_INT64 + signed integer + int64_t * + + + + t + SD_BUS_TYPE_UINT64 + unsigned integer + uint64_t * + + + + d + SD_BUS_TYPE_DOUBLE + floating-point + double * + + + + s + SD_BUS_TYPE_STRING + Unicode string + const char ** + + + + o + SD_BUS_TYPE_OBJECT_PATH + object path + const char ** + + + + g + SD_BUS_TYPE_SIGNATURE + signature + const char ** + + + + h + SD_BUS_TYPE_UNIX_FD + UNIX file descriptor + int * + + + +
+ + + If there is no object of the specified type at the current position in the + message, an error is returned. + +
+ + + Return Value + + + On success, sd_bus_message_read_basic() returns 0 or + a positive integer. On failure, it returns a negative errno-style error + code. + + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + Specified type string is invalid or the message parameter is + NULL. + + + + -ENXIO + + The message does not contain the specified type at current position. + + + + + -EBADMSG + + The message cannot be parsed. + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_append_basic3, + sd_bus_message_skip3, + sd_bus_message_read3 + + + +
diff --git a/man/sd_bus_message_rewind.xml b/man/sd_bus_message_rewind.xml new file mode 100644 index 00000000..cbfa2511 --- /dev/null +++ b/man/sd_bus_message_rewind.xml @@ -0,0 +1,88 @@ + + + + + + + + sd_bus_message_rewind + systemd + + + + sd_bus_message_rewind + 3 + + + + sd_bus_message_rewind + + Return to beginning of message or current container + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_rewind + sd_bus_message *m + int complete + + + + + + Description + + sd_bus_message_rewind() moves the "read pointer" in the message + m to either the beginning of the message (if + complete is true) or to the beginning of the currently open container. If + no container is open, complete has no effect. + + + + Return Value + + + On success, this function returns 0 or a positive integer. The value is zero if the current + container or whole message in case no container is open is empty, and positive otherwise. On + failure, it returns a negative errno-style error code. + + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The m parameter is NULL. + + + + -EPERM + + The message m has not been sealed. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_read3 + + + + diff --git a/man/sd_bus_message_set_destination.xml b/man/sd_bus_message_set_destination.xml new file mode 100644 index 00000000..ca3e466d --- /dev/null +++ b/man/sd_bus_message_set_destination.xml @@ -0,0 +1,153 @@ + + + + + + sd_bus_message_set_destination + systemd + + + + sd_bus_message_set_destination + 3 + + + + sd_bus_message_set_destination + sd_bus_message_get_destination + sd_bus_message_get_path + sd_bus_message_get_interface + sd_bus_message_get_member + sd_bus_message_set_sender + sd_bus_message_get_sender + + Set and query bus message addressing information + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_set_destination + sd_bus_message *message + const char *destination + + + + const char* sd_bus_message_get_destination + sd_bus_message *message + + + + const char* sd_bus_message_get_path + sd_bus_message *message + + + + const char* sd_bus_message_get_interface + sd_bus_message *message + + + + const char* sd_bus_message_get_member + sd_bus_message *message + + + + int sd_bus_message_set_sender + sd_bus_message *message + const char *sender + + + + const char* sd_bus_message_get_sender + sd_bus_message *message + + + + + + Description + + sd_bus_message_set_destination() sets the destination service name + for the specified bus message object. The specified name must be a valid unique or well-known + service name. + + sd_bus_message_get_destination(), + sd_bus_message_get_path(), + sd_bus_message_get_interface(), and + sd_bus_message_get_member() return the destination, path, interface, and + member fields from message header. The return value will be + NULL is message is NULL or the + message is of a type that doesn't use those fields or the message doesn't have them set. See + sd_bus_message_new_method_call3 + and + sd_bus_message_set_destination3 + for more discussion of those values. + + + sd_bus_message_set_sender() sets the sender service name for the specified bus message + object. The specified name must be a valid unique or well-known service name. This function is useful only for + messages to send on direct connections as for connections to bus brokers the broker will fill in the destination + field anyway, and the sender field set by original sender is ignored. + + sd_bus_message_get_sender() returns the sender field from + message. + + When a string is returned, it is a pointer to internal storage, and may not be modified or + freed. It is only valid as long as the message remains referenced and + this field hasn't been changed by a different call. + + + + Return Value + + On success, these calls return 0 or a positive integer. On failure, these calls return a + negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The message parameter or the output parameter are + NULL. + + + + -EPERM + + For sd_bus_message_set_destination or + sd_bus_message_set_sender, the message is already + sealed. + + + + -EEXIST + + The message already has a destination or sender field set. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_new3, + sd_bus_set_sender3 + + + + diff --git a/man/sd_bus_message_set_expect_reply.xml b/man/sd_bus_message_set_expect_reply.xml new file mode 100644 index 00000000..6f22e820 --- /dev/null +++ b/man/sd_bus_message_set_expect_reply.xml @@ -0,0 +1,127 @@ + + + + + + + + sd_bus_message_set_expect_reply + systemd + + + + sd_bus_message_set_expect_reply + 3 + + + + sd_bus_message_set_expect_reply + sd_bus_message_get_expect_reply + sd_bus_message_set_auto_start + sd_bus_message_get_auto_start + + Set and query bus message metadata + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_set_expect_reply + sd_bus_message *message + int b + + + + int sd_bus_message_get_expect_reply + sd_bus_message *message + + + + int sd_bus_message_set_auto_start + sd_bus_message *message + int b + + + + int sd_bus_message_get_auto_start + sd_bus_message *message + + + + + + + Description + + sd_bus_message_set_expect_reply() sets or clears the + NO_REPLY_EXPECTED flag on the message m. This flag + matters only for method call messages and is used to specify that no method return or error + reply is expected. It is ignored for other types. Thus, for a method call message, calling + sd_bus_message_set_expect_reply(…, 0) sets the flag and + suppresses the reply. + + sd_bus_message_get_expect_reply() checks if the + NO_REPLY_EXPECTED flag is set on the message m. It + will return positive if it is not set, and zero if it is. + + sd_bus_message_set_auto_start() sets or clears the + NO_AUTO_START flag on the message m. When the flag + is set the bus must not launch an owner for the destination name in response to this message. + Calling + sd_bus_message_set_auto_start(…, 0) sets the flag. + + + sd_bus_message_get_auto_start() checks if the + NO_AUTO_START flag is set on the message m. It + will return positive if it is not set, and zero if it is. + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a + negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The message parameter is + NULL. + + + + -EPERM + + The message message is sealed + when trying to set a flag. + + The message message has wrong + type. + + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_set_description3 + + + + diff --git a/man/sd_bus_message_skip.xml b/man/sd_bus_message_skip.xml new file mode 100644 index 00000000..0e740ab2 --- /dev/null +++ b/man/sd_bus_message_skip.xml @@ -0,0 +1,108 @@ + + + + + + + sd_bus_message_skip + systemd + + + + sd_bus_message_skip + 3 + + + + sd_bus_message_skip + + Skip elements in a bus message + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_skip + sd_bus_message *m + const char* types + + + + + + Description + + sd_bus_message_skip() is somewhat similar to + sd_bus_message_read3, + but instead of reading the contents of the message, it only moves the "read pointer". Subsequent + read operations will read the elements that are after the elements that were skipped. + + The types argument has the same meaning as in + sd_bus_message_read(). It may also be NULL, to skip a + single element of any type. + + + + Return Value + + On success, sd_bus_message_skip() returns 0 or a positive integer. On + failure, it returns a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The m parameter is + NULL. + + + + -EBADMSG + + The message cannot be parsed. + + + + -EPERM + + The message is not sealed. + + + + -ENXIO + + The message end has been reached and the requested elements cannot be read. + + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_read3, + sd_bus_message_read_basic3 + + + + diff --git a/man/sd_bus_message_verify_type.xml b/man/sd_bus_message_verify_type.xml new file mode 100644 index 00000000..e03a2538 --- /dev/null +++ b/man/sd_bus_message_verify_type.xml @@ -0,0 +1,99 @@ + + + + + + + sd_bus_message_verify_type + systemd + + + + sd_bus_message_verify_type + 3 + + + + sd_bus_message_verify_type + + Check if the message has specified type at the current location + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_message_verify_type + sd_bus_message *m + char type + const char* contents + + + + + + Description + + sd_bus_message_verify_type() checks if the complete type at the + current location in the message m matches the specified + type and contents. If non-zero, parameter + type must be one of the types specified in + sd_bus_message_append1. + If non-null, parameter contents must be a valid sequence of complete + types. If both type and contents are specified + type must be a container type. + + If type is specified, the type in the message must match. If + contents is specified, the type in the message must be a container type + with this signature. + + + + Return Value + + On success, this call returns true if the type matches and zero if not (the message + m contains different data or the end of the message has been reached). On + failure, it returns a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -EINVAL + + m or both type and + contents are NULL. + + Arguments do not satisfy other constraints listed above. + + + + + -EPERM + + Message m is not sealed. + + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_append3 + + + + diff --git a/man/sd_bus_negotiate_fds.xml b/man/sd_bus_negotiate_fds.xml new file mode 100644 index 00000000..c12b65c9 --- /dev/null +++ b/man/sd_bus_negotiate_fds.xml @@ -0,0 +1,144 @@ + + + + + + + + sd_bus_negotiate_fds + systemd + + + + sd_bus_negotiate_fds + 3 + + + + sd_bus_negotiate_fds + sd_bus_negotiate_timestamp + sd_bus_negotiate_creds + + Control feature negotiation on bus connections + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_negotiate_fds + sd_bus *bus + int b + + + + int sd_bus_negotiate_timestamp + sd_bus *bus + int b + + + + int sd_bus_negotiate_creds + sd_bus *bus + int b + uint64_t mask + + + + + + Description + + sd_bus_negotiate_fds() controls whether + file descriptor passing shall be negotiated for the specified bus + connection. It takes a bus object and a boolean, which, when true, + enables file descriptor passing, and, when false, disables + it. Note that not all transports and servers support file + descriptor passing. In particular, networked transports generally + do not support file descriptor passing. To find out whether file + descriptor passing is available after negotiation, use + sd_bus_can_send3 + and pass SD_BUS_TYPE_UNIX_FD. Note that file + descriptor passing is always enabled for both sending and + receiving or for neither, but never only in one direction. By + default, file descriptor passing is negotiated for all + connections. + + sd_bus_negotiate_timestamp() controls whether implicit sender + timestamps shall be attached automatically to all incoming messages. Takes a bus object and a + boolean, which, when true, enables timestamping, and, when false, disables it. Use + sd_bus_message_get_monotonic_usec3, + sd_bus_message_get_realtime_usec3, + sd_bus_message_get_seqnum3 + to query the timestamps of incoming messages. If negotiation is disabled or not supported, these + calls will fail with -ENODATA. Note that currently no transports support + timestamping of messages. By default, message timestamping is not negotiated for + connections. + + sd_bus_negotiate_creds() controls whether and which implicit sender + credentials shall be attached automatically to all incoming messages. Takes a bus object and a + boolean indicating whether to enable or disable the credential parts encoded in the bit mask + value argument. Note that not all transports support attaching sender credentials to messages, + or do not support all types of sender credential parameters, or might suppress them under + certain circumstances for individual messages. Specifically, dbus1 only supports + SD_BUS_CREDS_UNIQUE_NAME. The sender credentials are suitable for + authorization decisions. By default, only SD_BUS_CREDS_WELL_KNOWN_NAMES and + SD_BUS_CREDS_UNIQUE_NAME are enabled. In fact, these two credential fields + are always sent along and cannot be turned off. + + The sd_bus_negotiate_fds() function may + be called only before the connection has been started with + sd_bus_start3. Both + sd_bus_negotiate_timestamp() and + sd_bus_negotiate_creds() may also be called + after a connection has been set up. Note that, when operating on a + connection that is shared between multiple components of the same + program (for example via + sd_bus_default3), + it is highly recommended to only enable additional per message + metadata fields, but never disable them again, in order not to + disable functionality needed by other components. + + + + Return Value + + On success, these functions return 0 or a + positive integer. On failure, they return a negative errno-style + error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EPERM + + The bus connection has already been started. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_start3, + sd_bus_message_can_send3, + sd_bus_message_get_monotonic_usec3, + sd_bus_message_get_realtime_usec3, + sd_bus_message_get_seqnum3, + sd_bus_message_get_creds3 + + + + diff --git a/man/sd_bus_new.xml b/man/sd_bus_new.xml new file mode 100644 index 00000000..7771a78d --- /dev/null +++ b/man/sd_bus_new.xml @@ -0,0 +1,201 @@ + + + + + + + + sd_bus_new + systemd + + + + sd_bus_new + 3 + + + + sd_bus_new + sd_bus_ref + sd_bus_unref + sd_bus_unrefp + sd_bus_close_unref + sd_bus_close_unrefp + sd_bus_flush_close_unref + sd_bus_flush_close_unrefp + + Create a new bus object and create or destroy references to it + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_new + sd_bus **bus + + + + sd_bus *sd_bus_ref + sd_bus *bus + + + + sd_bus *sd_bus_unref + sd_bus *bus + + + + sd_bus *sd_bus_close_unref + sd_bus *bus + + + + sd_bus *sd_bus_flush_close_unref + sd_bus *bus + + + + void sd_bus_unrefp + sd_bus **busp + + + + void sd_bus_close_unrefp + sd_bus **busp + + + + void sd_bus_flush_close_unrefp + sd_bus **busp + + + + + + Description + + sd_bus_new() creates a new bus + object. This object is reference-counted, and will be destroyed + when all references are gone. Initially, the caller of this + function owns the sole reference and the bus object will not be + connected to any bus. To connect it to a bus, make sure + to set an address with + sd_bus_set_address3 + or a related call, and then start the connection with + sd_bus_start3. + + In most cases, it is a better idea to invoke + sd_bus_default_user3, + sd_bus_default_system3 + or related calls instead of the more low-level + sd_bus_new() and + sd_bus_start(). The higher-level calls not + only allocate a bus object but also start the connection to a + well-known bus in a single function invocation. + + sd_bus_ref() increases the reference + counter of bus by one. + + sd_bus_unref() decreases the reference + counter of bus by one. Once the reference + count has dropped to zero, bus is destroyed + and cannot be used anymore, so further calls to + sd_bus_ref() or + sd_bus_unref() are illegal. + + sd_bus_unrefp() is similar to + sd_bus_unref() but takes a pointer to a + pointer to an sd_bus object. This call is useful in + conjunction with GCC's and LLVM's Clean-up + Variable Attribute. Note that this function is defined as + inline function. Use a declaration like the following, in order to + allocate a bus object that is freed automatically as the code + block is left: + + { + __attribute__((cleanup(sd_bus_unrefp))) sd_bus *bus = NULL; + int r; + … + r = sd_bus_default(&bus); + if (r < 0) + fprintf(stderr, "Failed to allocate bus: %s\n", strerror(-r)); + … +} + + sd_bus_ref() and sd_bus_unref() + execute no operation if the passed in bus object address is + NULL. sd_bus_unrefp() will first + dereference its argument, which must not be NULL, and will + execute no operation if that is NULL. + + + sd_bus_close_unref() is similar to sd_bus_unref(), but + first executes + sd_bus_close3, + ensuring that the connection is terminated before the reference to the connection is dropped and possibly + the object freed. + + sd_bus_flush_close_unref() is similar to sd_bus_unref(), + but first executes + sd_bus_flush3 as well + as sd_bus_close3, + ensuring that any pending messages are synchronously flushed out before the reference to the connection + is dropped and possibly the object freed. This call is particularly useful immediately before exiting + from a program as it ensures that any pending outgoing messages are written out, and unprocessed but + queued incoming messages released before the connection is terminated and released. + + sd_bus_close_unrefp() is similar to + sd_bus_close_unref(), but may be used in GCC's and LLVM's Clean-up Variable + Attribute, see above. Similarly, sd_bus_flush_close_unrefp() is similar to + sd_bus_flush_close_unref(). + + + + Return Value + + On success, sd_bus_new() returns 0 or a + positive integer. On failure, it returns a negative errno-style + error code. + + sd_bus_ref() always returns the argument. + + + sd_bus_unref() and sd_bus_flush_close_unref() always return + NULL. + + + Errors + + Returned errors may indicate the following problems: + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_default_user3, + sd_bus_default_system3, + sd_bus_open_user3, + sd_bus_open_system3, + sd_bus_close3 + + + + diff --git a/man/sd_bus_path_encode.xml b/man/sd_bus_path_encode.xml new file mode 100644 index 00000000..ade11bc1 --- /dev/null +++ b/man/sd_bus_path_encode.xml @@ -0,0 +1,153 @@ + + + + + + + + sd_bus_path_encode + systemd + + + + sd_bus_path_encode + 3 + + + + sd_bus_path_encode + sd_bus_path_encode_many + sd_bus_path_decode + sd_bus_path_decode_many + + Convert an external identifier into an object path and back + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_path_encode + const char *prefix + const char *external_id + char **ret_path + + + + int sd_bus_path_encode_many + char **out + const char *path_template + … + + + + int sd_bus_path_decode + const char *path + const char *prefix + char **ret_external_id + + + + int sd_bus_path_decode_many + const char *path + const char *path_template + … + + + + + + Description + + sd_bus_path_encode() and + sd_bus_path_decode() convert external + identifier strings into object paths and back. These functions are + useful to map application-specific string identifiers of any kind + into bus object paths in a simple, reversible and safe way. + + sd_bus_path_encode() takes a bus path + prefix and an external identifier string as arguments, plus a + place to store the returned bus path string. The bus path prefix + must be a valid bus path, starting with a slash + /, and not ending in one. The external + identifier string may be in any format, may be the empty string, + and has no restrictions on the charset — however, it must + always be NUL-terminated. The returned string + will be the concatenation of the bus path prefix plus an escaped + version of the external identifier string. This operation may be + reversed with sd_bus_path_decode(). It is + recommended to only use external identifiers that generally + require little escaping to be turned into valid bus path + identifiers (for example, by sticking to a 7-bit ASCII character + set), in order to ensure the resulting bus path is still short and + easily processed. + + sd_bus_path_decode() reverses the + operation of sd_bus_path_encode() and thus + regenerates an external identifier string from a bus path. It + takes a bus path and a prefix string, plus a place to store the + returned external identifier string. If the bus path does not + start with the specified prefix, 0 is returned and the returned + string is set to NULL. Otherwise, the + string following the prefix is unescaped and returned in the + external identifier string. + + The escaping used will replace all characters which are + invalid in a bus object path by _, followed by a + hexadecimal value. As a special case, the empty string will be + replaced by a lone _. + + sd_bus_path_encode_many() works like + its counterpart sd_bus_path_encode(), but + takes a path template as argument and encodes multiple labels + according to its embedded directives. For each + % character found in the template, the caller + must provide a string via varargs, which will be encoded and + embedded at the position of the % character. + Any other character in the template is copied verbatim into the + encoded path. + + sd_bus_path_decode_many() does the + reverse of sd_bus_path_encode_many(). It + decodes the passed object path according to the given + path template. For each % character in the + template, the caller must provide an output storage + (char **) via varargs. The decoded label + will be stored there. Each % character will + only match the current label. It will never match across labels. + Furthermore, only a single directive is allowed per label. + If NULL is passed as output storage, the + label is verified but not returned to the caller. + + + + Return Value + + On success, sd_bus_path_encode() + returns positive or 0, and a valid bus path in the return + argument. On success, sd_bus_path_decode() + returns a positive value if the prefixed matched, or 0 if it + did not. If the prefix matched, the external identifier is returned + in the return parameter. If it did not match, NULL is returned in + the return parameter. On failure, a negative errno-style error + number is returned by either function. The returned strings must + be + free3'd + by the caller. + + + + + + See Also + + + systemd1, + sd-bus3, + free3 + + + + diff --git a/man/sd_bus_process.xml b/man/sd_bus_process.xml new file mode 100644 index 00000000..8f35388d --- /dev/null +++ b/man/sd_bus_process.xml @@ -0,0 +1,133 @@ + + + + + + + + + sd_bus_process + systemd + + + + sd_bus_process + 3 + + + + sd_bus_process + + Drive the connection + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_process + sd_bus *bus + sd_bus_message **ret + + + + + + Description + + sd_bus_process() drives the connection between the client and the message bus. That is, + it handles connecting, authentication, and message processing. When invoked pending I/O work is executed, and + queued incoming messages are dispatched to registered callbacks. Each time it is invoked a single operation is + executed. It returns zero when no operations were pending and positive if a message was processed. When zero is + returned the caller should synchronously poll for I/O events before calling into + sd_bus_process() again. For that either user the simple, synchronous + sd_bus_wait3 call, or hook up + the bus connection object to an external or manual event loop using + sd_bus_get_fd3. + + + sd_bus_process() processes at most one incoming message per call. If the parameter + ret is not NULL and the call processed a message, + *ret is set to this message. The caller owns a reference to this message and should call + sd_bus_message_unref3 when the + message is no longer needed. If ret is not NULL, progress was made, but no message was + processed, *ret is set to NULL. + + If a the bus object is connected to an + sd-event3 event loop (with + sd_bus_attach_event3), it is not + necessary to call sd_bus_process() directly as it is invoked automatically when + necessary. + + + + Return Value + + If progress was made, a positive integer is returned. If no progress was made, 0 is returned. If an + error occurs, a negative errno-style error code is returned. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + An invalid bus object was passed. + + + + -ECHILD + + The bus connection was allocated in a parent process and is being reused in a child + process after fork(). + + + + -ENOTCONN + + The bus connection has been terminated already. + + + + -ECONNRESET + + The bus connection has been terminated just now. + + + + -EBUSY + + This function is already being called, i.e. sd_bus_process() + has been called from a callback function that itself was called by + sd_bus_process(). + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_wait3, + sd_bus_get_fd3, + sd_bus_message_unref3, + sd-event3, + sd_bus_attach_event3 + + + + diff --git a/man/sd_bus_reply_method_error.xml b/man/sd_bus_reply_method_error.xml new file mode 100644 index 00000000..5a6cef6b --- /dev/null +++ b/man/sd_bus_reply_method_error.xml @@ -0,0 +1,158 @@ + + + + + + + + sd_bus_reply_method_error + systemd + + + + sd_bus_reply_method_error + 3 + + + + sd_bus_reply_method_error + sd_bus_reply_method_errorf + sd_bus_reply_method_errno + sd_bus_reply_method_errnof + + Reply with an error to a method call + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_reply_method_error + sd_bus_message *call + const sd_bus_error *e + + + + int sd_bus_reply_method_errorf + sd_bus_message *call + const char *name + const char *format + … + + + + int sd_bus_reply_method_errno + sd_bus_message *call + int error + const sd_bus_error *p + + + + int sd_bus_reply_method_errnof + sd_bus_message *call + int error + const char *format + … + + + + + + Description + + The sd_bus_reply_method_error() function sends an + error reply to the call message. The error structure + e specifies the error to send, and is used as described in + sd_bus_message_new_error3. + If no reply is expected to call, this function returns + success without sending reply. + + The sd_bus_reply_method_errorf() is to + sd_bus_reply_method_error() what + sd_bus_message_new_method_errorf() is to + sd_bus_message_new_method_error(). + + The sd_bus_reply_method_errno() is to + sd_bus_reply_method_error() what + sd_bus_message_new_method_errno() is to + sd_bus_message_new_method_error(). + + The sd_bus_reply_method_errnof() is to + sd_bus_reply_method_error() what + sd_bus_message_new_method_errnof() is to + sd_bus_message_new_method_error(). + + + + Return Value + + These functions return 0 if the error reply was successfully sent or if + none was expected, and a negative errno-style error code otherwise. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The call message call is + NULL. + + Message call is not a method call message. + + + Message call is not attached to a bus. + + The error error parameter to + sd_bus_reply_method_error is not set, see + sd_bus_error_is_set3. + + + + + + -EPERM + + Message call has been sealed. + + + + + -ENOTCONN + + The bus to which message call is attached is not + connected. + + + + -ENOMEM + + Memory allocation failed. + + + + In addition, any error message returned by + sd_bus_send1 + may be returned. + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_new_method_error3 + + + + diff --git a/man/sd_bus_request_name.xml b/man/sd_bus_request_name.xml new file mode 100644 index 00000000..7229ef51 --- /dev/null +++ b/man/sd_bus_request_name.xml @@ -0,0 +1,208 @@ + + + + + + + + sd_bus_request_name + systemd + + + + sd_bus_request_name + 3 + + + + sd_bus_request_name + sd_bus_request_name_async + sd_bus_release_name + sd_bus_release_name_async + Request or release a well-known service name on a bus + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_request_name + sd_bus *bus + const char *name + uint64_t flags + + + + int sd_bus_request_name_async + sd_bus *bus + sd_bus_slot **slot + const char *name + uint64_t flags + sd_bus_message_handler_t callback + void *userdata + + + + int sd_bus_release_name + sd_bus *bus + const char *name + + + + int sd_bus_release_name_async + sd_bus *bus + sd_bus_slot **slot + const char *name + sd_bus_message_handler_t callback + void *userdata + + + + + + Description + + sd_bus_request_name() requests a well-known service name on a bus. It takes a + bus connection, a valid bus name, and a flags parameter. The flags parameter is a combination of zero or + more of the following flags: + + + + SD_BUS_NAME_ALLOW_REPLACEMENT + + After acquiring the name successfully, permit other peers to take over the name when they try + to acquire it with the SD_BUS_NAME_REPLACE_EXISTING flag set. If + SD_BUS_NAME_ALLOW_REPLACEMENT is not set on the original request, such a request by other + peers will be denied. + + + + SD_BUS_NAME_REPLACE_EXISTING + + Take over the name if it was already acquired by another peer, and that other peer + has permitted takeover by setting SD_BUS_NAME_ALLOW_REPLACEMENT while acquiring + it. + + + + SD_BUS_NAME_QUEUE + + Queue the acquisition of the name when the name is already taken. + + + + sd_bus_request_name() operates in a synchronous fashion: a message requesting the name + is sent to the bus broker, and the call waits until the broker responds. + + sd_bus_request_name_async() is an asynchronous version of + sd_bus_release_name(). Instead of waiting for the request to complete, the request message is + enqueued. The specified callback will be called when the broker's response is received. If + the parameter is specified as NULL a default implementation is used instead which will + terminate the connection when the name cannot be acquired. The function returns a slot object in its + slot parameter — if it is passed as non-NULL — which may be used as a + reference to the name request operation. Use + sd_bus_slot_unref3 to destroy + this reference. Note that destroying the reference will not unregister the name, but simply ensure the specified + callback is no longer called. + + sd_bus_release_name() releases an acquired well-known name. It takes a bus connection + and a valid bus name as parameters. This function operates synchronously, sending a release request message to the + bus broker and waiting for it to reply. + + sd_bus_release_name_async() is an asynchronous version of + sd_bus_release_name(). The specified callback function is called when + the name has been released successfully. If specified as NULL a generic implementation is used + that ignores the result of the operation. As above, the slot (if + non-NULL) is set to an object that may be used to reference the operation. + + These functions are supported only on bus connections, i.e. connections to a bus broker and not on direct + connections. + + + + Return Value + + On success, these calls return 0 or a positive integer. On failure, these calls return a negative errno-style + error code. + + If SD_BUS_NAME_QUEUE is specified, sd_bus_request_name() will return + 0 when the name is already taken by another peer and the client has been added to the queue for the name. In that + case, the caller can subscribe to NameOwnerChanged signals to be notified when the name is + successfully acquired. sd_bus_request_name() returns > 0 when the name has immediately + been acquired successfully. + + + Errors + + Returned errors may indicate the following problems: + + + + -EALREADY + + The caller already is the owner of the specified name. + + + + -EEXIST + + The name has already been acquired by a different peer, and SD_BUS_NAME_REPLACE_EXISTING was + not specified or the other peer did not specify SD_BUS_NAME_ALLOW_REPLACEMENT while acquiring the + name. + + + + -ESRCH + + It was attempted to release a name that is currently not registered on the + bus. + + + + -EADDRINUSE + + It was attempted to release a name that is owned by a different peer on the + bus. + + + + -EINVAL + + A specified parameter is invalid. This is also generated when the requested name is + a special service name reserved by the D-Bus specification, or when the operation is requested on a + connection that does not refer to a bus. + + + + -ENOTCONN + + The bus connection has been disconnected. + + + + -ECHILD + + The bus connection has been created in a different process than the current + one. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_new3, + sd_bus_slot_unref3 + + + + diff --git a/man/sd_bus_set_close_on_exit.xml b/man/sd_bus_set_close_on_exit.xml new file mode 100644 index 00000000..751fc0a7 --- /dev/null +++ b/man/sd_bus_set_close_on_exit.xml @@ -0,0 +1,102 @@ + + + + + + + + sd_bus_set_close_on_exit + systemd + + + + sd_bus_set_close_on_exit + 3 + + + + sd_bus_set_close_on_exit + sd_bus_get_close_on_exit + + Control whether to close the bus connection during the event loop exit phase + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_set_close_on_exit + sd_bus *bus + int b + + + + int sd_bus_get_close_on_exit + sd_bus *bus + + + + + + + Description + + sd_bus_set_close_on_exit() may be used to enable or disable whether the bus connection + is automatically flushed (as in + sd_bus_flush3) and closed (as in + sd_bus_close3) during the exit + phase of the event loop. This logic only applies to bus connections that are attached to an + sd-event3 event loop, see + sd_bus_attach_event3. By default + this mechanism is enabled and makes sure that any pending messages that have not been written to the bus connection + are written out when the event loop is shutting down. In some cases this behaviour is not desirable, for example + when the bus connection shall remain usable until after the event loop exited. If b is + true, the feature is enabled (which is the default), otherwise disabled. + + sd_bus_get_close_on_exit() may be used to query the current setting of this feature. It + returns zero when the feature is disabled, and positive if enabled. + + + + Return Value + + On success, sd_bus_set_close_on_exit() returns 0 or a positive integer. On failure, it returns a negative errno-style + error code. + + sd_bus_get_close_on_exit() returns 0 if the feature is currently turned off or a + positive integer if it is on. On failure, it returns a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ECHILD + + The bus connection has been created in a different process. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_flush3, + sd_bus_attach_event3, + sd-event3, + sd_event_add_exit3 + + + + diff --git a/man/sd_bus_set_connected_signal.xml b/man/sd_bus_set_connected_signal.xml new file mode 100644 index 00000000..edb0df20 --- /dev/null +++ b/man/sd_bus_set_connected_signal.xml @@ -0,0 +1,109 @@ + + + + + + + + sd_bus_set_connected_signal + systemd + + + + sd_bus_set_connected_signal + 3 + + + + sd_bus_set_connected_signal + sd_bus_get_connected_signal + + Control emmission of local connection establishment signal on bus connections + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_set_connected_signal + sd_bus *bus + int b + + + + int sd_bus_get_connected_signal + sd_bus *bus + + + + + + + Description + + sd_bus_set_connected_signal() may be used to control whether a local, synthetic + Connected() signal message shall be generated and enqueued for dispatching when the connection + is fully established. If the b parameter is zero the message is not generated (the default), + otherwise it is generated. + + sd_bus_get_connected_signal() may be used to query whether this feature is enabled. It + returns zero if not, positive otherwise. + + The Connected() signal message is generated from the + org.freedesktop.DBus.Local service and interface, and + /org/freedesktop/DBus/Local object path. Use + sd_bus_match_signal_async3 to + match on this signal. + + This message is particularly useful on slow transports where connections take a long time to be + established. This is especially the case when + sd_bus_set_watch_bind3 is + used. The signal is generated when the + sd_bus_is_ready3 returns + positive for the first time. + + The Connected() signal corresponds with the Disconnected() signal + that is synthesized locally when the connection is terminated. The latter is generated unconditionally however, + unlike the former which needs to be enabled explicitly before it is generated, with + sd_bus_set_connected_signal(). + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a negative + errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ECHILD + + The bus connection has been created in a different process. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_match_signal_async3, + sd_bus_set_watch_bind3, + sd_bus_is_ready3 + + + + diff --git a/man/sd_bus_set_description.xml b/man/sd_bus_set_description.xml new file mode 100644 index 00000000..3c5580e2 --- /dev/null +++ b/man/sd_bus_set_description.xml @@ -0,0 +1,177 @@ + + + + + + + + sd_bus_set_description + systemd + + + + sd_bus_set_description + 3 + + + + sd_bus_set_description + sd_bus_get_description + sd_bus_set_anonymous + sd_bus_set_trusted + sd_bus_set_allow_interactive_authorization + sd_bus_get_allow_interactive_authorization + + Set or query properties of a bus object + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_set_description + sd_bus *bus + const char *description + + + + int sd_bus_get_description + sd_bus *bus + const char **description + + + + int sd_bus_set_anonymous + sd_bus *bus + int b + + + + int sd_bus_set_trusted + sd_bus *bus + int b + + + + int sd_bus_set_allow_interactive_authorization + sd_bus *bus + int b + + + + int sd_bus_get_allow_interactive_authorization + sd_bus *bus + + + + + + Description + + sd_bus_set_description() sets the description string + that is used in logging to the specified string. The string is copied internally + and freed when the bus object is deallocated. The + description argument may be NULL, in + which case the description is unset. This function must be called before the bus + has been started. + + sd_bus_get_description() returns a description string + in description. This string may have been previously set + with sd_bus_set_description() or + sd_bus_open_with_description3 + or similar. If not set this way, a default string like system + or user will be returned for the system or user buses, + and NULL otherwise. + + sd_bus_set_anonymous() enables or disables "anonymous + authentication", i.e. lack of authentication, of the bus peer. This function must + be called before the bus has been started. See the Authentication + Mechanisms section of the D-Bus specification for details. + + sd_bus_set_trusted() sets the "trusted" state on the + bus object. If true, all connections on the bus are + trusted and access to all privileged and unprivileged methods is granted. This + function must be called before the bus has been started. + + sd_bus_set_allow_interactive_authorization() + enables or disables interactive authorization for method calls. If true, + messages are marked with the + ALLOW_INTERACTIVE_AUTHORIZATION flag specified by the + D-Bus + specification, informing the receiving side that the caller is prepared to + wait for interactive authorization, which might take a considerable time to + complete. If this flag is set, the user may be queried for passwords or + confirmation via polkit or a + similar framework. + + sd_bus_get_allow_interactive_authorization() returns + true if interactive authorization is allowed and false if not. + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a negative + errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + An argument is invalid. + + + + -ENOPKG + + The bus cannot be resolved. + + + + -EPERM + + The bus has already been started. + + + + -ECHILD + + The bus was created in a different process. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_default_user3, + sd_bus_default_system3, + sd_bus_open_user3, + sd_bus_open_system3 + + + + diff --git a/man/sd_bus_set_sender.xml b/man/sd_bus_set_sender.xml new file mode 100644 index 00000000..b3f67d9f --- /dev/null +++ b/man/sd_bus_set_sender.xml @@ -0,0 +1,103 @@ + + + + + + + + sd_bus_set_sender + systemd + + + + sd_bus_set_sender + 3 + + + + sd_bus_set_sender + sd_bus_get_sender + + Configure default sender for outgoing messages + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_set_sender + sd_bus *bus + const char* name + + + + int sd_bus_get_sender + sd_bus *bus + const char** name + + + + + + + Description + + sd_bus_set_sender() configures the default sender service name to use for outgoing + messages. The service name specified in the name parameter is set on all outgoing messages + that are sent on the connection and have no sender set yet, for example through + sd_bus_message_set_sender3. Note + that this function is only supported on direct connections, i.e. not on connections to a bus broker as the broker + will fill in the sender service name automatically anyway. By default no sender name is configured, and hence + messages are sent without sender field set. If the name parameter is specified as + NULL the default sender service name is cleared, returning to the default state if a default + sender service name was set before. If passed as non-NULL the specified name must be a valid + unique or well-known service name. + + sd_bus_get_sender() may be used to query the current default service name for outgoing + messages. + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a negative + errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ECHILD + + The bus connection has been created in a different process. + + + + -EPERM + + The specified bus connection object is a not a direct but a brokered + connection. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_message_set_sender3 + + + + diff --git a/man/sd_bus_set_watch_bind.xml b/man/sd_bus_set_watch_bind.xml new file mode 100644 index 00000000..cbdc7dd1 --- /dev/null +++ b/man/sd_bus_set_watch_bind.xml @@ -0,0 +1,118 @@ + + + + + + + + sd_bus_set_watch_bind + systemd + + + + sd_bus_set_watch_bind + 3 + + + + sd_bus_set_watch_bind + sd_bus_get_watch_bind + + Control socket binding watching on bus connections + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_set_watch_bind + sd_bus *bus + int b + + + + int sd_bus_get_watch_bind + sd_bus *bus + + + + + + + Description + + sd_bus_set_watch_bind() may be used to enable or disable client-side watching of server + socket binding for a bus connection object. If the b is true, the feature is enabled, + otherwise disabled (which is the default). When enabled, and the selected bus address refers to an + AF_UNIX socket in the file system which does not exist while the connection attempt is made an + inotify7 watch is installed on + it, waiting for the socket to appear. As soon as the socket appears the connection is made. This functionality is + useful in particular in early-boot programs that need to run before the system bus is available, but want to + connect to it the instant it may be connected to. + + sd_bus_get_watch_bind() may be used to query the current setting of this feature. It + returns zero when the feature is disabled, and positive if enabled. + + Note that no timeout is applied while it is waited for the socket to appear. This means that any synchronous + remote operation (such as + sd_bus_call3, + sd_bus_add_match3 or + sd_bus_request_name3), that is + used on a connection with this feature enabled that is not established yet might block unbounded if the socket is + never created. However, asynchronous remote operations (such as + sd_bus_send3, + sd_bus_add_match_async3 or + sd_bus_request_match_async3) do + not block in this case, and safely enqueue the requested operations to be dispatched the instant the connection is + set up. + + Use sd_bus_is_ready3 to + determine whether the connection is fully established, i.e. whether the peer socket has been bound, connected to + and authenticated. Use + sd_bus_set_connected_signal3 to + be notified when the connection is fully established. + + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a negative + errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ECHILD + + The bus connection has been created in a different process. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + inotify7, + sd_bus_call3, + sd_bus_add_match3, + sd_bus_request_name3, + sd_bus_is_ready3, + sd_bus_set_connected_signal3 + + + + diff --git a/man/sd_bus_slot_ref.xml b/man/sd_bus_slot_ref.xml new file mode 100644 index 00000000..c73f3c9e --- /dev/null +++ b/man/sd_bus_slot_ref.xml @@ -0,0 +1,107 @@ + + + + + + + sd_bus_slot_ref + systemd + + + + sd_bus_slot_ref + 3 + + + + sd_bus_slot_ref + sd_bus_slot_unref + sd_bus_slot_unrefp + sd_bus_slot_get_bus + + Create and destroy references to a bus slot object + + + + + #include <systemd/sd-bus.h> + + + sd_bus_slot *sd_bus_slot_ref + sd_bus_slot *slot + + + + sd_bus_slot *sd_bus_slot_unref + sd_bus_slot *slot + + + + void sd_bus_slot_unrefp + sd_bus_slot **slotp + + + + sd_bus *sd_bus_slot_get_bus + sd_bus_slot *m + + + + + + Description + + sd_bus_slot_ref() increases the reference counter of + slot by one. + + sd_bus_slot_unref() decreases the reference counter of + slot by one. Once the reference count has dropped to zero, slot object is + destroyed and cannot be used anymore, so further calls to sd_bus_slot_ref() + or sd_bus_slot_unref() are illegal. + + sd_bus_slot_unrefp() is similar to + sd_bus_slot_unref() but takes a pointer to a pointer to an + sd_bus_slot object. This call is useful in conjunction with GCC's and LLVM's Clean-up Variable + Attribute. See + sd_bus_new3 + for an example how to use the cleanup attribute. + + sd_bus_slot_ref() and sd_bus_slot_unref() + execute no operation if the passed in bus object address is + NULL. sd_bus_slot_unrefp() will first dereference + its argument, which must not be NULL, and will execute no operation if + that is NULL. + + + sd_bus_slot_get_bus() returns the bus object that message + slot is attached to. + + + + Return Value + + sd_bus_slot_ref() always returns the argument. + + sd_bus_slot_unref() always returns NULL. + + sd_bus_slot_get_bus() always returns the bus object. + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_new3, + sd_bus_message_new3, + sd_bus_slot_new_signal3, + sd_bus_call_method_async3 + + + + diff --git a/man/sd_bus_slot_set_description.xml b/man/sd_bus_slot_set_description.xml new file mode 100644 index 00000000..9bc2ba85 --- /dev/null +++ b/man/sd_bus_slot_set_description.xml @@ -0,0 +1,105 @@ + + + + + + + sd_bus_slot_set_description + systemd + + + + sd_bus_slot_set_description + 3 + + + + sd_bus_slot_set_description + sd_bus_slot_get_description + + Set or query the description of bus slot objects + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_slot_set_description + sd_bus_slot* slot + const char *description + + + + int sd_bus_slot_get_description + sd_bus_slot* bus + const char **description + + + + + + Description + + sd_bus_slot_set_description() sets the description string + that is used in logging to the specified string. The string is copied internally + and freed when the bus slot object is deallocated. The + description argument may be NULL, in + which case the description is unset. + + sd_bus_slot_get_description() returns a description string in + description. If the string is not set, e.g. with + sd_bus_slot_set_description(), and the slot is a bus match callback slot, + the match string will be returned. Otherwise, -ENXIO is returned. + + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, + they return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + An required argument is NULL. + + + + -ENXIO + + The bus slot object has no description. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + + See Also + + + systemd1, + sd-bus3 + sd_bus_slot_ref3, + sd_bus_slot_set_userdata3 + + + + diff --git a/man/sd_bus_slot_set_destroy_callback.xml b/man/sd_bus_slot_set_destroy_callback.xml new file mode 100644 index 00000000..c6fe72e3 --- /dev/null +++ b/man/sd_bus_slot_set_destroy_callback.xml @@ -0,0 +1,130 @@ + + + + + + + + sd_bus_slot_set_destroy_callback + systemd + + + + sd_bus_slot_set_destroy_callback + 3 + + + + sd_bus_slot_set_destroy_callback + sd_bus_slot_get_destroy_callback + sd_bus_track_set_destroy_callback + sd_bus_track_get_destroy_callback + sd_bus_destroy_t + + Define the callback function for resource cleanup. + + + + + #include <systemd/sd-bus.h> + + + typedef int (*sd_bus_destroy_t) + void *userdata + + + + int sd_bus_slot_set_destroy_callback + sd_bus_slot *slot + sd_bus_destroy_t callback + + + + int sd_bus_slot_get_destroy_callback + sd_bus_slot *slot + sd_bus_destroy_t *callback + + + + int sd_bus_track_set_destroy_callback + sd_bus_track *track + sd_bus_destroy_t callback + + + + int sd_bus_track_get_destroy_callback + sd_bus_track *track + sd_bus_destroy_t *callback + + + + + + Description + + sd_bus_slot_set_destroy_callback() sets callback as the callback + function to be called right before the bus slot object slot is deallocated. The + userdata pointer from the slot object will be passed as the userdata + parameter. This pointer can be set by an argument to the constructor functions, see + sd_bus_add_match3, or directly, + see sd_bus_slot_set_userdata3. + This callback function is called even if userdata is NULL. Note that + this callback is invoked at a time where the bus slot object itself is already invalidated, and executing + operations or taking new references to the bus slot object is not permissible. + + sd_bus_slot_get_destroy_callback() returns the current callback + for slot in the callback parameter. + + sd_bus_track_set_destroy_callback() and + sd_bus_track_get_destroy_callback() provide equivalent functionality for the + userdata pointer associated with bus peer tracking objects. For details about bus peer + tracking objects, see + sd_bus_track_new3. + + + + Return Value + + On success, sd_bus_slot_set_destroy_callback() and + sd_bus_track_set_destroy_callback() return 0 or a positive integer. On failure, they + return a negative errno-style error code. + + sd_bus_slot_get_destroy_callback() and + sd_bus_track_get_destroy_callback() return positive if the destroy callback function + is set, 0 if not. On failure, they return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The slot or track parameter is + NULL. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_slot_set_floating3, + sd_bus_add_match3, + sd_bus_track_new3, + sd_bus_slot_set_userdata3, + sd_bus_track_set_userdata3 + + + + diff --git a/man/sd_bus_slot_set_floating.xml b/man/sd_bus_slot_set_floating.xml new file mode 100644 index 00000000..f63907aa --- /dev/null +++ b/man/sd_bus_slot_set_floating.xml @@ -0,0 +1,117 @@ + + + + + + + + sd_bus_slot_set_floating + systemd + + + + sd_bus_slot_set_floating + 3 + + + + sd_bus_slot_set_floating + sd_bus_slot_get_floating + + Control whether a bus slot object is "floating". + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_slot_set_floating + sd_bus_slot *slot + int b + + + + int sd_bus_slot_get_floating + sd_bus_slot *slot + + + + + + + Description + + sd_bus_slot_set_floating() controls whether the specified bus slot object + slot shall be "floating" or not. A floating bus slot object's lifetime is bound to the + lifetime of the bus object it is associated with, meaning that it remains allocated as long as the bus object + itself and is freed automatically when the bus object is freed. Regular (i.e. non-floating) bus slot objects keep + the bus referenced, hence the bus object remains allocated at least as long as there remains at least one + referenced bus slot object around. The floating state hence controls the direction of referencing between the bus + object and the bus slot objects: if floating the bus pins the bus slot, and otherwise the bus slot pins the bus + objects. Use sd_bus_slot_set_floating() to switch between both modes: if the + b parameter is zero, the slot object is considered floating, otherwise it is made a regular + (non-floating) slot object. + + Bus slot objects may be allocated with calls such as + sd_bus_add_match3. If the + slot of these functions is non-NULL the slot object will be of the + regular kind (i.e. non-floating), otherwise it will be created floating. With + sd_bus_slot_set_floating() a bus slot object allocated as regular can be converted into a + floating object and back. This is particularly useful for creating a bus slot object, then changing parameters of + it, and then turning it into a floating object, whose lifecycle is managed by the bus object. + + sd_bus_slot_get_floating() returns the current floating state of the specified bus slot + object. It returns negative on error, zero if the bus slot object is a regular (non-floating) object and positive + otherwise. + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a negative + errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The slot parameter is NULL. + + + + -ECHILD + + The bus connection has been created in a different process. + + + + -ESTALE + + The bus object the specified bus slot object is associated with has already been + freed, and hence no change in the floating state can be made anymore. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_slot_set_destroy_callback3, + sd_bus_add_match3 + + + + diff --git a/man/sd_bus_slot_set_userdata.xml b/man/sd_bus_slot_set_userdata.xml new file mode 100644 index 00000000..f0456b44 --- /dev/null +++ b/man/sd_bus_slot_set_userdata.xml @@ -0,0 +1,88 @@ + + + + + + + + sd_bus_slot_set_userdata + systemd + + + + sd_bus_slot_set_userdata + 3 + + + + sd_bus_slot_set_userdata + sd_bus_slot_get_userdata + + Set and query the value in the "userdata" field + + + + + #include <systemd/sd-bus.h> + + + void* sd_bus_slot_set_userdata + sd_bus_slot* slot + void* userdata + + + + void* sd_bus_slot_get_userdata + sd_bus_slot* slot + + + + + + + Description + + The userdata pointer allows data to be passed between the point where a callback is + registered, for example when a filter is added using + sd_bus_add_filter3 + or an asynchronous function call is made using + sd_bus_call_async3, + and the point where the callback is called, without having any global state. The pointer has + type void* and is not used by the sd-bus functions in any way, except to pass to + the callback function. + + Usually, the userdata field is set when the slot object is initially + registered. sd_bus_slot_set_userdata() may be used to change it later for + the bus slot object slot. Previous value of the field is returned. The + argument and returned value may be NULL. It will be passed as the + userdata argument to the callback function attached to the slot. + + sd_bus_slot_set_userdata() gets the value of the userdata field in + the bus slot object slot. + + + + Return Value + + On success, these functions return the value of the userdata field before the function + call. If the slot object is NULL, + NULL will be returned to signify an error, but this is not distinguishable + from the userdata field value being NULL. + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_slot_set_destroy_callback3, + sd_bus_add_match3, + sd_bus_slot_get_current_userdata3 + + + + diff --git a/man/sd_bus_track_add_name.xml b/man/sd_bus_track_add_name.xml new file mode 100644 index 00000000..29501adf --- /dev/null +++ b/man/sd_bus_track_add_name.xml @@ -0,0 +1,228 @@ + + + + + + + + sd_bus_track_add_name + systemd + + + + sd_bus_track_add_name + 3 + + + + sd_bus_track_add_name + sd_bus_track_add_sender + sd_bus_track_remove_name + sd_bus_track_remove_sender + sd_bus_track_count + sd_bus_track_count_sender + sd_bus_track_count_name + sd_bus_track_contains + sd_bus_track_first + sd_bus_track_next + + Add, remove and retrieve bus peers tracked in a bus peer tracking object + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_track_add_name + sd_bus_track* t + const char* name + + + + int sd_bus_track_add_sender + sd_bus_track* t + sd_bus_message* message + + + + int sd_bus_track_remove_name + sd_bus_track* t + const char* name + + + + int sd_bus_track_remove_sender + sd_bus_track* t + sd_bus_message* message + + + + unsigned sd_bus_track_count + sd_bus_track* t + + + + int sd_bus_track_count_name + sd_bus_track* t + const char* name + + + + int sd_bus_track_count_sender + sd_bus_track* t + sd_bus_message* message + + + + int sd_bus_track_contains + sd_bus_track* t + const char* name + + + + const char* sd_bus_track_first + sd_bus_track* t + + + + const char* sd_bus_track_next + sd_bus_track* t + + + + + + + Description + + sd_bus_track_add_name() adds a peer to track to a bus peer tracking object. The first + argument should refer to a bus peer tracking object created with + sd_bus_track_new3, the second + name should refer to a D-Bus peer name to track, either in unique or well-known service format. If the name is not + tracked yet it will be added to the list of names to track. If it already is being tracked and non-recursive mode + is enabled, no operation is executed by this call. If recursive mode is enabled a per-name counter is increased by + one each time this call is invoked, and sd_bus_track_remove_name() has to be called as many + times as sd_bus_track_add_name() was invoked before in order to stop tracking of the name. Use + sd_bus_track_set_recursive3 to + switch from the default non-recursive mode to recursive mode, or back. Note that the specified name is tracked as + it is, well-known names are not resolved to unique names by this call. Note that multiple bus peer tracking objects + may track the same name. + + sd_bus_track_remove_name() undoes the effect of + sd_bus_track_add_name() and removes a bus peer name from the list of peers to watch. Depending + on whether non-recursive or recursive mode is enabled for the bus peer tracking object this call will either remove + the name fully from the tracking object, or will simply decrement the per-name counter by one, removing the name + only when the counter reaches zero (see above). Note that a bus peer disconnecting from the bus will implicitly + remove its names fully from the bus peer tracking object, regardless of the current per-name counter. + + sd_bus_track_add_sender() and sd_bus_track_remove_sender() are + similar to sd_bus_track_add_name() and sd_bus_track_remove_name() but + take a bus message as argument. The sender of this bus message is determined and added to/removed from the bus peer + tracking object. As messages always originate from unique names, and never from well-known names this means that + this call will effectively only add unique names to the bus peer tracking object. + + sd_bus_track_count() returns the number of names currently being tracked by the + specified bus peer tracking object. Note that this function always returns the actual number of names tracked, and + hence if sd_bus_track_add_name() has been invoked multiple times for the same name it is only + counted as one, regardless if recursive mode is used or not. + + sd_bus_track_count_name() returns the current per-name counter for the specified + name. If non-recursive mode is used this returns either 1 or 0, depending on whether the specified name has been + added to the tracking object before, or not. If recursive mode has been enabled, values larger than 1 may be + returned too, in case sd_bus_track_add_name() has been called multiple times for the same + name. + + sd_bus_track_count_sender() is similar to + sd_bus_track_count_name(), but takes a bus message object and returns the per-name counter + matching the sender of the message. + + sd_bus_track_contains() may be used to determine whether the specified name has been + added at least once to the specified bus peer tracking object. + + sd_bus_track_first() and sd_bus_track_next() may be used to + enumerate all names currently being tracked by the passed bus peer tracking + object. sd_bus_track_first() returns the first entry in the object, and resets an internally + maintained read index. Each subsequent invocation of sd_bus_track_next() returns the next name + contained in the bus object. If the end is reached NULL is returned. If no names have been + added to the object yet sd_bus_track_first() will return NULL + immediately. The order in which names are returned is undefined; in particular which name is considered the first + returned is not defined. If recursive mode is enabled and the same name has been added multiple times to the bus + peer tracking object it is only returned once by this enumeration. If new names are added to or existing names + removed from the bus peer tracking object while it is being enumerated the enumeration ends on the next invocation + of sd_bus_track_next() as NULL is returned. + + + + Return Value + + On success, sd_bus_track_add_name() and sd_bus_track_add_sender() + return 0 if the specified name has already been added to the bus peer tracking object before and positive if it + hasn't. On failure, they return a negative errno-style error code. + + sd_bus_track_remove_name() and sd_bus_track_remove_sender() return + positive if the specified name was previously tracked by the bus peer tracking object and has now been removed. In + non-recursive mode, 0 is returned if the specified name was not being tracked yet. In recursive mode + -EUNATCH is returned in this case. On failure, they return a negative errno-style error + code. + + sd_bus_track_count() returns the number of names currently being tracked, or 0 on + failure. + + sd_bus_track_count_name() and sd_bus_track_count_sender() return + the current per-name counter for the specified name or the sender of the specified message. Zero is returned for + names that are not being tracked yet, a positive value for names added at least once. Larger values than 1 are only + returned in recursive mode. On failure, a negative errno-style error code is returned. + + sd_bus_track_contains() returns the passed name if it exists in the bus peer tracking + object. On failure, and if the name has not been added yet NULL is returned. + + sd_bus_track_first() and sd_bus_track_next() return the first/next + name contained in the bus peer tracking object, and NULL if the end of the enumeration is + reached and on error. + + + Errors + + Returned errors may indicate the following problems: + + + + + -EUNATCH + + sd_bus_track_remove_name() or + sd_bus_track_remove_sender() have been invoked for a name not previously added + to the bus peer object. + + + + -EINVAL + + Specified parameter is invalid. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_track_new3 + + + + diff --git a/man/sd_bus_track_new.xml b/man/sd_bus_track_new.xml new file mode 100644 index 00000000..9b79eb4c --- /dev/null +++ b/man/sd_bus_track_new.xml @@ -0,0 +1,231 @@ + + + + + + + + sd_bus_track_new + systemd + + + + sd_bus_track_new + 3 + + + + sd_bus_track_new + sd_bus_track_ref + sd_bus_track_unref + sd_bus_track_unrefp + sd_bus_track_set_recursive + sd_bus_track_get_recursive + sd_bus_track_get_bus + sd_bus_track_get_userdata + sd_bus_track_set_userdata + + Track bus peers + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_track_new + sd_bus* bus + sd_bus_track** ret + sd_bus_track_handler_t handler + void* userdata + + + + sd_bus_track *sd_bus_track_ref + sd_bus_track *t + + + + sd_bus_track *sd_bus_track_unref + sd_bus_track *t + + + + void sd_bus_track_unrefp + sd_bus_track **t + + + + int sd_bus_track_get_recursive + sd_bus_track *t + + + + int sd_bus_track_set_recursive + sd_bus_track *t + int b + + + + sd_bus* sd_bus_track_get_bus + sd_bus_track *t + + + + void* sd_bus_track_get_userdata + sd_bus_track *t + + + + void* sd_bus_track_set_userdata + sd_bus_track *t + void *userdata + + + + + + + Description + + sd_bus_track_new() creates a new bus peer tracking object. The object is allocated for + the specified bus, and returned in the *ret parameter. After use, the object should be freed + again by dropping the acquired reference with sd_bus_track_unref() (see below). A bus peer + tracking object may be used to keep track of peers on a specific IPC bus, for cases where peers are making use of + one or more local objects, in order to control the lifecycle of the local objects and ensure they stay around as + long as the peers needing them are around, and unreferenced (and possibly destroyed) as soon as all relevant peers + have vanished. Each bus peer tracking object may be used to track zero, one or more peers add a time. References to + specific bus peers are added via + sd_bus_track_add_name3 or + sd_bus_track_add_sender(). They may be dropped again via + sd_bus_track_remove_name() and + sd_bus_track_remove_sender(). Alternatively, references on peers are removed automatically + when they disconnect from the bus. If non-NULL the handler may specify a function that is + invoked whenever the last reference is dropped, regardless whether the reference is dropped explicitly via + sd_bus_track_remove_name() or implicitly because the peer disconnected from the bus. The final + argument userdata may be used to attach a generic user data pointer to the object. This + pointer is passed to the handler callback when it is invoked. + + sd_bus_track_ref() creates a new reference to a bus peer tracking object. This object + will not be destroyed until sd_bus_track_unref() has been called as many times plus once + more. Once the reference count has dropped to zero, the specified object cannot be used anymore, further calls to + sd_bus_track_ref() or sd_bus_track_unref() on the same object are + illegal. + + sd_bus_track_unref() destroys a reference to a bus peer tracking object. + + sd_bus_track_unrefp() is similar to sd_bus_track_unref() but takes + a pointer to a pointer to an sd_bus_track object. This call is useful in conjunction with GCC's and + LLVM's Clean-up Variable + Attribute. Note that this function is defined as inline function. + + sd_bus_track_ref(), sd_bus_track_unref() and + sd_bus_track_unrefp() execute no operation if the passed in bus peer tracking object is + NULL. + + Bus peer tracking objects may exist in two modes: by default they operate in non-recursive mode, but may + optionally be switched into recursive mode. If operating in the default non-recursive mode a peer is either tracked + or not tracked. In this mode invoking sd_bus_track_add_name() multiple times in a row for the + same peer is fully equivalent to calling it just once, as the call adds the peer to the set of tracked peers if + necessary, and executes no operation if the peer is already being tracked. A single invocation of + sd_bus_track_remove_name() removes the reference on the peer again, regardless how many times + sd_bus_track_add_name() was called before. If operating in recursive mode, the number of times + sd_bus_track_add_name() is invoked for the same peer name is counted and + sd_bus_track_remove_name() must be called the same number of times before the peer is not + tracked anymore, with the exception when the tracked peer vanishes from the bus, in which case the count is + irrelevant and the tracking of the specific peer is immediately + removed. sd_bus_track_get_recursive() may be used to determine whether the bus peer tracking + object is operating in recursive mode. sd_bus_track_set_recursive() may be used to enable or + disable recursive mode. By default a bus peer tracking object operates in non-recursive mode, and + sd_bus_track_get_recursive() for a newly allocated object hence returns a value equal to + zero. Use sd_bus_track_set_recursive() to enable recursive mode, right after allocation. It + takes a boolean argument to enable or disable recursive mode. Note that tracking objects for which + sd_bus_track_add_name() was already invoked at least once (and which hence track already one + or more peers) may not be switched from recursive to non-recursive mode anymore. + + sd_bus_track_get_bus() returns the bus object the bus peer tracking object belongs + to. It returns the bus object initially passed to sd_bus_track_new() when the object was + allocated. + + sd_bus_track_get_userdata() returns the generic user data pointer set on the bus peer + tracking object at the time of creation using sd_bus_track_new() or at a later time, using + sd_bus_track_set_userdata(). + + + + Return Value + + On success, sd_bus_track_new() and sd_bus_track_set_recursive() + return 0 or a positive integer. On failure, they return a negative errno-style error code. + + sd_bus_track_ref() always returns the argument. + + sd_bus_track_unref() always returns NULL. + + sd_bus_track_get_recursive() returns 0 if non-recursive mode is selected (default), and + greater than 0 if recursive mode is selected. On failure a negative errno-style error code is returned. + + sd_bus_track_get_bus() returns the bus object associated to the bus peer tracking + object. + + sd_bus_track_get_userdata() returns the generic user data pointer associated with the + bus peer tracking object. sd_bus_track_set_userdata() returns the previous user data pointer + set. + + + + + Reference ownership + + The sd_bus_track_new() function creates a new object and the caller owns the sole + reference. When not needed anymore, this reference should be destroyed with + sd_bus_track_unref(). + + + + Errors + + Returned errors may indicate the following problems: + + + + + -EBUSY + + Bus peers have already been added to the bus peer tracking object and + sd_bus_track_set_recursive() was called to change tracking mode. + + + + + -EINVAL + + Specified parameter is invalid + (NULL in case of output + parameters). + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + + See Also + + + systemd1, + sd-bus3 + sd_bus_track_add_name3 + + + + diff --git a/man/sd_bus_wait.xml b/man/sd_bus_wait.xml new file mode 100644 index 00000000..7b97dc02 --- /dev/null +++ b/man/sd_bus_wait.xml @@ -0,0 +1,113 @@ + + + + + + + + + sd_bus_wait + systemd + + + + sd_bus_wait + 3 + + + + sd_bus_wait + + Wait for I/O on a bus connection + + + + + #include <systemd/sd-bus.h> + + + int sd_bus_wait + sd_bus *bus + uint64_t timeout_usec + + + + + + Description + + sd_bus_wait() synchronously waits for I/O on the specified bus connection object. This + function is supposed to be called whenever + sd_bus_process3 returns zero, + indicating that no work is pending on the connection. Internally, this call invokes ppoll3, to wait for I/O on + the bus connection. If the timeout_sec parameter is specified, the call will block at most + for the specified amount of time in µs. Pass UINT64_MAX to permit it to sleep + indefinitely. + + After each invocation of sd_bus_wait() the sd_bus_process() call + should be invoked in order to process any now pending I/O work. + + Note that sd_bus_wait() is suitable only for simple programs as it does not permit + waiting for other I/O events. For more complex programs either connect the bus connection object to an external + event loop using sd_bus_get_fd3 + or to an sd-event3 event loop + using + sd_bus_attach_event3. + + + + Return Value + + If any I/O was seen, a positive value is returned, zero otherwise. If an error occurs, a negative + errno-style error code is returned. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + An invalid bus object was passed. + + + + -ECHILD + + The bus connection was allocated in a parent process and is being reused in a child + process after fork(). + + + + -ENOTCONN + + The bus connection has been terminated already. + + + + + + + + + See Also + + + systemd1, + sd-bus3, + sd_bus_process3, + sd_bus_get_fd3, + sd-event3, + sd_bus_attach_event3 + + + + diff --git a/man/sd_event_add_child.xml b/man/sd_event_add_child.xml new file mode 100644 index 00000000..509803d5 --- /dev/null +++ b/man/sd_event_add_child.xml @@ -0,0 +1,221 @@ + + + + + + + + sd_event_add_child + systemd + + + + sd_event_add_child + 3 + + + + sd_event_add_child + sd_event_source_get_child_pid + sd_event_child_handler_t + + Add a child process state change event source to an event loop + + + + + #include <systemd/sd-event.h> + + typedef struct sd_event_source sd_event_source; + + + typedef int (*sd_event_child_handler_t) + sd_event_source *s + const siginfo_t *si + void *userdata + + + + int sd_event_add_child + sd_event *event + sd_event_source **source + pid_t pid + int options + sd_event_child_handler_t handler + void *userdata + + + + int sd_event_source_get_child_pid + sd_event_source *source + pid_t *pid + + + + + + + Description + + sd_event_add_child() adds a new child + process state change event source to an event loop. The event loop + object is specified in the event parameter, + the event source object is returned in the + source parameter. The + pid parameter specifies the PID of the + process to watch. The handler must + reference a function to call when the process changes state. The + handler function will be passed the + userdata pointer, which may be chosen + freely by the caller. The handler also receives a pointer to a + siginfo_t structure containing + information about the child process event. The + options parameter determines which state + changes will be watched for. It must contain an OR-ed mask of + WEXITED (watch for the child process + terminating), WSTOPPED (watch for the child + process being stopped by a signal), and + WCONTINUED (watch for the child process being + resumed by a signal). See waitid2 + for further information. + + Only a single handler may be installed for a specific + child process. The handler is enabled for a single event + (SD_EVENT_ONESHOT), but this may be changed + with + sd_event_source_set_enabled3. + If the handler function returns a negative error code, it will be + disabled after the invocation, even if the + SD_EVENT_ON mode was requested before. + + + To destroy an event source object use + sd_event_source_unref3, + but note that the event source is only removed from the event loop + when all references to the event source are dropped. To make sure + an event source does not fire anymore, even when there's still a + reference to it kept, consider setting the event source to + SD_EVENT_OFF with + sd_event_source_set_enabled3. + + If the second parameter of + sd_event_add_child() is passed as NULL no + reference to the event source object is returned. In this case the + event source is considered "floating", and will be destroyed + implicitly when the event loop itself is destroyed. + + Note that the handler function is + invoked at a time where the child process is not reaped yet (and + thus still is exposed as a zombie process by the kernel). However, + the child will be reaped automatically after the function + returns. Child processes for which no child process state change + event sources are installed will not be reaped by the event loop + implementation. + + If both a child process state change event source and a + SIGCHLD signal event source is installed in + the same event loop, the configured event source priorities decide + which event source is dispatched first. If the signal handler is + processed first, it should leave the child processes for which + child process state change event sources are installed unreaped. + + sd_event_source_get_child_pid() + retrieves the configured PID of a child process state change event + source created previously with + sd_event_add_child(). It takes the event + source object as the source parameter and a + pointer to a pid_t variable to return the process ID + in. + + + + + Return Value + + On success, these functions return 0 or a positive + integer. On failure, they return a negative errno-style error + code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ENOMEM + + Not enough memory to allocate an object. + + + + -EINVAL + + An invalid argument has been passed. This includes + specifying an empty mask in options or a mask + which contains values different than a combination of + WEXITED, WSTOPPED, and + WCONTINUED. + + + + + + -EBUSY + + A handler is already installed for this + child process. + + + + + -ESTALE + + The event loop is already terminated. + + + + + -ECHILD + + The event loop has been created in a different process. + + + + + -EDOM + + The passed event source is not a child process event source. + + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_new3, + sd_event_now3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_enabled3, + sd_event_source_set_priority3, + sd_event_source_set_userdata3, + sd_event_source_set_description3, + sd_event_source_set_floating3, + waitid2 + + + + diff --git a/man/sd_event_add_defer.xml b/man/sd_event_add_defer.xml new file mode 100644 index 00000000..92be8353 --- /dev/null +++ b/man/sd_event_add_defer.xml @@ -0,0 +1,191 @@ + + + + + + + + sd_event_add_defer + systemd + + + + sd_event_add_defer + 3 + + + + sd_event_add_defer + sd_event_add_post + sd_event_add_exit + sd_event_handler_t + + Add static event sources to an event loop + + + + + #include <systemd/sd-event.h> + + typedef struct sd_event_source sd_event_source; + + + typedef int (*sd_event_handler_t) + sd_event_source *s + void *userdata + + + + int sd_event_add_defer + sd_event *event + sd_event_source **source + sd_event_handler_t handler + void *userdata + + + + int sd_event_add_post + sd_event *event + sd_event_source **source + sd_event_handler_t handler + void *userdata + + + + int sd_event_add_exit + sd_event *event + sd_event_source **source + sd_event_handler_t handler + void *userdata + + + + + + + Description + + These three functions add new static event sources to an + event loop. The event loop object is specified in the + event parameter, the event source object is + returned in the source parameter. The event + sources are enabled statically and will "fire" when the event loop + is run and the conditions described below are met. The handler + function will be passed the userdata + pointer, which may be chosen freely by the caller. + + sd_event_add_defer() adds a new event + source that will be dispatched instantly, before the event loop + goes to sleep again and waits for new events. By default, the + handler will be called once + (SD_EVENT_ONESHOT). Note that if the event + source is set to SD_EVENT_ON the event loop + will never go to sleep again, but continuously call the handler, + possibly interleaved with other event sources. + + sd_event_add_post() adds a new event + source that is run before the event loop will sleep and wait + for new events, but only after at least one other non-post event + source was dispatched. By default, the source is enabled + permanently (SD_EVENT_ON). Note that this + event source type will still allow the event loop to go to sleep + again, even if set to SD_EVENT_ON, as long as + no other event source is ever triggered. + + sd_event_add_exit() adds a new event + source that will be dispatched when the event loop is terminated + with sd_event_exit3. + + The + sd_event_source_set_enabled3 + function may be used to enable the event source permanently + (SD_EVENT_ON) or to make it fire just once + (SD_EVENT_ONESHOT). + + If the handler function returns a negative error code, it + will be disabled after the invocation, even if the + SD_EVENT_ON mode was requested before. + + To destroy an event source object use + sd_event_source_unref3, + but note that the event source is only removed from the event loop + when all references to the event source are dropped. To make sure + an event source does not fire anymore, even when there's still a + reference to it kept, consider setting the event source to + SD_EVENT_OFF with + sd_event_source_set_enabled3. + + If the second parameter of these functions is passed as + NULL no reference to the event source object is returned. In this + case the event source is considered "floating", and will be + destroyed implicitly when the event loop itself is + destroyed. + + + + Return Value + + On success, these functions return 0 or a positive + integer. On failure, they return a negative errno-style error + code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ENOMEM + + Not enough memory to allocate an object. + + + + -EINVAL + + An invalid argument has been passed. + + + + -ESTALE + + The event loop is already terminated. + + + + -ECHILD + + The event loop has been created in a different process. + + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_new3, + sd_event_now3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_source_set_enabled3, + sd_event_source_set_priority3, + sd_event_source_set_userdata3, + sd_event_source_set_description3, + sd_event_source_set_floating3, + sd_event_exit3 + + + + diff --git a/man/sd_event_add_inotify.xml b/man/sd_event_add_inotify.xml new file mode 100644 index 00000000..8860699d --- /dev/null +++ b/man/sd_event_add_inotify.xml @@ -0,0 +1,191 @@ + + + + + + + + sd_event_add_inotify + systemd + + + + sd_event_add_inotify + 3 + + + + sd_event_add_inotify + sd_event_source_get_inotify_mask + sd_event_inotify_handler_t + + Add an "inotify" file system inode event source to an event loop + + + + + #include <systemd/sd-event.h> + + typedef struct sd_event_source sd_event_source; + + + typedef int (*sd_event_inotify_handler_t) + sd_event_source *s + const struct inotify_event *event + void *userdata + + + + int sd_event_add_inotify + sd_event *event + sd_event_source **source + const char *path + uint32_t mask + sd_event_inotify_handler_t handler + void *userdata + + + + int sd_event_source_get_inotify_mask + sd_event_source *source + uint32_t *mask + + + + + + + Description + + sd_event_add_inotify() adds a new inotify7 file system inode + event source to an event loop. The event loop object is specified in the event parameter, + the event source object is returned in the source parameter. The path + parameter specifies the path of the file system inode to watch. The handler must reference a + function to call when the inode changes. The handler function will be passed the userdata + pointer, which may be chosen freely by the caller. The handler also receives a pointer to a struct + inotify_event structure containing information about the inode event. The mask + parameter specifie which types of inode events to watch specifically. It must contain an OR-ed combination of + IN_ACCESS, IN_ATTRIB, IN_CLOSE_WRITE, … flags. See + inotify7 for + further information. + + If multiple event sources are installed for the same inode the backing inotify watch descriptor is + automatically shared. The mask parameter may contain any flag defined by the inotify API, with the exception of + IN_MASK_ADD. + + The handler is enabled continuously (SD_EVENT_ON), but this may be changed with + sd_event_source_set_enabled3. Alternatively, + the IN_ONESHOT mask flag may be used to request SD_EVENT_ONESHOT mode. + If the handler function returns a negative error code, it will be disabled after the invocation, even if the + SD_EVENT_ON mode was requested before. + + + As a special limitation the priority of inotify event sources may only be altered (see + sd_event_source_set_priority3) + in the time between creation of the event source object with sd_event_add_inotify() and the + beginning of the next event loop iteration. Attempts of changing the priority any later will be refused. Consider + freeing and allocating a new inotify event source to change the priority at that point. + + To destroy an event source object use + sd_event_source_unref3, but note + that the event source is only removed from the event loop when all references to the event source are dropped. To + make sure an event source does not fire anymore, even when there's still a reference to it kept, consider disabling + it with + sd_event_source_set_enabled3. + + If the second parameter of sd_event_add_inotify() is passed as NULL no reference to the + event source object is returned. In this case the event source is considered "floating", and will be destroyed + implicitly when the event loop itself is destroyed. + + sd_event_source_get_inotify_mask() retrieves the configured inotify watch mask of an + event source created previously with sd_event_add_inotify(). It takes the event source object + as the source parameter and a pointer to a uint32_t variable to return the mask + in. + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a negative errno-style + error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ENOMEM + + Not enough memory to allocate an object. + + + + -EINVAL + + An invalid argument has been passed. This includes specifying a mask with + IN_MASK_ADD set. + + + + -ESTALE + + The event loop is already terminated. + + + + + -ECHILD + + The event loop has been created in a different process. + + + + + -EDOM + + The passed event source is not an inotify process event source. + + + + + + + + Examples + + + A simple program that uses inotify to monitor one or two directories + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_new3, + sd_event_now3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_defer3, + sd_event_add_child3, + sd_event_source_set_enabled3, + sd_event_source_set_priority3, + sd_event_source_set_userdata3, + sd_event_source_set_description3, + sd_event_source_set_floating3, + waitid2 + + + + diff --git a/man/sd_event_add_io.xml b/man/sd_event_add_io.xml new file mode 100644 index 00000000..35d02a17 --- /dev/null +++ b/man/sd_event_add_io.xml @@ -0,0 +1,305 @@ + + + + + + + + sd_event_add_io + systemd + + + + sd_event_add_io + 3 + + + + sd_event_add_io + sd_event_source_get_io_events + sd_event_source_set_io_events + sd_event_source_get_io_revents + sd_event_source_get_io_fd + sd_event_source_set_io_fd + sd_event_source_get_io_fd_own + sd_event_source_set_io_fd_own + sd_event_source + sd_event_io_handler_t + + Add an I/O event source to an event loop + + + + + #include <systemd/sd-event.h> + + typedef struct sd_event_source sd_event_source; + + + typedef int (*sd_event_io_handler_t) + sd_event_source *s + int fd + uint32_t revents + void *userdata + + + + int sd_event_add_io + sd_event *event + sd_event_source **source + int fd + uint32_t events + sd_event_io_handler_t handler + void *userdata + + + + int sd_event_source_get_io_events + sd_event_source *source + uint32_t *events + + + + int sd_event_source_set_io_events + sd_event_source *source + uint32_t events + + + + int sd_event_source_get_io_revents + sd_event_source *source + uint32_t *revents + + + + int sd_event_source_get_io_fd + sd_event_source *source + + + + int sd_event_source_set_io_fd + sd_event_source *source + int fd + + + + int sd_event_source_get_io_fd_own + sd_event_source *source + + + + int sd_event_source_set_io_fd_own + sd_event_source *source + int b + + + + + + + Description + + sd_event_add_io() adds a new I/O event + source to an event loop. The event loop object is specified in the + event parameter, the event source object is + returned in the source parameter. The + fd parameter takes the UNIX file descriptor + to watch, which may refer to a socket, a FIFO, a message queue, a + serial connection, a character device, or any other file descriptor + compatible with Linux + epoll7. The + events parameter takes a bit mask of events + to watch for, a combination of the following event flags: + EPOLLIN, EPOLLOUT, + EPOLLRDHUP, EPOLLPRI, + and EPOLLET, see + epoll_ctl2 + for details. The handler shall reference a + function to call when the event source is triggered. The + userdata pointer will be passed to the + handler function, and may be chosen freely by the caller. The + handler will also be passed the file descriptor the event was seen + on, as well as the actual event flags. It's generally a subset of + the events watched, however may additionally include + EPOLLERR and EPOLLHUP. + + + By default, an event source will stay enabled + continuously (SD_EVENT_ON), but this may be + changed with + sd_event_source_set_enabled3. + If the handler function returns a negative error code, it will be + disabled after the invocation, even if the + SD_EVENT_ON mode was requested before. Note + that an event source set to SD_EVENT_ON will + fire continuously unless data is read from or written to the file + descriptor to reset the mask of events seen. + + + Setting the I/O event mask to watch for to 0 does not mean + that the event source won't be triggered anymore, as + EPOLLHUP and EPOLLERR + may be triggered even with a zero event mask. To temporarily + disable an I/O event source use + sd_event_source_set_enabled3 + with SD_EVENT_OFF instead. + + To destroy an event source object use + sd_event_source_unref3, + but note that the event source is only removed from the event loop + when all references to the event source are dropped. To make sure + an event source does not fire anymore, even if it is still referenced, + disable the event source using + sd_event_source_set_enabled3 + with SD_EVENT_OFF. + + If the second parameter of + sd_event_add_io() is + NULL no reference to the event source object + is returned. In this case the event source is considered + "floating", and will be destroyed implicitly when the event loop + itself is destroyed. + + Note that this call does not take possession of the file descriptor passed in, ownership (and thus + the duty to close it when it is no longer needed) remains with the caller. However, with the + sd_event_source_set_io_fd_own() call (see below) the event source may optionally + take ownership of the file descriptor after the event source has been created. In that case the file + descriptor is closed automatically as soon as the event source is released. + + It is recommended to use + sd_event_add_io() only in conjunction with + file descriptors that have O_NONBLOCK set, to + ensure that all I/O operations from invoked handlers are properly + asynchronous and non-blocking. Using file descriptors without + O_NONBLOCK might result in unexpected + starvation of other event sources. See + fcntl2 + for details on enabling O_NONBLOCK mode. + + sd_event_source_get_io_events() retrieves + the configured mask of watched I/O events of an event source created + previously with sd_event_add_io(). It takes + the event source object and a pointer to a variable to store the + mask in. + + sd_event_source_set_io_events() + configures the mask of watched I/O events of an event source created + previously with sd_event_add_io(). It takes the + event source object and the new event mask. + + sd_event_source_get_io_revents() + retrieves the I/O event mask of currently seen but undispatched + events from an event source created previously with + sd_event_add_io(). It takes the event source + object and a pointer to a variable to store the event mask + in. When called from a handler function on the handler's event + source object this will return the same mask as passed to the + handler's revents parameter. This call is + primarily useful to check for undispatched events of an event + source from the handler of an unrelated (possibly higher priority) + event source. Note the relation between + sd_event_source_get_pending() and + sd_event_source_get_io_revents(): both + functions will report non-zero results when there's an event + pending for the event source, but the former applies to all event + source types, the latter only to I/O event sources. + + sd_event_source_get_io_fd() retrieves + the UNIX file descriptor of an event source created previously + with sd_event_add_io(). It takes the event + source object and returns the non-negative file descriptor + or a negative error number on error (see below). + + sd_event_source_set_io_fd() + changes the UNIX file descriptor of an I/O event source created + previously with sd_event_add_io(). It takes + the event source object and the new file descriptor. + + sd_event_source_set_io_fd_own() controls whether the file descriptor of the event source + shall be closed automatically when the event source is freed, i.e. whether it shall be considered 'owned' by the + event source object. By default it is not closed automatically, and the application has to do this on its own. The + b parameter is a boolean parameter: if zero, the file descriptor is not closed automatically + when the event source is freed, otherwise it is closed. + + sd_event_source_get_io_fd_own() may be used to query the current setting of the file + descriptor ownership boolean flag as set with sd_event_source_set_io_fd_own(). It returns + positive if the file descriptor is closed automatically when the event source is destroyed, zero if not, and + negative on error. + + + + Return Value + + On success, these functions return 0 or a positive + integer. On failure, they return a negative errno-style error + code. + + + Errors + + Returned values may indicate the following problems: + + + + -ENOMEM + + Not enough memory to allocate an object. + + + + -EINVAL + + An invalid argument has been passed. + + + + + -ESTALE + + The event loop is already terminated. + + + + + -ECHILD + + The event loop has been created in a different process. + + + + -EDOM + + The passed event source is not an I/O event source. + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_new3, + sd_event_now3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_enabled3, + sd_event_source_set_priority3, + sd_event_source_set_userdata3, + sd_event_source_set_description3, + sd_event_source_get_pending3, + sd_event_source_set_floating3, + epoll_ctl2, + epoll7 + + + + diff --git a/man/sd_event_add_signal.xml b/man/sd_event_add_signal.xml new file mode 100644 index 00000000..a7148ca8 --- /dev/null +++ b/man/sd_event_add_signal.xml @@ -0,0 +1,196 @@ + + + + + + + + sd_event_add_signal + systemd + + + + sd_event_add_signal + 3 + + + + sd_event_add_signal + sd_event_source_get_signal + sd_event_signal_handler_t + + Add a UNIX process signal event source to an event + loop + + + + + #include <systemd/sd-event.h> + + typedef struct sd_event_source sd_event_source; + + + typedef int (*sd_event_signal_handler_t) + sd_event_source *s + const struct signalfd_siginfo *si + void *userdata + + + + int sd_event_add_signal + sd_event *event + sd_event_source **source + int signal + sd_event_signal_handler_t handler + void *userdata + + + + int sd_event_source_get_signal + sd_event_source *source + + + + + + + Description + + sd_event_add_signal() adds a new UNIX + process signal event source to an event loop. The event loop + object is specified in the event parameter, + and the event source object is returned in the + source parameter. The + signal parameter specifies the numeric + signal to be handled (see signal7). + The handler parameter must reference a + function to call when the signal is received or be + NULL. The handler function will be passed + the userdata pointer, which may be chosen + freely by the caller. The handler also receives a pointer to a + signalfd_siginfo structure containing + information about the received signal. See signalfd2 + for further information. + + Only a single handler may be installed for a specific + signal. The signal will be unblocked by this call, and must be + blocked before this function is called in all threads (using + sigprocmask2). If + the handler is not specified (handler is + NULL), a default handler which causes the + program to exit cleanly will be used. + + By default, the event source is enabled permanently + (SD_EVENT_ON), but this may be changed with + sd_event_source_set_enabled3. + If the handler function returns a negative error code, it will be + disabled after the invocation, even if the + SD_EVENT_ON mode was requested before. + + + To destroy an event source object use + sd_event_source_unref3, + but note that the event source is only removed from the event loop + when all references to the event source are dropped. To make sure + an event source does not fire anymore, even if it is still referenced, + disable the event source using + sd_event_source_set_enabled3 + with SD_EVENT_OFF. + + If the second parameter of + sd_event_add_signal() is + NULL no reference to the event source object + is returned. In this case the event source is considered + "floating", and will be destroyed implicitly when the event loop + itself is destroyed. + + sd_event_source_get_signal() returns + the configured signal number of an event source created previously + with sd_event_add_signal(). It takes the + event source object as the source + parameter. + + + + Return Value + + On success, these functions return 0 or a positive + integer. On failure, they return a negative errno-style error + code. + + + Errors + + Returned errors may indicate the following problems: + + + + -ENOMEM + + Not enough memory to allocate an object. + + + + -EINVAL + + An invalid argument has been passed. + + + + -EBUSY + + A handler is already installed for this + signal or the signal was not blocked previously. + + + + -ESTALE + + The event loop is already terminated. + + + + -ECHILD + + The event loop has been created in a different process. + + + + -EDOM + + The passed event source is not a signal event source. + + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_new3, + sd_event_now3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_enabled3, + sd_event_source_set_description3, + sd_event_source_set_userdata3, + sd_event_source_set_floating3, + signal7, + signalfd2 + + + + diff --git a/man/sd_event_add_time.xml b/man/sd_event_add_time.xml new file mode 100644 index 00000000..8d3511ef --- /dev/null +++ b/man/sd_event_add_time.xml @@ -0,0 +1,288 @@ + + + + + + + + sd_event_add_time + systemd + + + + sd_event_add_time + 3 + + + + sd_event_add_time + sd_event_source_get_time + sd_event_source_set_time + sd_event_source_get_time_accuracy + sd_event_source_set_time_accuracy + sd_event_source_get_time_clock + sd_event_time_handler_t + + Add a timer event source to an event loop + + + + + #include <systemd/sd-event.h> + + typedef struct sd_event_source sd_event_source; + + + typedef int (*sd_event_time_handler_t) + sd_event_source *s + uint64_t usec + void *userdata + + + + int sd_event_add_time + sd_event *event + sd_event_source **source + clockid_t clock + uint64_t usec + uint64_t accuracy + sd_event_time_handler_t handler + void *userdata + + + + int sd_event_source_get_time + sd_event_source *source + uint64_t *usec + + + + int sd_event_source_set_time + sd_event_source *source + uint64_t usec + + + + int sd_event_source_get_time_accuracy + sd_event_source *source + uint64_t *usec + + + + int sd_event_source_set_time_accuracy + sd_event_source *source + uint64_t usec + + + + int sd_event_source_get_time_clock + sd_event_source *source + clockid_t *clock + + + + + + + Description + + sd_event_add_time() adds a new timer event source to an event loop. The event loop + object is specified in the event parameter, the event source object is returned in the + source parameter. The clock parameter takes a clock identifier, one + of CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_BOOTTIME, + CLOCK_REALTIME_ALARM, or CLOCK_BOOTTIME_ALARM. See + timerfd_create2 for details + regarding the various types of clocks. The usec parameter specifies the earliest time, in + microseconds (µs), relative to the clock's epoch, when the timer shall be triggered. If a time already in the past + is specified (including 0), this timer source "fires" immediately and is ready to be + dispatched. If the parameter is specified as UINT64_MAX the timer event will never elapse, + which may be used as an alternative to explicitly disabling a timer event source with + sd_event_source_set_enabled3. The + accuracy parameter specifies an additional accuracy value in µs specifying how much the + timer event may be delayed. Use 0 to select the default accuracy (250ms). Use 1µs for maximum + accuracy. Consider specifying 60000000µs (1min) or larger for long-running events that may be delayed + substantially. Picking higher accuracy values allows the system to coalesce timer events more aggressively, + improving power efficiency. The handler parameter shall reference a function to call when + the timer elapses. The handler function will be passed the userdata pointer, which may be + chosen freely by the caller. The handler is also passed the configured trigger time, even if it is actually called + slightly later, subject to the specified accuracy value, the kernel timer slack (see + prctl2), and additional + scheduling latencies. To query the actual time the handler was called use + sd_event_now3. + + By default, the timer will elapse once + (SD_EVENT_ONESHOT), but this may be changed + with + sd_event_source_set_enabled3. + If the handler function returns a negative error code, it will be + disabled after the invocation, even if the + SD_EVENT_ON mode was requested before. Note + that a timer event set to SD_EVENT_ON will + fire continuously unless its configured time is updated using + sd_event_source_set_time(). + + + To destroy an event source object use + sd_event_source_unref3, + but note that the event source is only removed from the event loop + when all references to the event source are dropped. To make sure + an event source does not fire anymore, even if it is still referenced, + disable the event source using + sd_event_source_set_enabled3 + with SD_EVENT_OFF. + + If the second parameter of + sd_event_add_time() is + NULL no reference to the event source object + is returned. In this case the event source is considered + "floating", and will be destroyed implicitly when the event loop + itself is destroyed. + + If the handler to + sd_event_add_time() is + NULL, and the event source fires, this will + be considered a request to exit the event loop. In this case, the + userdata parameter, cast to an integer, is + used for the exit code passed to + sd_event_exit3. + + Use CLOCK_BOOTTIME_ALARM and + CLOCK_REALTIME_ALARM to define event sources + that may wake up the system from suspend. + + In order to set up relative timers (that is, relative to the + current time), retrieve the current time via + sd_event_now3, + add the desired timespan to it, and use the result as + the usec parameter to + sd_event_add_time(). + + In order to set up repetitive timers (that is, timers that + are triggered in regular intervals), set up the timer normally, + for the first invocation. Each time the event handler is invoked, + update the timer's trigger time with + sd_event_source_set_time3 for the next timer + iteration, and reenable the timer using + sd_event_source_set_enabled(). To calculate + the next point in time to pass to + sd_event_source_set_time(), either use as + base the usec parameter passed to the timer + callback, or the timestamp returned by + sd_event_now(). In the former case timer + events will be regular, while in the latter case the scheduling + latency will keep accumulating on the timer. + + sd_event_source_get_time() retrieves + the configured time value of an event source created + previously with sd_event_add_time(). It takes + the event source object and a pointer to a variable to store the + time in, relative to the selected clock's epoch, in µs. + + sd_event_source_set_time() changes the + time of an event source created previously with + sd_event_add_time(). It takes the event + source object and a time relative to the selected clock's epoch, + in µs. + + sd_event_source_get_time_accuracy() + retrieves the configured accuracy value of an event source + created previously with sd_event_add_time(). It + takes the event source object and a pointer to a variable to store + the accuracy in. The accuracy is specified in µs. + + sd_event_source_set_time_accuracy() + changes the configured accuracy of a timer event source created + previously with sd_event_add_time(). It takes + the event source object and accuracy, in µs. + + sd_event_source_get_time_clock() + retrieves the configured clock of an event source created + previously with sd_event_add_time(). It takes + the event source object and a pointer to a variable to store the + clock identifier in. + + + + Return Value + + On success, these functions return 0 or a positive + integer. On failure, they return a negative errno-style error + code. + + + Errors + + Returned values may indicate the following problems: + + + + -ENOMEM + + Not enough memory to allocate an object. + + + + -EINVAL + + An invalid argument has been passed. + + + + + -ESTALE + + The event loop is already terminated. + + + + + -ECHILD + + The event loop has been created in a different process. + + + + + -EOPNOTSUPP + + The selected clock is not supported by the event loop implementation. + + + + + -EDOM + + The passed event source is not a timer event source. + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_new3, + sd_event_now3, + sd_event_add_io3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_enabled3, + sd_event_source_set_priority3, + sd_event_source_set_userdata3, + sd_event_source_set_description3, + sd_event_source_set_floating3, + clock_gettime2, + timerfd_create2, + prctl2 + + + + diff --git a/man/sd_event_exit.xml b/man/sd_event_exit.xml new file mode 100644 index 00000000..a02897af --- /dev/null +++ b/man/sd_event_exit.xml @@ -0,0 +1,135 @@ + + + + + + + + sd_event_exit + systemd + + + + sd_event_exit + 3 + + + + sd_event_exit + sd_event_get_exit_code + + Ask the event loop to exit + + + + + #include <systemd/sd-event.h> + + + int sd_event_exit + sd_event *event + int code + + + + int sd_event_get_exit_code + sd_event *event + int *code + + + + + + + Description + + sd_event_exit() requests the event loop + specified in the event event loop object to + exit. The code parameter may be any integer + value and is returned as-is by + sd_event_loop3 + after the last event loop iteration. It may also be queried + using sd_event_get_exit_code(), see + below. + + When exiting is requested the event loop will stop listening + for and dispatching regular event sources. Instead it will proceed + with executing only event sources registered with + sd_event_add_exit3 + in the order defined by their priority. After all exit event + sources have been dispatched the event loop is terminated. + + If sd_event_exit() is invoked a second + time while the event loop is still processing exit event sources, + the exit code stored in the event loop object is updated, but + otherwise no further operation is executed. + + sd_event_get_exit_code() may be used to + query the exit code passed into + sd_event_exit() earlier. + + While the full positive and negative integer ranges may be used + for the exit code, care should be taken not pick exit codes that + conflict with regular exit codes returned by + sd_event_loop(), if these exit codes shall be + distinguishable. + + + + Return Value + + On success, sd_event_exit() and sd_event_get_exit_code() + return 0 or a positive integer. On failure, they return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -EINVAL + + The event loop object or error code pointer are invalid. + + + + + -ECHILD + + The event loop was created in a different process. + + + + -ESTALE + + The event loop has exited already and all exit handlers are already processed. + + + + + -ENODATA + + The event loop has not been requested to exit yet. + + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_new3, + sd_event_add_exit3 + + + + diff --git a/man/sd_event_get_fd.xml b/man/sd_event_get_fd.xml new file mode 100644 index 00000000..3e781821 --- /dev/null +++ b/man/sd_event_get_fd.xml @@ -0,0 +1,111 @@ + + + + + + + + sd_event_get_fd + systemd + + + + sd_event_get_fd + 3 + + + + sd_event_get_fd + + Obtain a file descriptor to poll for event loop events + + + + + #include <systemd/sd-event.h> + + + int sd_event_get_fd + sd_event *event + + + + + + + Description + + sd_event_get_fd() returns the file + descriptor that an event loop object returned by the + sd_event_new3 + function uses to wait for events. This file descriptor may itself + be polled for + POLLIN/EPOLLIN + events. This makes it possible to embed an + sd-event3 + event loop into another, possibly foreign, event loop. + + The returned file descriptor refers to an epoll7 + object. It is recommended not to alter it by invoking + epoll_ctl2 + on it, in order to avoid interference with the event loop's inner + logic and assumptions. + + + + Return Value + + On success, sd_event_get_fd() returns a non-negative file descriptor. On + failure, it returns a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + event is not a valid pointer to an + sd_event structure. + + + + -ECHILD + + The event loop has been created in a different process. + + + + + + + + Examples + + + Integration in the GLib event loop + + + + + + + + + See Also + + + sd-event3, + sd_event_new3, + sd_event_wait3, + epoll_ctl2, + epoll7 + + + + diff --git a/man/sd_event_new.xml b/man/sd_event_new.xml new file mode 100644 index 00000000..3db39c9d --- /dev/null +++ b/man/sd_event_new.xml @@ -0,0 +1,216 @@ + + + + + + + + sd_event_new + systemd + + + + sd_event_new + 3 + + + + sd_event_new + sd_event_default + sd_event_ref + sd_event_unref + sd_event_unrefp + sd_event_get_tid + sd_event + + Acquire and release an event loop object + + + + + #include <systemd/sd-event.h> + + typedef struct sd_event sd_event; + + + int sd_event_new + sd_event **event + + + + int sd_event_default + sd_event **event + + + + sd_event *sd_event_ref + sd_event *event + + + + sd_event *sd_event_unref + sd_event *event + + + + void sd_event_unrefp + sd_event **event + + + + int sd_event_get_tid + sd_event *event + pid_t *tid + + + + + + + Description + + sd_event_new() allocates a new event + loop object. The event loop object is returned in the + event parameter. After use, drop + the returned reference with + sd_event_unref(). When the last reference is + dropped, the object is freed. + + sd_event_default() acquires a reference + to the default event loop object of the calling thread, possibly + allocating a new object if no default event loop object has been + allocated yet for the thread. After use, drop the returned + reference with sd_event_unref(). When the + last reference is dropped, the event loop is freed. If this + function is called while the object returned from a previous call + from the same thread is still referenced, the same object is + returned again, but the reference is increased by one. It is + recommended to use this call instead of + sd_event_new() in order to share event loop + objects between various components that are dispatched in the same + thread. All threads have exactly either zero or one default event loop + objects associated, but never more. + + After allocating an event loop object, add event sources to + it with + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_add_post3 or + sd_event_add_exit3, + and then execute the event loop using + sd_event_loop3. + + sd_event_ref() increases the reference + count of the specified event loop object by one. + + sd_event_unref() decreases the + reference count of the specified event loop object by one. If + the count hits zero, the object is freed. Note that it + is freed regardless of whether it is the default event loop object for a + thread or not. This means that allocating an event loop with + sd_event_default(), then releasing it, and + then acquiring a new one with + sd_event_default() will result in two + distinct objects. Note that, in order to free an event loop object, + all remaining event sources of the event loop also need to be + freed as each keeps a reference to it. + + sd_event_unrefp() is similar to + sd_event_unref() but takes a pointer to a + pointer to an sd_event object. This call is useful in + conjunction with GCC's and LLVM's Clean-up + Variable Attribute. Note that this function is defined as + inline function. Use a declaration like the following, + in order to allocate an event loop object that is freed + automatically as the code block is left: + + { + __attribute__((cleanup(sd_event_unrefp)) sd_event *event = NULL; + int r; + … + r = sd_event_default(&event); + if (r < 0) + fprintf(stderr, "Failed to allocate event loop: %s\n", strerror(-r)); + … +} + + sd_event_ref(), + sd_event_unref() and + sd_event_unrefp() execute no operation if the + passed in event loop object is NULL. + + sd_event_get_tid() retrieves the thread + identifier ("TID") of the thread the specified event loop object + is associated with. This call is only supported for event loops + allocated with sd_event_default(), and + returns the identifier for the thread the event loop is the + default event loop of. See gettid2 + for more information on thread identifiers. + + + + Return Value + + On success, sd_event_new(), sd_event_default() and + sd_event_get_tid() return 0 or a positive integer. On failure, they return a + negative errno-style error code. sd_event_ref() always returns a pointer to the + event loop object passed in. sd_event_unref() always returns + NULL. + + + Errors + + Returned errors may indicate the following problems: + + + + -ENOMEM + + Not enough memory to allocate the object. + + + + -EMFILE + + The maximum number of event loops has been allocated. + + + + + -ENXIO + + sd_event_get_tid() was invoked on an event loop object that + was not allocated with sd_event_default(). + + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_run3, + gettid2 + + + + diff --git a/man/sd_event_now.xml b/man/sd_event_now.xml new file mode 100644 index 00000000..2d2b0850 --- /dev/null +++ b/man/sd_event_now.xml @@ -0,0 +1,114 @@ + + + + + + + + sd_event_now + systemd + + + + sd_event_now + 3 + + + + sd_event_now + + Retrieve current event loop iteration timestamp + + + + + #include <systemd/sd-event.h> + + + int sd_event_now + sd_event *event + clockid_t clock + uint64_t *usec + + + + + + + Description + + sd_event_now() returns the time when + the most recent event loop iteration began. A timestamp + is taken right after returning from the event sleep, and before + dispatching any event sources. The event + parameter specifies the event loop object to retrieve the timestamp + from. The clock parameter specifies the clock to + retrieve the timestamp for, and is one of + CLOCK_REALTIME (or equivalently + CLOCK_REALTIME_ALARM), + CLOCK_MONOTONIC, or + CLOCK_BOOTTIME (or equivalently + CLOCK_BOOTTIME_ALARM), see + clock_gettime2 + for more information on the various clocks. The retrieved + timestamp is stored in the usec parameter, + in µs since the clock's epoch. If this function is invoked before + the first event loop iteration, the current time is returned, as + reported by clock_gettime(). To distinguish + this case from a regular invocation the return value will be + positive, and zero when the returned timestamp refers to an actual + event loop iteration. + + + + Return Value + + If the first event loop iteration has not run yet sd_event_now() writes + current time to usec and returns a positive return value. Otherwise, it will + write the requested timestamp to usec and return 0. On failure, the call returns a + negative errno-style error code. + + + Errors + + Returned values may indicate the following problems: + + + + -EINVAL + + An invalid parameter was passed. + + + + + -EOPNOTSUPP + + Unsupported clock type. + + + + -ECHILD + + The event loop object was created in a different process. + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_new3, + sd_event_add_time3, + clock_gettime2 + + + + diff --git a/man/sd_event_run.xml b/man/sd_event_run.xml new file mode 100644 index 00000000..5c33d61f --- /dev/null +++ b/man/sd_event_run.xml @@ -0,0 +1,164 @@ + + + + + + + + sd_event_run + systemd + + + + sd_event_run + 3 + + + + sd_event_run + sd_event_loop + + Run an event loop + + + + + #include <systemd/sd-event.h> + + + int sd_event_run + sd_event *event + uint64_t usec + + + + int sd_event_loop + sd_event *event + + + + + + Description + + sd_event_run() may be used to run a single + iteration of the event loop specified in the + event parameter. The function waits until an event to + process is available, and dispatches the registered handler for + it. The usec parameter specifies the + maximum time (in microseconds) to wait for an event. Use + (uint64_t) -1 to specify an infinite + timeout. + + sd_event_loop() invokes + sd_event_run() in a loop, thus implementing + the actual event loop. The call returns as soon as exiting was + requested using + sd_event_exit3. + + The event loop object event is + created with + sd_event_new3. + Events sources to wait for and their handlers may be registered + with + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_defer3, + sd_event_add_post3 + and + sd_event_add_exit3. + + + For low-level control of event loop execution, use + sd_event_prepare3, + sd_event_wait3 + and + sd_event_dispatch3 + which are wrapped by sd_event_run(). Along + with + sd_event_get_fd3, + these functions allow integration of an + sd-event3 + event loop into foreign event loop implementations. + + + + Return Value + + On failure, these functions return a negative errno-style + error code. sd_event_run() returns a + positive, non-zero integer if an event source was dispatched, and + zero when the specified timeout hit before an event source has + seen any event, and hence no event source was + dispatched. sd_event_loop() returns the exit + code specified when invoking + sd_event_exit(). + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The event parameter is invalid or + NULL. + + + + -EBUSY + + The event loop object is not in the right + state (see + sd_event_prepare3 + for an explanation of possible states). + + + + -ESTALE + + The event loop is already terminated. + + + + + -ECHILD + + The event loop has been created in a different process. + + + + + + Other errors are possible, too. + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_new3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_exit3, + sd_event_get_fd3, + sd_event_wait3, + GLib Main Event Loop + + + + diff --git a/man/sd_event_set_watchdog.xml b/man/sd_event_set_watchdog.xml new file mode 100644 index 00000000..cacc683b --- /dev/null +++ b/man/sd_event_set_watchdog.xml @@ -0,0 +1,145 @@ + + + + + + + + sd_event_set_watchdog + systemd + + + + sd_event_set_watchdog + 3 + + + + sd_event_set_watchdog + sd_event_get_watchdog + + Enable event loop watchdog support + + + + + #include <systemd/sd-event.h> + + + int sd_event_set_watchdog + sd_event *event + int b + + + + int sd_event_get_watchdog + sd_event *event + + + + + + + Description + + sd_event_set_watchdog() may be used to + enable or disable automatic watchdog notification support in the + event loop object specified in the event + parameter. Specifically, depending on the b + boolean argument this will make sure the event loop wakes up in + regular intervals and sends watchdog notification messages to the + service manager, if this was requested by the service + manager. Watchdog support is determined with + sd_watchdog_enabled3, + and watchdog messages are sent with + sd_notify3. See + the WatchdogSec= setting in + systemd.service5 + for details on how to enable watchdog support for a service and + the protocol used. The wake-up interval is chosen as half the + watchdog timeout declared by the service manager via the + $WATCHDOG_USEC environment variable. If the + service manager did not request watchdog notifications, or if the + process was not invoked by the service manager this call with a + true b parameter executes no + operation. Passing a false b parameter will + disable the automatic sending of watchdog notification messages if + it was enabled before. Newly allocated event loop objects have + this feature disabled. + + The first watchdog notification message is sent immediately + when sd_event_set_watchdog() is invoked with + a true b parameter. + + The watchdog logic is designed to allow the service manager + to automatically detect services that ceased processing of + incoming events, and thus appear "hung". Watchdog notifications + are sent out only at the beginning of each event loop + iteration. If an event source dispatch function blocks for an + excessively long time and does not return execution to the event + loop quickly, this might hence cause the notification message to + be delayed, and possibly result in abnormal program termination, + as configured in the service unit file. + + sd_event_get_watchdog() may be used to + determine whether watchdog support was previously requested by a + call to sd_event_set_watchdog() with a true + b parameter and successfully + enabled. + + + + Return Value + + On success, sd_event_set_watchdog() and + sd_event_get_watchdog() return a non-zero positive integer if the service manager + requested watchdog support and watchdog support was successfully enabled. They return zero if the service + manager did not request watchdog support, or if watchdog support was explicitly disabled with a false + b parameter. On failure, they return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -ECHILD + + The event loop has been created in a different process. + + + + -EINVAL + + The passed event loop object was invalid. + + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_new3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_watchdog_enabled3, + sd_notify3, + systemd.service5 + + + + diff --git a/man/sd_event_source_get_event.xml b/man/sd_event_source_get_event.xml new file mode 100644 index 00000000..2b059a35 --- /dev/null +++ b/man/sd_event_source_get_event.xml @@ -0,0 +1,74 @@ + + + + + + + + sd_event_source_get_event + systemd + + + + sd_event_source_get_event + 3 + + + + sd_event_source_get_event + + Retrieve the event loop of an event source + + + + + #include <systemd/sd-event.h> + + + sd_event* sd_event_source_get_event + sd_event_source *source + + + + + + + Description + + sd_event_source_get_event() may be used + to retrieve the event loop object the event source object specified + as source is associated with. The event + loop object is specified when creating an event source object with + calls such as + sd_event_add_io3 + or + sd_event_add_time3. + + + + Return Value + + On success, sd_event_source_get_event() + returns the associated event loop object. On failure, it returns + NULL. + + + + + + See Also + + + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_userdata3 + + + + diff --git a/man/sd_event_source_get_pending.xml b/man/sd_event_source_get_pending.xml new file mode 100644 index 00000000..603d4ad3 --- /dev/null +++ b/man/sd_event_source_get_pending.xml @@ -0,0 +1,137 @@ + + + + + + + + sd_event_source_get_pending + systemd + + + + sd_event_source_get_pending + 3 + + + + sd_event_source_get_pending + + Determine pending state of event sources + + + + + #include <systemd/sd-event.h> + + + int sd_event_source_get_pending + sd_event_source *source + + + + + + + Description + + sd_event_source_get_pending() may be + used to determine whether the event source object specified as + source has seen events but has not been + dispatched yet (and thus is marked "pending"). + + Event source objects initially are not marked pending, when + they are created with calls such as + sd_event_add_io3, + sd_event_add_time3, + with the exception of those created with + sd_event_add_defer3 + which are immediately marked pending, and + sd_event_add_exit3 + for which the "pending" concept is not defined. For details see + the respective manual pages. + + In each event loop iteration one event source of those + marked pending is dispatched, in the order defined by the event + source priority, as set with + sd_event_source_set_priority3. + + For I/O event sources, as created with + sd_event_add_io3, + the call + sd_event_source_get_io_revents3 + may be used to query the type of event pending in more + detail. + + + + + Return Value + + On success, sd_event_source_get_pending() returns an integer greater than zero + when the event source is marked pending, and zero when the event source is not marked pending. On + failure, it returns a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + source is not a valid pointer to an + sd_event_source object. + + + + -EDOM + + source refers to an event source object created with + sd_event_add_exit3. + + + + -ENOMEM + + Not enough memory. + + + + -ESTALE + + The event loop is already terminated. + + + + + -ECHILD + + The event loop has been created in a different process. + + + + + + + + + + + See Also + + + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_unref3 + + + + diff --git a/man/sd_event_source_set_description.xml b/man/sd_event_source_set_description.xml new file mode 100644 index 00000000..717cc5be --- /dev/null +++ b/man/sd_event_source_set_description.xml @@ -0,0 +1,140 @@ + + + + + + + + sd_event_source_set_description + systemd + + + + sd_event_source_set_description + 3 + + + + sd_event_source_set_description + sd_event_source_get_description + + Set or retrieve descriptive names of event sources + + + + + #include <systemd/sd-event.h> + + + int sd_event_source_set_description + sd_event_source *source + const char *description + + + + int sd_event_source_get_description + sd_event_source *source + const char **description + + + + + + + Description + + sd_event_source_set_description() may + be used to set an arbitrary descriptive name for the event source + object specified as source. This name will + be used in debugging messages generated by + sd-event3 + for this event source, and may be queried using + sd_event_source_get_description() for + debugging purposes. The description parameter shall + point to a NUL-terminated string or be + NULL. In the latter case, the descriptive + name will be unset. The string is copied internally, hence the + description argument is not referenced + after the function returns. + + sd_event_source_get_description() may + be used to query the current descriptive name assigned to the + event source object source. It returns a + pointer to the current name in description, + stored in memory internal to the event source. The memory is + invalidated when the event source is destroyed or the descriptive + name is changed. + + Event source objects generally have no description set when + they are created, except for UNIX signal event sources created + with + sd_event_add_signal3, + whose descriptive name is initialized to the signal's C constant + name (e.g. SIGINT or + SIGTERM). + + + + Return Value + + On success, sd_event_source_set_description() and + sd_event_source_get_description() return a non-negative integer. On failure, they + return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + source is not a valid pointer to an + sd_event_source object or the description argument + for sd_event_source_get_description() is NULL. + + + + + -ENOMEM + + Not enough memory to copy the name. + + + + -ECHILD + + The event loop has been created in a different process. + + + + + -ENXIO + + No name was set for the event source. + + + + + + + + + + See Also + + + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_userdata3 + + + + diff --git a/man/sd_event_source_set_destroy_callback.xml b/man/sd_event_source_set_destroy_callback.xml new file mode 100644 index 00000000..2ffca9ec --- /dev/null +++ b/man/sd_event_source_set_destroy_callback.xml @@ -0,0 +1,112 @@ + + + + + + + + sd_event_source_set_destroy_callback + systemd + + + + sd_event_source_set_destroy_callback + 3 + + + + sd_event_source_set_destroy_callback + sd_event_source_get_destroy_callback + sd_event_destroy_t + + Define the callback function for resource cleanup. + + + + + #include <systemd/sd-event.h> + + + typedef int (*sd_event_destroy_t) + void *userdata + + + + int sd_event_source_set_destroy_callback + sd_event_source *source + sd_event_destroy_t callback + + + + int sd_event_source_get_destroy_callback + sd_event_source *source + sd_event_destroy_t *callback + + + + + + + Description + + sd_event_source_set_destroy_callback() sets callback as the + callback function to be called right before the event source object source is + deallocated. The userdata pointer from the event source object will be passed as the + userdata parameter. This pointer can be set by an argument to the constructor functions, see + sd_event_add_io3, or directly, + see + sd_event_source_set_userdata3. + This callback function is called even if userdata is NULL. Note that + this callback is invoked at a time where the event source object itself is already invalidated, and executing + operations or taking new references to the event source object is not permissible. + + sd_event_source_get_destroy_callback() returns the current callback + for source in the callback parameter. + + + + Return Value + + On success, sd_event_source_set_destroy_callback() returns 0 or a positive + integer. On failure, it returns a negative errno-style error code. + + sd_event_source_get_destroy_callback() returns positive if the destroy + callback function is set, 0 if not. On failure, returns a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The source parameter is NULL. + + + + + + + + + + See Also + + + systemd1, + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_userdata3 + + + + diff --git a/man/sd_event_source_set_enabled.xml b/man/sd_event_source_set_enabled.xml new file mode 100644 index 00000000..6a7a39b4 --- /dev/null +++ b/man/sd_event_source_set_enabled.xml @@ -0,0 +1,154 @@ + + + + + + + + sd_event_source_set_enabled + systemd + + + + sd_event_source_set_enabled + 3 + + + + sd_event_source_set_enabled + sd_event_source_get_enabled + SD_EVENT_ON + SD_EVENT_OFF + SD_EVENT_ONESHOT + + Enable or disable event sources + + + + + #include <systemd/sd-event.h> + + enum { + SD_EVENT_OFF = 0, + SD_EVENT_ON = 1, + SD_EVENT_ONESHOT = -1, +}; + + + int sd_event_source_set_enabled + sd_event_source *source + int enabled + + + + int sd_event_source_get_enabled + sd_event_source *source + int *enabled + + + + + + + Description + + sd_event_source_set_enabled() may be + used to enable or disable the event source object specified as + source. The enabled + parameter takes one of SD_EVENT_ON (to + enable), SD_EVENT_OFF (to disable) or + SD_EVENT_ONESHOT. If invoked with + SD_EVENT_ONESHOT the event source will be + enabled but automatically reset to + SD_EVENT_OFF after the event source was + dispatched once. + + Event sources that are disabled will not result in event + loop wakeups and will not be dispatched, until they are enabled + again. + + sd_event_source_get_enabled() may be + used to query whether the event source object + source is currently enabled or not. It + returns the enablement state (one of SD_EVENT_ON, + SD_EVENT_OFF, SD_EVENT_ONESHOT) + in enabled, if it is not NULL. + It also returns true if the event source is not disabled. + + Event source objects are enabled when they are first created + with calls such as + sd_event_add_io3, + sd_event_add_time3. However, + depending on the event source type they are enabled continuously + (SD_EVENT_ON) or only for a single invocation + of the event source handler + (SD_EVENT_ONESHOT). For details see the + respective manual pages. + + As event source objects stay active and may be dispatched as + long as there is at least one reference to them, in many cases it + is a good idea to combine a call to + sd_event_source_unref3 + with a prior call to + sd_event_source_set_enabled() with + SD_EVENT_OFF, to ensure the event source is + not dispatched again until all other remaining references are dropped. + + + + Return Value + + On success, sd_event_source_set_enabled() returns a non-negative + integer. sd_event_source_get_enabled() returns zero if the source is disabled + (SD_EVENT_OFF) and a positive integer otherwise. On failure, they return a negative + errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + source is not a valid pointer to an + sd_event_source object. + + + + -ENOMEM + + Not enough memory. + + + + -ECHILD + + The event loop has been created in a different process. + + + + + + + + + + + See Also + + + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_unref3 + + + + diff --git a/man/sd_event_source_set_floating.xml b/man/sd_event_source_set_floating.xml new file mode 100644 index 00000000..89341d18 --- /dev/null +++ b/man/sd_event_source_set_floating.xml @@ -0,0 +1,118 @@ + + + + + + + + sd_event_source_set_floating + systemd + + + + sd_event_source_set_floating + 3 + + + + sd_event_source_set_floating + sd_event_source_get_floating + + Set or retrieve 'floating' state of event sources + + + + + #include <systemd/sd-event.h> + + + int sd_event_source_set_floating + sd_event_source *source + int floating + + + + int sd_event_source_get_floating + sd_event_source *source + + + + + + + Description + + sd_event_source_set_floating() takes a boolean and sets the 'floating' state + of the specified event source object. This is used to change the direction of reference counts for the + object and the event loop it is associated with. In non-floating mode, the event source object holds a + reference to the event loop object, but not vice versa. The creator of the event source object must hold + a reference to it as long as the source should exist. In floating mode, the event loop holds a reference + to the source object, and will decrease the reference count when being freed. This means that a reference + to the event loop should be held to prevent both from being destroyed. + + Various calls that allocate event source objects (i.e. + sd_event_add_io3, + sd_event_add_time3 and + similar) will automatically set an event source object to 'floating' mode if the caller passed + NULL in the parameter used to return a reference to the event source object. + Nevertheless, it may be necessary to gain temporary access to the source object, for example to adjust + event source properties after allocation (e.g. its priority or description string). In those cases the + object may be created in non-floating mode, and the returned reference used to adjust the properties, and + the object marked as floating afterwards, and the reference in the caller dropped. + + sd_event_source_get_floating() may be used to query the current 'floating' + state of the event source object source. It returns zero if 'floating' mode is + off, positive if it is on. + + + + Return Value + + On success, sd_event_source_set_floating() and + sd_event_source_get_floating() return a non-negative integer. On failure, they + return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + source is not a valid pointer to an + sd_event_source object. + + + + -ECHILD + + The event loop has been created in a different process. + + + + + + + + + + + See Also + + + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_description3, + sd_event_source_set_priority3 + + + + diff --git a/man/sd_event_source_set_prepare.xml b/man/sd_event_source_set_prepare.xml new file mode 100644 index 00000000..63c33ca1 --- /dev/null +++ b/man/sd_event_source_set_prepare.xml @@ -0,0 +1,142 @@ + + + + + + + + sd_event_source_set_prepare + systemd + + + + sd_event_source_set_prepare + 3 + + + + sd_event_source_set_prepare + + Set a preparation callback for event sources + + + + + #include <systemd/sd-event.h> + + + int sd_event_source_set_prepare + sd_event_source *source + sd_event_handler_t callback + + + + typedef int (*sd_event_handler_t) + sd_event_source *s + void *userdata + + + + + + + Description + + sd_event_source_set_prepare() may be + used to set a preparation callback for the event source object + specified as source. The callback function + specified as callback will be invoked + immediately before the event loop goes to sleep to wait for + incoming events. It is invoked with the user data pointer passed + when the event source was created. The event source will be disabled + if the callback function returns a negative error code. The callback + function may be used to reconfigure the precise events to wait for. + If the callback parameter is passed as NULL + the callback function is reset. + + Event source objects have no preparation callback associated + when they are first created with calls such as + sd_event_add_io3, + sd_event_add_time3. Preparation + callback functions are supported for all event source types with + the exception of those created with + sd_event_add_exit3. Preparation + callback functions are dispatched in the order indicated by the + event source's priority field, as set with + sd_event_source_set_priority3. Preparation + callbacks of disabled event sources (see + sd_event_source_set_enabled3) + are not invoked. + + + + Return Value + + On success, sd_event_source_set_prepare() returns a non-negative integer. On + failure, it returns a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + source is not a valid pointer to an + sd_event_source object. + + + + -ESTALE + + The event loop is already terminated. + + + + -ENOMEM + + Not enough memory. + + + + -ECHILD + + The event loop has been created in a different process. + + + + + -EDOM + + The specified event source has been created with + sd_event_add_exit3. + + + + + + + + + + + See Also + + + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_enabled3, + sd_event_source_set_priority3, + sd_event_source_set_userdata3 + + + + diff --git a/man/sd_event_source_set_priority.xml b/man/sd_event_source_set_priority.xml new file mode 100644 index 00000000..d1cb416d --- /dev/null +++ b/man/sd_event_source_set_priority.xml @@ -0,0 +1,166 @@ + + + + + + + + sd_event_source_set_priority + systemd + + + + sd_event_source_set_priority + 3 + + + + sd_event_source_set_priority + sd_event_source_get_priority + SD_EVENT_PRIORITY_IMPORTANT + SD_EVENT_PRIORITY_NORMAL + SD_EVENT_PRIORITY_IDLE + + Set or retrieve the priority of event sources + + + + + #include <systemd/sd-event.h> + + enum { + SD_EVENT_PRIORITY_IMPORTANT = -100, + SD_EVENT_PRIORITY_NORMAL = 0, + SD_EVENT_PRIORITY_IDLE = 100, +}; + + + int sd_event_source_set_priority + sd_event_source *source + int64_t priority + + + + int sd_event_source_get_priority + sd_event_source *source + int64_t *priority + + + + + + + Description + + sd_event_source_set_priority() may be + used to set the priority for the event source object specified as + source. The priority is specified as an + arbitrary signed 64bit integer. The priority is initialized to + SD_EVENT_PRIORITY_NORMAL (0) when the event + source is allocated with a call such as + sd_event_add_io3 + or + sd_event_add_time3, + and may be changed with this call. If multiple event sources have seen events at the same time, they are dispatched in the order indicated by the + event sources' priorities. Event sources with smaller priority + values are dispatched first. As well-known points of reference, + the constants SD_EVENT_PRIORITY_IMPORTANT + (-100), SD_EVENT_PRIORITY_NORMAL (0) and + SD_EVENT_PRIORITY_IDLE (100) may be used to + indicate event sources that shall be dispatched early, normally or + late. It is recommended to specify priorities based on these + definitions, and relative to them — however, the full 64bit + signed integer range is available for ordering event + sources. + + Priorities define the order in which event sources that have + seen events are dispatched. Care should be taken to ensure that + high-priority event sources (those with negative priority values + assigned) do not cause starvation of low-priority event sources + (those with positive priority values assigned). + + The order in which event sources with the same priority are + dispatched is undefined, but the event loop generally tries to + dispatch them in the order it learnt about events on them. As the + backing kernel primitives do not provide accurate information + about the order in which events occurred this is not necessarily + reliable. However, it is guaranteed that if events are seen on + multiple same-priority event sources at the same time, each one is + not dispatched again until all others have been dispatched + once. This behavior guarantees that within each priority + particular event sources do not starve or dominate the event + loop. + + The priority of event sources may be changed at any time of their lifetime, with the exception of inotify + event sources (i.e. those created with + sd_event_add_inotify3) whose + priority may only be changed in the time between their initial creation and the first subsequent event loop + iteration. + + sd_event_source_get_priority() may be + used to query the current priority assigned to the event source + object source. + + + + Return Value + + On success, sd_event_source_set_priority() and + sd_event_source_get_priority() return a non-negative integer. On failure, they + return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + source is not a valid pointer to an + sd_event_source object. + + + + -ENOMEM + + Not enough memory. + + + + -ESTALE + + The event loop is already terminated. + + + + + -ECHILD + + The event loop has been created in a different process. + + + + + + + + + + + See Also + + + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3 + + + + diff --git a/man/sd_event_source_set_userdata.xml b/man/sd_event_source_set_userdata.xml new file mode 100644 index 00000000..fe315845 --- /dev/null +++ b/man/sd_event_source_set_userdata.xml @@ -0,0 +1,93 @@ + + + + + + + + sd_event_source_set_userdata + systemd + + + + sd_event_source_set_userdata + 3 + + + + sd_event_source_set_userdata + sd_event_source_get_userdata + + Set or retrieve user data pointer of event sources + + + + + #include <systemd/sd-event.h> + + + void* sd_event_source_set_userdata + sd_event_source *source + void *userdata + + + + void* sd_event_source_get_userdata + sd_event_source *source + + + + + + + Description + + sd_event_source_set_userdata() may be + used to set an arbitrary user data pointer for the event source + object specified as source. The user data + pointer is usually specified when creating an event source object + with calls such as + sd_event_add_io3 + or + sd_event_add_time3, + and may be updated with this call. The user data pointer is also + passed to all handler callback functions associated with the event + source. The userdata parameter specifies + the new user data pointer to set, the function returns the + previous user data pointer. Note that NULL is + a valid user data pointer. + + sd_event_source_get_userdata() may be + used to query the current user data pointer assigned to the event + source object source. + + + + Return Value + + On success, + sd_event_source_set_userdata() and + sd_event_source_get_userdata() return the + previously set user data pointer. On failure, they return + NULL. + + + + + + See Also + + + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_description3 + + + + diff --git a/man/sd_event_source_unref.xml b/man/sd_event_source_unref.xml new file mode 100644 index 00000000..81131fa7 --- /dev/null +++ b/man/sd_event_source_unref.xml @@ -0,0 +1,136 @@ + + + + + + + + sd_event_source_unref + systemd + + + + sd_event_source_unref + 3 + + + + sd_event_source_unref + sd_event_source_unrefp + sd_event_source_ref + sd_event_source_disable_unref + sd_event_source_disable_unrefp + + Increase or decrease event source reference counters + + + + + #include <systemd/sd-event.h> + + + sd_event_source* sd_event_source_unref + sd_event_source *source + + + + void sd_event_source_unrefp + sd_event_source **source + + + + sd_event_source* sd_event_source_ref + sd_event_source *source + + + + sd_event_source* sd_event_source_disable_unref + sd_event_source *source + + + + void sd_event_source_disable_unrefp + sd_event_source **source + + + + + + Description + + sd_event_source_unref() may be used to + decrement by one the reference counter of the event source object + specified as source. The reference counter + is initially set to one, when the event source is created with calls + such as + sd_event_add_io3 + or + sd_event_add_time3. When + the reference counter reaches zero it is removed from its event loop + object and destroyed. + + sd_event_source_unrefp() is similar to + sd_event_source_unref() but takes a pointer to a + pointer to an sd_event_source object. This call is useful in + conjunction with GCC's and LLVM's Clean-up + Variable Attribute. Note that this function is defined as + inline function. + + sd_event_source_ref() may be used + to increase by one the reference counter of the event source object + specified as source. + + sd_event_source_unref(), + sd_bus_creds_unrefp() and + sd_bus_creds_ref() execute no operation if + the passed event source object is + NULL. + + Note that event source objects stay alive and may be dispatched as long as they have a reference + counter greater than zero. In order to drop a reference of an event source and make sure the associated + event source handler function is not called anymore it is recommended to combine a call of + sd_event_source_unref() with a prior call to + sd_event_source_set_enabled() with SD_EVENT_OFF or call + sd_event_source_disable_unref(), see below. + + sd_event_source_disable_unref() combines a call to + sd_event_source_set_enabled() with SD_EVENT_OFF with + sd_event_source_unref(). This ensures that the source is disabled before the local + reference to it is lost. The source parameter is allowed to be + NULL. + + sd_event_source_disable_unrefp() is similar to + sd_event_source_unrefp(), but in addition disables the source first. This call is + useful in conjunction with GCC's and LLVM's + Clean-up Variable + Attribute. Note that this function is defined as inline function. + + + + Return Value + + sd_event_source_unref() and + sd_event_source_disable_unref() always return NULL. + sd_event_source_ref() always returns the event source object passed in. + + + + + + See Also + + + sd-event3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_source_set_enabled3 + + + + diff --git a/man/sd_event_wait.xml b/man/sd_event_wait.xml new file mode 100644 index 00000000..210a0c94 --- /dev/null +++ b/man/sd_event_wait.xml @@ -0,0 +1,324 @@ + + + + + + + + sd_event_wait + systemd + + + + sd_event_wait + 3 + + + + sd_event_wait + sd_event_prepare + sd_event_dispatch + sd_event_get_state + sd_event_get_iteration + SD_EVENT_INITIAL + SD_EVENT_PREPARING + SD_EVENT_ARMED + SD_EVENT_PENDING + SD_EVENT_RUNNING + SD_EVENT_EXITING + SD_EVENT_FINISHED + + Low-level event loop operations + + + + + #include <systemd/sd-event.h> + + enum { + SD_EVENT_INITIAL, + SD_EVENT_PREPARING, + SD_EVENT_ARMED, + SD_EVENT_PENDING, + SD_EVENT_RUNNING, + SD_EVENT_EXITING, + SD_EVENT_FINISHED, +}; + + + int sd_event_prepare + sd_event *event + + + + int sd_event_wait + sd_event *event + uint64_t usec + + + + int sd_event_dispatch + sd_event *event + + + + int sd_event_get_state + sd_event *event + + + + int sd_event_get_iteration + sd_event *event + uint64_t *ret + + + + + + + Description + + The low-level sd_event_prepare(), + sd_event_wait() and + sd_event_dispatch() functions may be used to + execute specific phases of an event loop. See + sd_event_run3 + and + sd_event_loop3 + for higher-level functions that execute individual but complete + iterations of an event loop or run it continuously. + + sd_event_prepare() checks for pending + events and arms necessary timers. If any events are ready to be + processed ("pending"), it returns a positive, non-zero value, and the caller + should process these events with + sd_event_dispatch(). + + sd_event_dispatch() dispatches the + highest priority event source that has a pending event. On + success, sd_event_dispatch() returns either + zero, which indicates that no further event sources may be + dispatched and exiting of the event loop was requested via + sd_event_exit3; + or a positive non-zero value, which means that an event source was + dispatched and the loop returned to its initial state, and the + caller should initiate the next event loop iteration by invoking + sd_event_prepare() again. + + In case sd_event_prepare() returned + zero, sd_event_wait() should be called to + wait for further events or a timeout. If any events are ready to + be processed, it returns a positive, non-zero value, and the + events should be dispatched with + sd_event_dispatch(). Otherwise, the event + loop returned to its initial state and the next event loop + iteration should be initiated by invoking + sd_event_prepare() again. + + sd_event_get_state() may be used to + determine the state the event loop is currently in. It returns one + of the states described below. + + sd_event_get_iteration() may be used to determine the current iteration of the event + loop. It returns an unsigned 64bit integer containing a counter that increases monotonically with each iteration of + the event loop, starting with 0. The counter is increased at the time of the + sd_event_prepare() invocation. + + All five functions take, as the first argument, the event loop object event that has + been created with sd_event_new(). The timeout for sd_event_wait() is + specified in usec in microseconds. (uint64_t) -1 may be used to + specify an infinite timeout. + + + + State Machine + + The event loop knows the following states, that may be + queried with sd_event_get_state(). + + + + SD_EVENT_INITIAL + + The initial state the event loop is in, + before each event loop iteration. Use + sd_event_prepare() to transition the + event loop into the SD_EVENT_ARMED or + SD_EVENT_PENDING states. + + + + SD_EVENT_PREPARING + + An event source is currently being prepared, + i.e. the preparation handler is currently being executed, as + set with + sd_event_source_set_prepare3. This + state is only seen in the event source preparation handler + that is invoked from the + sd_event_prepare() call and is + immediately followed by SD_EVENT_ARMED or + SD_EVENT_PENDING. + + + + SD_EVENT_ARMED + + sd_event_prepare() has + been called and no event sources were ready to be + dispatched. Use sd_event_wait() to wait + for new events, and transition into + SD_EVENT_PENDING or back into + SD_EVENT_INITIAL. + + + + SD_EVENT_PENDING + + sd_event_prepare() or + sd_event_wait() have been called and + there were event sources with events pending. Use + sd_event_dispatch() to dispatch the + highest priority event source and transition back to + SD_EVENT_INITIAL, or + SD_EVENT_FINISHED. + + + + SD_EVENT_RUNNING + + A regular event source is currently being + dispatched. This state is only seen in the event source + handler that is invoked from the + sd_event_dispatch() call, and is + immediately followed by SD_EVENT_INITIAL + or SD_EVENT_FINISHED as soon the event + source handler returns. Note that during dispatching of exit + event sources the SD_EVENT_EXITING state + is seen instead. + + + + SD_EVENT_EXITING + + Similar to + SD_EVENT_RUNNING but is the state in + effect while dispatching exit event sources. It is followed by + SD_EVENT_INITIAL or + SD_EVENT_FINISHED as soon as the event + handler returns. + + + + SD_EVENT_FINISHED + + The event loop has exited. All exit event + sources have run. If the event loop is in this state it serves + no purpose anymore, and should be freed. + + + + + A simplified flow chart of the states and the calls to + transition between them is shown below. Note that + SD_EVENT_PREPARING, + SD_EVENT_RUNNING and + SD_EVENT_EXITING are not shown here. + + + INITIAL -<---<---<---<---<---<---<---<---<---<---<---<---\ + | | + | ^ + | | + v ret == 0 | + sd_event_prepare() >--->--->--->--->- ARMED | + | | ^ + | ret > 0 | | + | | | + v v ret == 0 | + PENDING <---<---<---<---<---< sd_event_wait() >--->--->--+ + | ret > 0 ^ + | | + | | + v | + sd_event_dispatch() >--->--->--->--->--->--->--->--->--->--->/ + | ret > 0 + | ret == 0 + | + v + FINISHED + + + + + Return Value + + On success, these functions return 0 or a positive integer. On failure, they return a negative + errno-style error code. In case of sd_event_prepare() and + sd_event_wait(), a positive, non-zero return code indicates that events are ready to + be processed and zero indicates that no events are ready. In case of + sd_event_dispatch(), a positive, non-zero return code indicates that the event loop + returned to its initial state and zero indicates the event loop has + exited. sd_event_get_state() returns a positive or zero state on success. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + The event parameter is invalid or NULL. + + + + + -EBUSY + + The event loop object is not in the right state. + + + + -ESTALE + + The event loop is already terminated. + + + + + -ECHILD + + The event loop has been created in a different process. + + + + + + Other errors are possible, too. + + + + + + + See Also + + + systemd1, + sd_event_new3, + sd_event_add_io3, + sd_event_add_time3, + sd_event_add_signal3, + sd_event_add_child3, + sd_event_add_inotify3, + sd_event_add_defer3, + sd_event_run3, + sd_event_get_fd3, + sd_event_source_set_prepare3 + + + + diff --git a/man/sd_get_seats.xml b/man/sd_get_seats.xml new file mode 100644 index 00000000..ed4b77b3 --- /dev/null +++ b/man/sd_get_seats.xml @@ -0,0 +1,118 @@ + + + + + + + + sd_get_seats + systemd + + + + sd_get_seats + 3 + + + + sd_get_seats + sd_get_sessions + sd_get_uids + sd_get_machine_names + Determine available seats, sessions, logged in users and virtual machines/containers + + + + + #include <systemd/sd-login.h> + + + int sd_get_seats + char ***seats + + + + int sd_get_sessions + char ***sessions + + + + int sd_get_uids + uid_t **users + + + + int sd_get_machine_names + char ***machines + + + + + + + Description + + sd_get_seats() may be used to determine + all currently available local seats. Returns the number of seat + identifiers and if the input pointer is non-NULL, a + NULL-terminated array of seat identifiers + is stored at the address. + The returned array and all strings it references need to be freed + with the libc + free3 + call after use. Note that instead of an empty array + NULL may be returned and should be considered + equivalent to an empty array. + + Similarly, sd_get_sessions() may be + used to determine all current login sessions. + + Similarly, sd_get_uids() may be used to + determine all Unix users who currently have login sessions. + + Similarly, sd_get_machine_names() may + be used to determine all current virtual machines and containers + on the system. + + Note that the returned lists are not sorted and in an + undefined order. + + + + Return Value + + On success, sd_get_seats(), sd_get_sessions(), + sd_get_uids() and sd_get_machine_names() return the number of + entries in the arrays. On failure, these calls return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-login3, + sd_session_get_seat3 + + + + diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml new file mode 100644 index 00000000..e665f734 --- /dev/null +++ b/man/sd_id128_get_machine.xml @@ -0,0 +1,208 @@ + + + + + + + + sd_id128_get_machine + systemd + + + + sd_id128_get_machine + 3 + + + + sd_id128_get_machine + sd_id128_get_machine_app_specific + sd_id128_get_boot + sd_id128_get_boot_app_specific + sd_id128_get_invocation + Retrieve 128-bit IDs + + + + + #include <systemd/sd-id128.h> + + + int sd_id128_get_machine + sd_id128_t *ret + + + + int sd_id128_get_machine_app_specific + sd_id128_t app_id + sd_id128_t *ret + + + + int sd_id128_get_boot + sd_id128_t *ret + + + + int sd_id128_get_boot_app_specific + sd_id128_t app_id + sd_id128_t *ret + + + + int sd_id128_get_invocation + sd_id128_t *ret + + + + + + + Description + + sd_id128_get_machine() returns the machine ID of the executing host. This reads and + parses the machine-id5 + file. This function caches the machine ID internally to make retrieving the machine ID a cheap operation. This ID + may be used wherever a unique identifier for the local system is needed. However, it is recommended to use this ID + as-is only in trusted environments. In untrusted environments it is recommended to derive an application specific + ID from this machine ID, in an irreversable (cryptographically secure) way. To make this easy + sd_id128_get_machine_app_specific() is provided, see below. + + sd_id128_get_machine_app_specific() is similar to + sd_id128_get_machine(), but retrieves a machine ID that is specific to the application that is + identified by the indicated application ID. It is recommended to use this function instead of + sd_id128_get_machine() when passing an ID to untrusted environments, in order to make sure + that the original machine ID may not be determined externally. This way, the ID used by the application remains + stable on a given machine, but cannot be easily correlated with IDs used in other applications on the same + machine. The application-specific ID should be generated via a tool like systemd-id128 new, + and may be compiled into the application. This function will return the same application-specific ID for each + combination of machine ID and application ID. Internally, this function calculates HMAC-SHA256 of the application + ID, keyed by the machine ID. + + sd_id128_get_boot() returns the boot ID of the executing kernel. This reads and parses + the /proc/sys/kernel/random/boot_id file exposed by the kernel. It is randomly generated early + at boot and is unique for every running kernel instance. See random4 for more + information. This function also internally caches the returned ID to make this call a cheap operation. It is + recommended to use this ID as-is only in trusted environments. In untrusted environments it is recommended to + derive an application specific ID using sd_id128_get_machine_app_specific(), see below. + + sd_id128_get_boot_app_specific() is analogous to + sd_id128_get_machine_app_specific() but returns an ID that changes between boots. Some + machines may be used for a long time without rebooting, hence the boot ID may remain constant for a long time, and + has properties similar to the machine ID during that time. + + sd_id128_get_invocation() returns the invocation ID of the currently executed + service. In its current implementation, this reads and parses the $INVOCATION_ID environment + variable that the service manager sets when activating a service, see + systemd.exec5 for details. The + ID is cached internally. In future a different mechanism to determine the invocation ID may be added. + + Note that sd_id128_get_machine_app_specific(), sd_id128_get_boot(), + sd_id128_get_boot_app_specific(), and sd_id128_get_invocation() always + return UUID v4 compatible IDs. sd_id128_get_machine() will also return a UUID v4-compatible + ID on new installations but might not on older. It is possible to convert the machine ID into a UUID v4-compatible + one. For more information, see + machine-id5. + + For more information about the sd_id128_t + type see + sd-id1283. + + + + Return Value + + Those calls return 0 on success (in which case ret is filled in), + or a negative errno-style error code. + + + Errors + Returned errors may indicate the following problems: + + + + -ENOENT + + Returned by sd_id128_get_machine(), + sd_id128_get_machine_app_specific(), and + sd_id128_get_boot_app_specific() when /etc/machine-id is + missing. + + + + -ENOMEDIUM + + Returned by sd_id128_get_machine(), + sd_id128_get_machine_app_specific(), and + sd_id128_get_boot_app_specific() when /etc/machine-id is + empty or all zeros. + + + + -ENXIO + + Returned by sd_id128_get_invocation() if no invocation ID is + set. + + + + -EIO + + Returned by any of the functions described here when the configured value has + invalid format. + + + + -EPERM + + Requested information could not be retrieved because of insufficient permissions. + + + + + + + + + + Examples + + + Application-specific machine ID + + First, generate the application ID: + $ systemd-id128 -p new +As string: +c273277323db454ea63bb96e79b53e97 + +As UUID: +c2732773-23db-454e-a63b-b96e79b53e97 + +As man:sd-id128(3) macro: +#define MESSAGE_XYZ SD_ID128_MAKE(c2,73,27,73,23,db,45,4e,a6,3b,b9,6e,79,b5,3e,97) +... + + + Then use the new identifier in an example application: + + + + + + + See Also + + + systemd1, + systemd-id1281, + sd-id1283, + machine-id5, + systemd.exec5, + sd_id128_randomize3, + random4 + + + + diff --git a/man/sd_id128_randomize.xml b/man/sd_id128_randomize.xml new file mode 100644 index 00000000..9cf55dda --- /dev/null +++ b/man/sd_id128_randomize.xml @@ -0,0 +1,79 @@ + + + + + + + + sd_id128_randomize + systemd + + + + sd_id128_randomize + 3 + + + + sd_id128_randomize + Generate 128-bit IDs + + + + + #include <systemd/sd-id128.h> + + + int sd_id128_randomize + sd_id128_t *ret + + + + + + + Description + + sd_id128_randomize() generates a new + randomized 128-bit ID and returns it in + ret. Every invocation returns a new + randomly generated ID. This uses the + /dev/urandom kernel random number + generator. + + Note that sd_id128_randomize() always + returns a UUID v4-compatible ID. + + For more information about the sd_id128_t + type, see + sd-id1283. + + systemd-id1281's + new command may be used as a command line front-end for + sd_id128_randomize(). + + + + Return Value + + The call returns 0 on success (in which case + ret is filled in), or a negative + errno-style error code. + + + + + + See Also + + + systemd1, + sd-id1283, + machine-id5, + random4, + sd_id128_get_machine3 + + + + diff --git a/man/sd_id128_to_string.xml b/man/sd_id128_to_string.xml new file mode 100644 index 00000000..4f585e35 --- /dev/null +++ b/man/sd_id128_to_string.xml @@ -0,0 +1,94 @@ + + + + + + + + sd_id128_to_string + systemd + + + + sd_id128_to_string + 3 + + + + sd_id128_to_string + sd_id128_from_string + Format or parse 128-bit IDs as strings + + + + + #include <systemd/sd-id128.h> + + + char *sd_id128_to_string + sd_id128_t id, char s[33] + + + + int sd_id128_from_string + const char *s, sd_id128_t *ret + + + + + + + Description + + sd_id128_to_string() formats a 128-bit + ID as a character string. It expects the ID and a string array + capable of storing 33 characters. The ID will be formatted as 32 + lowercase hexadecimal digits and be terminated by a + NUL byte. + + sd_id128_from_string() implements the reverse operation: it takes a 33 character string + with 32 hexadecimal digits (either lowercase or uppercase, terminated by NUL) and parses them + back into a 128-bit ID returned in ret. Alternatively, this call can also parse a + 37-character string with a 128-bit ID formatted as RFC UUID. If ret is passed as NULL the + function will validate the passed ID string, but not actually return it in parsed form. + + For more information about the sd_id128_t + type see + sd-id1283. + Note that these calls operate the same way on all architectures, + i.e. the results do not depend on endianness. + + When formatting a 128-bit ID into a string, it is often + easier to use a format string for + printf3. + This is easily done using the + SD_ID128_FORMAT_STR and + SD_ID128_FORMAT_VAL() macros. For more + information see + sd-id1283. + + + + Return Value + + sd_id128_to_string() always succeeds + and returns a pointer to the string array passed in. + sd_id128_from_string returns 0 on success, in + which case ret is filled in, or a negative + errno-style error code. + + + + + + See Also + + + systemd1, + sd-id1283, + printf3 + + + + diff --git a/man/sd_is_fifo.xml b/man/sd_is_fifo.xml new file mode 100644 index 00000000..26a0db12 --- /dev/null +++ b/man/sd_is_fifo.xml @@ -0,0 +1,201 @@ + + + + + + + + sd_is_fifo + systemd + + + + sd_is_fifo + 3 + + + + sd_is_fifo + sd_is_socket + sd_is_socket_inet + sd_is_socket_unix + sd_is_socket_sockaddr + sd_is_mq + sd_is_special + Check the type of a file descriptor + + + + + #include <systemd/sd-daemon.h> + + + int sd_is_fifo + int fd + const char *path + + + + int sd_is_socket + int fd + int family + int type + int listening + + + + int sd_is_socket_inet + int fd + int family + int type + int listening + uint16_t port + + + + int sd_is_socket_sockaddr + int fd + int type + const struct sockaddr *addr + unsigned addr_len + int listening + + + + int sd_is_socket_unix + int fd + int type + int listening + const char *path + size_t length + + + + int sd_is_mq + int fd + const char *path + + + + int sd_is_special + int fd + const char *path + + + + + + + Description + + sd_is_fifo() may be called to check + whether the specified file descriptor refers to a FIFO or pipe. If + the path parameter is not + NULL, it is checked whether the FIFO is bound + to the specified file system path. + + sd_is_socket() may be called to check + whether the specified file descriptor refers to a socket. If the + family parameter is not + AF_UNSPEC, it is checked whether the socket + is of the specified family (AF_UNIX, + AF_INET, …). If the type + parameter is not 0, it is checked whether the socket is of the + specified type (SOCK_STREAM, + SOCK_DGRAM, …). If the + listening parameter is positive, it is + checked whether the socket is in accepting mode, i.e. + listen() has been called for it. If + listening is 0, it is checked whether the + socket is not in this mode. If the parameter is negative, no such + check is made. The listening parameter + should only be used for stream sockets and should be set to a + negative value otherwise. + + sd_is_socket_inet() is similar to + sd_is_socket(), but optionally checks the + IPv4 or IPv6 port number the socket is bound to, unless + port is zero. For this call + family must be passed as either + AF_UNSPEC, AF_INET, or + AF_INET6. + + sd_is_socket_sockaddr() is similar to + sd_is_socket_inet(), but checks if the socket is bound to the + address specified by addr. The + family specified by addr must be + either AF_INET or AF_INET6 and + addr_len must be large enough for that family. If + addr specifies a non-zero port, it is also checked if the + socket is bound to this port. In addition, for IPv6, if addr + specifies non-zero sin6_flowinfo or + sin6_scope_id, it is checked if the socket has the same + values. + + sd_is_socket_unix() is similar to + sd_is_socket() but optionally checks the + AF_UNIX path the socket is bound to, unless + the path parameter is + NULL. For normal file system + AF_UNIX sockets, set the + length parameter to 0. For Linux abstract + namespace sockets, set the length to the + size of the address, including the initial 0 byte, and set the + path to the initial 0 byte of the socket + address. + + sd_is_mq() may be called to check + whether the specified file descriptor refers to a POSIX message + queue. If the path parameter is not + NULL, it is checked whether the message queue + is bound to the specified name. + + sd_is_special() may be called to check + whether the specified file descriptor refers to a special file. If + the path parameter is not + NULL, it is checked whether the file + descriptor is bound to the specified filename. Special files in + this context are character device nodes and files in + /proc or /sys. + + + + Return Value + + On failure, these calls return a negative errno-style error + code. If the file descriptor is of the specified type and bound to + the specified address, a positive return value is returned, + otherwise zero. + + + + Notes + + + + Internally, these function use a combination of + fstat() and + getsockname() to check the file descriptor + type and where it is bound to. + + + + See Also + + systemd1, + sd-daemon3, + sd_listen_fds3, + systemd.service5, + systemd.socket5, + ip7, + ipv67, + unix7, + fifo7, + mq_overview7, + socket7. + + + + diff --git a/man/sd_journal_add_match.xml b/man/sd_journal_add_match.xml new file mode 100644 index 00000000..83f7fe92 --- /dev/null +++ b/man/sd_journal_add_match.xml @@ -0,0 +1,177 @@ + + + + + + + + sd_journal_add_match + systemd + + + + sd_journal_add_match + 3 + + + + sd_journal_add_match + sd_journal_add_disjunction + sd_journal_add_conjunction + sd_journal_flush_matches + Add or remove entry matches + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_add_match + sd_journal *j + const void *data + size_t size + + + + int sd_journal_add_disjunction + sd_journal *j + + + + int sd_journal_add_conjunction + sd_journal *j + + + + void sd_journal_flush_matches + sd_journal *j + + + + + + Description + + sd_journal_add_match() adds a match by + which to filter the entries of the journal file. Matches applied + with this call will filter what can be iterated through and read + from the journal file via calls like + sd_journal_next3 + and + sd_journal_get_data3. + Parameter data must be of the form + FIELD=value, + where the FIELD part is a short uppercase string consisting only + of 0–9, A–Z and the underscore; it may not begin with two underscores or be the empty + string. The value part may be anything, including binary. Parameter + size specifies the number of bytes in data + (i.e. the length of FIELD, plus one, plus the length of + value). Parameter size may also be + specified as 0, in which case data + must be a NUL-terminated string, and the bytes before the terminating + zero are used as the match. + + If a match is applied, only entries with this field set + will be iterated. Multiple matches may be active at the same time: + If they apply to different fields, only entries with both fields + set like this will be iterated. If they apply to the same fields, + only entries where the field takes one of the specified values + will be iterated. Well known fields are documented in + systemd.journal-fields7. + Whenever a new match is added the current entry position is reset, + and + sd_journal_next3 + (or a similar call) needs to be called before entries can be read + again. + + sd_journal_add_disjunction() may be + used to insert a disjunction (i.e. logical OR) in the match list. + If this call is invoked, all previously added matches since the + last invocation of + sd_journal_add_disjunction() or + sd_journal_add_conjunction() are combined in + an OR with all matches added afterwards, until + sd_journal_add_disjunction() or + sd_journal_add_conjunction() is invoked again + to begin the next OR or AND term. + + sd_journal_add_conjunction() may be + used to insert a conjunction (i.e. logical AND) in the match list. + If this call is invoked, all previously added matches since the + last invocation of + sd_journal_add_conjunction() are combined in + an AND with all matches added afterwards, until + sd_journal_add_conjunction() is invoked again + to begin the next AND term. The combination of + sd_journal_add_match(), + sd_journal_add_disjunction() and + sd_journal_add_conjunction() may be used to + build complex search terms, even though full logical expressions + are not available. Note that + sd_journal_add_conjunction() operates one + level 'higher' than + sd_journal_add_disjunction(). It is hence + possible to build an expression of AND terms, consisting of OR + terms, consisting of AND terms, consisting of OR terms of matches + (the latter OR expression is implicitly created for matches with + the same field name, see above). + + sd_journal_flush_matches() may be used + to flush all matches, disjunction and conjunction terms again. + After this call all filtering is removed and all entries in the + journal will be iterated again. + + Note that filtering via matches only applies to the way the + journal is read, it has no effect on storage on disk. + + + + Return Value + + sd_journal_add_match(), + sd_journal_add_disjunction() and + sd_journal_add_conjunction() + return 0 on success or a negative errno-style error + code. sd_journal_flush_matches() + returns nothing. + + + + + + Examples + + The following example adds matches to a journal context + object to iterate only through messages generated by the Avahi + service at the four error log levels, plus all messages of the + message ID 03bb1dab98ab4ecfbf6fff2738bdd964 coming from any + service (this example lacks the necessary error checking): + + … +int add_matches(sd_journal *j) { + sd_journal_add_match(j, "_SYSTEMD_UNIT=avahi-daemon.service", 0); + sd_journal_add_match(j, "PRIORITY=0", 0); + sd_journal_add_match(j, "PRIORITY=1", 0); + sd_journal_add_match(j, "PRIORITY=2", 0); + sd_journal_add_match(j, "PRIORITY=3", 0); + sd_journal_add_disjunction(j); + sd_journal_add_match(j, "MESSAGE_ID=03bb1dab98ab4ecfbf6fff2738bdd964", 0); +} + + + + See Also + + + systemd1, + sd-journal3, + sd_journal_open3, + sd_journal_next3, + sd_journal_get_data3, + systemd.journal-fields7 + + + + diff --git a/man/sd_journal_enumerate_fields.xml b/man/sd_journal_enumerate_fields.xml new file mode 100644 index 00000000..791d1c74 --- /dev/null +++ b/man/sd_journal_enumerate_fields.xml @@ -0,0 +1,133 @@ + + + + + + + + sd_journal_enumerate_fields + systemd + + + + sd_journal_enumerate_fields + 3 + + + + sd_journal_enumerate_fields + sd_journal_restart_fields + SD_JOURNAL_FOREACH_FIELD + Read used field names from the journal + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_enumerate_fields + sd_journal *j + const char **field + + + + void sd_journal_restart_fields + sd_journal *j + + + + SD_JOURNAL_FOREACH_FIELD + sd_journal *j + const char *field + + + + + + + Description + + sd_journal_enumerate_fields() may be used to iterate through all field names used in the + opened journal files. On each invocation the next field name is returned. The order of the returned field names is + not defined. It takes two arguments: the journal context object, plus a pointer to a constant string pointer where + the field name is stored in. The returned data is in a read-only memory map and is only valid until the next + invocation of sd_journal_enumerate_fields(). Note that this call is subject to the data field + size threshold as controlled by sd_journal_set_data_threshold(). + + sd_journal_restart_fields() resets the field name enumeration index to the beginning of + the list. The next invocation of sd_journal_enumerate_fields() will return the first field + name again. + + The SD_JOURNAL_FOREACH_FIELD() macro may be used as a handy wrapper around + sd_journal_restart_fields() and sd_journal_enumerate_fields(). + + These functions currently are not influenced by matches set with sd_journal_add_match() + but this might change in a later version of this software. + + To retrieve the possible values a specific field can take use + sd_journal_query_unique3. + + + + Return Value + + sd_journal_enumerate_fields() returns a + positive integer if the next field name has been read, 0 when no + more field names are known, or a negative errno-style error code. + sd_journal_restart_fields() returns + nothing. + + + + Notes + + + + + + + + Examples + + Use the SD_JOURNAL_FOREACH_FIELD macro to iterate through all field names in use in the + current journal. + + #include <stdio.h> +#include <string.h> +#include <systemd/sd-journal.h> + +int main(int argc, char *argv[]) { + sd_journal *j; + const char *field; + int r; + + r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); + if (r < 0) { + fprintf(stderr, "Failed to open journal: %s\n", strerror(-r)); + return 1; + } + SD_JOURNAL_FOREACH_FIELD(j, field) + printf("%s\n", field); + sd_journal_close(j); + return 0; +} + + + + + See Also + + + systemd1, + systemd.journal-fields7, + sd-journal3, + sd_journal_open3, + sd_journal_query_unique3, + sd_journal_get_data3, + sd_journal_add_match3 + + + + diff --git a/man/sd_journal_get_catalog.xml b/man/sd_journal_get_catalog.xml new file mode 100644 index 00000000..8c7058a1 --- /dev/null +++ b/man/sd_journal_get_catalog.xml @@ -0,0 +1,113 @@ + + + + + + + + sd_journal_get_catalog + systemd + + + + sd_journal_get_catalog + 3 + + + + sd_journal_get_catalog + sd_journal_get_catalog_for_message_id + Retrieve message catalog entry + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_get_catalog + sd_journal *j + char **ret + + + + int sd_journal_get_catalog_for_message_id + sd_id128_t id + char **ret + + + + + + + Description + + sd_journal_get_catalog() retrieves a + message catalog entry for the current journal entry. This will + look up an entry in the message catalog by using the + MESSAGE_ID= field of the current journal entry. + Before returning the entry all journal field names in the catalog + entry text enclosed in "@" will be replaced by the respective + field values of the current entry. If a field name referenced in + the message catalog entry does not exist, in the current journal + entry, the "@" will be removed, but the field name otherwise left + untouched. + + sd_journal_get_catalog_for_message_id() + works similar to sd_journal_get_catalog() but + the entry is looked up by the specified message ID (no open + journal context is necessary for this), and no field substitution + is performed. + + For more information about the journal message catalog + please refer to the Journal + Message Catalogs documentation page. + + + + Return Value + + sd_journal_get_catalog() and + sd_journal_get_catalog_for_message_id() + return 0 on success or a negative errno-style error code. If no + matching message catalog entry is found, -ENOENT is + returned. + + On successful return, ret points to a + new string, which must be freed with + free3. + + + + + Notes + + Function sd_journal_get_catalog() is thread-agnostic and only + a single specific thread may operate on a given object during its entire lifetime. It's safe to allocate multiple + independent objects and use each from a specific thread in parallel. However, it's not safe to allocate such an + object in one thread, and operate or free it from any other, even if locking is used to ensure these threads don't + operate on it at the very same time. + + Function sd_journal_get_catalog_for_message_id() is are thread-safe and may be called in + parallel from multiple threads. + + + + + + See Also + + + systemd1, + systemd.journal-fields7, + sd-journal3, + sd_journal_open3, + sd_journal_next3, + sd_journal_get_data3, + malloc3 + + + + diff --git a/man/sd_journal_get_cursor.xml b/man/sd_journal_get_cursor.xml new file mode 100644 index 00000000..851bfde8 --- /dev/null +++ b/man/sd_journal_get_cursor.xml @@ -0,0 +1,114 @@ + + + + + + + + sd_journal_get_cursor + systemd + + + + sd_journal_get_cursor + 3 + + + + sd_journal_get_cursor + sd_journal_test_cursor + Get cursor string for or test cursor string against the current journal entry + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_get_cursor + sd_journal *j + char **cursor + + + + int sd_journal_test_cursor + sd_journal *j + const char *cursor + + + + + + + Description + + sd_journal_get_cursor() returns a + cursor string for the current journal entry. A cursor is a + serialization of the current journal position formatted as text. + The string only contains printable characters and can be passed + around in text form. The cursor identifies a journal entry + globally and in a stable way and may be used to later seek to it + via + sd_journal_seek_cursor3. + The cursor string should be considered opaque and not be parsed by + clients. Seeking to a cursor position without the specific entry + being available locally will seek to the next closest (in terms of + time) available entry. The call takes two arguments: a journal + context object and a pointer to a string pointer where the cursor + string will be placed. The string is allocated via libc + malloc3 + and should be freed after use with + free3. + + Note that sd_journal_get_cursor() will + not work before + sd_journal_next3 + (or related call) has been called at least once, in order to + position the read pointer at a valid entry. + + sd_journal_test_cursor() + may be used to check whether the current position in + the journal matches the specified cursor. This is + useful since cursor strings do not uniquely identify + an entry: the same entry might be referred to by + multiple different cursor strings, and hence string + comparing cursors is not possible. Use this call to + verify after an invocation of + sd_journal_seek_cursor3 + whether the entry being sought to was actually found + in the journal or the next closest entry was used + instead. + + + + Return Value + + sd_journal_get_cursor() returns 0 on + success or a negative errno-style error code. + sd_journal_test_cursor() returns positive if + the current entry matches the specified cursor, 0 if it does not + match the specified cursor or a negative errno-style error code on + failure. + + + + Notes + + + + + + + + See Also + + + systemd1, + sd-journal3, + sd_journal_open3, + sd_journal_seek_cursor3 + + + + diff --git a/man/sd_journal_get_cutoff_realtime_usec.xml b/man/sd_journal_get_cutoff_realtime_usec.xml new file mode 100644 index 00000000..a76855fe --- /dev/null +++ b/man/sd_journal_get_cutoff_realtime_usec.xml @@ -0,0 +1,114 @@ + + + + + + + + sd_journal_get_cutoff_realtime_usec + systemd + + + + sd_journal_get_cutoff_realtime_usec + 3 + + + + sd_journal_get_cutoff_realtime_usec + sd_journal_get_cutoff_monotonic_usec + Read cut-off timestamps from the current journal entry + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_get_cutoff_realtime_usec + sd_journal *j + uint64_t *from + uint64_t *to + + + + int sd_journal_get_cutoff_monotonic_usec + sd_journal *j + sd_id128_t boot_id + uint64_t *from + uint64_t *to + + + + + + + Description + + sd_journal_get_cutoff_realtime_usec() + retrieves the realtime (wallclock) timestamps of the first and + last entries accessible in the journal. It takes three arguments: + the journal context object j and two + pointers from and to + pointing at 64-bit unsigned integers to store the timestamps in. + The timestamps are in microseconds since the epoch, i.e. + CLOCK_REALTIME. Either one of the two + timestamp arguments may be passed as NULL in + case the timestamp is not needed, but not both. + + sd_journal_get_cutoff_monotonic_usec() + retrieves the monotonic timestamps of the first and last entries + accessible in the journal. It takes three arguments: the journal + context object j, a 128-bit identifier for + the boot boot_id, and two pointers to + 64-bit unsigned integers to store the timestamps, + from and to. The + timestamps are in microseconds since boot-up of the specific boot, + i.e. CLOCK_MONOTONIC. Since the monotonic + clock begins new with every reboot it only defines a well-defined + point in time when used together with an identifier identifying + the boot, see + sd_id128_get_boot3 + for more information. The function will return the timestamps for + the boot identified by the passed boot ID. Either one of the two + timestamp arguments may be passed as NULL in + case the timestamp is not needed, but not both. + + + + Return Value + + sd_journal_get_cutoff_realtime_usec() + and sd_journal_get_cutoff_monotonic_usec() + return 1 on success, 0 if not suitable entries are in the journal + or a negative errno-style error code. + + Locations pointed to by parameters + from and to will be + set only if the return value is positive, and obviously, the + parameters are non-null. + + + + Notes + + + + + + + + See Also + + + systemd1, + sd-journal3, + sd_journal_open3, + sd_journal_get_realtime_usec3, + sd_id128_get_boot3, + clock_gettime2 + + + + diff --git a/man/sd_journal_get_data.xml b/man/sd_journal_get_data.xml new file mode 100644 index 00000000..0a0030e3 --- /dev/null +++ b/man/sd_journal_get_data.xml @@ -0,0 +1,201 @@ + + + + + + + + sd_journal_get_data + systemd + + + + sd_journal_get_data + 3 + + + + sd_journal_get_data + sd_journal_enumerate_data + sd_journal_restart_data + SD_JOURNAL_FOREACH_DATA + sd_journal_set_data_threshold + sd_journal_get_data_threshold + Read data fields from the current journal entry + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_get_data + sd_journal *j + const char *field + const void **data + size_t *length + + + + int sd_journal_enumerate_data + sd_journal *j + const void **data + size_t *length + + + + void sd_journal_restart_data + sd_journal *j + + + + SD_JOURNAL_FOREACH_DATA + sd_journal *j + const void *data + size_t length + + + + int sd_journal_set_data_threshold + sd_journal *j + size_t sz + + + + int sd_journal_get_data_threshold + sd_journal *j + size_t *sz + + + + + + Description + + sd_journal_get_data() gets the data + object associated with a specific field from the current journal + entry. It takes four arguments: the journal context object, a + string with the field name to request, plus a pair of pointers to + pointer/size variables where the data object and its size shall be + stored in. The field name should be an entry field name. + Well-known field names are listed in + systemd.journal-fields7. + The returned data is in a read-only memory map and is only valid + until the next invocation of + sd_journal_get_data() or + sd_journal_enumerate_data(), or the read + pointer is altered. Note that the data returned will be prefixed + with the field name and '='. Also note that, by default, data fields + larger than 64K might get truncated to 64K. This threshold may be + changed and turned off with + sd_journal_set_data_threshold() (see + below). + + sd_journal_enumerate_data() may be used + to iterate through all fields of the current entry. On each + invocation the data for the next field is returned. The order of + these fields is not defined. The data returned is in the same + format as with sd_journal_get_data() and also + follows the same life-time semantics. + + sd_journal_restart_data() resets the + data enumeration index to the beginning of the entry. The next + invocation of sd_journal_enumerate_data() + will return the first field of the entry again. + + Note that the SD_JOURNAL_FOREACH_DATA() + macro may be used as a handy wrapper around + sd_journal_restart_data() and + sd_journal_enumerate_data(). + + Note that these functions will not work before + sd_journal_next3 + (or related call) has been called at least once, in order to + position the read pointer at a valid entry. + + sd_journal_set_data_threshold() may be + used to change the data field size threshold for data returned by + sd_journal_get_data(), + sd_journal_enumerate_data() and + sd_journal_enumerate_unique(). This threshold + is a hint only: it indicates that the client program is interested + only in the initial parts of the data fields, up to the threshold + in size — but the library might still return larger data objects. + That means applications should not rely exclusively on this + setting to limit the size of the data fields returned, but need to + apply an explicit size limit on the returned data as well. This + threshold defaults to 64K by default. To retrieve the complete + data fields this threshold should be turned off by setting it to + 0, so that the library always returns the complete data objects. + It is recommended to set this threshold as low as possible since + this relieves the library from having to decompress large + compressed data objects in full. + + sd_journal_get_data_threshold() returns + the currently configured data field size threshold. + + + + Return Value + + sd_journal_get_data() returns 0 on + success or a negative errno-style error code. If the current entry + does not include the specified field, -ENOENT is returned. If + sd_journal_next3 + has not been called at least once, -EADDRNOTAVAIL is returned. + sd_journal_enumerate_data() returns a + positive integer if the next field has been read, 0 when no more + fields are known, or a negative errno-style error code. + sd_journal_restart_data() returns nothing. + sd_journal_set_data_threshold() and + sd_journal_get_threshold() return 0 on + success or a negative errno-style error code. + + + + Notes + + + + + + + + Examples + + See + sd_journal_next3 + for a complete example how to use + sd_journal_get_data(). + + Use the + SD_JOURNAL_FOREACH_DATA macro to + iterate through all fields of the current journal + entry: + + … +int print_fields(sd_journal *j) { + const void *data; + size_t length; + SD_JOURNAL_FOREACH_DATA(j, data, length) + printf("%.*s\n", (int) length, data); +} +… + + + + See Also + + + systemd1, + systemd.journal-fields7, + sd-journal3, + sd_journal_open3, + sd_journal_next3, + sd_journal_get_realtime_usec3, + sd_journal_query_unique3 + + + + diff --git a/man/sd_journal_get_fd.xml b/man/sd_journal_get_fd.xml new file mode 100644 index 00000000..fc55bbd5 --- /dev/null +++ b/man/sd_journal_get_fd.xml @@ -0,0 +1,259 @@ + + + + + + + + sd_journal_get_fd + systemd + + + + sd_journal_get_fd + 3 + + + + sd_journal_get_fd + sd_journal_get_events + sd_journal_get_timeout + sd_journal_process + sd_journal_wait + sd_journal_reliable_fd + SD_JOURNAL_NOP + SD_JOURNAL_APPEND + SD_JOURNAL_INVALIDATE + Journal change notification + interface + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_get_fd + sd_journal *j + + + + int sd_journal_get_events + sd_journal *j + + + + int sd_journal_get_timeout + sd_journal *j + uint64_t *timeout_usec + + + + int sd_journal_process + sd_journal *j + + + + int sd_journal_wait + sd_journal *j + uint64_t timeout_usec + + + + int sd_journal_reliable_fd + sd_journal *j + + + + + + + Description + + sd_journal_get_fd() returns a file + descriptor that may be asynchronously polled in an external event + loop and is signaled as soon as the journal changes, because new + entries or files were added, rotation took place, or files have + been deleted, and similar. The file descriptor is suitable for + usage in + poll2. + Use sd_journal_get_events() for an events + mask to watch for. The call takes one argument: the journal + context object. Note that not all file systems are capable of + generating the necessary events for wakeups from this file + descriptor for changes to be noticed immediately. In particular + network files systems do not generate suitable file change events + in all cases. Cases like this can be detected with + sd_journal_reliable_fd(), below. + sd_journal_get_timeout() will ensure in these + cases that wake-ups happen frequently enough for changes to be + noticed, although with a certain latency. + + sd_journal_get_events() will return the + poll() mask to wait for. This function will + return a combination of POLLIN and + POLLOUT and similar to fill into the + .events field of struct + pollfd. + + sd_journal_get_timeout() will return a + timeout value for usage in poll(). This + returns a value in microseconds since the epoch of + CLOCK_MONOTONIC for timing out + poll() in timeout_usec. + See + clock_gettime2 + for details about CLOCK_MONOTONIC. If there + is no timeout to wait for, this will fill in (uint64_t) + -1 instead. Note that poll() takes + a relative timeout in milliseconds rather than an absolute timeout + in microseconds. To convert the absolute 'us' timeout into + relative 'ms', use code like the following: + + uint64_t t; +int msec; +sd_journal_get_timeout(m, &t); +if (t == (uint64_t) -1) + msec = -1; +else { + struct timespec ts; + uint64_t n; + clock_gettime(CLOCK_MONOTONIC, &ts); + n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; + msec = t > n ? (int) ((t - n + 999) / 1000) : 0; +} + + The code above does not do any error checking for brevity's + sake. The calculated msec integer can be passed + directly as poll()'s timeout + parameter. + + After each poll() wake-up + sd_journal_process() needs to be called to + process events. This call will also indicate what kind of change + has been detected (see below; note that spurious wake-ups are + possible). + + A synchronous alternative for using + sd_journal_get_fd(), + sd_journal_get_events(), + sd_journal_get_timeout() and + sd_journal_process() is + sd_journal_wait(). It will synchronously wait + until the journal gets changed. The maximum time this call sleeps + may be controlled with the timeout_usec + parameter. Pass (uint64_t) -1 to wait + indefinitely. Internally this call simply combines + sd_journal_get_fd(), + sd_journal_get_events(), + sd_journal_get_timeout(), + poll() and + sd_journal_process() into one. + + sd_journal_reliable_fd() may be used to + check whether the wakeup events from the file descriptor returned + by sd_journal_get_fd() are known to be + immediately triggered. On certain file systems where file change + events from the OS are not available (such as NFS) changes need to + be polled for repeatedly, and hence are detected only with a + certain latency. This call will return a positive value if the + journal changes are detected immediately and zero when they need + to be polled for and hence might be noticed only with a certain + latency. Note that there is usually no need to invoke this function + directly as sd_journal_get_timeout() on these + file systems will ask for timeouts explicitly anyway. + + + + Return Value + + sd_journal_get_fd() returns a valid + file descriptor on success or a negative errno-style error + code. + + sd_journal_get_events() returns a + combination of POLLIN, + POLLOUT and suchlike on success or a negative + errno-style error code. + + sd_journal_reliable_fd() returns a + positive integer if the file descriptor returned by + sd_journal_get_fd() will generate wake-ups + immediately for all journal changes. Returns 0 if there might be a + latency involved. + + sd_journal_process() and sd_journal_wait() return a negative + errno-style error code, or one of SD_JOURNAL_NOP, SD_JOURNAL_APPEND or + SD_JOURNAL_INVALIDATE on success: + + + If SD_JOURNAL_NOP is returned, the journal did not change since the last + invocation. + + If SD_JOURNAL_APPEND is returned, new entries have been appended to the end + of the journal. In this case it is sufficient to simply continue reading at the previous end location of the + journal, to read the newly added entries. + + If SD_JOURNAL_INVALIDATE, journal files were added to or removed from the + set of journal files watched (e.g. due to rotation or vacuuming), and thus entries might have appeared or + disappeared at arbitrary places in the log stream, possibly before or after the previous end of the log + stream. If SD_JOURNAL_INVALIDATE is returned, live-view UIs that want to reflect on screen + the precise state of the log data on disk should probably refresh their entire display (relative to the cursor of + the log entry on the top of the screen). Programs only interested in a strictly sequential stream of log data may + treat SD_JOURNAL_INVALIDATE the same way as SD_JOURNAL_APPEND, thus + ignoring any changes to the log view earlier than the old end of the log stream. + + + + + Signal safety + + In general, sd_journal_get_fd(), sd_journal_get_events(), and + sd_journal_get_timeout() are not "async signal safe" in the meaning of + signal-safety7. + Nevertheless, only the first call to any of those three functions performs unsafe operations, so subsequent calls + are safe. + + sd_journal_process() and sd_journal_wait() are not + safe. sd_journal_reliable_fd() is safe. + + + + Notes + + + + + + + + Examples + + Iterating through the journal, in a live view tracking all + changes: + + + + Waiting with poll() (this + example lacks all error checking for the sake of + simplicity): + + + + + + See Also + + + systemd1, + sd-journal3, + sd_journal_open3, + sd_journal_next3, + poll2, + clock_gettime2 + + + + diff --git a/man/sd_journal_get_realtime_usec.xml b/man/sd_journal_get_realtime_usec.xml new file mode 100644 index 00000000..f8150ded --- /dev/null +++ b/man/sd_journal_get_realtime_usec.xml @@ -0,0 +1,112 @@ + + + + + + + + sd_journal_get_realtime_usec + systemd + + + + sd_journal_get_realtime_usec + 3 + + + + sd_journal_get_realtime_usec + sd_journal_get_monotonic_usec + Read timestamps from the current journal entry + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_get_realtime_usec + sd_journal *j + uint64_t *usec + + + + int sd_journal_get_monotonic_usec + sd_journal *j + uint64_t *usec + sd_id128_t *boot_id + + + + + + + Description + + sd_journal_get_realtime_usec() gets the + realtime (wallclock) timestamp of the current journal entry. It + takes two arguments: the journal context object and a pointer to a + 64-bit unsigned integer to store the timestamp in. The timestamp + is in microseconds since the epoch, i.e. + CLOCK_REALTIME. + + sd_journal_get_monotonic_usec() gets + the monotonic timestamp of the current journal entry. It takes + three arguments: the journal context object, a pointer to a 64-bit + unsigned integer to store the timestamp in, as well as a 128-bit + ID buffer to store the boot ID of the monotonic timestamp. The + timestamp is in microseconds since boot-up of the specific boot, + i.e. CLOCK_MONOTONIC. Since the monotonic + clock begins new with every reboot, it only defines a well-defined + point in time when used together with an identifier identifying + the boot. See + sd_id128_get_boot3 + for more information. If the boot ID parameter is passed + NULL, the function will fail if the monotonic + timestamp of the current entry is not of the current system + boot. + + Note that these functions will not work before + sd_journal_next3 + (or related call) has been called at least + once, in order to position the read pointer at a valid entry. + + + + Return Value + + sd_journal_get_realtime_usec() and + sd_journal_get_monotonic_usec() returns 0 on + success or a negative errno-style error code. If the boot ID + parameter was passed NULL and the monotonic + timestamp of the current journal entry is not of the current + system boot, -ESTALE is returned by + sd_journal_get_monotonic_usec(). + + + + Notes + + + + + + + + See Also + + + systemd1, + sd-journal3, + sd_journal_open3, + sd_journal_next3, + sd_journal_get_data3, + sd_id128_get_boot3, + clock_gettime2, + sd_journal_get_cutoff_realtime_usec3 + + + + diff --git a/man/sd_journal_get_usage.xml b/man/sd_journal_get_usage.xml new file mode 100644 index 00000000..63683715 --- /dev/null +++ b/man/sd_journal_get_usage.xml @@ -0,0 +1,71 @@ + + + + + + + + sd_journal_get_usage + systemd + + + + sd_journal_get_usage + 3 + + + + sd_journal_get_usage + Journal disk usage + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_get_usage + sd_journal *j + uint64_t *bytes + + + + + + + Description + + sd_journal_get_usage() determines the + total disk space currently used by journal files (in bytes). If + SD_JOURNAL_LOCAL_ONLY was passed when opening + the journal, this value will only reflect the size of journal + files of the local host, otherwise of all hosts. + + + + Return Value + + sd_journal_get_usage() returns 0 on + success or a negative errno-style error code. + + + + Notes + + + + + + + + See Also + + + systemd1, + sd-journal3, + sd_journal_open3, + + + + diff --git a/man/sd_journal_has_runtime_files.xml b/man/sd_journal_has_runtime_files.xml new file mode 100644 index 00000000..7e6e7d4b --- /dev/null +++ b/man/sd_journal_has_runtime_files.xml @@ -0,0 +1,79 @@ + + + + + + + + + sd_journal_has_runtime_files + systemd + + + + sd_journal_has_runtime_files + 3 + + + + sd_journal_has_runtime_files + sd_journal_has_persistent_files + Query availability of runtime or persistent journal files. + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_has_runtime_files + sd_journal *j + + + + int sd_journal_has_persistent_files + sd_journal *j + + + + + + + Description + + sd_journal_has_runtime_files() returns a positive value + if runtime journal files (present in /run/systemd/journal/) have been found. + Otherwise returns 0. + + sd_journal_has_persistent_files() returns a positive value + if persistent journal files (present in /var/log/journal/) have been found. + Otherwise returns 0. + + + + Return value + Both sd_journal_has_runtime_files() + and sd_journal_has_persistent_files() return -EINVAL + if their argument is NULL. + + + + + Notes + + + + + + + + See Also + + sd-journal3 + + + + diff --git a/man/sd_journal_next.xml b/man/sd_journal_next.xml new file mode 100644 index 00000000..20d153db --- /dev/null +++ b/man/sd_journal_next.xml @@ -0,0 +1,175 @@ + + + + + + + + sd_journal_next + systemd + + + + sd_journal_next + 3 + + + + sd_journal_next + sd_journal_previous + sd_journal_next_skip + sd_journal_previous_skip + SD_JOURNAL_FOREACH + SD_JOURNAL_FOREACH_BACKWARDS + Advance or set back the read pointer in the journal + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_next + sd_journal *j + + + + int sd_journal_previous + sd_journal *j + + + + int sd_journal_next_skip + sd_journal *j + uint64_t skip + + + + int sd_journal_previous_skip + sd_journal *j + uint64_t skip + + + + SD_JOURNAL_FOREACH + sd_journal *j + + + + SD_JOURNAL_FOREACH_BACKWARDS + sd_journal *j + + + + + + Description + + sd_journal_next() advances the read + pointer into the journal by one entry. The only argument taken is + a journal context object as allocated via + sd_journal_open3. + After successful invocation the entry may be read with functions + such as + sd_journal_get_data3. + + Similarly, sd_journal_previous() sets + the read pointer back one entry. + + sd_journal_next_skip() and + sd_journal_previous_skip() advance/set back + the read pointer by multiple entries at once, as specified in the + skip parameter. + + The journal is strictly ordered by reception time, and hence + advancing to the next entry guarantees that the entry then + pointing to is later in time than then previous one, or has the + same timestamp. + + Note that + sd_journal_get_data3 + and related calls will fail unless + sd_journal_next() has been invoked at least + once in order to position the read pointer on a journal + entry. + + Note that the SD_JOURNAL_FOREACH() + macro may be used as a wrapper around + sd_journal_seek_head3 + and sd_journal_next() in order to make + iterating through the journal easier. See below for an example. + Similarly, SD_JOURNAL_FOREACH_BACKWARDS() may + be used for iterating the journal in reverse order. + + + + Return Value + + The four calls return the number of entries advanced/set + back on success or a negative errno-style error code. When the end + or beginning of the journal is reached, a number smaller than + requested is returned. More specifically, if + sd_journal_next() or + sd_journal_previous() reach the end/beginning + of the journal they will return 0, instead of 1 when they are + successful. This should be considered an EOF marker. + + + + Notes + + + + + + + + Examples + + Iterating through the journal: + + #include <stdio.h> +#include <string.h> +#include <systemd/sd-journal.h> + +int main(int argc, char *argv[]) { + int r; + sd_journal *j; + r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); + if (r < 0) { + fprintf(stderr, "Failed to open journal: %s\n", strerror(-r)); + return 1; + } + SD_JOURNAL_FOREACH(j) { + const char *d; + size_t l; + + r = sd_journal_get_data(j, "MESSAGE", (const void **)&d, &l); + if (r < 0) { + fprintf(stderr, "Failed to read message field: %s\n", strerror(-r)); + continue; + } + + printf("%.*s\n", (int) l, d); + } + sd_journal_close(j); + return 0; +} + + + + + See Also + + + systemd1, + sd-journal3, + sd_journal_open3, + sd_journal_get_data3, + sd_journal_get_realtime_usec3, + sd_journal_get_cursor3 + + + + diff --git a/man/sd_journal_open.xml b/man/sd_journal_open.xml new file mode 100644 index 00000000..47e57107 --- /dev/null +++ b/man/sd_journal_open.xml @@ -0,0 +1,202 @@ + + + + + + + + sd_journal_open + systemd + + + + sd_journal_open + 3 + + + + sd_journal_open + sd_journal_open_directory + sd_journal_open_directory_fd + sd_journal_open_files + sd_journal_open_files_fd + sd_journal_close + sd_journal + SD_JOURNAL_LOCAL_ONLY + SD_JOURNAL_RUNTIME_ONLY + SD_JOURNAL_SYSTEM + SD_JOURNAL_CURRENT_USER + SD_JOURNAL_OS_ROOT + Open the system journal for reading + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_open + sd_journal **ret + int flags + + + + int sd_journal_open_directory + sd_journal **ret + const char *path + int flags + + + + int sd_journal_open_directory_fd + sd_journal **ret + int fd + int flags + + + + int sd_journal_open_files + sd_journal **ret + const char **paths + int flags + + + + int sd_journal_open_files_fd + sd_journal **ret + int fds[] + unsigned n_fds + int flags + + + + void sd_journal_close + sd_journal *j + + + + + + Description + + sd_journal_open() opens the log journal + for reading. It will find all journal files automatically and + interleave them automatically when reading. As first argument it + takes a pointer to a sd_journal pointer, which, + on success, will contain a journal context object. The second + argument is a flags field, which may consist of the following + flags ORed together: SD_JOURNAL_LOCAL_ONLY + makes sure only journal files generated on the local machine will + be opened. SD_JOURNAL_RUNTIME_ONLY makes sure + only volatile journal files will be opened, excluding those which + are stored on persistent storage. + SD_JOURNAL_SYSTEM will cause journal files of + system services and the kernel (in opposition to user session + processes) to be opened. + SD_JOURNAL_CURRENT_USER will cause journal + files of the current user to be opened. If neither + SD_JOURNAL_SYSTEM nor + SD_JOURNAL_CURRENT_USER are specified, all + journal file types will be opened. + + sd_journal_open_directory() is similar to sd_journal_open() but + takes an absolute directory path as argument. All journal files in this directory will be opened and interleaved + automatically. This call also takes a flags argument. The flags parameters accepted by this call are + SD_JOURNAL_OS_ROOT, SD_JOURNAL_SYSTEM, and + SD_JOURNAL_CURRENT_USER. If SD_JOURNAL_OS_ROOT is specified, journal + files are searched for below the usual /var/log/journal and + /run/log/journal relative to the specified path, instead of directly beneath it. + The other two flags limit which files are opened, the same as for sd_journal_open(). + + + sd_journal_open_directory_fd() is similar to + sd_journal_open_directory(), but takes a file descriptor referencing a directory in the file + system instead of an absolute file system path. + + sd_journal_open_files() is similar to sd_journal_open() but takes a + NULL-terminated list of file paths to open. All files will be opened and interleaved + automatically. This call also takes a flags argument, but it must be passed as 0 as no flags are currently + understood for this call. Please note that in the case of a live journal, this function is only useful for + debugging, because individual journal files can be rotated at any moment, and the opening of specific files is + inherently racy. + + sd_journal_open_files_fd() is similar to sd_journal_open_files() + but takes an array of open file descriptors that must reference journal files, instead of an array of file system + paths. Pass the array of file descriptors as second argument, and the number of array entries in the third. The + flags parameter must be passed as 0. + + sd_journal objects cannot be used in the + child after a fork. Functions which take a journal object as an + argument (sd_journal_next() and others) will + return -ECHILD after a fork. + + + sd_journal_close() will close the + journal context allocated with + sd_journal_open() or + sd_journal_open_directory() and free its + resources. + + When opening the journal only journal files accessible to + the calling user will be opened. If journal files are not + accessible to the caller, this will be silently ignored. + + See + sd_journal_next3 + for an example of how to iterate through the journal after opening + it with sd_journal_open(). + + A journal context object returned by + sd_journal_open() references a specific + journal entry as current entry, similar to a + file seek index in a classic file system file, but without + absolute positions. It may be altered with + sd_journal_next3 + and + sd_journal_seek_head3 + and related calls. The current entry position may be exported in + cursor strings, as accessible via + sd_journal_get_cursor3. + Cursor strings may be used to globally identify a specific journal + entry in a stable way and then later to seek to it (or if the + specific entry is not available locally, to its closest entry in + time) + sd_journal_seek_cursor3. + + Notification of journal changes is available via + sd_journal_get_fd() and related calls. + + + + Return Value + + The sd_journal_open(), + sd_journal_open_directory(), and + sd_journal_open_files() calls return 0 on + success or a negative errno-style error code. + sd_journal_close() returns nothing. + + + + Notes + + + + + + + + See Also + + + systemd1, + sd-journal3, + systemd-journald.service8, + sd_journal_next3, + sd_journal_get_data3 + + + + diff --git a/man/sd_journal_print.xml b/man/sd_journal_print.xml new file mode 100644 index 00000000..85e5aa02 --- /dev/null +++ b/man/sd_journal_print.xml @@ -0,0 +1,210 @@ + + + + + + + + sd_journal_print + systemd + + + + sd_journal_print + 3 + + + + sd_journal_print + sd_journal_printv + sd_journal_send + sd_journal_sendv + sd_journal_perror + SD_JOURNAL_SUPPRESS_LOCATION + Submit log entries to the journal + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_print + int priority + const char *format + … + + + + int sd_journal_printv + int priority + const char *format + va_list ap + + + + int sd_journal_send + const char *format + … + + + + int sd_journal_sendv + const struct iovec *iov + int n + + + + int sd_journal_perror + const char *message + + + + + + + Description + + sd_journal_print() may be used to submit simple, plain text log entries to the system + journal. The first argument is a priority value. This is followed by a format string and its parameters, similar to + printf3 or + syslog3. + Note that currently the resulting message will be trucated to LINE_MAX - 8. + The priority value is one of LOG_EMERG, LOG_ALERT, + LOG_CRIT, LOG_ERR, LOG_WARNING, + LOG_NOTICE, LOG_INFO, LOG_DEBUG, as defined in + syslog.h, see syslog3 for details. It is + recommended to use this call to submit log messages in the application locale or system locale and in UTF-8 format, + but no such restrictions are enforced. Note that log messages written using this function are generally not + expected to end in a new-line character. However, as all trailing whitespace (including spaces, new-lines, + tabulators and carriage returns) are automatically stripped from the logged string, it is acceptable to specify one + (or more). Empty lines (after trailing whitespace removal) are suppressed. On non-empty lines, leading whitespace + (as well as inner whitespace) is left unmodified. + + sd_journal_printv() is similar to + sd_journal_print() but takes a variable + argument list encapsulated in an object of type + va_list (see + stdarg3 + for more information) instead of the format string. It is + otherwise equivalent in behavior. + + sd_journal_send() may be used to submit structured log entries to the system journal. It + takes a series of format strings, each immediately followed by their associated parameters, terminated by + NULL. The strings passed should be of the format VARIABLE=value. The + variable name must be in uppercase and consist only of characters, numbers and underscores, and may not begin with + an underscore. (All assignments that do not follow this syntax will be ignored.) The value can be of any size and + format. It is highly recommended to submit text strings formatted in the UTF-8 character encoding only, and submit + binary fields only when formatting in UTF-8 strings is not sensible. A number of well-known fields are defined, see + systemd.journal-fields7 for + details, but additional application defined fields may be used. A variable may be assigned more than one value per + entry. If this function is used, trailing whitespace is automatically removed from each formatted field. + + sd_journal_sendv() is similar to sd_journal_send() but takes an + array of struct iovec (as defined in uio.h, see readv3 for details) + instead of the format string. Each structure should reference one field of the entry to submit. The second argument + specifies the number of structures in the array. sd_journal_sendv() is particularly useful to + submit binary objects to the journal where that is necessary. Note that this function will not strip trailing + whitespace of the passed fields, but passes the specified data along unmodified. This is different from both + sd_journal_print() and sd_journal_send() described above, which are based + on format strings, and do strip trailing whitespace. + + sd_journal_perror() is a similar to + perror3 + and writes a message to the journal that consists of the passed + string, suffixed with ": " and a human-readable representation of + the current error code stored in + errno3. + If the message string is passed as NULL or + empty string, only the error string representation will be + written, prefixed with nothing. An additional journal field ERRNO= + is included in the entry containing the numeric error code + formatted as decimal string. The log priority used is + LOG_ERR (3). + + Note that sd_journal_send() is a + wrapper around sd_journal_sendv() to make it + easier to use when only text strings shall be submitted. Also, the + following two calls are mostly equivalent: + + sd_journal_print(LOG_INFO, "Hello World, this is PID %lu!", (unsigned long) getpid()); + +sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(), + "PRIORITY=%i", LOG_INFO, + NULL); + + Note that these calls implicitly add fields for the source + file, function name and code line where invoked. This is + implemented with macros. If this is not desired, it can be turned + off by defining SD_JOURNAL_SUPPRESS_LOCATION before including + sd-journal.h. + + syslog3 + and sd_journal_print() may + largely be used interchangeably + functionality-wise. However, note that log messages + logged via the former take a different path to the + journal server than the later, and hence global + chronological ordering between the two streams cannot + be guaranteed. Using + sd_journal_print() has the + benefit of logging source code line, filenames, and + functions as metadata along all entries, and + guaranteeing chronological ordering with structured + log entries that are generated via + sd_journal_send(). Using + syslog() has the benefit of being + more portable. + + + + Return Value + + The five calls return 0 on success or a negative errno-style error code. The errno3 variable itself is + not altered. + + If + systemd-journald8 + is not running (the socket is not present), those functions do + nothing, and also return 0. + + + + Thread safety + + + + sd_journal_sendv() is "async signal safe" in the meaning of signal-safety7. + + + sd_journal_print, + sd_journal_printv, + sd_journal_send, and + sd_journal_perror are + not async signal safe. + + + + + + See Also + + + systemd1, + sd-journal3, + sd_journal_stream_fd3, + syslog3, + perror3, + errno3, + systemd.journal-fields7, + signal7, + socket7 + + + + diff --git a/man/sd_journal_query_unique.xml b/man/sd_journal_query_unique.xml new file mode 100644 index 00000000..1bf83968 --- /dev/null +++ b/man/sd_journal_query_unique.xml @@ -0,0 +1,156 @@ + + + + + + + + sd_journal_query_unique + systemd + + + + sd_journal_query_unique + 3 + + + + sd_journal_query_unique + sd_journal_enumerate_unique + sd_journal_restart_unique + SD_JOURNAL_FOREACH_UNIQUE + Read unique data fields from the journal + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_query_unique + sd_journal *j + const char *field + + + + int sd_journal_enumerate_unique + sd_journal *j + const void **data + size_t *length + + + + void sd_journal_restart_unique + sd_journal *j + + + + SD_JOURNAL_FOREACH_UNIQUE + sd_journal *j + const void *data + size_t length + + + + + + + Description + + sd_journal_query_unique() queries the + journal for all unique values the specified field can take. It + takes two arguments: the journal to query and the field name to + look for. Well-known field names are listed on + systemd.journal-fields7. + Field names must be specified without a trailing '='. After this + function has been executed successfully the field values may be + queried using sd_journal_enumerate_unique(). + Invoking this call a second time will change the field name being + queried and reset the enumeration index to the first field value + that matches. + + sd_journal_enumerate_unique() may be + used to iterate through all data fields which match the previously + selected field name as set with + sd_journal_query_unique(). On each invocation + the next field data matching the field name is returned. The order + of the returned data fields is not defined. It takes three + arguments: the journal context object, plus a pair of pointers to + pointer/size variables where the data object and its size shall be + stored in. The returned data is in a read-only memory map and is + only valid until the next invocation of + sd_journal_enumerate_unique(). Note that the + data returned will be prefixed with the field name and '='. Note + that this call is subject to the data field size threshold as + controlled by + sd_journal_set_data_threshold(). + + sd_journal_restart_unique() resets the + data enumeration index to the beginning of the list. The next + invocation of sd_journal_enumerate_unique() + will return the first field data matching the field name + again. + + Note that the + SD_JOURNAL_FOREACH_UNIQUE() macro may be used + as a handy wrapper around + sd_journal_restart_unique() and + sd_journal_enumerate_unique(). + + Note that these functions currently are not influenced by + matches set with sd_journal_add_match() but + this might change in a later version of this software. + + To enumerate all field names currently in use (and thus all suitable field parameters for + sd_journal_query_unique()), use the + sd_journal_enumerate_fields3 + call. + + + + Return Value + + sd_journal_query_unique() returns 0 on + success or a negative errno-style error code. + sd_journal_enumerate_unique() returns a + positive integer if the next field data has been read, 0 when no + more fields are known, or a negative errno-style error code. + sd_journal_restart_unique() returns + nothing. + + + + Notes + + + + + + + + Examples + + Use the SD_JOURNAL_FOREACH_UNIQUE macro + to iterate through all values a field of the journal can take. The + following example lists all unit names referenced in the + journal: + + + + + + See Also + + + systemd1, + systemd.journal-fields7, + sd-journal3, + sd_journal_open3, + sd_journal_enumerate_fields3, + sd_journal_get_data3, + sd_journal_add_match3 + + + + diff --git a/man/sd_journal_seek_head.xml b/man/sd_journal_seek_head.xml new file mode 100644 index 00000000..8e505f91 --- /dev/null +++ b/man/sd_journal_seek_head.xml @@ -0,0 +1,131 @@ + + + + + + + + sd_journal_seek_head + systemd + + + + sd_journal_seek_head + 3 + + + + sd_journal_seek_head + sd_journal_seek_tail + sd_journal_seek_monotonic_usec + sd_journal_seek_realtime_usec + sd_journal_seek_cursor + Seek to a position in the + journal + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_seek_head + sd_journal *j + + + + int sd_journal_seek_tail + sd_journal *j + + + + int sd_journal_seek_monotonic_usec + sd_journal *j + sd_id128_t boot_id + uint64_t usec + + + + int sd_journal_seek_realtime_usec + sd_journal *j + uint64_t usec + + + + int sd_journal_seek_cursor + sd_journal *j + const char *cursor + + + + + + Description + + sd_journal_seek_head() seeks to the beginning of the journal, i.e. to the + position before the oldest available entry. + + Similarly, sd_journal_seek_tail() may be used to seek to the end of the + journal, i.e. the position after the most recent available entry. + + sd_journal_seek_monotonic_usec() seeks to a position with the specified + monotonic timestamp, i.e. CLOCK_MONOTONIC. Since monotonic time restarts on every + reboot a boot ID needs to be specified as well. + + sd_journal_seek_realtime_usec() seeks to a position with the specified + realtime (wallclock) timestamp, i.e. CLOCK_REALTIME. Note that the realtime clock is + not necessarily monotonic. If a realtime timestamp is ambiguous, it is not defined which position is + sought to. + + sd_journal_seek_cursor() seeks to the position at the specified cursor + string. For details on cursors, see + sd_journal_get_cursor3. + If no entry matching the specified cursor is found the call will seek to the next closest entry (in terms + of time) instead. To verify whether the newly selected entry actually matches the cursor, use + sd_journal_test_cursor3. + + Note that these calls do not actually make any entry the new current entry, this needs to be done + in a separate step with a subsequent + sd_journal_next3 + invocation (or a similar call). Only then, entry data may be retrieved via + sd_journal_get_data3 + or an entry cursor be retrieved via + sd_journal_get_cursor3. + If no entry exists that matches exactly the specified seek address, the next closest is sought to. If + sd_journal_next3 is + used, the closest following entry will be sought to, if + sd_journal_previous3 + is used the closest preceding entry is sought to. + + + + Return Value + + The functions return 0 on success or a negative errno-style + error code. + + + + Notes + + + + + + + + See Also + + + systemd1, + sd-journal3, + sd_journal_open3, + sd_journal_next3, + sd_journal_get_data3, + sd_journal_get_cursor3, + sd_journal_get_realtime_usec3 + + + + diff --git a/man/sd_journal_stream_fd.xml b/man/sd_journal_stream_fd.xml new file mode 100644 index 00000000..bdb27cc8 --- /dev/null +++ b/man/sd_journal_stream_fd.xml @@ -0,0 +1,146 @@ + + + + + + + + sd_journal_stream_fd + systemd + + + + sd_journal_stream_fd + 3 + + + + sd_journal_stream_fd + Create log stream file descriptor to the journal + + + + + #include <systemd/sd-journal.h> + + + int sd_journal_stream_fd + const char *identifier + int priority + int level_prefix + + + + + + + Description + + sd_journal_stream_fd() may be used to + create a log stream file descriptor. Log messages written to this + file descriptor as simple newline-separated text strings are + written to the journal. This file descriptor can be used + internally by applications or be made standard output or standard + error of other processes executed. + + sd_journal_stream_fd() takes a short + program identifier string as first argument, which will be written + to the journal as SYSLOG_IDENTIFIER= field for each log entry + (see + systemd.journal-fields7 + for more information). The second argument shall be the default + priority level for all messages. The priority level is one of + LOG_EMERG, LOG_ALERT, + LOG_CRIT, LOG_ERR, + LOG_WARNING, LOG_NOTICE, + LOG_INFO, LOG_DEBUG, as + defined in syslog.h, see + syslog3 + for details. The third argument is a boolean: if true kernel-style + log level prefixes (such as SD_WARNING) are + interpreted, see + sd-daemon3 + for more information. + + It is recommended that applications log UTF-8 messages only + with this API, but this is not enforced. + + Each invocation of sd_journal_stream_fd() allocates a new log stream file descriptor, + that is not shared with prior or later invocations. The file descriptor is write-only (its reading direction is + shut down), and O_NONBLOCK is turned off initially. + + + + Return Value + + The call returns a valid write-only file descriptor on + success or a negative errno-style error code. + + + + Signal safety + + sd_journal_stream_fd() is "async signal safe" in the meaning of signal-safety7. + + + + + Notes + + + + + + + + Examples + + Creating a log stream suitable for + fprintf3: + + #include <syslog.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <systemd/sd-journal.h> +#include <systemd/sd-daemon.h> + +int main(int argc, char *argv[]) { + int fd; + FILE *log; + fd = sd_journal_stream_fd("test", LOG_INFO, 1); + if (fd < 0) { + fprintf(stderr, "Failed to create stream fd: %s\n", strerror(-fd)); + return 1; + } + log = fdopen(fd, "w"); + if (!log) { + fprintf(stderr, "Failed to create file object: %m\n"); + close(fd); + return 1; + } + fprintf(log, "Hello World!\n"); + fprintf(log, SD_WARNING "This is a warning!\n"); + fclose(log); + return 0; +} + + + + + See Also + + + systemd1, + sd-journal3, + sd-daemon3, + sd_journal_print3, + syslog3, + fprintf3, + systemd.journal-fields7 + + + + diff --git a/man/sd_listen_fds.xml b/man/sd_listen_fds.xml new file mode 100644 index 00000000..9a66ee33 --- /dev/null +++ b/man/sd_listen_fds.xml @@ -0,0 +1,230 @@ + + + + + + + + sd_listen_fds + systemd + + + + sd_listen_fds + 3 + + + + sd_listen_fds + sd_listen_fds_with_names + SD_LISTEN_FDS_START + Check for file descriptors passed by the system manager + + + + + #include <systemd/sd-daemon.h> + + #define SD_LISTEN_FDS_START 3 + + + int sd_listen_fds + int unset_environment + + + + int sd_listen_fds_with_names + int unset_environment + char*** names + + + + + + Description + + sd_listen_fds() may be invoked by a + daemon to check for file descriptors passed by the service manager as + part of the socket-based activation logic. It returns the number + of received file descriptors. If no file descriptors have been + received, zero is returned. The first file descriptor may be found + at file descriptor number 3 + (i.e. SD_LISTEN_FDS_START), the remaining + descriptors follow at 4, 5, 6, …, if any. + + If a daemon receives more than one file descriptor, they + will be passed in the same order as configured in the systemd + socket unit file (see + systemd.socket5 + for details). Nonetheless, it is recommended to verify the correct + socket types before using them. To simplify this checking, the + functions + sd_is_fifo3, + sd_is_socket3, + sd_is_socket_inet3, + sd_is_socket_unix3 + are provided. In order to maximize flexibility, it is recommended + to make these checks as loose as possible without allowing + incorrect setups. i.e. often, the actual port number a socket is + bound to matters little for the service to work, hence it should + not be verified. On the other hand, whether a socket is a datagram + or stream socket matters a lot for the most common program logics + and should be checked. + + This function call will set the FD_CLOEXEC flag for all + passed file descriptors to avoid further inheritance to children + of the calling process. + + If multiple socket units activate the same service, the order + of the file descriptors passed to its main process is undefined. + If additional file descriptors have been passed to the service + manager using + sd_pid_notify_with_fds3's + FDSTORE=1 messages, these file descriptors are + passed last, in arbitrary order, and with duplicates + removed. + + If the unset_environment parameter is + non-zero, sd_listen_fds() will unset the + $LISTEN_FDS, $LISTEN_PID and + $LISTEN_FDNAMES environment variables before + returning (regardless of whether the function call itself + succeeded or not). Further calls to + sd_listen_fds() will then return zero, but the + variables are no longer inherited by child processes. + + sd_listen_fds_with_names() is like + sd_listen_fds(), but optionally also returns + an array of strings with identification names for the passed file + descriptors, if that is available and the + names parameter is non-NULL. This + information is read from the $LISTEN_FDNAMES + variable, which may contain a colon-separated list of names. For + socket-activated services, these names may be configured with the + FileDescriptorName= setting in socket unit + files, see + systemd.socket5 + for details. For file descriptors pushed into the file descriptor + store (see above), the name is set via the + FDNAME= field transmitted via + sd_pid_notify_with_fds(). The primary usecase + for these names are services which accept a variety of file + descriptors which are not recognizable with functions like + sd_is_socket() alone, and thus require + identification via a name. It is recommended to rely on named file + descriptors only if identification via + sd_is_socket() and related calls is not + sufficient. Note that the names used are not unique in any + way. The returned array of strings has as many entries as file + descriptors have been received, plus a final NULL pointer + terminating the array. The caller needs to free the array itself + and each of its elements with libc's free() + call after use. If the names parameter is + NULL, the call is entirely equivalent to + sd_listen_fds(). + + Under specific conditions, the following automatic file + descriptor names are returned: + + + + <command>Special names</command> + + + + + + Name + Description + + + + + unknown + The process received no name for the specific file descriptor from the service manager. + + + + stored + The file descriptor originates in the service manager's per-service file descriptor store, and the FDNAME= field was absent when the file descriptor was submitted to the service manager. + + + + connection + The service was activated in per-connection style using Accept=yes in the socket unit file, and the file descriptor is the connection socket. + + + +
+
+
+ + + Return Value + + On failure, these calls returns a negative errno-style error + code. If + $LISTEN_FDS/$LISTEN_PID was + not set or was not correctly set for this daemon and hence no file + descriptors were received, 0 is returned. Otherwise, the number of + file descriptors passed is returned. The application may find them + starting with file descriptor SD_LISTEN_FDS_START, i.e. file + descriptor 3. + + + + Notes + + + + Internally, sd_listen_fds() checks + whether the $LISTEN_PID environment variable + equals the daemon PID. If not, it returns immediately. Otherwise, + it parses the number passed in the $LISTEN_FDS + environment variable, then sets the FD_CLOEXEC flag for the parsed + number of file descriptors starting from SD_LISTEN_FDS_START. + Finally, it returns the parsed + number. sd_listen_fds_with_names() does the + same but also parses $LISTEN_FDNAMES if + set. + + + + Environment + + + + $LISTEN_PID + $LISTEN_FDS + $LISTEN_FDNAMES + + Set by the service manager for supervised + processes that use socket-based activation. This environment + variable specifies the data + sd_listen_fds() and + sd_listen_fds_with_names() parses. See + above for details. + + + + + + See Also + + + systemd1, + sd-daemon3, + sd_is_fifo3, + sd_is_socket3, + sd_is_socket_inet3, + sd_is_socket_unix3, + sd_pid_notify_with_fds3, + daemon7, + systemd.service5, + systemd.socket5 + + + +
diff --git a/man/sd_login_monitor_new.xml b/man/sd_login_monitor_new.xml new file mode 100644 index 00000000..be1c843e --- /dev/null +++ b/man/sd_login_monitor_new.xml @@ -0,0 +1,247 @@ + + + + + + + + sd_login_monitor_new + systemd + + + + sd_login_monitor_new + 3 + + + + sd_login_monitor_new + sd_login_monitor_unref + sd_login_monitor_unrefp + sd_login_monitor_flush + sd_login_monitor_get_fd + sd_login_monitor_get_events + sd_login_monitor_get_timeout + sd_login_monitor + Monitor login sessions, seats, users and virtual machines/containers + + + + + #include <systemd/sd-login.h> + + + int sd_login_monitor_new + const char *category + sd_login_monitor **ret + + + + sd_login_monitor *sd_login_monitor_unref + sd_login_monitor *m + + + + void sd_login_monitor_unrefp + sd_login_monitor **m + + + + int sd_login_monitor_flush + sd_login_monitor *m + + + + int sd_login_monitor_get_fd + sd_login_monitor *m + + + + int sd_login_monitor_get_events + sd_login_monitor *m + + + + int sd_login_monitor_get_timeout + sd_login_monitor *m + uint64_t *timeout_usec + + + + + + + Description + + sd_login_monitor_new() may be used to + monitor login sessions, users, seats, and virtual + machines/containers. Via a monitor object a file descriptor can be + integrated into an application defined event loop which is woken + up each time a user logs in, logs out or a seat is added or + removed, or a session, user, seat or virtual machine/container + changes state otherwise. The first parameter takes a string which + can be seat (to get only notifications about + seats being added, removed or changed), session + (to get only notifications about sessions being created or removed + or changed), uid (to get only notifications + when a user changes state in respect to logins) or + machine (to get only notifications when a + virtual machine or container is started or stopped). If + notifications shall be generated in all these conditions, + NULL may be passed. Note that in the future + additional categories may be defined. The second parameter returns + a monitor object and needs to be freed with the + sd_login_monitor_unref() call after + use. + + sd_login_monitor_unref() may be used to + destroy a monitor object. Note that this will invalidate any file + descriptor returned by + sd_login_monitor_get_fd(). + + sd_login_monitor_unrefp() is similar to + sd_login_monitor_unref() but takes a pointer + to a pointer to an sd_login_monitor object. This call + is useful in conjunction with GCC's and LLVM's Clean-up + Variable Attribute. Note that this function is defined as + inline function. Use a declaration like the following, in order to + allocate a login monitor object that is freed automatically as the + code block is left: + + { + __attribute__((cleanup(sd_login_monitor_unrefp)) sd_login_monitor *m = NULL; + int r; + … + r = sd_login_monitor_default(&m); + if (r < 0) + fprintf(stderr, "Failed to allocate login monitor object: %s\n", strerror(-r)); + … +} + + sd_login_monitor_flush() may be used to + reset the wakeup state of the monitor object. Whenever an event + causes the monitor to wake up the event loop via the file + descriptor this function needs to be called to reset the wake-up + state. If this call is not invoked, the file descriptor will + immediately wake up the event loop again. + + sd_login_monitor_unref() and + sd_login_monitor_unrefp() execute no + operation if the passed in monitor object is + NULL. + + sd_login_monitor_get_fd() may be used + to retrieve the file descriptor of the monitor object that may be + integrated in an application defined event loop, based around + poll2 + or a similar interface. The application should include the + returned file descriptor as wake-up source for the events mask + returned by sd_login_monitor_get_events(). It + should pass a timeout value as returned by + sd_login_monitor_get_timeout(). Whenever a + wake-up is triggered the file descriptor needs to be reset via + sd_login_monitor_flush(). An application + needs to reread the login state with a function like + sd_get_seats3 + or similar to determine what changed. + + sd_login_monitor_get_events() will + return the poll() mask to wait for. This + function will return a combination of POLLIN, + POLLOUT and similar to fill into the + .events field of struct + pollfd. + + sd_login_monitor_get_timeout() will + return a timeout value for usage in poll(). + This returns a value in microseconds since the epoch of + CLOCK_MONOTONIC for timing out + poll() in timeout_usec. + See + clock_gettime2 + for details about CLOCK_MONOTONIC. If there + is no timeout to wait for this will fill in (uint64_t) + -1 instead. Note that poll() takes + a relative timeout in milliseconds rather than an absolute timeout + in microseconds. To convert the absolute 'µs' timeout into + relative 'ms', use code like the following: + + uint64_t t; +int msec; +sd_login_monitor_get_timeout(m, &t); +if (t == (uint64_t) -1) + msec = -1; +else { + struct timespec ts; + uint64_t n; + clock_gettime(CLOCK_MONOTONIC, &ts); + n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000; + msec = t > n ? (int) ((t - n + 999) / 1000) : 0; +} + + The code above does not do any error checking for brevity's + sake. The calculated msec integer can be passed + directly as poll()'s timeout + parameter. + + + + Return Value + + On success, + sd_login_monitor_new(), + sd_login_monitor_flush() and + sd_login_monitor_get_timeout() + return 0 or a positive integer. On success, + sd_login_monitor_get_fd() returns + a Unix file descriptor. On success, + sd_login_monitor_get_events() + returns a combination of POLLIN, + POLLOUT and suchlike. On failure, + these calls return a negative errno-style error + code. + + sd_login_monitor_unref() + always returns NULL. + + + Errors + + Returned errors may indicate the following problems: + + + + + -EINVAL + + An input parameter was invalid (out of range, or NULL, where + that is not accepted). The specified category to watch is not known. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-login3, + sd_get_seats3, + poll2, + clock_gettime2 + + + + diff --git a/man/sd_machine_get_class.xml b/man/sd_machine_get_class.xml new file mode 100644 index 00000000..db6cf0db --- /dev/null +++ b/man/sd_machine_get_class.xml @@ -0,0 +1,115 @@ + + + + + + + + sd_machine_get_class + systemd + + + + sd_machine_get_class + 3 + + + + sd_machine_get_class + sd_machine_get_ifindices + Determine the class and network interface indices of a + locally running virtual machine or container. + + + + + #include <systemd/sd-login.h> + + + int sd_machine_get_class + const char* machine + char **class + + + + int sd_machine_get_ifindices + const char* machine + int **ifindices + + + + + + Description + + sd_machine_get_class() may be used to + determine the class of a locally running virtual machine or + container that is registered with + systemd-machined.service8. + The string returned is either vm or + container. The returned string needs to be + freed with the libc free3 + call after use. + + sd_machine_get_ifindices() may be used + to determine the numeric indices of the network interfaces on the + host that are pointing towards the specified locally running + virtual machine or container that is registered with + systemd-machined.service8. + The returned array needs to be freed with the libc free3 + call after use. + + + + Return Value + + On success, these calls return 0 or a positive integer. On failure, these calls return a negative + errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -ENXIO + + The specified machine does not exist or is currently not running. + + + + + -EINVAL + + An input parameter was invalid (out of range, or NULL, where + that is not accepted). + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-login3, + systemd-machined.service8, + sd_pid_get_machine_name3 + + + + diff --git a/man/sd_notify.xml b/man/sd_notify.xml new file mode 100644 index 00000000..3046ca88 --- /dev/null +++ b/man/sd_notify.xml @@ -0,0 +1,410 @@ + + + + + + + + sd_notify + systemd + + + + sd_notify + 3 + + + + sd_notify + sd_notifyf + sd_pid_notify + sd_pid_notifyf + sd_pid_notify_with_fds + Notify service manager about start-up completion and other service status changes + + + + + #include <systemd/sd-daemon.h> + + + int sd_notify + int unset_environment + const char *state + + + + int sd_notifyf + int unset_environment + const char *format + … + + + + int sd_pid_notify + pid_t pid + int unset_environment + const char *state + + + + int sd_pid_notifyf + pid_t pid + int unset_environment + const char *format + … + + + + int sd_pid_notify_with_fds + pid_t pid + int unset_environment + const char *state + const int *fds + unsigned n_fds + + + + + + Description + sd_notify() may be called by a service + to notify the service manager about state changes. It can be used + to send arbitrary information, encoded in an + environment-block-like string. Most importantly, it can be used for + start-up completion notification. + + If the unset_environment parameter is + non-zero, sd_notify() will unset the + $NOTIFY_SOCKET environment variable before + returning (regardless of whether the function call itself + succeeded or not). Further calls to + sd_notify() will then fail, but the variable + is no longer inherited by child processes. + + The state parameter should contain a + newline-separated list of variable assignments, similar in style + to an environment block. A trailing newline is implied if none is + specified. The string may contain any kind of variable + assignments, but the following shall be considered + well-known: + + + + READY=1 + + Tells the service manager that service startup is finished, or the service finished loading its + configuration. This is only used by systemd if the service definition file has Type=notify + set. Since there is little value in signaling non-readiness, the only value services should send is + READY=1 (i.e. READY=0 is not defined). + + + + RELOADING=1 + + Tells the service manager that the service is + reloading its configuration. This is useful to allow the + service manager to track the service's internal state, and + present it to the user. Note that a service that sends this + notification must also send a READY=1 + notification when it completed reloading its + configuration. Reloads are propagated in the same way as they + are when initiated by the user. + + + + STOPPING=1 + + Tells the service manager that the service is + beginning its shutdown. This is useful to allow the service + manager to track the service's internal state, and present it + to the user. + + + + STATUS=… + + Passes a single-line UTF-8 status string back + to the service manager that describes the service state. This + is free-form and can be used for various purposes: general + state feedback, fsck-like programs could pass completion + percentages and failing programs could pass a human-readable + error message. Example: STATUS=Completed 66% of file + system check… + + + + ERRNO=… + + If a service fails, the errno-style error + code, formatted as string. Example: ERRNO=2 + for ENOENT. + + + + BUSERROR=… + + If a service fails, the D-Bus error-style + error code. Example: + BUSERROR=org.freedesktop.DBus.Error.TimedOut + + + + MAINPID=… + + The main process ID (PID) of the service, in + case the service manager did not fork off the process itself. + Example: MAINPID=4711 + + + + WATCHDOG=1 + + Tells the service manager to update the + watchdog timestamp. This is the keep-alive ping that services + need to issue in regular intervals if + WatchdogSec= is enabled for it. See + systemd.service5 + for information how to enable this functionality and + sd_watchdog_enabled3 + for the details of how the service can check whether the + watchdog is enabled. + + + + WATCHDOG=trigger + + Tells the service manager that the service detected an internal error that should be handled by + the configured watchdog options. This will trigger the same behaviour as if WatchdogSec= is + enabled and the service did not send WATCHDOG=1 in time. Note that + WatchdogSec= does not need to be enabled for WATCHDOG=trigger to trigger + the watchdog action. See + systemd.service5 for + information about the watchdog behavior. + + + + WATCHDOG_USEC=… + + Reset watchdog_usec value during runtime. + Notice that this is not available when using sd_event_set_watchdog() + or sd_watchdog_enabled(). + Example : WATCHDOG_USEC=20000000 + + + + EXTEND_TIMEOUT_USEC=… + + Tells the service manager to extend the startup, runtime or shutdown service timeout + corresponding the current state. The value specified is a time in microseconds during which the service must + send a new message. A service timeout will occur if the message isn't received, but only if the runtime of the + current state is beyond the original maximum times of TimeoutStartSec=, RuntimeMaxSec=, + and TimeoutStopSec=. + See systemd.service5 + for effects on the service timeouts. + + + + FDSTORE=1 + + Stores additional file descriptors in the service manager. File descriptors sent this way will + be maintained per-service by the service manager and will later be handed back using the usual file descriptor + passing logic at the next invocation of the service, see + sd_listen_fds3. This is + useful for implementing services that can restart after an explicit request or a crash without losing + state. Any open sockets and other file descriptors which should not be closed during the restart may be stored + this way. Application state can either be serialized to a file in /run, or better, stored + in a memfd_create2 memory + file descriptor. Note that the service manager will accept messages for a service only if its + FileDescriptorStoreMax= setting is non-zero (defaults to zero, see + systemd.service5). If file + descriptors sent are pollable (see + epoll_ctl2), then any + EPOLLHUP or EPOLLERR event seen on them will result in their + automatic removal from the store. Multiple arrays of file descriptors may be sent in separate messages, in + which case the arrays are combined. Note that the service manager removes duplicate (pointing to the same + object) file descriptors before passing them to the service. Use sd_pid_notify_with_fds() + to send messages with FDSTORE=1, see below. + + + + FDSTOREREMOVE=1 + + Removes file descriptors from the file descriptor store. This field needs to be combined with + FDNAME= to specify the name of the file descriptors to remove. + + + + FDNAME=… + + When used in combination with FDSTORE=1, specifies a name for the submitted + file descriptors. When used with FDSTOREREMOVE=1, specifies the name for the file + descriptors to remove. This name is passed to the service during activation, and may be queried using + sd_listen_fds_with_names3. File + descriptors submitted without this field set, will implicitly get the name stored + assigned. Note that, if multiple file descriptors are submitted at once, the specified name will be assigned to + all of them. In order to assign different names to submitted file descriptors, submit them in separate + invocations of sd_pid_notify_with_fds(). The name may consist of arbitrary ASCII + characters except control characters or :. It may not be longer than 255 characters. If a + submitted name does not follow these restrictions, it is ignored. + + + + + It is recommended to prefix variable names that are not + listed above with X_ to avoid namespace + clashes. + + Note that systemd will accept status data sent from a + service only if the NotifyAccess= option is + correctly set in the service definition file. See + systemd.service5 + for details. + + Note that sd_notify() notifications may be attributed to units correctly only if either + the sending process is still around at the time PID 1 processes the message, or if the sending process is + explicitly runtime-tracked by the service manager. The latter is the case if the service manager originally forked + off the process, i.e. on all processes that match NotifyAccess= or + NotifyAccess=. Conversely, if an auxiliary process of the unit sends an + sd_notify() message and immediately exits, the service manager might not be able to properly + attribute the message to the unit, and thus will ignore it, even if + NotifyAccess= is set for it. + + sd_notifyf() is similar to + sd_notify() but takes a + printf()-like format string plus + arguments. + + sd_pid_notify() and + sd_pid_notifyf() are similar to + sd_notify() and + sd_notifyf() but take a process ID (PID) to + use as originating PID for the message as first argument. This is + useful to send notification messages on behalf of other processes, + provided the appropriate privileges are available. If the PID + argument is specified as 0, the process ID of the calling process + is used, in which case the calls are fully equivalent to + sd_notify() and + sd_notifyf(). + + sd_pid_notify_with_fds() is similar to + sd_pid_notify() but takes an additional array + of file descriptors. These file descriptors are sent along the + notification message to the service manager. This is particularly + useful for sending FDSTORE=1 messages, as + described above. The additional arguments are a pointer to the + file descriptor array plus the number of file descriptors in the + array. If the number of file descriptors is passed as 0, the call + is fully equivalent to sd_pid_notify(), i.e. + no file descriptors are passed. Note that sending file descriptors + to the service manager on messages that do not expect them (i.e. + without FDSTORE=1) they are immediately closed + on reception. + + + + Return Value + + On failure, these calls return a negative errno-style error code. If $NOTIFY_SOCKET was + not set and hence no status message could be sent, 0 is returned. If the status was sent, these functions return a + positive value. In order to support both service managers that implement this scheme and those which do not, it is + generally recommended to ignore the return value of this call. Note that the return value simply indicates whether + the notification message was enqueued properly, it does not reflect whether the message could be processed + successfully. Specifically, no error is returned when a file descriptor is attempted to be stored using + FDSTORE=1 but the service is not actually configured to permit storing of file descriptors (see + above). + + + + Notes + + + + These functions send a single datagram with the + state string as payload to the AF_UNIX socket + referenced in the $NOTIFY_SOCKET environment + variable. If the first character of + $NOTIFY_SOCKET is @, the + string is understood as Linux abstract namespace socket. The + datagram is accompanied by the process credentials of the sending + service, using SCM_CREDENTIALS. + + + + Environment + + + + $NOTIFY_SOCKET + + Set by the service manager for supervised + processes for status and start-up completion notification. + This environment variable specifies the socket + sd_notify() talks to. See above for + details. + + + + + + Examples + + + Start-up Notification + + When a service finished starting up, it might issue the + following call to notify the service manager: + + sd_notify(0, "READY=1"); + + + + Extended Start-up Notification + + A service could send the following after completing + initialization: + + sd_notifyf(0, "READY=1\n" + "STATUS=Processing requests…\n" + "MAINPID=%lu", + (unsigned long) getpid()); + + + + Error Cause Notification + + A service could send the following shortly before exiting, on failure: + + sd_notifyf(0, "STATUS=Failed to start up: %s\n" + "ERRNO=%i", + strerror(errno), + errno); + + + + Store a File Descriptor in the Service Manager + + To store an open file descriptor in the service manager, + in order to continue operation after a service restart without + losing state, use FDSTORE=1: + + sd_pid_notify_with_fds(0, 0, "FDSTORE=1\nFDNAME=foobar", &fd, 1); + + + + + See Also + + systemd1, + sd-daemon3, + sd_listen_fds3, + sd_listen_fds_with_names3, + sd_watchdog_enabled3, + daemon7, + systemd.service5 + + + + diff --git a/man/sd_pid_get_owner_uid.xml b/man/sd_pid_get_owner_uid.xml new file mode 100644 index 00000000..e9d7a8eb --- /dev/null +++ b/man/sd_pid_get_owner_uid.xml @@ -0,0 +1,314 @@ + + + + + + + + sd_pid_get_owner_uid + systemd + + + + sd_pid_get_owner_uid + 3 + + + + sd_pid_get_owner_uid + sd_pid_get_session + sd_pid_get_user_unit + sd_pid_get_unit + sd_pid_get_machine_name + sd_pid_get_slice + sd_pid_get_user_slice + sd_pid_get_cgroup + sd_peer_get_owner_uid + sd_peer_get_session + sd_peer_get_user_unit + sd_peer_get_unit + sd_peer_get_machine_name + sd_peer_get_slice + sd_peer_get_user_slice + sd_peer_get_cgroup + Determine the owner uid of the user unit or session, + or the session, user unit, system unit, container/VM or slice that + a specific PID or socket peer belongs to. + + + + + #include <systemd/sd-login.h> + + + int sd_pid_get_owner_uid + pid_t pid + uid_t *uid + + + + int sd_pid_get_session + pid_t pid + char **session + + + + int sd_pid_get_user_unit + pid_t pid + char **unit + + + + int sd_pid_get_unit + pid_t pid + char **unit + + + + int sd_pid_get_machine_name + pid_t pid + char **name + + + + int sd_pid_get_slice + pid_t pid + char **slice + + + + int sd_pid_get_user_slice + pid_t pid + char **slice + + + + int sd_pid_get_cgroup + pid_t pid + char **cgroup + + + + int sd_peer_get_owner_uid + int fd + uid_t *uid + + + + int sd_peer_get_session + int fd + char **session + + + + int sd_peer_get_user_unit + int fd + char **unit + + + + int sd_peer_get_unit + int fd + char **unit + + + + int sd_peer_get_machine_name + int fd + char **name + + + + int sd_peer_get_slice + int fd + char **slice + + + + int sd_peer_get_user_slice + int fd + char **slice + + + + int sd_peer_get_cgroup + int fd + char **cgroup + + + + + + Description + + sd_pid_get_owner_uid() may be used to + determine the Unix UID (user identifier) which owns the login + session or systemd user unit of a process identified by the + specified PID. For processes which are not part of a login session + and not managed by a user manager, this function will fail with + -ENODATA. + + sd_pid_get_session() may be used to + determine the login session identifier of a process identified by + the specified process identifier. The session identifier is a + short string, suitable for usage in file system paths. Please + note the login session may be limited to a stub process or two. + User processes may instead be started from their systemd user + manager, e.g. GUI applications started using DBus activation, as + well as service processes which are shared between multiple logins + of the same user. For processes which are not part of a login + session, this function will fail with -ENODATA. + The returned string needs to be freed with the libc free3 + call after use. + + sd_pid_get_user_unit() may be used to + determine the systemd user unit (i.e. user service or scope unit) + identifier of a process identified by the specified PID. The + unit name is a short string, suitable for usage in file system + paths. For processes which are not managed by a user manager, this + function will fail with -ENODATA. The + returned string needs to be freed with the libc free3 + call after use. + + sd_pid_get_unit() may be used to + determine the systemd system unit (i.e. system service or scope + unit) identifier of a process identified by the specified PID. The + unit name is a short string, suitable for usage in file system + paths. Note that not all processes are part of a system + unit/service. For processes not being part of a systemd system + unit, this function will fail with -ENODATA. + (More specifically, this call will not work for kernel threads.) + The returned string needs to be freed with the libc free3 + call after use. + + sd_pid_get_machine_name() may be used + to determine the name of the VM or container is a member of. The + machine name is a short string, suitable for usage in file system + paths. The returned string needs to be freed with the libc + free3 + call after use. For processes not part of a VM or container, this + function fails with -ENODATA. + + sd_pid_get_slice() may be used to + determine the slice unit the process is a member of. See + systemd.slice5 + for details about slices. The returned string needs to be freed + with the libc + free3 + call after use. + + Similarly, sd_pid_get_user_slice() + returns the user slice (as managed by the user's systemd instance) + of a process. + + sd_pid_get_cgroup() returns the control + group path of the specified process, relative to the root of the + hierarchy. Returns the path without trailing slash, except for + processes located in the root control group, where "/" is + returned. To find the actual control group path in the file system, + the returned path needs to be prefixed with + /sys/fs/cgroup/ (if the unified control group + setup is used), or + /sys/fs/cgroup/HIERARCHY/ + (if the legacy multi-hierarchy control group setup is used). + + If the pid parameter of any of these + functions is passed as 0, the operation is executed for the + calling process. + + The sd_peer_get_owner_uid(), + sd_peer_get_session(), + sd_peer_get_user_unit(), + sd_peer_get_unit(), + sd_peer_get_machine_name(), + sd_peer_get_slice(), + sd_peer_get_user_slice() and + sd_peer_get_cgroup() calls operate similar to + their PID counterparts, but operate on a connected AF_UNIX socket + and retrieve information about the connected peer process. Note + that these fields are retrieved via /proc, + and hence are not suitable for authorization purposes, as they are + subject to races. + + + + Return Value + + On success, these calls return 0 or a positive integer. On failure, these calls return a negative + errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -ESRCH + + The specified PID does not refer to a running process. + + + + + -EBADF + + The specified socket file descriptor was invalid. + + + + -ENODATA + + The given field is not specified for the described process or peer. + + + + + -EINVAL + + An input parameter was invalid (out of range, or NULL, where + that is not accepted). + + + + -ENOMEM + + Memory allocation failed. + + + + + + + Notes + + + + Note that the login session identifier as + returned by sd_pid_get_session() + is completely unrelated to the process session + identifier as returned by + getsid2. + + + + See Also + + + systemd1, + sd-login3, + sd_session_is_active3, + getsid2, + systemd.slice5, + systemd-machined.service8 + + + + diff --git a/man/sd_seat_get_active.xml b/man/sd_seat_get_active.xml new file mode 100644 index 00000000..2dba6803 --- /dev/null +++ b/man/sd_seat_get_active.xml @@ -0,0 +1,170 @@ + + + + + + + + sd_seat_get_active + systemd + + + + sd_seat_get_active + 3 + + + + sd_seat_get_active + sd_seat_get_sessions + sd_seat_can_multi_session + sd_seat_can_tty + sd_seat_can_graphical + Determine state of a specific seat + + + + + #include <systemd/sd-login.h> + + + int sd_seat_get_active + const char *seat + char **session + uid_t *uid + + + + int sd_seat_get_sessions + const char *seat + char ***sessions + uid_t **uid + unsigned int *n_uids + + + + int sd_seat_can_multi_session + const char *seat + + + + int sd_seat_can_tty + const char *seat + + + + int sd_seat_can_graphical + const char *seat + + + + + + Description + + sd_seat_get_active() may be used to + determine which session is currently active on a seat, if there is + any. Returns the session identifier and the user identifier of the + Unix user the session is belonging to. Either the session or the + user identifier parameter can be passed NULL, + in case only one of the parameters shall be queried. The returned + string needs to be freed with the libc + free3 + call after use. + + sd_seat_get_sessions() may be used to + determine all sessions on the specified seat. Returns two arrays, + one (NULL terminated) with the session + identifiers of the sessions and one with the user identifiers of + the Unix users the sessions belong to. An additional parameter may + be used to return the number of entries in the latter array. This + value is the same the return value, if the latter is nonnegative. + The two arrays and the last parameter may be passed as + NULL in case these values need not to be + determined. The arrays and the strings referenced by them need to + be freed with the libc + free3 + call after use. Note that instead of an empty array + NULL may be returned and should be considered + equivalent to an empty array. + + sd_seat_can_multi_session() may be used + to determine whether a specific seat is capable of multi-session, + i.e. allows multiple login sessions in parallel (with only one + being active at a time). + + sd_seat_can_tty() may be used to + determine whether a specific seat provides TTY functionality, i.e. + is useful as a text console. + + sd_seat_can_graphical() may be used to + determine whether a specific seat provides graphics functionality, + i.e. is useful as a graphics display. + + If the seat parameter of any of these + functions is passed as NULL, the operation is + executed for the seat of the session of the calling process, if + there is any. + + + + Return Value + + On success, sd_seat_get_active() returns 0 or a positive integer. On success, + sd_seat_get_sessions() returns the number of entries in the session identifier + array. If the test succeeds, sd_seat_can_multi_session, + sd_seat_can_tty and sd_seat_can_graphical return a positive + integer, if it fails 0. On failure, these calls return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -ENODATA + + The given field is not specified for the described seat. + + + + + -ENXIO + + The specified seat is unknown. + + + + + -EINVAL + + An input parameter was invalid (out of range, or NULL, where + that is not accepted). + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-login3, + sd_session_get_seat3 + + + + diff --git a/man/sd_session_is_active.xml b/man/sd_session_is_active.xml new file mode 100644 index 00000000..d4a12f53 --- /dev/null +++ b/man/sd_session_is_active.xml @@ -0,0 +1,315 @@ + + + + + + + + sd_session_is_active + systemd + + + + sd_session_is_active + 3 + + + + sd_session_is_active + sd_session_is_remote + sd_session_get_state + sd_session_get_uid + sd_session_get_seat + sd_session_get_service + sd_session_get_type + sd_session_get_class + sd_session_get_desktop + sd_session_get_display + sd_session_get_tty + sd_session_get_vt + sd_session_get_remote_host + sd_session_get_remote_user + Determine state of a specific session + + + + + #include <systemd/sd-login.h> + + + int sd_session_is_active + const char *session + + + + int sd_session_is_remote + const char *session + + + + int sd_session_get_state + const char *session + char **state + + + + int sd_session_get_uid + const char *session + uid_t *uid + + + + int sd_session_get_seat + const char *session + char **seat + + + + int sd_session_get_service + const char *session + char **service + + + + int sd_session_get_type + const char *session + char **type + + + + int sd_session_get_class + const char *session + char **class + + + + int sd_session_get_desktop + const char *session + char **desktop + + + + int sd_session_get_display + const char *session + char **display + + + + int sd_session_get_remote_host + const char *session + char **remote_host + + + + int sd_session_get_remote_user + const char *session + char **remote_user + + + + int sd_session_get_tty + const char *session + char **tty + + + + int sd_session_get_vt + const char *session + unsigned int *vt + + + + + + Description + + sd_session_is_active() may be used to + determine whether the session identified by the specified session + identifier is currently active (i.e. currently in the foreground + and available for user input) or not. + + sd_session_is_remote() may be used to + determine whether the session identified by the specified session + identifier is a remote session (i.e. its remote host is known) or + not. + + sd_session_get_state() may be used to + determine the state of the session identified by the specified + session identifier. The following states are currently known: + online (session logged in, but session not + active, i.e. not in the foreground), active + (session logged in and active, i.e. in the foreground), + closing (session nominally logged out, but some + processes belonging to it are still around). In the future + additional states might be defined, client code should be written + to be robust in regards to additional state strings being + returned. This function is a more generic version of + sd_session_is_active(). The returned string + needs to be freed with the libc + free3 + call after use. + + sd_session_get_uid() may be used to + determine the user identifier of the Unix user the session + identified by the specified session identifier belongs to. + + sd_session_get_seat() may be used to + determine the seat identifier of the seat the session identified + by the specified session identifier belongs to. Note that not all + sessions are attached to a seat, this call will fail (returning + -ENODATA) for them. The returned string needs + to be freed with the libc + free3 + call after use. + + sd_session_get_service() may be used to + determine the name of the service (as passed during PAM session + setup) that registered the session identified by the specified + session identifier. The returned string needs to be freed with the + libc + free3 + call after use. + + sd_session_get_type() may be used to + determine the type of the session identified by the specified + session identifier. The returned string is one of + x11, wayland, + tty, mir or + unspecified and needs to be freed with the libc + free3 + call after use. + + sd_session_get_class() may be used to + determine the class of the session identified by the specified + session identifier. The returned string is one of + user, greeter, + lock-screen, or background + and needs to be freed with the libc + free3 + call after use. + + sd_session_get_desktop() may be used to + determine the brand of the desktop running on the session + identified by the specified session identifier. This field can be + set freely by desktop environments and does not follow any special + formatting. However, desktops are strongly recommended to use the + same identifiers and capitalization as for + $XDG_CURRENT_DESKTOP, as defined by the Desktop + Entry Specification. The returned string needs to be freed + with the libc + free3 + call after use. + + sd_session_get_display() may be used to + determine the X11 display of the session identified by the + specified session identifier. The returned string needs to be + freed with the libc + free3 + call after use. + + sd_session_get_remote_host() may be + used to determine the remote hostname of the session identified by + the specified session identifier. The returned string needs to be + freed with the libc + free3 + call after use. + + sd_session_get_remote_user() may be + used to determine the remote username of the session identified by + the specified session identifier. The returned string needs to be + freed with the libc + free3 + call after use. Note that this value is rarely known to the + system, and even then should not be relied on. + + sd_session_get_tty() may be used to + determine the TTY device of the session identified by the + specified session identifier. The returned string needs to be + freed with the libc + free3 + call after use. + + sd_session_get_vt() may be used to + determine the VT number of the session identified by the specified + session identifier. This function will return an error if the seat + does not support VTs. + + If the session parameter of any of these + functions is passed as NULL, the operation is + executed for the session the calling process is a member of, if + there is any. + + + + Return Value + + If the test succeeds, + sd_session_is_active() and + sd_session_is_remote() return a + positive integer; if it fails, 0. On success, + sd_session_get_state(), + sd_session_get_uid(), + sd_session_get_seat(), + sd_session_get_service(), + sd_session_get_type(), + sd_session_get_class(), + sd_session_get_display(), + sd_session_get_remote_user(), + sd_session_get_remote_host() and + sd_session_get_tty() return 0 or + a positive integer. On failure, these calls return a + negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -ENXIO + + The specified session does not exist. + + + + + -ENODATA + + The given field is not specified for the described session. + + + + + -EINVAL + + An input parameter was invalid (out of range, or NULL, where + that is not accepted). + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-login3, + sd_pid_get_session3 + + + + diff --git a/man/sd_uid_get_state.xml b/man/sd_uid_get_state.xml new file mode 100644 index 00000000..ed38559b --- /dev/null +++ b/man/sd_uid_get_state.xml @@ -0,0 +1,190 @@ + + + + + + + + sd_uid_get_state + systemd + + + + sd_uid_get_state + 3 + + + + sd_uid_get_state + sd_uid_is_on_seat + sd_uid_get_sessions + sd_uid_get_seats + sd_uid_get_display + Determine login state of a specific Unix user ID + + + + + #include <systemd/sd-login.h> + + + int sd_uid_get_state + uid_t uid + char **state + + + + int sd_uid_is_on_seat + uid_t uid + int require_active + const char *seat + + + + int sd_uid_get_sessions + uid_t uid + int require_active + char ***sessions + + + + int sd_uid_get_seats + uid_t uid + int require_active + char ***seats + + + + int sd_uid_get_display + uid_t uid + char **session + + + + + + Description + + sd_uid_get_state() may be used to + determine the login state of a specific Unix user identifier. The + following states are currently known: offline + (user not logged in at all), lingering (user + not logged in, but some user services running), + online (user logged in, but not active, i.e. + has no session in the foreground), active (user + logged in, and has at least one active session, i.e. one session + in the foreground), closing (user not logged + in, and not lingering, but some processes are still around). In + the future additional states might be defined, client code should + be written to be robust in regards to additional state strings + being returned. The returned string needs to be freed with the + libc + free3 + call after use. + + sd_uid_is_on_seat() may be used to + determine whether a specific user is logged in or active on a + specific seat. Accepts a Unix user identifier and a seat + identifier string as parameters. The + require_active parameter is a boolean + value. If non-zero (true), this function will test if the user is + active (i.e. has a session that is in the foreground and accepting + user input) on the specified seat, otherwise (false) only if the + user is logged in (and possibly inactive) on the specified + seat. + + sd_uid_get_sessions() may be used to + determine the current sessions of the specified user. Accepts a + Unix user identifier as parameter. The + require_active parameter controls whether + the returned list shall consist of only those sessions where the + user is currently active (> 0), where the user is currently + online but possibly inactive (= 0), or logged in at all but + possibly closing the session (< 0). The call returns a + NULL terminated string array of session + identifiers in sessions which needs to be + freed by the caller with the libc + free3 + call after use, including all the strings referenced. If the + string array parameter is passed as NULL, the + array will not be filled in, but the return code still indicates + the number of current sessions. Note that instead of an empty + array NULL may be returned and should be + considered equivalent to an empty array. + + Similarly, sd_uid_get_seats() may be + used to determine the list of seats on which the user currently + has sessions. Similar semantics apply, however note that the user + may have multiple sessions on the same seat as well as sessions + with no attached seat and hence the number of entries in the + returned array may differ from the one returned by + sd_uid_get_sessions(). + + sd_uid_get_display() returns the name + of the "primary" session of a user. If the user has graphical + sessions, it will be the oldest graphical session. Otherwise, it + will be the oldest open session. + + + + Return Value + + On success, sd_uid_get_state() returns 0 or a positive integer. If the test + succeeds, sd_uid_is_on_seat() returns a positive integer; if it fails, 0. + sd_uid_get_sessions() and sd_uid_get_seats() return the number + of entries in the returned arrays. sd_uid_get_display() returns a non-negative code + on success. On failure, these calls return a negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + + -ENODATA + + The given field is not specified for the described user. + + + + + -ENXIO + + The specified seat is unknown. + + + + + -EINVAL + + An input parameter was invalid (out of range, or NULL, where that is not + accepted). This is also returned if the passed user ID is 0xFFFF or + 0xFFFFFFFF, which are undefined on Linux. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + See Also + + + systemd1, + sd-login3, + sd_pid_get_owner_uid3 + + + + diff --git a/man/sd_watchdog_enabled.xml b/man/sd_watchdog_enabled.xml new file mode 100644 index 00000000..0aa5609a --- /dev/null +++ b/man/sd_watchdog_enabled.xml @@ -0,0 +1,142 @@ + + + + + + + + sd_watchdog_enabled + systemd + + + + sd_watchdog_enabled + 3 + + + + sd_watchdog_enabled + Check whether the service manager expects watchdog keep-alive notifications from a service + + + + + #include <systemd/sd-daemon.h> + + + int sd_watchdog_enabled + int unset_environment + uint64_t *usec + + + + + + Description + sd_watchdog_enabled() may be called by + a service to detect whether the service manager expects regular + keep-alive watchdog notification events from it, and the timeout + after which the manager will act on the service if it did not get + such a notification. + + If the $WATCHDOG_USEC environment + variable is set, and the $WATCHDOG_PID variable + is unset or set to the PID of the current process, the service + manager expects notifications from this process. The manager will + usually terminate a service when it does not get a notification + message within the specified time after startup and after each + previous message. It is recommended that a daemon sends a + keep-alive notification message to the service manager every half + of the time returned here. Notification messages may be sent with + sd_notify3 + with a message string of WATCHDOG=1. + + If the unset_environment parameter is + non-zero, sd_watchdog_enabled() will unset + the $WATCHDOG_USEC and + $WATCHDOG_PID environment variables before + returning (regardless of whether the function call itself + succeeded or not). Those variables are no longer inherited by + child processes. Further calls to + sd_watchdog_enabled() will also return with + zero. + + If the usec parameter is non-NULL, + sd_watchdog_enabled() will write the timeout + in µs for the watchdog logic to it. + + To enable service supervision with the watchdog logic, use + WatchdogSec= in service files. See + systemd.service5 + for details. + + Use + sd_event_set_watchdog3 + to enable automatic watchdog support in + sd-event3-based event loops. + + + + Return Value + + On failure, this call returns a negative errno-style error + code. If the service manager expects watchdog keep-alive + notification messages to be sent, > 0 is returned, otherwise 0 + is returned. Only if the return value is > 0, the + usec parameter is valid after the + call. + + + + Notes + + + + Internally, this function parses the + $WATCHDOG_PID and + $WATCHDOG_USEC environment variable. The call + will ignore these variables if $WATCHDOG_PID + does not contain the PID of the current process, under the + assumption that in that case, the variables were set for a + different process further up the process tree. + + + + Environment + + + + $WATCHDOG_PID + + Set by the system manager for supervised + process for which watchdog support is enabled, and contains + the PID of that process. See above for + details. + + + + $WATCHDOG_USEC + + Set by the system manager for supervised + process for which watchdog support is enabled, and contains + the watchdog timeout in µs. See above for + details. + + + + + + See Also + + systemd1, + sd-daemon3, + daemon7, + systemd.service5, + sd_notify3, + sd_event_set_watchdog3 + + + + diff --git a/man/send-unit-files-changed.c b/man/send-unit-files-changed.c new file mode 100644 index 00000000..aecfbcbe --- /dev/null +++ b/man/send-unit-files-changed.c @@ -0,0 +1,16 @@ +#include +#define _cleanup_(f) __attribute__((cleanup(f))) + +int send_unit_files_changed(sd_bus *bus) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL; + int r; + + r = sd_bus_message_new_signal(bus, &message, + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "UnitFilesChanged"); + if (r < 0) + return r; + + return sd_bus_send(bus, message, NULL); +} diff --git a/man/shutdown.xml b/man/shutdown.xml new file mode 100644 index 00000000..bc2fa607 --- /dev/null +++ b/man/shutdown.xml @@ -0,0 +1,148 @@ + + + + + + + + shutdown + systemd + + + + shutdown + 8 + + + + shutdown + Halt, power-off or reboot the machine + + + + + shutdown + OPTIONS + TIME + WALL + + + + + Description + + shutdown may be used to halt, power-off + or reboot the machine. + + The first argument may be a time string (which is usually + now). Optionally, this may be followed by a + wall message to be sent to all logged-in users before going + down. + + The time string may either be in the format + hh:mm for hour/minutes specifying the time to + execute the shutdown at, specified in 24h clock format. + Alternatively it may be in the syntax +m + referring to the specified number of minutes m from now. + now is an alias for +0, i.e. + for triggering an immediate shutdown. If no time argument is + specified, +1 is implied. + + Note that to specify a wall message you must specify a time + argument, too. + + If the time argument is used, 5 minutes before the system + goes down the /run/nologin file is created to + ensure that further logins shall not be allowed. + + + + Options + + The following options are understood: + + + + + + + + + + + + + Halt the machine. + + + + + + + Power-off the machine (the + default). + + + + + + + Reboot the + machine. + + + + + + Equivalent to , + unless is specified. + + + + + + Do not halt, power-off, reboot, just write + wall message. + + + + + + Do not send wall + message before + halt, power-off, reboot. + + + + + + Cancel a pending shutdown. This may be used + to cancel the effect of an invocation of + shutdown with a time argument that is not + +0 or + now. + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + See Also + + systemd1, + systemctl1, + halt8, + wall1 + + + + diff --git a/man/standard-conf.xml b/man/standard-conf.xml new file mode 100644 index 00000000..1db859ac --- /dev/null +++ b/man/standard-conf.xml @@ -0,0 +1,77 @@ + + + + + + + + Configuration Directories and Precedence + + Configuration files are read from directories in /etc/, /run/, + /usr/local/lib/, and /usr/lib/, in order of precedence. Each + configuration file in these configuration directories shall be named in the style of + filename.conf. Files in /etc/ override files + with the same name in /run/, /usr/local/lib/, and + /usr/lib/. Files in /run/ override files with the same name under + /usr/. + + Packages should install their configuration files in /usr/lib/ (distribution packages) + or /usr/local/lib/ (local installs). Files in /etc/ are + reserved for the local administrator, who may use this logic to override the + configuration files installed by vendor packages. All configuration files + are sorted by their filename in lexicographic order, regardless of which of + the directories they reside in. If multiple files specify the same option, + the entry in the file with the lexicographically latest name will take + precedence. It is recommended to prefix all filenames with a two-digit number + and a dash, to simplify the ordering of the files. + + If the administrator wants to disable a configuration file supplied by + the vendor, the recommended way is to place a symlink to + /dev/null in the configuration directory in + /etc/, with the same filename as the vendor + configuration file. If the vendor configuration file is included in + the initrd image, the image has to be regenerated. + + + + Configuration Directories and Precedence + + The default configuration is defined during compilation, so a + configuration file is only needed when it is necessary to deviate + from those defaults. By default, the configuration file in + /etc/systemd/ contains commented out entries + showing the defaults as a guide to the administrator. This file + can be edited to create local overrides. + + + When packages need to customize the configuration, they can + install configuration snippets in + /usr/lib/systemd/*.conf.d/ or + /usr/local/lib/systemd/*.conf.d/. Files in + /etc/ are reserved for the local + administrator, who may use this logic to override the + configuration files installed by vendor packages. The main + configuration file is read before any of the configuration + directories, and has the lowest precedence; entries in a file in + any configuration directory override entries in the single + configuration file. Files in the *.conf.d/ + configuration subdirectories are sorted by their filename in lexicographic + order, regardless of which of the subdirectories they reside in. When + multiple files specify the same option, for options which accept just a + single value, the entry in the file with the lexicographically latest name + takes precedence. For options which accept a list of values, entries are + collected as they occur in files sorted lexicographically. It is recommended + to prefix all filenames in those subdirectories with a two-digit number and + a dash, to simplify the ordering of the files. + + To disable a configuration file supplied by the vendor, the + recommended way is to place a symlink to + /dev/null in the configuration directory in + /etc/, with the same filename as the vendor + configuration file. + + diff --git a/man/standard-options.xml b/man/standard-options.xml new file mode 100644 index 00000000..6a61d9ec --- /dev/null +++ b/man/standard-options.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + Print a short help text and exit. + + + + + + + + Print a short version string and exit. + + + + + + + + Do not pipe output into a pager. + + + + + + + Do not query the user for authentication for privileged operations. + + + + + + + Do not print the legend, i.e. column headers and the + footer with hints. + + + + + + + + Copy the contents of config files to standard output. + Before each file, the filename is printed as a comment. + + + diff --git a/man/sysctl.d.xml b/man/sysctl.d.xml new file mode 100644 index 00000000..32084ee8 --- /dev/null +++ b/man/sysctl.d.xml @@ -0,0 +1,165 @@ + + + + + + + sysctl.d + systemd + + + + sysctl.d + 5 + + + + sysctl.d + Configure kernel parameters at boot + + + + /etc/sysctl.d/*.conf + /run/sysctl.d/*.conf + /usr/lib/sysctl.d/*.conf + + + + Description + + At boot, + systemd-sysctl.service8 + reads configuration files from the above directories to configure + sysctl8 + kernel parameters. + + + + Configuration Format + + The configuration files contain a list of variable + assignments, separated by newlines. Empty lines and lines whose + first non-whitespace character is # or + ; are ignored. + + Note that either / or + . may be used as separators within sysctl + variable names. If the first separator is a slash, remaining + slashes and dots are left intact. If the first separator is a dot, + dots and slashes are interchanged. + kernel.domainname=foo and + kernel/domainname=foo are equivalent and will + cause foo to be written to + /proc/sys/kernel/domainname. Either + net.ipv4.conf.enp3s0/200.forwarding or + net/ipv4/conf/enp3s0.200/forwarding may be used + to refer to + /proc/sys/net/ipv4/conf/enp3s0.200/forwarding. + + + Any access permission errors and attempts to write variables not defined on the local system are + logged, but do not cause the service to fail. Moreover, if a variable assignment is prefixed with a + single - character, failure to set the variable will be logged, but will not cause the + service to fail. All other errors when setting variables cause the service to return failure at the end + (other variables are still processed). + + The settings configured with sysctl.d + files will be applied early on boot. The network + interface-specific options will also be applied individually for + each network interface as it shows up in the system. (More + specifically, net.ipv4.conf.*, + net.ipv6.conf.*, + net.ipv4.neigh.* and + net.ipv6.neigh.*). + + Many sysctl parameters only become available when certain + kernel modules are loaded. Modules are usually loaded on demand, + e.g. when certain hardware is plugged in or network brought up. + This means that + systemd-sysctl.service8 + which runs during early boot will not configure such parameters if + they become available after it has run. To set such parameters, it + is recommended to add an + udev7 + rule to set those parameters when they become available. + Alternatively, a slightly simpler and less efficient option is to + add the module to + modules-load.d5, + causing it to be loaded statically before sysctl settings are + applied (see example below). + + + + + + Examples + + Set kernel YP domain name + /etc/sysctl.d/domain-name.conf: + + + kernel.domainname=example.com + + + + Apply settings available only when a certain module is loaded (method one) + /etc/udev/rules.d/99-bridge.rules: + + + ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", \ + RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/net/bridge" + + + /etc/sysctl.d/bridge.conf: + + + net.bridge.bridge-nf-call-ip6tables = 0 +net.bridge.bridge-nf-call-iptables = 0 +net.bridge.bridge-nf-call-arptables = 0 + + + This method applies settings when the module is + loaded. Please note that, unless the br_netfilter + module is loaded, bridged packets will not be filtered by + Netfilter (starting with kernel 3.18), so simply not loading the + module is sufficient to avoid filtering. + + + + Apply settings available only when a certain module is loaded (method two) + /etc/modules-load.d/bridge.conf: + + + br_netfilter + + /etc/sysctl.d/bridge.conf: + + + net.bridge.bridge-nf-call-ip6tables = 0 +net.bridge.bridge-nf-call-iptables = 0 +net.bridge.bridge-nf-call-arptables = 0 + + + This method forces the module to be always loaded. Please + note that, unless the br_netfilter module is + loaded, bridged packets will not be filtered with Netfilter + (starting with kernel 3.18), so simply not loading the module is + sufficient to avoid filtering. + + + + + See Also + + systemd1, + systemd-sysctl.service8, + systemd-delta1, + sysctl8, + sysctl.conf5, + modprobe8 + + + + diff --git a/man/system-only.xml b/man/system-only.xml new file mode 100644 index 00000000..94aa08bd --- /dev/null +++ b/man/system-only.xml @@ -0,0 +1,16 @@ + + + + + + + +This option is only available for system services and is not supported for services +running in per-user instances of the service manager. + +These options are only available for system services and are not supported for services +running in per-user instances of the service manager. + + diff --git a/man/systemctl.xml b/man/systemctl.xml new file mode 100644 index 00000000..3d86f7df --- /dev/null +++ b/man/systemctl.xml @@ -0,0 +1,2185 @@ + + +%entities; +]> + + + + + + systemctl + systemd + + + + systemctl + 1 + + + + systemctl + Control the systemd system and service manager + + + + + systemctl + OPTIONS + COMMAND + UNIT + + + + + Description + + systemctl may be used to introspect and + control the state of the systemd system and + service manager. Please refer to + systemd1 + for an introduction into the basic concepts and functionality this + tool manages. + + + + Commands + + The following commands are understood: + + + Unit Commands + + + + list-units PATTERN… + + + List units that systemd currently has in memory. This includes units that are + either referenced directly or through a dependency, units that are pinned by applications programmatically, + or units that were active in the past and have failed. By default only units which are active, have pending + jobs, or have failed are shown; this can be changed with option . If one or more + PATTERNs are specified, only units matching one of them are shown. The units + that are shown are additionally filtered by and if those + options are specified. + + Produces output similar to + UNIT LOAD ACTIVE SUB DESCRIPTION + sys-module-fuse.device loaded active plugged /sys/module/fuse + -.mount loaded active mounted Root Mount + boot-efi.mount loaded active mounted /boot/efi + systemd-journald.service loaded active running Journal Service + systemd-logind.service loaded active running Login Service +● user@1000.service loaded failed failed User Manager for UID 1000 + … + systemd-tmpfiles-clean.timer loaded active waiting Daily Cleanup of Temporary Directories + +LOAD = Reflects whether the unit definition was properly loaded. +ACTIVE = The high-level unit activation state, i.e. generalization of SUB. +SUB = The low-level unit activation state, values depend on unit type. + +123 loaded units listed. Pass --all to see loaded but inactive units, too. +To show all installed unit files use 'systemctl list-unit-files'. + + The header and the last unit of a given type are underlined if the + terminal supports that. A colored dot is shown next to services which + were masked, not found, or otherwise failed. + + The LOAD column shows the load state, one of loaded, + not-found, bad-setting, error, + masked. The ACTIVE columns shows the general unit state, one of + active, reloading, inactive, + failed, activating, deactivating. The SUB + column shows the unit-type-specific detailed state of the unit, possible values vary by unit type. The list + of possible LOAD, ACTIVE, and SUB states is not constant and new systemd releases may both add and remove + values. systemctl --state=help command maybe be used to display the + current set of possible values. + + This is the default command. + + + + + list-sockets PATTERN… + + + List socket units currently in memory, ordered by listening address. If one or more + PATTERNs are specified, only socket units matching one of them are + shown. Produces output similar to + +LISTEN UNIT ACTIVATES +/dev/initctl systemd-initctl.socket systemd-initctl.service +… +[::]:22 sshd.socket sshd.service +kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service + +5 sockets listed. + Note: because the addresses might contains spaces, this output + is not suitable for programmatic consumption. + + + Also see , , and . + + + + + list-timers PATTERN… + + + List timer units currently in memory, ordered by the time they elapse next. If one or more + PATTERNs are specified, only units matching one of them are shown. + Produces output similar to + +NEXT LEFT LAST PASSED UNIT ACTIVATES +n/a n/a Thu 2017-02-23 13:40:29 EST 3 days ago ureadahead-stop.timer ureadahead-stop.service +Sun 2017-02-26 18:55:42 EST 1min 14s left Thu 2017-02-23 13:54:44 EST 3 days ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service +Sun 2017-02-26 20:37:16 EST 1h 42min left Sun 2017-02-26 11:56:36 EST 6h ago apt-daily.timer apt-daily.service +Sun 2017-02-26 20:57:49 EST 2h 3min left Sun 2017-02-26 11:56:36 EST 6h ago snapd.refresh.timer snapd.refresh.service + + + + NEXT shows the next time the timer will run. + LEFT shows how long till the next time the timer runs. + LAST shows the last time the timer ran. + PASSED shows how long has passed since the timer last ran. + UNIT shows the name of the timer + ACTIVATES shows the name the service the timer activates when it runs. + + Also see and . + + + + + start PATTERN… + + + Start (activate) one or more units specified on the command line. + + Note that unit glob patterns expand to names of units currently in memory. Units which are + not active and are not in a failed state usually are not in memory, and will not be matched by + any pattern. In addition, in case of instantiated units, systemd is often unaware of the instance + name until the instance has been started. Therefore, using glob patterns with + start has limited usefulness. Also, secondary alias names of units are not + considered. + + Option may be used to also operate on inactive units which are + referenced by other loaded units. Note that this is not the same as operating on "all" possible + units, because as the previous paragraph describes, such a list is ill-defined. Nevertheless, + systemctl start --all GLOB may be useful if all the + units that should match the pattern are pulled in by some target which is known to be loaded. + + + + + stop PATTERN… + + + Stop (deactivate) one or more units specified on the command line. + + This command will fail if the unit does not exist or if stopping of the unit is prohibited (see + RefuseManualStop= in + systemd.unit5). + It will not fail if any of the commands configured to stop the unit + (ExecStop=, etc.) fail, because the manager will still forcibly terminate the + unit. + + + + reload PATTERN… + + + Asks all units listed on the command line to reload + their configuration. Note that this will reload the + service-specific configuration, not the unit configuration + file of systemd. If you want systemd to reload the + configuration file of a unit, use the + daemon-reload command. In other words: + for the example case of Apache, this will reload Apache's + httpd.conf in the web server, not the + apache.service systemd unit + file. + + This command should not be confused with the + daemon-reload command. + + + + + restart PATTERN… + + + Stop and then start one or more units specified on the command line. If the units are not running + yet, they will be started. + + Note that restarting a unit with this command does not necessarily flush out all of the unit's + resources before it is started again. For example, the per-service file descriptor storage facility (see + FileDescriptorStoreMax= in + systemd.service5) will + remain intact as long as the unit has a job pending, and is only cleared when the unit is fully stopped and + no jobs are pending anymore. If it is intended that the file descriptor store is flushed out, too, during a + restart operation an explicit systemctl stop command followed by systemctl + start should be issued. + + + + try-restart PATTERN… + + + Stop and then start one or more units specified on the + command line if the units are running. This does nothing + if units are not running. + + + + + reload-or-restart PATTERN… + + + Reload one or more units if they support it. If not, stop and then start them instead. If the units + are not running yet, they will be started. + + + + try-reload-or-restart PATTERN… + + + Reload one or more units if they support it. If not, stop and then start them instead. This does + nothing if the units are not running. + + + + + isolate UNIT + + + Start the unit specified on the command line and its dependencies + and stop all others, unless they have + (see + systemd.unit5). + If a unit name with no extension is given, an extension of + .target will be assumed. + + This is similar to changing the runlevel in a + traditional init system. The isolate + command will immediately stop processes that are not enabled + in the new unit, possibly including the graphical + environment or terminal you are currently using. + + Note that this is allowed only on units where + is enabled. See + systemd.unit5 + for details. + + + + kill PATTERN… + + + Send a signal to one or more processes of the + unit. Use to select which + process to kill. Use to select + the signal to send. + + + + clean PATTERN… + + + Remove the configuration, state, cache, logs or runtime data of the specified units. Use + to select which kind of resource to remove. For service units this may + be used to remove the directories configured with ConfigurationDirectory=, + StateDirectory=, CacheDirectory=, + LogsDirectory= and RuntimeDirectory=, see + systemd.exec5 + for details. For timer units this may be used to clear out the persistent timestamp data if + Persistent= is used and is selected, see + systemd.timer5. This + command only applies to units that use either of these settings. If is + not specified, both the cache and runtime data are removed (as these two types of data are + generally redundant and reproducible on the next invocation of the unit). + + + + is-active PATTERN… + + + Check whether any of the specified units are active + (i.e. running). Returns an exit code + 0 if at least one is active, or + non-zero otherwise. Unless is + specified, this will also print the current unit state to + standard output. + + + + is-failed PATTERN… + + + Check whether any of the specified units are in a + "failed" state. Returns an exit code + 0 if at least one has failed, + non-zero otherwise. Unless is + specified, this will also print the current unit state to + standard output. + + + + status PATTERN…|PID…] + + + Show terse runtime status information about one or + more units, followed by most recent log data from the + journal. If no units are specified, show system status. If + combined with , also show the status of + all units (subject to limitations specified with + ). If a PID is passed, show information + about the unit the process belongs to. + + This function is intended to generate human-readable + output. If you are looking for computer-parsable output, + use show instead. By default, this + function only shows 10 lines of output and ellipsizes + lines to fit in the terminal window. This can be changed + with and , + see above. In addition, journalctl + --unit=NAME or + journalctl + --user-unit=NAME use + a similar filter for messages and might be more + convenient. + + + systemd implicitly loads units as necessary, so just running the status will + attempt to load a file. The command is thus not useful for determining if something was already loaded or + not. The units may possibly also be quickly unloaded after the operation is completed if there's no reason + to keep it in memory thereafter. + + + + Example output from systemctl status + + $ systemctl status bluetooth +● bluetooth.service - Bluetooth service + Loaded: loaded (/usr/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled) + Active: active (running) since Wed 2017-01-04 13:54:04 EST; 1 weeks 0 days ago + Docs: man:bluetoothd(8) + Main PID: 930 (bluetoothd) + Status: "Running" + Tasks: 1 + Memory: 648.0K + CPU: 435ms + CGroup: /system.slice/bluetooth.service + └─930 /usr/lib/bluetooth/bluetoothd + +Jan 12 10:46:45 example.com bluetoothd[8900]: Not enough free handles to register service +Jan 12 10:46:45 example.com bluetoothd[8900]: Current Time Service could not be registered +Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output error (5) + + + The dot ("●") uses color on supported terminals to summarize the unit state at a glance. White + indicates an inactive or deactivating state. Red indicates a + failed or error state and green indicates an + active, reloading or activating state. + + + The "Loaded:" line in the output will show loaded if the unit has been loaded into + memory. Other possible values for "Loaded:" include: error if there was a problem + loading it, not-found if not unit file was found for this unit, + bad-setting if an essential unit file setting could not be parsed and + masked if the unit file has been masked. Along with showing the path to the unit file, + this line will also show the enablement state. Enabled commands start at boot. See the full table of + possible enablement states — including the definition of masked — in the documentation + for the is-enabled command. + + + The "Active:" line shows active state. The value is usually active or + inactive. Active could mean started, bound, plugged in, etc depending on the unit type. + The unit could also be in process of changing states, reporting a state of activating or + deactivating. A special failed state is entered when the service + failed in some way, such as a crash, exiting with an error code or timing out. If the failed state is + entered the cause will be logged for later reference. + + + + + + show PATTERN…|JOB… + + + Show properties of one or more units, jobs, or the manager itself. If no argument is specified, + properties of the manager will be shown. If a unit name is specified, properties of the unit are shown, and + if a job ID is specified, properties of the job are shown. By default, empty properties are suppressed. Use + to show those too. To select specific properties to show, use + . This command is intended to be used whenever computer-parsable output is + required. Use status if you are looking for formatted human-readable output. + + Many properties shown by systemctl show map directly to configuration settings of + the system and service manager and its unit files. Note that the properties shown by the command are + generally more low-level, normalized versions of the original configuration settings and expose runtime + state in addition to configuration. For example, properties shown for service units include the service's + current main process identifier as MainPID (which is runtime state), and time settings + are always exposed as properties ending in the …USec suffix even if a matching + configuration options end in …Sec, because microseconds is the normalized time unit used + by the system and service manager. + + + + cat PATTERN… + + + Show backing files of one or more units. Prints the + "fragment" and "drop-ins" (source files) of units. Each + file is preceded by a comment which includes the file + name. Note that this shows the contents of the backing files + on disk, which may not match the system manager's + understanding of these units if any unit files were + updated on disk and the daemon-reload + command wasn't issued since. + + + + set-property UNIT PROPERTY=VALUE… + + + Set the specified unit properties at runtime where + this is supported. This allows changing configuration + parameter properties such as resource control settings at + runtime. Not all properties may be changed at runtime, but + many resource control settings (primarily those in + systemd.resource-control5) + may. The changes are applied immediately, and stored on disk + for future boots, unless is + passed, in which case the settings only apply until the + next reboot. The syntax of the property assignment follows + closely the syntax of assignments in unit files. + + Example: systemctl set-property foobar.service CPUWeight=200 + + If the specified unit appears to be inactive, the + changes will be only stored on disk as described + previously hence they will be effective when the unit will + be started. + + Note that this command allows changing multiple properties at the same time, which is + preferable over setting them individually. + + Example: systemctl set-property foobar.service CPUWeight=200 MemoryMax=2G IPAccounting=yes + + Like with unit file configuration settings, assigning an empty setting usually resets a + property to its defaults. + + Example: systemctl set-property avahi-daemon.service IPAddressDeny= + + + + + help PATTERN…|PID… + + + Show manual pages for one or more units, if + available. If a PID is given, the manual pages for the unit + the process belongs to are shown. + + + + + reset-failed [PATTERN…] + + + Reset the failed state of the specified units, or if no unit name is passed, reset + the state of all units. When a unit fails in some way (i.e. process exiting with non-zero error code, + terminating abnormally or timing out), it will automatically enter the failed state and + its exit code and status is recorded for introspection by the administrator until the service is + stopped/re-started or reset with this command. + + In addition to resetting the failed state of a unit it also resets various other + per-unit properties: the start rate limit counter of all unit types is reset to zero, as is the restart + counter of service units. Thus, if a unit's start limit (as configured with + StartLimitIntervalSec=/StartLimitBurst=) is hit and the unit refuses + to be started again, use this command to make it startable again. + + + + + + list-dependencies + UNIT + + + + Shows units required and wanted by the specified + unit. This recursively lists units following the + Requires=, + Requisite=, + ConsistsOf=, + Wants=, BindsTo= + dependencies. If no unit is specified, + default.target is implied. + + By default, only target units are recursively + expanded. When is passed, all other + units are recursively expanded as well. + + Options , + , + may be used to change what types of dependencies + are shown. + + Note that this command only lists units currently loaded into memory by the service manager. In + particular, this command is not suitable to get a comprehensive list at all reverse dependencies on a + specific unit, as it won't list the dependencies declared by units currently not loaded. + + + + + + + Unit File Commands + + + + list-unit-files PATTERN… + + + List unit files installed on the system, in combination with their enablement state (as reported by + is-enabled). If one or more PATTERNs are specified, only unit + files whose name matches one of them are shown (patterns matching unit file system paths are not + supported). + + + + + enable UNIT… + enable PATH… + + + Enable one or more units or unit instances. This will create a set of symlinks, as encoded in the + [Install] sections of the indicated unit files. After the symlinks have been created, + the system manager configuration is reloaded (in a way equivalent to daemon-reload), in + order to ensure the changes are taken into account immediately. Note that this does + not have the effect of also starting any of the units being enabled. If this is + desired, combine this command with the switch, or invoke start + with appropriate arguments later. Note that in case of unit instance enablement (i.e. enablement of units of + the form foo@bar.service), symlinks named the same as instances are created in the + unit configuration directory, however they point to the single template unit file they are instantiated + from. + + This command expects either valid unit names (in which case various unit file directories are + automatically searched for unit files with appropriate names), or absolute paths to unit files (in which + case these files are read directly). If a specified unit file is located outside of the usual unit file + directories, an additional symlink is created, linking it into the unit configuration path, thus ensuring + it is found when requested by commands such as start. The file system where the linked + unit files are located must be accessible when systemd is started (e.g. anything underneath + /home or /var is not allowed, unless those directories are + located on the root file system). + + This command will print the file system operations executed. This output may be suppressed by passing + . + + + Note that this operation creates only the symlinks suggested in the [Install] + section of the unit files. While this command is the recommended way to manipulate the unit configuration + directory, the administrator is free to make additional changes manually by placing or removing symlinks + below this directory. This is particularly useful to create configurations that deviate from the suggested + default installation. In this case, the administrator must make sure to invoke + daemon-reload manually as necessary, in order to ensure the changes are taken into + account. + + + Enabling units should not be confused with starting (activating) units, as done by the + start command. Enabling and starting units is orthogonal: units may be enabled without + being started and started without being enabled. Enabling simply hooks the unit into various suggested + places (for example, so that the unit is automatically started on boot or when a particular kind of + hardware is plugged in). Starting actually spawns the daemon process (in case of service units), or binds + the socket (in case of socket units), and so on. + + Depending on whether , , , + or is specified, this enables the unit for the system, for the calling user only, + for only this boot of the system, or for all future logins of all users. Note that in the last case, no + systemd daemon configuration is reloaded. + + Using enable on masked units is not supported and results in an error. + + + + + disable UNIT… + + + Disables one or more units. This removes all symlinks to the unit files backing the specified units + from the unit configuration directory, and hence undoes any changes made by enable or + link. Note that this removes all symlinks to matching unit files, + including manually created symlinks, and not just those actually created by enable or + link. Note that while disable undoes the effect of + enable, the two commands are otherwise not symmetric, as disable may + remove more symlinks than a prior enable invocation of the same unit created. + + This command expects valid unit names only, it does not accept paths to unit files. + + In addition to the units specified as arguments, all units are disabled that are listed in the + Also= setting contained in the [Install] section of any of the unit + files being operated on. + + This command implicitly reloads the system manager configuration after completing the operation. Note + that this command does not implicitly stop the units that are being disabled. If this is desired, either + combine this command with the switch, or invoke the stop command + with appropriate arguments later. + + This command will print information about the file system operations (symlink removals) + executed. This output may be suppressed by passing . + + + This command honors , , + and in a similar way as enable. + + + + + reenable UNIT… + + + Reenable one or more units, as specified on the command line. This is a combination of + disable and enable and is useful to reset the symlinks a unit file is + enabled with to the defaults configured in its [Install] section. This command expects + a unit name only, it does not accept paths to unit files. + + + + + preset UNIT… + + + Reset the enable/disable status one or more unit files, as specified on + the command line, to the defaults configured in the preset policy files. This + has the same effect as disable or + enable, depending how the unit is listed in the preset + files. + + Use to control whether units shall be + enabled and disabled, or only enabled, or only disabled. + + If the unit carries no install information, it will be silently ignored + by this command. UNIT must be the real unit name, + any alias names are ignored silently. + + For more information on the preset policy format, see + systemd.preset5. + For more information on the concept of presets, please consult the + Preset + document. + + + + + preset-all + + + Resets all installed unit files to the defaults + configured in the preset policy file (see above). + + Use to control + whether units shall be enabled and disabled, or only + enabled, or only disabled. + + + + + is-enabled UNIT… + + + Checks whether any of the specified unit files are + enabled (as with enable). Returns an + exit code of 0 if at least one is enabled, non-zero + otherwise. Prints the current enable status (see table). + To suppress this output, use . + To show installation targets, use . + + + + + <command>is-enabled</command> output + + + + + + Name + Description + Exit Code + + + + + enabled + Enabled via .wants/, .requires/ or Alias= symlinks (permanently in /etc/systemd/system/, or transiently in /run/systemd/system/). + 0 + + + enabled-runtime + + + linked + Made available through one or more symlinks to the unit file (permanently in /etc/systemd/system/ or transiently in /run/systemd/system/), even though the unit file might reside outside of the unit file search path. + > 0 + + + linked-runtime + + + masked + Completely disabled, so that any start operation on it fails (permanently in /etc/systemd/system/ or transiently in /run/systemd/systemd/). + > 0 + + + masked-runtime + + + static + The unit file is not enabled, and has no provisions for enabling in the [Install] unit file section. + 0 + + + indirect + The unit file itself is not enabled, but it has a non-empty Also= setting in the [Install] unit file section, listing other unit files that might be enabled, or it has an alias under a different name through a symlink that is not specified in Also=. For template unit file, an instance different than the one specified in DefaultInstance= is enabled. + 0 + + + disabled + The unit file is not enabled, but contains an [Install] section with installation instructions. + > 0 + + + generated + The unit file was generated dynamically via a generator tool. See systemd.generator7. Generated unit files may not be enabled, they are enabled implicitly by their generator. + 0 + + + transient + The unit file has been created dynamically with the runtime API. Transient units may not be enabled. + 0 + + + bad + The unit file is invalid or another error occurred. Note that is-enabled will not actually return this state, but print an error message instead. However the unit file listing printed by list-unit-files might show it. + > 0 + + + +
+ +
+
+ + + mask UNIT… + + + Mask one or more units, as specified on the command line. This will link these unit files to + /dev/null, making it impossible to start them. This is a stronger version of + disable, since it prohibits all kinds of activation of the unit, including enablement + and manual activation. Use this option with care. This honors the option to only + mask temporarily until the next reboot of the system. The option may be used to + ensure that the units are also stopped. This command expects valid unit names only, it does not accept unit + file paths. + + + + + unmask UNIT… + + + Unmask one or more unit files, as specified on the command line. This will undo the effect of + mask. This command expects valid unit names only, it does not accept unit file + paths. + + + + + link PATH… + + + Link a unit file that is not in the unit file search paths into the unit file search path. This + command expects an absolute path to a unit file. The effect of this may be undone with + disable. The effect of this command is that a unit file is made available for commands + such as start, even though it is not installed directly in the unit search path. The + file system where the linked unit files are located must be accessible when systemd is started + (e.g. anything underneath /home or /var is not allowed, unless + those directories are located on the root file system). + + + + + revert UNIT… + + + Revert one or more unit files to their vendor versions. This command removes drop-in configuration + files that modify the specified units, as well as any user-configured unit file that overrides a matching + vendor supplied unit file. Specifically, for a unit foo.service the matching directories + foo.service.d/ with all their contained files are removed, both below the persistent and + runtime configuration directories (i.e. below /etc/systemd/system and + /run/systemd/system); if the unit file has a vendor-supplied version (i.e. a unit file + located below /usr) any matching persistent or runtime unit file that overrides it is + removed, too. Note that if a unit file has no vendor-supplied version (i.e. is only defined below + /etc/systemd/system or /run/systemd/system, but not in a unit + file stored below /usr), then it is not removed. Also, if a unit is masked, it is + unmasked. + + Effectively, this command may be used to undo all changes made with systemctl + edit, systemctl set-property and systemctl mask and puts + the original unit file with its settings back in effect. + + + + + add-wants TARGET + UNIT… + add-requires TARGET + UNIT… + + + Adds Wants= or Requires= + dependencies, respectively, to the specified + TARGET for one or more units. + + This command honors , + , and + in a way similar to + enable. + + + + + + edit UNIT… + + + Edit a drop-in snippet or a whole replacement file if + is specified, to extend or override the + specified unit. + + Depending on whether (the default), + , or is specified, + this command creates a drop-in file for each unit either for the system, + for the calling user, or for all futures logins of all users. Then, + the editor (see the "Environment" section below) is invoked on + temporary files which will be written to the real location if the + editor exits successfully. + + If is specified, this will copy the + original units instead of creating drop-in files. + + If is specified and any units do + not already exist, new unit files will be opened for editing. + + If is specified, the changes will + be made temporarily in /run and they will be + lost on the next reboot. + + If the temporary file is empty upon exit, the modification of + the related unit is canceled. + + After the units have been edited, systemd configuration is + reloaded (in a way that is equivalent to daemon-reload). + + + Note that this command cannot be used to remotely edit units + and that you cannot temporarily edit units which are in + /etc, since they take precedence over + /run. + + + + + get-default + + + Return the default target to boot into. This returns + the target unit name default.target + is aliased (symlinked) to. + + + + + set-default TARGET + + + Set the default target to boot into. This sets + (symlinks) the default.target alias + to the given target unit. + + + +
+
+ + + Machine Commands + + + + list-machines PATTERN… + + + List the host and all running local containers with + their state. If one or more + PATTERNs are specified, only + containers matching one of them are shown. + + + + + + + + Job Commands + + + + list-jobs PATTERN… + + + List jobs that are in progress. If one or more + PATTERNs are specified, only + jobs for units matching one of them are shown. + + When combined with or the list is augmented with + information on which other job each job is waiting for, and which other jobs are waiting for it, see + above. + + + + cancel JOB… + + + Cancel one or more jobs specified on the command line + by their numeric job IDs. If no job ID is specified, cancel + all pending jobs. + + + + + + + Environment Commands + + + + show-environment + + + Dump the systemd manager environment block. This is the environment + block that is passed to all processes the manager spawns. The environment + block will be dumped in straight-forward form suitable for sourcing into + most shells. If no special characters or whitespace is present in the variable + values, no escaping is performed, and the assignments have the form + VARIABLE=value. If whitespace or characters which have + special meaning to the shell are present, dollar-single-quote escaping is + used, and assignments have the form VARIABLE=$'value'. + This syntax is known to be supported by + bash1, + zsh1, + ksh1, + and + busybox1's + ash1, + but not + dash1 + or + fish1. + + + + + set-environment VARIABLE=VALUE… + + + Set one or more systemd manager environment variables, + as specified on the command line. + + + + unset-environment VARIABLE… + + + Unset one or more systemd manager environment + variables. If only a variable name is specified, it will be + removed regardless of its value. If a variable and a value + are specified, the variable is only removed if it has the + specified value. + + + + + import-environment + VARIABLE… + + + + Import all, one or more environment variables set on + the client into the systemd manager environment block. If + no arguments are passed, the entire environment block is + imported. Otherwise, a list of one or more environment + variable names should be passed, whose client-side values + are then imported into the manager's environment + block. + + + + + + + Manager State Commands + + + + daemon-reload + + + Reload the systemd manager configuration. This will + rerun all generators (see + systemd.generator7), + reload all unit files, and recreate the entire dependency + tree. While the daemon is being reloaded, all sockets + systemd listens on behalf of user configuration will stay + accessible. + + This command should not be confused with the + reload command. + + + + + daemon-reexec + + + Reexecute the systemd manager. This will serialize the + manager state, reexecute the process and deserialize the + state again. This command is of little use except for + debugging and package upgrades. Sometimes, it might be + helpful as a heavy-weight daemon-reload. + While the daemon is being reexecuted, all sockets systemd listening + on behalf of user configuration will stay accessible. + + + + + + log-level [LEVEL] + + If no argument is given, print the current log level of the manager. If an + optional argument LEVEL is provided, then the command changes the + current log level of the manager to LEVEL (accepts the same values as + described in + systemd1). + + + + + log-target [TARGET] + + If no argument is given, print the current log target of the manager. If an + optional argument TARGET is provided, then the command changes the + current log target of the manager to TARGET (accepts the same values as + , described in + systemd1). + + + + + service-watchdogs [yes|no] + + If no argument is given, print the current state of service runtime watchdogs of + the manager. If an optional boolean argument is provided, then globally enables or disables the + service runtime watchdogs () and emergency actions (e.g. + or ); see + systemd.service5. + The hardware watchdog is not affected by this setting. + + + + + + System Commands + + + + is-system-running + + + Checks whether the system is operational. This + returns success (exit code 0) when the system is fully up + and running, specifically not in startup, shutdown or + maintenance mode, and with no failed services. Failure is + returned otherwise (exit code non-zero). In addition, the + current state is printed in a short string to standard + output, see the table below. Use to + suppress this output. + + Use to wait until the boot + process is completed before printing the current state and + returning the appropriate error status. If + is in use, states initializing or + starting will not be reported, instead + the command will block until a later state (such as + running or degraded) + is reached. + + + <command>is-system-running</command> output + + + + + + + Name + Description + Exit Code + + + + + initializing + Early bootup, before + basic.target is reached + or the maintenance state entered. + + > 0 + + + starting + Late bootup, before the job queue + becomes idle for the first time, or one of the + rescue targets are reached. + > 0 + + + running + The system is fully + operational. + 0 + + + degraded + The system is operational but one or more + units failed. + > 0 + + + maintenance + The rescue or emergency target is + active. + > 0 + + + stopping + The manager is shutting + down. + > 0 + + + offline + The manager is not + running. Specifically, this is the operational + state if an incompatible program is running as + system manager (PID 1). + > 0 + + + unknown + The operational state could not be + determined, due to lack of resources or another + error cause. + > 0 + + + +
+
+
+ + + default + + + Enter default mode. This is equivalent to systemctl isolate default.target. This + operation is blocking by default, use to request asynchronous behavior. + + + + + rescue + + + Enter rescue mode. This is equivalent to systemctl isolate rescue.target. This + operation is blocking by default, use to request asynchronous behavior. + + + + emergency + + + Enter emergency mode. This is equivalent to systemctl isolate + emergency.target. This operation is blocking by default, use to + request asynchronous behavior. + + + + halt + + + Shut down and halt the system. This is mostly equivalent to systemctl start halt.target + --job-mode=replace-irreversibly --no-block, but also prints a wall message to all users. This command is + asynchronous; it will return after the halt operation is enqueued, without waiting for it to complete. Note + that this operation will simply halt the OS kernel after shutting down, leaving the hardware powered + on. Use systemctl poweroff for powering off the system (see below). + + If combined with , shutdown of all running services is skipped, however all + processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the + system halt. If is specified twice, the operation is immediately executed without + terminating any processes or unmounting any file systems. This may result in data loss. Note that when + is specified twice the halt operation is executed by systemctl + itself, and the system manager is not contacted. This means the command should succeed even when the system + manager has crashed. + + + + poweroff + + + Shut down and power-off the system. This is mostly equivalent to systemctl start + poweroff.target --job-mode=replace-irreversibly --no-block, but also prints a wall message to all + users. This command is asynchronous; it will return after the power-off operation is enqueued, without + waiting for it to complete. + + If combined with , shutdown of all running services is skipped, however all + processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the + powering off. If is specified twice, the operation is immediately executed without + terminating any processes or unmounting any file systems. This may result in data loss. Note that when + is specified twice the power-off operation is executed by + systemctl itself, and the system manager is not contacted. This means the command should + succeed even when the system manager has crashed. + + + + reboot arg + + + Shut down and reboot the system. This is mostly equivalent to systemctl start reboot.target + --job-mode=replace-irreversibly --no-block, but also prints a wall message to all users. This + command is asynchronous; it will return after the reboot operation is enqueued, without waiting for it to + complete. + + If combined with , shutdown of all running services is skipped, however all + processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the + reboot. If is specified twice, the operation is immediately executed without + terminating any processes or unmounting any file systems. This may result in data loss. Note that when + is specified twice the reboot operation is executed by + systemctl itself, and the system manager is not contacted. This means the command should + succeed even when the system manager has crashed. + + If the optional argument arg is given, it will be passed as the optional + argument to the reboot2 + system call. The value is architecture and firmware specific. As an example, recovery + might be used to trigger system recovery, and fota might be used to trigger a + firmware over the air update. + + + + + kexec + + + Shut down and reboot the system via kexec. This is equivalent to + systemctl start kexec.target --job-mode=replace-irreversibly --no-block. This command is + asynchronous; it will return after the reboot operation is enqueued, without waiting for it to + complete. + + If combined with , shutdown of all running services is skipped, however all + processes are killed and all file systems are unmounted or mounted read-only, immediately followed by the + reboot. + + + + + exit EXIT_CODE + + + Ask the service manager to quit. This is only supported for user service managers (i.e. in + conjunction with the option) or in containers and is equivalent to + poweroff otherwise. This command is asynchronous; it will return after the exit + operation is enqueued, without waiting for it to complete. + + The service manager will exit with the specified exit code, if + EXIT_CODE is passed. + + + + + switch-root ROOT INIT + + + Switches to a different root directory and executes a new system manager process below it. This is + intended for usage in initial RAM disks ("initrd"), and will transition from the initrd's system manager + process (a.k.a. "init" process) to the main system manager process which is loaded from the actual host + volume. This call takes two arguments: the directory that is to become the new root directory, and the path + to the new system manager binary below it to execute as PID 1. If the latter is omitted or the empty + string, a systemd binary will automatically be searched for and used as init. If the system manager path is + omitted, equal to the empty string or identical to the path to the systemd binary, the state of the + initrd's system manager process is passed to the main system manager, which allows later introspection of + the state of the services involved in the initrd boot phase. + + + + + suspend + + + Suspend the system. This will trigger activation of the special target unit + suspend.target. This command is asynchronous, and will return after the suspend + operation is successfully enqueued. It will not wait for the suspend/resume cycle to complete. + + + + + hibernate + + + Hibernate the system. This will trigger activation of the special target unit + hibernate.target. This command is asynchronous, and will return after the hibernation + operation is successfully enqueued. It will not wait for the hibernate/thaw cycle to complete. + + + + + hybrid-sleep + + + Hibernate and suspend the system. This will trigger activation of the special target unit + hybrid-sleep.target. This command is asynchronous, and will return after the hybrid + sleep operation is successfully enqueued. It will not wait for the sleep/wake-up cycle to complete. + + + + + suspend-then-hibernate + + + Suspend the system and hibernate it after the delay specified in systemd-sleep.conf. + This will trigger activation of the special target unit suspend-then-hibernate.target. + This command is asynchronous, and will return after the hybrid sleep operation is successfully enqueued. + It will not wait for the sleep/wake-up or hibernate/thaw cycle to complete. + + +
+
+ + + Parameter Syntax + + Unit commands listed above take either a single unit name (designated as UNIT), + or multiple unit specifications (designated as PATTERN…). In the first case, the + unit name with or without a suffix must be given. If the suffix is not specified (unit name is "abbreviated"), + systemctl will append a suitable suffix, .service by default, and a type-specific suffix in + case of commands which operate only on specific unit types. For example, + # systemctl start sshd and + # systemctl start sshd.service + are equivalent, as are + # systemctl isolate default + and + # systemctl isolate default.target + Note that (absolute) paths to device nodes are automatically converted to device unit names, and other (absolute) + paths to mount unit names. + # systemctl status /dev/sda +# systemctl status /home + are equivalent to: + # systemctl status dev-sda.device +# systemctl status home.mount + In the second case, shell-style globs will be matched against the primary names of all units currently in memory; + literal unit names, with or without a suffix, will be treated as in the first case. This means that literal unit + names always refer to exactly one unit, but globs may match zero units and this is not considered an + error. + + Glob patterns use + fnmatch3, + so normal shell-style globbing rules are used, and + *, ?, + [] may be used. See + glob7 + for more details. The patterns are matched against the primary names of + units currently in memory, and patterns which do not match anything + are silently skipped. For example: + # systemctl stop sshd@*.service + will stop all sshd@.service instances. Note that alias names of units, and units that aren't + in memory are not considered for glob expansion. + + + For unit file commands, the specified UNIT should be the name of the unit file + (possibly abbreviated, see above), or the absolute path to the unit file: + # systemctl enable foo.service + or + # systemctl link /path/to/foo.service + + + +
+ + + Options + + The following options are understood: + + + + + + + + The argument should be a comma-separated list of unit + types such as and + . + + + If one of the arguments is a unit type, when listing + units, limit display to certain unit types. Otherwise, units + of all types will be shown. + + As a special case, if one of the arguments is + , a list of allowed values will be + printed and the program will exit. + + + + + + + + The argument should be a comma-separated list of unit + LOAD, SUB, or ACTIVE states. When listing units, show only + those in the specified states. Use + to show only failed units. + + As a special case, if one of the arguments is + , a list of allowed values will be + printed and the program will exit. + + + + + + + + + When showing unit/job/manager properties with the + show command, limit display to properties + specified in the argument. The argument should be a + comma-separated list of property names, such as + MainPID. Unless specified, all known + properties are shown. If specified more than once, all + properties with the specified names are shown. Shell + completion is implemented for property names. + + For the manager itself, + systemctl show will show all available + properties. Those properties are documented in + systemd-system.conf5. + + + Properties for units vary by unit type, so showing any + unit (even a non-existent one) is a way to list properties + pertaining to this type. Similarly, showing any job will list + properties pertaining to all jobs. Properties for units are + documented in + systemd.unit5, + and the pages for individual unit types + systemd.service5, + systemd.socket5, + etc. + + + + + + + + + When listing units with list-units, also show inactive units and + units which are following other units. When showing unit/job/manager properties, show all + properties regardless whether they are set or not. + + To list all units installed in the file system, use the + list-unit-files command instead. + + When listing units with list-dependencies, recursively show + dependencies of all dependent units (by default only dependencies of target units are + shown). + + When used with status, show journal messages in full, even if they include + unprintable characters or are very long. By default, fields with unprintable characters are + abbreviated as "blob data". (Note that the pager may escape unprintable characters again.) + + + + + + + + + When listing units, also show units of local + containers. Units of local containers will be prefixed with + the container name, separated by a single colon character + (:). + + + + + + + + Show reverse dependencies between units with + list-dependencies, i.e. follow + dependencies of type WantedBy=, + RequiredBy=, + PartOf=, BoundBy=, + instead of Wants= and similar. + + + + + + + + + With list-dependencies, show the + units that are ordered before the specified unit. In other + words, recursively list units following the + After= dependency. + + Note that any After= dependency is + automatically mirrored to create a + Before= dependency. Temporal dependencies + may be specified explicitly, but are also created implicitly + for units which are WantedBy= targets + (see + systemd.target5), + and as a result of other directives (for example + RequiresMountsFor=). Both explicitly + and implicitly introduced dependencies are shown with + list-dependencies. + + When passed to the list-jobs command, for each printed job show which other jobs are + waiting for it. May be combined with to show both the jobs waiting for each job as + well as all jobs each job is waiting for. + + + + + + + + With list-dependencies, show the + units that are ordered after the specified unit. In other + words, recursively list units following the + Before= dependency. + + When passed to the list-jobs command, for each printed job show which other jobs it + is waiting for. May be combined with to show both the jobs waiting for each job as + well as all jobs each job is waiting for. + + + + + + + + + Do not ellipsize unit names, process tree entries, + journal output, or truncate unit descriptions in the output + of status, list-units, + list-jobs, and + list-timers. + Also, show installation targets in the output of + is-enabled. + + + + + + + + When printing properties with show, + only print the value, and skip the property name and + =. + + + + + + + + When showing sockets, show the type of the socket. + + + + + + + + When queuing a new job, this option controls how to deal with + already queued jobs. It takes one of fail, + replace, + replace-irreversibly, + isolate, + ignore-dependencies, + ignore-requirements, + flush, or + triggering. Defaults to + replace, except when the + isolate command is used which implies the + isolate job mode. + + If fail is specified and a requested + operation conflicts with a pending job (more specifically: + causes an already pending start job to be reversed into a stop + job or vice versa), cause the operation to fail. + + If replace (the default) is + specified, any conflicting pending job will be replaced, as + necessary. + + If replace-irreversibly is specified, + operate like replace, but also mark the new + jobs as irreversible. This prevents future conflicting + transactions from replacing these jobs (or even being enqueued + while the irreversible jobs are still pending). Irreversible + jobs can still be cancelled using the cancel + command. This job mode should be used on any transaction which + pulls in shutdown.target. + + isolate is only valid for start + operations and causes all other units to be stopped when the + specified unit is started. This mode is always used when the + isolate command is used. + + flush will cause all queued jobs to + be canceled when the new job is enqueued. + + If ignore-dependencies is specified, + then all unit dependencies are ignored for this new job and + the operation is executed immediately. If passed, no required + units of the unit passed will be pulled in, and no ordering + dependencies will be honored. This is mostly a debugging and + rescue tool for the administrator and should not be used by + applications. + + ignore-requirements is similar to + ignore-dependencies, but only causes the + requirement dependencies to be ignored, the ordering + dependencies will still be honored. + + + triggering may only be used with + systemctl stop. In this mode, the specified + unit and any active units that trigger it are stopped. See the + discussion of + Triggers= in systemd.unit5 + for more information about triggering units. + + + + + + + + + When enqueuing a unit job (for example as effect of a systemctl start + invocation or similar), show brief information about all jobs enqueued, covering both the requested + job and any added because of unit dependencies. Note that the output will only include jobs + immediately part of the transaction requested. It is possible that service start-up program code + run as effect of the enqueued jobs might request further jobs to be pulled in. This means that + completion of the listed jobs might ultimately entail more jobs than the listed ones. + + + + + + + + Shorthand for fail. + When used with the kill command, + if no units were killed, the operation results in an error. + + + + + + + + + + When system shutdown or a sleep state is requested, ignore inhibitor locks. Applications can establish + inhibitor locks to avoid that certain important operations (such as CD burning or suchlike) are interrupted + by system shutdown or a sleep state. Any user may take these locks and privileged users may override these + locks. If any locks are taken, shutdown and sleep state requests will normally fail (unless privileged) and a + list of active locks is printed. However, if is specified, the + established locks are ignored and not shown, and the operation attempted anyway, possibly requiring + additional privileges. + + + + + + + + Just print what would be done. Currently supported by verbs + halt, poweroff, reboot, + kexec, suspend, hibernate, + hybrid-sleep, suspend-then-hibernate, + default, rescue, + emergency, and exit. + + + + + + + + + Suppress printing of the results of various commands + and also the hints about truncated log lines. This does not + suppress output of commands for which the printed output is + the only result (like show). Errors are + always printed. + + + + + + + + Do not synchronously wait for the requested operation + to finish. If this is not specified, the job will be + verified, enqueued and systemctl will + wait until the unit's start-up is completed. By passing this + argument, it is only verified and enqueued. This option may not be + combined with . + + + + + + + + Synchronously wait for started units to terminate again. + This option may not be combined with . + Note that this will wait forever if any given unit never terminates + (by itself or by getting stopped explicitly); particularly services + which use RemainAfterExit=yes. + + When used with is-system-running, wait + until the boot process is completed before returning. + + + + + + + + + + + List units in failed state. This is equivalent to + . + + + + + + + + Do not send wall message before halt, power-off and reboot. + + + + + + + + When used with enable and + disable, operate on the global user + configuration directory, thus enabling or disabling a unit + file globally for all future logins of all users. + + + + + + + + When used with enable and + disable, do not implicitly reload daemon + configuration after executing the changes. + + + + + + + + When used with start and related + commands, disables asking for passwords. Background services + may require input of a password or passphrase string, for + example to unlock system hard disks or cryptographic + certificates. Unless this option is specified and the + command is invoked from a terminal, + systemctl will query the user on the + terminal for the necessary secrets. Use this option to + switch this behavior off. In this case, the password must be + supplied by some other means (for example graphical password + agents) or the service might fail. This also disables + querying the user for authentication for privileged + operations. + + + + + + + + When used with kill, choose which + processes to send a signal to. Must be one of + , or + to select whether to kill only the main + process, the control process or all processes of the + unit. The main process of the unit is the one that defines + the life-time of it. A control process of a unit is one that + is invoked by the manager to induce state changes of it. For + example, all processes started due to the + ExecStartPre=, + ExecStop= or + ExecReload= settings of service units are + control processes. Note that there is only one control + process per unit at a time, as only one state change is + executed at a time. For services of type + Type=forking, the initial process started + by the manager for ExecStart= is a + control process, while the process ultimately forked off by + that one is then considered the main process of the unit (if + it can be determined). This is different for service units + of other types, where the process forked off by the manager + for ExecStart= is always the main process + itself. A service unit consists of zero or one main process, + zero or one control process plus any number of additional + processes. Not all unit types manage processes of these + types however. For example, for mount units, control processes + are defined (which are the invocations of + &MOUNT_PATH; and + &UMOUNT_PATH;), but no main process + is defined. If omitted, defaults to + . + + + + + + + + + + When used with kill, choose which + signal to send to selected processes. Must be one of the + well-known signal specifiers such as SIGTERM, SIGINT or + SIGSTOP. If omitted, defaults to + . + + + + + + + + Select what type of per-unit resources to remove when the clean command is + invoked, see below. Takes one of configuration, state, + cache, logs, runtime to select the + type of resource. This option may be specified more than once, in which case all specified resource + types are removed. Also accepts the special value all as a shortcut for + specifiying all five resource types. If this option is not specified defaults to the combination of + cache and runtime, i.e. the two kinds of resources that + are generally considered to be redundant and can be reconstructed on next invocation. + + + + + + + + + When used with enable, overwrite + any existing conflicting symlinks. + + When used with edit, create all of the + specified units which do not already exist. + + When used with halt, poweroff, reboot or + kexec, execute the selected operation without shutting down all units. However, all + processes will be killed forcibly and all file systems are unmounted or remounted read-only. This is hence a + drastic but relatively safe option to request an immediate reboot. If is specified + twice for these operations (with the exception of kexec), they will be executed + immediately, without terminating any processes or unmounting any file systems. Warning: specifying + twice with any of these operations might result in data loss. Note that when + is specified twice the selected operation is executed by + systemctl itself, and the system manager is not contacted. This means the command should + succeed even when the system manager has crashed. + + + + + + + + When used with halt, poweroff or reboot, set a + short message explaining the reason for the operation. The message will be logged together with the default + shutdown message. + + + + + + + + When used with enable, the units + will also be started. When used with disable or + mask, the units will also be stopped. The start + or stop operation is only carried out when the respective enable or + disable operation has been successful. + + + + + + + + When used with + enable/disable/is-enabled + (and related commands), use the specified root path when looking for unit + files. If this option is present, systemctl will operate on + the file system directly, instead of communicating with the systemd + daemon to carry out changes. + + + + + + + + + When used with enable, + disable, edit, + (and related commands), make changes only temporarily, so + that they are lost on the next reboot. This will have the + effect that changes are not made in subdirectories of + /etc but in /run, + with identical immediate effects, however, since the latter + is lost on reboot, the changes are lost too. + + Similarly, when used with + set-property, make changes only + temporarily, so that they are lost on the next + reboot. + + + + + + + + Takes one of full (the default), + enable-only, + disable-only. When used with the + preset or preset-all + commands, controls whether units shall be disabled and + enabled according to the preset rules, or only enabled, or + only disabled. + + + + + + + + + When used with status, controls the number of journal lines to show, counting from + the most recent ones. Takes a positive integer argument, or 0 to disable journal output. Defaults to + 10. + + + + + + + + + When used with status, controls the + formatting of the journal entries that are shown. For the + available choices, see + journalctl1. + Defaults to short. + + + + + + + + When used with the reboot command, indicate to the system's firmware to reboot into + the firmware setup interface. Note that this functionality is not available on all systems. + + + + + + + + When used with the reboot command, indicate to the system's boot loader to show the + boot loader menu on the following boot. Takes a time value as parameter — indicating the menu time-out. Pass + zero in order to disable the menu time-out. Note that not all boot loaders support this + functionality. + + + + + + + + When used with the reboot command, indicate to the system's boot loader to boot into + a specific boot loader entry on the following boot. Takes a boot loader entry identifier as argument, or + help in order to list available entries. Note that not all boot loaders support this + functionality. + + + + + + + + When used with list-dependencies, + list-units or list-machines, + the output is printed as a list instead of a tree, and the bullet + circles are omitted. + + + + + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code otherwise. + + systemctl uses the return codes defined by LSB, as defined in + LSB 3.0.0. + + + + LSB return codes + + + + + Value + Description in LSB + Use in systemd + + + + + 0 + "program is running or service is OK" + unit is active + + + 1 + "program is dead and /var/run pid file exists" + unit not failed (used by is-failed) + + + 2 + "program is dead and /var/lock lock file exists" + unused + + + 3 + "program is not running" + unit is not active + + + 4 + "program or service status is unknown" + no such unit + + + +
+ + The mapping of LSB service states to systemd unit states is imperfect, so it is better to + not rely on those return values but to look for specific unit states and substates instead. + +
+ + + Environment + + + + $SYSTEMD_EDITOR + + Editor to use when editing units; overrides + $EDITOR and $VISUAL. If neither + $SYSTEMD_EDITOR nor $EDITOR nor + $VISUAL are present or if it is set to an empty + string or if their execution failed, systemctl will try to execute well + known editors in this order: + editor1, + nano1, + vim1, + vi1. + + + + + + + + + + + + See Also + + systemd1, + journalctl1, + loginctl1, + machinectl1, + systemd.unit5, + systemd.resource-control5, + systemd.special7, + wall1, + systemd.preset5, + systemd.generator7, + glob7 + + + +
diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml new file mode 100644 index 00000000..1106c36d --- /dev/null +++ b/man/systemd-analyze.xml @@ -0,0 +1,765 @@ + + + + + + + + systemd-analyze + systemd + + + + systemd-analyze + 1 + + + + systemd-analyze + Analyze and debug system manager + + + + + systemd-analyze + OPTIONS + time + + + systemd-analyze + OPTIONS + blame + + + systemd-analyze + OPTIONS + critical-chain + UNIT + + + + systemd-analyze + OPTIONS + dump + + + + systemd-analyze + OPTIONS + plot + >file.svg + + + systemd-analyze + OPTIONS + dot + PATTERN + >file.dot + + + + systemd-analyze + OPTIONS + unit-paths + + + systemd-analyze + OPTIONS + exit-status + STATUS + + + systemd-analyze + OPTIONS + condition + CONDITION… + + + systemd-analyze + OPTIONS + syscall-filter + SET… + + + systemd-analyze + OPTIONS + calendar + SPEC + + + systemd-analyze + OPTIONS + timestamp + TIMESTAMP + + + systemd-analyze + OPTIONS + timespan + SPAN + + + systemd-analyze + OPTIONS + cat-config + NAME|PATH + + + systemd-analyze + OPTIONS + verify + FILE + + + systemd-analyze + OPTIONS + security + UNIT + + + + + Description + + systemd-analyze may be used to determine + system boot-up performance statistics and retrieve other state and + tracing information from the system and service manager, and to + verify the correctness of unit files. It is also used to access + special functions useful for advanced system manager debugging. + + If no command is passed, systemd-analyze + time is implied. + + + <command>systemd-analyze time</command> + + This command prints the time spent in the kernel before userspace has been reached, the time + spent in the initial RAM disk (initrd) before normal system userspace has been reached, and the time + normal system userspace took to initialize. Note that these measurements simply measure the time passed + up to the point where all system services have been spawned, but not necessarily until they fully + finished initialization or the disk is idle. + + + <command>Show how long the boot took</command> + + # in a container +$ systemd-analyze time +Startup finished in 296ms (userspace) +multi-user.target reached after 275ms in userspace + +# on a real machine +$ systemd-analyze time +Startup finished in 2.584s (kernel) + 19.176s (initrd) + 47.847s (userspace) = 1min 9.608s +multi-user.target reached after 47.820s in userspace + + + + + + <command>systemd-analyze blame</command> + + This command prints a list of all running units, ordered by the time they took to initialize. + This information may be used to optimize boot-up times. Note that the output might be misleading as the + initialization of one service might be slow simply because it waits for the initialization of another + service to complete. Also note: systemd-analyze blame doesn't display results for + services with Type=simple, because systemd considers such services to be started + immediately, hence no measurement of the initialization delays can be done. Also note that this command + only shows the time units took for starting up, it does not show how long unit jobs spent in the + execution queue. In particular it shows the time units spent in activating state, + which is not defined for units such as device units that transition directly from + inactive to active. This command hence gives an impression of the + performance of program code, but cannot accurately reflect latency introduced by waiting for + hardware and similar events. + + + <command>Show which units took the most time during boot</command> + + $ systemd-analyze blame + 32.875s pmlogger.service + 20.905s systemd-networkd-wait-online.service + 13.299s dev-vda1.device + ... + 23ms sysroot.mount + 11ms initrd-udevadm-cleanup-db.service + 3ms sys-kernel-config.mount + + + + + + <command>systemd-analyze critical-chain <optional><replaceable>UNIT</replaceable>...</optional></command> + + This command prints a tree of the time-critical chain of units (for each of the specified + UNITs or for the default target otherwise). The time after the unit is + active or started is printed after the "@" character. The time the unit takes to start is printed after + the "+" character. Note that the output might be misleading as the initialization of services might + depend on socket activation and because of the parallel execution of units. Also, similar to the + blame command, this only takes into account the time units spent in + activating state, and hence does not cover units that never went through an + activating state (such as device units that transition directly from + inactive to active). Moreover it does not show information on + jobs (and in particular not jobs that timed out). + + + <command>systemd-analyze critical-chain</command> + + $ systemd-analyze critical-chain +multi-user.target @47.820s +└─pmie.service @35.968s +548ms + └─pmcd.service @33.715s +2.247s + └─network-online.target @33.712s + └─systemd-networkd-wait-online.service @12.804s +20.905s + └─systemd-networkd.service @11.109s +1.690s + └─systemd-udevd.service @9.201s +1.904s + └─systemd-tmpfiles-setup-dev.service @7.306s +1.776s + └─kmod-static-nodes.service @6.976s +177ms + └─systemd-journald.socket + └─system.slice + └─-.slice + + + + + + <command>systemd-analyze dump</command> + + This command outputs a (usually very long) human-readable serialization of the complete server + state. Its format is subject to change without notice and should not be parsed by applications. + + + Show the internal state of user manager + + $ systemd-analyze --user dump +Timestamp userspace: Thu 2019-03-14 23:28:07 CET +Timestamp finish: Thu 2019-03-14 23:28:07 CET +Timestamp generators-start: Thu 2019-03-14 23:28:07 CET +Timestamp generators-finish: Thu 2019-03-14 23:28:07 CET +Timestamp units-load-start: Thu 2019-03-14 23:28:07 CET +Timestamp units-load-finish: Thu 2019-03-14 23:28:07 CET +-> Unit proc-timer_list.mount: + Description: /proc/timer_list + ... +-> Unit default.target: + Description: Main user target +... + + + + + + <command>systemd-analyze plot</command> + + This command prints an SVG graphic detailing which system services have been started at what + time, highlighting the time they spent on initialization. + + + <command>Plot a bootchart</command> + + $ systemd-analyze plot >bootup.svg +$ eog bootup.svg& + + + + + + <command>systemd-analyze dot [<replaceable>pattern</replaceable>...]</command> + + This command generates textual dependency graph description in dot format for further processing + with the GraphViz + dot1 + tool. Use a command line like systemd-analyze dot | dot -Tsvg >systemd.svg to + generate a graphical dependency tree. Unless or is + passed, the generated graph will show both ordering and requirement dependencies. Optional pattern + globbing style specifications (e.g. *.target) may be given at the end. A unit + dependency is included in the graph if any of these patterns match either the origin or destination + node. + + + Plot all dependencies of any unit whose name starts with <literal>avahi-daemon</literal> + + + $ systemd-analyze dot 'avahi-daemon.*' | dot -Tsvg >avahi.svg +$ eog avahi.svg + + + + Plot the dependencies between all known target units + + $ systemd-analyze dot --to-pattern='*.target' --from-pattern='*.target' \ + | dot -Tsvg >targets.svg +$ eog targets.svg + + + + + <command>systemd-analyze unit-paths</command> + + This command outputs a list of all directories from which unit files, .d + overrides, and .wants, .requires symlinks may be + loaded. Combine with to retrieve the list for the user manager instance, and + for the global configuration of user manager instances. + + + <command>Show all paths for generated units</command> + + $ systemd-analyze unit-paths | grep '^/run' +/run/systemd/system.control +/run/systemd/transient +/run/systemd/generator.early +/run/systemd/system +/run/systemd/system.attached +/run/systemd/generator +/run/systemd/generator.late + + + + Note that this verb prints the list that is compiled into systemd-analyze + itself, and does not communicate with the running manager. Use + systemctl [--user] [--global] show -p UnitPath --value + to retrieve the actual list that the manager uses, with any empty directories omitted. + + + + <command>systemd-analyze exit-status <optional><replaceable>STATUS</replaceable>...</optional></command> + + This command prints a list of exit statuses along with their "class", i.e. the source of the + definition (one of glibc, systemd, LSB, or + BSD), see the Process Exit Codes section in + systemd.exec5. + If no additional arguments are specified, all known statuses are are shown. Otherwise, only the + definitions for the specified codes are shown. + + + <command>Show some example exit status names</command> + + $ systemd-analyze exit-status 0 1 {63..65} +NAME STATUS CLASS +SUCCESS 0 glibc +FAILURE 1 glibc +- 63 - +USAGE 64 BSD +DATAERR 65 BSD + + + + + + <command>systemd-analyze condition <replaceable>CONDITION</replaceable>...</command> + + This command will evaluate Condition*=... and + Assert*=... assignments, and print their values, and + the resulting value of the combined condition set. See + systemd.unit5 + for a list of available conditions and asserts. + + + Evaluate conditions that check kernel versions + + $ systemd-analyze condition 'ConditionKernelVersion = ! <4.0' \ + 'ConditionKernelVersion = >=5.1' \ + 'ConditionACPower=|false' \ + 'ConditionArchitecture=|!arm' \ + 'AssertPathExists=/etc/os-release' +test.service: AssertPathExists=/etc/os-release succeeded. +Asserts succeeded. +test.service: ConditionArchitecture=|!arm succeeded. +test.service: ConditionACPower=|false failed. +test.service: ConditionKernelVersion=>=5.1 succeeded. +test.service: ConditionKernelVersion=!<4.0 succeeded. +Conditions succeeded. + + + + + <command>systemd-analyze syscall-filter <optional><replaceable>SET</replaceable>...</optional></command> + + This command will list system calls contained in the specified system call set + SET, or all known sets if no sets are specified. Argument + SET must include the @ prefix. + + + + <command>systemd-analyze calendar <replaceable>EXPRESSION</replaceable>...</command> + + This command will parse and normalize repetitive calendar time events, and will calculate when + they elapse next. This takes the same input as the OnCalendar= setting in + systemd.timer5, + following the syntax described in + systemd.time7. By + default, only the next time the calendar expression will elapse is shown; use + to show the specified number of next times the expression + elapses. Each time the expression elapses forms a timestamp, see the timestamp + verb below. + + + Show leap days in the near future + + $ systemd-analyze calendar --iterations=5 '*-2-29 0:0:0' + Original form: *-2-29 0:0:0 +Normalized form: *-02-29 00:00:00 + Next elapse: Sat 2020-02-29 00:00:00 UTC + From now: 11 months 15 days left + Iter. #2: Thu 2024-02-29 00:00:00 UTC + From now: 4 years 11 months left + Iter. #3: Tue 2028-02-29 00:00:00 UTC + From now: 8 years 11 months left + Iter. #4: Sun 2032-02-29 00:00:00 UTC + From now: 12 years 11 months left + Iter. #5: Fri 2036-02-29 00:00:00 UTC + From now: 16 years 11 months left + + + + + + <command>systemd-analyze timestamp <replaceable>TIMESTAMP</replaceable>...</command> + + This command parses a timestamp (i.e. a single point in time) and outputs the normalized form and + the difference between this timestamp and now. The timestamp should adhere to the syntax documented in + systemd.time7, + section "PARSING TIMESTAMPS". + + + Show parsing of timestamps + + $ systemd-analyze timestamp yesterday now tomorrow + Original form: yesterday +Normalized form: Mon 2019-05-20 00:00:00 CEST + (in UTC): Sun 2019-05-19 22:00:00 UTC + UNIX seconds: @15583032000 + From now: 1 day 9h ago + + Original form: now +Normalized form: Tue 2019-05-21 09:48:39 CEST + (in UTC): Tue 2019-05-21 07:48:39 UTC + UNIX seconds: @1558424919.659757 + From now: 43us ago + + Original form: tomorrow +Normalized form: Wed 2019-05-22 00:00:00 CEST + (in UTC): Tue 2019-05-21 22:00:00 UTC + UNIX seconds: @15584760000 + From now: 14h left + + + + + + <command>systemd-analyze timespan <replaceable>EXPRESSION</replaceable>...</command> + + This command parses a time span (i.e. a difference between two timestamps) and outputs the + normalized form and the equivalent value in microseconds. The time span should adhere to the syntax + documented in + systemd.time7, + section "PARSING TIME SPANS". Values without units are parsed as seconds. + + + Show parsing of timespans + + $ systemd-analyze timespan 1s 300s '1year 0.000001s' +Original: 1s + μs: 1000000 + Human: 1s + +Original: 300s + μs: 300000000 + Human: 5min + +Original: 1year 0.000001s + μs: 31557600000001 + Human: 1y 1us + + + + + + <command>systemd-analyze cat-config</command> + <replaceable>NAME</replaceable>|<replaceable>PATH</replaceable>... + + This command is similar to systemctl cat, but operates on config files. It + will copy the contents of a config file and any drop-ins to standard output, using the usual systemd + set of directories and rules for precedence. Each argument must be either an absolute path including + the prefix (such as /etc/systemd/logind.conf or + /usr/lib/systemd/logind.conf), or a name relative to the prefix (such as + systemd/logind.conf). + + + Showing logind configuration + $ systemd-analyze cat-config systemd/logind.conf +# /etc/systemd/logind.conf +... +[Login] +NAutoVTs=8 +... + +# /usr/lib/systemd/logind.conf.d/20-test.conf +... some override from another package + +# /etc/systemd/logind.conf.d/50-override.conf +... some administrator override + + + + + + <command>systemd-analyze verify <replaceable>FILE</replaceable>...</command> + + This command will load unit files and print warnings if any errors are detected. Files specified + on the command line will be loaded, but also any other units referenced by them. The full unit search + path is formed by combining the directories for all command line arguments, and the usual unit load + paths (variable $SYSTEMD_UNIT_PATH is supported, and may be used to replace or + augment the compiled in set of unit load paths; see + systemd.unit5). All + units files present in the directories containing the command line arguments will be used in preference + to the other paths. + + The following errors are currently detected: + + unknown sections and directives, + + missing dependencies which are required to start the given unit, + + man pages listed in Documentation= which are not found in the + system, + + commands listed in ExecStart= and similar which are not found in + the system or not executable. + + + + Misspelt directives + + $ cat ./user.slice +[Unit] +WhatIsThis=11 +Documentation=man:nosuchfile(1) +Requires=different.service + +[Service] +Description=x + +$ systemd-analyze verify ./user.slice +[./user.slice:9] Unknown lvalue 'WhatIsThis' in section 'Unit' +[./user.slice:13] Unknown section 'Service'. Ignoring. +Error: org.freedesktop.systemd1.LoadFailed: + Unit different.service failed to load: + No such file or directory. +Failed to create user.slice/start: Invalid argument +user.slice: man nosuchfile(1) command failed with code 16 + + + + + Missing service units + + $ tail ./a.socket ./b.socket +==> ./a.socket <== +[Socket] +ListenStream=100 + +==> ./b.socket <== +[Socket] +ListenStream=100 +Accept=yes + +$ systemd-analyze verify ./a.socket ./b.socket +Service a.service not loaded, a.socket cannot be started. +Service b@0.service not loaded, b.socket cannot be started. + + + + + + <command>systemd-analyze security <optional><replaceable>UNIT</replaceable>...</optional></command> + + This command analyzes the security and sandboxing settings of one or more specified service + units. If at least one unit name is specified the security settings of the specified service units are + inspected and a detailed analysis is shown. If no unit name is specified, all currently loaded, + long-running service units are inspected and a terse table with results shown. The command checks for + various security-related service settings, assigning each a numeric "exposure level" value, depending + on how important a setting is. It then calculates an overall exposure level for the whole unit, which + is an estimation in the range 0.0…10.0 indicating how exposed a service is security-wise. High exposure + levels indicate very little applied sandboxing. Low exposure levels indicate tight sandboxing and + strongest security restrictions. Note that this only analyzes the per-service security features systemd + itself implements. This means that any additional security mechanisms applied by the service code + itself are not accounted for. The exposure level determined this way should not be misunderstood: a + high exposure level neither means that there is no effective sandboxing applied by the service code + itself, nor that the service is actually vulnerable to remote or local attacks. High exposure levels do + indicate however that most likely the service might benefit from additional settings applied to + them. + + Please note that many of the security and sandboxing settings individually can be circumvented — + unless combined with others. For example, if a service retains the privilege to establish or undo mount + points many of the sandboxing options can be undone by the service code itself. Due to that is + essential that each service uses the most comprehensive and strict sandboxing and security settings + possible. The tool will take into account some of these combinations and relationships between the + settings, but not all. Also note that the security and sandboxing settings analyzed here only apply to + the operations executed by the service code itself. If a service has access to an IPC system (such as + D-Bus) it might request operations from other services that are not subject to the same + restrictions. Any comprehensive security and sandboxing analysis is hence incomplete if the IPC access + policy is not validated too. + + + Analyze <filename index="false">systemd-logind.service</filename> + + $ systemd-analyze security --no-pager systemd-logind.service + NAME DESCRIPTION EXPOSURE +✗ PrivateNetwork= Service has access to the host's network 0.5 +✗ User=/DynamicUser= Service runs as root user 0.4 +✗ DeviceAllow= Service has no device ACL 0.2 +✓ IPAddressDeny= Service blocks all IP address ranges +... +→ Overall exposure level for systemd-logind.service: 4.1 OK 🙂 + + + + + + + Options + + The following options are understood: + + + + + + Operates on the system systemd instance. This + is the implied default. + + + + + + Operates on the user systemd + instance. + + + + + + Operates on the system-wide configuration for + user systemd instance. + + + + + + + When used in conjunction with the + dot command (see above), selects which + dependencies are shown in the dependency graph. If + is passed, only dependencies of type + After= or Before= are + shown. If is passed, only + dependencies of type Requires=, + Requisite=, + Wants= and Conflicts= + are shown. If neither is passed, this shows dependencies of + all these types. + + + + + + + When used in conjunction with the + dot command (see above), this selects which + relationships are shown in the dependency graph. Both options + require a + glob7 + pattern as an argument, which will be matched against the + left-hand and the right-hand, respectively, nodes of a + relationship. + + Each of these can be used more than once, in which case + the unit name must match one of the values. When tests for + both sides of the relation are present, a relation must pass + both tests to be shown. When patterns are also specified as + positional arguments, they must match at least one side of the + relation. In other words, patterns specified with those two + options will trim the list of edges matched by the positional + arguments, if any are given, and fully determine the list of + edges shown otherwise. + + + + timespan + + When used in conjunction with the + critical-chain command (see above), also + show units, which finished timespan + earlier, than the latest unit in the same level. The unit of + timespan is seconds unless + specified with a different unit, e.g. + "50ms". + + + + + + Do not invoke man to verify the existence of + man pages listed in Documentation=. + + + + + + + Invoke unit generators, see + systemd.generator7. + Some generators require root privileges. Under a normal user, running with + generators enabled will generally result in some warnings. + + + + + + With cat-files, show config files underneath + the specified root path PATH. + + + + + + When used with the calendar command, show the specified number of + iterations the specified calendar expression will elapse next. Defaults to 1. + + + + + + When used with the calendar command, show next iterations relative + to the specified point in time. If not specified defaults to the current time. + + + + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + + + See Also + + systemd1, + systemctl1 + + + + diff --git a/man/systemd-ask-password-console.service.xml b/man/systemd-ask-password-console.service.xml new file mode 100644 index 00000000..8c0e8a88 --- /dev/null +++ b/man/systemd-ask-password-console.service.xml @@ -0,0 +1,68 @@ + + + + + + + + systemd-ask-password-console.service + systemd + + + + systemd-ask-password-console.service + 8 + + + + systemd-ask-password-console.service + systemd-ask-password-console.path + systemd-ask-password-wall.service + systemd-ask-password-wall.path + Query the user for system passwords on the + console and via wall + + + + systemd-ask-password-console.service + systemd-ask-password-console.path + systemd-ask-password-wall.service + systemd-ask-password-wall.path + + + + Description + + systemd-ask-password-console.service is + a system service that queries the user for system passwords (such + as hard disk encryption keys and SSL certificate passphrases) on + the console. It is intended to be used during boot to ensure + proper handling of passwords necessary for boot. + systemd-ask-password-wall.service is a system + service that informs all logged in users for system passwords via + wall1. + It is intended to be used after boot to ensure that users are + properly notified. + + See the + developer documentation for more information about the + system password logic. + + Note that these services invoke + systemd-tty-ask-password-agent1 + with either the --watch --console or + --watch --wall command line parameters. + + + + See Also + + systemd1, + systemd-tty-ask-password-agent1, + wall1 + + + + diff --git a/man/systemd-ask-password.xml b/man/systemd-ask-password.xml new file mode 100644 index 00000000..9bb045b9 --- /dev/null +++ b/man/systemd-ask-password.xml @@ -0,0 +1,213 @@ + + + + + + + + systemd-ask-password + systemd + + + + systemd-ask-password + 1 + + + + systemd-ask-password + Query the user for a system password + + + + + systemd-ask-password OPTIONS MESSAGE + + + + + Description + + systemd-ask-password may be used to query + a system password or passphrase from the user, using a question + message specified on the command line. When run from a TTY it will + query a password on the TTY and print it to standard output. When + run with no TTY or with it will use the + system-wide query mechanism, which allows active users to respond via + several agents, listed below. + + The purpose of this tool is to query system-wide passwords + — that is passwords not attached to a specific user account. + Examples include: unlocking encrypted hard disks when they are + plugged in or at boot, entering an SSL certificate passphrase for + web and VPN servers. + + Existing agents are: + + + A boot-time password agent asking the user for + passwords using + plymouth8, + + + A boot-time password agent querying the user + directly on the console — + systemd-ask-password-console.service8, + + + An agent requesting password input via a + wall1 + message — + systemd-ask-password-wall.service8, + + + A TTY agent that is temporarily spawned during + systemctl1 + invocations, + + A command line agent which can be started + temporarily to process queued password + requests — systemd-tty-ask-password-agent --query. + + + + Answering system-wide password queries is a privileged operation, hence + all the agents listed above (except for the last one), run as privileged + system services. The last one also needs elevated privileges, so + should be run through + sudo8 + or similar. + + Additional password agents may be implemented according to + the systemd + Password Agent Specification. + + If a password is queried on a TTY, the user may press TAB to + hide the asterisks normally shown for each character typed. + Pressing Backspace as first key achieves the same effect. + + + + + Options + + The following options are understood: + + + + + + Specify an icon name alongside the password + query, which may be used in all agents supporting graphical + display. The icon name should follow the XDG + Icon Naming Specification. + + + + + Specify an identifier for this password + query. This identifier is freely choosable and allows + recognition of queries by involved agents. It should include + the subsystem doing the query and the specific object the + query is done for. Example: + --id=cryptsetup:/dev/sda5. + + + + + Configure a kernel keyring key name to use as + cache for the password. If set, then the tool will try to push + any collected passwords into the kernel keyring of the root + user, as a key of the specified name. If combined with + , it will also try to retrieve + such cached passwords from the key in the kernel keyring + instead of querying the user right away. By using this option, + the kernel keyring may be used as effective cache to avoid + repeatedly asking users for passwords, if there are multiple + objects that may be unlocked with the same password. The + cached key will have a timeout of 2.5min set, after which it + will be purged from the kernel keyring. Note that it is + possible to cache multiple passwords under the same keyname, + in which case they will be stored as NUL-separated list of + passwords. Use + keyctl1 + to access the cached key via the kernel keyring + directly. Example: --keyname=cryptsetup + + + + + + Specify the query timeout in seconds. Defaults + to 90s. A timeout of 0 waits indefinitely. + + + + + + Echo the user input instead of masking it. + This is useful when using + systemd-ask-password to query for + usernames. + + + + + + Never ask for password on current TTY even if + one is available. Always use agent system. + + + + + + If passed, accept cached passwords, i.e. + passwords previously entered. + + + + + + When used in conjunction with + accept multiple passwords. + This will output one password per line. + + + + + + Do not print passwords to standard output. + This is useful if you want to store a password in kernel + keyring with but do not want it + to show up on screen or in logs. + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + See Also + + systemd1, + systemd-ask-password-console.service8, + systemd-tty-ask-password-agent1, + keyctl1, + plymouth8, + wall1 + + + + diff --git a/man/systemd-backlight@.service.xml b/man/systemd-backlight@.service.xml new file mode 100644 index 00000000..6e836d69 --- /dev/null +++ b/man/systemd-backlight@.service.xml @@ -0,0 +1,69 @@ + + + + + + + + systemd-backlight@.service + systemd + + + + systemd-backlight@.service + 8 + + + + systemd-backlight@.service + systemd-backlight + Load and save the display backlight brightness at boot and shutdown + + + + systemd-backlight@.service + /usr/lib/systemd/systemd-backlight + + + + Description + + systemd-backlight@.service is a service + that restores the display backlight brightness at early boot and + saves it at shutdown. On disk, the backlight brightness is stored + in /var/lib/systemd/backlight/. During + loading, if the udev property is + not set to false, the brightness is clamped to a value of at + least 1 or 5% of maximum brightness, whichever is greater. This + restriction will be removed when the kernel allows user space to + reliably set a brightness value which does not turn off the + display. + + + + Kernel Command Line + + systemd-backlight understands the + following kernel command line parameter: + + + + systemd.restore_state= + + Takes a boolean argument. Defaults to + 1. If 0, does not + restore the backlight settings on boot. However, settings will + still be stored on shutdown. + + + + + + See Also + + systemd1 + + + + diff --git a/man/systemd-binfmt.service.xml b/man/systemd-binfmt.service.xml new file mode 100644 index 00000000..27e34195 --- /dev/null +++ b/man/systemd-binfmt.service.xml @@ -0,0 +1,60 @@ + + + + + + + + systemd-binfmt.service + systemd + + + + systemd-binfmt.service + 8 + + + + systemd-binfmt.service + systemd-binfmt + Configure additional binary formats for executables at boot + + + + systemd-binfmt.service + /usr/lib/systemd/systemd-binfmt + + + + Description + + systemd-binfmt.service is an early boot + service that registers additional binary formats for executables + in the kernel. + + See + binfmt.d5 + for information about the configuration of this service. + + + Options + + + + + + + + + + See Also + + systemd1, + binfmt.d5, + wine8 + + + + diff --git a/man/systemd-bless-boot-generator.xml b/man/systemd-bless-boot-generator.xml new file mode 100644 index 00000000..0c5144f6 --- /dev/null +++ b/man/systemd-bless-boot-generator.xml @@ -0,0 +1,48 @@ + + + + + + + + systemd-bless-boot-generator + systemd + + + + systemd-bless-boot-generator + 8 + + + + systemd-bless-boot-generator + Pull systemd-bless-boot.service into the initial boot transaction when boot counting is in effect. + + + + /usr/lib/systemd/system-generators/systemd-bless-boot-generator + + + + Description + + systemd-bless-boot-generator is a generator that pulls + systemd-bless-boot.service into the initial boot transaction when boot counting, as + implemented by systemd-boot7, is + enabled. + + systemd-bless-boot-generator implements + systemd.generator7. + + + + See Also + + systemd1, + systemd-bless-boot.service8, + systemd-boot7 + + + + diff --git a/man/systemd-bless-boot.service.xml b/man/systemd-bless-boot.service.xml new file mode 100644 index 00000000..cd5e9ac0 --- /dev/null +++ b/man/systemd-bless-boot.service.xml @@ -0,0 +1,112 @@ + + + + + + + + systemd-bless-boot.service + systemd + + + + systemd-bless-boot.service + 8 + + + + systemd-bless-boot.service + Mark current boot process as successful + + + + systemd-bless-boot.service + /usr/lib/systemd/system-bless-boot + + + + Description + + systemd-bless-boot.service is a system service that marks the current boot process as + successful. It's automatically pulled into the initial transaction when + systemd-bless-boot-generator8 + detects that systemd-boot7 style + boot counting is used. + + Internally, the service operates based on the LoaderBootCountPath EFI variable (of the + vendor UUID 4a67b082-0a4c-41cf-b6c7-440b29bb8c4), which is passed from the boot loader to the + OS. It contains a file system path (relative to the EFI system partition) of the Boot Loader Specification compliant boot loader entry + file or unified kernel image file that was used to boot up the + system. systemd-bless-boot.service removes the two 'tries done' and 'tries left' numeric boot + counters from the filename, which indicates to future invocations of the boot loader that the entry has completed + booting successfully at least once. (This service will hence rename the boot loader entry file or unified kernel + image file on the first successful boot.) + + + + Options + + The /usr/lib/systemd/system-bless-boot executable may also be invoked from the + command line, taking one of the following command arguments: + + + + + + The current status of the boot loader entry file or unified kernel image file is shown. This + outputs one of good, bad, indeterminate, + clean, depending on the state and previous invocations of the command. The string + indeterminate is shown initially after boot, before it has been marked as "good" or + "bad". The string good is shown after the boot was marked as "good" with the + command below, and "bad" conversely after the command was + invoked. The string clean is returned when boot counting is currently not in effect. + + This command is implied if no command argument is specified. + + + + + + When invoked, the current boot loader entry file or unified kernel image file will be marked as + "good", executing the file rename operation described above. This command is intended to be invoked at the end + of a successful boot. The systemd-bless-boot.service unit invokes this + command. + + + + + + When called the 'tries left' counter in the boot loader entry file name or unified kernel image + file name is set to zero, marking the boot loader entry or kernel image as "bad", so that the boot loader won't + consider it anymore on future boots (at least as long as there are other entries available that are not marked + "bad" yet). This command is normally not executed, but can be used to instantly put an end to the boot counting + logic if a problem is detected and persistently mark the boot entry as bad. + + + + + + This command undoes any marking of the current boot loader entry file or unified kernel image + file as good or bad. This is implemented by renaming the boot loader entry file or unified kernel image file + back to the path encoded in the LoaderBootCountPath EFI variable. + + + + + + + + + + See Also + + systemd1, + systemd-boot7, + systemd.special1 + + + + diff --git a/man/systemd-boot-check-no-failures.service.xml b/man/systemd-boot-check-no-failures.service.xml new file mode 100644 index 00000000..d6d587f9 --- /dev/null +++ b/man/systemd-boot-check-no-failures.service.xml @@ -0,0 +1,51 @@ + + + + + + + + systemd-boot-check-no-failures.service + systemd + + + + systemd-boot-check-no-failures.service + 8 + + + + systemd-boot-check-no-failures.service + verify that the system booted up cleanly + + + + systemd-boot-check-no-failures.service + /usr/lib/systemd/system-boot-check-no-failures + + + + Description + + systemd-boot-check-no-failures.service is a system service that checks whether the + system booted up successfully. This service implements a very minimal test only: whether there are any failed units on + the system. This service is disabled by default. When enabled, it is ordered before + boot-complete.target, thus ensuring the target cannot be reached when the system booted up + with failed services. + + Note that due the simple nature of this check this service is probably not suitable for deployment in most + scenarios. It is primarily useful only as example for developing more fine-grained checks to order before + boot-complete.target. + + + + See Also + + systemd1, + systemd.special1 + + + + diff --git a/man/systemd-boot-system-token.service.xml b/man/systemd-boot-system-token.service.xml new file mode 100644 index 00000000..b2948a5c --- /dev/null +++ b/man/systemd-boot-system-token.service.xml @@ -0,0 +1,76 @@ + + + + + + + + systemd-boot-system-token.service + systemd + + + + systemd-boot-system-token.service + 8 + + + + systemd-boot-system-token.service + Generate an initial boot loader system token and random seed + + + + systemd-boot-system-token.service + + + + Description + + systemd-boot-system-token.service is a system service that automatically + generates a 'system token' to store in an EFI variable in the system's NVRAM and a random seed to store + on the EFI System Partition ESP on disk. The boot loader may then combine these two randomized data + fields by cryptographic hashing, and pass it to the OS it boots as initialization seed for its entropy + pool. The random seed stored in the ESP is refreshed on each reboot ensuring that multiple subsequent + boots will boot with different seeds. The 'system token' is generated randomly once, and then + persistently stored in the system's EFI variable storage. + + The systemd-boot-system-token.service unit invokes the bootctl + random-seed command, which updates the random seed in the ESP, and initializes the 'system + token' if it's not initialized yet. The service is conditionalized so that it is run only when all of the + below apply: + + + A boot loader is used that implements the Boot Loader Interface (which defines the 'system + token' concept). + + Either a 'system token' was not set yet, or the boot loader has not passed the OS a + random seed yet (and thus most likely has been missing the random seed file in the + ESP). + + The system is not running in a VM environment. This case is explicitly excluded since + on VM environments the ESP backing storage and EFI variable storage is typically not physically + separated and hence booting the same OS image in multiple instances would replicate both, thus reusing + the same random seed and 'system token' among all instances, which defeats its purpose. Note that it's + still possible to use boot loader random seed provisioning in this mode, but the automatic logic + implemented by this service has no effect then, and the user instead has to manually invoke the + bootctl random-seed acknowledging these restrictions. + + + For further details see + bootctl1, regarding + the command this service invokes. + + + + See Also + + systemd1, + bootctl1, + systemd-boot7 + + + + diff --git a/man/systemd-boot.xml b/man/systemd-boot.xml new file mode 100644 index 00000000..da8ddb5f --- /dev/null +++ b/man/systemd-boot.xml @@ -0,0 +1,490 @@ + + + + + + + systemd-boot + systemd + + + + systemd-boot + 7 + + + + systemd-boot + sd-boot + A simple UEFI boot manager + + + + Description + + systemd-boot (short: sd-boot) is a simple UEFI boot + manager. It provides a graphical menu to select the entry to boot and an editor for the kernel command + line. systemd-boot supports systems with UEFI firmware only. + + systemd-boot loads boot entry information from the EFI system partition (ESP), + usually mounted at /efi/, /boot/, or + /boot/efi/ during OS runtime, as well as from the Extended Boot Loader partition if + it exists (usually mounted to /boot/). Configuration file fragments, kernels, + initrds and other EFI images to boot generally need to reside on the ESP or the Extended Boot Loader + partition. Linux kernels must be built with to be able to be directly + executed as an EFI image. During boot systemd-boot automatically assembles a list of + boot entries from the following sources: + + + Boot entries defined with Boot Loader Specification description files + located in /loader/entries/ on the ESP and the Extended Boot Loader + Partition. These usually describe Linux kernel images with associated initrd images, but alternatively + may also describe arbitrary other EFI executables. + + Unified kernel images following the Boot Loader Specification, as executable EFI + binaries in /EFI/Linux/ on the ESP and the Extended Boot Loader Partition. + + + The Microsoft Windows EFI boot manager, if installed + + The Apple MacOS X boot manager, if installed + + The EFI Shell binary, if installed + + A reboot into the UEFI firmware setup option, if supported by the firmware + + + systemd-boot supports the following features: + + + Basic boot manager configuration changes (such as timeout + configuration, default boot entry selection, …) may be made directly from the boot loader UI at + boot-time, as well as during system runtime with EFI variables. + + The boot manager integrates with the systemctl command to implement + features such as systemctl reboot --boot-loader-entry=… (for rebooting into a + specific boot menu entry, i.e. "reboot into Windows") and systemctl reboot + --boot-loader-menu=… (for rebooting into the boot loader menu), by implementing the Boot Loader Interface. See + systemctl1 for + details. + + An EFI variable set by the boot loader informs the OS about the ESP partition used + during boot. This is then used to automatically mount the correct ESP partition to + /efi/ or /boot/ during OS runtime. See + systemd-gpt-auto-generator8 + for details. + + The boot manager provides information about the boot time spent in UEFI firmware using + the Boot Loader Interface. This + information can be displayed using + systemd-analyze1. + + + The boot manager implements boot counting and automatic fallback to older, working boot + entries on failure. See Automatic Boot + Assessment. + + The boot manager optionally reads a random seed from the ESP partition, combines it + with a 'system token' stored in a persistant EFI variable and derives a random seed to use by the OS as + entropy pool initializaton, providing a full entropy pool during early boot. + + + bootctl1 + may be used from a running system to locate the ESP and the Extended Boot Loader Partition, list + available entries, and install systemd-boot itself. + + kernel-install8 + may be used to copy kernel images onto the ESP or the Extended Boot Loader Partition and to generate + description files compliant with the Boot Loader + Specification. + + + + Key bindings + The following keys may be used in the boot menu: + + + + ↑ (Up) + ↓ (Down) + j + k + PageUp + PageDown + Home + End + Navigate up/down in the entry list + + + + ↵ (Enter) + Boot selected entry + + + + d + Make selected entry the default + + + + e + Edit the kernel command line for selected entry + + + + + + t + Increase the timeout before default entry is booted + + + + - + T + Decrease the timeout + + + + v + Show systemd-boot, UEFI, and firmware versions + + + + P + Print status + + + + Q + Quit + + + + h + ? + Show a help screen + + + + Ctrll + Reprint the screen + + + + The following keys may be used during bootup or in the boot menu to + directly boot a specific entry: + + + + l + Linux + + + + w + Windows + + + + a + OS X + + + + s + EFI shell + + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + Boot entry number 1 … 9 + + + + In the editor, most keys simply insert themselves, but the following keys + may be used to perform additional actions: + + + + ← (Left) + → (Right) + Home + End + Navigate left/right + + + + Esc + Abort the edit and quit the editor + + + + Ctrlk + Clear the command line + + + + Ctrlw + AltBackspace + Delete word backwards + + + + Altd + Delete word forwards + + + + ↵ (Enter) + Boot entry with the edited command line + + + + Note that unless configured otherwise in the UEFI firmware, systemd-boot will + use the US keyboard layout, so key labels might not match for keys like +/-. + + + + + Files + + The files systemd-boot processes generally reside on the UEFI ESP which is + usually mounted to /efi/, /boot/ or + /boot/efi/ during OS runtime. It also processes files on the Extended Boot Loader + partition which is typically mounted to /boot/, if it + exists. systemd-boot reads runtime configuration such as the boot timeout and default + entry from /loader/loader.conf on the ESP (in combination with data read from EFI + variables). See + loader.conf5. Boot + entry description files following the Boot + Loader Specification are read from /loader/entries/ on the ESP and the + Extended Boot Loader partition. Unified kernel boot entries following the Boot Loader Specification are read from + /EFI/Linux/ on the ESP and the Extended Boot Loader partition. Optionally, a random + seed for early boot entropy pool provisioning is stored in /loader/random-seed in + the ESP. + + + + EFI Variables + + The following EFI variables are defined, set and read by systemd-boot, under the vendor + UUID 4a67b082-0a4c-41cf-b6c7-440b29bb8c4, for communication between the OS and the boot + loader: + + + + LoaderBootCountPath + If boot counting is enabled, contains the path to the file in whose name the boot counters are + encoded. Set by the boot + loader. systemd-bless-boot.service8 + uses this information to mark a boot as successful as determined by the successful activation of the + boot-complete.target target unit. + + + + LoaderConfigTimeout + LoaderConfigTimeoutOneShot + The menu timeout in seconds. Read by the boot loader. LoaderConfigTimeout + is maintained persistently, while LoaderConfigTimeoutOneShot is a one-time override which is + read once (in which case it takes precedence over LoaderConfigTimeout) and then + removed. LoaderConfigTimeout may be manipulated with the + t/T keys, see above.) + + + + LoaderDevicePartUUID + + Contains the partition UUID of the EFI System Partition the boot loader was run from. Set by + the boot + loader. systemd-gpt-auto-generator8 + uses this information to automatically find the disk booted from, in order to discover various other partitions + on the same disk automatically. + + + + LoaderEntries + + A list of the identifiers of all discovered boot loader entries. Set by the boot + loader. + + + + LoaderEntryDefault + LoaderEntryOneShot + + The identifier of the default boot loader entry. Set primarily by the OS and read by the boot + loader. LoaderEntryOneShot sets the default entry for the next boot only, while + LoaderEntryDefault sets it persistently for all future + boots. bootctl1's + and commands make use of these variables. The boot + loader modifies LoaderEntryDefault on request, when the d key is used, see + above.) + + + + LoaderEntrySelected + + The identifier of the boot loader entry currently being booted. Set by the boot + loader. + + + + LoaderFeatures + + A set of flags indicating the features the boot loader supports. Set by the boot loader. Use + bootctl1 to view this + data. + + + + LoaderFirmwareInfo + LoaderFirmwareType + + Brief firmware information. Set by the boot loader. Use + bootctl1 to view this + data. + + + + LoaderImageIdentifier + + The path of executable of the boot loader used for the current boot, relative to the EFI System + Partition's root directory. Set by the boot loader. Use + bootctl1 to view this + data. + + + + LoaderInfo + + Brief information about the boot loader. Set by the boot loader. Use + bootctl1 to view this + data. + + + + LoaderTimeExecUSec + LoaderTimeInitUSec + LoaderTimeMenuUsec + + Information about the time spent in various parts of the boot loader. Set by the boot + loader. Use systemd-analyze1 + to view this data. + + + + LoaderRandomSeed + + A binary random seed systemd-boot may optionally pass to the + OS. This is a volatile EFI variable that is hashed at boot from the combination of a random seed + stored in the ESP (in /loader/random-seed) and a "system token" persistently + stored in the EFI variable LoaderSystemToken (see below). During early OS boot the + system manager reads this variable and passes it to the OS kernel's random pool, crediting the full + entropy it contains. This is an efficient way to ensure the system starts up with a fully initialized + kernel random pool — as early as the initial RAM disk phase. systemd-boot reads + the random seed from the ESP, combines it with the "system token", and both derives a new random seed + to update in-place the seed stored in the ESP, and the random seed to pass to the OS from it via + SHA256 hashing in counter mode. This ensures that different physical systems that boot the same + "golden" OS image — i.e. containing the same random seed file in the ESP — will still pass a + different random seed to the OS. It is made sure the random seed stored in the ESP is fully + overwritten before the OS is booted, to ensure different random seed data is used between subsequent + boots. + + See Random Seeds for + further information. + + + + LoaderSystemToken + + A binary random data field, that is used for generating the random see to pass to the + OS (see above). Note that this random data is generally only generated once, during OS installation, + and is then never updated again. + + + + Many of these variables are defined by the Boot Loader Interface. + + + + Boot Counting + + systemd-boot implements a simple boot counting mechanism on top of the Boot Loader Specification, for automatic and unattended + fallback to older kernel versions/boot loader entries when a specific entry continuously fails. Any boot loader + entry file and unified kernel image file that contains a + followed by one or two numbers (if + two they need to be separated by a -), before the .conf or + .efi suffix is subject to boot counting: the first of the two numbers ('tries left') is + decreased by one on every boot attempt, the second of the two numbers ('tries done') is increased by one (if 'tries + done' is absent it is considered equivalent to 0). Depending on the current value of these two counters the boot + entry is considered to be in one of three states: + + + If the 'tries left' counter of an entry is greater than zero the entry is considered to be in + 'indeterminate' state. This means the entry has not completed booting successfully yet, but also hasn't been + determined not to work. + + If the 'tries left' counter of an entry is zero it is considered to be in 'bad' state. This means + no further attempts to boot this item will be made (that is, unless all other boot entries are also in 'bad' + state), as all attempts to boot this entry have not completed successfully. + + If the 'tries left' and 'tries done' counters of an entry are absent it is considered to be in + 'good' state. This means further boot counting for the entry is turned off, as it successfully booted at least + once. The + systemd-bless-boot.service8 + service moves the currently booted entry from 'indeterminate' into 'good' state when a boot attempt completed + successfully. + + + Generally, when new entries are added to the boot loader, they first start out in 'indeterminate' state, + i.e. with a 'tries left' counter greater than zero. The boot entry remains in this state until either it managed to + complete a full boot successfully at least once (in which case it will be in 'good' state) — or the 'tries left' + counter reaches zero (in which case it will be in 'bad' state). + + Example: let's say a boot loader entry file foo.conf is set up for 3 boot tries. The + installer will hence create it under the name foo+3.conf. On first boot, the boot loader will + rename it to foo+2-1.conf. If that boot does not complete successfully, the boot loader will + rename it to foo+1-2.conf on the following boot. If that fails too, it will finally be renamed + foo+0-3.conf by the boot loader on next boot, after which it will be considered 'bad'. If the + boot succeeds however the entry file will be renamed to foo.conf by the OS, so that it is + considered 'good' from then on. + + The boot menu takes the 'tries left' counter into account when sorting the menu entries: entries in 'bad' + state are ordered at the end of the list, and entries in 'good' or 'indeterminate' at the beginning. The user can + freely choose to boot any entry of the menu, including those already marked 'bad'. If the menu entry to boot is + automatically determined, this means that 'good' or 'indeterminate' entries are generally preferred (as the top item of + the menu is the one booted by default), and 'bad' entries will only be considered if there are no 'good' or + 'indeterminate' entries left. + + The kernel-install8 kernel + install framework optionally sets the initial 'tries left' counter to the value specified in + /etc/kernel/tries when a boot loader entry is first created. + + + + See Also + + bootctl1, + loader.conf5, + systemd-bless-boot.service8, + systemd-boot-system-token.service8, + kernel-install8, + Boot Loader Specification, + Boot Loader Interface + + + diff --git a/man/systemd-cat.xml b/man/systemd-cat.xml new file mode 100644 index 00000000..96d3072a --- /dev/null +++ b/man/systemd-cat.xml @@ -0,0 +1,174 @@ + + + + + + + + systemd-cat + systemd + + + + systemd-cat + 1 + + + + systemd-cat + Connect a pipeline or program's output with the journal + + + + + systemd-cat OPTIONS COMMAND ARGUMENTS + + + systemd-cat OPTIONS + + + + + Description + + systemd-cat may be used to connect the + standard input and output of a process to the journal, or as a + filter tool in a shell pipeline to pass the output the previous + pipeline element generates to the journal. + + If no parameter is passed, systemd-cat + will write everything it reads from standard input (stdin) to the + journal. + + If parameters are passed, they are executed as command line + with standard output (stdout) and standard error output (stderr) + connected to the journal, so that all it writes is stored in the + journal. + + + + Options + + The following options are understood: + + + + + + + + + + Specify a short string that is used to + identify the logging tool. If not specified, no identification + string is written to the journal. + + + + + + + Specify the default priority level for the + logged messages. Pass one of + emerg, + alert, + crit, + err, + warning, + notice, + info, + debug, or a + value between 0 and 7 (corresponding to the same named + levels). These priority values are the same as defined by + syslog3. + Defaults to info. Note that this simply + controls the default, individual lines may be logged with + different levels if they are prefixed accordingly. For details, + see below. + + + + + + Specifies the default priority level for + messages from the process's standard error output (stderr). + Usage of this option is the same as the + option, above, and both can be + used at once. When both are used, + will specify the default priority for standard output (stdout). + + + If is not specified, + messages from stderr will still be logged, with the same + default priority level as stdout. + + Also, note that when stdout and stderr use the same + default priority, the messages will be strictly ordered, + because one channel is used for both. When the default priority + differs, two channels are used, and so stdout messages will not + be strictly ordered with respect to stderr messages - though + they will tend to be approximately ordered. + + + + + + Controls whether lines read are parsed for + syslog priority level prefixes. If enabled (the default), a + line prefixed with a priority prefix such as + <5> is logged at priority 5 + (notice), and similar for the other + priority levels. Takes a boolean argument. + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + Examples + + + Invoke a program + + This calls /bin/ls + with standard output and error connected to the journal: + + # systemd-cat ls + + + + Usage in a shell pipeline + + This builds a shell pipeline also invoking + /bin/ls and writes the output it generates + to the journal: + + # ls | systemd-cat + + + Even though the two examples have very similar effects the + first is preferable since only one process is running at a time, + and both stdout and stderr are captured while in the second + example, only stdout is captured. + + + + See Also + + systemd1, + systemctl1, + logger1 + + + + diff --git a/man/systemd-cgls.xml b/man/systemd-cgls.xml new file mode 100644 index 00000000..6181cdf8 --- /dev/null +++ b/man/systemd-cgls.xml @@ -0,0 +1,133 @@ + + + + + + + + systemd-cgls + systemd + + + + systemd-cgls + 1 + + + + systemd-cgls + Recursively show control group contents + + + + + systemd-cgls + OPTIONS + CGROUP + + + systemd-cgls + OPTIONS + | + UNIT + + + + + Description + + systemd-cgls recursively shows the + contents of the selected Linux control group hierarchy in a tree. + If arguments are specified, shows all member processes of the + specified control groups plus all their subgroups and their + members. The control groups may either be specified by their full + file paths or are assumed in the systemd control group hierarchy. + If no argument is specified and the current working directory is + beneath the control group mount point + /sys/fs/cgroup, shows the contents of the + control group the working directory refers to. Otherwise, the full + systemd control group hierarchy is shown. + + By default, empty control groups are not shown. + + + + Options + + The following options are understood: + + + + + + Do not hide empty control groups in the + output. + + + + + + + Do not ellipsize process tree members. + + + + + + + + Show cgroup subtrees for the specified units. + + + + + + + Show cgroup subtrees for the specified user units. + + + + + + + Include kernel threads in output. + + + + + + + + Limit control groups shown to the part + corresponding to the container + MACHINE. + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + See Also + + systemd1, + systemctl1, + systemd-cgtop1, + systemd-nspawn1, + ps1 + + + + diff --git a/man/systemd-cgtop.xml b/man/systemd-cgtop.xml new file mode 100644 index 00000000..5beeb586 --- /dev/null +++ b/man/systemd-cgtop.xml @@ -0,0 +1,356 @@ + + + + + + + + systemd-cgtop + systemd + + + + systemd-cgtop + 1 + + + + systemd-cgtop + Show top control groups by their resource usage + + + + + systemd-cgtop + OPTIONS + GROUP + + + + + Description + + systemd-cgtop shows the top control + groups of the local Linux control group hierarchy, ordered by + their CPU, memory, or disk I/O load. The display is refreshed in + regular intervals (by default every 1s), similar in style to + top1. + If a control group path is specified, shows only the services of + the specified control group. + + If systemd-cgtop is not connected to a + tty, no column headers are printed and the default is to only run + one iteration. The argument, if + given, is honored. This mode is suitable for scripting. + + Resource usage is only accounted for control groups in the + relevant hierarchy, i.e. CPU usage is only accounted for control + groups in the cpuacct hierarchy, memory usage + only for those in memory and disk I/O usage for + those in blkio. If resource monitoring for + these resources is required, it is recommended to add the + CPUAccounting=1, + MemoryAccounting=1 and + BlockIOAccounting=1 settings in the unit files + in question. See + systemd.resource-control5 + for details. + + The CPU load value can be between 0 and 100 times the number of + processors the system has. For example, if the system has 8 processors, + the CPU load value is going to be between 0% and 800%. The number of + processors can be found in /proc/cpuinfo. + + To emphasize this: unless + CPUAccounting=1, + MemoryAccounting=1 and + BlockIOAccounting=1 are enabled for the + services in question, no resource accounting will be available for + system services and the data shown by + systemd-cgtop will be incomplete. + + + + Options + + The following options are understood: + + + + + + + Order by control group + path name. + + + + + + + Order by number of tasks/processes in the control group. + + + + + + + Order by CPU load. + + + + + + + Order by memory usage. + + + + + + + Order by disk I/O load. + + + + + + + Run in "batch" mode: do not accept input and + run until the iteration limit set with + is exhausted or until killed. + This mode could be useful for sending output from + systemd-cgtop to other programs or to a + file. + + + + + + + Format byte counts (as in memory usage and I/O metrics) + with raw numeric values rather than human-readable + numbers. + + + + + + + Controls whether the CPU usage is shown as + percentage or time. By default, the CPU usage is shown as + percentage. This setting may also be toggled at runtime by + pressing the % key. + + + + + + Count only userspace processes instead of all + tasks. By default, all tasks are counted: each kernel thread + and each userspace thread individually. With this setting, + kernel threads are excluded from the counting and each + userspace process only counts as one, regardless how many + threads it consists of. This setting may also be toggled at + runtime by pressing the P key. This option + may not be combined with + . + + + + + + Count only userspace processes and kernel + threads instead of all tasks. By default, all tasks are + counted: each kernel thread and each userspace thread + individually. With this setting, kernel threads are included in + the counting and each userspace process only counts as on one, + regardless how many threads it consists of. This setting may + also be toggled at runtime by pressing the k + key. This option may not be combined with + . + + + + + + Controls whether the number of processes shown + for a control group shall include all processes that are + contained in any of the child control groups as well. Takes a + boolean argument, which defaults to yes. If + enabled, the processes in child control groups are included, if + disabled, only the processes in the control group itself are + counted. This setting may also be toggled at runtime by + pressing the r key. Note that this setting + only applies to process counting, i.e. when the + or options are + used. It has not effect if all tasks are counted, in which + case the counting is always recursive. + + + + + + + Perform only this many iterations. A value of + 0 indicates that the program should run + indefinitely. + + + + + + A shortcut for . + + + + + + + Specify refresh delay in seconds (or if one of + ms, us, + min is specified as unit in this time + unit). This setting may also be increased and decreased at + runtime by pressing the + and + - keys. + + + + + + Maximum control group tree traversal depth. + Specifies how deep systemd-cgtop shall + traverse the control group hierarchies. If 0 is specified, + only the root group is monitored. For 1, only the first level + of control groups is monitored, and so on. Defaults to + 3. + + + + + + + Limit control groups shown to the part + corresponding to the container + MACHINE. + This option may not be used when a control group path is specified. + + + + + + + + + + Keys + + systemd-cgtop is an interactive tool and + may be controlled via user input using the following keys: + + + + h + + Shows a short help text. + + + + + + Immediately refresh output. + + + + q + + Terminate the program. + + + + p + t + c + m + i + + Sort the control groups by path, number of + tasks, CPU load, memory usage, or I/O load, respectively. This + setting may also be controlled using the + command line + switch. + + + + % + + Toggle between showing CPU time as time or + percentage. This setting may also be controlled using the + command line switch. + + + + + + - + + Increase or decrease refresh delay, + respectively. This setting may also be controlled using the + command line + switch. + + + + P + + Toggle between counting all tasks, or only + userspace processes. This setting may also be controlled using + the command line switch (see + above). + + + + k + + Toggle between counting all tasks, or only + userspace processes and kernel threads. This setting may also + be controlled using the command line + switch (see above). + + + + r + + Toggle between recursively including or + excluding processes in child control groups in control group + process counts. This setting may also be controlled using the + command line switch. This key is + not available if all tasks are counted, it is only available + if processes are counted, as enabled with the + P or k + keys. + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + See Also + + systemd1, + systemctl1, + systemd-cgls1, + systemd.resource-control5, + top1 + + + + diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml new file mode 100644 index 00000000..1ab7e598 --- /dev/null +++ b/man/systemd-coredump.xml @@ -0,0 +1,149 @@ + + + + + + + + systemd-coredump + systemd + + + + systemd-coredump + 8 + + + + systemd-coredump + systemd-coredump.socket + systemd-coredump@.service + Acquire, save and process core dumps + + + + /usr/lib/systemd/systemd-coredump + /usr/lib/systemd/systemd-coredump + systemd-coredump@.service + systemd-coredump.socket + + + + Description + systemd-coredump@.service is a system service that can acquire core + dumps from the kernel and handle them in various ways. The systemd-coredump + executable does the actual work. It is invoked twice: once as the handler by the kernel, and the + second time in the systemd-coredump@.service to actually write the data to + the journal. + + When the kernel invokes systemd-coredump to handle a core dump, it runs + in privileged mode, and will connect to the socket created by the + systemd-coredump.socket unit, which in turn will spawn an unprivileged + systemd-coredump@.service instance to process the core dump. Hence + systemd-coredump.socket and systemd-coredump@.service + are helper units which do the actual processing of core dumps and are subject to normal service + management. + + Core dumps can be written to the journal or saved as a file. Once saved they can be retrieved + for further processing, for example in + gdb1. + + + By default, systemd-coredump will log the core dump including a backtrace + if possible to the journal and store the core dump itself in an external file in + /var/lib/systemd/coredump. + + The behavior of a specific program upon reception of a signal is governed by a few + factors which are described in detail in + core5. + In particular, the core dump will only be processed when the related resource limits are sufficient. + + + It is also possible to invoke systemd-coredump with + option. In this case, systemd-coredump expects + a journal entry in the journal + Journal Export Format + on standard input. The entry should contain a MESSAGE= field and any additional + metadata fields the caller deems reasonable. systemd-coredump will append + additional metadata fields in the same way it does for core dumps received from the kernel. In + this mode, no core dump is stored in the journal. + + + + Configuration + For programs started by systemd process resource limits can be set by directive + LimitCore=, see + systemd.exec5. + + + In order to be used by the kernel to handle core dumps, + systemd-coredump must be configured in + sysctl8 + parameter kernel.core_pattern. The syntax of this parameter is explained in + core5. + systemd installs the file /usr/lib/sysctl.d/50-coredump.conf which configures + kernel.core_pattern accordingly. This file may be masked or overridden to use a different + setting following normal + sysctl.d5 + rules. If the sysctl configuration is modified, it must be updated in the kernel before it + takes effect, see + sysctl8 + and + systemd-sysctl8. + + + In order to by used in the mode, an appropriate backtrace + handler must be installed on the sender side. For example, in case of + python1, this + means a sys.excepthook must installed, see + systemd-coredump-python. + + + The behavior of systemd-coredump itself is configured through the configuration file + /etc/systemd/coredump.conf and corresponding snippets + /etc/systemd/coredump.conf.d/*.conf, see + coredump.conf5. A new + instance of systemd-coredump is invoked upon receiving every core dump. Therefore, changes + in these files will take effect the next time a core dump is received. + + Resources used by core dump files are restricted in two ways. Parameters like maximum size of acquired + core dumps and files can be set in files /etc/systemd/coredump.conf and snippets mentioned + above. In addition the storage time of core dump files is restricted by systemd-tmpfiles, + corresponding settings are by default in /usr/lib/tmpfiles.d/systemd.conf. + + + Disabling coredump processing + + To disable potentially resource-intensive processing by systemd-coredump, + set Storage=none +ProcessSizeMax=0 in + coredump.conf5. + + + + + + Usage + Data stored in the journal can be viewed with + journalctl1 + as usual. + coredumpctl1 + can be used to retrieve saved core dumps independent of their location, to display information and to process + them e.g. by passing to the GNU debugger (gdb). + + + + See Also + + coredump.conf5, + coredumpctl1, + systemd-journald.service8, + systemd-tmpfiles8, + core5, + sysctl.d5, + systemd-sysctl.service8. + + + diff --git a/man/systemd-cryptsetup-generator.xml b/man/systemd-cryptsetup-generator.xml new file mode 100644 index 00000000..e3c17d64 --- /dev/null +++ b/man/systemd-cryptsetup-generator.xml @@ -0,0 +1,182 @@ + + + + + + + + systemd-cryptsetup-generator + systemd + + + + systemd-cryptsetup-generator + 8 + + + + systemd-cryptsetup-generator + Unit generator for /etc/crypttab + + + + /usr/lib/systemd/system-generators/systemd-cryptsetup-generator + + + + Description + + systemd-cryptsetup-generator is a + generator that translates /etc/crypttab into + native systemd units early at boot and when configuration of the + system manager is reloaded. This will create + systemd-cryptsetup@.service8 + units as necessary. + + systemd-cryptsetup-generator implements + systemd.generator7. + + + + Kernel Command Line + + systemd-cryptsetup-generator + understands the following kernel command line parameters: + + + + luks= + rd.luks= + + Takes a boolean argument. Defaults to + yes. If no, disables the + generator entirely. rd.luks= is honored + only by initial RAM disk (initrd) while + luks= is honored by both the main system + and the initrd. + + + + luks.crypttab= + rd.luks.crypttab= + + Takes a boolean argument. Defaults to + yes. If no, causes the + generator to ignore any devices configured in + /etc/crypttab + (luks.uuid= will still work however). + rd.luks.crypttab= is honored only by + initial RAM disk (initrd) while + luks.crypttab= is honored by both the main + system and the initrd. + + + + luks.uuid= + rd.luks.uuid= + + Takes a LUKS superblock UUID as argument. This + will activate the specified device as part of the boot process + as if it was listed in /etc/crypttab. + This option may be specified more than once in order to set up + multiple devices. rd.luks.uuid= is honored + only by initial RAM disk (initrd) while + luks.uuid= is honored by both the main + system and the initrd. + If /etc/crypttab contains entries with the same UUID, + then the name, keyfile and options specified there will be + used. Otherwise, the device will have the name + luks-UUID. + If /etc/crypttab exists, only those UUIDs + specified on the kernel command line + will be activated in the initrd or the real root. + + + + + luks.name= + rd.luks.name= + + Takes a LUKS super block UUID followed by an + = and a name. This implies + rd.luks.uuid= or + luks.uuid= and will additionally make the + LUKS device given by the UUID appear under the provided + name. + + rd.luks.name= is honored only by + initial RAM disk (initrd) while luks.name= + is honored by both the main system and the initrd. + + + + + luks.options= + rd.luks.options= + + Takes a LUKS super block UUID followed by an + = and a string of options separated by + commas as argument. This will override the options for the + given UUID. + If only a list of options, without an UUID, is + specified, they apply to any UUIDs not specified elsewhere, + and without an entry in + /etc/crypttab. + rd.luks.options= is honored only by initial + RAM disk (initrd) while luks.options= is + honored by both the main system and the initrd. + + + + + luks.key= + rd.luks.key= + + Takes a password file name as argument or a + LUKS super block UUID followed by a = and a + password file name. + + For those entries specified with + rd.luks.uuid= or + luks.uuid=, the password file will be set + to the one specified by rd.luks.key= or + luks.key= of the corresponding UUID, or the + password file that was specified without a UUID. + + It is also possible to specify an external device which + should be mounted before we attempt to unlock the LUKS device. + systemd-cryptsetup will use password file stored on that + device. Device containing password file is specified by + appending colon and a device identifier to the password file + path. For example, + rd.luks.uuid=b40f1abf-2a53-400a-889a-2eccc27eaa40 + rd.luks.key=b40f1abf-2a53-400a-889a-2eccc27eaa40=/keyfile:LABEL=keydev. + Hence, in this case, we will attempt to mount file system + residing on the block device with label keydev. + This syntax is for now only supported on a per-device basis, + i.e. you have to specify LUKS device UUID. + + rd.luks.key= + is honored only by initial RAM disk + (initrd) while + luks.key= is + honored by both the main system and + the initrd. + + + + + + + See Also + + systemd1, + crypttab5, + systemd-cryptsetup@.service8, + cryptsetup8, + systemd-fstab-generator8 + + + + diff --git a/man/systemd-cryptsetup@.service.xml b/man/systemd-cryptsetup@.service.xml new file mode 100644 index 00000000..0324a674 --- /dev/null +++ b/man/systemd-cryptsetup@.service.xml @@ -0,0 +1,59 @@ + + + + + + + + systemd-cryptsetup@.service + systemd + + + + systemd-cryptsetup@.service + 8 + + + + systemd-cryptsetup@.service + systemd-cryptsetup + Full disk decryption logic + + + + systemd-cryptsetup@.service + /usr/lib/systemd/systemd-cryptsetup + + + + Description + + systemd-cryptsetup@.service is a + service responsible for setting up encrypted block devices. It is + instantiated for each device that requires decryption for + access. + + systemd-cryptsetup@.service will ask + for hard disk passwords via the + password agent logic, in order to query the user for the + password using the right mechanism at boot and during + runtime. + + At early boot and when the system manager configuration is reloaded, /etc/crypttab is + translated into systemd-cryptsetup@.service units by + systemd-cryptsetup-generator8. + + + + See Also + + systemd1, + systemd-cryptsetup-generator8, + crypttab5, + cryptsetup8 + + + + diff --git a/man/systemd-debug-generator.xml b/man/systemd-debug-generator.xml new file mode 100644 index 00000000..305dc2ff --- /dev/null +++ b/man/systemd-debug-generator.xml @@ -0,0 +1,85 @@ + + + +%entities; +]> + + + + + systemd-debug-generator + systemd + + + + systemd-debug-generator + 8 + + + + systemd-debug-generator + Generator for enabling a runtime debug shell and + masking specific units at boot + + + + /usr/lib/systemd/system-generators/systemd-debug-generator + + + + Description + + systemd-debug-generator is a generator + that reads the kernel command line and understands three + options: + + If the or + option is specified and followed by a unit name, this unit is + masked for the runtime, similar to the effect of + systemctl1's + mask command. This is useful to boot with + certain units removed from the initial boot transaction for + debugging system startup. May be specified more than once. + is honored only by initial + RAM disk (initrd) while is + honored only in the main system. + + If the or + option is specified + and followed by a unit name, a start job for this unit is added to + the initial transaction. This is useful to start one or more + additional units at boot. May be specified more than once. + is honored only by initial + RAM disk (initrd) while is + honored only in the main system. + + If the or + option is + specified, the debug shell service + debug-shell.service is pulled into the boot + transaction and a debug shell will be spawned during early boot. + By default, &DEBUGTTY; is used, but a specific tty can also be set, + either with or without the /dev/ prefix. + Note that the shell may also be turned on persistently by enabling it with + systemctl1's + enable command. + is honored only by initial + RAM disk (initrd) while is + honored only in the main system. + + systemd-debug-generator implements + systemd.generator7. + + + + See Also + + systemd1, + systemctl1, + kernel-command-line7 + + + + diff --git a/man/systemd-delta.xml b/man/systemd-delta.xml new file mode 100644 index 00000000..02d7b885 --- /dev/null +++ b/man/systemd-delta.xml @@ -0,0 +1,178 @@ + + + + + + + + systemd-delta + systemd + + + + systemd-delta + 1 + + + + systemd-delta + Find overridden configuration files + + + + + systemd-delta + OPTIONS + PREFIX/SUFFIX|SUFFIX + + + + + Description + + systemd-delta may be used to identify and + compare configuration files that override other configuration + files. Files in /etc have highest priority, + files in /run have the second highest + priority, …, files in /usr/lib have lowest + priority. Files in a directory with higher priority override files + with the same name in directories of lower priority. In addition, + certain configuration files can have .d + directories which contain "drop-in" files with configuration + snippets which augment the main configuration file. "Drop-in" + files can be overridden in the same way by placing files with the + same name in a directory of higher priority (except that, in case + of "drop-in" files, both the "drop-in" file name and the name of + the containing directory, which corresponds to the name of the + main configuration file, must match). For a fuller explanation, + see + systemd.unit5. + + + The command line argument will be split into a prefix and a + suffix. Either is optional. The prefix must be one of the + directories containing configuration files + (/etc, /run, + /usr/lib, …). If it is given, only + overriding files contained in this directory will be shown. + Otherwise, all overriding files will be shown. The suffix must be + a name of a subdirectory containing configuration files like + tmpfiles.d, sysctl.d or + systemd/system. If it is given, only + configuration files in this subdirectory (across all configuration + paths) will be analyzed. Otherwise, all configuration files will + be analyzed. If the command line argument is not given at all, all + configuration files will be analyzed. See below for some + examples. + + + + Options + + The following options are understood: + + + + + + + When listing the differences, only list those + that are asked for. The list itself is a comma-separated list + of desired difference types. + + Recognized types are: + + + + masked + + Show masked files + + + + equivalent + + Show overridden files that while + overridden, do not differ in content. + + + + redirected + + Show files that are redirected to + another. + + + + overridden + + Show overridden, and changed + files. + + + + extended + + Show *.conf files + in drop-in directories for units. + + + + unchanged + + Show unmodified files + too. + + + + + + + + + When showing modified files, when a file is + overridden show a diff as well. This option takes a boolean + argument. If omitted, it defaults to + . + + + + + + + + + + Examples + + To see all local configuration: + systemd-delta + + To see all runtime configuration: + systemd-delta /run + + To see all system unit configuration changes: + systemd-delta systemd/system + + To see all runtime "drop-in" changes for system units: + systemd-delta --type=extended /run/systemd/system + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + See Also + + systemd1, + systemd.unit5 + + + + diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml new file mode 100644 index 00000000..d599ac20 --- /dev/null +++ b/man/systemd-detect-virt.xml @@ -0,0 +1,267 @@ + + + + + + + + systemd-detect-virt + systemd + + + + systemd-detect-virt + 1 + + + + systemd-detect-virt + Detect execution in a virtualized environment + + + + + systemd-detect-virt + OPTIONS + + + + + Description + + systemd-detect-virt detects execution in + a virtualized environment. It identifies the virtualization + technology and can distinguish full machine virtualization from + container virtualization. systemd-detect-virt + exits with a return value of 0 (success) if a virtualization + technology is detected, and non-zero (error) otherwise. By default, + any type of virtualization is detected, and the options + and can be used + to limit what types of virtualization are detected. + + When executed without will print a + short identifier for the detected virtualization technology. The + following technologies are currently identified: + + + Known virtualization technologies (both + VM, i.e. full hardware virtualization, + and container, i.e. shared kernel virtualization) + + + + + + + Type + ID + Product + + + + + VM + qemu + QEMU software virtualization, without KVM + + + + kvm + Linux KVM kernel virtual machine, with whatever software, except Oracle Virtualbox + + + + zvm + s390 z/VM + + + + vmware + VMware Workstation or Server, and related products + + + + microsoft + Hyper-V, also known as Viridian or Windows Server Virtualization + + + + oracle + Oracle VM VirtualBox (historically marketed by innotek and Sun Microsystems), for legacy and KVM hypervisor + + + + xen + Xen hypervisor (only domU, not dom0) + + + + bochs + Bochs Emulator + + + + uml + User-mode Linux + + + + parallels + Parallels Desktop, Parallels Server + + + + bhyve + bhyve, FreeBSD hypervisor + + + + qnx + QNX hypervisor + + + + acrn + ACRN hypervisor + + + + Container + openvz + OpenVZ/Virtuozzo + + + + lxc + Linux container implementation by LXC + + + + lxc-libvirt + Linux container implementation by libvirt + + + + systemd-nspawn + systemd's minimal container implementation, see systemd-nspawn1 + + + + docker + Docker container manager + + + + podman + Podman container manager + + + + rkt + rkt app container runtime + + + + wsl + Windows Subsystem for Linux + + + +
+ + If multiple virtualization solutions are used, only the + "innermost" is detected and identified. That means if both + machine and container virtualization are used in + conjunction, only the latter will be identified (unless + is passed). + Windows Subsystem for Linux is not a Linux container, + but an environment for running Linux userspace applications on + top of the Windows kernel using a Linux-compatible interface. + WSL is categorized as a container for practical purposes. + Multiple WSL environments share the same kernel and services + should generally behave like when being run in a container. +
+ + + Options + + The following options are understood: + + + + + + + Only detects container virtualization (i.e. + shared kernel virtualization). + + + + + + + Only detects hardware virtualization. + + + + + + + Detect whether invoked in a + chroot2 + environment. In this mode, no output is written, but the return + value indicates whether the process was invoked in a + chroot() + environment or not. + + + + + + Detect whether invoked in a user namespace. In this mode, no + output is written, but the return value indicates whether the process was invoked + inside of a user namespace or not. See + user_namespaces7 + for more information. + + + + + + + Suppress output of the virtualization + technology identifier. + + + + + + Output all currently known and detectable container and VM environments. + + + + + + + + + + Exit status + + If a virtualization technology is detected, 0 is returned, a + non-zero code otherwise. + + + + See Also + + systemd1, + systemd-nspawn1, + chroot2, + namespaces7 + + + +
diff --git a/man/systemd-environment-d-generator.xml b/man/systemd-environment-d-generator.xml new file mode 100644 index 00000000..4c88bd5e --- /dev/null +++ b/man/systemd-environment-d-generator.xml @@ -0,0 +1,53 @@ + + +%entities; +]> + + + + + systemd-environment-d-generator + systemd + + + + systemd-environment-d-generator + 8 + + + + systemd-environment-d-generator + 30-systemd-environment-d-generator + Load variables specified by environment.d + + + + + &userenvgeneratordir;/30-systemd-environment-d-generator + + + + Description + + systemd-environment-d-generator is a + systemd.environment-generator7 + that reads environment configuration specified by + environment.d5 + configuration files and passes it to the + systemd1 + user manager instance. + + + + See Also + + systemd1, + systemctl1, + systemd.environment-generator7, + systemd.generator5 + + + + diff --git a/man/systemd-escape.xml b/man/systemd-escape.xml new file mode 100644 index 00000000..86ef175a --- /dev/null +++ b/man/systemd-escape.xml @@ -0,0 +1,182 @@ + + + + + + + + systemd-escape + systemd + + + + systemd-escape + 1 + + + + systemd-escape + Escape strings for usage in systemd unit names + + + + + systemd-escape + OPTIONS + STRING + + + + + Description + + systemd-escape may be used to escape + strings for inclusion in systemd unit names. The command may be + used to escape and to undo escaping of strings. + + The command takes any number of strings on the command line, + and will process them individually, one after another. It will + output them separated by spaces to stdout. + + By default, this command will escape the strings passed, + unless is passed which results in the + inverse operation being applied. If is given, a + special mode of escaping is applied instead, which assumes the + string is already escaped but will escape everything that + appears obviously non-escaped. + + For details on the escaping and unescaping algorithms see the relevant section in + systemd.unit5. + + + + Options + + The following options are understood: + + + + + + Appends the specified unit type suffix to the + escaped string. Takes one of the unit types supported by + systemd, such as service or + mount. May not be used in conjunction with + , or + . + + + + + + Inserts the escaped strings in a unit name + template. Takes a unit name template such as + foobar@.service. With + , expects instantiated unit names + for this template and extracts and unescapes just the instance + part. May not be used in conjunction with + , + or + . + + + + + + + When escaping or unescaping a string, assume it refers to a file system path. This eliminates + leading, trailing or duplicate / characters and rejects . and + .. path components. This is particularly useful for generating strings suitable for + unescaping with the %f specifier in unit files, see + systemd.unit5. + + + + + + + + Instead of escaping the specified strings, + undo the escaping, reversing the operation. May not be used in + conjunction with or + . + + + + + + + Like , but only + escape characters that are obviously not escaped yet, and + possibly automatically append an appropriate unit type suffix + to the string. May not be used in conjunction with + , or + . + + + + + + With , unescape + and print only the instance part of an instantiated unit name + template. Results in an error for an uninstantiated template + like ssh@.service or a non-template name + like ssh.service. + Must be used in conjunction with + and may not be used in conjunction with + . + + + + + + + + + + Examples + + To escape a single string: + $ systemd-escape 'Hallöchen, Meister' +Hall\xc3\xb6chen\x2c\x20Meister + + To undo escaping on a single string: + $ systemd-escape -u 'Hall\xc3\xb6chen\x2c\x20Meister' +Hallöchen, Meister + + To generate the mount unit for a path: + $ systemd-escape -p --suffix=mount "/tmp//waldi/foobar/" +tmp-waldi-foobar.mount + + To generate instance names of three strings: + $ systemd-escape --template=systemd-nspawn@.service 'My Container 1' 'containerb' 'container/III' +systemd-nspawn@My\x20Container\x201.service systemd-nspawn@containerb.service systemd-nspawn@container-III.service + + To extract the instance part of an instantiated unit: + $ systemd-escape -u --instance 'systemd-nspawn@My\x20Container\x201.service' +My Container 1 + + To extract the instance part of an instance of a particular template: + $ systemd-escape -u --template=systemd-nspawn@.service 'systemd-nspawn@My\x20Container\x201.service' +My Container 1 + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + See Also + + systemd1, + systemd.unit5, + systemctl1 + + + + diff --git a/man/systemd-firstboot.xml b/man/systemd-firstboot.xml new file mode 100644 index 00000000..560649f2 --- /dev/null +++ b/man/systemd-firstboot.xml @@ -0,0 +1,268 @@ + + + + + + + + systemd-firstboot + systemd + + + + systemd-firstboot + 1 + + + + systemd-firstboot + systemd-firstboot.service + Initialize basic system settings on or before the first boot-up of a system + + + + + systemd-firstboot + OPTIONS + + + systemd-firstboot.service + + + + Description + + systemd-firstboot initializes the most + basic system settings interactively on the first boot, or + optionally non-interactively when a system image is created. + The service is started if ConditionFirstBoot=yes + is satisfied. This essentially means that /etc + is empty, see + systemd.unit5 + for details. + + The following settings may be set up: + + + The system locale, more specifically the two + locale variables LANG= and + LC_MESSAGES + + The system keyboard map + + The system time zone + + The system host name + + The machine ID of the system + + The root user's password + + + Each of the fields may either be queried interactively by + users, set non-interactively on the tool's command line, or be + copied from a host system that is used to set up the system + image. + + If a setting is already initialized, it will not be + overwritten and the user will not be prompted for the + setting. + + Note that this tool operates directly on the file system and + does not involve any running system services, unlike + localectl1, + timedatectl1 + or + hostnamectl1. + This allows systemd-firstboot to operate on + mounted but not booted disk images and in early boot. It is not + recommended to use systemd-firstboot on the + running system while it is up. + + + + Options + + The following options are understood: + + + + + Takes a directory path as an argument. All + paths will be prefixed with the given alternate + root path, including config search + paths. This is useful to operate on a system image mounted to + the specified directory instead of the host system itself. + + + + + + + + Sets the system locale, more specifically the + LANG= and LC_MESSAGES + settings. The argument should be a valid locale identifier, + such as de_DE.UTF-8. This controls the + locale.conf5 + configuration file. + + + + + + Sets the system keyboard layout. The argument should be a valid keyboard map, + such as de-latin1. This controls the KEYMAP entry in the + vconsole.conf5 + configuration file. + + + + + + Sets the system time zone. The argument should + be a valid time zone identifier, such as + Europe/Berlin. This controls the + localtime5 + symlink. + + + + + + Sets the system hostname. The argument should + be a host name, compatible with DNS. This controls the + hostname5 + configuration file. + + + + + + Sets the system's machine ID. This controls + the + machine-id5 + file. + + + + + + + Sets the password of the system's root user. + This creates a + shadow5 + file. This setting exists in two forms: + accepts the password to set + directly on the command line, and + reads it from a file. + Note that it is not recommended to specify passwords on the + command line, as other users might be able to see them simply + by invoking + ps1. + + + + + + + + + + Prompt the user interactively for a specific + basic setting. Note that any explicit configuration settings + specified on the command line take precedence, and the user is + not prompted for it. + + + + + + Query the user for locale, keymap, timezone, hostname + and root password. This is equivalent to specifying + , + , + , + , + in combination. + + + + + + + + + + Copy a specific basic setting from the host. + This only works in combination with + (see above). + + + + + + Copy locale, keymap, time zone and root password from + the host. This is equivalent to specifying + , + , + , + in combination. + + + + + + + Initialize the system's machine ID to a random + ID. This only works in combination with + . + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + Kernel Command Line + + + + systemd.firstboot= + + Takes a boolean argument, defaults to on. If off, systemd-firstboot.service + won't interactively query the user for basic settings at first boot, even if those settings are not + initialized yet. + + + + + + See Also + + systemd1, + locale.conf5, + vconsole.conf5, + localtime5, + hostname5, + machine-id5, + shadow5, + systemd-machine-id-setup1, + localectl1, + timedatectl1, + hostnamectl1 + + + + diff --git a/man/systemd-fsck@.service.xml b/man/systemd-fsck@.service.xml new file mode 100644 index 00000000..16fad1ae --- /dev/null +++ b/man/systemd-fsck@.service.xml @@ -0,0 +1,114 @@ + + + + + + + + systemd-fsck@.service + systemd + + + + systemd-fsck@.service + 8 + + + + systemd-fsck@.service + systemd-fsck-root.service + systemd-fsck + File system checker logic + + + + systemd-fsck@.service + systemd-fsck-root.service + /usr/lib/systemd/systemd-fsck + + + + Description + + systemd-fsck@.service and + systemd-fsck-root.service are services + responsible for file system checks. They are instantiated for each + device that is configured for file system checking. + systemd-fsck-root.service is responsible for + file system checks on the root file system, but only if the + root filesystem was not checked in the initramfs. + systemd-fsck@.service is used for all other + file systems and for the root file system in the initramfs. + + These services are started at boot if + in /etc/fstab for the + file system is set to a value greater than zero. The file system + check for root is performed before the other file systems. Other + file systems may be checked in parallel, except when they are on + the same rotating disk. + + systemd-fsck does not know any details + about specific filesystems, and simply executes file system + checkers specific to each filesystem type + (/sbin/fsck.type). These checkers will decide if + the filesystem should actually be checked based on the time since + last check, number of mounts, unclean unmount, etc. + + If a file system check fails for a service without + , emergency mode is activated, by isolating + to emergency.target. + + + + Kernel Command Line + + systemd-fsck understands these kernel + command line parameters: + + + + fsck.mode= + + One of auto, + force, skip. Controls + the mode of operation. The default is auto, + and ensures that file system checks are done when the file + system checker deems them necessary. force + unconditionally results in full file system checks. + skip skips any file system + checks. + + + + fsck.repair= + + One of preen, + yes, no. Controls the + mode of operation. The default is preen, + and will automatically repair problems that can be safely + fixed. yes will answer yes to all + questions by fsck and no will answer no to + all questions. + + + + + + See Also + + systemd1, + fsck8, + systemd-quotacheck.service8, + fsck.btrfs8, + fsck.cramfs8, + fsck.ext48, + fsck.fat8, + fsck.hfsplus8, + fsck.minix8, + fsck.ntfs8, + fsck.xfs8 + + + + diff --git a/man/systemd-fstab-generator.xml b/man/systemd-fstab-generator.xml new file mode 100644 index 00000000..82321c44 --- /dev/null +++ b/man/systemd-fstab-generator.xml @@ -0,0 +1,212 @@ + + + + + + + + systemd-fstab-generator + systemd + + + + systemd-fstab-generator + 8 + + + + systemd-fstab-generator + Unit generator for /etc/fstab + + + + /usr/lib/systemd/system-generators/systemd-fstab-generator + + + + Description + + systemd-fstab-generator is a generator + that translates /etc/fstab (see + fstab5 + for details) into native systemd units early at boot and when + configuration of the system manager is reloaded. This will + instantiate mount and swap units as necessary. + + The passno field is treated like a simple + boolean, and the ordering information is discarded. However, if + the root file system is checked, it is checked before all the + other file systems. + + See + systemd.mount5 + and + systemd.swap5 + for more information about special /etc/fstab + mount options this generator understands. + + One special topic is handling of symbolic links. Historical init + implementations supported symlinks in /etc/fstab. + Because mount units will refuse mounts where the target is a symbolic link, + this generator will resolve any symlinks as far as possible when processing + /etc/fstab in order to enhance backwards compatibility. + If a symlink target does not exist at the time that this generator runs, it + is assumed that the symlink target is the final target of the mount. + + systemd-fstab-generator implements + systemd.generator7. + + + + Kernel Command Line + + systemd-fstab-generator understands the + following kernel command line parameters: + + + + + fstab= + rd.fstab= + + Takes a boolean argument. Defaults to + yes. If no, causes the + generator to ignore any mounts or swap devices configured in + /etc/fstab. rd.fstab= + is honored only by the initial RAM disk (initrd) while + fstab= is honored by both the main system + and the initrd. + + + + root= + + Takes the root filesystem to mount in the + initrd. root= is honored by the + initrd. + + + + rootfstype= + + Takes the root filesystem type that will be + passed to the mount command. rootfstype= is + honored by the initrd. + + + + rootflags= + + Takes the root filesystem mount options to + use. rootflags= is honored by the + initrd. + + + + mount.usr= + + Takes the /usr filesystem + to be mounted by the initrd. If + mount.usrfstype= or + mount.usrflags= is set, then + mount.usr= will default to the value set in + root=. + + Otherwise, this parameter defaults to the + /usr entry found in + /etc/fstab on the root filesystem. + + mount.usr= is honored by the initrd. + + + + + mount.usrfstype= + + Takes the /usr filesystem + type that will be passed to the mount command. If + mount.usr= or + mount.usrflags= is set, then + mount.usrfstype= will default to the value + set in rootfstype=. + + Otherwise, this value will be read from the + /usr entry in + /etc/fstab on the root filesystem. + + mount.usrfstype= is honored by the + initrd. + + + + mount.usrflags= + + Takes the /usr filesystem + mount options to use. If mount.usr= or + mount.usrfstype= is set, then + mount.usrflags= will default to the value + set in rootflags=. + + Otherwise, this value will be read from the + /usr entry in + /etc/fstab on the root filesystem. + + mount.usrflags= is honored by the + initrd. + + + + systemd.volatile= + + Controls whether the system shall boot up in volatile mode. Takes a boolean argument or the + special value . + + If false (the default), this generator makes no changes to the mount tree and the system is booted up in + normal mode. + + If true the generator ensures + systemd-volatile-root.service8 + is run as part of the initial RAM disk ("initrd"). This service changes the mount table before transitioning to + the host system, so that a volatile memory file system (tmpfs) is used as root directory, + with only /usr mounted into it from the configured root file system, in read-only + mode. This way the system operates in fully stateless mode, with all configuration and state reset at boot and + lost at shutdown, as /etc and /var will be served from the (initially + unpopulated) volatile memory file system. + + If set to the generator will leave the root directory mount point unaltered, + however will mount a tmpfs file system to /var. In this mode the normal + system configuration (i.e. the contents of /etc) is in effect (and may be modified during + system runtime), however the system state (i.e. the contents of /var) is reset at boot and + lost at shutdown. + + If this setting is set to overlay the root file system is set up as + overlayfs mount combining the read-only root directory with a writable + tmpfs, so that no modifications are made to disk, but the file system may be modified + nonetheless with all changes being lost at reboot. + + Note that in none of these modes the root directory, /etc, /var + or any other resources stored in the root file system are physically removed. It's thus safe to boot a system + that is normally operated in non-volatile mode temporarily into volatile mode, without losing data. + + Note that with the exception of overlay mode, enabling this setting will only work + correctly on operating systems that can boot up with only /usr mounted, and are able to + automatically populate /etc, and also /var in case of + systemd.volatile=yes. + + + + + + See Also + + systemd1, + fstab5, + systemd.mount5, + systemd.swap5, + systemd-cryptsetup-generator8, + kernel-command-line7 + + + + diff --git a/man/systemd-getty-generator.xml b/man/systemd-getty-generator.xml new file mode 100644 index 00000000..4cc664db --- /dev/null +++ b/man/systemd-getty-generator.xml @@ -0,0 +1,73 @@ + + + + + + + + systemd-getty-generator + systemd + + + + systemd-getty-generator + 8 + + + + systemd-getty-generator + Generator for enabling getty instances on the + console + + + + /usr/lib/systemd/system-generators/systemd-getty-generator + + + + Description + + systemd-getty-generator is a generator + that automatically instantiates + serial-getty@.service on the kernel + console(s), if they can function as ttys and are not provided by + the virtual console subsystem. It will also instantiate + serial-getty@.service instances for + virtualizer consoles, if execution in a virtualized environment is + detected. If execution in a container environment is detected, it + will instead enable console-getty.service for + /dev/console, and + container-getty@.service instances for + additional container pseudo TTYs as requested by the container + manager (see Container + Interface). This should ensure that the user is + shown a login prompt at the right place, regardless of which + environment the system is started in. For example, it is + sufficient to redirect the kernel console with a kernel command + line argument such as console= to get both + kernel messages and a getty prompt on a serial TTY. See kernel-parameters.txt + for more information on the console= kernel + parameter. + + systemd-getty-generator implements + systemd.generator7. + + Further information about configuration of gettys can be + found in + systemd + for Administrators, Part XVI: Gettys on Serial Consoles (and + Elsewhere). + + + + See Also + + systemd1, + agetty8 + + + + diff --git a/man/systemd-gpt-auto-generator.xml b/man/systemd-gpt-auto-generator.xml new file mode 100644 index 00000000..22cd638f --- /dev/null +++ b/man/systemd-gpt-auto-generator.xml @@ -0,0 +1,275 @@ + + + + + + + + systemd-gpt-auto-generator + systemd + + + + systemd-gpt-auto-generator + 8 + + + + systemd-gpt-auto-generator + Generator for automatically discovering + and mounting root, /home and + /srv partitions, as well as + discovering and enabling swap partitions, based on GPT + partition type GUIDs. + + + + /usr/lib/systemd/system-generators/systemd-gpt-auto-generator + + + + Description + + systemd-gpt-auto-generator is a unit generator that automatically discovers + root, /home/, /srv/, the EFI System Partition, the Extended + Boot Loader Partition and swap partitions and creates mount and swap units for them, based on the + partition type GUIDs of GUID partition tables (GPT), see UEFI Specification, chapter 5. It implements the Discoverable Partitions + Specification. Note that this generator has no effect on non-GPT systems, and on specific mount + points that are directories already containing files. Also, on systems where the units are explicitly + configured (for example, listed in fstab5), the + units this generator creates are overridden, but additional implicit dependencies might be + created. + + This generator will only look for root partitions on the + same physical disk the EFI System Partition (ESP) is located on. + It will only look for the other partitions on the same physical + disk the root file system is located on. These partitions will not + be searched for on systems where the root file system is distributed + on multiple disks, for example via btrfs RAID. + + systemd-gpt-auto-generator is useful + for centralizing file system configuration in the partition table + and making configuration in /etc/fstab unnecessary. + + + This generator looks for the partitions based on their + partition type GUID. The following partition type GUIDs are + identified: + + + Partition Type GUIDs + + + + + + + + Partition Type GUID + Name + Mount Point + Explanation + + + + + 44479540-f297-41b2-9af7-d131d5f0458a + Root Partition (x86) + / + On 32-bit x86 systems, the first x86 root partition on the disk the EFI ESP is located on is mounted to the root directory /. + + + 4f68bce3-e8cd-4db1-96e7-fbcaf984b709 + Root Partition (x86-64) + / + On 64-bit x86 systems, the first x86-64 root partition on the disk the EFI ESP is located on is mounted to the root directory /. + + + 69dad710-2ce4-4e3c-b16c-21a1d49abed3 + Root Partition (32-bit ARM) + / + On 32-bit ARM systems, the first ARM root partition on the disk the EFI ESP is located on is mounted to the root directory /. + + + b921b045-1df0-41c3-af44-4c6f280d3fae + Root Partition (64-bit ARM) + / + On 64-bit ARM systems, the first ARM root partition on the disk the EFI ESP is located on is mounted to the root directory /. + + + 993d8d3d-f80e-4225-855a-9daf8ed7ea97 + Root Partition (Itanium/IA-64) + / + On Itanium systems, the first Itanium root partition on the disk the EFI ESP is located on is mounted to the root directory /. + + + 933ac7e1-2eb4-4f13-b844-0e14e2aef915 + Home Partition + /home/ + The first home partition on the disk the root partition is located on is mounted to /home. + + + 3b8f8425-20e0-4f3b-907f-1a25a76f98e8 + Server Data Partition + /srv/ + The first server data partition on the disk the root partition is located on is mounted to /srv. + + + 0657fd6d-a4ab-43c4-84e5-0933c84b4f4f + Swap + n/a + All swap partitions located on the disk the root partition is located on are enabled. + + + c12a7328-f81f-11d2-ba4b-00a0c93ec93b + EFI System Partition (ESP) + /efi/ or /boot/ + The first ESP located on the disk the root partition is located on is mounted to /boot or /efi, see below. + + + bc13c2ff-59e6-4262-a352-b275fd6f7172 + Extended Boot Loader Partition + /boot/ + The first Extended Boot Loader Partition is mounted to /boot, see below. + + + +
+ + This generator understands the following attribute flags for partitions: + + + Partition Attributes + + + + + + + + Name + Value + Applicable to + Explanation + + + + + GPT_FLAG_READ_ONLY + 0x1000000000000000 + /, /home/, /srv/, Extended Boot Loader Partition + Partition is mounted read-only + + + + GPT_FLAG_NO_AUTO + 0x8000000000000000 + /, /home/, /srv/, Extended Boot Loader Partition + Partition is not mounted automatically + + + + GPT_FLAG_NO_BLOCK_IO_PROTOCOL + 0x0000000000000002 + EFI System Partition (ESP) + Partition is not mounted automatically + + + +
+ + The /home/ and /srv/ partitions may be encrypted in LUKS + format. In this case, a device mapper device is set up under the names + /dev/mapper/home and /dev/mapper/srv. Note that this might + create conflicts if the same partition is listed in /etc/crypttab with a different + device mapper device name. + + When systemd is running in the initrd the / partition may be encrypted in LUKS + format as well. In this case, a device mapper device is set up under the name /dev/mapper/root, + and a sysroot.mount is set up that mounts the device under /sysroot. + For more information, see bootup7. + + + Mount and automount units for the EFI System Partition (ESP) are generated on EFI systems. The ESP + is mounted to /boot/ (except if an Extended Boot Loader partition exists, see + below), unless a mount point directory /efi/ exists, in which case it is mounted + there. Since this generator creates an automount unit, the mount will only be activated on-demand, when + accessed. On systems where /boot/ (or /efi/ if it exists) is an + explicitly configured mount (for example, listed in fstab5) or where + the /boot/ (or /efi/) mount point is non-empty, no mount units + are generated. + + If the disk contains an Extended Boot Loader partition, as defined in the Boot Loader Specification, it is made + available at /boot (by means of an automount point, similar to the ESP, see + above). If both an EFI System Partition and an Extended Boot Loader partition exist the latter is + preferably mounted to /boot/. Make sure to create both /efi/ + and /boot/ to ensure both partitions are mounted. + + When using this generator in conjunction with btrfs file + systems, make sure to set the correct default subvolumes on them, + using btrfs subvolume set-default. + + systemd-gpt-auto-generator implements + systemd.generator7. +
+ + + Kernel Command Line + + systemd-gpt-auto-generator understands the following kernel command line + parameters: + + + + + systemd.gpt_auto + rd.systemd.gpt_auto + + Those options take an optional boolean argument, and default to yes. + The generator is enabled by default, and a negative value may be used to disable it. + + + + + root= + + When used with the special value gpt-auto, automatic discovery of + the root partition based on the GPT partition type is enabled. Any other value disables this + generator. + + + + rw + ro + + Mount the root partition read-write or read-only initially. + + Note that unlike most kernel command line options these settings do not override configuration + in the file system, and the file system may be remounted later. See + systemd-remount-fs.service8. + + + + + + + See Also + + systemd1, + systemd.mount5, + systemd.swap5, + systemd-fstab-generator8, + systemd-cryptsetup@.service8, + cryptsetup8, + fstab5, + btrfs8 + + + +
diff --git a/man/systemd-halt.service.xml b/man/systemd-halt.service.xml new file mode 100644 index 00000000..2b102cc9 --- /dev/null +++ b/man/systemd-halt.service.xml @@ -0,0 +1,93 @@ + + + + + + + + systemd-halt.service + systemd + + + + systemd-halt.service + 8 + + + + systemd-halt.service + systemd-poweroff.service + systemd-reboot.service + systemd-kexec.service + systemd-shutdown + System shutdown logic + + + + systemd-halt.service + systemd-poweroff.service + systemd-reboot.service + systemd-kexec.service + /usr/lib/systemd/systemd-shutdown + /usr/lib/systemd/system-shutdown/ + + + + Description + + systemd-halt.service is a system + service that is pulled in by halt.target and + is responsible for the actual system halt. Similarly, + systemd-poweroff.service is pulled in by + poweroff.target, + systemd-reboot.service by + reboot.target and + systemd-kexec.service by + kexec.target to execute the respective + actions. + + When these services are run, they ensure that PID 1 is + replaced by the + /usr/lib/systemd/systemd-shutdown tool which + is then responsible for the actual shutdown. Before shutting down, + this binary will try to unmount all remaining file systems, + disable all remaining swap devices, detach all remaining storage + devices and kill all remaining processes. + + It is necessary to have this code in a separate binary + because otherwise rebooting after an upgrade might be broken — the + running PID 1 could still depend on libraries which are not + available any more, thus keeping the file system busy, which then + cannot be re-mounted read-only. + + Immediately before executing the actual system + halt/poweroff/reboot/kexec systemd-shutdown + will run all executables in + /usr/lib/systemd/system-shutdown/ and pass + one arguments to them: either halt, + poweroff, reboot or + kexec, depending on the chosen action. All + executables in this directory are executed in parallel, and + execution of the action is not continued before all executables + finished. + + Note that systemd-halt.service (and the + related units) should never be executed directly. Instead, trigger + system shutdown with a command such as systemctl + halt or suchlike. + + + + See Also + + systemd1, + systemctl1, + systemd.special7, + reboot2, + systemd-suspend.service8, + bootup7 + + + + diff --git a/man/systemd-hibernate-resume-generator.xml b/man/systemd-hibernate-resume-generator.xml new file mode 100644 index 00000000..f532a19a --- /dev/null +++ b/man/systemd-hibernate-resume-generator.xml @@ -0,0 +1,83 @@ + + + + + + + + systemd-hibernate-resume-generator + systemd + + + + systemd-hibernate-resume-generator + 8 + + + + systemd-hibernate-resume-generator + Unit generator for resume= kernel parameter + + + + /usr/lib/systemd/system-generators/systemd-hibernate-resume-generator + + + + Description + + systemd-hibernate-resume-generator is a + generator that initiates the procedure to resume the system from hibernation. + It instantiates the + systemd-hibernate-resume@.service8 + unit according to the value of parameter + specified on the kernel command line, which will instruct the kernel + to resume the system from the hibernation image on that device. + + + + Kernel Command Line + + systemd-hibernate-resume-generator + understands the following kernel command line parameters: + + + + + resume= + + Takes a path to the resume device. Both + persistent block device paths like + /dev/disk/by-foo/bar and + fstab5-style + specifiers like FOO=bar are + supported. + + + + resumeflags= + + Takes the resume device mount options to + use. Defaults rootflags= if not specified. + + + + noresume + + Do not try to resume from hibernation. If this parameter is + present, resume= is ignored. + + + + + + See Also + + systemd1, + systemd-hibernate-resume@.service8, + kernel-command-line7 + + + + diff --git a/man/systemd-hibernate-resume@.service.xml b/man/systemd-hibernate-resume@.service.xml new file mode 100644 index 00000000..88858ef6 --- /dev/null +++ b/man/systemd-hibernate-resume@.service.xml @@ -0,0 +1,56 @@ + + + + + + + + systemd-hibernate-resume@.service + systemd + + + + systemd-hibernate-resume@.service + 8 + + + + systemd-hibernate-resume@.service + systemd-hibernate-resume + Resume from hibernation + + + + systemd-hibernate-resume@.service + /usr/lib/systemd/systemd-hibernate-resume + + + + Description + + systemd-hibernate-resume@.service + initiates the resume from hibernation. It is instantiated with the + device to resume from as the template argument. + + systemd-hibernate-resume only supports + the in-kernel hibernation implementation, known as + swsusp. + Internally, it works by writing the major:minor of specified + device node to /sys/power/resume. + + Failing to initiate a resume is not an error condition. It + may mean that there was no resume image (e. g. if the system has + been simply powered off and not hibernated). In such case, the + boot is ordinarily continued. + + + + See Also + + systemd1, + systemd-hibernate-resume-generator8 + + + + diff --git a/man/systemd-hostnamed.service.xml b/man/systemd-hostnamed.service.xml new file mode 100644 index 00000000..19bd4c06 --- /dev/null +++ b/man/systemd-hostnamed.service.xml @@ -0,0 +1,58 @@ + + + + + + + + systemd-hostnamed.service + systemd + + + + systemd-hostnamed.service + 8 + + + + systemd-hostnamed.service + systemd-hostnamed + Host name bus mechanism + + + + systemd-hostnamed.service + /usr/lib/systemd/systemd-hostnamed + + + + Description + + systemd-hostnamed is a system service + that may be used as a mechanism to change the system's hostname. + systemd-hostnamed is automatically activated + on request and terminates itself when it is unused. + + The tool + hostnamectl1 + is a command line client to this service. + + See the + developer documentation for information about the APIs + systemd-hostnamed provides. + + + + See Also + + systemd1, + hostname5, + machine-info5, + hostnamectl1, + sethostname2 + + + + diff --git a/man/systemd-hwdb.xml b/man/systemd-hwdb.xml new file mode 100644 index 00000000..15a2c013 --- /dev/null +++ b/man/systemd-hwdb.xml @@ -0,0 +1,84 @@ + + + + + + + + systemd-hwdb + systemd + + + + systemd-hwdb + 8 + + + + systemd-hwdbhardware database management tool + + + + + systemd-hwdb options update + + + systemd-hwdb options query modalias + + + + Description + systemd-hwdb expects a command and command + specific arguments. It manages the binary hardware database. + + + Options + + + + + Generate in /usr/lib/udev instead of /etc/udev. + + + + + + + Alternate root path in the filesystem. + + + + + + + When updating, return non-zero exit value on any parsing error. + + + + + + + systemd-hwdb + <arg choice="opt"><replaceable>options</replaceable></arg> + update + Update the binary database. + + + systemd-hwdb + <arg choice="opt"><replaceable>options</replaceable></arg> + query + <arg><replaceable>MODALIAS</replaceable></arg> + + Query database and print result. + + + + + See Also + + hwdb7 + + + diff --git a/man/systemd-id128.xml b/man/systemd-id128.xml new file mode 100644 index 00000000..7b07d535 --- /dev/null +++ b/man/systemd-id128.xml @@ -0,0 +1,132 @@ + + + + + + + + systemd-id128 + systemd + + + + systemd-id128 + 1 + + + + systemd-id128 + Generate and print sd-128 identifiers + + + + + systemd-id128 + OPTIONS + new + + + + systemd-id128 + OPTIONS + machine-id + + + + systemd-id128 + OPTIONS + boot-id + + + + systemd-id128 + OPTIONS + invocation-id + + + + + Description + + id128 may be used to conveniently print + sd-id1283 + UUIDs. What identifier is printed depends on the specific verb. + + With new, a new random identifier will be generated. + + With machine-id, the identifier of the current machine will be + printed. See + machine-id5. + + + With boot-id, the identifier of the current boot will be + printed. + + Both machine-id and boot-id may be combined + with the switch to + generate application-specific IDs. See + sd_id128_get_machine3 + for the discussion when this is useful. + + With invocation-id, the identifier of the current service invocation + will be printed. This is available in systemd services. See + systemd.exec5. + + + + + Options + + The following options are understood: + + + + + + + Generate output as programming language snippets. + + + + + + + With this option, an identifier that is the result of hashing the + application identifier app-id and the machine identifier will be + printed. The app-id argument must be a valid sd-id128 string + identifying the application. + + + + + + + + Generate output as an UUID formatted in the "canonical representation", with five + groups of digits seperated by hyphens. See the + wikipedia + for more discussion. + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code otherwise. + + + + See Also + + systemd1, + sd-id1283, + sd_id128_get_machine3 + + + + diff --git a/man/systemd-importd.service.xml b/man/systemd-importd.service.xml new file mode 100644 index 00000000..355e5b0b --- /dev/null +++ b/man/systemd-importd.service.xml @@ -0,0 +1,55 @@ + + + + + + + + systemd-importd.service + systemd + + + + systemd-importd.service + 8 + + + + systemd-importd.service + systemd-importd + VM and container image import and export service + + + + systemd-importd.service + /usr/lib/systemd/systemd-importd + + + + Description + + systemd-importd is a system service that allows importing, exporting and downloading of + system images suitable for running as VM or containers. It is a companion service for + systemd-machined.service8, and provides the implementation for + machinectl1's + pull-raw, pull-tar, import-raw, + import-tar, export-raw, and export-tar commands. + + See the + + importd D-Bus API Documentation for information about the + APIs systemd-importd provides. + + + + See Also + + systemd1, + machinectl1, + systemd-machined.service8, + systemd-nspawn1 + + + + diff --git a/man/systemd-inhibit.xml b/man/systemd-inhibit.xml new file mode 100644 index 00000000..e0399ebb --- /dev/null +++ b/man/systemd-inhibit.xml @@ -0,0 +1,154 @@ + + + + + + + + systemd-inhibit + systemd + + + + systemd-inhibit + 1 + + + + systemd-inhibit + Execute a program with an inhibition lock taken + + + + + systemd-inhibit OPTIONS COMMAND ARGUMENTS + + + systemd-inhibit OPTIONS --list + + + + + Description + + systemd-inhibit may be used to execute a + program with a shutdown, sleep, or idle inhibitor lock taken. The + lock will be acquired before the specified command line is + executed and released afterwards. + + Inhibitor locks may be used to block or delay system sleep + and shutdown requests from the user, as well as automatic idle + handling of the OS. This is useful to avoid system suspends while + an optical disc is being recorded, or similar operations that + should not be interrupted. + + For more information see the Inhibitor + Lock Developer Documentation. + + + + Options + + The following options are understood: + + + + + + Takes a colon-separated list of one or more + operations to inhibit: + shutdown, + sleep, + idle, + handle-power-key, + handle-suspend-key, + handle-hibernate-key, + handle-lid-switch, + for inhibiting reboot/power-off/halt/kexec, + suspending/hibernating, the automatic idle detection, or the + low-level handling of the power/sleep key and the lid switch, + respectively. If omitted, defaults to + idle:sleep:shutdown. + + + + + + Takes a short, human-readable descriptive + string for the program taking the lock. If not passed, + defaults to the command line string. + + + + + + Takes a short, human-readable descriptive + string for the reason for taking the lock. Defaults to + "Unknown reason". + + + + + + Takes either block or + delay and describes how the lock is + applied. If block is used (the default), + the lock prohibits any of the requested operations without + time limit, and only privileged users may override it. If + delay is used, the lock can only delay the + requested operations for a limited time. If the time elapses, + the lock is ignored and the operation executed. The time limit + may be specified in + logind.conf5. + Note that delay is only available for + sleep and + shutdown. + + + + + + Lists all active inhibition locks instead of + acquiring one. + + + + + + + + + + + + Exit status + + Returns the exit status of the executed program. + + + + Example + + # systemd-inhibit wodim foobar.iso + + This burns the ISO image + foobar.iso on a CD using + wodim1, + and inhibits system sleeping, shutdown and idle while + doing so. + + + + + + See Also + + systemd1, + logind.conf5 + + + + diff --git a/man/systemd-initctl.service.xml b/man/systemd-initctl.service.xml new file mode 100644 index 00000000..0345936f --- /dev/null +++ b/man/systemd-initctl.service.xml @@ -0,0 +1,49 @@ + + + + + + + + systemd-initctl.service + systemd + + + + systemd-initctl.service + 8 + + + + systemd-initctl.service + systemd-initctl.socket + systemd-initctl + /dev/initctl compatibility + + + + systemd-initctl.service + systemd-initctl.socket + /usr/lib/systemd/systemd-initctl + + + + Description + + systemd-initctl is a system service + that implements compatibility with the + /dev/initctl FIFO file system object, as + implemented by the SysV init system. + systemd-initctl is automatically activated on + request and terminates itself when it is unused. + + + + See Also + + systemd1 + + + + diff --git a/man/systemd-journal-gatewayd.service.xml b/man/systemd-journal-gatewayd.service.xml new file mode 100644 index 00000000..633b4cb5 --- /dev/null +++ b/man/systemd-journal-gatewayd.service.xml @@ -0,0 +1,294 @@ + + + + + + + + systemd-journal-gatewayd.service + systemd + + + + systemd-journal-gatewayd.service + 8 + + + + systemd-journal-gatewayd.service + systemd-journal-gatewayd.socket + systemd-journal-gatewayd + HTTP server for journal events + + + + systemd-journal-gatewayd.service + systemd-journal-gatewayd.socket + + /usr/lib/systemd/systemd-journal-gatewayd + OPTIONS + + + + + Description + + systemd-journal-gatewayd serves journal + events over the network. Clients must connect using + HTTP. The server listens on port 19531 by default. + If is specified, the server expects + HTTPS connections. + + The program is started by + systemd1 + and expects to receive a single socket. Use + systemctl start systemd-journal-gatewayd.socket to start + the service, and systemctl enable systemd-journal-gatewayd.socket + to have it started on boot. + + + + Options + + The following options are understood: + + + + + + Specify the path to a file containing a server + certificate in PEM format. This option switches + systemd-journal-gatewayd into HTTPS mode + and must be used together with + . + + + + + + Specify the path to a file containing a server + key in PEM format corresponding to the certificate specified + with . + + + + + + Specify the path to a file containing a + CA certificate in PEM format. + + + + + + + Takes a directory path as argument. If + specified, systemd-journal-gatewayd will serve the + specified journal directory DIR instead of + the default runtime and system journal paths. + + + + + + + + + Supported URLs + + The following URLs are recognized: + + + + /browse + + Interactive browsing. + + + + /entries[?option1&option2=value…] + + Retrieval of events in various formats. + + The part of the HTTP header + determines the format. Supported values are described below. + + + The part of the HTTP header + determines the range of events returned. Supported values are + described below. + + + GET parameters can be used to modify what events are + returned. Supported parameters are described below. + + + + + /machine + + Return a JSON structure describing the machine. + + Example: + { "machine_id" : "8cf7ed9d451ea194b77a9f118f3dc446", + "boot_id" : "3d3c9efaf556496a9b04259ee35df7f7", + "hostname" : "fedora", + "os_pretty_name" : "Fedora 19 (Rawhide)", + "virtualization" : "kvm", + …} + + + + + + /fields/FIELD_NAME + + Return a list of values of this field present in the logs. + + + + + + + Accept header + + + + + + Recognized formats: + + + + text/plain + + The default. Plaintext syslog-like output, + one line per journal entry + (like journalctl --output short). + + + + + application/json + + Entries are formatted as JSON data structures, + one per line + (like journalctl --output json). + See Journal + JSON Format for more information. + + + + + text/event-stream + + Entries are formatted as JSON data structures, + wrapped in a format suitable for + Server-Sent Events + (like journalctl --output json-sse). + + + + + + application/vnd.fdo.journal + + Entries are serialized into a binary (but + mostly text-based) stream suitable for backups and network + transfer + (like journalctl --output export). + See Journal + Export Format for more information. + + + + + + + Range header + + + + + + where + is a cursor string, + is an integer, + is an unsigned integer. + + + Range defaults to all available events. + + + + URL GET parameters + + Following parameters can be used as part of the URL: + + + + follow + + wait for new events + (like journalctl --follow, except that + the number of events returned is not limited). + + + + + discrete + + Test that the specified cursor refers to an + entry in the journal. Returns just this entry. + + + + + boot + + Limit events to the current boot of the system + (like journalctl -b). + + + + KEY=match + + Match journal fields. See + systemd.journal-fields7. + + + + + + + Examples + Retrieve events from this boot from local journal + in Journal + Export Format: + curl --silent -H'Accept: application/vnd.fdo.journal' \ + 'http://localhost:19531/entries?boot' + + + Listen for core dumps: + curl 'http://localhost:19531/entries?follow&MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1' + + + + See Also + + systemd1, + journalctl1, + systemd.journal-fields7, + systemd-journald.service8, + systemd-journal-remote.service8, + systemd-journal-upload.service8 + + + + diff --git a/man/systemd-journal-remote.service.xml b/man/systemd-journal-remote.service.xml new file mode 100644 index 00000000..b28092d1 --- /dev/null +++ b/man/systemd-journal-remote.service.xml @@ -0,0 +1,350 @@ + + +%entities; +]> + + + + + + systemd-journal-remote.service + systemd + + + + systemd-journal-remote.service + 8 + + + + systemd-journal-remote.service + systemd-journal-remote.socket + systemd-journal-remote + Receive journal messages over the network + + + + systemd-journal-remote.service + systemd-journal-remote.socket + + /usr/lib/systemd/systemd-journal-remote + OPTIONS + -o/--output=DIR|FILE + SOURCES + + + + + Description + + systemd-journal-remote is a command to receive serialized journal + events and store them to journal files. Input streams are in the + Journal Export Format, + i.e. like the output from journalctl --output=export. For transport over the + network, this serialized stream is usually carried over an HTTPS connection. + + systemd-journal-remote.service is a system service that uses + systemd-journal-remote to listen for connections. + systemd-journal-remote.socket configures the network address that + systemd-journal-remote.service listens on. By default this is port 19532. + What connections are accepted and how the received data is stored can be configured through the + journal-remote.conf5 + configuration file. + + + + Sources + + + Sources can be either "active" + (systemd-journal-remote requests and pulls + the data), or "passive" + (systemd-journal-remote waits for a + connection and then receives events pushed by the other side). + + + + systemd-journal-remote can read more than one + event stream at a time. They will be interleaved in the output + file. In case of "active" connections, each "source" is one + stream, and in case of "passive" connections, each connection can + result in a separate stream. Sockets can be configured in + "accept" mode (i.e. only one connection), or "listen" mode (i.e. + multiple connections, each resulting in a stream). + + + + When there are no more connections, and no more can be created + (there are no listening sockets), then + systemd-journal-remote will exit. + + + Active sources can be specified in the following + ways: + + + + SOURCES + + When is given as a + positional argument, events will be read from standard input. + Other positional arguments will be treated as filenames + to open and read from. + + + + + + With the + option, + events will be retrieved using HTTP from + ADDRESS. This URL should refer to the + root of a remote + systemd-journal-gatewayd8 + instance, e.g. http://some.host:19531/ or + https://some.host:19531/. + + + + + + Program to invoke to retrieve data. The journal + event stream must be generated on standard output. + + Examples: + + --getter='curl "-HAccept: application/vnd.fdo.journal" https://some.host:19531/' + + --getter='wget --header="Accept: application/vnd.fdo.journal" -O- https://some.host:19531/' + + + + + Passive sources can be specified in the following + ways: + + + + + + ADDRESS must be an + address suitable for (cf. + systemd.socket5). + systemd-journal-remote will listen on this + socket for connections. Each connection is expected to be a + stream of journal events. + + + + + + + + ADDRESS must be + either a negative integer, in which case it will be + interpreted as the (negated) file descriptor number, or an + address suitable for (c.f. + systemd.socket5). + In the first case, the server listens on port 19532 by default, + and the matching file descriptor must be inherited through + $LISTEN_FDS/$LISTEN_PID. + In the second case, an HTTP or HTTPS server will be spawned on + this port, respectively for and + . Currently, only POST requests + to /upload with Content-Type: + application/vnd.fdo.journal are supported. + + + + + $LISTEN_FDS + + systemd-journal-remote + supports the + $LISTEN_FDS/$LISTEN_PID + protocol. Open sockets inherited through socket activation + behave like those opened with + described above, unless they are specified as an argument in + + or + + above. In the latter case, an HTTP or HTTPS server will be + spawned using this descriptor and connections must be made + over the HTTP protocol. + + + + + + + + Takes a path to a SSL key file in PEM format. + Defaults to &CERTIFICATE_ROOT;/private/journal-remote.pem. + This option can be used with . + + + + + + + + Takes a path to a SSL certificate file in PEM format. + Defaults to &CERTIFICATE_ROOT;/certs/journal-remote.pem. + This option can be used with . + + + + + + + + Takes a path to a SSL CA certificate file in PEM format, + or . If is set, + then certificate checking will be disabled. + Defaults to &CERTIFICATE_ROOT;/ca/trusted.pem. + This option can be used with . + + + + + + + + Takes a comma separated list of gnutls logging categories. + This option can be used with or + . + + + + + + + + Sinks + + The location of the output journal can be specified + with or . + + + + + + + Will write to this journal file. The filename + must end with .journal. The file will be + created if it does not exist. If necessary (journal file full, + or corrupted), the file will be renamed following normal + journald rules and a new journal file will be created in its + stead. + + + + + + Will create journal files underneath directory + DIR. The directory must exist. If + necessary (journal files over size, or corrupted), journal + files will be rotated following normal journald rules. Names + of files underneath DIR will be + generated using the rules described below. + + + + If is not used, the output + directory /var/log/journal/remote/ will be + used. In case the output file is not specified, journal files + will be created underneath the selected directory. Files will be + called + remote-hostname.journal, + where the hostname part is the + escaped hostname of the source endpoint of the connection, or the + numerical address if the hostname cannot be determined. + + In the case that "active" sources are given by the positional + arguments or option, the output file name + must always be given explicitly. + + + + Options + + The following options are understood: + + + + + + One of none or + host. For the first, only one output + journal file is used. For the latter, a separate output file + is used, based on the hostname of the other endpoint of a + connection. + + In the case that "active" sources are given by the positional + arguments or option, the output file name must + always be given explicitly and only none + is allowed. + + + + [BOOL] + + If this is set to yes then compress + the data in the journal using XZ. The default is yes. + + + + + [BOOL] + + If this is set to yes then + periodically sign the data in the journal using Forward Secure Sealing. + The default is no. + + + + + + + + + Examples + Copy local journal events to a different journal directory: + +journalctl -o export | systemd-journal-remote -o /tmp/dir/foo.journal - + + + + Retrieve all available events from a remote + systemd-journal-gatewayd8 + instance and store them in + /var/log/journal/remote/remote-some.host.journal: + +systemd-journal-remote --url http://some.host:19531/ + + + + Retrieve current boot events and wait for new events from a remote + systemd-journal-gatewayd8 + instance, and store them in + /var/log/journal/remote/remote-some.host.journal: + +systemd-journal-remote --url http://some.host:19531/entries?boot&follow + + + + + + See Also + + journal-remote.conf5, + journalctl1, + systemd-journal-gatewayd.service8, + systemd-journal-upload.service8, + systemd-journald.service8 + + + diff --git a/man/systemd-journal-upload.service.xml b/man/systemd-journal-upload.service.xml new file mode 100644 index 00000000..1b8b0be6 --- /dev/null +++ b/man/systemd-journal-upload.service.xml @@ -0,0 +1,286 @@ + + +%entities; +]> + + + + + + systemd-journal-upload.service + systemd + + + + systemd-journal-upload.service + 8 + + + + systemd-journal-upload.service + systemd-journal-upload + Send journal messages over the network + + + + systemd-journal-upload.service + + /usr/lib/systemd/systemd-journal-upload + OPTIONS + -u/--url=URL + SOURCES + + + + + Description + + systemd-journal-upload will upload journal entries to the URL specified + with . This program reads journal entries from one or more journal files, + similarly to + journalctl1. + Unless limited by one of the options specified below, all journal entries accessible to the user + the program is running as will be uploaded, and then the program will wait and send new entries + as they become available. + + systemd-journal-upload.service is a system service that uses + systemd-journal-upload to upload journal entries to a server. It uses the + configuration in + journal-upload.conf5. + At least the URL= option must be specified. + + + + Options + + + + + + + + Upload to the specified + address. URL may specify either + just the hostname or both the protocol and + hostname. https is the default. + The port number may be specified after a colon (:), + otherwise 19532 will be used by default. + + + + + + + + Limit uploaded entries to entries from system + services and the kernel, or to entries from services of + current user. This has the same meaning as + and options + for + journalctl1. If + neither is specified, all accessible entries are uploaded. + + + + + + + + Upload entries interleaved from all available + journals, including other machines. This has the same meaning + as option for + journalctl1. + + + + + + + Takes a directory path as argument. Upload + entries from the specified journal directory + DIR instead of the default runtime + and system journal paths. This has the same meaning as + option for + journalctl1. + + + + + + + Takes a file glob as an argument. Upload + entries from the specified journal files matching + GLOB instead of the default runtime + and system journal paths. May be specified multiple times, in + which case files will be suitably interleaved. This has the same meaning as + option for + journalctl1. + + + + + + + Upload entries from the location in the + journal specified by the passed cursor. This has the same + meaning as option for + journalctl1. + + + + + + Upload entries from the location in the + journal after the location specified by + the this cursor. This has the same meaning as + option for + journalctl1. + + + + + =PATH + + Upload entries from the location in the + journal after the location specified by + the cursor saved in file at PATH + (/var/lib/systemd/journal-upload/state by default). + After an entry is successfully uploaded, update this file + with the cursor of that entry. + + + + + =BOOL + + + If set to yes, then systemd-journal-upload waits for input. + + + + + + + + Takes a path to a SSL key file in PEM format. + Defaults to &CERTIFICATE_ROOT;/private/journal-upload.pem. + + + + + + + + Takes a path to a SSL certificate file in PEM format. + Defaults to &CERTIFICATE_ROOT;/certs/journal-upload.pem. + + + + + + + + Takes a path to a SSL CA certificate file in PEM format, + or . If is set, + then certificate checking will be disabled. + Defaults to &CERTIFICATE_ROOT;/ca/trusted.pem. + + + + + + + + + + Exit status + + On success, 0 is returned; otherwise, a non-zero + failure code is returned. + + + + Examples + + Setting up certificates for authentication + + Certificates signed by a trusted authority are used to + verify that the server to which messages are uploaded is + legitimate, and vice versa, that the client is trusted. + + A suitable set of certificates can be generated with + openssl. Note, 2048 bits of key length + is minimally recommended to use for security reasons: + + openssl req -newkey rsa:2048 -days 3650 -x509 -nodes \ + -out ca.pem -keyout ca.key -subj '/CN=Certificate authority/' + +cat >ca.conf <<EOF +[ ca ] +default_ca = this + +[ this ] +new_certs_dir = . +certificate = ca.pem +database = ./index +private_key = ca.key +serial = ./serial +default_days = 3650 +default_md = default +policy = policy_anything + +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional +EOF + +touch index +echo 0001 >serial + +SERVER=server +CLIENT=client + +openssl req -newkey rsa:2048 -nodes -out $SERVER.csr -keyout $SERVER.key -subj "/CN=$SERVER/" +openssl ca -batch -config ca.conf -notext -in $SERVER.csr -out $SERVER.pem + +openssl req -newkey rsa:2048 -nodes -out $CLIENT.csr -keyout $CLIENT.key -subj "/CN=$CLIENT/" +openssl ca -batch -config ca.conf -notext -in $CLIENT.csr -out $CLIENT.pem + + + Generated files ca.pem, + server.pem, and + server.key should be installed on server, + and ca.pem, + client.pem, and + client.key on the client. The location of + those files can be specified using + TrustedCertificateFile=, + ServerCertificateFile=, + ServerKeyFile=, in + /etc/systemd/journal-remote.conf and + /etc/systemd/journal-upload.conf, + respectively. The default locations can be queried by using + systemd-journal-remote --help and + systemd-journal-upload --help. + + + + + See Also + + journal-upload.conf5, + systemd-journal-remote.service8, + journalctl1, + systemd-journald.service8, + systemd-journal-gatewayd.service8 + + + diff --git a/man/systemd-journald.service.xml b/man/systemd-journald.service.xml new file mode 100644 index 00000000..ec9f974f --- /dev/null +++ b/man/systemd-journald.service.xml @@ -0,0 +1,305 @@ + + + + + + + + systemd-journald.service + systemd + + + + systemd-journald.service + 8 + + + + systemd-journald.service + systemd-journald.socket + systemd-journald-dev-log.socket + systemd-journald-audit.socket + systemd-journald + Journal service + + + + systemd-journald.service + systemd-journald.socket + systemd-journald-dev-log.socket + systemd-journald-audit.socket + /usr/lib/systemd/systemd-journald + + + + Description + + systemd-journald is a system service + that collects and stores logging data. It creates and maintains + structured, indexed journals based on logging information that is + received from a variety of sources: + + + Kernel log messages, via kmsg + + Simple system log messages, via the libc syslog3 + call + + Structured system log messages via the native + Journal API, see + sd_journal_print3 + + Standard output and standard error of service units. For further details see + below. + + Audit records, originating from the kernel audit subsystem + + + The daemon will implicitly collect numerous metadata fields + for each log messages in a secure and unfakeable way. See + systemd.journal-fields7 + for more information about the collected metadata. + + + Log data collected by the journal is primarily text-based but can also include binary data where + necessary. Individual fields making up a log record stored in the journal may be up to 2^64-1 bytes in size. + + The journal service stores log data either persistently below /var/log/journal or in a + volatile way below /run/log/journal/ (in the latter case it is lost at reboot). By default, log + data is stored persistently if /var/log/journal/ exists during boot, with an implicit fallback + to volatile storage otherwise. Use Storage= in + journald.conf5 to configure + where log data is placed, independently of the existence of /var/log/journal/. + + On systems where /var/log/journal/ does not exist yet but where persistent logging is + desired (and the default journald.conf is used), it is sufficient to create the directory, and + ensure it has the correct access modes and ownership: + + mkdir -p /var/log/journal +systemd-tmpfiles --create --prefix /var/log/journal + + See + journald.conf5 + for information about the configuration of this service. + + + + Stream logging + + The systemd service manager invokes all service processes with standard output and standard error connected + to the journal by default. This behaviour may be altered via the + StandardOutput=/StandardError= unit file settings, see + systemd.exec5 for details. The + journal converts the log byte stream received this way into individual log records, splitting the stream at newline + (\n, ASCII 10) and NUL bytes. + + If systemd-journald.service is stopped, the stream connections associated with all + services are terminated. Further writes to those streams by the service will result in EPIPE + errors. In order to react gracefully in this case it is recommended that programs logging to standard output/error + ignore such errors. If the SIGPIPE UNIX signal handler is not blocked or turned off, such + write attempts will also result in such process signals being generated, see + signal7. To mitigate this issue, + systemd service manager explicitly turns off the SIGPIPE signal for all invoked processes by + default (this may be changed for each unit individually via the IgnoreSIGPIPE= option, see + systemd.exec5 for + details). After the standard output/standard error streams have been terminated they may not be recovered until the + services they are associated with are restarted. Note that during normal operation, + systemd-journald.service stores copies of the file descriptors for those streams in the + service manager. If systemd-journald.service is restarted using systemctl + restart or equivalent operation instead of a pair of separate systemctl stop and + systemctl start commands (or equivalent operations), these stream connections are not terminated + and survive the restart. It is thus safe to restart systemd-journald.service, but stopping it + is not recommended. + + Note that the log record metadata for records transferred via such standard output/error streams reflect the + metadata of the peer the stream was originally created for. If the stream connection is passed on to other + processes (such as further child processes forked off the main service process), the log records will not reflect + their metadata, but will continue to describe the original process. This is different from the other logging + transports listed above, which are inherently record based and where the metadata is always associated with the + individual record. + + In addition to the implicit standard output/error logging of services, stream logging is also available + via the systemd-cat1 command + line tool. + + Currently, the number of parallel log streams systemd-journald will accept is limited to + 4096. When this limit is reached further log streams may be established but will receive + EPIPE right from the beginning. + + + + Signals + + + + SIGUSR1 + + Request that journal data from /run/ is flushed to + /var/ in order to make it persistent (if this is enabled). This must be used + after /var/ is mounted, as otherwise log data from /run is + never flushed to /var regardless of the configuration. Use the + journalctl --flush command to request flushing of the journal files, and wait for + the operation to complete. See + journalctl1 for + details. + + + + SIGUSR2 + + Request immediate rotation of the journal files. Use the journalctl + --rotate command to request journal file rotation, and wait for the operation to + complete. + + + + SIGRTMIN+1 + + Request that all unwritten log data is written to disk. Use the journalctl + --sync command to trigger journal synchronization, and wait for the operation to + complete. + + + + + + Kernel Command Line + + A few configuration parameters from + journald.conf may be overridden on the kernel + command line: + + + + systemd.journald.forward_to_syslog= + systemd.journald.forward_to_kmsg= + systemd.journald.forward_to_console= + systemd.journald.forward_to_wall= + + Enables/disables forwarding of collected log + messages to syslog, the kernel log buffer, the system console + or wall. + + + See + journald.conf5 + for information about these settings. + + + + + + + + Access Control + + Journal files are, by default, owned and readable by the + systemd-journal system group but are not + writable. Adding a user to this group thus enables them to read + the journal files. + + By default, each user, with a UID outside the range of system users, + dynamic service users, and the nobody user, will get their own set of + journal files in /var/log/journal/. See + Users, Groups, UIDs and GIDs on systemd systems + for more details about UID ranges. These journal + files will not be owned by the user, however, in order to avoid + that the user can write to them directly. Instead, file system + ACLs are used to ensure the user gets read access only. + + Additional users and groups may be granted access to journal + files via file system access control lists (ACL). Distributions + and administrators may choose to grant read access to all members + of the wheel and adm system + groups with a command such as the following: + + # setfacl -Rnm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal/ + + Note that this command will update the ACLs both for + existing journal files and for future journal files created in the + /var/log/journal/ directory. + + + + Files + + + + /etc/systemd/journald.conf + + Configure systemd-journald behavior. See + journald.conf5. + + + + + /run/log/journal/machine-id/*.journal + /run/log/journal/machine-id/*.journal~ + /var/log/journal/machine-id/*.journal + /var/log/journal/machine-id/*.journal~ + + systemd-journald writes entries to files in + /run/log/journal/machine-id/ + or + /var/log/journal/machine-id/ + with the .journal suffix. If the daemon is + stopped uncleanly, or if the files are found to be corrupted, + they are renamed using the .journal~ + suffix, and systemd-journald starts writing + to a new file. /run is used when + /var/log/journal is not available, or + when is set in the + journald.conf5 + configuration file. + + When systemd-journald ceases writing to a journal file, + it will be renamed to original-name@suffix.journal + (or original-name@suffix.journal~). + Such files are "archived" and will not be written to any more. + + In general, it is safe to read or copy any journal file (active or archived). + journalctl1 + and the functions in the + sd-journal3 + library should be able to read all entries that have been fully written. + + systemd-journald will automatically remove the oldest + archived journal files to limit disk use. See SystemMaxUse= + and related settings in + journald.conf5. + + + + + /dev/kmsg + /dev/log + /run/systemd/journal/dev-log + /run/systemd/journal/socket + /run/systemd/journal/stdout + + Sockets and other paths that + systemd-journald will listen on that are + visible in the file system. In addition to these, journald can + listen for audit events using netlink. + + + + + + See Also + + systemd1, + journalctl1, + journald.conf5, + systemd.journal-fields7, + sd-journal3, + systemd-coredump8, + setfacl1, + sd_journal_print3, + pydoc systemd.journal + + + + diff --git a/man/systemd-localed.service.xml b/man/systemd-localed.service.xml new file mode 100644 index 00000000..f620aade --- /dev/null +++ b/man/systemd-localed.service.xml @@ -0,0 +1,60 @@ + + + + + + + + systemd-localed.service + systemd + + + + systemd-localed.service + 8 + + + + systemd-localed.service + systemd-localed + Locale bus mechanism + + + + systemd-localed.service + /usr/lib/systemd/systemd-localed + + + + Description + + systemd-localed is a system service + that may be used as mechanism to change the system locale + settings, as well as the console key mapping and default X11 key + mapping. systemd-localed is automatically + activated on request and terminates itself when it is + unused. + + The tool + localectl1 + is a command line client to this service. + + See the + developer documentation for information about the APIs + systemd-localed provides. + + + + See Also + + systemd1, + locale.conf5, + vconsole.conf5, + localectl1, + loadkeys1 + + + + diff --git a/man/systemd-logind.service.xml b/man/systemd-logind.service.xml new file mode 100644 index 00000000..a66c53d0 --- /dev/null +++ b/man/systemd-logind.service.xml @@ -0,0 +1,103 @@ + + + + + + + + systemd-logind.service + systemd + + + + systemd-logind.service + 8 + + + + systemd-logind.service + systemd-logind + Login manager + + + + systemd-logind.service + /usr/lib/systemd/systemd-logind + + + + Description + + systemd-logind is a system service that + manages user logins. It is responsible for: + + + Keeping track of users and sessions, their processes and their idle state. This is implemented by + allocating a systemd slice unit for each user below user.slice, and a scope unit below it + for each concurrent session of a user. Also, a per-user service manager is started as system service instance of + user@.service for each logged in user. + + Generating and managing session IDs. If auditing is available and an audit session ID is already set for + a session, then this ID is reused as the session ID. Otherwise, an independent session counter is + used. + + Providing polkit-based + access for users for operations such as system shutdown or sleep + + + Implementing a shutdown/sleep inhibition logic + for applications + + Handling of power/sleep hardware + keys + + Multi-seat management + + Session switch management + + Device access management for + users + + Automatic spawning of text logins (gettys) on + virtual console activation and user runtime directory + management + + + User sessions are registered with logind via the + pam_systemd8 + PAM module. + + See + logind.conf5 + for information about the configuration of this service. + + See + sd-login3 + for information about the basic concepts of logind + such as users, sessions and seats. + + See the + logind D-Bus API Documentation for information about the + APIs systemd-logind provides. + + For more information on the inhibition logic see the Inhibitor + Lock Developer Documentation. + + + + See Also + + systemd1, + systemd-user-sessions.service8, + loginctl1, + logind.conf5, + pam_systemd8 + sd-login3 + + + + diff --git a/man/systemd-machine-id-commit.service.xml b/man/systemd-machine-id-commit.service.xml new file mode 100644 index 00000000..781a9845 --- /dev/null +++ b/man/systemd-machine-id-commit.service.xml @@ -0,0 +1,74 @@ + + + + + + + + systemd-machine-id-commit.service + systemd + + + + systemd-machine-id-commit.service + 8 + + + + systemd-machine-id-commit.service + Commit a transient machine ID to disk + + + + systemd-machine-id-commit.service + + + + Description + + systemd-machine-id-commit.service is an + early boot service responsible for committing transient + /etc/machine-id files to a writable disk file + system. See + machine-id5 + for more information about machine IDs. + + This service is started after + local-fs.target in case + /etc/machine-id is a mount point of its own + (usually from a memory file system such as + tmpfs) and /etc is writable. The service will + invoke systemd-machine-id-setup --commit, which + writes the current transient machine ID to disk and unmount the + /etc/machine-id file in a race-free manner to + ensure that file is always valid and accessible for other + processes. See + systemd-machine-id-setup1 + for details. + + The main use case of this service are systems where + /etc/machine-id is read-only and initially + not initialized. In this case, the system manager will generate a + transient machine ID file on a memory file system, and mount it + over /etc/machine-id, during the early boot + phase. This service is then invoked in a later boot phase, as soon + as /etc has been remounted writable and the + ID may thus be committed to disk to make it permanent. + + + + See Also + + systemd1, + systemd-machine-id-setup1, + machine-id5, + systemd-firstboot1 + + + + diff --git a/man/systemd-machine-id-setup.xml b/man/systemd-machine-id-setup.xml new file mode 100644 index 00000000..31e0cdcf --- /dev/null +++ b/man/systemd-machine-id-setup.xml @@ -0,0 +1,151 @@ + + + + + + + + systemd-machine-id-setup + systemd + + + + systemd-machine-id-setup + 1 + + + + systemd-machine-id-setup + Initialize the machine ID in /etc/machine-id + + + + + systemd-machine-id-setup + + + + + Description + + systemd-machine-id-setup may be used by + system installer tools to initialize the machine ID stored in + /etc/machine-id at install time, with a + provisioned or randomly generated ID. See + machine-id5 + for more information about this file. + + If the tool is invoked without the + switch, /etc/machine-id is initialized with a + valid, new machined ID if it is missing or empty. The new machine + ID will be acquired in the following fashion: + + + If a valid D-Bus machine ID is already + configured for the system, the D-Bus machine ID is copied and + used to initialize the machine ID in + /etc/machine-id. + + If run inside a KVM virtual machine and a UUID + is configured (via the + option), this UUID is used to initialize the machine ID. The + caller must ensure that the UUID passed is sufficiently unique + and is different for every booted instance of the + VM. + + Similarly, if run inside a Linux container + environment and a UUID is configured for the container, this is + used to initialize the machine ID. For details, see the + documentation of the Container + Interface. + + Otherwise, a new ID is randomly + generated. + + + The switch may be used to commit a + transient machined ID to disk, making it persistent. For details, + see below. + + Use + systemd-firstboot1 + to initialize the machine ID on mounted (but not booted) system + images. + + + + + Options + + The following options are understood: + + + + + + Takes a directory path as argument. All paths + operated will be prefixed with the given alternate + root path, including the path for + /etc/machine-id itself. + + + + + Commit a transient machine ID to disk. This + command may be used to convert a transient machine ID into a + persistent one. A transient machine ID file is one that was + bind mounted from a memory file system (usually + tmpfs) to + /etc/machine-id during the early phase of + the boot process. This may happen because + /etc is initially read-only and was + missing a valid machine ID file at that point. + + This command will execute no operation if + /etc/machine-id is not mounted from a + memory file system, or if /etc is + read-only. The command will write the current transient + machine ID to disk and unmount the + /etc/machine-id mount point in a + race-free manner to ensure that this file is always valid and + accessible for other processes. + + This command is primarily used by the + systemd-machine-id-commit.service8 + early boot service. + + + + + + Print the machine ID generated or committed after the operation is complete. + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + See Also + + systemd1, + machine-id5, + systemd-machine-id-commit.service8, + dbus-uuidgen1, + systemd-firstboot1 + + + + diff --git a/man/systemd-machined.service.xml b/man/systemd-machined.service.xml new file mode 100644 index 00000000..8771434e --- /dev/null +++ b/man/systemd-machined.service.xml @@ -0,0 +1,63 @@ + + + + + + + + systemd-machined.service + systemd + + + + systemd-machined.service + 8 + + + + systemd-machined.service + systemd-machined + Virtual machine and container registration manager + + + + systemd-machined.service + /usr/lib/systemd/systemd-machined + + + + Description + + systemd-machined is a system service that + keeps track of virtual machines and containers, and processes + belonging to them. + + See + systemd-nspawn1 + for some examples on how to run containers with OS tools. + + Use + nss-mymachines8 + to make the names of local containers known to + systemd-machined locally resolvable as host + names. + + See the + + machined D-Bus API Documentation for information about the + APIs systemd-machined provides. + + + + See Also + + systemd1, + machinectl1, + systemd-nspawn1, + nss-mymachines8, + systemd.special7 + + + + diff --git a/man/systemd-makefs@.service.xml b/man/systemd-makefs@.service.xml new file mode 100644 index 00000000..8514af67 --- /dev/null +++ b/man/systemd-makefs@.service.xml @@ -0,0 +1,94 @@ + + + + + + + + systemd-makefs@.service + systemd + + + + systemd-makefs@.service + 8 + + + + systemd-makefs@.service + systemd-mkswap@.service + systemd-growfs@.service + systemd-makefs + systemd-growfs + Creating and growing file systems on demand + + + + systemd-makefs@device.service + systemd-mkswap@device.service + systemd-growfs@mountpoint.service + /usr/lib/systemd/systemd-makefs + /usr/lib/systemd/systemd-growfs + + + + Description + + systemd-makefs@.service, + systemd-mkswap@.service, and + systemd-growfs@.service are used to implement the + and options + in fstab5, + see systemd.mount5. + They are instantiated for each device for which the file system or swap structure + needs to be initialized, and for each mount point where the file system needs to + be grown. + + These services are started at boot, either right before or right after the + mount point or swap device are used. + + systemd-makefs knows very little about specific file + systems and swap devices, and after checking that the block device does not already + contain a file system or other content, it will execute binaries specific to + each filesystem type (/sbin/mkfs.type). + + systemd-growfs knows very little about specific file + systems and swap devices, and will instruct the kernel to grow the mounted + filesystem to full size of the underlying block device. Nevertheless, it needs + to know the + ioctl2 + number specific to each file system, so only certain types are supported. + Currently: + ext45, + btrfs (see + btrfs-man55), + xfs5, + + and dm-crypt partitions (see + cryptsetup8). + + + If the creation of a file system or swap device fails, the mount point or + swap is failed too. If the growing of a file system fails, a warning is emitted. + + + + + See Also + + systemd1, + systemd.mount8, + systemd-fstab-generator8, + mkfs.btrfs8, + mkfs.cramfs8, + mkfs.ext48, + mkfs.fat8, + mkfs.hfsplus8, + mkfs.minix8, + mkfs.ntfs8, + mkfs.xfs8 + + + + diff --git a/man/systemd-modules-load.service.xml b/man/systemd-modules-load.service.xml new file mode 100644 index 00000000..ca9edef3 --- /dev/null +++ b/man/systemd-modules-load.service.xml @@ -0,0 +1,71 @@ + + + + + + + + systemd-modules-load.service + systemd + + + + systemd-modules-load.service + 8 + + + + systemd-modules-load.service + systemd-modules-load + Load kernel modules at boot + + + + systemd-modules-load.service + /usr/lib/systemd/systemd-modules-load + + + + Description + + systemd-modules-load.service is an + early boot service that loads kernel modules based on static + configuration. + + See + modules-load.d5 + for information about the configuration of this service. + + + + + Kernel Command Line + + systemd-modules-load.service + understands the following kernel command line parameters: + + + + + modules_load= + rd.modules_load= + + Takes a comma-separated list of kernel modules + to statically load during early boot. The option prefixed with + rd. is read by the initial RAM disk + only. + + + + + + + See Also + + systemd1, + modules-load.d5, + + + + diff --git a/man/systemd-mount.xml b/man/systemd-mount.xml new file mode 100644 index 00000000..4a7c33f5 --- /dev/null +++ b/man/systemd-mount.xml @@ -0,0 +1,326 @@ + + + + + + + + systemd-mount + systemd + + + + systemd-mount + 1 + + + + systemd-mount + systemd-umount + Establish and destroy transient mount or auto-mount points + + + + + systemd-mount + OPTIONS + WHAT + WHERE + + + systemd-mount + OPTIONS + + + + systemd-mount + OPTIONS + + WHAT|WHERE + + + + + Description + + systemd-mount may be used to create and start a transient .mount or + .automount unit of the file system WHAT on the mount point + WHERE. + + In many ways, systemd-mount is similar to the lower-level + mount8 command, however instead + of executing the mount operation directly and immediately, systemd-mount schedules it through + the service manager job queue, so that it may pull in further dependencies (such as parent mounts, or a file system + checker to execute a priori), and may make use of the auto-mounting logic. + + The command takes either one or two arguments. If only one argument is specified it should refer to + a block device or regular file containing a file system (e.g. /dev/sdb1 or + /path/to/disk.img). The block device or image file is then probed for a file system + label and other metadata, and is mounted to a directory below /run/media/system/ + whose name is generated from the file system label. In this mode the block device or image file must + exist at the time of invocation of the command, so that it may be probed. If the device is found to be a + removable block device (e.g. a USB stick) an automount point instead of a regular mount point is created + (i.e. the option is implied, see below). + + If two arguments are specified the first indicates the mount source (the WHAT) and + the second indicates the path to mount it on (the WHERE). In this mode no probing of the + source is attempted, and a backing device node doesn't have to exist yet. However, if this mode is combined with + , device node probing for additional metadata is enabled, and – much like in the + single-argument case discussed above – the specified device has to exist at the time of invocation of the + command. + + Use the command to show a terse table of all local, known block devices with file + systems that may be mounted with this command. + + systemd-umount can be used to unmount a mount or automount point. It is the same + as systemd-mount . + + + + Options + + The following options are understood: + + + + + + + + Do not synchronously wait for the requested operation to finish. If this is not specified, the job will + be verified, enqueued and systemd-mount will wait until the mount or automount unit's + start-up is completed. By passing this argument, it is only verified and enqueued. + + + + + + + + + + + Suppresses additional informational output while running. + + + + + + Enable probing of the mount source. This switch is implied if a single argument is specified on + the command line. If passed, additional metadata is read from the device to enhance the unit to create. For + example, a descriptive string for the transient units is generated from the file system label and device + model. Moreover if a removable block device (e.g. USB stick) is detected an automount unit instead of a regular + mount unit is created, with a short idle timeout, in order to ensure the file-system is placed in a clean + state quickly after each access. + + + + + + + Specifies the file system type to mount (e.g. vfat, ext4, + …). If omitted (or set to auto) the file system is determined automatically. + + + + + + + Additional mount options for the mount point. + + + + + + Let the specified user USER own the mounted file system. + This is done by appending and options to the list + of mount options. Only certain file systems support this option. + + + + + + Takes a boolean argument, defaults to on. Controls whether to run a file system check + immediately before the mount operation. In the automount case (see below) the + check will be run the moment the first access to the device is made, which might slightly delay the + access. + + + + + + Provide a description for the mount or automount unit. See Description= in + systemd.unit5. + + + + + + + + Sets a unit property for the mount unit that is created. This takes an assignment in the same + format as systemctl1's + set-property command. + + + + + + + Takes a boolean argument. Controls whether to create an automount point or a regular mount + point. If true an automount point is created that is backed by the actual file system at the time of first + access. If false a plain mount point is created that is backed by the actual file system immediately. Automount + points have the benefit that the file system stays unmounted and hence in clean state until it is first + accessed. In automount mode the switch (see below) may be used to ensure + the mount point is unmounted automatically after the last access and an idle period passed. + + If this switch is not specified it defaults to false. If not specified and is + used (or only a single argument passed, which implies , see above), and the file + system block device is detected to be removable, it is set to true, in order to increase the chance that the + file system is in a fully clean state if the device is unplugged abruptly. + + + + + + Equivalent to . + + + + + + Takes a time value that controls the idle timeout in automount mode. If set to + infinity (the default) no automatic unmounts are done. Otherwise the file system backing the + automount point is detached after the last access and the idle timeout passed. See + systemd.time7 for details on + the time syntax supported. This option has no effect if only a regular mount is established, and automounting + is not used. + + Note that if is used (or only a single argument passed, which implies + , see above), and the file system block device is detected to be removable, + is implied. + + + + + + Similar to , but applies additional properties to the automount + unit created, instead of the mount unit. + + + + + + This option only has an effect in automount mode, + and controls whether the automount unit shall be bound to the backing device's lifetime. If set, the + automount point will be removed automatically when the backing device vanishes. By default the automount point + stays around, and subsequent accesses will block until backing device is replugged. This option has no effect + in case of non-device mounts, such as network or virtual file system mounts. + + Note that if is used (or only a single argument passed, which implies + , see above), and the file system block device is detected to be removable, this + option is implied. + + + + + + Instead of establishing a mount or automount point, print a terse list of block devices + containing file systems that may be mounted with systemd-mount, along with useful metadata + such as labels, etc. + + + + + + + Stop the mount and automount units corresponding to the specified mount points + WHERE or the devices WHAT. + systemd-mount with this option or systemd-umount can take multiple arguments + which can be mount points, devices, /etc/fstab style node names, or backing files + corresponding to loop devices, like + systemd-mount --umount /path/to/umount /dev/sda1 UUID=xxxxxx-xxxx LABEL=xxxxx /path/to/disk.img. + Note that when or is specified, only absolute paths to mount points are + supported. + + + + + + + Unload the transient unit after it completed, even if it failed. Normally, without this option, + all mount units that mount and failed are kept in memory until the user explicitly resets their failure state with + systemctl reset-failed or an equivalent command. On the other hand, units that stopped + successfully are unloaded immediately. If this option is turned on the "garbage collection" of units is more + aggressive, and unloads units regardless if they exited successfully or failed. This option is a shortcut for + --property=CollectMode=inactive-or-failed, see the explanation for + CollectMode= in + systemd.unit5 for further + information. + + + + + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure + code otherwise. + + + + The udev Database + + If is used, systemd-mount honors a couple of additional udev + properties of block devices: + + + + SYSTEMD_MOUNT_OPTIONS= + + The mount options to use, if is not used. + + + + SYSTEMD_MOUNT_WHERE= + + The file system path to place the mount point at, instead of the automatically generated + one. + + + + + + Example + + Use a udev rule like the following to automatically mount all USB storage plugged in: + + ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", \ + RUN{program}+="/usr/bin/systemd-mount --no-block --automount=yes --collect $devnode" + + + + See Also + + systemd1, + mount8, + systemctl1, + systemd.unit5, + systemd.mount5, + systemd.automount5, + systemd-run1 + + + + diff --git a/man/systemd-networkd-wait-online.service.xml b/man/systemd-networkd-wait-online.service.xml new file mode 100644 index 00000000..51b865dc --- /dev/null +++ b/man/systemd-networkd-wait-online.service.xml @@ -0,0 +1,129 @@ + + + + + + + + systemd-networkd-wait-online.service + systemd + + + + systemd-networkd-wait-online.service + 8 + + + + systemd-networkd-wait-online.service + systemd-networkd-wait-online + Wait for network to come online + + + + systemd-networkd-wait-online.service + /usr/lib/systemd/systemd-networkd-wait-online + + + + Description + + systemd-networkd-wait-online is a + oneshot system service (see systemd.service5), that waits for the network to be + configured. By default, it will wait for all links it is aware of + and which are managed by + systemd-networkd.service8 + to be fully configured or failed, and for at least one link to be online. Here, online means that + the link's operational state is equal or higher than degraded. The threshold + can be configured by option. + + + + Options + + The following options are understood: + + + + INTERFACE:OPERSTATE + INTERFACE:OPERSTATE + + Network interface to wait for before deciding if the system is online. This + is useful when a system has several interfaces which will be configured, but a particular + one is necessary to access some network resources. When used, all other interfaces are ignored. + This option may be used more than once to wait for multiple network interfaces. When this + option is specified multiple times, then systemd-networkd-wait-online waits + for all specified interfaces to be online. Optionally, required minimum operational state can be + specified after a colon :. Please see + networkctl1 + for possible operational states. If the operational state is not specified here, then + the value from RequiredForOnline= in the corresponding + .network file is used if present, and degraded otherwise. + + + + + INTERFACE + + Network interfaces to be ignored when deciding + if the system is online. By default, only the loopback + interface is ignored. This option may be used more than once + to ignore multiple network interfaces. + + + + OPERSTATE + OPERSTATE + + Takes an operational state. Please see + networkctl1 + for possible operational states. If set, the specified value overrides + RequiredForOnline= settings in .network files. + But this does not override operational states specified in option. + + + + + + + Even if several interfaces are in configuring state, + systemd-networkd-wait-online exits with success when at least one interface + becomes online. When this option is specified with , then + systemd-networkd-wait-online waits for one of the specified interfaces to be + online. This option is useful when some interfaces may not have carrier on boot. + + + + + SECS + + Fail the service if the network is not online + by the time the timeout elapses. A timeout of 0 disables the + timeout. Defaults to 120 seconds. + + + + + + + Suppress log messages. + + + + + + + + + See Also + + systemd1, + systemd.service5, + systemd-networkd.service8, + networkctl1 + + + + diff --git a/man/systemd-networkd.service.xml b/man/systemd-networkd.service.xml new file mode 100644 index 00000000..b3ba621a --- /dev/null +++ b/man/systemd-networkd.service.xml @@ -0,0 +1,93 @@ + + + + + + + + systemd-networkd.service + systemd + + + + systemd-networkd.service + 8 + + + + systemd-networkd.service + systemd-networkd + Network manager + + + + systemd-networkd.service + /usr/lib/systemd/systemd-networkd + + + + Description + + systemd-networkd is a system service that + manages networks. It detects and configures network devices as + they appear, as well as creating virtual network devices. + + To configure low-level link settings independently of + networks, see + systemd.link5. + + systemd-networkd will create network devices based + on the configuration in + systemd.netdev5 + files, respecting the [Match] sections in those files. + + systemd-networkd will manage network addresses and + routes for any link for which it finds a .network file + with an appropriate [Match] section, see + systemd.network5. + For those links, it will flush existing network addresses and routes when + bringing up the device. Any links not matched by one of the + .network files will be ignored. It is also possible to + explicitly tell systemd-networkd to ignore a link by + using Unmanaged=yes option, see + systemd.network5. + + + When systemd-networkd exits, it generally leaves + existing network devices and configuration intact. This makes it possible to + transition from the initramfs and to restart the service without breaking + connectivity. This also means that when configuration is updated and + systemd-networkd is restarted, netdev interfaces for + which configuration was removed will not be dropped, and may need to be + cleaned up manually. + + + Configuration Files + The configuration files are read from the files located in the + system network directory /usr/lib/systemd/network, + the volatile runtime network directory + /run/systemd/network and the local administration + network directory /etc/systemd/network. + + Networks are configured in .network + files, see + systemd.network5, + and virtual network devices are configured in + .netdev files, see + systemd.netdev5. + + + + + See Also + + systemd1, + systemd.link5, + systemd.network5, + systemd.netdev5, + systemd-networkd-wait-online.service8 + + + + diff --git a/man/systemd-notify.xml b/man/systemd-notify.xml new file mode 100644 index 00000000..89060680 --- /dev/null +++ b/man/systemd-notify.xml @@ -0,0 +1,181 @@ + + + + + + + + systemd-notify + systemd + + + + systemd-notify + 1 + + + + systemd-notify + Notify service manager about start-up completion and other daemon status changes + + + + + systemd-notify OPTIONS VARIABLE=VALUE + + + + + Description + + systemd-notify may be called by daemon + scripts to notify the init system about status changes. It can be + used to send arbitrary information, encoded in an + environment-block-like list of strings. Most importantly, it can be + used for start-up completion notification. + + This is mostly just a wrapper around + sd_notify() and makes this functionality + available to shell scripts. For details see + sd_notify3. + + + The command line may carry a list of environment variables + to send as part of the status update. + + Note that systemd will refuse reception of status updates from this command unless + NotifyAccess= is set for the service unit this command is called from. + + Note that sd_notify() notifications may be attributed to units correctly only if either + the sending process is still around at the time PID 1 processes the message, or if the sending process is + explicitly runtime-tracked by the service manager. The latter is the case if the service manager originally forked + off the process, i.e. on all processes that match NotifyAccess= or + NotifyAccess=. Conversely, if an auxiliary process of the unit sends an + sd_notify() message and immediately exits, the service manager might not be able to properly + attribute the message to the unit, and thus will ignore it, even if + NotifyAccess= is set for it. + + systemd-notify will first attempt to invoke sd_notify() pretending to + have the PID of the invoking process. This will only succeed when invoked with sufficient privileges. On failure, + it will then fall back to invoking it under its own PID. This behaviour is useful in order that when the tool is + invoked from a shell script the shell process — and not the systemd-notify process — appears as + sender of the message, which in turn is helpful if the shell process is the main process of a service, due to the + limitations of NotifyAccess= described above. + + + + Options + + The following options are understood: + + + + + + Inform the init system about service start-up + completion. This is equivalent to systemd-notify + READY=1. For details about the semantics of this + option see + sd_notify3. + + + + + + Inform the init system about the main PID of + the daemon. Takes a PID as argument. If the argument is + omitted, the PID of the process that invoked + systemd-notify is used. This is equivalent + to systemd-notify MAINPID=$PID. For details + about the semantics of this option see + sd_notify3. + + + + USER + + Set the user ID to send the notification from. Takes a UNIX user name or numeric UID. When + specified the notification message will be sent with the specified UID as sender, in place of the user the + command was invoked as. This option requires sufficient privileges in order to be able manipulate the user + identity of the process. + + + + + + Send a free-form status string for the daemon + to the init systemd. This option takes the status string as + argument. This is equivalent to systemd-notify + STATUS=…. For details about the semantics of this + option see + sd_notify3. + + + + + + Returns 0 if the system was booted up with + systemd, non-zero otherwise. If this option is passed, no + message is sent. This option is hence unrelated to the other + options. For details about the semantics of this option, see + sd_booted3. An + alternate way to check for this state is to call + systemctl1 + with the is-system-running command. It will + return offline if the system was not booted + with systemd. + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + Example + + + Start-up Notification and Status Updates + + A simple shell daemon that sends start-up notifications + after having set up its communication channel. During runtime it + sends further status updates to the init system: + + #!/bin/bash + +mkfifo /tmp/waldo +systemd-notify --ready --status="Waiting for data…" + +while : ; do + read a < /tmp/waldo + systemd-notify --status="Processing $a" + + # Do something with $a … + + systemd-notify --status="Waiting for data…" +done + + + + + See Also + + systemd1, + systemctl1, + systemd.unit5, + sd_notify3, + sd_booted3 + + + + diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml new file mode 100644 index 00000000..afa7a17d --- /dev/null +++ b/man/systemd-nspawn.xml @@ -0,0 +1,1484 @@ + + + +]> + + + + + + systemd-nspawn + systemd + + + + systemd-nspawn + 1 + + + + systemd-nspawn + Spawn a command or OS in a light-weight container + + + + + systemd-nspawn + OPTIONS + COMMAND + ARGS + + + + systemd-nspawn + --boot + OPTIONS + ARGS + + + + + Description + + systemd-nspawn may be used to run a command or OS in a light-weight namespace + container. In many ways it is similar to chroot1, but more powerful + since it fully virtualizes the file system hierarchy, as well as the process tree, the various IPC subsystems and + the host and domain name. + + systemd-nspawn may be invoked on any directory tree containing an operating system tree, + using the command line option. By using the option an OS + tree is automatically searched for in a couple of locations, most importantly in + /var/lib/machines, the suggested directory to place OS container images installed on the + system. + + In contrast to chroot1 systemd-nspawn + may be used to boot full Linux-based operating systems in a container. + + systemd-nspawn limits access to various kernel interfaces in the container to read-only, + such as /sys, /proc/sys or /sys/fs/selinux. The + host's network interfaces and the system clock may not be changed from within the container. Device nodes may not + be created. The host system cannot be rebooted and kernel modules may not be loaded from within the + container. + + Use a tool like dnf8, debootstrap8, or + pacman8 to + set up an OS directory tree suitable as file system hierarchy for systemd-nspawn containers. See + the Examples section below for details on suitable invocation of these commands. + + As a safety check systemd-nspawn will verify the existence of + /usr/lib/os-release or /etc/os-release in the container tree before + starting the container (see + os-release5). It might be + necessary to add this file to the container tree manually if the OS of the container is too old to contain this + file out-of-the-box. + + systemd-nspawn may be invoked directly from the interactive command line or run as system + service in the background. In this mode each container instance runs as its own service instance; a default + template unit file systemd-nspawn@.service is provided to make this easy, taking the container + name as instance identifier. Note that different default options apply when systemd-nspawn is + invoked by the template unit file than interactively on the command line. Most importantly the template unit file + makes use of the which is not the default in case systemd-nspawn is + invoked from the interactive command line. Further differences with the defaults are documented along with the + various supported options below. + + The machinectl1 tool may + be used to execute a number of operations on containers. In particular it provides easy-to-use commands to run + containers as system services using the systemd-nspawn@.service template unit + file. + + Along with each container a settings file with the .nspawn suffix may exist, containing + additional settings to apply when running the container. See + systemd.nspawn5 for + details. Settings files override the default options used by the systemd-nspawn@.service + template unit file, making it usually unnecessary to alter this template file directly. + + Note that systemd-nspawn will mount file systems private to the container to + /dev, /run and similar. These will not be visible outside of the + container, and their contents will be lost when the container exits. + + Note that running two systemd-nspawn containers from the same directory tree will not make + processes in them see each other. The PID namespace separation of the two containers is complete and the containers + will share very few runtime objects except for the underlying file system. Use + machinectl1's + login or shell commands to request an additional login session in a running + container. + + systemd-nspawn implements the Container Interface + specification. + + While running, containers invoked with systemd-nspawn are registered with the + systemd-machined8 service that + keeps track of running containers, and provides programming interfaces to interact with them. + + + + Options + + If option is specified, the arguments + are used as arguments for the init program. Otherwise, + COMMAND specifies the program to launch + in the container, and the remaining arguments are used as + arguments for this program. If is not used and + no arguments are specified, a shell is launched in the + container. + + The following options are understood: + + + + + + + + Turns off any status output by the tool + itself. When this switch is used, the only output from nspawn + will be the console output of the container OS + itself. + + + + MODE + + Controls whether + systemd-nspawn shall search for and use + additional per-container settings from + .nspawn files. Takes a boolean or the + special values or + . + + If enabled (the default), a settings file named after the + machine (as specified with the + setting, or derived from the directory or image file name) + with the suffix .nspawn is searched in + /etc/systemd/nspawn/ and + /run/systemd/nspawn/. If it is found + there, its settings are read and used. If it is not found + there, it is subsequently searched in the same directory as the + image file or in the immediate parent of the root directory of + the container. In this case, if the file is found, its settings + will be also read and used, but potentially unsafe settings + are ignored. Note that in both these cases, settings on the + command line take precedence over the corresponding settings + from loaded .nspawn files, if both are + specified. Unsafe settings are considered all settings that + elevate the container's privileges or grant access to + additional resources such as files or directories of the + host. For details about the format and contents of + .nspawn files, consult + systemd.nspawn5. + + If this option is set to , the + file is searched, read and used the same way, however, the order of + precedence is reversed: settings read from the + .nspawn file will take precedence over + the corresponding command line options, if both are + specified. + + If this option is set to , the + file is searched, read and used the same way, but regardless + of being found in /etc/systemd/nspawn/, + /run/systemd/nspawn/ or next to the image + file or container root directory, all settings will take + effect, however, command line arguments still take precedence + over corresponding settings. + + If disabled, no .nspawn file is read + and no settings except the ones on the command line are in + effect. + + + + + + Image Options + + + + + + + + Directory to use as file system root for the + container. + + If neither , nor + is specified the directory is + determined by searching for a directory named the same as the + machine name specified with . See + machinectl1 + section "Files and Directories" for the precise search path. + + If neither , + , nor + are specified, the current directory will + be used. May not be specified together with + . + + + + + + Directory or btrfs subvolume to use as template for the + container's root directory. If this is specified and the container's root directory (as configured by + ) does not yet exist it is created as btrfs snapshot + (if supported) or plain directory (otherwise) and populated from this template tree. Ideally, the + specified template path refers to the root of a btrfs subvolume, in which case a + simple copy-on-write snapshot is taken, and populating the root directory is instant. If the + specified template path does not refer to the root of a btrfs subvolume (or not + even to a btrfs file system at all), the tree is copied (though possibly in a + 'reflink' copy-on-write scheme — if the file system supports that), which can be substantially more + time-consuming. Note that the snapshot taken is of the specified directory or subvolume, including + all subdirectories and subvolumes below it, but excluding any sub-mounts. May not be specified + together with or . + + Note that this switch leaves host name, machine ID and + all other settings that could identify the instance + unmodified. + + + + + + + If specified, the container is run with a temporary snapshot of its file system that is removed + immediately when the container terminates. May not be specified together with + . + Note that this switch leaves host name, machine ID and all other settings that could identify + the instance unmodified. Please note that — as with — taking the + temporary snapshot is more efficient on file systems that support subvolume snapshots or 'reflinks' + natively (btrfs or new xfs) than on more traditional file + systems that do not (ext4). Note that the snapshot taken is of the specified + directory or subvolume, including all subdirectories and subvolumes below it, but excluding any + sub-mounts. + + With this option no modifications of the container image are retained. Use + (described below) for other mechanisms to restrict persistency of + container images during runtime. + + + + + + + + Disk image to mount the root directory for the + container from. Takes a path to a regular file or to a block + device node. The file or block device must contain + either: + + + An MBR partition table with a single + partition of type 0x83 that is marked + bootable. + + A GUID partition table (GPT) with a single + partition of type + 0fc63daf-8483-4772-8e79-3d69d8477de4. + + A GUID partition table (GPT) with a marked + root partition which is mounted as the root directory of the + container. Optionally, GPT images may contain a home and/or + a server data partition which are mounted to the appropriate + places in the container. All these partitions must be + identified by the partition types defined by the Discoverable + Partitions Specification. + + No partition table, and a single file system spanning the whole image. + + + On GPT images, if an EFI System Partition (ESP) is discovered, it is automatically mounted to + /efi (or /boot as fallback) in case a directory by this name exists + and is empty. + + Partitions encrypted with LUKS are automatically decrypted. Also, on GPT images dm-verity data integrity + hash partitions are set up if the root hash for them is specified using the + option. + + Any other partitions, such as foreign partitions or swap partitions are not mounted. May not be specified + together with , . + + + + + + Takes the path to an OCI runtime bundle to invoke, as specified in the OCI Runtime Specification. In + this case no .nspawn file is loaded, and the root directory and various settings are read + from the OCI runtime JSON data (but data passed on the command line takes precedence). + + + + + + Mount the container's root file system (and any other file systems container in the container + image) read-only. This has no effect on additional mounts made with , + and similar options. This mode is implied if the container image file or directory is + marked read-only itself. It is also implied if is used. In this case the container + image on disk is strictly read-only, while changes are permitted but kept non-persistently in memory only. For + further details, see below. + + + + + MODE + + Boots the container in volatile mode. When no mode parameter is passed or when mode is + specified as , full volatile mode is enabled. This means the root directory is mounted as a + mostly unpopulated tmpfs instance, and /usr/ from the OS tree is + mounted into it in read-only mode (the system thus starts up with read-only OS image, but pristine state and + configuration, any changes are lost on shutdown). When the mode parameter is specified as + , the OS tree is mounted read-only, but /var/ is mounted as a + writable tmpfs instance into it (the system thus starts up with read-only OS resources and + configuration, but pristine state, and any changes to the latter are lost on shutdown). When the mode parameter + is specified as the read-only root file system is combined with a writable + tmpfs instance through overlayfs, so that it appears at it normally + would, but any changes are applied to the temporary file system only and lost when the container is + terminated. When the mode parameter is specified as (the default), the whole OS tree is + made available writable (unless is specified, see above). + + Note that if one of the volatile modes is chosen, its effect is limited to the root file system (or + /var/ in case of ), and any other mounts placed in the hierarchy are + unaffected — regardless if they are established automatically (e.g. the EFI system partition that might be + mounted to /efi/ or /boot/) or explicitly (e.g. through an additional + command line option such as , see below). This means, even if + is used changes to /efi/ or + /boot/ are prohibited in case such a partition exists in the container image operated on, + and even if is used the hypothetical file /etc/foobar is + potentially writable if if used to mount it from outside the read-only + container /etc directory. + + The option is closely related to this setting, and provides similar + behaviour by making a temporary, ephemeral copy of the whole OS image and executing that. For further details, + see above. + + The and options provide similar functionality, but + for specific sub-directories of the OS image only. For details, see below. + + This option provides similar functionality for containers as the systemd.volatile= + kernel command line switch provides for host systems. See + kernel-command-line7 for + details. + + Note that setting this option to or will only work + correctly with operating systems in the container that can boot up with only + /usr/ mounted, and are able to automatically populate /var/ + (and /etc/ in case of --volatile=yes). Specifically, this + means that operating systems that follow the historic split of /bin/ and + /lib/ (and related directories) from /usr/ (i.e. where the + former are not symlinks into the latter) are not supported by --volatile=yes as + container payload. The option does not require any particular preparations + in the OS, but do note that overlayfs behaviour differs from regular file systems + in a number of ways, and hence compatibility is limited. + + + + + + Takes a data integrity (dm-verity) root hash specified in hexadecimal. This option enables data + integrity checks using dm-verity, if the used image contains the appropriate integrity data (see above). The + specified hash must match the root hash of integrity data, and is usually at least 256 bits (and hence 64 + formatted hexadecimal characters) long (in case of SHA256 for example). If this option is not specified, but + the image file carries the user.verity.roothash extended file attribute (see xattr7), then the root + hash is read from it, also as formatted hexadecimal characters. If the extended file attribute is not found (or + is not supported by the underlying file system), but a file with the .roothash suffix is + found next to the image file, bearing otherwise the same name, the root hash is read from it and automatically + used, also as formatted hexadecimal characters. + + + + + + Pivot the specified directory to / inside the container, and either unmount the + container's old root, or pivot it to another specified directory. Takes one of: a path argument — in which case the + specified path will be pivoted to / and the old root will be unmounted; or a colon-separated pair + of new root path and pivot destination for the old root. The new root path will be pivoted to /, + and the old / will be pivoted to the other directory. Both paths must be absolute, and are resolved + in the container's file system namespace. + + This is for containers which have several bootable directories in them; for example, several + OSTree deployments. It emulates the behavior of + the boot loader and initial RAM disk which normally select which directory to mount as the root and start the + container's PID 1 in. + + + + + Execution Options + + + + + + + Invoke the shell or specified program as process ID (PID) 2 instead of PID 1 (init). By + default, if neither this option nor is used, the selected program is run as the process + with PID 1, a mode only suitable for programs that are aware of the special semantics that the process with + PID 1 has on UNIX. For example, it needs to reap all processes reparented to it, and should implement + sysvinit compatible signal handling (specifically: it needs to reboot on SIGINT, reexecute + on SIGTERM, reload configuration on SIGHUP, and so on). With a minimal stub init + process is run as PID 1 and the selected program is executed as PID 2 (and hence does not need to implement any + special semantics). The stub init process will reap processes as necessary and react appropriately to + signals. It is recommended to use this mode to invoke arbitrary commands in containers, unless they have been + modified to run correctly as PID 1. Or in other words: this switch should be used for pretty much all commands, + except when the command refers to an init or shell implementation, as these are generally capable of running + correctly as PID 1. This option may not be combined with . + + + + + + + + Automatically search for an init program and invoke it as PID 1, instead of a shell or a user + supplied program. If this option is used, arguments specified on the command line are used as arguments for the + init program. This option may not be combined with . + + The following table explains the different modes of invocation and relationship to + (see above): + + + Invocation Mode + + + + + + Switch + Explanation + + + + + Neither nor specified + The passed parameters are interpreted as the command line, which is executed as PID 1 in the container. + + + + specified + The passed parameters are interpreted as the command line, which is executed as PID 2 in the container. A stub init process is run as PID 1. + + + + specified + An init program is automatically searched for and run as PID 1 in the container. The passed parameters are used as invocation parameters for this process. + + + + +
+ + Note that is the default mode of operation if the + systemd-nspawn@.service template unit file is used. +
+
+ + + + + Change to the specified working directory before invoking the process in the container. Expects + an absolute path in the container's file system namespace. + + + + + + + Specifies an environment variable assignment + to pass to the init process in the container, in the format + NAME=VALUE. This may be used to override + the default variables or to set additional variables. This + parameter may be used more than once. + + + + + + + After transitioning into the container, change + to the specified user-defined in the container's user + database. Like all other systemd-nspawn features, this is not + a security feature and provides protection against accidental + destructive operations only. + + + + + + Specify the process signal to send to the container's PID 1 when nspawn itself receives + SIGTERM, in order to trigger an orderly shutdown of the container. Defaults to + SIGRTMIN+3 if is used (on systemd-compatible init systems + SIGRTMIN+3 triggers an orderly shutdown). If is not used and this + option is not specified the container's processes are terminated abruptly via SIGKILL. For + a list of valid signals, see signal7. + + + + + + Configures support for notifications from the container's init process. + takes a boolean ( and ). + With option systemd-nspawn notifies systemd + with a READY=1 message when the init process is created. + With option systemd-nspawn waits for the + READY=1 message from the init process in the container + before sending its own to systemd. For more details about notifications + see sd_notify3). + +
+ +
+ System Identity Options + + + + + + + Sets the machine name for this container. This + name may be used to identify this container during its runtime + (for example in tools like + machinectl1 + and similar), and is used to initialize the container's + hostname (which the container can choose to override, + however). If not specified, the last component of the root + directory path of the container is used, possibly suffixed + with a random identifier in case + mode is selected. If the root directory selected is the host's + root directory the host's hostname is used as default + instead. + + + + + + Controls the hostname to set within the container, if different from the machine name. Expects + a valid hostname as argument. If this option is used, the kernel hostname of the container will be set to this + value, otherwise it will be initialized to the machine name as controlled by the + option described above. The machine name is used for various aspect of identification of the container from the + outside, the kernel hostname configurable with this option is useful for the container to identify itself from + the inside. It is usually a good idea to keep both forms of identification synchronized, in order to avoid + confusion. It is hence recommended to avoid usage of this option, and use + exclusively. Note that regardless whether the container's hostname is initialized from the name set with + or the one set with , the container can later override + its kernel hostname freely on its own as well. + + + + + + + Set the specified UUID for the container. The + init system will initialize + /etc/machine-id from this if this file is + not set yet. Note that this option takes effect only if + /etc/machine-id in the container is + unpopulated. + + + + + Property Options + + + + + + + Make the container part of the specified slice, instead of the default + machine.slice. This applies only if the machine is run in its own scope unit, i.e. if + isn't used. + + + + + + + Set a unit property on the scope unit to register for the machine. This applies only if the + machine is run in its own scope unit, i.e. if isn't used. Takes unit property + assignments in the same format as systemctl set-property. This is useful to set memory + limits and similar for container. + + + + + + + Controls whether the container is registered with + systemd-machined8. Takes a + boolean argument, which defaults to yes. This option should be enabled when the container + runs a full Operating System (more specifically: a system and service manager as PID 1), and is useful to + ensure that the container is accessible via + machinectl1 and shown by + tools such as ps1. If the container + does not run a service manager, it is recommended to set this option to + no. + + + + + + Instead of creating a transient scope unit to run the container in, simply use the service or + scope unit systemd-nspawn has been invoked in. If is set + this unit is registered with + systemd-machined8. This + switch should be used if systemd-nspawn is invoked from within a service unit, and the + service unit's sole purpose is to run a single systemd-nspawn container. This option is not + available if run from a user session. + Note that passing disables the effect of and + . Use and in + combination to disable any kind of unit allocation or registration with + systemd-machined. + + + + + User Namespacing Options + + + + + + Controls user namespacing. If enabled, the container will run with its own private set of UNIX + user and group ids (UIDs and GIDs). This involves mapping the private UIDs/GIDs used in the container (starting + with the container's root user 0 and up) to a range of UIDs/GIDs on the host that are not used for other + purposes (usually in the range beyond the host's UID/GID 65536). The parameter may be specified as follows: + + + If one or two colon-separated numbers are specified, user namespacing is turned on. The first + parameter specifies the first host UID/GID to assign to the container, the second parameter specifies the + number of host UIDs/GIDs to assign to the container. If the second parameter is omitted, 65536 UIDs/GIDs are + assigned. + + If the parameter is omitted, or true, user namespacing is turned on. The UID/GID range to + use is determined automatically from the file ownership of the root directory of the container's directory + tree. To use this option, make sure to prepare the directory tree in advance, and ensure that all files and + directories in it are owned by UIDs/GIDs in the range you'd like to use. Also, make sure that used file ACLs + exclusively reference UIDs/GIDs in the appropriate range. If this mode is used the number of UIDs/GIDs + assigned to the container for use is 65536, and the UID/GID of the root directory must be a multiple of + 65536. + + If the parameter is false, user namespacing is turned off. This is the default. + + + The special value pick turns on user namespacing. In this case the UID/GID + range is automatically chosen. As first step, the file owner of the root directory of the container's + directory tree is read, and it is checked that it is currently not used by the system otherwise (in + particular, that no other container is using it). If this check is successful, the UID/GID range determined + this way is used, similar to the behavior if "yes" is specified. If the check is not successful (and thus + the UID/GID range indicated in the root directory's file owner is already used elsewhere) a new – currently + unused – UID/GID range of 65536 UIDs/GIDs is randomly chosen between the host UID/GIDs of 524288 and + 1878982656, always starting at a multiple of 65536. This setting implies + (see below), which has the effect that the files and directories in + the container's directory tree will be owned by the appropriate users of the range picked. Using this option + makes user namespace behavior fully automatic. Note that the first invocation of a previously unused + container image might result in picking a new UID/GID range for it, and thus in the (possibly expensive) file + ownership adjustment operation. However, subsequent invocations of the container will be cheap (unless of + course the picked UID/GID range is assigned to a different use by then). + + + It is recommended to assign at least 65536 UIDs/GIDs to each container, so that the usable UID/GID range in the + container covers 16 bit. For best security, do not assign overlapping UID/GID ranges to multiple containers. It is + hence a good idea to use the upper 16 bit of the host 32-bit UIDs/GIDs as container identifier, while the lower 16 + bit encode the container UID/GID used. This is in fact the behavior enforced by the + option. + + When user namespaces are used, the GID range assigned to each container is always chosen identical to the + UID range. + + In most cases, using is the recommended option as it enhances + container security massively and operates fully automatically in most cases. + + Note that the picked UID/GID range is not written to /etc/passwd or + /etc/group. In fact, the allocation of the range is not stored persistently anywhere, + except in the file ownership of the files and directories of the container. + + Note that when user namespacing is used file ownership on disk reflects this, and all of the container's + files and directories are owned by the container's effective user and group IDs. This means that copying files + from and to the container image requires correction of the numeric UID/GID values, according to the UID/GID + shift applied. + + + + + + If specified, all files and directories in the container's directory tree will be + adjusted so that they are owned by the appropriate UIDs/GIDs selected for the container (see above). + This operation is potentially expensive, as it involves iterating through the full directory tree of + the container. Besides actual file ownership, file ACLs are adjusted as well. + + This option is implied if is used. This option has no effect if + user namespacing is not used. + + + + + + If the kernel supports the user namespaces feature, equivalent to + , otherwise equivalent to + . + + Note that is the default if the + systemd-nspawn@.service template unit file is used. + + Note: it is possible to undo the effect of (or + ) on the file system by redoing the operation with the first UID of 0: + + systemd-nspawn … --private-users=0 --private-users-chown + + + + + + + Networking Options + + + + + + + Disconnect networking of the container from + the host. This makes all network interfaces unavailable in the + container, with the exception of the loopback device and those + specified with and + configured with . If this + option is specified, the CAP_NET_ADMIN capability will be + added to the set of capabilities the container retains. The + latter may be disabled by using . + If this option is not specified (or implied by one of the options + listed below), the container will have full access to the host network. + + + + + + + Assign the specified network interface to the + container. This will remove the specified interface from the + calling namespace and place it in the container. When the + container terminates, it is moved back to the host namespace. + Note that implies + . This option may be used + more than once to add multiple network interfaces to the + container. + + + + + + Create a macvlan interface + of the specified Ethernet network interface and add it to the + container. A macvlan interface is a virtual + interface that adds a second MAC address to an existing + physical Ethernet link. The interface in the container will be + named after the interface on the host, prefixed with + mv-. Note that + implies + . This option may be used + more than once to add multiple network interfaces to the + container. + + + + + + Create an ipvlan interface + of the specified Ethernet network interface and add it to the + container. An ipvlan interface is a virtual + interface, similar to a macvlan interface, + which uses the same MAC address as the underlying interface. + The interface in the container will be named after the + interface on the host, prefixed with iv-. + Note that implies + . This option may be used + more than once to add multiple network interfaces to the + container. + + + + + + + Create a virtual Ethernet link (veth) between host and container. The host + side of the Ethernet link will be available as a network interface named after the container's name (as + specified with ), prefixed with ve-. The container side of the + Ethernet link will be named host0. The option implies + . + + Note that + systemd-networkd.service8 + includes by default a network file /usr/lib/systemd/network/80-container-ve.network + matching the host-side interfaces created this way, which contains settings to enable automatic address + provisioning on the created virtual link via DHCP, as well as automatic IP routing onto the host's external + network interfaces. It also contains /usr/lib/systemd/network/80-container-host0.network + matching the container-side interface created this way, containing settings to enable client side address + assignment via DHCP. In case systemd-networkd is running on both the host and inside the + container, automatic IP communication from the container to the host is thus available, with further + connectivity to the external network. + + Note that is the default if the + systemd-nspawn@.service template unit file is used. + + Note that on Linux network interface names may have a length of 15 characters at maximum, while + container names may have a length up to 64 characters. As this option derives the host-side interface + name from the container name the name is possibly truncated. Thus, care needs to be taken to ensure + that interface names remain unique in this case, or even better container names are generally not + chosen longer than 12 characters, to avoid the truncation. Alternatively, the + option may be used, which allows free configuration of the + host-side interface name independently of the container name — but might require a bit more + additional configuration in case bridging in a fashion similar to + is desired. + + + + + + + Adds an additional virtual Ethernet link + between host and container. Takes a colon-separated pair of + host interface name and container interface name. The latter + may be omitted in which case the container and host sides will + be assigned the same name. This switch is independent of + , and — in contrast — may be + used multiple times, and allows configuration of the network + interface names. Note that + has no effect on interfaces created with + . + + + + + + Adds the host side of the Ethernet link created with + to the specified Ethernet bridge interface. Expects a valid network interface name of a bridge device + as argument. Note that implies . If + this option is used, the host side of the Ethernet link will use the vb- prefix + instead of ve-. Regardless of the used naming prefix the same network interface + name length limits imposed by Linux apply, along with the complications this creates (for details see + above). + + + + + + Creates a virtual Ethernet link (veth) to the container and adds it to an + automatically managed Ethernet bridge interface. The bridge interface is named after the passed argument, + prefixed with vz-. The bridge interface is automatically created when the first container + configured for its name is started, and is automatically removed when the last container configured for its + name exits. Hence, each bridge interface configured this way exists only as long as there's at least one + container referencing it running. This option is very similar to , besides + this automatic creation/removal of the bridge device. + + This setting makes it easy to place multiple related containers on a common, virtual Ethernet-based + broadcast domain, here called a "zone". Each container may only be part of one zone, but each zone may contain + any number of containers. Each zone is referenced by its name. Names may be chosen freely (as long as they form + valid network interface names when prefixed with vz-), and it is sufficient to pass the same + name to the switch of the various concurrently running containers to join + them in one zone. + + Note that + systemd-networkd.service8 + includes by default a network file /usr/lib/systemd/network/80-container-vz.network + matching the bridge interfaces created this way, which contains settings to enable automatic address + provisioning on the created virtual network via DHCP, as well as automatic IP routing onto the host's external + network interfaces. Using is hence in most cases fully automatic and + sufficient to connect multiple local containers in a joined broadcast domain to the host, with further + connectivity to the external network. + + + + + + + Takes the path to a file representing a kernel + network namespace that the container shall run in. The specified path + should refer to a (possibly bind-mounted) network namespace file, as + exposed by the kernel below /proc/$PID/ns/net. + This makes the container enter the given network namespace. One of the + typical use cases is to give a network namespace under + /run/netns created by ip-netns8, + for example, . + Note that this option cannot be used together with other + network-related options, such as + or . + + + + + + + If private networking is enabled, maps an IP + port on the host onto an IP port on the container. Takes a + protocol specifier (either tcp or + udp), separated by a colon from a host port + number in the range 1 to 65535, separated by a colon from a + container port number in the range from 1 to 65535. The + protocol specifier and its separating colon may be omitted, in + which case tcp is assumed. The container + port number and its colon may be omitted, in which case the + same port as the host port is implied. This option is only + supported if private networking is used, such as with + , + . + + + + + Security Options + + + + + + List one or more additional capabilities to grant the container. Takes a + comma-separated list of capability names, see capabilities7 + for more information. Note that the following capabilities will be granted in any way: + CAP_AUDIT_CONTROL, CAP_AUDIT_WRITE, + CAP_CHOWN, CAP_DAC_OVERRIDE, + CAP_DAC_READ_SEARCH, CAP_FOWNER, + CAP_FSETID, CAP_IPC_OWNER, CAP_KILL, + CAP_LEASE, CAP_LINUX_IMMUTABLE, + CAP_MKNOD, CAP_NET_BIND_SERVICE, + CAP_NET_BROADCAST, CAP_NET_RAW, + CAP_SETFCAP, CAP_SETGID, CAP_SETPCAP, + CAP_SETUID, CAP_SYS_ADMIN, + CAP_SYS_BOOT, CAP_SYS_CHROOT, + CAP_SYS_NICE, CAP_SYS_PTRACE, + CAP_SYS_RESOURCE, CAP_SYS_TTY_CONFIG. Also + CAP_NET_ADMIN is retained if is specified. + If the special value all is passed, all capabilities are retained. + + If the special value of help is passed, the program will print known + capability names and exit. + + + + + + Specify one or more additional capabilities to + drop for the container. This allows running the container with + fewer capabilities than the default (see + above). + + If the special value of help is passed, the program will print known + capability names and exit. + + + + + + Takes a boolean argument. Specifies the value of the PR_SET_NO_NEW_PRIVS + flag for the container payload. Defaults to off. When turned on the payload code of the container cannot + acquire new privileges, i.e. the "setuid" file bit as well as file system capabilities will not have an effect + anymore. See prctl2 for details + about this flag. + + + + + + Alter the system call filter applied to containers. Takes a space-separated list of system call + names or group names (the latter prefixed with @, as listed by the + syscall-filter command of + systemd-analyze1). Passed + system calls will be permitted. The list may optionally be prefixed by ~, in which case all + listed system calls are prohibited. If this command line option is used multiple times the configured lists are + combined. If both a positive and a negative list (that is one system call list without and one with the + ~ prefix) are configured, the negative list takes precedence over the positive list. Note + that systemd-nspawn always implements a system call whitelist (as opposed to a blacklist), + and this command line option hence adds or removes entries from the default whitelist, depending on the + ~ prefix. Note that the applied system call filter is also altered implicitly if additional + capabilities are passed using the --capabilities=. + + + + + + + Sets the SELinux security context to be used + to label processes in the container. + + + + + + + + Sets the SELinux security context to be used + to label files in the virtual API file systems in the + container. + + + + + + Resource Options + + + + + + + Sets the specified POSIX resource limit for the container payload. Expects an assignment of the + form + LIMIT=SOFT:HARD + or LIMIT=VALUE, where + LIMIT should refer to a resource limit type, such as + RLIMIT_NOFILE or RLIMIT_NICE. The SOFT and + HARD fields should refer to the numeric soft and hard resource limit values. If the + second form is used, VALUE may specify a value that is used both as soft and hard + limit. In place of a numeric value the special string infinity may be used to turn off + resource limiting for the specific type of resource. This command line option may be used multiple times to + control limits on multiple limit types. If used multiple times for the same limit type, the last use + wins. For details about resource limits see setrlimit2. By default + resource limits for the container's init process (PID 1) are set to the same values the Linux kernel originally + passed to the host init system. Note that some resource limits are enforced on resources counted per user, in + particular RLIMIT_NPROC. This means that unless user namespacing is deployed + (i.e. is used, see above), any limits set will be applied to the resource + usage of the same user on all local containers as well as the host. This means particular care needs to be + taken with these limits as they might be triggered by possibly less trusted code. Example: + --rlimit=RLIMIT_NOFILE=8192:16384. + + + + + + Changes the OOM ("Out Of Memory") score adjustment value for the container payload. This controls + /proc/self/oom_score_adj which influences the preference with which this container is + terminated when memory becomes scarce. For details see proc5. Takes an + integer in the range -1000…1000. + + + + + + Controls the CPU affinity of the container payload. Takes a comma separated list of CPU numbers + or number ranges (the latter's start and end value separated by dashes). See sched_setaffinity2 for + details. + + + + + + Control the architecture ("personality") + reported by + uname2 + in the container. Currently, only x86 and + x86-64 are supported. This is useful when + running a 32-bit container on a 64-bit host. If this setting + is not used, the personality reported in the container is the + same as the one reported on the host. + + + + + Integration Options + + + + + + Configures how /etc/resolv.conf inside of the container (i.e. DNS + configuration synchronization from host to container) shall be handled. Takes one of off, + copy-host, copy-static, bind-host, + bind-static, delete or auto. If set to + off the /etc/resolv.conf file in the container is left as it is + included in the image, and neither modified nor bind mounted over. If set to copy-host, the + /etc/resolv.conf file from the host is copied into the container. Similar, if + bind-host is used, the file is bind mounted from the host into the container. If set to + copy-static the static resolv.conf file supplied with + systemd-resolved.service8 is + copied into the container, and correspondingly bind-static bind mounts it there. If set to + delete the /etc/resolv.conf file in the container is deleted if it + exists. Finally, if set to auto the file is left as it is if private networking is turned on + (see ). Otherwise, if systemd-resolved.service is + connectible its static resolv.conf file is used, and if not the host's + /etc/resolv.conf file is used. In the latter cases the file is copied if the image is + writable, and bind mounted otherwise. It's recommended to use copy if the container shall be + able to make changes to the DNS configuration on its own, deviating from the host's settings. Otherwise + bind is preferable, as it means direct changes to /etc/resolv.conf in + the container are not allowed, as it is a read-only bind mount (but note that if the container has enough + privileges, it might simply go ahead and unmount the bind mount anyway). Note that both if the file is bind + mounted and if it is copied no further propagation of configuration is generally done after the one-time early + initialization (this is because the file is usually updated through copying and renaming). Defaults to + auto. + + + + + + Configures how /etc/localtime inside of the container (i.e. local timezone + synchronization from host to container) shall be handled. Takes one of off, + copy, bind, symlink, delete or + auto. If set to off the /etc/localtime file in the + container is left as it is included in the image, and neither modified nor bind mounted over. If set to + copy the /etc/localtime file of the host is copied into the + container. Similar, if bind is used, it is bind mounted from the host into the container. If + set to symlink a symlink from /etc/localtime in the container is + created pointing to the matching the timezone file of the container that matches the timezone setting on the + host. If set to delete the file in the container is deleted, should it exist. If set to + auto and the /etc/localtime file of the host is a symlink, then + symlink mode is used, and copy otherwise, except if the image is + read-only in which case bind is used instead. Defaults to + auto. + + + + + + Control whether the container's journal shall + be made visible to the host system. If enabled, allows viewing + the container's journal files from the host (but not vice + versa). Takes one of no, + host, try-host, + guest, try-guest, + auto. If no, the journal + is not linked. If host, the journal files + are stored on the host file system (beneath + /var/log/journal/machine-id) + and the subdirectory is bind-mounted into the container at the + same location. If guest, the journal files + are stored on the guest file system (beneath + /var/log/journal/machine-id) + and the subdirectory is symlinked into the host at the same + location. try-host and + try-guest do the same but do not fail if + the host does not have persistent journaling enabled. If + auto (the default), and the right + subdirectory of /var/log/journal exists, + it will be bind mounted into the container. If the + subdirectory does not exist, no linking is performed. + Effectively, booting a container once with + guest or host will link + the journal persistently if further on the default of + auto is used. + + Note that is the default if the + systemd-nspawn@.service template unit file is used. + + + + + + Equivalent to + . + + + + + + Mount Options + + + + + + + + Bind mount a file or directory from the host into the container. Takes one of: a path + argument — in which case the specified path will be mounted from the host to the same path in the container, or + a colon-separated pair of paths — in which case the first specified path is the source in the host, and the + second path is the destination in the container, or a colon-separated triple of source path, destination path + and mount options. The source path may optionally be prefixed with a + character. If so, the + source path is taken relative to the image's root directory. This permits setting up bind mounts within the + container image. The source path may be specified as empty string, in which case a temporary directory below + the host's /var/tmp directory is used. It is automatically removed when the container is + shut down. Mount options are comma-separated and currently, only and + are allowed, controlling whether to create a recursive or a regular bind + mount. Defaults to "rbind". Backslash escapes are interpreted, so \: may be used to embed + colons in either path. This option may be specified multiple times for creating multiple independent bind + mount points. The option creates read-only bind mounts. + + Note that when this option is used in combination with , the resulting + mount points will be owned by the nobody user. That's because the mount and its files and + directories continue to be owned by the relevant host users and groups, which do not exist in the container, + and thus show up under the wildcard UID 65534 (nobody). If such bind mounts are created, it is recommended to + make them read-only, using . + + + + + + Make the specified path inaccessible in the container. This over-mounts the specified path + (which must exist in the container) with a file node of the same type that is empty and has the most + restrictive access mode supported. This is an effective way to mask files, directories and other file system + objects from the container payload. This option may be used more than once in case all specified paths are + masked. + + + + + + Mount a tmpfs file system into the container. Takes a single absolute path argument that + specifies where to mount the tmpfs instance to (in which case the directory access mode will be chosen as 0755, + owned by root/root), or optionally a colon-separated pair of path and mount option string that is used for + mounting (in which case the kernel default for access mode and owner will be chosen, unless otherwise + specified). Backslash escapes are interpreted in the path, so \: may be used to embed colons + in the path. + + Note that this option cannot be used to replace the root file system of the container with a temporary + file system. However, the option described below provides similar + functionality, with a focus on implementing stateless operating system images. + + + + + + + Combine multiple directory trees into one + overlay file system and mount it into the container. Takes a + list of colon-separated paths to the directory trees to + combine and the destination mount point. + + Backslash escapes are interpreted in the paths, so + \: may be used to embed colons in the paths. + + + If three or more paths are specified, then the last + specified path is the destination mount point in the + container, all paths specified before refer to directory trees + on the host and are combined in the specified order into one + overlay file system. The left-most path is hence the lowest + directory tree, the second-to-last path the highest directory + tree in the stacking order. If + is used instead of , a read-only + overlay file system is created. If a writable overlay file + system is created, all changes made to it are written to the + highest directory tree in the stacking order, i.e. the + second-to-last specified. + + If only two paths are specified, then the second + specified path is used both as the top-level directory tree in + the stacking order as seen from the host, as well as the mount + point for the overlay file system in the container. At least + two paths have to be specified. + + The source paths may optionally be prefixed with + character. If so they are taken + relative to the image's root directory. The uppermost source path may also be specified as empty string, in + which case a temporary directory below the host's /var/tmp is used. The directory is + removed automatically when the container is shut down. This behaviour is useful in order to make read-only + container directories writable while the container is running. For example, use the + --overlay=+/var::/var option in order to automatically overlay a writable temporary + directory on a read-only /var directory. + + For details about overlay file systems, see overlayfs.txt. Note + that the semantics of overlay file systems are substantially + different from normal file systems, in particular regarding + reported device and inode information. Device and inode + information may change for a file while it is being written + to, and processes might see out-of-date versions of files at + times. Note that this switch automatically derives the + workdir= mount option for the overlay file + system from the top-level directory tree, making it a sibling + of it. It is hence essential that the top-level directory tree + is not a mount point itself (since the working directory must + be on the same file system as the top-most directory + tree). Also note that the lowerdir= mount + option receives the paths to stack in the opposite order of + this switch. + + Note that this option cannot be used to replace the root file system of the container with an overlay + file system. However, the option described above provides similar functionality, + with a focus on implementing stateless operating system images. + + + + + Input/Output Options + + + + MODE + + Configures how to set up standard input, output and error output for the container + payload, as well as the /dev/console device for the container. Takes one of + , , , or + . If , a pseudo-TTY is allocated and made available + as /dev/console in the container. It is then bi-directionally connected to the + standard input and output passed to systemd-nspawn. is + similar but only the output of the container is propagated and no input from the caller is read. If + , a pseudo TTY is allocated, but it is not connected anywhere. Finally, in + mode no pseudo TTY is allocated, but the standard input, output and error + output file descriptors passed to systemd-nspawn are passed on — as they are — to + the container payload, see the following paragraph. Defaults to if + systemd-nspawn is invoked from a terminal, and + otherwise. + + In mode, /dev/console will not exist in the + container. This means that the container payload generally cannot be a full init system as init + systems tend to require /dev/console to be available. On the other hand, in this + mode container invocations can be used within shell pipelines. This is because intermediary pseudo + TTYs do not permit independent bidirectional propagation of the end-of-file (EOF) condition, which is + necessary for shell pipelines to work correctly. Note that the mode + should be used carefully, as passing arbitrary file descriptors to less trusted container + payloads might open up unwanted interfaces for access by the container payload. For example, if a + passed file descriptor refers to a TTY of some form, APIs such as TIOCSTI may be + used to synthesize input that might be used for escaping the container. Hence + mode should only be used if the payload is sufficiently trusted or when the standard + input/output/error output file descriptors are known safe, for example pipes. + + + + + + + Equivalent to . + + + + + + + +
+ + + + + Examples + + + Download a + <ulink url="https://getfedora.org">Fedora</ulink> image and start a shell in it + + # machinectl pull-raw --verify=no \ + https://download.fedoraproject.org/pub/fedora/linux/releases/&fedora_latest_version;/Cloud/x86_64/images/Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86_64.raw.xz \ + Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86-64 +# systemd-nspawn -M Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86-64 + + This downloads an image using + machinectl1 + and opens a shell in it. + + + + Build and boot a minimal Fedora distribution in a container + + # dnf -y --releasever=&fedora_latest_version; --installroot=/var/lib/machines/f&fedora_latest_version; \ + --disablerepo='*' --enablerepo=fedora --enablerepo=updates install \ + systemd passwd dnf fedora-release vim-minimal +# systemd-nspawn -bD /var/lib/machines/f&fedora_latest_version; + + This installs a minimal Fedora distribution into the + directory /var/lib/machines/f&fedora_latest_version; + and then boots an OS in a namespace container in it. Because the installation + is located underneath the standard /var/lib/machines/ + directory, it is also possible to start the machine using + systemd-nspawn -M f&fedora_latest_version;. + + + + Spawn a shell in a container of a minimal Debian unstable distribution + + # debootstrap unstable ~/debian-tree/ +# systemd-nspawn -D ~/debian-tree/ + + This installs a minimal Debian unstable distribution into + the directory ~/debian-tree/ and then + spawns a shell in a namespace container in it. + + debootstrap supports + Debian, + Ubuntu, + and Tanglu + out of the box, so the same command can be used to install any of those. For other + distributions from the Debian family, a mirror has to be specified, see + debootstrap8. + + + + + Boot a minimal + <ulink url="https://www.archlinux.org">Arch Linux</ulink> distribution in a container + + # pacstrap -c ~/arch-tree/ base +# systemd-nspawn -bD ~/arch-tree/ + + This installs a minimal Arch Linux distribution into the + directory ~/arch-tree/ and then boots an OS + in a namespace container in it. + + + + Install the + <ulink url="https://software.opensuse.org/distributions/tumbleweed">OpenSUSE Tumbleweed</ulink> + rolling distribution + + # zypper --root=/var/lib/machines/tumbleweed ar -c \ + https://download.opensuse.org/tumbleweed/repo/oss tumbleweed +# zypper --root=/var/lib/machines/tumbleweed refresh +# zypper --root=/var/lib/machines/tumbleweed install --no-recommends \ + systemd shadow zypper openSUSE-release vim +# systemd-nspawn -M tumbleweed passwd root +# systemd-nspawn -M tumbleweed -b + + + + Boot into an ephemeral snapshot of the host system + + # systemd-nspawn -D / -xb + + This runs a copy of the host system in a snapshot which is removed immediately when the container + exits. All file system changes made during runtime will be lost on shutdown, hence. + + + + Run a container with SELinux sandbox security contexts + + # chcon system_u:object_r:svirt_sandbox_file_t:s0:c0,c1 -R /srv/container +# systemd-nspawn -L system_u:object_r:svirt_sandbox_file_t:s0:c0,c1 \ + -Z system_u:system_r:svirt_lxc_net_t:s0:c0,c1 -D /srv/container /bin/sh + + + + Run a container with an OSTree deployment + + # systemd-nspawn -b -i ~/image.raw \ + --pivot-root=/ostree/deploy/$OS/deploy/$CHECKSUM:/sysroot \ + --bind=+/sysroot/ostree/deploy/$OS/var:/var + + + + + Exit status + + The exit code of the program executed in the container is + returned. + + + + See Also + + systemd1, + systemd.nspawn5, + chroot1, + dnf8, + debootstrap8, + pacman8, + zypper8, + systemd.slice5, + machinectl1, + btrfs8 + + + +
diff --git a/man/systemd-path.xml b/man/systemd-path.xml new file mode 100644 index 00000000..91a8786a --- /dev/null +++ b/man/systemd-path.xml @@ -0,0 +1,81 @@ + + + + + + + + systemd-path + systemd + + + + systemd-path + 1 + + + + systemd-path + List and query system and user paths + + + + + systemd-path + OPTIONS + NAME + + + + + Description + + systemd-path may be used to query system + and user paths. The tool makes many of the paths described in + file-hierarchy7 + available for querying. + + When invoked without arguments, a list of known paths and + their current values is shown. When at least one argument is + passed, the path with this name is queried and its value shown. + The variables whose name begins with search- + do not refer to individual paths, but instead to a list of + colon-separated search paths, in their order of precedence. + + + + Options + + The following options are understood: + + + + + + Printed paths are suffixed by the specified string. + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + See Also + + systemd1, + file-hierarchy7 + + + + diff --git a/man/systemd-portabled.service.xml b/man/systemd-portabled.service.xml new file mode 100644 index 00000000..3363a1d9 --- /dev/null +++ b/man/systemd-portabled.service.xml @@ -0,0 +1,50 @@ + + + + + + + + systemd-portabled.service + systemd + + + + systemd-portabled.service + 8 + + + + systemd-portabled.service + systemd-portabled + Portable service manager + + + + systemd-portabled.service + /usr/lib/systemd/systemd-portabled + + + + Description + + systemd-portabled is a system service that may be used to attach, detach and inspect + portable service images. + + Most of systemd-portabled's functionality is accessible through the + portablectl1 command. + + See the Portable + Services Documentation for details about the concepts this service implements. + + + + See Also + + systemd1, + portablectl1 + + + + diff --git a/man/systemd-pstore.xml b/man/systemd-pstore.xml new file mode 100644 index 00000000..dd1aa5e8 --- /dev/null +++ b/man/systemd-pstore.xml @@ -0,0 +1,99 @@ + + + + + + + + systemd-pstore + systemd + + + + systemd-pstore + 8 + + + + systemd-pstore + systemd-pstore.service + Tool to archive contents of the persistent storage filesytem + + + + /usr/lib/systemd/systemd-pstore + systemd-pstore.service + + + + Description + systemd-pstore.service is a system service that archives the + contents of the Linux persistent storage filesystem, pstore, to other storage, + thus preserving the existing information contained in the pstore, and clearing + pstore storage for future error events. + + Linux provides a persistent storage file system, pstore, that can store + error records when the kernel dies (or reboots or powers-off). These records in + turn can be referenced to debug kernel problems (currently the kernel stuffs + the tail of the dmesg, which also contains a stack backtrace, into pstore). + + The pstore file system supports a variety of backends that map onto persistent + storage, such as the ACPI ERST and UEFI variables. The pstore backends + typically offer a relatively small amount of persistent storage, e.g. 64KiB, + which can quickly fill up and thus prevent subsequent kernel crashes from + recording errors. Thus there is a need to monitor and extract the pstore + contents so that future kernel problems can also record information in the + pstore. + + The pstore service is independent of the kdump service. In cloud environments + specifically, host and guest filesystems are on remote filesystems (eg. iSCSI + or NFS), thus kdump relies [implicitly and/or explicitly] upon proper operation + of networking software *and* hardware *and* infrastructure. Thus it may not be + possible to capture a kernel coredump to a file since writes over the network + may not be possible. + + The pstore backend, on the other hand, is completely local and provides a path + to store error records which will survive a reboot and aid in post-mortem + debugging. + + The systemd-pstore executable does the actual work. Upon starting, + the pstore.conf is read to obtain options, then the /sys/fs/pstore + directory contents are processed according to the options. Pstore files are written to the + journal, and optionally saved into /var/lib/systemd/pstore. + + + + Configuration + + The behavior of systemd-pstore is configured through the configuration file + /etc/systemd/pstore.conf and corresponding snippets + /etc/systemd/pstore.conf.d/*.conf, see + pstore.conf5. + + + + Disabling pstore processing + + To disable pstore processing by systemd-pstore, + set Storage=none in + pstore.conf5. + + + + + + Usage + Data stored in the journal can be viewed with + journalctl1 + as usual. + + + + See Also + + pstore.conf5 + + + diff --git a/man/systemd-quotacheck.service.xml b/man/systemd-quotacheck.service.xml new file mode 100644 index 00000000..9ba9f395 --- /dev/null +++ b/man/systemd-quotacheck.service.xml @@ -0,0 +1,69 @@ + + + + + + + + systemd-quotacheck.service + systemd + + + + systemd-quotacheck.service + 8 + + + + systemd-quotacheck.service + systemd-quotacheck + File system quota checker logic + + + + systemd-quotacheck.service + /usr/lib/systemd/systemd-quotacheck + + + + Description + + systemd-quotacheck.service is a service + responsible for file system quota checks. It is run once at boot + after all necessary file systems are mounted. It is pulled in only + if at least one file system has quotas enabled. + + + + Kernel Command Line + + systemd-quotacheck understands one + kernel command line parameter: + + + + quotacheck.mode= + + One of auto, + force, skip. Controls + the mode of operation. The default is auto, + and ensures that file system quota checks are done when the + file system quota checker deems them necessary. + force unconditionally results in full file + system quota checks. skip skips any file + system quota checks. + + + + + + See Also + + systemd1, + quotacheck8, + systemd-fsck@.service8 + + + + diff --git a/man/systemd-random-seed.service.xml b/man/systemd-random-seed.service.xml new file mode 100644 index 00000000..28783a15 --- /dev/null +++ b/man/systemd-random-seed.service.xml @@ -0,0 +1,92 @@ + + + + + + + + systemd-random-seed.service + systemd + + + + systemd-random-seed.service + 8 + + + + systemd-random-seed.service + systemd-random-seed + Load and save the system random seed at boot and shutdown + + + + systemd-random-seed.service + /usr/lib/systemd/random-seed + + + + Description + + systemd-random-seed.service is a service that loads an on-disk random seed + into the kernel entropy pool during boot and saves it at shutdown. See + random4 for + details. By default, no entropy is credited when the random seed is written into the kernel entropy pool, + but this may be changed with $SYSTEMD_RANDOM_SEED_CREDIT, see below. On disk the random + seed is stored in /var/lib/systemd/random-seed. + + Note that this service runs relatively late during the early boot phase, i.e. generally after the + initial RAM disk (initrd) completed its work, and the /var/ file system has been + mounted writable. Many system services require entropy much earlier than this — this service is hence of + limited use for complex system. It is recommended to use a boot loader that can pass an initial random + seed to the kernel to ensure that entropy is available from earliest boot on, for example + systemd-boot7, with + its bootctl random-seed functionality. + + When loading the random seed from disk its file is immediately updated with a new seed retrieved + from the kernel, in order to ensure no two boots operate with the same random seed. This new seed is + retrieved synchronously from the kernel, which means the service will not complete start-up until the + random pool is fully initialized. On entropy-starved systems this may take a while. This functionality is + intended to be used as synchronization point for ordering services that require an initialized entropy + pool to function securely (i.e. services that access /dev/urandom without any + further precautions). + + Care should be taken when creating OS images that are replicated to multiple systems: if the random + seed file is included unmodified each system will initialize its entropy pool with the same data, and + thus — if otherwise entropy-starved — generate the same or at least guessable random seed streams. As a + safety precaution crediting entropy is thus disabled by default. It is recommended to remove the random + seed from OS images intended for replication on multiple systems, in which case it is safe to enable + entropy crediting, see below. + + See Random Seeds for further + information. + + + + Environment + + + + $SYSTEMD_RANDOM_SEED_CREDIT + By default, systemd-random-seed.service does not credit any + entropy when loading the random seed. With this option this behaviour may be changed: it either takes + a boolean parameter or the special string force. Defaults to false, in which case + no entropy is credited. If true, entropy is credited if the random seed file and system state pass + various superficial concisistency checks. If set to force entropy is credited, + regardless of these checks, as long as the random seed file exists. + + + + + + See Also + + systemd1, + random4, + systemd-boot7, + bootctl4 + + + + diff --git a/man/systemd-rc-local-generator.xml b/man/systemd-rc-local-generator.xml new file mode 100644 index 00000000..81744c20 --- /dev/null +++ b/man/systemd-rc-local-generator.xml @@ -0,0 +1,55 @@ + + + + + + + + systemd-rc-local-generator + systemd + + + + systemd-rc-local-generator + 8 + + + + systemd-rc-local-generator + Compatibility generator for starting /etc/rc.local during boot + + + + /usr/lib/systemd/system-generators/systemd-rc-local-generator + + + + Description + + systemd-rc-local-generator is a generator that checks whether + /etc/rc.local exists and is executable, and if it is pulls the + rc-local.service unit into the boot process. This unit is responsible for running this script + during late boot. Note that the script will be run with slightly different semantics than the original System V + version, which was run "last" in the boot process, which is a concept that does not translate to systemd. The + script is run after network.target, but in parallel with most other regular system + services. + + Support for /etc/rc.local is provided + for compatibility with specific System V systems only. However, it is strongly recommended to avoid making use of + this script today, and instead provide proper unit files with appropriate dependencies for any scripts to run + during the boot process. + + systemd-rc-local-generator implements + systemd.generator7. + + + + See Also + + systemd1, + systemctl1 + + + + diff --git a/man/systemd-remount-fs.service.xml b/man/systemd-remount-fs.service.xml new file mode 100644 index 00000000..a744df75 --- /dev/null +++ b/man/systemd-remount-fs.service.xml @@ -0,0 +1,70 @@ + + + + + + + + systemd-remount-fs.service + systemd + + + + systemd-remount-fs.service + 8 + + + + systemd-remount-fs.service + systemd-remount-fs + Remount root and kernel file systems + + + + systemd-remount-fs.service + /usr/lib/systemd/systemd-remount-fs + + + + Description + + systemd-remount-fs.service is an early boot service that applies mount options + listed in fstab5, or + gathered from the partition table (when + systemd-gpt-auto-generator8 + is active) to the root file system, the /usr file system, and the kernel API file + systems. This is required so that the mount options of these file systems — which are pre-mounted by the + kernel, the initial RAM disk, container environments or system manager code — are updated to those + configured in /etc/fstab and the other sources. This service ignores normal file + systems and only changes the root file system (i.e. /), /usr, + and the virtual kernel API file systems such as /proc, /sys or + /dev. This service executes no operation if no configuration is found + (/etc/fstab does not exist or lists no entries for the mentioned file systems, or + the partition table does not contain relevant entries). + + For a longer discussion of kernel API file systems see + API + File Systems. + + Note: systemd-remount-fs.service is usually pulled in by + systemd-fstab-generator8, + hence it is also affected by the kernel command line option fstab=, which may be used + to disable the generator. It may also pulled in by + systemd-gpt-auto-generator8, + which is affected by systemd.gpt_auto and other options. + + + + See Also + + systemd1, + fstab5, + mount8, + systemd-fstab-generator8, + systemd-gpt-auto-generator8 + + + + diff --git a/man/systemd-resolved.service.xml b/man/systemd-resolved.service.xml new file mode 100644 index 00000000..53c46a10 --- /dev/null +++ b/man/systemd-resolved.service.xml @@ -0,0 +1,285 @@ + + + + + + + + systemd-resolved.service + systemd + + + + systemd-resolved.service + 8 + + + + systemd-resolved.service + systemd-resolved + Network Name Resolution manager + + + + systemd-resolved.service + /usr/lib/systemd/systemd-resolved + + + + Description + + systemd-resolved is a system service that provides network name resolution to local + applications. It implements a caching and validating DNS/DNSSEC stub resolver, as well as an LLMNR and MulticastDNS + resolver and responder. Local applications may submit network name resolution requests via three interfaces: + + + The native, fully-featured API systemd-resolved exposes on the bus. See the + API Documentation for + details. Usage of this API is generally recommended to clients as it is asynchronous and fully featured (for + example, properly returns DNSSEC validation status and interface scope for addresses as necessary for supporting + link-local networking). + + The glibc + getaddrinfo3 API as defined + by RFC3493 and its related resolver functions, + including gethostbyname3. This + API is widely supported, including beyond the Linux platform. In its current form it does not expose DNSSEC + validation status information however, and is synchronous only. This API is backed by the glibc Name Service + Switch (nss5). Usage of the + glibc NSS module nss-resolve8 + is required in order to allow glibc's NSS resolver functions to resolve host names via + systemd-resolved. + + Additionally, systemd-resolved provides a local DNS stub listener on IP + address 127.0.0.53 on the local loopback interface. Programs issuing DNS requests directly, bypassing any local + API may be directed to this stub, in order to connect them to systemd-resolved. Note however + that it is strongly recommended that local programs use the glibc NSS or bus APIs instead (as described above), + as various network resolution concepts (such as link-local addressing, or LLMNR Unicode domains) cannot be mapped + to the unicast DNS protocol. + + + The DNS servers contacted are determined from the global settings in + /etc/systemd/resolved.conf, the per-link static settings in + /etc/systemd/network/*.network files (in case + systemd-networkd.service8 is + used), the per-link dynamic settings received over DHCP, user request made via + resolvectl1, and any DNS server + information made available by other system services. See + resolved.conf5 and + systemd.network5 for details + about systemd's own configuration files for DNS servers. To improve compatibility, + /etc/resolv.conf is read in order to discover configured system DNS servers, but only if it is + not a symlink to /run/systemd/resolve/stub-resolv.conf, + /usr/lib/systemd/resolv.conf or /run/systemd/resolve/resolv.conf (see + below). + + + + + Synthetic Records + + systemd-resolved synthesizes DNS resource records (RRs) for the following cases: + + + The local, configured hostname is resolved to + all locally configured IP addresses ordered by their scope, or + — if none are configured — the IPv4 address 127.0.0.2 (which + is on the local loopback) and the IPv6 address ::1 (which is the + local host). + + The hostnames localhost and + localhost.localdomain (as well as any hostname + ending in .localhost or .localhost.localdomain) + are resolved to the IP addresses 127.0.0.1 and ::1. + + The hostname _gateway is + resolved to all current default routing gateway addresses, + ordered by their metric. This assigns a stable hostname to the + current gateway, useful for referencing it independently of the + current network configuration state. + + The mappings defined in /etc/hosts are resolved + to their configured addresses and back, but they will not affect lookups for + non-address types (like MX). + + + + + Protocols and Routing + + Lookup requests are routed to the available DNS servers, LLMNR and MulticastDNS interfaces according to the + following rules: + + + Lookups for the special hostname localhost are never routed to the network. (A + few other, special domains are handled the same way.) + + Single-label names are routed to all local interfaces capable of IP multicasting, using the LLMNR + protocol. Lookups for IPv4 addresses are only sent via LLMNR on IPv4, and lookups for IPv6 addresses are only + sent via LLMNR on IPv6. Lookups for the locally configured host name and the _gateway host + name are never routed to LLMNR. + + Multi-label names with the domain suffix .local are routed to all local + interfaces capable of IP multicasting, using the MulticastDNS protocol. As with LLMNR IPv4 address lookups are + sent via IPv4 and IPv6 address lookups are sent via IPv6. + + Other multi-label names are routed to all local interfaces that have a DNS server configured, + plus the globally configured DNS server if there is one. Address lookups from the link-local address range are + never routed to DNS. Note that by default lookups for domains with the .local suffix are not + routed to DNS servers, unless the domain is specified explicitly as routing or search domain for the DNS server + and interface. This means that on networks where the .local domain is defined in a + site-specific DNS server, explicit search or routing domains need to be configured to make lookups within this + DNS domain work. Note that today it's generally recommended to avoid defining .local in a DNS + server, as RFC6762 reserves this domain for exclusive + MulticastDNS use. + + + If lookups are routed to multiple interfaces, the first + successful response is returned (thus effectively merging the + lookup zones on all matching interfaces). If the lookup failed on + all interfaces, the last failing response is returned. + + Routing of lookups may be influenced by configuring per-interface domain names and other settings. See + systemd.network5 and + resolvectl1 for details. The + following query routing logic applies for unicast DNS traffic: + + + If a name to look up matches (that is: is equal to or has as suffix) any of the configured search + or route-only domains of any link (or the globally configured DNS settings), the "best matching" + search/route-only domain is determined: the matching one with the most labels. The query is then sent to all DNS + servers of any links or the globally configured DNS servers associated with this "best matching" + search/route-only domain. (Note that more than one link might have this same "best matching" search/route-only + domain configured, in which case the query is sent to all of them in parallel). + + If a query does not match any configured search/route-only domain (neither per-link nor global), + it is sent to all DNS servers that are configured on links with the "DNS default route" option set, as well as + the globally configured DNS server. + + If there is no link configured as "DNS default route" and no global DNS server configured, the + compiled-in fallback DNS server is used. + + Otherwise the query is failed as no suitable DNS servers could be determined. + + + The "DNS default route" option is a boolean setting configurable with resolvectl or in + .network files. If not set, it is implicitly determined based on the configured DNS domains + for a link: if there's any route-only domain (not matching ~.) it defaults to false, otherwise + to true. + + Effectively this means: in order to preferably route all DNS queries not explicitly matched by + search/route-only domain configuration to a specific link, configure a ~. route-only domain on + it. This will ensure that other links will not be considered for the queries (unless they too carry such a + route-only domain). In order to route all such DNS queries to a specific link only in case no other link is + preferable, then set the "DNS default route" option for the link to true, and do not configure a + ~. route-only domain on it. Finally, in order to ensure that a specific link never receives any + DNS traffic not matching any of its configured search/route-only domains, set the "DNS default route" option for it + to false. + + See the resolved D-Bus API + Documentation for information about the APIs systemd-resolved provides. + + + + <filename>/etc/resolv.conf</filename> + + Four modes of handling /etc/resolv.conf (see + resolv.conf5) are + supported: + + + systemd-resolved maintains the + /run/systemd/resolve/stub-resolv.conf file for compatibility with traditional Linux + programs. This file may be symlinked from /etc/resolv.conf. This file lists the 127.0.0.53 + DNS stub (see above) as the only DNS server. It also contains a list of search domains that are in use by + systemd-resolved. The list of search domains is always kept up-to-date. Note that + /run/systemd/resolve/stub-resolv.conf should not be used directly by applications, but only + through a symlink from /etc/resolv.conf. This file may be symlinked from + /etc/resolv.conf in order to connect all local clients that bypass local DNS APIs to + systemd-resolved with correct search domains settings. This mode of operation is + recommended. + + A static file /usr/lib/systemd/resolv.conf is provided that lists + the 127.0.0.53 DNS stub (see above) as only DNS server. This file may be symlinked from + /etc/resolv.conf in order to connect all local clients that bypass local DNS APIs to + systemd-resolved. This file does not contain any search domains. + + systemd-resolved maintains the + /run/systemd/resolve/resolv.conf file for compatibility with traditional Linux + programs. This file may be symlinked from /etc/resolv.conf and is always kept up-to-date, + containing information about all known DNS servers. Note the file format's limitations: it does not know a + concept of per-interface DNS servers and hence only contains system-wide DNS server definitions. Note that + /run/systemd/resolve/resolv.conf should not be used directly by applications, but only + through a symlink from /etc/resolv.conf. If this mode of operation is used local clients + that bypass any local DNS API will also bypass systemd-resolved and will talk directly to the + known DNS servers. + + Alternatively, /etc/resolv.conf may be managed by other packages, in which + case systemd-resolved will read it for DNS configuration data. In this mode of operation + systemd-resolved is consumer rather than provider of this configuration + file. + + + Note that the selected mode of operation for this file is detected fully automatically, depending on whether + /etc/resolv.conf is a symlink to /run/systemd/resolve/resolv.conf or + lists 127.0.0.53 as DNS server. + + + + Signals + + + + SIGUSR1 + + Upon reception of the SIGUSR1 process signal + systemd-resolved will dump the contents of all DNS resource record caches it maintains, as + well as all feature level information it learnt about configured DNS servers into the system + logs. + + + + SIGUSR2 + + Upon reception of the SIGUSR2 process signal + systemd-resolved will flush all caches it maintains. Note that it should normally not be + necessary to request this explicitly – except for debugging purposes – as systemd-resolved + flushes the caches automatically anyway any time the host's network configuration changes. Sending this signal + to systemd-resolved is equivalent to the resolvectl flush-caches + command, however the latter is recommended since it operates in a synchronous way. + + + + SIGRTMIN+1 + + Upon reception of the SIGRTMIN+1 process signal + systemd-resolved will forget everything it learnt about the configured DNS + servers. Specifically any information about server feature support is flushed out, and the server feature + probing logic is restarted on the next request, starting with the most fully featured level. Note that it + should normally not be necessary to request this explicitly – except for debugging purposes – as + systemd-resolved automatically forgets learnt information any time the DNS server + configuration changes. Sending this signal to systemd-resolved is equivalent to the + resolvectl reset-server-features command, however the latter is recommended since it + operates in a synchronous way. + + + + + + + See Also + + systemd1, + resolved.conf5, + dnssec-trust-anchors.d5, + nss-resolve8, + resolvectl1, + resolv.conf5, + hosts5, + systemd.network5, + systemd-networkd.service8 + + + + diff --git a/man/systemd-rfkill.service.xml b/man/systemd-rfkill.service.xml new file mode 100644 index 00000000..bc3322cf --- /dev/null +++ b/man/systemd-rfkill.service.xml @@ -0,0 +1,65 @@ + + + + + + + + systemd-rfkill.service + systemd + + + + systemd-rfkill.service + 8 + + + + systemd-rfkill.service + systemd-rfkill.socket + systemd-rfkill + Load and save the RF kill switch state at boot and change + + + + systemd-rfkill.service + systemd-rfkill.socket + /usr/lib/systemd/systemd-rfkill + + + + Description + + systemd-rfkill.service is a service + that restores the RF kill switch state at early boot and saves it + on each change. On disk, the RF kill switch state is stored in + /var/lib/systemd/rfkill/. + + + + Kernel Command Line + + systemd-rfkill understands the + following kernel command line parameter: + + + + systemd.restore_state= + + Takes a boolean argument. Defaults to + 1. If 0, does not + restore the rfkill settings on boot. However, settings will + still be stored on shutdown. + + + + + + See Also + + systemd1 + + + + diff --git a/man/systemd-run-generator.xml b/man/systemd-run-generator.xml new file mode 100644 index 00000000..db84cf73 --- /dev/null +++ b/man/systemd-run-generator.xml @@ -0,0 +1,81 @@ + + + + + + + + systemd-run-generator + systemd + + + + systemd-run-generator + 8 + + + + systemd-run-generator + Generator for invoking commands specified on the kernel command line as system service + + + + /usr/lib/systemd/system-generators/systemd-run-generator + + + + Description + + systemd-run-generator is a generator + that reads the kernel command line and understands three + options: + + If the option is specified and followed by a command line, a unit named + kernel-command-line.service is generated for it and booted into. The service has + Type=oneshot set, and has SuccessAction=exit and + FailureAction=exit configured by default, thus ensuring that the system is shut down as soon as + the command completes. The exit status of the command line is propagated to the invoking container manager, if + this applies (which might propagate this further, to the calling shell — e.g. + systemd-nspawn7 does this). If + this option is used multiple times the unit file will contain multiple ExecStart= lines, to + execute all commands in order. The command is started as regular service, i.e. with + DefaultDependencies= on. + + Use and to tweak + how to react to the process completing. In particular assigning none will leave the system + running after the command completes. For further details on supported arguments, see + systemd.unit5. + + systemd-run-generator implements + systemd.generator7. + + + + Example + + Use a command like the following to add a user to the user database inside a container run with + systemd-nspawn7: + + # systemd-nspawn -D mycontainer -b systemd.run='"adduser test"' + (Note the requirement for double quoting in the command line above. The first level of quoting ('') is + processed and removed by the command shell used to invoke systemd-nspawn. The second level of + quoting ("") is propagated to the kernel command line of the container and processed and removed by + systemd-run-generator. Both together make sure both words of the specified command line + adduser test end up in the generated unit file together and are neither split apart by the + command shell nor by the generator.) + + + + See Also + + systemd1, + systemctl1, + kernel-command-line7, + systemd-nspawn7, + systemd.unit5, + systemd.service5 + + + + diff --git a/man/systemd-run.xml b/man/systemd-run.xml new file mode 100644 index 00000000..3a1d18da --- /dev/null +++ b/man/systemd-run.xml @@ -0,0 +1,540 @@ + + + + + + + + systemd-run + systemd + + + + systemd-run + 1 + + + + systemd-run + Run programs in transient scope units, service units, or path-, socket-, or timer-triggered service units + + + + + systemd-run + OPTIONS + COMMAND + ARGS + + + + systemd-run + OPTIONS + PATH OPTIONS + COMMAND + ARGS + + + systemd-run + OPTIONS + SOCKET OPTIONS + COMMAND + ARGS + + + systemd-run + OPTIONS + TIMER OPTIONS + COMMAND + ARGS + + + + + Description + + systemd-run may be used to create and start a transient .service or + .scope unit and run the specified COMMAND in it. It may also be + used to create and start a transient .path, .socket, or + .timer unit, that activates a .service unit when elapsing. + + If a command is run as transient service unit, it will be started and managed by the service manager like any + other service, and thus shows up in the output of systemctl list-units like any other unit. It + will run in a clean and detached execution environment, with the service manager as its parent process. In this + mode, systemd-run will start the service asynchronously in the background and return after the + command has begun execution (unless or are specified, see + below). + + If a command is run as transient scope unit, it will be executed by systemd-run itself as + parent process and will thus inherit the execution environment of the caller. However, the processes of the command + are managed by the service manager similar to normal services, and will show up in the output of systemctl + list-units. Execution in this case is synchronous, and will return only when the command finishes. This + mode is enabled via the switch (see below). + + If a command is run with path, socket, or timer options such as (see below), + a transient path, socket, or timer unit is created alongside the service unit for the specified command. Only the + transient path, socket, or timer unit is started immediately, the transient service unit will be triggered by the + path, socket, or timer unit. If the option is specified, the + COMMAND may be omitted. In this case, systemd-run creates only a + .path, .socket, or .timer unit that triggers the + specified unit. + + By default, services created with systemd-run default to the type, + see the description of Type= in + systemd.service5 for + details. Note that when this type is used the service manager (and thus the systemd-run command) + considers service start-up successful as soon as the fork() for the main service process + succeeded, i.e. before the execve() is invoked, and thus even if the specified command cannot + be started. Consider using the service type (i.e. ) to + ensure that systemd-run returns successfully only if the specified command line has been + successfully started. + + + + Options + + The following options are understood: + + + + + + Do not query the user for authentication for + privileged operations. + + + + + + + Create a transient .scope unit instead of the default transient + .service unit (see above). + + + + + + + + + Use this unit name instead of an automatically + generated one. + + + + + + + Sets a property on the scope or service unit that is created. This option takes an assignment + in the same format as + systemctl1's + set-property command. + + + + + + + Provide a description for the service, scope, path, socket, or timer unit. If not specified, + the command itself will be used as a description. See Description= in + systemd.unit5. + + + + + + + Make the new .service or .scope unit part of the + specified slice, instead of system.slice. + + + + + + + + After the service process has terminated, keep the service around until it is explicitly + stopped. This is useful to collect runtime information about the service after it finished running. Also see + RemainAfterExit= in + systemd.service5. + + + + + + + + When terminating the scope or service unit, send a SIGHUP immediately after SIGTERM. This is + useful to indicate to shells and shell-like processes that the connection has been severed. Also see + SendSIGHUP= in + systemd.kill5. + + + + + + + + Sets the service type. Also see + Type= in + systemd.service5. This + option has no effect in conjunction with + . Defaults to + simple. + + + + + + + + Runs the service process under the specified UNIX user and group. Also see + User= and Group= in + systemd.exec5. + + + + + + + Runs the service process with the specified + nice level. Also see Nice= in + systemd.exec5. + + + + + + + Runs the service process with the specified working directory. Also see + WorkingDirectory= in + systemd.exec5. + + + + + + + + Similar to but uses the current working directory of the + caller for the service to execute. + + + + + + + Runs the service process with the specified environment variable set. + Also see Environment= in + systemd.exec5. + + + + + + + + When invoking the command, the transient service connects its standard input, output and error + to the terminal systemd-run is invoked on, via a pseudo TTY device. This allows running + programs that expect interactive user input/output as services, such as interactive command shells. + + Note that + machinectl1's + shell command is usually a better alternative for requesting a new, interactive login + session on the local host or a local container. + + See below for details on how this switch combines with . + + + + + + + If specified, standard input, output, and error of the transient service are inherited from the + systemd-run command itself. This allows systemd-run + to be used within shell pipelines. + Note that this mode is not suitable for interactive command shells and similar, as the + service process will not become a TTY controller when invoked on a terminal. Use instead + in that case. + + When both and are used in combination the more appropriate + option is automatically determined and used. Specifically, when invoked with standard input, output and error + connected to a TTY is used, and otherwise . + + When this option is used the original file descriptors systemd-run receives are passed + to the service processes as-is. If the service runs with different privileges than + systemd-run, this means the service might not be able to re-open the passed file + descriptors, due to normal file descriptor access restrictions. If the invoked process is a shell script that + uses the echo "hello" > /dev/stderr construct for writing messages to stderr, this might + cause problems, as this only works if stderr can be re-opened. To mitigate this use the construct echo + "hello" >&2 instead, which is mostly equivalent and avoids this pitfall. + + + + + + + A shortcut for --pty --same-dir --wait --collect --service-type=exec $SHELL, + i.e. requests an interactive shell in the current working directory, running in service context, accessible + with a single switch. + + + + + + + Suppresses additional informational output + while running. This is particularly useful in combination with + when it will suppress the initial + message explaining how to terminate the TTY connection. + + + + + + + + + + Defines a monotonic timer relative to different starting points for starting the specified + command. See OnActiveSec=, OnBootSec=, OnStartupSec=, + OnUnitActiveSec= and OnUnitInactiveSec= in + systemd.timer5 for + details. These options are shortcuts for --timer-property= with the relevant properties. + These options may not be combined with or . + + + + + + + Defines a calendar timer for starting the specified command. See OnCalendar= + in systemd.timer5. This + option is a shortcut for --timer-property=OnCalendar=. This option may not be combined with + or . + + + + + + + + Defines a trigger based on system clock jumps or timezone changes for starting the + specified command. See OnClockChange= and OnTimezoneChange= in + systemd.timer5. These + options are shortcuts for --timer-property=OnClockChange=yes and + --timer-property=OnTimezoneChange=yes. These options may not be combined with + or . + + + + + + + + Sets a property on the path, socket, or timer unit that is created. This option is similar to + but applies to the transient path, socket, or timer unit rather than the + transient service unit created. This option takes an assignment in the same format as + systemctl1's + set-property command. These options may not be combined with + or . + + + + + + + + Do not synchronously wait for the unit start operation to finish. If this option is not specified, the + start request for the transient unit will be verified, enqueued and systemd-run will wait + until the unit's start-up is completed. By passing this argument, it is only verified and enqueued. This + option may not be combined with . + + + + + + + Synchronously wait for the transient service to terminate. If this option is specified, the + start request for the transient unit is verified, enqueued, and waited for. Subsequently the invoked unit is + monitored, and it is waited until it is deactivated again (most likely because the specified command + completed). On exit, terse information about the unit's runtime is shown, including total runtime (as well as + CPU usage, if was set) and the exit code and status of the main + process. This output may be suppressed with . This option may not be combined with + , or the various path, socket, or timer options. + + + + + + + Unload the transient unit after it completed, even if it failed. Normally, without this option, + all units that ran and failed are kept in memory until the user explicitly resets their failure state with + systemctl reset-failed or an equivalent command. On the other hand, units that ran + successfully are unloaded immediately. If this option is turned on the "garbage collection" of units is more + aggressive, and unloads units regardless if they exited successfully or failed. This option is a shortcut for + --property=CollectMode=inactive-or-failed, see the explanation for + CollectMode= in + systemd.unit5 for further + information. + + + + + + + + + + + + All command line arguments after the first non-option + argument become part of the command line of the launched + process. If a command is run as service unit, the first argument + needs to be an absolute program path. + + + + Exit status + + On success, 0 is returned. If systemd-run failed to start the service, a + non-zero return value will be returned. If systemd-run waits for the service to + terminate, the return value will be propagated from the service. 0 will be returned on success, including + all the cases where systemd considers a service to have exited cleanly, see the discussion of + SuccessExitStatus= in + systemd.service5. + + + + + Examples + + + Logging environment variables provided by systemd to services + + # systemd-run env +Running as unit: run-19945.service +# journalctl -u run-19945.service +Sep 08 07:37:21 bupkis systemd[1]: Starting /usr/bin/env... +Sep 08 07:37:21 bupkis systemd[1]: Started /usr/bin/env. +Sep 08 07:37:21 bupkis env[19948]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin +Sep 08 07:37:21 bupkis env[19948]: LANG=en_US.UTF-8 +Sep 08 07:37:21 bupkis env[19948]: BOOT_IMAGE=/vmlinuz-3.11.0-0.rc5.git6.2.fc20.x86_64 + + + + Limiting resources available to a command + + # systemd-run -p BlockIOWeight=10 updatedb + + This command invokes the + updatedb8 + tool, but lowers the block I/O weight for it to 10. See + systemd.resource-control5 + for more information on the BlockIOWeight= + property. + + + + Running commands at a specified time + + The following command will touch a file after 30 seconds. + + # date; systemd-run --on-active=30 --timer-property=AccuracySec=100ms /bin/touch /tmp/foo +Mon Dec 8 20:44:24 KST 2014 +Running as unit: run-71.timer +Will run service as unit: run-71.service +# journalctl -b -u run-71.timer +-- Logs begin at Fri 2014-12-05 19:09:21 KST, end at Mon 2014-12-08 20:44:54 KST. -- +Dec 08 20:44:38 container systemd[1]: Starting /bin/touch /tmp/foo. +Dec 08 20:44:38 container systemd[1]: Started /bin/touch /tmp/foo. +# journalctl -b -u run-71.service +-- Logs begin at Fri 2014-12-05 19:09:21 KST, end at Mon 2014-12-08 20:44:54 KST. -- +Dec 08 20:44:48 container systemd[1]: Starting /bin/touch /tmp/foo... +Dec 08 20:44:48 container systemd[1]: Started /bin/touch /tmp/foo. + + + + Allowing access to the tty + + The following command invokes /bin/bash as a service + passing its standard input, output and error to the calling TTY. + + # systemd-run -t --send-sighup /bin/bash + + + + Start <command>screen</command> as a user service + + $ systemd-run --scope --user screen +Running scope as unit run-r14b0047ab6df45bfb45e7786cc839e76.scope. + +$ screen -ls +There is a screen on: + 492..laptop (Detached) +1 Socket in /var/run/screen/S-fatima. + + + This starts the screen process as a child of the + systemd --user process that was started by + user@.service, in a scope unit. A + systemd.scope5 + unit is used instead of a + systemd.service5 + unit, because screen will exit when detaching from the terminal, + and a service unit would be terminated. Running screen + as a user unit has the advantage that it is not part of the session scope. + If KillUserProcesses=yes is configured in + logind.conf5, + the default, the session scope will be terminated when the user logs + out of that session. + + The user@.service is started automatically + when the user first logs in, and stays around as long as at least one + login session is open. After the user logs out of the last session, + user@.service and all services underneath it + are terminated. This behavior is the default, when "lingering" is + not enabled for that user. Enabling lingering means that + user@.service is started automatically during + boot, even if the user is not logged in, and that the service is + not terminated when the user logs out. + + Enabling lingering allows the user to run processes without being logged in, + for example to allow screen to persist after the user logs out, + even if the session scope is terminated. In the default configuration, users can + enable lingering for themselves: + + $ loginctl enable-linger + + + + Return value + + $ systemd-run --user --wait true +$ systemd-run --user --wait -p SuccessExitStatus=11 bash -c 'exit 11' +$ systemd-run --user --wait -p SuccessExitStatus=SIGUSR1 bash -c 'kill -SIGUSR1 $$$$' + + Those three invocations will succeed, i.e. terminate with an exit code of 0. + + + + + See Also + + systemd1, + systemctl1, + systemd.unit5, + systemd.service5, + systemd.scope5, + systemd.slice5, + systemd.exec5, + systemd.resource-control5, + systemd.timer5, + systemd-mount1, + machinectl1 + + + + diff --git a/man/systemd-sleep.conf.xml b/man/systemd-sleep.conf.xml new file mode 100644 index 00000000..a6949b0c --- /dev/null +++ b/man/systemd-sleep.conf.xml @@ -0,0 +1,202 @@ + + + + + + + systemd-sleep.conf + systemd + + + + systemd-sleep.conf + 5 + + + + systemd-sleep.conf + sleep.conf.d + Suspend and hibernation configuration file + + + + /etc/systemd/sleep.conf + /etc/systemd/sleep.conf.d/*.conf + /run/systemd/sleep.conf.d/*.conf + /usr/lib/systemd/sleep.conf.d/*.conf + + + + Description + + systemd supports four general + power-saving modes: + + + + suspend + + a low-power state + where execution of the OS is paused, + and complete power loss might result + in lost data, and which is fast to + enter and exit. This corresponds to + suspend, standby, or freeze states as + understood by the kernel. + + + + + hibernate + + a low-power state + where execution of the OS is paused, + and complete power loss does not + result in lost data, and which might + be slow to enter and exit. This + corresponds to the hibernation as + understood by the kernel. + + + + + hybrid-sleep + + a low-power state + where execution of the OS is paused, + which might be slow to enter, and on + complete power loss does not result in + lost data but might be slower to exit + in that case. This mode is called + suspend-to-both by the kernel. + + + + + suspend-then-hibernate + + A low power state where the system is initially suspended + (the state is stored in RAM). If not interrupted within the delay specified by + HibernateDelaySec=, the system will be woken using an RTC + alarm and hibernated (the state is then stored on disk). + + + + + + Settings in these files determine what strings + will be written to + /sys/power/disk and + /sys/power/state by + systemd-sleep8 + when + systemd1 + attempts to suspend or hibernate the machine. + See + systemd.syntax5 + for a general description of the syntax. + + + + + + Options + + The following options can be configured in the + [Sleep] section of + /etc/systemd/sleep.conf or a + sleep.conf.d file: + + + + AllowSuspend= + AllowHibernation= + AllowSuspendThenHibernate= + AllowHybridSleep= + + By default any power-saving mode is advertised if possible (i.e. + the kernel supports that mode, the necessary resources are available). Those + switches can be used to disable specific modes. + + If AllowHibernation=no or AllowSuspend=no is + used, this implies AllowSuspendThenHibernate=no and + AllowHybridSleep=no, since those methods use both suspend and hibernation + internally. AllowSuspendThenHibernate=yes and + AllowHybridSleep=yes can be used to override and enable those specific + modes. + + + + SuspendMode= + HibernateMode= + HybridSleepMode= + + The string to be written to + /sys/power/disk by, + respectively, + systemd-suspend.service8, + systemd-hibernate.service8, + systemd-hybrid-sleep.service8, or + systemd-suspend-then-hibernate.service8. + More than one value can be specified by separating + multiple values with whitespace. They will be tried + in turn, until one is written without error. If + neither succeeds, the operation will be aborted. + + + + + SuspendState= + HibernateState= + HybridSleepState= + + The string to be written to + /sys/power/state by, + respectively, + systemd-suspend.service8, + systemd-hibernate.service8, + systemd-hybrid-sleep.service8, or + systemd-suspend-then-hibernate.service8. + More than one value can be specified by separating + multiple values with whitespace. They will be tried + in turn, until one is written without error. If + neither succeeds, the operation will be aborted. + + + + HibernateDelaySec= + + The amount of time the system spends in suspend mode before the system is + automatically put into hibernate mode, when using + systemd-suspend-then-hibernate.service8. Defaults + to 2h. + + + + + + Example: freeze + + Example: to exploit the freeze mode added + in Linux 3.9, one can use systemctl suspend + with + [Sleep] +SuspendState=freeze + + + + See Also + + systemd-sleep8, + systemd-suspend.service8, + systemd-hibernate.service8, + systemd-hybrid-sleep.service8, + systemd-suspend-then-hibernate.service8, + systemd1, + systemd.directives7 + + + + diff --git a/man/systemd-socket-activate.xml b/man/systemd-socket-activate.xml new file mode 100644 index 00000000..f3dbb47a --- /dev/null +++ b/man/systemd-socket-activate.xml @@ -0,0 +1,181 @@ + + + + + + + + systemd-socket-activate + systemd + + + + systemd-socket-activate + 1 + + + + systemd-socket-activate + Test socket activation of daemons + + + + + systemd-socket-activate + OPTIONS + daemon + OPTIONS + + + + + Description + + systemd-socket-activate may be used to launch a socket-activated service program from the + command line for testing purposes. It may also be used to launch individual instances of the service program per + connection. + + + The daemon to launch and its options should be specified + after options intended for systemd-socket-activate. + + + If the option is given, the socket file descriptor will be used as the standard + input and output of the launched process. Otherwise, standard input and output will be inherited, and sockets will + be passed through file descriptors 3 and higher. Sockets passed through $LISTEN_FDS to + systemd-socket-activate will be passed through to the daemon, in the original positions. Other sockets + specified with will use consecutive descriptors. By default, + systemd-socket-activate listens on a stream socket, use and + to listen on datagram or sequential packet sockets instead (see below). + + + + + Options + + + + + + Listen on this address. + Takes a string like 2000 or + 127.0.0.1:2001. + + + + + + + + Launch an instance of the service program for each connection and pass the connection + socket. + + + + + + + Listen on a datagram socket (SOCK_DGRAM), instead of a stream socket + (SOCK_STREAM). May not be combined with . + + + + + + Listen on a sequential packet socket (SOCK_SEQPACKET), instead of a stream + socket (SOCK_STREAM). May not be combined with + . + + + + + + Use the inetd protocol for passing file descriptors, i.e. as standard input and standard + output, instead of the new-style protocol for passing file descriptors using $LISTEN_FDS + (see above). + + + + + + + Add this variable to the environment of the + launched process. If VAR is + followed by =, assume that it is a + variable–value pair. Otherwise, obtain the value from the + environment of systemd-socket-activate itself. + + + + + NAME:NAME… + + Specify names for the file descriptors passed. This is equivalent to setting + FileDescriptorName= in socket unit files, and enables use of + sd_listen_fds_with_names3. + Multiple entries may be specifies using separate options or by separating names with colons + (:) in one option. In case more names are given than descriptors, superfluous ones will be + ignored. In case less names are given than descriptors, the remaining file descriptors will be unnamed. + + + + + + + + + + Environment variables + + + $LISTEN_FDS + $LISTEN_PID + $LISTEN_FDNAMES + + See + sd_listen_fds3. + + + + $SYSTEMD_LOG_TARGET + $SYSTEMD_LOG_LEVEL + $SYSTEMD_LOG_COLOR + $SYSTEMD_LOG_LOCATION + + Same as in + systemd1. + + + + + + Examples + + + Run an echo server on port 2000 + + $ systemd-socket-activate -l 2000 --inetd -a cat + + + + Run a socket-activated instance of <citerefentry><refentrytitle>systemd-journal-gatewayd</refentrytitle><manvolnum>8</manvolnum></citerefentry> + + $ systemd-socket-activate -l 19531 /usr/lib/systemd/systemd-journal-gatewayd + + + + + See Also + + systemd1, + systemd.socket5, + systemd.service5, + systemd-run1, + sd_listen_fds3, + sd_listen_fds_with_names3, + cat1 + + + diff --git a/man/systemd-socket-proxyd.xml b/man/systemd-socket-proxyd.xml new file mode 100644 index 00000000..a72ac1bb --- /dev/null +++ b/man/systemd-socket-proxyd.xml @@ -0,0 +1,174 @@ + + + + + + + + systemd-socket-proxyd + systemd + + + systemd-socket-proxyd + 8 + + + systemd-socket-proxyd + Bidirectionally proxy local sockets to another (possibly remote) socket. + + + + systemd-socket-proxyd + OPTIONS + HOST:PORT + + + systemd-socket-proxyd + OPTIONS + UNIX-DOMAIN-SOCKET-PATH + + + + + Description + + systemd-socket-proxyd is a generic + socket-activated network socket forwarder proxy daemon for IPv4, + IPv6 and UNIX stream sockets. It may be used to bi-directionally + forward traffic from a local listening socket to a local or remote + destination socket. + + One use of this tool is to provide socket activation support + for services that do not natively support socket activation. On + behalf of the service to activate, the proxy inherits the socket + from systemd, accepts each client connection, opens a connection + to a configured server for each client, and then bidirectionally + forwards data between the two. + This utility's behavior is similar to + socat1. + The main differences for systemd-socket-proxyd + are support for socket activation with + Accept=no and an event-driven + design that scales better with the number of + connections. + + + Options + The following options are understood: + + + + + + + + Sets the maximum number of simultaneous connections, defaults to 256. + If the limit of concurrent connections is reached further connections will be refused. + + + + + Exit status + On success, 0 is returned, a non-zero failure + code otherwise. + + + Examples + + Simple Example + Use two services with a dependency and no namespace + isolation. + + proxy-to-nginx.socket + + + + proxy-to-nginx.service + + + + nginx.conf + + + + + + Enabling the proxy + + + + + Namespace Example + Similar as above, but runs the socket proxy and the main + service in the same private namespace, assuming that + nginx.service has + PrivateTmp= and + PrivateNetwork= set, too. + + proxy-to-nginx.socket + + + + proxy-to-nginx.service + + + + nginx.conf + + + + Enabling the proxy + + + + + + See Also + + systemd1, + systemd.socket5, + systemd.service5, + systemctl1, + socat1, + nginx1, + curl1 + + + diff --git a/man/systemd-suspend.service.xml b/man/systemd-suspend.service.xml new file mode 100644 index 00000000..2310e6f5 --- /dev/null +++ b/man/systemd-suspend.service.xml @@ -0,0 +1,127 @@ + + + + + + + + systemd-suspend.service + systemd + + + + systemd-suspend.service + 8 + + + + systemd-suspend.service + systemd-hibernate.service + systemd-hybrid-sleep.service + systemd-suspend-then-hibernate.service + systemd-sleep + System sleep state logic + + + + systemd-suspend.service + systemd-hibernate.service + systemd-hybrid-sleep.service + systemd-suspend-then-hibernate.service + /usr/lib/systemd/system-sleep + + + + Description + + systemd-suspend.service is a system + service that is pulled in by suspend.target + and is responsible for the actual system suspend. Similarly, + systemd-hibernate.service is pulled in by + hibernate.target to execute the actual + hibernation. Finally, + systemd-hybrid-sleep.service is pulled in by + hybrid-sleep.target to execute hybrid + hibernation with system suspend and pulled in by + suspend-then-hibernate.target to execute system suspend + with a timeout that will activate hibernate later. + + Immediately before entering system suspend and/or + hibernation systemd-suspend.service (and the + other mentioned units, respectively) will run all executables in + /usr/lib/systemd/system-sleep/ and pass two + arguments to them. The first argument will be + pre, the second either + suspend, hibernate, + hybrid-sleep, or suspend-then-hibernate + depending on the chosen action. + Immediately after leaving system suspend and/or hibernation the + same executables are run, but the first argument is now + post. All executables in this directory are + executed in parallel, and execution of the action is not continued + until all executables have finished. + + Note that scripts or binaries dropped in + /usr/lib/systemd/system-sleep/ are intended + for local use only and should be considered hacks. If applications + want to react to system suspend/hibernation and resume, + they should rather use the Inhibitor + interface. + + Note that + systemd-suspend.service, + systemd-hibernate.service, and + systemd-hybrid-sleep.service + systemd-suspend-then-hibernate.service + should never be executed directly. Instead, trigger system sleep + states with a command such as systemctl suspend + or similar. + + Internally, this service will echo a string like + mem into /sys/power/state, + to trigger the actual system suspend. What exactly is written + where can be configured in the [Sleep] section + of /etc/systemd/sleep.conf or a + sleep.conf.d file. See + systemd-sleep.conf5. + + + + + Options + + systemd-sleep understands the + following commands: + + + + + + + + + + + + Suspend, hibernate, suspend then hibernate, or put the + system to hybrid sleep. + + + + + + + See Also + + systemd-sleep.conf5, + systemd1, + systemctl1, + systemd.special7, + systemd-halt.service8 + + + + diff --git a/man/systemd-sysctl.service.xml b/man/systemd-sysctl.service.xml new file mode 100644 index 00000000..7b04f4b7 --- /dev/null +++ b/man/systemd-sysctl.service.xml @@ -0,0 +1,129 @@ + + + + + + + + systemd-sysctl.service + systemd + + + + systemd-sysctl.service + 8 + + + + systemd-sysctl.service + systemd-sysctl + Configure kernel parameters at boot + + + + + /usr/lib/systemd/systemd-sysctl + OPTIONS + CONFIGFILE + + systemd-sysctl.service + + + + Description + + systemd-sysctl.service is an early boot + service that configures + sysctl8 + kernel parameters by invoking /usr/lib/systemd/systemd-sysctl. + + When invoked with no arguments, /usr/lib/systemd/systemd-sysctl applies + all directives from configuration files listed in + sysctl.d5. + If one or more filenames are passed on the command line, only the directives in these files are + applied. + + In addition, option may be used to limit which sysctl + settings are applied. + + See + sysctl.d5 + for information about the configuration of sysctl settings. After sysctl configuration is + changed on disk, it must be written to the files in /proc/sys before it + takes effect. It is possible to update specific settings, or simply to reload all configuration, + see Examples below. + + + Options + + + + + Only apply rules with the specified prefix. + + + + + + + + + + + + + Examples + + + Reset all sysctl settings + + systemctl restart systemd-sysctl + + + + View coredump handler configuration + + # sysctl kernel.core_pattern +kernel.core_pattern = |/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t %P %I + + + + + Update coredump handler configuration + + # /usr/lib/systemd/systemd-sysctl --prefix kernel.core_pattern + + This searches all the directories listed in + sysctl.d5 + for configuration files and writes /proc/sys/kernel/core_pattern. + + + + Update coredump handler configuration according to a specific file + + # /usr/lib/systemd/systemd-sysctl 50-coredump.conf + + This applies all the settings found in 50-coredump.conf. + Either /etc/sysctl.d/50-coredump.conf, or + /run/sysctl.d/50-coredump.conf, or + /usr/lib/sysctl.d/50-coredump.conf will be used, in the order + of preference. + + + See + sysctl8 + for various ways to directly apply sysctl settings. + + + + See Also + + systemd1, + sysctl.d5, + sysctl8, + + + + diff --git a/man/systemd-system-update-generator.xml b/man/systemd-system-update-generator.xml new file mode 100644 index 00000000..d816c0b2 --- /dev/null +++ b/man/systemd-system-update-generator.xml @@ -0,0 +1,50 @@ + + + + + + + + systemd-system-update-generator + systemd + + + + systemd-system-update-generator + 8 + + + + systemd-system-update-generator + Generator for redirecting boot to offline update mode + + + + /usr/lib/systemd/system-generators/systemd-system-update-generator + + + + Description + + systemd-system-update-generator is a + generator that automatically redirects the boot process to + system-update.target, if + /system-update exists. This is required to + implement the logic explained in the + systemd.offline-updates7. + + + systemd-system-update-generator implements + systemd.generator7. + + + + See Also + + systemd1, + systemd.special7 + + + + diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml new file mode 100644 index 00000000..e403fa53 --- /dev/null +++ b/man/systemd-system.conf.xml @@ -0,0 +1,436 @@ + + +%entities; +]> + + + + + systemd-system.conf + systemd + + + + systemd-system.conf + 5 + + + + systemd-system.conf + system.conf.d + systemd-user.conf + user.conf.d + System and session service manager configuration files + + + + /etc/systemd/system.conf, + /etc/systemd/system.conf.d/*.conf, + /run/systemd/system.conf.d/*.conf, + /usr/lib/systemd/system.conf.d/*.conf + /etc/systemd/user.conf, + /etc/systemd/user.conf.d/*.conf, + /run/systemd/user.conf.d/*.conf, + /usr/lib/systemd/user.conf.d/*.conf + + + + Description + + When run as a system instance, systemd interprets the + configuration file system.conf and the files + in system.conf.d directories; when run as a + user instance, systemd interprets the configuration file + user.conf and the files in + user.conf.d directories. These configuration + files contain a few settings controlling basic manager + operations. See + systemd.syntax5 + for a general description of the syntax. + + + + + + Options + + All options are configured in the + [Manager] section: + + + + + LogLevel= + LogTarget= + LogColor= + LogLocation= + DumpCore=yes + CrashChangeVT=no + CrashShell=no + CrashReboot=no + ShowStatus=yes + DefaultStandardOutput=journal + DefaultStandardError=inherit + + Configures various parameters of basic manager operation. These options may be overridden by + the respective process and kernel command line arguments. See + systemd1 for + details. + + + + CtrlAltDelBurstAction= + + Defines what action will be performed + if user presses Ctrl-Alt-Delete more than 7 times in 2s. + Can be set to reboot-force, poweroff-force, + reboot-immediate, poweroff-immediate + or disabled with none. Defaults to + reboot-force. + + + + + CPUAffinity= + + Configures the CPU affinity for the service manager as well as the default CPU + affinity for all forked off processes. Takes a list of CPU indices or ranges separated by either + whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a + dash. This option may be specified more than once, in which case the specified CPU affinity masks are + merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have + no effect. Individual services may override the CPU affinity for their processes with the + CPUAffinity= setting in unit files, see + systemd.exec5. + + + + NUMAPolicy= + + Configures the NUMA memory policy for the service manager and the default NUMA memory policy + for all forked off processes. Individual services may override the default policy with the + NUMAPolicy= setting in unit files, see + systemd.exec5. + + + + NUMAMask= + + Configures the NUMA node mask that will be associated with the selected NUMA policy. Note that + and NUMA policies don't require explicit NUMA node mask and + value of the option can be empty. Similarly to NUMAPolicy=, value can be overridden + by individual services in unit files, see + systemd.exec5. + + + + RuntimeWatchdogSec= + RebootWatchdogSec= + KExecWatchdogSec= + + Configure the hardware watchdog at runtime and at reboot. Takes a timeout value in seconds (or + in other time units if suffixed with ms, min, h, + d, w). If RuntimeWatchdogSec= is set to a non-zero + value, the watchdog hardware (/dev/watchdog or the path specified with + WatchdogDevice= or the kernel option systemd.watchdog-device=) will be + programmed to automatically reboot the system if it is not contacted within the specified timeout interval. The + system manager will ensure to contact it at least once in half the specified timeout interval. This feature + requires a hardware watchdog device to be present, as it is commonly the case in embedded and server + systems. Not all hardware watchdogs allow configuration of all possible reboot timeout values, in which case + the closest available timeout is picked. RebootWatchdogSec= may be used to configure the + hardware watchdog when the system is asked to reboot. It works as a safety net to ensure that the reboot takes + place even if a clean reboot attempt times out. Note that the RebootWatchdogSec= timeout + applies only to the second phase of the reboot, i.e. after all regular services are already terminated, and + after the system and service manager process (PID 1) got replaced by the systemd-shutdown + binary, see system bootup7 + for details. During the first phase of the shutdown operation the system and service manager remains running + and hence RuntimeWatchdogSec= is still honoured. In order to define a timeout on this first + phase of system shutdown, configure JobTimeoutSec= and JobTimeoutAction= + in the [Unit] section of the shutdown.target unit. By default + RuntimeWatchdogSec= defaults to 0 (off), and RebootWatchdogSec= to + 10min. KExecWatchdogSec= may be used to additionally enable the watchdog when kexec + is being executed rather than when rebooting. Note that if the kernel does not reset the watchdog on kexec (depending + on the specific hardware and/or driver), in this case the watchdog might not get disabled after kexec succeeds + and thus the system might get rebooted, unless RuntimeWatchdogSec= is also enabled at the same time. + For this reason it is recommended to enable KExecWatchdogSec= only if + RuntimeWatchdogSec= is also enabled. + These settings have no effect if a hardware watchdog is not available. + + + + WatchdogDevice= + + Configure the hardware watchdog device that the + runtime and shutdown watchdog timers will open and use. Defaults + to /dev/watchdog. This setting has no + effect if a hardware watchdog is not available. + + + + CapabilityBoundingSet= + + Controls which capabilities to include in the + capability bounding set for PID 1 and its children. See + capabilities7 + for details. Takes a whitespace-separated list of capability + names as read by + cap_from_name3. + Capabilities listed will be included in the bounding set, all + others are removed. If the list of capabilities is prefixed + with ~, all but the listed capabilities will be included, the + effect of the assignment inverted. Note that this option also + affects the respective capabilities in the effective, + permitted and inheritable capability sets. The capability + bounding set may also be individually configured for units + using the CapabilityBoundingSet= directive + for units, but note that capabilities dropped for PID 1 cannot + be regained in individual units, they are lost for + good. + + + + NoNewPrivileges= + + Takes a boolean argument. If true, ensures that PID 1 + and all its children can never gain new privileges through + execve2 + (e.g. via setuid or setgid bits, or filesystem capabilities). + Defaults to false. General purpose distributions commonly rely + on executables with setuid or setgid bits and will thus not + function properly with this option enabled. Individual units + cannot disable this option. + Also see No New Privileges Flag. + + + + + SystemCallArchitectures= + + Takes a space-separated list of architecture + identifiers. Selects from which architectures system calls may + be invoked on this system. This may be used as an effective + way to disable invocation of non-native binaries system-wide, + for example to prohibit execution of 32-bit x86 binaries on + 64-bit x86-64 systems. This option operates system-wide, and + acts similar to the + SystemCallArchitectures= setting of unit + files, see + systemd.exec5 + for details. This setting defaults to the empty list, in which + case no filtering of system calls based on architecture is + applied. Known architecture identifiers are + x86, x86-64, + x32, arm and the special + identifier native. The latter implicitly + maps to the native architecture of the system (or more + specifically, the architecture the system manager was compiled + for). Set this setting to native to + prohibit execution of any non-native binaries. When a binary + executes a system call of an architecture that is not listed + in this setting, it will be immediately terminated with the + SIGSYS signal. + + + + TimerSlackNSec= + + Sets the timer slack in nanoseconds for PID 1, + which is inherited by all executed processes, unless + overridden individually, for example with the + TimerSlackNSec= setting in service units + (for details see + systemd.exec5). + The timer slack controls the accuracy of wake-ups triggered by + system timers. See + prctl2 + for more information. Note that in contrast to most other time + span definitions this parameter takes an integer value in + nano-seconds if no unit is specified. The usual time units are + understood too. + + + + StatusUnitFormat= + + Takes either or as the value. If + , the system manager will use unit names in status messages, instead of the + longer and more informative descriptions set with Description=, see + systemd.unit5. + + + + + DefaultTimerAccuracySec= + + Sets the default accuracy of timer units. This + controls the global default for the + AccuracySec= setting of timer units, see + systemd.timer5 + for details. AccuracySec= set in individual + units override the global default for the specific unit. + Defaults to 1min. Note that the accuracy of timer units is + also affected by the configured timer slack for PID 1, see + TimerSlackNSec= above. + + + + DefaultTimeoutStartSec= + DefaultTimeoutStopSec= + DefaultTimeoutAbortSec= + DefaultRestartSec= + + Configures the default timeouts for starting, + stopping and aborting of units, as well as the default time to sleep + between automatic restarts of units, as configured per-unit in + TimeoutStartSec=, + TimeoutStopSec=, + TimeoutAbortSec= and + RestartSec= (for services, see + systemd.service5 + for details on the per-unit settings). Disabled by default, when + service with Type=oneshot is used. + For non-service units, + DefaultTimeoutStartSec= sets the default + TimeoutSec= + value. DefaultTimeoutStartSec= and + DefaultTimeoutStopSec= default to + 90s. DefaultTimeoutAbortSec= is not set by default + so that all units fall back to TimeoutStopSec=. + DefaultRestartSec= defaults to + 100ms. + + + + DefaultStartLimitIntervalSec= + DefaultStartLimitBurst= + + Configure the default unit start rate + limiting, as configured per-service by + StartLimitIntervalSec= and + StartLimitBurst=. See + systemd.service5 + for details on the per-service settings. + DefaultStartLimitIntervalSec= defaults to + 10s. DefaultStartLimitBurst= defaults to + 5. + + + + DefaultEnvironment= + + Sets manager environment variables passed to + all executed processes. Takes a space-separated list of + variable assignments. See + environ7 + for details about environment variables. + + Example: + + DefaultEnvironment="VAR1=word1 word2" VAR2=word3 "VAR3=word 5 6" + + Sets three variables + VAR1, + VAR2, + VAR3. + + + + DefaultCPUAccounting= + DefaultBlockIOAccounting= + DefaultMemoryAccounting= + DefaultTasksAccounting= + DefaultIOAccounting= + DefaultIPAccounting= + + Configure the default resource accounting settings, as configured per-unit by + CPUAccounting=, BlockIOAccounting=, MemoryAccounting=, + TasksAccounting=, IOAccounting= and IPAccounting=. See + systemd.resource-control5 + for details on the per-unit settings. DefaultTasksAccounting= defaults to yes, + DefaultMemoryAccounting= to &MEMORY_ACCOUNTING_DEFAULT;. DefaultCPUAccounting= + defaults to yes if enabling CPU accounting doesn't require the CPU controller to be enabled (Linux 4.15+ using the + unified hierarchy for resource control), otherwise it defaults to no. The other three settings default to no. + + + + DefaultTasksMax= + + Configure the default value for the per-unit TasksMax= setting. See + systemd.resource-control5 + for details. This setting applies to all unit types that support resource control settings, with the exception + of slice units. Defaults to 15%, which equals 4915 with the kernel's defaults on the host, but might be smaller + in OS containers. + + + + DefaultLimitCPU= + DefaultLimitFSIZE= + DefaultLimitDATA= + DefaultLimitSTACK= + DefaultLimitCORE= + DefaultLimitRSS= + DefaultLimitNOFILE= + DefaultLimitAS= + DefaultLimitNPROC= + DefaultLimitMEMLOCK= + DefaultLimitLOCKS= + DefaultLimitSIGPENDING= + DefaultLimitMSGQUEUE= + DefaultLimitNICE= + DefaultLimitRTPRIO= + DefaultLimitRTTIME= + + These settings control various default + resource limits for units. See + setrlimit2 + for details. The resource limit is possible to specify in two formats, + to set soft and hard limits to the same value, + or to set both limits individually (e.g. DefaultLimitAS=4G:16G). + Use the string infinity to + configure no limit on a specific resource. The multiplicative + suffixes K (=1024), M (=1024*1024) and so on for G, T, P and E + may be used for resource limits measured in bytes + (e.g. DefaultLimitAS=16G). For the limits referring to time values, + the usual time units ms, s, min, h and so on may be used (see + systemd.time7 + for details). Note that if no time unit is specified for + DefaultLimitCPU= the default unit of seconds is + implied, while for DefaultLimitRTTIME= the default + unit of microseconds is implied. Also, note that the effective + granularity of the limits might influence their + enforcement. For example, time limits specified for + DefaultLimitCPU= will be rounded up implicitly to + multiples of 1s. These settings may be overridden in individual units + using the corresponding LimitXXX= directives. Note that these resource + limits are only defaults for units, they are not applied to PID 1 + itself. + + + + DefaultOOMPolicy= + + Configure the default policy for reacting to processes being killed by the Linux + Out-Of-Memory (OOM) killer. This may be used to pick a global default for the per-unit + OOMPolicy= setting. See + systemd.service5 + for details. Note that this default is not used for services that have Delegate= + turned on. + + + + + + See Also + + systemd1, + systemd.directives7, + systemd.exec5, + systemd.service5, + environ7, + capabilities7 + + + + diff --git a/man/systemd-sysusers.xml b/man/systemd-sysusers.xml new file mode 100644 index 00000000..cc026256 --- /dev/null +++ b/man/systemd-sysusers.xml @@ -0,0 +1,135 @@ + + + + + + + + systemd-sysusers + systemd + + + + systemd-sysusers + 8 + + + + systemd-sysusers + systemd-sysusers.service + Allocate system users and groups + + + + + systemd-sysusers + OPTIONS + CONFIGFILE + + + systemd-sysusers.service + + + + Description + + systemd-sysusers creates system users and + groups, based on the file format and location specified in + sysusers.d5. + + + If invoked with no arguments, it applies all directives from all files + found in the directories specified by + sysusers.d5. + When invoked with positional arguments, if option + is specified, arguments + specified on the command line are used instead of the configuration file + PATH. Otherwise, just the configuration specified by + the command line arguments is executed. The string - may be + specified instead of a filename to instruct systemd-sysusers + to read the configuration from standard input. If only the basename of a file is + specified, all configuration directories are searched for a matching file and + the file found that has the highest priority is executed. + + + + Options + + The following options are understood: + + + + + Takes a directory path as an argument. All + paths will be prefixed with the given alternate + root path, including config search + paths. + + + + + When this option is given, one ore more positional arguments + must be specified. All configuration files found in the directories listed in + sysusers.d5 + will be read, and the configuration given on the command line will be + handled instead of and with the same priority as the configuration file + PATH. + + This option is intended to be used when package installation scripts + are running and files belonging to that package are not yet available on + disk, so their contents must be given on the command line, but the admin + configuration might already exist and should be given higher priority. + + + + RPM installation script for radvd + + echo 'u radvd - "radvd daemon"' | \ + systemd-sysusers --replace=/usr/lib/sysusers.d/radvd.conf - + + This will create the radvd user as if + /usr/lib/sysusers.d/radvd.conf was already on disk. + An admin might override the configuration specified on the command line by + placing /etc/sysusers.d/radvd.conf or even + /etc/sysusers.d/00-overrides.conf. + + Note that this is the expanded form, and when used in a package, this + would be written using a macro with "radvd" and a file containing the + configuration line as arguments. + + + + + + + Treat each positional argument as a separate configuration + line instead of a file name. + + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code + otherwise. + + + + See Also + + systemd1, + sysusers.d5, + Users, Groups, UIDs and GIDs on systemd systems + + + + diff --git a/man/systemd-sysv-generator.xml b/man/systemd-sysv-generator.xml new file mode 100644 index 00000000..795d9eeb --- /dev/null +++ b/man/systemd-sysv-generator.xml @@ -0,0 +1,72 @@ + + + + + + + + systemd-sysv-generator + systemd + + + + systemd-sysv-generator + 8 + + + + systemd-sysv-generator + Unit generator for SysV init scripts + + + + /usr/lib/systemd/system-generators/systemd-sysv-generator + + + + Description + + systemd-sysv-generator is a generator + that creates wrapper .service units for + SysV init + scripts in /etc/init.d/* at boot and when + configuration of the system manager is reloaded. This will allow + systemd1 + to support them similarly to native units. + + LSB headers + in SysV init scripts are interpreted, and the ordering specified + in the header is turned into dependencies between the generated + unit and other units. The LSB facilities + $remote_fs, $network, + $named, $portmap, + $time are supported and will be turned into + dependencies on specific native systemd targets. See + systemd.special5 + for more details. + + SysV runlevels have corresponding systemd targets + (runlevelX.target). + The wrapper unit that is generated will be wanted by those targets + which correspond to runlevels for which the script is + enabled. + + systemd does not support SysV scripts as + part of early boot, so all wrapper units are ordered after + basic.target. + + systemd-sysv-generator implements + systemd.generator7. + + + + See Also + + systemd1, + systemd.service5, + systemd.target5 + + + + diff --git a/man/systemd-time-wait-sync.service.xml b/man/systemd-time-wait-sync.service.xml new file mode 100644 index 00000000..c8a92f94 --- /dev/null +++ b/man/systemd-time-wait-sync.service.xml @@ -0,0 +1,68 @@ + + + + + + + + systemd-time-wait-sync.service + systemd + + + + systemd-time-wait-sync.service + 8 + + + + systemd-time-wait-sync.service + systemd-time-wait-sync + Wait Until Kernel Time Synchronized + + + + systemd-time-wait-sync.service + /usr/lib/systemd/systemd-time-wait-sync + + + + Description + + systemd-time-wait-sync is a system service that delays the start of units that depend on + time-sync.target until the system time has been synchronized with an accurate time source by + systemd-timesyncd.service. + + systemd-timesyncd.service notifies on successful synchronization. + systemd-time-wait-sync also tries to detect when the kernel marks the time as synchronized, + but this detection is not reliable and is intended only as a fallback for other services that can be used to + synchronize time (e.g., ntpd, chronyd). + + + + + Files + + + + /run/systemd/timesync/synchronized + + + The presence of this file indicates to this service that the system clock has been synchronized. + + + + + + + + + See Also + + systemd1, + systemd.special7, + systemd-timesyncd.service8, + + + + diff --git a/man/systemd-timedated.service.xml b/man/systemd-timedated.service.xml new file mode 100644 index 00000000..f981848c --- /dev/null +++ b/man/systemd-timedated.service.xml @@ -0,0 +1,90 @@ + + + + + + + + systemd-timedated.service + systemd + + + + systemd-timedated.service + 8 + + + + systemd-timedated.service + systemd-timedated + Time and date bus mechanism + + + + systemd-timedated.service + /usr/lib/systemd/systemd-timedated + + + + Description + + systemd-timedated is a system service + that may be used as a mechanism to change the system clock and + timezone, as well as to enable/disable network time synchronization. + systemd-timedated is automatically activated + on request and terminates itself when it is unused. + + The tool + timedatectl1 + is a command line client to this service. + + See the + developer documentation for information about the APIs + systemd-timedated provides. + + + + List of network time synchronization services + + systemd-timesyncd will look for files with a .list extension + in ntp-units.d/ directories. Each file is parsed as a list of unit names, one per + line. Empty lines and lines with comments (#) are ignored. Files are read from + /usr/lib/systemd/ntp-units.d/ and the corresponding directories under + /etc/, /run/, /usr/local/lib/. Files in + /etc/ override files with the same name in /run/, + /usr/local/lib/, and /usr/lib/. Files in + /run/ override files with the same name under /usr/. Packages + should install their configuration files in /usr/lib/ (distribution packages) or + /usr/local/lib/ (local installs). + + + <filename>ntp-units.d/</filename> entry for <command>systemd-timesyncd</command> + # /usr/lib/systemd/ntp-units.d/80-systemd-timesync.list +systemd-timesyncd.service + + + + If the environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES is set, + systemd-timesyncd will parse the contents of that variable as a colon-separated list + of unit names. When set, this variable overrides the file-based list described above. + + + An override that specifies that <command>chronyd</command> should be used if available + SYSTEMD_TIMEDATED_NTP_SERVICES=chronyd.service:systemd-timesyncd.service + + + + + See Also + + systemd1, + timedatectl1, + localtime5, + hwclock8, + systemd-timesyncd8 + + + + diff --git a/man/systemd-timesyncd.service.xml b/man/systemd-timesyncd.service.xml new file mode 100644 index 00000000..3dff6377 --- /dev/null +++ b/man/systemd-timesyncd.service.xml @@ -0,0 +1,104 @@ + + + + + + + + systemd-timesyncd.service + systemd + + + + systemd-timesyncd.service + 8 + + + + systemd-timesyncd.service + systemd-timesyncd + Network Time Synchronization + + + + systemd-timesyncd.service + /usr/lib/systemd/systemd-timesyncd + + + + Description + + systemd-timesyncd is a system service + that may be used to synchronize the local system clock with a + remote Network Time Protocol server. It also saves the local time + to disk every time the clock has been synchronized and uses this + to possibly advance the system realtime clock on subsequent + reboots to ensure it monotonically advances even if the system + lacks a battery-buffered RTC chip. + + The systemd-timesyncd service + specifically implements only SNTP. This minimalistic + service will set the system clock for large offsets or + slowly adjust it for smaller deltas. More complex use + cases are not covered by systemd-timesyncd. + + The NTP servers contacted are determined from the global + settings in + timesyncd.conf5, + the per-link static settings in .network + files, and the per-link dynamic settings received over DHCP. See + systemd.network5 + for more details. + + timedatectl1's + set-ntp command may be used to enable and + start, or disable and stop this service. + + timedatectl1's + timesync-status or show-timesync command can be used to show the + current status of this service. + + + + Files + + + + /var/lib/systemd/timesync/clock + + + The modification time of this file indicates the timestamp of the last successful + synchronization (or at least the systemd build date, in case synchronization was not + possible). + + + + + /run/systemd/timesync/synchronized + + + A file that is touched on each successful synchronization, to assist + systemd-time-wait-sync and other applications to detecting synchronization + events. + + + + + + + + See Also + + systemd1, + timesyncd.conf5, + systemd.network5, + systemd-networkd.service8, + systemd-time-wait-sync.service8, + timedatectl1, + localtime5, + hwclock8 + + + + diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml new file mode 100644 index 00000000..7720ef53 --- /dev/null +++ b/man/systemd-tmpfiles.xml @@ -0,0 +1,235 @@ + + + + + + + + systemd-tmpfiles + systemd + + + + systemd-tmpfiles + 8 + + + + systemd-tmpfiles + systemd-tmpfiles-setup.service + systemd-tmpfiles-setup-dev.service + systemd-tmpfiles-clean.service + systemd-tmpfiles-clean.timer + Creates, deletes and cleans up volatile + and temporary files and directories + + + + + systemd-tmpfiles + OPTIONS + CONFIGFILE + + + System units: +systemd-tmpfiles-setup.service +systemd-tmpfiles-setup-dev.service +systemd-tmpfiles-clean.service +systemd-tmpfiles-clean.timer + + User units: +systemd-tmpfiles-setup.service +systemd-tmpfiles-clean.service +systemd-tmpfiles-clean.timer + + + + Description + + systemd-tmpfiles creates, deletes, and + cleans up volatile and temporary files and directories, based on + the configuration file format and location specified in + tmpfiles.d5. + + + If invoked with no arguments, it applies all directives from all configuration + files. When invoked with , + arguments specified on the command line are used instead of the configuration file + PATH. Otherwise, if one or more absolute filenames are + passed on the command line, only the directives in these files are applied. If + - is specified instead of a filename, directives are read from + standard input. If only the basename of a configuration file is specified, all + configuration directories as specified in + tmpfiles.d5 + are searched for a matching file and the file found that has the highest priority is + executed. + + System services (systemd-tmpfiles-setup.service, + systemd-tmpfiles-setup-dev.service, + systemd-tmpfiles-clean.service) invoke systemd-tmpfiles to create + system files and to perform system wide cleanup. Those services read administrator-controlled + configuration files in tmpfiles.d/ directories. User services + (systemd-tmpfiles-setup.service, + systemd-tmpfiles-clean.service) also invoke systemd-tmpfiles, but + it reads a separate set of files, which includes user-controlled files under + ~/.config/user-tmpfiles.d/ and ~/.local/share/user-tmpfiles.d/, + and administrator-controller files under /usr/share/user-tmpfiles.d/. Users may use + this to create and clean up files under their control, but the system instance performs global cleanup + and is not influenced by user configuration. Note that this means a time-based cleanup configured in the + system instance, such as the one typically configured for /tmp, will thus also + affect files created by the user instance if they are placed in /tmp, even if the + user instance's time-based cleanup is turned off. + + + + Options + + The following options are understood: + + + + + If this option is passed, all files and + directories marked with + f, + F, + w, + d, + D, + v, + p, + L, + c, + b, + m + in the configuration files are created or written to. Files + and directories marked with + z, + Z, + t, + T, + a, and + A have their ownership, access mode and + security labels set. + + + + + If this option is passed, all files and + directories with an age parameter configured will be cleaned + up. + + + + + If this option is passed, the contents of + directories marked with D or + R, and files or directories themselves + marked with r or R are + removed. + + + + + Execute "user" configuration, i.e. tmpfiles.d + files in user configuration directories. + + + + + Also execute lines with an exclamation mark. + + + + + + Only apply rules with paths that start with + the specified prefix. This option can be specified multiple + times. + + + + Ignore rules with paths that start with the + specified prefix. This option can be specified multiple + times. + + + + + Takes a directory path as an argument. All paths will be prefixed with the given alternate + root path, including config search paths. + + Note that this option does not alter how the users and groups specified in the configuration files are + resolved. With or without this option, users and groups are always resolved according to the host's user and + group databases, any such databases stored under the specified root directories are not + consulted. + + + + + When this option is given, one ore more positional arguments + must be specified. All configuration files found in the directories listed in + tmpfiles.d5 + will be read, and the configuration given on the command line will be + handled instead of and with the same priority as the configuration file + PATH. + + This option is intended to be used when package installation scripts + are running and files belonging to that package are not yet available on + disk, so their contents must be given on the command line, but the admin + configuration might already exist and should be given higher priority. + + + + + + + + + + It is possible to combine , , and + in one invocation (in which case removal and cleanup are executed before creation of new files). For example, + during boot the following command line is executed to ensure that all temporary and volatile directories are + removed and created according to the configuration file: + + systemd-tmpfiles --remove --create + + + + Unprivileged --cleanup operation + + systemd-tmpfiles tries to avoid changing + the access and modification times on the directories it accesses, + which requires CAP_FOWNER privileges. When + running as non-root, directories which are checked for files to + clean up will have their access time bumped, which might prevent + their cleanup. + + + + + Exit status + + On success, 0 is returned. If the configuration was syntactically invalid (syntax errors, + missing arguments, …), so some lines had to be ignored, but no other errors occurred, + 65 is returned (EX_DATAERR from + /usr/include/sysexits.h). If the configuration was syntactically valid, but + could not be executed (lack of permissions, creation of files in missing directories, invalid + contents when writing to /sys/ values, …), 73 is + returned (EX_CANTCREAT from /usr/include/sysexits.h). + Otherwise, 1 is returned (EXIT_FAILURE from + /usr/include/stdlib.h). + + + + + See Also + + systemd1, + tmpfiles.d5 + + + + diff --git a/man/systemd-tty-ask-password-agent.xml b/man/systemd-tty-ask-password-agent.xml new file mode 100644 index 00000000..8d9e9e0c --- /dev/null +++ b/man/systemd-tty-ask-password-agent.xml @@ -0,0 +1,126 @@ + + + + + + + + systemd-tty-ask-password-agent + systemd + + + + systemd-tty-ask-password-agent + 1 + + + + systemd-tty-ask-password-agent + List or process pending systemd password requests + + + + + systemd-tty-ask-password-agent + OPTIONS + VARIABLE=VALUE + + + + + Description + + systemd-tty-ask-password-agent is a + password agent that handles password requests of the system, for + example for hard disk encryption passwords or SSL certificate + passwords that need to be queried at boot-time or during + runtime. + + systemd-tty-ask-password-agent implements + the Password + Agents Specification, and is one of many possible response agents which + answer to queries formulated with + systemd-ask-password1. + + + + + Options + + The following options are understood: + + + + + + Lists all currently pending system password requests. + + + + + + Process all currently pending system password + requests by querying the user on the calling + TTY. + + + + + + Continuously process password + requests. + + + + + + Forward password requests to + wall1 + instead of querying the user on the calling + TTY. + + + + + + Ask question with + plymouth8 + instead of querying the user on the calling + TTY. + + + + + + Ask question on + /dev/console instead of querying the user + on the calling TTY. + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure + code otherwise. + + + + See Also + + systemd1, + systemctl1, + systemd-ask-password-console.service8, + wall1, + plymouth8 + + + + diff --git a/man/systemd-udev-settle.service.xml b/man/systemd-udev-settle.service.xml new file mode 100644 index 00000000..3698bfaf --- /dev/null +++ b/man/systemd-udev-settle.service.xml @@ -0,0 +1,51 @@ + + + + + + + + systemd-udev-settle.service + systemd + + + + systemd-udev-settle.service + 8 + + + + systemd-udev-settle.service + Wait for all pending udev events to be handled + + + + systemd-udev-settle.service + + + Description + This service calls udevadm settle to wait until all events that have been queued + by udev7 have been + processed. It is a crude way to wait until "all" hardware has been discovered. Services may pull in this + service and order themselves after it to wait for the udev queue to be empty. + + Using this service is not recommended. There can be no guarantee that hardware + is fully discovered at any specific time, because the kernel does hardware detection asynchronously, and + certain buses and devices take a very long time to become ready, and also additional hardware may be + plugged in at any time. Instead, services should subscribe to udev events and react to any new hardware as + it is discovered. Services that, based on configuration, expect certain devices to appear, may warn or + report failure after a timeout. This timeout should be tailored to the hardware type. Waiting for + systemd-udev-settle.service usually slows boot significantly, because it means waiting + for all unrelated events too. + + + + See Also + + udev7, + udevadm8 + + + diff --git a/man/systemd-udevd.service.xml b/man/systemd-udevd.service.xml new file mode 100644 index 00000000..c267bb2b --- /dev/null +++ b/man/systemd-udevd.service.xml @@ -0,0 +1,199 @@ + + + + + + + + systemd-udevd.service + systemd + + + + systemd-udevd.service + 8 + + + + systemd-udevd.service + systemd-udevd-control.socket + systemd-udevd-kernel.socket + systemd-udevd + Device event managing daemon + + + + systemd-udevd.service + systemd-udevd-control.socket + systemd-udevd-kernel.socket + + + /usr/lib/systemd/systemd-udevd + + + + + + + + + + + + + Description + systemd-udevd listens to kernel uevents. + For every event, systemd-udevd executes matching instructions + specified in udev rules. See + udev7 + . + + The behavior of the daemon can be configured using + udev.conf5, + its command line options, environment variables, and on the kernel + command line, or changed dynamically with udevadm + control. + + + + Options + + + + + + Detach and run in the background. + + + + + + + + Print debug messages to standard error. + + + + + + + + Limit the number of events executed in parallel. + + + + + + + + Delay the execution of RUN + instructions by the given number of seconds. This option + might be useful when debugging system crashes during + coldplug caused by loading non-working kernel + modules. + + + + + + + + Set the number of seconds to wait for events to finish. After + this time, the event will be terminated. The default is 180 seconds. + + + + + + + + Specify when systemd-udevd should resolve names of users and groups. + When set to (the default), names will be + resolved when the rules are parsed. When set to + , names will be resolved for every event. + When set to , names will never be resolved + and all devices will be owned by root. + + + + + + + + + Kernel command line + + Parameters starting with "rd." will be read when + systemd-udevd is used in an initrd. + + udev.log_priority= + rd.udev.log_priority= + + Set the log level. + + + + udev.children_max= + rd.udev.children_max= + + Limit the number of events executed in parallel. + + + + udev.exec_delay= + rd.udev.exec_delay= + + Delay the execution of RUN instructions by the given + number of seconds. This option might be useful when + debugging system crashes during coldplug caused by loading + non-working kernel modules. + + + + udev.event_timeout= + rd.udev.event_timeout= + + Wait for events to finish up to the given number + of seconds. This option might be useful if events are + terminated due to kernel drivers taking too long to initialize. + + + + net.ifnames= + + Network interfaces are renamed to give them predictable names + when possible. It is enabled by default; specifying 0 disables it. + + + + net.naming-scheme= + + Network interfaces are renamed to give them predictable names when possible (unless + net.ifnames=0 is specified, see above). With this kernel command line option it + is possible to pick a specific version of this algorithm and override the default chosen at + compilation time. Expects one of the naming scheme identifiers listed in + systemd.net-naming-scheme7, + or latest to select the latest scheme known (to this particular version of + systemd-udevd.service). + + Note that selecting a specific scheme is not sufficient to fully stabilize interface naming: + the naming is generally derived from driver attributes exposed by the kernel. As the kernel is + updated, previously missing attributes systemd-udevd.service is checking might + appear, which affects older name derivation algorithms, too. + + + + + + + + See Also + + udev.conf5, + udev7, + udevadm8 + + + diff --git a/man/systemd-update-done.service.xml b/man/systemd-update-done.service.xml new file mode 100644 index 00000000..ad412691 --- /dev/null +++ b/man/systemd-update-done.service.xml @@ -0,0 +1,72 @@ + + + + + + + + systemd-update-done.service + systemd + + + + systemd-update-done.service + 8 + + + + systemd-update-done.service + systemd-update-done + Mark /etc and /var fully updated + + + + systemd-update-done.service + /usr/lib/systemd/systemd-update-done + + + + Description + + systemd-update-done.service is a + service that is invoked as part of the first boot after the vendor + operating system resources in /usr have been + updated. This is useful to implement offline updates of + /usr which might require updates to + /etc or /var on the + following boot. + + systemd-update-done.service updates the + file modification time (mtime) of the stamp files + /etc/.updated and + /var/.updated to the modification time of the + /usr directory, unless the stamp files are + already newer. + + Services that shall run after offline upgrades of + /usr should order themselves before + systemd-update-done.service, and use the + ConditionNeedsUpdate= (see + systemd.unit5) + condition to make sure to run when /etc or + /var are older than /usr + according to the modification times of the files described above. + This requires that updates to /usr are always + followed by an update of the modification time of + /usr, for example by invoking + touch1 + on it. + + + + + See Also + + systemd1, + systemd.unit5, + touch1 + + + + diff --git a/man/systemd-update-utmp.service.xml b/man/systemd-update-utmp.service.xml new file mode 100644 index 00000000..e1059ec7 --- /dev/null +++ b/man/systemd-update-utmp.service.xml @@ -0,0 +1,51 @@ + + + + + + + + systemd-update-utmp.service + systemd + + + + systemd-update-utmp.service + 8 + + + + systemd-update-utmp.service + systemd-update-utmp-runlevel.service + systemd-update-utmp + Write audit and utmp updates at bootup, runlevel + changes and shutdown + + + + systemd-update-utmp.service + systemd-update-utmp-runlevel.service + /usr/lib/systemd/systemd-update-utmp + + + + Description + + systemd-update-utmp-runlevel.service is + a service that writes SysV runlevel changes to utmp and wtmp, as + well as the audit logs, as they occur. + systemd-update-utmp.service does the same for + system reboots and shutdown requests. + + + + See Also + + systemd1, + utmp5, + auditd8 + + + + diff --git a/man/systemd-user-sessions.service.xml b/man/systemd-user-sessions.service.xml new file mode 100644 index 00000000..ab33d469 --- /dev/null +++ b/man/systemd-user-sessions.service.xml @@ -0,0 +1,50 @@ + + + + + + + + systemd-user-sessions.service + systemd + + + + systemd-user-sessions.service + 8 + + + + systemd-user-sessions.service + systemd-user-sessions + Permit user logins after boot, prohibit user logins at shutdown + + + + systemd-user-sessions.service + /usr/lib/systemd/systemd-user-sessions + + + + Description + + systemd-user-sessions.service is a + service that controls user logins through + pam_nologin8. + After basic system initialization is complete, it removes + /run/nologin, thus permitting logins. Before + system shutdown, it creates /run/nologin, thus + prohibiting further logins. + + + + See Also + + systemd1, + systemd-logind.service8, + pam_nologin8 + + + + diff --git a/man/systemd-vconsole-setup.service.xml b/man/systemd-vconsole-setup.service.xml new file mode 100644 index 00000000..7e763837 --- /dev/null +++ b/man/systemd-vconsole-setup.service.xml @@ -0,0 +1,63 @@ + + + + + + + + systemd-vconsole-setup.service + systemd + + + + systemd-vconsole-setup.service + 8 + + + + systemd-vconsole-setup.service + systemd-vconsole-setup + Configure the virtual consoles + + + + systemd-vconsole-setup.service + + /usr/lib/systemd/systemd-vconsole-setup + TTY + + + + + Description + + systemd-vconsole-setup sets up and configures either all virtual consoles, or — if the + optional TTY parameter is provided — a specific one. When the system is booting up, it's + called by systemd-udevd8 during + VT console subsystem initialization. Also, + systemd-localed.service8 invokes + it as needed when language or console changes are made. Internally, this program calls loadkeys1 and setfont8. + + + Execute systemctl restart systemd-vconsole-setup.service in order to apply any manual + changes made to /etc/vconsole.conf. + + See vconsole.conf5 for + information about the configuration files and kernel command line options understood by this program. + + + + See Also + + systemd1, + vconsole.conf5, + loadkeys1, + setfont8, + systemd-localed.service8 + + + + diff --git a/man/systemd-veritysetup-generator.xml b/man/systemd-veritysetup-generator.xml new file mode 100644 index 00000000..bcacd59c --- /dev/null +++ b/man/systemd-veritysetup-generator.xml @@ -0,0 +1,97 @@ + + + + + + + + systemd-veritysetup-generator + systemd + + + + systemd-veritysetup-generator + 8 + + + + systemd-veritysetup-generator + Unit generator for integrity protected block devices + + + + /usr/lib/systemd/system-generators/systemd-veritysetup-generator + + + + Description + + systemd-veritysetup-generator is a generator that translates kernel command line options + configuring integrity-protected block devices (verity) into native systemd units early at boot and when + configuration of the system manager is reloaded. This will create + systemd-veritysetup@.service8 + units as necessary. + + Currently, only a single verity device may be set up with this generator, backing the root file system of the + OS. + + systemd-veritysetup-generator implements + systemd.generator7. + + + + Kernel Command Line + + systemd-veritysetup-generator + understands the following kernel command line parameters: + + + + systemd.verity= + rd.systemd.verity= + + Takes a boolean argument. Defaults to yes. If no, + disables the generator entirely. rd.systemd.verity= is honored only by the initial RAM disk + (initrd) while systemd.verity= is honored by both the host system and the + initrd. + + + + roothash= + + Takes a root hash value for the root file system. Expects a hash value formatted in hexadecimal + characters of the appropriate length (i.e. most likely 256 bit/64 characters, or longer). If not specified via + systemd.verity_root_data= and systemd.verity_root_hash=, the hash and + data devices to use are automatically derived from the specified hash value. Specifically, the data partition + device is looked for under a GPT partition UUID derived from the first 128bit of the root hash, the hash + partition device is looked for under a GPT partition UUID derived from the last 128bit of the root hash. Hence + it is usually sufficient to specify the root hash to boot from an integrity protected root file system, as + device paths are automatically determined from it — as long as the partition table is properly set up. + + + + + systemd.verity_root_data= + systemd.verity_root_hash= + + These two settings take block device paths as arguments and may be used to explicitly + configure the data partition and hash partition to use for setting up the integrity protection for the root file + system. If not specified, these paths are automatically derived from the roothash= argument + (see above). + + + + + + + See Also + + systemd1, + systemd-veritysetup@.service8, + veritysetup8, + systemd-fstab-generator8 + + + + diff --git a/man/systemd-veritysetup@.service.xml b/man/systemd-veritysetup@.service.xml new file mode 100644 index 00000000..2c71c3e7 --- /dev/null +++ b/man/systemd-veritysetup@.service.xml @@ -0,0 +1,50 @@ + + + + + + + + systemd-veritysetup@.service + systemd + + + + systemd-veritysetup@.service + 8 + + + + systemd-veritysetup@.service + systemd-veritysetup + Disk integrity protection logic + + + + systemd-veritysetup@.service + /usr/lib/systemd/systemd-veritysetup + + + + Description + + systemd-veritysetup@.service is a service responsible for setting up integrity + protection (verity) block devices. It should be instantiated for each device that requires integrity + protection. + + At early boot and when the system manager configuration is reloaded kernel command line configuration for + integrity protected block devices is translated into systemd-veritysetup@.service units by + systemd-veritysetup-generator8. + + + + See Also + + systemd1, + systemd-veritysetup-generator8, + veritysetup8 + + + + diff --git a/man/systemd-volatile-root.service.xml b/man/systemd-volatile-root.service.xml new file mode 100644 index 00000000..440e9eac --- /dev/null +++ b/man/systemd-volatile-root.service.xml @@ -0,0 +1,54 @@ + + + + + + + + systemd-volatile-root.service + systemd + + + + systemd-volatile-root.service + 8 + + + + systemd-volatile-root.service + systemd-volatile-root + Make the root file system volatile + + + + systemd-volatile-root.service + /usr/lib/systemd/systemd-volatile-root + + + + Description + + systemd-volatile-root.service is a service that replaces the root directory with a + volatile memory file system (tmpfs), mounting the original (non-volatile) + /usr inside it read-only. This way, vendor data from /usr is available as + usual, but all configuration data in /etc, all state data in /var and all + other resources stored directly under the root directory are reset on boot and lost at shutdown, enabling fully + stateless systems. + + This service is only enabled if full volatile mode is selected, for example by specifying + systemd.volatile=yes on the kernel command line. This service runs only in the initial RAM disk + ("initrd"), before the system transitions to the host's root directory. Note that this service is not used if + systemd.volatile=state is used, as in that mode the root directory is non-volatile. + + + + See Also + + systemd1, + systemd-fstab-generator8, + kernel-command-line7 + + + + diff --git a/man/systemd.automount.xml b/man/systemd.automount.xml new file mode 100644 index 00000000..f2ed7610 --- /dev/null +++ b/man/systemd.automount.xml @@ -0,0 +1,161 @@ + + + + + + + systemd.automount + systemd + + + + systemd.automount + 5 + + + + systemd.automount + Automount unit configuration + + + + automount.automount + + + + Description + + A unit configuration file whose name ends in + .automount encodes information about a file + system automount point controlled and supervised by + systemd. + + This man page lists the configuration options specific to + this unit type. See + systemd.unit5 + for the common options of all unit configuration files. The common + configuration items are configured in the generic [Unit] and + [Install] sections. The automount specific configuration options + are configured in the [Automount] section. + + Automount units must be named after the automount directories they control. Example: the automount point + /home/lennart must be configured in a unit file + home-lennart.automount. For details about the escaping logic used to convert a file system + path to a unit name see + systemd.unit5. Note that + automount units cannot be templated, nor is it possible to add multiple names to an automount unit by creating + additional symlinks to its unit file. + + For each automount unit file a matching mount unit file (see + systemd.mount5 + for details) must exist which is activated when the automount path + is accessed. Example: if an automount unit + home-lennart.automount is active and the user + accesses /home/lennart the mount unit + home-lennart.mount will be activated. + + Automount units may be used to implement on-demand mounting + as well as parallelized mounting of file systems. + + + + Automatic Dependencies + + + Implicit Dependencies + + The following dependencies are implicitly added: + + + If an automount unit is beneath another mount unit in the + file system hierarchy, both a requirement and an ordering + dependency between both units are created automatically. + + An implicit Before= dependency is created + between an automount unit and the mount unit it activates. + + + + + Default Dependencies + + The following dependencies are added unless DefaultDependencies=no is set: + + + Automount units acquire automatic Before= and + Conflicts= on umount.target in order to be stopped during + shutdown. + + + + + + <filename>fstab</filename> + + Automount units may either be configured via unit files, or + via /etc/fstab (see + fstab5 + for details). + + For details how systemd parses + /etc/fstab see + systemd.mount5. + + If an automount point is configured in both + /etc/fstab and a unit file, the configuration + in the latter takes precedence. + + + + Options + + Automount files must include an [Automount] section, which + carries information about the file system automount points it + supervises. The options specific to the [Automount] section of + automount units are the following: + + + + + Where= + Takes an absolute path of a directory of the + automount point. If the automount point does not exist at time + that the automount point is installed, it is created. This + string must be reflected in the unit filename. (See above.) + This option is mandatory. + + + + DirectoryMode= + Directories of automount points (and any + parent directories) are automatically created if needed. This + option specifies the file system access mode used when + creating these directories. Takes an access mode in octal + notation. Defaults to 0755. + + + TimeoutIdleSec= + Configures an idle timeout. Once the mount has been + idle for the specified time, systemd will attempt to unmount. Takes a + unit-less value in seconds, or a time span value such as "5min 20s". + Pass 0 to disable the timeout logic. The timeout is disabled by + default. + + + + + + See Also + + systemd1, + systemctl1, + systemd.unit5, + systemd.mount5, + mount8, + automount8, + systemd.directives7 + + + + diff --git a/man/systemd.device.xml b/man/systemd.device.xml new file mode 100644 index 00000000..ae786a32 --- /dev/null +++ b/man/systemd.device.xml @@ -0,0 +1,165 @@ + + + + + + + systemd.device + systemd + + + + systemd.device + 5 + + + + systemd.device + Device unit configuration + + + + device.device + + + + Description + + A unit configuration file whose name ends in + .device encodes information about a device unit + as exposed in the + sysfs/udev7 + device tree. + + This unit type has no specific options. See + systemd.unit5 + for the common options of all unit configuration files. The common + configuration items are configured in the generic + [Unit] and [Install] + sections. A separate [Device] section does not + exist, since no device-specific options may be configured. + + systemd will dynamically create device units for all kernel + devices that are marked with the "systemd" udev tag (by default + all block and network devices, and a few others). This may be used + to define dependencies between devices and other units. To tag a + udev device, use TAG+="systemd" in the udev + rules file, see + udev7 + for details. + + Device units are named after the /sys + and /dev paths they control. Example: the + device /dev/sda5 is exposed in + systemd as dev-sda5.device. For details about + the escaping logic used to convert a file system path to a unit + name see + systemd.unit5. + + Device units will be reloaded by systemd whenever the + corresponding device generates a changed event. + Other units can use ReloadPropagatedFrom= to react + to that event + + + + Automatic Dependencies + + + Implicit Dependencies + + Many unit types automatically acquire dependencies on device + units of devices they require. For example, + .socket unit acquire dependencies on the + device units of the network interface specified in + BindToDevice=. Similar, swap and mount units + acquire dependencies on the units encapsulating their backing + block devices. + + + + Default Dependencies + + There are no default dependencies for device units. + + + + + The udev Database + + Unit settings of device units may either be configured via unit files, or directly from the udev + database. The following udev device properties are understood by the service manager: + + + + SYSTEMD_WANTS= + SYSTEMD_USER_WANTS= + Adds dependencies of type Wants= from the device unit to the specified + units. SYSTEMD_WANTS= is read by the system service manager, + SYSTEMD_USER_WANTS= by user service manager instances. These properties may be used to + activate arbitrary units when a specific device becomes available. + + Note that this and the other udev device properties are not taken into account unless the device is + tagged with the systemd tag in the udev database, because otherwise the device is not + exposed as a systemd unit (see above). + + Note that systemd will only act on Wants= dependencies when a device first becomes + active. It will not act on them if they are added to devices that are already active. Use + SYSTEMD_READY= (see below) to configure when a udev device shall be considered active, and + thus when to trigger the dependencies. + + + + The specified property value should be a space-separated list of valid unit names. If a unit template + name is specified (that is, a unit name containing an @ character indicating a unit name to + use for multiple instantiation, but with an empty instance name following the @), it will be + automatically instantiated by the device's sysfs path (that is: the path is escaped and + inserted as instance name into the template unit name). This is useful in order to instantiate a specific + template unit once for each device that appears and matches specific properties. + + + + SYSTEMD_ALIAS= + Adds an additional alias name to the device + unit. This must be an absolute path that is automatically + transformed into a unit name. (See above.) + + + + SYSTEMD_READY= + If set to 0, systemd will consider this device unplugged even if it shows up in the udev + tree. If this property is unset or set to 1, the device will be considered plugged if it is visible in the udev + tree. + + This option is useful for devices that initially show up in an uninitialized state in the tree, and for + which a changed event is generated the moment they are fully set up. Note that + SYSTEMD_WANTS= (see above) is not acted on as long as SYSTEMD_READY=0 is + set for a device. + + + + ID_MODEL_FROM_DATABASE= + ID_MODEL= + + If set, this property is used as description + string for the device unit. + + + + + + + + See Also + + systemd1, + systemctl1, + systemd.unit5, + udev7, + systemd.directives7 + + + + diff --git a/man/systemd.dnssd.xml b/man/systemd.dnssd.xml new file mode 100644 index 00000000..1ac760ee --- /dev/null +++ b/man/systemd.dnssd.xml @@ -0,0 +1,231 @@ + + + + + + + + systemd.dnssd + systemd + + + + systemd.dnssd + 5 + + + + systemd.dnssd + DNS-SD configuration + + + + network_service.dnssd + + + + Description + + DNS-SD setup is performed by + systemd-resolved8. + + + The main network service file must have the extension .dnssd; other + extensions are ignored. + + The .dnssd files are read from the files located in the system network + directories /usr/lib/systemd/dnssd and + /usr/local/lib/systemd/dnssd, the volatile runtime network directory + /run/systemd/dnssd and the local administration network directory + /etc/systemd/dnssd. All configuration files are collectively sorted and processed in + lexical order, regardless of the directories in which they live. However, files with identical filenames + replace each other. Files in /etc have the highest priority, files in + /run take precedence over files with the same name in + /usr/lib. This can be used to override a system-supplied configuration file with a + local file if needed. + + Along with the network service file foo.dnssd, a "drop-in" directory + foo.dnssd.d/ may exist. All files with the suffix + .conf from this directory will be parsed after the file itself is + parsed. This is useful to alter or add configuration settings, without having to modify the main + configuration file. Each drop-in file must have appropriate section headers. + + In addition to /etc/systemd/dnssd, drop-in .d directories + can be placed in /usr/lib/systemd/dnssd or /run/systemd/dnssd + directories. Drop-in files in /etc take precedence over those in + /run which in turn take precedence over those in /usr/lib or + /usr/local/lib. Drop-in files under any of these directories take precedence over + the main network service file wherever located. + + + + [Service] Section Options + + The network service file contains a [Service] + section, which specifies a discoverable network service announced in a + local network with Multicast DNS broadcasts. + + + + Name= + + An instance name of the network service as defined in the section 4.1.1 of RFC 6763, e.g. webserver. + The option supports simple specifier expansion. The following expansions are understood: + + Specifiers available + + + + + + + Specifier + Meaning + Details + + + + + %m + Machine ID + The machine ID of the running system, formatted as string. See machine-id5 for more information. + + + %b + Boot ID + The boot ID of the running system, formatted as string. See random4 for more information. + + + %H + Host name + The hostname of the running system. + + + %v + Kernel release + Identical to uname -r output. + + + +
+
+
+ + Type= + + A type of the network service as defined in the section 4.1.2 of RFC 6763, e.g. _http._tcp. + + + + + Port= + + An IP port number of the network service. + + + + Priority= + + A priority number set in SRV resource records corresponding to the network service. + + + + Weight= + + A weight number set in SRV resource records corresponding to the network service. + + + + TxtText= + + A whitespace-separated list of arbitrary key/value pairs + conveying additional information about the named service in the corresponding TXT resource record, + e.g. path=/portal/index.html. Keys and values can contain C-style escape + sequences which get translated upon reading configuration files. + + This option together with TxtData= may be specified more than once, in which + case multiple TXT resource records will be created for the service. If the empty string is assigned to + this option, the list is reset and all prior assignments will have no effect. + + + + + TxtData= + + A whitespace-separated list of arbitrary key/value pairs + conveying additional information about the named service in the corresponding TXT resource record + where values are base64-encoded string representing any binary data, + e.g. data=YW55IGJpbmFyeSBkYXRhCg==. Keys can contain C-style escape + sequences which get translated upon reading configuration files. + + This option together with TxtText= may be specified more than once, in which + case multiple TXT resource records will be created for the service. If the empty string is assigned to + this option, the list is reset and all prior assignments will have no effect. + + + +
+ +
+ + + Examples + + HTTP service + + # /etc/systemd/dnssd/http.dnssd +[Service] +Name=%H +Type=_http._tcp +Port=80 +TxtText=path=/stats/index.html t=temperature_sensor + + This makes the http server running on the host discoverable in the local network + given MulticastDNS is enabled on the network interface. + + Now the utility resolvectl should be able to resolve the + service to the host's name: + + $ resolvectl service meteo._http._tcp.local +meteo._http._tcp.local: meteo.local:80 [priority=0, weight=0] + 169.254.208.106%senp0s21f0u2u4 + fe80::213:3bff:fe49:8aa%senp0s21f0u2u4 + path=/stats/index.html + t=temperature_sensor + (meteo/_http._tcp/local) + +-- Information acquired via protocol mDNS/IPv6 in 4.0ms. +-- Data is authenticated: yes + + Avahi running on a different host in the same local network should see the service as well: + + $ avahi-browse -a -r ++ enp3s0 IPv6 meteo Web Site local ++ enp3s0 IPv4 meteo Web Site local += enp3s0 IPv6 meteo Web Site local + hostname = [meteo.local] + address = [fe80::213:3bff:fe49:8aa] + port = [80] + txt = ["path=/stats/index.html" "t=temperature_sensor"] += enp3s0 IPv4 meteo Web Site local + hostname = [meteo.local] + address = [169.254.208.106] + port = [80] + txt = ["path=/stats/index.html" "t=temperature_sensor"] + + + + + + See Also + + systemd1, + systemd-resolved.service8, + resolvectl1 + + + +
diff --git a/man/systemd.environment-generator.xml b/man/systemd.environment-generator.xml new file mode 100644 index 00000000..a806f7bc --- /dev/null +++ b/man/systemd.environment-generator.xml @@ -0,0 +1,134 @@ + + +%entities; +]> + + + + + systemd.environment-generator + systemd + + + + systemd.environment-generator + 7 + + + + systemd.environment-generator + systemd environment file generators + + + + + &systemenvgeneratordir;/some-generator + + + &userenvgeneratordir;/some-generator + + + + /run/systemd/system-environment-generators/* +/etc/systemd/system-environment-generators/* +/usr/local/lib/systemd/system-environment-generators/* +&systemenvgeneratordir;/* + + + + /run/systemd/user-environment-generators/* +/etc/systemd/user-environment-generators/* +/usr/local/lib/systemd/user-environment-generators/* +&userenvgeneratordir;/* + + + + + Description + Generators are small executables that live in + &systemenvgeneratordir;/ and other directories listed above. + systemd1 will + execute those binaries very early at the startup of each manager and at configuration + reload time, before running the generators described in + systemd.generator7 + and before starting any units. Environment generators can override the environment that the + manager exports to services and other processes. + + Generators are loaded from a set of paths determined during compilation, as listed + above. System and user environment generators are loaded from directories with names ending in + system-environment-generators/ and + user-environment-generators/, respectively. Generators found in directories + listed earlier override the ones with the same name in directories lower in the list. A symlink + to /dev/null or an empty file can be used to mask a generator, thereby + preventing it from running. Please note that the order of the two directories with the highest + priority is reversed with respect to the unit load path, and generators in + /run overwrite those in /etc. + + After installing new generators or updating the configuration, systemctl + daemon-reload may be executed. This will re-run all generators, updating environment + configuration. It will be used for any services that are started subsequently. + + Environment file generators are executed similarly to unit file generators described + in + systemd.generator7, + with the following differences: + + + + Generators are executed sequentially in the alphanumerical order of the final + component of their name. The output of each generator output is immediately parsed and used + to update the environment for generators that run after that. Thus, later generators can use + and/or modify the output of earlier generators. + + + + Generators are run by every manager instance, their output can be different for each + user. + + + + It is recommended to use numerical prefixes for generator names to simplify ordering. + + + + Examples + + + A simple generator that extends an environment variable if a directory exists in the file system + + # 50-xdg-data-dirs.sh + + + + + + A more complicated generator which reads existing configuration and mutates one variable + + # 90-rearrange-path.py + + + + + + Debugging a generator + + SYSTEMD_LOG_LEVEL=debug VAR_A=something VAR_B="something else" \ +&systemenvgeneratordir;/path-to-generator + + + + + + See also + + + systemd-environment-d-generator8, + systemd.generator7, + systemd1, + systemctl1 + + + diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml new file mode 100644 index 00000000..5706e3e2 --- /dev/null +++ b/man/systemd.exec.xml @@ -0,0 +1,3186 @@ + + + + + + + systemd.exec + systemd + + + + systemd.exec + 5 + + + + systemd.exec + Execution environment configuration + + + + service.service, + socket.socket, + mount.mount, + swap.swap + + + + Description + + Unit configuration files for services, sockets, mount points, and swap devices share a subset of + configuration options which define the execution environment of spawned processes. + + This man page lists the configuration options shared by these four unit types. See + systemd.unit5 for the common + options of all unit configuration files, and + systemd.service5, + systemd.socket5, + systemd.swap5, and + systemd.mount5 for more + information on the specific unit configuration files. The execution specific configuration options are configured + in the [Service], [Socket], [Mount], or [Swap] sections, depending on the unit type. + + In addition, options which control resources through Linux Control Groups (cgroups) are listed in + systemd.resource-control5. + Those options complement options listed here. + + + + Implicit Dependencies + + A few execution parameters result in additional, automatic dependencies to be added: + + + Units with WorkingDirectory=, RootDirectory=, + RootImage=, RuntimeDirectory=, StateDirectory=, + CacheDirectory=, LogsDirectory= or + ConfigurationDirectory= set automatically gain dependencies of type + Requires= and After= on all mount units required to access the specified + paths. This is equivalent to having them listed explicitly in + RequiresMountsFor=. + + Similar, units with PrivateTmp= enabled automatically get mount unit + dependencies for all mounts required to access /tmp and /var/tmp. They + will also gain an automatic After= dependency on + systemd-tmpfiles-setup.service8. + + Units whose standard output or error output is connected to , + or (or their combinations with console output, see below) + automatically acquire dependencies of type After= on + systemd-journald.socket. + + + + + + + Paths + + The following settings may be used to change a service's view of the filesystem. Please note that the paths + must be absolute and must not contain a .. path component. + + + + + WorkingDirectory= + + Takes a directory path relative to the service's root directory specified by + RootDirectory=, or the special value ~. Sets the working directory for + executed processes. If set to ~, the home directory of the user specified in + User= is used. If not set, defaults to the root directory when systemd is running as a + system instance and the respective user's home directory if run as user. If the setting is prefixed with the + - character, a missing working directory is not considered fatal. If + RootDirectory=/RootImage= is not set, then + WorkingDirectory= is relative to the root of the system running the service manager. Note + that setting this parameter might result in additional dependencies to be added to the unit (see + above). + + + + RootDirectory= + + Takes a directory path relative to the host's root directory (i.e. the root of the system + running the service manager). Sets the root directory for executed processes, with the chroot2 system + call. If this is used, it must be ensured that the process binary and all its auxiliary files are available in + the chroot() jail. Note that setting this parameter might result in additional + dependencies to be added to the unit (see above). + + The MountAPIVFS= and PrivateUsers= settings are particularly useful + in conjunction with RootDirectory=. For details, see below. + + + + + + RootImage= + + Takes a path to a block device node or regular file as argument. This call is similar to + RootDirectory= however mounts a file system hierarchy from a block device node or loopback + file instead of a directory. The device node or file system image file needs to contain a file system without a + partition table, or a file system within an MBR/MS-DOS or GPT partition table with only a single + Linux-compatible partition, or a set of file systems within a GPT partition table that follows the Discoverable Partitions + Specification. + + When DevicePolicy= is set to closed or + strict, or set to auto and DeviceAllow= is + set, then this setting adds /dev/loop-control with rw mode, + block-loop and block-blkext with rwm mode + to DeviceAllow=. See + systemd.resource-control5 + for the details about DevicePolicy= or DeviceAllow=. Also, see + PrivateDevices= below, as it may change the setting of + DevicePolicy=. + + + + + + MountAPIVFS= + + Takes a boolean argument. If on, a private mount namespace for the unit's processes is created + and the API file systems /proc, /sys, and /dev + are mounted inside of it, unless they are already mounted. Note that this option has no effect unless used in + conjunction with RootDirectory=/RootImage= as these three mounts are + generally mounted in the host anyway, and unless the root directory is changed, the private mount namespace + will be a 1:1 copy of the host's, and include these three mounts. Note that the /dev file + system of the host is bind mounted if this option is used without PrivateDevices=. To run + the service with a private, minimal version of /dev/, combine this option with + PrivateDevices=. + + + + + + BindPaths= + BindReadOnlyPaths= + + Configures unit-specific bind mounts. A bind mount makes a particular file or directory + available at an additional place in the unit's view of the file system. Any bind mounts created with this + option are specific to the unit, and are not visible in the host's mount table. This option expects a + whitespace separated list of bind mount definitions. Each definition consists of a colon-separated triple of + source path, destination path and option string, where the latter two are optional. If only a source path is + specified the source and destination is taken to be the same. The option string may be either + rbind or norbind for configuring a recursive or non-recursive bind + mount. If the destination path is omitted, the option string must be omitted too. + Each bind mount definition may be prefixed with -, in which case it will be ignored + when its source path does not exist. + + BindPaths= creates regular writable bind mounts (unless the source file system mount + is already marked read-only), while BindReadOnlyPaths= creates read-only bind mounts. These + settings may be used more than once, each usage appends to the unit's list of bind mounts. If the empty string + is assigned to either of these two options the entire list of bind mounts defined prior to this is reset. Note + that in this case both read-only and regular bind mounts are reset, regardless which of the two settings is + used. + + This option is particularly useful when RootDirectory=/RootImage= + is used. In this case the source path refers to a path on the host file system, while the destination path + refers to a path below the root directory of the unit. + + Note that the destination directory must exist or systemd must be able to create it. Thus, it + is not possible to use those options for mount points nested underneath paths specified in + InaccessiblePaths=, or under /home/ and other protected + directories if ProtectHome=yes is + specified. TemporaryFileSystem= with :ro or + ProtectHome=tmpfs should be used instead. + + + + + + + + + Credentials + + + + + + + User= + Group= + + Set the UNIX user or group that the processes are executed as, respectively. Takes a single + user or group name, or a numeric ID as argument. For system services (services run by the system service + manager, i.e. managed by PID 1) and for user services of the root user (services managed by root's instance of + systemd --user), the default is root, but User= may be + used to specify a different user. For user services of any other user, switching user identity is not + permitted, hence the only valid setting is the same user the user's service manager is running as. If no group + is set, the default group of the user is used. This setting does not affect commands whose command line is + prefixed with +. + + Note that restrictions on the user/group name syntax are enforced: the specified name must consist only + of the characters a-z, A-Z, 0-9, _ and -, except for the first character + which must be one of a-z, A-Z or _ (i.e. numbers and - are not permitted + as first character). The user/group name must have at least one character, and at most 31. These restrictions + are enforced in order to avoid ambiguities and to ensure user/group names and unit files remain portable among + Linux systems. + + When used in conjunction with DynamicUser= the user/group name specified is + dynamically allocated at the time the service is started, and released at the time the service is stopped — + unless it is already allocated statically (see below). If DynamicUser= is not used the + specified user and group must have been created statically in the user database no later than the moment the + service is started, for example using the + sysusers.d5 facility, which + is applied at boot or package install time. + + If the User= setting is used the supplementary group list is initialized + from the specified user's default group list, as defined in the system's user and group + database. Additional groups may be configured through the SupplementaryGroups= + setting (see below). + + + + DynamicUser= + + Takes a boolean parameter. If set, a UNIX user and group pair is allocated + dynamically when the unit is started, and released as soon as it is stopped. The user and group will + not be added to /etc/passwd or /etc/group, but are managed + transiently during runtime. The + nss-systemd8 glibc + NSS module provides integration of these dynamic users/groups into the system's user and group + databases. The user and group name to use may be configured via User= and + Group= (see above). If these options are not used and dynamic user/group + allocation is enabled for a unit, the name of the dynamic user/group is implicitly derived from the + unit name. If the unit name without the type suffix qualifies as valid user name it is used directly, + otherwise a name incorporating a hash of it is used. If a statically allocated user or group of the + configured name already exists, it is used and no dynamic user/group is allocated. Note that if + User= is specified and the static group with the name exists, then it is required + that the static user with the name already exists. Similarly, if Group= is + specified and the static user with the name exists, then it is required that the static group with + the name already exists. Dynamic users/groups are allocated from the UID/GID range 61184…65519. It is + recommended to avoid this range for regular system or login users. At any point in time each UID/GID + from this range is only assigned to zero or one dynamically allocated users/groups in use. However, + UID/GIDs are recycled after a unit is terminated. Care should be taken that any processes running as + part of a unit for which dynamic users/groups are enabled do not leave files or directories owned by + these users/groups around, as a different unit might get the same UID/GID assigned later on, and thus + gain access to these files or directories. If DynamicUser= is enabled, + RemoveIPC= and PrivateTmp= are implied (and cannot be turned + off). This ensures that the lifetime of IPC objects and temporary files created by the executed + processes is bound to the runtime of the service, and hence the lifetime of the dynamic + user/group. Since /tmp/ and /var/tmp/ are usually the only + world-writable directories on a system this ensures that a unit making use of dynamic user/group + allocation cannot leave files around after unit termination. Furthermore + NoNewPrivileges= and RestrictSUIDSGID= are implicitly enabled + (and cannot be disabled), to ensure that processes invoked cannot take benefit or create SUID/SGID + files or directories. Moreover ProtectSystem=strict and + ProtectHome=read-only are implied, thus prohibiting the service to write to + arbitrary file system locations. In order to allow the service to write to certain directories, they + have to be whitelisted using ReadWritePaths=, but care must be taken so that + UID/GID recycling doesn't create security issues involving files created by the service. Use + RuntimeDirectory= (see below) in order to assign a writable runtime directory to a + service, owned by the dynamic user/group and removed automatically when the unit is terminated. Use + StateDirectory=, CacheDirectory= and + LogsDirectory= in order to assign a set of writable directories for specific + purposes to the service in a way that they are protected from vulnerabilities due to UID reuse (see + below). If this option is enabled, care should be taken that the unit's processes do not get access + to directories outside of these explicitly configured and managed ones. Specifically, do not use + BindPaths= and be careful with AF_UNIX file descriptor + passing for directory file descriptors, as this would permit processes to create files or directories + owned by the dynamic user/group that are not subject to the lifecycle and access guarantees of the + service. Defaults to off. + + + + SupplementaryGroups= + + Sets the supplementary Unix groups the processes are executed as. This takes a space-separated + list of group names or IDs. This option may be specified more than once, in which case all listed groups are + set as supplementary groups. When the empty string is assigned, the list of supplementary groups is reset, and + all assignments prior to this one will have no effect. In any way, this option does not override, but extends + the list of supplementary groups configured in the system group database for the user. This does not affect + commands prefixed with +. + + + + PAMName= + + Sets the PAM service name to set up a session as. If set, the executed process will be + registered as a PAM session under the specified service name. This is only useful in conjunction with the + User= setting, and is otherwise ignored. If not set, no PAM session will be opened for the + executed processes. See pam8 for + details. + + Note that for each unit making use of this option a PAM session handler process will be maintained as + part of the unit and stays around as long as the unit is active, to ensure that appropriate actions can be + taken when the unit and hence the PAM session terminates. This process is named (sd-pam) and + is an immediate child process of the unit's main process. + + Note that when this option is used for a unit it is very likely (depending on PAM configuration) that the + main unit process will be migrated to its own session scope unit when it is activated. This process will hence + be associated with two units: the unit it was originally started from (and for which + PAMName= was configured), and the session scope unit. Any child processes of that process + will however be associated with the session scope unit only. This has implications when used in combination + with NotifyAccess=, as these child processes will not be able to affect + changes in the original unit through notification messages. These messages will be considered belonging to the + session scope unit and not the original unit. It is hence not recommended to use PAMName= in + combination with NotifyAccess=. + + + + + + + + Capabilities + + + + + + + CapabilityBoundingSet= + + Controls which capabilities to include in the capability bounding set for the executed + process. See capabilities7 for + details. Takes a whitespace-separated list of capability names, e.g. CAP_SYS_ADMIN, + CAP_DAC_OVERRIDE, CAP_SYS_PTRACE. Capabilities listed will be + included in the bounding set, all others are removed. If the list of capabilities is prefixed with + ~, all but the listed capabilities will be included, the effect of the assignment + inverted. Note that this option also affects the respective capabilities in the effective, permitted and + inheritable capability sets. If this option is not used, the capability bounding set is not modified on process + execution, hence no limits on the capabilities of the process are enforced. This option may appear more than + once, in which case the bounding sets are merged by OR, or by AND if + the lines are prefixed with ~ (see below). If the empty string is assigned to this option, + the bounding set is reset to the empty capability set, and all prior settings have no effect. If set to + ~ (without any further argument), the bounding set is reset to the full set of available + capabilities, also undoing any previous settings. This does not affect commands prefixed with + +. + + Example: if a unit has the following, + CapabilityBoundingSet=CAP_A CAP_B +CapabilityBoundingSet=CAP_B CAP_C + then CAP_A, CAP_B, and + CAP_C are set. If the second line is prefixed with + ~, e.g., + CapabilityBoundingSet=CAP_A CAP_B +CapabilityBoundingSet=~CAP_B CAP_C + then, only CAP_A is set. + + + + AmbientCapabilities= + + Controls which capabilities to include in the ambient capability set for the executed + process. Takes a whitespace-separated list of capability names, e.g. CAP_SYS_ADMIN, + CAP_DAC_OVERRIDE, CAP_SYS_PTRACE. This option may appear more than + once in which case the ambient capability sets are merged (see the above examples in + CapabilityBoundingSet=). If the list of capabilities is prefixed with ~, + all but the listed capabilities will be included, the effect of the assignment inverted. If the empty string is + assigned to this option, the ambient capability set is reset to the empty capability set, and all prior + settings have no effect. If set to ~ (without any further argument), the ambient capability + set is reset to the full set of available capabilities, also undoing any previous settings. Note that adding + capabilities to ambient capability set adds them to the process's inherited capability set. + Ambient capability sets are useful if you want to execute a process as a non-privileged user but still want to + give it some capabilities. Note that in this case option keep-caps is automatically added + to SecureBits= to retain the capabilities over the user + change. AmbientCapabilities= does not affect commands prefixed with + +. + + + + + + + Security + + + + + NoNewPrivileges= + + Takes a boolean argument. If true, ensures that the service process and all its + children can never gain new privileges through execve() (e.g. via setuid or + setgid bits, or filesystem capabilities). This is the simplest and most effective way to ensure that + a process and its children can never elevate privileges again. Defaults to false, but certain + settings override this and ignore the value of this setting. This is the case when + SystemCallFilter=, SystemCallArchitectures=, + RestrictAddressFamilies=, RestrictNamespaces=, + PrivateDevices=, ProtectKernelTunables=, + ProtectKernelModules=, ProtectKernelLogs=, + MemoryDenyWriteExecute=, RestrictRealtime=, + RestrictSUIDSGID=, DynamicUser= or LockPersonality= + are specified. Note that even if this setting is overridden by them, systemctl show shows the + original value of this setting. Also see No New Privileges + Flag. + + + + SecureBits= + + Controls the secure bits set for the executed process. Takes a space-separated combination of + options from the following list: , , + , , , and + . This option may appear more than once, in which case the secure bits are + ORed. If the empty string is assigned to this option, the bits are reset to 0. This does not affect commands + prefixed with +. See capabilities7 for + details. + + + + + + + Mandatory Access Control + + + + + + + SELinuxContext= + + Set the SELinux security context of the executed process. If set, this will override the + automated domain transition. However, the policy still needs to authorize the transition. This directive is + ignored if SELinux is disabled. If prefixed by -, all errors will be ignored. This does not + affect commands prefixed with +. See setexeccon3 for + details. + + + + AppArmorProfile= + + Takes a profile name as argument. The process executed by the unit will switch to this profile + when started. Profiles must already be loaded in the kernel, or the unit will fail. This result in a non + operation if AppArmor is not enabled. If prefixed by -, all errors will be ignored. This + does not affect commands prefixed with +. + + + + SmackProcessLabel= + + Takes a security label as argument. The process executed by the unit + will be started under this label and SMACK will decide whether the process is allowed to run or not, based on + it. The process will continue to run under the label specified here unless the executable has its own + label, in which case the process will transition to run under that label. When not + specified, the label that systemd is running under is used. This directive is ignored if SMACK is + disabled. + + The value may be prefixed by -, in which case all errors will be ignored. An empty + value may be specified to unset previous assignments. This does not affect commands prefixed with + +. + + + + + + + Process Properties + + + + + LimitCPU= + LimitFSIZE= + LimitDATA= + LimitSTACK= + LimitCORE= + LimitRSS= + LimitNOFILE= + LimitAS= + LimitNPROC= + LimitMEMLOCK= + LimitLOCKS= + LimitSIGPENDING= + LimitMSGQUEUE= + LimitNICE= + LimitRTPRIO= + LimitRTTIME= + + Set soft and hard limits on various resources for executed processes. See + setrlimit2 for details on + the resource limit concept. Resource limits may be specified in two formats: either as single value to set a + specific soft and hard limit to the same value, or as colon-separated pair to set + both limits individually (e.g. LimitAS=4G:16G). Use the string to + configure no limit on a specific resource. The multiplicative suffixes K, M, G, T, P and E (to the base 1024) + may be used for resource limits measured in bytes (e.g. LimitAS=16G). For the limits referring to time values, + the usual time units ms, s, min, h and so on may be used (see + systemd.time7 for + details). Note that if no time unit is specified for LimitCPU= the default unit of seconds + is implied, while for LimitRTTIME= the default unit of microseconds is implied. Also, note + that the effective granularity of the limits might influence their enforcement. For example, time limits + specified for LimitCPU= will be rounded up implicitly to multiples of 1s. For + LimitNICE= the value may be specified in two syntaxes: if prefixed with + + or -, the value is understood as regular Linux nice value in the range -20..19. If not + prefixed like this the value is understood as raw resource limit parameter in the range 0..40 (with 0 being + equivalent to 1). + + Note that most process resource limits configured with these options are per-process, and processes may + fork in order to acquire a new set of resources that are accounted independently of the original process, and + may thus escape limits set. Also note that LimitRSS= is not implemented on Linux, and + setting it has no effect. Often it is advisable to prefer the resource controls listed in + systemd.resource-control5 + over these per-process limits, as they apply to services as a whole, may be altered dynamically at runtime, and + are generally more expressive. For example, MemoryLimit= is a more powerful (and working) + replacement for LimitRSS=. + + For system units these resource limits may be chosen freely. For user units however (i.e. units run by a + per-user instance of + systemd1), these limits are + bound by (possibly more restrictive) per-user limits enforced by the OS. + + Resource limits not configured explicitly for a unit default to the value configured in the various + DefaultLimitCPU=, DefaultLimitFSIZE=, … options available in + systemd-system.conf5, and – + if not configured there – the kernel or per-user defaults, as defined by the OS (the latter only for user + services, see above). + + + Resource limit directives, their equivalent <command>ulimit</command> shell commands and the unit used + + + + + + + + Directive + ulimit equivalent + Unit + + + + + LimitCPU= + ulimit -t + Seconds + + + LimitFSIZE= + ulimit -f + Bytes + + + LimitDATA= + ulimit -d + Bytes + + + LimitSTACK= + ulimit -s + Bytes + + + LimitCORE= + ulimit -c + Bytes + + + LimitRSS= + ulimit -m + Bytes + + + LimitNOFILE= + ulimit -n + Number of File Descriptors + + + LimitAS= + ulimit -v + Bytes + + + LimitNPROC= + ulimit -u + Number of Processes + + + LimitMEMLOCK= + ulimit -l + Bytes + + + LimitLOCKS= + ulimit -x + Number of Locks + + + LimitSIGPENDING= + ulimit -i + Number of Queued Signals + + + LimitMSGQUEUE= + ulimit -q + Bytes + + + LimitNICE= + ulimit -e + Nice Level + + + LimitRTPRIO= + ulimit -r + Realtime Priority + + + LimitRTTIME= + No equivalent + Microseconds + + + +
+
+ + + UMask= + + Controls the file mode creation mask. Takes an access mode in octal notation. See + umask2 for details. Defaults + to 0022. + + + + KeyringMode= + + Controls how the kernel session keyring is set up for the service (see session-keyring7 for + details on the session keyring). Takes one of , , + . If set to no special keyring setup is done, and the kernel's + default behaviour is applied. If is used a new session keyring is allocated when a + service process is invoked, and it is not linked up with any user keyring. This is the recommended setting for + system services, as this ensures that multiple services running under the same system user ID (in particular + the root user) do not share their key material among each other. If is used a new + session keyring is allocated as for , but the user keyring of the user configured with + User= is linked into it, so that keys assigned to the user may be requested by the unit's + processes. In this modes multiple units running processes under the same user ID may share key material. Unless + is selected the unique invocation ID for the unit (see below) is added as a protected + key by the name invocation_id to the newly created session keyring. Defaults to + for services of the system service manager and to for + non-service units and for services of the user service manager. + + + + OOMScoreAdjust= + + Sets the adjustment value for the Linux kernel's Out-Of-Memory (OOM) killer score for + executed processes. Takes an integer between -1000 (to disable OOM killing of processes of this unit) + and 1000 (to make killing of processes of this unit under memory pressure very likely). See proc.txt for details. If + not specified defaults to the OOM score adjustment level of the service manager itself, which is + normally at 0. + + Use the OOMPolicy= setting of service units to configure how the service + manager shall react to the kernel OOM killer terminating a process of the service. See + systemd.service5 + for details. + + + + TimerSlackNSec= + Sets the timer slack in nanoseconds for the executed processes. The timer slack controls the + accuracy of wake-ups triggered by timers. See + prctl2 for more + information. Note that in contrast to most other time span definitions this parameter takes an integer value in + nano-seconds if no unit is specified. The usual time units are understood too. + + + + Personality= + + Controls which kernel architecture uname2 shall report, + when invoked by unit processes. Takes one of the architecture identifiers x86, + x86-64, ppc, ppc-le, ppc64, + ppc64-le, s390 or s390x. Which personality + architectures are supported depends on the system architecture. Usually the 64bit versions of the various + system architectures support their immediate 32bit personality architecture counterpart, but no others. For + example, x86-64 systems support the x86-64 and + x86 personalities but no others. The personality feature is useful when running 32-bit + services on a 64-bit host system. If not specified, the personality is left unmodified and thus reflects the + personality of the host system's kernel. + + + + IgnoreSIGPIPE= + + Takes a boolean argument. If true, causes SIGPIPE to be ignored in the + executed process. Defaults to true because SIGPIPE generally is useful only in shell + pipelines. + + +
+
+ + + Scheduling + + + + + Nice= + + Sets the default nice level (scheduling priority) for executed processes. Takes an integer + between -20 (highest priority) and 19 (lowest priority). See + setpriority2 for + details. + + + + CPUSchedulingPolicy= + + Sets the CPU scheduling policy for executed processes. Takes one of , + , , or . See + sched_setscheduler2 for + details. + + + + CPUSchedulingPriority= + + Sets the CPU scheduling priority for executed processes. The available priority range depends + on the selected CPU scheduling policy (see above). For real-time scheduling policies an integer between 1 + (lowest priority) and 99 (highest priority) can be used. See + sched_setscheduler2 for + details. + + + + CPUSchedulingResetOnFork= + + Takes a boolean argument. If true, elevated CPU scheduling priorities and policies will be + reset when the executed processes fork, and can hence not leak into child processes. See + sched_setscheduler2 for + details. Defaults to false. + + + + CPUAffinity= + + Controls the CPU affinity of the executed processes. Takes a list of CPU indices or ranges + separated by either whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated + by a dash. This option may be specified more than once, in which case the specified CPU affinity masks are + merged. If the empty string is assigned, the mask is reset, all assignments prior to this will have no + effect. See + sched_setaffinity2 for + details. + + + + NUMAPolicy= + + Controls the NUMA memory policy of the executed processes. Takes a policy type, one of: + , , , and + . A list of NUMA nodes that should be associated with the policy must be specified + in NUMAMask=. For more details on each policy please see, + set_mempolicy2. For overall + overview of NUMA support in Linux see, + numa7 + + + + + NUMAMask= + + Controls the NUMA node list which will be applied alongside with selected NUMA policy. + Takes a list of NUMA nodes and has the same syntax as a list of CPUs for CPUAffinity= + option. Note that the list of NUMA nodes is not required for and + policies and for policy we expect a single NUMA node. + + + + IOSchedulingClass= + + Sets the I/O scheduling class for executed processes. Takes an integer between 0 and 3 or one + of the strings , , or + . If the empty string is assigned to this option, all prior assignments to both + IOSchedulingClass= and IOSchedulingPriority= have no effect. See + ioprio_set2 for + details. + + + + IOSchedulingPriority= + + Sets the I/O scheduling priority for executed processes. Takes an integer between 0 (highest + priority) and 7 (lowest priority). The available priorities depend on the selected I/O scheduling class (see + above). If the empty string is assigned to this option, all prior assignments to both + IOSchedulingClass= and IOSchedulingPriority= have no effect. + See ioprio_set2 for + details. + + + + + + + Sandboxing + + The following sandboxing options are an effective way to limit the exposure of the system towards the unit's + processes. It is recommended to turn on as many of these options for each unit as is possible without negatively + affecting the process' ability to operate. Note that many of these sandboxing features are gracefully turned off on + systems where the underlying security mechanism is not available. For example, ProtectSystem= + has no effect if the kernel is built without file system namespacing or if the service manager runs in a container + manager that makes file system namespacing unavailable to its payload. Similar, + RestrictRealtime= has no effect on systems that lack support for SECCOMP system call filtering, + or in containers where support for this is turned off. + + Also note that some sandboxing functionality is generally not available in user services (i.e. services run + by the per-user service manager). Specifically, the various settings requiring file system namespacing support + (such as ProtectSystem=) are not available, as the underlying kernel functionality is only + accessible to privileged processes. + + + + + ProtectSystem= + + Takes a boolean argument or the special values full or + strict. If true, mounts the /usr and /boot + directories read-only for processes invoked by this unit. If set to full, the + /etc directory is mounted read-only, too. If set to strict the entire + file system hierarchy is mounted read-only, except for the API file system subtrees /dev, + /proc and /sys (protect these directories using + PrivateDevices=, ProtectKernelTunables=, + ProtectControlGroups=). This setting ensures that any modification of the vendor-supplied + operating system (and optionally its configuration, and local mounts) is prohibited for the service. It is + recommended to enable this setting for all long-running services, unless they are involved with system updates + or need to modify the operating system in other ways. If this option is used, + ReadWritePaths= may be used to exclude specific directories from being made read-only. This + setting is implied if DynamicUser= is set. This setting cannot ensure protection in all + cases. In general it has the same limitations as ReadOnlyPaths=, see below. Defaults to + off. + + + + ProtectHome= + + Takes a boolean argument or the special values read-only or + tmpfs. If true, the directories /home, + /root, and /run/user are made inaccessible and empty for + processes invoked by this unit. If set to read-only, the three directories are + made read-only instead. If set to tmpfs, temporary file systems are mounted on the + three directories in read-only mode. The value tmpfs is useful to hide home + directories not relevant to the processes invoked by the unit, while still allowing necessary + directories to be made visible when listed in BindPaths= or + BindReadOnlyPaths=. + + Setting this to yes is mostly equivalent to set the three directories in + InaccessiblePaths=. Similarly, read-only is mostly equivalent to + ReadOnlyPaths=, and tmpfs is mostly equivalent to + TemporaryFileSystem= with :ro. + + It is recommended to enable this setting for all long-running services (in particular + network-facing ones), to ensure they cannot get access to private user data, unless the services + actually require access to the user's private data. This setting is implied if + DynamicUser= is set. This setting cannot ensure protection in all cases. In + general it has the same limitations as ReadOnlyPaths=, see below. + + + + + + RuntimeDirectory= + StateDirectory= + CacheDirectory= + LogsDirectory= + ConfigurationDirectory= + + These options take a whitespace-separated list of directory names. The specified directory + names must be relative, and may not include ... If set, one or more + directories by the specified names will be created (including their parents) below the locations + defined in the following table, when the unit is started. Also, the corresponding environment variable + is defined with the full path of directories. If multiple directories are set, then in the environment variable + the paths are concatenated with colon (:). + + Automatic directory creation and environment variables + + + + Directory + Below path for system units + Below path for user units + Environment variable set + + + + + RuntimeDirectory= + /run/ + $XDG_RUNTIME_DIR + $RUNTIME_DIRECTORY + + + StateDirectory= + /var/lib/ + $XDG_CONFIG_HOME + $STATE_DIRECTORY + + + CacheDirectory= + /var/cache/ + $XDG_CACHE_HOME + $CACHE_DIRECTORY + + + LogsDirectory= + /var/log/ + $XDG_CONFIG_HOME/log/ + $LOGS_DIRECTORY + + + ConfigurationDirectory= + /etc/ + $XDG_CONFIG_HOME + $CONFIGURATION_DIRECTORY + + + +
+ + In case of RuntimeDirectory= the innermost subdirectories are removed when + the unit is stopped. It is possible to preserve the specified directories in this case if + RuntimeDirectoryPreserve= is configured to or + (see below). The directories specified with StateDirectory=, + CacheDirectory=, LogsDirectory=, + ConfigurationDirectory= are not removed when the unit is stopped. + + Except in case of ConfigurationDirectory=, the innermost specified directories will be + owned by the user and group specified in User= and Group=. If the + specified directories already exist and their owning user or group do not match the configured ones, all files + and directories below the specified directories as well as the directories themselves will have their file + ownership recursively changed to match what is configured. As an optimization, if the specified directories are + already owned by the right user and group, files and directories below of them are left as-is, even if they do + not match what is requested. The innermost specified directories will have their access mode adjusted to the + what is specified in RuntimeDirectoryMode=, StateDirectoryMode=, + CacheDirectoryMode=, LogsDirectoryMode= and + ConfigurationDirectoryMode=. + + These options imply BindPaths= for the specified paths. When combined with + RootDirectory= or RootImage= these paths always reside on the host and + are mounted from there into the unit's file system namespace. + + If DynamicUser= is used in conjunction with StateDirectory=, + CacheDirectory= and LogsDirectory= is slightly altered: the directories + are created below /var/lib/private, /var/cache/private and + /var/log/private, respectively, which are host directories made inaccessible to + unprivileged users, which ensures that access to these directories cannot be gained through dynamic user ID + recycling. Symbolic links are created to hide this difference in behaviour. Both from perspective of the host + and from inside the unit, the relevant directories hence always appear directly below + /var/lib, /var/cache and /var/log. + + Use RuntimeDirectory= to manage one or more runtime directories for the unit and bind + their lifetime to the daemon runtime. This is particularly useful for unprivileged daemons that cannot create + runtime directories in /run due to lack of privileges, and to make sure the runtime + directory is cleaned up automatically after use. For runtime directories that require more complex or different + configuration or lifetime guarantees, please consider using + tmpfiles.d5. + + The directories defined by these options are always created under the standard paths used by systemd + (/var, /run, /etc, …). If the service needs + directories in a different location, a different mechanism has to be used to create them. + + tmpfiles.d5 provides + functionality that overlaps with these options. Using these options is recommended, because the lifetime of + the directories is tied directly to the lifetime of the unit, and it is not necessary to ensure that the + tmpfiles.d configuration is executed before the unit is started. + + To remove any of the directories created by these settings, use the systemctl clean + … command on the relevant units, see + systemctl1 for + details. + + Example: if a system service unit has the following, + RuntimeDirectory=foo/bar baz + the service manager creates /run/foo (if it does not exist), + + /run/foo/bar, and /run/baz. The + directories /run/foo/bar and + /run/baz except /run/foo are + owned by the user and group specified in User= and Group=, and removed + when the service is stopped. + + Example: if a system service unit has the following, + RuntimeDirectory=foo/bar +StateDirectory=aaa/bbb ccc + then the environment variable RUNTIME_DIRECTORY is set with /run/foo/bar, and + STATE_DIRECTORY is set with /var/lib/aaa/bbb:/var/lib/ccc.
+
+ + + RuntimeDirectoryMode= + StateDirectoryMode= + CacheDirectoryMode= + LogsDirectoryMode= + ConfigurationDirectoryMode= + + Specifies the access mode of the directories specified in RuntimeDirectory=, + StateDirectory=, CacheDirectory=, LogsDirectory=, or + ConfigurationDirectory=, respectively, as an octal number. Defaults to + 0755. See "Permissions" in path_resolution7 for a + discussion of the meaning of permission bits. + + + + RuntimeDirectoryPreserve= + + Takes a boolean argument or . If set to (the + default), the directories specified in RuntimeDirectory= are always removed when the service + stops. If set to the directories are preserved when the service is both automatically + and manually restarted. Here, the automatic restart means the operation specified in + Restart=, and manual restart means the one triggered by systemctl restart + foo.service. If set to , then the directories are not removed when the service is + stopped. Note that since the runtime directory /run is a mount point of + tmpfs, then for system services the directories specified in + RuntimeDirectory= are removed when the system is rebooted. + + + + TimeoutCleanSec= + Configures a timeout on the clean-up operation requested through systemctl + clean …, see + systemctl1 for + details. Takes the usual time values and defaults to infinity, i.e. by default + no time-out is applied. If a time-out is configured the clean operation will be aborted forcibly when + the time-out is reached, potentially leaving resources on disk. + + + + ReadWritePaths= + ReadOnlyPaths= + InaccessiblePaths= + + Sets up a new file system namespace for executed processes. These options may be used to limit + access a process might have to the file system hierarchy. Each setting takes a space-separated list of paths + relative to the host's root directory (i.e. the system running the service manager). Note that if paths + contain symlinks, they are resolved relative to the root directory set with + RootDirectory=/RootImage=. + + Paths listed in ReadWritePaths= are accessible from within the namespace with the same + access modes as from outside of it. Paths listed in ReadOnlyPaths= are accessible for + reading only, writing will be refused even if the usual file access controls would permit this. Nest + ReadWritePaths= inside of ReadOnlyPaths= in order to provide writable + subdirectories within read-only directories. Use ReadWritePaths= in order to whitelist + specific paths for write access if ProtectSystem=strict is used. + + Paths listed in InaccessiblePaths= will be made inaccessible for processes inside + the namespace along with everything below them in the file system hierarchy. This may be more restrictive than + desired, because it is not possible to nest ReadWritePaths=, ReadOnlyPaths=, + BindPaths=, or BindReadOnlyPaths= inside it. For a more flexible option, + see TemporaryFileSystem=. + + Non-directory paths may be specified as well. These options may be specified more than once, + in which case all paths listed will have limited access from within the namespace. If the empty string is + assigned to this option, the specific list is reset, and all prior assignments have no effect. + + Paths in ReadWritePaths=, ReadOnlyPaths= and + InaccessiblePaths= may be prefixed with -, in which case they will be + ignored when they do not exist. If prefixed with + the paths are taken relative to the root + directory of the unit, as configured with RootDirectory=/RootImage=, + instead of relative to the root directory of the host (see above). When combining - and + + on the same path make sure to specify - first, and + + second. + + Note that these settings will disconnect propagation of mounts from the unit's processes to the + host. This means that this setting may not be used for services which shall be able to install mount points in + the main mount namespace. For ReadWritePaths= and ReadOnlyPaths= + propagation in the other direction is not affected, i.e. mounts created on the host generally appear in the + unit processes' namespace, and mounts removed on the host also disappear there too. In particular, note that + mount propagation from host to unit will result in unmodified mounts to be created in the unit's namespace, + i.e. writable mounts appearing on the host will be writable in the unit's namespace too, even when propagated + below a path marked with ReadOnlyPaths=! Restricting access with these options hence does + not extend to submounts of a directory that are created later on. This means the lock-down offered by that + setting is not complete, and does not offer full protection. + + Note that the effect of these settings may be undone by privileged processes. In order to set up an + effective sandboxed environment for a unit it is thus recommended to combine these settings with either + CapabilityBoundingSet=~CAP_SYS_ADMIN or + SystemCallFilter=~@mount. + + + + + + TemporaryFileSystem= + + Takes a space-separated list of mount points for temporary file systems (tmpfs). If set, a new file + system namespace is set up for executed processes, and a temporary file system is mounted on each mount point. + This option may be specified more than once, in which case temporary file systems are mounted on all listed mount + points. If the empty string is assigned to this option, the list is reset, and all prior assignments have no effect. + Each mount point may optionally be suffixed with a colon (:) and mount options such as + size=10% or ro. By default, each temporary file system is mounted + with nodev,strictatime,mode=0755. These can be disabled by explicitly specifying the corresponding + mount options, e.g., dev or nostrictatime. + + This is useful to hide files or directories not relevant to the processes invoked by the unit, while necessary + files or directories can be still accessed by combining with BindPaths= or + BindReadOnlyPaths=: + + Example: if a unit has the following, + TemporaryFileSystem=/var:ro +BindReadOnlyPaths=/var/lib/systemd + then the invoked processes by the unit cannot see any files or directories under /var except for + /var/lib/systemd or its contents. + + + + + + PrivateTmp= + + Takes a boolean argument. If true, sets up a new file system namespace for the executed + processes and mounts private /tmp and /var/tmp directories inside it + that is not shared by processes outside of the namespace. This is useful to secure access to temporary files of + the process, but makes sharing between processes via /tmp or /var/tmp + impossible. If this is enabled, all temporary files created by a service in these directories will be removed + after the service is stopped. Defaults to false. It is possible to run two or more units within the same + private /tmp and /var/tmp namespace by using the + JoinsNamespaceOf= directive, see + systemd.unit5 for + details. This setting is implied if DynamicUser= is set. For this setting the same + restrictions regarding mount propagation and privileges apply as for ReadOnlyPaths= and + related calls, see above. Enabling this setting has the side effect of adding Requires= and + After= dependencies on all mount units necessary to access /tmp and + /var/tmp. Moreover an implicitly After= ordering on + systemd-tmpfiles-setup.service8 + is added. + + Note that the implementation of this setting might be impossible (for example if mount namespaces are not + available), and the unit should be written in a way that does not solely rely on this setting for + security. + + + + + + PrivateDevices= + + Takes a boolean argument. If true, sets up a new /dev mount for the + executed processes and only adds API pseudo devices such as /dev/null, + /dev/zero or /dev/random (as well as the pseudo TTY subsystem) to it, + but no physical devices such as /dev/sda, system memory /dev/mem, + system ports /dev/port and others. This is useful to securely turn off physical device + access by the executed process. Defaults to false. Enabling this option will install a system call filter to + block low-level I/O system calls that are grouped in the @raw-io set, will also remove + CAP_MKNOD and CAP_SYS_RAWIO from the capability bounding set for the + unit (see above), and set DevicePolicy=closed (see + systemd.resource-control5 + for details). Note that using this setting will disconnect propagation of mounts from the service to the host + (propagation in the opposite direction continues to work). This means that this setting may not be used for + services which shall be able to install mount points in the main mount namespace. The new + /dev will be mounted read-only and 'noexec'. The latter may break old programs which try + to set up executable memory by using + mmap2 of + /dev/zero instead of using MAP_ANON. For this setting the same + restrictions regarding mount propagation and privileges apply as for ReadOnlyPaths= and + related calls, see above. If turned on and if running in user mode, or in system mode, but without the + CAP_SYS_ADMIN capability (e.g. setting User=), + NoNewPrivileges=yes is implied. + + Note that the implementation of this setting might be impossible (for example if mount namespaces are not + available), and the unit should be written in a way that does not solely rely on this setting for + security. + + + + + + PrivateNetwork= + + Takes a boolean argument. If true, sets up a new network namespace for the executed processes + and configures only the loopback network device lo inside it. No other network devices will + be available to the executed process. This is useful to turn off network access by the executed process. + Defaults to false. It is possible to run two or more units within the same private network namespace by using + the JoinsNamespaceOf= directive, see + systemd.unit5 for + details. Note that this option will disconnect all socket families from the host, including + AF_NETLINK and AF_UNIX. Effectively, for + AF_NETLINK this means that device configuration events received from + systemd-udevd.service8 are + not delivered to the unit's processes. And for AF_UNIX this has the effect that + AF_UNIX sockets in the abstract socket namespace of the host will become unavailable to + the unit's processes (however, those located in the file system will continue to be accessible). + + Note that the implementation of this setting might be impossible (for example if network namespaces are + not available), and the unit should be written in a way that does not solely rely on this setting for + security. + + When this option is used on a socket unit any sockets bound on behalf of this unit will be + bound within a private network namespace. This may be combined with + JoinsNamespaceOf= to listen on sockets inside of network namespaces of other + services. + + + + + + NetworkNamespacePath= + + Takes an absolute file system path refererring to a Linux network namespace + pseudo-file (i.e. a file like /proc/$PID/ns/net or a bind mount or symlink to + one). When set the invoked processes are added to the network namespace referenced by that path. The + path has to point to a valid namespace file at the moment the processes are forked off. If this + option is used PrivateNetwork= has no effect. If this option is used together with + JoinsNamespaceOf= then it only has an effect if this unit is started before any of + the listed units that have PrivateNetwork= or + NetworkNamespacePath= configured, as otherwise the network namespace of those + units is reused. + + When this option is used on a socket unit any sockets bound on behalf of this unit will be + bound within the specified network namespace. + + + + + + PrivateUsers= + + Takes a boolean argument. If true, sets up a new user namespace for the executed processes and + configures a minimal user and group mapping, that maps the root user and group as well as + the unit's own user and group to themselves and everything else to the nobody user and + group. This is useful to securely detach the user and group databases used by the unit from the rest of the + system, and thus to create an effective sandbox environment. All files, directories, processes, IPC objects and + other resources owned by users/groups not equaling root or the unit's own will stay visible + from within the unit but appear owned by the nobody user and group. If this mode is enabled, + all unit processes are run without privileges in the host user namespace (regardless if the unit's own + user/group is root or not). Specifically this means that the process will have zero process + capabilities on the host's user namespace, but full capabilities within the service's user namespace. Settings + such as CapabilityBoundingSet= will affect only the latter, and there's no way to acquire + additional capabilities in the host's user namespace. Defaults to off. + + This setting is particularly useful in conjunction with + RootDirectory=/RootImage=, as the need to synchronize the user and group + databases in the root directory and on the host is reduced, as the only users and groups who need to be matched + are root, nobody and the unit's own user and group. + + Note that the implementation of this setting might be impossible (for example if user namespaces are not + available), and the unit should be written in a way that does not solely rely on this setting for + security. + + + + + + ProtectHostname= + + Takes a boolean argument. When set, sets up a new UTS namespace for the executed + processes. In addition, changing hostname or domainname is prevented. Defaults to off. + + Note that the implementation of this setting might be impossible (for example if UTS namespaces + are not available), and the unit should be written in a way that does not solely rely on this setting + for security. + + Note that when this option is enabled for a service hostname changes no longer propagate from + the system into the service, it is hence not suitable for services that need to take notice of system + hostname changes dynamically. + + + + + + ProtectKernelTunables= + + Takes a boolean argument. If true, kernel variables accessible through + /proc/sys, /sys, /proc/sysrq-trigger, + /proc/latency_stats, /proc/acpi, + /proc/timer_stats, /proc/fs and /proc/irq will + be made read-only to all processes of the unit. Usually, tunable kernel variables should be initialized only at + boot-time, for example with the + sysctl.d5 mechanism. Few + services need to write to these at runtime; it is hence recommended to turn this on for most services. For this + setting the same restrictions regarding mount propagation and privileges apply as for + ReadOnlyPaths= and related calls, see above. Defaults to off. If turned on and if running + in user mode, or in system mode, but without the CAP_SYS_ADMIN capability (e.g. services + for which User= is set), NoNewPrivileges=yes is implied. Note that this + option does not prevent indirect changes to kernel tunables effected by IPC calls to other processes. However, + InaccessiblePaths= may be used to make relevant IPC file system objects inaccessible. If + ProtectKernelTunables= is set, MountAPIVFS=yes is + implied. + + + + + + ProtectKernelModules= + + Takes a boolean argument. If true, explicit module loading will be denied. This allows + module load and unload operations to be turned off on modular kernels. It is recommended to turn this on for most services + that do not need special file systems or extra kernel modules to work. Defaults to off. Enabling this option + removes CAP_SYS_MODULE from the capability bounding set for the unit, and installs a + system call filter to block module system calls, also /usr/lib/modules is made + inaccessible. For this setting the same restrictions regarding mount propagation and privileges apply as for + ReadOnlyPaths= and related calls, see above. Note that limited automatic module loading due + to user configuration or kernel mapping tables might still happen as side effect of requested user operations, + both privileged and unprivileged. To disable module auto-load feature please see + sysctl.d5 + kernel.modules_disabled mechanism and + /proc/sys/kernel/modules_disabled documentation. If turned on and if running in user + mode, or in system mode, but without the CAP_SYS_ADMIN capability (e.g. setting + User=), NoNewPrivileges=yes is implied. + + + + + + ProtectKernelLogs= + + Takes a boolean argument. If true, access to the kernel log ring buffer will be denied. It is + recommended to turn this on for most services that do not need to read from or write to the kernel log ring + buffer. Enabling this option removes CAP_SYSLOG from the capability bounding set for this + unit, and installs a system call filter to block the + syslog2 + system call (not to be confused with the libc API + syslog3 + for userspace logging). The kernel exposes its log buffer to userspace via /dev/kmsg and + /proc/kmsg. If enabled, these are made inaccessible to all the processes in the unit. + + + + + + ProtectControlGroups= + + Takes a boolean argument. If true, the Linux Control Groups (cgroups7) hierarchies + accessible through /sys/fs/cgroup will be made read-only to all processes of the + unit. Except for container managers no services should require write access to the control groups hierarchies; + it is hence recommended to turn this on for most services. For this setting the same restrictions regarding + mount propagation and privileges apply as for ReadOnlyPaths= and related calls, see + above. Defaults to off. If ProtectControlGroups= is set, MountAPIVFS=yes + is implied. + + + + + + RestrictAddressFamilies= + + Restricts the set of socket address families accessible to the processes of this unit. Takes a + space-separated list of address family names to whitelist, such as AF_UNIX, + AF_INET or AF_INET6. When prefixed with ~ the + listed address families will be applied as blacklist, otherwise as whitelist. Note that this restricts access + to the socket2 system call + only. Sockets passed into the process by other means (for example, by using socket activation with socket + units, see systemd.socket5) + are unaffected. Also, sockets created with socketpair() (which creates connected AF_UNIX + sockets only) are unaffected. Note that this option has no effect on 32-bit x86, s390, s390x, mips, mips-le, + ppc, ppc-le, pcc64, ppc64-le and is ignored (but works correctly on other ABIs, including x86-64). Note that on + systems supporting multiple ABIs (such as x86/x86-64) it is recommended to turn off alternative ABIs for + services, so that they cannot be used to circumvent the restrictions of this option. Specifically, it is + recommended to combine this option with SystemCallArchitectures=native or similar. If + running in user mode, or in system mode, but without the CAP_SYS_ADMIN capability + (e.g. setting User=nobody), NoNewPrivileges=yes is implied. By default, + no restrictions apply, all address families are accessible to processes. If assigned the empty string, any + previous address family restriction changes are undone. This setting does not affect commands prefixed with + +. + + Use this option to limit exposure of processes to remote access, in particular via exotic and sensitive + network protocols, such as AF_PACKET. Note that in most cases, the local + AF_UNIX address family should be included in the configured whitelist as it is frequently + used for local communication, including for + syslog2 + logging. + + + + RestrictNamespaces= + + Restricts access to Linux namespace functionality for the processes of this unit. For details + about Linux namespaces, see namespaces7. Either + takes a boolean argument, or a space-separated list of namespace type identifiers. If false (the default), no + restrictions on namespace creation and switching are made. If true, access to any kind of namespacing is + prohibited. Otherwise, a space-separated list of namespace type identifiers must be specified, consisting of + any combination of: cgroup, ipc, net, + mnt, pid, user and uts. Any + namespace type listed is made accessible to the unit's processes, access to namespace types not listed is + prohibited (whitelisting). By prepending the list with a single tilde character (~) the + effect may be inverted: only the listed namespace types will be made inaccessible, all unlisted ones are + permitted (blacklisting). If the empty string is assigned, the default namespace restrictions are applied, + which is equivalent to false. This option may appear more than once, in which case the namespace types are + merged by OR, or by AND if the lines are prefixed with + ~ (see examples below). Internally, this setting limits access to the + unshare2, + clone2 and + setns2 system calls, taking + the specified flags parameters into account. Note that — if this option is used — in addition to restricting + creation and switching of the specified types of namespaces (or all of them, if true) access to the + setns() system call with a zero flags parameter is prohibited. This setting is only + supported on x86, x86-64, mips, mips-le, mips64, mips64-le, mips64-n32, mips64-le-n32, ppc64, ppc64-le, s390 + and s390x, and enforces no restrictions on other architectures. If running in user mode, or in system mode, but + without the CAP_SYS_ADMIN capability (e.g. setting User=), + NoNewPrivileges=yes is implied. + + Example: if a unit has the following, + RestrictNamespaces=cgroup ipc +RestrictNamespaces=cgroup net + then cgroup, ipc, and net are set. + If the second line is prefixed with ~, e.g., + RestrictNamespaces=cgroup ipc +RestrictNamespaces=~cgroup net + then, only ipc is set. + + + + LockPersonality= + + Takes a boolean argument. If set, locks down the personality2 system + call so that the kernel execution domain may not be changed from the default or the personality selected with + Personality= directive. This may be useful to improve security, because odd personality + emulations may be poorly tested and source of vulnerabilities. If running in user mode, or in system mode, but + without the CAP_SYS_ADMIN capability (e.g. setting User=), + NoNewPrivileges=yes is implied. + + + + MemoryDenyWriteExecute= + + Takes a boolean argument. If set, attempts to create memory mappings that are writable and + executable at the same time, or to change existing memory mappings to become executable, or mapping shared + memory segments as executable are prohibited. Specifically, a system call filter is added that rejects + mmap2 system calls with both + PROT_EXEC and PROT_WRITE set, + mprotect2 or + pkey_mprotect2 system calls + with PROT_EXEC set and + shmat2 system calls with + SHM_EXEC set. Note that this option is incompatible with programs and libraries that + generate program code dynamically at runtime, including JIT execution engines, executable stacks, and code + "trampoline" feature of various C compilers. This option improves service security, as it makes harder for + software exploits to change running code dynamically. However, the protection can be circumvented, if + the service can write to a filesystem, which is not mounted with noexec (such as + /dev/shm), or it can use memfd_create(). This can be + prevented by making such file systems inaccessible to the service + (e.g. InaccessiblePaths=/dev/shm) and installing further system call filters + (SystemCallFilter=~memfd_create). Note that this feature is fully available on + x86-64, and partially on x86. Specifically, the shmat() protection is not + available on x86. Note that on systems supporting multiple ABIs (such as x86/x86-64) it is + recommended to turn off alternative ABIs for services, so that they cannot be used to circumvent the + restrictions of this option. Specifically, it is recommended to combine this option with + SystemCallArchitectures=native or similar. If running in user mode, or in system + mode, but without the CAP_SYS_ADMIN capability (e.g. setting + User=), NoNewPrivileges=yes is implied. + + + + RestrictRealtime= + + Takes a boolean argument. If set, any attempts to enable realtime scheduling in a process of + the unit are refused. This restricts access to realtime task scheduling policies such as + SCHED_FIFO, SCHED_RR or SCHED_DEADLINE. See + sched7 + for details about these scheduling policies. If running in user mode, or in system mode, but without the + CAP_SYS_ADMIN capability (e.g. setting User=), + NoNewPrivileges=yes is implied. Realtime scheduling policies may be used to monopolize CPU + time for longer periods of time, and may hence be used to lock up or otherwise trigger Denial-of-Service + situations on the system. It is hence recommended to restrict access to realtime scheduling to the few programs + that actually require them. Defaults to off. + + + + RestrictSUIDSGID= + + Takes a boolean argument. If set, any attempts to set the set-user-ID (SUID) or + set-group-ID (SGID) bits on files or directories will be denied (for details on these bits see + inode7). If + running in user mode, or in system mode, but without the CAP_SYS_ADMIN + capability (e.g. setting User=), NoNewPrivileges=yes is + implied. As the SUID/SGID bits are mechanisms to elevate privileges, and allows users to acquire the + identity of other users, it is recommended to restrict creation of SUID/SGID files to the few + programs that actually require them. Note that this restricts marking of any type of file system + object with these bits, including both regular files and directories (where the SGID is a different + meaning than for files, see documentation). This option is implied if DynamicUser= + is enabled. Defaults to off. + + + + RemoveIPC= + + Takes a boolean parameter. If set, all System V and POSIX IPC objects owned by the user and + group the processes of this unit are run as are removed when the unit is stopped. This setting only has an + effect if at least one of User=, Group= and + DynamicUser= are used. It has no effect on IPC objects owned by the root user. Specifically, + this removes System V semaphores, as well as System V and POSIX shared memory segments and message queues. If + multiple units use the same user or group the IPC objects are removed when the last of these units is + stopped. This setting is implied if DynamicUser= is set. + + + + + + PrivateMounts= + + Takes a boolean parameter. If set, the processes of this unit will be run in their own private + file system (mount) namespace with all mount propagation from the processes towards the host's main file system + namespace turned off. This means any file system mount points established or removed by the unit's processes + will be private to them and not be visible to the host. However, file system mount points established or + removed on the host will be propagated to the unit's processes. See mount_namespaces7 for + details on file system namespaces. Defaults to off. + + When turned on, this executes three operations for each invoked process: a new + CLONE_NEWNS namespace is created, after which all existing mounts are remounted to + MS_SLAVE to disable propagation from the unit's processes to the host (but leaving + propagation in the opposite direction in effect). Finally, the mounts are remounted again to the propagation + mode configured with MountFlags=, see below. + + File system namespaces are set up individually for each process forked off by the service manager. Mounts + established in the namespace of the process created by ExecStartPre= will hence be cleaned + up automatically as soon as that process exits and will not be available to subsequent processes forked off for + ExecStart= (and similar applies to the various other commands configured for + units). Similarly, JoinsNamespaceOf= does not permit sharing kernel mount namespaces between + units, it only enables sharing of the /tmp/ and /var/tmp/ + directories. + + Other file system namespace unit settings — PrivateMounts=, + PrivateTmp=, PrivateDevices=, ProtectSystem=, + ProtectHome=, ReadOnlyPaths=, InaccessiblePaths=, + ReadWritePaths=, … — also enable file system namespacing in a fashion equivalent to this + option. Hence it is primarily useful to explicitly request this behaviour if none of the other settings are + used. + + + + + + MountFlags= + + Takes a mount propagation setting: , or + , which controls whether file system mount points in the file system namespaces set up + for this unit's processes will receive or propagate mounts and unmounts from other file system namespaces. See + mount2 + for details on mount propagation, and the three propagation flags in particular. + + This setting only controls the final propagation setting in effect on all mount + points of the file system namespace created for each process of this unit. Other file system namespacing unit + settings (see the discussion in PrivateMounts= above) will implicitly disable mount and + unmount propagation from the unit's processes towards the host by changing the propagation setting of all mount + points in the unit's file system namepace to first. Setting this option to + does not reestablish propagation in that case. + + If not set – but file system namespaces are enabled through another file system namespace unit setting – + mount propagation is used, but — as mentioned — as is applied + first, propagation from the unit's processes to the host is still turned off. + + It is not recommended to to use mount propagation for units, as this means + temporary mounts (such as removable media) of the host will stay mounted and thus indefinitely busy in forked + off processes, as unmount propagation events won't be received by the file system namespace of the unit. + + Usually, it is best to leave this setting unmodified, and use higher level file system namespacing + options instead, in particular PrivateMounts=, see above. + + + + +
+
+ + + System Call Filtering + + + + SystemCallFilter= + + Takes a space-separated list of system call names. If this setting is used, all + system calls executed by the unit processes except for the listed ones will result in immediate + process termination with the SIGSYS signal (whitelisting). (See + SystemCallErrorNumber= below for changing the default action). If the first + character of the list is ~, the effect is inverted: only the listed system calls + will result in immediate process termination (blacklisting). Blacklisted system calls and system call + groups may optionally be suffixed with a colon (:) and errno + error number (between 0 and 4095) or errno name such as EPERM, + EACCES or EUCLEAN (see errno3 for a + full list). This value will be returned when a blacklisted system call is triggered, instead of + terminating the processes immediately. This value takes precedence over the one given in + SystemCallErrorNumber=, see below. If running in user mode, or in system mode, + but without the CAP_SYS_ADMIN capability (e.g. setting + User=nobody), NoNewPrivileges=yes is implied. This feature + makes use of the Secure Computing Mode 2 interfaces of the kernel ('seccomp filtering') and is useful + for enforcing a minimal sandboxing environment. Note that the execve, + exit, exit_group, getrlimit, + rt_sigreturn, sigreturn system calls and the system calls + for querying time and sleeping are implicitly whitelisted and do not need to be listed + explicitly. This option may be specified more than once, in which case the filter masks are + merged. If the empty string is assigned, the filter is reset, all prior assignments will have no + effect. This does not affect commands prefixed with +. + + Note that on systems supporting multiple ABIs (such as x86/x86-64) it is recommended to turn off + alternative ABIs for services, so that they cannot be used to circumvent the restrictions of this + option. Specifically, it is recommended to combine this option with + SystemCallArchitectures=native or similar. + + Note that strict system call filters may impact execution and error handling code paths of the service + invocation. Specifically, access to the execve system call is required for the execution + of the service binary — if it is blocked service invocation will necessarily fail. Also, if execution of the + service binary fails for some reason (for example: missing service executable), the error handling logic might + require access to an additional set of system calls in order to process and log this failure correctly. It + might be necessary to temporarily disable system call filters in order to simplify debugging of such + failures. + + If you specify both types of this option (i.e. whitelisting and blacklisting), the first encountered + will take precedence and will dictate the default action (termination or approval of a system call). Then the + next occurrences of this option will add or delete the listed system calls from the set of the filtered system + calls, depending of its type and the default action. (For example, if you have started with a whitelisting of + read and write, and right after it add a blacklisting of + write, then write will be removed from the set.) + + As the number of possible system calls is large, predefined sets of system calls are provided. A set + starts with @ character, followed by name of the set. + + + Currently predefined system call sets + + + + + + + Set + Description + + + + + @aio + Asynchronous I/O (io_setup2, io_submit2, and related calls) + + + @basic-io + System calls for basic I/O: reading, writing, seeking, file descriptor duplication and closing (read2, write2, and related calls) + + + @chown + Changing file ownership (chown2, fchownat2, and related calls) + + + @clock + System calls for changing the system clock (adjtimex2, settimeofday2, and related calls) + + + @cpu-emulation + System calls for CPU emulation functionality (vm862 and related calls) + + + @debug + Debugging, performance monitoring and tracing functionality (ptrace2, perf_event_open2 and related calls) + + + @file-system + File system operations: opening, creating files and directories for read and write, renaming and removing them, reading file properties, or creating hard and symbolic links. + + + @io-event + Event loop system calls (poll2, select2, epoll7, eventfd2 and related calls) + + + @ipc + Pipes, SysV IPC, POSIX Message Queues and other IPC (mq_overview7, svipc7) + + + @keyring + Kernel keyring access (keyctl2 and related calls) + + + @memlock + Locking of memory into RAM (mlock2, mlockall2 and related calls) + + + @module + Loading and unloading of kernel modules (init_module2, delete_module2 and related calls) + + + @mount + Mounting and unmounting of file systems (mount2, chroot2, and related calls) + + + @network-io + Socket I/O (including local AF_UNIX): socket7, unix7 + + + @obsolete + Unusual, obsolete or unimplemented (create_module2, gtty2, …) + + + @privileged + All system calls which need super-user capabilities (capabilities7) + + + @process + Process control, execution, namespaceing operations (clone2, kill2, namespaces7, … + + + @raw-io + Raw I/O port access (ioperm2, iopl2, pciconfig_read(), …) + + + @reboot + System calls for rebooting and reboot preparation (reboot2, kexec(), …) + + + @resources + System calls for changing resource limits, memory and scheduling parameters (setrlimit2, setpriority2, …) + + + @setuid + System calls for changing user ID and group ID credentials, (setuid2, setgid2, setresuid2, …) + + + @signal + System calls for manipulating and handling process signals (signal2, sigprocmask2, …) + + + @swap + System calls for enabling/disabling swap devices (swapon2, swapoff2) + + + @sync + Synchronizing files and memory to disk: (fsync2, msync2, and related calls) + + + @system-service + A reasonable set of system calls used by common system services, excluding any special purpose calls. This is the recommended starting point for whitelisting system calls for system services, as it contains what is typically needed by system services, but excludes overly specific interfaces. For example, the following APIs are excluded: @clock, @mount, @swap, @reboot. + + + @timer + System calls for scheduling operations by time (alarm2, timer_create2, …) + + + +
+ + Note, that as new system calls are added to the kernel, additional system calls might be added to the groups + above. Contents of the sets may also change between systemd versions. In addition, the list of system calls + depends on the kernel version and architecture for which systemd was compiled. Use + systemd-analyze syscall-filter to list the actual list of system calls in each + filter.
+ + Generally, whitelisting system calls (rather than blacklisting) is the safer mode of operation. It is + recommended to enforce system call whitelists for all long-running system services. Specifically, the + following lines are a relatively safe basic choice for the majority of system services: + + [Service] +SystemCallFilter=@system-service +SystemCallErrorNumber=EPERM + + Note that various kernel system calls are defined redundantly: there are multiple system calls + for executing the same operation. For example, the pidfd_send_signal() system + call may be used to execute operations similar to what can be done with the older + kill() system call, hence blocking the latter without the former only provides + weak protection. Since new system calls are added regularly to the kernel as development progresses, + keeping system call blacklists comprehensive requires constant work. It is thus recommended to use + whitelisting instead, which offers the benefit that new system calls are by default implicitly + blocked until the whitelist is updated. + + Also note that a number of system calls are required to be accessible for the dynamic linker to + work. The dynamic linker is required for running most regular programs (specifically: all dynamic ELF + binaries, which is how most distributions build packaged programs). This means that blocking these + system calls (which include open(), openat() or + mmap()) will make most programs typically shipped with generic distributions + unusable. + + It is recommended to combine the file system namespacing related options with + SystemCallFilter=~@mount, in order to prohibit the unit's processes to undo the + mappings. Specifically these are the options PrivateTmp=, + PrivateDevices=, ProtectSystem=, ProtectHome=, + ProtectKernelTunables=, ProtectControlGroups=, + ProtectKernelLogs=, ReadOnlyPaths=, + InaccessiblePaths= and ReadWritePaths=.
+
+ + + SystemCallErrorNumber= + + Takes an errno error number (between 1 and 4095) or errno name + such as EPERM, EACCES or EUCLEAN, to + return when the system call filter configured with SystemCallFilter= is triggered, + instead of terminating the process immediately. See errno3 for a + full list of error codes. When this setting is not used, or when the empty string is assigned, the + process will be terminated immediately when the filter is triggered. + + + + SystemCallArchitectures= + + Takes a space-separated list of architecture identifiers to include in the system call + filter. The known architecture identifiers are the same as for ConditionArchitecture= + described in systemd.unit5, + as well as x32, mips64-n32, mips64-le-n32, and + the special identifier native. The special identifier native + implicitly maps to the native architecture of the system (or more precisely: to the architecture the system + manager is compiled for). If running in user mode, or in system mode, but without the + CAP_SYS_ADMIN capability (e.g. setting User=nobody), + NoNewPrivileges=yes is implied. By default, this option is set to the empty list, i.e. no + system call architecture filtering is applied. + + If this setting is used, processes of this unit will only be permitted to call native system calls, and + system calls of the specified architectures. For the purposes of this option, the x32 architecture is treated + as including x86-64 system calls. However, this setting still fulfills its purpose, as explained below, on + x32. + + System call filtering is not equally effective on all architectures. For example, on x86 + filtering of network socket-related calls is not possible, due to ABI limitations — a limitation that x86-64 + does not have, however. On systems supporting multiple ABIs at the same time — such as x86/x86-64 — it is hence + recommended to limit the set of permitted system call architectures so that secondary ABIs may not be used to + circumvent the restrictions applied to the native ABI of the system. In particular, setting + SystemCallArchitectures=native is a good choice for disabling non-native ABIs. + + System call architectures may also be restricted system-wide via the + SystemCallArchitectures= option in the global configuration. See + systemd-system.conf5 for + details. + + +
+
+ + + Environment + + + + + Environment= + + Sets environment variables for executed processes. Takes a space-separated list of variable + assignments. This option may be specified more than once, in which case all listed variables will be set. If + the same variable is set twice, the later setting will override the earlier setting. If the empty string is + assigned to this option, the list of environment variables is reset, all prior assignments have no + effect. Variable expansion is not performed inside the strings, however, specifier expansion is possible. The $ + character has no special meaning. If you need to assign a value containing spaces or the equals sign to a + variable, use double quotes (") for the assignment. + + Example: + Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" + gives three variables VAR1, + VAR2, VAR3 + with the values word1 word2, + word3, $word 5 6. + + + + See environ7 for details + about environment variables. + + Note that environment variables are not suitable for passing secrets (such as passwords, key material, …) + to service processes. Environment variables set for a unit are exposed to unprivileged clients via D-Bus IPC, + and generally not understood as being data that requires protection. Moreover, environment variables are + propagated down the process tree, including across security boundaries (such as setuid/setgid executables), and + hence might leak to processes that should not have access to the secret data. + + + + EnvironmentFile= + + Similar to Environment= but reads the environment variables from a text + file. The text file should contain new-line-separated variable assignments. Empty lines, lines without an + = separator, or lines starting with ; or # will be ignored, which may be used for + commenting. A line ending with a backslash will be concatenated with the following one, allowing multiline + variable definitions. The parser strips leading and trailing whitespace from the values of assignments, unless + you use double quotes ("). + + C escapes + are supported, but not + most control characters. + \t and \n can be used to insert tabs and newlines within + EnvironmentFile=. + + The argument passed should be an absolute filename or wildcard expression, optionally prefixed with + -, which indicates that if the file does not exist, it will not be read and no error or + warning message is logged. This option may be specified more than once in which case all specified files are + read. If the empty string is assigned to this option, the list of file to read is reset, all prior assignments + have no effect. + + The files listed with this directive will be read shortly before the process is executed (more + specifically, after all processes from a previous unit state terminated. This means you can generate these + files in one unit state, and read it with this option in the next. The files are read from the file + system of the service manager, before any file system changes like bind mounts take place). + + Settings from these files override settings made with Environment=. If the same + variable is set twice from these files, the files will be read in the order they are specified and the later + setting will override the earlier setting. + + + + PassEnvironment= + + Pass environment variables set for the system service manager to executed processes. Takes a + space-separated list of variable names. This option may be specified more than once, in which case all listed + variables will be passed. If the empty string is assigned to this option, the list of environment variables to + pass is reset, all prior assignments have no effect. Variables specified that are not set for the system + manager will not be passed and will be silently ignored. Note that this option is only relevant for the system + service manager, as system services by default do not automatically inherit any environment variables set for + the service manager itself. However, in case of the user service manager all environment variables are passed + to the executed processes anyway, hence this option is without effect for the user service manager. + + Variables set for invoked processes due to this setting are subject to being overridden by those + configured with Environment= or EnvironmentFile=. + + C escapes + are supported, but not + most control characters. + \t and \n can be used to insert tabs and newlines within + EnvironmentFile=. + + Example: + PassEnvironment=VAR1 VAR2 VAR3 + passes three variables VAR1, + VAR2, VAR3 + with the values set for those variables in PID1. + + + See environ7 for details + about environment variables. + + + + UnsetEnvironment= + + Explicitly unset environment variable assignments that would normally be passed from the + service manager to invoked processes of this unit. Takes a space-separated list of variable names or variable + assignments. This option may be specified more than once, in which case all listed variables/assignments will + be unset. If the empty string is assigned to this option, the list of environment variables/assignments to + unset is reset. If a variable assignment is specified (that is: a variable name, followed by + =, followed by its value), then any environment variable matching this precise assignment is + removed. If a variable name is specified (that is a variable name without any following = or + value), then any assignment matching the variable name, regardless of its value is removed. Note that the + effect of UnsetEnvironment= is applied as final step when the environment list passed to + executed processes is compiled. That means it may undo assignments from any configuration source, including + assignments made through Environment= or EnvironmentFile=, inherited from + the system manager's global set of environment variables, inherited via PassEnvironment=, + set by the service manager itself (such as $NOTIFY_SOCKET and such), or set by a PAM module + (in case PAMName= is used). + + + See environ7 for details + about environment variables. + + + + + + + Logging and Standard Input/Output + + + + + StandardInput= + + Controls where file descriptor 0 (STDIN) of the executed processes is connected to. Takes one + of , , , , + , , or + . + + If is selected, standard input will be connected to /dev/null, + i.e. all read attempts by the process will result in immediate EOF. + + If is selected, standard input is connected to a TTY (as configured by + TTYPath=, see below) and the executed process becomes the controlling process of the + terminal. If the terminal is already being controlled by another process, the executed process waits until the + current controlling process releases the terminal. + + is similar to , but the executed process is forcefully and + immediately made the controlling process of the terminal, potentially removing previous controlling processes + from the terminal. + + is similar to , but if the terminal already has a + controlling process start-up of the executed process fails. + + The option may be used to configure arbitrary textual or binary data to pass via + standard input to the executed process. The data to pass is configured via + StandardInputText=/StandardInputData= (see below). Note that the actual + file descriptor type passed (memory file, regular file, UNIX pipe, …) might depend on the kernel and available + privileges. In any case, the file descriptor is read-only, and when read returns the specified data followed by + EOF. + + The option may be used to connect a specific file + system object to standard input. An absolute path following the : character is expected, + which may refer to a regular file, a FIFO or special file. If an AF_UNIX socket in the + file system is specified, a stream socket is connected to it. The latter is useful for connecting standard + input of processes to arbitrary system services. + + The option is valid in socket-activated services only, and requires the relevant + socket unit file (see + systemd.socket5 for details) + to have Accept=yes set, or to specify a single socket only. If this option is set, standard + input will be connected to the socket the service was activated from, which is primarily useful for + compatibility with daemons designed for use with the traditional inetd8 socket activation + daemon. + + The option connects standard input to a specific, + named file descriptor provided by a socket unit. The name may be specified as part of this option, following a + : character (e.g. fd:foobar). If no name is specified, the name + stdin is implied (i.e. fd is equivalent to fd:stdin). + At least one socket unit defining the specified name must be provided via the Sockets= + option, and the file descriptor name may differ from the name of its containing socket unit. If multiple + matches are found, the first one will be used. See FileDescriptorName= in + systemd.socket5 for more + details about named file descriptors and their ordering. + + This setting defaults to . + + Note that services which specify and use + StandardInput= or StandardOutput= with + //, should specify + , to make sure that the tty initialization is + finished before they start. + + + + StandardOutput= + + Controls where file descriptor 1 (stdout) of the executed processes is connected + to. Takes one of , , , + , , , + , , + , or + . + + duplicates the file descriptor of standard input for standard output. + + connects standard output to /dev/null, i.e. everything written + to it will be lost. + + connects standard output to a tty (as configured via TTYPath=, + see below). If the TTY is used for output only, the executed process will not become the controlling process of + the terminal, and will not fail or wait for other processes to release the terminal. + + connects standard output with the journal, which is accessible via + journalctl1. Note + that everything that is written to kmsg (see below) is implicitly stored in the journal as well, the + specific option listed below is hence a superset of this one. (Also note that any external, + additional syslog daemons receive their log data from the journal, too, hence this is the option to + use when logging shall be processed with such a daemon.) + + connects standard output with the kernel log buffer which is accessible via + dmesg1, + in addition to the journal. The journal daemon might be configured to send all logs to kmsg anyway, in which + case this option is no different from . + + and work in a similar way as the + two options above but copy the output to the system console as well. + + The option may be used to connect a specific file + system object to standard output. The semantics are similar to the same option of + StandardInput=, see above. If path refers to a regular file + on the filesystem, it is opened (created if it doesn't exist yet) for writing at the beginning of the file, + but without truncating it. + If standard input and output are directed to the same file path, it is opened only once, for reading as well + as writing and duplicated. This is particularly useful when the specified path refers to an + AF_UNIX socket in the file system, as in that case only a + single stream connection is created for both input and output. + + is similar to above, but it opens the file in append mode. + + connects standard output to a socket acquired via socket activation. The + semantics are similar to the same option of StandardInput=, see above. + + The option connects standard output to a specific, + named file descriptor provided by a socket unit. A name may be specified as part of this option, following a + : character (e.g. fd:foobar). If no name is specified, the name + stdout is implied (i.e. fd is equivalent to + fd:stdout). At least one socket unit defining the specified name must be provided via the + Sockets= option, and the file descriptor name may differ from the name of its containing + socket unit. If multiple matches are found, the first one will be used. See + FileDescriptorName= in + systemd.socket5 for more + details about named descriptors and their ordering. + + If the standard output (or error output, see below) of a unit is connected to the journal or + the kernel log buffer, the unit will implicitly gain a dependency of type After= + on systemd-journald.socket (also see the "Implicit Dependencies" section + above). Also note that in this case stdout (or stderr, see below) will be an + AF_UNIX stream socket, and not a pipe or FIFO that can be re-opened. This means + when executing shell scripts the construct echo "hello" > /dev/stderr for + writing text to stderr will not work. To mitigate this use the construct echo "hello" + >&2 instead, which is mostly equivalent and avoids this pitfall. + + This setting defaults to the value set with DefaultStandardOutput= in + systemd-system.conf5, which + defaults to . Note that setting this parameter might result in additional dependencies + to be added to the unit (see above). + + + + StandardError= + + Controls where file descriptor 2 (stderr) of the executed processes is connected to. The + available options are identical to those of StandardOutput=, with some exceptions: if set to + the file descriptor used for standard output is duplicated for standard error, while + will use a default file descriptor name of + stderr. + + This setting defaults to the value set with DefaultStandardError= in + systemd-system.conf5, which + defaults to . Note that setting this parameter might result in additional dependencies + to be added to the unit (see above). + + + + StandardInputText= + StandardInputData= + + Configures arbitrary textual or binary data to pass via file descriptor 0 (STDIN) to the + executed processes. These settings have no effect unless StandardInput= is set to + . Use this option to embed process input data directly in the unit file. + + StandardInputText= accepts arbitrary textual data. C-style escapes for special + characters as well as the usual %-specifiers are resolved. Each time this setting is used + the specified text is appended to the per-unit data buffer, followed by a newline character (thus every use + appends a new line to the end of the buffer). Note that leading and trailing whitespace of lines configured + with this option is removed. If an empty line is specified the buffer is cleared (hence, in order to insert an + empty line, add an additional \n to the end or beginning of a line). + + StandardInputData= accepts arbitrary binary data, encoded in Base64. No escape sequences or specifiers are + resolved. Any whitespace in the encoded version is ignored during decoding. + + Note that StandardInputText= and StandardInputData= operate on the + same data buffer, and may be mixed in order to configure both binary and textual data for the same input + stream. The textual or binary data is joined strictly in the order the settings appear in the unit + file. Assigning an empty string to either will reset the data buffer. + + Please keep in mind that in order to maintain readability long unit file settings may be split into + multiple lines, by suffixing each line (except for the last) with a \ character (see + systemd.unit5 for + details). This is particularly useful for large data configured with these two options. Example: + + … +StandardInput=data +StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy4KSWNrIGtpZWtl \ + LCBzdGF1bmUsIHd1bmRyZSBtaXIsCnVmZiBlZW1hbCBqZWh0IHNlIHVmZiBkaWUgVMO8ci4KTmFu \ + dSwgZGVuayBpY2ssIGljayBkZW5rIG5hbnUhCkpldHogaXNzZSB1ZmYsIGVyc2NodCB3YXIgc2Ug \ + enUhCkljayBqZWhlIHJhdXMgdW5kIGJsaWNrZSDigJQKdW5kIHdlciBzdGVodCBkcmF1w59lbj8g \ + SWNrZSEK +… + + + + LogLevelMax= + + Configures filtering by log level of log messages generated by this unit. Takes a + syslog log level, one of (lowest log level, only highest priority + messages), , , , , + , , (highest log level, also lowest priority + messages). See syslog3 for + details. By default no filtering is applied (i.e. the default maximum log level is ). Use + this option to configure the logging system to drop log messages of a specific service above the specified + level. For example, set LogLevelMax= in order to turn off debug logging + of a particularly chatty unit. Note that the configured level is applied to any log messages written by any + of the processes belonging to this unit, sent via any supported logging protocol. The filtering is applied + early in the logging pipeline, before any kind of further processing is done. Moreover, messages which pass + through this filter successfully might still be dropped by filters applied at a later stage in the logging + subsystem. For example, MaxLevelStore= configured in + journald.conf5 might + prohibit messages of higher log levels to be stored on disk, even though the per-unit + LogLevelMax= permitted it to be processed. + + + + LogExtraFields= + + Configures additional log metadata fields to include in all log records generated by + processes associated with this unit. This setting takes one or more journal field assignments in the + format FIELD=VALUE separated by whitespace. See + systemd.journal-fields7 + for details on the journal field concept. Even though the underlying journal implementation permits + binary field values, this setting accepts only valid UTF-8 values. To include space characters in a + journal field value, enclose the assignment in double quotes ("). + The usual specifiers are expanded in all assignments (see below). Note that this setting is not only + useful for attaching additional metadata to log records of a unit, but given that all fields and + values are indexed may also be used to implement cross-unit log record matching. Assign an empty + string to reset the list. + + + + LogRateLimitIntervalSec= + LogRateLimitBurst= + + Configures the rate limiting that is applied to messages generated by this unit. If, in the + time interval defined by LogRateLimitIntervalSec=, more messages than specified in + LogRateLimitBurst= are logged by a service, all further messages within the interval are + dropped until the interval is over. A message about the number of dropped messages is generated. The time + specification for LogRateLimitIntervalSec= may be specified in the following units: "s", + "min", "h", "ms", "us" (see + systemd.time7 for details). + The default settings are set by RateLimitIntervalSec= and RateLimitBurst= + configured in journald.conf5. + + + + + SyslogIdentifier= + + Sets the process name ("syslog tag") to prefix log lines sent to + the logging system or the kernel log buffer with. If not set, defaults to the process name of the + executed process. This option is only useful when StandardOutput= or + StandardError= are set to or (or to + the same settings in combination with ) and only applies to log messages + written to stdout or stderr. + + + + SyslogFacility= + + Sets the syslog facility identifier to use when logging. One of + , , , , + , , , , + , , , , + , , , , + , , or + . See syslog3 for + details. This option is only useful when StandardOutput= or + StandardError= are set to or (or to + the same settings in combination with ), and only applies to log messages + written to stdout or stderr. Defaults to . + + + + SyslogLevel= + + The default syslog log level to use when logging to the logging system or + the kernel log buffer. One of , , , + , , , , + . See syslog3 for + details. This option is only useful when StandardOutput= or + StandardError= are set to or + (or to the same settings in combination with ), and only applies + to log messages written to stdout or stderr. Note that individual lines output by executed processes may be + prefixed with a different log level which can be used to override the default log level specified here. The + interpretation of these prefixes may be disabled with SyslogLevelPrefix=, see below. For + details, see sd-daemon3. + Defaults to . + + + + SyslogLevelPrefix= + + Takes a boolean argument. If true and StandardOutput= or + StandardError= are set to or (or to + the same settings in combination with ), log lines written by the executed + process that are prefixed with a log level will be processed with this log level set but the prefix + removed. If set to false, the interpretation of these prefixes is disabled and the logged lines are + passed on as-is. This only applies to log messages written to stdout or stderr. For details about + this prefixing see + sd-daemon3. + Defaults to true. + + + + TTYPath= + + Sets the terminal device node to use if standard input, output, or error are connected to a TTY + (see above). Defaults to /dev/console. + + + + TTYReset= + + Reset the terminal device specified with TTYPath= before and after + execution. Defaults to no. + + + + TTYVHangup= + + Disconnect all clients which have opened the terminal device specified with + TTYPath= before and after execution. Defaults to no. + + + + TTYVTDisallocate= + + If the terminal device specified with TTYPath= is a virtual console + terminal, try to deallocate the TTY before and after execution. This ensures that the screen and scrollback + buffer is cleared. Defaults to no. + + + + + + System V Compatibility + + + + UtmpIdentifier= + + Takes a four character identifier string for an utmp5 and wtmp entry + for this service. This should only be set for services such as getty implementations (such + as agetty8) where utmp/wtmp + entries must be created and cleared before and after execution, or for services that shall be executed as if + they were run by a getty process (see below). If the configured string is longer than four + characters, it is truncated and the terminal four characters are used. This setting interprets %I style string + replacements. This setting is unset by default, i.e. no utmp/wtmp entries are created or cleaned up for this + service. + + + + UtmpMode= + + Takes one of init, login or user. If + UtmpIdentifier= is set, controls which type of utmp5/wtmp entries + for this service are generated. This setting has no effect unless UtmpIdentifier= is set + too. If init is set, only an INIT_PROCESS entry is generated and the + invoked process must implement a getty-compatible utmp/wtmp logic. If + login is set, first an INIT_PROCESS entry, followed by a + LOGIN_PROCESS entry is generated. In this case, the invoked process must implement a + login1-compatible + utmp/wtmp logic. If user is set, first an INIT_PROCESS entry, then a + LOGIN_PROCESS entry and finally a USER_PROCESS entry is + generated. In this case, the invoked process may be any process that is suitable to be run as session + leader. Defaults to init. + + + + + + + Environment variables in spawned processes + + Processes started by the service manager are executed with an environment variable block assembled from + multiple sources. Processes started by the system service manager generally do not inherit environment variables + set for the service manager itself (but this may be altered via PassEnvironment=), but processes + started by the user service manager instances generally do inherit all environment variables set for the service + manager itself. + + For each invoked process the list of environment variables set is compiled from the following sources: + + + Variables globally configured for the service manager, using the + DefaultEnvironment= setting in + systemd-system.conf5, the kernel command line option systemd.setenv= (see + systemd1) or via + systemctl set-environment (see systemctl1). + + Variables defined by the service manager itself (see the list below) + + Variables set in the service manager's own environment variable block (subject to PassEnvironment= for the system service manager) + + Variables set via Environment= in the unit file + + Variables read from files specified via EnvironmentFile= in the unit file + + Variables set by any PAM modules in case PAMName= is in effect, + cf. pam_env8 + + + If the same environment variables are set by multiple of these sources, the later source — according to the + order of the list above — wins. Note that as final step all variables listed in + UnsetEnvironment= are removed again from the compiled environment variable list, immediately + before it is passed to the executed process. + + The following select environment variables are set or propagated by the service manager for each invoked + process: + + + + $PATH + + Colon-separated list of directories to use when launching + executables. systemd uses a fixed value of + /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin + in the system manager. When compiled for systems with "unmerged /usr" (/bin is + not a symlink to /usr/bin), + :/sbin:/bin is appended. In case of the + the user manager, a different path may be configured by the distribution. It is recommended to not + rely on the order of entries, and have only one program with a given name in + $PATH. + + + + $LANG + + Locale. Can be set in + locale.conf5 + or on the kernel command line (see + systemd1 + and + kernel-command-line7). + + + + + $USER + $LOGNAME + $HOME + $SHELL + + User name (twice), home directory, and the + login shell. The variables are set for the units that have + User= set, which includes user + systemd instances. See + passwd5. + + + + + $INVOCATION_ID + + Contains a randomized, unique 128bit ID identifying each runtime cycle of the unit, formatted + as 32 character hexadecimal string. A new ID is assigned each time the unit changes from an inactive state into + an activating or active state, and may be used to identify this specific runtime cycle, in particular in data + stored offline, such as the journal. The same ID is passed to all processes run as part of the + unit. + + + + $XDG_RUNTIME_DIR + + The directory to use for runtime objects (such as IPC objects) and volatile state. Set for all + services run by the user systemd instance, as well as any system services that use + PAMName= with a PAM stack that includes pam_systemd. See below and + pam_systemd8 for more + information. + + + + $RUNTIME_DIRECTORY + $STATE_DIRECTORY + $CACHE_DIRECTORY + $LOGS_DIRECTORY + $CONFIGURATION_DIRECTORY + + Contains and absolute paths to the directories defined with + RuntimeDirectory=, StateDirectory=, + CacheDirectory=, LogsDirectory=, and + ConfigurationDirectory= when those settings are used. + + + + + $MAINPID + + The PID of the unit's main process if it is + known. This is only set for control processes as invoked by + ExecReload= and similar. + + + + $MANAGERPID + + The PID of the user systemd + instance, set for processes spawned by it. + + + + $LISTEN_FDS + $LISTEN_PID + $LISTEN_FDNAMES + + Information about file descriptors passed to a + service for socket activation. See + sd_listen_fds3. + + + + + $NOTIFY_SOCKET + + The socket + sd_notify() talks to. See + sd_notify3. + + + + + $WATCHDOG_PID + $WATCHDOG_USEC + + Information about watchdog keep-alive notifications. See + sd_watchdog_enabled3. + + + + + $TERM + + Terminal type, set only for units connected to + a terminal (StandardInput=tty, + StandardOutput=tty, or + StandardError=tty). See + termcap5. + + + + + $JOURNAL_STREAM + + If the standard output or standard error output of the executed processes are connected to the + journal (for example, by setting StandardError=journal) $JOURNAL_STREAM + contains the device and inode numbers of the connection file descriptor, formatted in decimal, separated by a + colon (:). This permits invoked processes to safely detect whether their standard output or + standard error output are connected to the journal. The device and inode numbers of the file descriptors should + be compared with the values set in the environment variable to determine whether the process output is still + connected to the journal. Note that it is generally not sufficient to only check whether + $JOURNAL_STREAM is set at all as services might invoke external processes replacing their + standard output or standard error output, without unsetting the environment variable. + + If both standard output and standard error of the executed processes are connected to the journal via a + stream socket, this environment variable will contain information about the standard error stream, as that's + usually the preferred destination for log data. (Note that typically the same stream is used for both standard + output and standard error, hence very likely the environment variable contains device and inode information + matching both stream file descriptors.) + + This environment variable is primarily useful to allow services to optionally upgrade their used log + protocol to the native journal protocol (using + sd_journal_print3 and other + functions) if their standard output or standard error output is connected to the journal anyway, thus enabling + delivery of structured metadata along with logged messages. + + + + $SERVICE_RESULT + + Only defined for the service unit type, this environment variable is passed to all + ExecStop= and ExecStopPost= processes, and encodes the service + "result". Currently, the following values are defined: + + + Defined <varname>$SERVICE_RESULT</varname> values + + + + + + Value + Meaning + + + + + + success + The service ran successfully and exited cleanly. + + + protocol + A protocol violation occurred: the service did not take the steps required by its unit configuration (specifically what is configured in its Type= setting). + + + timeout + One of the steps timed out. + + + exit-code + Service process exited with a non-zero exit code; see $EXIT_CODE below for the actual exit code returned. + + + signal + A service process was terminated abnormally by a signal, without dumping core. See $EXIT_CODE below for the actual signal causing the termination. + + + core-dump + A service process terminated abnormally with a signal and dumped core. See $EXIT_CODE below for the signal causing the termination. + + + watchdog + Watchdog keep-alive ping was enabled for the service, but the deadline was missed. + + + start-limit-hit + A start limit was defined for the unit and it was hit, causing the unit to fail to start. See systemd.unit5's StartLimitIntervalSec= and StartLimitBurst= for details. + + + resources + A catch-all condition in case a system operation failed. + + + +
+ + This environment variable is useful to monitor failure or successful termination of a service. Even + though this variable is available in both ExecStop= and ExecStopPost=, it + is usually a better choice to place monitoring tools in the latter, as the former is only invoked for services + that managed to start up correctly, and the latter covers both services that failed during their start-up and + those which failed during their runtime.
+
+ + + $EXIT_CODE + $EXIT_STATUS + + Only defined for the service unit type, these environment variables are passed to all + ExecStop=, ExecStopPost= processes and contain exit status/code + information of the main process of the service. For the precise definition of the exit code and status, see + wait2. $EXIT_CODE + is one of exited, killed, + dumped. $EXIT_STATUS contains the numeric exit code formatted as string + if $EXIT_CODE is exited, and the signal name in all other cases. Note + that these environment variables are only set if the service manager succeeded to start and identify the main + process of the service. + + + Summary of possible service result variable values + + + + + + + $SERVICE_RESULT + $EXIT_CODE + $EXIT_STATUS + + + + + + success + killed + HUP, INT, TERM, PIPE + + + exited + 0 + + + protocol + not set + not set + + + exited + 0 + + + timeout + killed + TERM, KILL + + + exited + 0, 1, 2, 3, …, 255 + + + exit-code + exited + 1, 2, 3, …, 255 + + + signal + killed + HUP, INT, KILL, … + + + core-dump + dumped + ABRT, SEGV, QUIT, … + + + watchdog + dumped + ABRT + + + killed + TERM, KILL + + + exited + 0, 1, 2, 3, …, 255 + + + exec-condition + exited + 1, 2, 3, 4, …, 254 + + + oom-kill + killed + TERM, KILL + + + start-limit-hit + not set + not set + + + resources + any of the above + any of the above + + + Note: the process may be also terminated by a signal not sent by systemd. In particular the process may send an arbitrary signal to itself in a handler for any of the non-maskable signals. Nevertheless, in the timeout and watchdog rows above only the signals that systemd sends have been included. Moreover, using SuccessExitStatus= additional exit statuses may be declared to indicate clean termination, which is not reflected by this table. + + + +
+ +
+
+ + + $PIDFILE + + The path to the configured PID file, in case the process is forked off on behalf of a + service that uses the PIDFile= setting, see + systemd.service5 + for details. Service code may use this environment variable to automatically generate a PID file at + the location configured in the unit file. This field is set to an absolute path in the file + system. + + +
+ + For system services, when PAMName= is enabled and pam_systemd is part + of the selected PAM stack, additional environment variables defined by systemd may be set for + services. Specifically, these are $XDG_SEAT, $XDG_VTNR, see + pam_systemd8 for details. +
+ + + Process exit codes + + When invoking a unit process the service manager possibly fails to apply the execution parameters configured + with the settings above. In that case the already created service process will exit with a non-zero exit code + before the configured command line is executed. (Or in other words, the child process possibly exits with these + error codes, after having been created by the fork2 system call, but + before the matching execve2 system call is + called.) Specifically, exit codes defined by the C library, by the LSB specification and by the systemd service + manager itself are used. + + The following basic service exit codes are defined by the C library. + + + Basic C library exit codes + + + + Exit Code + Symbolic Name + Description + + + + + 0 + EXIT_SUCCESS + Generic success code. + + + 1 + EXIT_FAILURE + Generic failure or unspecified error. + + + +
+ + The following service exit codes are defined by the LSB specification. + + + + LSB service exit codes + + + + Exit Code + Symbolic Name + Description + + + + + 2 + EXIT_INVALIDARGUMENT + Invalid or excess arguments. + + + 3 + EXIT_NOTIMPLEMENTED + Unimplemented feature. + + + 4 + EXIT_NOPERMISSION + The user has insufficient privileges. + + + 5 + EXIT_NOTINSTALLED + The program is not installed. + + + 6 + EXIT_NOTCONFIGURED + The program is not configured. + + + 7 + EXIT_NOTRUNNING + The program is not running. + + + +
+ + + The LSB specification suggests that error codes 200 and above are reserved for implementations. Some of them are + used by the service manager to indicate problems during process invocation: + + + systemd-specific exit codes + + + + Exit Code + Symbolic Name + Description + + + + + 200 + EXIT_CHDIR + Changing to the requested working directory failed. See WorkingDirectory= above. + + + 201 + EXIT_NICE + Failed to set up process scheduling priority (nice level). See Nice= above. + + + 202 + EXIT_FDS + Failed to close unwanted file descriptors, or to adjust passed file descriptors. + + + 203 + EXIT_EXEC + The actual process execution failed (specifically, the execve2 system call). Most likely this is caused by a missing or non-accessible executable file. + + + 204 + EXIT_MEMORY + Failed to perform an action due to memory shortage. + + + 205 + EXIT_LIMITS + Failed to adjust resource limits. See LimitCPU= and related settings above. + + + 206 + EXIT_OOM_ADJUST + Failed to adjust the OOM setting. See OOMScoreAdjust= above. + + + 207 + EXIT_SIGNAL_MASK + Failed to set process signal mask. + + + 208 + EXIT_STDIN + Failed to set up standard input. See StandardInput= above. + + + 209 + EXIT_STDOUT + Failed to set up standard output. See StandardOutput= above. + + + 210 + EXIT_CHROOT + Failed to change root directory (chroot2). See RootDirectory=/RootImage= above. + + + 211 + EXIT_IOPRIO + Failed to set up IO scheduling priority. See IOSchedulingClass=/IOSchedulingPriority= above. + + + 212 + EXIT_TIMERSLACK + Failed to set up timer slack. See TimerSlackNSec= above. + + + 213 + EXIT_SECUREBITS + Failed to set process secure bits. See SecureBits= above. + + + 214 + EXIT_SETSCHEDULER + Failed to set up CPU scheduling. See CPUSchedulingPolicy=/CPUSchedulingPriority= above. + + + 215 + EXIT_CPUAFFINITY + Failed to set up CPU affinity. See CPUAffinity= above. + + + 216 + EXIT_GROUP + Failed to determine or change group credentials. See Group=/SupplementaryGroups= above. + + + 217 + EXIT_USER + Failed to determine or change user credentials, or to set up user namespacing. See User=/PrivateUsers= above. + + + 218 + EXIT_CAPABILITIES + Failed to drop capabilities, or apply ambient capabilities. See CapabilityBoundingSet=/AmbientCapabilities= above. + + + 219 + EXIT_CGROUP + Setting up the service control group failed. + + + 220 + EXIT_SETSID + Failed to create new process session. + + + 221 + EXIT_CONFIRM + Execution has been cancelled by the user. See the systemd.confirm_spawn= kernel command line setting on kernel-command-line7 for details. + + + 222 + EXIT_STDERR + Failed to set up standard error output. See StandardError= above. + + + 224 + EXIT_PAM + Failed to set up PAM session. See PAMName= above. + + + 225 + EXIT_NETWORK + Failed to set up network namespacing. See PrivateNetwork= above. + + + 226 + EXIT_NAMESPACE + Failed to set up mount namespacing. See ReadOnlyPaths= and related settings above. + + + 227 + EXIT_NO_NEW_PRIVILEGES + Failed to disable new privileges. See NoNewPrivileges=yes above. + + + 228 + EXIT_SECCOMP + Failed to apply system call filters. See SystemCallFilter= and related settings above. + + + 229 + EXIT_SELINUX_CONTEXT + Determining or changing SELinux context failed. See SELinuxContext= above. + + + 230 + EXIT_PERSONALITY + Failed to set up an execution domain (personality). See Personality= above. + + + 231 + EXIT_APPARMOR_PROFILE + Failed to prepare changing AppArmor profile. See AppArmorProfile= above. + + + 232 + EXIT_ADDRESS_FAMILIES + Failed to restrict address families. See RestrictAddressFamilies= above. + + + 233 + EXIT_RUNTIME_DIRECTORY + Setting up runtime directory failed. See RuntimeDirectory= and related settings above. + + + 235 + EXIT_CHOWN + Failed to adjust socket ownership. Used for socket units only. + + + 236 + EXIT_SMACK_PROCESS_LABEL + Failed to set SMACK label. See SmackProcessLabel= above. + + + 237 + EXIT_KEYRING + Failed to set up kernel keyring. + + + 238 + EXIT_STATE_DIRECTORY + Failed to set up unit's state directory. See StateDirectory= above. + + + 239 + EXIT_CACHE_DIRECTORY + Failed to set up unit's cache directory. See CacheDirectory= above. + + + 240 + EXIT_LOGS_DIRECTORY + Failed to set up unit's logging directory. See LogsDirectory= above. + + + 241 + EXIT_CONFIGURATION_DIRECTORY + Failed to set up unit's configuration directory. See ConfigurationDirectory= above. + + + 242 + EXIT_NUMA_POLICY + Failed to set up unit's NUMA memory policy. See NUMAPolicy= and NUMAMask=above. + + + + +
+ + Finally, the BSD operating systems define a set of exit codes, typically defined on Linux systems too: + + + BSD exit codes + + + + Exit Code + Symbolic Name + Description + + + + + 64 + EX_USAGE + Command line usage error + + + 65 + EX_DATAERR + Data format error + + + 66 + EX_NOINPUT + Cannot open input + + + 67 + EX_NOUSER + Addressee unknown + + + 68 + EX_NOHOST + Host name unknown + + + 69 + EX_UNAVAILABLE + Service unavailable + + + 70 + EX_SOFTWARE + internal software error + + + 71 + EX_OSERR + System error (e.g., can't fork) + + + 72 + EX_OSFILE + Critical OS file missing + + + 73 + EX_CANTCREAT + Can't create (user) output file + + + 74 + EX_IOERR + Input/output error + + + 75 + EX_TEMPFAIL + Temporary failure; user is invited to retry + + + 76 + EX_PROTOCOL + Remote error in protocol + + + 77 + EX_NOPERM + Permission denied + + + 78 + EX_CONFIG + Configuration error + + + +
+
+ + + See Also + + systemd1, + systemctl1, + systemd-analyze1, + journalctl1, + systemd-system.conf5, + systemd.unit5, + systemd.service5, + systemd.socket5, + systemd.swap5, + systemd.mount5, + systemd.kill5, + systemd.resource-control5, + systemd.time7, + systemd.directives7, + tmpfiles.d5, + exec3 + + + +
diff --git a/man/systemd.generator.xml b/man/systemd.generator.xml new file mode 100644 index 00000000..dd0b5919 --- /dev/null +++ b/man/systemd.generator.xml @@ -0,0 +1,318 @@ + + +%entities; +]> + + + + + systemd.generator + systemd + + + + systemd.generator + 7 + + + + systemd.generator + systemd unit generators + + + + + /path/to/generator + normal-dir + early-dir + late-dir + + + + /run/systemd/system-generators/* +/etc/systemd/system-generators/* +/usr/local/lib/systemd/system-generators/* +&systemgeneratordir;/* + + + + /run/systemd/user-generators/* +/etc/systemd/user-generators/* +/usr/local/lib/systemd/user-generators/* +&usergeneratordir;/* + + + + + Description + Generators are small executables that live in + &systemgeneratordir;/ and other directories listed above. + systemd1 + will execute those binaries very early at bootup and at configuration reload time + — before unit files are loaded. Their main purpose is to convert configuration + that is not native into dynamically generated unit files. + + Each generator is called with three directory paths that are to be used for + generator output. In these three directories, generators may dynamically generate + unit files (regular ones, instances, as well as templates), unit file + .d/ drop-ins, and create symbolic links to unit files to add + additional dependencies, create aliases, or instantiate existing templates. Those + directories are included in the unit load path of + systemd1, + allowing generated configuration to extend or override existing + definitions. + + Directory paths for generator output differ by priority: + …/generator.early has priority higher than the admin + configuration in /etc, while + …/generator has lower priority than + /etc but higher than vendor configuration in + /usr, and …/generator.late has priority + lower than all other configuration. See the next section and the discussion of + unit load paths and unit overriding in + systemd.unit5. + + + Generators are loaded from a set of paths determined during + compilation, as listed above. System and user generators are loaded + from directories with names ending in + system-generators/ and + user-generators/, respectively. Generators + found in directories listed earlier override the ones with the + same name in directories lower in the list. A symlink to + /dev/null or an empty file can be used to + mask a generator, thereby preventing it from running. Please note + that the order of the two directories with the highest priority is + reversed with respect to the unit load path, and generators in + /run overwrite those in + /etc. + + After installing new generators or updating the + configuration, systemctl daemon-reload may be + executed. This will delete the previous configuration created by + generators, re-run all generators, and cause + systemd to reload units from disk. See + systemctl1 + for more information. + + + + + Output directories + + Generators are invoked with three arguments: paths to directories where + generators can place their generated unit files or symlinks. By default those + paths are runtime directories that are included in the search path of + systemd, but a generator may be called with different paths + for debugging purposes. + + + + normal-dir + In normal use this is /run/systemd/generator in + case of the system generators and + $XDG_RUNTIME_DIR/generator in case of the user + generators. Unit files placed in this directory take precedence over vendor + unit configuration but not over native user/administrator unit configuration. + + + + + early-dir + In normal use this is /run/systemd/generator.early + in case of the system generators and + $XDG_RUNTIME_DIR/generator.early in case of the user + generators. Unit files placed in this directory override unit files in + /usr, /run and + /etc. This means that unit files placed in this + directory take precedence over all normal configuration, both vendor and + user/administrator. + + + + late-dir + In normal use this is /run/systemd/generator.late + in case of the system generators and + $XDG_RUNTIME_DIR/generator.late in case of the user + generators. This directory may be used to extend the unit file tree without + overriding any other unit files. Any native configuration files supplied by + the vendor or user/administrator take precedence. + + + + + + Notes about writing generators + + + + All generators are executed in parallel. That means all executables are + started at the very same time and need to be able to cope with this + parallelism. + + + + + Generators are run very early at boot and cannot rely on any external + services. They may not talk to any other process. That includes simple things + such as logging to + syslog3, + or systemd itself (this means: no + systemctl1)! + Non-essential file systems like /var and + /home are mounted after generators have run. Generators + can however rely on the most basic kernel functionality to be available, + including a mounted /sys, /proc, + /dev, /usr. + + + + + Units written by generators are removed when the configuration is + reloaded. That means the lifetime of the generated units is closely bound to + the reload cycles of systemd itself. + + + + Generators should only be used to generate unit files and symlinks to + them, not any other kind of configuration. Due to the lifecycle logic + mentioned above, generators are not a good fit to generate dynamic + configuration for other services. If you need to generate dynamic + configuration for other services, do so in normal services you order before + the service in question. + + + + Since + syslog3 + + is not available (see above), log messages have to be written to + /dev/kmsg instead. + + + + The generator should always include its own name in a comment at the top of the generated file, + so that the user can easily figure out which component created or amended a particular unit. + + The SourcePath= directive should be used in generated files to specify the + source configuration file they are generated from. This makes things more easily understood by the + user and also has the benefit that systemd can warn the user about configuration files that changed + on disk but have not been read yet by systemd. The SourcePath= value does not have + to be a file in a physical filesystem. For example, in the common case of the generator looking at + the kernel command line, should be used. + + + + Generators may write out dynamic unit files or just hook unit files + into other units with the usual .wants/ or + .requires/ symlinks. Often, it is nicer to simply + instantiate a template unit file from /usr with a + generator instead of writing out entirely dynamic unit files. Of course, this + works only if a single parameter is to be used. + + + + If you are careful, you can implement generators in shell scripts. We + do recommend C code however, since generators are executed synchronously and + hence delay the entire boot if they are slow. + + + + Regarding overriding semantics: there are two rules we try to follow + when thinking about the overriding semantics: + + + + User configuration should override vendor configuration. This + (mostly) means that stuff from /etc should override + stuff from /usr. + + + + Native configuration should override non-native configuration. This + (mostly) means that stuff you generate should never override native unit + files for the same purpose. + + + + Of these two rules the first rule is probably the more important one + and breaks the second one sometimes. Hence, when deciding whether to use + argv[1], argv[2], or argv[3], your default choice should probably be + argv[1]. + + + + Instead of heading off now and writing all kind of generators for + legacy configuration file formats, please think twice! It is often a better + idea to just deprecate old stuff instead of keeping it artificially alive. + + + + + + + Examples + + systemd-fstab-generator + + systemd-fstab-generator8 + converts /etc/fstab into native mount units. It uses + argv[1] as location to place the generated unit files in order to allow the + user to override /etc/fstab with their own native unit + files, but also to ensure that /etc/fstab overrides any + vendor default from /usr. + + After editing /etc/fstab, the user should invoke + systemctl daemon-reload. This will re-run all generators and + cause systemd to reload units from disk. To actually mount + new directories added to fstab, systemctl start + /path/to/mountpoint or systemctl + start local-fs.target may be used. + + + + systemd-system-update-generator + + systemd-system-update-generator8 + temporarily redirects default.target to + system-update.target, if a system update is + scheduled. Since this needs to override the default user configuration for + default.target, it uses argv[2]. For details about this + logic, see + systemd.offline-updates7. + + + + + Debugging a generator + + dir=$(mktemp -d) +SYSTEMD_LOG_LEVEL=debug &systemgeneratordir;/systemd-fstab-generator \ + "$dir" "$dir" "$dir" +find $dir + + + + + See also + + + systemd1, + systemd-cryptsetup-generator8, + systemd-debug-generator8, + systemd-fstab-generator8, + fstab5, + systemd-getty-generator8, + systemd-gpt-auto-generator8, + systemd-hibernate-resume-generator8, + systemd-rc-local-generator8, + systemd-system-update-generator8, + systemd-sysv-generator8, + systemd.unit5, + systemctl1, + systemd.environment-generator7 + + + diff --git a/man/systemd.journal-fields.xml b/man/systemd.journal-fields.xml new file mode 100644 index 00000000..79a9a067 --- /dev/null +++ b/man/systemd.journal-fields.xml @@ -0,0 +1,553 @@ + + + + + + + + systemd.journal-fields + systemd + + + + systemd.journal-fields + 7 + + + + systemd.journal-fields + Special journal fields + + + + Description + + Entries in the journal (as written by + systemd-journald.service8) + resemble a UNIX process environment block in syntax but with fields that may include binary data. + Primarily, fields are formatted UTF-8 text strings, and binary encoding is used only where formatting as + UTF-8 text strings makes little sense. New fields may freely be defined by applications, but a few fields + have special meanings. All fields with special meanings are optional. In some cases, fields may appear + more than once per entry. + + + + User Journal Fields + + User fields are fields that are directly passed from clients + and stored in the journal. + + + + MESSAGE= + + The human-readable message string for this entry. This + is supposed to be the primary text shown to the user. It is + usually not translated (but might be in some cases), and is + not supposed to be parsed for metadata. + + + + + MESSAGE_ID= + + A 128-bit message identifier ID for recognizing certain message types, if this is desirable. This + should contain a 128-bit ID formatted as a lower-case hexadecimal string, without any separating dashes or + suchlike. This is recommended to be a UUID-compatible ID, but this is not enforced, and formatted + differently. Developers can generate a new ID for this purpose with systemd-id128 new. + + + + + + PRIORITY= + + A priority value between 0 (emerg) + and 7 (debug) formatted as a decimal + string. This field is compatible with syslog's priority + concept. + + + + + CODE_FILE= + CODE_LINE= + CODE_FUNC= + + The code location generating this message, if known. + Contains the source filename, the line number and the + function name. + + + + + ERRNO= + + The low-level Unix error number causing this entry, if + any. Contains the numeric value of + errno3 + formatted as a decimal string. + + + + + SYSLOG_FACILITY= + SYSLOG_IDENTIFIER= + SYSLOG_PID= + SYSLOG_TIMESTAMP= + + Syslog compatibility fields containing the facility (formatted as + decimal string), the identifier string (i.e. "tag"), the client PID, and + the timestamp as specified in the original datagram. (Note that the tag is + usually derived from glibc's + program_invocation_short_name variable, see + program_invocation_short_name3.) + Note that the journal service does not validate the values of any structured + journal fields whose name is not prefixed with an underscore, and this includes any + syslog related fields such as these. Hence, applications that supply a facility, PID, + or log level are expected to do so properly formatted, i.e. as numeric integers formatted + as decimal strings. + + + + + SYSLOG_RAW= + + The original contents of the syslog line as received in the syslog + datagram. This field is only included if the MESSAGE= + field was modified compared to the original payload or the timestamp could + not be located properly and is not included in + SYSLOG_TIMESTAMP=. Message truncation occurs when when + the message contains leading or trailing whitespace (trailing and leading + whitespace is stripped), or it contains an embedded + NUL byte (the NUL byte and + anything after it is not included). Thus, the original syslog line is + either stored as SYSLOG_RAW= or it can be recreated + based on the stored priority and facility, timestamp, identifier, and the + message payload in MESSAGE=. + + + + + + + + Trusted Journal Fields + + Fields prefixed with an underscore are trusted fields, i.e. + fields that are implicitly added by the journal and cannot be + altered by client code. + + + + _PID= + _UID= + _GID= + + The process, user, and group ID of the process the + journal entry originates from formatted as a decimal + string. Note that entries obtained via stdout or + stderr of forked processes will contain credentials valid for a parent + process (that initiated the connection to systemd-journald). + + + + + _COMM= + _EXE= + _CMDLINE= + + The name, the executable path, and the command line of + the process the journal entry originates from. + + + + + _CAP_EFFECTIVE= + + The effective + capabilities7 + of the process the journal entry originates from. + + + + + _AUDIT_SESSION= + _AUDIT_LOGINUID= + + The session and login UID of the process the journal + entry originates from, as maintained by the kernel audit + subsystem. + + + + + _SYSTEMD_CGROUP= + _SYSTEMD_SLICE= + _SYSTEMD_UNIT= + _SYSTEMD_USER_UNIT= + _SYSTEMD_USER_SLICE= + _SYSTEMD_SESSION= + _SYSTEMD_OWNER_UID= + + + The control group path in the systemd hierarchy, the + the systemd slice unit name, the systemd unit name, the + unit name in the systemd user manager (if any), the systemd + session ID (if any), and the owner UID of the systemd user + unit or systemd session (if any) of the process the journal + entry originates from. + + + + + _SELINUX_CONTEXT= + + The SELinux security context (label) of the process + the journal entry originates from. + + + + + _SOURCE_REALTIME_TIMESTAMP= + + The earliest trusted timestamp of the message, if any + is known that is different from the reception time of the + journal. This is the time in microseconds since the epoch + UTC, formatted as a decimal string. + + + + + _BOOT_ID= + + The kernel boot ID for the boot the message was + generated in, formatted as a 128-bit hexadecimal + string. + + + + + _MACHINE_ID= + + The machine ID of the originating host, as available + in + machine-id5. + + + + + _SYSTEMD_INVOCATION_ID= + + The invocation ID for the runtime cycle of the unit + the message was generated in, as available to processes + of the unit in $INVOCATION_ID (see + systemd.exec5). + + + + + _HOSTNAME= + + The name of the originating host. + + + + + _TRANSPORT= + + How the entry was received by the journal service. + Valid transports are: + + + + + + + + for those read from the kernel audit subsystem + + + + + + + + + + for internally generated messages + + + + + + + + + + for those received via the local syslog socket + with the syslog protocol + + + + + + + + + + for those received via the native journal + protocol + + + + + + + + + + for those read from a service's standard output + or error output + + + + + + + + + + for those read from the kernel + + + + + + + + _STREAM_ID= + + Only applies to _TRANSPORT=stdout records: specifies a randomized 128bit ID assigned + to the stream connection when it was first created. This ID is useful to reconstruct individual log streams + from the log records: all log records carrying the same stream ID originate from the same stream. + + + + _LINE_BREAK= + + Only applies to _TRANSPORT=stdout records: indicates that the log message in the + standard output/error stream was not terminated with a normal newline character (\n, + i.e. ASCII 10). Specifically, when set this field is one of (in case the line was + terminated by a NUL byte), (in case the maximum log line length was reached, as + configured with LineMax= in + journald.conf5) or + (if this was the last log record of a stream and the stream ended without a final + newline character). Note that this record is not generated when a normal newline character was used for + marking the log line end. + + + + + + + Kernel Journal Fields + + Kernel fields are fields that are used by messages + originating in the kernel and stored in the journal. + + + + _KERNEL_DEVICE= + + The kernel device name. If the entry is associated to + a block device, the major and minor of the device node, + separated by : and prefixed by + b. Similar for character devices but + prefixed by c. For network devices, this + is the interface index prefixed by n. For + all other devices, this is the subsystem name prefixed by + +, followed by :, + followed by the kernel device name. + + + + _KERNEL_SUBSYSTEM= + + The kernel subsystem name. + + + + _UDEV_SYSNAME= + + The kernel device name as it shows up in the device + tree below /sys. + + + + _UDEV_DEVNODE= + + The device node path of this device in + /dev. + + + + _UDEV_DEVLINK= + + Additional symlink names pointing to the device node + in /dev. This field is frequently set + more than once per entry. + + + + + + + Fields to log on behalf of a different program + + Fields in this section are used by programs to specify that + they are logging on behalf of another program or unit. + + + Fields used by the systemd-coredump + coredump kernel helper: + + + + + COREDUMP_UNIT= + COREDUMP_USER_UNIT= + + Used to annotate messages containing coredumps from + system and session units. See + coredumpctl1. + + + + + + Privileged programs (currently UID 0) may attach + OBJECT_PID= to a message. This will instruct + systemd-journald to attach additional fields on + behalf of the caller: + + + + OBJECT_PID=PID + + PID of the program that this message pertains to. + + + + + + OBJECT_UID= + OBJECT_GID= + OBJECT_COMM= + OBJECT_EXE= + OBJECT_CMDLINE= + OBJECT_AUDIT_SESSION= + OBJECT_AUDIT_LOGINUID= + OBJECT_SYSTEMD_CGROUP= + OBJECT_SYSTEMD_SESSION= + OBJECT_SYSTEMD_OWNER_UID= + OBJECT_SYSTEMD_UNIT= + OBJECT_SYSTEMD_USER_UNIT= + + These are additional fields added automatically by + systemd-journald. Their meaning is the + same as + _UID=, + _GID=, + _COMM=, + _EXE=, + _CMDLINE=, + _AUDIT_SESSION=, + _AUDIT_LOGINUID=, + _SYSTEMD_CGROUP=, + _SYSTEMD_SESSION=, + _SYSTEMD_UNIT=, + _SYSTEMD_USER_UNIT=, and + _SYSTEMD_OWNER_UID= + as described above, except that the process identified by + PID is described, instead of the + process which logged the message. + + + + + + + + Address Fields + + During serialization into external formats, such as the + Journal + Export Format or the Journal + JSON Format, the addresses of journal entries are + serialized into fields prefixed with double underscores. Note that + these are not proper fields when stored in the journal but for + addressing metadata of entries. They cannot be written as part of + structured log entries via calls such as + sd_journal_send3. + They may also not be used as matches for + sd_journal_add_match3 + + + + __CURSOR= + + The cursor for the entry. A cursor is an opaque text + string that uniquely describes the position of an entry in + the journal and is portable across machines, platforms and + journal files. + + + + + + __REALTIME_TIMESTAMP= + + The wallclock time + (CLOCK_REALTIME) at the point in time + the entry was received by the journal, in microseconds since + the epoch UTC, formatted as a decimal string. This has + different properties from + _SOURCE_REALTIME_TIMESTAMP=, as it is + usually a bit later but more likely to be monotonic. + + + + + + __MONOTONIC_TIMESTAMP= + + The monotonic time + (CLOCK_MONOTONIC) at the point in time + the entry was received by the journal in microseconds, + formatted as a decimal string. To be useful as an address + for the entry, this should be combined with the boot ID in + _BOOT_ID=. + + + + + + + + See Also + + systemd1, + systemd-journald.service8, + journalctl1, + journald.conf5, + sd-journal3, + coredumpctl1, + systemd.directives7 + + + + diff --git a/man/systemd.kill.xml b/man/systemd.kill.xml new file mode 100644 index 00000000..6a1c67d4 --- /dev/null +++ b/man/systemd.kill.xml @@ -0,0 +1,191 @@ + + + + + + + systemd.kill + systemd + + + + systemd.kill + 5 + + + + systemd.kill + Process killing procedure + configuration + + + + service.service, + socket.socket, + mount.mount, + swap.swap, + scope.scope + + + + Description + + Unit configuration files for services, sockets, mount + points, swap devices and scopes share a subset of configuration + options which define the killing procedure of processes belonging + to the unit. + + This man page lists the configuration options shared by + these five unit types. See + systemd.unit5 + for the common options shared by all unit configuration files, and + systemd.service5, + systemd.socket5, + systemd.swap5, + systemd.mount5 + and + systemd.scope5 + for more information on the configuration file options specific to + each unit type. + + The kill procedure configuration options are configured in + the [Service], [Socket], [Mount] or [Swap] section, depending on + the unit type. + + + + Options + + + + + KillMode= + Specifies how processes of this unit shall be + killed. One of + , + , + , + . + + If set to , all remaining + processes in the control group of this unit will be killed on + unit stop (for services: after the stop command is executed, + as configured with ExecStop=). If set to + , only the main process itself is + killed. If set to , the + SIGTERM signal (see below) is sent to the + main process while the subsequent SIGKILL + signal (see below) is sent to all remaining processes of the + unit's control group. If set to , no + process is killed. In this case, only the stop command will be + executed on unit stop, but no process will be killed otherwise. + Processes remaining alive after stop are left in their control + group and the control group continues to exist after stop + unless it is empty. + + Processes will first be terminated via SIGTERM (unless the signal to send + is changed via KillSignal= or RestartKillSignal=). Optionally, + this is immediately followed by a SIGHUP (if enabled with + SendSIGHUP=). If processes still remain after the main process of a unit has + exited or the delay configured via the TimeoutStopSec= has passed, the termination + request is repeated with the SIGKILL signal or the signal specified via + FinalKillSignal= (unless this is disabled via the SendSIGKILL= + option). See kill2 + for more information. + + Defaults to . + + + + KillSignal= + Specifies which signal to use when stopping a service. This controls the signal that + is sent as first step of shutting down a unit (see above), and is usually followed by + SIGKILL (see above and below). For a list of valid signals, see + signal7. + Defaults to SIGTERM. + + Note that, right after sending the signal specified in this setting, systemd will always send + SIGCONT, to ensure that even suspended tasks can be terminated cleanly. + + + + + RestartKillSignal= + Specifies which signal to use when restarting a service. The same as + KillSignal= described above, with the exception that this setting is used in a + restart job. Not set by default, and the value of KillSignal= is used. + + + + + SendSIGHUP= + Specifies whether to send + SIGHUP to remaining processes immediately + after sending the signal configured with + KillSignal=. This is useful to indicate to + shells and shell-like programs that their connection has been + severed. Takes a boolean value. Defaults to "no". + + + + + SendSIGKILL= + Specifies whether to send + SIGKILL (or the signal specified by + FinalKillSignal=) to remaining processes + after a timeout, if the normal shutdown procedure left + processes of the service around. When disabled, a + KillMode= of control-group + or mixed service will not restart if + processes from prior services exist within the control group. + Takes a boolean value. Defaults to "yes". + + + + + FinalKillSignal= + Specifies which signal to send to remaining + processes after a timeout if SendSIGKILL= + is enabled. The signal configured here should be one that is + not typically caught and processed by services (SIGTERM + is not suitable). Developers can find it useful to use this to + generate a coredump to troubleshoot why a service did not + terminate upon receiving the initial SIGTERM + signal. This can be achieved by configuring LimitCORE= + and setting FinalKillSignal= to either + SIGQUIT or SIGABRT + Defaults to SIGKILL. + + + + + WatchdogSignal= + Specifies which signal to use to terminate the + service when the watchdog timeout expires (enabled through + WatchdogSec=). Defaults to SIGABRT. + + + + + + + + See Also + + systemd1, + systemctl1, + journalctl1, + systemd.unit5, + systemd.service5, + systemd.socket5, + systemd.swap5, + systemd.mount5, + systemd.exec5, + systemd.directives7, + kill2, + signal7 + + + + diff --git a/man/systemd.link.xml b/man/systemd.link.xml new file mode 100644 index 00000000..63bb31d6 --- /dev/null +++ b/man/systemd.link.xml @@ -0,0 +1,782 @@ + + + + + + + systemd.link + systemd + + + + systemd.link + 5 + + + + systemd.link + Network device configuration + + + + link.link + + + + Description + + Network link configuration is performed by the + net_setup_link udev builtin. + + The link files are read from the files located in the system + network directory /usr/lib/systemd/network, + the volatile runtime network directory + /run/systemd/network, and the local + administration network directory + /etc/systemd/network. Link files must have + the extension .link; other extensions are + ignored. All link files are collectively sorted and processed in + lexical order, regardless of the directories in which they live. + However, files with identical filenames replace each other. Files + in /etc have the highest priority, files in + /run take precedence over files with the same + name in /usr/lib. This can be used to + override a system-supplied link file with a local file if needed. + As a special case, an empty file (file size 0) or symlink with the + same name pointing to /dev/null disables the + configuration file entirely (it is "masked"). + + The link file contains a [Match] section, which determines if a given link file may be applied to a + given device, as well as a [Link] section specifying how the device should be configured. The first (in + lexical order) of the link files that matches a given device is applied. Note that a default file + 99-default.link is shipped by the system. Any user-supplied + .link should hence have a lexically earlier name to be considered at all. + + See udevadm8 for + diagnosing problems with .link files. + + + + [Match] Section Options + + A link file is said to match a device if all matches specified by the + [Match] section are satisfied. When a link file does not contain valid settings + in [Match] section, then the file will match all devices and + systemd-udevd warns about that. Hint: to avoid the warning and to make it clear + that all interfaces shall be matched, add the following: + OriginalName=* + The following keys are accepted: + + + + MACAddress= + + A whitespace-separated list of hardware addresses. Use full colon-, hyphen- or dot-delimited hexadecimal. See the example below. + This option may appear more than once, in which case the lists are merged. If the empty string is assigned to this option, the list + of hardware addresses defined prior to this is reset. + + Example: + MACAddress=01:23:45:67:89:ab 00-11-22-33-44-55 AABB.CCDD.EEFF + + + + OriginalName= + + A whitespace-separated list of shell-style globs matching + the device name, as exposed by the udev property + "INTERFACE". This cannot be used to match on names that have + already been changed from userspace. Caution is advised when matching on + kernel-assigned names, as they are known to be unstable + between reboots. + + + + Path= + + A whitespace-separated list of shell-style globs matching + the persistent path, as exposed by the udev property + ID_PATH. + + + + Driver= + + A whitespace-separated list of shell-style globs matching the driver currently bound to the + device, as exposed by the udev property ID_NET_DRIVER of its parent device, or if that + is not set, the driver as exposed by ethtool -i of the device itself. + + + + Type= + + A whitespace-separated list of shell-style globs matching + the device type, as exposed by the udev + property DEVTYPE. + + + + Property= + + A whitespace-separated list of udev property name with its value after a equal + (=). If multiple properties are specified, the test results are ANDed. + If the list is prefixed with a "!", the test is inverted. If a value contains white + spaces, then please quote whole key and value pair. If a value contains quotation, then + please escape the quotation with \. + + Example: if a .link file has the following: + Property=ID_MODEL_ID=9999 "ID_VENDOR_FROM_DATABASE=vendor name" "KEY=with \"quotation\"" + then, the .link file matches only when an interface has all the above three properties. + + + + + Host= + + Matches against the hostname or machine ID of the host. See ConditionHost= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + Virtualization= + + Checks whether the system is executed in a virtualized environment and optionally test + whether it is a specific implementation. See ConditionVirtualization= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + KernelCommandLine= + + Checks whether a specific kernel command line option is set. See + ConditionKernelCommandLine= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + KernelVersion= + + Checks whether the kernel version (as reported by uname -r) matches a certain + expression. See ConditionKernelVersion= in + systemd.unit5 for + details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + Architecture= + + Checks whether the system is running on a specific architecture. See + ConditionArchitecture= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + + + + + [Link] Section Options + + The [Link] section accepts the following + keys: + + + + Description= + + A description of the device. + + + + Alias= + + The ifalias interface property is set to this value. + + + + MACAddressPolicy= + + The policy by which the MAC address should be set. The + available policies are: + + + + + + + If the hardware has a persistent MAC address, as + most hardware should, and if it is used by the kernel, + nothing is done. Otherwise, a new MAC address is + generated which is guaranteed to be the same on every + boot for the given machine and the given device, but + which is otherwise random. This feature depends on ID_NET_NAME_* + properties to exist for the link. On hardware where these + properties are not set, the generation of a persistent MAC address + will fail. + + + + + + If the kernel is using a random MAC address, + nothing is done. Otherwise, a new address is randomly + generated each time the device appears, typically at + boot. Either way, the random address will have the + unicast and + locally administered bits set. + + + + + + Keeps the MAC address assigned by the kernel. + + + + + + + MACAddress= + + The MAC address to use, if no + MACAddressPolicy= + is specified. + + + + NamePolicy= + + An ordered, space-separated list of policies by which the interface name should be set. + NamePolicy= may be disabled by specifying on the + kernel command line. Each of the policies may fail, and the first successful one is used. The name + is not set directly, but is exported to udev as the property , which + is, by default, used by a + udev7, + rule to set NAME. The available policies are: + + + + + + + If the kernel claims that the name it has set + for a device is predictable, then no renaming is + performed. + + + + + + The name is set based on entries in the udev's + Hardware Database with the key + ID_NET_NAME_FROM_DATABASE. + + + + + + + The name is set based on information given by + the firmware for on-board devices, as exported by the + udev property ID_NET_NAME_ONBOARD. + See systemd.net-naming-scheme7. + + + + + + + The name is set based on information given by + the firmware for hot-plug devices, as exported by the + udev property ID_NET_NAME_SLOT. + See systemd.net-naming-scheme7. + + + + + + + The name is set based on the device's physical + location, as exported by the udev property + ID_NET_NAME_PATH. + See systemd.net-naming-scheme7. + + + + + + + The name is set based on the device's persistent + MAC address, as exported by the udev property + ID_NET_NAME_MAC. + See systemd.net-naming-scheme7. + + + + + + + If the device already had a name given by userspace (as part of creation of the device + or a rename), keep it. + + + + + + + Name= + + The interface name to use. This option has lower precedence than + NamePolicy=, so for this setting to take effect, NamePolicy= + must either be unset, empty, disabled, or all policies configured there must fail. Also see the + example below with Name=dmz0. + + Note that specifying a name that the kernel might use for another + interface (for example eth0) is dangerous because the + name assignment done by udev will race with the assignment done by the + kernel, and only one interface may use the name. Depending on the order of + operations, either udev or the kernel will win, making the naming + unpredictable. It is best to use some different prefix, for example + internal0/external0 or + lan0/lan1/lan3. + + + + + MTUBytes= + + The maximum transmission unit in bytes to set for the + device. The usual suffixes K, M, G, are supported and are + understood to the base of 1024. + + + + BitsPerSecond= + + The speed to set for the device, the value is rounded + down to the nearest Mbps. The usual suffixes K, M, G, are + supported and are understood to the base of 1000. + + + + Duplex= + + The duplex mode to set for the device. The accepted values are and + . + + + + AutoNegotiation= + + Takes a boolean. If set to yes, automatic negotiation of transmission parameters is enabled. + Autonegotiation is a procedure by which two connected ethernet devices choose + common transmission parameters, such as speed, duplex mode, and flow control. + When unset, the kernel's default will be used. + + Note that if autonegotiation is enabled, speed and duplex settings are + read-only. If autonegotation is disabled, speed and duplex settings are writable + if the driver supports multiple link modes. + + + + WakeOnLan= + + The Wake-on-LAN policy to set for the device. The + supported values are: + + + + + + Wake on PHY activity. + + + + + + Wake on unicast messages. + + + + + + Wake on multicast messages. + + + + + + Wake on broadcast messages. + + + + + + Wake on ARP. + + + + + + Wake on receipt of a magic packet. + + + + + + + Enable secureon(tm) password for MagicPacket(tm). + + + + + + + Never wake. + + + + + Defaults to . + + + + Port= + + The port option is used to select the device port. The + supported values are: + + + + + + An Ethernet interface using Twisted-Pair cable as the medium. + + + + + + Attachment Unit Interface (AUI). Normally used with hubs. + + + + + + + An Ethernet interface using BNC connectors and co-axial cable. + + + + + + An Ethernet interface using a Media Independent Interface (MII). + + + + + + An Ethernet interface using Optical Fibre as the medium. + + + + + + + Advertise= + + This sets what speeds and duplex modes of operation are advertised for auto-negotiation. + This implies AutoNegotiation=yes. The supported values are: + + + Supported advertise values + + + + + + + Advertise + Speed (Mbps) + Duplex Mode + + + + 10half + + + 10full + + + 100half + + + 100full + + + 1000half + + + 1000full + + + 10000full + + + 2500full + + + 1000full + + + 10000full + + + 10000full + + + 10000full + + + 20000full + + + 20000full + + +
+ + By default this is unset, i.e. all possible modes will be advertised. + This option may be specified more than once, in which case all specified speeds and modes are advertised. + If the empty string is assigned to this option, the list is reset, and all prior assignments have no effect. +
+
+
+ + TCPSegmentationOffload= + + Takes a boolean. If set to true, the TCP Segmentation Offload (TSO) is enabled. + When unset, the kernel's default will be used. + + + + TCP6SegmentationOffload= + + Takes a boolean. If set to true, the TCP6 Segmentation Offload (tx-tcp6-segmentation) is enabled. + When unset, the kernel's default will be used. + + + + GenericSegmentationOffload= + + Takes a boolean. If set to true, the Generic Segmentation Offload (GSO) is enabled. + When unset, the kernel's default will be used. + + + + GenericReceiveOffload= + + Takes a boolean. If set to true, the Generic Receive Offload (GRO) is enabled. + When unset, the kernel's default will be used. + + + + LargeReceiveOffload= + + Takes a boolean. If set to true, the Large Receive Offload (LRO) is enabled. + When unset, the kernel's default will be used. + + + + RxChannels= + + Sets the number of receive channels (a number between 1 and 4294967295) . + + + + TxChannels= + + Sets the number of transmit channels (a number between 1 and 4294967295). + + + + OtherChannels= + + Sets the number of other channels (a number between 1 and 4294967295). + + + + CombinedChannels= + + Sets the number of combined set channels (a number between 1 and 4294967295). + + + + RxBufferSize= + + Takes a integer. Specifies the NIC receive ring buffer size. When unset, the kernel's default will be used. + + + + TxBufferSize= + + Takes a integer. Specifies the NIC transmit ring buffer size. When unset, the kernel's default will be used. + + + +
+
+ + + Examples + + + /usr/lib/systemd/network/99-default.link + + The link file 99-default.link that is + shipped with systemd defines the default naming policy for + links. + + [Link] +NamePolicy=kernel database onboard slot path +MACAddressPolicy=persistent + + + + /etc/systemd/network/10-dmz.link + + This example assigns the fixed name dmz0 to the interface with the MAC address + 00:a0:de:63:7a:e6: + + [Match] +MACAddress=00:a0:de:63:7a:e6 + +[Link] +Name=dmz0 + + NamePolicy= is not set, so Name= takes effect. We use the + 10- prefix to order this file early in the list. Note that it needs to be before + 99-link, i.e. it needs a numerical prefix, to have any effect at all. + + + + Debugging <varname>NamePolicy=</varname> assignments + + $ sudo SYSTEMD_LOG_LEVEL=debug udevadm test-builtin net_setup_link /sys/class/net/hub0 +… +Parsed configuration file /usr/lib/systemd/network/99-default.link +Parsed configuration file /etc/systemd/network/10-eth0.link +ID_NET_DRIVER=cdc_ether +Config file /etc/systemd/network/10-eth0.link applies to device hub0 +link_config: autonegotiation is unset or enabled, the speed and duplex are not writable. +hub0: Device has name_assign_type=4 +Using default interface naming scheme 'v240'. +hub0: Policies didn't yield a name, using specified Name=hub0. +ID_NET_LINK_FILE=/etc/systemd/network/10-eth0.link +ID_NET_NAME=hub0 +… + + Explicit Name= configuration wins in this case. + + sudo SYSTEMD_LOG_LEVEL=debug udevadm test-builtin net_setup_link /sys/class/net/enp0s31f6 +… +Parsed configuration file /usr/lib/systemd/network/99-default.link +Parsed configuration file /etc/systemd/network/10-eth0.link +Created link configuration context. +ID_NET_DRIVER=e1000e +Config file /usr/lib/systemd/network/99-default.link applies to device enp0s31f6 +link_config: autonegotiation is unset or enabled, the speed and duplex are not writable. +enp0s31f6: Device has name_assign_type=4 +Using default interface naming scheme 'v240'. +enp0s31f6: Policy *keep*: keeping existing userspace name +enp0s31f6: Device has addr_assign_type=0 +enp0s31f6: MAC on the device already matches policy *persistent* +ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link +… + + + In this case, the interface was already renamed, so the policy specified as + the first option in 99-default.link means that the existing name is + preserved. If was removed, or if were in boot before the renaming has happened, + we might get the following instead: + + enp0s31f6: Policy *path* yields "enp0s31f6". +enp0s31f6: Device has addr_assign_type=0 +enp0s31f6: MAC on the device already matches policy *persistent* +ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link +ID_NET_NAME=enp0s31f6 +… + + + Please note that the details of output are subject to change. + + + + /etc/systemd/network/10-internet.link + + This example assigns the fixed name + internet0 to the interface with the device + path pci-0000:00:1a.0-*: + + [Match] +Path=pci-0000:00:1a.0-* + +[Link] +Name=internet0 + + + + /etc/systemd/network/25-wireless.link + + Here's an overly complex example that shows the use of a large number of [Match] and [Link] settings. + + [Match] +MACAddress=12:34:56:78:9a:bc +Driver=brcmsmac +Path=pci-0000:02:00.0-* +Type=wlan +Virtualization=no +Host=my-laptop +Architecture=x86-64 + +[Link] +Name=wireless0 +MTUBytes=1450 +BitsPerSecond=10M +WakeOnLan=magic +MACAddress=cb:a9:87:65:43:21 + + + + + See Also + + + systemd-udevd.service8 + , + + udevadm8 + , + + systemd.netdev5 + , + + systemd.network5 + + + + +
diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml new file mode 100644 index 00000000..4e350ec5 --- /dev/null +++ b/man/systemd.mount.xml @@ -0,0 +1,548 @@ + + + + + + + systemd.mount + systemd + + + + systemd.mount + 5 + + + + systemd.mount + Mount unit configuration + + + + mount.mount + + + + Description + + A unit configuration file whose name ends in + .mount encodes information about a file system + mount point controlled and supervised by systemd. + + This man page lists the configuration options specific to + this unit type. See + systemd.unit5 + for the common options of all unit configuration files. The common + configuration items are configured in the generic [Unit] and + [Install] sections. The mount specific configuration options are + configured in the [Mount] section. + + Additional options are listed in + systemd.exec5, + which define the execution environment the + mount8 + program is executed in, and in + systemd.kill5, + which define the way the processes are terminated, and in + systemd.resource-control5, + which configure resource control settings for the processes of the + service. + + Note that the options User= and + Group= are not useful for mount units. + systemd passes two parameters to + mount8; + the values of What= and Where=. + When invoked in this way, + mount8 + does not read any options from /etc/fstab, and + must be run as UID 0. + + Mount units must be named after the mount point directories they control. Example: the mount point /home/lennart must be configured in a unit file home-lennart.mount. + For details about the escaping logic used to convert a file system path to a unit name, see + systemd.unit5. Note that mount + units cannot be templated, nor is possible to add multiple names to a mount unit by creating additional symlinks to + it. + + Optionally, a mount unit may be accompanied by an automount + unit, to allow on-demand or parallelized mounting. See + systemd.automount5. + + Mount points created at runtime (independently of unit files + or /etc/fstab) will be monitored by systemd + and appear like any other mount unit in systemd. See + /proc/self/mountinfo description in + proc5. + + + Some file systems have special semantics as API file systems + for kernel-to-userspace and userspace-to-userspace interfaces. Some + of them may not be changed via mount units, and cannot be + disabled. For a longer discussion see API + File Systems. + + The + systemd-mount1 command + allows creating .mount and .automount units dynamically and + transiently from the command line. + + + + Automatic Dependencies + + + Implicit Dependencies + + The following dependencies are implicitly added: + + + If a mount unit is beneath another mount unit in the file + system hierarchy, both a requirement dependency and an ordering + dependency between both units are created automatically. + + Block device backed file systems automatically gain + BindsTo= and After= type + dependencies on the device unit encapsulating the block + device (see below). + + If traditional file system quota is enabled for a mount + unit, automatic Wants= and + Before= dependencies on + systemd-quotacheck.service and + quotaon.service are added. + + Additional implicit dependencies may be added as result of + execution and resource control parameters as documented in + systemd.exec5 + and + systemd.resource-control5. + + + + + + Default Dependencies + + The following dependencies are added unless DefaultDependencies=no is set: + + + All mount units acquire automatic Before= and Conflicts= on + umount.target in order to be stopped during shutdown. + + Mount units referring to local file systems automatically gain + an After= dependency on local-fs-pre.target, and a + Before= dependency on local-fs.target unless + mount option is set. + + Network mount units + automatically acquire After= dependencies on remote-fs-pre.target, + network.target and network-online.target, and gain a + Before= dependency on remote-fs.target unless + mount option is set. Towards the latter a + Wants= unit is added as well. + + + Mount units referring to local and network file systems are distinguished by their file system type + specification. In some cases this is not sufficient (for example network block device based mounts, such as + iSCSI), in which case may be added to the mount option string of the unit, which forces + systemd to consider the mount unit a network mount. + + + + + <filename>fstab</filename> + + Mount units may either be configured via unit files, or via + /etc/fstab (see + fstab5 + for details). Mounts listed in /etc/fstab + will be converted into native units dynamically at boot and when + the configuration of the system manager is reloaded. In general, + configuring mount points through /etc/fstab + is the preferred approach. See + systemd-fstab-generator8 + for details about the conversion. + + The NFS mount option for NFS background mounts + as documented in nfs5 + is detected by systemd-fstab-generator and the options + are transformed so that systemd fulfills the job-control implications of + that option. Specifically systemd-fstab-generator acts + as though x-systemd.mount-timeout=infinity,retry=10000 was + prepended to the option list, and fg,nofail was appended. + Depending on specific requirements, it may be appropriate to provide some of + these options explicitly, or to make use of the + x-systemd.automount option described below instead + of using bg. + + When reading /etc/fstab a few special + mount options are understood by systemd which influence how + dependencies are created for mount points. systemd will create a + dependency of type Wants= or + (see option + below), from either local-fs.target or + remote-fs.target, depending whether the file + system is local or remote. + + + + + + + Configures a Requires= and + an After= dependency between the created + mount unit and another systemd unit, such as a device or mount + unit. The argument should be a unit name, or an absolute path + to a device node or mount point. This option may be specified + more than once. This option is particularly useful for mount + point declarations that need an additional device to be around + (such as an external journal device for journal file systems) + or an additional mount to be in place (such as an overlay file + system that merges multiple mount points). See + After= and Requires= in + systemd.unit5 + for details. + + + + + + + In the created mount unit, configures a + Before= or After= + dependency on another systemd unit, such as a mount unit. + The argument should be a unit name or an absolute path + to a mount point. This option may be specified more than once. + This option is particularly useful for mount point declarations + with option that are mounted + asynchronously but need to be mounted before or after some unit + start, for example, before local-fs.target + unit. + See Before= and After= in + systemd.unit5 + for details. + + + + + + Configures a + RequiresMountsFor= dependency between the + created mount unit and other mount units. The argument must be + an absolute path. This option may be specified more than once. + See RequiresMountsFor= in + systemd.unit5 + for details. + + + + + + The block device backed file system will be upgraded + to BindsTo= dependency. This option is only useful + when mounting file systems manually with + mount8 + as the default dependency in this case is Requires=. + This option is already implied by entries in /etc/fstab + or by mount units. + + + + + + + An automount unit will be created for the file + system. See + systemd.automount5 + for details. + + + + + + Configures the idle timeout of the + automount unit. See TimeoutIdleSec= in + systemd.automount5 + for details. + + + + + + Configure how long systemd should wait for a + device to show up before giving up on an entry from + /etc/fstab. Specify a time in seconds or + explicitly append a unit such as s, + min, h, + ms. + + Note that this option can only be used in + /etc/fstab, and will be + ignored when part of the Options= + setting in a unit file. + + + + + + + Configure how long systemd should wait for the + mount command to finish before giving up on an entry from + /etc/fstab. Specify a time in seconds or + explicitly append a unit such as s, + min, h, + ms. + + Note that this option can only be used in + /etc/fstab, and will be + ignored when part of the Options= + setting in a unit file. + + See TimeoutSec= below for + details. + + + + + + + The file system will be initialized + on the device. If the device is not "empty", i.e. it contains any signature, + the operation will be skipped. It is hence expected that this option + remains set even after the device has been initialized. + + Note that this option can only be used in + /etc/fstab, and will be ignored when part of the + Options= setting in a unit file. + + See + systemd-makefs@.service8. + + + wipefs8 + may be used to remove any signatures from a block device to force + to reinitialize the device. + + + + + + + The file system will be grown to occupy the full block + device. If the file system is already at maximum size, no action will + be performed. It is hence expected that this option remains set even after + the file system has been grown. Only certain file system types are supported, + see + systemd-makefs@.service8 + for details. + + Note that this option can only be used in + /etc/fstab, and will be ignored when part of the + Options= setting in a unit file. + + + + + + Normally the file system type is used to determine if a + mount is a "network mount", i.e. if it should only be started after the + network is available. Using this option overrides this detection and + specifies that the mount requires network. + + Network mount units are ordered between remote-fs-pre.target + and remote-fs.target, instead of + local-fs-pre.target and local-fs.target. + They also pull in network-online.target and are ordered after + it and network.target. + + + + + + + + With , the mount unit will not be added as a dependency for + local-fs.target or remote-fs.target. This means that it will not be + mounted automatically during boot, unless it is pulled in by some other unit. The option + has the opposite meaning and is the default. Note that the option has an effect on the + mount unit itself only — if is used (see above), then the matching + automount unit will still be pulled in by these targets. + + + + + + + With , this mount will be only wanted, not required, by + local-fs.target or remote-fs.target. Moreover the mount unit is not + ordered before these target units. This means that the boot will continue without waiting for the mount unit + and regardless whether the mount point can be mounted successfully. + + + + + + + An additional filesystem to be mounted in the + initramfs. See initrd-fs.target + description in + systemd.special7. + + + + + If a mount point is configured in both + /etc/fstab and a unit file that is stored + below /usr, the former will take precedence. + If the unit file is stored below /etc, it + will take precedence. This means: native unit files take + precedence over traditional configuration files, but this is + superseded by the rule that configuration in + /etc will always take precedence over + configuration in /usr. + + + + Options + + Mount files must include a [Mount] section, which carries + information about the file system mount points it supervises. A + number of options that may be used in this section are shared with + other unit types. These options are documented in + systemd.exec5 + and + systemd.kill5. + The options specific to the [Mount] section of mount units are the + following: + + + + + What= + Takes an absolute path of a device node, file or other resource to mount. See mount8 for details. If + this refers to a device node, a dependency on the respective device unit is automatically created. (See + systemd.device5 for more + information.) This option is mandatory. Note that the usual specifier expansion is applied to this setting, + literal percent characters should hence be written as %%. + + + + Where= + Takes an absolute path of a directory for the + mount point; in particular, the destination cannot be a symbolic + link. If the mount point does not exist at the time of + mounting, it is created. This string must be reflected in the + unit filename. (See above.) This option is + mandatory. + + + + Type= + Takes a string for the file system type. See + mount8 + for details. This setting is optional. + + + + Options= + + Mount options to use when mounting. This takes a comma-separated list of options. This setting + is optional. Note that the usual specifier expansion is applied to this setting, literal percent characters + should hence be written as %%. + + + + SloppyOptions= + + Takes a boolean argument. If true, parsing of + the options specified in Options= is + relaxed, and unknown mount options are tolerated. This + corresponds with + mount8's + -s switch. Defaults to + off. + + + + LazyUnmount= + + Takes a boolean argument. If true, detach the + filesystem from the filesystem hierarchy at time of the unmount + operation, and clean up all references to the filesystem as + soon as they are not busy anymore. + This corresponds with + umount8's + -l switch. Defaults to + off. + + + + ForceUnmount= + + Takes a boolean argument. If true, force an + unmount (in case of an unreachable NFS system). + This corresponds with + umount8's + -f switch. Defaults to + off. + + + + DirectoryMode= + Directories of mount points (and any parent + directories) are automatically created if needed. This option + specifies the file system access mode used when creating these + directories. Takes an access mode in octal notation. Defaults + to 0755. + + + + TimeoutSec= + Configures the time to wait for the mount + command to finish. If a command does not exit within the + configured time, the mount will be considered failed and be + shut down again. All commands still running will be terminated + forcibly via SIGTERM, and after another + delay of this time with SIGKILL. (See + in + systemd.kill5.) + Takes a unit-less value in seconds, or a time span value such + as "5min 20s". Pass 0 to disable the timeout logic. The + default value is set from DefaultTimeoutStartSec= option in + systemd-system.conf5. + + + + + Check + systemd.exec5 + and + systemd.kill5 + for more settings. + + + + See Also + + systemd1, + systemctl1, + systemd-system.conf5, + systemd.unit5, + systemd.exec5, + systemd.kill5, + systemd.resource-control5, + systemd.service5, + systemd.device5, + proc5, + mount8, + systemd-fstab-generator8, + systemd.directives7, + systemd-mount1 + + + + diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml new file mode 100644 index 00000000..7a3673fa --- /dev/null +++ b/man/systemd.net-naming-scheme.xml @@ -0,0 +1,442 @@ + + + + + + + systemd.net-naming-scheme + systemd + + + + systemd.net-naming-scheme + 7 + + + + systemd.net-naming-scheme + Network device naming schemes + + + + Description + + Network interfaces names and MAC addresses may be generated based on certain stable interface + attributes. This is possible when there is enough information about the device to generate those + attributes and the use of this information is configured. This page describes interface naming, i.e. what + possible names may be generated. Those names are generated by the + systemd-udevd.service8 + builtin net_id and exported as udev properties + (ID_NET_NAME_ONBOARD=, ID_NET_LABEL_ONBOARD=, + ID_NET_NAME_PATH=, ID_NET_NAME_SLOT=). + + Names and MAC addresses are derived from various stable device metadata attributes. Newer versions + of udev take more of these attributes into account, improving (and thus possibly changing) the names and + addresses used for the same devices. Different versions of those generation rules are called "naming + schemes". The default naming scheme is chosen at compilation time. Usually this will be the latest + implemented version, but it is also possible to set one of the older versions to preserve + compatibility. This may be useful for example for distributions, which may introduce new versions of + systemd in stable releases without changing the naming scheme. The naming scheme may also be overridden + using the net.naming-scheme= kernel command line switch, see + systemd-udevd.service8. + Available naming schemes are described below. + + After the udev properties have been generated, appropriate udev rules may be used to actually rename + devices based on those properties. See the description of NamePolicy= and + MACAddressPolicy= in + systemd.link5. + + + + Naming + + All names start with a two-character prefix that signifies the interface type. + + + Two character prefixes based on the type of interface + + + + + Prefix + Description + + + + + en + Ethernet + + + ib + InfiniBand + + + sl + serial line IP (slip) + + + wl + Wireless local area network (WLAN) + + + ww + Wireless wide area network (WWAN) + + + +
+ + The udev net_id builtin exports the following udev device properties: + + + + ID_NET_NAME_ONBOARD=prefixonumber + + This name is set based on the numeric ordering information given by the firmware + for on-board devices. The name consists of the prefix, letter o, and a number + specified by the firmware. This is only available for PCI devices. + + + + + ID_NET_LABEL_ONBOARD=prefix label + + This property is set based on textual label given by the firmware for on-board + devices. The name consists of the prefix concatenated with the label. This is only available for + PCI devices. + + + + + + ID_NET_NAME_MAC=prefixxAABBCCDDEEFF + + This name consists of the prefix, letter x, and 12 hexadecimal + digits of the MAC address. It is available if the device has a fixed MAC address. Because this name + is based on an attribute of the card itself, it remains "stable" when the device is moved (even + between machines), but will change when the hardware is replaced. + + + + + ID_NET_NAME_SLOT=prefix[Pdomain]sslot[ffunction][nport_name|ddev_port] + ID_NET_NAME_SLOT=prefixvslot + ID_NET_NAME_SLOT=prefix[Pdomain]sslot[ffunction][nport_name|ddev_port]bnumber + ID_NET_NAME_SLOT=prefix[Pdomain]sslot[ffunction][nport_name|ddev_port]uport…[cconfig][iinterface] + ID_NET_NAME_SLOT=prefix[Pdomain]sslot[ffunction][nport_name|ddev_port]vslot + + This property describes the slot position. Different schemes are used depending on + the bus type, as described in the table below. In case of USB, BCMA, and SR-VIO devices, the full + name consists of the prefix, PCI slot identifier, and USB or BCMA or SR-VIO slot identifier. The + first two parts are denoted as "…" in the table below. + + + Slot naming schemes + + + + + Format + Description + + + + + + prefix [Pdomain] sslot [ffunction] [nport_name | ddev_port] + PCI slot number + + + + prefix vslot + VIO slot number (IBM PowerVM) + + + + … bnumber + Broadcom bus (BCMA) core number + + + + … uport… [cconfig] [iinterface] + USB port number chain + + + + … vslot + SR-VIO slot number + + + +
+ + The PCI domain is only prepended when it is not 0. All multi-function PCI devices will carry + the ffunction number in the device name, including + the function 0 device. For non-multi-function devices, the number is suppressed if 0. The port name + port_name is used, or the port number + ddev_port if the name is not known. + + For BCMA devices, the core number is suppressed when 0. + + For USB devices the full chain of port numbers of hubs is composed. If the name gets longer + than the maximum number of 15 characters, the name is not exported. The usual USB configuration + number 1 and interface number 0 values are suppressed. + + SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of + v and the virtual device number, with any leading zeros removed. The bus + number is ignored. +
+
+ + + ID_NET_NAME_PATH=prefixcbus_id + ID_NET_NAME_PATH=prefixavendormodeliinstance + ID_NET_NAME_PATH=prefixiaddressnport_name + ID_NET_NAME_PATH=prefix[Pdomain]pbussslot[ffunction][nphys_port_name|ddev_port] + ID_NET_NAME_PATH=prefix[Pdomain]pbussslot[ffunction][nphys_port_name|ddev_port]bnumber + ID_NET_NAME_PATH=prefix[Pdomain]pbussslot[ffunction][nphys_port_name|ddev_port]uport…[cconfig][iinterface] + + This property describes the device installation location. Different schemes are + used depending on the bus type, as described in the table below. For BCMA and USB devices, PCI path + information must known, and the full name consists of the prefix, PCI slot identifier, and USB or + BCMA location. The first two parts are denoted as "…" in the table below. + + + Path naming schemes + + + + + Format + Description + + + + + + prefix cbus_id + CCW or grouped CCW device identifier + + + + prefix avendor model iinstance + ACPI path names for ARM64 platform devices + + + + prefix iaddress nport_name + Netdevsim (simulated networking device) device number and port name + + + + prefix [Pdomain] pbus sslot [ffunction] [nphys_port_name | ddev_port] + PCI geographical location + + + + … bnumber + Broadcom bus (BCMA) core number + + + + … uport… [cconfig] [iinterface] + USB port number chain + + + + +
+ + CCW and grouped CCW devices are found in IBM System Z mainframes. Any leading zeros and + dots are suppressed. + + For PCI, BCMA, and USB devices, the same rules as described above for slot naming are + used. +
+
+
+
+ + + History + + The following "naming schemes" have been defined: + + + + v238 + + This is the naming scheme that was implemented in systemd 238. + + + + v239 + + Naming was changed for virtual network interfaces created with SR-IOV and NPAR and + for devices where the PCI network controller device does not have a slot number associated. + + SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of + vport, where port is the + virtual device number. Previously those virtual devices were named as if completely independent. + + + The ninth and later NPAR virtual devices are named following the scheme used for the first + eight NPAR partitions. Previously those devices were not renamed and the kernel default + ("ethN") was used. + + Names are also generated for PCI devices where the PCI network controller device does not + have an associated slot number itself, but one of its parents does. Previously those devices were + not renamed and the kernel default was used. + + + + + v240 + + The ib prefix and stable names for infiniband devices are + introduced. Previously those devices were not renamed. + + The ACPI index field (used in ID_NET_NAME_ONBOARD=) is now also used when + 0. + + A new naming policy NamePolicy=keep was introduced. With this policy, if + the network device name was already set by userspace, the device will not be renamed + again. Previously, this naming policy applied implicitly, and now it must be explicitly + requested. Effectively, this means that network devices will be renamed according to the + configuration, even if they have been renamed already, if keep is not + specified as the naming policy in the .link file. See + systemd.link5 + for a description of NamePolicy=. + + + + v241 + + was extended to set MAC addresses + based on the device name. Previously addresses were only based on the + ID_NET_NAME_* attributes, which meant that interface names would + never be generated for virtual devices. Now a persistent address will be generated for most + devices, including in particular bridges. + + Note: when userspace does not set a MAC address for a bridge device, the kernel will + initially assign a random address, and then change it when the first device is enslaved to the + bridge. With this naming policy change, bridges get a persistent MAC address based on the bridge + name instead of the first enslaved device. + + + + v243 + + Support for renaming netdevsim (simulated networking) devices was added. Previously + those devices were not renamed. + + Previously two-letter interface type prefix was prepended to + ID_NET_LABEL_ONBOARD=. This is not done anymore. + + + + Note that latest may be used to denote the latest scheme known (to this + particular version of systemd. + + + + Examples + + + Using <command>udevadm test-builtin</command> to display device properties + + $ udevadm test-builtin net_id /sys/class/net/enp0s31f6 +... +Using default interface naming scheme 'v243'. +ID_NET_NAMING_SCHEME=v243 +ID_NET_NAME_MAC=enx54ee75cb1dc0 +ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd. +ID_NET_NAME_PATH=enp0s31f6 +... + + + + PCI Ethernet card with firmware index "1" + + ID_NET_NAME_ONBOARD=eno1 +ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1 + + + + + PCI Ethernet card in hotplug slot with firmware index number + + # /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1 +ID_NET_NAME_MAC=enx000000000466 +ID_NET_NAME_PATH=enp5s0 +ID_NET_NAME_SLOT=ens1 + + + + PCI Ethernet multi-function card with 2 ports + + # /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0 +ID_NET_NAME_MAC=enx78e7d1ea46da +ID_NET_NAME_PATH=enp2s0f0 + +# /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1 +ID_NET_NAME_MAC=enx78e7d1ea46dc +ID_NET_NAME_PATH=enp2s0f1 + + + + PCI WLAN card + + # /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0 +ID_NET_NAME_MAC=wlx0024d7e31130 +ID_NET_NAME_PATH=wlp3s0 + + + + PCI IB host adapter with 2 ports + + # /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.0/net/ibp21s0f0 +ID_NET_NAME_PATH=ibp21s0f0 + +# /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.1/net/ibp21s0f1 +ID_NET_NAME_PATH=ibp21s0f1 + + + + USB built-in 3G modem + + # /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6 +ID_NET_NAME_MAC=wwx028037ec0200 +ID_NET_NAME_PATH=wwp0s29u1u4i6 + + + + USB Android phone + + # /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2 +ID_NET_NAME_MAC=enxd626b3450fb5 +ID_NET_NAME_PATH=enp0s29u1u2 + + + + s390 grouped CCW interface + + # /sys/devices/css0/0.0.0007/0.0.f5f0/group_device/net/encf5f0 +ID_NET_NAME_MAC=enx026d3c00000a +ID_NET_NAME_PATH=encf5f0 + + + + + See Also + + udev7, + udevadm8, + the + original page describing stable interface names + + + +
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml new file mode 100644 index 00000000..c3d09d39 --- /dev/null +++ b/man/systemd.netdev.xml @@ -0,0 +1,2131 @@ + + + + + + + + systemd.network + systemd + + + + systemd.netdev + 5 + + + + systemd.netdev + Virtual Network Device configuration + + + + netdev.netdev + + + + Description + + Network setup is performed by + systemd-networkd8. + + + The main Virtual Network Device file must have the extension .netdev; + other extensions are ignored. Virtual network devices are created as soon as networkd is + started. If a netdev with the specified name already exists, networkd will use that as-is rather + than create its own. Note that the settings of the pre-existing netdev will not be changed by + networkd. + + The .netdev files are read from the files located in the system + network directory /usr/lib/systemd/network, the volatile runtime network + directory /run/systemd/network and the local administration network + directory /etc/systemd/network. All configuration files are collectively + sorted and processed in lexical order, regardless of the directories in which they live. + However, files with identical filenames replace each other. Files in /etc + have the highest priority, files in /run take precedence over files with + the same name in /usr/lib. This can be used to override a system-supplied + configuration file with a local file if needed. As a special case, an empty file (file size 0) + or symlink with the same name pointing to /dev/null disables the + configuration file entirely (it is "masked"). + + Along with the netdev file foo.netdev, a "drop-in" directory + foo.netdev.d/ may exist. All files with the suffix .conf + from this directory will be parsed after the file itself is parsed. This is useful to alter or + add configuration settings, without having to modify the main configuration file. Each drop-in + file must have appropriate section headers. + + In addition to /etc/systemd/network, drop-in .d + directories can be placed in /usr/lib/systemd/network or + /run/systemd/network directories. Drop-in files in + /etc take precedence over those in /run which in turn + take precedence over those in /usr/lib. Drop-in files under any of these + directories take precedence over the main netdev file wherever located. (Of course, since + /run is temporary and /usr/lib is for vendors, it is + unlikely drop-ins should be used in either of those places.) + + + + Supported netdev kinds + + The following kinds of virtual network devices may be + configured in .netdev files: + + + Supported kinds of virtual network devices + + + + + + Kind + Description + + + bond + A bond device is an aggregation of all its slave devices. See Linux Ethernet Bonding Driver HOWTO for details.Local configuration + + bridge + A bridge device is a software switch, and each of its slave devices and the bridge itself are ports of the switch. + + dummy + A dummy device drops all packets sent to it. + + gre + A Level 3 GRE tunnel over IPv4. See RFC 2784 for details. + + gretap + A Level 2 GRE tunnel over IPv4. + + erspan + ERSPAN mirrors traffic on one or more source ports and delivers the mirrored traffic to one or more destination ports on another switch. The traffic is encapsulated in generic routing encapsulation (GRE) and is therefore routable across a layer 3 network between the source switch and the destination switch. + + ip6gre + A Level 3 GRE tunnel over IPv6. + + ip6tnl + An IPv4 or IPv6 tunnel over IPv6 + + ip6gretap + A Level 2 GRE tunnel over IPv6. + + ipip + An IPv4 over IPv4 tunnel. + + ipvlan + An ipvlan device is a stacked device which receives packets from its underlying device based on IP address filtering. + + ipvtap + An ipvtap device is a stacked device which receives packets from its underlying device based on IP address filtering and can be accessed using the tap user space interface. + + macvlan + A macvlan device is a stacked device which receives packets from its underlying device based on MAC address filtering. + + macvtap + A macvtap device is a stacked device which receives packets from its underlying device based on MAC address filtering. + + sit + An IPv6 over IPv4 tunnel. + + tap + A persistent Level 2 tunnel between a network device and a device node. + + tun + A persistent Level 3 tunnel between a network device and a device node. + + veth + An Ethernet tunnel between a pair of network devices. + + vlan + A VLAN is a stacked device which receives packets from its underlying device based on VLAN tagging. See IEEE 802.1Q for details. + + vti + An IPv4 over IPSec tunnel. + + vti6 + An IPv6 over IPSec tunnel. + + vxlan + A virtual extensible LAN (vxlan), for connecting Cloud computing deployments. + + geneve + A GEneric NEtwork Virtualization Encapsulation (GENEVE) netdev driver. + + l2tp + A Layer 2 Tunneling Protocol (L2TP) is a tunneling protocol used to support virtual private networks (VPNs) or as part of the delivery of services by ISPs. It does not provide any encryption or confidentiality by itself + + macsec + Media Access Control Security (MACsec) is an 802.1AE IEEE industry-standard security technology that provides secure communication for all traffic on Ethernet links. MACsec provides point-to-point security on Ethernet links between directly connected nodes and is capable of identifying and preventing most security threats. + + vrf + A Virtual Routing and Forwarding (VRF) interface to create separate routing and forwarding domains. + + vcan + The virtual CAN driver (vcan). Similar to the network loopback devices, vcan offers a virtual local CAN interface. + + vxcan + The virtual CAN tunnel driver (vxcan). Similar to the virtual ethernet driver veth, vxcan implements a local CAN traffic tunnel between two virtual CAN network devices. When creating a vxcan, two vxcan devices are created as pair. When one end receives the packet it appears on its pair and vice versa. The vxcan can be used for cross namespace communication. + + + wireguard + WireGuard Secure Network Tunnel. + + netdevsim + A simulator. This simulated networking device is used for testing various networking APIs and at this time is particularly focused on testing hardware offloading related interfaces. + + nlmon + A Netlink monitor device. Use an nlmon device when you want to monitor system Netlink messages. + + fou + Foo-over-UDP tunneling. + + xfrm + A virtual tunnel interface like vti/vti6 but with several advantages. + + + +
+ +
+ + + [Match] Section Options + + A virtual network device is only created if the + [Match] section matches the current + environment, or if the section is empty. The following keys are + accepted: + + + + Host= + + Matches against the hostname or machine ID of the host. See + ConditionHost= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + Virtualization= + + Checks whether the system is executed in a virtualized environment and optionally test + whether it is a specific implementation. See ConditionVirtualization= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + KernelCommandLine= + + Checks whether a specific kernel command line option is set. See + ConditionKernelCommandLine= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + KernelVersion= + + Checks whether the kernel version (as reported by uname -r) matches a + certain expression. See ConditionKernelVersion= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + Architecture= + + Checks whether the system is running on a specific architecture. See + ConditionArchitecture= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + + + + [NetDev] Section Options + + The [NetDev] section accepts the + following keys: + + + + Description= + + A free-form description of the netdev. + + + + Name= + + The interface name used when creating the netdev. + This option is compulsory. + + + + Kind= + + The netdev kind. This option is compulsory. See the + Supported netdev kinds section for the + valid keys. + + + + MTUBytes= + + The maximum transmission unit in bytes to set for the device. The usual suffixes K, M, G, + are supported and are understood to the base of 1024. For tun or + tap devices, MTUBytes= setting is not currently supported in + [NetDev] section. Please specify it in [Link] section of + corresponding + systemd.network5 + files. + + + + MACAddress= + + The MAC address to use for the device. For tun or tap + devices, setting MACAddress= in the [NetDev] section is not + supported. Please specify it in [Link] section of the corresponding + systemd.network5 + file. If this option is not set, vlan devices inherit the MAC address of the + physical interface. For other kind of netdevs, if this option is not set, then MAC address is + generated based on the interface name and the + machine-id5. + + + + + + + + [Bridge] Section Options + + The [Bridge] section only applies for + netdevs of kind bridge, and accepts the + following keys: + + + + HelloTimeSec= + + HelloTimeSec specifies the number of seconds between two hello packets + sent out by the root bridge and the designated bridges. Hello packets are + used to communicate information about the topology throughout the entire + bridged local area network. + + + + MaxAgeSec= + + MaxAgeSec specifies the number of seconds of maximum message age. + If the last seen (received) hello packet is more than this number of + seconds old, the bridge in question will start the takeover procedure + in attempt to become the Root Bridge itself. + + + + ForwardDelaySec= + + ForwardDelaySec specifies the number of seconds spent in each + of the Listening and Learning states before the Forwarding state is entered. + + + + AgeingTimeSec= + + This specifies the number of seconds a MAC Address will be kept in + the forwarding database after having a packet received from this MAC Address. + + + + Priority= + + The priority of the bridge. An integer between 0 and 65535. A lower value + means higher priority. The bridge having the lowest priority will be elected as root bridge. + + + + GroupForwardMask= + + A 16-bit bitmask represented as an integer which allows forwarding of link + local frames with 802.1D reserved addresses (01:80:C2:00:00:0X). A logical AND + is performed between the specified bitmask and the exponentiation of 2^X, the + lower nibble of the last octet of the MAC address. For example, a value of 8 + would allow forwarding of frames addressed to 01:80:C2:00:00:03 (802.1X PAE). + + + + DefaultPVID= + + This specifies the default port VLAN ID of a newly attached bridge port. + Set this to an integer in the range 1–4094 or none to disable the PVID. + + + + MulticastQuerier= + + Takes a boolean. This setting controls the IFLA_BR_MCAST_QUERIER option in the kernel. + If enabled, the kernel will send general ICMP queries from a zero source address. + This feature should allow faster convergence on startup, but it causes some + multicast-aware switches to misbehave and disrupt forwarding of multicast packets. + When unset, the kernel's default will be used. + + + + + MulticastSnooping= + + Takes a boolean. This setting controls the IFLA_BR_MCAST_SNOOPING option in the kernel. + If enabled, IGMP snooping monitors the Internet Group Management Protocol (IGMP) traffic + between hosts and multicast routers. When unset, the kernel's default will be used. + + + + + VLANFiltering= + + Takes a boolean. This setting controls the IFLA_BR_VLAN_FILTERING option in the kernel. + If enabled, the bridge will be started in VLAN-filtering mode. When unset, the kernel's default will be used. + + + + + STP= + + Takes a boolean. This enables the bridge's Spanning Tree Protocol (STP). + When unset, the kernel's default will be used. + + + + + MulticastIGMPVersion= + + Allows to change bridge's multicast Internet Group Management Protocol (IGMP) version. + Takes an interger 2 or 3. When unset, the kernel's default will be used. + + + + + + + + [VLAN] Section Options + + The [VLAN] section only applies for + netdevs of kind vlan, and accepts the + following key: + + + + Id= + + The VLAN ID to use. An integer in the range 0–4094. + This option is compulsory. + + + + GVRP= + + Takes a boolean. The Generic VLAN Registration Protocol (GVRP) is a protocol that + allows automatic learning of VLANs on a network. + When unset, the kernel's default will be used. + + + + + MVRP= + + Takes a boolean. Multiple VLAN Registration Protocol (MVRP) formerly known as GARP VLAN + Registration Protocol (GVRP) is a standards-based Layer 2 network protocol, + for automatic configuration of VLAN information on switches. It was defined + in the 802.1ak amendment to 802.1Q-2005. When unset, the kernel's default will be used. + + + + + LooseBinding= + + Takes a boolean. The VLAN loose binding mode, in which only the operational state is passed + from the parent to the associated VLANs, but the VLAN device state is not changed. + When unset, the kernel's default will be used. + + + + ReorderHeader= + + Takes a boolean. The VLAN reorder header is set VLAN interfaces behave like physical interfaces. + When unset, the kernel's default will be used. + + + + + + + [MACVLAN] Section Options + + The [MACVLAN] section only applies for + netdevs of kind macvlan, and accepts the + following key: + + + + Mode= + + The MACVLAN mode to use. The supported options are + private, + vepa, + bridge, and + passthru. + + + + + + + + [MACVTAP] Section Options + + The [MACVTAP] section applies for + netdevs of kind macvtap and accepts the + same key as [MACVLAN]. + + + + [IPVLAN] Section Options + + The [IPVLAN] section only applies for + netdevs of kind ipvlan, and accepts the + following key: + + + + Mode= + + The IPVLAN mode to use. The supported options are + L2,L3 and L3S. + + + + + Flags= + + The IPVLAN flags to use. The supported options are + bridge,private and vepa. + + + + + + + + [IPVTAP] Section Options + + The [IPVTAP] section only applies for + netdevs of kind ipvtap and accepts the + same key as [IPVLAN]. + + + + [VXLAN] Section Options + + The [VXLAN] section only applies for + netdevs of kind vxlan, and accepts the + following keys: + + + + VNI= + + The VXLAN Network Identifier (or VXLAN Segment ID). Takes a number in the range 1-16777215. + + + + Remote= + + Configures destination IP address. + + + + Local= + + Configures local IP address. + + + + Group= + + Configures VXLAN multicast group IP address. All members of a VXLAN must use the same multicast group address. + + + + TOS= + + The Type Of Service byte value for a vxlan interface. + + + + TTL= + + A fixed Time To Live N on Virtual eXtensible Local Area Network packets. + Takes inherit or a number in the range 0–255. 0 is a special + value meaning inherit the inner protocol's TTL value. inherit + means that it will inherit the outer protocol's TTL value. + + + + MacLearning= + + Takes a boolean. When true, enables dynamic MAC learning + to discover remote MAC addresses. + + + + FDBAgeingSec= + + The lifetime of Forwarding Database entry learnt by + the kernel, in seconds. + + + + MaximumFDBEntries= + + Configures maximum number of FDB entries. + + + + ReduceARPProxy= + + Takes a boolean. When true, bridge-connected VXLAN tunnel + endpoint answers ARP requests from the local bridge on behalf + of remote Distributed Overlay Virtual Ethernet + + (DVOE) clients. Defaults to false. + + + + L2MissNotification= + + Takes a boolean. When true, enables netlink LLADDR miss + notifications. + + + + L3MissNotification= + + Takes a boolean. When true, enables netlink IP address miss + notifications. + + + + RouteShortCircuit= + + Takes a boolean. When true, route short circuiting is turned + on. + + + + UDPChecksum= + + Takes a boolean. When true, transmitting UDP checksums when doing VXLAN/IPv4 is turned on. + + + + UDP6ZeroChecksumTx= + + Takes a boolean. When true, sending zero checksums in VXLAN/IPv6 is turned on. + + + + UDP6ZeroChecksumRx= + + Takes a boolean. When true, receiving zero checksums in VXLAN/IPv6 is turned on. + + + + RemoteChecksumTx= + + Takes a boolean. When true, remote transmit checksum offload of VXLAN is turned on. + + + + RemoteChecksumRx= + + Takes a boolean. When true, remote receive checksum offload in VXLAN is turned on. + + + + GroupPolicyExtension= + + Takes a boolean. When true, it enables Group Policy VXLAN extension security label mechanism + across network peers based on VXLAN. For details about the Group Policy VXLAN, see the + + VXLAN Group Policy document. Defaults to false. + + + + GenericProtocolExtension= + + Takes a boolean. When true, Generic Protocol Extension extends the existing VXLAN protocol + to provide protocol typing, OAM, and versioning capabilities. For details about the VXLAN GPE + Header, see the + Generic Protocol Extension for VXLAN document. If destination port is not specified and + Generic Protocol Extension is set then default port of 4790 is used. Defaults to false. + + + + DestinationPort= + + Configures the default destination UDP port on a per-device basis. + If destination port is not specified then Linux kernel default will be used. + Set destination port 4789 to get the IANA assigned value. If not set or if the + destination port is assigned the empty string the default port of 4789 is used. + + + + PortRange= + + Configures VXLAN port range. VXLAN bases source + UDP port based on flow to help the receiver to be able + to load balance based on outer header flow. It + restricts the port range to the normal UDP local + ports, and allows overriding via configuration. + + + + FlowLabel= + + Specifies the flow label to use in outgoing packets. + The valid range is 0-1048575. + + + + + IPDoNotFragment= + + Allows to set the IPv4 Do not Fragment (DF) bit in outgoing packets, or to inherit its + value from the IPv4 inner header. Takes a boolean value, or inherit. Set + to inherit if the encapsulated protocol is IPv6. When unset, the kernel's + default will be used. + + + + + + + [GENEVE] Section Options + + The [GENEVE] section only applies for + netdevs of kind geneve, and accepts the + following keys: + + + + Id= + + Specifies the Virtual Network Identifier (VNI) to use. Ranges [0-16777215]. This field is mandatory. + + + + Remote= + + Specifies the unicast destination IP address to use in outgoing packets. + + + + TOS= + + Specifies the TOS value to use in outgoing packets. Ranges [1-255]. + + + + TTL= + + Accepts the same key in [VXLAN] section except when unset or + set to 0, the kernel's default will be used meaning that packets TTL will be set from + /proc/sys/net/ipv4/ip_default_ttl. + + + + UDPChecksum= + + Takes a boolean. When true, specifies if UDP checksum is calculated for transmitted packets over IPv4. + + + + UDP6ZeroChecksumTx= + + Takes a boolean. When true, skip UDP checksum calculation for transmitted packets over IPv6. + + + + UDP6ZeroChecksumRx= + + Takes a boolean. When true, allows incoming UDP packets over IPv6 with zero checksum field. + + + + DestinationPort= + + Specifies destination port. Defaults to 6081. If not set or assigned the empty string, the default + port of 6081 is used. + + + + FlowLabel= + + Specifies the flow label to use in outgoing packets. + + + + IPDoNotFragment= + + Accepts the same key in [VXLAN] section. + + + + + + + [L2TP] Section Options + + The [L2TP] section only applies for + netdevs of kind l2tp, and accepts the + following keys: + + + + TunnelId= + + Specifies the tunnel id. The value used must match the PeerTunnelId= value being used at the peer. + Ranges a number between 1 and 4294967295). This option is compulsory. + + + + PeerTunnelId= + + Specifies the peer tunnel id. The value used must match the PeerTunnelId= value being used at the peer. + Ranges a number between 1 and 4294967295). This option is compulsory. + + + + Remote= + + Specifies the IP address of the remote peer. This option is compulsory. + + + + Local= + + Specifies the IP address of the local interface. Takes an IP address, or the special values + auto, static, or dynamic. When an address + is set, then the local interface must have the address. If auto, then one of the + addresses on the local interface is used. Similarly, if static or + dynamic is set, then one of the static or dynamic addresses on the local + interface is used. Defaults to auto. + + + + EncapsulationType= + + Specifies the encapsulation type of the tunnel. Takes one of udp or ip. + + + + UDPSourcePort= + + Specifies the UDP source port to be used for the tunnel. When UDP encapsulation is selected it's mandotory. Ignored when ip + encapsulation is selected. + + + + DestinationPort= + + Specifies destination port. When UDP encapsulation is selected it's mandotory. Ignored when ip + encapsulation is selected. + + + + UDPChecksum= + + Takes a boolean. When true, specifies if UDP checksum is calculated for transmitted packets over IPv4. + + + + UDP6ZeroChecksumTx= + + Takes a boolean. When true, skip UDP checksum calculation for transmitted packets over IPv6. + + + + UDP6ZeroChecksumRx= + + Takes a boolean. When true, allows incoming UDP packets over IPv6 with zero checksum field. + + + + + + + [L2TPSession] Section Options + + The [L2TPSession] section only applies for + netdevs of kind l2tp, and accepts the + following keys: + + + Name= + + Specifies the name of the session. This option is compulsory. + + + + SessionId= + + Specifies the session id. The value used must match the SessionId= value being used at the peer. + Ranges a number between 1 and 4294967295). This option is compulsory. + + + + PeerSessionId= + + Specifies the peer session id. The value used must match the PeerSessionId= value being used at the peer. + Ranges a number between 1 and 4294967295). This option is compulsory. + + + + Layer2SpecificHeader= + + Specifies layer2specific header type of the session. One of none or default. Defaults to default. + + + + + + + [MACsec] Section Options + + The [MACsec] section only applies for network devices of kind + macsec, and accepts the following keys: + + + + Port= + + Specifies the port to be used for the MACsec transmit channel. The port is used to make + secure channel identifier (SCI). Takes a value between 1 and 65535. Defaults to unset. + + + + + Encrypt= + + Takes a boolean. When true, enable encryption. Defaults to unset. + + + + + + + [MACsecReceiveChannel] Section Options + The [MACsecReceiveChannel] section only applies for network devices of + kind macsec, and accepts the following keys: + + + + Port= + + Specifies the port to be used for the MACsec receive channel. The port is used to make + secure channel identifier (SCI). Takes a value between 1 and 65535. This option is + compulsory, and is not set by default. + + + + MACAddress= + + Specifies the MAC address to be used for the MACsec receive channel. The MAC address + used to make secure channel identifier (SCI). This option is compulsory, and is not set by + default. + + + + + + + [MACsecTransmitAssociation] Section Options + + The [MACsecTransmitAssociation] section only applies for network devices + of kind macsec, and accepts the following keys: + + + + PacketNumber= + + Specifies the packet number to be used for replay protection and the construction of + the initialization vector (along with the secure channel identifier [SCI]). Takes a value + between 1-4,294,967,295. Defaults to unset. + + + + + KeyId= + + Specifies the identification for the key. Takes a number between 0-255. This option + is compulsory, and is not set by default. + + + + Key= + + Specifies the encryption key used in the transmission channel. The same key must be + configured on the peer’s matching receive channel. This option is compulsory, and is not set + by default. Takes a 128-bit key encoded in a hexadecimal string, for example + dffafc8d7b9a43d5b9a3dfbbf6a30c16. + + + + KeyFile= + + Takes a absolute path to a file which contains a 128-bit key encoded in a hexadecimal + string, which will be used in the transmission channel. When this option is specified, + Key= is ignored. Note that the file must be readable by the user + systemd-network, so it should be, e.g., owned by + root:systemd-network with a 0640 file mode. + + + + Activate= + + Takes a boolean. If enabled, then the security association is activated. Defaults to + unset. + + + + UseForEncoding= + + Takes a boolean. If enabled, then the security association is used for encoding. Only + one [MACsecTransmitAssociation] section can enable this option. When enabled, + Activate=yes is implied. Defaults to unset. + + + + + + + [MACsecReceiveAssociation] Section Options + + The [MACsecReceiveAssociation] section only applies for + network devices of kind macsec, and accepts the + following keys: + + + + Port= + + Accepts the same key in [MACsecReceiveChannel] section. + + + + MACAddress= + + Accepts the same key in [MACsecReceiveChannel] section. + + + + PacketNumber= + + Accepts the same key in [MACsecTransmitAssociation] section. + + + + KeyId= + + Accepts the same key in [MACsecTransmitAssociation] section. + + + + Key= + + Accepts the same key in [MACsecTransmitAssociation] section. + + + + KeyFile= + + Accepts the same key in [MACsecTransmitAssociation] section. + + + + Activate= + + Accepts the same key in [MACsecTransmitAssociation] section. + + + + + + + [Tunnel] Section Options + + The [Tunnel] section only applies for + netdevs of kind + ipip, + sit, + gre, + gretap, + ip6gre, + ip6gretap, + vti, + vti6, + ip6tnl, and + erspan and accepts + the following keys: + + + + Local= + + A static local address for tunneled packets. It must be an address on another interface of + this host, or the special value any. + + + + Remote= + + The remote endpoint of the tunnel. Takes an IP address or the special value + any. + + + + TOS= + + The Type Of Service byte value for a tunnel interface. + For details about the TOS, see the + Type of + Service in the Internet Protocol Suite document. + + + + + TTL= + + A fixed Time To Live N on tunneled packets. N is a + number in the range 1–255. 0 is a special value meaning that + packets inherit the TTL value. The default value for IPv4 + tunnels is: inherit. The default value for IPv6 tunnels is + 64. + + + + DiscoverPathMTU= + + Takes a boolean. When true, enables Path MTU Discovery on + the tunnel. + + + + IPv6FlowLabel= + + Configures the 20-bit flow label (see + RFC 6437) field in the IPv6 header (see + RFC 2460), which is used by a node to label packets of a flow. + It is only used for IPv6 tunnels. + A flow label of zero is used to indicate packets that have + not been labeled. + It can be configured to a value in the range 0–0xFFFFF, or be + set to inherit, in which case the original flowlabel is used. + + + + CopyDSCP= + + Takes a boolean. When true, the Differentiated Service Code + Point (DSCP) field will be copied to the inner header from + outer header during the decapsulation of an IPv6 tunnel + packet. DSCP is a field in an IP packet that enables different + levels of service to be assigned to network traffic. + Defaults to no. + + + + + EncapsulationLimit= + + The Tunnel Encapsulation Limit option specifies how many additional + levels of encapsulation are permitted to be prepended to the packet. + For example, a Tunnel Encapsulation Limit option containing a limit + value of zero means that a packet carrying that option may not enter + another tunnel before exiting the current tunnel. + (see RFC 2473). + The valid range is 0–255 and none. Defaults to 4. + + + + + Key= + + The Key= parameter specifies the same key to use in + both directions (InputKey= and OutputKey=). + The Key= is either a number or an IPv4 address-like dotted quad. + It is used as mark-configured SAD/SPD entry as part of the lookup key (both in data + and control path) in ip xfrm (framework used to implement IPsec protocol). + See + ip-xfrm — transform configuration for details. It is only used for VTI/VTI6, + GRE, GRETAP, and ERSPAN tunnels. + + + + InputKey= + + The InputKey= parameter specifies the key to use for input. + The format is same as Key=. It is only used for VTI/VTI6, GRE, GRETAP, + and ERSPAN tunnels. + + + + OutputKey= + + The OutputKey= parameter specifies the key to use for output. + The format is same as Key=. It is only used for VTI/VTI6, GRE, GRETAP, + and ERSPAN tunnels. + + + + Mode= + + An ip6tnl tunnel can be in one of three + modes + ip6ip6 for IPv6 over IPv6, + ipip6 for IPv4 over IPv6 or + any for either. + + + + + Independent= + + Takes a boolean. When true tunnel does not require .network file. Created as "tunnel@NONE". + Defaults to false. + + + + + AssignToLoopback= + + Takes a boolean. If set to yes, the loopback interface lo + is used as the underlying device of the tunnel interface. Defaults to no. + + + + AllowLocalRemote= + + Takes a boolean. When true allows tunnel traffic on ip6tnl devices where the remote endpoint is a local host address. + When unset, the kernel's default will be used. + + + + + FooOverUDP= + + Takes a boolean. Specifies whether FooOverUDP= tunnel is to be configured. + Defaults to false. This takes effects only for IPIP, SIT, GRE, and GRETAP tunnels. + For more detail information see + Foo over UDP + + + + FOUDestinationPort= + + This setting specifies the UDP destination port for encapsulation. + This field is mandatory when FooOverUDP=yes, and is not set by default. + + + + FOUSourcePort= + + This setting specifies the UDP source port for encapsulation. Defaults to 0 + — that is, the source port for packets is left to the network stack to decide. + + + + Encapsulation= + + Accepts the same key as in the [FooOverUDP] section. + + + + IPv6RapidDeploymentPrefix= + + Reconfigure the tunnel for IPv6 Rapid + Deployment, also known as 6rd. The value is an ISP-specific IPv6 prefix with a non-zero length. Only + applicable to SIT tunnels. + + + + ISATAP= + + Takes a boolean. If set, configures the tunnel as Intra-Site Automatic Tunnel Addressing Protocol (ISATAP) tunnel. + Only applicable to SIT tunnels. When unset, the kernel's default will be used. + + + + SerializeTunneledPackets= + + Takes a boolean. If set to yes, then packets are serialized. Only applies for GRE, + GRETAP, and ERSPAN tunnels. When unset, the kernel's default will be used. + + + + + ERSPANIndex= + + Specifies the ERSPAN index field for the interface, an integer in the range 1-1048575 associated with + the ERSPAN traffic's source port and direction. This field is mandatory. + + + + + + + + [FooOverUDP] Section Options + + The [FooOverUDP] section only applies for + netdevs of kind fou and accepts the + following keys: + + + + Encapsulation= + + Specifies the encapsulation mechanism used to store networking packets of various protocols inside the UDP packets. Supports the following values: + + FooOverUDP provides the simplest no frills model of UDP encapsulation, it simply encapsulates + packets directly in the UDP payload. + GenericUDPEncapsulation is a generic and extensible encapsulation, it allows encapsulation of packets for any IP + protocol and optional data as part of the encapsulation. + For more detailed information see Generic UDP Encapsulation. + Defaults to FooOverUDP. + + + + + Port= + + Specifies the port number, where the IP encapsulation packets will arrive. Please take note that the packets + will arrive with the encapsulation will be removed. Then they will be manually fed back into the network stack, and sent ahead + for delivery to the real destination. This option is mandatory. + + + + PeerPort= + + Specifies the peer port number. Defaults to unset. Note that when peer port is set Peer= address is mandotory. + + + + Protocol= + + The Protocol= specifies the protocol number of the packets arriving + at the UDP port. When Encapsulation=FooOverUDP, this field is mandatory + and is not set by default. Takes an IP protocol name such as gre or + ipip, or an integer within the range 1-255. When + Encapsulation=GenericUDPEncapsulation, this must not be specified. + + + + Peer= + + Configures peer IP address. Note that when peer address is set PeerPort= is mandotory. + + + + Local= + + Configures local IP address. + + + + + + + [Peer] Section Options + + The [Peer] section only applies for + netdevs of kind veth and accepts the + following keys: + + + + Name= + + The interface name used when creating the netdev. + This option is compulsory. + + + + MACAddress= + + The peer MACAddress, if not set, it is generated in + the same way as the MAC address of the main + interface. + + + + + + + [VXCAN] Section Options + + The [VXCAN] section only applies for + netdevs of kind vxcan and accepts the + following key: + + + + Peer= + + The peer interface name used when creating the netdev. + This option is compulsory. + + + + + + + [Tun] Section Options + + The [Tun] section only applies for + netdevs of kind tun, and accepts the following + keys: + + + + MultiQueue= + Takes a boolean. Configures whether + to use multiple file descriptors (queues) to parallelize + packets sending and receiving. Defaults to + no. + + + + PacketInfo= + Takes a boolean. Configures whether + packets should be prepended with four extra bytes (two flag + bytes and two protocol bytes). If disabled, it indicates that + the packets will be pure IP packets. Defaults to + no. + + + + VNetHeader= + Takes a boolean. Configures + IFF_VNET_HDR flag for a tun or tap device. It allows sending + and receiving larger Generic Segmentation Offload (GSO) + packets. This may increase throughput significantly. + Defaults to + no. + + + + User= + User to grant access to the + /dev/net/tun device. + + + + Group= + Group to grant access to the + /dev/net/tun device. + + + + + + + [Tap] Section Options + + The [Tap] section only applies for + netdevs of kind tap, and accepts the same keys + as the [Tun] section. + + + + [WireGuard] Section Options + + The [WireGuard] section accepts the following + keys: + + + + PrivateKey= + + The Base64 encoded private key for the interface. It can be + generated using the wg genkey command + (see wg8). + This option or PrivateKeyFile= is mandatory to use WireGuard. + Note that because this information is secret, you may want to set + the permissions of the .netdev file to be owned by root:systemd-network + with a 0640 file mode. + + + + PrivateKeyFile= + + Takes an absolute path to a file which contains the Base64 encoded private key for the interface. + When this option is specified, then PrivateKey= is ignored. + Note that the file must be readable by the user systemd-network, so it + should be, e.g., owned by root:systemd-network with a + 0640 file mode. + + + + ListenPort= + + Sets UDP port for listening. Takes either value between 1 and 65535 + or auto. If auto is specified, + the port is automatically generated based on interface name. + Defaults to auto. + + + + FirewallMark= + + Sets a firewall mark on outgoing WireGuard packets from this interface. Takes a number between 1 and 4294967295. + + + + + + + [WireGuardPeer] Section Options + + The [WireGuardPeer] section accepts the following + keys: + + + + PublicKey= + + Sets a Base64 encoded public key calculated by wg pubkey + (see wg8) + from a private key, and usually transmitted out of band to the + author of the configuration file. This option is mandatory for this + section. + + + + PresharedKey= + + Optional preshared key for the interface. It can be generated + by the wg genpsk command. This option adds an + additional layer of symmetric-key cryptography to be mixed into the + already existing public-key cryptography, for post-quantum + resistance. + Note that because this information is secret, you may want to set + the permissions of the .netdev file to be owned by root:systemd-networkd + with a 0640 file mode. + + + + PresharedKeyFile= + + Takes an absolute path to a file which contains the Base64 encoded preshared key for the + peer. When this option is specified, then PresharedKey= is ignored. + Note that the file must be readable by the user systemd-network, so it + should be, e.g., owned by root:systemd-network with a + 0640 file mode. + + + + AllowedIPs= + + Sets a comma-separated list of IP (v4 or v6) addresses with CIDR masks + from which this peer is allowed to send incoming traffic and to + which outgoing traffic for this peer is directed. The catch-all + 0.0.0.0/0 may be specified for matching all IPv4 addresses, and + ::/0 may be specified for matching all IPv6 addresses. + + + + Endpoint= + + Sets an endpoint IP address or hostname, followed by a colon, and then + a port number. This endpoint will be updated automatically once to + the most recent source IP address and port of correctly + authenticated packets from the peer at configuration time. + + + + PersistentKeepalive= + + Sets a seconds interval, between 1 and 65535 inclusive, of how often + to send an authenticated empty packet to the peer for the purpose + of keeping a stateful firewall or NAT mapping valid persistently. + For example, if the interface very rarely sends traffic, but it + might at anytime receive traffic from a peer, and it is behind NAT, + the interface might benefit from having a persistent keepalive + interval of 25 seconds. If set to 0 or "off", this option is + disabled. By default or when unspecified, this option is off. + Most users will not need this. + + + + + + + [Bond] Section Options + + The [Bond] section accepts the following + key: + + + + Mode= + + Specifies one of the bonding policies. The default is + balance-rr (round robin). Possible values are + balance-rr, + active-backup, + balance-xor, + broadcast, + 802.3ad, + balance-tlb, and + balance-alb. + + + + + + TransmitHashPolicy= + + Selects the transmit hash policy to use for slave + selection in balance-xor, 802.3ad, and tlb modes. Possible + values are + layer2, + layer3+4, + layer2+3, + encap2+3, and + encap3+4. + + + + + + LACPTransmitRate= + + Specifies the rate with which link partner transmits + Link Aggregation Control Protocol Data Unit packets in + 802.3ad mode. Possible values are slow, + which requests partner to transmit LACPDUs every 30 seconds, + and fast, which requests partner to + transmit LACPDUs every second. The default value is + slow. + + + + + MIIMonitorSec= + + Specifies the frequency that Media Independent + Interface link monitoring will occur. A value of zero + disables MII link monitoring. This value is rounded down to + the nearest millisecond. The default value is 0. + + + + + UpDelaySec= + + Specifies the delay before a link is enabled after a + link up status has been detected. This value is rounded down + to a multiple of MIIMonitorSec. The default value is + 0. + + + + + DownDelaySec= + + Specifies the delay before a link is disabled after a + link down status has been detected. This value is rounded + down to a multiple of MIIMonitorSec. The default value is + 0. + + + + + LearnPacketIntervalSec= + + Specifies the number of seconds between instances where the bonding + driver sends learning packets to each slave peer switch. + The valid range is 1–0x7fffffff; the default value is 1. This option + has an effect only for the balance-tlb and balance-alb modes. + + + + + AdSelect= + + Specifies the 802.3ad aggregation selection logic to use. Possible values are + stable, + bandwidth and + count. + + + + + + AdActorSystemPriority= + + Specifies the 802.3ad actor system priority. Ranges [1-65535]. + + + + + AdUserPortKey= + + Specifies the 802.3ad user defined portion of the port key. Ranges [0-1023]. + + + + + AdActorSystem= + + Specifies the 802.3ad system mac address. This can not be either NULL or Multicast. + + + + + FailOverMACPolicy= + + Specifies whether the active-backup mode should set all slaves to + the same MAC address at the time of enslavement or, when enabled, to perform special handling of the + bond's MAC address in accordance with the selected policy. The default policy is none. + Possible values are + none, + active and + follow. + + + + + + ARPValidate= + + Specifies whether or not ARP probes and replies should be + validated in any mode that supports ARP monitoring, or whether + non-ARP traffic should be filtered (disregarded) for link + monitoring purposes. Possible values are + none, + active, + backup and + all. + + + + + + ARPIntervalSec= + + Specifies the ARP link monitoring frequency. A value of 0 disables ARP monitoring. The + default value is 0, and the default unit seconds. + + + + + + ARPIPTargets= + + Specifies the IP addresses to use as ARP monitoring peers when + ARPIntervalSec is greater than 0. These are the targets of the ARP request + sent to determine the health of the link to the targets. + Specify these values in IPv4 dotted decimal format. At least one IP + address must be given for ARP monitoring to function. The + maximum number of targets that can be specified is 16. The + default value is no IP addresses. + + + + + + ARPAllTargets= + + Specifies the quantity of ARPIPTargets that must be reachable + in order for the ARP monitor to consider a slave as being up. + This option affects only active-backup mode for slaves with + ARPValidate enabled. Possible values are + any and + all. + + + + + + PrimaryReselectPolicy= + + Specifies the reselection policy for the primary slave. This + affects how the primary slave is chosen to become the active slave + when failure of the active slave or recovery of the primary slave + occurs. This option is designed to prevent flip-flopping between + the primary slave and other slaves. Possible values are + always, + better and + failure. + + + + + + ResendIGMP= + + Specifies the number of IGMP membership reports to be issued after + a failover event. One membership report is issued immediately after + the failover, subsequent packets are sent in each 200ms interval. + The valid range is 0–255. Defaults to 1. A value of 0 + prevents the IGMP membership report from being issued in response + to the failover event. + + + + + + PacketsPerSlave= + + Specify the number of packets to transmit through a slave before + moving to the next one. When set to 0, then a slave is chosen at + random. The valid range is 0–65535. Defaults to 1. This option + only has effect when in balance-rr mode. + + + + + + GratuitousARP= + + Specify the number of peer notifications (gratuitous ARPs and + unsolicited IPv6 Neighbor Advertisements) to be issued after a + failover event. As soon as the link is up on the new slave, + a peer notification is sent on the bonding device and each + VLAN sub-device. This is repeated at each link monitor interval + (ARPIntervalSec or MIIMonitorSec, whichever is active) if the number is + greater than 1. The valid range is 0–255. The default value is 1. + These options affect only the active-backup mode. + + + + + + AllSlavesActive= + + Takes a boolean. Specifies that duplicate frames (received on inactive ports) + should be dropped when false, or delivered when true. Normally, bonding will drop + duplicate frames (received on inactive ports), which is desirable for + most users. But there are some times it is nice to allow duplicate + frames to be delivered. The default value is false (drop duplicate frames + received on inactive ports). + + + + + + DynamicTransmitLoadBalancing= + + Takes a boolean. Specifies if dynamic shuffling of flows is enabled. Applies only + for balance-tlb mode. Defaults to unset. + + + + + + MinLinks= + + Specifies the minimum number of links that must be active before + asserting carrier. The default value is 0. + + + + + + For more detail information see + + Linux Ethernet Bonding Driver HOWTO + + + + [Xfrm] Section Options + + The [Xfrm] section accepts the following + keys: + + + + InterfaceId= + + Sets the ID/key of the xfrm interface which needs to be associated with a SA/policy. + Can be decimal or hexadecimal, valid range is 0-0xffffffff, defaults to 0. + + + + Independent= + + Takes a boolean. If set to no, the xfrm interface should have an + underlying device which can be used for hardware offloading. Defaults to no. + See systemd.network5 + for how to configure the underlying device. + + + + + For more detail information see + + Virtual xfrm interfaces + + + + [VRF] Section Options + The [VRF] section only applies for + netdevs of kind vrf and accepts the + following key: + + + + Table= + + The numeric routing table identifier. This option is compulsory. + + + + + + + Examples + + /etc/systemd/network/25-bridge.netdev + + [NetDev] +Name=bridge0 +Kind=bridge + + + + /etc/systemd/network/25-vlan1.netdev + + [Match] +Virtualization=no + +[NetDev] +Name=vlan1 +Kind=vlan + +[VLAN] +Id=1 + + + /etc/systemd/network/25-ipip.netdev + [NetDev] +Name=ipip-tun +Kind=ipip +MTUBytes=1480 + +[Tunnel] +Local=192.168.223.238 +Remote=192.169.224.239 +TTL=64 + + + /etc/systemd/network/1-fou-tunnel.netdev + [NetDev] +Name=fou-tun +Kind=fou + +[FooOverUDP] +Port=5555 +Protocol=4 + + + + /etc/systemd/network/25-fou-ipip.netdev + [NetDev] +Name=ipip-tun +Kind=ipip + +[Tunnel] +Independent=yes +Local=10.65.208.212 +Remote=10.65.208.211 +FooOverUDP=yes +FOUDestinationPort=5555 + + + + /etc/systemd/network/25-tap.netdev + [NetDev] +Name=tap-test +Kind=tap + +[Tap] +MultiQueue=yes +PacketInfo=yes + + + /etc/systemd/network/25-sit.netdev + [NetDev] +Name=sit-tun +Kind=sit +MTUBytes=1480 + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 + + + + /etc/systemd/network/25-6rd.netdev + [NetDev] +Name=6rd-tun +Kind=sit +MTUBytes=1480 + +[Tunnel] +Local=10.65.223.238 +IPv6RapidDeploymentPrefix=2602::/24 + + + + /etc/systemd/network/25-gre.netdev + [NetDev] +Name=gre-tun +Kind=gre +MTUBytes=1480 + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 + + + + /etc/systemd/network/25-ip6gre.netdev + [NetDev] +Name=ip6gre-tun +Kind=ip6gre + +[Tunnel] +Key=123 + + + + /etc/systemd/network/25-vti.netdev + + [NetDev] +Name=vti-tun +Kind=vti +MTUBytes=1480 + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 + + + + /etc/systemd/network/25-veth.netdev + [NetDev] +Name=veth-test +Kind=veth + +[Peer] +Name=veth-peer + + + + /etc/systemd/network/25-bond.netdev + [NetDev] +Name=bond1 +Kind=bond + +[Bond] +Mode=802.3ad +TransmitHashPolicy=layer3+4 +MIIMonitorSec=1s +LACPTransmitRate=fast + + + + + /etc/systemd/network/25-dummy.netdev + [NetDev] +Name=dummy-test +Kind=dummy +MACAddress=12:34:56:78:9a:bc + + + /etc/systemd/network/25-vrf.netdev + Create a VRF interface with table 42. + [NetDev] +Name=vrf-test +Kind=vrf + +[VRF] +Table=42 + + + + /etc/systemd/network/25-macvtap.netdev + Create a MacVTap device. + [NetDev] +Name=macvtap-test +Kind=macvtap + + + + /etc/systemd/network/25-wireguard.netdev + [NetDev] +Name=wg0 +Kind=wireguard + +[WireGuard] +PrivateKey=EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong= +ListenPort=51820 + +[WireGuardPeer] +PublicKey=RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA= +AllowedIPs=fd31:bf08:57cb::/48,192.168.26.0/24 +Endpoint=wireguard.example.com:51820 + + + + /etc/systemd/network/27-xfrm.netdev + [NetDev] +Name=xfrm0 +Kind=xfrm + +[Xfrm] +Independent=yes + + + + + See Also + + systemd1, + systemd-networkd8, + systemd.link5, + systemd.network5 + + + +
diff --git a/man/systemd.network.xml b/man/systemd.network.xml new file mode 100644 index 00000000..8254d7ca --- /dev/null +++ b/man/systemd.network.xml @@ -0,0 +1,2664 @@ + + + + + + + + systemd.network + systemd + + + + systemd.network + 5 + + + + systemd.network + Network configuration + + + + network.network + + + + Description + + Network setup is performed by + systemd-networkd8. + + + The main network file must have the extension .network; other + extensions are ignored. Networks are applied to links whenever the links appear. + + The .network files are read from the files located in the system network + directories /usr/lib/systemd/network and + /usr/local/lib/systemd/network, the volatile runtime network directory + /run/systemd/network and the local administration network directory + /etc/systemd/network. All configuration files are collectively sorted and processed + in lexical order, regardless of the directories in which they live. However, files with identical + filenames replace each other. Files in /etc have the highest priority, files in + /run take precedence over files with the same name under + /usr. This can be used to override a system-supplied configuration file with a local + file if needed. As a special case, an empty file (file size 0) or symlink with the same name pointing to + /dev/null disables the configuration file entirely (it is "masked"). + + Along with the network file foo.network, a "drop-in" directory + foo.network.d/ may exist. All files with the suffix + .conf from this directory will be parsed after the file itself is + parsed. This is useful to alter or add configuration settings, without having to modify the main + configuration file. Each drop-in file must have appropriate section headers. + + In addition to /etc/systemd/network, drop-in .d + directories can be placed in /usr/lib/systemd/network or + /run/systemd/network directories. Drop-in files in + /etc take precedence over those in /run which in turn + take precedence over those in /usr/lib. Drop-in files under any of these + directories take precedence over the main network file wherever located. + + Note that an interface without any static IPv6 addresses configured, and neither DHCPv6 + nor IPv6LL enabled, shall be considered to have no IPv6 support. IPv6 will be automatically + disabled for that interface by writing "1" to + /proc/sys/net/ipv6/conf/ifname/disable_ipv6. + + + + + [Match] Section Options + + The network file contains a [Match] + section, which determines if a given network file may be applied + to a given device; and a [Network] section + specifying how the device should be configured. The first (in + lexical order) of the network files that matches a given device + is applied, all later files are ignored, even if they match as + well. + + A network file is said to match a network interface if all matches specified by the + [Match] section are satisfied. When a network file does not contain valid + settings in [Match] section, then the file will match all interfaces and + systemd-networkd warns about that. Hint: to avoid the warning and to make it + clear that all interfaces shall be matched, add the following: + Name=* + The following keys are accepted: + + + + MACAddress= + + A whitespace-separated list of hardware addresses. Use full colon-, hyphen- or dot-delimited hexadecimal. See the example below. + This option may appear more than once, in which case the lists are merged. If the empty string is assigned to this option, the list + of hardware addresses defined prior to this is reset. + + Example: + MACAddress=01:23:45:67:89:ab 00-11-22-33-44-55 AABB.CCDD.EEFF + + + + Path= + + A whitespace-separated list of shell-style globs + matching the persistent path, as exposed by the udev + property ID_PATH. If the list is + prefixed with a "!", the test is inverted; i.e. it is + true when ID_PATH does not match any + item in the list. + + + + Driver= + + A whitespace-separated list of shell-style globs + matching the driver currently bound to the device, as + exposed by the udev property ID_NET_DRIVER + of its parent device, or if that is not set the driver + as exposed by ethtool -i of the + device itself. If the list is prefixed with a "!", the + test is inverted. + + + + Type= + + A whitespace-separated list of shell-style globs + matching the device type, as exposed by the udev property + DEVTYPE. If the list is prefixed with + a "!", the test is inverted. + + + + Name= + + A whitespace-separated list of shell-style globs + matching the device name, as exposed by the udev property + INTERFACE. If the list is prefixed + with a "!", the test is inverted. + + + + Property= + + A whitespace-separated list of udev property name with its value after a equal + (=). If multiple properties are specified, the test results are ANDed. + If the list is prefixed with a "!", the test is inverted. If a value contains white + spaces, then please quote whole key and value pair. If a value contains quotation, then + please escape the quotation with \. + + Example: if a .network file has the following: + Property=ID_MODEL_ID=9999 "ID_VENDOR_FROM_DATABASE=vendor name" "KEY=with \"quotation\"" + then, the .network file matches only when an interface has all the above three properties. + + + + + WLANInterfaceType= + + A whitespace-separated list of wireless network type. Supported values are + ad-hoc, station, ap, + ap-vlan, wds, monitor, + mesh-point, p2p-client, p2p-go, + p2p-device, ocb, and nan. If the + list is prefixed with a "!", the test is inverted. + + + + + SSID= + + A whitespace-separated list of shell-style globs matching the SSID of the currently + connected wireless LAN. If the list is prefixed with a "!", the test is inverted. + + + + + BSSID= + + A whitespace-separated list of hardware address of the currently connected wireless + LAN. Use full colon-, hyphen- or dot-delimited hexadecimal. See the example in + MACAddress=. This option may appear more than one, in which case the + lists are merged. If the empty string is assigned to this option, the list of BSSID defined + prior to this is reset. + + + + Host= + + Matches against the hostname or machine ID of the host. See + ConditionHost= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + Virtualization= + + Checks whether the system is executed in a virtualized environment and optionally test + whether it is a specific implementation. See ConditionVirtualization= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + KernelCommandLine= + + Checks whether a specific kernel command line option is set. See + ConditionKernelCommandLine= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + KernelVersion= + + Checks whether the kernel version (as reported by uname -r) matches a + certain expression. See ConditionKernelVersion= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + Architecture= + + Checks whether the system is running on a specific architecture. See + ConditionArchitecture= in + systemd.unit5 + for details. When prefixed with an exclamation mark (!), the result is negated. + If an empty string is assigned, then previously assigned value is cleared. + + + + + + + + + [Link] Section Options + + The [Link] section accepts the following keys: + + + + MACAddress= + + The hardware address to set for the device. + + + + MTUBytes= + + The maximum transmission unit in bytes to set for the + device. The usual suffixes K, M, G, are supported and are + understood to the base of 1024. + Note that if IPv6 is enabled on the interface, and the MTU is chosen + below 1280 (the minimum MTU for IPv6) it will automatically be increased to this value. + + + + ARP= + + Takes a boolean. If set to true, the ARP (low-level Address Resolution Protocol) + for this interface is enabled. When unset, the kernel's default will be used. + For example, disabling ARP is useful when creating multiple MACVLAN or VLAN virtual + interfaces atop a single lower-level physical interface, which will then only serve as a + link/"bridge" device aggregating traffic to the same physical link and not participate in + the network otherwise. + + + + Multicast= + + Takes a boolean. If set to true, the multicast flag on the device is enabled. + + + + AllMulticast= + + Takes a boolean. If set to true, the driver retrieves all multicast packets from the network. + This happens when multicast routing is enabled. + + + + Unmanaged= + + Takes a boolean. When yes, no attempts are + made to bring up or configure matching links, equivalent to + when there are no matching network files. Defaults to + no. + This is useful for preventing later matching network + files from interfering with certain interfaces that are fully + controlled by other applications. + + + + RequiredForOnline= + + Takes a boolean or operational state. Please see + networkctl1 + for possible operational states. When yes, the network is deemed required when + determining whether the system is online when running + systemd-networkd-wait-online. When no, the network is ignored + when checking for online state. When an operational state is set, yes is implied, + and this controls the operational state required for the network interface to be considered online. + Defaults to yes. + + The network will be brought up normally in all cases, but in + the event that there is no address being assigned by DHCP or the + cable is not plugged in, the link will simply remain offline and be + skipped automatically by systemd-networkd-wait-online + if RequiredForOnline=no. + + + + + + + [Network] Section Options + + The [Network] section accepts the following keys: + + + + Description= + + A description of the device. This is only used for + presentation purposes. + + + + DHCP= + + Enables DHCPv4 and/or DHCPv6 client support. Accepts + yes, no, + ipv4, or ipv6. Defaults + to no. + + Note that DHCPv6 will by default be triggered by Router + Advertisement, if that is enabled, regardless of this parameter. + By enabling DHCPv6 support explicitly, the DHCPv6 client will + be started regardless of the presence of routers on the link, + or what flags the routers pass. See + IPv6AcceptRA=. + + Furthermore, note that by default the domain name + specified through DHCP is not used for name resolution. + See option below. + + See the [DHCPv4] or [DHCPv6] section below for + further configuration options for the DHCP client support. + + + + DHCPServer= + + Takes a boolean. If set to yes, DHCPv4 server will be started. Defaults + to no. Further settings for the DHCP + server may be set in the [DHCPServer] + section described below. + + + + LinkLocalAddressing= + + Enables link-local address autoconfiguration. Accepts yes, + no, ipv4, ipv6, + fallback, or ipv4-fallback. If + fallback or ipv4-fallback is specified, then an IPv4 + link-local address is configured only when DHCPv4 fails. If fallback, + an IPv6 link-local address is always configured, and if ipv4-fallback, + the address is not configured. Note that, the fallback mechanism works only when DHCPv4 + client is enabled, that is, it requires DHCP=yes or + DHCP=ipv4. If Bridge= is set, defaults to + no, and if not, defaults to ipv6. + + + + + IPv4LLRoute= + + Takes a boolean. If set to true, sets up the route needed for + non-IPv4LL hosts to communicate with IPv4LL-only hosts. Defaults + to false. + + + + + DefaultRouteOnDevice= + + Takes a boolean. If set to true, sets up the default route bound to the interface. + Defaults to false. This is useful when creating routes on point-to-point interfaces. + This is equivalent to e.g. the following. + ip route add default dev veth99 + + + + IPv6Token= + + An IPv6 address with the top 64 bits unset. When set, indicates the + 64-bit interface part of SLAAC IPv6 addresses for this link. Note that + the token is only ever used for SLAAC, and not for DHCPv6 addresses, even + in the case DHCP is requested by router advertisement. By default, the + token is autogenerated. + + + + LLMNR= + + Takes a boolean or resolve. When true, + enables Link-Local + Multicast Name Resolution on the link. When set to + resolve, only resolution is enabled, + but not host registration and announcement. Defaults to + true. This setting is read by + systemd-resolved.service8. + + + + MulticastDNS= + + Takes a boolean or resolve. When true, + enables Multicast + DNS support on the link. When set to + resolve, only resolution is enabled, + but not host or service registration and + announcement. Defaults to false. This setting is read by + systemd-resolved.service8. + + + + DNSOverTLS= + + Takes a boolean or opportunistic. + When true, enables + DNS-over-TLS + support on the link. + When set to opportunistic, compatibility with + non-DNS-over-TLS servers is increased, by automatically + turning off DNS-over-TLS servers in this case. + This option defines a per-interface setting for + resolved.conf5's + global DNSOverTLS= option. Defaults to + false. This setting is read by + systemd-resolved.service8. + + + + DNSSEC= + + Takes a boolean. or + allow-downgrade. When true, enables + DNSSEC + DNS validation support on the link. When set to + allow-downgrade, compatibility with + non-DNSSEC capable networks is increased, by automatically + turning off DNSSEC in this case. This option defines a + per-interface setting for + resolved.conf5's + global DNSSEC= option. Defaults to + false. This setting is read by + systemd-resolved.service8. + + + + DNSSECNegativeTrustAnchors= + A space-separated list of DNSSEC negative + trust anchor domains. If specified and DNSSEC is enabled, + look-ups done via the interface's DNS server will be subject + to the list of negative trust anchors, and not require + authentication for the specified domains, or anything below + it. Use this to disable DNSSEC authentication for specific + private domains, that cannot be proven valid using the + Internet DNS hierarchy. Defaults to the empty list. This + setting is read by + systemd-resolved.service8. + + + + LLDP= + + Controls support for Ethernet LLDP packet reception. LLDP is a link-layer protocol commonly + implemented on professional routers and bridges which announces which physical port a system is connected + to, as well as other related data. Accepts a boolean or the special value + routers-only. When true, incoming LLDP packets are accepted and a database of all LLDP + neighbors maintained. If routers-only is set only LLDP data of various types of routers + is collected and LLDP data about other types of devices ignored (such as stations, telephones and + others). If false, LLDP reception is disabled. Defaults to routers-only. Use + networkctl1 to query the + collected neighbor data. LLDP is only available on Ethernet links. See EmitLLDP= below + for enabling LLDP packet emission from the local system. + + + + + EmitLLDP= + + Controls support for Ethernet LLDP packet emission. Accepts a boolean parameter or the special values + nearest-bridge, non-tpmr-bridge and + customer-bridge. Defaults to false, which turns off LLDP packet emission. If not false, + a short LLDP packet with information about the local system is sent out in regular intervals on the + link. The LLDP packet will contain information about the local host name, the local machine ID (as stored + in machine-id5) and the + local interface name, as well as the pretty hostname of the system (as set in + machine-info5). LLDP + emission is only available on Ethernet links. Note that this setting passes data suitable for + identification of host to the network and should thus not be enabled on untrusted networks, where such + identification data should not be made available. Use this option to permit other systems to identify on + which interfaces they are connected to this system. The three special values control propagation of the + LLDP packets. The nearest-bridge setting permits propagation only to the nearest + connected bridge, non-tpmr-bridge permits propagation across Two-Port MAC Relays, but + not any other bridges, and customer-bridge permits propagation until a customer bridge + is reached. For details about these concepts, see IEEE 802.1AB-2016. Note that + configuring this setting to true is equivalent to nearest-bridge, the recommended and + most restricted level of propagation. See LLDP= above for an option to enable LLDP + reception. + + + + BindCarrier= + + A link name or a list of link names. When set, controls the behavior of the current + link. When all links in the list are in an operational down state, the current link is brought + down. When at least one link has carrier, the current interface is brought up. + + + + + Address= + + A static IPv4 or IPv6 address and its prefix length, + separated by a / character. Specify + this key more than once to configure several addresses. + The format of the address must be as described in + inet_pton3. + This is a short-hand for an [Address] section only + containing an Address key (see below). This option may be + specified more than once. + + + If the specified address is 0.0.0.0 (for IPv4) or :: + (for IPv6), a new address range of the requested size is automatically allocated from a + system-wide pool of unused ranges. Note that the prefix length must be equal or larger than 8 for + IPv4, and 64 for IPv6. The allocated range is checked against all current network interfaces and + all known network configuration files to avoid address range conflicts. The default system-wide + pool consists of 192.168.0.0/16, 172.16.0.0/12 and 10.0.0.0/8 for IPv4, and fd00::/8 for IPv6. + This functionality is useful to manage a large number of dynamically created network interfaces + with the same network configuration and automatic address range assignment. + + + + + Gateway= + + The gateway address, which must be in the format + described in + inet_pton3. + This is a short-hand for a [Route] section only containing + a Gateway key. This option may be specified more than + once. + + + + DNS= + + A DNS server address, which must be in the format + described in + inet_pton3. + This option may be specified more than once. This setting is read by + systemd-resolved.service8. + + + + Domains= + + A list of domains which should be resolved using the DNS servers on this link. Each item in the list + should be a domain name, optionally prefixed with a tilde (~). The domains with the + prefix are called "routing-only domains". The domains without the prefix are called "search domains" and + are first used as search suffixes for extending single-label host names (host names containing no dots) to + become fully qualified domain names (FQDNs). If a single-label host name is resolved on this interface, + each of the specified search domains are appended to it in turn, converting it into a fully qualified + domain name, until one of them may be successfully resolved. + + Both "search" and "routing-only" domains are used for routing of DNS queries: look-ups for host names + ending in those domains (hence also single label names, if any "search domains" are listed), are routed to + the DNS servers configured for this interface. The domain routing logic is particularly useful on + multi-homed hosts with DNS servers serving particular private DNS zones on each interface. + + The "routing-only" domain ~. (the tilde indicating definition of a routing domain, + the dot referring to the DNS root domain which is the implied suffix of all valid DNS names) has special + effect. It causes all DNS traffic which does not match another configured domain routing entry to be routed + to DNS servers specified for this interface. This setting is useful to prefer a certain set of DNS servers + if a link on which they are connected is available. + + This setting is read by + systemd-resolved.service8. + "Search domains" correspond to the domain and search entries in + resolv.conf5. + Domain name routing has no equivalent in the traditional glibc API, which has no concept of domain + name servers limited to a specific link. + + + + DNSDefaultRoute= + + Takes a boolean argument. If true, this link's configured DNS servers are used for resolving domain + names that do not match any link's configured Domains= setting. If false, this link's + configured DNS servers are never used for such domains, and are exclusively used for resolving names that + match at least one of the domains configured on this link. If not specified defaults to an automatic mode: + queries not matching any link's configured domains will be routed to this link if it has no routing-only + domains configured. + + + + NTP= + + An NTP server address. This option may be specified more than once. This setting is read by + systemd-timesyncd.service8. + + + + IPForward= + Configures IP packet forwarding for the + system. If enabled, incoming packets on any network + interface will be forwarded to any other interfaces + according to the routing table. Takes a boolean, + or the values ipv4 or + ipv6, which only enable IP packet + forwarding for the specified address family. This controls + the net.ipv4.ip_forward and + net.ipv6.conf.all.forwarding sysctl + options of the network interface (see ip-sysctl.txt + for details about sysctl options). Defaults to + no. + + Note: this setting controls a global kernel option, + and does so one way only: if a network that has this setting + enabled is set up the global setting is turned on. However, + it is never turned off again, even after all networks with + this setting enabled are shut down again. + + To allow IP packet forwarding only between specific + network interfaces use a firewall. + + + + IPMasquerade= + Configures IP masquerading for the network + interface. If enabled, packets forwarded from the network + interface will be appear as coming from the local host. + Takes a boolean argument. Implies + IPForward=ipv4. Defaults to + no. + + + IPv6PrivacyExtensions= + Configures use of stateless temporary + addresses that change over time (see RFC 4941, + Privacy Extensions for Stateless Address Autoconfiguration + in IPv6). Takes a boolean or the special values + prefer-public and + kernel. When true, enables the privacy + extensions and prefers temporary addresses over public + addresses. When prefer-public, enables the + privacy extensions, but prefers public addresses over + temporary addresses. When false, the privacy extensions + remain disabled. When kernel, the kernel's + default setting will be left in place. Defaults to + no. + + + IPv6AcceptRA= + Takes a boolean. Controls IPv6 Router Advertisement (RA) reception support + for the interface. If true, RAs are accepted; if false, RAs are ignored, independently of the + local forwarding state. When RAs are accepted, they may trigger the start of the DHCPv6 + client if the relevant flags are set in the RA data, or if no routers are found on the link. + + Further settings for the IPv6 RA support may be configured in the + [IPv6AcceptRA] section, see below. + + Also see ip-sysctl.txt in the kernel + documentation regarding accept_ra, but note that systemd's setting of + 1 (i.e. true) corresponds to kernel's setting of 2. + + Note that kernel's implementation of the IPv6 RA protocol is always disabled, + regardless of this setting. If this option is enabled, a userspace implementation of the IPv6 + RA protocol is used, and the kernel's own implementation remains disabled, since + systemd-networkd needs to know all details supplied in the advertisements, + and these are not available from the kernel if the kernel's own implementation is used. + + + + IPv6DuplicateAddressDetection= + Configures the amount of IPv6 Duplicate + Address Detection (DAD) probes to send. When unset, the kernel's default will be used. + + + + IPv6HopLimit= + Configures IPv6 Hop Limit. For each router that + forwards the packet, the hop limit is decremented by 1. When the + hop limit field reaches zero, the packet is discarded. + When unset, the kernel's default will be used. + + + + IPv4ProxyARP= + Takes a boolean. Configures proxy ARP for IPv4. Proxy ARP is the technique in which one host, + usually a router, answers ARP requests intended for another machine. By "faking" its identity, + the router accepts responsibility for routing packets to the "real" destination. (see RFC 1027. + When unset, the kernel's default will be used. + + + + IPv6ProxyNDP= + Takes a boolean. Configures proxy NDP for IPv6. Proxy NDP (Neighbor Discovery + Protocol) is a technique for IPv6 to allow routing of addresses to a different + destination when peers expect them to be present on a certain physical link. + In this case a router answers Neighbour Advertisement messages intended for + another machine by offering its own MAC address as destination. + Unlike proxy ARP for IPv4, it is not enabled globally, but will only send Neighbour + Advertisement messages for addresses in the IPv6 neighbor proxy table, + which can also be shown by ip -6 neighbour show proxy. + systemd-networkd will control the per-interface `proxy_ndp` switch for each configured + interface depending on this option. + When unset, the kernel's default will be used. + + + + IPv6ProxyNDPAddress= + An IPv6 address, for which Neighbour Advertisement messages will be + proxied. This option may be specified more than once. systemd-networkd will add the + entries to the kernel's IPv6 neighbor proxy table. + This option implies but has no effect if + has been set to false. When unset, the kernel's default will be used. + + + + IPv6PrefixDelegation= + Whether to enable or disable Router Advertisement sending on a link. + Allowed values are static which distributes prefixes as defined in + the [IPv6PrefixDelegation] and any [IPv6Prefix] + sections, dhcpv6 which requests prefixes using a DHCPv6 client + configured for another link and any values configured in the + [IPv6PrefixDelegation] section while ignoring all static prefix + configuration sections, yes which uses both static configuration + and DHCPv6, and false which turns off IPv6 prefix delegation + altogether. Defaults to false. See the + [IPv6PrefixDelegation] and the [IPv6Prefix] + sections for more configuration options. + + + + IPv6MTUBytes= + Configures IPv6 maximum transmission unit (MTU). + An integer greater than or equal to 1280 bytes. When unset, the kernel's default will be used. + + + + Bridge= + + The name of the bridge to add the link to. See + systemd.netdev5. + + + + + Bond= + + The name of the bond to add the link to. See + systemd.netdev5. + + + + + VRF= + + The name of the VRF to add the link to. See + systemd.netdev5. + + + + + VLAN= + + The name of a VLAN to create on the link. See + systemd.netdev5. + This option may be specified more than once. + + + + IPVLAN= + + The name of a IPVLAN to create on the link. See + systemd.netdev5. + This option may be specified more than once. + + + + MACVLAN= + + The name of a MACVLAN to create on the link. See + systemd.netdev5. + This option may be specified more than once. + + + + VXLAN= + + The name of a VXLAN to create on the link. See + systemd.netdev5. + This option may be specified more than once. + + + + Tunnel= + + The name of a Tunnel to create on the link. See + systemd.netdev5. + This option may be specified more than once. + + + + MACsec= + + The name of a MACsec device to create on the link. See + systemd.netdev5. + This option may be specified more than once. + + + + ActiveSlave= + + Takes a boolean. Specifies the new active slave. The ActiveSlave= + option is only valid for following modes: + active-backup, + balance-alb and + balance-tlb. Defaults to false. + + + + + PrimarySlave= + + Takes a boolean. Specifies which slave is the primary device. The specified + device will always be the active slave while it is available. Only when the + primary is off-line will alternate devices be used. This is useful when + one slave is preferred over another, e.g. when one slave has higher throughput + than another. The PrimarySlave= option is only valid for + following modes: + active-backup, + balance-alb and + balance-tlb. Defaults to false. + + + + + ConfigureWithoutCarrier= + + Takes a boolean. Allows networkd to configure a specific link even if it has no carrier. + Defaults to false. + + + + + IgnoreCarrierLoss= + + A boolean. Allows networkd to retain both the static and dynamic configuration of the + interface even if its carrier is lost. Defaults to false. + + + + + Xfrm= + + The name of the xfrm to create on the link. See + systemd.netdev5. + This option may be specified more than once. + + + + KeepConfiguration= + + Takes a boolean or one of static, dhcp-on-stop, + dhcp. When static, systemd-networkd + will not drop static addresses and routes on starting up process. When set to + dhcp-on-stop, systemd-networkd will not drop addresses + and routes on stopping the daemon. When dhcp, + the addresses and routes provided by a DHCP server will never be dropped even if the DHCP + lease expires. This is contrary to the DHCP specification, but may be the best choice if, + e.g., the root filesystem relies on this connection. The setting dhcp + implies dhcp-on-stop, and yes implies + dhcp and static. Defaults to no. + + + + + + + + + + [Address] Section Options + + An [Address] section accepts the + following keys. Specify several [Address] + sections to configure several addresses. + + + + Address= + + As in the [Network] section. This key is mandatory. Each + [Address] section can contain one Address= setting. + + + + Peer= + + The peer address in a point-to-point connection. + Accepts the same format as the Address= + key. + + + + Broadcast= + + The broadcast address, which must be in the format + described in + inet_pton3. + This key only applies to IPv4 addresses. If it is not + given, it is derived from the Address= + key. + + + + Label= + + An address label. + + + + PreferredLifetime= + + Allows the default "preferred lifetime" of the address to be overridden. + Only three settings are accepted: forever or infinity + which is the default and means that the address never expires, and 0 which means + that the address is considered immediately "expired" and will not be used, + unless explicitly requested. A setting of PreferredLifetime=0 is useful for + addresses which are added to be used only by a specific application, + which is then configured to use them explicitly. + + + + Scope= + + The scope of the address, which can be global, + link or host or an unsigned integer ranges 0 to 255. + Defaults to global. + + + + HomeAddress= + + Takes a boolean. Designates this address the "home address" as defined in + RFC 6275. + Supported only on IPv6. Defaults to false. + + + + DuplicateAddressDetection= + + Takes a boolean. Do not perform Duplicate Address Detection + RFC 4862 when adding this address. + Supported only on IPv6. Defaults to false. + + + + ManageTemporaryAddress= + + Takes a boolean. If true the kernel manage temporary addresses created + from this one as template on behalf of Privacy Extensions + RFC 3041. For this to become + active, the use_tempaddr sysctl setting has to be set to a value greater than zero. + The given address needs to have a prefix length of 64. This flag allows to use privacy + extensions in a manually configured network, just like if stateless auto-configuration + was active. Defaults to false. + + + + AddPrefixRoute= + + Takes a boolean. When true, the prefix route for the address is automatically added. + Defaults to true. + + + + AutoJoin= + + Takes a boolean. Joining multicast group on ethernet level via + ip maddr command would not work if we have an Ethernet switch that does + IGMP snooping since the switch would not replicate multicast packets on ports that did not + have IGMP reports for the multicast addresses. Linux vxlan interfaces created via + ip link add vxlan or networkd's netdev kind vxlan have the group option + that enables then to do the required join. By extending ip address command with option + autojoin we can get similar functionality for openvswitch (OVS) vxlan + interfaces as well as other tunneling mechanisms that need to receive multicast traffic. + Defaults to no. + + + + + + + [Neighbor] Section Options + A [Neighbor] section accepts the + following keys. The neighbor section adds a permanent, static + entry to the neighbor table (IPv6) or ARP table (IPv4) for + the given hardware address on the links matched for the network. + Specify several [Neighbor] sections to configure + several static neighbors. + + + + Address= + + The IP address of the neighbor. + + + + LinkLayerAddress= + + The link layer address (MAC address or IP address) of the neighbor. + + + + + + + [IPv6AddressLabel] Section Options + + An [IPv6AddressLabel] section accepts the + following keys. Specify several [IPv6AddressLabel] + sections to configure several address labels. IPv6 address labels are + used for address selection. See RFC 3484. + Precedence is managed by userspace, and only the label itself is stored in the kernel + + + + Label= + + The label for the prefix (an unsigned integer) ranges 0 to 4294967294. + 0xffffffff is reserved. This key is mandatory. + + + + Prefix= + + IPv6 prefix is an address with a prefix length, separated by a slash / character. + This key is mandatory. + + + + + + + [RoutingPolicyRule] Section Options + + An [RoutingPolicyRule] section accepts the + following keys. Specify several [RoutingPolicyRule] + sections to configure several rules. + + + + TypeOfService= + + Specifies the type of service to match a number between 0 to 255. + + + + From= + + Specifies the source address prefix to match. Possibly followed by a slash and the prefix length. + + + + To= + + Specifies the destination address prefix to match. Possibly followed by a slash and the prefix length. + + + + FirewallMark= + + Specifies the iptables firewall mark value to match (a number between 1 and 4294967295). + + + + Table= + + Specifies the routing table identifier to lookup if the rule selector matches. Takes + one of default, main, and local, + or a number between 1 and 4294967295. Defaults to main. + + + + Priority= + + Specifies the priority of this rule. Priority= is an unsigned + integer. Higher number means lower priority, and rules get processed in order of increasing number. + + + + IncomingInterface= + + Specifies incoming device to match. If the interface is loopback, the rule only matches packets originating from this host. + + + + OutgoingInterface= + + Specifies the outgoing device to match. The outgoing interface is only available for packets originating from local sockets that are bound to a device. + + + + SourcePort= + + Specifies the source IP port or IP port range match in forwarding information base (FIB) rules. + A port range is specified by the lower and upper port separated by a dash. Defaults to unset. + + + + DestinationPort= + + Specifies the destination IP port or IP port range match in forwarding information base (FIB) rules. + A port range is specified by the lower and upper port separated by a dash. Defaults to unset. + + + + IPProtocol= + + Specifies the IP protocol to match in forwarding information base (FIB) rules. Takes IP protocol name such as tcp, + udp or sctp, or IP protocol number such as 6 for tcp or + 17 for udp. + Defaults to unset. + + + + InvertRule= + + A boolean. Specifies whether the rule to be inverted. Defaults to false. + + + + Family= + + Takes a special value ipv4, ipv6, or + both. By default, the address family is determined by the address + specified in To= or From=. If neither + To= nor From= are specified, then defaults to + ipv4. + + + + + + + [NextHop] Section Options + The [NextHop] section accepts the + following keys. Specify several [NextHop] + sections to configure several nexthop. Nexthop is used to manipulate entries in the kernel's nexthop + tables. + + + + Gateway= + + As in the [Network] section. This is mandatory. + + + + Id= + + The id of the nexthop (an unsigned integer). If unspecified or '0' then automatically chosen by kernel. + + + + + + + [Route] Section Options + The [Route] section accepts the + following keys. Specify several [Route] + sections to configure several routes. + + + + Gateway= + + As in the [Network] section. + + + + GatewayOnLink= + + Takes a boolean. If set to true, the kernel does not have + to check if the gateway is reachable directly by the current machine (i.e., the kernel does + not need to check if the gateway is attached to the local network), so that we can insert the + route in the kernel table without it being complained about. Defaults to no. + + + + + Destination= + + The destination prefix of the route. Possibly + followed by a slash and the prefix length. If omitted, a + full-length host route is assumed. + + + + Source= + + The source prefix of the route. Possibly followed by + a slash and the prefix length. If omitted, a full-length + host route is assumed. + + + + Metric= + + The metric of the route (an unsigned integer). + + + + IPv6Preference= + + Specifies the route preference as defined in RFC4191 for Router Discovery messages. + Which can be one of low the route has a lowest priority, + medium the route has a default priority or + high the route has a highest priority. + + + + Scope= + + The scope of the route, which can be global, site, + link, host, or nowhere. For IPv4 route, + defaults to host if Type= is local + or nat, and link if Type= is + broadcast, multicast, or anycast. + In other cases, defaults to global. + + + + PreferredSource= + + The preferred source address of the route. The address + must be in the format described in + inet_pton3. + + + + Table= + + The table identifier for the route. Takes default, + main, local or a number between 1 and 4294967295. + The table can be retrieved using ip route show table num. + If unset and Type= is local, broadcast, + anycast, or nat, then local is used. + In other cases, defaults to main. + + + + + Protocol= + + The protocol identifier for the route. Takes a number between 0 and 255 or the special values + kernel, boot, static, + ra and dhcp. Defaults to static. + + + + + Type= + + Specifies the type for the route. Takes one of unicast, + local, broadcast, anycast, + multicast, blackhole, unreachable, + prohibit, throw, nat, and + xresolve. If unicast, a regular route is defined, i.e. a + route indicating the path to take to a destination network address. If blackhole, packets + to the defined route are discarded silently. If unreachable, packets to the defined route + are discarded and the ICMP message "Host Unreachable" is generated. If prohibit, packets + to the defined route are discarded and the ICMP message "Communication Administratively Prohibited" is + generated. If throw, route lookup in the current routing table will fail and the route + selection process will return to Routing Policy Database (RPDB). Defaults to unicast. + + + + + InitialCongestionWindow= + + The TCP initial congestion window is used during the start of a TCP connection. During the start of a TCP + session, when a client requests a resource, the server's initial congestion window determines how many data bytes + will be sent during the initial burst of data. Takes a size in bytes between 1 and 4294967295 (2^32 - 1). The usual + suffixes K, M, G are supported and are understood to the base of 1024. When unset, the kernel's default will be used. + + + + + InitialAdvertisedReceiveWindow= + + The TCP initial advertised receive window is the amount of receive data (in bytes) that can initially be buffered at one time + on a connection. The sending host can send only that amount of data before waiting for an acknowledgment and window update + from the receiving host. Takes a size in bytes between 1 and 4294967295 (2^32 - 1). The usual suffixes K, M, G are supported + and are understood to the base of 1024. When unset, the kernel's default will be used. + + + + + QuickAck= + + Takes a boolean. When true enables TCP quick ack mode for the route. When unset, the kernel's default will be used. + + + + + FastOpenNoCookie= + + Takes a boolean. When true enables TCP fastopen without a cookie on a per-route basis. + When unset, the kernel's default will be used. + + + + + TTLPropagate= + + Takes a boolean. When true enables TTL propagation at Label Switched Path (LSP) egress. + When unset, the kernel's default will be used. + + + + + MTUBytes= + + The maximum transmission unit in bytes to set for the + route. The usual suffixes K, M, G, are supported and are + understood to the base of 1024. + Note that if IPv6 is enabled on the interface, and the MTU is chosen + below 1280 (the minimum MTU for IPv6) it will automatically be increased to this value. + + + + IPServiceType= + + Takes string; CS6 or CS4. Used to set IP + service type to CS6 (network control) or CS4 (Realtime). Defaults to CS6. + + + + + + + [DHCPv4] Section Options + The [DHCPv4] section configures the + DHCPv4 client, if it is enabled with the + DHCP= setting described above: + + + + UseDNS= + + When true (the default), the DNS servers received + from the DHCP server will be used and take precedence over + any statically configured ones. + + This corresponds to the + option in resolv.conf5. + + + + RoutesToDNS= + + When true, the routes to the DNS servers received from the DHCP server will be + configured. When UseDNS= is disabled, this setting is ignored. + Defaults to false. + + + + UseNTP= + + When true (the default), the NTP servers received + from the DHCP server will be used by systemd-timesyncd + and take precedence over any statically configured ones. + + + + UseSIP= + + When true (the default), the SIP servers received + from the DHCP server will be saved at the state files and can be + read via sd_network_link_get_sip_servers() function. + + + + UseMTU= + + When true, the interface maximum transmission unit + from the DHCP server will be used on the current link. + If MTUBytes= is set, then this setting is ignored. + Defaults to false. + + + + Anonymize= + + Takes a boolean. When true, the options sent to the DHCP server will + follow the RFC 7844 + (Anonymity Profiles for DHCP Clients) to minimize disclosure of identifying information. + Defaults to false. + + This option should only be set to true when + MACAddressPolicy= is set to random + (see systemd.link5). + + Note that this configuration will overwrite others. + In concrete, the following variables will be ignored: + SendHostname=, ClientIdentifier=, + UseRoutes=, SendHostname=, + UseMTU=, VendorClassIdentifier=, + UseTimezone=. + + With this option enabled DHCP requests will mimic those generated by Microsoft Windows, in + order to reduce the ability to fingerprint and recognize installations. This means DHCP request + sizes will grow and lease data will be more comprehensive than normally, though most of the + requested data is not actually used. + + + + SendHostname= + + When true (the default), the machine's hostname will be sent to the DHCP server. + Note that the machine's hostname must consist only of 7-bit ASCII lower-case characters and + no spaces or dots, and be formatted as a valid DNS domain name. Otherwise, the hostname is not + sent even if this is set to true. + + + + UseHostname= + + When true (the default), the hostname received from + the DHCP server will be set as the transient hostname of the system. + + + + + Hostname= + + Use this value for the hostname which is sent to the DHCP server, instead of machine's hostname. + Note that the specified hostname must consist only of 7-bit ASCII lower-case characters and + no spaces or dots, and be formatted as a valid DNS domain name. + + + + UseDomains= + + Takes a boolean, or the special value route. When true, the domain name + received from the DHCP server will be used as DNS search domain over this link, similar to the effect of + the setting. If set to route, the domain name received from + the DHCP server will be used for routing DNS queries only, but not for searching, similar to the effect of + the setting when the argument is prefixed with ~. Defaults to + false. + + It is recommended to enable this option only on trusted networks, as setting this affects resolution + of all host names, in particular of single-label names. It is generally safer to use the supplied domain + only as routing domain, rather than as search domain, in order to not have it affect local resolution of + single-label names. + + When set to true, this setting corresponds to the option in resolv.conf5. + + + + UseRoutes= + + When true (the default), the static routes will be requested from the DHCP server and added to the + routing table with a metric of 1024, and a scope of "global", "link" or "host", depending on the route's + destination and gateway. If the destination is on the local host, e.g., 127.x.x.x, or the same as the + link's own address, the scope will be set to "host". Otherwise if the gateway is null (a direct route), a + "link" scope will be used. For anything else, scope defaults to "global". + + + + + UseTimezone= + + When true, the timezone received from the + DHCP server will be set as timezone of the local + system. Defaults to no. + + + + ClientIdentifier= + + The DHCPv4 client identifier to use. Takes one of mac, duid or duid-only. + If set to mac, the MAC address of the link is used. + If set to duid, an RFC4361-compliant Client ID, which is the combination of IAID and DUID (see below), is used. + If set to duid-only, only DUID is used, this may not be RFC compliant, but some setups may require to use this. + Defaults to duid. + + + + + VendorClassIdentifier= + + The vendor class identifier used to identify vendor + type and configuration. + + + + + UserClass= + + A DHCPv4 client can use UserClass option to identify the type or category of user or applications + it represents. The information contained in this option is a string that represents the user class of which + the client is a member. Each class sets an identifying string of information to be used by the DHCP + service to classify clients. Takes a whitespace-separated list of strings. + + + + + MaxAttempts= + + Specifies how many times the DHCPv4 client configuration should be attempted. Takes a + number or infinity. Defaults to infinity. + Note that the time between retries is increased exponentially, so the network will not be + overloaded even if this number is high. + + + + + DUIDType= + + Override the global DUIDType setting for this network. See + networkd.conf5 + for a description of possible values. + + + + + DUIDRawData= + + Override the global DUIDRawData setting for this network. See + networkd.conf5 + for a description of possible values. + + + + + IAID= + + The DHCP Identity Association Identifier (IAID) for the interface, a 32-bit unsigned integer. + + + + + RequestBroadcast= + + Request the server to use broadcast messages before + the IP address has been configured. This is necessary for + devices that cannot receive RAW packets, or that cannot + receive packets at all before an IP address has been + configured. On the other hand, this must not be enabled on + networks where broadcasts are filtered out. + + + + + RouteMetric= + + Set the routing metric for routes specified by the + DHCP server. + + + + + RouteTable=num + + The table identifier for DHCP routes (a number between 1 and 4294967295, or 0 to unset). + The table can be retrieved using ip route show table num. + + When used in combination with VRF= the + VRF's routing table is used unless this parameter is specified. + + + + + + ListenPort= + + Allow setting custom port for the DHCP client to listen on. + + + + + SendRelease= + + When true, the DHCPv4 client sends a DHCP release packet when it stops. + Defaults to true. + + + + + BlackList= + + A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are rejected. + + + + + RequestOptions= + + A whitespace-separated list of integers in the range 1–254. + + + + + SendOption= + + Send an arbitrary option in the DHCPv4 request. Takes a DHCP option number, data type + and data separated with a colon + (option:type:value). + The option number must be an interger in the range 1..254. The type takes one of uint8, + uint16, uint32, ipv4address, or + string. Special characters in the data string may be escaped using + C-style + escapes. This setting can be specified multiple times. If an empty string is specified, + then all options specified earlier are cleared. Defaults to unset. + + + + + + + [DHCPv6] Section Options + The [DHCPv6] section configures the DHCPv6 client, if it is enabled with the + DHCP= setting described above, or invoked by the IPv6 Router Advertisement: + + + + UseDNS= + UseNTP= + + As in the [DHCPv4] section. + + + + + RapidCommit= + + Takes a boolean. The DHCPv6 client can obtain configuration parameters from a DHCPv6 server through + a rapid two-message exchange (solicit and reply). When the rapid commit option is enabled by both + the DHCPv6 client and the DHCPv6 server, the two-message exchange is used, rather than the default + four-method exchange (solicit, advertise, request, and reply). The two-message exchange provides + faster client configuration and is beneficial in environments in which networks are under a heavy load. + See RFC 3315 for details. + Defaults to true. + + + + + ForceDHCPv6PDOtherInformation= + + Takes a boolean that enforces DHCPv6 stateful mode when the 'Other information' bit is set in + Router Advertisement messages. By default setting only the 'O' bit in Router Advertisements + makes DHCPv6 request network information in a stateless manner using a two-message Information + Request and Information Reply message exchange. + RFC 7084, requirement WPD-4, updates + this behavior for a Customer Edge router so that stateful DHCPv6 Prefix Delegation is also + requested when only the 'O' bit is set in Router Advertisements. This option enables such a CE + behavior as it is impossible to automatically distinguish the intention of the 'O' bit otherwise. + By default this option is set to 'false', enable it if no prefixes are delegated when the device + should be acting as a CE router. + + + + + PrefixDelegationHint= + + Takes an IPv6 address with prefix length as Address= in + the "[Network]" section. Specifies the DHCPv6 client for the requesting router to include + a prefix-hint in the DHCPv6 solicitation. Prefix ranges 1-128. Defaults to unset. + + + + + + + [IPv6AcceptRA] Section Options + The [IPv6AcceptRA] section configures the IPv6 Router Advertisement + (RA) client, if it is enabled with the IPv6AcceptRA= setting described + above: + + + + UseDNS= + + When true (the default), the DNS servers received in the Router Advertisement will be used and take + precedence over any statically configured ones. + + This corresponds to the option in resolv.conf5. + + + + + UseDomains= + + Takes a boolean, or the special value route. When true, the domain name + received via IPv6 Router Advertisement (RA) will be used as DNS search domain over this link, similar to + the effect of the setting. If set to route, the domain name + received via IPv6 RA will be used for routing DNS queries only, but not for searching, similar to the + effect of the setting when the argument is prefixed with + ~. Defaults to false. + + It is recommended to enable this option only on trusted networks, as setting this affects resolution + of all host names, in particular of single-label names. It is generally safer to use the supplied domain + only as routing domain, rather than as search domain, in order to not have it affect local resolution of + single-label names. + + When set to true, this setting corresponds to the option in resolv.conf5. + + + + + RouteTable=num + + The table identifier for the routes received in the Router Advertisement + (a number between 1 and 4294967295, or 0 to unset). + The table can be retrieved using ip route show table num. + + + + + + UseAutonomousPrefix= + + When true (the default), the autonomous prefix received in the Router Advertisement will be used and take + precedence over any statically configured ones. + + + + + UseOnLinkPrefix= + + When true (the default), the onlink prefix received in the Router Advertisement will be used and take + precedence over any statically configured ones. + + + + + BlackList= + + A whitespace-separated list of IPv6 prefixes. IPv6 prefixes supplied via router advertisements in the list are ignored. + + + + + + + + [DHCPServer] Section Options + The [DHCPServer] section contains + settings for the DHCP server, if enabled via the + DHCPServer= option described above: + + + + + PoolOffset= + PoolSize= + + Configures the pool of addresses to hand out. The pool + is a contiguous sequence of IP addresses in the subnet configured for + the server address, which does not include the subnet nor the broadcast + address. PoolOffset= takes the offset of the pool + from the start of subnet, or zero to use the default value. + PoolSize= takes the number of IP addresses in the + pool or zero to use the default value. By default, the pool starts at + the first address after the subnet address and takes up the rest of + the subnet, excluding the broadcast address. If the pool includes + the server address (the default), this is reserved and not handed + out to clients. + + + + DefaultLeaseTimeSec= + MaxLeaseTimeSec= + + Control the default and maximum DHCP lease + time to pass to clients. These settings take time values in seconds or + another common time unit, depending on the suffix. The default + lease time is used for clients that did not ask for a specific + lease time. If a client asks for a lease time longer than the + maximum lease time, it is automatically shortened to the + specified time. The default lease time defaults to 1h, the + maximum lease time to 12h. Shorter lease times are beneficial + if the configuration data in DHCP leases changes frequently + and clients shall learn the new settings with shorter + latencies. Longer lease times reduce the generated DHCP + network traffic. + + + + EmitDNS= + DNS= + + Takes a boolean. Configures whether the DHCP leases handed out + to clients shall contain DNS server information. Defaults to yes. + The DNS servers to pass to clients may be configured with the + DNS= option, which takes a list of IPv4 + addresses. If the EmitDNS= option is + enabled but no servers configured, the servers are + automatically propagated from an "uplink" interface that has + appropriate servers set. The "uplink" interface is determined + by the default route of the system with the highest + priority. Note that this information is acquired at the time + the lease is handed out, and does not take uplink interfaces + into account that acquire DNS or NTP server information at a + later point. DNS server propagation does not take + /etc/resolv.conf into account. Also, note + that the leases are not refreshed if the uplink network + configuration changes. To ensure clients regularly acquire the + most current uplink DNS server information, it is thus + advisable to shorten the DHCP lease time via + MaxLeaseTimeSec= described + above. + + + + EmitNTP= + NTP= + + Similar to the EmitDNS= and + DNS= settings described above, these + settings configure whether and what NTP server information + shall be emitted as part of the DHCP lease. The same syntax, + propagation semantics and defaults apply as for + EmitDNS= and + DNS=. + + + + EmitSIP= + SIP= + + Similar to the EmitDNS= and + DNS= settings described above, these + settings configure whether and what SIP server information + shall be emitted as part of the DHCP lease. The same syntax, + propagation semantics and defaults apply as for + EmitDNS= and + DNS=. + + + + EmitRouter= + + Similar to the EmitDNS= + setting described above, this setting configures whether the + DHCP lease should contain the router option. The same syntax, + propagation semantics and defaults apply as for + EmitDNS=. + + + + EmitTimezone= + Timezone= + + Takes a boolean. Configures whether the DHCP leases handed out + to clients shall contain timezone information. Defaults to yes. The + Timezone= setting takes a timezone string + (such as Europe/Berlin or + UTC) to pass to clients. If no explicit + timezone is set, the system timezone of the local host is + propagated, as determined by the + /etc/localtime symlink. + + + + SendOption= + + Send a raw option with value via DHCPv4 server. Takes a DHCP option number, data type + and data (option:type:value). + The option number is an integer in the range 1..254. The type takes one of uint8, + uint16, uint32, ipv4address, or + string. Special characters in the data string may be escaped using + C-style + escapes. This setting can be specified multiple times. If an empty string is specified, + then all options specified earlier are cleared. Defaults to unset. + + + + + + + + [IPv6PrefixDelegation] Section Options + The [IPv6PrefixDelegation] section contains + settings for sending IPv6 Router Advertisements and whether to act as + a router, if enabled via the IPv6PrefixDelegation= + option described above. IPv6 network prefixes are defined with one or + more [IPv6Prefix] sections. + + + + + Managed= + OtherInformation= + + Takes a boolean. Controls whether a DHCPv6 server is used to acquire IPv6 + addresses on the network link when Managed= + is set to true or if only additional network + information can be obtained via DHCPv6 for the network link when + OtherInformation= is set to + true. Both settings default to + false, which means that a DHCPv6 server is not being + used. + + + + RouterLifetimeSec= + + Takes a timespan. Configures the IPv6 router lifetime in seconds. If set, + this host also announces itself in Router Advertisements as an IPv6 + router for the network link. When unset, the host is not acting as a router. + + + + + RouterPreference= + + Configures IPv6 router preference if + RouterLifetimeSec= is non-zero. Valid values are + high, medium and + low, with normal and + default added as synonyms for + medium just to make configuration easier. See + RFC 4191 + for details. Defaults to medium. + + + + EmitDNS= + DNS= + + DNS= specifies a list of recursive + DNS server IPv6 addresses that distributed via Router Advertisement + messages when EmitDNS= is true. If DNS= + is empty, DNS servers are read from the + [Network] section. If the + [Network] section does not contain any DNS servers + either, DNS servers from the uplink with the highest priority default + route are used. When EmitDNS= is false, no DNS server + information is sent in Router Advertisement messages. + EmitDNS= defaults to true. + + + + + EmitDomains= + Domains= + + A list of DNS search domains distributed via Router + Advertisement messages when EmitDomains= is true. If + Domains= is empty, DNS search domains are read from the + [Network] section. If the [Network] + section does not contain any DNS search domains either, DNS search + domains from the uplink with the highest priority default route are + used. When EmitDomains= is false, no DNS search domain + information is sent in Router Advertisement messages. + EmitDomains= defaults to true. + + + + + DNSLifetimeSec= + + Lifetime in seconds for the DNS server addresses listed + in DNS= and search domains listed in + Domains=. + + + + + + + [IPv6Prefix] Section Options + One or more [IPv6Prefix] sections contain the IPv6 + prefixes that are announced via Router Advertisements. See + RFC 4861 + for further details. + + + + + AddressAutoconfiguration= + OnLink= + + Takes a boolean to specify whether IPv6 addresses can be + autoconfigured with this prefix and whether the prefix can be used for + onlink determination. Both settings default to true + in order to ease configuration. + + + + + Prefix= + + The IPv6 prefix that is to be distributed to hosts. + Similarly to configuring static IPv6 addresses, the setting is + configured as an IPv6 prefix and its prefix length, separated by a + / character. Use multiple + [IPv6Prefix] sections to configure multiple IPv6 + prefixes since prefix lifetimes, address autoconfiguration and onlink + status may differ from one prefix to another. + + + + PreferredLifetimeSec= + ValidLifetimeSec= + + Preferred and valid lifetimes for the prefix measured in + seconds. PreferredLifetimeSec= defaults to 604800 + seconds (one week) and ValidLifetimeSec= defaults + to 2592000 seconds (30 days). + + + + + + + [IPv6RoutePrefix] Section Options + One or more [IPv6RoutePrefix] sections contain the IPv6 + prefix routes that are announced via Router Advertisements. See + RFC 4191 + for further details. + + + + + Route= + + The IPv6 route that is to be distributed to hosts. + Similarly to configuring static IPv6 routes, the setting is + configured as an IPv6 prefix routes and its prefix route length, + separated by a/ character. Use multiple + [IPv6PrefixRoutes] sections to configure multiple IPv6 + prefix routes. + + + + LifetimeSec= + + Lifetime for the route prefix measured in + seconds. LifetimeSec= defaults to 604800 seconds (one week). + + + + + + + + [Bridge] Section Options + The [Bridge] section accepts the + following keys. + + + UnicastFlood= + + Takes a boolean. Controls whether the bridge should flood + traffic for which an FDB entry is missing and the destination + is unknown through this port. When unset, the kernel's default will be used. + + + + + MulticastFlood= + + Takes a boolean. Controls whether the bridge should flood + traffic for which an MDB entry is missing and the destination + is unknown through this port. When unset, the kernel's default will be used. + + + + + MulticastToUnicast= + + Takes a boolean. Multicast to unicast works on top of the multicast snooping feature of + the bridge. Which means unicast copies are only delivered to hosts which are interested in it. + When unset, the kernel's default will be used. + + + + + NeighborSuppression= + + Takes a boolean. Configures whether ARP and ND neighbor suppression is enabled for + this port. When unset, the kernel's default will be used. + + + + + Learning= + + Takes a boolean. Configures whether MAC address learning is enabled for + this port. When unset, the kernel's default will be used. + + + + + HairPin= + + Takes a boolean. Configures whether traffic may be sent back + out of the port on which it was received. When this flag is false, and the bridge + will not forward traffic back out of the receiving port. + When unset, the kernel's default will be used. + + + + UseBPDU= + + Takes a boolean. Configures whether STP Bridge Protocol Data Units will be + processed by the bridge port. When unset, the kernel's default will be used. + + + + FastLeave= + + Takes a boolean. This flag allows the bridge to immediately stop multicast + traffic on a port that receives an IGMP Leave message. It is only used with + IGMP snooping if enabled on the bridge. When unset, the kernel's default will be used. + + + + AllowPortToBeRoot= + + Takes a boolean. Configures whether a given port is allowed to + become a root port. Only used when STP is enabled on the bridge. + When unset, the kernel's default will be used. + + + + ProxyARP= + + Takes a boolean. Configures whether proxy ARP to be enabled on this port. + When unset, the kernel's default will be used. + + + + ProxyARPWiFi= + + Takes a boolean. Configures whether proxy ARP to be enabled on this port + which meets extended requirements by IEEE 802.11 and Hotspot 2.0 specifications. + When unset, the kernel's default will be used. + + + + MulticastRouter= + + Configures this port for having multicast routers attached. A port with a multicast + router will receive all multicast traffic. Takes one of no + to disable multicast routers on this port, query to let the system detect + the presence of routers, permanent to permanently enable multicast traffic + forwarding on this port, or temporary to enable multicast routers temporarily + on this port, not depending on incoming queries. When unset, the kernel's default will be used. + + + + Cost= + + Sets the "cost" of sending packets of this interface. + Each port in a bridge may have a different speed and the cost + is used to decide which link to use. Faster interfaces + should have lower costs. It is an integer value between 1 and + 65535. + + + + Priority= + + Sets the "priority" of sending packets on this interface. + Each port in a bridge may have a different priority which is used + to decide which link to use. Lower value means higher priority. + It is an integer value between 0 to 63. Networkd does not set any + default, meaning the kernel default value of 32 is used. + + + + + + [BridgeFDB] Section Options + The [BridgeFDB] section manages the + forwarding database table of a port and accepts the following + keys. Specify several [BridgeFDB] sections to + configure several static MAC table entries. + + + + MACAddress= + + As in the [Network] section. This + key is mandatory. + + + + Destination= + + Takes an IP address of the destination VXLAN tunnel endpoint. + + + + VLANId= + + The VLAN ID for the new static MAC table entry. If + omitted, no VLAN ID information is appended to the new static MAC + table entry. + + + + VNI= + + The VXLAN Network Identifier (or VXLAN Segment ID) to use to connect to + the remote VXLAN tunnel endpoint. Takes a number in the range 1-16777215. + Defaults to unset. + + + + AssociatedWith= + + Specifies where the address is associated with. Takes one of use, + self, master or router. + use means the address is in use. User space can use this option to + indicate to the kernel that the fdb entry is in use. self means + the address is associated with the port drivers fdb. Usually hardware. master + means the address is associated with master devices fdb. router means + the destination address is associated with a router. Note that it's valid if the referenced + device is a VXLAN type device and has route shortcircuit enabled. Defaults to self. + + + + + + + [CAN] Section Options + The [CAN] section manages the Controller Area Network (CAN bus) and accepts the + following keys. + + + BitRate= + + The bitrate of CAN device in bits per second. The usual SI prefixes (K, M) with the base of 1000 can + be used here. + + + + SamplePoint= + + Optional sample point in percent with one decimal (e.g. 75%, + 87.5%) or permille (e.g. 875‰). + + + + RestartSec= + + Automatic restart delay time. If set to a non-zero value, a restart of the CAN controller will be + triggered automatically in case of a bus-off condition after the specified delay time. Subsecond delays can + be specified using decimals (e.g. 0.1s) or a ms or + us postfix. Using infinity or 0 will turn the + automatic restart off. By default automatic restart is disabled. + + + + TripleSampling= + + Takes a boolean. When yes, three samples (instead of one) are used to determine + the value of a received bit by majority rule. When unset, the kernel's default will be used. + + + + + + + [TrafficControlQueueingDiscipline] Section Options + The [TrafficControlQueueingDiscipline] section manages the Traffic control. It can be used + to configure the kernel packet scheduler and simulate packet delay and loss for UDP or TCP applications, + or limit the bandwidth usage of a particular service to simulate internet connections. + + + + Parent= + + Specifies the parent Queueing Discipline (qdisc). Takes one of root + or clsact. Defaults to root. + + + + + NetworkEmulatorDelaySec= + + Specifies the fixed amount of delay to be added to all packets going out of the + interface. Defaults to unset. + + + + + NetworkEmulatorDelayJitterSec= + + Specifies the chosen delay to be added to the packets outgoing to the network + interface. Defaults to unset. + + + + + NetworkEmulatorPacketLimit= + + Specifies the maximum number of packets the qdisc may hold queued at a time. + An unsigned integer ranges 0 to 4294967294. Defaults to 1000. + + + + + NetworkEmulatorLossRate= + + Specifies an independent loss probability to be added to the packets outgoing from the + network interface. Takes a percentage value, suffixed with "%". Defaults to unset. + + + + + NetworkEmulatorDuplicateRate= + + Specifies that the chosen percent of packets is duplicated before queuing them. + Takes a percentage value, suffixed with "%". Defaults to unset. + + + + + + + + [BridgeVLAN] Section Options + The [BridgeVLAN] section manages the VLAN ID configuration of a bridge port and accepts + the following keys. Specify several [BridgeVLAN] sections to configure several VLAN entries. + The VLANFiltering= option has to be enabled, see [Bridge] section in + systemd.netdev5. + + + + VLAN= + + The VLAN ID allowed on the port. This can be either a single ID or a range M-N. VLAN IDs are valid + from 1 to 4094. + + + + EgressUntagged= + + The VLAN ID specified here will be used to untag frames on egress. Configuring + EgressUntagged= implicates the use of VLAN= above and will enable the + VLAN ID for ingress as well. This can be either a single ID or a range M-N. + + + + PVID= + + The Port VLAN ID specified here is assigned to all untagged frames at ingress. + PVID= can be used only once. Configuring PVID= implicates the use of + VLAN= above and will enable the VLAN ID for ingress as well. + + + + + + + Examples + + Static network configuration + + # /etc/systemd/network/50-static.network +[Match] +Name=enp2s0 + +[Network] +Address=192.168.0.15/24 +Gateway=192.168.0.1 + + This brings interface enp2s0 up with a static address. The + specified gateway will be used for a default route. + + + + DHCP on ethernet links + + # /etc/systemd/network/80-dhcp.network +[Match] +Name=en* + +[Network] +DHCP=yes + + This will enable DHCPv4 and DHCPv6 on all interfaces with names starting with + en (i.e. ethernet interfaces). + + + + IPv6 Prefix Delegation + + # /etc/systemd/network/55-ipv6-pd-upstream.network +[Match] +Name=enp1s0 + +[Network] +DHCP=ipv6 + + # /etc/systemd/network/56-ipv6-pd-downstream.network +[Match] +Name=enp2s0 + +[Network] +IPv6PrefixDelegation=dhcpv6 + + This will enable IPv6 PD on the interface enp1s0 as an upstream interface where the + DHCPv6 client is running and enp2s0 as a downstream interface where the prefix is delegated to. + + + + A bridge with two enslaved links + + # /etc/systemd/network/25-bridge-static.network +[Match] +Name=bridge0 + +[Network] +Address=192.168.0.15/24 +Gateway=192.168.0.1 +DNS=192.168.0.1 + + # /etc/systemd/network/25-bridge-slave-interface-1.network +[Match] +Name=enp2s0 + +[Network] +Bridge=bridge0 + + # /etc/systemd/network/25-bridge-slave-interface-2.network +[Match] +Name=wlp3s0 + +[Network] +Bridge=bridge0 + + This creates a bridge and attaches devices enp2s0 and + wlp3s0 to it. The bridge will have the specified static address + and network assigned, and a default route via the specified gateway will be + added. The specified DNS server will be added to the global list of DNS resolvers. + + + + + + + +# /etc/systemd/network/20-bridge-slave-interface-vlan.network +[Match] +Name=enp2s0 + +[Network] +Bridge=bridge0 + +[BridgeVLAN] +VLAN=1-32 +PVID=42 +EgressUntagged=42 + +[BridgeVLAN] +VLAN=100-200 + +[BridgeVLAN] +EgressUntagged=300-400 + + This overrides the configuration specified in the previous example for the + interface enp2s0, and enables VLAN on that bridge port. VLAN IDs + 1-32, 42, 100-400 will be allowed. Packets tagged with VLAN IDs 42, 300-400 will be + untagged when they leave on this interface. Untagged packets which arrive on this + interface will be assigned VLAN ID 42. + + + + Various tunnels + + /etc/systemd/network/25-tunnels.network +[Match] +Name=ens1 + +[Network] +Tunnel=ipip-tun +Tunnel=sit-tun +Tunnel=gre-tun +Tunnel=vti-tun + + + /etc/systemd/network/25-tunnel-ipip.netdev +[NetDev] +Name=ipip-tun +Kind=ipip + + + /etc/systemd/network/25-tunnel-sit.netdev +[NetDev] +Name=sit-tun +Kind=sit + + + /etc/systemd/network/25-tunnel-gre.netdev +[NetDev] +Name=gre-tun +Kind=gre + + + /etc/systemd/network/25-tunnel-vti.netdev +[NetDev] +Name=vti-tun +Kind=vti + + + This will bring interface ens1 up and create an IPIP tunnel, + a SIT tunnel, a GRE tunnel, and a VTI tunnel using it. + + + + A bond device + + # /etc/systemd/network/30-bond1.network +[Match] +Name=bond1 + +[Network] +DHCP=ipv6 + + + # /etc/systemd/network/30-bond1.netdev +[NetDev] +Name=bond1 +Kind=bond + + + # /etc/systemd/network/30-bond1-dev1.network +[Match] +MACAddress=52:54:00:e9:64:41 + +[Network] +Bond=bond1 + + + # /etc/systemd/network/30-bond1-dev2.network +[Match] +MACAddress=52:54:00:e9:64:42 + +[Network] +Bond=bond1 + + + This will create a bond device bond1 and enslave the two + devices with MAC addresses 52:54:00:e9:64:41 and 52:54:00:e9:64:42 to it. IPv6 DHCP + will be used to acquire an address. + + + + Virtual Routing and Forwarding (VRF) + Add the bond1 interface to the VRF master interface + vrf1. This will redirect routes generated on this interface to be + within the routing table defined during VRF creation. For kernels before 4.8 traffic + won't be redirected towards the VRFs routing table unless specific ip-rules are added. + + # /etc/systemd/network/25-vrf.network +[Match] +Name=bond1 + +[Network] +VRF=vrf1 + + + + + MacVTap + This brings up a network interface macvtap-test + and attaches it to enp0s25. + # /usr/lib/systemd/network/25-macvtap.network +[Match] +Name=enp0s25 + +[Network] +MACVTAP=macvtap-test + + + + + A Xfrm interface with physical underlying device. + + # /etc/systemd/network/27-xfrm.netdev +[NetDev] +Name=xfrm0 + +[Xfrm] +InterfaceId=7 + + # /etc/systemd/network/27-eth0.network +[Match] +Name=eth0 + +[Network] +Xfrm=xfrm0 + + This creates a xfrm0 interface and binds it to the eth0 device. + This allows hardware based ipsec offloading to the eth0 nic. + If offloading is not needed, xfrm interfaces can be assigned to the lo device. + + + + + + See Also + + systemd1, + systemd-networkd.service8, + systemd.link5, + systemd.netdev5, + systemd-resolved.service8 + + + + diff --git a/man/systemd.nspawn.xml b/man/systemd.nspawn.xml new file mode 100644 index 00000000..11df4623 --- /dev/null +++ b/man/systemd.nspawn.xml @@ -0,0 +1,553 @@ + + +%entities; +]> + + + + + + systemd.nspawn + systemd + + + + systemd.nspawn + 5 + + + + systemd.nspawn + Container settings + + + + /etc/systemd/nspawn/machine.nspawn + /run/systemd/nspawn/machine.nspawn + /var/lib/machines/machine.nspawn + + + + Description + + An nspawn container settings file (suffix .nspawn) contains runtime + configuration for a local container, and is used used by + systemd-nspawn1. + Files of this type are named after the containers they define settings for. They are optional, and only + required for containers whose execution environment shall differ from the defaults. Files of this type + mostly contain settings that may also be set on the systemd-nspawn command line, and + make it easier to persistently attach specific settings to specific containers. The syntax of these files + is inspired by .desktop files, similarly to other configuration files supported by + the systemd project. See + systemd.syntax7 for an + overview. + + + + <filename>.nspawn</filename> File Discovery + + Files are searched for by appending the .nspawn suffix to the machine name of + the container, as specified with the switch of + systemd-nspawn, or derived from the directory or image file name. This file is first + searched for in /etc/systemd/nspawn/ and + /run/systemd/nspawn/. If found there, the settings are read and all of them take + full effect (but may still be overridden by corresponding command line arguments). Otherwise, the file + will then be searched for next to the image file or in the immediate parent of the root directory of the + container. If the file is found there, only a subset of the settings will take effect however. All + settings that possibly elevate privileges or grant additional access to resources of the host (such as + files or directories) are ignored. To which options this applies is documented below. + + Persistent settings files created and maintained by the + administrator (and thus trusted) should be placed in + /etc/systemd/nspawn/, while automatically + downloaded (and thus potentially untrusted) settings files are + placed in /var/lib/machines/ instead (next to + the container images), where their security impact is limited. In + order to add privileged settings to .nspawn + files acquired from the image vendor, it is recommended to copy the + settings files into /etc/systemd/nspawn/ and + edit them there, so that the privileged options become + available. The precise algorithm for how the files are searched and + interpreted may be configured with + systemd-nspawn's + switch, see + systemd-nspawn1 + for details. + + + + [Exec] Section Options + + Settings files may include an [Exec] + section, which carries various execution parameters: + + + + + Boot= + + Takes a boolean argument, which defaults to off. If enabled, systemd-nspawn + will automatically search for an init executable and invoke it. In this case, the + specified parameters using Parameters= are passed as additional arguments to the + init process. This setting corresponds to the switch on the + systemd-nspawn command line. This option may not be combined with + ProcessTwo=yes. This option is specified by default in the + systemd-nspawn@.service template unit. + + + + Ephemeral= + + Takes a boolean argument, which defaults to off, If enabled, the container is run with + a temporary snapshot of its file system that is removed immediately when the container terminates. + This is equivalent to the command line switch. See + systemd-nspawn1 for details + about the specific options supported. + + + + ProcessTwo= + + Takes a boolean argument, which defaults to off. If enabled, the specified program is run as + PID 2. A stub init process is run as PID 1. This setting corresponds to the switch + on the systemd-nspawn command line. This option may not be combined with + Boot=yes. + + + + Parameters= + + Takes a whitespace-separated list of arguments. Single (') and + double (") quotes may be used around arguments with whitespace. This is either a + command line, beginning with the binary name to execute, or – if Boot= is enabled + – the list of arguments to pass to the init process. This setting corresponds to the command line + parameters passed on the systemd-nspawn command line. + + Note: , is the same as + systemd-nspawn a b "c c", and , + is the same as systemd-nspawn --boot b 'c c'. + + + + Environment= + + Takes an environment variable assignment + consisting of key and value, separated by + =. Sets an environment variable for the + main process invoked in the container. This setting may be + used multiple times to set multiple environment variables. It + corresponds to the command line + switch. + + + + User= + + Takes a UNIX user name. Specifies the user + name to invoke the main process of the container as. This user + must be known in the container's user database. This + corresponds to the command line + switch. + + + + WorkingDirectory= + + Selects the working directory for the process invoked in the container. Expects an absolute + path in the container's file system namespace. This corresponds to the command line + switch. + + + + PivotRoot= + + Selects a directory to pivot to / inside the container when starting up. + Takes a single path, or a pair of two paths separated by a colon. Both paths must be absolute, and are resolved + in the container's file system namespace. This corresponds to the command line + switch. + + + + Capability= + DropCapability= + + Takes a space-separated list of Linux process + capabilities (see + capabilities7 + for details). The Capability= setting + specifies additional capabilities to pass on top of the + default set of capabilities. The + DropCapability= setting specifies + capabilities to drop from the default set. These settings + correspond to the and + command line + switches. Note that Capability= is a + privileged setting, and only takes effect in + .nspawn files in + /etc/systemd/nspawn/ and + /run/system/nspawn/ (see above). On the + other hand, DropCapability= takes effect in + all cases. If the special value all is passed, all + capabilities are retained (or dropped). + + + + NoNewPrivileges= + + Takes a boolean argument that controls the PR_SET_NO_NEW_PRIVS flag for + the container payload. This is equivalent to the + command line switch. See + systemd-nspawn1 for + details. + + + + + KillSignal= + + Specify the process signal to send to the + container's PID 1 when nspawn itself receives SIGTERM, in + order to trigger an orderly shutdown of the container. + Defaults to SIGRTMIN+3 if is used + (on systemd-compatible init systems SIGRTMIN+3 triggers an + orderly shutdown). For a list of valid signals, see + signal7. + + + + Personality= + + Configures the kernel personality for the + container. This is equivalent to the + switch. + + + + MachineID= + + Configures the 128-bit machine ID (UUID) to pass to + the container. This is equivalent to the + command line switch. This option is + privileged (see above). + + + + PrivateUsers= + + Configures support for usernamespacing. This is equivalent to the + command line switch, and takes the same options. This option is privileged + (see above). This option is the default if the systemd-nspawn@.service template unit file + is used. + + + + NotifyReady= + + Configures support for notifications from the container's init process. This is equivalent to + the command line switch, and takes the same parameters. See + systemd-nspawn1 for details + about the specific options supported. + + + + SystemCallFilter= + + Configures the system call filter applied to containers. This is equivalent to the + command line switch, and takes the same list parameter. See + systemd-nspawn1 for + details. + + + + LimitCPU= + LimitFSIZE= + LimitDATA= + LimitSTACK= + LimitCORE= + LimitRSS= + LimitNOFILE= + LimitAS= + LimitNPROC= + LimitMEMLOCK= + LimitLOCKS= + LimitSIGPENDING= + LimitMSGQUEUE= + LimitNICE= + LimitRTPRIO= + LimitRTTIME= + + Configures various types of resource limits applied to containers. This is equivalent to the + command line switch, and takes the same arguments. See + systemd-nspawn1 for + details. + + + + OOMScoreAdjust= + + Configures the OOM score adjustment value. This is equivalent to the + command line switch, and takes the same argument. See + systemd-nspawn1 for + details. + + + + CPUAffinity= + + Configures the CPU affinity. This is equivalent to the command + line switch, and takes the same argument. See + systemd-nspawn1 for + details. + + + + Hostname= + + Configures the kernel hostname set for the container. This is equivalent to the + command line switch, and takes the same argument. See + systemd-nspawn1 for + details. + + + + ResolvConf= + + Configures how /etc/resolv.conf in the container shall be handled. This is + equivalent to the command line switch, and takes the same argument. See + systemd-nspawn1 for + details. + + + + Timezone= + + Configures how /etc/localtime in the container shall be handled. This is + equivalent to the command line switch, and takes the same argument. See + systemd-nspawn1 for + details. + + + + LinkJournal= + + Configures how to link host and container journal setups. This is equivalent to the + command line switch, and takes the same parameter. See + systemd-nspawn1 for + details. + + + + + + + [Files] Section Options + + Settings files may include a [Files] + section, which carries various parameters configuring the file + system of the container: + + + + + ReadOnly= + + Takes a boolean argument, which defaults to off. If + specified, the container will be run with a read-only file + system. This setting corresponds to the + command line + switch. + + + + Volatile= + + Takes a boolean argument, or the special value + state. This configures whether to run the + container with volatile state and/or configuration. This + option is equivalent to , see + systemd-nspawn1 + for details about the specific options + supported. + + + + Bind= + BindReadOnly= + + Adds a bind mount from the host into the + container. Takes a single path, a pair of two paths separated + by a colon, or a triplet of two paths plus an option string + separated by colons. This option may be used multiple times to + configure multiple bind mounts. This option is equivalent to + the command line switches and + , see + systemd-nspawn1 + for details about the specific options supported. This setting + is privileged (see above). + + + + TemporaryFileSystem= + + Adds a tmpfs mount to the + container. Takes a path or a pair of path and option string, + separated by a colon. This option may be used multiple times to + configure multiple tmpfs mounts. This + option is equivalent to the command line switch + , see + systemd-nspawn1 + for details about the specific options supported. This setting + is privileged (see above). + + + + Inaccessible= + + Masks the specified file or directly in the container, by over-mounting it with an empty file + node of the same type with the most restrictive access mode. Takes a file system path as argument. This option + may be used multiple times to mask multiple files or directories. This option is equivalent to the command line + switch , see + systemd-nspawn1 for details + about the specific options supported. This setting is privileged (see above). + + + + Overlay= + OverlayReadOnly= + + Adds an overlay mount point. Takes a colon-separated list of paths. This option may be used + multiple times to configure multiple overlay mounts. This option is equivalent to the command line switches + and , see + systemd-nspawn1 for details + about the specific options supported. This setting is privileged (see above). + + + + PrivateUsersChown= + + Configures whether the ownership of the files and directories in the container tree shall be + adjusted to the UID/GID range used, if necessary and user namespacing is enabled. This is equivalent to the + command line switch. This option is privileged (see + above). + + + + + + + [Network] Section Options + + Settings files may include a [Network] + section, which carries various parameters configuring the network + connectivity of the container: + + + + + Private= + + Takes a boolean argument, which defaults to off. If + enabled, the container will run in its own network namespace + and not share network interfaces and configuration with the + host. This setting corresponds to the + command line + switch. + + + + VirtualEthernet= + + Takes a boolean argument. Configures whether to create a virtual Ethernet connection + (veth) between host and the container. This setting implies + Private=yes. This setting corresponds to the command line + switch. This option is privileged (see above). This option is the default if the + systemd-nspawn@.service template unit file is used. + + + + VirtualEthernetExtra= + + Takes a colon-separated pair of interface + names. Configures an additional virtual Ethernet connection + (veth) between host and the container. The + first specified name is the interface name on the host, the + second the interface name in the container. The latter may be + omitted in which case it is set to the same name as the host + side interface. This setting implies + Private=yes. This setting corresponds to + the command line + switch, and maybe be used multiple times. It is independent of + VirtualEthernet=. This option is privileged + (see above). + + + + Interface= + + Takes a space-separated list of interfaces to + add to the container. This option corresponds to the + command line switch and + implies Private=yes. This option is + privileged (see above). + + + + MACVLAN= + IPVLAN= + + Takes a space-separated list of interfaces to + add MACLVAN or IPVLAN interfaces to, which are then added to + the container. These options correspond to the + and + command line switches and + imply Private=yes. These options are + privileged (see above). + + + + Bridge= + + Takes an interface name. This setting implies + VirtualEthernet=yes and + Private=yes and has the effect that the + host side of the created virtual Ethernet link is connected to + the specified bridge interface. This option corresponds to the + command line switch. This + option is privileged (see above). + + + + Zone= + + Takes a network zone name. This setting implies VirtualEthernet=yes and + Private=yes and has the effect that the host side of the created virtual Ethernet link is + connected to an automatically managed bridge interface named after the passed argument, prefixed with + vz-. This option corresponds to the command line + switch. This option is privileged (see above). + + + + Port= + + Exposes a TCP or UDP port of the container on + the host. This option corresponds to the + command line switch, see + systemd-nspawn1 + for the precise syntax of the argument this option takes. This + option is privileged (see above). + + + + + + See Also + + systemd1, + systemd-nspawn1, + systemd.directives7 + + + + diff --git a/man/systemd.offline-updates.xml b/man/systemd.offline-updates.xml new file mode 100644 index 00000000..89c12b59 --- /dev/null +++ b/man/systemd.offline-updates.xml @@ -0,0 +1,163 @@ + + + + + + + systemd.offline-updates + systemd + + + + systemd.offline-updates + 7 + + + + systemd.offline-updates + Implementation of offline updates in systemd + + + + Implementing Offline System Updates + + This man page describes how to implement "offline" system updates with systemd. By "offline" + OS updates we mean package installations and updates that are run with the system booted into a + special system update mode, in order to avoid problems related to conflicts of libraries and + services that are currently running with those on disk. This document is inspired by this + GNOME design whiteboard. + + + The logic: + + + + The package manager prepares system updates by downloading all (RPM or DEB or + whatever) packages to update off-line in a special directory + /var/lib/system-update (or + another directory of the package/upgrade manager's choice). + + + + When the user OK'ed the update, the symlink /system-update is + created that points to /var/lib/system-update (or + wherever the directory with the upgrade files is located) and the system is rebooted. This + symlink is in the root directory, since we need to check for it very early at boot, at a + time where /var is not available yet. + + + + Very early in the new boot + systemd-system-update-generator8 + checks whether /system-update exists. If so, it (temporarily and for + this boot only) redirects (i.e. symlinks) default.target to + system-update.target, a special target that pulls in the base system + (i.e. sysinit.target, so that all file systems are mounted but little + else) and the system update units. + + + + The system now continues to boot into default.target, and + thus into system-update.target. This target pulls in all system + update units. Only one service should perform an update (see the next point), and all + the other ones should exit cleanly with a "success" return code and without doing + anything. Update services should be ordered after sysinit.target + so that the update starts after all file systems have been mounted. + + + + As the first step, an update service should check if the + /system-update symlink points to the location used by that update + service. In case it does not exist or points to a different location, the service must exit + without error. It is possible for multiple update services to be installed, and for multiple + update services to be launched in parallel, and only the one that corresponds to the tool + that created the symlink before reboot should perform any actions. It + is unsafe to run multiple updates in parallel. + + + + The update service should now do its job. If applicable and possible, it should + create a file system snapshot, then install all packages. After completion (regardless + whether the update succeeded or failed) the machine must be rebooted, for example by + calling systemctl reboot. In addition, on failure the script should + revert to the old file system snapshot (without the symlink). + + + + The upgrade scripts should exit only after the update is finished. It is expected + that the service which performs the upgrade will cause the machine to reboot after it + is done. If the system-update.target is successfully reached, i.e. + all update services have run, and the /system-update symlink still + exists, it will be removed and the machine rebooted as a safety measure. + + + + After a reboot, now that the /system-update symlink is gone, + the generator won't redirect default.target anymore and the system + now boots into the default target again. + + + + + + Recommendations + + + + To make things a bit more robust we recommend hooking the update script into + system-update.target via a .wants/ + symlink in the distribution package, rather than depending on systemctl + enable in the postinst scriptlets of your package. More specifically, for your + update script create a .service file, without [Install] section, and then add a symlink like + /usr/lib/systemd/system-update.target.wants/foobar.service + → ../foobar.service to your package. + + + + Make sure to remove the /system-update symlink as early as + possible in the update script to avoid reboot loops in case the update fails. + + + + Use FailureAction=reboot in the service file for your update script + to ensure that a reboot is automatically triggered if the update fails. + FailureAction= makes sure that the specified unit is activated if your + script exits uncleanly (by non-zero error code, or signal/coredump). If your script succeeds + you should trigger the reboot in your own code, for example by invoking logind's + Reboot() call or calling systemctl reboot. See + logind dbus API + for details. + + + + The update service should declare DefaultDependencies=no, + Requires=sysinit.target, After=sysinit.target, + After=system-update-pre.target, Before=system-update.target + and explicitly pull in any other services it requires. + + + + It may be desirable to always run an auxiliary unit when booting + into offline-updates mode, which itself does not install updates. To + do this create a .service file with + Wants=system-update-pre.target and + Before=system-update-pre.target and add a symlink + to that file under + /usr/lib/systemd/system-update.target.wants + . + + + + + + See also + + + systemd1, + systemd.generator7, + systemd-system-update-generator8, + dnf.plugin.system-upgrade8 + + + diff --git a/man/systemd.path.xml b/man/systemd.path.xml new file mode 100644 index 00000000..39cca8cf --- /dev/null +++ b/man/systemd.path.xml @@ -0,0 +1,192 @@ + + + + + + + systemd.path + systemd + + + + systemd.path + 5 + + + + systemd.path + Path unit configuration + + + + path.path + + + + Description + + A unit configuration file whose name ends in + .path encodes information about a path + monitored by systemd, for path-based activation. + + This man page lists the configuration options specific to + this unit type. See + systemd.unit5 + for the common options of all unit configuration files. The common + configuration items are configured in the generic [Unit] and + [Install] sections. The path specific configuration options are + configured in the [Path] section. + + For each path file, a matching unit file must exist, + describing the unit to activate when the path changes. By default, + a service by the same name as the path (except for the suffix) is + activated. Example: a path file foo.path + activates a matching service foo.service. The + unit to activate may be controlled by Unit= + (see below). + + Internally, path units use the + inotify7 + API to monitor file systems. Due to that, it suffers by the same + limitations as inotify, and for example cannot be used to monitor + files or directories changed by other machines on remote NFS file + systems. + + + + Automatic Dependencies + + + Implicit Dependencies + + The following dependencies are implicitly added: + + + If a path unit is beneath another mount unit in the file + system hierarchy, both a requirement and an ordering dependency + between both units are created automatically. + + An implicit Before= dependency is added + between a path unit and the unit it is supposed to activate. + + + + + Default Dependencies + + The following dependencies are added unless DefaultDependencies=no is set: + + + Path units will automatically have dependencies of type Before= on + paths.target, + dependencies of type After= and Requires= on + sysinit.target, and have dependencies of type Conflicts= and + Before= on shutdown.target. These ensure that path units are terminated + cleanly prior to system shutdown. Only path units involved with early boot or late system shutdown should + disable DefaultDependencies= option. + + + + + + + + Options + + Path files must include a [Path] section, which carries + information about the path(s) it monitors. The options specific to + the [Path] section of path units are the following: + + + + PathExists= + PathExistsGlob= + PathChanged= + PathModified= + DirectoryNotEmpty= + + Defines paths to monitor for certain changes: + PathExists= may be used to watch the mere + existence of a file or directory. If the file specified + exists, the configured unit is activated. + PathExistsGlob= works similar, but checks + for the existence of at least one file matching the globbing + pattern specified. PathChanged= may be used + to watch a file or directory and activate the configured unit + whenever it changes. It is not activated on every write to the + watched file but it is activated if the file which was open + for writing gets closed. PathModified= is + similar, but additionally it is activated also on simple + writes to the watched file. + DirectoryNotEmpty= may be used to watch a + directory and activate the configured unit whenever it + contains at least one file. + + The arguments of these directives must be absolute file + system paths. + + Multiple directives may be combined, of the same and of + different types, to watch multiple paths. If the empty string + is assigned to any of these options, the list of paths to + watch is reset, and any prior assignments of these options + will not have any effect. + + If a path already exists (in case of + PathExists= and + PathExistsGlob=) or a directory already is + not empty (in case of DirectoryNotEmpty=) + at the time the path unit is activated, then the configured + unit is immediately activated as well. Something similar does + not apply to PathChanged= and + PathModified=. + + If the path itself or any of the containing directories + are not accessible, systemd will watch for + permission changes and notice that conditions are satisfied + when permissions allow that. + + + Unit= + + The unit to activate when any of the + configured paths changes. The argument is a unit name, whose + suffix is not .path. If not specified, this + value defaults to a service that has the same name as the path + unit, except for the suffix. (See above.) It is recommended + that the unit name that is activated and the unit name of the + path unit are named identical, except for the + suffix. + + + MakeDirectory= + + Takes a boolean argument. If true, the + directories to watch are created before watching. This option + is ignored for PathExists= settings. + Defaults to . + + + DirectoryMode= + + If MakeDirectory= is + enabled, use the mode specified here to create the directories + in question. Takes an access mode in octal notation. Defaults + to . + + + + + + See Also + + systemd1, + systemctl1, + systemd.unit5, + systemd.service5, + inotify7, + systemd.directives7 + + + + diff --git a/man/systemd.preset.xml b/man/systemd.preset.xml new file mode 100644 index 00000000..30c838b3 --- /dev/null +++ b/man/systemd.preset.xml @@ -0,0 +1,173 @@ + + + + + + + + systemd.preset + systemd + + + + systemd.preset + 5 + + + + systemd.preset + Service enablement presets + + + + /etc/systemd/system-preset/*.preset + /run/systemd/system-preset/*.preset + /usr/lib/systemd/system-preset/*.preset + /etc/systemd/user-preset/*.preset + /run/systemd/user-preset/*.preset + /usr/lib/systemd/user-preset/*.preset + + + + Description + + Preset files may be used to encode policy which units shall + be enabled by default and which ones shall be disabled. They are + read by systemctl preset (for more information + see + systemctl1) + which uses this information to enable or disable a unit according + to preset policy. systemctl preset is used by + the post install scriptlets of RPM packages (or other OS package + formats), to enable/disable specific units by default on package + installation, enforcing distribution, spin or administrator preset + policy. This allows choosing a certain set of units to be + enabled/disabled even before installing the actual package. + + For more information on the preset logic please have a look + at the Presets + document. + + It is not recommended to ship preset files within the + respective software packages implementing the units, but rather + centralize them in a distribution or spin default policy, which + can be amended by administrator policy. + + If no preset files exist, systemctl + preset will enable all units that are installed by + default. If this is not desired and all units shall rather be + disabled, it is necessary to ship a preset file with a single, + catchall "disable *" line. (See example 1, + below.) + + + + Preset File Format + + The preset files contain a list of directives consisting of + either the word enable or + disable followed by a space and a unit name + (possibly with shell style wildcards), separated by newlines. + Empty lines and lines whose first non-whitespace character is # or + ; are ignored. + + Presets must refer to the "real" unit file, and not to any aliases. See + systemd.unit5 + for a description of unit aliasing. + + Two different directives are understood: + enable may be used to enable units by default, + disable to disable units by default. + + If multiple lines apply to a unit name, the first matching + one takes precedence over all others. + + Each preset file shall be named in the style of + <priority>-<policy-name>.preset. Files + in /etc/ override files with the same name in + /usr/lib/ and /run/. + Files in /run/ override files with the same + name in /usr/lib/. Packages should install + their preset files in /usr/lib/. Files in + /etc/ are reserved for the local + administrator, who may use this logic to override the preset files + installed by vendor packages. All preset files are sorted by their + filename in lexicographic order, regardless of which of the + directories they reside in. If multiple files specify the same + unit name, the entry in the file with the lexicographically + earliest name will be applied. It is recommended to prefix all + filenames with a two-digit number and a dash, to simplify the + ordering of the files. + + If the administrator wants to disable a preset file supplied + by the vendor, the recommended way is to place a symlink to + /dev/null in + /etc/systemd/system-preset/ bearing the same + filename. + + + + Examples + + + Default to off + + # /usr/lib/systemd/system-preset/99-default.preset + +disable * + + + This disables all units. Due to the filename prefix + 99-, it will be read last and hence can easily + be overridden by spin or administrator preset policy. + + + A GNOME spin + + # /usr/lib/systemd/system-preset/50-gnome.preset + +enable gdm.service +enable colord.service +enable accounts-daemon.service +enable avahi-daemon.* + + + + This enables the three mentioned units, plus all + avahi-daemon regardless of which unit type. A + file like this could be useful for inclusion in a GNOME spin of a + distribution. It will ensure that the units necessary for GNOME + are properly enabled as they are installed. It leaves all other + units untouched, and subject to other (later) preset files, for + example like the one from the first example above. + + + Administrator policy + + # /etc/systemd/system-preset/00-lennart.preset + +enable httpd.service +enable sshd.service +enable postfix.service +disable * + + + This enables three specific services and disables all + others. This is useful for administrators to specifically select + the units to enable, and disable all others. Due to the filename + prefix 00- it will be read early and + override all other preset policy files. + + + + See Also + + systemd1, + systemctl1, + systemd-delta1 + + + + diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml new file mode 100644 index 00000000..a9600917 --- /dev/null +++ b/man/systemd.resource-control.xml @@ -0,0 +1,1032 @@ + + + + + + + systemd.resource-control + systemd + + + + systemd.resource-control + 5 + + + + systemd.resource-control + Resource control unit settings + + + + + slice.slice, + scope.scope, + service.service, + socket.socket, + mount.mount, + swap.swap + + + + + Description + + Unit configuration files for services, slices, scopes, sockets, mount points, and swap devices share a subset + of configuration options for resource control of spawned processes. Internally, this relies on the Linux Control + Groups (cgroups) kernel concept for organizing processes in a hierarchical tree of named groups for the purpose of + resource management. + + This man page lists the configuration options shared by + those six unit types. See + systemd.unit5 + for the common options of all unit configuration files, and + systemd.slice5, + systemd.scope5, + systemd.service5, + systemd.socket5, + systemd.mount5, + and + systemd.swap5 + for more information on the specific unit configuration files. The + resource control configuration options are configured in the + [Slice], [Scope], [Service], [Socket], [Mount], or [Swap] + sections, depending on the unit type. + + In addition, options which control resources available to programs + executed by systemd are listed in + systemd.exec5. + Those options complement options listed here. + + See the New + Control Group Interfaces for an introduction on how to make + use of resource control APIs from programs. + + + + Implicit Dependencies + + The following dependencies are implicitly added: + + + Units with the Slice= setting set automatically acquire + Requires= and After= dependencies on the specified + slice unit. + + + + + + + Unified and Legacy Control Group Hierarchies + + The unified control group hierarchy is the new version of kernel control group interface, see cgroup-v2.txt. Depending on the resource type, + there are differences in resource control capabilities. Also, because of interface changes, some resource types + have separate set of options on the unified hierarchy. + + + + + + CPU + + CPUWeight= and StartupCPUWeight= replace + CPUShares= and StartupCPUShares=, respectively. + + The cpuacct controller does not exist separately on the unified hierarchy. + + + + + Memory + + MemoryMax= replaces MemoryLimit=. MemoryLow= + and MemoryHigh= are effective only on unified hierarchy. + + + + + IO + + IO-prefixed settings are a superset of and replace + BlockIO-prefixed ones. On unified hierarchy, IO resource control also applies + to buffered writes. + + + + + + + To ease the transition, there is best-effort translation between the two versions of settings. For each + controller, if any of the settings for the unified hierarchy are present, all settings for the legacy hierarchy are + ignored. If the resulting settings are for the other type of hierarchy, the configurations are translated before + application. + + Legacy control group hierarchy (see cgroups.txt), also called cgroup-v1, + doesn't allow safe delegation of controllers to unprivileged processes. If the system uses the legacy control group + hierarchy, resource control is disabled for systemd user instance, see + systemd1. + + + + + Options + + Units of the types listed above can have settings + for resource control configuration: + + + + + CPUAccounting= + + + Turn on CPU usage accounting for this unit. Takes a + boolean argument. Note that turning on CPU accounting for + one unit will also implicitly turn it on for all units + contained in the same slice and for all its parent slices + and the units contained therein. The system default for this + setting may be controlled with + DefaultCPUAccounting= in + systemd-system.conf5. + + + + + CPUWeight=weight + StartupCPUWeight=weight + + + Assign the specified CPU time weight to the processes executed, if the unified control group hierarchy + is used on the system. These options take an integer value and control the cpu.weight + control group attribute. The allowed range is 1 to 10000. Defaults to 100. For details about this control + group attribute, see cgroup-v2.txt and sched-design-CFS.txt. + The available CPU time is split up among all units within one slice relative to their CPU time weight. + + While StartupCPUWeight= only applies to the startup phase of the system, + CPUWeight= applies to normal runtime of the system, and if the former is not set also to + the startup phase. Using StartupCPUWeight= allows prioritizing specific services at + boot-up differently than during normal runtime. + + These settings replace CPUShares= and StartupCPUShares=. + + + + + CPUQuota= + + + Assign the specified CPU time quota to the processes executed. Takes a percentage value, suffixed with + "%". The percentage specifies how much CPU time the unit shall get at maximum, relative to the total CPU time + available on one CPU. Use values > 100% for allotting CPU time on more than one CPU. This controls the + cpu.max attribute on the unified control group hierarchy and + cpu.cfs_quota_us on legacy. For details about these control group attributes, see cgroup-v2.txt and sched-bwc.txt. + + Example: CPUQuota=20% ensures that the executed processes will never get more than + 20% CPU time on one CPU. + + + + + + CPUQuotaPeriodSec= + + + Assign the duration over which the CPU time quota specified by CPUQuota= is measured. + Takes a time duration value in seconds, with an optional suffix such as "ms" for milliseconds (or "s" for seconds.) + The default setting is 100ms. The period is clamped to the range supported by the kernel, which is [1ms, 1000ms]. + Additionally, the period is adjusted up so that the quota interval is also at least 1ms. + Setting CPUQuotaPeriodSec= to an empty value resets it to the default. + + This controls the second field of cpu.max attribute on the unified control group hierarchy + and cpu.cfs_period_us on legacy. For details about these control group attributes, see + cgroup-v2.txt and + sched-design-CFS.txt. + + Example: CPUQuotaPeriodSec=10ms to request that the CPU quota is measured in periods of 10ms. + + + + + AllowedCPUs= + + + Restrict processes to be executed on specific CPUs. Takes a list of CPU indices or ranges separated by either + whitespace or commas. CPU ranges are specified by the lower and upper CPU indices separated by a dash. + + Setting AllowedCPUs= doesn't guarantee that all of the CPUs will be used by the processes + as it may be limited by parent units. The effective configuration is reported as EffectiveCPUs=. + + This setting is supported only with the unified control group hierarchy. + + + + + AllowedMemoryNodes= + + + Restrict processes to be executed on specific memory NUMA nodes. Takes a list of memory NUMA nodes indices + or ranges separated by either whitespace or commas. Memory NUMA nodes ranges are specified by the lower and upper + CPU indices separated by a dash. + + Setting AllowedMemoryNodes= doesn't guarantee that all of the memory NUMA nodes will + be used by the processes as it may be limited by parent units. The effective configuration is reported as + EffectiveMemoryNodes=. + + This setting is supported only with the unified control group hierarchy. + + + + + MemoryAccounting= + + + Turn on process and kernel memory accounting for this + unit. Takes a boolean argument. Note that turning on memory + accounting for one unit will also implicitly turn it on for + all units contained in the same slice and for all its parent + slices and the units contained therein. The system default + for this setting may be controlled with + DefaultMemoryAccounting= in + systemd-system.conf5. + + + + + MemoryMin=bytes + + + Specify the memory usage protection of the executed processes in this unit. If the memory usages of + this unit and all its ancestors are below their minimum boundaries, this unit's memory won't be reclaimed. + + Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is + parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. Alternatively, a + percentage value may be specified, which is taken relative to the installed physical memory on the + system. If assigned the special value infinity, all available memory is protected, which may be + useful in order to always inherit all of the protection afforded by ancestors. + This controls the memory.min control group attribute. For details about this + control group attribute, see cgroup-v2.txt. + + This setting is supported only if the unified control group hierarchy is used and disables + MemoryLimit=. + + Units may have their children use a default memory.min value by specifying + DefaultMemoryMin=, which has the same semantics as MemoryMin=. This setting + does not affect memory.min in the unit itself. + + + + + MemoryLow=bytes + + + Specify the best-effort memory usage protection of the executed processes in this unit. If the memory + usages of this unit and all its ancestors are below their low boundaries, this unit's memory won't be + reclaimed as long as memory can be reclaimed from unprotected units. + + Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is + parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. Alternatively, a + percentage value may be specified, which is taken relative to the installed physical memory on the + system. If assigned the special value infinity, all available memory is protected, which may be + useful in order to always inherit all of the protection afforded by ancestors. + This controls the memory.low control group attribute. For details about this + control group attribute, see cgroup-v2.txt. + + This setting is supported only if the unified control group hierarchy is used and disables + MemoryLimit=. + + Units may have their children use a default memory.low value by specifying + DefaultMemoryLow=, which has the same semantics as MemoryLow=. This setting + does not affect memory.low in the unit itself. + + + + + MemoryHigh=bytes + + + Specify the throttling limit on memory usage of the executed processes in this unit. Memory usage may go + above the limit if unavoidable, but the processes are heavily slowed down and memory is taken away + aggressively in such cases. This is the main mechanism to control memory usage of a unit. + + Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is + parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. Alternatively, a + percentage value may be specified, which is taken relative to the installed physical memory on the + system. If assigned the + special value infinity, no memory throttling is applied. This controls the + memory.high control group attribute. For details about this control group attribute, see + cgroup-v2.txt. + + This setting is supported only if the unified control group hierarchy is used and disables + MemoryLimit=. + + + + + MemoryMax=bytes + + + Specify the absolute limit on memory usage of the executed processes in this unit. If memory usage + cannot be contained under the limit, out-of-memory killer is invoked inside the unit. It is recommended to + use MemoryHigh= as the main control mechanism and use MemoryMax= as the + last line of defense. + + Takes a memory size in bytes. If the value is suffixed with K, M, G or T, the specified memory size is + parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. Alternatively, a + percentage value may be specified, which is taken relative to the installed physical memory on the system. If + assigned the special value infinity, no memory limit is applied. This controls the + memory.max control group attribute. For details about this control group attribute, see + cgroup-v2.txt. + + This setting replaces MemoryLimit=. + + + + + MemorySwapMax=bytes + + + Specify the absolute limit on swap usage of the executed processes in this unit. + + Takes a swap size in bytes. If the value is suffixed with K, M, G or T, the specified swap size is + parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes (with the base 1024), respectively. If assigned the + special value infinity, no swap limit is applied. This controls the + memory.swap.max control group attribute. For details about this control group attribute, + see cgroup-v2.txt. + + This setting is supported only if the unified control group hierarchy is used and disables + MemoryLimit=. + + + + + TasksAccounting= + + + Turn on task accounting for this unit. Takes a + boolean argument. If enabled, the system manager will keep + track of the number of tasks in the unit. The number of + tasks accounted this way includes both kernel threads and + userspace processes, with each thread counting + individually. Note that turning on tasks accounting for one + unit will also implicitly turn it on for all units contained + in the same slice and for all its parent slices and the + units contained therein. The system default for this setting + may be controlled with + DefaultTasksAccounting= in + systemd-system.conf5. + + + + + TasksMax=N + + + Specify the maximum number of tasks that may be created in the unit. This ensures that the number of + tasks accounted for the unit (see above) stays below a specific limit. This either takes an absolute number + of tasks or a percentage value that is taken relative to the configured maximum number of tasks on the + system. If assigned the special value infinity, no tasks limit is applied. This controls + the pids.max control group attribute. For details about this control group attribute, see + pids.txt. + + The + system default for this setting may be controlled with + DefaultTasksMax= in + systemd-system.conf5. + + + + + IOAccounting= + + + Turn on Block I/O accounting for this unit, if the unified control group hierarchy is used on the + system. Takes a boolean argument. Note that turning on block I/O accounting for one unit will also implicitly + turn it on for all units contained in the same slice and all for its parent slices and the units contained + therein. The system default for this setting may be controlled with DefaultIOAccounting= + in + systemd-system.conf5. + + This setting replaces BlockIOAccounting= and disables settings prefixed with + BlockIO or StartupBlockIO. + + + + + IOWeight=weight + StartupIOWeight=weight + + + Set the default overall block I/O weight for the executed processes, if the unified control group + hierarchy is used on the system. Takes a single weight value (between 1 and 10000) to set the default block + I/O weight. This controls the io.weight control group attribute, which defaults to + 100. For details about this control group attribute, see cgroup-v2.txt. The available I/O + bandwidth is split up among all units within one slice relative to their block I/O weight. + + While StartupIOWeight= only applies + to the startup phase of the system, + IOWeight= applies to the later runtime of + the system, and if the former is not set also to the startup + phase. This allows prioritizing specific services at boot-up + differently than during runtime. + + These settings replace BlockIOWeight= and StartupBlockIOWeight= + and disable settings prefixed with BlockIO or StartupBlockIO. + + + + + IODeviceWeight=device weight + + + Set the per-device overall block I/O weight for the executed processes, if the unified control group + hierarchy is used on the system. Takes a space-separated pair of a file path and a weight value to specify + the device specific weight value, between 1 and 10000. (Example: /dev/sda 1000). The file + path may be specified as path to a block device node or as any other file, in which case the backing block + device of the file system of the file is determined. This controls the io.weight control + group attribute, which defaults to 100. Use this option multiple times to set weights for multiple devices. + For details about this control group attribute, see cgroup-v2.txt. + + This setting replaces BlockIODeviceWeight= and disables settings prefixed with + BlockIO or StartupBlockIO. + + + + + IOReadBandwidthMax=device bytes + IOWriteBandwidthMax=device bytes + + + Set the per-device overall block I/O bandwidth maximum limit for the executed processes, if the unified + control group hierarchy is used on the system. This limit is not work-conserving and the executed processes + are not allowed to use more even if the device has idle capacity. Takes a space-separated pair of a file + path and a bandwidth value (in bytes per second) to specify the device specific bandwidth. The file path may + be a path to a block device node, or as any other file in which case the backing block device of the file + system of the file is used. If the bandwidth is suffixed with K, M, G, or T, the specified bandwidth is + parsed as Kilobytes, Megabytes, Gigabytes, or Terabytes, respectively, to the base of 1000. (Example: + "/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 5M"). This controls the io.max control + group attributes. Use this option multiple times to set bandwidth limits for multiple devices. For details + about this control group attribute, see cgroup-v2.txt. + + + These settings replace BlockIOReadBandwidth= and + BlockIOWriteBandwidth= and disable settings prefixed with BlockIO or + StartupBlockIO. + + + + + IOReadIOPSMax=device IOPS + IOWriteIOPSMax=device IOPS + + + Set the per-device overall block I/O IOs-Per-Second maximum limit for the executed processes, if the + unified control group hierarchy is used on the system. This limit is not work-conserving and the executed + processes are not allowed to use more even if the device has idle capacity. Takes a space-separated pair of + a file path and an IOPS value to specify the device specific IOPS. The file path may be a path to a block + device node, or as any other file in which case the backing block device of the file system of the file is + used. If the IOPS is suffixed with K, M, G, or T, the specified IOPS is parsed as KiloIOPS, MegaIOPS, + GigaIOPS, or TeraIOPS, respectively, to the base of 1000. (Example: + "/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 1K"). This controls the io.max control + group attributes. Use this option multiple times to set IOPS limits for multiple devices. For details about + this control group attribute, see cgroup-v2.txt. + + + These settings are supported only if the unified control group hierarchy is used and disable settings + prefixed with BlockIO or StartupBlockIO. + + + + + IODeviceLatencyTargetSec=device target + + + Set the per-device average target I/O latency for the executed processes, if the unified control group + hierarchy is used on the system. Takes a file path and a timespan separated by a space to specify + the device specific latency target. (Example: "/dev/sda 25ms"). The file path may be specified + as path to a block device node or as any other file, in which case the backing block device of the file + system of the file is determined. This controls the io.latency control group + attribute. Use this option multiple times to set latency target for multiple devices. For details about this + control group attribute, see cgroup-v2.txt. + + Implies IOAccounting=yes. + + These settings are supported only if the unified control group hierarchy is used. + + + + + IPAccounting= + + + Takes a boolean argument. If true, turns on IPv4 and IPv6 network traffic accounting for packets sent + or received by the unit. When this option is turned on, all IPv4 and IPv6 sockets created by any process of + the unit are accounted for. + + When this option is used in socket units, it applies to all IPv4 and IPv6 sockets + associated with it (including both listening and connection sockets where this applies). Note that for + socket-activated services, this configuration setting and the accounting data of the service unit and the + socket unit are kept separate, and displayed separately. No propagation of the setting and the collected + statistics is done, in either direction. Moreover, any traffic sent or received on any of the socket unit's + sockets is accounted to the socket unit — and never to the service unit it might have activated, even if the + socket is used by it. + + The system default for this setting may be controlled with DefaultIPAccounting= in + systemd-system.conf5. + + + + + IPAddressAllow=ADDRESS[/PREFIXLENGTH]… + IPAddressDeny=ADDRESS[/PREFIXLENGTH]… + + + Turn on address range network traffic filtering for IP packets sent and received over + AF_INET and AF_INET6 sockets. Both directives take a + space separated list of IPv4 or IPv6 addresses, each optionally suffixed with an address prefix + length in bits (separated by a / character). If the latter is omitted, the + address is considered a host address, i.e. the prefix covers the whole address (32 for IPv4, 128 + for IPv6). + + The access lists configured with this option are applied to all sockets created by processes + of this unit (or in the case of socket units, associated with it). The lists are implicitly + combined with any lists configured for any of the parent slice units this unit might be a member + of. By default all access lists are empty. Both ingress and egress traffic is filtered by these + settings. In case of ingress traffic the source IP address is checked against these access lists, + in case of egress traffic the destination IP address is checked. When configured the lists are + enforced as follows: + + + Access will be granted in case an IP packet's destination/source address matches + any entry in the IPAddressAllow= setting. + + Otherwise, access will be denied in case its destination/source address matches + any entry in the IPAddressDeny= setting. + + Otherwise, access will be granted. + + + In order to implement a whitelisting IP firewall, it is recommended to use a + IPAddressDeny=any setting on an upper-level slice unit (such as the + root slice -.slice or the slice containing all system services + system.slice – see + systemd.special7 for + details on these slice units), plus individual per-service IPAddressAllow= lines + permitting network access to relevant services, and only them. + + Note that for socket-activated services, the IP access list configured on the socket unit applies to + all sockets associated with it directly, but not to any sockets created by the ultimately activated services + for it. Conversely, the IP access list configured for the service is not applied to any sockets passed into + the service via socket activation. Thus, it is usually a good idea, to replicate the IP access lists on both + the socket and the service unit, however it often makes sense to maintain one list more open and the other + one more restricted, depending on the usecase. + + If these settings are used multiple times in the same unit the specified lists are combined. If an + empty string is assigned to these settings the specific access list is reset and all previous settings undone. + + In place of explicit IPv4 or IPv6 address and prefix length specifications a small set of symbolic + names may be used. The following names are defined: + + + Special address/network names + + + + + + + + + Symbolic Name + Definition + Meaning + + + + + + any + 0.0.0.0/0 ::/0 + Any host + + + + localhost + 127.0.0.0/8 ::1/128 + All addresses on the local loopback + + + + link-local + 169.254.0.0/16 fe80::/64 + All link-local IP addresses + + + + multicast + 224.0.0.0/4 ff00::/8 + All IP multicasting addresses + + + +
+ + Note that these settings might not be supported on some systems (for example if eBPF control group + support is not enabled in the underlying kernel or container manager). These settings will have no effect in + that case. If compatibility with such systems is desired it is hence recommended to not exclusively rely on + them for IP security. +
+
+ + + IPIngressFilterPath=BPF_FS_PROGRAMM_PATH + IPEgressFilterPath=BPF_FS_PROGRAMM_PATH + + + Add custom network traffic filters implemented as BPF programs, applying to all IP packets + sent and received over AF_INET and AF_INET6 sockets. + Takes an absolute path to a pinned BPF program in the BPF virtual filesystem (/sys/fs/bpf/). + + + The filters configured with this option are applied to all sockets created by processes + of this unit (or in the case of socket units, associated with it). The filters are loaded in addition + to filters any of the parent slice units this unit might be a member of as well as any + IPAddressAllow= and IPAddressDeny= filters in any of these units. + By default there are no filters specified. + + If these settings are used multiple times in the same unit all the specified programs are attached. If an + empty string is assigned to these settings the program list is reset and all previous specified programs ignored. + + Note that for socket-activated services, the IP filter programs configured on the socket unit apply to + all sockets associated with it directly, but not to any sockets created by the ultimately activated services + for it. Conversely, the IP filter programs configured for the service are not applied to any sockets passed into + the service via socket activation. Thus, it is usually a good idea, to replicate the IP filter programs on both + the socket and the service unit, however it often makes sense to maintain one configuration more open and the other + one more restricted, depending on the usecase. + + Note that these settings might not be supported on some systems (for example if eBPF control group + support is not enabled in the underlying kernel or container manager). These settings will fail the service in + that case. If compatibility with such systems is desired it is hence recommended to attach your filter manually + (requires Delegate=yes) instead of using this setting. + + + + + DeviceAllow= + + + Control access to specific device nodes by the executed processes. Takes two space-separated + strings: a device node specifier followed by a combination of r, + w, m to control reading, + writing, or creation of the specific device node(s) by the unit + (mknod), respectively. On cgroup-v1 this controls the + devices.allow control group attribute. For details about this control group + attribute, see devices.txt. On + cgroup-v2 this functionality is implemented using eBPF filtering. + + The device node specifier is either a path to a device node in the file system, starting with + /dev/, or a string starting with either char- or + block- followed by a device group name, as listed in + /proc/devices. The latter is useful to whitelist all current and future + devices belonging to a specific device group at once. The device group is matched according to + filename globbing rules, you may hence use the * and ? + wildcards. (Note that such globbing wildcards are not available for device node path + specifications!) In order to match device nodes by numeric major/minor, use device node paths in + the /dev/char/ and /dev/block/ directories. However, + matching devices by major/minor is generally not recommended as assignments are neither stable nor + portable between systems or different kernel versions. + + Examples: /dev/sda5 is a path to a device node, referring to an ATA or + SCSI block device. char-pts and char-alsa are specifiers for + all pseudo TTYs and all ALSA sound devices, respectively. char-cpu/* is a + specifier matching all CPU related device groups. + + Note that whitelists defined this way should only reference device groups which are + resolvable at the time the unit is started. Any device groups not resolvable then are not added to + the device whitelist. In order to work around this limitation, consider extending service units + with an ExecStartPre=/sbin/modprobe… line that loads the necessary + kernel module implementing the device group if missing. Example: … +[Service] +ExecStartPre=-/sbin/modprobe -abq loop +DeviceAllow=block-loop +DeviceAllow=/dev/loop-control +… + + + + + + DevicePolicy=auto|closed|strict + + + + Control the policy for allowing device access: + + + + + + means to only allow types of access that are + explicitly specified. + + + + + + + in addition, allows access to standard pseudo + devices including + /dev/null, + /dev/zero, + /dev/full, + /dev/random, and + /dev/urandom. + + + + + + + + + in addition, allows access to all devices if no + explicit DeviceAllow= is present. + This is the default. + + + + + + + + + Slice= + + + The name of the slice unit to place the unit + in. Defaults to system.slice for all + non-instantiated units of all unit types (except for slice + units themselves see below). Instance units are by default + placed in a subslice of system.slice + that is named after the template name. + + This option may be used to arrange systemd units in a + hierarchy of slices each of which might have resource + settings applied. + + For units of type slice, the only accepted value for + this setting is the parent slice. Since the name of a slice + unit implies the parent slice, it is hence redundant to ever + set this parameter directly for slice units. + + Special care should be taken when relying on the default slice assignment in templated service units + that have DefaultDependencies=no set, see + systemd.service5, section + "Default Dependencies" for details. + + + + + + Delegate= + + + Turns on delegation of further resource control partitioning to processes of the unit. Units where this + is enabled may create and manage their own private subhierarchy of control groups below the control group of + the unit itself. For unprivileged services (i.e. those using the User= setting) the unit's + control group will be made accessible to the relevant user. When enabled the service manager will refrain + from manipulating control groups or moving processes below the unit's control group, so that a clear concept + of ownership is established: the control group tree above the unit's control group (i.e. towards the root + control group) is owned and managed by the service manager of the host, while the control group tree below + the unit's control group is owned and managed by the unit itself. Takes either a boolean argument or a list + of control group controller names. If true, delegation is turned on, and all supported controllers are + enabled for the unit, making them available to the unit's processes for management. If false, delegation is + turned off entirely (and no additional controllers are enabled). If set to a list of controllers, delegation + is turned on, and the specified controllers are enabled for the unit. Note that additional controllers than + the ones specified might be made available as well, depending on configuration of the containing slice unit + or other units contained in it. Note that assigning the empty string will enable delegation, but reset the + list of controllers, all assignments prior to this will have no effect. Defaults to false. + + Note that controller delegation to less privileged code is only safe on the unified control group + hierarchy. Accordingly, access to the specified controllers will not be granted to unprivileged services on + the legacy hierarchy, even when requested. + + The following controller names may be specified: , , + , , , , + . Not all of these controllers are available on all kernels however, and some are + specific to the unified hierarchy while others are specific to the legacy hierarchy. Also note that the + kernel might support further controllers, which aren't covered here yet as delegation is either not supported + at all for them or not defined cleanly. + + For further details on the delegation model consult Control Group APIs and Delegation. + + + + + DisableControllers= + + + Disables controllers from being enabled for a unit's children. If a controller listed is already in use + in its subtree, the controller will be removed from the subtree. This can be used to avoid child units being + able to implicitly or explicitly enable a controller. Defaults to not disabling any controllers. + + It may not be possible to successfully disable a controller if the unit or any child of the unit in + question delegates controllers to its children, as any delegated subtree of the cgroup hierarchy is unmanaged + by systemd. + + Multiple controllers may be specified, separated by spaces. You may also pass + DisableControllers= multiple times, in which case each new instance adds another controller + to disable. Passing DisableControllers= by itself with no controller name present resets + the disabled controller list. + + Valid controllers are , , , + , , , and . + + +
+
+ + + Deprecated Options + + The following options are deprecated. Use the indicated superseding options instead: + + + + + CPUShares=weight + StartupCPUShares=weight + + + Assign the specified CPU time share weight to the processes executed. These options take an integer + value and control the cpu.shares control group attribute. The allowed range is 2 to + 262144. Defaults to 1024. For details about this control group attribute, see sched-design-CFS.txt. + The available CPU time is split up among all units within one slice relative to their CPU time share + weight. + + While StartupCPUShares= only applies to the startup phase of the system, + CPUShares= applies to normal runtime of the system, and if the former is not set also to + the startup phase. Using StartupCPUShares= allows prioritizing specific services at + boot-up differently than during normal runtime. + + Implies CPUAccounting=yes. + + These settings are deprecated. Use CPUWeight= and + StartupCPUWeight= instead. + + + + + MemoryLimit=bytes + + + Specify the limit on maximum memory usage of the executed processes. The limit specifies how much + process and kernel memory can be used by tasks in this unit. Takes a memory size in bytes. If the value is + suffixed with K, M, G or T, the specified memory size is parsed as Kilobytes, Megabytes, Gigabytes, or + Terabytes (with the base 1024), respectively. Alternatively, a percentage value may be specified, which is + taken relative to the installed physical memory on the system. If assigned the special value + infinity, no memory limit is applied. This controls the + memory.limit_in_bytes control group attribute. For details about this control group + attribute, see memory.txt. + + Implies MemoryAccounting=yes. + + This setting is deprecated. Use MemoryMax= instead. + + + + + BlockIOAccounting= + + + Turn on Block I/O accounting for this unit, if the legacy control group hierarchy is used on the + system. Takes a boolean argument. Note that turning on block I/O accounting for one unit will also implicitly + turn it on for all units contained in the same slice and all for its parent slices and the units contained + therein. The system default for this setting may be controlled with + DefaultBlockIOAccounting= in + systemd-system.conf5. + + This setting is deprecated. Use IOAccounting= instead. + + + + + BlockIOWeight=weight + StartupBlockIOWeight=weight + + Set the default overall block I/O weight for the executed processes, if the legacy control + group hierarchy is used on the system. Takes a single weight value (between 10 and 1000) to set the default + block I/O weight. This controls the blkio.weight control group attribute, which defaults to + 500. For details about this control group attribute, see blkio-controller.txt. + The available I/O bandwidth is split up among all units within one slice relative to their block I/O + weight. + + While StartupBlockIOWeight= only + applies to the startup phase of the system, + BlockIOWeight= applies to the later runtime + of the system, and if the former is not set also to the + startup phase. This allows prioritizing specific services at + boot-up differently than during runtime. + + Implies + BlockIOAccounting=yes. + + These settings are deprecated. Use IOWeight= and StartupIOWeight= + instead. + + + + + + BlockIODeviceWeight=device weight + + + Set the per-device overall block I/O weight for the executed processes, if the legacy control group + hierarchy is used on the system. Takes a space-separated pair of a file path and a weight value to specify + the device specific weight value, between 10 and 1000. (Example: "/dev/sda 500"). The file path may be + specified as path to a block device node or as any other file, in which case the backing block device of the + file system of the file is determined. This controls the blkio.weight_device control group + attribute, which defaults to 1000. Use this option multiple times to set weights for multiple devices. For + details about this control group attribute, see blkio-controller.txt. + + Implies + BlockIOAccounting=yes. + + This setting is deprecated. Use IODeviceWeight= instead. + + + + + BlockIOReadBandwidth=device bytes + BlockIOWriteBandwidth=device bytes + + + Set the per-device overall block I/O bandwidth limit for the executed processes, if the legacy control + group hierarchy is used on the system. Takes a space-separated pair of a file path and a bandwidth value (in + bytes per second) to specify the device specific bandwidth. The file path may be a path to a block device + node, or as any other file in which case the backing block device of the file system of the file is used. If + the bandwidth is suffixed with K, M, G, or T, the specified bandwidth is parsed as Kilobytes, Megabytes, + Gigabytes, or Terabytes, respectively, to the base of 1000. (Example: + "/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 5M"). This controls the + blkio.throttle.read_bps_device and blkio.throttle.write_bps_device + control group attributes. Use this option multiple times to set bandwidth limits for multiple devices. For + details about these control group attributes, see blkio-controller.txt. + + + Implies + BlockIOAccounting=yes. + + These settings are deprecated. Use IOReadBandwidthMax= and + IOWriteBandwidthMax= instead. + + + + + + + + See Also + + systemd1, + systemd-system.conf5, + systemd.unit5, + systemd.service5, + systemd.slice5, + systemd.scope5, + systemd.socket5, + systemd.mount5, + systemd.swap5, + systemd.exec5, + systemd.directives7, + systemd.special7, + The documentation for control groups and specific controllers in the Linux kernel: + cgroups.txt, + cpuacct.txt, + memory.txt, + blkio-controller.txt. + sched-bwc.txt. + + +
diff --git a/man/systemd.scope.xml b/man/systemd.scope.xml new file mode 100644 index 00000000..daf3554d --- /dev/null +++ b/man/systemd.scope.xml @@ -0,0 +1,117 @@ + + + + + + + systemd.scope + systemd + + + + systemd.scope + 5 + + + + systemd.scope + Scope unit configuration + + + + scope.scope + + + + Description + + Scope units are not configured via unit configuration files, + but are only created programmatically using the bus interfaces of + systemd. They are named similar to filenames. A unit whose name + ends in .scope refers to a scope unit. Scopes + units manage a set of system processes. Unlike service units, scope + units manage externally created processes, and do not fork off + processes on its own. + + The main purpose of scope units is grouping worker processes + of a system service for organization and for managing resources. + + systemd-run may + be used to easily launch a command in a new scope unit from the + command line. + + See the New + Control Group Interfaces for an introduction on how to make + use of scope units from programs. + + + + Automatic Dependencies + + + Implicit Dependencies + + Implicit dependencies may be added as result of + resource control parameters as documented in + systemd.resource-control5. + + + + Default Dependencies + + The following dependencies are added unless + DefaultDependencies=no is set: + + + Scope units will automatically have dependencies of + type Conflicts= and + Before= on + shutdown.target. These ensure + that scope units are removed prior to system + shutdown. Only scope units involved with early boot or + late system shutdown should disable + DefaultDependencies= option. + + + + + + Options + + Scope files may include a [Scope] + section, which carries information about the scope and the + units it contains. A number of options that may be used in + this section are shared with other unit types. These options are + documented in + systemd.kill5 + and + systemd.resource-control5. + The options specific to the [Scope] section + of scope units are the following: + + + + RuntimeMaxSec= + + Configures a maximum time for the scope to run. If this is used and the scope has been + active for longer than the specified time it is terminated and put into a failure state. Pass + infinity (the default) to configure no runtime limit. + + + + + + See Also + + systemd1, + systemd-run1, + systemd.unit5, + systemd.resource-control5, + systemd.service5, + systemd.directives7. + + + + diff --git a/man/systemd.service.xml b/man/systemd.service.xml new file mode 100644 index 00000000..e178724c --- /dev/null +++ b/man/systemd.service.xml @@ -0,0 +1,1524 @@ + + + + + + + systemd.service + systemd + + + + systemd.service + 5 + + + + systemd.service + Service unit configuration + + + + service.service + + + + Description + + A unit configuration file whose name ends in + .service encodes information about a process + controlled and supervised by systemd. + + This man page lists the configuration options specific to + this unit type. See + systemd.unit5 + for the common options of all unit configuration files. The common + configuration items are configured in the generic + [Unit] and [Install] + sections. The service specific configuration options are + configured in the [Service] section. + + Additional options are listed in + systemd.exec5, + which define the execution environment the commands are executed + in, and in + systemd.kill5, + which define the way the processes of the service are terminated, + and in + systemd.resource-control5, + which configure resource control settings for the processes of the + service. + + If a service is requested under a certain name but no unit + configuration file is found, systemd looks for a SysV init script + by the same name (with the .service suffix + removed) and dynamically creates a service unit from that script. + This is useful for compatibility with SysV. Note that this + compatibility is quite comprehensive but not 100%. For details + about the incompatibilities, see the Incompatibilities + with SysV document. + + The systemd-run1 + command allows creating .service and .scope units dynamically + and transiently from the command line. + + + + Service Templates + + It is possible for systemd services to take a single argument via the + service@argument.service + syntax. Such services are called "instantiated" services, while the unit definition without the + argument parameter is called a "template". An example could be a + dhcpcd@.service service template which takes a network interface as a + parameter to form an instantiated service. Within the service file, this parameter or "instance + name" can be accessed with %-specifiers. See + systemd.unit5 + for details. + + + + Automatic Dependencies + + + Implicit Dependencies + + The following dependencies are implicitly added: + + + Services with Type=dbus set automatically + acquire dependencies of type Requires= and + After= on + dbus.socket. + + Socket activated services are automatically ordered after + their activating .socket units via an + automatic After= dependency. + Services also pull in all .socket units + listed in Sockets= via automatic + Wants= and After= dependencies. + + + Additional implicit dependencies may be added as result of + execution and resource control parameters as documented in + systemd.exec5 + and + systemd.resource-control5. + + + + Default Dependencies + + The following dependencies are added unless DefaultDependencies=no is set: + + + Service units will have dependencies of type Requires= and + After= on sysinit.target, a dependency of type After= on + basic.target as well as dependencies of type Conflicts= and + Before= on shutdown.target. These ensure that normal service units pull in + basic system initialization, and are terminated cleanly prior to system shutdown. Only services involved with early + boot or late system shutdown should disable this option. + + Instanced service units (i.e. service units with an @ in their name) are assigned by + default a per-template slice unit (see + systemd.slice5), named after the + template unit, containing all instances of the specific template. This slice is normally stopped at shutdown, + together with all template instances. If that is not desired, set DefaultDependencies=no in the + template unit, and either define your own per-template slice unit file that also sets + DefaultDependencies=no, or set Slice=system.slice (or another suitable slice) + in the template unit. Also see + systemd.resource-control5. + + + + + + + Options + + Service files must include a [Service] + section, which carries information about the service and the + process it supervises. A number of options that may be used in + this section are shared with other unit types. These options are + documented in + systemd.exec5, + systemd.kill5 + and + systemd.resource-control5. + The options specific to the [Service] section + of service units are the following: + + + + Type= + + + Configures the process start-up type for this service unit. One of , + , , , , + or : + + + If set to (the default if ExecStart= is + specified but neither Type= nor BusName= are), the service manager + will consider the unit started immediately after the main service process has been forked off. It is + expected that the process configured with ExecStart= is the main process of the + service. In this mode, if the process offers functionality to other processes on the system, its + communication channels should be installed before the service is started up (e.g. sockets set up by + systemd, via socket activation), as the service manager will immediately proceed starting follow-up units, + right after creating the main service process, and before executing the service's binary. Note that this + means systemctl start command lines for services will report + success even if the service's binary cannot be invoked successfully (for example because the selected + User= doesn't exist, or the service binary is missing). + + The type is similar to , but the service + manager will consider the unit started immediately after the main service binary has been executed. The service + manager will delay starting of follow-up units until that point. (Or in other words: + proceeds with further jobs right after fork() returns, while + will not proceed before both fork() and + execve() in the service process succeeded.) Note that this means systemctl + start command lines for services will report failure when the service's + binary cannot be invoked successfully (for example because the selected User= doesn't + exist, or the service binary is missing). + + If set to , it is expected that the process configured with + ExecStart= will call fork() as part of its start-up. The parent + process is expected to exit when start-up is complete and all communication channels are set up. The child + continues to run as the main service process, and the service manager will consider the unit started when + the parent process exits. This is the behavior of traditional UNIX services. If this setting is used, it is + recommended to also use the PIDFile= option, so that systemd can reliably identify the + main process of the service. systemd will proceed with starting follow-up units as soon as the parent + process exits. + + Behavior of is similar to ; + however, the service manager will consider the unit up after the main process exits. It will then + start follow-up units. RemainAfterExit= is particularly useful for this type + of service. Type= is the implied default if neither + Type= nor ExecStart= are specified. Note that if this + option is used without RemainAfterExit= the service will never enter + active unit state, but directly transition from activating + to deactivating or dead since no process is configured that + shall run continously. In particular this means that after a service of this type ran (and which + has RemainAfterExit= not set) it will not show up as started afterwards, but + as dead. + + Behavior of is similar to ; however, it is + expected that the service acquires a name on the D-Bus bus, as configured by + BusName=. systemd will proceed with starting follow-up units after the D-Bus bus name + has been acquired. Service units with this option configured implicitly gain dependencies on the + dbus.socket unit. This type is the default if BusName= is + specified. + + Behavior of is similar to ; however, it is + expected that the service sends a notification message via + sd_notify3 or an + equivalent call when it has finished starting up. systemd will proceed with starting follow-up units after + this notification message has been sent. If this option is used, NotifyAccess= (see + below) should be set to open access to the notification socket provided by systemd. If + NotifyAccess= is missing or set to , it will be forcibly set to + . Note that currently Type= will not work if + used in combination with PrivateNetwork=. + + Behavior of is very similar to ; however, + actual execution of the service program is delayed until all active jobs are dispatched. This may be used + to avoid interleaving of output of shell services with the status output on the console. Note that this + type is useful only to improve console output, it is not useful as a general unit ordering tool, and the + effect of this service type is subject to a 5s timeout, after which the service program is invoked + anyway. + + + It is generally recommended to use Type= for long-running + services whenever possible, as it is the simplest and fastest option. However, as this service type won't + propagate service start-up failures and doesn't allow ordering of other units against completion of + initialization of the service (which for example is useful if clients need to connect to the service through + some form of IPC, and the IPC channel is only established by the service itself — in contrast to doing this + ahead of time through socket or bus activation or similar), it might not be sufficient for many cases. If so, + or (the latter only in case the service provides a D-Bus + interface) are the preferred options as they allow service program code to precisely schedule when to + consider the service started up successfully and when to proceed with follow-up units. The + service type requires explicit support in the service codebase (as + sd_notify() or an equivalent API needs to be invoked by the service at the appropriate + time) — if it's not supported, then is an alternative: it supports the traditional + UNIX service start-up protocol. Finally, might be an option for cases where it is + enough to ensure the service binary is invoked, and where the service binary itself executes no or little + initialization on its own (and its initialization is unlikely to fail). Note that using any type other than + possibly delays the boot process, as the service manager needs to wait for service + initialization to complete. It is hence recommended not to needlessly use any types other than + . (Also note it is generally not recommended to use or + for long-running services.) + + + + + RemainAfterExit= + + Takes a boolean value that specifies whether + the service shall be considered active even when all its + processes exited. Defaults to . + + + + + GuessMainPID= + + Takes a boolean value that specifies whether + systemd should try to guess the main PID of a service if it + cannot be determined reliably. This option is ignored unless + is set and + is unset because for the other types + or with an explicitly configured PID file, the main PID is + always known. The guessing algorithm might come to incorrect + conclusions if a daemon consists of more than one process. If + the main PID cannot be determined, failure detection and + automatic restarting of a service will not work reliably. + Defaults to . + + + + + PIDFile= + + Takes a path referring to the PID file of the service. Usage of this option is recommended for + services where Type= is set to . The path specified typically points + to a file below /run/. If a relative path is specified it is hence prefixed with + /run/. The service manager will read the PID of the main process of the service from this + file after start-up of the service. The service manager will not write to the file configured here, although it + will remove the file after the service has shut down if it still exists. The PID file does not need to be owned + by a privileged user, but if it is owned by an unprivileged user additional safety restrictions are enforced: + the file may not be a symlink to a file owned by a different user (neither directly nor indirectly), and the + PID file must refer to a process already belonging to the service. + + + + BusName= + + Takes a D-Bus bus name that this service is + reachable as. This option is mandatory for services where + Type= is set to + . + + + + + ExecStart= + Commands with their arguments that are + executed when this service is started. The value is split into + zero or more command lines according to the rules described + below (see section "Command Lines" below). + + + Unless Type= is , exactly one command must be given. When + Type=oneshot is used, zero or more commands may be specified. Commands may be specified by + providing multiple command lines in the same directive, or alternatively, this directive may be specified more + than once with the same effect. If the empty string is assigned to this option, the list of commands to start + is reset, prior assignments of this option will have no effect. If no ExecStart= is + specified, then the service must have RemainAfterExit=yes and at least one + ExecStop= line set. (Services lacking both ExecStart= and + ExecStop= are not valid.) + + For each of the specified commands, the first argument must be either an absolute path to an executable + or a simple file name without any slashes. Optionally, this filename may be prefixed with a number of special + characters: + + + Special executable prefixes + + + + + + + + Prefix + Effect + + + + + @ + If the executable path is prefixed with @, the second specified token will be passed as argv[0] to the executed process (instead of the actual filename), followed by the further arguments specified. + + + + - + If the executable path is prefixed with -, an exit code of the command normally considered a failure (i.e. non-zero exit status or abnormal exit due to signal) is recorded, but has no further effect and is considered equivalent to success. + + + + : + If the executable path is prefixed with :, environment variable substitution (as described by the "Command Lines" section below) is not applied. + + + + + + If the executable path is prefixed with + then the process is executed with full privileges. In this mode privilege restrictions configured with User=, Group=, CapabilityBoundingSet= or the various file system namespacing options (such as PrivateDevices=, PrivateTmp=) are not applied to the invoked command line (but still affect any other ExecStart=, ExecStop=, … lines). + + + + ! + + Similar to the + character discussed above this permits invoking command lines with elevated privileges. However, unlike + the ! character exclusively alters the effect of User=, Group= and SupplementaryGroups=, i.e. only the stanzas that affect user and group credentials. Note that this setting may be combined with DynamicUser=, in which case a dynamic user/group pair is allocated before the command is invoked, but credential changing is left to the executed process itself. + + + + !! + + This prefix is very similar to !, however it only has an effect on systems lacking support for ambient process capabilities, i.e. without support for AmbientCapabilities=. It's intended to be used for unit files that take benefit of ambient capabilities to run processes with minimal privileges wherever possible while remaining compatible with systems that lack ambient capabilities support. Note that when !! is used, and a system lacking ambient capability support is detected any configured SystemCallFilter= and CapabilityBoundingSet= stanzas are implicitly modified, in order to permit spawned processes to drop credentials and capabilities themselves, even if this is configured to not be allowed. Moreover, if this prefix is used and a system lacking ambient capability support is detected AmbientCapabilities= will be skipped and not be applied. On systems supporting ambient capabilities, !! has no effect and is redundant. + + + +
+ + @, -, :, and one of + +/!/!! may be used together and they can appear in any + order. However, only one of +, !, !! may be used at a + time. Note that these prefixes are also supported for the other command line settings, + i.e. ExecStartPre=, ExecStartPost=, ExecReload=, + ExecStop= and ExecStopPost=. + + If more than one command is specified, the commands are + invoked sequentially in the order they appear in the unit + file. If one of the commands fails (and is not prefixed with + -), other lines are not executed, and the + unit is considered failed. + + Unless Type=forking is set, the + process started via this command line will be considered the + main process of the daemon. +
+
+ + + ExecStartPre= + ExecStartPost= + Additional commands that are executed before + or after the command in ExecStart=, + respectively. Syntax is the same as for + ExecStart=, except that multiple command + lines are allowed and the commands are executed one after the + other, serially. + + If any of those commands (not prefixed with + -) fail, the rest are not executed and the + unit is considered failed. + + ExecStart= commands are only run after + all ExecStartPre= commands that were not prefixed + with a - exit successfully. + + ExecStartPost= commands are only run after the commands specified in + ExecStart= have been invoked successfully, as determined by Type= + (i.e. the process has been started for Type=simple or Type=idle, the last + ExecStart= process exited successfully for Type=oneshot, the initial + process exited successfully for Type=forking, READY=1 is sent for + Type=notify, or the BusName= has been taken for + Type=dbus). + + Note that ExecStartPre= may not be + used to start long-running processes. All processes forked + off by processes invoked via ExecStartPre= will + be killed before the next service process is run. + + Note that if any of the commands specified in ExecStartPre=, + ExecStart=, or ExecStartPost= fail (and are not prefixed with + -, see above) or time out before the service is fully up, execution continues with commands + specified in ExecStopPost=, the commands in ExecStop= are skipped. + + + + + ExecCondition= + Optional commands that are executed before the command(s) in ExecStartPre=. + Syntax is the same as for ExecStart=, except that multiple command lines are allowed and the + commands are executed one after the other, serially. + + The behavior is like an ExecStartPre= and condition check hybrid: when an + ExecCondition= command exits with exit code 1 through 254 (inclusive), the remaining + commands are skipped and the unit is not marked as failed. However, if an + ExecCondition= command exits with 255 or abnormally (e.g. timeout, killed by a + signal, etc.), the unit will be considered failed (and remaining commands will be skipped). Exit code of 0 or + those matching SuccessExitStatus= will continue execution to the next command(s). + + The same recommendations about not running long-running processes in ExecStartPre= + also applies to ExecCondition=. ExecCondition= will also run the commands + in ExecStopPost=, as part of stopping the service, in the case of any non-zero or abnormal + exits, like the ones described above. + + + + + ExecReload= + Commands to execute to trigger a configuration + reload in the service. This argument takes multiple command + lines, following the same scheme as described for + ExecStart= above. Use of this setting is + optional. Specifier and environment variable substitution is + supported here following the same scheme as for + ExecStart=. + + One additional, special environment variable is set: if + known, $MAINPID is set to the main process + of the daemon, and may be used for command lines like the + following: + + /bin/kill -HUP $MAINPID + + Note however that reloading a daemon by sending a signal + (as with the example line above) is usually not a good choice, + because this is an asynchronous operation and hence not + suitable to order reloads of multiple services against each + other. It is strongly recommended to set + ExecReload= to a command that not only + triggers a configuration reload of the daemon, but also + synchronously waits for it to complete. + + + + + ExecStop= + Commands to execute to stop the service started via + ExecStart=. This argument takes multiple command lines, following the same scheme + as described for ExecStart= above. Use of this setting is optional. After the + commands configured in this option are run, it is implied that the service is stopped, and any + processes remaining for it are terminated according to the KillMode= setting (see + systemd.kill5). + If this option is not specified, the process is terminated by sending the signal specified in + KillSignal= or RestartKillSignal= when service stop is + requested. Specifier and environment variable substitution is supported (including + $MAINPID, see above). + + Note that it is usually not sufficient to specify a command for this setting that only asks the + service to terminate (for example, by sending some form of termination signal to it), but does not + wait for it to do so. Since the remaining processes of the services are killed according to + KillMode= and KillSignal= or + RestartKillSignal= as described above immediately after the command exited, this + may not result in a clean stop. The specified command should hence be a synchronous operation, not an + asynchronous one. + + Note that the commands specified in ExecStop= are only executed when the service + started successfully first. They are not invoked if the service was never started at all, or in case its + start-up failed, for example because any of the commands specified in ExecStart=, + ExecStartPre= or ExecStartPost= failed (and weren't prefixed with + -, see above) or timed out. Use ExecStopPost= to invoke commands when a + service failed to start up correctly and is shut down again. Also note that the stop operation is always + performed if the service started successfully, even if the processes in the service terminated on their + own or were killed. The stop commands must be prepared to deal with that case. $MAINPID + will be unset if systemd knows that the main process exited by the time the stop commands are called. + + Service restart requests are implemented as stop operations followed by start operations. This + means that ExecStop= and ExecStopPost= are executed during a + service restart operation. + + It is recommended to use this setting for commands that communicate with the service requesting + clean termination. For post-mortem clean-up steps use ExecStopPost= instead. + + + + + ExecStopPost= + Additional commands that are executed after the service is stopped. This includes cases where + the commands configured in ExecStop= were used, where the service does not have any + ExecStop= defined, or where the service exited unexpectedly. This argument takes multiple + command lines, following the same scheme as described for ExecStart=. Use of these settings + is optional. Specifier and environment variable substitution is supported. Note that – unlike + ExecStop= – commands specified with this setting are invoked when a service failed to start + up correctly and is shut down again. + + It is recommended to use this setting for clean-up operations that shall be executed even when the + service failed to start up correctly. Commands configured with this setting need to be able to operate even if + the service failed starting up half-way and left incompletely initialized data around. As the service's + processes have been terminated already when the commands specified with this setting are executed they should + not attempt to communicate with them. + + Note that all commands that are configured with this setting are invoked with the result code of the + service, as well as the main process' exit code and status, set in the $SERVICE_RESULT, + $EXIT_CODE and $EXIT_STATUS environment variables, see + systemd.exec5 for + details. + + + + RestartSec= + Configures the time to sleep before restarting + a service (as configured with Restart=). + Takes a unit-less value in seconds, or a time span value such + as "5min 20s". Defaults to 100ms. + + + + TimeoutStartSec= + Configures the time to wait for start-up. If a + daemon service does not signal start-up completion within the + configured time, the service will be considered failed and + will be shut down again. Takes a unit-less value in seconds, + or a time span value such as "5min 20s". Pass + infinity to disable the timeout logic. Defaults to + DefaultTimeoutStartSec= from the manager + configuration file, except when + Type=oneshot is used, in which case the + timeout is disabled by default (see + systemd-system.conf5). + + + If a service of Type=notify sends EXTEND_TIMEOUT_USEC=…, this may cause + the start time to be extended beyond TimeoutStartSec=. The first receipt of this message + must occur before TimeoutStartSec= is exceeded, and once the start time has exended beyond + TimeoutStartSec=, the service manager will allow the service to continue to start, provided + the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified until the service + startup status is finished by READY=1. (see + sd_notify3). + + + + + TimeoutStopSec= + This option serves two purposes. First, it configures the time to wait for each + ExecStop= command. If any of them times out, subsequent ExecStop= commands + are skipped and the service will be terminated by SIGTERM. If no ExecStop= + commands are specified, the service gets the SIGTERM immediately. Second, it configures the time + to wait for the service itself to stop. If it doesn't terminate in the specified time, it will be forcibly terminated + by SIGKILL (see KillMode= in + systemd.kill5). + Takes a unit-less value in seconds, or a time span value such + as "5min 20s". Pass infinity to disable the + timeout logic. Defaults to + DefaultTimeoutStopSec= from the manager + configuration file (see + systemd-system.conf5). + + + If a service of Type=notify sends EXTEND_TIMEOUT_USEC=…, this may cause + the stop time to be extended beyond TimeoutStopSec=. The first receipt of this message + must occur before TimeoutStopSec= is exceeded, and once the stop time has exended beyond + TimeoutStopSec=, the service manager will allow the service to continue to stop, provided + the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified, or terminates itself + (see sd_notify3). + + + + + TimeoutAbortSec= + This option configures the time to wait for the service to terminate when it was aborted due to a + watchdog timeout (see WatchdogSec=). If the service has a short TimeoutStopSec= + this option can be used to give the system more time to write a core dump of the service. Upon expiration the service + will be forcibly terminated by SIGKILL (see KillMode= in + systemd.kill5). The core file will + be truncated in this case. Use TimeoutAbortSec= to set a sensible timeout for the core dumping per + service that is large enough to write all expected data while also being short enough to handle the service failure + in due time. + + + Takes a unit-less value in seconds, or a time span value such as "5min 20s". Pass an empty value to skip + the dedicated watchdog abort timeout handling and fall back TimeoutStopSec=. Pass + infinity to disable the timeout logic. Defaults to DefaultTimeoutAbortSec= from + the manager configuration file (see + systemd-system.conf5). + + + If a service of Type=notify handles SIGABRT itself (instead of relying + on the kernel to write a core dump) it can send EXTEND_TIMEOUT_USEC=… to + extended the abort time beyond TimeoutAbortSec=. The first receipt of this message + must occur before TimeoutAbortSec= is exceeded, and once the abort time has exended beyond + TimeoutAbortSec=, the service manager will allow the service to continue to abort, provided + the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified, or terminates itself + (see sd_notify3). + + + + + TimeoutSec= + A shorthand for configuring both + TimeoutStartSec= and + TimeoutStopSec= to the specified value. + + + + + RuntimeMaxSec= + + Configures a maximum time for the service to run. If this is used and the service has been + active for longer than the specified time it is terminated and put into a failure state. Note that this setting + does not have any effect on Type=oneshot services, as they terminate immediately after + activation completed. Pass infinity (the default) to configure no runtime + limit. + + If a service of Type=notify sends EXTEND_TIMEOUT_USEC=…, this may cause + the runtime to be extended beyond RuntimeMaxSec=. The first receipt of this message + must occur before RuntimeMaxSec= is exceeded, and once the runtime has exended beyond + RuntimeMaxSec=, the service manager will allow the service to continue to run, provided + the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified until the service + shutdown is achieved by STOPPING=1 (or termination). (see + sd_notify3). + + + + + WatchdogSec= + Configures the watchdog timeout for a service. + The watchdog is activated when the start-up is completed. The + service must call + sd_notify3 + regularly with WATCHDOG=1 (i.e. the + "keep-alive ping"). If the time between two such calls is + larger than the configured time, then the service is placed in + a failed state and it will be terminated with + SIGABRT (or the signal specified by + WatchdogSignal=). By setting + Restart= to , + , or + , the service will be automatically + restarted. The time configured here will be passed to the + executed service process in the + WATCHDOG_USEC= environment variable. This + allows daemons to automatically enable the keep-alive pinging + logic if watchdog support is enabled for the service. If this + option is used, NotifyAccess= (see below) + should be set to open access to the notification socket + provided by systemd. If NotifyAccess= is + not set, it will be implicitly set to . + Defaults to 0, which disables this feature. The service can + check whether the service manager expects watchdog keep-alive + notifications. See + sd_watchdog_enabled3 + for details. + sd_event_set_watchdog3 + may be used to enable automatic watchdog notification support. + + + + + Restart= + Configures whether the service shall be + restarted when the service process exits, is killed, or a + timeout is reached. The service process may be the main + service process, but it may also be one of the processes + specified with ExecStartPre=, + ExecStartPost=, + ExecStop=, + ExecStopPost=, or + ExecReload=. When the death of the process + is a result of systemd operation (e.g. service stop or + restart), the service will not be restarted. Timeouts include + missing the watchdog "keep-alive ping" deadline and a service + start, reload, and stop operation timeouts. + + Takes one of + , + , + , + , + , + , or + . + If set to (the default), the service will + not be restarted. If set to , it + will be restarted only when the service process exits cleanly. + In this context, a clean exit means an exit code of 0, or one + of the signals + SIGHUP, + SIGINT, + SIGTERM or + SIGPIPE, and + additionally, exit statuses and signals specified in + SuccessExitStatus=. If set to + , the service will be restarted + when the process exits with a non-zero exit code, is + terminated by a signal (including on core dump, but excluding + the aforementioned four signals), when an operation (such as + service reload) times out, and when the configured watchdog + timeout is triggered. If set to , + the service will be restarted when the process is terminated + by a signal (including on core dump, excluding the + aforementioned four signals), when an operation times out, or + when the watchdog timeout is triggered. If set to + , the service will be restarted only + if the service process exits due to an uncaught signal not + specified as a clean exit status. If set to + , the service will be restarted + only if the watchdog timeout for the service expires. If set + to , the service will be restarted + regardless of whether it exited cleanly or not, got terminated + abnormally by a signal, or hit a timeout. + + + Exit causes and the effect of the <varname>Restart=</varname> settings on them + + + + + + + Restart settings/Exit causes + + + + + + + + + + + + Clean exit code or signal + + X + X + + + + + + + Unclean exit code + + X + + X + + + + + + Unclean signal + + X + + X + X + X + + + + Timeout + + X + + X + X + + + + + Watchdog + + X + + X + X + + X + + + +
+ + As exceptions to the setting above, the service will not + be restarted if the exit code or signal is specified in + RestartPreventExitStatus= (see below) or + the service is stopped with systemctl stop + or an equivalent operation. Also, the services will always be + restarted if the exit code or signal is specified in + RestartForceExitStatus= (see below). + + Note that service restart is subject to unit start rate + limiting configured with StartLimitIntervalSec= + and StartLimitBurst=, see + systemd.unit5 + for details. A restarted service enters the failed state only + after the start limits are reached. + + Setting this to is the + recommended choice for long-running services, in order to + increase reliability by attempting automatic recovery from + errors. For services that shall be able to terminate on their + own choice (and avoid immediate restarting), + is an alternative choice. +
+
+ + + SuccessExitStatus= + Takes a list of exit status definitions that, when returned by the main service + process, will be considered successful termination, in addition to the normal successful exit code 0 + and the signals SIGHUP, SIGINT, + SIGTERM, and SIGPIPE. Exit status definitions can be + numeric exit codes, termination code names, or termination signal names, separated by spaces. See the + Process Exit Codes section in + systemd.exec5 for + a list of termination codes names (for this setting only the part without the + EXIT_ or EX_ prefix should be used). See + signal7 for + a list of signal names. + + This option may appear more than once, in which case the + list of successful exit statuses is merged. If the empty + string is assigned to this option, the list is reset, all + prior assignments of this option will have no + effect. + + + A service with with the <varname>SuccessExitStatus=</varname> setting + + SuccessExitStatus=TEMPFAIL 250 SIGUSR1 + + Exit codes 75 (TEMPFAIL), 250, and the termination signal + SIGKILL are considered clean service terminations. + + + Note: systemd-analyze exit-codes may be used to list exit + codes and translate between numerical code values and names. + + + + RestartPreventExitStatus= + + Takes a list of exit status definitions that, when returned by the main service + process, will prevent automatic service restarts, regardless of the restart setting configured with + Restart=. Exit status definitions can either be numeric exit codes or termination + signal names, and are separated by spaces. Defaults to the empty list, so that, by default, no exit + status is excluded from the configured restart logic. For example: + + RestartPreventExitStatus=1 6 SIGABRT + + ensures that exit codes 1 and 6 and the termination signal SIGABRT will not + result in automatic service restarting. This option may appear more than once, in which case the list + of restart-preventing statuses is merged. If the empty string is assigned to this option, the list is + reset and all prior assignments of this option will have no effect. + + Note that this setting has no effect on processes configured via + ExecStartPre=, ExecStartPost=, ExecStop=, + ExecStopPost= or ExecReload=, but only on the main service + process, i.e. either the one invoked by ExecStart= or (depending on + Type=, PIDFile=, …) the otherwise configured main + process. + + + + RestartForceExitStatus= + Takes a list of exit status definitions that, + when returned by the main service process, will force automatic + service restarts, regardless of the restart setting configured + with Restart=. The argument format is + similar to + RestartPreventExitStatus=. + + + + RootDirectoryStartOnly= + Takes a boolean argument. If true, the root + directory, as configured with the + RootDirectory= option (see + systemd.exec5 + for more information), is only applied to the process started + with ExecStart=, and not to the various + other ExecStartPre=, + ExecStartPost=, + ExecReload=, ExecStop=, + and ExecStopPost= commands. If false, the + setting is applied to all configured commands the same way. + Defaults to false. + + + + NonBlocking= + Set the O_NONBLOCK flag for all file descriptors passed via socket-based + activation. If true, all file descriptors >= 3 (i.e. all except stdin, stdout, stderr), excluding those passed + in via the file descriptor storage logic (see FileDescriptorStoreMax= for details), will + have the O_NONBLOCK flag set and hence are in non-blocking mode. This option is only + useful in conjunction with a socket unit, as described in + systemd.socket5 and has no + effect on file descriptors which were previously saved in the file-descriptor store for example. Defaults to + false. + + + + NotifyAccess= + Controls access to the service status notification socket, as accessible via the + sd_notify3 call. Takes one + of (the default), , or + . If , no daemon status updates are accepted from the service + processes, all status update messages are ignored. If , only service updates sent from the + main process of the service are accepted. If , only service updates sent from any of the + main or control processes originating from one of the Exec*= commands are accepted. If + , all services updates from all members of the service's control group are accepted. This + option should be set to open access to the notification socket when using Type=notify or + WatchdogSec= (see above). If those options are used but NotifyAccess= is + not configured, it will be implicitly set to . + + Note that sd_notify() notifications may be attributed to units correctly only if + either the sending process is still around at the time PID 1 processes the message, or if the sending process + is explicitly runtime-tracked by the service manager. The latter is the case if the service manager originally + forked off the process, i.e. on all processes that match or + . Conversely, if an auxiliary process of the unit sends an + sd_notify() message and immediately exits, the service manager might not be able to + properly attribute the message to the unit, and thus will ignore it, even if + NotifyAccess= is set for it. + + + + Sockets= + Specifies the name of the socket units this + service shall inherit socket file descriptors from when the + service is started. Normally, it should not be necessary to use + this setting, as all socket file descriptors whose unit shares + the same name as the service (subject to the different unit + name suffix of course) are passed to the spawned + process. + + Note that the same socket file descriptors may be passed + to multiple processes simultaneously. Also note that a + different service may be activated on incoming socket traffic + than the one which is ultimately configured to inherit the + socket file descriptors. Or, in other words: the + Service= setting of + .socket units does not have to match the + inverse of the Sockets= setting of the + .service it refers to. + + This option may appear more than once, in which case the list of socket units is merged. Note + that once set, clearing the list of sockets again (for example, by assigning the empty string to this + option) is not supported. + + + + FileDescriptorStoreMax= + Configure how many file descriptors may be stored in the service manager for the service using + sd_pid_notify_with_fds3's + FDSTORE=1 messages. This is useful for implementing services that can restart after an + explicit request or a crash without losing state. Any open sockets and other file descriptors which should not + be closed during the restart may be stored this way. Application state can either be serialized to a file in + /run, or better, stored in a + memfd_create2 memory file + descriptor. Defaults to 0, i.e. no file descriptors may be stored in the service manager. All file descriptors + passed to the service manager from a specific service are passed back to the service's main process on the next + service restart. Any file descriptors passed to the service manager are automatically closed when + POLLHUP or POLLERR is seen on them, or when the service is fully + stopped and no job is queued or being executed for it. If this option is used, NotifyAccess= + (see above) should be set to open access to the notification socket provided by systemd. If + NotifyAccess= is not set, it will be implicitly set to + . + + + + USBFunctionDescriptors= + Configure the location of a file containing + USB + FunctionFS descriptors, for implementation of USB + gadget functions. This is used only in conjunction with a + socket unit with ListenUSBFunction= + configured. The contents of this file are written to the + ep0 file after it is + opened. + + + + USBFunctionStrings= + Configure the location of a file containing + USB FunctionFS strings. Behavior is similar to + USBFunctionDescriptors= + above. + + + + OOMPolicy= + + Configure the Out-Of-Memory (OOM) killer policy. On Linux, when memory becomes scarce + the kernel might decide to kill a running process in order to free up memory and reduce memory + pressure. This setting takes one of continue, stop or + kill. If set to continue and a process of the service is + killed by the kernel's OOM killer this is logged but the service continues running. If set to + stop the event is logged but the service is terminated cleanly by the service + manager. If set to kill and one of the service's processes is killed by the OOM + killer the kernel is instructed to kill all remaining processes of the service, too. Defaults to the + setting DefaultOOMPolicy= in + system.conf5 is + set to, except for services where Delegate= is turned on, where it defaults to + continue. + + Use the OOMScoreAdjust= setting to configure whether processes of the unit + shall be considered preferred or less preferred candidates for process termination by the Linux OOM + killer logic. See + systemd.exec5 for + details. + + +
+ + Check + systemd.exec5 + and + systemd.kill5 + for more settings. + +
+ + + Command lines + + This section describes command line parsing and + variable and specifier substitutions for + ExecStart=, + ExecStartPre=, + ExecStartPost=, + ExecReload=, + ExecStop=, and + ExecStopPost= options. + + Multiple command lines may be concatenated in a single + directive by separating them with semicolons (these semicolons + must be passed as separate words). Lone semicolons may be escaped + as \;. + + Each command line is split on whitespace, with the first item being the command to + execute, and the subsequent items being the arguments. Double quotes ("…") and single quotes + ('…') may be used to wrap a whole item (the opening quote may appear only at the beginning or + after whitespace that is not quoted, and the closing quote must be followed by whitespace or the + end of line), in which case everything until the next matching quote becomes part of the same + argument. Quotes themselves are removed. C-style escapes are also supported. The table below + contains the list of known escape patterns. Only escape patterns which match the syntax in the + table are allowed; other patterns may be added in the future and unknown patterns will result in + a warning. In particular, any backslashes should be doubled. Finally, a trailing backslash + (\) may be used to merge lines. + + This syntax is inspired by shell syntax, but only the meta-characters and expansions + described in the following paragraphs are understood, and the expansion of variables is + different. Specifically, redirection using + <, + <<, + >, and + >>, pipes using + |, running programs in the background using + &, and other elements of shell + syntax are not supported. + + The command to execute may contain spaces, but control characters are not allowed. + + The command line accepts % specifiers as described in + systemd.unit5. + + Basic environment variable substitution is supported. Use + ${FOO} as part of a word, or as a word of its + own, on the command line, in which case it will be replaced by the + value of the environment variable including all whitespace it + contains, resulting in a single argument. Use + $FOO as a separate word on the command line, in + which case it will be replaced by the value of the environment + variable split at whitespace, resulting in zero or more arguments. + For this type of expansion, quotes are respected when splitting + into words, and afterwards removed. + + If the command is not a full (absolute) path, it will be resolved to a full path using a + fixed search path determinted at compilation time. Searched directories include + /usr/local/bin/, /usr/bin/, /bin/ + on systems using split /usr/bin/ and /bin/ + directories, and their sbin/ counterparts on systems using split + bin/ and sbin/. It is thus safe to use just the + executable name in case of executables located in any of the "standard" directories, and an + absolute path must be used in other cases. Using an absolute path is recommended to avoid + ambiguity. Hint: this search path may be queried using + systemd-path search-binaries-default. + + Example: + + Environment="ONE=one" 'TWO=two two' +ExecStart=echo $ONE $TWO ${TWO} + + This will execute /bin/echo with four + arguments: one, two, + two, and two two. + + Example: + Environment=ONE='one' "TWO='two two' too" THREE= +ExecStart=/bin/echo ${ONE} ${TWO} ${THREE} +ExecStart=/bin/echo $ONE $TWO $THREE + This results in /bin/echo being + called twice, the first time with arguments + 'one', + 'two two' too, , + and the second time with arguments + one, two two, + too. + + + To pass a literal dollar sign, use $$. + Variables whose value is not known at expansion time are treated + as empty strings. Note that the first argument (i.e. the program + to execute) may not be a variable. + + Variables to be used in this fashion may be defined through + Environment= and + EnvironmentFile=. In addition, variables listed + in the section "Environment variables in spawned processes" in + systemd.exec5, + which are considered "static configuration", may be used (this + includes e.g. $USER, but not + $TERM). + + Note that shell command lines are not directly supported. If + shell command lines are to be used, they need to be passed + explicitly to a shell implementation of some kind. Example: + ExecStart=sh -c 'dmesg | tac' + + Example: + + ExecStart=echo one ; echo "two two" + + This will execute echo two times, + each time with one argument: one and + two two, respectively. Because two commands are + specified, Type=oneshot must be used. + + Example: + + ExecStart=echo / >/dev/null & \; \ +ls + + This will execute echo + with five arguments: /, + >/dev/null, + &, ;, and + ls. + + + C escapes supported in command lines and environment variables + + + + + + Literal + Actual value + + + + + \a + bell + + + \b + backspace + + + \f + form feed + + + \n + newline + + + \r + carriage return + + + \t + tab + + + \v + vertical tab + + + \\ + backslash + + + \" + double quotation mark + + + \' + single quotation mark + + + \s + space + + + \xxx + character number xx in hexadecimal encoding + + + \nnn + character number nnn in octal encoding + + + +
+
+ + + Examples + + + Simple service + + The following unit file creates a service that will + execute /usr/sbin/foo-daemon. Since no + Type= is specified, the default + Type= will be assumed. + systemd will assume the unit to be started immediately after the + program has begun executing. + + [Unit] +Description=Foo + +[Service] +ExecStart=/usr/sbin/foo-daemon + +[Install] +WantedBy=multi-user.target + + Note that systemd assumes here that the process started by + systemd will continue running until the service terminates. If + the program daemonizes itself (i.e. forks), please use + Type= instead. + + Since no ExecStop= was specified, + systemd will send SIGTERM to all processes started from this + service, and after a timeout also SIGKILL. This behavior can be + modified, see + systemd.kill5 + for details. + + Note that this unit type does not include any type of + notification when a service has completed initialization. For + this, you should use other unit types, such as + Type= if the service + understands systemd's notification protocol, + Type= if the service + can background itself or + Type= if the unit + acquires a DBus name once initialization is complete. See + below. + + + + Oneshot service + + Sometimes, units should just execute an action without + keeping active processes, such as a filesystem check or a + cleanup action on boot. For this, + Type= exists. Units + of this type will wait until the process specified terminates + and then fall back to being inactive. The following unit will + perform a cleanup action: + + [Unit] +Description=Cleanup old Foo data + +[Service] +Type=oneshot +ExecStart=/usr/sbin/foo-cleanup + +[Install] +WantedBy=multi-user.target + + Note that systemd will consider the unit to be in the + state "starting" until the program has terminated, so ordered + dependencies will wait for the program to finish before starting + themselves. The unit will revert to the "inactive" state after + the execution is done, never reaching the "active" state. That + means another request to start the unit will perform the action + again. + + Type= are the + only service units that may have more than one + ExecStart= specified. For units with multiple + commands (Type=oneshot), all commands will be run again. + For Type=oneshot, Restart= + and Restart= are not allowed. + + + + Stoppable oneshot service + + Similarly to the oneshot services, there are sometimes + units that need to execute a program to set up something and + then execute another to shut it down, but no process remains + active while they are considered "started". Network + configuration can sometimes fall into this category. Another use + case is if a oneshot service shall not be executed each time + when they are pulled in as a dependency, but only the first + time. + + For this, systemd knows the setting + RemainAfterExit=, which + causes systemd to consider the unit to be active if the start + action exited successfully. This directive can be used with all + types, but is most useful with + Type= and + Type=. With + Type=, systemd waits + until the start action has completed before it considers the + unit to be active, so dependencies start only after the start + action has succeeded. With + Type=, dependencies + will start immediately after the start action has been + dispatched. The following unit provides an example for a simple + static firewall. + + [Unit] +Description=Simple firewall + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/local/sbin/simple-firewall-start +ExecStop=/usr/local/sbin/simple-firewall-stop + +[Install] +WantedBy=multi-user.target + + Since the unit is considered to be running after the start + action has exited, invoking systemctl start + on that unit again will cause no action to be taken. + + + + Traditional forking services + + Many traditional daemons/services background (i.e. fork, + daemonize) themselves when starting. Set + Type= in the + service's unit file to support this mode of operation. systemd + will consider the service to be in the process of initialization + while the original program is still running. Once it exits + successfully and at least a process remains (and + RemainAfterExit=), the + service is considered started. + + Often, a traditional daemon only consists of one process. + Therefore, if only one process is left after the original + process terminates, systemd will consider that process the main + process of the service. In that case, the + $MAINPID variable will be available in + ExecReload=, ExecStop=, + etc. + + In case more than one process remains, systemd will be + unable to determine the main process, so it will not assume + there is one. In that case, $MAINPID will not + expand to anything. However, if the process decides to write a + traditional PID file, systemd will be able to read the main PID + from there. Please set PIDFile= accordingly. + Note that the daemon should write that file before finishing + with its initialization. Otherwise, systemd might try to read the + file before it exists. + + The following example shows a simple daemon that forks and + just starts one process in the background: + + [Unit] +Description=Some simple daemon + +[Service] +Type=forking +ExecStart=/usr/sbin/my-simple-daemon -d + +[Install] +WantedBy=multi-user.target + + Please see + systemd.kill5 + for details on how you can influence the way systemd terminates + the service. + + + + DBus services + + For services that acquire a name on the DBus system bus, + use Type= and set + BusName= accordingly. The service should not + fork (daemonize). systemd will consider the service to be + initialized once the name has been acquired on the system bus. + The following example shows a typical DBus service: + + [Unit] +Description=Simple DBus service + +[Service] +Type=dbus +BusName=org.example.simple-dbus-service +ExecStart=/usr/sbin/simple-dbus-service + +[Install] +WantedBy=multi-user.target + + For bus-activatable services, do not + include a [Install] section in the systemd + service file, but use the SystemdService= + option in the corresponding DBus service file, for example + (/usr/share/dbus-1/system-services/org.example.simple-dbus-service.service): + + [D-BUS Service] +Name=org.example.simple-dbus-service +Exec=/usr/sbin/simple-dbus-service +User=root +SystemdService=simple-dbus-service.service + + Please see + systemd.kill5 + for details on how you can influence the way systemd terminates + the service. + + + + Services that notify systemd about their initialization + + Type= services + are really easy to write, but have the major disadvantage of + systemd not being able to tell when initialization of the given + service is complete. For this reason, systemd supports a simple + notification protocol that allows daemons to make systemd aware + that they are done initializing. Use + Type= for this. A + typical service file for such a daemon would look like + this: + + [Unit] +Description=Simple notifying service + +[Service] +Type=notify +ExecStart=/usr/sbin/simple-notifying-service + +[Install] +WantedBy=multi-user.target + + Note that the daemon has to support systemd's notification + protocol, else systemd will think the service has not started yet + and kill it after a timeout. For an example of how to update + daemons to support this protocol transparently, take a look at + sd_notify3. + systemd will consider the unit to be in the 'starting' state + until a readiness notification has arrived. + + Please see + systemd.kill5 + for details on how you can influence the way systemd terminates + the service. + + + + + See Also + + systemd1, + systemctl1, + systemd-system.conf5, + systemd.unit5, + systemd.exec5, + systemd.resource-control5, + systemd.kill5, + systemd.directives7, + systemd-run1 + + + +
diff --git a/man/systemd.slice.xml b/man/systemd.slice.xml new file mode 100644 index 00000000..7157dfa3 --- /dev/null +++ b/man/systemd.slice.xml @@ -0,0 +1,114 @@ + + + + + + + systemd.slice + systemd + + + + systemd.slice + 5 + + + + systemd.slice + Slice unit configuration + + + + slice.slice + + + + Description + + A unit configuration file whose name ends in .slice encodes information about a slice + unit. A slice unit is a concept for hierarchically managing resources of a group of processes. This management is + performed by creating a node in the Linux Control Group (cgroup) tree. Units that manage processes (primarily scope + and service units) may be assigned to a specific slice. For each slice, certain resource limits may be set that + apply to all processes of all units contained in that slice. Slices are organized hierarchically in a tree. The + name of the slice encodes the location in the tree. The name consists of a dash-separated series of names, which + describes the path to the slice from the root slice. The root slice is named -.slice. Example: + foo-bar.slice is a slice that is located within foo.slice, which in turn + is located in the root slice -.slice. + + + Note that slice units cannot be templated, nor is possible to add multiple names to a slice unit by creating + additional symlinks to its unit file. + + By default, service and scope units are placed in + system.slice, virtual machines and containers + registered with + systemd-machined1 + are found in machine.slice, and user sessions + handled by + systemd-logind1 + in user.slice. See + systemd.special5 + for more information. + + See + systemd.unit5 + for the common options of all unit configuration + files. The common configuration items are configured + in the generic [Unit] and [Install] sections. The + slice specific configuration options are configured in + the [Slice] section. Currently, only generic resource control settings + as described in + systemd.resource-control5 are allowed. + + + See the New + Control Group Interfaces for an introduction on how to make + use of slice units from programs. + + + + Automatic Dependencies + + + Implicit Dependencies + + The following dependencies are implicitly added: + + + Slice units automatically gain dependencies of type + After= and Requires= on + their immediate parent slice unit. + + + + + Default Dependencies + + The following dependencies are added unless DefaultDependencies=no is set: + + + Slice units will automatically have dependencies of type Conflicts= and + Before= on + shutdown.target. These ensure that slice units are removed prior to system shutdown. + Only slice units involved with late system shutdown should disable + DefaultDependencies= option. + + + + + + See Also + + systemd1, + systemd.unit5, + systemd.resource-control5, + systemd.service5, + systemd.scope5, + systemd.special7, + systemd.directives7 + + + + diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml new file mode 100644 index 00000000..60ea63f7 --- /dev/null +++ b/man/systemd.socket.xml @@ -0,0 +1,872 @@ + + + + + + + systemd.socket + systemd + + + + systemd.socket + 5 + + + + systemd.socket + Socket unit configuration + + + + socket.socket + + + + Description + + A unit configuration file whose name ends in + .socket encodes information about an IPC or + network socket or a file system FIFO controlled and supervised by + systemd, for socket-based activation. + + This man page lists the configuration options specific to + this unit type. See + systemd.unit5 + for the common options of all unit configuration files. The common + configuration items are configured in the generic [Unit] and + [Install] sections. The socket specific configuration options are + configured in the [Socket] section. + + Additional options are listed in + systemd.exec5, + which define the execution environment the + , , + and + commands are executed in, and in + systemd.kill5, + which define the way the processes are terminated, and in + systemd.resource-control5, + which configure resource control settings for the processes of the + socket. + + For each socket unit, a matching service unit must exist, + describing the service to start on incoming traffic on the socket + (see + systemd.service5 + for more information about .service units). The name of the + .service unit is by default the same as the name of the .socket + unit, but can be altered with the option + described below. Depending on the setting of the + option described below, this .service + unit must either be named like the .socket unit, but with the + suffix replaced, unless overridden with ; + or it must be a template unit named the same way. Example: a + socket file foo.socket needs a matching + service foo.service if + is set. If + is set, a service template + foo@.service must exist from which services + are instantiated for each incoming connection. + + No implicit WantedBy= or + RequiredBy= dependency from the socket to the + service is added. This means that the service may be started + without the socket, in which case it must be able to open sockets + by itself. To prevent this, an explicit + Requires= dependency may be added. + + Socket units may be used to implement on-demand starting of + services, as well as parallelized starting of services. See the + blog stories linked at the end for an introduction. + + Note that the daemon software configured for socket + activation with socket units needs to be able to accept sockets + from systemd, either via systemd's native socket passing interface + (see + sd_listen_fds3 + for details) or via the traditional + inetd8-style + socket passing (i.e. sockets passed in via standard input and + output, using StandardInput=socket in the + service file). + + All network sockets allocated through .socket units are allocated in the host's network + namespace (see network_namespaces7). This + does not mean however that the service activated by a configured socket unit has to be part of the host's network + namespace as well. It is supported and even good practice to run services in their own network namespace (for + example through PrivateNetwork=, see + systemd.exec5), receiving only + the sockets configured through socket-activation from the host's namespace. In such a set-up communication within + the host's network namespace is only permitted through the activation sockets passed in while all sockets allocated + from the service code itself will be associated with the service's own namespace, and thus possibly subject to a a + much more restrictive configuration. + + + + Automatic Dependencies + + + Implicit Dependencies + + The following dependencies are implicitly added: + + + Socket units automatically gain a Before= + dependency on the service units they activate. + + Socket units referring to file system paths (such as AF_UNIX + sockets or FIFOs) implicitly gain Requires= and + After= dependencies on all mount units + necessary to access those paths. + + Socket units using the BindToDevice= + setting automatically gain a BindsTo= and + After= dependency on the device unit + encapsulating the specified network interface. + + + Additional implicit dependencies may be added as result of + execution and resource control parameters as documented in + systemd.exec5 + and + systemd.resource-control5. + + + + Default Dependencies + + The following dependencies are added unless + DefaultDependencies=no is set: + + + Socket units automatically gain a + Before= dependency on + sockets.target. + + Socket units automatically gain a pair of + After= and Requires= + dependency on sysinit.target, and a pair of + Before= and Conflicts= + dependencies on shutdown.target. These + dependencies ensure that the socket unit is started before normal + services at boot, and is stopped on shutdown. Only sockets + involved with early boot or late system shutdown should disable + DefaultDependencies= option. + + + + + + Options + + Socket files must include a [Socket] section, which carries + information about the socket or FIFO it supervises. A number of + options that may be used in this section are shared with other + unit types. These options are documented in + systemd.exec5 + and + systemd.kill5. + The options specific to the [Socket] section of socket units are + the following: + + + + ListenStream= + ListenDatagram= + ListenSequentialPacket= + Specifies an address to listen on for a stream + (SOCK_STREAM), datagram + (SOCK_DGRAM), or sequential packet + (SOCK_SEQPACKET) socket, respectively. + The address can be written in various formats: + + If the address starts with a slash + (/), it is read as file system socket in + the AF_UNIX socket family. + + If the address starts with an at symbol + (@), it is read as abstract namespace + socket in the AF_UNIX family. The + @ is replaced with a + NUL character before binding. For + details, see + unix7. + + If the address string is a single number, it is read as + port number to listen on via IPv6. Depending on the value of + BindIPv6Only= (see below) this might result + in the service being available via both IPv6 and IPv4 + (default) or just via IPv6. + + + If the address string is a string in the format + v.w.x.y:z, it is read as IPv4 specifier for listening on an + address v.w.x.y on a port z. + + If the address string is a string in the format [x]:y, + it is read as IPv6 address x on a port y. Note that this might + make the service available via IPv4, too, depending on the + BindIPv6Only= setting (see below). + + + If the address string is a string in the format + vsock:x:y, it is read as CID x on + a port y address in the + AF_VSOCK family. The CID is a unique 32-bit + integer identifier in AF_VSOCK analogous to an IP + address. Specifying the CID is optional, and may be set to the empty + string. + + Note that SOCK_SEQPACKET (i.e. + ListenSequentialPacket=) is only available + for AF_UNIX sockets. + SOCK_STREAM (i.e. + ListenStream=) when used for IP sockets + refers to TCP sockets, SOCK_DGRAM (i.e. + ListenDatagram=) to UDP. + + These options may be specified more than once, in which + case incoming traffic on any of the sockets will trigger + service activation, and all listed sockets will be passed to + the service, regardless of whether there is incoming traffic + on them or not. If the empty string is assigned to any of + these options, the list of addresses to listen on is reset, + all prior uses of any of these options will have no + effect. + + It is also possible to have more than one socket unit + for the same service when using Service=, + and the service will receive all the sockets configured in all + the socket units. Sockets configured in one unit are passed in + the order of configuration, but no ordering between socket + units is specified. + + If an IP address is used here, it is often desirable to + listen on it before the interface it is configured on is up + and running, and even regardless of whether it will be up and + running at any point. To deal with this, it is recommended to + set the FreeBind= option described + below. + + + + ListenFIFO= + Specifies a file system FIFO to listen on. + This expects an absolute file system path as argument. + Behavior otherwise is very similar to the + ListenDatagram= directive + above. + + + + ListenSpecial= + Specifies a special file in the file system to + listen on. This expects an absolute file system path as + argument. Behavior otherwise is very similar to the + ListenFIFO= directive above. Use this to + open character device nodes as well as special files in + /proc and + /sys. + + + + ListenNetlink= + Specifies a Netlink family to create a socket + for to listen on. This expects a short string referring to the + AF_NETLINK family name (such as + audit or kobject-uevent) + as argument, optionally suffixed by a whitespace followed by a + multicast group integer. Behavior otherwise is very similar to + the ListenDatagram= directive + above. + + + + ListenMessageQueue= + Specifies a POSIX message queue name to listen + on. This expects a valid message queue name (i.e. beginning + with /). Behavior otherwise is very similar to the + ListenFIFO= directive above. On Linux + message queue descriptors are actually file descriptors and + can be inherited between processes. + + + + ListenUSBFunction= + Specifies a USB + FunctionFS endpoints location to listen on, for + implementation of USB gadget functions. This expects an + absolute file system path of functionfs mount point as the argument. + Behavior otherwise is very similar to the ListenFIFO= + directive above. Use this to open the FunctionFS endpoint + ep0. When using this option, the + activated service has to have the + USBFunctionDescriptors= and + USBFunctionStrings= options set. + + + + + SocketProtocol= + Takes one of + or . Specifies a socket protocol + (IPPROTO_UDPLITE) UDP-Lite + (IPPROTO_SCTP) SCTP socket respectively. + + + + + BindIPv6Only= + Takes one of , + or . Controls + the IPV6_V6ONLY socket option (see + ipv67 + for details). If , IPv6 sockets bound + will be accessible via both IPv4 and IPv6. If + , they will be accessible via IPv6 + only. If (which is the default, + surprise!), the system wide default setting is used, as + controlled by + /proc/sys/net/ipv6/bindv6only, which in + turn defaults to the equivalent of + . + + + + + Backlog= + Takes an unsigned integer argument. Specifies + the number of connections to queue that have not been accepted + yet. This setting matters only for stream and sequential + packet sockets. See + listen2 + for details. Defaults to SOMAXCONN (128). + + + + BindToDevice= + Specifies a network interface name to bind + this socket to. If set, traffic will only be accepted from the + specified network interfaces. This controls the + SO_BINDTODEVICE socket option (see socket7 + for details). If this option is used, an implicit dependency + from this socket unit on the network interface device unit + (systemd.device5 + is created. Note that setting this parameter might result in + additional dependencies to be added to the unit (see + above). + + + + SocketUser= + SocketGroup= + + Takes a UNIX user/group name. When specified, + all AF_UNIX sockets and FIFO nodes in the file system are + owned by the specified user and group. If unset (the default), + the nodes are owned by the root user/group (if run in system + context) or the invoking user/group (if run in user context). + If only a user is specified but no group, then the group is + derived from the user's default group. + + + + SocketMode= + If listening on a file system socket or FIFO, + this option specifies the file system access mode used when + creating the file node. Takes an access mode in octal + notation. Defaults to 0666. + + + + DirectoryMode= + If listening on a file system socket or FIFO, + the parent directories are automatically created if needed. + This option specifies the file system access mode used when + creating these directories. Takes an access mode in octal + notation. Defaults to 0755. + + + + Accept= + Takes a boolean argument. If true, a service + instance is spawned for each incoming connection and only the + connection socket is passed to it. If false, all listening + sockets themselves are passed to the started service unit, and + only one service unit is spawned for all connections (also see + above). This value is ignored for datagram sockets and FIFOs + where a single service unit unconditionally handles all + incoming traffic. Defaults to . For + performance reasons, it is recommended to write new daemons + only in a way that is suitable for + . A daemon listening on an + AF_UNIX socket may, but does not need to, + call + close2 + on the received socket before exiting. However, it must not + unlink the socket from a file system. It should not invoke + shutdown2 + on sockets it got with Accept=no, but it + may do so for sockets it got with + Accept=yes set. Setting + Accept=yes is mostly useful to allow + daemons designed for usage with + inetd8 + to work unmodified with systemd socket + activation. + + For IPv4 and IPv6 connections, the REMOTE_ADDR + environment variable will contain the remote IP address, and REMOTE_PORT + will contain the remote port. This is the same as the format used by CGI. + For SOCK_RAW, the port is the IP protocol. + + + + Writable= + Takes a boolean argument. May only be used in + conjunction with ListenSpecial=. If true, + the specified special file is opened in read-write mode, if + false, in read-only mode. Defaults to false. + + + + MaxConnections= + The maximum number of connections to + simultaneously run services instances for, when + is set. If more concurrent + connections are coming in, they will be refused until at least + one existing connection is terminated. This setting has no + effect on sockets configured with + or datagram sockets. Defaults to + 64. + + + + MaxConnectionsPerSource= + The maximum number of connections for a service per source IP address. + This is very similar to the MaxConnections= directive + above. Disabled by default. + + + + + KeepAlive= + Takes a boolean argument. If true, the TCP/IP + stack will send a keep alive message after 2h (depending on + the configuration of + /proc/sys/net/ipv4/tcp_keepalive_time) + for all TCP streams accepted on this socket. This controls the + SO_KEEPALIVE socket option (see + socket7 + and the TCP + Keepalive HOWTO for details.) Defaults to + . + + + + KeepAliveTimeSec= + Takes time (in seconds) as argument. The connection needs to remain + idle before TCP starts sending keepalive probes. This controls the TCP_KEEPIDLE + socket option (see + socket7 + and the TCP + Keepalive HOWTO for details.) + Defaults value is 7200 seconds (2 hours). + + + + KeepAliveIntervalSec= + Takes time (in seconds) as argument between + individual keepalive probes, if the socket option SO_KEEPALIVE + has been set on this socket. This controls + the TCP_KEEPINTVL socket option (see + socket7 + and the TCP + Keepalive HOWTO for details.) Defaults value is 75 + seconds. + + + + KeepAliveProbes= + Takes an integer as argument. It is the number of + unacknowledged probes to send before considering the + connection dead and notifying the application layer. This + controls the TCP_KEEPCNT socket option (see + socket7 + and the TCP + Keepalive HOWTO for details.) Defaults value is + 9. + + + + NoDelay= + Takes a boolean argument. TCP Nagle's + algorithm works by combining a number of small outgoing + messages, and sending them all at once. This controls the + TCP_NODELAY socket option (see + tcp7 + Defaults to . + + + + Priority= + Takes an integer argument controlling the + priority for all traffic sent from this socket. This controls + the SO_PRIORITY socket option (see + socket7 + for details.). + + + + DeferAcceptSec= + + Takes time (in seconds) as argument. If set, + the listening process will be awakened only when data arrives + on the socket, and not immediately when connection is + established. When this option is set, the + TCP_DEFER_ACCEPT socket option will be + used (see + tcp7), + and the kernel will ignore initial ACK packets without any + data. The argument specifies the approximate amount of time + the kernel should wait for incoming data before falling back + to the normal behavior of honoring empty ACK packets. This + option is beneficial for protocols where the client sends the + data first (e.g. HTTP, in contrast to SMTP), because the + server process will not be woken up unnecessarily before it + can take any action. + + + If the client also uses the + TCP_DEFER_ACCEPT option, the latency of + the initial connection may be reduced, because the kernel will + send data in the final packet establishing the connection (the + third packet in the "three-way handshake"). + + Disabled by default. + + + + + ReceiveBuffer= + SendBuffer= + Takes an integer argument controlling the + receive or send buffer sizes of this socket, respectively. + This controls the SO_RCVBUF and SO_SNDBUF socket options (see + socket7 + for details.). The usual suffixes K, M, G are supported and + are understood to the base of 1024. + + + + IPTOS= + Takes an integer argument controlling the IP + Type-Of-Service field for packets generated from this socket. + This controls the IP_TOS socket option (see + ip7 + for details.). Either a numeric string or one of + , , + or may + be specified. + + + + IPTTL= + Takes an integer argument controlling the IPv4 + Time-To-Live/IPv6 Hop-Count field for packets generated from + this socket. This sets the IP_TTL/IPV6_UNICAST_HOPS socket + options (see + ip7 + and + ipv67 + for details.) + + + + Mark= + Takes an integer value. Controls the firewall + mark of packets generated by this socket. This can be used in + the firewall logic to filter packets from this socket. This + sets the SO_MARK socket option. See + iptables8 + for details. + + + + ReusePort= + Takes a boolean value. If true, allows + multiple + bind2s + to this TCP or UDP port. This controls the SO_REUSEPORT socket + option. See + socket7 + for details. + + + + SmackLabel= + SmackLabelIPIn= + SmackLabelIPOut= + Takes a string value. Controls the extended + attributes security.SMACK64, + security.SMACK64IPIN and + security.SMACK64IPOUT, respectively, i.e. + the security label of the FIFO, or the security label for the + incoming or outgoing connections of the socket, respectively. + See Smack.txt + for details. + + + + SELinuxContextFromNet= + Takes a boolean argument. When true, systemd + will attempt to figure out the SELinux label used for the + instantiated service from the information handed by the peer + over the network. Note that only the security level is used + from the information provided by the peer. Other parts of the + resulting SELinux context originate from either the target + binary that is effectively triggered by socket unit or from + the value of the SELinuxContext= option. + This configuration option only affects sockets with + Accept= mode set to + true. Also note that this option is useful + only when MLS/MCS SELinux policy is deployed. Defaults to + false. + + + + PipeSize= + Takes a size in bytes. Controls the pipe + buffer size of FIFOs configured in this socket unit. See + fcntl2 + for details. The usual suffixes K, M, G are supported and are + understood to the base of 1024. + + + + MessageQueueMaxMessages=, + MessageQueueMessageSize= + These two settings take integer values and + control the mq_maxmsg field or the mq_msgsize field, + respectively, when creating the message queue. Note that + either none or both of these variables need to be set. See + mq_setattr3 + for details. + + + + FreeBind= + Takes a boolean value. Controls whether the + socket can be bound to non-local IP addresses. This is useful + to configure sockets listening on specific IP addresses before + those IP addresses are successfully configured on a network + interface. This sets the IP_FREEBIND socket option. For + robustness reasons it is recommended to use this option + whenever you bind a socket to a specific IP address. Defaults + to . + + + + Transparent= + Takes a boolean value. Controls the + IP_TRANSPARENT socket option. Defaults to + . + + + + Broadcast= + Takes a boolean value. This controls the + SO_BROADCAST socket option, which allows broadcast datagrams + to be sent from this socket. Defaults to + . + + + + PassCredentials= + Takes a boolean value. This controls the + SO_PASSCRED socket option, which allows + AF_UNIX sockets to receive the + credentials of the sending process in an ancillary message. + Defaults to . + + + + PassSecurity= + Takes a boolean value. This controls the + SO_PASSSEC socket option, which allows + AF_UNIX sockets to receive the security + context of the sending process in an ancillary message. + Defaults to . + + + + TCPCongestion= + Takes a string value. Controls the TCP + congestion algorithm used by this socket. Should be one of + "westwood", "veno", "cubic", "lp" or any other available + algorithm supported by the IP stack. This setting applies only + to stream sockets. + + + + ExecStartPre= + ExecStartPost= + Takes one or more command lines, which are + executed before or after the listening sockets/FIFOs are + created and bound, respectively. The first token of the + command line must be an absolute filename, then followed by + arguments for the process. Multiple command lines may be + specified following the same scheme as used for + ExecStartPre= of service unit + files. + + + + ExecStopPre= + ExecStopPost= + Additional commands that are executed before + or after the listening sockets/FIFOs are closed and removed, + respectively. Multiple command lines may be specified + following the same scheme as used for + ExecStartPre= of service unit + files. + + + + TimeoutSec= + Configures the time to wait for the commands + specified in ExecStartPre=, + ExecStartPost=, + ExecStopPre= and + ExecStopPost= to finish. If a command does + not exit within the configured time, the socket will be + considered failed and be shut down again. All commands still + running will be terminated forcibly via + SIGTERM, and after another delay of this + time with SIGKILL. (See + in + systemd.kill5.) + Takes a unit-less value in seconds, or a time span value such + as "5min 20s". Pass 0 to disable the + timeout logic. Defaults to + DefaultTimeoutStartSec= from the manager + configuration file (see + systemd-system.conf5). + + + + + Service= + Specifies the service unit name to activate on + incoming traffic. This setting is only allowed for sockets + with Accept=no. It defaults to the service + that bears the same name as the socket (with the suffix + replaced). In most cases, it should not be necessary to use + this option. Note that setting this parameter might result in + additional dependencies to be added to the unit (see + above). + + + + RemoveOnStop= + Takes a boolean argument. If enabled, any file + nodes created by this socket unit are removed when it is + stopped. This applies to AF_UNIX sockets in the file system, + POSIX message queues, FIFOs, as well as any symlinks to them + configured with Symlinks=. Normally, it + should not be necessary to use this option, and is not + recommended as services might continue to run after the socket + unit has been terminated and it should still be possible to + communicate with them via their file system node. Defaults to + off. + + + + Symlinks= + Takes a list of file system paths. The specified paths will be created as symlinks to the + AF_UNIX socket path or FIFO path of this socket unit. If this setting is used, only one + AF_UNIX socket in the file system or one FIFO may be configured for the socket unit. Use + this option to manage one or more symlinked alias names for a socket, binding their lifecycle together. Note + that if creation of a symlink fails this is not considered fatal for the socket unit, and the socket unit may + still start. If an empty string is assigned, the list of paths is reset. Defaults to an empty + list. + + + + FileDescriptorName= + Assigns a name to all file descriptors this + socket unit encapsulates. This is useful to help activated + services identify specific file descriptors, if multiple fds + are passed. Services may use the + sd_listen_fds_with_names3 + call to acquire the names configured for the received file + descriptors. Names may contain any ASCII character, but must + exclude control characters and :, and must + be at most 255 characters in length. If this setting is not + used, the file descriptor name defaults to the name of the + socket unit, including its .socket + suffix. + + + + TriggerLimitIntervalSec= + TriggerLimitBurst= + + Configures a limit on how often this socket unit my be activated within a specific time + interval. The TriggerLimitIntervalSec= may be used to configure the length of the time + interval in the usual time units us, ms, s, + min, h, … and defaults to 2s (See + systemd.time7 for details on + the various time units understood). The TriggerLimitBurst= setting takes a positive integer + value and specifies the number of permitted activations per time interval, and defaults to 200 for + Accept=yes sockets (thus by default permitting 200 activations per 2s), and 20 otherwise (20 + activations per 2s). Set either to 0 to disable any form of trigger rate limiting. If the limit is hit, the + socket unit is placed into a failure mode, and will not be connectible anymore until restarted. Note that this + limit is enforced before the service activation is enqueued. + + + + + Check + systemd.exec5 + and + systemd.kill5 + for more settings. + + + + + See Also + + systemd1, + systemctl1, + systemd-system.conf5, + systemd.unit5, + systemd.exec5, + systemd.kill5, + systemd.resource-control5, + systemd.service5, + systemd.directives7, + sd_listen_fds3, + sd_listen_fds_with_names3 + + + For more extensive descriptions see the "systemd for Developers" series: + Socket Activation, + Socket Activation, part II, + Converting inetd Services, + Socket Activated Internet Services and OS Containers. + + + + diff --git a/man/systemd.special.xml b/man/systemd.special.xml new file mode 100644 index 00000000..248fb924 --- /dev/null +++ b/man/systemd.special.xml @@ -0,0 +1,1143 @@ + + + + + + + + systemd.special + systemd + + + + systemd.special + 7 + + + + systemd.special + Special systemd units + + + + basic.target, + bluetooth.target, + cryptsetup-pre.target, + cryptsetup.target, + ctrl-alt-del.target, + boot-complete.target, + default.target, + emergency.target, + exit.target, + final.target, + getty.target, + getty-pre.target, + graphical.target, + halt.target, + hibernate.target, + hybrid-sleep.target, + suspend-then-hibernate.target, + initrd-fs.target, + initrd-root-device.target, + initrd-root-fs.target, + kbrequest.target, + kexec.target, + local-fs-pre.target, + local-fs.target, + machines.target + multi-user.target, + network-online.target, + network-pre.target, + network.target, + nss-lookup.target, + nss-user-lookup.target, + paths.target, + poweroff.target, + printer.target, + reboot.target, + remote-cryptsetup.target, + remote-fs-pre.target, + remote-fs.target, + rescue.target, + rpcbind.target, + runlevel2.target, + runlevel3.target, + runlevel4.target, + runlevel5.target, + shutdown.target, + sigpwr.target, + sleep.target, + slices.target, + smartcard.target, + sockets.target, + sound.target, + suspend.target, + swap.target, + sysinit.target, + system-update.target, + system-update-pre.target, + time-set.target, + time-sync.target, + timers.target, + umount.target, + usb-gadget.target, + -.slice, + system.slice, + user.slice, + machine.slice, + -.mount, + dbus.service, + dbus.socket, + display-manager.service, + init.scope, + syslog.socket, + system-update-cleanup.service + + + + Description + + A few units are treated specially by systemd. Many of them have + special internal semantics and cannot be renamed, while others simply + have a standard meaning and should be present on all systems. + + + + Units managed by the system's service manager + + + Special System Units + + + + -.mount + + The root mount point, i.e. the mount unit for the / + path. This unit is unconditionally active, during the entire time the system is up, as + this mount point is where the basic userspace is running from. + + + + + basic.target + + A special target unit covering basic boot-up. + + systemd automatically adds dependency of the type + After= for this target unit to all + services (except for those with + DefaultDependencies=no). + + Usually, this should pull-in all local mount points plus + /var, /tmp and + /var/tmp, swap devices, sockets, timers, + path units and other basic initialization necessary for general + purpose daemons. The mentioned mount points are special cased + to allow them to be remote. + + + This target usually does not pull in any non-target units + directly, but rather does so indirectly via other early boot targets. + It is instead meant as a synchronization point for late boot + services. Refer to + bootup7 + for details on the targets involved. + + + + + boot-complete.target + + This target is intended as generic synchronization point for services that shall determine or act on + whether the boot process completed successfully. Order units that are required to succeed for a boot process + to be considered successful before this unit, and add a Requires= dependency from the + target unit to them. Order units that shall only run when the boot process is considered successful after the + target unit and pull in the target from it, also with Requires=. Note that by default this + target unit is not part of the initial boot transaction, but is supposed to be pulled in only if required by + units that want to run only on successful boots. + + See + systemd-boot-check-no-failures.service8 + for a service that implements a generic system health check and orders itself before + boot-complete.target. + + See + systemd-bless-boot.service8 + for a service that propagates boot success information to the boot loader, and orders itself after + boot-complete.target. + + + + ctrl-alt-del.target + + systemd starts this target whenever Control+Alt+Del is + pressed on the console. Usually, this should be aliased + (symlinked) to reboot.target. + + + + cryptsetup.target + + A target that pulls in setup services for all + encrypted block devices. + + + + dbus.service + + A special unit for the D-Bus bus daemon. As soon as + this service is fully started up systemd will connect to it + and register its service. + + + + dbus.socket + + A special unit for the D-Bus system bus socket. All + units with Type=dbus automatically gain a + dependency on this unit. + + + + default.target + + The default unit systemd starts at bootup. Usually, + this should be aliased (symlinked) to + multi-user.target or + graphical.target. + + The default unit systemd starts at bootup can be + overridden with the systemd.unit= kernel + command line option. + + + + display-manager.service + + The display manager service. Usually, this should be + aliased (symlinked) to gdm.service or a + similar display manager service. + + + + emergency.target + + A special target unit that starts an emergency shell on the main console. This + target does not pull in any services or mounts. It is the most minimal version of + starting the system in order to acquire an interactive shell; the only processes running + are usually just the system manager (PID 1) and the shell process. This unit is supposed + to be used with the kernel command line option systemd.unit=; it is + also used when a file system check on a required file system fails, and boot-up cannot + continue. Compare with rescue.target, which serves a similar + purpose, but also starts the most basic services and mounts all file systems. + + Use the systemd.unit=emergency.target kernel command line + option to boot into this mode. A short alias for this kernel command line option is + emergency, for compatibility with SysV. + + In many ways booting into emergency.target is similar to the + effect of booting with init=/bin/sh on the kernel command line, + except that emergency mode provides you with the full system and service manager, and + allows starting individual units in order to continue the boot process in steps. + + + + exit.target + + A special service unit for shutting down the system or + user service manager. It is equivalent to + poweroff.target on non-container + systems, and also works in containers. + + systemd will start this unit when it receives the + SIGTERM or SIGINT + signal when running as user service daemon. + + Normally, this (indirectly) pulls in + shutdown.target, which in turn should be + conflicted by all units that want to be scheduled for + shutdown when the service manager starts to exit. + + + + final.target + + A special target unit that is used during the shutdown + logic and may be used to pull in late services after all + normal services are already terminated and all mounts + unmounted. + + + + + getty.target + + A special target unit that pulls in statically + configured local TTY getty instances. + + + + + graphical.target + + A special target unit for setting up a graphical login + screen. This pulls in + multi-user.target. + + Units that are needed for graphical logins shall add + Wants= dependencies for their unit to + this unit (or multi-user.target) during + installation. This is best configured via + WantedBy=graphical.target in the unit's + [Install] section. + + + + hibernate.target + + A special target unit for hibernating the system. This + pulls in sleep.target. + + + + hybrid-sleep.target + + A special target unit for hibernating and suspending + the system at the same time. This pulls in + sleep.target. + + + + suspend-then-hibernate.target + + A special target unit for suspending the system for a period + of time, waking it and putting it into hibernate. This pulls in + sleep.target. + + + + + halt.target + + A special target unit for shutting down and halting + the system. Note that this target is distinct from + poweroff.target in that it generally + really just halts the system rather than powering it + down. + + Applications wanting to halt the system should not start this unit + directly, but should instead execute systemctl halt + (possibly with the option) or call + systemd1's + org.freedesktop.systemd1.Manager.Halt D-Bus method + directly. + + + + init.scope + + This scope unit is where the system and service manager (PID 1) itself resides. It + is active as long as the system is running. + + + + initrd-fs.target + + systemd-fstab-generator3 + automatically adds dependencies of type + Before= to + sysroot-usr.mount and all mount points + found in /etc/fstab that have + and not have + mount options set. + + + + initrd-root-device.target + + A special initrd target unit that is reached when the root filesystem device is available, but before + it has been mounted. + systemd-fstab-generator3 + and + systemd-gpt-auto-generator3 + automatically setup the appropriate dependencies to make this happen. + + + + + initrd-root-fs.target + + systemd-fstab-generator3 + automatically adds dependencies of type + Before= to the + sysroot.mount unit, which is generated + from the kernel command line. + + + + + kbrequest.target + + systemd starts this target whenever Alt+ArrowUp is + pressed on the console. Note that any user with physical access + to the machine will be able to do this, without authentication, + so this should be used carefully. + + + + kexec.target + + A special target unit for shutting down and rebooting + the system via kexec. + + Applications wanting to reboot the system should not start this unit + directly, but should instead execute systemctl kexec + (possibly with the option) or call + systemd1's + org.freedesktop.systemd1.Manager.KExec D-Bus method + directly. + + + + local-fs.target + + systemd-fstab-generator3 + automatically adds dependencies of type + Before= to all mount units that refer to + local mount points for this target unit. In addition, it + adds dependencies of type Wants= to this + target unit for those mounts listed in + /etc/fstab that have the + mount option set. + + + + machines.target + + A standard target unit for starting all the containers + and other virtual machines. See systemd-nspawn@.service + for an example. + + + + multi-user.target + + A special target unit for setting up a multi-user + system (non-graphical). This is pulled in by + graphical.target. + + Units that are needed for a multi-user system shall + add Wants= dependencies for their unit to + this unit during installation. This is best configured via + WantedBy=multi-user.target in the unit's + [Install] section. + + + + network-online.target + + Units that strictly require a configured network + connection should pull in + network-online.target (via a + Wants= type dependency) and order + themselves after it. This target unit is intended to pull in + a service that delays further execution until the network is + sufficiently set up. What precisely this requires is left to + the implementation of the network managing service. + + Note the distinction between this unit and + network.target. This unit is an active + unit (i.e. pulled in by the consumer rather than the + provider of this functionality) and pulls in a service which + possibly adds substantial delays to further execution. In + contrast, network.target is a passive + unit (i.e. pulled in by the provider of the functionality, + rather than the consumer) that usually does not delay + execution much. Usually, network.target + is part of the boot of most systems, while + network-online.target is not, except + when at least one unit requires it. Also see Running + Services After the Network is up for more + information. + + All mount units for remote network file systems + automatically pull in this unit, and order themselves after + it. Note that networking daemons that simply provide + functionality to other hosts generally do not need to pull + this in. + + systemd automatically adds dependencies of type Wants= and + After= for this target unit to all SysV init script service units + with an LSB header referring to the $network facility. + + Note that this unit is only useful during the original system start-up + logic. After the system has completed booting up, it will not track the online state of + the system anymore. Due to this it cannot be used as a network connection monitor + concept, it is purely a one-time system start-up concept. + + + + paths.target + + A special target unit that sets up all path units (see + systemd.path5 + for details) that shall be active after boot. + + It is recommended that path units installed by + applications get pulled in via Wants= + dependencies from this unit. This is best configured via a + WantedBy=paths.target in the path unit's + [Install] section. + + + + poweroff.target + + A special target unit for shutting down and powering + off the system. + + Applications wanting to power off the system should not start this unit + directly, but should instead execute systemctl poweroff + (possibly with the option) or call + systemd-logind8's + org.freedesktop.login1.Manager.PowerOff D-Bus method + directly. + + runlevel0.target is an alias for + this target unit, for compatibility with SysV. + + + + reboot.target + + A special target unit for shutting down and rebooting + the system. + + Applications wanting to reboot the system should not start this unit + directly, but should instead execute systemctl reboot + (possibly with the option) or call + systemd-logind8's + org.freedesktop.login1.Manager.Reboot D-Bus method + directly. + + runlevel6.target is an alias for + this target unit, for compatibility with SysV. + + + + remote-cryptsetup.target + + Similar to cryptsetup.target, but for encrypted + devices which are accessed over the network. It is used for + crypttab8 + entries marked with . + + + + remote-fs.target + + Similar to local-fs.target, but + for remote mount points. + + systemd automatically adds dependencies of type + After= for this target unit to all SysV + init script service units with an LSB header referring to + the $remote_fs facility. + + + + rescue.target + + A special target unit that pulls in the base system (including system mounts) and + spawns a rescue shell. Isolate to this target in order to administer the system in + single-user mode with all file systems mounted but with no services running, except for + the most basic. Compare with emergency.target, which is much more + reduced and does not provide the file systems or most basic services. Compare with + multi-user.target, this target could be seen as + single-user.target. + + runlevel1.target is an alias for this target unit, for + compatibility with SysV. + + Use the systemd.unit=rescue.target kernel command line option + to boot into this mode. A short alias for this kernel command line option is + 1, for compatibility with SysV. + + + + runlevel2.target + runlevel3.target + runlevel4.target + runlevel5.target + + These are targets that are called whenever the SysV + compatibility code asks for runlevel 2, 3, 4, 5, + respectively. It is a good idea to make this an alias for + (i.e. symlink to) graphical.target + (for runlevel 5) or multi-user.target + (the others). + + + + shutdown.target + + A special target unit that terminates the services on + system shutdown. + + Services that shall be terminated on system shutdown + shall add Conflicts= and + Before= dependencies to this unit for + their service unit, which is implicitly done when + DefaultDependencies=yes is set (the + default). + + + + sigpwr.target + + A special target that is started when systemd receives + the SIGPWR process signal, which is normally sent by the + kernel or UPS daemons when power fails. + + + + sleep.target + + A special target unit that is pulled in by + suspend.target, + hibernate.target and + hybrid-sleep.target and may be used to + hook units into the sleep state logic. + + + + slices.target + + A special target unit that sets up all slice units (see + systemd.slice5 + for details) that shall always be active after boot. By default the generic + system.slice slice unit as well as the root slice unit + -.slice are pulled in and ordered before this unit (see + below). + + Adding slice units to slices.target is generally not + necessary. Instead, when some unit that uses Slice= is started, the + specified slice will be started automatically. Adding + WantedBy=slices.target lines to the [Install] + section should only be done for units that need to be always active. In that case care + needs to be taken to avoid creating a loop through the automatic dependencies on + "parent" slices. + + + + sockets.target + + A special target unit that sets up all socket + units (see + systemd.socket5 + for details) that shall be active after boot. + + Services that can be socket-activated shall add + Wants= dependencies to this unit for + their socket unit during installation. This is best + configured via a WantedBy=sockets.target + in the socket unit's [Install] + section. + + + + suspend.target + + A special target unit for suspending the system. This + pulls in sleep.target. + + + + swap.target + + Similar to local-fs.target, but + for swap partitions and swap files. + + + + sysinit.target + + systemd automatically adds dependencies of the types + Requires= and After= + for this target unit to all services (except for those with + DefaultDependencies=no). + + This target pulls in the services required for system + initialization. System services pulled in by this target should + declare DefaultDependencies=no and specify + all their dependencies manually, including access to anything + more than a read only root filesystem. For details on the + dependencies of this target, refer to + bootup7. + + + + + syslog.socket + + The socket unit syslog implementations should listen + on. All userspace log messages will be made available on + this socket. For more information about syslog integration, + please consult the Syslog + Interface document. + + + + system-update.target + system-update-pre.target + system-update-cleanup.service + + A special target unit that is used for offline system updates. + systemd-system-update-generator8 + will redirect the boot process to this target if /system-update + exists. For more information see + systemd.offline-updates7. + + + Updates should happen before the system-update.target is + reached, and the services which implement them should cause the machine to reboot. The + main units executing the update should order themselves after + system-update-pre.target but not pull it in. Services which want to + run during system updates only, but before the actual system update is executed should + order themselves before this unit and pull it in. As a safety measure, if this does not + happen, and /system-update still exists after + system-update.target is reached, + system-update-cleanup.service will remove this symlink and reboot + the machine. + + + + timers.target + + A special target unit that sets up all timer units + (see + systemd.timer5 + for details) that shall be active after boot. + + It is recommended that timer units installed by + applications get pulled in via Wants= + dependencies from this unit. This is best configured via + WantedBy=timers.target in the timer + unit's [Install] section. + + + + umount.target + + A special target unit that unmounts all mount and + automount points on system shutdown. + + Mounts that shall be unmounted on system shutdown + shall add Conflicts dependencies to this unit for their + mount unit, which is implicitly done when + DefaultDependencies=yes is set (the + default). + + + + + + + + Special System Units for Devices + + Some target units are automatically pulled in as devices of + certain kinds show up in the system. These may be used to + automatically activate various services based on the specific type + of the available hardware. + + + + bluetooth.target + + This target is started automatically as soon as a + Bluetooth controller is plugged in or becomes available at + boot. + + This may be used to pull in Bluetooth management + daemons dynamically when Bluetooth hardware is found. + + + + printer.target + + This target is started automatically as soon as a + printer is plugged in or becomes available at boot. + + This may be used to pull in printer management daemons + dynamically when printer hardware is found. + + + + smartcard.target + + This target is started automatically as soon as a + smartcard controller is plugged in or becomes available at + boot. + + This may be used to pull in smartcard management + daemons dynamically when smartcard hardware is found. + + + + sound.target + + This target is started automatically as soon as a + sound card is plugged in or becomes available at + boot. + + This may be used to pull in audio management daemons + dynamically when audio hardware is found. + + + + usb-gadget.target + + This target is started automatically as soon as a + USB Device Controller becomes available at boot. + + This may be used to pull in usb gadget + dynamically when UDC hardware is found. + + + + + + + Special Passive System Units + + A number of special system targets are defined that can be + used to properly order boot-up of optional services. These targets + are generally not part of the initial boot transaction, unless + they are explicitly pulled in by one of the implementing services. + Note specifically that these passive target + units are generally not pulled in by the consumer of a service, + but by the provider of the service. This means: a consuming + service should order itself after these targets (as appropriate), + but not pull it in. A providing service should order itself before + these targets (as appropriate) and pull it in (via a + Wants= type dependency). + + Note that these passive units cannot be started manually, + i.e. systemctl start time-sync.target will fail + with an error. They can only be pulled in by dependency. This is + enforced since they exist for ordering purposes only and thus are + not useful as only unit within a transaction. + + + + cryptsetup-pre.target + + This passive target unit may be pulled in by services + that want to run before any encrypted block device is set + up. All encrypted block devices are set up after this target + has been reached. Since the shutdown order is implicitly the + reverse start-up order between units, this target is + particularly useful to ensure that a service is shut down + only after all encrypted block devices are fully + stopped. + + + + getty-pre.target + + A special passive target unit. Users of this target + are expected to pull it in the boot transaction via + a dependency (e.g. Wants=). Order your + unit before this unit if you want to make use of the console + just before getty is started. + + + + + local-fs-pre.target + + This target unit is + automatically ordered before + all local mount points marked + with + (see above). It can be used to + execute certain units before + all local mounts. + + + + network.target + + This unit is supposed to indicate when network + functionality is available, but it is only very weakly + defined what that is supposed to mean, with one exception: + at shutdown, a unit that is ordered after + network.target will be stopped before + the network — to whatever level it might be set up then — + is shut down. It is hence useful when writing service files + that require network access on shutdown, which should order + themselves after this target, but not pull it in. Also see + Running + Services After the Network is up for more + information. Also see + network-online.target described + above. + + + + network-pre.target + + This passive target unit may be pulled in by services + that want to run before any network is set up, for example + for the purpose of setting up a firewall. All network + management software orders itself after this target, but + does not pull it in. + + + + nss-lookup.target + + A target that should be used as synchronization point for all host/network name + service lookups. Note that this is independent of UNIX user/group name lookups for which + nss-user-lookup.target should be used. All services for which the + availability of full host/network name resolution is essential should be ordered after + this target, but not pull it in. systemd automatically adds dependencies of type + After= for this target unit to all SysV init script service units + with an LSB header referring to the $named facility. + + + + nss-user-lookup.target + + A target that should be used as synchronization point for all regular UNIX + user/group name service lookups. Note that this is independent of host/network name + lookups for which nss-lookup.target should be used. All services + for which the availability of the full user/group database is essential should be + ordered after this target, but not pull it in. All services which provide parts of the + user/group database should be ordered before this target, and pull it in. Note that this + unit is only relevant for regular users and groups — system users and groups are + required to be resolvable during earliest boot already, and hence do not need any + special ordering against this target. + + + + remote-fs-pre.target + + This target unit is automatically ordered before all + mount point units (see above) and cryptsetup devices + marked with the . It can be used to run + certain units before remote encrypted devices and mounts are established. + Note that this unit is generally not part of the initial + transaction, unless the unit that wants to be ordered before + all remote mounts pulls it in via a + Wants= type dependency. If the unit wants + to be pulled in by the first remote mount showing up, it + should use network-online.target (see + above). + + + + rpcbind.target + + The portmapper/rpcbind pulls in this target and orders + itself before it, to indicate its availability. systemd + automatically adds dependencies of type + After= for this target unit to all SysV + init script service units with an LSB header referring to + the $portmap facility. + + + + time-set.target + + Services responsible for setting the system clock from + a local source (such as a maintained timestamp file or + imprecise real-time clock) should pull in this target and + order themselves before it. Services where approximate time + is desired should be ordered after this unit, but not pull + it in. This target does not provide the accuracy guarantees + of time-sync.target. + + + + time-sync.target + + Services responsible for synchronizing the system + clock from a remote source (such as NTP client + implementations) should pull in this target and order + themselves before it. All services where correct time is + essential should be ordered after this unit, but not pull it + in. systemd automatically adds dependencies of type + After= for this target unit to all SysV + init script service units with an LSB header referring to + the $time facility. + + + + + + + Special Slice Units + + There are four .slice units which form the basis of the hierarchy for + assignment of resources for services, users, and virtual machines or containers. See + systemd.slice7 + for details about slice units. + + + + -.slice + + The root slice is the root of the slice hierarchy. It usually does not contain + units directly, but may be used to set defaults for the whole tree. + + + + + system.slice + + By default, all system services started by + systemd are found in this slice. + + + + + user.slice + + By default, all user processes and services started on + behalf of the user, including the per-user systemd instance + are found in this slice. This is pulled in by + systemd-logind.service + + + + + machine.slice + + By default, all virtual machines and containers + registered with systemd-machined are + found in this slice. This is pulled in by + systemd-machined.service + + + + + + + + Units managed by the user's service manager + + + Special User Units + + When systemd runs as a user instance, the following special + units are available: + + + + default.target + + This is the main target of the user session, started by default. Various services that + compose the normal user session should be pulled into this target. In this regard, + default.target is similar to multi-user.target in the + system instance, but it is a real unit, not an alias. + + + + + In addition, the following units are available which have definitions similar to their + system counterparts: + exit.target, + shutdown.target, + sockets.target, + timers.target, + paths.target, + bluetooth.target, + printer.target, + smartcard.target, + sound.target. + + + + Special Passive User Units + + + + graphical-session.target + + This target is active whenever any graphical session is running. It is used to + stop user services which only apply to a graphical (X, Wayland, etc.) session when the + session is terminated. Such services should have + PartOf=graphical-session.target in their [Unit] + section. A target for a particular session (e. g. + gnome-session.target) starts and stops + graphical-session.target with + BindsTo=graphical-session.target. + + Which services are started by a session target is determined by the + Wants= and Requires= dependencies. For services + that can be enabled independently, symlinks in .wants/ and + .requires/ should be used, see + systemd.unit5. + Those symlinks should either be shipped in packages, or should be added dynamically + after installation, for example using systemctl add-wants, see + systemctl1. + + + + Nautilus as part of a GNOME session + + gnome-session.target pulls in Nautilus as top-level service: + + [Unit] + Description=User systemd services for GNOME graphical session + Wants=nautilus.service + BindsTo=graphical-session.target + + nautilus.service gets stopped when the session stops: + + [Unit] + Description=Render the desktop icons with Nautilus + PartOf=graphical-session.target + + [Service] + … + + + + + + graphical-session-pre.target + + This target contains services which set up the environment or global configuration + of a graphical session, such as SSH/GPG agents (which need to export an environment + variable into all desktop processes) or migration of obsolete d-conf keys after an OS + upgrade (which needs to happen before starting any process that might use them). This + target must be started before starting a graphical session like + gnome-session.target. + + + + + + + + See Also + + systemd1, + systemd.unit5, + systemd.service5, + systemd.socket5, + systemd.target5, + systemd.slice5, + bootup7, + systemd-fstab-generator8, + user@.service5 + + + + diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml new file mode 100644 index 00000000..190fc388 --- /dev/null +++ b/man/systemd.swap.xml @@ -0,0 +1,258 @@ + + + + + + + + systemd.swap + systemd + + + + systemd.swap + 5 + + + + systemd.swap + Swap unit configuration + + + + swap.swap + + + + Description + + A unit configuration file whose name ends in + .swap encodes information about a swap device + or file for memory paging controlled and supervised by + systemd. + + This man page lists the configuration options specific to + this unit type. See + systemd.unit5 + for the common options of all unit configuration files. The common + configuration items are configured in the generic [Unit] and + [Install] sections. The swap specific configuration options are + configured in the [Swap] section. + + Additional options are listed in + systemd.exec5, + which define the execution environment the swapon8 + program is executed in, in + systemd.kill5, + which define the way these processes are + terminated, and in + systemd.resource-control5, + which configure resource control settings for these processes of the + unit. + + Swap units must be named after the devices or files they control. Example: the swap device /dev/sda5 must be configured in a unit file dev-sda5.swap. For + details about the escaping logic used to convert a file system path to a unit name, see + systemd.unit5. Note that swap + units cannot be templated, nor is possible to add multiple names to a swap unit by creating additional symlinks to + it. + + + + Automatic Dependencies + + + Implicit Dependencies + + The following dependencies are implicitly added: + + + All swap units automatically get the + BindsTo= and After= + dependencies on the device units or the mount units of the files + they are activated from. + + + Additional implicit dependencies may be added as result of + execution and resource control parameters as documented in + systemd.exec5 + and + systemd.resource-control5. + + + + Default Dependencies + + The following dependencies are added unless DefaultDependencies=no is set: + + + Swap units automatically acquire a Conflicts= and a + Before= dependency on umount.target so that they are deactivated at + shutdown as well as a Before=swap.target dependency. + + + + + + <filename>fstab</filename> + + Swap units may either be configured via unit files, or via + /etc/fstab (see + fstab5 + for details). Swaps listed in /etc/fstab will + be converted into native units dynamically at boot and when the + configuration of the system manager is reloaded. See + systemd-fstab-generator8 + for details about the conversion. + + If a swap device or file is configured in both + /etc/fstab and a unit file, the configuration + in the latter takes precedence. + + When reading /etc/fstab, a few special + options are understood by systemd which influence how dependencies + are created for swap units. + + + + + + + With , the swap unit + will not be added as a dependency for + swap.target. This means that it will not + be activated automatically during boot, unless it is pulled in + by some other unit. The option has the + opposite meaning and is the default. + + + + + + + With , the swap unit + will be only wanted, not required by + swap.target. This means that the boot + will continue even if this swap device is not activated + successfully. + + + + + + + + + The swap structure will be initialized on the device. If the device is not + "empty", i.e. it contains any signature, the operation will be skipped. It is hence expected + that this option remains set even after the device has been initialized. + + Note that this option can only be used in /etc/fstab, and will be + ignored when part of the Options= setting in a unit file. + + See + systemd-mkswap@.service8 + and the discussion of + wipefs8 + in systemd.mount5. + + + + + + + Options + + Swap files must include a [Swap] section, which carries + information about the swap device it supervises. A number of + options that may be used in this section are shared with other + unit types. These options are documented in + systemd.exec5 + and + systemd.kill5. + The options specific to the [Swap] section of swap units are the + following: + + + + + What= + Takes an absolute path of a device node or file to use for paging. See swapon8 for + details. If this refers to a device node, a dependency on the respective device unit is automatically + created. (See + systemd.device5 for more + information.) If this refers to a file, a dependency on the respective mount unit is automatically + created. (See systemd.mount5 + for more information.) This option is mandatory. Note that the usual specifier expansion is applied to this + setting, literal percent characters should hence be written as %%. + + + + Priority= + + Swap priority to use when activating the swap + device or file. This takes an integer. This setting is + optional and ignored when the priority is set by in the + Options= key. + + + + Options= + + May contain an option string for the swap device. This may be used for controlling discard + options among other functionality, if the swap backing device supports the discard or trim operation. (See + swapon8 + for more information.) Note that the usual specifier expansion is applied to this setting, literal percent + characters should hence be written as %%. + + + + TimeoutSec= + Configures the time to wait for the swapon + command to finish. If a command does not exit within the + configured time, the swap will be considered failed and be + shut down again. All commands still running will be terminated + forcibly via SIGTERM, and after another + delay of this time with SIGKILL. (See + in + systemd.kill5.) + Takes a unit-less value in seconds, or a time span value such + as "5min 20s". Pass 0 to disable the + timeout logic. Defaults to + DefaultTimeoutStartSec= from the manager + configuration file (see + systemd-system.conf5). + + + + + Check + systemd.exec5 + and + systemd.kill5 + for more settings. + + + + See Also + + systemd1, + systemctl1, + systemd-system.conf5, + systemd.unit5, + systemd.exec5, + systemd.kill5, + systemd.resource-control5, + systemd.device5, + systemd.mount5, + swapon8, + systemd-fstab-generator8, + systemd.directives7 + + + + diff --git a/man/systemd.syntax.xml b/man/systemd.syntax.xml new file mode 100644 index 00000000..05786cc5 --- /dev/null +++ b/man/systemd.syntax.xml @@ -0,0 +1,130 @@ + + +%entities; +]> + + + + + + systemd.syntax + systemd + + + + systemd.syntax + 7 + + + + systemd.syntax + General syntax of systemd configuration files + + + + Introduction + + This page describes the basic principles of configuration files used by + systemd1 + and related programs for: + + systemd unit files, see + systemd.unit5, + systemd.service5, + systemd.socket5, + systemd.device5, + systemd.mount5, + systemd.automount5, + systemd.swap5, + systemd.target5, + systemd.path5, + systemd.timer5, + systemd.slice5, + systemd.scope5, + systemd.nspawn5 + + + daemon config files, see + systemd-system.conf5, + systemd-user.conf5, + logind.conf5, + journald.conf5, + journal-remote.conf5, + journal-upload.conf5, + systemd-sleep.conf5, + timesyncd.conf5 + + + + + The syntax is inspired by + XDG Desktop Entry Specification + .desktop files, which are in turn inspired by Microsoft Windows + .ini files. + + + Each file is a plain text file divided into sections, with configuration entries in the + style key=value. + Whitespace immediately before or after the = is ignored. Empty lines and lines starting with # or ; are + ignored, which may be used for commenting. + + Lines ending in a backslash are concatenated with the following line while reading and the + backslash is replaced by a space character. This may be used to wrap long lines. The limit on + line length is very large (currently 1 MB), but it is recommended to avoid such long lines and + use multiple directives, variable substitution, or other mechanism as appropriate for the given + file type. When a comment line or lines follow a line ending with a backslash, the comment block + is ignored, so the continued line is concatenated with whatever follows the comment block. + + [Section A] +KeyOne=value 1 +KeyTwo=value 2 + +# a comment + +[Section B] +Setting="something" "some thing" "…" +KeyTwo=value 2 \ + value 2 continued + +[Section C] +KeyThree=value 2\ +# this line is ignored +; this line is ignored too + value 2 continued + + + Boolean arguments used in configuration files can be written in + various formats. For positive settings the strings + , , + and are equivalent. For negative settings, the + strings , , + and are + equivalent. + + Time span values encoded in configuration files can be written in various formats. A stand-alone + number specifies a time in seconds. If suffixed with a time unit, the unit is honored. A + concatenation of multiple values with units is supported, in which case the values are added + up. Example: 50 refers to 50 seconds; 2min 200ms refers to + 2 minutes and 200 milliseconds, i.e. 120200 ms. The following time units are understood: + s, min, h, d, + w, ms, us. For details see + systemd.time7. + + Various settings are allowed to be specified more than once, in which case the + interpretation depends on the setting. Often, multiple settings form a list, and setting to an + empty value "resets", which means that previous assignments are ignored. When this is allowed, + it is mentioned in the description of the setting. Note that using multiple assignments to the + same value makes the file incompatible with parsers for the XDG .desktop + file format. + + + + See Also + + systemd.time7 + + + + diff --git a/man/systemd.target.xml b/man/systemd.target.xml new file mode 100644 index 00000000..3052b177 --- /dev/null +++ b/man/systemd.target.xml @@ -0,0 +1,135 @@ + + + + + + + systemd.target + systemd + + + + systemd.target + 5 + + + + systemd.target + Target unit configuration + + + + target.target + + + + Description + + A unit configuration file whose name ends in + .target encodes information about a target unit + of systemd, which is used for grouping units and as well-known + synchronization points during start-up. + + This unit type has no specific options. See + systemd.unit5 + for the common options of all unit configuration files. The common + configuration items are configured in the generic [Unit] and + [Install] sections. A separate [Target] section does not exist, + since no target-specific options may be configured. + + Target units do not offer any additional functionality on + top of the generic functionality provided by units. They exist + merely to group units via dependencies (useful as boot targets), + and to establish standardized names for synchronization points + used in dependencies between units. Among other things, target + units are a more flexible replacement for SysV runlevels in the + classic SysV init system. (And for compatibility reasons special + target units such as runlevel3.target exist + which are used by the SysV runlevel compatibility code in systemd. + See + systemd.special7 + for details). + + + + Automatic Dependencies + + + Implicit Dependencies + + There are no implicit dependencies for target units. + + + + Default Dependencies + + The following dependencies are added unless + DefaultDependencies=no is set: + + + Target units will automatically complement all + configured dependencies of type Wants= or + Requires= with dependencies of type + After= unless DefaultDependencies=no + is set in the specified units. Note that Wants= or + Requires= must be defined in the target unit itself — if + you for example define Wants=some.target in + some.service, the automatic ordering will not be added. + + Target units automatically gain Conflicts= + and Before= dependencies against + shutdown.target. + + + + + + Example + + + Simple standalone target + + # emergency-net.target + +[Unit] +Description=Emergency Mode with Networking +Requires=emergency.target systemd-networkd.service +After=emergency.target systemd-networkd.service +AllowIsolate=yes + + When adding dependencies to other units, it's important to check if they set + DefaultDependencies=. Service units, unless they set + DefaultDependencies=no, automatically get a dependency on + sysinit.target. In this case, both + emergency.target and systemd-networkd.service + have DefaultDependencies=no, so they are suitable for use + in this target, and do not pull in sysinit.target. + + You can now switch into this emergency mode by running systemctl + isolate emergency-net.target or by passing the option + systemd.unit=emergency-net.target on the kernel command + line. + + Other units can have WantedBy=emergency-net.target in the + [Install] section. After they are enabled using + systemctl enable, they will be started before + emergency-net.target is started. It is also possible to add + arbitrary units as dependencies of emergency.target without + modifying them by using systemctl add-wants. + + + + + + See Also + + systemd1, + systemctl1, + systemd.unit5, + systemd.special7, + systemd.directives7 + + + + diff --git a/man/systemd.time.xml b/man/systemd.time.xml new file mode 100644 index 00000000..dc1e78a1 --- /dev/null +++ b/man/systemd.time.xml @@ -0,0 +1,301 @@ + + + + + + + + systemd.time + systemd + + + + systemd.time + 7 + + + + systemd.time + Time and date specifications + + + + Description + + In systemd, timestamps, time spans, and calendar events are + displayed and may be specified in closely related syntaxes. + + + + Displaying Time Spans + + Time spans refer to time durations. On display, systemd will present time spans as a space-separated series + of time values each suffixed by a time unit. Example: + + 2h 30min + + All specified time values are meant to be added up. The above hence refers to 150 minutes. Display is + locale-independent, only English names for the time units are used. + + + + Parsing Time Spans + + When parsing, systemd will accept the same time span syntax. + Separating spaces may be omitted. The following time units are + understood: + + + usec, us, µs + msec, ms + seconds, second, sec, s + minutes, minute, min, m + hours, hour, hr, h + days, day, d + weeks, week, w + months, month, M (defined as 30.44 days) + years, year, y (defined as 365.25 days) + + + If no time unit is specified, generally seconds are assumed, but some exceptions exist and are marked as + such. In a few cases ns, nsec is accepted too, where the granularity of the + time span permits this. Parsing is generally locale-independent, non-English names for the time units are not + accepted. + + Examples for valid time span specifications: + + 2 h +2hours +48hr +1y 12month +55s500ms +300ms20s 5day + + One can use the timespan command of + systemd-analyze1 + to normalise a textual time span for testing and validation purposes. + + + + Displaying Timestamps + + Timestamps refer to specific, unique points in time. On + display, systemd will format these in the local timezone as + follows: + + Fri 2012-11-23 23:02:15 CET + + The weekday is printed in the abbreviated English language form. The formatting is locale-independent. + + In some cases timestamps are shown in the UTC timezone instead of the local timezone, which is indicated via + the UTC timezone specifier in the output. + + In some cases timestamps are shown with microsecond granularity. In this case the sub-second remainder is + separated by a full stop from the seconds component. + + + + Parsing Timestamps + + When parsing, systemd will accept a similar syntax, but expects no timezone specification, unless it is given + as the literal string UTC (for the UTC timezone), or is specified to be the locally configured + timezone, or the timezone name in the IANA timezone database format. The complete list of timezones + supported on your system can be obtained using the timedatectl list-timezones + (see timedatectl1). + Using IANA format is recommended over local timezone names, as less prone to errors (eg: with local timezone it's possible to + specify daylight saving time in winter, while it's incorrect). The weekday specification is optional, but when + the weekday is specified, it must either be in the abbreviated (Wed) or non-abbreviated + (Wednesday) English language form (case does not matter), and is not subject to the locale + choice of the user. Either the date, or the time part may be omitted, in which case the current date or 00:00:00, + respectively, is assumed. The seconds component of the time may also be omitted, in which case ":00" is + assumed. Year numbers may be specified in full or may be abbreviated (omitting the century). + + A timestamp is considered invalid if a weekday is specified and the date does not match the specified day of + the week. + + When parsing, systemd will also accept a few special + placeholders instead of timestamps: now may be + used to refer to the current time (or of the invocation of the + command that is currently executed). today, + yesterday, and tomorrow refer to + 00:00:00 of the current day, the day before, or the next day, + respectively. + + When parsing, systemd will also accept relative time + specifications. A time span (see above) that is prefixed with + + is evaluated to the current time plus the + specified time span. Correspondingly, a time span that is prefixed + with - is evaluated to the current time minus + the specified time span. Instead of prefixing the time span with + + or -, it may also be + suffixed with a space and the word left or + ago. + + Finally, a timespan prefixed with @ is + evaluated relative to the UNIX time epoch 1st Jan, 1970, + 00:00. + + Examples for valid timestamps and their normalized form (assuming the current time was 2012-11-23 + 18:15:22 and the timezone was UTC+8, for example TZ=:Asia/Shanghai): + + Fri 2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13 + 2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13 + 2012-11-23 11:12:13 UTC → Fri 2012-11-23 19:12:13 + 2012-11-23 → Fri 2012-11-23 00:00:00 + 12-11-23 → Fri 2012-11-23 00:00:00 + 11:12:13 → Fri 2012-11-23 11:12:13 + 11:12 → Fri 2012-11-23 11:12:00 + now → Fri 2012-11-23 18:15:22 + today → Fri 2012-11-23 00:00:00 + today UTC → Fri 2012-11-23 16:00:00 + yesterday → Fri 2012-11-22 00:00:00 + tomorrow → Fri 2012-11-24 00:00:00 +tomorrow Pacific/Auckland → Thu 2012-11-23 19:00:00 + +3h30min → Fri 2012-11-23 21:45:22 + -5s → Fri 2012-11-23 18:15:17 + 11min ago → Fri 2012-11-23 18:04:22 + @1395716396 → Tue 2014-03-25 03:59:56 + + Note that timestamps displayed by remote systems with a non-matching timezone are usually not parsable + locally, as the timezone component is not understood (unless it happens to be UTC). + + Timestamps may also be specified with microsecond granularity. The sub-second remainder is expected separated + by a full stop from the seconds component. Example: + + 2014-03-25 03:59:56.654563 + + In some cases, systemd will display a relative timestamp (relative to the current time, or the time of + invocation of the command) instead of or in addition to an absolute timestamp as described above. A relative + timestamp is formatted as follows: + + 2 months 5 days ago + + Note that a relative timestamp is also accepted where a timestamp is expected (see above). + + Use the timestamp command of + systemd-analyze1 to + validate and normalize timestamps for testing purposes. + + + + Calendar Events + + Calendar events may be used to refer to one or more points + in time in a single expression. They form a superset of the + absolute timestamps explained above: + + Thu,Fri 2012-*-1,5 11:12:13 + + The above refers to 11:12:13 of the first or fifth day of + any month of the year 2012, but only if that day is a Thursday or + Friday. + + The weekday specification is optional. If specified, it + should consist of one or more English language weekday names, + either in the abbreviated (Wed) or non-abbreviated (Wednesday) + form (case does not matter), separated by commas. Specifying two + weekdays separated by .. refers to a range of + continuous weekdays. , and .. + may be combined freely. + + In the date and time specifications, any component may be + specified as * in which case any value will + match. Alternatively, each component can be specified as a list of + values separated by commas. Values may be suffixed with + / and a repetition value, which indicates that + the value itself and the value plus all multiples of the repetition value + are matched. Two values separated by .. may be used + to indicate a range of values; ranges may also be followed with + / and a repetition value. + + A date specification may use ~ to indicate the + last day(s) in a month. For example, *-02~03 means + "the third last day in February," and Mon *-05~07/1 + means "the last Monday in May." + + The seconds component may contain decimal fractions both in + the value and the repetition. All fractions are rounded to 6 + decimal places. + + Either time or date specification may be omitted, in which + case the current day and 00:00:00 is implied, respectively. If the + second component is not specified, :00 is + assumed. + + Timezone can be specified as the literal string UTC, or + the local timezone, similar to the supported syntax of timestamps (see above), or the timezone + in the IANA timezone database format (also see above). + + The following special expressions may be used as shorthands for longer normalized forms: + + minutely → *-*-* *:*:00 + hourly → *-*-* *:00:00 + daily → *-*-* 00:00:00 + monthly → *-*-01 00:00:00 + weekly → Mon *-*-* 00:00:00 + yearly → *-01-01 00:00:00 + quarterly → *-01,04,07,10-01 00:00:00 +semiannually → *-01,07-01 00:00:00 + + + Examples for valid timestamps and their + normalized form: + + Sat,Thu,Mon..Wed,Sat..Sun → Mon..Thu,Sat,Sun *-*-* 00:00:00 + Mon,Sun 12-*-* 2,1:23 → Mon,Sun 2012-*-* 01,02:23:00 + Wed *-1 → Wed *-*-01 00:00:00 + Wed..Wed,Wed *-1 → Wed *-*-01 00:00:00 + Wed, 17:48 → Wed *-*-* 17:48:00 +Wed..Sat,Tue 12-10-15 1:2:3 → Tue..Sat 2012-10-15 01:02:03 + *-*-7 0:0:0 → *-*-07 00:00:00 + 10-15 → *-10-15 00:00:00 + monday *-12-* 17:00 → Mon *-12-* 17:00:00 + Mon,Fri *-*-3,1,2 *:30:45 → Mon,Fri *-*-01,02,03 *:30:45 + 12,14,13,12:20,10,30 → *-*-* 12,13,14:10,20,30:00 + 12..14:10,20,30 → *-*-* 12..14:10,20,30:00 + mon,fri *-1/2-1,3 *:30:45 → Mon,Fri *-01/2-01,03 *:30:45 + 03-05 08:05:40 → *-03-05 08:05:40 + 08:05:40 → *-*-* 08:05:40 + 05:40 → *-*-* 05:40:00 + Sat,Sun 12-05 08:05:40 → Sat,Sun *-12-05 08:05:40 + Sat,Sun 08:05:40 → Sat,Sun *-*-* 08:05:40 + 2003-03-05 05:40 → 2003-03-05 05:40:00 + 05:40:23.4200004/3.1700005 → *-*-* 05:40:23.420000/3.170001 + 2003-02..04-05 → 2003-02..04-05 00:00:00 + 2003-03-05 05:40 UTC → 2003-03-05 05:40:00 UTC + 2003-03-05 → 2003-03-05 00:00:00 + 03-05 → *-03-05 00:00:00 + hourly → *-*-* *:00:00 + daily → *-*-* 00:00:00 + daily UTC → *-*-* 00:00:00 UTC + monthly → *-*-01 00:00:00 + weekly → Mon *-*-* 00:00:00 + weekly Pacific/Auckland → Mon *-*-* 00:00:00 Pacific/Auckland + yearly → *-01-01 00:00:00 + annually → *-01-01 00:00:00 + *:2/3 → *-*-* *:02/3:00 + + Calendar events are used by timer units, see + systemd.timer5 + for details. + + Use the calendar command of + systemd-analyze1 to validate + and normalize calendar time specifications for testing purposes. The tool also calculates when a specified + calendar event would elapse next. + + + + See Also + + systemd1, + journalctl1, + systemd.timer5, + systemd.unit5, + systemd.directives7, + systemd-analyze1 + + + + diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml new file mode 100644 index 00000000..ebf6de4e --- /dev/null +++ b/man/systemd.timer.xml @@ -0,0 +1,350 @@ + + + + + + + systemd.timer + systemd + + + + systemd.timer + 5 + + + + systemd.timer + Timer unit configuration + + + + timer.timer + + + + Description + + A unit configuration file whose name ends in + .timer encodes information about a timer + controlled and supervised by systemd, for timer-based + activation. + + This man page lists the configuration options specific to + this unit type. See + systemd.unit5 + for the common options of all unit configuration files. The common + configuration items are configured in the generic [Unit] and + [Install] sections. The timer specific configuration options are + configured in the [Timer] section. + + For each timer file, a matching unit file must exist, + describing the unit to activate when the timer elapses. By + default, a service by the same name as the timer (except for the + suffix) is activated. Example: a timer file + foo.timer activates a matching service + foo.service. The unit to activate may be + controlled by Unit= (see below). + + Note that in case the unit to activate is already active at the time the timer elapses it is not restarted, + but simply left running. There is no concept of spawning new service instances in this case. Due to this, services + with RemainAfterExit= set (which stay around continuously even after the service's main process + exited) are usually not suitable for activation via repetitive timers, as they will only be activated once, and + then stay around forever. + + + + Automatic Dependencies + + + Implicit Dependencies + + The following dependencies are implicitly added: + + + Timer units automatically gain a Before= + dependency on the service they are supposed to activate. + + + + + Default Dependencies + + The following dependencies are added unless DefaultDependencies=no is set: + + + Timer units will automatically have dependencies of type Requires= and + After= on sysinit.target, a dependency of type Before= + on timers.target, as well as Conflicts= and Before= on + shutdown.target to ensure that they are stopped cleanly prior to system shutdown. Only timer + units involved with early boot or late system shutdown should disable the + DefaultDependencies= option. + + Timer units + with at least one OnCalendar= directive will have an additional After= + dependency on time-sync.target to avoid being started before the system clock has been + correctly set. + + + + + + Options + + Timer files must include a [Timer] section, which carries + information about the timer it defines. The options specific to + the [Timer] section of timer units are the following: + + + + OnActiveSec= + OnBootSec= + OnStartupSec= + OnUnitActiveSec= + OnUnitInactiveSec= + + Defines monotonic timers relative to different + starting points: + + + Settings and their starting points + + + + + Setting + Meaning + + + + + OnActiveSec= + Defines a timer relative to the moment the timer unit itself is activated. + + + OnBootSec= + Defines a timer relative to when the machine was booted up. In containers, for the system manager instance, this is mapped to OnStartupSec=, making both equivalent. + + + OnStartupSec= + Defines a timer relative to when the service manager was first started. For system timer units this is very similar to OnBootSec= as the system service manager is generally started very early at boot. It's primarily useful when configured in units running in the per-user service manager, as the user service manager is generally started on first login only, not already during boot. + + + OnUnitActiveSec= + Defines a timer relative to when the unit the timer unit is activating was last activated. + + + OnUnitInactiveSec= + Defines a timer relative to when the unit the timer unit is activating was last deactivated. + + + +
+ + Multiple directives may be combined of the same and of different types, in which case the timer + unit will trigger whenever any of the specified timer expressions elapse. For example, by combining + OnBootSec= and OnUnitActiveSec=, it is possible to define a + timer that elapses in regular intervals and activates a specific service each time. Moreover, both + monotonic time expressions and OnCalendar= calendar expressions may be combined in + the same timer unit. + + The arguments to the directives are time spans + configured in seconds. Example: "OnBootSec=50" means 50s after + boot-up. The argument may also include time units. Example: + "OnBootSec=5h 30min" means 5 hours and 30 minutes after + boot-up. For details about the syntax of time spans, see + systemd.time7. + + If a timer configured with OnBootSec= + or OnStartupSec= is already in the past + when the timer unit is activated, it will immediately elapse + and the configured unit is started. This is not the case for + timers defined in the other directives. + + These are monotonic timers, independent of wall-clock time and timezones. If the computer is + temporarily suspended, the monotonic clock pauses, too. + + If the empty string is assigned to any of these options, the list of timers is reset (both + monotonic timers and OnCalendar= timers, see below), and all prior assignments + will have no effect. + + Note that timers do not necessarily expire at the + precise time configured with these settings, as they are + subject to the AccuracySec= setting + below.
+ +
+ + + OnCalendar= + + Defines realtime (i.e. wallclock) timers with + calendar event expressions. See + systemd.time7 + for more information on the syntax of calendar event + expressions. Otherwise, the semantics are similar to + OnActiveSec= and related settings. + + Note that timers do not necessarily expire at the + precise time configured with this setting, as it is subject to + the AccuracySec= setting + below. + + May be specified more than once, in which case the timer unit will trigger whenever any of the + specified expressions elapse. Moreover calendar timers and monotonic timers (see above) may be + combined within the same timer unit. + + If the empty string is assigned to any of these options, the list of timers is reset (both + OnCalendar= timers and monotonic timers, see above), and all prior assignments + will have no effect. + + + + AccuracySec= + + Specify the accuracy the timer shall elapse + with. Defaults to 1min. The timer is scheduled to elapse + within a time window starting with the time specified in + OnCalendar=, + OnActiveSec=, + OnBootSec=, + OnStartupSec=, + OnUnitActiveSec= or + OnUnitInactiveSec= and ending the time + configured with AccuracySec= later. Within + this time window, the expiry time will be placed at a + host-specific, randomized, but stable position that is + synchronized between all local timer units. This is done in + order to optimize power consumption to suppress unnecessary + CPU wake-ups. To get best accuracy, set this option to + 1us. Note that the timer is still subject to the timer slack + configured via + systemd-system.conf5's + TimerSlackNSec= setting. See + prctl2 + for details. To optimize power consumption, make sure to set + this value as high as possible and as low as + necessary. + + + + RandomizedDelaySec= + + Delay the timer by a randomly selected, evenly + distributed amount of time between 0 and the specified time + value. Defaults to 0, indicating that no randomized delay + shall be applied. Each timer unit will determine this delay + randomly before each iteration, and the delay will simply be + added on top of the next determined elapsing time. This is + useful to stretch dispatching of similarly configured timer + events over a certain amount time, to avoid that they all fire + at the same time, possibly resulting in resource + congestion. Note the relation to + AccuracySec= above: the latter allows the + service manager to coalesce timer events within a specified + time range in order to minimize wakeups, the former does the + opposite: it stretches timer events over a time range, to make + it unlikely that they fire simultaneously. If + RandomizedDelaySec= and + AccuracySec= are used in conjunction, first + the randomized delay is added, and then the result is + possibly further shifted to coalesce it with other timer + events happening on the system. As mentioned above + AccuracySec= defaults to 1min and + RandomizedDelaySec= to 0, thus encouraging + coalescing of timer events. In order to optimally stretch + timer events over a certain range of time, make sure to set + RandomizedDelaySec= to a higher value, and + AccuracySec=1us. + + + + OnClockChange= + OnTimezoneChange= + + These options take boolean arguments. When true, the service unit will be triggered + when the system clock (CLOCK_REALTIME) jumps relative to the monotonic clock + (CLOCK_MONOTONIC), or when the local system timezone is modified. These options + can be used alone or in combination with other timer expressions (see above) within the same timer + unit. These options default to false. + + + + Unit= + + The unit to activate when this timer elapses. + The argument is a unit name, whose suffix is not + .timer. If not specified, this value + defaults to a service that has the same name as the timer + unit, except for the suffix. (See above.) It is recommended + that the unit name that is activated and the unit name of the + timer unit are named identically, except for the + suffix. + + + + Persistent= + + Takes a boolean argument. If true, the time when the service unit was last triggered + is stored on disk. When the timer is activated, the service unit is triggered immediately if it + would have been triggered at least once during the time when the timer was inactive. This is useful + to catch up on missed runs of the service when the system was powered down. Note that this setting + only has an effect on timers configured with OnCalendar=. Defaults to + false. + + Use systemctl clean --what=state … on the timer unit to remove the timestamp + file maintained by this option from disk. In particular, use this command before uninstalling a timer + unit. See + systemctl1 for + details. + + + + WakeSystem= + + Takes a boolean argument. If true, an elapsing timer will cause the system to resume + from suspend, should it be suspended and if the system supports this. Note that this option will only + make sure the system resumes on the appropriate times, it will not take care of suspending it again + after any work that is to be done is finished. Defaults to + false. + + Note that this functionality requires privileges and is thus generally only available in the + system service manager. + + + + RemainAfterElapse= + + Takes a boolean argument. If true, an elapsed + timer will stay loaded, and its state remains queryable. If + false, an elapsed timer unit that cannot elapse anymore is + unloaded. Turning this off is particularly useful for + transient timer units that shall disappear after they first + elapse. Note that this setting has an effect on repeatedly + starting a timer unit that only elapses once: if + RemainAfterElapse= is on, it will not be + started again, and is guaranteed to elapse only once. However, + if RemainAfterElapse= is off, it might be + started again if it is already elapsed, and thus be triggered + multiple times. Defaults to + yes. + +
+
+ + + See Also + + systemd1, + systemctl1, + systemd.unit5, + systemd.service5, + systemd.time7, + systemd.directives7, + systemd-system.conf5, + prctl2 + + + +
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml new file mode 100644 index 00000000..8e2765c8 --- /dev/null +++ b/man/systemd.unit.xml @@ -0,0 +1,1993 @@ + + +%entities; +]> + + + + + + systemd.unit + systemd + + + + systemd.unit + 5 + + + + systemd.unit + Unit configuration + + + + service.service, + socket.socket, + device.device, + mount.mount, + automount.automount, + swap.swap, + target.target, + path.path, + timer.timer, + slice.slice, + scope.scope + + + System Unit Search Path + + /etc/systemd/system.control/* +/run/systemd/system.control/* +/run/systemd/transient/* +/run/systemd/generator.early/* +/etc/systemd/system/* +/etc/systemd/systemd.attached/* +/run/systemd/system/* +/run/systemd/systemd.attached/* +/run/systemd/generator/* +… +/usr/lib/systemd/system/* +/run/systemd/generator.late/* + + + + User Unit Search Path + ~/.config/systemd/user.control/* +$XDG_RUNTIME_DIR/systemd/user.control/* +$XDG_RUNTIME_DIR/systemd/transient/* +$XDG_RUNTIME_DIR/systemd/generator.early/* +~/.config/systemd/user/* +/etc/systemd/user/* +$XDG_RUNTIME_DIR/systemd/user/* +/run/systemd/user/* +$XDG_RUNTIME_DIR/systemd/generator/* +~/.local/share/systemd/user/* +… +/usr/lib/systemd/user/* +$XDG_RUNTIME_DIR/systemd/generator.late/* + + + + + + Description + + A unit file is a plain text ini-style file that encodes information about a service, a + socket, a device, a mount point, an automount point, a swap file or partition, a start-up + target, a watched file system path, a timer controlled and supervised by + systemd1, a + resource management slice or a group of externally created processes. See + systemd.syntax5 + for a general description of the syntax. + + This man page lists the common configuration options of all + the unit types. These options need to be configured in the [Unit] + or [Install] sections of the unit files. + + In addition to the generic [Unit] and [Install] sections + described here, each unit may have a type-specific section, e.g. + [Service] for a service unit. See the respective man pages for + more information: + systemd.service5, + systemd.socket5, + systemd.device5, + systemd.mount5, + systemd.automount5, + systemd.swap5, + systemd.target5, + systemd.path5, + systemd.timer5, + systemd.slice5, + systemd.scope5. + + + Unit files are loaded from a set of paths determined during compilation, described in the next + section. + + Valid unit names consist of a "name prefix" and a dot and a suffix specifying the unit type. The + "unit prefix" must consist of one or more valid characters (ASCII letters, digits, :, + -, _, ., and \). The total + length of the unit name including the suffix must not exceed 256 characters. The type suffix must be one + of .service, .socket, .device, + .mount, .automount, .swap, + .target, .path, .timer, + .slice, or .scope. + + Units names can be parameterized by a single argument called the "instance name". The unit is then + constructed based on a "template file" which serves as the definition of multiple services or other + units. A template unit must have a single @ at the end of the name (right before the + type suffix). The name of the full unit is formed by inserting the instance name between + @ and the unit type suffix. In the unit file itself, the instance parameter may be + referred to using %i and other specifiers, see below. + + Unit files may contain additional options on top of those + listed here. If systemd encounters an unknown option, it will + write a warning log message but continue loading the unit. If an + option or section name is prefixed with , it is + ignored completely by systemd. Options within an ignored section + do not need the prefix. Applications may use this to include + additional information in the unit files. + + Units can be aliased (have an alternative name), by creating a symlink from the new name to the + existing name in one of the unit search paths. For example, systemd-networkd.service + has the alias dbus-org.freedesktop.network1.service, created during installation as + a symlink, so when systemd is asked through D-Bus to load + dbus-org.freedesktop.network1.service, it'll load + systemd-networkd.service. Alias names may be used in commands like + disable, start, stop, status, + and similar, and in all unit dependency directives, including Wants=, + Requires=, Before=, After=. Aliases cannot be + used with the preset command. + + Unit files may specify aliases through the Alias= directive in the [Install] + section. When the unit is enabled, symlinks will be created for those names, and removed when the unit is + disabled. For example, reboot.target specifies + Alias=ctrl-alt-del.target, so when enabled, the symlink + /etc/systemd/systemd/ctrl-alt-del.service pointing to the + reboot.target file will be created, and when + CtrlAltDel is invoked, + systemd will look for the ctrl-alt-del.service and execute + reboot.service. systemd does not look at the [Install] section at + all during normal operation, so any directives in that section only have an effect through the symlinks + created during enablement. + + Along with a unit file foo.service, the directory + foo.service.wants/ may exist. All unit files symlinked from such a directory are + implicitly added as dependencies of type Wants= to the unit. Similar functionality + exists for Requires= type dependencies as well, the directory suffix is + .requires/ in this case. This functionality is useful to hook units into the + start-up of other units, without having to modify their unit files. For details about the semantics of + Wants=, see below. The preferred way to create symlinks in the + .wants/ or .requires/ directory of a unit file is by embedding + the dependency in [Install] section of the target unit, and creating the symlink in the file system with + the enable or preset commands of + systemctl1. + + Along with a unit file foo.service, a "drop-in" directory + foo.service.d/ may exist. All files with the suffix .conf from this + directory will be parsed after the unit file itself is parsed. This is useful to alter or add configuration + settings for a unit, without having to modify unit files. Drop-in files must contain appropriate section + headers. For instantiated units, this logic will first look for the instance .d/ subdirectory + (e.g. foo@bar.service.d/) and read its .conf files, followed by the template + .d/ subdirectory (e.g. foo@.service.d/) and the .conf + files there. Moreover for units names containing dashes (-), the set of directories generated by + truncating the unit name after all dashes is searched too. Specifically, for a unit name + foo-bar-baz.service not only the regular drop-in directory + foo-bar-baz.service.d/ is searched but also both foo-bar-.service.d/ and + foo-.service.d/. This is useful for defining common drop-ins for a set of related units, whose + names begin with a common prefix. This scheme is particularly useful for mount, automount and slice units, whose + systematic naming structure is built around dashes as component separators. Note that equally named drop-in files + further down the prefix hierarchy override those further up, + i.e. foo-bar-.service.d/10-override.conf overrides + foo-.service.d/10-override.conf. + + In addition to /etc/systemd/system, the drop-in .d/ + directories for system services can be placed in /usr/lib/systemd/system or + /run/systemd/system directories. Drop-in files in /etc + take precedence over those in /run which in turn take precedence over those + in /usr/lib. Drop-in files under any of these directories take precedence + over unit files wherever located. Multiple drop-in files with different names are applied in + lexicographic order, regardless of which of the directories they reside in. + + Units also support a top-level drop-in with type.d/, + where type may be e.g. service or socket, + that allows altering or adding to the settings of all corresponding unit files on the system. + The formatting and precedence of applying drop-in configurations follow what is defined above. + Configurations in type.d/ have the lowest precedence + compared to settings in the name specific override directories. So the contents of + foo-.service.d/10-override.conf would override + service.d/10-override.conf. + + + + Note that while systemd offers a flexible dependency system + between units it is recommended to use this functionality only + sparingly and instead rely on techniques such as bus-based or + socket-based activation which make dependencies implicit, + resulting in a both simpler and more flexible system. + + As mentioned above, a unit may be instantiated from a template file. This allows creation + of multiple units from a single configuration file. If systemd looks for a unit configuration + file, it will first search for the literal unit name in the file system. If that yields no + success and the unit name contains an @ character, systemd will look for a + unit template that shares the same name but with the instance string (i.e. the part between the + @ character and the suffix) removed. Example: if a service + getty@tty3.service is requested and no file by that name is found, systemd + will look for getty@.service and instantiate a service from that + configuration file if it is found. + + To refer to the instance string from within the + configuration file you may use the special %i + specifier in many of the configuration options. See below for + details. + + If a unit file is empty (i.e. has the file size 0) or is + symlinked to /dev/null, its configuration + will not be loaded and it appears with a load state of + masked, and cannot be activated. Use this as an + effective way to fully disable a unit, making it impossible to + start it even manually. + + The unit file format is covered by the + Interface + Stability Promise. + + + + + String Escaping for Inclusion in Unit Names + + Sometimes it is useful to convert arbitrary strings into unit names. To facilitate this, a method of string + escaping is used, in order to map strings containing arbitrary byte values (except NUL) into valid unit names and + their restricted character set. A common special case are unit names that reflect paths to objects in the file + system hierarchy. Example: a device unit dev-sda.device refers to a device with the device + node /dev/sda in the file system. + + The escaping algorithm operates as follows: given a string, any / character is replaced by + -, and all other characters which are not ASCII alphanumerics or _ are + replaced by C-style \x2d escapes. In addition, . is replaced with such a + C-style escape when it would appear as the first character in the escaped string. + + When the input qualifies as absolute file system path, this algorithm is extended slightly: the path to the + root directory / is encoded as single dash -. In addition, any leading, + trailing or duplicate / characters are removed from the string before transformation. Example: + /foo//bar/baz/ becomes foo-bar-baz. + + This escaping is fully reversible, as long as it is known whether the escaped string was a path (the + unescaping results are different for paths and non-path strings). The + systemd-escape1 command may be + used to apply and reverse escaping on arbitrary strings. Use systemd-escape --path to escape + path strings, and systemd-escape without otherwise. + + + + Automatic dependencies + + + Implicit Dependencies + + A number of unit dependencies are implicitly established, depending on unit type and + unit configuration. These implicit dependencies can make unit configuration file cleaner. For + the implicit dependencies in each unit type, please refer to section "Implicit Dependencies" + in respective man pages. + + For example, service units with Type=dbus automatically acquire + dependencies of type Requires= and After= on + dbus.socket. See + systemd.service5 + for details. + + + + Default Dependencies + + Default dependencies are similar to implicit dependencies, but can be turned on and off + by setting DefaultDependencies= to yes (the default) and + no, while implicit dependencies are always in effect. See section "Default + Dependencies" in respective man pages for the effect of enabling + DefaultDependencies= in each unit types. + + For example, target units will complement all configured dependencies of type + Wants= or Requires= with dependencies of type + After= unless DefaultDependencies=no is set in the + specified units. See + systemd.target5 + for details. Note that this behavior can be turned off by setting + DefaultDependencies=no. + + + + + Unit File Load Path + + Unit files are loaded from a set of paths determined during + compilation, described in the two tables below. Unit files found + in directories listed earlier override files with the same name in + directories lower in the list. + + When the variable $SYSTEMD_UNIT_PATH is set, + the contents of this variable overrides the unit load path. If + $SYSTEMD_UNIT_PATH ends with an empty component + (:), the usual unit load path will be appended + to the contents of the variable. + + + + Load path when running in system mode (<option>--system</option>). + + + + + + + + Path + Description + + + + + /etc/systemd/system.control + Persistent and transient configuration created using the dbus API + + + /run/systemd/system.control + + + /run/systemd/transient + Dynamic configuration for transient units + + + /run/systemd/generator.early + Generated units with high priority (see early-dir in systemd.generator7) + + + /etc/systemd/system + System units created by the administrator + + + /run/systemd/system + Runtime units + + + /run/systemd/generator + Generated units with medium priority (see normal-dir in systemd.generator7) + + + /usr/local/lib/systemd/system + System units installed by the administrator + + + /usr/lib/systemd/system + System units installed by the distribution package manager + + + /run/systemd/generator.late + Generated units with low priority (see late-dir in systemd.generator7) + + + +
+ + + + Load path when running in user mode (<option>--user</option>). + + + + + + + + Path + Description + + + + + $XDG_CONFIG_HOME/systemd/user.control or ~/.config/systemd/user.control + Persistent and transient configuration created using the dbus API ($XDG_CONFIG_HOME is used if set, ~/.config otherwise) + + + $XDG_RUNTIME_DIR/systemd/user.control + + + /run/systemd/transient + Dynamic configuration for transient units + + + /run/systemd/generator.early + Generated units with high priority (see early-dir in systemd.generator7) + + + $XDG_CONFIG_HOME/systemd/user or $HOME/.config/systemd/user + User configuration ($XDG_CONFIG_HOME is used if set, ~/.config otherwise) + + + /etc/systemd/user + User units created by the administrator + + + $XDG_RUNTIME_DIR/systemd/user + Runtime units (only used when $XDG_RUNTIME_DIR is set) + + + /run/systemd/user + Runtime units + + + $XDG_RUNTIME_DIR/systemd/generator + Generated units with medium priority (see normal-dir in systemd.generator7) + + + $XDG_DATA_HOME/systemd/user or $HOME/.local/share/systemd/user + Units of packages that have been installed in the home directory ($XDG_DATA_HOME is used if set, ~/.local/share otherwise) + + + $dir/systemd/user for each $dir in $XDG_DATA_DIRS + Additional locations for installed user units, one for each entry in $XDG_DATA_DIRS + + + /usr/local/lib/systemd/user + User units installed by the administrator + + + /usr/lib/systemd/user + User units installed by the distribution package manager + + + $XDG_RUNTIME_DIR/systemd/generator.late + Generated units with low priority (see late-dir in systemd.generator7) + + + +
+ + The set of load paths for the user manager instance may be augmented or + changed using various environment variables. And environment variables may in + turn be set using environment generators, see + systemd.environment-generator7. + In particular, $XDG_DATA_HOME and + $XDG_DATA_DIRS may be easily set using + systemd-environment-d-generator8. + Thus, directories listed here are just the defaults. To see the actual list that + would be used based on compilation options and current environment use + systemd-analyze --user unit-paths + + + Moreover, additional units might be loaded into systemd from + directories not on the unit load path by creating a symlink pointing to a + unit file in the directories. You can use systemctl link + for this operation. See + systemctl1 + for its usage and precaution. + +
+ + + Unit Garbage Collection + + The system and service manager loads a unit's configuration automatically when a unit is referenced for the + first time. It will automatically unload the unit configuration and state again when the unit is not needed anymore + ("garbage collection"). A unit may be referenced through a number of different mechanisms: + + + Another loaded unit references it with a dependency such as After=, + Wants=, … + + The unit is currently starting, running, reloading or stopping. + + The unit is currently in the failed state. (But see below.) + + A job for the unit is pending. + + The unit is pinned by an active IPC client program. + + The unit is a special "perpetual" unit that is always active and loaded. Examples for perpetual + units are the root mount unit -.mount or the scope unit init.scope that + the service manager itself lives in. + + The unit has running processes associated with it. + + + The garbage collection logic may be altered with the CollectMode= option, which allows + configuration whether automatic unloading of units that are in failed state is permissible, + see below. + + Note that when a unit's configuration and state is unloaded, all execution results, such as exit codes, exit + signals, resource consumption and other statistics are lost, except for what is stored in the log subsystem. + + Use systemctl daemon-reload or an equivalent command to reload unit configuration while + the unit is already loaded. In this case all configuration settings are flushed out and replaced with the new + configuration (which however might not be in effect immediately), however all runtime state is + saved/restored. + + + + [Unit] Section Options + + The unit file may include a [Unit] section, which carries + generic information about the unit that is not dependent on the + type of unit: + + + + Description= + A human readable name for the unit. This is used by + systemd (and other UIs) as the label for the unit, so this string should + identify the unit rather than describe it, despite the name. Apache2 Web + Server is a good example. Bad examples are high-performance light-weight + HTTP server (too generic) or Apache2 (too specific and + meaningless for people who do not know Apache). systemd will use this + string as a noun in status messages (Starting + description..., Started + description., Reached target + description., Failed to start + description.), so it should be capitalized, and should + not be a full sentence or a phrase with a continuous verb. Bad examples include + exiting the container or updating the database once per + day.. + + + + + Documentation= + A space-separated list of URIs referencing + documentation for this unit or its configuration. Accepted are + only URIs of the types http://, + https://, file:, + info:, man:. For more + information about the syntax of these URIs, see uri7. + The URIs should be listed in order of relevance, starting with + the most relevant. It is a good idea to first reference + documentation that explains what the unit's purpose is, + followed by how it is configured, followed by any other + related documentation. This option may be specified more than + once, in which case the specified list of URIs is merged. If + the empty string is assigned to this option, the list is reset + and all prior assignments will have no + effect. + + + + Wants= + + Configures requirement dependencies on other units. This option may be specified more + than once or multiple space-separated units may be specified in one option in which case dependencies + for all listed names will be created. Dependencies of this type may also be configured outside of the + unit configuration file by adding a symlink to a .wants/ directory accompanying + the unit file. For details, see above. + + Units listed in this option will be started if the configuring unit is. However, if the listed + units fail to start or cannot be added to the transaction, this has no impact on the validity of the + transaction as a whole, and this unit will still be started. This is the recommended way to hook + start-up of one unit to the start-up of another unit. + + Note that requirement dependencies do not influence the order in which services are started or + stopped. This has to be configured independently with the After= or + Before= options. If unit foo.service pulls in unit + bar.service as configured with Wants= and no ordering is + configured with After= or Before=, then both units will be + started simultaneously and without any delay between them if foo.service is + activated. + + + + Requires= + + Similar to Wants=, but declares a stronger + dependency. Dependencies of this type may also be configured by adding a symlink to a + .requires/ directory accompanying the unit file. + + If this unit gets activated, the units listed will be activated as well. If one of + the other units fails to activate, and an ordering dependency After= on the + failing unit is set, this unit will not be started. Besides, with or without specifying + After=, this unit will be stopped if one of the other units is explicitly + stopped. + + Often, it is a better choice to use Wants= instead of + Requires= in order to achieve a system that is more robust when dealing with + failing services. + + Note that this dependency type does not imply that the other unit always has to be in active state when + this unit is running. Specifically: failing condition checks (such as ConditionPathExists=, + ConditionPathIsSymbolicLink=, … — see below) do not cause the start job of a unit with a + Requires= dependency on it to fail. Also, some unit types may deactivate on their own (for + example, a service process may decide to exit cleanly, or a device may be unplugged by the user), which is not + propagated to units having a Requires= dependency. Use the BindsTo= + dependency type together with After= to ensure that a unit may never be in active state + without a specific other unit also in active state (see below). + + + + Requisite= + + Similar to Requires=. However, if the units listed here + are not started already, they will not be started and the starting of this unit will fail + immediately. Requisite= does not imply an ordering dependency, even if + both units are started in the same transaction. Hence this setting should usually be + combined with After=, to ensure this unit is not started before the other + unit. + + When Requisite=b.service is used on + a.service, this dependency will show as + RequisiteOf=a.service in property listing of + b.service. RequisiteOf= + dependency cannot be specified directly. + + + + + BindsTo= + + Configures requirement dependencies, very similar in style to + Requires=. However, this dependency type is stronger: in addition to the effect of + Requires= it declares that if the unit bound to is stopped, this unit will be stopped + too. This means a unit bound to another unit that suddenly enters inactive state will be stopped too. + Units can suddenly, unexpectedly enter inactive state for different reasons: the main process of a service unit + might terminate on its own choice, the backing device of a device unit might be unplugged or the mount point of + a mount unit might be unmounted without involvement of the system and service manager. + + When used in conjunction with After= on the same unit the behaviour of + BindsTo= is even stronger. In this case, the unit bound to strictly has to be in active + state for this unit to also be in active state. This not only means a unit bound to another unit that suddenly + enters inactive state, but also one that is bound to another unit that gets skipped due to a failed condition + check (such as ConditionPathExists=, ConditionPathIsSymbolicLink=, … — + see below) will be stopped, should it be running. Hence, in many cases it is best to combine + BindsTo= with After=. + + When BindsTo=b.service is used on + a.service, this dependency will show as + BoundBy=a.service in property listing of + b.service. BoundBy= + dependency cannot be specified directly. + + + + + PartOf= + + Configures dependencies similar to + Requires=, but limited to stopping and + restarting of units. When systemd stops or restarts the units + listed here, the action is propagated to this unit. Note that + this is a one-way dependency — changes to this unit do not + affect the listed units. + + When PartOf=b.service is used on + a.service, this dependency will show as + ConsistsOf=a.service in property listing of + b.service. ConsistsOf= + dependency cannot be specified directly. + + + + + Conflicts= + + A space-separated list of unit names. Configures negative requirement + dependencies. If a unit has a Conflicts= setting on another unit, starting the + former will stop the latter and vice versa. + + Note that this setting does not imply an ordering dependency, similarly to the + Wants= and Requires= dependencies described above. This means + that to ensure that the conflicting unit is stopped before the other unit is started, an + After= or Before= dependency must be declared. It doesn't + matter which of the two ordering dependencies is used, because stop jobs are always ordered before + start jobs, see the discussion in Before=/After= below. + + If unit A that conflicts with unit B is scheduled to + be started at the same time as B, the transaction will either + fail (in case both are required parts of the transaction) or be + modified to be fixed (in case one or both jobs are not a + required part of the transaction). In the latter case, the job + that is not required will be removed, or in case both are + not required, the unit that conflicts will be started and the + unit that is conflicted is stopped. + + + + Before= + After= + + These two settings expect a space-separated list of unit names. They may be specified + more than once, in which case dependencies for all listed names are created. + + Those two setttings configure ordering dependencies between units. If unit + foo.service contains the setting and both + units are being started, bar.service's start-up is delayed until + foo.service has finished starting up. After= is the inverse + of Before=, i.e. while Before= ensures that the configured unit + is started before the listed unit begins starting up, After= ensures the opposite, + that the listed unit is fully started up before the configured unit is started. + + When two units with an ordering dependency between them are shut down, the inverse of the + start-up order is applied. i.e. if a unit is configured with After= on another + unit, the former is stopped before the latter if both are shut down. Given two units with any + ordering dependency between them, if one unit is shut down and the other is started up, the shutdown + is ordered before the start-up. It doesn't matter if the ordering dependency is + After= or Before=, in this case. It also doesn't matter which + of the two is shut down, as long as one is shut down and the other is started up; the shutdown is + ordered before the start-up in all cases. If two units have no ordering dependencies between them, + they are shut down or started up simultaneously, and no ordering takes place. It depends on the unit + type when precisely a unit has finished starting up. Most importantly, for service units start-up is + considered completed for the purpose of Before=/After= when all + its configured start-up commands have been invoked and they either failed or reported start-up + success. + + Note that those settings are independent of and orthogonal to the requirement dependencies as + configured by Requires=, Wants=, Requisite=, + or BindsTo=. It is a common pattern to include a unit name in both the + After= and Wants= options, in which case the unit listed will + be started before the unit that is configured with these options. + + + + OnFailure= + + A space-separated list of one or more units + that are activated when this unit enters the + failed state. A service unit using + Restart= enters the failed state only after + the start limits are reached. + + + + PropagatesReloadTo= + ReloadPropagatedFrom= + + A space-separated list of one or more units + where reload requests on this unit will be propagated to, or + reload requests on the other unit will be propagated to this + unit, respectively. Issuing a reload request on a unit will + automatically also enqueue a reload request on all units that + the reload request shall be propagated to via these two + settings. + + + + JoinsNamespaceOf= + + For units that start processes (such as service units), lists one or more other units + whose network and/or temporary file namespace to join. This only applies to unit types which support + the PrivateNetwork=, NetworkNamespacePath= and + PrivateTmp= directives (see + systemd.exec5 for + details). If a unit that has this setting set is started, its processes will see the same + /tmp, /var/tmp and network namespace as one listed unit + that is started. If multiple listed units are already started, it is not defined which namespace is + joined. Note that this setting only has an effect if + PrivateNetwork=/NetworkNamespacePath= and/or + PrivateTmp= is enabled for both the unit that joins the namespace and the unit + whose namespace is joined. + + + + RequiresMountsFor= + + Takes a space-separated list of absolute + paths. Automatically adds dependencies of type + Requires= and After= for + all mount units required to access the specified path. + + Mount points marked with are not + mounted automatically through local-fs.target, + but are still honored for the purposes of this option, i.e. they + will be pulled in by this unit. + + + + OnFailureJobMode= + + Takes a value of + fail, + replace, + replace-irreversibly, + isolate, + flush, + ignore-dependencies or + ignore-requirements. Defaults to + replace. Specifies how the units listed in + OnFailure= will be enqueued. See + systemctl1's + option for details on the + possible values. If this is set to isolate, + only a single unit may be listed in + OnFailure=.. + + + + IgnoreOnIsolate= + + Takes a boolean argument. If , this unit + will not be stopped when isolating another unit. Defaults to + for service, target, socket, busname, timer, and path + units, and for slice, scope, device, swap, mount, and + automount units. + + + + StopWhenUnneeded= + + Takes a boolean argument. If + , this unit will be stopped when it is no + longer used. Note that, in order to minimize the work to be + executed, systemd will not stop units by default unless they + are conflicting with other units, or the user explicitly + requested their shut down. If this option is set, a unit will + be automatically cleaned up if no other active unit requires + it. Defaults to . + + + + RefuseManualStart= + RefuseManualStop= + + Takes a boolean argument. If + , this unit can only be activated or + deactivated indirectly. In this case, explicit start-up or + termination requested by the user is denied, however if it is + started or stopped as a dependency of another unit, start-up + or termination will succeed. This is mostly a safety feature + to ensure that the user does not accidentally activate units + that are not intended to be activated explicitly, and not + accidentally deactivate units that are not intended to be + deactivated. These options default to + . + + + + AllowIsolate= + + Takes a boolean argument. If + , this unit may be used with the + systemctl isolate command. Otherwise, this + will be refused. It probably is a good idea to leave this + disabled except for target units that shall be used similar to + runlevels in SysV init systems, just as a precaution to avoid + unusable system states. This option defaults to + . + + + + DefaultDependencies= + + Takes a boolean argument. If + , (the default), a few default + dependencies will implicitly be created for the unit. The + actual dependencies created depend on the unit type. For + example, for service units, these dependencies ensure that the + service is started only after basic system initialization is + completed and is properly terminated on system shutdown. See + the respective man pages for details. Generally, only services + involved with early boot or late shutdown should set this + option to . It is highly recommended to + leave this option enabled for the majority of common units. If + set to , this option does not disable + all implicit dependencies, just non-essential + ones. + + + + CollectMode= + + Tweaks the "garbage collection" algorithm for this unit. Takes one of + or . If set to the unit will be unloaded if it is + in the inactive state and is not referenced by clients, jobs or other units — however it + is not unloaded if it is in the failed state. In mode, failed + units are not unloaded until the user invoked systemctl reset-failed on them to reset the + failed state, or an equivalent command. This behaviour is altered if this option is set to + : in this case the unit is unloaded even if the unit is in a + failed state, and thus an explicitly resetting of the failed state is + not necessary. Note that if this mode is used unit results (such as exit codes, exit signals, consumed + resources, …) are flushed out immediately after the unit completed, except for what is stored in the logging + subsystem. Defaults to . + + + + + FailureAction= + SuccessAction= + + Configure the action to take when the unit stops and enters a failed state or inactive state. + Takes one of , , , + , , , + , , and . In system mode, + all options are allowed. In user mode, only , , and + are allowed. Both options default to . + + If is set, no action will be triggered. causes a reboot + following the normal shutdown procedure (i.e. equivalent to systemctl reboot). + causes a forced reboot which will terminate all processes forcibly but should + cause no dirty file systems on reboot (i.e. equivalent to systemctl reboot -f) and + causes immediate execution of the + reboot2 system call, which + might result in data loss (i.e. equivalent to systemctl reboot -ff). Similarly, + , , have the effect + of powering down the system with similar semantics. causes the manager to exit following + the normal shutdown procedure, and causes it terminate without shutting down + services. When or is used by default the exit status of the + main process of the unit (if this applies) is returned from the service manager. However, this may be overridden + with FailureActionExitStatus=/SuccessActionExitStatus=, see + below. + + + + FailureActionExitStatus= + SuccessActionExitStatus= + + Controls the exit status to propagate back to an invoking container manager (in case of a + system service) or service manager (in case of a user manager) when the + FailureAction=/SuccessAction= are set to or + and the action is triggered. By default the exit status of the main process of the + triggering unit (if this applies) is propagated. Takes a value in the range 0…255 or the empty string to + request default behaviour. + + + + JobTimeoutSec= + JobRunningTimeoutSec= + + When a job for this unit is queued, a timeout JobTimeoutSec= may be + configured. Similarly, JobRunningTimeoutSec= starts counting when the queued job is actually + started. If either time limit is reached, the job will be cancelled, the unit however will not change state or + even enter the failed mode. This value defaults to infinity (job timeouts + disabled), except for device units (JobRunningTimeoutSec= defaults to + DefaultTimeoutStartSec=). NB: this timeout is independent from any unit-specific timeout + (for example, the timeout set with TimeoutStartSec= in service units) as the job timeout has + no effect on the unit itself, only on the job that might be pending for it. Or in other words: unit-specific + timeouts are useful to abort unit state changes, and revert them. The job timeout set with this option however + is useful to abort only the job waiting for the unit state to change. + + + + + JobTimeoutAction= + JobTimeoutRebootArgument= + + JobTimeoutAction= optionally configures an additional action to take when + the timeout is hit, see description of JobTimeoutSec= and + JobRunningTimeoutSec= above. It takes the same values as + StartLimitAction=. Defaults to . + JobTimeoutRebootArgument= configures an optional reboot string to pass to the + reboot2 system call. + + + + + StartLimitIntervalSec=interval + StartLimitBurst=burst + + Configure unit start rate limiting. Units which are started more than + burst times within an interval time interval are not + permitted to start any more. Use StartLimitIntervalSec= to configure the checking interval + (defaults to DefaultStartLimitIntervalSec= in manager configuration file, set it to 0 to + disable any kind of rate limiting). Use StartLimitBurst= to configure how many starts per + interval are allowed (defaults to DefaultStartLimitBurst= in manager configuration + file). These configuration options are particularly useful in conjunction with the service setting + Restart= (see + systemd.service5); however, + they apply to all kinds of starts (including manual), not just those triggered by the + Restart= logic. Note that units which are configured for Restart= and + which reach the start limit are not attempted to be restarted anymore; however, they may still be restarted + manually at a later point, after the interval has passed. From this point on, the + restart logic is activated again. Note that systemctl reset-failed will cause the restart + rate counter for a service to be flushed, which is useful if the administrator wants to manually start a unit + and the start limit interferes with that. Note that this rate-limiting is enforced after any unit condition + checks are executed, and hence unit activations with failing conditions do not count towards this rate + limit. This setting does not apply to slice, target, device, and scope units, since they are unit types whose + activation may either never fail, or may succeed only a single time. + + When a unit is unloaded due to the garbage collection logic (see above) its rate limit counters are + flushed out too. This means that configuring start rate limiting for a unit that is not referenced continuously + has no effect. + + + + StartLimitAction= + + Configure an additional action to take if the rate limit configured with + StartLimitIntervalSec= and StartLimitBurst= is hit. Takes the same + values as the setting FailureAction=/SuccessAction= settings and executes + the same actions. If is set, hitting the rate limit will trigger no action besides that + the start will not be permitted. Defaults to . + + + + RebootArgument= + Configure the optional argument for the + reboot2 system call if + StartLimitAction= or FailureAction= is a reboot action. This + works just like the optional argument to systemctl reboot command. + + + + SourcePath= + A path to a configuration file this unit has + been generated from. This is primarily useful for + implementation of generator tools that convert configuration + from an external configuration file format into native unit + files. This functionality should not be used in normal + units. + + + + + Conditions and Asserts + + Unit files may also include a number of Condition…= and + Assert…= settings. Before the unit is started, systemd will verify + that the specified conditions are true. If not, the starting of the unit will be (mostly silently) + skipped. Failing conditions will not result in the unit being moved into the failed + state. The conditions are checked at the time the queued start job is to be executed. The ordering + dependencies are still respected, so other units are still pulled in and ordered as if this unit was + successfully activated. Use condition expressions in order to skip units that do not apply to the local + system, for example because the kernel or runtime environment doesn't require their functionality. + + + If multiple conditions are specified, the unit will be executed if all of them apply (i.e. a + logical AND is applied). Condition checks can use a pipe symbol (|) after the equals + sign (Condition…=|…), which causes the condition becomes a triggering condition. If + at least one triggering condition is defined for a unit, then the unit will be executed if at least one + of the triggering conditions apply and all of the non-triggering conditions. If you prefix an argument + with the pipe symbol and an exclamation mark, the pipe symbol must be passed first, the exclamation + second. If any of these options is assigned the empty string, the list of conditions is reset + completely, all previous condition settings (of any kind) will have no effect. + + The AssertArchitecture=, AssertVirtualization=, … options + provide a similar mechanism that causes the job to fail (instead of being skipped). The failed check is + logged. Units with failed conditions are considered to be in a clean state and will be garbage + collected if they are not referenced. This means that when queried, the condition failure may or may + not show up in the state of the unit. + + Note that neither assertion nor condition expressions result in unit state changes. Also note + that both are checked at the time the job is to be executed, i.e. long after depending jobs and it + itself were queued. Thus, neither condition nor assertion expressions are suitable for conditionalizing + unit dependencies. + + The condition verb of + systemd-analyze1 can + be used to test condition and assert expressions. + + Except for ConditionPathIsSymbolicLink=, all path checks follow symlinks. + + + + + + ConditionArchitecture= + + Check whether the system is running on a specific architecture. Takes one of + x86, + x86-64, + ppc, + ppc-le, + ppc64, + ppc64-le, + ia64, + parisc, + parisc64, + s390, + s390x, + sparc, + sparc64, + mips, + mips-le, + mips64, + mips64-le, + alpha, + arm, + arm-be, + arm64, + arm64-be, + sh, + sh64, + m68k, + tilegx, + cris, + arc, + arc-be, or + native. + + The architecture is determined from the information returned by + uname2 + and is thus subject to + personality2. + Note that a Personality= setting in the same unit file has no effect on this + condition. A special architecture name native is mapped to the architecture the + system manager itself is compiled for. The test may be negated by prepending an exclamation + mark. + + + + + ConditionVirtualization= + + Check whether the system is executed in a virtualized environment and optionally + test whether it is a specific implementation. Takes either boolean value to check if being executed + in any virtualized environment, or one of + vm and + container to test against a generic type of virtualization solution, or one of + qemu, + kvm, + zvm, + vmware, + microsoft, + oracle, + xen, + bochs, + uml, + bhyve, + qnx, + openvz, + lxc, + lxc-libvirt, + systemd-nspawn, + docker, + podman, + rkt, + wsl, + acrn to test + against a specific implementation, or + private-users to check whether we are running in a user namespace. See + systemd-detect-virt1 + for a full list of known virtualization technologies and their identifiers. If multiple + virtualization technologies are nested, only the innermost is considered. The test may be negated + by prepending an exclamation mark. + + + + + ConditionHost= + + ConditionHost= may be used to match against the hostname or + machine ID of the host. This either takes a hostname string (optionally with shell style globs) + which is tested against the locally set hostname as returned by + gethostname2, or + a machine ID formatted as string (see + machine-id5). + The test may be negated by prepending an exclamation mark. + + + + + ConditionKernelCommandLine= + + ConditionKernelCommandLine= may be used to check whether a + specific kernel command line option is set (or if prefixed with the exclamation mark — unset). The + argument must either be a single word, or an assignment (i.e. two words, separated by + =). In the former case the kernel command line is searched for the word + appearing as is, or as left hand side of an assignment. In the latter case, the exact assignment is + looked for with right and left hand side matching. + + + + + ConditionKernelVersion= + + ConditionKernelVersion= may be used to check whether the kernel + version (as reported by uname -r) matches a certain expression (or if prefixed + with the exclamation mark does not match it). The argument must be a list of (potentially quoted) + expressions. For each of the expressions, if it starts with one of <, + <=, =, !=, >=, + > a relative version comparison is done, otherwise the specified string is + matched with shell-style globs. + + Note that using the kernel version string is an unreliable way to determine which features + are supported by a kernel, because of the widespread practice of backporting drivers, features, and + fixes from newer upstream kernels into older versions provided by distributions. Hence, this check + is inherently unportable and should not be used for units which may be used on different + distributions. + + + + + ConditionSecurity= + + ConditionSecurity= may be used to check whether the given + security technology is enabled on the system. Currently, the recognized values are + selinux, apparmor, tomoyo, + ima, smack, audit and + uefi-secureboot. The test may be negated by prepending an exclamation + mark. + + + + + ConditionCapability= + + Check whether the given capability exists in the capability bounding set of the + service manager (i.e. this does not check whether capability is actually available in the permitted + or effective sets, see + capabilities7 + for details). Pass a capability name such as CAP_MKNOD, possibly prefixed with + an exclamation mark to negate the check. + + + + + ConditionACPower= + + Check whether the system has AC power, or is exclusively battery powered at the + time of activation of the unit. This takes a boolean argument. If set to true, + the condition will hold only if at least one AC connector of the system is connected to a power + source, or if no AC connectors are known. Conversely, if set to false, the + condition will hold only if there is at least one AC connector known and all AC connectors are + disconnected from a power source. + + + + + ConditionNeedsUpdate= + + Takes one of /var or /etc as argument, + possibly prefixed with a ! (to inverting the condition). This condition may be + used to conditionalize units on whether the specified directory requires an update because + /usr's modification time is newer than the stamp file + .updated in the specified directory. This is useful to implement offline + updates of the vendor operating system resources in /usr that require updating + of /etc or /var on the next following boot. Units making + use of this condition should order themselves before + systemd-update-done.service8, + to make sure they run before the stamp file's modification time gets reset indicating a completed + update. + + + + + ConditionFirstBoot= + + Takes a boolean argument. This condition may be used to conditionalize units on + whether the system is booting up with an unpopulated /etc directory + (specifically: an /etc with no /etc/machine-id). This may + be used to populate /etc on the first boot after factory reset, or when a new + system instance boots up for the first time. + + + + + ConditionPathExists= + + Check for the exists of a file. If the specified absolute path name does not exist, + the condition will fail. If the absolute path name passed to + ConditionPathExists= is prefixed with an exclamation mark + (!), the test is negated, and the unit is only started if the path does not + exist. + + + + + ConditionPathExistsGlob= + + ConditionPathExistsGlob= is similar to + ConditionPathExists=, but checks for the existence of at least one file or + directory matching the specified globbing pattern. + + + + + ConditionPathIsDirectory= + + ConditionPathIsDirectory= is similar to + ConditionPathExists= but verifies that a certain path exists and is a + directory. + + + + + ConditionPathIsSymbolicLink= + + ConditionPathIsSymbolicLink= is similar to + ConditionPathExists= but verifies that a certain path exists and is a symbolic + link. + + + + + ConditionPathIsMountPoint= + + ConditionPathIsMountPoint= is similar to + ConditionPathExists= but verifies that a certain path exists and is a mount + point. + + + + + ConditionPathIsReadWrite= + + ConditionPathIsReadWrite= is similar to + ConditionPathExists= but verifies that the underlying file system is readable + and writable (i.e. not mounted read-only). + + + + + ConditionDirectoryNotEmpty= + + ConditionDirectoryNotEmpty= is similar to + ConditionPathExists= but verifies that a certain path exists and is a non-empty + directory. + + + + + ConditionFileNotEmpty= + + ConditionFileNotEmpty= is similar to + ConditionPathExists= but verifies that a certain path exists and refers to a + regular file with a non-zero size. + + + + + ConditionFileIsExecutable= + + ConditionFileIsExecutable= is similar to + ConditionPathExists= but verifies that a certain path exists, is a regular file, + and marked executable. + + + + + ConditionUser= + + ConditionUser= takes a numeric UID, a UNIX + user name, or the special value @system. This condition may be used to check + whether the service manager is running as the given user. The special value + @system can be used to check if the user id is within the system user + range. This option is not useful for system services, as the system manager exclusively runs as the + root user, and thus the test result is constant. + + + + + ConditionGroup= + + ConditionGroup= is similar to ConditionUser= + but verifies that the service manager's real or effective group, or any of its auxiliary groups, + match the specified group or GID. This setting does not support the special value + @system. + + + + + ConditionControlGroupController= + + Verify that the given cgroup controller (eg. cpu) is available + for use on the system. For example, a particular controller may not be available if it was disabled + on the kernel command line with cgroup_disable=controller. Multiple controllers + may be passed with a space separating them; in this case the condition will only pass if all listed + controllers are available for use. Controllers unknown to systemd are ignored. Valid controllers + are cpu, cpuacct, io, + blkio, memory, devices, and + pids. + + + + + ConditionMemory= + + Verify that the specified amount of system memory is available to the current + system. Takes a memory size in bytes as argument, optionally prefixed with a comparison operator + <, <=, =, !=, + >=, >. On bare-metal systems compares the amount of + physical memory in the system with the specified size, adhering to the specified comparison + operator. In containers compares the amount of memory assigned to the container instead. + + + + + ConditionCPUs= + + Verify that the specified number of CPUs is available to the current system. Takes + a number of CPUs as argument, optionally prefixed with a comparison operator + <, <=, =, !=, + >=, >. Compares the number of CPUs in the CPU affinity + mask configured of the service manager itself with the specified number, adhering to the specified + comparison operator. On physical systems the number of CPUs in the affinity mask of the service + manager usually matches the number of physical CPUs, but in special and virtual environments might + differ. In particular, in containers the affinity mask usually matches the number of CPUs assigned + to the container and not the physically available ones. + + + + AssertArchitecture= + AssertVirtualization= + AssertHost= + AssertKernelCommandLine= + AssertKernelVersion= + AssertSecurity= + AssertCapability= + AssertACPower= + AssertNeedsUpdate= + AssertFirstBoot= + AssertPathExists= + AssertPathExistsGlob= + AssertPathIsDirectory= + AssertPathIsSymbolicLink= + AssertPathIsMountPoint= + AssertPathIsReadWrite= + AssertDirectoryNotEmpty= + AssertFileNotEmpty= + AssertFileIsExecutable= + AssertUser= + AssertGroup= + AssertControlGroupController= + + Similar to the ConditionArchitecture=, + ConditionVirtualization=, …, condition settings described above, these settings + add assertion checks to the start-up of the unit. However, unlike the conditions settings, any + assertion setting that is not met results in failure of the start job (which means this is logged + loudly). Note that hitting a configured assertion does not cause the unit to enter the + failed state (or in fact result in any state change of the unit), it affects + only the job queued for it. Use assertion expressions for units that cannot operate when specific + requirements are not met, and when this is something the administrator or user should look + into. + + + + + + + + Mapping of unit properties to their inverses + + Unit settings that create a relationship with a second unit usually show up + in properties of both units, for example in systemctl show + output. In some cases the name of the property is the same as the name of the + configuration setting, but not always. This table lists the properties + that are shown on two units which are connected through some dependency, and shows + which property on "source" unit corresponds to which property on the "target" unit. + + + + + "Forward" and "reverse" unit properties + + + + + + + + + + "Forward" property + "Reverse" property + Where used + + + + + Before= + After= + [Unit] section + + + After= + Before= + + + Requires= + RequiredBy= + [Unit] section + [Install] section + + + Wants= + WantedBy= + [Unit] section + [Install] section + + + PartOf= + ConsistsOf= + [Unit] section + an automatic property + + + BindsTo= + BoundBy= + [Unit] section + an automatic property + + + Requisite= + RequisiteOf= + [Unit] section + an automatic property + + + Triggers= + TriggeredBy= + Automatic properties, see notes below + + + Conflicts= + ConflictedBy= + [Unit] section + an automatic property + + + PropagatesReloadTo= + ReloadPropagatedFrom= + [Unit] section + + + ReloadPropagatedFrom= + PropagatesReloadTo= + + + Following= + n/a + An automatic property + + + +
+ + Note: WantedBy= and RequiredBy= are + used in the [Install] section to create symlinks in .wants/ + and .requires/ directories. They cannot be used directly as a + unit configuration setting. + + Note: ConsistsOf=, BoundBy=, + RequisiteOf=, ConflictedBy= are created + implicitly along with their reverses and cannot be specified directly. + + Note: Triggers= is created implicitly between a socket, + path unit, or an automount unit, and the unit they activate. By default a unit + with the same name is triggered, but this can be overridden using + Sockets=, Service=, and Unit= + settings. See + systemd.service5, + systemd.socket5, + systemd.path5, + and + systemd.automount5 + for details. TriggeredBy= is created implicitly on the + triggered unit. + + Note: Following= is used to group device aliases and points to the + "primary" device unit that systemd is using to track device state, usually corresponding to a + sysfs path. It does not show up in the "target" unit. +
+ + + [Install] Section Options + + Unit files may include an [Install] section, which carries installation information for + the unit. This section is not interpreted by + systemd1 during runtime; it is + used by the enable and disable commands of the + systemctl1 tool during + installation of a unit. + + + + Alias= + + A space-separated list of additional names this unit shall be installed under. The names listed + here must have the same suffix (i.e. type) as the unit filename. This option may be specified more than once, + in which case all listed names are used. At installation time, systemctl enable will create + symlinks from these names to the unit filename. Note that not all unit types support such alias names, and this + setting is not supported for them. Specifically, mount, slice, swap, and automount units do not support + aliasing. + + + + WantedBy= + RequiredBy= + + This option may be used more than once, or a + space-separated list of unit names may be given. A symbolic + link is created in the .wants/ or + .requires/ directory of each of the + listed units when this unit is installed by systemctl + enable. This has the effect that a dependency of + type Wants= or Requires= + is added from the listed unit to the current unit. The primary + result is that the current unit will be started when the + listed unit is started. See the description of + Wants= and Requires= in + the [Unit] section for details. + + WantedBy=foo.service in a service + bar.service is mostly equivalent to + Alias=foo.service.wants/bar.service in the + same file. In case of template units, systemctl + enable must be called with an instance name, and + this instance will be added to the + .wants/ or + .requires/ list of the listed unit. E.g. + WantedBy=getty.target in a service + getty@.service will result in + systemctl enable getty@tty2.service + creating a + getty.target.wants/getty@tty2.service + link to getty@.service. + + + + + Also= + + Additional units to install/deinstall when + this unit is installed/deinstalled. If the user requests + installation/deinstallation of a unit with this option + configured, systemctl enable and + systemctl disable will automatically + install/uninstall units listed in this option as well. + + This option may be used more than once, or a + space-separated list of unit names may be + given. + + + + DefaultInstance= + + In template unit files, this specifies for + which instance the unit shall be enabled if the template is + enabled without any explicitly set instance. This option has + no effect in non-template unit files. The specified string + must be usable as instance identifier. + + + + The following specifiers are interpreted in the Install + section: %n, %N, %p, %i, %j, %g, %G, %U, %u, %m, %H, %b, %v. For their + meaning see the next section. + + + + + Specifiers + + Many settings resolve specifiers which may be used to write + generic unit files referring to runtime or unit parameters that + are replaced when the unit files are loaded. Specifiers must be known + and resolvable for the setting to be valid. The following + specifiers are understood: + + + Specifiers available in unit files + + + + + + + Specifier + Meaning + Details + + + + + %b + Boot ID + The boot ID of the running system, formatted as string. See random4 for more information. + + + %C + Cache directory root + This is either /var/cache (for the system manager) or the path $XDG_CACHE_HOME resolves to (for user managers). + + + %E + Configuration directory root + This is either /etc (for the system manager) or the path $XDG_CONFIG_HOME resolves to (for user managers). + + + %f + Unescaped filename + This is either the unescaped instance name (if applicable) with / prepended (if applicable), or the unescaped prefix name prepended with /. This implements unescaping according to the rules for escaping absolute file system paths discussed above. + + + %h + User home directory + This is the home directory of the user running the service manager instance. In case of the system manager this resolves to /root. + +Note that this setting is not influenced by the User= setting configurable in the [Service] section of the service unit. + + + %H + Host name + The hostname of the running system at the point in time the unit configuration is loaded. + + + %i + Instance name + For instantiated units this is the string between the first @ character and the type suffix. Empty for non-instantiated units. + + + %I + Unescaped instance name + Same as %i, but with escaping undone. + + + %j + Final component of the prefix + This is the string between the last - and the end of the prefix name. If there is no -, this is the same as %p. + + + %J + Unescaped final component of the prefix + Same as %j, but with escaping undone. + + + %L + Log directory root + This is either /var/log (for the system manager) or the path $XDG_CONFIG_HOME resolves to with /log appended (for user managers). + + + %m + Machine ID + The machine ID of the running system, formatted as string. See machine-id5 for more information. + + + %n + Full unit name + + + + %N + Full unit name + Same as %n, but with the type suffix removed. + + + %p + Prefix name + For instantiated units, this refers to the string before the first @ character of the unit name. For non-instantiated units, same as %N. + + + %P + Unescaped prefix name + Same as %p, but with escaping undone. + + + %s + User shell + This is the shell of the user running the service manager instance. In case of the system manager this resolves to /bin/sh. + + + %S + State directory root + This is either /var/lib (for the system manager) or the path $XDG_CONFIG_HOME resolves to (for user managers). + + + %t + Runtime directory root + This is either /run (for the system manager) or the path $XDG_RUNTIME_DIR resolves to (for user managers). + + + %T + Directory for temporary files + This is either /tmp or the path $TMPDIR, $TEMP or $TMP are set to. + + + %g + User group + This is the name of the group running the service manager instance. In case of the system manager this resolves to root. + + + %G + User GID + This is the numeric GID of the user running the service manager instance. In case of the system manager this resolves to 0. + + + %u + User name + This is the name of the user running the service manager instance. In case of the system manager this resolves to root. + +Note that this setting is not influenced by the User= setting configurable in the [Service] section of the service unit. + + + %U + User UID + This is the numeric UID of the user running the service manager instance. In case of the system manager this resolves to 0. + +Note that this setting is not influenced by the User= setting configurable in the [Service] section of the service unit. + + + %v + Kernel release + Identical to uname -r output + + + %V + Directory for larger and persistent temporary files + This is either /var/tmp or the path $TMPDIR, $TEMP or $TMP are set to. + + + %% + Single percent sign + Use %% in place of % to specify a single percent sign. + + + +
+
+ + + Examples + + + Allowing units to be enabled + + The following snippet (highlighted) allows a unit (e.g. + foo.service) to be enabled via + systemctl enable: + + [Unit] +Description=Foo + +[Service] +ExecStart=/usr/sbin/foo-daemon + +[Install] +WantedBy=multi-user.target + + After running systemctl enable, a + symlink + /etc/systemd/system/multi-user.target.wants/foo.service + linking to the actual unit will be created. It tells systemd to + pull in the unit when starting + multi-user.target. The inverse + systemctl disable will remove that symlink + again. + + + + Overriding vendor settings + + There are two methods of overriding vendor settings in + unit files: copying the unit file from + /usr/lib/systemd/system to + /etc/systemd/system and modifying the + chosen settings. Alternatively, one can create a directory named + unit.d/ within + /etc/systemd/system and place a drop-in + file name.conf + there that only changes the specific settings one is interested + in. Note that multiple such drop-in files are read if + present, processed in lexicographic order of their filename. + + The advantage of the first method is that one easily + overrides the complete unit, the vendor unit is not parsed at + all anymore. It has the disadvantage that improvements to the + unit file by the vendor are not automatically incorporated on + updates. + + The advantage of the second method is that one only + overrides the settings one specifically wants, where updates to + the unit by the vendor automatically apply. This has the + disadvantage that some future updates by the vendor might be + incompatible with the local changes. + + This also applies for user instances of systemd, but with + different locations for the unit files. See the section on unit + load paths for further details. + + Suppose there is a vendor-supplied unit + /usr/lib/systemd/system/httpd.service with + the following contents: + + [Unit] +Description=Some HTTP server +After=remote-fs.target sqldb.service +Requires=sqldb.service +AssertPathExists=/srv/webserver + +[Service] +Type=notify +ExecStart=/usr/sbin/some-fancy-httpd-server +Nice=5 + +[Install] +WantedBy=multi-user.target + + Now one wants to change some settings as an administrator: + firstly, in the local setup, /srv/webserver + might not exist, because the HTTP server is configured to use + /srv/www instead. Secondly, the local + configuration makes the HTTP server also depend on a memory + cache service, memcached.service, that + should be pulled in (Requires=) and also be + ordered appropriately (After=). Thirdly, in + order to harden the service a bit more, the administrator would + like to set the PrivateTmp= setting (see + systemd.exec5 + for details). And lastly, the administrator would like to reset + the niceness of the service to its default value of 0. + + The first possibility is to copy the unit file to + /etc/systemd/system/httpd.service and + change the chosen settings: + + [Unit] +Description=Some HTTP server +After=remote-fs.target sqldb.service memcached.service +Requires=sqldb.service memcached.service +AssertPathExists=/srv/www + +[Service] +Type=notify +ExecStart=/usr/sbin/some-fancy-httpd-server +Nice=0 +PrivateTmp=yes + +[Install] +WantedBy=multi-user.target + + Alternatively, the administrator could create a drop-in + file + /etc/systemd/system/httpd.service.d/local.conf + with the following contents: + + [Unit] +After=memcached.service +Requires=memcached.service +# Reset all assertions and then re-add the condition we want +AssertPathExists= +AssertPathExists=/srv/www + +[Service] +Nice=0 +PrivateTmp=yes + + Note that for drop-in files, if one wants to remove + entries from a setting that is parsed as a list (and is not a + dependency), such as AssertPathExists= (or + e.g. ExecStart= in service units), one needs + to first clear the list before re-adding all entries except the + one that is to be removed. Dependencies (After=, etc.) + cannot be reset to an empty list, so dependencies can only be + added in drop-ins. If you want to remove dependencies, you have + to override the entire unit. + + + + + + See Also + + systemd1, + systemctl1, + systemd-system.conf5, + systemd.special7, + systemd.service5, + systemd.socket5, + systemd.device5, + systemd.mount5, + systemd.automount5, + systemd.swap5, + systemd.target5, + systemd.path5, + systemd.timer5, + systemd.scope5, + systemd.slice5, + systemd.time7, + systemd-analyze1, + capabilities7, + systemd.directives7, + uname1 + + + +
diff --git a/man/systemd.xml b/man/systemd.xml new file mode 100644 index 00000000..bde79d56 --- /dev/null +++ b/man/systemd.xml @@ -0,0 +1,1241 @@ + + + + + + + + systemd + systemd + + + + systemd + 1 + + + + systemd + init + systemd system and service manager + + + + + /usr/lib/systemd/systemd + OPTIONS + + + init + OPTIONS + COMMAND + + + + + Description + + systemd is a system and service manager for Linux operating systems. When run as first process on + boot (as PID 1), it acts as init system that brings up and maintains userspace services. Seperate + instances are started for logged-in users to start their services. + + systemd is usually not invoked directly by the user, but is installed as the + /sbin/init symlink and started during early boot. The user manager instances are + started automatically through the + user@.service5 + service. + + For compatibility with SysV, if the binary is called as init and is not the + first process on the machine (PID is not 1), it will execute telinit and pass all + command line arguments unmodified. That means init and telinit are + mostly equivalent when invoked from normal login sessions. See + telinit8 for more + information. + + When run as a system instance, systemd interprets the + configuration file system.conf and the files + in system.conf.d directories; when run as a + user instance, systemd interprets the configuration file + user.conf and the files in + user.conf.d directories. See + systemd-system.conf5 + for more information. + + + + Concepts + + systemd provides a dependency system between various + entities called "units" of 11 different types. Units encapsulate + various objects that are relevant for system boot-up and + maintenance. The majority of units are configured in unit + configuration files, whose syntax and basic set of options is + described in + systemd.unit5, + however some are created automatically from other configuration, + dynamically from system state or programmatically at runtime. + Units may be "active" (meaning started, bound, plugged in, …, + depending on the unit type, see below), or "inactive" (meaning + stopped, unbound, unplugged, …), as well as in the process of + being activated or deactivated, i.e. between the two states (these + states are called "activating", "deactivating"). A special + "failed" state is available as well, which is very similar to + "inactive" and is entered when the service failed in some way + (process returned error code on exit, or crashed, an operation + timed out, or after too many restarts). If this state is entered, + the cause will be logged, for later reference. Note that the + various unit types may have a number of additional substates, + which are mapped to the five generalized unit states described + here. + + The following unit types are available: + + + Service units, which start and control daemons + and the processes they consist of. For details, see + systemd.service5. + + Socket units, which encapsulate local IPC or + network sockets in the system, useful for socket-based + activation. For details about socket units, see + systemd.socket5, + for details on socket-based activation and other forms of + activation, see + daemon7. + + Target units are useful to group units, or + provide well-known synchronization points during boot-up, see + systemd.target5. + + Device units expose kernel devices in systemd + and may be used to implement device-based activation. For + details, see + systemd.device5. + + Mount units control mount points in the file + system, for details see + systemd.mount5. + + Automount units provide automount capabilities, + for on-demand mounting of file systems as well as parallelized + boot-up. See + systemd.automount5. + + Timer units are useful for triggering activation + of other units based on timers. You may find details in + systemd.timer5. + + Swap units are very similar to mount units and + encapsulate memory swap partitions or files of the operating + system. They are described in + systemd.swap5. + + Path units may be used to activate other + services when file system objects change or are modified. See + systemd.path5. + + Slice units may be used to group units which + manage system processes (such as service and scope units) in a + hierarchical tree for resource management purposes. See + systemd.slice5. + + Scope units are similar to service units, but + manage foreign processes instead of starting them as well. See + systemd.scope5. + + + + Units are named as their configuration files. Some units + have special semantics. A detailed list is available in + systemd.special7. + + systemd knows various kinds of dependencies, including + positive and negative requirement dependencies (i.e. + Requires= and Conflicts=) as + well as ordering dependencies (After= and + Before=). NB: ordering and requirement + dependencies are orthogonal. If only a requirement dependency + exists between two units (e.g. foo.service + requires bar.service), but no ordering + dependency (e.g. foo.service after + bar.service) and both are requested to start, + they will be started in parallel. It is a common pattern that both + requirement and ordering dependencies are placed between two + units. Also note that the majority of dependencies are implicitly + created and maintained by systemd. In most cases, it should be + unnecessary to declare additional dependencies manually, however + it is possible to do this. + + Application programs and units (via dependencies) may + request state changes of units. In systemd, these requests are + encapsulated as 'jobs' and maintained in a job queue. Jobs may + succeed or can fail, their execution is ordered based on the + ordering dependencies of the units they have been scheduled + for. + + On boot systemd activates the target unit + default.target whose job is to activate + on-boot services and other on-boot units by pulling them in via + dependencies. Usually, the unit name is just an alias (symlink) for + either graphical.target (for fully-featured + boots into the UI) or multi-user.target (for + limited console-only boots for use in embedded or server + environments, or similar; a subset of graphical.target). However, + it is at the discretion of the administrator to configure it as an + alias to any other target unit. See + systemd.special7 + for details about these target units. + + systemd only keeps a minimal set of units loaded into memory. Specifically, the only units that are kept + loaded into memory are those for which at least one of the following conditions is true: + + + It is in an active, activating, deactivating or failed state (i.e. in any unit state except for inactive) + It has a job queued for it + It is a dependency of some sort of at least one other unit that is loaded into memory + It has some form of resource still allocated (e.g. a service unit that is inactive but for which + a process is still lingering that ignored the request to be terminated) + It has been pinned into memory programmatically by a D-Bus call + + + systemd will automatically and implicitly load units from disk — if they are not loaded yet — as soon as + operations are requested for them. Thus, in many respects, the fact whether a unit is loaded or not is invisible to + clients. Use systemctl list-units --all to comprehensively list all units currently loaded. Any + unit for which none of the conditions above applies is promptly unloaded. Note that when a unit is unloaded from + memory its accounting data is flushed out too. However, this data is generally not lost, as a journal log record + is generated declaring the consumed resources whenever a unit shuts down. + + Processes systemd spawns are placed in individual Linux + control groups named after the unit which they belong to in the + private systemd hierarchy. (see cgroups.txt + for more information about control groups, or short "cgroups"). + systemd uses this to effectively keep track of processes. Control + group information is maintained in the kernel, and is accessible + via the file system hierarchy (beneath + /sys/fs/cgroup/systemd/), or in tools such as + systemd-cgls1 + or + ps1 + (ps xawf -eo pid,user,cgroup,args is + particularly useful to list all processes and the systemd units + they belong to.). + + systemd is compatible with the SysV init system to a large + degree: SysV init scripts are supported and simply read as an + alternative (though limited) configuration file format. The SysV + /dev/initctl interface is provided, and + compatibility implementations of the various SysV client tools are + available. In addition to that, various established Unix + functionality such as /etc/fstab or the + utmp database are supported. + + systemd has a minimal transaction system: if a unit is + requested to start up or shut down it will add it and all its + dependencies to a temporary transaction. Then, it will verify if + the transaction is consistent (i.e. whether the ordering of all + units is cycle-free). If it is not, systemd will try to fix it up, + and removes non-essential jobs from the transaction that might + remove the loop. Also, systemd tries to suppress non-essential + jobs in the transaction that would stop a running service. Finally + it is checked whether the jobs of the transaction contradict jobs + that have already been queued, and optionally the transaction is + aborted then. If all worked out and the transaction is consistent + and minimized in its impact it is merged with all already + outstanding jobs and added to the run queue. Effectively this + means that before executing a requested operation, systemd will + verify that it makes sense, fixing it if possible, and only + failing if it really cannot work. + + Note that transactions are generated independently of a unit's + state at runtime, hence, for example, if a start job is requested on an + already started unit, it will still generate a transaction and wake up any + inactive dependencies (and cause propagation of other jobs as per the + defined relationships). This is because the enqueued job is at the time of + execution compared to the target unit's state and is marked successful and + complete when both satisfy. However, this job also pulls in other + dependencies due to the defined relationships and thus leads to, in our + our example, start jobs for any of those inactive units getting queued as + well. + + systemd contains native implementations of various tasks + that need to be executed as part of the boot process. For example, + it sets the hostname or configures the loopback network device. It + also sets up and mounts various API file systems, such as + /sys or /proc. + + For more information about the concepts and + ideas behind systemd, please refer to the + Original Design Document. + + Note that some but not all interfaces provided + by systemd are covered by the + Interface + Stability Promise. + + Units may be generated dynamically at boot and system + manager reload time, for example based on other configuration + files or parameters passed on the kernel command line. For details, see + systemd.generator7. + + Systems which invoke systemd in a container or initrd + environment should implement the + Container Interface or + initrd Interface + specifications, respectively. + + + + Directories + + + + System unit directories + + The systemd system manager reads unit + configuration from various directories. Packages that want to + install unit files shall place them in the directory returned + by pkg-config systemd + --variable=systemdsystemunitdir. Other directories + checked are /usr/local/lib/systemd/system + and /usr/lib/systemd/system. User + configuration always takes precedence. pkg-config + systemd --variable=systemdsystemconfdir returns the + path of the system configuration directory. Packages should + alter the content of these directories only with the + enable and disable + commands of the + systemctl1 + tool. Full list of directories is provided in + systemd.unit5. + + + + + + + User unit directories + + Similar rules apply for the user unit + directories. However, here the + XDG + Base Directory specification is followed to find + units. Applications should place their unit files in the + directory returned by pkg-config systemd + --variable=systemduserunitdir. Global configuration + is done in the directory reported by pkg-config + systemd --variable=systemduserconfdir. The + enable and disable + commands of the + systemctl1 + tool can handle both global (i.e. for all users) and private + (for one user) enabling/disabling of units. Full list of + directories is provided in + systemd.unit5. + + + + + + + SysV init scripts directory + + The location of the SysV init script directory + varies between distributions. If systemd cannot find a native + unit file for a requested service, it will look for a SysV + init script of the same name (with the + .service suffix + removed). + + + + + + SysV runlevel link farm directory + + The location of the SysV runlevel link farm + directory varies between distributions. systemd will take the + link farm into account when figuring out whether a service + shall be enabled. Note that a service unit with a native unit + configuration file cannot be started by activating it in the + SysV runlevel link farm. + + + + + + Signals + + + + SIGTERM + + Upon receiving this signal the systemd system + manager serializes its state, reexecutes itself and + deserializes the saved state again. This is mostly equivalent + to systemctl daemon-reexec. + + systemd user managers will start the + exit.target unit when this signal is + received. This is mostly equivalent to systemctl + --user start exit.target + --job-mode=replace-irreversibly. + + + + SIGINT + + Upon receiving this signal the systemd system manager will start the + ctrl-alt-del.target unit. This is mostly equivalent to + systemctl start ctrl-alt-del.target --job-mode=replace-irreversibly. If + this signal is received more than 7 times per 2s, an immediate reboot is triggered. Note + that pressing + CtrlAltDel on the + console will trigger this signal. Hence, if a reboot is hanging, pressing + CtrlAltDel more than + 7 times in 2 seconds is a relatively safe way to trigger an immediate reboot. + + systemd user managers treat this signal the same way as + SIGTERM. + + + + SIGWINCH + + When this signal is received the systemd + system manager will start the + kbrequest.target unit. This is mostly + equivalent to systemctl start + kbrequest.target. + + This signal is ignored by systemd user + managers. + + + + SIGPWR + + When this signal is received the systemd + manager will start the sigpwr.target + unit. This is mostly equivalent to systemctl start + sigpwr.target. + + + + SIGUSR1 + + When this signal is received the systemd + manager will try to reconnect to the D-Bus + bus. + + + + SIGUSR2 + + When this signal is received the systemd + manager will log its complete state in human-readable form. + The data logged is the same as printed by + systemd-analyze dump. + + + + SIGHUP + + Reloads the complete daemon configuration. + This is mostly equivalent to systemctl + daemon-reload. + + + + SIGRTMIN+0 + + Enters default mode, starts the + default.target unit. This is mostly + equivalent to systemctl isolate + default.target. + + + + SIGRTMIN+1 + + Enters rescue mode, starts the + rescue.target unit. This is mostly + equivalent to systemctl isolate + rescue.target. + + + + SIGRTMIN+2 + + Enters emergency mode, starts the + emergency.service unit. This is mostly + equivalent to systemctl isolate + emergency.service. + + + + SIGRTMIN+3 + + Halts the machine, starts the + halt.target unit. This is mostly + equivalent to systemctl start halt.target + --job-mode=replace-irreversibly. + + + + + SIGRTMIN+4 + + Powers off the machine, starts the + poweroff.target unit. This is mostly + equivalent to systemctl start poweroff.target + --job-mode=replace-irreversibly. + + + + + SIGRTMIN+5 + + Reboots the machine, starts the + reboot.target unit. This is mostly + equivalent to systemctl start reboot.target + --job-mode=replace-irreversibly. + + + + + SIGRTMIN+6 + + Reboots the machine via kexec, starts the + kexec.target unit. This is mostly + equivalent to systemctl start kexec.target + --job-mode=replace-irreversibly. + + + + + SIGRTMIN+13 + + Immediately halts the machine. + + + + SIGRTMIN+14 + + Immediately powers off the machine. + + + + SIGRTMIN+15 + + Immediately reboots the machine. + + + + SIGRTMIN+16 + + Immediately reboots the machine with kexec. + + + + SIGRTMIN+20 + + Enables display of status messages on the + console, as controlled via + systemd.show_status=1 on the kernel command + line. + + + + SIGRTMIN+21 + + Disables display of + status messages on the console, as + controlled via + systemd.show_status=0 + on the kernel command + line. + + + + SIGRTMIN+22 + + Sets the service manager's log level to debug, in a fashion equivalent to + systemd.log_level=debug on the kernel command line. + + + + SIGRTMIN+23 + + Restores the log level to its configured value. The configured value is derived from – in order + of priority – the value specified with systemd.log-level= on the kernel command line, or the + value specified with in the configuration file, or the built-in default of + info. + + + + SIGRTMIN+24 + + Immediately exits the manager (only available + for --user instances). + + + + SIGRTMIN+26 + + Restores the log target to its configured value. The configured value is derived from – in + order of priority – the value specified with systemd.log-target= on the kernel command line, + or the value specified with in the configuration file, or the built-in + default. + + + + SIGRTMIN+27 + SIGRTMIN+28 + + Sets the log target to console on SIGRTMIN+27 (or + kmsg on SIGRTMIN+28), in a fashion equivalent to + systemd.log_target=console (or systemd.log_target=kmsg on + SIGRTMIN+28) on the kernel command line. + + + + + + Environment + + + + $SYSTEMD_LOG_LEVEL + systemd reads the log level from this + environment variable. This can be overridden with + . + + + + $SYSTEMD_LOG_TARGET + systemd reads the log target from this + environment variable. This can be overridden with + . + + + + $SYSTEMD_LOG_COLOR + Controls whether systemd highlights important + log messages. This can be overridden with + . + + + + $SYSTEMD_LOG_LOCATION + Controls whether systemd prints the code + location along with log messages. This can be overridden with + . + + + + $XDG_CONFIG_HOME + $XDG_CONFIG_DIRS + $XDG_DATA_HOME + $XDG_DATA_DIRS + + The systemd user manager uses these variables + in accordance to the XDG + Base Directory specification to find its + configuration. + + + + $SYSTEMD_UNIT_PATH + + Controls where systemd looks for unit + files. + + + + $SYSTEMD_SYSVINIT_PATH + + Controls where systemd looks for SysV init + scripts. + + + + $SYSTEMD_SYSVRCND_PATH + + Controls where systemd looks for SysV init + script runlevel link farms. + + + + + + + + + + $LISTEN_PID + $LISTEN_FDS + $LISTEN_FDNAMES + + Set by systemd for supervised processes during + socket-based activation. See + sd_listen_fds3 + for more information. + + + + $NOTIFY_SOCKET + + Set by systemd for supervised processes for + status and start-up completion notification. See + sd_notify3 + for more information. + + + + For further environment variables understood by systemd and its various components, see Known Environment Variables. + + + + Kernel Command Line + + When run as the system instance systemd parses a number of options listed below. They can be + specified as kernel command line argumentsIf run inside a Linux container these arguments + may be passed as command line arguments to systemd itself, next to any of the command line options listed + in the Options section above. If run outside of Linux containers, these arguments are parsed from + /proc/cmdline instead., or through the + SystemdOptions EFI variable (on EFI systems). The kernel command line has higher + priority. Following variables are understood: + + + + systemd.unit= + rd.systemd.unit= + + Overrides the unit to activate on boot. + Defaults to default.target. This may be + used to temporarily boot into a different boot unit, for + example rescue.target or + emergency.service. See + systemd.special7 + for details about these units. The option prefixed with + rd. is honored only in the initial RAM disk + (initrd), while the one that is not prefixed only in the main + system. + + + + systemd.dump_core + + Takes a boolean argument or enables the option if specified + without an argument. If enabled, the systemd manager (PID 1) dumps core when + it crashes. Otherwise, no core dump is created. Defaults to enabled. + + + + + systemd.crash_chvt + + Takes a positive integer, or a boolean argument. Can be also + specified without an argument, with the same effect as a positive boolean. If + a positive integer (in the range 1–63) is specified, the system manager (PID + 1) will activate the specified virtual terminal (VT) when it + crashes. Defaults to disabled, meaning that no such switch is attempted. If + set to enabled, the VT the kernel messages are written to is selected. + + + + + systemd.crash_shell + + Takes a boolean argument or enables the option if specified + without an argument. If enabled, the system manager (PID 1) spawns a shell + when it crashes, after a 10s delay. Otherwise, no shell is spawned. Defaults + to disabled, for security reasons, as the shell is not protected by password + authentication. + + + + systemd.crash_reboot + + Takes a boolean argument or enables the option if specified + without an argument. If enabled, the system manager (PID 1) will reboot the + machine automatically when it crashes, after a 10s delay. Otherwise, the + system will hang indefinitely. Defaults to disabled, in order to avoid a + reboot loop. If combined with systemd.crash_shell, the + system is rebooted after the shell exits. + + + + systemd.confirm_spawn + + Takes a boolean argument or a path to the virtual console + where the confirmation messages should be emitted. Can be also specified + without an argument, with the same effect as a positive boolean. If enabled, + the system manager (PID 1) asks for confirmation when spawning processes + using . If a path or a console name (such as + ttyS0) is provided, the virtual console pointed to by this + path or described by the give name will be used instead. Defaults to disabled. + + + + + systemd.service_watchdogs= + + Takes a boolean argument. If disabled, all service runtime + watchdogs () and emergency actions (e.g. + or ) are + ignored by the system manager (PID 1); see + systemd.service5. + Defaults to enabled, i.e. watchdogs and failure actions are processed + normally. The hardware watchdog is not affected by this + option. + + + + systemd.show_status + + Takes a boolean argument or the constant + auto. Can be also specified without an argument, with + the same effect as a positive boolean. If enabled, the systemd manager (PID + 1) shows terse service status updates on the console during bootup. + auto behaves like until a unit + fails or there is a significant delay in boot. Defaults to enabled, unless + is passed as kernel command line option, in which case + it defaults to auto. If specified overrides the system + manager configuration file option , see + systemd-system.conf5. + + + + + systemd.status_unit_format= + + Takes either or as the value. If + , the system manager will use unit names in status messages. If specified, + overrides the system manager configuration file option , see + systemd-system.conf5. + + + + + systemd.log_target= + systemd.log_level= + systemd.log_location= + systemd.log_color + + Controls log output, with the same effect as the + $SYSTEMD_LOG_TARGET, + $SYSTEMD_LOG_LEVEL, + $SYSTEMD_LOG_LOCATION, + $SYSTEMD_LOG_COLOR environment variables described above. + systemd.log_color can be specified without an argument, + with the same effect as a positive boolean. + + + + systemd.default_standard_output= + systemd.default_standard_error= + + Controls default standard output and error output for services and sockets. That is, + controls the default for and (see + systemd.exec5 for + details). Takes one of , , , + , , , + . If the argument is omitted + systemd.default-standard-output= defaults to and + systemd.default-standard-error= to . + + + + systemd.setenv= + + Takes a string argument in the form + VARIABLE=VALUE. May be used to set default environment + variables to add to forked child processes. May be used more + than once to set multiple variables. + + + + systemd.machine_id= + + Takes a 32 character hex value to be + used for setting the machine-id. Intended mostly for + network booting where the same machine-id is desired + for every boot. + + + + systemd.unified_cgroup_hierarchy + + When specified without an argument or with a true argument, + enables the usage of + unified cgroup hierarchy + (a.k.a. cgroups-v2). When specified with a false argument, fall back to + hybrid or full legacy cgroup hierarchy. + + If this option is not specified, the default behaviour is determined + during compilation (the meson + option). If the kernel does not support unified cgroup hierarchy, the legacy + hierarchy will be used even if this option is specified. + + + + + systemd.legacy_systemd_cgroup_controller + + Takes effect if the full unified cgroup hierarchy is not used + (see previous option). When specified without an argument or with a true + argument, disables the use of "hybrid" cgroup hierarchy (i.e. a cgroups-v2 + tree used for systemd, and + legacy + cgroup hierarchy, a.k.a. cgroups-v1, for other controllers), and + forces a full "legacy" mode. When specified with a false argument, enables + the use of "hybrid" hierarchy. + + If this option is not specified, the default behaviour is determined + during compilation (the meson + option). If the kernel does not support unified cgroup hierarchy, the legacy + hierarchy will be used even if this option is specified. + + + + + quiet + + Turn off status output at boot, much like + systemd.show_status=no would. Note that + this option is also read by the kernel itself and disables + kernel log output. Passing this option hence turns off the + usual output from both the system manager and the kernel. + + + + + debug + + Turn on debugging output. This is equivalent + to systemd.log_level=debug. Note that this + option is also read by the kernel itself and enables kernel + debug output. Passing this option hence turns on the debug + output from both the system manager and the + kernel. + + + + emergency + rd.emergency + -b + + Boot into emergency mode. This is equivalent + to systemd.unit=emergency.target or + rd.systemd.unit=emergency.target, respectively, and + provided for compatibility reasons and to be easier to type. + + + + rescue + rd.rescue + single + s + S + 1 + + Boot into rescue mode. This is equivalent to + systemd.unit=rescue.target or + rd.systemd.unit=rescue.target, respectively, and + provided for compatibility reasons and to be easier to type. + + + + 2 + 3 + 4 + 5 + + Boot into the specified legacy SysV runlevel. + These are equivalent to + systemd.unit=runlevel2.target, + systemd.unit=runlevel3.target, + systemd.unit=runlevel4.target, and + systemd.unit=runlevel5.target, + respectively, and provided for compatibility reasons and to be + easier to type. + + + + locale.LANG= + locale.LANGUAGE= + locale.LC_CTYPE= + locale.LC_NUMERIC= + locale.LC_TIME= + locale.LC_COLLATE= + locale.LC_MONETARY= + locale.LC_MESSAGES= + locale.LC_PAPER= + locale.LC_NAME= + locale.LC_ADDRESS= + locale.LC_TELEPHONE= + locale.LC_MEASUREMENT= + locale.LC_IDENTIFICATION= + + Set the system locale to use. This overrides + the settings in /etc/locale.conf. For + more information, see + locale.conf5 + and + locale7. + + + + + For other kernel command line parameters understood by + components of the core OS, please refer to + kernel-command-line7. + + + + Options + + systemd is only very rarely invoked directly, since it is started early and is + already running by the time users may interact with it. Normally, tools like + systemctl1 are used to + give commands to the manager. Since systemd is usually not invoked directly, the + options listed below are mostly useful for debugging and special purposes. + + + Introspection and debugging options + + Those options are used for testing and introspection, and systemd may + be invoked with them at any time: + + + + + + Dump understood unit configuration items. This outputs a terse but complete list of + configuration items understood in unit definition files. + + + + + + Dump exposed bus properties. This outputs a terse but complete list of properties + exposed on D-Bus. + + + + + + Determine the initial start-up transaction (i.e. the list of jobs enqueued at + start-up), dump it and exit — without actually executing any of the determined jobs. This option is + useful for debugging only. Note that during regular service manager start-up additional units not + shown by this operation may be started, because hardware, socket, bus or other kinds of activation + might add additional jobs as the transaction is executed. Use to request + the initial transaction of the system service manager (this is also the implied default), combine + with to request the initial transaction of the per-user service manager + instead. + + + + + + + When used in conjunction with , selects whether to calculate + the initial transaction for the system instance or for a per-user instance. These options have no + effect when invoked without , as during regular + (i.e. non-) invocations the service manager will automatically detect + whether it shall operate in system or per-user mode, by checking whether the PID it is run as is 1 + or not. Note that it is not supported booting and maintaining a system with the service manager + running in mode but with a PID other than 1. + + + + + + + + + Options that duplicate kernel command line settings + + Those options correspond directly to options listed above in "Kernel Command Line". Both forms + may be used equivalently for the system manager, but it is recommended to use the forms listed above in + this context, because they are properly namespaced. When an option is specified both on the kernel + command line, and as a normal command line argument, the latter has higher precedence. + + When systemd is used a user manager, the kernel command line is ignored and + the options described are understood. Nevertheless, systemd is usually started in + this mode through the + user@.service5 + service, which is shared between all users, and it may be more convenient to use configuration files to + modify settings, see + systemd-user.conf5, + or a drop-in that specifies one of the environment variables listed above in "Environment, see + systemd.unit5. + + + + + + Set default unit to activate on startup. If not specified, defaults to + default.target. See systemd.unit= above. + + + + + + Enable core dumping on crash. This switch has no effect when running as user + instance. Same as systemd.dump_core= above. + + + + VT + + Switch to a specific virtual console (VT) on crash. This switch has no effect when + running as user instance. Same as systemd.crash_chvt= above (but not the + different spelling!). + + + + + + Run a shell on crash. This switch has no effect when running as user instance. See + systemd.crash_shell= above. + + + + + + Automatically reboot the system on crash. This switch has no effect when running as + user instance. See systemd.crash_reboot above. + + + + + + Ask for confirmation when spawning processes. This switch has no effect when run as + user instance. See systemd.confirm_spawn above. + + + + + + Show terse unit status information is shown on the console during boot-up and + shutdown. See systemd.show_status above. + + + + + + Set log target. See systemd.log_target above. + + + + + + Set log level. See systemd.log_level above. + + + + + + Highlight important log messages. See systemd.log_color above. + + + + + + + Include code location in log messages. See systemd.log_location + above. + + + + + + Override the machine-id set on the hard drive. See + systemd.machine_id= above. + + + + + + Globally enable/disable all service watchdog timeouts and emergency actions. See + systemd.service_watchdogs above. + + + + + + + Sets the default output or error output for all services and sockets, + respectively. See systemd.default_standard_output= and + systemd.default_standard_error= above. + + + + + + + Sockets and FIFOs + + + + /run/systemd/notify + + Daemon status notification socket. This is an + AF_UNIX datagram socket and is used to + implement the daemon notification logic as implemented by + sd_notify3. + + + + + /run/systemd/private + + Used internally as communication channel + between + systemctl1 + and the systemd process. This is an + AF_UNIX stream socket. This interface is + private to systemd and should not be used in external + projects. + + + + /dev/initctl + + Limited compatibility support for the SysV + client interface, as implemented by the + systemd-initctl.service unit. This is a + named pipe in the file system. This interface is obsolete and + should not be used in new applications. + + + + + + See Also + + The systemd Homepage, + systemd-system.conf5, + locale.conf5, + systemctl1, + journalctl1, + systemd-notify1, + daemon7, + sd-daemon3, + systemd.unit5, + systemd.special5, + pkg-config1, + kernel-command-line7, + bootup7, + systemd.directives7 + + + + diff --git a/man/sysusers.d.xml b/man/sysusers.d.xml new file mode 100644 index 00000000..2e93715b --- /dev/null +++ b/man/sysusers.d.xml @@ -0,0 +1,296 @@ + + + + + + + + sysusers.d + systemd + + + + sysusers.d + 5 + + + + sysusers.d + Declarative allocation of system users and groups + + + + /etc/sysusers.d/*.conf + /run/sysusers.d/*.conf + /usr/lib/sysusers.d/*.conf + + + + Description + + systemd-sysusers uses the files from + sysusers.d directory to create system users and groups and + to add users to groups, at package installation or boot time. This tool may be + used to allocate system users and groups only, it is not useful for creating + non-system (i.e. regular, "human") users and groups, as it accesses + /etc/passwd and /etc/group directly, + bypassing any more complex user databases, for example any database involving NIS + or LDAP. + + + + Configuration Directories and Precedence + + Each configuration file shall be named in the style of + package.conf or + package-part.conf. + The second variant should be used when it is desirable to make it + easy to override just this part of configuration. + + Files in /etc/sysusers.d override files + with the same name in /usr/lib/sysusers.d and + /run/sysusers.d. Files in + /run/sysusers.d override files with the same + name in /usr/lib/sysusers.d. Packages should + install their configuration files in + /usr/lib/sysusers.d. Files in + /etc/sysusers.d are reserved for the local + administrator, who may use this logic to override the + configuration files installed by vendor packages. All + configuration files are sorted by their filename in lexicographic + order, regardless of which of the directories they reside in. If + multiple files specify the same path, the entry in the file with + the lexicographically earliest name will be applied. All later + entries for the same user and group names will be logged as warnings. + + + If the administrator wants to disable a configuration file + supplied by the vendor, the recommended way is to place a symlink + to /dev/null in + /etc/sysusers.d/ bearing the same filename. + + + + + Configuration File Format + + The file format is one line per user or group containing name, ID, GECOS + field description, home directory, and login shell: + + #Type Name ID GECOS Home directory Shell +u httpd 404 "HTTP User" +u authd /usr/bin/authd "Authorization user" +u postgres - "Postgresql Database" /var/lib/pgsql /usr/libexec/postgresdb +g input - - +m authd input +u root 0 "Superuser" /root /bin/zsh + + Empty lines and lines beginning with the # character are ignored, and may be used for + commenting. + + + Type + + The type consists of a single letter. The following line + types are understood: + + + + u + Create a system user and group of the specified name should + they not exist yet. The user's primary group will be set to the group + bearing the same name. The account will be created disabled, so that logins + are not allowed. + + + + g + Create a system group of the specified name + should it not exist yet. Note that u + implicitly create a matching group. The group will be + created with no password set. + + + + m + Add a user to a group. If the user or group + do not exist yet, they will be implicitly + created. + + + + r + Add a range of numeric UIDs/GIDs to the pool + to allocate new UIDs and GIDs from. If no line of this type + is specified, the range of UIDs/GIDs is set to some + compiled-in default. Note that both UIDs and GIDs are + allocated from the same pool, in order to ensure that users + and groups of the same name are likely to carry the same + numeric UID and GID. + + + + + + + Name + + The name field specifies the user or group name. The specified name must consist only of the characters a-z, + A-Z, 0-9, _ and -, except for the first character which must be one of a-z, + A-Z or _ (i.e. numbers and - are not permitted as first character). The + user/group name must have at least one character, and at most 31. + + It is strongly recommended to pick user and group names that are unlikely to clash with normal users + created by the administrator. A good scheme to guarantee this is by prefixing all system and group names with the + underscore, and avoiding too generic names. + + For m lines, this field should contain + the user name to add to a group. + + For lines of type r, this field should + be set to -. + + + + ID + + For u and g, the + numeric 32-bit UID or GID of the user/group. Do not use IDs 65535 + or 4294967295, as they have special placeholder meanings. + Specify - for automatic UID/GID allocation + for the user or group (this is strongly recommended unless it is strictly + necessary to use a specific UID or GID). Alternatively, specify an absolute path + in the file system. In this case, the UID/GID is read from the + path's owner/group. This is useful to create users whose UID/GID + match the owners of pre-existing files (such as SUID or SGID + binaries). + The syntax uid:gid is also supported to + allow creating user and group pairs with different numeric UID and GID values. The group with the indicated GID must get created explicitly before or it must already exist. Specifying - for the UID in this syntax + is also supported. + + + For m lines, this field should contain + the group name to add to a user to. + + For lines of type r, this field should + be set to a UID/GID range in the format + FROM-TO, where both values are formatted as + decimal ASCII numbers. Alternatively, a single UID/GID may be + specified formatted as decimal ASCII numbers. + + + + GECOS + + A short, descriptive string for users to be created, enclosed in + quotation marks. Note that this field may not contain colons. + + Only applies to lines of type u and should otherwise + be left unset (or -). + + + + Home Directory + + The home directory for a new system user. If omitted, defaults to the + root directory. + + Only applies to lines of type u and should otherwise + be left unset (or -). It is recommended to omit this, unless + software strictly requires a home directory to be set. + + + + Shell + + The login shell of the user. If not specified, this will be set to + /usr/sbin/nologin, except if the UID of the user is 0, in + which case /bin/sh will be used. + + Only applies to lines of type u and should otherwise + be left unset (or -). It is recommended to omit this, unless + a shell different /usr/sbin/nologin must be used. + + + + + Specifiers + + Specifiers can be used in the "Name", "ID", "GECOS", "Home directory", and "Shell" fields. + An unknown or unresolvable specifier is treated as invalid configuration. + The following expansions are understood: + + Specifiers available + + + + + + + Specifier + Meaning + Details + + + + + %b + Boot ID + The boot ID of the running system, formatted as string. See random4 for more information. + + + %H + Host name + The hostname of the running system. + + + %m + Machine ID + The machine ID of the running system, formatted as string. See machine-id5 for more information. + + + %T + Directory for temporary files + This is either /tmp or the path $TMPDIR, $TEMP or $TMP are set to. + + + %v + Kernel release + Identical to uname -r output. + + + %V + Directory for larger and persistent temporary files + This is either /var/tmp or the path $TMPDIR, $TEMP or $TMP are set to. + + + %% + Escaped % + Single percent sign. + + + +
+
+ + + Idempotence + + Note that systemd-sysusers will do nothing if the + specified users or groups already exist or the users are members of specified + groups, so normally there is no reason to override + sysusers.d vendor configuration, except to block certain + users or groups from being created. + + + + See Also + + systemd1, + systemd-sysusers8 + + + +
diff --git a/man/telinit.xml b/man/telinit.xml new file mode 100644 index 00000000..43871eb3 --- /dev/null +++ b/man/telinit.xml @@ -0,0 +1,152 @@ + + + + + + + + telinit + systemd + + + + telinit + 8 + + + + telinit + Change SysV runlevel + + + + + telinit OPTIONS COMMAND + + + + + Description + + telinit may be used to change the SysV + system runlevel. Since the concept of SysV runlevels is obsolete + the runlevel requests will be transparently translated into + systemd unit activation requests. + + + + + Options + + The following options are understood: + + + + + + + + + + + + Do not send wall message before + reboot/halt/power-off. + + + + The following commands are understood: + + + + 0 + + Power-off the machine. This is translated into + an activation request for poweroff.target + and is equivalent to systemctl + poweroff. + + + + 6 + + Reboot the machine. This is translated into an + activation request for reboot.target and + is equivalent to systemctl + reboot. + + + + 2 + 3 + 4 + 5 + + Change the SysV runlevel. This is translated + into an activation request for + runlevel2.target, + runlevel3.target, … and is equivalent + to systemctl isolate runlevel2.target, + systemctl isolate runlevel3.target, + … + + + + 1 + s + S + + Change into system rescue mode. This is + translated into an activation request for + rescue.target and is equivalent to + systemctl rescue. + + + + q + Q + + Reload daemon configuration. This is + equivalent to systemctl + daemon-reload. + + + + u + U + + Serialize state, reexecute daemon and + deserialize state again. This is equivalent to + systemctl daemon-reexec. + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure + code otherwise. + + + + Notes + + This is a legacy command available for compatibility only. + It should not be used anymore, as the concept of runlevels is + obsolete. + + + + See Also + + systemd1, + systemctl1, + wall1 + + + + diff --git a/man/threads-aware.xml b/man/threads-aware.xml new file mode 100644 index 00000000..49de3444 --- /dev/null +++ b/man/threads-aware.xml @@ -0,0 +1,15 @@ + + + + + + +All functions listed here are thread-agnostic and only a single specific thread may operate on a +given object during its entire lifetime. It's safe to allocate multiple independent objects and use each from a +specific thread in parallel. However, it's not safe to allocate such an object in one thread, and operate or free it +from any other, even if locking is used to ensure these threads don't operate on it at the very same time. + +All functions listed here are thread-safe and may be called in parallel from multiple threads. + + diff --git a/man/timedatectl.xml b/man/timedatectl.xml new file mode 100644 index 00000000..a8c1f5c0 --- /dev/null +++ b/man/timedatectl.xml @@ -0,0 +1,325 @@ + + + + + + + + timedatectl + systemd + + + + timedatectl + 1 + + + + timedatectl + Control the system time and date + + + + + timedatectl + OPTIONS + COMMAND + + + + + Description + + timedatectl may be used to query and change the system clock and its settings, + and enable or disable time synchronization services. + + Use + systemd-firstboot1 + to initialize the system time zone for mounted (but not booted) + system images. + + timedatectl may be used to show the current status of time synchronization + services, for example + systemd-timesyncd.service8. + + + + + + Commands + + The following commands are understood: + + + + status + + Show current settings of the system clock and RTC, including whether network time + synchronization is active. If no command is specified, this is the implied default. + + + + + show + + Show the same information as , but in machine readable form. + This command is intended to be used whenever computer-parsable output is required. + Use if you are looking for formatted human-readable output. + By default, empty properties are suppressed. Use to show those too. + To select specific properties to show, use . + + + + set-time [TIME] + + Set the system clock to the specified time. + This will also update the RTC time accordingly. The time may + be specified in the format "2012-10-30 + 18:17:16". + + + + set-timezone [TIMEZONE] + + Set the system time zone to the specified + value. Available timezones can be listed with + list-timezones. If the RTC is configured to + be in the local time, this will also update the RTC time. This + call will alter the /etc/localtime + symlink. See + localtime5 + for more information. + + + + list-timezones + + List available time zones, one per line. + Entries from the list can be set as the system timezone with + set-timezone. + + + + set-local-rtc [BOOL] + + Takes a boolean argument. If + 0, the system is configured to maintain the + RTC in universal time. If 1, it will + maintain the RTC in local time instead. Note that maintaining + the RTC in the local timezone is not fully supported and will + create various problems with time zone changes and daylight + saving adjustments. If at all possible, keep the RTC in UTC + mode. Note that invoking this will also synchronize the RTC + from the system clock, unless + is passed (see above). + This command will change the 3rd line of + /etc/adjtime, as documented in + hwclock8. + + + + + set-ntp [BOOL] + + Takes a boolean argument. Controls whether network time synchronization is active and + enabled (if available). If the argument is true, this enables and starts the first existing network + synchronization service. If the argument is false, then this disables and stops the known network + synchronization services. The way that the list of services is built is described below. + + + + + + + systemd-timesyncd Commands + + The following commands are specific to + systemd-timesyncd.service8. + + + + + timesync-status + + Show current status of + systemd-timesyncd.service8. + If is specified, then this will monitor the status updates. + + + + show-timesync + + Show the same information as , but in machine readable form. + This command is intended to be used whenever computer-parsable output is required. + Use if you are looking for formatted human-readable output. + By default, empty properties are suppressed. Use to show those too. + To select specific properties to show, use . + + + + ntp-servers INTERFACE SERVER… + + Set the interface specific NTP servers. This command can be used only when the + interface is managed by systemd-networkd. + + + + revert INTERFACE + + Revert the interface specific NTP servers. This command can be used only when + the interface is managed by systemd-networkd. + + + + + + + + + Options + + The following options are understood: + + + + + + Do not query the user for authentication for + privileged operations. + + + + + + If set-local-rtc is invoked + and this option is passed, the system clock is synchronized + from the RTC again, taking the new setting into account. + Otherwise, the RTC is synchronized from the system + clock. + + + + + + If timesync-status is invoked and this option is passed, then + timedatectl monitors the status of + systemd-timesyncd.service8 + and updates the outputs. Use CtrlC to terminate the + monitoring. + + + + + + + When showing properties of + systemd-timesyncd.service8, + show all properties regardless of whether they are set or not. + + + + + + + When showing properties of + systemd-timesyncd.service8, + limit display to certain properties as specified as argument. If not specified, all set properties are shown. + The argument should be a property name, such as ServerName. If specified more than once, + all properties with the specified names are shown. + + + + + + + When printing properties with show-timesync, only print the value, and skip the + property name and =. + + + + + + + + + + + + + Exit status + + On success, 0 is returned, a non-zero failure code otherwise. + + + + + + Examples + Show current settings: + $ timedatectl + Local time: Thu 2017-09-21 16:08:56 CEST + Universal time: Thu 2017-09-21 14:08:56 UTC + RTC time: Thu 2017-09-21 14:08:56 + Time zone: Europe/Warsaw (CEST, +0200) +System clock synchronized: yes + NTP service: active + RTC in local TZ: no + + + Enable network time synchronization: + $ timedatectl set-ntp true +==== AUTHENTICATING FOR org.freedesktop.timedate1.set-ntp === +Authentication is required to control whether network time synchronization shall be enabled. +Authenticating as: user +Password: ******** +==== AUTHENTICATION COMPLETE === + + $ systemctl status systemd-timesyncd.service +● systemd-timesyncd.service - Network Time Synchronization + Loaded: loaded (/usr/lib/systemd/system/systemd-timesyncd.service; enabled) + Active: active (running) since Mo 2015-03-30 14:20:38 CEST; 5s ago + Docs: man:systemd-timesyncd.service(8) + Main PID: 595 (systemd-timesyn) + Status: "Using Time Server 216.239.38.15:123 (time4.google.com)." + CGroup: /system.slice/systemd-timesyncd.service + └─595 /usr/lib/systemd/systemd-timesyncd +… + + + Show current status of + systemd-timesyncd.service8: + $ timedatectl timesync-status + Server: 216.239.38.15 (time4.google.com) +Poll interval: 1min 4s (min: 32s; max 34min 8s) + Leap: normal + Version: 4 + Stratum: 1 + Reference: GPS + Precision: 1us (-20) +Root distance: 335us (max: 5s) + Offset: +316us + Delay: 349us + Jitter: 0 + Packet count: 1 + Frequency: -8.802ppm + + + + + + See Also + + systemd1, + hwclock8, + date1, + localtime5, + systemctl1, + systemd-timedated.service8, + systemd-timesyncd.service8, + systemd-firstboot1 + + + + diff --git a/man/timesyncd.conf.xml b/man/timesyncd.conf.xml new file mode 100644 index 00000000..c64d0154 --- /dev/null +++ b/man/timesyncd.conf.xml @@ -0,0 +1,106 @@ + + + + + + + timesyncd.conf + systemd + + + + timesyncd.conf + 5 + + + + timesyncd.conf + timesyncd.conf.d + Network Time Synchronization configuration files + + + + /etc/systemd/timesyncd.conf + /etc/systemd/timesyncd.conf.d/*.conf + /run/systemd/timesyncd.conf.d/*.conf + /usr/lib/systemd/timesyncd.conf.d/*.conf + + + + Description + + These configuration files control NTP network time synchronization. See + systemd.syntax5 + for a general description of the syntax. + + + + + + Options + + The following settings are configured in the [Time] section: + + + + + NTP= + A space-separated list of NTP server host + names or IP addresses. During runtime this list is combined + with any per-interface NTP servers acquired from + systemd-networkd.service8. + systemd-timesyncd will contact all configured system or + per-interface servers in turn until one is found that + responds. When the empty string is assigned, the list of + NTP servers is reset, and all assignments prior to this one + will have no effect. This setting defaults to an empty + list. + + + + FallbackNTP= + A space-separated list of NTP server host + names or IP addresses to be used as the fallback NTP servers. + Any per-interface NTP servers obtained from + systemd-networkd.service8 + take precedence over this setting, as do any servers set via + NTP= above. This setting is hence only used + if no other NTP server information is known. When the empty + string is assigned, the list of NTP servers is reset, + and all assignments prior to this one will have no effect. + If this option is not given, a compiled-in list of NTP servers + is used instead. + + + + RootDistanceMaxSec= + Maximum acceptable root distance. Takes a time value (in seconds). + Defaults to 5 seconds. + + + + PollIntervalMinSec= + PollIntervalMaxSec= + The minimum and maximum poll intervals for NTP messages. + Each setting takes a time value (in seconds). + PollIntervalMinSec= must not be smaller than 16 seconds. + PollIntervalMaxSec= must be larger than PollIntervalMinSec=. + PollIntervalMinSec= defaults to 32 seconds, and + PollIntervalMaxSec= defaults to 2048 seconds. + + + + + + + See Also + + systemd1, + systemd-timesyncd.service8, + systemd-networkd.service8 + + + + diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml new file mode 100644 index 00000000..5915012f --- /dev/null +++ b/man/tmpfiles.d.xml @@ -0,0 +1,817 @@ + + + + + + + tmpfiles.d + systemd + + + + tmpfiles.d + 5 + + + + tmpfiles.d + Configuration for creation, deletion and cleaning of + volatile and temporary files + + + + /etc/tmpfiles.d/*.conf +/run/tmpfiles.d/*.conf +/usr/lib/tmpfiles.d/*.conf + + + ~/.config/user-tmpfiles.d/*.conf +$XDG_RUNTIME_DIR/user-tmpfiles.d/*.conf +~/.local/share/user-tmpfiles.d/*.conf +… +/usr/share/user-tmpfiles.d/*.conf + + + #Type Path Mode User Group Age Argument +f /file/to/create mode user group - content +f+ /file/to/create-or-truncate mode user group - content +w /file/to/write-to - - - - content +w+ /file/to/append-to - - - - content +d /directory/to/create-and-cleanup mode user group cleanup-age - +D /directory/to/create-and-remove mode user group cleanup-age - +e /directory/to/cleanup mode user group cleanup-age - +v /subvolume/to/create mode user group - - +v /subvolume-or-directory/to/create mode user group - - +Q /subvolume/to/create mode user group - - +p /fifo/to/create mode user group - - +p+ /fifo/to/[re]create mode user group - - +L /symlink/to/create - - - - symlink/target/path +L+ /symlink/to/[re]create - - - - symlink/target/path +c /dev/char-device-to-create mode user group - - +c+ /dev/char-device-to-[re]create mode user group - - +b /dev/block-device-to-create mode user group - - +b+ /dev/block-device-to-[re]create mode user group - - +C /target/to/create - - - - /source/to/copy +x /path-or-glob/to/ignore - - - - - +X /path-or-glob/to/ignore/recursively - - - - - +r /empty/dir/to/remove - - - - - +R /dir/to/remove/recursively - - - - - +z /path-or-glob/to/adjust/mode mode user group - MAC context +Z /path-or-glob/to/adjust/mode/recursively mode user group - MAC context +t /path-or-glob/to/set/xattrs - - - - xattrs +T /path-or-glob/to/set/xattrs/recursively - - - - xattrs +h /path-or-glob/to/set/attrs - - - - file attrs +H /path-or-glob/to/set/attrs/recursively - - - - file attrs +a /path-or-glob/to/set/acls - - - - POSIX ACLs +a+ /path-or-glob/to/append/acls - - - - POSIX ACLs +A /path-or-glob/to/set/acls/recursively - - - - POSIX ACLs +A+ /path-or-glob/to/append/acls/recursively - - - - POSIX ACLs + + + + + + Description + + tmpfiles.d configuration files provide a generic mechanism to define the + creation of regular files, directories, pipes, and device nodes, adjustments to + their access mode, ownership, attributes, quota assignments, and contents, and + finally their time-based removal. It is mostly commonly used for volatile and + temporary files and directories (such as those located under /run, + /tmp, /var/tmp, the API file systems such as + /sys or /proc, as well as some other directories below + /var). + + systemd-tmpfiles uses this configuration to create volatile files and + directories during boot and to do periodic cleanup afterwards. See + systemd-tmpfiles5 for + the description of systemd-tmpfiles-setup.service, + systemd-tmpfiles-cleanup.service, and associated units. + + System daemons frequently require private runtime directories below /run to + store communication sockets and similar. For these, is is better to use + RuntimeDirectory= in their unit files (see + systemd.exec5 for + details), if the flexibility provided by tmpfiles.d is not required. The advantages + are that the configuration required by the unit is centralized in one place, and that the lifetime of the + directory is tied to the lifetime of the service itself. Similarly, StateDirectory=, + CacheDirectory=, LogsDirectory=, and + ConfigurationDirectory= should be used to create directories under + /var/lib/, /var/cache/, /var/log/, and + /etc/. tmpfiles.d should be used for files whose lifetime is + independent of any service or requires more complicated configuration. + + + + Configuration Directories and Precedence + + Each configuration file shall be named in the style of + package.conf or + package-part.conf. + The second variant should be used when it is desirable to make it + easy to override just this part of configuration. + + Files in /etc/tmpfiles.d override files with the same name in + /usr/lib/tmpfiles.d and /run/tmpfiles.d. Files in + /run/tmpfiles.d override files with the same name in + /usr/lib/tmpfiles.d. Packages should install their configuration files in + /usr/lib/tmpfiles.d. Files in /etc/tmpfiles.d are reserved for the local + administrator, who may use this logic to override the configuration files installed by vendor packages. All + configuration files are sorted by their filename in lexicographic order, regardless of which of the directories + they reside in. If multiple files specify the same path, the entry in the file with the lexicographically earliest + name will be applied. All other conflicting entries will be logged as errors. When two lines are prefix path and + suffix path of each other, then the prefix line is always created first, the suffix later (and if removal applies + to the line, the order is reversed: the suffix is removed first, the prefix later). Lines that take globs are + applied after those accepting no globs. If multiple operations shall be applied on the same file (such as ACL, + xattr, file attribute adjustments), these are always done in the same fixed order. Except for those cases, the + files/directories are processed in the order they are listed. + + If the administrator wants to disable a configuration file + supplied by the vendor, the recommended way is to place a symlink + to /dev/null in + /etc/tmpfiles.d/ bearing the same filename. + + + + + Configuration File Format + + The configuration format is one line per path containing + type, path, mode, ownership, age, and argument fields: + + #Type Path Mode User Group Age Argument +d /run/user 0755 root root 10d - +L /tmp/foobar - - - - /dev/null + + Fields may be enclosed within quotes and contain C-style escapes. + + + Type + + The type consists of a single letter and optionally an + exclamation mark and/or minus sign. + + The following line types are understood: + + + + f + f+ + f will create a file if it does not exist yet. If the argument + parameter is given and the file did not exist yet, it will be written to the file. + f+ will create or truncate the file. If the argument parameter is given, it will + be written to the file. Does not follow symlinks. + + + + w + w+ + Write the argument parameter to a file, if the file exists. + If suffixed with +, the line will be appended to the file. + If your configuration writes multiple lines to the same file, use w+. + Lines of this type accept shell-style globs in place of normal path names. + The argument parameter will be written without a trailing newline. + C-style backslash escapes are interpreted. Follows symlinks. + + + + d + Create a directory. The mode and ownership will be adjusted if specified. Contents + of this directory are subject to time based cleanup if the age argument is specified. + + + + + D + Similar to d, but in addition the contents of the directory will + be removed when is used. + + + + e + Adjust the mode and ownership of existing directories and remove their contents + based on age. + Lines of this type accept shell-style globs in place of normal path names. Contents of the + directories are subject to time based cleanup if the age argument is specified. If the age argument + is 0, contents will be unconditionally deleted every time + systemd-tmpfiles --clean is run. + + For this entry to be useful, at least one of the mode, user, group, or age arguments must be + specified, since otherwise this entry has no effect. As an exception, an entry with no effect may + be useful when combined with !, see the examples. + + + + v + Create a subvolume if the path does not exist yet, the file system supports + subvolumes (btrfs), and the system itself is installed into a subvolume (specifically: the root + directory / is itself a subvolume). Otherwise, create a normal directory, in + the same way as d. + + A subvolume created with this line type is not assigned to any higher-level quota group. For + that, use q or Q, which allow creating simple quota group + hierarchies, see below. + + + + q + Create a subvolume or directory the same as v, but assign the + subvolume to the same higher-level quota groups as the parent. This ensures that higher-level + limits and accounting applied to the parent subvolume also include the specified subvolume. On + non-btrfs file systems, this line type is identical to d. + + If the subvolume already exists, no change to the quota hierarchy is made, regardless of whether the + subvolume is already attached to a quota group or not. Also see Q below. See btrfs-qgroup8 for + details about the btrfs quota group concept. + + + + Q + Create the subvolume or directory the same as v, but assign the + new subvolume to a new leaf quota group. Instead of copying the higher-level quota group + assignments from the parent as is done with q, the lowest quota group of the + parent subvolume is determined that is not the leaf quota group. Then, an "intermediary" quota + group is inserted that is one level below this level, and shares the same ID part as the specified + subvolume. If no higher-level quota group exists for the parent subvolume, a new quota group at + level 255 sharing the same ID as the specified subvolume is inserted instead. This new intermediary + quota group is then assigned to the parent subvolume's higher-level quota groups, and the specified + subvolume's leaf quota group is assigned to it. + + Effectively, this has a similar effect as q, however introduces a new higher-level + quota group for the specified subvolume that may be used to enforce limits and accounting to the specified + subvolume and children subvolume created within it. Thus, by creating subvolumes only via + q and Q, a concept of "subtree quotas" is implemented. Each subvolume + for which Q is set will get a "subtree" quota group created, and all child subvolumes + created within it will be assigned to it. Each subvolume for which q is set will not get + such a "subtree" quota group, but it is ensured that they are added to the same "subtree" quota group as + their immediate parents. + + It is recommended to use Q for subvolumes that typically contain further subvolumes, + and where it is desirable to have accounting and quota limits on all child subvolumes together. Examples for + Q are typically /home or /var/lib/machines. In + contrast, q should be used for subvolumes that either usually do not include further + subvolumes or where no accounting and quota limits are needed that apply to all child subvolumes + together. Examples for q are typically /var or + /var/tmp. + + As with q, Q has no effect on the quota group hierarchy if the + subvolume already exists, regardless of whether the subvolume already belong to a quota group or not. + + + + + p + p+ + Create a named pipe (FIFO) if it does not + exist yet. If suffixed with + and a file + already exists where the pipe is to be created, it will be + removed and be replaced by the pipe. + + + + L + L+ + Create a symlink if it does not exist + yet. If suffixed with + and a file or + directory already exists where the symlink is to be created, + it will be removed and be replaced by the symlink. If the + argument is omitted, symlinks to files with the same name + residing in the directory + /usr/share/factory/ are created. Note + that permissions and ownership on symlinks are ignored. + + + + + c + c+ + Create a character device node if it does + not exist yet. If suffixed with + and a + file already exists where the device node is to be created, + it will be removed and be replaced by the device node. It is + recommended to suffix this entry with an exclamation mark to + only create static device nodes at boot, as udev will not + manage static device nodes that are created at runtime. + + + + + b + b+ + Create a block device node if it does not + exist yet. If suffixed with + and a file + already exists where the device node is to be created, it + will be removed and be replaced by the device node. It is + recommended to suffix this entry with an exclamation mark to + only create static device nodes at boot, as udev will not + manage static device nodes that are created at runtime. + + + + + C + Recursively copy a file or directory, if the + destination files or directories do not exist yet or the + destination directory is empty. Note that this command will not + descend into subdirectories if the destination directory already + exists and is not empty. Instead, the entire copy operation is + skipped. If the argument is omitted, files from the source directory + /usr/share/factory/ with the same name + are copied. Does not follow symlinks. + + + + x + Ignore a path during cleaning. Use this type + to exclude paths from clean-up as controlled with the Age + parameter. Note that lines of this type do not influence the + effect of r or R + lines. Lines of this type accept shell-style globs in place + of normal path names. + + + + X + Ignore a path during cleaning. Use this type + to exclude paths from clean-up as controlled with the Age + parameter. Unlike x, this parameter will + not exclude the content if path is a directory, but only + directory itself. Note that lines of this type do not + influence the effect of r or + R lines. Lines of this type accept + shell-style globs in place of normal path names. + + + + + r + Remove a file or directory if it exists. + This may not be used to remove non-empty directories, use + R for that. Lines of this type accept + shell-style globs in place of normal path + names. Does not follow symlinks. + + + + R + Recursively remove a path and all its + subdirectories (if it is a directory). Lines of this type + accept shell-style globs in place of normal path + names. Does not follow symlinks. + + + + z + Adjust the access mode, user and group ownership, and restore the SELinux security + context of a file or directory, if it exists. Lines of this type accept shell-style globs in place + of normal path names. Does not follow symlinks. + + + + Z + Recursively set the access mode, user and group ownership, and restore the SELinux + security context of a file or directory if it exists, as well as of its subdirectories and the + files contained therein (if applicable). Lines of this type accept shell-style globs in place of + normal path names. Does not follow symlinks. + + + + t + Set extended attributes, see attr + 5 for details. The argument field should take one or more + assignment expressions in the form + namespace.attribute=value, + for examples see below. Lines of this type accept shell-style globs in place of normal path + names. This can be useful for setting SMACK labels. Does not follow symlinks. + + Please note that extended attributes settable with this line type are a different concept + from the Linux file attributes settable with h/H, see + below. + + + + T + Same as t, but operates recursively. + + + + h + Set Linux file/directory attributes. Lines of this type accept shell-style globs in + place of normal path names. + + The format of the argument field is [+-=][aAcCdDeijPsStTu]. The prefix + + (the default one) causes the attribute(s) to be added; - + causes the attribute(s) to be removed; = causes the attributes to be set exactly + as the following letters. The letters aAcCdDeijPsStTu select the new attributes + for the files, see chattr + 1 for further information. + + + Passing only = as argument resets all the file attributes listed above. It + has to be pointed out that the = prefix limits itself to the attributes + corresponding to the letters listed here. All other attributes will be left untouched. Does not + follow symlinks. + + Please note that the Linux file attributes settable with this line type are a different + concept from the extended attributes settable with t/T, + see above. + + + + H + Sames as h, but operates recursively. + + + + a + a+ + Set POSIX ACLs (access control lists), see acl + 5. If suffixed with +, the specified + entries will be added to the existing set. systemd-tmpfiles will automatically + add the required base entries for user and group based on the access mode of the file, unless base + entries already exist or are explicitly specified. The mask will be added if not specified + explicitly or already present. Lines of this type accept shell-style globs in place of normal path + names. This can be useful for allowing additional access to certain files. Does not follow + symlinks. + + + + A + A+ + Same as a and + a+, but recursive. Does not follow + symlinks. + + + + If the exclamation mark is used, this line is only safe to + execute during boot, and can break a running system. Lines + without the exclamation mark are presumed to be safe to execute + at any time, e.g. on package upgrades. + systemd-tmpfiles will execute line with an + exclamation mark only if option is + given. + + For example: + # Make sure these are created by default so that nobody else can +d /tmp/.X11-unix 1777 root root 10d + +# Unlink the X11 lock files +r! /tmp/.X[0-9]*-lock + The second line in contrast to the first one would break a + running system, and will only be executed with + . + + If the minus sign is used, this line failing to run + successfully during create (and only create) will not cause + the execution of systemd-tmpfiles to return + an error. + + For example: + # Modify sysfs but don't fail if we are in a container with a read-only /proc +w- /proc/sys/vm/swappiness - - - - 10 + + Note that for all line types that result in creation of any kind of file node + (i.e. f/F, + d/D/v/q/Q, + p, L, c/b and C) + leading directories are implicitly created if needed, owned by root with an access mode of 0755. In order to + create them with different modes or ownership make sure to add appropriate d lines. + + + + Path + + The file system path specification supports simple + specifier expansion, see below. The path (after expansion) must be + absolute. + + + + Mode + + The file access mode to use when creating this file or + directory. If omitted or when set to -, the + default is used: 0755 for directories, 0644 for all other file + objects. For z, Z lines, + if omitted or when set to -, the file access + mode will not be modified. This parameter is ignored for + x, r, + R, L, t, + and a lines. + + Optionally, if prefixed with ~, the + access mode is masked based on the already set access bits for + existing file or directories: if the existing file has all + executable bits unset, all executable bits are removed from the + new access mode, too. Similarly, if all read bits are removed + from the old access mode, they will be removed from the new + access mode too, and if all write bits are removed, they will be + removed from the new access mode too. In addition, the + sticky/SUID/SGID bit is removed unless applied to a + directory. This functionality is particularly useful in + conjunction with Z. + + + + User, Group + + The user and group to use for this file or directory. This may either be a numeric ID or a + user/group name. If omitted or when set to -, the user and group of the user who + invokes systemd-tmpfiles is used. For z and Z + lines, when omitted or when set to -, the file ownership will not be modified. These + parameters are ignored for x, r, R, + L, t, and a lines. + + This field should generally only reference system users/groups, i.e. users/groups that are + guaranteed to be resolvable during early boot. If this field references users/groups that only become + resolveable during later boot (i.e. after NIS, LDAP or a similar networked directory service become + available), execution of the operations declared by the line will likely fail. Also see Notes on + Resolvability of User and Group Names for more information on requirements on system user/group + definitions. + + + + Age + The date field, when set, is used to decide what files to + delete when cleaning. If a file or directory is older than the + current time minus the age field, it is deleted. The field + format is a series of integers each followed by one of the + following suffixes for the respective time units: + s, + m or min, + h, + d, + w, + ms, and + us, + meaning seconds, minutes, hours, days, weeks, + milliseconds, and microseconds, respectively. Full names of the time units can + be used too. + + + If multiple integers and units are specified, the time + values are summed. If an integer is given without a unit, + s is assumed. + + + When the age is set to zero, the files are cleaned + unconditionally. + + The age field only applies to lines starting with + d, D, e, + v, q, + Q, C, x + and X. If omitted or set to + -, no automatic clean-up is done. + + If the age field starts with a tilde character + ~, the clean-up is only applied to files and + directories one level inside the directory specified, but not + the files and directories immediately inside it. + + The age of a file system entry is determined from its last + modification timestamp (mtime), its last access timestamp (atime), + and (except for directories) its last status change timestamp + (ctime). Any of these three (or two) values will prevent cleanup + if it is more recent than the current time minus the age + field. + + Note that while the aging algorithm is run a 'shared' BSD file lock (see flock2) is + taken on each directory the algorithm descends into (and each directory below that, and so on). If the + aging algorithm finds a lock is already taken on some directory, it (and everything below it) is + skipped. Applications may use this to temporarily exclude certain directory subtrees from the aging + algorithm: the applications can take a BSD file lock themselves, and as long as they keep it aging of + the directory and everything below it is disabled. + + + + Argument + + For L lines determines the destination path of the symlink. For c and + b, determines the major/minor of the device node, with major and minor formatted as integers, + separated by :, e.g. 1:3. For f, F, + and w, the argument may be used to specify a short string that is written to the file, + suffixed by a newline. For C, specifies the source file or directory. For t + and T, determines extended attributes to be set. For a and + A, determines ACL attributes to be set. For h and H, + determines the file attributes to set. Ignored for all other lines. + + This field can contain specifiers, see below. + + + + + Specifiers + + Specifiers can be used in the "path" and "argument" fields. + An unknown or unresolvable specifier is treated as invalid configuration. + The following expansions are understood: + + Specifiers available + + + + + + + Specifier + Meaning + Details + + + + + %b + Boot ID + The boot ID of the running system, formatted as string. See random4 for more information. + + + %C + System or user cache directory + In mode, this is the same as $XDG_CACHE_HOME, and /var/cache otherwise. + + + %h + User home directory + This is the home directory of the user running the command. In case of the system instance this resolves to /root. + + + %H + Host name + The hostname of the running system. + + + %L + System or user log directory + In mode, this is the same as $XDG_CONFIG_HOME with /log appended, and /var/log otherwise. + + + %m + Machine ID + The machine ID of the running system, formatted as string. See machine-id5 for more information. + + + %S + System or user state directory + In mode, this is the same as $XDG_CONFIG_HOME, and /var/lib otherwise. + + + %t + System or user runtime directory + In mode, this is the same $XDG_RUNTIME_DIR, and /run otherwise. + + + %T + Directory for temporary files + This is either /tmp or the path $TMPDIR, $TEMP or $TMP are set to. + + + %g + User group + This is the name of the group running the command. In case of the system instance this resolves to root. + + + %G + User GID + This is the numeric GID of the group running the command. In case of the system instance this resolves to 0. + + + %u + User name + This is the name of the user running the command. In case of the system instance this resolves to root. + + + %U + User UID + This is the numeric UID of the user running the command. In case of the system instance this resolves to 0. + + + %v + Kernel release + Identical to uname -r output. + + + %V + Directory for larger and persistent temporary files + This is either /var/tmp or the path $TMPDIR, $TEMP or $TMP are set to. + + + %% + Escaped % + Single percent sign. + + + +
+
+ + + Examples + + Create directories with specific mode and ownership + + screen1, + needs two directories created at boot with specific modes and ownership: + + # /usr/lib/tmpfiles.d/screen.conf +d /run/screens 1777 root screen 10d +d /run/uscreens 0755 root screen 10d12h + + + Contents of /run/screens and /run/uscreens will + be cleaned up after 10 and 10½ days, respectively. + + + + Create a directory with a SMACK attribute + D /run/cups - - - - +t /run/cups - - - - security.SMACK64=printing user.attr-with-spaces="foo bar" + + + The directory will be owned by root and have default mode. Its contents are + not subject to time based cleanup, but will be obliterated when + systemd-tmpfiles --remove runs. + + + + Create a directory and prevent its contents from cleanup + + abrt1, + needs a directory created at boot with specific mode and ownership and its content + should be preserved from the automatic cleanup applied to the contents of + /var/tmp: + + # /usr/lib/tmpfiles.d/tmp.conf +d /var/tmp 1777 root root 30d + + + # /usr/lib/tmpfiles.d/abrt.conf +d /var/tmp/abrt 0755 abrt abrt - + + + + + Apply clean up during boot and based on time + + # /usr/lib/tmpfiles.d/dnf.conf +r! /var/cache/dnf/*/*/download_lock.pid +r! /var/cache/dnf/*/*/metadata_lock.pid +r! /var/lib/dnf/rpmdb_lock.pid +e /var/cache/dnf/ - - - 30d + + + The lock files will be removed during boot. Any files and directories in + /var/cache/dnf/ will be removed after they have not been + accessed in 30 days. + + + + Empty the contents of a cache directory on boot + + # /usr/lib/tmpfiles.d/krb5rcache.conf +e! /var/cache/krb5rcache - - - 0 + + + Any files and subdirectories in /var/cache/krb5rcache/ + will be removed on boot. The directory will not be created. + + + + + + <filename>/run/</filename> and <filename>/var/run/</filename> + /var/run/ is a deprecated symlink to /run/, and + applications should use the latter. systemd-tmpfiles will warn if + /var/run/ is used. + + + + See Also + + systemd1, + systemd-tmpfiles8, + systemd-delta1, + systemd.exec5, + attr5, + getfattr1, + setfattr1, + setfacl1, + getfacl1, + chattr1, + btrfs-subvolume8, + btrfs-qgroup8 + + + +
diff --git a/man/udev.conf.xml b/man/udev.conf.xml new file mode 100644 index 00000000..04301c81 --- /dev/null +++ b/man/udev.conf.xml @@ -0,0 +1,117 @@ + + + + + + + + udev.conf + systemd + + + + udev.conf + 5 + + + + udev.conf + Configuration for device event managing daemon + + + + /etc/udev/udev.conf + + + + Description + + + systemd-udevd8 + expects its main configuration file at + /etc/udev/udev.conf. It consists of a set + of variables allowing the user to override default udev + values. All empty lines or lines beginning with '#' are + ignored. The following variables can be set: + + + + + udev_log= + + + The log level. Valid values are the numerical + syslog priorities or their textual representations: + , and + . + + + + + children_max= + + + An integer. The maximum number of events executed in parallel. + + This is the same as the option. + + + + + exec_delay= + + + An integer. Delay the execution of RUN + instructions by the given number of seconds. This option + might be useful when debugging system crashes during + coldplug caused by loading non-working kernel + modules. + + This is the same as the option. + + + + + event_timeout= + + + An integer. The number of seconds to wait for events to finish. After + this time, the event will be terminated. The default is 180 seconds. + + This is the same as the option. + + + + + resolve_names= + + + Specifes when systemd-udevd should resolve names of users and groups. When set to + (the default), names will be resolved when the rules are parsed. + When set to , names will be resolved for every event. When set to + , names will never be resolved and all devices will be owned by + root. + + This is the same as the option. + + + + + + In addition, systemd-udevd can be configured + by command line options and the kernel command line (see + systemd-udevd8). + + + + + See Also + + systemd-udevd8, + udev7, + udevadm8 + + + diff --git a/man/udev.xml b/man/udev.xml new file mode 100644 index 00000000..09254f81 --- /dev/null +++ b/man/udev.xml @@ -0,0 +1,789 @@ + + + + + + + + udev + systemd + + + + udev + 7 + + + + udev + Dynamic device management + + + Description + udev supplies the system software with device events, manages permissions + of device nodes and may create additional symlinks in the /dev + directory, or renames network interfaces. The kernel usually just assigns unpredictable + device names based on the order of discovery. Meaningful symlinks or network device + names provide a way to reliably identify devices based on their properties or + current configuration. + + The udev daemon, systemd-udevd.service + 8, receives device uevents directly from + the kernel whenever a device is added or removed from the system, or it changes its + state. When udev receives a device event, it matches its configured set of rules + against various device attributes to identify the device. Rules that match may + provide additional device information to be stored in the udev database or + to be used to create meaningful symlink names. + + All device information udev processes is stored in the udev database and + sent out to possible event subscribers. Access to all stored data and the event + sources is provided by the library libudev. + + + Rules Files + The udev rules are read from the files located in the system rules directories + /usr/lib/udev/rules.d and /usr/local/lib/udev/rules.d, the + volatile runtime directory /run/udev/rules.d and the local administration + directory /etc/udev/rules.d. All rules files are collectively sorted and + processed in lexical order, regardless of the directories in which they live. However, files with + identical filenames replace each other. Files in /etc have the highest priority, + files in /run take precedence over files with the same name under + /usr. This can be used to override a system-supplied rules file with a local + file if needed; a symlink in /etc with the same name as a rules file in + /usr/lib, pointing to /dev/null, disables the rules file + entirely. Rule files must have the extension .rules; other extensions are + ignored. + + Every line in the rules file contains at least one key-value pair. + Except for empty lines or lines beginning with #, which are ignored. + There are two kinds of keys: match and assignment. + If all match keys match against their values, the rule gets applied and the + assignment keys get the specified values assigned. + + A matching rule may rename a network interface, add symlinks + pointing to the device node, or run a specified program as part of + the event handling. + + A rule consists of a comma-separated list of one or more key-value pairs. + Each key has a distinct operation, depending on the used operator. Valid + operators are: + + + == + + Compare for equality. + + + + + != + + Compare for inequality. + + + + + = + + Assign a value to a key. Keys that represent a list are reset + and only this single value is assigned. + + + + + += + + Add the value to a key that holds a list of entries. + + + + + -= + + Remove the value from a key that holds a list of entries. + + + + + := + + Assign a value to a key finally; disallow any later changes. + + + + + The following key names can be used to match against device properties. + Some of the keys also match against properties of the parent devices in sysfs, + not only the device that has generated the event. If multiple keys that match + a parent device are specified in a single rule, all these keys must match at + one and the same parent device. + + + ACTION + + Match the name of the event action. + + + + + DEVPATH + + Match the devpath of the event device. + + + + + KERNEL + + Match the name of the event device. + + + + + NAME + + Match the name of a network interface. It can be used once the + NAME key has been set in one of the preceding rules. + + + + + SYMLINK + + Match the name of a symlink targeting the node. It can + be used once a SYMLINK key has been set in one of the preceding + rules. There may be multiple symlinks; only one needs to match. + + + + + + SUBSYSTEM + + Match the subsystem of the event device. + + + + DRIVER + + Match the driver name of the event device. Only set this key for devices + which are bound to a driver at the time the event is generated. + + + + ATTR{filename} + + Match sysfs attribute values of the event device. Trailing + whitespace in the attribute values is ignored unless the specified match + value itself contains trailing whitespace. + + + + + SYSCTL{kernel parameter} + + Match a kernel parameter value. + + + + + + KERNELS + + Search the devpath upwards for a matching device name. + + + + + SUBSYSTEMS + + Search the devpath upwards for a matching device subsystem name. + + + + + DRIVERS + + Search the devpath upwards for a matching device driver name. + + + + + ATTRS{filename} + + Search the devpath upwards for a device with matching sysfs attribute values. + If multiple ATTRS matches are specified, all of them + must match on the same device. Trailing whitespace in the attribute values is ignored + unless the specified match value itself contains trailing whitespace. + + + + + TAGS + + Search the devpath upwards for a device with matching tag. + + + + + ENV{key} + + Match against a device property value. + + + + + CONST{key} + + Match against a system-wide constant. Supported keys are: + + + arch + + System's architecture. See in + systemd.unit5 + for possible values. + + + + virt + + System's virtualization environment. See + systemd-detect-virt1 + for possible values. + + + + Unknown keys will never match. + + + + + TAG + + Match against a device tag. + + + + + TEST{octal mode mask} + + Test the existence of a file. An octal mode mask can be specified + if needed. + + + + + PROGRAM + + Execute a program to determine whether there + is a match; the key is true if the program returns + successfully. The device properties are made available to the + executed program in the environment. The program's standard output + is available in the RESULT key. + This can only be used for very short-running foreground tasks. For details, + see RUN. + + + + + RESULT + + Match the returned string of the last PROGRAM call. + This key can be used in the same or in any later rule after a + PROGRAM call. + + + + + Most of the fields support shell glob pattern matching and + alternate patterns. The following special characters are supported: + + + * + + Matches zero or more characters. + + + + ? + + Matches any single character. + + + + [] + + Matches any single character specified within the brackets. For + example, the pattern string tty[SR] + would match either ttyS or ttyR. + Ranges are also supported via the - character. + For example, to match on the range of all digits, the pattern + [0-9] could be used. If the first character + following the [ is a !, + any characters not enclosed are matched. + + + + | + + Separates alternative patterns. For example, the pattern string + abc|x* would match either abc + or x*. + + + + + The following keys can get values assigned: + + + NAME + + The name to use for a network interface. See + systemd.link5 + for a higher-level mechanism for setting the interface name. + The name of a device node cannot be changed by udev, only additional + symlinks can be created. + + + + + SYMLINK + + The name of a symlink targeting the node. Every matching rule adds + this value to the list of symlinks to be created. + The set of characters to name a symlink is limited. Allowed + characters are 0-9A-Za-z#+-.:=@_/, valid UTF-8 character + sequences, and \x00 hex encoding. All other + characters are replaced by a _ character. + Multiple symlinks may be specified by separating the names by the + space character. In case multiple devices claim the same name, the link + always points to the device with the highest link_priority. If the current + device goes away, the links are re-evaluated and the device with the + next highest link_priority becomes the owner of the link. If no + link_priority is specified, the order of the devices (and which one of + them owns the link) is undefined. + Symlink names must never conflict with the kernel's default device + node names, as that would result in unpredictable behavior. + + + + + + OWNER, GROUP, MODE + + The permissions for the device node. Every specified value overrides + the compiled-in default value. + + + + + SECLABEL{module} + + Applies the specified Linux Security Module label to the device node. + + + + + ATTR{key} + + The value that should be written to a sysfs attribute of the + event device. + + + + + SYSCTL{kernel parameter} + + The value that should be written to kernel parameter. + + + + + ENV{key} + + Set a device property value. Property names with a leading . + are neither stored in the database nor exported to events or + external tools (run by, for example, the PROGRAM + match key). + + + + + TAG + + Attach a tag to a device. This is used to filter events for users + of libudev's monitor functionality, or to enumerate a group of tagged + devices. The implementation can only work efficiently if only a few + tags are attached to a device. It is only meant to be used in + contexts with specific device filter requirements, and not as a + general-purpose flag. Excessive use might result in inefficient event + handling. + + + + + RUN{type} + + Add a program to the list of programs to be executed after + processing all the rules for a specific event, depending on + type: + + + program + + Execute an external program specified as the assigned + value. If no absolute path is given, the program is expected + to live in /usr/lib/udev; otherwise, the + absolute path must be specified. + This is the default if no type + is specified. + + + + builtin + + As program, but use one of the + built-in programs rather than an external one. + + + + The program name and following arguments are separated by spaces. + Single quotes can be used to specify arguments with spaces. + This can only be used for very short-running foreground tasks. Running an + event process for a long period of time may block all further events for + this or a dependent device. + Starting daemons or other long-running processes is not appropriate + for udev; the forked processes, detached or not, will be unconditionally + killed after the event handling has finished. + Note that running programs that access the network or mount/unmount + filesystems is not allowed inside of udev rules, due to the default sandbox + that is enforced on systemd-udevd.service. + Please also note that := and = are clearing + both, program and builtin commands. + + + + + LABEL + + A named label to which a GOTO may jump. + + + + + GOTO + + Jumps to the next LABEL with a matching name. + + + + + IMPORT{type} + + Import a set of variables as device properties, + depending on type: + + + program + + Execute an external program specified as the assigned + value and, if it returns successfully, + import its output, which must be in environment key + format. Path specification, command/argument separation, + and quoting work like in RUN. + + + + builtin + + Similar to program, but use one of the + built-in programs rather than an external one. + + + + file + + Import a text file specified as the assigned value, the content + of which must be in environment key format. + + + + db + + Import a single property specified as the assigned value from the + current device database. This works only if the database is already populated + by an earlier event. + + + + cmdline + + Import a single property from the kernel command line. For simple flags + the value of the property is set to 1. + + + + parent + + Import the stored keys from the parent device by reading + the database entry of the parent device. The value assigned to + is used as a filter of key names + to import (with the same shell glob pattern matching used for + comparisons). + + + + This can only be used for very short-running foreground tasks. For details + see . + + + + + OPTIONS + + Rule and device options: + + + + + Specify the priority of the created symlinks. Devices with higher + priorities overwrite existing symlinks of other devices. The default is 0. + + + + + + Usually, control and other possibly unsafe characters are replaced + in strings used for device naming. The mode of replacement can be specified + with this option. + + + + + + Apply the permissions specified in this rule to the + static device node with the specified name. Also, for every + tag specified in this rule, create a symlink + in the directory + /run/udev/static_node-tags/tag + pointing at the static device node with the specified name. + Static device node creation is performed by systemd-tmpfiles + before systemd-udevd is started. The static nodes might not + have a corresponding kernel device; they are used to trigger + automatic kernel module loading when they are accessed. + + + + + + Watch the device node with inotify; when the node is + closed after being opened for writing, a change uevent is + synthesized. + + + + + + Disable the watching of a device node with inotify. + + + + + + Set the flag (sticky bit) on the udev database entry + of the event device. Device properties are then kept in the + database even when + udevadm info --cleanup-db is called. + This option can be useful in certain cases + (e.g. Device Mapper devices) for persisting device state + on the transition from initramfs. + + + + + + + + The NAME, SYMLINK, + PROGRAM, OWNER, + GROUP, MODE, SECLABEL, + and RUN fields support simple string substitutions. + The RUN substitutions are performed after all rules + have been processed, right before the program is executed, allowing for + the use of device properties set by earlier matching rules. For all other + fields, substitutions are performed while the individual rule is being + processed. The available substitutions are: + + + , + + The kernel name for this device. + + + + + , + + The kernel number for this device. For example, + sda3 has kernel number 3. + + + + + + , + + The devpath of the device. + + + + + , + + The name of the device matched while searching the devpath + upwards for , , + , and . + + + + + + + + The driver name of the device matched while searching the + devpath upwards for , + , , and + . + + + + + + , + + The value of a sysfs attribute found at the device where + all keys of the rule have matched. If the matching device does not + have such an attribute, and a previous , + , , or + test selected a parent device, then the + attribute from that parent device is used. + + If the attribute is a symlink, the last element of the + symlink target is returned as the value. + + + + + + , + + A device property value. + + + + + , + + The kernel major number for the device. + + + + + , + + The kernel minor number for the device. + + + + + , + + The string returned by the external program requested with + PROGRAM. + A single part of the string, separated by a space character, may be selected + by specifying the part number as an attribute: %c{N}. + If the number is followed by the + character, this part plus all remaining parts + of the result string are substituted: %c{N+}. + + + + + , + + The node name of the parent device. + + + + + + + The current name of the device. If not changed by a rule, it is the + name of the kernel device. + + + + + + + A space-separated list of the current symlinks. The value is + only set during a remove event or if an earlier rule assigned a value. + + + + + , + + The udev_root value. + + + + + , + + The sysfs mount point. + + + + + , + + The name of the device node. + + + + + + + The % character itself. + + + + + + + The $ character itself. + + + + + + + See Also + + + systemd-udevd.service8 + , + + udevadm8 + , + + systemd.link5 + + + + diff --git a/man/udev_device_get_syspath.xml b/man/udev_device_get_syspath.xml new file mode 100644 index 00000000..0deb1d0d --- /dev/null +++ b/man/udev_device_get_syspath.xml @@ -0,0 +1,180 @@ + + +%entities; +]> + + + + + + udev_device_get_syspath + systemd + + + + udev_device_get_syspath + 3 + + + + udev_device_get_syspath + udev_device_get_sysname + udev_device_get_sysnum + udev_device_get_devpath + udev_device_get_devnode + udev_device_get_devnum + udev_device_get_devtype + udev_device_get_subsystem + udev_device_get_driver + udev_device_get_udev + udev_device_get_parent + udev_device_get_parent_with_subsystem_devtype + udev_device_get_is_initialized + udev_device_get_action + + Query device properties + + + + + #include <libudev.h> + + + const char *udev_device_get_syspath + struct udev_device *udev_device + + + + const char *udev_device_get_sysname + struct udev_device *udev_device + + + + const char *udev_device_get_sysnum + struct udev_device *udev_device + + + + const char *udev_device_get_devpath + struct udev_device *udev_device + + + + const char *udev_device_get_devnode + struct udev_device *udev_device + + + + dev_t udev_device_get_devnum + struct udev_device *udev_device + + + + const char *udev_device_get_devtype + struct udev_device *udev_device + + + + const char *udev_device_get_subsystem + struct udev_device *udev_device + + + + const char *udev_device_get_driver + struct udev_device *udev_device + + + + struct udev *udev_device_get_udev + struct udev_device *udev_device + + + + struct udev_device *udev_device_get_parent + struct udev_device *udev_device + + + + struct udev_device *udev_device_get_parent_with_subsystem_devtype + struct udev_device *udev_device + const char *subsystem + const char *devtype + + + + int udev_device_get_is_initialized + struct udev_device *udev_device + + + + const char *udev_device_get_action + struct udev_device *udev_device + + + + + + + + + Return Value + + On success, udev_device_get_syspath(), + udev_device_get_sysname(), + udev_device_get_sysnum(), + udev_device_get_devpath(), + udev_device_get_devnode(), + udev_device_get_devtype(), + udev_device_get_subsystem(), + udev_device_get_driver() and + udev_device_get_action() return a pointer + to a constant string that describes the requested property. The + lifetime of this string is bound to the device it was requested + on. On failure, each function may return + NULL. + + On success, udev_device_get_devnum() + returns the device type of the passed device. On failure, a + device type with minor and major number set to + 0 is returned. + + udev_device_get_udev() always returns + a valid pointer to the udev context that this device belongs + to. + + On success, udev_device_get_parent() + and + udev_device_get_parent_with_subsystem_devtype() + return a pointer to the parent device. No additional reference + to this device is acquired, but the child device owns a reference + to such a parent device. On failure, NULL + is returned. + + On success, udev_device_get_is_initialized() returns either 1 or + 0, depending on whether the passed device has already been initialized by udev or not. On + failure, a negative error code is returned. Note that devices for which no udev rules are defined are never + reported initialized. + + + + See Also + + + udev_new3, + udev_device_new_from_syspath3, + udev_device_has_tag3, + udev_enumerate_new3, + udev_monitor_new_from_netlink3, + udev_list_entry3, + systemd1, + + + + diff --git a/man/udev_device_has_tag.xml b/man/udev_device_has_tag.xml new file mode 100644 index 00000000..9c64a4b4 --- /dev/null +++ b/man/udev_device_has_tag.xml @@ -0,0 +1,143 @@ + + +%entities; +]> + + + + + + udev_device_has_tag + systemd + + + + udev_device_has_tag + 3 + + + + udev_device_has_tag + udev_device_get_devlinks_list_entry + udev_device_get_properties_list_entry + udev_device_get_tags_list_entry + udev_device_get_sysattr_list_entry + udev_device_get_property_value + udev_device_get_sysattr_value + udev_device_set_sysattr_value + + Retrieve or set device attributes + + + + + #include <libudev.h> + + + struct udev_list_entry *udev_device_get_devlinks_list_entry + struct udev_device *udev_device + + + + struct udev_list_entry *udev_device_get_properties_list_entry + struct udev_device *udev_device + + + + struct udev_list_entry *udev_device_get_tags_list_entry + struct udev_device *udev_device + + + + struct udev_list_entry *udev_device_get_sysattr_list_entry + struct udev_device *udev_device + + + + const char *udev_device_get_property_value + struct udev_device *udev_device + const char *key + + + + int udev_device_has_tag + struct udev_device *udev_device + const char *tag + + + + const char *udev_device_get_sysattr_value + struct udev_device *udev_device + const char *sysattr + + + + int udev_device_set_sysattr_value + struct udev_device *udev_device + const char *sysattr + const char *value + + + + + + + + + Return Value + + On success, + udev_device_get_devlinks_list_entry(), + udev_device_get_properties_list_entry(), + udev_device_get_tags_list_entry() and + udev_device_get_sysattr_list_entry() return + a pointer to the first entry of the retrieved list. If that list + is empty, or if an error occurred, NULL is + returned. + + On success, + udev_device_get_property_value() and + udev_device_get_sysattr_value() return a + pointer to a constant string of the requested value. On error, + NULL is returned. Attributes that may + contain NUL bytes should not be retrieved + with udev_device_get_sysattr_value(); + instead, read them directly from the files within the device's + syspath. + + On success, + udev_device_set_sysattr_value() returns + an integer greater than, or equal to, 0. + On failure, a negative error code is returned. Values that + contain NUL bytes should not be set with + this function; instead, write them directly to the files within + the device's syspath. + + On success, udev_device_has_tag() + returns 1 or 0, + depending on whether the device has the given tag or not. + On failure, a negative error code is returned. + + + + See Also + + + udev_new3, + udev_device_new_from_syspath3, + udev_device_get_syspath3, + udev_enumerate_new3, + udev_monitor_new_from_netlink3, + udev_list_entry3, + systemd1, + + + + diff --git a/man/udev_device_new_from_syspath.xml b/man/udev_device_new_from_syspath.xml new file mode 100644 index 00000000..118adfa2 --- /dev/null +++ b/man/udev_device_new_from_syspath.xml @@ -0,0 +1,187 @@ + + +%entities; +]> + + + + + + udev_device_new_from_syspath + systemd + + + + udev_device_new_from_syspath + 3 + + + + udev_device_new_from_syspath + udev_device_new_from_devnum + udev_device_new_from_subsystem_sysname + udev_device_new_from_device_id + udev_device_new_from_environment + udev_device_ref + udev_device_unref + + Create, acquire and release a udev device object + + + + + #include <libudev.h> + + + struct udev_device *udev_device_new_from_syspath + struct udev *udev + const char *syspath + + + + struct udev_device *udev_device_new_from_devnum + struct udev *udev + char type + dev_t devnum + + + + struct udev_device *udev_device_new_from_subsystem_sysname + struct udev *udev + const char *subsystem + const char *sysname + + + + struct udev_device *udev_device_new_from_device_id + struct udev *udev + const char *id + + + + struct udev_device *udev_device_new_from_environment + struct udev *udev + + + + struct udev_device *udev_device_ref + struct udev_device *udev_device + + + + struct udev_device *udev_device_unref + struct udev_device *udev_device + + + + + + + Description + + udev_device_new_from_syspath, + udev_device_new_from_devnum, + udev_device_new_from_subsystem_sysname, + udev_device_new_from_device_id, and + udev_device_new_from_environment + allocate a new udev device object and returns a pointer to it. This + object is opaque and must not be accessed by the caller via different + means than functions provided by libudev. Initially, the reference count + of the device is 1. You can acquire further references, and drop + gained references via udev_device_ref() and + udev_device_unref(). Once the reference count hits 0, + the device object is destroyed and freed. + + udev_device_new_from_syspath, + udev_device_new_from_devnum, + udev_device_new_from_subsystem_sysname, and + udev_device_new_from_device_id + create the device object based on information found in + /sys, annotated with properties from the udev-internal + device database. A syspath is any subdirectory of /sys, + with the restriction that a subdirectory of /sys/devices + (or a symlink to one) represents a real device and as such must contain + a uevent file. udev_device_new_from_devnum + takes a device type, which can be b for block devices or + c for character devices, as well as a devnum (see + makedev3). + udev_device_new_from_subsystem_sysname looks up devices based + on the provided subsystem and sysname + (see udev_device_get_subsystem3 + and + udev_device_get_sysname3) + and udev_device_new_from_device_id looks up devices based on the provided + device ID, which is a special string in one of the following four forms: + + Device ID strings + + + + + + Example + Explanation + + + b8:2 + block device major:minor + + c128:1 + char device major:minor + + n3 + network device ifindex + + +sound:card29 + kernel driver core subsystem:device name + + +
+
+ + udev_device_new_from_environment + creates a device from the current environment (see + environ7). + Each key-value pair is interpreted in the same way as if it was + received in an uevent (see + udev_monitor_receive_device3). + The keys DEVPATH, SUBSYSTEM, + ACTION, and SEQNUM are mandatory. + +
+ + + Return Value + + On success, udev_device_new_from_syspath(), + udev_device_new_from_devnum(), + udev_device_new_from_subsystem_sysname(), + udev_device_new_from_device_id() and + udev_device_new_from_environment() return a + pointer to the allocated udev device. On failure, + NULL is returned, + and errno is set appropriately. + udev_device_ref() returns the argument + that it was passed, unmodified. + udev_device_unref() always returns + NULL. + + + + See Also + + + udev_new3, + udev_device_get_syspath3, + udev_device_has_tag3, + udev_enumerate_new3, + udev_monitor_new_from_netlink3, + udev_list_entry3, + systemd1, + + + +
diff --git a/man/udev_enumerate_add_match_subsystem.xml b/man/udev_enumerate_add_match_subsystem.xml new file mode 100644 index 00000000..0dbb926f --- /dev/null +++ b/man/udev_enumerate_add_match_subsystem.xml @@ -0,0 +1,136 @@ + + +%entities; +]> + + + + + + udev_enumerate_add_match_subsystem + systemd + + + + udev_enumerate_add_match_subsystem + 3 + + + + udev_enumerate_add_match_subsystem + udev_enumerate_add_nomatch_subsystem + udev_enumerate_add_match_sysattr + udev_enumerate_add_nomatch_sysattr + udev_enumerate_add_match_property + udev_enumerate_add_match_sysname + udev_enumerate_add_match_tag + udev_enumerate_add_match_parent + udev_enumerate_add_match_is_initialized + + Modify filters + + + + + #include <libudev.h> + + + int udev_enumerate_add_match_subsystem + struct udev_enumerate *udev_enumerate + const char *subsystem + + + + int udev_enumerate_add_nomatch_subsystem + struct udev_enumerate *udev_enumerate + const char *subsystem + + + + int udev_enumerate_add_match_sysattr + struct udev_enumerate *udev_enumerate + const char *sysattr + const char *value + + + + int udev_enumerate_add_nomatch_sysattr + struct udev_enumerate *udev_enumerate + const char *sysattr + const char *value + + + + int udev_enumerate_add_match_property + struct udev_enumerate *udev_enumerate + const char *property + const char *value + + + + int udev_enumerate_add_match_sysname + struct udev_enumerate *udev_enumerate + const char *sysname + + + + int udev_enumerate_add_match_tag + struct udev_enumerate *udev_enumerate + const char *tag + + + + int udev_enumerate_add_match_parent + struct udev_enumerate *udev_enumerate + struct udev_device *parent + + + + int udev_enumerate_add_match_is_initialized + struct udev_enumerate *udev_enumerate + + + + + + + + + Return Value + + On success, + udev_enumerate_add_match_subsystem, + udev_enumerate_add_nomatch_subsystem, + udev_enumerate_add_match_sysattr, + udev_enumerate_add_nomatch_sysattr, + udev_enumerate_add_match_property, + udev_enumerate_add_match_sysname, + udev_enumerate_add_match_tag, + udev_enumerate_add_match_parent and + udev_enumerate_add_match_is_initialized + return an integer greater than, or equal to, + 0. + + + + See Also + + + udev_new3, + udev_device_new_from_syspath3, + udev_enumerate_new3, + udev_enumerate_scan_devices3, + udev_monitor_new_from_netlink3, + udev_list_entry3, + systemd1, + + + + diff --git a/man/udev_enumerate_new.xml b/man/udev_enumerate_new.xml new file mode 100644 index 00000000..013d5cc8 --- /dev/null +++ b/man/udev_enumerate_new.xml @@ -0,0 +1,84 @@ + + +%entities; +]> + + + + + + udev_enumerate_new + systemd + + + + udev_enumerate_new + 3 + + + + udev_enumerate_new + udev_enumerate_ref + udev_enumerate_unref + + Create, acquire and release a udev enumerate object + + + + + #include <libudev.h> + + + struct udev_enumerate *udev_enumerate_new + struct udev *udev + + + + struct udev_enumerate *udev_enumerate_ref + struct udev_enumerate *udev_enumerate + + + + struct udev_enumerate *udev_enumerate_unref + struct udev_enumerate *udev_enumerate + + + + + + + + + Return Value + + On success, udev_enumerate_new() returns a + pointer to the allocated udev monitor. On failure, + NULL is returned. + udev_enumerate_ref() returns the argument + that it was passed, unmodified. + udev_enumerate_unref() always returns + NULL. + + + + See Also + + + udev_new3, + udev_device_new_from_syspath3, + udev_enumerate_add_match_subsystem3, + udev_enumerate_scan_devices3, + udev_monitor_new_from_netlink3, + udev_list_entry3, + systemd1, + + + + diff --git a/man/udev_enumerate_scan_devices.xml b/man/udev_enumerate_scan_devices.xml new file mode 100644 index 00000000..d3dddd41 --- /dev/null +++ b/man/udev_enumerate_scan_devices.xml @@ -0,0 +1,106 @@ + + +%entities; +]> + + + + + + udev_enumerate_scan_devices + systemd + + + + udev_enumerate_scan_devices + 3 + + + + udev_enumerate_scan_devices + udev_enumerate_scan_subsystems + udev_enumerate_get_list_entry + udev_enumerate_add_syspath + udev_enumerate_get_udev + + Query or modify a udev enumerate object + + + + + #include <libudev.h> + + + int udev_enumerate_scan_devices + struct udev_enumerate *udev_enumerate + + + + int udev_enumerate_scan_subsystems + struct udev_enumerate *udev_enumerate + + + + struct udev_list_entry *udev_enumerate_get_list_entry + struct udev_enumerate *udev_enumerate + + + + int udev_enumerate_add_syspath + struct udev_enumerate *udev_enumerate + const char *syspath + + + + struct udev *udev_enumerate_get_udev + struct udev_enumerate *udev_enumerate + + + + + + + + + Return Value + + On success, + udev_enumerate_scan_devices(), + udev_enumerate_scan_subsystems() and + udev_enumerate_add_syspath() + return an integer greater than, or equal to, + 0. + + On success, + udev_enumerate_get_list_entry() + returns a pointer to the first entry in the list of found + devices. If the list is empty, or on failure, + NULL is returned. + + udev_enumerate_get_udev() always + returns a pointer to the udev context that this enumerated + object is associated with. + + + + See Also + + + udev_new3, + udev_device_new_from_syspath3, + udev_enumerate_new3, + udev_enumerate_add_match_subsystem3, + udev_monitor_new_from_netlink3, + udev_list_entry3, + systemd1, + + + + diff --git a/man/udev_list_entry.xml b/man/udev_list_entry.xml new file mode 100644 index 00000000..9f44812c --- /dev/null +++ b/man/udev_list_entry.xml @@ -0,0 +1,96 @@ + + +%entities; +]> + + + + + + udev_list_entry + systemd + + + + udev_list_entry + 3 + + + + udev_list_entry + udev_list_entry_get_next + udev_list_entry_get_by_name + udev_list_entry_get_name + udev_list_entry_get_value + + Iterate and access udev lists + + + + + #include <libudev.h> + + + struct udev_list_entry *udev_list_entry_get_next + struct udev_list_entry *list_entry + + + + struct udev_list_entry *udev_list_entry_get_by_name + struct udev_list_entry *list_entry + const char *name + + + + const char *udev_list_entry_get_name + struct udev_list_entry *list_entry + + + + const char *udev_list_entry_get_value + struct udev_list_entry *list_entry + + + + + + + + + Return Value + + On success, + udev_list_entry_get_next() and + udev_list_entry_get_by_name() return + a pointer to the requested list entry. If no such entry can + be found, or on failure, NULL is + returned. + + On success, + udev_list_entry_get_name() and + udev_list_entry_get_value() return a + pointer to a constant string representing the requested value. + The string is bound to the lifetime of the list entry itself. + On failure, NULL is returned. + + + + See Also + + + udev_new3, + udev_device_new_from_syspath3, + udev_enumerate_new3, + udev_monitor_new_from_netlink3, + systemd1, + + + + diff --git a/man/udev_monitor_filter_update.xml b/man/udev_monitor_filter_update.xml new file mode 100644 index 00000000..88a19f1d --- /dev/null +++ b/man/udev_monitor_filter_update.xml @@ -0,0 +1,95 @@ + + +%entities; +]> + + + + + + udev_monitor_filter_update + systemd + + + + udev_monitor_filter_update + 3 + + + + udev_monitor_filter_update + udev_monitor_filter_remove + udev_monitor_filter_add_match_subsystem_devtype + udev_monitor_filter_add_match_tag + + Modify filters + + + + + #include <libudev.h> + + + int udev_monitor_filter_update + struct udev_monitor *udev_monitor + + + + int udev_monitor_filter_remove + struct udev_monitor *udev_monitor + + + + int udev_monitor_filter_add_match_subsystem_devtype + struct udev_monitor *udev_monitor + const char *subsystem + const char *devtype + + + + int udev_monitor_filter_add_match_tag + struct udev_monitor *udev_monitor + const char *tag + + + + + + + + + Return Value + + On success, + udev_monitor_filter_update(), + udev_monitor_filter_remove(), + udev_monitor_filter_add_match_subsystem_devtype() + and + udev_monitor_filter_add_match_tag() + return an integer greater than, or equal to, + 0. On failure, a negative error code is + returned. + + + + See Also + + + udev_new3, + udev_device_new_from_syspath3, + udev_enumerate_new3, + udev_monitor_new_from_netlink3, + udev_monitor_receive_device3, + udev_list_entry3, + systemd1, + + + + diff --git a/man/udev_monitor_new_from_netlink.xml b/man/udev_monitor_new_from_netlink.xml new file mode 100644 index 00000000..cc37d219 --- /dev/null +++ b/man/udev_monitor_new_from_netlink.xml @@ -0,0 +1,86 @@ + + +%entities; +]> + + + + + + udev_monitor_new_from_netlink + systemd + + + + udev_monitor_new_from_netlink + 3 + + + + udev_monitor_new_from_netlink + udev_monitor_ref + udev_monitor_unref + + Create, acquire and release a udev monitor object + + + + + #include <libudev.h> + + + struct udev_monitor *udev_monitor_new_from_netlink + struct udev *udev + const char *name + + + + struct udev_monitor *udev_monitor_ref + struct udev_monitor *udev_monitor + + + + struct udev_monitor *udev_monitor_unref + struct udev_monitor *udev_monitor + + + + + + + + + Return Value + + On success, + udev_monitor_new_from_netlink() returns a + pointer to the allocated udev monitor. On failure, + NULL is returned. + udev_monitor_ref() returns the argument + that it was passed, unmodified. + udev_monitor_unref() always returns + NULL. + + + + See Also + + + udev_new3, + udev_device_new_from_syspath3, + udev_enumerate_new3, + udev_monitor_filter_update3, + udev_monitor_receive_device3, + udev_list_entry3, + systemd1, + + + + diff --git a/man/udev_monitor_receive_device.xml b/man/udev_monitor_receive_device.xml new file mode 100644 index 00000000..5b3f097d --- /dev/null +++ b/man/udev_monitor_receive_device.xml @@ -0,0 +1,110 @@ + + +%entities; +]> + + + + + + udev_monitor_receive_device + systemd + + + + udev_monitor_receive_device + 3 + + + + udev_monitor_receive_device + udev_monitor_enable_receiving + udev_monitor_set_receive_buffer_size + udev_monitor_get_fd + udev_monitor_get_udev + + Query and modify device monitor + + + + + #include <libudev.h> + + + struct udev_device *udev_monitor_receive_device + struct udev_monitor *udev_monitor + + + + int udev_monitor_enable_receiving + struct udev_monitor *udev_monitor + + + + int udev_monitor_set_receive_buffer_size + struct udev_monitor *udev_monitor + int size + + + + int udev_monitor_get_fd + struct udev_monitor *udev_monitor + + + + struct udev *udev_monitor_get_udev + struct udev_monitor *udev_monitor + + + + + + + + + Return Value + + On success, + udev_monitor_receive_device() returns a + pointer to a newly referenced device that was received via the + monitor. The caller is responsible to drop this reference when + done. On failure, NULL is returned. + + On success, + udev_monitor_enable_receiving() and + udev_monitor_set_receive_buffer_size() + return an integer greater than, or equal to, + 0. On failure, a negative error code is + returned. + + On success, udev_monitor_get_fd() + returns the file descriptor used by this monitor. On failure, + a negative error code is returned. + + udev_monitor_get_udev() always returns + a pointer to the udev context that this monitor is associated + with. + + + + See Also + + + udev_new3, + udev_device_new_from_syspath3, + udev_enumerate_new3, + udev_monitor_new_from_netlink3, + udev_monitor_filter_update3, + udev_list_entry3, + systemd1, + + + + diff --git a/man/udev_new.xml b/man/udev_new.xml new file mode 100644 index 00000000..89fa05e3 --- /dev/null +++ b/man/udev_new.xml @@ -0,0 +1,83 @@ + + +%entities; +]> + + + + + + udev_new + systemd + + + + udev_new + 3 + + + + udev_new + udev_ref + udev_unref + + Create, acquire and release a udev context object + + + + + #include <libudev.h> + + + struct udev *udev_new + void + + + + struct udev *udev_ref + struct udev *udev + + + + struct udev *udev_unref + struct udev *udev + + + + + + + Description + + udev_new() allocates a new udev context + object and returns a pointer to it. This object is opaque and must + not be accessed by the caller via different means than functions + provided by libudev. Initially, the reference count of the context + is 1. You can acquire further references, and drop gained references + via udev_ref() and + udev_unref(). Once the reference count hits 0, + the context object is destroyed and freed. + + + + Return Value + + On success, udev_new() returns a pointer + to the allocated udev context. On failure, NULL + is returned. udev_ref() returns the argument + that it was passed, unmodified. udev_unref() + always returns NULL. + + + + See Also + + + systemd1, + + + + diff --git a/man/udevadm.xml b/man/udevadm.xml new file mode 100644 index 00000000..c2f2bc95 --- /dev/null +++ b/man/udevadm.xml @@ -0,0 +1,579 @@ + + + + + + + + udevadm + systemd + + + + udevadm + 8 + + + + udevadmudev management tool + + + + + udevadm + + + + + + udevadm info options devpath + + + udevadm trigger options devpath + + + udevadm settle options + + + udevadm control option + + + udevadm monitor options + + + udevadm test options devpath + + + udevadm test-builtin options command devpath + + + + Description + udevadm expects a command and command + specific options. It controls the runtime behavior of + systemd-udevd, requests kernel events, manages + the event queue, and provides simple debugging mechanisms. + + + Options + + + + + + Print debug messages to standard error. This option is implied in udevadm test and + udevadm test-builtin commands. + + + + + + + udevadm info + <arg choice="opt"><replaceable>options</replaceable></arg> + <arg choice="opt" rep="repeat"><replaceable>devpath</replaceable>|<replaceable>file</replaceable>|<replaceable>unit</replaceable></arg> + + + Query the udev database for device information. + + Positional arguments should be used to specify one or more devices. Each one may be a device name + (in which case it must start with /dev/), a sys path (in which case it must start + with /sys/), or a systemd device unit name (in which case it must end with + .device, see + systemd.device5). + + + + + + + + Query the database for the specified type of device data. + Valid TYPEs are: + name, symlink, + path, property, + all. + + + + + + + + The /sys path of the device to query, e.g. + /sys/class/block/sda. This option is an alternative to + the positional argument with a /sys/ prefix. udevadm info + --path=/class/block/sda is equivalent to udevadm info + /sys/class/block/sda. + + + + + + + The name of the device node or a symlink to query, + e.g. /dev/sda. This option is an alternative to the + positional argument with a /dev/ prefix. udevadm info + --name=sda is equivalent to udevadm info /dev/sda. + + + + + + + Print absolute paths in name or symlink + query. + + + + + + + Print all sysfs properties of the specified device that can be used + in udev rules to match the specified device. It prints all devices + along the chain, up to the root of sysfs that can be used in udev rules. + + + + + + + Print output as key/value pairs. Values are enclosed in single quotes. + This takes effects only when or + is specified. + + + + + + + Add a prefix to the key name of exported values. + This implies . + + + + + + + Print major/minor numbers of the underlying device, where the file lives on. + If this is specified, all positional arguments are ignored. + + + + + + + Export the content of the udev database. + + + + + + + Cleanup the udev database. + + + + + + + Wait for device to be initialized. If argument SECONDS + is not specified, the default is to wait forever. + + + + + + + + udevadm trigger + <arg choice="opt"><replaceable>options</replaceable></arg> + <arg choice="opt"><replaceable>devpath</replaceable>|<replaceable>file</replaceable>|<replaceable>unit</replaceable></arg> + + Request device events from the kernel. Primarily used to replay events at system coldplug time. + + Takes device specifications as positional arguments. See the description of info + above. + + + + + + + Print the list of devices which will be triggered. + + + + + + + Do not actually trigger the event. + + + + + + + Trigger a specific type of devices. Valid types are: + devices, subsystems. + The default value is devices. + + + + + + + Type of event to be triggered. Possible actions are add, + remove, change, move, + online, offline, bind, + and unbind. Also, the special value help can be used + to list the possible actions. The default value is change. + + + + + + + + Trigger events for devices which belong to a + matching subsystem. This option supports shell style pattern matching. + When this option is specified more than once, then each matching result is ORed, that is, + all the devices in each subsystem are triggered. + + + + + + + Do not trigger events for devices which belong to a matching subsystem. This option + supports shell style pattern matching. When this option is specified more than once, + then each matching result is ANDed, that is, devices which do not match all specified + subsystems are triggered. + + + + + + + Trigger events for devices with a matching sysfs attribute. If a value is specified along + with the attribute name, the content of the attribute is matched against the given value using + shell style pattern matching. If no value is specified, the existence of the sysfs attribute is + checked. When this option is specified multiple times, then each matching result is ANDed, + that is, only devices which have all specified attributes are triggered. + + + + + + + Do not trigger events for devices with a matching sysfs attribute. If a value is specified + along with the attribute name, the content of the attribute is matched against the given value + using shell style pattern matching. If no value is specified, the existence of the sysfs attribute + is checked. When this option is specified multiple times, then each matching result is ANDed, + that is, only devices which have none of the specified attributes are triggered. + + + + + + + Trigger events for devices with a matching property value. This option supports shell style + pattern matching. When this option is specified more than once, then each matching result is ORed, + that is, devices which have one of the specified properties are triggered. + + + + + + + Trigger events for devices with a matching tag. When this option is specified multiple times, + then each matching result is ANDed, that is, devices which have all specified tags are triggered. + + + + + + + Trigger events for devices for which the last component (i.e. the filename) of the + /sys path matches the specified PATH. This option + supports shell style pattern matching. When this option is specified more than once, then each + matching result is ORed, that is, all devices which have any of the specified + NAME are triggered. + + + + + + Trigger events for devices with a matching device path. When this option is specified more than once, + then each matching result is ORed, that is, all specified devices are triggered. + + + + + + + Trigger events for all children of a given device. When this option is specified more than once, + then each matching result is ORed, that is, all children of each specified device are triggered. + + + + + + + Apart from triggering events, also waits for those events to + finish. Note that this is different from calling udevadm + settle. udevadm settle waits for all + events to finish. This option only waits for events triggered by + the same command to finish. + + + + + + Before triggering uevents, wait for systemd-udevd daemon to be initialized. + Optionally takes timeout value. Default timeout is 5 seconds. This is equivalent to invoke + invoking udevadm control --ping before udevadm trigger. + + + + + + + In addition, optional positional arguments can be used + to specify device names or sys paths. They must start with + /dev or /sys + respectively. + + + udevadm settle + <arg choice="opt"><replaceable>options</replaceable></arg> + + Watches the udev event queue, and exits if all current events are handled. + + + + + + Maximum number of seconds to wait for the event + queue to become empty. The default value is 120 seconds. A + value of 0 will check if the queue is empty and always + return immediately. + + + + + + + Stop waiting if file exists. + + + + + + + See + systemd-udev-settle.service8 + for more information. + + + udevadm control <replaceable>option</replaceable> + Modify the internal state of the running udev daemon. + + + + + + Signal and wait for systemd-udevd to exit. No option except for + can be specified after this option. + Note that systemd-udevd.service contains + and so as a result, this option restarts systemd-udevd. + If you want to stop systemd-udevd.service, please use the following: + systemctl stop systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd.service + + + + + + + + Set the internal log level of + systemd-udevd. Valid values are the + numerical syslog priorities or their textual + representations: , + , , + , , + , , and + . + + + + + + + Signal systemd-udevd to stop executing new events. Incoming events + will be queued. + + + + + + + Signal systemd-udevd to enable the execution of events. + + + + + + + Signal systemd-udevd to reload the rules files and other databases like the kernel + module index. Reloading rules and databases does not apply any changes to already + existing devices; the new configuration will only be applied to new events. + + + + + + + Set a global property for all events. + + + + + value + + Set the maximum number of events, systemd-udevd will handle at the + same time. + + + + + + Send a ping message to systemd-udevd and wait for the reply. This may be useful to check that + systemd-udevd daemon is running. + + + + + seconds + + The maximum number of seconds to wait for a reply from systemd-udevd. + + + + + + + + udevadm monitor + <arg choice="opt"><replaceable>options</replaceable></arg> + + Listens to the kernel uevents and events sent out by a udev rule + and prints the devpath of the event to the console. It can be used to analyze the + event timing, by comparing the timestamps of the kernel uevent and the udev event. + + + + + + + Print the kernel uevents. + + + + + + + Print the udev event after the rule processing. + + + + + + + Also print the properties of the event. + + + + + + + Filter kernel uevents and udev events by subsystem[/devtype]. Only events with a matching subsystem value will pass. + When this option is specified more than once, then each matching result is ORed, that is, all devices in the specified + subsystems are monitored. + + + + + + + Filter udev events by tag. Only udev events with a given tag attached will pass. + When this option is specified more than once, then each matching result is ORed, that is, devices which have one of the + specified tags are monitored. + + + + + + + + udevadm test + <arg choice="opt"><replaceable>options</replaceable></arg> + <arg><replaceable>devpath</replaceable></arg> + + Simulate a udev event run for the given device, and print debug output. + + + + + + Type of event to be simulated. Possible actions are add, + remove, change, move, + online, offline, bind, + and unbind. Also, the special value help can be used + to list the possible actions. The default value is add. + + + + + + + Specify when udevadm should resolve names of users + and groups. When set to early (the + default), names will be resolved when the rules are + parsed. When set to late, names will + be resolved for every event. When set to + never, names will never be resolved + and all devices will be owned by root. + + + + + + + + udevadm test-builtin + <arg choice="opt"><replaceable>options</replaceable></arg> + <arg><replaceable>command</replaceable></arg> + <arg><replaceable>devpath</replaceable></arg> + + Run a built-in command COMMAND + for device DEVPATH, and print debug + output. + + + + + + + + See Also + + udev7 + , + + systemd-udevd.service8 + + + diff --git a/man/user-system-options.xml b/man/user-system-options.xml new file mode 100644 index 00000000..80347356 --- /dev/null +++ b/man/user-system-options.xml @@ -0,0 +1,52 @@ + + + + + + + + + + Talk to the service manager of the calling user, + rather than the service manager of the system. + + + + + + + + Talk to the service manager of the system. This is the + implied default. + + + + + + + + + Execute the operation remotely. Specify a hostname, or a + username and hostname separated by @, to + connect to. The hostname may optionally be suffixed by a + port ssh is listening on, separated by :, and then a + container name, separated by /, which + connects directly to a specific container on the specified + host. This will use SSH to talk to the remote machine manager + instance. Container names may be enumerated with + machinectl -H + HOST. Put IPv6 addresses in brackets. + + + + + + + + + Execute operation on a local container. Specify a + container name to connect to. + + + diff --git a/man/user@.service.xml b/man/user@.service.xml new file mode 100644 index 00000000..81a6fef4 --- /dev/null +++ b/man/user@.service.xml @@ -0,0 +1,191 @@ + + + + + + + user@.service + systemd + + + + user@.service + 5 + + + + user@.service + user-runtime-dir@.service + System units to manage user processes + + + + user@UID.service + user-runtime-dir@UID.service + user-UID.slice + + + + Description + + The + systemd1 + system manager (PID 1) starts user manager instances as + user@UID.service, where the user's numerical UID + is used as the instance identifier. Each systemd --user instance manages a + hierarchy of its own units. See + systemd1 for + a discussion of systemd units and + systemd.special1 + for a list of units that form the basis of the unit hierarchies of system and user units. + + user@UID.service is accompanied by the + system unit user-runtime-dir@UID.service, which + creates the user's runtime directory + /run/user/UID, and then removes it when this + unit is stopped. + + User processes may be started by the user@.service instance, in which + case they will be part of that unit in the system hierarchy. They may also be started elsewhere, + for example by + sshd8 or a + display manager like gdm, in which case they form a .scope unit (see + systemd.scope5). + Both user@UID.service and the scope units are + collected under a user-UID.slice. + + Individual user-UID.slice slices are + collected under user.slice, see + systemd.special8. + + + + + Controlling resources for logged-in users + + Options that control resources available to logged-in users can be configured at a few + different levels. As described in the previous section, user.slice contains + processes of all users, so any resource limits on that slice apply to all users together. The + usual way to configure them would be through drop-ins, e.g. /etc/systemd/system/user.slice.d/resources.conf. + + + The processes of a single user are collected under + user-UID.slice. Resource limits for that user + can be configured through drop-ins for that unit, e.g. /etc/systemd/system/user-1000.slice.d/resources.conf. If the limits + should apply to all users instead, they may be configured through drop-ins for the truncated + unit name, user-.slice. For example, configuration in /etc/systemd/system/user-.slice.d/resources.conf is included in all + user-UID.slice units, see + systemd.unit5 + for a discussion of the drop-in mechanism. + + When a user logs in and a .scope unit is created for the session (see previous section), + the creation of the scope may be managed through + pam_systemd8. + This PAM module communicates with + systemd-logind8 + to create the session scope and provide access to hardware resources. Resource limits for the + scope may be configured through the PAM module configuration, see + pam_systemd8. + Configuring them through the normal unit configuration is also possible, but since + the name of the slice unit is generally unpredictable, this is less useful. + + In general any resources that apply to units may be set for + user@UID.service and the slice + units discussed above, see + systemd.resource-control5 + for an overview. + + + + Examples + + Hierarchy of control groups with two logged in users + + $ systemd-cgls +Control group /: +-.slice +├─user.slice +│ ├─user-1000.slice +│ │ ├─user@1000.service +│ │ │ ├─pulseaudio.service +│ │ │ │ └─2386 /usr/bin/pulseaudio --daemonize=no +│ │ │ └─gnome-terminal-server.service +│ │ │ └─init.scope +│ │ │ ├─ 4127 /usr/libexec/gnome-terminal-server +│ │ │ └─ 4198 zsh +│ │ … +│ │ └─session-4.scope +│ │ ├─ 1264 gdm-session-worker [pam/gdm-password] +│ │ ├─ 2339 /usr/bin/gnome-shell +│ │ … +│ │ ├─session-19.scope +│ │ ├─6497 sshd: zbyszek [priv] +│ │ ├─6502 sshd: zbyszek@pts/6 +│ │ ├─6509 -zsh +│ │ └─6602 systemd-cgls --no-pager +│ … +│ └─user-1001.slice +│ ├─session-20.scope +│ │ ├─6675 sshd: guest [priv] +│ │ ├─6708 sshd: guest@pts/6 +│ │ └─6717 -bash +│ └─user@1001.service +│ ├─init.scope +│ │ ├─6680 /usr/lib/systemd/systemd --user +│ │ └─6688 (sd-pam) +│ └─sleep.service +│ └─6706 /usr/bin/sleep 30 +… + User with UID 1000 is logged in using gdm (session-4.scope) and + ssh1 + (session-19.scope), and also has a user manager instance + running (user@1000.service). User with UID 1001 is logged + in using ssh (session-20.scope) and + also has a user manager instance running (user@1001.service). Those are all (leaf) system units, and form + part of the slice hierarchy, with user-1000.slice and + user-1001.slice below user.slice. User units are visible below the + user@.service instances (pulseaudio.service, gnome-terminal-server.service, init.scope, sleep.service). + + + + + Default user resource limits + + $ systemctl cat user-1000.slice +# /usr/lib/systemd/system/user-.slice.d/10-defaults.conf +# … +[Unit] +Description=User Slice of UID %j +After=systemd-user-sessions.service + +[Slice] +TasksMax=33% + The user-UID.slice units by default don't + have a unit file. The resource limits are set through a drop-in, which can be easily replaced + or extended following standard drop-in mechanisms discussed in the first section. + + + + + See Also + + systemd1, + systemd.service5, + systemd.slice5, + systemd.resource-control5, + systemd.exec5, + systemd.special7, + pam8 + + + diff --git a/man/vconsole.conf.xml b/man/vconsole.conf.xml new file mode 100644 index 00000000..2e2223cc --- /dev/null +++ b/man/vconsole.conf.xml @@ -0,0 +1,144 @@ + + + + + + + vconsole.conf + systemd + + + + vconsole.conf + 5 + + + + vconsole.conf + Configuration file for the virtual console + + + + /etc/vconsole.conf + + + + Description + + The /etc/vconsole.conf file configures + the virtual console, i.e. keyboard mapping and console font. It is + applied at boot by udev using 90-vconsole.rules file. + You can safely mask this file if you want to avoid this kind of initialization. + + + The basic file format of the + vconsole.conf is a newline-separated list of + environment-like shell-compatible variable assignments. It is + possible to source the configuration from shell scripts, however, + beyond mere variable assignments no shell features are supported, + allowing applications to read the file without implementing a + shell compatible execution engine. + + Note that the kernel command line options + vconsole.keymap=, + vconsole.keymap_toggle=, + vconsole.font=, + vconsole.font_map=, + vconsole.font_unimap= may be used + to override the console settings at boot. + + Depending on the operating system other configuration files + might be checked for configuration of the virtual console as well, + however only as fallback. + + /etc/vconsole.conf is usually created and updated + using + systemd-localed.service8. + localectl1 + may be used to instruct systemd-localed.service to + query or update configuration. + + + + Options + + The following options are understood: + + + + + KEYMAP= + KEYMAP_TOGGLE= + + Configures the key mapping table for the keyboard. + KEYMAP= defaults to us if not set. The + KEYMAP_TOGGLE= can be used to configure a second toggle keymap and is by + default unset. + + + + FONT= + FONT_MAP= + FONT_UNIMAP= + + Configures the console font, the console map + and the unicode font map. + + + + + + + Kernel Command Line + + A few configuration parameters from vconsole.conf may be overridden + on the kernel command line: + + + + vconsole.keymap= + vconsole.keymap_toggle= + + Overrides KEYMAP= and KEYMAP_TOGGLE=. + + + + + vconsole.font= + vconsole.font_map= + vconsole.font_unimap= + + Overrides FONT=, FONT_MAP=, and + FONT_UNIMAP=. + + + + + + Example + + + German keyboard and console + + /etc/vconsole.conf: + + KEYMAP=de-latin1 +FONT=eurlatgr + + + + + + See Also + + systemd1, + systemd-vconsole-setup.service8, + loadkeys1, + setfont8, + locale.conf5, + systemd-localed.service8 + + + + diff --git a/man/vtable-example.c b/man/vtable-example.c new file mode 100644 index 00000000..98c20eec --- /dev/null +++ b/man/vtable-example.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include + +#define _cleanup_(f) __attribute__((cleanup(f))) + +typedef struct object { + char *name; + uint32_t number; +} object; + +static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) { + printf("Got called with userdata=%p\n", userdata); + return 1; +} + +static const sd_bus_vtable vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD( + "Method1", "s", "s", method, 0), + SD_BUS_METHOD_WITH_NAMES_OFFSET( + "Method2", + "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path), + "s", SD_BUS_PARAM(returnstring), + method, offsetof(object, number), + SD_BUS_VTABLE_DEPRECATED), + SD_BUS_WRITABLE_PROPERTY( + "AutomaticStringProperty", "s", NULL, NULL, + offsetof(object, name), + SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_WRITABLE_PROPERTY( + "AutomaticIntegerProperty", "u", NULL, NULL, + offsetof(object, number), + SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_VTABLE_END +}; + +#define check(x) ({ \ + int r = x; \ + errno = r < 0 ? -r : 0; \ + printf(#x ": %m\n"); \ + if (r < 0) \ + return EXIT_FAILURE; \ + }) + +int main(int argc, char **argv) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + + sd_bus_default(&bus); + + object object = { .number = 666 }; + check((object.name = strdup("name")) != NULL); + + check(sd_bus_add_object_vtable(bus, NULL, "/object", + "org.freedesktop.systemd.VtableExample", + vtable, + &object)); + + for (;;) { + check(sd_bus_wait(bus, UINT64_MAX)); + check(sd_bus_process(bus, NULL)); + } + + free(object.name); + + return 0; +} diff --git a/man/vtable-example.xml b/man/vtable-example.xml new file mode 100644 index 00000000..a3cdeae7 --- /dev/null +++ b/man/vtable-example.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..1bdb9c7b --- /dev/null +++ b/meson.build @@ -0,0 +1,3293 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +project('systemd', 'c', + version : '244', + license : 'LGPLv2+', + default_options: [ + 'c_std=gnu99', + 'prefix=/usr', + 'sysconfdir=/etc', + 'localstatedir=/var', + 'warning_level=2', + ], + meson_version : '>= 0.46', + ) + +libsystemd_version = '0.27.1' +libudev_version = '1.6.16' + +# We need the same data in two different formats, ugh! +# Also, for hysterical reasons, we use different variable +# names, sometimes. Not all variables are included in every +# set. Ugh, ugh, ugh! +conf = configuration_data() +conf.set('PROJECT_VERSION', meson.project_version()) + +substs = configuration_data() +substs.set('PROJECT_URL', 'https://www.freedesktop.org/wiki/Software/systemd') +substs.set('PROJECT_VERSION', meson.project_version()) + +# This is to be used instead of meson.source_root(), as the latter will return +# the wrong result when systemd is being built as a meson subproject +project_source_root = meson.current_source_dir() +relative_source_path = run_command('realpath', + '--relative-to=@0@'.format(meson.current_build_dir()), + project_source_root).stdout().strip() +conf.set_quoted('RELATIVE_SOURCE_PATH', relative_source_path) + +want_ossfuzz = get_option('oss-fuzz') +want_libfuzzer = get_option('llvm-fuzz') +want_fuzzbuzz = get_option('fuzzbuzz') +if want_ossfuzz + want_libfuzzer + want_fuzzbuzz > 1 + error('only one of oss-fuzz, llvm-fuzz or fuzzbuzz can be specified') +endif + +skip_deps = want_ossfuzz or want_libfuzzer +fuzzer_build = want_ossfuzz or want_libfuzzer or want_fuzzbuzz + +##################################################################### + +# Try to install the git pre-commit hook +git_hook = run_command(join_paths(project_source_root, 'tools/add-git-hook.sh')) +if git_hook.returncode() == 0 + message(git_hook.stdout().strip()) +endif + +##################################################################### + +if get_option('split-usr') == 'auto' + split_usr = run_command('test', '-L', '/bin').returncode() != 0 +else + split_usr = get_option('split-usr') == 'true' +endif +conf.set10('HAVE_SPLIT_USR', split_usr, + description : '/usr/bin and /bin directories are separate') + +if get_option('split-bin') == 'auto' + split_bin = run_command('test', '-L', '/usr/sbin').returncode() != 0 +else + split_bin = get_option('split-bin') == 'true' +endif +conf.set10('HAVE_SPLIT_BIN', split_bin, + description : 'bin and sbin directories are separate') + +rootprefixdir = get_option('rootprefix') +# Unusual rootprefixdir values are used by some distros +# (see https://github.com/systemd/systemd/pull/7461). +rootprefix_default = split_usr ? '/' : '/usr' +if rootprefixdir == '' + rootprefixdir = rootprefix_default +endif +rootprefixdir_noslash = rootprefixdir == '/' ? '' : rootprefixdir + +sysvinit_path = get_option('sysvinit-path') +sysvrcnd_path = get_option('sysvrcnd-path') +conf.set10('HAVE_SYSV_COMPAT', sysvinit_path != '' and sysvrcnd_path != '', + description : 'SysV init scripts and rcN.d links are supported') + +conf.set10('BUMP_PROC_SYS_FS_FILE_MAX', get_option('bump-proc-sys-fs-file-max')) +conf.set10('BUMP_PROC_SYS_FS_NR_OPEN', get_option('bump-proc-sys-fs-nr-open')) +conf.set('HIGH_RLIMIT_NOFILE', 512*1024) + +# join_paths ignores the preceding arguments if an absolute component is +# encountered, so this should canonicalize various paths when they are +# absolute or relative. +prefixdir = get_option('prefix') +if not prefixdir.startswith('/') + error('Prefix is not absolute: "@0@"'.format(prefixdir)) +endif +bindir = join_paths(prefixdir, get_option('bindir')) +libdir = join_paths(prefixdir, get_option('libdir')) +sysconfdir = join_paths(prefixdir, get_option('sysconfdir')) +includedir = join_paths(prefixdir, get_option('includedir')) +datadir = join_paths(prefixdir, get_option('datadir')) +localstatedir = join_paths('/', get_option('localstatedir')) + +rootbindir = join_paths(rootprefixdir, 'bin') +rootsbindir = join_paths(rootprefixdir, split_bin ? 'sbin' : 'bin') +rootlibexecdir = join_paths(rootprefixdir, 'lib/systemd') + +rootlibdir = get_option('rootlibdir') +if rootlibdir == '' + rootlibdir = join_paths(rootprefixdir, libdir.split('/')[-1]) +endif + +# Dirs of external packages +pkgconfigdatadir = get_option('pkgconfigdatadir') == '' ? join_paths(datadir, 'pkgconfig') : get_option('pkgconfigdatadir') +pkgconfiglibdir = get_option('pkgconfiglibdir') == '' ? join_paths(libdir, 'pkgconfig') : get_option('pkgconfiglibdir') +polkitpolicydir = join_paths(datadir, 'polkit-1/actions') +polkitrulesdir = join_paths(datadir, 'polkit-1/rules.d') +polkitpkladir = join_paths(localstatedir, 'lib/polkit-1/localauthority/10-vendor.d') +xinitrcdir = join_paths(sysconfdir, 'X11/xinit/xinitrc.d') +rpmmacrosdir = get_option('rpmmacrosdir') +if rpmmacrosdir != 'no' + rpmmacrosdir = join_paths(prefixdir, rpmmacrosdir) +endif +modprobedir = join_paths(rootprefixdir, 'lib/modprobe.d') + +# Our own paths +pkgdatadir = join_paths(datadir, 'systemd') +environmentdir = join_paths(prefixdir, 'lib/environment.d') +pkgsysconfdir = join_paths(sysconfdir, 'systemd') +userunitdir = join_paths(prefixdir, 'lib/systemd/user') +userpresetdir = join_paths(prefixdir, 'lib/systemd/user-preset') +tmpfilesdir = join_paths(prefixdir, 'lib/tmpfiles.d') +sysusersdir = join_paths(prefixdir, 'lib/sysusers.d') +sysctldir = join_paths(prefixdir, 'lib/sysctl.d') +binfmtdir = join_paths(prefixdir, 'lib/binfmt.d') +modulesloaddir = join_paths(prefixdir, 'lib/modules-load.d') +networkdir = join_paths(rootprefixdir, 'lib/systemd/network') +pkgincludedir = join_paths(includedir, 'systemd') +systemgeneratordir = join_paths(rootlibexecdir, 'system-generators') +usergeneratordir = join_paths(prefixdir, 'lib/systemd/user-generators') +systemenvgeneratordir = join_paths(prefixdir, 'lib/systemd/system-environment-generators') +userenvgeneratordir = join_paths(prefixdir, 'lib/systemd/user-environment-generators') +systemshutdowndir = join_paths(rootlibexecdir, 'system-shutdown') +systemsleepdir = join_paths(rootlibexecdir, 'system-sleep') +systemunitdir = join_paths(rootprefixdir, 'lib/systemd/system') +systempresetdir = join_paths(rootprefixdir, 'lib/systemd/system-preset') +udevlibexecdir = join_paths(rootprefixdir, 'lib/udev') +udevrulesdir = join_paths(udevlibexecdir, 'rules.d') +udevhwdbdir = join_paths(udevlibexecdir, 'hwdb.d') +catalogdir = join_paths(prefixdir, 'lib/systemd/catalog') +kernelinstalldir = join_paths(prefixdir, 'lib/kernel/install.d') +factorydir = join_paths(datadir, 'factory') +bootlibdir = join_paths(prefixdir, 'lib/systemd/boot/efi') +testsdir = join_paths(prefixdir, 'lib/systemd/tests') +systemdstatedir = join_paths(localstatedir, 'lib/systemd') +catalogstatedir = join_paths(systemdstatedir, 'catalog') +randomseeddir = join_paths(localstatedir, 'lib/systemd') +profiledir = join_paths(rootlibexecdir, 'portable', 'profile') +ntpservicelistdir = join_paths(rootprefixdir, 'lib/systemd/ntp-units.d') + +docdir = get_option('docdir') +if docdir == '' + docdir = join_paths(datadir, 'doc/systemd') +endif + +dbuspolicydir = get_option('dbuspolicydir') +if dbuspolicydir == '' + dbuspolicydir = join_paths(datadir, 'dbus-1/system.d') +endif + +dbussessionservicedir = get_option('dbussessionservicedir') +if dbussessionservicedir == '' + dbussessionservicedir = join_paths(datadir, 'dbus-1/services') +endif + +dbussystemservicedir = get_option('dbussystemservicedir') +if dbussystemservicedir == '' + dbussystemservicedir = join_paths(datadir, 'dbus-1/system-services') +endif + +pamlibdir = get_option('pamlibdir') +if pamlibdir == '' + pamlibdir = join_paths(rootlibdir, 'security') +endif + +pamconfdir = get_option('pamconfdir') +if pamconfdir == '' + pamconfdir = join_paths(sysconfdir, 'pam.d') +endif + +memory_accounting_default = get_option('memory-accounting-default') +status_unit_format_default = get_option('status-unit-format-default') + +conf.set_quoted('PKGSYSCONFDIR', pkgsysconfdir) +conf.set_quoted('SYSTEM_CONFIG_UNIT_PATH', join_paths(pkgsysconfdir, 'system')) +conf.set_quoted('SYSTEM_DATA_UNIT_PATH', systemunitdir) +conf.set_quoted('SYSTEM_SYSVINIT_PATH', sysvinit_path) +conf.set_quoted('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) +conf.set_quoted('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local')) + +conf.set('ANSI_OK_COLOR', 'ANSI_' + get_option('ok-color').underscorify().to_upper()) + +conf.set_quoted('USER_CONFIG_UNIT_PATH', join_paths(pkgsysconfdir, 'user')) +conf.set_quoted('USER_DATA_UNIT_PATH', userunitdir) +conf.set_quoted('CERTIFICATE_ROOT', get_option('certificate-root')) +conf.set_quoted('CATALOG_DATABASE', join_paths(catalogstatedir, 'database')) +conf.set_quoted('SYSTEMD_CGROUP_AGENT_PATH', join_paths(rootlibexecdir, 'systemd-cgroups-agent')) +conf.set_quoted('SYSTEMD_BINARY_PATH', join_paths(rootlibexecdir, 'systemd')) +conf.set_quoted('SYSTEMD_FSCK_PATH', join_paths(rootlibexecdir, 'systemd-fsck')) +conf.set_quoted('SYSTEMD_MAKEFS_PATH', join_paths(rootlibexecdir, 'systemd-makefs')) +conf.set_quoted('SYSTEMD_GROWFS_PATH', join_paths(rootlibexecdir, 'systemd-growfs')) +conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH', join_paths(rootlibexecdir, 'systemd-shutdown')) +conf.set_quoted('SYSTEMD_SLEEP_BINARY_PATH', join_paths(rootlibexecdir, 'systemd-sleep')) +conf.set_quoted('SYSTEMCTL_BINARY_PATH', join_paths(rootbindir, 'systemctl')) +conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent')) +conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH', join_paths(bindir, 'systemd-stdio-bridge')) +conf.set_quoted('ROOTPREFIX', rootprefixdir) +conf.set_quoted('RANDOM_SEED_DIR', randomseeddir) +conf.set_quoted('RANDOM_SEED', join_paths(randomseeddir, 'random-seed')) +conf.set_quoted('SYSTEMD_CRYPTSETUP_PATH', join_paths(rootlibexecdir, 'systemd-cryptsetup')) +conf.set_quoted('SYSTEM_GENERATOR_PATH', systemgeneratordir) +conf.set_quoted('USER_GENERATOR_PATH', usergeneratordir) +conf.set_quoted('SYSTEM_ENV_GENERATOR_PATH', systemenvgeneratordir) +conf.set_quoted('USER_ENV_GENERATOR_PATH', userenvgeneratordir) +conf.set_quoted('SYSTEM_SHUTDOWN_PATH', systemshutdowndir) +conf.set_quoted('SYSTEM_SLEEP_PATH', systemsleepdir) +conf.set_quoted('SYSTEMD_KBD_MODEL_MAP', join_paths(pkgdatadir, 'kbd-model-map')) +conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP', join_paths(pkgdatadir, 'language-fallback-map')) +conf.set_quoted('SYSTEMD_TEST_DATA', join_paths(testsdir, 'testdata')) +conf.set_quoted('SYSTEMD_CATALOG_DIR', catalogdir) +conf.set_quoted('UDEVLIBEXECDIR', udevlibexecdir) +conf.set_quoted('POLKIT_AGENT_BINARY_PATH', join_paths(bindir, 'pkttyagent')) +conf.set_quoted('LIBDIR', libdir) +conf.set_quoted('ROOTLIBDIR', rootlibdir) +conf.set_quoted('ROOTLIBEXECDIR', rootlibexecdir) +conf.set_quoted('BOOTLIBDIR', bootlibdir) +conf.set_quoted('SYSTEMD_PULL_PATH', join_paths(rootlibexecdir, 'systemd-pull')) +conf.set_quoted('SYSTEMD_IMPORT_PATH', join_paths(rootlibexecdir, 'systemd-import')) +conf.set_quoted('SYSTEMD_IMPORT_FS_PATH', join_paths(rootlibexecdir, 'systemd-import-fs')) +conf.set_quoted('SYSTEMD_EXPORT_PATH', join_paths(rootlibexecdir, 'systemd-export')) +conf.set_quoted('VENDOR_KEYRING_PATH', join_paths(rootlibexecdir, 'import-pubring.gpg')) +conf.set_quoted('USER_KEYRING_PATH', join_paths(pkgsysconfdir, 'import-pubring.gpg')) +conf.set_quoted('DOCUMENT_ROOT', join_paths(pkgdatadir, 'gatewayd')) +conf.set10('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default) +conf.set_quoted('MEMORY_ACCOUNTING_DEFAULT_YES_NO', memory_accounting_default ? 'yes' : 'no') +conf.set('STATUS_UNIT_FORMAT_DEFAULT', 'STATUS_UNIT_FORMAT_' + status_unit_format_default.to_upper()) + +substs.set('prefix', prefixdir) +substs.set('rootprefix', rootprefixdir) +substs.set('rootprefix_noslash', rootprefixdir_noslash) +substs.set('exec_prefix', prefixdir) +substs.set('libdir', libdir) +substs.set('rootlibdir', rootlibdir) +substs.set('includedir', includedir) +substs.set('sysconfdir', sysconfdir) +substs.set('bindir', bindir) +substs.set('rootbindir', rootbindir) +substs.set('rootlibexecdir', rootlibexecdir) +substs.set('systemunitdir', systemunitdir) +substs.set('userunitdir', userunitdir) +substs.set('systempresetdir', systempresetdir) +substs.set('userpresetdir', userpresetdir) +substs.set('udevhwdbdir', udevhwdbdir) +substs.set('udevrulesdir', udevrulesdir) +substs.set('udevlibexecdir', udevlibexecdir) +substs.set('environmentdir', environmentdir) +substs.set('catalogdir', catalogdir) +substs.set('tmpfilesdir', tmpfilesdir) +substs.set('sysusersdir', sysusersdir) +substs.set('sysctldir', sysctldir) +substs.set('binfmtdir', binfmtdir) +substs.set('modulesloaddir', modulesloaddir) +substs.set('modprobedir', modprobedir) +substs.set('systemgeneratordir', systemgeneratordir) +substs.set('usergeneratordir', usergeneratordir) +substs.set('systemenvgeneratordir', systemenvgeneratordir) +substs.set('userenvgeneratordir', userenvgeneratordir) +substs.set('systemshutdowndir', systemshutdowndir) +substs.set('systemsleepdir', systemsleepdir) +substs.set('CERTIFICATEROOT', get_option('certificate-root')) +substs.set('SYSTEMCTL', join_paths(rootbindir, 'systemctl')) +substs.set('RANDOM_SEED', join_paths(randomseeddir, 'random-seed')) +substs.set('SYSTEM_SYSVINIT_PATH', sysvinit_path) +substs.set('SYSTEM_SYSVRCND_PATH', sysvrcnd_path) +substs.set('RC_LOCAL_SCRIPT_PATH_START', get_option('rc-local')) +substs.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'yes' : 'no') +substs.set('STATUS_UNIT_FORMAT_DEFAULT', status_unit_format_default) +substs.set('HIGH_RLIMIT_NOFILE', conf.get('HIGH_RLIMIT_NOFILE')) +substs.set('BUILD_ROOT', meson.current_build_dir()) + +##################################################################### + +cc = meson.get_compiler('c') +pkgconfig = import('pkgconfig') +check_compilation_sh = find_program('tools/meson-check-compilation.sh') +meson_build_sh = find_program('tools/meson-build.sh') + +want_tests = get_option('tests') +slow_tests = want_tests != 'false' and get_option('slow-tests') +install_tests = get_option('install-tests') + +if add_languages('cpp', required : fuzzer_build) + # Used only for tests + cxx = meson.get_compiler('cpp') + cxx_cmd = ' '.join(cxx.cmd_array()) +else + cxx_cmd = '' +endif + +if want_libfuzzer + fuzzing_engine = meson.get_compiler('cpp').find_library('Fuzzer', required : false) + if fuzzing_engine.found() + add_project_arguments('-fsanitize-coverage=trace-pc-guard,trace-cmp', language : 'c') + elif cc.has_argument('-fsanitize=fuzzer-no-link') + add_project_arguments('-fsanitize=fuzzer-no-link', language : 'c') + else + error('Looks like neither libFuzzer nor -fsanitize=fuzzer-no-link is supported') + endif +elif want_ossfuzz + fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine') +elif want_fuzzbuzz + fuzzing_engine = meson.get_compiler('cpp').find_library(get_option('fuzzbuzz-engine'), dirs: get_option('fuzzbuzz-engine-dir')) +endif + +# Those generate many false positives, and we do not want to change the code to +# avoid them. +basic_disabled_warnings = [ + '-Wno-unused-parameter', + '-Wno-missing-field-initializers', + '-Wno-unused-result', + '-Wno-format-signedness', +] +if get_option('b_ndebug') == 'true' + # With asserts disabled with get a bunch of warnings about variables which + # are used only in the asserts. This is not useful at all, so let's just silence + # those warnings. + basic_disabled_warnings += [ + '-Wno-unused-variable', + '-Wno-unused-but-set-variable', + ] +endif + +possible_cc_flags = [ + '-Werror=undef', + '-Wlogical-op', + '-Wmissing-include-dirs', + '-Wold-style-definition', + '-Wpointer-arith', + '-Winit-self', + '-Wfloat-equal', + '-Wsuggest-attribute=noreturn', + '-Werror=missing-prototypes', + '-Werror=implicit-function-declaration', + '-Werror=missing-declarations', + '-Werror=return-type', + '-Werror=incompatible-pointer-types', + '-Werror=format=2', + '-Wstrict-prototypes', + '-Wredundant-decls', + '-Wmissing-noreturn', + '-Wimplicit-fallthrough=5', + '-Wshadow', + '-Wendif-labels', + '-Wstrict-aliasing=2', + '-Wwrite-strings', + '-Werror=overflow', + '-Werror=shift-count-overflow', + '-Werror=shift-overflow=2', + '-Wdate-time', + '-Wnested-externs', + + # negative arguments are correctly detected starting with meson 0.46. + '-Wno-error=#warnings', # clang + '-Wno-string-plus-int', # clang + + # work-around for gcc 7.1 turning this on on its own. + '-Wno-error=nonnull', + + # Disable -Wmaybe-uninitialized, since it's noisy on gcc 8 with + # optimizations enabled, producing essentially false positives. + '-Wno-maybe-uninitialized', + + '-ffast-math', + '-fno-common', + '-fdiagnostics-show-option', + '-fno-strict-aliasing', + '-fvisibility=hidden', + '-fstack-protector', + '-fstack-protector-strong', + '--param=ssp-buffer-size=4', +] + +# --as-needed and --no-undefined are provided by meson by default, +# run mesonconf to see what is enabled +possible_link_flags = [ + '-Wl,-z,relro', + '-Wl,-z,now', + '-fstack-protector', +] + +if cc.get_id() == 'clang' + possible_cc_flags += [ + '-Wno-typedef-redefinition', + '-Wno-gnu-variable-sized-type-not-at-end', + ] +endif + +if get_option('buildtype') != 'debug' + possible_cc_flags += [ + '-ffunction-sections', + '-fdata-sections', + ] + + possible_link_flags += '-Wl,--gc-sections' +endif + +add_project_arguments(cc.get_supported_arguments(basic_disabled_warnings), language : 'c') +add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'c') +add_project_link_arguments(cc.get_supported_link_arguments(possible_link_flags), language : 'c') + +if cc.compiles(''' + #include + #include + typedef uint64_t usec_t; + usec_t now(clockid_t clock); + int main(void) { + struct timespec now; + return 0; + } +''', args: '-Werror=shadow', name : '-Werror=shadow with local shadowing') + add_project_arguments('-Werror=shadow', language : 'c') +endif + +if cxx_cmd != '' + add_project_arguments(cxx.get_supported_arguments(basic_disabled_warnings), language : 'cpp') +endif + +cpp = ' '.join(cc.cmd_array()) + ' -E' + +has_wstringop_truncation = cc.has_argument('-Wstringop-truncation') + +##################################################################### +# compilation result tests + +conf.set('_GNU_SOURCE', true) +conf.set('__SANE_USERSPACE_TYPES__', true) +conf.set10('HAVE_WSTRINGOP_TRUNCATION', has_wstringop_truncation) + +conf.set('SIZEOF_PID_T', cc.sizeof('pid_t', prefix : '#include ')) +conf.set('SIZEOF_UID_T', cc.sizeof('uid_t', prefix : '#include ')) +conf.set('SIZEOF_GID_T', cc.sizeof('gid_t', prefix : '#include ')) +conf.set('SIZEOF_DEV_T', cc.sizeof('dev_t', prefix : '#include ')) +conf.set('SIZEOF_INO_T', cc.sizeof('ino_t', prefix : '#include ')) +conf.set('SIZEOF_TIME_T', cc.sizeof('time_t', prefix : '#include ')) +conf.set('SIZEOF_RLIM_T', cc.sizeof('rlim_t', prefix : '#include ')) + +decl_headers = ''' +#include +#include +''' + +foreach decl : ['char16_t', + 'char32_t', + 'struct statx', + ] + + # We get -1 if the size cannot be determined + have = cc.sizeof(decl, prefix : decl_headers, args : '-D_GNU_SOURCE') > 0 + + if decl == 'struct statx' + if have + want_linux_stat_h = false + else + have = cc.sizeof(decl, + prefix : decl_headers + '#include ', + args : '-D_GNU_SOURCE') > 0 + want_linux_stat_h = have + endif + endif + + conf.set10('HAVE_' + decl.underscorify().to_upper(), have) +endforeach + +conf.set10('WANT_LINUX_STAT_H', want_linux_stat_h) + +foreach ident : ['secure_getenv', '__secure_getenv'] + conf.set10('HAVE_' + ident.to_upper(), cc.has_function(ident)) +endforeach + +foreach ident : [ + ['memfd_create', '''#include '''], + ['gettid', '''#include + #include '''], + ['pivot_root', '''#include + #include '''], # no known header declares pivot_root + ['name_to_handle_at', '''#include + #include + #include '''], + ['setns', '''#include '''], + ['renameat2', '''#include + #include '''], + ['kcmp', '''#include '''], + ['keyctl', '''#include + #include '''], + ['copy_file_range', '''#include + #include '''], + ['bpf', '''#include + #include '''], + ['statx', '''#include + #include + #include '''], + ['explicit_bzero' , '''#include '''], + ['reallocarray', '''#include '''], + ['set_mempolicy', '''#include + #include '''], + ['get_mempolicy', '''#include + #include '''], +] + + have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE') + conf.set10('HAVE_' + ident[0].to_upper(), have) +endforeach + +if cc.has_function('getrandom', prefix : '''#include ''', args : '-D_GNU_SOURCE') + conf.set10('USE_SYS_RANDOM_H', true) + conf.set10('HAVE_GETRANDOM', true) +else + have = cc.has_function('getrandom', prefix : '''#include ''') + conf.set10('USE_SYS_RANDOM_H', false) + conf.set10('HAVE_GETRANDOM', have) +endif + +##################################################################### + +vcs_tagger = [project_source_root + '/tools/meson-vcs-tag.sh', + project_source_root, + get_option('version-tag'), + meson.project_version()] + +version_h = vcs_tag( + input : 'src/version/version.h.in', + output : 'version.h', + command: vcs_tagger) + +versiondep = declare_dependency(sources: version_h) + +sed = find_program('sed') +awk = find_program('awk') +m4 = find_program('m4') +stat = find_program('stat') +git = find_program('git', required : false) +env = find_program('env') +perl = find_program('perl', required : false) + +meson_make_symlink = project_source_root + '/tools/meson-make-symlink.sh' +mkdir_p = 'mkdir -p $DESTDIR/@0@' +test_efi_create_disk_sh = find_program('test/test-efi-create-disk.sh') +splash_bmp = files('test/splash.bmp') + +# if -Dxxx-path option is found, use that. Otherwise, check in $PATH, +# /usr/sbin, /sbin, and fall back to the default from middle column. +progs = [['quotaon', '/usr/sbin/quotaon' ], + ['quotacheck', '/usr/sbin/quotacheck' ], + ['kmod', '/usr/bin/kmod' ], + ['kexec', '/usr/sbin/kexec' ], + ['sulogin', '/usr/sbin/sulogin' ], + ['mount', '/usr/bin/mount', 'MOUNT_PATH'], + ['umount', '/usr/bin/umount', 'UMOUNT_PATH'], + ['loadkeys', '/usr/bin/loadkeys', 'KBD_LOADKEYS'], + ['setfont', '/usr/bin/setfont', 'KBD_SETFONT'], + ['nologin', '/usr/sbin/nologin', ], + ] +foreach prog : progs + path = get_option(prog[0] + '-path') + if path != '' + message('Using @1@ for @0@'.format(prog[0], path)) + else + exe = find_program(prog[0], + '/usr/sbin/' + prog[0], + '/sbin/' + prog[0], + required: false) + path = exe.found() ? exe.path() : prog[1] + endif + name = prog.length() > 2 ? prog[2] : prog[0].to_upper() + conf.set_quoted(name, path) + substs.set(name, path) +endforeach + +conf.set_quoted('TELINIT', get_option('telinit-path')) + +if run_command('ln', '--relative', '--help').returncode() != 0 + error('ln does not support --relative (added in coreutils 8.16)') +endif + +############################################################ + +gperf = find_program('gperf') + +gperf_test_format = ''' +#include +const char * in_word_set(const char *, @0@); +@1@ +''' +gperf_snippet_format = 'echo foo,bar | @0@ -L ANSI-C' +gperf_snippet = run_command('sh', '-c', gperf_snippet_format.format(gperf.path())) +gperf_test = gperf_test_format.format('size_t', gperf_snippet.stdout()) +if cc.compiles(gperf_test) + gperf_len_type = 'size_t' +else + gperf_test = gperf_test_format.format('unsigned', gperf_snippet.stdout()) + if cc.compiles(gperf_test) + gperf_len_type = 'unsigned' + else + error('unable to determine gperf len type') + endif +endif +message('gperf len type is @0@'.format(gperf_len_type)) +conf.set('GPERF_LEN_TYPE', gperf_len_type, + description : 'The type of gperf "len" parameter') + +############################################################ + +if not cc.has_header('sys/capability.h') + error('POSIX caps headers not found') +endif +foreach header : ['crypt.h', + 'linux/memfd.h', + 'linux/vm_sockets.h', + 'sys/auxv.h', + 'valgrind/memcheck.h', + 'valgrind/valgrind.h', + ] + + conf.set10('HAVE_' + header.underscorify().to_upper(), + cc.has_header(header)) +endforeach + +############################################################ + +conf.set_quoted('FALLBACK_HOSTNAME', get_option('fallback-hostname')) +conf.set10('ENABLE_COMPAT_GATEWAY_HOSTNAME', get_option('compat-gateway-hostname')) +gateway_hostnames = ['_gateway'] + (conf.get('ENABLE_COMPAT_GATEWAY_HOSTNAME') == 1 ? ['gateway'] : []) + +default_hierarchy = get_option('default-hierarchy') +conf.set_quoted('DEFAULT_HIERARCHY_NAME', default_hierarchy, + description : 'default cgroup hierarchy as string') +if default_hierarchy == 'legacy' + conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_NONE') +elif default_hierarchy == 'hybrid' + conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_SYSTEMD') +else + conf.set('DEFAULT_HIERARCHY', 'CGROUP_UNIFIED_ALL') +endif + +default_net_naming_scheme = get_option('default-net-naming-scheme') +conf.set_quoted('DEFAULT_NET_NAMING_SCHEME', default_net_naming_scheme) + +time_epoch = get_option('time-epoch') +if time_epoch == -1 + NEWS = files('NEWS') + time_epoch = run_command(stat, '-c', '%Y', NEWS).stdout().to_int() +endif +conf.set('TIME_EPOCH', time_epoch) + +system_uid_max = get_option('system-uid-max') +if system_uid_max == -1 + system_uid_max = run_command( + awk, + '/^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }', + '/etc/login.defs').stdout().strip() + if system_uid_max == '' + system_uid_max = 999 + else + system_uid_max = system_uid_max.to_int() + endif +endif +conf.set('SYSTEM_UID_MAX', system_uid_max) +substs.set('systemuidmax', system_uid_max) + +system_gid_max = get_option('system-gid-max') +if system_gid_max == -1 + system_gid_max = run_command( + awk, + '/^\s*SYS_GID_MAX\s+/ { gid=$2 } END { print gid }', + '/etc/login.defs').stdout().strip() + if system_gid_max == '' + system_gid_max = 999 + else + system_gid_max = system_gid_max.to_int() + endif +endif +conf.set('SYSTEM_GID_MAX', system_gid_max) +substs.set('systemgidmax', system_gid_max) + +dynamic_uid_min = get_option('dynamic-uid-min') +dynamic_uid_max = get_option('dynamic-uid-max') +conf.set('DYNAMIC_UID_MIN', dynamic_uid_min) +conf.set('DYNAMIC_UID_MAX', dynamic_uid_max) +substs.set('dynamicuidmin', dynamic_uid_min) +substs.set('dynamicuidmax', dynamic_uid_max) + +container_uid_base_min = get_option('container-uid-base-min') +container_uid_base_max = get_option('container-uid-base-max') +conf.set('CONTAINER_UID_BASE_MIN', container_uid_base_min) +conf.set('CONTAINER_UID_BASE_MAX', container_uid_base_max) +substs.set('containeruidbasemin', container_uid_base_min) +substs.set('containeruidbasemax', container_uid_base_max) + +nobody_user = get_option('nobody-user') +nobody_group = get_option('nobody-group') + +if not meson.is_cross_build() + getent_result = run_command('getent', 'passwd', '65534') + if getent_result.returncode() == 0 + name = getent_result.stdout().split(':')[0] + if name != nobody_user + warning('\n' + + 'The local user with the UID 65534 does not match the configured user name "@0@" of the nobody user (its name is @1@).\n'.format(nobody_user, name) + + 'Your build will result in an user table setup that is incompatible with the local system.') + endif + endif + id_result = run_command('id', '-u', nobody_user) + if id_result.returncode() == 0 + id = id_result.stdout().to_int() + if id != 65534 + warning('\n' + + 'The local user with the configured user name "@0@" of the nobody user does not have UID 65534 (it has @1@).\n'.format(nobody_user, id) + + 'Your build will result in an user table setup that is incompatible with the local system.') + endif + endif + + getent_result = run_command('getent', 'group', '65534') + if getent_result.returncode() == 0 + name = getent_result.stdout().split(':')[0] + if name != nobody_group + warning('\n' + + 'The local group with the GID 65534 does not match the configured group name "@0@" of the nobody group (its name is @1@).\n'.format(nobody_group, name) + + 'Your build will result in an group table setup that is incompatible with the local system.') + endif + endif + id_result = run_command('id', '-g', nobody_group) + if id_result.returncode() == 0 + id = id_result.stdout().to_int() + if id != 65534 + warning('\n' + + 'The local group with the configured group name "@0@" of the nobody group does not have UID 65534 (it has @1@).\n'.format(nobody_group, id) + + 'Your build will result in an group table setup that is incompatible with the local system.') + endif + endif +endif +if nobody_user != nobody_group and not (nobody_user == 'nobody' and nobody_group == 'nogroup') + warning('\n' + + 'The configured user name "@0@" and group name "@0@" of the nobody user/group are not equivalent.\n'.format(nobody_user, nobody_group) + + 'Please re-check that both "nobody-user" and "nobody-group" options are correctly set.') +endif + +conf.set_quoted('NOBODY_USER_NAME', nobody_user) +conf.set_quoted('NOBODY_GROUP_NAME', nobody_group) +substs.set('NOBODY_USER_NAME', nobody_user) +substs.set('NOBODY_GROUP_NAME', nobody_group) + +tty_gid = get_option('tty-gid') +conf.set('TTY_GID', tty_gid) +substs.set('TTY_GID', tty_gid) + +# Ensure provided GID argument is numeric, otherwise fallback to default assignment +users_gid = get_option('users-gid') +substs.set('USERS_GID', users_gid < 0 ? '-' : users_gid) + +conf.set10('ENABLE_ADM_GROUP', get_option('adm-group')) +conf.set10('ENABLE_WHEEL_GROUP', get_option('wheel-group')) + +dev_kvm_mode = get_option('dev-kvm-mode') +substs.set('DEV_KVM_MODE', dev_kvm_mode) +conf.set10('DEV_KVM_UACCESS', dev_kvm_mode != '0666') +group_render_mode = get_option('group-render-mode') +substs.set('GROUP_RENDER_MODE', group_render_mode) +conf.set10('GROUP_RENDER_UACCESS', group_render_mode != '0666') + +kill_user_processes = get_option('default-kill-user-processes') +conf.set10('KILL_USER_PROCESSES', kill_user_processes) +conf.set_quoted('KILL_USER_PROCESSES_YES_NO', kill_user_processes ? 'yes' : 'no') +substs.set('KILL_USER_PROCESSES', kill_user_processes ? 'yes' : 'no') + +dns_servers = get_option('dns-servers') +conf.set_quoted('DNS_SERVERS', dns_servers) +substs.set('DNS_SERVERS', dns_servers) + +ntp_servers = get_option('ntp-servers') +conf.set_quoted('NTP_SERVERS', ntp_servers) +substs.set('NTP_SERVERS', ntp_servers) + +default_locale = get_option('default-locale') +if default_locale == '' + if not meson.is_cross_build() + choose_default_locale_sh = find_program('tools/choose-default-locale.sh') + default_locale = run_command(choose_default_locale_sh).stdout().strip() + else + default_locale = 'C.UTF-8' + endif +endif +conf.set_quoted('SYSTEMD_DEFAULT_LOCALE', default_locale) + +conf.set_quoted('GETTEXT_PACKAGE', meson.project_name()) + +service_watchdog = get_option('service-watchdog') +watchdog_value = service_watchdog == '' ? '' : 'WatchdogSec=' + service_watchdog +substs.set('SERVICE_WATCHDOG', watchdog_value) + +substs.set('SUSHELL', get_option('debug-shell')) +substs.set('DEBUGTTY', get_option('debug-tty')) +conf.set_quoted('DEBUGTTY', get_option('debug-tty')) + +enable_debug_hashmap = false +enable_debug_mmap_cache = false +enable_debug_siphash = false +foreach name : get_option('debug-extra') + if name == 'hashmap' + enable_debug_hashmap = true + elif name == 'mmap-cache' + enable_debug_mmap_cache = true + elif name == 'siphash' + enable_debug_siphash = true + else + message('unknown debug option "@0@", ignoring'.format(name)) + endif +endforeach +conf.set10('ENABLE_DEBUG_HASHMAP', enable_debug_hashmap) +conf.set10('ENABLE_DEBUG_MMAP_CACHE', enable_debug_mmap_cache) +conf.set10('ENABLE_DEBUG_SIPHASH', enable_debug_siphash) + +conf.set10('VALGRIND', get_option('valgrind')) +conf.set10('LOG_TRACE', get_option('log-trace')) + +default_user_path = get_option('user-path') +if default_user_path != '' + conf.set_quoted('DEFAULT_USER_PATH', default_user_path) + default_user_path_display = default_user_path +else + # meson 0.49 fails when ?: is used in .format() + default_user_path_display = '(same as system services)' +endif + + +##################################################################### + +threads = dependency('threads') +librt = cc.find_library('rt') +libm = cc.find_library('m') +libdl = cc.find_library('dl') +libcrypt = cc.find_library('crypt') + +libcap = dependency('libcap', required : false) +if not libcap.found() + # Compat with Ubuntu 14.04 which ships libcap w/o .pc file + libcap = cc.find_library('cap') +endif + +libmount = dependency('mount', + version : fuzzer_build ? '>= 0' : '>= 2.30') + +want_seccomp = get_option('seccomp') +if want_seccomp != 'false' and not skip_deps + libseccomp = dependency('libseccomp', + version : '>= 2.3.1', + required : want_seccomp == 'true') + have = libseccomp.found() +else + have = false + libseccomp = [] +endif +conf.set10('HAVE_SECCOMP', have) + +want_selinux = get_option('selinux') +if want_selinux != 'false' and not skip_deps + libselinux = dependency('libselinux', + version : '>= 2.1.9', + required : want_selinux == 'true') + have = libselinux.found() +else + have = false + libselinux = [] +endif +conf.set10('HAVE_SELINUX', have) + +want_apparmor = get_option('apparmor') +if want_apparmor != 'false' and not skip_deps + libapparmor = dependency('libapparmor', + required : want_apparmor == 'true') + have = libapparmor.found() +else + have = false + libapparmor = [] +endif +conf.set10('HAVE_APPARMOR', have) + +smack_run_label = get_option('smack-run-label') +if smack_run_label != '' + conf.set_quoted('SMACK_RUN_LABEL', smack_run_label) +endif + +want_polkit = get_option('polkit') +install_polkit = false +install_polkit_pkla = false +if want_polkit != 'false' and not skip_deps + install_polkit = true + + libpolkit = dependency('polkit-gobject-1', + required : false) + if libpolkit.found() and libpolkit.version().version_compare('< 0.106') + message('Old polkit detected, will install pkla files') + install_polkit_pkla = true + endif +endif +conf.set10('ENABLE_POLKIT', install_polkit) + +want_acl = get_option('acl') +if want_acl != 'false' and not skip_deps + libacl = cc.find_library('acl', required : want_acl == 'true') + have = libacl.found() +else + have = false + libacl = [] +endif +conf.set10('HAVE_ACL', have) + +want_audit = get_option('audit') +if want_audit != 'false' and not skip_deps + libaudit = dependency('audit', required : want_audit == 'true') + have = libaudit.found() +else + have = false + libaudit = [] +endif +conf.set10('HAVE_AUDIT', have) + +want_blkid = get_option('blkid') +if want_blkid != 'false' and not skip_deps + libblkid = dependency('blkid', required : want_blkid == 'true') + have = libblkid.found() +else + have = false + libblkid = [] +endif +conf.set10('HAVE_BLKID', have) + +want_kmod = get_option('kmod') +if want_kmod != 'false' and not skip_deps + libkmod = dependency('libkmod', + version : '>= 15', + required : want_kmod == 'true') + have = libkmod.found() +else + have = false + libkmod = [] +endif +conf.set10('HAVE_KMOD', have) + +want_pam = get_option('pam') +if want_pam != 'false' and not skip_deps + libpam = cc.find_library('pam', required : want_pam == 'true') + libpam_misc = cc.find_library('pam_misc', required : want_pam == 'true') + have = libpam.found() and libpam_misc.found() +else + have = false + libpam = [] + libpam_misc = [] +endif +conf.set10('HAVE_PAM', have) + +want_microhttpd = get_option('microhttpd') +if want_microhttpd != 'false' and not skip_deps + libmicrohttpd = dependency('libmicrohttpd', + version : '>= 0.9.33', + required : want_microhttpd == 'true') + have = libmicrohttpd.found() +else + have = false + libmicrohttpd = [] +endif +conf.set10('HAVE_MICROHTTPD', have) + +want_libcryptsetup = get_option('libcryptsetup') +if want_libcryptsetup != 'false' and not skip_deps + libcryptsetup = dependency('libcryptsetup', + version : '>= 2.0.1', + required : want_libcryptsetup == 'true') + have = libcryptsetup.found() +else + have = false + libcryptsetup = [] +endif +conf.set10('HAVE_LIBCRYPTSETUP', have) + +want_libcurl = get_option('libcurl') +if want_libcurl != 'false' and not skip_deps + libcurl = dependency('libcurl', + version : '>= 7.32.0', + required : want_libcurl == 'true') + have = libcurl.found() +else + have = false + libcurl = [] +endif +conf.set10('HAVE_LIBCURL', have) + +want_libidn = get_option('libidn') +want_libidn2 = get_option('libidn2') +if want_libidn == 'true' and want_libidn2 == 'true' + error('libidn and libidn2 cannot be requested simultaneously') +endif + +if want_libidn2 != 'false' and want_libidn != 'true' and not skip_deps + libidn = dependency('libidn2', + required : want_libidn2 == 'true') + have = libidn.found() +else + have = false + libidn = [] +endif +conf.set10('HAVE_LIBIDN2', have) +if not have and want_libidn != 'false' and not skip_deps + # libidn is used for both libidn and libidn2 objects + libidn = dependency('libidn', + required : want_libidn == 'true') + have = libidn.found() +else + have = false +endif +conf.set10('HAVE_LIBIDN', have) + +want_libiptc = get_option('libiptc') +if want_libiptc != 'false' and not skip_deps + libiptc = dependency('libiptc', + required : want_libiptc == 'true') + have = libiptc.found() +else + have = false + libiptc = [] +endif +conf.set10('HAVE_LIBIPTC', have) + +want_qrencode = get_option('qrencode') +if want_qrencode != 'false' and not skip_deps + libqrencode = dependency('libqrencode', + required : want_qrencode == 'true') + have = libqrencode.found() +else + have = false + libqrencode = [] +endif +conf.set10('HAVE_QRENCODE', have) + +want_gcrypt = get_option('gcrypt') +if want_gcrypt != 'false' and not skip_deps + libgcrypt = cc.find_library('gcrypt', required : want_gcrypt == 'true') + libgpg_error = cc.find_library('gpg-error', required : want_gcrypt == 'true') + have = libgcrypt.found() and libgpg_error.found() +else + have = false +endif +if not have + # link to neither of the libs if one is not found + libgcrypt = [] + libgpg_error = [] +endif +conf.set10('HAVE_GCRYPT', have) + +want_gnutls = get_option('gnutls') +if want_gnutls != 'false' and not skip_deps + libgnutls = dependency('gnutls', + version : '>= 3.1.4', + required : want_gnutls == 'true') + have = libgnutls.found() +else + have = false + libgnutls = [] +endif +conf.set10('HAVE_GNUTLS', have) + +want_openssl = get_option('openssl') +if want_openssl != 'false' and not skip_deps + libopenssl = dependency('openssl', + version : '>= 1.1.0', + required : want_openssl == 'true') + have = libopenssl.found() +else + have = false + libopenssl = [] +endif +conf.set10('HAVE_OPENSSL', have) + +want_elfutils = get_option('elfutils') +if want_elfutils != 'false' and not skip_deps + libdw = dependency('libdw', + required : want_elfutils == 'true') + have = libdw.found() +else + have = false + libdw = [] +endif +conf.set10('HAVE_ELFUTILS', have) + +want_zlib = get_option('zlib') +if want_zlib != 'false' and not skip_deps + libz = dependency('zlib', + required : want_zlib == 'true') + have = libz.found() +else + have = false + libz = [] +endif +conf.set10('HAVE_ZLIB', have) + +want_bzip2 = get_option('bzip2') +if want_bzip2 != 'false' and not skip_deps + libbzip2 = cc.find_library('bz2', + required : want_bzip2 == 'true') + have = libbzip2.found() +else + have = false + libbzip2 = [] +endif +conf.set10('HAVE_BZIP2', have) + +want_xz = get_option('xz') +if want_xz != 'false' and not skip_deps + libxz = dependency('liblzma', + required : want_xz == 'true') + have = libxz.found() +else + have = false + libxz = [] +endif +conf.set10('HAVE_XZ', have) + +want_lz4 = get_option('lz4') +if want_lz4 != 'false' and not skip_deps + liblz4 = dependency('liblz4', + version : '>= 1.3.0', + required : want_lz4 == 'true') + have = liblz4.found() +else + have = false + liblz4 = [] +endif +conf.set10('HAVE_LZ4', have) + +want_xkbcommon = get_option('xkbcommon') +if want_xkbcommon != 'false' and not skip_deps + libxkbcommon = dependency('xkbcommon', + version : '>= 0.3.0', + required : want_xkbcommon == 'true') + have = libxkbcommon.found() +else + have = false + libxkbcommon = [] +endif +conf.set10('HAVE_XKBCOMMON', have) + +want_pcre2 = get_option('pcre2') +if want_pcre2 != 'false' + libpcre2 = dependency('libpcre2-8', + required : want_pcre2 == 'true') + have = libpcre2.found() +else + have = false + libpcre2 = [] +endif +conf.set10('HAVE_PCRE2', have) + +want_glib = get_option('glib') +if want_glib != 'false' and not skip_deps + libglib = dependency('glib-2.0', + version : '>= 2.22.0', + required : want_glib == 'true') + libgobject = dependency('gobject-2.0', + version : '>= 2.22.0', + required : want_glib == 'true') + libgio = dependency('gio-2.0', + required : want_glib == 'true') + have = libglib.found() and libgobject.found() and libgio.found() +else + have = false + libglib = [] + libgobject = [] + libgio = [] +endif +conf.set10('HAVE_GLIB', have) + +want_dbus = get_option('dbus') +if want_dbus != 'false' and not skip_deps + libdbus = dependency('dbus-1', + version : '>= 1.3.2', + required : want_dbus == 'true') + have = libdbus.found() +else + have = false + libdbus = [] +endif +conf.set10('HAVE_DBUS', have) + +default_dnssec = get_option('default-dnssec') +if skip_deps + default_dnssec = 'no' +endif +if default_dnssec != 'no' and conf.get('HAVE_GCRYPT') == 0 + message('default-dnssec cannot be set to yes or allow-downgrade when gcrypt is disabled. Setting default-dnssec to no.') + default_dnssec = 'no' +endif +conf.set('DEFAULT_DNSSEC_MODE', + 'DNSSEC_' + default_dnssec.underscorify().to_upper()) +substs.set('DEFAULT_DNSSEC_MODE', default_dnssec) + +dns_over_tls = get_option('dns-over-tls') +if dns_over_tls != 'false' + if dns_over_tls == 'openssl' + have_gnutls = false + else + have_gnutls = (conf.get('HAVE_GNUTLS') == 1 and libgnutls.version().version_compare('>= 3.6.0')) + if dns_over_tls == 'gnutls' and not have_gnutls + error('DNS-over-TLS support was requested with gnutls, but dependencies are not available') + endif + endif + if dns_over_tls == 'gnutls' or have_gnutls + have_openssl = false + else + have_openssl = conf.get('HAVE_OPENSSL') == 1 + if dns_over_tls != 'auto' and not have_openssl + str = dns_over_tls == 'openssl' ? ' with openssl' : '' + error('DNS-over-TLS support was requested@0@, but dependencies are not available'.format(str)) + endif + endif + have = have_gnutls or have_openssl +else + have = false + have_gnutls = false + have_openssl = false +endif +conf.set10('ENABLE_DNS_OVER_TLS', have) +conf.set10('DNS_OVER_TLS_USE_GNUTLS', have_gnutls) +conf.set10('DNS_OVER_TLS_USE_OPENSSL', have_openssl) + +default_dns_over_tls = get_option('default-dns-over-tls') +if skip_deps + default_dns_over_tls = 'no' +endif +if default_dns_over_tls != 'no' and conf.get('ENABLE_DNS_OVER_TLS') == 0 + message('default-dns-over-tls cannot be enabled or set to opportunistic when DNS-over-TLS support is disabled. Setting default-dns-over-tls to no.') + default_dns_over_tls = 'no' +endif +conf.set('DEFAULT_DNS_OVER_TLS_MODE', + 'DNS_OVER_TLS_' + default_dns_over_tls.underscorify().to_upper()) +substs.set('DEFAULT_DNS_OVER_TLS_MODE', default_dns_over_tls) + +want_importd = get_option('importd') +if want_importd != 'false' + have = (conf.get('HAVE_LIBCURL') == 1 and + conf.get('HAVE_ZLIB') == 1 and + conf.get('HAVE_XZ') == 1 and + conf.get('HAVE_GCRYPT') == 1) + if want_importd == 'true' and not have + error('importd support was requested, but dependencies are not available') + endif +else + have = false +endif +conf.set10('ENABLE_IMPORTD', have) + +want_remote = get_option('remote') +if want_remote != 'false' + have_deps = [conf.get('HAVE_MICROHTTPD') == 1, + conf.get('HAVE_LIBCURL') == 1] + # sd-j-remote requires µhttpd, and sd-j-upload requires libcurl, so + # it's possible to build one without the other. Complain only if + # support was explicitly requested. The auxiliary files like sysusers + # config should be installed when any of the programs are built. + if want_remote == 'true' and not (have_deps[0] and have_deps[1]) + error('remote support was requested, but dependencies are not available') + endif + have = have_deps[0] or have_deps[1] +else + have = false +endif +conf.set10('ENABLE_REMOTE', have) + +foreach term : ['utmp', + 'hibernate', + 'environment-d', + 'binfmt', + 'coredump', + 'pstore', + 'resolve', + 'logind', + 'hostnamed', + 'localed', + 'machined', + 'portabled', + 'networkd', + 'timedated', + 'timesyncd', + 'firstboot', + 'randomseed', + 'backlight', + 'vconsole', + 'quotacheck', + 'sysusers', + 'tmpfiles', + 'hwdb', + 'rfkill', + 'ldconfig', + 'efi', + 'tpm', + 'ima', + 'smack', + 'gshadow', + 'idn', + 'nss-myhostname', + 'nss-systemd'] + have = get_option(term) + name = 'ENABLE_' + term.underscorify().to_upper() + conf.set10(name, have) +endforeach + +foreach tuple : [['nss-mymachines', 'machined'], + ['nss-resolve', 'resolve']] + want = get_option(tuple[0]) + if want != 'false' + have = get_option(tuple[1]) + if want == 'true' and not have + error('@0@ is requested but @1@ is disabled'.format(tuple[0], tuple[1])) + endif + else + have = false + endif + name = 'ENABLE_' + tuple[0].underscorify().to_upper() + conf.set10(name, have) +endforeach + +enable_nss = false +foreach term : ['ENABLE_NSS_MYHOSTNAME', + 'ENABLE_NSS_MYMACHINES', + 'ENABLE_NSS_RESOLVE', + 'ENABLE_NSS_SYSTEMD'] + if conf.get(term) == 1 + enable_nss = true + endif +endforeach +conf.set10('ENABLE_NSS', enable_nss) + +conf.set10('ENABLE_TIMEDATECTL', get_option('timedated') or get_option('timesyncd')) + +tests = [] +fuzzers = [] + +conf.set10('SYSTEMD_SLOW_TESTS_DEFAULT', slow_tests) + +##################################################################### + +if get_option('efi') + efi_arch = host_machine.cpu_family() + + if efi_arch == 'x86' + EFI_MACHINE_TYPE_NAME = 'ia32' + gnu_efi_arch = 'ia32' + elif efi_arch == 'x86_64' + EFI_MACHINE_TYPE_NAME = 'x64' + gnu_efi_arch = 'x86_64' + elif efi_arch == 'arm' + EFI_MACHINE_TYPE_NAME = 'arm' + gnu_efi_arch = 'arm' + elif efi_arch == 'aarch64' + EFI_MACHINE_TYPE_NAME = 'aa64' + gnu_efi_arch = 'aarch64' + else + EFI_MACHINE_TYPE_NAME = '' + gnu_efi_arch = '' + endif + + have = true + conf.set_quoted('EFI_MACHINE_TYPE_NAME', EFI_MACHINE_TYPE_NAME) + + conf.set('SD_TPM_PCR', get_option('tpm-pcrindex')) +else + have = false +endif +conf.set10('ENABLE_EFI', have) + +##################################################################### + +config_h = configure_file( + output : 'config.h', + configuration : conf) + +meson_apply_m4 = find_program('tools/meson-apply-m4.sh') + +includes = include_directories('src/basic', + 'src/boot', + 'src/shared', + 'src/systemd', + 'src/journal', + 'src/journal-remote', + 'src/nspawn', + 'src/resolve', + 'src/timesync', + 'src/time-wait-sync', + 'src/login', + 'src/udev', + 'src/libudev', + 'src/core', + 'src/shutdown', + 'src/libsystemd/sd-bus', + 'src/libsystemd/sd-device', + 'src/libsystemd/sd-event', + 'src/libsystemd/sd-hwdb', + 'src/libsystemd/sd-id128', + 'src/libsystemd/sd-netlink', + 'src/libsystemd/sd-network', + 'src/libsystemd/sd-resolve', + 'src/libsystemd-network', + '.') + +add_project_arguments('-include', 'config.h', language : 'c') + +generate_gperfs = find_program('tools/generate-gperfs.py') + +subdir('po') +subdir('catalog') +subdir('src/systemd') +subdir('src/basic') +subdir('src/libsystemd') +subdir('src/libsystemd-network') +subdir('src/journal') +subdir('src/login') + +libjournal_core = static_library( + 'journal-core', + libjournal_core_sources, + journald_gperf_c, + include_directories : includes, + install : false) + +libsystemd_sym_path = '@0@/@1@'.format(project_source_root, libsystemd_sym) +libsystemd = shared_library( + 'systemd', + disable_mempool_c, + version : libsystemd_version, + include_directories : includes, + link_args : ['-shared', + '-Wl,--version-script=' + libsystemd_sym_path], + link_with : [libbasic, + libbasic_gcrypt], + link_whole : [libsystemd_static, + libjournal_client], + dependencies : [threads, + librt, + libxz, + liblz4], + link_depends : libsystemd_sym, + install : true, + install_dir : rootlibdir) + +static_libsystemd = get_option('static-libsystemd') +static_libsystemd_pic = static_libsystemd == 'true' or static_libsystemd == 'pic' + +install_libsystemd_static = static_library( + 'systemd', + libsystemd_sources, + journal_client_sources, + basic_sources, + basic_gcrypt_sources, + disable_mempool_c, + include_directories : includes, + build_by_default : static_libsystemd != 'false', + install : static_libsystemd != 'false', + install_dir : rootlibdir, + pic : static_libsystemd == 'true' or static_libsystemd == 'pic', + dependencies : [threads, + librt, + libxz, + liblz4, + libcap, + libblkid, + libmount, + libselinux, + libgcrypt], + c_args : libsystemd_c_args + (static_libsystemd_pic ? [] : ['-fno-PIC'])) + +#Generate autosuspend rules +make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py') + +############################################################ + +# binaries that have --help and are intended for use by humans, +# usually, but not always, installed in /bin. +public_programs = [] + +subdir('src/libudev') +subdir('src/shared') +subdir('src/core') +subdir('src/shutdown') +subdir('src/udev') +subdir('src/network') + +subdir('src/analyze') +subdir('src/journal-remote') +subdir('src/coredump') +subdir('src/pstore') +subdir('src/hostname') +subdir('src/import') +subdir('src/kernel-install') +subdir('src/locale') +subdir('src/machine') +subdir('src/portable') +subdir('src/nspawn') +subdir('src/resolve') +subdir('src/timedate') +subdir('src/timesync') +subdir('src/vconsole') +subdir('src/boot/efi') + +subdir('src/test') +subdir('src/fuzz') +subdir('rules.d') +subdir('test') + +############################################################ + +# only static linking apart from libdl, to make sure that the +# module is linked to all libraries that it uses. +test_dlopen = executable( + 'test-dlopen', + test_dlopen_c, + disable_mempool_c, + include_directories : includes, + link_with : [libbasic], + dependencies : [libdl], + build_by_default : want_tests != 'false') + +foreach tuple : [['myhostname', 'ENABLE_NSS_MYHOSTNAME'], + ['systemd', 'ENABLE_NSS_SYSTEMD'], + ['mymachines', 'ENABLE_NSS_MYMACHINES'], + ['resolve', 'ENABLE_NSS_RESOLVE']] + + condition = tuple[1] == '' or conf.get(tuple[1]) == 1 + if condition + module = tuple[0] + + sym = 'src/nss-@0@/nss-@0@.sym'.format(module) + version_script_arg = join_paths(project_source_root, sym) + + nss = shared_library( + 'nss_' + module, + 'src/nss-@0@/nss-@0@.c'.format(module), + disable_mempool_c, + version : '2', + include_directories : includes, + # Note that we link NSS modules with '-z nodelete' so that mempools never get orphaned + link_args : ['-Wl,-z,nodelete', + '-shared', + '-Wl,--version-script=' + version_script_arg], + link_with : [libsystemd_static, + libshared_static, + libbasic], + dependencies : [threads, + librt], + link_depends : sym, + install : true, + install_dir : rootlibdir) + + # We cannot use shared_module because it does not support version suffix. + # Unfortunately shared_library insists on creating the symlink… + meson.add_install_script('sh', '-c', + 'rm $DESTDIR@0@/libnss_@1@.so' + .format(rootlibdir, module)) + + if want_tests != 'false' + test('dlopen-nss_' + module, + test_dlopen, + # path to dlopen must include a slash + args : nss.full_path()) + endif + endif +endforeach + +############################################################ + +executable('systemd', + systemd_sources, + include_directories : includes, + link_with : [libcore, + libshared], + dependencies : [versiondep, + threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +meson.add_install_script(meson_make_symlink, + join_paths(rootlibexecdir, 'systemd'), + join_paths(rootsbindir, 'init')) + +exe = executable('systemd-analyze', + systemd_analyze_sources, + include_directories : includes, + link_with : [libcore, + libshared], + dependencies : [versiondep, + threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +executable('systemd-journald', + systemd_journald_sources, + include_directories : includes, + link_with : [libjournal_core, + libshared], + dependencies : [threads, + libxz, + liblz4, + libselinux], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +exe = executable('systemd-cat', + systemd_cat_sources, + include_directories : includes, + link_with : [libjournal_core, + libshared], + dependencies : [threads], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +exe = executable('journalctl', + journalctl_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [threads, + libqrencode, + libxz, + liblz4, + libpcre2], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) +public_programs += exe + +executable('systemd-getty-generator', + 'src/getty-generator/getty-generator.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) + +executable('systemd-debug-generator', + 'src/debug-generator/debug-generator.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) + +executable('systemd-run-generator', + 'src/run-generator/run-generator.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) + +executable('systemd-fstab-generator', + 'src/fstab-generator/fstab-generator.c', + include_directories : includes, + link_with : [libcore_shared, + libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) + +if conf.get('ENABLE_ENVIRONMENT_D') == 1 + executable('30-systemd-environment-d-generator', + 'src/environment-d-generator/environment-d-generator.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : userenvgeneratordir) + + meson.add_install_script(meson_make_symlink, + join_paths(sysconfdir, 'environment'), + join_paths(environmentdir, '99-environment.conf')) +endif + +if conf.get('ENABLE_HIBERNATE') == 1 + executable('systemd-hibernate-resume-generator', + 'src/hibernate-resume/hibernate-resume-generator.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) + + executable('systemd-hibernate-resume', + 'src/hibernate-resume/hibernate-resume.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +if conf.get('HAVE_BLKID') == 1 + executable('systemd-gpt-auto-generator', + 'src/gpt-auto-generator/gpt-auto-generator.c', + 'src/shared/blkid-util.h', + include_directories : includes, + link_with : [libshared], + dependencies : libblkid, + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) + + exe = executable('systemd-dissect', + 'src/dissect/dissect.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + public_programs += exe +endif + +if conf.get('ENABLE_RESOLVE') == 1 + executable('systemd-resolved', + systemd_resolved_sources, + include_directories : includes, + link_with : [libshared, + libbasic_gcrypt, + libsystemd_resolve_core], + dependencies : systemd_resolved_dependencies, + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + exe = executable('resolvectl', + resolvectl_sources, + include_directories : includes, + link_with : [libshared, + libbasic_gcrypt, + libsystemd_resolve_core], + dependencies : [threads, + libgpg_error, + libm, + libidn], + install_rpath : rootlibexecdir, + install : true) + public_programs += exe + + meson.add_install_script(meson_make_symlink, + join_paths(bindir, 'resolvectl'), + join_paths(rootsbindir, 'resolvconf')) + + meson.add_install_script(meson_make_symlink, + join_paths(bindir, 'resolvectl'), + join_paths(bindir, 'systemd-resolve')) +endif + +if conf.get('ENABLE_LOGIND') == 1 + executable('systemd-logind', + systemd_logind_sources, + include_directories : includes, + link_with : [liblogind_core, + libshared], + dependencies : [threads, + libacl], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + exe = executable('loginctl', + loginctl_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [threads, + liblz4, + libxz], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) + public_programs += exe + + exe = executable('systemd-inhibit', + 'src/login/inhibit.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) + public_programs += exe + + if conf.get('HAVE_PAM') == 1 + version_script_arg = join_paths(project_source_root, pam_systemd_sym) + pam_systemd = shared_library( + 'pam_systemd', + pam_systemd_c, + name_prefix : '', + include_directories : includes, + link_args : ['-shared', + '-Wl,--version-script=' + version_script_arg], + link_with : [libsystemd_static, + libshared_static], + dependencies : [threads, + libpam, + libpam_misc], + link_depends : pam_systemd_sym, + install : true, + install_dir : pamlibdir) + + if want_tests != 'false' + test('dlopen-pam_systemd', + test_dlopen, + # path to dlopen must include a slash + args : pam_systemd.full_path()) + endif + endif + + executable('systemd-user-runtime-dir', + user_runtime_dir_sources, + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +if conf.get('HAVE_PAM') == 1 + executable('systemd-user-sessions', + 'src/user-sessions/user-sessions.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +if conf.get('ENABLE_EFI') == 1 and conf.get('HAVE_BLKID') == 1 + exe = executable('bootctl', + 'src/boot/bootctl.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libblkid], + install_rpath : rootlibexecdir, + install : true) + public_programs += exe + + executable('systemd-bless-boot', + 'src/boot/bless-boot.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libblkid], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + executable('systemd-bless-boot-generator', + 'src/boot/bless-boot-generator.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) +endif + +executable('systemd-boot-check-no-failures', + 'src/boot/boot-check-no-failures.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libblkid], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +exe = executable('systemd-socket-activate', 'src/activate/activate.c', + include_directories : includes, + link_with : [libshared], + dependencies : [threads], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + + +if get_option('link-systemctl-shared') + systemctl_link_with = [libshared] +else + systemctl_link_with = [libsystemd_static, + libshared_static, + libjournal_client, + libbasic_gcrypt] +endif + +exe = executable('systemctl', + 'src/systemctl/systemctl.c', + 'src/systemctl/sysv-compat.h', + 'src/systemctl/sysv-compat.c', + include_directories : includes, + link_with : systemctl_link_with, + dependencies : [threads, + libcap, + libselinux, + libxz, + liblz4], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) +public_programs += exe + +if conf.get('ENABLE_PORTABLED') == 1 + executable('systemd-portabled', + systemd_portabled_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [threads], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + exe = executable('portablectl', 'src/portable/portablectl.c', + include_directories : includes, + link_with : [libshared], + dependencies : [threads], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) + public_programs += exe +endif + +foreach alias : ['halt', 'poweroff', 'reboot', 'runlevel', 'shutdown', 'telinit'] + meson.add_install_script(meson_make_symlink, + join_paths(rootbindir, 'systemctl'), + join_paths(rootsbindir, alias)) +endforeach + +if conf.get('ENABLE_BACKLIGHT') == 1 + executable('systemd-backlight', + 'src/backlight/backlight.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +if conf.get('ENABLE_RFKILL') == 1 + executable('systemd-rfkill', + 'src/rfkill/rfkill.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +executable('systemd-system-update-generator', + 'src/system-update-generator/system-update-generator.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) + +if conf.get('HAVE_LIBCRYPTSETUP') == 1 + executable('systemd-cryptsetup', + 'src/cryptsetup/cryptsetup.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libcryptsetup], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + executable('systemd-cryptsetup-generator', + 'src/cryptsetup/cryptsetup-generator.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libcryptsetup], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) + + executable('systemd-veritysetup', + 'src/veritysetup/veritysetup.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libcryptsetup], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + executable('systemd-veritysetup-generator', + 'src/veritysetup/veritysetup-generator.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libcryptsetup], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) +endif + +if conf.get('HAVE_SYSV_COMPAT') == 1 + executable('systemd-sysv-generator', + 'src/sysv-generator/sysv-generator.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) + + executable('systemd-rc-local-generator', + 'src/rc-local-generator/rc-local-generator.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : systemgeneratordir) +endif + +if conf.get('ENABLE_HOSTNAMED') == 1 + executable('systemd-hostnamed', + 'src/hostname/hostnamed.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + exe = executable('hostnamectl', + 'src/hostname/hostnamectl.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true) + public_programs += exe +endif + +if conf.get('ENABLE_LOCALED') == 1 + if conf.get('HAVE_XKBCOMMON') == 1 + # logind will load libxkbcommon.so dynamically on its own + deps = [libdl] + else + deps = [] + endif + + executable('systemd-localed', + systemd_localed_sources, + include_directories : includes, + link_with : [libshared], + dependencies : deps, + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + exe = executable('localectl', + localectl_sources, + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true) + public_programs += exe +endif + +if conf.get('ENABLE_TIMEDATED') == 1 + executable('systemd-timedated', + 'src/timedate/timedated.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +if conf.get('ENABLE_TIMEDATECTL') == 1 + exe = executable('timedatectl', + 'src/timedate/timedatectl.c', + include_directories : includes, + install_rpath : rootlibexecdir, + link_with : [libshared], + dependencies : [libm], + install : true) + public_programs += exe +endif + +if conf.get('ENABLE_TIMESYNCD') == 1 + executable('systemd-timesyncd', + systemd_timesyncd_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [threads, + libm], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + executable('systemd-time-wait-sync', + 'src/time-wait-sync/time-wait-sync.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +if conf.get('ENABLE_MACHINED') == 1 + executable('systemd-machined', + systemd_machined_sources, + include_directories : includes, + link_with : [libmachine_core, + libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + exe = executable('machinectl', + 'src/machine/machinectl.c', + include_directories : includes, + link_with : [libshared], + dependencies : [threads, + libxz, + liblz4], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) + public_programs += exe +endif + +if conf.get('ENABLE_IMPORTD') == 1 + executable('systemd-importd', + systemd_importd_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [threads], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + systemd_pull = executable('systemd-pull', + systemd_pull_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [versiondep, + libcurl, + libz, + libbzip2, + libxz, + libgcrypt], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + systemd_import = executable('systemd-import', + systemd_import_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [libcurl, + libz, + libbzip2, + libxz], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + systemd_import_fs = executable('systemd-import-fs', + systemd_import_fs_sources, + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + systemd_export = executable('systemd-export', + systemd_export_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [libcurl, + libz, + libbzip2, + libxz], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + public_programs += [systemd_pull, systemd_import, systemd_import_fs, systemd_export] +endif + +if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_LIBCURL') == 1 + exe = executable('systemd-journal-upload', + systemd_journal_upload_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [versiondep, + threads, + libcurl, + libgnutls, + libxz, + liblz4], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + public_programs += exe +endif + +if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1 + s_j_remote = executable('systemd-journal-remote', + systemd_journal_remote_sources, + include_directories : includes, + link_with : [libshared, + libsystemd_journal_remote], + dependencies : [threads, + libmicrohttpd, + libgnutls, + libxz, + liblz4], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + s_j_gatewayd = executable('systemd-journal-gatewayd', + systemd_journal_gatewayd_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [threads, + libmicrohttpd, + libgnutls, + libxz, + liblz4], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + public_programs += [s_j_remote, s_j_gatewayd] +endif + +if conf.get('ENABLE_COREDUMP') == 1 + executable('systemd-coredump', + systemd_coredump_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [threads, + libacl, + libdw, + libxz, + liblz4], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + exe = executable('coredumpctl', + coredumpctl_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [threads, + libxz, + liblz4], + install_rpath : rootlibexecdir, + install : true) + public_programs += exe +endif + +if conf.get('ENABLE_PSTORE') == 1 + executable('systemd-pstore', + systemd_pstore_sources, + include_directories : includes, + link_with : [libshared], + dependencies : [threads, + libacl, + libdw, + libxz, + liblz4], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +if conf.get('ENABLE_BINFMT') == 1 + exe = executable('systemd-binfmt', + 'src/binfmt/binfmt.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + public_programs += exe + + meson.add_install_script('sh', '-c', + mkdir_p.format(binfmtdir)) + meson.add_install_script('sh', '-c', + mkdir_p.format(join_paths(sysconfdir, 'binfmt.d'))) +endif + +if conf.get('ENABLE_VCONSOLE') == 1 + executable('systemd-vconsole-setup', + 'src/vconsole/vconsole-setup.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +if conf.get('ENABLE_RANDOMSEED') == 1 + executable('systemd-random-seed', + 'src/random-seed/random-seed.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +if conf.get('ENABLE_FIRSTBOOT') == 1 + executable('systemd-firstboot', + 'src/firstboot/firstboot.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libcrypt], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) +endif + +executable('systemd-remount-fs', + 'src/remount-fs/remount-fs.c', + include_directories : includes, + link_with : [libcore_shared, + libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +executable('systemd-machine-id-setup', + 'src/machine-id-setup/machine-id-setup-main.c', + include_directories : includes, + link_with : [libcore_shared, + libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) + +executable('systemd-fsck', + 'src/fsck/fsck.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +executable('systemd-growfs', + 'src/partition/growfs.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libcryptsetup], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +executable('systemd-makefs', + 'src/partition/makefs.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +executable('systemd-sleep', + 'src/sleep/sleep.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +install_data('src/sleep/sleep.conf', + install_dir : pkgsysconfdir) + +exe = executable('systemd-sysctl', + 'src/sysctl/sysctl.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +public_programs += exe + +executable('systemd-ac-power', + 'src/ac-power/ac-power.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +exe = executable('systemd-detect-virt', + 'src/detect-virt/detect-virt.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +exe = executable('systemd-delta', + 'src/delta/delta.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +exe = executable('systemd-escape', + 'src/escape/escape.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) +public_programs += exe + +exe = executable('systemd-notify', + 'src/notify/notify.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) +public_programs += exe + +executable('systemd-volatile-root', + 'src/volatile-root/volatile-root.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +executable('systemd-cgroups-agent', + 'src/cgroups-agent/cgroups-agent.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +exe = executable('systemd-id128', + 'src/id128/id128.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +exe = executable('systemd-path', + 'src/path/path.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +exe = executable('systemd-ask-password', + 'src/ask-password/ask-password.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) +public_programs += exe + +executable('systemd-reply-password', + 'src/reply-password/reply-password.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +exe = executable('systemd-tty-ask-password-agent', + 'src/tty-ask-password-agent/tty-ask-password-agent.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) +public_programs += exe + +exe = executable('systemd-cgls', + 'src/cgls/cgls.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +exe = executable('systemd-cgtop', + 'src/cgtop/cgtop.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +executable('systemd-initctl', + 'src/initctl/initctl.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +exe = executable('systemd-mount', + 'src/mount/mount-tool.c', + include_directories : includes, + link_with : [libshared], + dependencies: [libmount], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +meson.add_install_script(meson_make_symlink, + 'systemd-mount', join_paths(bindir, 'systemd-umount')) + +exe = executable('systemd-run', + 'src/run/run.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +exe = executable('systemd-stdio-bridge', + 'src/stdio-bridge/stdio-bridge.c', + include_directories : includes, + link_with : [libshared], + dependencies : [versiondep], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +exe = executable('busctl', + 'src/busctl/busctl.c', + 'src/busctl/busctl-introspect.c', + 'src/busctl/busctl-introspect.h', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +if conf.get('ENABLE_SYSUSERS') == 1 + exe = executable('systemd-sysusers', + 'src/sysusers/sysusers.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) + public_programs += exe +endif + +if conf.get('ENABLE_TMPFILES') == 1 + exe = executable('systemd-tmpfiles', + 'src/tmpfiles/tmpfiles.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libacl], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) + public_programs += exe + + if want_tests != 'false' + test('test-systemd-tmpfiles', + test_systemd_tmpfiles_py, + # https://github.com/mesonbuild/meson/issues/2681 + args : exe.full_path()) + endif +endif + +if conf.get('ENABLE_HWDB') == 1 + exe = executable('systemd-hwdb', + 'src/hwdb/hwdb.c', + 'src/libsystemd/sd-hwdb/hwdb-internal.h', + include_directories : includes, + link_with : [libudev_static], + install_rpath : udev_rpath, + install : true, + install_dir : rootbindir) + public_programs += exe +endif + +if conf.get('ENABLE_QUOTACHECK') == 1 + executable('systemd-quotacheck', + 'src/quotacheck/quotacheck.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +exe = executable('systemd-socket-proxyd', + 'src/socket-proxy/socket-proxyd.c', + include_directories : includes, + link_with : [libshared], + dependencies : [threads], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +public_programs += exe + +exe = executable('systemd-udevd', + systemd_udevd_sources, + include_directories : includes, + c_args : '-DLOG_REALM=LOG_REALM_UDEV', + link_with : [libudev_core, + libsystemd_network, + libudev_static], + dependencies : [versiondep, + threads, + libkmod, + libidn, + libacl, + libblkid], + install_rpath : udev_rpath, + install : true, + install_dir : rootlibexecdir) +public_programs += exe + +exe = executable('udevadm', + udevadm_sources, + c_args : '-DLOG_REALM=LOG_REALM_UDEV', + include_directories : includes, + link_with : [libudev_core, + libsystemd_network, + libudev_static], + dependencies : [versiondep, + threads, + libkmod, + libidn, + libacl, + libblkid], + install_rpath : udev_rpath, + install : true, + install_dir : rootbindir) +public_programs += exe + +executable('systemd-shutdown', + systemd_shutdown_sources, + include_directories : includes, + link_with : [libcore_shared, + libshared], + dependencies : [libmount], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +executable('systemd-update-done', + 'src/update-done/update-done.c', + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +executable('systemd-update-utmp', + 'src/update-utmp/update-utmp.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libaudit], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +if conf.get('HAVE_KMOD') == 1 + executable('systemd-modules-load', + 'src/modules-load/modules-load.c', + include_directories : includes, + link_with : [libshared], + dependencies : [libkmod], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + meson.add_install_script('sh', '-c', + mkdir_p.format(modulesloaddir)) + meson.add_install_script('sh', '-c', + mkdir_p.format(join_paths(sysconfdir, 'modules-load.d'))) +endif + +exe = executable('systemd-nspawn', + systemd_nspawn_sources, + include_directories : includes, + link_with : [libcore_shared, + libnspawn_core, + libshared], + dependencies : [libblkid, + libseccomp], + install_rpath : rootlibexecdir, + install : true) +public_programs += exe + +if conf.get('ENABLE_NETWORKD') == 1 + executable('systemd-networkd', + systemd_networkd_sources, + include_directories : network_include_dir, + link_with : [libnetworkd_core, + libsystemd_network, + libudev_static, + libshared], + dependencies : [threads], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + executable('systemd-networkd-wait-online', + systemd_networkd_wait_online_sources, + include_directories : includes, + link_with : [libnetworkd_core, + libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + + exe = executable('networkctl', + networkctl_sources, + include_directories : includes, + link_with : [libsystemd_network, + libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootbindir) + public_programs += exe + + executable('systemd-network-generator', + network_generator_sources, + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) +endif + +executable('systemd-sulogin-shell', + ['src/sulogin-shell/sulogin-shell.c'], + include_directories : includes, + link_with : [libshared], + install_rpath : rootlibexecdir, + install : true, + install_dir : rootlibexecdir) + +############################################################ + +custom_target( + 'systemd-runtest.env', + output : 'systemd-runtest.env', + command : ['sh', '-c', '{ ' + + 'echo SYSTEMD_TEST_DATA=@0@; '.format(join_paths(project_source_root, 'test')) + + 'echo SYSTEMD_CATALOG_DIR=@0@; '.format(join_paths(meson.current_build_dir(), 'catalog')) + + '} >@OUTPUT@'], + build_by_default : true) + +foreach tuple : tests + sources = tuple[0] + link_with = tuple[1].length() > 0 ? tuple[1] : [libshared] + dependencies = tuple[2] + condition = tuple.length() >= 4 ? tuple[3] : '' + type = tuple.length() >= 5 ? tuple[4] : '' + defs = tuple.length() >= 6 ? tuple[5] : [] + incs = tuple.length() >= 7 ? tuple[6] : includes + timeout = 30 + + name = sources[0].split('/')[-1].split('.')[0] + if type.startswith('timeout=') + timeout = type.split('=')[1].to_int() + type = '' + endif + + if condition == '' or conf.get(condition) == 1 + exe = executable( + name, + sources, + include_directories : incs, + link_with : link_with, + dependencies : [versiondep, + dependencies], + c_args : defs, + build_by_default : want_tests != 'false', + install_rpath : rootlibexecdir, + install : install_tests, + install_dir : join_paths(testsdir, type)) + + if type == 'manual' + message('@0@ is a manual test'.format(name)) + elif type == 'unsafe' and want_tests != 'unsafe' + message('@0@ is an unsafe test'.format(name)) + elif want_tests != 'false' + test(name, exe, + env : test_env, + timeout : timeout) + endif + else + message('Not compiling @0@ because @1@ is not true'.format(name, condition)) + endif +endforeach + +exe = executable( + 'test-libsystemd-sym', + test_libsystemd_sym_c, + include_directories : includes, + link_with : [libsystemd], + build_by_default : want_tests != 'false', + install : install_tests, + install_dir : testsdir) +if want_tests != 'false' + test('test-libsystemd-sym', exe) +endif + +exe = executable( + 'test-libsystemd-static-sym', + test_libsystemd_sym_c, + include_directories : includes, + link_with : [install_libsystemd_static], + dependencies : [threads], # threads is already included in dependencies on the library, + # but does not seem to get propagated. Add here as a work-around. + build_by_default : want_tests != 'false' and static_libsystemd_pic, + install : install_tests and static_libsystemd_pic, + install_dir : testsdir) +if want_tests != 'false' and static_libsystemd_pic + test('test-libsystemd-static-sym', exe) +endif + +exe = executable( + 'test-libudev-sym', + test_libudev_sym_c, + include_directories : includes, + c_args : '-Wno-deprecated-declarations', + link_with : [libudev], + build_by_default : want_tests != 'false', + install : install_tests, + install_dir : testsdir) +if want_tests != 'false' + test('test-libudev-sym', exe) +endif + +exe = executable( + 'test-libudev-static-sym', + test_libudev_sym_c, + include_directories : includes, + c_args : '-Wno-deprecated-declarations', + link_with : [install_libudev_static], + build_by_default : want_tests != 'false' and static_libudev_pic, + install : install_tests and static_libudev_pic, + install_dir : testsdir) +if want_tests != 'false' and static_libudev_pic + test('test-libudev-static-sym', exe) +endif + +############################################################ + +fuzzer_exes = [] + +if get_option('tests') != 'false' +foreach tuple : fuzzers + sources = tuple[0] + link_with = tuple[1].length() > 0 ? tuple[1] : [libshared] + dependencies = tuple[2] + defs = tuple.length() >= 4 ? tuple[3] : [] + incs = tuple.length() >= 5 ? tuple[4] : includes + link_args = [] + + if want_ossfuzz or want_fuzzbuzz + dependencies += fuzzing_engine + elif want_libfuzzer + if fuzzing_engine.found() + dependencies += fuzzing_engine + else + link_args += ['-fsanitize=fuzzer'] + endif + else + sources += 'src/fuzz/fuzz-main.c' + endif + + if want_fuzzbuzz + sources += 'src/fuzz/fuzzer-entry-point.c' + endif + + name = sources[0].split('/')[-1].split('.')[0] + + fuzzer_exes += executable( + name, + sources, + include_directories : [incs, include_directories('src/fuzz')], + link_with : link_with, + dependencies : dependencies, + c_args : defs, + link_args: link_args, + install : false) +endforeach +endif + +run_target('fuzzers', + depends : fuzzer_exes, + command : ['true']) + +############################################################ + +make_directive_index_py = find_program('tools/make-directive-index.py') +make_man_index_py = find_program('tools/make-man-index.py') +xml_helper_py = find_program('tools/xml_helper.py') +hwdb_update_sh = find_program('tools/meson-hwdb-update.sh') +autosuspend_update_sh = find_program('tools/meson-autosuspend-update.sh') + +subdir('sysctl.d') +subdir('sysusers.d') +subdir('tmpfiles.d') +subdir('hwdb.d') +subdir('units') +subdir('presets') +subdir('network') +subdir('man') +subdir('shell-completion/bash') +subdir('shell-completion/zsh') +subdir('docs/sysvinit') +subdir('docs/var-log') + +install_subdir('factory/etc', + install_dir : factorydir) + +install_data('xorg/50-systemd-user.sh', + install_dir : xinitrcdir) +install_data('modprobe.d/systemd.conf', + install_dir : modprobedir) +install_data('LICENSE.GPL2', + 'LICENSE.LGPL2.1', + 'NEWS', + 'README', + 'docs/CODING_STYLE.md', + 'docs/DISTRO_PORTING.md', + 'docs/ENVIRONMENT.md', + 'docs/HACKING.md', + 'docs/TRANSIENT-SETTINGS.md', + 'docs/TRANSLATORS.md', + 'docs/UIDS-GIDS.md', + 'src/libsystemd/sd-bus/GVARIANT-SERIALIZATION', + install_dir : docdir) + +meson.add_install_script('sh', '-c', mkdir_p.format(systemdstatedir)) +meson.add_install_script('sh', '-c', 'touch $DESTDIR@0@'.format(prefixdir)) + +############################################################ + +meson_check_help = find_program('tools/meson-check-help.sh') + +foreach exec : public_programs + name = exec.full_path().split('/')[-1] + if want_tests != 'false' + test('check-help-' + name, + meson_check_help, + args : exec.full_path()) + endif +endforeach + +############################################################ + +check_directives_sh = find_program('tools/check-directives.sh') + +if want_tests != 'false' + test('check-directives', + check_directives_sh, + args : project_source_root) +endif + +############################################################ + +# Enable tests for all supported sanitizers +foreach tuple : sanitizers + sanitizer = tuple[0] + build = tuple[1] + + if cc.has_link_argument('-fsanitize=@0@'.format(sanitizer)) + prev = '' + foreach p : fuzz_regression_tests + b = p.split('/')[-2] + c = p.split('/')[-1] + + name = '@0@:@1@'.format(b, sanitizer) + + if name != prev + if want_tests == 'false' + message('Not compiling @0@ because tests is set to false'.format(name)) + elif slow_tests + exe = custom_target( + name, + output : name, + depends : build, + command : [env, 'ln', '-fs', + join_paths(build.full_path(), b), + '@OUTPUT@'], + build_by_default : true) + else + message('Not compiling @0@ because slow-tests is set to false'.format(name)) + endif + endif + prev = name + + if want_tests != 'false' and slow_tests + test('@0@:@1@:@2@'.format(b, c, sanitizer), + env, + args : [exe.full_path(), + join_paths(project_source_root, p)]) + endif + endforeach + endif +endforeach + + +############################################################ + +if git.found() + all_files = run_command( + git, + ['--git-dir=@0@/.git'.format(project_source_root), + 'ls-files', + ':/*.[ch]']) + all_files = files(all_files.stdout().split()) + + custom_target( + 'tags', + output : 'tags', + command : [env, 'etags', '-o', '@0@/TAGS'.format(project_source_root)] + all_files) + run_target( + 'ctags', + command : [env, 'ctags', '-o', '@0@/tags'.format(project_source_root)] + all_files) +endif + +if git.found() + meson_git_contrib_sh = find_program('tools/meson-git-contrib.sh') + run_target( + 'git-contrib', + command : [meson_git_contrib_sh]) +endif + +if git.found() + git_head = run_command( + git, + ['--git-dir=@0@/.git'.format(project_source_root), + 'rev-parse', 'HEAD']).stdout().strip() + git_head_short = run_command( + git, + ['--git-dir=@0@/.git'.format(project_source_root), + 'rev-parse', '--short=7', 'HEAD']).stdout().strip() + + run_target( + 'git-snapshot', + command : ['git', 'archive', + '-o', '@0@/systemd-@1@.tar.gz'.format(project_source_root, + git_head_short), + '--prefix', 'systemd-@0@/'.format(git_head), + 'HEAD']) +endif + +############################################################ + +meson_check_api_docs_sh = find_program('tools/meson-check-api-docs.sh') +run_target( + 'check-api-docs', + depends : [man, libsystemd, libudev], + command : [meson_check_api_docs_sh, libsystemd.full_path(), libudev.full_path()]) + +############################################################ +watchdog_opt = service_watchdog == '' ? 'disabled' : service_watchdog + +status = [ + '@0@ @1@'.format(meson.project_name(), meson.project_version()), + + 'split /usr: @0@'.format(split_usr), + 'split bin-sbin: @0@'.format(split_bin), + 'prefix directory: @0@'.format(prefixdir), + 'rootprefix directory: @0@'.format(rootprefixdir), + 'sysconf directory: @0@'.format(sysconfdir), + 'include directory: @0@'.format(includedir), + 'lib directory: @0@'.format(libdir), + 'rootlib directory: @0@'.format(rootlibdir), + 'SysV init scripts: @0@'.format(sysvinit_path), + 'SysV rc?.d directories: @0@'.format(sysvrcnd_path), + 'PAM modules directory: @0@'.format(pamlibdir), + 'PAM configuration directory: @0@'.format(pamconfdir), + 'RPM macros directory: @0@'.format(rpmmacrosdir), + 'modprobe.d directory: @0@'.format(modprobedir), + 'D-Bus policy directory: @0@'.format(dbuspolicydir), + 'D-Bus session directory: @0@'.format(dbussessionservicedir), + 'D-Bus system directory: @0@'.format(dbussystemservicedir), + 'bash completions directory: @0@'.format(bashcompletiondir), + 'zsh completions directory: @0@'.format(zshcompletiondir), + 'extra start script: @0@'.format(get_option('rc-local')), + 'debug shell: @0@ @ @1@'.format(get_option('debug-shell'), + get_option('debug-tty')), + 'TTY GID: @0@'.format(tty_gid), + 'users GID: @0@'.format(substs.get('USERS_GID')), + 'maximum system UID: @0@'.format(system_uid_max), + 'maximum system GID: @0@'.format(system_gid_max), + 'minimum dynamic UID: @0@'.format(dynamic_uid_min), + 'maximum dynamic UID: @0@'.format(dynamic_uid_max), + 'minimum container UID base: @0@'.format(container_uid_base_min), + 'maximum container UID base: @0@'.format(container_uid_base_max), + '/dev/kvm access mode: @0@'.format(get_option('dev-kvm-mode')), + 'render group access mode: @0@'.format(get_option('group-render-mode')), + 'certificate root directory: @0@'.format(get_option('certificate-root')), + 'support URL: @0@'.format(support_url), + 'nobody user name: @0@'.format(nobody_user), + 'nobody group name: @0@'.format(nobody_group), + 'fallback hostname: @0@'.format(get_option('fallback-hostname')), + 'symbolic gateway hostnames: @0@'.format(', '.join(gateway_hostnames)), + + 'default DNSSEC mode: @0@'.format(default_dnssec), + 'default DNS-over-TLS mode: @0@'.format(default_dns_over_tls), + 'default cgroup hierarchy: @0@'.format(default_hierarchy), + 'default net.naming-scheme setting: @0@'.format(default_net_naming_scheme), + 'default KillUserProcesses setting: @0@'.format(kill_user_processes), + 'default locale: @0@'.format(default_locale), + 'default user $PATH: @0@'.format(default_user_path_display), + 'systemd service watchdog: @0@'.format(watchdog_opt)] + +alt_dns_servers = '\n '.join(dns_servers.split(' ')) +alt_ntp_servers = '\n '.join(ntp_servers.split(' ')) +status += [ + 'default DNS servers: @0@'.format(alt_dns_servers), + 'default NTP servers: @0@'.format(alt_ntp_servers)] + +alt_time_epoch = run_command('date', '-Is', '-u', '-d', + '@@0@'.format(time_epoch)).stdout().strip() +status += [ + 'time epoch: @0@ (@1@)'.format(time_epoch, alt_time_epoch)] + +status += [ + 'static libsystemd: @0@'.format(static_libsystemd), + 'static libudev: @0@'.format(static_libudev)] + +# TODO: +# CFLAGS: ${OUR_CFLAGS} ${CFLAGS} +# CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS} +# LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS} + +if conf.get('ENABLE_EFI') == 1 + status += 'efi arch: @0@'.format(efi_arch) + + if have_gnu_efi + status += [ + 'EFI machine type: @0@'.format(EFI_MACHINE_TYPE_NAME), + 'EFI CC @0@'.format(' '.join(efi_cc)), + 'EFI lds: @0@'.format(efi_lds), + 'EFI crt0: @0@'.format(efi_crt0), + 'EFI include directory: @0@'.format(efi_incdir)] + endif +endif + +found = [] +missing = [] + +foreach tuple : [ + ['libcryptsetup'], + ['PAM'], + ['AUDIT'], + ['IMA'], + ['AppArmor'], + ['SELinux'], + ['SECCOMP'], + ['SMACK'], + ['zlib'], + ['xz'], + ['lz4'], + ['bzip2'], + ['ACL'], + ['gcrypt'], + ['qrencode'], + ['microhttpd'], + ['gnutls'], + ['openssl'], + ['libcurl'], + ['idn'], + ['libidn2'], + ['libidn'], + ['libiptc'], + ['elfutils'], + ['binfmt'], + ['vconsole'], + ['quotacheck'], + ['tmpfiles'], + ['environment.d'], + ['sysusers'], + ['firstboot'], + ['randomseed'], + ['backlight'], + ['rfkill'], + ['logind'], + ['machined'], + ['portabled'], + ['importd'], + ['hostnamed'], + ['timedated'], + ['timesyncd'], + ['localed'], + ['networkd'], + ['resolve'], + ['DNS-over-TLS(gnutls)', conf.get('DNS_OVER_TLS_USE_GNUTLS') == 1], + ['DNS-over-TLS(openssl)', conf.get('DNS_OVER_TLS_USE_OPENSSL') == 1], + ['coredump'], + ['pstore'], + ['polkit'], + ['legacy pkla', install_polkit_pkla], + ['efi'], + ['gnu-efi', have_gnu_efi], + ['kmod'], + ['xkbcommon'], + ['pcre2'], + ['blkid'], + ['dbus'], + ['glib'], + ['nss-myhostname'], + ['nss-mymachines'], + ['nss-resolve'], + ['nss-systemd'], + ['hwdb'], + ['tpm'], + ['man pages', want_man], + ['html pages', want_html], + ['man page indices', want_man and have_lxml], + ['SysV compat'], + ['utmp'], + ['ldconfig'], + ['hibernate'], + ['adm group', get_option('adm-group')], + ['wheel group', get_option('wheel-group')], + ['gshadow'], + ['debug hashmap'], + ['debug mmap cache'], + ['debug siphash'], + ['valgrind', conf.get('VALGRIND') == 1], + ['trace logging', conf.get('LOG_TRACE') == 1], + ['link-udev-shared', get_option('link-udev-shared')], + ['link-systemctl-shared', get_option('link-systemctl-shared')], +] + + if tuple.length() >= 2 + cond = tuple[1] + else + ident1 = 'HAVE_' + tuple[0].underscorify().to_upper() + ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper() + cond = conf.get(ident1, 0) == 1 or conf.get(ident2, 0) == 1 + endif + if cond + found += tuple[0] + else + missing += tuple[0] + endif +endforeach + +status += [ + '', + 'enabled features: @0@'.format(', '.join(found)), + '', + 'disabled features: @0@'.format(', '.join(missing)), + ''] +message('\n '.join(status)) + +if rootprefixdir != rootprefix_default + warning('\n' + + 'Note that the installation prefix was changed to "@0@".\n'.format(rootprefixdir) + + 'systemd used fixed names for unit file directories and other paths, so anything\n' + + 'except the default ("@0@") is strongly discouraged.'.format(rootprefix_default)) +endif diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 00000000..44ff23f6 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,346 @@ +# -*- mode: meson -*- +# SPDX-License-Identifier: LGPL-2.1+ + +option('version-tag', type : 'string', + description : 'override the git version string') + +option('split-usr', type : 'combo', choices : ['auto', 'true', 'false'], + description : '''/bin, /sbin aren't symlinks into /usr''') +option('split-bin', type : 'combo', choices : ['auto', 'true', 'false'], + description : '''sbin is not a symlink to bin''') +option('rootlibdir', type : 'string', + description : '''[/usr]/lib/x86_64-linux-gnu or such''') +option('rootprefix', type : 'string', + description : '''override the root prefix [default '/' if split-usr and '/usr' otherwise]''') +option('link-udev-shared', type : 'boolean', + description : 'link systemd-udev and its helpers to libsystemd-shared.so') +option('link-systemctl-shared', type: 'boolean', + description : 'link systemctl against libsystemd-shared.so') +option('static-libsystemd', type : 'combo', + choices : ['false', 'true', 'pic', 'no-pic'], + description : '''install a static library for libsystemd''') +option('static-libudev', type : 'combo', + choices : ['false', 'true', 'pic', 'no-pic'], + description : '''install a static library for libudev''') + +option('sysvinit-path', type : 'string', value : '/etc/init.d', + description : 'the directory where the SysV init scripts are located') +option('sysvrcnd-path', type : 'string', value : '/etc/rc.d', + description : 'the base directory for SysV rcN.d directories') +option('telinit-path', type : 'string', value : '/lib/sysvinit/telinit', + description : 'path to telinit') +option('rc-local', type : 'string', + value : '/etc/rc.local') + +option('quotaon-path', type : 'string', description : 'path to quotaon') +option('quotacheck-path', type : 'string', description : 'path to quotacheck') +option('kmod-path', type : 'string', description : 'path to kmod') +option('kexec-path', type : 'string', description : 'path to kexec') +option('sulogin-path', type : 'string', description : 'path to sulogin') +option('mount-path', type : 'string', description : 'path to mount') +option('umount-path', type : 'string', description : 'path to umount') +option('loadkeys-path', type : 'string', description : 'path to loadkeys') +option('setfont-path', type : 'string', description : 'path to setfont') +option('nologin-path', type : 'string', description : 'path to nologin') + +option('debug-shell', type : 'string', value : '/bin/sh', + description : 'path to debug shell binary') +option('debug-tty', type : 'string', value : '/dev/tty9', + description : 'specify the tty device for debug shell') +option('debug-extra', type : 'array', choices : ['hashmap', 'mmap-cache', 'siphash'], value : [], + description : 'enable extra debugging') +option('memory-accounting-default', type : 'boolean', + description : 'enable MemoryAccounting= by default') +option('bump-proc-sys-fs-file-max', type : 'boolean', + description : 'bump /proc/sys/fs/file-max to ULONG_MAX') +option('bump-proc-sys-fs-nr-open', type : 'boolean', + description : 'bump /proc/sys/fs/nr_open to INT_MAX') +option('valgrind', type : 'boolean', value : false, + description : 'do extra operations to avoid valgrind warnings') +option('log-trace', type : 'boolean', value : false, + description : 'enable low level debug logging') +option('user-path', type : 'string', + description : '$PATH to use for user sessions') + +option('utmp', type : 'boolean', + description : 'support for utmp/wtmp log handling') +option('hibernate', type : 'boolean', + description : 'support for hibernation') +option('ldconfig', type : 'boolean', + description : 'support for dynamic linker cache creation') +option('resolve', type : 'boolean', + description : 'systemd-resolved stack') +option('efi', type : 'boolean', + description : 'enable systemd-boot and bootctl') +option('tpm', type : 'boolean', + description : 'TPM should be used to log events and extend the registers') +option('environment-d', type : 'boolean', + description : 'support for environment.d') +option('binfmt', type : 'boolean', + description : 'support for custom binary formats') +option('coredump', type : 'boolean', + description : 'install the coredump handler') +option('pstore', type : 'boolean', + description : 'install the pstore archival tool') +option('logind', type : 'boolean', + description : 'install the systemd-logind stack') +option('hostnamed', type : 'boolean', + description : 'install the systemd-hostnamed stack') +option('localed', type : 'boolean', + description : 'install the systemd-localed stack') +option('machined', type : 'boolean', + description : 'install the systemd-machined stack') +option('portabled', type : 'boolean', + description : 'install the systemd-portabled stack') +option('networkd', type : 'boolean', + description : 'install the systemd-networkd stack') +option('timedated', type : 'boolean', + description : 'install the systemd-timedated daemon') +option('timesyncd', type : 'boolean', + description : 'install the systemd-timesyncd daemon') +option('remote', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'support for "journal over the network"') +option('create-log-dirs', type : 'boolean', + description : 'create /var/log/journal{,/remote}') +option('nss-myhostname', type : 'boolean', + description : 'install nss-myhostname module') +option('nss-mymachines', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'install nss-mymachines module') +option('nss-resolve', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'install nss-resolve module') +option('nss-systemd', type : 'boolean', + description : 'install nss-systemd module') +option('firstboot', type : 'boolean', + description : 'support for firstboot mechanism') +option('randomseed', type : 'boolean', + description : 'support for restoring random seed') +option('backlight', type : 'boolean', + description : 'support for restoring backlight state') +option('vconsole', type : 'boolean', + description : 'support for vconsole configuration') +option('quotacheck', type : 'boolean', + description : 'support for the quotacheck tools') +option('sysusers', type : 'boolean', + description : 'support for the sysusers configuration') +option('tmpfiles', type : 'boolean', + description : 'support for tmpfiles.d') +option('importd', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'install the systemd-importd daemon') +option('hwdb', type : 'boolean', + description : 'support for the hardware database') +option('rfkill', type : 'boolean', + description : 'support for the rfkill tools') +option('man', type : 'combo', choices : ['auto', 'true', 'false'], + value : 'false', + description : 'build and install man pages') +option('html', type : 'combo', choices : ['auto', 'true', 'false'], + value : 'false', + description : 'build and install html pages') + +option('certificate-root', type : 'string', value : '/etc/ssl', + description : 'the prefix for TLS certificates') +option('dbuspolicydir', type : 'string', + description : 'D-Bus policy directory') +option('dbussessionservicedir', type : 'string', + description : 'D-Bus session service directory') +option('dbussystemservicedir', type : 'string', + description : 'D-Bus system service directory') +option('pkgconfigdatadir', type : 'string', value : '', + description : 'directory for arch-independent pkg-config files') +option('pkgconfiglibdir', type : 'string', value : '', + description : 'directory for standard pkg-config files') +option('rpmmacrosdir', type : 'string', value : 'lib/rpm/macros.d', + description : 'directory for rpm macros ["no" disables]') +option('pamlibdir', type : 'string', + description : 'directory for PAM modules') +option('pamconfdir', type : 'string', + description : 'directory for PAM configuration ["no" disables]') +option('docdir', type : 'string', + description : 'documentation directory') + +option('fallback-hostname', type : 'string', value : 'localhost', + description : 'the hostname used if none configured') +option('compat-gateway-hostname', type : 'boolean', value : 'false', + description : 'allow "gateway" as the symbolic name for default gateway') +option('default-hierarchy', type : 'combo', + choices : ['legacy', 'hybrid', 'unified'], value : 'unified', + description : 'default cgroup hierarchy') +option('default-net-naming-scheme', type : 'combo', + choices : ['latest', 'v238', 'v239', 'v240'], + description : 'default net.naming-scheme= value') +option('status-unit-format-default', type : 'combo', + choices : ['description', 'name'], + description : 'use unit name or description in messages by default') +option('time-epoch', type : 'integer', value : '-1', + description : 'time epoch for time clients') +option('system-uid-max', type : 'integer', value : '-1', + description : 'maximum system UID') +option('system-gid-max', type : 'integer', value : '-1', + description : 'maximum system GID') +option('dynamic-uid-min', type : 'integer', value : 0x0000EF00, + description : 'minimum dynamic UID') +option('dynamic-uid-max', type : 'integer', value : 0x0000FFEF, + description : 'maximum dynamic UID') +option('container-uid-base-min', type : 'integer', value : 0x00080000, + description : 'minimum container UID base') +option('container-uid-base-max', type : 'integer', value : 0x6FFF0000, + description : 'maximum container UID base') +option('tty-gid', type : 'integer', value : 5, + description : 'the numeric GID of the "tty" group') +option('users-gid', type : 'integer', value : '-1', + description : 'the numeric GID of the "users" group') +option('adm-group', type : 'boolean', + description : 'the ACL for adm group should be added') +option('wheel-group', type : 'boolean', + description : 'the ACL for wheel group should be added') +option('nobody-user', type : 'string', + description : 'The name of the nobody user (the one with UID 65534)', + value : 'nobody') +option('nobody-group', type : 'string', + description : 'The name of the nobody group (the one with GID 65534)', + value : 'nobody') +option('dev-kvm-mode', type : 'string', value : '0666', + description : '/dev/kvm access mode') +option('group-render-mode', type : 'string', value : '0666', + description : 'Access mode for devices owned by render group (e.g. /dev/dri/renderD*, /dev/kfd).') +option('default-kill-user-processes', type : 'boolean', + description : 'the default value for KillUserProcesses= setting') +option('gshadow', type : 'boolean', + description : 'support for shadow group') +option('default-locale', type : 'string', value : '', + description : 'default locale used when /etc/locale.conf does not exist') +option('service-watchdog', type : 'string', value : '3min', + description : 'default watchdog setting for systemd services') + +option('default-dnssec', type : 'combo', + description : 'default DNSSEC mode', + choices : ['yes', 'allow-downgrade', 'no'], + value : 'allow-downgrade') +option('default-dns-over-tls', type : 'combo', + description : 'default DNS-over-TLS mode', + choices : ['yes', 'opportunistic', 'no'], + value : 'no') +option('dns-over-tls', type : 'combo', choices : ['auto', 'gnutls', 'openssl', 'true', 'false'], + description : 'DNS-over-TLS support') +option('dns-servers', type : 'string', + description : 'space-separated list of default DNS servers', + value : '1.1.1.1 8.8.8.8 1.0.0.1 8.8.4.4 2606:4700:4700::1111 2001:4860:4860::8888 2606:4700:4700::1001 2001:4860:4860::8844') +option('ntp-servers', type : 'string', + description : 'space-separated list of default NTP servers', + value : 'time1.google.com time2.google.com time3.google.com time4.google.com') +option('support-url', type : 'string', + description : 'the support URL to show in catalog entries included in systemd', + value : 'https://lists.freedesktop.org/mailman/listinfo/systemd-devel') +option('www-target', type : 'string', + description : 'the address and dir to upload docs too', + value : 'www.freedesktop.org:/srv/www.freedesktop.org/www/software/systemd') + +option('seccomp', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'SECCOMP support') +option('selinux', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'SELinux support') +option('apparmor', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'AppArmor support') +option('smack', type : 'boolean', + description : 'SMACK support') +option('smack-run-label', type : 'string', + description : 'run systemd --system itself with a specific SMACK label') +option('polkit', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'polkit support') +option('ima', type : 'boolean', + description : 'IMA support') + +option('acl', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libacl support') +option('audit', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libaudit support') +option('blkid', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libblkid support') +option('kmod', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'support for loadable modules') +option('pam', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'PAM support') +option('microhttpd', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libµhttpd support') +option('libcryptsetup', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libcryptsetup support') +option('libcurl', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libcurl support') +option('idn', type : 'boolean', + description : 'use IDN when printing host names') +option('libidn2', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libidn2 support') +option('libidn', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libidn support') +option('libiptc', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libiptc support') +option('qrencode', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libqrencode support') +option('gcrypt', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'gcrypt support') +option('gnutls', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'gnutls support') +option('openssl', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'openssl support') +option('elfutils', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'elfutils support') +option('zlib', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'zlib compression support') +option('bzip2', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'bzip2 compression support') +option('xz', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'xz compression support') +option('lz4', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'lz4 compression support') +option('xkbcommon', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'xkbcommon keymap support') +option('pcre2', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'regexp matching support using pcre2') +option('glib', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libglib support (for tests only)') +option('dbus', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'libdbus support (for tests only)') + +option('gnu-efi', type : 'combo', choices : ['auto', 'true', 'false'], + description : 'gnu-efi support for sd-boot') +option('efi-cc', type : 'array', + description : 'the compiler to use for EFI modules') +option('efi-ld', type : 'string', + description : 'the linker to use for EFI modules') +option('efi-libdir', type : 'string', + description : 'path to the EFI lib directory') +option('efi-includedir', type : 'string', value : '/usr/include/efi', + description : 'path to the EFI header directory') +option('tpm-pcrindex', type : 'integer', value : 8, + description : 'TPM PCR register number to use') + +option('bashcompletiondir', type : 'string', + description : 'directory for bash completion scripts ["no" disables]') +option('zshcompletiondir', type : 'string', + description : 'directory for zsh completion scripts ["no" disables]') + +option('tests', type : 'combo', choices : ['true', 'unsafe', 'false'], + description : 'enable extra tests with =unsafe') +option('slow-tests', type : 'boolean', value : 'false', + description : 'run the slow tests by default') +option('install-tests', type : 'boolean', value : 'false', + description : 'install test executables') + +option('ok-color', type: 'combo', + choices : ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', + 'white', 'highlight-black', 'highlight-red', 'highlight-green', + 'highlight-yellow', 'highlight-blue', 'highlight-magenta', + 'highlight-cyan', 'highlight-white'], + value : 'green', + description: 'color of the "OK" status message') + +option('oss-fuzz', type : 'boolean', value : 'false', + description : 'build against oss-fuzz') +option('llvm-fuzz', type : 'boolean', value : 'false', + description : 'build against LLVM libFuzzer') +option('fuzzbuzz', type : 'boolean', value : 'false', + description : 'build against FuzzBuzz') +option('fuzzbuzz-engine', type : 'string', + description : 'the name of the FuzzBuzz fuzzing engine') +option('fuzzbuzz-engine-dir', type : 'string', + description : 'the directory where the FuzzBuzz fuzzing engine is') diff --git a/mkosi.build b/mkosi.build new file mode 100755 index 00000000..16ac2e9d --- /dev/null +++ b/mkosi.build @@ -0,0 +1,101 @@ +#!/bin/sh +set -ex + +# This is a build script for OS image generation using mkosi (https://github.com/systemd/mkosi). +# Simply invoke "mkosi" in the project directory to build an OS image. + +# Reset the permissions of the tree. Since Meson keeps the permissions +# all the way to the installed files, reset them to one of 0644 or 0755 +# so the files keep those permissions, otherwise details of what umask +# was set at the time the git tree was cloned will leak all the way +# through. Also set umask explicitly during the build. +chmod -R u+w,go-w,a+rX . +umask 022 + +# If mkosi.builddir/ exists mkosi will set $BUILDDIR to it, let's then use it +# as out-of-tree build dir. Otherwise, let's make up our own builddir. +[ -z "$BUILDDIR" ] && BUILDDIR=build + +# Meson uses Python 3 and requires a locale with an UTF-8 character map. +# Not running under UTF-8 makes the `ninja test` step break with a CodecError. +# So let's ensure we're running under UTF-8. +# +# If our current locale already is UTF-8, then we don't need to do anything: +if [ "$(locale charmap)" != "UTF-8" ] ; then + # Try using C.UTF-8 locale, if available. This locale is not shipped + # by upstream glibc, so it's not available in all distros. + # (In particular, it's not available in Arch Linux.) + export LC_CTYPE=C.UTF-8 + if [ "$(locale charmap)" != "UTF-8" ] ; then + # Finally, try something like en_US.UTF-8, which should be + # available in Arch Linux, but is not present in Debian's + # minimal image in our mkosi config. + export LC_CTYPE=en_US.UTF-8 + if [ "$(locale charmap)" != "UTF-8" ] ; then + # If nothing works, fail early. + echo "*** Could not find a valid locale that supports UTF-8. ***" >&2 + exit 1 + fi + fi +fi + +if [ ! -f "$BUILDDIR"/build.ninja ] ; then + sysvinit_path=`realpath /etc/init.d` + + nobody_user=`id -u -n 65534 2> /dev/null` + if [ "$nobody_user" != "" ] ; then + # Validate that we can translate forth and back + if [ "`id -u $nobody_user`" != 65534 ] ; then + nobody_user="" + fi + fi + if [ "$nobody_user" = "" ] ; then + if id -u nobody 2> /dev/null ; then + # The "nobody" user is defined already for something else, pick the Fedora name + nobody_user=nfsnobody + else + # The "nobody" user name is free, use it + nobody_user=nobody + fi + fi + + nobody_group=`id -g -n 65534 2> /dev/null` + if [ "$nobody_group" != "" ] ; then + # Validate that we can translate forth and back + if [ "`id -g $nobody_group`" != 65534 ] ; then + nobody_group="" + fi + fi + if [ "$nobody_group" = "" ] ; then + if id -u nobody 2> /dev/null ; then + # The "nobody" group is defined already for something else, pick the Fedora name + nobody_group=nfsnobody + else + # The "nobody" group name is free, use it + nobody_group=nobody + fi + fi + + meson "$BUILDDIR" -D "sysvinit-path=$sysvinit_path" -D default-hierarchy=unified -D man=false -D "nobody-user=$nobody_user" -D "nobody-group=$nobody_group" +fi + +ninja -C "$BUILDDIR" all +[ "$WITH_TESTS" = 0 ] || ninja -C "$BUILDDIR" test +ninja -C "$BUILDDIR" install + +mkdir -p "$DESTDIR"/etc + +cat > "$DESTDIR"/etc/issue <, 2015, 2016. +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-06-09 19:54+0300\n" +"PO-Revision-Date: 2016-06-09 19:47+0300\n" +"Last-Translator: Viktar Vaŭčkievič \n" +"Language-Team: \n" +"Language: be\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"X-Generator: Lokalize 2.0\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Адправіць пароль назад сістэме" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "Неабходна аўтэнтыфікацыя для адпраўкі пароля назад сістэме." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Кіраваць сэрвісамі і іншымі сістэмнымі адзінкамі" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Неабходна аўтэнтыфікацыя для кіравання сэрвісамі і іншымі сістэмнымі " +"адзінкамі." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Кіраваць файламі сэрвісаў і іншых сістэмных адзінак" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Неабходна аўтэнтыфікацыя для кіравання файламі сэрвісаў і іншых сістэмных " +"адзінак." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "Усталяваць або скінуць зменныя асяроддзя сістэмнага мэнэджэра" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Неабходна аўтэнтыфікацыя для ўсталявання або скіду зменных асяроддзя " +"сістэмнага мэнэджэра." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Перачытаць стан systemd" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Неабходна аўтэнтыфікацыя для перачытання стану systemd." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Усталяваць імя вузла" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Неабходна аўтэнтыфікацыя для ўсталявання імя вузла." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Усталяваць статычнае імя вузла" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Неабходна аўтэнтыфікацыя для ўсталявання як статычнага так і прыгожага імя " +"вузла." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Усталяваць інфармацыю аб машыне" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "" +"Неабходна аўтэнтыфікацыя для ўсталявання інфармацыі аб лакальнай машыне." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Імпартаваць вобраз ВМ або кантэйнера" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "Неабходна аўтэнтыфікацыя для імпарту вобраза ВМ або кантэйнера" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Экспартаваць вобраз ВМ або кантэйнера" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "Неабходна аўтэнтыфікацыя для экспарту вобраза ВМ або кантэйнера" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Спампаваць вобраз ВМ або кантэйнера" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "Неабходна аўтэнтыфікацыя для спампоўкі вобраза ВМ або кантэйнера" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Усталяваць сістэмную лакаль" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнай лакалі." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Усталяваць сістэмныя налады клавіятуры" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмных налад клавіятуры." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Дазволіць праграмам перашкаджаць выключэнню сістэмы" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць выключэнню " +"сістэмы." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Дазволіць праграмам затрымліваць выключэнне сістэмы" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Неабходна аўтэнтыфікацыя для дазволу праграмам затрымліваць выключэнне " +"сістэмы." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Дазволіць праграмам перашкаджаць засыпанню сістэмы" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць засыпанню " +"сістэмы." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Дазволіць праграмам затрымліваць засыпанне сістэмы" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Неабходна аўтэнтыфікацыя для дазволу праграмам затрымліваць засыпанне " +"сістэмы." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Дазволіць праграмам перашкаджаць аўтаматычнаму прыпыненню сістэмы" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць аўтаматычнаму " +"прыпыненню сістэмы." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу выключэння" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " +"апрацоўваць клавішу выключэння." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу прыпынення" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " +"апрацоўваць клавішу прыпынення." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Дазволіць праграмам перашкаджаць сістэме апрацоўваць клавішу гібернацыі" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " +"апрацоўваць клавішу гібернацыі." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Дазволіць праграмам перашкаджаць сістэме апрацоўваць закрыццё крышкі ноўтбука" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Неабходна аўтэнтыфікацыя для дазволу праграмам перашкаджаць сістэме " +"апрацоўваць закрыццё крышкі ноўтбука." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in user to run programs" +msgstr "" +"Дазволіць карыстальніку, якія яшчэ не ўвайшоў у сістэму, выконваць праграмы" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Неабходны відавочны запыт для выканання праграм карыстальніка, які яшчэ не " +"ўвайшоў у сістэму." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow non-logged-in users to run programs" +msgstr "" +"Дазволіць карыстальнікам, якія яшчэ не ўвайшлі ў сістэму, выконваць праграмы" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Неабходна аўтэнтыфікацыя для выканання праграм карыстальніка, які яшчэ не " +"ўвайшоў у сістэму." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Allow attaching devices to seats" +msgstr "Дазволіць далучаць прылады да працоўных месцаў" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "Authentication is required for attaching a device to a seat." +msgstr "Неабходна аўтэнтыфікацыя для далучэння прылад да працоўных месцаў." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Flush device to seat attachments" +msgstr "Адключаць прылады ад працоўных месцаў" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "Неабходна аўтэнтыфікацыя для адключэння прылад ад працоўных месцаў." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system" +msgstr "Выключыць сістэму" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "Authentication is required for powering off the system." +msgstr "Неабходна аўтэнтыфікацыя для выключэння сістэмы." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while other users are logged in" +msgstr "Выключыць сістэму пры прысутнасці іншых карыстальнікаў" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Неабходна аўтэнтыфікацыя для выключэння сістэмы пры прысутнасці іншых " +"карыстальнікаў." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Выключыць сістэму, калі праграмы перашкаджаюць гэтаму" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Неабходна аўтэнтыфікацыя для выключэння сістэмы, калі праграмы перашкаджаюць " +"гэтаму." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system" +msgstr "Перазагрузіць сістэму" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "Authentication is required for rebooting the system." +msgstr "Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while other users are logged in" +msgstr "Перазагрузіць сістэму пры прысутнасці іншых карыстальнікаў" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы пры прысутнасці іншых " +"карыстальнікаў." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Перазагрузіць сістэму, калі праграмы перашкаджаюць гэтаму" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Неабходна аўтэнтыфікацыя для перазагрузкі сістэмы, калі праграмы " +"перашкаджаюць гэтаму." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system" +msgstr "Прыпыніць сістэму" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "Authentication is required for suspending the system." +msgstr "Неабходна аўтэнтыфікацыя для прыпынення сістэмы." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while other users are logged in" +msgstr "Прыпыніць сістэму пры прысутнасці іншых карыстальнікаў" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Неабходна аўтэнтыфікацыя для прыпынення сістэмы пры прысутнасці іншых " +"карыстальнікаў." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Прыпыніць сістэму, калі праграмы перашкаджаюць гэтаму" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Неабходна аўтэнтыфікацыя для прыпынення сістэмы, калі праграмы перашкаджаюць " +"гэтаму." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system" +msgstr "Гібернаваць сістэму" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "Authentication is required for hibernating the system." +msgstr "Неабходна аўтэнтыфікацыя для гібернацыі сістэмы." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while other users are logged in" +msgstr "Гібернаваць сістэму пры прысутнасці іншых карыстальнікаў" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Неабходна аўтэнтыфікацыя для гібернацыі сістэмы пры прысутнасці іншых " +"карыстальнікаў." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Гібернаваць сістэму, калі праграмы перашкаджаюць гэтаму" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Неабходна аўтэнтыфікацыя для гібернацыі сістэмы, калі праграмы перашкаджаюць " +"гэтаму." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Manage active sessions, users and seats" +msgstr "Кіраваць актыўнымі сесіямі, карыстальнікамі і працоўнымі месцамі" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Неабходна аўтэнтыфікацыя для кіравання актыўнымі сесіямі, карыстальнікамі і " +"месцамі." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Lock or unlock active sessions" +msgstr "Блакаваць або разблакаваць актыўную сесію" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Неабходна аўтэнтыфікацыя для блакіроўкі або разблакіроўкі актыўнай сесіі." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "Дазволіць указанне прашыўцы на загрузку інтэрфейсу налад" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Неабходна аўтэнтыфікацыя для ўказання прашыўцы на загрузку інтэрфейсу налад." + +#: ../src/login/org.freedesktop.login1.policy.in.h:57 +msgid "Set a wall message" +msgstr "Усталяваць усеагульнае паведамленне" + +#: ../src/login/org.freedesktop.login1.policy.in.h:58 +msgid "Authentication is required to set a wall message" +msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўсеагульнага паведамлення" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Увайсці ў лакальны кантэйнер" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "Неабходна аўтэнтыфікацыя для ўваходу ў лакальны кантэйнер." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Увайсці ў лакальны вузел" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Неабходна аўтэнтыфікацыя для ўваходу ў лакальны вузел." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Атрымаць абалонку на лакальным кантэйнеры" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Неабходна аўтэнтыфікацыя для атрымання абалонкі на лакальным кантэйнеры." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Атрымаць абалонку на лакальным вузле" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Неабходна аўтэнтыфікацыя для атрымання абалонкі на лакальным вузле." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Атрымаць псеўда TTY на лакальным кантэйнеры" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Неабходна аўтэнтыфікацыя для атрымання псеўда TTY на лакальным кантэйнеры." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Атрымаць псеўда TTY на лакальным вузле" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "Неабходна аўтэнтыфікацыя для атрымання псеўда TTY на лакальным вузле." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Кіраваць лакальнымі віртуальнымі машынамі або кантэйнерамі" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Неабходна аўтэнтыфікацыя для кіравання лакальнымі віртуальнымі машынамі і " +"кантэйнерамі." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Кіраваць вобразамі лакальных віртуальных машын і кантэйнераў" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Неабходна аўтэнтыфікацыя для кіравання вобразамі лакальных віртуальных машын " +"і кантэйнераў." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Усталяваць сістэмны час" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часу." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Усталяваць сістэмны часавы пояс" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "Неабходна аўтэнтыфікацыя для ўсталявання сістэмнага часавога поясу." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Усталяваць часавы пояс (мясцовы або UTC), у якім RTC захоўвае час" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Неабходна аўтэнтыфікацыя для ўсталявання часавога поясу (мясцовы або UTC), у " +"якім захоўваецца час у RTC." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Уключыць або выключыць сінхранізацыю часу па сетцы" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Неабходна аўтэнтыфікацыя для ўключэння або выключэння сінхранізацыі часу па " +"сетцы." + +#: ../src/core/dbus-unit.c:450 +msgid "Authentication is required to start '$(unit)'." +msgstr "Неабходна аўтэнтыфікацыя для запуску '$(unit)'." + +#: ../src/core/dbus-unit.c:451 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Неабходна аўтэнтыфікацыя для спынення '$(unit)'." + +#: ../src/core/dbus-unit.c:452 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Неабходна аўтэнтыфікацыя для перачытання стану '$(unit)'." + +#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Неабходна аўтэнтыфікацыя для перазапуску '$(unit)'." + +#: ../src/core/dbus-unit.c:560 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Неабходна аўтэнтыфікацыя для забойства '$(unit)'." + +#: ../src/core/dbus-unit.c:590 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "Неабходна аўтэнтыфікацыя для анулявання памылковага стану '$(unit)'." + +#: ../src/core/dbus-unit.c:622 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Неабходна аўтэнтыфікацыя для ўсталявання ўласцівасцей '$(unit)'." diff --git a/po/be@latin.po b/po/be@latin.po new file mode 100644 index 00000000..eed51937 --- /dev/null +++ b/po/be@latin.po @@ -0,0 +1,605 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Belarusian translation for systemd. +# +# +# Viktar Vaŭčkievič , 2015, 2016. +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-06-09 19:54+0300\n" +"PO-Revision-Date: 2016-06-09 19:50+0300\n" +"Last-Translator: Viktar Vaŭčkievič \n" +"Language-Team: \n" +"Language: be@latin\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"X-Generator: Lokalize 2.0\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Adpravić paroĺ nazad sistemie" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "Nieabchodna aŭtentyfikacyja dlia adpraŭki parolia nazad sistemie." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Kiravać servisami i inšymi sistemnymi adzinkami" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia kiravannia servisami i inšymi sistemnymi " +"adzinkami." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Kiravać fajlami servisaŭ i inšych sistemnych adzinak" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia kiravannia fajlami servisaŭ i inšych " +"sistemnych adzinak." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "Ustaliavać abo skinuć zmiennyja asiaroddzia sistemnaha menedžera" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia abo skidu zmiennych " +"asiaroddzia sistemnaha menedžera." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Pieračytać stan systemd" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu systemd." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Ustaliavać imia vuzla" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia imia vuzla." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Ustaliavać statyčnaje imia vuzla" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia jak statyčnaha tak i " +"pryhožaha imia vuzla." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Ustaliavać infarmacyju ab mašynie" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia infarmacyi ab lakaĺnaj " +"mašynie." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Impartavać vobraz VM abo kantejniera" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "Nieabchodna aŭtentyfikacyja dlia impartu vobraza VM abo kantejniera" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Ekspartavać vobraz VM abo kantejniera" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "Nieabchodna aŭtentyfikacyja dlia ekspartu vobraza VM abo kantejniera" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Spampavać vobraz VM abo kantejniera" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "Nieabchodna aŭtentyfikacyja dlia spampoŭki vobraza VM abo kantejniera" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Ustaliavać sistemnuju lakaĺ" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaj lakali." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Ustaliavać sistemnyja nalady klavijatury" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnych nalad klavijatury." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Dazvolić prahramam pieraškadžać vykliučenniu sistemy" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać vykliučenniu " +"sistemy." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Dazvolić prahramam zatrymlivać vykliučennie sistemy" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam zatrymlivać vykliučennie " +"sistemy." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Dazvolić prahramam pieraškadžać zasypanniu sistemy" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać zasypanniu " +"sistemy." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Dazvolić prahramam zatrymlivać zasypannie sistemy" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam zatrymlivać zasypannie " +"sistemy." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Dazvolić prahramam pieraškadžać aŭtamatyčnamu prypynienniu sistemy" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać " +"aŭtamatyčnamu prypynienniu sistemy." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Dazvolić prahramam pieraškadžać sistemie apracoŭvać klavišu vykliučennia" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " +"apracoŭvać klavišu vykliučennia." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Dazvolić prahramam pieraškadžać sistemie apracoŭvać klavišu prypyniennia" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " +"apracoŭvać klavišu prypyniennia." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Dazvolić prahramam pieraškadžać sistemie apracoŭvać klavišu hibiernacyi" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " +"apracoŭvać klavišu hibiernacyi." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Dazvolić prahramam pieraškadžać sistemie apracoŭvać zakryccio kryški noŭtbuka" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia dazvolu prahramam pieraškadžać sistemie " +"apracoŭvać zakryccio kryški noŭtbuka." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in user to run programs" +msgstr "" +"Dazvolić karystaĺniku, jakija jašče nie ŭvajšoŭ u sistemu, vykonvać prahramy" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Nieabchodny vidavočny zapyt dlia vykanannia prahram karystaĺnika, jaki jašče " +"nie ŭvajšoŭ u sistemu." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow non-logged-in users to run programs" +msgstr "" +"Dazvolić karystaĺnikam, jakija jašče nie ŭvajšli ŭ sistemu, vykonvać prahramy" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia vykanannia prahram karystaĺnika, jaki jašče " +"nie ŭvajšoŭ u sistemu." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Allow attaching devices to seats" +msgstr "Dazvolić dalučać prylady da pracoŭnych miescaŭ" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia dalučennia prylad da pracoŭnych miescaŭ." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Flush device to seat attachments" +msgstr "Adkliučać prylady ad pracoŭnych miescaŭ" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia adkliučennia prylad ad pracoŭnych miescaŭ." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system" +msgstr "Vykliučyć sistemu" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "Authentication is required for powering off the system." +msgstr "Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while other users are logged in" +msgstr "Vykliučyć sistemu pry prysutnasci inšych karystaĺnikaŭ" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy pry prysutnasci inšych " +"karystaĺnikaŭ." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Vykliučyć sistemu, kali prahramy pieraškadžajuć hetamu" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia vykliučennia sistemy, kali prahramy " +"pieraškadžajuć hetamu." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system" +msgstr "Pierazahruzić sistemu" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "Authentication is required for rebooting the system." +msgstr "Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while other users are logged in" +msgstr "Pierazahruzić sistemu pry prysutnasci inšych karystaĺnikaŭ" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy pry prysutnasci " +"inšych karystaĺnikaŭ." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Pierazahruzić sistemu, kali prahramy pieraškadžajuć hetamu" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia pierazahruzki sistemy, kali prahramy " +"pieraškadžajuć hetamu." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system" +msgstr "Prypynić sistemu" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "Authentication is required for suspending the system." +msgstr "Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while other users are logged in" +msgstr "Prypynić sistemu pry prysutnasci inšych karystaĺnikaŭ" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy pry prysutnasci inšych " +"karystaĺnikaŭ." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Prypynić sistemu, kali prahramy pieraškadžajuć hetamu" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia prypyniennia sistemy, kali prahramy " +"pieraškadžajuć hetamu." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system" +msgstr "Hibiernavać sistemu" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "Authentication is required for hibernating the system." +msgstr "Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while other users are logged in" +msgstr "Hibiernavać sistemu pry prysutnasci inšych karystaĺnikaŭ" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy pry prysutnasci inšych " +"karystaĺnikaŭ." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Hibiernavać sistemu, kali prahramy pieraškadžajuć hetamu" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia hibiernacyi sistemy, kali prahramy " +"pieraškadžajuć hetamu." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Manage active sessions, users and seats" +msgstr "Kiravać aktyŭnymi siesijami, karystaĺnikami i pracoŭnymi miescami" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia kiravannia aktyŭnymi siesijami, " +"karystaĺnikami i miescami." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Lock or unlock active sessions" +msgstr "Blakavać abo razblakavać aktyŭnuju siesiju" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia blakiroŭki abo razblakiroŭki aktyŭnaj " +"siesii." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "Dazvolić ukazannie prašyŭcy na zahruzku interfiejsu nalad" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia ŭkazannia prašyŭcy na zahruzku interfiejsu " +"nalad." + +#: ../src/login/org.freedesktop.login1.policy.in.h:57 +msgid "Set a wall message" +msgstr "Ustaliavać usieahuĺnaje paviedamliennie" + +#: ../src/login/org.freedesktop.login1.policy.in.h:58 +msgid "Authentication is required to set a wall message" +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭsieahuĺnaha paviedamliennia" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Uvajsci ŭ lakaĺny kantejnier" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "Nieabchodna aŭtentyfikacyja dlia ŭvachodu ŭ lakaĺny kantejnier." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Uvajsci ŭ lakaĺny vuziel" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Nieabchodna aŭtentyfikacyja dlia ŭvachodu ŭ lakaĺny vuziel." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Atrymać abalonku na lakaĺnym kantejniery" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia atrymannia abalonki na lakaĺnym kantejniery." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Atrymać abalonku na lakaĺnym vuzlie" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia atrymannia abalonki na lakaĺnym vuzlie." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Atrymać psieŭda TTY na lakaĺnym kantejniery" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia atrymannia psieŭda TTY na lakaĺnym " +"kantejniery." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Atrymać psieŭda TTY na lakaĺnym vuzlie" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia atrymannia psieŭda TTY na lakaĺnym vuzlie." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Kiravać lakaĺnymi virtuaĺnymi mašynami abo kantejnierami" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia kiravannia lakaĺnymi virtuaĺnymi mašynami i " +"kantejnierami." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Kiravać vobrazami lakaĺnych virtuaĺnych mašyn i kantejnieraŭ" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia kiravannia vobrazami lakaĺnych virtuaĺnych " +"mašyn i kantejnieraŭ." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Ustaliavać sistemny čas" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha času." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Ustaliavać sistemny časavy pojas" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia sistemnaha časavoha pojasu." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Ustaliavać časavy pojas (miascovy abo UTC), u jakim RTC zachoŭvaje čas" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia časavoha pojasu (miascovy abo " +"UTC), u jakim zachoŭvajecca čas u RTC." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Ukliučyć abo vykliučyć sinchranizacyju času pa sietcy" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia ŭkliučennia abo vykliučennia sinchranizacyi " +"času pa sietcy." + +#: ../src/core/dbus-unit.c:450 +msgid "Authentication is required to start '$(unit)'." +msgstr "Nieabchodna aŭtentyfikacyja dlia zapusku '$(unit)'." + +#: ../src/core/dbus-unit.c:451 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Nieabchodna aŭtentyfikacyja dlia spyniennia '$(unit)'." + +#: ../src/core/dbus-unit.c:452 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Nieabchodna aŭtentyfikacyja dlia pieračytannia stanu '$(unit)'." + +#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Nieabchodna aŭtentyfikacyja dlia pierazapusku '$(unit)'." + +#: ../src/core/dbus-unit.c:560 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Nieabchodna aŭtentyfikacyja dlia zabojstva '$(unit)'." + +#: ../src/core/dbus-unit.c:590 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia anuliavannia pamylkovaha stanu '$(unit)'." + +#: ../src/core/dbus-unit.c:622 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "" +"Nieabchodna aŭtentyfikacyja dlia ŭstaliavannia ŭlascivasciej '$(unit)'." diff --git a/po/bg.po b/po/bg.po new file mode 100644 index 00000000..98edfc5f --- /dev/null +++ b/po/bg.po @@ -0,0 +1,618 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Bulgarian translation of systemd po-file. +# Copyright © 2016 Alexander Shopov +# Alexander Shopov , 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-05-14 13:28+0300\n" +"PO-Revision-Date: 2016-05-14 13:28+0300\n" +"Last-Translator: Alexander Shopov \n" +"Language-Team: Bulgarian \n" +"Language: bg\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Изпращане на паролата към системата" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "За изпращане на паролата към системата е необходима идентификация." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Управление на услугите или другите модули" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"За управление на услугите или другите модули е необходима идентификация." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Управление на файловете за услугите или другите модули" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"За управление на файловете за услугите или другите модули е необходима " +"идентификация." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Задаване или изтриване на променливи на средата за системата и управлението " +"на услугите" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"За задаване или изтриване на променливи на средата за системата и " +"управлението на услугите е необходима идентификация." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Презареждане на състоянието на systemd" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "За презареждане на състоянието на systemd е необходима идентификация." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Задаване на име на машината" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "За задаване на име на локалната машина е необходима идентификация." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Задаване на статично име на машината" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"За задаване на статично име на локалната машина е необходима идентификация." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Задаване на информация за машината" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "" +"За задаване на информация за локалната машина е необходима идентификация." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Внасяне на изображение на виртуална машина или контейнер" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"За внасяне на изображение на виртуална машина или контейнер е необходима " +"идентификация." + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Изнасяне на изображение на виртуална машина или контейнер" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"За изнасяне на изображение на виртуална машина или контейнер е необходима " +"идентификация." + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Изтегляне на изображение на виртуална машина или контейнер" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"За изтегляне на изображение на виртуална машина или контейнер е необходима " +"идентификация." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Задаване на локала на системата" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "За задаване на локала на системата е необходима идентификация." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Задаване на настройките на клавиатурата" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "За задаване на настройките на клавиатурата е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Позволяване на програмите да предотвратяват спирането на системата" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"За позволяване на програмите да предотвратяват спирането на системата е " +"необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Позволяване на програмите да забавят спирането на системата" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"За позволяване на програмите да забавят спирането на системата е необходима " +"идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Позволяване на програмите да предотвратяват приспиването на системата" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"За позволяване на програмите да предотвратяват приспиването на системата е " +"необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Позволяване на програмите да забавят приспиването на системата" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"За позволяване на програмите да забавят приспиването на системата е " +"необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "" +"Позволяване на програмите да предотвратяват автоматичното приспиване на " +"системата" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"За позволяване на програмите да предотвратяват автоматичното приспиване на " +"системата е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Позволяване на програмите да предотвратяват реакцията на системата при " +"натискане на клавиша за захранване" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"За позволяване на програмите да предотвратяват реакцията на системата при " +"натискане на клавиша за захранване е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Позволяване на програмите да предотвратяват реакцията на системата при " +"натискане на клавиша за приспиване" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"За позволяване на програмите да предотвратяват реакцията на системата при " +"натискане на клавиша за приспиване е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Позволяване на програмите да предотвратяват реакцията на системата при " +"натискане на клавиша за дълбоко приспиване" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"За позволяване на програмите да предотвратяват реакцията на системата при " +"натискане на клавиша за дълбоко приспиване е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Позволяване на програмите да предотвратяват реакцията на системата при " +"затваряне на екрана" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"За позволяване на програмите да предотвратяват реакцията на системата при " +"затваряне на екрана е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in user to run programs" +msgstr "" +"Позволяване на потребители, които не са се идентифицирали, да изпълняват " +"програми" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"За позволяване на потребители, които не са се идентифицирали, да изпълняват " +"програми е необходима изрична заявка." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow non-logged-in users to run programs" +msgstr "" +"Позволяване на потребители, които не са се идентифицирали, да изпълняват " +"програми" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"За позволяване на потребители, които не са се идентифицирали, да изпълняват " +"програми е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Allow attaching devices to seats" +msgstr "Позволяване на закачане на устройства към работните места" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"За позволяване на закачане на устройства към работните места е необходима " +"идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Flush device to seat attachments" +msgstr "Изчистване на връзките между устройствата и работните места" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"За изчистване на връзките между устройствата и работните места е необходима " +"идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system" +msgstr "Изключване на системата" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "Authentication is required for powering off the system." +msgstr "За изключване на системата е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while other users are logged in" +msgstr "Изключване на системата, дори когато има други вписани потребители" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"За изключване на системата, дори когато има други вписани потребители, е " +"необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Изключване на системата, дори когато програма иска да предотврати това" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"За изключване на системата, дори когато програма иска да предотврати това, е " +"необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system" +msgstr "Рестартиране на системата" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "Authentication is required for rebooting the system." +msgstr "За рестартиране на системата е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while other users are logged in" +msgstr "Рестартиране на системата, дори когато има други вписани потребители" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"За рестартиране на системата, дори когато има други вписани потребители, е " +"необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "" +"Рестартиране на системата, дори когато програма иска да предотврати това" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"За рестартиране на системата, дори когато програма иска да предотврати това, " +"е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system" +msgstr "Приспиване на системата" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "Authentication is required for suspending the system." +msgstr "За приспиване на системата е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while other users are logged in" +msgstr "Приспиване на системата, дори когато има други вписани потребители" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"За приспиване на системата, дори когато има други вписани потребители, е " +"необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Приспиване на системата, дори когато програма иска да предотврати това" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"За приспиване на системата, дори когато програма иска да предотврати това, е " +"необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system" +msgstr "Дълбоко приспиване на системата" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "Authentication is required for hibernating the system." +msgstr "За дълбоко приспиване на системата е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while other users are logged in" +msgstr "" +"Дълбоко приспиване на системата, дори когато има други вписани потребители" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"За дълбоко приспиване на системата, дори когато има други вписани " +"потребители, е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "" +"Дълбоко приспиване на системата, дори когато програма иска да предотврати " +"това" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"За дълбоко приспиване на системата, дори когато програма иска да предотврати " +"това, е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Manage active sessions, users and seats" +msgstr "Управление на работещите сесии, потребители и работни места" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"За управление на работещите сесии, потребители и работни места е необходима " +"идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Lock or unlock active sessions" +msgstr "Заключване или отключване на работещите сесии" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"За заключване или отключване на работещите сесии е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "" +"Позволяване на заявки към фърмуера да стартира с интерфейса за управление" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"За позволяване на заявки към фърмуера да стартира с интерфейса за управление " +"е необходима идентификация." + +#: ../src/login/org.freedesktop.login1.policy.in.h:57 +msgid "Set a wall message" +msgstr "Задаване на системно съобщение „wall“" + +#: ../src/login/org.freedesktop.login1.policy.in.h:58 +msgid "Authentication is required to set a wall message" +msgstr "За задаване на системно съобщение „wall“ е необходима идентификация." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Вписване в локален контейнер" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "За вписване в локален контейнер е необходима идентификация." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Вписване в локалната машина" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "За вписване в локалната машина е необходима идентификация." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Достъп до обвивка в локален контейнер" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "За достъп до обвивка в локален контейнер е необходима идентификация." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Достъп до обвивка на локалната машина" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "За достъп до обвивка на локалната машина е необходима идентификация." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Получаване на псевдо терминал в локален контейнер" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"За получаване на псевдо терминал в локален контейнер е необходима " +"идентификация." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Получаване на псевдо терминал на локалната машина" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"За получаване на псевдо терминал на локалната машина е необходима " +"идентификация." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Управление на локалните виртуални машини и контейнери" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"За управление на локалните виртуални машини и контейнери е необходима " +"идентификация." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Управление на изображения на виртуални машини или контейнери" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"За управление на изображения на виртуални машини или е необходима " +"идентификация." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Задаване на времето на системата" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "За задаване на времето на системата е необходима идентификация." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Задаване на часовия пояс на системата" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "За задаване на часовия пояс на системата е необходима идентификация." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Превключване на системния часовник между местния часови пояс и UTC" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"За превключване на системния часовник между местния часови пояс и UTC е " +"необходима идентификация." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Превключване на синхронизацията на времето по мрежата" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"За превключване на синхронизацията на времето по мрежата е необходима " +"идентификация." + +#: ../src/core/dbus-unit.c:450 +msgid "Authentication is required to start '$(unit)'." +msgstr "За стартиране на „$(unit)“ е необходима идентификация." + +#: ../src/core/dbus-unit.c:451 +msgid "Authentication is required to stop '$(unit)'." +msgstr "За спиране на „$(unit)“ е необходима идентификация." + +#: ../src/core/dbus-unit.c:452 +msgid "Authentication is required to reload '$(unit)'." +msgstr "За презареждане на „$(unit)“ е необходима идентификация." + +#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 +msgid "Authentication is required to restart '$(unit)'." +msgstr "За рестартиране на „$(unit)“ е необходима идентификация." + +#: ../src/core/dbus-unit.c:560 +msgid "Authentication is required to kill '$(unit)'." +msgstr "За убиване на „$(unit)“ е необходима идентификация." + +#: ../src/core/dbus-unit.c:590 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"За премахване на състоянието за неуспех на „$(unit)“ е необходима " +"идентификация." + +#: ../src/core/dbus-unit.c:622 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "За задаване на свойствата на „$(unit)“ е необходима идентификация." diff --git a/po/ca.po b/po/ca.po new file mode 100644 index 00000000..4a3e221d --- /dev/null +++ b/po/ca.po @@ -0,0 +1,667 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Catalan translation for systemd. +# Walter Garcia-Fontes , 2016. +# Robert Antoni Buj Gelonch , 2018. #zanata +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-02-19 13:32+0100\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: 2018-02-27 04:18-0500\n" +"Last-Translator: Robert Antoni Buj Gelonch \n" +"Language-Team: Català \n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Zanata 3.9.6\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Retorna la frase de pas al sistema" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +"" +msgstr "" +"Es requereix autenticació per retornar la frase de pas introduïda al sistema." +"" + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Gestiona els serveis del sistema o bé altres unitats." + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Es requereix autenticació per gestionar els serveis del sistema o bé altres " +"unitats." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Gestiona el servei del sistema o bé fitxers d'unitats" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Es requereix autenticació per gestionar un servei del sistema o bé fitxers " +"d'unitats." + +#: src/core/org.freedesktop.systemd1.policy.in:53 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Estableix o desestableix les variables d'entorn del gestor de serveis o del " +"sistema" + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Es requereix autenticació per establir o desestablir les variables d'entorn " +"del gestor de serveis o del sistema." + +#: src/core/org.freedesktop.systemd1.policy.in:63 +msgid "Reload the systemd state" +msgstr "Torna a carregar l'estat de systemd" + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Authentication is required to reload the systemd state." +msgstr "Es requereix autenticació per tornar a carregar l'estat de systemd." + +#: src/hostname/org.freedesktop.hostname1.policy:22 +msgid "Set host name" +msgstr "Estableix el nom d'amfitrió" + +#: src/hostname/org.freedesktop.hostname1.policy:23 +msgid "Authentication is required to set the local host name." +msgstr "Es requereix autenticació per establir el nom d'amfitrió local." + +#: src/hostname/org.freedesktop.hostname1.policy:32 +msgid "Set static host name" +msgstr "Estableix el nom d'amfitrió estàtic" + +#: src/hostname/org.freedesktop.hostname1.policy:33 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Es requereix autenticació per establir el nom d'amfitrió local configurat " +"estàticament, així com el nom bonic d'amfitrió." + +#: src/hostname/org.freedesktop.hostname1.policy:43 +msgid "Set machine information" +msgstr "Estableix la informació de la màquina" + +#: src/hostname/org.freedesktop.hostname1.policy:44 +msgid "Authentication is required to set local machine information." +msgstr "" +"Es requereix autenticació per establir la informació de la màquina local." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Importa una màquina virtual o una imatge de contenidor" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Es requereix autenticació per importar una màquina virtual o una imatge de " +"contenidor" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Exporta una màquina virtual o una imatge de contenidor" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Es requereix autenticació per exportar una màquina virtual o una imatge de " +"contenidor" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Baixa una màquina virtual o una imatge de contenidor" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Es requereix autenticació per baixar una màquina virtual o una imatge de " +"contenidor" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Estableix la configuració regional del sistema" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "" +"Es requereix autenticació per establir la configuració regional del sistema." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Estableix els ajusts del teclat del sistema" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Es requereix autenticació per establir els ajusts del teclat del sistema." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Permet a les aplicacions inhibir l'apagada del sistema" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Es requereix autenticació perquè una aplicació inhibeixi l'apagada del " +"sistema." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Permet a les aplicacions endarrerir l'apagada del sistema" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "" +"Authentication is required for an application to delay system shutdown." +msgstr "" +"Es requereix autenticació perquè una aplicació endarrereixi l'apagada del " +"sistema." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Permet a les aplicacions inhibir el repòs del sistema" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Es requereix autenticació perquè una aplicació inhibeixi el repòs del " +"sistema." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Permet a les aplicacions endarrerir el repòs del sistema" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Es requereix autenticació perquè una aplicació endarrereixi el repòs del " +"sistema." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Permet a les aplicacions inhibir la suspensió automàtica del sistema" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Es requereix autenticació perquè una aplicació inhibeixi la suspensió " +"automàtica del sistema." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Permet a les aplicacions inhibir la gestió de la tecla d'encesa per part del " +"sistema" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Es requereix autenticació perquè una aplicació inhibeixi la gestió de la " +"tecla d'encesa per part del sistema." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Permet a les aplicacions inhibir la tecla de suspensió per part del sistema" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Es requereix autenticació perquè una aplicació inhibeixi la gestió de la " +"tecla de suspensió per part del sistema." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Permet a les aplicacions inhibir la gestió de la tecla d'hibernació per part " +"del sistema" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Es requereix autenticació perquè una aplicació inhibeixi la gestió de la " +"tecla d'hibernació per part del sistema." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Permet a les aplicacions la gestió del tancament de la tapa per part del " +"sistema" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Es requereix autenticació perquè una aplicació inhibeixi la gestió del " +"tancament de la tapa per part del sistema." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "Permet a l'usuari sense inici de sessió executar programes" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Es requereix una sol·licitud explícita per executar programes com a usuari " +"sense inici de sessió." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "Permet als usuaris sense inici de sessió executar programes" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Es requereix una sol·licitud explícita per executar programes com a usuari " +"sense inici de sessió." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Permet l'annexió de dispositius als llocs de treball" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Es requereix autenticació per annexar un dispositiu a un lloc de treball." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Allibera els dispositius a les annexions dels llocs de treball" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Es requereix autenticació per restablir com s'annexionen els dispositius als " +"llocs de treball." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Apaga el sistema" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "Es requereix autenticació per apagar el sistema." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "Apaga el sistema mentre hi ha altres usuaris amb la sessió iniciada" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Es requereix autenticació per apagar el sistema mentre hi ha altres usuaris " +"amb la sessió iniciada." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Apaga el sistema mentre hi ha una aplicació que ha demanat inhibir-ho" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Es requereix autenticació per apagar el sistema mentre hi ha una aplicació " +"que ha demanat inhibir-ho." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Reinicia el sistema" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "Es requereix autenticació per reiniciar el sistema." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "Reinicia el sistema mentre hi ha usuaris amb la sessió iniciada" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Es requereix autenticació per reiniciar el sistema mentre hi ha usuaris amb " +"la sessió iniciada." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "" +"Reinicia el sistema mentre hi ha una aplicació que ha demanat inhibir-ho" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Es requereix autenticació per reiniciar el sistema mentre hi ha una " +"aplicació que ha demanat inhibir-ho." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Atura el sistema" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "Es requereix autenticació per aturar el sistema." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "Atura el sistema mentre hi ha altres usuaris amb la sessió iniciada" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Es requereix autenticació per aturar el sistema mentre hi ha altres usuaris " +"amb la sessió iniciada." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "" +"Atura el sistema mentre hi ha una aplicació que ha demanat d'inhibir-ho" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Es requereix autenticació per aturar el sistema mentre hi ha una aplicació " +"que ha demanat d'inhibir-ho." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Suspèn el sistema" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "Es requereix autenticació per suspendre el sistema." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "Suspèn el sistema mentre hi ha altres usuaris amb la sessió iniciada" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Es requereix autenticació per reiniciar el sistema mentre hi ha altres " +"usuaris amb la sessió iniciada." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "" +"Suspèn el sistema mentre hi ha una aplicació que ha demanat d'inhibir-ho" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Es requereix autenticació per suspendre el sistema mentre hi ha una " +"aplicació que ha demanat d'inhibir-ho." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Hiberna el sistema" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "Es requereix autenticació per hibernar el sistema." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "Hiberna el sistema mentre hi ha altres usuaris amb la sessió iniciada" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Es requereix autenticació per hibernar el sistema mentre hi ha altres " +"usuaris amb la sessió iniciada." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "" +"Hiberna el sistema mentre hi ha una aplicació que ha demanat d'inhibir-ho" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Es requereix autenticació per hibernar el sistema mentre hi ha una aplicació " +"que ha demanat d'inhibir-ho." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Gestiona les sessions, usuaris i llocs de treball actius" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Es requereix autenticació per gestionar les sessions, usuaris i llocs de " +"treball actius." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Bloqueja o desbloqueja les sessions actives" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Es requereix autenticació per bloquejar o desbloquejar les sessions actives." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "" +"Permet la indicació al microprogramari en l'arrencada perquè prepari la " +"interfície" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Es requereix autenticació per indicar al microprogramari en l'arrencada " +"perquè prepari la interfície." + +#: src/login/org.freedesktop.login1.policy:351 +msgid "Set a wall message" +msgstr "Estableix un missatge de mur" + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Authentication is required to set a wall message" +msgstr "Es requereix autenticació per establir un missatge de mur" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Inicia la sessió a un contenidor local" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "" +"Es requereix autenticació per iniciar la sessió a un contenidor local." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Inicia la sessió a l'amfitrió local" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "Es requereix autenticació per iniciar la sessió a l'amfitrió local." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Adquireix un shell en un contenidor local" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Es requereix autenticació per adquirir un shell en un contenidor local." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Adquireix un shell a l'amfitrió local" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Es requereix autenticació per adquirir un shell a l'amfitrió local." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Adquireix un pseudo TTY en un contenidor local" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Es requereix autenticació per adquirir un pseudo TTY en un contenidor local." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Adquireix un pseudo TTY a l'amfitrió local" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Es requereix autenticació per adquirir un pseudo TTY a l'amfitrió local." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Gestiona les màquines virtuals i els contenidors locals " + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Es requereix autenticació per gestionar les màquines virtuals i els " +"contenidors locals." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Gestiona les màquines virtuals i les imatges dels contenidors locals" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Es requereix autenticació per gestionar les màquines virtuals i les imatges " +"dels contenidors locals." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Registra un servei DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Es requereix autenticació per registrar un servei DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Desregistra un servei DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "Es requereix autenticació per desregistrar un servei DNS-SD" + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Estableix l'hora del sistema" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "Es requereix autenticació per establir l'hora del sistema." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Estableix la zona horària del sistema" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "Es requereix autenticació per establir la zona horària del sistema." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "Estableix el rellotge del sistema a la zona horària local o de l'UTC" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Es requereix autenticació per controlar si el rellotge del sistema " +"emmagatzema l'hora local o l'UTC." + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "Turn network time synchronization on or off" +msgstr "Activa o desactiva la sincronització de l'hora de xarxa" + +#: src/timedate/org.freedesktop.timedate1.policy:55 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Es requereix autenticació per controlar si s'ha d'activar la sincronització " +"de l'hora de xarxa." + +#: src/core/dbus-unit.c:496 +msgid "Authentication is required to start '$(unit)'." +msgstr "Es requereix autenticació per iniciar «$(unit)»." + +#: src/core/dbus-unit.c:497 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Es requereix autenticació per aturar «$(unit)»." + +#: src/core/dbus-unit.c:498 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Es requereix autenticació per tornar a carregar «$(unit)»." + +#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Es requereix autenticació per reiniciar «$(unit)»." + +#: src/core/dbus-unit.c:607 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Es requereix autenticació per matar «$(unit)»." + +#: src/core/dbus-unit.c:638 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Es requereix autenticació per restablir l'estat «failed» de «$(unit)»." + +#: src/core/dbus-unit.c:671 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Es requereix autenticació per establir les propietats a «$(unit)»." + diff --git a/po/cs.po b/po/cs.po new file mode 100644 index 00000000..985be305 --- /dev/null +++ b/po/cs.po @@ -0,0 +1,812 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Czech translation for systemd. +# Daniel Maixner , 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2019-09-17 14:31+0000\n" +"PO-Revision-Date: 2019-09-19 15:48+0200\n" +"Last-Translator: Daniel Rusek \n" +"Language-Team: Czech\n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 2.2.3\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Odeslat heslo zpět do systému" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "Pro odeslání zadaného hesla do systému je vyžadováno ověření." + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Spravovat systémové služby nebo další jednotky" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Pro správu systémových služeb nebo dalších jednotek je vyžadováno ověření." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Spravovat systémové služby nebo soubory jednotek" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Pro správu systémových služeb nebo souborů jednotek je vyžadováno ověření." + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "Nastavit nebo rušit proměnné správce systému a služeb" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Pro nastavení nebo rušení proměnných správce systému a služeb je vyžadováno " +"ověření." + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "Znovu načíst stav systemd" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "Pro znovu načtení stavu systemd je vyžadováno ověření." + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "Nastavit název stroje" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "Pro nastavení lokálního názvu stroje je vyžadováno ověření." + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "Nastavit statický název stroje" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Pro nastavení staticky konfigurovaného názvu lokálního stroje, stejně tak " +"pro změnu uživatelsky přívětivého jména je vyžadováno ověření." + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "Nastavit informace o stroji" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "Pro nastavení informací o stroji je vyžadováno ověření." + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "Získat UUID produktu" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "Pro získání UUID produktu je vyžadováno ověření." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Importovat obraz virtuální stroje nebo kontejneru" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Pro import obrazu virtuálního stroje nebo kontejneru je vyžadováno ověření" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Exportovat obraz virtuálního stroje nebo kontejneru" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Pro export obrazu virtuálního stroje nebo kontejneru je vyžadováno ověření" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Stáhnout obraz virtuálního stroje nebo kontejneru" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Pro stažení obrazu virtuálního stroje nebo kontejneru je vyžadováno ověření" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Nastavit lokalizaci systému" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "Pro nastavení lokalizace systému je vyžadováno ověření." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Nastavit systémovou konfiguraci klávesnice" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "Pro nastavení systémové konfigurace klávesnice je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Povolit aplikacím zakázat vypnutí systému" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "Pro povolení aplikacím zakázat vypnutí systému je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Povolit aplikacím odložit vypnutí systému" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "Pro povolení aplikacím odložit vypnutí systému je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Povolit aplikacím zakázat uspání systému" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "Pro povolení aplikacím zakázat uspání systému je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Povolit aplikacím odložit uspání systému" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "Pro povolení aplikacím odložit uspání systému je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Povolit aplikacím zakázat automatické vypnutí systému" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Pro povolení aplikacím zakázat automatické vypnutí systému je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Povolit aplikacím zakázat chovaní systému na stisknutí vypínacího tlačítka" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Pro povolení aplikacím zakázat chovaní systému na stisknutí vypínacího " +"tlačítka je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Povolit aplikacím zakázat chovaní systému na stisknutí uspávacího tlačítka" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Pro povolení aplikacím zakázat chovaní systému na stisknutí uspávacího " +"tlačítka je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Povolit aplikacím zakázat chovaní systému na stisknutí tlačítka hibernace" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Pro povolení aplikacím zakázat chovaní systému na stisknutí tlačítka " +"hibernace je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "Povolit aplikacím zakázat chovaní systému na zavření víka" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Pro povolení aplikacím zakázat chovaní systému na zavření víka je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "Povolit nepřihlášenému uživateli spouštět programy" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Ke spuštění programů jako nepřihlášený uživatel je třeba speciální požadavek." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "Povolit nepřihlášeným uživatelům spouštět programy" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "Ke spuštění programů jako nepřihlášený uživatel je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Povolit připojování zařízení ke stanovištím" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "Pro připojování zařízení ke stanovišti je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Odstranit přiřazení zařízení ke stanovištím" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Pro reset způsobu jak jsou zařízení přiřazována ke stanovištím je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Vypnout systém" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "Pro vypnutí systému je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "Vypnout systém, i když jsou přihlášeni další uživatelé" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Pro vypnutí systému, když jsou přihlášeni další uživatelé je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Vypnout systém, i když aplikace požádala o zákaz vypnutí" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Pro vypnutí systému, když aplikace požádala o zákaz vypnutí je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Restartovat systém" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "Pro restartování systému je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "Restartovat systém, i když jsou přihlášeni další uživatelé" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Pro restartování systému, když jsou přihlášeni další uživatelé je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Restartovat systém, i když aplikace požádala o zákaz restartu" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Pro restartování systému, když aplikace požádala o zákaz restartu je " +"vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Zastavit systém" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "Pro zastavení systému je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "Zastavit systém, i když jsou přihlášeni další uživatelé" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Pro zastavení systému, když jsou přihlášeni další uživatelé je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Zastavit systém, i když aplikace požádala o zákaz zastavení" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Pro zastavení systému, když aplikace požádala o zákaz zastavení je " +"vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Uspat systém" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "Pro uspání systému je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "Uspat systém, i když jsou přihlášeni další uživatelé" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Pro uspání systému, když jsou přihlášeni další uživatelé je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Uspat systém, i když aplikace požádala o zákaz uspání" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Pro uspání systému, když aplikace požádala o zákaz uspání je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Hibernovat systém" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "Pro hibernaci systému je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "Hibernovat systém, i když jsou přihlášeni další uživatelé" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Pro hibernaci systému, když jsou přihlášeni další uživatelé je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Hibernovat systém, i když aplikace požádala o zákaz hibernace" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Pro hibernaci systému, když aplikace požádala o zákaz hibernace je " +"vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Spravovat aktivní sezení, uživatele a stanoviště" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Pro správu aktivních sezení, uživatelů a stanovišť je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Zamknout nebo odemknout aktivní sezení" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "Pro zamčení nebo odemčení aktivních sezení je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Set the reboot \"reason\" in the kernel" +msgstr "Nastavit \"důvod\" rebootu v jádře" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "Authentication is required to set the reboot \"reason\" in the kernel." +msgstr "Pro nastavení \"důvodu\" rebootu v jádře je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Indicate to the firmware to boot to setup interface" +msgstr "Indikovat firmwaru, aby bootoval do instalačního prostředí" + +#: src/login/org.freedesktop.login1.policy:353 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"K indikaci firmwaru, aby bootoval do instalačního prostředí je vyžadováno " +"ověření." + +#: src/login/org.freedesktop.login1.policy:363 +msgid "Indicate to the boot loader to boot to the boot loader menu" +msgstr "Indikovat zavaděči, aby bootoval do menu zavaděče" + +#: src/login/org.freedesktop.login1.policy:364 +msgid "" +"Authentication is required to indicate to the boot loader to boot to the " +"boot loader menu." +msgstr "" +"K indikaci zavaděči, aby bootoval do menu zavaděče je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:374 +msgid "Indicate to the boot loader to boot a specific entry" +msgstr "Indikovat zavaděči, aby bootoval specifickou položku" + +#: src/login/org.freedesktop.login1.policy:375 +msgid "" +"Authentication is required to indicate to the boot loader to boot into a " +"specific boot loader entry." +msgstr "" +"K indikaci zavaděči, aby bootoval specifickou položku je vyžadováno ověření." + +#: src/login/org.freedesktop.login1.policy:385 +msgid "Set a wall message" +msgstr "Nastavit zprávu všem uživatelům" + +#: src/login/org.freedesktop.login1.policy:386 +msgid "Authentication is required to set a wall message" +msgstr "K nastavení zprávy všem uživatelům je vyžadováno ověření" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Přihlásit se do lokálního kontejneru" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "Pro přihlášení do lokálního kontejneru je vyžadováno ověření." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Přihlásit se na lokální stroj" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "Pro přihlášení k lokálnímu stroji je vyžadováno ověření." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Získat shell v lokálním kontejneru" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "Pro získání shellu v lokálním kontejneru je vyžadováno ověření." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Získat shell na lokálním stroji" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Pro získání shellu na lokálním stroji je vyžadováno ověření." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Získat pseudo TTY v lokálním kontejneru" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "Pro získání pseudo TTY v lokálním kontejneru je vyžadováno ověření." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Získat pseudo TTY na lokálním stroji" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "Pro získání pseudo TTY na lokálním stroji je vyžadováno ověření." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Spravovat lokální virtuální stroje a kontejnery" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Pro správu lokálních virtuálních strojů a kontejnerů je vyžadováno ověření." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Spravovat lokální obrazy virtuálních strojů a kontejnerů" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Pro správu obrazů lokálních virtuálních strojů a kontejnerů je vyžadováno " +"ověření." + +#: src/network/org.freedesktop.network1.policy:22 +msgid "Set NTP servers" +msgstr "Nastavit NTP servery" + +#: src/network/org.freedesktop.network1.policy:23 +msgid "Authentication is required to set NTP servers." +msgstr "Pro nastavení NTP serverů je vyžadováno ověření." + +#: src/network/org.freedesktop.network1.policy:33 +#: src/resolve/org.freedesktop.resolve1.policy:44 +msgid "Set DNS servers" +msgstr "Nastavit DNS servery" + +#: src/network/org.freedesktop.network1.policy:34 +#: src/resolve/org.freedesktop.resolve1.policy:45 +msgid "Authentication is required to set DNS servers." +msgstr "Pro nastavení DNS serverů je vyžadováno ověření." + +#: src/network/org.freedesktop.network1.policy:44 +#: src/resolve/org.freedesktop.resolve1.policy:55 +msgid "Set domains" +msgstr "Nastavit domény" + +#: src/network/org.freedesktop.network1.policy:45 +#: src/resolve/org.freedesktop.resolve1.policy:56 +msgid "Authentication is required to set domains." +msgstr "Pro nastavení domén je vyžadováno ověření." + +#: src/network/org.freedesktop.network1.policy:55 +#: src/resolve/org.freedesktop.resolve1.policy:66 +msgid "Set default route" +msgstr "Nastavit implicitní směrování" + +#: src/network/org.freedesktop.network1.policy:56 +#: src/resolve/org.freedesktop.resolve1.policy:67 +msgid "Authentication is required to set default route." +msgstr "Pro nastavení implicitního směrování je vyžadováno ověření." + +#: src/network/org.freedesktop.network1.policy:66 +#: src/resolve/org.freedesktop.resolve1.policy:77 +msgid "Enable/disable LLMNR" +msgstr "Povolit/zakázat LLMNR" + +#: src/network/org.freedesktop.network1.policy:67 +#: src/resolve/org.freedesktop.resolve1.policy:78 +msgid "Authentication is required to enable or disable LLMNR." +msgstr "Pro povolení nebo zakázání LLMNR je vyžadováno ověření." + +#: src/network/org.freedesktop.network1.policy:77 +#: src/resolve/org.freedesktop.resolve1.policy:88 +msgid "Enable/disable multicast DNS" +msgstr "Povolit/zakázat multicast DNS" + +#: src/network/org.freedesktop.network1.policy:78 +#: src/resolve/org.freedesktop.resolve1.policy:89 +msgid "Authentication is required to enable or disable multicast DNS." +msgstr "Pro povolení nebo zakázání multicast DNS je vyžadováno ověření." + +#: src/network/org.freedesktop.network1.policy:88 +#: src/resolve/org.freedesktop.resolve1.policy:99 +msgid "Enable/disable DNS over TLS" +msgstr "Povolit/zakázat DNS over TLS" + +#: src/network/org.freedesktop.network1.policy:89 +#: src/resolve/org.freedesktop.resolve1.policy:100 +msgid "Authentication is required to enable or disable DNS over TLS." +msgstr "Pro povolení nebo zakázání DNS over TLS vyžadováno ověření." + +#: src/network/org.freedesktop.network1.policy:99 +#: src/resolve/org.freedesktop.resolve1.policy:110 +msgid "Enable/disable DNSSEC" +msgstr "Povolit/zakázat DNSSEC" + +#: src/network/org.freedesktop.network1.policy:100 +#: src/resolve/org.freedesktop.resolve1.policy:111 +msgid "Authentication is required to enable or disable DNSSEC." +msgstr "Pro povolení nebo zakázání DNSSEC je vyžadováno ověření." + +#: src/network/org.freedesktop.network1.policy:110 +#: src/resolve/org.freedesktop.resolve1.policy:121 +msgid "Set DNSSEC Negative Trust Anchors" +msgstr "Nastavit DNSSEC Negative Trust Anchors" + +#: src/network/org.freedesktop.network1.policy:111 +#: src/resolve/org.freedesktop.resolve1.policy:122 +msgid "Authentication is required to set DNSSEC Negative Trust Anchors." +msgstr "Pro nastavení DNSSEC Negative Trust Anchors je vyžadováno ověření." + +#: src/network/org.freedesktop.network1.policy:121 +msgid "Revert NTP settings" +msgstr "Vrátit změny nastavení NTP" + +#: src/network/org.freedesktop.network1.policy:122 +msgid "Authentication is required to reset NTP settings." +msgstr "Pro resetování nastavení NTP je vyžadováno ověření." + +#: src/network/org.freedesktop.network1.policy:132 +msgid "Revert DNS settings" +msgstr "Vrátit změny nastavení DNS" + +#: src/network/org.freedesktop.network1.policy:133 +msgid "Authentication is required to reset DNS settings." +msgstr "Pro resetování nastavení DNS je vyžadováno ověření." + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "Prohlédnout obraz přenosné služby" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "Pro prohlížení obrazu přenosné služby je vyžadováno ověření." + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "Připojit nebo odpojit obraz přenosné služby" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "" +"Pro připojení nebo odpojení obrazu přenosné služby je vyžadováno ověření." + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "Odstranit nebo upravit obraz přenosné služby" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "" +"Pro odstranění nebo úpravu obrazu přenosné služby je vyžadováno ověření." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Registrovat službu DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Pro registraci služby DNS-SD je vyžadováno ověření" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Zrušit registraci služby DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "Pro zrušení registrace služby DNS-SD je vyžadováno ověření" + +#: src/resolve/org.freedesktop.resolve1.policy:132 +msgid "Revert name resolution settings" +msgstr "Vrátit změny nastavení překladu jmen" + +#: src/resolve/org.freedesktop.resolve1.policy:133 +msgid "Authentication is required to reset name resolution settings." +msgstr "Pro resetování nastavení překladu jmen je vyžadováno ověření." + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Nastavit systémový čas" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "Pro nastavení systémového času je vyžadováno ověření." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Nastavit systémovou časovou zónu" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "Pro nastavení systémové časové zóny je vyžadováno ověření." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "Nastavit RTC na lokální časovou zónu nebo UTC" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Pro kontrolu jestli RTC ukládá lokální časovou zónu nebo UTC čas je " +"vyžadováno ověření." + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "Zapnout nebo vypnout synchronizaci s časem ze sítě" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "Pro kontrolu synchronizace času ze sítě je vyžadováno ověření." + +#: src/core/dbus-unit.c:354 +msgid "Authentication is required to start '$(unit)'." +msgstr "Pro spuštění „$(unit)” je vyžadováno ověření." + +#: src/core/dbus-unit.c:355 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Pro vypnutí „$(unit)” je vyžadováno ověření." + +#: src/core/dbus-unit.c:356 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Pro znovu načtení „$(unit)” je vyžadováno ověření." + +#: src/core/dbus-unit.c:357 src/core/dbus-unit.c:358 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Pro restart „$(unit)” je vyžadováno ověření." + +#: src/core/dbus-unit.c:530 +msgid "" +"Authentication is required to send a UNIX signal to the processes of " +"'$(unit)'." +msgstr "Pro odeslání UNIX signálu procesům „$(unit)” je vyžadováno ověření." + +#: src/core/dbus-unit.c:561 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "Pro resetování chybného stavu „$(unit)” je vyžadováno ověření." + +#: src/core/dbus-unit.c:594 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Pro nastavení vlastností na „$(unit)” je vyžadováno ověření." + +#: src/core/dbus-unit.c:703 +msgid "" +"Authentication is required to delete files and directories associated with " +"'$(unit)'." +msgstr "" +"Pro odstranění souborů nebo adresářů souvisejících s „$(unit)” je vyžadováno " +"ověření." + +#~ msgid "Authentication is required to kill '$(unit)'." +#~ msgstr "Pro ukončení „$(unit)” je vyžadováno ověření." diff --git a/po/da.po b/po/da.po new file mode 100644 index 00000000..cc234471 --- /dev/null +++ b/po/da.po @@ -0,0 +1,609 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Danish translation for systemd. +# Daniel Machon , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2015-10-07 19:30+0000\n" +"PO-Revision-Date: 2015-10-07 19:30+0200\n" +"Last-Translator: Daniel Machon \n" +"Language-Team: Danish\n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Send adgangssætning tilbage til systemet" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Autentificering er nødvendig for at sende adgangssætning tilbage til systemet." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Håndtér system services eller andre enheder" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Autentificering er nødvendig for at håndtere system services og andre enheder." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Håndtér system services eller enhedsfiler" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Autentificering er nødvendig for at håndtere system service eller enhedsfiler." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Sæt eller fjern system- og service-forvalter miljøvariabler" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "Autentificering er nødvendig for at sætte eller fjerne system- " +"og service-forvalter miljøvariabler." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Genindlæs systemd tilstand" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Autentificering er nødvendig for at genindlæse systemd tilstanden." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Sæt værtsnavn" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Autentificering er nødvendig for at sætte værtsnavn." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Sæt statisk værstnavn" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Autentificering er nødvendig for at sætte det statisk konfigurerede lokale " +"værtsnavn, lige så vel som det pæne værtsnavn." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Sæt maskininformation." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "Autentificering er nødvendig for at sætte lokal maskininformation." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Importér en VM eller container billede" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Autentificering er nødvendig for at importére en VM eller " +"container billeder." + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Exportér en VM eller container billede" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "Autentificering er nødvendig for at exportére en VM eller container billede" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Hent en VM eller container billede" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "Autentificering er nødvendig for at hente en VM eller container billede" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Sæt sprogindstillinger for systemet" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "" +"Autentificering er nødvendig for at sætte sprogindstillinger " +"for systemet." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Sæt tastaturindstillinger for systemet." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Autentificering er nødvendig for at sætte tastaturindstillinger " +"for systemet." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Tillad applikationer at hæmme system nedlukning" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Autentificering er nødvendig for at en applikation kan hæmme " +"system nedlukning." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Tillad applikationer at forsinke system nedlukning" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Autentificering er nødvendig for at en applikation kan forsinke " +"system nedlukning." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Tillad applikationer at hæmme system dvale" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep" +msgstr "Autentificering er nødvendig for at en applikation kan hæmme system dvale" + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Tillad applikationer at forsinke system dvale" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Autentificering er nødvendig for at en applikation kan forsinke system " +"dvale." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Tillad applikationer at hæmme automatisk system standby" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Autentificering er nødvendig for at en applikation kan hæmme automatisk " +"system standby." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "Tillad applikationer at hæmme systemhåndtering af tænd/sluk-knappen" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering " +"af tænd/sluk-knappen." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "Tillad applikationer at hæmme systemhåndtering af standby-knappen" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering " +"af standby-knappen." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "Tillad applikationer at hæmme systemhåndtering af dvale-knappen" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Autentificering er nødvendig for at en applikation kan hæmme " +"systemhåndtering af dvale-knappen." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Tillad applikationer at hæmme systemhåndtering af skærmlukning" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Autentificering er nødvendig for at en applikation kan hæmme systemhåndtering " +"af skærmlukning." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in users to run programs" +msgstr "Tillad brugere der ikke er logget ind, at køre programmer" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Autentificering er nødvendig for at brugere, som ikke er logget ind, kan " +"køre programmer." + +# www.freedesktop.org/wiki/Software/systemd/multiseat/ +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow attaching devices to seats" +msgstr "Tillad at montere af enheder til arbejdsstationer" + +# www.freedesktop.org/wiki/Software/systemd/multiseat/ +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Autentificering er nødvendig for at montere en enhed til en " +"arbejdsstation." + +# www.freedesktop.org/wiki/Software/systemd/multiseat/ +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Flush device to seat attachments" +msgstr "Nulstil enhed monteret til en arbejdsstation" + +# www.freedesktop.org/wiki/Software/systemd/multiseat/ +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Autentificering er nødvendig for at nulstille måden enheder er monteret " +"arbejdsstationer." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Power off the system" +msgstr "Sluk for systemet" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "Authentication is required for powering off the system." +msgstr "Autentificering er nødvendig for at slukke systemet" + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system while other users are logged in" +msgstr "Sluk systemet mens andre brugere er logget på" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Autentificering er nødvendig for at slukke systemet mens andre brugere " +"er logget på." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while an application asked to inhibit it" +msgstr "" +"Sluk for systemet mens en applikation har forespurgt at hæmme det" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Autentificering er nødvendig for at slukke systemet mens en applikation har " +"forespurgt at hæmme det." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Reboot the system" +msgstr "Genstart systemet" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "Authentication is required for rebooting the system." +msgstr "Autentificering er nødvendig for at genstarte systemet." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system while other users are logged in" +msgstr "Genstart systemet mens andre brugere er logget ind" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Autentificering er nødvendig for at genstarte systemet mens andre brugere " +"er logget ind." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "" +"Genstart systemet mens en applikation har forespurgt at hæmme det" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Autentificering er nødvendig for at genstarte systemet mens en applikation " +"har forespurgt at hæmme det." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Suspend the system" +msgstr "Sæt systemet på standby" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "Authentication is required for suspending the system." +msgstr "Autentificering er nødvendig for at sætte systemet på standby" + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system while other users are logged in" +msgstr "Sæt systemet på standby mens andre brugere er logget på" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Autentificering er nødvendig for at sætte systemet på standby, mens andre " +"brugere er logget på." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "" +"Sæt systemet på standby mens en applikation har forespurgt at hæmme" +"det" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Autentificering er nødvendig for at sætte systemet på standby, mens en " +"applikation har forespurgt at hæmme det." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Hibernate the system" +msgstr "Sæt systemet i dvale" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "Authentication is required for hibernating the system." +msgstr "" +"Autentificering er nødvendig for at sætte systemet i dvale-tilstand." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system while other users are logged in" +msgstr "" +"Sæt systemet i dvale-tilstand mens andre brugere er logget på" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Autentificering er nødvendig for at sætte systemet i dvale-tilstand, mens " +"andre brugere er logget på." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Sæt systemet i dvale-tilstand mens en applikation har forespurgt at " +"hæmme det" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Autentificering er nødvendig for at sætte systemet i dvale tilstand, mens " +"en applikation har forespurgt at hæmme det." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Manage active sessions, users and seats" +msgstr "Håndtér aktive sessioner, brugere og arbejdsstationer" + +# www.freedesktop.org/wiki/Software/systemd/multiseat/ +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Autentificering er nødvendig for at håndtere aktive sessioner, brugere " +"og arbejdsstationer." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Lock or unlock active sessions" +msgstr "Lås eller oplås aktive sessioner" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Autentificering er nødvendig for at låse eller oplåse aktive sessioner." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "Tillad meddelelse til firmwaren om at starte op i opsætningsgrænseflade" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "Autentificering er nødvendig for at meddele firmwaren om at starte " +"op i opsætningsgrænseflade." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Set a wall message" +msgstr "Sæt broadcast-besked" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "Authentication is required to set a wall message" +msgstr "Autentificering er nødvendig for at sætte en broadcast-besked" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Log på en lokal container" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "Autentificering er nødvendig for at logge på en lokal container." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Log på den lokale vært" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Auitentificering er nødvendig for at logge på den lokale vært." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Anskaf en shell i en lokal container" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Autentificering er nødvendig for at anskaffe en shell i en lokal " +"container." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Anskaf en shell på den lokale vært" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Autentificering er nødvendig for at anskaffe en shell på den lokale vært." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Anskaf en pseudo-TTY i en lokal container" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Autentificering er nødvendig for at anskaffe en pseudo-TTY i en lokal " +"container." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Anskaf en pseudo-TTY på den lokale vært" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Autentificering er nødvendig for at anskaffe en pseudo-TTY på den " +"lokale vært." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Håndtér lokale virtuelle maskiner og containere" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Autentificering er nødvendig for at håndtere lokale virtuelle maskiner og " +"containere." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Håndtér lokal virtuel maskine- og container billeder" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Autentificering er nødvendig for at håndtere lokal virtuel maskine- og " +"container billeder." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Sæt tiden for systemet" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Autentificering er nødvendig for at sætte tiden for systemet." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Sæt tidszone for systemet" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "Autentificering er nødvendig for at sætte tidszonen for systemet." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Sæt RTC til lokal tidszone eller UTC" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Autentificering er nødvendig for at kontrollere hvorvidt RTC'en gemmer " +"den lokale tid eller UTC tid." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Slå synkronisering af netværkstid til eller fra" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Autentificering er nødvendig for at kontrollere hvorvidt synkronisering af " +"netværkstid skal aktiveres" + +#: ../src/core/dbus-unit.c:428 +msgid "Authentication is required to start '$(unit)'." +msgstr "Autentificering er nødvendig for at starte '$(unit)'." + +#: ../src/core/dbus-unit.c:429 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Autentificering er nødvendig for at stoppe '$(unit)'." + +#: ../src/core/dbus-unit.c:430 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Autentificering er nødvendig for at genindlæse '$(unit)'." + +#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Autentificering at nødvendig for at genstarte '$(unit)'." + +#: ../src/core/dbus-unit.c:535 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Autentificering er nødvendig for at eliminere '$(unit)'." + +#: ../src/core/dbus-unit.c:565 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Autentificering er nødvendig for at nulstille \"fejl\" tilstanden på '$(unit)'." + +#: ../src/core/dbus-unit.c:597 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "" +"Autentificering er nødvendig for at sætte egenskaber på '$(unit)'." + +#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" +#~ msgstr "" +#~ "Tryk Ctrl-C for at annulere alle igangværende kontrolleringer af " +#~ "filsystemet" + +#~ msgid "Checking in progress on %d disk (%3.1f%% complete)" +#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" +#~ msgstr[0] "Igangværende kontrollering på %d disk (%3.1f%% færdig)" +#~ msgstr[1] "Igangværende kontrollering på %d diske (%3.1f%% færdig)" diff --git a/po/de.po b/po/de.po new file mode 100644 index 00000000..eb3423c2 --- /dev/null +++ b/po/de.po @@ -0,0 +1,633 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# German translation for systemd. +# Christian Kirbach , 2014, 2015. +# Benjamin Steinwender , 2014. +# Bernd Homuth , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2015-09-19 12:09+0000\n" +"PO-Revision-Date: 2015-09-19 20:02+0200\n" +"Last-Translator: Bernd Homuth \n" +"Language-Team: Deutsch \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Gtranslator 2.91.6\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Passphrase zurück an das System senden" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Legitimierung ist zum Senden des eingegebenen Kennworts zurück an das System " +"notwendig." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Systemdienste und andere Einheiten verwalten" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Legitimierung ist notwendig für die Verwaltung von Systemdiensten und " +"anderen Einheiten." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Systemdienste und Einheitendateien verwalten" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Legitimierung ist notwendig für die Verwaltung von Systemdiensten und " +"Einheitendateien." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Umgebungsvariablen der System- und Dienstverwaltung festlegen oder entfernen" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "Legitimierung ist notwendig für die System- und Dienstverwaltung." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Den systemd-Zustand neu laden" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Legitimierung ist zum erneuten Laden des systemd-Zustands notwendig." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Rechnername festlegen" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Legitimierung ist zum Festlegen des lokalen Rechnernamens notwendig" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Statischen Rechnernamen festlegen" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Authentifizierung ist erforderlich, um den statisch geänderten, lokalen " +"Rechnernamen, sowie den beschönigten Rechnernamen festzulegen." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Maschinen-Information festlegen" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "" +"Legitimierung ist zum Festlegen der lokalen Maschinen-Information " +"erforderlich." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Abbild einer VM oder eines Containers importieren" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Legitimierung ist zum Importieren eines VM- oder Containerabbilds " +"erforderlich" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Abbild einer VM oder eines Containers exportieren" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Legitimierung ist zum Exportieren eines VM- oder Containerabbilds " +"erforderlich" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Abbild einer VM oder eines Containers herunterladen" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Legitimierung ist zum Herunterladen eines VM- oder Containerabbilds " +"erforderlich" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Die lokale Sprachumgebung festlegen" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "" +"Legitimierung ist zum Festlegen der systemweiten Spracheinstellungen " +"erforderlich." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Tastatureinstellungen des Systems festlegen" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Legitimierung ist zum Festlegen der Tastatureinstellungen des Systems " +"erforderlich." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Anwendungen dürfen das Herunterfahren des Systems unterbinden" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Legitimierung ist notwendig, um Anwendungen das Herunterfahren des Systems " +"zu erlauben." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Anwendungen dürfen das Herunterfahren des Systems verzögern" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Legitimierung ist notwendig, um Anwendungen das Verzögern des Herunterfahren " +"des Systems zu erlauben." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Anwendungen dürfen den Bereitschaftsmodus unterbinden" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Legitimierung ist erforderlich, um Anwendungen das Unterbinden des " +"Bereitschaftsmodus zu erlauben." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Anwendungen dürfen den Bereitschaftsmodus verzögern" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Legitimierung ist erforderlich, um Anwendungen das Verzögern des " +"Bereitschaftsmodus zu erlauben." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Anwendungen dürfen den automatischen Bereitschaftsmodus unterbinden" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Legitimierung ist notwendig, um Anwendungen das Unterbinden des " +"automatischen Bereitschaftsmodus zu erlauben." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Anwendungen dürfen das Auswerten des Ein-/Ausschaltknopfs des Systems " +"unterbinden" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Legitmierung ist erforderlich, um Anwendungen das Unterbinden der Auswertung " +"der Ein-/Ausschaltknopfs des Systems zu erlauben." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Anwendungen dürfen das Auswerten des Bereitschaftsknopfs des Systems " +"unterbinden" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Legitimierung ist erforderlich, um Anwendungen das Unterbinden der " +"Auswertung des Bereitschaftsknopfes des Systems zu erlauben." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Anwendungen dürfen das Auswerten des Knopfs für den Ruhezustand unterbinden" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Legitimierung ist erforderlich, um Anwendungen das Unterbinden der " +"Auswertung des Knopfs für den Ruhezustand zu erlauben." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Anwendungen dürfen das Auswerten des Notebookdeckelschalters unterbinden" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Legitimierung ist erforderlich, um Anwendungen das Unterbinden der " +"Auswertung des Notebookdeckelschalters des Systems zu erlauben." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in users to run programs" +msgstr "Nicht angemeldete Benutzer dürfen Programme ausführen" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Legitimierung ist erforderlich, damit nicht angemeldete Benutzer Programme " +"ausführen dürfen." + +# www.freedesktop.org/wiki/Software/systemd/multiseat/ +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow attaching devices to seats" +msgstr "Das Anschließen von Geräten an Arbeitsstationen erlauben" + +# www.freedesktop.org/wiki/Software/systemd/multiseat/ +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Legitimierung ist zum Anschließen eines Geräts an eine Arbeitsstation " +"notwendig." + +# www.freedesktop.org/wiki/Software/systemd/multiseat/ +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Flush device to seat attachments" +msgstr "Zurücksetzen der an eine Arbeitsstation angeschlossenen Geräte" + +# www.freedesktop.org/wiki/Software/systemd/multiseat/ +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Legitimierung ist zum Zurücksetzen notwendig, wie Geräte an eine " +"Arbeitsstation angeschlossen werden." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Power off the system" +msgstr "Das System ausschalten" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "Authentication is required for powering off the system." +msgstr "Legitimierung ist zum Ausschalten des Systems notwendig." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system while other users are logged in" +msgstr "Das System herunter fahren, während andere Benutzer angemeldet sind" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Legitimierung ist zum Herunterfahren des Systems notwendig, während andere " +"Benutzer angemeldet sind." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while an application asked to inhibit it" +msgstr "" +"Das System ausschalten, während eine Anwendung anfordert es zu unterbinden" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Legitimierung ist zum Ausschalten des Systems notwendig, während eine " +"Anwendung anfordert es zu unterbinden." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Reboot the system" +msgstr "Das System neu starten" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "Authentication is required for rebooting the system." +msgstr "Legitimierung ist zum Neustart des Systems notwendig." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system while other users are logged in" +msgstr "Das Systems neu starten, während andere Benutzer angemeldet sind" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Legitimierung ist zum Neustart des Systems notwendig, während andere " +"Benutzer angemeldet sind." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "" +"Das System neu starten, während eine Anwendung anfordert es zu unterbinden" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Legitimierung ist zum Neustart des Systems notwendig, während eine Anwendung " +"anforderte es zu unterbinden." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Suspend the system" +msgstr "Das System in Bereitschaft versetzen" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "Authentication is required for suspending the system." +msgstr "Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system while other users are logged in" +msgstr "" +"Das System in Bereitschaft versetzen, während andere Benutzer angemeldet " +"sind." + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig, " +"während andere Benutzer angemeldet sind." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "" +"Das System in Bereitschaft versetzen, während eine Anwendung anfordert dies " +"zu unterbinden" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Legitimierung ist zum Versetzen des Systems in Bereitschaft notwendig, " +"während eine Anwendung anfordert dies zu unterbinden." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Hibernate the system" +msgstr "Den Ruhezustand des Systems aktivieren" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "Authentication is required for hibernating the system." +msgstr "" +"Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system while other users are logged in" +msgstr "" +"Den Ruhezustand des Systems aktivieren, während andere Benutzer angemeldet " +"sind" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Legitimierung ist zum Aktivieren des Ruhezustands des Systems notwendig, " +"während andere Benutzer angemeldet sind." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "" +"Das System in den Ruhezustand versetzen, während eine Anwendung wünscht dies " +"zu verhindern" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Legitimierung ist zum Versetzen des System in den Ruhezustand notwendig, " +"während eine Anwendung wünscht dies zu verhindern." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Manage active sessions, users and seats" +msgstr "Aktive Sitzungen, Benutzer und Arbeitsstationen verwalten" + +# www.freedesktop.org/wiki/Software/systemd/multiseat/ +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Legitimierung ist zur Verwaltung aktiver Sitzungen, Benutzern und " +"Arbeitsstationen notwendig." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Lock or unlock active sessions" +msgstr "Aktive Sitzungen sperren und entsperren" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Legitimierung ist zum Sperren und Entsperren aktiver Sitzungen notwendig." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "" +"Mitteilungen an die Firmware zum Starten in die Einrichtungsoberfläche " +"zulassen" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Legitimierung ist zum Starten der Firmware in die Einrichtungsoberfläche " +"notwendig." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Set a wall message" +msgstr "Nachricht an alle einstellen" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "Authentication is required to set a wall message" +msgstr "Legitimierung ist zum Einstellen einer Nachricht an alle notwendig" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "In einem lokalen Container anmelden" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "Legitimierung ist zum Anmelden in einem lokalen Container notwendig." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Am lokalen Rechner anmelden" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Legitimierung ist zum Anmelden am lokalen Rechner notwendig." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Eine Shell in einem lokalen Container erhalten" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Legitimierung ist zum Erhalten einer Shell in einem lokalen Container " +"notwendig." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Eine Shell auf dem lokalen Rechner erhalten" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Legitimierung ist zum Erhalten einer Shell auf dem lokalen Rechner notwendig." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Ein Pseudo-TTY in einem lokalen Container erhalten" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Legitimierung ist zum Erhalten eines Pseudo-TTY in einem lokalen Container " +"notwendig." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Ein Pseudo-TTY auf dem lokalen Rechner erhalten" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Legitimierung ist zum Erhalten eines Pseudo-TTY auf dem lokalen Rechner " +"notwendig." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Lokale virtuelle Maschinen und Container verwalten" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Legitimierung ist zum Verwalten lokaler virtueller Maschinen und Container " +"erforderlich." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Lokale virtuelle Maschinen und Containerabbilder verwalten" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Legitimierung ist zum Verwalten lokaler virtueller Maschinen und " +"Containerabbildern erforderlich." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Die Systemzeit festlegen" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Legitimierung ist zum Festlegen der Systemzeit notwendig." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Die Systemzeitzone festlegen" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "Legitimierung ist zum Festlegen der Systemzeitzone notwendig." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Echtzeituhr auf lokale Zeitzone oder UTC setzen" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Legitimierung ist notwendig zum Festlegen, ob die Echtzeituhr auf lokale " +"Zeitzone oder UTC eingestellt ist." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Netzwerkzeitabgeich ein- oder ausschalten" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Legitimierung ist zum Festlegen, ob Netzwerkzeitabgeich eingeschaltet sein " +"soll, erforderlich." + +#: ../src/core/dbus-unit.c:428 +msgid "Authentication is required to start '$(unit)'." +msgstr "Legitimierung ist zum Starten von »$(unit)« notwendig." + +#: ../src/core/dbus-unit.c:429 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Legitimierung ist zum Stoppen von »$(unit)« notwendig." + +#: ../src/core/dbus-unit.c:430 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Legitimierung ist zum erneuten Laden von »$(unit)« notwendig." + +#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Legitimierung ist zum Neustarten von »$(unit)« notwendig." + +#: ../src/core/dbus-unit.c:535 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Legitimierung ist zum Eliminieren von »$(unit)« notwendig." + +#: ../src/core/dbus-unit.c:565 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Legitimierung ist zum Zurücksetzen des Status »fehlgeschlagen« von »$(unit)« " +"notwendig" + +#: ../src/core/dbus-unit.c:597 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "" +"Legitimierung ist zum Festlegen der Eigenschaften von »$(unit)« notwendig." + +#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" +#~ msgstr "Strg+C drücken um laufende Dateisystem-Prüfungen abzubrechen" + +#~ msgid "Checking in progress on %d disk (%3.1f%% complete)" +#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" +#~ msgstr[0] "Prüfe %d Laufwerk (%3.1f%% fertig)" +#~ msgstr[1] "Prüfe %d Laufwerke (%3.1f%% fertig)" diff --git a/po/el.po b/po/el.po new file mode 100644 index 00000000..271a5d42 --- /dev/null +++ b/po/el.po @@ -0,0 +1,614 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Greek translation for systemd. +# Dimitris Spingos , 2014. +# Dimitris Spingos (Δημήτρης Σπίγγος) , 2014. +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-11-22 16:37+0100\n" +"PO-Revision-Date: 2014-04-29 09:17+0300\n" +"Last-Translator: Dimitris Spingos (Δημήτρης Σπίγγος) \n" +"Language-Team: team@lists.gnome.gr\n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.0\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Αποστολή του συνθηματικού πίσω στο σύστημα" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Απαιτείται πιστοποίηση για αποστολή του εισερχόμενου συνθηματικού πίσω στο " +"σύστημα." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +#, fuzzy +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και " +"υπηρεσιών." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +#, fuzzy +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και " +"υπηρεσιών." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +#, fuzzy +msgid "Set or unset system and service manager environment variables" +msgstr "Προνομιούχος πρόσβαση διαχειριστή συστήματος και υπηρεσίας" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +#, fuzzy +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Απαιτείται πιστοποίηση για να προσπελάσετε τον διαχειριστή συστήματος και " +"υπηρεσιών." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +#, fuzzy +msgid "Reload the systemd state" +msgstr "Επανεκκίνηση του συστήματος" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +#, fuzzy +msgid "Authentication is required to reload the systemd state." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Ορισμός ονόματος οικοδεσπότη" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Ορισμός στατικού ονόματος οικοδεσπότη" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Απαιτείται πιστοποίηση για να ορίσετε το στατικά ρυθμισμένο όνομα τοπικού " +"οικοδεσπότη, καθώς και το pretty όνομα οικοδεσπότη." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Ορισμός πληροφοριών μηχανής" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +#, fuzzy +msgid "Authentication is required to import a VM or container image" +msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +#, fuzzy +msgid "Authentication is required to export a VM or container image" +msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +#, fuzzy +msgid "Authentication is required to download a VM or container image" +msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Ορισμός τοπικών ρυθμίσεων συστήματος" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "" +"Απαιτείται πιστοποίηση για να ορίσετε τις τοπικές ρυθμίσεις του συστήματος." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Ορισμός ρυθμίσεων πληκτρολογίου συστήματος" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Απαιτείται πιστοποίηση για να ορίσετε τις ρυθμίσεις πληκτρολογίου του " +"συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "" +"Να επιτρέπεται στις εφαρμογές να αποτρέπουν τον τερματισμό του συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει τον " +"τερματισμό του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "" +"Να επιτρέπεται στις εφαρμογές να καθυστερούν τον τερματισμό του συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να καθυστερήσει " +"τον τερματισμό του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Να επιτρέπεται στις εφαρμογές να αποτρέπουν την ύπνωση του συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " +"ύπνωση του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Να επιτρέπεται στις εφαρμογές να καθυστερούν την ύπνωση του συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να καθυστερήσει " +"την ύπνωση του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "" +"Να επιτρέπεται στις εφαρμογές να αποτρέπουν την αυτόματη αναστολή του " +"συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " +"αυτόματη αναστολή του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου " +"ενεργοποίησης του συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " +"διαχείριση του πλήκτρου ενεργοποίησης του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου " +"αναστολής του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " +"διαχείριση του πλήκτρου αναστολής του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του πλήκτρου " +"αδρανοποίησης του συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " +"διαχείριση του πλήκτρου αδρανοποίησης του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Να επιτρέπεται στις εφαρμογές να αποτρέπουν τη διαχείριση του διακόπτη " +"καλύμματος του συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Απαιτείται πιστοποίηση για να επιτρέπεται σε μια εφαρμογή να αποτρέψει την " +"διαχείριση του διακόπτη καλύμματος του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in users to run programs" +msgstr "Να επιτρέπεται σε μη συνδεμένους χρήστες να εκτελούν προγράμματα" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Απαιτείται πιστοποίηση για να επιτρέπεται σε μη συνδεμένους χρήστες να " +"εκτελούν προγράμματα." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow attaching devices to seats" +msgstr "Να επιτρέπεται η προσάρτηση συσκευών στους σταθμούς εργασίας" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Flush device to seat attachments" +msgstr "Αφαίρεση συσκευής από προσαρτήσεις σταθμού εργασίας" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Απαιτείται πιστοποίηση για επαναφορά του τρόπου που οι συσκευές προσαρτώνται " +"στους σταθμούς εργασίας." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Power off the system" +msgstr "Σβήσιμο του συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "Authentication is required for powering off the system." +msgstr "Απαιτείται πιστοποίηση για την σβήσιμο του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system while other users are logged in" +msgstr "Σβήσιμο του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Απαιτείται πιστοποίηση για σβήσιμο του συστήματος ενώ άλλοι χρήστες είναι " +"συνδεμένοι." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Απενεργοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί." + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Απαιτείται πιστοποίηση για απενεργοποίηση του συστήματος ενώ μια εφαρμογή " +"ζήτησε να αποτραπεί." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Reboot the system" +msgstr "Επανεκκίνηση του συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "Authentication is required for rebooting the system." +msgstr "Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system while other users are logged in" +msgstr "Επανεκκίνηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος ενώ άλλοι χρήστες " +"είναι συνδεμένοι." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Επανεκκίνηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Απαιτείται πιστοποίηση για επανεκκίνηση του συστήματος ενώ μια εφαρμογή " +"ζήτησε να αποτραπεί." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Suspend the system" +msgstr "Αναστολή του συστήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "Authentication is required for suspending the system." +msgstr "Απαιτείται πιστοποίηση για την αναστολή του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system while other users are logged in" +msgstr "Αναστολή του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Απαιτείται πιστοποίηση για αναστολή του συστήματος ενώ άλλοι χρήστες είναι " +"συνδεμένοι." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Αναστολή του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Απαιτείται πιστοποίηση για αναστολή του συστήματος ενώ μια εφαρμογή ζήτησε " +"να αποτραπεί." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Hibernate the system" +msgstr "Αδρανοποίηση του συτήματος" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "Authentication is required for hibernating the system." +msgstr "Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system while other users are logged in" +msgstr "Αδρανοποίηση του συστήματος ενώ άλλοι χρήστες είναι συνδεμένοι" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος ενώ άλλοι χρήστες " +"είναι συνδεμένοι." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Αδρανοποίηση του συστήματος ενώ μια εφαρμογή ζήτησε να αποτραπεί" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Απαιτείται πιστοποίηση για αδρανοποίηση του συστήματος ενώ μια εφαρμογή " +"ζήτησε να αποτραπεί." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Manage active sessions, users and seats" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +#, fuzzy +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Απαιτείται πιστοποίηση για προσάρτηση μιας συσκευής σε έναν σταθμό εργασίας." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Lock or unlock active sessions" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +#, fuzzy +msgid "Authentication is required to lock or unlock active sessions." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +#, fuzzy +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Set a wall message" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +#, fuzzy +msgid "Authentication is required to set a wall message" +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +#, fuzzy +msgid "Authentication is required to log into a local container." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +#, fuzzy +msgid "Authentication is required to log into the local host." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +#, fuzzy +msgid "Acquire a shell in a local container" +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +#, fuzzy +msgid "Authentication is required to acquire a shell in a local container." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +#, fuzzy +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +#, fuzzy +msgid "Acquire a pseudo TTY in a local container" +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +#, fuzzy +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +#, fuzzy +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +#, fuzzy +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +#, fuzzy +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε πληροφορίες τοπικής μηχανής." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Ορισμός ώρας συστήματος" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Ορισμός ζώνης ώρας συστήματος" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα ζώνης του συστήματος." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Ορισμός RTC στην τοπική ζώνη ώρας ή UTC" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Απαιτείται πιστοποίηση για να ελέγξετε αν το RTC αποθηκεύει την τοπική ή την " +"ώρα UTC." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Ενεργοποίηση/Απενεργοποίηση συγχρονισμού ώρας δικτύου" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Απαιτείται πιστοποίηση για να ελέγξετε αν ο συγχρονισμός ώρας δικτύου θα " +"ενεργοποιηθεί." + +#: ../src/core/dbus-unit.c:428 +#, fuzzy +msgid "Authentication is required to start '$(unit)'." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." + +#: ../src/core/dbus-unit.c:429 +#, fuzzy +msgid "Authentication is required to stop '$(unit)'." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." + +#: ../src/core/dbus-unit.c:430 +#, fuzzy +msgid "Authentication is required to reload '$(unit)'." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." + +#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 +#, fuzzy +msgid "Authentication is required to restart '$(unit)'." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." + +#: ../src/core/dbus-unit.c:535 +#, fuzzy +msgid "Authentication is required to kill '$(unit)'." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/core/dbus-unit.c:565 +#, fuzzy +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε τοπικά όνομα οικοδεσπότη." + +#: ../src/core/dbus-unit.c:597 +#, fuzzy +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Απαιτείται πιστοποίηση για να ορίσετε την ώρα του συστήματος." diff --git a/po/es.po b/po/es.po new file mode 100644 index 00000000..786e0d2c --- /dev/null +++ b/po/es.po @@ -0,0 +1,612 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Spanish translation for systemd. +# Alex Puchades , 2015. +# Daniel Mustieles , 2015. +# Álex Puchades , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-11-22 16:37+0100\n" +"PO-Revision-Date: 2016-06-07 15:41-0400\n" +"Last-Translator: Pablo Lezaeta Reyes \n" +"Language-Team: Español; Castellano \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.7.1\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Devolver contraseña al sistema" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Se requiere autenticación para devolver la contraseña introducida al sistema." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Administrar servicios del sistema u otras unidades" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Se requiere autenticación para administrar los servicios de sistema u otras " +"unidades." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Administrar servicio del sistema o archivos de unidad" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Se requiere autenticación para administrar el servicio de sistema o los " +"archivos de unidad." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "Administrar variables de entorno del sistema y del gestor de servicios" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Se requiere autenticación para administrar las variables de entorno del " +"sistema y del gestor de servicios." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Recargar el estado de systemd" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Se requiere autenticación para recargar el estado de systemd." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Establecer el nombre del equipo" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Se requiere autenticación para establecer el nombre del equipo local." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Establecer nombre estático del equipo" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Se requiere autenticación para establecer el nombre estático de equipo " +"local, así como el nombre visible del equipo." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Establecer información del sistema" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "" +"Se requiere autenticación para establecer la información de sistema local." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Importar una imagen de máquina virtual o de contenedor" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Se requiere autenticación para importar una imagen de máquina virtual o de " +"contenedor" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Exportar imagen de máquina virtual o de contenedor" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Se requiere autenticación para exportar una imagen de máquina virtual o de " +"contenedor" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Descargar una imagen de máquina virtual o de contenedor" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Se requiere autenticación para descargar una imagen de máquina virtual o de " +"contenedor" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Establecer región del sistema" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "Se requiere autenticación para establecer la región del sistema." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Configurar teclado" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "Se requiere autenticación para configurar el teclado del sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Permitir que las aplicaciones impidan el apagado del sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Se requiere autenticación para que una aplicación impida el apagado del " +"sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Permitir a las aplicaciones retrasar el apagado del sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Se requiere autenticación para que una aplicación retrase el apagado del " +"sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Permitir a las aplicaciones impedir la hibernación del sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Se requiere autenticación para que una aplicación impida la hibernación del " +"sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Permitir a las aplicaciones retrasar la hibernación del sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Se requiere autenticación para que una aplicación retrase la hibernación del " +"sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "" +"Permitir a las aplicaciones impedir la suspensión automática del sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Se requiere autenticación para que una aplicación impida la suspensión " +"automática del sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Permitir a las aplicaciones impedir el manejo de la tecla de encendido/" +"apagado por parte del sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Se requiere autenticación para que una aplicación impida el manejo de la " +"tecla de encendido/apagado por parte del sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Permitir a las aplicaciones impedir el manejo de la tecla de suspensión por " +"parte del sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Se requiere autenticación para que una aplicación impida el manejo de la " +"tecla de suspensión por parte del sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Permitir a las aplicaciones impedir el manejo de la tecla de hibernación por " +"parte del sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Se requiere autenticación para que una aplicación impida el manejo de la " +"tecla de hibernación por parte del sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Permitir a las aplicaciones impedir el manejo del cierre de la tapa del " +"portátil por parte del sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Se requiere autenticación para que una aplicación impida el manejo del " +"cierre de la tapa del portátil por parte del sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in users to run programs" +msgstr "Permitir la ejecución de programas a usuarios no conectados" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Se requiere autenticación para la ejecución de programas por usuarios no " +"conectados." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow attaching devices to seats" +msgstr "Permitir la conexión de dispositivos a los puestos de trabajo" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Se requiere autenticación para conectar un dispositivo a un puesto de " +"trabajo." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Flush device to seat attachments" +msgstr "Refrescar los dispositivos asociados a cada puesto de trabajo" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Se requiere autenticación para reconfigurar los dispositivos asociados a " +"cada puesto de trabajo." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Power off the system" +msgstr "Apagar el sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "Authentication is required for powering off the system." +msgstr "Se requiere autenticación para apagar el sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system while other users are logged in" +msgstr "Apagar el sistema mientras todavía hay usuarios conectados" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Se requiere autenticación para apagar el sistema mientras todavía hay " +"usuarios conectados." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Apagar el sistema a pesar de que una aplicación lo impide" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Se requiere autenticación para apagar el sistema a pesar de que una " +"aplicación lo impide." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Reboot the system" +msgstr "Reiniciar el sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "Authentication is required for rebooting the system." +msgstr "Se requiere autenticación para reiniciar el sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system while other users are logged in" +msgstr "Reiniciar el sistema mientras todavía hay usuarios conectados" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Se requiere autenticación para reiniciar el sistema mientras todavía hay " +"usuarios conectados." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Reiniciar el sistema a pesar de que una aplicación lo impide" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Se requiere autenticación para reiniciar el sistema a pesar de que una " +"aplicación lo impide." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Suspend the system" +msgstr "Suspender el sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "Authentication is required for suspending the system." +msgstr "Se requiere autenticación para suspender el sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system while other users are logged in" +msgstr "Suspender el sistema mientras todavía hay usuarios conectados" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Se requiere autenticación para suspender el sistema mientras todavía hay " +"usuarios conectados." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Suspender el sistema a pesar de que una aplicación lo impide" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Se requiere autenticación para suspender el sistema a pesar de que una " +"aplicación lo impide." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Hibernate the system" +msgstr "Hibernar el sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "Authentication is required for hibernating the system." +msgstr "Se requiere autenticación para hibernar el sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system while other users are logged in" +msgstr "Hibernar el sistema mientras todavía hay usuarios conectados" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Se requiere autenticación para hibernar el sistema mientras todavía hay " +"usuarios conectados." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Hibernar el sistema a pesar de que una aplicación lo impide" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Se requiere autenticación para hibernar el sistema a pesar de que una " +"aplicación lo impide." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Manage active sessions, users and seats" +msgstr "Administrar sesiones activas, usuarios y puestos de trabajo" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Se requiere autenticación para administrar las sesiones activas, usuarios y " +"puestos de trabajo." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Lock or unlock active sessions" +msgstr "Bloquear/desbloquear sesiones activas" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "Se requiere autenticación para bloquear/desbloquear sesiones activas." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "" +"Permitir indicación al firmware para arrancar la interfaz de configuración" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Se requiere autenticación para indicar al firmware que arranque la interfaz " +"de configuración." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Set a wall message" +msgstr "Establecer muro de texto" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "Authentication is required to set a wall message" +msgstr "Se requiere autenticación para establecer un muro de texto" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Conectarse a un contenedor local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "Se requiere autenticación para conectarse a un contenedor local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Conectarse al equipo local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Se requiere autenticación para conectarse al equipo local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Se adquiere un intérprete de órdenes en un contenedor local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Se requiere autenticación para adquirir un intérprete de órdenes en un " +"contenedor local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Se adquiere un intérprete de órdenes en el equipo local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Se requiere autenticación para adquirir un intérprete de órdenes del equipo " +"local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Se adquiere un seudo-TTY en el contenedor local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Se requiere autenticación para adquirir un seudo-TTY en el contenedor local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Se adquiere un seudo-TTY en el equipo local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Se requiere autenticación para adquirir un seudo-TTY en el equipo local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Administrar máquinas virtuales y contenedores locales" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Se requiere autenticación para administrar las máquinas virtuales y los " +"contenedores locales." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Administrar imágenes de máquina virtual y de contenedores locales" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Se requiere autenticación para administrar las imágenes de máquina virtual y " +"de contenedores locales." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Establecer fecha y hora del sistema" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Se requiere autenticación para establecer la fecha y hora del sistema." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Establecer la zona horaria del sistema" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "Se requiere autenticación para establecer la zona horaria del sistema." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Establecer reloj del sistema en formato de hora local/tiempo UTC" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Se requiere autenticación para establecer el reloj del sistema en formato de " +"hora local o tiempo UTC." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Activar/desactivar la sincronización de hora por red" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Se requiere autenticación para activar/desactivar la sincronización de hora " +"por red." + +#: ../src/core/dbus-unit.c:428 +msgid "Authentication is required to start '$(unit)'." +msgstr "Se requiere autenticación para iniciar '$(unit)'." + +#: ../src/core/dbus-unit.c:429 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Se requiere autenticación para detener '$(unit)'." + +#: ../src/core/dbus-unit.c:430 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Se requiere autenticación para recargar '$(unit)'." + +#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Se requiere autenticación para reiniciar '$(unit)'." + +#: ../src/core/dbus-unit.c:535 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Se requiere autenticación para matar a '$(unit)'." + +#: ../src/core/dbus-unit.c:565 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "Se requiere autenticación para reiniciar el estado de «fallido» de '$(unit)'." + +#: ../src/core/dbus-unit.c:597 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "" +"Se requiere autenticación para establecer las propiedades de '$(unit)'." + +#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" +#~ msgstr "" +#~ "Presione Ctrl+C para cancelar todas las comprobaciones del sistema de " +#~ "archivos en curso" + +#~ msgid "Checking in progress on %d disk (%3.1f%% complete)" +#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" +#~ msgstr[0] "Comprobando progreso en %d disco (%3.1f %% completado)" +#~ msgstr[1] "Comprobando progreso en %d discos (%3.1f %% completado)" diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 00000000..3f099788 --- /dev/null +++ b/po/fr.po @@ -0,0 +1,748 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# French translations for systemd package +# Traductions françaises du paquet systemd. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-03-07 22:43+0100\n" +"PO-Revision-Date: 2019-03-07 23:09+0100\n" +"Last-Translator: Sylvain Plantefève \n" +"Language-Team: French\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Renvoyer la phrase secrète au système" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "Authentification requise pour renvoyer la phrase secrète au système." + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Gérer les services système ou les unités" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Authentification requise pour gérer les services système ou les unités." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Gérer le service système ou ses fichiers unités" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Authentification requise pour gérer le service système ou ses fichiers " +"unités." + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Définir ou supprimer des variables d'environnement du système ou du " +"gestionnaire de services" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Authentification requise pour définir ou supprimer des variables " +"d'environnement du système ou du gestionnaire de services." + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "Recharger l'état de systemd" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "Authentification requise pour recharger l'état de systemd" + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "Définir le nom d'hôte" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "Authentification requise pour définir le nom d'hôte local." + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "Définir le nom d'hôte statique" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Authentification requise pour définir le nom d'hôte local de manière " +"statique, tout comme le nom d'hôte familier." + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "Définir les informations sur la machine" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "" +"Authentification requise pour définir les informations sur la machine locale." + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "Obtenir l'UUID du produit" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "Authentification requise pour obtenir l'UUID du produit." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Importer une image de machine virtuelle (VM) ou de conteneur" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Authentification requise pour importer une image de machine virtuelle (VM) " +"ou de conteneur." + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Exporter une image de machine virtuelle (VM) ou de conteneur" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Authentification requise pour exporter une image de machine virtuelle (VM) " +"ou de conteneur." + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Télécharger une image de machine virtuelle (VM) ou de conteneur" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Authentification requise pour télécharger une image de machine virtuelle " +"(VM) ou de conteneur." + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Définir la langue du système" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "Authentification requise pour définir la langue du système." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Définir les paramètres de clavier du système" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Authentification requise pour définir les paramètres de clavier du système." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Permet aux applications d'empêcher l'arrêt du système" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Authentification requise pour permettre à une application d'empêcher l'arrêt " +"du système." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Permet aux applications de retarder l'arrêt du système" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Authentification requise pour permettre à une application de retarder " +"l'arrêt du système." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Permet aux applications d'empêcher la mise en veille du système" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Authentification requise pour permettre à une application d'empêcher la mise " +"en veille du système." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Permet aux applications de retarder la mise en veille du système" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Authentification requise pour permettre à une application de retarder la " +"mise en veille du système." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "" +"Permet aux applications d'empêcher l'hibernation automatique du système" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Authentification requise pour permettre à une application d'empêcher " +"l'hibernation automatique du système." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Permet aux applications d'empêcher la gestion du bouton d'alimentation du " +"système" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Authentification requise pour permettre à une application d'empêcher la " +"gestion du bouton d'alimentation du système." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Permet aux applications d'empêcher la gestion du bouton de mise en veille du " +"système" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Authentification requise pour permettre à une application d'empêcher la " +"gestion du bouton de mise en veille du système." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Permet aux applications d'empêcher la gestion du bouton d'hibernation du " +"système" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Authentification requise pour permettre à une application d'empêcher la " +"gestion du bouton d'hibernation du système." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Permet aux applications d'empêcher la gestion par le système du rabat de " +"l'écran" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Authentification requise pour permettre à une application d'empêcher la " +"gestion par le système du rabat de l'écran." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "Permet à un utilisateur non connecté d'exécuter des programmes" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Requête explicite requise pour exécuter des programmes en tant " +"qu'utilisateur non connecté." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "Permet aux utilisateurs non connectés d'exécuter des programmes" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Authentification requise pour exécuter des programmes en tant qu'utilisateur " +"non connecté." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Permet d'associer des périphériques à des postes (seats)" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Authentification requise pour associer un périphérique à un poste (seat)." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Révoquer les associations de périphériques aux postes (seats)" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Authentification requise pour révoquer les associations de périphériques aux " +"postes (seats)." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Éteindre le système" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "Authentification requise pour éteindre le système." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "Éteindre le système alors que d'autres utilisateurs sont connectés" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Authentification requise pour éteindre le système alors que d'autres " +"utilisateurs sont connectés." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Éteindre le système alors qu'une application a demandé de l'empêcher" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Authentification requise pour éteindre le système alors qu'une application a " +"demandé de l'empêcher." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Redémarrer le système" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "Authentification requise pour redémarrer le système." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "Redémarrer le système alors que d'autres utilisateurs sont connectés" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Authentification requise pour redémarrer le système alors que d'autres " +"utilisateurs sont connectés." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Redémarrer le système alors qu'une application a demandé de l'empêcher" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Authentification requise pour redémarrer le système alors qu'une application " +"a demandé de l'empêcher." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Arrêter le système" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "Authentification requise pour arrêter le système." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "Arrêter le système alors que d'autres utilisateurs sont connectés" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Authentification requise pour arrêter le système alors que d'autres " +"utilisateurs sont connectés." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Arrêter le système alors qu'une application a demandé de l'empêcher" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Authentification requise pour arrêter le système alors qu'une application a " +"demandé de l'empêcher." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Mettre le système en veille" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "Authentification requise pour mettre le système en veille." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "" +"Mettre le système en veille alors que d'autres utilisateurs sont connectés" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Authentification requise pour mettre le système en veille alors que d'autres " +"utilisateurs sont connectés." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "" +"Mettre le système en veille alors qu'une application a demandé de l'empêcher" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Authentification requise pour mettre le système en veille alors qu'une " +"application a demandé de l'empêcher." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Mettre le système en hibernation" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "Authentification requise pour mettre le système en hibernation." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "" +"Mettre le système en hibernation alors que d'autres utilisateurs sont " +"connectés" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Authentification requise pour mettre le système en hibernation alors que " +"d'autres utilisateurs sont connectés." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "" +"Mettre le système en hibernation alors qu'une application a demandé de " +"l'empêcher" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Authentification requise pour mettre le système en hibernation alors qu'une " +"application a demandé de l'empêcher." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Gérer les sessions actives, les utilisateurs et les postes (seats)" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Authentification requise pour gérer les sessions actives, les utilisateurs " +"et les postes (seats)." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Verrouiller ou déverrouiller des sessions actives" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Authentification requise pour verrouiller ou déverrouiller des sessions " +"actives." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Indicate to the firmware to boot to setup interface" +msgstr "" +"Indiquer au micrologiciel de démarrer sur l'interface de configuration" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Authentification requise pour indiquer au micrologiciel de démarrer sur " +"l'interface de configuration." + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Indicate to the boot loader to boot to the boot loader menu" +msgstr "Indiquer au programme d'amorçage d'afficher le menu au démarrage" + +#: src/login/org.freedesktop.login1.policy:353 +msgid "" +"Authentication is required to indicate to the boot loader to boot to the " +"boot loader menu." +msgstr "" +"Authentification requise pour indiquer au programme d'amorçage d'afficher " +"le menu au démarrage." + +#: src/login/org.freedesktop.login1.policy:363 +msgid "Indicate to the boot loader to boot a specific entry" +msgstr "Indiquer au programme d'amorçage de démarrer une entrée spécifique" + +#: src/login/org.freedesktop.login1.policy:364 +msgid "" +"Authentication is required to indicate to the boot loader to boot into a " +"specific boot loader entry." +msgstr "" +"Authentification requise pour indiquer au programme d'amorçage de démarrer " +"une entrée spécifique." + +#: src/login/org.freedesktop.login1.policy:374 +msgid "Set a wall message" +msgstr "Définir un message wall" + +#: src/login/org.freedesktop.login1.policy:375 +msgid "Authentication is required to set a wall message" +msgstr "Authentification requise pour définir un message wall." + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Connexion dans un conteneur local" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "" +"Authentification requise pour permettre la connexion dans un conteneur local." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Connexion à l'hôte local" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "Authentification requise pour permettre la connexion à l'hôte local." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Obtenir une interface système dans un conteneur local" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Authentification requise pour obtenir une interface système dans un " +"conteneur local." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Obtenir une interface système sur l'hôte local" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Authentification requise pour obtenir une interface système sur l'hôte local." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Obtenir un pseudo terminal dans un conteneur local" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Authentification requise pour obtenir un pseudo terminal dans un conteneur " +"local." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Obtenir un pseudo terminal sur l'hôte local" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Authentification requise pour obtenir un pseudo terminal sur l'hôte local." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Gérer les machines virtuelles (VM) et conteneurs locaux" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Authentification requise pour gérer les machines virtuelles (VM) et les " +"conteneurs locaux." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Gérer les images locales de machines virtuelles (VM) et de conteneurs" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Authentification requise pour gérer les images locales de machines " +"virtuelles (VM) et de conteneurs." + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "Inspecter une image de service portable" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "Authentification requise pour inspecter une image de service portable." + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "Attacher ou détacher une image de service portable" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "" +"Authentification requise pour attacher ou détacher une image de service " +"portable." + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "Supprimer ou modifier une image de service portable" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "" +"Authentification requise pour supprimer ou modifier une image de service " +"portable." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Enregistrer un service DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Authentification requise pour enregistrer un service DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Retirer un service DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "Authentification requise pour retirer un service DNS-SD" + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Définir l'heure du système" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "Authentification requise pour définir l'heure du système." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Définir le fuseau horaire du système" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "Authentification requise pour définir le fuseau horaire du système." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "" +"Positionner l'horloge matérielle à l'heure locale ou sur le temps universel " +"coordonné (UTC)" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Authentification requise pour positionner l'horloge matérielle à l'heure " +"locale ou sur le temps universel coordonné (UTC)." + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "Activer ou désactiver la synchronisation de l'heure avec le réseau" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Authentification requise pour activer ou désactiver la synchronisation de " +"l'heure avec le réseau." + +#: src/core/dbus-unit.c:326 +msgid "Authentication is required to start '$(unit)'." +msgstr "Authentification requise pour démarrer « $(unit) »." + +#: src/core/dbus-unit.c:327 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Authentification requise pour arrêter « $(unit) »." + +#: src/core/dbus-unit.c:328 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Authentification requise pour recharger « $(unit) »." + +#: src/core/dbus-unit.c:329 src/core/dbus-unit.c:330 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Authentification requise pour redémarrer « $(unit) »." + +#: src/core/dbus-unit.c:437 +msgid "" +"Authentication is required to send a UNIX signal to the processes of " +"'$(unit)'." +msgstr "" +"Authentification requise pour envoyer un signal UNIX aux processus de " +"« $(unit) »." + +#: src/core/dbus-unit.c:468 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Authentification requise pour réinitialiser l'état d'« échec » de " +"« $(unit) »." + +#: src/core/dbus-unit.c:501 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Authentification requise pour définir des propriétés de « $(unit) »." + +#~ msgid "Authentication is required to kill '$(unit)'." +#~ msgstr "Authentification requise pour tuer « $(unit) »." + +#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" +#~ msgstr "" +#~ "Appuyez sur Ctrl+C pour annuler toutes vérifications en cours du système " +#~ "de fichiers" + +#~ msgid "Checking in progress on %d disk (%3.1f%% complete)" +#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" +#~ msgstr[0] "Vérification en cours sur %d disque (%3.1f%% complété)" +#~ msgstr[1] "Vérification en cours sur %d disques (%3.1f%% complété)" diff --git a/po/gl.po b/po/gl.po new file mode 100644 index 00000000..4b09007a --- /dev/null +++ b/po/gl.po @@ -0,0 +1,584 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Fran Dieguez , 2015. +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-09-14 23:55+0200\n" +"PO-Revision-Date: 2015-09-15 00:20+0200\n" +"Last-Translator: Fran Dieguez \n" +"Language-Team: gnome-l10n-gl@gnome.org\n" +"Language: gl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Enviar frase de paso de volta ao sistema" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Requírese autenticación para enviar a frase de paso escrita de volta ao " +"sistema." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Xestionar os servizos do sistema ou outras unidades" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Requírese autenticación para xestionar os servizos do sistema ou outras " +"unidades" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Xestionar os servizos do sistema ou outros ficheiros" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Requírese autenticación para xestionar os servizos do sistema ou outros " +"ficheiros." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Estabelecer ou desestabelecer as variables de ambiente do sistema ou do " +"xestor de servizos" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Requírese autenticación para estabelecer ou desestabelecer as variables de " +"ambiente do sistema ou do xestor de servizos" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Recargar o estado de systemd" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Requírese autenticación para recargar o estado de systemd." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Estabelecer o nome do equipo" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Requírese autenticación para estabelecer o nome local do equiupo." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Estabelecer o nome do equipo estático" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Requírese autenticación para estabelecer de forma o nome do equipo local " +"estabelecido de forma estática, así como o nome do equipo lexíbel por " +"persoas." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Estabelecer a información da máquina" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "Requírese autenticación para estabelecer a información da máquina local" + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Importar unha imaxe de MV ou contenedor" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "Requírese autenticación para imporar unha imaxe de MV ou contenedor" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Exportar unha imaxe de MV ou contenedor" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "Requírese autenticación para exportar unha imaxe de MV ou contenedor" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Descargar unha imaxe de MV ou contenedor" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "Requírese autenticación para descargar unha imaxe de MV ou contenedor" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Estabelecer a configuración rexional do sistema" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "" +"Requírese autenticación para estabelecer a configuración rexional do sistema" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Estabelecer as preferencias do teclado do sistema" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Requírese autenticación para estabelecer as preferencias do teclado do " +"sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Permitir aos aplicativos inhibit o apagado do sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Requírese autenticación para permitirlle a un aplicativo poida inhibir o " +"apagado do sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Permitir aos aplicativos retrasar o apagado do sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Requírese autenticación para permitirlle a un aplicativo retrasar o apagado " +"do sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Permitir aos aplicativos inhibir a suspensión do sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Requírese autenticación para permitirlle a un aplicativo inhibir a " +"suspensión do sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Permitir aos aplicativos retrasar a suspensión do sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Requírese autenticación para permitirlle a un aplicativo retrasar a " +"suspensión do sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Permitir aos aplicativos inhibir a suspensión automática do sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Requírese autenticación para permitirlle a un aplicativo inhibir a " +"suspensión automática do sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Permitir aos aplicativos inhibir a xestión do sistema da tecla de acendido" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Requírese autenticación para permitirlle a un aplicativo inhibir a xestión " +"do sistema da tecla de acendido." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Permitir aos aplicativos inhibir a xestión do sistema da tecla de suspensión" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Requírese autenticación para permitirlle a un aplicativo inhibir a xestión " +"do sistema da tecla de suspensión." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Permitir aos aplicativos inhibir a xestión do sistema da tecla de hibernado" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Requírese autenticación para permitirlle a un aplicativo inhibir a xestión " +"do sistema da tecla de hibernado." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Permitir aos aplicativos inhibir a xestión do sistema do interruptor da tapa." + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Requírese autenticación para permitirlle a un aplicativo inhibir a xestión " +"do sistema do interruptor da tapa." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in users to run programs" +msgstr "Permitirlle a usuarios sen unha sesión iniciada executar programas" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Requírese autenticación para permitirlle executar programas a un usuario sen " +"unha sesión iniciada." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow attaching devices to seats" +msgstr "Permitir conectar anexar a asentos" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required for attaching a device to a seat." +msgstr "Requírese autenticación para anexar un dispositivo a un asento." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Flush device to seat attachments" +msgstr "Reiniciar os anexos do dispositivo aos asentos" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Requírese autenticación para reiniciar como os dispositivos están anexados " +"aos asentos." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Power off the system" +msgstr "Apagar o sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "Authentication is required for powering off the system." +msgstr "Requírese autenticación para apagar o sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system while other users are logged in" +msgstr "Apagar o sistema mentres hai usuarios con unha sesión iniciada" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Requírese autenticación para apagar o sistema mentres hai usuarios con unha " +"sesión iniciada." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Apagar o sistema cando un aplicativo solicitou a súa inhibición" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Requírese autenticación para apagar o sistema mentres un aplicativo " +"solicitou a súa inhibición." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Reboot the system" +msgstr "Reiniciar o sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "Authentication is required for rebooting the system." +msgstr "Requírese autenticación para reiniciar o sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system while other users are logged in" +msgstr "Reiniciar o sistema mentres outros usuarios teñen unha sesión iniciada" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Requírese autenticación para reiniciar o sistema mentres outros usuarios " +"teñen unha sesión iniciada." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Reiniciar o sistema cando un aplicativo solicitou a súa inhibición" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Requírese autenticación para reiniciar o sistema mentres un aplicativo " +"solicitou a súa inhibición." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Suspend the system" +msgstr "Suspender o sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "Authentication is required for suspending the system." +msgstr "Requírese autenticación para suspender o sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system while other users are logged in" +msgstr "Suspender o sistema mentres outros usuarios teñen unha sesión iniciada" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Requírese autenticación para suspender o sistema mentres outros usuarios " +"teñen unha sesión iniciada." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Suspender o sistema cando un aplicativo solicitou a súa inhibición" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Requírese autenticación para suspender o sistema mentres un aplicativo " +"solicitou a súa inhibición." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Hibernate the system" +msgstr "Hibernar o sistema" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "Authentication is required for hibernating the system." +msgstr "Requírese autenticación para hibernar o sistema." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system while other users are logged in" +msgstr "Hibernar o sistema mentres outros usuarios teñen unha sesión iniciada" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Requírese autenticación para hibernar o sistema mentres outros usuarios " +"teñen unha sesión iniciada." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Hibernar o sistema cando un aplicativo solicitou a súa inhibición" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Requírese autenticación para hibernar o sistema mentres un aplicativo " +"solicitou a súa inhibición." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Manage active sessions, users and seats" +msgstr "Xestionar as sesións, usuarios e asentos activos" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Requírese autenticación para xestionar as sesións, usuariso e asentos activos" + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Lock or unlock active sessions" +msgstr "Bloquear ou desbloquear sesión activas" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Requírese autenticación para bloquear ou desbloquear as sesións activas." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "Permitir indicarlle ao firmware arrincar para configurar unha interface" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Requírese autenticación para indicarlle ao firmware arrincar para configurar " +"unha interface." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Set a wall message" +msgstr "Estabelecer a mensaxe do muro" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "Authentication is required to set a wall message" +msgstr "Requírese autenticación para estabelecer unha mensaxe de muro" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Iniciar sesión nun contenedor local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "Requírese autenticación para iniciar sesión nun contenedor local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Iniciar sesión nun equipo local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Requírese autenticación para iniciar sesión nun equipo local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Adquirir unha shell nun contenedor local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "Requírese autenticación para adquirir unha shell nun contenedor local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Adquirir unha shell nun equipo local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Requírese autenticación para adquirir unha shell nun equipo local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Adquirir unha pseudo TTY nun contenedor local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Requírese autenticación para adquirir unha pseudo TTY nun contenedor local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Adquirir unha pseudo TTY nun equipo local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "Requírese autenticación para adquirir unha pseudo TTY nun equipo local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Xestionar máquinas virtuais e contenedores locais" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Requírese autenticación para xestionar máquinas virtuais e contenedores " +"locais." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Xestionar imaxes locais virtuais e contenedores locais" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Requírese autenticación para xestionar imaxes de máquinas virtuais e " +"contenedores locais." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Estabelecer a hora do sistema" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Requírese autenticación para estabelecer a hora do sistema." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Estabelecer o fuso horario" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "Requírese autenticación para estabelecer o fuso horario do sistema." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Estabelecer o RTC ao fuso horario ou UTC" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Requírese autenticación para controlar se o RTC almacena a hora local ou a " +"UTC." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Activar ou desactivar a sincronización de hora por rede" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Requírese autenticación para controlar se a sincronización de hora por rede " +"debería activarse." + +#: ../src/core/dbus-unit.c:428 +msgid "Authentication is required to start '$(unit)'." +msgstr "Requírese autenticación para inciar '$(unit)'." + +#: ../src/core/dbus-unit.c:429 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Requírese autenticación para deter '$(unit)'." + +#: ../src/core/dbus-unit.c:430 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Requírese autenticación para recargar '$(unit)'." + +#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Requírese autenticación para reiniciar '$(unit)'." + +#: ../src/core/dbus-unit.c:535 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Requírese autenticación para matar '$(unit)'." + +#: ../src/core/dbus-unit.c:565 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "Requírese autenticación para reinicair o estado «fallido» de '$(unit)'." + +#: ../src/core/dbus-unit.c:597 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Requírese autenticación para estabelecer as propiedades en '$(unit)'." diff --git a/po/hr.po b/po/hr.po new file mode 100644 index 00000000..4c884f18 --- /dev/null +++ b/po/hr.po @@ -0,0 +1,571 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# SOME DESCRIPTIVE TITLE. +# This file is distributed under the same license as the PACKAGE package. +# gogo , 2016. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2016-04-27 11:57+0100\n" +"PO-Revision-Date: 2016-04-27 12:11+0200\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.7.1\n" +"Last-Translator: gogo com>\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Language: hr\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Pošalji lozinku natrag u sustav" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "Potrebna je ovjera za slanje upisane lozinke natrag u sustav." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Upravljajte uslugama sustava ili drugim jedinicama" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "Potrebna je ovjera za upravljanje uslugama sustava ili jedinicama." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Upravljajte uslugama sustava ili datotekama jedinica" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Potrebna je ovjera za upravljanje uslugama sustava ili datotekama jedinica." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "Postavite ili uklonite varijable okruženja sustava i usluga" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Potrebna je ovjera za postavljanje ili uklanjanje varijabla okruženja " +"sustava i usluga." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Ponovno učitaj systemd stanje" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Potrebna je ovjera za ponovno učitavanje systemd stanja." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Postavi naziv računala" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Potrebna je ovjera za postavljanje naziva lokalnog računala." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Postavi nepromjenjivi naziv račumala" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Potrebna je ovjera za postavljenje nepromjenjivog naziva lokalnog računala, " +"kao i prijatnog naziva računala." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Postavi informacije računala" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "Potrebna je ovjera za postavljanje informacije lokalnog računala." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Uvezi VM ili spremnik slike" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "Potrebna je ovjera za uvoz WM ili spremnika slike" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Izvezi VM ili spremnik slike" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "Potrebna je ovjera za izvoz WM ili spremnika slike" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Preuzmi VM ili spremnik slike" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "Potrebna je ovjera za preuzimanje VM ili spremnika slike." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Postavi sustav lokalizacije" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "Potrebna je ovjera za postavljanje sustava lokalizacije." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Postavi postavke tipkovnice sustava" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "Potrebna je ovjera za postavljanje postavki tipkovnice sustava." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Dopusti aplikacijama zaustavljanje isključivanja sustava" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Potrebna je ovjera za dopuštanje aplikacijama zaustavljanje isključivanja " +"sustava." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Dopusti aplikacijama odgodu isključivanja sustava" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Potrebna je ovjera za dopuštanje aplikacijama odgode isključivanja sustava." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Dopusti aplikacijama zaustavljanje spavanja sustava" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Potrebna je ovjera za dopuštanje aplikacijama zaustavljanja spavanja sustava." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Dopusti aplikacijama odgodu spavanja sustava" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "Potrebna je ovjera za odgodu spavanja sustava." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Dopusti aplikacijama zaustavljanje automatskog suspendiranja sustava" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Potrebna je ovjera za dopuštanje aplikacijama zaustavljanje automatskog " +"suspendiranja sustava." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Dopusti aplikacijama sprječavanje rukovanja sustava tipkom isključivanja" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Potrebna je ovjera za dopuštanje aplikacijama sprječavanje rukovanja sustava " +"tipkom isključivanja." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "Dopusti aplikacijama sprječavanje rukovanja sustava tipkom suspenzije" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Potrebna je ovjera za dopuštanje aplikacijama sprječavanje rukovanja sustava " +"tipkom suspenzije." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "Dopusti aplikacijama sprječavanje rukovanja sustava tipkom hibernacije" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Potrebna je ovjera za dopuštanje aplikacijama sprječavanje rukovanja sustava " +"tipkom hibernacije." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "Dopusti aplikacijama sprječavanje rukovanja sustava preklopnicama" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Potrebna je ovjera za dopuštenje sprječavanja rukovanja sustava " +"preklopnicama." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in users to run programs" +msgstr "Dopusti neprijavljenim korisnicima pokretanje programa" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Potrebna je ovjera za dopuštenje neprijavljenim korisnicima pokretanje " +"programa." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow attaching devices to seats" +msgstr "Dopusti povezivanje uređaja skupu sesija i hardvera" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required for attaching a device to a seat." +msgstr "Potrebna je ovjera za povezivanje uređaja sa skupom sesija i hardvera." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Flush device to seat attachments" +msgstr "Ukloni povezani uređaj sa skupa sesija i hardvera" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Potrebna je ovjera za obnovu povezivanja uređaja sa skupom sesija i hardvera." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Power off the system" +msgstr "Isključi sustav" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "Authentication is required for powering off the system." +msgstr "Potrebna je ovjera za isključivanje sustava." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system while other users are logged in" +msgstr "Isključi sustav kada su ostali korisnici prijavljeni" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Potrebna je ovjera za isključivanje sustava kada su ostali korisnici " +"prijavljeni." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while an application asked to inhibit it" +msgstr "" +"Isključi sustav kada je aplikacija zatražila zaustavljanje isključivanja" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Potrebna je ovjera za isključivanje sustava kada je aplikacija zatražila " +"zaustavljanje isključivanja." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Reboot the system" +msgstr "Ponovno pokreni sustav" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "Authentication is required for rebooting the system." +msgstr "Potrebna je ovjera za ponovno pokretanje sustava." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system while other users are logged in" +msgstr "Ponovno pokreni sustav kada su ostali korisnici prijavljeni" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Potrebna je ovjera za ponovno pokretanje sustava kada su ostali korisnici " +"prijavljeni." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "" +"Ponovno pokreni sustav kada je aplikacija zatražila zaustavljanje ponovnog " +"pokretanja" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Potrebna je ovjera za ponovno pokretanje sustava kada je aplikacija " +"zatražila zaustavljanje ponovnog pokretanja." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Suspend the system" +msgstr "Suspendiraj sustav" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "Authentication is required for suspending the system." +msgstr "Potrebna je ovjera za suspendiranje sustava." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system while other users are logged in" +msgstr "Suspendiraj sustav kada su drugi korisnici prijavljeni" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Potrebna je ovjera za suspendiranje sustava kada su drugi korisnici " +"prijavljeni." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "" +"Suspendiraj sustav kada je aplikacija zatražila zaustavljanje suspendiranja" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Potrebna je ovjera za suspendiranje sustava kada je aplikacija zatražila " +"zaustavljanje suspendiranja." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Hibernate the system" +msgstr "Hiberniraj sustav" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "Authentication is required for hibernating the system." +msgstr "Potrebna je ovjera za hibernaciju sustava." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system while other users are logged in" +msgstr "Hiberniraj sustav kada su ostali korisnici prijavljeni." + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Potrebna je ovjera za hibernaciju sustava kada su drugi korisnici " +"prijavljeni." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "" +"Hiberniraj sustav kada je aplikacija zatražila zaustavljanje hibernacije" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Potrebna je ovjera za hibernaciju sustava kada je aplikacija zatražila " +"zaustavljanje hibernacije." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Manage active sessions, users and seats" +msgstr "" +"Upravljanje aktivnim sesijama, korisnicima i skupovima sesija i hardvera" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Potrebna je ovjera za upravljanje aktivnim sesijama, korisnicima i skupovima " +"sesija i hardvera." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Lock or unlock active sessions" +msgstr "Zaključavanje ili otključavanje aktivne sesije" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "Potrebna je ovjera za zaključavanje ili otključavanje aktivne sesije." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "Dopusti najavu frimveru za pokretanje sučelja postavljanja" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "Potrebna je ovjera najave frimvera za pokretanje sučelja postavljanja." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Set a wall message" +msgstr "Postavljanje zaslonske pruke" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "Authentication is required to set a wall message" +msgstr "Potrebna je ovjera za postavljanje zaslonske pruke." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Prijavi se u lokalni spremnik" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "Potrebna je ovjera za prijavu u lokalni spremnik." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Prijava na lokalno računalo" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Potrebna je ovjera za prijavu na lokalno račuanlo." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Pokretanje ljuske u lokalnom spremniku" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "Potrebna je ovjera za pokretanje ljuske u lokalnom spremniku." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Pokretanje ljuske na lokalnom računalu" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Potrebna je ovjera za pokretanje ljuske na lokalnom računalu." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Pokretanje pseudo TTY na lokalnom spremniku" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "Potrebna je ovjera za pokretanje pseudo TTY na lokalnom spremniku." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Pokretanje pseudo TTY na lokalnom računalu" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "Potrebna je ovjera za pokretanje pseudo TTY na lokalnom računalu." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Upravljanje lokalnim vurtualnim strojevima i spremnicima" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Potrebna je ovjera za upravljanje lokalnim vurtualnim strojevima i " +"spremnicima." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Upravljanje lokalnim vurtualnim strojevima i spremnicima slika" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Potrebna je ovjera za upravljanje lokalnim vurtualnim strojevima i " +"spremnicima slika." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Postavi vrijeme sustava" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Potrebna je ovjera za postavljanje vremena sustava." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Postavi vremensku zonu sustava" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "Potrebna je ovjera za postavljanje vremenske zone sustava." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Postavi RTC u lokalnu vremensku zonu ili UTC" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Potrebna je ovjera za postavljanje RTC-a u lokalnu vremensku zonu ili UTC." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Uključi ili isključi mrežno uklađivanje vremena" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Potrebna je ovjera za uključivanje ili isključivanje mrežnog usklađivanja " +"vremena." + +#: ../src/core/dbus-unit.c:428 +msgid "Authentication is required to start '$(unit)'." +msgstr "Potrebna je ovjera za pokretanje '$(unit)'." + +#: ../src/core/dbus-unit.c:429 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Potrebna je ovjera za zaustavljanje '$(unit)'." + +#: ../src/core/dbus-unit.c:430 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Potrebna je ovjera za ponovno učitavnje '$(unit)'." + +#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Potrebna je ovjera za ponovno pokretanje'$(unit)'." + +#: ../src/core/dbus-unit.c:535 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Potrebna je ovjera za ubijanje '$(unit)'." + +#: ../src/core/dbus-unit.c:565 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "Potrebna je ovjera za vraćanje \"neuspjelog\" stanja '$(unit)'." + +#: ../src/core/dbus-unit.c:597 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Potrebna je ovjera za postavljanje svojstava na '$(unit)'." diff --git a/po/hu.po b/po/hu.po new file mode 100644 index 00000000..98090bab --- /dev/null +++ b/po/hu.po @@ -0,0 +1,597 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Hungarian translation of systemd +# Copyright © 2015, 2016. Free Software Foundation, Inc. +# +# Gabor Kelemen , 2015, 2016. +# Balázs Úr , 2016. +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2016-04-24 12:53+0000\n" +"PO-Revision-Date: 2016-08-23 18:03+0100\n" +"Last-Translator: Balázs Úr \n" +"Language-Team: Hungarian \n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 2.0\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Jelmondat visszaküldése a rendszernek" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Hitelesítés szükséges a bevitt jelmondat visszaküldéséhez a rendszernek." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Rendszerszolgáltatások vagy más egységek kezelése" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Hitelesítés szükséges a rendszerszolgáltatások vagy más egységek kezeléséhez." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Rendszerszolgáltatás- vagy egységfájlok kezelése" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Hitelesítés szükséges a rendszerszolgáltatás- vagy egységfájlok kezeléséhez." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Rendszer- és szolgáltatáskezelő környezeti változóinak beállítása vagy " +"törlése" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Hitelesítés szükséges a rendszer- és szolgáltatáskezelő környezeti " +"változóinak beállításához vagy törléséhez." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "A systemd állapotának újratöltése" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Hitelesítés szükséges a systemd állapotának újratöltéséhez." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Gépnév beállítása" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Hitelesítés szükséges a helyi gépnév beállításához." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Statikus gépnév beállítása" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Hitelesítés szükséges a statikusan megadott helyi gépnév, valamint a szép " +"gépnév beállításához." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Gépinformációk beállítása" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "Hitelesítés szükséges a helyi gép információinak beállításához." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "VM vagy konténer lemezkép importálása" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép importálásához." + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "VM vagy konténer lemezkép exportálása" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép exportálásához." + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "VM vagy konténer lemezkép letöltése" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "Hitelesítés szükséges a VM vagy konténer lemezkép letöltéséhez." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Területi beállítás megadása" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "Hitelesítés szükséges a rendszer területi beállításainak megadásához." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Rendszer billentyűzetbeállítások megadása" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Hitelesítés szükséges a rendszer billentyűzetbeállításainak megadásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Alkalmazások meggátolhatják a rendszer leállítását" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Hitelesítés szükséges egy alkalmazás számára a rendszerleállítás " +"meggátlásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Alkalmazások késleltethetik a rendszer leállítását" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Hitelesítés szükséges egy alkalmazás számára a rendszerleállítás " +"késleltetéséhez." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Alkalmazások meggátolhatják a rendszer altatását" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Hitelesítés szükséges egy alkalmazás számára a rendszeraltatás meggátlásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Alkalmazások késleltethetik a rendszer altatását" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Hitelesítés szükséges egy alkalmazás számára a rendszeraltatás " +"késleltetéséhez." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Alkalmazások meggátolhatják a rendszer automatikus felfüggesztését" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Hitelesítés szükséges egy alkalmazás számára az automatikus " +"rendszerfelfüggesztés meggátlásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Alkalmazások meggátolhatják a bekapcsoló gomb rendszer általi kezelését" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Hitelesítés szükséges egy alkalmazás számára a bekapcsoló gomb rendszer " +"általi kezelésének meggátlásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Alkalmazások meggátolhatják a felfüggesztés gomb rendszer általi kezelését" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Hitelesítés szükséges egy alkalmazás számára a felfüggesztés gomb rendszer " +"általi kezelésének meggátlásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Alkalmazások meggátolhatják a hibernálás gomb rendszer általi kezelését" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Hitelesítés szükséges egy alkalmazás számára a hibernálás gomb rendszer " +"általi kezelésének meggátlásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "Alkalmazások meggátolhatják a fedélkapcsoló rendszer általi kezelését" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Hitelesítés szükséges egy alkalmazás számára a fedélkapcsoló rendszer általi " +"kezelésének meggátlásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in user to run programs" +msgstr "Programfuttatás engedélyezése be nem jelentkezett felhasználó számára" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Határozott kérés szükséges a programfuttatáshoz be nem jelentkezett " +"felhasználóként." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow non-logged-in users to run programs" +msgstr "Programfuttatás engedélyezése be nem jelentkezett felhasználók számára" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Hitelesítés szükséges a programfuttatáshoz be nem jelentkezett " +"felhasználóként." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Allow attaching devices to seats" +msgstr "Eszközök csatolásának engedélyezése munkaállomásokhoz" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Hitelesítés szükséges eszköz csatolásának engedélyezéséhez egy " +"munkaállomáshoz" + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Flush device to seat attachments" +msgstr "Eszközök és munkaállomások csatolásainak törlése" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Hitelesítés szükséges az eszközök munkaállomásokhoz csatolásainak " +"alaphelyzetbe állításához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system" +msgstr "A rendszer kikapcsolása" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "Authentication is required for powering off the system." +msgstr "Hitelesítés szükséges a rendszer kikapcsolásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while other users are logged in" +msgstr "" +"A rendszer kikapcsolása miközben be vannak jelentkezve más felhasználók" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Hitelesítés szükséges a rendszer kikapcsolásához miközben be vannak " +"jelentkezve más felhasználók." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Power off the system while an application asked to inhibit it" +msgstr "" +"A rendszer kikapcsolása miközben egy alkalmazás ennek meggátlását kérte" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Hitelesítés szükséges a rendszer kikapcsolásához miközben egy alkalmazás " +"ennek meggátlását kérte." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system" +msgstr "A rendszer újraindítása" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "Authentication is required for rebooting the system." +msgstr "Hitelesítés szükséges a rendszer újraindításához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while other users are logged in" +msgstr "A rendszer újraindítása mialatt be vannak jelentkezve más felhasználók" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Hitelesítés szükséges a rendszer újraindításához miközben be vannak " +"jelentkezve más felhasználók." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "" +"A rendszer újraindítása miközben egy alkalmazás ennek meggátlását kérte" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Hitelesítés szükséges a rendszer újraindításához miközben egy alkalmazás " +"ennek meggátlását kérte." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system" +msgstr "A rendszer felfüggesztése" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "Authentication is required for suspending the system." +msgstr "Hitelesítés szükséges a rendszer felfüggesztéséhez." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while other users are logged in" +msgstr "" +"A rendszer felfüggesztése mialatt be vannak jelentkezve más felhasználók" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Hitelesítés szükséges a rendszer felfüggesztéséhez miközben be vannak " +"jelentkezve más felhasználók." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "" +"A rendszer felfüggesztése miközben egy alkalmazás ennek meggátlását kérte" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Hitelesítés szükséges a rendszer felfüggesztéséhez miközben egy alkalmazás " +"ennek meggátlását kérte." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system" +msgstr "A rendszer hibernálása" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "Authentication is required for hibernating the system." +msgstr "Hitelesítés szükséges a rendszer hibernálásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while other users are logged in" +msgstr "A rendszer hibernálása mialatt be vannak jelentkezve más felhasználók" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Hitelesítés szükséges a rendszer hibernálásához miközben be vannak " +"jelentkezve más felhasználók." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "A rendszer hibernálása miközben egy alkalmazás ennek meggátlását kérte" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Hitelesítés szükséges a rendszer hibernálásához miközben egy alkalmazás " +"ennek meggátlását kérte." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Manage active sessions, users and seats" +msgstr "Aktív munkamenetek, felhasználók és munkaállomások kezelése" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Hitelesítés szükséges az aktív munkamenetek, felhasználók és munkaállomások " +"kezeléséhez." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Lock or unlock active sessions" +msgstr "Aktív munkamenetek zárolása vagy feloldása" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Hitelesítés szükséges az aktív munkamenetek zárolásához vagy feloldásához." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "A firmware-nek jelezhető, hogy a beállítófelületet bootolja" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Hitelesítés szükséges a firmware-nek jelzéshez, hogy a beállítófelületet " +"bootolja" + +#: ../src/login/org.freedesktop.login1.policy.in.h:57 +msgid "Set a wall message" +msgstr "Falüzenet beállítása" + +#: ../src/login/org.freedesktop.login1.policy.in.h:58 +msgid "Authentication is required to set a wall message" +msgstr "Hitelesítés szükséges a falüzenet beállításához" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Bejelentkezés helyi konténerbe" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "Hitelesítés szükséges a bejelentkezéshez egy helyi konténerbe." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Bejelentkezés a helyi gépre" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Hitelesítés szükséges a bejelentkezéshez a helyi gépre." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Parancsértelmező elérése helyi konténerben" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez helyi konténerben." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Parancsértelmező elérése a helyi gépen" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Hitelesítés szükséges a parancsértelmező eléréséhez a helyi gépen." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Pszeudoterminál elérése helyi konténerben" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez helyi konténerben." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Pszeudoterminál elérése helyi gépen" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "Hitelesítés szükséges a pszeudoterminál eléréséhez a helyi gépen." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Virtuális gépek és konténerek kezelése" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "Hitelesítés szükséges helyi virtuális gépek és konténerek kezeléséhez." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Helyi virtuális gép és konténer lemezképek kezelése" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Hitelesítés szükséges a helyi virtuális gép és konténer lemezképek " +"kezeléséhez." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Rendszeridő beállítása" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Hitelesítés szükséges a rendszeridő beállításához." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Rendszer időzónájának beállítása" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "Hitelesítés szükséges a rendszer időzónájának beállításához." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Az RTC beállítása helyi időzónára vagy UTC-re" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Hitelesítés szükséges az RTC beállításához a helyi időzóna vagy UTC " +"tárolására." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Hálózati időszinkronizáció be- vagy kikapcsolása" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "Hitelesítés szükséges a hálózati időszinkronizáció engedélyezéséhez." + +#: ../src/core/dbus-unit.c:450 +msgid "Authentication is required to start '$(unit)'." +msgstr "Hitelesítés szükséges a következő elindításához: „$(unit)”." + +#: ../src/core/dbus-unit.c:451 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Hitelesítés szükséges a következő leállításához: „$(unit)”." + +#: ../src/core/dbus-unit.c:452 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Hitelesítés szükséges a következő újratöltéséhez: „$(unit)”." + +#: ../src/core/dbus-unit.c:453 ../src/core/dbus-unit.c:454 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Hitelesítés szükséges a következő újraindításához: „$(unit)”." + +#: ../src/core/dbus-unit.c:560 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Hitelesítés szükséges a következő kilövéséhez: „$(unit)”." + +#: ../src/core/dbus-unit.c:590 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Hitelesítés szükséges a következő „sikertelen” állapotának törléséhez: " +"„$(unit)”." + +#: ../src/core/dbus-unit.c:622 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "" +"Hitelesítés szükséges a következő tulajdonságainak beállításához: „$(unit)”." + diff --git a/po/id.po b/po/id.po new file mode 100644 index 00000000..2e06e3bf --- /dev/null +++ b/po/id.po @@ -0,0 +1,624 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Indonesian translation for systemd. +# Andika Triwidada , 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2018-03-04 11:09+0700\n" +"PO-Revision-Date: 2018-03-04 11:12+0700\n" +"Last-Translator: Andika Triwidada \n" +"Language-Team: Indonesian \n" +"Language: id\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.11\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Kirim frasa sandi kembali ke sistem" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Otentikasi diperlukan untuk mengirim frasa sandi yang dimasukkan kembali ke " +"sistem." + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Kelola layanan sistem atau unit lainnya" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Otentikasi diperlukan untuk mengelola layanan sistem atau unit lainnya." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Kelola layanan sistem atau berkas unit" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "Otentikasi diperlukan untuk mengelola layanan sistem atau berkas unit." + +#: src/core/org.freedesktop.systemd1.policy.in:53 +msgid "Set or unset system and service manager environment variables" +msgstr "Atur atau hapus variabel lingkungan manajer layanan dan sistem" + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Otentikasi diperlukan untuk menata atau menghapus variabel lingkungan " +"manajer layanan dan sistem." + +#: src/core/org.freedesktop.systemd1.policy.in:63 +msgid "Reload the systemd state" +msgstr "Muat ulang keadaan systemd" + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Authentication is required to reload the systemd state." +msgstr "Otentikasi diperlukan untuk memuat ulang keadaan systemd." + +#: src/hostname/org.freedesktop.hostname1.policy:22 +msgid "Set host name" +msgstr "Setel nama host" + +#: src/hostname/org.freedesktop.hostname1.policy:23 +msgid "Authentication is required to set the local host name." +msgstr "Otentikasi diperlukan untuk menata nama host lokal." + +#: src/hostname/org.freedesktop.hostname1.policy:32 +msgid "Set static host name" +msgstr "Setel nama host statik" + +#: src/hostname/org.freedesktop.hostname1.policy:33 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Otentikasi diperlukan untuk menata nama host lokal yang dikonfigurasi " +"statik, maupun nama host cantik." + +#: src/hostname/org.freedesktop.hostname1.policy:43 +msgid "Set machine information" +msgstr "Setel informasi mesin" + +#: src/hostname/org.freedesktop.hostname1.policy:44 +msgid "Authentication is required to set local machine information." +msgstr "Otentikasi diperlukan untuk menata informasi mesin lokal." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Impor sebuah image kontainer atau VM" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "Otentikasi diperlukan untuk mengimpor suatu image kontainer atau VM" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Ekspor sebuah image kontainer atau VM" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "Otentikasi diperlukan untuk mengekspor suatu image kontainer atau VM" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Unduh sebuah image kontainer atau VM" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "Otentikasi diperlukan untuk mengunduh suatu image kontainer atau VM" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Setel locale sistem" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "Otentikasi diperlukan untuk menyetel locale sistem." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Setel pengaturan papan tik sistem" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "Otentikasi diperlukan untuk menyetel pengaturan papan tik sistem." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Ijinkan aplikasi untuk mencegah shutdown sistem" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah shutdown sistem." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Ijinkan aplikasi untuk menunda shutdown sistem" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Otentikasi diperlukan bagi suatu aplikasi untuk menunda shutdown sistem." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Ijinkan aplikasi untuk mencegah tidur sistem" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "Otentikasi diperlukan bagi suatu aplikasi untuk menunda tidur sistem." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Ijinkan aplikasi untuk menunda tidur sistem" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "Otentikasi diperlukan bagi suatu aplikasi untuk menunda tidur sistem." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Ijinkan aplikasi mencegah suspensi sistem otomatis" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah suspensi sistem." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "Ijinkan aplikasi mencegah penanganan sistem atas tombol daya" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah penanganan sistem " +"atas tombol daya." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "Ijinkan aplikasi mencegah penanganan sistem atas tombol suspensi" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah penanganan sistem " +"atas tombol suspensi." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "Ijinkan aplikasi mencegah penanganan sistem atas tombol hibernasi" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah penanganan sistem " +"dari tombol hibernasi." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "Ijinkan aplikasi mencegah penanganan sistem atas saklar lid" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Otentikasi diperlukan bagi suatu aplikasi untuk mencegah penanganan sistem " +"atas saklar lid." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "Ijinkan pengguna yang tidak log masuk menjalankan program" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Permintaan eksplisit diperlukan untuk menjalankan program sebagai pengguna " +"yang tidak log masuk." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "Ijinkan pengguna yang tidak log masuk menjalankan program" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Otentikasi diperlukan untuk menjalankan program sebagai pengguna yang tidak " +"log masuk." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Ijinkan mencantolkan perangkat ke seat" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "Otentikasi diperlukan untuk mencantol suatu perangkat ke sebuah seat." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Siram perangkat untuk mendudukkan lampiran" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Otentikasi diperlukan untuk me-reset bagaimana perangkat dicantolkan ke seat." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Matikan daya sistem" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "Otentikasi diperlukan untuk mematikan daya sistem." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "Matikan daya sistem ketika pengguna lain sedang log masuk" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Otentikasi diperlukan untuk mematikan daya sistem ketika pengguna lain " +"sedang log masuk." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Matikan daya sistem ketika sebuah aplikasi meminta untuk mencegahnya" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Otentikasi diperlukan untuk mematikan daya sistem ketika sebuah aplikasi " +"meminta untuk mencegahnya." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Boot ulang sistem" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "Otentikasi diperlukan untuk mem-boot ulang sistem." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "Boot ulang sistem ketika pengguna lain sedang log masuk" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Otentikasi diperlukan untuk mem-boot ulang sistem ketika pengguna lain " +"sedang log masuk." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Boot ulang sistem ketika sebuah aplikasi meminta untuk mencegahnya" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Otentikasi diperlukan untuk mem-boot ulang sistem ketika sebuah aplikasi " +"meminta untuk mencegahnya." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Halt sistem" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "Otentikasi diperlukan untuk meng-halt sistem." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "Halt sistem ketika pengguna lain sedang log masuk" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Otentikasi diperlukan untuk meng-halt sistem ketika pengguna lain sedang log " +"masuk." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Halt sistem ketika sebuah aplikasi meminta untuk mencegahnya" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Otentikasi diperlukan untuk meng-halt sistem ketika sebuah aplikasi meminta " +"untuk mencegahnya." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Suspensikan sistem" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "Otentikasi diperlukan untuk mensuspensi sistem." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "Suspensikan sistem ketika pengguna lain sedang log masuk" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Otentikasi diperlukan untuk mensuspensi sistem ketika pengguna lain sedang " +"log masuk." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Suspensikan sistem ketika sebuah aplikasi meminta untuk mencegahnya" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Otentikasi diperlukan untuk mensuspensi sistem ketika suatu aplikasi meminta " +"untuk mencegahnya." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Hibernasikan sistem" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "Otentikasi diperlukan untuk menghibernasi sistem." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "Hibernasikan sistem ketika pengguna lain sedang log masuk." + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Otentikasi diperlukan untuk menghibernasi sistem ketika pengguna lain sedang " +"log masuk." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Hibernasikan sistem ketika sebuah aplikasi meminta untuk mencegahnya." + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Otentikasi diperlukan untuk menghibernasi sistem ketika sebuah aplikasi " +"meminta mencegahnya." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Kelola seat, pengguna, dan sesi aktif" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "Otentikasi diperlukan untuk mengelola seat, pengguna, dan sesi aktif." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Kunci/buka kunci sesi aktif" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "Otentikasi diperlukan untuk mengunci atau membuka kunci sesi aktif." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "Ijinkan indikasi ke firmware untuk boot ke antar muka penyiapan" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Otentikasi diperlukan untuk mengindikasikan ke firmware agar boot ke " +"antarmuka penyiapan." + +#: src/login/org.freedesktop.login1.policy:351 +msgid "Set a wall message" +msgstr "Setel suatu pesan wall" + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Authentication is required to set a wall message" +msgstr "Otentikasi diperlukan untuk menyetel pesan wall" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Log masuk ke dalam suatu kontainer lokal" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "Otentikasi diperlukan untuk log masuk ke dalam suatu kontainer lokal." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Log masuk ke dalam host lokal" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "Otentikasi diperlukan untuk log masuk ke dalam host lokal." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Dapatkan sebuah shell dalam kontainer lokal" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Otentikasi diperlukan untuk mendapatkan suatu shell dalam sebuah kontainer " +"lokal." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Dapatkan sebuah shell pada host lokal" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Otentikasi diperlukan untuk mendapatkan suatu shell pada host lokal." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Dapatkan sebuah TTY semu dalam suatu kontainer lokal" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Otentikasi diperlukan untuk mendapatkan suatu TTY semu dalam sebuah " +"kontainer lokal." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Dapatkan sebuah TTY semu pada host lokal" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Otentikasi diperlukan untuk mendapatkan suatu TTY semu pada host lokal." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Kelola mesin virtual lokal dan kontainer" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Otentikasi diperlukan untuk mengelola mesin virtual lokal dan kontainer." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Kelola mesin virtual lokal dan image kontainer" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Otentikasi diperlukan untuk mengelola mesin virtual lokal dan image " +"kontainer." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Daftarkan suatu layanan DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Otentikasi diperlukan untuk mendaftarkan suatu layanan DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Cabut pendaftaran suatu layanan DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "Otentikasi diperlukan untuk mencabut pendaftaran suatu layanan DNS-SD" + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Setel waktu sistem" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "Otentikasi diperlukan untuk menyetel waktu sistem." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Setel zona waktu sistem" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "Otentikasi diperlukan untuk menyetel zona waktu sistem." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "Atur RTC ke zona waktu lokal atau UTC" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Otentikasi diperlukan untuk mengendalikan apakah RTC menyimpan waktu UTC " +"atau lokal." + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "Turn network time synchronization on or off" +msgstr "Nyalakan atau matikan penyelarasan waktu jaringan" + +#: src/timedate/org.freedesktop.timedate1.policy:55 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Otentikasi diperlukan untuk mengendalikan apakah sinkronisasi waktu jaringan " +"mesti difungsikan." + +#: src/core/dbus-unit.c:496 +msgid "Authentication is required to start '$(unit)'." +msgstr "Otentikasi diperlukan untuk memulai '$(unit)'." + +#: src/core/dbus-unit.c:497 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Otentikasi diperlukan untuk menghentikan '$(unit)'." + +#: src/core/dbus-unit.c:498 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Otentikasi diperlukan untuk memuat ulang '$(unit)'." + +#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Otentikasi diperlukan untuk memulai ulang '$(unit)'." + +#: src/core/dbus-unit.c:607 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Otentikasi diperlukan untuk mematikan '$(unit)'." + +#: src/core/dbus-unit.c:638 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Otentikasi diperlukan untuk me-reset keadaan \"failed\" dari '$(unit)'." + +#: src/core/dbus-unit.c:671 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Otentikasi diperlukan untuk menata properti pada '$(unit)'." diff --git a/po/it.po b/po/it.po new file mode 100644 index 00000000..1eafe5a6 --- /dev/null +++ b/po/it.po @@ -0,0 +1,728 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Italian translation for systemd package +# Traduzione in italiano per il pacchetto systemd +# Daniele Medri , 2013-2019. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2019-05-05 17:02+0200\n" +"PO-Revision-Date: 2019-05-05 17:13+0200\n" +"Last-Translator: Daniele Medri \n" +"Language-Team: Italian\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.2.1\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Invia la frase segreta (passphrase) al sistema" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Autenticazione richiesta per inviare la frase segreta (passphrase) al " +"sistema." + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Gestisci i servizi o le altre unità di sistema" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Autenticazione richiesta per gestire i servizi o le altre unità di sistema." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Gestisci i file dei servizi o delle unità di sistema" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Autenticazione richiesta per gestire i file dei servizi o delle unità di " +"sistema." + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Configura le variabili d'ambiente per la gestione dei servizi e del sistema" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Autenticazione richiesta per configurare le variabili d'ambiente per la " +"gestione dei servizi e del sistema." + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "Ricarica lo stato di systemd" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "Autenticazione richiesta per riavviare lo stato di sistemd." + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "Configura il nome host" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "Autenticazione richiesta per configurare il nome host locale." + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "Configura il nome host statico" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Autenticazione richiesta per configurare staticamente il nome host locale e " +"il nome host descrittivo." + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "Configura le informazioni sulla macchina" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "" +"Autenticazione richiesta per configurare le informazioni sulla macchina " +"locale." + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "Ottieni UUID del prodotto" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "Autenticazione richiesta per ottenere UUID del prodotto." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Importa un'immagine VM o un container" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "Autenticazione richiesta per importare un'immagine VM o un container" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Esporta un'immagine VM o un container" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "Autenticazione richiesta per esportare un'immagine VM o un container" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Scarica un'immagine VM o un container" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "Autenticazione richiesta per scaricare un'immagine VM o un container" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Configura le impostazioni regionali di sistema" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "" +"Autenticazione richiesta per configurare le impostazioni regionali di " +"sistema." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Configura la tastiera di sistema" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "Autenticazione richiesta per configurare la tastiera di sistema." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Consenti alle applicazioni di inibire lo spegnimento del sistema" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Autenticazione richiesta per un'applicazione per inibire lo spegnimento del " +"sistema." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Consenti alle applicazioni di ritardare lo spegnimento del sistema" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Autenticazione richiesta ad un'applicazione per ritardare lo spegnimento " +"del sistema." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Consenti alle applicazioni di inibire il sistema in pausa" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Autenticazione richiesta ad un'applicazione per inibire il sistema in pausa." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Consenti alle applicazioni di ritardare il sistema in pausa" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Autenticazione richiesta ad un'applicazione per ritardare il sistema in " +"pausa." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "" +"Consenti alle applicazioni di inibire la sospesione automatica del sistema" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Autenticazione richiesta ad un'applicazione per inibire la sospensione " +"automatica del sistema." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Consenti alle applicazioni di inibire la gestione di sistema del tasto" +"accensione" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Autenticazione richiesta per un'applicazione per inibire la gestione di " +"sistema del tasto accensione." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Consenti alle applicazioni di inibire la gestione di sistema del tasto di " +"sospensione" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Autenticazione richiesta ad un'applicazione per inibire la gestione di " +"sistema del tasto di sospensione." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Consenti alle applicazioni di inibire la gestione di sistema del tasto di " +"ibernazione" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Autenticazione richiesta ad un'applicazione per inibire la gestione di " +"sistema del tasto di ibernazione." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Consenti alle applicazioni di inibire la gestione di sistema alla apertura/" +"chiusura del portatile" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Autenticazione richiesta per consentire ad un'applicazione di inibire la " +"gestione di sistema alla apertura/chiusura del portatile." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "Consenti agli utenti non connessi di eseguire programmi" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"E' necessaria un'esplicita richiesta per eseguire programmi come utenti non " +"connessi." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "Consenti agli utenti non connessi di eseguire programmi" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Autenticazione richiesta per consentire agli utenti non connessi di eseguire " +"programmi." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Consenti di collegare dispositivi alle postazioni" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Autenticazione richiesta per collegare un dispositivo ad una postazione." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Scollega i dispositivi dalla postazione" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Autenticazione richiesta per ripristinare come i dispositivi sono collegati " +"alle postazioni." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Spegni il sistema" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "Autenticazione richiesta per spegnere il sistema." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "Spegni il sistema mentre altri utenti sono connessi" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Autenticazione richiesta per spegnere il sistema mentre altri utenti sono " +"connessi." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Spegni il sistema mentre un'applicazione chiede di inibirne l'azione" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Autenticazione richiesta per spegnere il sistema mentre un'applicazione " +"chiede di inibirne l'azione." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Riavvia il sistema" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "Autenticazione richiesta per riavviare il sistema." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "Riavvia il sistema mentre altri utenti sono connessi" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Autenticazione richiesta per riavviare il sistema mentre altri utenti sono " +"connessi." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Riavvia il sistema mentre un'applicazione chiede di inibirne l'azione" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Autenticazione richiesta per riavviare il sistema mentre un'applicazione " +"chiede di inibirne l'azione." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Ferma il sistema" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "Autenticazione richiesta per fermare il sistema." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "Ferma il sistema mentre altri utenti sono connessi" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Autenticazione richiesta per fermare il sistema mentre altri utenti sono " +"connessi." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Ferma il sistema mentre un'applicazione chiede di inibirne l'azione" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Autenticazione richiesta per fermare il sistema mentre un'applicazione " +"chiede di inibirne l'azione." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Sospendi il sistema" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "Autenticazione richiesta per sospendere il sistema." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "Sospendi il sistema mentre altri utenti sono connessi" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Autenticazione richiesta per sospendere il sistema mentre altri utenti sono " +"connessi." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Sospendi il sistema mentre un'applicazione chiede di inibirne l'azione" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Autenticazione richiesta per sospendere il sistema mentre un'applicazione " +"chiede di inibirne l'azione." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Iberna il sistema" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "Autenticazione richiesta per ibernare il sistema." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "Iberna il sistema mentre altri utenti sono connessi" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Autenticazione richiesta per ibernare il sistema mentre altri utenti sono " +"connessi." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Iberna il sistema mentre un'applicazione chiede di inibirne l'azione" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Autenticazione richiesta per ibernare il sistema mentre un'applicazione " +"chiede di inibirne l'azione." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Gestione delle sessioni attive, utenti e postazioni" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Autenticazione richiesta per gestire le sessioni attive, gli utenti e le " +"postazioni." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Blocca/sblocca sessioni attive" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "Autenticazione richiesta per bloccare o sbloccare le sessioni attive." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Set the reboot \"reason\" in the kernel" +msgstr "Indica il \"motivo\" del riavvio nel kernel" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "Authentication is required to set the reboot \"reason\" in the kernel." +msgstr "" +"Autenticazione richiesta per configurare il \"motivo\" del riavvio nel " +"kernel." + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Indicate to the firmware to boot to setup interface" +msgstr "Indicate al firmware di avviare un'interfaccia di configurazione" + +#: src/login/org.freedesktop.login1.policy:353 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Autenticazione richiesta per indicare al firmware l'avvio di un'interfaccia " +"di configurazione." + +#: src/login/org.freedesktop.login1.policy:363 +msgid "Indicate to the boot loader to boot to the boot loader menu" +msgstr "Indicate al boot loader di avviare un menu" + +#: src/login/org.freedesktop.login1.policy:364 +msgid "" +"Authentication is required to indicate to the boot loader to boot to the " +"boot loader menu." +msgstr "" +"Autenticazione richiesta per indicate al boot loader l'avvio di uno " +"specifico menu." + +#: src/login/org.freedesktop.login1.policy:374 +msgid "Indicate to the boot loader to boot a specific entry" +msgstr "Indicare al boot loader di avviare una voce specifica" + +#: src/login/org.freedesktop.login1.policy:375 +msgid "" +"Authentication is required to indicate to the boot loader to boot into a " +"specific boot loader entry." +msgstr "" +"Autenticazione richiesta per indicare al boot loader l'avvio di una " +"specifica voce in elenco." + +#: src/login/org.freedesktop.login1.policy:385 +msgid "Set a wall message" +msgstr "Configura un messaggio per gli utenti" + +#: src/login/org.freedesktop.login1.policy:386 +msgid "Authentication is required to set a wall message" +msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Accedi ad un container locale" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "Autenticazione richiesta per accedere ad un container locale." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Accedi in un host locale" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "Autenticazione richiesta per accedere ad un host locale." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Apri una shell in un container locale" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "Autenticazione richiesta per aprire una shell in un container locale." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Apri una shell in un host locale" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Autenticazione richiesta per aprire una shell in un host locale." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Apri un pseudo TTY in un container locale" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Autenticazione richiesta per aprire un pseudo TTY in un container locale." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Apri un pseudo TTY in un host locale" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "Autenticazione richiesta per aprire un pseudo TTY in un host locale." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Gestisci le virtual machine e i container locali" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Autenticazione richiesta per gestire le virtual machine e i container locali." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Gestisci le immagini locali delle virtual machine e dei container" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Autenticazione richiesta per gestire le immagini delle virtual machine e dei " +"container locali." + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "Ispeziona un'immagine di servizio portabile" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "" +"Autenticazione richiesta per ispezionare un'immagine di servizio portabile." + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "Collega o meno un'immagine di servizio portabile" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "" +"Autenticazione richiesta per collegare o meno un'immagine di servizio " +"portabile." + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "Elimina o modifica un'immagine di servizio portabile" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "" +"Autenticazione richiesta per eliminare o modificare un'immagine di servizio " +"portabile." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Registra un servizio DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Autenticazione richiesta per registrare un servizio DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Annulla la registrazione di un servizio DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "" +"Autenticazione richiesta per annullare la registrazione di un servizio DNS-SD" + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Configura l'orario di sistema" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "Autenticazione richiesta per configurare l'orario di sistema." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Configura il fuso orario di sistema" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "Autenticazione richiesta per configurare il fuso orario di sistema." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "" +"Configura l'orologio di sistema (RTC) al fuso orario locale o al tempo " +"civile (UTC)" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Autenticazione richiesta per verificare se l'orologio di sistema (RTC) è " +"configurato all'orario locale o al tempo civile (UTC)." + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "Abilita o meno la sincronizzazione dell'orario in rete" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Autenticazione richiesta per verificare se la sincronizzazione dell'orario " +"in rete deve essere attivata." + +#: src/core/dbus-unit.c:317 +msgid "Authentication is required to start '$(unit)'." +msgstr "Autenticazione richiesta per avviare '$(unit)'." + +#: src/core/dbus-unit.c:318 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Autenticazione richiesta per fermare '$(unit)'." + +#: src/core/dbus-unit.c:319 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Autenticazione richiesta per ricaricare '$(unit)'." + +#: src/core/dbus-unit.c:320 src/core/dbus-unit.c:321 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Autenticazione richiesta per riavviare '$(unit)'." + +#: src/core/dbus-unit.c:493 +msgid "" +"Authentication is required to send a UNIX signal to the processes of " +"'$(unit)'." +msgstr "" +"Autenticazione richiesta per inviare un segnale UNIX ai processi di " +"'$(unit)'." + +#: src/core/dbus-unit.c:524 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Autenticazione richiesta per riconfigurare lo stato \"fallito\" di '$(unit)'." + +#: src/core/dbus-unit.c:557 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Autenticazione richiesta per configurare le proprietà di '$(unit)'." diff --git a/po/its/polkit.its b/po/its/polkit.its new file mode 100644 index 00000000..1c37e6be --- /dev/null +++ b/po/its/polkit.its @@ -0,0 +1,8 @@ + + + + + diff --git a/po/its/polkit.loc b/po/its/polkit.loc new file mode 100644 index 00000000..c7427ec6 --- /dev/null +++ b/po/its/polkit.loc @@ -0,0 +1,6 @@ + + + + + + diff --git a/po/ja.po b/po/ja.po new file mode 100644 index 00000000..55106f4b --- /dev/null +++ b/po/ja.po @@ -0,0 +1,779 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Japanese translation for systemd. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-21 20:13+0900\n" +"PO-Revision-Date: 2018-10-27 07:41+0900\n" +"Last-Translator: Yu Watanabe \n" +"Language-Team: \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "パスフレーズをシステムに送信" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "パスフレーズをシステムに送信するには認証が必要です。" + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "システムサービスやその他のユニットの管理" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "システムサービスやその他のユニットを管理するには認証が必要です。" + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "システムサービスファイルやその他のユニットファイルの管理" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"システムサービスファイルやその他のユニットファイルを管理するには認証が必要で" +"す。" + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "システムマネージャ環境変数の設定もしくは解除" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "システムマネージャ環境変数を設定もしくは解除するには認証が必要です。" + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "systemdの状態の再読込" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "systemdの状態を再読込するには認証が必要です。" + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "ホスト名の設定" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "ホスト名を設定するには認証が必要です。" + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "静的なホスト名の設定" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "静的なホスト名を設定するには認証が必要です。" + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "マシン情報の設定" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "マシン情報を設定するには認証が必要です。" + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "プロダクトUUIDを取得する" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "プロダクトUUIDを取得するには認証が必要です。" + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "仮想マシンもしくはコンテナイメージの読込" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "仮想マシンもしくはコンテナイメージを読込むには認証が必要です。" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "仮想マシンもしくはコンテナイメージの書出し" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "仮想マシンもしくはコンテナイメージを書出すには認証が必要です。" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "仮想マシンもしくはコンテナイメージのダウンロード" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"仮想マシンもしくはコンテナイメージをダウンロードするには認証が必要です。" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "システムロケールの設定" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "システムロケールを設定するには認証が必要です。" + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "システムキーボードの設定" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "システムキーボードを設定するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "アプリケーションがシステムのシャットダウンを阻害することを許可" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"アプリケーションがシステムのシャットダウンを阻害するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "アプリケーションがシステムのシャットダウンを遅延させることを許可" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"アプリケーションがシステムのシャットダウンを遅延させるには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "アプリケーションがシステムのスリープを阻害することを許可" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "アプリケーションがシステムのスリープを阻害するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "アプリケーションがシステムのスリープを遅延させることを許可" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "アプリケーションがシステムのスリープを遅延させるには許可が必要です。" + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "アプリケーションがシステムの自動的なサスペンドを阻害することを許可" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"アプリケーションがシステムの自動的なサスペンドを阻害するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "アプリケーションが電源ボタンによる動作を阻害することを許可" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "アプリケーションが電源ボタンによる動作を阻害するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "アプリケーションがサスペンドキーによる動作を阻害することを許可" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"アプリケーションがサスペンドキーによる動作を阻害するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "アプリケーションがハイバネートキーによる動作を阻害することを許可" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"アプリケーションがハイバネートキーによる動作を阻害するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "アプリケーションが液晶開閉による動作を阻害することを許可" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "アプリケーションが液晶開閉による動作を阻害するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "ログインしていないユーザがプログラムを実行することを許可" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"ログインしていないユーザがプログラムを実行するには明示的な要求が必要です。" + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "ログインしていないユーザがプログラムを実行することを許可" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "ログインしていないユーザがプログラムを実行するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "シートにデバイスを接続することを許可" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "シートにデバイスを接続するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "デバイスのシートへの接続のリセット" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "デバイスのシートへの接続をリセットするには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "システムの電源を切る" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "システムの電源を切るには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "他のユーザがログインしている状態でシステムの電源を切る" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"他のユーザがログインしている状態でシステムの電源を切るには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "アプリケーションが使用されている状態でシステムの電源を切る" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"アプリケーションが使用されている状態でシステムの電源を切るには認証が必要で" +"す。" + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "システムの再起動" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "システムの再起動には認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "他のユーザがログインしている状態でシステムを再起動する" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"他のユーザがログインしている状態でシステムを再起動するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "アプリケーションが使用されている状態でシステムを再起動する" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"アプリケーションが使用されている状態でシステムを再起動するには認証が必要で" +"す。" + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "システムの停止" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "システムを停止するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "他のユーザがログインしている状態でシステムを停止する" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"他のユーザがログインしている状態でシステムを停止するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "アプリケーションが使用されている状態でシステムを停止する" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"アプリケーションが使用されている状態でシステムを停止するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "システムのサスペンド" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "システムのサスペンドには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "他のユーザがログインしている状態でシステムをサスペンドする" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"他のユーザがログインしている状態でシステムをサスペンドするには認証が必要で" +"す。" + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "アプリケーションが使用されている状態でシステムをサスペンドする" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"アプリケーションが使用されている状態でシステムをサスペンドするには認証が必要" +"です。" + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "システムのハイバネート" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "システムのハイバネートには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "他のユーザがログインしている状態でシステムをハイバネートする" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"他のユーザがログインしている状態でシステムをハイバネートするには認証が必要で" +"す。" + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "アプリケーションが使用されている状態でシステムをハイバネートする" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"アプリケーションが使用されている状態でシステムをハイバネートするには認証が必" +"要です。" + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "アクティブなセッションやユーザ,シートの管理" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "アクティブなセッションやユーザ,シートを管理するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "アクティブなセッションのロックもしくはアンロック" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"アクティブなセッションをロックもしくはアンロックするには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Set the reboot \"reason\" in the kernel" +msgstr "再起動の理由を設定する" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "Authentication is required to set the reboot \"reason\" in the kernel." +msgstr "再起動の理由を設定するには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Indicate to the firmware to boot to setup interface" +msgstr "ファームウェアに「インターフェースの設定を起動」を表示させる" + +#: src/login/org.freedesktop.login1.policy:353 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"ファームウェアに「インターフェースの設定を起動」を表示させるには認証が必要で" +"す。" + +#: src/login/org.freedesktop.login1.policy:363 +msgid "Indicate to the boot loader to boot to the boot loader menu" +msgstr "ブートローダにブートローダメニューを起動するための項目を表示させる。" + +#: src/login/org.freedesktop.login1.policy:364 +msgid "" +"Authentication is required to indicate to the boot loader to boot to the " +"boot loader menu." +msgstr "" +"ブートローダにブートローダメニューを起動するための項目を表示させるには認証が" +"必要です。" + +#: src/login/org.freedesktop.login1.policy:374 +msgid "Indicate to the boot loader to boot a specific entry" +msgstr "ブートローダに特定の項目を表示させる" + +#: src/login/org.freedesktop.login1.policy:375 +msgid "" +"Authentication is required to indicate to the boot loader to boot into a " +"specific boot loader entry." +msgstr "ブートローダに特定の項目を表示させるには認証が必要です。" + +#: src/login/org.freedesktop.login1.policy:385 +msgid "Set a wall message" +msgstr "全ユーザへのメッセージの設定" + +#: src/login/org.freedesktop.login1.policy:386 +msgid "Authentication is required to set a wall message" +msgstr "全ユーザへのメッセージを設定するには認証が必要です。" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "ローカルなコンテナへログイン" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "ローカルなコンテナへログインするには認証が必要です。" + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "ローカルホストへログイン" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "ローカルホストへログインするには認証が必要です。" + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "ローカルなコンテナのシェルを取得" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "ローカルなコンテナのシェルを取得するには認証が必要です。" + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "ローカルホストのシェルを取得" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "ローカルホストのシェルを取得するには認証が必要です。" + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "ローカルなコンテナの仮想TTYを取得" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "ローカルなコンテナの仮想TTYを取得するには認証が必要です。" + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "ローカルホストの仮想TTYを取得する" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "ローカルホストの仮想TTYを取得するには認証が必要です。" + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "ローカルな仮想マシンやコンテナの管理" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "ローカルな仮想マシンやコンテナを管理するには認証が必要です。" + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "ローカルな仮想マシンやコンテナのイメージ管理" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "ローカルな仮想マシンやコンテナのイメージを管理するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:22 +msgid "Set NTP servers" +msgstr "NTPサーバの設定" + +#: src/network/org.freedesktop.network1.policy:23 +msgid "Authentication is required to set NTP servers." +msgstr "NTPサーバを設定するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:33 +#: src/resolve/org.freedesktop.resolve1.policy:44 +msgid "Set DNS servers" +msgstr "DNSサーバの設定" + +#: src/network/org.freedesktop.network1.policy:34 +#: src/resolve/org.freedesktop.resolve1.policy:45 +msgid "Authentication is required to set DNS servers." +msgstr "DNSサーバを設定するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:44 +#: src/resolve/org.freedesktop.resolve1.policy:55 +msgid "Set domains" +msgstr "ドメインの設定" + +#: src/network/org.freedesktop.network1.policy:45 +#: src/resolve/org.freedesktop.resolve1.policy:56 +msgid "Authentication is required to set domains." +msgstr "ドメインを設定するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:55 +#: src/resolve/org.freedesktop.resolve1.policy:66 +msgid "Set default route" +msgstr "デフォルトルートの設定" + +#: src/network/org.freedesktop.network1.policy:56 +#: src/resolve/org.freedesktop.resolve1.policy:67 +msgid "Authentication is required to set default route." +msgstr "デフォルトルートを設定するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:66 +#: src/resolve/org.freedesktop.resolve1.policy:77 +msgid "Enable/disable LLMNR" +msgstr "LLMNRの有効化/無効化" + +#: src/network/org.freedesktop.network1.policy:67 +#: src/resolve/org.freedesktop.resolve1.policy:78 +msgid "Authentication is required to enable or disable LLMNR." +msgstr "LLMNRを有効化もしくは無効化するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:77 +#: src/resolve/org.freedesktop.resolve1.policy:88 +msgid "Enable/disable multicast DNS" +msgstr "マルチキャストDNSの有効化/無効化" + +#: src/network/org.freedesktop.network1.policy:78 +#: src/resolve/org.freedesktop.resolve1.policy:89 +msgid "Authentication is required to enable or disable multicast DNS." +msgstr "マルチキャストDNSを有効化もしくは無効化するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:88 +#: src/resolve/org.freedesktop.resolve1.policy:99 +msgid "Enable/disable DNS over TLS" +msgstr "DNS over TLSの有効化/無効化" + +#: src/network/org.freedesktop.network1.policy:89 +#: src/resolve/org.freedesktop.resolve1.policy:100 +msgid "Authentication is required to enable or disable DNS over TLS." +msgstr "DNS over TLSを有効化もしくは無効化するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:99 +#: src/resolve/org.freedesktop.resolve1.policy:110 +msgid "Enable/disable DNSSEC" +msgstr "DNSSECの有効化/無効化" + +#: src/network/org.freedesktop.network1.policy:100 +#: src/resolve/org.freedesktop.resolve1.policy:111 +msgid "Authentication is required to enable or disable DNSSEC." +msgstr "DNSSECを有効化もしくは無効化するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:110 +#: src/resolve/org.freedesktop.resolve1.policy:121 +msgid "Set DNSSEC Negative Trust Anchors" +msgstr "DNSSEC Negative Trust Anchorsの設定" + +#: src/network/org.freedesktop.network1.policy:111 +#: src/resolve/org.freedesktop.resolve1.policy:122 +msgid "Authentication is required to set DNSSEC Negative Trust Anchors." +msgstr "DNSSEC Negative Trust Anchorsを設定するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:121 +msgid "Revert NTP settings" +msgstr "NTPの設定の破棄" + +#: src/network/org.freedesktop.network1.policy:122 +msgid "Authentication is required to reset NTP settings." +msgstr "NTPの設定を破棄するには認証が必要です。" + +#: src/network/org.freedesktop.network1.policy:132 +msgid "Revert DNS settings" +msgstr "DNSの設定を破棄" + +#: src/network/org.freedesktop.network1.policy:133 +msgid "Authentication is required to reset DNS settings." +msgstr "DNSの設定を破棄するには認証が必要です。" + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "ポータブルサービスイメージの読み込み" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "ポータブルサービスイメージを読み込むには認証が必要です。" + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "ポータブルサービスイメージの接続もしくは切り離し" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "ポータブルサービスイメージを接続もしくは切り離すには認証が必要です。" + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "ポータブルサービスイメージの削除もしくは修正" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "ポータブルサービスイメージを削除もしくは修正するには認証が必要です。" + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "DNS-SDサービスを登録" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "DNS-SDサービスを登録するには認証が必要です。" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "DNS-SDサービスへの登録を解除" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "DNS-SDサービスへの登録を解除するには認証が必要です。" + +#: src/resolve/org.freedesktop.resolve1.policy:132 +msgid "Revert name resolution settings" +msgstr "名前解決の設定の破棄" + +#: src/resolve/org.freedesktop.resolve1.policy:133 +msgid "Authentication is required to reset name resolution settings." +msgstr "名前解決の設定を破棄するには認証が必要です。" + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "システムの時刻設定" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "システムの時刻を設定するには認証が必要です。" + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "システムのタイムゾーンを設定" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "システムのタイムゾーンを設定するには認証が必要です。" + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "ハードウェア時刻をローカルタイムゾーンもしくはUTCに設定" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"ハードウェア時刻をローカルタイムゾーンもしくはUTCに設定するには認証が必要で" +"す。" + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "ネットワーク経由の時刻同期の有効化もしくは無効化" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "ネットワーク経由の時刻同期を有効もしくは無効にするには認証が必要です。" + +#: src/core/dbus-unit.c:354 +msgid "Authentication is required to start '$(unit)'." +msgstr "'$(unit)'を開始するには認証が必要です。" + +#: src/core/dbus-unit.c:355 +msgid "Authentication is required to stop '$(unit)'." +msgstr "'$(unit)'を停止するには認証が必要です。" + +#: src/core/dbus-unit.c:356 +msgid "Authentication is required to reload '$(unit)'." +msgstr "'$(unit)'を再読込するには認証が必要です。" + +#: src/core/dbus-unit.c:357 src/core/dbus-unit.c:358 +msgid "Authentication is required to restart '$(unit)'." +msgstr "'$(unit)'を再起動するには認証が必要です。" + +#: src/core/dbus-unit.c:530 +msgid "" +"Authentication is required to send a UNIX signal to the processes of " +"'$(unit)'." +msgstr "'$(unit)'のプロセスにUNIXシグナルを送るには認証が必要です。" + +#: src/core/dbus-unit.c:561 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "'$(unit)'の「失敗」状態をリセットするには認証が必要です。" + +#: src/core/dbus-unit.c:594 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "'$(unit)'のプロパティを設定するには認証が必要です。" + +#: src/core/dbus-unit.c:703 +msgid "" +"Authentication is required to delete files and directories associated with " +"'$(unit)'." +msgstr "" +"'$(unit)'に関連付けられたファイルやディレクトリの削除には認証が必要です。" diff --git a/po/ko.po b/po/ko.po new file mode 100644 index 00000000..e2805462 --- /dev/null +++ b/po/ko.po @@ -0,0 +1,545 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Korean translation for the systemd. +# Seong-ho Cho , 2015. +# Dongsu Park , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2015-09-25 22:52+0900\n" +"PO-Revision-Date: 2015-11-03 13:19+0100\n" +"Last-Translator: Dongsu Park \n" +"Language-Team: GNOME Korea \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Gtranslator 2.91.7\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Language: ko\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "시스템에 암호문 보내기" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "시스템에 입력한 암호를 보내려면 인증이 필요합니다." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "시스템 서비스 또는 기타 유닛 관리" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "시스템 서비스 또는 기타 유닛을 관리하려면 인증이 필요합니다." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "시스템 서비스 또는 유닛 파일 관리" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "시스템 서비스 또는 유닛 파일을 관리하려면 인증이 필요합니다." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "시스템 및 서비스 관리자 환경 변수 설정 또는 설정 해제" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"시스템 및 서비스 관리자 환경 변수를 설정하거나 설정 해제하려면 인증이 필요합" +"니다." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "systemd 상태 다시 불러오기" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "systemd 상태를 다시 불러오려면 인증이 필요합니다." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "호스트 이름 설정" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "로컬 호스트 이름을 설정하려면 인증이 필요합니다." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "정적 호스트 이름 설정" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"로컬 호스트 이름을 모양새를 갖춘 호스트 이름 처럼 정적으로 설정하려면 인증" +"이 필요합니다." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "머신 정보 설정" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "로컬 머신 정보를 설정하려면 인증이 필요합니다." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "VM 또는 컨테이너의 이미지 가져오기" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "VM 또는 컨테이너의 이미지를 가져오려면 인증이 필요합니다" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "가상 머신 또는 컨테이너의 이미지 내보내기" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "가상 머신 또는 컨테이너의 이미지를 내보내려면 인증이 필요합니다" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "가상머신 또는 컨테이너 이미지 다운로드" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "가상머신 또는 컨테이너 이미지를 다운로드하려면 인증이 필요합니다" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "시스템 로캘 설정" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "시스템 로캘을 설정하려면 인증이 필요합니다." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "시스템 키보드 설정" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "시스템 키보드를 설정하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "프로그램의 시스템 전원 끄기 방지 요청 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "프로그램의 시스템 전원 끄기 방지 요청을 허용하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "프로그램의 시스템 전원 끄기 지연 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "프로그램의 시스템 전원 끄기 지연 동작을 허용하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "프로그램의 시스템 대기 상태 진입 방지 요청 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"프로그램의 시스템 대기 상태 진입 방지 요청을 허용하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "프로그램의 시스템 대기 상태 진입 지연 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"프로그램의 시스템 대기 상태 진입 지연 동작을 허용하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "프로그램의 시스템 자동 절전 상태 진입 방지 요청 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"프로그램의 시스템 자동 절전 상태 진입 방지 요청을 허용하려면 인증이 필요합니" +"다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "프로그램의 시스템 전원 키 처리 방지 요청 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"프로그램의 시스템 전원 키 처리 방지 요청을 허용하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "프로그램의 시스템 절전 키 처리 방지 요청 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"프로그램의 시스템 절전 키 처리 방지 요청을 허용하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "프로그램의 시스템 최대 절전 키 처리 방지 요청 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"프로그램의 시스템 최대 절전 키 처리 방지 요청을 허용하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "프로그램의 시스템 랩톱 덮개 스위치 처리 방지 요청 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"프로그램의 시스템 랩톱 덮개 스위치 처리 방지 요청을 허용하려면 인증이 필요합" +"니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in users to run programs" +msgstr "비 로그인 사용자 프로그램 실행 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "비 로그인 사용자에게 프로그램 실행을 허용하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow attaching devices to seats" +msgstr "시트에 장치 부착 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required for attaching a device to a seat." +msgstr "시트에 장치 부착을 허용하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Flush device to seat attachments" +msgstr "시트로부터 장치 해제 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "시트에 붙인 장치 상태를 초기화하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Power off the system" +msgstr "시스템 끄기" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "Authentication is required for powering off the system." +msgstr "시스템을 끄려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system while other users are logged in" +msgstr "다른 사용자가 로그인 했을 때 시스템 끄기" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "다른 사용자가 로그인 했을 때 시스템 전원을 끄려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while an application asked to inhibit it" +msgstr "프로그램이 시스템을 끄지 못하게 요청할 때 시스템 전원 끄기" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"프로그램이 시스템을 끄지 못하게 요청할 때 시스템 전원을 끄려면 인증이 필요합" +"니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Reboot the system" +msgstr "시스템 다시 시작" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "Authentication is required for rebooting the system." +msgstr "시스템을 다시 시작하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system while other users are logged in" +msgstr "다른 사용자가 로그인 했을 때 시스템 다시 시작" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"다른 사용자가 로그인 했을 때 시스템을 다시 시작하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "프로그램이 시스템을 다시 시작하지 못하게 요청할 때 시스템 다시 시작" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"프로그램이 시스템을 다시 시작하지 못하게 요청할 때 시스템을 다시 시작하려면 " +"인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Suspend the system" +msgstr "시스템 절전 상태 진입" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "Authentication is required for suspending the system." +msgstr "시스템을 절전 상태로 놓으려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system while other users are logged in" +msgstr "다른 사용자가 로그인 했을 때 시스템 절전 상태 진입" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"다른 사용자가 로그인 했을 때 시스템을 절전 상태로 놓으려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "프로그램이 절전 상태 진입을 못하게 요청할 때 시스템 절전 상태 진입" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"프로그램이 절전 상태 진입을 못하게 요청할 때 시스템을 절전 상태로 놓으려면 인" +"증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Hibernate the system" +msgstr "시스템 최대 절전 상태 진입" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "Authentication is required for hibernating the system." +msgstr "시스템을 최대 절전 상태로 놓으려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system while other users are logged in" +msgstr "다른 사용자가 로그인 했을 때 시스템 최대 절전 상태 진입" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"다른 사용자가 로그인 했을 때 시스템을 최대 절전 상태로 놓으려면 인증이 필요합" +"니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "" +"프로그램이 최대 절전 상태 진입을 못하게 요청할 때 시스템 최대 절전 상태 진입" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"프로그램이 최대 절전 상태 진입을 못하게 요청할 때 시스템을 최대 절전 상태로 " +"놓으려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Manage active sessions, users and seats" +msgstr "활성 세션, 사용자, 시트 관리" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "활성 세션, 사용자 시트를 관리하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Lock or unlock active sessions" +msgstr "활성 세션 잠금 또는 잠금 해제" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "활성화 세션을 잠금 또는 잠금 해제하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "설정 화면으로 부팅하도록 펌웨어에게 지시 허용" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "설정 화면으로 부팅하도록 펌웨어에게 지시하려면 인증이 필요합니다." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Set a wall message" +msgstr "wall 메시지 설정" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "Authentication is required to set a wall message" +msgstr "wall 메시지를 설정하려면 인증이 필요합니다" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "로컬 컨테이너 로그인" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "로컬 컨테이너로 로그인하려면 인증이 필요합니다." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "로컬 호스트 로그인" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "로컬 호스트로 로그인하려면 인증이 필요합니다." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "로컬 컨테이너의 쉘 획득" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "로컬 컨테이너에서 쉘을 획득하려면 인증이 필요합니다." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "로컬 호스트 쉘 획득" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "로컬 호스트의 쉘을 획득하려면 인증이 필요합니다." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "로컬 컨테이너에서 의사 TTY 획득" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "로컬 컨테이너에서 의사 TTY를 획득하려면 인증이 필요합니다." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "로컬 호스트에서 유사 TTY 획득" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "로컬 호스트에서 의사 TTY를 획득하려면 인증이 필요합니다." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "로컬 가상 머신 및 컨테이너 관리" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "로컬 가상 머신 및 컨테이너를 관리하려면 인증이 필요합니다." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "로컬 가상 머신 및 컨테이너 이미지 관리" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "로컬 가상 머신 및 컨테이너 이미지를 관리하려면 인증이 필요합니다." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "시스템 시간 설정" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "시스템 시간을 설정하려면 인증이 필요합니다." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "시스템 시간대 설정" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "시스템 시간대를 설정하려면 인증이 필요합니다." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "RTC를 로컬 시간대 또는 UTC로 설정" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"RTC를 로컬 시간 또는 UTC 시간으로 저장할 지 여부를 제어하려면 인증이 필요합니" +"다." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "네트워크 시간 동기화 켜거나 끄기" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "네트워크 시간 동기화의 활성화 여부를 제어하려면 인증이 필요합니다." + +#: ../src/core/dbus-unit.c:428 +msgid "Authentication is required to start '$(unit)'." +msgstr "'$(unit)' 서비스 유닛을 시작하려면 인증이 필요합니다." + +#: ../src/core/dbus-unit.c:429 +msgid "Authentication is required to stop '$(unit)'." +msgstr "'$(unit)' 서비스 유닛을 멈추려면 인증이 필요합니다." + +#: ../src/core/dbus-unit.c:430 +msgid "Authentication is required to reload '$(unit)'." +msgstr "'$(unit)' 서비스 유닛을 다시 불러오려면 인증이 필요합니다." + +#: ../src/core/dbus-unit.c:431 ../src/core/dbus-unit.c:432 +msgid "Authentication is required to restart '$(unit)'." +msgstr "'$(unit)' 서비스 유닛을 다시 시작하려면 인증이 필요합니다." + +#: ../src/core/dbus-unit.c:535 +msgid "Authentication is required to kill '$(unit)'." +msgstr "'$(unit)' 서비스 유닛을 강제로 끝내려면 인증이 필요합니다." + +#: ../src/core/dbus-unit.c:565 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "'$(unit)' 서비스 유닛의 \"실패\" 상태를 되돌리려면 인증이 필요합니다." + +#: ../src/core/dbus-unit.c:597 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "'$(unit)' 서비스 유닛 속성을 설정하려면 인증이 필요합니다." diff --git a/po/lt.po b/po/lt.po new file mode 100644 index 00000000..3790f9c1 --- /dev/null +++ b/po/lt.po @@ -0,0 +1,724 @@ +# Moo, 2018. #zanata +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2019-04-08 15:29+0000\n" +"PO-Revision-Date: 2019-04-08 22:01+0300\n" +"Last-Translator: Moo\n" +"Language-Team: Lithuanian\n" +"Language: lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.2.1\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Siųsti slaptafrazę atgal į sistemą" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Norint siųsti įvestą slaptafrazę atgal į sistemą, reikia nustatyti tapatybę." + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Tvarkyti sistemos tarnybas ar kitus įtaisus" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Norint tvarkyti sistemos tarnybas ar kitus įtaisus, reikia nustatyti " +"tapatybę." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Tvarkyti sistemos tarnybos ar įtaiso failus" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Norint tvarkyti sistemos tarnybos ar įtaiso failus, reikia nustatyti " +"tapatybę." + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Nustatyti ar atšaukti sistemos ir tarnybų tvarkytuvės aplinkos kintamųjų " +"nustatymą" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Norint nustatyti ar atšaukti sistemos ir tarnybų tvarkytuvės aplinkos " +"kintamųjų nustatymą, reikia nustatyti tapatybę." + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "Iš naujo įkelti systemd būseną" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "Norint iš naujo įkelti systemd būseną, reikia patvirtinti tapatybę." + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "Nustatyti serverio pavadinimą" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "" +"Norint nustatyti vietinio serverio pavadinimą, reikia nustatyti tapatybę." + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "Nustatyti statinį serverio pavadinimą" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Norint nustatyti statiškai sukonfigūruotą serverio pavadinimą, o taip pat " +"lengvai įsimenamą serverio pavadinimą, reikia nustatyti tapatybę." + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "Nustatyti kompiuterio informaciją" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "Norint nustatyti kompiuterio informaciją, reikia nustatyti tapatybę." + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "Gauti produkto UUID" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "Norint gauti produkto UUID, reikia nustatyti tapatybę." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Importuoti VM ar konteinerio atvaizdį" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Norint importuoti VM ar konteinerio atvaizdį, reikia nustatyti tapatybę" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Eksportuoti VM ar konteinerio atvaizdį" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Norint eksportuoti VM ar konteinerio atvaizdį, reikia nustatyti tapatybę" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Atsisiųsti VM ar konteinerio atvaizdį" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Norint atsisiųsti VM ar konteinerio atvaizdį, reikia nustatyti tapatybę" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Nustatyti sistemos lokalę" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "Norint nustatyti sistemos lokalę, reikia nustatyti tapatybę." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Nustatyti sistemos klaviatūros nustatymus" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Norint nustatyti sistemos klaviatūros nustatymus, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Leisti programoms sulaikyti sistemos išjungimą" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Norint leisti programai sulaikyti sistemos išjungimą, reikia nustatyti " +"tapatybę." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Leisti programoms atidėti sistemos išjungimą" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Norint leisti programai atidėti sistemos išjungimą, reikia nustatyti " +"tapatybę." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Leisti programoms sulaikyti sistemos miegą" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Norint leisti programai sulaikyti sistemos miegą, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Leisti programoms atidėti sistemos miegą" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Norint leisti programai atidėti sistemos miegą, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Leisti programoms sulaikyti automatinį sistemos pristabdymą" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Norint leisti programai sulaikyti automatinį sistemos pristabdymą, reikia " +"nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "Leisti programoms sulaikyti maitinimo rakto sisteminį apdorojimą" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Norint leisti programai sulaikyti maitinimo rakto sisteminį apdorojimą, " +"reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "Leisti programoms sulaikyti pristabdymo rakto sisteminį apdorojimą" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Norint leisti programai sulaikyti pristabdymo rakto sisteminį apdorojimą, " +"reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "Leisti programoms sulaikyti užmigdymo rakto sisteminį apdorojimą" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Norint leisti programai sulaikyti užmigdymo rakto sisteminį apdorojimą, " +"reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "Leisti programoms sulaikyti dangčio perjungiklio sisteminį apdorojimą" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Norint leisti programai sulaikyti dangčio perjungiklio sisteminį apdorojimą, " +"reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "Leisti neprisijungusiam naudotojui vykdyti programas" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Norint vykdyti programas kaip neprisijungusiam naudotojui, reikia aiškiai " +"išreikštos užklausos." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "Leisti neprisijungusiems naudotojams vykdyti programas" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Norint vykdyti programas kaip neprisijungusiems naudotojams, reikia " +"nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Leisti prijungti įrenginius prie darbo vietų" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Norint prijungti įrenginį prie darbo vietos, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Išvalyti įrenginių prijungimus prie darbo vietų" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Norint atstatyti tai, kaip įrenginiai yra prijungti prie darbo vietų, reikia " +"nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Išjungti sistemos maitinimą" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "Norint išjungti sistemos maitinimą, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "Išjungti sistemos maitinimą nepaisant kitų prisijungusių naudotojų" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Norint išjungti sistemos maitinimą nepaisant kitų prisijungusių naudotojų, " +"reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Išjungti sistemos maitinimą, nors programa paprašė tai sulaikyti" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Norint išjungti sistemos maitinimą, nepaisant to, kad programa paprašė tai " +"sulaikyti, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Paleisti sistemą iš naujo" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "Norint paleisti sistemą iš naujo, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "Paleisti sistemą iš naujo nepaisant kitų prisijungusių naudotojų" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Norint paleisti sistemą iš naujo nepaisant kitų prisijungusių naudotojų, " +"reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Paleisti sistemą iš naujo, nors programa paprašė tai sulaikyti" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Norint paleisti sistemą iš naujo, nepaisant to, kad programa paprašė tai " +"sulaikyti, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Stabdyti sistemą" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "Norint stabdyti sistemą, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "Stabdyti sistemą nepaisant kitų prisijungusių naudotojų" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Norint stabdyti sistemą nepaisant kitų prisijungusių naudotojų, reikia " +"nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Stabdyti sistemą, nors programa paprašė tai sulaikyti" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Norint stabdyti sistemą, nepaisant to, kad programa paprašė tai sulaikyti, " +"reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Pristabdyti sistemą" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "Norint pristabdyti sistemą, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "Pristabdyti sistemą nepaisant kitų prisijungusių naudotojų" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Norint pristabdyti sistemą nepaisant kitų prisijungusių naudotojų, reikia " +"nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Pristabdyti sistemą, nors programa paprašė tai sulaikyti" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Norint pristabdyti sistemą, nepaisant to, kad programa paprašė tai " +"sulaikyti, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Užmigdyti sistemą" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "Norint užmigdyti sistemą, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "Užmigdyti sistemą nepaisant kitų prisijungusių naudotojų" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Norint užmigdyti sistemą nepaisant kitų prisijungusių naudotojų, reikia " +"nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Užmigdyti sistemą, nors programa paprašė tai sulaikyti" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Norint užmigdyti sistemą, nepaisant to, kad programa paprašė tai sulaikyti, " +"reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Tvarkyti aktyvius seansus, naudotojus ir darbo vietas" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Norint tvarkyti aktyvius seansus, naudotojus ir darbo vietas, reikia " +"nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Užrakinti ar atrakinti aktyvius seansus" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Norint užrakinti ar atrakinti aktyvius seansus, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Set the reboot \"reason\" in the kernel" +msgstr "Nustatyti paleidimo iš naujo \"priežastį\" branduolyje" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "Authentication is required to set the reboot \"reason\" in the kernel." +msgstr "" +"Norint nustatyti paleidimo iš naujo \"priežastį\" branduolyje, reikia " +"nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Indicate to the firmware to boot to setup interface" +msgstr "Nurodyti programinei aparatinei įrangai pasileisti į sąrankos sąsają" + +#: src/login/org.freedesktop.login1.policy:353 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Norint nurodyti programinei aparatinei įrangai pasileisti į sąrankos sąsają, " +"reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:363 +msgid "Indicate to the boot loader to boot to the boot loader menu" +msgstr "Nurodyti pradiniam įkėlikliui paleisti pradinio įkėliklio meniu" + +#: src/login/org.freedesktop.login1.policy:364 +msgid "" +"Authentication is required to indicate to the boot loader to boot to the " +"boot loader menu." +msgstr "" +"Norint nurodyti pradiniam įkėlikliui paleisti pradinio įkėliklio meniu, " +"reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:374 +msgid "Indicate to the boot loader to boot a specific entry" +msgstr "Nurodyti pradiniam įkėlikliui paleisti tam tikrą įrašą" + +#: src/login/org.freedesktop.login1.policy:375 +msgid "" +"Authentication is required to indicate to the boot loader to boot into a " +"specific boot loader entry." +msgstr "" +"Norint nurodyti pradiniam įkėlikliui paleisti tam tikrą pradinio įkėliklio " +"įrašą, reikia nustatyti tapatybę." + +#: src/login/org.freedesktop.login1.policy:385 +msgid "Set a wall message" +msgstr "Nustatyti sienos pranešimą" + +#: src/login/org.freedesktop.login1.policy:386 +msgid "Authentication is required to set a wall message" +msgstr "Norint nustatyti sienos pranešimą, reikia nustatyti tapatybę" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Prisijungti prie vietinio konteinerio" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "" +"Norint prisijungti prie vietinio konteinerio, reikia nustatyti tapatybę." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Prisijungti į vietinį serverį" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "Norint prisijungti į vietinį serverį, reikia nustatyti tapatybę." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Įgyti apvalkalą vietiniame konteineryje" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Norint įgyti apvalkalą vietiniame konteineryje, reikia nustatyti tapatybę." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Įgyti apvalkalą vietiniame serveryje" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Norint įgyti apvalkalą vietiniame serveryje, reikia nustatyti tapatybę." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Įgyti pseudo TTY vietiniame konteineryje" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Norint įgyti pseudo TTY vietiniame konteineryje, reikia nustatyti tapatybę." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Įgyti pseudo TTY vietiniame serveryje" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Norint įgyti pseudo TTY vietiniame serveryje, reikia nustatyti tapatybę." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Tvarkyti vietines virtualiąsias mašinas ir konteinerius" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Norint tvarkyti vietines virtualiąsias mašinas ir konteinerius, reikia " +"nustatyti tapatybę." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Tvarkyti vietinę virtualiąją mašiną ir konteinerio atvaizdžius" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Norint tvarkyti vietinę virtualiąją mašiną ir konteinerio atvaizdžius, " +"reikia nustatyti tapatybę." + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "Išnagrinėti perkeliamos tarnybos atvaizdį" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "" +"Norint išnagrinėti perkeliamos tarnybos atvaizdį, reikia nustatyti tapatybę." + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "Prijungti ar atskirti perkeliamos tarnybos atvaizdį" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "" +"Norint prijungti ar atskirti perkeliamos tarnybos atvaizdį, reikia nustatyti " +"tapatybę." + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "Ištrinti ar modifikuoti perkeliamos tarnybos atvaizdį" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "" +"Norint ištrinti ar modifikuoti perkeliamos tarnybos atvaizdį, reikia " +"nustatyti tapatybę." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Registruoti DNS-SD tarnybą" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Norint registruoti DNS-SD tarnybą, reikia nustatyti tapatybę" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Išregistruoti DNS-SD tarnybą" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "Norint išregistruoti DNS-SD tarnybą, reikia nustatyti tapatybę" + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Nustatyti sistemos laiką" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "Norint nustatyti sistemos laiką, reikia nustatyti tapatybę." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Nustatyti sistemos laiko juostą" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "Norint nustatyti sistemos laiko juostą, reikia nustatyti tapatybę." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "" +"Nustatyti tikrojo laiko daviklį (RTC) į vietinę laiko juostą ar suderintąjį " +"pasaulinį laiką (UTC)" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Norint valdyti ar tikrojo laiko daviklis (RTC) atmintyje saugos vietinį, ar " +"suderintąjį pasaulinį laiką (UTC), reikia nustatyti tapatybę." + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "Įjungti ar išjungti tinklo laiko sinchronizavimą" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Norint valdyti ar tinklo laiko sinchronizavimas turėtų būti įjungtas, reikia " +"nustatyti tapatybę." + +#: src/core/dbus-unit.c:316 +msgid "Authentication is required to start '$(unit)'." +msgstr "Norint paleisti \"$(unit)\", reikia nustatyti tapatybę." + +#: src/core/dbus-unit.c:317 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Norint stabdyti \"$(unit)\", reikia nustatyti tapatybę." + +#: src/core/dbus-unit.c:318 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Norint įkelti \"$(unit)\" iš naujo, reikia nustatyti tapatybę." + +#: src/core/dbus-unit.c:319 src/core/dbus-unit.c:320 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Norint paleisti \"$(unit)\" iš naujo, reikia nustatyti tapatybę." + +#: src/core/dbus-unit.c:492 +msgid "" +"Authentication is required to send a UNIX signal to the processes of " +"'$(unit)'." +msgstr "" +"Norint siųsti UNIX signalą į \"$(unit)\" procesus, reikia nustatyti tapatybę." + +#: src/core/dbus-unit.c:523 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Norint atstatyti \"$(unit)\" įtaiso \"failed\" būseną, reikia nustatyti " +"tapatybę." + +#: src/core/dbus-unit.c:556 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Norint nustatyti \"$(unit)\" savybes, reikia nustatyti tapatybę." + +#~ msgid "Authentication is required to kill '$(unit)'." +#~ msgstr "Norint nutraukti \"$(unit)\", reikia nustatyti tapatybę." diff --git a/po/meson.build b/po/meson.build new file mode 100644 index 00000000..3611ac90 --- /dev/null +++ b/po/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +i18n = import('i18n') +i18n.gettext(meson.project_name(), + preset : 'glib', + data_dirs : '.') diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 00000000..6441eb78 --- /dev/null +++ b/po/pl.po @@ -0,0 +1,887 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Polish translation for systemd. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2019-10-26 14:02+0000\n" +"PO-Revision-Date: 2019-10-26 16:05+0200\n" +"Last-Translator: Piotr Drąg \n" +"Language-Team: Polish \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Wysłanie hasła z powrotem do systemu" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Wymagane jest uwierzytelnienie, aby wysłać podane hasło z powrotem do " +"systemu." + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Zarządzanie usługami lub innymi jednostkami systemu" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zarządzać usługami lub innymi " +"jednostkami systemu." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Zarządzanie plikami usług lub jednostek systemu" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zarządzać plikami usług lub jednostek " +"systemu." + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Ustawienie lub usunięcie zmiennych środowiskowych menedżera systemu i usług" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ustawić lub usunąć zmienne środowiskowe " +"menedżera systemu i usług." + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "Ponowne wczytanie stanu systemd" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "Wymagane jest uwierzytelnienie, aby ponownie wczytać stan systemd." + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "Ustawienie nazwy komputera" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "Wymagane jest uwierzytelnienie, aby ustawić nazwę lokalnego komputera." + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "Ustawienie statycznej nazwy komputera" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ustawić statycznie skonfigurowaną nazwę " +"lokalnego komputera, a także jego nazwę czytelną dla człowieka." + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "Ustawienie informacji o komputerze" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ustawić informacje o lokalnym komputerze." + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "Uzyskanie UUID produktu" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "Wymagane jest uwierzytelnienie, aby uzyskać UUID produktu." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Import obrazu maszyny wirtualnej lub kontenera" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Wymagane jest uwierzytelnienie, aby zaimportować obraz maszyny wirtualnej " +"lub kontenera" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Eksport obrazu maszyny wirtualnej lub kontenera" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Wymagane jest uwierzytelnienie, aby wyeksportować obraz maszyny wirtualnej " +"lub kontenera" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Pobranie obrazu maszyny wirtualnej lub kontenera" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Wymagane jest uwierzytelnienie, aby pobrać obraz maszyny wirtualnej lub " +"kontenera" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Ustawienie lokalizacji systemu" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "Wymagane jest uwierzytelnienie, aby ustawić lokalizację systemu." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Ustawienie klawiatury systemu" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "Wymagane jest uwierzytelnienie, aby ustawić klawiaturę systemu." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Zezwolenie programom na wstrzymywanie wyłączenia systemu" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "Program wymaga uwierzytelnienia, aby wstrzymać wyłączenie systemu." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Zezwolenie programom na opóźnienie wyłączenia systemu" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "Program wymaga uwierzytelnienia, aby opóźnić wyłączenie systemu." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Zezwolenie programom na wstrzymanie uśpienia systemu" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "Program wymaga uwierzytelnienia, aby wstrzymać uśpienie systemu." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Zezwolenie programom na opóźnienie uśpienia systemu" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "Program wymaga uwierzytelnienia, aby opóźnić uśpienie systemu." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Zezwolenie programom na wstrzymanie automatycznego uśpienia systemu" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Program wymaga uwierzytelnienia, aby wstrzymać automatyczne uśpienie systemu." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Zezwolenie programom na wstrzymanie obsługi klawisza zasilania przez system" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza zasilania " +"przez system." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Zezwolenie programom na wstrzymanie obsługi klawisza uśpienia przez system" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza uśpienia " +"przez system." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Zezwolenie programom na wstrzymanie obsługi klawisza hibernacji przez system" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Program wymaga uwierzytelnienia, aby wstrzymać obsługę klawisza hibernacji " +"przez system." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Zezwolenie programom na wstrzymanie obsługi przełącznika pokrywy przez system" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Program wymaga uwierzytelnienia, aby wstrzymać obsługę przełącznika pokrywy " +"przez system." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "Zezwolenie niezalogowanemu użytkownikowi na uruchamianie programów" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Wymagane jest bezpośrednie żądanie, aby uruchamiać programy jako " +"niezalogowany użytkownik." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "Zezwolenie niezalogowanym użytkownikom na uruchamianie programów" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Wymagane jest uwierzytelnienie, aby uruchamiać programy jako niezalogowany " +"użytkownik." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Zezwolenie na podłączanie urządzeń do stanowisk" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Wymagane jest uwierzytelnienie, aby podłączyć urządzenie do stanowiska." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Usunięcie podłączenia urządzeń do stanowisk" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ponownie ustawić sposób podłączenia " +"urządzeń do stanowisk." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Wyłączenie systemu" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "Wymagane jest uwierzytelnienie, aby wyłączyć system." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "Wyłączenie systemu, kiedy są zalogowani inni użytkownicy" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy są zalogowani " +"inni użytkownicy." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Wyłączenie systemu, kiedy program zażądał jego wstrzymania" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Wymagane jest uwierzytelnienie, aby wyłączyć system, kiedy program zażądał " +"jego wstrzymania." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Ponowne uruchomienie systemu" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "Wymagane jest uwierzytelnienie, aby ponownie uruchomić system." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "Ponowne uruchomienie systemu, kiedy są zalogowani inni użytkownicy" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy są " +"zalogowani inni użytkownicy." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Ponowne uruchomienie systemu, kiedy program zażądał jego wstrzymania" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ponownie uruchomić system, kiedy program " +"zażądał jego wstrzymania." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Zatrzymanie systemu" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać system." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "Zatrzymanie systemu, kiedy są zalogowani inni użytkownicy" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zatrzymać system, kiedy są zalogowani " +"inni użytkownicy." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Zatrzymanie systemu, kiedy program zażądał jego wstrzymania" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zatrzymać system, kiedy program zażądał " +"jego wstrzymania." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Uśpienie systemu" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "Wymagane jest uwierzytelnienie, aby uśpić system." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "Uśpienie systemu, kiedy są zalogowani inni użytkownicy" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Wymagane jest uwierzytelnienie, aby uśpić system, kiedy są zalogowani inni " +"użytkownicy." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Uśpienie systemu, kiedy program zażądał jego wstrzymania" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Wymagane jest uwierzytelnienie, aby uśpić system, kiedy program zażądał jego " +"wstrzymania." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Hibernacja systemu" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "Wymagane jest uwierzytelnienie, aby zahibernować system." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "Hibernacja systemu, kiedy są zalogowani inni użytkownicy" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy są zalogowani " +"inni użytkownicy." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Hibernacja systemu, kiedy program zażądał jej wstrzymania" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zahibernować system, kiedy program " +"zażądał jej wstrzymania." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Zarządzanie aktywnymi sesjami, użytkownikami i stanowiskami" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zarządzać aktywnymi sesjami, " +"użytkownikami i stanowiskami." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Zablokowanie lub odblokowanie aktywnych sesji" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zablokować lub odblokować aktywne sesje." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Set the reboot \"reason\" in the kernel" +msgstr "Ustawienie przyczyny ponownego uruchomienia w jądrze" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "Authentication is required to set the reboot \"reason\" in the kernel." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ustawić przyczynę ponownego uruchomienia " +"w jądrze." + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Indicate to the firmware to boot to setup interface" +msgstr "Wskazanie oprogramowaniu sprzętowemu, aby uruchomić interfejs ustawień" + +#: src/login/org.freedesktop.login1.policy:353 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Wymagane jest uwierzytelnienie, aby wskazać oprogramowaniu sprzętowemu, że " +"należy uruchomić interfejs ustawień." + +#: src/login/org.freedesktop.login1.policy:363 +msgid "Indicate to the boot loader to boot to the boot loader menu" +msgstr "Wskazanie programowi startowemu, aby uruchomić jego menu" + +#: src/login/org.freedesktop.login1.policy:364 +msgid "" +"Authentication is required to indicate to the boot loader to boot to the " +"boot loader menu." +msgstr "" +"Wymagane jest uwierzytelnienie, aby wskazać programowi startowemu, że należy " +"uruchomić jego menu." + +#: src/login/org.freedesktop.login1.policy:374 +msgid "Indicate to the boot loader to boot a specific entry" +msgstr "Wskazanie programowi startowemu, aby uruchomić podany wpis" + +#: src/login/org.freedesktop.login1.policy:375 +msgid "" +"Authentication is required to indicate to the boot loader to boot into a " +"specific boot loader entry." +msgstr "" +"Wymagane jest uwierzytelnienie, aby wskazać programowi startowemu, że należy " +"uruchomić podany wpis." + +#: src/login/org.freedesktop.login1.policy:385 +msgid "Set a wall message" +msgstr "Ustawienie komunikatu wall" + +#: src/login/org.freedesktop.login1.policy:386 +msgid "Authentication is required to set a wall message" +msgstr "Wymagane jest uwierzytelnienie, aby ustawić komunikat wall" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Logowanie do lokalnego kontenera" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zalogować się do lokalnego kontenera." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Logowanie do lokalnego komputera" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zalogować się do lokalnego komputera." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Uzyskanie powłoki w lokalnym kontenerze" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Wymagane jest uwierzytelnienie, aby uzyskać powłokę w lokalnym kontenerze." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Uzyskanie powłoki na lokalnym komputerze" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Wymagane jest uwierzytelnienie, aby uzyskać powłokę na lokalnym komputerze." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Uzyskanie pseudo-TTY w lokalnym kontenerze" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Wymagane jest uwierzytelnienie, aby uzyskać pseudo-TTY w lokalnym kontenerze." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Uzyskanie pseudo-TTY na lokalnym komputerze" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Wymagane jest uwierzytelnienie, aby uzyskać pseudo-TTY na lokalnym " +"komputerze." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Zarządzanie lokalnymi maszynami wirtualnymi i kontenerami" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zarządzać lokalnymi maszynami " +"wirtualnymi i kontenerami." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Zarządzanie lokalnymi obrazami maszyn wirtualnych i kontenerów" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Wymagane jest uwierzytelnienie, aby zarządzać lokalnymi obrazami maszyn " +"wirtualnych i kontenerów." + +#: src/network/org.freedesktop.network1.policy:22 +msgid "Set NTP servers" +msgstr "Ustawienie serwerów NTP" + +#: src/network/org.freedesktop.network1.policy:23 +msgid "Authentication is required to set NTP servers." +msgstr "Wymagane jest uwierzytelnienie, aby ustawić serwery NTP." + +#: src/network/org.freedesktop.network1.policy:33 +#: src/resolve/org.freedesktop.resolve1.policy:44 +msgid "Set DNS servers" +msgstr "Ustawienie serwerów DNS" + +#: src/network/org.freedesktop.network1.policy:34 +#: src/resolve/org.freedesktop.resolve1.policy:45 +msgid "Authentication is required to set DNS servers." +msgstr "Wymagane jest uwierzytelnienie, aby ustawić serwery DNS." + +#: src/network/org.freedesktop.network1.policy:44 +#: src/resolve/org.freedesktop.resolve1.policy:55 +msgid "Set domains" +msgstr "Ustawienie domen" + +#: src/network/org.freedesktop.network1.policy:45 +#: src/resolve/org.freedesktop.resolve1.policy:56 +msgid "Authentication is required to set domains." +msgstr "Wymagane jest uwierzytelnienie, aby ustawić domeny." + +#: src/network/org.freedesktop.network1.policy:55 +#: src/resolve/org.freedesktop.resolve1.policy:66 +msgid "Set default route" +msgstr "Ustawienie domyślnej trasy" + +#: src/network/org.freedesktop.network1.policy:56 +#: src/resolve/org.freedesktop.resolve1.policy:67 +msgid "Authentication is required to set default route." +msgstr "Wymagane jest uwierzytelnienie, aby ustawić domyślną trasę." + +#: src/network/org.freedesktop.network1.policy:66 +#: src/resolve/org.freedesktop.resolve1.policy:77 +msgid "Enable/disable LLMNR" +msgstr "Włączenie/wyłączenie LLMNR" + +#: src/network/org.freedesktop.network1.policy:67 +#: src/resolve/org.freedesktop.resolve1.policy:78 +msgid "Authentication is required to enable or disable LLMNR." +msgstr "Wymagane jest uwierzytelnienie, aby włączyć lub wyłączyć LLMNR." + +#: src/network/org.freedesktop.network1.policy:77 +#: src/resolve/org.freedesktop.resolve1.policy:88 +msgid "Enable/disable multicast DNS" +msgstr "Włączenie/wyłączenie multikastowego DNS" + +#: src/network/org.freedesktop.network1.policy:78 +#: src/resolve/org.freedesktop.resolve1.policy:89 +msgid "Authentication is required to enable or disable multicast DNS." +msgstr "" +"Wymagane jest uwierzytelnienie, aby włączyć lub wyłączyć multikastowe DNS." + +#: src/network/org.freedesktop.network1.policy:88 +#: src/resolve/org.freedesktop.resolve1.policy:99 +msgid "Enable/disable DNS over TLS" +msgstr "Włączenie/wyłączenie DNS przez TLS" + +#: src/network/org.freedesktop.network1.policy:89 +#: src/resolve/org.freedesktop.resolve1.policy:100 +msgid "Authentication is required to enable or disable DNS over TLS." +msgstr "" +"Wymagane jest uwierzytelnienie, aby włączyć lub wyłączyć DNS przez TLS." + +#: src/network/org.freedesktop.network1.policy:99 +#: src/resolve/org.freedesktop.resolve1.policy:110 +msgid "Enable/disable DNSSEC" +msgstr "Włączenie/wyłączenie DNSSEC" + +#: src/network/org.freedesktop.network1.policy:100 +#: src/resolve/org.freedesktop.resolve1.policy:111 +msgid "Authentication is required to enable or disable DNSSEC." +msgstr "Wymagane jest uwierzytelnienie, aby włączyć lub wyłączyć DNSSEC." + +#: src/network/org.freedesktop.network1.policy:110 +#: src/resolve/org.freedesktop.resolve1.policy:121 +msgid "Set DNSSEC Negative Trust Anchors" +msgstr "Ustawienie negatywnych kotwic zaufania DNSSEC" + +#: src/network/org.freedesktop.network1.policy:111 +#: src/resolve/org.freedesktop.resolve1.policy:122 +msgid "Authentication is required to set DNSSEC Negative Trust Anchors." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ustawić negatywne kotwice zaufania " +"DNSSEC." + +#: src/network/org.freedesktop.network1.policy:121 +msgid "Revert NTP settings" +msgstr "Przywrócenie ustawień NTP" + +#: src/network/org.freedesktop.network1.policy:122 +msgid "Authentication is required to reset NTP settings." +msgstr "Wymagane jest uwierzytelnienie, aby przywrócić ustawienia NTP." + +#: src/network/org.freedesktop.network1.policy:132 +msgid "Revert DNS settings" +msgstr "Przywrócenie ustawień DNS" + +#: src/network/org.freedesktop.network1.policy:133 +msgid "Authentication is required to reset DNS settings." +msgstr "Wymagane jest uwierzytelnienie, aby przywrócić ustawienia DNS." + +#: src/network/org.freedesktop.network1.policy:143 +msgid "Renew dynamic addresses" +msgstr "Odnowienie adresów dynamicznych" + +#: src/network/org.freedesktop.network1.policy:144 +msgid "Authentication is required to renew dynamic addresses." +msgstr "Wymagane jest uwierzytelnienie, aby odnowić adresy dynamiczne." + +#: src/network/org.freedesktop.network1.policy:154 +msgid "Reload network settings" +msgstr "Ponowne wczytanie ustawień sieci" + +#: src/network/org.freedesktop.network1.policy:155 +msgid "Authentication is required to reload network settings." +msgstr "Wymagane jest uwierzytelnienie, aby ponownie wczytać ustawienia sieci." + +#: src/network/org.freedesktop.network1.policy:165 +msgid "Reconfigure network interface" +msgstr "Ponowna konfiguracja interfejsu sieciowego" + +#: src/network/org.freedesktop.network1.policy:166 +msgid "Authentication is required to reconfigure network interface." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ponownie skonfigurować interfejs " +"sieciowy." + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "Badanie obrazu przenośnej usługi" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "Wymagane jest uwierzytelnienie, aby zbadać obraz przenośnej usługi." + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "Podłączenie lub odłączenie obrazu przenośnej usługi" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "" +"Wymagane jest uwierzytelnienie, aby podłączyć lub odłączyć obraz przenośnej " +"usługi." + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "Usunięcie lub modyfikacja obrazu przenośnej usługi" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "" +"Wymagane jest uwierzytelnienie, aby usunąć lub zmodyfikować obraz przenośnej " +"usługi." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Rejestracja usługi DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Wymagane jest uwierzytelnienie, aby zarejestrować usługę DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Wyrejestrowanie usługi DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "Wymagane jest uwierzytelnienie, aby wyrejestrować usługę DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:132 +msgid "Revert name resolution settings" +msgstr "Przywrócenie ustawień rozwiązywania nazw" + +#: src/resolve/org.freedesktop.resolve1.policy:133 +msgid "Authentication is required to reset name resolution settings." +msgstr "" +"Wymagane jest uwierzytelnienie, aby przywrócić ustawienia rozwiązywania nazw." + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Ustawienie czasu systemu" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "Wymagane jest uwierzytelnienie, aby ustawić czas systemu." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Ustawienie strefy czasowej systemu" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "Wymagane jest uwierzytelnienie, aby ustawić strefę czasową systemu." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "Ustawienie RTC na lokalną strefę czasową lub strefę UTC" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Wymagane jest uwierzytelnienie, aby kontrolować, czy RTC przechowuje czas " +"lokalny lub czas UTC." + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "Włączenie lub wyłączenie synchronizacji czasu przez sieć" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Wymagane jest uwierzytelnienie, aby kontrolować, czy włączyć synchronizację " +"czasu przez sieć." + +#: src/core/dbus-unit.c:354 +msgid "Authentication is required to start '$(unit)'." +msgstr "Wymagane jest uwierzytelnienie, aby uruchomić jednostkę „$(unit)”." + +#: src/core/dbus-unit.c:355 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Wymagane jest uwierzytelnienie, aby zatrzymać jednostkę „$(unit)”." + +#: src/core/dbus-unit.c:356 +msgid "Authentication is required to reload '$(unit)'." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ponownie wczytać jednostkę „$(unit)”." + +#: src/core/dbus-unit.c:357 src/core/dbus-unit.c:358 +msgid "Authentication is required to restart '$(unit)'." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ponownie uruchomić jednostkę „$(unit)”." + +#: src/core/dbus-unit.c:530 +msgid "" +"Authentication is required to send a UNIX signal to the processes of " +"'$(unit)'." +msgstr "" +"Wymagane jest uwierzytelnienie, aby wysłać sygnał uniksowy do procesów " +"jednostki „$(unit)”." + +#: src/core/dbus-unit.c:561 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Wymagane jest uwierzytelnienie, aby przywrócić stan „failed” (niepowodzenia) " +"jednostki „$(unit)”." + +#: src/core/dbus-unit.c:594 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "" +"Wymagane jest uwierzytelnienie, aby ustawić właściwości jednostki „$(unit)”." + +#: src/core/dbus-unit.c:703 +msgid "" +"Authentication is required to delete files and directories associated with " +"'$(unit)'." +msgstr "" +"Wymagane jest uwierzytelnienie, aby usunąć pliki i katalogi powiązane " +"z jednostką „$(unit)”." + +#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" +#~ msgstr "" +#~ "Naciśnięcie klawiszy Ctrl+C anuluje wszystkie trwające procesy " +#~ "sprawdzania systemów plików" + +#~ msgid "Checking in progress on %d disk (%3.1f%% complete)" +#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" +#~ msgstr[0] "Trwa sprawdzanie %d dysku (ukończono %3.1f%%)" +#~ msgstr[1] "Trwa sprawdzanie %d dysków (ukończono %3.1f%%)" +#~ msgstr[2] "Trwa sprawdzanie %d dysków (ukończono %3.1f%%)" diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 00000000..70c1881a --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,854 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Brazilian Portuguese translation for systemd. +# Enrico Nicoletto , 2014. +# Filipe Brandenburger , 2018. +# Rafael Fontenelle , 2015-2019. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2019-09-08 15:28+0000\n" +"PO-Revision-Date: 2019-09-08 19:00-0300\n" +"Last-Translator: Rafael Fontenelle \n" +"Language-Team: Brazilian Portuguese \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1)\n" +"X-Generator: Gtranslator 3.32.0\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Enviar frase secreta de volta ao sistema" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"É necessária autenticação para enviar a frase secreta informada de volta ao " +"sistema." + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Gerenciar serviços do sistema e outras unidades" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"É necessária autenticação para gerenciar serviços do sistema ou outras " +"unidades." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Gerenciar arquivos de unidades e serviços do sistema" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"É necessária autenticação para gerenciar arquivos “unit” e “service” do " +"sistema." + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Definir ou retirar definição de variáveis de ambiente de gerenciador de " +"serviço e sistema" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"É necessária autenticação para definir ou retirar definição de variáveis de " +"ambiente de gerenciador de serviço e sistema." + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "Recarregar o estado do sistema" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "É necessária autenticação para recarregar o estado do sistema." + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "Definir nome de máquina" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "É necessária autenticação para definir nome de máquina local." + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "Definir nome estático de máquina" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"É necessária autenticação para definir o nome de máquina local configurado " +"estaticamente, assim como o nome apresentável de máquina." + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "Definir informações da máquina" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "É necessária autenticação para definir informações de máquina local." + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "Obter UUID do produto" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "É necessária autenticação para obter a UUID." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Importar uma VM ou imagem contêiner" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "É necessária autenticação para importar uma VM ou imagem contêiner" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Exportar uma VM ou imagem contêiner" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "É necessária autenticação para exportar uma VM ou imagem contêiner" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Baixar uma VM ou imagem contêiner" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "É necessária autenticação para baixar uma VM ou imagem contêiner" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Definir configurações regionais do sistema" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "" +"É necessária autenticação para definir as configurações regionais do sistema." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Definir configurações de teclado do sistema" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"É necessária autenticação para definir as configurações de teclado do " +"sistema." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Permitir que aplicativos inibam o desligamento do sistema" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"É necessária autenticação para que um aplicativo iniba o desligamento do " +"sistema." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Permitir que aplicativos atrasem o desligamento do sistema" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"É necessária autenticação para que um aplicativo atrase o desligamento do " +"sistema." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Permitir que aplicativos inibam a suspensão do sistema" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"É necessária autenticação para que um aplicativo iniba a suspensão do " +"sistema." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Permite que aplicativos atrasem a suspensão do sistema" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"É necessária autenticação para que um aplicativo atrase a suspensão do " +"sistema." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Permitir que aplicativos inibam a suspensão automática do sistema" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"É necessária autenticação para que um aplicativo iniba a suspensão " +"automática do sistema." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Permitir que aplicativos inibam o sistema de gerenciar o botão de energia" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"É necessária autenticação para que um aplicativo iniba a manipulação do " +"sistema sobre a chave de ligar/desligar." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Permitir que aplicativos inibam o sistema de gerenciar o botão de suspensão" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"É necessária autenticação para que um aplicativo iniba a manipulação do " +"sistema sobre a chave de suspensão." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Permitir que aplicativos inibam o sistema de gerenciar o botão de hibernação" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"É necessária autenticação para que um aplicativo iniba a manipulação do " +"sistema sobre a chave de hibernar." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Permitir que aplicativos inibam o sistema de gerenciar a abertura/fechamento " +"da tampa do dispositivo portátil" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"É necessária autenticação para que um aplicativo iniba a manipulação do " +"sistema sobre o interruptor da tela." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "" +"Permitir que programas sejam executados por usuário que não possui sessão" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"É necessária requisição explícita para executar programas como usuário sem " +"sessão aberta." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "" +"Permitir que programas sejam executados por usuários que não possuem sessão" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"É necessária autenticação para executar programas como usuário sem sessão " +"aberta." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Permitir conectar dispositivos em estações" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "É necessária autenticação para conectar um dispositivo em uma estação." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Liberar dispositivo para conexões da estação" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"É necessária autenticação para redefinir a quantidade de dispositivos " +"conectados na estação." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Desligar o sistema" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "É necessária autenticação para desligar o sistema." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "Desligar o sistema enquanto outros usuários estão conectados" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"É necessária autenticação para desligar o sistema enquanto outros usuários " +"estão conectados." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Desligar o sistema enquanto um aplicativo solicitou inibição" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"É necessária autenticação para desligar o sistema enquanto um aplicativo " +"solicitou inibição." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Reiniciar o sistema" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "É necessária autenticação para reiniciar o sistema." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "Reiniciar o sistema enquanto outros usuários estiverem conectados" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"É necessária autenticação para reiniciar o sistema enquanto outros usuários " +"estiverem conectados." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Reiniciar o sistema enquanto um aplicativo solicitou inibição" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"É necessária autenticação para reiniciar o sistema enquanto um aplicativo " +"solicitou inibição." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Parar o sistema" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "É necessária autenticação para parar o sistema." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "Parar o sistema enquanto outros usuários estão logados" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"É necessária autenticação para parar o sistema enquanto outros usuários " +"estejam logados." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Parar o sistema enquanto um aplicativo solicitou inibição" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"É necessária autenticação para parar o sistema enquanto um aplicativo " +"solicitou inibição." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Suspender o sistema" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "É necessária autenticação para suspender o sistema." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "Suspender o sistema enquanto outros usuários estiverem conectados" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"É necessária autenticação para suspender o sistema enquanto outros usuários " +"estiverem conectados." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Suspender o sistema enquanto um aplicativo solicitou inibição" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"É necessária autenticação para suspender o sistema enquanto um aplicativo " +"solicitou inibição." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Hibernar o sistema" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "É necessária autenticação para hibernar o sistema." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "Hibernar o sistema enquanto outros usuários estiverem conectados" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"É necessária autenticação para hibernar o sistema enquanto outros usuários " +"estiverem conectados." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Hibernar o sistema enquanto um aplicativo solicitou inibição" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"É necessária autenticação para hibernar o sistema enquanto um aplicativo " +"solicitou inibição." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Gerenciar estações, usuários e sessões ativas" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"É necessária autenticação para gerenciar estações, usuários e sessões ativas." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Travar ou destravar sessões ativas" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "É necessária autenticação para travar ou destravar sessões ativas." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Set the reboot \"reason\" in the kernel" +msgstr "Definir o “motivo” de reinicialização no kernel" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "Authentication is required to set the reboot \"reason\" in the kernel." +msgstr "" +"É necessária autenticação para definir o “motivo” de reinicialização no " +"kernel." + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Indicate to the firmware to boot to setup interface" +msgstr "Indicar para o firmware inicializar para a interface de configuração" + +#: src/login/org.freedesktop.login1.policy:353 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"É necessária autenticação para indicar para o firmware inicializar para a " +"interface de configuração." + +#: src/login/org.freedesktop.login1.policy:363 +msgid "Indicate to the boot loader to boot to the boot loader menu" +msgstr "Indicar para o carregador de inicialização iniciar seu menu" + +#: src/login/org.freedesktop.login1.policy:364 +msgid "" +"Authentication is required to indicate to the boot loader to boot to the " +"boot loader menu." +msgstr "" +"É necessária autenticação para indicar para o carregador de inicialização " +"iniciar seu menu" + +#: src/login/org.freedesktop.login1.policy:374 +msgid "Indicate to the boot loader to boot a specific entry" +msgstr "" +"Indicar para o carregador de inicializar iniciar uma entrada específica" + +#: src/login/org.freedesktop.login1.policy:375 +msgid "" +"Authentication is required to indicate to the boot loader to boot into a " +"specific boot loader entry." +msgstr "" +"É necessária autenticação para indicar para o carregador de inicializar " +"iniciar uma entrada específica" + +#: src/login/org.freedesktop.login1.policy:385 +msgid "Set a wall message" +msgstr "Definir uma mensagem de parede" + +#: src/login/org.freedesktop.login1.policy:386 +msgid "Authentication is required to set a wall message" +msgstr "É necessária autenticação para definir uma mensagem de parede" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Conectar a um contêiner local" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "É necessária autenticação para se conectar a um contêiner local." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Conectar a uma máquina local" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "É necessária autenticação para se conectar a uma máquina local." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Adquirir uma shell em um contêiner local" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"É necessária autenticação para adquirir uma shell em um contêiner local." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Adquirir uma shell na máquina local" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"É necessária autenticação para adquirir uma shell em uma máquina local." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Adquirir um pseudo TTY em um contêiner local" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"É necessária autenticação para adquirir um pseudo TTY em um contêiner local." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Adquiri um pseudo TTY na máquina local" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"É necessária autenticação para adquirir um pseudo TTY em um máquina local." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Gerenciar máquinas virtuais locais e contêineres" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"É necessária autenticação para gerenciar máquinas virtuais locais e " +"contêineres." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Gerenciar máquinas virtuais locais e imagens contêineres" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"É necessária autenticação para gerenciar máquinas virtuais locais e imagens " +"contêineres." + +#: src/network/org.freedesktop.network1.policy:22 +msgid "Set NTP servers" +msgstr "Definir servidores NTP" + +#: src/network/org.freedesktop.network1.policy:23 +msgid "Authentication is required to set NTP servers." +msgstr "É necessária autenticação para definir os servidores NTP." + +#: src/network/org.freedesktop.network1.policy:33 +#: src/resolve/org.freedesktop.resolve1.policy:44 +msgid "Set DNS servers" +msgstr "Definir servidores DNS" + +#: src/network/org.freedesktop.network1.policy:34 +#: src/resolve/org.freedesktop.resolve1.policy:45 +msgid "Authentication is required to set DNS servers." +msgstr "É necessária autenticação para definir os servidores DNS." + +#: src/network/org.freedesktop.network1.policy:44 +#: src/resolve/org.freedesktop.resolve1.policy:55 +msgid "Set domains" +msgstr "Definir domínios" + +#: src/network/org.freedesktop.network1.policy:45 +#: src/resolve/org.freedesktop.resolve1.policy:56 +msgid "Authentication is required to set domains." +msgstr "É necessária autenticação para definir domínios." + +#: src/network/org.freedesktop.network1.policy:55 +#: src/resolve/org.freedesktop.resolve1.policy:66 +msgid "Set default route" +msgstr "Definir rota padrão" + +#: src/network/org.freedesktop.network1.policy:56 +#: src/resolve/org.freedesktop.resolve1.policy:67 +msgid "Authentication is required to set default route." +msgstr "É necessária autenticação para definir a rota padrão." + +#: src/network/org.freedesktop.network1.policy:66 +#: src/resolve/org.freedesktop.resolve1.policy:77 +msgid "Enable/disable LLMNR" +msgstr "Habilitar/desabilitar LLMNR" + +#: src/network/org.freedesktop.network1.policy:67 +#: src/resolve/org.freedesktop.resolve1.policy:78 +msgid "Authentication is required to enable or disable LLMNR." +msgstr "É necessária autenticação para definir habilitar ou desabilitar LLMNR." + +#: src/network/org.freedesktop.network1.policy:77 +#: src/resolve/org.freedesktop.resolve1.policy:88 +msgid "Enable/disable multicast DNS" +msgstr "Habilitar/desabilitar DNS multicast" + +#: src/network/org.freedesktop.network1.policy:78 +#: src/resolve/org.freedesktop.resolve1.policy:89 +msgid "Authentication is required to enable or disable multicast DNS." +msgstr "É necessária autenticação para habilitar ou desabilitar DNS multicast." + +#: src/network/org.freedesktop.network1.policy:88 +#: src/resolve/org.freedesktop.resolve1.policy:99 +msgid "Enable/disable DNS over TLS" +msgstr "Habilitar/desabilitar DNS por TLS" + +#: src/network/org.freedesktop.network1.policy:89 +#: src/resolve/org.freedesktop.resolve1.policy:100 +msgid "Authentication is required to enable or disable DNS over TLS." +msgstr "É necessária autenticação para habilitar ou desabilitar DNS por TLS." + +#: src/network/org.freedesktop.network1.policy:99 +#: src/resolve/org.freedesktop.resolve1.policy:110 +msgid "Enable/disable DNSSEC" +msgstr "Habilitar/desabilitar DNSSEC" + +#: src/network/org.freedesktop.network1.policy:100 +#: src/resolve/org.freedesktop.resolve1.policy:111 +msgid "Authentication is required to enable or disable DNSSEC." +msgstr "É necessária autenticação para habilitar ou desabilitar DNSSEC." + +#: src/network/org.freedesktop.network1.policy:110 +#: src/resolve/org.freedesktop.resolve1.policy:121 +msgid "Set DNSSEC Negative Trust Anchors" +msgstr "Definir DNSSEC Negative Trust Anchors" + +#: src/network/org.freedesktop.network1.policy:111 +#: src/resolve/org.freedesktop.resolve1.policy:122 +msgid "Authentication is required to set DNSSEC Negative Trust Anchors." +msgstr "É necessária autenticação para definir DNSSEC Negative Trust Anchors." + +#: src/network/org.freedesktop.network1.policy:121 +msgid "Revert NTP settings" +msgstr "Reverter configurações de NTP" + +#: src/network/org.freedesktop.network1.policy:122 +msgid "Authentication is required to revert NTP settings." +msgstr "É necessária autenticação para reverter as configurações de NTP." + +#: src/network/org.freedesktop.network1.policy:132 +msgid "Revert DNS settings" +msgstr "Reverter configurações de DNS" + +#: src/network/org.freedesktop.network1.policy:133 +msgid "Authentication is required to revert DNS settings." +msgstr "É necessária autenticação para reverter as configurações de DNS." + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "Inspecionar uma imagem de serviço portável" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "" +"É necessária autenticação para inspecionar uma imagem de serviço portável." + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "Conectar ou desconectar uma imagem de serviço portável" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "" +"É necessária autenticação para conectar ou desconectar uma imagem de serviço " +"portável." + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "Remover ou modificar imagem de serviço portável" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "" +"É necessária autenticação para remover ou modificar imagem de serviço " +"portável." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Registrar um serviço DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "É necessária autenticação para registrar um serviço DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Remover um serviço DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "É necessária autenticação para remover um serviço DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:132 +msgid "Revert name resolution settings" +msgstr "Reverter configurações de resolução de nome" + +#: src/resolve/org.freedesktop.resolve1.policy:133 +msgid "Authentication is required to revert name resolution settings." +msgstr "" +"É necessária autenticação para reverter as configurações de resolução de " +"nome." + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Definir horário do sistema" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "É necessária autenticação para definir o horário do sistema." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Definir fuso horário do sistema" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "É necessária autenticação para definir o fuso horário do sistema." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "Definir o relógio do sistema (RTC) para fuso horário local ou UTC" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"É necessária autenticação para controlar se o RTC deve, ou não, armazenar o " +"horário local ou de UTC." + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "Ligar/desligar a sincronização do horário em rede" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"É necessária autenticação para controlar se deve ser habilitada, ou não, a " +"sincronização de horário através de rede." + +#: src/core/dbus-unit.c:354 +msgid "Authentication is required to start '$(unit)'." +msgstr "É necessária autenticação para iniciar “$(unit)”." + +#: src/core/dbus-unit.c:355 +msgid "Authentication is required to stop '$(unit)'." +msgstr "É necessária autenticação para parar “$(unit)”." + +#: src/core/dbus-unit.c:356 +msgid "Authentication is required to reload '$(unit)'." +msgstr "É necessária autenticação para recarregar “$(unit)”." + +#: src/core/dbus-unit.c:357 src/core/dbus-unit.c:358 +msgid "Authentication is required to restart '$(unit)'." +msgstr "É necessária autenticação para reiniciar “$(unit)”." + +#: src/core/dbus-unit.c:530 +msgid "" +"Authentication is required to send a UNIX signal to the processes of " +"'$(unit)'." +msgstr "" +"É necessária autenticação para enviar um sinal UNIX para os processos de " +"“$(unit)”." + +#: src/core/dbus-unit.c:561 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"É necessária autenticação para reiniciar o estado “failed” de “$(unit)”." + +#: src/core/dbus-unit.c:594 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "É necessária autenticação para definir propriedades em “$(unit)”." + +#: src/core/dbus-unit.c:703 +msgid "" +"Authentication is required to delete files and directories associated with " +"'$(unit)'." +msgstr "" +"É necessária autenticação para excluir arquivos e diretórios associados com " +"“$(unit)”." + +#~ msgid "Authentication is required to kill '$(unit)'." +#~ msgstr "É necessária autenticação para matar “$(unit)”." diff --git a/po/ro.po b/po/ro.po new file mode 100644 index 00000000..fb54fe01 --- /dev/null +++ b/po/ro.po @@ -0,0 +1,618 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Romanian translation for systemd. +# va511e , 2015. +# Daniel Șerbănescu , 2015, 2017. +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2017-08-13 15:26+0000\n" +"PO-Revision-Date: 2017-08-13 19:48+0200\n" +"Last-Translator: Daniel Șerbănescu \n" +"Language-Team: Gnome Romanian Translation Team\n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " +"20)) ? 1 : 2);;\n" +"X-Generator: Virtaal 0.7.1\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Trimite fraza secretă înapoi la sistem" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Autentificarea este necesară pentru a trimite fraza secretă introdusă înapoi " +"la sistem." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Gestionează serviciile de sistem sau alte unități" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Autentificarea este necesară pentru a gestiona serviciile de sistem sau alte " +"unități." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Gestionează serviciul de sistem sau fișiere unitate" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Autentificarea este necesară pentru a gestiona serviciul de sistem sau " +"fișierele unitate." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Stabilește sau destabilește variabilele de mediu și managerul de servicii " +"ale sistemului" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Autentificarea este necesară pentru a stabili sau destabili variabile de " +"mediu și managerul de servicii ale sistemului." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Reîncarcă starea systemd" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Autentificarea este necesară pentru a reîncărca starea systemd." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Stabilește numele de server" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Autentificarea este necesară pentru a stabili numele de server local." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Stabilește numele de server static" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Autentificarea este necesara pentru a stabili numele de server static " +"configurat local, precum și numele lung de server." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Stabilește informațiile despre mașină" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "" +"Autentificarea este necesară pentru stabili informațiile mașinii locale." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Importă o VM (mașină virtuală) sau o imagine container" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Autentificarea este necesară pentru a importa o VM (mașină virtuală) sau o " +"imagine container" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Exportă o VM (mașină virtuală) sau o imagine container" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Autentificarea este necesară pentru a exporta o VM (mașină virtuală) sau o " +"imagine container" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Descarcă o VM (mașină virtuală) sau o imagine container" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Autentificarea este necesară pentru a descărca o VM (mașină virtuală) sau o " +"imagine container" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Stabilește localizarea sistemului" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "Autentificarea este necesară pentru a stabili localizarea sistemului." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Stabilește configurările tastaturii sistemului" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Autentificarea este necesară pentru a stabili configurările tastaturii " +"sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Permite aplicațiilor să împiedice închiderea sistemului" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Autentificarea este necesară pentru ca o aplicație să împiedice închiderea " +"sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Permite aplicațiilor să întârzie închiderea sistemului" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Autentificarea este necesară pentru ca o aplicație să întârzie închiderea " +"sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Permite aplicațiilor să împiedice starea de veghe a sistemului" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Autentificarea este necesară pentru ca o aplicație să împiedice starea de " +"veghe a sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Permite aplicațiilor să întârzie starea de veghe sistemului" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Autentificarea este necesară pentru ca o aplicație să întârzie starea de " +"veghe a sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Permite aplicațiilor să împiedice suspendarea automată a sistemului" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Autentificarea este necesară pentru ca o aplicație să împiedice suspendarea " +"automată a sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Permite aplicațiilor să împiedice administrarea butonului de pornire a " +"sistemului" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Autentificarea este necesară pentru o aplicație să împiedice administrarea " +"butonului de pornire a sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Permite aplicațiilor să împiedice administrarea butonului de suspendare al " +"sistemului" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Autentificarea este necesară pentru o aplicație pentru a împiedica " +"manipularea butonului de suspendare al sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Permite aplicațiilor să împiedice administrarea butonului de hibernare al " +"sistemului" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Autentificarea este necesară pentru o aplicație să împiedice administrarea " +"butonului de hibernare al sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Permite aplicațiilor să împiedice administrarea comutatorului capacului al " +"sistemului" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Autentificarea este necesară pentru ca o aplicație să împiedice manipularea " +"comutatorului capacului al sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in user to run programs" +msgstr "Permite utilizatorilor neautentificați să execute programe" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Cererea explicită este necesară pentru a rula programe ca utilizator " +"neautentificat." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow non-logged-in users to run programs" +msgstr "Permite utilizatorilor neautentificați să execute programe" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Autentificarea este necesară pentru a rula programe ca utilizator " +"neautentificat." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Allow attaching devices to seats" +msgstr "Permite atașarea dispozitivelor la locuri" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "Authentication is required for attaching a device to a seat." +msgstr "Autentificarea este necesară pentru a atașa un dispozitiv la un loc." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Flush device to seat attachments" +msgstr "Purjează atașamentele dispozitiv-loc" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Autentificarea este necesară pentru a restabili cum dispozitivele sunt " +"atașate la locuri." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system" +msgstr "Oprește sistemul" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "Authentication is required for powering off the system." +msgstr "Este necesară autentificarea pentru oprirea sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while other users are logged in" +msgstr "Oprește sistemul în timp ce alți utilizatori sunt autentificați" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Autentificarea este necesară pentru oprirea sistemului în timp ce alți " +"utilizatori sunt autentificați." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Oprește sistemul în timp ce o aplicație a cerut să împiedice asta" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Autentificarea este necesară pentru oprirea sistemului în timp ce o " +"aplicație a cerut să împiedice asta." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system" +msgstr "Repornește sistemul" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "Authentication is required for rebooting the system." +msgstr "Autentificarea este necesară pentru repornirea sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while other users are logged in" +msgstr "Repornește sistemul în timp ce alți utilizatori sunt autentificați" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Autentificarea este necesară pentru repornirea sistemului în timp ce alți " +"utilizatori autentificați." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Repornește sistemul în timp ce o aplicație a cerut să împiedice asta" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Autentificarea este necesară pentru repornirea sistemului în timp ce o " +"aplicație a cerut să împiedice asta." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system" +msgstr "Suspendă sistemul" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "Authentication is required for suspending the system." +msgstr "Este necesară autentificarea pentru suspendarea sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while other users are logged in" +msgstr "Suspendă sistemul în timp ce alți utilizatori sunt autentificați" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Autentificarea este necesară pentru suspendarea sistemului timp ce alți " +"utilizatori autentificați." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Suspendă sistemul în timp ce o aplicație a cerut să împiedice asta" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Autentificarea este necesară pentru suspendarea sistemului în timp ce o " +"aplicație a cerut să împiedice asta." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system" +msgstr "Hiberneaza sistemul" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "Authentication is required for hibernating the system." +msgstr "Este necesară autentificarea pentru hibernarea sistemului." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while other users are logged in" +msgstr "Hiberneaza sistemul în timp ce alți utilizatori sunt autentificați" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Autentificarea este necesară pentru hibernare a sistemului în timp ce alți " +"utilizatori sunt autentificați." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Hibernează sistemul în timp ce o aplicație a cerut să împiedice asta" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Autentificarea este necesară pentru hibernarea sistemului în timp ce o " +"aplicație a cerut să împiedice asta." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Manage active sessions, users and seats" +msgstr "Gestionează sesiuni active, utilizatori și locuri" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Autentificarea este necesară pentru gestionarea sesiunilor active, " +"utilizatorilor și locurilor." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Lock or unlock active sessions" +msgstr "Blochează sau deblochează sesiuni active" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Autentificarea este necesară pentru a bloca sau debloca sesiuni active." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "" +"Permite semnalizatrea către firmware pentru a porni în interfața de " +"configurare" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Autentificarea este necesară pentru a semnaliza către firmware să pornească " +"în interfața de configurare." + +#: ../src/login/org.freedesktop.login1.policy.in.h:57 +msgid "Set a wall message" +msgstr "Stabilește un mesaj de perete" + +#: ../src/login/org.freedesktop.login1.policy.in.h:58 +msgid "Authentication is required to set a wall message" +msgstr "Autentificarea este necesară pentru a stabili un mesaj de perete" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Conectează la un container local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "" +"Autentificarea este necesară pentru a vă conecta într-un container local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Conectează la serverul local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Autentificarea este necesară pentru a vă conecta la serverul local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Obține un shell într-un container local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Autentificarea este necesară pentru a obține un shell într-un container " +"local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Obține un shell pe serverul local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Autentificarea este necesară pentru a obține un shell pe serverul local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Obține un pseudo-TTY într-un container local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Autentificarea este necesară pentru a obține un pseudo-TTY într-un container " +"local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Obține un pseudo-TTY pe serverul local" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Autentificarea este necesară pentru a obține un pseudo-TTY pe serverul local." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Gestioneaza mașini virtuale locale și containere" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Autentificarea este necesară pentru a gestiona mașini virtuale locale și " +"containere." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Gestionează imaginile locale de mașină virtuală și containere" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Autentificarea este necesară pentru a gestiona imagini locale de mașini " +"virtuale și de containere." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Stabilește ora sistemului" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Autentificarea este necesară pentru a stabili ora sistemului." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Stabilește fusul orar al sistemului" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "" +"Autentificarea este necesară pentru a stabili fusul orar al sistemului." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "Stabilește RTC la ora locală sau UTC" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Autentificarea este necesară pentru a controla dacă RTC stochează ora locală " +"sau UTC." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Comută sincronizarea cu ora rețelei" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Autentificarea este necesară pentru a controla dacă sincronizarea cu ora " +"rețelei ar trebui activată." + +#: ../src/core/dbus-unit.c:457 +msgid "Authentication is required to start '$(unit)'." +msgstr "Autentificarea este necesară pentru a porni „$(unit)”." + +#: ../src/core/dbus-unit.c:458 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Autentificarea este necesară pentru a opri „$(unit)”." + +#: ../src/core/dbus-unit.c:459 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Autentificarea este necesară pentru a reîncărca „$ (unit)”." + +#: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Autentificarea este necesară pentru a reporni „$(unit)”." + +#: ../src/core/dbus-unit.c:568 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Autentificarea este necesară pentru a omorî „$(unit)”." + +#: ../src/core/dbus-unit.c:599 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Autentificarea este necesară pentru a restabili starea „eșuată” a „$(unit)”." + +#: ../src/core/dbus-unit.c:632 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "" +"Autentificarea este necesară pentru a stabili proprietățile pe „$(unit)”." diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 00000000..bda6a456 --- /dev/null +++ b/po/ru.po @@ -0,0 +1,744 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# translation of ru.po to Rissian +# Julia Dronova , 2013. +# Sergey Ptashnick <0comffdiz@inbox.ru>, 2013-2018. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2015-11-22 16:37+0100\n" +"PO-Revision-Date: 2018-09-01 18:46+0300\n" +"Last-Translator: Sergey Ptashnick <0comffdiz@inbox.ru>\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Отправить пароль системе" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "Чтобы отправить пароль системе, необходимо пройти аутентификацию." + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Управление системными службами и юнитами" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Для управления системными службами и юнитами, необходимо пройти " +"аутентификацию." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Управление файлами конфигурации системных служб и юнитов" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Для управления файлами конфигурации системных служб и юнитов, необходимо " +"пройти аутентификацию." + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "Настроить переменные окружения для системного менеджера" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Чтобы настроить переменные окружения для системного менеджера, необходимо " +"пройти аутентификацию." + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "Перечитать конфигурацию systemd" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "" +"Чтобы заставить systemd перечитать конфигурацию, необходимо пройти " +"аутентификацию." + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "Настроить имя компьютера" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "Чтобы настроить имя компьютера, необходимо пройти аутентификацию." + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "Настроить статическое имя компьютера" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Чтобы настроить статическое имя компьютера, а также его «красивое» имя, " +"необходимо пройти аутентификацию." + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "Настроить информацию о компьютере" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "" +"Чтобы настроить информацию о компьютере, необходимо пройти аутентификацию." + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "Получить UUID продукта" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "Чтобы получить UUID продукта, необходимо пройти аутентификацию." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Импортировать образ виртуальной машины или контейнера" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Чтобы импортировать образ виртуальной машины или контейнера, необходимо " +"пройти аутентификацию." + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Экспортировать образ виртуальной машины или контейнера" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Чтобы экспортировать образ виртуальной машины или контейнера, необходимо " +"пройти аутентификацию." + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Загрузить образ виртуальной машины или контейнера" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Чтобы загрузить образ виртуальной машины или контейнера, необходимо пройти " +"аутентификацию." + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Настроить системную локаль" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "Чтобы настроить системную локаль, необходимо пройти аутентификацию." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Настроить параметры клавиатуры" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Чтобы настроить параметры клавиатуры, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Разрешить приложениям устанавливать блокировку на выключение системы" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Чтобы разрешить приложениям устанавливать блокировку на выключение системы, " +"необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Разрешить приложениям устанавливать задержку на выключение системы" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Чтобы разрешить приложениям устанавливать задержку на выключение системы, " +"необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Разрешить приложениям устанавливать блокировку на засыпание системы" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Чтобы разрешить приложениям устанавливать блокировку на засыпание системы, " +"необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Разрешить приложениям устанавливать задержку на засыпание системы" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Чтобы разрешить приложениям устанавливать задержку на засыпание системы, " +"необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "" +"Разрешить приложениям устанавливать блокировку на автоматический переход " +"системы в ждущий режим" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Чтобы разрешить приложениям устанавливать блокировку на автоматический " +"переход системы в ждущий режим, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" +"Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку " +"выключения" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на " +"кнопку выключения, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку " +"перехода в ждущий режим" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на " +"кнопку перехода в ждущий режим, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Разрешить приложениям устанавливать блокировку обработки нажатий на кнопку " +"перехода в спящий режим" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Чтобы разрешить приложениям устанавливать блокировку обработки нажатий на " +"кнопку перехода в спящий режим, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Разрешить приложениям устанавливать блокировку на обработку закрытия крышки " +"ноутбука" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Чтобы разрешить приложениям устанавливать блокировку на обработку закрытия " +"крышки ноутбука, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "" +"Разрешить работу программ в фоновом режиме после завершения сеанса" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Чтобы разрешить работу программ в фоновом режиме после завершения сеанса, " +"необходимо явное подтверждение." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "" +"Разрешить пользователям оставлять программы в фоновом режиме после " +"завершения сеанса" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Чтобы разрешить пользователям оставлять программы в фоновом режиме после " +"завершения сеанса, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Разрешить подключение устройств к рабочим местам" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Чтобы разрешить подключение устройств к рабочим местам, необходимо пройти " +"аутентификацию." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Сбросить привязки устройств к рабочим местам" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Чтобы сбросить привязки устройств к рабочим местам, необходимо пройти " +"аутентификацию." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Выключить систему" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "Чтобы выключить систему, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "" +"Выключить систему, несмотря на то, что в ней работают другие пользователи" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Чтобы выключить систему, несмотря на то, что в ней работают другие " +"пользователи, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "" +"Выключить систему, несмотря на то, что приложение запросило блокировку " +"выключения" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Чтобы выключить систему, несмотря на то, что приложение запросило блокировку " +"выключения, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Перезагрузить систему" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "Чтобы перезагрузить систему, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "" +"Перезагрузить систему, несмотря на то, что в ней работают другие пользователи" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Чтобы перезагрузить систему, несмотря на то, что в ней работают другие " +"пользователи, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "" +"Перезагрузить систему, несмотря на то, что приложение запросило блокировку " +"выключения" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Чтобы перезагрузить систему, несмотря на то, что приложение запросило " +"блокировку выключения, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Остановить систему" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "Чтобы остановить систему, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "" +"Остановить систему, несмотря на то, что в ней работают другие пользователи" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Чтобы остановить систему, несмотря на то, что в ней работают другие " +"пользователи, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "" +"Остановить систему, несмотря на то, что приложение запросило блокировку " +"выключения" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Чтобы остановить систему, несмотря на то, что приложение запросило " +"блокировку выключения, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Перевести систему в ждущий режим" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "" +"Чтобы перевести систему в ждущий режим, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "" +"Перевести систему в ждущий режим, несмотря на то, что в ней работают другие " +"пользователи" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Чтобы перевести систему в ждущий режим, несмотря на то, что в ней работают " +"другие пользователи, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "" +"Перевести систему в ждущий режим, несмотря на то, что приложение запросило " +"блокировку" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Чтобы перевести систему в ждущий режим, несмотря на то, что приложение " +"запросило блокировку, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Перевести систему в спящий режим" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "" +"Чтобы перевести систему в спящий режим, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "" +"Перевести систему в спящий режим, несмотря на то, что в ней работают другие " +"пользователи" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Чтобы перевести систему в спящий режим, несмотря на то, что в ней работают " +"другие пользователи, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "" +"Перевести систему в спящий режим, несмотря на то, что приложение запросило " +"блокировку" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Чтобы перевести систему в спящий режим, несмотря на то, что приложение " +"запросило блокировку, необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Управление текущими сеансами, пользователями и рабочими местами" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Для управления текущими сеансами, пользователями и рабочими местами, " +"необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Заблокировать или разблокировать текущие сеансы" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Чтобы заблокировать или разблокировать текущие сеансы, необходимо пройти " +"аутентификацию." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "Разрешить загрузку в режиме настройки прошивки материнской платы" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Чтобы разрешить загрузку в режиме настройки прошивки материнской платы, " +"необходимо пройти аутентификацию." + +#: src/login/org.freedesktop.login1.policy:351 +msgid "Set a wall message" +msgstr "Отправить сообщение на все терминалы" + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Authentication is required to set a wall message" +msgstr "" +"Чтобы отправить сообщение на все терминалы, необходимо пройти аутентификацию." + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Зайти в локальный контейнер" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "Чтобы зайти в локальный контейнер, необходимо пройти аутентификацию." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Зайти на этот компьютер" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "Чтобы зайти на этот компьютер, необходимо пройти аутентификацию." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Получить командную оболочку в локальном контейнере" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Чтобы получить командную оболочку в локальном контейнере, необходимо пройти " +"аутентификацию." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Запустить командную оболочку на этом компьютере" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Чтобы запустить командную оболочку на этом компьютере, необходимо пройти " +"аутентификацию." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Получить псевдо-терминал в локальном контейнере" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Чтобы получить псевдо-терминал в локальном контейнере, необходимо пройти " +"аутентификацию." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Получить псевдо-терминал на этом компьютере" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Чтобы получить псевдо-терминал на этом компьютере, необходимо пройти " +"аутентификацию." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Управление виртуальными машинами и контейнерами" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Для управления виртуальными машинами и контейнерами, необходимо пройти " +"аутентификацию." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Управление образами виртуальных машин и контейнеров" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Для управления образами виртуальных машин и контейнеров, необходимо пройти " +"аутентификацию." + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "Прочитать образ переносимой службы" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "Чтобы прочитать образ переносимой службы, необходимо пройти " +"аутентификацию." + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "Подключить или отключить образ переносимой службы" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "Чтобы подключить или отключить образ переносимой службы, необходимо " +"пройти аутентификацию." + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "Удалить или изменить образ переносимой службы" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "" +"Чтобы удалить или изменить образ переносимой службы, необходимо пройти " +"аутентификацию." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Зарегистрировать службу в DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Чтобы зарегистрировать службу в DNS-SD, необходимо пройти " +"аутентификацию." + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Удалить службу из DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "Чтобы удалить службу из DNS-SD, необходимо пройти аутентификацию." + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Настроить системное время" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "Чтобы настроить системное время, необходимо пройти аутентификацию." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Настроить часовой пояс" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "Чтобы настроить часовой пояс, необходимо пройти аутентификацию." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "Установить аппаратные часы по местному времени или по Гринвичу" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Чтобы контролировать, установлены аппаратные часы по местному времени или по " +"Гринвичу, необходимо пройти аутентификацию." + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "Включить или выключить синхронизацию времени по сети" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Чтобы включить или выключить синхронизацию времени по сети, необходимо " +"пройти аутентификацию." + +#: src/core/dbus-unit.c:326 +msgid "Authentication is required to start '$(unit)'." +msgstr "Чтобы запустить «$(unit)», необходимо пройти аутентификацию." + +#: src/core/dbus-unit.c:327 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Чтобы остановить «$(unit)», необходимо пройти аутентификацию." + +#: src/core/dbus-unit.c:328 +msgid "Authentication is required to reload '$(unit)'." +msgstr "" +"Чтобы заставить «$(unit)» перечитать конфигурацию, необходимо пройти " +"аутентификацию." + +#: src/core/dbus-unit.c:329 src/core/dbus-unit.c:330 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Чтобы перезапустить «$(unit)», необходимо пройти аутентификацию." + +#: src/core/dbus-unit.c:437 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Чтобы убить юнит «$(unit)», необходимо пройти аутентификацию." + +#: src/core/dbus-unit.c:468 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Чтобы сбросить состояние «failed» у юнита «$(unit)», необходимо пройти " +"аутентификацию." + +#: src/core/dbus-unit.c:501 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Чтобы изменить параметры юнита «$(unit)», необходимо пройти " +"аутентификацию." + +#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" +#~ msgstr "" +#~ "Чтобы прервать все запущенные проверки файловых систем, нажмите Ctrl+C" + +# There is no difference between "на 2 дисках" (plural==1) and "на 5 дисках" (plural==2) +#~ msgid "Checking in progress on %d disk (%3.1f%% complete)" +#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" +#~ msgstr[0] "" +#~ "Проверяется целостность файловой системы на %d диске (выполнено %3.1f%%)" +#~ msgstr[1] "" +#~ "Проверяется целостность файловых систем на %d дисках (выполнено %3.1f%%)" +#~ msgstr[2] "" +#~ "Проверяется целостность файловых систем на %d дисках (выполнено %3.1f%%)" diff --git a/po/sk.po b/po/sk.po new file mode 100644 index 00000000..41d8279e --- /dev/null +++ b/po/sk.po @@ -0,0 +1,556 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Slovak translation for systemd. +# Dušan Kazik , 2017. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2017-06-24 03:26+0000\n" +"PO-Revision-Date: 2017-06-25 11:03+0200\n" +"Language-Team: Slovak \n" +"Language: sk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n" +"Last-Translator: Dušan Kazik \n" +"X-Generator: Poedit 2.0.2\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Odoslanie hesla späť do systému" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Vyžaduje sa overenie totožnosti na odoslanie zadaného hesla späť do systému." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Správa systémových služieb alebo iných jednotiek" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Vyžaduje sa overenie totožnosti na správu systémových služieb alebo iných " +"jednotiek." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Správa systémovej služby alebo súborov jednotky" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Vyžaduje sa overenie totožnosti na správu systémovej služby alebo súborov " +"jednotky." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Nastavenie alebo zrušenie nastavenia premenných prostredia systému a správcu " +"služieb" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Vyžaduje sa overenie totožnosti na nastavenie alebo zrušenie nastavenia " +"premenných prostredia systému a správcu služieb." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Znovu načítanie stavu systému systemd" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "" +"Vyžaduje sa overenie totožnosti na znovu načítanie stavu systému systemd." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Nastavenie názvu hostiteľa" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Vyžaduje sa overenie totožnosti na nastavenie názvu hostiteľa." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Nastavenie nemenného názvu hostiteľa" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Vyžaduje sa overenie totožnosti na nastavenie pevne určeného názvu miestneho " +"hostiteľa, známeho ako zrozumiteľný názov hostiteľa." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Nastavenie informácií o počítači" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "" +"Vyžaduje sa overenie totožnosti na nastavenie informácií o miestnom počítači." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Nastavenie miestnych nastavení" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "Vyžaduje sa overenie totožnosti na nastavenie miestnych nastavení." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Nastavenie nastavení systémovej klávesnice" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Vyžaduje sa overenie totožnosti na nastavenie nastavení systémovej " +"klávesnice." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Umožnenie aplikáciám odložiť spánok systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Vyžaduje sa overenie totožnosti na odloženie spánku systému aplikáciou." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in user to run programs" +msgstr "Umožnenie neprihlásenému používateľovi spúšťanie programov" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Vyžaduje sa explicitná požiadavka na spúšťanie programov ako neprihlásený " +"používateľ." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow non-logged-in users to run programs" +msgstr "Umožnenie neprihláseným používateľom spúšťanie programov" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Vyžaduje sa overenie totožnosti na spúšťanie programov ako neprihlásený " +"používateľ." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Allow attaching devices to seats" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Flush device to seat attachments" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system" +msgstr "Vypnutie systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "Authentication is required for powering off the system." +msgstr "Vyžaduje sa overenie totožnosti na vypnutie systému." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while other users are logged in" +msgstr "Vypnutie systému, pokiaľ sú prihlásení iní používatelia" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Vyžaduje sa overenie totožnosti na vypnutie systému, pokiaľ sú prihlásení " +"iní používatelia." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Power off the system while an application asked to inhibit it" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system" +msgstr "Reštart systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "Authentication is required for rebooting the system." +msgstr "Vyžaduje sa overenie totožnosti na reštartovanie systému." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while other users are logged in" +msgstr "Reštart systému, pokiaľ sú prihlásení iní používatelia" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Vyžaduje sa overenie totožnosti na reštartovanie systému, pokiaľ sú " +"prihlásení iní používatelia." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system" +msgstr "Uspanie systému" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "Authentication is required for suspending the system." +msgstr "Vyžaduje sa overenie totožnosti na uspanie systému." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while other users are logged in" +msgstr "Uspanie systému, pokiaľ sú prihlásení iní používatelia" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Vyžaduje sa overenie totožnosti na uspanie systému, pokiaľ sú prihlásení iní " +"používatelia." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "Authentication is required for hibernating the system." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while other users are logged in" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Manage active sessions, users and seats" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Lock or unlock active sessions" +msgstr "Zamknutie alebo odomknutie aktívnych relácií" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Vyžaduje sa overenie totožnosti na uzamknutie alebo odomknutie aktívnych " +"relácií." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "Umožnenie indikácie spustenia inštalačného rozhrania pre firmvér" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Vyžaduje sa overenie totožnosti na indikáciu spustenia inštalačného " +"rozhrania pre firmvér." + +#: ../src/login/org.freedesktop.login1.policy.in.h:57 +msgid "Set a wall message" +msgstr "" + +#: ../src/login/org.freedesktop.login1.policy.in.h:58 +msgid "Authentication is required to set a wall message" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Prihlásenie do miestneho kontajneru" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "" +"Vyžaduje sa overenie totožnosti na prihlásenie do miestneho kontajneru." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Zapnutie alebo vypnutie sieťovej synchronizácie času" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Vyžaduje sa overenie totožnosti na ovládanie, či má byť povolená " +"synchronizácia času cez sieť." + +#: ../src/core/dbus-unit.c:457 +msgid "Authentication is required to start '$(unit)'." +msgstr "" + +#: ../src/core/dbus-unit.c:458 +msgid "Authentication is required to stop '$(unit)'." +msgstr "" + +#: ../src/core/dbus-unit.c:459 +msgid "Authentication is required to reload '$(unit)'." +msgstr "" + +#: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461 +msgid "Authentication is required to restart '$(unit)'." +msgstr "" + +#: ../src/core/dbus-unit.c:568 +msgid "Authentication is required to kill '$(unit)'." +msgstr "" + +#: ../src/core/dbus-unit.c:599 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" + +#: ../src/core/dbus-unit.c:632 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "" diff --git a/po/sr.po b/po/sr.po new file mode 100644 index 00000000..422e9fa8 --- /dev/null +++ b/po/sr.po @@ -0,0 +1,676 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# SOME DESCRIPTIVE TITLE. +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2018-02-13 03:26+0000\n" +"PO-Revision-Date: 2018-02-18 22:03+0100\n" +"Last-Translator: Марко М. Костић \n" +"Language-Team: \n" +"Language: sr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.0.3\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: src/core/org.freedesktop.systemd1.policy.in.in:22 +msgid "Send passphrase back to system" +msgstr "Пошаљи фразу назад ка систему" + +#: src/core/org.freedesktop.systemd1.policy.in.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Потребно је да се идентификујете да бисте послали фразу назад у систем." + +#: src/core/org.freedesktop.systemd1.policy.in.in:33 +msgid "Manage system services or other units" +msgstr "Управљај системским услугама и другим јединицама" + +#: src/core/org.freedesktop.systemd1.policy.in.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Потребно је да се идентификујете да бисте управљали системским услугама или " +"другим јединицама." + +#: src/core/org.freedesktop.systemd1.policy.in.in:43 +msgid "Manage system service or unit files" +msgstr "Управљај системском услугом или јединичним датотекама" + +#: src/core/org.freedesktop.systemd1.policy.in.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Потребно је да се идентификујете да бисте управљали системском услугом или " +"јединичним датотекама." + +#: src/core/org.freedesktop.systemd1.policy.in.in:53 +msgid "Set or unset system and service manager environment variables" +msgstr "Мењај променљиве окружења на систему и унутар управника услуга" + +#: src/core/org.freedesktop.systemd1.policy.in.in:54 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Потребно је да се идентификујете да бисте мењали променљиве окружења на " +"систему и унутар управника услуга." + +#: src/core/org.freedesktop.systemd1.policy.in.in:63 +msgid "Reload the systemd state" +msgstr "Поново учитај стање систем-деа" + +#: src/core/org.freedesktop.systemd1.policy.in.in:64 +msgid "Authentication is required to reload the systemd state." +msgstr "" +"Потребно је да се идентификујете да бисте поново учитали стање систем-деа." + +#: src/hostname/org.freedesktop.hostname1.policy.in:22 +msgid "Set host name" +msgstr "Постави назив машине" + +#: src/hostname/org.freedesktop.hostname1.policy.in:23 +msgid "Authentication is required to set the local host name." +msgstr "Потребно је да се идентификујете да бисте поставили назив машине." + +#: src/hostname/org.freedesktop.hostname1.policy.in:32 +msgid "Set static host name" +msgstr "Постави статички назив машине" + +#: src/hostname/org.freedesktop.hostname1.policy.in:33 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Потребно је да се идентификујете да бисте поставили статички назив машине и " +"да бисте поставили леп назив машине." + +#: src/hostname/org.freedesktop.hostname1.policy.in:43 +msgid "Set machine information" +msgstr "Постави податке о машини" + +#: src/hostname/org.freedesktop.hostname1.policy.in:44 +msgid "Authentication is required to set local machine information." +msgstr "" +"Потребно је да се идентификујете да бисте поставили податке о локалној " +"машини." + +#: src/import/org.freedesktop.import1.policy.in:22 +msgid "Import a VM or container image" +msgstr "Увези ВМ или слику контејнера" + +#: src/import/org.freedesktop.import1.policy.in:23 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Потребно је да се идентификујете да бисте увезли виртуелну машину или слику " +"контејнера" + +#: src/import/org.freedesktop.import1.policy.in:32 +msgid "Export a VM or container image" +msgstr "Извези ВМ или слику контејнера" + +#: src/import/org.freedesktop.import1.policy.in:33 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Потребно је да се идентификујете да бисте извезли виртуелну машину или слику " +"контејнера" + +#: src/import/org.freedesktop.import1.policy.in:42 +msgid "Download a VM or container image" +msgstr "Преузми ВМ или слику контејнера" + +#: src/import/org.freedesktop.import1.policy.in:43 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Потребно је да се идентификујете да бисте преузели виртуелну машину или " +"слику контејнера" + +#: src/locale/org.freedesktop.locale1.policy.in:22 +msgid "Set system locale" +msgstr "Постави основни језик система" + +#: src/locale/org.freedesktop.locale1.policy.in:23 +msgid "Authentication is required to set the system locale." +msgstr "" +"Потребно је да се идентификујете да бисте поставили основни језик система." + +#: src/locale/org.freedesktop.locale1.policy.in:33 +msgid "Set system keyboard settings" +msgstr "Постави подешавање системске тастатуре" + +#: src/locale/org.freedesktop.locale1.policy.in:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Потребно је да се идентификујете да бисте поставили подешавања системске " +"тастатуре." + +#: src/login/org.freedesktop.login1.policy.in:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Дозволи програмима да спрече гашење система" + +#: src/login/org.freedesktop.login1.policy.in:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Потребно је да се идентификујете да бисте дозволили програму да спречи " +"гашење система." + +#: src/login/org.freedesktop.login1.policy.in:33 +msgid "Allow applications to delay system shutdown" +msgstr "Дозволи програмима да одложе гашење система" + +#: src/login/org.freedesktop.login1.policy.in:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Потребно је да се идентификујете да бисте дозволили програму да одложи " +"гашење система." + +#: src/login/org.freedesktop.login1.policy.in:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Дозволи програмима да спрече спавање система" + +#: src/login/org.freedesktop.login1.policy.in:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Потребно је да се идентификујете да бисте дозволили програму да спречи " +"спавање система." + +#: src/login/org.freedesktop.login1.policy.in:55 +msgid "Allow applications to delay system sleep" +msgstr "Дозволи програмима да одложе спавање система" + +#: src/login/org.freedesktop.login1.policy.in:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Потребно је да се идентификујете да бисте дозволили програму да одложи " +"спавање система." + +#: src/login/org.freedesktop.login1.policy.in:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Дозволи програмима да спрече самосталну обуставу система" + +#: src/login/org.freedesktop.login1.policy.in:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Потребно је да се идентификујете да бисте дозволили програму да спречи " +"самосталну обуставу система." + +#: src/login/org.freedesktop.login1.policy.in:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "Дозволи програмима да спрече систему управљање дугметом за напајање" + +#: src/login/org.freedesktop.login1.policy.in:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Потребно је да се идентификујете да бисте дозволили програму да спречи " +"систему управљање дугметом за напајање." + +#: src/login/org.freedesktop.login1.policy.in:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "Дозволи програмима да спрече систему управљање дугметом за обуставу" + +#: src/login/org.freedesktop.login1.policy.in:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Потребно је да се идентификујете да бисте дозволили програму да спречи " +"систему управљање дугметом за обуставу." + +#: src/login/org.freedesktop.login1.policy.in:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "Дозволи програмима да спрече систему управљање дугметом за спавање" + +#: src/login/org.freedesktop.login1.policy.in:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Потребно је да се идентификујете да бисте дозволили програму да спречи " +"систему управљање дугметом за спавање." + +#: src/login/org.freedesktop.login1.policy.in:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Дозволи програмима да спрече систему да уради било шта приликом заклапања " +"екрана" + +#: src/login/org.freedesktop.login1.policy.in:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Потребно је да се идентификујете да бисте дозволили програму да спречи " +"систему да уради било шта приликом заклапања екрана." + +#: src/login/org.freedesktop.login1.policy.in:117 +msgid "Allow non-logged-in user to run programs" +msgstr "Дозволи непријављеним корисницима да покрећу програме" + +#: src/login/org.freedesktop.login1.policy.in:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Експлицитан захтев је потребан да бисте покретали програме као непријављен " +"корисник." + +#: src/login/org.freedesktop.login1.policy.in:127 +msgid "Allow non-logged-in users to run programs" +msgstr "Дозволи непријављеним корисницима да покрећу програме" + +#: src/login/org.freedesktop.login1.policy.in:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Потребно је да се идентификујете да бисте покретали програме као непријављен " +"корисник." + +#: src/login/org.freedesktop.login1.policy.in:137 +msgid "Allow attaching devices to seats" +msgstr "Дозволи качење уређаја на седишта" + +#: src/login/org.freedesktop.login1.policy.in:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "Потребно је да се идентификујете да бисте закачили уређај на седиште." + +#: src/login/org.freedesktop.login1.policy.in:148 +msgid "Flush device to seat attachments" +msgstr "Испери уређај да би уседиштио закачено" + +#: src/login/org.freedesktop.login1.policy.in:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Потребно је да се идентификујете да бисте поново подесили како се уређаји " +"каче на седишта." + +#: src/login/org.freedesktop.login1.policy.in:158 +msgid "Power off the system" +msgstr "Искључи систем" + +#: src/login/org.freedesktop.login1.policy.in:159 +msgid "Authentication is required for powering off the system." +msgstr "Потребно је да се идентификујете да бисте искључили систем." + +#: src/login/org.freedesktop.login1.policy.in:169 +msgid "Power off the system while other users are logged in" +msgstr "Искључи систем док су други корисници пријављени" + +#: src/login/org.freedesktop.login1.policy.in:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Потребно је да се идентификујете да бисте искључили систем док су други " +"корисници пријављени." + +#: src/login/org.freedesktop.login1.policy.in:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Искључи систем иако је програм затражио да се спречи гашење" + +#: src/login/org.freedesktop.login1.policy.in:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Потребно је да се идентификујете да бисте искључили систем иако је програм " +"затражио да се спречи гашење система." + +#: src/login/org.freedesktop.login1.policy.in:191 +msgid "Reboot the system" +msgstr "Поново покрени систем" + +#: src/login/org.freedesktop.login1.policy.in:192 +msgid "Authentication is required for rebooting the system." +msgstr "Потребно је да се идентификујете да бисте поново покренули систем." + +#: src/login/org.freedesktop.login1.policy.in:202 +msgid "Reboot the system while other users are logged in" +msgstr "Поново покрени систем док су други корисници пријављени" + +#: src/login/org.freedesktop.login1.policy.in:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Потребно је да се идентификујете да бисте поново покренули систем док су " +"други корисници пријављени." + +#: src/login/org.freedesktop.login1.policy.in:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Поново покрени систем иако је програм затражио да се спречи гашење" + +#: src/login/org.freedesktop.login1.policy.in:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Потребно је да се идентификујете да бисте поново покренули систем иако је " +"програм затражио да се спречи гашење система." + +#: src/login/org.freedesktop.login1.policy.in:224 +msgid "Halt the system" +msgstr "Заустави систем" + +#: src/login/org.freedesktop.login1.policy.in:225 +msgid "Authentication is required for halting the system." +msgstr "Потребно је да се идентификујете да бисте зауставили систем." + +#: src/login/org.freedesktop.login1.policy.in:235 +msgid "Halt the system while other users are logged in" +msgstr "Заустави систем док су други корисници пријављени" + +#: src/login/org.freedesktop.login1.policy.in:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Потребно је да се идентификујете да бисте зауставили систем док су други " +"корисници пријављени." + +#: src/login/org.freedesktop.login1.policy.in:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Заустави систем иако програм тражи да се спречи заустављање" + +#: src/login/org.freedesktop.login1.policy.in:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Потребно је да се идентификујете да бисте зауставили систем иако програм " +"тражи да се спречи заустављање система." + +#: src/login/org.freedesktop.login1.policy.in:257 +msgid "Suspend the system" +msgstr "Обустави систем" + +#: src/login/org.freedesktop.login1.policy.in:258 +msgid "Authentication is required for suspending the system." +msgstr "Потребно је да се идентификујете да бисте обуставили систем." + +#: src/login/org.freedesktop.login1.policy.in:267 +msgid "Suspend the system while other users are logged in" +msgstr "Обустави систем док су други корисници пријављени" + +#: src/login/org.freedesktop.login1.policy.in:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Потребно је да се идентификујете да бисте обуставили систем док су други " +"корисници пријављени." + +#: src/login/org.freedesktop.login1.policy.in:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Обуставите систем иако програм тражи да се спречи обустава" + +#: src/login/org.freedesktop.login1.policy.in:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Потребно је да се идентификујете да бисте обуставили систем иако је програм " +"затражио да се спречи обустава система." + +#: src/login/org.freedesktop.login1.policy.in:289 +msgid "Hibernate the system" +msgstr "Успавај систем" + +#: src/login/org.freedesktop.login1.policy.in:290 +msgid "Authentication is required for hibernating the system." +msgstr "Потребно је да се идентификујете да бисте успавали систем." + +#: src/login/org.freedesktop.login1.policy.in:299 +msgid "Hibernate the system while other users are logged in" +msgstr "Успавај систем док су други корисници пријављени" + +#: src/login/org.freedesktop.login1.policy.in:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Потребно је да се идентификујете да бисте успавали систем док су други " +"корисници пријављени." + +#: src/login/org.freedesktop.login1.policy.in:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Успавај систем иако је програм затражио да се спречи спавање" + +#: src/login/org.freedesktop.login1.policy.in:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Потребно је да се идентификујете да бисте успавали систем иако је програм " +"затражио да се спречи успављивање система." + +#: src/login/org.freedesktop.login1.policy.in:321 +msgid "Manage active sessions, users and seats" +msgstr "Управљај покренутим сесијама, корисницима и седиштима" + +#: src/login/org.freedesktop.login1.policy.in:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Потребно је да се идентификујете да бисте управљали покренутим сесијама, " +"корисницима и седиштима." + +#: src/login/org.freedesktop.login1.policy.in:331 +msgid "Lock or unlock active sessions" +msgstr "Закључај или откључај покренуте сесије" + +#: src/login/org.freedesktop.login1.policy.in:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Потребно је да се идентификујете да бисте закључавали или откључавали " +"покренуте сесије." + +#: src/login/org.freedesktop.login1.policy.in:341 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "Напомени фирмверу да се подигне у режиму подешавања интерфејса" + +#: src/login/org.freedesktop.login1.policy.in:342 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Потребно је да се идентификујете да бисте напоменули фирмверу да се подигне " +"у режиму подешавања интерфејса." + +#: src/login/org.freedesktop.login1.policy.in:351 +msgid "Set a wall message" +msgstr "Постави зидну поруку" + +#: src/login/org.freedesktop.login1.policy.in:352 +msgid "Authentication is required to set a wall message" +msgstr "Потребно је да се идентификујете да бисте поставили зидну поруку" + +#: src/machine/org.freedesktop.machine1.policy.in:22 +msgid "Log into a local container" +msgstr "Пријави се у локални контејнер" + +#: src/machine/org.freedesktop.machine1.policy.in:23 +msgid "Authentication is required to log into a local container." +msgstr "" +"Потребно је да се идентификујете да бисте се пријавили у локални контејнер." + +#: src/machine/org.freedesktop.machine1.policy.in:32 +msgid "Log into the local host" +msgstr "Пријави се у локалног домаћина" + +#: src/machine/org.freedesktop.machine1.policy.in:33 +msgid "Authentication is required to log into the local host." +msgstr "" +"Потребно је да се идентификујете да бисте се пријавили у локалног домаћина." + +#: src/machine/org.freedesktop.machine1.policy.in:42 +msgid "Acquire a shell in a local container" +msgstr "Добиј приступ шкољци унутар локалног контејнера" + +#: src/machine/org.freedesktop.machine1.policy.in:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Потребно је да се идентификујете да бисте добили приступ шкољци унутар " +"локалног контејнера." + +#: src/machine/org.freedesktop.machine1.policy.in:53 +msgid "Acquire a shell on the local host" +msgstr "Добиј приступ шкољци на локалном домаћину" + +#: src/machine/org.freedesktop.machine1.policy.in:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Потребно је да се идентификујете да бисте добили приступ шкољци на локалном " +"домаћину." + +#: src/machine/org.freedesktop.machine1.policy.in:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Добиј приступ псеудо писаћој машини унутар локалног контејнера" + +#: src/machine/org.freedesktop.machine1.policy.in:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Потребно је да се идентификујете да бисте добили приступ псеудо писаћој " +"машини унутар локалног контејнера." + +#: src/machine/org.freedesktop.machine1.policy.in:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Добиј приступ псеудо писаћој машини на локалном домаћину" + +#: src/machine/org.freedesktop.machine1.policy.in:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Потребно је да се идентификујете да бисте добили приступ псеудо писаћој " +"машини на локалном домаћину." + +#: src/machine/org.freedesktop.machine1.policy.in:84 +msgid "Manage local virtual machines and containers" +msgstr "Управљај локалним виртуелним машинама и контејнерима" + +#: src/machine/org.freedesktop.machine1.policy.in:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Потребно је да се идентификујете да бисте управљали локалним виртуелним " +"машинама и контејнерима." + +#: src/machine/org.freedesktop.machine1.policy.in:95 +msgid "Manage local virtual machine and container images" +msgstr "Управљај локалним виртуелним машинама и сликама контејнера" + +#: src/machine/org.freedesktop.machine1.policy.in:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Потребно је да се идентификујете да бисте управљали локалним виртуелним " +"машинама и сликама контејнера." + +#: src/resolve/org.freedesktop.resolve1.policy.in:22 +msgid "Register a DNS-SD service" +msgstr "Региструј DNS-SD услугу" + +#: src/resolve/org.freedesktop.resolve1.policy.in:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Потребно је да се идентификујете да бисте регистровали DNS-SD услугу" + +#: src/resolve/org.freedesktop.resolve1.policy.in:33 +msgid "Unregister a DNS-SD service" +msgstr "Укини регистрацију DNS-SD услуге" + +#: src/resolve/org.freedesktop.resolve1.policy.in:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "" +"Потребно је да се идентификујете да бисте укинули регистрацију DNS-SD услуге" + +#: src/timedate/org.freedesktop.timedate1.policy.in:22 +msgid "Set system time" +msgstr "Постави системско време" + +#: src/timedate/org.freedesktop.timedate1.policy.in:23 +msgid "Authentication is required to set the system time." +msgstr "Потребно је да се идентификујете да бисте поставили системско време." + +#: src/timedate/org.freedesktop.timedate1.policy.in:33 +msgid "Set system timezone" +msgstr "Постави системску временску зону" + +#: src/timedate/org.freedesktop.timedate1.policy.in:34 +msgid "Authentication is required to set the system timezone." +msgstr "" +"Потребно је да се идентификујете да бисте поставили системску временску зону." + +#: src/timedate/org.freedesktop.timedate1.policy.in:43 +msgid "Set RTC to local timezone or UTC" +msgstr "" +"Постави часовник реалног времена на локалну временску зону или UTC зону" + +#: src/timedate/org.freedesktop.timedate1.policy.in:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Потребно је да се идентификујете да бисте подесили да ли RTC чува локално " +"или UTC време." + +#: src/timedate/org.freedesktop.timedate1.policy.in:54 +msgid "Turn network time synchronization on or off" +msgstr "Укључи или искључи усклађивање времена са мреже" + +#: src/timedate/org.freedesktop.timedate1.policy.in:55 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Потребно је да се идентификујете да бисте подесили да ли се време усклађује " +"са мреже." + +#: src/core/dbus-unit.c:496 +msgid "Authentication is required to start '$(unit)'." +msgstr "Потребно је да се идентификујете да бисте покренули „$(unit)“." + +#: src/core/dbus-unit.c:497 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Потребно је да се идентификујете да бисте зауставили „$(unit)“." + +#: src/core/dbus-unit.c:498 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Потребно је да се идентификујете да бисте поново учитали „$(unit)“." + +#: src/core/dbus-unit.c:499 src/core/dbus-unit.c:500 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Потребно је да се идентификујете да бисте поново покренули „$(unit)“." + +#: src/core/dbus-unit.c:607 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Потребно је да се идентификујете да бисте убили „$(unit)“." + +#: src/core/dbus-unit.c:638 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Потребно је да се идентификујете да бисте поново поставили „неуспешно“ стање " +"за „$(unit)“." + +#: src/core/dbus-unit.c:671 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "" +"Потребно је да се идентификујете да бисте поставили својства за „$(unit)“." + +msgid "Press Ctrl+C to cancel all filesystem checks in progress" +msgstr "" +"Притисните Ctrl+C да бисте прекинули све текуће провере система датотека" + +msgid "Checking in progress on %d disk (%3.1f%% complete)" +msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" +msgstr[0] "Провера у току на %d диску (%3.1f%% готово)" +msgstr[1] "Провера у току на %d диска (%3.1f%% готово)" +msgstr[2] "Провера у току на %d дискова (%3.1f%% готово)" diff --git a/po/sv.po b/po/sv.po new file mode 100644 index 00000000..6aeca087 --- /dev/null +++ b/po/sv.po @@ -0,0 +1,626 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Swedish translation for systemd. +# Sebastian Rasmussen , 2015. +# Andreas Henriksson , 2016. +# Josef Andersson , 2015, 2017. +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2017-03-01 15:50+0000\n" +"PO-Revision-Date: 2017-03-19 21:18+0100\n" +"Last-Translator: Josef Andersson \n" +"Language-Team: Swedish\n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.9\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "Skicka tillbaka lösenfras till system" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Autentisering krävs för att skicka tillbaka den angivna lösenfrasen till " +"systemet." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "Hantera systemtjänster eller andra enheter" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Autentisering krävs för att hantera systemtjänster eller andra enheter." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "Hantera systemtjänster eller enhetsfiler" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "Autentisering krävs för att hantera systemtjänster eller enhetsfiler." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "Ställ in eller ta bort miljövariabler för system- och servicehanterare" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Autentisering krävs för att ställa in eller ta bort miljövariabler för " +"system- och servicehanterare." + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "Läs om tillståndet för systemd" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "Autentisering krävs för att läsa om tillståndet för systemd." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "Ange värdnamn" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "Autentisering krävs för att ställa in lokalt värdnamn." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "Ange statiskt värdnamn" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Autentisering krävs för att ställa in det statiskt konfigurerade lokala " +"värdnamnet såväl som det stiliga värdnamnet." + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "Ställa in datorinformation" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "Autentisering krävs för att ställa in lokal datorinformation." + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "Importera en VM eller behållaravbildning" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "Autentisering krävs för att importera en VM eller behållaravbildning" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "Exportera en VM eller behållaravbildning" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "Autentisering krävs för att exportera en VM eller behållaravbildning" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "Hämta ner en VM eller behållaravbildning" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "Autentisering krävs för att hämta ner en VM eller behållaravbildning" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "Ange systemlokal" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "Autentisering krävs för att ställa in systemlokal." + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "Ange systeminställningar för tangentbord" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Autentisering krävs för att ställa in systeminställningar för tangentbord." + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "Tillåt program att hindra systemavstängning" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Autentisering krävs för att tillåta ett program att hindra systemavstängning." + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "Tillåt program att fördröja systemavstängning" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Autentisering krävs för att tillåta ett program att fördröja " +"systemavstängning." + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "Tillåt program att hindra system att försättas i viloläge" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Autentisering krävs för att tillåta ett program att hindra ett system att " +"försättas i viloläge." + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "Tillåt program att fördröja att system försätts i viloläge" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Autentisering krävs för att tillåta ett program att fördröja ett system att " +"försättas i viloläge." + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Tillåt program att hindra automatiskt systemvänteläge" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Autentisering krävs för att tillåta ett program att hindra automatiskt " +"systemvänteläge." + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "Tillåt program att hindra systemhantering av strömknappen" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Autentisering krävs för att tillåta ett program att hindra systemhantering " +"av strömknappen." + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "Tillåt program att hindra systemhantering av väntelägesknappen" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Autentisering krävs för att tillåta ett program att hindra systemhantering " +"av väntelägesknappen." + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "Tillåt program att hindra systemhantering av vilolägesknappen" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Autentisering krävs för att tillåta ett program att hindra systemhantering " +"av vilolägesknappen." + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "Tillåt program att hindra systemhantering av växel för datorhölje" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Autentisering krävs för att tillåta ett program att hindra systemhantering " +"av brytaren för datorhöljet." + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in user to run programs" +msgstr "Tillåt ej inloggad användare att köra program" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Uttrycklig begäran krävs för att köra program som en icke inloggad användare." + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow non-logged-in users to run programs" +msgstr "Tillåt ej inloggade användare att köra program" + +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Autentisering krävs för att köra program som en icke inloggad användare." + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Allow attaching devices to seats" +msgstr "Tillåt att binda enheter till platser" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "Authentication is required for attaching a device to a seat." +msgstr "Autentisering krävs för att binda en enhet till en plats." + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Flush device to seat attachments" +msgstr "Töm bindningar för enhet-till-plats" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Autentisering krävs för att återställa hur enheter är bundna till platser." + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system" +msgstr "Stäng av systemet" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "Authentication is required for powering off the system." +msgstr "Autentisering krävs för att stänga av systemet." + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while other users are logged in" +msgstr "Stäng av systemet medan andra användare är inloggade" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Autentisering krävs för att stänga av systemet medan andra användare är " +"inloggade." + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Stäng av systemet även då ett program hindrar det" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Autentisering krävs för att stänga av systemet även då ett program hindrar " +"det." + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system" +msgstr "Starta om systemet" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "Authentication is required for rebooting the system." +msgstr "Autentisering krävs för att starta om systemet." + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while other users are logged in" +msgstr "Starta om systemet medan andra användare är inloggade" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Autentisering krävs för att starta om systemet medan andra användare är " +"inloggade." + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Starta om systemet även då ett program hindrar det" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Autentisering krävs för att starta om systemet även då ett program hindrar " +"det." + +#: src/login/org.freedesktop.login1.policy.in:224 +msgid "Halt the system" +msgstr "Stoppa systemet" + +#: src/login/org.freedesktop.login1.policy.in:225 +msgid "Authentication is required for halting the system." +msgstr "Autentisering krävs för att stoppa systemet." + +#: src/login/org.freedesktop.login1.policy.in:235 +msgid "Halt the system while other users are logged in" +msgstr "Stoppa systemet medan andra användare är inloggade" + +#: src/login/org.freedesktop.login1.policy.in:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Autentisering krävs för att stoppa systemet medan andra användare är " +"inloggade." + +#: src/login/org.freedesktop.login1.policy.in:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Stoppa systemet även då ett program hindrar det" + +#: src/login/org.freedesktop.login1.policy.in:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Autentisering krävs för att stoppa systemet även då ett program hindrar det." + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system" +msgstr "Försätt system i vänteläge" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "Authentication is required for suspending the system." +msgstr "Autentisering krävs för att försätta system i vänteläge." + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while other users are logged in" +msgstr "Försätt systemet i vänteläge medan andra användare är inloggade" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Autentisering krävs för att försätta systemet i vänteläge medan andra " +"användare är inloggade." + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Försätt systemet i vänteläge även då ett program hindrar det" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Autentisering krävs för att försätta ett program i vänteläge även då ett " +"program hindrar det." + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system" +msgstr "Försätt systemet i viloläge" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "Authentication is required for hibernating the system." +msgstr "Autentisering krävs för att försätta systemet i viloläge." + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while other users are logged in" +msgstr "Försätt systemet i viloläge medan andra användare är inloggade" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Autentisering krävs för att försätta systemet i viloläge medan andra " +"användare är inloggade." + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Försätt systemet i viloläge även då ett program hindrar det" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Autentisering krävs för att försätta ett program i viloläge även då ett " +"program hindrar det." + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Manage active sessions, users and seats" +msgstr "Hantera aktiva sessioner, användare och platser" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Autentisering krävs för att hantera aktiva sessioner, användare och platser." + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Lock or unlock active sessions" +msgstr "Lås eller lås upp aktiva sessioner" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "Autentisering krävs för att låsa eller låsa upp aktiva sessioner." + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "" +"Tillåt indikering till firmware att starta upp i inställningsgränssnitt" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Autentisering krävs för att indikera till firmware att starta upp till " +"inställningsgränssnitt." + +#: ../src/login/org.freedesktop.login1.policy.in.h:57 +msgid "Set a wall message" +msgstr "Ange ett väggmeddelande" + +#: ../src/login/org.freedesktop.login1.policy.in.h:58 +msgid "Authentication is required to set a wall message" +msgstr "Autentisering krävs för att ställa in ett väggmeddelande" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "Logga in i en lokal behållare" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "Autentisering krävs för att logga in i en lokal behållare" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "Logga in på en lokal värd" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "Autentisering krävs för att logga in på den lokala värden" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "Förvärva en kommandotolk i en lokal behållare" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Autentisering krävs för att förvärva en kommandotolk i en lokal behållare." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "Förvärva en kommandotolk på den lokala värden" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Autentisering krävs för att förvärva en kommandotolk på den lokala värden." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Förvärva en pseudo TTY i en lokal behållare" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Autentisering krävs för att förvärva en pseudo TTY i en lokal behållare" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Förvärva en pseudo TTY på den lokala värden" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Autentisering krävs för att förvärva en pseudo TTY på den lokala värden." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "Hantera lokala virtuella maskiner och behållare" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Autentisering krävs för att hantera lokala virtuella maskiner och behållare." + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "Hantera lokala virtuella maskin- och behållaravbildningar" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Autentisering krävs för att hantera lokala virtuella maskin- och " +"behållaravbildningar." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "Ange systemtid" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "Autentisering krävs för ställa in systemtiden." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "Ange systemets tidszon" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "Autentisering krävs för att ställa in systemets tidszon." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "" +"Sätt realtidsklocka (RTC) till lokal tidszon eller koordinerad universell " +"tid (UTC)" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Autentisering krävs för att kunna kontrollera huruvida realtidsklockan (RTC) " +"lagrar den lokala eller koordinerade universella tiden (UTC)." + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "Växla synkronisering av nätverkstid på och av" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Autentisering krävs för att kontrollera huruvida synkronisering av " +"nätverkstid ska vara aktiverat." + +#: ../src/core/dbus-unit.c:457 +msgid "Authentication is required to start '$(unit)'." +msgstr "Autentisering krävs för att starta \"$(unit)\"." + +#: ../src/core/dbus-unit.c:458 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Autentisering krävs för att stoppa \"$(unit)\"." + +#: ../src/core/dbus-unit.c:459 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Autentisering krävs för att läsa om tillståndet för \"$(unit)\"." + +#: ../src/core/dbus-unit.c:460 ../src/core/dbus-unit.c:461 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Autentisering krävs för att starta om \"$(unit)\"." + +#: ../src/core/dbus-unit.c:568 +msgid "Authentication is required to kill '$(unit)'." +msgstr "Autentisering krävs för att döda \"$(unit)\"." + +#: ../src/core/dbus-unit.c:599 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"Autentisering krävs för att återställa det \"fallerade\" tillståndet för " +"\"$(unit)\"." + +#: ../src/core/dbus-unit.c:632 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Autentisering krävs för att ställa in egenskaper på \"$(unit)\"." + +#~ msgid "Press Ctrl+C to cancel all filesystem checks in progress" +#~ msgstr "Tryck Ctrl+C för att avbryta alla pågående filsystemskontroller." + +#~ msgid "Checking in progress on %d disk (%3.1f%% complete)" +#~ msgid_plural "Checking in progress on %d disks (%3.1f%% complete)" +#~ msgstr[0] "Kontroll pågår på %d disk (%3.1f%% klart)" +#~ msgstr[1] "Kontroll pågår på %d diskar (%3.1f%% klart)" diff --git a/po/tr.po b/po/tr.po new file mode 100644 index 00000000..e0239594 --- /dev/null +++ b/po/tr.po @@ -0,0 +1,704 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Turkish translation for systemd. +# Necdet Yücel , 2014. +# Gökhan Gurbetoğlu , 2015. +# Muhammet Kara , 2015, 2016, 2017, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2018-10-26 19:14+0000\n" +"PO-Revision-Date: 2018-10-31 00:12+0300\n" +"Last-Translator: Muhammet Kara \n" +"Language-Team: Turkish \n" +"Language: tr_TR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Gtranslator 2.91.7\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Sisteme parolayı geri gönder" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "Sisteme parolayı geri göndermek kimlik doğrulaması gerektiriyor." + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Sistem servislerini veya diğer birimlerini yönet" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Sistem servislerini veya diğer birimlerini yönetmek kimlik doğrulaması " +"gerektiriyor." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Sistem servislerini veya birim dosyalarını yönet" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Sistem servislerini veya birim dosyalarını yönetmek kimlik doğrulaması " +"gerektiriyor." + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "Sistem ve servis yöneticisi ortam değişkenlerini ayarla ya da kaldır" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Sistem ve servis yöneticisi ortam değişkenlerini ayarlamak ya da kaldırmak " +"kimlik doğrulaması gerektiriyor." + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "systemd durumunu yeniden yükle" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "systemd durumunu yeniden yüklemek kimlik doğrulaması gerektiriyor." + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "Makine adını ayarla" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "Yerel makine adını ayarlamak kimlik doğrulaması gerektiriyor." + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "Statik makine adı ayarla" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Statik olarak yapılandırılmış konak makine adını ve yerel makine adını " +"ayarlamak kimlik doğrulaması gerektiriyor." + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "Makine bilgisini ayarla" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "Yerel makine bilgisini ayarlamak kimlik doğrulaması gerektiriyor." + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "Ürün UUID'ini al" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "Ürün UUID'ini almak için kimlik doğrulaması gereklidir." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Bir SM ya da kapsayıcı kalıbını içe aktar" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Bir SM ya da kapsayıcı kalıbını içe aktarmak için kimlik doğrulaması " +"gereklidir" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Bir SM ya da kapsayıcı kalıbını dışa aktar" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Bir SM ya da kapsayıcı kalıbını dışa aktarmak için kimlik doğrulaması " +"gereklidir" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Bir SM ya da kapsayıcı kalıbını indir" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Bir SM ya da kapsayıcı kalıbını indirmek için kimlik doğrulaması gereklidir" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Sistem yerelini ayarla" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "Sistem yerelini ayarlamak kimlik doğrulaması gerektiriyor." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Sistem klavye ayarlarını ayarla" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "Sistem klavye ayarlarını ayarlamak kimlik doğrulaması gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Uygulamaların sistemin kapanmasına engel olmasına izin ver" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Bir uygulamanın sistemin kapanmasına engel olması için kimlik doğrulaması " +"gereklidir." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Uygulamaların sistemin kapanmasını geciktirmelerine izin ver" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Bir uygulamanın sistemin kapanmasını geciktirmesi için kimlik doğrulaması " +"gereklidir." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Uygulamaların sistemin beklemeye geçmesini engellemesine izin ver" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Bir uygulamanın sistemin uykuya geçmesine engel olması için kimlik " +"doğrulaması gereklidir." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Uygulamaların sistemin beklemeye geçmesini ertelemesine izin ver" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Bir uygulamanın sistemin uykuya geçmesini geciktirmesi için kimlik " +"doğrulaması gereklidir." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "" +"Uygulamaların sistemin otomatik bekletmeye geçmesini engellemesine izin ver" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Bir uygulamanın sistemin otomatik olarak askıya alınmasına engel olması için " +"kimlik doğrulaması gereklidir." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "Uygulamaların sistemin güç tuşunun kullanımını engellemesine izin ver" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Bir uygulamanın sistemin güç tuşunu idare etmesine engel olması için kimlik " +"doğrulaması gereklidir." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Uygulamaların sistemin beklet tuşunun kullanımını engellemesine izin ver" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Bir uygulamanın sistemin askıya alma tuşunu idare etmesine engel olması için " +"kimlik doğrulaması gereklidir." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Uygulamaların sistemin uykuya geçme tuşunun kullanımını engellemesine izin " +"ver" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Bir uygulamanın sistemin hazırda bekletme tuşunu idare etmesine engel olması " +"için kimlik doğrulaması gereklidir." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Uygulamaların sistemin kapak anahtarının kullanımını engellemesine izin ver" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Bir uygulamanın sistemin kapak anahtarını idare etmesine engel olması için " +"kimlik doğrulaması gereklidir." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "Oturum açmamış kullanıcının program çalıştırmasına izin ver" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Oturum açmamış bir kullanıcı olarak program çalıştırmak için açıkça istekte " +"bulunulması gerekir." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "Oturum açmamış kullanıcıların program çalıştırmasına izin ver" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Oturum açmamış bir kullanıcı olarak program çalıştırmak için kimlik " +"doğrulaması gereklidir." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Aygıtların yuvaya takılmasına izin ver" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "" +"Bir aygıtın yuvaya takılmasına izin vermek kimlik doğrulaması gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Aygıtın yuvaya eklenmesini sıfırla" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Aygıtların yuvalara nasıl takıldığını sıfırlamak kimlik doğrulama " +"gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Sistemi kapat" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "Sistemi kapatmak için kimlik doğrulaması gerekiyor." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "Diğer kullanıcılar oturum açmışken sistemi kapat" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Diğer kullanıcılar oturum açmışken sistemi kapatmak kimlik doğrulaması " +"gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Bir uygulama engellenmesini isterken sistemi kapat" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Bir uygulama engellenmesini isterken sistemi kapatmak kimlik doğrulaması " +"gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Sistemi yeniden başlat" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "Sistemi yeniden başlatmak kimlik doğrulaması gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "Diğer kullanıcılar oturum açmışken sistemi yeniden başlat" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Diğer kullanıcılar oturum açmışken sistemi yeniden başlatmak kimlik " +"doğrulaması gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Bir uygulama engellenmesini isterken sistemi yeniden başlat" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Bir uygulama engellenmesini isterken sistemi yeniden başlatmak kimlik " +"doğrulaması gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Sistemi durdur" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "Sistemi durdurmak kimlik doğrulaması gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "Diğer kullanıcılar oturum açmışken sistemi durdur" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Diğer kullanıcılar oturum açmışken sistemi durdurmak kimlik doğrulaması " +"gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Bir uygulama engellenmesini isterken sistemi durdur" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Bir uygulama engellenmesini isterken sistemi durdurmak kimlik doğrulaması " +"gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Sistemi askıya al" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "Sistemi askıya almak kimlik doğrulaması gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "Diğer kullanıcılar oturum açmışken sistemi askıya al" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Diğer kullanıcılar oturum açmışken sistemi askıya almak kimlik doğrulaması " +"gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Bir uygulama engellenmesini isterken sistemi askıya al" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Bir uygulama engellenmesini isterken sistemi askıya almak kimlik doğrulaması " +"gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Sistemi hazırda beklet" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "Sistemi hazırda bekletmek kimlik doğrulaması gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "Diğer kullanıcılar oturum açmışken sistemi hazırda beklet" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Diğer kullanıcılar oturum açmışken sistemi hazırda bekletmek kimlik " +"doğrulaması gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Bir uygulama engellenmesini isterken sistemi hazırda beklet" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Bir uygulama engellenmesini isterken sistemi hazırda bekletmek kimlik " +"doğrulaması gerektiriyor." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Aktif oturumları, kullanıcıları ve yuvaları yönet" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Aktif oturumları, kullanıcıları ve yuvaları yönetmek için kimlik doğrulaması " +"gereklidir." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Aktif oturumları kilitle ya da kilidini aç" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "" +"Aktif oturumları kilitlemek ve bunların kilidini açmak için kimlik " +"doğrulaması gereklidir." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "" +"Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesine izin ver" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Kurulum arayüzünü önyüklemek için ürün yazılımının belirtilmesi için kimlik " +"doğrulaması gereklidir." + +#: src/login/org.freedesktop.login1.policy:351 +msgid "Set a wall message" +msgstr "Bir duvar mesajı ayarla" + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Authentication is required to set a wall message" +msgstr "Duvar mesajı ayarlamak için kimlik doğrulaması gereklidir" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Yerel kapsayıcıya giriş yap" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "Yerel kapsayıcıda oturum açmak için kimlik doğrulaması gereklidir." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Yerel (ana) makineye giriş yap" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "Yerel (ana) makinede oturum açmak için kimlik doğrulaması gereklidir." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Yerel kapsayıcıda kabuk (shell) aç" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Yerel kapsayıcıda kabuk (shell) açmak için kimlik doğrulaması gereklidir." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Yerel (ana) makinede kabuk (shell) aç" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "" +"Yerel (ana) makinede kabuk (shell) açmak için kimlik doğrulaması gereklidir." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Yerel kapsayıcıda sözde (pseudo) TTY al" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Yerel kapsayıcıda sözde (pseudo) TTY almak için kimlik doğrulaması " +"gereklidir." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Yerel (ana) makinede sözde (pseudo) TTY al" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "" +"Yerel (ana) makinede sözde (pseudo) TTY almak için kimlik doğrulaması " +"gereklidir." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Yerel sanal makineleri ve kapsayıcıları yönet" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Yerel sanal makineleri ve kapsayıcıları yönetmek için kimlik doğrulaması " +"gereklidir." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Yerel sanal makine ve kapsayıcı kalıplarını yönet" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Yerel sanal makineler ve kapsayıcı kalıplarını yönetmek için kimlik " +"doğrulaması gereklidir." + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "Bir taşınabilir hizmet kalıbını incele" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "" +"Bir taşınabilir hizmet kalıbını incelemek için kimlik doğrulaması gereklidir." + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "Bir taşınabilir hizmet kalıbını tuttur ya da ayır" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "" +"Bir taşınabilir hizmet kalıbını tutturmak ya da ayırmak için kimlik " +"doğrulaması gereklidir." + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "Taşınabilir hizmet kalıbını sil ya da değiştir" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "" +"Taşınabilir hizmet kalıbını silmek ya da değiştirmek için kimlik doğrulaması " +"gereklidir." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Bir DNS-SD hizmeti kaydet" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Bir DNS-SD hizmeti kaydetmek için kimlik doğrulaması gereklidir" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Bir DNS-SD hizmetinin kaydını sil" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "" +"Bir DNS-SD hizmetinin kaydını silmek için kimlik doğrulaması gereklidir" + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Sistem zamanını ayarla" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "Sistem zamanını ayarlamak kimlik doğrulaması gerektiriyor." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Sistem zaman dilimini ayarla" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "Sistem zaman dilimini ayarlamak kimlik doğrulaması gerektiriyor." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "Gerçek zamanlı saat olarak yerel zaman dilimini veya UTC'yi ayarla" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Gerçek zamanlı saat olarak yerel zaman dilimini veya UTC'yi ayarlamak kimlik " +"doğrulaması gerektiriyor." + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "Ağ zaman eş zamanlamasını aç veya kapat" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Ağ zaman eş zamanlamasını kontrol etmek kimlik doğrulaması gerektiriyor." + +#: src/core/dbus-unit.c:326 +msgid "Authentication is required to start '$(unit)'." +msgstr "'$(unit)' başlatmak için kimlik doğrulaması gereklidir." + +#: src/core/dbus-unit.c:327 +msgid "Authentication is required to stop '$(unit)'." +msgstr "'$(unit)' durdurmak için kimlik doğrulaması gereklidir." + +#: src/core/dbus-unit.c:328 +msgid "Authentication is required to reload '$(unit)'." +msgstr "'$(unit)' yeniden yüklemek için kimlik doğrulaması gereklidir." + +#: src/core/dbus-unit.c:329 src/core/dbus-unit.c:330 +msgid "Authentication is required to restart '$(unit)'." +msgstr "'$(unit)' yeniden başlatmak için kimlik doğrulaması gereklidir." + +#: src/core/dbus-unit.c:437 +#| msgid "Authentication is required to set properties on '$(unit)'." +msgid "" +"Authentication is required to send a UNIX signal to the processes of " +"'$(unit)'." +msgstr "" +"'$(unit)' süreçlerine bir UNIX sinyali göndermek için kimlik doğrulaması " +"gereklidir." + +#: src/core/dbus-unit.c:468 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "" +"'$(unit)'in \"failed\" (başarısız) durumunu sıfırlamak için kimlik " +"doğrulaması gereklidir." + +#: src/core/dbus-unit.c:501 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "" +"'$(unit)' üzerindeki özellikleri ayarlamak için kimlik doğrulaması " +"gereklidir." + +#~ msgid "Authentication is required to kill '$(unit)'." +#~ msgstr "'$(unit)' sonlandırmak için kimlik doğrulaması gereklidir." diff --git a/po/uk.po b/po/uk.po new file mode 100644 index 00000000..96c0c550 --- /dev/null +++ b/po/uk.po @@ -0,0 +1,813 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# Ukrainian translation for systemd. +# Eugene Melnik , 2014. +# Daniel Korostil , 2014, 2016, 2018. +# Yuri Chornoivan , 2019. +msgid "" +msgstr "" +"Project-Id-Version: systemd master\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2019-07-29 15:34+0000\n" +"PO-Revision-Date: 2019-08-16 09:11+0300\n" +"Last-Translator: Yuri Chornoivan \n" +"Language-Team: Ukrainian \n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<" +"=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Lokalize 19.11.70\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "Надіслати пароль назад у систему" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "" +"Потрібна автентифікація, щоб надіслати введений пароль назад у систему." + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "Керувати системними службами й іншими одиницями systemd" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "" +"Потрібна автентифікація, щоб керувати системними службами й іншими одиницями " +"systemd." + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "Керувати системними службами й одиницями systemd" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "" +"Потрібна автентифікація, щоб керувати системними службами й одиницями " +"systemd." + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "" +"Встановити або забрати змінну середовища з керування службами і системою" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "" +"Потрібна автентифікація, щоб установити або забрати змінні середовища з " +"керування службами і системою." + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "Перезапустити стан системи" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "Потрібна автентифікація, щоб перезапустити стан системи." + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "Встановити назву вузла" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "Потрібна автентифікація, щоб встановити назву локального вузла." + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "Встановити статичну назву вузла" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "" +"Потрібна автентифікація, щоб вказати статично налаштовану назву локального " +"вузла, так само й форматовану." + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "Встановити інформацію про машину" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "Потрібна автентифікація, щоб вказати локальну інформацію про машини." + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "Отримання UUID продукту" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "Потрібна автентифікація, щоб отримати UUID продукту." + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "Імпортувати образ контейнера або віртуальної машини" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "" +"Потрібна автентифікація, щоб імпортувати образ контейнера або віртуальної " +"машини" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "Експортувати образ контейнера або віртуальної машини" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "" +"Потрібна автентифікація, щоб експортувати образ контейнера або віртуальної " +"машини" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "Звантажити образ контейнера або віртуальної машини" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "" +"Потрібна автентифікація, щоб звантажити образ контейнера або віртуальної " +"машини" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "Вказати системну локаль" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "Потрібна автентифікація, щоб встановити системну локаль." + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "Вказати налаштування системної клавіатури" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "" +"Потрібна автентифікація, щоб вказати налаштування системної клавіатури." + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "Дозволити програмам перешкоджати вимкненню системи" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "" +"Потрібна автентифікація, щоб дозволити програмам перешкоджати вимкненню " +"системи." + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "Дозволити програмам затримувати вимкнення системи" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "" +"Потрібна автентифікація, щоб дозволити програмам затримувати вимкнення " +"системи." + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "Дозволити програмам перешкоджати засинанню системи" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "" +"Потрібна автентифікація, щоб дозволити програмам перешкоджати засинанню " +"системи." + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "Дозволити програмами затримувати засинання системи" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "" +"Потрібна автентифікація, щоб дозволити програмам затримувати засинання " +"системи." + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "Дозволити програмам перешкоджати автоматичному призупиненню системи" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "" +"Потрібна автентифікація, щоб дозволити програмам перешкоджати автоматичному " +"призупиненню системи." + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "Дозволити програмам перешкоджати обробленню системою клавіші живлення" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "" +"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню " +"системою клавіші живлення." + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "" +"Дозволити програмам перешкоджати обробленню системою клавіші призупинення" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "" +"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню " +"системою клавіші призупинення." + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "" +"Дозволити програмам перешкоджати обробленню системою клавіші присипання" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "" +"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню " +"системою клавіші присипання." + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "" +"Дозволити програмам перешкоджати обробленню системою клавіші перемикання " +"кришки" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "" +"Потрібна автентифікація, щоб дозволити програмам перешкоджати обробленню " +"системою клавіші перемикання кришки." + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "Дозволити незареєстрованим користувачам запускати програми" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "" +"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам " +"запускати програми." + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "Дозволити незареєстрованим користувачам запускати програми" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "" +"Потрібна автентифікація, щоб дозволити незареєстрованим користувачам " +"запускати програми." + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "Дозволити під'єднання пристроїв до місць" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "Потрібна автентифікація, щоб під'єднувати пристрої до місць." + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "Очисний пристрій для під'єднань до місця" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "" +"Потрібна автентифікація, щоб перезапустити спосіб під'єднання до місць." + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "Вимкнути систему" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "Потрібна автентифікація, щоб вимкнути систему." + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "Вимкнути систему, коли інші користувачі ще в ній" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "" +"Потрібна автентифікація, щоб вимкнути систему, коли інші користувачі в ній." + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "Вимкнути систему, коли програми намагаються перешкодити цьому" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "" +"Потрібна автентифікація, щоб вимкнути систему, коли програми намагаються " +"перешкодити цьому." + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "Перезавантажити систему" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "Для перезавантаження системи необхідна ідентифікація." + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "Перезавантажити, якщо інші користувачі в системі" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "" +"Потрібна автентифікація, щоб перезапустити систему, коли інші користувачі в " +"ній." + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "Перезапустити систему, коли програми намагаються перешкодити цьому" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "" +"Потрібна автентифікація, щоб перезапустити систему, коли програми " +"намагаються перешкодити цьому." + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "Зупинити систему" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "Потрібна автентифікація, щоб зупинити систему." + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "Зупинити систему, коли інші користувачі в ній" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "" +"Потрібна автентифікація, щоб зупинити систему, коли інші користувачі в ній." + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "Зупинити систему, коли програми намагаються перешкодити цьому" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "" +"Потрібна автентифікація, щоб зупинити систему, коли програми намагаються " +"перешкодити цьому." + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "Призупинити систему" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "Потрібна автентифікація, щоб призупинити систему." + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "Призупинити систему, коли інші користувачі в ній" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "" +"Потрібна автентифікація, щоб призупинити систему, коли інші користувачі в " +"ній." + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "Призупинити систему, коли програми намагаються перешкодити цьому" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "" +"Потрібна автентифікація, щоб призупинити систему, коли програми намагаються " +"перешкодити цьому." + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "Приспати систему" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "Потрібна автентифікація, щоб приспати систему." + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "Приспати систему, коли інші користувачі в ній" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "" +"Потрібна автентифікація, щоб присипання систему, коли інші користувачі в ній." + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "Приспати систему, коли програми намагаються перешкодити цьому" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "" +"Потрібна автентифікація, щоб приспати систему, коли програми намагаються " +"перешкодити цьому." + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "Керувати сеансами, користувачами і робочими місцями" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "" +"Потрібна автентифікація, щоб керувати сеансами, користувачами і робочими " +"місцями." + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "Заблокувати або розблокувати сеанси" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "Потрібна автентифікація, щоб заблокувати або розблокувати сеанси." + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Set the reboot \"reason\" in the kernel" +msgstr "Встановлення «причини» перезавантаження у ядрі" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "Authentication is required to set the reboot \"reason\" in the kernel." +msgstr "" +"Потрібна автентифікація, щоб встановити «причину» перезавантаження у ядрі." + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Indicate to the firmware to boot to setup interface" +msgstr "Визначення для мікрокоду завантаження інтерфейсу встановлення" + +#: src/login/org.freedesktop.login1.policy:353 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "" +"Потрібна автентифікація, щоб дозволити мікрокоду визначати, чи завантажувати " +"інтерфейс встановлення." + +#: src/login/org.freedesktop.login1.policy:363 +msgid "Indicate to the boot loader to boot to the boot loader menu" +msgstr "Визначення для завантажувача завантаження до меню завантажувача" + +#: src/login/org.freedesktop.login1.policy:364 +msgid "" +"Authentication is required to indicate to the boot loader to boot to the " +"boot loader menu." +msgstr "" +"Потрібна автентифікація, щоб вказати завантажувачу, що слід завантажитися до " +"меню завантажувача." + +#: src/login/org.freedesktop.login1.policy:374 +msgid "Indicate to the boot loader to boot a specific entry" +msgstr "Визначення для завантажувача певного пункту для завантаження" + +#: src/login/org.freedesktop.login1.policy:375 +msgid "" +"Authentication is required to indicate to the boot loader to boot into a " +"specific boot loader entry." +msgstr "" +"Потрібна автентифікація, щоб вказати завантажувачу, що слід завантажити " +"певний пункт меню завантаження." + +#: src/login/org.freedesktop.login1.policy:385 +msgid "Set a wall message" +msgstr "Вказати повідомлення на стіні" + +#: src/login/org.freedesktop.login1.policy:386 +msgid "Authentication is required to set a wall message" +msgstr "Потрібна автентифікація, щоб вказати повідомлення на стіні" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "Увійти в локальний контейнер" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "Потрібна автентифікація, щоб увійти в локальний контейнер." + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "Увійти в локальний вузол" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "Потрібна автентифікація, щоб увійти в локальний вузол." + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "Перейняти оболонку в локальному контейнері" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "" +"Потрібна автентифікація, щоб перейняти оболонку в локальному контейнері." + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "Перейняти оболонку на локальному вузлі" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "Потрібна автентифікація, щоб перейняти оболонку на локальному вузлі." + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "Перейняти псевдо TTY в локальному контейнері" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "" +"Потрібна автентифікація, щоб перейняти псевдо TTY в локальному контейнері." + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "Перейняти псевдо TTY на локальному вузлі" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "Потрібна автентифікація, щоб перейняти псевдо TTY на локальному вузлі." + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "Керувати локальними віртуальними машинами і контейнерами" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "" +"Потрібна автентифікація, щоб керувати локальними віртуальними машинами і " +"контейнерами." + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "Керувати локальними образами віртуальних машин і контейнерів" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "" +"Потрібна автентифікація, щоб керувати локальними образами віртуальних машин " +"і контейнерів." + +#: src/network/org.freedesktop.network1.policy:22 +msgid "Set NTP servers" +msgstr "Встановлення серверів NTP" + +#: src/network/org.freedesktop.network1.policy:23 +msgid "Authentication is required to set NTP servers." +msgstr "Потрібна автентифікація, щоб встановити сервери NTP." + +#: src/network/org.freedesktop.network1.policy:33 +msgid "Set DNS servers" +msgstr "Встановлення серверів DNS" + +#: src/network/org.freedesktop.network1.policy:34 +msgid "Authentication is required to set DNS servers." +msgstr "Потрібна автентифікація, щоб встановити сервери DNS." + +#: src/network/org.freedesktop.network1.policy:44 +msgid "Set domains" +msgstr "Встановлення доменів" + +#: src/network/org.freedesktop.network1.policy:45 +msgid "Authentication is required to set domains." +msgstr "Потрібна автентифікація, щоб встановити домени." + +#: src/network/org.freedesktop.network1.policy:55 +msgid "Set default route" +msgstr "Встановлення типового маршруту" + +#: src/network/org.freedesktop.network1.policy:56 +msgid "Authentication is required to set default route." +msgstr "Потрібна автентифікація, щоб встановити типовий маршрут." + +#: src/network/org.freedesktop.network1.policy:66 +msgid "Enable/disable LLMNR" +msgstr "Вмикання або вимикання LLMNR" + +#: src/network/org.freedesktop.network1.policy:67 +msgid "Authentication is required to enable or disable LLMNR." +msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути LLMNR." + +#: src/network/org.freedesktop.network1.policy:77 +msgid "Enable/disable multicast DNS" +msgstr "Вмикання або вимикання трансляційного DNS" + +#: src/network/org.freedesktop.network1.policy:78 +msgid "Authentication is required to enable or disable multicast DNS." +msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути трансляційну DNS." + +#: src/network/org.freedesktop.network1.policy:88 +msgid "Enable/disable DNS over TLS" +msgstr "Вмикання і вимикання DNS через TLS" + +#: src/network/org.freedesktop.network1.policy:89 +msgid "Authentication is required to enable or disable DNS over TLS." +msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути DNS через TLS." + +#: src/network/org.freedesktop.network1.policy:99 +msgid "Enable/disable DNSSEC" +msgstr "Вмикання або вимикання DNSSEC" + +#: src/network/org.freedesktop.network1.policy:100 +msgid "Authentication is required to enable or disable DNSSEC." +msgstr "Потрібна автентифікація, щоб увімкнути або вимкнути DNSSEC." + +#: src/network/org.freedesktop.network1.policy:110 +msgid "Set DNSSEC Negative Trust Anchors" +msgstr "Встановлення прив'язок від'ємної довіри DNSSEC" + +#: src/network/org.freedesktop.network1.policy:111 +msgid "Authentication is required to set DNSSEC Negative Trust Anchors." +msgstr "" +"Потрібна автентифікація, щоб встановити прив'язки від'ємної довіри DNSSEC." + +#: src/network/org.freedesktop.network1.policy:121 +msgid "Revert NTP settings" +msgstr "Повернення до початкових параметрів NTP" + +#: src/network/org.freedesktop.network1.policy:122 +msgid "Authentication is required to revert NTP settings." +msgstr "Потрібна автентифікація, щоб повернутися до початкових параметрів NTP." + +#: src/network/org.freedesktop.network1.policy:132 +msgid "Revert DNS settings" +msgstr "Повернення до початкових параметрів DNS" + +#: src/network/org.freedesktop.network1.policy:133 +msgid "Authentication is required to revert DNS settings." +msgstr "Потрібна автентифікація, щоб повернутися до початкових параметрів DNS." + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "Інспектування образу портативної служби" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "Потрібна автентифікація, щоб інспектувати образ портативної служби." + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "Долучення або вилучення образу портативної служби" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "" +"Потрібна автентифікація, щоб долучити або вилучити образ портативної служби." + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "Вилучення або внесення змін до образу портативної служби" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "" +"Потрібна автентифікація, щоб вилучити образ портативної служби або внести до " +"нього зміни." + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "Зареєструвати службу DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "Потрібна автентифікація, щоб зареєструвати службу DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "Зняти з реєстрації службу DNS-SD" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "Потрібна автентифікація, щоб зняти з реєстрації службу DNS-SD" + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "Вказати системний час" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "Потрібна автентифікація, щоб вказати системний час." + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "Вказати системний часовий пояс" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "Потрібна автентифікація, щоб вказати системний часовий пояс." + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "Вкажіть RTC для локального часового поясу або UTC" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "" +"Потрібна автентифікація, щоб контролювати, чи зберігає RTC локальний час або " +"UTC." + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "Увімкнути або вимкнути синхронізування часу через мережу" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "" +"Потрібна автентифікація, щоб контролювати, чи синхронізування часу через " +"мережу запущено." + +#: src/core/dbus-unit.c:354 +msgid "Authentication is required to start '$(unit)'." +msgstr "Потрібна автентифікація, щоб запустити «$(unit)»." + +#: src/core/dbus-unit.c:355 +msgid "Authentication is required to stop '$(unit)'." +msgstr "Потрібна автентифікація, щоб зупинити «$(unit)»." + +#: src/core/dbus-unit.c:356 +msgid "Authentication is required to reload '$(unit)'." +msgstr "Потрібна автентифікація, щоб перезавантажити «$(unit)»." + +#: src/core/dbus-unit.c:357 src/core/dbus-unit.c:358 +msgid "Authentication is required to restart '$(unit)'." +msgstr "Потрібна автентифікація, щоб перезапустити «$(unit)»." + +#: src/core/dbus-unit.c:530 +msgid "" +"Authentication is required to send a UNIX signal to the processes of " +"'$(unit)'." +msgstr "" +"Потрібна автентифікація, щоб надіслати сигнал UNIX до процесів «$(unit)»." + +#: src/core/dbus-unit.c:561 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "Потрібна автентифікація, щоб скинути «пошкоджений» стан з «$(unit)»." + +#: src/core/dbus-unit.c:594 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "Потрібна автентифікація, щоб вказати властивості на «$(unit)»." + +#: src/core/dbus-unit.c:703 +msgid "" +"Authentication is required to delete files and directories associated with " +"'$(unit)'." +msgstr "" +"Потрібна автентифікація, щоб вилучити файли і каталоги, які пов'язано із" +" «$(unit)»." diff --git a/po/zh_CN.po b/po/zh_CN.po new file mode 100644 index 00000000..18c966ab --- /dev/null +++ b/po/zh_CN.po @@ -0,0 +1,524 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Simplified Chinese translation for systemd. +# +# Frank Hill , 2014. +# Boyuan Yang <073plan@gmail.com>, 2015. +# Jeff Bai , 2016. +msgid "" +msgstr "" +"Project-Id-Version: systemd\n" +"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n" +"POT-Creation-Date: 2015-10-27 02:24+0000\n" +"PO-Revision-Date: 2016-03-01 20:38-0700\n" +"Last-Translator: Jeff Bai \n" +"Language-Team: Chinese \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.7.1\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:1 +msgid "Send passphrase back to system" +msgstr "将密码发回系统" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:2 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "将输入的密码发回系统需要认证。" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:3 +msgid "Manage system services or other units" +msgstr "管理系统服务或其它单元" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:4 +msgid "Authentication is required to manage system services or other units." +msgstr "管理系统服务或其它单元需要认证。" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:5 +msgid "Manage system service or unit files" +msgstr "管理系统服务或单元文件" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:6 +msgid "Authentication is required to manage system service or unit files." +msgstr "管理系统服务或单元文件需要认证。" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:7 +msgid "Set or unset system and service manager environment variables" +msgstr "设置或清除系统及服务管理器的环境变量" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:8 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "设置或清除系统及服务管理器的环境变量需要认证。" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:9 +msgid "Reload the systemd state" +msgstr "重新载入 systemd 状态" + +#: ../src/core/org.freedesktop.systemd1.policy.in.in.h:10 +msgid "Authentication is required to reload the systemd state." +msgstr "重新载入 systemd 状态需要认证。" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:1 +msgid "Set host name" +msgstr "设置主机名" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:2 +msgid "Authentication is required to set the local host name." +msgstr "设置本地主机名需要认证。" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:3 +msgid "Set static host name" +msgstr "设置静态主机名" + +# For pretty hostname, the zh_CN/zh_TW translation should be discussed again. +# +# There were some discussions, like https://lists.fedoraprojects.org/pipermail/trans-zh_cn/2012-December/001347.html +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:4 +#, fuzzy +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "设置静态本地主机名或美观主机名需要认证。" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:5 +msgid "Set machine information" +msgstr "设置机器信息" + +#: ../src/hostname/org.freedesktop.hostname1.policy.in.h:6 +msgid "Authentication is required to set local machine information." +msgstr "设置本地机器信息需要认证。" + +#: ../src/import/org.freedesktop.import1.policy.in.h:1 +msgid "Import a VM or container image" +msgstr "导入虚拟机或容器镜像" + +#: ../src/import/org.freedesktop.import1.policy.in.h:2 +msgid "Authentication is required to import a VM or container image" +msgstr "导入虚拟机或容器镜像需要认证" + +#: ../src/import/org.freedesktop.import1.policy.in.h:3 +msgid "Export a VM or container image" +msgstr "导出虚拟机或容器镜像" + +#: ../src/import/org.freedesktop.import1.policy.in.h:4 +msgid "Authentication is required to export a VM or container image" +msgstr "导出虚拟机或容器镜像需要认证" + +#: ../src/import/org.freedesktop.import1.policy.in.h:5 +msgid "Download a VM or container image" +msgstr "下载虚拟机或容器镜像" + +#: ../src/import/org.freedesktop.import1.policy.in.h:6 +msgid "Authentication is required to download a VM or container image" +msgstr "下载虚拟机或容器镜像需要认证。" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:1 +msgid "Set system locale" +msgstr "设置系统区域和语言" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:2 +msgid "Authentication is required to set the system locale." +msgstr "设置系统区域和语言需要认证。" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:3 +msgid "Set system keyboard settings" +msgstr "设置系统键盘" + +#: ../src/locale/org.freedesktop.locale1.policy.in.h:4 +msgid "Authentication is required to set the system keyboard settings." +msgstr "设置系统键盘需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:1 +msgid "Allow applications to inhibit system shutdown" +msgstr "允许应用程序阻止系统关机" + +#: ../src/login/org.freedesktop.login1.policy.in.h:2 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "允许应用程序阻止系统关机需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:3 +msgid "Allow applications to delay system shutdown" +msgstr "允许应用程序延迟系统关机" + +#: ../src/login/org.freedesktop.login1.policy.in.h:4 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "允许应用程序延迟系统关机需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:5 +msgid "Allow applications to inhibit system sleep" +msgstr "允许应用程序阻止系统睡眠" + +#: ../src/login/org.freedesktop.login1.policy.in.h:6 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "允许应用程序阻止系统睡眠需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:7 +msgid "Allow applications to delay system sleep" +msgstr "允许应用程序延迟系统睡眠" + +#: ../src/login/org.freedesktop.login1.policy.in.h:8 +msgid "Authentication is required for an application to delay system sleep." +msgstr "允许应用程序延迟系统睡眠需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:9 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "允许应用程序阻止系统自动挂起" + +#: ../src/login/org.freedesktop.login1.policy.in.h:10 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "允许应用程序阻止系统自动挂起需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:11 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "允许应用程序阻止系统响应电源键" + +#: ../src/login/org.freedesktop.login1.policy.in.h:12 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "允许应用程序阻止系统响应电源键需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:13 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "允许应用程序阻止系统响应挂起键" + +#: ../src/login/org.freedesktop.login1.policy.in.h:14 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "允许应用程序阻止系统响应挂起键需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:15 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "允许应用程序阻止系统响应挂起键" + +#: ../src/login/org.freedesktop.login1.policy.in.h:16 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "允许应用程序阻止系统响应挂起键需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:17 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "允许应用程序阻止系统响应笔记本上盖开关事件" + +#: ../src/login/org.freedesktop.login1.policy.in.h:18 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "允许应用程序阻止系统响应笔记本上盖开关事件需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:19 +msgid "Allow non-logged-in users to run programs" +msgstr "允许未登录用户运行程序" + +#: ../src/login/org.freedesktop.login1.policy.in.h:20 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "允许未登录用户运行程序需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:21 +msgid "Allow attaching devices to seats" +msgstr "允许将设备附加至会话座位" + +# Pay attention to the concept of "seat". +# +# To fully understand the meaning, please refer to session management in old ConsoleKit and new systemd-logind. +#: ../src/login/org.freedesktop.login1.policy.in.h:22 +msgid "Authentication is required for attaching a device to a seat." +msgstr "允许将设备附加至某个会话座位需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:23 +msgid "Flush device to seat attachments" +msgstr "刷新设备至会话座位间的连接" + +#: ../src/login/org.freedesktop.login1.policy.in.h:24 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "重新设定设备的会话座位接入方式时需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:25 +msgid "Power off the system" +msgstr "关闭系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:26 +msgid "Authentication is required for powering off the system." +msgstr "关闭系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:27 +msgid "Power off the system while other users are logged in" +msgstr "存在其他已登录用户时仍然关机" + +#: ../src/login/org.freedesktop.login1.policy.in.h:28 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "存在其他已登录用户时关闭系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:29 +msgid "Power off the system while an application asked to inhibit it" +msgstr "有其它应用程序阻止时仍然关机" + +#: ../src/login/org.freedesktop.login1.policy.in.h:30 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "在其它应用程序阻止关机时关闭系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:31 +msgid "Reboot the system" +msgstr "重启系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:32 +msgid "Authentication is required for rebooting the system." +msgstr "重启系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:33 +msgid "Reboot the system while other users are logged in" +msgstr "存在其他已登录用户时仍然重启" + +#: ../src/login/org.freedesktop.login1.policy.in.h:34 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "存在其他已登录用户时重启系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:35 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "有其它应用程序阻止时仍然重启" + +#: ../src/login/org.freedesktop.login1.policy.in.h:36 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "在其它应用程序阻止重启时重启系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:37 +msgid "Suspend the system" +msgstr "挂起系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:38 +msgid "Authentication is required for suspending the system." +msgstr "挂起系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:39 +msgid "Suspend the system while other users are logged in" +msgstr "存在其他已登录用户时仍然挂起系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:40 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "存在其他已登录用户时挂起系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:41 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "有其它应用程序阻止时仍然挂起系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:42 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "在其它应用程序阻止挂起时挂起系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:43 +msgid "Hibernate the system" +msgstr "休眠系统" + +#: ../src/login/org.freedesktop.login1.policy.in.h:44 +msgid "Authentication is required for hibernating the system." +msgstr "休眠系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:45 +msgid "Hibernate the system while other users are logged in" +msgstr "存在其他已登录用户时仍然休眠" + +#: ../src/login/org.freedesktop.login1.policy.in.h:46 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "存在其他已登录用户时进行休眠系统需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:47 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "有其它应用程序阻止时仍然休眠" + +#: ../src/login/org.freedesktop.login1.policy.in.h:48 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "在其它应用程序阻止休眠时进行休眠需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:49 +msgid "Manage active sessions, users and seats" +msgstr "管理活动会话、用户与会话座位" + +#: ../src/login/org.freedesktop.login1.policy.in.h:50 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "管理活动会话、用户与会话座位需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:51 +msgid "Lock or unlock active sessions" +msgstr "锁定或解锁活动会话" + +#: ../src/login/org.freedesktop.login1.policy.in.h:52 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "对活动会话进行锁定或解锁需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:53 +msgid "Allow indication to the firmware to boot to setup interface" +msgstr "允许向固件发出指示以启动至设置界面" + +#: ../src/login/org.freedesktop.login1.policy.in.h:54 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "向固件发出启动时进入设置界面的指令需要认证。" + +#: ../src/login/org.freedesktop.login1.policy.in.h:55 +msgid "Set a wall message" +msgstr "设置 wall 消息" + +#: ../src/login/org.freedesktop.login1.policy.in.h:56 +msgid "Authentication is required to set a wall message" +msgstr "设置 wall 消息需要认证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:1 +msgid "Log into a local container" +msgstr "登入本地容器" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:2 +msgid "Authentication is required to log into a local container." +msgstr "登录一个本地容器需要认证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:3 +msgid "Log into the local host" +msgstr "登入本地主机" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:4 +msgid "Authentication is required to log into the local host." +msgstr "登入本地主机需要认证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:5 +msgid "Acquire a shell in a local container" +msgstr "在本地容器中获取一个 shell" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:6 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "在本地容器中获取 shell 需要认证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:7 +msgid "Acquire a shell on the local host" +msgstr "在本地主机中获取一个 shell" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:8 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "在本地主机中获取 shell 需要认证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:9 +msgid "Acquire a pseudo TTY in a local container" +msgstr "在本地容器中获取一个假 TTY" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:10 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "在本地容器中获取假 TTY 需要认证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:11 +msgid "Acquire a pseudo TTY on the local host" +msgstr "在本地主机中获取一个假 TTY" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:12 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "在本地主机中获取假 TTY 需要认证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:13 +msgid "Manage local virtual machines and containers" +msgstr "管理本地虚拟机和容器" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:14 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "管理本地虚拟机和容器需要认证。" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:15 +msgid "Manage local virtual machine and container images" +msgstr "管理本地虚拟机和容器的镜像" + +#: ../src/machine/org.freedesktop.machine1.policy.in.h:16 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "管理本地的虚拟机和容器镜像需要认证。" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:1 +msgid "Set system time" +msgstr "设置系统时间" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:2 +msgid "Authentication is required to set the system time." +msgstr "设置系统时间需要认证。" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:3 +msgid "Set system timezone" +msgstr "设置系统时区" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:4 +msgid "Authentication is required to set the system timezone." +msgstr "设置系统时区需要认证。" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:5 +msgid "Set RTC to local timezone or UTC" +msgstr "设置硬件时钟使用本地时间或 UTC" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:6 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "设置硬件时钟使用本地时间或 UTC 需要认证。" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:7 +msgid "Turn network time synchronization on or off" +msgstr "打开或关闭网络时间同步" + +#: ../src/timedate/org.freedesktop.timedate1.policy.in.h:8 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "打开或关闭网络时间同步需要认证。" + +#: ../src/core/dbus-unit.c:430 +msgid "Authentication is required to start '$(unit)'." +msgstr "启动“$(unit)”需要认证。" + +#: ../src/core/dbus-unit.c:431 +msgid "Authentication is required to stop '$(unit)'." +msgstr "停止“$(unit)”需要认证。" + +#: ../src/core/dbus-unit.c:432 +msgid "Authentication is required to reload '$(unit)'." +msgstr "重新载入“$(unit)”需要认证。" + +#: ../src/core/dbus-unit.c:433 ../src/core/dbus-unit.c:434 +msgid "Authentication is required to restart '$(unit)'." +msgstr "重新启动“$(unit)”需要认证。" + +#: ../src/core/dbus-unit.c:537 +msgid "Authentication is required to kill '$(unit)'." +msgstr "杀死“$(unit)”需要认证。" + +#: ../src/core/dbus-unit.c:567 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "重置“$(unit)”的失败(\"failed\")状态需要认证。" + +#: ../src/core/dbus-unit.c:599 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "设置“$(unit)”的属性需要认证。" diff --git a/po/zh_TW.po b/po/zh_TW.po new file mode 100644 index 00000000..4e5e4bf8 --- /dev/null +++ b/po/zh_TW.po @@ -0,0 +1,760 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# Traditional Chinese translation for systemd. +# Jeff Huang , 2015, 2016. +# pan93412 , 2019. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-10-23 19:12+0800\n" +"PO-Revision-Date: 2019-10-23 19:19+0800\n" +"Last-Translator: pan93412 \n" +"Language-Team: Chinese \n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 19.08.2\n" + +#: src/core/org.freedesktop.systemd1.policy.in:22 +msgid "Send passphrase back to system" +msgstr "將密碼片語傳回系統" + +#: src/core/org.freedesktop.systemd1.policy.in:23 +msgid "" +"Authentication is required to send the entered passphrase back to the system." +msgstr "將已輸入的密碼片語傳回系統需要驗證。" + +#: src/core/org.freedesktop.systemd1.policy.in:33 +msgid "Manage system services or other units" +msgstr "管理系統服務或其他單位" + +#: src/core/org.freedesktop.systemd1.policy.in:34 +msgid "Authentication is required to manage system services or other units." +msgstr "管理系統服務或其他單位需要驗證。" + +#: src/core/org.freedesktop.systemd1.policy.in:43 +msgid "Manage system service or unit files" +msgstr "管理系統服務或單位檔案" + +#: src/core/org.freedesktop.systemd1.policy.in:44 +msgid "Authentication is required to manage system service or unit files." +msgstr "管理系統服務或單位檔案需要驗證。" + +#: src/core/org.freedesktop.systemd1.policy.in:54 +msgid "Set or unset system and service manager environment variables" +msgstr "設定或取消設定系統及服務管理員環境變數" + +#: src/core/org.freedesktop.systemd1.policy.in:55 +msgid "" +"Authentication is required to set or unset system and service manager " +"environment variables." +msgstr "設定或取消設定系統及服務管理員的環境變數需要身份驗證。" + +#: src/core/org.freedesktop.systemd1.policy.in:64 +msgid "Reload the systemd state" +msgstr "重新載入 systemd 狀態" + +#: src/core/org.freedesktop.systemd1.policy.in:65 +msgid "Authentication is required to reload the systemd state." +msgstr "重新載入 systemd 狀態需要驗證。" + +#: src/hostname/org.freedesktop.hostname1.policy:20 +msgid "Set host name" +msgstr "設定主機名稱" + +#: src/hostname/org.freedesktop.hostname1.policy:21 +msgid "Authentication is required to set the local host name." +msgstr "設定主機名稱需要驗證。" + +#: src/hostname/org.freedesktop.hostname1.policy:30 +msgid "Set static host name" +msgstr "設定靜態主機名稱" + +#: src/hostname/org.freedesktop.hostname1.policy:31 +msgid "" +"Authentication is required to set the statically configured local host name, " +"as well as the pretty host name." +msgstr "設定靜態預先設定或 pretty 本地主機名稱需要身份驗證。" + +#: src/hostname/org.freedesktop.hostname1.policy:41 +msgid "Set machine information" +msgstr "設定機器資訊" + +#: src/hostname/org.freedesktop.hostname1.policy:42 +msgid "Authentication is required to set local machine information." +msgstr "設定本地機器資訊需要身份驗證。" + +#: src/hostname/org.freedesktop.hostname1.policy:51 +msgid "Get product UUID" +msgstr "取得產品的 UUID" + +#: src/hostname/org.freedesktop.hostname1.policy:52 +msgid "Authentication is required to get product UUID." +msgstr "取得產品 UUID 需要身份驗證。" + +#: src/import/org.freedesktop.import1.policy:22 +msgid "Import a VM or container image" +msgstr "匯入虛擬機器或容器映像" + +#: src/import/org.freedesktop.import1.policy:23 +msgid "Authentication is required to import a VM or container image" +msgstr "匯入虛擬機器或容器映像需要驗證" + +#: src/import/org.freedesktop.import1.policy:32 +msgid "Export a VM or container image" +msgstr "匯出虛擬機器或容器映像" + +#: src/import/org.freedesktop.import1.policy:33 +msgid "Authentication is required to export a VM or container image" +msgstr "匯出虛擬機器或容器映像需要驗證" + +#: src/import/org.freedesktop.import1.policy:42 +msgid "Download a VM or container image" +msgstr "下載虛擬機器或容器映像" + +#: src/import/org.freedesktop.import1.policy:43 +msgid "Authentication is required to download a VM or container image" +msgstr "下載虛擬機器或容器映像需要驗證" + +#: src/locale/org.freedesktop.locale1.policy:22 +msgid "Set system locale" +msgstr "設定系統語系" + +#: src/locale/org.freedesktop.locale1.policy:23 +msgid "Authentication is required to set the system locale." +msgstr "設定系統語系需要驗證。" + +#: src/locale/org.freedesktop.locale1.policy:33 +msgid "Set system keyboard settings" +msgstr "設定系統鍵盤設定" + +#: src/locale/org.freedesktop.locale1.policy:34 +msgid "Authentication is required to set the system keyboard settings." +msgstr "設定系統鍵盤設定需要驗證。" + +#: src/login/org.freedesktop.login1.policy:22 +msgid "Allow applications to inhibit system shutdown" +msgstr "允許應用程式阻止系統關機" + +#: src/login/org.freedesktop.login1.policy:23 +msgid "" +"Authentication is required for an application to inhibit system shutdown." +msgstr "要讓應用程式阻止系統關機需要驗證。" + +#: src/login/org.freedesktop.login1.policy:33 +msgid "Allow applications to delay system shutdown" +msgstr "允許應用程式延遲系統關機" + +#: src/login/org.freedesktop.login1.policy:34 +msgid "Authentication is required for an application to delay system shutdown." +msgstr "要讓應用程式延遲系統關機需要驗證。" + +#: src/login/org.freedesktop.login1.policy:44 +msgid "Allow applications to inhibit system sleep" +msgstr "允許應用程式阻止系統睡眠" + +#: src/login/org.freedesktop.login1.policy:45 +msgid "Authentication is required for an application to inhibit system sleep." +msgstr "要讓應用程式阻止系統睡眠需要驗證。" + +#: src/login/org.freedesktop.login1.policy:55 +msgid "Allow applications to delay system sleep" +msgstr "允許應用程式延遲系統睡眠" + +#: src/login/org.freedesktop.login1.policy:56 +msgid "Authentication is required for an application to delay system sleep." +msgstr "要讓應用程式延遲系統睡眠需要驗證。" + +#: src/login/org.freedesktop.login1.policy:65 +msgid "Allow applications to inhibit automatic system suspend" +msgstr "允許應用程式阻止自動系統暫停" + +#: src/login/org.freedesktop.login1.policy:66 +msgid "" +"Authentication is required for an application to inhibit automatic system " +"suspend." +msgstr "要讓應用程式阻止自動系統暫停需要驗證。" + +#: src/login/org.freedesktop.login1.policy:75 +msgid "Allow applications to inhibit system handling of the power key" +msgstr "允許應用程式阻止系統處理電源鍵" + +#: src/login/org.freedesktop.login1.policy:76 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the power key." +msgstr "要讓應用程式阻止系統處理電源鍵需要驗證。" + +#: src/login/org.freedesktop.login1.policy:86 +msgid "Allow applications to inhibit system handling of the suspend key" +msgstr "允許應用程式阻止系統處理暫停鍵" + +#: src/login/org.freedesktop.login1.policy:87 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the suspend key." +msgstr "要讓應用程式阻止系統處理暫停鍵需要驗證。" + +#: src/login/org.freedesktop.login1.policy:97 +msgid "Allow applications to inhibit system handling of the hibernate key" +msgstr "允許應用程式阻止系統處理冬眠鍵" + +#: src/login/org.freedesktop.login1.policy:98 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the hibernate key." +msgstr "要讓應用程式阻止系統處理冬眠鍵需要驗證。" + +#: src/login/org.freedesktop.login1.policy:107 +msgid "Allow applications to inhibit system handling of the lid switch" +msgstr "允許應用程式阻止系統處理上蓋開關" + +#: src/login/org.freedesktop.login1.policy:108 +msgid "" +"Authentication is required for an application to inhibit system handling of " +"the lid switch." +msgstr "要讓應用程式阻止系統處理上蓋開關需要驗證。" + +#: src/login/org.freedesktop.login1.policy:117 +msgid "Allow non-logged-in user to run programs" +msgstr "允許未登入的使用者執行程式" + +#: src/login/org.freedesktop.login1.policy:118 +msgid "Explicit request is required to run programs as a non-logged-in user." +msgstr "需要明確請求,才能以未登入使用者身份執行程式。" + +#: src/login/org.freedesktop.login1.policy:127 +msgid "Allow non-logged-in users to run programs" +msgstr "允許未登入的使用者執行程式" + +#: src/login/org.freedesktop.login1.policy:128 +msgid "Authentication is required to run programs as a non-logged-in user." +msgstr "要讓未登入的使用者執行程式需要驗證。" + +#: src/login/org.freedesktop.login1.policy:137 +msgid "Allow attaching devices to seats" +msgstr "允許將設備連接到座位" + +#: src/login/org.freedesktop.login1.policy:138 +msgid "Authentication is required for attaching a device to a seat." +msgstr "將設備連接到座位需要驗證。" + +#: src/login/org.freedesktop.login1.policy:148 +msgid "Flush device to seat attachments" +msgstr "暴露裝置以安裝附件" + +#: src/login/org.freedesktop.login1.policy:149 +msgid "" +"Authentication is required for resetting how devices are attached to seats." +msgstr "要重置裝置如何連接到座位需要驗證。" + +#: src/login/org.freedesktop.login1.policy:158 +msgid "Power off the system" +msgstr "關閉系統電源" + +#: src/login/org.freedesktop.login1.policy:159 +msgid "Authentication is required for powering off the system." +msgstr "關閉系統電源需要身份驗證。" + +#: src/login/org.freedesktop.login1.policy:169 +msgid "Power off the system while other users are logged in" +msgstr "在有其他使用者登入時關閉系統電源" + +#: src/login/org.freedesktop.login1.policy:170 +msgid "" +"Authentication is required for powering off the system while other users are " +"logged in." +msgstr "在有其他使用者登入時關閉系統電源需要驗證。" + +#: src/login/org.freedesktop.login1.policy:180 +msgid "Power off the system while an application asked to inhibit it" +msgstr "當應用程式阻止系統電源關閉時將其關閉" + +#: src/login/org.freedesktop.login1.policy:181 +msgid "" +"Authentication is required for powering off the system while an application " +"asked to inhibit it." +msgstr "當應用程式阻止系統電源關閉時將系統電源關閉需要驗證。" + +#: src/login/org.freedesktop.login1.policy:191 +msgid "Reboot the system" +msgstr "重新啟動系統" + +#: src/login/org.freedesktop.login1.policy:192 +msgid "Authentication is required for rebooting the system." +msgstr "重新啟動系統需要驗證。" + +#: src/login/org.freedesktop.login1.policy:202 +msgid "Reboot the system while other users are logged in" +msgstr "在有其他使用者登入時重新啟動系統" + +#: src/login/org.freedesktop.login1.policy:203 +msgid "" +"Authentication is required for rebooting the system while other users are " +"logged in." +msgstr "在有其他使用者登入時重新啟動系統需要驗證。" + +#: src/login/org.freedesktop.login1.policy:213 +msgid "Reboot the system while an application asked to inhibit it" +msgstr "當應用程式阻止重新啟動系統時將系統重新啟動" + +#: src/login/org.freedesktop.login1.policy:214 +msgid "" +"Authentication is required for rebooting the system while an application " +"asked to inhibit it." +msgstr "當應用程式阻止系統重新啟動時將系統重新啟動需要驗證。" + +#: src/login/org.freedesktop.login1.policy:224 +msgid "Halt the system" +msgstr "停止系統" + +#: src/login/org.freedesktop.login1.policy:225 +msgid "Authentication is required for halting the system." +msgstr "停止系統需要身份驗證。" + +#: src/login/org.freedesktop.login1.policy:235 +msgid "Halt the system while other users are logged in" +msgstr "在其他使用者登入時停止系統" + +#: src/login/org.freedesktop.login1.policy:236 +msgid "" +"Authentication is required for halting the system while other users are " +"logged in." +msgstr "在其他使用者登入時停止系統需要身份驗證。" + +#: src/login/org.freedesktop.login1.policy:246 +msgid "Halt the system while an application asked to inhibit it" +msgstr "在應用程式阻止時停止系統" + +#: src/login/org.freedesktop.login1.policy:247 +msgid "" +"Authentication is required for halting the system while an application asked " +"to inhibit it." +msgstr "在應用程式阻止時停止系統需要身份驗證。" + +#: src/login/org.freedesktop.login1.policy:257 +msgid "Suspend the system" +msgstr "暫停系統" + +#: src/login/org.freedesktop.login1.policy:258 +msgid "Authentication is required for suspending the system." +msgstr "暫停系統需要驗證。" + +#: src/login/org.freedesktop.login1.policy:267 +msgid "Suspend the system while other users are logged in" +msgstr "在有其他使用者登入時暫停系統" + +#: src/login/org.freedesktop.login1.policy:268 +msgid "" +"Authentication is required for suspending the system while other users are " +"logged in." +msgstr "在有其他使用者登入時暫停系統需要驗證。" + +#: src/login/org.freedesktop.login1.policy:278 +msgid "Suspend the system while an application asked to inhibit it" +msgstr "當應用程式阻止暫停系統時將系統暫停" + +#: src/login/org.freedesktop.login1.policy:279 +msgid "" +"Authentication is required for suspending the system while an application " +"asked to inhibit it." +msgstr "當應用程式阻止系統暫停時將系統暫停需要驗證。" + +#: src/login/org.freedesktop.login1.policy:289 +msgid "Hibernate the system" +msgstr "系統冬眠" + +#: src/login/org.freedesktop.login1.policy:290 +msgid "Authentication is required for hibernating the system." +msgstr "系統冬眠需要驗證。" + +#: src/login/org.freedesktop.login1.policy:299 +msgid "Hibernate the system while other users are logged in" +msgstr "在有其他使用者登入時冬眠系統" + +#: src/login/org.freedesktop.login1.policy:300 +msgid "" +"Authentication is required for hibernating the system while other users are " +"logged in." +msgstr "在有其他使用者登入時冬眠系統需要驗證。" + +#: src/login/org.freedesktop.login1.policy:310 +msgid "Hibernate the system while an application asked to inhibit it" +msgstr "當應用程式阻止冬眠系統時將系統冬眠" + +#: src/login/org.freedesktop.login1.policy:311 +msgid "" +"Authentication is required for hibernating the system while an application " +"asked to inhibit it." +msgstr "當應用程式阻止系統冬眠時將系統冬眠需要驗證。" + +#: src/login/org.freedesktop.login1.policy:321 +msgid "Manage active sessions, users and seats" +msgstr "管理活躍的工作階段、使用者與座位" + +#: src/login/org.freedesktop.login1.policy:322 +msgid "" +"Authentication is required for managing active sessions, users and seats." +msgstr "管理活躍的工作階段、使用者與座位需要驗證。" + +#: src/login/org.freedesktop.login1.policy:331 +msgid "Lock or unlock active sessions" +msgstr "鎖定或解鎖活躍的工作階段" + +#: src/login/org.freedesktop.login1.policy:332 +msgid "Authentication is required to lock or unlock active sessions." +msgstr "鎖定或解鎖活躍的工作階段需要驗證。" + +#: src/login/org.freedesktop.login1.policy:341 +msgid "Set the reboot \"reason\" in the kernel" +msgstr "設定內核中的重新啟動 \"reason (原因)\"" + +#: src/login/org.freedesktop.login1.policy:342 +msgid "Authentication is required to set the reboot \"reason\" in the kernel." +msgstr "設定內核中的重新啟動 \"reason (原因)\"需要身份驗證。" + +#: src/login/org.freedesktop.login1.policy:352 +msgid "Indicate to the firmware to boot to setup interface" +msgstr "引導韌體啟動設定畫面" + +#: src/login/org.freedesktop.login1.policy:353 +msgid "" +"Authentication is required to indicate to the firmware to boot to setup " +"interface." +msgstr "對韌體的指示以開始設定介面需要驗證。" + +#: src/login/org.freedesktop.login1.policy:363 +msgid "Indicate to the boot loader to boot to the boot loader menu" +msgstr "引導開機載入器啟動開機載入選單" + +#: src/login/org.freedesktop.login1.policy:364 +msgid "" +"Authentication is required to indicate to the boot loader to boot to the " +"boot loader menu." +msgstr "引導開機載入器啟動開機載入器選單需要身份驗證。" + +#: src/login/org.freedesktop.login1.policy:374 +msgid "Indicate to the boot loader to boot a specific entry" +msgstr "引導開機載入器啟動指定項目" + +#: src/login/org.freedesktop.login1.policy:375 +msgid "" +"Authentication is required to indicate to the boot loader to boot into a " +"specific boot loader entry." +msgstr "引導開機載入器啟動指定的開機載入器項目需要身份驗證。" + +#: src/login/org.freedesktop.login1.policy:385 +msgid "Set a wall message" +msgstr "設定 wall 訊息" + +#: src/login/org.freedesktop.login1.policy:386 +msgid "Authentication is required to set a wall message" +msgstr "設定 wall 訊息需要身份驗證" + +#: src/machine/org.freedesktop.machine1.policy:22 +msgid "Log into a local container" +msgstr "登入到本機容器" + +#: src/machine/org.freedesktop.machine1.policy:23 +msgid "Authentication is required to log into a local container." +msgstr "登入到本機容器需要驗證。" + +#: src/machine/org.freedesktop.machine1.policy:32 +msgid "Log into the local host" +msgstr "登入到本機主機" + +#: src/machine/org.freedesktop.machine1.policy:33 +msgid "Authentication is required to log into the local host." +msgstr "登入到本機主機需要驗證。" + +#: src/machine/org.freedesktop.machine1.policy:42 +msgid "Acquire a shell in a local container" +msgstr "在本機容器中取得一個 shell" + +#: src/machine/org.freedesktop.machine1.policy:43 +msgid "Authentication is required to acquire a shell in a local container." +msgstr "在本機容器中取得一個 shell 需要驗證。" + +#: src/machine/org.freedesktop.machine1.policy:53 +msgid "Acquire a shell on the local host" +msgstr "在本機主機中取得一個 shell" + +#: src/machine/org.freedesktop.machine1.policy:54 +msgid "Authentication is required to acquire a shell on the local host." +msgstr "在本機主機中取得一個 shell 需要驗證。" + +#: src/machine/org.freedesktop.machine1.policy:64 +msgid "Acquire a pseudo TTY in a local container" +msgstr "取得在本機容器中的偽 TTY" + +#: src/machine/org.freedesktop.machine1.policy:65 +msgid "" +"Authentication is required to acquire a pseudo TTY in a local container." +msgstr "取得在本機容器中的偽 TTY 需要驗證。" + +#: src/machine/org.freedesktop.machine1.policy:74 +msgid "Acquire a pseudo TTY on the local host" +msgstr "取得在本機主機中的偽 TTY" + +#: src/machine/org.freedesktop.machine1.policy:75 +msgid "Authentication is required to acquire a pseudo TTY on the local host." +msgstr "取得在本機主機中的偽 TTY 需要驗證。" + +#: src/machine/org.freedesktop.machine1.policy:84 +msgid "Manage local virtual machines and containers" +msgstr "管理本機虛擬機器及容器" + +#: src/machine/org.freedesktop.machine1.policy:85 +msgid "" +"Authentication is required to manage local virtual machines and containers." +msgstr "管理本機虛擬機器及容器需要驗證。" + +#: src/machine/org.freedesktop.machine1.policy:95 +msgid "Manage local virtual machine and container images" +msgstr "管理本機虛擬機器及容器映像" + +#: src/machine/org.freedesktop.machine1.policy:96 +msgid "" +"Authentication is required to manage local virtual machine and container " +"images." +msgstr "管理本機虛擬機器及容器映像需要驗證。" + +#: src/network/org.freedesktop.network1.policy:22 +msgid "Set NTP servers" +msgstr "設定 NTP 伺服器" + +#: src/network/org.freedesktop.network1.policy:23 +msgid "Authentication is required to set NTP servers." +msgstr "設定 NTP 伺服器需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:33 +#: src/resolve/org.freedesktop.resolve1.policy:44 +msgid "Set DNS servers" +msgstr "設定 DNS 伺服器" + +#: src/network/org.freedesktop.network1.policy:34 +#: src/resolve/org.freedesktop.resolve1.policy:45 +msgid "Authentication is required to set DNS servers." +msgstr "設定 DNS 伺服器需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:44 +#: src/resolve/org.freedesktop.resolve1.policy:55 +msgid "Set domains" +msgstr "設定網域" + +#: src/network/org.freedesktop.network1.policy:45 +#: src/resolve/org.freedesktop.resolve1.policy:56 +msgid "Authentication is required to set domains." +msgstr "設定網域需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:55 +#: src/resolve/org.freedesktop.resolve1.policy:66 +msgid "Set default route" +msgstr "設定預設路由" + +#: src/network/org.freedesktop.network1.policy:56 +#: src/resolve/org.freedesktop.resolve1.policy:67 +msgid "Authentication is required to set default route." +msgstr "設定預設路由需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:66 +#: src/resolve/org.freedesktop.resolve1.policy:77 +msgid "Enable/disable LLMNR" +msgstr "啟用/停用 LLMNR" + +#: src/network/org.freedesktop.network1.policy:67 +#: src/resolve/org.freedesktop.resolve1.policy:78 +msgid "Authentication is required to enable or disable LLMNR." +msgstr "啟用或停用 LLMNR 需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:77 +#: src/resolve/org.freedesktop.resolve1.policy:88 +msgid "Enable/disable multicast DNS" +msgstr "啟用/停用 多點 DNS" + +#: src/network/org.freedesktop.network1.policy:78 +#: src/resolve/org.freedesktop.resolve1.policy:89 +msgid "Authentication is required to enable or disable multicast DNS." +msgstr "啟用或停用 多點 DNS 需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:88 +#: src/resolve/org.freedesktop.resolve1.policy:99 +msgid "Enable/disable DNS over TLS" +msgstr "啟用/停用 DNS over TLS" + +#: src/network/org.freedesktop.network1.policy:89 +#: src/resolve/org.freedesktop.resolve1.policy:100 +msgid "Authentication is required to enable or disable DNS over TLS." +msgstr "啟用或停用 DNS over LTS 需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:99 +#: src/resolve/org.freedesktop.resolve1.policy:110 +msgid "Enable/disable DNSSEC" +msgstr "啟用/停用 DNSSEC" + +#: src/network/org.freedesktop.network1.policy:100 +#: src/resolve/org.freedesktop.resolve1.policy:111 +msgid "Authentication is required to enable or disable DNSSEC." +msgstr "啟用或停用 DNSSEC 需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:110 +#: src/resolve/org.freedesktop.resolve1.policy:121 +msgid "Set DNSSEC Negative Trust Anchors" +msgstr "設定 DNSSEC Negative Trust Anchors" + +#: src/network/org.freedesktop.network1.policy:111 +#: src/resolve/org.freedesktop.resolve1.policy:122 +msgid "Authentication is required to set DNSSEC Negative Trust Anchors." +msgstr "設定 DNSSEC Negative Trust Anchors 需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:121 +msgid "Revert NTP settings" +msgstr "還原 NTP 設定" + +#: src/network/org.freedesktop.network1.policy:122 +msgid "Authentication is required to reset NTP settings." +msgstr "重設 NTP 設定需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:132 +msgid "Revert DNS settings" +msgstr "還原 DNS 設定" + +#: src/network/org.freedesktop.network1.policy:133 +msgid "Authentication is required to reset DNS settings." +msgstr "重設 DNS 設定需要身份驗證。" + +#: src/network/org.freedesktop.network1.policy:143 +msgid "Renew dynamic addresses" +msgstr "重新產生動態位址" + +#: src/network/org.freedesktop.network1.policy:144 +msgid "Authentication is required to renew dynamic addresses." +msgstr "重新產生動態位址需要身份驗證。" + +#: src/portable/org.freedesktop.portable1.policy:13 +msgid "Inspect a portable service image" +msgstr "檢查可攜式服務映像" + +#: src/portable/org.freedesktop.portable1.policy:14 +msgid "Authentication is required to inspect a portable service image." +msgstr "檢查可攜式服務映像需要身份驗證。" + +#: src/portable/org.freedesktop.portable1.policy:23 +msgid "Attach or detach a portable service image" +msgstr "連結或取消連結可攜式服務映像" + +#: src/portable/org.freedesktop.portable1.policy:24 +msgid "" +"Authentication is required to attach or detach a portable service image." +msgstr "連結或取消連結可攜式服務映像需要身份驗證。" + +#: src/portable/org.freedesktop.portable1.policy:34 +msgid "Delete or modify portable service image" +msgstr "刪除或修改可攜式服務映像" + +#: src/portable/org.freedesktop.portable1.policy:35 +msgid "" +"Authentication is required to delete or modify a portable service image." +msgstr "刪除或修改可攜式服務映像需要身份驗證。" + +#: src/resolve/org.freedesktop.resolve1.policy:22 +msgid "Register a DNS-SD service" +msgstr "註冊 DNS-SD 服務" + +#: src/resolve/org.freedesktop.resolve1.policy:23 +msgid "Authentication is required to register a DNS-SD service" +msgstr "註冊 DNS-SD 服務需要身份驗證" + +#: src/resolve/org.freedesktop.resolve1.policy:33 +msgid "Unregister a DNS-SD service" +msgstr "取消註冊 DNS-SD 服務" + +#: src/resolve/org.freedesktop.resolve1.policy:34 +msgid "Authentication is required to unregister a DNS-SD service" +msgstr "取消註冊 DNS-SD 服務需要身份驗證" + +#: src/resolve/org.freedesktop.resolve1.policy:132 +msgid "Revert name resolution settings" +msgstr "還原名稱解析設定" + +#: src/resolve/org.freedesktop.resolve1.policy:133 +msgid "Authentication is required to reset name resolution settings." +msgstr "重設名稱解析設定需要身份驗證。" + +#: src/timedate/org.freedesktop.timedate1.policy:22 +msgid "Set system time" +msgstr "設定系統時間" + +#: src/timedate/org.freedesktop.timedate1.policy:23 +msgid "Authentication is required to set the system time." +msgstr "設定系統時間需要驗證。" + +#: src/timedate/org.freedesktop.timedate1.policy:33 +msgid "Set system timezone" +msgstr "設定系統時區" + +#: src/timedate/org.freedesktop.timedate1.policy:34 +msgid "Authentication is required to set the system timezone." +msgstr "設定系統時區需要驗證。" + +#: src/timedate/org.freedesktop.timedate1.policy:43 +msgid "Set RTC to local timezone or UTC" +msgstr "將 RTC 設定為本地時區或 UTC" + +#: src/timedate/org.freedesktop.timedate1.policy:44 +msgid "" +"Authentication is required to control whether the RTC stores the local or " +"UTC time." +msgstr "控制 RTC 儲存本地或 UTC 時間需要驗證。" + +#: src/timedate/org.freedesktop.timedate1.policy:53 +msgid "Turn network time synchronization on or off" +msgstr "打開或關閉網路時間同步" + +#: src/timedate/org.freedesktop.timedate1.policy:54 +msgid "" +"Authentication is required to control whether network time synchronization " +"shall be enabled." +msgstr "控制網路時間同步是否啟用需要驗證。" + +#: src/core/dbus-unit.c:354 +msgid "Authentication is required to start '$(unit)'." +msgstr "啟動 '$(unit)' 需要驗證。" + +#: src/core/dbus-unit.c:355 +msgid "Authentication is required to stop '$(unit)'." +msgstr "停止 '$(unit)' 需要驗證。" + +#: src/core/dbus-unit.c:356 +msgid "Authentication is required to reload '$(unit)'." +msgstr "重新載入 '$(unit)' 需要驗證。" + +#: src/core/dbus-unit.c:357 src/core/dbus-unit.c:358 +msgid "Authentication is required to restart '$(unit)'." +msgstr "重新啟動 '$(unit)' 需要驗證。" + +#: src/core/dbus-unit.c:530 +msgid "" +"Authentication is required to send a UNIX signal to the processes of " +"'$(unit)'." +msgstr "傳送 UNIX 信號至「$(unit)」的程序需要身份驗證。" + +#: src/core/dbus-unit.c:561 +msgid "Authentication is required to reset the \"failed\" state of '$(unit)'." +msgstr "重置 '$(unit)' 的「失敗」狀態需要驗證。" + +#: src/core/dbus-unit.c:594 +msgid "Authentication is required to set properties on '$(unit)'." +msgstr "在 '$(unit)' 上設定屬性需要驗證。" + +#: src/core/dbus-unit.c:703 +msgid "" +"Authentication is required to delete files and directories associated with " +"'$(unit)'." +msgstr "刪除與 '$(unit)' 相關的檔案及目錄需要身份驗證。" + +#~ msgid "Authentication is required to kill '$(unit)'." +#~ msgstr "砍除 '$(unit)' 需要驗證。" diff --git a/presets/90-systemd.preset b/presets/90-systemd.preset new file mode 100644 index 00000000..4009cbb9 --- /dev/null +++ b/presets/90-systemd.preset @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# Settings for systemd units distributed with systemd itself. Most of these +# should be enabled by default, even if the distribution follows a general +# default-off policy. + +enable remote-fs.target +enable remote-cryptsetup.target +enable machines.target + +enable getty@.service +enable systemd-timesyncd.service +enable systemd-networkd.service +enable systemd-resolved.service + +disable console-getty.service +disable debug-shell.service + +disable halt.target +disable kexec.target +disable poweroff.target +enable reboot.target +disable rescue.target +disable exit.target + +disable syslog.socket + +disable systemd-journal-gatewayd.* +disable systemd-journal-remote.* +disable systemd-journal-upload.* + +# Passive targets: always off by default, since they should only be pulled in +# by dependent units. + +disable cryptsetup-pre.target +disable getty-pre.target +disable local-fs-pre.target +disable network.target +disable network-pre.target +disable nss-lookup.target +disable nss-user-lookup.target +disable remote-fs-pre.target +disable rpcbind.target +disable time-set.target +disable time-sync.target diff --git a/presets/meson.build b/presets/meson.build new file mode 100644 index 00000000..0b16acf5 --- /dev/null +++ b/presets/meson.build @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +install_data('90-systemd.preset', + install_dir : systempresetdir) + +install_data('user/90-systemd.preset', + install_dir : userpresetdir) diff --git a/presets/user/90-systemd.preset b/presets/user/90-systemd.preset new file mode 100644 index 00000000..fd402c8c --- /dev/null +++ b/presets/user/90-systemd.preset @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# Settings for systemd units distributed with systemd itself. These should be +# enabled by default, even if the distribution follows a general default-off +# policy. + +enable systemd-tmpfiles-setup.service +enable systemd-tmpfiles-clean.timer + +# Passive targets: always off by default, since they should only be pulled in +# by dependent units. + +disable graphical-session-pre.target +disable graphical-session.target diff --git a/rules.d/50-udev-default.rules.in b/rules.d/50-udev-default.rules.in new file mode 100644 index 00000000..50747a19 --- /dev/null +++ b/rules.d/50-udev-default.rules.in @@ -0,0 +1,91 @@ +# do not edit this file, it will be overwritten on update + +# run a command on remove events +ACTION=="remove", ENV{REMOVE_CMD}!="", RUN+="$env{REMOVE_CMD}" +ACTION=="remove", GOTO="default_end" + +SUBSYSTEM=="virtio-ports", KERNEL=="vport*", ATTR{name}=="?*", SYMLINK+="virtio-ports/$attr{name}" + +# select "system RTC" or just use the first one +SUBSYSTEM=="rtc", ATTR{hctosys}=="1", SYMLINK+="rtc" +SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100" + +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" +ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}" + +ACTION!="add", GOTO="default_end" + +SUBSYSTEM=="tty", KERNEL=="ptmx", GROUP="tty", MODE="0666" +SUBSYSTEM=="tty", KERNEL=="tty", GROUP="tty", MODE="0666" +SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0620" +SUBSYSTEM=="tty", KERNEL=="sclp_line[0-9]*", GROUP="tty", MODE="0620" +SUBSYSTEM=="tty", KERNEL=="ttysclp[0-9]*", GROUP="tty", MODE="0620" +SUBSYSTEM=="tty", KERNEL=="3270/tty[0-9]*", GROUP="tty", MODE="0620" +SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", GROUP="tty" +KERNEL=="tty[A-Z]*[0-9]|ttymxc[0-9]*|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout" + +SUBSYSTEM=="mem", KERNEL=="mem|kmem|port", GROUP="kmem", MODE="0640" + +SUBSYSTEM=="input", GROUP="input" +SUBSYSTEM=="input", KERNEL=="js[0-9]*", MODE="0664" + +SUBSYSTEM=="video4linux", GROUP="video" +SUBSYSTEM=="graphics", GROUP="video" +SUBSYSTEM=="drm", KERNEL!="renderD*", GROUP="video" +SUBSYSTEM=="dvb", GROUP="video" +SUBSYSTEM=="media", GROUP="video" +SUBSYSTEM=="cec", GROUP="video" + +SUBSYSTEM=="drm", KERNEL=="renderD*", GROUP="render", MODE="@GROUP_RENDER_MODE@" +SUBSYSTEM=="kfd", GROUP="render", MODE="@GROUP_RENDER_MODE@" + +# When using static_node= with non-default permissions, also update +# tmpfiles.d/static-nodes-permissions.conf.in to keep permissions synchronized. + +SUBSYSTEM=="sound", GROUP="audio", \ + OPTIONS+="static_node=snd/seq", OPTIONS+="static_node=snd/timer" + +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0664" + +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", GROUP="video" +SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", GROUP="video" +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", GROUP="video" +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", GROUP="video" + +KERNEL=="parport[0-9]*", GROUP="lp" +SUBSYSTEM=="printer", KERNEL=="lp*", GROUP="lp" +SUBSYSTEM=="ppdev", GROUP="lp" +KERNEL=="lp[0-9]*", GROUP="lp" +KERNEL=="irlpt[0-9]*", GROUP="lp" +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", GROUP="lp" + +SUBSYSTEM=="block", GROUP="disk" +SUBSYSTEM=="block", KERNEL=="sr[0-9]*", GROUP="cdrom" +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", GROUP="cdrom" +KERNEL=="sch[0-9]*", GROUP="cdrom" +KERNEL=="pktcdvd[0-9]*", GROUP="cdrom" +KERNEL=="pktcdvd", GROUP="cdrom" + +SUBSYSTEM=="scsi_generic|scsi_tape", SUBSYSTEMS=="scsi", ATTRS{type}=="1|8", GROUP="tape" +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="0", GROUP="disk" +KERNEL=="qft[0-9]*|nqft[0-9]*|zqft[0-9]*|nzqft[0-9]*|rawqft[0-9]*|nrawqft[0-9]*", GROUP="disk" +KERNEL=="loop-control", GROUP="disk", OPTIONS+="static_node=loop-control" +KERNEL=="btrfs-control", GROUP="disk" +KERNEL=="rawctl", GROUP="disk" +SUBSYSTEM=="raw", KERNEL=="raw[0-9]*", GROUP="disk" +SUBSYSTEM=="aoe", GROUP="disk", MODE="0220" +SUBSYSTEM=="aoe", KERNEL=="err", MODE="0440" + +KERNEL=="rfkill", MODE="0664" +KERNEL=="tun", MODE="0666", OPTIONS+="static_node=net/tun" + +KERNEL=="fuse", MODE="0666", OPTIONS+="static_node=fuse" + +# The static_node is required on s390x and ppc (they are using MODULE_ALIAS) +KERNEL=="kvm", GROUP="kvm", MODE="@DEV_KVM_MODE@", OPTIONS+="static_node=kvm" + +KERNEL=="udmabuf", GROUP="kvm" + +SUBSYSTEM=="ptp", ATTR{clock_name}=="KVM virtual PTP", SYMLINK += "ptp_kvm" + +LABEL="default_end" diff --git a/rules.d/60-block.rules b/rules.d/60-block.rules new file mode 100644 index 00000000..3134ab99 --- /dev/null +++ b/rules.d/60-block.rules @@ -0,0 +1,13 @@ +# do not edit this file, it will be overwritten on update + +# enable in-kernel media-presence polling +ACTION=="add", SUBSYSTEM=="module", KERNEL=="block", ATTR{parameters/events_dfl_poll_msecs}=="0", \ + ATTR{parameters/events_dfl_poll_msecs}="2000" + +# forward scsi device event to corresponding block device +ACTION=="change", SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST=="block", ATTR{block/*/uevent}="change" + +# watch metadata changes, caused by tools closing the device node which was opened for writing +ACTION!="remove", SUBSYSTEM=="block", \ + KERNEL=="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*|ubi*|scm*|pmem*|nbd*|zd*", \ + OPTIONS+="watch" diff --git a/rules.d/60-cdrom_id.rules b/rules.d/60-cdrom_id.rules new file mode 100644 index 00000000..288f8ce2 --- /dev/null +++ b/rules.d/60-cdrom_id.rules @@ -0,0 +1,29 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="cdrom_end" +SUBSYSTEM!="block", GOTO="cdrom_end" +KERNEL!="sr[0-9]*|vdisk*|xvd*", GOTO="cdrom_end" +ENV{DEVTYPE}!="disk", GOTO="cdrom_end" + +# unconditionally tag device as CDROM +KERNEL=="sr[0-9]*", ENV{ID_CDROM}="1" + +# stop automatically any mount units bound to the device if the media eject +# button is pressed. +ENV{ID_CDROM}=="1", ENV{SYSTEMD_MOUNT_DEVICE_BOUND}="1" + +# media eject button pressed +ENV{DISK_EJECT_REQUEST}=="?*", RUN+="cdrom_id --eject-media $devnode", GOTO="cdrom_end" + +# import device and media properties and lock tray to +# enable the receiving of media eject button events +IMPORT{program}="cdrom_id --lock-media $devnode" + +# ejecting a CD does not remove the device node, so mark the systemd device +# unit as inactive while there is no medium; this automatically cleans up of +# stale mounts after ejecting +ENV{DISK_MEDIA_CHANGE}=="?*", ENV{ID_CDROM_MEDIA}!="?*", ENV{SYSTEMD_READY}="0" + +KERNEL=="sr0", SYMLINK+="cdrom", OPTIONS+="link_priority=-100" + +LABEL="cdrom_end" diff --git a/rules.d/60-drm.rules b/rules.d/60-drm.rules new file mode 100644 index 00000000..f7f3435d --- /dev/null +++ b/rules.d/60-drm.rules @@ -0,0 +1,8 @@ +# do not edit this file, it will be overwritten on update + +ACTION!="remove", SUBSYSTEM=="drm", SUBSYSTEMS=="pci|usb|platform", IMPORT{builtin}="path_id" + +# by-path +ENV{ID_PATH}=="?*", KERNEL=="card*", SYMLINK+="dri/by-path/$env{ID_PATH}-card" +ENV{ID_PATH}=="?*", KERNEL=="controlD*", SYMLINK+="dri/by-path/$env{ID_PATH}-control" +ENV{ID_PATH}=="?*", KERNEL=="renderD*", SYMLINK+="dri/by-path/$env{ID_PATH}-render" diff --git a/rules.d/60-evdev.rules b/rules.d/60-evdev.rules new file mode 100644 index 00000000..e5e608ac --- /dev/null +++ b/rules.d/60-evdev.rules @@ -0,0 +1,23 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="evdev_end" +KERNEL!="event*", GOTO="evdev_end" + +# skip later rules when we find something for this input device +IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \ + RUN{builtin}+="keyboard", GOTO="evdev_end" + +# AT keyboard matching by the machine's DMI data +DRIVERS=="atkbd", \ + IMPORT{builtin}="hwdb 'evdev:atkbd:$attr{[dmi/id]modalias}'", \ + RUN{builtin}+="keyboard", GOTO="evdev_end" + +# device matching the input device name + properties + the machine's DMI data +KERNELS=="input*", IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:phys:$attr{phys}:ev:$attr{capabilities/ev}:$attr{[dmi/id]modalias}'", \ + RUN{builtin}+="keyboard", GOTO="evdev_end" + +# device matching the input device name and the machine's DMI data +KERNELS=="input*", IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:$attr{[dmi/id]modalias}'", \ + RUN{builtin}+="keyboard", GOTO="evdev_end" + +LABEL="evdev_end" diff --git a/rules.d/60-fido-id.rules b/rules.d/60-fido-id.rules new file mode 100644 index 00000000..fcf50797 --- /dev/null +++ b/rules.d/60-fido-id.rules @@ -0,0 +1,7 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="fido_id_end" + +SUBSYSTEM=="hidraw", IMPORT{program}="fido_id" + +LABEL="fido_id_end" diff --git a/rules.d/60-input-id.rules b/rules.d/60-input-id.rules new file mode 100644 index 00000000..bb8a812d --- /dev/null +++ b/rules.d/60-input-id.rules @@ -0,0 +1,8 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="id_input_end" + +SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id" +SUBSYSTEM=="input", IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=id-input:modalias:" + +LABEL="id_input_end" diff --git a/rules.d/60-persistent-alsa.rules b/rules.d/60-persistent-alsa.rules new file mode 100644 index 00000000..8154e2db --- /dev/null +++ b/rules.d/60-persistent-alsa.rules @@ -0,0 +1,14 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="persistent_alsa_end" +SUBSYSTEM!="sound", GOTO="persistent_alsa_end" +KERNEL!="controlC[0-9]*", GOTO="persistent_alsa_end" + +SUBSYSTEMS=="usb", ENV{ID_MODEL}=="", IMPORT{builtin}="usb_id" +ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", SYMLINK+="snd/by-id/$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}" +ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", SYMLINK+="snd/by-id/$env{ID_BUS}-$env{ID_SERIAL}" + +IMPORT{builtin}="path_id" +ENV{ID_PATH}=="?*", SYMLINK+="snd/by-path/$env{ID_PATH}" + +LABEL="persistent_alsa_end" diff --git a/rules.d/60-persistent-input.rules b/rules.d/60-persistent-input.rules new file mode 100644 index 00000000..255547d9 --- /dev/null +++ b/rules.d/60-persistent-input.rules @@ -0,0 +1,42 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="persistent_input_end" +SUBSYSTEM!="input", GOTO="persistent_input_end" +SUBSYSTEMS=="bluetooth", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end" +# Bluetooth devices don't always have the bluetooth subsystem +ATTRS{id/bustype}=="0005", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end" +SUBSYSTEMS=="rmi4", ENV{ID_BUS}="rmi" +SUBSYSTEMS=="serio", ENV{ID_BUS}="i8042" + +SUBSYSTEMS=="usb", ENV{ID_BUS}=="", IMPORT{builtin}="usb_id" + +# determine class name for persistent symlinks +ENV{ID_INPUT_KEYBOARD}=="?*", ENV{.INPUT_CLASS}="kbd" +ENV{ID_INPUT_MOUSE}=="?*", ENV{.INPUT_CLASS}="mouse" +ENV{ID_INPUT_TOUCHPAD}=="?*", ENV{.INPUT_CLASS}="mouse" +ENV{ID_INPUT_TABLET}=="?*", ENV{.INPUT_CLASS}="mouse" +ENV{ID_INPUT_JOYSTICK}=="?*", ENV{.INPUT_CLASS}="joystick" +DRIVERS=="pcspkr", ENV{.INPUT_CLASS}="spkr" +ATTRS{name}=="*dvb*|*DVB*|* IR *", ENV{.INPUT_CLASS}="ir" + +# fill empty serial number +ENV{.INPUT_CLASS}=="?*", ENV{ID_SERIAL}=="", ENV{ID_SERIAL}="noserial" + +# by-id links +KERNEL=="mouse*|js*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="|00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-$env{.INPUT_CLASS}" +KERNEL=="mouse*|js*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="?*", ATTRS{bInterfaceNumber}!="00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$attr{bInterfaceNumber}-$env{.INPUT_CLASS}" +KERNEL=="event*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="|00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-event-$env{.INPUT_CLASS}" +KERNEL=="event*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="?*", ATTRS{bInterfaceNumber}!="00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$attr{bInterfaceNumber}-event-$env{.INPUT_CLASS}" +# allow empty class for USB devices, by appending the interface number +SUBSYSTEMS=="usb", ENV{ID_BUS}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="", ATTRS{bInterfaceNumber}=="?*", \ + SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-event-if$attr{bInterfaceNumber}" + +# by-path +SUBSYSTEMS=="pci|usb|platform|acpi", IMPORT{builtin}="path_id" +ENV{ID_PATH}=="?*", KERNEL=="mouse*|js*", ENV{.INPUT_CLASS}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-$env{.INPUT_CLASS}" +ENV{ID_PATH}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-event-$env{.INPUT_CLASS}" +# allow empty class for platform and usb devices; platform supports only a single interface that way +SUBSYSTEMS=="usb|platform", ENV{ID_PATH}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="", \ + SYMLINK+="input/by-path/$env{ID_PATH}-event" + +LABEL="persistent_input_end" diff --git a/rules.d/60-persistent-storage-tape.rules b/rules.d/60-persistent-storage-tape.rules new file mode 100644 index 00000000..0136140a --- /dev/null +++ b/rules.d/60-persistent-storage-tape.rules @@ -0,0 +1,36 @@ +# do not edit this file, it will be overwritten on update + +# persistent storage links: /dev/tape/{by-id,by-path} + +ACTION=="remove", GOTO="persistent_storage_tape_end" +ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="persistent_storage_tape_end" + +# type 8 devices are "Medium Changers" +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{program}="scsi_id --sg-version=3 --export --whitelisted -d $devnode", \ + SYMLINK+="tape/by-id/scsi-$env{ID_SERIAL}" + +# iSCSI devices from the same host have all the same ID_SERIAL, +# but additionally a property named ID_SCSI_SERIAL. +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", ENV{ID_SCSI_SERIAL}=="?*", \ + SYMLINK+="tape/by-id/scsi-$env{ID_SCSI_SERIAL}" + +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{builtin}="path_id", \ + SYMLINK+="tape/by-path/$env{ID_PATH}-changer" + +SUBSYSTEM!="scsi_tape", GOTO="persistent_storage_tape_end" + +KERNEL=="st*[0-9]|nst*[0-9]", ATTRS{ieee1394_id}=="?*", ENV{ID_SERIAL}="$attr{ieee1394_id}", ENV{ID_BUS}="ieee1394" +KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" +KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", KERNELS=="[0-9]*:*[0-9]", ENV{.BSG_DEV}="$root/bsg/$id" +KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --whitelisted --export --device=$env{.BSG_DEV}", ENV{ID_BUS}="scsi" +KERNEL=="st*[0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SERIAL}" +KERNEL=="st*[0-9]", ENV{ID_SCSI_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SCSI_SERIAL}" +KERNEL=="nst*[0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SERIAL}-nst" +KERNEL=="nst*[0-9]", ENV{ID_SCSI_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SCSI_SERIAL}-nst" + +# by-path (parent device path) +KERNEL=="st*[0-9]|nst*[0-9]", IMPORT{builtin}="path_id" +KERNEL=="st*[0-9]", ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}" +KERNEL=="nst*[0-9]", ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}-nst" + +LABEL="persistent_storage_tape_end" diff --git a/rules.d/60-persistent-storage.rules b/rules.d/60-persistent-storage.rules new file mode 100644 index 00000000..01586690 --- /dev/null +++ b/rules.d/60-persistent-storage.rules @@ -0,0 +1,123 @@ +# do not edit this file, it will be overwritten on update + +# persistent storage links: /dev/disk/{by-id,by-uuid,by-label,by-path} +# scheme based on "Linux persistent device names", 2004, Hannes Reinecke + +ACTION=="remove", GOTO="persistent_storage_end" +ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="persistent_storage_end" + +SUBSYSTEM!="block", GOTO="persistent_storage_end" +KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*|ubi*|scm*|pmem*|nbd*|zd*", GOTO="persistent_storage_end" + +# ignore partitions that span the entire disk +TEST=="whole_disk", GOTO="persistent_storage_end" + +# For partitions import parent disk ID_* information, except ID_FS_*. +# +# This is particularly important on media where a filesystem superblock and +# partition table are found on the same level, e.g. common Linux distro ISO +# installation media. +# +# In the case where a partition device points to the same filesystem that +# was detected on the parent disk, the ID_FS_* information is already +# present on the partition devices as well as the parent, so no need to +# propagate it. In the case where the partition device points to a different +# filesystem, merging the parent ID_FS_ properties would lead to +# inconsistencies, so we avoid doing so. +ENV{DEVTYPE}=="partition", \ + IMPORT{parent}="ID_[!F]*", IMPORT{parent}="ID_", \ + IMPORT{parent}="ID_F[!S]*", IMPORT{parent}="ID_F", \ + IMPORT{parent}="ID_FS[!_]*", IMPORT{parent}="ID_FS" + +# NVMe +KERNEL=="nvme*[0-9]n*[0-9]", ATTR{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}" +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}-part%n" + +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}" +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{wwid}=="?*", ENV{ID_WWN}="$attr{wwid}" +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}" +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{firmware_rev}=="?*", ENV{ID_REVISION}="$attr{firmware_rev}" +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \ + ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}" + +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}" +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}" +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{firmware_rev}=="?*", ENV{ID_REVISION}="$attr{firmware_rev}" +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \ + ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n" + +# virtio-blk +KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}" +KERNEL=="vd*[0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}-part%n" + +# ATA +KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", IMPORT{program}="ata_id --export $devnode" + +# ATAPI devices (SPC-3 or later) +KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{type}=="5", ATTRS{scsi_level}=="[6-9]*", IMPORT{program}="ata_id --export $devnode" + +# Run ata_id on non-removable USB Mass Storage (SATA/PATA disks in enclosures) +KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", ATTR{removable}=="0", SUBSYSTEMS=="usb", IMPORT{program}="ata_id --export $devnode" + +# Fall back usb_id for USB devices +KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" + +# SCSI devices +KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_BUS}="scsi" +KERNEL=="cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_BUS}="cciss" +KERNEL=="sd*|sr*|cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}" +KERNEL=="sd*|cciss*", ENV{DEVTYPE}=="partition", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}-part%n" + +# PMEM devices +KERNEL=="pmem*", ENV{DEVTYPE}=="disk", ATTRS{uuid}=="?*", SYMLINK+="disk/by-id/pmem-$attr{uuid}" + +# FireWire +KERNEL=="sd*[!0-9]|sr*", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}" +KERNEL=="sd*[0-9]", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}-part%n" + +# MMC +KERNEL=="mmcblk[0-9]", SUBSYSTEMS=="mmc", ATTRS{name}=="?*", ATTRS{serial}=="?*", \ + ENV{ID_NAME}="$attr{name}", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}" +KERNEL=="mmcblk[0-9]p[0-9]*", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}-part%n" + +# UBI-MTD +SUBSYSTEM=="ubi", KERNEL=="ubi*_*", ATTRS{mtd_num}=="*", SYMLINK+="ubi_mtd%s{mtd_num}_%s{name}" + +# Memstick +KERNEL=="msblk[0-9]|mspblk[0-9]", SUBSYSTEMS=="memstick", ATTRS{name}=="?*", ATTRS{serial}=="?*", \ + ENV{ID_NAME}="$attr{name}", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/memstick-$env{ID_NAME}_$env{ID_SERIAL}" +KERNEL=="msblk[0-9]p[0-9]|mspblk[0-9]p[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/memstick-$env{ID_NAME}_$env{ID_SERIAL}-part%n" + +# by-path +ENV{DEVTYPE}=="disk", DEVPATH!="*/virtual/*", IMPORT{builtin}="path_id" +KERNEL=="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-boot%n" +KERNEL!="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}" +ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n" + +# legacy virtio-pci by-path links (deprecated) +KERNEL=="vd*[!0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}" +KERNEL=="vd*[0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}-part%n" + +# probe filesystem metadata of optical drives which have a media inserted +KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="?*", \ + IMPORT{builtin}="blkid --offset=$env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}" +# single-session CDs do not have ID_CDROM_MEDIA_SESSION_LAST_OFFSET +KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="", \ + IMPORT{builtin}="blkid --noraid" + +# probe filesystem metadata of disks +KERNEL!="sr*", IMPORT{builtin}="blkid" + +# by-label/by-uuid links (filesystem metadata) +ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}" +ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}" + +# by-id (World Wide Name) +ENV{DEVTYPE}=="disk", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}" +ENV{DEVTYPE}=="partition", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}-part%n" + +# by-partlabel/by-partuuid links (partition metadata) +ENV{ID_PART_ENTRY_UUID}=="?*", SYMLINK+="disk/by-partuuid/$env{ID_PART_ENTRY_UUID}" +ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_NAME}=="?*", SYMLINK+="disk/by-partlabel/$env{ID_PART_ENTRY_NAME}" + +LABEL="persistent_storage_end" diff --git a/rules.d/60-persistent-v4l.rules b/rules.d/60-persistent-v4l.rules new file mode 100644 index 00000000..93c5ee8c --- /dev/null +++ b/rules.d/60-persistent-v4l.rules @@ -0,0 +1,20 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="persistent_v4l_end" +SUBSYSTEM!="video4linux", GOTO="persistent_v4l_end" +ENV{MAJOR}=="", GOTO="persistent_v4l_end" + +IMPORT{program}="v4l_id $devnode" + +SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" +KERNEL=="video*", ENV{ID_SERIAL}=="?*", SYMLINK+="v4l/by-id/$env{ID_BUS}-$env{ID_SERIAL}-video-index$attr{index}" + +# check for valid "index" number +TEST!="index", GOTO="persistent_v4l_end" +ATTR{index}!="?*", GOTO="persistent_v4l_end" + +IMPORT{builtin}="path_id" +ENV{ID_PATH}=="?*", KERNEL=="video*|vbi*", SYMLINK+="v4l/by-path/$env{ID_PATH}-video-index$attr{index}" +ENV{ID_PATH}=="?*", KERNEL=="audio*", SYMLINK+="v4l/by-path/$env{ID_PATH}-audio-index$attr{index}" + +LABEL="persistent_v4l_end" diff --git a/rules.d/60-sensor.rules b/rules.d/60-sensor.rules new file mode 100644 index 00000000..7b9b7d28 --- /dev/null +++ b/rules.d/60-sensor.rules @@ -0,0 +1,18 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="sensor_end" + +# device matching the sensor's name and the machine's DMI data for IIO devices +SUBSYSTEM=="iio", KERNEL=="iio*", SUBSYSTEMS=="usb|i2c|platform", \ + IMPORT{builtin}="hwdb 'sensor:modalias:$attr{modalias}:$attr{[dmi/id]modalias}'", \ + GOTO="sensor_end" + +SUBSYSTEM=="input", ENV{ID_INPUT_ACCELEROMETER}=="1", SUBSYSTEMS=="acpi", \ + IMPORT{builtin}="hwdb 'sensor:modalias:acpi:$attr{hid}:$attr{[dmi/id]modalias}'", \ + GOTO="sensor_end" + +SUBSYSTEM=="input", ENV{ID_INPUT_ACCELEROMETER}=="1", SUBSYSTEMS=="platform", \ + IMPORT{builtin}="hwdb 'sensor:modalias:platform:$id:$attr{[dmi/id]modalias}'", \ + GOTO="sensor_end" + +LABEL="sensor_end" diff --git a/rules.d/60-serial.rules b/rules.d/60-serial.rules new file mode 100644 index 00000000..f303e27f --- /dev/null +++ b/rules.d/60-serial.rules @@ -0,0 +1,26 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="serial_end" +SUBSYSTEM!="tty", GOTO="serial_end" + +SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" +SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci" +SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" + +# /dev/serial/by-path/, /dev/serial/by-id/ for USB devices +KERNEL!="ttyUSB[0-9]*|ttyACM[0-9]*", GOTO="serial_end" + +SUBSYSTEMS=="usb-serial", ENV{.ID_PORT}="$attr{port_number}" + +IMPORT{builtin}="path_id" +ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", SYMLINK+="serial/by-path/$env{ID_PATH}" +ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-path/$env{ID_PATH}-port$env{.ID_PORT}" + +IMPORT{builtin}="usb_id" +ENV{ID_SERIAL}=="", GOTO="serial_end" +SUBSYSTEMS=="usb", ENV{ID_USB_INTERFACE_NUM}="$attr{bInterfaceNumber}" +ENV{ID_USB_INTERFACE_NUM}=="", GOTO="serial_end" +ENV{.ID_PORT}=="", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}" +ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}-port$env{.ID_PORT}" + +LABEL="serial_end" diff --git a/rules.d/61-autosuspend-manual.rules b/rules.d/61-autosuspend-manual.rules new file mode 100644 index 00000000..2b973af9 --- /dev/null +++ b/rules.d/61-autosuspend-manual.rules @@ -0,0 +1,19 @@ +# This udev rule is for any devices that should enter automatic suspend +# but are not already included in generated rules from Chromium OS via +# tools/make-autosuspend-rules.py +# + +ACTION!="add", GOTO="autosuspend_manual_end" +SUBSYSTEM!="usb", GOTO="autosuspend_manual_end" + +SUBSYSTEM=="usb", GOTO="autosuspend_manual_usb" + +# USB rules +LABEL="autosuspend_manual_usb" +GOTO="autosuspend_manual_end" + +# Enable autosuspend +LABEL="autosuspend_manual_enable" +TEST=="power/control", ATTR{power/control}="auto", GOTO="autosuspend_manual_end" + +LABEL="autosuspend_manual_end" diff --git a/rules.d/64-btrfs.rules.in b/rules.d/64-btrfs.rules.in new file mode 100644 index 00000000..aad29afb --- /dev/null +++ b/rules.d/64-btrfs.rules.in @@ -0,0 +1,17 @@ +# do not edit this file, it will be overwritten on update + +SUBSYSTEM!="block", GOTO="btrfs_end" +ACTION=="remove", GOTO="btrfs_end" +ENV{ID_FS_TYPE}!="btrfs", GOTO="btrfs_end" +ENV{SYSTEMD_READY}=="0", GOTO="btrfs_end" + +# let the kernel know about this btrfs filesystem, and check if it is complete +IMPORT{builtin}="btrfs ready $devnode" + +# mark the device as not ready to be used by the system +ENV{ID_BTRFS_READY}=="0", ENV{SYSTEMD_READY}="0" + +# reconsider pending devices in case when multidevice volume awaits +ENV{ID_BTRFS_READY}=="1", RUN+="@rootbindir@/udevadm trigger -s block -p ID_BTRFS_READY=0" + +LABEL="btrfs_end" diff --git a/rules.d/70-joystick.rules b/rules.d/70-joystick.rules new file mode 100644 index 00000000..b80d2036 --- /dev/null +++ b/rules.d/70-joystick.rules @@ -0,0 +1,12 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="joystick_end" +ENV{ID_INPUT_JOYSTICK}=="", GOTO="joystick_end" +KERNEL!="event*", GOTO="joystick_end" + +# joystick::vp:name::* +KERNELS=="input*", ENV{ID_BUS}!="", \ + IMPORT{builtin}="hwdb 'joystick:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \ + GOTO="joystick_end" + +LABEL="joystick_end" diff --git a/rules.d/70-mouse.rules b/rules.d/70-mouse.rules new file mode 100644 index 00000000..3ea743af --- /dev/null +++ b/rules.d/70-mouse.rules @@ -0,0 +1,18 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="mouse_end" +KERNEL!="event*", GOTO="mouse_end" +ENV{ID_INPUT_MOUSE}=="", GOTO="mouse_end" + +# mouse::vp:name::* +KERNELS=="input*", ENV{ID_BUS}=="usb", \ + IMPORT{builtin}="hwdb 'mouse:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \ + GOTO="mouse_end" +KERNELS=="input*", ENV{ID_BUS}=="bluetooth", \ + IMPORT{builtin}="hwdb 'mouse:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \ + GOTO="mouse_end" +DRIVERS=="psmouse", SUBSYSTEMS=="serio", \ + IMPORT{builtin}="hwdb 'mouse:ps2::name:$attr{device/name}:'", \ + GOTO="mouse_end" + +LABEL="mouse_end" diff --git a/rules.d/70-touchpad.rules b/rules.d/70-touchpad.rules new file mode 100644 index 00000000..7bede02d --- /dev/null +++ b/rules.d/70-touchpad.rules @@ -0,0 +1,13 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="touchpad_end" +ENV{ID_INPUT}=="", GOTO="touchpad_end" +ENV{ID_INPUT_TOUCHPAD}=="", GOTO="touchpad_end" +KERNEL!="event*", GOTO="touchpad_end" + +# touchpad::vp:name::* +KERNELS=="input*", ENV{ID_BUS}!="", \ + IMPORT{builtin}="hwdb 'touchpad:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \ + GOTO="touchpad_end" + +LABEL="touchpad_end" diff --git a/rules.d/75-net-description.rules b/rules.d/75-net-description.rules new file mode 100644 index 00000000..7e62f8b2 --- /dev/null +++ b/rules.d/75-net-description.rules @@ -0,0 +1,14 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="net_end" +SUBSYSTEM!="net", GOTO="net_end" + +IMPORT{builtin}="net_id" + +SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" +SUBSYSTEMS=="usb", GOTO="net_end" + +SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" +SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci" + +LABEL="net_end" diff --git a/rules.d/75-probe_mtd.rules b/rules.d/75-probe_mtd.rules new file mode 100644 index 00000000..8848aeea --- /dev/null +++ b/rules.d/75-probe_mtd.rules @@ -0,0 +1,7 @@ +# do not edit this file, it will be overwritten on update + +ACTION!="add", GOTO="mtd_probe_end" + +KERNEL=="mtd*ro", IMPORT{program}="mtd_probe $devnode" + +LABEL="mtd_probe_end" diff --git a/rules.d/78-sound-card.rules b/rules.d/78-sound-card.rules new file mode 100644 index 00000000..f2fc2773 --- /dev/null +++ b/rules.d/78-sound-card.rules @@ -0,0 +1,96 @@ +# do not edit this file, it will be overwritten on update + +SUBSYSTEM!="sound", GOTO="sound_end" + +ACTION=="add|change", KERNEL=="controlC*", ATTR{../uevent}="change" +ACTION!="change", GOTO="sound_end" + +# Ok, we probably need a little explanation here for what the two lines above +# are good for. +# +# The story goes like this: when ALSA registers a new sound card it emits a +# series of 'add' events to userspace, for the main card device and for all the +# child device nodes that belong to it. udev relays those to applications, +# however only maintains the order between father and child, but not between +# the siblings. The control device node creation can be used as synchronization +# point. All other devices that belong to a card are created in the kernel +# before it. However unfortunately due to the fact that siblings are forwarded +# out of order by udev this fact is lost to applications. +# +# OTOH before an application can open a device it needs to make sure that all +# its device nodes are completely created and set up. +# +# As a workaround for this issue we have added the udev rule above which will +# generate a 'change' event on the main card device from the 'add' event of the +# card's control device. Due to the ordering semantics of udev this event will +# only be relayed after all child devices have finished processing properly. +# When an application needs to listen for appearing devices it can hence look +# for 'change' events only, and ignore the actual 'add' events. +# +# When the application is initialized at the same time as a device is plugged +# in it may need to figure out if the 'change' event has already been triggered +# or not for a card. To find that out we store the flag environment variable +# SOUND_INITIALIZED on the device which simply tells us if the card 'change' +# event has already been processed. + +KERNEL!="card*", GOTO="sound_end" + +ENV{SOUND_INITIALIZED}="1" + +IMPORT{builtin}="hwdb" +SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" +SUBSYSTEMS=="usb", GOTO="skip_pci" + +SUBSYSTEMS=="firewire", ATTRS{guid}=="?*", \ + ENV{ID_BUS}="firewire", ENV{ID_SERIAL}="$attr{guid}", ENV{ID_SERIAL_SHORT}="$attr{guid}", \ + ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{model}", \ + ENV{ID_VENDOR}="$attr{vendor_name}", ENV{ID_MODEL}="$attr{model_name}" +SUBSYSTEMS=="firewire", GOTO="skip_pci" + +SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" +SUBSYSTEMS=="pci", GOTO="skip_pci" + +# If we reach here, the device nor any of its parents are USB/PCI/firewire bus devices. +# If we now find a parent that is a platform device, assume that we're working with +# an internal sound card. +SUBSYSTEMS=="platform", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" + +LABEL="skip_pci" + +# Define ID_ID if ID_BUS and ID_SERIAL are set. This will work for both +# USB and firewire. +ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}" +ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}" + +IMPORT{builtin}="path_id" + +# The values used here for $SOUND_FORM_FACTOR and $SOUND_CLASS should be kept +# in sync with those defined for PulseAudio's src/pulse/proplist.h +# PA_PROP_DEVICE_FORM_FACTOR, PA_PROP_DEVICE_CLASS properties. + +# If the first PCM device of this card has the pcm class 'modem', then the card is a modem +ATTR{pcmC%nD0p/pcm_class}=="modem", ENV{SOUND_CLASS}="modem", GOTO="sound_end" + +# Identify cards on the internal PCI bus as internal +SUBSYSTEMS=="pci", DEVPATH=="*/0000:00:??.?/sound/*", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" + +# Devices that also support Image/Video interfaces are most likely webcams +SUBSYSTEMS=="usb", ENV{ID_USB_INTERFACES}=="*:0e????:*", ENV{SOUND_FORM_FACTOR}="webcam", GOTO="sound_end" + +# Matching on the model strings is a bit ugly, I admit +ENV{ID_MODEL}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" +ENV{ID_MODEL_FROM_DATABASE}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" + +ENV{ID_MODEL}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" +ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" + +ENV{ID_MODEL}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" +ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" + +ENV{ID_MODEL}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" +ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" + +ENV{ID_MODEL}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" +ENV{ID_MODEL_FROM_DATABASE}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" + +LABEL="sound_end" diff --git a/rules.d/80-drivers.rules b/rules.d/80-drivers.rules new file mode 100644 index 00000000..16fa5d8e --- /dev/null +++ b/rules.d/80-drivers.rules @@ -0,0 +1,13 @@ +# do not edit this file, it will be overwritten on update + +ACTION!="add", GOTO="drivers_end" + +ENV{MODALIAS}=="?*", RUN{builtin}+="kmod load $env{MODALIAS}" +SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN{builtin}+="kmod load tifm_sd" +SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN{builtin}+="kmod load tifm_ms" +SUBSYSTEM=="memstick", RUN{builtin}+="kmod load ms_block mspro_block" +SUBSYSTEM=="i2o", RUN{builtin}+="kmod load i2o_block" +SUBSYSTEM=="module", KERNEL=="parport_pc", RUN{builtin}+="kmod load ppdev" +KERNEL=="mtd*ro", ENV{MTD_FTL}=="smartmedia", RUN{builtin}+="kmod load sm_ftl" + +LABEL="drivers_end" diff --git a/rules.d/80-net-setup-link.rules b/rules.d/80-net-setup-link.rules new file mode 100644 index 00000000..6e411a91 --- /dev/null +++ b/rules.d/80-net-setup-link.rules @@ -0,0 +1,13 @@ +# do not edit this file, it will be overwritten on update + +SUBSYSTEM!="net", GOTO="net_setup_link_end" + +IMPORT{builtin}="path_id" + +ACTION!="add", GOTO="net_setup_link_end" + +IMPORT{builtin}="net_setup_link" + +NAME=="", ENV{ID_NET_NAME}!="", NAME="$env{ID_NET_NAME}" + +LABEL="net_setup_link_end" diff --git a/rules.d/99-systemd.rules.in b/rules.d/99-systemd.rules.in new file mode 100644 index 00000000..c34b6062 --- /dev/null +++ b/rules.d/99-systemd.rules.in @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +ACTION=="remove", GOTO="systemd_end" + +SUBSYSTEM=="tty", KERNEL=="tty[a-zA-Z]*|hvc*|xvc*|hvsi*|ttysclp*|sclp_line*|3270/tty[0-9]*", TAG+="systemd" +KERNEL=="vport*", TAG+="systemd" + +SUBSYSTEM=="ubi", TAG+="systemd" + +SUBSYSTEM=="block", TAG+="systemd" +SUBSYSTEM=="block", ACTION=="add", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0" + +# Ignore encrypted devices with no identified superblock on it, since +# we are probably still calling mke2fs or mkswap on it. +SUBSYSTEM=="block", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0" + +# add symlink to GPT root disk +SUBSYSTEM=="block", ENV{ID_PART_GPT_AUTO_ROOT}=="1", ENV{ID_FS_TYPE}!="crypto_LUKS", SYMLINK+="gpt-auto-root" +SUBSYSTEM=="block", ENV{ID_PART_GPT_AUTO_ROOT}=="1", ENV{ID_FS_TYPE}=="crypto_LUKS", SYMLINK+="gpt-auto-root-luks" +SUBSYSTEM=="block", ENV{DM_UUID}=="CRYPT-*", ENV{DM_NAME}=="root", SYMLINK+="gpt-auto-root" + +# Ignore raid devices that are not yet assembled and started +SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", TEST!="md/array_state", ENV{SYSTEMD_READY}="0" +SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", ATTR{md/array_state}=="|clear|inactive", ENV{SYSTEMD_READY}="0" + +# Ignore loop devices that don't have any file attached +SUBSYSTEM=="block", KERNEL=="loop[0-9]*", ENV{DEVTYPE}=="disk", TEST!="loop/backing_file", ENV{SYSTEMD_READY}="0" + +# Ignore nbd devices until the PID file exists (which signals a connected device) +SUBSYSTEM=="block", KERNEL=="nbd*", ENV{DEVTYPE}=="disk", TEST!="pid", ENV{SYSTEMD_READY}="0" + +# We need a hardware independent way to identify network devices. We +# use the /sys/subsystem/ path for this. Kernel "bus" and "class" names +# should be treated as one namespace, like udev handles it. This is mostly +# just an identification string for systemd, so whether the path actually is +# accessible or not does not matter as long as it is unique and in the +# filesystem namespace. +# +# http://cgit.freedesktop.org/systemd/systemd/tree/src/libudev/libudev-enumerate.c#n955 + +SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/$name" +SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k" + +SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}+="bluetooth.target", ENV{SYSTEMD_USER_WANTS}+="bluetooth.target" +ENV{ID_SMARTCARD_READER}=="?*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target", ENV{SYSTEMD_USER_WANTS}+="smartcard.target" +SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target", ENV{SYSTEMD_USER_WANTS}+="sound.target" + +SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target", ENV{SYSTEMD_USER_WANTS}+="printer.target" +SUBSYSTEM=="usb", KERNEL=="lp*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target", ENV{SYSTEMD_USER_WANTS}+="printer.target" +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target", ENV{SYSTEMD_USER_WANTS}+="printer.target" + +SUBSYSTEM=="udc", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="usb-gadget.target" + +# Apply sysctl variables to network devices (and only to those) as they appear. +ACTION=="add", SUBSYSTEM=="net", KERNEL!="lo", RUN+="@rootlibexecdir@/systemd-sysctl --prefix=/net/ipv4/conf/$name --prefix=/net/ipv4/neigh/$name --prefix=/net/ipv6/conf/$name --prefix=/net/ipv6/neigh/$name" + +# Pull in backlight save/restore for all backlight devices and +# keyboard backlights +SUBSYSTEM=="backlight", TAG+="systemd", IMPORT{builtin}="path_id", ENV{SYSTEMD_WANTS}+="systemd-backlight@backlight:$name.service" +SUBSYSTEM=="leds", KERNEL=="*kbd_backlight", TAG+="systemd", IMPORT{builtin}="path_id", ENV{SYSTEMD_WANTS}+="systemd-backlight@leds:$name.service" + +# Pull in rfkill save/restore for all rfkill devices +SUBSYSTEM=="rfkill", ENV{SYSTEMD_RFKILL}="1" +SUBSYSTEM=="rfkill", IMPORT{builtin}="path_id" +SUBSYSTEM=="misc", KERNEL=="rfkill", TAG+="systemd", ENV{SYSTEMD_WANTS}+="systemd-rfkill.socket" + +# Asynchronously mount file systems implemented by these modules as soon as they are loaded. +SUBSYSTEM=="module", KERNEL=="fuse", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-fs-fuse-connections.mount" +SUBSYSTEM=="module", KERNEL=="configfs", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-kernel-config.mount" + +LABEL="systemd_end" diff --git a/rules.d/meson.build b/rules.d/meson.build new file mode 100644 index 00000000..13d1d330 --- /dev/null +++ b/rules.d/meson.build @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +rules = files(''' + 60-block.rules + 60-cdrom_id.rules + 60-drm.rules + 60-evdev.rules + 60-fido-id.rules + 60-input-id.rules + 60-persistent-alsa.rules + 60-persistent-input.rules + 60-persistent-storage.rules + 60-persistent-storage-tape.rules + 60-persistent-v4l.rules + 60-sensor.rules + 60-serial.rules + 61-autosuspend-manual.rules + 70-joystick.rules + 70-mouse.rules + 70-touchpad.rules + 75-net-description.rules + 75-probe_mtd.rules + 78-sound-card.rules + 80-drivers.rules + 80-net-setup-link.rules +'''.split()) + +install_data(rules, + install_dir : udevrulesdir) + +all_rules = rules + +rules_in = ''' + 50-udev-default.rules + 64-btrfs.rules + 99-systemd.rules +'''.split() + +foreach file : rules_in + gen = configure_file( + input : file + '.in', + output : file, + configuration : substs) + install_data(gen, + install_dir : udevrulesdir) + all_rules += gen +endforeach + +auto_suspend_rules = custom_target( + '60-autosuspend-chromiumos.rules', + output : '60-autosuspend-chromiumos.rules', + command : make_autosuspend_rules_py, + capture : true, + install : true, + install_dir: [udevrulesdir]) diff --git a/semaphoreci/semaphore-runner.sh b/semaphoreci/semaphore-runner.sh new file mode 100755 index 00000000..9e98638d --- /dev/null +++ b/semaphoreci/semaphore-runner.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +set -eux + +# default to Debian testing +DISTRO=${DISTRO:-debian} +RELEASE=${RELEASE:-buster} +BRANCH=${BRANCH:-master} +ARCH=${ARCH:-amd64} +CONTAINER=${RELEASE}-${ARCH} +CACHE_DIR=${SEMAPHORE_CACHE_DIR:=/tmp} +AUTOPKGTEST_DIR="${CACHE_DIR}/autopkgtest" +# semaphore cannot expose these, but useful for interactive/local runs +ARTIFACTS_DIR=/tmp/artifacts +PHASES=(${@:-SETUP RUN}) + +create_container() { + # create autopkgtest LXC image; this sometimes fails with "Unable to fetch + # GPG key from keyserver", so retry a few times + for retry in $(seq 5); do + sudo lxc-create -n $CONTAINER -t download -- -d $DISTRO -r $RELEASE -a $ARCH --keyserver hkp://keyserver.ubuntu.com:80 && break + sleep $((retry*retry)) + done + + # unconfine the container, otherwise some tests fail + echo 'lxc.apparmor.profile = unconfined' | sudo tee -a /var/lib/lxc/$CONTAINER/config + + sudo lxc-start -n $CONTAINER + + # enable source repositories so that apt-get build-dep works + sudo lxc-attach -n $CONTAINER -- sh -ex <> /etc/apt/sources.list.d/sources.list +# wait until online +while [ -z "\$(ip route list 0/0)" ]; do sleep 1; done +apt-get -q --allow-releaseinfo-change update +apt-get -y dist-upgrade +apt-get install -y eatmydata +apt-get purge --auto-remove -y unattended-upgrades +systemctl unmask systemd-networkd +systemctl enable systemd-networkd +EOF + sudo lxc-stop -n $CONTAINER +} + +for phase in "${PHASES[@]}"; do + case $phase in + SETUP) + # remove semaphore repos, some of them don't work and cause error messages + sudo rm -f /etc/apt/sources.list.d/* + + # enable backports for latest LXC + echo 'deb http://archive.ubuntu.com/ubuntu xenial-backports main restricted universe multiverse' | sudo tee -a /etc/apt/sources.list.d/backports.list + sudo apt-get -q update + sudo apt-get install -y -t xenial-backports lxc + sudo apt-get install -y python3-debian git dpkg-dev fakeroot + + [ -d $AUTOPKGTEST_DIR ] || git clone --quiet --depth=1 https://salsa.debian.org/ci-team/autopkgtest.git "$AUTOPKGTEST_DIR" + + create_container + ;; + RUN) + # add current debian/ packaging + git fetch --depth=1 https://salsa.debian.org/systemd-team/systemd.git $BRANCH + git checkout FETCH_HEAD debian + + # craft changelog + UPSTREAM_VER=$(git describe | sed 's/^v//') + cat << EOF > debian/changelog.new +systemd (${UPSTREAM_VER}-0) UNRELEASED; urgency=low + + * Automatic build for upstream test + + -- systemd test $(date -R) + +EOF + cat debian/changelog >> debian/changelog.new + mv debian/changelog.new debian/changelog + + # clean out patches + rm -rf debian/patches + # disable autopkgtests which are not for upstream + sed -i '/# NOUPSTREAM/ q' debian/tests/control + # enable more unit tests + sed -i '/^CONFFLAGS =/ s/=/= --werror -Dtests=unsafe -Dsplit-usr=true -Dslow-tests=true -Dman=true /' debian/rules + # no orig tarball + echo '1.0' > debian/source/format + + # build source package + dpkg-buildpackage -S -I -I$(basename "$CACHE_DIR") -d -us -uc -nc + + # now build the package and run the tests + rm -rf "$ARTIFACTS_DIR" + # autopkgtest exits with 2 for "some tests skipped", accept that + $AUTOPKGTEST_DIR/runner/autopkgtest --env DEB_BUILD_OPTIONS=noudeb \ + --env TEST_UPSTREAM=1 ../systemd_*.dsc \ + -o "$ARTIFACTS_DIR" \ + -- lxc -s $CONTAINER \ + || [ $? -eq 2 ] + ;; + *) + echo >&2 "Unknown phase '$phase'" + exit 1 + esac +done diff --git a/shell-completion/bash/bootctl b/shell-completion/bash/bootctl new file mode 100644 index 00000000..27b73900 --- /dev/null +++ b/shell-completion/bash/bootctl @@ -0,0 +1,95 @@ +# bootctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_entry_ids() { + bootctl --no-pager list 2>/dev/null | { while read -r a b; do [[ $a == 'id:' ]] && echo " $b"; done } +} + +_bootctl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help --no-variables -p --print-esp-path -x --print-boot-path --version --no-pager' + [ARG]='--esp-path --boot-path' + ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --esp-path|--boot-path) + if [[ -z $cur ]]; then + comps=$(compgen -A directory -- "/" ) + else + comps=$(compgen -A directory -- "$cur" ) + fi + compopt -o filenames + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [STANDALONE]='help install list remove status update' + [BOOTENTRY]='set-default set-oneshot' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + elif __contains_word "$verb" ${VERBS[BOOTENTRY]}; then + name= + for ((i++; i < COMP_CWORD; i++)); do + if ! __contains_word "${COMP_WORDS[i]}" ${OPTS[*]} ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps=$( __get_entry_ids ) + else + comps='' + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _bootctl bootctl diff --git a/shell-completion/bash/busctl b/shell-completion/bash/busctl new file mode 100644 index 00000000..96bf9ae2 --- /dev/null +++ b/shell-completion/bash/busctl @@ -0,0 +1,207 @@ +# busctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + machinectl list --no-legend --no-pager 2>/dev/null | + { while read a b; do echo " $a"; done; }; +} + +__get_busnames() { + local mode=$1 + local a b + COLUMNS=65535 busctl $mode list --no-legend --no-pager 2>/dev/null | + { while read a b; do echo " $a"; done; }; +} + +__get_objects() { + local mode=$1 + local busname=$2 + local a b + busctl $mode tree --list --no-legend --no-pager $busname 2>/dev/null | + { while read a b; do echo " $a"; done; }; +} + +__get_interfaces() { + local mode=$1 + local busname=$2 + local path=$3 + local a b c + busctl $mode introspect --list --no-legend --no-pager $busname $path 2>/dev/null | + { while read a b c; do [[ "$b" == "interface" ]] && echo " $a"; done; }; +} + +__get_members() { + local mode=$1 + local busname=$2 + local path=$3 + local interface=$4 + local type=$5 + local flags=$6 + local a b c d e + busctl $mode introspect --list --no-legend --no-pager $busname $path $interface 2>/dev/null | + sed -e 's/^\.//' | + { while read a b c d e; do [[ "$b" == "$type" && ( -z $flags || "$e" == "$flags" ) ]] && echo " $a"; done; }; +} + +__get_signature() { + local mode=$1 + local busname=$2 + local path=$3 + local interface=$4 + local member=$5 + local a b c d + busctl $mode introspect --list --no-legend --no-pager $busname $path $interface 2>/dev/null | + sed -e 's/^\.//' | { while read a b c d; do [[ "$a" == "$member" && "$c" != '-' ]] && echo " \"$c\""; done; }; +} + +_busctl() { + local i n verb comps mode + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help --version --no-pager --no-legend --system --user + --show-machine --unique --acquired --activatable --list + -q --quiet --verbose --expect-reply=no --auto-start=no + --allow-interactive-authorization=no --augment-creds=no + --watch-bind=yes -j' + [ARG]='--address -H --host -M --machine --match --timeout --size --json + --destination' + ) + + if __contains_word "--user" ${COMP_WORDS[*]}; then + mode=--user + else + mode=--system + fi + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --json) + comps=$( busctl --json=help 2>/dev/null ) + ;; + --destination) + comps=$( __get_busnames $mode ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [STANDALONE]='list help' + [BUSNAME]='status monitor capture tree' + [OBJECT]='introspect' + [METHOD]='call' + [EMIT]='emit' + [PROPERTY_GET]='get-property' + [PROPERTY_SET]='set-property' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + n=$(($COMP_CWORD - $i)) + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + elif __contains_word "$verb" ${VERBS[BUSNAME]}; then + comps=$( __get_busnames $mode) + elif __contains_word "$verb" ${VERBS[OBJECT]}; then + if [[ $n -eq 1 ]] ; then + comps=$( __get_busnames $mode) + elif [[ $n -eq 2 ]] ; then + comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 3 ]] ; then + comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + else + comps='' + fi + elif __contains_word "$verb" ${VERBS[METHOD]}; then + if [[ $n -eq 1 ]] ; then + comps=$( __get_busnames $mode) + elif [[ $n -eq 2 ]] ; then + comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 3 ]] ; then + comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 4 ]] ; then + comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} method) + elif [[ $n -eq 5 ]] ; then + comps=$( __get_signature $mode ${COMP_WORDS[COMP_CWORD-4]} ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + else + comps='' + fi + elif __contains_word "$verb" ${VERBS[EMIT]}; then + comps='' + elif __contains_word "$verb" ${VERBS[PROPERTY_GET]}; then + if [[ $n -eq 1 ]] ; then + comps=$( __get_busnames $mode) + elif [[ $n -eq 2 ]] ; then + comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 3 ]] ; then + comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 4 ]] ; then + comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} property) + else + comps='' + fi + elif __contains_word "$verb" ${VERBS[PROPERTY_SET]}; then + if [[ $n -eq 1 ]] ; then + comps=$( __get_busnames $mode) + elif [[ $n -eq 2 ]] ; then + comps=$( __get_objects $mode ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 3 ]] ; then + comps=$( __get_interfaces $mode ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + elif [[ $n -eq 4 ]] ; then + comps=$( __get_members $mode ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]} property writable) + elif [[ $n -eq 5 ]] ; then + comps=$( __get_signature $mode ${COMP_WORDS[COMP_CWORD-4]} ${COMP_WORDS[COMP_CWORD-3]} ${COMP_WORDS[COMP_CWORD-2]} ${COMP_WORDS[COMP_CWORD-1]}) + else + comps='' + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _busctl busctl diff --git a/shell-completion/bash/coredumpctl b/shell-completion/bash/coredumpctl new file mode 100644 index 00000000..d4366df0 --- /dev/null +++ b/shell-completion/bash/coredumpctl @@ -0,0 +1,94 @@ +# coredumpctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC} + ERRNO SYSLOG_{FACILITY,IDENTIFIER,PID} COREDUMP_EXE + _{P,U,G}ID _COMM _EXE _CMDLINE + _AUDIT_{SESSION,LOGINUID} + _SYSTEMD_{CGROUP,SESSION,UNIT,OWNER_UID} + _SELINUX_CONTEXT _SOURCE_REALTIME_TIMESTAMP + _{BOOT,MACHINE}_ID _HOSTNAME _TRANSPORT + _KERNEL_{DEVICE,SUBSYSTEM} + _UDEV_{SYSNAME,DEVNODE,DEVLINK} + __CURSOR __{REALTIME,MONOTONIC}_TIMESTAMP) +_coredumpctl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local OPTS='-h --help --version --no-pager --no-legend -o --output -F --field -1 + -r --reverse -S --since -U --until -D --directory -q --quiet --debugger' + + local -A VERBS=( + [LIST]='list info' + [DUMP]='dump debug' + ) + + if __contains_word "$prev" '--output -o'; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + elif __contains_word "$prev" '-D --directory'; then + comps=$( compgen -A directory -- "$cur" ) + compopt -o filenames + elif __contains_word "$prev" '--debugger'; then + comps=$( compgen -A command -- "$cur" ) + compopt -o filenames + elif __contains_word "$prev" '--field -F'; then + comps=$( compgen -W '${__journal_fields[*]}' -- "$cur" ) + elif [[ $cur = -* ]]; then + comps=${OPTS} + elif __contains_word "$prev" ${VERBS[*]} && + ! __contains_word ${COMP_WORDS[COMP_CWORD-2]} \ + '--output -o -D --directory -F --field --debugger'; then + compopt -o nospace + COMPREPLY=( $(compgen -W '${__journal_fields[*]}' -S= -- "$cur") ) + return 0 + elif [[ $cur = *=* ]]; then + mapfile -t field_vals < <(coredumpctl -F "${prev%=}" 2>/dev/null) + COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "${cur#=}") ) + return 0 + elif [[ $prev = '=' ]]; then + mapfile -t field_vals < <(coredumpctl -F "${COMP_WORDS[COMP_CWORD-2]}" 2>/dev/null) + comps=${field_vals[*]} + else + for ((i=0; i <= COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[LIST]} ${VERBS[DUMP]}; then + comps='' + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _coredumpctl coredumpctl diff --git a/shell-completion/bash/hostnamectl b/shell-completion/bash/hostnamectl new file mode 100644 index 00000000..0d829e70 --- /dev/null +++ b/shell-completion/bash/hostnamectl @@ -0,0 +1,65 @@ +# hostnamectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +_hostnamectl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local OPTS='-h --help --version --transient --static --pretty + --no-ask-password -H --host -M --machine' + + if [[ $cur = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [STANDALONE]='status' + [ICONS]='set-icon-name' + [NAME]='set-hostname set-deployment set-location' + [CHASSIS]='set-chassis' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[CHASSIS]}; then + comps='desktop laptop convertible server tablet handset watch embedded vm container' + elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[ICONS]} ${VERBS[NAME]}; then + comps='' + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _hostnamectl hostnamectl diff --git a/shell-completion/bash/journalctl b/shell-completion/bash/journalctl new file mode 100644 index 00000000..35ff311b --- /dev/null +++ b/shell-completion/bash/journalctl @@ -0,0 +1,149 @@ +# journalctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + (machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager; echo ".host") | \ + { while read a b; do echo " $a"; done; } | sort -u; +} + +__syslog_priorities=(emerg alert crit err warning notice info debug) + +_journalctl() { + local field_vals= cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-a --all --full --system --user + --disk-usage -f --follow --header + -h --help -l --local -m --merge --no-pager + --no-tail -q --quiet --setup-keys --verify + --version --list-catalog --update-catalog --list-boots + --show-cursor --dmesg -k --pager-end -e -r --reverse + --utc -x --catalog --no-full --force --dump-catalog + --flush --rotate --sync --no-hostname -N --fields' + [ARG]='-b --boot -D --directory --file -F --field -t --identifier + -M --machine -o --output -u --unit --user-unit -p --priority + --root --case-sensitive' + [ARGUNKNOWN]='-c --cursor --interval -n --lines -S --since -U --until + --after-cursor --cursor-file --verify-key -g --grep + --vacuum-size --vacuum-time --vacuum-files --output-fields' + ) + + # Use the default completion for shell redirect operators + if __contains_word "$prev" '>' '>>' '&>'; then + compopt -o filenames + COMPREPLY=( $(compgen -f -- "$cur") ) + return 0; + fi + + if __contains_word "$prev" ${OPTS[ARG]} ${OPTS[ARGUNKNOWN]}; then + case $prev in + --boot|-b) + comps=$(journalctl -F '_BOOT_ID' 2>/dev/null) + ;; + --directory|-D|--root) + comps=$(compgen -d -- "$cur") + compopt -o filenames + ;; + --file) + comps=$(compgen -f -- "$cur") + compopt -o filenames + ;; + --output|-o) + comps=$( journalctl --output=help 2>/dev/null ) + ;; + --field|-F) + comps=$(journalctl --fields | sort 2>/dev/null) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --priority|-p) + comps=${__syslog_priorities[*]} + compopt -o nosort + ;; + --unit|-u) + comps=$(journalctl -F '_SYSTEMD_UNIT' 2>/dev/null) + # Similarly to systemctl, we need to distinguish between + # escaped and unescaped names in order to be able to correctly + # complete them. In this particular case, if the name we're + # trying to complete is unescaped (i.e. foo\x2dbaz), escape + # it first, so the compgen below works as expected. For more + # information about these shenanigans see the systemctl + # completion file + if ! [[ $cur =~ '\\' ]]; then + cur="$(printf '%q' $cur)" + fi + compopt -o filenames + ;; + --user-unit) + comps=$(journalctl -F '_SYSTEMD_USER_UNIT' 2>/dev/null) + ;; + --identifier|-t) + comps=$(journalctl -F 'SYSLOG_IDENTIFIER' 2>/dev/null) + ;; + --case-sensitive) + comps='yes no' + ;; + *) + return 0 + ;; + esac + COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + elif [[ $cur = *=* ]]; then + mapfile -t field_vals < <(journalctl -F "${prev%=}" 2>/dev/null) + COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "${cur#=}") ) + elif [[ $cur = /dev* ]]; then + compopt -o filenames + COMPREPLY=( $(compgen -f -- "${cur}") ) + elif [[ $cur = /* ]]; then + # Append /dev/ to the list of completions, so that + # after typing / the user sees /dev/ as one + # of the alternatives. Later on the rule above will + # take care of showing device files in /dev/. + mapfile -t field_vals < <(journalctl -F "_EXE" 2>/dev/null; echo '/dev/') + COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "${cur}") ) + if [[ "${COMPREPLY[@]}" = '/dev/' ]]; then + compopt -o filenames + COMPREPLY=( $(compgen -f -- "${cur}") ) + fi + elif [[ $prev = '=' ]]; then + mapfile -t field_vals < <(journalctl -F "${COMP_WORDS[COMP_CWORD-2]}" 2>/dev/null) + COMPREPLY=( $(compgen -W '${field_vals[*]}' -- "$cur") ) + else + mapfile -t field_vals < <(journalctl --fields 2>/dev/null) + compopt -o nospace + COMPREPLY=( $(compgen -W '${field_vals[*]}' -S= -- "$cur") ) + fi +} + +complete -F _journalctl journalctl diff --git a/shell-completion/bash/kernel-install b/shell-completion/bash/kernel-install new file mode 100644 index 00000000..224ea83e --- /dev/null +++ b/shell-completion/bash/kernel-install @@ -0,0 +1,48 @@ +# kernel-install(8) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +_kernel_install() { + local comps + local MACHINE_ID + local cur=${COMP_WORDS[COMP_CWORD]} + + case $COMP_CWORD in + 1) + comps="add remove" + ;; + 2) + comps=$(cd /lib/modules; echo [0-9]*) + if [[ ${COMP_WORDS[1]} == "remove" ]] && [[ -f /etc/machine-id ]]; then + read MACHINE_ID < /etc/machine-id + if [[ $MACHINE_ID ]] && ( [[ -d /boot/$MACHINE_ID ]] || [[ -L /boot/$MACHINE_ID ]] ); then + comps=$(cd "/boot/$MACHINE_ID"; echo [0-9]*) + fi + fi + ;; + 3) + [[ "$cur" ]] || cur=/lib/modules/${COMP_WORDS[2]}/vmlinuz + comps=$(compgen -f -- "$cur") + compopt -o filenames + ;; + esac + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _kernel_install kernel-install diff --git a/shell-completion/bash/localectl b/shell-completion/bash/localectl new file mode 100644 index 00000000..fe53112f --- /dev/null +++ b/shell-completion/bash/localectl @@ -0,0 +1,96 @@ +# localectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__locale_fields=( LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME + LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER + LC_NAME LC_ADDRESS LC_TELEPHONE + LC_MEASUREMENT LC_IDENTIFICATION ) +# LC_ALL is omitted on purpose + +_localectl() { + local i verb comps locale_vals + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local OPTS='-h --help --version --no-convert --no-pager --no-ask-password + -H --host -M --machine' + + if __contains_word "$prev" $OPTS; then + case $prev in + --host|-H) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [STANDALONE]='status list-locales list-keymaps list-x11-keymap-models list-x11-keymap-layouts list-x11-keymap-options' + [VARIANTS]='list-x11-keymap-variants' + [LOCALES]='set-locale' + [KEYMAPS]='set-keymap' + [X11]='set-x11-keymap' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[VARIANTS]}; then + comps=$(command localectl list-x11-keymap-layouts) + elif __contains_word "$verb" ${VERBS[LOCALES]}; then + if [[ $cur = *=* ]]; then + mapfile -t locale_vals < <(command localectl list-locales 2>/dev/null) + COMPREPLY=( $(compgen -W '${locale_vals[*]}' -- "${cur#=}") ) + elif [[ $prev = "=" ]]; then + mapfile -t locale_vals < <(command localectl list-locales 2>/dev/null) + COMPREPLY=( $(compgen -W '${locale_vals[*]}' -- "$cur") ) + else + compopt -o nospace + COMPREPLY=( $(compgen -W '${__locale_fields[*]}' -S= -- "$cur") ) + fi + return 0 + elif __contains_word "$verb" ${VERBS[KEYMAPS]}; then + comps=$(command localectl list-keymaps) + elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[X11]}; then + comps='' + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _localectl localectl diff --git a/shell-completion/bash/loginctl b/shell-completion/bash/loginctl new file mode 100644 index 00000000..c3e1ca75 --- /dev/null +++ b/shell-completion/bash/loginctl @@ -0,0 +1,125 @@ +# loginctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_all_sessions () { loginctl --no-legend list-sessions | { while read -r a b; do printf "%s\n" "$a"; done; } ; } +__get_all_users () { loginctl --no-legend list-users | { while read -r a b; do printf "%s\n" "$b"; done; } ; } +__get_all_seats () { loginctl --no-legend list-seats | { while read -r a b; do printf "%s\n" "$a"; done; } ; } + +__get_machines() { + local a b + machinectl list --no-legend --no-pager 2>/dev/null | + { while read a b; do echo " $a"; done; }; +} + +_loginctl () { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local i verb comps + + local -A OPTS=( + [STANDALONE]='--all -a --help -h --no-pager --version + --no-legend --no-ask-password -l --full --value' + [ARG]='--host -H --kill-who --property -p --signal -s -M --machine + -n --lines -o --output' + ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --signal|-s) + _signals + return + ;; + --kill-who) + comps='all leader' + ;; + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --property|-p) + comps='' + ;; + --output|-o) + comps=$( loginctl --output=help 2>/dev/null ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [SESSIONS]='session-status show-session activate lock-session unlock-session terminate-session kill-session' + [USERS]='user-status show-user enable-linger disable-linger terminate-user kill-user' + [SEATS]='seat-status show-seat terminate-seat' + [STANDALONE]='list-sessions lock-sessions unlock-sessions list-users list-seats flush-devices' + [ATTACH]='attach' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $verb ]]; then + comps="${VERBS[*]}" + + elif __contains_word "$verb" ${VERBS[SESSIONS]}; then + comps=$( __get_all_sessions ) + + elif __contains_word "$verb" ${VERBS[USERS]}; then + comps=$( __get_all_users ) + + elif __contains_word "$verb" ${VERBS[SEATS]}; then + comps=$( __get_all_seats ) + + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + + elif __contains_word "$verb" ${VERBS[ATTACH]}; then + if [[ $prev = $verb ]]; then + comps=$( __get_all_seats ) + else + comps=$(compgen -A file -- "$cur" ) + compopt -o filenames + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _loginctl loginctl diff --git a/shell-completion/bash/machinectl b/shell-completion/bash/machinectl new file mode 100644 index 00000000..b785cd41 --- /dev/null +++ b/shell-completion/bash/machinectl @@ -0,0 +1,116 @@ +# machinectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + (machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager; echo ".host") | \ + { while read a b; do echo " $a"; done; } | sort -u; +} + +_machinectl() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local i verb comps + + local -A OPTS=( + [STANDALONE]='--all -a -l --full --help -h --no-ask-password --no-legend --no-pager --version --value + --mkdir --read-only --force -q --quiet' + [ARG]='--host -H --kill-who -M --machine --property -p --signal -s --uid -E --setenv -n --lines + -o --output --verify --format --max-addresses' + ) + + local -A VERBS=( + [STANDALONE]='list list-images clean pull-tar pull-raw list-transfers cancel-transfer import-fs' + [MACHINES]='status show start stop login shell enable disable poweroff reboot terminate kill bind + copy-to copy-from image-status show-image clone rename read-only remove set-limit + export-tar export-raw' + [FILE]='import-tar import-raw' + ) + + _init_completion || return + + for ((i=0; i <= COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --signal|-s) + _signals + return + ;; + --kill-who) + comps='all leader' + ;; + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --property|-p) + comps='' + ;; + --output|-o) + comps=$( machinectl --output=help 2>/dev/null ) + ;; + --verify) + comps=$( machinectl --verify=help 2>/dev/null ) + ;; + --format) + comps='uncompressed xz gzip bzip2' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + + elif __contains_word "$verb" ${VERBS[MACHINES]}; then + comps=$( __get_machines ) + + elif __contains_word "$verb" ${VERBS[FILE]}; then + comps=$(compgen -f -- "cur") + compopt -o filenames + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _machinectl machinectl diff --git a/shell-completion/bash/meson.build b/shell-completion/bash/meson.build new file mode 100644 index 00000000..0d3022b1 --- /dev/null +++ b/shell-completion/bash/meson.build @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +bashcompletiondir = get_option('bashcompletiondir') +if bashcompletiondir == '' + bash_completion = dependency('bash-completion', required : false) + if bash_completion.found() + bashcompletiondir = bash_completion.get_pkgconfig_variable('completionsdir') + else + bashcompletiondir = join_paths(datadir, 'bash-completion/completions') + endif +endif + +if bashcompletiondir != 'no' + bash_systemctl = configure_file( + input : 'systemctl.in', + output : 'systemctl', + configuration : substs) + + items = [['busctl', ''], + ['journalctl', ''], + ['systemd-analyze', ''], + ['systemd-cat', ''], + ['systemd-cgls', ''], + ['systemd-cgtop', ''], + ['systemd-delta', ''], + ['systemd-detect-virt', ''], + ['systemd-nspawn', ''], + ['systemd-path', ''], + ['systemd-run', ''], + ['udevadm', ''], + ['kernel-install', ''], + [bash_systemctl, ''], + ['bootctl', 'ENABLE_EFI'], + ['coredumpctl', 'ENABLE_COREDUMP'], + ['hostnamectl', 'ENABLE_HOSTNAMED'], + ['localectl', 'ENABLE_LOCALED'], + ['loginctl', 'ENABLE_LOGIND'], + ['machinectl', 'ENABLE_MACHINED'], + ['networkctl', 'ENABLE_NETWORKD'], + ['portablectl', 'ENABLE_PORTABLED'], + ['resolvectl', 'ENABLE_RESOLVE'], + ['systemd-resolve', 'ENABLE_RESOLVE'], + ['timedatectl', 'ENABLE_TIMEDATED'], + ] + + foreach item : items + if item[1] == '' or conf.get(item[1]) == 1 + install_data(item[0], + install_dir : bashcompletiondir) + endif + endforeach +endif diff --git a/shell-completion/bash/networkctl b/shell-completion/bash/networkctl new file mode 100644 index 00000000..290a62f8 --- /dev/null +++ b/shell-completion/bash/networkctl @@ -0,0 +1,71 @@ +# networkctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done + return 1 +} + +__get_links() { + networkctl list --no-legend --no-pager --all | { while read -r a b c; do echo " $b"; done; }; +} + +_networkctl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-a --all -h --help --version --no-pager --no-legend -s --stats' + [ARG]='' + ) + + local -A VERBS=( + [STANDALONE]='label' + [LINKS]='status list lldp delete renew' + ) + + _init_completion || return + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + elif __contains_word "$verb" ${VERBS[LINKS]}; then + comps=$( __get_links ) + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _networkctl networkctl diff --git a/shell-completion/bash/portablectl b/shell-completion/bash/portablectl new file mode 100644 index 00000000..d20c9629 --- /dev/null +++ b/shell-completion/bash/portablectl @@ -0,0 +1,111 @@ +# portablectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + machinectl list --no-legend --no-pager 2>/dev/null | + { while read a b; do echo " $a"; done; }; +} + +_portablectl() { + local i n comps verb + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-q --quiet --runtime --no-reload --cat --no-pager --no-legend + --no-ask-password -h --help --version' + [ARG]='-p --profile --copy -H --host -M --machine' + ) + + local -A VERBS=( + [STANDALONE]='list' + [IMAGE]='attach detach inspect is-attached set-limit' + [IMAGES]='remove' + [IMAGE_WITH_BOOL]='read-only' + ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --profile|-p) + comps="default nonetwork strict trusted" + ;; + --copy) + comps="copy symlink auto" + ;; + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + n=$(($COMP_CWORD - $i)) + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + elif __contains_word "$verb" ${VERBS[IMAGE]}; then + if [[ $n == 1 ]]; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + else + comps='' + fi + elif __contains_word "$verb" ${VERBS[IMAGES]}; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + elif __contains_word "$verb" ${VERBS[IMAGE_WITH_BOOL]}; then + if [[ $n == 1 ]]; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + elif [[ $n == 2 ]]; then + comps='yes no' + else + comps='' + fi + fi + + COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _portablectl portablectl diff --git a/shell-completion/bash/resolvectl b/shell-completion/bash/resolvectl new file mode 100644 index 00000000..d4ac3390 --- /dev/null +++ b/shell-completion/bash/resolvectl @@ -0,0 +1,181 @@ +# resolvectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_interfaces(){ + local name + for name in $(cd /sys/class/net && ls); do + [[ "$name" != "lo" ]] && echo "$name" + done +} + +_resolvectl() { + local i comps verb name + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help --version --no-pager -4 -6 + --service-address=no --service-txt=no + --cname=no --search=no --legend=no' + [ARG]='-i --interface -p --protocol -t --type -c --class --raw' + ) + local -A VERBS=( + [DOMAIN]='query service openpgp' + [FAMILY]='tlsa' + [STATUS]='status' + [LINK]='revert dns domain nta' + [RESOLVE]='llmnr mdns' + [DNSSEC]='dnssec' + [DNSOVERTLS]='dnsovertls' + [STANDALONE]='statistics reset-statistics flush-caches reset-server-features' + ) + local -A ARGS=( + [FAMILY]='tcp udp sctp' + [RESOLVE]='yes no resolve' + [DNSSEC]='yes no allow-downgrade' + [DNSOVERTLS]='yes no opportunistic' + ) + local interfaces=$( __get_interfaces ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --interface|-i) + comps="$interfaces" + ;; + --protocol|-p|--type|-t|--class|-c) + comps=$( resolvectl --legend=no "$prev" help; echo help ) + ;; + --raw) + comps="payload packet" + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $verb ]]; then + comps="${VERBS[*]}" + + elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[DOMAIN]}; then + comps='' + + elif __contains_word "$verb" ${VERBS[STATUS]}; then + comps="$interfaces" + + elif __contains_word "$verb" ${VERBS[FAMILY]}; then + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${ARGS[FAMILY]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + if [[ -z $name ]]; then + comps=${ARGS[FAMILY]} + else + comps="" + fi + + elif __contains_word "$verb" ${VERBS[LINK]} ${VERBS[RESOLVE]} ${VERBS[DNSSEC]} ${VERBS[DNSOVERTLS]}; then + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" $interfaces && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps="$interfaces" + + elif __contains_word "$verb" ${VERBS[RESOLVE]}; then + name= + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${ARGS[RESOLVE]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps=${ARGS[RESOLVE]} + else + comps='' + fi + + elif __contains_word "$verb" ${VERBS[DNSSEC]}; then + name= + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${ARGS[DNSSEC]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps=${ARGS[DNSSEC]} + else + comps='' + fi + + elif __contains_word "$verb" ${VERBS[DNSOVERTLS]}; then + name= + for ((i++; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${ARGS[DNSOVERTLS]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + name=${COMP_WORDS[i]} + break; + fi + done + + if [[ -z $name ]]; then + comps=${ARGS[DNSOVERTLS]} + else + comps='' + fi + + else + comps='' + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _resolvectl resolvectl diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in new file mode 100644 index 00000000..1bda6f2b --- /dev/null +++ b/shell-completion/bash/systemctl.in @@ -0,0 +1,335 @@ +# systemctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita + +__systemctl() { + local mode=$1; shift 1 + systemctl $mode --full --no-legend --no-pager "$@" 2>/dev/null +} + +__systemd_properties() { + @rootlibexecdir@/systemd --dump-bus-properties +} + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__filter_units_by_properties () { + local mode=$1 properties=$2; shift 2 + local units=("$@") + local props i p n + local names= count=0 + + IFS=$',' read -r -a p < <(echo "Names,$properties") + n=${#p[*]} + readarray -t props < \ + <(__systemctl $mode show --property "Names,$properties" -- "${units[@]}") + + for ((i=0; i < ${#props[*]}; i++)); do + if [[ -z ${props[i]} ]]; then + if (( count == n )) && [[ -n $names ]]; then + echo $names + fi + names= + count=0 + else + (( count++ )) + if [[ ${props[i]%%=*} == 'Names' ]]; then + names=${props[i]#*=} + fi + fi + done + if (( count == n )) && [[ -n $names ]]; then + echo $names + fi +} + +__get_all_units () { { __systemctl $1 list-unit-files "$2*"; __systemctl $1 list-units --all "$2*"; } \ + | { while read -r a b; do echo " $a"; done; }; } +__get_non_template_units() { { __systemctl $1 list-unit-files "$2*"; __systemctl $1 list-units --all "$2*"; } \ + | { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; }; } +__get_template_names () { __systemctl $1 list-unit-files "$2*" \ + | { while read -r a b; do [[ $a =~ @\. ]] && echo " ${a%%@.*}@"; done; }; } +__get_active_units () { __systemctl $1 list-units "$2*" \ + | { while read -r a b; do echo " $a"; done; }; } + +__get_not_masked_unit_files() { + # filter out masked, not-found, or template units. + __systemctl $1 list-unit-files --state enabled,enabled-runtime,linked,linked-runtime,static,indirect,disabled,generated,transient "$2*" | \ + { while read -r a b; do [[ $a =~ @\. ]] || echo " $a"; done; } +} + +__get_startable_units () { + __filter_units_by_properties $1 ActiveState=inactive,CanStart=yes $( + { __get_not_masked_unit_files $1 $2 + # get inactive template units + __systemctl $1 list-units --state inactive,failed "$2*" | \ + { while read -r a b c; do [[ $b == "loaded" ]] && echo " $a"; done; } + } | sort -u ) +} +__get_restartable_units () { + # filter out masked and not-found + __filter_units_by_properties $1 CanStart=yes $( + { __get_not_masked_unit_files $1 $2 + __get_active_units $1 $2 + } | sort -u ) +} + +__get_stoppable_units () { + # filter out masked and not-found + local units=$( + { __get_not_masked_unit_files $1 $2 + __get_active_units $1 $2 + } | sort -u ) + __filter_units_by_properties $1 ActiveState=active,CanStop=yes $units + __filter_units_by_properties $1 ActiveState=reloading,CanStop=yes $units + __filter_units_by_properties $1 ActiveState=activating,CanStop=yes $units +} + +__get_reloadable_units () { + # filter out masked and not-found + __filter_units_by_properties $1 ActiveState=active,CanReload=yes $( + { __get_not_masked_unit_files $1 $2 + __get_active_units $1 $2 + } | sort -u ) +} + +__get_failed_units () { __systemctl $1 list-units "$2*" \ + | { while read -r a b c d; do [[ $c == "failed" ]] && echo " $a"; done; }; } +__get_enabled_units () { __systemctl $1 list-unit-files "$2*" \ + | { while read -r a b c ; do [[ $b == "enabled" ]] && echo " $a"; done; }; } +__get_disabled_units () { __systemctl $1 list-unit-files "$2*" \ + | { while read -r a b c ; do [[ $b == "disabled" ]] && echo " $a"; done; }; } +__get_masked_units () { __systemctl $1 list-unit-files "$2*" \ + | { while read -r a b c ; do [[ $b == "masked" ]] && echo " $a"; done; }; } +__get_all_unit_files () { { __systemctl $1 list-unit-files "$2*"; } | { while read -r a b; do echo " $a"; done; }; } + +__get_machines() { + local a b + { machinectl list-images --no-legend --no-pager; machinectl list --no-legend --no-pager; } | \ + { while read a b; do echo " $a"; done; } +} + +_systemctl () { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local i verb comps mode cur_orig + + local -A OPTS=( + [STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global + --help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall --now + --quiet -q --system --user --version --runtime --recursive -r --firmware-setup + --show-types -i --ignore-inhibitors --plain --failed --value --fail --dry-run --wait' + [ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --job-mode --root + --preset-mode -n --lines -o --output -M --machine --message' + ) + + if __contains_word "--user" ${COMP_WORDS[*]}; then + mode=--user + elif __contains_word "--global" ${COMP_WORDS[*]}; then + mode=--user + else + mode=--system + fi + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --signal|-s) + _signals + return + ;; + --type|-t) + comps=$(__systemctl $mode -t help) + ;; + --state) + comps=$(__systemctl $mode --state=help) + ;; + --job-mode) + comps='fail replace replace-irreversibly isolate + ignore-dependencies ignore-requirements flush' + ;; + --kill-who) + comps='all control main' + ;; + --root) + comps=$(compgen -A directory -- "$cur" ) + compopt -o filenames + ;; + --host|-H) + comps=$(compgen -A hostname) + ;; + --property|-p) + comps=$(__systemd_properties) + ;; + --preset-mode) + comps='full enable-only disable-only' + ;; + --output|-o) + comps=$( systemctl --output=help 2>/dev/null ) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [ALL_UNITS]='cat mask' + [NONTEMPLATE_UNITS]='is-active is-failed is-enabled status show preset help list-dependencies edit set-property revert' + [ENABLED_UNITS]='disable' + [DISABLED_UNITS]='enable' + [REENABLABLE_UNITS]='reenable' + [FAILED_UNITS]='reset-failed' + [STARTABLE_UNITS]='start' + [STOPPABLE_UNITS]='stop condstop kill try-restart condrestart' + [ISOLATABLE_UNITS]='isolate' + [RELOADABLE_UNITS]='reload condreload try-reload-or-restart force-reload' + [RESTARTABLE_UNITS]='restart reload-or-restart' + [TARGET_AND_UNITS]='add-wants add-requires' + [MASKED_UNITS]='unmask' + [JOBS]='cancel' + [ENVS]='set-environment unset-environment import-environment' + [STANDALONE]='daemon-reexec daemon-reload default + emergency exit halt hibernate hybrid-sleep + suspend-then-hibernate kexec list-jobs list-sockets + list-timers list-units list-unit-files poweroff + reboot rescue show-environment suspend get-default + is-system-running preset-all' + [FILE]='link switch-root' + [TARGETS]='set-default' + [MACHINES]='list-machines' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + # When trying to match a unit name with certain special characters in its name (i.e + # foo\x2dbar:01) they get (un)escaped by bash along the way, thus causing any possible + # match to fail. + # The following condition solves two cases: + # 1) We're trying to complete an already escaped unit name part, + # i.e foo\\x2dba. In this case we need to unescape the name, so it + # gets properly matched with the systemctl output (i.e. foo\x2dba). + # However, we need to keep the original escaped name as well for the + # final match, as the completion machinery does the unescaping + # automagically. + # 2) We're trying to complete an unescaped (literal) unit name part, + # i.e. foo\x2dba. That means we don't have to do the unescaping + # required for correct matching with systemctl's output, however, + # we need to escape the name for the final match, where the completion + # expects the string to be escaped. + cur_orig=$cur + if [[ $cur =~ '\\' ]]; then + cur="$(echo $cur | xargs echo)" + else + cur_orig="$(printf '%q' $cur)" + fi + + if [[ -z $verb ]]; then + comps="${VERBS[*]}" + + elif __contains_word "$verb" ${VERBS[ALL_UNITS]}; then + comps=$( __get_all_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[NONTEMPLATE_UNITS]}; then + comps=$( __get_non_template_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[ENABLED_UNITS]}; then + comps=$( __get_enabled_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[DISABLED_UNITS]}; then + comps=$( __get_disabled_units $mode "$cur"; + __get_template_names $mode "$cur") + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[REENABLABLE_UNITS]}; then + comps=$( __get_disabled_units $mode "$cur"; + __get_enabled_units $mode "$cur"; + __get_template_names $mode "$cur") + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[STARTABLE_UNITS]}; then + comps=$( __get_startable_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[RESTARTABLE_UNITS]}; then + comps=$( __get_restartable_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[STOPPABLE_UNITS]}; then + comps=$( __get_stoppable_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[RELOADABLE_UNITS]}; then + comps=$( __get_reloadable_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[ISOLATABLE_UNITS]}; then + comps=$( __filter_units_by_properties $mode AllowIsolate=yes \ + $( __get_non_template_units $mode "$cur" ) ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[FAILED_UNITS]}; then + comps=$( __get_failed_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[MASKED_UNITS]}; then + comps=$( __get_masked_units $mode "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[TARGET_AND_UNITS]}; then + if __contains_word "$prev" ${VERBS[TARGET_AND_UNITS]} \ + || __contains_word "$prev" ${OPTS[STANDALONE]}; then + comps=$( __systemctl $mode list-unit-files --type target --all "$cur*" \ + | { while read -r a b; do echo " $a"; done; } ) + else + comps=$( __get_all_unit_files $mode "$cur" ) + fi + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + + elif __contains_word "$verb" ${VERBS[JOBS]}; then + comps=$( __systemctl $mode list-jobs | { while read -r a b; do echo " $a"; done; } ) + + elif __contains_word "$verb" ${VERBS[ENVS]}; then + comps=$( __systemctl $mode show-environment \ + | while read -r line; do echo " ${line%%=*}="; done ) + compopt -o nospace + + elif __contains_word "$verb" ${VERBS[FILE]}; then + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + + elif __contains_word "$verb" ${VERBS[TARGETS]}; then + comps=$( __systemctl $mode list-unit-files --type target --full --all "$cur*" \ + | { while read -r a b; do echo " $a"; done; } ) + fi + + COMPREPLY=( $(compgen -o filenames -W '$comps' -- "$cur_orig") ) + return 0 +} + +complete -F _systemctl systemctl diff --git a/shell-completion/bash/systemd-analyze b/shell-completion/bash/systemd-analyze new file mode 100644 index 00000000..88688f72 --- /dev/null +++ b/shell-completion/bash/systemd-analyze @@ -0,0 +1,186 @@ +# systemd-analyze(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; +} + +__get_services() { + systemctl list-units --no-legend --no-pager -t service --all $1 | \ + { while read -r a b c; do [[ $b == "loaded" ]]; echo " $a"; done } +} + +__get_syscall_sets() { + local line + systemd-analyze syscall-filter --no-pager | while IFS= read -r line; do + if [[ $line == @* ]]; then + printf '%s\n' "$line" + fi + done +} + +_systemd_analyze() { + local i verb comps mode + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + + local -A OPTS=( + [STANDALONE]='-h --help --version --system --user --global --order --require --no-pager + --man=no --generators=yes' + [ARG]='-H --host -M --machine --fuzz --from-pattern --to-pattern --root' + ) + + local -A VERBS=( + [STANDALONE]='time blame plot dump unit-paths exit-status condition calendar timestamp timespan' + [CRITICAL_CHAIN]='critical-chain' + [DOT]='dot' + [LOG_LEVEL]='log-level' + [LOG_TARGET]='log-target' + [VERIFY]='verify' + [SECCOMP_FILTER]='syscall-filter' + [SERVICE_WATCHDOGS]='service-watchdogs' + [CAT_CONFIG]='cat-config' + [SECURITY]='security' + ) + + local CONFIGS='systemd/bootchart.conf systemd/coredump.conf systemd/journald.conf + systemd/journal-remote.conf systemd/journal-upload.conf systemd/logind.conf + systemd/resolved.conf systemd/networkd.conf systemd/resolved.conf + systemd/sleep.conf systemd/system.conf systemd/timedated.conf + systemd/timesyncd.conf systemd/user.conf udev/udev.conf' + + _init_completion || return + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ -z $verb && $cur = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user --global --no-pager' + fi + + elif __contains_word "$verb" ${VERBS[CRITICAL_CHAIN]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user --fuzz --no-pager' + fi + + elif __contains_word "$verb" ${VERBS[DOT]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user --global --from-pattern --to-pattern --order --require' + fi + + elif __contains_word "$verb" ${VERBS[LOG_LEVEL]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user' + else + comps='debug info notice warning err crit alert emerg' + fi + + elif __contains_word "$verb" ${VERBS[LOG_TARGET]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user' + else + comps='console journal kmsg journal-or-kmsg null' + fi + + elif __contains_word "$verb" ${VERBS[SECCOMP_FILTER]}; then + if [[ $cur = -* ]]; then + comps='--help --version --no-pager' + else + comps=$( __get_syscall_sets ) + fi + + elif __contains_word "$verb" ${VERBS[VERIFY]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user --global --man=no --generators=yes' + else + comps=$( compgen -A file -- "$cur" ) + compopt -o filenames + fi + + elif __contains_word "$verb" ${VERBS[SERVICE_WATCHDOGS]}; then + if [[ $cur = -* ]]; then + comps='--help --version --system --user' + else + comps='on off' + fi + + elif __contains_word "$verb" ${VERBS[CAT_CONFIG]}; then + if [[ $cur = -* ]]; then + comps='--help --version --root --no-pager' + elif [[ -z $cur ]]; then + comps="$CONFIGS" + compopt -o filenames + else + comps="$CONFIGS $( compgen -A file -- "$cur" )" + compopt -o filenames + fi + + elif __contains_word "$verb" ${VERBS[SECURITY]}; then + if [[ $cur = -* ]]; then + comps='--help --version --no-pager --system --user -H --host -M --machine' + else + if __contains_word "--user" ${COMP_WORDS[*]}; then + mode=--user + else + mode=--system + fi + comps=$( __get_services $mode ) + fi + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _systemd_analyze systemd-analyze diff --git a/shell-completion/bash/systemd-cat b/shell-completion/bash/systemd-cat new file mode 100644 index 00000000..62da65da --- /dev/null +++ b/shell-completion/bash/systemd-cat @@ -0,0 +1,57 @@ +# systemd-cat(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +_systemd_cat() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local i verb comps + + local -A OPTS=( + [STANDALONE]='-h --help --version' + [ARG]='-t --identifier -p --priority --level-prefix' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --identifier|-t) + comps='' + ;; + --priority|-p) + comps='emerg alert crit err warning notice info debug' + ;; + --level-prefix) + comps='yes no' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) +} + +complete -F _systemd_cat systemd-cat diff --git a/shell-completion/bash/systemd-cgls b/shell-completion/bash/systemd-cgls new file mode 100644 index 00000000..9a5969be --- /dev/null +++ b/shell-completion/bash/systemd-cgls @@ -0,0 +1,69 @@ +# systemd-cgls(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; +} + +__get_units_have_cgroup() { + systemctl $1 list-units | { + while read -r a b c d; do + [[ $c == "active" && ${a##*.} =~ (service|socket|mount|swap|slice|scope) ]] && echo " $a" + done + }; +} + +_systemd_cgls() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local i verb comps + + local -A OPTS=( + [STANDALONE]='-h --help --version --all -l --full -k --no-pager' + [ARG]='-M --machine -u --unit --user-unit' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --machine|-M) + comps=$( __get_machines ) + ;; + --unit|-u) + comps=$( __get_units_have_cgroup --system ) + ;; + --user-unit) + comps=$( __get_units_have_cgroup --user ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) +} + +complete -F _systemd_cgls systemd-cgls diff --git a/shell-completion/bash/systemd-cgtop b/shell-completion/bash/systemd-cgtop new file mode 100644 index 00000000..86898971 --- /dev/null +++ b/shell-completion/bash/systemd-cgtop @@ -0,0 +1,61 @@ +# systemd-cgtop(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; +} + +_systemd_cgtop() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local comps + + local -A OPTS=( + [STANDALONE]='-h --help --version -p -t -c -m -i -b --batch -r --raw -k -P' + [ARG]='--cpu --depth -M --machine --recursive -n --iterations -d --delay --order' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --machine|-M) + comps=$( __get_machines ) + ;; + --recursive) + comps='yes no' + ;; + --order) + comps='path tasks cpu memory io' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) +} + +complete -F _systemd_cgtop systemd-cgtop diff --git a/shell-completion/bash/systemd-delta b/shell-completion/bash/systemd-delta new file mode 100644 index 00000000..fcf27ba3 --- /dev/null +++ b/shell-completion/bash/systemd-delta @@ -0,0 +1,60 @@ +# systemd-delta(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +_systemd-delta() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local comps + + local -A OPTS=( + [STANDALONE]='--help -h --no-pager --version' + [ARG]='--diff --type -t' + ) + + _init_completion || return + + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --diff) + comps='yes no' + ;; + --type|-t) + comps='masked equivalent redirected overridden unchanged extended default' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _systemd-delta systemd-delta diff --git a/shell-completion/bash/systemd-detect-virt b/shell-completion/bash/systemd-detect-virt new file mode 100644 index 00000000..bea00fc7 --- /dev/null +++ b/shell-completion/bash/systemd-detect-virt @@ -0,0 +1,40 @@ +# systemd-detect-virt(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +_systemd_detect_virt() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local i verb comps + + local -A OPTS=( + [STANDALONE]='-h --help --version -c --container -v --vm -q --quiet + --private-users' + ) + + _init_completion || return + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) +} + +complete -F _systemd_detect_virt systemd-detect-virt diff --git a/shell-completion/bash/systemd-id128 b/shell-completion/bash/systemd-id128 new file mode 100644 index 00000000..f25848be --- /dev/null +++ b/shell-completion/bash/systemd-id128 @@ -0,0 +1,74 @@ +# networkctl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done + return 1 +} + +_systemd_id128() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help --version -p --pretty' + [ARG]='-a --app-specific' + ) + + local -A VERBS=( + [STANDALONE]='new machine-id boot-id invocation-id help' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --app-specific|-a) + comps="" + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]} && + ! __contains_word "${COMP_WORDS[i-1]}" ${OPTS[ARG]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[STANDALONE]}; then + comps='' + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _systemd_id128 systemd-id128 diff --git a/shell-completion/bash/systemd-nspawn b/shell-completion/bash/systemd-nspawn new file mode 100644 index 00000000..941ea909 --- /dev/null +++ b/shell-completion/bash/systemd-nspawn @@ -0,0 +1,194 @@ +# systemd-nspawn(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word() { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_users() { + local a b + loginctl list-users --no-legend --no-pager | { while read a b; do echo " $b"; done; }; +} + +__get_slices() { + local a b + systemctl list-units -t slice --no-legend --no-pager | { while read a b; do echo " $a"; done; }; +} + +__get_machines() { + local a b + machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; +} + +__get_env() { + local a + env | { while read a; do echo " ${a%%=*}"; done; }; +} + +__get_interfaces(){ + local name + for name in $(cd /sys/class/net && ls); do + [[ "$name" != "lo" ]] && echo "$name" + done +} + +__get_rlimit() { + local i + for i in $(systemd-nspawn --rlimit=help 2>/dev/null); do + echo " ${i}=" + done +} + +_systemd_nspawn() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local i verb comps + + local -A OPTS=( + [STANDALONE]='-h --help --version --private-network -b --boot --read-only -q --quiet --share-system + --keep-unit -n --network-veth -j -x --ephemeral -a --as-pid2 --private-users-chown -U' + [ARG]='-D --directory -u --user --uuid --capability --drop-capability --link-journal --bind --bind-ro + -M --machine -S --slice -E --setenv -Z --selinux-context -L --selinux-apifs-context + --register --network-interface --network-bridge --personality -i --image --tmpfs + --volatile --network-macvlan --kill-signal --template --notify-ready --root-hash --chdir + --pivot-root --property --private-users --network-namespace-path --network-ipvlan + --network-veth-extra --network-zone -p --port --system-call-filter --overlay --overlay-ro + --settings --rlimit --hostname --no-new-privileges --oom-score-adjust --cpu-affinity + --resolv-conf --timezone' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --directory|-D|--template) + compopt -o nospace + comps=$(compgen -S/ -A directory -- "$cur" ) + ;; + --user|-u) + comps=$( __get_users ) + ;; + --uuid|--root-hash) + comps='' + ;; + --capability) + comps='CAP_BLOCK_SUSPEND CAP_IPC_LOCK CAP_MAC_ADMIN CAP_MAC_OVERRIDE CAP_SYS_MODULE CAP_SYS_PACCT CAP_SYS_RAWIO + CAP_SYS_TIME CAP_SYSLOG CAP_WAKE_ALARM CAP_NET_ADMIN' + ;; + --drop-capability) + comps='CAP_AUDIT_CONTROL CAP_AUDIT_WRITE CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_FSETID + CAP_IPC_OWNER CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE CAP_MKNOD CAP_NET_ADMIN CAP_NET_BIND_SERVICE + CAP_NET_BROADCAST CAP_NET_RAW CAP_SETFCAP CAP_SETGID CAP_SETPCAP CAP_SETUID CAP_SYS_ADMIN CAP_SYS_BOOT + CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_PTRACE CAP_SYS_RESOURCE CAP_SYS_TTY_CONFIG' + ;; + --link-journal) + comps='no auto guest try-guest host try-host' + ;; + --bind|--bind-ro) + compopt -o nospace -o filenames + comps=$(compgen -f -- "$cur" ) + ;; + --tmpfs) + compopt -o nospace + comps=$(compgen -S/ -A directory -- "$cur" ) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + --slice|-S) + comps=$( __get_slices ) + ;; + --setenv|-E) + comps=$( __get_env ) + ;; + --selinux-context|-Z) + comps='' + ;; + --selinux-apifs-context|-L) + comps='' + ;; + --register) + comps='yes no' + ;; + --network-interface) + comps=$(__get_interfaces) + ;; + --network-bridge) + comps='' + ;; + --network-macvlan) + comps='' + ;; + --personality) + comps='x86 x86-64' + ;; + --volatile) + comps=$( systemd-nspawn --volatile=help 2>/dev/null ) + ;; + --image|-i) + compopt -o nospace + comps=$( compgen -A file -- "$cur" ) + ;; + --kill-signal) + _signals + return + ;; + --notify-ready) + comps='yes no' + ;; + --private-users) + comps='yes no pick' + ;; + --network-namespace-path) + comps=$( compgen -A file -- "$cur" ) + ;; + --settings) + comps='yes no override trusted' + ;; + --rlimit) + comps=$( __get_rlimit ) + ;; + --hostname) + comps='' + ;; + --no-new-privileges) + comps='yes no' + ;; + --oom-score-adjust) + comps='' + ;; + --cpu-affinity) + comps='' + ;; + --resolv-conf) + comps=$( systemd-nspawn --resolv-conf=help 2>/dev/null ) + ;; + --timezone) + comps=$( systemd-nspawn --timezone=help 2>/dev/null ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) +} + +complete -F _systemd_nspawn systemd-nspawn diff --git a/shell-completion/bash/systemd-path b/shell-completion/bash/systemd-path new file mode 100644 index 00000000..189fec09 --- /dev/null +++ b/shell-completion/bash/systemd-path @@ -0,0 +1,61 @@ +# systemd-path(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done + return 1 +} + +__get_names() { + systemd-path | { while IFS=: read -r a b; do echo " $a"; done; } +} + +_systemd_path() { + local comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help --version' + [ARG]='--suffix' + ) + + _init_completion || return + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --suffix) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + comps=$( __get_names ) + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _systemd_path systemd-path diff --git a/shell-completion/bash/systemd-resolve b/shell-completion/bash/systemd-resolve new file mode 100644 index 00000000..66f0ae04 --- /dev/null +++ b/shell-completion/bash/systemd-resolve @@ -0,0 +1,80 @@ +# systemd-resolve(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_interfaces(){ + local name + for name in $(cd /sys/class/net && ls); do + [[ "$name" != "lo" ]] && echo "$name" + done +} + +_systemd-resolve() { + local i comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [STANDALONE]='-h --help --version --no-pager -4 -6 + --service --openpgp --tlsa --status --statistics + --reset-statistics --service-address=no --service-txt=no + --cname=no --search=no --legend=no --flush-caches + --reset-server-features --revert' + [ARG]='-i --interface -p --protocol -t --type -c --class --raw + --set-dns --set-domain --set-llmnr --set-mdns --set-dnssec --set-nta' + ) + + if __contains_word "$prev" ${OPTS[ARG]}; then + case $prev in + --interface|-i) + comps=$( __get_interfaces ) + ;; + --protocol|-p|--type|-t|--class|-c) + comps=$( systemd-resolve --legend=no "$prev" help; echo help ) + ;; + --raw) + comps="payload packet" + ;; + --set-dns|--set-domain|--set-nta) + comps="" + ;; + --set-llmnr|--set-mdns) + comps="yes no resolve" + ;; + --set-dnssec) + comps="yes no allow-downgrade" + ;; + --set-dnsovertls) + comps="yes no opportunistic" + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi +} + +complete -F _systemd-resolve systemd-resolve diff --git a/shell-completion/bash/systemd-run b/shell-completion/bash/systemd-run new file mode 100644 index 00000000..707b038d --- /dev/null +++ b/shell-completion/bash/systemd-run @@ -0,0 +1,130 @@ +# systemd-run(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__systemctl() { + local mode=$1; shift 1 + systemctl $mode --full --no-legend "$@" +} + +__get_slice_units () { __systemctl $1 list-units --all -t slice \ + | { while read -r a b c d; do echo " $a"; done; }; } + +__get_machines() { + local a b + machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; +} + +_systemd_run() { + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local OPTS='-h --help --version --user --system --scope --unit --description --slice + -r --remain-after-exit --send-sighup -H --host -M --machine --service-type + --on-active --on-boot --on-startup --on-unit-active --on-unit-inactive + --on-calendar --timer-property --path-property --socket-property -t --pty + -q --quiet --no-block --uid --gid --nice -E --setenv -p --property + --no-ask-password --wait -P --pipe -G --collect --working-directory + -d --same-dir -S --shell' + + local mode=--system + local i + local opts_with_values=( + --unit --description --slice --service-type -H --host -M --machine -p --property --on-active + --on-boot --on-startup --on-unit-active --on-unit-inactive --on-calendar --timer-property + --path-property --socket-property --uid --gid --nice -E --setenv --working-directory + ) + for (( i=1; i <= COMP_CWORD; i++ )); do + if [[ ${COMP_WORDS[i]} != -* ]]; then + local root_command=${COMP_WORDS[i]} + _command_offset $i + return + fi + + [[ ${COMP_WORDS[i]} == "--user" ]] && mode=--user + + [[ $i -lt $COMP_CWORD && " ${opts_with_values[@]} " =~ " ${COMP_WORDS[i]} " ]] && ((i++)) + done + + case "$prev" in + --unit|--description|--on-active|--on-boot|--on-startup|--on-unit-active|--on-unit-inactive|--on-calendar) + # argument required but no completions available + return + ;; + --slice) + local comps=$(__get_slice_units $mode) + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + --service-type) + local comps='simple forking oneshot dbus notify idle' + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + -p|--property) + local comps='CPUAccounting= MemoryAccounting= BlockIOAccounting= SendSIGHUP= + SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group= + DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth= + BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment= + KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA= + LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC= + LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE= + LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices= + PrivateNetwork= NoNewPrivileges= WorkingDirectory= RootDirectory= + TTYPath= SyslogIdentifier= SyslogLevelPrefix= SyslogLevel= + SyslogFacility= TimerSlackNSec= OOMScoreAdjust= ReadWritePaths= + ReadOnlyPaths= InaccessiblePaths= EnvironmentFile= + ProtectSystem= ProtectHome= RuntimeDirectory= PassEnvironment=' + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + -H|--host) + local comps=$(compgen -A hostname) + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + -M|--machine) + local comps=$( __get_machines ) + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + --timer-property) + local comps='AccuracySec= WakeSystem=' + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + ;; + --working-directory) + local comps + if [[ -z $cur ]]; then + comps=$(compgen -A directory -- "/" ) + else + comps=$(compgen -A directory -- "$cur" ) + fi + compopt -o filenames + COMPREPLY=( $(compgen -W '$comps' -- "$cur" ) ) + return 0 + ;; + esac + + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 +} + +complete -F _systemd_run systemd-run diff --git a/shell-completion/bash/timedatectl b/shell-completion/bash/timedatectl new file mode 100644 index 00000000..385dee7d --- /dev/null +++ b/shell-completion/bash/timedatectl @@ -0,0 +1,95 @@ +# timedatectl(1) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_machines() { + local a b + machinectl list --no-legend --no-pager | { while read a b; do echo " $a"; done; }; +} + +__get_interfaces(){ + local name + for name in $(cd /sys/class/net && ls); do + [[ "$name" != "lo" ]] && echo "$name" + done +} +_timedatectl() { + local i verb comps + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local OPTS='-h --help --version --adjust-system-clock --no-pager + --no-ask-password -H --host -M --machine --monitor + -p --property -a --all --value' + + if __contains_word "$prev" $OPTS; then + case $prev in + --host|-H) + comps=$(compgen -A hostname) + ;; + --machine|-M) + comps=$( __get_machines ) + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") ) + return 0 + fi + + local -A VERBS=( + [BOOLEAN]='set-local-rtc set-ntp' + [STANDALONE]='status show list-timezones timesync-status show-timesync' + [TIMEZONES]='set-timezone' + [TIME]='set-time' + [IFNAME]='ntp-servers revert' + ) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" ${VERBS[*]}; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $verb ]]; then + comps=${VERBS[*]} + elif __contains_word "$verb" ${VERBS[BOOLEAN]}; then + comps='true false' + elif __contains_word "$verb" ${VERBS[TIMEZONES]}; then + comps=$(command timedatectl list-timezones) + elif __contains_word "$verb" ${VERBS[STANDALONE]} ${VERBS[TIME]}; then + comps='' + elif __contains_word "$verb" ${VERBS[TIMEZONES]}; then + comps=$( __get_interfaces ) + fi + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _timedatectl timedatectl diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm new file mode 100644 index 00000000..cb12c255 --- /dev/null +++ b/shell-completion/bash/udevadm @@ -0,0 +1,244 @@ +# udevadm(8) completion -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# Copyright © 2010 Ran Benita +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +__contains_word () { + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done +} + +__get_all_sysdevs() { + local -a devs=(/sys/bus/*/devices/*/ /sys/class/*/*/) + printf '%s\n' "${devs[@]%/}" +} + +__get_all_devs() { + local i + for i in /dev/* /dev/*/*; do + echo $i + done +} + +__get_all_device_units() { + systemctl list-units -t device --full --no-legend --no-pager 2>/dev/null | \ + { while read -r a b; do echo "$a"; done; } +} + +_udevadm() { + local i verb comps builtin + local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} + local -A OPTS=( + [COMMON]='-h --help -V --version' + [DEBUG]='-d --debug' + [INFO_STANDALONE]='-r --root -a --attribute-walk -x --export -e --export-db -c --cleanup-db + -w --wait-for-initialization' + [INFO_ARG]='-q --query -p --path -n --name -P --export-prefix -d --device-id-of-file' + [TRIGGER_STANDALONE]='-v --verbose -n --dry-run -w --settle --wait-daemon' + [TRIGGER_ARG]='-t --type -c --action -s --subsystem-match -S --subsystem-nomatch + -a --attr-match -A --attr-nomatch -p --property-match + -g --tag-match -y --sysname-match --name-match -b --parent-match' + [SETTLE]='-t --timeout -E --exit-if-exists' + [CONTROL_STANDALONE]='-e --exit -s --stop-exec-queue -S --start-exec-queue -R --reload --ping' + [CONTROL_ARG]='-l --log-priority -p --property -m --children-max -t --timeout' + [MONITOR_STANDALONE]='-k --kernel -u --udev -p --property' + [MONITOR_ARG]='-s --subsystem-match -t --tag-match' + [TEST]='-a --action -N --resolve-names' + ) + + local verbs=(info trigger settle control monitor test-builtin test) + local builtins=(blkid btrfs hwdb input_id keyboard kmod net_id net_setup_link path_id usb_id uaccess) + + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" "${verbs[@]}"; then + verb=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $verb ]]; then + if [[ "$cur" = -* ]]; then + COMPREPLY=( $(compgen -W '${OPTS[COMMON]} ${OPTS[DEBUG]}' -- "$cur") ) + else + COMPREPLY=( $(compgen -W '${verbs[*]}' -- "$cur") ) + fi + return 0 + fi + + case $verb in + 'info') + if __contains_word "$prev" ${OPTS[INFO_ARG]}; then + case $prev in + -q|--query) + comps='name symlink path property all' + ;; + -p|--path) + comps=$( __get_all_sysdevs ) + local IFS=$'\n' + ;; + -n|--name) + comps=$( __get_all_devs ) + ;; + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + comps="${OPTS[COMMON]} ${OPTS[INFO_STANDALONE]} ${OPTS[INFO_ARG]}" + else + comps=$( __get_all_sysdevs; __get_all_device_units ) + local IFS=$'\n' + fi + ;; + + 'trigger') + if __contains_word "$prev" ${OPTS[TRIGGER_ARG]}; then + case $prev in + -t|--type) + comps='devices subsystems' + ;; + -c|--action) + comps=$( udevadm trigger --action help ) + ;; + -y|--sysname-match|-b|--parent-match) + comps=$( __get_all_sysdevs ) + local IFS=$'\n' + ;; + --name-match) + comps=$( __get_all_devs ) + ;; + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + comps="${OPTS[COMMON]} ${OPTS[TRIGGER_STANDALONE]} ${OPTS[TRIGGER_ARG]}" + else + comps=$( __get_all_sysdevs; __get_all_device_units ) + local IFS=$'\n' + fi + ;; + + 'settle') + if __contains_word "$prev" ${OPTS[SETTLE]}; then + case $prev in + -E|--exit-if-exists) + comps=$( compgen -A file -- "$cur" ) + ;; + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + comps="${OPTS[COMMON]} ${OPTS[SETTLE]}" + ;; + + 'control') + if __contains_word "$prev" ${OPTS[CONTROL_ARG]}; then + case $prev in + -l|--log-priority) + comps='alert crit debug emerg err info notice warning' + ;; + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + comps="${OPTS[COMMON]} ${OPTS[CONTROL_STANDALONE]} ${OPTS[CONTROL_ARG]}" + ;; + + 'monitor') + if __contains_word "$prev" ${OPTS[MONITOR_ARG]}; then + case $prev in + *) + comps='' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + comps="${OPTS[COMMON]} ${OPTS[MONITOR_STANDALONE]} ${OPTS[MONITOR_ARG]}" + ;; + + 'test') + if __contains_word "$prev" ${OPTS[TEST]}; then + case $prev in + -a|--action) + comps=$( udevadm test --action help ) + ;; + -N|--resolve-names) + comps='early late never' + ;; + esac + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 + fi + + if [[ $cur = -* ]]; then + comps="${OPTS[COMMON]} ${OPTS[TEST]}" + else + comps=$( __get_all_sysdevs ) + local IFS=$'\n' + fi + ;; + + 'test-builtin') + for ((i=0; i < COMP_CWORD; i++)); do + if __contains_word "${COMP_WORDS[i]}" "${builtins[@]}"; then + builtin=${COMP_WORDS[i]} + break + fi + done + + if [[ -z $builtin ]]; then + comps="${builtins[@]}" + elif [[ $cur = -* ]]; then + comps="${OPTS[COMMON]}" + else + comps=$( __get_all_sysdevs ) + local IFS=$'\n' + fi + ;; + + *) + comps=${VERBS[*]} + ;; + esac + + COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) + return 0 +} + +complete -F _udevadm udevadm diff --git a/shell-completion/zsh/_bootctl b/shell-completion/zsh/_bootctl new file mode 100644 index 00000000..a84601ae --- /dev/null +++ b/shell-completion/zsh/_bootctl @@ -0,0 +1,62 @@ +#compdef bootctl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +__bootctl() { + bootctl --no-pager $@ 2>/dev/null +} + +_bootctl_comp_ids() { + local expl + local -a ids + __bootctl list | while read a b; do + if [[ "$a" == "id:" ]]; then + ids+="$b" + fi + done + _wanted id expl 'boot id' compadd "$@" -a ids +} + +_bootctl_set-default() { + _bootctl_comp_ids +} + +_bootctl_set-oneshot() { + _bootctl_comp_ids +} + +(( $+functions[_bootctl_commands] )) || _bootctl_commands() +{ + local -a _bootctl_cmds + _bootctl_cmds=( + "status:Show status of installed systemd-boot and EFI variables" + "install:Install systemd-boot to the ESP and EFI variables" + "update:Update systemd-boot in the ESP and EFI variables" + "remove:Remove systemd-boot from the ESP and EFI variables" + "random-seed:Initialize random seed in ESP and EFI variables" + "is-installed:Test whether systemd-boot is installed in the ESP" + "set-default:Set the default boot loader entry" + "set-oneshot:Set the default boot loader entry only for the next boot" + ) + if (( CURRENT == 1 )); then + _describe -t commands 'bootctl command' _bootctl_cmds || compadd "$@" + else + local curcontext="$curcontext" + cmd="${${_bootctl_cmds[(r)$words[1]:*]%%:*}}" + if (( $+functions[_bootctl_$cmd] )); then + _bootctl_$cmd + else + _message "no more options" + fi + fi +} + +_arguments \ + {-h,--help}'[Prints a short help text and exits.]' \ + '--version[Prints a short version string and exits.]' \ + '--esp-path=[Path to the EFI System Partition (ESP)]:path:_directories' \ + '--boot-path=[Path to the $BOOT partition]:path:_directories' \ + {-p,--print-esp-path}'[Print path to the EFI system partition]' \ + {-x,--print-boot-path}'[Print path to the $BOOT partition]' \ + '--no-variables[Do not touch EFI variables]' \ + '--no-pager[Do not pipe output into a pager]' \ + '*::bootctl command:_bootctl_commands' diff --git a/shell-completion/zsh/_busctl b/shell-completion/zsh/_busctl new file mode 100644 index 00000000..0589e993 --- /dev/null +++ b/shell-completion/zsh/_busctl @@ -0,0 +1,286 @@ +#compdef busctl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +# busctl(1) completion -*- shell-script -*- +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +(( $+functions[_busctl_commands] )) || _busctl_commands() +{ + local -a _busctl_cmds + _busctl_cmds=( + "list:List bus names" + "status:Show bus service, process or bus owner credentials" + "monitor:Show bus traffic" + "capture:Capture bus traffix as pcap" + "tree:Show object tree of service" + "introspect:Introspect object" + "call:Call a method" + "get-property:Get property value" + "set-property:Set property value" + ) + if (( CURRENT == 1 )); then + _describe -t commands 'busctl command' _busctl_cmds || compadd "$@" + else + local curcontext="$curcontext" + cmd="${${_busctl_cmds[(r)$words[1]:*]%%:*}}" + curcontext="${curcontext%:*:*}:busctl-${cmd}:" + if (( $+functions[_busctl_$cmd] )); then + _busctl_$cmd + else + _message "no more options" + fi + fi +} + +__busctl() { + busctl $_bus_address --no-pager --no-legend "$@" 2>/dev/null +} + +__dbus_matchspec() { + # https://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-routing + _values -s, 'rules' \ + 'type[Match on message type]:type:(signal method_call method_return error)' \ + 'eavesdrop[Include unicast messages]:bool:(true false)' \ + 'sender[Match messages sent by a particular sender]:sender:{compadd $(_busctl_get_service_names)}'\ + 'interface[Match messages sent over or to a particular interface]:interface' \ + 'member[Match messages which have the given method or signal name]:member' \ + 'path[Match messages which are sent from or to the given object]:path' \ + 'path_namespace[Match messages which are sent from or to the given namespace]:namespace' \ + 'destination[Match messaged sent to the given unique name]:unique name:{compadd $(_busctl_get_unique_names)}' +} + +(( $+functions[_busctl_get_json] )) || _busctl_get_json() +{ + local -a _json_forms + _json_forms=( $(__busctl --json=help; echo help) ) + _values 'format' $_json_forms +} + +(( $+functions[_busctl_get_service_names] )) || _busctl_get_service_names() +{ + local -a bus_names + bus_names=( $(__busctl call \ + "org.freedesktop.DBus" \ + "/org/freedesktop/DBus" \ + "org.freedesktop.DBus" \ + ListNames) ) + echo ${(Q)bus_names[3,-1]} +} + +(( $+functions[_busctl_get_unique_names] )) || _busctl_get_unique_names() +{ + local -a bus_names + local NAME OTHER + __busctl --unique list | + while read NAME OTHER; do + echo $NAME + done +} + +(( $+functions[_busctl_get_objects] )) || _busctl_get_objects() +{ + local -a objects + local name="$1" + objects=($(__busctl --list tree $name )) + echo $objects +} + +(( $+functions[_busctl_get_interfaces] )) || _busctl_get_interfaces() +{ + local NAME TYPE OTHER + __busctl introspect "$1" "$2" | + while read NAME TYPE OTHER; do + if [[ ${TYPE} == "interface" ]]; then + echo ${NAME} + fi + done +} + +(( $+functions[_busctl_get_members] )) || _busctl_get_members() +{ + local member="$4" + local required="$5" + local NAME TYPE SIGNATURE VALUE FLAGS + __busctl introspect "$1" "$2" "$3" | + while read NAME TYPE SIGNATURE VALUE FLAGS; do + [[ -z "$member" || ${TYPE} == "$member" ]] && + [[ -z "$required" || ${${(s: :)FLAGS}[-1]} == "$required" ]] && + echo ${NAME#.} + done +} + +(( $+functions[_busctl_get_signature] )) || _busctl_get_signature() +{ + local NAME TYPE SIGNATURE VALUE FLAGS + __busctl introspect "$1" "$2" "$3" | + while read NAME TYPE SIGNATURE VALUE FLAGS; do + if [[ ${NAME#.} == "$4" ]]; then + [[ ${SIGNATURE} != "-" ]] && echo ${SIGNATURE} + fi + done +} + +(( $+functions[_busctl_status] )) || _busctl_status() +{ + local expl + _wanted busname expl 'busname' compadd "$@" - $(_busctl_get_service_names) +} + +(( $+functions[_busctl_monitor] )) || _busctl_monitor() +{ + local expl + _wanted busname expl 'busname' compadd "$@" - $(_busctl_get_service_names) +} + +(( $+functions[_busctl_tree] )) || _busctl_tree() +{ + local expl + _wanted busname expl 'busname' compadd "$@" - $(_busctl_get_service_names) +} + +(( $+functions[_busctl_introspect] )) || _busctl_introspect() +{ + local expl + case $CURRENT in + 2) + _wanted busname expl 'busname' \ + compadd "$@" - $(_busctl_get_service_names) + ;; + 3) + _wanted path expl 'path' \ + compadd "$@" - $(_busctl_get_objects $words[2]) + ;; + 4) + _wanted interface expl 'interface' \ + compadd "$@" - $(_busctl_get_interfaces $words[2,3]) + ;; + *) + _message "no more options" + esac +} + +(( $+functions[_busctl_call] )) || _busctl_call() +{ + local expl + case $CURRENT in + 2) + _wanted busname expl 'busname' \ + compadd "$@" - $(_busctl_get_service_names) + ;; + 3) + _wanted path expl 'path' \ + compadd "$@" - $(_busctl_get_objects $words[2]) + ;; + 4) + _wanted interface expl 'interface' \ + compadd "$@" - $(_busctl_get_interfaces $words[2,3]) + ;; + 5) + _wanted method expl 'method' \ + compadd "$@" - $(_busctl_get_members $words[2,4] "method") + ;; + 6) + compadd "$@" - $(_busctl_get_signature $words[2,5]) + ;; + *) + _message "no more options" + esac +} + +(( $+functions[_busctl_get-property] )) || _busctl_get-property() +{ + local expl + case $CURRENT in + 2) + _wanted busname expl 'busname' \ + compadd "$@" - $(_busctl_get_service_names) + ;; + 3) + _wanted path expl 'path' \ + compadd "$@" - $(_busctl_get_objects $words[2]) + ;; + 4) + _wanted interface expl 'interface' \ + compadd "$@" - $(_busctl_get_interfaces $words[2,3]) + ;; + 5) + _wanted property expl 'property' \ + compadd "$@" - $(_busctl_get_members $words[2,4] "property") + ;; + *) + _message "no more options" + esac +} + +(( $+functions[_busctl_set-property] )) || _busctl_set-property() +{ + local expl + case $CURRENT in + 2) + _wanted busname expl 'busname' \ + compadd "$@" - $(_busctl_get_service_names) + ;; + 3) + _wanted path expl 'path' \ + compadd "$@" - $(_busctl_get_objects $words[2]) + ;; + 4) + _wanted interface expl 'interface' \ + compadd "$@" - $(_busctl_get_interfaces $words[2,3]) + ;; + 5) + _wanted property expl 'property' \ + compadd "$@" - $(_busctl_get_members $words[2,4] "property" "writable") + ;; + 6) + compadd "$@" - $(_busctl_get_signature $words[2,5]) + ;; + *) + _message "no more options" + esac +} + +local -a _modes; _modes=("--user" "--system") +# Use the last mode (they are exclusive and the last one is used). +local _bus_address=${${words:*_modes}[(R)(${(j.|.)_modes})]} +local curcontext=$curcontext state line +_arguments \ + {-h,--help}'[Prints a short help text and exits.]' \ + '--version[Prints a short version string and exits.]' \ + '--no-pager[Do not pipe output into a pager]' \ + '--no-legend[Do not show the headers and footers]' \ + '--system[Connect to system manager]' \ + '--user[Connect to user service manager]' \ + {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ + {-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ + '--address=[Connect to the bus specified by address]:address' \ + '--show-machine[Show machine ID column in list]' \ + '--unique[Only show unique names]' \ + '--acquired[Only show acquired names]' \ + '--activatable[Only show activatable names]' \ + '--match=[Only show matching messages]:match:__dbus_matchspec' \ + '--list[Do not show tree, but simple object path list]' \ + {-q,--quiet}'[Do not show method call reply]'\ + '--verbose[Show result values in long format]' \ + '--json=[Show result values in long format]:format:_busctl_get_json' \ + '-j[Show pretty json in interactive sessions, short json otherwise]' \ + '--expect-reply=[Expect a method call reply]:boolean:(1 0)' \ + '--auto-start=[Auto-start destination service]:boolean:(1 0)' \ + '--allow-interactive-authorization=[Allow interactive authorization for operation]:boolean:(1 0)' \ + '--timeout=[Maximum time to wait for method call completion]:timeout (seconds)' \ + '--augment-creds=[Extend credential data with data read from /proc/$PID]:boolean:(1 0)' \ + '*::busctl command:_busctl_commands' diff --git a/shell-completion/zsh/_coredumpctl b/shell-completion/zsh/_coredumpctl new file mode 100644 index 00000000..6b7d14a7 --- /dev/null +++ b/shell-completion/zsh/_coredumpctl @@ -0,0 +1,46 @@ +#compdef coredumpctl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_coredumpctl_commands] )) || +_coredumpctl_commands(){ + local -a _coredumpctl_cmds + _coredumpctl_cmds=( + 'list:List available coredumps' + 'info:Show detailed information about one or more coredumps' + 'dump:Print coredump to stdout' + 'debug:Start debugger (gdb) on a coredump' + ) + if (( CURRENT == 1 )); then + _describe -t commands 'coredumpctl command' _coredumpctl_cmds + else + local curcontext="$curcontext" + local -a _dumps + cmd="${${_coredumpctl_cmds[(r)$words[1]:*]%%:*}}" + if (( $#cmd )); then + _dumps=( "${(f)$(coredumpctl list -q --no-legend | awk 'BEGIN{OFS=":"} {sub(/[[ \t]+/, ""); print $4,$0}' 2>/dev/null)}" ) + if [[ -n "$_dumps" ]]; then + _describe -V -t pids 'coredumps' _dumps + else + _message "no coredumps" + fi + else + _message "no more options" + fi + fi +} + +_arguments \ + {-o+,--output=}'[Write output to FILE]:output file:_files' \ + {-F+,--field=}'[Show field in list output]:field' \ + '-1[Show information about most recent entry only]' \ + {-S,--since}'[Print entries since the specified date]' \ + {-U,--until}'[Print entries until the specified date]' \ + {-r,--reverse}'[Show the newest entries first]' \ + '--no-pager[Do not pipe output into a pager]' \ + '--no-legend[Do not print the column headers]' \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + '--debugger=[Use the given debugger]:debugger: _command_names -e' \ + {-D,--directory=}'[Use the journal files in the specified dir]:directory: _directories' \ + {-q,--quiet}'[Do not show info messages and privilege warning]' \ + '*::coredumpctl commands:_coredumpctl_commands' diff --git a/shell-completion/zsh/_hostnamectl b/shell-completion/zsh/_hostnamectl new file mode 100644 index 00000000..d1ad85a1 --- /dev/null +++ b/shell-completion/zsh/_hostnamectl @@ -0,0 +1,87 @@ +#compdef hostnamectl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_hostnamectl_set-hostname] )) || +_hostnamectl_set-hostname() { + if (( CURRENT <= 3 )); then + _message "new hostname" + else + _message "no more options" + fi +} + +(( $+functions[_hostnamectl_set-icon-name] )) || +_hostnamectl_set-icon-name() { + if (( CURRENT <= 3 )); then + _message "new icon name" + else + _message "no more options" + fi +} + +(( $+functions[_hostnamectl_set-chassis] )) || +_hostnamectl_set-chassis() { + if (( CURRENT <= 3 )); then + _chassis=( desktop laptop convertible server tablet handset watch embedded vm container ) + _describe chassis _chassis + else + _message "no more options" + fi +} + +(( $+functions[_hostnamectl_set-deployment] )) || +_hostnamectl_set-deployment() { + if (( CURRENT <= 3 )); then + _message "new environment" + else + _message "no more options" + fi +} + +(( $+functions[_hostnamectl_set-location] )) || +_hostnamectl_set-location() { + if (( CURRENT <= 3 )); then + _message "new location" + else + _message "no more options" + fi +} + +(( $+functions[_hostnamectl_commands] )) || +_hostnamectl_commands() { + local -a _hostnamectl_cmds + _hostnamectl_cmds=( + "status:Show current hostname settings" + "set-hostname:Set system hostname" + "set-icon-name:Set icon name for host" + "set-chassis:Set chassis type for host" + "set-deployment:Set deployment environment for host" + "set-location:Set location for host" + ) + if (( CURRENT == 1 )); then + _describe -t commands 'hostnamectl commands' _hostnamectl_cmds || compadd "$@" + else + local curcontext="$curcontext" + cmd="${${_hostnamectl_cmds[(r)$words[1]:*]%%:*}}" + if (( $#cmd )); then + if [[ $cmd == status ]]; then + _message "no options" + else + _hostnamectl_$cmd + fi + else + _message "unknown hostnamectl command: $words[1]" + fi + fi +} + +_arguments -s \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + '--transient[Only set transient hostname]' \ + '--static[Only set static hostname]' \ + '--pretty[Only set pretty hostname]' \ + '--no-ask-password[Do not prompt for password]' \ + {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ + {-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ + '*::hostnamectl commands:_hostnamectl_commands' diff --git a/shell-completion/zsh/_journalctl b/shell-completion/zsh/_journalctl new file mode 100644 index 00000000..43bec9b1 --- /dev/null +++ b/shell-completion/zsh/_journalctl @@ -0,0 +1,136 @@ +#compdef journalctl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_journalctl_fields] )) || +_journalctl_fields() { + local -a journal_fields + journal_fields=(MESSAGE{,_ID} PRIORITY CODE_{FILE,LINE,FUNC} + ERRNO SYSLOG_{FACILITY,IDENTIFIER,PID} + _{P,U,G}ID _COMM _EXE _CMDLINE + _AUDIT_{SESSION,LOGINUID} + _SYSTEMD_{CGROUP,SESSION,UNIT,OWNER_UID} + _SYSTEMD_USER_UNIT USER_UNIT + _SELINUX_CONTEXT _SOURCE_REALTIME_TIMESTAMP + _{BOOT,MACHINE}_ID _HOSTNAME _TRANSPORT + _KERNEL_{DEVICE,SUBSYSTEM} + _UDEV_{SYSNAME,DEVNODE,DEVLINK} + __CURSOR __{REALTIME,MONOTONIC}_TIMESTAMP) + case $_jrnl_none in + yes) _values -s '=' 'possible fields' \ + "${journal_fields[@]}:value:_journalctl_field_values ${words[CURRENT]%%=*}" ;; + *) _describe 'possible fields' journal_fields ;; + esac +} + +(( $+functions[_journalctl_none] )) || +_journalctl_none() { + local -a _commands _files _jrnl_none + # Setting use-cache will slow this down considerably + _commands=( ${"$(_call_program commands "$service $_sys_service_mgr -F _EXE" 2>/dev/null)"} ) + _jrnl_none='yes' + _alternative : \ + 'files:/dev files:_files -W /dev -P /dev/' \ + "commands:commands:($_commands[@])" \ + 'fields:fields:_journalctl_fields' +} + +(( $+functions[_journalctl_field_values] )) || +_journalctl_field_values() { + local -a _fields cmd + cmd=("journalctl $_sys_service_mgr" "-F ${@[-1]}" "2>/dev/null" ) + _fields=$(_call_program fields $cmd[@]) + _fields=${_fields//'\'/'\\'} + _fields=${_fields//':'/'\:'} + _fields=( ${(f)_fields} ) + typeset -U _fields + _describe 'possible values' _fields +} + +(( $+functions[_journalctl_boots] )) || +_journalctl_boots() { + local -a _bootid _previousboots + _bootid=( ${(f)"$(_call_program bootid "$service -F _BOOT_ID")"} ) + _previousboots=( -{1..${#_bootid}} ) + _alternative : \ + "offsets:boot offsets:compadd -a '_previousboots[1,-2]'" \ + "bootid:boot ids:compadd -a _bootid" +} + +# Build arguments for "journalctl" to be used in completion. +# Use both --user and --system modes, they are not exclusive. +local -a _modes; _modes=(--user --system) +local -a _modes_with_arg; _modes_with_arg=(--directory -D --file -M --machine --root) +typeset -a _sys_service_mgr +local w k v i=0 n=$#words +while (( i++ < n )); do + w=$words[$i] + if (( $_modes[(I)$w] )); then + _sys_service_mgr+=($w) + else + # Handle options with arguments. "--key=value" and "--key value". + k=${w%%=*} + if (( ${_modes_with_arg[(I)$k]} )); then + v=${w#*=} + if [[ "$k" != "$w" ]]; then + # "--key=value" style. + _sys_service_mgr+=($w) + else + # "--key value" style. + _sys_service_mgr+=($w ${words[((++i))]}) + fi + fi + fi +done +_arguments -s \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + '--no-pager[Do not pipe output into a pager]' \ + --no-hostname"[Don't show the hostname of local log messages]" \ + {-l,--full}'[Show long fields in full]' \ + {-a,--all}'[Show all fields, including long and unprintable]' \ + {-f,--follow}'[Follow journal]' \ + {-e,--pager-end}'[Jump to the end of the journal in the pager]' \ + {-n+,--lines=}'[Number of journal entries to show]:integer' \ + '--no-tail[Show all lines, even in follow mode]' \ + {-r,--reverse}'[Reverse output]' \ + {-o+,--output=}'[Change journal output mode]:output modes:_sd_outputmodes' \ + {-x,--catalog}'[Show explanatory texts with each log line]' \ + {-q,--quiet}"[Don't show privilege warning]" \ + {-m,--merge}'[Show entries from all available journals]' \ + {-b+,--boot=}'[Show data only from the specified boot or offset]::boot id or offset:_journalctl_boots' \ + '--list-boots[List boots ordered by time]' \ + {-k,--dmesg}'[Show only kernel messages from the current boot]' \ + {-u+,--unit=}'[Show data only from the specified unit]:units:_journalctl_field_values _SYSTEMD_UNIT' \ + '--user-unit=[Show data only from the specified user session unit]:units:_journalctl_field_values USER_UNIT' \ + {-p+,--priority=}'[Show only messages within the specified priority range]:priority:_journalctl_field_values PRIORITY' \ + {-t+,--identifier=}'[Show only messages with the specified syslog identifier]:identifier:_journalctl_field_values SYSLOG_IDENTIFIER' \ + {-c+,--cursor=}'[Start showing entries from the specified cursor]:cursors:_journalctl_field_values __CURSORS' \ + '--cursor-file=[Show entries using cursor store in file]:file:_files' \ + '--after-cursor=[Start showing entries from after the specified cursor]:cursors:_journalctl_field_values __CURSORS' \ + '--since=[Start showing entries on or newer than the specified date]:YYYY-MM-DD HH\:MM\:SS' \ + '--until=[Stop showing entries on or older than the specified date]:YYYY-MM-DD HH\:MM\:SS' \ + {-F,--field=}'[List all values a certain field takes]:Fields:_journalctl_fields' \ + '--system[Show system and kernel messages]' \ + '--user[Show messages from user services]' \ + '(--directory -D -M --machine --root --file)'{-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ + '(--directory -D -M --machine --root --file)'{-D+,--directory=}'[Show journal files from directory]:directories:_directories' \ + '(--directory -D -M --machine --root --file)--root=[Operate on catalog hierarchy under specified directory]:directories:_directories' \ + '(--directory -D -M --machine --root)*--file=[Operate on specified journal files]:file:_files' \ + '--disk-usage[Show total disk usage]' \ + '--dump-catalog[Dump messages in catalog]' \ + '--flush[Flush all journal data from /run into /var]' \ + '--force[Force recreation of the FSS keys]' \ + '--header[Show journal header information]' \ + '--interval=[Time interval for changing the FSS sealing key]:time interval' \ + '--list-catalog[List messages in catalog]' \ + '--new-id128[Generate a new 128 Bit ID]' \ + '--rotate[Request immediate rotation of the journal files]' \ + '--setup-keys[Generate a new FSS key pair]' \ + '--sync[Synchronize unwritten journal messages to disk]' \ + '--update-catalog[Update binary catalog database]' \ + '--vacuum-files=[Leave only the specified number of journal files]:integer' \ + '--vacuum-size=[Reduce disk usage below specified size]:bytes' \ + '--vacuum-time=[Remove journal files older than specified time]:time' \ + '--verify-key=[Specify FSS verification key]:FSS key' \ + '--verify[Verify journal file consistency]' \ + '*::default: _journalctl_none' diff --git a/shell-completion/zsh/_kernel-install b/shell-completion/zsh/_kernel-install new file mode 100644 index 00000000..4b5dd89d --- /dev/null +++ b/shell-completion/zsh/_kernel-install @@ -0,0 +1,27 @@ +#compdef kernel-install -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_kernel-install_images] )) || +_kernel-install_images(){ + if [[ "$words[2]" == "remove" ]]; then + _message 'No more options' + else + _path_files -W /boot/ -P /boot/ -g "vmlinuz-*" + fi +} + +(( $+functions[_kernel-install_kernels] )) || +_kernel-install_kernels(){ + read _MACHINE_ID < /etc/machine-id + _kernel=( /lib/modules/[0-9]* ) + if [[ "$cmd" == "remove" && -n "$_MACHINE_ID" ]]; then + _kernel=( "/boot/$_MACHINE_ID"/[0-9]* ) + fi + _kernel=( ${_kernel##*/} ) + _describe "installed kernels" _kernel +} + +_arguments \ + '1::add or remove:(add remove)' \ + '2::kernel versions:_kernel-install_kernels' \ + '3::kernel images:_kernel-install_images' diff --git a/shell-completion/zsh/_localectl b/shell-completion/zsh/_localectl new file mode 100644 index 00000000..a712473c --- /dev/null +++ b/shell-completion/zsh/_localectl @@ -0,0 +1,98 @@ +#compdef localectl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_localectl_set-locale] )) || +_localectl_set-locale() { + local -a _locales locale_fields + locale_fields=(LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME \ + LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER \ + LC_NAME LC_ADDRESS LC_TELEPHONE \ + LC_MEASUREMENT LC_IDENTIFICATION) + # LC_ALL is omitted on purpose + + local expl suf + _locales=( ${(f)"$(_call_program locales "$service" list-locales)"} ) + compset -P1 '*=' + if [[ -prefix 1 *\= ]]; then + local conf=${PREFIX%%\=*} + _wanted locales expl "locales configs" \ + _combination localeconfs confs=$conf locales "$@" - + else + compadd -S '=' $locale_fields + fi +} + +(( $+functions[_localectl_set-keymap] )) || +_localectl_set-keymap() { + local -a _keymaps + if (( CURRENT <= 3 )); then + _keymaps=( ${(f)"$(_call_program locales "$service" list-keymaps)"} ) + _describe keymaps _keymaps + else + _message "no more options" + fi +} + +(( $+functions[_localectl_set-x11-keymap] )) || +_localectl_set-x11-keymap() { + if (( $+commands[pkg-config] )); then + local -a _file _layout _model _variant _options + local _xorg_lst + _xorg_lst=${"$($commands[pkg-config] xkeyboard-config --variable=xkb_base)"} + _file=( ${(ps:\n\!:)"$(<$_xorg_lst/rules/xorg.lst)"} ) + _layout=( ${${${(M)${(f)_file[2]}:# *}# }%% *} ) + _model=( ${${${(M)${(f)_file[1]}:# *}# }%% *} ) + _variant=( ${${${(M)${(f)_file[3]}:# *}# }%% *} ) + _options=( ${${${(M)${(f)_file[4]}:# *}# }%% *} ) + #_layout=( ${(f)"$( echo $_file[1] | awk '/^ / {print $1}' )"} ) + #_model=( ${(f)"$(echo $_file[2] | awk '/^ / {print $1}')"} ) + #_variant=( ${(f)"$(echo $_file[3] | awk '/^ / {print $1}')"} ) + #_options=( ${(f)"$(echo ${_file[4]//:/\\:} | awk '/^ / {print $1}')"} ) + + case $CURRENT in + 2) _describe layouts _layout ;; + 3) _describe models _model;; + 4) _describe variants _variant;; + 5) _describe options _options;; + *) _message "no more options" + esac + fi +} + +(( $+functions[_localectl_commands] )) || +_localectl_commands() { + local -a _localectl_cmds + _localectl_cmds=( + 'status:Show current locale settings' + 'set-locale:Set system locale' + 'list-locales:Show known locales' + 'set-keymap:Set virtual console keyboard mapping' + 'list-keymaps:Show known virtual console keyboard mappings' + 'set-x11-keymap:Set X11 keyboard mapping' + 'list-x11-keymap-models:Show known X11 keyboard mapping models' + 'list-x11-keymap-layouts:Show known X11 keyboard mapping layouts' + 'list-x11-keymap-variants:Show known X11 keyboard mapping variants' + 'list-x11-keymap-options:Show known X11 keyboard mapping options' + ) + if (( CURRENT == 1 )); then + _describe -t commands 'localectl command' _localectl_cmds + else + local curcontext="$curcontext" + cmd="${${_localectl_cmds[(r)$words[1]:*]%%:*}}" + if (( $+functions[_localectl_$cmd] )); then + _localectl_$cmd + else + _message "unknown localectl command: $words[1]" + fi + fi +} + +_arguments \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + "--no-convert[Don't convert keyboard mappings]" \ + '--no-pager[Do not pipe output into a pager]' \ + '--no-ask-password[Do not prompt for password]' \ + {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ + {-M+,--machine=}'[Operate on local container]:machine' \ + '*::localectl commands:_localectl_commands' diff --git a/shell-completion/zsh/_loginctl b/shell-completion/zsh/_loginctl new file mode 100644 index 00000000..b9ccbedf --- /dev/null +++ b/shell-completion/zsh/_loginctl @@ -0,0 +1,176 @@ +#compdef loginctl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_loginctl_all_sessions] )) || +_loginctl_all_sessions() { + local session description + loginctl --no-legend list-sessions | while read -r session description; do + _sys_all_sessions+=( "$session" ) + _sys_all_sessions_descr+=( "${session}:$description" ) + done +} + +(( $+functions[_loginctl_all_users] )) || +_loginctl_all_users() { + local uid description + loginctl --no-legend list-users | while read -r uid description; do + _sys_all_users+=( "$uid" ) + _sys_all_users_descr+=( "${uid}:$description" ) + done +} + +(( $+functions[_loginctl_all_seats] )) || +_loginctl_all_seats() { + local seat description + loginctl --no-legend list-seats | while read -r seat description; do + _sys_all_seats+=( "$seat" ) + _sys_all_seats_descr+=( "${seat}:$description" ) + done +} + +local fun +# Completion functions for SESSIONS +for fun in session-status show-session activate lock-session unlock-session terminate-session kill-session ; do + (( $+functions[_loginctl_$fun] )) || +_loginctl_$fun() { + local -a _sys_all_sessions{,_descr} + + _loginctl_all_sessions + for _ignore in $words[2,-1]; do + _sys_all_sessions[(i)$_ignore]=() + _sys_all_sessions_descr[(i)$_ignore:*]=() + done + + if zstyle -T ":completion:${curcontext}:systemd-sessions" verbose; then + _describe -t systemd-sessions session _sys_all_sessions_descr _sys_all_sessions "$@" + else + local expl + _wanted systemd-sessions expl session compadd "$@" -a _sys_all_sessions + fi +} +done + +# Completion functions for USERS +for fun in user-status show-user enable-linger disable-linger terminate-user kill-user ; do + (( $+functions[_loginctl_$fun] )) || +_loginctl_$fun() { + local -a _sys_all_users{,_descr} + zstyle -a ":completion:${curcontext}:users" users _sys_all_users + + if ! (( $#_sys_all_users )); then + _loginctl_all_users + fi + + for _ignore in $words[2,-1]; do + _sys_all_users[(i)$_ignore]=() + _sys_all_users_descr[(i)$_ignore:*]=() + done + + # using the common tag `users' here, not rolling our own `systemd-users' tag + if zstyle -T ":completion:${curcontext}:users" verbose; then + _describe -t users user ${_sys_all_users_descr:+_sys_all_users_descr} _sys_all_users "$@" + else + local expl + _wanted users expl user compadd "$@" -a _sys_all_users + fi +} +done + +# Completion functions for SEATS +(( $+functions[_loginctl_seats] )) || +_loginctl_seats() { + local -a _sys_all_seats{,_descr} + + _loginctl_all_seats + for _ignore in $words[2,-1]; do + _sys_all_seats[(i)$_ignore]=() + _sys_all_seats_descr[(i)$_ignore:*]=() + done + + if zstyle -T ":completion:${curcontext}:systemd-seats" verbose; then + _describe -t systemd-seats seat _sys_all_seats_descr _sys_all_seats "$@" + else + local expl + _wanted systemd-seats expl seat compadd "$@" -a _sys_all_seats + fi +} +for fun in seat-status show-seat terminate-seat ; do + (( $+functions[_loginctl_$fun] )) || +_loginctl_$fun() { _loginctl_seats } +done + +# Completion functions for ATTACH +(( $+functions[_loginctl_attach] )) || +_loginctl_attach() { + _arguments -w -C -S -s \ + ':seat:_loginctl_seats' \ + '*:device:_files' +} + +# no loginctl completion for: +# [STANDALONE]='list-sessions list-users list-seats flush-devices' + +(( $+functions[_loginctl_commands] )) || +_loginctl_commands() { + local -a _loginctl_cmds + _loginctl_cmds=( + "list-sessions:List sessions" + "session-status:Show session status" + "show-session:Show properties of one or more sessions" + "activate:Activate a session" + "lock-session:Screen lock one or more sessions" + "unlock-session:Screen unlock one or more sessions" + "lock-sessions:Screen lock all current sessions" + "unlock-sessions:Screen unlock all current sessions" + "terminate-session:Terminate one or more sessions" + "kill-session:Send signal to processes of a session" + "list-users:List users" + "user-status:Show user status" + "show-user:Show properties of one or more users" + "enable-linger:Enable linger state of one or more users" + "disable-linger:Disable linger state of one or more users" + "terminate-user:Terminate all sessions of one or more users" + "kill-user:Send signal to processes of a user" + "list-seats:List seats" + "seat-status:Show seat status" + "show-seat:Show properties of one or more seats" + "attach:Attach one or more devices to a seat" + "flush-devices:Flush all device associations" + "terminate-seat:Terminate all sessions on one or more seats" + ) + + if (( CURRENT == 1 )); then + _describe -t commands 'loginctl command' _loginctl_cmds || compadd "$@" + else + local curcontext="$curcontext" _ignore + + cmd="${${_loginctl_cmds[(r)$words[1]:*]%%:*}}" + + if (( $#cmd )); then + curcontext="${curcontext%:*:*}:loginctl-${cmd}:" + + _call_function ret _loginctl_$cmd || _message 'no more arguments' + else + _message "unknown loginctl command: $words[1]" + fi + return ret + fi +} + + +_arguments -s \ + {-h,--help}'[Show help]' \ + '--version[Show package version]' \ + \*{-p+,--property=}'[Show only properties by this name]:unit property' \ + {-a,--all}'[Show all properties, including empty ones]' \ + '--kill-who=[Who to send signal to]:killwho:(main control all)' \ + {-s+,--signal=}'[Which signal to send]:signal:_signals' \ + {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ + {-M+,--machine=}'[Operate on local container]:machine:_sd_machines' \ + {-l,--full}'[Do not ellipsize output]' \ + '--no-pager[Do not pipe output into a pager]' \ + '--no-legend[Do not show the headers and footers]' \ + '--no-ask-password[Do not ask for system passwords]' \ + {-n+,--lines=}'[Number of journal entries to show]' \ + {-o+,--output=}'[Change journal output mode]:output modes:_sd_outputmodes' \ + '*::loginctl command:_loginctl_commands' diff --git a/shell-completion/zsh/_machinectl b/shell-completion/zsh/_machinectl new file mode 100644 index 00000000..5ffb7e8b --- /dev/null +++ b/shell-completion/zsh/_machinectl @@ -0,0 +1,105 @@ +#compdef machinectl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[__machinectl_get_machines] )) || + __machinectl_get_machines () { + machinectl --no-legend list-images | {while read -r a b; do echo $a; done;} + } + +(( $+functions[_machinectl_machines] )) || + _machinectl_machines() { + local -a _machines + _machines=("${(fo)$(__machinectl_get_machines)}") + typeset -U _machines + if [[ -n "$_machines" ]]; then + _describe 'machines' _machines + else + _message 'no machines' + fi + } + +(( $+functions[_machinectl_commands] )) || _machinectl_commands() +{ + local -a _machinectl_cmds + _machinectl_cmds=( + "list:List currently running VMs/containers" + "status:Show VM/container status" + "show:Show properties of one or more VMs/containers" + "start:Start container as a service" + "stop:Stop container (equal to poweroff)" + "login:Get a login prompt on a VM/container" + "enable:Enable automatic container start at boot" + "disable:Disable automatic container start at boot" + "poweroff:Power off one or more VMs/containers" + "reboot:Reboot one or more VMs/containers" + "terminate:Terminate one or more VMs/containers" + "kill:Send signal to process or a VM/container" + "copy-to:Copy files from the host to a container" + "copy-from:Copy files from a container to the host" + "bind:Bind mount a path from the host into a container" + + "list-images:Show available container and VM images" + "image-status:Show image details" + "show-image:Show properties of image" + "clone:Clone an image" + "rename:Rename an image" + "read-only:Mark or unmark image read-only" + "remove:Remove an image" + + "pull-tar:Download a TAR container image" + "pull-raw:Download a RAW container or VM image" + "list-transfers:Show list of downloads in progress" + "cancel-transfer:Cancel a download" + ) + + if (( CURRENT == 1 )); then + _describe -t commands 'machinectl command' _machinectl_cmds || compadd "$@" + else + local curcontext="$curcontext" + cmd="${${_machinectl_cmds[(r)$words[1]:*]%%:*}}" + if (( $#cmd )); then + if (( CURRENT == 2 )); then + case $cmd in + list*|cancel-transfer|pull-tar|pull-raw) + msg="no options" ;; + clone) + _machinectl_machines ;; + start) + _machinectl_machines ;; + *) + _sd_machines + esac + else + case $cmd in + copy-to|copy-from|bind) + _files ;; + *) msg="no options" + esac + fi + else + _message "no more options" + fi + fi +} + +_arguments \ + {-h,--help}'[Prints a short help text and exits.]' \ + '--version[Prints a short version string and exits.]' \ + '--no-pager[Do not pipe output into a pager.]' \ + '--no-legend[Do not show the headers and footers.]' \ + '--no-ask-password[Do not ask for system passwords.]' \ + {-H+,--host=}'[Operate on remote host.]:userathost:_sd_hosts_or_user_at_host' \ + {-M+,--machine=}'[Operate on local container.]:machine:_sd_machines' \ + {-p+,--property=}'[Limit output to specified property.]:property:(Name Id Timestamp TimestampMonotonic Service Scope Leader Class State RootDirectory)' \ + {-a,--all}'[Show all properties.]' \ + {-q,--quiet}'[Suppress output.]' \ + {-l,--full}'[Do not ellipsize cgroup members.]' \ + '--kill-who=[Who to send signal to.]:killwho:(leader all)' \ + {-s+,--signal=}'[Which signal to send.]:signal:_signals' \ + '--read-only[Create read-only bind mount.]' \ + '--mkdir[Create directory before bind mounting, if missing.]' \ + {-n+,--lines=}'[Number of journal entries to show.]:integer' \ + {-o+,--output=}'[Change journal output mode.]:output modes:_sd_outputmodes' \ + '--verify=[Verification mode for downloaded images.]:verify:(no checksum signature)' \ + '--force[Download image even if already exists.]' \ + '*::machinectl command:_machinectl_commands' diff --git a/shell-completion/zsh/_networkctl b/shell-completion/zsh/_networkctl new file mode 100644 index 00000000..4995bd3d --- /dev/null +++ b/shell-completion/zsh/_networkctl @@ -0,0 +1,38 @@ +#compdef networkctl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_networkctl_commands] )) || + _networkctl_commands() { + local -a _networkctl_cmds + _networkctl_cmds=( + 'list:List existing links' + 'status:Show information about the specified links' + 'lldp:Show Link Layer Discovery Protocol status' + 'label:Show address labels' + ) + if (( CURRENT == 1 )); then + _describe -t commands 'networkctl command' _networkctl_cmds + else + local curcontext="$curcontext" + local -a _links + cmd="${${_networkctl_cmds[(r)$words[1]:*]%%:*}}" + if [ $cmd = "status" ]; then + _links=( "${(foa)$(networkctl list --no-legend | awk 'BEGIN{OFS=":"} {sub(/[[ \t]+/, ""); print $2,$0}' 2>/dev/null)}" ) + if [[ -n "$_links" ]]; then + _describe -t links 'links' _links + else + _message "no links" + fi + else + _message "no more options" + fi + fi + } + +_arguments \ + {-a,--all}'[Show all links with status]' \ + '--no-pager[Do not pipe output into a pager]' \ + '--no-legend[Do not print the column headers]' \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + '*::networkctl commands:_networkctl_commands' diff --git a/shell-completion/zsh/_resolvectl b/shell-completion/zsh/_resolvectl new file mode 100644 index 00000000..7458f436 --- /dev/null +++ b/shell-completion/zsh/_resolvectl @@ -0,0 +1,87 @@ +#compdef resolvectl systemd-resolve -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +(( $+functions[_resolvectl_protocols] )) || + _resolvectl_protocols() { + local -a _protocol + _protocol=( $(_call_program protocol ${service} --legend=no --protocol help; echo help) ) + _values 'protocol' "$_protocol[@]" + } + +(( $+functions[_resolvectl_types] )) || + _resolvectl_types() { + local -a _type + _type=( $(_call_program type ${service} --legend=no --type help; echo help) ) + _values 'type' "$_type[@]" + } + +(( $+functions[_resolvectl_classes] )) || + _resolvectl_classes() { + local -a _class + _class=( $(_call_program class ${service} --legend=no --class help; echo help) ) + _values 'class' "$_class[@]" + } + +(( $+functions[_resolvectl_commands] )) || + _resolvectl_commands() { + local -a _resolvectl_cmds + _resolvectl_cmds=( + default-route:"Configure per-interface default-route setting" + dns:"Configure per-interface DNS configuration" + dnsovertls:"Configure per-interface dnsovertls enabled status" + dnssec:"Configure per-interface dnssec enabled status" + domain:"Configure per-interface search and route-only domains" + flush-caches:"Flushes all DNS resource record caches the service maintains locally" + llmnr:"Configure per-interface llmnr enabled status" + mdns:"Configure per-interface mdns enabled status" + nta:"Configure per-interface nta domains" + openpgp:"Retrieve openpgp keys for an email" + query:"Resolve domain names, IPv4 and IPv6 addresses" + reset-server-features:"Flushes all feature level information the resolver has learned about specific servers" + reset-statistics:"Resets the statistics counter show in statistics to zero" + revert:"Revert the per-interfce DNS configuration" + service:"Resolve DNS-SD and SRV services" + status:"Show the global and per-link DNS settings currently in effect" + tlsa:"Query tlsa public keys stored as TLSA resource records" + ) + + if (( CURRENT == 1 )); then + _describe -t commands 'resolvectl commands' _resolvectl_cmds + fi +} + +_arguments \ + {-h,--help}'[Print a short help text and exit]' \ + '--version[Print a short version string and exit]' \ + '--legend=no[Do not show headers and footers]' \ + '-4[Resolve IPv4 addresses]' \ + '-6[Resolve IPv6 addresses]' \ + {-i+,--interface=}'[Look on interface]:interface:_net_interfaces' \ + {-p+,--protocol=}'[Look via protocol]:protocol:_resolvectl_protocols' \ + {-t+,--type=}'[Query RR with DNS type]:type:_resolvectl_types' \ + {-c+,--class=}'[Query RR with DNS class]:class:_resolvectl_classes' \ + '--service[Resolve services]' \ + '--service-address=no[Do not resolve address for services]' \ + '--service-txt=no[Do not resolve TXT records for services]' \ + '--openpgp[Query OpenPGP public key]' \ + '--tlsa[Query TLS public key]' \ + '--cname=no[Do not follow CNAME redirects]' \ + '--search=no[Do not use search domains]' \ + '--statistics[Show resolver statistics]' \ + '--reset-statistics[Reset resolver statistics]' \ + '*::default: _resolvectl_commands' diff --git a/shell-completion/zsh/_sd_hosts_or_user_at_host b/shell-completion/zsh/_sd_hosts_or_user_at_host new file mode 100644 index 00000000..a510bf3c --- /dev/null +++ b/shell-completion/zsh/_sd_hosts_or_user_at_host @@ -0,0 +1,6 @@ +#autoload +# SPDX-License-Identifier: LGPL-2.1+ + +_alternative \ + 'users-hosts:: _user_at_host' \ + 'hosts:: _hosts' diff --git a/shell-completion/zsh/_sd_machines b/shell-completion/zsh/_sd_machines new file mode 100644 index 00000000..30b7fd81 --- /dev/null +++ b/shell-completion/zsh/_sd_machines @@ -0,0 +1,16 @@ +#autoload +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[__sd_machines_get_machines] )) || + __sd_machines_get_machines () { + machinectl --full --no-legend --no-pager list | {while read -r a b; do echo $a; done;}; + } + +local -a _machines +_machines=("${(fo)$(__sd_machines_get_machines)}") +typeset -U _machines +if [[ -n "$_machines" ]]; then + _describe 'machines' _machines +else + _message 'no machines' +fi diff --git a/shell-completion/zsh/_sd_outputmodes b/shell-completion/zsh/_sd_outputmodes new file mode 100644 index 00000000..763b106f --- /dev/null +++ b/shell-completion/zsh/_sd_outputmodes @@ -0,0 +1,6 @@ +#autoload +# SPDX-License-Identifier: LGPL-2.1+ + +local -a _output_opts +_output_opts=(short short-full short-iso short-iso-precise short-precise short-monotonic short-unix verbose export json json-pretty json-sse json-seq cat with-unit) +_describe -t output 'output mode' _output_opts || compadd "$@" diff --git a/shell-completion/zsh/_sd_unit_files b/shell-completion/zsh/_sd_unit_files new file mode 100644 index 00000000..cce44423 --- /dev/null +++ b/shell-completion/zsh/_sd_unit_files @@ -0,0 +1,10 @@ +#autoload +# SPDX-License-Identifier: LGPL-2.1+ + +_sd_unit_files() { + local files expl + files=( '*:files:->files' ) + + _description files expl 'unit file' + _files "$expl[@]" -g '*.(automount|device|mount|path|service|socket|swap|target|timer)' +} diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in new file mode 100644 index 00000000..67c1c2b3 --- /dev/null +++ b/shell-completion/zsh/_systemctl.in @@ -0,0 +1,424 @@ +#compdef systemctl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_systemctl_commands] )) || _systemctl_commands() +{ + local -a _systemctl_cmds + _systemctl_cmds=( + "list-sockets:List sockets" + "list-timers:List timers" + "list-units:List units" + "start:Start (activate) one or more units" + "stop:Stop (deactivate) one or more units" + "reload:Reload one or more units" + "restart:Start or restart one or more units" + "condrestart:Restart one or more units if active" + "try-restart:Restart one or more units if active" + "reload-or-restart:Reload one or more units if possible, otherwise start or restart" + "force-reload:Reload one or more units if possible, otherwise restart if active" + "hibernate:Hibernate the system" + "hybrid-sleep:Hibernate and suspend the system" + "suspend-then-hibernate:Suspend the system for a period of time, and then hibernate it" + "try-reload-or-restart:Reload one or more units if possible, otherwise restart if active" + "isolate:Start one unit and stop all others" + "kill:Send signal to processes of a unit" + "is-active:Check whether units are active" + "is-failed:Check whether units are failed" + "status:Show runtime status of one or more units" + "show:Show properties of one or more units/jobs or the manager" + "cat:Show the source unit files and drop-ins" + "reset-failed:Reset failed state for all, one, or more units" + "list-unit-files:List installed unit files" + "enable:Enable one or more unit files" + "disable:Disable one or more unit files" + "add-wants:Add Wants= dependencies to a unit" + "add-requires:Add Requires= dependencies to a unit" + "reenable:Reenable one or more unit files" + "preset:Enable/disable one or more unit files based on preset configuration" + "preset-all:Enable/disable all unit files based on preset configuration" + "set-default:Set the default target" + "get-default:Query the default target" + "edit:Edit one or more unit files" + "is-system-running:Query overall status of the system" + "help:Show documentation for specified units" + "list-dependencies:Show unit dependency tree" + "mask:Mask one or more units" + "unmask:Unmask one or more units" + "link:Link one or more units files into the search path" + "is-enabled:Check whether unit files are enabled" + "list-jobs:List jobs" + "cancel:Cancel all, one, or more jobs" + "show-environment:Dump environment" + "set-environment:Set one or more environment variables" + "unset-environment:Unset one or more environment variables" + "daemon-reload:Reload systemd manager configuration" + "daemon-reexec:Reexecute systemd manager" + "default:Enter system default mode" + "rescue:Enter system rescue mode" + "emergency:Enter system emergency mode" + "halt:Shut down and halt the system" + "suspend:Suspend the system" + "poweroff:Shut down and power-off the system" + "reboot:Shut down and reboot the system" + "kexec:Shut down and reboot the system with kexec" + "exit:Ask for user instance termination" + "switch-root:Change root directory" + "revert:Revert unit files to their vendor versions" + "set-property:Sets one or more properties of a unit" + ) + + if (( CURRENT == 1 )); then + _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@" + else + local curcontext="$curcontext" expl + + cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}" + # Deal with any aliases + case $cmd in + condrestart) cmd="try-restart";; + force-reload) cmd="try-reload-or-restart";; + esac + + if (( $#cmd )); then + curcontext="${curcontext%:*:*}:systemctl-${cmd}:" + + local update_policy + zstyle -s ":completion:${curcontext}:" cache-policy update_policy + if [[ -z "$update_policy" ]]; then + zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy + fi + + _call_function ret _systemctl_$cmd || _message 'no more arguments' + else + _message "unknown systemctl command: $words[1]" + fi + return ret + fi +} + +# @todo _systemd-run has a helper with the same name, so we must redefine +__systemctl() +{ + systemctl $_sys_service_mgr --full --no-legend --no-pager "$@" 2>/dev/null +} + + +# Fills the unit list +(( $+functions[_systemctl_all_units] )) || + _systemctl_all_units() +{ + if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS$_sys_service_mgr ) || + ! _retrieve_cache SYS_ALL_UNITS$_sys_service_mgr; + then + _sys_all_units=( ${${(f)"$(__systemctl list-units --all "$PREFIX*" )"}%% *} ) + _store_cache SYS_ALL_UNITS$_sys_service_mgr _sys_all_units + fi +} + +# Fills the unit list including all file units +(( $+functions[_systemctl_really_all_units] )) || + _systemctl_really_all_units() +{ + local -a all_unit_files; + local -a really_all_units; + if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS$_sys_service_mgr ) || + ! _retrieve_cache SYS_REALLY_ALL_UNITS$_sys_service_mgr; + then + all_unit_files=( ${${(f)"$(__systemctl list-unit-files "$PREFIX*" )"}%% *} ) + _systemctl_all_units + really_all_units=($_sys_all_units $all_unit_files) + _sys_really_all_units=(${(u)really_all_units}) + _store_cache SYS_REALLY_ALL_UNITS$_sys_service_mgr _sys_really_all_units + fi +} + +(( $+functions[_filter_units_by_property] )) || + _filter_units_by_property() { + local property=$1 value=$2; shift 2 + local -a units; units=("${(q-)@}") + local -A props + props=(${(f)"$(_call_program units "$service $_sys_service_mgr show --no-pager --property=\"Id,$property\" -- ${units} 2>/dev/null")"}) + echo -E - "${(@g:o:)${(k@)props[(Re)$property=$value]}#Id=}" + } + +(( $+functions[_systemctl_get_non_template_names] )) || + _systemctl_get_non_template_names() { echo -E - ${^${(R)${(f)"$( + __systemctl $mode list-unit-files "$PREFIX*" + __systemctl $mode list-units --all "$PREFIX*" + )"}:#*@.*}%%[[:space:]]*} } + +(( $+functions[_systemctl_get_template_names] )) || + _systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files "$PREFIX*" )"}##*@.[^[:space:]]##}%%@.*}\@ } + +(( $+functions[_systemctl_active_units] )) || + _systemctl_active_units() {_sys_active_units=( ${${(f)"$(__systemctl list-units "$PREFIX*" )"}%% *} )} + +(( $+functions[_systemctl_startable_units] )) || + _systemctl_startable_units(){ + _sys_startable_units=( $( _filter_units_by_property ActiveState inactive $( + _filter_units_by_property CanStart yes ${${${(f)"$( + __systemctl $mode list-unit-files --state enabled,enabled-runtime,linked,linked-runtime,static,indirect,disabled,generated,transient "$PREFIX*" + __systemctl $mode list-units --state inactive,failed "$PREFIX*" + )"}:#*@.*}%%[[:space:]]*} + )) ) + } + +(( $+functions[_systemctl_restartable_units] )) || + _systemctl_restartable_units(){ + _sys_restartable_units=( $( _filter_units_by_property CanStart yes ${${${(f)"$( + __systemctl $mode list-unit-files --state enabled,disabled,static "$PREFIX*" + __systemctl $mode list-units "$PREFIX*" + )"}:#*@.*}%%[[:space:]]*} ) ) + } + +(( $+functions[_systemctl_failed_units] )) || + _systemctl_failed_units() {_sys_failed_units=( ${${(f)"$(__systemctl list-units --state=failed "$PREFIX*" )"}%% *} ) } + +(( $+functions[_systemctl_unit_state] )) || + _systemctl_unit_state() { typeset -gA _sys_unit_state; _sys_unit_state=( $(__systemctl list-unit-files "$PREFIX*" ) ) } + +local fun +# Completion functions for ALL_UNITS +for fun in cat mask ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _systemctl_really_all_units + _wanted systemd-units expl unit \ + compadd "$@" -a - _sys_really_all_units + } +done + +# Completion functions for NONTEMPLATE_UNITS +for fun in is-active is-failed is-enabled status show preset help list-dependencies edit revert add-wants add-requires set-property; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + _wanted systemd-units expl unit \ + compadd "$@" - $(_systemctl_get_non_template_names) + } +done + +# Completion functions for ENABLED_UNITS +(( $+functions[_systemctl_disable] )) || _systemctl_disable() +{ + local _sys_unit_state; _systemctl_unit_state + _wanted systemd-units expl 'enabled unit' \ + compadd "$@" - ${(k)_sys_unit_state[(R)enabled]} +} + +(( $+functions[_systemctl_reenable] )) || _systemctl_reenable() +{ + local _sys_unit_state; _systemctl_unit_state + _wanted systemd-units expl 'enabled/disabled unit' \ + compadd "$@" - ${(k)_sys_unit_state[(R)(enabled|disabled)]} $(_systemctl_get_template_names) +} + +# Completion functions for DISABLED_UNITS +(( $+functions[_systemctl_enable] )) || _systemctl_enable() +{ + local _sys_unit_state; _systemctl_unit_state + _wanted systemd-units expl 'disabled unit' \ + compadd "$@" - ${(k)_sys_unit_state[(R)disabled]} $(_systemctl_get_template_names) +} + +# Completion functions for FAILED_UNITS +(( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed() +{ + local _sys_failed_units; _systemctl_failed_units + _wanted systemd-units expl 'failed unit' \ + compadd "$@" -a - _sys_failed_units || _message "no failed unit found" +} + +# Completion functions for STARTABLE_UNITS +(( $+functions[_systemctl_start] )) || _systemctl_start() +{ + local _sys_startable_units; _systemctl_startable_units + _wanted systemd-units expl 'startable unit' \ + compadd "$@" - ${_sys_startable_units[*]} +} + +# Completion functions for STOPPABLE_UNITS +for fun in stop kill try-restart condrestart ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + local _sys_active_units; _systemctl_active_units + _wanted systemd-units expl 'stoppable unit' \ + compadd "$@" - $( _filter_units_by_property CanStop yes \ + ${_sys_active_units[*]} ) + } +done + +# Completion functions for ISOLATABLE_UNITS +(( $+functions[_systemctl_isolate] )) || _systemctl_isolate() +{ + _systemctl_all_units + _wanted systemd-units expl 'isolatable unit' \ + compadd "$@" - $( _filter_units_by_property AllowIsolate yes \ + ${_sys_all_units[*]} ) +} + +# Completion functions for RELOADABLE_UNITS +for fun in reload try-reload-or-restart force-reload ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + local _sys_active_units; _systemctl_active_units + _wanted systemd-units expl 'reloadable unit' \ + compadd "$@" - $( _filter_units_by_property CanReload yes \ + ${_sys_active_units[*]} ) + } +done + +# Completion functions for RESTARTABLE_UNITS +for fun in restart reload-or-restart ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + local _sys_restartable_units; _systemctl_restartable_units + _wanted systemd-units expl 'restartable unit' \ + compadd "$@" - ${_sys_restartable_units[*]} + } +done + +# Completion functions for MASKED_UNITS +(( $+functions[_systemctl_unmask] )) || _systemctl_unmask() +{ + local _sys_unit_state; _systemctl_unit_state + _wanted systemd-units expl 'masked unit' \ + compadd "$@" - ${(k)_sys_unit_state[(R)masked]} || _message "no masked units found" +} + +# Completion functions for JOBS +(( $+functions[_systemctl_cancel] )) || _systemctl_cancel() +{ + _wanted systemd-jobs expl job \ + compadd "$@" - ${${(f)"$(__systemctl list-jobs)"}%% *} || + _message "no jobs found" +} + +# Completion functions for TARGETS +(( $+functions[_systemctl_set-default] )) || _systemctl_set-default() +{ + _wanted systemd-targets expl target \ + compadd "$@" - ${${(f)"$(__systemctl list-unit-files --type target --all "$PREFIX*" )"}%% *} || + _message "no targets found" +} + +# Completion functions for ENVS +for fun in set-environment unset-environment ; do + (( $+functions[_systemctl_$fun] )) || _systemctl_$fun() + { + local fun=$0 ; fun=${fun##_systemctl_} + local suf + if [[ "${fun}" = "set-environment" ]]; then + suf='-S=' + fi + _wanted systemd-environment expl 'environment variable' \ + compadd "$@" ${suf} - ${${(f)"$(systemctl show-environment)"}%%=*} + } +done + +(( $+functions[_systemctl_link] )) || _systemctl_link() { + _sd_unit_files + } + +(( $+functions[_systemctl_switch-root] )) || _systemctl_switch-root() { + _files + } + +# no systemctl completion for: +# [STANDALONE]='daemon-reexec daemon-reload default +# emergency exit halt kexec list-jobs list-units +# list-unit-files poweroff reboot rescue show-environment' + +(( $+functions[_systemctl_caching_policy] )) || + _systemctl_caching_policy() +{ + local _sysunits + local -a oldcache + + # rebuild if cache is more than a day old + oldcache=( "$1"(mh+1) ) + (( $#oldcache )) && return 0 + + _sysunits=(${${(f)"$(__systemctl --all)"}%% *}) + + if (( $#_sysunits )); then + for unit in $_sysunits; do + [[ "$unit" -nt "$1" ]] && return 0 + done + fi + + return 1 +} + +(( $+functions[_systemctl_unit_states] )) || + _systemctl_unit_states() { + local -a _states + _states=("${(fo)$(__systemctl --state=help)}") + _values -s , "${_states[@]}" + } + +(( $+functions[_systemctl_unit_types] )) || + _systemctl_unit_types() { + local -a _types + _types=("${(fo)$(__systemctl -t help)}") + _values -s , "${_types[@]}" + } + +(( $+functions[_systemctl_unit_properties] )) || + _systemctl_unit_properties() { + if ( [[ ${+_sys_all_properties} -eq 0 ]] || _cache_invalid SYS_ALL_PROPERTIES$_sys_service_mgr ) || + ! _retrieve_cache SYS_ALL_PROPERTIES$_sys_service_mgr; + then + _sys_all_properties=( ${${(M)${(f)"$(@rootlibexecdir@/systemd --dump-bus-properties)"}}} ) + _store_cache SYS_ALL_PROPERTIES$_sys_service_mgr _sys_all_properties + fi + _values -s , "${_sys_all_properties[@]}" + } + +(( $+functions[_systemctl_job_modes] )) || + _systemctl_job_modes() { + local -a _modes + _modes=(fail replace replace-irreversibly isolate ignore-dependencies ignore-requirements flush) + _values -s , "${_modes[@]}" + } + +# Build arguments for "systemctl" to be used in completion. +local -a _modes; _modes=("--user" "--system") +# Use the last mode (they are exclusive and the last one is used). +local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]} +_arguments -s \ + {-h,--help}'[Show help]' \ + '--version[Show package version]' \ + {-t+,--type=}'[List only units of a particular type]:unit type:_systemctl_unit_types' \ + '--state=[Display units in the specified state]:unit state:_systemctl_unit_states' \ + '--job-mode=[Specify how to deal with other jobs]:mode:_systemctl_job_modes' \ + {-p+,--property=}'[Show only properties by specific name]:unit property:_systemctl_unit_properties' \ + {-a,--all}'[Show all units/properties, including dead/empty ones]' \ + '--reverse[Show reverse dependencies]' \ + '--after[Show units ordered after]' \ + '--before[Show units ordered before]' \ + {-l,--full}"[Don't ellipsize unit names on output]" \ + '--show-types[When showing sockets, show socket type]' \ + {-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \ + {-q,--quiet}'[Suppress output]' \ + '--no-block[Do not wait until operation finished]' \ + '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \ + '--no-pager[Do not pipe output into a pager]' \ + '--system[Connect to system manager]' \ + '--user[Connect to user service manager]' \ + "--no-wall[Don't send wall message before halt/power-off/reboot]" \ + '--global[Enable/disable/mask unit files globally]' \ + "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \ + '--no-ask-password[Do not ask for system passwords]' \ + '--kill-who=[Who to send signal to]:killwho:(main control all)' \ + {-s+,--signal=}'[Which signal to send]:signal:_signals' \ + {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \ + '--root=[Enable/disable/mask unit files in the specified root directory]:directory:_directories' \ + '--runtime[Enable/disable/mask unit files only temporarily until next reboot]' \ + {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ + {-P,--privileged}'[Acquire privileges before execution]' \ + {-n+,--lines=}'[Journal entries to show]:number of entries' \ + {-o+,--output=}'[Change journal output mode]:modes:_sd_outputmodes' \ + '--firmware-setup[Tell the firmware to show the setup menu on next boot]' \ + '--plain[When used with list-dependencies, print output as a list]' \ + '--failed[Show failed units]' \ + '*::systemctl command:_systemctl_commands' diff --git a/shell-completion/zsh/_systemd b/shell-completion/zsh/_systemd new file mode 100644 index 00000000..3550c151 --- /dev/null +++ b/shell-completion/zsh/_systemd @@ -0,0 +1,81 @@ +#compdef systemd-cat systemd-ask-password systemd-cgls systemd-cgtop systemd-detect-virt systemd-machine-id-setup systemd-notify systemd-tty-ask-password-agent -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +local curcontext="$curcontext" state lstate line +case "$service" in + systemd-ask-password) + _arguments \ + {-h,--help}'[Show this help]' \ + '--icon=[Icon name]:icon name:' \ + '--timeout=[Timeout in sec]:timeout (seconds):' \ + '--no-tty[Ask question via agent even on TTY]' \ + '--accept-cached[Accept cached passwords]' \ + '--multiple[List multiple passwords if available]' + ;; + systemd-cat) + _arguments \ + {-h,--help}'[Show this help]' \ + '--version[Show package version.]' \ + {-t+,--identifier=}'[Set syslog identifier.]:syslog identifier:' \ + {-p+,--priority=}'[Set priority value.]:value:({0..7})' \ + '--level-prefix=[Control whether level prefix shall be parsed.]:boolean:(1 0)' \ + ':Message' + ;; + systemd-cgls) + _arguments \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + '--no-pager[Do not pipe output into a pager]' \ + {-a,--all}'[Show all groups, including empty]' \ + '-k[Include kernel threads in output]' \ + ':cgroups:(cpuset cpu cpuacct memory devices freezer blkio)' + ;; + systemd-cgtop) + _arguments \ + {-h,--help}'[Show this help]' \ + '--version[Print version and exit]' \ + '(-c -m -i -t)-p[Order by path]' \ + '(-c -p -m -i)-t[Order by number of tasks]' \ + '(-m -p -i -t)-c[Order by CPU load]' \ + '(-c -p -i -t)-m[Order by memory load]' \ + '(-c -m -p -t)-i[Order by IO load]' \ + {-d+,--delay=}'[Specify delay]:delay:' \ + {-n+,--iterations=}'[Run for N iterations before exiting]:number of iterations:' \ + {-b,--batch}'[Run in batch mode, accepting no input]' \ + '--depth=[Maximum traversal depth]:maximum depth:' + ;; + systemd-detect-virt) + _arguments \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + {-c,--container}'[Only detect whether we are run in a container]' \ + {-v,--vm}'[Only detect whether we are run in a VM]' \ + {-q,--quiet}"[Don't output anything, just set return value]" + ;; + systemd-machine-id-setup) + _arguments \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' + ;; + systemd-notify) + _arguments \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + '--ready[Inform the init system about service start-up completion.]' \ + '--pid=[Inform the init system about the main PID of the daemon]:daemon main PID:_pids' \ + '--status=[Send a free-form status string for the daemon to the init systemd]:status string:' \ + '--booted[Returns 0 if the system was booted up with systemd]' + ;; + systemd-tty-ask-password-agent) + _arguments \ + {-h,--help}'[Prints a short help text and exits.]' \ + '--version[Prints a short version string and exits.]' \ + '--list[Lists all currently pending system password requests.]' \ + '--query[Process all currently pending system password requests by querying the user on the calling TTY.]' \ + '--watch[Continuously process password requests.]' \ + '--wall[Forward password requests to wall(1).]' \ + '--plymouth[Ask question with plymouth(8).]' \ + '--console[Ask question on /dev/console.]' + ;; + *) _message 'eh?' ;; +esac diff --git a/shell-completion/zsh/_systemd-analyze b/shell-completion/zsh/_systemd-analyze new file mode 100644 index 00000000..89ba46c9 --- /dev/null +++ b/shell-completion/zsh/_systemd-analyze @@ -0,0 +1,82 @@ +#compdef systemd-analyze -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_systemd-analyze_log-level] )) || + _systemd-analyze_log-level() { + local -a _levels + _levels=(debug info notice warning err crit alert emerg) + _describe -t level 'logging level' _levels || compadd "$@" + } + +(( $+functions[_systemd-analyze_log-target] )) || + _systemd-analyze_log-target() { + local -a _targets + _targets=(console journal kmsg journal-or-kmsg null) + _describe -t target 'logging target' _targets || compadd "$@" + } + +(( $+functions[_systemd-analyze_verify] )) || + _systemd-analyze_verify() { + _sd_unit_files + } + +(( $+functions[_systemd-analyze_service-watchdogs] )) || + _systemd-analyze_service-watchdogs() { + local -a _states + _states=(on off) + _describe -t state 'state' _states || compadd "$@" + } + +(( $+functions[_systemd-analyze_commands] )) || + _systemd-analyze_commands(){ + local -a _systemd_analyze_cmds + # Descriptions taken from systemd-analyze --help. + _systemd_analyze_cmds=( + 'time:Print time spent in the kernel before reaching userspace' + 'blame:Print list of running units ordered by time to init' + 'critical-chain:Print a tree of the time critical chain of units' + 'plot:Output SVG graphic showing service initialization' + 'dot:Dump dependency graph (in dot(1) format)' + 'dump:Dump server status' + 'unit-paths:List unit load paths' + 'log-level:Get/set systemd log threshold' + 'log-target:Get/set systemd log target' + 'service-watchdogs:Get/set service watchdog status' + 'syscall-filter:List syscalls in seccomp filter' + 'verify:Check unit files for correctness' + 'calendar:Validate repetitive calendar time events' + ) + + if (( CURRENT == 1 )); then + _describe "options" _systemd_analyze_cmds + else + local curcontext="$curcontext" + cmd="${${_systemd_analyze_cmds[(r)$words[1]:*]%%:*}}" + if (( $#cmd )); then + if (( $+functions[_systemd-analyze_$cmd] )) && (( CURRENT == 2 )); then + _systemd-analyze_$cmd + else + _message "no more options" + fi + else + _message "unknown systemd-analyze command: $words[1]" + fi + fi + } + +_arguments \ + {-h,--help}'[Show help text]' \ + '--version[Show package version]' \ + '--system[Operate on system systemd instance]' \ + '--user[Operate on user systemd instance]' \ + '--global[Show global user instance config]' \ + '--no-pager[Do not pipe output into a pager]' \ + '--man=[Do (not) check for existence of man pages]:boolean:(1 0)' \ + '--order[When generating graph for dot, show only order]' \ + '--require[When generating graph for dot, show only requirement]' \ + '--fuzz=[When printing the tree of the critical chain, print also services, which finished TIMESPAN earlier, than the latest in the branch]:TIMESPAN' \ + '--from-pattern=[When generating a dependency graph, filter only origins]:GLOB' \ + '--to-pattern=[When generating a dependency graph, filter only destinations]:GLOB' \ + {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ + {-M+,--machine=}'[Operate on local container]:machine:_sd_machines' \ + '*::systemd-analyze commands:_systemd-analyze_commands' diff --git a/shell-completion/zsh/_systemd-delta b/shell-completion/zsh/_systemd-delta new file mode 100644 index 00000000..b4361f78 --- /dev/null +++ b/shell-completion/zsh/_systemd-delta @@ -0,0 +1,17 @@ +#compdef systemd-delta -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_systemd-delta_types] )) || +_systemd-delta_types() { + local -a _delta_types + _delta_types=(masked equivalent redirected overridden unchanged) + _values -s , "${_delta_types[@]}" +} + +_arguments \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + '--no-pager[Do not pipe output into a pager]' \ + '--diff=[Show a diff when overridden files differ]:boolean:(1 0)' \ + {-t+,--type=}'[Only display a selected set of override types]:types:_systemd-delta_types' \ + ':SUFFIX:(tmpfiles.d sysctl.d systemd/system)' diff --git a/shell-completion/zsh/_systemd-inhibit b/shell-completion/zsh/_systemd-inhibit new file mode 100644 index 00000000..4536f9bd --- /dev/null +++ b/shell-completion/zsh/_systemd-inhibit @@ -0,0 +1,36 @@ +#compdef systemd-inhibit -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_systemd-inhibit_commands] )) || +_systemd-inhibit_commands(){ + if (( CURRENT == 1 )); then + compset -q + _normal + else + local n=${words[(b:2:i)[^-]*]} + if (( n <= CURRENT )); then + compset -n $n + _alternative \ + 'files:file:_files' \ + 'commands:command:_normal' && return 0 + fi + _default + fi +} + +(( $+functions[_systemd-inhibit_what] )) || +_systemd-inhibit_what() { + local _inhibit + _inhibit=(shutdown sleep idle handle-power-key handle-suspend-key handle-hibernate-key handle-lid-switch) + _values -s : "${_inhibit[@]}" +} + +_arguments \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + '--what=[Operations to inhibit]:options:_systemd-inhibit_what' \ + '--who=[A descriptive string who is inhibiting]:who is inhibiting:' \ + '--why=[A descriptive string why is being inhibited]:reason for the lock:' \ + '--mode=[One of block or delay]:lock mode:( block delay )' \ + '--list[List active inhibitors]' \ + '*:commands:_systemd-inhibit_commands' diff --git a/shell-completion/zsh/_systemd-nspawn b/shell-completion/zsh/_systemd-nspawn new file mode 100644 index 00000000..414d82e2 --- /dev/null +++ b/shell-completion/zsh/_systemd-nspawn @@ -0,0 +1,52 @@ +#compdef systemd-nspawn -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_systemd-nspawn_caps] )) || +_systemd-nspawn_caps(){ + local -a _caps + _caps=( CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH + CAP_FOWNER CAP_FSETID CAP_IPC_OWNER CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE + CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETGID CAP_SETFCAP CAP_SETPCAP + CAP_SETUID CAP_SYS_ADMIN CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_PTRACE CAP_SYS_TTY_CONFIG + CAP_SYS_RESOURCE CAP_SYS_BOOT ) + _values -s , 'capabilities' "$_caps[@]" +} + +_arguments \ + {-h,--help}'[Show this help.]' \ + '--version[Print a short version string and exit.]' \ + {--quiet,-q}'[Turns off any status output by the tool itself.]' \ + {--directory=,-D+}'[Directory to use as file system root for the namespace container. If omitted the current directory will be used.]:directories:_directories' \ + '--template=[Initialize root directory from template directory, if missing.]:template:_directories' \ + {--ephemeral,-x}'[Run container with snapshot of root directory, and remove it after exit.]' \ + {--image=,-i+}'[Disk image to mount the root directory for the container from.]:disk image: _files' \ + {--boot,-b}'[Automatically search for an init binary and invoke it instead of a shell or a user supplied program.]' \ + {--user=,-u+}'[Run the command under specified user, create home directory and cd into it.]:user:_users' \ + {--machine=,-M+}'[Sets the machine name for this container.]: : _message "container name"' \ + '--uuid=[Set the specified uuid for the container.]: : _message "container UUID"' \ + {--slice=,-S+}'[Make the container part of the specified slice, instead of the default machine.slice.]: : _message slice' \ + '--private-network[Disconnect networking of the container from the host.]' \ + '--network-interface=[Assign the specified network interface to the container.]: : _net_interfaces' \ + '--network-macvlan=[Create a "macvlan" interface of the specified Ethernet network interface and add it to the container.]: : _net_interfaces' \ + '--network-ipvlan=[Create a ipvlan network interface based on an existing network interface to the container.]: : _net_interfaces' \ + {--network-veth,-n}'[Create a virtual Ethernet link (veth) between host and container.]' \ + '--network-bridge=[Adds the host side of the Ethernet link created with --network-veth to the specified bridge.]: : _net_interfaces' \ + {--port=,-p+}'[Expose a container IP port on the host.]: : _message port' \ + {--selinux-context=,-Z+}'[Sets the SELinux security context to be used to label processes in the container.]: : _message "SELinux context"' \ + {--selinux-apifs-context=,-L+}'[Sets the SELinux security context to be used to label files in the virtual API file systems in the container.]: : _message "SELinux context"' \ + '--capability=[List one or more additional capabilities to grant the container.]:capabilities:_systemd-nspawn_caps' \ + '--drop-capability=[Specify one or more additional capabilities to drop for the containerm]:capabilities:_systemd-nspawn_caps' \ + "--link-journal=[Control whether the container's journal shall be made visible to the host system.]:options:(no host guest auto)" \ + '-j[Equivalent to --link-journal=guest.]' \ + '--read-only[Mount the root file system read only for the container.]' \ + '--bind=[Bind mount a file or directory from the host into the container.]: : _files' \ + '--bind-ro=[Bind mount a file or directory from the host into the container (read-only).]: : _files' \ + '--tmpfs=[Mount an empty tmpfs to the specified directory.]: : _files' \ + '--setenv=[Specifies an environment variable assignment to pass to the init process in the container, in the format "NAME=VALUE".]: : _message "environment variables"' \ + '--share-system[Allows the container to share certain system facilities with the host.]' \ + '--register=[Controls whether the container is registered with systemd-machined(8).]:systemd-machined registration:( yes no )' \ + '--keep-unit[Instead of creating a transient scope unit to run the container in, simply register the service or scope unit systemd-nspawn has been invoked in with systemd-machined(8).]' \ + '--personality=[Control the architecture ("personality") reported by uname(2) in the container.]:architecture:(x86 x86-64)' \ + '--volatile=[Run the system in volatile mode.]:volatile:(no yes state)' \ + "--notify-ready=[Control when the ready notification is sent]:options:(yes no)" \ + '*:: : _normal' diff --git a/shell-completion/zsh/_systemd-run b/shell-completion/zsh/_systemd-run new file mode 100644 index 00000000..ca0faa14 --- /dev/null +++ b/shell-completion/zsh/_systemd-run @@ -0,0 +1,65 @@ +#compdef systemd-run -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +# @todo _systemctl has a helper with the same name, so we must redefine +__systemctl() { + local -a _modes + _modes=("--user" "--system") + systemctl ${words:*_modes} --full --no-legend --no-pager "$@" 2>/dev/null +} + +(( $+functions[__systemd-run_get_slices] )) || + __systemd-run_get_slices () { + __systemctl list-units --all -t slice \ + | { while read -r a b; do echo $a; done; }; + } + +(( $+functions[__systemd-run_slices] )) || + __systemd-run_slices () { + local -a _slices + _slices=(${(fo)"$(__systemd-run_get_slices)"}) + typeset -U _slices + _describe 'slices' _slices + } + +_arguments \ + {-h,--help}'[Show help message]' \ + '--version[Show package version]' \ + '--user[Run as user unit]' \ + {-H+,--host=}'[Operate on remote host]:[user@]host:_sd_hosts_or_user_at_host' \ + {-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ + '--scope[Run this as scope rather than service]' \ + '--unit=[Run under the specified unit name]:unit name' \ + {-p+,--property=}'[Set unit property]:NAME=VALUE:(( \ + CPUAccounting= MemoryAccounting= BlockIOAccounting= SendSIGHUP= \ + SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group= \ + DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth= \ + BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment= \ + KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA= \ + LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC= \ + LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE= \ + LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices= \ + PrivateNetwork= NoNewPrivileges= WorkingDirectory= RootDirectory= \ + TTYPath= SyslogIdentifier= SyslogLevelPrefix= SyslogLevel= \ + SyslogFacility= TimerSlackNSec= OOMScoreAdjust= ReadWritePaths= \ + ReadOnlyPaths= InaccessiblePaths= EnvironmentFile= \ + ProtectSystem= ProtectHome= RuntimeDirectory= PassEnvironment= \ + ))' \ + '--description=[Description for unit]:description' \ + '--slice=[Run in the specified slice]:slices:__systemd-run_slices' \ + {-r,--remain-after-exit}'[Leave service around until explicitly stopped]' \ + '--send-sighup[Send SIGHUP when terminating]' \ + '--service-type=[Service type]:type:(simple forking oneshot dbus notify idle)' \ + '--uid=[Run as system user]:user:_users' \ + '--gid=[Run as system group]:group:_groups' \ + '--nice=[Nice level]:nice level' \ + '--setenv=[Set environment]:NAME=VALUE' \ + '--on-active=[Run after SEC seconds]:SEC' \ + '--on-boot=[Run SEC seconds after machine was booted up]:SEC' \ + '--on-startup=[Run SEC seconds after systemd was first started]:SEC' \ + '--on-unit-active=[Run SEC seconds after the last activation]:SEC' \ + '--on-unit-inactive=[Run SEC seconds after the last deactivation]:SEC' \ + '--on-calendar=[Realtime timer]:SPEC' \ + '--timer-property=[Set timer unit property]:NAME=VALUE' \ + '--wait=[Wait until service stopped again]' \ + '*::command:_command' diff --git a/shell-completion/zsh/_systemd-tmpfiles b/shell-completion/zsh/_systemd-tmpfiles new file mode 100644 index 00000000..8860dc79 --- /dev/null +++ b/shell-completion/zsh/_systemd-tmpfiles @@ -0,0 +1,14 @@ +#compdef systemd-tmpfiles -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +_arguments \ + {-h,--help}'[Show help]' \ + '--version[Show package version]' \ + '--create[Create, set ownership/permissions based on the config files.]' \ + '--clean[Clean up all files and directories with an age parameter configured.]' \ + '--remove[All files and directories marked with r, R in the configuration files are removed.]' \ + '--boot[Execute actions only safe at boot]' \ + '--prefix=[Only apply rules that apply to paths with the specified prefix.]' \ + '--exclude-prefix=[Ignore rules that apply to paths with the specified prefix.]' \ + '--root=[Operate on an alternate filesystem root]:directory:_directories' \ + '*::files:_files' diff --git a/shell-completion/zsh/_timedatectl b/shell-completion/zsh/_timedatectl new file mode 100644 index 00000000..e2dabc79 --- /dev/null +++ b/shell-completion/zsh/_timedatectl @@ -0,0 +1,67 @@ +#compdef timedatectl -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +_timedatectl_set-timezone(){ + local -a _timezones + _timezones=( ${(f)"$(_call_program timezones "${service}" list-timezones)"} ) + compadd "$_timezones[@]" +} + +_timedatectl_set-time(){ + _message "YYYY-MM-DD HH:MM:SS" +} + +_timedatectl_set-local-rtc(){ + local -a _options + _options=( + '0:Maintain RTC in universal time' + '1:Maintain RTC in local time' + ) + _describe options _options +} + +_timedatectl_set-ntp(){ + local -a _options + _options=( + '0:Disable NTP based network time configuration' + '1:Enable NTP based network time configuration' + ) + _describe options _options +} + +_timedatectl_command(){ + local -a _timedatectl_cmds + _timedatectl_cmds=( + 'status:Show current time settings' + 'set-time:Set system time' + 'set-timezone:Set system timezone' + 'list-timezones:Show known timezones' + 'set-local-rtc:Control whether RTC is in local time' + 'set-ntp:Control whether NTP is enabled' + ) + if (( CURRENT == 1 )); then + _describe -t commands 'timedatectl command' _timedatectl_cmds + else + local curcontext="$curcontext" + cmd="${${_timedatectl_cmds[(r)$words[1]:*]%%:*}}" + if (( $#cmd )); then + if (( $+functions[_timedatectl_$cmd] )); then + _timedatectl_$cmd + else + _message "no more options" + fi + else + _message "unknown timedatectl command: $words[1]" + fi + fi +} + +_arguments -s \ + {-h,--help}'[Show this help]' \ + '--version[Show package version]' \ + '--adjust-system-clock[Adjust system clock when changing local RTC mode]' \ + '--no-pager[Do not pipe output into a pager]' \ + '--no-ask-password[Do not prompt for password]' \ + {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \ + {-M+,--machine=}'[Operate on local container]:machines:_sd_machines' \ + '*::timedatectl commands:_timedatectl_command' diff --git a/shell-completion/zsh/_udevadm b/shell-completion/zsh/_udevadm new file mode 100644 index 00000000..ad0b73d4 --- /dev/null +++ b/shell-completion/zsh/_udevadm @@ -0,0 +1,149 @@ +#compdef udevadm -*- shell-script -*- +# SPDX-License-Identifier: LGPL-2.1+ + +(( $+functions[_udevadm_info] )) || +_udevadm_info(){ + _arguments \ + '--query=[Query the database for specified type of device data. It needs the --path or --name to identify the specified device.]:type:(name symlink path property all)' \ + '--path=[The devpath of the device to query.]:sys files:_files -P /sys/ -W /sys' \ + '--name=[The name of the device node or a symlink to query]:device files:_files -P /dev/ -W /dev' \ + '--root[Print absolute paths in name or symlink query.]' \ + '--attribute-walk[Print all sysfs properties of the specified device that can be used in udev rules to match the specified device]' \ + '--export[Print output as key/value pairs.]' \ + '--export-prefix=[Add a prefix to the key name of exported values.]:prefix' \ + '--device-id-of-file=[Print major/minor numbers of the underlying device, where the file lives on.]:files:_udevadm_mounts' \ + '--export-db[Export the content of the udev database.]' \ + '--cleanup-db[Cleanup the udev database.]' +} + +(( $+functions[_udevadm_trigger] )) || +_udevadm_trigger(){ + _arguments \ + '--verbose[Print the list of devices which will be triggered.]' \ + '--dry-run[Do not actually trigger the event.]' \ + '--type=[Trigger a specific type of devices.]:types:(devices subsystems failed)' \ + '--action=[Type of event to be triggered.]:actions:(add change remove)' \ + '--subsystem-match=[Trigger events for devices which belong to a matching subsystem.]' \ + '--subsystem-nomatch=[Do not trigger events for devices which belong to a matching subsystem.]' \ + '--attr-match=attribute=[Trigger events for devices with a matching sysfs attribute.]' \ + '--attr-nomatch=attribute=[Do not trigger events for devices with a matching sysfs attribute.]' \ + '--property-match=[Trigger events for devices with a matching property value.]' \ + '--tag-match=property[Trigger events for devices with a matching tag.]' \ + '--sysname-match=[Trigger events for devices with a matching sys device name.]' \ + '--parent-match=[Trigger events for all children of a given device.]' +} + +(( $+functions[_udevadm_settle] )) || +_udevadm_settle(){ + _arguments \ + '--timeout=[Maximum number of seconds to wait for the event queue to become empty.]' \ + '--seq-start=[Wait only for events after the given sequence number.]' \ + '--seq-end=[Wait only for events before the given sequence number.]' \ + '--exit-if-exists=[Stop waiting if file exists.]:files:_files' \ + '--quiet[Do not print any output, like the remaining queue entries when reaching the timeout.]' \ + '--help[Print help text.]' +} + +(( $+functions[_udevadm_control] )) || +_udevadm_control(){ + _arguments \ + '--exit[Signal and wait for systemd-udevd to exit.]' \ + '--log-priority=[Set the internal log level of systemd-udevd.]:priorities:(err info debug)' \ + '--stop-exec-queue[Signal systemd-udevd to stop executing new events. Incoming events will be queued.]' \ + '--start-exec-queue[Signal systemd-udevd to enable the execution of events.]' \ + '--reload[Signal systemd-udevd to reload the rules files and other databases like the kernel module index.]' \ + '--property=[Set a global property for all events.]' \ + '--children-max=[Set the maximum number of events.]' \ + '--timeout=[The maximum number of seconds to wait for a reply from systemd-udevd.]' \ + '--help[Print help text.]' +} + +(( $+functions[_udevadm_monitor] )) || +_udevadm_monitor(){ + _arguments \ + '--kernel[Print the kernel uevents.]' \ + '--udev[Print the udev event after the rule processing.]' \ + '--property[Also print the properties of the event.]' \ + '--subsystem-match=[Filter events by subsystem/\[devtype\].]' \ + '--tag-match=[Filter events by property.]' \ + '--help[Print help text.]' +} + +(( $+functions[_udevadm_test] )) || +_udevadm_test(){ + _arguments \ + '--action=[The action string.]:actions:(add change remove)' \ + '--subsystem=[The subsystem string.]' \ + '--help[Print help text.]' \ + '*::devpath:_files -P /sys/ -W /sys' +} + +(( $+functions[_udevadm_test-builtin] )) || +_udevadm_test-builtin(){ + if (( CURRENT == 2 )); then + _arguments \ + '--help[Print help text]' \ + '*::builtins:(blkid btrfs hwdb input_id net_id net_setup_link kmod path_id usb_id uaccess)' + elif (( CURRENT == 3 )); then + _arguments \ + '--help[Print help text]' \ + '*::syspath:_files -P /sys -W /sys' + else + _arguments \ + '--help[Print help text]' + fi +} + +(( $+functions[_udevadm_mounts] )) || +_udevadm_mounts(){ + local dev_tmp dpath_tmp mp_tmp mline + + tmp=( "${(@f)$(< /proc/self/mounts)}" ) + dev_tmp=( "${(@)${(@)tmp%% *}:#none}" ) + mp_tmp=( "${(@)${(@)tmp#* }%% *}" ) + + local MATCH + mp_tmp=("${(@q)mp_tmp//(#m)\\[0-7](#c3)/${(#)$(( 8#${MATCH[2,-1]} ))}}") + dpath_tmp=( "${(@Mq)dev_tmp:#/*}" ) + dev_tmp=( "${(@q)dev_tmp:#/*}" ) + + _alternative \ + 'device-paths: device path:compadd -a dpath_tmp' \ + 'directories:mount point:compadd -a mp_tmp' +} + +(( $+functions[_udevadm_commands] )) || +_udevadm_commands(){ + local -a _udevadm_cmds + _udevadm_cmds=( + 'info:query sysfs or the udev database' + 'trigger:request events from the kernel' + 'settle:wait for the event queue to finish' + 'control:control the udev daemon' + 'monitor:listen to kernel and udev events' + 'test:test an event run' + 'test-builtin:test a built-in command' + ) + + if ((CURRENT == 1)); then + _describe -t commands 'udevadm commands' _udevadm_cmds + else + local curcontext="$curcontext" + cmd="${${_udevadm_cmds[(r)$words[1]:*]%%:*}}" + if (($#cmd)); then + if (( $+functions[_udevadm_$cmd] )); then + _udevadm_$cmd + else + _message "no options for $cmd" + fi + else + _message "no more options" + fi + fi +} + +_arguments \ + '--debug[Print debug messages to stderr]' \ + '--version[Print version number]' \ + '--help[Print help text]' \ + '*::udevadm commands:_udevadm_commands' diff --git a/shell-completion/zsh/meson.build b/shell-completion/zsh/meson.build new file mode 100644 index 00000000..6df9cc6a --- /dev/null +++ b/shell-completion/zsh/meson.build @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +zshcompletiondir = get_option('zshcompletiondir') +if zshcompletiondir == '' + zshcompletiondir = join_paths(datadir, 'zsh/site-functions') +endif + +if zshcompletiondir != 'no' + zsh_systemctl = configure_file( + input : '_systemctl.in', + output : '_systemctl', + configuration : substs) + + items = [['_busctl', ''], + ['_journalctl', ''], + ['_systemd-analyze', ''], + ['_systemd-delta', ''], + ['_systemd-nspawn', ''], + ['_systemd', ''], + ['_systemd-run', ''], + ['_udevadm', ''], + ['_kernel-install', ''], + ['_sd_hosts_or_user_at_host', ''], + ['_sd_outputmodes', ''], + ['_sd_unit_files', ''], + ['_sd_machines', ''], + [zsh_systemctl, ''], + ['_bootctl', 'ENABLE_EFI'], + ['_coredumpctl', 'ENABLE_COREDUMP'], + ['_hostnamectl', 'ENABLE_HOSTNAMED'], + ['_localectl', 'ENABLE_LOCALED'], + ['_loginctl', 'ENABLE_LOGIND'], + ['_machinectl', 'ENABLE_MACHINED'], + ['_networkctl', 'ENABLE_NETWORKD'], + ['_systemd-inhibit', 'ENABLE_LOGIND'], + ['_resolvectl', 'ENABLE_RESOLVE'], + ['_systemd-tmpfiles', 'ENABLE_TMPFILES'], + ['_timedatectl', 'ENABLE_TIMEDATED'], + ] + + foreach item : items + if item[1] == '' or conf.get(item[1]) == 1 + install_data(item[0], + install_dir : zshcompletiondir) + endif + endforeach +endif diff --git a/src/ac-power/ac-power.c b/src/ac-power/ac-power.c new file mode 100644 index 00000000..90ba5d2b --- /dev/null +++ b/src/ac-power/ac-power.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "main-func.h" +#include "util.h" + +static bool arg_verbose = false; + +static void help(void) { + printf("%s\n\n" + "Report whether we are connected to an external power source.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -v --verbose Show state as text\n" + , program_invocation_short_name); +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "verbose", no_argument, NULL, 'v' }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hv", options, NULL)) >= 0) + + switch (c) { + + case 'h': + help(); + return 0; + + case ARG_VERSION: + return version(); + + case 'v': + arg_verbose = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s takes no arguments.", + program_invocation_short_name); + + return 1; +} + +static int run(int argc, char *argv[]) { + int r; + + /* This is mostly intended to be used for scripts which want + * to detect whether AC power is plugged in or not. */ + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = on_ac_power(); + if (r < 0) + return log_error_errno(r, "Failed to read AC status: %m"); + + if (arg_verbose) + puts(yes_no(r)); + + return r == 0; +} + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/activate/activate.c b/src/activate/activate.c new file mode 100644 index 00000000..77b9a055 --- /dev/null +++ b/src/activate/activate.c @@ -0,0 +1,524 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "errno-util.h" +#include "escape.h" +#include "fd-util.h" +#include "log.h" +#include "macro.h" +#include "pretty-print.h" +#include "process-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "util.h" + +static char **arg_listen = NULL; +static bool arg_accept = false; +static int arg_socket_type = SOCK_STREAM; +static char **arg_args = NULL; +static char **arg_setenv = NULL; +static char **arg_fdnames = NULL; +static bool arg_inetd = false; + +static int add_epoll(int epoll_fd, int fd) { + struct epoll_event ev = { + .events = EPOLLIN, + .data.fd = fd, + }; + + assert(epoll_fd >= 0); + assert(fd >= 0); + + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) + return log_error_errno(errno, "Failed to add event on epoll fd:%d for fd:%d: %m", epoll_fd, fd); + + return 0; +} + +static int open_sockets(int *epoll_fd, bool accept) { + char **address; + int n, fd, r, count = 0; + + n = sd_listen_fds(true); + if (n < 0) + return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); + if (n > 0) { + log_info("Received %i descriptors via the environment.", n); + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { + r = fd_cloexec(fd, arg_accept); + if (r < 0) + return r; + + count++; + } + } + + /* Close logging and all other descriptors */ + if (arg_listen) { + _cleanup_free_ int *except = NULL; + int i; + + except = new(int, n); + if (!except) + return log_oom(); + + for (i = 0; i < n; i++) + except[i] = SD_LISTEN_FDS_START + i; + + log_close(); + r = close_all_fds(except, n); + if (r < 0) + return log_error_errno(r, "Failed to close all file descriptors: %m"); + } + + /** Note: we leak some fd's on error here. I doesn't matter + * much, since the program will exit immediately anyway, but + * would be a pain to fix. + */ + + STRV_FOREACH(address, arg_listen) { + fd = make_socket_fd(LOG_DEBUG, *address, arg_socket_type, (arg_accept * SOCK_CLOEXEC)); + if (fd < 0) { + log_open(); + return log_error_errno(fd, "Failed to open '%s': %m", *address); + } + + assert(fd == SD_LISTEN_FDS_START + count); + count++; + } + + if (arg_listen) + log_open(); + + *epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (*epoll_fd < 0) + return log_error_errno(errno, "Failed to create epoll object: %m"); + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + count; fd++) { + _cleanup_free_ char *name = NULL; + + getsockname_pretty(fd, &name); + log_info("Listening on %s as %i.", strna(name), fd); + + r = add_epoll(*epoll_fd, fd); + if (r < 0) + return r; + } + + return count; +} + +static int exec_process(const char *name, char **argv, char **env, int start_fd, size_t n_fds) { + + _cleanup_strv_free_ char **envp = NULL; + _cleanup_free_ char *joined = NULL; + size_t n_env = 0, length; + const char *tocopy; + char **s; + int r; + + if (arg_inetd && n_fds != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--inetd only supported for single file descriptors."); + + length = strv_length(arg_setenv); + + /* PATH, TERM, HOME, USER, LISTEN_FDS, LISTEN_PID, LISTEN_FDNAMES, NULL */ + envp = new0(char *, length + 8); + if (!envp) + return log_oom(); + + STRV_FOREACH(s, arg_setenv) { + + if (strchr(*s, '=')) { + char *k; + + k = strdup(*s); + if (!k) + return log_oom(); + + envp[n_env++] = k; + } else { + _cleanup_free_ char *p; + const char *n; + + p = strjoin(*s, "="); + if (!p) + return log_oom(); + + n = strv_find_prefix(env, p); + if (!n) + continue; + + envp[n_env] = strdup(n); + if (!envp[n_env]) + return log_oom(); + + n_env++; + } + } + + FOREACH_STRING(tocopy, "TERM=", "PATH=", "USER=", "HOME=") { + const char *n; + + n = strv_find_prefix(env, tocopy); + if (!n) + continue; + + envp[n_env] = strdup(n); + if (!envp[n_env]) + return log_oom(); + + n_env++; + } + + if (arg_inetd) { + assert(n_fds == 1); + + r = rearrange_stdio(start_fd, start_fd, STDERR_FILENO); /* invalidates start_fd on success + error */ + if (r < 0) + return log_error_errno(r, "Failed to move fd to stdin+stdout: %m"); + + } else { + if (start_fd != SD_LISTEN_FDS_START) { + assert(n_fds == 1); + + if (dup2(start_fd, SD_LISTEN_FDS_START) < 0) + return log_error_errno(errno, "Failed to dup connection: %m"); + + safe_close(start_fd); + start_fd = SD_LISTEN_FDS_START; + } + + if (asprintf((char **) (envp + n_env++), "LISTEN_FDS=%zu", n_fds) < 0) + return log_oom(); + + if (asprintf((char **) (envp + n_env++), "LISTEN_PID=" PID_FMT, getpid_cached()) < 0) + return log_oom(); + + if (arg_fdnames) { + _cleanup_free_ char *names = NULL; + size_t len; + char *e; + + len = strv_length(arg_fdnames); + if (len == 1) { + size_t i; + + for (i = 1; i < n_fds; i++) { + r = strv_extend(&arg_fdnames, arg_fdnames[0]); + if (r < 0) + return log_error_errno(r, "Failed to extend strv: %m"); + } + } else if (len != n_fds) + log_warning("The number of fd names is different than number of fds: %zu vs %zu", len, n_fds); + + names = strv_join(arg_fdnames, ":"); + if (!names) + return log_oom(); + + e = strjoin("LISTEN_FDNAMES=", names); + if (!e) + return log_oom(); + + envp[n_env++] = e; + } + } + + joined = strv_join(argv, " "); + if (!joined) + return log_oom(); + + log_info("Execing %s (%s)", name, joined); + execvpe(name, argv, envp); + + return log_error_errno(errno, "Failed to execp %s (%s): %m", name, joined); +} + +static int fork_and_exec_process(const char *child, char **argv, char **env, int fd) { + _cleanup_free_ char *joined = NULL; + pid_t child_pid; + int r; + + joined = strv_join(argv, " "); + if (!joined) + return log_oom(); + + r = safe_fork("(activate)", + FORK_RESET_SIGNALS | FORK_DEATHSIG | FORK_RLIMIT_NOFILE_SAFE | FORK_LOG, + &child_pid); + if (r < 0) + return r; + if (r == 0) { + /* In the child */ + exec_process(child, argv, env, fd, 1); + _exit(EXIT_FAILURE); + } + + log_info("Spawned %s (%s) as PID " PID_FMT ".", child, joined, child_pid); + return 0; +} + +static int do_accept(const char *name, char **argv, char **envp, int fd) { + _cleanup_free_ char *local = NULL, *peer = NULL; + _cleanup_close_ int fd_accepted = -1; + + fd_accepted = accept4(fd, NULL, NULL, 0); + if (fd_accepted < 0) { + if (ERRNO_IS_ACCEPT_AGAIN(errno)) + return 0; + + return log_error_errno(errno, "Failed to accept connection on fd:%d: %m", fd); + } + + (void) getsockname_pretty(fd_accepted, &local); + (void) getpeername_pretty(fd_accepted, true, &peer); + log_info("Connection from %s to %s", strna(peer), strna(local)); + + return fork_and_exec_process(name, argv, envp, fd_accepted); +} + +/* SIGCHLD handler. */ +static void sigchld_hdl(int sig) { + PROTECT_ERRNO; + + for (;;) { + siginfo_t si; + int r; + + si.si_pid = 0; + r = waitid(P_ALL, 0, &si, WEXITED | WNOHANG); + if (r < 0) { + if (errno != ECHILD) + log_error_errno(errno, "Failed to reap children: %m"); + return; + } + if (si.si_pid == 0) + return; + + log_info("Child %d died with code %d", si.si_pid, si.si_status); + } +} + +static int install_chld_handler(void) { + static const struct sigaction act = { + .sa_flags = SA_NOCLDSTOP | SA_RESTART, + .sa_handler = sigchld_hdl, + }; + + if (sigaction(SIGCHLD, &act, 0) < 0) + return log_error_errno(errno, "Failed to install SIGCHLD handler: %m"); + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-socket-activate", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n" + "\n%sListen on sockets and launch child on connection.%s\n" + "\nOptions:\n" + " -h --help Show this help and exit\n" + " --version Print version string and exit\n" + " -l --listen=ADDR Listen for raw connections at ADDR\n" + " -d --datagram Listen on datagram instead of stream socket\n" + " --seqpacket Listen on SOCK_SEQPACKET instead of stream socket\n" + " -a --accept Spawn separate child for each connection\n" + " -E --setenv=NAME[=VALUE] Pass an environment variable to children\n" + " --fdname=NAME[:NAME...] Specify names for file descriptors\n" + " --inetd Enable inetd file descriptor passing protocol\n" + "\nNote: file descriptors from sd_listen_fds() will be passed through.\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_FDNAME, + ARG_SEQPACKET, + ARG_INETD, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "datagram", no_argument, NULL, 'd' }, + { "seqpacket", no_argument, NULL, ARG_SEQPACKET }, + { "listen", required_argument, NULL, 'l' }, + { "accept", no_argument, NULL, 'a' }, + { "setenv", required_argument, NULL, 'E' }, + { "environment", required_argument, NULL, 'E' }, /* legacy alias */ + { "fdname", required_argument, NULL, ARG_FDNAME }, + { "inetd", no_argument, NULL, ARG_INETD }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "+hl:aE:d", options, NULL)) >= 0) + switch (c) { + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case 'l': + r = strv_extend(&arg_listen, optarg); + if (r < 0) + return log_oom(); + + break; + + case 'd': + if (arg_socket_type == SOCK_SEQPACKET) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--datagram may not be combined with --seqpacket."); + + arg_socket_type = SOCK_DGRAM; + break; + + case ARG_SEQPACKET: + if (arg_socket_type == SOCK_DGRAM) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--seqpacket may not be combined with --datagram."); + + arg_socket_type = SOCK_SEQPACKET; + break; + + case 'a': + arg_accept = true; + break; + + case 'E': + r = strv_extend(&arg_setenv, optarg); + if (r < 0) + return log_oom(); + + break; + + case ARG_FDNAME: { + _cleanup_strv_free_ char **names; + char **s; + + names = strv_split(optarg, ":"); + if (!names) + return log_oom(); + + STRV_FOREACH(s, names) + if (!fdname_is_valid(*s)) { + _cleanup_free_ char *esc; + + esc = cescape(*s); + log_warning("File descriptor name \"%s\" is not valid.", esc); + } + + /* Empty optargs means one empty name */ + r = strv_extend_strv(&arg_fdnames, + strv_isempty(names) ? STRV_MAKE("") : names, + false); + if (r < 0) + return log_error_errno(r, "strv_extend_strv: %m"); + break; + } + + case ARG_INETD: + arg_inetd = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind == argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: command to execute is missing.", + program_invocation_short_name); + + if (arg_socket_type == SOCK_DGRAM && arg_accept) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Datagram sockets do not accept connections. " + "The --datagram and --accept options may not be combined."); + + arg_args = argv + optind; + + return 1 /* work to do */; +} + +int main(int argc, char **argv, char **envp) { + int r, n; + int epoll_fd = -1; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + + r = install_chld_handler(); + if (r < 0) + return EXIT_FAILURE; + + n = open_sockets(&epoll_fd, arg_accept); + if (n < 0) + return EXIT_FAILURE; + if (n == 0) { + log_error("No sockets to listen on specified or passed in."); + return EXIT_FAILURE; + } + + for (;;) { + struct epoll_event event; + + if (epoll_wait(epoll_fd, &event, 1, -1) < 0) { + if (errno == EINTR) + continue; + + log_error_errno(errno, "epoll_wait() failed: %m"); + return EXIT_FAILURE; + } + + log_info("Communication attempt on fd %i.", event.data.fd); + if (arg_accept) { + r = do_accept(argv[optind], argv + optind, envp, event.data.fd); + if (r < 0) + return EXIT_FAILURE; + } else + break; + } + + exec_process(argv[optind], argv + optind, envp, SD_LISTEN_FDS_START, (size_t) n); + + return EXIT_SUCCESS; +} diff --git a/src/analyze/analyze-condition.c b/src/analyze/analyze-condition.c new file mode 100644 index 00000000..d0cefa09 --- /dev/null +++ b/src/analyze/analyze-condition.c @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "analyze-condition.h" +#include "condition.h" +#include "conf-parser.h" +#include "load-fragment.h" +#include "service.h" + +typedef struct condition_definition { + const char *name; + ConfigParserCallback parser; + ConditionType type; +} condition_definition; + +static const condition_definition condition_definitions[] = { + { "ConditionPathExists", config_parse_unit_condition_path, CONDITION_PATH_EXISTS }, + { "ConditionPathExistsGlob", config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB }, + { "ConditionPathIsDirectory", config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY }, + { "ConditionPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK }, + { "ConditionPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT }, + { "ConditionPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE }, + { "ConditionDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY }, + { "ConditionFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY }, + { "ConditionFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE }, + { "ConditionNeedsUpdate", config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE }, + { "ConditionFirstBoot", config_parse_unit_condition_string, CONDITION_FIRST_BOOT }, + { "ConditionKernelCommandLine", config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE }, + { "ConditionKernelVersion", config_parse_unit_condition_string, CONDITION_KERNEL_VERSION }, + { "ConditionArchitecture", config_parse_unit_condition_string, CONDITION_ARCHITECTURE }, + { "ConditionVirtualization", config_parse_unit_condition_string, CONDITION_VIRTUALIZATION }, + { "ConditionSecurity", config_parse_unit_condition_string, CONDITION_SECURITY }, + { "ConditionCapability", config_parse_unit_condition_string, CONDITION_CAPABILITY }, + { "ConditionHost", config_parse_unit_condition_string, CONDITION_HOST }, + { "ConditionACPower", config_parse_unit_condition_string, CONDITION_AC_POWER }, + { "ConditionUser", config_parse_unit_condition_string, CONDITION_USER }, + { "ConditionGroup", config_parse_unit_condition_string, CONDITION_GROUP }, + { "ConditionControlGroupController", config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER }, + + { "AssertPathExists", config_parse_unit_condition_path, CONDITION_PATH_EXISTS }, + { "AssertPathExistsGlob", config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB }, + { "AssertPathIsDirectory", config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY }, + { "AssertPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK }, + { "AssertPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT }, + { "AssertPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE }, + { "AssertDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY }, + { "AssertFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY }, + { "AssertFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE }, + { "AssertNeedsUpdate", config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE }, + { "AssertFirstBoot", config_parse_unit_condition_string, CONDITION_FIRST_BOOT }, + { "AssertKernelCommandLine", config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE }, + { "AssertKernelVersion", config_parse_unit_condition_string, CONDITION_KERNEL_VERSION }, + { "AssertArchitecture", config_parse_unit_condition_string, CONDITION_ARCHITECTURE }, + { "AssertVirtualization", config_parse_unit_condition_string, CONDITION_VIRTUALIZATION }, + { "AssertSecurity", config_parse_unit_condition_string, CONDITION_SECURITY }, + { "AssertCapability", config_parse_unit_condition_string, CONDITION_CAPABILITY }, + { "AssertHost", config_parse_unit_condition_string, CONDITION_HOST }, + { "AssertACPower", config_parse_unit_condition_string, CONDITION_AC_POWER }, + { "AssertUser", config_parse_unit_condition_string, CONDITION_USER }, + { "AssertGroup", config_parse_unit_condition_string, CONDITION_GROUP }, + { "AssertControlGroupController", config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER }, + + /* deprecated, but we should still parse them */ + { "ConditionNull", config_parse_unit_condition_null, 0 }, + { "AssertNull", config_parse_unit_condition_null, 0 }, +}; + +static int parse_condition(Unit *u, const char *line) { + const char *p; + Condition **target; + + if ((p = startswith(line, "Condition"))) + target = &u->conditions; + else if ((p = startswith(line, "Assert"))) + target = &u->asserts; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line); + + for (size_t i = 0; i < ELEMENTSOF(condition_definitions); i++) { + const condition_definition *c = &condition_definitions[i]; + + p = startswith(line, c->name); + if (!p) + continue; + p += strspn(p, WHITESPACE); + if (*p != '=') + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected \"=\" in \"%s\".", line); + + p += 1 + strspn(p + 1, WHITESPACE); + + return c->parser(NULL, "(stdin)", 0, NULL, 0, c->name, c->type, p, target, u); + } + + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line); +} + +_printf_(7, 8) +static int log_helper(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) { + Unit *u = userdata; + va_list ap; + int r; + + assert(u); + + /* "upgrade" debug messages */ + level = MIN(LOG_INFO, level); + + va_start(ap, format); + r = log_object_internalv(level, error, file, line, func, + NULL, + u->id, + NULL, + NULL, + format, ap); + va_end(ap); + + return r; +} + +int verify_conditions(char **lines, UnitFileScope scope) { + _cleanup_(manager_freep) Manager *m = NULL; + Unit *u; + char **line; + int r, q = 1; + + r = manager_new(scope, MANAGER_TEST_RUN_MINIMAL, &m); + if (r < 0) + return log_error_errno(r, "Failed to initialize manager: %m"); + + log_debug("Starting manager..."); + r = manager_startup(m, NULL, NULL); + if (r < 0) + return r; + + r = unit_new_for_name(m, sizeof(Service), "test.service", &u); + if (r < 0) + return log_error_errno(r, "Failed to create test.service: %m"); + + STRV_FOREACH(line, lines) { + r = parse_condition(u, *line); + if (r < 0) + return r; + } + + r = condition_test_list(u->asserts, assert_type_to_string, log_helper, u); + if (u->asserts) + log_notice("Asserts %s.", r > 0 ? "succeeded" : "failed"); + + q = condition_test_list(u->conditions, condition_type_to_string, log_helper, u); + if (u->conditions) + log_notice("Conditions %s.", q > 0 ? "succeeded" : "failed"); + + return r > 0 && q > 0 ? 0 : -EIO; +} diff --git a/src/analyze/analyze-condition.h b/src/analyze/analyze-condition.h new file mode 100644 index 00000000..2ef278eb --- /dev/null +++ b/src/analyze/analyze-condition.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "install.h" + +int verify_conditions(char **lines, UnitFileScope scope); diff --git a/src/analyze/analyze-security.c b/src/analyze/analyze-security.c new file mode 100644 index 00000000..aadc9d51 --- /dev/null +++ b/src/analyze/analyze-security.c @@ -0,0 +1,2147 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "analyze-security.h" +#include "bus-error.h" +#include "bus-unit-util.h" +#include "bus-util.h" +#include "env-util.h" +#include "format-table.h" +#include "in-addr-util.h" +#include "locale-util.h" +#include "macro.h" +#include "missing_capability.h" +#include "missing_sched.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#if HAVE_SECCOMP +# include "seccomp-util.h" +#endif +#include "set.h" +#include "stdio-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "unit-def.h" +#include "unit-name.h" + +struct security_info { + char *id; + char *type; + char *load_state; + char *fragment_path; + bool default_dependencies; + + uint64_t ambient_capabilities; + uint64_t capability_bounding_set; + + char *user; + char **supplementary_groups; + bool dynamic_user; + + bool ip_address_deny_all; + bool ip_address_allow_localhost; + bool ip_address_allow_other; + + bool ip_filters_custom_ingress; + bool ip_filters_custom_egress; + + char *keyring_mode; + bool lock_personality; + bool memory_deny_write_execute; + bool no_new_privileges; + char *notify_access; + bool protect_hostname; + + bool private_devices; + bool private_mounts; + bool private_network; + bool private_tmp; + bool private_users; + + bool protect_control_groups; + bool protect_kernel_modules; + bool protect_kernel_tunables; + bool protect_kernel_logs; + + char *protect_home; + char *protect_system; + + bool remove_ipc; + + bool restrict_address_family_inet; + bool restrict_address_family_unix; + bool restrict_address_family_netlink; + bool restrict_address_family_packet; + bool restrict_address_family_other; + + uint64_t restrict_namespaces; + bool restrict_realtime; + bool restrict_suid_sgid; + + char *root_directory; + char *root_image; + + bool delegate; + char *device_policy; + bool device_allow_non_empty; + + char **system_call_architectures; + + bool system_call_filter_whitelist; + Set *system_call_filter; + + uint32_t _umask; +}; + +struct security_assessor { + const char *id; + const char *description_good; + const char *description_bad; + const char *description_na; + const char *url; + uint64_t weight; + uint64_t range; + int (*assess)( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description); + size_t offset; + uint64_t parameter; + bool default_dependencies_only; +}; + +static void security_info_free(struct security_info *i) { + if (!i) + return; + + free(i->id); + free(i->type); + free(i->load_state); + free(i->fragment_path); + + free(i->user); + + free(i->protect_home); + free(i->protect_system); + + free(i->root_directory); + free(i->root_image); + + free(i->keyring_mode); + free(i->notify_access); + + free(i->device_policy); + + strv_free(i->supplementary_groups); + strv_free(i->system_call_architectures); + + set_free_free(i->system_call_filter); +} + +static bool security_info_runs_privileged(const struct security_info *i) { + assert(i); + + if (STRPTR_IN_SET(i->user, "0", "root")) + return true; + + if (i->dynamic_user) + return false; + + return isempty(i->user); +} + +static int assess_bool( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + const bool *b = data; + + assert(b); + assert(ret_badness); + assert(ret_description); + + *ret_badness = a->parameter ? *b : !*b; + *ret_description = NULL; + + return 0; +} + +static int assess_user( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + _cleanup_free_ char *d = NULL; + uint64_t b; + + assert(ret_badness); + assert(ret_description); + + if (streq_ptr(info->user, NOBODY_USER_NAME)) { + d = strdup("Service runs under as '" NOBODY_USER_NAME "' user, which should not be used for services"); + b = 9; + } else if (info->dynamic_user && !STR_IN_SET(info->user, "0", "root")) { + d = strdup("Service runs under a transient non-root user identity"); + b = 0; + } else if (info->user && !STR_IN_SET(info->user, "0", "root", "")) { + d = strdup("Service runs under a static non-root user identity"); + b = 0; + } else { + *ret_badness = 10; + *ret_description = NULL; + return 0; + } + + if (!d) + return log_oom(); + + *ret_badness = b; + *ret_description = TAKE_PTR(d); + + return 0; +} + +static int assess_protect_home( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + const char *description; + uint64_t badness; + char *copy; + int r; + + assert(ret_badness); + assert(ret_description); + + badness = 10; + description = "Service has full access to home directories"; + + r = parse_boolean(info->protect_home); + if (r < 0) { + if (streq_ptr(info->protect_home, "read-only")) { + badness = 5; + description = "Service has read-only access to home directories"; + } else if (streq_ptr(info->protect_home, "tmpfs")) { + badness = 1; + description = "Service has access to fake empty home directories"; + } + } else if (r > 0) { + badness = 0; + description = "Service has no access to home directories"; + } + + copy = strdup(description); + if (!copy) + return log_oom(); + + *ret_badness = badness; + *ret_description = copy; + + return 0; +} + +static int assess_protect_system( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + const char *description; + uint64_t badness; + char *copy; + int r; + + assert(ret_badness); + assert(ret_description); + + badness = 10; + description = "Service has full access to the OS file hierarchy"; + + r = parse_boolean(info->protect_system); + if (r < 0) { + if (streq_ptr(info->protect_system, "full")) { + badness = 3; + description = "Service has very limited write access to the OS file hierarchy"; + } else if (streq_ptr(info->protect_system, "strict")) { + badness = 0; + description = "Service has strict read-only access to the OS file hierarchy"; + } + } else if (r > 0) { + badness = 5; + description = "Service has limited write access to the OS file hierarchy"; + } + + copy = strdup(description); + if (!copy) + return log_oom(); + + *ret_badness = badness; + *ret_description = copy; + + return 0; +} + +static int assess_root_directory( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + assert(ret_badness); + assert(ret_description); + + *ret_badness = + empty_or_root(info->root_directory) && + empty_or_root(info->root_image); + *ret_description = NULL; + + return 0; +} + +static int assess_capability_bounding_set( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + assert(ret_badness); + assert(ret_description); + + *ret_badness = !!(info->capability_bounding_set & a->parameter); + *ret_description = NULL; + + return 0; +} + +static int assess_umask( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + char *copy = NULL; + const char *d; + uint64_t b; + + assert(ret_badness); + assert(ret_description); + + if (!FLAGS_SET(info->_umask, 0002)) { + d = "Files created by service are world-writable by default"; + b = 10; + } else if (!FLAGS_SET(info->_umask, 0004)) { + d = "Files created by service are world-readable by default"; + b = 5; + } else if (!FLAGS_SET(info->_umask, 0020)) { + d = "Files created by service are group-writable by default"; + b = 2; + } else if (!FLAGS_SET(info->_umask, 0040)) { + d = "Files created by service are group-readable by default"; + b = 1; + } else { + d = "Files created by service are accessible only by service's own user by default"; + b = 0; + } + + copy = strdup(d); + if (!copy) + return log_oom(); + + *ret_badness = b; + *ret_description = copy; + + return 0; +} + +static int assess_keyring_mode( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + assert(ret_badness); + assert(ret_description); + + *ret_badness = !streq_ptr(info->keyring_mode, "private"); + *ret_description = NULL; + + return 0; +} + +static int assess_notify_access( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + assert(ret_badness); + assert(ret_description); + + *ret_badness = streq_ptr(info->notify_access, "all"); + *ret_description = NULL; + + return 0; +} + +static int assess_remove_ipc( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + assert(ret_badness); + assert(ret_description); + + if (security_info_runs_privileged(info)) + *ret_badness = UINT64_MAX; + else + *ret_badness = !info->remove_ipc; + + *ret_description = NULL; + return 0; +} + +static int assess_supplementary_groups( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + assert(ret_badness); + assert(ret_description); + + if (security_info_runs_privileged(info)) + *ret_badness = UINT64_MAX; + else + *ret_badness = !strv_isempty(info->supplementary_groups); + + *ret_description = NULL; + return 0; +} + +static int assess_restrict_namespaces( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + assert(ret_badness); + assert(ret_description); + + *ret_badness = !!(info->restrict_namespaces & a->parameter); + *ret_description = NULL; + + return 0; +} + +static int assess_system_call_architectures( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + char *d; + uint64_t b; + + assert(ret_badness); + assert(ret_description); + + if (strv_isempty(info->system_call_architectures)) { + b = 10; + d = strdup("Service may execute system calls with all ABIs"); + } else if (strv_equal(info->system_call_architectures, STRV_MAKE("native"))) { + b = 0; + d = strdup("Service may execute system calls only with native ABI"); + } else { + b = 8; + d = strdup("Service may execute system calls with multiple ABIs"); + } + + if (!d) + return log_oom(); + + *ret_badness = b; + *ret_description = d; + + return 0; +} + +#if HAVE_SECCOMP + +static bool syscall_names_in_filter(Set *s, bool whitelist, const SyscallFilterSet *f) { + const char *syscall; + + NULSTR_FOREACH(syscall, f->value) { + int id; + + if (syscall[0] == '@') { + const SyscallFilterSet *g; + + assert_se(g = syscall_filter_set_find(syscall)); + if (syscall_names_in_filter(s, whitelist, g)) + return true; /* bad! */ + + continue; + } + + /* Let's see if the system call actually exists on this platform, before complaining */ + id = seccomp_syscall_resolve_name(syscall); + if (id < 0) + continue; + + if (set_contains(s, syscall) == whitelist) { + log_debug("Offending syscall filter item: %s", syscall); + return true; /* bad! */ + } + } + + return false; +} + +static int assess_system_call_filter( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + const SyscallFilterSet *f; + char *d = NULL; + uint64_t b; + + assert(a); + assert(info); + assert(ret_badness); + assert(ret_description); + + assert(a->parameter < _SYSCALL_FILTER_SET_MAX); + f = syscall_filter_sets + a->parameter; + + if (!info->system_call_filter_whitelist && set_isempty(info->system_call_filter)) { + d = strdup("Service does not filter system calls"); + b = 10; + } else { + bool bad; + + log_debug("Analyzing system call filter, checking against: %s", f->name); + bad = syscall_names_in_filter(info->system_call_filter, info->system_call_filter_whitelist, f); + log_debug("Result: %s", bad ? "bad" : "good"); + + if (info->system_call_filter_whitelist) { + if (bad) { + (void) asprintf(&d, "System call whitelist defined for service, and %s is included", f->name); + b = 9; + } else { + (void) asprintf(&d, "System call whitelist defined for service, and %s is not included", f->name); + b = 0; + } + } else { + if (bad) { + (void) asprintf(&d, "System call blacklist defined for service, and %s is not included", f->name); + b = 10; + } else { + (void) asprintf(&d, "System call blacklist defined for service, and %s is included", f->name); + b = 5; + } + } + } + + if (!d) + return log_oom(); + + *ret_badness = b; + *ret_description = d; + + return 0; +} + +#endif + +static int assess_ip_address_allow( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + char *d = NULL; + uint64_t b; + + assert(info); + assert(ret_badness); + assert(ret_description); + + if (info->ip_filters_custom_ingress || info->ip_filters_custom_egress) { + d = strdup("Service defines custom ingress/egress IP filters with BPF programs"); + b = 0; + } else if (!info->ip_address_deny_all) { + d = strdup("Service does not define an IP address whitelist"); + b = 10; + } else if (info->ip_address_allow_other) { + d = strdup("Service defines IP address whitelist with non-localhost entries"); + b = 5; + } else if (info->ip_address_allow_localhost) { + d = strdup("Service defines IP address whitelist with only localhost entries"); + b = 2; + } else { + d = strdup("Service blocks all IP address ranges"); + b = 0; + } + + if (!d) + return log_oom(); + + *ret_badness = b; + *ret_description = d; + + return 0; +} + +static int assess_device_allow( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + char *d = NULL; + uint64_t b; + + assert(info); + assert(ret_badness); + assert(ret_description); + + if (STRPTR_IN_SET(info->device_policy, "strict", "closed")) { + + if (info->device_allow_non_empty) { + d = strdup("Service has a device ACL with some special devices"); + b = 5; + } else { + d = strdup("Service has a minimal device ACL"); + b = 0; + } + } else { + d = strdup("Service has no device ACL"); + b = 10; + } + + if (!d) + return log_oom(); + + *ret_badness = b; + *ret_description = d; + + return 0; +} + +static int assess_ambient_capabilities( + const struct security_assessor *a, + const struct security_info *info, + const void *data, + uint64_t *ret_badness, + char **ret_description) { + + assert(ret_badness); + assert(ret_description); + + *ret_badness = info->ambient_capabilities != 0; + *ret_description = NULL; + + return 0; +} + +static const struct security_assessor security_assessor_table[] = { + { + .id = "User=/DynamicUser=", + .description_bad = "Service runs as root user", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#User=", + .weight = 2000, + .range = 10, + .assess = assess_user, + }, + { + .id = "SupplementaryGroups=", + .description_good = "Service has no supplementary groups", + .description_bad = "Service runs with supplementary groups", + .description_na = "Service runs as root, option does not matter", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SupplementaryGroups=", + .weight = 200, + .range = 1, + .assess = assess_supplementary_groups, + }, + { + .id = "PrivateDevices=", + .description_good = "Service has no access to hardware devices", + .description_bad = "Service potentially has access to hardware devices", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateDevices=", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, private_devices), + }, + { + .id = "PrivateMounts=", + .description_good = "Service cannot install system mounts", + .description_bad = "Service may install system mounts", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateMounts=", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, private_mounts), + }, + { + .id = "PrivateNetwork=", + .description_good = "Service has no access to the host's network", + .description_bad = "Service has access to the host's network", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateNetwork=", + .weight = 2500, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, private_network), + }, + { + .id = "PrivateTmp=", + .description_good = "Service has no access to other software's temporary files", + .description_bad = "Service has access to other software's temporary files", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp=", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, private_tmp), + .default_dependencies_only = true, + }, + { + .id = "PrivateUsers=", + .description_good = "Service does not have access to other users", + .description_bad = "Service has access to other users", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateUsers=", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, private_users), + }, + { + .id = "ProtectControlGroups=", + .description_good = "Service cannot modify the control group file system", + .description_bad = "Service may modify the control group file system", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectControlGroups=", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, protect_control_groups), + }, + { + .id = "ProtectKernelModules=", + .description_good = "Service cannot load or read kernel modules", + .description_bad = "Service may load or read kernel modules", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelModules=", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, protect_kernel_modules), + }, + { + .id = "ProtectKernelTunables=", + .description_good = "Service cannot alter kernel tunables (/proc/sys, …)", + .description_bad = "Service may alter kernel tunables", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelTunables=", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, protect_kernel_tunables), + }, + { + .id = "ProtectKernelLogs=", + .description_good = "Service cannot read from or write to the kernel log ring buffer", + .description_bad = "Service may read from or write to the kernel log ring buffer", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelLogs=", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, protect_kernel_logs), + }, + { + .id = "ProtectHome=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome=", + .weight = 1000, + .range = 10, + .assess = assess_protect_home, + .default_dependencies_only = true, + }, + { + .id = "ProtectHostname=", + .description_good = "Service cannot change system host/domainname", + .description_bad = "Service may change system host/domainname", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHostname=", + .weight = 50, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, protect_hostname), + }, + { + .id = "ProtectSystem=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectSystem=", + .weight = 1000, + .range = 10, + .assess = assess_protect_system, + .default_dependencies_only = true, + }, + { + .id = "RootDirectory=/RootImage=", + .description_good = "Service has its own root directory/image", + .description_bad = "Service runs within the host's root directory", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RootDirectory=", + .weight = 200, + .range = 1, + .assess = assess_root_directory, + .default_dependencies_only = true, + }, + { + .id = "LockPersonality=", + .description_good = "Service cannot change ABI personality", + .description_bad = "Service may change ABI personality", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LockPersonality=", + .weight = 100, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, lock_personality), + }, + { + .id = "MemoryDenyWriteExecute=", + .description_good = "Service cannot create writable executable memory mappings", + .description_bad = "Service may create writable executable memory mappings", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#MemoryDenyWriteExecute=", + .weight = 100, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, memory_deny_write_execute), + }, + { + .id = "NoNewPrivileges=", + .description_good = "Service processes cannot acquire new privileges", + .description_bad = "Service processes may acquire new privileges", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NoNewPrivileges=", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, no_new_privileges), + }, + { + .id = "CapabilityBoundingSet=~CAP_SYS_ADMIN", + .description_good = "Service has no administrator privileges", + .description_bad = "Service has administrator privileges", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 1500, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = UINT64_C(1) << CAP_SYS_ADMIN, + }, + { + .id = "CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP)", + .description_good = "Service cannot change UID/GID identities/capabilities", + .description_bad = "Service may change UID/GID identities/capabilities", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 1500, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_SETUID)| + (UINT64_C(1) << CAP_SETGID)| + (UINT64_C(1) << CAP_SETPCAP), + }, + { + .id = "CapabilityBoundingSet=~CAP_SYS_PTRACE", + .description_good = "Service has no ptrace() debugging abilities", + .description_bad = "Service has ptrace() debugging abilities", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 1500, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_SYS_PTRACE), + }, + { + .id = "CapabilityBoundingSet=~CAP_SYS_TIME", + .description_good = "Service processes cannot change the system clock", + .description_bad = "Service processes may change the system clock", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 1000, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = UINT64_C(1) << CAP_SYS_TIME, + }, + { + .id = "CapabilityBoundingSet=~CAP_NET_ADMIN", + .description_good = "Service has no network configuration privileges", + .description_bad = "Service has network configuration privileges", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 1000, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_NET_ADMIN), + }, + { + .id = "CapabilityBoundingSet=~CAP_RAWIO", + .description_good = "Service has no raw I/O access", + .description_bad = "Service has raw I/O access", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 1000, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_SYS_RAWIO), + }, + { + .id = "CapabilityBoundingSet=~CAP_SYS_MODULE", + .description_good = "Service cannot load kernel modules", + .description_bad = "Service may load kernel modules", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 1000, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_SYS_MODULE), + }, + { + .id = "CapabilityBoundingSet=~CAP_AUDIT_*", + .description_good = "Service has no audit subsystem access", + .description_bad = "Service has audit subsystem access", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 500, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_AUDIT_CONTROL) | + (UINT64_C(1) << CAP_AUDIT_READ) | + (UINT64_C(1) << CAP_AUDIT_WRITE), + }, + { + .id = "CapabilityBoundingSet=~CAP_SYSLOG", + .description_good = "Service has no access to kernel logging", + .description_bad = "Service has access to kernel logging", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 500, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_SYSLOG), + }, + { + .id = "CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE)", + .description_good = "Service has no privileges to change resource use parameters", + .description_bad = "Service has privileges to change resource use parameters", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 500, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_SYS_NICE) | + (UINT64_C(1) << CAP_SYS_RESOURCE), + }, + { + .id = "CapabilityBoundingSet=~CAP_MKNOD", + .description_good = "Service cannot create device nodes", + .description_bad = "Service may create device nodes", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 500, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_MKNOD), + }, + { + .id = "CapabilityBoundingSet=~CAP_(CHOWN|FSETID|SETFCAP)", + .description_good = "Service cannot change file ownership/access mode/capabilities", + .description_bad = "Service may change file ownership/access mode/capabilities unrestricted", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 1000, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_CHOWN) | + (UINT64_C(1) << CAP_FSETID) | + (UINT64_C(1) << CAP_SETFCAP), + }, + { + .id = "CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER)", + .description_good = "Service cannot override UNIX file/IPC permission checks", + .description_bad = "Service may override UNIX file/IPC permission checks", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 1000, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_DAC_OVERRIDE) | + (UINT64_C(1) << CAP_DAC_READ_SEARCH) | + (UINT64_C(1) << CAP_FOWNER) | + (UINT64_C(1) << CAP_IPC_OWNER), + }, + { + .id = "CapabilityBoundingSet=~CAP_KILL", + .description_good = "Service cannot send UNIX signals to arbitrary processes", + .description_bad = "Service may send UNIX signals to arbitrary processes", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 500, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_KILL), + }, + { + .id = "CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW)", + .description_good = "Service has no elevated networking privileges", + .description_bad = "Service has elevated networking privileges", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 500, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_NET_BIND_SERVICE) | + (UINT64_C(1) << CAP_NET_BROADCAST) | + (UINT64_C(1) << CAP_NET_RAW), + }, + { + .id = "CapabilityBoundingSet=~CAP_SYS_BOOT", + .description_good = "Service cannot issue reboot()", + .description_bad = "Service may issue reboot()", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 100, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_SYS_BOOT), + }, + { + .id = "CapabilityBoundingSet=~CAP_MAC_*", + .description_good = "Service cannot adjust SMACK MAC", + .description_bad = "Service may adjust SMACK MAC", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 100, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_MAC_ADMIN)| + (UINT64_C(1) << CAP_MAC_OVERRIDE), + }, + { + .id = "CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE", + .description_good = "Service cannot mark files immutable", + .description_bad = "Service may mark files immutable", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 75, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_LINUX_IMMUTABLE), + }, + { + .id = "CapabilityBoundingSet=~CAP_IPC_LOCK", + .description_good = "Service cannot lock memory into RAM", + .description_bad = "Service may lock memory into RAM", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 50, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_IPC_LOCK), + }, + { + .id = "CapabilityBoundingSet=~CAP_SYS_CHROOT", + .description_good = "Service cannot issue chroot()", + .description_bad = "Service may issue chroot()", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 50, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_SYS_CHROOT), + }, + { + .id = "CapabilityBoundingSet=~CAP_BLOCK_SUSPEND", + .description_good = "Service cannot establish wake locks", + .description_bad = "Service may establish wake locks", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 25, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_BLOCK_SUSPEND), + }, + { + .id = "CapabilityBoundingSet=~CAP_WAKE_ALARM", + .description_good = "Service cannot program timers that wake up the system", + .description_bad = "Service may program timers that wake up the system", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 25, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_WAKE_ALARM), + }, + { + .id = "CapabilityBoundingSet=~CAP_LEASE", + .description_good = "Service cannot create file leases", + .description_bad = "Service may create file leases", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 25, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_LEASE), + }, + { + .id = "CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG", + .description_good = "Service cannot issue vhangup()", + .description_bad = "Service may issue vhangup()", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 25, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_SYS_TTY_CONFIG), + }, + { + .id = "CapabilityBoundingSet=~CAP_SYS_PACCT", + .description_good = "Service cannot use acct()", + .description_bad = "Service may use acct()", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=", + .weight = 25, + .range = 1, + .assess = assess_capability_bounding_set, + .parameter = (UINT64_C(1) << CAP_SYS_PACCT), + }, + { + .id = "UMask=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#UMask=", + .weight = 100, + .range = 10, + .assess = assess_umask, + }, + { + .id = "KeyringMode=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#KeyringMode=", + .description_good = "Service doesn't share key material with other services", + .description_bad = "Service shares key material with other service", + .weight = 1000, + .range = 1, + .assess = assess_keyring_mode, + }, + { + .id = "NotifyAccess=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NotifyAccess=", + .description_good = "Service child processes cannot alter service state", + .description_bad = "Service child processes may alter service state", + .weight = 1000, + .range = 1, + .assess = assess_notify_access, + }, + { + .id = "RemoveIPC=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RemoveIPC=", + .description_good = "Service user cannot leave SysV IPC objects around", + .description_bad = "Service user may leave SysV IPC objects around", + .description_na = "Service runs as root, option does not apply", + .weight = 100, + .range = 1, + .assess = assess_remove_ipc, + .offset = offsetof(struct security_info, remove_ipc), + }, + { + .id = "Delegate=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Delegate=", + .description_good = "Service does not maintain its own delegated control group subtree", + .description_bad = "Service maintains its own delegated control group subtree", + .weight = 100, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, delegate), + .parameter = true, /* invert! */ + }, + { + .id = "RestrictRealtime=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictRealtime=", + .description_good = "Service realtime scheduling access is restricted", + .description_bad = "Service may acquire realtime scheduling", + .weight = 500, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, restrict_realtime), + }, + { + .id = "RestrictSUIDSGID=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictSUIDSGID=", + .description_good = "SUID/SGID file creation by service is restricted", + .description_bad = "Service may create SUID/SGID files", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, restrict_suid_sgid), + }, + { + .id = "RestrictNamespaces=~CLONE_NEWUSER", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", + .description_good = "Service cannot create user namespaces", + .description_bad = "Service may create user namespaces", + .weight = 1500, + .range = 1, + .assess = assess_restrict_namespaces, + .parameter = CLONE_NEWUSER, + }, + { + .id = "RestrictNamespaces=~CLONE_NEWNS", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", + .description_good = "Service cannot create file system namespaces", + .description_bad = "Service may create file system namespaces", + .weight = 500, + .range = 1, + .assess = assess_restrict_namespaces, + .parameter = CLONE_NEWNS, + }, + { + .id = "RestrictNamespaces=~CLONE_NEWIPC", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", + .description_good = "Service cannot create IPC namespaces", + .description_bad = "Service may create IPC namespaces", + .weight = 500, + .range = 1, + .assess = assess_restrict_namespaces, + .parameter = CLONE_NEWIPC, + }, + { + .id = "RestrictNamespaces=~CLONE_NEWPID", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", + .description_good = "Service cannot create process namespaces", + .description_bad = "Service may create process namespaces", + .weight = 500, + .range = 1, + .assess = assess_restrict_namespaces, + .parameter = CLONE_NEWPID, + }, + { + .id = "RestrictNamespaces=~CLONE_NEWCGROUP", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", + .description_good = "Service cannot create cgroup namespaces", + .description_bad = "Service may create cgroup namespaces", + .weight = 500, + .range = 1, + .assess = assess_restrict_namespaces, + .parameter = CLONE_NEWCGROUP, + }, + { + .id = "RestrictNamespaces=~CLONE_NEWNET", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", + .description_good = "Service cannot create network namespaces", + .description_bad = "Service may create network namespaces", + .weight = 500, + .range = 1, + .assess = assess_restrict_namespaces, + .parameter = CLONE_NEWNET, + }, + { + .id = "RestrictNamespaces=~CLONE_NEWUTS", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", + .description_good = "Service cannot create hostname namespaces", + .description_bad = "Service may create hostname namespaces", + .weight = 100, + .range = 1, + .assess = assess_restrict_namespaces, + .parameter = CLONE_NEWUTS, + }, + { + .id = "RestrictAddressFamilies=~AF_(INET|INET6)", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=", + .description_good = "Service cannot allocate Internet sockets", + .description_bad = "Service may allocate Internet sockets", + .weight = 1500, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, restrict_address_family_inet), + }, + { + .id = "RestrictAddressFamilies=~AF_UNIX", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=", + .description_good = "Service cannot allocate local sockets", + .description_bad = "Service may allocate local sockets", + .weight = 25, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, restrict_address_family_unix), + }, + { + .id = "RestrictAddressFamilies=~AF_NETLINK", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=", + .description_good = "Service cannot allocate netlink sockets", + .description_bad = "Service may allocate netlink sockets", + .weight = 200, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, restrict_address_family_netlink), + }, + { + .id = "RestrictAddressFamilies=~AF_PACKET", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=", + .description_good = "Service cannot allocate packet sockets", + .description_bad = "Service may allocate packet sockets", + .weight = 1000, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, restrict_address_family_packet), + }, + { + .id = "RestrictAddressFamilies=~…", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=", + .description_good = "Service cannot allocate exotic sockets", + .description_bad = "Service may allocate exotic sockets", + .weight = 1250, + .range = 1, + .assess = assess_bool, + .offset = offsetof(struct security_info, restrict_address_family_other), + }, + { + .id = "SystemCallArchitectures=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallArchitectures=", + .weight = 1000, + .range = 10, + .assess = assess_system_call_architectures, + }, +#if HAVE_SECCOMP + { + .id = "SystemCallFilter=~@swap", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 1000, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_SWAP, + }, + { + .id = "SystemCallFilter=~@obsolete", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 250, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_OBSOLETE, + }, + { + .id = "SystemCallFilter=~@clock", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 1000, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_CLOCK, + }, + { + .id = "SystemCallFilter=~@cpu-emulation", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 250, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_CPU_EMULATION, + }, + { + .id = "SystemCallFilter=~@debug", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 1000, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_DEBUG, + }, + { + .id = "SystemCallFilter=~@mount", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 1000, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_MOUNT, + }, + { + .id = "SystemCallFilter=~@module", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 1000, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_MODULE, + }, + { + .id = "SystemCallFilter=~@raw-io", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 1000, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_RAW_IO, + }, + { + .id = "SystemCallFilter=~@reboot", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 1000, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_REBOOT, + }, + { + .id = "SystemCallFilter=~@privileged", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 700, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_PRIVILEGED, + }, + { + .id = "SystemCallFilter=~@resources", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=", + .weight = 700, + .range = 10, + .assess = assess_system_call_filter, + .parameter = SYSCALL_FILTER_SET_RESOURCES, + }, +#endif + { + .id = "IPAddressDeny=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#IPAddressDeny=", + .weight = 1000, + .range = 10, + .assess = assess_ip_address_allow, + }, + { + .id = "DeviceAllow=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#DeviceAllow=", + .weight = 1000, + .range = 10, + .assess = assess_device_allow, + }, + { + .id = "AmbientCapabilities=", + .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#AmbientCapabilities=", + .description_good = "Service process does not receive ambient capabilities", + .description_bad = "Service process receives ambient capabilities", + .weight = 500, + .range = 1, + .assess = assess_ambient_capabilities, + }, +}; + +static int assess(const struct security_info *info, Table *overview_table, AnalyzeSecurityFlags flags) { + static const struct { + uint64_t exposure; + const char *name; + const char *color; + SpecialGlyph smiley; + } badness_table[] = { + { 100, "DANGEROUS", ANSI_HIGHLIGHT_RED, SPECIAL_GLYPH_DEPRESSED_SMILEY }, + { 90, "UNSAFE", ANSI_HIGHLIGHT_RED, SPECIAL_GLYPH_UNHAPPY_SMILEY }, + { 75, "EXPOSED", ANSI_HIGHLIGHT_YELLOW, SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY }, + { 50, "MEDIUM", NULL, SPECIAL_GLYPH_NEUTRAL_SMILEY }, + { 10, "OK", ANSI_HIGHLIGHT_GREEN, SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY }, + { 1, "SAFE", ANSI_HIGHLIGHT_GREEN, SPECIAL_GLYPH_HAPPY_SMILEY }, + { 0, "PERFECT", ANSI_HIGHLIGHT_GREEN, SPECIAL_GLYPH_ECSTATIC_SMILEY }, + }; + + uint64_t badness_sum = 0, weight_sum = 0, exposure; + _cleanup_(table_unrefp) Table *details_table = NULL; + size_t i; + int r; + + if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT)) { + details_table = table_new(" ", "name", "description", "weight", "badness", "range", "exposure"); + if (!details_table) + return log_oom(); + + (void) table_set_sort(details_table, 3, 1, (size_t) -1); + (void) table_set_reverse(details_table, 3, true); + + if (getenv_bool("SYSTEMD_ANALYZE_DEBUG") <= 0) + (void) table_set_display(details_table, 0, 1, 2, 6, (size_t) -1); + } + + for (i = 0; i < ELEMENTSOF(security_assessor_table); i++) { + const struct security_assessor *a = security_assessor_table + i; + _cleanup_free_ char *d = NULL; + uint64_t badness; + void *data; + + data = (uint8_t *) info + a->offset; + + if (a->default_dependencies_only && !info->default_dependencies) { + badness = UINT64_MAX; + d = strdup("Service runs in special boot phase, option does not apply"); + if (!d) + return log_oom(); + } else { + r = a->assess(a, info, data, &badness, &d); + if (r < 0) + return r; + } + + assert(a->range > 0); + + if (badness != UINT64_MAX) { + assert(badness <= a->range); + + badness_sum += DIV_ROUND_UP(badness * a->weight, a->range); + weight_sum += a->weight; + } + + if (details_table) { + const char *checkmark, *description, *color = NULL; + TableCell *cell; + + if (badness == UINT64_MAX) { + checkmark = " "; + description = a->description_na; + color = NULL; + } else if (badness == a->range) { + checkmark = special_glyph(SPECIAL_GLYPH_CROSS_MARK); + description = a->description_bad; + color = ansi_highlight_red(); + } else if (badness == 0) { + checkmark = special_glyph(SPECIAL_GLYPH_CHECK_MARK); + description = a->description_good; + color = ansi_highlight_green(); + } else { + checkmark = special_glyph(SPECIAL_GLYPH_CROSS_MARK); + description = NULL; + color = ansi_highlight_red(); + } + + if (d) + description = d; + + r = table_add_cell_full(details_table, &cell, TABLE_STRING, checkmark, 1, 1, 0, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to add cell to table: %m"); + if (color) + (void) table_set_color(details_table, cell, color); + + r = table_add_many(details_table, + TABLE_STRING, a->id, TABLE_SET_URL, a->url, + TABLE_STRING, description, + TABLE_UINT64, a->weight, TABLE_SET_ALIGN_PERCENT, 100, + TABLE_UINT64, badness, TABLE_SET_ALIGN_PERCENT, 100, + TABLE_UINT64, a->range, TABLE_SET_ALIGN_PERCENT, 100, + TABLE_EMPTY, TABLE_SET_ALIGN_PERCENT, 100); + if (r < 0) + return log_error_errno(r, "Failed to add cells to table: %m"); + } + } + + assert(weight_sum > 0); + + if (details_table) { + size_t row; + + for (row = 1; row < table_get_rows(details_table); row++) { + char buf[DECIMAL_STR_MAX(uint64_t) + 1 + DECIMAL_STR_MAX(uint64_t) + 1]; + const uint64_t *weight, *badness, *range; + TableCell *cell; + uint64_t x; + + assert_se(weight = table_get_at(details_table, row, 3)); + assert_se(badness = table_get_at(details_table, row, 4)); + assert_se(range = table_get_at(details_table, row, 5)); + + if (*badness == UINT64_MAX || *badness == 0) + continue; + + assert_se(cell = table_get_cell(details_table, row, 6)); + + x = DIV_ROUND_UP(DIV_ROUND_UP(*badness * *weight * 100U, *range), weight_sum); + xsprintf(buf, "%" PRIu64 ".%" PRIu64, x / 10, x % 10); + + r = table_update(details_table, cell, TABLE_STRING, buf); + if (r < 0) + return log_error_errno(r, "Failed to update cell in table: %m"); + } + + r = table_print(details_table, stdout); + if (r < 0) + return log_error_errno(r, "Failed to output table: %m"); + } + + exposure = DIV_ROUND_UP(badness_sum * 100U, weight_sum); + + for (i = 0; i < ELEMENTSOF(badness_table); i++) + if (exposure >= badness_table[i].exposure) + break; + + assert(i < ELEMENTSOF(badness_table)); + + if (details_table) { + _cleanup_free_ char *clickable = NULL; + const char *name; + + /* If we shall output the details table, also print the brief summary underneath */ + + if (info->fragment_path) { + r = terminal_urlify_path(info->fragment_path, info->id, &clickable); + if (r < 0) + return log_oom(); + + name = clickable; + } else + name = info->id; + + printf("\n%s %sOverall exposure level for %s%s: %s%" PRIu64 ".%" PRIu64 " %s%s %s\n", + special_glyph(SPECIAL_GLYPH_ARROW), + ansi_highlight(), + name, + ansi_normal(), + colors_enabled() ? strempty(badness_table[i].color) : "", + exposure / 10, exposure % 10, + badness_table[i].name, + ansi_normal(), + special_glyph(badness_table[i].smiley)); + } + + fflush(stdout); + + if (overview_table) { + char buf[DECIMAL_STR_MAX(uint64_t) + 1 + DECIMAL_STR_MAX(uint64_t) + 1]; + TableCell *cell; + + r = table_add_cell(overview_table, &cell, TABLE_STRING, info->id); + if (r < 0) + return log_error_errno(r, "Failed to add cell to table: %m"); + if (info->fragment_path) { + _cleanup_free_ char *url = NULL; + + r = file_url_from_path(info->fragment_path, &url); + if (r < 0) + return log_error_errno(r, "Failed to generate URL from path: %m"); + + (void) table_set_url(overview_table, cell, url); + } + + xsprintf(buf, "%" PRIu64 ".%" PRIu64, exposure / 10, exposure % 10); + r = table_add_cell(overview_table, &cell, TABLE_STRING, buf); + if (r < 0) + return log_error_errno(r, "Failed to add cell to table: %m"); + (void) table_set_align_percent(overview_table, cell, 100); + + r = table_add_cell(overview_table, &cell, TABLE_STRING, badness_table[i].name); + if (r < 0) + return log_error_errno(r, "Failed to add cell to table: %m"); + (void) table_set_color(overview_table, cell, strempty(badness_table[i].color)); + + r = table_add_cell(overview_table, NULL, TABLE_STRING, special_glyph(badness_table[i].smiley)); + if (r < 0) + return log_error_errno(r, "Failed to add cell to table: %m"); + } + + return 0; +} + +static int property_read_restrict_address_families( + sd_bus *bus, + const char *member, + sd_bus_message *m, + sd_bus_error *error, + void *userdata) { + + struct security_info *info = userdata; + int whitelist, r; + + assert(bus); + assert(member); + assert(m); + + r = sd_bus_message_enter_container(m, 'r', "bas"); + if (r < 0) + return r; + + r = sd_bus_message_read(m, "b", &whitelist); + if (r < 0) + return r; + + info->restrict_address_family_inet = + info->restrict_address_family_unix = + info->restrict_address_family_netlink = + info->restrict_address_family_packet = + info->restrict_address_family_other = whitelist; + + r = sd_bus_message_enter_container(m, 'a', "s"); + if (r < 0) + return r; + + for (;;) { + const char *name; + + r = sd_bus_message_read(m, "s", &name); + if (r < 0) + return r; + if (r == 0) + break; + + if (STR_IN_SET(name, "AF_INET", "AF_INET6")) + info->restrict_address_family_inet = !whitelist; + else if (streq(name, "AF_UNIX")) + info->restrict_address_family_unix = !whitelist; + else if (streq(name, "AF_NETLINK")) + info->restrict_address_family_netlink = !whitelist; + else if (streq(name, "AF_PACKET")) + info->restrict_address_family_packet = !whitelist; + else + info->restrict_address_family_other = !whitelist; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return sd_bus_message_exit_container(m); +} + +static int property_read_system_call_filter( + sd_bus *bus, + const char *member, + sd_bus_message *m, + sd_bus_error *error, + void *userdata) { + + struct security_info *info = userdata; + int whitelist, r; + + assert(bus); + assert(member); + assert(m); + + r = sd_bus_message_enter_container(m, 'r', "bas"); + if (r < 0) + return r; + + r = sd_bus_message_read(m, "b", &whitelist); + if (r < 0) + return r; + + info->system_call_filter_whitelist = whitelist; + + r = sd_bus_message_enter_container(m, 'a', "s"); + if (r < 0) + return r; + + for (;;) { + const char *name; + + r = sd_bus_message_read(m, "s", &name); + if (r < 0) + return r; + if (r == 0) + break; + + r = set_ensure_allocated(&info->system_call_filter, &string_hash_ops); + if (r < 0) + return r; + + r = set_put_strdup(info->system_call_filter, name); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return sd_bus_message_exit_container(m); +} + +static int property_read_ip_address_allow( + sd_bus *bus, + const char *member, + sd_bus_message *m, + sd_bus_error *error, + void *userdata) { + + struct security_info *info = userdata; + bool deny_ipv4 = false, deny_ipv6 = false; + int r; + + assert(bus); + assert(member); + assert(m); + + r = sd_bus_message_enter_container(m, 'a', "(iayu)"); + if (r < 0) + return r; + + for (;;) { + const void *data; + size_t size; + int32_t family; + uint32_t prefixlen; + + r = sd_bus_message_enter_container(m, 'r', "iayu"); + if (r < 0) + return r; + if (r == 0) + break; + + r = sd_bus_message_read(m, "i", &family); + if (r < 0) + return r; + + r = sd_bus_message_read_array(m, 'y', &data, &size); + if (r < 0) + return r; + + r = sd_bus_message_read(m, "u", &prefixlen); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + if (streq(member, "IPAddressAllow")) { + union in_addr_union u; + + if (family == AF_INET && size == 4 && prefixlen == 8) + memcpy(&u.in, data, size); + else if (family == AF_INET6 && size == 16 && prefixlen == 128) + memcpy(&u.in6, data, size); + else { + info->ip_address_allow_other = true; + continue; + } + + if (in_addr_is_localhost(family, &u)) + info->ip_address_allow_localhost = true; + else + info->ip_address_allow_other = true; + } else { + assert(streq(member, "IPAddressDeny")); + + if (family == AF_INET && size == 4 && prefixlen == 0) + deny_ipv4 = true; + else if (family == AF_INET6 && size == 16 && prefixlen == 0) + deny_ipv6 = true; + } + } + + info->ip_address_deny_all = deny_ipv4 && deny_ipv6; + + return sd_bus_message_exit_container(m); +} + +static int property_read_ip_filters( + sd_bus *bus, + const char *member, + sd_bus_message *m, + sd_bus_error *error, + void *userdata) { + + struct security_info *info = userdata; + _cleanup_(strv_freep) char **l = NULL; + int r; + + assert(bus); + assert(member); + assert(m); + + r = sd_bus_message_read_strv(m, &l); + if (r < 0) + return r; + + if (streq(member, "IPIngressFilterPath")) + info->ip_filters_custom_ingress = !strv_isempty(l); + else if (streq(member, "IPEgressFilterPath")) + info->ip_filters_custom_ingress = !strv_isempty(l); + + return 0; +} + +static int property_read_device_allow( + sd_bus *bus, + const char *member, + sd_bus_message *m, + sd_bus_error *error, + void *userdata) { + + struct security_info *info = userdata; + size_t n = 0; + int r; + + assert(bus); + assert(member); + assert(m); + + r = sd_bus_message_enter_container(m, 'a', "(ss)"); + if (r < 0) + return r; + + for (;;) { + const char *name, *policy; + + r = sd_bus_message_read(m, "(ss)", &name, &policy); + if (r < 0) + return r; + if (r == 0) + break; + + n++; + } + + info->device_allow_non_empty = n > 0; + + return sd_bus_message_exit_container(m); +} + +static int acquire_security_info(sd_bus *bus, const char *name, struct security_info *info, AnalyzeSecurityFlags flags) { + + static const struct bus_properties_map security_map[] = { + { "AmbientCapabilities", "t", NULL, offsetof(struct security_info, ambient_capabilities) }, + { "CapabilityBoundingSet", "t", NULL, offsetof(struct security_info, capability_bounding_set) }, + { "DefaultDependencies", "b", NULL, offsetof(struct security_info, default_dependencies) }, + { "Delegate", "b", NULL, offsetof(struct security_info, delegate) }, + { "DeviceAllow", "a(ss)", property_read_device_allow, 0 }, + { "DevicePolicy", "s", NULL, offsetof(struct security_info, device_policy) }, + { "DynamicUser", "b", NULL, offsetof(struct security_info, dynamic_user) }, + { "FragmentPath", "s", NULL, offsetof(struct security_info, fragment_path) }, + { "IPAddressAllow", "a(iayu)", property_read_ip_address_allow, 0 }, + { "IPAddressDeny", "a(iayu)", property_read_ip_address_allow, 0 }, + { "IPIngressFilterPath", "as", property_read_ip_filters, 0 }, + { "IPEgressFilterPath", "as", property_read_ip_filters, 0 }, + { "Id", "s", NULL, offsetof(struct security_info, id) }, + { "KeyringMode", "s", NULL, offsetof(struct security_info, keyring_mode) }, + { "LoadState", "s", NULL, offsetof(struct security_info, load_state) }, + { "LockPersonality", "b", NULL, offsetof(struct security_info, lock_personality) }, + { "MemoryDenyWriteExecute", "b", NULL, offsetof(struct security_info, memory_deny_write_execute) }, + { "NoNewPrivileges", "b", NULL, offsetof(struct security_info, no_new_privileges) }, + { "NotifyAccess", "s", NULL, offsetof(struct security_info, notify_access) }, + { "PrivateDevices", "b", NULL, offsetof(struct security_info, private_devices) }, + { "PrivateMounts", "b", NULL, offsetof(struct security_info, private_mounts) }, + { "PrivateNetwork", "b", NULL, offsetof(struct security_info, private_network) }, + { "PrivateTmp", "b", NULL, offsetof(struct security_info, private_tmp) }, + { "PrivateUsers", "b", NULL, offsetof(struct security_info, private_users) }, + { "ProtectControlGroups", "b", NULL, offsetof(struct security_info, protect_control_groups) }, + { "ProtectHome", "s", NULL, offsetof(struct security_info, protect_home) }, + { "ProtectHostname", "b", NULL, offsetof(struct security_info, protect_hostname) }, + { "ProtectKernelModules", "b", NULL, offsetof(struct security_info, protect_kernel_modules) }, + { "ProtectKernelTunables", "b", NULL, offsetof(struct security_info, protect_kernel_tunables) }, + { "ProtectKernelLogs", "b", NULL, offsetof(struct security_info, protect_kernel_logs) }, + { "ProtectSystem", "s", NULL, offsetof(struct security_info, protect_system) }, + { "RemoveIPC", "b", NULL, offsetof(struct security_info, remove_ipc) }, + { "RestrictAddressFamilies", "(bas)", property_read_restrict_address_families, 0 }, + { "RestrictNamespaces", "t", NULL, offsetof(struct security_info, restrict_namespaces) }, + { "RestrictRealtime", "b", NULL, offsetof(struct security_info, restrict_realtime) }, + { "RestrictSUIDSGID", "b", NULL, offsetof(struct security_info, restrict_suid_sgid) }, + { "RootDirectory", "s", NULL, offsetof(struct security_info, root_directory) }, + { "RootImage", "s", NULL, offsetof(struct security_info, root_image) }, + { "SupplementaryGroups", "as", NULL, offsetof(struct security_info, supplementary_groups) }, + { "SystemCallArchitectures", "as", NULL, offsetof(struct security_info, system_call_architectures) }, + { "SystemCallFilter", "(as)", property_read_system_call_filter, 0 }, + { "Type", "s", NULL, offsetof(struct security_info, type) }, + { "UMask", "u", NULL, offsetof(struct security_info, _umask) }, + { "User", "s", NULL, offsetof(struct security_info, user) }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + int r; + + /* Note: this mangles *info on failure! */ + + assert(bus); + assert(name); + assert(info); + + path = unit_dbus_path_from_name(name); + if (!path) + return log_oom(); + + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + path, + security_map, + BUS_MAP_STRDUP | BUS_MAP_BOOLEAN_AS_BOOL, + &error, + NULL, + info); + if (r < 0) + return log_error_errno(r, "Failed to get unit properties: %s", bus_error_message(&error, r)); + + if (!streq_ptr(info->load_state, "loaded")) { + + if (FLAGS_SET(flags, ANALYZE_SECURITY_ONLY_LOADED)) + return -EMEDIUMTYPE; + + if (streq_ptr(info->load_state, "not-found")) + log_error("Unit %s not found, cannot analyze.", name); + else if (streq_ptr(info->load_state, "masked")) + log_error("Unit %s is masked, cannot analyze.", name); + else + log_error("Unit %s not loaded properly, cannot analyze.", name); + + return -EINVAL; + } + + if (FLAGS_SET(flags, ANALYZE_SECURITY_ONLY_LONG_RUNNING) && streq_ptr(info->type, "oneshot")) + return -EMEDIUMTYPE; + + if (info->private_devices || + info->private_tmp || + info->protect_control_groups || + info->protect_kernel_tunables || + info->protect_kernel_modules || + !streq_ptr(info->protect_home, "no") || + !streq_ptr(info->protect_system, "no") || + info->root_image) + info->private_mounts = true; + + if (info->protect_kernel_modules) + info->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYS_MODULE); + + if (info->protect_kernel_logs) + info->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYSLOG); + + if (info->private_devices) + info->capability_bounding_set &= ~((UINT64_C(1) << CAP_MKNOD) | + (UINT64_C(1) << CAP_SYS_RAWIO)); + + return 0; +} + +static int analyze_security_one(sd_bus *bus, const char *name, Table *overview_table, AnalyzeSecurityFlags flags) { + _cleanup_(security_info_free) struct security_info info = { + .default_dependencies = true, + .capability_bounding_set = UINT64_MAX, + .restrict_namespaces = UINT64_MAX, + ._umask = 0002, + }; + int r; + + assert(bus); + assert(name); + + r = acquire_security_info(bus, name, &info, flags); + if (r == -EMEDIUMTYPE) /* Ignore this one because not loaded or Type is oneshot */ + return 0; + if (r < 0) + return r; + + r = assess(&info, overview_table, flags); + if (r < 0) + return r; + + return 0; +} + +int analyze_security(sd_bus *bus, char **units, AnalyzeSecurityFlags flags) { + _cleanup_(table_unrefp) Table *overview_table = NULL; + int ret = 0, r; + + assert(bus); + + if (strv_length(units) != 1) { + overview_table = table_new("unit", "exposure", "predicate", "happy"); + if (!overview_table) + return log_oom(); + } + + if (strv_isempty(units)) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_strv_free_ char **list = NULL; + size_t allocated = 0, n = 0; + char **i; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListUnits", + &error, + &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); + if (r < 0) + return bus_log_parse_error(r); + + for (;;) { + UnitInfo info; + char *copy = NULL; + + r = bus_parse_unit_info(reply, &info); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + if (!endswith(info.id, ".service")) + continue; + + if (!GREEDY_REALLOC(list, allocated, n + 2)) + return log_oom(); + + copy = strdup(info.id); + if (!copy) + return log_oom(); + + list[n++] = copy; + list[n] = NULL; + } + + strv_sort(list); + + flags |= ANALYZE_SECURITY_SHORT|ANALYZE_SECURITY_ONLY_LOADED|ANALYZE_SECURITY_ONLY_LONG_RUNNING; + + STRV_FOREACH(i, list) { + r = analyze_security_one(bus, *i, overview_table, flags); + if (r < 0 && ret >= 0) + ret = r; + } + + } else { + char **i; + + STRV_FOREACH(i, units) { + _cleanup_free_ char *mangled = NULL, *instance = NULL; + const char *name; + + if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT) && i != units) { + putc('\n', stdout); + fflush(stdout); + } + + r = unit_name_mangle(*i, 0, &mangled); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name '%s': %m", *i); + + if (!endswith(mangled, ".service")) { + log_error("Unit %s is not a service unit, refusing.", *i); + return -EINVAL; + } + + if (unit_name_is_valid(mangled, UNIT_NAME_TEMPLATE)) { + r = unit_name_replace_instance(mangled, "test-instance", &instance); + if (r < 0) + return log_oom(); + + name = instance; + } else + name = mangled; + + r = analyze_security_one(bus, name, overview_table, flags); + if (r < 0 && ret >= 0) + ret = r; + } + } + + if (overview_table) { + if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT)) { + putc('\n', stdout); + fflush(stdout); + } + + r = table_print(overview_table, stdout); + if (r < 0) + return log_error_errno(r, "Failed to output table: %m"); + } + + return ret; +} diff --git a/src/analyze/analyze-security.h b/src/analyze/analyze-security.h new file mode 100644 index 00000000..c00ae7c8 --- /dev/null +++ b/src/analyze/analyze-security.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +typedef enum AnalyzeSecurityFlags { + ANALYZE_SECURITY_SHORT = 1 << 0, + ANALYZE_SECURITY_ONLY_LOADED = 1 << 1, + ANALYZE_SECURITY_ONLY_LONG_RUNNING = 1 << 2, +} AnalyzeSecurityFlags; + +int analyze_security(sd_bus *bus, char **units, AnalyzeSecurityFlags flags); diff --git a/src/analyze/analyze-verify.c b/src/analyze/analyze-verify.c new file mode 100644 index 00000000..4cfbdfa5 --- /dev/null +++ b/src/analyze/analyze-verify.c @@ -0,0 +1,290 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "all-units.h" +#include "analyze-verify.h" +#include "bus-error.h" +#include "bus-util.h" +#include "log.h" +#include "manager.h" +#include "pager.h" +#include "path-util.h" +#include "strv.h" +#include "unit-name.h" + +static int prepare_filename(const char *filename, char **ret) { + int r; + const char *name; + _cleanup_free_ char *abspath = NULL; + _cleanup_free_ char *dir = NULL; + _cleanup_free_ char *with_instance = NULL; + char *c; + + assert(filename); + assert(ret); + + r = path_make_absolute_cwd(filename, &abspath); + if (r < 0) + return r; + + name = basename(abspath); + if (!unit_name_is_valid(name, UNIT_NAME_ANY)) + return -EINVAL; + + if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { + r = unit_name_replace_instance(name, "i", &with_instance); + if (r < 0) + return r; + } + + dir = dirname_malloc(abspath); + if (!dir) + return -ENOMEM; + + c = path_join(dir, with_instance ?: name); + if (!c) + return -ENOMEM; + + *ret = c; + return 0; +} + +static int generate_path(char **var, char **filenames) { + const char *old; + char **filename; + + _cleanup_strv_free_ char **ans = NULL; + int r; + + STRV_FOREACH(filename, filenames) { + char *t; + + t = dirname_malloc(*filename); + if (!t) + return -ENOMEM; + + r = strv_consume(&ans, t); + if (r < 0) + return r; + } + + assert_se(strv_uniq(ans)); + + /* First, prepend our directories. Second, if some path was specified, use that, and + * otherwise use the defaults. Any duplicates will be filtered out in path-lookup.c. + * Treat explicit empty path to mean that nothing should be appended. + */ + old = getenv("SYSTEMD_UNIT_PATH"); + if (!streq_ptr(old, "")) { + if (!old) + old = ":"; + + r = strv_extend(&ans, old); + if (r < 0) + return r; + } + + *var = strv_join(ans, ":"); + if (!*var) + return -ENOMEM; + + return 0; +} + +static int verify_socket(Unit *u) { + int r; + + assert(u); + + if (u->type != UNIT_SOCKET) + return 0; + + /* Cannot run this without the service being around */ + + /* This makes sure instance is created if necessary. */ + r = socket_instantiate_service(SOCKET(u)); + if (r < 0) + return log_unit_error_errno(u, r, "Socket cannot be started, failed to create instance: %m"); + + /* This checks both type of sockets */ + if (UNIT_ISSET(SOCKET(u)->service)) { + Service *service; + + service = SERVICE(UNIT_DEREF(SOCKET(u)->service)); + log_unit_debug(u, "Using %s", UNIT(service)->id); + + if (UNIT(service)->load_state != UNIT_LOADED) { + log_unit_error(u, "Service %s not loaded, %s cannot be started.", UNIT(service)->id, u->id); + return -ENOENT; + } + } + + return 0; +} + +static int verify_executable(Unit *u, ExecCommand *exec) { + if (!exec) + return 0; + + if (access(exec->path, X_OK) < 0) + return log_unit_error_errno(u, errno, "Command %s is not executable: %m", exec->path); + + return 0; +} + +static int verify_executables(Unit *u) { + ExecCommand *exec; + int r = 0, k; + unsigned i; + + assert(u); + + exec = u->type == UNIT_SOCKET ? SOCKET(u)->control_command : + u->type == UNIT_MOUNT ? MOUNT(u)->control_command : + u->type == UNIT_SWAP ? SWAP(u)->control_command : NULL; + k = verify_executable(u, exec); + if (k < 0 && r == 0) + r = k; + + if (u->type == UNIT_SERVICE) + for (i = 0; i < ELEMENTSOF(SERVICE(u)->exec_command); i++) { + k = verify_executable(u, SERVICE(u)->exec_command[i]); + if (k < 0 && r == 0) + r = k; + } + + if (u->type == UNIT_SOCKET) + for (i = 0; i < ELEMENTSOF(SOCKET(u)->exec_command); i++) { + k = verify_executable(u, SOCKET(u)->exec_command[i]); + if (k < 0 && r == 0) + r = k; + } + + return r; +} + +static int verify_documentation(Unit *u, bool check_man) { + char **p; + int r = 0, k; + + STRV_FOREACH(p, u->documentation) { + log_unit_debug(u, "Found documentation item: %s", *p); + + if (check_man && startswith(*p, "man:")) { + k = show_man_page(*p + 4, true); + if (k != 0) { + if (k < 0) + log_unit_error_errno(u, k, "Can't show %s: %m", *p + 4); + else { + log_unit_error(u, "Command 'man %s' failed with code %d", *p + 4, k); + k = -ENOEXEC; + } + if (r == 0) + r = k; + } + } + } + + /* Check remote URLs? */ + + return r; +} + +static int verify_unit(Unit *u, bool check_man) { + _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL; + int r, k; + + assert(u); + + if (DEBUG_LOGGING) + unit_dump(u, stdout, "\t"); + + log_unit_debug(u, "Creating %s/start job", u->id); + r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, NULL, &err, NULL); + if (r < 0) + log_unit_error_errno(u, r, "Failed to create %s/start: %s", u->id, bus_error_message(&err, r)); + + k = verify_socket(u); + if (k < 0 && r == 0) + r = k; + + k = verify_executables(u); + if (k < 0 && r == 0) + r = k; + + k = verify_documentation(u, check_man); + if (k < 0 && r == 0) + r = k; + + return r; +} + +int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators) { + const ManagerTestRunFlags flags = + MANAGER_TEST_RUN_BASIC | + MANAGER_TEST_RUN_ENV_GENERATORS | + run_generators * MANAGER_TEST_RUN_GENERATORS; + + _cleanup_(manager_freep) Manager *m = NULL; + Unit *units[strv_length(filenames)]; + _cleanup_free_ char *var = NULL; + int r = 0, k, i, count = 0; + char **filename; + + if (strv_isempty(filenames)) + return 0; + + /* set the path */ + r = generate_path(&var, filenames); + if (r < 0) + return log_error_errno(r, "Failed to generate unit load path: %m"); + + assert_se(set_unit_path(var) >= 0); + + r = manager_new(scope, flags, &m); + if (r < 0) + return log_error_errno(r, "Failed to initialize manager: %m"); + + log_debug("Starting manager..."); + + r = manager_startup(m, NULL, NULL); + if (r < 0) + return r; + + manager_clear_jobs(m); + + log_debug("Loading remaining units from the command line..."); + + STRV_FOREACH(filename, filenames) { + _cleanup_free_ char *prepared = NULL; + + log_debug("Handling %s...", *filename); + + k = prepare_filename(*filename, &prepared); + if (k < 0) { + log_error_errno(k, "Failed to prepare filename %s: %m", *filename); + if (r == 0) + r = k; + continue; + } + + k = manager_load_startable_unit_or_warn(m, NULL, prepared, &units[count]); + if (k < 0) { + if (r == 0) + r = k; + continue; + } + + count++; + } + + for (i = 0; i < count; i++) { + k = verify_unit(units[i], check_man); + if (k < 0 && r == 0) + r = k; + } + + return r; +} diff --git a/src/analyze/analyze-verify.h b/src/analyze/analyze-verify.h new file mode 100644 index 00000000..3561d430 --- /dev/null +++ b/src/analyze/analyze-verify.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "path-lookup.h" + +int verify_units(char **filenames, UnitFileScope scope, bool check_man, bool run_generators); diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c new file mode 100644 index 00000000..991e61de --- /dev/null +++ b/src/analyze/analyze.c @@ -0,0 +1,2518 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Simon Peeters +***/ + +#include +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "analyze-condition.h" +#include "analyze-security.h" +#include "analyze-verify.h" +#include "build.h" +#include "bus-error.h" +#include "bus-unit-util.h" +#include "bus-util.h" +#include "calendarspec.h" +#include "conf-files.h" +#include "copy.h" +#include "def.h" +#include "exit-status.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-table.h" +#include "glob-util.h" +#include "hashmap.h" +#include "locale-util.h" +#include "log.h" +#include "main-func.h" +#include "nulstr-util.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#if HAVE_SECCOMP +# include "seccomp-util.h" +#endif +#include "sort-util.h" +#include "special.h" +#include "strv.h" +#include "strxcpyx.h" +#include "terminal-util.h" +#include "time-util.h" +#include "unit-name.h" +#include "util.h" +#include "verbs.h" + +#define SCALE_X (0.1 / 1000.0) /* pixels per us */ +#define SCALE_Y (20.0) + +#define svg(...) printf(__VA_ARGS__) + +#define svg_bar(class, x1, x2, y) \ + svg(" \n", \ + (class), \ + SCALE_X * (x1), SCALE_Y * (y), \ + SCALE_X * ((x2) - (x1)), SCALE_Y - 1.0) + +#define svg_text(b, x, y, format, ...) \ + do { \ + svg(" ", (b) ? "left" : "right", SCALE_X * (x) + (b ? 5.0 : -5.0), SCALE_Y * (y) + 14.0); \ + svg(format, ## __VA_ARGS__); \ + svg("\n"); \ + } while (false) + +static enum dot { + DEP_ALL, + DEP_ORDER, + DEP_REQUIRE +} arg_dot = DEP_ALL; +static char **arg_dot_from_patterns = NULL; +static char **arg_dot_to_patterns = NULL; +static usec_t arg_fuzz = 0; +static PagerFlags arg_pager_flags = 0; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static const char *arg_host = NULL; +static UnitFileScope arg_scope = UNIT_FILE_SYSTEM; +static bool arg_man = true; +static bool arg_generators = false; +static const char *arg_root = NULL; +static unsigned arg_iterations = 1; +static usec_t arg_base_time = USEC_INFINITY; + +STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_dot_to_patterns, strv_freep); + +struct boot_times { + usec_t firmware_time; + usec_t loader_time; + usec_t kernel_time; + usec_t kernel_done_time; + usec_t initrd_time; + usec_t userspace_time; + usec_t finish_time; + usec_t security_start_time; + usec_t security_finish_time; + usec_t generators_start_time; + usec_t generators_finish_time; + usec_t unitsload_start_time; + usec_t unitsload_finish_time; + usec_t initrd_security_start_time; + usec_t initrd_security_finish_time; + usec_t initrd_generators_start_time; + usec_t initrd_generators_finish_time; + usec_t initrd_unitsload_start_time; + usec_t initrd_unitsload_finish_time; + + /* + * If we're analyzing the user instance, all timestamps will be offset + * by its own start-up timestamp, which may be arbitrarily big. + * With "plot", this causes arbitrarily wide output SVG files which almost + * completely consist of empty space. Thus we cancel out this offset. + * + * This offset is subtracted from times above by acquire_boot_times(), + * but it still needs to be subtracted from unit-specific timestamps + * (so it is stored here for reference). + */ + usec_t reverse_offset; +}; + +struct unit_times { + bool has_data; + char *name; + usec_t activating; + usec_t activated; + usec_t deactivated; + usec_t deactivating; + usec_t time; +}; + +struct host_info { + char *hostname; + char *kernel_name; + char *kernel_release; + char *kernel_version; + char *os_pretty_name; + char *virtualization; + char *architecture; +}; + +static int acquire_bus(sd_bus **bus, bool *use_full_bus) { + bool user = arg_scope != UNIT_FILE_SYSTEM; + int r; + + if (use_full_bus && *use_full_bus) { + r = bus_connect_transport(arg_transport, arg_host, user, bus); + if (IN_SET(r, 0, -EHOSTDOWN)) + return r; + + *use_full_bus = false; + } + + return bus_connect_transport_systemd(arg_transport, arg_host, user, bus); +} + +static int bus_get_uint64_property(sd_bus *bus, const char *path, const char *interface, const char *property, uint64_t *val) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(property); + assert(val); + + r = sd_bus_get_property_trivial( + bus, + "org.freedesktop.systemd1", + path, + interface, + property, + &error, + 't', val); + + if (r < 0) + return log_error_errno(r, "Failed to parse reply: %s", bus_error_message(&error, r)); + + return 0; +} + +static int bus_get_unit_property_strv(sd_bus *bus, const char *path, const char *property, char ***strv) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + assert(path); + assert(property); + assert(strv); + + r = sd_bus_get_property_strv( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + property, + &error, + strv); + if (r < 0) + return log_error_errno(r, "Failed to get unit property %s: %s", property, bus_error_message(&error, r)); + + return 0; +} + +static int compare_unit_start(const struct unit_times *a, const struct unit_times *b) { + return CMP(a->activating, b->activating); +} + +static void unit_times_free(struct unit_times *t) { + struct unit_times *p; + + for (p = t; p->has_data; p++) + free(p->name); + free(t); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct unit_times *, unit_times_free); + +static void subtract_timestamp(usec_t *a, usec_t b) { + assert(a); + + if (*a > 0) { + assert(*a >= b); + *a -= b; + } +} + +static int acquire_boot_times(sd_bus *bus, struct boot_times **bt) { + static const struct bus_properties_map property_map[] = { + { "FirmwareTimestampMonotonic", "t", NULL, offsetof(struct boot_times, firmware_time) }, + { "LoaderTimestampMonotonic", "t", NULL, offsetof(struct boot_times, loader_time) }, + { "KernelTimestamp", "t", NULL, offsetof(struct boot_times, kernel_time) }, + { "InitRDTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_time) }, + { "UserspaceTimestampMonotonic", "t", NULL, offsetof(struct boot_times, userspace_time) }, + { "FinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, finish_time) }, + { "SecurityStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, security_start_time) }, + { "SecurityFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, security_finish_time) }, + { "GeneratorsStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, generators_start_time) }, + { "GeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, generators_finish_time) }, + { "UnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, unitsload_start_time) }, + { "UnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, unitsload_finish_time) }, + { "InitRDSecurityStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_security_start_time) }, + { "InitRDSecurityFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_security_finish_time) }, + { "InitRDGeneratorsStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_generators_start_time) }, + { "InitRDGeneratorsFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_generators_finish_time) }, + { "InitRDUnitsLoadStartTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_unitsload_start_time) }, + { "InitRDUnitsLoadFinishTimestampMonotonic", "t", NULL, offsetof(struct boot_times, initrd_unitsload_finish_time) }, + {}, + }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + static struct boot_times times; + static bool cached = false; + int r; + + if (cached) + goto finish; + + assert_cc(sizeof(usec_t) == sizeof(uint64_t)); + + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + property_map, + BUS_MAP_STRDUP, + &error, + NULL, + ×); + if (r < 0) + return log_error_errno(r, "Failed to get timestamp properties: %s", bus_error_message(&error, r)); + + if (times.finish_time <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINPROGRESS), + "Bootup is not yet finished (org.freedesktop.systemd1.Manager.FinishTimestampMonotonic=%"PRIu64").\n" + "Please try again later.\n" + "Hint: Use 'systemctl%s list-jobs' to see active jobs", + times.finish_time, + arg_scope == UNIT_FILE_SYSTEM ? "" : " --user"); + + if (arg_scope == UNIT_FILE_SYSTEM && times.security_start_time > 0) { + /* security_start_time is set when systemd is not running under container environment. */ + if (times.initrd_time > 0) + times.kernel_done_time = times.initrd_time; + else + times.kernel_done_time = times.userspace_time; + } else { + /* + * User-instance-specific or container-system-specific timestamps processing + * (see comment to reverse_offset in struct boot_times). + */ + times.reverse_offset = times.userspace_time; + + times.firmware_time = times.loader_time = times.kernel_time = times.initrd_time = + times.userspace_time = times.security_start_time = times.security_finish_time = 0; + + subtract_timestamp(×.finish_time, times.reverse_offset); + + subtract_timestamp(×.generators_start_time, times.reverse_offset); + subtract_timestamp(×.generators_finish_time, times.reverse_offset); + + subtract_timestamp(×.unitsload_start_time, times.reverse_offset); + subtract_timestamp(×.unitsload_finish_time, times.reverse_offset); + } + + cached = true; + +finish: + *bt = × + return 0; +} + +static void free_host_info(struct host_info *hi) { + if (!hi) + return; + + free(hi->hostname); + free(hi->kernel_name); + free(hi->kernel_release); + free(hi->kernel_version); + free(hi->os_pretty_name); + free(hi->virtualization); + free(hi->architecture); + free(hi); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct host_info *, free_host_info); + +static int acquire_time_data(sd_bus *bus, struct unit_times **out) { + static const struct bus_properties_map property_map[] = { + { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(struct unit_times, activating) }, + { "ActiveEnterTimestampMonotonic", "t", NULL, offsetof(struct unit_times, activated) }, + { "ActiveExitTimestampMonotonic", "t", NULL, offsetof(struct unit_times, deactivating) }, + { "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(struct unit_times, deactivated) }, + {}, + }; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(unit_times_freep) struct unit_times *unit_times = NULL; + struct boot_times *boot_times = NULL; + size_t allocated = 0, c = 0; + UnitInfo u; + int r; + + r = acquire_boot_times(bus, &boot_times); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListUnits", + &error, &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = bus_parse_unit_info(reply, &u)) > 0) { + struct unit_times *t; + + if (!GREEDY_REALLOC(unit_times, allocated, c + 2)) + return log_oom(); + + unit_times[c + 1].has_data = false; + t = &unit_times[c]; + t->name = NULL; + + assert_cc(sizeof(usec_t) == sizeof(uint64_t)); + + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + u.unit_path, + property_map, + BUS_MAP_STRDUP, + &error, + NULL, + t); + if (r < 0) + return log_error_errno(r, "Failed to get timestamp properties of unit %s: %s", + u.id, bus_error_message(&error, r)); + + subtract_timestamp(&t->activating, boot_times->reverse_offset); + subtract_timestamp(&t->activated, boot_times->reverse_offset); + subtract_timestamp(&t->deactivating, boot_times->reverse_offset); + subtract_timestamp(&t->deactivated, boot_times->reverse_offset); + + if (t->activated >= t->activating) + t->time = t->activated - t->activating; + else if (t->deactivated >= t->activating) + t->time = t->deactivated - t->activating; + else + t->time = 0; + + if (t->activating == 0) + continue; + + t->name = strdup(u.id); + if (!t->name) + return log_oom(); + + t->has_data = true; + c++; + } + if (r < 0) + return bus_log_parse_error(r); + + *out = TAKE_PTR(unit_times); + return c; +} + +static int acquire_host_info(sd_bus *bus, struct host_info **hi) { + static const struct bus_properties_map hostname_map[] = { + { "Hostname", "s", NULL, offsetof(struct host_info, hostname) }, + { "KernelName", "s", NULL, offsetof(struct host_info, kernel_name) }, + { "KernelRelease", "s", NULL, offsetof(struct host_info, kernel_release) }, + { "KernelVersion", "s", NULL, offsetof(struct host_info, kernel_version) }, + { "OperatingSystemPrettyName", "s", NULL, offsetof(struct host_info, os_pretty_name) }, + {} + }; + + static const struct bus_properties_map manager_map[] = { + { "Virtualization", "s", NULL, offsetof(struct host_info, virtualization) }, + { "Architecture", "s", NULL, offsetof(struct host_info, architecture) }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *system_bus = NULL; + _cleanup_(free_host_infop) struct host_info *host; + int r; + + host = new0(struct host_info, 1); + if (!host) + return log_oom(); + + if (arg_scope != UNIT_FILE_SYSTEM) { + r = bus_connect_transport(arg_transport, arg_host, false, &system_bus); + if (r < 0) { + log_debug_errno(r, "Failed to connect to system bus, ignoring: %m"); + goto manager; + } + } + + r = bus_map_all_properties( + system_bus ?: bus, + "org.freedesktop.hostname1", + "/org/freedesktop/hostname1", + hostname_map, + BUS_MAP_STRDUP, + &error, + NULL, + host); + if (r < 0) { + log_debug_errno(r, "Failed to get host information from systemd-hostnamed, ignoring: %s", + bus_error_message(&error, r)); + sd_bus_error_free(&error); + } + +manager: + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + manager_map, + BUS_MAP_STRDUP, + &error, + NULL, + host); + if (r < 0) + return log_error_errno(r, "Failed to get host information from systemd: %s", + bus_error_message(&error, r)); + + *hi = TAKE_PTR(host); + return 0; +} + +static int pretty_boot_time(sd_bus *bus, char **_buf) { + char ts[FORMAT_TIMESPAN_MAX]; + struct boot_times *t; + static char buf[4096]; + size_t size; + char *ptr; + int r; + usec_t activated_time = USEC_INFINITY; + _cleanup_free_ char *path = NULL, *unit_id = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = acquire_boot_times(bus, &t); + if (r < 0) + return r; + + path = unit_dbus_path_from_name(SPECIAL_DEFAULT_TARGET); + if (!path) + return log_oom(); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + "Id", + &error, + &unit_id); + if (r < 0) { + log_error_errno(r, "default.target doesn't seem to exist: %s", bus_error_message(&error, r)); + unit_id = NULL; + } + + r = bus_get_uint64_property(bus, path, + "org.freedesktop.systemd1.Unit", + "ActiveEnterTimestampMonotonic", + &activated_time); + if (r < 0) { + log_info_errno(r, "Could not get time to reach default.target, ignoring: %m"); + activated_time = USEC_INFINITY; + } + + ptr = buf; + size = sizeof(buf); + + size = strpcpyf(&ptr, size, "Startup finished in "); + if (t->firmware_time > 0) + size = strpcpyf(&ptr, size, "%s (firmware) + ", format_timespan(ts, sizeof(ts), t->firmware_time - t->loader_time, USEC_PER_MSEC)); + if (t->loader_time > 0) + size = strpcpyf(&ptr, size, "%s (loader) + ", format_timespan(ts, sizeof(ts), t->loader_time, USEC_PER_MSEC)); + if (t->kernel_done_time > 0) + size = strpcpyf(&ptr, size, "%s (kernel) + ", format_timespan(ts, sizeof(ts), t->kernel_done_time, USEC_PER_MSEC)); + if (t->initrd_time > 0) + size = strpcpyf(&ptr, size, "%s (initrd) + ", format_timespan(ts, sizeof(ts), t->userspace_time - t->initrd_time, USEC_PER_MSEC)); + + size = strpcpyf(&ptr, size, "%s (userspace) ", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time, USEC_PER_MSEC)); + if (t->kernel_done_time > 0) + strpcpyf(&ptr, size, "= %s ", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time, USEC_PER_MSEC)); + + if (unit_id && timestamp_is_set(activated_time)) { + usec_t base = t->userspace_time > 0 ? t->userspace_time : t->reverse_offset; + + size = strpcpyf(&ptr, size, "\n%s reached after %s in userspace", unit_id, + format_timespan(ts, sizeof(ts), activated_time - base, USEC_PER_MSEC)); + } else if (unit_id && activated_time == 0) + size = strpcpyf(&ptr, size, "\n%s was never reached", unit_id); + else if (unit_id && activated_time == USEC_INFINITY) + size = strpcpyf(&ptr, size, "\nCould not get time to reach %s.", unit_id); + else if (!unit_id) + size = strpcpyf(&ptr, size, "\ncould not find default.target"); + + ptr = strdup(buf); + if (!ptr) + return log_oom(); + + *_buf = ptr; + return 0; +} + +static void svg_graph_box(double height, double begin, double end) { + long long i; + + /* outside box, fill */ + svg("\n", + SCALE_X * (end - begin), + SCALE_Y * height); + + for (i = ((long long) (begin / 100000)) * 100000; i <= end; i += 100000) { + /* lines for each second */ + if (i % 5000000 == 0) + svg(" \n" + " %.01fs\n", + SCALE_X * i, + SCALE_X * i, + SCALE_Y * height, + SCALE_X * i, + -5.0, + 0.000001 * i); + else if (i % 1000000 == 0) + svg(" \n" + " %.01fs\n", + SCALE_X * i, + SCALE_X * i, + SCALE_Y * height, + SCALE_X * i, + -5.0, + 0.000001 * i); + else + svg(" \n", + SCALE_X * i, + SCALE_X * i, + SCALE_Y * height); + } +} + +static int plot_unit_times(struct unit_times *u, double width, int y) { + char ts[FORMAT_TIMESPAN_MAX]; + bool b; + + if (!u->name) + return 0; + + svg_bar("activating", u->activating, u->activated, y); + svg_bar("active", u->activated, u->deactivating, y); + svg_bar("deactivating", u->deactivating, u->deactivated, y); + + /* place the text on the left if we have passed the half of the svg width */ + b = u->activating * SCALE_X < width / 2; + if (u->time) + svg_text(b, u->activating, y, "%s (%s)", + u->name, format_timespan(ts, sizeof(ts), u->time, USEC_PER_MSEC)); + else + svg_text(b, u->activating, y, "%s", u->name); + + return 1; +} + +static int analyze_plot(int argc, char *argv[], void *userdata) { + _cleanup_(free_host_infop) struct host_info *host = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(unit_times_freep) struct unit_times *times = NULL; + _cleanup_free_ char *pretty_times = NULL; + bool use_full_bus = arg_scope == UNIT_FILE_SYSTEM; + struct boot_times *boot; + struct unit_times *u; + int n, m = 1, y = 0, r; + double width; + + r = acquire_bus(&bus, &use_full_bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + n = acquire_boot_times(bus, &boot); + if (n < 0) + return n; + + n = pretty_boot_time(bus, &pretty_times); + if (n < 0) + return n; + + if (use_full_bus || arg_scope != UNIT_FILE_SYSTEM) { + n = acquire_host_info(bus, &host); + if (n < 0) + return n; + } + + n = acquire_time_data(bus, ×); + if (n <= 0) + return n; + + typesafe_qsort(times, n, compare_unit_start); + + width = SCALE_X * (boot->firmware_time + boot->finish_time); + if (width < 800.0) + width = 800.0; + + if (boot->firmware_time > boot->loader_time) + m++; + if (boot->loader_time > 0) { + m++; + if (width < 1000.0) + width = 1000.0; + } + if (boot->initrd_time > 0) + m++; + if (boot->kernel_done_time > 0) + m++; + + for (u = times; u->has_data; u++) { + double text_start, text_width; + + if (u->activating > boot->finish_time) { + u->name = mfree(u->name); + continue; + } + + /* If the text cannot fit on the left side then + * increase the svg width so it fits on the right. + * TODO: calculate the text width more accurately */ + text_width = 8.0 * strlen(u->name); + text_start = (boot->firmware_time + u->activating) * SCALE_X; + if (text_width > text_start && text_width + text_start > width) + width = text_width + text_start; + + if (u->deactivated > u->activating && + u->deactivated <= boot->finish_time && + u->activated == 0 && u->deactivating == 0) + u->activated = u->deactivating = u->deactivated; + if (u->activated < u->activating || u->activated > boot->finish_time) + u->activated = boot->finish_time; + if (u->deactivating < u->activated || u->deactivating > boot->finish_time) + u->deactivating = boot->finish_time; + if (u->deactivated < u->deactivating || u->deactivated > boot->finish_time) + u->deactivated = boot->finish_time; + m++; + } + + svg("\n" + "\n"); + + svg("\n\n", + 80.0 + width, 150.0 + (m * SCALE_Y) + + 5 * SCALE_Y /* legend */); + + /* write some basic info as a comment, including some help */ + svg("\n" + "\n" + "\n" + "\n" + "\n\n" + "\n\n", GIT_VERSION); + + /* style sheet */ + svg("\n \n\n\n"); + + svg("\n"); + svg("%s", pretty_times); + if (host) + svg("%s %s (%s %s %s) %s %s", + isempty(host->os_pretty_name) ? "Linux" : host->os_pretty_name, + strempty(host->hostname), + strempty(host->kernel_name), + strempty(host->kernel_release), + strempty(host->kernel_version), + strempty(host->architecture), + strempty(host->virtualization)); + + svg("\n", 20.0 + (SCALE_X * boot->firmware_time)); + svg_graph_box(m, -(double) boot->firmware_time, boot->finish_time); + + if (boot->firmware_time > 0) { + svg_bar("firmware", -(double) boot->firmware_time, -(double) boot->loader_time, y); + svg_text(true, -(double) boot->firmware_time, y, "firmware"); + y++; + } + if (boot->loader_time > 0) { + svg_bar("loader", -(double) boot->loader_time, 0, y); + svg_text(true, -(double) boot->loader_time, y, "loader"); + y++; + } + if (boot->kernel_done_time > 0) { + svg_bar("kernel", 0, boot->kernel_done_time, y); + svg_text(true, 0, y, "kernel"); + y++; + } + if (boot->initrd_time > 0) { + svg_bar("initrd", boot->initrd_time, boot->userspace_time, y); + if (boot->initrd_security_start_time < boot->initrd_security_finish_time) + svg_bar("security", boot->initrd_security_start_time, boot->initrd_security_finish_time, y); + if (boot->initrd_generators_start_time < boot->initrd_generators_finish_time) + svg_bar("generators", boot->initrd_generators_start_time, boot->initrd_generators_finish_time, y); + if (boot->initrd_unitsload_start_time < boot->initrd_unitsload_finish_time) + svg_bar("unitsload", boot->initrd_unitsload_start_time, boot->initrd_unitsload_finish_time, y); + svg_text(true, boot->initrd_time, y, "initrd"); + y++; + } + + for (u = times; u->has_data; u++) { + if (u->activating >= boot->userspace_time) + break; + + y += plot_unit_times(u, width, y); + } + + svg_bar("active", boot->userspace_time, boot->finish_time, y); + if (boot->security_start_time > 0) + svg_bar("security", boot->security_start_time, boot->security_finish_time, y); + svg_bar("generators", boot->generators_start_time, boot->generators_finish_time, y); + svg_bar("unitsload", boot->unitsload_start_time, boot->unitsload_finish_time, y); + svg_text(true, boot->userspace_time, y, "systemd"); + y++; + + for (; u->has_data; u++) + y += plot_unit_times(u, width, y); + + svg("\n"); + + /* Legend */ + svg("\n"); + y++; + svg_bar("activating", 0, 300000, y); + svg_text(true, 400000, y, "Activating"); + y++; + svg_bar("active", 0, 300000, y); + svg_text(true, 400000, y, "Active"); + y++; + svg_bar("deactivating", 0, 300000, y); + svg_text(true, 400000, y, "Deactivating"); + y++; + if (boot->security_start_time > 0) { + svg_bar("security", 0, 300000, y); + svg_text(true, 400000, y, "Setting up security module"); + y++; + } + svg_bar("generators", 0, 300000, y); + svg_text(true, 400000, y, "Generators"); + y++; + svg_bar("unitsload", 0, 300000, y); + svg_text(true, 400000, y, "Loading unit files"); + y++; + + svg("\n\n"); + + svg("\n"); + + return 0; +} + +static int list_dependencies_print( + const char *name, + unsigned level, + unsigned branches, + bool last, + struct unit_times *times, + struct boot_times *boot) { + + unsigned i; + char ts[FORMAT_TIMESPAN_MAX], ts2[FORMAT_TIMESPAN_MAX]; + + for (i = level; i != 0; i--) + printf("%s", special_glyph(branches & (1 << (i-1)) ? SPECIAL_GLYPH_TREE_VERTICAL : SPECIAL_GLYPH_TREE_SPACE)); + + printf("%s", special_glyph(last ? SPECIAL_GLYPH_TREE_RIGHT : SPECIAL_GLYPH_TREE_BRANCH)); + + if (times) { + if (times->time > 0) + printf("%s%s @%s +%s%s", ansi_highlight_red(), name, + format_timespan(ts, sizeof(ts), times->activating - boot->userspace_time, USEC_PER_MSEC), + format_timespan(ts2, sizeof(ts2), times->time, USEC_PER_MSEC), ansi_normal()); + else if (times->activated > boot->userspace_time) + printf("%s @%s", name, format_timespan(ts, sizeof(ts), times->activated - boot->userspace_time, USEC_PER_MSEC)); + else + printf("%s", name); + } else + printf("%s", name); + printf("\n"); + + return 0; +} + +static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) { + _cleanup_free_ char *path = NULL; + + assert(bus); + assert(name); + assert(deps); + + path = unit_dbus_path_from_name(name); + if (!path) + return -ENOMEM; + + return bus_get_unit_property_strv(bus, path, "After", deps); +} + +static Hashmap *unit_times_hashmap; + +static int list_dependencies_compare(char *const *a, char *const *b) { + usec_t usa = 0, usb = 0; + struct unit_times *times; + + times = hashmap_get(unit_times_hashmap, *a); + if (times) + usa = times->activated; + times = hashmap_get(unit_times_hashmap, *b); + if (times) + usb = times->activated; + + return CMP(usb, usa); +} + +static bool times_in_range(const struct unit_times *times, const struct boot_times *boot) { + return times && times->activated > 0 && times->activated <= boot->finish_time; +} + +static int list_dependencies_one(sd_bus *bus, const char *name, unsigned level, char ***units, unsigned branches) { + _cleanup_strv_free_ char **deps = NULL; + char **c; + int r = 0; + usec_t service_longest = 0; + int to_print = 0; + struct unit_times *times; + struct boot_times *boot; + + if (strv_extend(units, name)) + return log_oom(); + + r = list_dependencies_get_dependencies(bus, name, &deps); + if (r < 0) + return r; + + typesafe_qsort(deps, strv_length(deps), list_dependencies_compare); + + r = acquire_boot_times(bus, &boot); + if (r < 0) + return r; + + STRV_FOREACH(c, deps) { + times = hashmap_get(unit_times_hashmap, *c); + if (times_in_range(times, boot) && times->activated >= service_longest) + service_longest = times->activated; + } + + if (service_longest == 0) + return r; + + STRV_FOREACH(c, deps) { + times = hashmap_get(unit_times_hashmap, *c); + if (times_in_range(times, boot) && service_longest - times->activated <= arg_fuzz) + to_print++; + } + + if (!to_print) + return r; + + STRV_FOREACH(c, deps) { + times = hashmap_get(unit_times_hashmap, *c); + if (!times_in_range(times, boot) || service_longest - times->activated > arg_fuzz) + continue; + + to_print--; + + r = list_dependencies_print(*c, level, branches, to_print == 0, times, boot); + if (r < 0) + return r; + + if (strv_contains(*units, *c)) { + r = list_dependencies_print("...", level + 1, (branches << 1) | (to_print ? 1 : 0), + true, NULL, boot); + if (r < 0) + return r; + continue; + } + + r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (to_print ? 1 : 0)); + if (r < 0) + return r; + + if (to_print == 0) + break; + } + return 0; +} + +static int list_dependencies(sd_bus *bus, const char *name) { + _cleanup_strv_free_ char **units = NULL; + char ts[FORMAT_TIMESPAN_MAX]; + struct unit_times *times; + int r; + const char *id; + _cleanup_free_ char *path = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + struct boot_times *boot; + + assert(bus); + + path = unit_dbus_path_from_name(name); + if (!path) + return -ENOMEM; + + r = sd_bus_get_property( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + "Id", + &error, + &reply, + "s"); + if (r < 0) + return log_error_errno(r, "Failed to get ID: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "s", &id); + if (r < 0) + return bus_log_parse_error(r); + + times = hashmap_get(unit_times_hashmap, id); + + r = acquire_boot_times(bus, &boot); + if (r < 0) + return r; + + if (times) { + if (times->time) + printf("%s%s +%s%s\n", ansi_highlight_red(), id, + format_timespan(ts, sizeof(ts), times->time, USEC_PER_MSEC), ansi_normal()); + else if (times->activated > boot->userspace_time) + printf("%s @%s\n", id, format_timespan(ts, sizeof(ts), times->activated - boot->userspace_time, USEC_PER_MSEC)); + else + printf("%s\n", id); + } + + return list_dependencies_one(bus, name, 0, &units, 0); +} + +static int analyze_critical_chain(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(unit_times_freep) struct unit_times *times = NULL; + struct unit_times *u; + Hashmap *h; + int n, r; + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + n = acquire_time_data(bus, ×); + if (n <= 0) + return n; + + h = hashmap_new(&string_hash_ops); + if (!h) + return log_oom(); + + for (u = times; u->has_data; u++) { + r = hashmap_put(h, u->name, u); + if (r < 0) + return log_error_errno(r, "Failed to add entry to hashmap: %m"); + } + unit_times_hashmap = h; + + (void) pager_open(arg_pager_flags); + + puts("The time when unit became active or started is printed after the \"@\" character.\n" + "The time the unit took to start is printed after the \"+\" character.\n"); + + if (argc > 1) { + char **name; + STRV_FOREACH(name, strv_skip(argv, 1)) + list_dependencies(bus, *name); + } else + list_dependencies(bus, SPECIAL_DEFAULT_TARGET); + + h = hashmap_free(h); + return 0; +} + +static int analyze_blame(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(unit_times_freep) struct unit_times *times = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + struct unit_times *u; + TableCell *cell; + int n, r; + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + n = acquire_time_data(bus, ×); + if (n <= 0) + return n; + + table = table_new("time", "unit"); + if (!table) + return log_oom(); + + table_set_header(table, false); + + assert_se(cell = table_get_cell(table, 0, 0)); + r = table_set_ellipsize_percent(table, cell, 100); + if (r < 0) + return r; + + r = table_set_align_percent(table, cell, 100); + if (r < 0) + return r; + + assert_se(cell = table_get_cell(table, 0, 1)); + r = table_set_ellipsize_percent(table, cell, 100); + if (r < 0) + return r; + + r = table_set_sort(table, 0, SIZE_MAX); + if (r < 0) + return r; + + r = table_set_reverse(table, 0, true); + if (r < 0) + return r; + + for (u = times; u->has_data; u++) { + if (u->time <= 0) + continue; + + r = table_add_cell(table, NULL, TABLE_TIMESPAN_MSEC, &u->time); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_STRING, u->name); + if (r < 0) + return r; + } + + (void) pager_open(arg_pager_flags); + + return table_print(table, NULL); +} + +static int analyze_time(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *buf = NULL; + int r; + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = pretty_boot_time(bus, &buf); + if (r < 0) + return r; + + puts(buf); + return 0; +} + +static int graph_one_property( + sd_bus *bus, + const UnitInfo *u, + const char *prop, + const char *color, + char *patterns[], + char *from_patterns[], + char *to_patterns[]) { + + _cleanup_strv_free_ char **units = NULL; + char **unit; + int r; + bool match_patterns; + + assert(u); + assert(prop); + assert(color); + + match_patterns = strv_fnmatch(patterns, u->id, 0); + + if (!strv_isempty(from_patterns) && !match_patterns && !strv_fnmatch(from_patterns, u->id, 0)) + return 0; + + r = bus_get_unit_property_strv(bus, u->unit_path, prop, &units); + if (r < 0) + return r; + + STRV_FOREACH(unit, units) { + bool match_patterns2; + + match_patterns2 = strv_fnmatch(patterns, *unit, 0); + + if (!strv_isempty(to_patterns) && !match_patterns2 && !strv_fnmatch(to_patterns, *unit, 0)) + continue; + + if (!strv_isempty(patterns) && !match_patterns && !match_patterns2) + continue; + + printf("\t\"%s\"->\"%s\" [color=\"%s\"];\n", u->id, *unit, color); + } + + return 0; +} + +static int graph_one(sd_bus *bus, const UnitInfo *u, char *patterns[], char *from_patterns[], char *to_patterns[]) { + int r; + + assert(bus); + assert(u); + + if (IN_SET(arg_dot, DEP_ORDER, DEP_ALL)) { + r = graph_one_property(bus, u, "After", "green", patterns, from_patterns, to_patterns); + if (r < 0) + return r; + } + + if (IN_SET(arg_dot, DEP_REQUIRE, DEP_ALL)) { + r = graph_one_property(bus, u, "Requires", "black", patterns, from_patterns, to_patterns); + if (r < 0) + return r; + r = graph_one_property(bus, u, "Requisite", "darkblue", patterns, from_patterns, to_patterns); + if (r < 0) + return r; + r = graph_one_property(bus, u, "Wants", "grey66", patterns, from_patterns, to_patterns); + if (r < 0) + return r; + r = graph_one_property(bus, u, "Conflicts", "red", patterns, from_patterns, to_patterns); + if (r < 0) + return r; + } + + return 0; +} + +static int expand_patterns(sd_bus *bus, char **patterns, char ***ret) { + _cleanup_strv_free_ char **expanded_patterns = NULL; + char **pattern; + int r; + + STRV_FOREACH(pattern, patterns) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *unit = NULL, *unit_id = NULL; + + if (strv_extend(&expanded_patterns, *pattern) < 0) + return log_oom(); + + if (string_is_glob(*pattern)) + continue; + + unit = unit_dbus_path_from_name(*pattern); + if (!unit) + return log_oom(); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + unit, + "org.freedesktop.systemd1.Unit", + "Id", + &error, + &unit_id); + if (r < 0) + return log_error_errno(r, "Failed to get ID: %s", bus_error_message(&error, r)); + + if (!streq(*pattern, unit_id)) { + if (strv_extend(&expanded_patterns, unit_id) < 0) + return log_oom(); + } + } + + *ret = expanded_patterns; + expanded_patterns = NULL; /* do not free */ + + return 0; +} + +static int dot(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_strv_free_ char **expanded_patterns = NULL; + _cleanup_strv_free_ char **expanded_from_patterns = NULL; + _cleanup_strv_free_ char **expanded_to_patterns = NULL; + int r; + UnitInfo u; + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = expand_patterns(bus, strv_skip(argv, 1), &expanded_patterns); + if (r < 0) + return r; + + r = expand_patterns(bus, arg_dot_from_patterns, &expanded_from_patterns); + if (r < 0) + return r; + + r = expand_patterns(bus, arg_dot_to_patterns, &expanded_to_patterns); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListUnits", + &error, + &reply, + ""); + if (r < 0) + log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); + if (r < 0) + return bus_log_parse_error(r); + + printf("digraph systemd {\n"); + + while ((r = bus_parse_unit_info(reply, &u)) > 0) { + + r = graph_one(bus, &u, expanded_patterns, expanded_from_patterns, expanded_to_patterns); + if (r < 0) + return r; + } + if (r < 0) + return bus_log_parse_error(r); + + printf("}\n"); + + log_info(" Color legend: black = Requires\n" + " dark blue = Requisite\n" + " dark grey = Wants\n" + " red = Conflicts\n" + " green = After\n"); + + if (on_tty()) + log_notice("-- You probably want to process this output with graphviz' dot tool.\n" + "-- Try a shell pipeline like 'systemd-analyze dot | dot -Tsvg > systemd.svg'!\n"); + + return 0; +} + +static int dump_fallback(sd_bus *bus) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *text = NULL; + int r; + + assert(bus); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Dump", + &error, + &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to issue method call Dump: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "s", &text); + if (r < 0) + return bus_log_parse_error(r); + + fputs(text, stdout); + return 0; +} + +static int dump(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int fd = -1; + int r; + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + (void) pager_open(arg_pager_flags); + + if (!sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD)) + return dump_fallback(bus); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "DumpByFileDescriptor", + &error, + &reply, + NULL); + if (r < 0) { + /* fall back to Dump if DumpByFileDescriptor is not supported */ + if (!IN_SET(r, -EACCES, -EBADR)) + return log_error_errno(r, "Failed to issue method call DumpByFileDescriptor: %s", + bus_error_message(&error, r)); + + return dump_fallback(bus); + } + + r = sd_bus_message_read(reply, "h", &fd); + if (r < 0) + return bus_log_parse_error(r); + + fflush(stdout); + return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0); +} + +static int cat_config(int argc, char *argv[], void *userdata) { + char **arg, **list; + int r; + + (void) pager_open(arg_pager_flags); + + list = strv_skip(argv, 1); + STRV_FOREACH(arg, list) { + const char *t = NULL; + + if (arg != list) + print_separator(); + + if (path_is_absolute(*arg)) { + const char *dir; + + NULSTR_FOREACH(dir, CONF_PATHS_NULSTR("")) { + t = path_startswith(*arg, dir); + if (t) + break; + } + + if (!t) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Path %s does not start with any known prefix.", *arg); + } else + t = *arg; + + r = conf_files_cat(arg_root, t); + if (r < 0) + return r; + } + + return 0; +} + +static int set_log_level(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + assert(argc == 2); + assert(argv); + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = sd_bus_set_property( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LogLevel", + &error, + "s", + argv[1]); + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); + + return 0; +} + +static int get_log_level(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *level = NULL; + int r; + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LogLevel", + &error, + &level); + if (r < 0) + return log_error_errno(r, "Failed to get log level: %s", bus_error_message(&error, r)); + + puts(level); + return 0; +} + +static int get_or_set_log_level(int argc, char *argv[], void *userdata) { + return (argc == 1) ? get_log_level(argc, argv, userdata) : set_log_level(argc, argv, userdata); +} + +static int set_log_target(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + assert(argc == 2); + assert(argv); + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = sd_bus_set_property( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LogTarget", + &error, + "s", + argv[1]); + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); + + return 0; +} + +static int get_log_target(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *target = NULL; + int r; + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LogTarget", + &error, + &target); + if (r < 0) + return log_error_errno(r, "Failed to get log target: %s", bus_error_message(&error, r)); + + puts(target); + return 0; +} + +static int get_or_set_log_target(int argc, char *argv[], void *userdata) { + return (argc == 1) ? get_log_target(argc, argv, userdata) : set_log_target(argc, argv, userdata); +} + +static bool strv_fnmatch_strv_or_empty(char* const* patterns, char **strv, int flags) { + char **s; + STRV_FOREACH(s, strv) + if (strv_fnmatch_or_empty(patterns, *s, flags)) + return true; + + return false; +} + +static int do_unit_files(int argc, char *argv[], void *userdata) { + _cleanup_(lookup_paths_free) LookupPaths lp = {}; + _cleanup_hashmap_free_ Hashmap *unit_ids = NULL; + _cleanup_hashmap_free_ Hashmap *unit_names = NULL; + char **patterns = strv_skip(argv, 1); + Iterator i; + const char *k, *dst; + char **v; + int r; + + r = lookup_paths_init(&lp, arg_scope, 0, NULL); + if (r < 0) + return log_error_errno(r, "lookup_paths_init() failed: %m"); + + r = unit_file_build_name_map(&lp, NULL, &unit_ids, &unit_names, NULL); + if (r < 0) + return log_error_errno(r, "unit_file_build_name_map() failed: %m"); + + HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) { + if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) && + !strv_fnmatch_or_empty(patterns, dst, FNM_NOESCAPE)) + continue; + + printf("ids: %s → %s\n", k, dst); + } + + HASHMAP_FOREACH_KEY(v, k, unit_names, i) { + if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) && + !strv_fnmatch_strv_or_empty(patterns, v, FNM_NOESCAPE)) + continue; + + _cleanup_free_ char *j = strv_join(v, ", "); + printf("aliases: %s ← %s\n", k, j); + } + + return 0; +} + +static int dump_unit_paths(int argc, char *argv[], void *userdata) { + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + int r; + char **p; + + r = lookup_paths_init(&paths, arg_scope, 0, NULL); + if (r < 0) + return log_error_errno(r, "lookup_paths_init() failed: %m"); + + STRV_FOREACH(p, paths.search_path) + puts(*p); + + return 0; +} + +static int dump_exit_status(int argc, char *argv[], void *userdata) { + _cleanup_(table_unrefp) Table *table = NULL; + int r; + + table = table_new("name", "status", "class"); + if (!table) + return log_oom(); + + r = table_set_align_percent(table, table_get_cell(table, 0, 1), 100); + if (r < 0) + return log_error_errno(r, "Failed to right-align status: %m"); + + if (strv_isempty(strv_skip(argv, 1))) + for (size_t i = 0; i < ELEMENTSOF(exit_status_mappings); i++) { + if (!exit_status_mappings[i].name) + continue; + + r = table_add_many(table, + TABLE_STRING, exit_status_mappings[i].name, + TABLE_INT, (int) i, + TABLE_STRING, exit_status_class(i)); + if (r < 0) + return r; + } + else + for (int i = 1; i < argc; i++) { + int status; + + status = exit_status_from_string(argv[i]); + if (status < 0) + return log_error_errno(r, "Invalid exit status \"%s\": %m", argv[i]); + + assert(status >= 0 && (size_t) status < ELEMENTSOF(exit_status_mappings)); + r = table_add_many(table, + TABLE_STRING, exit_status_mappings[status].name ?: "-", + TABLE_INT, status, + TABLE_STRING, exit_status_class(status) ?: "-"); + if (r < 0) + return r; + } + + (void) pager_open(arg_pager_flags); + + return table_print(table, NULL); +} + +#if HAVE_SECCOMP + +static int load_kernel_syscalls(Set **ret) { + _cleanup_(set_free_freep) Set *syscalls = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + /* Let's read the available system calls from the list of available tracing events. Slightly dirty, + * but good enough for analysis purposes. */ + + f = fopen("/sys/kernel/tracing/available_events", "re"); + if (!f) { + /* We tried the non-debugfs mount point and that didn't work. If it wasn't mounted, maybe the + * old debugfs mount point works? */ + f = fopen("/sys/kernel/debug/tracing/available_events", "re"); + if (!f) + return log_full_errno(IN_SET(errno, EPERM, EACCES, ENOENT) ? LOG_DEBUG : LOG_WARNING, errno, + "Can't read open tracefs' available_events file: %m"); + } + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *e; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read system call list: %m"); + if (r == 0) + break; + + e = startswith(line, "syscalls:sys_enter_"); + if (!e) + continue; + + /* These are named differently inside the kernel than their external name for historical + * reasons. Let's hide them here. */ + if (STR_IN_SET(e, "newuname", "newfstat", "newstat", "newlstat", "sysctl")) + continue; + + r = set_ensure_allocated(&syscalls, &string_hash_ops); + if (r < 0) + return log_oom(); + + r = set_put_strdup(syscalls, e); + if (r < 0) + return log_error_errno(r, "Failed to add system call to list: %m"); + } + + *ret = TAKE_PTR(syscalls); + return 0; +} + +static void kernel_syscalls_remove(Set *s, const SyscallFilterSet *set) { + const char *syscall; + + NULSTR_FOREACH(syscall, set->value) { + if (syscall[0] == '@') + continue; + + free(set_remove(s, syscall)); + } +} + +static void dump_syscall_filter(const SyscallFilterSet *set) { + const char *syscall; + + printf("%s%s%s\n" + " # %s\n", + ansi_highlight(), + set->name, + ansi_normal(), + set->help); + + NULSTR_FOREACH(syscall, set->value) + printf(" %s%s%s\n", syscall[0] == '@' ? ansi_underline() : "", syscall, ansi_normal()); +} + +static int dump_syscall_filters(int argc, char *argv[], void *userdata) { + bool first = true; + + (void) pager_open(arg_pager_flags); + + if (strv_isempty(strv_skip(argv, 1))) { + _cleanup_(set_free_freep) Set *kernel = NULL; + int i, k; + + k = load_kernel_syscalls(&kernel); + + for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { + const SyscallFilterSet *set = syscall_filter_sets + i; + if (!first) + puts(""); + + dump_syscall_filter(set); + kernel_syscalls_remove(kernel, set); + first = false; + } + + if (k < 0) { + fputc('\n', stdout); + fflush(stdout); + log_notice_errno(k, "# Not showing unlisted system calls, couldn't retrieve kernel system call list: %m"); + } else if (!set_isempty(kernel)) { + _cleanup_free_ char **l = NULL; + char **syscall; + + printf("\n" + "# %sUnlisted System Calls%s (supported by the local kernel, but not included in any of the groups listed above):\n", + ansi_highlight(), ansi_normal()); + + l = set_get_strv(kernel); + if (!l) + return log_oom(); + + strv_sort(l); + + STRV_FOREACH(syscall, l) + printf("# %s\n", *syscall); + } + } else { + char **name; + + STRV_FOREACH(name, strv_skip(argv, 1)) { + const SyscallFilterSet *set; + + if (!first) + puts(""); + + set = syscall_filter_set_find(*name); + if (!set) { + /* make sure the error appears below normal output */ + fflush(stdout); + + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), + "Filter set \"%s\" not found.", *name); + } + + dump_syscall_filter(set); + first = false; + } + } + + return 0; +} + +#else +static int dump_syscall_filters(int argc, char *argv[], void *userdata) { + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Not compiled with syscall filters, sorry."); +} +#endif + +static void parsing_hint(const char *p, bool calendar, bool timestamp, bool timespan) { + if (calendar && calendar_spec_from_string(p, NULL) >= 0) + log_notice("Hint: this expression is a valid calendar specification. " + "Use 'systemd-analyze calendar \"%s\"' instead?", p); + if (timestamp && parse_timestamp(p, NULL) >= 0) + log_notice("Hint: this expression is a valid timestamp. " + "Use 'systemd-analyze timestamp \"%s\"' instead?", p); + if (timespan && parse_time(p, NULL, USEC_PER_SEC) >= 0) + log_notice("Hint: this expression is a valid timespan. " + "Use 'systemd-analyze timespan \"%s\"' instead?", p); +} + +static int dump_timespan(int argc, char *argv[], void *userdata) { + char **input_timespan; + + STRV_FOREACH(input_timespan, strv_skip(argv, 1)) { + _cleanup_(table_unrefp) Table *table = NULL; + usec_t output_usecs; + TableCell *cell; + int r; + + r = parse_time(*input_timespan, &output_usecs, USEC_PER_SEC); + if (r < 0) { + log_error_errno(r, "Failed to parse time span '%s': %m", *input_timespan); + parsing_hint(*input_timespan, true, true, false); + return r; + } + + table = table_new("name", "value"); + if (!table) + return log_oom(); + + table_set_header(table, false); + + assert_se(cell = table_get_cell(table, 0, 0)); + r = table_set_ellipsize_percent(table, cell, 100); + if (r < 0) + return r; + + r = table_set_align_percent(table, cell, 100); + if (r < 0) + return r; + + assert_se(cell = table_get_cell(table, 0, 1)); + r = table_set_ellipsize_percent(table, cell, 100); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_STRING, "Original:"); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_STRING, *input_timespan); + if (r < 0) + return r; + + r = table_add_cell_stringf(table, NULL, "%ss:", special_glyph(SPECIAL_GLYPH_MU)); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_UINT64, &output_usecs); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_STRING, "Human:"); + if (r < 0) + return r; + + r = table_add_cell(table, &cell, TABLE_TIMESPAN, &output_usecs); + if (r < 0) + return r; + + r = table_set_color(table, cell, ansi_highlight()); + if (r < 0) + return r; + + r = table_print(table, NULL); + if (r < 0) + return r; + + if (input_timespan[1]) + putchar('\n'); + } + + return EXIT_SUCCESS; +} + +static int test_timestamp_one(const char *p) { + _cleanup_(table_unrefp) Table *table = NULL; + TableCell *cell; + usec_t usec; + int r; + + r = parse_timestamp(p, &usec); + if (r < 0) { + log_error_errno(r, "Failed to parse \"%s\": %m", p); + parsing_hint(p, true, false, true); + return r; + } + + table = table_new("name", "value"); + if (!table) + return log_oom(); + + table_set_header(table, false); + + assert_se(cell = table_get_cell(table, 0, 0)); + r = table_set_ellipsize_percent(table, cell, 100); + if (r < 0) + return r; + + r = table_set_align_percent(table, cell, 100); + if (r < 0) + return r; + + assert_se(cell = table_get_cell(table, 0, 1)); + r = table_set_ellipsize_percent(table, cell, 100); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_STRING, "Original form:"); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_STRING, p); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_STRING, "Normalized form:"); + if (r < 0) + return r; + + r = table_add_cell(table, &cell, TABLE_TIMESTAMP, &usec); + if (r < 0) + return r; + + r = table_set_color(table, cell, ansi_highlight_blue()); + if (r < 0) + return r; + + if (!in_utc_timezone()) { + r = table_add_cell(table, NULL, TABLE_STRING, "(in UTC):"); + if (r < 0) + return r; + + r = table_add_cell(table, &cell, TABLE_TIMESTAMP_UTC, &usec); + if (r < 0) + return r; + } + + r = table_add_cell(table, NULL, TABLE_STRING, "UNIX seconds:"); + if (r < 0) + return r; + + if (usec % USEC_PER_SEC == 0) + r = table_add_cell_stringf(table, &cell, "@%"PRI_USEC, + usec / USEC_PER_SEC); + else + r = table_add_cell_stringf(table, &cell, "@%"PRI_USEC".%06"PRI_USEC"", + usec / USEC_PER_SEC, + usec % USEC_PER_SEC); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_STRING, "From now:"); + if (r < 0) + return r; + + r = table_add_cell(table, &cell, TABLE_TIMESTAMP_RELATIVE, &usec); + if (r < 0) + return r; + + return table_print(table, NULL); +} + +static int test_timestamp(int argc, char *argv[], void *userdata) { + int ret = 0, r; + char **p; + + STRV_FOREACH(p, strv_skip(argv, 1)) { + r = test_timestamp_one(*p); + if (ret == 0 && r < 0) + ret = r; + + if (*(p + 1)) + putchar('\n'); + } + + return ret; +} + +static int test_calendar_one(usec_t n, const char *p) { + _cleanup_(calendar_spec_freep) CalendarSpec *spec = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + _cleanup_free_ char *t = NULL; + TableCell *cell; + int r; + + r = calendar_spec_from_string(p, &spec); + if (r < 0) { + log_error_errno(r, "Failed to parse calendar specification '%s': %m", p); + parsing_hint(p, false, true, true); + return r; + } + + r = calendar_spec_to_string(spec, &t); + if (r < 0) + return log_error_errno(r, "Failed to format calendar specification '%s': %m", p); + + table = table_new("name", "value"); + if (!table) + return log_oom(); + + table_set_header(table, false); + + assert_se(cell = table_get_cell(table, 0, 0)); + r = table_set_ellipsize_percent(table, cell, 100); + if (r < 0) + return r; + + r = table_set_align_percent(table, cell, 100); + if (r < 0) + return r; + + assert_se(cell = table_get_cell(table, 0, 1)); + r = table_set_ellipsize_percent(table, cell, 100); + if (r < 0) + return r; + + if (!streq(t, p)) { + r = table_add_cell(table, NULL, TABLE_STRING, "Original form:"); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_STRING, p); + if (r < 0) + return r; + } + + r = table_add_cell(table, NULL, TABLE_STRING, "Normalized form:"); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_STRING, t); + if (r < 0) + return r; + + for (unsigned i = 0; i < arg_iterations; i++) { + usec_t next; + + r = calendar_spec_next_usec(spec, n, &next); + if (r == -ENOENT) { + if (i == 0) { + r = table_add_cell(table, NULL, TABLE_STRING, "Next elapse:"); + if (r < 0) + return r; + + r = table_add_cell(table, &cell, TABLE_STRING, "never"); + if (r < 0) + return r; + + r = table_set_color(table, cell, ansi_highlight_yellow()); + if (r < 0) + return r; + } + break; + } + if (r < 0) + return log_error_errno(r, "Failed to determine next elapse for '%s': %m", p); + + if (i == 0) { + r = table_add_cell(table, NULL, TABLE_STRING, "Next elapse:"); + if (r < 0) + return r; + + r = table_add_cell(table, &cell, TABLE_TIMESTAMP, &next); + if (r < 0) + return r; + + r = table_set_color(table, cell, ansi_highlight_blue()); + if (r < 0) + return r; + } else { + int k = DECIMAL_STR_WIDTH(i + 1); + + if (k < 8) + k = 8 - k; + else + k = 0; + + r = table_add_cell_stringf(table, NULL, "Iter. #%u:", i+1); + if (r < 0) + return r; + + r = table_add_cell(table, &cell, TABLE_TIMESTAMP, &next); + if (r < 0) + return r; + + r = table_set_color(table, cell, ansi_highlight_blue()); + if (r < 0) + return r; + } + + if (!in_utc_timezone()) { + r = table_add_cell(table, NULL, TABLE_STRING, "(in UTC):"); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_TIMESTAMP_UTC, &next); + if (r < 0) + return r; + } + + r = table_add_cell(table, NULL, TABLE_STRING, "From now:"); + if (r < 0) + return r; + + r = table_add_cell(table, NULL, TABLE_TIMESTAMP_RELATIVE, &next); + if (r < 0) + return r; + + n = next; + } + + return table_print(table, NULL); +} + +static int test_calendar(int argc, char *argv[], void *userdata) { + int ret = 0, r; + char **p; + usec_t n; + + if (arg_base_time != USEC_INFINITY) + n = arg_base_time; + else + n = now(CLOCK_REALTIME); /* We want to use the same "base" for all expressions */ + + STRV_FOREACH(p, strv_skip(argv, 1)) { + r = test_calendar_one(n, *p); + if (ret == 0 && r < 0) + ret = r; + + if (*(p + 1)) + putchar('\n'); + } + + return ret; +} + +static int service_watchdogs(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int b, r; + + assert(IN_SET(argc, 1, 2)); + assert(argv); + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + if (argc == 1) { + /* get ServiceWatchdogs */ + r = sd_bus_get_property_trivial( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ServiceWatchdogs", + &error, + 'b', + &b); + if (r < 0) + return log_error_errno(r, "Failed to get service-watchdog state: %s", bus_error_message(&error, r)); + + printf("%s\n", yes_no(!!b)); + + } else { + /* set ServiceWatchdogs */ + b = parse_boolean(argv[1]); + if (b < 0) + return log_error_errno(b, "Failed to parse service-watchdogs argument: %m"); + + r = sd_bus_set_property( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ServiceWatchdogs", + &error, + "b", + b); + if (r < 0) + return log_error_errno(r, "Failed to set service-watchdog state: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int do_condition(int argc, char *argv[], void *userdata) { + return verify_conditions(strv_skip(argv, 1), arg_scope); +} + +static int do_verify(int argc, char *argv[], void *userdata) { + return verify_units(strv_skip(argv, 1), arg_scope, arg_man, arg_generators); +} + +static int do_security(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + r = acquire_bus(&bus, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + (void) pager_open(arg_pager_flags); + + return analyze_security(bus, strv_skip(argv, 1), 0); +} + +static int help(int argc, char *argv[], void *userdata) { + _cleanup_free_ char *link = NULL, *dot_link = NULL; + int r; + + (void) pager_open(arg_pager_flags); + + r = terminal_urlify_man("systemd-analyze", "1", &link); + if (r < 0) + return log_oom(); + + /* Not using terminal_urlify_man() for this, since we don't want the "man page" text suffix in this case. */ + r = terminal_urlify("man:dot(1)", "dot(1)", &dot_link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n\n" + "%sProfile systemd, show unit dependencies, check unit files.%s\n" + "\nCommands:\n" + " [time] Print time required to boot the machine\n" + " blame Print list of running units ordered by time to init\n" + " critical-chain [UNIT...] Print a tree of the time critical chain of units\n" + " plot Output SVG graphic showing service initialization\n" + " dot [UNIT...] Output dependency graph in %s format\n" + " dump Output state serialization of service manager\n" + " cat-config Show configuration file and drop-ins\n" + " unit-files List files and symlinks for units\n" + " unit-paths List load directories for units\n" + " exit-status [STATUS...] List exit status definitions\n" + " syscall-filter [NAME...] Print list of syscalls in seccomp filter\n" + " condition CONDITION... Evaluate conditions and asserts\n" + " verify FILE... Check unit files for correctness\n" + " calendar SPEC... Validate repetitive calendar time events\n" + " timestamp TIMESTAMP... Validate a timestamp\n" + " timespan SPAN... Validate a time span\n" + " security [UNIT...] Analyze security of unit\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --system Operate on system systemd instance\n" + " --user Operate on user systemd instance\n" + " --global Operate on global user configuration\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " --order Show only order in the graph\n" + " --require Show only requirement in the graph\n" + " --from-pattern=GLOB Show only origins in the graph\n" + " --to-pattern=GLOB Show only destinations in the graph\n" + " --fuzz=SECONDS Also print services which finished SECONDS earlier\n" + " than the latest in the branch\n" + " --man[=BOOL] Do [not] check for existence of man pages\n" + " --generators[=BOOL] Do [not] run unit generators (requires privileges)\n" + " --iterations=N Show the specified number of iterations\n" + " --base-time=TIMESTAMP Calculate calendar times relative to specified time\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , dot_link + , link + ); + + /* When updating this list, including descriptions, apply changes to + * shell-completion/bash/systemd-analyze and shell-completion/zsh/_systemd-analyze too. */ + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_ORDER, + ARG_REQUIRE, + ARG_ROOT, + ARG_SYSTEM, + ARG_USER, + ARG_GLOBAL, + ARG_DOT_FROM_PATTERN, + ARG_DOT_TO_PATTERN, + ARG_FUZZ, + ARG_NO_PAGER, + ARG_MAN, + ARG_GENERATORS, + ARG_ITERATIONS, + ARG_BASE_TIME, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "order", no_argument, NULL, ARG_ORDER }, + { "require", no_argument, NULL, ARG_REQUIRE }, + { "root", required_argument, NULL, ARG_ROOT }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "user", no_argument, NULL, ARG_USER }, + { "global", no_argument, NULL, ARG_GLOBAL }, + { "from-pattern", required_argument, NULL, ARG_DOT_FROM_PATTERN }, + { "to-pattern", required_argument, NULL, ARG_DOT_TO_PATTERN }, + { "fuzz", required_argument, NULL, ARG_FUZZ }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "man", optional_argument, NULL, ARG_MAN }, + { "generators", optional_argument, NULL, ARG_GENERATORS }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "iterations", required_argument, NULL, ARG_ITERATIONS }, + { "base-time", required_argument, NULL, ARG_BASE_TIME }, + {} + }; + + int r, c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) + switch (c) { + + case 'h': + return help(0, NULL, NULL); + + case ARG_VERSION: + return version(); + + case ARG_ROOT: + arg_root = optarg; + break; + + case ARG_SYSTEM: + arg_scope = UNIT_FILE_SYSTEM; + break; + + case ARG_USER: + arg_scope = UNIT_FILE_USER; + break; + + case ARG_GLOBAL: + arg_scope = UNIT_FILE_GLOBAL; + break; + + case ARG_ORDER: + arg_dot = DEP_ORDER; + break; + + case ARG_REQUIRE: + arg_dot = DEP_REQUIRE; + break; + + case ARG_DOT_FROM_PATTERN: + if (strv_extend(&arg_dot_from_patterns, optarg) < 0) + return log_oom(); + + break; + + case ARG_DOT_TO_PATTERN: + if (strv_extend(&arg_dot_to_patterns, optarg) < 0) + return log_oom(); + + break; + + case ARG_FUZZ: + r = parse_sec(optarg, &arg_fuzz); + if (r < 0) + return r; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case ARG_MAN: + if (optarg) { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse --man= argument."); + + arg_man = r; + } else + arg_man = true; + + break; + + case ARG_GENERATORS: + if (optarg) { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse --generators= argument."); + + arg_generators = r; + } else + arg_generators = true; + + break; + + case ARG_ITERATIONS: + r = safe_atou(optarg, &arg_iterations); + if (r < 0) + return log_error_errno(r, "Failed to parse iterations: %s", optarg); + + break; + + case ARG_BASE_TIME: + r = parse_timestamp(optarg, &arg_base_time); + if (r < 0) + return log_error_errno(r, "Failed to parse --base-time= parameter: %s", optarg); + + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option code."); + } + + if (arg_scope == UNIT_FILE_GLOBAL && + !STR_IN_SET(argv[optind] ?: "time", "dot", "unit-paths", "verify")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --global only makes sense with verbs dot, unit-paths, verify."); + + if (streq_ptr(argv[optind], "cat-config") && arg_scope == UNIT_FILE_USER) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --user is not supported for cat-config right now."); + + if (arg_root && !streq_ptr(argv[optind], "cat-config")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --root is only supported for cat-config right now."); + + return 1; /* work to do */ +} + +static int run(int argc, char *argv[]) { + + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "time", VERB_ANY, 1, VERB_DEFAULT, analyze_time }, + { "blame", VERB_ANY, 1, 0, analyze_blame }, + { "critical-chain", VERB_ANY, VERB_ANY, 0, analyze_critical_chain }, + { "plot", VERB_ANY, 1, 0, analyze_plot }, + { "dot", VERB_ANY, VERB_ANY, 0, dot }, + /* The following seven verbs are deprecated */ + { "log-level", VERB_ANY, 2, 0, get_or_set_log_level }, + { "log-target", VERB_ANY, 2, 0, get_or_set_log_target }, + { "set-log-level", 2, 2, 0, set_log_level }, + { "get-log-level", VERB_ANY, 1, 0, get_log_level }, + { "set-log-target", 2, 2, 0, set_log_target }, + { "get-log-target", VERB_ANY, 1, 0, get_log_target }, + { "service-watchdogs", VERB_ANY, 2, 0, service_watchdogs }, + { "dump", VERB_ANY, 1, 0, dump }, + { "cat-config", 2, VERB_ANY, 0, cat_config }, + { "unit-files", VERB_ANY, VERB_ANY, 0, do_unit_files }, + { "unit-paths", 1, 1, 0, dump_unit_paths }, + { "exit-status", VERB_ANY, VERB_ANY, 0, dump_exit_status }, + { "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters }, + { "condition", 2, VERB_ANY, 0, do_condition }, + { "verify", 2, VERB_ANY, 0, do_verify }, + { "calendar", 2, VERB_ANY, 0, test_calendar }, + { "timestamp", 2, VERB_ANY, 0, test_timestamp }, + { "timespan", 2, VERB_ANY, 0, dump_timespan }, + { "security", VERB_ANY, VERB_ANY, 0, do_security }, + {} + }; + + int r; + + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); /* we want to format/parse floats in C style */ + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/analyze/meson.build b/src/analyze/meson.build new file mode 100644 index 00000000..58760d60 --- /dev/null +++ b/src/analyze/meson.build @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +systemd_analyze_sources = files(''' + analyze.c + analyze-condition.c + analyze-condition.h + analyze-verify.c + analyze-verify.h + analyze-security.c + analyze-security.h +'''.split()) diff --git a/src/ask-password/ask-password.c b/src/ask-password/ask-password.c new file mode 100644 index 00000000..ca6da40b --- /dev/null +++ b/src/ask-password/ask-password.c @@ -0,0 +1,189 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "ask-password-api.h" +#include "def.h" +#include "log.h" +#include "macro.h" +#include "main-func.h" +#include "pretty-print.h" +#include "strv.h" + +static const char *arg_icon = NULL; +static const char *arg_id = NULL; +static const char *arg_keyname = NULL; +static char *arg_message = NULL; +static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC; +static bool arg_multiple = false; +static bool arg_no_output = false; +static AskPasswordFlags arg_flags = ASK_PASSWORD_PUSH_CACHE; + +STATIC_DESTRUCTOR_REGISTER(arg_message, freep); + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-ask-password", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] MESSAGE\n\n" + "Query the user for a system passphrase, via the TTY or an UI agent.\n\n" + " -h --help Show this help\n" + " --icon=NAME Icon name\n" + " --id=ID Query identifier (e.g. \"cryptsetup:/dev/sda5\")\n" + " --keyname=NAME Kernel key name for caching passwords (e.g. \"cryptsetup\")\n" + " --timeout=SEC Timeout in seconds\n" + " --echo Do not mask input (useful for usernames)\n" + " --no-tty Ask question via agent even on TTY\n" + " --accept-cached Accept cached passwords\n" + " --multiple List multiple passwords if available\n" + " --no-output Do not print password to standard output\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_ICON = 0x100, + ARG_TIMEOUT, + ARG_ECHO, + ARG_NO_TTY, + ARG_ACCEPT_CACHED, + ARG_MULTIPLE, + ARG_ID, + ARG_KEYNAME, + ARG_NO_OUTPUT, + ARG_VERSION, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "icon", required_argument, NULL, ARG_ICON }, + { "timeout", required_argument, NULL, ARG_TIMEOUT }, + { "echo", no_argument, NULL, ARG_ECHO }, + { "no-tty", no_argument, NULL, ARG_NO_TTY }, + { "accept-cached", no_argument, NULL, ARG_ACCEPT_CACHED }, + { "multiple", no_argument, NULL, ARG_MULTIPLE }, + { "id", required_argument, NULL, ARG_ID }, + { "keyname", required_argument, NULL, ARG_KEYNAME }, + { "no-output", no_argument, NULL, ARG_NO_OUTPUT }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_ICON: + arg_icon = optarg; + break; + + case ARG_TIMEOUT: + if (parse_sec(optarg, &arg_timeout) < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse --timeout parameter %s", + optarg); + break; + + case ARG_ECHO: + arg_flags |= ASK_PASSWORD_ECHO; + break; + + case ARG_NO_TTY: + arg_flags |= ASK_PASSWORD_NO_TTY; + break; + + case ARG_ACCEPT_CACHED: + arg_flags |= ASK_PASSWORD_ACCEPT_CACHED; + break; + + case ARG_MULTIPLE: + arg_multiple = true; + break; + + case ARG_ID: + arg_id = optarg; + break; + + case ARG_KEYNAME: + arg_keyname = optarg; + break; + + case ARG_NO_OUTPUT: + arg_no_output = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (argc > optind) { + arg_message = strv_join(argv + optind, " "); + if (!arg_message) + return log_oom(); + } + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_strv_free_erase_ char **l = NULL; + usec_t timeout; + char **p; + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (arg_timeout > 0) + timeout = now(CLOCK_MONOTONIC) + arg_timeout; + else + timeout = 0; + + r = ask_password_auto(arg_message, arg_icon, arg_id, arg_keyname, timeout, arg_flags, &l); + if (r < 0) + return log_error_errno(r, "Failed to query password: %m"); + + STRV_FOREACH(p, l) { + if (!arg_no_output) + puts(*p); + + if (!arg_multiple) + break; + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c new file mode 100644 index 00000000..04844142 --- /dev/null +++ b/src/backlight/backlight.c @@ -0,0 +1,435 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-device.h" + +#include "alloc-util.h" +#include "device-util.h" +#include "escape.h" +#include "fileio.h" +#include "main-func.h" +#include "mkdir.h" +#include "parse-util.h" +#include "reboot-util.h" +#include "string-util.h" +#include "strv.h" +#include "util.h" + +static int find_pci_or_platform_parent(sd_device *device, sd_device **ret) { + const char *subsystem, *sysname, *value; + sd_device *parent; + int r; + + assert(device); + assert(ret); + + r = sd_device_get_parent(device, &parent); + if (r < 0) + return r; + + r = sd_device_get_subsystem(parent, &subsystem); + if (r < 0) + return r; + + r = sd_device_get_sysname(parent, &sysname); + if (r < 0) + return r; + + if (streq(subsystem, "drm")) { + const char *c; + + c = startswith(sysname, "card"); + if (!c) + return -ENODATA; + + c += strspn(c, DIGITS); + if (*c == '-') { + /* A connector DRM device, let's ignore all but LVDS and eDP! */ + if (!STARTSWITH_SET(c, "-LVDS-", "-Embedded DisplayPort-")) + return -EOPNOTSUPP; + } + + } else if (streq(subsystem, "pci") && + sd_device_get_sysattr_value(parent, "class", &value) >= 0) { + unsigned long class = 0; + + r = safe_atolu(value, &class); + if (r < 0) + return log_warning_errno(r, "Cannot parse PCI class '%s' of device %s:%s: %m", + value, subsystem, sysname); + + /* Graphics card */ + if (class == 0x30000) { + *ret = parent; + return 0; + } + + } else if (streq(subsystem, "platform")) { + *ret = parent; + return 0; + } + + return find_pci_or_platform_parent(parent, ret); +} + +static int same_device(sd_device *a, sd_device *b) { + const char *a_val, *b_val; + int r; + + assert(a); + assert(b); + + r = sd_device_get_subsystem(a, &a_val); + if (r < 0) + return r; + + r = sd_device_get_subsystem(b, &b_val); + if (r < 0) + return r; + + if (!streq(a_val, b_val)) + return false; + + r = sd_device_get_sysname(a, &a_val); + if (r < 0) + return r; + + r = sd_device_get_sysname(b, &b_val); + if (r < 0) + return r; + + return streq(a_val, b_val); +} + +static int validate_device(sd_device *device) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *enumerate = NULL; + const char *v, *subsystem; + sd_device *parent, *other; + int r; + + assert(device); + + /* Verify whether we should actually care for a specific + * backlight device. For backlight devices there might be + * multiple ways to access the same control: "firmware" + * (i.e. ACPI), "platform" (i.e. via the machine's EC) and + * "raw" (via the graphics card). In general we should prefer + * "firmware" (i.e. ACPI) or "platform" access over "raw" + * access, in order not to confuse the BIOS/EC, and + * compatibility with possible low-level hotkey handling of + * screen brightness. The kernel will already make sure to + * expose only one of "firmware" and "platform" for the same + * device to userspace. However, we still need to make sure + * that we use "raw" only if no "firmware" or "platform" + * device for the same device exists. */ + + r = sd_device_get_subsystem(device, &subsystem); + if (r < 0) + return r; + if (!streq(subsystem, "backlight")) + return true; + + r = sd_device_get_sysattr_value(device, "type", &v); + if (r < 0) + return r; + if (!streq(v, "raw")) + return true; + + r = find_pci_or_platform_parent(device, &parent); + if (r < 0) + return r; + + r = sd_device_get_subsystem(parent, &subsystem); + if (r < 0) + return r; + + r = sd_device_enumerator_new(&enumerate); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(enumerate); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_subsystem(enumerate, "backlight", true); + if (r < 0) + return r; + + FOREACH_DEVICE(enumerate, other) { + const char *other_subsystem; + sd_device *other_parent; + + if (same_device(device, other) > 0) + continue; + + if (sd_device_get_sysattr_value(other, "type", &v) < 0 || + !STR_IN_SET(v, "platform", "firmware")) + continue; + + /* OK, so there's another backlight device, and it's a + * platform or firmware device, so, let's see if we + * can verify it belongs to the same device as ours. */ + if (find_pci_or_platform_parent(other, &other_parent) < 0) + continue; + + if (same_device(parent, other_parent)) { + const char *device_sysname = NULL, *other_sysname = NULL; + + /* Both have the same PCI parent, that means we are out. */ + + (void) sd_device_get_sysname(device, &device_sysname); + (void) sd_device_get_sysname(other, &other_sysname); + + log_debug("Skipping backlight device %s, since device %s is on same PCI device and takes precedence.", + device_sysname, other_sysname); + return false; + } + + if (sd_device_get_subsystem(other_parent, &other_subsystem) < 0) + continue; + + if (streq(other_subsystem, "platform") && streq(subsystem, "pci")) { + const char *device_sysname = NULL, *other_sysname = NULL; + + /* The other is connected to the platform bus and we are a PCI device, that also means we are out. */ + + (void) sd_device_get_sysname(device, &device_sysname); + (void) sd_device_get_sysname(other, &other_sysname); + + log_debug("Skipping backlight device %s, since device %s is a platform device and takes precedence.", + device_sysname, other_sysname); + return false; + } + } + + return true; +} + +static int get_max_brightness(sd_device *device, unsigned *ret) { + const char *max_brightness_str; + unsigned max_brightness; + int r; + + assert(device); + assert(ret); + + r = sd_device_get_sysattr_value(device, "max_brightness", &max_brightness_str); + if (r < 0) + return log_device_warning_errno(device, r, "Failed to read 'max_brightness' attribute: %m"); + + r = safe_atou(max_brightness_str, &max_brightness); + if (r < 0) + return log_device_warning_errno(device, r, "Failed to parse 'max_brightness' \"%s\": %m", max_brightness_str); + + if (max_brightness <= 0) { + log_device_warning(device, "Maximum brightness is 0, ignoring device."); + return -EINVAL; + } + + *ret = max_brightness; + return 0; +} + +/* Some systems turn the backlight all the way off at the lowest levels. + * clamp_brightness clamps the saved brightness to at least 1 or 5% of + * max_brightness in case of 'backlight' subsystem. This avoids preserving + * an unreadably dim screen, which would otherwise force the user to + * disable state restoration. */ +static int clamp_brightness(sd_device *device, char **value, unsigned max_brightness) { + unsigned brightness, new_brightness, min_brightness; + const char *subsystem; + int r; + + assert(value); + assert(*value); + + r = safe_atou(*value, &brightness); + if (r < 0) + return log_device_warning_errno(device, r, "Failed to parse brightness \"%s\": %m", *value); + + r = sd_device_get_subsystem(device, &subsystem); + if (r < 0) + return log_device_warning_errno(device, r, "Failed to get device subsystem: %m"); + + if (streq(subsystem, "backlight")) + min_brightness = MAX(1U, max_brightness/20); + else + min_brightness = 0; + + new_brightness = CLAMP(brightness, min_brightness, max_brightness); + if (new_brightness != brightness) { + char *new_value; + + r = asprintf(&new_value, "%u", new_brightness); + if (r < 0) + return log_oom(); + + log_device_info(device, "Saved brightness %s %s to %s.", *value, + new_brightness > brightness ? + "too low; increasing" : "too high; decreasing", + new_value); + + free_and_replace(*value, new_value); + } + + return 0; +} + +static bool shall_clamp(sd_device *d) { + const char *s; + int r; + + assert(d); + + r = sd_device_get_property_value(d, "ID_BACKLIGHT_CLAMP", &s); + if (r < 0) { + log_device_debug_errno(d, r, "Failed to get ID_BACKLIGHT_CLAMP property, ignoring: %m"); + return true; + } + + r = parse_boolean(s); + if (r < 0) { + log_device_debug_errno(d, r, "Failed to parse ID_BACKLIGHT_CLAMP property, ignoring: %m"); + return true; + } + + return r; +} + +static int run(int argc, char *argv[]) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + _cleanup_free_ char *escaped_ss = NULL, *escaped_sysname = NULL, *escaped_path_id = NULL; + const char *sysname, *path_id, *ss, *saved; + unsigned max_brightness; + int r; + + if (argc != 3) { + log_error("This program requires two arguments."); + return -EINVAL; + } + + log_setup_service(); + + umask(0022); + + r = mkdir_p("/var/lib/systemd/backlight", 0755); + if (r < 0) + return log_error_errno(r, "Failed to create backlight directory /var/lib/systemd/backlight: %m"); + + sysname = strchr(argv[2], ':'); + if (!sysname) { + log_error("Requires a subsystem and sysname pair specifying a backlight device."); + return -EINVAL; + } + + ss = strndupa(argv[2], sysname - argv[2]); + + sysname++; + + if (!STR_IN_SET(ss, "backlight", "leds")) { + log_error("Not a backlight or LED device: '%s:%s'", ss, sysname); + return -EINVAL; + } + + r = sd_device_new_from_subsystem_sysname(&device, ss, sysname); + if (r < 0) + return log_error_errno(r, "Failed to get backlight or LED device '%s:%s': %m", ss, sysname); + + /* If max_brightness is 0, then there is no actual backlight + * device. This happens on desktops with Asus mainboards + * that load the eeepc-wmi module. */ + if (get_max_brightness(device, &max_brightness) < 0) + return 0; + + escaped_ss = cescape(ss); + if (!escaped_ss) + return log_oom(); + + escaped_sysname = cescape(sysname); + if (!escaped_sysname) + return log_oom(); + + if (sd_device_get_property_value(device, "ID_PATH", &path_id) >= 0) { + escaped_path_id = cescape(path_id); + if (!escaped_path_id) + return log_oom(); + + saved = strjoina("/var/lib/systemd/backlight/", escaped_path_id, ":", escaped_ss, ":", escaped_sysname); + } else + saved = strjoina("/var/lib/systemd/backlight/", escaped_ss, ":", escaped_sysname); + + /* If there are multiple conflicting backlight devices, then + * their probing at boot-time might happen in any order. This + * means the validity checking of the device then is not + * reliable, since it might not see other devices conflicting + * with a specific backlight. To deal with this, we will + * actively delete backlight state files at shutdown (where + * device probing should be complete), so that the validity + * check at boot time doesn't have to be reliable. */ + + if (streq(argv[1], "load")) { + _cleanup_free_ char *value = NULL; + bool clamp; + + if (shall_restore_state() == 0) + return 0; + + if (validate_device(device) == 0) + return 0; + + clamp = shall_clamp(device); + + r = read_one_line_file(saved, &value); + if (IN_SET(r, -ENOENT, 0)) { + const char *curval; + + /* Fallback to clamping current brightness or exit early if + * clamping is not supported/enabled. */ + if (!clamp) + return 0; + + r = sd_device_get_sysattr_value(device, "brightness", &curval); + if (r < 0) + return log_device_warning_errno(device, r, "Failed to read 'brightness' attribute: %m"); + + value = strdup(curval); + if (!value) + return log_oom(); + } else if (r < 0) + return log_error_errno(r, "Failed to read %s: %m", saved); + + if (clamp) + (void) clamp_brightness(device, &value, max_brightness); + + r = sd_device_set_sysattr_value(device, "brightness", value); + if (r < 0) + return log_device_error_errno(device, r, "Failed to write system 'brightness' attribute: %m"); + + } else if (streq(argv[1], "save")) { + const char *value; + + if (validate_device(device) == 0) { + (void) unlink(saved); + return 0; + } + + r = sd_device_get_sysattr_value(device, "brightness", &value); + if (r < 0) + return log_device_error_errno(device, r, "Failed to read system 'brightness' attribute: %m"); + + r = write_string_file(saved, value, WRITE_STRING_FILE_CREATE); + if (r < 0) + return log_device_error_errno(device, r, "Failed to write %s: %m", saved); + + } else { + log_error("Unknown verb %s.", argv[1]); + return -EINVAL; + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/basic/MurmurHash2.c b/src/basic/MurmurHash2.c new file mode 100644 index 00000000..5859af0a --- /dev/null +++ b/src/basic/MurmurHash2.c @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// MurmurHash2 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +// Note - This code makes a few assumptions about how your machine behaves - + +// 1. We can read a 4-byte value from any address without crashing +// 2. sizeof(int) == 4 + +// And it has a few limitations - + +// 1. It will not work incrementally. +// 2. It will not produce the same results on little-endian and big-endian +// machines. + +#include "MurmurHash2.h" + +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif + +//----------------------------------------------------------------------------- +// Platform-specific functions and macros + +// Microsoft Visual Studio + +#if defined(_MSC_VER) + +#define BIG_CONSTANT(x) (x) + +// Other compilers + +#else // defined(_MSC_VER) + +#define BIG_CONSTANT(x) (x##LLU) + +#endif // !defined(_MSC_VER) + +//----------------------------------------------------------------------------- + +uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed ) +{ + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + + const uint32_t m = 0x5bd1e995; + const int r = 24; + + // Initialize the hash to a 'random' value + + uint32_t h = seed ^ len; + + // Mix 4 bytes at a time into the hash + + const unsigned char * data = (const unsigned char *)key; + + while (len >= 4) + { + uint32_t k = *(uint32_t*)data; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + data += 4; + len -= 4; + } + + // Handle the last few bytes of the input array + + switch(len) + { + case 3: h ^= data[2] << 16; /* fall through */ + case 2: h ^= data[1] << 8; /* fall through */ + case 1: h ^= data[0]; /* fall through */ + h *= m; + }; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} diff --git a/src/basic/MurmurHash2.h b/src/basic/MurmurHash2.h new file mode 100644 index 00000000..1aef3afb --- /dev/null +++ b/src/basic/MurmurHash2.h @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// MurmurHash2 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +#pragma once + +//----------------------------------------------------------------------------- +// Platform-specific functions and macros + +// Microsoft Visual Studio + +#if defined(_MSC_VER) + +typedef unsigned char uint8_t; +typedef unsigned long uint32_t; +typedef unsigned __int64 uint64_t; + +// Other compilers + +#else // defined(_MSC_VER) + +#include + +#endif // !defined(_MSC_VER) + +//----------------------------------------------------------------------------- + +uint32_t MurmurHash2 ( const void * key, int len, uint32_t seed ); + +//----------------------------------------------------------------------------- diff --git a/src/basic/af-list.c b/src/basic/af-list.c new file mode 100644 index 00000000..abad221d --- /dev/null +++ b/src/basic/af-list.c @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "af-list.h" +#include "macro.h" + +static const struct af_name* lookup_af(register const char *str, register GPERF_LEN_TYPE len); + +#include "af-from-name.h" +#include "af-to-name.h" + +const char *af_to_name(int id) { + + if (id <= 0) + return NULL; + + if ((size_t) id >= ELEMENTSOF(af_names)) + return NULL; + + return af_names[id]; +} + +int af_from_name(const char *name) { + const struct af_name *sc; + + assert(name); + + sc = lookup_af(name, strlen(name)); + if (!sc) + return -EINVAL; + + return sc->id; +} + +int af_max(void) { + return ELEMENTSOF(af_names); +} diff --git a/src/basic/af-list.h b/src/basic/af-list.h new file mode 100644 index 00000000..8342323b --- /dev/null +++ b/src/basic/af-list.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "string-util.h" + +const char *af_to_name(int id); +int af_from_name(const char *name); + +static inline const char* af_to_name_short(int id) { + const char *f; + + if (id == AF_UNSPEC) + return "*"; + + f = af_to_name(id); + if (!f) + return "unknown"; + + assert(startswith(f, "AF_")); + return f + 3; +} + +int af_max(void); diff --git a/src/basic/af-to-name.awk b/src/basic/af-to-name.awk new file mode 100644 index 00000000..18d0a897 --- /dev/null +++ b/src/basic/af-to-name.awk @@ -0,0 +1,9 @@ +BEGIN{ + print "static const char* const af_names[] = { " +} +!/AF_FILE/ && !/AF_ROUTE/ && !/AF_LOCAL/ { + printf " [%s] = \"%s\",\n", $1, $1 +} +END{ + print "};" +} diff --git a/src/basic/alloc-util.c b/src/basic/alloc-util.c new file mode 100644 index 00000000..5951e8c3 --- /dev/null +++ b/src/basic/alloc-util.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "macro.h" +#include "memory-util.h" + +void* memdup(const void *p, size_t l) { + void *ret; + + assert(l == 0 || p); + + ret = malloc(l ?: 1); + if (!ret) + return NULL; + + memcpy(ret, p, l); + return ret; +} + +void* memdup_suffix0(const void *p, size_t l) { + void *ret; + + assert(l == 0 || p); + + /* The same as memdup() but place a safety NUL byte after the allocated memory */ + + if (_unlikely_(l == SIZE_MAX)) /* prevent overflow */ + return NULL; + + ret = malloc(l + 1); + if (!ret) + return NULL; + + *((uint8_t*) mempcpy(ret, p, l)) = 0; + return ret; +} + +void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) { + size_t a, newalloc; + void *q; + + assert(p); + assert(allocated); + + if (*allocated >= need) + return *p; + + if (_unlikely_(need > SIZE_MAX/2)) /* Overflow check */ + return NULL; + + newalloc = need * 2; + if (size_multiply_overflow(newalloc, size)) + return NULL; + + a = newalloc * size; + if (a < 64) /* Allocate at least 64 bytes */ + a = 64; + + q = realloc(*p, a); + if (!q) + return NULL; + + if (size > 0) { + size_t bn; + + /* Adjust for the 64 byte minimum */ + newalloc = a / size; + + bn = malloc_usable_size(q) / size; + if (bn > newalloc) { + void *qq; + + /* The actual size allocated is larger than what we asked for. Let's call realloc() again to + * take possession of the extra space. This should be cheap, since libc doesn't have to move + * the memory for this. */ + + qq = reallocarray(q, bn, size); + if (_likely_(qq)) { + *p = qq; + *allocated = bn; + return qq; + } + } + } + + *p = q; + *allocated = newalloc; + return q; +} + +void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) { + size_t prev; + uint8_t *q; + + assert(p); + assert(allocated); + + prev = *allocated; + + q = greedy_realloc(p, allocated, need, size); + if (!q) + return NULL; + + if (*allocated > prev) + memzero(q + prev * size, (*allocated - prev) * size); + + return q; +} diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h new file mode 100644 index 00000000..64d9e003 --- /dev/null +++ b/src/basic/alloc-util.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "macro.h" + +#if HAS_FEATURE_MEMORY_SANITIZER +# include +#endif + +typedef void (*free_func_t)(void *p); + +/* If for some reason more than 4M are allocated on the stack, let's abort immediately. It's better than + * proceeding and smashing the stack limits. Note that by default RLIMIT_STACK is 8M on Linux. */ +#define ALLOCA_MAX (4U*1024U*1024U) + +#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n))) + +#define new0(t, n) ((t*) calloc((n) ?: 1, sizeof(t))) + +#define newa(t, n) \ + ({ \ + size_t _n_ = n; \ + assert(!size_multiply_overflow(sizeof(t), _n_)); \ + assert(sizeof(t)*_n_ <= ALLOCA_MAX); \ + (t*) alloca(sizeof(t)*_n_); \ + }) + +#define newa0(t, n) \ + ({ \ + size_t _n_ = n; \ + assert(!size_multiply_overflow(sizeof(t), _n_)); \ + assert(sizeof(t)*_n_ <= ALLOCA_MAX); \ + (t*) alloca0(sizeof(t)*_n_); \ + }) + +#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n))) + +#define newdup_suffix0(t, p, n) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) + +#define malloc0(n) (calloc(1, (n))) + +static inline void *mfree(void *memory) { + free(memory); + return NULL; +} + +#define free_and_replace(a, b) \ + ({ \ + free(a); \ + (a) = (b); \ + (b) = NULL; \ + 0; \ + }) + +void* memdup(const void *p, size_t l) _alloc_(2); +void* memdup_suffix0(const void *p, size_t l); /* We can't use _alloc_() here, since we return a buffer one byte larger than the specified size */ + +#define memdupa(p, l) \ + ({ \ + void *_q_; \ + size_t _l_ = l; \ + assert(_l_ <= ALLOCA_MAX); \ + _q_ = alloca(_l_); \ + memcpy(_q_, p, _l_); \ + }) + +#define memdupa_suffix0(p, l) \ + ({ \ + void *_q_; \ + size_t _l_ = l; \ + assert(_l_ <= ALLOCA_MAX); \ + _q_ = alloca(_l_ + 1); \ + ((uint8_t*) _q_)[_l_] = 0; \ + memcpy(_q_, p, _l_); \ + }) + +static inline void freep(void *p) { + free(*(void**) p); +} + +#define _cleanup_free_ _cleanup_(freep) + +static inline bool size_multiply_overflow(size_t size, size_t need) { + return _unlikely_(need != 0 && size > (SIZE_MAX / need)); +} + +_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) { + if (size_multiply_overflow(size, need)) + return NULL; + + return malloc(size * need ?: 1); +} + +#if !HAVE_REALLOCARRAY +_alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) { + if (size_multiply_overflow(size, need)) + return NULL; + + return realloc(p, size * need ?: 1); +} +#endif + +_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) { + if (size_multiply_overflow(size, need)) + return NULL; + + return memdup(p, size * need); +} + +/* Note that we can't decorate this function with _alloc_() since the returned memory area is one byte larger + * than the product of its parameters. */ +static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) { + if (size_multiply_overflow(size, need)) + return NULL; + + return memdup_suffix0(p, size * need); +} + +void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); +void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); + +#define GREEDY_REALLOC(array, allocated, need) \ + greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0])) + +#define GREEDY_REALLOC0(array, allocated, need) \ + greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0])) + +#define alloca0(n) \ + ({ \ + char *_new_; \ + size_t _len_ = n; \ + assert(_len_ <= ALLOCA_MAX); \ + _new_ = alloca(_len_); \ + (void *) memset(_new_, 0, _len_); \ + }) + +/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */ +#define alloca_align(size, align) \ + ({ \ + void *_ptr_; \ + size_t _mask_ = (align) - 1; \ + size_t _size_ = size; \ + assert(_size_ <= ALLOCA_MAX); \ + _ptr_ = alloca(_size_ + _mask_); \ + (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ + }) + +#define alloca0_align(size, align) \ + ({ \ + void *_new_; \ + size_t _xsize_ = (size); \ + _new_ = alloca_align(_xsize_, (align)); \ + (void*)memset(_new_, 0, _xsize_); \ + }) + +/* Takes inspiration from Rust's Option::take() method: reads and returns a pointer, but at the same time + * resets it to NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */ +#define TAKE_PTR(ptr) \ + ({ \ + typeof(ptr) _ptr_ = (ptr); \ + (ptr) = NULL; \ + _ptr_; \ + }) + +#if HAS_FEATURE_MEMORY_SANITIZER +# define msan_unpoison(r, s) __msan_unpoison(r, s) +#else +# define msan_unpoison(r, s) +#endif diff --git a/src/basic/architecture.c b/src/basic/architecture.c new file mode 100644 index 00000000..85837b5e --- /dev/null +++ b/src/basic/architecture.c @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "architecture.h" +#include "macro.h" +#include "string-table.h" +#include "string-util.h" + +int uname_architecture(void) { + + /* Return a sanitized enum identifying the architecture we are + * running on. This is based on uname(), and the user may + * hence control what this returns by using + * personality(). This puts the user in control on systems + * that can run binaries of multiple architectures. + * + * We do not translate the string returned by uname() + * 1:1. Instead we try to clean it up and break down the + * confusion on x86 and arm in particular. + * + * We do not try to distinguish CPUs not CPU features, but + * actual architectures, i.e. that have genuinely different + * code. */ + + static const struct { + const char *machine; + int arch; + } arch_map[] = { +#if defined(__x86_64__) || defined(__i386__) + { "x86_64", ARCHITECTURE_X86_64 }, + { "i686", ARCHITECTURE_X86 }, + { "i586", ARCHITECTURE_X86 }, + { "i486", ARCHITECTURE_X86 }, + { "i386", ARCHITECTURE_X86 }, +#elif defined(__powerpc__) || defined(__powerpc64__) + { "ppc64", ARCHITECTURE_PPC64 }, + { "ppc64le", ARCHITECTURE_PPC64_LE }, + { "ppc", ARCHITECTURE_PPC }, + { "ppcle", ARCHITECTURE_PPC_LE }, +#elif defined(__ia64__) + { "ia64", ARCHITECTURE_IA64 }, +#elif defined(__hppa__) || defined(__hppa64__) + { "parisc64", ARCHITECTURE_PARISC64 }, + { "parisc", ARCHITECTURE_PARISC }, +#elif defined(__s390__) || defined(__s390x__) + { "s390x", ARCHITECTURE_S390X }, + { "s390", ARCHITECTURE_S390 }, +#elif defined(__sparc__) + { "sparc64", ARCHITECTURE_SPARC64 }, + { "sparc", ARCHITECTURE_SPARC }, +#elif defined(__mips__) || defined(__mips64__) + { "mips64", ARCHITECTURE_MIPS64 }, + { "mips", ARCHITECTURE_MIPS }, +#elif defined(__alpha__) + { "alpha" , ARCHITECTURE_ALPHA }, +#elif defined(__arm__) || defined(__aarch64__) + { "aarch64", ARCHITECTURE_ARM64 }, + { "aarch64_be", ARCHITECTURE_ARM64_BE }, + { "armv4l", ARCHITECTURE_ARM }, + { "armv4b", ARCHITECTURE_ARM_BE }, + { "armv4tl", ARCHITECTURE_ARM }, + { "armv4tb", ARCHITECTURE_ARM_BE }, + { "armv5tl", ARCHITECTURE_ARM }, + { "armv5tb", ARCHITECTURE_ARM_BE }, + { "armv5tel", ARCHITECTURE_ARM }, + { "armv5teb" , ARCHITECTURE_ARM_BE }, + { "armv5tejl", ARCHITECTURE_ARM }, + { "armv5tejb", ARCHITECTURE_ARM_BE }, + { "armv6l", ARCHITECTURE_ARM }, + { "armv6b", ARCHITECTURE_ARM_BE }, + { "armv7l", ARCHITECTURE_ARM }, + { "armv7b", ARCHITECTURE_ARM_BE }, + { "armv7ml", ARCHITECTURE_ARM }, + { "armv7mb", ARCHITECTURE_ARM_BE }, + { "armv4l", ARCHITECTURE_ARM }, + { "armv4b", ARCHITECTURE_ARM_BE }, + { "armv4tl", ARCHITECTURE_ARM }, + { "armv4tb", ARCHITECTURE_ARM_BE }, + { "armv5tl", ARCHITECTURE_ARM }, + { "armv5tb", ARCHITECTURE_ARM_BE }, + { "armv5tel", ARCHITECTURE_ARM }, + { "armv5teb", ARCHITECTURE_ARM_BE }, + { "armv5tejl", ARCHITECTURE_ARM }, + { "armv5tejb", ARCHITECTURE_ARM_BE }, + { "armv6l", ARCHITECTURE_ARM }, + { "armv6b", ARCHITECTURE_ARM_BE }, + { "armv7l", ARCHITECTURE_ARM }, + { "armv7b", ARCHITECTURE_ARM_BE }, + { "armv7ml", ARCHITECTURE_ARM }, + { "armv7mb", ARCHITECTURE_ARM_BE }, + { "armv8l", ARCHITECTURE_ARM }, + { "armv8b", ARCHITECTURE_ARM_BE }, +#elif defined(__sh__) || defined(__sh64__) + { "sh5", ARCHITECTURE_SH64 }, + { "sh2", ARCHITECTURE_SH }, + { "sh2a", ARCHITECTURE_SH }, + { "sh3", ARCHITECTURE_SH }, + { "sh4", ARCHITECTURE_SH }, + { "sh4a", ARCHITECTURE_SH }, +#elif defined(__m68k__) + { "m68k", ARCHITECTURE_M68K }, +#elif defined(__tilegx__) + { "tilegx", ARCHITECTURE_TILEGX }, +#elif defined(__cris__) + { "crisv32", ARCHITECTURE_CRIS }, +#elif defined(__nios2__) + { "nios2", ARCHITECTURE_NIOS2 }, +#elif defined(__riscv__) || defined(__riscv) + /* __riscv__ is obsolete, remove in 2018 */ + { "riscv32", ARCHITECTURE_RISCV32 }, + { "riscv64", ARCHITECTURE_RISCV64 }, +# if __SIZEOF_POINTER__ == 4 + { "riscv", ARCHITECTURE_RISCV32 }, +# elif __SIZEOF_POINTER__ == 8 + { "riscv", ARCHITECTURE_RISCV64 }, +# endif +#elif defined(__arc__) + { "arc", ARCHITECTURE_ARC }, + { "arceb", ARCHITECTURE_ARC_BE }, +#else +#error "Please register your architecture here!" +#endif + }; + + static int cached = _ARCHITECTURE_INVALID; + struct utsname u; + unsigned i; + + if (cached != _ARCHITECTURE_INVALID) + return cached; + + assert_se(uname(&u) >= 0); + + for (i = 0; i < ELEMENTSOF(arch_map); i++) + if (streq(arch_map[i].machine, u.machine)) + return cached = arch_map[i].arch; + + assert_not_reached("Couldn't identify architecture. You need to patch systemd."); + return _ARCHITECTURE_INVALID; +} + +static const char *const architecture_table[_ARCHITECTURE_MAX] = { + [ARCHITECTURE_X86] = "x86", + [ARCHITECTURE_X86_64] = "x86-64", + [ARCHITECTURE_PPC] = "ppc", + [ARCHITECTURE_PPC_LE] = "ppc-le", + [ARCHITECTURE_PPC64] = "ppc64", + [ARCHITECTURE_PPC64_LE] = "ppc64-le", + [ARCHITECTURE_IA64] = "ia64", + [ARCHITECTURE_PARISC] = "parisc", + [ARCHITECTURE_PARISC64] = "parisc64", + [ARCHITECTURE_S390] = "s390", + [ARCHITECTURE_S390X] = "s390x", + [ARCHITECTURE_SPARC] = "sparc", + [ARCHITECTURE_SPARC64] = "sparc64", + [ARCHITECTURE_MIPS] = "mips", + [ARCHITECTURE_MIPS_LE] = "mips-le", + [ARCHITECTURE_MIPS64] = "mips64", + [ARCHITECTURE_MIPS64_LE] = "mips64-le", + [ARCHITECTURE_ALPHA] = "alpha", + [ARCHITECTURE_ARM] = "arm", + [ARCHITECTURE_ARM_BE] = "arm-be", + [ARCHITECTURE_ARM64] = "arm64", + [ARCHITECTURE_ARM64_BE] = "arm64-be", + [ARCHITECTURE_SH] = "sh", + [ARCHITECTURE_SH64] = "sh64", + [ARCHITECTURE_M68K] = "m68k", + [ARCHITECTURE_TILEGX] = "tilegx", + [ARCHITECTURE_CRIS] = "cris", + [ARCHITECTURE_NIOS2] = "nios2", + [ARCHITECTURE_RISCV32] = "riscv32", + [ARCHITECTURE_RISCV64] = "riscv64", + [ARCHITECTURE_ARC] = "arc", + [ARCHITECTURE_ARC_BE] = "arc-be", +}; + +DEFINE_STRING_TABLE_LOOKUP(architecture, int); diff --git a/src/basic/architecture.h b/src/basic/architecture.h new file mode 100644 index 00000000..443e890e --- /dev/null +++ b/src/basic/architecture.h @@ -0,0 +1,237 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" +#include "util.h" + +/* A cleaned up architecture definition. We don't want to get lost in + * processor features, models, generations or even ABIs. Hence we + * focus on general family, and distinguish word width and + * endianness. */ + +enum { + ARCHITECTURE_X86 = 0, + ARCHITECTURE_X86_64, + ARCHITECTURE_PPC, + ARCHITECTURE_PPC_LE, + ARCHITECTURE_PPC64, + ARCHITECTURE_PPC64_LE, + ARCHITECTURE_IA64, + ARCHITECTURE_PARISC, + ARCHITECTURE_PARISC64, + ARCHITECTURE_S390, + ARCHITECTURE_S390X, + ARCHITECTURE_SPARC, + ARCHITECTURE_SPARC64, + ARCHITECTURE_MIPS, + ARCHITECTURE_MIPS_LE, + ARCHITECTURE_MIPS64, + ARCHITECTURE_MIPS64_LE, + ARCHITECTURE_ALPHA, + ARCHITECTURE_ARM, + ARCHITECTURE_ARM_BE, + ARCHITECTURE_ARM64, + ARCHITECTURE_ARM64_BE, + ARCHITECTURE_SH, + ARCHITECTURE_SH64, + ARCHITECTURE_M68K, + ARCHITECTURE_TILEGX, + ARCHITECTURE_CRIS, + ARCHITECTURE_NIOS2, + ARCHITECTURE_RISCV32, + ARCHITECTURE_RISCV64, + ARCHITECTURE_ARC, + ARCHITECTURE_ARC_BE, + _ARCHITECTURE_MAX, + _ARCHITECTURE_INVALID = -1 +}; + +int uname_architecture(void); + +/* + * LIB_ARCH_TUPLE should resolve to the local library path + * architecture tuple systemd is built for, according to the Debian + * tuple list: + * + * https://wiki.debian.org/Multiarch/Tuples + * + * This is used in library search paths that should understand + * Debian's paths on all distributions. + */ + +#if defined(__x86_64__) +# define native_architecture() ARCHITECTURE_X86_64 +# if defined(__ILP32__) +# define LIB_ARCH_TUPLE "x86_64-linux-gnux32" +# else +# define LIB_ARCH_TUPLE "x86_64-linux-gnu" +# endif +# define SECONDARY_ARCHITECTURE ARCHITECTURE_X86 +#elif defined(__i386__) +# define native_architecture() ARCHITECTURE_X86 +# define LIB_ARCH_TUPLE "i386-linux-gnu" +#elif defined(__powerpc64__) +# if __BYTE_ORDER == __BIG_ENDIAN +# define native_architecture() ARCHITECTURE_PPC64 +# define LIB_ARCH_TUPLE "ppc64-linux-gnu" +# define SECONDARY_ARCHITECTURE ARCHITECTURE_PPC +# else +# define native_architecture() ARCHITECTURE_PPC64_LE +# define LIB_ARCH_TUPLE "powerpc64le-linux-gnu" +# define SECONDARY_ARCHITECTURE ARCHITECTURE_PPC_LE +# endif +#elif defined(__powerpc__) +# if __BYTE_ORDER == __BIG_ENDIAN +# define native_architecture() ARCHITECTURE_PPC +# if defined(__NO_FPRS__) +# define LIB_ARCH_TUPLE "powerpc-linux-gnuspe" +# else +# define LIB_ARCH_TUPLE "powerpc-linux-gnu" +# endif +# else +# define native_architecture() ARCHITECTURE_PPC_LE +# error "Missing LIB_ARCH_TUPLE for PPCLE" +# endif +#elif defined(__ia64__) +# define native_architecture() ARCHITECTURE_IA64 +# define LIB_ARCH_TUPLE "ia64-linux-gnu" +#elif defined(__hppa64__) +# define native_architecture() ARCHITECTURE_PARISC64 +# error "Missing LIB_ARCH_TUPLE for HPPA64" +#elif defined(__hppa__) +# define native_architecture() ARCHITECTURE_PARISC +# define LIB_ARCH_TUPLE "hppa‑linux‑gnu" +#elif defined(__s390x__) +# define native_architecture() ARCHITECTURE_S390X +# define LIB_ARCH_TUPLE "s390x-linux-gnu" +# define SECONDARY_ARCHITECTURE ARCHITECTURE_S390 +#elif defined(__s390__) +# define native_architecture() ARCHITECTURE_S390 +# define LIB_ARCH_TUPLE "s390-linux-gnu" +#elif defined(__sparc__) && defined (__arch64__) +# define native_architecture() ARCHITECTURE_SPARC64 +# define LIB_ARCH_TUPLE "sparc64-linux-gnu" +#elif defined(__sparc__) +# define native_architecture() ARCHITECTURE_SPARC +# define LIB_ARCH_TUPLE "sparc-linux-gnu" +#elif defined(__mips64) && defined(__LP64__) +# if __BYTE_ORDER == __BIG_ENDIAN +# define native_architecture() ARCHITECTURE_MIPS64 +# define LIB_ARCH_TUPLE "mips64-linux-gnuabi64" +# else +# define native_architecture() ARCHITECTURE_MIPS64_LE +# define LIB_ARCH_TUPLE "mips64el-linux-gnuabi64" +# endif +#elif defined(__mips64) +# if __BYTE_ORDER == __BIG_ENDIAN +# define native_architecture() ARCHITECTURE_MIPS64 +# define LIB_ARCH_TUPLE "mips64-linux-gnuabin32" +# else +# define native_architecture() ARCHITECTURE_MIPS64_LE +# define LIB_ARCH_TUPLE "mips64el-linux-gnuabin32" +# endif +#elif defined(__mips__) +# if __BYTE_ORDER == __BIG_ENDIAN +# define native_architecture() ARCHITECTURE_MIPS +# define LIB_ARCH_TUPLE "mips-linux-gnu" +# else +# define native_architecture() ARCHITECTURE_MIPS_LE +# define LIB_ARCH_TUPLE "mipsel-linux-gnu" +# endif +#elif defined(__alpha__) +# define native_architecture() ARCHITECTURE_ALPHA +# define LIB_ARCH_TUPLE "alpha-linux-gnu" +#elif defined(__aarch64__) +# if __BYTE_ORDER == __BIG_ENDIAN +# define native_architecture() ARCHITECTURE_ARM64_BE +# define LIB_ARCH_TUPLE "aarch64_be-linux-gnu" +# else +# define native_architecture() ARCHITECTURE_ARM64 +# define LIB_ARCH_TUPLE "aarch64-linux-gnu" +# define SECONDARY_ARCHITECTURE ARCHITECTURE_ARM +# endif +#elif defined(__arm__) +# if __BYTE_ORDER == __BIG_ENDIAN +# define native_architecture() ARCHITECTURE_ARM_BE +# if defined(__ARM_EABI__) +# if defined(__ARM_PCS_VFP) +# define LIB_ARCH_TUPLE "armeb-linux-gnueabihf" +# else +# define LIB_ARCH_TUPLE "armeb-linux-gnueabi" +# endif +# else +# define LIB_ARCH_TUPLE "armeb-linux-gnu" +# endif +# else +# define native_architecture() ARCHITECTURE_ARM +# if defined(__ARM_EABI__) +# if defined(__ARM_PCS_VFP) +# define LIB_ARCH_TUPLE "arm-linux-gnueabihf" +# else +# define LIB_ARCH_TUPLE "arm-linux-gnueabi" +# endif +# else +# define LIB_ARCH_TUPLE "arm-linux-gnu" +# endif +# endif +#elif defined(__sh64__) +# define native_architecture() ARCHITECTURE_SH64 +# error "Missing LIB_ARCH_TUPLE for SH64" +#elif defined(__sh__) +# define native_architecture() ARCHITECTURE_SH +# if defined(__SH1__) +# define LIB_ARCH_TUPLE "sh1-linux-gnu" +# elif defined(__SH2__) +# define LIB_ARCH_TUPLE "sh2-linux-gnu" +# elif defined(__SH2A__) +# define LIB_ARCH_TUPLE "sh2a-linux-gnu" +# elif defined(__SH2E__) +# define LIB_ARCH_TUPLE "sh2e-linux-gnu" +# elif defined(__SH3__) +# define LIB_ARCH_TUPLE "sh3-linux-gnu" +# elif defined(__SH3E__) +# define LIB_ARCH_TUPLE "sh3e-linux-gnu" +# elif defined(__SH4__) && !defined(__SH4A__) +# define LIB_ARCH_TUPLE "sh4-linux-gnu" +# elif defined(__SH4A__) +# define LIB_ARCH_TUPLE "sh4a-linux-gnu" +# endif +#elif defined(__m68k__) +# define native_architecture() ARCHITECTURE_M68K +# define LIB_ARCH_TUPLE "m68k-linux-gnu" +#elif defined(__tilegx__) +# define native_architecture() ARCHITECTURE_TILEGX +# define LIB_ARCH_TUPLE "tilegx-linux-gnu" +#elif defined(__cris__) +# define native_architecture() ARCHITECTURE_CRIS +# error "Missing LIB_ARCH_TUPLE for CRIS" +#elif defined(__nios2__) +# define native_architecture() ARCHITECTURE_NIOS2 +# define LIB_ARCH_TUPLE "nios2-linux-gnu" +#elif defined(__riscv__) || defined(__riscv) + /* __riscv__ is obsolete, remove in 2018 */ +# if __SIZEOF_POINTER__ == 4 +# define native_architecture() ARCHITECTURE_RISCV32 +# define LIB_ARCH_TUPLE "riscv32-linux-gnu" +# elif __SIZEOF_POINTER__ == 8 +# define native_architecture() ARCHITECTURE_RISCV64 +# define LIB_ARCH_TUPLE "riscv64-linux-gnu" +# else +# error "Unrecognized riscv architecture variant" +# endif +#elif defined(__arc__) +# if __BYTE_ORDER == __BIG_ENDIAN +# define native_architecture() ARCHITECTURE_ARC_BE +# define LIB_ARCH_TUPLE "arceb-linux" +# else +# define native_architecture() ARCHITECTURE_ARC +# define LIB_ARCH_TUPLE "arc-linux" +# endif +#else +# error "Please register your architecture here!" +#endif + +const char *architecture_to_string(int a) _const_; +int architecture_from_string(const char *s) _pure_; diff --git a/src/basic/arphrd-list.c b/src/basic/arphrd-list.c new file mode 100644 index 00000000..7e5570ab --- /dev/null +++ b/src/basic/arphrd-list.c @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "arphrd-list.h" +#include "macro.h" + +static const struct arphrd_name* lookup_arphrd(register const char *str, register GPERF_LEN_TYPE len); + +#include "arphrd-from-name.h" +#include "arphrd-to-name.h" + +int arphrd_from_name(const char *name) { + const struct arphrd_name *sc; + + assert(name); + + sc = lookup_arphrd(name, strlen(name)); + if (!sc) + return -EINVAL; + + return sc->id; +} diff --git a/src/basic/arphrd-list.h b/src/basic/arphrd-list.h new file mode 100644 index 00000000..aae56bc8 --- /dev/null +++ b/src/basic/arphrd-list.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +const char *arphrd_to_name(int id); +int arphrd_from_name(const char *name); diff --git a/src/basic/arphrd-to-name.awk b/src/basic/arphrd-to-name.awk new file mode 100644 index 00000000..db1c739a --- /dev/null +++ b/src/basic/arphrd-to-name.awk @@ -0,0 +1,12 @@ +BEGIN{ + print "const char *arphrd_to_name(int id) {" + print " switch(id) {" +} +!/^HDLC$/ { + printf " case ARPHRD_%s: return \"%s\";\n", $1, $1 +} +END{ + print " default: return NULL;" + print " }" + print "}" +} diff --git a/src/basic/async.c b/src/basic/async.c new file mode 100644 index 00000000..daa95cd1 --- /dev/null +++ b/src/basic/async.c @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "async.h" +#include "errno-util.h" +#include "fd-util.h" +#include "log.h" +#include "macro.h" +#include "process-util.h" +#include "signal-util.h" +#include "util.h" + +int asynchronous_job(void* (*func)(void *p), void *arg) { + sigset_t ss, saved_ss; + pthread_attr_t a; + pthread_t t; + int r, k; + + /* It kinda sucks that we have to resort to threads to implement an asynchronous close(), but well, such is + * life. */ + + r = pthread_attr_init(&a); + if (r > 0) + return -r; + + r = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); + if (r > 0) { + r = -r; + goto finish; + } + + assert_se(sigfillset(&ss) >= 0); + + /* Block all signals before forking off the thread, so that the new thread is started with all signals + * blocked. This way the existence of the new thread won't affect signal handling in other threads. */ + + r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss); + if (r > 0) { + r = -r; + goto finish; + } + + r = pthread_create(&t, &a, func, arg); + + k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL); + + if (r > 0) + r = -r; + else if (k > 0) + r = -k; + else + r = 0; + +finish: + pthread_attr_destroy(&a); + return r; +} + +int asynchronous_sync(pid_t *ret_pid) { + int r; + + /* This forks off an invocation of fork() as a child process, in order to initiate synchronization to + * disk. Note that we implement this as helper process rather than thread as we don't want the sync() to hang our + * original process ever, and a thread would do that as the process can't exit with threads hanging in blocking + * syscalls. */ + + r = safe_fork("(sd-sync)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, ret_pid); + if (r < 0) + return r; + if (r == 0) { + /* Child process */ + (void) sync(); + _exit(EXIT_SUCCESS); + } + + return 0; +} + +static void *close_thread(void *p) { + (void) pthread_setname_np(pthread_self(), "close"); + + assert_se(close_nointr(PTR_TO_FD(p)) != -EBADF); + return NULL; +} + +int asynchronous_close(int fd) { + int r; + + /* This is supposed to behave similar to safe_close(), but + * actually invoke close() asynchronously, so that it will + * never block. Ideally the kernel would have an API for this, + * but it doesn't, so we work around it, and hide this as a + * far away as we can. */ + + if (fd >= 0) { + PROTECT_ERRNO; + + r = asynchronous_job(close_thread, FD_TO_PTR(fd)); + if (r < 0) + assert_se(close_nointr(fd) != -EBADF); + } + + return -1; +} diff --git a/src/basic/async.h b/src/basic/async.h new file mode 100644 index 00000000..31606131 --- /dev/null +++ b/src/basic/async.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int asynchronous_job(void* (*func)(void *p), void *arg); + +int asynchronous_sync(pid_t *ret_pid); +int asynchronous_close(int fd); diff --git a/src/basic/audit-util.c b/src/basic/audit-util.c new file mode 100644 index 00000000..6eb224b2 --- /dev/null +++ b/src/basic/audit-util.c @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "audit-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "macro.h" +#include "parse-util.h" +#include "process-util.h" +#include "user-util.h" + +int audit_session_from_pid(pid_t pid, uint32_t *id) { + _cleanup_free_ char *s = NULL; + const char *p; + uint32_t u; + int r; + + assert(id); + + /* We don't convert ENOENT to ESRCH here, since we can't + * really distinguish between "audit is not available in the + * kernel" and "the process does not exist", both which will + * result in ENOENT. */ + + p = procfs_file_alloca(pid, "sessionid"); + + r = read_one_line_file(p, &s); + if (r < 0) + return r; + + r = safe_atou32(s, &u); + if (r < 0) + return r; + + if (!audit_session_is_valid(u)) + return -ENODATA; + + *id = u; + return 0; +} + +int audit_loginuid_from_pid(pid_t pid, uid_t *uid) { + _cleanup_free_ char *s = NULL; + const char *p; + uid_t u; + int r; + + assert(uid); + + p = procfs_file_alloca(pid, "loginuid"); + + r = read_one_line_file(p, &s); + if (r < 0) + return r; + + r = parse_uid(s, &u); + if (r == -ENXIO) /* the UID was -1 */ + return -ENODATA; + if (r < 0) + return r; + + *uid = u; + return 0; +} + +bool use_audit(void) { + static int cached_use = -1; + + if (cached_use < 0) { + int fd; + + fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT); + if (fd < 0) { + cached_use = !IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT, EPERM); + if (!cached_use) + log_debug_errno(errno, "Won't talk to audit: %m"); + } else { + cached_use = true; + safe_close(fd); + } + } + + return cached_use; +} diff --git a/src/basic/audit-util.h b/src/basic/audit-util.h new file mode 100644 index 00000000..c9fc4987 --- /dev/null +++ b/src/basic/audit-util.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#define AUDIT_SESSION_INVALID ((uint32_t) -1) + +int audit_session_from_pid(pid_t pid, uint32_t *id); +int audit_loginuid_from_pid(pid_t pid, uid_t *uid); + +bool use_audit(void); + +static inline bool audit_session_is_valid(uint32_t id) { + return id > 0 && id != AUDIT_SESSION_INVALID; +} diff --git a/src/basic/blockdev-util.c b/src/basic/blockdev-util.c new file mode 100644 index 00000000..5372c26b --- /dev/null +++ b/src/basic/blockdev-util.c @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "blockdev-util.h" +#include "btrfs-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "missing_magic.h" +#include "parse-util.h" +#include "stat-util.h" + +int block_get_whole_disk(dev_t d, dev_t *ret) { + char p[SYS_BLOCK_PATH_MAX("/partition")]; + _cleanup_free_ char *s = NULL; + dev_t devt; + int r; + + assert(ret); + + if (major(d) == 0) + return -ENODEV; + + /* If it has a queue this is good enough for us */ + xsprintf_sys_block_path(p, "/queue", d); + if (access(p, F_OK) >= 0) { + *ret = d; + return 0; + } + + /* If it is a partition find the originating device */ + xsprintf_sys_block_path(p, "/partition", d); + if (access(p, F_OK) < 0) + return -errno; + + /* Get parent dev_t */ + xsprintf_sys_block_path(p, "/../dev", d); + r = read_one_line_file(p, &s); + if (r < 0) + return r; + + r = parse_dev(s, &devt); + if (r < 0) + return r; + + /* Only return this if it is really good enough for us. */ + xsprintf_sys_block_path(p, "/queue", devt); + if (access(p, F_OK) < 0) + return -errno; + + *ret = devt; + return 1; +} + +int get_block_device(const char *path, dev_t *dev) { + struct stat st; + struct statfs sfs; + + assert(path); + assert(dev); + + /* Gets the block device directly backing a file system. If + * the block device is encrypted, returns the device mapper + * block device. */ + + if (lstat(path, &st)) + return -errno; + + if (major(st.st_dev) != 0) { + *dev = st.st_dev; + return 1; + } + + if (statfs(path, &sfs) < 0) + return -errno; + + if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC)) + return btrfs_get_block_device(path, dev); + + *dev = 0; + return 0; +} + +int block_get_originating(dev_t dt, dev_t *ret) { + _cleanup_closedir_ DIR *d = NULL; + _cleanup_free_ char *t = NULL; + char p[SYS_BLOCK_PATH_MAX("/slaves")]; + struct dirent *de, *found = NULL; + const char *q; + dev_t devt; + int r; + + /* For the specified block device tries to chase it through the layers, in case LUKS-style DM stacking is used, + * trying to find the next underlying layer. */ + + xsprintf_sys_block_path(p, "/slaves", dt); + d = opendir(p); + if (!d) + return -errno; + + FOREACH_DIRENT_ALL(de, d, return -errno) { + + if (dot_or_dot_dot(de->d_name)) + continue; + + if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN)) + continue; + + if (found) { + _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL; + + /* We found a device backed by multiple other devices. We don't really support automatic + * discovery on such setups, with the exception of dm-verity partitions. In this case there are + * two backing devices: the data partition and the hash partition. We are fine with such + * setups, however, only if both partitions are on the same physical device. Hence, let's + * verify this. */ + + u = path_join(p, de->d_name, "../dev"); + if (!u) + return -ENOMEM; + + v = path_join(p, found->d_name, "../dev"); + if (!v) + return -ENOMEM; + + r = read_one_line_file(u, &a); + if (r < 0) + return log_debug_errno(r, "Failed to read %s: %m", u); + + r = read_one_line_file(v, &b); + if (r < 0) + return log_debug_errno(r, "Failed to read %s: %m", v); + + /* Check if the parent device is the same. If not, then the two backing devices are on + * different physical devices, and we don't support that. */ + if (!streq(a, b)) + return -ENOTUNIQ; + } + + found = de; + } + + if (!found) + return -ENOENT; + + q = strjoina(p, "/", found->d_name, "/dev"); + + r = read_one_line_file(q, &t); + if (r < 0) + return r; + + r = parse_dev(t, &devt); + if (r < 0) + return -EINVAL; + + if (major(devt) == 0) + return -ENOENT; + + *ret = devt; + return 1; +} + +int get_block_device_harder(const char *path, dev_t *ret) { + int r; + + assert(path); + assert(ret); + + /* Gets the backing block device for a file system, and handles LUKS encrypted file systems, looking for its + * immediate parent, if there is one. */ + + r = get_block_device(path, ret); + if (r <= 0) + return r; + + r = block_get_originating(*ret, ret); + if (r < 0) + log_debug_errno(r, "Failed to chase block device '%s', ignoring: %m", path); + + return 1; +} diff --git a/src/basic/blockdev-util.h b/src/basic/blockdev-util.h new file mode 100644 index 00000000..6d8a7965 --- /dev/null +++ b/src/basic/blockdev-util.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" +#include "stdio-util.h" +#include "string-util.h" + +#define SYS_BLOCK_PATH_MAX(suffix) \ + (STRLEN("/sys/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t) + strlen_ptr(suffix)) +#define xsprintf_sys_block_path(buf, suffix, devno) \ + xsprintf(buf, "/sys/dev/block/%u:%u%s", major(devno), minor(devno), strempty(suffix)) + +int block_get_whole_disk(dev_t d, dev_t *ret); +int block_get_originating(dev_t d, dev_t *ret); + +int get_block_device(const char *path, dev_t *dev); + +int get_block_device_harder(const char *path, dev_t *dev); diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c new file mode 100644 index 00000000..18a72177 --- /dev/null +++ b/src/basic/btrfs-util.c @@ -0,0 +1,1986 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "blockdev-util.h" +#include "btrfs-util.h" +#include "chattr-util.h" +#include "copy.h" +#include "device-nodes.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "io-util.h" +#include "macro.h" +#include "path-util.h" +#include "rm-rf.h" +#include "smack-util.h" +#include "sparse-endian.h" +#include "stat-util.h" +#include "string-util.h" +#include "time-util.h" +#include "util.h" + +/* WARNING: Be careful with file system ioctls! When we get an fd, we + * need to make sure it either refers to only a regular file or + * directory, or that it is located on btrfs, before invoking any + * btrfs ioctls. The ioctl numbers are reused by some device drivers + * (such as DRM), and hence might have bad effects when invoked on + * device nodes (that reference drivers) rather than fds to normal + * files or directories. */ + +static int validate_subvolume_name(const char *name) { + + if (!filename_is_valid(name)) + return -EINVAL; + + if (strlen(name) > BTRFS_SUBVOL_NAME_MAX) + return -E2BIG; + + return 0; +} + +static int extract_subvolume_name(const char *path, const char **subvolume) { + const char *fn; + int r; + + assert(path); + assert(subvolume); + + fn = basename(path); + + r = validate_subvolume_name(fn); + if (r < 0) + return r; + + *subvolume = fn; + return 0; +} + +int btrfs_is_filesystem(int fd) { + struct statfs sfs; + + assert(fd >= 0); + + if (fstatfs(fd, &sfs) < 0) + return -errno; + + return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC); +} + +int btrfs_is_subvol_fd(int fd) { + struct stat st; + + assert(fd >= 0); + + /* On btrfs subvolumes always have the inode 256 */ + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode) || st.st_ino != 256) + return 0; + + return btrfs_is_filesystem(fd); +} + +int btrfs_is_subvol(const char *path) { + _cleanup_close_ int fd = -1; + + assert(path); + + fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (fd < 0) + return -errno; + + return btrfs_is_subvol_fd(fd); +} + +int btrfs_subvol_make_fd(int fd, const char *subvolume) { + struct btrfs_ioctl_vol_args args = {}; + _cleanup_close_ int real_fd = -1; + int r; + + assert(subvolume); + + r = validate_subvolume_name(subvolume); + if (r < 0) + return r; + + r = fcntl(fd, F_GETFL); + if (r < 0) + return -errno; + if (FLAGS_SET(r, O_PATH)) { + /* An O_PATH fd was specified, let's convert here to a proper one, as btrfs ioctl's can't deal with + * O_PATH. */ + + real_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (real_fd < 0) + return real_fd; + + fd = real_fd; + } + + strncpy(args.name, subvolume, sizeof(args.name)-1); + + if (ioctl(fd, BTRFS_IOC_SUBVOL_CREATE, &args) < 0) + return -errno; + + return 0; +} + +int btrfs_subvol_make(const char *path) { + _cleanup_close_ int fd = -1; + const char *subvolume; + int r; + + assert(path); + + r = extract_subvolume_name(path, &subvolume); + if (r < 0) + return r; + + fd = open_parent(path, O_CLOEXEC, 0); + if (fd < 0) + return fd; + + return btrfs_subvol_make_fd(fd, subvolume); +} + +int btrfs_subvol_set_read_only_fd(int fd, bool b) { + uint64_t flags, nflags; + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode) || st.st_ino != 256) + return -EINVAL; + + if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0) + return -errno; + + if (b) + nflags = flags | BTRFS_SUBVOL_RDONLY; + else + nflags = flags & ~BTRFS_SUBVOL_RDONLY; + + if (flags == nflags) + return 0; + + if (ioctl(fd, BTRFS_IOC_SUBVOL_SETFLAGS, &nflags) < 0) + return -errno; + + return 0; +} + +int btrfs_subvol_set_read_only(const char *path, bool b) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (fd < 0) + return -errno; + + return btrfs_subvol_set_read_only_fd(fd, b); +} + +int btrfs_subvol_get_read_only_fd(int fd) { + uint64_t flags; + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode) || st.st_ino != 256) + return -EINVAL; + + if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0) + return -errno; + + return !!(flags & BTRFS_SUBVOL_RDONLY); +} + +int btrfs_reflink(int infd, int outfd) { + int r; + + assert(infd >= 0); + assert(outfd >= 0); + + /* Make sure we invoke the ioctl on a regular file, so that no device driver accidentally gets it. */ + + r = fd_verify_regular(outfd); + if (r < 0) + return r; + + if (ioctl(outfd, BTRFS_IOC_CLONE, infd) < 0) + return -errno; + + return 0; +} + +int btrfs_clone_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offset, uint64_t sz) { + struct btrfs_ioctl_clone_range_args args = { + .src_fd = infd, + .src_offset = in_offset, + .src_length = sz, + .dest_offset = out_offset, + }; + int r; + + assert(infd >= 0); + assert(outfd >= 0); + assert(sz > 0); + + r = fd_verify_regular(outfd); + if (r < 0) + return r; + + if (ioctl(outfd, BTRFS_IOC_CLONE_RANGE, &args) < 0) + return -errno; + + return 0; +} + +int btrfs_get_block_device_fd(int fd, dev_t *dev) { + struct btrfs_ioctl_fs_info_args fsi = {}; + uint64_t id; + int r; + + assert(fd >= 0); + assert(dev); + + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (!r) + return -ENOTTY; + + if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0) + return -errno; + + /* We won't do this for btrfs RAID */ + if (fsi.num_devices != 1) { + *dev = 0; + return 0; + } + + for (id = 1; id <= fsi.max_id; id++) { + struct btrfs_ioctl_dev_info_args di = { + .devid = id, + }; + struct stat st; + + if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) { + if (errno == ENODEV) + continue; + + return -errno; + } + + if (stat((char*) di.path, &st) < 0) + return -errno; + + if (!S_ISBLK(st.st_mode)) + return -ENODEV; + + if (major(st.st_rdev) == 0) + return -ENODEV; + + *dev = st.st_rdev; + return 1; + } + + return -ENODEV; +} + +int btrfs_get_block_device(const char *path, dev_t *dev) { + _cleanup_close_ int fd = -1; + + assert(path); + assert(dev); + + fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return -errno; + + return btrfs_get_block_device_fd(fd, dev); +} + +int btrfs_subvol_get_id_fd(int fd, uint64_t *ret) { + struct btrfs_ioctl_ino_lookup_args args = { + .objectid = BTRFS_FIRST_FREE_OBJECTID + }; + int r; + + assert(fd >= 0); + assert(ret); + + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (!r) + return -ENOTTY; + + if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args) < 0) + return -errno; + + *ret = args.treeid; + return 0; +} + +int btrfs_subvol_get_id(int fd, const char *subvol, uint64_t *ret) { + _cleanup_close_ int subvol_fd = -1; + + assert(fd >= 0); + assert(ret); + + subvol_fd = openat(fd, subvol, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (subvol_fd < 0) + return -errno; + + return btrfs_subvol_get_id_fd(subvol_fd, ret); +} + +static bool btrfs_ioctl_search_args_inc(struct btrfs_ioctl_search_args *args) { + assert(args); + + /* the objectid, type, offset together make up the btrfs key, + * which is considered a single 136byte integer when + * comparing. This call increases the counter by one, dealing + * with the overflow between the overflows */ + + if (args->key.min_offset < (uint64_t) -1) { + args->key.min_offset++; + return true; + } + + if (args->key.min_type < (uint8_t) -1) { + args->key.min_type++; + args->key.min_offset = 0; + return true; + } + + if (args->key.min_objectid < (uint64_t) -1) { + args->key.min_objectid++; + args->key.min_offset = 0; + args->key.min_type = 0; + return true; + } + + return 0; +} + +static void btrfs_ioctl_search_args_set(struct btrfs_ioctl_search_args *args, const struct btrfs_ioctl_search_header *h) { + assert(args); + assert(h); + + args->key.min_objectid = h->objectid; + args->key.min_type = h->type; + args->key.min_offset = h->offset; +} + +static int btrfs_ioctl_search_args_compare(const struct btrfs_ioctl_search_args *args) { + int r; + + assert(args); + + /* Compare min and max */ + + r = CMP(args->key.min_objectid, args->key.max_objectid); + if (r != 0) + return r; + + r = CMP(args->key.min_type, args->key.max_type); + if (r != 0) + return r; + + return CMP(args->key.min_offset, args->key.max_offset); +} + +#define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) \ + for ((i) = 0, \ + (sh) = (const struct btrfs_ioctl_search_header*) (args).buf; \ + (i) < (args).key.nr_items; \ + (i)++, \ + (sh) = (const struct btrfs_ioctl_search_header*) ((uint8_t*) (sh) + sizeof(struct btrfs_ioctl_search_header) + (sh)->len)) + +#define BTRFS_IOCTL_SEARCH_HEADER_BODY(sh) \ + ((void*) ((uint8_t*) sh + sizeof(struct btrfs_ioctl_search_header))) + +int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) { + struct btrfs_ioctl_search_args args = { + /* Tree of tree roots */ + .key.tree_id = BTRFS_ROOT_TREE_OBJECTID, + + /* Look precisely for the subvolume items */ + .key.min_type = BTRFS_ROOT_ITEM_KEY, + .key.max_type = BTRFS_ROOT_ITEM_KEY, + + .key.min_offset = 0, + .key.max_offset = (uint64_t) -1, + + /* No restrictions on the other components */ + .key.min_transid = 0, + .key.max_transid = (uint64_t) -1, + }; + + bool found = false; + int r; + + assert(fd >= 0); + assert(ret); + + if (subvol_id == 0) { + r = btrfs_subvol_get_id_fd(fd, &subvol_id); + if (r < 0) + return r; + } else { + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (!r) + return -ENOTTY; + } + + args.key.min_objectid = args.key.max_objectid = subvol_id; + + while (btrfs_ioctl_search_args_compare(&args) <= 0) { + const struct btrfs_ioctl_search_header *sh; + unsigned i; + + args.key.nr_items = 256; + if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) + return -errno; + + if (args.key.nr_items <= 0) + break; + + FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { + + const struct btrfs_root_item *ri; + + /* Make sure we start the next search at least from this entry */ + btrfs_ioctl_search_args_set(&args, sh); + + if (sh->objectid != subvol_id) + continue; + if (sh->type != BTRFS_ROOT_ITEM_KEY) + continue; + + /* Older versions of the struct lacked the otime setting */ + if (sh->len < offsetof(struct btrfs_root_item, otime) + sizeof(struct btrfs_timespec)) + continue; + + ri = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); + + ret->otime = (usec_t) le64toh(ri->otime.sec) * USEC_PER_SEC + + (usec_t) le32toh(ri->otime.nsec) / NSEC_PER_USEC; + + ret->subvol_id = subvol_id; + ret->read_only = le64toh(ri->flags) & BTRFS_ROOT_SUBVOL_RDONLY; + + assert_cc(sizeof(ri->uuid) == sizeof(ret->uuid)); + memcpy(&ret->uuid, ri->uuid, sizeof(ret->uuid)); + memcpy(&ret->parent_uuid, ri->parent_uuid, sizeof(ret->parent_uuid)); + + found = true; + goto finish; + } + + /* Increase search key by one, to read the next item, if we can. */ + if (!btrfs_ioctl_search_args_inc(&args)) + break; + } + +finish: + if (!found) + return -ENODATA; + + return 0; +} + +int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) { + + struct btrfs_ioctl_search_args args = { + /* Tree of quota items */ + .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID, + + /* The object ID is always 0 */ + .key.min_objectid = 0, + .key.max_objectid = 0, + + /* Look precisely for the quota items */ + .key.min_type = BTRFS_QGROUP_STATUS_KEY, + .key.max_type = BTRFS_QGROUP_LIMIT_KEY, + + /* No restrictions on the other components */ + .key.min_transid = 0, + .key.max_transid = (uint64_t) -1, + }; + + bool found_info = false, found_limit = false; + int r; + + assert(fd >= 0); + assert(ret); + + if (qgroupid == 0) { + r = btrfs_subvol_get_id_fd(fd, &qgroupid); + if (r < 0) + return r; + } else { + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (!r) + return -ENOTTY; + } + + args.key.min_offset = args.key.max_offset = qgroupid; + + while (btrfs_ioctl_search_args_compare(&args) <= 0) { + const struct btrfs_ioctl_search_header *sh; + unsigned i; + + args.key.nr_items = 256; + if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) { + if (errno == ENOENT) /* quota tree is missing: quota disabled */ + break; + + return -errno; + } + + if (args.key.nr_items <= 0) + break; + + FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { + + /* Make sure we start the next search at least from this entry */ + btrfs_ioctl_search_args_set(&args, sh); + + if (sh->objectid != 0) + continue; + if (sh->offset != qgroupid) + continue; + + if (sh->type == BTRFS_QGROUP_INFO_KEY) { + const struct btrfs_qgroup_info_item *qii = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); + + ret->referenced = le64toh(qii->rfer); + ret->exclusive = le64toh(qii->excl); + + found_info = true; + + } else if (sh->type == BTRFS_QGROUP_LIMIT_KEY) { + const struct btrfs_qgroup_limit_item *qli = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); + + if (le64toh(qli->flags) & BTRFS_QGROUP_LIMIT_MAX_RFER) + ret->referenced_max = le64toh(qli->max_rfer); + else + ret->referenced_max = (uint64_t) -1; + + if (le64toh(qli->flags) & BTRFS_QGROUP_LIMIT_MAX_EXCL) + ret->exclusive_max = le64toh(qli->max_excl); + else + ret->exclusive_max = (uint64_t) -1; + + found_limit = true; + } + + if (found_info && found_limit) + goto finish; + } + + /* Increase search key by one, to read the next item, if we can. */ + if (!btrfs_ioctl_search_args_inc(&args)) + break; + } + +finish: + if (!found_limit && !found_info) + return -ENODATA; + + if (!found_info) { + ret->referenced = (uint64_t) -1; + ret->exclusive = (uint64_t) -1; + } + + if (!found_limit) { + ret->referenced_max = (uint64_t) -1; + ret->exclusive_max = (uint64_t) -1; + } + + return 0; +} + +int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *ret) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return btrfs_qgroup_get_quota_fd(fd, qgroupid, ret); +} + +int btrfs_subvol_find_subtree_qgroup(int fd, uint64_t subvol_id, uint64_t *ret) { + uint64_t level, lowest = (uint64_t) -1, lowest_qgroupid = 0; + _cleanup_free_ uint64_t *qgroups = NULL; + int r, n, i; + + assert(fd >= 0); + assert(ret); + + /* This finds the "subtree" qgroup for a specific + * subvolume. This only works for subvolumes that have been + * prepared with btrfs_subvol_auto_qgroup_fd() with + * insert_intermediary_qgroup=true (or equivalent). For others + * it will return the leaf qgroup instead. The two cases may + * be distuingished via the return value, which is 1 in case + * an appropriate "subtree" qgroup was found, and 0 + * otherwise. */ + + if (subvol_id == 0) { + r = btrfs_subvol_get_id_fd(fd, &subvol_id); + if (r < 0) + return r; + } + + r = btrfs_qgroupid_split(subvol_id, &level, NULL); + if (r < 0) + return r; + if (level != 0) /* Input must be a leaf qgroup */ + return -EINVAL; + + n = btrfs_qgroup_find_parents(fd, subvol_id, &qgroups); + if (n < 0) + return n; + + for (i = 0; i < n; i++) { + uint64_t id; + + r = btrfs_qgroupid_split(qgroups[i], &level, &id); + if (r < 0) + return r; + + if (id != subvol_id) + continue; + + if (lowest == (uint64_t) -1 || level < lowest) { + lowest_qgroupid = qgroups[i]; + lowest = level; + } + } + + if (lowest == (uint64_t) -1) { + /* No suitable higher-level qgroup found, let's return + * the leaf qgroup instead, and indicate that with the + * return value. */ + + *ret = subvol_id; + return 0; + } + + *ret = lowest_qgroupid; + return 1; +} + +int btrfs_subvol_get_subtree_quota_fd(int fd, uint64_t subvol_id, BtrfsQuotaInfo *ret) { + uint64_t qgroupid; + int r; + + assert(fd >= 0); + assert(ret); + + /* This determines the quota data of the qgroup with the + * lowest level, that shares the id part with the specified + * subvolume. This is useful for determining the quota data + * for entire subvolume subtrees, as long as the subtrees have + * been set up with btrfs_qgroup_subvol_auto_fd() or in a + * compatible way */ + + r = btrfs_subvol_find_subtree_qgroup(fd, subvol_id, &qgroupid); + if (r < 0) + return r; + + return btrfs_qgroup_get_quota_fd(fd, qgroupid, ret); +} + +int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQuotaInfo *ret) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return btrfs_subvol_get_subtree_quota_fd(fd, subvol_id, ret); +} + +int btrfs_defrag_fd(int fd) { + int r; + + assert(fd >= 0); + + r = fd_verify_regular(fd); + if (r < 0) + return r; + + if (ioctl(fd, BTRFS_IOC_DEFRAG, NULL) < 0) + return -errno; + + return 0; +} + +int btrfs_defrag(const char *p) { + _cleanup_close_ int fd = -1; + + fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return btrfs_defrag_fd(fd); +} + +int btrfs_quota_enable_fd(int fd, bool b) { + struct btrfs_ioctl_quota_ctl_args args = { + .cmd = b ? BTRFS_QUOTA_CTL_ENABLE : BTRFS_QUOTA_CTL_DISABLE, + }; + int r; + + assert(fd >= 0); + + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (!r) + return -ENOTTY; + + if (ioctl(fd, BTRFS_IOC_QUOTA_CTL, &args) < 0) + return -errno; + + return 0; +} + +int btrfs_quota_enable(const char *path, bool b) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return btrfs_quota_enable_fd(fd, b); +} + +int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max) { + + struct btrfs_ioctl_qgroup_limit_args args = { + .lim.max_rfer = referenced_max, + .lim.flags = BTRFS_QGROUP_LIMIT_MAX_RFER, + }; + unsigned c; + int r; + + assert(fd >= 0); + + if (qgroupid == 0) { + r = btrfs_subvol_get_id_fd(fd, &qgroupid); + if (r < 0) + return r; + } else { + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (!r) + return -ENOTTY; + } + + args.qgroupid = qgroupid; + + for (c = 0;; c++) { + if (ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &args) < 0) { + + if (errno == EBUSY && c < 10) { + (void) btrfs_quota_scan_wait(fd); + continue; + } + + return -errno; + } + + break; + } + + return 0; +} + +int btrfs_qgroup_set_limit(const char *path, uint64_t qgroupid, uint64_t referenced_max) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return btrfs_qgroup_set_limit_fd(fd, qgroupid, referenced_max); +} + +int btrfs_subvol_set_subtree_quota_limit_fd(int fd, uint64_t subvol_id, uint64_t referenced_max) { + uint64_t qgroupid; + int r; + + assert(fd >= 0); + + r = btrfs_subvol_find_subtree_qgroup(fd, subvol_id, &qgroupid); + if (r < 0) + return r; + + return btrfs_qgroup_set_limit_fd(fd, qgroupid, referenced_max); +} + +int btrfs_subvol_set_subtree_quota_limit(const char *path, uint64_t subvol_id, uint64_t referenced_max) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return btrfs_subvol_set_subtree_quota_limit_fd(fd, subvol_id, referenced_max); +} + +int btrfs_qgroupid_make(uint64_t level, uint64_t id, uint64_t *ret) { + assert(ret); + + if (level >= (UINT64_C(1) << (64 - BTRFS_QGROUP_LEVEL_SHIFT))) + return -EINVAL; + + if (id >= (UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT)) + return -EINVAL; + + *ret = (level << BTRFS_QGROUP_LEVEL_SHIFT) | id; + return 0; +} + +int btrfs_qgroupid_split(uint64_t qgroupid, uint64_t *level, uint64_t *id) { + assert(level || id); + + if (level) + *level = qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT; + + if (id) + *id = qgroupid & ((UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT) - 1); + + return 0; +} + +static int qgroup_create_or_destroy(int fd, bool b, uint64_t qgroupid) { + + struct btrfs_ioctl_qgroup_create_args args = { + .create = b, + .qgroupid = qgroupid, + }; + unsigned c; + int r; + + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (r == 0) + return -ENOTTY; + + for (c = 0;; c++) { + if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) < 0) { + + /* If quota is not enabled, we get EINVAL. Turn this into a recognizable error */ + if (errno == EINVAL) + return -ENOPROTOOPT; + + if (errno == EBUSY && c < 10) { + (void) btrfs_quota_scan_wait(fd); + continue; + } + + return -errno; + } + + break; + } + + return 0; +} + +int btrfs_qgroup_create(int fd, uint64_t qgroupid) { + return qgroup_create_or_destroy(fd, true, qgroupid); +} + +int btrfs_qgroup_destroy(int fd, uint64_t qgroupid) { + return qgroup_create_or_destroy(fd, false, qgroupid); +} + +int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid) { + _cleanup_free_ uint64_t *qgroups = NULL; + uint64_t subvol_id; + int i, n, r; + + /* Destroys the specified qgroup, but unassigns it from all + * its parents first. Also, it recursively destroys all + * qgroups it is assigned to that have the same id part of the + * qgroupid as the specified group. */ + + r = btrfs_qgroupid_split(qgroupid, NULL, &subvol_id); + if (r < 0) + return r; + + n = btrfs_qgroup_find_parents(fd, qgroupid, &qgroups); + if (n < 0) + return n; + + for (i = 0; i < n; i++) { + uint64_t id; + + r = btrfs_qgroupid_split(qgroups[i], NULL, &id); + if (r < 0) + return r; + + r = btrfs_qgroup_unassign(fd, qgroupid, qgroups[i]); + if (r < 0) + return r; + + if (id != subvol_id) + continue; + + /* The parent qgroupid shares the same id part with + * us? If so, destroy it too. */ + + (void) btrfs_qgroup_destroy_recursive(fd, qgroups[i]); + } + + return btrfs_qgroup_destroy(fd, qgroupid); +} + +int btrfs_quota_scan_start(int fd) { + struct btrfs_ioctl_quota_rescan_args args = {}; + + assert(fd >= 0); + + if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN, &args) < 0) + return -errno; + + return 0; +} + +int btrfs_quota_scan_wait(int fd) { + assert(fd >= 0); + + if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_WAIT) < 0) + return -errno; + + return 0; +} + +int btrfs_quota_scan_ongoing(int fd) { + struct btrfs_ioctl_quota_rescan_args args = {}; + + assert(fd >= 0); + + if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_STATUS, &args) < 0) + return -errno; + + return !!args.flags; +} + +static int qgroup_assign_or_unassign(int fd, bool b, uint64_t child, uint64_t parent) { + struct btrfs_ioctl_qgroup_assign_args args = { + .assign = b, + .src = child, + .dst = parent, + }; + unsigned c; + int r; + + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (r == 0) + return -ENOTTY; + + for (c = 0;; c++) { + r = ioctl(fd, BTRFS_IOC_QGROUP_ASSIGN, &args); + if (r < 0) { + if (errno == EBUSY && c < 10) { + (void) btrfs_quota_scan_wait(fd); + continue; + } + + return -errno; + } + + if (r == 0) + return 0; + + /* If the return value is > 0, we need to request a rescan */ + + (void) btrfs_quota_scan_start(fd); + return 1; + } +} + +int btrfs_qgroup_assign(int fd, uint64_t child, uint64_t parent) { + return qgroup_assign_or_unassign(fd, true, child, parent); +} + +int btrfs_qgroup_unassign(int fd, uint64_t child, uint64_t parent) { + return qgroup_assign_or_unassign(fd, false, child, parent); +} + +static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol_id, BtrfsRemoveFlags flags) { + struct btrfs_ioctl_search_args args = { + .key.tree_id = BTRFS_ROOT_TREE_OBJECTID, + + .key.min_objectid = BTRFS_FIRST_FREE_OBJECTID, + .key.max_objectid = BTRFS_LAST_FREE_OBJECTID, + + .key.min_type = BTRFS_ROOT_BACKREF_KEY, + .key.max_type = BTRFS_ROOT_BACKREF_KEY, + + .key.min_transid = 0, + .key.max_transid = (uint64_t) -1, + }; + + struct btrfs_ioctl_vol_args vol_args = {}; + _cleanup_close_ int subvol_fd = -1; + struct stat st; + bool made_writable = false; + int r; + + assert(fd >= 0); + assert(subvolume); + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode)) + return -EINVAL; + + subvol_fd = openat(fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); + if (subvol_fd < 0) + return -errno; + + /* Let's check if this is actually a subvolume. Note that this is mostly redundant, as BTRFS_IOC_SNAP_DESTROY + * would fail anyway if it is not. However, it's a good thing to check this ahead of time so that we can return + * ENOTTY unconditionally in this case. This is different from the ioctl() which will return EPERM/EACCES if we + * don't have the privileges to remove subvolumes, regardless if the specified directory is actually a + * subvolume or not. In order to make it easy for callers to cover the "this is not a btrfs subvolume" case + * let's prefer ENOTTY over EPERM/EACCES though. */ + r = btrfs_is_subvol_fd(subvol_fd); + if (r < 0) + return r; + if (r == 0) /* Not a btrfs subvolume */ + return -ENOTTY; + + if (subvol_id == 0) { + r = btrfs_subvol_get_id_fd(subvol_fd, &subvol_id); + if (r < 0) + return r; + } + + /* First, try to remove the subvolume. If it happens to be + * already empty, this will just work. */ + strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1); + if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) >= 0) { + (void) btrfs_qgroup_destroy_recursive(fd, subvol_id); /* for the leaf subvolumes, the qgroup id is identical to the subvol id */ + return 0; + } + if (!(flags & BTRFS_REMOVE_RECURSIVE) || errno != ENOTEMPTY) + return -errno; + + /* OK, the subvolume is not empty, let's look for child + * subvolumes, and remove them, first */ + + args.key.min_offset = args.key.max_offset = subvol_id; + + while (btrfs_ioctl_search_args_compare(&args) <= 0) { + const struct btrfs_ioctl_search_header *sh; + unsigned i; + + args.key.nr_items = 256; + if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) + return -errno; + + if (args.key.nr_items <= 0) + break; + + FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { + _cleanup_free_ char *p = NULL; + const struct btrfs_root_ref *ref; + struct btrfs_ioctl_ino_lookup_args ino_args; + + btrfs_ioctl_search_args_set(&args, sh); + + if (sh->type != BTRFS_ROOT_BACKREF_KEY) + continue; + if (sh->offset != subvol_id) + continue; + + ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); + + p = strndup((char*) ref + sizeof(struct btrfs_root_ref), le64toh(ref->name_len)); + if (!p) + return -ENOMEM; + + zero(ino_args); + ino_args.treeid = subvol_id; + ino_args.objectid = htole64(ref->dirid); + + if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0) + return -errno; + + if (!made_writable) { + r = btrfs_subvol_set_read_only_fd(subvol_fd, false); + if (r < 0) + return r; + + made_writable = true; + } + + if (isempty(ino_args.name)) + /* Subvolume is in the top-level + * directory of the subvolume. */ + r = subvol_remove_children(subvol_fd, p, sh->objectid, flags); + else { + _cleanup_close_ int child_fd = -1; + + /* Subvolume is somewhere further down, + * hence we need to open the + * containing directory first */ + + child_fd = openat(subvol_fd, ino_args.name, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); + if (child_fd < 0) + return -errno; + + r = subvol_remove_children(child_fd, p, sh->objectid, flags); + } + if (r < 0) + return r; + } + + /* Increase search key by one, to read the next item, if we can. */ + if (!btrfs_ioctl_search_args_inc(&args)) + break; + } + + /* OK, the child subvolumes should all be gone now, let's try + * again to remove the subvolume */ + if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) < 0) + return -errno; + + (void) btrfs_qgroup_destroy_recursive(fd, subvol_id); + return 0; +} + +int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags) { + _cleanup_close_ int fd = -1; + const char *subvolume; + int r; + + assert(path); + + r = extract_subvolume_name(path, &subvolume); + if (r < 0) + return r; + + fd = open_parent(path, O_CLOEXEC, 0); + if (fd < 0) + return fd; + + return subvol_remove_children(fd, subvolume, 0, flags); +} + +int btrfs_subvol_remove_fd(int fd, const char *subvolume, BtrfsRemoveFlags flags) { + return subvol_remove_children(fd, subvolume, 0, flags); +} + +int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupid) { + + struct btrfs_ioctl_search_args args = { + /* Tree of quota items */ + .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID, + + /* The object ID is always 0 */ + .key.min_objectid = 0, + .key.max_objectid = 0, + + /* Look precisely for the quota items */ + .key.min_type = BTRFS_QGROUP_LIMIT_KEY, + .key.max_type = BTRFS_QGROUP_LIMIT_KEY, + + /* For our qgroup */ + .key.min_offset = old_qgroupid, + .key.max_offset = old_qgroupid, + + /* No restrictions on the other components */ + .key.min_transid = 0, + .key.max_transid = (uint64_t) -1, + }; + + int r; + + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (!r) + return -ENOTTY; + + while (btrfs_ioctl_search_args_compare(&args) <= 0) { + const struct btrfs_ioctl_search_header *sh; + unsigned i; + + args.key.nr_items = 256; + if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) { + if (errno == ENOENT) /* quota tree missing: quota is not enabled, hence nothing to copy */ + break; + + return -errno; + } + + if (args.key.nr_items <= 0) + break; + + FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { + const struct btrfs_qgroup_limit_item *qli = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); + struct btrfs_ioctl_qgroup_limit_args qargs; + unsigned c; + + /* Make sure we start the next search at least from this entry */ + btrfs_ioctl_search_args_set(&args, sh); + + if (sh->objectid != 0) + continue; + if (sh->type != BTRFS_QGROUP_LIMIT_KEY) + continue; + if (sh->offset != old_qgroupid) + continue; + + /* We found the entry, now copy things over. */ + + qargs = (struct btrfs_ioctl_qgroup_limit_args) { + .qgroupid = new_qgroupid, + + .lim.max_rfer = le64toh(qli->max_rfer), + .lim.max_excl = le64toh(qli->max_excl), + .lim.rsv_rfer = le64toh(qli->rsv_rfer), + .lim.rsv_excl = le64toh(qli->rsv_excl), + + .lim.flags = le64toh(qli->flags) & (BTRFS_QGROUP_LIMIT_MAX_RFER| + BTRFS_QGROUP_LIMIT_MAX_EXCL| + BTRFS_QGROUP_LIMIT_RSV_RFER| + BTRFS_QGROUP_LIMIT_RSV_EXCL), + }; + + for (c = 0;; c++) { + if (ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &qargs) < 0) { + if (errno == EBUSY && c < 10) { + (void) btrfs_quota_scan_wait(fd); + continue; + } + return -errno; + } + + break; + } + + return 1; + } + + /* Increase search key by one, to read the next item, if we can. */ + if (!btrfs_ioctl_search_args_inc(&args)) + break; + } + + return 0; +} + +static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_subvol_id) { + _cleanup_free_ uint64_t *old_qgroups = NULL, *old_parent_qgroups = NULL; + bool copy_from_parent = false, insert_intermediary_qgroup = false; + int n_old_qgroups, n_old_parent_qgroups, r, i; + uint64_t old_parent_id; + + assert(fd >= 0); + + /* Copies a reduced form of quota information from the old to + * the new subvolume. */ + + n_old_qgroups = btrfs_qgroup_find_parents(fd, old_subvol_id, &old_qgroups); + if (n_old_qgroups <= 0) /* Nothing to copy */ + return n_old_qgroups; + + r = btrfs_subvol_get_parent(fd, old_subvol_id, &old_parent_id); + if (r == -ENXIO) + /* We have no parent, hence nothing to copy. */ + n_old_parent_qgroups = 0; + else if (r < 0) + return r; + else { + n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups); + if (n_old_parent_qgroups < 0) + return n_old_parent_qgroups; + } + + for (i = 0; i < n_old_qgroups; i++) { + uint64_t id; + int j; + + r = btrfs_qgroupid_split(old_qgroups[i], NULL, &id); + if (r < 0) + return r; + + if (id == old_subvol_id) { + /* The old subvolume was member of a qgroup + * that had the same id, but a different level + * as it self. Let's set up something similar + * in the destination. */ + insert_intermediary_qgroup = true; + break; + } + + for (j = 0; j < n_old_parent_qgroups; j++) + if (old_parent_qgroups[j] == old_qgroups[i]) { + /* The old subvolume shared a common + * parent qgroup with its parent + * subvolume. Let's set up something + * similar in the destination. */ + copy_from_parent = true; + } + } + + if (!insert_intermediary_qgroup && !copy_from_parent) + return 0; + + return btrfs_subvol_auto_qgroup_fd(fd, new_subvol_id, insert_intermediary_qgroup); +} + +static int copy_subtree_quota_limits(int fd, uint64_t old_subvol, uint64_t new_subvol) { + uint64_t old_subtree_qgroup, new_subtree_qgroup; + bool changed; + int r; + + /* First copy the leaf limits */ + r = btrfs_qgroup_copy_limits(fd, old_subvol, new_subvol); + if (r < 0) + return r; + changed = r > 0; + + /* Then, try to copy the subtree limits, if there are any. */ + r = btrfs_subvol_find_subtree_qgroup(fd, old_subvol, &old_subtree_qgroup); + if (r < 0) + return r; + if (r == 0) + return changed; + + r = btrfs_subvol_find_subtree_qgroup(fd, new_subvol, &new_subtree_qgroup); + if (r < 0) + return r; + if (r == 0) + return changed; + + r = btrfs_qgroup_copy_limits(fd, old_subtree_qgroup, new_subtree_qgroup); + if (r != 0) + return r; + + return changed; +} + +static int subvol_snapshot_children( + int old_fd, + int new_fd, + const char *subvolume, + uint64_t old_subvol_id, + BtrfsSnapshotFlags flags) { + + struct btrfs_ioctl_search_args args = { + .key.tree_id = BTRFS_ROOT_TREE_OBJECTID, + + .key.min_objectid = BTRFS_FIRST_FREE_OBJECTID, + .key.max_objectid = BTRFS_LAST_FREE_OBJECTID, + + .key.min_type = BTRFS_ROOT_BACKREF_KEY, + .key.max_type = BTRFS_ROOT_BACKREF_KEY, + + .key.min_transid = 0, + .key.max_transid = (uint64_t) -1, + }; + + struct btrfs_ioctl_vol_args_v2 vol_args = { + .flags = flags & BTRFS_SNAPSHOT_READ_ONLY ? BTRFS_SUBVOL_RDONLY : 0, + .fd = old_fd, + }; + _cleanup_close_ int subvolume_fd = -1; + uint64_t new_subvol_id; + int r; + + assert(old_fd >= 0); + assert(new_fd >= 0); + assert(subvolume); + + strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1); + + if (ioctl(new_fd, BTRFS_IOC_SNAP_CREATE_V2, &vol_args) < 0) + return -errno; + + if (!(flags & BTRFS_SNAPSHOT_RECURSIVE) && + !(flags & BTRFS_SNAPSHOT_QUOTA)) + return 0; + + if (old_subvol_id == 0) { + r = btrfs_subvol_get_id_fd(old_fd, &old_subvol_id); + if (r < 0) + return r; + } + + r = btrfs_subvol_get_id(new_fd, vol_args.name, &new_subvol_id); + if (r < 0) + return r; + + if (flags & BTRFS_SNAPSHOT_QUOTA) + (void) copy_quota_hierarchy(new_fd, old_subvol_id, new_subvol_id); + + if (!(flags & BTRFS_SNAPSHOT_RECURSIVE)) { + + if (flags & BTRFS_SNAPSHOT_QUOTA) + (void) copy_subtree_quota_limits(new_fd, old_subvol_id, new_subvol_id); + + return 0; + } + + args.key.min_offset = args.key.max_offset = old_subvol_id; + + while (btrfs_ioctl_search_args_compare(&args) <= 0) { + const struct btrfs_ioctl_search_header *sh; + unsigned i; + + args.key.nr_items = 256; + if (ioctl(old_fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) + return -errno; + + if (args.key.nr_items <= 0) + break; + + FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { + _cleanup_free_ char *p = NULL, *c = NULL, *np = NULL; + struct btrfs_ioctl_ino_lookup_args ino_args; + const struct btrfs_root_ref *ref; + _cleanup_close_ int old_child_fd = -1, new_child_fd = -1; + + btrfs_ioctl_search_args_set(&args, sh); + + if (sh->type != BTRFS_ROOT_BACKREF_KEY) + continue; + + /* Avoid finding the source subvolume a second + * time */ + if (sh->offset != old_subvol_id) + continue; + + /* Avoid running into loops if the new + * subvolume is below the old one. */ + if (sh->objectid == new_subvol_id) + continue; + + ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh); + p = strndup((char*) ref + sizeof(struct btrfs_root_ref), le64toh(ref->name_len)); + if (!p) + return -ENOMEM; + + zero(ino_args); + ino_args.treeid = old_subvol_id; + ino_args.objectid = htole64(ref->dirid); + + if (ioctl(old_fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0) + return -errno; + + c = path_join(ino_args.name, p); + if (!c) + return -ENOMEM; + + old_child_fd = openat(old_fd, c, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); + if (old_child_fd < 0) + return -errno; + + np = path_join(subvolume, ino_args.name); + if (!np) + return -ENOMEM; + + new_child_fd = openat(new_fd, np, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); + if (new_child_fd < 0) + return -errno; + + if (flags & BTRFS_SNAPSHOT_READ_ONLY) { + /* If the snapshot is read-only we + * need to mark it writable + * temporarily, to put the subsnapshot + * into place. */ + + if (subvolume_fd < 0) { + subvolume_fd = openat(new_fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); + if (subvolume_fd < 0) + return -errno; + } + + r = btrfs_subvol_set_read_only_fd(subvolume_fd, false); + if (r < 0) + return r; + } + + /* When btrfs clones the subvolumes, child + * subvolumes appear as empty directories. Remove + * them, so that we can create a new snapshot + * in their place */ + if (unlinkat(new_child_fd, p, AT_REMOVEDIR) < 0) { + int k = -errno; + + if (flags & BTRFS_SNAPSHOT_READ_ONLY) + (void) btrfs_subvol_set_read_only_fd(subvolume_fd, true); + + return k; + } + + r = subvol_snapshot_children(old_child_fd, new_child_fd, p, sh->objectid, flags & ~BTRFS_SNAPSHOT_FALLBACK_COPY); + + /* Restore the readonly flag */ + if (flags & BTRFS_SNAPSHOT_READ_ONLY) { + int k; + + k = btrfs_subvol_set_read_only_fd(subvolume_fd, true); + if (r >= 0 && k < 0) + return k; + } + + if (r < 0) + return r; + } + + /* Increase search key by one, to read the next item, if we can. */ + if (!btrfs_ioctl_search_args_inc(&args)) + break; + } + + if (flags & BTRFS_SNAPSHOT_QUOTA) + (void) copy_subtree_quota_limits(new_fd, old_subvol_id, new_subvol_id); + + return 0; +} + +int btrfs_subvol_snapshot_fd_full( + int old_fd, + const char *new_path, + BtrfsSnapshotFlags flags, + copy_progress_path_t progress_path, + copy_progress_bytes_t progress_bytes, + void *userdata) { + + _cleanup_close_ int new_fd = -1; + const char *subvolume; + int r; + + assert(old_fd >= 0); + assert(new_path); + + r = btrfs_is_subvol_fd(old_fd); + if (r < 0) + return r; + if (r == 0) { + bool plain_directory = false; + + /* If the source isn't a proper subvolume, fail unless fallback is requested */ + if (!(flags & BTRFS_SNAPSHOT_FALLBACK_COPY)) + return -EISDIR; + + r = btrfs_subvol_make(new_path); + if (r == -ENOTTY && (flags & BTRFS_SNAPSHOT_FALLBACK_DIRECTORY)) { + /* If the destination doesn't support subvolumes, then use a plain directory, if that's requested. */ + if (mkdir(new_path, 0755) < 0) + return -errno; + + plain_directory = true; + } else if (r < 0) + return r; + + r = copy_directory_fd_full(old_fd, new_path, COPY_MERGE|COPY_REFLINK|COPY_SAME_MOUNT|(FLAGS_SET(flags, BTRFS_SNAPSHOT_SIGINT) ? COPY_SIGINT : 0), progress_path, progress_bytes, userdata); + if (r < 0) + goto fallback_fail; + + if (flags & BTRFS_SNAPSHOT_READ_ONLY) { + + if (plain_directory) { + /* Plain directories have no recursive read-only flag, but something pretty close to + * it: the IMMUTABLE bit. Let's use this here, if this is requested. */ + + if (flags & BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE) + (void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL, NULL); + } else { + r = btrfs_subvol_set_read_only(new_path, true); + if (r < 0) + goto fallback_fail; + } + } + + return 0; + + fallback_fail: + (void) rm_rf(new_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + return r; + } + + r = extract_subvolume_name(new_path, &subvolume); + if (r < 0) + return r; + + new_fd = open_parent(new_path, O_CLOEXEC, 0); + if (new_fd < 0) + return new_fd; + + return subvol_snapshot_children(old_fd, new_fd, subvolume, 0, flags); +} + +int btrfs_subvol_snapshot_full( + const char *old_path, + const char *new_path, + BtrfsSnapshotFlags flags, + copy_progress_path_t progress_path, + copy_progress_bytes_t progress_bytes, + void *userdata) { + + _cleanup_close_ int old_fd = -1; + + assert(old_path); + assert(new_path); + + old_fd = open(old_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (old_fd < 0) + return -errno; + + return btrfs_subvol_snapshot_fd_full(old_fd, new_path, flags, progress_path, progress_bytes, userdata); +} + +int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) { + + struct btrfs_ioctl_search_args args = { + /* Tree of quota items */ + .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID, + + /* Look precisely for the quota relation items */ + .key.min_type = BTRFS_QGROUP_RELATION_KEY, + .key.max_type = BTRFS_QGROUP_RELATION_KEY, + + /* No restrictions on the other components */ + .key.min_offset = 0, + .key.max_offset = (uint64_t) -1, + + .key.min_transid = 0, + .key.max_transid = (uint64_t) -1, + }; + + _cleanup_free_ uint64_t *items = NULL; + size_t n_items = 0, n_allocated = 0; + int r; + + assert(fd >= 0); + assert(ret); + + if (qgroupid == 0) { + r = btrfs_subvol_get_id_fd(fd, &qgroupid); + if (r < 0) + return r; + } else { + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (!r) + return -ENOTTY; + } + + args.key.min_objectid = args.key.max_objectid = qgroupid; + + while (btrfs_ioctl_search_args_compare(&args) <= 0) { + const struct btrfs_ioctl_search_header *sh; + unsigned i; + + args.key.nr_items = 256; + if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) { + if (errno == ENOENT) /* quota tree missing: quota is disabled */ + break; + + return -errno; + } + + if (args.key.nr_items <= 0) + break; + + FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { + + /* Make sure we start the next search at least from this entry */ + btrfs_ioctl_search_args_set(&args, sh); + + if (sh->type != BTRFS_QGROUP_RELATION_KEY) + continue; + if (sh->offset < sh->objectid) + continue; + if (sh->objectid != qgroupid) + continue; + + if (!GREEDY_REALLOC(items, n_allocated, n_items+1)) + return -ENOMEM; + + items[n_items++] = sh->offset; + } + + /* Increase search key by one, to read the next item, if we can. */ + if (!btrfs_ioctl_search_args_inc(&args)) + break; + } + + if (n_items <= 0) { + *ret = NULL; + return 0; + } + + *ret = TAKE_PTR(items); + + return (int) n_items; +} + +int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermediary_qgroup) { + _cleanup_free_ uint64_t *qgroups = NULL; + uint64_t parent_subvol; + bool changed = false; + int n = 0, r; + + assert(fd >= 0); + + /* + * Sets up the specified subvolume's qgroup automatically in + * one of two ways: + * + * If insert_intermediary_qgroup is false, the subvolume's + * leaf qgroup will be assigned to the same parent qgroups as + * the subvolume's parent subvolume. + * + * If insert_intermediary_qgroup is true a new intermediary + * higher-level qgroup is created, with a higher level number, + * but reusing the id of the subvolume. The level number is + * picked as one smaller than the lowest level qgroup the + * parent subvolume is a member of. If the parent subvolume's + * leaf qgroup is assigned to no higher-level qgroup a new + * qgroup of level 255 is created instead. Either way, the new + * qgroup is then assigned to the parent's higher-level + * qgroup, and the subvolume itself is assigned to it. + * + * If the subvolume is already assigned to a higher level + * qgroup, no operation is executed. + * + * Effectively this means: regardless if + * insert_intermediary_qgroup is true or not, after this + * function is invoked the subvolume will be accounted within + * the same qgroups as the parent. However, if it is true, it + * will also get its own higher-level qgroup, which may in + * turn be used by subvolumes created beneath this subvolume + * later on. + * + * This hence defines a simple default qgroup setup for + * subvolumes, as long as this function is invoked on each + * created subvolume: each subvolume is always accounting + * together with its immediate parents. Optionally, if + * insert_intermediary_qgroup is true, it will also get a + * qgroup that then includes all its own child subvolumes. + */ + + if (subvol_id == 0) { + r = btrfs_is_subvol_fd(fd); + if (r < 0) + return r; + if (!r) + return -ENOTTY; + + r = btrfs_subvol_get_id_fd(fd, &subvol_id); + if (r < 0) + return r; + } + + n = btrfs_qgroup_find_parents(fd, subvol_id, &qgroups); + if (n < 0) + return n; + if (n > 0) /* already parent qgroups set up, let's bail */ + return 0; + + qgroups = mfree(qgroups); + + r = btrfs_subvol_get_parent(fd, subvol_id, &parent_subvol); + if (r == -ENXIO) + /* No parent, hence no qgroup memberships */ + n = 0; + else if (r < 0) + return r; + else { + n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups); + if (n < 0) + return n; + } + + if (insert_intermediary_qgroup) { + uint64_t lowest = 256, new_qgroupid; + bool created = false; + int i; + + /* Determine the lowest qgroup that the parent + * subvolume is assigned to. */ + + for (i = 0; i < n; i++) { + uint64_t level; + + r = btrfs_qgroupid_split(qgroups[i], &level, NULL); + if (r < 0) + return r; + + if (level < lowest) + lowest = level; + } + + if (lowest <= 1) /* There are no levels left we could use insert an intermediary qgroup at */ + return -EBUSY; + + r = btrfs_qgroupid_make(lowest - 1, subvol_id, &new_qgroupid); + if (r < 0) + return r; + + /* Create the new intermediary group, unless it already exists */ + r = btrfs_qgroup_create(fd, new_qgroupid); + if (r < 0 && r != -EEXIST) + return r; + if (r >= 0) + changed = created = true; + + for (i = 0; i < n; i++) { + r = btrfs_qgroup_assign(fd, new_qgroupid, qgroups[i]); + if (r < 0 && r != -EEXIST) { + if (created) + (void) btrfs_qgroup_destroy_recursive(fd, new_qgroupid); + + return r; + } + if (r >= 0) + changed = true; + } + + r = btrfs_qgroup_assign(fd, subvol_id, new_qgroupid); + if (r < 0 && r != -EEXIST) { + if (created) + (void) btrfs_qgroup_destroy_recursive(fd, new_qgroupid); + return r; + } + if (r >= 0) + changed = true; + + } else { + int i; + + /* Assign our subvolume to all the same qgroups as the parent */ + + for (i = 0; i < n; i++) { + r = btrfs_qgroup_assign(fd, subvol_id, qgroups[i]); + if (r < 0 && r != -EEXIST) + return r; + if (r >= 0) + changed = true; + } + } + + return changed; +} + +int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_intermediary_qgroup) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (fd < 0) + return -errno; + + return btrfs_subvol_auto_qgroup_fd(fd, subvol_id, create_intermediary_qgroup); +} + +int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) { + + struct btrfs_ioctl_search_args args = { + /* Tree of tree roots */ + .key.tree_id = BTRFS_ROOT_TREE_OBJECTID, + + /* Look precisely for the subvolume items */ + .key.min_type = BTRFS_ROOT_BACKREF_KEY, + .key.max_type = BTRFS_ROOT_BACKREF_KEY, + + /* No restrictions on the other components */ + .key.min_offset = 0, + .key.max_offset = (uint64_t) -1, + + .key.min_transid = 0, + .key.max_transid = (uint64_t) -1, + }; + int r; + + assert(fd >= 0); + assert(ret); + + if (subvol_id == 0) { + r = btrfs_subvol_get_id_fd(fd, &subvol_id); + if (r < 0) + return r; + } else { + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (!r) + return -ENOTTY; + } + + args.key.min_objectid = args.key.max_objectid = subvol_id; + + while (btrfs_ioctl_search_args_compare(&args) <= 0) { + const struct btrfs_ioctl_search_header *sh; + unsigned i; + + args.key.nr_items = 256; + if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) + return negative_errno(); + + if (args.key.nr_items <= 0) + break; + + FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) { + + if (sh->type != BTRFS_ROOT_BACKREF_KEY) + continue; + if (sh->objectid != subvol_id) + continue; + + *ret = sh->offset; + return 0; + } + } + + return -ENXIO; +} diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h new file mode 100644 index 00000000..b15667bf --- /dev/null +++ b/src/basic/btrfs-util.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "sd-id128.h" + +#include "copy.h" +#include "time-util.h" + +typedef struct BtrfsSubvolInfo { + uint64_t subvol_id; + usec_t otime; + + sd_id128_t uuid; + sd_id128_t parent_uuid; + + bool read_only; +} BtrfsSubvolInfo; + +typedef struct BtrfsQuotaInfo { + uint64_t referenced; + uint64_t exclusive; + uint64_t referenced_max; + uint64_t exclusive_max; +} BtrfsQuotaInfo; + +typedef enum BtrfsSnapshotFlags { + BTRFS_SNAPSHOT_FALLBACK_COPY = 1 << 0, /* If the source isn't a subvolume, reflink everything */ + BTRFS_SNAPSHOT_READ_ONLY = 1 << 1, + BTRFS_SNAPSHOT_RECURSIVE = 1 << 2, + BTRFS_SNAPSHOT_QUOTA = 1 << 3, + BTRFS_SNAPSHOT_FALLBACK_DIRECTORY = 1 << 4, /* If the destination doesn't support subvolumes, reflink/copy instead */ + BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE = 1 << 5, /* When we can't create a subvolume, use the FS_IMMUTABLE attribute for indicating read-only */ + BTRFS_SNAPSHOT_SIGINT = 1 << 6, /* Check for SIGINT regularly, and return EINTR if seen */ +} BtrfsSnapshotFlags; + +typedef enum BtrfsRemoveFlags { + BTRFS_REMOVE_RECURSIVE = 1 << 0, + BTRFS_REMOVE_QUOTA = 1 << 1, +} BtrfsRemoveFlags; + +int btrfs_is_filesystem(int fd); + +int btrfs_is_subvol_fd(int fd); +int btrfs_is_subvol(const char *path); + +int btrfs_reflink(int infd, int outfd); +int btrfs_clone_range(int infd, uint64_t in_offset, int ofd, uint64_t out_offset, uint64_t sz); + +int btrfs_get_block_device_fd(int fd, dev_t *dev); +int btrfs_get_block_device(const char *path, dev_t *dev); + +int btrfs_defrag_fd(int fd); +int btrfs_defrag(const char *p); + +int btrfs_quota_enable_fd(int fd, bool b); +int btrfs_quota_enable(const char *path, bool b); + +int btrfs_quota_scan_start(int fd); +int btrfs_quota_scan_wait(int fd); +int btrfs_quota_scan_ongoing(int fd); + +int btrfs_subvol_make(const char *path); +int btrfs_subvol_make_fd(int fd, const char *subvolume); + +int btrfs_subvol_snapshot_fd_full(int old_fd, const char *new_path, BtrfsSnapshotFlags flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata); +static inline int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags) { + return btrfs_subvol_snapshot_fd_full(old_fd, new_path, flags, NULL, NULL, NULL); +} + +int btrfs_subvol_snapshot_full(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata); +static inline int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags) { + return btrfs_subvol_snapshot_full(old_path, new_path, flags, NULL, NULL, NULL); +} + +int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags); +int btrfs_subvol_remove_fd(int fd, const char *subvolume, BtrfsRemoveFlags flags); + +int btrfs_subvol_set_read_only_fd(int fd, bool b); +int btrfs_subvol_set_read_only(const char *path, bool b); +int btrfs_subvol_get_read_only_fd(int fd); + +int btrfs_subvol_get_id(int fd, const char *subvolume, uint64_t *ret); +int btrfs_subvol_get_id_fd(int fd, uint64_t *ret); +int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret); + +int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *info); + +int btrfs_subvol_find_subtree_qgroup(int fd, uint64_t subvol_id, uint64_t *ret); + +int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQuotaInfo *quota); +int btrfs_subvol_get_subtree_quota_fd(int fd, uint64_t subvol_id, BtrfsQuotaInfo *quota); + +int btrfs_subvol_set_subtree_quota_limit(const char *path, uint64_t subvol_id, uint64_t referenced_max); +int btrfs_subvol_set_subtree_quota_limit_fd(int fd, uint64_t subvol_id, uint64_t referenced_max); + +int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool new_qgroup); +int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_intermediary_qgroup); + +int btrfs_qgroupid_make(uint64_t level, uint64_t id, uint64_t *ret); +int btrfs_qgroupid_split(uint64_t qgroupid, uint64_t *level, uint64_t *id); + +int btrfs_qgroup_create(int fd, uint64_t qgroupid); +int btrfs_qgroup_destroy(int fd, uint64_t qgroupid); +int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid); + +int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max); +int btrfs_qgroup_set_limit(const char *path, uint64_t qgroupid, uint64_t referenced_max); + +int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupid); + +int btrfs_qgroup_assign(int fd, uint64_t child, uint64_t parent); +int btrfs_qgroup_unassign(int fd, uint64_t child, uint64_t parent); + +int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret); + +int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *quota); +int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *quota); diff --git a/src/basic/build.h b/src/basic/build.h new file mode 100644 index 00000000..c47e912e --- /dev/null +++ b/src/basic/build.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "version.h" + +#if HAVE_PAM +#define _PAM_FEATURE_ "+PAM" +#else +#define _PAM_FEATURE_ "-PAM" +#endif + +#if HAVE_AUDIT +#define _AUDIT_FEATURE_ "+AUDIT" +#else +#define _AUDIT_FEATURE_ "-AUDIT" +#endif + +#if HAVE_SELINUX +#define _SELINUX_FEATURE_ "+SELINUX" +#else +#define _SELINUX_FEATURE_ "-SELINUX" +#endif + +#if HAVE_APPARMOR +#define _APPARMOR_FEATURE_ "+APPARMOR" +#else +#define _APPARMOR_FEATURE_ "-APPARMOR" +#endif + +#if ENABLE_IMA +#define _IMA_FEATURE_ "+IMA" +#else +#define _IMA_FEATURE_ "-IMA" +#endif + +#if ENABLE_SMACK +#define _SMACK_FEATURE_ "+SMACK" +#else +#define _SMACK_FEATURE_ "-SMACK" +#endif + +#if HAVE_SYSV_COMPAT +#define _SYSVINIT_FEATURE_ "+SYSVINIT" +#else +#define _SYSVINIT_FEATURE_ "-SYSVINIT" +#endif + +#if ENABLE_UTMP +#define _UTMP_FEATURE_ "+UTMP" +#else +#define _UTMP_FEATURE_ "-UTMP" +#endif + +#if HAVE_LIBCRYPTSETUP +#define _LIBCRYPTSETUP_FEATURE_ "+LIBCRYPTSETUP" +#else +#define _LIBCRYPTSETUP_FEATURE_ "-LIBCRYPTSETUP" +#endif + +#if HAVE_GCRYPT +#define _GCRYPT_FEATURE_ "+GCRYPT" +#else +#define _GCRYPT_FEATURE_ "-GCRYPT" +#endif + +#if HAVE_GNUTLS +#define _GNUTLS_FEATURE_ "+GNUTLS" +#else +#define _GNUTLS_FEATURE_ "-GNUTLS" +#endif + +#if HAVE_ACL +#define _ACL_FEATURE_ "+ACL" +#else +#define _ACL_FEATURE_ "-ACL" +#endif + +#if HAVE_XZ +#define _XZ_FEATURE_ "+XZ" +#else +#define _XZ_FEATURE_ "-XZ" +#endif + +#if HAVE_LZ4 +#define _LZ4_FEATURE_ "+LZ4" +#else +#define _LZ4_FEATURE_ "-LZ4" +#endif + +#if HAVE_SECCOMP +#define _SECCOMP_FEATURE_ "+SECCOMP" +#else +#define _SECCOMP_FEATURE_ "-SECCOMP" +#endif + +#if HAVE_BLKID +#define _BLKID_FEATURE_ "+BLKID" +#else +#define _BLKID_FEATURE_ "-BLKID" +#endif + +#if HAVE_ELFUTILS +#define _ELFUTILS_FEATURE_ "+ELFUTILS" +#else +#define _ELFUTILS_FEATURE_ "-ELFUTILS" +#endif + +#if HAVE_KMOD +#define _KMOD_FEATURE_ "+KMOD" +#else +#define _KMOD_FEATURE_ "-KMOD" +#endif + +#if HAVE_LIBIDN2 +#define _IDN2_FEATURE_ "+IDN2" +#else +#define _IDN2_FEATURE_ "-IDN2" +#endif + +#if HAVE_LIBIDN +#define _IDN_FEATURE_ "+IDN" +#else +#define _IDN_FEATURE_ "-IDN" +#endif + +#if HAVE_PCRE2 +#define _PCRE2_FEATURE_ "+PCRE2" +#else +#define _PCRE2_FEATURE_ "-PCRE2" +#endif + +#define _CGROUP_HIERARCHY_ "default-hierarchy=" DEFAULT_HIERARCHY_NAME + +#define SYSTEMD_FEATURES \ + _PAM_FEATURE_ " " \ + _AUDIT_FEATURE_ " " \ + _SELINUX_FEATURE_ " " \ + _IMA_FEATURE_ " " \ + _APPARMOR_FEATURE_ " " \ + _SMACK_FEATURE_ " " \ + _SYSVINIT_FEATURE_ " " \ + _UTMP_FEATURE_ " " \ + _LIBCRYPTSETUP_FEATURE_ " " \ + _GCRYPT_FEATURE_ " " \ + _GNUTLS_FEATURE_ " " \ + _ACL_FEATURE_ " " \ + _XZ_FEATURE_ " " \ + _LZ4_FEATURE_ " " \ + _SECCOMP_FEATURE_ " " \ + _BLKID_FEATURE_ " " \ + _ELFUTILS_FEATURE_ " " \ + _KMOD_FEATURE_ " " \ + _IDN2_FEATURE_ " " \ + _IDN_FEATURE_ " " \ + _PCRE2_FEATURE_ " " \ + _CGROUP_HIERARCHY_ diff --git a/src/basic/bus-label.c b/src/basic/bus-label.c new file mode 100644 index 00000000..1613cf7f --- /dev/null +++ b/src/basic/bus-label.c @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "bus-label.h" +#include "hexdecoct.h" +#include "macro.h" + +char *bus_label_escape(const char *s) { + char *r, *t; + const char *f; + + assert_return(s, NULL); + + /* Escapes all chars that D-Bus' object path cannot deal + * with. Can be reversed with bus_path_unescape(). We special + * case the empty string. */ + + if (*s == 0) + return strdup("_"); + + r = new(char, strlen(s)*3 + 1); + if (!r) + return NULL; + + for (f = s, t = r; *f; f++) { + + /* Escape everything that is not a-zA-Z0-9. We also + * escape 0-9 if it's the first character */ + + if (!(*f >= 'A' && *f <= 'Z') && + !(*f >= 'a' && *f <= 'z') && + !(f > s && *f >= '0' && *f <= '9')) { + *(t++) = '_'; + *(t++) = hexchar(*f >> 4); + *(t++) = hexchar(*f); + } else + *(t++) = *f; + } + + *t = 0; + + return r; +} + +char *bus_label_unescape_n(const char *f, size_t l) { + char *r, *t; + size_t i; + + assert_return(f, NULL); + + /* Special case for the empty string */ + if (l == 1 && *f == '_') + return strdup(""); + + r = new(char, l + 1); + if (!r) + return NULL; + + for (i = 0, t = r; i < l; ++i) { + if (f[i] == '_') { + int a, b; + + if (l - i < 3 || + (a = unhexchar(f[i + 1])) < 0 || + (b = unhexchar(f[i + 2])) < 0) { + /* Invalid escape code, let's take it literal then */ + *(t++) = '_'; + } else { + *(t++) = (char) ((a << 4) | b); + i += 2; + } + } else + *(t++) = f[i]; + } + + *t = 0; + + return r; +} diff --git a/src/basic/bus-label.h b/src/basic/bus-label.h new file mode 100644 index 00000000..4a1b097a --- /dev/null +++ b/src/basic/bus-label.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "string-util.h" + +char *bus_label_escape(const char *s); +char *bus_label_unescape_n(const char *f, size_t l); + +static inline char *bus_label_unescape(const char *f) { + return bus_label_unescape_n(f, strlen_ptr(f)); +} diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c new file mode 100644 index 00000000..84083b45 --- /dev/null +++ b/src/basic/cap-list.c @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "capability-util.h" +#include "cap-list.h" +#include "extract-word.h" +#include "macro.h" +#include "parse-util.h" +#include "util.h" + +static const struct capability_name* lookup_capability(register const char *str, register GPERF_LEN_TYPE len); + +#include "cap-from-name.h" +#include "cap-to-name.h" + +const char *capability_to_name(int id) { + + if (id < 0) + return NULL; + + if ((size_t) id >= ELEMENTSOF(capability_names)) + return NULL; + + return capability_names[id]; +} + +int capability_from_name(const char *name) { + const struct capability_name *sc; + int r, i; + + assert(name); + + /* Try to parse numeric capability */ + r = safe_atoi(name, &i); + if (r >= 0) { + if (i >= 0 && (size_t) i < ELEMENTSOF(capability_names)) + return i; + else + return -EINVAL; + } + + /* Try to parse string capability */ + sc = lookup_capability(name, strlen(name)); + if (!sc) + return -EINVAL; + + return sc->id; +} + +int capability_list_length(void) { + return (int) ELEMENTSOF(capability_names); +} + +int capability_set_to_string_alloc(uint64_t set, char **s) { + _cleanup_free_ char *str = NULL; + unsigned long i; + size_t allocated = 0, n = 0; + + assert(s); + + for (i = 0; i <= cap_last_cap(); i++) + if (set & (UINT64_C(1) << i)) { + const char *p; + size_t add; + + p = capability_to_name(i); + if (!p) + return -EINVAL; + + add = strlen(p); + + if (!GREEDY_REALLOC(str, allocated, n + add + 2)) + return -ENOMEM; + + strcpy(mempcpy(str + n, p, add), " "); + n += add + 1; + } + + if (!GREEDY_REALLOC(str, allocated, n + 1)) + return -ENOMEM; + + str[n > 0 ? n - 1 : 0] = '\0'; /* truncate the last space, if it's there */ + + *s = TAKE_PTR(str); + + return 0; +} + +int capability_set_from_string(const char *s, uint64_t *set) { + uint64_t val = 0; + const char *p; + + assert(set); + + for (p = s;;) { + _cleanup_free_ char *word = NULL; + int r; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return r; + if (r <= 0) + break; + + r = capability_from_name(word); + if (r < 0) + continue; + + val |= ((uint64_t) UINT64_C(1)) << (uint64_t) r; + } + + *set = val; + + return 0; +} diff --git a/src/basic/cap-list.h b/src/basic/cap-list.h new file mode 100644 index 00000000..ab41924d --- /dev/null +++ b/src/basic/cap-list.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +const char *capability_to_name(int id); +int capability_from_name(const char *name); +int capability_list_length(void); + +int capability_set_to_string_alloc(uint64_t set, char **s); +int capability_set_from_string(const char *s, uint64_t *set); diff --git a/src/basic/cap-to-name.awk b/src/basic/cap-to-name.awk new file mode 100644 index 00000000..402a7820 --- /dev/null +++ b/src/basic/cap-to-name.awk @@ -0,0 +1,9 @@ +BEGIN{ + print "static const char* const capability_names[] = { " +} +{ + printf " [%s] = \"%s\",\n", $1, tolower($1) +} +END{ + print "};" +} diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c new file mode 100644 index 00000000..d084ad5c --- /dev/null +++ b/src/basic/capability-util.c @@ -0,0 +1,574 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "capability-util.h" +#include "cap-list.h" +#include "fileio.h" +#include "log.h" +#include "macro.h" +#include "missing_prctl.h" +#include "parse-util.h" +#include "user-util.h" +#include "util.h" + +int have_effective_cap(int value) { + _cleanup_cap_free_ cap_t cap; + cap_flag_value_t fv; + + cap = cap_get_proc(); + if (!cap) + return -errno; + + if (cap_get_flag(cap, value, CAP_EFFECTIVE, &fv) < 0) + return -errno; + + return fv == CAP_SET; +} + +unsigned long cap_last_cap(void) { + static thread_local unsigned long saved; + static thread_local bool valid = false; + _cleanup_free_ char *content = NULL; + unsigned long p = 0; + int r; + + if (valid) + return saved; + + /* available since linux-3.2 */ + r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content); + if (r >= 0) { + r = safe_atolu(content, &p); + if (r >= 0) { + + if (p > 63) /* Safety for the future: if one day the kernel learns more than 64 caps, + * then we are in trouble (since we, as much userspace and kernel space + * store capability masks in uint64_t types). Let's hence protect + * ourselves against that and always cap at 63 for now. */ + p = 63; + + saved = p; + valid = true; + return p; + } + } + + /* fall back to syscall-probing for pre linux-3.2 */ + p = MIN((unsigned long) CAP_LAST_CAP, 63U); + + if (prctl(PR_CAPBSET_READ, p) < 0) { + + /* Hmm, look downwards, until we find one that works */ + for (p--; p > 0; p --) + if (prctl(PR_CAPBSET_READ, p) >= 0) + break; + + } else { + + /* Hmm, look upwards, until we find one that doesn't work */ + for (; p < 63; p++) + if (prctl(PR_CAPBSET_READ, p+1) < 0) + break; + } + + saved = p; + valid = true; + + return p; +} + +int capability_update_inherited_set(cap_t caps, uint64_t set) { + unsigned long i; + + /* Add capabilities in the set to the inherited caps. Do not apply + * them yet. */ + + for (i = 0; i <= cap_last_cap(); i++) { + + if (set & (UINT64_C(1) << i)) { + cap_value_t v; + + v = (cap_value_t) i; + + /* Make the capability inheritable. */ + if (cap_set_flag(caps, CAP_INHERITABLE, 1, &v, CAP_SET) < 0) + return -errno; + } + } + + return 0; +} + +int capability_ambient_set_apply(uint64_t set, bool also_inherit) { + _cleanup_cap_free_ cap_t caps = NULL; + unsigned long i; + int r; + + /* Add the capabilities to the ambient set. */ + + if (also_inherit) { + caps = cap_get_proc(); + if (!caps) + return -errno; + + r = capability_update_inherited_set(caps, set); + if (r < 0) + return -errno; + + if (cap_set_proc(caps) < 0) + return -errno; + } + + for (i = 0; i <= cap_last_cap(); i++) { + + if (set & (UINT64_C(1) << i)) { + + /* Add the capability to the ambient set. */ + if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0) < 0) + return -errno; + } + } + + return 0; +} + +int capability_bounding_set_drop(uint64_t keep, bool right_now) { + _cleanup_cap_free_ cap_t before_cap = NULL, after_cap = NULL; + cap_flag_value_t fv; + unsigned long i; + int r; + + /* If we are run as PID 1 we will lack CAP_SETPCAP by default + * in the effective set (yes, the kernel drops that when + * executing init!), so get it back temporarily so that we can + * call PR_CAPBSET_DROP. */ + + before_cap = cap_get_proc(); + if (!before_cap) + return -errno; + + if (cap_get_flag(before_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) + return -errno; + + if (fv != CAP_SET) { + _cleanup_cap_free_ cap_t temp_cap = NULL; + static const cap_value_t v = CAP_SETPCAP; + + temp_cap = cap_dup(before_cap); + if (!temp_cap) + return -errno; + + if (cap_set_flag(temp_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0) + return -errno; + + if (cap_set_proc(temp_cap) < 0) + log_debug_errno(errno, "Can't acquire effective CAP_SETPCAP bit, ignoring: %m"); + + /* If we didn't manage to acquire the CAP_SETPCAP bit, we continue anyway, after all this just means + * we'll fail later, when we actually intend to drop some capabilities. */ + } + + after_cap = cap_dup(before_cap); + if (!after_cap) + return -errno; + + for (i = 0; i <= cap_last_cap(); i++) { + cap_value_t v; + + if ((keep & (UINT64_C(1) << i))) + continue; + + /* Drop it from the bounding set */ + if (prctl(PR_CAPBSET_DROP, i) < 0) { + r = -errno; + + /* If dropping the capability failed, let's see if we didn't have it in the first place. If so, + * continue anyway, as dropping a capability we didn't have in the first place doesn't really + * matter anyway. */ + if (prctl(PR_CAPBSET_READ, i) != 0) + goto finish; + } + v = (cap_value_t) i; + + /* Also drop it from the inheritable set, so + * that anything we exec() loses the + * capability for good. */ + if (cap_set_flag(after_cap, CAP_INHERITABLE, 1, &v, CAP_CLEAR) < 0) { + r = -errno; + goto finish; + } + + /* If we shall apply this right now drop it + * also from our own capability sets. */ + if (right_now) { + if (cap_set_flag(after_cap, CAP_PERMITTED, 1, &v, CAP_CLEAR) < 0 || + cap_set_flag(after_cap, CAP_EFFECTIVE, 1, &v, CAP_CLEAR) < 0) { + r = -errno; + goto finish; + } + } + } + + r = 0; + +finish: + if (cap_set_proc(after_cap) < 0) { + /* If there are no actual changes anyway then let's ignore this error. */ + if (cap_compare(before_cap, after_cap) != 0) + r = -errno; + } + + return r; +} + +static int drop_from_file(const char *fn, uint64_t keep) { + _cleanup_free_ char *p = NULL; + uint64_t current, after; + uint32_t hi, lo; + int r, k; + + r = read_one_line_file(fn, &p); + if (r < 0) + return r; + + k = sscanf(p, "%" PRIu32 " %" PRIu32, &lo, &hi); + if (k != 2) + return -EIO; + + current = (uint64_t) lo | ((uint64_t) hi << 32); + after = current & keep; + + if (current == after) + return 0; + + lo = after & UINT32_C(0xFFFFFFFF); + hi = (after >> 32) & UINT32_C(0xFFFFFFFF); + + return write_string_filef(fn, 0, "%" PRIu32 " %" PRIu32, lo, hi); +} + +int capability_bounding_set_drop_usermode(uint64_t keep) { + int r; + + r = drop_from_file("/proc/sys/kernel/usermodehelper/inheritable", keep); + if (r < 0) + return r; + + r = drop_from_file("/proc/sys/kernel/usermodehelper/bset", keep); + if (r < 0) + return r; + + return r; +} + +int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) { + int r; + + /* Unfortunately we cannot leave privilege dropping to PID 1 here, since we want to run as user but + * want to keep some capabilities. Since file capabilities have been introduced this cannot be done + * across exec() anymore, unless our binary has the capability configured in the file system, which + * we want to avoid. */ + + if (setresgid(gid, gid, gid) < 0) + return log_error_errno(errno, "Failed to change group ID: %m"); + + r = maybe_setgroups(0, NULL); + if (r < 0) + return log_error_errno(r, "Failed to drop auxiliary groups list: %m"); + + /* Ensure we keep the permitted caps across the setresuid(). Note that we do this even if we actually + * don't want to keep any capabilities, since we want to be able to drop them from the bounding set + * too, and we can only do that if we have capabilities. */ + if (prctl(PR_SET_KEEPCAPS, 1) < 0) + return log_error_errno(errno, "Failed to enable keep capabilities flag: %m"); + + if (setresuid(uid, uid, uid) < 0) + return log_error_errno(errno, "Failed to change user ID: %m"); + + if (prctl(PR_SET_KEEPCAPS, 0) < 0) + return log_error_errno(errno, "Failed to disable keep capabilities flag: %m"); + + /* Drop all caps from the bounding set (as well as the inheritable/permitted/effective sets), except + * the ones we want to keep */ + r = capability_bounding_set_drop(keep_capabilities, true); + if (r < 0) + return log_error_errno(r, "Failed to drop capabilities: %m"); + + /* Now upgrade the permitted caps we still kept to effective caps */ + if (keep_capabilities != 0) { + cap_value_t bits[u64log2(keep_capabilities) + 1]; + _cleanup_cap_free_ cap_t d = NULL; + unsigned i, j = 0; + + d = cap_init(); + if (!d) + return log_oom(); + + for (i = 0; i < ELEMENTSOF(bits); i++) + if (keep_capabilities & (1ULL << i)) + bits[j++] = i; + + /* use enough bits */ + assert(i == 64 || (keep_capabilities >> i) == 0); + /* don't use too many bits */ + assert(keep_capabilities & (UINT64_C(1) << (i - 1))); + + if (cap_set_flag(d, CAP_EFFECTIVE, j, bits, CAP_SET) < 0 || + cap_set_flag(d, CAP_PERMITTED, j, bits, CAP_SET) < 0) + return log_error_errno(errno, "Failed to enable capabilities bits: %m"); + + if (cap_set_proc(d) < 0) + return log_error_errno(errno, "Failed to increase capabilities: %m"); + } + + return 0; +} + +int drop_capability(cap_value_t cv) { + _cleanup_cap_free_ cap_t tmp_cap = NULL; + + tmp_cap = cap_get_proc(); + if (!tmp_cap) + return -errno; + + if ((cap_set_flag(tmp_cap, CAP_INHERITABLE, 1, &cv, CAP_CLEAR) < 0) || + (cap_set_flag(tmp_cap, CAP_PERMITTED, 1, &cv, CAP_CLEAR) < 0) || + (cap_set_flag(tmp_cap, CAP_EFFECTIVE, 1, &cv, CAP_CLEAR) < 0)) + return -errno; + + if (cap_set_proc(tmp_cap) < 0) + return -errno; + + return 0; +} + +bool ambient_capabilities_supported(void) { + static int cache = -1; + + if (cache >= 0) + return cache; + + /* If PR_CAP_AMBIENT returns something valid, or an unexpected error code we assume that ambient caps are + * available. */ + + cache = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_KILL, 0, 0) >= 0 || + !IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS); + + return cache; +} + +bool capability_quintet_mangle(CapabilityQuintet *q) { + unsigned long i; + uint64_t combined, drop = 0; + bool ambient_supported; + + assert(q); + + combined = q->effective | q->bounding | q->inheritable | q->permitted; + + ambient_supported = q->ambient != (uint64_t) -1; + if (ambient_supported) + combined |= q->ambient; + + for (i = 0; i <= cap_last_cap(); i++) { + unsigned long bit = UINT64_C(1) << i; + if (!FLAGS_SET(combined, bit)) + continue; + + if (prctl(PR_CAPBSET_READ, i) > 0) + continue; + + drop |= bit; + + log_debug("Not in the current bounding set: %s", capability_to_name(i)); + } + + q->effective &= ~drop; + q->bounding &= ~drop; + q->inheritable &= ~drop; + q->permitted &= ~drop; + + if (ambient_supported) + q->ambient &= ~drop; + + return drop != 0; /* Let the caller know we changed something */ +} + +int capability_quintet_enforce(const CapabilityQuintet *q) { + _cleanup_cap_free_ cap_t c = NULL, modified = NULL; + int r; + + if (q->ambient != (uint64_t) -1) { + unsigned long i; + bool changed = false; + + c = cap_get_proc(); + if (!c) + return -errno; + + /* In order to raise the ambient caps set we first need to raise the matching inheritable + permitted + * cap */ + for (i = 0; i <= cap_last_cap(); i++) { + uint64_t m = UINT64_C(1) << i; + cap_value_t cv = (cap_value_t) i; + cap_flag_value_t old_value_inheritable, old_value_permitted; + + if ((q->ambient & m) == 0) + continue; + + if (cap_get_flag(c, cv, CAP_INHERITABLE, &old_value_inheritable) < 0) + return -errno; + if (cap_get_flag(c, cv, CAP_PERMITTED, &old_value_permitted) < 0) + return -errno; + + if (old_value_inheritable == CAP_SET && old_value_permitted == CAP_SET) + continue; + + if (cap_set_flag(c, CAP_INHERITABLE, 1, &cv, CAP_SET) < 0) + return -errno; + if (cap_set_flag(c, CAP_PERMITTED, 1, &cv, CAP_SET) < 0) + return -errno; + + changed = true; + } + + if (changed) + if (cap_set_proc(c) < 0) + return -errno; + + r = capability_ambient_set_apply(q->ambient, false); + if (r < 0) + return r; + } + + if (q->inheritable != (uint64_t) -1 || q->permitted != (uint64_t) -1 || q->effective != (uint64_t) -1) { + bool changed = false; + unsigned long i; + + if (!c) { + c = cap_get_proc(); + if (!c) + return -errno; + } + + for (i = 0; i <= cap_last_cap(); i++) { + uint64_t m = UINT64_C(1) << i; + cap_value_t cv = (cap_value_t) i; + + if (q->inheritable != (uint64_t) -1) { + cap_flag_value_t old_value, new_value; + + if (cap_get_flag(c, cv, CAP_INHERITABLE, &old_value) < 0) { + if (errno == EINVAL) /* If the kernel knows more caps than this + * version of libcap, then this will return + * EINVAL. In that case, simply ignore it, + * pretend it doesn't exist. */ + continue; + + return -errno; + } + + new_value = (q->inheritable & m) ? CAP_SET : CAP_CLEAR; + + if (old_value != new_value) { + changed = true; + + if (cap_set_flag(c, CAP_INHERITABLE, 1, &cv, new_value) < 0) + return -errno; + } + } + + if (q->permitted != (uint64_t) -1) { + cap_flag_value_t old_value, new_value; + + if (cap_get_flag(c, cv, CAP_PERMITTED, &old_value) < 0) { + if (errno == EINVAL) + continue; + + return -errno; + } + + new_value = (q->permitted & m) ? CAP_SET : CAP_CLEAR; + + if (old_value != new_value) { + changed = true; + + if (cap_set_flag(c, CAP_PERMITTED, 1, &cv, new_value) < 0) + return -errno; + } + } + + if (q->effective != (uint64_t) -1) { + cap_flag_value_t old_value, new_value; + + if (cap_get_flag(c, cv, CAP_EFFECTIVE, &old_value) < 0) { + if (errno == EINVAL) + continue; + + return -errno; + } + + new_value = (q->effective & m) ? CAP_SET : CAP_CLEAR; + + if (old_value != new_value) { + changed = true; + + if (cap_set_flag(c, CAP_EFFECTIVE, 1, &cv, new_value) < 0) + return -errno; + } + } + } + + if (changed) { + /* In order to change the bounding caps, we need to keep CAP_SETPCAP for a bit + * longer. Let's add it to our list hence for now. */ + if (q->bounding != (uint64_t) -1) { + cap_value_t cv = CAP_SETPCAP; + + modified = cap_dup(c); + if (!modified) + return -ENOMEM; + + if (cap_set_flag(modified, CAP_PERMITTED, 1, &cv, CAP_SET) < 0) + return -errno; + if (cap_set_flag(modified, CAP_EFFECTIVE, 1, &cv, CAP_SET) < 0) + return -errno; + + if (cap_compare(modified, c) == 0) { + /* No change? then drop this nonsense again */ + cap_free(modified); + modified = NULL; + } + } + + /* Now, let's enforce the caps for the first time. Note that this is where we acquire + * caps in any of the sets we currently don't have. We have to do this before + * dropping the bounding caps below, since at that point we can never acquire new + * caps in inherited/permitted/effective anymore, but only lose them. */ + if (cap_set_proc(modified ?: c) < 0) + return -errno; + } + } + + if (q->bounding != (uint64_t) -1) { + r = capability_bounding_set_drop(q->bounding, false); + if (r < 0) + return r; + } + + /* If needed, let's now set the caps again, this time in the final version, which differs from what + * we have already set only in the CAP_SETPCAP bit, which we needed for dropping the bounding + * bits. This call only undoes bits and doesn't acquire any which means the bounding caps don't + * matter. */ + if (modified) + if (cap_set_proc(c) < 0) + return -errno; + + return 0; +} diff --git a/src/basic/capability-util.h b/src/basic/capability-util.h new file mode 100644 index 00000000..b5bce29a --- /dev/null +++ b/src/basic/capability-util.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "macro.h" +#include "missing_capability.h" +#include "util.h" + +#define CAP_ALL (uint64_t) -1 + +unsigned long cap_last_cap(void); +int have_effective_cap(int value); +int capability_bounding_set_drop(uint64_t keep, bool right_now); +int capability_bounding_set_drop_usermode(uint64_t keep); + +int capability_ambient_set_apply(uint64_t set, bool also_inherit); +int capability_update_inherited_set(cap_t caps, uint64_t ambient_set); + +int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities); + +int drop_capability(cap_value_t cv); + +DEFINE_TRIVIAL_CLEANUP_FUNC(cap_t, cap_free); +#define _cleanup_cap_free_ _cleanup_(cap_freep) + +static inline void cap_free_charpp(char **p) { + if (*p) + cap_free(*p); +} +#define _cleanup_cap_free_charp_ _cleanup_(cap_free_charpp) + +static inline uint64_t all_capabilities(void) { + return UINT64_MAX >> (63 - cap_last_cap()); +} + +static inline bool cap_test_all(uint64_t caps) { + return FLAGS_SET(caps, all_capabilities()); +} + +bool ambient_capabilities_supported(void); + +/* Identical to linux/capability.h's CAP_TO_MASK(), but uses an unsigned 1U instead of a signed 1 for shifting left, in + * order to avoid complaints about shifting a signed int left by 31 bits, which would make it negative. */ +#define CAP_TO_MASK_CORRECTED(x) (1U << ((x) & 31U)) + +typedef struct CapabilityQuintet { + /* Stores all five types of capabilities in one go. Note that we use (uint64_t) -1 for unset here. This hence + * needs to be updated as soon as Linux learns more than 63 caps. */ + uint64_t effective; + uint64_t bounding; + uint64_t inheritable; + uint64_t permitted; + uint64_t ambient; +} CapabilityQuintet; + +assert_cc(CAP_LAST_CAP < 64); + +#define CAPABILITY_QUINTET_NULL { (uint64_t) -1, (uint64_t) -1, (uint64_t) -1, (uint64_t) -1, (uint64_t) -1 } + +static inline bool capability_quintet_is_set(const CapabilityQuintet *q) { + return q->effective != (uint64_t) -1 || + q->bounding != (uint64_t) -1 || + q->inheritable != (uint64_t) -1 || + q->permitted != (uint64_t) -1 || + q->ambient != (uint64_t) -1; +} + +/* Mangles the specified caps quintet taking the current bounding set into account: + * drops all caps from all five sets if our bounding set doesn't allow them. + * Returns true if the quintet was modified. */ +bool capability_quintet_mangle(CapabilityQuintet *q); + +int capability_quintet_enforce(const CapabilityQuintet *q); diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c new file mode 100644 index 00000000..54fc6ecf --- /dev/null +++ b/src/basic/cgroup-util.c @@ -0,0 +1,2130 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "cgroup-util.h" +#include "def.h" +#include "dirent-util.h" +#include "extract-word.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "log.h" +#include "login-util.h" +#include "macro.h" +#include "missing_magic.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "set.h" +#include "special.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "user-util.h" + +static int cg_enumerate_items(const char *controller, const char *path, FILE **_f, const char *item) { + _cleanup_free_ char *fs = NULL; + FILE *f; + int r; + + assert(_f); + + r = cg_get_path(controller, path, item, &fs); + if (r < 0) + return r; + + f = fopen(fs, "re"); + if (!f) + return -errno; + + *_f = f; + return 0; +} + +int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) { + return cg_enumerate_items(controller, path, _f, "cgroup.procs"); +} + +int cg_read_pid(FILE *f, pid_t *_pid) { + unsigned long ul; + + /* Note that the cgroup.procs might contain duplicates! See + * cgroups.txt for details. */ + + assert(f); + assert(_pid); + + errno = 0; + if (fscanf(f, "%lu", &ul) != 1) { + + if (feof(f)) + return 0; + + return errno_or_else(EIO); + } + + if (ul <= 0) + return -EIO; + + *_pid = (pid_t) ul; + return 1; +} + +int cg_read_event( + const char *controller, + const char *path, + const char *event, + char **ret) { + + _cleanup_free_ char *events = NULL, *content = NULL; + int r; + + r = cg_get_path(controller, path, "cgroup.events", &events); + if (r < 0) + return r; + + r = read_full_file(events, &content, NULL); + if (r < 0) + return r; + + for (const char *p = content;;) { + _cleanup_free_ char *line = NULL, *key = NULL, *val = NULL; + const char *q; + + r = extract_first_word(&p, &line, "\n", 0); + if (r < 0) + return r; + if (r == 0) + return -ENOENT; + + q = line; + r = extract_first_word(&q, &key, " ", 0); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + if (!streq(key, event)) + continue; + + val = strdup(q); + if (!val) + return -ENOMEM; + + *ret = TAKE_PTR(val); + return 0; + } +} + +bool cg_ns_supported(void) { + static thread_local int enabled = -1; + + if (enabled >= 0) + return enabled; + + if (access("/proc/self/ns/cgroup", F_OK) < 0) { + if (errno != ENOENT) + log_debug_errno(errno, "Failed to check whether /proc/self/ns/cgroup is available, assuming not: %m"); + enabled = false; + } else + enabled = true; + + return enabled; +} + +int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) { + _cleanup_free_ char *fs = NULL; + int r; + DIR *d; + + assert(_d); + + /* This is not recursive! */ + + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + d = opendir(fs); + if (!d) + return -errno; + + *_d = d; + return 0; +} + +int cg_read_subgroup(DIR *d, char **fn) { + struct dirent *de; + + assert(d); + assert(fn); + + FOREACH_DIRENT_ALL(de, d, return -errno) { + char *b; + + if (de->d_type != DT_DIR) + continue; + + if (dot_or_dot_dot(de->d_name)) + continue; + + b = strdup(de->d_name); + if (!b) + return -ENOMEM; + + *fn = b; + return 1; + } + + return 0; +} + +int cg_rmdir(const char *controller, const char *path) { + _cleanup_free_ char *p = NULL; + int r; + + r = cg_get_path(controller, path, NULL, &p); + if (r < 0) + return r; + + r = rmdir(p); + if (r < 0 && errno != ENOENT) + return -errno; + + r = cg_hybrid_unified(); + if (r <= 0) + return r; + + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { + r = cg_rmdir(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path); + if (r < 0) + log_warning_errno(r, "Failed to remove compat systemd cgroup %s: %m", path); + } + + return 0; +} + +static int cg_kill_items( + const char *controller, + const char *path, + int sig, + CGroupFlags flags, + Set *s, + cg_kill_log_func_t log_kill, + void *userdata, + const char *item) { + + _cleanup_set_free_ Set *allocated_set = NULL; + bool done = false; + int r, ret = 0, ret_log_kill = 0; + pid_t my_pid; + + assert(sig >= 0); + + /* Don't send SIGCONT twice. Also, SIGKILL always works even when process is suspended, hence don't send + * SIGCONT on SIGKILL. */ + if (IN_SET(sig, SIGCONT, SIGKILL)) + flags &= ~CGROUP_SIGCONT; + + /* This goes through the tasks list and kills them all. This + * is repeated until no further processes are added to the + * tasks list, to properly handle forking processes */ + + if (!s) { + s = allocated_set = set_new(NULL); + if (!s) + return -ENOMEM; + } + + my_pid = getpid_cached(); + + do { + _cleanup_fclose_ FILE *f = NULL; + pid_t pid = 0; + done = true; + + r = cg_enumerate_items(controller, path, &f, item); + if (r < 0) { + if (ret >= 0 && r != -ENOENT) + return r; + + return ret; + } + + while ((r = cg_read_pid(f, &pid)) > 0) { + + if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid) + continue; + + if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid)) + continue; + + if (log_kill) + ret_log_kill = log_kill(pid, sig, userdata); + + /* If we haven't killed this process yet, kill + * it */ + if (kill(pid, sig) < 0) { + if (ret >= 0 && errno != ESRCH) + ret = -errno; + } else { + if (flags & CGROUP_SIGCONT) + (void) kill(pid, SIGCONT); + + if (ret == 0) { + if (log_kill) + ret = ret_log_kill; + else + ret = 1; + } + } + + done = false; + + r = set_put(s, PID_TO_PTR(pid)); + if (r < 0) { + if (ret >= 0) + return r; + + return ret; + } + } + + if (r < 0) { + if (ret >= 0) + return r; + + return ret; + } + + /* To avoid racing against processes which fork + * quicker than we can kill them we repeat this until + * no new pids need to be killed. */ + + } while (!done); + + return ret; +} + +int cg_kill( + const char *controller, + const char *path, + int sig, + CGroupFlags flags, + Set *s, + cg_kill_log_func_t log_kill, + void *userdata) { + int r; + + r = cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.procs"); + if (r < 0 || sig != SIGKILL) + return r; + + /* Only in case of killing with SIGKILL and when using cgroupsv2, kill remaining threads manually as + a workaround for kernel bug. It was fixed in 5.2-rc5 (c03cd7738a83), backported to 4.19.66 + (4340d175b898) and 4.14.138 (feb6b123b7dd). */ + r = cg_unified_controller(controller); + if (r <= 0) + return r; + + return cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.threads"); +} + +int cg_kill_recursive( + const char *controller, + const char *path, + int sig, + CGroupFlags flags, + Set *s, + cg_kill_log_func_t log_kill, + void *userdata) { + + _cleanup_set_free_ Set *allocated_set = NULL; + _cleanup_closedir_ DIR *d = NULL; + int r, ret; + char *fn; + + assert(path); + assert(sig >= 0); + + if (!s) { + s = allocated_set = set_new(NULL); + if (!s) + return -ENOMEM; + } + + ret = cg_kill(controller, path, sig, flags, s, log_kill, userdata); + + r = cg_enumerate_subgroups(controller, path, &d); + if (r < 0) { + if (ret >= 0 && r != -ENOENT) + return r; + + return ret; + } + + while ((r = cg_read_subgroup(d, &fn)) > 0) { + _cleanup_free_ char *p = NULL; + + p = path_join(empty_to_root(path), fn); + free(fn); + if (!p) + return -ENOMEM; + + r = cg_kill_recursive(controller, p, sig, flags, s, log_kill, userdata); + if (r != 0 && ret >= 0) + ret = r; + } + if (ret >= 0 && r < 0) + ret = r; + + if (flags & CGROUP_REMOVE) { + r = cg_rmdir(controller, path); + if (r < 0 && ret >= 0 && !IN_SET(r, -ENOENT, -EBUSY)) + return r; + } + + return ret; +} + +static const char *controller_to_dirname(const char *controller) { + const char *e; + + assert(controller); + + /* Converts a controller name to the directory name below + * /sys/fs/cgroup/ we want to mount it to. Effectively, this + * just cuts off the name= prefixed used for named + * hierarchies, if it is specified. */ + + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { + if (cg_hybrid_unified() > 0) + controller = SYSTEMD_CGROUP_CONTROLLER_HYBRID; + else + controller = SYSTEMD_CGROUP_CONTROLLER_LEGACY; + } + + e = startswith(controller, "name="); + if (e) + return e; + + return controller; +} + +static int join_path_legacy(const char *controller, const char *path, const char *suffix, char **fs) { + const char *dn; + char *t = NULL; + + assert(fs); + assert(controller); + + dn = controller_to_dirname(controller); + + if (isempty(path) && isempty(suffix)) + t = path_join("/sys/fs/cgroup", dn); + else if (isempty(path)) + t = path_join("/sys/fs/cgroup", dn, suffix); + else if (isempty(suffix)) + t = path_join("/sys/fs/cgroup", dn, path); + else + t = path_join("/sys/fs/cgroup", dn, path, suffix); + if (!t) + return -ENOMEM; + + *fs = t; + return 0; +} + +static int join_path_unified(const char *path, const char *suffix, char **fs) { + char *t; + + assert(fs); + + if (isempty(path) && isempty(suffix)) + t = strdup("/sys/fs/cgroup"); + else if (isempty(path)) + t = path_join("/sys/fs/cgroup", suffix); + else if (isempty(suffix)) + t = path_join("/sys/fs/cgroup", path); + else + t = path_join("/sys/fs/cgroup", path, suffix); + if (!t) + return -ENOMEM; + + *fs = t; + return 0; +} + +int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) { + int r; + + assert(fs); + + if (!controller) { + char *t; + + /* If no controller is specified, we return the path + * *below* the controllers, without any prefix. */ + + if (!path && !suffix) + return -EINVAL; + + if (!suffix) + t = strdup(path); + else if (!path) + t = strdup(suffix); + else + t = path_join(path, suffix); + if (!t) + return -ENOMEM; + + *fs = path_simplify(t, false); + return 0; + } + + if (!cg_controller_is_valid(controller)) + return -EINVAL; + + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) + r = join_path_unified(path, suffix, fs); + else + r = join_path_legacy(controller, path, suffix, fs); + if (r < 0) + return r; + + path_simplify(*fs, false); + return 0; +} + +static int controller_is_accessible(const char *controller) { + int r; + + assert(controller); + + /* Checks whether a specific controller is accessible, + * i.e. its hierarchy mounted. In the unified hierarchy all + * controllers are considered accessible, except for the named + * hierarchies */ + + if (!cg_controller_is_valid(controller)) + return -EINVAL; + + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) { + /* We don't support named hierarchies if we are using + * the unified hierarchy. */ + + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) + return 0; + + if (startswith(controller, "name=")) + return -EOPNOTSUPP; + + } else { + const char *cc, *dn; + + dn = controller_to_dirname(controller); + cc = strjoina("/sys/fs/cgroup/", dn); + + if (laccess(cc, F_OK) < 0) + return -errno; + } + + return 0; +} + +int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) { + int r; + + assert(controller); + assert(fs); + + /* Check if the specified controller is actually accessible */ + r = controller_is_accessible(controller); + if (r < 0) + return r; + + return cg_get_path(controller, path, suffix, fs); +} + +int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags) { + _cleanup_free_ char *fs = NULL; + int r; + + assert(path); + assert(name); + assert(value || size <= 0); + + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + if (setxattr(fs, name, value, size, flags) < 0) + return -errno; + + return 0; +} + +int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size) { + _cleanup_free_ char *fs = NULL; + ssize_t n; + int r; + + assert(path); + assert(name); + + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + n = getxattr(fs, name, value, size); + if (n < 0) + return -errno; + + return (int) n; +} + +int cg_remove_xattr(const char *controller, const char *path, const char *name) { + _cleanup_free_ char *fs = NULL; + int r; + + assert(path); + assert(name); + + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + if (removexattr(fs, name) < 0) + return -errno; + + return 0; +} + +int cg_pid_get_path(const char *controller, pid_t pid, char **path) { + _cleanup_fclose_ FILE *f = NULL; + const char *fs, *controller_str; + int unified, r; + size_t cs = 0; + + assert(path); + assert(pid >= 0); + + if (controller) { + if (!cg_controller_is_valid(controller)) + return -EINVAL; + } else + controller = SYSTEMD_CGROUP_CONTROLLER; + + unified = cg_unified_controller(controller); + if (unified < 0) + return unified; + if (unified == 0) { + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) + controller_str = SYSTEMD_CGROUP_CONTROLLER_LEGACY; + else + controller_str = controller; + + cs = strlen(controller_str); + } + + fs = procfs_file_alloca(pid, "cgroup"); + r = fopen_unlocked(fs, "re", &f); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *line = NULL; + char *e, *p; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + if (unified) { + e = startswith(line, "0:"); + if (!e) + continue; + + e = strchr(e, ':'); + if (!e) + continue; + } else { + char *l; + size_t k; + const char *word, *state; + bool found = false; + + l = strchr(line, ':'); + if (!l) + continue; + + l++; + e = strchr(l, ':'); + if (!e) + continue; + + *e = 0; + FOREACH_WORD_SEPARATOR(word, k, l, ",", state) + if (k == cs && memcmp(word, controller_str, cs) == 0) { + found = true; + break; + } + if (!found) + continue; + } + + p = strdup(e + 1); + if (!p) + return -ENOMEM; + + /* Truncate suffix indicating the process is a zombie */ + e = endswith(p, " (deleted)"); + if (e) + *e = 0; + + *path = p; + return 0; + } + + return -ENODATA; +} + +int cg_install_release_agent(const char *controller, const char *agent) { + _cleanup_free_ char *fs = NULL, *contents = NULL; + const char *sc; + int r; + + assert(agent); + + r = cg_unified_controller(controller); + if (r < 0) + return r; + if (r > 0) /* doesn't apply to unified hierarchy */ + return -EOPNOTSUPP; + + r = cg_get_path(controller, NULL, "release_agent", &fs); + if (r < 0) + return r; + + r = read_one_line_file(fs, &contents); + if (r < 0) + return r; + + sc = strstrip(contents); + if (isempty(sc)) { + r = write_string_file(fs, agent, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return r; + } else if (!path_equal(sc, agent)) + return -EEXIST; + + fs = mfree(fs); + r = cg_get_path(controller, NULL, "notify_on_release", &fs); + if (r < 0) + return r; + + contents = mfree(contents); + r = read_one_line_file(fs, &contents); + if (r < 0) + return r; + + sc = strstrip(contents); + if (streq(sc, "0")) { + r = write_string_file(fs, "1", WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return r; + + return 1; + } + + if (!streq(sc, "1")) + return -EIO; + + return 0; +} + +int cg_uninstall_release_agent(const char *controller) { + _cleanup_free_ char *fs = NULL; + int r; + + r = cg_unified_controller(controller); + if (r < 0) + return r; + if (r > 0) /* Doesn't apply to unified hierarchy */ + return -EOPNOTSUPP; + + r = cg_get_path(controller, NULL, "notify_on_release", &fs); + if (r < 0) + return r; + + r = write_string_file(fs, "0", WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return r; + + fs = mfree(fs); + + r = cg_get_path(controller, NULL, "release_agent", &fs); + if (r < 0) + return r; + + r = write_string_file(fs, "", WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return r; + + return 0; +} + +int cg_is_empty(const char *controller, const char *path) { + _cleanup_fclose_ FILE *f = NULL; + pid_t pid; + int r; + + assert(path); + + r = cg_enumerate_processes(controller, path, &f); + if (r == -ENOENT) + return true; + if (r < 0) + return r; + + r = cg_read_pid(f, &pid); + if (r < 0) + return r; + + return r == 0; +} + +int cg_is_empty_recursive(const char *controller, const char *path) { + int r; + + assert(path); + + /* The root cgroup is always populated */ + if (controller && empty_or_root(path)) + return false; + + r = cg_unified_controller(controller); + if (r < 0) + return r; + if (r > 0) { + _cleanup_free_ char *t = NULL; + + /* On the unified hierarchy we can check empty state + * via the "populated" attribute of "cgroup.events". */ + + r = cg_read_event(controller, path, "populated", &t); + if (r == -ENOENT) + return true; + if (r < 0) + return r; + + return streq(t, "0"); + } else { + _cleanup_closedir_ DIR *d = NULL; + char *fn; + + r = cg_is_empty(controller, path); + if (r <= 0) + return r; + + r = cg_enumerate_subgroups(controller, path, &d); + if (r == -ENOENT) + return true; + if (r < 0) + return r; + + while ((r = cg_read_subgroup(d, &fn)) > 0) { + _cleanup_free_ char *p = NULL; + + p = path_join(path, fn); + free(fn); + if (!p) + return -ENOMEM; + + r = cg_is_empty_recursive(controller, p); + if (r <= 0) + return r; + } + if (r < 0) + return r; + + return true; + } +} + +int cg_split_spec(const char *spec, char **controller, char **path) { + char *t = NULL, *u = NULL; + const char *e; + + assert(spec); + + if (*spec == '/') { + if (!path_is_normalized(spec)) + return -EINVAL; + + if (path) { + t = strdup(spec); + if (!t) + return -ENOMEM; + + *path = path_simplify(t, false); + } + + if (controller) + *controller = NULL; + + return 0; + } + + e = strchr(spec, ':'); + if (!e) { + if (!cg_controller_is_valid(spec)) + return -EINVAL; + + if (controller) { + t = strdup(spec); + if (!t) + return -ENOMEM; + + *controller = t; + } + + if (path) + *path = NULL; + + return 0; + } + + t = strndup(spec, e-spec); + if (!t) + return -ENOMEM; + if (!cg_controller_is_valid(t)) { + free(t); + return -EINVAL; + } + + if (isempty(e+1)) + u = NULL; + else { + u = strdup(e+1); + if (!u) { + free(t); + return -ENOMEM; + } + + if (!path_is_normalized(u) || + !path_is_absolute(u)) { + free(t); + free(u); + return -EINVAL; + } + + path_simplify(u, false); + } + + if (controller) + *controller = t; + else + free(t); + + if (path) + *path = u; + else + free(u); + + return 0; +} + +int cg_mangle_path(const char *path, char **result) { + _cleanup_free_ char *c = NULL, *p = NULL; + char *t; + int r; + + assert(path); + assert(result); + + /* First, check if it already is a filesystem path */ + if (path_startswith(path, "/sys/fs/cgroup")) { + + t = strdup(path); + if (!t) + return -ENOMEM; + + *result = path_simplify(t, false); + return 0; + } + + /* Otherwise, treat it as cg spec */ + r = cg_split_spec(path, &c, &p); + if (r < 0) + return r; + + return cg_get_path(c ?: SYSTEMD_CGROUP_CONTROLLER, p ?: "/", NULL, result); +} + +int cg_get_root_path(char **path) { + char *p, *e; + int r; + + assert(path); + + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p); + if (r < 0) + return r; + + e = endswith(p, "/" SPECIAL_INIT_SCOPE); + if (!e) + e = endswith(p, "/" SPECIAL_SYSTEM_SLICE); /* legacy */ + if (!e) + e = endswith(p, "/system"); /* even more legacy */ + if (e) + *e = 0; + + *path = p; + return 0; +} + +int cg_shift_path(const char *cgroup, const char *root, const char **shifted) { + _cleanup_free_ char *rt = NULL; + char *p; + int r; + + assert(cgroup); + assert(shifted); + + if (!root) { + /* If the root was specified let's use that, otherwise + * let's determine it from PID 1 */ + + r = cg_get_root_path(&rt); + if (r < 0) + return r; + + root = rt; + } + + p = path_startswith(cgroup, root); + if (p && p > cgroup) + *shifted = p - 1; + else + *shifted = cgroup; + + return 0; +} + +int cg_pid_get_path_shifted(pid_t pid, const char *root, char **cgroup) { + _cleanup_free_ char *raw = NULL; + const char *c; + int r; + + assert(pid >= 0); + assert(cgroup); + + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &raw); + if (r < 0) + return r; + + r = cg_shift_path(raw, root, &c); + if (r < 0) + return r; + + if (c == raw) + *cgroup = TAKE_PTR(raw); + else { + char *n; + + n = strdup(c); + if (!n) + return -ENOMEM; + + *cgroup = n; + } + + return 0; +} + +int cg_path_decode_unit(const char *cgroup, char **unit) { + char *c, *s; + size_t n; + + assert(cgroup); + assert(unit); + + n = strcspn(cgroup, "/"); + if (n < 3) + return -ENXIO; + + c = strndupa(cgroup, n); + c = cg_unescape(c); + + if (!unit_name_is_valid(c, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) + return -ENXIO; + + s = strdup(c); + if (!s) + return -ENOMEM; + + *unit = s; + return 0; +} + +static bool valid_slice_name(const char *p, size_t n) { + + if (!p) + return false; + + if (n < STRLEN("x.slice")) + return false; + + if (memcmp(p + n - 6, ".slice", 6) == 0) { + char buf[n+1], *c; + + memcpy(buf, p, n); + buf[n] = 0; + + c = cg_unescape(buf); + + return unit_name_is_valid(c, UNIT_NAME_PLAIN); + } + + return false; +} + +static const char *skip_slices(const char *p) { + assert(p); + + /* Skips over all slice assignments */ + + for (;;) { + size_t n; + + p += strspn(p, "/"); + + n = strcspn(p, "/"); + if (!valid_slice_name(p, n)) + return p; + + p += n; + } +} + +int cg_path_get_unit(const char *path, char **ret) { + const char *e; + char *unit; + int r; + + assert(path); + assert(ret); + + e = skip_slices(path); + + r = cg_path_decode_unit(e, &unit); + if (r < 0) + return r; + + /* We skipped over the slices, don't accept any now */ + if (endswith(unit, ".slice")) { + free(unit); + return -ENXIO; + } + + *ret = unit; + return 0; +} + +int cg_pid_get_unit(pid_t pid, char **unit) { + _cleanup_free_ char *cgroup = NULL; + int r; + + assert(unit); + + r = cg_pid_get_path_shifted(pid, NULL, &cgroup); + if (r < 0) + return r; + + return cg_path_get_unit(cgroup, unit); +} + +/** + * Skip session-*.scope, but require it to be there. + */ +static const char *skip_session(const char *p) { + size_t n; + + if (isempty(p)) + return NULL; + + p += strspn(p, "/"); + + n = strcspn(p, "/"); + if (n < STRLEN("session-x.scope")) + return NULL; + + if (memcmp(p, "session-", 8) == 0 && memcmp(p + n - 6, ".scope", 6) == 0) { + char buf[n - 8 - 6 + 1]; + + memcpy(buf, p + 8, n - 8 - 6); + buf[n - 8 - 6] = 0; + + /* Note that session scopes never need unescaping, + * since they cannot conflict with the kernel's own + * names, hence we don't need to call cg_unescape() + * here. */ + + if (!session_id_valid(buf)) + return false; + + p += n; + p += strspn(p, "/"); + return p; + } + + return NULL; +} + +/** + * Skip user@*.service, but require it to be there. + */ +static const char *skip_user_manager(const char *p) { + size_t n; + + if (isempty(p)) + return NULL; + + p += strspn(p, "/"); + + n = strcspn(p, "/"); + if (n < STRLEN("user@x.service")) + return NULL; + + if (memcmp(p, "user@", 5) == 0 && memcmp(p + n - 8, ".service", 8) == 0) { + char buf[n - 5 - 8 + 1]; + + memcpy(buf, p + 5, n - 5 - 8); + buf[n - 5 - 8] = 0; + + /* Note that user manager services never need unescaping, + * since they cannot conflict with the kernel's own + * names, hence we don't need to call cg_unescape() + * here. */ + + if (parse_uid(buf, NULL) < 0) + return NULL; + + p += n; + p += strspn(p, "/"); + + return p; + } + + return NULL; +} + +static const char *skip_user_prefix(const char *path) { + const char *e, *t; + + assert(path); + + /* Skip slices, if there are any */ + e = skip_slices(path); + + /* Skip the user manager, if it's in the path now... */ + t = skip_user_manager(e); + if (t) + return t; + + /* Alternatively skip the user session if it is in the path... */ + return skip_session(e); +} + +int cg_path_get_user_unit(const char *path, char **ret) { + const char *t; + + assert(path); + assert(ret); + + t = skip_user_prefix(path); + if (!t) + return -ENXIO; + + /* And from here on it looks pretty much the same as for a system unit, hence let's use the same + * parser. */ + return cg_path_get_unit(t, ret); +} + +int cg_pid_get_user_unit(pid_t pid, char **unit) { + _cleanup_free_ char *cgroup = NULL; + int r; + + assert(unit); + + r = cg_pid_get_path_shifted(pid, NULL, &cgroup); + if (r < 0) + return r; + + return cg_path_get_user_unit(cgroup, unit); +} + +int cg_path_get_machine_name(const char *path, char **machine) { + _cleanup_free_ char *u = NULL; + const char *sl; + int r; + + r = cg_path_get_unit(path, &u); + if (r < 0) + return r; + + sl = strjoina("/run/systemd/machines/unit:", u); + return readlink_malloc(sl, machine); +} + +int cg_pid_get_machine_name(pid_t pid, char **machine) { + _cleanup_free_ char *cgroup = NULL; + int r; + + assert(machine); + + r = cg_pid_get_path_shifted(pid, NULL, &cgroup); + if (r < 0) + return r; + + return cg_path_get_machine_name(cgroup, machine); +} + +int cg_path_get_session(const char *path, char **session) { + _cleanup_free_ char *unit = NULL; + char *start, *end; + int r; + + assert(path); + + r = cg_path_get_unit(path, &unit); + if (r < 0) + return r; + + start = startswith(unit, "session-"); + if (!start) + return -ENXIO; + end = endswith(start, ".scope"); + if (!end) + return -ENXIO; + + *end = 0; + if (!session_id_valid(start)) + return -ENXIO; + + if (session) { + char *rr; + + rr = strdup(start); + if (!rr) + return -ENOMEM; + + *session = rr; + } + + return 0; +} + +int cg_pid_get_session(pid_t pid, char **session) { + _cleanup_free_ char *cgroup = NULL; + int r; + + r = cg_pid_get_path_shifted(pid, NULL, &cgroup); + if (r < 0) + return r; + + return cg_path_get_session(cgroup, session); +} + +int cg_path_get_owner_uid(const char *path, uid_t *uid) { + _cleanup_free_ char *slice = NULL; + char *start, *end; + int r; + + assert(path); + + r = cg_path_get_slice(path, &slice); + if (r < 0) + return r; + + start = startswith(slice, "user-"); + if (!start) + return -ENXIO; + end = endswith(start, ".slice"); + if (!end) + return -ENXIO; + + *end = 0; + if (parse_uid(start, uid) < 0) + return -ENXIO; + + return 0; +} + +int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) { + _cleanup_free_ char *cgroup = NULL; + int r; + + r = cg_pid_get_path_shifted(pid, NULL, &cgroup); + if (r < 0) + return r; + + return cg_path_get_owner_uid(cgroup, uid); +} + +int cg_path_get_slice(const char *p, char **slice) { + const char *e = NULL; + + assert(p); + assert(slice); + + /* Finds the right-most slice unit from the beginning, but + * stops before we come to the first non-slice unit. */ + + for (;;) { + size_t n; + + p += strspn(p, "/"); + + n = strcspn(p, "/"); + if (!valid_slice_name(p, n)) { + + if (!e) { + char *s; + + s = strdup(SPECIAL_ROOT_SLICE); + if (!s) + return -ENOMEM; + + *slice = s; + return 0; + } + + return cg_path_decode_unit(e, slice); + } + + e = p; + p += n; + } +} + +int cg_pid_get_slice(pid_t pid, char **slice) { + _cleanup_free_ char *cgroup = NULL; + int r; + + assert(slice); + + r = cg_pid_get_path_shifted(pid, NULL, &cgroup); + if (r < 0) + return r; + + return cg_path_get_slice(cgroup, slice); +} + +int cg_path_get_user_slice(const char *p, char **slice) { + const char *t; + assert(p); + assert(slice); + + t = skip_user_prefix(p); + if (!t) + return -ENXIO; + + /* And now it looks pretty much the same as for a system + * slice, so let's just use the same parser from here on. */ + return cg_path_get_slice(t, slice); +} + +int cg_pid_get_user_slice(pid_t pid, char **slice) { + _cleanup_free_ char *cgroup = NULL; + int r; + + assert(slice); + + r = cg_pid_get_path_shifted(pid, NULL, &cgroup); + if (r < 0) + return r; + + return cg_path_get_user_slice(cgroup, slice); +} + +char *cg_escape(const char *p) { + bool need_prefix = false; + + /* This implements very minimal escaping for names to be used + * as file names in the cgroup tree: any name which might + * conflict with a kernel name or is prefixed with '_' is + * prefixed with a '_'. That way, when reading cgroup names it + * is sufficient to remove a single prefixing underscore if + * there is one. */ + + /* The return value of this function (unlike cg_unescape()) + * needs free()! */ + + if (IN_SET(p[0], 0, '_', '.') || + STR_IN_SET(p, "notify_on_release", "release_agent", "tasks") || + startswith(p, "cgroup.")) + need_prefix = true; + else { + const char *dot; + + dot = strrchr(p, '.'); + if (dot) { + CGroupController c; + size_t l = dot - p; + + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { + const char *n; + + n = cgroup_controller_to_string(c); + + if (l != strlen(n)) + continue; + + if (memcmp(p, n, l) != 0) + continue; + + need_prefix = true; + break; + } + } + } + + if (need_prefix) + return strjoin("_", p); + + return strdup(p); +} + +char *cg_unescape(const char *p) { + assert(p); + + /* The return value of this function (unlike cg_escape()) + * doesn't need free()! */ + + if (p[0] == '_') + return (char*) p+1; + + return (char*) p; +} + +#define CONTROLLER_VALID \ + DIGITS LETTERS \ + "_" + +bool cg_controller_is_valid(const char *p) { + const char *t, *s; + + if (!p) + return false; + + if (streq(p, SYSTEMD_CGROUP_CONTROLLER)) + return true; + + s = startswith(p, "name="); + if (s) + p = s; + + if (IN_SET(*p, 0, '_')) + return false; + + for (t = p; *t; t++) + if (!strchr(CONTROLLER_VALID, *t)) + return false; + + if (t - p > FILENAME_MAX) + return false; + + return true; +} + +int cg_slice_to_path(const char *unit, char **ret) { + _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL; + const char *dash; + int r; + + assert(unit); + assert(ret); + + if (streq(unit, SPECIAL_ROOT_SLICE)) { + char *x; + + x = strdup(""); + if (!x) + return -ENOMEM; + *ret = x; + return 0; + } + + if (!unit_name_is_valid(unit, UNIT_NAME_PLAIN)) + return -EINVAL; + + if (!endswith(unit, ".slice")) + return -EINVAL; + + r = unit_name_to_prefix(unit, &p); + if (r < 0) + return r; + + dash = strchr(p, '-'); + + /* Don't allow initial dashes */ + if (dash == p) + return -EINVAL; + + while (dash) { + _cleanup_free_ char *escaped = NULL; + char n[dash - p + sizeof(".slice")]; + +#if HAS_FEATURE_MEMORY_SANITIZER + /* msan doesn't instrument stpncpy, so it thinks + * n is later used uninitialized: + * https://github.com/google/sanitizers/issues/926 + */ + zero(n); +#endif + + /* Don't allow trailing or double dashes */ + if (IN_SET(dash[1], 0, '-')) + return -EINVAL; + + strcpy(stpncpy(n, p, dash - p), ".slice"); + if (!unit_name_is_valid(n, UNIT_NAME_PLAIN)) + return -EINVAL; + + escaped = cg_escape(n); + if (!escaped) + return -ENOMEM; + + if (!strextend(&s, escaped, "/", NULL)) + return -ENOMEM; + + dash = strchr(dash+1, '-'); + } + + e = cg_escape(unit); + if (!e) + return -ENOMEM; + + if (!strextend(&s, e, NULL)) + return -ENOMEM; + + *ret = TAKE_PTR(s); + + return 0; +} + +int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) { + _cleanup_free_ char *p = NULL; + int r; + + r = cg_get_path(controller, path, attribute, &p); + if (r < 0) + return r; + + return write_string_file(p, value, WRITE_STRING_FILE_DISABLE_BUFFER); +} + +int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) { + _cleanup_free_ char *p = NULL; + int r; + + r = cg_get_path(controller, path, attribute, &p); + if (r < 0) + return r; + + return read_one_line_file(p, ret); +} + +int cg_get_keyed_attribute( + const char *controller, + const char *path, + const char *attribute, + char **keys, + char **ret_values) { + + _cleanup_free_ char *filename = NULL, *contents = NULL; + const char *p; + size_t n, i, n_done = 0; + char **v; + int r; + + /* Reads one or more fields of a cgroup v2 keyed attribute file. The 'keys' parameter should be an strv with + * all keys to retrieve. The 'ret_values' parameter should be passed as string size with the same number of + * entries as 'keys'. On success each entry will be set to the value of the matching key. + * + * If the attribute file doesn't exist at all returns ENOENT, if any key is not found returns ENXIO. */ + + r = cg_get_path(controller, path, attribute, &filename); + if (r < 0) + return r; + + r = read_full_file(filename, &contents, NULL); + if (r < 0) + return r; + + n = strv_length(keys); + if (n == 0) /* No keys to retrieve? That's easy, we are done then */ + return 0; + + /* Let's build this up in a temporary array for now in order not to clobber the return parameter on failure */ + v = newa0(char*, n); + + for (p = contents; *p;) { + const char *w = NULL; + + for (i = 0; i < n; i++) + if (!v[i]) { + w = first_word(p, keys[i]); + if (w) + break; + } + + if (w) { + size_t l; + + l = strcspn(w, NEWLINE); + v[i] = strndup(w, l); + if (!v[i]) { + r = -ENOMEM; + goto fail; + } + + n_done++; + if (n_done >= n) + goto done; + + p = w + l; + } else + p += strcspn(p, NEWLINE); + + p += strspn(p, NEWLINE); + } + + r = -ENXIO; + +fail: + for (i = 0; i < n; i++) + free(v[i]); + + return r; + +done: + memcpy(ret_values, v, sizeof(char*) * n); + return 0; +} + +int cg_mask_to_string(CGroupMask mask, char **ret) { + _cleanup_free_ char *s = NULL; + size_t n = 0, allocated = 0; + bool space = false; + CGroupController c; + + assert(ret); + + if (mask == 0) { + *ret = NULL; + return 0; + } + + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { + const char *k; + size_t l; + + if (!FLAGS_SET(mask, CGROUP_CONTROLLER_TO_MASK(c))) + continue; + + k = cgroup_controller_to_string(c); + l = strlen(k); + + if (!GREEDY_REALLOC(s, allocated, n + space + l + 1)) + return -ENOMEM; + + if (space) + s[n] = ' '; + memcpy(s + n + space, k, l); + n += space + l; + + space = true; + } + + assert(s); + + s[n] = 0; + *ret = TAKE_PTR(s); + + return 0; +} + +int cg_mask_from_string(const char *value, CGroupMask *ret) { + CGroupMask m = 0; + + assert(ret); + assert(value); + + for (;;) { + _cleanup_free_ char *n = NULL; + CGroupController v; + int r; + + r = extract_first_word(&value, &n, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + v = cgroup_controller_from_string(n); + if (v < 0) + continue; + + m |= CGROUP_CONTROLLER_TO_MASK(v); + } + + *ret = m; + return 0; +} + +int cg_mask_supported(CGroupMask *ret) { + CGroupMask mask; + int r; + + /* Determines the mask of supported cgroup controllers. Only includes controllers we can make sense of and that + * are actually accessible. Only covers real controllers, i.e. not the CGROUP_CONTROLLER_BPF_xyz + * pseudo-controllers. */ + + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) { + _cleanup_free_ char *root = NULL, *controllers = NULL, *path = NULL; + + /* In the unified hierarchy we can read the supported + * and accessible controllers from a the top-level + * cgroup attribute */ + + r = cg_get_root_path(&root); + if (r < 0) + return r; + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, "cgroup.controllers", &path); + if (r < 0) + return r; + + r = read_one_line_file(path, &controllers); + if (r < 0) + return r; + + r = cg_mask_from_string(controllers, &mask); + if (r < 0) + return r; + + /* Mask controllers that are not supported in unified hierarchy. */ + mask &= CGROUP_MASK_V2; + + } else { + CGroupController c; + + /* In the legacy hierarchy, we check which hierarchies are mounted. */ + + mask = 0; + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { + CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); + const char *n; + + if (!FLAGS_SET(CGROUP_MASK_V1, bit)) + continue; + + n = cgroup_controller_to_string(c); + if (controller_is_accessible(n) >= 0) + mask |= bit; + } + } + + *ret = mask; + return 0; +} + +int cg_kernel_controllers(Set **ret) { + _cleanup_set_free_free_ Set *controllers = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(ret); + + /* Determines the full list of kernel-known controllers. Might include controllers we don't actually support + * and controllers that aren't currently accessible (because not mounted). This does not include "name=" + * pseudo-controllers. */ + + controllers = set_new(&string_hash_ops); + if (!controllers) + return -ENOMEM; + + r = fopen_unlocked("/proc/cgroups", "re", &f); + if (r == -ENOENT) { + *ret = NULL; + return 0; + } + if (r < 0) + return r; + + /* Ignore the header line */ + (void) read_line(f, (size_t) -1, NULL); + + for (;;) { + char *controller; + int enabled = 0; + + errno = 0; + if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) { + + if (feof(f)) + break; + + if (ferror(f)) + return errno_or_else(EIO); + + return -EBADMSG; + } + + if (!enabled) { + free(controller); + continue; + } + + if (!cg_controller_is_valid(controller)) { + free(controller); + return -EBADMSG; + } + + r = set_consume(controllers, controller); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(controllers); + + return 0; +} + +/* The hybrid mode was initially implemented in v232 and simply mounted cgroup2 on + * /sys/fs/cgroup/systemd. This unfortunately broke other tools (such as docker) which expected the v1 + * "name=systemd" hierarchy on /sys/fs/cgroup/systemd. From v233 and on, the hybrid mode mounts v2 on + * /sys/fs/cgroup/unified and maintains "name=systemd" hierarchy on /sys/fs/cgroup/systemd for compatibility + * with other tools. + * + * To keep live upgrade working, we detect and support v232 layout. When v232 layout is detected, to keep + * cgroup v2 process management but disable the compat dual layout, we return true on + * cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) and false on cg_hybrid_unified(). + */ +static thread_local bool unified_systemd_v232; + +int cg_unified_cached(bool flush) { + static thread_local CGroupUnified unified_cache = CGROUP_UNIFIED_UNKNOWN; + + struct statfs fs; + + /* Checks if we support the unified hierarchy. Returns an + * error when the cgroup hierarchies aren't mounted yet or we + * have any other trouble determining if the unified hierarchy + * is supported. */ + + if (flush) + unified_cache = CGROUP_UNIFIED_UNKNOWN; + else if (unified_cache >= CGROUP_UNIFIED_NONE) + return unified_cache; + + if (statfs("/sys/fs/cgroup/", &fs) < 0) + return log_debug_errno(errno, "statfs(\"/sys/fs/cgroup/\") failed: %m"); + + if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) { + log_debug("Found cgroup2 on /sys/fs/cgroup/, full unified hierarchy"); + unified_cache = CGROUP_UNIFIED_ALL; + } else if (F_TYPE_EQUAL(fs.f_type, TMPFS_MAGIC)) { + if (statfs("/sys/fs/cgroup/unified/", &fs) == 0 && + F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) { + log_debug("Found cgroup2 on /sys/fs/cgroup/unified, unified hierarchy for systemd controller"); + unified_cache = CGROUP_UNIFIED_SYSTEMD; + unified_systemd_v232 = false; + } else { + if (statfs("/sys/fs/cgroup/systemd/", &fs) < 0) + return log_debug_errno(errno, "statfs(\"/sys/fs/cgroup/systemd\" failed: %m"); + + if (F_TYPE_EQUAL(fs.f_type, CGROUP2_SUPER_MAGIC)) { + log_debug("Found cgroup2 on /sys/fs/cgroup/systemd, unified hierarchy for systemd controller (v232 variant)"); + unified_cache = CGROUP_UNIFIED_SYSTEMD; + unified_systemd_v232 = true; + } else if (F_TYPE_EQUAL(fs.f_type, CGROUP_SUPER_MAGIC)) { + log_debug("Found cgroup on /sys/fs/cgroup/systemd, legacy hierarchy"); + unified_cache = CGROUP_UNIFIED_NONE; + } else { + log_debug("Unexpected filesystem type %llx mounted on /sys/fs/cgroup/systemd, assuming legacy hierarchy", + (unsigned long long) fs.f_type); + unified_cache = CGROUP_UNIFIED_NONE; + } + } + } else + return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM), + "Unknown filesystem type %llx mounted on /sys/fs/cgroup.", + (unsigned long long)fs.f_type); + + return unified_cache; +} + +int cg_unified_controller(const char *controller) { + int r; + + r = cg_unified_cached(false); + if (r < 0) + return r; + + if (r == CGROUP_UNIFIED_NONE) + return false; + + if (r >= CGROUP_UNIFIED_ALL) + return true; + + return streq_ptr(controller, SYSTEMD_CGROUP_CONTROLLER); +} + +int cg_all_unified(void) { + int r; + + r = cg_unified_cached(false); + if (r < 0) + return r; + + return r >= CGROUP_UNIFIED_ALL; +} + +int cg_hybrid_unified(void) { + int r; + + r = cg_unified_cached(false); + if (r < 0) + return r; + + return r == CGROUP_UNIFIED_SYSTEMD && !unified_systemd_v232; +} + +const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX] = { + [CGROUP_IO_RBPS_MAX] = CGROUP_LIMIT_MAX, + [CGROUP_IO_WBPS_MAX] = CGROUP_LIMIT_MAX, + [CGROUP_IO_RIOPS_MAX] = CGROUP_LIMIT_MAX, + [CGROUP_IO_WIOPS_MAX] = CGROUP_LIMIT_MAX, +}; + +static const char* const cgroup_io_limit_type_table[_CGROUP_IO_LIMIT_TYPE_MAX] = { + [CGROUP_IO_RBPS_MAX] = "IOReadBandwidthMax", + [CGROUP_IO_WBPS_MAX] = "IOWriteBandwidthMax", + [CGROUP_IO_RIOPS_MAX] = "IOReadIOPSMax", + [CGROUP_IO_WIOPS_MAX] = "IOWriteIOPSMax", +}; + +DEFINE_STRING_TABLE_LOOKUP(cgroup_io_limit_type, CGroupIOLimitType); + +bool is_cgroup_fs(const struct statfs *s) { + return is_fs_type(s, CGROUP_SUPER_MAGIC) || + is_fs_type(s, CGROUP2_SUPER_MAGIC); +} + +bool fd_is_cgroup_fs(int fd) { + struct statfs s; + + if (fstatfs(fd, &s) < 0) + return -errno; + + return is_cgroup_fs(&s); +} + +static const char *const cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = { + [CGROUP_CONTROLLER_CPU] = "cpu", + [CGROUP_CONTROLLER_CPUACCT] = "cpuacct", + [CGROUP_CONTROLLER_CPUSET] = "cpuset", + [CGROUP_CONTROLLER_IO] = "io", + [CGROUP_CONTROLLER_BLKIO] = "blkio", + [CGROUP_CONTROLLER_MEMORY] = "memory", + [CGROUP_CONTROLLER_DEVICES] = "devices", + [CGROUP_CONTROLLER_PIDS] = "pids", + [CGROUP_CONTROLLER_BPF_FIREWALL] = "bpf-firewall", + [CGROUP_CONTROLLER_BPF_DEVICES] = "bpf-devices", +}; + +DEFINE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController); + +CGroupMask get_cpu_accounting_mask(void) { + static CGroupMask needed_mask = (CGroupMask) -1; + + /* On kernel ≥4.15 with unified hierarchy, cpu.stat's usage_usec is + * provided externally from the CPU controller, which means we don't + * need to enable the CPU controller just to get metrics. This is good, + * because enabling the CPU controller comes at a minor performance + * hit, especially when it's propagated deep into large hierarchies. + * There's also no separate CPU accounting controller available within + * a unified hierarchy. + * + * This combination of factors results in the desired cgroup mask to + * enable for CPU accounting varying as follows: + * + * ╔═════════════════════╤═════════════════════╗ + * ║ Linux ≥4.15 │ Linux <4.15 ║ + * ╔═══════════════╬═════════════════════╪═════════════════════╣ + * ║ Unified ║ nothing │ CGROUP_MASK_CPU ║ + * ╟───────────────╫─────────────────────┼─────────────────────╢ + * ║ Hybrid/Legacy ║ CGROUP_MASK_CPUACCT │ CGROUP_MASK_CPUACCT ║ + * ╚═══════════════╩═════════════════════╧═════════════════════╝ + * + * We check kernel version here instead of manually checking whether + * cpu.stat is present for every cgroup, as that check in itself would + * already be fairly expensive. + * + * Kernels where this patch has been backported will therefore have the + * CPU controller enabled unnecessarily. This is more expensive than + * necessary, but harmless. ☺️ + */ + + if (needed_mask == (CGroupMask) -1) { + if (cg_all_unified()) { + struct utsname u; + assert_se(uname(&u) >= 0); + + if (str_verscmp(u.release, "4.15") < 0) + needed_mask = CGROUP_MASK_CPU; + else + needed_mask = 0; + } else + needed_mask = CGROUP_MASK_CPUACCT; + } + + return needed_mask; +} + +bool cpu_accounting_is_cheap(void) { + return get_cpu_accounting_mask() == 0; +} diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h new file mode 100644 index 00000000..ad166190 --- /dev/null +++ b/src/basic/cgroup-util.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "def.h" +#include "set.h" + +#define SYSTEMD_CGROUP_CONTROLLER_LEGACY "name=systemd" +#define SYSTEMD_CGROUP_CONTROLLER_HYBRID "name=unified" +#define SYSTEMD_CGROUP_CONTROLLER "_systemd" + +/* An enum of well known cgroup controllers */ +typedef enum CGroupController { + /* Original cgroup controllers */ + CGROUP_CONTROLLER_CPU, + CGROUP_CONTROLLER_CPUACCT, /* v1 only */ + CGROUP_CONTROLLER_CPUSET, /* v2 only */ + CGROUP_CONTROLLER_IO, /* v2 only */ + CGROUP_CONTROLLER_BLKIO, /* v1 only */ + CGROUP_CONTROLLER_MEMORY, + CGROUP_CONTROLLER_DEVICES, /* v1 only */ + CGROUP_CONTROLLER_PIDS, + + /* BPF-based pseudo-controllers, v2 only */ + CGROUP_CONTROLLER_BPF_FIREWALL, + CGROUP_CONTROLLER_BPF_DEVICES, + + _CGROUP_CONTROLLER_MAX, + _CGROUP_CONTROLLER_INVALID = -1, +} CGroupController; + +#define CGROUP_CONTROLLER_TO_MASK(c) (1U << (c)) + +/* A bit mask of well known cgroup controllers */ +typedef enum CGroupMask { + CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU), + CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT), + CGROUP_MASK_CPUSET = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUSET), + CGROUP_MASK_IO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_IO), + CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO), + CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY), + CGROUP_MASK_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_DEVICES), + CGROUP_MASK_PIDS = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_PIDS), + CGROUP_MASK_BPF_FIREWALL = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_FIREWALL), + CGROUP_MASK_BPF_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BPF_DEVICES), + + /* All real cgroup v1 controllers */ + CGROUP_MASK_V1 = CGROUP_MASK_CPU|CGROUP_MASK_CPUACCT|CGROUP_MASK_BLKIO|CGROUP_MASK_MEMORY|CGROUP_MASK_DEVICES|CGROUP_MASK_PIDS, + + /* All real cgroup v2 controllers */ + CGROUP_MASK_V2 = CGROUP_MASK_CPU|CGROUP_MASK_CPUSET|CGROUP_MASK_IO|CGROUP_MASK_MEMORY|CGROUP_MASK_PIDS, + + /* All cgroup v2 BPF pseudo-controllers */ + CGROUP_MASK_BPF = CGROUP_MASK_BPF_FIREWALL|CGROUP_MASK_BPF_DEVICES, + + _CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1 +} CGroupMask; + +static inline CGroupMask CGROUP_MASK_EXTEND_JOINED(CGroupMask mask) { + /* We always mount "cpu" and "cpuacct" in the same hierarchy. Hence, when one bit is set also set the other */ + + if (mask & (CGROUP_MASK_CPU|CGROUP_MASK_CPUACCT)) + mask |= (CGROUP_MASK_CPU|CGROUP_MASK_CPUACCT); + + return mask; +} + +CGroupMask get_cpu_accounting_mask(void); +bool cpu_accounting_is_cheap(void); + +/* Special values for all weight knobs on unified hierarchy */ +#define CGROUP_WEIGHT_INVALID ((uint64_t) -1) +#define CGROUP_WEIGHT_MIN UINT64_C(1) +#define CGROUP_WEIGHT_MAX UINT64_C(10000) +#define CGROUP_WEIGHT_DEFAULT UINT64_C(100) + +#define CGROUP_LIMIT_MIN UINT64_C(0) +#define CGROUP_LIMIT_MAX ((uint64_t) -1) + +static inline bool CGROUP_WEIGHT_IS_OK(uint64_t x) { + return + x == CGROUP_WEIGHT_INVALID || + (x >= CGROUP_WEIGHT_MIN && x <= CGROUP_WEIGHT_MAX); +} + +/* IO limits on unified hierarchy */ +typedef enum CGroupIOLimitType { + CGROUP_IO_RBPS_MAX, + CGROUP_IO_WBPS_MAX, + CGROUP_IO_RIOPS_MAX, + CGROUP_IO_WIOPS_MAX, + + _CGROUP_IO_LIMIT_TYPE_MAX, + _CGROUP_IO_LIMIT_TYPE_INVALID = -1 +} CGroupIOLimitType; + +extern const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX]; + +const char* cgroup_io_limit_type_to_string(CGroupIOLimitType t) _const_; +CGroupIOLimitType cgroup_io_limit_type_from_string(const char *s) _pure_; + +/* Special values for the cpu.shares attribute */ +#define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1) +#define CGROUP_CPU_SHARES_MIN UINT64_C(2) +#define CGROUP_CPU_SHARES_MAX UINT64_C(262144) +#define CGROUP_CPU_SHARES_DEFAULT UINT64_C(1024) + +static inline bool CGROUP_CPU_SHARES_IS_OK(uint64_t x) { + return + x == CGROUP_CPU_SHARES_INVALID || + (x >= CGROUP_CPU_SHARES_MIN && x <= CGROUP_CPU_SHARES_MAX); +} + +/* Special values for the blkio.weight attribute */ +#define CGROUP_BLKIO_WEIGHT_INVALID ((uint64_t) -1) +#define CGROUP_BLKIO_WEIGHT_MIN UINT64_C(10) +#define CGROUP_BLKIO_WEIGHT_MAX UINT64_C(1000) +#define CGROUP_BLKIO_WEIGHT_DEFAULT UINT64_C(500) + +static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) { + return + x == CGROUP_BLKIO_WEIGHT_INVALID || + (x >= CGROUP_BLKIO_WEIGHT_MIN && x <= CGROUP_BLKIO_WEIGHT_MAX); +} + +typedef enum CGroupUnified { + CGROUP_UNIFIED_UNKNOWN = -1, + CGROUP_UNIFIED_NONE = 0, /* Both systemd and controllers on legacy */ + CGROUP_UNIFIED_SYSTEMD = 1, /* Only systemd on unified */ + CGROUP_UNIFIED_ALL = 2, /* Both systemd and controllers on unified */ +} CGroupUnified; + +/* + * General rules: + * + * We accept named hierarchies in the syntax "foo" and "name=foo". + * + * We expect that named hierarchies do not conflict in name with a + * kernel hierarchy, modulo the "name=" prefix. + * + * We always generate "normalized" controller names, i.e. without the + * "name=" prefix. + * + * We require absolute cgroup paths. When returning, we will always + * generate paths with multiple adjacent / removed. + */ + +int cg_enumerate_processes(const char *controller, const char *path, FILE **_f); +int cg_read_pid(FILE *f, pid_t *_pid); +int cg_read_event(const char *controller, const char *path, const char *event, + char **val); + +int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d); +int cg_read_subgroup(DIR *d, char **fn); + +typedef enum CGroupFlags { + CGROUP_SIGCONT = 1 << 0, + CGROUP_IGNORE_SELF = 1 << 1, + CGROUP_REMOVE = 1 << 2, +} CGroupFlags; + +typedef int (*cg_kill_log_func_t)(pid_t pid, int sig, void *userdata); + +int cg_kill(const char *controller, const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata); +int cg_kill_recursive(const char *controller, const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata); + +int cg_split_spec(const char *spec, char **controller, char **path); +int cg_mangle_path(const char *path, char **result); + +int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs); +int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs); + +int cg_pid_get_path(const char *controller, pid_t pid, char **path); + +int cg_rmdir(const char *controller, const char *path); + +int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value); +int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret); +int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, char **keys, char **values); + +int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid); + +int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags); +int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size); +int cg_remove_xattr(const char *controller, const char *path, const char *name); + +int cg_install_release_agent(const char *controller, const char *agent); +int cg_uninstall_release_agent(const char *controller); + +int cg_is_empty(const char *controller, const char *path); +int cg_is_empty_recursive(const char *controller, const char *path); + +int cg_get_root_path(char **path); + +int cg_path_get_session(const char *path, char **session); +int cg_path_get_owner_uid(const char *path, uid_t *uid); +int cg_path_get_unit(const char *path, char **unit); +int cg_path_get_user_unit(const char *path, char **unit); +int cg_path_get_machine_name(const char *path, char **machine); +int cg_path_get_slice(const char *path, char **slice); +int cg_path_get_user_slice(const char *path, char **slice); + +int cg_shift_path(const char *cgroup, const char *cached_root, const char **shifted); +int cg_pid_get_path_shifted(pid_t pid, const char *cached_root, char **cgroup); + +int cg_pid_get_session(pid_t pid, char **session); +int cg_pid_get_owner_uid(pid_t pid, uid_t *uid); +int cg_pid_get_unit(pid_t pid, char **unit); +int cg_pid_get_user_unit(pid_t pid, char **unit); +int cg_pid_get_machine_name(pid_t pid, char **machine); +int cg_pid_get_slice(pid_t pid, char **slice); +int cg_pid_get_user_slice(pid_t pid, char **slice); + +int cg_path_decode_unit(const char *cgroup, char **unit); + +char *cg_escape(const char *p); +char *cg_unescape(const char *p) _pure_; + +bool cg_controller_is_valid(const char *p); + +int cg_slice_to_path(const char *unit, char **ret); + +typedef const char* (*cg_migrate_callback_t)(CGroupMask mask, void *userdata); + +int cg_mask_supported(CGroupMask *ret); +int cg_mask_from_string(const char *s, CGroupMask *ret); +int cg_mask_to_string(CGroupMask mask, char **ret); + +int cg_kernel_controllers(Set **controllers); + +bool cg_ns_supported(void); + +int cg_all_unified(void); +int cg_hybrid_unified(void); +int cg_unified_controller(const char *controller); +int cg_unified_cached(bool flush); +static inline int cg_unified(void) { + return cg_unified_cached(true); +} + +const char* cgroup_controller_to_string(CGroupController c) _const_; +CGroupController cgroup_controller_from_string(const char *s) _pure_; + +bool is_cgroup_fs(const struct statfs *s); +bool fd_is_cgroup_fs(int fd); diff --git a/src/basic/chattr-util.c b/src/basic/chattr-util.c new file mode 100644 index 00000000..235cfb9b --- /dev/null +++ b/src/basic/chattr-util.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "chattr-util.h" +#include "fd-util.h" +#include "macro.h" + +int chattr_fd(int fd, unsigned value, unsigned mask, unsigned *previous) { + unsigned old_attr, new_attr; + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + /* Explicitly check whether this is a regular file or + * directory. If it is anything else (such as a device node or + * fifo), then the ioctl will not hit the file systems but + * possibly drivers, where the ioctl might have different + * effects. Notably, DRM is using the same ioctl() number. */ + + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) + return -ENOTTY; + + if (mask == 0 && !previous) + return 0; + + if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0) + return -errno; + + new_attr = (old_attr & ~mask) | (value & mask); + if (new_attr == old_attr) { + if (previous) + *previous = old_attr; + return 0; + } + + if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0) + return -errno; + + if (previous) + *previous = old_attr; + + return 1; +} + +int chattr_path(const char *p, unsigned value, unsigned mask, unsigned *previous) { + _cleanup_close_ int fd = -1; + + assert(p); + + if (mask == 0) + return 0; + + fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return chattr_fd(fd, value, mask, previous); +} + +int read_attr_fd(int fd, unsigned *ret) { + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) + return -ENOTTY; + + if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0) + return -errno; + + return 0; +} + +int read_attr_path(const char *p, unsigned *ret) { + _cleanup_close_ int fd = -1; + + assert(p); + assert(ret); + + fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return read_attr_fd(fd, ret); +} diff --git a/src/basic/chattr-util.h b/src/basic/chattr-util.h new file mode 100644 index 00000000..29070c84 --- /dev/null +++ b/src/basic/chattr-util.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "missing_fs.h" + +/* The chattr() flags to apply when creating a new file *before* writing to it. In particular, flags such as + * FS_NOCOW_FL don't work if applied a-posteriori. All other flags are fine (or even necessary, think + * FS_IMMUTABLE_FL!) to apply after writing to the files. */ +#define CHATTR_EARLY_FL \ + (FS_NOATIME_FL | \ + FS_COMPR_FL | \ + FS_NOCOW_FL | \ + FS_NOCOMP_FL | \ + FS_PROJINHERIT_FL) + +#define CHATTR_ALL_FL \ + (FS_NOATIME_FL | \ + FS_SYNC_FL | \ + FS_DIRSYNC_FL | \ + FS_APPEND_FL | \ + FS_COMPR_FL | \ + FS_NODUMP_FL | \ + FS_EXTENT_FL | \ + FS_IMMUTABLE_FL | \ + FS_JOURNAL_DATA_FL | \ + FS_SECRM_FL | \ + FS_UNRM_FL | \ + FS_NOTAIL_FL | \ + FS_TOPDIR_FL | \ + FS_NOCOW_FL | \ + FS_PROJINHERIT_FL) + +int chattr_fd(int fd, unsigned value, unsigned mask, unsigned *previous); +int chattr_path(const char *p, unsigned value, unsigned mask, unsigned *previous); + +int read_attr_fd(int fd, unsigned *ret); +int read_attr_path(const char *p, unsigned *ret); diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c new file mode 100644 index 00000000..58eb62fb --- /dev/null +++ b/src/basic/conf-files.c @@ -0,0 +1,318 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "conf-files.h" +#include "def.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "hashmap.h" +#include "log.h" +#include "macro.h" +#include "path-util.h" +#include "set.h" +#include "sort-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" + +static int files_add( + Hashmap *h, + Set *masked, + const char *suffix, + const char *root, + unsigned flags, + const char *path) { + + _cleanup_closedir_ DIR *dir = NULL; + const char *dirpath; + struct dirent *de; + int r; + + assert(h); + assert((flags & CONF_FILES_FILTER_MASKED) == 0 || masked); + assert(path); + + dirpath = prefix_roota(root, path); + + dir = opendir(dirpath); + if (!dir) { + if (errno == ENOENT) + return 0; + + return log_debug_errno(errno, "Failed to open directory '%s': %m", dirpath); + } + + FOREACH_DIRENT(de, dir, return -errno) { + struct stat st; + char *p, *key; + + /* Does this match the suffix? */ + if (suffix && !endswith(de->d_name, suffix)) + continue; + + /* Has this file already been found in an earlier directory? */ + if (hashmap_contains(h, de->d_name)) { + log_debug("Skipping overridden file '%s/%s'.", dirpath, de->d_name); + continue; + } + + /* Has this been masked in an earlier directory? */ + if ((flags & CONF_FILES_FILTER_MASKED) && set_contains(masked, de->d_name)) { + log_debug("File '%s/%s' is masked by previous entry.", dirpath, de->d_name); + continue; + } + + /* Read file metadata if we shall validate the check for file masks, for node types or whether the node is marked executable. */ + if (flags & (CONF_FILES_FILTER_MASKED|CONF_FILES_REGULAR|CONF_FILES_DIRECTORY|CONF_FILES_EXECUTABLE)) + if (fstatat(dirfd(dir), de->d_name, &st, 0) < 0) { + log_debug_errno(errno, "Failed to stat '%s/%s', ignoring: %m", dirpath, de->d_name); + continue; + } + + /* Is this a masking entry? */ + if ((flags & CONF_FILES_FILTER_MASKED)) + if (null_or_empty(&st)) { + /* Mark this one as masked */ + r = set_put_strdup(masked, de->d_name); + if (r < 0) + return r; + + log_debug("File '%s/%s' is a mask.", dirpath, de->d_name); + continue; + } + + /* Does this node have the right type? */ + if (flags & (CONF_FILES_REGULAR|CONF_FILES_DIRECTORY)) + if (!((flags & CONF_FILES_DIRECTORY) && S_ISDIR(st.st_mode)) && + !((flags & CONF_FILES_REGULAR) && S_ISREG(st.st_mode))) { + log_debug("Ignoring '%s/%s', as it is not a of the right type.", dirpath, de->d_name); + continue; + } + + /* Does this node have the executable bit set? */ + if (flags & CONF_FILES_EXECUTABLE) + /* As requested: check if the file is marked executable. Note that we don't check access(X_OK) + * here, as we care about whether the file is marked executable at all, and not whether it is + * executable for us, because if so, such errors are stuff we should log about. */ + + if ((st.st_mode & 0111) == 0) { /* not executable */ + log_debug("Ignoring '%s/%s', as it is not marked executable.", dirpath, de->d_name); + continue; + } + + if (flags & CONF_FILES_BASENAME) { + p = strdup(de->d_name); + if (!p) + return -ENOMEM; + + key = p; + } else { + p = path_join(dirpath, de->d_name); + if (!p) + return -ENOMEM; + + key = basename(p); + } + + r = hashmap_put(h, key, p); + if (r < 0) { + free(p); + return log_debug_errno(r, "Failed to add item to hashmap: %m"); + } + + assert(r > 0); + } + + return 0; +} + +static int base_cmp(char * const *a, char * const *b) { + return strcmp(basename(*a), basename(*b)); +} + +static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, unsigned flags, char **dirs) { + _cleanup_hashmap_free_ Hashmap *fh = NULL; + _cleanup_set_free_free_ Set *masked = NULL; + char **files, **p; + int r; + + assert(strv); + + /* This alters the dirs string array */ + if (!path_strv_resolve_uniq(dirs, root)) + return -ENOMEM; + + fh = hashmap_new(&path_hash_ops); + if (!fh) + return -ENOMEM; + + if (flags & CONF_FILES_FILTER_MASKED) { + masked = set_new(&path_hash_ops); + if (!masked) + return -ENOMEM; + } + + STRV_FOREACH(p, dirs) { + r = files_add(fh, masked, suffix, root, flags, *p); + if (r == -ENOMEM) + return r; + if (r < 0) + log_debug_errno(r, "Failed to search for files in %s, ignoring: %m", *p); + } + + files = hashmap_get_strv(fh); + if (!files) + return -ENOMEM; + + typesafe_qsort(files, hashmap_size(fh), base_cmp); + *strv = files; + + return 0; +} + +int conf_files_insert(char ***strv, const char *root, char **dirs, const char *path) { + /* Insert a path into strv, at the place honouring the usual sorting rules: + * - we first compare by the basename + * - and then we compare by dirname, allowing just one file with the given + * basename. + * This means that we will + * - add a new entry if basename(path) was not on the list, + * - do nothing if an entry with higher priority was already present, + * - do nothing if our new entry matches the existing entry, + * - replace the existing entry if our new entry has higher priority. + */ + size_t i, n; + char *t; + int r; + + n = strv_length(*strv); + for (i = 0; i < n; i++) { + int c; + + c = base_cmp((char* const*) *strv + i, (char* const*) &path); + if (c == 0) { + char **dir; + + /* Oh, there already is an entry with a matching name (the last component). */ + + STRV_FOREACH(dir, dirs) { + _cleanup_free_ char *rdir = NULL; + char *p1, *p2; + + rdir = path_join(root, *dir); + if (!rdir) + return -ENOMEM; + + p1 = path_startswith((*strv)[i], rdir); + if (p1) + /* Existing entry with higher priority + * or same priority, no need to do anything. */ + return 0; + + p2 = path_startswith(path, *dir); + if (p2) { + /* Our new entry has higher priority */ + + t = path_join(root, path); + if (!t) + return log_oom(); + + return free_and_replace((*strv)[i], t); + } + } + + } else if (c > 0) + /* Following files have lower priority, let's go insert our + * new entry. */ + break; + + /* … we are not there yet, let's continue */ + } + + /* The new file has lower priority than all the existing entries */ + t = path_join(root, path); + if (!t) + return -ENOMEM; + + r = strv_insert(strv, i, t); + if (r < 0) + free(t); + + return r; +} + +int conf_files_list_strv(char ***strv, const char *suffix, const char *root, unsigned flags, const char* const* dirs) { + _cleanup_strv_free_ char **copy = NULL; + + assert(strv); + + copy = strv_copy((char**) dirs); + if (!copy) + return -ENOMEM; + + return conf_files_list_strv_internal(strv, suffix, root, flags, copy); +} + +int conf_files_list(char ***strv, const char *suffix, const char *root, unsigned flags, const char *dir) { + _cleanup_strv_free_ char **dirs = NULL; + + assert(strv); + + dirs = strv_new(dir); + if (!dirs) + return -ENOMEM; + + return conf_files_list_strv_internal(strv, suffix, root, flags, dirs); +} + +int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, unsigned flags, const char *dirs) { + _cleanup_strv_free_ char **d = NULL; + + assert(strv); + + d = strv_split_nulstr(dirs); + if (!d) + return -ENOMEM; + + return conf_files_list_strv_internal(strv, suffix, root, flags, d); +} + +int conf_files_list_with_replacement( + const char *root, + char **config_dirs, + const char *replacement, + char ***files, + char **replace_file) { + + _cleanup_strv_free_ char **f = NULL; + _cleanup_free_ char *p = NULL; + int r; + + assert(config_dirs); + assert(files); + assert(replace_file || !replacement); + + r = conf_files_list_strv(&f, ".conf", root, 0, (const char* const*) config_dirs); + if (r < 0) + return log_error_errno(r, "Failed to enumerate config files: %m"); + + if (replacement) { + r = conf_files_insert(&f, root, config_dirs, replacement); + if (r < 0) + return log_error_errno(r, "Failed to extend config file list: %m"); + + p = path_join(root, replacement); + if (!p) + return log_oom(); + } + + *files = TAKE_PTR(f); + if (replace_file) + *replace_file = TAKE_PTR(p); + return 0; +} diff --git a/src/basic/conf-files.h b/src/basic/conf-files.h new file mode 100644 index 00000000..7d7be5c9 --- /dev/null +++ b/src/basic/conf-files.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "macro.h" + +enum { + CONF_FILES_EXECUTABLE = 1 << 0, + CONF_FILES_REGULAR = 1 << 1, + CONF_FILES_DIRECTORY = 1 << 2, + CONF_FILES_BASENAME = 1 << 3, + CONF_FILES_FILTER_MASKED = 1 << 4, +}; + +int conf_files_list(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dir); +int conf_files_list_strv(char ***ret, const char *suffix, const char *root, unsigned flags, const char* const* dirs); +int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dirs); +int conf_files_insert(char ***strv, const char *root, char **dirs, const char *path); +int conf_files_list_with_replacement( + const char *root, + char **config_dirs, + const char *replacement, + char ***files, + char **replace_file); diff --git a/src/basic/copy.c b/src/basic/copy.c new file mode 100644 index 00000000..9028868f --- /dev/null +++ b/src/basic/copy.c @@ -0,0 +1,942 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "chattr-util.h" +#include "copy.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "io-util.h" +#include "macro.h" +#include "missing_syscall.h" +#include "mountpoint-util.h" +#include "nulstr-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "tmpfile-util.h" +#include "umask-util.h" +#include "user-util.h" +#include "xattr-util.h" + +#define COPY_BUFFER_SIZE (16U*1024U) + +/* A safety net for descending recursively into file system trees to copy. On Linux PATH_MAX is 4096, which means the + * deepest valid path one can build is around 2048, which we hence use as a safety net here, to not spin endlessly in + * case of bind mount cycles and suchlike. */ +#define COPY_DEPTH_MAX 2048U + +static ssize_t try_copy_file_range( + int fd_in, loff_t *off_in, + int fd_out, loff_t *off_out, + size_t len, + unsigned flags) { + + static int have = -1; + ssize_t r; + + if (have == 0) + return -ENOSYS; + + r = copy_file_range(fd_in, off_in, fd_out, off_out, len, flags); + if (have < 0) + have = r >= 0 || errno != ENOSYS; + if (r < 0) + return -errno; + + return r; +} + +enum { + FD_IS_NO_PIPE, + FD_IS_BLOCKING_PIPE, + FD_IS_NONBLOCKING_PIPE, +}; + +static int fd_is_nonblock_pipe(int fd) { + struct stat st; + int flags; + + /* Checks whether the specified file descriptor refers to a pipe, and if so if O_NONBLOCK is set. */ + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISFIFO(st.st_mode)) + return FD_IS_NO_PIPE; + + flags = fcntl(fd, F_GETFL); + if (flags < 0) + return -errno; + + return FLAGS_SET(flags, O_NONBLOCK) ? FD_IS_NONBLOCKING_PIPE : FD_IS_BLOCKING_PIPE; +} + +static int sigint_pending(void) { + sigset_t ss; + + assert_se(sigemptyset(&ss) >= 0); + assert_se(sigaddset(&ss, SIGINT) >= 0); + + if (sigtimedwait(&ss, NULL, &(struct timespec) { 0, 0 }) < 0) { + if (errno == EAGAIN) + return false; + + return -errno; + } + + return true; +} + +int copy_bytes_full( + int fdf, int fdt, + uint64_t max_bytes, + CopyFlags copy_flags, + void **ret_remains, + size_t *ret_remains_size, + copy_progress_bytes_t progress, + void *userdata) { + + bool try_cfr = true, try_sendfile = true, try_splice = true; + int r, nonblock_pipe = -1; + size_t m = SSIZE_MAX; /* that is the maximum that sendfile and c_f_r accept */ + + assert(fdf >= 0); + assert(fdt >= 0); + + /* Tries to copy bytes from the file descriptor 'fdf' to 'fdt' in the smartest possible way. Copies a maximum + * of 'max_bytes', which may be specified as UINT64_MAX, in which no maximum is applied. Returns negative on + * error, zero if EOF is hit before the bytes limit is hit and positive otherwise. If the copy fails for some + * reason but we read but didn't yet write some data an ret_remains/ret_remains_size is not NULL, then it will + * be initialized with an allocated buffer containing this "remaining" data. Note that these two parameters are + * initialized with a valid buffer only on failure and only if there's actually data already read. Otherwise + * these parameters if non-NULL are set to NULL. */ + + if (ret_remains) + *ret_remains = NULL; + if (ret_remains_size) + *ret_remains_size = 0; + + /* Try btrfs reflinks first. This only works on regular, seekable files, hence let's check the file offsets of + * source and destination first. */ + if ((copy_flags & COPY_REFLINK)) { + off_t foffset; + + foffset = lseek(fdf, 0, SEEK_CUR); + if (foffset >= 0) { + off_t toffset; + + toffset = lseek(fdt, 0, SEEK_CUR); + if (toffset >= 0) { + + if (foffset == 0 && toffset == 0 && max_bytes == UINT64_MAX) + r = btrfs_reflink(fdf, fdt); /* full file reflink */ + else + r = btrfs_clone_range(fdf, foffset, fdt, toffset, max_bytes == UINT64_MAX ? 0 : max_bytes); /* partial reflink */ + if (r >= 0) { + off_t t; + + /* This worked, yay! Now — to be fully correct — let's adjust the file pointers */ + if (max_bytes == UINT64_MAX) { + + /* We cloned to the end of the source file, let's position the read + * pointer there, and query it at the same time. */ + t = lseek(fdf, 0, SEEK_END); + if (t < 0) + return -errno; + if (t < foffset) + return -ESPIPE; + + /* Let's adjust the destination file write pointer by the same number + * of bytes. */ + t = lseek(fdt, toffset + (t - foffset), SEEK_SET); + if (t < 0) + return -errno; + + return 0; /* we copied the whole thing, hence hit EOF, return 0 */ + } else { + t = lseek(fdf, foffset + max_bytes, SEEK_SET); + if (t < 0) + return -errno; + + t = lseek(fdt, toffset + max_bytes, SEEK_SET); + if (t < 0) + return -errno; + + return 1; /* we copied only some number of bytes, which worked, but this means we didn't hit EOF, return 1 */ + } + } + } + } + } + + for (;;) { + ssize_t n; + + if (max_bytes <= 0) + return 1; /* return > 0 if we hit the max_bytes limit */ + + if (FLAGS_SET(copy_flags, COPY_SIGINT)) { + r = sigint_pending(); + if (r < 0) + return r; + if (r > 0) + return -EINTR; + } + + if (max_bytes != UINT64_MAX && m > max_bytes) + m = max_bytes; + + /* First try copy_file_range(), unless we already tried */ + if (try_cfr) { + n = try_copy_file_range(fdf, NULL, fdt, NULL, m, 0u); + if (n < 0) { + if (!IN_SET(n, -EINVAL, -ENOSYS, -EXDEV, -EBADF)) + return n; + + try_cfr = false; + /* use fallback below */ + } else if (n == 0) /* EOF */ + break; + else + /* Success! */ + goto next; + } + + /* First try sendfile(), unless we already tried */ + if (try_sendfile) { + n = sendfile(fdt, fdf, NULL, m); + if (n < 0) { + if (!IN_SET(errno, EINVAL, ENOSYS)) + return -errno; + + try_sendfile = false; + /* use fallback below */ + } else if (n == 0) /* EOF */ + break; + else + /* Success! */ + goto next; + } + + /* Then try splice, unless we already tried. */ + if (try_splice) { + + /* splice()'s asynchronous I/O support is a bit weird. When it encounters a pipe file + * descriptor, then it will ignore its O_NONBLOCK flag and instead only honour the + * SPLICE_F_NONBLOCK flag specified in its flag parameter. Let's hide this behaviour here, and + * check if either of the specified fds are a pipe, and if so, let's pass the flag + * automatically, depending on O_NONBLOCK being set. + * + * Here's a twist though: when we use it to move data between two pipes of which one has + * O_NONBLOCK set and the other has not, then we have no individual control over O_NONBLOCK + * behaviour. Hence in that case we can't use splice() and still guarantee systematic + * O_NONBLOCK behaviour, hence don't. */ + + if (nonblock_pipe < 0) { + int a, b; + + /* Check if either of these fds is a pipe, and if so non-blocking or not */ + a = fd_is_nonblock_pipe(fdf); + if (a < 0) + return a; + + b = fd_is_nonblock_pipe(fdt); + if (b < 0) + return b; + + if ((a == FD_IS_NO_PIPE && b == FD_IS_NO_PIPE) || + (a == FD_IS_BLOCKING_PIPE && b == FD_IS_NONBLOCKING_PIPE) || + (a == FD_IS_NONBLOCKING_PIPE && b == FD_IS_BLOCKING_PIPE)) + + /* splice() only works if one of the fds is a pipe. If neither is, let's skip + * this step right-away. As mentioned above, if one of the two fds refers to a + * blocking pipe and the other to a non-blocking pipe, we can't use splice() + * either, hence don't try either. This hence means we can only use splice() if + * either only one of the two fds is a pipe, or if both are pipes with the same + * nonblocking flag setting. */ + + try_splice = false; + else + nonblock_pipe = a == FD_IS_NONBLOCKING_PIPE || b == FD_IS_NONBLOCKING_PIPE; + } + } + + if (try_splice) { + n = splice(fdf, NULL, fdt, NULL, m, nonblock_pipe ? SPLICE_F_NONBLOCK : 0); + if (n < 0) { + if (!IN_SET(errno, EINVAL, ENOSYS)) + return -errno; + + try_splice = false; + /* use fallback below */ + } else if (n == 0) /* EOF */ + break; + else + /* Success! */ + goto next; + } + + /* As a fallback just copy bits by hand */ + { + uint8_t buf[MIN(m, COPY_BUFFER_SIZE)], *p = buf; + ssize_t z; + + n = read(fdf, buf, sizeof buf); + if (n < 0) + return -errno; + if (n == 0) /* EOF */ + break; + + z = (size_t) n; + do { + ssize_t k; + + k = write(fdt, p, z); + if (k < 0) { + r = -errno; + + if (ret_remains) { + void *copy; + + copy = memdup(p, z); + if (!copy) + return -ENOMEM; + + *ret_remains = copy; + } + + if (ret_remains_size) + *ret_remains_size = z; + + return r; + } + + assert(k <= z); + z -= k; + p += k; + } while (z > 0); + } + + next: + if (progress) { + r = progress(n, userdata); + if (r < 0) + return r; + } + + if (max_bytes != (uint64_t) -1) { + assert(max_bytes >= (uint64_t) n); + max_bytes -= n; + } + + /* sendfile accepts at most SSIZE_MAX-offset bytes to copy, + * so reduce our maximum by the amount we already copied, + * but don't go below our copy buffer size, unless we are + * close the limit of bytes we are allowed to copy. */ + m = MAX(MIN(COPY_BUFFER_SIZE, max_bytes), m - n); + } + + return 0; /* return 0 if we hit EOF earlier than the size limit */ +} + +static int fd_copy_symlink( + int df, + const char *from, + const struct stat *st, + int dt, + const char *to, + uid_t override_uid, + gid_t override_gid, + CopyFlags copy_flags) { + + _cleanup_free_ char *target = NULL; + int r; + + assert(from); + assert(st); + assert(to); + + r = readlinkat_malloc(df, from, &target); + if (r < 0) + return r; + + if (symlinkat(target, dt, to) < 0) + return -errno; + + if (fchownat(dt, to, + uid_is_valid(override_uid) ? override_uid : st->st_uid, + gid_is_valid(override_gid) ? override_gid : st->st_gid, + AT_SYMLINK_NOFOLLOW) < 0) + return -errno; + + return 0; +} + +static int fd_copy_regular( + int df, + const char *from, + const struct stat *st, + int dt, + const char *to, + uid_t override_uid, + gid_t override_gid, + CopyFlags copy_flags, + copy_progress_bytes_t progress, + void *userdata) { + + _cleanup_close_ int fdf = -1, fdt = -1; + struct timespec ts[2]; + int r, q; + + assert(from); + assert(st); + assert(to); + + fdf = openat(df, from, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fdf < 0) + return -errno; + + fdt = openat(dt, to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, st->st_mode & 07777); + if (fdt < 0) + return -errno; + + r = copy_bytes_full(fdf, fdt, (uint64_t) -1, copy_flags, NULL, NULL, progress, userdata); + if (r < 0) { + (void) unlinkat(dt, to, 0); + return r; + } + + if (fchown(fdt, + uid_is_valid(override_uid) ? override_uid : st->st_uid, + gid_is_valid(override_gid) ? override_gid : st->st_gid) < 0) + r = -errno; + + if (fchmod(fdt, st->st_mode & 07777) < 0) + r = -errno; + + ts[0] = st->st_atim; + ts[1] = st->st_mtim; + (void) futimens(fdt, ts); + (void) copy_xattr(fdf, fdt); + + q = close(fdt); + fdt = -1; + + if (q < 0) { + r = -errno; + (void) unlinkat(dt, to, 0); + } + + return r; +} + +static int fd_copy_fifo( + int df, + const char *from, + const struct stat *st, + int dt, + const char *to, + uid_t override_uid, + gid_t override_gid, + CopyFlags copy_flags) { + int r; + + assert(from); + assert(st); + assert(to); + + r = mkfifoat(dt, to, st->st_mode & 07777); + if (r < 0) + return -errno; + + if (fchownat(dt, to, + uid_is_valid(override_uid) ? override_uid : st->st_uid, + gid_is_valid(override_gid) ? override_gid : st->st_gid, + AT_SYMLINK_NOFOLLOW) < 0) + r = -errno; + + if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0) + r = -errno; + + return r; +} + +static int fd_copy_node( + int df, + const char *from, + const struct stat *st, + int dt, + const char *to, + uid_t override_uid, + gid_t override_gid, + CopyFlags copy_flags) { + int r; + + assert(from); + assert(st); + assert(to); + + r = mknodat(dt, to, st->st_mode, st->st_rdev); + if (r < 0) + return -errno; + + if (fchownat(dt, to, + uid_is_valid(override_uid) ? override_uid : st->st_uid, + gid_is_valid(override_gid) ? override_gid : st->st_gid, + AT_SYMLINK_NOFOLLOW) < 0) + r = -errno; + + if (fchmodat(dt, to, st->st_mode & 07777, 0) < 0) + r = -errno; + + return r; +} + +static int fd_copy_directory( + int df, + const char *from, + const struct stat *st, + int dt, + const char *to, + dev_t original_device, + unsigned depth_left, + uid_t override_uid, + gid_t override_gid, + CopyFlags copy_flags, + const char *display_path, + copy_progress_path_t progress_path, + copy_progress_bytes_t progress_bytes, + void *userdata) { + + _cleanup_close_ int fdf = -1, fdt = -1; + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + bool exists, created; + int r; + + assert(st); + assert(to); + + if (depth_left == 0) + return -ENAMETOOLONG; + + if (from) + fdf = openat(df, from, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + else + fdf = fcntl(df, F_DUPFD_CLOEXEC, 3); + if (fdf < 0) + return -errno; + + d = fdopendir(fdf); + if (!d) + return -errno; + fdf = -1; + + exists = false; + if (copy_flags & COPY_MERGE_EMPTY) { + r = dir_is_empty_at(dt, to); + if (r < 0 && r != -ENOENT) + return r; + else if (r == 1) + exists = true; + } + + if (exists) + created = false; + else { + r = mkdirat(dt, to, st->st_mode & 07777); + if (r >= 0) + created = true; + else if (errno == EEXIST && (copy_flags & COPY_MERGE)) + created = false; + else + return -errno; + } + + fdt = openat(dt, to, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fdt < 0) + return -errno; + + r = 0; + + FOREACH_DIRENT_ALL(de, d, return -errno) { + const char *child_display_path = NULL; + _cleanup_free_ char *dp = NULL; + struct stat buf; + int q; + + if (dot_or_dot_dot(de->d_name)) + continue; + + if (FLAGS_SET(copy_flags, COPY_SIGINT)) { + r = sigint_pending(); + if (r < 0) + return r; + if (r > 0) + return -EINTR; + } + + if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) { + r = -errno; + continue; + } + + if (progress_path) { + if (display_path) + child_display_path = dp = path_join(display_path, de->d_name); + else + child_display_path = de->d_name; + + r = progress_path(child_display_path, &buf, userdata); + if (r < 0) + return r; + } + + if (S_ISDIR(buf.st_mode)) { + /* + * Don't descend into directories on other file systems, if this is requested. We do a simple + * .st_dev check here, which basically comes for free. Note that we do this check only on + * directories, not other kind of file system objects, for two reason: + * + * • The kernel's overlayfs pseudo file system that overlays multiple real file systems + * propagates the .st_dev field of the file system a file originates from all the way up + * through the stack to stat(). It doesn't do that for directories however. This means that + * comparing .st_dev on non-directories suggests that they all are mount points. To avoid + * confusion we hence avoid relying on this check for regular files. + * + * • The main reason we do this check at all is to protect ourselves from bind mount cycles, + * where we really want to avoid descending down in all eternity. However the .st_dev check + * is usually not sufficient for this protection anyway, as bind mount cycles from the same + * file system onto itself can't be detected that way. (Note we also do a recursion depth + * check, which is probably the better protection in this regard, which is why + * COPY_SAME_MOUNT is optional). + */ + + if (FLAGS_SET(copy_flags, COPY_SAME_MOUNT)) { + if (buf.st_dev != original_device) + continue; + + r = fd_is_mount_point(dirfd(d), de->d_name, 0); + if (r < 0) + return r; + if (r > 0) + continue; + } + + q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, depth_left-1, override_uid, override_gid, copy_flags, child_display_path, progress_path, progress_bytes, userdata); + } else if (S_ISREG(buf.st_mode)) + q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags, progress_bytes, userdata); + else if (S_ISLNK(buf.st_mode)) + q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags); + else if (S_ISFIFO(buf.st_mode)) + q = fd_copy_fifo(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags); + else if (S_ISBLK(buf.st_mode) || S_ISCHR(buf.st_mode) || S_ISSOCK(buf.st_mode)) + q = fd_copy_node(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags); + else + q = -EOPNOTSUPP; + + if (q == -EINTR) /* Propagate SIGINT up instantly */ + return q; + if (q == -EEXIST && (copy_flags & COPY_MERGE)) + q = 0; + if (q < 0) + r = q; + } + + if (created) { + struct timespec ut[2] = { + st->st_atim, + st->st_mtim + }; + + if (fchown(fdt, + uid_is_valid(override_uid) ? override_uid : st->st_uid, + gid_is_valid(override_gid) ? override_gid : st->st_gid) < 0) + r = -errno; + + if (fchmod(fdt, st->st_mode & 07777) < 0) + r = -errno; + + (void) copy_xattr(dirfd(d), fdt); + (void) futimens(fdt, ut); + } + + return r; +} + +int copy_tree_at_full( + int fdf, + const char *from, + int fdt, + const char *to, + uid_t override_uid, + gid_t override_gid, + CopyFlags copy_flags, + copy_progress_path_t progress_path, + copy_progress_bytes_t progress_bytes, + void *userdata) { + + struct stat st; + + assert(from); + assert(to); + + if (fstatat(fdf, from, &st, AT_SYMLINK_NOFOLLOW) < 0) + return -errno; + + if (S_ISREG(st.st_mode)) + return fd_copy_regular(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags, progress_bytes, userdata); + else if (S_ISDIR(st.st_mode)) + return fd_copy_directory(fdf, from, &st, fdt, to, st.st_dev, COPY_DEPTH_MAX, override_uid, override_gid, copy_flags, NULL, progress_path, progress_bytes, userdata); + else if (S_ISLNK(st.st_mode)) + return fd_copy_symlink(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags); + else if (S_ISFIFO(st.st_mode)) + return fd_copy_fifo(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags); + else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode) || S_ISSOCK(st.st_mode)) + return fd_copy_node(fdf, from, &st, fdt, to, override_uid, override_gid, copy_flags); + else + return -EOPNOTSUPP; +} + +int copy_directory_fd_full( + int dirfd, + const char *to, + CopyFlags copy_flags, + copy_progress_path_t progress_path, + copy_progress_bytes_t progress_bytes, + void *userdata) { + + struct stat st; + + assert(dirfd >= 0); + assert(to); + + if (fstat(dirfd, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode)) + return -ENOTDIR; + + return fd_copy_directory(dirfd, NULL, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags, NULL, progress_path, progress_bytes, userdata); +} + +int copy_directory_full( + const char *from, + const char *to, + CopyFlags copy_flags, + copy_progress_path_t progress_path, + copy_progress_bytes_t progress_bytes, + void *userdata) { + + struct stat st; + + assert(from); + assert(to); + + if (lstat(from, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode)) + return -ENOTDIR; + + return fd_copy_directory(AT_FDCWD, from, &st, AT_FDCWD, to, st.st_dev, COPY_DEPTH_MAX, UID_INVALID, GID_INVALID, copy_flags, NULL, progress_path, progress_bytes, userdata); +} + +int copy_file_fd_full( + const char *from, + int fdt, + CopyFlags copy_flags, + copy_progress_bytes_t progress_bytes, + void *userdata) { + + _cleanup_close_ int fdf = -1; + int r; + + assert(from); + assert(fdt >= 0); + + fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fdf < 0) + return -errno; + + r = copy_bytes_full(fdf, fdt, (uint64_t) -1, copy_flags, NULL, NULL, progress_bytes, userdata); + + (void) copy_times(fdf, fdt, copy_flags); + (void) copy_xattr(fdf, fdt); + + return r; +} + +int copy_file_full( + const char *from, + const char *to, + int flags, + mode_t mode, + unsigned chattr_flags, + unsigned chattr_mask, + CopyFlags copy_flags, + copy_progress_bytes_t progress_bytes, + void *userdata) { + + int fdt = -1, r; + + assert(from); + assert(to); + + RUN_WITH_UMASK(0000) { + fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode); + if (fdt < 0) + return -errno; + } + + if (chattr_mask != 0) + (void) chattr_fd(fdt, chattr_flags, chattr_mask & CHATTR_EARLY_FL, NULL); + + r = copy_file_fd_full(from, fdt, copy_flags, progress_bytes, userdata); + if (r < 0) { + close(fdt); + (void) unlink(to); + return r; + } + + if (chattr_mask != 0) + (void) chattr_fd(fdt, chattr_flags, chattr_mask & ~CHATTR_EARLY_FL, NULL); + + if (close(fdt) < 0) { + unlink_noerrno(to); + return -errno; + } + + return 0; +} + +int copy_file_atomic_full( + const char *from, + const char *to, + mode_t mode, + unsigned chattr_flags, + unsigned chattr_mask, + CopyFlags copy_flags, + copy_progress_bytes_t progress_bytes, + void *userdata) { + + _cleanup_(unlink_and_freep) char *t = NULL; + _cleanup_close_ int fdt = -1; + int r; + + assert(from); + assert(to); + + /* We try to use O_TMPFILE here to create the file if we can. Note that that only works if COPY_REPLACE is not + * set though as we need to use linkat() for linking the O_TMPFILE file into the file system but that system + * call can't replace existing files. Hence, if COPY_REPLACE is set we create a temporary name in the file + * system right-away and unconditionally which we then can renameat() to the right name after we completed + * writing it. */ + + if (copy_flags & COPY_REPLACE) { + r = tempfn_random(to, NULL, &t); + if (r < 0) + return r; + + fdt = open(t, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|O_WRONLY|O_CLOEXEC, 0600); + if (fdt < 0) { + t = mfree(t); + return -errno; + } + } else { + fdt = open_tmpfile_linkable(to, O_WRONLY|O_CLOEXEC, &t); + if (fdt < 0) + return fdt; + } + + if (chattr_mask != 0) + (void) chattr_fd(fdt, chattr_flags, chattr_mask & CHATTR_EARLY_FL, NULL); + + r = copy_file_fd_full(from, fdt, copy_flags, progress_bytes, userdata); + if (r < 0) + return r; + + if (fchmod(fdt, mode) < 0) + return -errno; + + if (copy_flags & COPY_REPLACE) { + if (renameat(AT_FDCWD, t, AT_FDCWD, to) < 0) + return -errno; + } else { + r = link_tmpfile(fdt, t, to); + if (r < 0) + return r; + } + + if (chattr_mask != 0) + (void) chattr_fd(fdt, chattr_flags, chattr_mask & ~CHATTR_EARLY_FL, NULL); + + t = mfree(t); + return 0; +} + +int copy_times(int fdf, int fdt, CopyFlags flags) { + struct timespec ut[2]; + struct stat st; + + assert(fdf >= 0); + assert(fdt >= 0); + + if (fstat(fdf, &st) < 0) + return -errno; + + ut[0] = st.st_atim; + ut[1] = st.st_mtim; + + if (futimens(fdt, ut) < 0) + return -errno; + + if (FLAGS_SET(flags, COPY_CRTIME)) { + usec_t crtime; + + if (fd_getcrtime(fdf, &crtime) >= 0) + (void) fd_setcrtime(fdt, crtime); + } + + return 0; +} + +int copy_xattr(int fdf, int fdt) { + _cleanup_free_ char *names = NULL; + int ret = 0, r; + const char *p; + + r = flistxattr_malloc(fdf, &names); + if (r < 0) + return r; + + NULSTR_FOREACH(p, names) { + _cleanup_free_ char *value = NULL; + + if (!startswith(p, "user.")) + continue; + + r = fgetxattr_malloc(fdf, p, &value); + if (r == -ENODATA) + continue; /* gone by now */ + if (r < 0) + return r; + + if (fsetxattr(fdt, p, value, r, 0) < 0) + ret = -errno; + } + + return ret; +} diff --git a/src/basic/copy.h b/src/basic/copy.h new file mode 100644 index 00000000..906c6f70 --- /dev/null +++ b/src/basic/copy.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include +#include + +typedef enum CopyFlags { + COPY_REFLINK = 1 << 0, /* Try to reflink */ + COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */ + COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */ + COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */ + COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */ + COPY_CRTIME = 1 << 5, /* Generate a user.crtime_usec xattr off the source crtime if there is one, on copying */ + COPY_SIGINT = 1 << 6, /* Check for SIGINT regularly and return EINTR if seen (caller needs to block SIGINT) */ +} CopyFlags; + +typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, void *userdata); +typedef int (*copy_progress_path_t)(const char *path, const struct stat *st, void *userdata); + +int copy_file_fd_full(const char *from, int to, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata); +static inline int copy_file_fd(const char *from, int to, CopyFlags copy_flags) { + return copy_file_fd_full(from, to, copy_flags, NULL, NULL); +} + +int copy_file_full(const char *from, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata); +static inline int copy_file(const char *from, const char *to, int open_flags, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags) { + return copy_file_full(from, to, open_flags, mode, chattr_flags, chattr_mask, copy_flags, NULL, NULL); +} + +int copy_file_atomic_full(const char *from, const char *to, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags, copy_progress_bytes_t progress, void *userdata); +static inline int copy_file_atomic(const char *from, const char *to, mode_t mode, unsigned chattr_flags, unsigned chattr_mask, CopyFlags copy_flags) { + return copy_file_atomic_full(from, to, mode, chattr_flags, chattr_mask, copy_flags, NULL, NULL); +} + +int copy_tree_at_full(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata); +static inline int copy_tree_at(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags) { + return copy_tree_at_full(fdf, from, fdt, to, override_uid, override_gid, copy_flags, NULL, NULL, NULL); +} +static inline int copy_tree(const char *from, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags) { + return copy_tree_at_full(AT_FDCWD, from, AT_FDCWD, to, override_uid, override_gid, copy_flags, NULL, NULL, NULL); +} + +int copy_directory_fd_full(int dirfd, const char *to, CopyFlags copy_flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata); +static inline int copy_directory_fd(int dirfd, const char *to, CopyFlags copy_flags) { + return copy_directory_fd_full(dirfd, to, copy_flags, NULL, NULL, NULL); +} + +int copy_directory_full(const char *from, const char *to, CopyFlags copy_flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata); +static inline int copy_directory(const char *from, const char *to, CopyFlags copy_flags) { + return copy_directory_full(from, to, copy_flags, NULL, NULL, NULL); +} + +int copy_bytes_full(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags, void **ret_remains, size_t *ret_remains_size, copy_progress_bytes_t progress, void *userdata); +static inline int copy_bytes(int fdf, int fdt, uint64_t max_bytes, CopyFlags copy_flags) { + return copy_bytes_full(fdf, fdt, max_bytes, copy_flags, NULL, NULL, NULL, NULL); +} + +int copy_times(int fdf, int fdt, CopyFlags flags); +int copy_xattr(int fdf, int fdt); diff --git a/src/basic/def.h b/src/basic/def.h new file mode 100644 index 00000000..970654a1 --- /dev/null +++ b/src/basic/def.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#define DEFAULT_TIMEOUT_USEC (90*USEC_PER_SEC) +#define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC) +#define DEFAULT_CONFIRM_USEC (30*USEC_PER_SEC) + +#define DEFAULT_START_LIMIT_INTERVAL (10*USEC_PER_SEC) +#define DEFAULT_START_LIMIT_BURST 5 + +/* The default time after which exit-on-idle services exit. This + * should be kept lower than the watchdog timeout, because otherwise + * the watchdog pings will keep the loop busy. */ +#define DEFAULT_EXIT_USEC (30*USEC_PER_SEC) + +/* The default value for the net.unix.max_dgram_qlen sysctl */ +#define DEFAULT_UNIX_MAX_DGRAM_QLEN 512UL + +#define SIGNALS_CRASH_HANDLER SIGSEGV,SIGILL,SIGFPE,SIGBUS,SIGQUIT,SIGABRT +#define SIGNALS_IGNORE SIGPIPE + +#define NOTIFY_FD_MAX 768 +#define NOTIFY_BUFFER_MAX PIPE_BUF + +#if HAVE_SPLIT_USR +# define _CONF_PATHS_SPLIT_USR_NULSTR(n) "/lib/" n "\0" +# define _CONF_PATHS_SPLIT_USR(n) , "/lib/" n +#else +# define _CONF_PATHS_SPLIT_USR_NULSTR(n) +# define _CONF_PATHS_SPLIT_USR(n) +#endif + +/* Return a nulstr for a standard cascade of configuration paths, + * suitable to pass to conf_files_list_nulstr() or config_parse_many_nulstr() + * to implement drop-in directories for extending configuration + * files. */ +#define CONF_PATHS_NULSTR(n) \ + "/etc/" n "\0" \ + "/run/" n "\0" \ + "/usr/local/lib/" n "\0" \ + "/usr/lib/" n "\0" \ + _CONF_PATHS_SPLIT_USR_NULSTR(n) + +#define CONF_PATHS_USR(n) \ + "/etc/" n, \ + "/run/" n, \ + "/usr/local/lib/" n, \ + "/usr/lib/" n + +#define CONF_PATHS(n) \ + CONF_PATHS_USR(n) \ + _CONF_PATHS_SPLIT_USR(n) + +#define CONF_PATHS_USR_STRV(n) \ + STRV_MAKE(CONF_PATHS_USR(n)) + +#define CONF_PATHS_STRV(n) \ + STRV_MAKE(CONF_PATHS(n)) + +#define HIGH_RLIMIT_MEMLOCK (1024ULL*1024ULL*64ULL) + +#define PLYMOUTH_SOCKET { \ + .un.sun_family = AF_UNIX, \ + .un.sun_path = "\0/org/freedesktop/plymouthd", \ + } diff --git a/src/basic/device-nodes.c b/src/basic/device-nodes.c new file mode 100644 index 00000000..5ebe5b24 --- /dev/null +++ b/src/basic/device-nodes.c @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "device-nodes.h" +#include "utf8.h" + +int whitelisted_char_for_devnode(char c, const char *white) { + + if ((c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + strchr("#+-.:=@_", c) != NULL || + (white != NULL && strchr(white, c) != NULL)) + return 1; + + return 0; +} + +int encode_devnode_name(const char *str, char *str_enc, size_t len) { + size_t i, j; + + if (!str || !str_enc) + return -EINVAL; + + for (i = 0, j = 0; str[i] != '\0'; i++) { + int seqlen; + + seqlen = utf8_encoded_valid_unichar(str + i, (size_t) -1); + if (seqlen > 1) { + + if (len-j < (size_t)seqlen) + return -EINVAL; + + memcpy(&str_enc[j], &str[i], seqlen); + j += seqlen; + i += (seqlen-1); + + } else if (str[i] == '\\' || !whitelisted_char_for_devnode(str[i], NULL)) { + + if (len-j < 4) + return -EINVAL; + + sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]); + j += 4; + + } else { + if (len-j < 1) + return -EINVAL; + + str_enc[j] = str[i]; + j++; + } + } + + if (len-j < 1) + return -EINVAL; + + str_enc[j] = '\0'; + return 0; +} diff --git a/src/basic/device-nodes.h b/src/basic/device-nodes.h new file mode 100644 index 00000000..3840e6d3 --- /dev/null +++ b/src/basic/device-nodes.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "macro.h" +#include "stdio-util.h" + +int encode_devnode_name(const char *str, char *str_enc, size_t len); +int whitelisted_char_for_devnode(char c, const char *additional); + +#define DEV_NUM_PATH_MAX \ + (STRLEN("/dev/block/") + DECIMAL_STR_MAX(dev_t) + 1 + DECIMAL_STR_MAX(dev_t)) +#define xsprintf_dev_num_path(buf, type, devno) \ + xsprintf(buf, "/dev/%s/%u:%u", type, major(devno), minor(devno)) diff --git a/src/basic/dirent-util.c b/src/basic/dirent-util.c new file mode 100644 index 00000000..d1d2c0ef --- /dev/null +++ b/src/basic/dirent-util.c @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "dirent-util.h" +#include "path-util.h" +#include "string-util.h" + +int dirent_ensure_type(DIR *d, struct dirent *de) { + struct stat st; + + assert(d); + assert(de); + + if (de->d_type != DT_UNKNOWN) + return 0; + + if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) + return -errno; + + de->d_type = + S_ISREG(st.st_mode) ? DT_REG : + S_ISDIR(st.st_mode) ? DT_DIR : + S_ISLNK(st.st_mode) ? DT_LNK : + S_ISFIFO(st.st_mode) ? DT_FIFO : + S_ISSOCK(st.st_mode) ? DT_SOCK : + S_ISCHR(st.st_mode) ? DT_CHR : + S_ISBLK(st.st_mode) ? DT_BLK : + DT_UNKNOWN; + + return 0; +} + +bool dirent_is_file(const struct dirent *de) { + assert(de); + + if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN)) + return false; + + if (hidden_or_backup_file(de->d_name)) + return false; + + return true; +} + +bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) { + assert(de); + + if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN)) + return false; + + if (de->d_name[0] == '.') + return false; + + if (!suffix) + return true; + + return endswith(de->d_name, suffix); +} + +struct dirent* readdir_no_dot(DIR *dirp) { + struct dirent* d; + + for (;;) { + d = readdir(dirp); + if (d && dot_or_dot_dot(d->d_name)) + continue; + return d; + } +} diff --git a/src/basic/dirent-util.h b/src/basic/dirent-util.h new file mode 100644 index 00000000..b1b87679 --- /dev/null +++ b/src/basic/dirent-util.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "macro.h" +#include "path-util.h" + +int dirent_ensure_type(DIR *d, struct dirent *de); + +bool dirent_is_file(const struct dirent *de) _pure_; +bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_; + +struct dirent* readdir_no_dot(DIR *dirp); + +#define FOREACH_DIRENT(de, d, on_error) \ + for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ + if (!de) { \ + if (errno > 0) { \ + on_error; \ + } \ + break; \ + } else if (hidden_or_backup_file((de)->d_name)) \ + continue; \ + else + +#define FOREACH_DIRENT_ALL(de, d, on_error) \ + for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d)) \ + if (!de) { \ + if (errno > 0) { \ + on_error; \ + } \ + break; \ + } else diff --git a/src/basic/efivars.c b/src/basic/efivars.c new file mode 100644 index 00000000..a1f040c5 --- /dev/null +++ b/src/basic/efivars.c @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "chattr-util.h" +#include "efivars.h" +#include "fd-util.h" +#include "io-util.h" +#include "macro.h" +#include "stdio-util.h" +#include "strv.h" +#include "time-util.h" +#include "utf8.h" +#include "virt.h" + +#if ENABLE_EFI + +char* efi_variable_path(sd_id128_t vendor, const char *name) { + char *p; + + if (asprintf(&p, + "/sys/firmware/efi/efivars/%s-" SD_ID128_UUID_FORMAT_STR, + name, SD_ID128_FORMAT_VAL(vendor)) < 0) + return NULL; + + return p; +} + +int efi_get_variable( + sd_id128_t vendor, + const char *name, + uint32_t *ret_attribute, + void **ret_value, + size_t *ret_size) { + + _cleanup_close_ int fd = -1; + _cleanup_free_ char *p = NULL; + _cleanup_free_ void *buf = NULL; + struct stat st; + uint32_t a; + ssize_t n; + + assert(name); + + p = efi_variable_path(vendor, name); + if (!p) + return -ENOMEM; + + if (!ret_value && !ret_size && !ret_attribute) { + /* If caller is not interested in anything, just check if the variable exists and is readable + * to us. */ + if (access(p, R_OK) < 0) + return -errno; + + return 0; + } + + fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return -errno; + + if (fstat(fd, &st) < 0) + return -errno; + if (st.st_size < 4) + return -ENODATA; + if (st.st_size > 4*1024*1024 + 4) + return -E2BIG; + + if (ret_value || ret_attribute) { + n = read(fd, &a, sizeof(a)); + if (n < 0) + return -errno; + if (n != sizeof(a)) + return -EIO; + } + + if (ret_value) { + buf = malloc(st.st_size - 4 + 2); + if (!buf) + return -ENOMEM; + + n = read(fd, buf, (size_t) st.st_size - 4); + if (n < 0) + return -errno; + if (n != st.st_size - 4) + return -EIO; + + /* Always NUL terminate (2 bytes, to protect UTF-16) */ + ((char*) buf)[st.st_size - 4] = 0; + ((char*) buf)[st.st_size - 4 + 1] = 0; + } + + /* Note that efivarfs interestingly doesn't require ftruncate() to update an existing EFI variable + * with a smaller value. */ + + if (ret_attribute) + *ret_attribute = a; + + if (ret_value) + *ret_value = TAKE_PTR(buf); + + if (ret_size) + *ret_size = (size_t) st.st_size - 4; + + return 0; +} + +int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { + _cleanup_free_ void *s = NULL; + size_t ss = 0; + int r; + char *x; + + r = efi_get_variable(vendor, name, NULL, &s, &ss); + if (r < 0) + return r; + + x = utf16_to_utf8(s, ss); + if (!x) + return -ENOMEM; + + *p = x; + return 0; +} + +int efi_set_variable( + sd_id128_t vendor, + const char *name, + const void *value, + size_t size) { + + struct var { + uint32_t attr; + char buf[]; + } _packed_ * _cleanup_free_ buf = NULL; + _cleanup_free_ char *p = NULL; + _cleanup_close_ int fd = -1; + bool saved_flags_valid = false; + unsigned saved_flags; + int r; + + assert(name); + assert(value || size == 0); + + p = efi_variable_path(vendor, name); + if (!p) + return -ENOMEM; + + /* Newer efivarfs protects variables that are not in a whitelist with FS_IMMUTABLE_FL by default, to protect + * them for accidental removal and modification. We are not changing these variables accidentally however, + * hence let's unset the bit first. */ + + r = chattr_path(p, 0, FS_IMMUTABLE_FL, &saved_flags); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to drop FS_IMMUTABLE_FL flag from '%s', ignoring: %m", p); + + saved_flags_valid = r >= 0; + + if (size == 0) { + if (unlink(p) < 0) { + r = -errno; + goto finish; + } + + return 0; + } + + fd = open(p, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0644); + if (fd < 0) { + r = -errno; + goto finish; + } + + buf = malloc(sizeof(uint32_t) + size); + if (!buf) { + r = -ENOMEM; + goto finish; + } + + buf->attr = EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS; + memcpy(buf->buf, value, size); + + r = loop_write(fd, buf, sizeof(uint32_t) + size, false); + if (r < 0) + goto finish; + + r = 0; + +finish: + if (saved_flags_valid) { + int q; + + /* Restore the original flags field, just in case */ + if (fd < 0) + q = chattr_path(p, saved_flags, FS_IMMUTABLE_FL, NULL); + else + q = chattr_fd(fd, saved_flags, FS_IMMUTABLE_FL, NULL); + if (q < 0) + log_debug_errno(q, "Failed to restore FS_IMMUTABLE_FL on '%s', ignoring: %m", p); + } + + return r; +} + +int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *v) { + _cleanup_free_ char16_t *u16 = NULL; + + u16 = utf8_to_utf16(v, strlen(v)); + if (!u16) + return -ENOMEM; + + return efi_set_variable(vendor, name, u16, (char16_strlen(u16) + 1) * sizeof(char16_t)); +} + +bool is_efi_boot(void) { + if (detect_container() > 0) + return false; + + return access("/sys/firmware/efi/", F_OK) >= 0; +} + +static int read_flag(const char *varname) { + _cleanup_free_ void *v = NULL; + uint8_t b; + size_t s; + int r; + + if (!is_efi_boot()) /* If this is not an EFI boot, assume the queried flags are zero */ + return 0; + + r = efi_get_variable(EFI_VENDOR_GLOBAL, varname, NULL, &v, &s); + if (r < 0) + return r; + + if (s != 1) + return -EINVAL; + + b = *(uint8_t *)v; + return !!b; +} + +bool is_efi_secure_boot(void) { + return read_flag("SecureBoot") > 0; +} + +bool is_efi_secure_boot_setup_mode(void) { + return read_flag("SetupMode") > 0; +} + +int systemd_efi_options_variable(char **line) { + const char *e; + int r; + + assert(line); + + /* For testing purposes it is sometimes useful to be able to override this */ + e = secure_getenv("SYSTEMD_EFI_OPTIONS"); + if (e) { + char *m; + + m = strdup(e); + if (!m) + return -ENOMEM; + + *line = m; + return 0; + } + + r = efi_get_variable_string(EFI_VENDOR_SYSTEMD, "SystemdOptions", line); + if (r == -ENOENT) + return -ENODATA; + + return r; +} +#endif diff --git a/src/basic/efivars.h b/src/basic/efivars.h new file mode 100644 index 00000000..13a33c66 --- /dev/null +++ b/src/basic/efivars.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if !ENABLE_EFI +# include +#endif +#include +#include +#include + +#include "sd-id128.h" + +#include "efi/loader-features.h" +#include "time-util.h" + +#define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f) +#define EFI_VENDOR_GLOBAL SD_ID128_MAKE(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c) +#define EFI_VENDOR_SYSTEMD SD_ID128_MAKE(8c,f2,64,4b,4b,0b,42,8f,93,87,6d,87,60,50,dc,67) +#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 + +#if ENABLE_EFI + +char* efi_variable_path(sd_id128_t vendor, const char *name); +int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size); +int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p); +int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size); +int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *p); + +bool is_efi_boot(void); +bool is_efi_secure_boot(void); +bool is_efi_secure_boot_setup_mode(void); + +int systemd_efi_options_variable(char **line); + +#else + +static inline char* efi_variable_path(sd_id128_t vendor, const char *name) { + return NULL; +} + +static inline int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size) { + return -EOPNOTSUPP; +} + +static inline int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { + return -EOPNOTSUPP; +} + +static inline int efi_set_variable(sd_id128_t vendor, const char *name, const void *value, size_t size) { + return -EOPNOTSUPP; +} + +static inline int efi_set_variable_string(sd_id128_t vendor, const char *name, const char *p) { + return -EOPNOTSUPP; +} + +static inline bool is_efi_boot(void) { + return false; +} + +static inline bool is_efi_secure_boot(void) { + return false; +} + +static inline bool is_efi_secure_boot_setup_mode(void) { + return false; +} + +static inline int systemd_efi_options_variable(char **line) { + return -ENODATA; +} + +#endif diff --git a/src/basic/env-file.c b/src/basic/env-file.c new file mode 100644 index 00000000..26470796 --- /dev/null +++ b/src/basic/env-file.c @@ -0,0 +1,563 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "env-file.h" +#include "env-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "utf8.h" + +static int parse_env_file_internal( + FILE *f, + const char *fname, + int (*push) (const char *filename, unsigned line, + const char *key, char *value, void *userdata, int *n_pushed), + void *userdata, + int *n_pushed) { + + size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1; + _cleanup_free_ char *contents = NULL, *key = NULL, *value = NULL; + unsigned line = 1; + char *p; + int r; + + enum { + PRE_KEY, + KEY, + PRE_VALUE, + VALUE, + VALUE_ESCAPE, + SINGLE_QUOTE_VALUE, + DOUBLE_QUOTE_VALUE, + DOUBLE_QUOTE_VALUE_ESCAPE, + COMMENT, + COMMENT_ESCAPE + } state = PRE_KEY; + + if (f) + r = read_full_stream(f, &contents, NULL); + else + r = read_full_file(fname, &contents, NULL); + if (r < 0) + return r; + + for (p = contents; *p; p++) { + char c = *p; + + switch (state) { + + case PRE_KEY: + if (strchr(COMMENTS, c)) + state = COMMENT; + else if (!strchr(WHITESPACE, c)) { + state = KEY; + last_key_whitespace = (size_t) -1; + + if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) + return -ENOMEM; + + key[n_key++] = c; + } + break; + + case KEY: + if (strchr(NEWLINE, c)) { + state = PRE_KEY; + line++; + n_key = 0; + } else if (c == '=') { + state = PRE_VALUE; + last_value_whitespace = (size_t) -1; + } else { + if (!strchr(WHITESPACE, c)) + last_key_whitespace = (size_t) -1; + else if (last_key_whitespace == (size_t) -1) + last_key_whitespace = n_key; + + if (!GREEDY_REALLOC(key, key_alloc, n_key+2)) + return -ENOMEM; + + key[n_key++] = c; + } + + break; + + case PRE_VALUE: + if (strchr(NEWLINE, c)) { + state = PRE_KEY; + line++; + key[n_key] = 0; + + if (value) + value[n_value] = 0; + + /* strip trailing whitespace from key */ + if (last_key_whitespace != (size_t) -1) + key[last_key_whitespace] = 0; + + r = push(fname, line, key, value, userdata, n_pushed); + if (r < 0) + return r; + + n_key = 0; + value = NULL; + value_alloc = n_value = 0; + + } else if (c == '\'') + state = SINGLE_QUOTE_VALUE; + else if (c == '"') + state = DOUBLE_QUOTE_VALUE; + else if (c == '\\') + state = VALUE_ESCAPE; + else if (!strchr(WHITESPACE, c)) { + state = VALUE; + + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) + return -ENOMEM; + + value[n_value++] = c; + } + + break; + + case VALUE: + if (strchr(NEWLINE, c)) { + state = PRE_KEY; + line++; + + key[n_key] = 0; + + if (value) + value[n_value] = 0; + + /* Chomp off trailing whitespace from value */ + if (last_value_whitespace != (size_t) -1) + value[last_value_whitespace] = 0; + + /* strip trailing whitespace from key */ + if (last_key_whitespace != (size_t) -1) + key[last_key_whitespace] = 0; + + r = push(fname, line, key, value, userdata, n_pushed); + if (r < 0) + return r; + + n_key = 0; + value = NULL; + value_alloc = n_value = 0; + + } else if (c == '\\') { + state = VALUE_ESCAPE; + last_value_whitespace = (size_t) -1; + } else { + if (!strchr(WHITESPACE, c)) + last_value_whitespace = (size_t) -1; + else if (last_value_whitespace == (size_t) -1) + last_value_whitespace = n_value; + + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) + return -ENOMEM; + + value[n_value++] = c; + } + + break; + + case VALUE_ESCAPE: + state = VALUE; + + if (!strchr(NEWLINE, c)) { + /* Escaped newlines we eat up entirely */ + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) + return -ENOMEM; + + value[n_value++] = c; + } + break; + + case SINGLE_QUOTE_VALUE: + if (c == '\'') + state = PRE_VALUE; + else { + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) + return -ENOMEM; + + value[n_value++] = c; + } + + break; + + case DOUBLE_QUOTE_VALUE: + if (c == '"') + state = PRE_VALUE; + else if (c == '\\') + state = DOUBLE_QUOTE_VALUE_ESCAPE; + else { + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) + return -ENOMEM; + + value[n_value++] = c; + } + + break; + + case DOUBLE_QUOTE_VALUE_ESCAPE: + state = DOUBLE_QUOTE_VALUE; + + if (c == '"') { + if (!GREEDY_REALLOC(value, value_alloc, n_value+2)) + return -ENOMEM; + value[n_value++] = '"'; + } else if (!strchr(NEWLINE, c)) { + if (!GREEDY_REALLOC(value, value_alloc, n_value+3)) + return -ENOMEM; + value[n_value++] = '\\'; + value[n_value++] = c; + } + + break; + + case COMMENT: + if (c == '\\') + state = COMMENT_ESCAPE; + else if (strchr(NEWLINE, c)) { + state = PRE_KEY; + line++; + } + break; + + case COMMENT_ESCAPE: + state = COMMENT; + break; + } + } + + if (IN_SET(state, + PRE_VALUE, + VALUE, + VALUE_ESCAPE, + SINGLE_QUOTE_VALUE, + DOUBLE_QUOTE_VALUE, + DOUBLE_QUOTE_VALUE_ESCAPE)) { + + key[n_key] = 0; + + if (value) + value[n_value] = 0; + + if (state == VALUE) + if (last_value_whitespace != (size_t) -1) + value[last_value_whitespace] = 0; + + /* strip trailing whitespace from key */ + if (last_key_whitespace != (size_t) -1) + key[last_key_whitespace] = 0; + + r = push(fname, line, key, value, userdata, n_pushed); + if (r < 0) + return r; + + value = NULL; + } + + return 0; +} + +static int check_utf8ness_and_warn( + const char *filename, unsigned line, + const char *key, char *value) { + + if (!utf8_is_valid(key)) { + _cleanup_free_ char *p = NULL; + + p = utf8_escape_invalid(key); + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s:%u: invalid UTF-8 in key '%s', ignoring.", + strna(filename), line, p); + } + + if (value && !utf8_is_valid(value)) { + _cleanup_free_ char *p = NULL; + + p = utf8_escape_invalid(value); + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.", + strna(filename), line, key, p); + } + + return 0; +} + +static int parse_env_file_push( + const char *filename, unsigned line, + const char *key, char *value, + void *userdata, + int *n_pushed) { + + const char *k; + va_list aq, *ap = userdata; + int r; + + r = check_utf8ness_and_warn(filename, line, key, value); + if (r < 0) + return r; + + va_copy(aq, *ap); + + while ((k = va_arg(aq, const char *))) { + char **v; + + v = va_arg(aq, char **); + + if (streq(key, k)) { + va_end(aq); + free(*v); + *v = value; + + if (n_pushed) + (*n_pushed)++; + + return 1; + } + } + + va_end(aq); + free(value); + + return 0; +} + +int parse_env_filev( + FILE *f, + const char *fname, + va_list ap) { + + int r, n_pushed = 0; + va_list aq; + + va_copy(aq, ap); + r = parse_env_file_internal(f, fname, parse_env_file_push, &aq, &n_pushed); + va_end(aq); + if (r < 0) + return r; + + return n_pushed; +} + +int parse_env_file_sentinel( + FILE *f, + const char *fname, + ...) { + + va_list ap; + int r; + + va_start(ap, fname); + r = parse_env_filev(f, fname, ap); + va_end(ap); + + return r; +} + +static int load_env_file_push( + const char *filename, unsigned line, + const char *key, char *value, + void *userdata, + int *n_pushed) { + char ***m = userdata; + char *p; + int r; + + r = check_utf8ness_and_warn(filename, line, key, value); + if (r < 0) + return r; + + p = strjoin(key, "=", value); + if (!p) + return -ENOMEM; + + r = strv_env_replace(m, p); + if (r < 0) { + free(p); + return r; + } + + if (n_pushed) + (*n_pushed)++; + + free(value); + return 0; +} + +int load_env_file(FILE *f, const char *fname, char ***rl) { + char **m = NULL; + int r; + + r = parse_env_file_internal(f, fname, load_env_file_push, &m, NULL); + if (r < 0) { + strv_free(m); + return r; + } + + *rl = m; + return 0; +} + +static int load_env_file_push_pairs( + const char *filename, unsigned line, + const char *key, char *value, + void *userdata, + int *n_pushed) { + char ***m = userdata; + int r; + + r = check_utf8ness_and_warn(filename, line, key, value); + if (r < 0) + return r; + + r = strv_extend(m, key); + if (r < 0) + return -ENOMEM; + + if (!value) { + r = strv_extend(m, ""); + if (r < 0) + return -ENOMEM; + } else { + r = strv_push(m, value); + if (r < 0) + return r; + } + + if (n_pushed) + (*n_pushed)++; + + return 0; +} + +int load_env_file_pairs(FILE *f, const char *fname, char ***rl) { + char **m = NULL; + int r; + + r = parse_env_file_internal(f, fname, load_env_file_push_pairs, &m, NULL); + if (r < 0) { + strv_free(m); + return r; + } + + *rl = m; + return 0; +} + +static int merge_env_file_push( + const char *filename, unsigned line, + const char *key, char *value, + void *userdata, + int *n_pushed) { + + char ***env = userdata; + char *expanded_value; + + assert(env); + + if (!value) { + log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename), line, key); + return 0; + } + + if (!env_name_is_valid(key)) { + log_error("%s:%u: invalid variable name \"%s\", ignoring.", strna(filename), line, key); + free(value); + return 0; + } + + expanded_value = replace_env(value, *env, + REPLACE_ENV_USE_ENVIRONMENT| + REPLACE_ENV_ALLOW_BRACELESS| + REPLACE_ENV_ALLOW_EXTENDED); + if (!expanded_value) + return -ENOMEM; + + free_and_replace(value, expanded_value); + + log_debug("%s:%u: setting %s=%s", filename, line, key, value); + + return load_env_file_push(filename, line, key, value, env, n_pushed); +} + +int merge_env_file( + char ***env, + FILE *f, + const char *fname) { + + /* NOTE: this function supports braceful and braceless variable expansions, + * plus "extended" substitutions, unlike other exported parsing functions. + */ + + return parse_env_file_internal(f, fname, merge_env_file_push, env, NULL); +} + +static void write_env_var(FILE *f, const char *v) { + const char *p; + + p = strchr(v, '='); + if (!p) { + /* Fallback */ + fputs_unlocked(v, f); + fputc_unlocked('\n', f); + return; + } + + p++; + fwrite_unlocked(v, 1, p-v, f); + + if (string_has_cc(p, NULL) || chars_intersect(p, WHITESPACE SHELL_NEED_QUOTES)) { + fputc_unlocked('"', f); + + for (; *p; p++) { + if (strchr(SHELL_NEED_ESCAPE, *p)) + fputc_unlocked('\\', f); + + fputc_unlocked(*p, f); + } + + fputc_unlocked('"', f); + } else + fputs_unlocked(p, f); + + fputc_unlocked('\n', f); +} + +int write_env_file(const char *fname, char **l) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *p = NULL; + char **i; + int r; + + assert(fname); + + r = fopen_temporary(fname, &f, &p); + if (r < 0) + return r; + + (void) fchmod_umask(fileno(f), 0644); + + STRV_FOREACH(i, l) + write_env_var(f, *i); + + r = fflush_and_check(f); + if (r >= 0) { + if (rename(p, fname) >= 0) + return 0; + + r = -errno; + } + + (void) unlink(p); + return r; +} diff --git a/src/basic/env-file.h b/src/basic/env-file.h new file mode 100644 index 00000000..e1ca195f --- /dev/null +++ b/src/basic/env-file.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "macro.h" + +int parse_env_filev(FILE *f, const char *fname, va_list ap); +int parse_env_file_sentinel(FILE *f, const char *fname, ...) _sentinel_; +#define parse_env_file(f, fname, ...) parse_env_file_sentinel(f, fname, __VA_ARGS__, NULL) +int load_env_file(FILE *f, const char *fname, char ***l); +int load_env_file_pairs(FILE *f, const char *fname, char ***l); + +int merge_env_file(char ***env, FILE *f, const char *fname); + +int write_env_file(const char *fname, char **l); diff --git a/src/basic/env-util.c b/src/basic/env-util.c new file mode 100644 index 00000000..b8dc9891 --- /dev/null +++ b/src/basic/env-util.c @@ -0,0 +1,751 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "env-util.h" +#include "escape.h" +#include "extract-word.h" +#include "macro.h" +#include "parse-util.h" +#include "string-util.h" +#include "strv.h" +#include "utf8.h" + +#define VALID_CHARS_ENV_NAME \ + DIGITS LETTERS \ + "_" + +static bool env_name_is_valid_n(const char *e, size_t n) { + const char *p; + + if (!e) + return false; + + if (n <= 0) + return false; + + if (e[0] >= '0' && e[0] <= '9') + return false; + + /* POSIX says the overall size of the environment block cannot + * be > ARG_MAX, an individual assignment hence cannot be + * either. Discounting the equal sign and trailing NUL this + * hence leaves ARG_MAX-2 as longest possible variable + * name. */ + if (n > (size_t) sysconf(_SC_ARG_MAX) - 2) + return false; + + for (p = e; p < e + n; p++) + if (!strchr(VALID_CHARS_ENV_NAME, *p)) + return false; + + return true; +} + +bool env_name_is_valid(const char *e) { + if (!e) + return false; + + return env_name_is_valid_n(e, strlen(e)); +} + +bool env_value_is_valid(const char *e) { + if (!e) + return false; + + if (!utf8_is_valid(e)) + return false; + + /* bash allows tabs and newlines in environment variables, and so + * should we */ + if (string_has_cc(e, "\t\n")) + return false; + + /* POSIX says the overall size of the environment block cannot + * be > ARG_MAX, an individual assignment hence cannot be + * either. Discounting the shortest possible variable name of + * length 1, the equal sign and trailing NUL this hence leaves + * ARG_MAX-3 as longest possible variable value. */ + if (strlen(e) > sc_arg_max() - 3) + return false; + + return true; +} + +bool env_assignment_is_valid(const char *e) { + const char *eq; + + eq = strchr(e, '='); + if (!eq) + return false; + + if (!env_name_is_valid_n(e, eq - e)) + return false; + + if (!env_value_is_valid(eq + 1)) + return false; + + /* POSIX says the overall size of the environment block cannot + * be > ARG_MAX, hence the individual variable assignments + * cannot be either, but let's leave room for one trailing NUL + * byte. */ + if (strlen(e) > sc_arg_max() - 1) + return false; + + return true; +} + +bool strv_env_is_valid(char **e) { + char **p, **q; + + STRV_FOREACH(p, e) { + size_t k; + + if (!env_assignment_is_valid(*p)) + return false; + + /* Check if there are duplicate assignments */ + k = strcspn(*p, "="); + STRV_FOREACH(q, p + 1) + if (strneq(*p, *q, k) && (*q)[k] == '=') + return false; + } + + return true; +} + +bool strv_env_name_is_valid(char **l) { + char **p; + + STRV_FOREACH(p, l) { + if (!env_name_is_valid(*p)) + return false; + + if (strv_contains(p + 1, *p)) + return false; + } + + return true; +} + +bool strv_env_name_or_assignment_is_valid(char **l) { + char **p; + + STRV_FOREACH(p, l) { + if (!env_assignment_is_valid(*p) && !env_name_is_valid(*p)) + return false; + + if (strv_contains(p + 1, *p)) + return false; + } + + return true; +} + +static int env_append(char **r, char ***k, char **a) { + assert(r); + assert(k); + assert(*k >= r); + + if (!a) + return 0; + + /* Expects the following arguments: 'r' shall point to the beginning of an strv we are going to append to, 'k' + * to a pointer pointing to the NULL entry at the end of the same array. 'a' shall point to another strv. + * + * This call adds every entry of 'a' to 'r', either overriding an existing matching entry, or appending to it. + * + * This call assumes 'r' has enough pre-allocated space to grow by all of 'a''s items. */ + + for (; *a; a++) { + char **j, *c; + size_t n; + + n = strcspn(*a, "="); + if ((*a)[n] == '=') + n++; + + for (j = r; j < *k; j++) + if (strneq(*j, *a, n)) + break; + + c = strdup(*a); + if (!c) + return -ENOMEM; + + if (j >= *k) { /* Append to the end? */ + (*k)[0] = c; + (*k)[1] = NULL; + (*k)++; + } else + free_and_replace(*j, c); /* Override existing item */ + } + + return 0; +} + +char **strv_env_merge(size_t n_lists, ...) { + _cleanup_strv_free_ char **ret = NULL; + size_t n = 0, i; + char **l, **k; + va_list ap; + + /* Merges an arbitrary number of environment sets */ + + va_start(ap, n_lists); + for (i = 0; i < n_lists; i++) { + l = va_arg(ap, char**); + n += strv_length(l); + } + va_end(ap); + + ret = new(char*, n+1); + if (!ret) + return NULL; + + *ret = NULL; + k = ret; + + va_start(ap, n_lists); + for (i = 0; i < n_lists; i++) { + l = va_arg(ap, char**); + if (env_append(ret, &k, l) < 0) { + va_end(ap); + return NULL; + } + } + va_end(ap); + + return TAKE_PTR(ret); +} + +static bool env_match(const char *t, const char *pattern) { + assert(t); + assert(pattern); + + /* pattern a matches string a + * a matches a= + * a matches a=b + * a= matches a= + * a=b matches a=b + * a= does not match a + * a=b does not match a= + * a=b does not match a + * a=b does not match a=c */ + + if (streq(t, pattern)) + return true; + + if (!strchr(pattern, '=')) { + size_t l = strlen(pattern); + + return strneq(t, pattern, l) && t[l] == '='; + } + + return false; +} + +static bool env_entry_has_name(const char *entry, const char *name) { + const char *t; + + assert(entry); + assert(name); + + t = startswith(entry, name); + if (!t) + return false; + + return *t == '='; +} + +char **strv_env_delete(char **x, size_t n_lists, ...) { + size_t n, i = 0; + char **k, **r; + va_list ap; + + /* Deletes every entry from x that is mentioned in the other + * string lists */ + + n = strv_length(x); + + r = new(char*, n+1); + if (!r) + return NULL; + + STRV_FOREACH(k, x) { + size_t v; + + va_start(ap, n_lists); + for (v = 0; v < n_lists; v++) { + char **l, **j; + + l = va_arg(ap, char**); + STRV_FOREACH(j, l) + if (env_match(*k, *j)) + goto skip; + } + va_end(ap); + + r[i] = strdup(*k); + if (!r[i]) { + strv_free(r); + return NULL; + } + + i++; + continue; + + skip: + va_end(ap); + } + + r[i] = NULL; + + assert(i <= n); + + return r; +} + +char **strv_env_unset(char **l, const char *p) { + + char **f, **t; + + if (!l) + return NULL; + + assert(p); + + /* Drops every occurrence of the env var setting p in the + * string list. Edits in-place. */ + + for (f = t = l; *f; f++) { + + if (env_match(*f, p)) { + free(*f); + continue; + } + + *(t++) = *f; + } + + *t = NULL; + return l; +} + +char **strv_env_unset_many(char **l, ...) { + char **f, **t; + + if (!l) + return NULL; + + /* Like strv_env_unset() but applies many at once. Edits in-place. */ + + for (f = t = l; *f; f++) { + bool found = false; + const char *p; + va_list ap; + + va_start(ap, l); + + while ((p = va_arg(ap, const char*))) { + if (env_match(*f, p)) { + found = true; + break; + } + } + + va_end(ap); + + if (found) { + free(*f); + continue; + } + + *(t++) = *f; + } + + *t = NULL; + return l; +} + +int strv_env_replace(char ***l, char *p) { + const char *t, *name; + char **f; + int r; + + assert(p); + + /* Replace first occurrence of the env var or add a new one in the string list. Drop other occurrences. Edits + * in-place. Does not copy p. p must be a valid key=value assignment. + */ + + t = strchr(p, '='); + if (!t) + return -EINVAL; + + name = strndupa(p, t - p); + + STRV_FOREACH(f, *l) + if (env_entry_has_name(*f, name)) { + free_and_replace(*f, p); + strv_env_unset(f + 1, *f); + return 0; + } + + /* We didn't find a match, we need to append p or create a new strv */ + r = strv_push(l, p); + if (r < 0) + return r; + + return 1; +} + +char **strv_env_set(char **x, const char *p) { + _cleanup_strv_free_ char **ret = NULL; + size_t n, m; + char **k; + + /* Overrides the env var setting of p, returns a new copy */ + + n = strv_length(x); + m = n + 2; + if (m < n) /* overflow? */ + return NULL; + + ret = new(char*, m); + if (!ret) + return NULL; + + *ret = NULL; + k = ret; + + if (env_append(ret, &k, x) < 0) + return NULL; + + if (env_append(ret, &k, STRV_MAKE(p)) < 0) + return NULL; + + return TAKE_PTR(ret); +} + +char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) { + char **i; + + assert(name); + + if (k <= 0) + return NULL; + + STRV_FOREACH_BACKWARDS(i, l) + if (strneq(*i, name, k) && + (*i)[k] == '=') + return *i + k + 1; + + if (flags & REPLACE_ENV_USE_ENVIRONMENT) { + const char *t; + + t = strndupa(name, k); + return getenv(t); + }; + + return NULL; +} + +char *strv_env_get(char **l, const char *name) { + assert(name); + + return strv_env_get_n(l, name, strlen(name), 0); +} + +char **strv_env_clean_with_callback(char **e, void (*invalid_callback)(const char *p, void *userdata), void *userdata) { + char **p, **q; + int k = 0; + + STRV_FOREACH(p, e) { + size_t n; + bool duplicate = false; + + if (!env_assignment_is_valid(*p)) { + if (invalid_callback) + invalid_callback(*p, userdata); + free(*p); + continue; + } + + n = strcspn(*p, "="); + STRV_FOREACH(q, p + 1) + if (strneq(*p, *q, n) && (*q)[n] == '=') { + duplicate = true; + break; + } + + if (duplicate) { + free(*p); + continue; + } + + e[k++] = *p; + } + + if (e) + e[k] = NULL; + + return e; +} + +char *replace_env_n(const char *format, size_t n, char **env, unsigned flags) { + enum { + WORD, + CURLY, + VARIABLE, + VARIABLE_RAW, + TEST, + DEFAULT_VALUE, + ALTERNATE_VALUE, + } state = WORD; + + const char *e, *word = format, *test_value; + char *k; + _cleanup_free_ char *r = NULL; + size_t i, len; + int nest = 0; + + assert(format); + + for (e = format, i = 0; *e && i < n; e ++, i ++) + switch (state) { + + case WORD: + if (*e == '$') + state = CURLY; + break; + + case CURLY: + if (*e == '{') { + k = strnappend(r, word, e-word-1); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e-1; + state = VARIABLE; + nest++; + } else if (*e == '$') { + k = strnappend(r, word, e-word); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e+1; + state = WORD; + + } else if (flags & REPLACE_ENV_ALLOW_BRACELESS && strchr(VALID_CHARS_ENV_NAME, *e)) { + k = strnappend(r, word, e-word-1); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e-1; + state = VARIABLE_RAW; + + } else + state = WORD; + break; + + case VARIABLE: + if (*e == '}') { + const char *t; + + t = strv_env_get_n(env, word+2, e-word-2, flags); + + k = strjoin(r, t); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e+1; + state = WORD; + } else if (*e == ':') { + if (!(flags & REPLACE_ENV_ALLOW_EXTENDED)) + /* Treat this as unsupported syntax, i.e. do no replacement */ + state = WORD; + else { + len = e-word-2; + state = TEST; + } + } + break; + + case TEST: + if (*e == '-') + state = DEFAULT_VALUE; + else if (*e == '+') + state = ALTERNATE_VALUE; + else { + state = WORD; + break; + } + + test_value = e+1; + break; + + case DEFAULT_VALUE: /* fall through */ + case ALTERNATE_VALUE: + assert(flags & REPLACE_ENV_ALLOW_EXTENDED); + + if (*e == '{') { + nest++; + break; + } + + if (*e != '}') + break; + + nest--; + if (nest == 0) { + const char *t; + _cleanup_free_ char *v = NULL; + + t = strv_env_get_n(env, word+2, len, flags); + + if (t && state == ALTERNATE_VALUE) + t = v = replace_env_n(test_value, e-test_value, env, flags); + else if (!t && state == DEFAULT_VALUE) + t = v = replace_env_n(test_value, e-test_value, env, flags); + + k = strjoin(r, t); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e+1; + state = WORD; + } + break; + + case VARIABLE_RAW: + assert(flags & REPLACE_ENV_ALLOW_BRACELESS); + + if (!strchr(VALID_CHARS_ENV_NAME, *e)) { + const char *t; + + t = strv_env_get_n(env, word+1, e-word-1, flags); + + k = strjoin(r, t); + if (!k) + return NULL; + + free_and_replace(r, k); + + word = e--; + i--; + state = WORD; + } + break; + } + + if (state == VARIABLE_RAW) { + const char *t; + + assert(flags & REPLACE_ENV_ALLOW_BRACELESS); + + t = strv_env_get_n(env, word+1, e-word-1, flags); + return strjoin(r, t); + } else + return strnappend(r, word, e-word); +} + +char **replace_env_argv(char **argv, char **env) { + char **ret, **i; + size_t k = 0, l = 0; + + l = strv_length(argv); + + ret = new(char*, l+1); + if (!ret) + return NULL; + + STRV_FOREACH(i, argv) { + + /* If $FOO appears as single word, replace it by the split up variable */ + if ((*i)[0] == '$' && !IN_SET((*i)[1], '{', '$')) { + char *e; + char **w, **m = NULL; + size_t q; + + e = strv_env_get(env, *i+1); + if (e) { + int r; + + r = strv_split_extract(&m, e, WHITESPACE, EXTRACT_RELAX|EXTRACT_UNQUOTE); + if (r < 0) { + ret[k] = NULL; + strv_free(ret); + return NULL; + } + } else + m = NULL; + + q = strv_length(m); + l = l + q - 1; + + w = reallocarray(ret, l + 1, sizeof(char *)); + if (!w) { + ret[k] = NULL; + strv_free(ret); + strv_free(m); + return NULL; + } + + ret = w; + if (m) { + memcpy(ret + k, m, q * sizeof(char*)); + free(m); + } + + k += q; + continue; + } + + /* If ${FOO} appears as part of a word, replace it by the variable as-is */ + ret[k] = replace_env(*i, env, 0); + if (!ret[k]) { + strv_free(ret); + return NULL; + } + k++; + } + + ret[k] = NULL; + return ret; +} + +int getenv_bool(const char *p) { + const char *e; + + e = getenv(p); + if (!e) + return -ENXIO; + + return parse_boolean(e); +} + +int getenv_bool_secure(const char *p) { + const char *e; + + e = secure_getenv(p); + if (!e) + return -ENXIO; + + return parse_boolean(e); +} diff --git a/src/basic/env-util.h b/src/basic/env-util.h new file mode 100644 index 00000000..92802ed7 --- /dev/null +++ b/src/basic/env-util.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "macro.h" +#include "string.h" + +static inline size_t sc_arg_max(void) { + long l = sysconf(_SC_ARG_MAX); + assert(l > 0); + return (size_t) l; +} + +bool env_name_is_valid(const char *e); +bool env_value_is_valid(const char *e); +bool env_assignment_is_valid(const char *e); + +enum { + REPLACE_ENV_USE_ENVIRONMENT = 1 << 0, + REPLACE_ENV_ALLOW_BRACELESS = 1 << 1, + REPLACE_ENV_ALLOW_EXTENDED = 1 << 2, +}; + +char *replace_env_n(const char *format, size_t n, char **env, unsigned flags); +char **replace_env_argv(char **argv, char **env); + +static inline char *replace_env(const char *format, char **env, unsigned flags) { + return replace_env_n(format, strlen(format), env, flags); +} + +bool strv_env_is_valid(char **e); +#define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL) +char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata); + +bool strv_env_name_is_valid(char **l); +bool strv_env_name_or_assignment_is_valid(char **l); + +char **strv_env_merge(size_t n_lists, ...); +char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */ + +char **strv_env_set(char **x, const char *p); /* New copy ... */ +char **strv_env_unset(char **l, const char *p); /* In place ... */ +char **strv_env_unset_many(char **l, ...) _sentinel_; +int strv_env_replace(char ***l, char *p); /* In place ... */ + +char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) _pure_; +char *strv_env_get(char **x, const char *n) _pure_; + +int getenv_bool(const char *p); +int getenv_bool_secure(const char *p); diff --git a/src/basic/errno-list.c b/src/basic/errno-list.c new file mode 100644 index 00000000..44cc5705 --- /dev/null +++ b/src/basic/errno-list.c @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "errno-list.h" +#include "macro.h" + +static const struct errno_name* lookup_errno(register const char *str, + register GPERF_LEN_TYPE len); + +#include "errno-from-name.h" +#include "errno-to-name.h" + +const char *errno_to_name(int id) { + + if (id < 0) + id = -id; + + if ((size_t) id >= ELEMENTSOF(errno_names)) + return NULL; + + return errno_names[id]; +} + +int errno_from_name(const char *name) { + const struct errno_name *sc; + + assert(name); + + sc = lookup_errno(name, strlen(name)); + if (!sc) + return -EINVAL; + + assert(sc->id > 0); + return sc->id; +} diff --git a/src/basic/errno-list.h b/src/basic/errno-list.h new file mode 100644 index 00000000..9c639b4f --- /dev/null +++ b/src/basic/errno-list.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +/* + * MAX_ERRNO is defined as 4095 in linux/err.h + * We use the same value here. + */ +#define ERRNO_MAX 4095 + +const char *errno_to_name(int id); +int errno_from_name(const char *name); +static inline bool errno_is_valid(int n) { + return n > 0 && n <= ERRNO_MAX; +} diff --git a/src/basic/errno-to-name.awk b/src/basic/errno-to-name.awk new file mode 100644 index 00000000..0878abac --- /dev/null +++ b/src/basic/errno-to-name.awk @@ -0,0 +1,9 @@ +BEGIN{ + print "static const char* const errno_names[] = { " +} +!/EDEADLOCK/ && !/EWOULDBLOCK/ && !/ENOTSUP/ { + printf " [%s] = \"%s\",\n", $1, $1 +} +END{ + print "};" +} diff --git a/src/basic/errno-util.h b/src/basic/errno-util.h new file mode 100644 index 00000000..8f1be6c0 --- /dev/null +++ b/src/basic/errno-util.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "macro.h" + +static inline void _reset_errno_(int *saved_errno) { + if (*saved_errno < 0) /* Invalidated by UNPROTECT_ERRNO? */ + return; + + errno = *saved_errno; +} + +#define PROTECT_ERRNO \ + _cleanup_(_reset_errno_) _unused_ int _saved_errno_ = errno + +#define UNPROTECT_ERRNO \ + do { \ + errno = _saved_errno_; \ + _saved_errno_ = -1; \ + } while (false) + +static inline int negative_errno(void) { + /* This helper should be used to shut up gcc if you know 'errno' is + * negative. Instead of "return -errno;", use "return negative_errno();" + * It will suppress bogus gcc warnings in case it assumes 'errno' might + * be 0 and thus the caller's error-handling might not be triggered. */ + assert_return(errno > 0, -EINVAL); + return -errno; +} + +static inline const char *strerror_safe(int error) { + /* 'safe' here does NOT mean thread safety. */ + return strerror(abs(error)); +} + +static inline int errno_or_else(int fallback) { + /* To be used when invoking library calls where errno handling is not defined clearly: we return + * errno if it is set, and the specified error otherwise. The idea is that the caller initializes + * errno to zero before doing an API call, and then uses this helper to retrieve a somewhat useful + * error code */ + if (errno > 0) + return -errno; + + return -abs(fallback); +} + +/* Hint #1: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5. + * + * Hint #2: The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. See the + * icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources */ +static inline bool ERRNO_IS_DISCONNECT(int r) { + return IN_SET(abs(r), + ECONNABORTED, + ECONNREFUSED, + ECONNRESET, + EHOSTDOWN, + EHOSTUNREACH, + ENETDOWN, + ENETRESET, + ENETUNREACH, + ENONET, + ENOPROTOOPT, + ENOTCONN, + EPIPE, + EPROTO, + ESHUTDOWN); +} + +/* Transient errors we might get on accept() that we should ignore. As per error handling comment in + * the accept(2) man page. */ +static inline bool ERRNO_IS_ACCEPT_AGAIN(int r) { + return ERRNO_IS_DISCONNECT(r) || + IN_SET(abs(r), + EAGAIN, + EINTR, + EOPNOTSUPP); +} + +/* Resource exhaustion, could be our fault or general system trouble */ +static inline bool ERRNO_IS_RESOURCE(int r) { + return IN_SET(abs(r), + EMFILE, + ENFILE, + ENOMEM); +} + +/* Three different errors for "operation/system call/ioctl not supported" */ +static inline bool ERRNO_IS_NOT_SUPPORTED(int r) { + return IN_SET(abs(r), + EOPNOTSUPP, + ENOTTY, + ENOSYS); +} + +/* Two different errors for access problems */ +static inline bool ERRNO_IS_PRIVILEGE(int r) { + return IN_SET(abs(r), + EACCES, + EPERM); +} diff --git a/src/basic/escape.c b/src/basic/escape.c new file mode 100644 index 00000000..33a6f204 --- /dev/null +++ b/src/basic/escape.c @@ -0,0 +1,551 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "escape.h" +#include "hexdecoct.h" +#include "macro.h" +#include "utf8.h" + +int cescape_char(char c, char *buf) { + char *buf_old = buf; + + /* Needs space for 4 characters in the buffer */ + + switch (c) { + + case '\a': + *(buf++) = '\\'; + *(buf++) = 'a'; + break; + case '\b': + *(buf++) = '\\'; + *(buf++) = 'b'; + break; + case '\f': + *(buf++) = '\\'; + *(buf++) = 'f'; + break; + case '\n': + *(buf++) = '\\'; + *(buf++) = 'n'; + break; + case '\r': + *(buf++) = '\\'; + *(buf++) = 'r'; + break; + case '\t': + *(buf++) = '\\'; + *(buf++) = 't'; + break; + case '\v': + *(buf++) = '\\'; + *(buf++) = 'v'; + break; + case '\\': + *(buf++) = '\\'; + *(buf++) = '\\'; + break; + case '"': + *(buf++) = '\\'; + *(buf++) = '"'; + break; + case '\'': + *(buf++) = '\\'; + *(buf++) = '\''; + break; + + default: + /* For special chars we prefer octal over + * hexadecimal encoding, simply because glib's + * g_strescape() does the same */ + if ((c < ' ') || (c >= 127)) { + *(buf++) = '\\'; + *(buf++) = octchar((unsigned char) c >> 6); + *(buf++) = octchar((unsigned char) c >> 3); + *(buf++) = octchar((unsigned char) c); + } else + *(buf++) = c; + break; + } + + return buf - buf_old; +} + +char *cescape_length(const char *s, size_t n) { + const char *f; + char *r, *t; + + assert(s || n == 0); + + /* Does C style string escaping. May be reversed with + * cunescape(). */ + + r = new(char, n*4 + 1); + if (!r) + return NULL; + + for (f = s, t = r; f < s + n; f++) + t += cescape_char(*f, t); + + *t = 0; + + return r; +} + +char *cescape(const char *s) { + assert(s); + + return cescape_length(s, strlen(s)); +} + +int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) { + int r = 1; + + assert(p); + assert(ret); + + /* Unescapes C style. Returns the unescaped character in ret. + * Sets *eight_bit to true if the escaped sequence either fits in + * one byte in UTF-8 or is a non-unicode literal byte and should + * instead be copied directly. + */ + + if (length != (size_t) -1 && length < 1) + return -EINVAL; + + switch (p[0]) { + + case 'a': + *ret = '\a'; + break; + case 'b': + *ret = '\b'; + break; + case 'f': + *ret = '\f'; + break; + case 'n': + *ret = '\n'; + break; + case 'r': + *ret = '\r'; + break; + case 't': + *ret = '\t'; + break; + case 'v': + *ret = '\v'; + break; + case '\\': + *ret = '\\'; + break; + case '"': + *ret = '"'; + break; + case '\'': + *ret = '\''; + break; + + case 's': + /* This is an extension of the XDG syntax files */ + *ret = ' '; + break; + + case 'x': { + /* hexadecimal encoding */ + int a, b; + + if (length != (size_t) -1 && length < 3) + return -EINVAL; + + a = unhexchar(p[1]); + if (a < 0) + return -EINVAL; + + b = unhexchar(p[2]); + if (b < 0) + return -EINVAL; + + /* Don't allow NUL bytes */ + if (a == 0 && b == 0) + return -EINVAL; + + *ret = (a << 4U) | b; + *eight_bit = true; + r = 3; + break; + } + + case 'u': { + /* C++11 style 16bit unicode */ + + int a[4]; + size_t i; + uint32_t c; + + if (length != (size_t) -1 && length < 5) + return -EINVAL; + + for (i = 0; i < 4; i++) { + a[i] = unhexchar(p[1 + i]); + if (a[i] < 0) + return a[i]; + } + + c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3]; + + /* Don't allow 0 chars */ + if (c == 0) + return -EINVAL; + + *ret = c; + r = 5; + break; + } + + case 'U': { + /* C++11 style 32bit unicode */ + + int a[8]; + size_t i; + char32_t c; + + if (length != (size_t) -1 && length < 9) + return -EINVAL; + + for (i = 0; i < 8; i++) { + a[i] = unhexchar(p[1 + i]); + if (a[i] < 0) + return a[i]; + } + + c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) | + ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] << 8U) | ((uint32_t) a[6] << 4U) | (uint32_t) a[7]; + + /* Don't allow 0 chars */ + if (c == 0) + return -EINVAL; + + /* Don't allow invalid code points */ + if (!unichar_is_valid(c)) + return -EINVAL; + + *ret = c; + r = 9; + break; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': { + /* octal encoding */ + int a, b, c; + char32_t m; + + if (length != (size_t) -1 && length < 3) + return -EINVAL; + + a = unoctchar(p[0]); + if (a < 0) + return -EINVAL; + + b = unoctchar(p[1]); + if (b < 0) + return -EINVAL; + + c = unoctchar(p[2]); + if (c < 0) + return -EINVAL; + + /* don't allow NUL bytes */ + if (a == 0 && b == 0 && c == 0) + return -EINVAL; + + /* Don't allow bytes above 255 */ + m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c; + if (m > 255) + return -EINVAL; + + *ret = m; + *eight_bit = true; + r = 3; + break; + } + + default: + return -EINVAL; + } + + return r; +} + +int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) { + char *r, *t; + const char *f; + size_t pl; + + assert(s); + assert(ret); + + /* Undoes C style string escaping, and optionally prefixes it. */ + + pl = strlen_ptr(prefix); + + r = new(char, pl+length+1); + if (!r) + return -ENOMEM; + + if (prefix) + memcpy(r, prefix, pl); + + for (f = s, t = r + pl; f < s + length; f++) { + size_t remaining; + bool eight_bit = false; + char32_t u; + int k; + + remaining = s + length - f; + assert(remaining > 0); + + if (*f != '\\') { + /* A literal, copy verbatim */ + *(t++) = *f; + continue; + } + + if (remaining == 1) { + if (flags & UNESCAPE_RELAX) { + /* A trailing backslash, copy verbatim */ + *(t++) = *f; + continue; + } + + free(r); + return -EINVAL; + } + + k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit); + if (k < 0) { + if (flags & UNESCAPE_RELAX) { + /* Invalid escape code, let's take it literal then */ + *(t++) = '\\'; + continue; + } + + free(r); + return k; + } + + f += k; + if (eight_bit) + /* One byte? Set directly as specified */ + *(t++) = u; + else + /* Otherwise encode as multi-byte UTF-8 */ + t += utf8_encode_unichar(t, u); + } + + *t = 0; + + *ret = r; + return t - r; +} + +int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) { + return cunescape_length_with_prefix(s, length, NULL, flags, ret); +} + +int cunescape(const char *s, UnescapeFlags flags, char **ret) { + return cunescape_length(s, strlen(s), flags, ret); +} + +char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits) { + char *ans, *t, *prev, *prev2; + const char *f; + + /* Escapes all chars in bad, in addition to \ and all special chars, in \xFF style escaping. May be + * reversed with cunescape(). If eight_bits is true, characters >= 127 are let through unchanged. + * This corresponds to non-ASCII printable characters in pre-unicode encodings. + * + * If console_width is reached, output is truncated and "..." is appended. */ + + if (console_width == 0) + return strdup(""); + + ans = new(char, MIN(strlen(s), console_width) * 4 + 1); + if (!ans) + return NULL; + + memset(ans, '_', MIN(strlen(s), console_width) * 4); + ans[MIN(strlen(s), console_width) * 4] = 0; + + for (f = s, t = prev = prev2 = ans; ; f++) { + char *tmp_t = t; + + if (!*f) { + *t = 0; + return ans; + } + + if ((unsigned char) *f < ' ' || (!eight_bits && (unsigned char) *f >= 127) || + *f == '\\' || strchr(bad, *f)) { + if ((size_t) (t - ans) + 4 > console_width) + break; + + *(t++) = '\\'; + *(t++) = 'x'; + *(t++) = hexchar(*f >> 4); + *(t++) = hexchar(*f); + } else { + if ((size_t) (t - ans) + 1 > console_width) + break; + + *(t++) = *f; + } + + /* We might need to go back two cycles to fit three dots, so remember two positions */ + prev2 = prev; + prev = tmp_t; + } + + /* We can just write where we want, since chars are one-byte */ + size_t c = MIN(console_width, 3u); /* If the console is too narrow, write fewer dots */ + size_t off; + if (console_width - c >= (size_t) (t - ans)) + off = (size_t) (t - ans); + else if (console_width - c >= (size_t) (prev - ans)) + off = (size_t) (prev - ans); + else if (console_width - c >= (size_t) (prev2 - ans)) + off = (size_t) (prev2 - ans); + else + off = console_width - c; + assert(off <= (size_t) (t - ans)); + + memcpy(ans + off, "...", c); + ans[off + c] = '\0'; + return ans; +} + +char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit) { + if (eight_bit) + return xescape_full(str, "", console_width, true); + else + return utf8_escape_non_printable_full(str, console_width); +} + +char *octescape(const char *s, size_t len) { + char *r, *t; + const char *f; + + /* Escapes all chars in bad, in addition to \ and " chars, + * in \nnn style escaping. */ + + r = new(char, len * 4 + 1); + if (!r) + return NULL; + + for (f = s, t = r; f < s + len; f++) { + + if (*f < ' ' || *f >= 127 || IN_SET(*f, '\\', '"')) { + *(t++) = '\\'; + *(t++) = '0' + (*f >> 6); + *(t++) = '0' + ((*f >> 3) & 8); + *(t++) = '0' + (*f & 8); + } else + *(t++) = *f; + } + + *t = 0; + + return r; + +} + +static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad, bool escape_tab_nl) { + assert(bad); + + for (; *s; s++) { + if (escape_tab_nl && IN_SET(*s, '\n', '\t')) { + *(t++) = '\\'; + *(t++) = *s == '\n' ? 'n' : 't'; + continue; + } + + if (*s == '\\' || strchr(bad, *s)) + *(t++) = '\\'; + + *(t++) = *s; + } + + return t; +} + +char *shell_escape(const char *s, const char *bad) { + char *r, *t; + + r = new(char, strlen(s)*2+1); + if (!r) + return NULL; + + t = strcpy_backslash_escaped(r, s, bad, false); + *t = 0; + + return r; +} + +char* shell_maybe_quote(const char *s, EscapeStyle style) { + const char *p; + char *r, *t; + + assert(s); + + /* Encloses a string in quotes if necessary to make it OK as a shell + * string. Note that we treat benign UTF-8 characters as needing + * escaping too, but that should be OK. */ + + for (p = s; *p; p++) + if (*p <= ' ' || + *p >= 127 || + strchr(SHELL_NEED_QUOTES, *p)) + break; + + if (!*p) + return strdup(s); + + r = new(char, (style == ESCAPE_POSIX) + 1 + strlen(s)*2 + 1 + 1); + if (!r) + return NULL; + + t = r; + if (style == ESCAPE_BACKSLASH) + *(t++) = '"'; + else if (style == ESCAPE_POSIX) { + *(t++) = '$'; + *(t++) = '\''; + } else + assert_not_reached("Bad EscapeStyle"); + + t = mempcpy(t, s, p - s); + + if (style == ESCAPE_BACKSLASH) + t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE, false); + else + t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE_POSIX, true); + + if (style == ESCAPE_BACKSLASH) + *(t++) = '"'; + else + *(t++) = '\''; + *t = 0; + + return r; +} diff --git a/src/basic/escape.h b/src/basic/escape.h new file mode 100644 index 00000000..b26054c5 --- /dev/null +++ b/src/basic/escape.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include + +#include "string-util.h" +#include "missing_type.h" + +/* What characters are special in the shell? */ +/* must be escaped outside and inside double-quotes */ +#define SHELL_NEED_ESCAPE "\"\\`$" + +/* Those that can be escaped or double-quoted. + * + * Stricly speaking, ! does not need to be escaped, except in interactive + * mode, but let's be extra nice to the user and quote ! in case this + * output is ever used in interactive mode. */ +#define SHELL_NEED_QUOTES SHELL_NEED_ESCAPE GLOB_CHARS "'()<>|&;!" + +/* Note that we assume control characters would need to be escaped too in + * addition to the "special" characters listed here, if they appear in the + * string. Current users disallow control characters. Also '"' shall not + * be escaped. + */ +#define SHELL_NEED_ESCAPE_POSIX "\\\'" + +typedef enum UnescapeFlags { + UNESCAPE_RELAX = 1, +} UnescapeFlags; + +typedef enum EscapeStyle { + ESCAPE_BACKSLASH = 1, + ESCAPE_POSIX = 2, +} EscapeStyle; + +char *cescape(const char *s); +char *cescape_length(const char *s, size_t n); +int cescape_char(char c, char *buf); + +int cunescape(const char *s, UnescapeFlags flags, char **ret); +int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret); +int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret); +int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit); + +char *xescape_full(const char *s, const char *bad, size_t console_width, bool eight_bits); +static inline char *xescape(const char *s, const char *bad) { + return xescape_full(s, bad, SIZE_MAX, false); +} +char *octescape(const char *s, size_t len); +char *escape_non_printable_full(const char *str, size_t console_width, bool eight_bit); + +char *shell_escape(const char *s, const char *bad); +char* shell_maybe_quote(const char *s, EscapeStyle style); diff --git a/src/basic/ether-addr-util.c b/src/basic/ether-addr-util.c new file mode 100644 index 00000000..e875696a --- /dev/null +++ b/src/basic/ether-addr-util.c @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "ether-addr-util.h" +#include "macro.h" +#include "string-util.h" + +char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) { + assert(addr); + assert(buffer); + + /* Like ether_ntoa() but uses %02x instead of %x to print + * ethernet addresses, which makes them look less funny. Also, + * doesn't use a static buffer. */ + + sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", + addr->ether_addr_octet[0], + addr->ether_addr_octet[1], + addr->ether_addr_octet[2], + addr->ether_addr_octet[3], + addr->ether_addr_octet[4], + addr->ether_addr_octet[5]); + + return buffer; +} + +int ether_addr_compare(const struct ether_addr *a, const struct ether_addr *b) { + return memcmp(a, b, ETH_ALEN); +} + +static void ether_addr_hash_func(const struct ether_addr *p, struct siphash *state) { + siphash24_compress(p, sizeof(struct ether_addr), state); +} + +DEFINE_HASH_OPS(ether_addr_hash_ops, struct ether_addr, ether_addr_hash_func, ether_addr_compare); + +int ether_addr_from_string(const char *s, struct ether_addr *ret) { + size_t pos = 0, n, field; + char sep = '\0'; + const char *hex = HEXDIGITS, *hexoff; + size_t x; + bool touched; + +#define parse_fields(v) \ + for (field = 0; field < ELEMENTSOF(v); field++) { \ + touched = false; \ + for (n = 0; n < (2 * sizeof(v[0])); n++) { \ + if (s[pos] == '\0') \ + break; \ + hexoff = strchr(hex, s[pos]); \ + if (!hexoff) \ + break; \ + assert(hexoff >= hex); \ + x = hexoff - hex; \ + if (x >= 16) \ + x -= 6; /* A-F */ \ + assert(x < 16); \ + touched = true; \ + v[field] <<= 4; \ + v[field] += x; \ + pos++; \ + } \ + if (!touched) \ + return -EINVAL; \ + if (field < (ELEMENTSOF(v)-1)) { \ + if (s[pos] != sep) \ + return -EINVAL; \ + else \ + pos++; \ + } \ + } + + assert(s); + assert(ret); + + s += strspn(s, WHITESPACE); + sep = s[strspn(s, hex)]; + + if (sep == '.') { + uint16_t shorts[3] = { 0 }; + + parse_fields(shorts); + + if (s[pos] != '\0') + return -EINVAL; + + for (n = 0; n < ELEMENTSOF(shorts); n++) { + ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8); + ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff); + } + + } else if (IN_SET(sep, ':', '-')) { + struct ether_addr out = ETHER_ADDR_NULL; + + parse_fields(out.ether_addr_octet); + + if (s[pos] != '\0') + return -EINVAL; + + for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++) + ret->ether_addr_octet[n] = out.ether_addr_octet[n]; + + } else + return -EINVAL; + + return 0; +} diff --git a/src/basic/ether-addr-util.h b/src/basic/ether-addr-util.h new file mode 100644 index 00000000..4e44b30b --- /dev/null +++ b/src/basic/ether-addr-util.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "hash-funcs.h" + +#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X" +#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5] + +#define ETHER_ADDR_TO_STRING_MAX (3*6) +char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]); + +int ether_addr_compare(const struct ether_addr *a, const struct ether_addr *b); +static inline bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) { + return ether_addr_compare(a, b) == 0; +} + +#define ETHER_ADDR_NULL ((const struct ether_addr){}) + +static inline bool ether_addr_is_null(const struct ether_addr *addr) { + return ether_addr_equal(addr, ÐER_ADDR_NULL); +} + +int ether_addr_from_string(const char *s, struct ether_addr *ret); + +extern const struct hash_ops ether_addr_hash_ops; diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c new file mode 100644 index 00000000..d7c215cb --- /dev/null +++ b/src/basic/extract-word.c @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "escape.h" +#include "extract-word.h" +#include "log.h" +#include "macro.h" +#include "string-util.h" +#include "utf8.h" + +int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) { + _cleanup_free_ char *s = NULL; + size_t allocated = 0, sz = 0; + char c; + int r; + + char quote = 0; /* 0 or ' or " */ + bool backslash = false; /* whether we've just seen a backslash */ + + assert(p); + assert(ret); + + /* Bail early if called after last value or with no input */ + if (!*p) + goto finish; + c = **p; + + if (!separators) + separators = WHITESPACE; + + /* Parses the first word of a string, and returns it in + * *ret. Removes all quotes in the process. When parsing fails + * (because of an uneven number of quotes or similar), leaves + * the pointer *p at the first invalid character. */ + + if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) + if (!GREEDY_REALLOC(s, allocated, sz+1)) + return -ENOMEM; + + for (;; (*p)++, c = **p) { + if (c == 0) + goto finish_force_terminate; + else if (strchr(separators, c)) { + if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { + (*p)++; + goto finish_force_next; + } + } else { + /* We found a non-blank character, so we will always + * want to return a string (even if it is empty), + * allocate it here. */ + if (!GREEDY_REALLOC(s, allocated, sz+1)) + return -ENOMEM; + break; + } + } + + for (;; (*p)++, c = **p) { + if (backslash) { + if (!GREEDY_REALLOC(s, allocated, sz+7)) + return -ENOMEM; + + if (c == 0) { + if ((flags & EXTRACT_CUNESCAPE_RELAX) && + (!quote || flags & EXTRACT_RELAX)) { + /* If we find an unquoted trailing backslash and we're in + * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the + * output. + * + * Unbalanced quotes will only be allowed in EXTRACT_RELAX + * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them. + */ + s[sz++] = '\\'; + goto finish_force_terminate; + } + if (flags & EXTRACT_RELAX) + goto finish_force_terminate; + return -EINVAL; + } + + if (flags & EXTRACT_CUNESCAPE) { + bool eight_bit = false; + char32_t u; + + r = cunescape_one(*p, (size_t) -1, &u, &eight_bit); + if (r < 0) { + if (flags & EXTRACT_CUNESCAPE_RELAX) { + s[sz++] = '\\'; + s[sz++] = c; + } else + return -EINVAL; + } else { + (*p) += r - 1; + + if (eight_bit) + s[sz++] = u; + else + sz += utf8_encode_unichar(s + sz, u); + } + } else + s[sz++] = c; + + backslash = false; + + } else if (quote) { /* inside either single or double quotes */ + for (;; (*p)++, c = **p) { + if (c == 0) { + if (flags & EXTRACT_RELAX) + goto finish_force_terminate; + return -EINVAL; + } else if (c == quote) { /* found the end quote */ + quote = 0; + break; + } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) { + backslash = true; + break; + } else { + if (!GREEDY_REALLOC(s, allocated, sz+2)) + return -ENOMEM; + + s[sz++] = c; + } + } + + } else { + for (;; (*p)++, c = **p) { + if (c == 0) + goto finish_force_terminate; + else if (IN_SET(c, '\'', '"') && (flags & EXTRACT_UNQUOTE)) { + quote = c; + break; + } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) { + backslash = true; + break; + } else if (strchr(separators, c)) { + if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { + (*p)++; + goto finish_force_next; + } + /* Skip additional coalesced separators. */ + for (;; (*p)++, c = **p) { + if (c == 0) + goto finish_force_terminate; + if (!strchr(separators, c)) + break; + } + goto finish; + + } else { + if (!GREEDY_REALLOC(s, allocated, sz+2)) + return -ENOMEM; + + s[sz++] = c; + } + } + } + } + +finish_force_terminate: + *p = NULL; +finish: + if (!s) { + *p = NULL; + *ret = NULL; + return 0; + } + +finish_force_next: + s[sz] = 0; + *ret = TAKE_PTR(s); + + return 1; +} + +int extract_first_word_and_warn( + const char **p, + char **ret, + const char *separators, + ExtractFlags flags, + const char *unit, + const char *filename, + unsigned line, + const char *rvalue) { + + /* Try to unquote it, if it fails, warn about it and try again + * but this time using EXTRACT_CUNESCAPE_RELAX to keep the + * backslashes verbatim in invalid escape sequences. */ + + const char *save; + int r; + + save = *p; + r = extract_first_word(p, ret, separators, flags); + if (r >= 0) + return r; + + if (r == -EINVAL && !(flags & EXTRACT_CUNESCAPE_RELAX)) { + + /* Retry it with EXTRACT_CUNESCAPE_RELAX. */ + *p = save; + r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX); + if (r >= 0) { + /* It worked this time, hence it must have been an invalid escape sequence. */ + log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Ignoring unknown escape sequences: \"%s\"", *ret); + return r; + } + + /* If it's still EINVAL; then it must be unbalanced quoting, report this. */ + if (r == -EINVAL) + return log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting, ignoring: \"%s\"", rvalue); + } + + /* Can be any error, report it */ + return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue); +} + +/* We pass ExtractFlags as unsigned int (to avoid undefined behaviour when passing + * an object that undergoes default argument promotion as an argument to va_start). + * Let's make sure that ExtractFlags fits into an unsigned int. */ +assert_cc(sizeof(enum ExtractFlags) <= sizeof(unsigned)); + +int extract_many_words(const char **p, const char *separators, unsigned flags, ...) { + va_list ap; + char **l; + int n = 0, i, c, r; + + /* Parses a number of words from a string, stripping any + * quotes if necessary. */ + + assert(p); + + /* Count how many words are expected */ + va_start(ap, flags); + for (;;) { + if (!va_arg(ap, char **)) + break; + n++; + } + va_end(ap); + + if (n <= 0) + return 0; + + /* Read all words into a temporary array */ + l = newa0(char*, n); + for (c = 0; c < n; c++) { + + r = extract_first_word(p, &l[c], separators, flags); + if (r < 0) { + int j; + + for (j = 0; j < c; j++) + free(l[j]); + + return r; + } + + if (r == 0) + break; + } + + /* If we managed to parse all words, return them in the passed + * in parameters */ + va_start(ap, flags); + for (i = 0; i < n; i++) { + char **v; + + v = va_arg(ap, char **); + assert(v); + + *v = l[i]; + } + va_end(ap); + + return c; +} diff --git a/src/basic/extract-word.h b/src/basic/extract-word.h new file mode 100644 index 00000000..e2d43389 --- /dev/null +++ b/src/basic/extract-word.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "macro.h" + +typedef enum ExtractFlags { + EXTRACT_RELAX = 1 << 0, + EXTRACT_CUNESCAPE = 1 << 1, + EXTRACT_CUNESCAPE_RELAX = 1 << 2, + EXTRACT_UNQUOTE = 1 << 3, + EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 4, + EXTRACT_RETAIN_ESCAPE = 1 << 5, +} ExtractFlags; + +int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags); +int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue); +int extract_many_words(const char **p, const char *separators, unsigned flags, ...) _sentinel_; diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c new file mode 100644 index 00000000..4be876e2 --- /dev/null +++ b/src/basic/fd-util.c @@ -0,0 +1,978 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "copy.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "io-util.h" +#include "macro.h" +#include "memfd-util.h" +#include "missing_fcntl.h" +#include "missing_syscall.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "util.h" +#include "tmpfile-util.h" + +/* The maximum number of iterations in the loop to close descriptors in the fallback case + * when /proc/self/fd/ is inaccessible. */ +#define MAX_FD_LOOP_LIMIT (1024*1024) + +int close_nointr(int fd) { + assert(fd >= 0); + + if (close(fd) >= 0) + return 0; + + /* + * Just ignore EINTR; a retry loop is the wrong thing to do on + * Linux. + * + * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html + * https://bugzilla.gnome.org/show_bug.cgi?id=682819 + * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR + * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain + */ + if (errno == EINTR) + return 0; + + return -errno; +} + +int safe_close(int fd) { + + /* + * Like close_nointr() but cannot fail. Guarantees errno is + * unchanged. Is a NOP with negative fds passed, and returns + * -1, so that it can be used in this syntax: + * + * fd = safe_close(fd); + */ + + if (fd >= 0) { + PROTECT_ERRNO; + + /* The kernel might return pretty much any error code + * via close(), but the fd will be closed anyway. The + * only condition we want to check for here is whether + * the fd was invalid at all... */ + + assert_se(close_nointr(fd) != -EBADF); + } + + return -1; +} + +void safe_close_pair(int p[static 2]) { + assert(p); + + if (p[0] == p[1]) { + /* Special case pairs which use the same fd in both + * directions... */ + p[0] = p[1] = safe_close(p[0]); + return; + } + + p[0] = safe_close(p[0]); + p[1] = safe_close(p[1]); +} + +void close_many(const int fds[], size_t n_fd) { + size_t i; + + assert(fds || n_fd <= 0); + + for (i = 0; i < n_fd; i++) + safe_close(fds[i]); +} + +int fclose_nointr(FILE *f) { + assert(f); + + /* Same as close_nointr(), but for fclose() */ + + if (fclose(f) == 0) + return 0; + + if (errno == EINTR) + return 0; + + return -errno; +} + +FILE* safe_fclose(FILE *f) { + + /* Same as safe_close(), but for fclose() */ + + if (f) { + PROTECT_ERRNO; + + assert_se(fclose_nointr(f) != -EBADF); + } + + return NULL; +} + +DIR* safe_closedir(DIR *d) { + + if (d) { + PROTECT_ERRNO; + + assert_se(closedir(d) >= 0 || errno != EBADF); + } + + return NULL; +} + +int fd_nonblock(int fd, bool nonblock) { + int flags, nflags; + + assert(fd >= 0); + + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) + return -errno; + + if (nonblock) + nflags = flags | O_NONBLOCK; + else + nflags = flags & ~O_NONBLOCK; + + if (nflags == flags) + return 0; + + if (fcntl(fd, F_SETFL, nflags) < 0) + return -errno; + + return 0; +} + +int fd_cloexec(int fd, bool cloexec) { + int flags, nflags; + + assert(fd >= 0); + + flags = fcntl(fd, F_GETFD, 0); + if (flags < 0) + return -errno; + + if (cloexec) + nflags = flags | FD_CLOEXEC; + else + nflags = flags & ~FD_CLOEXEC; + + if (nflags == flags) + return 0; + + if (fcntl(fd, F_SETFD, nflags) < 0) + return -errno; + + return 0; +} + +_pure_ static bool fd_in_set(int fd, const int fdset[], size_t n_fdset) { + size_t i; + + assert(n_fdset == 0 || fdset); + + for (i = 0; i < n_fdset; i++) + if (fdset[i] == fd) + return true; + + return false; +} + +static int get_max_fd(void) { + struct rlimit rl; + rlim_t m; + + /* Return the highest possible fd, based RLIMIT_NOFILE, but enforcing FD_SETSIZE-1 as lower boundary + * and INT_MAX as upper boundary. */ + + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) + return -errno; + + m = MAX(rl.rlim_cur, rl.rlim_max); + if (m < FD_SETSIZE) /* Let's always cover at least 1024 fds */ + return FD_SETSIZE-1; + + if (m == RLIM_INFINITY || m > INT_MAX) /* Saturate on overflow. After all fds are "int", hence can + * never be above INT_MAX */ + return INT_MAX; + + return (int) (m - 1); +} + +int close_all_fds(const int except[], size_t n_except) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r = 0; + + assert(n_except == 0 || except); + + d = opendir("/proc/self/fd"); + if (!d) { + int fd, max_fd; + + /* When /proc isn't available (for example in chroots) the fallback is brute forcing through + * the fd table */ + + max_fd = get_max_fd(); + if (max_fd < 0) + return max_fd; + + /* Refuse to do the loop over more too many elements. It's better to fail immediately than to + * spin the CPU for a long time. */ + if (max_fd > MAX_FD_LOOP_LIMIT) + return log_debug_errno(SYNTHETIC_ERRNO(EPERM), + "/proc/self/fd is inaccessible. Refusing to loop over %d potential fds.", + max_fd); + + for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) { + int q; + + if (fd_in_set(fd, except, n_except)) + continue; + + q = close_nointr(fd); + if (q < 0 && q != -EBADF && r >= 0) + r = q; + } + + return r; + } + + FOREACH_DIRENT(de, d, return -errno) { + int fd = -1, q; + + if (safe_atoi(de->d_name, &fd) < 0) + /* Let's better ignore this, just in case */ + continue; + + if (fd < 3) + continue; + + if (fd == dirfd(d)) + continue; + + if (fd_in_set(fd, except, n_except)) + continue; + + q = close_nointr(fd); + if (q < 0 && q != -EBADF && r >= 0) /* Valgrind has its own FD and doesn't want to have it closed */ + r = q; + } + + return r; +} + +int same_fd(int a, int b) { + struct stat sta, stb; + pid_t pid; + int r, fa, fb; + + assert(a >= 0); + assert(b >= 0); + + /* Compares two file descriptors. Note that semantics are + * quite different depending on whether we have kcmp() or we + * don't. If we have kcmp() this will only return true for + * dup()ed file descriptors, but not otherwise. If we don't + * have kcmp() this will also return true for two fds of the same + * file, created by separate open() calls. Since we use this + * call mostly for filtering out duplicates in the fd store + * this difference hopefully doesn't matter too much. */ + + if (a == b) + return true; + + /* Try to use kcmp() if we have it. */ + pid = getpid_cached(); + r = kcmp(pid, pid, KCMP_FILE, a, b); + if (r == 0) + return true; + if (r > 0) + return false; + if (!IN_SET(errno, ENOSYS, EACCES, EPERM)) + return -errno; + + /* We don't have kcmp(), use fstat() instead. */ + if (fstat(a, &sta) < 0) + return -errno; + + if (fstat(b, &stb) < 0) + return -errno; + + if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT)) + return false; + + /* We consider all device fds different, since two device fds + * might refer to quite different device contexts even though + * they share the same inode and backing dev_t. */ + + if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode)) + return false; + + if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino) + return false; + + /* The fds refer to the same inode on disk, let's also check + * if they have the same fd flags. This is useful to + * distinguish the read and write side of a pipe created with + * pipe(). */ + fa = fcntl(a, F_GETFL); + if (fa < 0) + return -errno; + + fb = fcntl(b, F_GETFL); + if (fb < 0) + return -errno; + + return fa == fb; +} + +void cmsg_close_all(struct msghdr *mh) { + struct cmsghdr *cmsg; + + assert(mh); + + CMSG_FOREACH(cmsg, mh) + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) + close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int)); +} + +bool fdname_is_valid(const char *s) { + const char *p; + + /* Validates a name for $LISTEN_FDNAMES. We basically allow + * everything ASCII that's not a control character. Also, as + * special exception the ":" character is not allowed, as we + * use that as field separator in $LISTEN_FDNAMES. + * + * Note that the empty string is explicitly allowed + * here. However, we limit the length of the names to 255 + * characters. */ + + if (!s) + return false; + + for (p = s; *p; p++) { + if (*p < ' ') + return false; + if (*p >= 127) + return false; + if (*p == ':') + return false; + } + + return p - s < 256; +} + +int fd_get_path(int fd, char **ret) { + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + int r; + + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + r = readlink_malloc(procfs_path, ret); + if (r == -ENOENT) { + /* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make + * things debuggable and distinguish the two. */ + + if (access("/proc/self/fd/", F_OK) < 0) + /* /proc is not available or not set up properly, we're most likely in some chroot + * environment. */ + return errno == ENOENT ? -EOPNOTSUPP : -errno; + + return -EBADF; /* The directory exists, hence it's the fd that doesn't. */ + } + + return r; +} + +int move_fd(int from, int to, int cloexec) { + int r; + + /* Move fd 'from' to 'to', make sure FD_CLOEXEC remains equal if requested, and release the old fd. If + * 'cloexec' is passed as -1, the original FD_CLOEXEC is inherited for the new fd. If it is 0, it is turned + * off, if it is > 0 it is turned on. */ + + if (from < 0) + return -EBADF; + if (to < 0) + return -EBADF; + + if (from == to) { + + if (cloexec >= 0) { + r = fd_cloexec(to, cloexec); + if (r < 0) + return r; + } + + return to; + } + + if (cloexec < 0) { + int fl; + + fl = fcntl(from, F_GETFD, 0); + if (fl < 0) + return -errno; + + cloexec = !!(fl & FD_CLOEXEC); + } + + r = dup3(from, to, cloexec ? O_CLOEXEC : 0); + if (r < 0) + return -errno; + + assert(r == to); + + safe_close(from); + + return to; +} + +int acquire_data_fd(const void *data, size_t size, unsigned flags) { + + _cleanup_close_pair_ int pipefds[2] = { -1, -1 }; + char pattern[] = "/dev/shm/data-fd-XXXXXX"; + _cleanup_close_ int fd = -1; + int isz = 0, r; + ssize_t n; + off_t f; + + assert(data || size == 0); + + /* Acquire a read-only file descriptor that when read from returns the specified data. This is much more + * complex than I wish it was. But here's why: + * + * a) First we try to use memfds. They are the best option, as we can seal them nicely to make them + * read-only. Unfortunately they require kernel 3.17, and – at the time of writing – we still support 3.14. + * + * b) Then, we try classic pipes. They are the second best options, as we can close the writing side, retaining + * a nicely read-only fd in the reading side. However, they are by default quite small, and unprivileged + * clients can only bump their size to a system-wide limit, which might be quite low. + * + * c) Then, we try an O_TMPFILE file in /dev/shm (that dir is the only suitable one known to exist from + * earliest boot on). To make it read-only we open the fd a second time with O_RDONLY via + * /proc/self/. Unfortunately O_TMPFILE is not available on older kernels on tmpfs. + * + * d) Finally, we try creating a regular file in /dev/shm, which we then delete. + * + * It sucks a bit that depending on the situation we return very different objects here, but that's Linux I + * figure. */ + + if (size == 0 && ((flags & ACQUIRE_NO_DEV_NULL) == 0)) { + /* As a special case, return /dev/null if we have been called for an empty data block */ + r = open("/dev/null", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (r < 0) + return -errno; + + return r; + } + + if ((flags & ACQUIRE_NO_MEMFD) == 0) { + fd = memfd_new("data-fd"); + if (fd < 0) + goto try_pipe; + + n = write(fd, data, size); + if (n < 0) + return -errno; + if ((size_t) n != size) + return -EIO; + + f = lseek(fd, 0, SEEK_SET); + if (f != 0) + return -errno; + + r = memfd_set_sealed(fd); + if (r < 0) + return r; + + return TAKE_FD(fd); + } + +try_pipe: + if ((flags & ACQUIRE_NO_PIPE) == 0) { + if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0) + return -errno; + + isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0); + if (isz < 0) + return -errno; + + if ((size_t) isz < size) { + isz = (int) size; + if (isz < 0 || (size_t) isz != size) + return -E2BIG; + + /* Try to bump the pipe size */ + (void) fcntl(pipefds[1], F_SETPIPE_SZ, isz); + + /* See if that worked */ + isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0); + if (isz < 0) + return -errno; + + if ((size_t) isz < size) + goto try_dev_shm; + } + + n = write(pipefds[1], data, size); + if (n < 0) + return -errno; + if ((size_t) n != size) + return -EIO; + + (void) fd_nonblock(pipefds[0], false); + + return TAKE_FD(pipefds[0]); + } + +try_dev_shm: + if ((flags & ACQUIRE_NO_TMPFILE) == 0) { + fd = open("/dev/shm", O_RDWR|O_TMPFILE|O_CLOEXEC, 0500); + if (fd < 0) + goto try_dev_shm_without_o_tmpfile; + + n = write(fd, data, size); + if (n < 0) + return -errno; + if ((size_t) n != size) + return -EIO; + + /* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */ + return fd_reopen(fd, O_RDONLY|O_CLOEXEC); + } + +try_dev_shm_without_o_tmpfile: + if ((flags & ACQUIRE_NO_REGULAR) == 0) { + fd = mkostemp_safe(pattern); + if (fd < 0) + return fd; + + n = write(fd, data, size); + if (n < 0) { + r = -errno; + goto unlink_and_return; + } + if ((size_t) n != size) { + r = -EIO; + goto unlink_and_return; + } + + /* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */ + r = open(pattern, O_RDONLY|O_CLOEXEC); + if (r < 0) + r = -errno; + + unlink_and_return: + (void) unlink(pattern); + return r; + } + + return -EOPNOTSUPP; +} + +/* When the data is smaller or equal to 64K, try to place the copy in a memfd/pipe */ +#define DATA_FD_MEMORY_LIMIT (64U*1024U) + +/* If memfd/pipe didn't work out, then let's use a file in /tmp up to a size of 1M. If it's large than that use /var/tmp instead. */ +#define DATA_FD_TMP_LIMIT (1024U*1024U) + +int fd_duplicate_data_fd(int fd) { + + _cleanup_close_ int copy_fd = -1, tmp_fd = -1; + _cleanup_free_ void *remains = NULL; + size_t remains_size = 0; + const char *td; + struct stat st; + int r; + + /* Creates a 'data' fd from the specified source fd, containing all the same data in a read-only fashion, but + * independent of it (i.e. the source fd can be closed and unmounted after this call succeeded). Tries to be + * somewhat smart about where to place the data. In the best case uses a memfd(). If memfd() are not supported + * uses a pipe instead. For larger data will use an unlinked file in /tmp, and for even larger data one in + * /var/tmp. */ + + if (fstat(fd, &st) < 0) + return -errno; + + /* For now, let's only accept regular files, sockets, pipes and char devices */ + if (S_ISDIR(st.st_mode)) + return -EISDIR; + if (S_ISLNK(st.st_mode)) + return -ELOOP; + if (!S_ISREG(st.st_mode) && !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode) && !S_ISCHR(st.st_mode)) + return -EBADFD; + + /* If we have reason to believe the data is bounded in size, then let's use memfds or pipes as backing fd. Note + * that we use the reported regular file size only as a hint, given that there are plenty special files in + * /proc and /sys which report a zero file size but can be read from. */ + + if (!S_ISREG(st.st_mode) || st.st_size < DATA_FD_MEMORY_LIMIT) { + + /* Try a memfd first */ + copy_fd = memfd_new("data-fd"); + if (copy_fd >= 0) { + off_t f; + + r = copy_bytes(fd, copy_fd, DATA_FD_MEMORY_LIMIT, 0); + if (r < 0) + return r; + + f = lseek(copy_fd, 0, SEEK_SET); + if (f != 0) + return -errno; + + if (r == 0) { + /* Did it fit into the limit? If so, we are done. */ + r = memfd_set_sealed(copy_fd); + if (r < 0) + return r; + + return TAKE_FD(copy_fd); + } + + /* Hmm, pity, this didn't fit. Let's fall back to /tmp then, see below */ + + } else { + _cleanup_(close_pairp) int pipefds[2] = { -1, -1 }; + int isz; + + /* If memfds aren't available, use a pipe. Set O_NONBLOCK so that we will get EAGAIN rather + * then block indefinitely when we hit the pipe size limit */ + + if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0) + return -errno; + + isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0); + if (isz < 0) + return -errno; + + /* Try to enlarge the pipe size if necessary */ + if ((size_t) isz < DATA_FD_MEMORY_LIMIT) { + + (void) fcntl(pipefds[1], F_SETPIPE_SZ, DATA_FD_MEMORY_LIMIT); + + isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0); + if (isz < 0) + return -errno; + } + + if ((size_t) isz >= DATA_FD_MEMORY_LIMIT) { + + r = copy_bytes_full(fd, pipefds[1], DATA_FD_MEMORY_LIMIT, 0, &remains, &remains_size, NULL, NULL); + if (r < 0 && r != -EAGAIN) + return r; /* If we get EAGAIN it could be because of the source or because of + * the destination fd, we can't know, as sendfile() and friends won't + * tell us. Hence, treat this as reason to fall back, just to be + * sure. */ + if (r == 0) { + /* Everything fit in, yay! */ + (void) fd_nonblock(pipefds[0], false); + + return TAKE_FD(pipefds[0]); + } + + /* Things didn't fit in. But we read data into the pipe, let's remember that, so that + * when writing the new file we incorporate this first. */ + copy_fd = TAKE_FD(pipefds[0]); + } + } + } + + /* If we have reason to believe this will fit fine in /tmp, then use that as first fallback. */ + if ((!S_ISREG(st.st_mode) || st.st_size < DATA_FD_TMP_LIMIT) && + (DATA_FD_MEMORY_LIMIT + remains_size) < DATA_FD_TMP_LIMIT) { + off_t f; + + tmp_fd = open_tmpfile_unlinkable(NULL /* NULL as directory means /tmp */, O_RDWR|O_CLOEXEC); + if (tmp_fd < 0) + return tmp_fd; + + if (copy_fd >= 0) { + /* If we tried a memfd/pipe first and it ended up being too large, then copy this into the + * temporary file first. */ + + r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, 0); + if (r < 0) + return r; + + assert(r == 0); + } + + if (remains_size > 0) { + /* If there were remaining bytes (i.e. read into memory, but not written out yet) from the + * failed copy operation, let's flush them out next. */ + + r = loop_write(tmp_fd, remains, remains_size, false); + if (r < 0) + return r; + } + + r = copy_bytes(fd, tmp_fd, DATA_FD_TMP_LIMIT - DATA_FD_MEMORY_LIMIT - remains_size, COPY_REFLINK); + if (r < 0) + return r; + if (r == 0) + goto finish; /* Yay, it fit in */ + + /* It didn't fit in. Let's not forget to use what we already used */ + f = lseek(tmp_fd, 0, SEEK_SET); + if (f != 0) + return -errno; + + safe_close(copy_fd); + copy_fd = TAKE_FD(tmp_fd); + + remains = mfree(remains); + remains_size = 0; + } + + /* As last fallback use /var/tmp */ + r = var_tmp_dir(&td); + if (r < 0) + return r; + + tmp_fd = open_tmpfile_unlinkable(td, O_RDWR|O_CLOEXEC); + if (tmp_fd < 0) + return tmp_fd; + + if (copy_fd >= 0) { + /* If we tried a memfd/pipe first, or a file in /tmp, and it ended up being too large, than copy this + * into the temporary file first. */ + r = copy_bytes(copy_fd, tmp_fd, UINT64_MAX, COPY_REFLINK); + if (r < 0) + return r; + + assert(r == 0); + } + + if (remains_size > 0) { + /* Then, copy in any read but not yet written bytes. */ + r = loop_write(tmp_fd, remains, remains_size, false); + if (r < 0) + return r; + } + + /* Copy in the rest */ + r = copy_bytes(fd, tmp_fd, UINT64_MAX, COPY_REFLINK); + if (r < 0) + return r; + + assert(r == 0); + +finish: + /* Now convert the O_RDWR file descriptor into an O_RDONLY one (and as side effect seek to the beginning of the + * file again */ + + return fd_reopen(tmp_fd, O_RDONLY|O_CLOEXEC); +} + +int fd_move_above_stdio(int fd) { + int flags, copy; + PROTECT_ERRNO; + + /* Moves the specified file descriptor if possible out of the range [0…2], i.e. the range of + * stdin/stdout/stderr. If it can't be moved outside of this range the original file descriptor is + * returned. This call is supposed to be used for long-lasting file descriptors we allocate in our code that + * might get loaded into foreign code, and where we want ensure our fds are unlikely used accidentally as + * stdin/stdout/stderr of unrelated code. + * + * Note that this doesn't fix any real bugs, it just makes it less likely that our code will be affected by + * buggy code from others that mindlessly invokes 'fprintf(stderr, …' or similar in places where stderr has + * been closed before. + * + * This function is written in a "best-effort" and "least-impact" style. This means whenever we encounter an + * error we simply return the original file descriptor, and we do not touch errno. */ + + if (fd < 0 || fd > 2) + return fd; + + flags = fcntl(fd, F_GETFD, 0); + if (flags < 0) + return fd; + + if (flags & FD_CLOEXEC) + copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); + else + copy = fcntl(fd, F_DUPFD, 3); + if (copy < 0) + return fd; + + assert(copy > 2); + + (void) close(fd); + return copy; +} + +int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd) { + + int fd[3] = { /* Put together an array of fds we work on */ + original_input_fd, + original_output_fd, + original_error_fd + }; + + int r, i, + null_fd = -1, /* if we open /dev/null, we store the fd to it here */ + copy_fd[3] = { -1, -1, -1 }; /* This contains all fds we duplicate here temporarily, and hence need to close at the end */ + bool null_readable, null_writable; + + /* Sets up stdin, stdout, stderr with the three file descriptors passed in. If any of the descriptors is + * specified as -1 it will be connected with /dev/null instead. If any of the file descriptors is passed as + * itself (e.g. stdin as STDIN_FILENO) it is left unmodified, but the O_CLOEXEC bit is turned off should it be + * on. + * + * Note that if any of the passed file descriptors are > 2 they will be closed — both on success and on + * failure! Thus, callers should assume that when this function returns the input fds are invalidated. + * + * Note that when this function fails stdin/stdout/stderr might remain half set up! + * + * O_CLOEXEC is turned off for all three file descriptors (which is how it should be for + * stdin/stdout/stderr). */ + + null_readable = original_input_fd < 0; + null_writable = original_output_fd < 0 || original_error_fd < 0; + + /* First step, open /dev/null once, if we need it */ + if (null_readable || null_writable) { + + /* Let's open this with O_CLOEXEC first, and convert it to non-O_CLOEXEC when we move the fd to the final position. */ + null_fd = open("/dev/null", (null_readable && null_writable ? O_RDWR : + null_readable ? O_RDONLY : O_WRONLY) | O_CLOEXEC); + if (null_fd < 0) { + r = -errno; + goto finish; + } + + /* If this fd is in the 0…2 range, let's move it out of it */ + if (null_fd < 3) { + int copy; + + copy = fcntl(null_fd, F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */ + if (copy < 0) { + r = -errno; + goto finish; + } + + safe_close(null_fd); + null_fd = copy; + } + } + + /* Let's assemble fd[] with the fds to install in place of stdin/stdout/stderr */ + for (i = 0; i < 3; i++) { + + if (fd[i] < 0) + fd[i] = null_fd; /* A negative parameter means: connect this one to /dev/null */ + else if (fd[i] != i && fd[i] < 3) { + /* This fd is in the 0…2 territory, but not at its intended place, move it out of there, so that we can work there. */ + copy_fd[i] = fcntl(fd[i], F_DUPFD_CLOEXEC, 3); /* Duplicate this with O_CLOEXEC set */ + if (copy_fd[i] < 0) { + r = -errno; + goto finish; + } + + fd[i] = copy_fd[i]; + } + } + + /* At this point we now have the fds to use in fd[], and they are all above the stdio range, so that we + * have freedom to move them around. If the fds already were at the right places then the specific fds are + * -1. Let's now move them to the right places. This is the point of no return. */ + for (i = 0; i < 3; i++) { + + if (fd[i] == i) { + + /* fd is already in place, but let's make sure O_CLOEXEC is off */ + r = fd_cloexec(i, false); + if (r < 0) + goto finish; + + } else { + assert(fd[i] > 2); + + if (dup2(fd[i], i) < 0) { /* Turns off O_CLOEXEC on the new fd. */ + r = -errno; + goto finish; + } + } + } + + r = 0; + +finish: + /* Close the original fds, but only if they were outside of the stdio range. Also, properly check for the same + * fd passed in multiple times. */ + safe_close_above_stdio(original_input_fd); + if (original_output_fd != original_input_fd) + safe_close_above_stdio(original_output_fd); + if (original_error_fd != original_input_fd && original_error_fd != original_output_fd) + safe_close_above_stdio(original_error_fd); + + /* Close the copies we moved > 2 */ + for (i = 0; i < 3; i++) + safe_close(copy_fd[i]); + + /* Close our null fd, if it's > 2 */ + safe_close_above_stdio(null_fd); + + return r; +} + +int fd_reopen(int fd, int flags) { + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + int new_fd; + + /* Reopens the specified fd with new flags. This is useful for convert an O_PATH fd into a regular one, or to + * turn O_RDWR fds into O_RDONLY fds. + * + * This doesn't work on sockets (since they cannot be open()ed, ever). + * + * This implicitly resets the file read index to 0. */ + + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + new_fd = open(procfs_path, flags); + if (new_fd < 0) + return -errno; + + return new_fd; +} + +int read_nr_open(void) { + _cleanup_free_ char *nr_open = NULL; + int r; + + /* Returns the kernel's current fd limit, either by reading it of /proc/sys if that works, or using the + * hard-coded default compiled-in value of current kernels (1M) if not. This call will never fail. */ + + r = read_one_line_file("/proc/sys/fs/nr_open", &nr_open); + if (r < 0) + log_debug_errno(r, "Failed to read /proc/sys/fs/nr_open, ignoring: %m"); + else { + int v; + + r = safe_atoi(nr_open, &v); + if (r < 0) + log_debug_errno(r, "Failed to parse /proc/sys/fs/nr_open value '%s', ignoring: %m", nr_open); + else + return v; + } + + /* If we fail, fallback to the hard-coded kernel limit of 1024 * 1024. */ + return 1024 * 1024; +} diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h new file mode 100644 index 00000000..e490753c --- /dev/null +++ b/src/basic/fd-util.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "macro.h" + +/* Make sure we can distinguish fd 0 and NULL */ +#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1) +#define PTR_TO_FD(p) (PTR_TO_INT(p)-1) + +int close_nointr(int fd); +int safe_close(int fd); +void safe_close_pair(int p[static 2]); + +static inline int safe_close_above_stdio(int fd) { + if (fd < 3) /* Don't close stdin/stdout/stderr, but still invalidate the fd by returning -1 */ + return -1; + + return safe_close(fd); +} + +void close_many(const int fds[], size_t n_fd); + +int fclose_nointr(FILE *f); +FILE* safe_fclose(FILE *f); +DIR* safe_closedir(DIR *f); + +static inline void closep(int *fd) { + safe_close(*fd); +} + +static inline void close_pairp(int (*p)[2]) { + safe_close_pair(*p); +} + +static inline void fclosep(FILE **f) { + safe_fclose(*f); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose); +DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir); + +#define _cleanup_close_ _cleanup_(closep) +#define _cleanup_fclose_ _cleanup_(fclosep) +#define _cleanup_pclose_ _cleanup_(pclosep) +#define _cleanup_closedir_ _cleanup_(closedirp) +#define _cleanup_close_pair_ _cleanup_(close_pairp) + +int fd_nonblock(int fd, bool nonblock); +int fd_cloexec(int fd, bool cloexec); + +int close_all_fds(const int except[], size_t n_except); + +int same_fd(int a, int b); + +void cmsg_close_all(struct msghdr *mh); + +bool fdname_is_valid(const char *s); + +int fd_get_path(int fd, char **ret); + +int move_fd(int from, int to, int cloexec); + +enum { + ACQUIRE_NO_DEV_NULL = 1 << 0, + ACQUIRE_NO_MEMFD = 1 << 1, + ACQUIRE_NO_PIPE = 1 << 2, + ACQUIRE_NO_TMPFILE = 1 << 3, + ACQUIRE_NO_REGULAR = 1 << 4, +}; + +int acquire_data_fd(const void *data, size_t size, unsigned flags); + +int fd_duplicate_data_fd(int fd); + +int fd_move_above_stdio(int fd); + +int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd); + +static inline int make_null_stdio(void) { + return rearrange_stdio(-1, -1, -1); +} + +/* Like TAKE_PTR() but for file descriptors, resetting them to -1 */ +#define TAKE_FD(fd) \ + ({ \ + int _fd_ = (fd); \ + (fd) = -1; \ + _fd_; \ + }) + +int fd_reopen(int fd, int flags); + +int read_nr_open(void); diff --git a/src/basic/fileio.c b/src/basic/fileio.c new file mode 100644 index 00000000..714a00cd --- /dev/null +++ b/src/basic/fileio.c @@ -0,0 +1,1044 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hexdecoct.h" +#include "log.h" +#include "macro.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "tmpfile-util.h" + +#define READ_FULL_BYTES_MAX (4U*1024U*1024U) + +int fopen_unlocked(const char *path, const char *options, FILE **ret) { + assert(ret); + + FILE *f = fopen(path, options); + if (!f) + return -errno; + + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + + *ret = f; + return 0; +} + +int fdopen_unlocked(int fd, const char *options, FILE **ret) { + assert(ret); + + FILE *f = fdopen(fd, options); + if (!f) + return -errno; + + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + + *ret = f; + return 0; +} + +FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc) { + FILE *f = open_memstream(ptr, sizeloc); + if (!f) + return NULL; + + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + + return f; +} + +FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode) { + FILE *f = fmemopen(buf, size, mode); + if (!f) + return NULL; + + (void) __fsetlocking(f, FSETLOCKING_BYCALLER); + + return f; +} + +int write_string_stream_ts( + FILE *f, + const char *line, + WriteStringFileFlags flags, + struct timespec *ts) { + + bool needs_nl; + int r; + + assert(f); + assert(line); + + if (ferror(f)) + return -EIO; + + needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"); + + if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) { + /* If STDIO buffering was disabled, then let's append the newline character to the string itself, so + * that the write goes out in one go, instead of two */ + + line = strjoina(line, "\n"); + needs_nl = false; + } + + if (fputs(line, f) == EOF) + return -errno; + + if (needs_nl) + if (fputc('\n', f) == EOF) + return -errno; + + if (flags & WRITE_STRING_FILE_SYNC) + r = fflush_sync_and_check(f); + else + r = fflush_and_check(f); + if (r < 0) + return r; + + if (ts) { + struct timespec twice[2] = {*ts, *ts}; + + if (futimens(fileno(f), twice) < 0) + return -errno; + } + + return 0; +} + +static int write_string_file_atomic( + const char *fn, + const char *line, + WriteStringFileFlags flags, + struct timespec *ts) { + + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *p = NULL; + int r; + + assert(fn); + assert(line); + + r = fopen_temporary(fn, &f, &p); + if (r < 0) + return r; + + (void) fchmod_umask(fileno(f), 0644); + + r = write_string_stream_ts(f, line, flags, ts); + if (r < 0) + goto fail; + + if (rename(p, fn) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + (void) unlink(p); + return r; +} + +int write_string_file_ts( + const char *fn, + const char *line, + WriteStringFileFlags flags, + struct timespec *ts) { + + _cleanup_fclose_ FILE *f = NULL; + int q, r; + + assert(fn); + assert(line); + + /* We don't know how to verify whether the file contents was already on-disk. */ + assert(!((flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE) && (flags & WRITE_STRING_FILE_SYNC))); + + if (flags & WRITE_STRING_FILE_MKDIR_0755) { + r = mkdir_parents(fn, 0755); + if (r < 0) + return r; + } + + if (flags & WRITE_STRING_FILE_ATOMIC) { + assert(flags & WRITE_STRING_FILE_CREATE); + + r = write_string_file_atomic(fn, line, flags, ts); + if (r < 0) + goto fail; + + return r; + } else + assert(!ts); + + if (flags & WRITE_STRING_FILE_CREATE) { + r = fopen_unlocked(fn, "we", &f); + if (r < 0) + goto fail; + } else { + int fd; + + /* We manually build our own version of fopen(..., "we") that + * works without O_CREAT */ + fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY | ((flags & WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0)); + if (fd < 0) { + r = -errno; + goto fail; + } + + r = fdopen_unlocked(fd, "w", &f); + if (r < 0) { + safe_close(fd); + goto fail; + } + } + + if (flags & WRITE_STRING_FILE_DISABLE_BUFFER) + setvbuf(f, NULL, _IONBF, 0); + + r = write_string_stream_ts(f, line, flags, ts); + if (r < 0) + goto fail; + + return 0; + +fail: + if (!(flags & WRITE_STRING_FILE_VERIFY_ON_FAILURE)) + return r; + + f = safe_fclose(f); + + /* OK, the operation failed, but let's see if the right + * contents in place already. If so, eat up the error. */ + + q = verify_file(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE)); + if (q <= 0) + return r; + + return 0; +} + +int write_string_filef( + const char *fn, + WriteStringFileFlags flags, + const char *format, ...) { + + _cleanup_free_ char *p = NULL; + va_list ap; + int r; + + va_start(ap, format); + r = vasprintf(&p, format, ap); + va_end(ap); + + if (r < 0) + return -ENOMEM; + + return write_string_file(fn, p, flags); +} + +int read_one_line_file(const char *fn, char **line) { + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(fn); + assert(line); + + r = fopen_unlocked(fn, "re", &f); + if (r < 0) + return r; + + return read_line(f, LONG_LINE_MAX, line); +} + +int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *buf = NULL; + size_t l, k; + int r; + + assert(fn); + assert(blob); + + l = strlen(blob); + + if (accept_extra_nl && endswith(blob, "\n")) + accept_extra_nl = false; + + buf = malloc(l + accept_extra_nl + 1); + if (!buf) + return -ENOMEM; + + r = fopen_unlocked(fn, "re", &f); + if (r < 0) + return r; + + /* We try to read one byte more than we need, so that we know whether we hit eof */ + errno = 0; + k = fread(buf, 1, l + accept_extra_nl + 1, f); + if (ferror(f)) + return errno_or_else(EIO); + + if (k != l && k != l + accept_extra_nl) + return 0; + if (memcmp(buf, blob, l) != 0) + return 0; + if (k > l && buf[l] != '\n') + return 0; + + return 1; +} + +int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size) { + _cleanup_free_ char *buf = NULL; + _cleanup_close_ int fd = -1; + struct stat st; + size_t n, size; + int n_retries; + char *p; + + assert(ret_contents); + + /* Virtual filesystems such as sysfs or procfs use kernfs, and kernfs can work + * with two sorts of virtual files. One sort uses "seq_file", and the results of + * the first read are buffered for the second read. The other sort uses "raw" + * reads which always go direct to the device. In the latter case, the content of + * the virtual file must be retrieved with a single read otherwise a second read + * might get the new value instead of finding EOF immediately. That's the reason + * why the usage of fread(3) is prohibited in this case as it always performs a + * second call to read(2) looking for EOF. See issue 13585. */ + + fd = open(filename, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return -errno; + + /* Start size for files in /proc which usually report a file size of 0. */ + size = LINE_MAX / 2; + + /* Limit the number of attempts to read the number of bytes returned by fstat(). */ + n_retries = 3; + + for (;;) { + if (n_retries <= 0) + return -EIO; + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISREG(st.st_mode)) + return -EBADF; + + /* Be prepared for files from /proc which generally report a file size of 0. */ + if (st.st_size > 0) { + size = st.st_size; + n_retries--; + } else + size = size * 2; + + if (size > READ_FULL_BYTES_MAX) + return -E2BIG; + + p = realloc(buf, size + 1); + if (!p) + return -ENOMEM; + buf = TAKE_PTR(p); + + for (;;) { + ssize_t k; + + /* Read one more byte so we can detect whether the content of the + * file has already changed or the guessed size for files from /proc + * wasn't large enough . */ + k = read(fd, buf, size + 1); + if (k >= 0) { + n = k; + break; + } + + if (errno != -EINTR) + return -errno; + } + + /* Consider a short read as EOF */ + if (n <= size) + break; + + /* Hmm... either we read too few bytes from /proc or less likely the content + * of the file might have been changed (and is now bigger) while we were + * processing, let's try again either with a bigger guessed size or the new + * file size. */ + + if (lseek(fd, 0, SEEK_SET) < 0) + return -errno; + } + + if (n < size) { + p = realloc(buf, n + 1); + if (!p) + return -ENOMEM; + buf = TAKE_PTR(p); + } + + if (!ret_size) { + /* Safety check: if the caller doesn't want to know the size of what we + * just read it will rely on the trailing NUL byte. But if there's an + * embedded NUL byte, then we should refuse operation as otherwise + * there'd be ambiguity about what we just read. */ + + if (memchr(buf, 0, n)) + return -EBADMSG; + } else + *ret_size = n; + + buf[n] = 0; + *ret_contents = TAKE_PTR(buf); + + return 0; +} + +int read_full_stream_full( + FILE *f, + const char *filename, + ReadFullFileFlags flags, + char **ret_contents, + size_t *ret_size) { + + _cleanup_free_ char *buf = NULL; + struct stat st; + size_t n, n_next, l; + int fd, r; + + assert(f); + assert(ret_contents); + assert(!FLAGS_SET(flags, READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)); + assert(!(flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) || ret_size); + + n_next = LINE_MAX; /* Start size */ + + fd = fileno(f); + if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen(), let's + * optimize our buffering) */ + + if (fstat(fd, &st) < 0) + return -errno; + + if (S_ISREG(st.st_mode)) { + + /* Safety check */ + if (st.st_size > READ_FULL_BYTES_MAX) + return -E2BIG; + + /* Start with the right file size. Note that we increase the size + * to read here by one, so that the first read attempt already + * makes us notice the EOF. */ + if (st.st_size > 0) + n_next = st.st_size + 1; + + if (flags & READ_FULL_FILE_SECURE) + (void) warn_file_is_world_accessible(filename, &st, NULL, 0); + } + } + + n = l = 0; + for (;;) { + char *t; + size_t k; + + if (flags & READ_FULL_FILE_SECURE) { + t = malloc(n_next + 1); + if (!t) { + r = -ENOMEM; + goto finalize; + } + memcpy_safe(t, buf, n); + explicit_bzero_safe(buf, n); + buf = mfree(buf); + } else { + t = realloc(buf, n_next + 1); + if (!t) + return -ENOMEM; + } + + buf = t; + n = n_next; + + errno = 0; + k = fread(buf + l, 1, n - l, f); + if (k > 0) + l += k; + + if (ferror(f)) { + r = errno_or_else(EIO); + goto finalize; + } + + if (feof(f)) + break; + + /* We aren't expecting fread() to return a short read outside + * of (error && eof), assert buffer is full and enlarge buffer. + */ + assert(l == n); + + /* Safety check */ + if (n >= READ_FULL_BYTES_MAX) { + r = -E2BIG; + goto finalize; + } + + n_next = MIN(n * 2, READ_FULL_BYTES_MAX); + } + + if (flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) { + buf[l++] = 0; + if (flags & READ_FULL_FILE_UNBASE64) + r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size); + else + r = unhexmem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size); + goto finalize; + } + + if (!ret_size) { + /* Safety check: if the caller doesn't want to know the size of what we just read it will rely on the + * trailing NUL byte. But if there's an embedded NUL byte, then we should refuse operation as otherwise + * there'd be ambiguity about what we just read. */ + + if (memchr(buf, 0, l)) { + r = -EBADMSG; + goto finalize; + } + } + + buf[l] = 0; + *ret_contents = TAKE_PTR(buf); + + if (ret_size) + *ret_size = l; + + return 0; + +finalize: + if (flags & READ_FULL_FILE_SECURE) + explicit_bzero_safe(buf, n); + + return r; +} + +int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) { + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(filename); + assert(contents); + + r = fopen_unlocked(filename, "re", &f); + if (r < 0) + return r; + + return read_full_stream_full(f, filename, flags, contents, size); +} + +int executable_is_script(const char *path, char **interpreter) { + _cleanup_free_ char *line = NULL; + size_t len; + char *ans; + int r; + + assert(path); + + r = read_one_line_file(path, &line); + if (r == -ENOBUFS) /* First line overly long? if so, then it's not a script */ + return 0; + if (r < 0) + return r; + + if (!startswith(line, "#!")) + return 0; + + ans = strstrip(line + 2); + len = strcspn(ans, " \t"); + + if (len == 0) + return 0; + + ans = strndup(ans, len); + if (!ans) + return -ENOMEM; + + *interpreter = ans; + return 1; +} + +/** + * Retrieve one field from a file like /proc/self/status. pattern + * should not include whitespace or the delimiter (':'). pattern matches only + * the beginning of a line. Whitespace before ':' is skipped. Whitespace and + * zeros after the ':' will be skipped. field must be freed afterwards. + * terminator specifies the terminating characters of the field value (not + * included in the value). + */ +int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) { + _cleanup_free_ char *status = NULL; + char *t, *f; + size_t len; + int r; + + assert(terminator); + assert(filename); + assert(pattern); + assert(field); + + r = read_full_virtual_file(filename, &status, NULL); + if (r < 0) + return r; + + t = status; + + do { + bool pattern_ok; + + do { + t = strstr(t, pattern); + if (!t) + return -ENOENT; + + /* Check that pattern occurs in beginning of line. */ + pattern_ok = (t == status || t[-1] == '\n'); + + t += strlen(pattern); + + } while (!pattern_ok); + + t += strspn(t, " \t"); + if (!*t) + return -ENOENT; + + } while (*t != ':'); + + t++; + + if (*t) { + t += strspn(t, " \t"); + + /* Also skip zeros, because when this is used for + * capabilities, we don't want the zeros. This way the + * same capability set always maps to the same string, + * irrespective of the total capability set size. For + * other numbers it shouldn't matter. */ + t += strspn(t, "0"); + /* Back off one char if there's nothing but whitespace + and zeros */ + if (!*t || isspace(*t)) + t--; + } + + len = strcspn(t, terminator); + + f = strndup(t, len); + if (!f) + return -ENOMEM; + + *field = f; + return 0; +} + +DIR *xopendirat(int fd, const char *name, int flags) { + int nfd; + DIR *d; + + assert(!(flags & O_CREAT)); + + nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags, 0); + if (nfd < 0) + return NULL; + + d = fdopendir(nfd); + if (!d) { + safe_close(nfd); + return NULL; + } + + return d; +} + +static int search_and_fopen_internal(const char *path, const char *mode, const char *root, char **search, FILE **_f) { + char **i; + + assert(path); + assert(mode); + assert(_f); + + if (!path_strv_resolve_uniq(search, root)) + return -ENOMEM; + + STRV_FOREACH(i, search) { + _cleanup_free_ char *p = NULL; + FILE *f; + + p = path_join(root, *i, path); + if (!p) + return -ENOMEM; + + f = fopen(p, mode); + if (f) { + *_f = f; + return 0; + } + + if (errno != ENOENT) + return -errno; + } + + return -ENOENT; +} + +int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f) { + _cleanup_strv_free_ char **copy = NULL; + + assert(path); + assert(mode); + assert(_f); + + if (path_is_absolute(path)) { + FILE *f; + + f = fopen(path, mode); + if (f) { + *_f = f; + return 0; + } + + return -errno; + } + + copy = strv_copy((char**) search); + if (!copy) + return -ENOMEM; + + return search_and_fopen_internal(path, mode, root, copy, _f); +} + +int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f) { + _cleanup_strv_free_ char **s = NULL; + + if (path_is_absolute(path)) { + FILE *f; + + f = fopen(path, mode); + if (f) { + *_f = f; + return 0; + } + + return -errno; + } + + s = strv_split_nulstr(search); + if (!s) + return -ENOMEM; + + return search_and_fopen_internal(path, mode, root, s, _f); +} + +int fflush_and_check(FILE *f) { + assert(f); + + errno = 0; + fflush(f); + + if (ferror(f)) + return errno_or_else(EIO); + + return 0; +} + +int fflush_sync_and_check(FILE *f) { + int r; + + assert(f); + + r = fflush_and_check(f); + if (r < 0) + return r; + + if (fsync(fileno(f)) < 0) + return -errno; + + r = fsync_directory_of_file(fileno(f)); + if (r < 0) + return r; + + return 0; +} + +int write_timestamp_file_atomic(const char *fn, usec_t n) { + char ln[DECIMAL_STR_MAX(n)+2]; + + /* Creates a "timestamp" file, that contains nothing but a + * usec_t timestamp, formatted in ASCII. */ + + if (n <= 0 || n >= USEC_INFINITY) + return -ERANGE; + + xsprintf(ln, USEC_FMT "\n", n); + + return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); +} + +int read_timestamp_file(const char *fn, usec_t *ret) { + _cleanup_free_ char *ln = NULL; + uint64_t t; + int r; + + r = read_one_line_file(fn, &ln); + if (r < 0) + return r; + + r = safe_atou64(ln, &t); + if (r < 0) + return r; + + if (t <= 0 || t >= (uint64_t) USEC_INFINITY) + return -ERANGE; + + *ret = (usec_t) t; + return 0; +} + +int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) { + int r; + + assert(s); + + /* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter + * when specified shall initially point to a boolean variable initialized to false. It is set to true after the + * first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each + * element, but not before the first one. */ + + if (!f) + f = stdout; + + if (space) { + if (!separator) + separator = " "; + + if (*space) { + r = fputs(separator, f); + if (r < 0) + return r; + } + + *space = true; + } + + return fputs(s, f); +} + +/* A bitmask of the EOL markers we know */ +typedef enum EndOfLineMarker { + EOL_NONE = 0, + EOL_ZERO = 1 << 0, /* \0 (aka NUL) */ + EOL_TEN = 1 << 1, /* \n (aka NL, aka LF) */ + EOL_THIRTEEN = 1 << 2, /* \r (aka CR) */ +} EndOfLineMarker; + +static EndOfLineMarker categorize_eol(char c, ReadLineFlags flags) { + + if (!IN_SET(flags, READ_LINE_ONLY_NUL)) { + if (c == '\n') + return EOL_TEN; + if (c == '\r') + return EOL_THIRTEEN; + } + + if (c == '\0') + return EOL_ZERO; + + return EOL_NONE; +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile); + +int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret) { + size_t n = 0, allocated = 0, count = 0; + _cleanup_free_ char *buffer = NULL; + int r, tty = -1; + + assert(f); + + /* Something like a bounded version of getline(). + * + * Considers EOF, \n, \r and \0 end of line delimiters (or combinations of these), and does not include these + * delimiters in the string returned. Specifically, recognizes the following combinations of markers as line + * endings: + * + * • \n (UNIX) + * • \r (old MacOS) + * • \0 (C strings) + * • \n\0 + * • \r\0 + * • \r\n (Windows) + * • \n\r + * • \r\n\0 + * • \n\r\0 + * + * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from + * the number of characters in the returned string). When EOF is hit, 0 is returned. + * + * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding + * delimiters. If the limit is hit we fail and return -ENOBUFS. + * + * If a line shall be skipped ret may be initialized as NULL. */ + + if (ret) { + if (!GREEDY_REALLOC(buffer, allocated, 1)) + return -ENOMEM; + } + + { + _unused_ _cleanup_(funlockfilep) FILE *flocked = f; + EndOfLineMarker previous_eol = EOL_NONE; + flockfile(f); + + for (;;) { + EndOfLineMarker eol; + char c; + + if (n >= limit) + return -ENOBUFS; + + if (count >= INT_MAX) /* We couldn't return the counter anymore as "int", hence refuse this */ + return -ENOBUFS; + + r = safe_fgetc(f, &c); + if (r < 0) + return r; + if (r == 0) /* EOF is definitely EOL */ + break; + + eol = categorize_eol(c, flags); + + if (FLAGS_SET(previous_eol, EOL_ZERO) || + (eol == EOL_NONE && previous_eol != EOL_NONE) || + (eol != EOL_NONE && (previous_eol & eol) != 0)) { + /* Previous char was a NUL? This is not an EOL, but the previous char was? This type of + * EOL marker has been seen right before? In either of these three cases we are + * done. But first, let's put this character back in the queue. (Note that we have to + * cast this to (unsigned char) here as ungetc() expects a positive 'int', and if we + * are on an architecture where 'char' equals 'signed char' we need to ensure we don't + * pass a negative value here. That said, to complicate things further ungetc() is + * actually happy with most negative characters and implicitly casts them back to + * positive ones as needed, except for \xff (aka -1, aka EOF), which it refuses. What a + * godawful API!) */ + assert_se(ungetc((unsigned char) c, f) != EOF); + break; + } + + count++; + + if (eol != EOL_NONE) { + /* If we are on a tty, we can't wait for more input. But we expect only + * \n as the single EOL marker, so there is no need to wait. We check + * this condition last to avoid isatty() check if not necessary. */ + + if (tty < 0) + tty = isatty(fileno(f)); + if (tty > 0) + break; + } + + if (eol != EOL_NONE) { + previous_eol |= eol; + continue; + } + + if (ret) { + if (!GREEDY_REALLOC(buffer, allocated, n + 2)) + return -ENOMEM; + + buffer[n] = c; + } + + n++; + } + } + + if (ret) { + buffer[n] = 0; + + *ret = TAKE_PTR(buffer); + } + + return (int) count; +} + +int safe_fgetc(FILE *f, char *ret) { + int k; + + assert(f); + + /* A safer version of plain fgetc(): let's propagate the error that happened while reading as such, and + * separate the EOF condition from the byte read, to avoid those confusion signed/unsigned issues fgetc() + * has. */ + + errno = 0; + k = fgetc(f); + if (k == EOF) { + if (ferror(f)) + return errno_or_else(EIO); + + if (ret) + *ret = 0; + + return 0; + } + + if (ret) + *ret = k; + + return 1; +} + +int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line) { + struct stat _st; + + if (!filename) + return 0; + + if (!st) { + if (stat(filename, &_st) < 0) + return -errno; + st = &_st; + } + + if ((st->st_mode & S_IRWXO) == 0) + return 0; + + if (unit) + log_syntax(unit, LOG_WARNING, filename, line, 0, + "%s has %04o mode that is too permissive, please adjust the ownership and access mode.", + filename, st->st_mode & 07777); + else + log_warning("%s has %04o mode that is too permissive, please adjust the ownership and access mode.", + filename, st->st_mode & 07777); + return 0; +} diff --git a/src/basic/fileio.h b/src/basic/fileio.h new file mode 100644 index 00000000..31bfef33 --- /dev/null +++ b/src/basic/fileio.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "macro.h" +#include "time-util.h" + +#define LONG_LINE_MAX (1U*1024U*1024U) + +typedef enum { + WRITE_STRING_FILE_CREATE = 1 << 0, + WRITE_STRING_FILE_ATOMIC = 1 << 1, + WRITE_STRING_FILE_AVOID_NEWLINE = 1 << 2, + WRITE_STRING_FILE_VERIFY_ON_FAILURE = 1 << 3, + WRITE_STRING_FILE_SYNC = 1 << 4, + WRITE_STRING_FILE_DISABLE_BUFFER = 1 << 5, + WRITE_STRING_FILE_NOFOLLOW = 1 << 6, + WRITE_STRING_FILE_MKDIR_0755 = 1 << 7, + + /* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one + more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file() + and friends. */ + +} WriteStringFileFlags; + +typedef enum { + READ_FULL_FILE_SECURE = 1 << 0, + READ_FULL_FILE_UNBASE64 = 1 << 1, + READ_FULL_FILE_UNHEX = 1 << 2, +} ReadFullFileFlags; + +int fopen_unlocked(const char *path, const char *options, FILE **ret); +int fdopen_unlocked(int fd, const char *options, FILE **ret); +FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc); +FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode); + +int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts); +static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) { + return write_string_stream_ts(f, line, flags, NULL); +} +int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts); +static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) { + return write_string_file_ts(fn, line, flags, NULL); +} + +int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4); + +int read_one_line_file(const char *filename, char **line); +int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size); +static inline int read_full_file(const char *filename, char **contents, size_t *size) { + return read_full_file_full(filename, 0, contents, size); +} +int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size); +int read_full_stream_full(FILE *f, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size); +static inline int read_full_stream(FILE *f, char **contents, size_t *size) { + return read_full_stream_full(f, NULL, 0, contents, size); +} + +int verify_file(const char *fn, const char *blob, bool accept_extra_nl); + +int executable_is_script(const char *path, char **interpreter); + +int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field); + +DIR *xopendirat(int dirfd, const char *name, int flags); + +int search_and_fopen(const char *path, const char *mode, const char *root, const char **search, FILE **_f); +int search_and_fopen_nulstr(const char *path, const char *mode, const char *root, const char *search, FILE **_f); + +int fflush_and_check(FILE *f); +int fflush_sync_and_check(FILE *f); + +int write_timestamp_file_atomic(const char *fn, usec_t n); +int read_timestamp_file(const char *fn, usec_t *ret); + +int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space); + +typedef enum ReadLineFlags { + READ_LINE_ONLY_NUL = 1 << 0, +} ReadLineFlags; + +int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret); + +static inline int read_line(FILE *f, size_t limit, char **ret) { + return read_line_full(f, limit, 0, ret); +} + +static inline int read_nul_string(FILE *f, size_t limit, char **ret) { + return read_line_full(f, limit, READ_LINE_ONLY_NUL, ret); +} + +int safe_fgetc(FILE *f, char *ret); + +int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line); diff --git a/src/basic/format-util.c b/src/basic/format-util.c new file mode 100644 index 00000000..b4144e03 --- /dev/null +++ b/src/basic/format-util.c @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "format-util.h" +#include "memory-util.h" +#include "stdio-util.h" + +assert_cc(DECIMAL_STR_MAX(int) + 1 <= IF_NAMESIZE + 1); +char *format_ifname_full(int ifindex, char buf[static IF_NAMESIZE + 1], FormatIfnameFlag flag) { + /* Buffer is always cleared */ + memzero(buf, IF_NAMESIZE + 1); + if (if_indextoname(ifindex, buf)) + return buf; + + if (!FLAGS_SET(flag, FORMAT_IFNAME_IFINDEX)) + return NULL; + + if (FLAGS_SET(flag, FORMAT_IFNAME_IFINDEX_WITH_PERCENT)) + snprintf(buf, IF_NAMESIZE + 1, "%%%d", ifindex); + else + snprintf(buf, IF_NAMESIZE + 1, "%d", ifindex); + + return buf; +} + +char *format_bytes_full(char *buf, size_t l, uint64_t t, FormatBytesFlag flag) { + typedef struct { + const char *suffix; + uint64_t factor; + } suffix_table; + static const suffix_table table_iec[] = { + { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) }, + { "M", UINT64_C(1024)*UINT64_C(1024) }, + { "K", UINT64_C(1024) }, + }, table_si[] = { + { "E", UINT64_C(1000)*UINT64_C(1000)*UINT64_C(1000)*UINT64_C(1000)*UINT64_C(1000)*UINT64_C(1000) }, + { "P", UINT64_C(1000)*UINT64_C(1000)*UINT64_C(1000)*UINT64_C(1000)*UINT64_C(1000) }, + { "T", UINT64_C(1000)*UINT64_C(1000)*UINT64_C(1000)*UINT64_C(1000) }, + { "G", UINT64_C(1000)*UINT64_C(1000)*UINT64_C(1000) }, + { "M", UINT64_C(1000)*UINT64_C(1000) }, + { "K", UINT64_C(1000) }, + }; + const suffix_table *table; + size_t n, i; + + assert_cc(ELEMENTSOF(table_iec) == ELEMENTSOF(table_si)); + + if (t == (uint64_t) -1) + return NULL; + + table = flag & FORMAT_BYTES_USE_IEC ? table_iec : table_si; + n = ELEMENTSOF(table_iec); + + for (i = 0; i < n; i++) + if (t >= table[i].factor) { + if (flag & FORMAT_BYTES_BELOW_POINT) { + snprintf(buf, l, + "%" PRIu64 ".%" PRIu64 "%s", + t / table[i].factor, + i != n - 1 ? + (t / table[i + 1].factor * UINT64_C(10) / table[n - 1].factor) % UINT64_C(10): + (t * UINT64_C(10) / table[i].factor) % UINT64_C(10), + table[i].suffix); + } else + snprintf(buf, l, + "%" PRIu64 "%s", + t / table[i].factor, + table[i].suffix); + + goto finish; + } + + snprintf(buf, l, "%" PRIu64 "%s", t, flag & FORMAT_BYTES_TRAILING_B ? "B" : ""); + +finish: + buf[l-1] = 0; + return buf; + +} diff --git a/src/basic/format-util.h b/src/basic/format-util.h new file mode 100644 index 00000000..59622508 --- /dev/null +++ b/src/basic/format-util.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#if SIZEOF_PID_T == 4 +# define PID_PRI PRIi32 +#elif SIZEOF_PID_T == 2 +# define PID_PRI PRIi16 +#else +# error Unknown pid_t size +#endif +#define PID_FMT "%" PID_PRI + +#if SIZEOF_UID_T == 4 +# define UID_FMT "%" PRIu32 +#elif SIZEOF_UID_T == 2 +# define UID_FMT "%" PRIu16 +#else +# error Unknown uid_t size +#endif + +#if SIZEOF_GID_T == 4 +# define GID_FMT "%" PRIu32 +#elif SIZEOF_GID_T == 2 +# define GID_FMT "%" PRIu16 +#else +# error Unknown gid_t size +#endif + +#if SIZEOF_TIME_T == 8 +# define PRI_TIME PRIi64 +#elif SIZEOF_TIME_T == 4 +# define PRI_TIME "li" +#else +# error Unknown time_t size +#endif + +#if defined __x86_64__ && defined __ILP32__ +# define PRI_TIMEX PRIi64 +#else +# define PRI_TIMEX "li" +#endif + +#if SIZEOF_RLIM_T == 8 +# define RLIM_FMT "%" PRIu64 +#elif SIZEOF_RLIM_T == 4 +# define RLIM_FMT "%" PRIu32 +#else +# error Unknown rlim_t size +#endif + +#if SIZEOF_DEV_T == 8 +# define DEV_FMT "%" PRIu64 +#elif SIZEOF_DEV_T == 4 +# define DEV_FMT "%" PRIu32 +#else +# error Unknown dev_t size +#endif + +#if SIZEOF_INO_T == 8 +# define INO_FMT "%" PRIu64 +#elif SIZEOF_INO_T == 4 +# define INO_FMT "%" PRIu32 +#else +# error Unknown ino_t size +#endif + +typedef enum { + FORMAT_IFNAME_IFINDEX = 1 << 0, + FORMAT_IFNAME_IFINDEX_WITH_PERCENT = (1 << 1) | FORMAT_IFNAME_IFINDEX, +} FormatIfnameFlag; + +char *format_ifname_full(int ifindex, char buf[static IF_NAMESIZE + 1], FormatIfnameFlag flag); +static inline char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]) { + return format_ifname_full(ifindex, buf, 0); +} + +typedef enum { + FORMAT_BYTES_USE_IEC = 1 << 0, + FORMAT_BYTES_BELOW_POINT = 1 << 1, + FORMAT_BYTES_TRAILING_B = 1 << 2, +} FormatBytesFlag; + +#define FORMAT_BYTES_MAX 8 +char *format_bytes_full(char *buf, size_t l, uint64_t t, FormatBytesFlag flag); +static inline char *format_bytes(char *buf, size_t l, uint64_t t) { + return format_bytes_full(buf, l, t, FORMAT_BYTES_USE_IEC | FORMAT_BYTES_BELOW_POINT | FORMAT_BYTES_TRAILING_B); +} diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c new file mode 100644 index 00000000..5723c845 --- /dev/null +++ b/src/basic/fs-util.c @@ -0,0 +1,1394 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "locale-util.h" +#include "log.h" +#include "macro.h" +#include "missing_fcntl.h" +#include "missing_fs.h" +#include "missing_syscall.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "tmpfile-util.h" +#include "user-util.h" +#include "util.h" + +int unlink_noerrno(const char *path) { + PROTECT_ERRNO; + int r; + + r = unlink(path); + if (r < 0) + return -errno; + + return 0; +} + +int rmdir_parents(const char *path, const char *stop) { + size_t l; + int r = 0; + + assert(path); + assert(stop); + + l = strlen(path); + + /* Skip trailing slashes */ + while (l > 0 && path[l-1] == '/') + l--; + + while (l > 0) { + char *t; + + /* Skip last component */ + while (l > 0 && path[l-1] != '/') + l--; + + /* Skip trailing slashes */ + while (l > 0 && path[l-1] == '/') + l--; + + if (l <= 0) + break; + + t = strndup(path, l); + if (!t) + return -ENOMEM; + + if (path_startswith(stop, t)) { + free(t); + return 0; + } + + r = rmdir(t); + free(t); + + if (r < 0) + if (errno != ENOENT) + return -errno; + } + + return 0; +} + +int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { + int r; + + /* Try the ideal approach first */ + if (renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE) >= 0) + return 0; + + /* renameat2() exists since Linux 3.15, btrfs and FAT added support for it later. If it is not implemented, + * fall back to a different method. */ + if (!IN_SET(errno, EINVAL, ENOSYS, ENOTTY)) + return -errno; + + /* Let's try to use linkat()+unlinkat() as fallback. This doesn't work on directories and on some file systems + * that do not support hard links (such as FAT, most prominently), but for files it's pretty close to what we + * want — though not atomic (i.e. for a short period both the new and the old filename will exist). */ + if (linkat(olddirfd, oldpath, newdirfd, newpath, 0) >= 0) { + + if (unlinkat(olddirfd, oldpath, 0) < 0) { + r = -errno; /* Backup errno before the following unlinkat() alters it */ + (void) unlinkat(newdirfd, newpath, 0); + return r; + } + + return 0; + } + + if (!IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM)) /* FAT returns EPERM on link()… */ + return -errno; + + /* OK, neither RENAME_NOREPLACE nor linkat()+unlinkat() worked. Let's then fallback to the racy TOCTOU + * vulnerable accessat(F_OK) check followed by classic, replacing renameat(), we have nothing better. */ + + if (faccessat(newdirfd, newpath, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) + return -EEXIST; + if (errno != ENOENT) + return -errno; + + if (renameat(olddirfd, oldpath, newdirfd, newpath) < 0) + return -errno; + + return 0; +} + +int readlinkat_malloc(int fd, const char *p, char **ret) { + size_t l = FILENAME_MAX+1; + int r; + + assert(p); + assert(ret); + + for (;;) { + char *c; + ssize_t n; + + c = new(char, l); + if (!c) + return -ENOMEM; + + n = readlinkat(fd, p, c, l-1); + if (n < 0) { + r = -errno; + free(c); + return r; + } + + if ((size_t) n < l-1) { + c[n] = 0; + *ret = c; + return 0; + } + + free(c); + l *= 2; + } +} + +int readlink_malloc(const char *p, char **ret) { + return readlinkat_malloc(AT_FDCWD, p, ret); +} + +int readlink_value(const char *p, char **ret) { + _cleanup_free_ char *link = NULL; + char *value; + int r; + + r = readlink_malloc(p, &link); + if (r < 0) + return r; + + value = basename(link); + if (!value) + return -ENOENT; + + value = strdup(value); + if (!value) + return -ENOMEM; + + *ret = value; + + return 0; +} + +int readlink_and_make_absolute(const char *p, char **r) { + _cleanup_free_ char *target = NULL; + char *k; + int j; + + assert(p); + assert(r); + + j = readlink_malloc(p, &target); + if (j < 0) + return j; + + k = file_in_same_dir(p, target); + if (!k) + return -ENOMEM; + + *r = k; + return 0; +} + +int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) { + _cleanup_close_ int fd = -1; + + assert(path); + + fd = open(path, O_PATH|O_CLOEXEC|O_NOFOLLOW); /* Let's acquire an O_PATH fd, as precaution to change + * mode/owner on the same file */ + if (fd < 0) + return -errno; + + return fchmod_and_chown(fd, mode, uid, gid); +} + +int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid) { + bool do_chown, do_chmod; + struct stat st; + + /* Change ownership and access mode of the specified fd. Tries to do so safely, ensuring that at no + * point in time the access mode is above the old access mode under the old ownership or the new + * access mode under the new ownership. Note: this call tries hard to leave the access mode + * unaffected if the uid/gid is changed, i.e. it undoes implicit suid/sgid dropping the kernel does + * on chown(). + * + * This call is happy with O_PATH fds. */ + + if (fstat(fd, &st) < 0) + return -errno; + + do_chown = + (uid != UID_INVALID && st.st_uid != uid) || + (gid != GID_INVALID && st.st_gid != gid); + + do_chmod = + !S_ISLNK(st.st_mode) && /* chmod is not defined on symlinks */ + ((mode != MODE_INVALID && ((st.st_mode ^ mode) & 07777) != 0) || + do_chown); /* If we change ownership, make sure we reset the mode afterwards, since chown() + * modifies the access mode too */ + + if (mode == MODE_INVALID) + mode = st.st_mode; /* If we only shall do a chown(), save original mode, since chown() might break it. */ + else if ((mode & S_IFMT) != 0 && ((mode ^ st.st_mode) & S_IFMT) != 0) + return -EINVAL; /* insist on the right file type if it was specified */ + + if (do_chown && do_chmod) { + mode_t minimal = st.st_mode & mode; /* the subset of the old and the new mask */ + + if (((minimal ^ st.st_mode) & 07777) != 0) + if (fchmod_opath(fd, minimal & 07777) < 0) + return -errno; + } + + if (do_chown) + if (fchownat(fd, "", uid, gid, AT_EMPTY_PATH) < 0) + return -errno; + + if (do_chmod) + if (fchmod_opath(fd, mode & 07777) < 0) + return -errno; + + return do_chown || do_chmod; +} + +int fchmod_umask(int fd, mode_t m) { + mode_t u; + int r; + + u = umask(0777); + r = fchmod(fd, m & (~u)) < 0 ? -errno : 0; + umask(u); + + return r; +} + +int fchmod_opath(int fd, mode_t m) { + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + + /* This function operates also on fd that might have been opened with + * O_PATH. Indeed fchmodat() doesn't have the AT_EMPTY_PATH flag like + * fchownat() does. */ + + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + if (chmod(procfs_path, m) < 0) + return -errno; + + return 0; +} + +int fd_warn_permissions(const char *path, int fd) { + struct stat st; + + if (fstat(fd, &st) < 0) + return -errno; + + /* Don't complain if we are reading something that is not a file, for example /dev/null */ + if (!S_ISREG(st.st_mode)) + return 0; + + if (st.st_mode & 0111) + log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path); + + if (st.st_mode & 0002) + log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path); + + if (getpid_cached() == 1 && (st.st_mode & 0044) != 0044) + log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path); + + return 0; +} + +int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) { + char fdpath[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + _cleanup_close_ int fd = -1; + int r, ret = 0; + + assert(path); + + /* Note that touch_file() does not follow symlinks: if invoked on an existing symlink, then it is the symlink + * itself which is updated, not its target + * + * Returns the first error we encounter, but tries to apply as much as possible. */ + + if (parents) + (void) mkdir_parents(path, 0755); + + /* Initially, we try to open the node with O_PATH, so that we get a reference to the node. This is useful in + * case the path refers to an existing device or socket node, as we can open it successfully in all cases, and + * won't trigger any driver magic or so. */ + fd = open(path, O_PATH|O_CLOEXEC|O_NOFOLLOW); + if (fd < 0) { + if (errno != ENOENT) + return -errno; + + /* if the node doesn't exist yet, we create it, but with O_EXCL, so that we only create a regular file + * here, and nothing else */ + fd = open(path, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, IN_SET(mode, 0, MODE_INVALID) ? 0644 : mode); + if (fd < 0) + return -errno; + } + + /* Let's make a path from the fd, and operate on that. With this logic, we can adjust the access mode, + * ownership and time of the file node in all cases, even if the fd refers to an O_PATH object — which is + * something fchown(), fchmod(), futimensat() don't allow. */ + xsprintf(fdpath, "/proc/self/fd/%i", fd); + + ret = fchmod_and_chown(fd, mode, uid, gid); + + if (stamp != USEC_INFINITY) { + struct timespec ts[2]; + + timespec_store(&ts[0], stamp); + ts[1] = ts[0]; + r = utimensat(AT_FDCWD, fdpath, ts, 0); + } else + r = utimensat(AT_FDCWD, fdpath, NULL, 0); + if (r < 0 && ret >= 0) + return -errno; + + return ret; +} + +int touch(const char *path) { + return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID); +} + +int symlink_idempotent(const char *from, const char *to, bool make_relative) { + _cleanup_free_ char *relpath = NULL; + int r; + + assert(from); + assert(to); + + if (make_relative) { + _cleanup_free_ char *parent = NULL; + + parent = dirname_malloc(to); + if (!parent) + return -ENOMEM; + + r = path_make_relative(parent, from, &relpath); + if (r < 0) + return r; + + from = relpath; + } + + if (symlink(from, to) < 0) { + _cleanup_free_ char *p = NULL; + + if (errno != EEXIST) + return -errno; + + r = readlink_malloc(to, &p); + if (r == -EINVAL) /* Not a symlink? In that case return the original error we encountered: -EEXIST */ + return -EEXIST; + if (r < 0) /* Any other error? In that case propagate it as is */ + return r; + + if (!streq(p, from)) /* Not the symlink we want it to be? In that case, propagate the original -EEXIST */ + return -EEXIST; + } + + return 0; +} + +int symlink_atomic(const char *from, const char *to) { + _cleanup_free_ char *t = NULL; + int r; + + assert(from); + assert(to); + + r = tempfn_random(to, NULL, &t); + if (r < 0) + return r; + + if (symlink(from, t) < 0) + return -errno; + + if (rename(t, to) < 0) { + unlink_noerrno(t); + return -errno; + } + + return 0; +} + +int mknod_atomic(const char *path, mode_t mode, dev_t dev) { + _cleanup_free_ char *t = NULL; + int r; + + assert(path); + + r = tempfn_random(path, NULL, &t); + if (r < 0) + return r; + + if (mknod(t, mode, dev) < 0) + return -errno; + + if (rename(t, path) < 0) { + unlink_noerrno(t); + return -errno; + } + + return 0; +} + +int mkfifo_atomic(const char *path, mode_t mode) { + _cleanup_free_ char *t = NULL; + int r; + + assert(path); + + r = tempfn_random(path, NULL, &t); + if (r < 0) + return r; + + if (mkfifo(t, mode) < 0) + return -errno; + + if (rename(t, path) < 0) { + unlink_noerrno(t); + return -errno; + } + + return 0; +} + +int mkfifoat_atomic(int dirfd, const char *path, mode_t mode) { + _cleanup_free_ char *t = NULL; + int r; + + assert(path); + + if (path_is_absolute(path)) + return mkfifo_atomic(path, mode); + + /* We're only interested in the (random) filename. */ + r = tempfn_random_child("", NULL, &t); + if (r < 0) + return r; + + if (mkfifoat(dirfd, t, mode) < 0) + return -errno; + + if (renameat(dirfd, t, dirfd, path) < 0) { + unlink_noerrno(t); + return -errno; + } + + return 0; +} + +int get_files_in_directory(const char *path, char ***list) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + size_t bufsize = 0, n = 0; + _cleanup_strv_free_ char **l = NULL; + + assert(path); + + /* Returns all files in a directory in *list, and the number + * of files as return value. If list is NULL returns only the + * number. */ + + d = opendir(path); + if (!d) + return -errno; + + FOREACH_DIRENT_ALL(de, d, return -errno) { + dirent_ensure_type(d, de); + + if (!dirent_is_file(de)) + continue; + + if (list) { + /* one extra slot is needed for the terminating NULL */ + if (!GREEDY_REALLOC(l, bufsize, n + 2)) + return -ENOMEM; + + l[n] = strdup(de->d_name); + if (!l[n]) + return -ENOMEM; + + l[++n] = NULL; + } else + n++; + } + + if (list) + *list = TAKE_PTR(l); + + return n; +} + +static int getenv_tmp_dir(const char **ret_path) { + const char *n; + int r, ret = 0; + + assert(ret_path); + + /* We use the same order of environment variables python uses in tempfile.gettempdir(): + * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */ + FOREACH_STRING(n, "TMPDIR", "TEMP", "TMP") { + const char *e; + + e = secure_getenv(n); + if (!e) + continue; + if (!path_is_absolute(e)) { + r = -ENOTDIR; + goto next; + } + if (!path_is_normalized(e)) { + r = -EPERM; + goto next; + } + + r = is_dir(e, true); + if (r < 0) + goto next; + if (r == 0) { + r = -ENOTDIR; + goto next; + } + + *ret_path = e; + return 1; + + next: + /* Remember first error, to make this more debuggable */ + if (ret >= 0) + ret = r; + } + + if (ret < 0) + return ret; + + *ret_path = NULL; + return ret; +} + +static int tmp_dir_internal(const char *def, const char **ret) { + const char *e; + int r, k; + + assert(def); + assert(ret); + + r = getenv_tmp_dir(&e); + if (r > 0) { + *ret = e; + return 0; + } + + k = is_dir(def, true); + if (k == 0) + k = -ENOTDIR; + if (k < 0) + return r < 0 ? r : k; + + *ret = def; + return 0; +} + +int var_tmp_dir(const char **ret) { + + /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus + * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is + * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR, + * making it a variable that overrides all temporary file storage locations. */ + + return tmp_dir_internal("/var/tmp", ret); +} + +int tmp_dir(const char **ret) { + + /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually + * backed by an in-memory file system: /tmp. */ + + return tmp_dir_internal("/tmp", ret); +} + +int unlink_or_warn(const char *filename) { + if (unlink(filename) < 0 && errno != ENOENT) + /* If the file doesn't exist and the fs simply was read-only (in which + * case unlink() returns EROFS even if the file doesn't exist), don't + * complain */ + if (errno != EROFS || access(filename, F_OK) >= 0) + return log_error_errno(errno, "Failed to remove \"%s\": %m", filename); + + return 0; +} + +int inotify_add_watch_fd(int fd, int what, uint32_t mask) { + char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; + int r; + + /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */ + xsprintf(path, "/proc/self/fd/%i", what); + + r = inotify_add_watch(fd, path, mask); + if (r < 0) + return -errno; + + return r; +} + +int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) { + + if (inotify_add_watch(fd, pathname, mask) < 0) { + if (errno == ENOSPC) + return log_error_errno(errno, "Failed to add a watch for %s: inotify watch limit reached", pathname); + + return log_error_errno(errno, "Failed to add a watch for %s: %m", pathname); + } + + return 0; +} + +static bool unsafe_transition(const struct stat *a, const struct stat *b) { + /* Returns true if the transition from a to b is safe, i.e. that we never transition from unprivileged to + * privileged files or directories. Why bother? So that unprivileged code can't symlink to privileged files + * making us believe we read something safe even though it isn't safe in the specific context we open it in. */ + + if (a->st_uid == 0) /* Transitioning from privileged to unprivileged is always fine */ + return false; + + return a->st_uid != b->st_uid; /* Otherwise we need to stay within the same UID */ +} + +static int log_unsafe_transition(int a, int b, const char *path, unsigned flags) { + _cleanup_free_ char *n1 = NULL, *n2 = NULL; + + if (!FLAGS_SET(flags, CHASE_WARN)) + return -ENOLINK; + + (void) fd_get_path(a, &n1); + (void) fd_get_path(b, &n2); + + return log_warning_errno(SYNTHETIC_ERRNO(ENOLINK), + "Detected unsafe path transition %s %s %s during canonicalization of %s.", + n1, special_glyph(SPECIAL_GLYPH_ARROW), n2, path); +} + +static int log_autofs_mount_point(int fd, const char *path, unsigned flags) { + _cleanup_free_ char *n1 = NULL; + + if (!FLAGS_SET(flags, CHASE_WARN)) + return -EREMOTE; + + (void) fd_get_path(fd, &n1); + + return log_warning_errno(SYNTHETIC_ERRNO(EREMOTE), + "Detected autofs mount point %s during canonicalization of %s.", + n1, path); +} + +int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret_path, int *ret_fd) { + _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL; + _cleanup_close_ int fd = -1; + unsigned max_follow = CHASE_SYMLINKS_MAX; /* how many symlinks to follow before giving up and returning ELOOP */ + struct stat previous_stat; + bool exists = true; + char *todo; + int r; + + assert(path); + + /* Either the file may be missing, or we return an fd to the final object, but both make no sense */ + if ((flags & CHASE_NONEXISTENT) && ret_fd) + return -EINVAL; + + if ((flags & CHASE_STEP) && ret_fd) + return -EINVAL; + + if (isempty(path)) + return -EINVAL; + + /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following + * symlinks relative to a root directory, instead of the root of the host. + * + * Note that "root" primarily matters if we encounter an absolute symlink. It is also used when following + * relative symlinks to ensure they cannot be used to "escape" the root directory. The path parameter passed is + * assumed to be already prefixed by it, except if the CHASE_PREFIX_ROOT flag is set, in which case it is first + * prefixed accordingly. + * + * Algorithmically this operates on two path buffers: "done" are the components of the path we already + * processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to + * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning + * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no + * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races + * to a minimum. + * + * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got + * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this + * function what to do when encountering a symlink with an absolute path as directory: prefix it by the + * specified path. + * + * There are five ways to invoke this function: + * + * 1. Without CHASE_STEP or ret_fd: in this case the path is resolved and the normalized path is + * returned in `ret_path`. The return value is < 0 on error. If CHASE_NONEXISTENT is also set, 0 + * is returned if the file doesn't exist, > 0 otherwise. If CHASE_NONEXISTENT is not set, >= 0 is + * returned if the destination was found, -ENOENT if it wasn't. + * + * 2. With ret_fd: in this case the destination is opened after chasing it as O_PATH and this file + * descriptor is returned as return value. This is useful to open files relative to some root + * directory. Note that the returned O_PATH file descriptors must be converted into a regular one (using + * fd_reopen() or such) before it can be used for reading/writing. ret_fd may not be combined with + * CHASE_NONEXISTENT. + * + * 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only the first + * symlink or ".." component of the path is resolved, and the resulting path is returned. This is useful if + * a caller wants to trace the a path through the file system verbosely. Returns < 0 on error, > 0 if the + * path is fully normalized, and == 0 for each normalization step. This may be combined with + * CHASE_NONEXISTENT, in which case 1 is returned when a component is not found. + * + * 4. With CHASE_SAFE: in this case the path must not contain unsafe transitions, i.e. transitions from + * unprivileged to privileged files or directories. In such cases the return value is -ENOLINK. If + * CHASE_WARN is also set, a warning describing the unsafe transition is emitted. + * + * 5. With CHASE_NO_AUTOFS: in this case if an autofs mount point is encountered, path normalization + * is aborted and -EREMOTE is returned. If CHASE_WARN is also set, a warning showing the path of + * the mount point is emitted. + */ + + /* A root directory of "/" or "" is identical to none */ + if (empty_or_root(original_root)) + original_root = NULL; + + if (!original_root && !ret_path && !(flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_STEP)) && ret_fd) { + /* Shortcut the ret_fd case if the caller isn't interested in the actual path and has no root set + * and doesn't care about any of the other special features we provide either. */ + r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0)); + if (r < 0) + return -errno; + + *ret_fd = r; + return 0; + } + + if (original_root) { + r = path_make_absolute_cwd(original_root, &root); + if (r < 0) + return r; + + if (flags & CHASE_PREFIX_ROOT) { + /* We don't support relative paths in combination with a root directory */ + if (!path_is_absolute(path)) + return -EINVAL; + + path = prefix_roota(root, path); + } + } + + r = path_make_absolute_cwd(path, &buffer); + if (r < 0) + return r; + + fd = open("/", O_CLOEXEC|O_NOFOLLOW|O_PATH); + if (fd < 0) + return -errno; + + if (flags & CHASE_SAFE) { + if (fstat(fd, &previous_stat) < 0) + return -errno; + } + + todo = buffer; + for (;;) { + _cleanup_free_ char *first = NULL; + _cleanup_close_ int child = -1; + struct stat st; + size_t n, m; + + /* Determine length of first component in the path */ + n = strspn(todo, "/"); /* The slashes */ + m = n + strcspn(todo + n, "/"); /* The entire length of the component */ + + /* Extract the first component. */ + first = strndup(todo, m); + if (!first) + return -ENOMEM; + + todo += m; + + /* Empty? Then we reached the end. */ + if (isempty(first)) + break; + + /* Just a single slash? Then we reached the end. */ + if (path_equal(first, "/")) { + /* Preserve the trailing slash */ + + if (flags & CHASE_TRAIL_SLASH) + if (!strextend(&done, "/", NULL)) + return -ENOMEM; + + break; + } + + /* Just a dot? Then let's eat this up. */ + if (path_equal(first, "/.")) + continue; + + /* Two dots? Then chop off the last bit of what we already found out. */ + if (path_equal(first, "/..")) { + _cleanup_free_ char *parent = NULL; + _cleanup_close_ int fd_parent = -1; + + /* If we already are at the top, then going up will not change anything. This is in-line with + * how the kernel handles this. */ + if (empty_or_root(done)) + continue; + + parent = dirname_malloc(done); + if (!parent) + return -ENOMEM; + + /* Don't allow this to leave the root dir. */ + if (root && + path_startswith(done, root) && + !path_startswith(parent, root)) + continue; + + free_and_replace(done, parent); + + if (flags & CHASE_STEP) + goto chased_one; + + fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH); + if (fd_parent < 0) + return -errno; + + if (flags & CHASE_SAFE) { + if (fstat(fd_parent, &st) < 0) + return -errno; + + if (unsafe_transition(&previous_stat, &st)) + return log_unsafe_transition(fd, fd_parent, path, flags); + + previous_stat = st; + } + + safe_close(fd); + fd = TAKE_FD(fd_parent); + + continue; + } + + /* Otherwise let's see what this is. */ + child = openat(fd, first + n, O_CLOEXEC|O_NOFOLLOW|O_PATH); + if (child < 0) { + + if (errno == ENOENT && + (flags & CHASE_NONEXISTENT) && + (isempty(todo) || path_is_normalized(todo))) { + + /* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return + * what we got so far. But don't allow this if the remaining path contains "../ or "./" + * or something else weird. */ + + /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */ + if (streq_ptr(done, "/")) + *done = '\0'; + + if (!strextend(&done, first, todo, NULL)) + return -ENOMEM; + + exists = false; + break; + } + + return -errno; + } + + if (fstat(child, &st) < 0) + return -errno; + if ((flags & CHASE_SAFE) && + (empty_or_root(root) || (size_t)(todo - buffer) > strlen(root)) && + unsafe_transition(&previous_stat, &st)) + return log_unsafe_transition(fd, child, path, flags); + + previous_stat = st; + + if ((flags & CHASE_NO_AUTOFS) && + fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0) + return log_autofs_mount_point(child, path, flags); + + if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) { + char *joined; + _cleanup_free_ char *destination = NULL; + + /* This is a symlink, in this case read the destination. But let's make sure we don't follow + * symlinks without bounds. */ + if (--max_follow <= 0) + return -ELOOP; + + r = readlinkat_malloc(fd, first + n, &destination); + if (r < 0) + return r; + if (isempty(destination)) + return -EINVAL; + + if (path_is_absolute(destination)) { + + /* An absolute destination. Start the loop from the beginning, but use the root + * directory as base. */ + + safe_close(fd); + fd = open(root ?: "/", O_CLOEXEC|O_NOFOLLOW|O_PATH); + if (fd < 0) + return -errno; + + if (flags & CHASE_SAFE) { + if (fstat(fd, &st) < 0) + return -errno; + + if (unsafe_transition(&previous_stat, &st)) + return log_unsafe_transition(child, fd, path, flags); + + previous_stat = st; + } + + free(done); + + /* Note that we do not revalidate the root, we take it as is. */ + if (isempty(root)) + done = NULL; + else { + done = strdup(root); + if (!done) + return -ENOMEM; + } + + /* Prefix what's left to do with what we just read, and start the loop again, but + * remain in the current directory. */ + joined = path_join(destination, todo); + } else + joined = path_join("/", destination, todo); + if (!joined) + return -ENOMEM; + + free(buffer); + todo = buffer = joined; + + if (flags & CHASE_STEP) + goto chased_one; + + continue; + } + + /* If this is not a symlink, then let's just add the name we read to what we already verified. */ + if (!done) + done = TAKE_PTR(first); + else { + /* If done is "/", as first also contains slash at the head, then remove this redundant slash. */ + if (streq(done, "/")) + *done = '\0'; + + if (!strextend(&done, first, NULL)) + return -ENOMEM; + } + + /* And iterate again, but go one directory further down. */ + safe_close(fd); + fd = TAKE_FD(child); + } + + if (!done) { + /* Special case, turn the empty string into "/", to indicate the root directory. */ + done = strdup("/"); + if (!done) + return -ENOMEM; + } + + if (ret_path) + *ret_path = TAKE_PTR(done); + + if (ret_fd) { + /* Return the O_PATH fd we currently are looking to the caller. It can translate it to a + * proper fd by opening /proc/self/fd/xyz. */ + + assert(fd >= 0); + *ret_fd = TAKE_FD(fd); + } + + if (flags & CHASE_STEP) + return 1; + + return exists; + +chased_one: + if (ret_path) { + char *c; + + c = strjoin(strempty(done), todo); + if (!c) + return -ENOMEM; + + *ret_path = c; + } + + return 0; +} + +int chase_symlinks_and_open( + const char *path, + const char *root, + unsigned chase_flags, + int open_flags, + char **ret_path) { + + _cleanup_close_ int path_fd = -1; + _cleanup_free_ char *p = NULL; + int r; + + if (chase_flags & CHASE_NONEXISTENT) + return -EINVAL; + + if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) { + /* Shortcut this call if none of the special features of this call are requested */ + r = open(path, open_flags); + if (r < 0) + return -errno; + + return r; + } + + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); + + r = fd_reopen(path_fd, open_flags); + if (r < 0) + return r; + + if (ret_path) + *ret_path = TAKE_PTR(p); + + return r; +} + +int chase_symlinks_and_opendir( + const char *path, + const char *root, + unsigned chase_flags, + char **ret_path, + DIR **ret_dir) { + + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + _cleanup_close_ int path_fd = -1; + _cleanup_free_ char *p = NULL; + DIR *d; + int r; + + if (!ret_dir) + return -EINVAL; + if (chase_flags & CHASE_NONEXISTENT) + return -EINVAL; + + if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) { + /* Shortcut this call if none of the special features of this call are requested */ + d = opendir(path); + if (!d) + return -errno; + + *ret_dir = d; + return 0; + } + + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); + + xsprintf(procfs_path, "/proc/self/fd/%i", path_fd); + d = opendir(procfs_path); + if (!d) + return -errno; + + if (ret_path) + *ret_path = TAKE_PTR(p); + + *ret_dir = d; + return 0; +} + +int chase_symlinks_and_stat( + const char *path, + const char *root, + unsigned chase_flags, + char **ret_path, + struct stat *ret_stat, + int *ret_fd) { + + _cleanup_close_ int path_fd = -1; + _cleanup_free_ char *p = NULL; + int r; + + assert(path); + assert(ret_stat); + + if (chase_flags & CHASE_NONEXISTENT) + return -EINVAL; + + if (empty_or_root(root) && !ret_path && (chase_flags & (CHASE_NO_AUTOFS|CHASE_SAFE)) == 0) { + /* Shortcut this call if none of the special features of this call are requested */ + if (stat(path, ret_stat) < 0) + return -errno; + + return 1; + } + + r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd); + if (r < 0) + return r; + assert(path_fd >= 0); + + if (fstat(path_fd, ret_stat) < 0) + return -errno; + + if (ret_path) + *ret_path = TAKE_PTR(p); + if (ret_fd) + *ret_fd = TAKE_FD(path_fd); + + return 1; +} + +int access_fd(int fd, int mode) { + char p[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; + int r; + + /* Like access() but operates on an already open fd */ + + xsprintf(p, "/proc/self/fd/%i", fd); + r = access(p, mode); + if (r < 0) + return -errno; + + return r; +} + +void unlink_tempfilep(char (*p)[]) { + /* If the file is created with mkstemp(), it will (almost always) + * change the suffix. Treat this as a sign that the file was + * successfully created. We ignore both the rare case where the + * original suffix is used and unlink failures. */ + if (!endswith(*p, ".XXXXXX")) + (void) unlink_noerrno(*p); +} + +int unlinkat_deallocate(int fd, const char *name, int flags) { + _cleanup_close_ int truncate_fd = -1; + struct stat st; + off_t l, bs; + + /* Operates like unlinkat() but also deallocates the file contents if it is a regular file and there's no other + * link to it. This is useful to ensure that other processes that might have the file open for reading won't be + * able to keep the data pinned on disk forever. This call is particular useful whenever we execute clean-up + * jobs ("vacuuming"), where we want to make sure the data is really gone and the disk space released and + * returned to the free pool. + * + * Deallocation is preferably done by FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE (👊) if supported, which means + * the file won't change size. That's a good thing since we shouldn't needlessly trigger SIGBUS in other + * programs that have mmap()ed the file. (The assumption here is that changing file contents to all zeroes + * underneath those programs is the better choice than simply triggering SIGBUS in them which truncation does.) + * However if hole punching is not implemented in the kernel or file system we'll fall back to normal file + * truncation (🔪), as our goal of deallocating the data space trumps our goal of being nice to readers (💐). + * + * Note that we attempt deallocation, but failure to succeed with that is not considered fatal, as long as the + * primary job – to delete the file – is accomplished. */ + + if ((flags & AT_REMOVEDIR) == 0) { + truncate_fd = openat(fd, name, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK); + if (truncate_fd < 0) { + + /* If this failed because the file doesn't exist propagate the error right-away. Also, + * AT_REMOVEDIR wasn't set, and we tried to open the file for writing, which means EISDIR is + * returned when this is a directory but we are not supposed to delete those, hence propagate + * the error right-away too. */ + if (IN_SET(errno, ENOENT, EISDIR)) + return -errno; + + if (errno != ELOOP) /* don't complain if this is a symlink */ + log_debug_errno(errno, "Failed to open file '%s' for deallocation, ignoring: %m", name); + } + } + + if (unlinkat(fd, name, flags) < 0) + return -errno; + + if (truncate_fd < 0) /* Don't have a file handle, can't do more ☹️ */ + return 0; + + if (fstat(truncate_fd, &st) < 0) { + log_debug_errno(errno, "Failed to stat file '%s' for deallocation, ignoring: %m", name); + return 0; + } + + if (!S_ISREG(st.st_mode) || st.st_blocks == 0 || st.st_nlink > 0) + return 0; + + /* If this is a regular file, it actually took up space on disk and there are no other links it's time to + * punch-hole/truncate this to release the disk space. */ + + bs = MAX(st.st_blksize, 512); + l = DIV_ROUND_UP(st.st_size, bs) * bs; /* Round up to next block size */ + + if (fallocate(truncate_fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE, 0, l) >= 0) + return 0; /* Successfully punched a hole! 😊 */ + + /* Fall back to truncation */ + if (ftruncate(truncate_fd, 0) < 0) { + log_debug_errno(errno, "Failed to truncate file to 0, ignoring: %m"); + return 0; + } + + return 0; +} + +int fsync_directory_of_file(int fd) { + _cleanup_free_ char *path = NULL; + _cleanup_close_ int dfd = -1; + int r; + + r = fd_verify_regular(fd); + if (r < 0) + return r; + + r = fd_get_path(fd, &path); + if (r < 0) { + log_debug_errno(r, "Failed to query /proc/self/fd/%d%s: %m", + fd, + r == -EOPNOTSUPP ? ", ignoring" : ""); + + if (r == -EOPNOTSUPP) + /* If /proc is not available, we're most likely running in some + * chroot environment, and syncing the directory is not very + * important in that case. Let's just silently do nothing. */ + return 0; + + return r; + } + + if (!path_is_absolute(path)) + return -EINVAL; + + dfd = open_parent(path, O_CLOEXEC, 0); + if (dfd < 0) + return dfd; + + if (fsync(dfd) < 0) + return -errno; + + return 0; +} + +int fsync_full(int fd) { + int r, q; + + /* Sync both the file and the directory */ + + r = fsync(fd) < 0 ? -errno : 0; + q = fsync_directory_of_file(fd); + + return r < 0 ? r : q; +} + +int fsync_path_at(int at_fd, const char *path) { + _cleanup_close_ int opened_fd = -1; + int fd; + + if (isempty(path)) { + if (at_fd == AT_FDCWD) { + opened_fd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC); + if (opened_fd < 0) + return -errno; + + fd = opened_fd; + } else + fd = at_fd; + } else { + + opened_fd = openat(at_fd, path, O_RDONLY|O_CLOEXEC); + if (opened_fd < 0) + return -errno; + + fd = opened_fd; + } + + if (fsync(fd) < 0) + return -errno; + + return 0; +} + +int syncfs_path(int atfd, const char *path) { + _cleanup_close_ int fd = -1; + + assert(path); + + fd = openat(atfd, path, O_CLOEXEC|O_RDONLY|O_NONBLOCK); + if (fd < 0) + return -errno; + + if (syncfs(fd) < 0) + return -errno; + + return 0; +} + +int open_parent(const char *path, int flags, mode_t mode) { + _cleanup_free_ char *parent = NULL; + int fd; + + if (isempty(path)) + return -EINVAL; + if (path_equal(path, "/")) /* requesting the parent of the root dir is fishy, let's prohibit that */ + return -EINVAL; + + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; + + /* Let's insist on O_DIRECTORY since the parent of a file or directory is a directory. Except if we open an + * O_TMPFILE file, because in that case we are actually create a regular file below the parent directory. */ + + if (FLAGS_SET(flags, O_PATH)) + flags |= O_DIRECTORY; + else if (!FLAGS_SET(flags, O_TMPFILE)) + flags |= O_DIRECTORY|O_RDONLY; + + fd = open(parent, flags, mode); + if (fd < 0) + return -errno; + + return fd; +} diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h new file mode 100644 index 00000000..78d68be9 --- /dev/null +++ b/src/basic/fs-util.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "errno-util.h" +#include "time-util.h" + +#define MODE_INVALID ((mode_t) -1) + +/* The following macros add 1 when converting things, since 0 is a valid mode, while the pointer + * NULL is special */ +#define PTR_TO_MODE(p) ((mode_t) ((uintptr_t) (p)-1)) +#define MODE_TO_PTR(u) ((void *) ((uintptr_t) (u)+1)) + +int unlink_noerrno(const char *path); + +int rmdir_parents(const char *path, const char *stop); + +int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); + +int readlinkat_malloc(int fd, const char *p, char **ret); +int readlink_malloc(const char *p, char **r); +int readlink_value(const char *p, char **ret); +int readlink_and_make_absolute(const char *p, char **r); + +int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid); +int fchmod_and_chown(int fd, mode_t mode, uid_t uid, gid_t gid); + +int fchmod_umask(int fd, mode_t mode); +int fchmod_opath(int fd, mode_t m); + +int fd_warn_permissions(const char *path, int fd); + +#define laccess(path, mode) faccessat(AT_FDCWD, (path), (mode), AT_SYMLINK_NOFOLLOW) + +int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode); +int touch(const char *path); + +int symlink_idempotent(const char *from, const char *to, bool make_relative); + +int symlink_atomic(const char *from, const char *to); +int mknod_atomic(const char *path, mode_t mode, dev_t dev); +int mkfifo_atomic(const char *path, mode_t mode); +int mkfifoat_atomic(int dir_fd, const char *path, mode_t mode); + +int get_files_in_directory(const char *path, char ***list); + +int tmp_dir(const char **ret); +int var_tmp_dir(const char **ret); + +int unlink_or_warn(const char *filename); + +#define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1) + +#define FOREACH_INOTIFY_EVENT(e, buffer, sz) \ + for ((e) = &buffer.ev; \ + (uint8_t*) (e) < (uint8_t*) (buffer.raw) + (sz); \ + (e) = (struct inotify_event*) ((uint8_t*) (e) + sizeof(struct inotify_event) + (e)->len)) + +union inotify_event_buffer { + struct inotify_event ev; + uint8_t raw[INOTIFY_EVENT_MAX]; +}; + +int inotify_add_watch_fd(int fd, int what, uint32_t mask); +int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask); + +enum { + CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */ + CHASE_NONEXISTENT = 1 << 1, /* It's OK if the path doesn't actually exist. */ + CHASE_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */ + CHASE_SAFE = 1 << 3, /* Return EPERM if we ever traverse from unprivileged to privileged files or directories */ + CHASE_TRAIL_SLASH = 1 << 4, /* Any trailing slash will be preserved */ + CHASE_STEP = 1 << 5, /* Just execute a single step of the normalization */ + CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most compontent. With ret_fd, when the path's + * right-most component refers to symlink, return O_PATH fd of the symlink. */ + CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered */ +}; + +/* How many iterations to execute before returning -ELOOP */ +#define CHASE_SYMLINKS_MAX 32 + +int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret_path, int *ret_fd); + +int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path); +int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir); +int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd); + +/* Useful for usage with _cleanup_(), removes a directory and frees the pointer */ +static inline void rmdir_and_free(char *p) { + PROTECT_ERRNO; + (void) rmdir(p); + free(p); +} +DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rmdir_and_free); + +static inline void unlink_and_free(char *p) { + (void) unlink_noerrno(p); + free(p); +} +DEFINE_TRIVIAL_CLEANUP_FUNC(char*, unlink_and_free); + +int access_fd(int fd, int mode); + +void unlink_tempfilep(char (*p)[]); +int unlinkat_deallocate(int fd, const char *name, int flags); + +int fsync_directory_of_file(int fd); +int fsync_full(int fd); +int fsync_path_at(int at_fd, const char *path); + +int syncfs_path(int atfd, const char *path); + +int open_parent(const char *path, int flags, mode_t mode); diff --git a/src/basic/gcrypt-util.c b/src/basic/gcrypt-util.c new file mode 100644 index 00000000..a82be979 --- /dev/null +++ b/src/basic/gcrypt-util.c @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if HAVE_GCRYPT + +#include "gcrypt-util.h" +#include "hexdecoct.h" + +void initialize_libgcrypt(bool secmem) { + if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) + return; + + assert_se(gcry_check_version("1.4.5")); + + /* Turn off "secmem". Clients which wish to make use of this + * feature should initialize the library manually */ + if (!secmem) + gcry_control(GCRYCTL_DISABLE_SECMEM); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); +} + +int string_hashsum(const char *s, size_t len, int md_algorithm, char **out) { + _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL; + size_t hash_size; + void *hash; + char *enc; + + initialize_libgcrypt(false); + + hash_size = gcry_md_get_algo_dlen(md_algorithm); + assert(hash_size > 0); + + gcry_md_open(&md, md_algorithm, 0); + if (!md) + return -EIO; + + gcry_md_write(md, s, len); + + hash = gcry_md_read(md, 0); + if (!hash) + return -EIO; + + enc = hexmem(hash, hash_size); + if (!enc) + return -ENOMEM; + + *out = enc; + return 0; +} +#endif diff --git a/src/basic/gcrypt-util.h b/src/basic/gcrypt-util.h new file mode 100644 index 00000000..87eb6068 --- /dev/null +++ b/src/basic/gcrypt-util.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#pragma once + +#include +#include +#include + +#if HAVE_GCRYPT +#include + +#include "macro.h" + +void initialize_libgcrypt(bool secmem); +int string_hashsum(const char *s, size_t len, int md_algorithm, char **out); + +DEFINE_TRIVIAL_CLEANUP_FUNC(gcry_md_hd_t, gcry_md_close); +#endif + +static inline int string_hashsum_sha224(const char *s, size_t len, char **out) { +#if HAVE_GCRYPT + return string_hashsum(s, len, GCRY_MD_SHA224, out); +#else + return -EOPNOTSUPP; +#endif +} + +static inline int string_hashsum_sha256(const char *s, size_t len, char **out) { +#if HAVE_GCRYPT + return string_hashsum(s, len, GCRY_MD_SHA256, out); +#else + return -EOPNOTSUPP; +#endif +} diff --git a/src/basic/generate-af-list.sh b/src/basic/generate-af-list.sh new file mode 100755 index 00000000..6987877e --- /dev/null +++ b/src/basic/generate-af-list.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu + +$1 -E -dM -include sys/socket.h -include "$2" -include "$3" - +#include +#include +#include + +#include "dirent-util.h" +#include "errno-util.h" +#include "glob-util.h" +#include "macro.h" +#include "path-util.h" +#include "strv.h" + +static void closedir_wrapper(void* v) { + (void) closedir(v); +} + +int safe_glob(const char *path, int flags, glob_t *pglob) { + int k; + + /* We want to set GLOB_ALTDIRFUNC ourselves, don't allow it to be set. */ + assert(!(flags & GLOB_ALTDIRFUNC)); + + if (!pglob->gl_closedir) + pglob->gl_closedir = closedir_wrapper; + if (!pglob->gl_readdir) + pglob->gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot; + if (!pglob->gl_opendir) + pglob->gl_opendir = (void *(*)(const char *)) opendir; + if (!pglob->gl_lstat) + pglob->gl_lstat = lstat; + if (!pglob->gl_stat) + pglob->gl_stat = stat; + + errno = 0; + k = glob(path, flags | GLOB_ALTDIRFUNC, NULL, pglob); + if (k == GLOB_NOMATCH) + return -ENOENT; + if (k == GLOB_NOSPACE) + return -ENOMEM; + if (k != 0) + return errno_or_else(EIO); + if (strv_isempty(pglob->gl_pathv)) + return -ENOENT; + + return 0; +} + +int glob_exists(const char *path) { + _cleanup_globfree_ glob_t g = {}; + int k; + + assert(path); + + k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g); + if (k == -ENOENT) + return false; + if (k < 0) + return k; + return true; +} + +int glob_extend(char ***strv, const char *path) { + _cleanup_globfree_ glob_t g = {}; + int k; + + k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g); + if (k < 0) + return k; + + return strv_extend_strv(strv, g.gl_pathv, false); +} diff --git a/src/basic/glob-util.h b/src/basic/glob-util.h new file mode 100644 index 00000000..8b1bb02b --- /dev/null +++ b/src/basic/glob-util.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "macro.h" +#include "string-util.h" + +/* Note: this function modifies pglob to set various functions. */ +int safe_glob(const char *path, int flags, glob_t *pglob); + +int glob_exists(const char *path); +int glob_extend(char ***strv, const char *path); + +#define _cleanup_globfree_ _cleanup_(globfree) + +_pure_ static inline bool string_is_glob(const char *p) { + /* Check if a string contains any glob patterns. */ + return !!strpbrk(p, GLOB_CHARS); +} diff --git a/src/basic/gunicode.c b/src/basic/gunicode.c new file mode 100644 index 00000000..c51b1a7a --- /dev/null +++ b/src/basic/gunicode.c @@ -0,0 +1,110 @@ +/* gunicode.c - Unicode manipulation functions + * + * Copyright (C) 1999, 2000 Tom Tromey + * Copyright © 2000, 2005 Red Hat, Inc. + */ + +#include "gunicode.h" + +#define unichar uint32_t + +/** + * g_utf8_prev_char: + * @p: a pointer to a position within a UTF-8 encoded string + * + * Finds the previous UTF-8 character in the string before @p. + * + * @p does not have to be at the beginning of a UTF-8 character. No check + * is made to see if the character found is actually valid other than + * it starts with an appropriate byte. If @p might be the first + * character of the string, you must use g_utf8_find_prev_char() instead. + * + * Return value: a pointer to the found character. + **/ +char * +utf8_prev_char (const char *p) +{ + for (;;) + { + p--; + if ((*p & 0xc0) != 0x80) + return (char *)p; + } +} + +struct Interval +{ + unichar start, end; +}; + +static int +interval_compare (const void *key, const void *elt) +{ + unichar c = (unichar) (long) (key); + struct Interval *interval = (struct Interval *)elt; + + if (c < interval->start) + return -1; + if (c > interval->end) + return +1; + + return 0; +} + +/* + * NOTE: + * + * The tables for g_unichar_iswide() and g_unichar_iswide_cjk() are + * generated from the Unicode Character Database's file + * extracted/DerivedEastAsianWidth.txt using the gen-iswide-table.py + * in this way: + * + * ./gen-iswide-table.py < path/to/ucd/extracted/DerivedEastAsianWidth.txt | fmt + * + * Last update for Unicode 6.0. + */ + +/** + * g_unichar_iswide: + * @c: a Unicode character + * + * Determines if a character is typically rendered in a double-width + * cell. + * + * Return value: %TRUE if the character is wide + **/ +bool +unichar_iswide (unichar c) +{ + /* See NOTE earlier for how to update this table. */ + static const struct Interval wide[] = { + {0x1100, 0x115F}, {0x2329, 0x232A}, {0x2E80, 0x2E99}, {0x2E9B, 0x2EF3}, + {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, {0x3000, 0x303E}, {0x3041, 0x3096}, + {0x3099, 0x30FF}, {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA}, + {0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, {0x3250, 0x32FE}, + {0x3300, 0x4DBF}, {0x4E00, 0xA48C}, {0xA490, 0xA4C6}, {0xA960, 0xA97C}, + {0xAC00, 0xD7A3}, {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, + {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, {0xFFE0, 0xFFE6}, + {0x1B000, 0x1B001}, {0x1F200, 0x1F202}, {0x1F210, 0x1F23A}, + {0x1F240, 0x1F248}, {0x1F250, 0x1F251}, + {0x1F300, 0x1F567}, /* Miscellaneous Symbols and Pictographs */ + {0x20000, 0x2FFFD}, {0x30000, 0x3FFFD}, + }; + + if (bsearch ((void *)(uintptr_t)c, wide, (sizeof (wide) / sizeof ((wide)[0])), sizeof wide[0], + interval_compare)) + return true; + + return false; +} + +const char utf8_skip_data[256] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1 +}; diff --git a/src/basic/gunicode.h b/src/basic/gunicode.h new file mode 100644 index 00000000..a16b7b6f --- /dev/null +++ b/src/basic/gunicode.h @@ -0,0 +1,30 @@ +#pragma once + +/* gunicode.h - Unicode manipulation functions + * + * Copyright (C) 1999, 2000 Tom Tromey + * Copyright © 2000, 2005 Red Hat, Inc. + */ + +#include +#include +#include + +char *utf8_prev_char (const char *p); + +extern const char utf8_skip_data[256]; + +/** + * g_utf8_next_char: + * @p: Pointer to the start of a valid UTF-8 character + * + * Skips to the next character in a UTF-8 string. The string must be + * valid; this macro is as fast as possible, and has no error-checking. + * You would use this macro to iterate over a string character by + * character. The macro returns the start of the next UTF-8 character. + * Before using this macro, use g_utf8_validate() to validate strings + * that may contain invalid UTF-8. + */ +#define utf8_next_char(p) (char *)((p) + utf8_skip_data[*(const unsigned char *)(p)]) + +bool unichar_iswide (uint32_t c); diff --git a/src/basic/hash-funcs.c b/src/basic/hash-funcs.c new file mode 100644 index 00000000..fce33951 --- /dev/null +++ b/src/basic/hash-funcs.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "hash-funcs.h" +#include "path-util.h" + +void string_hash_func(const char *p, struct siphash *state) { + siphash24_compress(p, strlen(p) + 1, state); +} + +DEFINE_HASH_OPS(string_hash_ops, char, string_hash_func, string_compare_func); +DEFINE_HASH_OPS_FULL(string_hash_ops_free_free, + char, string_hash_func, string_compare_func, free, + char, free); + +void path_hash_func(const char *q, struct siphash *state) { + size_t n; + + assert(q); + assert(state); + + /* Calculates a hash for a path in a way this duplicate inner slashes don't make a differences, and also + * whether there's a trailing slash or not. This fits well with the semantics of path_compare(), which does + * similar checks and also doesn't care for trailing slashes. Note that relative and absolute paths (i.e. those + * which begin in a slash or not) will hash differently though. */ + + n = strspn(q, "/"); + if (n > 0) { /* Eat up initial slashes, and add one "/" to the hash for all of them */ + siphash24_compress(q, 1, state); + q += n; + } + + for (;;) { + /* Determine length of next component */ + n = strcspn(q, "/"); + if (n == 0) /* Reached the end? */ + break; + + /* Add this component to the hash and skip over it */ + siphash24_compress(q, n, state); + q += n; + + /* How many slashes follow this component? */ + n = strspn(q, "/"); + if (q[n] == 0) /* Is this a trailing slash? If so, we are at the end, and don't care about the slashes anymore */ + break; + + /* We are not add the end yet. Hash exactly one slash for all of the ones we just encountered. */ + siphash24_compress(q, 1, state); + q += n; + } +} + +DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare); + +void trivial_hash_func(const void *p, struct siphash *state) { + siphash24_compress(&p, sizeof(p), state); +} + +int trivial_compare_func(const void *a, const void *b) { + return CMP(a, b); +} + +const struct hash_ops trivial_hash_ops = { + .hash = trivial_hash_func, + .compare = trivial_compare_func, +}; + +void uint64_hash_func(const uint64_t *p, struct siphash *state) { + siphash24_compress(p, sizeof(uint64_t), state); +} + +int uint64_compare_func(const uint64_t *a, const uint64_t *b) { + return CMP(*a, *b); +} + +DEFINE_HASH_OPS(uint64_hash_ops, uint64_t, uint64_hash_func, uint64_compare_func); + +#if SIZEOF_DEV_T != 8 +void devt_hash_func(const dev_t *p, struct siphash *state) { + siphash24_compress(p, sizeof(dev_t), state); +} + +int devt_compare_func(const dev_t *a, const dev_t *b) { + return CMP(*a, *b); +} + +DEFINE_HASH_OPS(devt_hash_ops, dev_t, devt_hash_func, devt_compare_func); +#endif diff --git a/src/basic/hash-funcs.h b/src/basic/hash-funcs.h new file mode 100644 index 00000000..7bb5d1cd --- /dev/null +++ b/src/basic/hash-funcs.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "alloc-util.h" +#include "macro.h" +#include "siphash24.h" + +typedef void (*hash_func_t)(const void *p, struct siphash *state); +typedef int (*compare_func_t)(const void *a, const void *b); + +struct hash_ops { + hash_func_t hash; + compare_func_t compare; + free_func_t free_key; + free_func_t free_value; +}; + +#define _DEFINE_HASH_OPS(uq, name, type, hash_func, compare_func, free_key_func, free_value_func, scope) \ + _unused_ static void (* UNIQ_T(static_hash_wrapper, uq))(const type *, struct siphash *) = hash_func; \ + _unused_ static int (* UNIQ_T(static_compare_wrapper, uq))(const type *, const type *) = compare_func; \ + scope const struct hash_ops name = { \ + .hash = (hash_func_t) hash_func, \ + .compare = (compare_func_t) compare_func, \ + .free_key = free_key_func, \ + .free_value = free_value_func, \ + } + +#define _DEFINE_FREE_FUNC(uq, type, wrapper_name, func) \ + /* Type-safe free function */ \ + static void UNIQ_T(wrapper_name, uq)(void *a) { \ + type *_a = a; \ + func(_a); \ + } + +#define _DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(uq, name, type, hash_func, compare_func, free_func, scope) \ + _DEFINE_FREE_FUNC(uq, type, static_free_wrapper, free_func); \ + _DEFINE_HASH_OPS(uq, name, type, hash_func, compare_func, \ + UNIQ_T(static_free_wrapper, uq), NULL, scope) + +#define _DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(uq, name, type, hash_func, compare_func, type_value, free_func, scope) \ + _DEFINE_FREE_FUNC(uq, type_value, static_free_wrapper, free_func); \ + _DEFINE_HASH_OPS(uq, name, type, hash_func, compare_func, \ + NULL, UNIQ_T(static_free_wrapper, uq), scope) + +#define _DEFINE_HASH_OPS_FULL(uq, name, type, hash_func, compare_func, free_key_func, type_value, free_value_func, scope) \ + _DEFINE_FREE_FUNC(uq, type, static_free_key_wrapper, free_key_func); \ + _DEFINE_FREE_FUNC(uq, type_value, static_free_value_wrapper, free_value_func); \ + _DEFINE_HASH_OPS(uq, name, type, hash_func, compare_func, \ + UNIQ_T(static_free_key_wrapper, uq), \ + UNIQ_T(static_free_value_wrapper, uq), scope) + +#define DEFINE_HASH_OPS(name, type, hash_func, compare_func) \ + _DEFINE_HASH_OPS(UNIQ, name, type, hash_func, compare_func, NULL, NULL,) + +#define DEFINE_PRIVATE_HASH_OPS(name, type, hash_func, compare_func) \ + _DEFINE_HASH_OPS(UNIQ, name, type, hash_func, compare_func, NULL, NULL, static) + +#define DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(name, type, hash_func, compare_func, free_func) \ + _DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(UNIQ, name, type, hash_func, compare_func, free_func,) + +#define DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(name, type, hash_func, compare_func, free_func) \ + _DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(UNIQ, name, type, hash_func, compare_func, free_func, static) + +#define DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(name, type, hash_func, compare_func, value_type, free_func) \ + _DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(UNIQ, name, type, hash_func, compare_func, value_type, free_func,) + +#define DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(name, type, hash_func, compare_func, value_type, free_func) \ + _DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(UNIQ, name, type, hash_func, compare_func, value_type, free_func, static) + +#define DEFINE_HASH_OPS_FULL(name, type, hash_func, compare_func, free_key_func, value_type, free_value_func) \ + _DEFINE_HASH_OPS_FULL(UNIQ, name, type, hash_func, compare_func, free_key_func, value_type, free_value_func,) + +#define DEFINE_PRIVATE_HASH_OPS_FULL(name, type, hash_func, compare_func, free_key_func, value_type, free_value_func) \ + _DEFINE_HASH_OPS_FULL(UNIQ, name, type, hash_func, compare_func, free_key_func, value_type, free_value_func, static) + +void string_hash_func(const char *p, struct siphash *state); +#define string_compare_func strcmp +extern const struct hash_ops string_hash_ops; +extern const struct hash_ops string_hash_ops_free_free; + +void path_hash_func(const char *p, struct siphash *state); +extern const struct hash_ops path_hash_ops; + +/* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings + * or suchlike. */ +void trivial_hash_func(const void *p, struct siphash *state); +int trivial_compare_func(const void *a, const void *b) _const_; +extern const struct hash_ops trivial_hash_ops; + +/* 32bit values we can always just embed in the pointer itself, but in order to support 32bit archs we need store 64bit + * values indirectly, since they don't fit in a pointer. */ +void uint64_hash_func(const uint64_t *p, struct siphash *state); +int uint64_compare_func(const uint64_t *a, const uint64_t *b) _pure_; +extern const struct hash_ops uint64_hash_ops; + +/* On some archs dev_t is 32bit, and on others 64bit. And sometimes it's 64bit on 32bit archs, and sometimes 32bit on + * 64bit archs. Yuck! */ +#if SIZEOF_DEV_T != 8 +void devt_hash_func(const dev_t *p, struct siphash *state) _pure_; +int devt_compare_func(const dev_t *a, const dev_t *b) _pure_; +extern const struct hash_ops devt_hash_ops; +#else +#define devt_hash_func uint64_hash_func +#define devt_compare_func uint64_compare_func +#define devt_hash_ops uint64_hash_ops +#endif diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c new file mode 100644 index 00000000..4853514c --- /dev/null +++ b/src/basic/hashmap.c @@ -0,0 +1,1938 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fileio.h" +#include "hashmap.h" +#include "macro.h" +#include "memory-util.h" +#include "mempool.h" +#include "missing_syscall.h" +#include "process-util.h" +#include "random-util.h" +#include "set.h" +#include "siphash24.h" +#include "string-util.h" +#include "strv.h" + +#if ENABLE_DEBUG_HASHMAP +#include +#include "list.h" +#endif + +/* + * Implementation of hashmaps. + * Addressing: open + * - uses less RAM compared to closed addressing (chaining), because + * our entries are small (especially in Sets, which tend to contain + * the majority of entries in systemd). + * Collision resolution: Robin Hood + * - tends to equalize displacement of entries from their optimal buckets. + * Probe sequence: linear + * - though theoretically worse than random probing/uniform hashing/double + * hashing, it is good for cache locality. + * + * References: + * Celis, P. 1986. Robin Hood Hashing. + * Ph.D. Dissertation. University of Waterloo, Waterloo, Ont., Canada, Canada. + * https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf + * - The results are derived for random probing. Suggests deletion with + * tombstones and two mean-centered search methods. None of that works + * well for linear probing. + * + * Janson, S. 2005. Individual displacements for linear probing hashing with different insertion policies. + * ACM Trans. Algorithms 1, 2 (October 2005), 177-213. + * DOI=10.1145/1103963.1103964 http://doi.acm.org/10.1145/1103963.1103964 + * http://www.math.uu.se/~svante/papers/sj157.pdf + * - Applies to Robin Hood with linear probing. Contains remarks on + * the unsuitability of mean-centered search with linear probing. + * + * Viola, A. 2005. Exact distribution of individual displacements in linear probing hashing. + * ACM Trans. Algorithms 1, 2 (October 2005), 214-242. + * DOI=10.1145/1103963.1103965 http://doi.acm.org/10.1145/1103963.1103965 + * - Similar to Janson. Note that Viola writes about C_{m,n} (number of probes + * in a successful search), and Janson writes about displacement. C = d + 1. + * + * Goossaert, E. 2013. Robin Hood hashing: backward shift deletion. + * http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/ + * - Explanation of backward shift deletion with pictures. + * + * Khuong, P. 2013. The Other Robin Hood Hashing. + * http://www.pvk.ca/Blog/2013/11/26/the-other-robin-hood-hashing/ + * - Short summary of random vs. linear probing, and tombstones vs. backward shift. + */ + +/* + * XXX Ideas for improvement: + * For unordered hashmaps, randomize iteration order, similarly to Perl: + * http://blog.booking.com/hardening-perls-hash-function.html + */ + +/* INV_KEEP_FREE = 1 / (1 - max_load_factor) + * e.g. 1 / (1 - 0.8) = 5 ... keep one fifth of the buckets free. */ +#define INV_KEEP_FREE 5U + +/* Fields common to entries of all hashmap/set types */ +struct hashmap_base_entry { + const void *key; +}; + +/* Entry types for specific hashmap/set types + * hashmap_base_entry must be at the beginning of each entry struct. */ + +struct plain_hashmap_entry { + struct hashmap_base_entry b; + void *value; +}; + +struct ordered_hashmap_entry { + struct plain_hashmap_entry p; + unsigned iterate_next, iterate_previous; +}; + +struct set_entry { + struct hashmap_base_entry b; +}; + +/* In several functions it is advantageous to have the hash table extended + * virtually by a couple of additional buckets. We reserve special index values + * for these "swap" buckets. */ +#define _IDX_SWAP_BEGIN (UINT_MAX - 3) +#define IDX_PUT (_IDX_SWAP_BEGIN + 0) +#define IDX_TMP (_IDX_SWAP_BEGIN + 1) +#define _IDX_SWAP_END (_IDX_SWAP_BEGIN + 2) + +#define IDX_FIRST (UINT_MAX - 1) /* special index for freshly initialized iterators */ +#define IDX_NIL UINT_MAX /* special index value meaning "none" or "end" */ + +assert_cc(IDX_FIRST == _IDX_SWAP_END); +assert_cc(IDX_FIRST == _IDX_ITERATOR_FIRST); + +/* Storage space for the "swap" buckets. + * All entry types can fit into a ordered_hashmap_entry. */ +struct swap_entries { + struct ordered_hashmap_entry e[_IDX_SWAP_END - _IDX_SWAP_BEGIN]; +}; + +/* Distance from Initial Bucket */ +typedef uint8_t dib_raw_t; +#define DIB_RAW_OVERFLOW ((dib_raw_t)0xfdU) /* indicates DIB value is greater than representable */ +#define DIB_RAW_REHASH ((dib_raw_t)0xfeU) /* entry yet to be rehashed during in-place resize */ +#define DIB_RAW_FREE ((dib_raw_t)0xffU) /* a free bucket */ +#define DIB_RAW_INIT ((char)DIB_RAW_FREE) /* a byte to memset a DIB store with when initializing */ + +#define DIB_FREE UINT_MAX + +#if ENABLE_DEBUG_HASHMAP +struct hashmap_debug_info { + LIST_FIELDS(struct hashmap_debug_info, debug_list); + unsigned max_entries; /* high watermark of n_entries */ + + /* who allocated this hashmap */ + int line; + const char *file; + const char *func; + + /* fields to detect modification while iterating */ + unsigned put_count; /* counts puts into the hashmap */ + unsigned rem_count; /* counts removals from hashmap */ + unsigned last_rem_idx; /* remembers last removal index */ +}; + +/* Tracks all existing hashmaps. Get at it from gdb. See sd_dump_hashmaps.py */ +static LIST_HEAD(struct hashmap_debug_info, hashmap_debug_list); +static pthread_mutex_t hashmap_debug_list_mutex = PTHREAD_MUTEX_INITIALIZER; + +#define HASHMAP_DEBUG_FIELDS struct hashmap_debug_info debug; + +#else /* !ENABLE_DEBUG_HASHMAP */ +#define HASHMAP_DEBUG_FIELDS +#endif /* ENABLE_DEBUG_HASHMAP */ + +enum HashmapType { + HASHMAP_TYPE_PLAIN, + HASHMAP_TYPE_ORDERED, + HASHMAP_TYPE_SET, + _HASHMAP_TYPE_MAX +}; + +struct _packed_ indirect_storage { + void *storage; /* where buckets and DIBs are stored */ + uint8_t hash_key[HASH_KEY_SIZE]; /* hash key; changes during resize */ + + unsigned n_entries; /* number of stored entries */ + unsigned n_buckets; /* number of buckets */ + + unsigned idx_lowest_entry; /* Index below which all buckets are free. + Makes "while(hashmap_steal_first())" loops + O(n) instead of O(n^2) for unordered hashmaps. */ + uint8_t _pad[3]; /* padding for the whole HashmapBase */ + /* The bitfields in HashmapBase complete the alignment of the whole thing. */ +}; + +struct direct_storage { + /* This gives us 39 bytes on 64bit, or 35 bytes on 32bit. + * That's room for 4 set_entries + 4 DIB bytes + 3 unused bytes on 64bit, + * or 7 set_entries + 7 DIB bytes + 0 unused bytes on 32bit. */ + uint8_t storage[sizeof(struct indirect_storage)]; +}; + +#define DIRECT_BUCKETS(entry_t) \ + (sizeof(struct direct_storage) / (sizeof(entry_t) + sizeof(dib_raw_t))) + +/* We should be able to store at least one entry directly. */ +assert_cc(DIRECT_BUCKETS(struct ordered_hashmap_entry) >= 1); + +/* We have 3 bits for n_direct_entries. */ +assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3)); + +/* Hashmaps with directly stored entries all use this shared hash key. + * It's no big deal if the key is guessed, because there can be only + * a handful of directly stored entries in a hashmap. When a hashmap + * outgrows direct storage, it gets its own key for indirect storage. */ +static uint8_t shared_hash_key[HASH_KEY_SIZE]; +static bool shared_hash_key_initialized; + +/* Fields that all hashmap/set types must have */ +struct HashmapBase { + const struct hash_ops *hash_ops; /* hash and compare ops to use */ + + union _packed_ { + struct indirect_storage indirect; /* if has_indirect */ + struct direct_storage direct; /* if !has_indirect */ + }; + + enum HashmapType type:2; /* HASHMAP_TYPE_* */ + bool has_indirect:1; /* whether indirect storage is used */ + unsigned n_direct_entries:3; /* Number of entries in direct storage. + * Only valid if !has_indirect. */ + bool from_pool:1; /* whether was allocated from mempool */ + bool dirty:1; /* whether dirtied since last iterated_cache_get() */ + bool cached:1; /* whether this hashmap is being cached */ + HASHMAP_DEBUG_FIELDS /* optional hashmap_debug_info */ +}; + +/* Specific hash types + * HashmapBase must be at the beginning of each hashmap struct. */ + +struct Hashmap { + struct HashmapBase b; +}; + +struct OrderedHashmap { + struct HashmapBase b; + unsigned iterate_list_head, iterate_list_tail; +}; + +struct Set { + struct HashmapBase b; +}; + +typedef struct CacheMem { + const void **ptr; + size_t n_populated, n_allocated; + bool active:1; +} CacheMem; + +struct IteratedCache { + HashmapBase *hashmap; + CacheMem keys, values; +}; + +DEFINE_MEMPOOL(hashmap_pool, Hashmap, 8); +DEFINE_MEMPOOL(ordered_hashmap_pool, OrderedHashmap, 8); +/* No need for a separate Set pool */ +assert_cc(sizeof(Hashmap) == sizeof(Set)); + +struct hashmap_type_info { + size_t head_size; + size_t entry_size; + struct mempool *mempool; + unsigned n_direct_buckets; +}; + +static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = { + [HASHMAP_TYPE_PLAIN] = { + .head_size = sizeof(Hashmap), + .entry_size = sizeof(struct plain_hashmap_entry), + .mempool = &hashmap_pool, + .n_direct_buckets = DIRECT_BUCKETS(struct plain_hashmap_entry), + }, + [HASHMAP_TYPE_ORDERED] = { + .head_size = sizeof(OrderedHashmap), + .entry_size = sizeof(struct ordered_hashmap_entry), + .mempool = &ordered_hashmap_pool, + .n_direct_buckets = DIRECT_BUCKETS(struct ordered_hashmap_entry), + }, + [HASHMAP_TYPE_SET] = { + .head_size = sizeof(Set), + .entry_size = sizeof(struct set_entry), + .mempool = &hashmap_pool, + .n_direct_buckets = DIRECT_BUCKETS(struct set_entry), + }, +}; + +#if VALGRIND +_destructor_ static void cleanup_pools(void) { + _cleanup_free_ char *t = NULL; + int r; + + /* Be nice to valgrind */ + + /* The pool is only allocated by the main thread, but the memory can + * be passed to other threads. Let's clean up if we are the main thread + * and no other threads are live. */ + /* We build our own is_main_thread() here, which doesn't use C11 + * TLS based caching of the result. That's because valgrind apparently + * doesn't like malloc() (which C11 TLS internally uses) to be called + * from a GCC destructors. */ + if (getpid() != gettid()) + return; + + r = get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t); + if (r < 0 || !streq(t, "1")) + return; + + mempool_drop(&hashmap_pool); + mempool_drop(&ordered_hashmap_pool); +} +#endif + +static unsigned n_buckets(HashmapBase *h) { + return h->has_indirect ? h->indirect.n_buckets + : hashmap_type_info[h->type].n_direct_buckets; +} + +static unsigned n_entries(HashmapBase *h) { + return h->has_indirect ? h->indirect.n_entries + : h->n_direct_entries; +} + +static void n_entries_inc(HashmapBase *h) { + if (h->has_indirect) + h->indirect.n_entries++; + else + h->n_direct_entries++; +} + +static void n_entries_dec(HashmapBase *h) { + if (h->has_indirect) + h->indirect.n_entries--; + else + h->n_direct_entries--; +} + +static void *storage_ptr(HashmapBase *h) { + return h->has_indirect ? h->indirect.storage + : h->direct.storage; +} + +static uint8_t *hash_key(HashmapBase *h) { + return h->has_indirect ? h->indirect.hash_key + : shared_hash_key; +} + +static unsigned base_bucket_hash(HashmapBase *h, const void *p) { + struct siphash state; + uint64_t hash; + + siphash24_init(&state, hash_key(h)); + + h->hash_ops->hash(p, &state); + + hash = siphash24_finalize(&state); + + return (unsigned) (hash % n_buckets(h)); +} +#define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p) + +static void base_set_dirty(HashmapBase *h) { + h->dirty = true; +} +#define hashmap_set_dirty(h) base_set_dirty(HASHMAP_BASE(h)) + +static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) { + static uint8_t current[HASH_KEY_SIZE]; + static bool current_initialized = false; + + /* Returns a hash function key to use. In order to keep things + * fast we will not generate a new key each time we allocate a + * new hash table. Instead, we'll just reuse the most recently + * generated one, except if we never generated one or when we + * are rehashing an entire hash table because we reached a + * fill level */ + + if (!current_initialized || !reuse_is_ok) { + random_bytes(current, sizeof(current)); + current_initialized = true; + } + + memcpy(hash_key, current, sizeof(current)); +} + +static struct hashmap_base_entry *bucket_at(HashmapBase *h, unsigned idx) { + return (struct hashmap_base_entry*) + ((uint8_t*) storage_ptr(h) + idx * hashmap_type_info[h->type].entry_size); +} + +static struct plain_hashmap_entry *plain_bucket_at(Hashmap *h, unsigned idx) { + return (struct plain_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx); +} + +static struct ordered_hashmap_entry *ordered_bucket_at(OrderedHashmap *h, unsigned idx) { + return (struct ordered_hashmap_entry*) bucket_at(HASHMAP_BASE(h), idx); +} + +static struct set_entry *set_bucket_at(Set *h, unsigned idx) { + return (struct set_entry*) bucket_at(HASHMAP_BASE(h), idx); +} + +static struct ordered_hashmap_entry *bucket_at_swap(struct swap_entries *swap, unsigned idx) { + return &swap->e[idx - _IDX_SWAP_BEGIN]; +} + +/* Returns a pointer to the bucket at index idx. + * Understands real indexes and swap indexes, hence "_virtual". */ +static struct hashmap_base_entry *bucket_at_virtual(HashmapBase *h, struct swap_entries *swap, + unsigned idx) { + if (idx < _IDX_SWAP_BEGIN) + return bucket_at(h, idx); + + if (idx < _IDX_SWAP_END) + return &bucket_at_swap(swap, idx)->p.b; + + assert_not_reached("Invalid index"); +} + +static dib_raw_t *dib_raw_ptr(HashmapBase *h) { + return (dib_raw_t*) + ((uint8_t*) storage_ptr(h) + hashmap_type_info[h->type].entry_size * n_buckets(h)); +} + +static unsigned bucket_distance(HashmapBase *h, unsigned idx, unsigned from) { + return idx >= from ? idx - from + : n_buckets(h) + idx - from; +} + +static unsigned bucket_calculate_dib(HashmapBase *h, unsigned idx, dib_raw_t raw_dib) { + unsigned initial_bucket; + + if (raw_dib == DIB_RAW_FREE) + return DIB_FREE; + + if (_likely_(raw_dib < DIB_RAW_OVERFLOW)) + return raw_dib; + + /* + * Having an overflow DIB value is very unlikely. The hash function + * would have to be bad. For example, in a table of size 2^24 filled + * to load factor 0.9 the maximum observed DIB is only about 60. + * In theory (assuming I used Maxima correctly), for an infinite size + * hash table with load factor 0.8 the probability of a given entry + * having DIB > 40 is 1.9e-8. + * This returns the correct DIB value by recomputing the hash value in + * the unlikely case. XXX Hitting this case could be a hint to rehash. + */ + initial_bucket = bucket_hash(h, bucket_at(h, idx)->key); + return bucket_distance(h, idx, initial_bucket); +} + +static void bucket_set_dib(HashmapBase *h, unsigned idx, unsigned dib) { + dib_raw_ptr(h)[idx] = dib != DIB_FREE ? MIN(dib, DIB_RAW_OVERFLOW) : DIB_RAW_FREE; +} + +static unsigned skip_free_buckets(HashmapBase *h, unsigned idx) { + dib_raw_t *dibs; + + dibs = dib_raw_ptr(h); + + for ( ; idx < n_buckets(h); idx++) + if (dibs[idx] != DIB_RAW_FREE) + return idx; + + return IDX_NIL; +} + +static void bucket_mark_free(HashmapBase *h, unsigned idx) { + memzero(bucket_at(h, idx), hashmap_type_info[h->type].entry_size); + bucket_set_dib(h, idx, DIB_FREE); +} + +static void bucket_move_entry(HashmapBase *h, struct swap_entries *swap, + unsigned from, unsigned to) { + struct hashmap_base_entry *e_from, *e_to; + + assert(from != to); + + e_from = bucket_at_virtual(h, swap, from); + e_to = bucket_at_virtual(h, swap, to); + + memcpy(e_to, e_from, hashmap_type_info[h->type].entry_size); + + if (h->type == HASHMAP_TYPE_ORDERED) { + OrderedHashmap *lh = (OrderedHashmap*) h; + struct ordered_hashmap_entry *le, *le_to; + + le_to = (struct ordered_hashmap_entry*) e_to; + + if (le_to->iterate_next != IDX_NIL) { + le = (struct ordered_hashmap_entry*) + bucket_at_virtual(h, swap, le_to->iterate_next); + le->iterate_previous = to; + } + + if (le_to->iterate_previous != IDX_NIL) { + le = (struct ordered_hashmap_entry*) + bucket_at_virtual(h, swap, le_to->iterate_previous); + le->iterate_next = to; + } + + if (lh->iterate_list_head == from) + lh->iterate_list_head = to; + if (lh->iterate_list_tail == from) + lh->iterate_list_tail = to; + } +} + +static unsigned next_idx(HashmapBase *h, unsigned idx) { + return (idx + 1U) % n_buckets(h); +} + +static unsigned prev_idx(HashmapBase *h, unsigned idx) { + return (n_buckets(h) + idx - 1U) % n_buckets(h); +} + +static void *entry_value(HashmapBase *h, struct hashmap_base_entry *e) { + switch (h->type) { + + case HASHMAP_TYPE_PLAIN: + case HASHMAP_TYPE_ORDERED: + return ((struct plain_hashmap_entry*)e)->value; + + case HASHMAP_TYPE_SET: + return (void*) e->key; + + default: + assert_not_reached("Unknown hashmap type"); + } +} + +static void base_remove_entry(HashmapBase *h, unsigned idx) { + unsigned left, right, prev, dib; + dib_raw_t raw_dib, *dibs; + + dibs = dib_raw_ptr(h); + assert(dibs[idx] != DIB_RAW_FREE); + +#if ENABLE_DEBUG_HASHMAP + h->debug.rem_count++; + h->debug.last_rem_idx = idx; +#endif + + left = idx; + /* Find the stop bucket ("right"). It is either free or has DIB == 0. */ + for (right = next_idx(h, left); ; right = next_idx(h, right)) { + raw_dib = dibs[right]; + if (IN_SET(raw_dib, 0, DIB_RAW_FREE)) + break; + + /* The buckets are not supposed to be all occupied and with DIB > 0. + * That would mean we could make everyone better off by shifting them + * backward. This scenario is impossible. */ + assert(left != right); + } + + if (h->type == HASHMAP_TYPE_ORDERED) { + OrderedHashmap *lh = (OrderedHashmap*) h; + struct ordered_hashmap_entry *le = ordered_bucket_at(lh, idx); + + if (le->iterate_next != IDX_NIL) + ordered_bucket_at(lh, le->iterate_next)->iterate_previous = le->iterate_previous; + else + lh->iterate_list_tail = le->iterate_previous; + + if (le->iterate_previous != IDX_NIL) + ordered_bucket_at(lh, le->iterate_previous)->iterate_next = le->iterate_next; + else + lh->iterate_list_head = le->iterate_next; + } + + /* Now shift all buckets in the interval (left, right) one step backwards */ + for (prev = left, left = next_idx(h, left); left != right; + prev = left, left = next_idx(h, left)) { + dib = bucket_calculate_dib(h, left, dibs[left]); + assert(dib != 0); + bucket_move_entry(h, NULL, left, prev); + bucket_set_dib(h, prev, dib - 1); + } + + bucket_mark_free(h, prev); + n_entries_dec(h); + base_set_dirty(h); +} +#define remove_entry(h, idx) base_remove_entry(HASHMAP_BASE(h), idx) + +static unsigned hashmap_iterate_in_insertion_order(OrderedHashmap *h, Iterator *i) { + struct ordered_hashmap_entry *e; + unsigned idx; + + assert(h); + assert(i); + + if (i->idx == IDX_NIL) + goto at_end; + + if (i->idx == IDX_FIRST && h->iterate_list_head == IDX_NIL) + goto at_end; + + if (i->idx == IDX_FIRST) { + idx = h->iterate_list_head; + e = ordered_bucket_at(h, idx); + } else { + idx = i->idx; + e = ordered_bucket_at(h, idx); + /* + * We allow removing the current entry while iterating, but removal may cause + * a backward shift. The next entry may thus move one bucket to the left. + * To detect when it happens, we remember the key pointer of the entry we were + * going to iterate next. If it does not match, there was a backward shift. + */ + if (e->p.b.key != i->next_key) { + idx = prev_idx(HASHMAP_BASE(h), idx); + e = ordered_bucket_at(h, idx); + } + assert(e->p.b.key == i->next_key); + } + +#if ENABLE_DEBUG_HASHMAP + i->prev_idx = idx; +#endif + + if (e->iterate_next != IDX_NIL) { + struct ordered_hashmap_entry *n; + i->idx = e->iterate_next; + n = ordered_bucket_at(h, i->idx); + i->next_key = n->p.b.key; + } else + i->idx = IDX_NIL; + + return idx; + +at_end: + i->idx = IDX_NIL; + return IDX_NIL; +} + +static unsigned hashmap_iterate_in_internal_order(HashmapBase *h, Iterator *i) { + unsigned idx; + + assert(h); + assert(i); + + if (i->idx == IDX_NIL) + goto at_end; + + if (i->idx == IDX_FIRST) { + /* fast forward to the first occupied bucket */ + if (h->has_indirect) { + i->idx = skip_free_buckets(h, h->indirect.idx_lowest_entry); + h->indirect.idx_lowest_entry = i->idx; + } else + i->idx = skip_free_buckets(h, 0); + + if (i->idx == IDX_NIL) + goto at_end; + } else { + struct hashmap_base_entry *e; + + assert(i->idx > 0); + + e = bucket_at(h, i->idx); + /* + * We allow removing the current entry while iterating, but removal may cause + * a backward shift. The next entry may thus move one bucket to the left. + * To detect when it happens, we remember the key pointer of the entry we were + * going to iterate next. If it does not match, there was a backward shift. + */ + if (e->key != i->next_key) + e = bucket_at(h, --i->idx); + + assert(e->key == i->next_key); + } + + idx = i->idx; +#if ENABLE_DEBUG_HASHMAP + i->prev_idx = idx; +#endif + + i->idx = skip_free_buckets(h, i->idx + 1); + if (i->idx != IDX_NIL) + i->next_key = bucket_at(h, i->idx)->key; + else + i->idx = IDX_NIL; + + return idx; + +at_end: + i->idx = IDX_NIL; + return IDX_NIL; +} + +static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) { + if (!h) { + i->idx = IDX_NIL; + return IDX_NIL; + } + +#if ENABLE_DEBUG_HASHMAP + if (i->idx == IDX_FIRST) { + i->put_count = h->debug.put_count; + i->rem_count = h->debug.rem_count; + } else { + /* While iterating, must not add any new entries */ + assert(i->put_count == h->debug.put_count); + /* ... or remove entries other than the current one */ + assert(i->rem_count == h->debug.rem_count || + (i->rem_count == h->debug.rem_count - 1 && + i->prev_idx == h->debug.last_rem_idx)); + /* Reset our removals counter */ + i->rem_count = h->debug.rem_count; + } +#endif + + return h->type == HASHMAP_TYPE_ORDERED ? hashmap_iterate_in_insertion_order((OrderedHashmap*) h, i) + : hashmap_iterate_in_internal_order(h, i); +} + +bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key) { + struct hashmap_base_entry *e; + void *data; + unsigned idx; + + idx = hashmap_iterate_entry(h, i); + if (idx == IDX_NIL) { + if (value) + *value = NULL; + if (key) + *key = NULL; + + return false; + } + + e = bucket_at(h, idx); + data = entry_value(h, e); + if (value) + *value = data; + if (key) + *key = e->key; + + return true; +} + +bool set_iterate(const Set *s, Iterator *i, void **value) { + return internal_hashmap_iterate(HASHMAP_BASE((Set*) s), i, value, NULL); +} + +#define HASHMAP_FOREACH_IDX(idx, h, i) \ + for ((i) = ITERATOR_FIRST, (idx) = hashmap_iterate_entry((h), &(i)); \ + (idx != IDX_NIL); \ + (idx) = hashmap_iterate_entry((h), &(i))) + +IteratedCache *internal_hashmap_iterated_cache_new(HashmapBase *h) { + IteratedCache *cache; + + assert(h); + assert(!h->cached); + + if (h->cached) + return NULL; + + cache = new0(IteratedCache, 1); + if (!cache) + return NULL; + + cache->hashmap = h; + h->cached = true; + + return cache; +} + +static void reset_direct_storage(HashmapBase *h) { + const struct hashmap_type_info *hi = &hashmap_type_info[h->type]; + void *p; + + assert(!h->has_indirect); + + p = mempset(h->direct.storage, 0, hi->entry_size * hi->n_direct_buckets); + memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets); +} + +static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) { + HashmapBase *h; + const struct hashmap_type_info *hi = &hashmap_type_info[type]; + bool up; + + up = mempool_enabled(); + + h = up ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size); + if (!h) + return NULL; + + h->type = type; + h->from_pool = up; + h->hash_ops = hash_ops ?: &trivial_hash_ops; + + if (type == HASHMAP_TYPE_ORDERED) { + OrderedHashmap *lh = (OrderedHashmap*)h; + lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL; + } + + reset_direct_storage(h); + + if (!shared_hash_key_initialized) { + random_bytes(shared_hash_key, sizeof(shared_hash_key)); + shared_hash_key_initialized= true; + } + +#if ENABLE_DEBUG_HASHMAP + h->debug.func = func; + h->debug.file = file; + h->debug.line = line; + assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0); + LIST_PREPEND(debug_list, hashmap_debug_list, &h->debug); + assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0); +#endif + + return h; +} + +Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { + return (Hashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS); +} + +OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { + return (OrderedHashmap*) hashmap_base_new(hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS); +} + +Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { + return (Set*) hashmap_base_new(hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS); +} + +static int hashmap_base_ensure_allocated(HashmapBase **h, const struct hash_ops *hash_ops, + enum HashmapType type HASHMAP_DEBUG_PARAMS) { + HashmapBase *q; + + assert(h); + + if (*h) + return 0; + + q = hashmap_base_new(hash_ops, type HASHMAP_DEBUG_PASS_ARGS); + if (!q) + return -ENOMEM; + + *h = q; + return 0; +} + +int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { + return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_PLAIN HASHMAP_DEBUG_PASS_ARGS); +} + +int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { + return hashmap_base_ensure_allocated((HashmapBase**)h, hash_ops, HASHMAP_TYPE_ORDERED HASHMAP_DEBUG_PASS_ARGS); +} + +int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS) { + return hashmap_base_ensure_allocated((HashmapBase**)s, hash_ops, HASHMAP_TYPE_SET HASHMAP_DEBUG_PASS_ARGS); +} + +static void hashmap_free_no_clear(HashmapBase *h) { + assert(!h->has_indirect); + assert(h->n_direct_entries == 0); + +#if ENABLE_DEBUG_HASHMAP + assert_se(pthread_mutex_lock(&hashmap_debug_list_mutex) == 0); + LIST_REMOVE(debug_list, hashmap_debug_list, &h->debug); + assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0); +#endif + + if (h->from_pool) { + /* Ensure that the object didn't get migrated between threads. */ + assert_se(is_main_thread()); + mempool_free_tile(hashmap_type_info[h->type].mempool, h); + } else + free(h); +} + +HashmapBase *internal_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) { + if (h) { + internal_hashmap_clear(h, default_free_key, default_free_value); + hashmap_free_no_clear(h); + } + + return NULL; +} + +void internal_hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) { + free_func_t free_key, free_value; + if (!h) + return; + + free_key = h->hash_ops->free_key ?: default_free_key; + free_value = h->hash_ops->free_value ?: default_free_value; + + if (free_key || free_value) { + + /* If destructor calls are defined, let's destroy things defensively: let's take the item out of the + * hash table, and only then call the destructor functions. If these destructors then try to unregister + * themselves from our hash table a second time, the entry is already gone. */ + + while (internal_hashmap_size(h) > 0) { + void *k = NULL; + void *v; + + v = internal_hashmap_first_key_and_value(h, true, &k); + + if (free_key) + free_key(k); + + if (free_value) + free_value(v); + } + } + + if (h->has_indirect) { + free(h->indirect.storage); + h->has_indirect = false; + } + + h->n_direct_entries = 0; + reset_direct_storage(h); + + if (h->type == HASHMAP_TYPE_ORDERED) { + OrderedHashmap *lh = (OrderedHashmap*) h; + lh->iterate_list_head = lh->iterate_list_tail = IDX_NIL; + } + + base_set_dirty(h); +} + +static int resize_buckets(HashmapBase *h, unsigned entries_add); + +/* + * Finds an empty bucket to put an entry into, starting the scan at 'idx'. + * Performs Robin Hood swaps as it goes. The entry to put must be placed + * by the caller into swap slot IDX_PUT. + * If used for in-place resizing, may leave a displaced entry in swap slot + * IDX_PUT. Caller must rehash it next. + * Returns: true if it left a displaced entry to rehash next in IDX_PUT, + * false otherwise. + */ +static bool hashmap_put_robin_hood(HashmapBase *h, unsigned idx, + struct swap_entries *swap) { + dib_raw_t raw_dib, *dibs; + unsigned dib, distance; + +#if ENABLE_DEBUG_HASHMAP + h->debug.put_count++; +#endif + + dibs = dib_raw_ptr(h); + + for (distance = 0; ; distance++) { + raw_dib = dibs[idx]; + if (IN_SET(raw_dib, DIB_RAW_FREE, DIB_RAW_REHASH)) { + if (raw_dib == DIB_RAW_REHASH) + bucket_move_entry(h, swap, idx, IDX_TMP); + + if (h->has_indirect && h->indirect.idx_lowest_entry > idx) + h->indirect.idx_lowest_entry = idx; + + bucket_set_dib(h, idx, distance); + bucket_move_entry(h, swap, IDX_PUT, idx); + if (raw_dib == DIB_RAW_REHASH) { + bucket_move_entry(h, swap, IDX_TMP, IDX_PUT); + return true; + } + + return false; + } + + dib = bucket_calculate_dib(h, idx, raw_dib); + + if (dib < distance) { + /* Found a wealthier entry. Go Robin Hood! */ + bucket_set_dib(h, idx, distance); + + /* swap the entries */ + bucket_move_entry(h, swap, idx, IDX_TMP); + bucket_move_entry(h, swap, IDX_PUT, idx); + bucket_move_entry(h, swap, IDX_TMP, IDX_PUT); + + distance = dib; + } + + idx = next_idx(h, idx); + } +} + +/* + * Puts an entry into a hashmap, boldly - no check whether key already exists. + * The caller must place the entry (only its key and value, not link indexes) + * in swap slot IDX_PUT. + * Caller must ensure: the key does not exist yet in the hashmap. + * that resize is not needed if !may_resize. + * Returns: 1 if entry was put successfully. + * -ENOMEM if may_resize==true and resize failed with -ENOMEM. + * Cannot return -ENOMEM if !may_resize. + */ +static int hashmap_base_put_boldly(HashmapBase *h, unsigned idx, + struct swap_entries *swap, bool may_resize) { + struct ordered_hashmap_entry *new_entry; + int r; + + assert(idx < n_buckets(h)); + + new_entry = bucket_at_swap(swap, IDX_PUT); + + if (may_resize) { + r = resize_buckets(h, 1); + if (r < 0) + return r; + if (r > 0) + idx = bucket_hash(h, new_entry->p.b.key); + } + assert(n_entries(h) < n_buckets(h)); + + if (h->type == HASHMAP_TYPE_ORDERED) { + OrderedHashmap *lh = (OrderedHashmap*) h; + + new_entry->iterate_next = IDX_NIL; + new_entry->iterate_previous = lh->iterate_list_tail; + + if (lh->iterate_list_tail != IDX_NIL) { + struct ordered_hashmap_entry *old_tail; + + old_tail = ordered_bucket_at(lh, lh->iterate_list_tail); + assert(old_tail->iterate_next == IDX_NIL); + old_tail->iterate_next = IDX_PUT; + } + + lh->iterate_list_tail = IDX_PUT; + if (lh->iterate_list_head == IDX_NIL) + lh->iterate_list_head = IDX_PUT; + } + + assert_se(hashmap_put_robin_hood(h, idx, swap) == false); + + n_entries_inc(h); +#if ENABLE_DEBUG_HASHMAP + h->debug.max_entries = MAX(h->debug.max_entries, n_entries(h)); +#endif + + base_set_dirty(h); + + return 1; +} +#define hashmap_put_boldly(h, idx, swap, may_resize) \ + hashmap_base_put_boldly(HASHMAP_BASE(h), idx, swap, may_resize) + +/* + * Returns 0 if resize is not needed. + * 1 if successfully resized. + * -ENOMEM on allocation failure. + */ +static int resize_buckets(HashmapBase *h, unsigned entries_add) { + struct swap_entries swap; + void *new_storage; + dib_raw_t *old_dibs, *new_dibs; + const struct hashmap_type_info *hi; + unsigned idx, optimal_idx; + unsigned old_n_buckets, new_n_buckets, n_rehashed, new_n_entries; + uint8_t new_shift; + bool rehash_next; + + assert(h); + + hi = &hashmap_type_info[h->type]; + new_n_entries = n_entries(h) + entries_add; + + /* overflow? */ + if (_unlikely_(new_n_entries < entries_add)) + return -ENOMEM; + + /* For direct storage we allow 100% load, because it's tiny. */ + if (!h->has_indirect && new_n_entries <= hi->n_direct_buckets) + return 0; + + /* + * Load factor = n/m = 1 - (1/INV_KEEP_FREE). + * From it follows: m = n + n/(INV_KEEP_FREE - 1) + */ + new_n_buckets = new_n_entries + new_n_entries / (INV_KEEP_FREE - 1); + /* overflow? */ + if (_unlikely_(new_n_buckets < new_n_entries)) + return -ENOMEM; + + if (_unlikely_(new_n_buckets > UINT_MAX / (hi->entry_size + sizeof(dib_raw_t)))) + return -ENOMEM; + + old_n_buckets = n_buckets(h); + + if (_likely_(new_n_buckets <= old_n_buckets)) + return 0; + + new_shift = log2u_round_up(MAX( + new_n_buckets * (hi->entry_size + sizeof(dib_raw_t)), + 2 * sizeof(struct direct_storage))); + + /* Realloc storage (buckets and DIB array). */ + new_storage = realloc(h->has_indirect ? h->indirect.storage : NULL, + 1U << new_shift); + if (!new_storage) + return -ENOMEM; + + /* Must upgrade direct to indirect storage. */ + if (!h->has_indirect) { + memcpy(new_storage, h->direct.storage, + old_n_buckets * (hi->entry_size + sizeof(dib_raw_t))); + h->indirect.n_entries = h->n_direct_entries; + h->indirect.idx_lowest_entry = 0; + h->n_direct_entries = 0; + } + + /* Get a new hash key. If we've just upgraded to indirect storage, + * allow reusing a previously generated key. It's still a different key + * from the shared one that we used for direct storage. */ + get_hash_key(h->indirect.hash_key, !h->has_indirect); + + h->has_indirect = true; + h->indirect.storage = new_storage; + h->indirect.n_buckets = (1U << new_shift) / + (hi->entry_size + sizeof(dib_raw_t)); + + old_dibs = (dib_raw_t*)((uint8_t*) new_storage + hi->entry_size * old_n_buckets); + new_dibs = dib_raw_ptr(h); + + /* + * Move the DIB array to the new place, replacing valid DIB values with + * DIB_RAW_REHASH to indicate all of the used buckets need rehashing. + * Note: Overlap is not possible, because we have at least doubled the + * number of buckets and dib_raw_t is smaller than any entry type. + */ + for (idx = 0; idx < old_n_buckets; idx++) { + assert(old_dibs[idx] != DIB_RAW_REHASH); + new_dibs[idx] = old_dibs[idx] == DIB_RAW_FREE ? DIB_RAW_FREE + : DIB_RAW_REHASH; + } + + /* Zero the area of newly added entries (including the old DIB area) */ + memzero(bucket_at(h, old_n_buckets), + (n_buckets(h) - old_n_buckets) * hi->entry_size); + + /* The upper half of the new DIB array needs initialization */ + memset(&new_dibs[old_n_buckets], DIB_RAW_INIT, + (n_buckets(h) - old_n_buckets) * sizeof(dib_raw_t)); + + /* Rehash entries that need it */ + n_rehashed = 0; + for (idx = 0; idx < old_n_buckets; idx++) { + if (new_dibs[idx] != DIB_RAW_REHASH) + continue; + + optimal_idx = bucket_hash(h, bucket_at(h, idx)->key); + + /* + * Not much to do if by luck the entry hashes to its current + * location. Just set its DIB. + */ + if (optimal_idx == idx) { + new_dibs[idx] = 0; + n_rehashed++; + continue; + } + + new_dibs[idx] = DIB_RAW_FREE; + bucket_move_entry(h, &swap, idx, IDX_PUT); + /* bucket_move_entry does not clear the source */ + memzero(bucket_at(h, idx), hi->entry_size); + + do { + /* + * Find the new bucket for the current entry. This may make + * another entry homeless and load it into IDX_PUT. + */ + rehash_next = hashmap_put_robin_hood(h, optimal_idx, &swap); + n_rehashed++; + + /* Did the current entry displace another one? */ + if (rehash_next) + optimal_idx = bucket_hash(h, bucket_at_swap(&swap, IDX_PUT)->p.b.key); + } while (rehash_next); + } + + assert(n_rehashed == n_entries(h)); + + return 1; +} + +/* + * Finds an entry with a matching key + * Returns: index of the found entry, or IDX_NIL if not found. + */ +static unsigned base_bucket_scan(HashmapBase *h, unsigned idx, const void *key) { + struct hashmap_base_entry *e; + unsigned dib, distance; + dib_raw_t *dibs = dib_raw_ptr(h); + + assert(idx < n_buckets(h)); + + for (distance = 0; ; distance++) { + if (dibs[idx] == DIB_RAW_FREE) + return IDX_NIL; + + dib = bucket_calculate_dib(h, idx, dibs[idx]); + + if (dib < distance) + return IDX_NIL; + if (dib == distance) { + e = bucket_at(h, idx); + if (h->hash_ops->compare(e->key, key) == 0) + return idx; + } + + idx = next_idx(h, idx); + } +} +#define bucket_scan(h, idx, key) base_bucket_scan(HASHMAP_BASE(h), idx, key) + +int hashmap_put(Hashmap *h, const void *key, void *value) { + struct swap_entries swap; + struct plain_hashmap_entry *e; + unsigned hash, idx; + + assert(h); + + hash = bucket_hash(h, key); + idx = bucket_scan(h, hash, key); + if (idx != IDX_NIL) { + e = plain_bucket_at(h, idx); + if (e->value == value) + return 0; + return -EEXIST; + } + + e = &bucket_at_swap(&swap, IDX_PUT)->p; + e->b.key = key; + e->value = value; + return hashmap_put_boldly(h, hash, &swap, true); +} + +int set_put(Set *s, const void *key) { + struct swap_entries swap; + struct hashmap_base_entry *e; + unsigned hash, idx; + + assert(s); + + hash = bucket_hash(s, key); + idx = bucket_scan(s, hash, key); + if (idx != IDX_NIL) + return 0; + + e = &bucket_at_swap(&swap, IDX_PUT)->p.b; + e->key = key; + return hashmap_put_boldly(s, hash, &swap, true); +} + +int hashmap_replace(Hashmap *h, const void *key, void *value) { + struct swap_entries swap; + struct plain_hashmap_entry *e; + unsigned hash, idx; + + assert(h); + + hash = bucket_hash(h, key); + idx = bucket_scan(h, hash, key); + if (idx != IDX_NIL) { + e = plain_bucket_at(h, idx); +#if ENABLE_DEBUG_HASHMAP + /* Although the key is equal, the key pointer may have changed, + * and this would break our assumption for iterating. So count + * this operation as incompatible with iteration. */ + if (e->b.key != key) { + h->b.debug.put_count++; + h->b.debug.rem_count++; + h->b.debug.last_rem_idx = idx; + } +#endif + e->b.key = key; + e->value = value; + hashmap_set_dirty(h); + + return 0; + } + + e = &bucket_at_swap(&swap, IDX_PUT)->p; + e->b.key = key; + e->value = value; + return hashmap_put_boldly(h, hash, &swap, true); +} + +int hashmap_update(Hashmap *h, const void *key, void *value) { + struct plain_hashmap_entry *e; + unsigned hash, idx; + + assert(h); + + hash = bucket_hash(h, key); + idx = bucket_scan(h, hash, key); + if (idx == IDX_NIL) + return -ENOENT; + + e = plain_bucket_at(h, idx); + e->value = value; + hashmap_set_dirty(h); + + return 0; +} + +void *internal_hashmap_get(HashmapBase *h, const void *key) { + struct hashmap_base_entry *e; + unsigned hash, idx; + + if (!h) + return NULL; + + hash = bucket_hash(h, key); + idx = bucket_scan(h, hash, key); + if (idx == IDX_NIL) + return NULL; + + e = bucket_at(h, idx); + return entry_value(h, e); +} + +void *hashmap_get2(Hashmap *h, const void *key, void **key2) { + struct plain_hashmap_entry *e; + unsigned hash, idx; + + if (!h) + return NULL; + + hash = bucket_hash(h, key); + idx = bucket_scan(h, hash, key); + if (idx == IDX_NIL) + return NULL; + + e = plain_bucket_at(h, idx); + if (key2) + *key2 = (void*) e->b.key; + + return e->value; +} + +bool internal_hashmap_contains(HashmapBase *h, const void *key) { + unsigned hash; + + if (!h) + return false; + + hash = bucket_hash(h, key); + return bucket_scan(h, hash, key) != IDX_NIL; +} + +void *internal_hashmap_remove(HashmapBase *h, const void *key) { + struct hashmap_base_entry *e; + unsigned hash, idx; + void *data; + + if (!h) + return NULL; + + hash = bucket_hash(h, key); + idx = bucket_scan(h, hash, key); + if (idx == IDX_NIL) + return NULL; + + e = bucket_at(h, idx); + data = entry_value(h, e); + remove_entry(h, idx); + + return data; +} + +void *hashmap_remove2(Hashmap *h, const void *key, void **rkey) { + struct plain_hashmap_entry *e; + unsigned hash, idx; + void *data; + + if (!h) { + if (rkey) + *rkey = NULL; + return NULL; + } + + hash = bucket_hash(h, key); + idx = bucket_scan(h, hash, key); + if (idx == IDX_NIL) { + if (rkey) + *rkey = NULL; + return NULL; + } + + e = plain_bucket_at(h, idx); + data = e->value; + if (rkey) + *rkey = (void*) e->b.key; + + remove_entry(h, idx); + + return data; +} + +int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value) { + struct swap_entries swap; + struct plain_hashmap_entry *e; + unsigned old_hash, new_hash, idx; + + if (!h) + return -ENOENT; + + old_hash = bucket_hash(h, old_key); + idx = bucket_scan(h, old_hash, old_key); + if (idx == IDX_NIL) + return -ENOENT; + + new_hash = bucket_hash(h, new_key); + if (bucket_scan(h, new_hash, new_key) != IDX_NIL) + return -EEXIST; + + remove_entry(h, idx); + + e = &bucket_at_swap(&swap, IDX_PUT)->p; + e->b.key = new_key; + e->value = value; + assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1); + + return 0; +} + +int set_remove_and_put(Set *s, const void *old_key, const void *new_key) { + struct swap_entries swap; + struct hashmap_base_entry *e; + unsigned old_hash, new_hash, idx; + + if (!s) + return -ENOENT; + + old_hash = bucket_hash(s, old_key); + idx = bucket_scan(s, old_hash, old_key); + if (idx == IDX_NIL) + return -ENOENT; + + new_hash = bucket_hash(s, new_key); + if (bucket_scan(s, new_hash, new_key) != IDX_NIL) + return -EEXIST; + + remove_entry(s, idx); + + e = &bucket_at_swap(&swap, IDX_PUT)->p.b; + e->key = new_key; + assert_se(hashmap_put_boldly(s, new_hash, &swap, false) == 1); + + return 0; +} + +int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value) { + struct swap_entries swap; + struct plain_hashmap_entry *e; + unsigned old_hash, new_hash, idx_old, idx_new; + + if (!h) + return -ENOENT; + + old_hash = bucket_hash(h, old_key); + idx_old = bucket_scan(h, old_hash, old_key); + if (idx_old == IDX_NIL) + return -ENOENT; + + old_key = bucket_at(HASHMAP_BASE(h), idx_old)->key; + + new_hash = bucket_hash(h, new_key); + idx_new = bucket_scan(h, new_hash, new_key); + if (idx_new != IDX_NIL) + if (idx_old != idx_new) { + remove_entry(h, idx_new); + /* Compensate for a possible backward shift. */ + if (old_key != bucket_at(HASHMAP_BASE(h), idx_old)->key) + idx_old = prev_idx(HASHMAP_BASE(h), idx_old); + assert(old_key == bucket_at(HASHMAP_BASE(h), idx_old)->key); + } + + remove_entry(h, idx_old); + + e = &bucket_at_swap(&swap, IDX_PUT)->p; + e->b.key = new_key; + e->value = value; + assert_se(hashmap_put_boldly(h, new_hash, &swap, false) == 1); + + return 0; +} + +void *internal_hashmap_remove_value(HashmapBase *h, const void *key, void *value) { + struct hashmap_base_entry *e; + unsigned hash, idx; + + if (!h) + return NULL; + + hash = bucket_hash(h, key); + idx = bucket_scan(h, hash, key); + if (idx == IDX_NIL) + return NULL; + + e = bucket_at(h, idx); + if (entry_value(h, e) != value) + return NULL; + + remove_entry(h, idx); + + return value; +} + +static unsigned find_first_entry(HashmapBase *h) { + Iterator i = ITERATOR_FIRST; + + if (!h || !n_entries(h)) + return IDX_NIL; + + return hashmap_iterate_entry(h, &i); +} + +void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key) { + struct hashmap_base_entry *e; + void *key, *data; + unsigned idx; + + idx = find_first_entry(h); + if (idx == IDX_NIL) { + if (ret_key) + *ret_key = NULL; + return NULL; + } + + e = bucket_at(h, idx); + key = (void*) e->key; + data = entry_value(h, e); + + if (remove) + remove_entry(h, idx); + + if (ret_key) + *ret_key = key; + + return data; +} + +unsigned internal_hashmap_size(HashmapBase *h) { + if (!h) + return 0; + + return n_entries(h); +} + +unsigned internal_hashmap_buckets(HashmapBase *h) { + if (!h) + return 0; + + return n_buckets(h); +} + +int internal_hashmap_merge(Hashmap *h, Hashmap *other) { + Iterator i; + unsigned idx; + + assert(h); + + HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) { + struct plain_hashmap_entry *pe = plain_bucket_at(other, idx); + int r; + + r = hashmap_put(h, pe->b.key, pe->value); + if (r < 0 && r != -EEXIST) + return r; + } + + return 0; +} + +int set_merge(Set *s, Set *other) { + Iterator i; + unsigned idx; + + assert(s); + + HASHMAP_FOREACH_IDX(idx, HASHMAP_BASE(other), i) { + struct set_entry *se = set_bucket_at(other, idx); + int r; + + r = set_put(s, se->b.key); + if (r < 0) + return r; + } + + return 0; +} + +int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add) { + int r; + + assert(h); + + r = resize_buckets(h, entries_add); + if (r < 0) + return r; + + return 0; +} + +/* + * The same as hashmap_merge(), but every new item from other is moved to h. + * Keys already in h are skipped and stay in other. + * Returns: 0 on success. + * -ENOMEM on alloc failure, in which case no move has been done. + */ +int internal_hashmap_move(HashmapBase *h, HashmapBase *other) { + struct swap_entries swap; + struct hashmap_base_entry *e, *n; + Iterator i; + unsigned idx; + int r; + + assert(h); + + if (!other) + return 0; + + assert(other->type == h->type); + + /* + * This reserves buckets for the worst case, where none of other's + * entries are yet present in h. This is preferable to risking + * an allocation failure in the middle of the moving and having to + * rollback or return a partial result. + */ + r = resize_buckets(h, n_entries(other)); + if (r < 0) + return r; + + HASHMAP_FOREACH_IDX(idx, other, i) { + unsigned h_hash; + + e = bucket_at(other, idx); + h_hash = bucket_hash(h, e->key); + if (bucket_scan(h, h_hash, e->key) != IDX_NIL) + continue; + + n = &bucket_at_swap(&swap, IDX_PUT)->p.b; + n->key = e->key; + if (h->type != HASHMAP_TYPE_SET) + ((struct plain_hashmap_entry*) n)->value = + ((struct plain_hashmap_entry*) e)->value; + assert_se(hashmap_put_boldly(h, h_hash, &swap, false) == 1); + + remove_entry(other, idx); + } + + return 0; +} + +int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key) { + struct swap_entries swap; + unsigned h_hash, other_hash, idx; + struct hashmap_base_entry *e, *n; + int r; + + assert(h); + + h_hash = bucket_hash(h, key); + if (bucket_scan(h, h_hash, key) != IDX_NIL) + return -EEXIST; + + if (!other) + return -ENOENT; + + assert(other->type == h->type); + + other_hash = bucket_hash(other, key); + idx = bucket_scan(other, other_hash, key); + if (idx == IDX_NIL) + return -ENOENT; + + e = bucket_at(other, idx); + + n = &bucket_at_swap(&swap, IDX_PUT)->p.b; + n->key = e->key; + if (h->type != HASHMAP_TYPE_SET) + ((struct plain_hashmap_entry*) n)->value = + ((struct plain_hashmap_entry*) e)->value; + r = hashmap_put_boldly(h, h_hash, &swap, true); + if (r < 0) + return r; + + remove_entry(other, idx); + return 0; +} + +HashmapBase *internal_hashmap_copy(HashmapBase *h) { + HashmapBase *copy; + int r; + + assert(h); + + copy = hashmap_base_new(h->hash_ops, h->type HASHMAP_DEBUG_SRC_ARGS); + if (!copy) + return NULL; + + switch (h->type) { + case HASHMAP_TYPE_PLAIN: + case HASHMAP_TYPE_ORDERED: + r = hashmap_merge((Hashmap*)copy, (Hashmap*)h); + break; + case HASHMAP_TYPE_SET: + r = set_merge((Set*)copy, (Set*)h); + break; + default: + assert_not_reached("Unknown hashmap type"); + } + + if (r < 0) { + internal_hashmap_free(copy, false, false); + return NULL; + } + + return copy; +} + +char **internal_hashmap_get_strv(HashmapBase *h) { + char **sv; + Iterator i; + unsigned idx, n; + + sv = new(char*, n_entries(h)+1); + if (!sv) + return NULL; + + n = 0; + HASHMAP_FOREACH_IDX(idx, h, i) + sv[n++] = entry_value(h, bucket_at(h, idx)); + sv[n] = NULL; + + return sv; +} + +void *ordered_hashmap_next(OrderedHashmap *h, const void *key) { + struct ordered_hashmap_entry *e; + unsigned hash, idx; + + if (!h) + return NULL; + + hash = bucket_hash(h, key); + idx = bucket_scan(h, hash, key); + if (idx == IDX_NIL) + return NULL; + + e = ordered_bucket_at(h, idx); + if (e->iterate_next == IDX_NIL) + return NULL; + return ordered_bucket_at(h, e->iterate_next)->p.value; +} + +int set_consume(Set *s, void *value) { + int r; + + assert(s); + assert(value); + + r = set_put(s, value); + if (r <= 0) + free(value); + + return r; +} + +int hashmap_put_strdup(Hashmap **h, const char *k, const char *v) { + int r; + + r = hashmap_ensure_allocated(h, &string_hash_ops_free_free); + if (r < 0) + return r; + + _cleanup_free_ char *kdup = NULL, *vdup = NULL; + kdup = strdup(k); + vdup = strdup(v); + if (!kdup || !vdup) + return -ENOMEM; + + r = hashmap_put(*h, kdup, vdup); + if (r < 0) { + if (r == -EEXIST && streq(v, hashmap_get(*h, kdup))) + return 0; + return r; + } + + assert(r > 0); /* 0 would mean vdup is already in the hashmap, which cannot be */ + kdup = vdup = NULL; + + return 0; +} + +int set_put_strdup(Set *s, const char *p) { + char *c; + + assert(s); + assert(p); + + if (set_contains(s, (char*) p)) + return 0; + + c = strdup(p); + if (!c) + return -ENOMEM; + + return set_consume(s, c); +} + +int set_put_strdupv(Set *s, char **l) { + int n = 0, r; + char **i; + + assert(s); + + STRV_FOREACH(i, l) { + r = set_put_strdup(s, *i); + if (r < 0) + return r; + + n += r; + } + + return n; +} + +int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags) { + const char *p = v; + int r; + + assert(s); + assert(v); + + for (;;) { + char *word; + + r = extract_first_word(&p, &word, separators, flags); + if (r <= 0) + return r; + + r = set_consume(s, word); + if (r < 0) + return r; + } +} + +/* expand the cachemem if needed, return true if newly (re)activated. */ +static int cachemem_maintain(CacheMem *mem, unsigned size) { + assert(mem); + + if (!GREEDY_REALLOC(mem->ptr, mem->n_allocated, size)) { + if (size > 0) + return -ENOMEM; + } + + if (!mem->active) { + mem->active = true; + return true; + } + + return false; +} + +int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries) { + bool sync_keys = false, sync_values = false; + unsigned size; + int r; + + assert(cache); + assert(cache->hashmap); + + size = n_entries(cache->hashmap); + + if (res_keys) { + r = cachemem_maintain(&cache->keys, size); + if (r < 0) + return r; + + sync_keys = r; + } else + cache->keys.active = false; + + if (res_values) { + r = cachemem_maintain(&cache->values, size); + if (r < 0) + return r; + + sync_values = r; + } else + cache->values.active = false; + + if (cache->hashmap->dirty) { + if (cache->keys.active) + sync_keys = true; + if (cache->values.active) + sync_values = true; + + cache->hashmap->dirty = false; + } + + if (sync_keys || sync_values) { + unsigned i, idx; + Iterator iter; + + i = 0; + HASHMAP_FOREACH_IDX(idx, cache->hashmap, iter) { + struct hashmap_base_entry *e; + + e = bucket_at(cache->hashmap, idx); + + if (sync_keys) + cache->keys.ptr[i] = e->key; + if (sync_values) + cache->values.ptr[i] = entry_value(cache->hashmap, e); + i++; + } + } + + if (res_keys) + *res_keys = cache->keys.ptr; + if (res_values) + *res_values = cache->values.ptr; + if (res_n_entries) + *res_n_entries = size; + + return 0; +} + +IteratedCache *iterated_cache_free(IteratedCache *cache) { + if (cache) { + free(cache->keys.ptr); + free(cache->values.ptr); + } + + return mfree(cache); +} diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h new file mode 100644 index 00000000..65adc925 --- /dev/null +++ b/src/basic/hashmap.h @@ -0,0 +1,433 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "hash-funcs.h" +#include "macro.h" +#include "util.h" + +/* + * A hash table implementation. As a minor optimization a NULL hashmap object + * will be treated as empty hashmap for all read operations. That way it is not + * necessary to instantiate an object for each Hashmap use. + * + * If ENABLE_DEBUG_HASHMAP is defined (by configuring with --enable-debug=hashmap), + * the implementation will: + * - store extra data for debugging and statistics (see tools/gdb-sd_dump_hashmaps.py) + * - perform extra checks for invalid use of iterators + */ + +#define HASH_KEY_SIZE 16 + +typedef void* (*hashmap_destroy_t)(void *p); + +/* The base type for all hashmap and set types. Many functions in the + * implementation take (HashmapBase*) parameters and are run-time polymorphic, + * though the API is not meant to be polymorphic (do not call functions + * internal_*() directly). */ +typedef struct HashmapBase HashmapBase; + +/* Specific hashmap/set types */ +typedef struct Hashmap Hashmap; /* Maps keys to values */ +typedef struct OrderedHashmap OrderedHashmap; /* Like Hashmap, but also remembers entry insertion order */ +typedef struct Set Set; /* Stores just keys */ + +typedef struct IteratedCache IteratedCache; /* Caches the iterated order of one of the above */ + +/* Ideally the Iterator would be an opaque struct, but it is instantiated + * by hashmap users, so the definition has to be here. Do not use its fields + * directly. */ +typedef struct { + unsigned idx; /* index of an entry to be iterated next */ + const void *next_key; /* expected value of that entry's key pointer */ +#if ENABLE_DEBUG_HASHMAP + unsigned put_count; /* hashmap's put_count recorded at start of iteration */ + unsigned rem_count; /* hashmap's rem_count in previous iteration */ + unsigned prev_idx; /* idx in previous iteration */ +#endif +} Iterator; + +#define _IDX_ITERATOR_FIRST (UINT_MAX - 1) +#define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL }) + +/* Macros for type checking */ +#define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \ + (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \ + __builtin_types_compatible_p(typeof(h), Hashmap*) || \ + __builtin_types_compatible_p(typeof(h), OrderedHashmap*) || \ + __builtin_types_compatible_p(typeof(h), Set*)) + +#define PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h) \ + (__builtin_types_compatible_p(typeof(h), Hashmap*) || \ + __builtin_types_compatible_p(typeof(h), OrderedHashmap*)) \ + +#define HASHMAP_BASE(h) \ + __builtin_choose_expr(PTR_COMPATIBLE_WITH_HASHMAP_BASE(h), \ + (HashmapBase*)(h), \ + (void)0) + +#define PLAIN_HASHMAP(h) \ + __builtin_choose_expr(PTR_COMPATIBLE_WITH_PLAIN_HASHMAP(h), \ + (Hashmap*)(h), \ + (void)0) + +#if ENABLE_DEBUG_HASHMAP +# define HASHMAP_DEBUG_PARAMS , const char *func, const char *file, int line +# define HASHMAP_DEBUG_SRC_ARGS , __func__, PROJECT_FILE, __LINE__ +# define HASHMAP_DEBUG_PASS_ARGS , func, file, line +#else +# define HASHMAP_DEBUG_PARAMS +# define HASHMAP_DEBUG_SRC_ARGS +# define HASHMAP_DEBUG_PASS_ARGS +#endif + +Hashmap *internal_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +#define hashmap_new(ops) internal_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) +#define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS) + +HashmapBase *internal_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value); +static inline Hashmap *hashmap_free(Hashmap *h) { + return (void*) internal_hashmap_free(HASHMAP_BASE(h), NULL, NULL); +} +static inline OrderedHashmap *ordered_hashmap_free(OrderedHashmap *h) { + return (void*) internal_hashmap_free(HASHMAP_BASE(h), NULL, NULL); +} + +static inline Hashmap *hashmap_free_free(Hashmap *h) { + return (void*) internal_hashmap_free(HASHMAP_BASE(h), NULL, free); +} +static inline OrderedHashmap *ordered_hashmap_free_free(OrderedHashmap *h) { + return (void*) internal_hashmap_free(HASHMAP_BASE(h), NULL, free); +} + +static inline Hashmap *hashmap_free_free_key(Hashmap *h) { + return (void*) internal_hashmap_free(HASHMAP_BASE(h), free, NULL); +} +static inline OrderedHashmap *ordered_hashmap_free_free_key(OrderedHashmap *h) { + return (void*) internal_hashmap_free(HASHMAP_BASE(h), free, NULL); +} + +static inline Hashmap *hashmap_free_free_free(Hashmap *h) { + return (void*) internal_hashmap_free(HASHMAP_BASE(h), free, free); +} +static inline OrderedHashmap *ordered_hashmap_free_free_free(OrderedHashmap *h) { + return (void*) internal_hashmap_free(HASHMAP_BASE(h), free, free); +} + +IteratedCache *iterated_cache_free(IteratedCache *cache); +int iterated_cache_get(IteratedCache *cache, const void ***res_keys, const void ***res_values, unsigned *res_n_entries); + +HashmapBase *internal_hashmap_copy(HashmapBase *h); +static inline Hashmap *hashmap_copy(Hashmap *h) { + return (Hashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); +} +static inline OrderedHashmap *ordered_hashmap_copy(OrderedHashmap *h) { + return (OrderedHashmap*) internal_hashmap_copy(HASHMAP_BASE(h)); +} + +int internal_hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +int internal_ordered_hashmap_ensure_allocated(OrderedHashmap **h, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +#define hashmap_ensure_allocated(h, ops) internal_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) +#define ordered_hashmap_ensure_allocated(h, ops) internal_ordered_hashmap_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) + +IteratedCache *internal_hashmap_iterated_cache_new(HashmapBase *h); +static inline IteratedCache *hashmap_iterated_cache_new(Hashmap *h) { + return (IteratedCache*) internal_hashmap_iterated_cache_new(HASHMAP_BASE(h)); +} +static inline IteratedCache *ordered_hashmap_iterated_cache_new(OrderedHashmap *h) { + return (IteratedCache*) internal_hashmap_iterated_cache_new(HASHMAP_BASE(h)); +} + +int hashmap_put(Hashmap *h, const void *key, void *value); +static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void *value) { + return hashmap_put(PLAIN_HASHMAP(h), key, value); +} + +int hashmap_put_strdup(Hashmap **h, const char *k, const char *v); + +int hashmap_update(Hashmap *h, const void *key, void *value); +static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) { + return hashmap_update(PLAIN_HASHMAP(h), key, value); +} + +int hashmap_replace(Hashmap *h, const void *key, void *value); +static inline int ordered_hashmap_replace(OrderedHashmap *h, const void *key, void *value) { + return hashmap_replace(PLAIN_HASHMAP(h), key, value); +} + +void *internal_hashmap_get(HashmapBase *h, const void *key); +static inline void *hashmap_get(Hashmap *h, const void *key) { + return internal_hashmap_get(HASHMAP_BASE(h), key); +} +static inline void *ordered_hashmap_get(OrderedHashmap *h, const void *key) { + return internal_hashmap_get(HASHMAP_BASE(h), key); +} + +void *hashmap_get2(Hashmap *h, const void *key, void **rkey); +static inline void *ordered_hashmap_get2(OrderedHashmap *h, const void *key, void **rkey) { + return hashmap_get2(PLAIN_HASHMAP(h), key, rkey); +} + +bool internal_hashmap_contains(HashmapBase *h, const void *key); +static inline bool hashmap_contains(Hashmap *h, const void *key) { + return internal_hashmap_contains(HASHMAP_BASE(h), key); +} +static inline bool ordered_hashmap_contains(OrderedHashmap *h, const void *key) { + return internal_hashmap_contains(HASHMAP_BASE(h), key); +} + +void *internal_hashmap_remove(HashmapBase *h, const void *key); +static inline void *hashmap_remove(Hashmap *h, const void *key) { + return internal_hashmap_remove(HASHMAP_BASE(h), key); +} +static inline void *ordered_hashmap_remove(OrderedHashmap *h, const void *key) { + return internal_hashmap_remove(HASHMAP_BASE(h), key); +} + +void *hashmap_remove2(Hashmap *h, const void *key, void **rkey); +static inline void *ordered_hashmap_remove2(OrderedHashmap *h, const void *key, void **rkey) { + return hashmap_remove2(PLAIN_HASHMAP(h), key, rkey); +} + +void *internal_hashmap_remove_value(HashmapBase *h, const void *key, void *value); +static inline void *hashmap_remove_value(Hashmap *h, const void *key, void *value) { + return internal_hashmap_remove_value(HASHMAP_BASE(h), key, value); +} + +static inline void *ordered_hashmap_remove_value(OrderedHashmap *h, const void *key, void *value) { + return hashmap_remove_value(PLAIN_HASHMAP(h), key, value); +} + +int hashmap_remove_and_put(Hashmap *h, const void *old_key, const void *new_key, void *value); +static inline int ordered_hashmap_remove_and_put(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) { + return hashmap_remove_and_put(PLAIN_HASHMAP(h), old_key, new_key, value); +} + +int hashmap_remove_and_replace(Hashmap *h, const void *old_key, const void *new_key, void *value); +static inline int ordered_hashmap_remove_and_replace(OrderedHashmap *h, const void *old_key, const void *new_key, void *value) { + return hashmap_remove_and_replace(PLAIN_HASHMAP(h), old_key, new_key, value); +} + +/* Since merging data from a OrderedHashmap into a Hashmap or vice-versa + * should just work, allow this by having looser type-checking here. */ +int internal_hashmap_merge(Hashmap *h, Hashmap *other); +#define hashmap_merge(h, other) internal_hashmap_merge(PLAIN_HASHMAP(h), PLAIN_HASHMAP(other)) +#define ordered_hashmap_merge(h, other) hashmap_merge(h, other) + +int internal_hashmap_reserve(HashmapBase *h, unsigned entries_add); +static inline int hashmap_reserve(Hashmap *h, unsigned entries_add) { + return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); +} +static inline int ordered_hashmap_reserve(OrderedHashmap *h, unsigned entries_add) { + return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); +} + +int internal_hashmap_move(HashmapBase *h, HashmapBase *other); +/* Unlike hashmap_merge, hashmap_move does not allow mixing the types. */ +static inline int hashmap_move(Hashmap *h, Hashmap *other) { + return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other)); +} +static inline int ordered_hashmap_move(OrderedHashmap *h, OrderedHashmap *other) { + return internal_hashmap_move(HASHMAP_BASE(h), HASHMAP_BASE(other)); +} + +int internal_hashmap_move_one(HashmapBase *h, HashmapBase *other, const void *key); +static inline int hashmap_move_one(Hashmap *h, Hashmap *other, const void *key) { + return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key); +} +static inline int ordered_hashmap_move_one(OrderedHashmap *h, OrderedHashmap *other, const void *key) { + return internal_hashmap_move_one(HASHMAP_BASE(h), HASHMAP_BASE(other), key); +} + +unsigned internal_hashmap_size(HashmapBase *h) _pure_; +static inline unsigned hashmap_size(Hashmap *h) { + return internal_hashmap_size(HASHMAP_BASE(h)); +} +static inline unsigned ordered_hashmap_size(OrderedHashmap *h) { + return internal_hashmap_size(HASHMAP_BASE(h)); +} + +static inline bool hashmap_isempty(Hashmap *h) { + return hashmap_size(h) == 0; +} +static inline bool ordered_hashmap_isempty(OrderedHashmap *h) { + return ordered_hashmap_size(h) == 0; +} + +unsigned internal_hashmap_buckets(HashmapBase *h) _pure_; +static inline unsigned hashmap_buckets(Hashmap *h) { + return internal_hashmap_buckets(HASHMAP_BASE(h)); +} +static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) { + return internal_hashmap_buckets(HASHMAP_BASE(h)); +} + +bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key); +static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) { + return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key); +} +static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) { + return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key); +} + +void internal_hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value); +static inline void hashmap_clear(Hashmap *h) { + internal_hashmap_clear(HASHMAP_BASE(h), NULL, NULL); +} +static inline void ordered_hashmap_clear(OrderedHashmap *h) { + internal_hashmap_clear(HASHMAP_BASE(h), NULL, NULL); +} + +static inline void hashmap_clear_free(Hashmap *h) { + internal_hashmap_clear(HASHMAP_BASE(h), NULL, free); +} +static inline void ordered_hashmap_clear_free(OrderedHashmap *h) { + internal_hashmap_clear(HASHMAP_BASE(h), NULL, free); +} + +static inline void hashmap_clear_free_key(Hashmap *h) { + internal_hashmap_clear(HASHMAP_BASE(h), free, NULL); +} +static inline void ordered_hashmap_clear_free_key(OrderedHashmap *h) { + internal_hashmap_clear(HASHMAP_BASE(h), free, NULL); +} + +static inline void hashmap_clear_free_free(Hashmap *h) { + internal_hashmap_clear(HASHMAP_BASE(h), free, free); +} +static inline void ordered_hashmap_clear_free_free(OrderedHashmap *h) { + internal_hashmap_clear(HASHMAP_BASE(h), free, free); +} + +/* + * Note about all *_first*() functions + * + * For plain Hashmaps and Sets the order of entries is undefined. + * The functions find whatever entry is first in the implementation + * internal order. + * + * Only for OrderedHashmaps the order is well defined and finding + * the first entry is O(1). + */ + +void *internal_hashmap_first_key_and_value(HashmapBase *h, bool remove, void **ret_key); +static inline void *hashmap_steal_first_key_and_value(Hashmap *h, void **ret) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret); +} +static inline void *ordered_hashmap_steal_first_key_and_value(OrderedHashmap *h, void **ret) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, ret); +} +static inline void *hashmap_first_key_and_value(Hashmap *h, void **ret) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret); +} +static inline void *ordered_hashmap_first_key_and_value(OrderedHashmap *h, void **ret) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, ret); +} + +static inline void *hashmap_steal_first(Hashmap *h) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL); +} +static inline void *ordered_hashmap_steal_first(OrderedHashmap *h) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), true, NULL); +} +static inline void *hashmap_first(Hashmap *h) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL); +} +static inline void *ordered_hashmap_first(OrderedHashmap *h) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE(h), false, NULL); +} + +static inline void *internal_hashmap_first_key(HashmapBase *h, bool remove) { + void *key = NULL; + + (void) internal_hashmap_first_key_and_value(HASHMAP_BASE(h), remove, &key); + return key; +} +static inline void *hashmap_steal_first_key(Hashmap *h) { + return internal_hashmap_first_key(HASHMAP_BASE(h), true); +} +static inline void *ordered_hashmap_steal_first_key(OrderedHashmap *h) { + return internal_hashmap_first_key(HASHMAP_BASE(h), true); +} +static inline void *hashmap_first_key(Hashmap *h) { + return internal_hashmap_first_key(HASHMAP_BASE(h), false); +} +static inline void *ordered_hashmap_first_key(OrderedHashmap *h) { + return internal_hashmap_first_key(HASHMAP_BASE(h), false); +} + +#define hashmap_clear_with_destructor(_s, _f) \ + ({ \ + void *_item; \ + while ((_item = hashmap_steal_first(_s))) \ + _f(_item); \ + }) +#define hashmap_free_with_destructor(_s, _f) \ + ({ \ + hashmap_clear_with_destructor(_s, _f); \ + hashmap_free(_s); \ + }) +#define ordered_hashmap_clear_with_destructor(_s, _f) \ + ({ \ + void *_item; \ + while ((_item = ordered_hashmap_steal_first(_s))) \ + _f(_item); \ + }) +#define ordered_hashmap_free_with_destructor(_s, _f) \ + ({ \ + ordered_hashmap_clear_with_destructor(_s, _f); \ + ordered_hashmap_free(_s); \ + }) + +/* no hashmap_next */ +void *ordered_hashmap_next(OrderedHashmap *h, const void *key); + +char **internal_hashmap_get_strv(HashmapBase *h); +static inline char **hashmap_get_strv(Hashmap *h) { + return internal_hashmap_get_strv(HASHMAP_BASE(h)); +} +static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { + return internal_hashmap_get_strv(HASHMAP_BASE(h)); +} + +/* + * Hashmaps are iterated in unpredictable order. + * OrderedHashmaps are an exception to this. They are iterated in the order + * the entries were inserted. + * It is safe to remove the current entry. + */ +#define HASHMAP_FOREACH(e, h, i) \ + for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); ) + +#define ORDERED_HASHMAP_FOREACH(e, h, i) \ + for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); ) + +#define HASHMAP_FOREACH_KEY(e, k, h, i) \ + for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) + +#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ + for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); ) + +DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_key); +DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_key); +DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free); + +#define _cleanup_hashmap_free_ _cleanup_(hashmap_freep) +#define _cleanup_hashmap_free_free_ _cleanup_(hashmap_free_freep) +#define _cleanup_hashmap_free_free_free_ _cleanup_(hashmap_free_free_freep) +#define _cleanup_ordered_hashmap_free_ _cleanup_(ordered_hashmap_freep) +#define _cleanup_ordered_hashmap_free_free_ _cleanup_(ordered_hashmap_free_freep) +#define _cleanup_ordered_hashmap_free_free_free_ _cleanup_(ordered_hashmap_free_free_freep) + +DEFINE_TRIVIAL_CLEANUP_FUNC(IteratedCache*, iterated_cache_free); + +#define _cleanup_iterated_cache_free_ _cleanup_(iterated_cache_freep) diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c new file mode 100644 index 00000000..5e425b02 --- /dev/null +++ b/src/basic/hexdecoct.c @@ -0,0 +1,862 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "hexdecoct.h" +#include "macro.h" +#include "memory-util.h" +#include "string-util.h" + +char octchar(int x) { + return '0' + (x & 7); +} + +int unoctchar(char c) { + + if (c >= '0' && c <= '7') + return c - '0'; + + return -EINVAL; +} + +char decchar(int x) { + return '0' + (x % 10); +} + +int undecchar(char c) { + + if (c >= '0' && c <= '9') + return c - '0'; + + return -EINVAL; +} + +char hexchar(int x) { + static const char table[16] = "0123456789abcdef"; + + return table[x & 15]; +} + +int unhexchar(char c) { + + if (c >= '0' && c <= '9') + return c - '0'; + + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + + return -EINVAL; +} + +char *hexmem(const void *p, size_t l) { + const uint8_t *x; + char *r, *z; + + z = r = new(char, l * 2 + 1); + if (!r) + return NULL; + + for (x = p; x < (const uint8_t*) p + l; x++) { + *(z++) = hexchar(*x >> 4); + *(z++) = hexchar(*x & 15); + } + + *z = 0; + return r; +} + +static int unhex_next(const char **p, size_t *l) { + int r; + + assert(p); + assert(l); + + /* Find the next non-whitespace character, and decode it. We + * greedily skip all preceding and all following whitespace. */ + + for (;;) { + if (*l == 0) + return -EPIPE; + + if (!strchr(WHITESPACE, **p)) + break; + + /* Skip leading whitespace */ + (*p)++, (*l)--; + } + + r = unhexchar(**p); + if (r < 0) + return r; + + for (;;) { + (*p)++, (*l)--; + + if (*l == 0 || !strchr(WHITESPACE, **p)) + break; + + /* Skip following whitespace */ + } + + return r; +} + +int unhexmem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_len) { + _cleanup_free_ uint8_t *buf = NULL; + size_t buf_size; + const char *x; + uint8_t *z; + int r; + + assert(ret); + assert(ret_len); + assert(p || l == 0); + + if (l == (size_t) -1) + l = strlen(p); + + /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */ + buf_size = (l + 1) / 2 + 1; + buf = malloc(buf_size); + if (!buf) + return -ENOMEM; + + for (x = p, z = buf;;) { + int a, b; + + a = unhex_next(&x, &l); + if (a == -EPIPE) /* End of string */ + break; + if (a < 0) { + r = a; + goto on_failure; + } + + b = unhex_next(&x, &l); + if (b < 0) { + r = b; + goto on_failure; + } + + *(z++) = (uint8_t) a << 4 | (uint8_t) b; + } + + *z = 0; + + *ret_len = (size_t) (z - buf); + *ret = TAKE_PTR(buf); + + return 0; + +on_failure: + if (secure) + explicit_bzero_safe(buf, buf_size); + + return r; +} + +/* https://tools.ietf.org/html/rfc4648#section-6 + * Notice that base32hex differs from base32 in the alphabet it uses. + * The distinction is that the base32hex representation preserves the + * order of the underlying data when compared as bytestrings, this is + * useful when representing NSEC3 hashes, as one can then verify the + * order of hashes directly from their representation. */ +char base32hexchar(int x) { + static const char table[32] = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUV"; + + return table[x & 31]; +} + +int unbase32hexchar(char c) { + unsigned offset; + + if (c >= '0' && c <= '9') + return c - '0'; + + offset = '9' - '0' + 1; + + if (c >= 'A' && c <= 'V') + return c - 'A' + offset; + + return -EINVAL; +} + +char *base32hexmem(const void *p, size_t l, bool padding) { + char *r, *z; + const uint8_t *x; + size_t len; + + assert(p || l == 0); + + if (padding) + /* five input bytes makes eight output bytes, padding is added so we must round up */ + len = 8 * (l + 4) / 5; + else { + /* same, but round down as there is no padding */ + len = 8 * l / 5; + + switch (l % 5) { + case 4: + len += 7; + break; + case 3: + len += 5; + break; + case 2: + len += 4; + break; + case 1: + len += 2; + break; + } + } + + z = r = malloc(len + 1); + if (!r) + return NULL; + + for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) { + /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ + * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */ + *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ + *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ + *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ + *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ + *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */ + *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */ + *(z++) = base32hexchar((x[3] & 3) << 3 | x[4] >> 5); /* 000QQWWW */ + *(z++) = base32hexchar((x[4] & 31)); /* 000WWWWW */ + } + + switch (l % 5) { + case 4: + *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ + *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ + *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ + *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ + *(z++) = base32hexchar((x[2] & 15) << 1 | x[3] >> 7); /* 000ZZZZQ */ + *(z++) = base32hexchar((x[3] & 127) >> 2); /* 000QQQQQ */ + *(z++) = base32hexchar((x[3] & 3) << 3); /* 000QQ000 */ + if (padding) + *(z++) = '='; + + break; + + case 3: + *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ + *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ + *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ + *(z++) = base32hexchar((x[1] & 1) << 4 | x[2] >> 4); /* 000YZZZZ */ + *(z++) = base32hexchar((x[2] & 15) << 1); /* 000ZZZZ0 */ + if (padding) { + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + } + + break; + + case 2: + *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ + *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ + *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ + *(z++) = base32hexchar((x[1] & 1) << 4); /* 000Y0000 */ + if (padding) { + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + } + + break; + + case 1: + *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ + *(z++) = base32hexchar((x[0] & 7) << 2); /* 000XXX00 */ + if (padding) { + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + *(z++) = '='; + } + + break; + } + + *z = 0; + return r; +} + +int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_len) { + _cleanup_free_ uint8_t *r = NULL; + int a, b, c, d, e, f, g, h; + uint8_t *z; + const char *x; + size_t len; + unsigned pad = 0; + + assert(p || l == 0); + assert(mem); + assert(_len); + + if (l == (size_t) -1) + l = strlen(p); + + /* padding ensures any base32hex input has input divisible by 8 */ + if (padding && l % 8 != 0) + return -EINVAL; + + if (padding) { + /* strip the padding */ + while (l > 0 && p[l - 1] == '=' && pad < 7) { + pad++; + l--; + } + } + + /* a group of eight input bytes needs five output bytes, in case of + * padding we need to add some extra bytes */ + len = (l / 8) * 5; + + switch (l % 8) { + case 7: + len += 4; + break; + case 5: + len += 3; + break; + case 4: + len += 2; + break; + case 2: + len += 1; + break; + case 0: + break; + default: + return -EINVAL; + } + + z = r = malloc(len + 1); + if (!r) + return -ENOMEM; + + for (x = p; x < p + (l / 8) * 8; x += 8) { + /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW + * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */ + a = unbase32hexchar(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase32hexchar(x[1]); + if (b < 0) + return -EINVAL; + + c = unbase32hexchar(x[2]); + if (c < 0) + return -EINVAL; + + d = unbase32hexchar(x[3]); + if (d < 0) + return -EINVAL; + + e = unbase32hexchar(x[4]); + if (e < 0) + return -EINVAL; + + f = unbase32hexchar(x[5]); + if (f < 0) + return -EINVAL; + + g = unbase32hexchar(x[6]); + if (g < 0) + return -EINVAL; + + h = unbase32hexchar(x[7]); + if (h < 0) + return -EINVAL; + + *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ + *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ + *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ + *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */ + *(z++) = (uint8_t) g << 5 | (uint8_t) h; /* VVVRRRRR */ + } + + switch (l % 8) { + case 7: + a = unbase32hexchar(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase32hexchar(x[1]); + if (b < 0) + return -EINVAL; + + c = unbase32hexchar(x[2]); + if (c < 0) + return -EINVAL; + + d = unbase32hexchar(x[3]); + if (d < 0) + return -EINVAL; + + e = unbase32hexchar(x[4]); + if (e < 0) + return -EINVAL; + + f = unbase32hexchar(x[5]); + if (f < 0) + return -EINVAL; + + g = unbase32hexchar(x[6]); + if (g < 0) + return -EINVAL; + + /* g == 000VV000 */ + if (g & 7) + return -EINVAL; + + *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ + *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ + *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ + *(z++) = (uint8_t) e << 7 | (uint8_t) f << 2 | (uint8_t) g >> 3; /* SQQQQQVV */ + + break; + case 5: + a = unbase32hexchar(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase32hexchar(x[1]); + if (b < 0) + return -EINVAL; + + c = unbase32hexchar(x[2]); + if (c < 0) + return -EINVAL; + + d = unbase32hexchar(x[3]); + if (d < 0) + return -EINVAL; + + e = unbase32hexchar(x[4]); + if (e < 0) + return -EINVAL; + + /* e == 000SSSS0 */ + if (e & 1) + return -EINVAL; + + *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ + *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ + *(z++) = (uint8_t) d << 4 | (uint8_t) e >> 1; /* WWWWSSSS */ + + break; + case 4: + a = unbase32hexchar(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase32hexchar(x[1]); + if (b < 0) + return -EINVAL; + + c = unbase32hexchar(x[2]); + if (c < 0) + return -EINVAL; + + d = unbase32hexchar(x[3]); + if (d < 0) + return -EINVAL; + + /* d == 000W0000 */ + if (d & 15) + return -EINVAL; + + *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ + *(z++) = (uint8_t) b << 6 | (uint8_t) c << 1 | (uint8_t) d >> 4; /* YYZZZZZW */ + + break; + case 2: + a = unbase32hexchar(x[0]); + if (a < 0) + return -EINVAL; + + b = unbase32hexchar(x[1]); + if (b < 0) + return -EINVAL; + + /* b == 000YYY00 */ + if (b & 3) + return -EINVAL; + + *(z++) = (uint8_t) a << 3 | (uint8_t) b >> 2; /* XXXXXYYY */ + + break; + case 0: + break; + default: + return -EINVAL; + } + + *z = 0; + + *mem = TAKE_PTR(r); + *_len = len; + + return 0; +} + +/* https://tools.ietf.org/html/rfc4648#section-4 */ +char base64char(int x) { + static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + return table[x & 63]; +} + +int unbase64char(char c) { + unsigned offset; + + if (c >= 'A' && c <= 'Z') + return c - 'A'; + + offset = 'Z' - 'A' + 1; + + if (c >= 'a' && c <= 'z') + return c - 'a' + offset; + + offset += 'z' - 'a' + 1; + + if (c >= '0' && c <= '9') + return c - '0' + offset; + + offset += '9' - '0' + 1; + + if (c == '+') + return offset; + + offset++; + + if (c == '/') + return offset; + + return -EINVAL; +} + +ssize_t base64mem(const void *p, size_t l, char **out) { + char *r, *z; + const uint8_t *x; + + assert(p || l == 0); + assert(out); + + /* three input bytes makes four output bytes, padding is added so we must round up */ + z = r = malloc(4 * (l + 2) / 3 + 1); + if (!r) + return -ENOMEM; + + for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) { + /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */ + *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ + *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */ + *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */ + *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */ + } + + switch (l % 3) { + case 2: + *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ + *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */ + *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */ + *(z++) = '='; + + break; + case 1: + *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */ + *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */ + *(z++) = '='; + *(z++) = '='; + + break; + } + + *z = 0; + *out = r; + return z - r; +} + +static int base64_append_width( + char **prefix, int plen, + const char *sep, int indent, + const void *p, size_t l, + int width) { + + _cleanup_free_ char *x = NULL; + char *t, *s; + ssize_t len, slen, avail, line, lines; + + len = base64mem(p, l, &x); + if (len <= 0) + return len; + + lines = DIV_ROUND_UP(len, width); + + slen = strlen_ptr(sep); + if (plen >= SSIZE_MAX - 1 - slen || + lines > (SSIZE_MAX - plen - 1 - slen) / (indent + width + 1)) + return -ENOMEM; + + t = realloc(*prefix, (ssize_t) plen + 1 + slen + (indent + width + 1) * lines); + if (!t) + return -ENOMEM; + + memcpy_safe(t + plen, sep, slen); + + for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) { + int act = MIN(width, avail); + + if (line > 0 || sep) { + memset(s, ' ', indent); + s += indent; + } + + memcpy(s, x + width * line, act); + s += act; + *(s++) = line < lines - 1 ? '\n' : '\0'; + avail -= act; + } + assert(avail == 0); + + *prefix = t; + return 0; +} + +int base64_append( + char **prefix, int plen, + const void *p, size_t l, + int indent, int width) { + + if (plen > width / 2 || plen + indent > width) + /* leave indent on the left, keep last column free */ + return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1); + else + /* leave plen on the left, keep last column free */ + return base64_append_width(prefix, plen, " ", plen, p, l, width - plen - 1); +} + +static int unbase64_next(const char **p, size_t *l) { + int ret; + + assert(p); + assert(l); + + /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We + * greedily skip all preceding and all following whitespace. */ + + for (;;) { + if (*l == 0) + return -EPIPE; + + if (!strchr(WHITESPACE, **p)) + break; + + /* Skip leading whitespace */ + (*p)++, (*l)--; + } + + if (**p == '=') + ret = INT_MAX; /* return padding as INT_MAX */ + else { + ret = unbase64char(**p); + if (ret < 0) + return ret; + } + + for (;;) { + (*p)++, (*l)--; + + if (*l == 0) + break; + if (!strchr(WHITESPACE, **p)) + break; + + /* Skip following whitespace */ + } + + return ret; +} + +int unbase64mem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_size) { + _cleanup_free_ uint8_t *buf = NULL; + const char *x; + uint8_t *z; + size_t len; + int r; + + assert(p || l == 0); + assert(ret); + assert(ret_size); + + if (l == (size_t) -1) + l = strlen(p); + + /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra + * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */ + len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0); + + buf = malloc(len + 1); + if (!buf) + return -ENOMEM; + + for (x = p, z = buf;;) { + int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */ + + a = unbase64_next(&x, &l); + if (a == -EPIPE) /* End of string */ + break; + if (a < 0) { + r = a; + goto on_failure; + } + if (a == INT_MAX) { /* Padding is not allowed at the beginning of a 4ch block */ + r = -EINVAL; + goto on_failure; + } + + b = unbase64_next(&x, &l); + if (b < 0) { + r = b; + goto on_failure; + } + if (b == INT_MAX) { /* Padding is not allowed at the second character of a 4ch block either */ + r = -EINVAL; + goto on_failure; + } + + c = unbase64_next(&x, &l); + if (c < 0) { + r = c; + goto on_failure; + } + + d = unbase64_next(&x, &l); + if (d < 0) { + r = d; + goto on_failure; + } + + if (c == INT_MAX) { /* Padding at the third character */ + + if (d != INT_MAX) { /* If the third character is padding, the fourth must be too */ + r = -EINVAL; + goto on_failure; + } + + /* b == 00YY0000 */ + if (b & 15) { + r = -EINVAL; + goto on_failure; + } + + if (l > 0) { /* Trailing rubbish? */ + r = -ENAMETOOLONG; + goto on_failure; + } + + *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */ + break; + } + + if (d == INT_MAX) { + /* c == 00ZZZZ00 */ + if (c & 3) { + r = -EINVAL; + goto on_failure; + } + + if (l > 0) { /* Trailing rubbish? */ + r = -ENAMETOOLONG; + goto on_failure; + } + + *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ + *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ + break; + } + + *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ + *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ + *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */ + } + + *z = 0; + + *ret_size = (size_t) (z - buf); + *ret = TAKE_PTR(buf); + + return 0; + +on_failure: + if (secure) + explicit_bzero_safe(buf, len); + + return r; +} + +void hexdump(FILE *f, const void *p, size_t s) { + const uint8_t *b = p; + unsigned n = 0; + + assert(b || s == 0); + + if (!f) + f = stdout; + + while (s > 0) { + size_t i; + + fprintf(f, "%04x ", n); + + for (i = 0; i < 16; i++) { + + if (i >= s) + fputs(" ", f); + else + fprintf(f, "%02x ", b[i]); + + if (i == 7) + fputc(' ', f); + } + + fputc(' ', f); + + for (i = 0; i < 16; i++) { + + if (i >= s) + fputc(' ', f); + else + fputc(isprint(b[i]) ? (char) b[i] : '.', f); + } + + fputc('\n', f); + + if (s < 16) + break; + + n += 16; + b += 16; + s -= 16; + } +} diff --git a/src/basic/hexdecoct.h b/src/basic/hexdecoct.h new file mode 100644 index 00000000..dfdff1e9 --- /dev/null +++ b/src/basic/hexdecoct.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "macro.h" + +char octchar(int x) _const_; +int unoctchar(char c) _const_; + +char decchar(int x) _const_; +int undecchar(char c) _const_; + +char hexchar(int x) _const_; +int unhexchar(char c) _const_; + +char *hexmem(const void *p, size_t l); +int unhexmem_full(const char *p, size_t l, bool secure, void **mem, size_t *len); +static inline int unhexmem(const char *p, size_t l, void **mem, size_t *len) { + return unhexmem_full(p, l, false, mem, len); +} + +char base32hexchar(int x) _const_; +int unbase32hexchar(char c) _const_; + +char base64char(int x) _const_; +int unbase64char(char c) _const_; + +char *base32hexmem(const void *p, size_t l, bool padding); +int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len); + +ssize_t base64mem(const void *p, size_t l, char **out); +int base64_append(char **prefix, int plen, + const void *p, size_t l, + int margin, int width); +int unbase64mem_full(const char *p, size_t l, bool secure, void **mem, size_t *len); +static inline int unbase64mem(const char *p, size_t l, void **mem, size_t *len) { + return unbase64mem_full(p, l, false, mem, len); +} + +void hexdump(FILE *f, const void *p, size_t s); diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c new file mode 100644 index 00000000..7bc2e3f3 --- /dev/null +++ b/src/basic/hostname-util.c @@ -0,0 +1,307 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "hostname-util.h" +#include "macro.h" +#include "string-util.h" + +bool hostname_is_set(void) { + struct utsname u; + + assert_se(uname(&u) >= 0); + + if (isempty(u.nodename)) + return false; + + /* This is the built-in kernel default host name */ + if (streq(u.nodename, "(none)")) + return false; + + return true; +} + +char* gethostname_malloc(void) { + struct utsname u; + + /* This call tries to return something useful, either the actual hostname + * or it makes something up. The only reason it might fail is OOM. + * It might even return "localhost" if that's set. */ + + assert_se(uname(&u) >= 0); + + if (isempty(u.nodename) || streq(u.nodename, "(none)")) + return strdup(FALLBACK_HOSTNAME); + + return strdup(u.nodename); +} + +int gethostname_strict(char **ret) { + struct utsname u; + char *k; + + /* This call will rather fail than make up a name. It will not return "localhost" either. */ + + assert_se(uname(&u) >= 0); + + if (isempty(u.nodename)) + return -ENXIO; + + if (streq(u.nodename, "(none)")) + return -ENXIO; + + if (is_localhost(u.nodename)) + return -ENXIO; + + k = strdup(u.nodename); + if (!k) + return -ENOMEM; + + *ret = k; + return 0; +} + +bool valid_ldh_char(char c) { + return + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '-'; +} + +/** + * Check if s looks like a valid host name or FQDN. This does not do + * full DNS validation, but only checks if the name is composed of + * allowed characters and the length is not above the maximum allowed + * by Linux (c.f. dns_name_is_valid()). Trailing dot is allowed if + * allow_trailing_dot is true and at least two components are present + * in the name. Note that due to the restricted charset and length + * this call is substantially more conservative than + * dns_name_is_valid(). + */ +bool hostname_is_valid(const char *s, bool allow_trailing_dot) { + unsigned n_dots = 0; + const char *p; + bool dot, hyphen; + + if (isempty(s)) + return false; + + /* Doesn't accept empty hostnames, hostnames with + * leading dots, and hostnames with multiple dots in a + * sequence. Also ensures that the length stays below + * HOST_NAME_MAX. */ + + for (p = s, dot = hyphen = true; *p; p++) + if (*p == '.') { + if (dot || hyphen) + return false; + + dot = true; + hyphen = false; + n_dots++; + + } else if (*p == '-') { + if (dot) + return false; + + dot = false; + hyphen = true; + + } else { + if (!valid_ldh_char(*p)) + return false; + + dot = false; + hyphen = false; + } + + if (dot && (n_dots < 2 || !allow_trailing_dot)) + return false; + if (hyphen) + return false; + + if (p-s > HOST_NAME_MAX) /* Note that HOST_NAME_MAX is 64 on + * Linux, but DNS allows domain names + * up to 255 characters */ + return false; + + return true; +} + +char* hostname_cleanup(char *s) { + char *p, *d; + bool dot, hyphen; + + assert(s); + + for (p = s, d = s, dot = hyphen = true; *p && d - s < HOST_NAME_MAX; p++) + if (*p == '.') { + if (dot || hyphen) + continue; + + *(d++) = '.'; + dot = true; + hyphen = false; + + } else if (*p == '-') { + if (dot) + continue; + + *(d++) = '-'; + dot = false; + hyphen = true; + + } else if (valid_ldh_char(*p)) { + *(d++) = *p; + dot = false; + hyphen = false; + } + + if (d > s && IN_SET(d[-1], '-', '.')) + /* The dot can occur at most once, but we might have multiple + * hyphens, hence the loop */ + d--; + *d = 0; + + return s; +} + +bool is_localhost(const char *hostname) { + assert(hostname); + + /* This tries to identify local host and domain names + * described in RFC6761 plus the redhatism of localdomain */ + + return strcaseeq(hostname, "localhost") || + strcaseeq(hostname, "localhost.") || + strcaseeq(hostname, "localhost.localdomain") || + strcaseeq(hostname, "localhost.localdomain.") || + endswith_no_case(hostname, ".localhost") || + endswith_no_case(hostname, ".localhost.") || + endswith_no_case(hostname, ".localhost.localdomain") || + endswith_no_case(hostname, ".localhost.localdomain."); +} + +bool is_gateway_hostname(const char *hostname) { + assert(hostname); + + /* This tries to identify the valid syntaxes for the our + * synthetic "gateway" host. */ + + return + strcaseeq(hostname, "_gateway") || strcaseeq(hostname, "_gateway.") +#if ENABLE_COMPAT_GATEWAY_HOSTNAME + || strcaseeq(hostname, "gateway") || strcaseeq(hostname, "gateway.") +#endif + ; +} + +int sethostname_idempotent(const char *s) { + char buf[HOST_NAME_MAX + 1] = {}; + + assert(s); + + if (gethostname(buf, sizeof(buf)) < 0) + return -errno; + + if (streq(buf, s)) + return 0; + + if (sethostname(s, strlen(s)) < 0) + return -errno; + + return 1; +} + +int shorten_overlong(const char *s, char **ret) { + char *h, *p; + + /* Shorten an overlong name to HOST_NAME_MAX or to the first dot, + * whatever comes earlier. */ + + assert(s); + + h = strdup(s); + if (!h) + return -ENOMEM; + + if (hostname_is_valid(h, false)) { + *ret = h; + return 0; + } + + p = strchr(h, '.'); + if (p) + *p = 0; + + strshorten(h, HOST_NAME_MAX); + + if (!hostname_is_valid(h, false)) { + free(h); + return -EDOM; + } + + *ret = h; + return 1; +} + +int read_etc_hostname_stream(FILE *f, char **ret) { + int r; + + assert(f); + assert(ret); + + for (;;) { + _cleanup_free_ char *line = NULL; + char *p; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) /* EOF without any hostname? the file is empty, let's treat that exactly like no file at all: ENOENT */ + return -ENOENT; + + p = strstrip(line); + + /* File may have empty lines or comments, ignore them */ + if (!IN_SET(*p, '\0', '#')) { + char *copy; + + hostname_cleanup(p); /* normalize the hostname */ + + if (!hostname_is_valid(p, true)) /* check that the hostname we return is valid */ + return -EBADMSG; + + copy = strdup(p); + if (!copy) + return -ENOMEM; + + *ret = copy; + return 0; + } + } +} + +int read_etc_hostname(const char *path, char **ret) { + _cleanup_fclose_ FILE *f = NULL; + + assert(ret); + + if (!path) + path = "/etc/hostname"; + + f = fopen(path, "re"); + if (!f) + return -errno; + + return read_etc_hostname_stream(f, ret); + +} diff --git a/src/basic/hostname-util.h b/src/basic/hostname-util.h new file mode 100644 index 00000000..7ba386a0 --- /dev/null +++ b/src/basic/hostname-util.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "macro.h" + +bool hostname_is_set(void); + +char* gethostname_malloc(void); +int gethostname_strict(char **ret); + +bool valid_ldh_char(char c) _const_; +bool hostname_is_valid(const char *s, bool allow_trailing_dot) _pure_; +char* hostname_cleanup(char *s); + +#define machine_name_is_valid(s) hostname_is_valid(s, false) + +bool is_localhost(const char *hostname); +bool is_gateway_hostname(const char *hostname); + +int sethostname_idempotent(const char *s); + +int shorten_overlong(const char *s, char **ret); + +int read_etc_hostname_stream(FILE *f, char **ret); +int read_etc_hostname(const char *path, char **ret); diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c new file mode 100644 index 00000000..06b92db5 --- /dev/null +++ b/src/basic/in-addr-util.c @@ -0,0 +1,760 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "errno-util.h" +#include "in-addr-util.h" +#include "macro.h" +#include "parse-util.h" +#include "random-util.h" +#include "strxcpyx.h" +#include "util.h" + +bool in4_addr_is_null(const struct in_addr *a) { + assert(a); + + return a->s_addr == 0; +} + +int in_addr_is_null(int family, const union in_addr_union *u) { + assert(u); + + if (family == AF_INET) + return in4_addr_is_null(&u->in); + + if (family == AF_INET6) + return IN6_IS_ADDR_UNSPECIFIED(&u->in6); + + return -EAFNOSUPPORT; +} + +bool in4_addr_is_link_local(const struct in_addr *a) { + assert(a); + + return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16); +} + +int in_addr_is_link_local(int family, const union in_addr_union *u) { + assert(u); + + if (family == AF_INET) + return in4_addr_is_link_local(&u->in); + + if (family == AF_INET6) + return IN6_IS_ADDR_LINKLOCAL(&u->in6); + + return -EAFNOSUPPORT; +} + +int in_addr_is_multicast(int family, const union in_addr_union *u) { + assert(u); + + if (family == AF_INET) + return IN_MULTICAST(be32toh(u->in.s_addr)); + + if (family == AF_INET6) + return IN6_IS_ADDR_MULTICAST(&u->in6); + + return -EAFNOSUPPORT; +} + +bool in4_addr_is_localhost(const struct in_addr *a) { + assert(a); + + /* All of 127.x.x.x is localhost. */ + return (be32toh(a->s_addr) & UINT32_C(0xFF000000)) == UINT32_C(127) << 24; +} + +bool in4_addr_is_non_local(const struct in_addr *a) { + /* Whether the address is not null and not localhost. + * + * As such, it is suitable to configure as DNS/NTP server from DHCP. */ + return !in4_addr_is_null(a) && + !in4_addr_is_localhost(a); +} + +int in_addr_is_localhost(int family, const union in_addr_union *u) { + assert(u); + + if (family == AF_INET) + return in4_addr_is_localhost(&u->in); + + if (family == AF_INET6) + return IN6_IS_ADDR_LOOPBACK(&u->in6); + + return -EAFNOSUPPORT; +} + +bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b) { + assert(a); + assert(b); + + return a->s_addr == b->s_addr; +} + +int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b) { + assert(a); + assert(b); + + if (family == AF_INET) + return in4_addr_equal(&a->in, &b->in); + + if (family == AF_INET6) + return + a->in6.s6_addr32[0] == b->in6.s6_addr32[0] && + a->in6.s6_addr32[1] == b->in6.s6_addr32[1] && + a->in6.s6_addr32[2] == b->in6.s6_addr32[2] && + a->in6.s6_addr32[3] == b->in6.s6_addr32[3]; + + return -EAFNOSUPPORT; +} + +int in_addr_prefix_intersect( + int family, + const union in_addr_union *a, + unsigned aprefixlen, + const union in_addr_union *b, + unsigned bprefixlen) { + + unsigned m; + + assert(a); + assert(b); + + /* Checks whether there are any addresses that are in both + * networks */ + + m = MIN(aprefixlen, bprefixlen); + + if (family == AF_INET) { + uint32_t x, nm; + + x = be32toh(a->in.s_addr ^ b->in.s_addr); + nm = (m == 0) ? 0 : 0xFFFFFFFFUL << (32 - m); + + return (x & nm) == 0; + } + + if (family == AF_INET6) { + unsigned i; + + if (m > 128) + m = 128; + + for (i = 0; i < 16; i++) { + uint8_t x, nm; + + x = a->in6.s6_addr[i] ^ b->in6.s6_addr[i]; + + if (m < 8) + nm = 0xFF << (8 - m); + else + nm = 0xFF; + + if ((x & nm) != 0) + return 0; + + if (m > 8) + m -= 8; + else + m = 0; + } + + return 1; + } + + return -EAFNOSUPPORT; +} + +int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen) { + assert(u); + + /* Increases the network part of an address by one. Returns + * positive it that succeeds, or 0 if this overflows. */ + + if (prefixlen <= 0) + return 0; + + if (family == AF_INET) { + uint32_t c, n; + + if (prefixlen > 32) + prefixlen = 32; + + c = be32toh(u->in.s_addr); + n = c + (1UL << (32 - prefixlen)); + if (n < c) + return 0; + n &= 0xFFFFFFFFUL << (32 - prefixlen); + + u->in.s_addr = htobe32(n); + return 1; + } + + if (family == AF_INET6) { + struct in6_addr add = {}, result; + uint8_t overflow = 0; + unsigned i; + + if (prefixlen > 128) + prefixlen = 128; + + /* First calculate what we have to add */ + add.s6_addr[(prefixlen-1) / 8] = 1 << (7 - (prefixlen-1) % 8); + + for (i = 16; i > 0; i--) { + unsigned j = i - 1; + + result.s6_addr[j] = u->in6.s6_addr[j] + add.s6_addr[j] + overflow; + overflow = (result.s6_addr[j] < u->in6.s6_addr[j]); + } + + if (overflow) + return 0; + + u->in6 = result; + return 1; + } + + return -EAFNOSUPPORT; +} + +int in_addr_random_prefix( + int family, + union in_addr_union *u, + unsigned prefixlen_fixed_part, + unsigned prefixlen) { + + assert(u); + + /* Random network part of an address by one. */ + + if (prefixlen <= 0) + return 0; + + if (family == AF_INET) { + uint32_t c, n; + + if (prefixlen_fixed_part > 32) + prefixlen_fixed_part = 32; + if (prefixlen > 32) + prefixlen = 32; + if (prefixlen_fixed_part >= prefixlen) + return -EINVAL; + + c = be32toh(u->in.s_addr); + c &= ((UINT32_C(1) << prefixlen_fixed_part) - 1) << (32 - prefixlen_fixed_part); + + random_bytes(&n, sizeof(n)); + n &= ((UINT32_C(1) << (prefixlen - prefixlen_fixed_part)) - 1) << (32 - prefixlen); + + u->in.s_addr = htobe32(n | c); + return 1; + } + + if (family == AF_INET6) { + struct in6_addr n; + unsigned i, j; + + if (prefixlen_fixed_part > 128) + prefixlen_fixed_part = 128; + if (prefixlen > 128) + prefixlen = 128; + if (prefixlen_fixed_part >= prefixlen) + return -EINVAL; + + random_bytes(&n, sizeof(n)); + + for (i = 0; i < 16; i++) { + uint8_t mask_fixed_part = 0, mask = 0; + + if (i < (prefixlen_fixed_part + 7) / 8) { + if (i < prefixlen_fixed_part / 8) + mask_fixed_part = 0xffu; + else { + j = prefixlen_fixed_part % 8; + mask_fixed_part = ((UINT8_C(1) << (j + 1)) - 1) << (8 - j); + } + } + + if (i < (prefixlen + 7) / 8) { + if (i < prefixlen / 8) + mask = 0xffu ^ mask_fixed_part; + else { + j = prefixlen % 8; + mask = (((UINT8_C(1) << (j + 1)) - 1) << (8 - j)) ^ mask_fixed_part; + } + } + + u->in6.s6_addr[i] &= mask_fixed_part; + u->in6.s6_addr[i] |= n.s6_addr[i] & mask; + } + + return 1; + } + + return -EAFNOSUPPORT; +} + +int in_addr_to_string(int family, const union in_addr_union *u, char **ret) { + _cleanup_free_ char *x = NULL; + size_t l; + + assert(u); + assert(ret); + + if (family == AF_INET) + l = INET_ADDRSTRLEN; + else if (family == AF_INET6) + l = INET6_ADDRSTRLEN; + else + return -EAFNOSUPPORT; + + x = new(char, l); + if (!x) + return -ENOMEM; + + errno = 0; + if (!inet_ntop(family, u, x, l)) + return errno_or_else(EINVAL); + + *ret = TAKE_PTR(x); + return 0; +} + +int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret) { + _cleanup_free_ char *x = NULL; + char *p; + size_t l; + + assert(u); + assert(ret); + + if (family == AF_INET) + l = INET_ADDRSTRLEN + 3; + else if (family == AF_INET6) + l = INET6_ADDRSTRLEN + 4; + else + return -EAFNOSUPPORT; + + if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8) + return -EINVAL; + + x = new(char, l); + if (!x) + return -ENOMEM; + + errno = 0; + if (!inet_ntop(family, u, x, l)) + return errno_or_else(EINVAL); + + p = x + strlen(x); + l -= strlen(x); + (void) strpcpyf(&p, l, "/%u", prefixlen); + + *ret = TAKE_PTR(x); + return 0; +} + +int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) { + _cleanup_free_ char *x = NULL; + size_t l; + int r; + + assert(u); + assert(ret); + + /* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly + * handle IPv6 link-local addresses. */ + + if (family != AF_INET6) + goto fallback; + if (ifindex <= 0) + goto fallback; + + r = in_addr_is_link_local(family, u); + if (r < 0) + return r; + if (r == 0) + goto fallback; + + l = INET6_ADDRSTRLEN + 1 + DECIMAL_STR_MAX(ifindex) + 1; + x = new(char, l); + if (!x) + return -ENOMEM; + + errno = 0; + if (!inet_ntop(family, u, x, l)) + return errno_or_else(EINVAL); + + sprintf(strchr(x, 0), "%%%i", ifindex); + + *ret = TAKE_PTR(x); + return 0; + +fallback: + return in_addr_to_string(family, u, ret); +} + +int in_addr_from_string(int family, const char *s, union in_addr_union *ret) { + union in_addr_union buffer; + assert(s); + + if (!IN_SET(family, AF_INET, AF_INET6)) + return -EAFNOSUPPORT; + + errno = 0; + if (inet_pton(family, s, ret ?: &buffer) <= 0) + return errno_or_else(EINVAL); + + return 0; +} + +int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret) { + int r; + + assert(s); + + r = in_addr_from_string(AF_INET, s, ret); + if (r >= 0) { + if (ret_family) + *ret_family = AF_INET; + return 0; + } + + r = in_addr_from_string(AF_INET6, s, ret); + if (r >= 0) { + if (ret_family) + *ret_family = AF_INET6; + return 0; + } + + return -EINVAL; +} + +int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) { + _cleanup_free_ char *buf = NULL; + const char *suffix; + int r, ifi = 0; + + assert(s); + assert(family); + assert(ret); + + /* Similar to in_addr_from_string_auto() but also parses an optionally appended IPv6 zone suffix ("scope id") + * if one is found. */ + + suffix = strchr(s, '%'); + if (suffix) { + + if (ifindex) { + /* If we shall return the interface index, try to parse it */ + r = parse_ifindex(suffix + 1, &ifi); + if (r < 0) { + unsigned u; + + u = if_nametoindex(suffix + 1); + if (u <= 0) + return -errno; + + ifi = (int) u; + } + } + + buf = strndup(s, suffix - s); + if (!buf) + return -ENOMEM; + + s = buf; + } + + r = in_addr_from_string_auto(s, family, ret); + if (r < 0) + return r; + + if (ifindex) + *ifindex = ifi; + + return r; +} + +unsigned char in4_addr_netmask_to_prefixlen(const struct in_addr *addr) { + assert(addr); + + return 32U - u32ctz(be32toh(addr->s_addr)); +} + +struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) { + assert(addr); + assert(prefixlen <= 32); + + /* Shifting beyond 32 is not defined, handle this specially. */ + if (prefixlen == 0) + addr->s_addr = 0; + else + addr->s_addr = htobe32((0xffffffff << (32 - prefixlen)) & 0xffffffff); + + return addr; +} + +int in4_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) { + uint8_t msb_octet = *(uint8_t*) addr; + + /* addr may not be aligned, so make sure we only access it byte-wise */ + + assert(addr); + assert(prefixlen); + + if (msb_octet < 128) + /* class A, leading bits: 0 */ + *prefixlen = 8; + else if (msb_octet < 192) + /* class B, leading bits 10 */ + *prefixlen = 16; + else if (msb_octet < 224) + /* class C, leading bits 110 */ + *prefixlen = 24; + else + /* class D or E, no default prefixlen */ + return -ERANGE; + + return 0; +} + +int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask) { + unsigned char prefixlen; + int r; + + assert(addr); + assert(mask); + + r = in4_addr_default_prefixlen(addr, &prefixlen); + if (r < 0) + return r; + + in4_addr_prefixlen_to_netmask(mask, prefixlen); + return 0; +} + +int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen) { + assert(addr); + + if (family == AF_INET) { + struct in_addr mask; + + if (!in4_addr_prefixlen_to_netmask(&mask, prefixlen)) + return -EINVAL; + + addr->in.s_addr &= mask.s_addr; + return 0; + } + + if (family == AF_INET6) { + unsigned i; + + for (i = 0; i < 16; i++) { + uint8_t mask; + + if (prefixlen >= 8) { + mask = 0xFF; + prefixlen -= 8; + } else { + mask = 0xFF << (8 - prefixlen); + prefixlen = 0; + } + + addr->in6.s6_addr[i] &= mask; + } + + return 0; + } + + return -EAFNOSUPPORT; +} + +int in_addr_prefix_covers(int family, + const union in_addr_union *prefix, + unsigned char prefixlen, + const union in_addr_union *address) { + + union in_addr_union masked_prefix, masked_address; + int r; + + assert(prefix); + assert(address); + + masked_prefix = *prefix; + r = in_addr_mask(family, &masked_prefix, prefixlen); + if (r < 0) + return r; + + masked_address = *address; + r = in_addr_mask(family, &masked_address, prefixlen); + if (r < 0) + return r; + + return in_addr_equal(family, &masked_prefix, &masked_address); +} + +int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) { + uint8_t u; + int r; + + if (!IN_SET(family, AF_INET, AF_INET6)) + return -EAFNOSUPPORT; + + r = safe_atou8(p, &u); + if (r < 0) + return r; + + if (u > FAMILY_ADDRESS_SIZE(family) * 8) + return -ERANGE; + + *ret = u; + return 0; +} + +int in_addr_prefix_from_string( + const char *p, + int family, + union in_addr_union *ret_prefix, + unsigned char *ret_prefixlen) { + + _cleanup_free_ char *str = NULL; + union in_addr_union buffer; + const char *e, *l; + unsigned char k; + int r; + + assert(p); + + if (!IN_SET(family, AF_INET, AF_INET6)) + return -EAFNOSUPPORT; + + e = strchr(p, '/'); + if (e) { + str = strndup(p, e - p); + if (!str) + return -ENOMEM; + + l = str; + } else + l = p; + + r = in_addr_from_string(family, l, &buffer); + if (r < 0) + return r; + + if (e) { + r = in_addr_parse_prefixlen(family, e+1, &k); + if (r < 0) + return r; + } else + k = FAMILY_ADDRESS_SIZE(family) * 8; + + if (ret_prefix) + *ret_prefix = buffer; + if (ret_prefixlen) + *ret_prefixlen = k; + + return 0; +} + +int in_addr_prefix_from_string_auto_internal( + const char *p, + InAddrPrefixLenMode mode, + int *ret_family, + union in_addr_union *ret_prefix, + unsigned char *ret_prefixlen) { + + _cleanup_free_ char *str = NULL; + union in_addr_union buffer; + const char *e, *l; + unsigned char k; + int family, r; + + assert(p); + + e = strchr(p, '/'); + if (e) { + str = strndup(p, e - p); + if (!str) + return -ENOMEM; + + l = str; + } else + l = p; + + r = in_addr_from_string_auto(l, &family, &buffer); + if (r < 0) + return r; + + if (e) { + r = in_addr_parse_prefixlen(family, e+1, &k); + if (r < 0) + return r; + } else + switch (mode) { + case PREFIXLEN_FULL: + k = FAMILY_ADDRESS_SIZE(family) * 8; + break; + case PREFIXLEN_REFUSE: + return -ENOANO; /* To distinguish this error from others. */ + case PREFIXLEN_LEGACY: + if (family == AF_INET) { + r = in4_addr_default_prefixlen(&buffer.in, &k); + if (r < 0) + return r; + } else + k = 0; + break; + default: + assert_not_reached("Invalid prefixlen mode"); + } + + if (ret_family) + *ret_family = family; + if (ret_prefix) + *ret_prefix = buffer; + if (ret_prefixlen) + *ret_prefixlen = k; + + return 0; + +} + +static void in_addr_data_hash_func(const struct in_addr_data *a, struct siphash *state) { + siphash24_compress(&a->family, sizeof(a->family), state); + siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state); +} + +static int in_addr_data_compare_func(const struct in_addr_data *x, const struct in_addr_data *y) { + int r; + + r = CMP(x->family, y->family); + if (r != 0) + return r; + + return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family)); +} + +DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func); + +static void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) { + assert(addr); + + siphash24_compress(addr, sizeof(*addr), state); +} + +static int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) { + return memcmp(a, b, sizeof(*a)); +} + +DEFINE_HASH_OPS(in6_addr_hash_ops, struct in6_addr, in6_addr_hash_func, in6_addr_compare_func); diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h new file mode 100644 index 00000000..28afc7d8 --- /dev/null +++ b/src/basic/in-addr-util.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "hash-funcs.h" +#include "macro.h" +#include "util.h" + +union in_addr_union { + struct in_addr in; + struct in6_addr in6; +}; + +struct in_addr_data { + int family; + union in_addr_union address; +}; + +bool in4_addr_is_null(const struct in_addr *a); +int in_addr_is_null(int family, const union in_addr_union *u); + +int in_addr_is_multicast(int family, const union in_addr_union *u); + +bool in4_addr_is_link_local(const struct in_addr *a); +int in_addr_is_link_local(int family, const union in_addr_union *u); + +bool in4_addr_is_localhost(const struct in_addr *a); +int in_addr_is_localhost(int family, const union in_addr_union *u); + +bool in4_addr_is_non_local(const struct in_addr *a); + +bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b); +int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b); +int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen); +int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen); +int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen); +int in_addr_to_string(int family, const union in_addr_union *u, char **ret); +int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret); +int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret); +int in_addr_from_string(int family, const char *s, union in_addr_union *ret); +int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret); +int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex); +unsigned char in4_addr_netmask_to_prefixlen(const struct in_addr *addr); +struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen); +int in4_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen); +int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask); +int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen); +int in_addr_prefix_covers(int family, const union in_addr_union *prefix, unsigned char prefixlen, const union in_addr_union *address); +int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret); +int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); + +typedef enum InAddrPrefixLenMode { + PREFIXLEN_FULL, /* Default to prefixlen of address size, 32 for IPv4 or 128 for IPv6, if not specified. */ + PREFIXLEN_REFUSE, /* Fail with -ENOANO if prefixlen is not specified. */ + PREFIXLEN_LEGACY, /* Default to legacy default prefixlen calculation from address if not specified. */ +} InAddrPrefixLenMode; + +int in_addr_prefix_from_string_auto_internal(const char *p, InAddrPrefixLenMode mode, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen); +static inline int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen) { + return in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_FULL, ret_family, ret_prefix, ret_prefixlen); +} + +static inline size_t FAMILY_ADDRESS_SIZE(int family) { + assert(IN_SET(family, AF_INET, AF_INET6)); + return family == AF_INET6 ? 16 : 4; +} + +/* Workaround for clang, explicitly specify the maximum-size element here. + * See also oss-fuzz#11344. */ +#define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} }) + +extern const struct hash_ops in_addr_data_hash_ops; +extern const struct hash_ops in6_addr_hash_ops; diff --git a/src/basic/io-util.c b/src/basic/io-util.c new file mode 100644 index 00000000..c906fc07 --- /dev/null +++ b/src/basic/io-util.c @@ -0,0 +1,345 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "io-util.h" +#include "string-util.h" +#include "time-util.h" + +int flush_fd(int fd) { + struct pollfd pollfd = { + .fd = fd, + .events = POLLIN, + }; + int count = 0; + + /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything + * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read + * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used + * was set to non-blocking too. */ + + for (;;) { + char buf[LINE_MAX]; + ssize_t l; + int r; + + r = poll(&pollfd, 1, 0); + if (r < 0) { + if (errno == EINTR) + continue; + + return -errno; + + } else if (r == 0) + return count; + + l = read(fd, buf, sizeof(buf)); + if (l < 0) { + + if (errno == EINTR) + continue; + + if (errno == EAGAIN) + return count; + + return -errno; + } else if (l == 0) + return count; + + count += (int) l; + } +} + +ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) { + uint8_t *p = buf; + ssize_t n = 0; + + assert(fd >= 0); + assert(buf); + + /* If called with nbytes == 0, let's call read() at least + * once, to validate the operation */ + + if (nbytes > (size_t) SSIZE_MAX) + return -EINVAL; + + do { + ssize_t k; + + k = read(fd, p, nbytes); + if (k < 0) { + if (errno == EINTR) + continue; + + if (errno == EAGAIN && do_poll) { + + /* We knowingly ignore any return value here, + * and expect that any error/EOF is reported + * via read() */ + + (void) fd_wait_for_event(fd, POLLIN, USEC_INFINITY); + continue; + } + + return n > 0 ? n : -errno; + } + + if (k == 0) + return n; + + assert((size_t) k <= nbytes); + + p += k; + nbytes -= k; + n += k; + } while (nbytes > 0); + + return n; +} + +int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) { + ssize_t n; + + n = loop_read(fd, buf, nbytes, do_poll); + if (n < 0) + return (int) n; + if ((size_t) n != nbytes) + return -EIO; + + return 0; +} + +int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { + const uint8_t *p = buf; + + assert(fd >= 0); + assert(buf); + + if (_unlikely_(nbytes > (size_t) SSIZE_MAX)) + return -EINVAL; + + do { + ssize_t k; + + k = write(fd, p, nbytes); + if (k < 0) { + if (errno == EINTR) + continue; + + if (errno == EAGAIN && do_poll) { + /* We knowingly ignore any return value here, + * and expect that any error/EOF is reported + * via write() */ + + (void) fd_wait_for_event(fd, POLLOUT, USEC_INFINITY); + continue; + } + + return -errno; + } + + if (_unlikely_(nbytes > 0 && k == 0)) /* Can't really happen */ + return -EIO; + + assert((size_t) k <= nbytes); + + p += k; + nbytes -= k; + } while (nbytes > 0); + + return 0; +} + +int pipe_eof(int fd) { + struct pollfd pollfd = { + .fd = fd, + .events = POLLIN|POLLHUP, + }; + + int r; + + r = poll(&pollfd, 1, 0); + if (r < 0) + return -errno; + + if (r == 0) + return 0; + + return pollfd.revents & POLLHUP; +} + +int fd_wait_for_event(int fd, int event, usec_t t) { + + struct pollfd pollfd = { + .fd = fd, + .events = event, + }; + + struct timespec ts; + int r; + + r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL); + if (r < 0) + return -errno; + if (r == 0) + return 0; + + return pollfd.revents; +} + +static size_t nul_length(const uint8_t *p, size_t sz) { + size_t n = 0; + + while (sz > 0) { + if (*p != 0) + break; + + n++; + p++; + sz--; + } + + return n; +} + +ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) { + const uint8_t *q, *w, *e; + ssize_t l; + + q = w = p; + e = q + sz; + while (q < e) { + size_t n; + + n = nul_length(q, e - q); + + /* If there are more than the specified run length of + * NUL bytes, or if this is the beginning or the end + * of the buffer, then seek instead of write */ + if ((n > run_length) || + (n > 0 && q == p) || + (n > 0 && q + n >= e)) { + if (q > w) { + l = write(fd, w, q - w); + if (l < 0) + return -errno; + if (l != q -w) + return -EIO; + } + + if (lseek(fd, n, SEEK_CUR) == (off_t) -1) + return -errno; + + q += n; + w = q; + } else if (n > 0) + q += n; + else + q++; + } + + if (q > w) { + l = write(fd, w, q - w); + if (l < 0) + return -errno; + if (l != q - w) + return -EIO; + } + + return q - (const uint8_t*) p; +} + +char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value) { + char *x; + + x = strjoin(field, value); + if (x) + iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(x); + return x; +} + +char* set_iovec_string_field_free(struct iovec *iovec, size_t *n_iovec, const char *field, char *value) { + char *x; + + x = set_iovec_string_field(iovec, n_iovec, field, value); + free(value); + return x; +} + +struct iovec_wrapper *iovw_new(void) { + return malloc0(sizeof(struct iovec_wrapper)); +} + +void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors) { + if (free_vectors) + for (size_t i = 0; i < iovw->count; i++) + free(iovw->iovec[i].iov_base); + + iovw->iovec = mfree(iovw->iovec); + iovw->count = 0; + iovw->size_bytes = 0; +} + +struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw) { + iovw_free_contents(iovw, true); + + return mfree(iovw); +} + +struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw) { + iovw_free_contents(iovw, false); + + return mfree(iovw); +} + +int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len) { + if (iovw->count >= IOV_MAX) + return -E2BIG; + + if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1)) + return log_oom(); + + iovw->iovec[iovw->count++] = IOVEC_MAKE(data, len); + return 0; +} + +int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value) { + _cleanup_free_ char *x = NULL; + int r; + + x = strjoin(field, value); + if (!x) + return log_oom(); + + r = iovw_put(iovw, x, strlen(x)); + if (r >= 0) + TAKE_PTR(x); + + return r; +} + +int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value) { + _cleanup_free_ _unused_ char *free_ptr = value; + + return iovw_put_string_field(iovw, field, value); +} + +void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new) { + size_t i; + + for (i = 0; i < iovw->count; i++) + iovw->iovec[i].iov_base = (char *)iovw->iovec[i].iov_base - old + new; +} + +size_t iovw_size(struct iovec_wrapper *iovw) { + size_t n = 0, i; + + for (i = 0; i < iovw->count; i++) + n += iovw->iovec[i].iov_len; + + return n; +} diff --git a/src/basic/io-util.h b/src/basic/io-util.h new file mode 100644 index 00000000..719e19e8 --- /dev/null +++ b/src/basic/io-util.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include + +#include "macro.h" +#include "time-util.h" + +int flush_fd(int fd); + +ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll); +int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll); +int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll); + +int pipe_eof(int fd); + +int fd_wait_for_event(int fd, int event, usec_t timeout); + +ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length); + +static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, size_t n) { + size_t j, r = 0; + + for (j = 0; j < n; j++) + r += i[j].iov_len; + + return r; +} + +static inline size_t IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) { + size_t j; + + for (j = 0; j < n; j++) { + size_t sub; + + if (_unlikely_(k <= 0)) + break; + + sub = MIN(i[j].iov_len, k); + i[j].iov_len -= sub; + i[j].iov_base = (uint8_t*) i[j].iov_base + sub; + k -= sub; + } + + return k; +} + +static inline bool FILE_SIZE_VALID(uint64_t l) { + /* ftruncate() and friends take an unsigned file size, but actually cannot deal with file sizes larger than + * 2^63 since the kernel internally handles it as signed value. This call allows checking for this early. */ + + return (l >> 63) == 0; +} + +static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) { + + /* Same as above, but allows one extra value: -1 as indication for infinity. */ + + if (l == (uint64_t) -1) + return true; + + return FILE_SIZE_VALID(l); + +} + +#define IOVEC_INIT(base, len) { .iov_base = (base), .iov_len = (len) } +#define IOVEC_MAKE(base, len) (struct iovec) IOVEC_INIT(base, len) +#define IOVEC_INIT_STRING(string) IOVEC_INIT((char*) string, strlen(string)) +#define IOVEC_MAKE_STRING(string) (struct iovec) IOVEC_INIT_STRING(string) + +char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value); +char* set_iovec_string_field_free(struct iovec *iovec, size_t *n_iovec, const char *field, char *value); + +struct iovec_wrapper { + struct iovec *iovec; + size_t count; + size_t size_bytes; +}; + +struct iovec_wrapper *iovw_new(void); +struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw); +struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw); +void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors); +int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len); +int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value); +int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value); +void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new); +size_t iovw_size(struct iovec_wrapper *iovw); diff --git a/src/basic/ioprio.h b/src/basic/ioprio.h new file mode 100644 index 00000000..3fb168da --- /dev/null +++ b/src/basic/ioprio.h @@ -0,0 +1,56 @@ +#ifndef IOPRIO_H +#define IOPRIO_H + +/* This is minimal version of Linux' linux/ioprio.h header file, which + * is licensed GPL2 */ + +#include +#include + +/* + * Gives us 8 prio classes with 13-bits of data for each class + */ +#define IOPRIO_BITS 16 +#define IOPRIO_N_CLASSES 8 +#define IOPRIO_CLASS_SHIFT 13 +#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) + +#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT) +#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK) +#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) + +#define ioprio_valid(mask) (IOPRIO_PRIO_CLASS((mask)) != IOPRIO_CLASS_NONE) + +/* + * These are the io priority groups as implemented by CFQ. RT is the realtime + * class, it always gets premium service. BE is the best-effort scheduling + * class, the default for any process. IDLE is the idle scheduling class, it + * is only served when no one else is using the disk. + */ +enum { + IOPRIO_CLASS_NONE, + IOPRIO_CLASS_RT, + IOPRIO_CLASS_BE, + IOPRIO_CLASS_IDLE, +}; + +/* + * 8 best effort priority levels are supported + */ +#define IOPRIO_BE_NR (8) + +enum { + IOPRIO_WHO_PROCESS = 1, + IOPRIO_WHO_PGRP, + IOPRIO_WHO_USER, +}; + +static inline int ioprio_set(int which, int who, int ioprio) { + return syscall(__NR_ioprio_set, which, who, ioprio); +} + +static inline int ioprio_get(int which, int who) { + return syscall(__NR_ioprio_get, which, who); +} + +#endif diff --git a/src/basic/kbd-util.c b/src/basic/kbd-util.c new file mode 100644 index 00000000..17d4022d --- /dev/null +++ b/src/basic/kbd-util.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "kbd-util.h" +#include "log.h" +#include "nulstr-util.h" +#include "path-util.h" +#include "set.h" +#include "string-util.h" +#include "strv.h" +#include "utf8.h" + +static thread_local Set *keymaps = NULL; + +static int nftw_cb( + const char *fpath, + const struct stat *sb, + int tflag, + struct FTW *ftwbuf) { + + _cleanup_free_ char *p = NULL; + char *e; + int r; + + if (tflag != FTW_F) + return 0; + + if (!endswith(fpath, ".map") && + !endswith(fpath, ".map.gz")) + return 0; + + p = strdup(basename(fpath)); + if (!p) + return FTW_STOP; + + e = endswith(p, ".map"); + if (e) + *e = 0; + + e = endswith(p, ".map.gz"); + if (e) + *e = 0; + + if (!keymap_is_valid(p)) + return 0; + + r = set_consume(keymaps, TAKE_PTR(p)); + if (r < 0 && r != -EEXIST) + return r; + + return 0; +} + +int get_keymaps(char ***ret) { + _cleanup_strv_free_ char **l = NULL; + const char *dir; + int r; + + keymaps = set_new(&string_hash_ops); + if (!keymaps) + return -ENOMEM; + + NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) { + r = nftw(dir, nftw_cb, 20, FTW_PHYS|FTW_ACTIONRETVAL); + + if (r == FTW_STOP) + log_debug("Directory not found %s", dir); + else if (r < 0) + log_debug_errno(r, "Can't add keymap: %m"); + } + + l = set_get_strv(keymaps); + if (!l) { + set_free_free(keymaps); + return -ENOMEM; + } + + set_free(keymaps); + + if (strv_isempty(l)) + return -ENOENT; + + strv_sort(l); + + *ret = TAKE_PTR(l); + + return 0; +} + +bool keymap_is_valid(const char *name) { + + if (isempty(name)) + return false; + + if (strlen(name) >= 128) + return false; + + if (!utf8_is_valid(name)) + return false; + + if (!filename_is_valid(name)) + return false; + + if (!string_is_safe(name)) + return false; + + return true; +} diff --git a/src/basic/kbd-util.h b/src/basic/kbd-util.h new file mode 100644 index 00000000..9efd2c70 --- /dev/null +++ b/src/basic/kbd-util.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#if HAVE_SPLIT_USR +#define KBD_KEYMAP_DIRS \ + "/usr/share/keymaps/\0" \ + "/usr/share/kbd/keymaps/\0" \ + "/usr/lib/kbd/keymaps/\0" \ + "/lib/kbd/keymaps/\0" +#else +#define KBD_KEYMAP_DIRS \ + "/usr/share/keymaps/\0" \ + "/usr/share/kbd/keymaps/\0" \ + "/usr/lib/kbd/keymaps/\0" +#endif + +int get_keymaps(char ***l); +bool keymap_is_valid(const char *name); diff --git a/src/basic/khash.c b/src/basic/khash.c new file mode 100644 index 00000000..e893298d --- /dev/null +++ b/src/basic/khash.c @@ -0,0 +1,322 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "hexdecoct.h" +#include "khash.h" +#include "macro.h" +#include "missing_socket.h" +#include "string-util.h" +#include "util.h" + +/* On current kernels the maximum digest (according to "grep digestsize /proc/crypto | sort -u") is actually 32, but + * let's add some extra room, the few wasted bytes don't really matter... */ +#define LONGEST_DIGEST 128 + +struct khash { + int fd; + char *algorithm; + uint8_t digest[LONGEST_DIGEST+1]; + size_t digest_size; + bool digest_valid; +}; + +int khash_supported(void) { + static const union { + struct sockaddr sa; + struct sockaddr_alg alg; + } sa = { + .alg.salg_family = AF_ALG, + .alg.salg_type = "hash", + .alg.salg_name = "sha256", /* a very common algorithm */ + }; + + static int cached = -1; + + if (cached < 0) { + _cleanup_close_ int fd1 = -1, fd2 = -1; + uint8_t buf[LONGEST_DIGEST+1]; + + fd1 = socket(AF_ALG, SOCK_SEQPACKET|SOCK_CLOEXEC, 0); + if (fd1 < 0) { + /* The kernel returns EAFNOSUPPORT if AF_ALG is not supported at all */ + if (IN_SET(errno, EAFNOSUPPORT, EOPNOTSUPP)) + return (cached = false); + + return -errno; + } + + if (bind(fd1, &sa.sa, sizeof(sa)) < 0) { + /* The kernel returns ENOENT if the selected algorithm is not supported at all. We use a check + * for SHA256 as a proxy for whether the whole API is supported at all. After all it's one of + * the most common hash functions, and if it isn't supported, that's ample indication that + * something is really off. */ + + if (IN_SET(errno, ENOENT, EOPNOTSUPP)) + return (cached = false); + + return -errno; + } + + fd2 = accept4(fd1, NULL, 0, SOCK_CLOEXEC); + if (fd2 < 0) { + if (errno == EOPNOTSUPP) + return (cached = false); + + return -errno; + } + + if (recv(fd2, buf, sizeof(buf), 0) < 0) { + /* On some kernels we get ENOKEY for non-keyed hash functions (such as sha256), let's refuse + * using the API in those cases, since the kernel is + * broken. https://github.com/systemd/systemd/issues/8278 */ + + if (IN_SET(errno, ENOKEY, EOPNOTSUPP)) + return (cached = false); + } + + cached = true; + } + + return cached; +} + +int khash_new_with_key(khash **ret, const char *algorithm, const void *key, size_t key_size) { + union { + struct sockaddr sa; + struct sockaddr_alg alg; + } sa = { + .alg.salg_family = AF_ALG, + .alg.salg_type = "hash", + }; + + _cleanup_(khash_unrefp) khash *h = NULL; + _cleanup_close_ int fd = -1; + int supported; + ssize_t n; + + assert(ret); + assert(key || key_size == 0); + + /* Filter out an empty algorithm early, as we do not support an algorithm by that name. */ + if (isempty(algorithm)) + return -EINVAL; + + /* Overly long hash algorithm names we definitely do not support */ + if (strlen(algorithm) >= sizeof(sa.alg.salg_name)) + return -EOPNOTSUPP; + + supported = khash_supported(); + if (supported < 0) + return supported; + if (supported == 0) + return -EOPNOTSUPP; + + fd = socket(AF_ALG, SOCK_SEQPACKET|SOCK_CLOEXEC, 0); + if (fd < 0) + return -errno; + + strcpy((char*) sa.alg.salg_name, algorithm); + if (bind(fd, &sa.sa, sizeof(sa)) < 0) { + if (errno == ENOENT) + return -EOPNOTSUPP; + return -errno; + } + + if (key) { + if (setsockopt(fd, SOL_ALG, ALG_SET_KEY, key, key_size) < 0) + return -errno; + } + + h = new0(khash, 1); + if (!h) + return -ENOMEM; + + h->fd = accept4(fd, NULL, 0, SOCK_CLOEXEC); + if (h->fd < 0) + return -errno; + + h->algorithm = strdup(algorithm); + if (!h->algorithm) + return -ENOMEM; + + /* Temporary fix for rc kernel bug: https://bugzilla.redhat.com/show_bug.cgi?id=1395896 */ + (void) send(h->fd, NULL, 0, 0); + + /* Figure out the digest size */ + n = recv(h->fd, h->digest, sizeof(h->digest), 0); + if (n < 0) + return -errno; + if (n >= LONGEST_DIGEST) /* longer than what we expected? If so, we don't support this */ + return -EOPNOTSUPP; + + h->digest_size = (size_t) n; + h->digest_valid = true; + + /* Temporary fix for rc kernel bug: https://bugzilla.redhat.com/show_bug.cgi?id=1395896 */ + (void) send(h->fd, NULL, 0, 0); + + *ret = h; + h = NULL; + + return 0; +} + +int khash_new(khash **ret, const char *algorithm) { + return khash_new_with_key(ret, algorithm, NULL, 0); +} + +khash* khash_unref(khash *h) { + if (!h) + return NULL; + + safe_close(h->fd); + free(h->algorithm); + return mfree(h); +} + +int khash_dup(khash *h, khash **ret) { + _cleanup_(khash_unrefp) khash *copy = NULL; + + assert(h); + assert(ret); + + copy = newdup(khash, h, 1); + if (!copy) + return -ENOMEM; + + copy->fd = -1; + copy->algorithm = strdup(h->algorithm); + if (!copy->algorithm) + return -ENOMEM; + + copy->fd = accept4(h->fd, NULL, 0, SOCK_CLOEXEC); + if (copy->fd < 0) + return -errno; + + *ret = TAKE_PTR(copy); + + return 0; +} + +const char *khash_get_algorithm(khash *h) { + assert(h); + + return h->algorithm; +} + +size_t khash_get_size(khash *h) { + assert(h); + + return h->digest_size; +} + +int khash_reset(khash *h) { + ssize_t n; + + assert(h); + + n = send(h->fd, NULL, 0, 0); + if (n < 0) + return -errno; + + h->digest_valid = false; + + return 0; +} + +int khash_put(khash *h, const void *buffer, size_t size) { + ssize_t n; + + assert(h); + assert(buffer || size == 0); + + if (size <= 0) + return 0; + + n = send(h->fd, buffer, size, MSG_MORE); + if (n < 0) + return -errno; + + h->digest_valid = false; + + return 0; +} + +int khash_put_iovec(khash *h, const struct iovec *iovec, size_t n) { + struct msghdr mh = { + mh.msg_iov = (struct iovec*) iovec, + mh.msg_iovlen = n, + }; + ssize_t k; + + assert(h); + assert(iovec || n == 0); + + if (n <= 0) + return 0; + + k = sendmsg(h->fd, &mh, MSG_MORE); + if (k < 0) + return -errno; + + h->digest_valid = false; + + return 0; +} + +static int retrieve_digest(khash *h) { + ssize_t n; + + assert(h); + + if (h->digest_valid) + return 0; + + n = recv(h->fd, h->digest, h->digest_size, 0); + if (n < 0) + return n; + if ((size_t) n != h->digest_size) /* digest size changed? */ + return -EIO; + + h->digest_valid = true; + + return 0; +} + +int khash_digest_data(khash *h, const void **ret) { + int r; + + assert(h); + assert(ret); + + r = retrieve_digest(h); + if (r < 0) + return r; + + *ret = h->digest; + return 0; +} + +int khash_digest_string(khash *h, char **ret) { + int r; + char *p; + + assert(h); + assert(ret); + + r = retrieve_digest(h); + if (r < 0) + return r; + + p = hexmem(h->digest, h->digest_size); + if (!p) + return -ENOMEM; + + *ret = p; + return 0; +} diff --git a/src/basic/khash.h b/src/basic/khash.h new file mode 100644 index 00000000..a3013b9d --- /dev/null +++ b/src/basic/khash.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "macro.h" + +typedef struct khash khash; + +int khash_supported(void); + +/* For plain hash functions. Hash functions commonly supported on today's kernels are: crc32c, crct10dif, crc32, + * sha224, sha256, sha512, sha384, sha1, md5, md4, sha3-224, sha3-256, sha3-384, sha3-512, and more. */ +int khash_new(khash **ret, const char *algorithm); + +/* For keyed hash functions. Hash functions commonly supported on today's kernels are: hmac(sha256), cmac(aes), + * cmac(des3_ede), hmac(sha3-512), hmac(sha3-384), hmac(sha3-256), hmac(sha3-224), hmac(rmd160), hmac(rmd128), + * hmac(sha224), hmac(sha512), hmac(sha384), hmac(sha1), hmac(md5), and more. */ +int khash_new_with_key(khash **ret, const char *algorithm, const void *key, size_t key_size); + +int khash_dup(khash *h, khash **ret); +khash* khash_unref(khash *h); + +const char *khash_get_algorithm(khash *h); +size_t khash_get_size(khash *h); + +int khash_reset(khash *h); + +int khash_put(khash *h, const void *buffer, size_t size); +int khash_put_iovec(khash *h, const struct iovec *iovec, size_t n); + +int khash_digest_data(khash *h, const void **ret); +int khash_digest_string(khash *h, char **ret); + +DEFINE_TRIVIAL_CLEANUP_FUNC(khash*, khash_unref); diff --git a/src/basic/label.c b/src/basic/label.c new file mode 100644 index 00000000..12a7fb09 --- /dev/null +++ b/src/basic/label.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "btrfs-util.h" +#include "label.h" +#include "macro.h" +#include "selinux-util.h" +#include "smack-util.h" + +int label_fix(const char *path, LabelFixFlags flags) { + int r, q; + + r = mac_selinux_fix(path, flags); + q = mac_smack_fix(path, flags); + + if (r < 0) + return r; + if (q < 0) + return q; + + return 0; +} + +int symlink_label(const char *old_path, const char *new_path) { + int r; + + assert(old_path); + assert(new_path); + + r = mac_selinux_create_file_prepare(new_path, S_IFLNK); + if (r < 0) + return r; + + if (symlink(old_path, new_path) < 0) + r = -errno; + + mac_selinux_create_file_clear(); + + if (r < 0) + return r; + + return mac_smack_fix(new_path, 0); +} + +int btrfs_subvol_make_label(const char *path) { + int r; + + assert(path); + + r = mac_selinux_create_file_prepare(path, S_IFDIR); + if (r < 0) + return r; + + r = btrfs_subvol_make(path); + mac_selinux_create_file_clear(); + + if (r < 0) + return r; + + return mac_smack_fix(path, 0); +} diff --git a/src/basic/label.h b/src/basic/label.h new file mode 100644 index 00000000..594fd659 --- /dev/null +++ b/src/basic/label.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +typedef enum LabelFixFlags { + LABEL_IGNORE_ENOENT = 1 << 0, + LABEL_IGNORE_EROFS = 1 << 1, +} LabelFixFlags; + +int label_fix(const char *path, LabelFixFlags flags); + +int mkdir_label(const char *path, mode_t mode); +int mkdirat_label(int dirfd, const char *path, mode_t mode); +int symlink_label(const char *old_path, const char *new_path); + +int btrfs_subvol_make_label(const char *path); diff --git a/src/basic/limits-util.c b/src/basic/limits-util.c new file mode 100644 index 00000000..a74d8197 --- /dev/null +++ b/src/basic/limits-util.c @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "cgroup-util.h" +#include "limits-util.h" +#include "memory-util.h" +#include "parse-util.h" +#include "process-util.h" +#include "procfs-util.h" +#include "string-util.h" + +uint64_t physical_memory(void) { + _cleanup_free_ char *root = NULL, *value = NULL; + uint64_t mem, lim; + size_t ps; + long sc; + int r; + + /* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of + * memory. + * + * In order to support containers nicely that have a configured memory limit we'll take the minimum of the + * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */ + + sc = sysconf(_SC_PHYS_PAGES); + assert(sc > 0); + + ps = page_size(); + mem = (uint64_t) sc * (uint64_t) ps; + + r = cg_get_root_path(&root); + if (r < 0) { + log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m"); + return mem; + } + + r = cg_all_unified(); + if (r < 0) { + log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m"); + return mem; + } + if (r > 0) { + r = cg_get_attribute("memory", root, "memory.max", &value); + if (r < 0) { + log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m"); + return mem; + } + + if (streq(value, "max")) + return mem; + } else { + r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value); + if (r < 0) { + log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m"); + return mem; + } + } + + r = safe_atou64(value, &lim); + if (r < 0) { + log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value); + return mem; + } + if (lim == UINT64_MAX) + return mem; + + /* Make sure the limit is a multiple of our own page size */ + lim /= ps; + lim *= ps; + + return MIN(mem, lim); +} + +uint64_t physical_memory_scale(uint64_t v, uint64_t max) { + uint64_t p, m, ps, r; + + assert(max > 0); + + /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success + * the result is a multiple of the page size (rounds down). */ + + ps = page_size(); + assert(ps > 0); + + p = physical_memory() / ps; + assert(p > 0); + + m = p * v; + if (m / p != v) + return UINT64_MAX; + + m /= max; + + r = m * ps; + if (r / ps != m) + return UINT64_MAX; + + return r; +} + +uint64_t system_tasks_max(void) { + uint64_t a = TASKS_MAX, b = TASKS_MAX; + _cleanup_free_ char *root = NULL; + int r; + + /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this + * limit: + * + * a) the maximum tasks value the kernel allows on this architecture + * b) the cgroups pids_max attribute for the system + * c) the kernel's configured maximum PID value + * + * And then pick the smallest of the three */ + + r = procfs_tasks_get_limit(&a); + if (r < 0) + log_debug_errno(r, "Failed to read maximum number of tasks from /proc, ignoring: %m"); + + r = cg_get_root_path(&root); + if (r < 0) + log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m"); + else { + _cleanup_free_ char *value = NULL; + + r = cg_get_attribute("pids", root, "pids.max", &value); + if (r < 0) + log_debug_errno(r, "Failed to read pids.max attribute of cgroup root, ignoring: %m"); + else if (!streq(value, "max")) { + r = safe_atou64(value, &b); + if (r < 0) + log_debug_errno(r, "Failed to parse pids.max attribute of cgroup root, ignoring: %m"); + } + } + + return MIN3(TASKS_MAX, + a <= 0 ? TASKS_MAX : a, + b <= 0 ? TASKS_MAX : b); +} + +uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) { + uint64_t t, m; + + assert(max > 0); + + /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages + * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */ + + t = system_tasks_max(); + assert(t > 0); + + m = t * v; + if (m / t != v) /* overflow? */ + return UINT64_MAX; + + return m / max; +} diff --git a/src/basic/limits-util.h b/src/basic/limits-util.h new file mode 100644 index 00000000..77895cba --- /dev/null +++ b/src/basic/limits-util.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +uint64_t physical_memory(void); +uint64_t physical_memory_scale(uint64_t v, uint64_t max); + +uint64_t system_tasks_max(void); +uint64_t system_tasks_max_scale(uint64_t v, uint64_t max); diff --git a/src/basic/linux/README b/src/basic/linux/README new file mode 100644 index 00000000..2bb70fda --- /dev/null +++ b/src/basic/linux/README @@ -0,0 +1,6 @@ +The files in this directory are copied from current kernel master +(b06ed1e7a2fa9b636f368a9e97c3c8877623f8b2) or WireGuard master +(8416093498ac2c754536dad4757c5d86c9ba8809), and the following +modifications are applied: +- btrfs.h: drop '__user' attributes +- if.h: drop '#include ' and '__user' attributes diff --git a/src/basic/linux/btrfs.h b/src/basic/linux/btrfs.h new file mode 100644 index 00000000..b960b45d --- /dev/null +++ b/src/basic/linux/btrfs.h @@ -0,0 +1,947 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2007 Oracle. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef _UAPI_LINUX_BTRFS_H +#define _UAPI_LINUX_BTRFS_H +#include +#include + +#define BTRFS_IOCTL_MAGIC 0x94 +#define BTRFS_VOL_NAME_MAX 255 +#define BTRFS_LABEL_SIZE 256 + +/* this should be 4k */ +#define BTRFS_PATH_NAME_MAX 4087 +struct btrfs_ioctl_vol_args { + __s64 fd; + char name[BTRFS_PATH_NAME_MAX + 1]; +}; + +#define BTRFS_DEVICE_PATH_NAME_MAX 1024 +#define BTRFS_SUBVOL_NAME_MAX 4039 + +#define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) +#define BTRFS_SUBVOL_RDONLY (1ULL << 1) +#define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) + +#define BTRFS_DEVICE_SPEC_BY_ID (1ULL << 3) + +#define BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED \ + (BTRFS_SUBVOL_CREATE_ASYNC | \ + BTRFS_SUBVOL_RDONLY | \ + BTRFS_SUBVOL_QGROUP_INHERIT | \ + BTRFS_DEVICE_SPEC_BY_ID) + +#define BTRFS_FSID_SIZE 16 +#define BTRFS_UUID_SIZE 16 +#define BTRFS_UUID_UNPARSED_SIZE 37 + +/* + * flags definition for qgroup limits + * + * Used by: + * struct btrfs_qgroup_limit.flags + * struct btrfs_qgroup_limit_item.flags + */ +#define BTRFS_QGROUP_LIMIT_MAX_RFER (1ULL << 0) +#define BTRFS_QGROUP_LIMIT_MAX_EXCL (1ULL << 1) +#define BTRFS_QGROUP_LIMIT_RSV_RFER (1ULL << 2) +#define BTRFS_QGROUP_LIMIT_RSV_EXCL (1ULL << 3) +#define BTRFS_QGROUP_LIMIT_RFER_CMPR (1ULL << 4) +#define BTRFS_QGROUP_LIMIT_EXCL_CMPR (1ULL << 5) + +struct btrfs_qgroup_limit { + __u64 flags; + __u64 max_rfer; + __u64 max_excl; + __u64 rsv_rfer; + __u64 rsv_excl; +}; + +/* + * flags definition for qgroup inheritance + * + * Used by: + * struct btrfs_qgroup_inherit.flags + */ +#define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0) + +struct btrfs_qgroup_inherit { + __u64 flags; + __u64 num_qgroups; + __u64 num_ref_copies; + __u64 num_excl_copies; + struct btrfs_qgroup_limit lim; + __u64 qgroups[0]; +}; + +struct btrfs_ioctl_qgroup_limit_args { + __u64 qgroupid; + struct btrfs_qgroup_limit lim; +}; + +/* + * flags for subvolumes + * + * Used by: + * struct btrfs_ioctl_vol_args_v2.flags + * + * BTRFS_SUBVOL_RDONLY is also provided/consumed by the following ioctls: + * - BTRFS_IOC_SUBVOL_GETFLAGS + * - BTRFS_IOC_SUBVOL_SETFLAGS + */ + +struct btrfs_ioctl_vol_args_v2 { + __s64 fd; + __u64 transid; + __u64 flags; + union { + struct { + __u64 size; + struct btrfs_qgroup_inherit *qgroup_inherit; + }; + __u64 unused[4]; + }; + union { + char name[BTRFS_SUBVOL_NAME_MAX + 1]; + __u64 devid; + }; +}; + +/* + * structure to report errors and progress to userspace, either as a + * result of a finished scrub, a canceled scrub or a progress inquiry + */ +struct btrfs_scrub_progress { + __u64 data_extents_scrubbed; /* # of data extents scrubbed */ + __u64 tree_extents_scrubbed; /* # of tree extents scrubbed */ + __u64 data_bytes_scrubbed; /* # of data bytes scrubbed */ + __u64 tree_bytes_scrubbed; /* # of tree bytes scrubbed */ + __u64 read_errors; /* # of read errors encountered (EIO) */ + __u64 csum_errors; /* # of failed csum checks */ + __u64 verify_errors; /* # of occurences, where the metadata + * of a tree block did not match the + * expected values, like generation or + * logical */ + __u64 no_csum; /* # of 4k data block for which no csum + * is present, probably the result of + * data written with nodatasum */ + __u64 csum_discards; /* # of csum for which no data was found + * in the extent tree. */ + __u64 super_errors; /* # of bad super blocks encountered */ + __u64 malloc_errors; /* # of internal kmalloc errors. These + * will likely cause an incomplete + * scrub */ + __u64 uncorrectable_errors; /* # of errors where either no intact + * copy was found or the writeback + * failed */ + __u64 corrected_errors; /* # of errors corrected */ + __u64 last_physical; /* last physical address scrubbed. In + * case a scrub was aborted, this can + * be used to restart the scrub */ + __u64 unverified_errors; /* # of occurences where a read for a + * full (64k) bio failed, but the re- + * check succeeded for each 4k piece. + * Intermittent error. */ +}; + +#define BTRFS_SCRUB_READONLY 1 +struct btrfs_ioctl_scrub_args { + __u64 devid; /* in */ + __u64 start; /* in */ + __u64 end; /* in */ + __u64 flags; /* in */ + struct btrfs_scrub_progress progress; /* out */ + /* pad to 1k */ + __u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8]; +}; + +#define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS 0 +#define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID 1 +struct btrfs_ioctl_dev_replace_start_params { + __u64 srcdevid; /* in, if 0, use srcdev_name instead */ + __u64 cont_reading_from_srcdev_mode; /* in, see #define + * above */ + __u8 srcdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1]; /* in */ + __u8 tgtdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1]; /* in */ +}; + +#define BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED 0 +#define BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED 1 +#define BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED 2 +#define BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED 3 +#define BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED 4 +struct btrfs_ioctl_dev_replace_status_params { + __u64 replace_state; /* out, see #define above */ + __u64 progress_1000; /* out, 0 <= x <= 1000 */ + __u64 time_started; /* out, seconds since 1-Jan-1970 */ + __u64 time_stopped; /* out, seconds since 1-Jan-1970 */ + __u64 num_write_errors; /* out */ + __u64 num_uncorrectable_read_errors; /* out */ +}; + +#define BTRFS_IOCTL_DEV_REPLACE_CMD_START 0 +#define BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS 1 +#define BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL 2 +#define BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR 0 +#define BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED 1 +#define BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED 2 +#define BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS 3 +struct btrfs_ioctl_dev_replace_args { + __u64 cmd; /* in */ + __u64 result; /* out */ + + union { + struct btrfs_ioctl_dev_replace_start_params start; + struct btrfs_ioctl_dev_replace_status_params status; + }; /* in/out */ + + __u64 spare[64]; +}; + +struct btrfs_ioctl_dev_info_args { + __u64 devid; /* in/out */ + __u8 uuid[BTRFS_UUID_SIZE]; /* in/out */ + __u64 bytes_used; /* out */ + __u64 total_bytes; /* out */ + __u64 unused[379]; /* pad to 4k */ + __u8 path[BTRFS_DEVICE_PATH_NAME_MAX]; /* out */ +}; + +struct btrfs_ioctl_fs_info_args { + __u64 max_id; /* out */ + __u64 num_devices; /* out */ + __u8 fsid[BTRFS_FSID_SIZE]; /* out */ + __u32 nodesize; /* out */ + __u32 sectorsize; /* out */ + __u32 clone_alignment; /* out */ + __u32 reserved32; + __u64 reserved[122]; /* pad to 1k */ +}; + +/* + * feature flags + * + * Used by: + * struct btrfs_ioctl_feature_flags + */ +#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0) +/* + * Older kernels (< 4.9) on big-endian systems produced broken free space tree + * bitmaps, and btrfs-progs also used to corrupt the free space tree (versions + * < 4.7.3). If this bit is clear, then the free space tree cannot be trusted. + * btrfs-progs can also intentionally clear this bit to ask the kernel to + * rebuild the free space tree, however this might not work on older kernels + * that do not know about this bit. If not sure, clear the cache manually on + * first mount when booting older kernel versions. + */ +#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID (1ULL << 1) + +#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) +#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) +#define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) +#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO (1ULL << 3) +#define BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD (1ULL << 4) + +/* + * older kernels tried to do bigger metadata blocks, but the + * code was pretty buggy. Lets not let them try anymore. + */ +#define BTRFS_FEATURE_INCOMPAT_BIG_METADATA (1ULL << 5) + +#define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF (1ULL << 6) +#define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7) +#define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8) +#define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9) +#define BTRFS_FEATURE_INCOMPAT_METADATA_UUID (1ULL << 10) + +struct btrfs_ioctl_feature_flags { + __u64 compat_flags; + __u64 compat_ro_flags; + __u64 incompat_flags; +}; + +/* balance control ioctl modes */ +#define BTRFS_BALANCE_CTL_PAUSE 1 +#define BTRFS_BALANCE_CTL_CANCEL 2 + +/* + * this is packed, because it should be exactly the same as its disk + * byte order counterpart (struct btrfs_disk_balance_args) + */ +struct btrfs_balance_args { + __u64 profiles; + union { + __u64 usage; + struct { + __u32 usage_min; + __u32 usage_max; + }; + }; + __u64 devid; + __u64 pstart; + __u64 pend; + __u64 vstart; + __u64 vend; + + __u64 target; + + __u64 flags; + + /* + * BTRFS_BALANCE_ARGS_LIMIT with value 'limit' + * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum + * and maximum + */ + union { + __u64 limit; /* limit number of processed chunks */ + struct { + __u32 limit_min; + __u32 limit_max; + }; + }; + + /* + * Process chunks that cross stripes_min..stripes_max devices, + * BTRFS_BALANCE_ARGS_STRIPES_RANGE + */ + __u32 stripes_min; + __u32 stripes_max; + + __u64 unused[6]; +} __attribute__ ((__packed__)); + +/* report balance progress to userspace */ +struct btrfs_balance_progress { + __u64 expected; /* estimated # of chunks that will be + * relocated to fulfill the request */ + __u64 considered; /* # of chunks we have considered so far */ + __u64 completed; /* # of chunks relocated so far */ +}; + +/* + * flags definition for balance + * + * Restriper's general type filter + * + * Used by: + * btrfs_ioctl_balance_args.flags + * btrfs_balance_control.flags (internal) + */ +#define BTRFS_BALANCE_DATA (1ULL << 0) +#define BTRFS_BALANCE_SYSTEM (1ULL << 1) +#define BTRFS_BALANCE_METADATA (1ULL << 2) + +#define BTRFS_BALANCE_TYPE_MASK (BTRFS_BALANCE_DATA | \ + BTRFS_BALANCE_SYSTEM | \ + BTRFS_BALANCE_METADATA) + +#define BTRFS_BALANCE_FORCE (1ULL << 3) +#define BTRFS_BALANCE_RESUME (1ULL << 4) + +/* + * flags definitions for per-type balance args + * + * Balance filters + * + * Used by: + * struct btrfs_balance_args + */ +#define BTRFS_BALANCE_ARGS_PROFILES (1ULL << 0) +#define BTRFS_BALANCE_ARGS_USAGE (1ULL << 1) +#define BTRFS_BALANCE_ARGS_DEVID (1ULL << 2) +#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3) +#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4) +#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5) +#define BTRFS_BALANCE_ARGS_LIMIT_RANGE (1ULL << 6) +#define BTRFS_BALANCE_ARGS_STRIPES_RANGE (1ULL << 7) +#define BTRFS_BALANCE_ARGS_USAGE_RANGE (1ULL << 10) + +#define BTRFS_BALANCE_ARGS_MASK \ + (BTRFS_BALANCE_ARGS_PROFILES | \ + BTRFS_BALANCE_ARGS_USAGE | \ + BTRFS_BALANCE_ARGS_DEVID | \ + BTRFS_BALANCE_ARGS_DRANGE | \ + BTRFS_BALANCE_ARGS_VRANGE | \ + BTRFS_BALANCE_ARGS_LIMIT | \ + BTRFS_BALANCE_ARGS_LIMIT_RANGE | \ + BTRFS_BALANCE_ARGS_STRIPES_RANGE | \ + BTRFS_BALANCE_ARGS_USAGE_RANGE) + +/* + * Profile changing flags. When SOFT is set we won't relocate chunk if + * it already has the target profile (even though it may be + * half-filled). + */ +#define BTRFS_BALANCE_ARGS_CONVERT (1ULL << 8) +#define BTRFS_BALANCE_ARGS_SOFT (1ULL << 9) + + +/* + * flags definition for balance state + * + * Used by: + * struct btrfs_ioctl_balance_args.state + */ +#define BTRFS_BALANCE_STATE_RUNNING (1ULL << 0) +#define BTRFS_BALANCE_STATE_PAUSE_REQ (1ULL << 1) +#define BTRFS_BALANCE_STATE_CANCEL_REQ (1ULL << 2) + +struct btrfs_ioctl_balance_args { + __u64 flags; /* in/out */ + __u64 state; /* out */ + + struct btrfs_balance_args data; /* in/out */ + struct btrfs_balance_args meta; /* in/out */ + struct btrfs_balance_args sys; /* in/out */ + + struct btrfs_balance_progress stat; /* out */ + + __u64 unused[72]; /* pad to 1k */ +}; + +#define BTRFS_INO_LOOKUP_PATH_MAX 4080 +struct btrfs_ioctl_ino_lookup_args { + __u64 treeid; + __u64 objectid; + char name[BTRFS_INO_LOOKUP_PATH_MAX]; +}; + +#define BTRFS_INO_LOOKUP_USER_PATH_MAX (4080 - BTRFS_VOL_NAME_MAX - 1) +struct btrfs_ioctl_ino_lookup_user_args { + /* in, inode number containing the subvolume of 'subvolid' */ + __u64 dirid; + /* in */ + __u64 treeid; + /* out, name of the subvolume of 'treeid' */ + char name[BTRFS_VOL_NAME_MAX + 1]; + /* + * out, constructed path from the directory with which the ioctl is + * called to dirid + */ + char path[BTRFS_INO_LOOKUP_USER_PATH_MAX]; +}; + +/* Search criteria for the btrfs SEARCH ioctl family. */ +struct btrfs_ioctl_search_key { + /* + * The tree we're searching in. 1 is the tree of tree roots, 2 is the + * extent tree, etc... + * + * A special tree_id value of 0 will cause a search in the subvolume + * tree that the inode which is passed to the ioctl is part of. + */ + __u64 tree_id; /* in */ + + /* + * When doing a tree search, we're actually taking a slice from a + * linear search space of 136-bit keys. + * + * A full 136-bit tree key is composed as: + * (objectid << 72) + (type << 64) + offset + * + * The individual min and max values for objectid, type and offset + * define the min_key and max_key values for the search range. All + * metadata items with a key in the interval [min_key, max_key] will be + * returned. + * + * Additionally, we can filter the items returned on transaction id of + * the metadata block they're stored in by specifying a transid range. + * Be aware that this transaction id only denotes when the metadata + * page that currently contains the item got written the last time as + * result of a COW operation. The number does not have any meaning + * related to the transaction in which an individual item that is being + * returned was created or changed. + */ + __u64 min_objectid; /* in */ + __u64 max_objectid; /* in */ + __u64 min_offset; /* in */ + __u64 max_offset; /* in */ + __u64 min_transid; /* in */ + __u64 max_transid; /* in */ + __u32 min_type; /* in */ + __u32 max_type; /* in */ + + /* + * input: The maximum amount of results desired. + * output: The actual amount of items returned, restricted by any of: + * - reaching the upper bound of the search range + * - reaching the input nr_items amount of items + * - completely filling the supplied memory buffer + */ + __u32 nr_items; /* in/out */ + + /* align to 64 bits */ + __u32 unused; + + /* some extra for later */ + __u64 unused1; + __u64 unused2; + __u64 unused3; + __u64 unused4; +}; + +struct btrfs_ioctl_search_header { + __u64 transid; + __u64 objectid; + __u64 offset; + __u32 type; + __u32 len; +}; + +#define BTRFS_SEARCH_ARGS_BUFSIZE (4096 - sizeof(struct btrfs_ioctl_search_key)) +/* + * the buf is an array of search headers where + * each header is followed by the actual item + * the type field is expanded to 32 bits for alignment + */ +struct btrfs_ioctl_search_args { + struct btrfs_ioctl_search_key key; + char buf[BTRFS_SEARCH_ARGS_BUFSIZE]; +}; + +struct btrfs_ioctl_search_args_v2 { + struct btrfs_ioctl_search_key key; /* in/out - search parameters */ + __u64 buf_size; /* in - size of buffer + * out - on EOVERFLOW: needed size + * to store item */ + __u64 buf[0]; /* out - found items */ +}; + +struct btrfs_ioctl_clone_range_args { + __s64 src_fd; + __u64 src_offset, src_length; + __u64 dest_offset; +}; + +/* + * flags definition for the defrag range ioctl + * + * Used by: + * struct btrfs_ioctl_defrag_range_args.flags + */ +#define BTRFS_DEFRAG_RANGE_COMPRESS 1 +#define BTRFS_DEFRAG_RANGE_START_IO 2 +struct btrfs_ioctl_defrag_range_args { + /* start of the defrag operation */ + __u64 start; + + /* number of bytes to defrag, use (u64)-1 to say all */ + __u64 len; + + /* + * flags for the operation, which can include turning + * on compression for this one defrag + */ + __u64 flags; + + /* + * any extent bigger than this will be considered + * already defragged. Use 0 to take the kernel default + * Use 1 to say every single extent must be rewritten + */ + __u32 extent_thresh; + + /* + * which compression method to use if turning on compression + * for this defrag operation. If unspecified, zlib will + * be used + */ + __u32 compress_type; + + /* spare for later */ + __u32 unused[4]; +}; + + +#define BTRFS_SAME_DATA_DIFFERS 1 +/* For extent-same ioctl */ +struct btrfs_ioctl_same_extent_info { + __s64 fd; /* in - destination file */ + __u64 logical_offset; /* in - start of extent in destination */ + __u64 bytes_deduped; /* out - total # of bytes we were able + * to dedupe from this file */ + /* status of this dedupe operation: + * 0 if dedup succeeds + * < 0 for error + * == BTRFS_SAME_DATA_DIFFERS if data differs + */ + __s32 status; /* out - see above description */ + __u32 reserved; +}; + +struct btrfs_ioctl_same_args { + __u64 logical_offset; /* in - start of extent in source */ + __u64 length; /* in - length of extent */ + __u16 dest_count; /* in - total elements in info array */ + __u16 reserved1; + __u32 reserved2; + struct btrfs_ioctl_same_extent_info info[0]; +}; + +struct btrfs_ioctl_space_info { + __u64 flags; + __u64 total_bytes; + __u64 used_bytes; +}; + +struct btrfs_ioctl_space_args { + __u64 space_slots; + __u64 total_spaces; + struct btrfs_ioctl_space_info spaces[0]; +}; + +struct btrfs_data_container { + __u32 bytes_left; /* out -- bytes not needed to deliver output */ + __u32 bytes_missing; /* out -- additional bytes needed for result */ + __u32 elem_cnt; /* out */ + __u32 elem_missed; /* out */ + __u64 val[0]; /* out */ +}; + +struct btrfs_ioctl_ino_path_args { + __u64 inum; /* in */ + __u64 size; /* in */ + __u64 reserved[4]; + /* struct btrfs_data_container *fspath; out */ + __u64 fspath; /* out */ +}; + +struct btrfs_ioctl_logical_ino_args { + __u64 logical; /* in */ + __u64 size; /* in */ + __u64 reserved[3]; /* must be 0 for now */ + __u64 flags; /* in, v2 only */ + /* struct btrfs_data_container *inodes; out */ + __u64 inodes; +}; +/* Return every ref to the extent, not just those containing logical block. + * Requires logical == extent bytenr. */ +#define BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET (1ULL << 0) + +enum btrfs_dev_stat_values { + /* disk I/O failure stats */ + BTRFS_DEV_STAT_WRITE_ERRS, /* EIO or EREMOTEIO from lower layers */ + BTRFS_DEV_STAT_READ_ERRS, /* EIO or EREMOTEIO from lower layers */ + BTRFS_DEV_STAT_FLUSH_ERRS, /* EIO or EREMOTEIO from lower layers */ + + /* stats for indirect indications for I/O failures */ + BTRFS_DEV_STAT_CORRUPTION_ERRS, /* checksum error, bytenr error or + * contents is illegal: this is an + * indication that the block was damaged + * during read or write, or written to + * wrong location or read from wrong + * location */ + BTRFS_DEV_STAT_GENERATION_ERRS, /* an indication that blocks have not + * been written */ + + BTRFS_DEV_STAT_VALUES_MAX +}; + +/* Reset statistics after reading; needs SYS_ADMIN capability */ +#define BTRFS_DEV_STATS_RESET (1ULL << 0) + +struct btrfs_ioctl_get_dev_stats { + __u64 devid; /* in */ + __u64 nr_items; /* in/out */ + __u64 flags; /* in/out */ + + /* out values: */ + __u64 values[BTRFS_DEV_STAT_VALUES_MAX]; + + __u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */ +}; + +#define BTRFS_QUOTA_CTL_ENABLE 1 +#define BTRFS_QUOTA_CTL_DISABLE 2 +#define BTRFS_QUOTA_CTL_RESCAN__NOTUSED 3 +struct btrfs_ioctl_quota_ctl_args { + __u64 cmd; + __u64 status; +}; + +struct btrfs_ioctl_quota_rescan_args { + __u64 flags; + __u64 progress; + __u64 reserved[6]; +}; + +struct btrfs_ioctl_qgroup_assign_args { + __u64 assign; + __u64 src; + __u64 dst; +}; + +struct btrfs_ioctl_qgroup_create_args { + __u64 create; + __u64 qgroupid; +}; +struct btrfs_ioctl_timespec { + __u64 sec; + __u32 nsec; +}; + +struct btrfs_ioctl_received_subvol_args { + char uuid[BTRFS_UUID_SIZE]; /* in */ + __u64 stransid; /* in */ + __u64 rtransid; /* out */ + struct btrfs_ioctl_timespec stime; /* in */ + struct btrfs_ioctl_timespec rtime; /* out */ + __u64 flags; /* in */ + __u64 reserved[16]; /* in */ +}; + +/* + * Caller doesn't want file data in the send stream, even if the + * search of clone sources doesn't find an extent. UPDATE_EXTENT + * commands will be sent instead of WRITE commands. + */ +#define BTRFS_SEND_FLAG_NO_FILE_DATA 0x1 + +/* + * Do not add the leading stream header. Used when multiple snapshots + * are sent back to back. + */ +#define BTRFS_SEND_FLAG_OMIT_STREAM_HEADER 0x2 + +/* + * Omit the command at the end of the stream that indicated the end + * of the stream. This option is used when multiple snapshots are + * sent back to back. + */ +#define BTRFS_SEND_FLAG_OMIT_END_CMD 0x4 + +#define BTRFS_SEND_FLAG_MASK \ + (BTRFS_SEND_FLAG_NO_FILE_DATA | \ + BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | \ + BTRFS_SEND_FLAG_OMIT_END_CMD) + +struct btrfs_ioctl_send_args { + __s64 send_fd; /* in */ + __u64 clone_sources_count; /* in */ + __u64 *clone_sources; /* in */ + __u64 parent_root; /* in */ + __u64 flags; /* in */ + __u64 reserved[4]; /* in */ +}; + +/* + * Information about a fs tree root. + * + * All items are filled by the ioctl + */ +struct btrfs_ioctl_get_subvol_info_args { + /* Id of this subvolume */ + __u64 treeid; + + /* Name of this subvolume, used to get the real name at mount point */ + char name[BTRFS_VOL_NAME_MAX + 1]; + + /* + * Id of the subvolume which contains this subvolume. + * Zero for top-level subvolume or a deleted subvolume. + */ + __u64 parent_id; + + /* + * Inode number of the directory which contains this subvolume. + * Zero for top-level subvolume or a deleted subvolume + */ + __u64 dirid; + + /* Latest transaction id of this subvolume */ + __u64 generation; + + /* Flags of this subvolume */ + __u64 flags; + + /* UUID of this subvolume */ + __u8 uuid[BTRFS_UUID_SIZE]; + + /* + * UUID of the subvolume of which this subvolume is a snapshot. + * All zero for a non-snapshot subvolume. + */ + __u8 parent_uuid[BTRFS_UUID_SIZE]; + + /* + * UUID of the subvolume from which this subvolume was received. + * All zero for non-received subvolume. + */ + __u8 received_uuid[BTRFS_UUID_SIZE]; + + /* Transaction id indicating when change/create/send/receive happened */ + __u64 ctransid; + __u64 otransid; + __u64 stransid; + __u64 rtransid; + /* Time corresponding to c/o/s/rtransid */ + struct btrfs_ioctl_timespec ctime; + struct btrfs_ioctl_timespec otime; + struct btrfs_ioctl_timespec stime; + struct btrfs_ioctl_timespec rtime; + + /* Must be zero */ + __u64 reserved[8]; +}; + +#define BTRFS_MAX_ROOTREF_BUFFER_NUM 255 +struct btrfs_ioctl_get_subvol_rootref_args { + /* in/out, minimum id of rootref's treeid to be searched */ + __u64 min_treeid; + + /* out */ + struct { + __u64 treeid; + __u64 dirid; + } rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM]; + + /* out, number of found items */ + __u8 num_items; + __u8 align[7]; +}; + +/* Error codes as returned by the kernel */ +enum btrfs_err_code { + BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET = 1, + BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET, + BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET, + BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET, + BTRFS_ERROR_DEV_TGT_REPLACE, + BTRFS_ERROR_DEV_MISSING_NOT_FOUND, + BTRFS_ERROR_DEV_ONLY_WRITABLE, + BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS +}; + +#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_RESIZE _IOW(BTRFS_IOCTL_MAGIC, 3, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_FORGET_DEV _IOW(BTRFS_IOCTL_MAGIC, 5, \ + struct btrfs_ioctl_vol_args) +/* trans start and trans end are dangerous, and only for + * use by applications that know how to avoid the + * resulting deadlocks + */ +#define BTRFS_IOC_TRANS_START _IO(BTRFS_IOCTL_MAGIC, 6) +#define BTRFS_IOC_TRANS_END _IO(BTRFS_IOCTL_MAGIC, 7) +#define BTRFS_IOC_SYNC _IO(BTRFS_IOCTL_MAGIC, 8) + +#define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int) +#define BTRFS_IOC_ADD_DEV _IOW(BTRFS_IOCTL_MAGIC, 10, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_RM_DEV _IOW(BTRFS_IOCTL_MAGIC, 11, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_BALANCE _IOW(BTRFS_IOCTL_MAGIC, 12, \ + struct btrfs_ioctl_vol_args) + +#define BTRFS_IOC_CLONE_RANGE _IOW(BTRFS_IOCTL_MAGIC, 13, \ + struct btrfs_ioctl_clone_range_args) + +#define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_DEFRAG_RANGE _IOW(BTRFS_IOCTL_MAGIC, 16, \ + struct btrfs_ioctl_defrag_range_args) +#define BTRFS_IOC_TREE_SEARCH _IOWR(BTRFS_IOCTL_MAGIC, 17, \ + struct btrfs_ioctl_search_args) +#define BTRFS_IOC_TREE_SEARCH_V2 _IOWR(BTRFS_IOCTL_MAGIC, 17, \ + struct btrfs_ioctl_search_args_v2) +#define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \ + struct btrfs_ioctl_ino_lookup_args) +#define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, __u64) +#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \ + struct btrfs_ioctl_space_args) +#define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64) +#define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64) +#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \ + struct btrfs_ioctl_vol_args_v2) +#define BTRFS_IOC_SUBVOL_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 24, \ + struct btrfs_ioctl_vol_args_v2) +#define BTRFS_IOC_SUBVOL_GETFLAGS _IOR(BTRFS_IOCTL_MAGIC, 25, __u64) +#define BTRFS_IOC_SUBVOL_SETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 26, __u64) +#define BTRFS_IOC_SCRUB _IOWR(BTRFS_IOCTL_MAGIC, 27, \ + struct btrfs_ioctl_scrub_args) +#define BTRFS_IOC_SCRUB_CANCEL _IO(BTRFS_IOCTL_MAGIC, 28) +#define BTRFS_IOC_SCRUB_PROGRESS _IOWR(BTRFS_IOCTL_MAGIC, 29, \ + struct btrfs_ioctl_scrub_args) +#define BTRFS_IOC_DEV_INFO _IOWR(BTRFS_IOCTL_MAGIC, 30, \ + struct btrfs_ioctl_dev_info_args) +#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \ + struct btrfs_ioctl_fs_info_args) +#define BTRFS_IOC_BALANCE_V2 _IOWR(BTRFS_IOCTL_MAGIC, 32, \ + struct btrfs_ioctl_balance_args) +#define BTRFS_IOC_BALANCE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int) +#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 34, \ + struct btrfs_ioctl_balance_args) +#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \ + struct btrfs_ioctl_ino_path_args) +#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ + struct btrfs_ioctl_logical_ino_args) +#define BTRFS_IOC_SET_RECEIVED_SUBVOL _IOWR(BTRFS_IOCTL_MAGIC, 37, \ + struct btrfs_ioctl_received_subvol_args) +#define BTRFS_IOC_SEND _IOW(BTRFS_IOCTL_MAGIC, 38, struct btrfs_ioctl_send_args) +#define BTRFS_IOC_DEVICES_READY _IOR(BTRFS_IOCTL_MAGIC, 39, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_QUOTA_CTL _IOWR(BTRFS_IOCTL_MAGIC, 40, \ + struct btrfs_ioctl_quota_ctl_args) +#define BTRFS_IOC_QGROUP_ASSIGN _IOW(BTRFS_IOCTL_MAGIC, 41, \ + struct btrfs_ioctl_qgroup_assign_args) +#define BTRFS_IOC_QGROUP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 42, \ + struct btrfs_ioctl_qgroup_create_args) +#define BTRFS_IOC_QGROUP_LIMIT _IOR(BTRFS_IOCTL_MAGIC, 43, \ + struct btrfs_ioctl_qgroup_limit_args) +#define BTRFS_IOC_QUOTA_RESCAN _IOW(BTRFS_IOCTL_MAGIC, 44, \ + struct btrfs_ioctl_quota_rescan_args) +#define BTRFS_IOC_QUOTA_RESCAN_STATUS _IOR(BTRFS_IOCTL_MAGIC, 45, \ + struct btrfs_ioctl_quota_rescan_args) +#define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46) +#define BTRFS_IOC_GET_FSLABEL _IOR(BTRFS_IOCTL_MAGIC, 49, \ + char[BTRFS_LABEL_SIZE]) +#define BTRFS_IOC_SET_FSLABEL _IOW(BTRFS_IOCTL_MAGIC, 50, \ + char[BTRFS_LABEL_SIZE]) +#define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \ + struct btrfs_ioctl_get_dev_stats) +#define BTRFS_IOC_DEV_REPLACE _IOWR(BTRFS_IOCTL_MAGIC, 53, \ + struct btrfs_ioctl_dev_replace_args) +#define BTRFS_IOC_FILE_EXTENT_SAME _IOWR(BTRFS_IOCTL_MAGIC, 54, \ + struct btrfs_ioctl_same_args) +#define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ + struct btrfs_ioctl_feature_flags) +#define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 57, \ + struct btrfs_ioctl_feature_flags[2]) +#define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ + struct btrfs_ioctl_feature_flags[3]) +#define BTRFS_IOC_RM_DEV_V2 _IOW(BTRFS_IOCTL_MAGIC, 58, \ + struct btrfs_ioctl_vol_args_v2) +#define BTRFS_IOC_LOGICAL_INO_V2 _IOWR(BTRFS_IOCTL_MAGIC, 59, \ + struct btrfs_ioctl_logical_ino_args) +#define BTRFS_IOC_GET_SUBVOL_INFO _IOR(BTRFS_IOCTL_MAGIC, 60, \ + struct btrfs_ioctl_get_subvol_info_args) +#define BTRFS_IOC_GET_SUBVOL_ROOTREF _IOWR(BTRFS_IOCTL_MAGIC, 61, \ + struct btrfs_ioctl_get_subvol_rootref_args) +#define BTRFS_IOC_INO_LOOKUP_USER _IOWR(BTRFS_IOCTL_MAGIC, 62, \ + struct btrfs_ioctl_ino_lookup_user_args) + +#endif /* _UAPI_LINUX_BTRFS_H */ diff --git a/src/basic/linux/btrfs_tree.h b/src/basic/linux/btrfs_tree.h new file mode 100644 index 00000000..421239b9 --- /dev/null +++ b/src/basic/linux/btrfs_tree.h @@ -0,0 +1,976 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _BTRFS_CTREE_H_ +#define _BTRFS_CTREE_H_ + +#include +#include + +/* + * This header contains the structure definitions and constants used + * by file system objects that can be retrieved using + * the BTRFS_IOC_SEARCH_TREE ioctl. That means basically anything that + * is needed to describe a leaf node's key or item contents. + */ + +/* holds pointers to all of the tree roots */ +#define BTRFS_ROOT_TREE_OBJECTID 1ULL + +/* stores information about which extents are in use, and reference counts */ +#define BTRFS_EXTENT_TREE_OBJECTID 2ULL + +/* + * chunk tree stores translations from logical -> physical block numbering + * the super block points to the chunk tree + */ +#define BTRFS_CHUNK_TREE_OBJECTID 3ULL + +/* + * stores information about which areas of a given device are in use. + * one per device. The tree of tree roots points to the device tree + */ +#define BTRFS_DEV_TREE_OBJECTID 4ULL + +/* one per subvolume, storing files and directories */ +#define BTRFS_FS_TREE_OBJECTID 5ULL + +/* directory objectid inside the root tree */ +#define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL + +/* holds checksums of all the data extents */ +#define BTRFS_CSUM_TREE_OBJECTID 7ULL + +/* holds quota configuration and tracking */ +#define BTRFS_QUOTA_TREE_OBJECTID 8ULL + +/* for storing items that use the BTRFS_UUID_KEY* types */ +#define BTRFS_UUID_TREE_OBJECTID 9ULL + +/* tracks free space in block groups. */ +#define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL + +/* device stats in the device tree */ +#define BTRFS_DEV_STATS_OBJECTID 0ULL + +/* for storing balance parameters in the root tree */ +#define BTRFS_BALANCE_OBJECTID -4ULL + +/* orhpan objectid for tracking unlinked/truncated files */ +#define BTRFS_ORPHAN_OBJECTID -5ULL + +/* does write ahead logging to speed up fsyncs */ +#define BTRFS_TREE_LOG_OBJECTID -6ULL +#define BTRFS_TREE_LOG_FIXUP_OBJECTID -7ULL + +/* for space balancing */ +#define BTRFS_TREE_RELOC_OBJECTID -8ULL +#define BTRFS_DATA_RELOC_TREE_OBJECTID -9ULL + +/* + * extent checksums all have this objectid + * this allows them to share the logging tree + * for fsyncs + */ +#define BTRFS_EXTENT_CSUM_OBJECTID -10ULL + +/* For storing free space cache */ +#define BTRFS_FREE_SPACE_OBJECTID -11ULL + +/* + * The inode number assigned to the special inode for storing + * free ino cache + */ +#define BTRFS_FREE_INO_OBJECTID -12ULL + +/* dummy objectid represents multiple objectids */ +#define BTRFS_MULTIPLE_OBJECTIDS -255ULL + +/* + * All files have objectids in this range. + */ +#define BTRFS_FIRST_FREE_OBJECTID 256ULL +#define BTRFS_LAST_FREE_OBJECTID -256ULL +#define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL + + +/* + * the device items go into the chunk tree. The key is in the form + * [ 1 BTRFS_DEV_ITEM_KEY device_id ] + */ +#define BTRFS_DEV_ITEMS_OBJECTID 1ULL + +#define BTRFS_BTREE_INODE_OBJECTID 1 + +#define BTRFS_EMPTY_SUBVOL_DIR_OBJECTID 2 + +#define BTRFS_DEV_REPLACE_DEVID 0ULL + +/* + * inode items have the data typically returned from stat and store other + * info about object characteristics. There is one for every file and dir in + * the FS + */ +#define BTRFS_INODE_ITEM_KEY 1 +#define BTRFS_INODE_REF_KEY 12 +#define BTRFS_INODE_EXTREF_KEY 13 +#define BTRFS_XATTR_ITEM_KEY 24 +#define BTRFS_ORPHAN_ITEM_KEY 48 +/* reserve 2-15 close to the inode for later flexibility */ + +/* + * dir items are the name -> inode pointers in a directory. There is one + * for every name in a directory. + */ +#define BTRFS_DIR_LOG_ITEM_KEY 60 +#define BTRFS_DIR_LOG_INDEX_KEY 72 +#define BTRFS_DIR_ITEM_KEY 84 +#define BTRFS_DIR_INDEX_KEY 96 +/* + * extent data is for file data + */ +#define BTRFS_EXTENT_DATA_KEY 108 + +/* + * extent csums are stored in a separate tree and hold csums for + * an entire extent on disk. + */ +#define BTRFS_EXTENT_CSUM_KEY 128 + +/* + * root items point to tree roots. They are typically in the root + * tree used by the super block to find all the other trees + */ +#define BTRFS_ROOT_ITEM_KEY 132 + +/* + * root backrefs tie subvols and snapshots to the directory entries that + * reference them + */ +#define BTRFS_ROOT_BACKREF_KEY 144 + +/* + * root refs make a fast index for listing all of the snapshots and + * subvolumes referenced by a given root. They point directly to the + * directory item in the root that references the subvol + */ +#define BTRFS_ROOT_REF_KEY 156 + +/* + * extent items are in the extent map tree. These record which blocks + * are used, and how many references there are to each block + */ +#define BTRFS_EXTENT_ITEM_KEY 168 + +/* + * The same as the BTRFS_EXTENT_ITEM_KEY, except it's metadata we already know + * the length, so we save the level in key->offset instead of the length. + */ +#define BTRFS_METADATA_ITEM_KEY 169 + +#define BTRFS_TREE_BLOCK_REF_KEY 176 + +#define BTRFS_EXTENT_DATA_REF_KEY 178 + +#define BTRFS_EXTENT_REF_V0_KEY 180 + +#define BTRFS_SHARED_BLOCK_REF_KEY 182 + +#define BTRFS_SHARED_DATA_REF_KEY 184 + +/* + * block groups give us hints into the extent allocation trees. Which + * blocks are free etc etc + */ +#define BTRFS_BLOCK_GROUP_ITEM_KEY 192 + +/* + * Every block group is represented in the free space tree by a free space info + * item, which stores some accounting information. It is keyed on + * (block_group_start, FREE_SPACE_INFO, block_group_length). + */ +#define BTRFS_FREE_SPACE_INFO_KEY 198 + +/* + * A free space extent tracks an extent of space that is free in a block group. + * It is keyed on (start, FREE_SPACE_EXTENT, length). + */ +#define BTRFS_FREE_SPACE_EXTENT_KEY 199 + +/* + * When a block group becomes very fragmented, we convert it to use bitmaps + * instead of extents. A free space bitmap is keyed on + * (start, FREE_SPACE_BITMAP, length); the corresponding item is a bitmap with + * (length / sectorsize) bits. + */ +#define BTRFS_FREE_SPACE_BITMAP_KEY 200 + +#define BTRFS_DEV_EXTENT_KEY 204 +#define BTRFS_DEV_ITEM_KEY 216 +#define BTRFS_CHUNK_ITEM_KEY 228 + +/* + * Records the overall state of the qgroups. + * There's only one instance of this key present, + * (0, BTRFS_QGROUP_STATUS_KEY, 0) + */ +#define BTRFS_QGROUP_STATUS_KEY 240 +/* + * Records the currently used space of the qgroup. + * One key per qgroup, (0, BTRFS_QGROUP_INFO_KEY, qgroupid). + */ +#define BTRFS_QGROUP_INFO_KEY 242 +/* + * Contains the user configured limits for the qgroup. + * One key per qgroup, (0, BTRFS_QGROUP_LIMIT_KEY, qgroupid). + */ +#define BTRFS_QGROUP_LIMIT_KEY 244 +/* + * Records the child-parent relationship of qgroups. For + * each relation, 2 keys are present: + * (childid, BTRFS_QGROUP_RELATION_KEY, parentid) + * (parentid, BTRFS_QGROUP_RELATION_KEY, childid) + */ +#define BTRFS_QGROUP_RELATION_KEY 246 + +/* + * Obsolete name, see BTRFS_TEMPORARY_ITEM_KEY. + */ +#define BTRFS_BALANCE_ITEM_KEY 248 + +/* + * The key type for tree items that are stored persistently, but do not need to + * exist for extended period of time. The items can exist in any tree. + * + * [subtype, BTRFS_TEMPORARY_ITEM_KEY, data] + * + * Existing items: + * + * - balance status item + * (BTRFS_BALANCE_OBJECTID, BTRFS_TEMPORARY_ITEM_KEY, 0) + */ +#define BTRFS_TEMPORARY_ITEM_KEY 248 + +/* + * Obsolete name, see BTRFS_PERSISTENT_ITEM_KEY + */ +#define BTRFS_DEV_STATS_KEY 249 + +/* + * The key type for tree items that are stored persistently and usually exist + * for a long period, eg. filesystem lifetime. The item kinds can be status + * information, stats or preference values. The item can exist in any tree. + * + * [subtype, BTRFS_PERSISTENT_ITEM_KEY, data] + * + * Existing items: + * + * - device statistics, store IO stats in the device tree, one key for all + * stats + * (BTRFS_DEV_STATS_OBJECTID, BTRFS_DEV_STATS_KEY, 0) + */ +#define BTRFS_PERSISTENT_ITEM_KEY 249 + +/* + * Persistantly stores the device replace state in the device tree. + * The key is built like this: (0, BTRFS_DEV_REPLACE_KEY, 0). + */ +#define BTRFS_DEV_REPLACE_KEY 250 + +/* + * Stores items that allow to quickly map UUIDs to something else. + * These items are part of the filesystem UUID tree. + * The key is built like this: + * (UUID_upper_64_bits, BTRFS_UUID_KEY*, UUID_lower_64_bits). + */ +#if BTRFS_UUID_SIZE != 16 +#error "UUID items require BTRFS_UUID_SIZE == 16!" +#endif +#define BTRFS_UUID_KEY_SUBVOL 251 /* for UUIDs assigned to subvols */ +#define BTRFS_UUID_KEY_RECEIVED_SUBVOL 252 /* for UUIDs assigned to + * received subvols */ + +/* + * string items are for debugging. They just store a short string of + * data in the FS + */ +#define BTRFS_STRING_ITEM_KEY 253 + + + +/* 32 bytes in various csum fields */ +#define BTRFS_CSUM_SIZE 32 + +/* csum types */ +#define BTRFS_CSUM_TYPE_CRC32 0 + +/* + * flags definitions for directory entry item type + * + * Used by: + * struct btrfs_dir_item.type + * + * Values 0..7 must match common file type values in fs_types.h. + */ +#define BTRFS_FT_UNKNOWN 0 +#define BTRFS_FT_REG_FILE 1 +#define BTRFS_FT_DIR 2 +#define BTRFS_FT_CHRDEV 3 +#define BTRFS_FT_BLKDEV 4 +#define BTRFS_FT_FIFO 5 +#define BTRFS_FT_SOCK 6 +#define BTRFS_FT_SYMLINK 7 +#define BTRFS_FT_XATTR 8 +#define BTRFS_FT_MAX 9 + +/* + * The key defines the order in the tree, and so it also defines (optimal) + * block layout. + * + * objectid corresponds to the inode number. + * + * type tells us things about the object, and is a kind of stream selector. + * so for a given inode, keys with type of 1 might refer to the inode data, + * type of 2 may point to file data in the btree and type == 3 may point to + * extents. + * + * offset is the starting byte offset for this key in the stream. + * + * btrfs_disk_key is in disk byte order. struct btrfs_key is always + * in cpu native order. Otherwise they are identical and their sizes + * should be the same (ie both packed) + */ +struct btrfs_disk_key { + __le64 objectid; + __u8 type; + __le64 offset; +} __attribute__ ((__packed__)); + +struct btrfs_key { + __u64 objectid; + __u8 type; + __u64 offset; +} __attribute__ ((__packed__)); + +struct btrfs_dev_item { + /* the internal btrfs device id */ + __le64 devid; + + /* size of the device */ + __le64 total_bytes; + + /* bytes used */ + __le64 bytes_used; + + /* optimal io alignment for this device */ + __le32 io_align; + + /* optimal io width for this device */ + __le32 io_width; + + /* minimal io size for this device */ + __le32 sector_size; + + /* type and info about this device */ + __le64 type; + + /* expected generation for this device */ + __le64 generation; + + /* + * starting byte of this partition on the device, + * to allow for stripe alignment in the future + */ + __le64 start_offset; + + /* grouping information for allocation decisions */ + __le32 dev_group; + + /* seek speed 0-100 where 100 is fastest */ + __u8 seek_speed; + + /* bandwidth 0-100 where 100 is fastest */ + __u8 bandwidth; + + /* btrfs generated uuid for this device */ + __u8 uuid[BTRFS_UUID_SIZE]; + + /* uuid of FS who owns this device */ + __u8 fsid[BTRFS_UUID_SIZE]; +} __attribute__ ((__packed__)); + +struct btrfs_stripe { + __le64 devid; + __le64 offset; + __u8 dev_uuid[BTRFS_UUID_SIZE]; +} __attribute__ ((__packed__)); + +struct btrfs_chunk { + /* size of this chunk in bytes */ + __le64 length; + + /* objectid of the root referencing this chunk */ + __le64 owner; + + __le64 stripe_len; + __le64 type; + + /* optimal io alignment for this chunk */ + __le32 io_align; + + /* optimal io width for this chunk */ + __le32 io_width; + + /* minimal io size for this chunk */ + __le32 sector_size; + + /* 2^16 stripes is quite a lot, a second limit is the size of a single + * item in the btree + */ + __le16 num_stripes; + + /* sub stripes only matter for raid10 */ + __le16 sub_stripes; + struct btrfs_stripe stripe; + /* additional stripes go here */ +} __attribute__ ((__packed__)); + +#define BTRFS_FREE_SPACE_EXTENT 1 +#define BTRFS_FREE_SPACE_BITMAP 2 + +struct btrfs_free_space_entry { + __le64 offset; + __le64 bytes; + __u8 type; +} __attribute__ ((__packed__)); + +struct btrfs_free_space_header { + struct btrfs_disk_key location; + __le64 generation; + __le64 num_entries; + __le64 num_bitmaps; +} __attribute__ ((__packed__)); + +#define BTRFS_HEADER_FLAG_WRITTEN (1ULL << 0) +#define BTRFS_HEADER_FLAG_RELOC (1ULL << 1) + +/* Super block flags */ +/* Errors detected */ +#define BTRFS_SUPER_FLAG_ERROR (1ULL << 2) + +#define BTRFS_SUPER_FLAG_SEEDING (1ULL << 32) +#define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33) +#define BTRFS_SUPER_FLAG_METADUMP_V2 (1ULL << 34) +#define BTRFS_SUPER_FLAG_CHANGING_FSID (1ULL << 35) +#define BTRFS_SUPER_FLAG_CHANGING_FSID_V2 (1ULL << 36) + + +/* + * items in the extent btree are used to record the objectid of the + * owner of the block and the number of references + */ + +struct btrfs_extent_item { + __le64 refs; + __le64 generation; + __le64 flags; +} __attribute__ ((__packed__)); + +struct btrfs_extent_item_v0 { + __le32 refs; +} __attribute__ ((__packed__)); + + +#define BTRFS_EXTENT_FLAG_DATA (1ULL << 0) +#define BTRFS_EXTENT_FLAG_TREE_BLOCK (1ULL << 1) + +/* following flags only apply to tree blocks */ + +/* use full backrefs for extent pointers in the block */ +#define BTRFS_BLOCK_FLAG_FULL_BACKREF (1ULL << 8) + +/* + * this flag is only used internally by scrub and may be changed at any time + * it is only declared here to avoid collisions + */ +#define BTRFS_EXTENT_FLAG_SUPER (1ULL << 48) + +struct btrfs_tree_block_info { + struct btrfs_disk_key key; + __u8 level; +} __attribute__ ((__packed__)); + +struct btrfs_extent_data_ref { + __le64 root; + __le64 objectid; + __le64 offset; + __le32 count; +} __attribute__ ((__packed__)); + +struct btrfs_shared_data_ref { + __le32 count; +} __attribute__ ((__packed__)); + +struct btrfs_extent_inline_ref { + __u8 type; + __le64 offset; +} __attribute__ ((__packed__)); + +/* old style backrefs item */ +struct btrfs_extent_ref_v0 { + __le64 root; + __le64 generation; + __le64 objectid; + __le32 count; +} __attribute__ ((__packed__)); + + +/* dev extents record free space on individual devices. The owner + * field points back to the chunk allocation mapping tree that allocated + * the extent. The chunk tree uuid field is a way to double check the owner + */ +struct btrfs_dev_extent { + __le64 chunk_tree; + __le64 chunk_objectid; + __le64 chunk_offset; + __le64 length; + __u8 chunk_tree_uuid[BTRFS_UUID_SIZE]; +} __attribute__ ((__packed__)); + +struct btrfs_inode_ref { + __le64 index; + __le16 name_len; + /* name goes here */ +} __attribute__ ((__packed__)); + +struct btrfs_inode_extref { + __le64 parent_objectid; + __le64 index; + __le16 name_len; + __u8 name[0]; + /* name goes here */ +} __attribute__ ((__packed__)); + +struct btrfs_timespec { + __le64 sec; + __le32 nsec; +} __attribute__ ((__packed__)); + +struct btrfs_inode_item { + /* nfs style generation number */ + __le64 generation; + /* transid that last touched this inode */ + __le64 transid; + __le64 size; + __le64 nbytes; + __le64 block_group; + __le32 nlink; + __le32 uid; + __le32 gid; + __le32 mode; + __le64 rdev; + __le64 flags; + + /* modification sequence number for NFS */ + __le64 sequence; + + /* + * a little future expansion, for more than this we can + * just grow the inode item and version it + */ + __le64 reserved[4]; + struct btrfs_timespec atime; + struct btrfs_timespec ctime; + struct btrfs_timespec mtime; + struct btrfs_timespec otime; +} __attribute__ ((__packed__)); + +struct btrfs_dir_log_item { + __le64 end; +} __attribute__ ((__packed__)); + +struct btrfs_dir_item { + struct btrfs_disk_key location; + __le64 transid; + __le16 data_len; + __le16 name_len; + __u8 type; +} __attribute__ ((__packed__)); + +#define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0) + +/* + * Internal in-memory flag that a subvolume has been marked for deletion but + * still visible as a directory + */ +#define BTRFS_ROOT_SUBVOL_DEAD (1ULL << 48) + +struct btrfs_root_item { + struct btrfs_inode_item inode; + __le64 generation; + __le64 root_dirid; + __le64 bytenr; + __le64 byte_limit; + __le64 bytes_used; + __le64 last_snapshot; + __le64 flags; + __le32 refs; + struct btrfs_disk_key drop_progress; + __u8 drop_level; + __u8 level; + + /* + * The following fields appear after subvol_uuids+subvol_times + * were introduced. + */ + + /* + * This generation number is used to test if the new fields are valid + * and up to date while reading the root item. Every time the root item + * is written out, the "generation" field is copied into this field. If + * anyone ever mounted the fs with an older kernel, we will have + * mismatching generation values here and thus must invalidate the + * new fields. See btrfs_update_root and btrfs_find_last_root for + * details. + * the offset of generation_v2 is also used as the start for the memset + * when invalidating the fields. + */ + __le64 generation_v2; + __u8 uuid[BTRFS_UUID_SIZE]; + __u8 parent_uuid[BTRFS_UUID_SIZE]; + __u8 received_uuid[BTRFS_UUID_SIZE]; + __le64 ctransid; /* updated when an inode changes */ + __le64 otransid; /* trans when created */ + __le64 stransid; /* trans when sent. non-zero for received subvol */ + __le64 rtransid; /* trans when received. non-zero for received subvol */ + struct btrfs_timespec ctime; + struct btrfs_timespec otime; + struct btrfs_timespec stime; + struct btrfs_timespec rtime; + __le64 reserved[8]; /* for future */ +} __attribute__ ((__packed__)); + +/* + * this is used for both forward and backward root refs + */ +struct btrfs_root_ref { + __le64 dirid; + __le64 sequence; + __le16 name_len; +} __attribute__ ((__packed__)); + +struct btrfs_disk_balance_args { + /* + * profiles to operate on, single is denoted by + * BTRFS_AVAIL_ALLOC_BIT_SINGLE + */ + __le64 profiles; + + /* + * usage filter + * BTRFS_BALANCE_ARGS_USAGE with a single value means '0..N' + * BTRFS_BALANCE_ARGS_USAGE_RANGE - range syntax, min..max + */ + union { + __le64 usage; + struct { + __le32 usage_min; + __le32 usage_max; + }; + }; + + /* devid filter */ + __le64 devid; + + /* devid subset filter [pstart..pend) */ + __le64 pstart; + __le64 pend; + + /* btrfs virtual address space subset filter [vstart..vend) */ + __le64 vstart; + __le64 vend; + + /* + * profile to convert to, single is denoted by + * BTRFS_AVAIL_ALLOC_BIT_SINGLE + */ + __le64 target; + + /* BTRFS_BALANCE_ARGS_* */ + __le64 flags; + + /* + * BTRFS_BALANCE_ARGS_LIMIT with value 'limit' + * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum + * and maximum + */ + union { + __le64 limit; + struct { + __le32 limit_min; + __le32 limit_max; + }; + }; + + /* + * Process chunks that cross stripes_min..stripes_max devices, + * BTRFS_BALANCE_ARGS_STRIPES_RANGE + */ + __le32 stripes_min; + __le32 stripes_max; + + __le64 unused[6]; +} __attribute__ ((__packed__)); + +/* + * store balance parameters to disk so that balance can be properly + * resumed after crash or unmount + */ +struct btrfs_balance_item { + /* BTRFS_BALANCE_* */ + __le64 flags; + + struct btrfs_disk_balance_args data; + struct btrfs_disk_balance_args meta; + struct btrfs_disk_balance_args sys; + + __le64 unused[4]; +} __attribute__ ((__packed__)); + +#define BTRFS_FILE_EXTENT_INLINE 0 +#define BTRFS_FILE_EXTENT_REG 1 +#define BTRFS_FILE_EXTENT_PREALLOC 2 +#define BTRFS_FILE_EXTENT_TYPES 2 + +struct btrfs_file_extent_item { + /* + * transaction id that created this extent + */ + __le64 generation; + /* + * max number of bytes to hold this extent in ram + * when we split a compressed extent we can't know how big + * each of the resulting pieces will be. So, this is + * an upper limit on the size of the extent in ram instead of + * an exact limit. + */ + __le64 ram_bytes; + + /* + * 32 bits for the various ways we might encode the data, + * including compression and encryption. If any of these + * are set to something a given disk format doesn't understand + * it is treated like an incompat flag for reading and writing, + * but not for stat. + */ + __u8 compression; + __u8 encryption; + __le16 other_encoding; /* spare for later use */ + + /* are we inline data or a real extent? */ + __u8 type; + + /* + * disk space consumed by the extent, checksum blocks are included + * in these numbers + * + * At this offset in the structure, the inline extent data start. + */ + __le64 disk_bytenr; + __le64 disk_num_bytes; + /* + * the logical offset in file blocks (no csums) + * this extent record is for. This allows a file extent to point + * into the middle of an existing extent on disk, sharing it + * between two snapshots (useful if some bytes in the middle of the + * extent have changed + */ + __le64 offset; + /* + * the logical number of file blocks (no csums included). This + * always reflects the size uncompressed and without encoding. + */ + __le64 num_bytes; + +} __attribute__ ((__packed__)); + +struct btrfs_csum_item { + __u8 csum; +} __attribute__ ((__packed__)); + +struct btrfs_dev_stats_item { + /* + * grow this item struct at the end for future enhancements and keep + * the existing values unchanged + */ + __le64 values[BTRFS_DEV_STAT_VALUES_MAX]; +} __attribute__ ((__packed__)); + +#define BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_ALWAYS 0 +#define BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_AVOID 1 +#define BTRFS_DEV_REPLACE_ITEM_STATE_NEVER_STARTED 0 +#define BTRFS_DEV_REPLACE_ITEM_STATE_STARTED 1 +#define BTRFS_DEV_REPLACE_ITEM_STATE_SUSPENDED 2 +#define BTRFS_DEV_REPLACE_ITEM_STATE_FINISHED 3 +#define BTRFS_DEV_REPLACE_ITEM_STATE_CANCELED 4 + +struct btrfs_dev_replace_item { + /* + * grow this item struct at the end for future enhancements and keep + * the existing values unchanged + */ + __le64 src_devid; + __le64 cursor_left; + __le64 cursor_right; + __le64 cont_reading_from_srcdev_mode; + + __le64 replace_state; + __le64 time_started; + __le64 time_stopped; + __le64 num_write_errors; + __le64 num_uncorrectable_read_errors; +} __attribute__ ((__packed__)); + +/* different types of block groups (and chunks) */ +#define BTRFS_BLOCK_GROUP_DATA (1ULL << 0) +#define BTRFS_BLOCK_GROUP_SYSTEM (1ULL << 1) +#define BTRFS_BLOCK_GROUP_METADATA (1ULL << 2) +#define BTRFS_BLOCK_GROUP_RAID0 (1ULL << 3) +#define BTRFS_BLOCK_GROUP_RAID1 (1ULL << 4) +#define BTRFS_BLOCK_GROUP_DUP (1ULL << 5) +#define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6) +#define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7) +#define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8) +#define BTRFS_BLOCK_GROUP_RESERVED (BTRFS_AVAIL_ALLOC_BIT_SINGLE | \ + BTRFS_SPACE_INFO_GLOBAL_RSV) + +enum btrfs_raid_types { + BTRFS_RAID_RAID10, + BTRFS_RAID_RAID1, + BTRFS_RAID_DUP, + BTRFS_RAID_RAID0, + BTRFS_RAID_SINGLE, + BTRFS_RAID_RAID5, + BTRFS_RAID_RAID6, + BTRFS_NR_RAID_TYPES +}; + +#define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | \ + BTRFS_BLOCK_GROUP_SYSTEM | \ + BTRFS_BLOCK_GROUP_METADATA) + +#define BTRFS_BLOCK_GROUP_PROFILE_MASK (BTRFS_BLOCK_GROUP_RAID0 | \ + BTRFS_BLOCK_GROUP_RAID1 | \ + BTRFS_BLOCK_GROUP_RAID5 | \ + BTRFS_BLOCK_GROUP_RAID6 | \ + BTRFS_BLOCK_GROUP_DUP | \ + BTRFS_BLOCK_GROUP_RAID10) +#define BTRFS_BLOCK_GROUP_RAID56_MASK (BTRFS_BLOCK_GROUP_RAID5 | \ + BTRFS_BLOCK_GROUP_RAID6) + +/* + * We need a bit for restriper to be able to tell when chunks of type + * SINGLE are available. This "extended" profile format is used in + * fs_info->avail_*_alloc_bits (in-memory) and balance item fields + * (on-disk). The corresponding on-disk bit in chunk.type is reserved + * to avoid remappings between two formats in future. + */ +#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48) + +/* + * A fake block group type that is used to communicate global block reserve + * size to userspace via the SPACE_INFO ioctl. + */ +#define BTRFS_SPACE_INFO_GLOBAL_RSV (1ULL << 49) + +#define BTRFS_EXTENDED_PROFILE_MASK (BTRFS_BLOCK_GROUP_PROFILE_MASK | \ + BTRFS_AVAIL_ALLOC_BIT_SINGLE) + +static inline __u64 chunk_to_extended(__u64 flags) +{ + if ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0) + flags |= BTRFS_AVAIL_ALLOC_BIT_SINGLE; + + return flags; +} +static inline __u64 extended_to_chunk(__u64 flags) +{ + return flags & ~BTRFS_AVAIL_ALLOC_BIT_SINGLE; +} + +struct btrfs_block_group_item { + __le64 used; + __le64 chunk_objectid; + __le64 flags; +} __attribute__ ((__packed__)); + +struct btrfs_free_space_info { + __le32 extent_count; + __le32 flags; +} __attribute__ ((__packed__)); + +#define BTRFS_FREE_SPACE_USING_BITMAPS (1ULL << 0) + +#define BTRFS_QGROUP_LEVEL_SHIFT 48 +static inline __u64 btrfs_qgroup_level(__u64 qgroupid) +{ + return qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT; +} + +/* + * is subvolume quota turned on? + */ +#define BTRFS_QGROUP_STATUS_FLAG_ON (1ULL << 0) +/* + * RESCAN is set during the initialization phase + */ +#define BTRFS_QGROUP_STATUS_FLAG_RESCAN (1ULL << 1) +/* + * Some qgroup entries are known to be out of date, + * either because the configuration has changed in a way that + * makes a rescan necessary, or because the fs has been mounted + * with a non-qgroup-aware version. + * Turning qouta off and on again makes it inconsistent, too. + */ +#define BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT (1ULL << 2) + +#define BTRFS_QGROUP_STATUS_VERSION 1 + +struct btrfs_qgroup_status_item { + __le64 version; + /* + * the generation is updated during every commit. As older + * versions of btrfs are not aware of qgroups, it will be + * possible to detect inconsistencies by checking the + * generation on mount time + */ + __le64 generation; + + /* flag definitions see above */ + __le64 flags; + + /* + * only used during scanning to record the progress + * of the scan. It contains a logical address + */ + __le64 rescan; +} __attribute__ ((__packed__)); + +struct btrfs_qgroup_info_item { + __le64 generation; + __le64 rfer; + __le64 rfer_cmpr; + __le64 excl; + __le64 excl_cmpr; +} __attribute__ ((__packed__)); + +struct btrfs_qgroup_limit_item { + /* + * only updated when any of the other values change + */ + __le64 flags; + __le64 max_rfer; + __le64 max_excl; + __le64 rsv_rfer; + __le64 rsv_excl; +} __attribute__ ((__packed__)); + +#endif /* _BTRFS_CTREE_H_ */ diff --git a/src/basic/linux/can/vxcan.h b/src/basic/linux/can/vxcan.h new file mode 100644 index 00000000..066812d1 --- /dev/null +++ b/src/basic/linux/can/vxcan.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_CAN_VXCAN_H +#define _UAPI_CAN_VXCAN_H + +enum { + VXCAN_INFO_UNSPEC, + VXCAN_INFO_PEER, + + __VXCAN_INFO_MAX +#define VXCAN_INFO_MAX (__VXCAN_INFO_MAX - 1) +}; + +#endif diff --git a/src/basic/linux/fib_rules.h b/src/basic/linux/fib_rules.h new file mode 100644 index 00000000..232df14e --- /dev/null +++ b/src/basic/linux/fib_rules.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_FIB_RULES_H +#define __LINUX_FIB_RULES_H + +#include +#include + +/* rule is permanent, and cannot be deleted */ +#define FIB_RULE_PERMANENT 0x00000001 +#define FIB_RULE_INVERT 0x00000002 +#define FIB_RULE_UNRESOLVED 0x00000004 +#define FIB_RULE_IIF_DETACHED 0x00000008 +#define FIB_RULE_DEV_DETACHED FIB_RULE_IIF_DETACHED +#define FIB_RULE_OIF_DETACHED 0x00000010 + +/* try to find source address in routing lookups */ +#define FIB_RULE_FIND_SADDR 0x00010000 + +struct fib_rule_hdr { + __u8 family; + __u8 dst_len; + __u8 src_len; + __u8 tos; + + __u8 table; + __u8 res1; /* reserved */ + __u8 res2; /* reserved */ + __u8 action; + + __u32 flags; +}; + +struct fib_rule_uid_range { + __u32 start; + __u32 end; +}; + +struct fib_rule_port_range { + __u16 start; + __u16 end; +}; + +enum { + FRA_UNSPEC, + FRA_DST, /* destination address */ + FRA_SRC, /* source address */ + FRA_IIFNAME, /* interface name */ +#define FRA_IFNAME FRA_IIFNAME + FRA_GOTO, /* target to jump to (FR_ACT_GOTO) */ + FRA_UNUSED2, + FRA_PRIORITY, /* priority/preference */ + FRA_UNUSED3, + FRA_UNUSED4, + FRA_UNUSED5, + FRA_FWMARK, /* mark */ + FRA_FLOW, /* flow/class id */ + FRA_TUN_ID, + FRA_SUPPRESS_IFGROUP, + FRA_SUPPRESS_PREFIXLEN, + FRA_TABLE, /* Extended table id */ + FRA_FWMASK, /* mask for netfilter mark */ + FRA_OIFNAME, + FRA_PAD, + FRA_L3MDEV, /* iif or oif is l3mdev goto its table */ + FRA_UID_RANGE, /* UID range */ + FRA_PROTOCOL, /* Originator of the rule */ + FRA_IP_PROTO, /* ip proto */ + FRA_SPORT_RANGE, /* sport */ + FRA_DPORT_RANGE, /* dport */ + __FRA_MAX +}; + +#define FRA_MAX (__FRA_MAX - 1) + +enum { + FR_ACT_UNSPEC, + FR_ACT_TO_TBL, /* Pass to fixed table */ + FR_ACT_GOTO, /* Jump to another rule */ + FR_ACT_NOP, /* No operation */ + FR_ACT_RES3, + FR_ACT_RES4, + FR_ACT_BLACKHOLE, /* Drop without notification */ + FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ + FR_ACT_PROHIBIT, /* Drop with EACCES */ + __FR_ACT_MAX, +}; + +#define FR_ACT_MAX (__FR_ACT_MAX - 1) + +#endif diff --git a/src/basic/linux/fou.h b/src/basic/linux/fou.h new file mode 100644 index 00000000..87c2c9f0 --- /dev/null +++ b/src/basic/linux/fou.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* fou.h - FOU Interface */ + +#ifndef _UAPI_LINUX_FOU_H +#define _UAPI_LINUX_FOU_H + +/* NETLINK_GENERIC related info + */ +#define FOU_GENL_NAME "fou" +#define FOU_GENL_VERSION 0x1 + +enum { + FOU_ATTR_UNSPEC, + FOU_ATTR_PORT, /* u16 */ + FOU_ATTR_AF, /* u8 */ + FOU_ATTR_IPPROTO, /* u8 */ + FOU_ATTR_TYPE, /* u8 */ + FOU_ATTR_REMCSUM_NOPARTIAL, /* flag */ + FOU_ATTR_LOCAL_V4, /* u32 */ + FOU_ATTR_LOCAL_V6, /* in6_addr */ + FOU_ATTR_PEER_V4, /* u32 */ + FOU_ATTR_PEER_V6, /* in6_addr */ + FOU_ATTR_PEER_PORT, /* u16 */ + FOU_ATTR_IFINDEX, /* s32 */ + + __FOU_ATTR_MAX, +}; + +#define FOU_ATTR_MAX (__FOU_ATTR_MAX - 1) + +enum { + FOU_CMD_UNSPEC, + FOU_CMD_ADD, + FOU_CMD_DEL, + FOU_CMD_GET, + + __FOU_CMD_MAX, +}; + +enum { + FOU_ENCAP_UNSPEC, + FOU_ENCAP_DIRECT, + FOU_ENCAP_GUE, +}; + +#define FOU_CMD_MAX (__FOU_CMD_MAX - 1) + +#endif /* _UAPI_LINUX_FOU_H */ diff --git a/src/basic/linux/if.h b/src/basic/linux/if.h new file mode 100644 index 00000000..4c6f030a --- /dev/null +++ b/src/basic/linux/if.h @@ -0,0 +1,294 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the INET interface module. + * + * Version: @(#)if.h 1.0.2 04/18/93 + * + * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988 + * Ross Biro + * Fred N. van Kempen, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _LINUX_IF_H +#define _LINUX_IF_H + +#include /* for compatibility with glibc */ +#include /* for "__kernel_caddr_t" et al */ +#include /* for "struct sockaddr" et al */ + +#ifndef __KERNEL__ +#include /* for struct sockaddr. */ +#endif + +#if __UAPI_DEF_IF_IFNAMSIZ +#define IFNAMSIZ 16 +#endif /* __UAPI_DEF_IF_IFNAMSIZ */ +#define IFALIASZ 256 +#include + +/* For glibc compatibility. An empty enum does not compile. */ +#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 || \ + __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 +/** + * enum net_device_flags - &struct net_device flags + * + * These are the &struct net_device flags, they can be set by drivers, the + * kernel and some can be triggered by userspace. Userspace can query and + * set these flags using userspace utilities but there is also a sysfs + * entry available for all dev flags which can be queried and set. These flags + * are shared for all types of net_devices. The sysfs entries are available + * via /sys/class/net//flags. Flags which can be toggled through sysfs + * are annotated below, note that only a few flags can be toggled and some + * other flags are always preserved from the original net_device flags + * even if you try to set them via sysfs. Flags which are always preserved + * are kept under the flag grouping @IFF_VOLATILE. Flags which are volatile + * are annotated below as such. + * + * You should have a pretty good reason to be extending these flags. + * + * @IFF_UP: interface is up. Can be toggled through sysfs. + * @IFF_BROADCAST: broadcast address valid. Volatile. + * @IFF_DEBUG: turn on debugging. Can be toggled through sysfs. + * @IFF_LOOPBACK: is a loopback net. Volatile. + * @IFF_POINTOPOINT: interface is has p-p link. Volatile. + * @IFF_NOTRAILERS: avoid use of trailers. Can be toggled through sysfs. + * Volatile. + * @IFF_RUNNING: interface RFC2863 OPER_UP. Volatile. + * @IFF_NOARP: no ARP protocol. Can be toggled through sysfs. Volatile. + * @IFF_PROMISC: receive all packets. Can be toggled through sysfs. + * @IFF_ALLMULTI: receive all multicast packets. Can be toggled through + * sysfs. + * @IFF_MASTER: master of a load balancer. Volatile. + * @IFF_SLAVE: slave of a load balancer. Volatile. + * @IFF_MULTICAST: Supports multicast. Can be toggled through sysfs. + * @IFF_PORTSEL: can set media type. Can be toggled through sysfs. + * @IFF_AUTOMEDIA: auto media select active. Can be toggled through sysfs. + * @IFF_DYNAMIC: dialup device with changing addresses. Can be toggled + * through sysfs. + * @IFF_LOWER_UP: driver signals L1 up. Volatile. + * @IFF_DORMANT: driver signals dormant. Volatile. + * @IFF_ECHO: echo sent packets. Volatile. + */ +enum net_device_flags { +/* for compatibility with glibc net/if.h */ +#if __UAPI_DEF_IF_NET_DEVICE_FLAGS + IFF_UP = 1<<0, /* sysfs */ + IFF_BROADCAST = 1<<1, /* volatile */ + IFF_DEBUG = 1<<2, /* sysfs */ + IFF_LOOPBACK = 1<<3, /* volatile */ + IFF_POINTOPOINT = 1<<4, /* volatile */ + IFF_NOTRAILERS = 1<<5, /* sysfs */ + IFF_RUNNING = 1<<6, /* volatile */ + IFF_NOARP = 1<<7, /* sysfs */ + IFF_PROMISC = 1<<8, /* sysfs */ + IFF_ALLMULTI = 1<<9, /* sysfs */ + IFF_MASTER = 1<<10, /* volatile */ + IFF_SLAVE = 1<<11, /* volatile */ + IFF_MULTICAST = 1<<12, /* sysfs */ + IFF_PORTSEL = 1<<13, /* sysfs */ + IFF_AUTOMEDIA = 1<<14, /* sysfs */ + IFF_DYNAMIC = 1<<15, /* sysfs */ +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */ +#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO + IFF_LOWER_UP = 1<<16, /* volatile */ + IFF_DORMANT = 1<<17, /* volatile */ + IFF_ECHO = 1<<18, /* volatile */ +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ +}; +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 || __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 */ + +/* for compatibility with glibc net/if.h */ +#if __UAPI_DEF_IF_NET_DEVICE_FLAGS +#define IFF_UP IFF_UP +#define IFF_BROADCAST IFF_BROADCAST +#define IFF_DEBUG IFF_DEBUG +#define IFF_LOOPBACK IFF_LOOPBACK +#define IFF_POINTOPOINT IFF_POINTOPOINT +#define IFF_NOTRAILERS IFF_NOTRAILERS +#define IFF_RUNNING IFF_RUNNING +#define IFF_NOARP IFF_NOARP +#define IFF_PROMISC IFF_PROMISC +#define IFF_ALLMULTI IFF_ALLMULTI +#define IFF_MASTER IFF_MASTER +#define IFF_SLAVE IFF_SLAVE +#define IFF_MULTICAST IFF_MULTICAST +#define IFF_PORTSEL IFF_PORTSEL +#define IFF_AUTOMEDIA IFF_AUTOMEDIA +#define IFF_DYNAMIC IFF_DYNAMIC +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */ + +#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO +#define IFF_LOWER_UP IFF_LOWER_UP +#define IFF_DORMANT IFF_DORMANT +#define IFF_ECHO IFF_ECHO +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ + +#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\ + IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) + +#define IF_GET_IFACE 0x0001 /* for querying only */ +#define IF_GET_PROTO 0x0002 + +/* For definitions see hdlc.h */ +#define IF_IFACE_V35 0x1000 /* V.35 serial interface */ +#define IF_IFACE_V24 0x1001 /* V.24 serial interface */ +#define IF_IFACE_X21 0x1002 /* X.21 serial interface */ +#define IF_IFACE_T1 0x1003 /* T1 telco serial interface */ +#define IF_IFACE_E1 0x1004 /* E1 telco serial interface */ +#define IF_IFACE_SYNC_SERIAL 0x1005 /* can't be set by software */ +#define IF_IFACE_X21D 0x1006 /* X.21 Dual Clocking (FarSite) */ + +/* For definitions see hdlc.h */ +#define IF_PROTO_HDLC 0x2000 /* raw HDLC protocol */ +#define IF_PROTO_PPP 0x2001 /* PPP protocol */ +#define IF_PROTO_CISCO 0x2002 /* Cisco HDLC protocol */ +#define IF_PROTO_FR 0x2003 /* Frame Relay protocol */ +#define IF_PROTO_FR_ADD_PVC 0x2004 /* Create FR PVC */ +#define IF_PROTO_FR_DEL_PVC 0x2005 /* Delete FR PVC */ +#define IF_PROTO_X25 0x2006 /* X.25 */ +#define IF_PROTO_HDLC_ETH 0x2007 /* raw HDLC, Ethernet emulation */ +#define IF_PROTO_FR_ADD_ETH_PVC 0x2008 /* Create FR Ethernet-bridged PVC */ +#define IF_PROTO_FR_DEL_ETH_PVC 0x2009 /* Delete FR Ethernet-bridged PVC */ +#define IF_PROTO_FR_PVC 0x200A /* for reading PVC status */ +#define IF_PROTO_FR_ETH_PVC 0x200B +#define IF_PROTO_RAW 0x200C /* RAW Socket */ + +/* RFC 2863 operational status */ +enum { + IF_OPER_UNKNOWN, + IF_OPER_NOTPRESENT, + IF_OPER_DOWN, + IF_OPER_LOWERLAYERDOWN, + IF_OPER_TESTING, + IF_OPER_DORMANT, + IF_OPER_UP, +}; + +/* link modes */ +enum { + IF_LINK_MODE_DEFAULT, + IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */ +}; + +/* + * Device mapping structure. I'd just gone off and designed a + * beautiful scheme using only loadable modules with arguments + * for driver options and along come the PCMCIA people 8) + * + * Ah well. The get() side of this is good for WDSETUP, and it'll + * be handy for debugging things. The set side is fine for now and + * being very small might be worth keeping for clean configuration. + */ + +/* for compatibility with glibc net/if.h */ +#if __UAPI_DEF_IF_IFMAP +struct ifmap { + unsigned long mem_start; + unsigned long mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + /* 3 bytes spare */ +}; +#endif /* __UAPI_DEF_IF_IFMAP */ + +struct if_settings { + unsigned int type; /* Type of physical device or protocol */ + unsigned int size; /* Size of the data allocated by the caller */ + union { + /* {atm/eth/dsl}_settings anyone ? */ + raw_hdlc_proto *raw_hdlc; + cisco_proto *cisco; + fr_proto *fr; + fr_proto_pvc *fr_pvc; + fr_proto_pvc_info *fr_pvc_info; + + /* interface settings */ + sync_serial_settings *sync; + te1_settings *te1; + } ifs_ifsu; +}; + +/* + * Interface request structure used for socket + * ioctl's. All interface ioctl's must have parameter + * definitions which begin with ifr_name. The + * remainder may be interface specific. + */ + +/* for compatibility with glibc net/if.h */ +#if __UAPI_DEF_IF_IFREQ +struct ifreq { +#define IFHWADDRLEN 6 + union + { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct ifmap ifru_map; + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ + char ifru_newname[IFNAMSIZ]; + void * ifru_data; + struct if_settings ifru_settings; + } ifr_ifru; +}; +#endif /* __UAPI_DEF_IF_IFREQ */ + +#define ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_metric ifr_ifru.ifru_ivalue /* metric */ +#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +#define ifr_map ifr_ifru.ifru_map /* device map */ +#define ifr_slave ifr_ifru.ifru_slave /* slave device */ +#define ifr_data ifr_ifru.ifru_data /* for use by interface */ +#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ +#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */ +#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */ +#define ifr_newname ifr_ifru.ifru_newname /* New name */ +#define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/ + +/* + * Structure used in SIOCGIFCONF request. + * Used to retrieve interface configuration + * for machine (useful for programs which + * must know all networks accessible). + */ + +/* for compatibility with glibc net/if.h */ +#if __UAPI_DEF_IF_IFCONF +struct ifconf { + int ifc_len; /* size of buffer */ + union { + char *ifcu_buf; + struct ifreq *ifcu_req; + } ifc_ifcu; +}; +#endif /* __UAPI_DEF_IF_IFCONF */ + +#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ +#define ifc_req ifc_ifcu.ifcu_req /* array of structures */ + +#endif /* _LINUX_IF_H */ diff --git a/src/basic/linux/if_addr.h b/src/basic/linux/if_addr.h new file mode 100644 index 00000000..dfcf3ce0 --- /dev/null +++ b/src/basic/linux/if_addr.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_IF_ADDR_H +#define __LINUX_IF_ADDR_H + +#include +#include + +struct ifaddrmsg { + __u8 ifa_family; + __u8 ifa_prefixlen; /* The prefix length */ + __u8 ifa_flags; /* Flags */ + __u8 ifa_scope; /* Address scope */ + __u32 ifa_index; /* Link index */ +}; + +/* + * Important comment: + * IFA_ADDRESS is prefix address, rather than local interface address. + * It makes no difference for normally configured broadcast interfaces, + * but for point-to-point IFA_ADDRESS is DESTINATION address, + * local address is supplied in IFA_LOCAL attribute. + * + * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags. + * If present, the value from struct ifaddrmsg will be ignored. + */ +enum { + IFA_UNSPEC, + IFA_ADDRESS, + IFA_LOCAL, + IFA_LABEL, + IFA_BROADCAST, + IFA_ANYCAST, + IFA_CACHEINFO, + IFA_MULTICAST, + IFA_FLAGS, + IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */ + IFA_TARGET_NETNSID, + __IFA_MAX, +}; + +#define IFA_MAX (__IFA_MAX - 1) + +/* ifa_flags */ +#define IFA_F_SECONDARY 0x01 +#define IFA_F_TEMPORARY IFA_F_SECONDARY + +#define IFA_F_NODAD 0x02 +#define IFA_F_OPTIMISTIC 0x04 +#define IFA_F_DADFAILED 0x08 +#define IFA_F_HOMEADDRESS 0x10 +#define IFA_F_DEPRECATED 0x20 +#define IFA_F_TENTATIVE 0x40 +#define IFA_F_PERMANENT 0x80 +#define IFA_F_MANAGETEMPADDR 0x100 +#define IFA_F_NOPREFIXROUTE 0x200 +#define IFA_F_MCAUTOJOIN 0x400 +#define IFA_F_STABLE_PRIVACY 0x800 + +struct ifa_cacheinfo { + __u32 ifa_prefered; + __u32 ifa_valid; + __u32 cstamp; /* created timestamp, hundredths of seconds */ + __u32 tstamp; /* updated timestamp, hundredths of seconds */ +}; + +/* backwards compatibility for userspace */ +#ifndef __KERNEL__ +#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) +#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) +#endif + +#endif diff --git a/src/basic/linux/if_arp.h b/src/basic/linux/if_arp.h new file mode 100644 index 00000000..c3cc5a9e --- /dev/null +++ b/src/basic/linux/if_arp.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the ARP (RFC 826) protocol. + * + * Version: @(#)if_arp.h 1.0.1 04/16/93 + * + * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 + * Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source. + * Ross Biro + * Fred N. van Kempen, + * Florian La Roche, + * Jonathan Layes + * Arnaldo Carvalho de Melo ARPHRD_HWX25 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _UAPI_LINUX_IF_ARP_H +#define _UAPI_LINUX_IF_ARP_H + +#include + +/* ARP protocol HARDWARE identifiers. */ +#define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */ +#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ +#define ARPHRD_EETHER 2 /* Experimental Ethernet */ +#define ARPHRD_AX25 3 /* AX.25 Level 2 */ +#define ARPHRD_PRONET 4 /* PROnet token ring */ +#define ARPHRD_CHAOS 5 /* Chaosnet */ +#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */ +#define ARPHRD_ARCNET 7 /* ARCnet */ +#define ARPHRD_APPLETLK 8 /* APPLEtalk */ +#define ARPHRD_DLCI 15 /* Frame Relay DLCI */ +#define ARPHRD_ATM 19 /* ATM */ +#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id) */ +#define ARPHRD_IEEE1394 24 /* IEEE 1394 IPv4 - RFC 2734 */ +#define ARPHRD_EUI64 27 /* EUI-64 */ +#define ARPHRD_INFINIBAND 32 /* InfiniBand */ + +/* Dummy types for non ARP hardware */ +#define ARPHRD_SLIP 256 +#define ARPHRD_CSLIP 257 +#define ARPHRD_SLIP6 258 +#define ARPHRD_CSLIP6 259 +#define ARPHRD_RSRVD 260 /* Notional KISS type */ +#define ARPHRD_ADAPT 264 +#define ARPHRD_ROSE 270 +#define ARPHRD_X25 271 /* CCITT X.25 */ +#define ARPHRD_HWX25 272 /* Boards with X.25 in firmware */ +#define ARPHRD_CAN 280 /* Controller Area Network */ +#define ARPHRD_PPP 512 +#define ARPHRD_CISCO 513 /* Cisco HDLC */ +#define ARPHRD_HDLC ARPHRD_CISCO +#define ARPHRD_LAPB 516 /* LAPB */ +#define ARPHRD_DDCMP 517 /* Digital's DDCMP protocol */ +#define ARPHRD_RAWHDLC 518 /* Raw HDLC */ +#define ARPHRD_RAWIP 519 /* Raw IP */ + +#define ARPHRD_TUNNEL 768 /* IPIP tunnel */ +#define ARPHRD_TUNNEL6 769 /* IP6IP6 tunnel */ +#define ARPHRD_FRAD 770 /* Frame Relay Access Device */ +#define ARPHRD_SKIP 771 /* SKIP vif */ +#define ARPHRD_LOOPBACK 772 /* Loopback device */ +#define ARPHRD_LOCALTLK 773 /* Localtalk device */ +#define ARPHRD_FDDI 774 /* Fiber Distributed Data Interface */ +#define ARPHRD_BIF 775 /* AP1000 BIF */ +#define ARPHRD_SIT 776 /* sit0 device - IPv6-in-IPv4 */ +#define ARPHRD_IPDDP 777 /* IP over DDP tunneller */ +#define ARPHRD_IPGRE 778 /* GRE over IP */ +#define ARPHRD_PIMREG 779 /* PIMSM register interface */ +#define ARPHRD_HIPPI 780 /* High Performance Parallel Interface */ +#define ARPHRD_ASH 781 /* Nexus 64Mbps Ash */ +#define ARPHRD_ECONET 782 /* Acorn Econet */ +#define ARPHRD_IRDA 783 /* Linux-IrDA */ +/* ARP works differently on different FC media .. so */ +#define ARPHRD_FCPP 784 /* Point to point fibrechannel */ +#define ARPHRD_FCAL 785 /* Fibrechannel arbitrated loop */ +#define ARPHRD_FCPL 786 /* Fibrechannel public loop */ +#define ARPHRD_FCFABRIC 787 /* Fibrechannel fabric */ + /* 787->799 reserved for fibrechannel media types */ +#define ARPHRD_IEEE802_TR 800 /* Magic type ident for TR */ +#define ARPHRD_IEEE80211 801 /* IEEE 802.11 */ +#define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */ +#define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ +#define ARPHRD_IEEE802154 804 +#define ARPHRD_IEEE802154_MONITOR 805 /* IEEE 802.15.4 network monitor */ + +#define ARPHRD_PHONET 820 /* PhoNet media type */ +#define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */ +#define ARPHRD_CAIF 822 /* CAIF media type */ +#define ARPHRD_IP6GRE 823 /* GRE over IPv6 */ +#define ARPHRD_NETLINK 824 /* Netlink header */ +#define ARPHRD_6LOWPAN 825 /* IPv6 over LoWPAN */ +#define ARPHRD_VSOCKMON 826 /* Vsock monitor header */ + +#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ +#define ARPHRD_NONE 0xFFFE /* zero header length */ + +/* ARP protocol opcodes. */ +#define ARPOP_REQUEST 1 /* ARP request */ +#define ARPOP_REPLY 2 /* ARP reply */ +#define ARPOP_RREQUEST 3 /* RARP request */ +#define ARPOP_RREPLY 4 /* RARP reply */ +#define ARPOP_InREQUEST 8 /* InARP request */ +#define ARPOP_InREPLY 9 /* InARP reply */ +#define ARPOP_NAK 10 /* (ATM)ARP NAK */ + + +/* ARP ioctl request. */ +struct arpreq { + struct sockaddr arp_pa; /* protocol address */ + struct sockaddr arp_ha; /* hardware address */ + int arp_flags; /* flags */ + struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ + char arp_dev[IFNAMSIZ]; +}; + +struct arpreq_old { + struct sockaddr arp_pa; /* protocol address */ + struct sockaddr arp_ha; /* hardware address */ + int arp_flags; /* flags */ + struct sockaddr arp_netmask; /* netmask (only for proxy arps) */ +}; + +/* ARP Flag values. */ +#define ATF_COM 0x02 /* completed entry (ha valid) */ +#define ATF_PERM 0x04 /* permanent entry */ +#define ATF_PUBL 0x08 /* publish entry */ +#define ATF_USETRAILERS 0x10 /* has requested trailers */ +#define ATF_NETMASK 0x20 /* want to use a netmask (only + for proxy entries) */ +#define ATF_DONTPUB 0x40 /* don't answer this addresses */ + +/* + * This structure defines an ethernet arp header. + */ + +struct arphdr { + __be16 ar_hrd; /* format of hardware address */ + __be16 ar_pro; /* format of protocol address */ + unsigned char ar_hln; /* length of hardware address */ + unsigned char ar_pln; /* length of protocol address */ + __be16 ar_op; /* ARP opcode (command) */ + +#if 0 + /* + * Ethernet looks like this : This bit is variable sized however... + */ + unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ + unsigned char ar_sip[4]; /* sender IP address */ + unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ + unsigned char ar_tip[4]; /* target IP address */ +#endif + +}; + + +#endif /* _UAPI_LINUX_IF_ARP_H */ diff --git a/src/basic/linux/if_bonding.h b/src/basic/linux/if_bonding.h new file mode 100644 index 00000000..790585f0 --- /dev/null +++ b/src/basic/linux/if_bonding.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: GPL-1.0+ WITH Linux-syscall-note */ +/* + * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'. + * + * + * Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes + * NCM: Network and Communications Management, Inc. + * + * BUT, I'm the one who modified it for ethernet, so: + * (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov + * + * This software may be used and distributed according to the terms + * of the GNU Public License, incorporated herein by reference. + * + * 2003/03/18 - Amir Noam + * - Added support for getting slave's speed and duplex via ethtool. + * Needed for 802.3ad and other future modes. + * + * 2003/03/18 - Tsippy Mendelson and + * Shmulik Hen + * - Enable support of modes that need to use the unique mac address of + * each slave. + * + * 2003/03/18 - Tsippy Mendelson and + * Amir Noam + * - Moved driver's private data types to bonding.h + * + * 2003/03/18 - Amir Noam , + * Tsippy Mendelson and + * Shmulik Hen + * - Added support for IEEE 802.3ad Dynamic link aggregation mode. + * + * 2003/05/01 - Amir Noam + * - Added ABI version control to restore compatibility between + * new/old ifenslave and new/old bonding. + * + * 2003/12/01 - Shmulik Hen + * - Code cleanup and style changes + * + * 2005/05/05 - Jason Gabler + * - added definitions for various XOR hashing policies + */ + +#ifndef _LINUX_IF_BONDING_H +#define _LINUX_IF_BONDING_H + +#include +#include +#include + +/* userland - kernel ABI version (2003/05/08) */ +#define BOND_ABI_VERSION 2 + +/* + * We can remove these ioctl definitions in 2.5. People should use the + * SIOC*** versions of them instead + */ +#define BOND_ENSLAVE_OLD (SIOCDEVPRIVATE) +#define BOND_RELEASE_OLD (SIOCDEVPRIVATE + 1) +#define BOND_SETHWADDR_OLD (SIOCDEVPRIVATE + 2) +#define BOND_SLAVE_INFO_QUERY_OLD (SIOCDEVPRIVATE + 11) +#define BOND_INFO_QUERY_OLD (SIOCDEVPRIVATE + 12) +#define BOND_CHANGE_ACTIVE_OLD (SIOCDEVPRIVATE + 13) + +#define BOND_CHECK_MII_STATUS (SIOCGMIIPHY) + +#define BOND_MODE_ROUNDROBIN 0 +#define BOND_MODE_ACTIVEBACKUP 1 +#define BOND_MODE_XOR 2 +#define BOND_MODE_BROADCAST 3 +#define BOND_MODE_8023AD 4 +#define BOND_MODE_TLB 5 +#define BOND_MODE_ALB 6 /* TLB + RLB (receive load balancing) */ + +/* each slave's link has 4 states */ +#define BOND_LINK_UP 0 /* link is up and running */ +#define BOND_LINK_FAIL 1 /* link has just gone down */ +#define BOND_LINK_DOWN 2 /* link has been down for too long time */ +#define BOND_LINK_BACK 3 /* link is going back */ + +/* each slave has several states */ +#define BOND_STATE_ACTIVE 0 /* link is active */ +#define BOND_STATE_BACKUP 1 /* link is backup */ + +#define BOND_DEFAULT_MAX_BONDS 1 /* Default maximum number of devices to support */ + +#define BOND_DEFAULT_TX_QUEUES 16 /* Default number of tx queues per device */ + +#define BOND_DEFAULT_RESEND_IGMP 1 /* Default number of IGMP membership reports */ + +/* hashing types */ +#define BOND_XMIT_POLICY_LAYER2 0 /* layer 2 (MAC only), default */ +#define BOND_XMIT_POLICY_LAYER34 1 /* layer 3+4 (IP ^ (TCP || UDP)) */ +#define BOND_XMIT_POLICY_LAYER23 2 /* layer 2+3 (IP ^ MAC) */ +#define BOND_XMIT_POLICY_ENCAP23 3 /* encapsulated layer 2+3 */ +#define BOND_XMIT_POLICY_ENCAP34 4 /* encapsulated layer 3+4 */ + +typedef struct ifbond { + __s32 bond_mode; + __s32 num_slaves; + __s32 miimon; +} ifbond; + +typedef struct ifslave { + __s32 slave_id; /* Used as an IN param to the BOND_SLAVE_INFO_QUERY ioctl */ + char slave_name[IFNAMSIZ]; + __s8 link; + __s8 state; + __u32 link_failure_count; +} ifslave; + +struct ad_info { + __u16 aggregator_id; + __u16 ports; + __u16 actor_key; + __u16 partner_key; + __u8 partner_system[ETH_ALEN]; +}; + +/* Embedded inside LINK_XSTATS_TYPE_BOND */ +enum { + BOND_XSTATS_UNSPEC, + BOND_XSTATS_3AD, + __BOND_XSTATS_MAX +}; +#define BOND_XSTATS_MAX (__BOND_XSTATS_MAX - 1) + +/* Embedded inside BOND_XSTATS_3AD */ +enum { + BOND_3AD_STAT_LACPDU_RX, + BOND_3AD_STAT_LACPDU_TX, + BOND_3AD_STAT_LACPDU_UNKNOWN_RX, + BOND_3AD_STAT_LACPDU_ILLEGAL_RX, + BOND_3AD_STAT_MARKER_RX, + BOND_3AD_STAT_MARKER_TX, + BOND_3AD_STAT_MARKER_RESP_RX, + BOND_3AD_STAT_MARKER_RESP_TX, + BOND_3AD_STAT_MARKER_UNKNOWN_RX, + BOND_3AD_STAT_PAD, + __BOND_3AD_STAT_MAX +}; +#define BOND_3AD_STAT_MAX (__BOND_3AD_STAT_MAX - 1) + +#endif /* _LINUX_IF_BONDING_H */ + +/* + * Local variables: + * version-control: t + * kept-new-versions: 5 + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ + diff --git a/src/basic/linux/if_bridge.h b/src/basic/linux/if_bridge.h new file mode 100644 index 00000000..773e476a --- /dev/null +++ b/src/basic/linux/if_bridge.h @@ -0,0 +1,316 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Linux ethernet bridge + * + * Authors: + * Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _UAPI_LINUX_IF_BRIDGE_H +#define _UAPI_LINUX_IF_BRIDGE_H + +#include +#include +#include + +#define SYSFS_BRIDGE_ATTR "bridge" +#define SYSFS_BRIDGE_FDB "brforward" +#define SYSFS_BRIDGE_PORT_SUBDIR "brif" +#define SYSFS_BRIDGE_PORT_ATTR "brport" +#define SYSFS_BRIDGE_PORT_LINK "bridge" + +#define BRCTL_VERSION 1 + +#define BRCTL_GET_VERSION 0 +#define BRCTL_GET_BRIDGES 1 +#define BRCTL_ADD_BRIDGE 2 +#define BRCTL_DEL_BRIDGE 3 +#define BRCTL_ADD_IF 4 +#define BRCTL_DEL_IF 5 +#define BRCTL_GET_BRIDGE_INFO 6 +#define BRCTL_GET_PORT_LIST 7 +#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8 +#define BRCTL_SET_BRIDGE_HELLO_TIME 9 +#define BRCTL_SET_BRIDGE_MAX_AGE 10 +#define BRCTL_SET_AGEING_TIME 11 +#define BRCTL_SET_GC_INTERVAL 12 +#define BRCTL_GET_PORT_INFO 13 +#define BRCTL_SET_BRIDGE_STP_STATE 14 +#define BRCTL_SET_BRIDGE_PRIORITY 15 +#define BRCTL_SET_PORT_PRIORITY 16 +#define BRCTL_SET_PATH_COST 17 +#define BRCTL_GET_FDB_ENTRIES 18 + +#define BR_STATE_DISABLED 0 +#define BR_STATE_LISTENING 1 +#define BR_STATE_LEARNING 2 +#define BR_STATE_FORWARDING 3 +#define BR_STATE_BLOCKING 4 + +struct __bridge_info { + __u64 designated_root; + __u64 bridge_id; + __u32 root_path_cost; + __u32 max_age; + __u32 hello_time; + __u32 forward_delay; + __u32 bridge_max_age; + __u32 bridge_hello_time; + __u32 bridge_forward_delay; + __u8 topology_change; + __u8 topology_change_detected; + __u8 root_port; + __u8 stp_enabled; + __u32 ageing_time; + __u32 gc_interval; + __u32 hello_timer_value; + __u32 tcn_timer_value; + __u32 topology_change_timer_value; + __u32 gc_timer_value; +}; + +struct __port_info { + __u64 designated_root; + __u64 designated_bridge; + __u16 port_id; + __u16 designated_port; + __u32 path_cost; + __u32 designated_cost; + __u8 state; + __u8 top_change_ack; + __u8 config_pending; + __u8 unused0; + __u32 message_age_timer_value; + __u32 forward_delay_timer_value; + __u32 hold_timer_value; +}; + +struct __fdb_entry { + __u8 mac_addr[ETH_ALEN]; + __u8 port_no; + __u8 is_local; + __u32 ageing_timer_value; + __u8 port_hi; + __u8 pad0; + __u16 unused; +}; + +/* Bridge Flags */ +#define BRIDGE_FLAGS_MASTER 1 /* Bridge command to/from master */ +#define BRIDGE_FLAGS_SELF 2 /* Bridge command to/from lowerdev */ + +#define BRIDGE_MODE_VEB 0 /* Default loopback mode */ +#define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */ +#define BRIDGE_MODE_UNDEF 0xFFFF /* mode undefined */ + +/* Bridge management nested attributes + * [IFLA_AF_SPEC] = { + * [IFLA_BRIDGE_FLAGS] + * [IFLA_BRIDGE_MODE] + * [IFLA_BRIDGE_VLAN_INFO] + * } + */ +enum { + IFLA_BRIDGE_FLAGS, + IFLA_BRIDGE_MODE, + IFLA_BRIDGE_VLAN_INFO, + IFLA_BRIDGE_VLAN_TUNNEL_INFO, + __IFLA_BRIDGE_MAX, +}; +#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) + +#define BRIDGE_VLAN_INFO_MASTER (1<<0) /* Operate on Bridge device as well */ +#define BRIDGE_VLAN_INFO_PVID (1<<1) /* VLAN is PVID, ingress untagged */ +#define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */ +#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */ +#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */ +#define BRIDGE_VLAN_INFO_BRENTRY (1<<5) /* Global bridge VLAN entry */ + +struct bridge_vlan_info { + __u16 flags; + __u16 vid; +}; + +enum { + IFLA_BRIDGE_VLAN_TUNNEL_UNSPEC, + IFLA_BRIDGE_VLAN_TUNNEL_ID, + IFLA_BRIDGE_VLAN_TUNNEL_VID, + IFLA_BRIDGE_VLAN_TUNNEL_FLAGS, + __IFLA_BRIDGE_VLAN_TUNNEL_MAX, +}; + +#define IFLA_BRIDGE_VLAN_TUNNEL_MAX (__IFLA_BRIDGE_VLAN_TUNNEL_MAX - 1) + +struct bridge_vlan_xstats { + __u64 rx_bytes; + __u64 rx_packets; + __u64 tx_bytes; + __u64 tx_packets; + __u16 vid; + __u16 flags; + __u32 pad2; +}; + +/* Bridge multicast database attributes + * [MDBA_MDB] = { + * [MDBA_MDB_ENTRY] = { + * [MDBA_MDB_ENTRY_INFO] { + * struct br_mdb_entry + * [MDBA_MDB_EATTR attributes] + * } + * } + * } + * [MDBA_ROUTER] = { + * [MDBA_ROUTER_PORT] = { + * u32 ifindex + * [MDBA_ROUTER_PATTR attributes] + * } + * } + */ +enum { + MDBA_UNSPEC, + MDBA_MDB, + MDBA_ROUTER, + __MDBA_MAX, +}; +#define MDBA_MAX (__MDBA_MAX - 1) + +enum { + MDBA_MDB_UNSPEC, + MDBA_MDB_ENTRY, + __MDBA_MDB_MAX, +}; +#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1) + +enum { + MDBA_MDB_ENTRY_UNSPEC, + MDBA_MDB_ENTRY_INFO, + __MDBA_MDB_ENTRY_MAX, +}; +#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1) + +/* per mdb entry additional attributes */ +enum { + MDBA_MDB_EATTR_UNSPEC, + MDBA_MDB_EATTR_TIMER, + __MDBA_MDB_EATTR_MAX +}; +#define MDBA_MDB_EATTR_MAX (__MDBA_MDB_EATTR_MAX - 1) + +/* multicast router types */ +enum { + MDB_RTR_TYPE_DISABLED, + MDB_RTR_TYPE_TEMP_QUERY, + MDB_RTR_TYPE_PERM, + MDB_RTR_TYPE_TEMP +}; + +enum { + MDBA_ROUTER_UNSPEC, + MDBA_ROUTER_PORT, + __MDBA_ROUTER_MAX, +}; +#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) + +/* router port attributes */ +enum { + MDBA_ROUTER_PATTR_UNSPEC, + MDBA_ROUTER_PATTR_TIMER, + MDBA_ROUTER_PATTR_TYPE, + __MDBA_ROUTER_PATTR_MAX +}; +#define MDBA_ROUTER_PATTR_MAX (__MDBA_ROUTER_PATTR_MAX - 1) + +struct br_port_msg { + __u8 family; + __u32 ifindex; +}; + +struct br_mdb_entry { + __u32 ifindex; +#define MDB_TEMPORARY 0 +#define MDB_PERMANENT 1 + __u8 state; +#define MDB_FLAGS_OFFLOAD (1 << 0) + __u8 flags; + __u16 vid; + struct { + union { + __be32 ip4; + struct in6_addr ip6; + } u; + __be16 proto; + } addr; +}; + +enum { + MDBA_SET_ENTRY_UNSPEC, + MDBA_SET_ENTRY, + __MDBA_SET_ENTRY_MAX, +}; +#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1) + +/* Embedded inside LINK_XSTATS_TYPE_BRIDGE */ +enum { + BRIDGE_XSTATS_UNSPEC, + BRIDGE_XSTATS_VLAN, + BRIDGE_XSTATS_MCAST, + BRIDGE_XSTATS_PAD, + __BRIDGE_XSTATS_MAX +}; +#define BRIDGE_XSTATS_MAX (__BRIDGE_XSTATS_MAX - 1) + +enum { + BR_MCAST_DIR_RX, + BR_MCAST_DIR_TX, + BR_MCAST_DIR_SIZE +}; + +/* IGMP/MLD statistics */ +struct br_mcast_stats { + __u64 igmp_v1queries[BR_MCAST_DIR_SIZE]; + __u64 igmp_v2queries[BR_MCAST_DIR_SIZE]; + __u64 igmp_v3queries[BR_MCAST_DIR_SIZE]; + __u64 igmp_leaves[BR_MCAST_DIR_SIZE]; + __u64 igmp_v1reports[BR_MCAST_DIR_SIZE]; + __u64 igmp_v2reports[BR_MCAST_DIR_SIZE]; + __u64 igmp_v3reports[BR_MCAST_DIR_SIZE]; + __u64 igmp_parse_errors; + + __u64 mld_v1queries[BR_MCAST_DIR_SIZE]; + __u64 mld_v2queries[BR_MCAST_DIR_SIZE]; + __u64 mld_leaves[BR_MCAST_DIR_SIZE]; + __u64 mld_v1reports[BR_MCAST_DIR_SIZE]; + __u64 mld_v2reports[BR_MCAST_DIR_SIZE]; + __u64 mld_parse_errors; + + __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; + __u64 mcast_packets[BR_MCAST_DIR_SIZE]; +}; + +/* bridge boolean options + * BR_BOOLOPT_NO_LL_LEARN - disable learning from link-local packets + * + * IMPORTANT: if adding a new option do not forget to handle + * it in br_boolopt_toggle/get and bridge sysfs + */ +enum br_boolopt_id { + BR_BOOLOPT_NO_LL_LEARN, + BR_BOOLOPT_MAX +}; + +/* struct br_boolopt_multi - change multiple bridge boolean options + * + * @optval: new option values (bit per option) + * @optmask: options to change (bit per option) + */ +struct br_boolopt_multi { + __u32 optval; + __u32 optmask; +}; +#endif /* _UAPI_LINUX_IF_BRIDGE_H */ diff --git a/src/basic/linux/if_ether.h b/src/basic/linux/if_ether.h new file mode 100644 index 00000000..3158ba67 --- /dev/null +++ b/src/basic/linux/if_ether.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Global definitions for the Ethernet IEEE 802.3 interface. + * + * Version: @(#)if_ether.h 1.0.1a 02/08/94 + * + * Author: Fred N. van Kempen, + * Donald Becker, + * Alan Cox, + * Steve Whitehouse, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _UAPI_LINUX_IF_ETHER_H +#define _UAPI_LINUX_IF_ETHER_H + +#include + +/* + * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble + * and FCS/CRC (frame check sequence). + */ + +#define ETH_ALEN 6 /* Octets in one ethernet addr */ +#define ETH_TLEN 2 /* Octets in ethernet type field */ +#define ETH_HLEN 14 /* Total octets in header. */ +#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ +#define ETH_DATA_LEN 1500 /* Max. octets in payload */ +#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ +#define ETH_FCS_LEN 4 /* Octets in the FCS */ + +#define ETH_MIN_MTU 68 /* Min IPv4 MTU per RFC791 */ +#define ETH_MAX_MTU 0xFFFFU /* 65535, same as IP_MAX_MTU */ + +/* + * These are the defined Ethernet Protocol ID's. + */ + +#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ +#define ETH_P_PUP 0x0200 /* Xerox PUP packet */ +#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */ +#define ETH_P_TSN 0x22F0 /* TSN (IEEE 1722) packet */ +#define ETH_P_ERSPAN2 0x22EB /* ERSPAN version 2 (type III) */ +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#define ETH_P_X25 0x0805 /* CCITT X.25 */ +#define ETH_P_ARP 0x0806 /* Address Resolution packet */ +#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */ +#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */ +#define ETH_P_BATMAN 0x4305 /* B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_DEC 0x6000 /* DEC Assigned proto */ +#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */ +#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */ +#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */ +#define ETH_P_LAT 0x6004 /* DEC LAT */ +#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */ +#define ETH_P_CUST 0x6006 /* DEC Customer use */ +#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */ +#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */ +#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ +#define ETH_P_ATALK 0x809B /* Appletalk DDP */ +#define ETH_P_AARP 0x80F3 /* Appletalk AARP */ +#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ +#define ETH_P_ERSPAN 0x88BE /* ERSPAN type II */ +#define ETH_P_IPX 0x8137 /* IPX over DIX */ +#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ +#define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */ +#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ +#define ETH_P_WCCP 0x883E /* Web-cache coordination protocol + * defined in draft-wilson-wrec-wccp-v2-00.txt */ +#define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */ +#define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */ +#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ +#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ +#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ +#define ETH_P_LINK_CTL 0x886c /* HPNA, wlan link local tunnel */ +#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport + * over Ethernet + */ +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ +#define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */ +#define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */ +#define ETH_P_PREAUTH 0x88C7 /* 802.11 Preauthentication */ +#define ETH_P_TIPC 0x88CA /* TIPC */ +#define ETH_P_MACSEC 0x88E5 /* 802.1ae MACsec */ +#define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */ +#define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */ +#define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ +#define ETH_P_NCSI 0x88F8 /* NCSI protocol */ +#define ETH_P_PRP 0x88FB /* IEC 62439-3 PRP/HSRv0 */ +#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ +#define ETH_P_IBOE 0x8915 /* Infiniband over Ethernet */ +#define ETH_P_TDLS 0x890D /* TDLS */ +#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ +#define ETH_P_80221 0x8917 /* IEEE 802.21 Media Independent Handover Protocol */ +#define ETH_P_HSR 0x892F /* IEC 62439-3 HSRv1 */ +#define ETH_P_NSH 0x894F /* Network Service Header */ +#define ETH_P_LOOPBACK 0x9000 /* Ethernet loopback packet, per IEEE 802.3 */ +#define ETH_P_QINQ1 0x9100 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_QINQ2 0x9200 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_DSA_8021Q 0xDADB /* Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ +#define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */ +#define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */ + +#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is less than this value + * then the frame is Ethernet II. Else it is 802.3 */ + +/* + * Non DIX types. Won't clash for 1500 types. + */ + +#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */ +#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */ +#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ +#define ETH_P_802_2 0x0004 /* 802.2 frames */ +#define ETH_P_SNAP 0x0005 /* Internal only */ +#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */ +#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/ +#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */ +#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */ +#define ETH_P_CAN 0x000C /* CAN: Controller Area Network */ +#define ETH_P_CANFD 0x000D /* CANFD: CAN flexible data rate*/ +#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/ +#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */ +#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */ +#define ETH_P_CONTROL 0x0016 /* Card specific control frames */ +#define ETH_P_IRDA 0x0017 /* Linux-IrDA */ +#define ETH_P_ECONET 0x0018 /* Acorn Econet */ +#define ETH_P_HDLC 0x0019 /* HDLC frames */ +#define ETH_P_ARCNET 0x001A /* 1A for ArcNet :-) */ +#define ETH_P_DSA 0x001B /* Distributed Switch Arch. */ +#define ETH_P_TRAILER 0x001C /* Trailer switch tagging */ +#define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */ +#define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */ +#define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */ +#define ETH_P_XDSA 0x00F8 /* Multiplexed DSA protocol */ +#define ETH_P_MAP 0x00F9 /* Qualcomm multiplexing and + * aggregation protocol + */ + +/* + * This is an Ethernet frame header. + */ + +/* allow libcs like musl to deactivate this, glibc does not implement this. */ +#ifndef __UAPI_DEF_ETHHDR +#define __UAPI_DEF_ETHHDR 1 +#endif + +#if __UAPI_DEF_ETHHDR +struct ethhdr { + unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ + unsigned char h_source[ETH_ALEN]; /* source ether addr */ + __be16 h_proto; /* packet type ID field */ +} __attribute__((packed)); +#endif + + +#endif /* _UAPI_LINUX_IF_ETHER_H */ diff --git a/src/basic/linux/if_link.h b/src/basic/linux/if_link.h new file mode 100644 index 00000000..5b225ff6 --- /dev/null +++ b/src/basic/linux/if_link.h @@ -0,0 +1,1025 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_LINUX_IF_LINK_H +#define _UAPI_LINUX_IF_LINK_H + +#include +#include + +/* This struct should be in sync with struct rtnl_link_stats64 */ +struct rtnl_link_stats { + __u32 rx_packets; /* total packets received */ + __u32 tx_packets; /* total packets transmitted */ + __u32 rx_bytes; /* total bytes received */ + __u32 tx_bytes; /* total bytes transmitted */ + __u32 rx_errors; /* bad packets received */ + __u32 tx_errors; /* packet transmit problems */ + __u32 rx_dropped; /* no space in linux buffers */ + __u32 tx_dropped; /* no space available in linux */ + __u32 multicast; /* multicast packets received */ + __u32 collisions; + + /* detailed rx_errors: */ + __u32 rx_length_errors; + __u32 rx_over_errors; /* receiver ring buff overflow */ + __u32 rx_crc_errors; /* recved pkt with crc error */ + __u32 rx_frame_errors; /* recv'd frame alignment error */ + __u32 rx_fifo_errors; /* recv'r fifo overrun */ + __u32 rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + __u32 tx_aborted_errors; + __u32 tx_carrier_errors; + __u32 tx_fifo_errors; + __u32 tx_heartbeat_errors; + __u32 tx_window_errors; + + /* for cslip etc */ + __u32 rx_compressed; + __u32 tx_compressed; + + __u32 rx_nohandler; /* dropped, no handler found */ +}; + +/* The main device statistics structure */ +struct rtnl_link_stats64 { + __u64 rx_packets; /* total packets received */ + __u64 tx_packets; /* total packets transmitted */ + __u64 rx_bytes; /* total bytes received */ + __u64 tx_bytes; /* total bytes transmitted */ + __u64 rx_errors; /* bad packets received */ + __u64 tx_errors; /* packet transmit problems */ + __u64 rx_dropped; /* no space in linux buffers */ + __u64 tx_dropped; /* no space available in linux */ + __u64 multicast; /* multicast packets received */ + __u64 collisions; + + /* detailed rx_errors: */ + __u64 rx_length_errors; + __u64 rx_over_errors; /* receiver ring buff overflow */ + __u64 rx_crc_errors; /* recved pkt with crc error */ + __u64 rx_frame_errors; /* recv'd frame alignment error */ + __u64 rx_fifo_errors; /* recv'r fifo overrun */ + __u64 rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + __u64 tx_aborted_errors; + __u64 tx_carrier_errors; + __u64 tx_fifo_errors; + __u64 tx_heartbeat_errors; + __u64 tx_window_errors; + + /* for cslip etc */ + __u64 rx_compressed; + __u64 tx_compressed; + + __u64 rx_nohandler; /* dropped, no handler found */ +}; + +/* The struct should be in sync with struct ifmap */ +struct rtnl_link_ifmap { + __u64 mem_start; + __u64 mem_end; + __u64 base_addr; + __u16 irq; + __u8 dma; + __u8 port; +}; + +/* + * IFLA_AF_SPEC + * Contains nested attributes for address family specific attributes. + * Each address family may create a attribute with the address family + * number as type and create its own attribute structure in it. + * + * Example: + * [IFLA_AF_SPEC] = { + * [AF_INET] = { + * [IFLA_INET_CONF] = ..., + * }, + * [AF_INET6] = { + * [IFLA_INET6_FLAGS] = ..., + * [IFLA_INET6_CONF] = ..., + * } + * } + */ + +enum { + IFLA_UNSPEC, + IFLA_ADDRESS, + IFLA_BROADCAST, + IFLA_IFNAME, + IFLA_MTU, + IFLA_LINK, + IFLA_QDISC, + IFLA_STATS, + IFLA_COST, +#define IFLA_COST IFLA_COST + IFLA_PRIORITY, +#define IFLA_PRIORITY IFLA_PRIORITY + IFLA_MASTER, +#define IFLA_MASTER IFLA_MASTER + IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ +#define IFLA_WIRELESS IFLA_WIRELESS + IFLA_PROTINFO, /* Protocol specific information for a link */ +#define IFLA_PROTINFO IFLA_PROTINFO + IFLA_TXQLEN, +#define IFLA_TXQLEN IFLA_TXQLEN + IFLA_MAP, +#define IFLA_MAP IFLA_MAP + IFLA_WEIGHT, +#define IFLA_WEIGHT IFLA_WEIGHT + IFLA_OPERSTATE, + IFLA_LINKMODE, + IFLA_LINKINFO, +#define IFLA_LINKINFO IFLA_LINKINFO + IFLA_NET_NS_PID, + IFLA_IFALIAS, + IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ + IFLA_VFINFO_LIST, + IFLA_STATS64, + IFLA_VF_PORTS, + IFLA_PORT_SELF, + IFLA_AF_SPEC, + IFLA_GROUP, /* Group the device belongs to */ + IFLA_NET_NS_FD, + IFLA_EXT_MASK, /* Extended info mask, VFs, etc */ + IFLA_PROMISCUITY, /* Promiscuity count: > 0 means acts PROMISC */ +#define IFLA_PROMISCUITY IFLA_PROMISCUITY + IFLA_NUM_TX_QUEUES, + IFLA_NUM_RX_QUEUES, + IFLA_CARRIER, + IFLA_PHYS_PORT_ID, + IFLA_CARRIER_CHANGES, + IFLA_PHYS_SWITCH_ID, + IFLA_LINK_NETNSID, + IFLA_PHYS_PORT_NAME, + IFLA_PROTO_DOWN, + IFLA_GSO_MAX_SEGS, + IFLA_GSO_MAX_SIZE, + IFLA_PAD, + IFLA_XDP, + IFLA_EVENT, + IFLA_NEW_NETNSID, + IFLA_IF_NETNSID, + IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */ + IFLA_CARRIER_UP_COUNT, + IFLA_CARRIER_DOWN_COUNT, + IFLA_NEW_IFINDEX, + IFLA_MIN_MTU, + IFLA_MAX_MTU, + __IFLA_MAX +}; + + +#define IFLA_MAX (__IFLA_MAX - 1) + +/* backwards compatibility for userspace */ +#ifndef __KERNEL__ +#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) +#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) +#endif + +enum { + IFLA_INET_UNSPEC, + IFLA_INET_CONF, + __IFLA_INET_MAX, +}; + +#define IFLA_INET_MAX (__IFLA_INET_MAX - 1) + +/* ifi_flags. + + IFF_* flags. + + The only change is: + IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are + more not changeable by user. They describe link media + characteristics and set by device driver. + + Comments: + - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid + - If neither of these three flags are set; + the interface is NBMA. + + - IFF_MULTICAST does not mean anything special: + multicasts can be used on all not-NBMA links. + IFF_MULTICAST means that this media uses special encapsulation + for multicast frames. Apparently, all IFF_POINTOPOINT and + IFF_BROADCAST devices are able to use multicasts too. + */ + +/* IFLA_LINK. + For usual devices it is equal ifi_index. + If it is a "virtual interface" (f.e. tunnel), ifi_link + can point to real physical interface (f.e. for bandwidth calculations), + or maybe 0, what means, that real media is unknown (usual + for IPIP tunnels, when route to endpoint is allowed to change) + */ + +/* Subtype attributes for IFLA_PROTINFO */ +enum { + IFLA_INET6_UNSPEC, + IFLA_INET6_FLAGS, /* link flags */ + IFLA_INET6_CONF, /* sysctl parameters */ + IFLA_INET6_STATS, /* statistics */ + IFLA_INET6_MCAST, /* MC things. What of them? */ + IFLA_INET6_CACHEINFO, /* time values and max reasm size */ + IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */ + IFLA_INET6_TOKEN, /* device token */ + IFLA_INET6_ADDR_GEN_MODE, /* implicit address generator mode */ + __IFLA_INET6_MAX +}; + +#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) + +enum in6_addr_gen_mode { + IN6_ADDR_GEN_MODE_EUI64, + IN6_ADDR_GEN_MODE_NONE, + IN6_ADDR_GEN_MODE_STABLE_PRIVACY, + IN6_ADDR_GEN_MODE_RANDOM, +}; + +/* Bridge section */ + +enum { + IFLA_BR_UNSPEC, + IFLA_BR_FORWARD_DELAY, + IFLA_BR_HELLO_TIME, + IFLA_BR_MAX_AGE, + IFLA_BR_AGEING_TIME, + IFLA_BR_STP_STATE, + IFLA_BR_PRIORITY, + IFLA_BR_VLAN_FILTERING, + IFLA_BR_VLAN_PROTOCOL, + IFLA_BR_GROUP_FWD_MASK, + IFLA_BR_ROOT_ID, + IFLA_BR_BRIDGE_ID, + IFLA_BR_ROOT_PORT, + IFLA_BR_ROOT_PATH_COST, + IFLA_BR_TOPOLOGY_CHANGE, + IFLA_BR_TOPOLOGY_CHANGE_DETECTED, + IFLA_BR_HELLO_TIMER, + IFLA_BR_TCN_TIMER, + IFLA_BR_TOPOLOGY_CHANGE_TIMER, + IFLA_BR_GC_TIMER, + IFLA_BR_GROUP_ADDR, + IFLA_BR_FDB_FLUSH, + IFLA_BR_MCAST_ROUTER, + IFLA_BR_MCAST_SNOOPING, + IFLA_BR_MCAST_QUERY_USE_IFADDR, + IFLA_BR_MCAST_QUERIER, + IFLA_BR_MCAST_HASH_ELASTICITY, + IFLA_BR_MCAST_HASH_MAX, + IFLA_BR_MCAST_LAST_MEMBER_CNT, + IFLA_BR_MCAST_STARTUP_QUERY_CNT, + IFLA_BR_MCAST_LAST_MEMBER_INTVL, + IFLA_BR_MCAST_MEMBERSHIP_INTVL, + IFLA_BR_MCAST_QUERIER_INTVL, + IFLA_BR_MCAST_QUERY_INTVL, + IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, + IFLA_BR_MCAST_STARTUP_QUERY_INTVL, + IFLA_BR_NF_CALL_IPTABLES, + IFLA_BR_NF_CALL_IP6TABLES, + IFLA_BR_NF_CALL_ARPTABLES, + IFLA_BR_VLAN_DEFAULT_PVID, + IFLA_BR_PAD, + IFLA_BR_VLAN_STATS_ENABLED, + IFLA_BR_MCAST_STATS_ENABLED, + IFLA_BR_MCAST_IGMP_VERSION, + IFLA_BR_MCAST_MLD_VERSION, + IFLA_BR_VLAN_STATS_PER_PORT, + IFLA_BR_MULTI_BOOLOPT, + __IFLA_BR_MAX, +}; + +#define IFLA_BR_MAX (__IFLA_BR_MAX - 1) + +struct ifla_bridge_id { + __u8 prio[2]; + __u8 addr[6]; /* ETH_ALEN */ +}; + +enum { + BRIDGE_MODE_UNSPEC, + BRIDGE_MODE_HAIRPIN, +}; + +enum { + IFLA_BRPORT_UNSPEC, + IFLA_BRPORT_STATE, /* Spanning tree state */ + IFLA_BRPORT_PRIORITY, /* " priority */ + IFLA_BRPORT_COST, /* " cost */ + IFLA_BRPORT_MODE, /* mode (hairpin) */ + IFLA_BRPORT_GUARD, /* bpdu guard */ + IFLA_BRPORT_PROTECT, /* root port protection */ + IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ + IFLA_BRPORT_LEARNING, /* mac learning */ + IFLA_BRPORT_UNICAST_FLOOD, /* flood unicast traffic */ + IFLA_BRPORT_PROXYARP, /* proxy ARP */ + IFLA_BRPORT_LEARNING_SYNC, /* mac learning sync from device */ + IFLA_BRPORT_PROXYARP_WIFI, /* proxy ARP for Wi-Fi */ + IFLA_BRPORT_ROOT_ID, /* designated root */ + IFLA_BRPORT_BRIDGE_ID, /* designated bridge */ + IFLA_BRPORT_DESIGNATED_PORT, + IFLA_BRPORT_DESIGNATED_COST, + IFLA_BRPORT_ID, + IFLA_BRPORT_NO, + IFLA_BRPORT_TOPOLOGY_CHANGE_ACK, + IFLA_BRPORT_CONFIG_PENDING, + IFLA_BRPORT_MESSAGE_AGE_TIMER, + IFLA_BRPORT_FORWARD_DELAY_TIMER, + IFLA_BRPORT_HOLD_TIMER, + IFLA_BRPORT_FLUSH, + IFLA_BRPORT_MULTICAST_ROUTER, + IFLA_BRPORT_PAD, + IFLA_BRPORT_MCAST_FLOOD, + IFLA_BRPORT_MCAST_TO_UCAST, + IFLA_BRPORT_VLAN_TUNNEL, + IFLA_BRPORT_BCAST_FLOOD, + IFLA_BRPORT_GROUP_FWD_MASK, + IFLA_BRPORT_NEIGH_SUPPRESS, + IFLA_BRPORT_ISOLATED, + IFLA_BRPORT_BACKUP_PORT, + __IFLA_BRPORT_MAX +}; +#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) + +struct ifla_cacheinfo { + __u32 max_reasm_len; + __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ + __u32 reachable_time; + __u32 retrans_time; +}; + +enum { + IFLA_INFO_UNSPEC, + IFLA_INFO_KIND, + IFLA_INFO_DATA, + IFLA_INFO_XSTATS, + IFLA_INFO_SLAVE_KIND, + IFLA_INFO_SLAVE_DATA, + __IFLA_INFO_MAX, +}; + +#define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1) + +/* VLAN section */ + +enum { + IFLA_VLAN_UNSPEC, + IFLA_VLAN_ID, + IFLA_VLAN_FLAGS, + IFLA_VLAN_EGRESS_QOS, + IFLA_VLAN_INGRESS_QOS, + IFLA_VLAN_PROTOCOL, + __IFLA_VLAN_MAX, +}; + +#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1) + +struct ifla_vlan_flags { + __u32 flags; + __u32 mask; +}; + +enum { + IFLA_VLAN_QOS_UNSPEC, + IFLA_VLAN_QOS_MAPPING, + __IFLA_VLAN_QOS_MAX +}; + +#define IFLA_VLAN_QOS_MAX (__IFLA_VLAN_QOS_MAX - 1) + +struct ifla_vlan_qos_mapping { + __u32 from; + __u32 to; +}; + +/* MACVLAN section */ +enum { + IFLA_MACVLAN_UNSPEC, + IFLA_MACVLAN_MODE, + IFLA_MACVLAN_FLAGS, + IFLA_MACVLAN_MACADDR_MODE, + IFLA_MACVLAN_MACADDR, + IFLA_MACVLAN_MACADDR_DATA, + IFLA_MACVLAN_MACADDR_COUNT, + __IFLA_MACVLAN_MAX, +}; + +#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1) + +enum macvlan_mode { + MACVLAN_MODE_PRIVATE = 1, /* don't talk to other macvlans */ + MACVLAN_MODE_VEPA = 2, /* talk to other ports through ext bridge */ + MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ + MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */ + MACVLAN_MODE_SOURCE = 16,/* use source MAC address list to assign */ +}; + +enum macvlan_macaddr_mode { + MACVLAN_MACADDR_ADD, + MACVLAN_MACADDR_DEL, + MACVLAN_MACADDR_FLUSH, + MACVLAN_MACADDR_SET, +}; + +#define MACVLAN_FLAG_NOPROMISC 1 + +/* VRF section */ +enum { + IFLA_VRF_UNSPEC, + IFLA_VRF_TABLE, + __IFLA_VRF_MAX +}; + +#define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1) + +enum { + IFLA_VRF_PORT_UNSPEC, + IFLA_VRF_PORT_TABLE, + __IFLA_VRF_PORT_MAX +}; + +#define IFLA_VRF_PORT_MAX (__IFLA_VRF_PORT_MAX - 1) + +/* MACSEC section */ +enum { + IFLA_MACSEC_UNSPEC, + IFLA_MACSEC_SCI, + IFLA_MACSEC_PORT, + IFLA_MACSEC_ICV_LEN, + IFLA_MACSEC_CIPHER_SUITE, + IFLA_MACSEC_WINDOW, + IFLA_MACSEC_ENCODING_SA, + IFLA_MACSEC_ENCRYPT, + IFLA_MACSEC_PROTECT, + IFLA_MACSEC_INC_SCI, + IFLA_MACSEC_ES, + IFLA_MACSEC_SCB, + IFLA_MACSEC_REPLAY_PROTECT, + IFLA_MACSEC_VALIDATION, + IFLA_MACSEC_PAD, + __IFLA_MACSEC_MAX, +}; + +#define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1) + +/* XFRM section */ +enum { + IFLA_XFRM_UNSPEC, + IFLA_XFRM_LINK, + IFLA_XFRM_IF_ID, + __IFLA_XFRM_MAX +}; + +#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1) + +enum macsec_validation_type { + MACSEC_VALIDATE_DISABLED = 0, + MACSEC_VALIDATE_CHECK = 1, + MACSEC_VALIDATE_STRICT = 2, + __MACSEC_VALIDATE_END, + MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1, +}; + +/* IPVLAN section */ +enum { + IFLA_IPVLAN_UNSPEC, + IFLA_IPVLAN_MODE, + IFLA_IPVLAN_FLAGS, + __IFLA_IPVLAN_MAX +}; + +#define IFLA_IPVLAN_MAX (__IFLA_IPVLAN_MAX - 1) + +enum ipvlan_mode { + IPVLAN_MODE_L2 = 0, + IPVLAN_MODE_L3, + IPVLAN_MODE_L3S, + IPVLAN_MODE_MAX +}; + +#define IPVLAN_F_PRIVATE 0x01 +#define IPVLAN_F_VEPA 0x02 + +/* VXLAN section */ +enum { + IFLA_VXLAN_UNSPEC, + IFLA_VXLAN_ID, + IFLA_VXLAN_GROUP, /* group or remote address */ + IFLA_VXLAN_LINK, + IFLA_VXLAN_LOCAL, + IFLA_VXLAN_TTL, + IFLA_VXLAN_TOS, + IFLA_VXLAN_LEARNING, + IFLA_VXLAN_AGEING, + IFLA_VXLAN_LIMIT, + IFLA_VXLAN_PORT_RANGE, /* source port */ + IFLA_VXLAN_PROXY, + IFLA_VXLAN_RSC, + IFLA_VXLAN_L2MISS, + IFLA_VXLAN_L3MISS, + IFLA_VXLAN_PORT, /* destination port */ + IFLA_VXLAN_GROUP6, + IFLA_VXLAN_LOCAL6, + IFLA_VXLAN_UDP_CSUM, + IFLA_VXLAN_UDP_ZERO_CSUM6_TX, + IFLA_VXLAN_UDP_ZERO_CSUM6_RX, + IFLA_VXLAN_REMCSUM_TX, + IFLA_VXLAN_REMCSUM_RX, + IFLA_VXLAN_GBP, + IFLA_VXLAN_REMCSUM_NOPARTIAL, + IFLA_VXLAN_COLLECT_METADATA, + IFLA_VXLAN_LABEL, + IFLA_VXLAN_GPE, + IFLA_VXLAN_TTL_INHERIT, + IFLA_VXLAN_DF, + __IFLA_VXLAN_MAX +}; +#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) + +struct ifla_vxlan_port_range { + __be16 low; + __be16 high; +}; + +enum ifla_vxlan_df { + VXLAN_DF_UNSET = 0, + VXLAN_DF_SET, + VXLAN_DF_INHERIT, + __VXLAN_DF_END, + VXLAN_DF_MAX = __VXLAN_DF_END - 1, +}; + +/* GENEVE section */ +enum { + IFLA_GENEVE_UNSPEC, + IFLA_GENEVE_ID, + IFLA_GENEVE_REMOTE, + IFLA_GENEVE_TTL, + IFLA_GENEVE_TOS, + IFLA_GENEVE_PORT, /* destination port */ + IFLA_GENEVE_COLLECT_METADATA, + IFLA_GENEVE_REMOTE6, + IFLA_GENEVE_UDP_CSUM, + IFLA_GENEVE_UDP_ZERO_CSUM6_TX, + IFLA_GENEVE_UDP_ZERO_CSUM6_RX, + IFLA_GENEVE_LABEL, + IFLA_GENEVE_TTL_INHERIT, + IFLA_GENEVE_DF, + __IFLA_GENEVE_MAX +}; +#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) + +enum ifla_geneve_df { + GENEVE_DF_UNSET = 0, + GENEVE_DF_SET, + GENEVE_DF_INHERIT, + __GENEVE_DF_END, + GENEVE_DF_MAX = __GENEVE_DF_END - 1, +}; + +/* PPP section */ +enum { + IFLA_PPP_UNSPEC, + IFLA_PPP_DEV_FD, + __IFLA_PPP_MAX +}; +#define IFLA_PPP_MAX (__IFLA_PPP_MAX - 1) + +/* GTP section */ + +enum ifla_gtp_role { + GTP_ROLE_GGSN = 0, + GTP_ROLE_SGSN, +}; + +enum { + IFLA_GTP_UNSPEC, + IFLA_GTP_FD0, + IFLA_GTP_FD1, + IFLA_GTP_PDP_HASHSIZE, + IFLA_GTP_ROLE, + __IFLA_GTP_MAX, +}; +#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1) + +/* Bonding section */ + +enum { + IFLA_BOND_UNSPEC, + IFLA_BOND_MODE, + IFLA_BOND_ACTIVE_SLAVE, + IFLA_BOND_MIIMON, + IFLA_BOND_UPDELAY, + IFLA_BOND_DOWNDELAY, + IFLA_BOND_USE_CARRIER, + IFLA_BOND_ARP_INTERVAL, + IFLA_BOND_ARP_IP_TARGET, + IFLA_BOND_ARP_VALIDATE, + IFLA_BOND_ARP_ALL_TARGETS, + IFLA_BOND_PRIMARY, + IFLA_BOND_PRIMARY_RESELECT, + IFLA_BOND_FAIL_OVER_MAC, + IFLA_BOND_XMIT_HASH_POLICY, + IFLA_BOND_RESEND_IGMP, + IFLA_BOND_NUM_PEER_NOTIF, + IFLA_BOND_ALL_SLAVES_ACTIVE, + IFLA_BOND_MIN_LINKS, + IFLA_BOND_LP_INTERVAL, + IFLA_BOND_PACKETS_PER_SLAVE, + IFLA_BOND_AD_LACP_RATE, + IFLA_BOND_AD_SELECT, + IFLA_BOND_AD_INFO, + IFLA_BOND_AD_ACTOR_SYS_PRIO, + IFLA_BOND_AD_USER_PORT_KEY, + IFLA_BOND_AD_ACTOR_SYSTEM, + IFLA_BOND_TLB_DYNAMIC_LB, + __IFLA_BOND_MAX, +}; + +#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) + +enum { + IFLA_BOND_AD_INFO_UNSPEC, + IFLA_BOND_AD_INFO_AGGREGATOR, + IFLA_BOND_AD_INFO_NUM_PORTS, + IFLA_BOND_AD_INFO_ACTOR_KEY, + IFLA_BOND_AD_INFO_PARTNER_KEY, + IFLA_BOND_AD_INFO_PARTNER_MAC, + __IFLA_BOND_AD_INFO_MAX, +}; + +#define IFLA_BOND_AD_INFO_MAX (__IFLA_BOND_AD_INFO_MAX - 1) + +enum { + IFLA_BOND_SLAVE_UNSPEC, + IFLA_BOND_SLAVE_STATE, + IFLA_BOND_SLAVE_MII_STATUS, + IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, + IFLA_BOND_SLAVE_PERM_HWADDR, + IFLA_BOND_SLAVE_QUEUE_ID, + IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, + IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, + IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, + __IFLA_BOND_SLAVE_MAX, +}; + +#define IFLA_BOND_SLAVE_MAX (__IFLA_BOND_SLAVE_MAX - 1) + +/* SR-IOV virtual function management section */ + +enum { + IFLA_VF_INFO_UNSPEC, + IFLA_VF_INFO, + __IFLA_VF_INFO_MAX, +}; + +#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1) + +enum { + IFLA_VF_UNSPEC, + IFLA_VF_MAC, /* Hardware queue specific attributes */ + IFLA_VF_VLAN, /* VLAN ID and QoS */ + IFLA_VF_TX_RATE, /* Max TX Bandwidth Allocation */ + IFLA_VF_SPOOFCHK, /* Spoof Checking on/off switch */ + IFLA_VF_LINK_STATE, /* link state enable/disable/auto switch */ + IFLA_VF_RATE, /* Min and Max TX Bandwidth Allocation */ + IFLA_VF_RSS_QUERY_EN, /* RSS Redirection Table and Hash Key query + * on/off switch + */ + IFLA_VF_STATS, /* network device statistics */ + IFLA_VF_TRUST, /* Trust VF */ + IFLA_VF_IB_NODE_GUID, /* VF Infiniband node GUID */ + IFLA_VF_IB_PORT_GUID, /* VF Infiniband port GUID */ + IFLA_VF_VLAN_LIST, /* nested list of vlans, option for QinQ */ + __IFLA_VF_MAX, +}; + +#define IFLA_VF_MAX (__IFLA_VF_MAX - 1) + +struct ifla_vf_mac { + __u32 vf; + __u8 mac[32]; /* MAX_ADDR_LEN */ +}; + +struct ifla_vf_vlan { + __u32 vf; + __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ + __u32 qos; +}; + +enum { + IFLA_VF_VLAN_INFO_UNSPEC, + IFLA_VF_VLAN_INFO, /* VLAN ID, QoS and VLAN protocol */ + __IFLA_VF_VLAN_INFO_MAX, +}; + +#define IFLA_VF_VLAN_INFO_MAX (__IFLA_VF_VLAN_INFO_MAX - 1) +#define MAX_VLAN_LIST_LEN 1 + +struct ifla_vf_vlan_info { + __u32 vf; + __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ + __u32 qos; + __be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */ +}; + +struct ifla_vf_tx_rate { + __u32 vf; + __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ +}; + +struct ifla_vf_rate { + __u32 vf; + __u32 min_tx_rate; /* Min Bandwidth in Mbps */ + __u32 max_tx_rate; /* Max Bandwidth in Mbps */ +}; + +struct ifla_vf_spoofchk { + __u32 vf; + __u32 setting; +}; + +struct ifla_vf_guid { + __u32 vf; + __u64 guid; +}; + +enum { + IFLA_VF_LINK_STATE_AUTO, /* link state of the uplink */ + IFLA_VF_LINK_STATE_ENABLE, /* link always up */ + IFLA_VF_LINK_STATE_DISABLE, /* link always down */ + __IFLA_VF_LINK_STATE_MAX, +}; + +struct ifla_vf_link_state { + __u32 vf; + __u32 link_state; +}; + +struct ifla_vf_rss_query_en { + __u32 vf; + __u32 setting; +}; + +enum { + IFLA_VF_STATS_RX_PACKETS, + IFLA_VF_STATS_TX_PACKETS, + IFLA_VF_STATS_RX_BYTES, + IFLA_VF_STATS_TX_BYTES, + IFLA_VF_STATS_BROADCAST, + IFLA_VF_STATS_MULTICAST, + IFLA_VF_STATS_PAD, + IFLA_VF_STATS_RX_DROPPED, + IFLA_VF_STATS_TX_DROPPED, + __IFLA_VF_STATS_MAX, +}; + +#define IFLA_VF_STATS_MAX (__IFLA_VF_STATS_MAX - 1) + +struct ifla_vf_trust { + __u32 vf; + __u32 setting; +}; + +/* VF ports management section + * + * Nested layout of set/get msg is: + * + * [IFLA_NUM_VF] + * [IFLA_VF_PORTS] + * [IFLA_VF_PORT] + * [IFLA_PORT_*], ... + * [IFLA_VF_PORT] + * [IFLA_PORT_*], ... + * ... + * [IFLA_PORT_SELF] + * [IFLA_PORT_*], ... + */ + +enum { + IFLA_VF_PORT_UNSPEC, + IFLA_VF_PORT, /* nest */ + __IFLA_VF_PORT_MAX, +}; + +#define IFLA_VF_PORT_MAX (__IFLA_VF_PORT_MAX - 1) + +enum { + IFLA_PORT_UNSPEC, + IFLA_PORT_VF, /* __u32 */ + IFLA_PORT_PROFILE, /* string */ + IFLA_PORT_VSI_TYPE, /* 802.1Qbg (pre-)standard VDP */ + IFLA_PORT_INSTANCE_UUID, /* binary UUID */ + IFLA_PORT_HOST_UUID, /* binary UUID */ + IFLA_PORT_REQUEST, /* __u8 */ + IFLA_PORT_RESPONSE, /* __u16, output only */ + __IFLA_PORT_MAX, +}; + +#define IFLA_PORT_MAX (__IFLA_PORT_MAX - 1) + +#define PORT_PROFILE_MAX 40 +#define PORT_UUID_MAX 16 +#define PORT_SELF_VF -1 + +enum { + PORT_REQUEST_PREASSOCIATE = 0, + PORT_REQUEST_PREASSOCIATE_RR, + PORT_REQUEST_ASSOCIATE, + PORT_REQUEST_DISASSOCIATE, +}; + +enum { + PORT_VDP_RESPONSE_SUCCESS = 0, + PORT_VDP_RESPONSE_INVALID_FORMAT, + PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES, + PORT_VDP_RESPONSE_UNUSED_VTID, + PORT_VDP_RESPONSE_VTID_VIOLATION, + PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION, + PORT_VDP_RESPONSE_OUT_OF_SYNC, + /* 0x08-0xFF reserved for future VDP use */ + PORT_PROFILE_RESPONSE_SUCCESS = 0x100, + PORT_PROFILE_RESPONSE_INPROGRESS, + PORT_PROFILE_RESPONSE_INVALID, + PORT_PROFILE_RESPONSE_BADSTATE, + PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES, + PORT_PROFILE_RESPONSE_ERROR, +}; + +struct ifla_port_vsi { + __u8 vsi_mgr_id; + __u8 vsi_type_id[3]; + __u8 vsi_type_version; + __u8 pad[3]; +}; + + +/* IPoIB section */ + +enum { + IFLA_IPOIB_UNSPEC, + IFLA_IPOIB_PKEY, + IFLA_IPOIB_MODE, + IFLA_IPOIB_UMCAST, + __IFLA_IPOIB_MAX +}; + +enum { + IPOIB_MODE_DATAGRAM = 0, /* using unreliable datagram QPs */ + IPOIB_MODE_CONNECTED = 1, /* using connected QPs */ +}; + +#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) + + +/* HSR section */ + +enum { + IFLA_HSR_UNSPEC, + IFLA_HSR_SLAVE1, + IFLA_HSR_SLAVE2, + IFLA_HSR_MULTICAST_SPEC, /* Last byte of supervision addr */ + IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */ + IFLA_HSR_SEQ_NR, + IFLA_HSR_VERSION, /* HSR version */ + __IFLA_HSR_MAX, +}; + +#define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1) + +/* STATS section */ + +struct if_stats_msg { + __u8 family; + __u8 pad1; + __u16 pad2; + __u32 ifindex; + __u32 filter_mask; +}; + +/* A stats attribute can be netdev specific or a global stat. + * For netdev stats, lets use the prefix IFLA_STATS_LINK_* + */ +enum { + IFLA_STATS_UNSPEC, /* also used as 64bit pad attribute */ + IFLA_STATS_LINK_64, + IFLA_STATS_LINK_XSTATS, + IFLA_STATS_LINK_XSTATS_SLAVE, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_STATS_AF_SPEC, + __IFLA_STATS_MAX, +}; + +#define IFLA_STATS_MAX (__IFLA_STATS_MAX - 1) + +#define IFLA_STATS_FILTER_BIT(ATTR) (1 << (ATTR - 1)) + +/* These are embedded into IFLA_STATS_LINK_XSTATS: + * [IFLA_STATS_LINK_XSTATS] + * -> [LINK_XSTATS_TYPE_xxx] + * -> [rtnl link type specific attributes] + */ +enum { + LINK_XSTATS_TYPE_UNSPEC, + LINK_XSTATS_TYPE_BRIDGE, + LINK_XSTATS_TYPE_BOND, + __LINK_XSTATS_TYPE_MAX +}; +#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1) + +/* These are stats embedded into IFLA_STATS_LINK_OFFLOAD_XSTATS */ +enum { + IFLA_OFFLOAD_XSTATS_UNSPEC, + IFLA_OFFLOAD_XSTATS_CPU_HIT, /* struct rtnl_link_stats64 */ + __IFLA_OFFLOAD_XSTATS_MAX +}; +#define IFLA_OFFLOAD_XSTATS_MAX (__IFLA_OFFLOAD_XSTATS_MAX - 1) + +/* XDP section */ + +#define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0) +#define XDP_FLAGS_SKB_MODE (1U << 1) +#define XDP_FLAGS_DRV_MODE (1U << 2) +#define XDP_FLAGS_HW_MODE (1U << 3) +#define XDP_FLAGS_MODES (XDP_FLAGS_SKB_MODE | \ + XDP_FLAGS_DRV_MODE | \ + XDP_FLAGS_HW_MODE) +#define XDP_FLAGS_MASK (XDP_FLAGS_UPDATE_IF_NOEXIST | \ + XDP_FLAGS_MODES) + +/* These are stored into IFLA_XDP_ATTACHED on dump. */ +enum { + XDP_ATTACHED_NONE = 0, + XDP_ATTACHED_DRV, + XDP_ATTACHED_SKB, + XDP_ATTACHED_HW, + XDP_ATTACHED_MULTI, +}; + +enum { + IFLA_XDP_UNSPEC, + IFLA_XDP_FD, + IFLA_XDP_ATTACHED, + IFLA_XDP_FLAGS, + IFLA_XDP_PROG_ID, + IFLA_XDP_DRV_PROG_ID, + IFLA_XDP_SKB_PROG_ID, + IFLA_XDP_HW_PROG_ID, + __IFLA_XDP_MAX, +}; + +#define IFLA_XDP_MAX (__IFLA_XDP_MAX - 1) + +enum { + IFLA_EVENT_NONE, + IFLA_EVENT_REBOOT, /* internal reset / reboot */ + IFLA_EVENT_FEATURES, /* change in offload features */ + IFLA_EVENT_BONDING_FAILOVER, /* change in active slave */ + IFLA_EVENT_NOTIFY_PEERS, /* re-sent grat. arp/ndisc */ + IFLA_EVENT_IGMP_RESEND, /* re-sent IGMP JOIN */ + IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */ +}; + +/* tun section */ + +enum { + IFLA_TUN_UNSPEC, + IFLA_TUN_OWNER, + IFLA_TUN_GROUP, + IFLA_TUN_TYPE, + IFLA_TUN_PI, + IFLA_TUN_VNET_HDR, + IFLA_TUN_PERSIST, + IFLA_TUN_MULTI_QUEUE, + IFLA_TUN_NUM_QUEUES, + IFLA_TUN_NUM_DISABLED_QUEUES, + __IFLA_TUN_MAX, +}; + +#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1) + +/* rmnet section */ + +#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0) +#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1) +#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2) +#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3) + +enum { + IFLA_RMNET_UNSPEC, + IFLA_RMNET_MUX_ID, + IFLA_RMNET_FLAGS, + __IFLA_RMNET_MAX, +}; + +#define IFLA_RMNET_MAX (__IFLA_RMNET_MAX - 1) + +struct ifla_rmnet_flags { + __u32 flags; + __u32 mask; +}; + +#endif /* _UAPI_LINUX_IF_LINK_H */ diff --git a/src/basic/linux/if_macsec.h b/src/basic/linux/if_macsec.h new file mode 100644 index 00000000..98e4d5d7 --- /dev/null +++ b/src/basic/linux/if_macsec.h @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * include/uapi/linux/if_macsec.h - MACsec device + * + * Copyright (c) 2015 Sabrina Dubroca + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _UAPI_MACSEC_H +#define _UAPI_MACSEC_H + +#include + +#define MACSEC_GENL_NAME "macsec" +#define MACSEC_GENL_VERSION 1 + +#define MACSEC_MAX_KEY_LEN 128 + +#define MACSEC_KEYID_LEN 16 + +/* cipher IDs as per IEEE802.1AEbn-2011 */ +#define MACSEC_CIPHER_ID_GCM_AES_128 0x0080C20001000001ULL +#define MACSEC_CIPHER_ID_GCM_AES_256 0x0080C20001000002ULL + +/* deprecated cipher ID for GCM-AES-128 */ +#define MACSEC_DEFAULT_CIPHER_ID 0x0080020001000001ULL +#define MACSEC_DEFAULT_CIPHER_ALT MACSEC_CIPHER_ID_GCM_AES_128 + +#define MACSEC_MIN_ICV_LEN 8 +#define MACSEC_MAX_ICV_LEN 32 +/* upper limit for ICV length as recommended by IEEE802.1AE-2006 */ +#define MACSEC_STD_ICV_LEN 16 + +enum macsec_attrs { + MACSEC_ATTR_UNSPEC, + MACSEC_ATTR_IFINDEX, /* u32, ifindex of the MACsec netdevice */ + MACSEC_ATTR_RXSC_CONFIG, /* config, nested macsec_rxsc_attrs */ + MACSEC_ATTR_SA_CONFIG, /* config, nested macsec_sa_attrs */ + MACSEC_ATTR_SECY, /* dump, nested macsec_secy_attrs */ + MACSEC_ATTR_TXSA_LIST, /* dump, nested, macsec_sa_attrs for each TXSA */ + MACSEC_ATTR_RXSC_LIST, /* dump, nested, macsec_rxsc_attrs for each RXSC */ + MACSEC_ATTR_TXSC_STATS, /* dump, nested, macsec_txsc_stats_attr */ + MACSEC_ATTR_SECY_STATS, /* dump, nested, macsec_secy_stats_attr */ + __MACSEC_ATTR_END, + NUM_MACSEC_ATTR = __MACSEC_ATTR_END, + MACSEC_ATTR_MAX = __MACSEC_ATTR_END - 1, +}; + +enum macsec_secy_attrs { + MACSEC_SECY_ATTR_UNSPEC, + MACSEC_SECY_ATTR_SCI, + MACSEC_SECY_ATTR_ENCODING_SA, + MACSEC_SECY_ATTR_WINDOW, + MACSEC_SECY_ATTR_CIPHER_SUITE, + MACSEC_SECY_ATTR_ICV_LEN, + MACSEC_SECY_ATTR_PROTECT, + MACSEC_SECY_ATTR_REPLAY, + MACSEC_SECY_ATTR_OPER, + MACSEC_SECY_ATTR_VALIDATE, + MACSEC_SECY_ATTR_ENCRYPT, + MACSEC_SECY_ATTR_INC_SCI, + MACSEC_SECY_ATTR_ES, + MACSEC_SECY_ATTR_SCB, + MACSEC_SECY_ATTR_PAD, + __MACSEC_SECY_ATTR_END, + NUM_MACSEC_SECY_ATTR = __MACSEC_SECY_ATTR_END, + MACSEC_SECY_ATTR_MAX = __MACSEC_SECY_ATTR_END - 1, +}; + +enum macsec_rxsc_attrs { + MACSEC_RXSC_ATTR_UNSPEC, + MACSEC_RXSC_ATTR_SCI, /* config/dump, u64 */ + MACSEC_RXSC_ATTR_ACTIVE, /* config/dump, u8 0..1 */ + MACSEC_RXSC_ATTR_SA_LIST, /* dump, nested */ + MACSEC_RXSC_ATTR_STATS, /* dump, nested, macsec_rxsc_stats_attr */ + MACSEC_RXSC_ATTR_PAD, + __MACSEC_RXSC_ATTR_END, + NUM_MACSEC_RXSC_ATTR = __MACSEC_RXSC_ATTR_END, + MACSEC_RXSC_ATTR_MAX = __MACSEC_RXSC_ATTR_END - 1, +}; + +enum macsec_sa_attrs { + MACSEC_SA_ATTR_UNSPEC, + MACSEC_SA_ATTR_AN, /* config/dump, u8 0..3 */ + MACSEC_SA_ATTR_ACTIVE, /* config/dump, u8 0..1 */ + MACSEC_SA_ATTR_PN, /* config/dump, u32 */ + MACSEC_SA_ATTR_KEY, /* config, data */ + MACSEC_SA_ATTR_KEYID, /* config/dump, 128-bit */ + MACSEC_SA_ATTR_STATS, /* dump, nested, macsec_sa_stats_attr */ + MACSEC_SA_ATTR_PAD, + __MACSEC_SA_ATTR_END, + NUM_MACSEC_SA_ATTR = __MACSEC_SA_ATTR_END, + MACSEC_SA_ATTR_MAX = __MACSEC_SA_ATTR_END - 1, +}; + +enum macsec_nl_commands { + MACSEC_CMD_GET_TXSC, + MACSEC_CMD_ADD_RXSC, + MACSEC_CMD_DEL_RXSC, + MACSEC_CMD_UPD_RXSC, + MACSEC_CMD_ADD_TXSA, + MACSEC_CMD_DEL_TXSA, + MACSEC_CMD_UPD_TXSA, + MACSEC_CMD_ADD_RXSA, + MACSEC_CMD_DEL_RXSA, + MACSEC_CMD_UPD_RXSA, +}; + +/* u64 per-RXSC stats */ +enum macsec_rxsc_stats_attr { + MACSEC_RXSC_STATS_ATTR_UNSPEC, + MACSEC_RXSC_STATS_ATTR_IN_OCTETS_VALIDATED, + MACSEC_RXSC_STATS_ATTR_IN_OCTETS_DECRYPTED, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNCHECKED, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_DELAYED, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_OK, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_INVALID, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_LATE, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_VALID, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_USING_SA, + MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNUSED_SA, + MACSEC_RXSC_STATS_ATTR_PAD, + __MACSEC_RXSC_STATS_ATTR_END, + NUM_MACSEC_RXSC_STATS_ATTR = __MACSEC_RXSC_STATS_ATTR_END, + MACSEC_RXSC_STATS_ATTR_MAX = __MACSEC_RXSC_STATS_ATTR_END - 1, +}; + +/* u32 per-{RX,TX}SA stats */ +enum macsec_sa_stats_attr { + MACSEC_SA_STATS_ATTR_UNSPEC, + MACSEC_SA_STATS_ATTR_IN_PKTS_OK, + MACSEC_SA_STATS_ATTR_IN_PKTS_INVALID, + MACSEC_SA_STATS_ATTR_IN_PKTS_NOT_VALID, + MACSEC_SA_STATS_ATTR_IN_PKTS_NOT_USING_SA, + MACSEC_SA_STATS_ATTR_IN_PKTS_UNUSED_SA, + MACSEC_SA_STATS_ATTR_OUT_PKTS_PROTECTED, + MACSEC_SA_STATS_ATTR_OUT_PKTS_ENCRYPTED, + __MACSEC_SA_STATS_ATTR_END, + NUM_MACSEC_SA_STATS_ATTR = __MACSEC_SA_STATS_ATTR_END, + MACSEC_SA_STATS_ATTR_MAX = __MACSEC_SA_STATS_ATTR_END - 1, +}; + +/* u64 per-TXSC stats */ +enum macsec_txsc_stats_attr { + MACSEC_TXSC_STATS_ATTR_UNSPEC, + MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED, + MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED, + MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED, + MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED, + MACSEC_TXSC_STATS_ATTR_PAD, + __MACSEC_TXSC_STATS_ATTR_END, + NUM_MACSEC_TXSC_STATS_ATTR = __MACSEC_TXSC_STATS_ATTR_END, + MACSEC_TXSC_STATS_ATTR_MAX = __MACSEC_TXSC_STATS_ATTR_END - 1, +}; + +/* u64 per-SecY stats */ +enum macsec_secy_stats_attr { + MACSEC_SECY_STATS_ATTR_UNSPEC, + MACSEC_SECY_STATS_ATTR_OUT_PKTS_UNTAGGED, + MACSEC_SECY_STATS_ATTR_IN_PKTS_UNTAGGED, + MACSEC_SECY_STATS_ATTR_OUT_PKTS_TOO_LONG, + MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_TAG, + MACSEC_SECY_STATS_ATTR_IN_PKTS_BAD_TAG, + MACSEC_SECY_STATS_ATTR_IN_PKTS_UNKNOWN_SCI, + MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_SCI, + MACSEC_SECY_STATS_ATTR_IN_PKTS_OVERRUN, + MACSEC_SECY_STATS_ATTR_PAD, + __MACSEC_SECY_STATS_ATTR_END, + NUM_MACSEC_SECY_STATS_ATTR = __MACSEC_SECY_STATS_ATTR_END, + MACSEC_SECY_STATS_ATTR_MAX = __MACSEC_SECY_STATS_ATTR_END - 1, +}; + +#endif /* _UAPI_MACSEC_H */ diff --git a/src/basic/linux/if_tun.h b/src/basic/linux/if_tun.h new file mode 100644 index 00000000..454ae31b --- /dev/null +++ b/src/basic/linux/if_tun.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Universal TUN/TAP device driver. + * Copyright (C) 1999-2000 Maxim Krasnyansky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _UAPI__IF_TUN_H +#define _UAPI__IF_TUN_H + +#include +#include +#include + +/* Read queue size */ +#define TUN_READQ_SIZE 500 +/* TUN device type flags: deprecated. Use IFF_TUN/IFF_TAP instead. */ +#define TUN_TUN_DEV IFF_TUN +#define TUN_TAP_DEV IFF_TAP +#define TUN_TYPE_MASK 0x000f + +/* Ioctl defines */ +#define TUNSETNOCSUM _IOW('T', 200, int) +#define TUNSETDEBUG _IOW('T', 201, int) +#define TUNSETIFF _IOW('T', 202, int) +#define TUNSETPERSIST _IOW('T', 203, int) +#define TUNSETOWNER _IOW('T', 204, int) +#define TUNSETLINK _IOW('T', 205, int) +#define TUNSETGROUP _IOW('T', 206, int) +#define TUNGETFEATURES _IOR('T', 207, unsigned int) +#define TUNSETOFFLOAD _IOW('T', 208, unsigned int) +#define TUNSETTXFILTER _IOW('T', 209, unsigned int) +#define TUNGETIFF _IOR('T', 210, unsigned int) +#define TUNGETSNDBUF _IOR('T', 211, int) +#define TUNSETSNDBUF _IOW('T', 212, int) +#define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog) +#define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog) +#define TUNGETVNETHDRSZ _IOR('T', 215, int) +#define TUNSETVNETHDRSZ _IOW('T', 216, int) +#define TUNSETQUEUE _IOW('T', 217, int) +#define TUNSETIFINDEX _IOW('T', 218, unsigned int) +#define TUNGETFILTER _IOR('T', 219, struct sock_fprog) +#define TUNSETVNETLE _IOW('T', 220, int) +#define TUNGETVNETLE _IOR('T', 221, int) +/* The TUNSETVNETBE and TUNGETVNETBE ioctls are for cross-endian support on + * little-endian hosts. Not all kernel configurations support them, but all + * configurations that support SET also support GET. + */ +#define TUNSETVNETBE _IOW('T', 222, int) +#define TUNGETVNETBE _IOR('T', 223, int) +#define TUNSETSTEERINGEBPF _IOR('T', 224, int) +#define TUNSETFILTEREBPF _IOR('T', 225, int) +#define TUNSETCARRIER _IOW('T', 226, int) +#define TUNGETDEVNETNS _IO('T', 227) + +/* TUNSETIFF ifr flags */ +#define IFF_TUN 0x0001 +#define IFF_TAP 0x0002 +#define IFF_NAPI 0x0010 +#define IFF_NAPI_FRAGS 0x0020 +#define IFF_NO_PI 0x1000 +/* This flag has no real effect */ +#define IFF_ONE_QUEUE 0x2000 +#define IFF_VNET_HDR 0x4000 +#define IFF_TUN_EXCL 0x8000 +#define IFF_MULTI_QUEUE 0x0100 +#define IFF_ATTACH_QUEUE 0x0200 +#define IFF_DETACH_QUEUE 0x0400 +/* read-only flag */ +#define IFF_PERSIST 0x0800 +#define IFF_NOFILTER 0x1000 + +/* Socket options */ +#define TUN_TX_TIMESTAMP 1 + +/* Features for GSO (TUNSETOFFLOAD). */ +#define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ +#define TUN_F_TSO4 0x02 /* I can handle TSO for IPv4 packets */ +#define TUN_F_TSO6 0x04 /* I can handle TSO for IPv6 packets */ +#define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ +#define TUN_F_UFO 0x10 /* I can handle UFO packets */ + +/* Protocol info prepended to the packets (when IFF_NO_PI is not set) */ +#define TUN_PKT_STRIP 0x0001 +struct tun_pi { + __u16 flags; + __be16 proto; +}; + +/* + * Filter spec (used for SETXXFILTER ioctls) + * This stuff is applicable only to the TAP (Ethernet) devices. + * If the count is zero the filter is disabled and the driver accepts + * all packets (promisc mode). + * If the filter is enabled in order to accept broadcast packets + * broadcast addr must be explicitly included in the addr list. + */ +#define TUN_FLT_ALLMULTI 0x0001 /* Accept all multicast packets */ +struct tun_filter { + __u16 flags; /* TUN_FLT_ flags see above */ + __u16 count; /* Number of addresses */ + __u8 addr[0][ETH_ALEN]; +}; + +#endif /* _UAPI__IF_TUN_H */ diff --git a/src/basic/linux/if_tunnel.h b/src/basic/linux/if_tunnel.h new file mode 100644 index 00000000..7d910553 --- /dev/null +++ b/src/basic/linux/if_tunnel.h @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_IF_TUNNEL_H_ +#define _UAPI_IF_TUNNEL_H_ + +#include +#include +#include +#include +#include + + +#define SIOCGETTUNNEL (SIOCDEVPRIVATE + 0) +#define SIOCADDTUNNEL (SIOCDEVPRIVATE + 1) +#define SIOCDELTUNNEL (SIOCDEVPRIVATE + 2) +#define SIOCCHGTUNNEL (SIOCDEVPRIVATE + 3) +#define SIOCGETPRL (SIOCDEVPRIVATE + 4) +#define SIOCADDPRL (SIOCDEVPRIVATE + 5) +#define SIOCDELPRL (SIOCDEVPRIVATE + 6) +#define SIOCCHGPRL (SIOCDEVPRIVATE + 7) +#define SIOCGET6RD (SIOCDEVPRIVATE + 8) +#define SIOCADD6RD (SIOCDEVPRIVATE + 9) +#define SIOCDEL6RD (SIOCDEVPRIVATE + 10) +#define SIOCCHG6RD (SIOCDEVPRIVATE + 11) + +#define GRE_CSUM __cpu_to_be16(0x8000) +#define GRE_ROUTING __cpu_to_be16(0x4000) +#define GRE_KEY __cpu_to_be16(0x2000) +#define GRE_SEQ __cpu_to_be16(0x1000) +#define GRE_STRICT __cpu_to_be16(0x0800) +#define GRE_REC __cpu_to_be16(0x0700) +#define GRE_ACK __cpu_to_be16(0x0080) +#define GRE_FLAGS __cpu_to_be16(0x0078) +#define GRE_VERSION __cpu_to_be16(0x0007) + +#define GRE_IS_CSUM(f) ((f) & GRE_CSUM) +#define GRE_IS_ROUTING(f) ((f) & GRE_ROUTING) +#define GRE_IS_KEY(f) ((f) & GRE_KEY) +#define GRE_IS_SEQ(f) ((f) & GRE_SEQ) +#define GRE_IS_STRICT(f) ((f) & GRE_STRICT) +#define GRE_IS_REC(f) ((f) & GRE_REC) +#define GRE_IS_ACK(f) ((f) & GRE_ACK) + +#define GRE_VERSION_0 __cpu_to_be16(0x0000) +#define GRE_VERSION_1 __cpu_to_be16(0x0001) +#define GRE_PROTO_PPP __cpu_to_be16(0x880b) +#define GRE_PPTP_KEY_MASK __cpu_to_be32(0xffff) + +struct ip_tunnel_parm { + char name[IFNAMSIZ]; + int link; + __be16 i_flags; + __be16 o_flags; + __be32 i_key; + __be32 o_key; + struct iphdr iph; +}; + +enum { + IFLA_IPTUN_UNSPEC, + IFLA_IPTUN_LINK, + IFLA_IPTUN_LOCAL, + IFLA_IPTUN_REMOTE, + IFLA_IPTUN_TTL, + IFLA_IPTUN_TOS, + IFLA_IPTUN_ENCAP_LIMIT, + IFLA_IPTUN_FLOWINFO, + IFLA_IPTUN_FLAGS, + IFLA_IPTUN_PROTO, + IFLA_IPTUN_PMTUDISC, + IFLA_IPTUN_6RD_PREFIX, + IFLA_IPTUN_6RD_RELAY_PREFIX, + IFLA_IPTUN_6RD_PREFIXLEN, + IFLA_IPTUN_6RD_RELAY_PREFIXLEN, + IFLA_IPTUN_ENCAP_TYPE, + IFLA_IPTUN_ENCAP_FLAGS, + IFLA_IPTUN_ENCAP_SPORT, + IFLA_IPTUN_ENCAP_DPORT, + IFLA_IPTUN_COLLECT_METADATA, + IFLA_IPTUN_FWMARK, + __IFLA_IPTUN_MAX, +}; +#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) + +enum tunnel_encap_types { + TUNNEL_ENCAP_NONE, + TUNNEL_ENCAP_FOU, + TUNNEL_ENCAP_GUE, + TUNNEL_ENCAP_MPLS, +}; + +#define TUNNEL_ENCAP_FLAG_CSUM (1<<0) +#define TUNNEL_ENCAP_FLAG_CSUM6 (1<<1) +#define TUNNEL_ENCAP_FLAG_REMCSUM (1<<2) + +/* SIT-mode i_flags */ +#define SIT_ISATAP 0x0001 + +struct ip_tunnel_prl { + __be32 addr; + __u16 flags; + __u16 __reserved; + __u32 datalen; + __u32 __reserved2; + /* data follows */ +}; + +/* PRL flags */ +#define PRL_DEFAULT 0x0001 + +struct ip_tunnel_6rd { + struct in6_addr prefix; + __be32 relay_prefix; + __u16 prefixlen; + __u16 relay_prefixlen; +}; + +enum { + IFLA_GRE_UNSPEC, + IFLA_GRE_LINK, + IFLA_GRE_IFLAGS, + IFLA_GRE_OFLAGS, + IFLA_GRE_IKEY, + IFLA_GRE_OKEY, + IFLA_GRE_LOCAL, + IFLA_GRE_REMOTE, + IFLA_GRE_TTL, + IFLA_GRE_TOS, + IFLA_GRE_PMTUDISC, + IFLA_GRE_ENCAP_LIMIT, + IFLA_GRE_FLOWINFO, + IFLA_GRE_FLAGS, + IFLA_GRE_ENCAP_TYPE, + IFLA_GRE_ENCAP_FLAGS, + IFLA_GRE_ENCAP_SPORT, + IFLA_GRE_ENCAP_DPORT, + IFLA_GRE_COLLECT_METADATA, + IFLA_GRE_IGNORE_DF, + IFLA_GRE_FWMARK, + IFLA_GRE_ERSPAN_INDEX, + IFLA_GRE_ERSPAN_VER, + IFLA_GRE_ERSPAN_DIR, + IFLA_GRE_ERSPAN_HWID, + __IFLA_GRE_MAX, +}; + +#define IFLA_GRE_MAX (__IFLA_GRE_MAX - 1) + +/* VTI-mode i_flags */ +#define VTI_ISVTI ((__force __be16)0x0001) + +enum { + IFLA_VTI_UNSPEC, + IFLA_VTI_LINK, + IFLA_VTI_IKEY, + IFLA_VTI_OKEY, + IFLA_VTI_LOCAL, + IFLA_VTI_REMOTE, + IFLA_VTI_FWMARK, + __IFLA_VTI_MAX, +}; + +#define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1) + +#define TUNNEL_CSUM __cpu_to_be16(0x01) +#define TUNNEL_ROUTING __cpu_to_be16(0x02) +#define TUNNEL_KEY __cpu_to_be16(0x04) +#define TUNNEL_SEQ __cpu_to_be16(0x08) +#define TUNNEL_STRICT __cpu_to_be16(0x10) +#define TUNNEL_REC __cpu_to_be16(0x20) +#define TUNNEL_VERSION __cpu_to_be16(0x40) +#define TUNNEL_NO_KEY __cpu_to_be16(0x80) +#define TUNNEL_DONT_FRAGMENT __cpu_to_be16(0x0100) +#define TUNNEL_OAM __cpu_to_be16(0x0200) +#define TUNNEL_CRIT_OPT __cpu_to_be16(0x0400) +#define TUNNEL_GENEVE_OPT __cpu_to_be16(0x0800) +#define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000) +#define TUNNEL_NOCACHE __cpu_to_be16(0x2000) +#define TUNNEL_ERSPAN_OPT __cpu_to_be16(0x4000) + +#define TUNNEL_OPTIONS_PRESENT \ + (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT) + +#endif /* _UAPI_IF_TUNNEL_H_ */ diff --git a/src/basic/linux/in.h b/src/basic/linux/in.h new file mode 100644 index 00000000..e7ad9d35 --- /dev/null +++ b/src/basic/linux/in.h @@ -0,0 +1,306 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions of the Internet Protocol. + * + * Version: @(#)in.h 1.0.1 04/21/93 + * + * Authors: Original taken from the GNU Project file. + * Fred N. van Kempen, + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _UAPI_LINUX_IN_H +#define _UAPI_LINUX_IN_H + +#include +#include +#include + +#if __UAPI_DEF_IN_IPPROTO +/* Standard well-defined IP protocols. */ +enum { + IPPROTO_IP = 0, /* Dummy protocol for TCP */ +#define IPPROTO_IP IPPROTO_IP + IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ +#define IPPROTO_ICMP IPPROTO_ICMP + IPPROTO_IGMP = 2, /* Internet Group Management Protocol */ +#define IPPROTO_IGMP IPPROTO_IGMP + IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94) */ +#define IPPROTO_IPIP IPPROTO_IPIP + IPPROTO_TCP = 6, /* Transmission Control Protocol */ +#define IPPROTO_TCP IPPROTO_TCP + IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ +#define IPPROTO_EGP IPPROTO_EGP + IPPROTO_PUP = 12, /* PUP protocol */ +#define IPPROTO_PUP IPPROTO_PUP + IPPROTO_UDP = 17, /* User Datagram Protocol */ +#define IPPROTO_UDP IPPROTO_UDP + IPPROTO_IDP = 22, /* XNS IDP protocol */ +#define IPPROTO_IDP IPPROTO_IDP + IPPROTO_TP = 29, /* SO Transport Protocol Class 4 */ +#define IPPROTO_TP IPPROTO_TP + IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol */ +#define IPPROTO_DCCP IPPROTO_DCCP + IPPROTO_IPV6 = 41, /* IPv6-in-IPv4 tunnelling */ +#define IPPROTO_IPV6 IPPROTO_IPV6 + IPPROTO_RSVP = 46, /* RSVP Protocol */ +#define IPPROTO_RSVP IPPROTO_RSVP + IPPROTO_GRE = 47, /* Cisco GRE tunnels (rfc 1701,1702) */ +#define IPPROTO_GRE IPPROTO_GRE + IPPROTO_ESP = 50, /* Encapsulation Security Payload protocol */ +#define IPPROTO_ESP IPPROTO_ESP + IPPROTO_AH = 51, /* Authentication Header protocol */ +#define IPPROTO_AH IPPROTO_AH + IPPROTO_MTP = 92, /* Multicast Transport Protocol */ +#define IPPROTO_MTP IPPROTO_MTP + IPPROTO_BEETPH = 94, /* IP option pseudo header for BEET */ +#define IPPROTO_BEETPH IPPROTO_BEETPH + IPPROTO_ENCAP = 98, /* Encapsulation Header */ +#define IPPROTO_ENCAP IPPROTO_ENCAP + IPPROTO_PIM = 103, /* Protocol Independent Multicast */ +#define IPPROTO_PIM IPPROTO_PIM + IPPROTO_COMP = 108, /* Compression Header Protocol */ +#define IPPROTO_COMP IPPROTO_COMP + IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ +#define IPPROTO_SCTP IPPROTO_SCTP + IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */ +#define IPPROTO_UDPLITE IPPROTO_UDPLITE + IPPROTO_MPLS = 137, /* MPLS in IP (RFC 4023) */ +#define IPPROTO_MPLS IPPROTO_MPLS + IPPROTO_RAW = 255, /* Raw IP packets */ +#define IPPROTO_RAW IPPROTO_RAW + IPPROTO_MAX +}; +#endif + +#if __UAPI_DEF_IN_ADDR +/* Internet address. */ +struct in_addr { + __be32 s_addr; +}; +#endif + +#define IP_TOS 1 +#define IP_TTL 2 +#define IP_HDRINCL 3 +#define IP_OPTIONS 4 +#define IP_ROUTER_ALERT 5 +#define IP_RECVOPTS 6 +#define IP_RETOPTS 7 +#define IP_PKTINFO 8 +#define IP_PKTOPTIONS 9 +#define IP_MTU_DISCOVER 10 +#define IP_RECVERR 11 +#define IP_RECVTTL 12 +#define IP_RECVTOS 13 +#define IP_MTU 14 +#define IP_FREEBIND 15 +#define IP_IPSEC_POLICY 16 +#define IP_XFRM_POLICY 17 +#define IP_PASSSEC 18 +#define IP_TRANSPARENT 19 + +/* BSD compatibility */ +#define IP_RECVRETOPTS IP_RETOPTS + +/* TProxy original addresses */ +#define IP_ORIGDSTADDR 20 +#define IP_RECVORIGDSTADDR IP_ORIGDSTADDR + +#define IP_MINTTL 21 +#define IP_NODEFRAG 22 +#define IP_CHECKSUM 23 +#define IP_BIND_ADDRESS_NO_PORT 24 +#define IP_RECVFRAGSIZE 25 + +/* IP_MTU_DISCOVER values */ +#define IP_PMTUDISC_DONT 0 /* Never send DF frames */ +#define IP_PMTUDISC_WANT 1 /* Use per route hints */ +#define IP_PMTUDISC_DO 2 /* Always DF */ +#define IP_PMTUDISC_PROBE 3 /* Ignore dst pmtu */ +/* Always use interface mtu (ignores dst pmtu) but don't set DF flag. + * Also incoming ICMP frag_needed notifications will be ignored on + * this socket to prevent accepting spoofed ones. + */ +#define IP_PMTUDISC_INTERFACE 4 +/* weaker version of IP_PMTUDISC_INTERFACE, which allos packets to get + * fragmented if they exeed the interface mtu + */ +#define IP_PMTUDISC_OMIT 5 + +#define IP_MULTICAST_IF 32 +#define IP_MULTICAST_TTL 33 +#define IP_MULTICAST_LOOP 34 +#define IP_ADD_MEMBERSHIP 35 +#define IP_DROP_MEMBERSHIP 36 +#define IP_UNBLOCK_SOURCE 37 +#define IP_BLOCK_SOURCE 38 +#define IP_ADD_SOURCE_MEMBERSHIP 39 +#define IP_DROP_SOURCE_MEMBERSHIP 40 +#define IP_MSFILTER 41 +#define MCAST_JOIN_GROUP 42 +#define MCAST_BLOCK_SOURCE 43 +#define MCAST_UNBLOCK_SOURCE 44 +#define MCAST_LEAVE_GROUP 45 +#define MCAST_JOIN_SOURCE_GROUP 46 +#define MCAST_LEAVE_SOURCE_GROUP 47 +#define MCAST_MSFILTER 48 +#define IP_MULTICAST_ALL 49 +#define IP_UNICAST_IF 50 + +#define MCAST_EXCLUDE 0 +#define MCAST_INCLUDE 1 + +/* These need to appear somewhere around here */ +#define IP_DEFAULT_MULTICAST_TTL 1 +#define IP_DEFAULT_MULTICAST_LOOP 1 + +/* Request struct for multicast socket ops */ + +#if __UAPI_DEF_IP_MREQ +struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +}; + +struct ip_mreqn { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_address; /* local IP address of interface */ + int imr_ifindex; /* Interface index */ +}; + +struct ip_mreq_source { + __be32 imr_multiaddr; + __be32 imr_interface; + __be32 imr_sourceaddr; +}; + +struct ip_msfilter { + __be32 imsf_multiaddr; + __be32 imsf_interface; + __u32 imsf_fmode; + __u32 imsf_numsrc; + __be32 imsf_slist[1]; +}; + +#define IP_MSFILTER_SIZE(numsrc) \ + (sizeof(struct ip_msfilter) - sizeof(__u32) \ + + (numsrc) * sizeof(__u32)) + +struct group_req { + __u32 gr_interface; /* interface index */ + struct __kernel_sockaddr_storage gr_group; /* group address */ +}; + +struct group_source_req { + __u32 gsr_interface; /* interface index */ + struct __kernel_sockaddr_storage gsr_group; /* group address */ + struct __kernel_sockaddr_storage gsr_source; /* source address */ +}; + +struct group_filter { + __u32 gf_interface; /* interface index */ + struct __kernel_sockaddr_storage gf_group; /* multicast address */ + __u32 gf_fmode; /* filter mode */ + __u32 gf_numsrc; /* number of sources */ + struct __kernel_sockaddr_storage gf_slist[1]; /* interface index */ +}; + +#define GROUP_FILTER_SIZE(numsrc) \ + (sizeof(struct group_filter) - sizeof(struct __kernel_sockaddr_storage) \ + + (numsrc) * sizeof(struct __kernel_sockaddr_storage)) +#endif + +#if __UAPI_DEF_IN_PKTINFO +struct in_pktinfo { + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; +}; +#endif + +/* Structure describing an Internet (IP) socket address. */ +#if __UAPI_DEF_SOCKADDR_IN +#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ +struct sockaddr_in { + __kernel_sa_family_t sin_family; /* Address family */ + __be16 sin_port; /* Port number */ + struct in_addr sin_addr; /* Internet address */ + + /* Pad to size of `struct sockaddr'. */ + unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - + sizeof(unsigned short int) - sizeof(struct in_addr)]; +}; +#define sin_zero __pad /* for BSD UNIX comp. -FvK */ +#endif + +#if __UAPI_DEF_IN_CLASS +/* + * Definitions of the bits in an Internet address integer. + * On subnets, host and network parts are found according + * to the subnet mask, not these masks. + */ +#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) + +#define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000) +#define IN_MULTICAST(a) IN_CLASSD(a) +#define IN_MULTICAST_NET 0xe0000000 + +#define IN_BADCLASS(a) (((long int) (a) ) == (long int)0xffffffff) +#define IN_EXPERIMENTAL(a) IN_BADCLASS((a)) + +#define IN_CLASSE(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000) +#define IN_CLASSE_NET 0xffffffff +#define IN_CLASSE_NSHIFT 0 + +/* Address to accept any incoming messages. */ +#define INADDR_ANY ((unsigned long int) 0x00000000) + +/* Address to send to all hosts. */ +#define INADDR_BROADCAST ((unsigned long int) 0xffffffff) + +/* Address indicating an error return. */ +#define INADDR_NONE ((unsigned long int) 0xffffffff) + +/* Network number for local host loopback. */ +#define IN_LOOPBACKNET 127 + +/* Address to loopback in software to local host. */ +#define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */ +#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000) + +/* Defines for Multicast INADDR */ +#define INADDR_UNSPEC_GROUP 0xe0000000U /* 224.0.0.0 */ +#define INADDR_ALLHOSTS_GROUP 0xe0000001U /* 224.0.0.1 */ +#define INADDR_ALLRTRS_GROUP 0xe0000002U /* 224.0.0.2 */ +#define INADDR_ALLSNOOPERS_GROUP 0xe000006aU /* 224.0.0.106 */ +#define INADDR_MAX_LOCAL_GROUP 0xe00000ffU /* 224.0.0.255 */ +#endif + +/* contains the htonl type stuff.. */ +#include + + +#endif /* _UAPI_LINUX_IN_H */ diff --git a/src/basic/linux/in6.h b/src/basic/linux/in6.h new file mode 100644 index 00000000..9f2273a0 --- /dev/null +++ b/src/basic/linux/in6.h @@ -0,0 +1,300 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Types and definitions for AF_INET6 + * Linux INET6 implementation + * + * Authors: + * Pedro Roque + * + * Sources: + * IPv6 Program Interfaces for BSD Systems + * + * + * Advanced Sockets API for IPv6 + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _UAPI_LINUX_IN6_H +#define _UAPI_LINUX_IN6_H + +#include +#include + +/* + * IPv6 address structure + */ + +#if __UAPI_DEF_IN6_ADDR +struct in6_addr { + union { + __u8 u6_addr8[16]; +#if __UAPI_DEF_IN6_ADDR_ALT + __be16 u6_addr16[8]; + __be32 u6_addr32[4]; +#endif + } in6_u; +#define s6_addr in6_u.u6_addr8 +#if __UAPI_DEF_IN6_ADDR_ALT +#define s6_addr16 in6_u.u6_addr16 +#define s6_addr32 in6_u.u6_addr32 +#endif +}; +#endif /* __UAPI_DEF_IN6_ADDR */ + +#if __UAPI_DEF_SOCKADDR_IN6 +struct sockaddr_in6 { + unsigned short int sin6_family; /* AF_INET6 */ + __be16 sin6_port; /* Transport layer port # */ + __be32 sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + __u32 sin6_scope_id; /* scope id (new in RFC2553) */ +}; +#endif /* __UAPI_DEF_SOCKADDR_IN6 */ + +#if __UAPI_DEF_IPV6_MREQ +struct ipv6_mreq { + /* IPv6 multicast address of group */ + struct in6_addr ipv6mr_multiaddr; + + /* local IPv6 address of interface */ + int ipv6mr_ifindex; +}; +#endif /* __UAPI_DEF_IVP6_MREQ */ + +#define ipv6mr_acaddr ipv6mr_multiaddr + +struct in6_flowlabel_req { + struct in6_addr flr_dst; + __be32 flr_label; + __u8 flr_action; + __u8 flr_share; + __u16 flr_flags; + __u16 flr_expires; + __u16 flr_linger; + __u32 __flr_pad; + /* Options in format of IPV6_PKTOPTIONS */ +}; + +#define IPV6_FL_A_GET 0 +#define IPV6_FL_A_PUT 1 +#define IPV6_FL_A_RENEW 2 + +#define IPV6_FL_F_CREATE 1 +#define IPV6_FL_F_EXCL 2 +#define IPV6_FL_F_REFLECT 4 +#define IPV6_FL_F_REMOTE 8 + +#define IPV6_FL_S_NONE 0 +#define IPV6_FL_S_EXCL 1 +#define IPV6_FL_S_PROCESS 2 +#define IPV6_FL_S_USER 3 +#define IPV6_FL_S_ANY 255 + + +/* + * Bitmask constant declarations to help applications select out the + * flow label and priority fields. + * + * Note that this are in host byte order while the flowinfo field of + * sockaddr_in6 is in network byte order. + */ + +#define IPV6_FLOWINFO_FLOWLABEL 0x000fffff +#define IPV6_FLOWINFO_PRIORITY 0x0ff00000 + +/* These definitions are obsolete */ +#define IPV6_PRIORITY_UNCHARACTERIZED 0x0000 +#define IPV6_PRIORITY_FILLER 0x0100 +#define IPV6_PRIORITY_UNATTENDED 0x0200 +#define IPV6_PRIORITY_RESERVED1 0x0300 +#define IPV6_PRIORITY_BULK 0x0400 +#define IPV6_PRIORITY_RESERVED2 0x0500 +#define IPV6_PRIORITY_INTERACTIVE 0x0600 +#define IPV6_PRIORITY_CONTROL 0x0700 +#define IPV6_PRIORITY_8 0x0800 +#define IPV6_PRIORITY_9 0x0900 +#define IPV6_PRIORITY_10 0x0a00 +#define IPV6_PRIORITY_11 0x0b00 +#define IPV6_PRIORITY_12 0x0c00 +#define IPV6_PRIORITY_13 0x0d00 +#define IPV6_PRIORITY_14 0x0e00 +#define IPV6_PRIORITY_15 0x0f00 + +/* + * IPV6 extension headers + */ +#if __UAPI_DEF_IPPROTO_V6 +#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ +#define IPPROTO_ROUTING 43 /* IPv6 routing header */ +#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 */ +#define IPPROTO_NONE 59 /* IPv6 no next header */ +#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ +#define IPPROTO_MH 135 /* IPv6 mobility header */ +#endif /* __UAPI_DEF_IPPROTO_V6 */ + +/* + * IPv6 TLV options. + */ +#define IPV6_TLV_PAD1 0 +#define IPV6_TLV_PADN 1 +#define IPV6_TLV_ROUTERALERT 5 +#define IPV6_TLV_CALIPSO 7 /* RFC 5570 */ +#define IPV6_TLV_JUMBO 194 +#define IPV6_TLV_HAO 201 /* home address option */ + +/* + * IPV6 socket options + */ +#if __UAPI_DEF_IPV6_OPTIONS +#define IPV6_ADDRFORM 1 +#define IPV6_2292PKTINFO 2 +#define IPV6_2292HOPOPTS 3 +#define IPV6_2292DSTOPTS 4 +#define IPV6_2292RTHDR 5 +#define IPV6_2292PKTOPTIONS 6 +#define IPV6_CHECKSUM 7 +#define IPV6_2292HOPLIMIT 8 +#define IPV6_NEXTHOP 9 +#define IPV6_AUTHHDR 10 /* obsolete */ +#define IPV6_FLOWINFO 11 + +#define IPV6_UNICAST_HOPS 16 +#define IPV6_MULTICAST_IF 17 +#define IPV6_MULTICAST_HOPS 18 +#define IPV6_MULTICAST_LOOP 19 +#define IPV6_ADD_MEMBERSHIP 20 +#define IPV6_DROP_MEMBERSHIP 21 +#define IPV6_ROUTER_ALERT 22 +#define IPV6_MTU_DISCOVER 23 +#define IPV6_MTU 24 +#define IPV6_RECVERR 25 +#define IPV6_V6ONLY 26 +#define IPV6_JOIN_ANYCAST 27 +#define IPV6_LEAVE_ANYCAST 28 +#define IPV6_MULTICAST_ALL 29 +#define IPV6_ROUTER_ALERT_ISOLATE 30 + +/* IPV6_MTU_DISCOVER values */ +#define IPV6_PMTUDISC_DONT 0 +#define IPV6_PMTUDISC_WANT 1 +#define IPV6_PMTUDISC_DO 2 +#define IPV6_PMTUDISC_PROBE 3 +/* same as IPV6_PMTUDISC_PROBE, provided for symetry with IPv4 + * also see comments on IP_PMTUDISC_INTERFACE + */ +#define IPV6_PMTUDISC_INTERFACE 4 +/* weaker version of IPV6_PMTUDISC_INTERFACE, which allows packets to + * get fragmented if they exceed the interface mtu + */ +#define IPV6_PMTUDISC_OMIT 5 + +/* Flowlabel */ +#define IPV6_FLOWLABEL_MGR 32 +#define IPV6_FLOWINFO_SEND 33 + +#define IPV6_IPSEC_POLICY 34 +#define IPV6_XFRM_POLICY 35 +#define IPV6_HDRINCL 36 +#endif + +/* + * Multicast: + * Following socket options are shared between IPv4 and IPv6. + * + * MCAST_JOIN_GROUP 42 + * MCAST_BLOCK_SOURCE 43 + * MCAST_UNBLOCK_SOURCE 44 + * MCAST_LEAVE_GROUP 45 + * MCAST_JOIN_SOURCE_GROUP 46 + * MCAST_LEAVE_SOURCE_GROUP 47 + * MCAST_MSFILTER 48 + */ + +/* + * Advanced API (RFC3542) (1) + * + * Note: IPV6_RECVRTHDRDSTOPTS does not exist. see net/ipv6/datagram.c. + */ + +#define IPV6_RECVPKTINFO 49 +#define IPV6_PKTINFO 50 +#define IPV6_RECVHOPLIMIT 51 +#define IPV6_HOPLIMIT 52 +#define IPV6_RECVHOPOPTS 53 +#define IPV6_HOPOPTS 54 +#define IPV6_RTHDRDSTOPTS 55 +#define IPV6_RECVRTHDR 56 +#define IPV6_RTHDR 57 +#define IPV6_RECVDSTOPTS 58 +#define IPV6_DSTOPTS 59 +#define IPV6_RECVPATHMTU 60 +#define IPV6_PATHMTU 61 +#define IPV6_DONTFRAG 62 +#if 0 /* not yet */ +#define IPV6_USE_MIN_MTU 63 +#endif + +/* + * Netfilter (1) + * + * Following socket options are used in ip6_tables; + * see include/linux/netfilter_ipv6/ip6_tables.h. + * + * IP6T_SO_SET_REPLACE / IP6T_SO_GET_INFO 64 + * IP6T_SO_SET_ADD_COUNTERS / IP6T_SO_GET_ENTRIES 65 + */ + +/* + * Advanced API (RFC3542) (2) + */ +#define IPV6_RECVTCLASS 66 +#define IPV6_TCLASS 67 + +/* + * Netfilter (2) + * + * Following socket options are used in ip6_tables; + * see include/linux/netfilter_ipv6/ip6_tables.h. + * + * IP6T_SO_GET_REVISION_MATCH 68 + * IP6T_SO_GET_REVISION_TARGET 69 + * IP6T_SO_ORIGINAL_DST 80 + */ + +#define IPV6_AUTOFLOWLABEL 70 +/* RFC5014: Source address selection */ +#define IPV6_ADDR_PREFERENCES 72 + +#define IPV6_PREFER_SRC_TMP 0x0001 +#define IPV6_PREFER_SRC_PUBLIC 0x0002 +#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100 +#define IPV6_PREFER_SRC_COA 0x0004 +#define IPV6_PREFER_SRC_HOME 0x0400 +#define IPV6_PREFER_SRC_CGA 0x0008 +#define IPV6_PREFER_SRC_NONCGA 0x0800 + +/* RFC5082: Generalized Ttl Security Mechanism */ +#define IPV6_MINHOPCOUNT 73 + +#define IPV6_ORIGDSTADDR 74 +#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR +#define IPV6_TRANSPARENT 75 +#define IPV6_UNICAST_IF 76 +#define IPV6_RECVFRAGSIZE 77 +#define IPV6_FREEBIND 78 + +/* + * Multicast Routing: + * see include/uapi/linux/mroute6.h. + * + * MRT6_BASE 200 + * ... + * MRT6_MAX + */ +#endif /* _UAPI_LINUX_IN6_H */ diff --git a/src/basic/linux/l2tp.h b/src/basic/linux/l2tp.h new file mode 100644 index 00000000..61158f5a --- /dev/null +++ b/src/basic/linux/l2tp.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * L2TP-over-IP socket for L2TPv3. + * + * Author: James Chapman + */ + +#ifndef _UAPI_LINUX_L2TP_H_ +#define _UAPI_LINUX_L2TP_H_ + +#include +#include +#include +#include + +#define IPPROTO_L2TP 115 + +/** + * struct sockaddr_l2tpip - the sockaddr structure for L2TP-over-IP sockets + * @l2tp_family: address family number AF_L2TPIP. + * @l2tp_addr: protocol specific address information + * @l2tp_conn_id: connection id of tunnel + */ +#define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ +struct sockaddr_l2tpip { + /* The first fields must match struct sockaddr_in */ + __kernel_sa_family_t l2tp_family; /* AF_INET */ + __be16 l2tp_unused; /* INET port number (unused) */ + struct in_addr l2tp_addr; /* Internet address */ + + __u32 l2tp_conn_id; /* Connection ID of tunnel */ + + /* Pad to size of `struct sockaddr'. */ + unsigned char __pad[__SOCK_SIZE__ - + sizeof(__kernel_sa_family_t) - + sizeof(__be16) - sizeof(struct in_addr) - + sizeof(__u32)]; +}; + +/** + * struct sockaddr_l2tpip6 - the sockaddr structure for L2TP-over-IPv6 sockets + * @l2tp_family: address family number AF_L2TPIP. + * @l2tp_addr: protocol specific address information + * @l2tp_conn_id: connection id of tunnel + */ +struct sockaddr_l2tpip6 { + /* The first fields must match struct sockaddr_in6 */ + __kernel_sa_family_t l2tp_family; /* AF_INET6 */ + __be16 l2tp_unused; /* INET port number (unused) */ + __be32 l2tp_flowinfo; /* IPv6 flow information */ + struct in6_addr l2tp_addr; /* IPv6 address */ + __u32 l2tp_scope_id; /* scope id (new in RFC2553) */ + __u32 l2tp_conn_id; /* Connection ID of tunnel */ +}; + +/***************************************************************************** + * NETLINK_GENERIC netlink family. + *****************************************************************************/ + +/* + * Commands. + * Valid TLVs of each command are:- + * TUNNEL_CREATE - CONN_ID, pw_type, netns, ifname, ipinfo, udpinfo, udpcsum + * TUNNEL_DELETE - CONN_ID + * TUNNEL_MODIFY - CONN_ID, udpcsum + * TUNNEL_GETSTATS - CONN_ID, (stats) + * TUNNEL_GET - CONN_ID, (...) + * SESSION_CREATE - SESSION_ID, PW_TYPE, cookie, peer_cookie, l2spec + * SESSION_DELETE - SESSION_ID + * SESSION_MODIFY - SESSION_ID + * SESSION_GET - SESSION_ID, (...) + * SESSION_GETSTATS - SESSION_ID, (stats) + * + */ +enum { + L2TP_CMD_NOOP, + L2TP_CMD_TUNNEL_CREATE, + L2TP_CMD_TUNNEL_DELETE, + L2TP_CMD_TUNNEL_MODIFY, + L2TP_CMD_TUNNEL_GET, + L2TP_CMD_SESSION_CREATE, + L2TP_CMD_SESSION_DELETE, + L2TP_CMD_SESSION_MODIFY, + L2TP_CMD_SESSION_GET, + __L2TP_CMD_MAX, +}; + +#define L2TP_CMD_MAX (__L2TP_CMD_MAX - 1) + +/* + * ATTR types defined for L2TP + */ +enum { + L2TP_ATTR_NONE, /* no data */ + L2TP_ATTR_PW_TYPE, /* u16, enum l2tp_pwtype */ + L2TP_ATTR_ENCAP_TYPE, /* u16, enum l2tp_encap_type */ + L2TP_ATTR_OFFSET, /* u16 (not used) */ + L2TP_ATTR_DATA_SEQ, /* u16 (not used) */ + L2TP_ATTR_L2SPEC_TYPE, /* u8, enum l2tp_l2spec_type */ + L2TP_ATTR_L2SPEC_LEN, /* u8 (not used) */ + L2TP_ATTR_PROTO_VERSION, /* u8 */ + L2TP_ATTR_IFNAME, /* string */ + L2TP_ATTR_CONN_ID, /* u32 */ + L2TP_ATTR_PEER_CONN_ID, /* u32 */ + L2TP_ATTR_SESSION_ID, /* u32 */ + L2TP_ATTR_PEER_SESSION_ID, /* u32 */ + L2TP_ATTR_UDP_CSUM, /* u8 */ + L2TP_ATTR_VLAN_ID, /* u16 (not used) */ + L2TP_ATTR_COOKIE, /* 0, 4 or 8 bytes */ + L2TP_ATTR_PEER_COOKIE, /* 0, 4 or 8 bytes */ + L2TP_ATTR_DEBUG, /* u32, enum l2tp_debug_flags */ + L2TP_ATTR_RECV_SEQ, /* u8 */ + L2TP_ATTR_SEND_SEQ, /* u8 */ + L2TP_ATTR_LNS_MODE, /* u8 */ + L2TP_ATTR_USING_IPSEC, /* u8 */ + L2TP_ATTR_RECV_TIMEOUT, /* msec */ + L2TP_ATTR_FD, /* int */ + L2TP_ATTR_IP_SADDR, /* u32 */ + L2TP_ATTR_IP_DADDR, /* u32 */ + L2TP_ATTR_UDP_SPORT, /* u16 */ + L2TP_ATTR_UDP_DPORT, /* u16 */ + L2TP_ATTR_MTU, /* u16 (not used) */ + L2TP_ATTR_MRU, /* u16 (not used) */ + L2TP_ATTR_STATS, /* nested */ + L2TP_ATTR_IP6_SADDR, /* struct in6_addr */ + L2TP_ATTR_IP6_DADDR, /* struct in6_addr */ + L2TP_ATTR_UDP_ZERO_CSUM6_TX, /* flag */ + L2TP_ATTR_UDP_ZERO_CSUM6_RX, /* flag */ + L2TP_ATTR_PAD, + __L2TP_ATTR_MAX, +}; + +#define L2TP_ATTR_MAX (__L2TP_ATTR_MAX - 1) + +/* Nested in L2TP_ATTR_STATS */ +enum { + L2TP_ATTR_STATS_NONE, /* no data */ + L2TP_ATTR_TX_PACKETS, /* u64 */ + L2TP_ATTR_TX_BYTES, /* u64 */ + L2TP_ATTR_TX_ERRORS, /* u64 */ + L2TP_ATTR_RX_PACKETS, /* u64 */ + L2TP_ATTR_RX_BYTES, /* u64 */ + L2TP_ATTR_RX_SEQ_DISCARDS, /* u64 */ + L2TP_ATTR_RX_OOS_PACKETS, /* u64 */ + L2TP_ATTR_RX_ERRORS, /* u64 */ + L2TP_ATTR_STATS_PAD, + __L2TP_ATTR_STATS_MAX, +}; + +#define L2TP_ATTR_STATS_MAX (__L2TP_ATTR_STATS_MAX - 1) + +enum l2tp_pwtype { + L2TP_PWTYPE_NONE = 0x0000, + L2TP_PWTYPE_ETH_VLAN = 0x0004, + L2TP_PWTYPE_ETH = 0x0005, + L2TP_PWTYPE_PPP = 0x0007, + L2TP_PWTYPE_PPP_AC = 0x0008, + L2TP_PWTYPE_IP = 0x000b, + __L2TP_PWTYPE_MAX +}; + +enum l2tp_l2spec_type { + L2TP_L2SPECTYPE_NONE, + L2TP_L2SPECTYPE_DEFAULT, +}; + +enum l2tp_encap_type { + L2TP_ENCAPTYPE_UDP, + L2TP_ENCAPTYPE_IP, +}; + +/* For L2TP_ATTR_DATA_SEQ. Unused. */ +enum l2tp_seqmode { + L2TP_SEQ_NONE = 0, + L2TP_SEQ_IP = 1, + L2TP_SEQ_ALL = 2, +}; + +/** + * enum l2tp_debug_flags - debug message categories for L2TP tunnels/sessions + * + * @L2TP_MSG_DEBUG: verbose debug (if compiled in) + * @L2TP_MSG_CONTROL: userspace - kernel interface + * @L2TP_MSG_SEQ: sequence numbers + * @L2TP_MSG_DATA: data packets + */ +enum l2tp_debug_flags { + L2TP_MSG_DEBUG = (1 << 0), + L2TP_MSG_CONTROL = (1 << 1), + L2TP_MSG_SEQ = (1 << 2), + L2TP_MSG_DATA = (1 << 3), +}; + +/* + * NETLINK_GENERIC related info + */ +#define L2TP_GENL_NAME "l2tp" +#define L2TP_GENL_VERSION 0x1 +#define L2TP_GENL_MCGROUP "l2tp" + +#endif /* _UAPI_LINUX_L2TP_H_ */ diff --git a/src/basic/linux/libc-compat.h b/src/basic/linux/libc-compat.h new file mode 100644 index 00000000..8254c937 --- /dev/null +++ b/src/basic/linux/libc-compat.h @@ -0,0 +1,267 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Compatibility interface for userspace libc header coordination: + * + * Define compatibility macros that are used to control the inclusion or + * exclusion of UAPI structures and definitions in coordination with another + * userspace C library. + * + * This header is intended to solve the problem of UAPI definitions that + * conflict with userspace definitions. If a UAPI header has such conflicting + * definitions then the solution is as follows: + * + * * Synchronize the UAPI header and the libc headers so either one can be + * used and such that the ABI is preserved. If this is not possible then + * no simple compatibility interface exists (you need to write translating + * wrappers and rename things) and you can't use this interface. + * + * Then follow this process: + * + * (a) Include libc-compat.h in the UAPI header. + * e.g. #include + * This include must be as early as possible. + * + * (b) In libc-compat.h add enough code to detect that the comflicting + * userspace libc header has been included first. + * + * (c) If the userspace libc header has been included first define a set of + * guard macros of the form __UAPI_DEF_FOO and set their values to 1, else + * set their values to 0. + * + * (d) Back in the UAPI header with the conflicting definitions, guard the + * definitions with: + * #if __UAPI_DEF_FOO + * ... + * #endif + * + * This fixes the situation where the linux headers are included *after* the + * libc headers. To fix the problem with the inclusion in the other order the + * userspace libc headers must be fixed like this: + * + * * For all definitions that conflict with kernel definitions wrap those + * defines in the following: + * #if !__UAPI_DEF_FOO + * ... + * #endif + * + * This prevents the redefinition of a construct already defined by the kernel. + */ +#ifndef _UAPI_LIBC_COMPAT_H +#define _UAPI_LIBC_COMPAT_H + +/* We have included glibc headers... */ +#if defined(__GLIBC__) + +/* Coordinate with glibc net/if.h header. */ +#if defined(_NET_IF_H) && defined(__USE_MISC) + +/* GLIBC headers included first so don't define anything + * that would already be defined. */ + +#define __UAPI_DEF_IF_IFCONF 0 +#define __UAPI_DEF_IF_IFMAP 0 +#define __UAPI_DEF_IF_IFNAMSIZ 0 +#define __UAPI_DEF_IF_IFREQ 0 +/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0 +/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ +#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 +#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ + +#else /* _NET_IF_H */ + +/* Linux headers included first, and we must define everything + * we need. The expectation is that glibc will check the + * __UAPI_DEF_* defines and adjust appropriately. */ + +#define __UAPI_DEF_IF_IFCONF 1 +#define __UAPI_DEF_IF_IFMAP 1 +#define __UAPI_DEF_IF_IFNAMSIZ 1 +#define __UAPI_DEF_IF_IFREQ 1 +/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1 +/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 + +#endif /* _NET_IF_H */ + +/* Coordinate with glibc netinet/in.h header. */ +#if defined(_NETINET_IN_H) + +/* GLIBC headers included first so don't define anything + * that would already be defined. */ +#define __UAPI_DEF_IN_ADDR 0 +#define __UAPI_DEF_IN_IPPROTO 0 +#define __UAPI_DEF_IN_PKTINFO 0 +#define __UAPI_DEF_IP_MREQ 0 +#define __UAPI_DEF_SOCKADDR_IN 0 +#define __UAPI_DEF_IN_CLASS 0 + +#define __UAPI_DEF_IN6_ADDR 0 +/* The exception is the in6_addr macros which must be defined + * if the glibc code didn't define them. This guard matches + * the guard in glibc/inet/netinet/in.h which defines the + * additional in6_addr macros e.g. s6_addr16, and s6_addr32. */ +#if defined(__USE_MISC) || defined (__USE_GNU) +#define __UAPI_DEF_IN6_ADDR_ALT 0 +#else +#define __UAPI_DEF_IN6_ADDR_ALT 1 +#endif +#define __UAPI_DEF_SOCKADDR_IN6 0 +#define __UAPI_DEF_IPV6_MREQ 0 +#define __UAPI_DEF_IPPROTO_V6 0 +#define __UAPI_DEF_IPV6_OPTIONS 0 +#define __UAPI_DEF_IN6_PKTINFO 0 +#define __UAPI_DEF_IP6_MTUINFO 0 + +#else + +/* Linux headers included first, and we must define everything + * we need. The expectation is that glibc will check the + * __UAPI_DEF_* defines and adjust appropriately. */ +#define __UAPI_DEF_IN_ADDR 1 +#define __UAPI_DEF_IN_IPPROTO 1 +#define __UAPI_DEF_IN_PKTINFO 1 +#define __UAPI_DEF_IP_MREQ 1 +#define __UAPI_DEF_SOCKADDR_IN 1 +#define __UAPI_DEF_IN_CLASS 1 + +#define __UAPI_DEF_IN6_ADDR 1 +/* We unconditionally define the in6_addr macros and glibc must + * coordinate. */ +#define __UAPI_DEF_IN6_ADDR_ALT 1 +#define __UAPI_DEF_SOCKADDR_IN6 1 +#define __UAPI_DEF_IPV6_MREQ 1 +#define __UAPI_DEF_IPPROTO_V6 1 +#define __UAPI_DEF_IPV6_OPTIONS 1 +#define __UAPI_DEF_IN6_PKTINFO 1 +#define __UAPI_DEF_IP6_MTUINFO 1 + +#endif /* _NETINET_IN_H */ + +/* Coordinate with glibc netipx/ipx.h header. */ +#if defined(__NETIPX_IPX_H) + +#define __UAPI_DEF_SOCKADDR_IPX 0 +#define __UAPI_DEF_IPX_ROUTE_DEFINITION 0 +#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 0 +#define __UAPI_DEF_IPX_CONFIG_DATA 0 +#define __UAPI_DEF_IPX_ROUTE_DEF 0 + +#else /* defined(__NETIPX_IPX_H) */ + +#define __UAPI_DEF_SOCKADDR_IPX 1 +#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1 +#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1 +#define __UAPI_DEF_IPX_CONFIG_DATA 1 +#define __UAPI_DEF_IPX_ROUTE_DEF 1 + +#endif /* defined(__NETIPX_IPX_H) */ + +/* Definitions for xattr.h */ +#if defined(_SYS_XATTR_H) +#define __UAPI_DEF_XATTR 0 +#else +#define __UAPI_DEF_XATTR 1 +#endif + +/* If we did not see any headers from any supported C libraries, + * or we are being included in the kernel, then define everything + * that we need. Check for previous __UAPI_* definitions to give + * unsupported C libraries a way to opt out of any kernel definition. */ +#else /* !defined(__GLIBC__) */ + +/* Definitions for if.h */ +#ifndef __UAPI_DEF_IF_IFCONF +#define __UAPI_DEF_IF_IFCONF 1 +#endif +#ifndef __UAPI_DEF_IF_IFMAP +#define __UAPI_DEF_IF_IFMAP 1 +#endif +#ifndef __UAPI_DEF_IF_IFNAMSIZ +#define __UAPI_DEF_IF_IFNAMSIZ 1 +#endif +#ifndef __UAPI_DEF_IF_IFREQ +#define __UAPI_DEF_IF_IFREQ 1 +#endif +/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */ +#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1 +#endif +/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */ +#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1 +#endif + +/* Definitions for in.h */ +#ifndef __UAPI_DEF_IN_ADDR +#define __UAPI_DEF_IN_ADDR 1 +#endif +#ifndef __UAPI_DEF_IN_IPPROTO +#define __UAPI_DEF_IN_IPPROTO 1 +#endif +#ifndef __UAPI_DEF_IN_PKTINFO +#define __UAPI_DEF_IN_PKTINFO 1 +#endif +#ifndef __UAPI_DEF_IP_MREQ +#define __UAPI_DEF_IP_MREQ 1 +#endif +#ifndef __UAPI_DEF_SOCKADDR_IN +#define __UAPI_DEF_SOCKADDR_IN 1 +#endif +#ifndef __UAPI_DEF_IN_CLASS +#define __UAPI_DEF_IN_CLASS 1 +#endif + +/* Definitions for in6.h */ +#ifndef __UAPI_DEF_IN6_ADDR +#define __UAPI_DEF_IN6_ADDR 1 +#endif +#ifndef __UAPI_DEF_IN6_ADDR_ALT +#define __UAPI_DEF_IN6_ADDR_ALT 1 +#endif +#ifndef __UAPI_DEF_SOCKADDR_IN6 +#define __UAPI_DEF_SOCKADDR_IN6 1 +#endif +#ifndef __UAPI_DEF_IPV6_MREQ +#define __UAPI_DEF_IPV6_MREQ 1 +#endif +#ifndef __UAPI_DEF_IPPROTO_V6 +#define __UAPI_DEF_IPPROTO_V6 1 +#endif +#ifndef __UAPI_DEF_IPV6_OPTIONS +#define __UAPI_DEF_IPV6_OPTIONS 1 +#endif +#ifndef __UAPI_DEF_IN6_PKTINFO +#define __UAPI_DEF_IN6_PKTINFO 1 +#endif +#ifndef __UAPI_DEF_IP6_MTUINFO +#define __UAPI_DEF_IP6_MTUINFO 1 +#endif + +/* Definitions for ipx.h */ +#ifndef __UAPI_DEF_SOCKADDR_IPX +#define __UAPI_DEF_SOCKADDR_IPX 1 +#endif +#ifndef __UAPI_DEF_IPX_ROUTE_DEFINITION +#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1 +#endif +#ifndef __UAPI_DEF_IPX_INTERFACE_DEFINITION +#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1 +#endif +#ifndef __UAPI_DEF_IPX_CONFIG_DATA +#define __UAPI_DEF_IPX_CONFIG_DATA 1 +#endif +#ifndef __UAPI_DEF_IPX_ROUTE_DEF +#define __UAPI_DEF_IPX_ROUTE_DEF 1 +#endif + +/* Definitions for xattr.h */ +#ifndef __UAPI_DEF_XATTR +#define __UAPI_DEF_XATTR 1 +#endif + +#endif /* __GLIBC__ */ + +#endif /* _UAPI_LIBC_COMPAT_H */ diff --git a/src/basic/linux/netdevice.h b/src/basic/linux/netdevice.h new file mode 100644 index 00000000..f3770c5b --- /dev/null +++ b/src/basic/linux/netdevice.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions for the Interfaces handler. + * + * Version: @(#)dev.h 1.0.10 08/12/93 + * + * Authors: Ross Biro + * Fred N. van Kempen, + * Corey Minyard + * Donald J. Becker, + * Alan Cox, + * Bjorn Ekwall. + * Pekka Riikonen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Moved to /usr/include/linux for NET3 + */ +#ifndef _UAPI_LINUX_NETDEVICE_H +#define _UAPI_LINUX_NETDEVICE_H + +#include +#include +#include +#include + + +#define MAX_ADDR_LEN 32 /* Largest hardware address length */ + +/* Initial net device group. All devices belong to group 0 by default. */ +#define INIT_NETDEV_GROUP 0 + + +/* interface name assignment types (sysfs name_assign_type attribute) */ +#define NET_NAME_UNKNOWN 0 /* unknown origin (not exposed to userspace) */ +#define NET_NAME_ENUM 1 /* enumerated by kernel */ +#define NET_NAME_PREDICTABLE 2 /* predictably named by the kernel */ +#define NET_NAME_USER 3 /* provided by user-space */ +#define NET_NAME_RENAMED 4 /* renamed by user-space */ + +/* Media selection options. */ +enum { + IF_PORT_UNKNOWN = 0, + IF_PORT_10BASE2, + IF_PORT_10BASET, + IF_PORT_AUI, + IF_PORT_100BASET, + IF_PORT_100BASETX, + IF_PORT_100BASEFX +}; + +/* hardware address assignment types */ +#define NET_ADDR_PERM 0 /* address is permanent (default) */ +#define NET_ADDR_RANDOM 1 /* address is generated randomly */ +#define NET_ADDR_STOLEN 2 /* address is stolen from other device */ +#define NET_ADDR_SET 3 /* address is set using + * dev_set_mac_address() */ + +#endif /* _UAPI_LINUX_NETDEVICE_H */ diff --git a/src/basic/linux/netlink.h b/src/basic/linux/netlink.h new file mode 100644 index 00000000..0a4d7331 --- /dev/null +++ b/src/basic/linux/netlink.h @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI__LINUX_NETLINK_H +#define _UAPI__LINUX_NETLINK_H + +#include +#include /* for __kernel_sa_family_t */ +#include + +#define NETLINK_ROUTE 0 /* Routing/device hook */ +#define NETLINK_UNUSED 1 /* Unused number */ +#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ +#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */ +#define NETLINK_SOCK_DIAG 4 /* socket monitoring */ +#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ +#define NETLINK_XFRM 6 /* ipsec */ +#define NETLINK_SELINUX 7 /* SELinux event notifications */ +#define NETLINK_ISCSI 8 /* Open-iSCSI */ +#define NETLINK_AUDIT 9 /* auditing */ +#define NETLINK_FIB_LOOKUP 10 +#define NETLINK_CONNECTOR 11 +#define NETLINK_NETFILTER 12 /* netfilter subsystem */ +#define NETLINK_IP6_FW 13 +#define NETLINK_DNRTMSG 14 /* DECnet routing messages */ +#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ +#define NETLINK_GENERIC 16 +/* leave room for NETLINK_DM (DM Events) */ +#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */ +#define NETLINK_ECRYPTFS 19 +#define NETLINK_RDMA 20 +#define NETLINK_CRYPTO 21 /* Crypto layer */ +#define NETLINK_SMC 22 /* SMC monitoring */ + +#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG + +#define MAX_LINKS 32 + +struct sockaddr_nl { + __kernel_sa_family_t nl_family; /* AF_NETLINK */ + unsigned short nl_pad; /* zero */ + __u32 nl_pid; /* port ID */ + __u32 nl_groups; /* multicast groups mask */ +}; + +struct nlmsghdr { + __u32 nlmsg_len; /* Length of message including header */ + __u16 nlmsg_type; /* Message content */ + __u16 nlmsg_flags; /* Additional flags */ + __u32 nlmsg_seq; /* Sequence number */ + __u32 nlmsg_pid; /* Sending process port ID */ +}; + +/* Flags values */ + +#define NLM_F_REQUEST 0x01 /* It is request message. */ +#define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */ +#define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */ +#define NLM_F_ECHO 0x08 /* Echo this request */ +#define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */ +#define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */ + +/* Modifiers to GET request */ +#define NLM_F_ROOT 0x100 /* specify tree root */ +#define NLM_F_MATCH 0x200 /* return all matching */ +#define NLM_F_ATOMIC 0x400 /* atomic GET */ +#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH) + +/* Modifiers to NEW request */ +#define NLM_F_REPLACE 0x100 /* Override existing */ +#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */ +#define NLM_F_CREATE 0x400 /* Create, if it does not exist */ +#define NLM_F_APPEND 0x800 /* Add to end of list */ + +/* Modifiers to DELETE request */ +#define NLM_F_NONREC 0x100 /* Do not delete recursively */ + +/* Flags for ACK message */ +#define NLM_F_CAPPED 0x100 /* request was capped */ +#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */ + +/* + 4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL + 4.4BSD CHANGE NLM_F_REPLACE + + True CHANGE NLM_F_CREATE|NLM_F_REPLACE + Append NLM_F_CREATE + Check NLM_F_EXCL + */ + +#define NLMSG_ALIGNTO 4U +#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) ) +#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) +#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN) +#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) +#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0))) +#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ + (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) +#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \ + (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ + (nlh)->nlmsg_len <= (len)) +#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) + +#define NLMSG_NOOP 0x1 /* Nothing. */ +#define NLMSG_ERROR 0x2 /* Error */ +#define NLMSG_DONE 0x3 /* End of a dump */ +#define NLMSG_OVERRUN 0x4 /* Data lost */ + +#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */ + +struct nlmsgerr { + int error; + struct nlmsghdr msg; + /* + * followed by the message contents unless NETLINK_CAP_ACK was set + * or the ACK indicates success (error == 0) + * message length is aligned with NLMSG_ALIGN() + */ + /* + * followed by TLVs defined in enum nlmsgerr_attrs + * if NETLINK_EXT_ACK was set + */ +}; + +/** + * enum nlmsgerr_attrs - nlmsgerr attributes + * @NLMSGERR_ATTR_UNUSED: unused + * @NLMSGERR_ATTR_MSG: error message string (string) + * @NLMSGERR_ATTR_OFFS: offset of the invalid attribute in the original + * message, counting from the beginning of the header (u32) + * @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to + * be used - in the success case - to identify a created + * object or operation or similar (binary) + * @__NLMSGERR_ATTR_MAX: number of attributes + * @NLMSGERR_ATTR_MAX: highest attribute number + */ +enum nlmsgerr_attrs { + NLMSGERR_ATTR_UNUSED, + NLMSGERR_ATTR_MSG, + NLMSGERR_ATTR_OFFS, + NLMSGERR_ATTR_COOKIE, + + __NLMSGERR_ATTR_MAX, + NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1 +}; + +#define NETLINK_ADD_MEMBERSHIP 1 +#define NETLINK_DROP_MEMBERSHIP 2 +#define NETLINK_PKTINFO 3 +#define NETLINK_BROADCAST_ERROR 4 +#define NETLINK_NO_ENOBUFS 5 +#ifndef __KERNEL__ +#define NETLINK_RX_RING 6 +#define NETLINK_TX_RING 7 +#endif +#define NETLINK_LISTEN_ALL_NSID 8 +#define NETLINK_LIST_MEMBERSHIPS 9 +#define NETLINK_CAP_ACK 10 +#define NETLINK_EXT_ACK 11 +#define NETLINK_GET_STRICT_CHK 12 + +struct nl_pktinfo { + __u32 group; +}; + +struct nl_mmap_req { + unsigned int nm_block_size; + unsigned int nm_block_nr; + unsigned int nm_frame_size; + unsigned int nm_frame_nr; +}; + +struct nl_mmap_hdr { + unsigned int nm_status; + unsigned int nm_len; + __u32 nm_group; + /* credentials */ + __u32 nm_pid; + __u32 nm_uid; + __u32 nm_gid; +}; + +#ifndef __KERNEL__ +enum nl_mmap_status { + NL_MMAP_STATUS_UNUSED, + NL_MMAP_STATUS_RESERVED, + NL_MMAP_STATUS_VALID, + NL_MMAP_STATUS_COPY, + NL_MMAP_STATUS_SKIP, +}; + +#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO +#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT) +#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr)) +#endif + +#define NET_MAJOR 36 /* Major 36 is reserved for networking */ + +enum { + NETLINK_UNCONNECTED = 0, + NETLINK_CONNECTED, +}; + +/* + * <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)--> + * +---------------------+- - -+- - - - - - - - - -+- - -+ + * | Header | Pad | Payload | Pad | + * | (struct nlattr) | ing | | ing | + * +---------------------+- - -+- - - - - - - - - -+- - -+ + * <-------------- nlattr->nla_len --------------> + */ + +struct nlattr { + __u16 nla_len; + __u16 nla_type; +}; + +/* + * nla_type (16 bits) + * +---+---+-------------------------------+ + * | N | O | Attribute Type | + * +---+---+-------------------------------+ + * N := Carries nested attributes + * O := Payload stored in network byte order + * + * Note: The N and O flag are mutually exclusive. + */ +#define NLA_F_NESTED (1 << 15) +#define NLA_F_NET_BYTEORDER (1 << 14) +#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) + +#define NLA_ALIGNTO 4 +#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1)) +#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) + +/* Generic 32 bitflags attribute content sent to the kernel. + * + * The value is a bitmap that defines the values being set + * The selector is a bitmask that defines which value is legit + * + * Examples: + * value = 0x0, and selector = 0x1 + * implies we are selecting bit 1 and we want to set its value to 0. + * + * value = 0x2, and selector = 0x2 + * implies we are selecting bit 2 and we want to set its value to 1. + * + */ +struct nla_bitfield32 { + __u32 value; + __u32 selector; +}; + +#endif /* _UAPI__LINUX_NETLINK_H */ diff --git a/src/basic/linux/nexthop.h b/src/basic/linux/nexthop.h new file mode 100644 index 00000000..d51b6e1d --- /dev/null +++ b/src/basic/linux/nexthop.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_NEXTHOP_H +#define _LINUX_NEXTHOP_H + +#include + +struct nhmsg { + unsigned char nh_family; + unsigned char nh_scope; /* return only */ + unsigned char nh_protocol; /* Routing protocol that installed nh */ + unsigned char resvd; + unsigned int nh_flags; /* RTNH_F flags */ +}; + +/* entry in a nexthop group */ +struct nexthop_grp { + __u32 id; /* nexthop id - must exist */ + __u8 weight; /* weight of this nexthop */ + __u8 resvd1; + __u16 resvd2; +}; + +enum { + NEXTHOP_GRP_TYPE_MPATH, /* default type if not specified */ + __NEXTHOP_GRP_TYPE_MAX, +}; + +#define NEXTHOP_GRP_TYPE_MAX (__NEXTHOP_GRP_TYPE_MAX - 1) + +enum { + NHA_UNSPEC, + NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */ + + NHA_GROUP, /* array of nexthop_grp */ + NHA_GROUP_TYPE, /* u16 one of NEXTHOP_GRP_TYPE */ + /* if NHA_GROUP attribute is added, no other attributes can be set */ + + NHA_BLACKHOLE, /* flag; nexthop used to blackhole packets */ + /* if NHA_BLACKHOLE is added, OIF, GATEWAY, ENCAP can not be set */ + + NHA_OIF, /* u32; nexthop device */ + NHA_GATEWAY, /* be32 (IPv4) or in6_addr (IPv6) gw address */ + NHA_ENCAP_TYPE, /* u16; lwt encap type */ + NHA_ENCAP, /* lwt encap data */ + + /* NHA_OIF can be appended to dump request to return only + * nexthops using given device + */ + NHA_GROUPS, /* flag; only return nexthop groups in dump */ + NHA_MASTER, /* u32; only return nexthops with given master dev */ + + __NHA_MAX, +}; + +#define NHA_MAX (__NHA_MAX - 1) +#endif diff --git a/src/basic/linux/pkt_sched.h b/src/basic/linux/pkt_sched.h new file mode 100644 index 00000000..daf60576 --- /dev/null +++ b/src/basic/linux/pkt_sched.h @@ -0,0 +1,1184 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_PKT_SCHED_H +#define __LINUX_PKT_SCHED_H + +#include +#include + +/* Logical priority bands not depending on specific packet scheduler. + Every scheduler will map them to real traffic classes, if it has + no more precise mechanism to classify packets. + + These numbers have no special meaning, though their coincidence + with obsolete IPv6 values is not occasional :-). New IPv6 drafts + preferred full anarchy inspired by diffserv group. + + Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy + class, actually, as rule it will be handled with more care than + filler or even bulk. +*/ + +#define TC_PRIO_BESTEFFORT 0 +#define TC_PRIO_FILLER 1 +#define TC_PRIO_BULK 2 +#define TC_PRIO_INTERACTIVE_BULK 4 +#define TC_PRIO_INTERACTIVE 6 +#define TC_PRIO_CONTROL 7 + +#define TC_PRIO_MAX 15 + +/* Generic queue statistics, available for all the elements. + Particular schedulers may have also their private records. +*/ + +struct tc_stats { + __u64 bytes; /* Number of enqueued bytes */ + __u32 packets; /* Number of enqueued packets */ + __u32 drops; /* Packets dropped because of lack of resources */ + __u32 overlimits; /* Number of throttle events when this + * flow goes out of allocated bandwidth */ + __u32 bps; /* Current flow byte rate */ + __u32 pps; /* Current flow packet rate */ + __u32 qlen; + __u32 backlog; +}; + +struct tc_estimator { + signed char interval; + unsigned char ewma_log; +}; + +/* "Handles" + --------- + + All the traffic control objects have 32bit identifiers, or "handles". + + They can be considered as opaque numbers from user API viewpoint, + but actually they always consist of two fields: major and + minor numbers, which are interpreted by kernel specially, + that may be used by applications, though not recommended. + + F.e. qdisc handles always have minor number equal to zero, + classes (or flows) have major equal to parent qdisc major, and + minor uniquely identifying class inside qdisc. + + Macros to manipulate handles: +*/ + +#define TC_H_MAJ_MASK (0xFFFF0000U) +#define TC_H_MIN_MASK (0x0000FFFFU) +#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK) +#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK) +#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK)) + +#define TC_H_UNSPEC (0U) +#define TC_H_ROOT (0xFFFFFFFFU) +#define TC_H_INGRESS (0xFFFFFFF1U) +#define TC_H_CLSACT TC_H_INGRESS + +#define TC_H_MIN_PRIORITY 0xFFE0U +#define TC_H_MIN_INGRESS 0xFFF2U +#define TC_H_MIN_EGRESS 0xFFF3U + +/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */ +enum tc_link_layer { + TC_LINKLAYER_UNAWARE, /* Indicate unaware old iproute2 util */ + TC_LINKLAYER_ETHERNET, + TC_LINKLAYER_ATM, +}; +#define TC_LINKLAYER_MASK 0x0F /* limit use to lower 4 bits */ + +struct tc_ratespec { + unsigned char cell_log; + __u8 linklayer; /* lower 4 bits */ + unsigned short overhead; + short cell_align; + unsigned short mpu; + __u32 rate; +}; + +#define TC_RTAB_SIZE 1024 + +struct tc_sizespec { + unsigned char cell_log; + unsigned char size_log; + short cell_align; + int overhead; + unsigned int linklayer; + unsigned int mpu; + unsigned int mtu; + unsigned int tsize; +}; + +enum { + TCA_STAB_UNSPEC, + TCA_STAB_BASE, + TCA_STAB_DATA, + __TCA_STAB_MAX +}; + +#define TCA_STAB_MAX (__TCA_STAB_MAX - 1) + +/* FIFO section */ + +struct tc_fifo_qopt { + __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */ +}; + +/* SKBPRIO section */ + +/* + * Priorities go from zero to (SKBPRIO_MAX_PRIORITY - 1). + * SKBPRIO_MAX_PRIORITY should be at least 64 in order for skbprio to be able + * to map one to one the DS field of IPV4 and IPV6 headers. + * Memory allocation grows linearly with SKBPRIO_MAX_PRIORITY. + */ + +#define SKBPRIO_MAX_PRIORITY 64 + +struct tc_skbprio_qopt { + __u32 limit; /* Queue length in packets. */ +}; + +/* PRIO section */ + +#define TCQ_PRIO_BANDS 16 +#define TCQ_MIN_PRIO_BANDS 2 + +struct tc_prio_qopt { + int bands; /* Number of bands */ + __u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */ +}; + +/* MULTIQ section */ + +struct tc_multiq_qopt { + __u16 bands; /* Number of bands */ + __u16 max_bands; /* Maximum number of queues */ +}; + +/* PLUG section */ + +#define TCQ_PLUG_BUFFER 0 +#define TCQ_PLUG_RELEASE_ONE 1 +#define TCQ_PLUG_RELEASE_INDEFINITE 2 +#define TCQ_PLUG_LIMIT 3 + +struct tc_plug_qopt { + /* TCQ_PLUG_BUFFER: Inset a plug into the queue and + * buffer any incoming packets + * TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head + * to beginning of the next plug. + * TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue. + * Stop buffering packets until the next TCQ_PLUG_BUFFER + * command is received (just act as a pass-thru queue). + * TCQ_PLUG_LIMIT: Increase/decrease queue size + */ + int action; + __u32 limit; +}; + +/* TBF section */ + +struct tc_tbf_qopt { + struct tc_ratespec rate; + struct tc_ratespec peakrate; + __u32 limit; + __u32 buffer; + __u32 mtu; +}; + +enum { + TCA_TBF_UNSPEC, + TCA_TBF_PARMS, + TCA_TBF_RTAB, + TCA_TBF_PTAB, + TCA_TBF_RATE64, + TCA_TBF_PRATE64, + TCA_TBF_BURST, + TCA_TBF_PBURST, + TCA_TBF_PAD, + __TCA_TBF_MAX, +}; + +#define TCA_TBF_MAX (__TCA_TBF_MAX - 1) + + +/* TEQL section */ + +/* TEQL does not require any parameters */ + +/* SFQ section */ + +struct tc_sfq_qopt { + unsigned quantum; /* Bytes per round allocated to flow */ + int perturb_period; /* Period of hash perturbation */ + __u32 limit; /* Maximal packets in queue */ + unsigned divisor; /* Hash divisor */ + unsigned flows; /* Maximal number of flows */ +}; + +struct tc_sfqred_stats { + __u32 prob_drop; /* Early drops, below max threshold */ + __u32 forced_drop; /* Early drops, after max threshold */ + __u32 prob_mark; /* Marked packets, below max threshold */ + __u32 forced_mark; /* Marked packets, after max threshold */ + __u32 prob_mark_head; /* Marked packets, below max threshold */ + __u32 forced_mark_head;/* Marked packets, after max threshold */ +}; + +struct tc_sfq_qopt_v1 { + struct tc_sfq_qopt v0; + unsigned int depth; /* max number of packets per flow */ + unsigned int headdrop; + /* SFQRED parameters */ + __u32 limit; /* HARD maximal flow queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; + __u32 max_P; /* probability, high resolution */ + /* SFQRED stats */ + struct tc_sfqred_stats stats; +}; + + +struct tc_sfq_xstats { + __s32 allot; +}; + +/* RED section */ + +enum { + TCA_RED_UNSPEC, + TCA_RED_PARMS, + TCA_RED_STAB, + TCA_RED_MAX_P, + __TCA_RED_MAX, +}; + +#define TCA_RED_MAX (__TCA_RED_MAX - 1) + +struct tc_red_qopt { + __u32 limit; /* HARD maximal queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; +#define TC_RED_ECN 1 +#define TC_RED_HARDDROP 2 +#define TC_RED_ADAPTATIVE 4 +}; + +struct tc_red_xstats { + __u32 early; /* Early drops */ + __u32 pdrop; /* Drops due to queue limits */ + __u32 other; /* Drops due to drop() calls */ + __u32 marked; /* Marked packets */ +}; + +/* GRED section */ + +#define MAX_DPs 16 + +enum { + TCA_GRED_UNSPEC, + TCA_GRED_PARMS, + TCA_GRED_STAB, + TCA_GRED_DPS, + TCA_GRED_MAX_P, + TCA_GRED_LIMIT, + TCA_GRED_VQ_LIST, /* nested TCA_GRED_VQ_ENTRY */ + __TCA_GRED_MAX, +}; + +#define TCA_GRED_MAX (__TCA_GRED_MAX - 1) + +enum { + TCA_GRED_VQ_ENTRY_UNSPEC, + TCA_GRED_VQ_ENTRY, /* nested TCA_GRED_VQ_* */ + __TCA_GRED_VQ_ENTRY_MAX, +}; +#define TCA_GRED_VQ_ENTRY_MAX (__TCA_GRED_VQ_ENTRY_MAX - 1) + +enum { + TCA_GRED_VQ_UNSPEC, + TCA_GRED_VQ_PAD, + TCA_GRED_VQ_DP, /* u32 */ + TCA_GRED_VQ_STAT_BYTES, /* u64 */ + TCA_GRED_VQ_STAT_PACKETS, /* u32 */ + TCA_GRED_VQ_STAT_BACKLOG, /* u32 */ + TCA_GRED_VQ_STAT_PROB_DROP, /* u32 */ + TCA_GRED_VQ_STAT_PROB_MARK, /* u32 */ + TCA_GRED_VQ_STAT_FORCED_DROP, /* u32 */ + TCA_GRED_VQ_STAT_FORCED_MARK, /* u32 */ + TCA_GRED_VQ_STAT_PDROP, /* u32 */ + TCA_GRED_VQ_STAT_OTHER, /* u32 */ + TCA_GRED_VQ_FLAGS, /* u32 */ + __TCA_GRED_VQ_MAX +}; + +#define TCA_GRED_VQ_MAX (__TCA_GRED_VQ_MAX - 1) + +struct tc_gred_qopt { + __u32 limit; /* HARD maximal queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + __u32 DP; /* up to 2^32 DPs */ + __u32 backlog; + __u32 qave; + __u32 forced; + __u32 early; + __u32 other; + __u32 pdrop; + __u8 Wlog; /* log(W) */ + __u8 Plog; /* log(P_max/(qth_max-qth_min)) */ + __u8 Scell_log; /* cell size for idle damping */ + __u8 prio; /* prio of this VQ */ + __u32 packets; + __u32 bytesin; +}; + +/* gred setup */ +struct tc_gred_sopt { + __u32 DPs; + __u32 def_DP; + __u8 grio; + __u8 flags; + __u16 pad1; +}; + +/* CHOKe section */ + +enum { + TCA_CHOKE_UNSPEC, + TCA_CHOKE_PARMS, + TCA_CHOKE_STAB, + TCA_CHOKE_MAX_P, + __TCA_CHOKE_MAX, +}; + +#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1) + +struct tc_choke_qopt { + __u32 limit; /* Hard queue length (packets) */ + __u32 qth_min; /* Min average threshold (packets) */ + __u32 qth_max; /* Max average threshold (packets) */ + unsigned char Wlog; /* log(W) */ + unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ + unsigned char Scell_log; /* cell size for idle damping */ + unsigned char flags; /* see RED flags */ +}; + +struct tc_choke_xstats { + __u32 early; /* Early drops */ + __u32 pdrop; /* Drops due to queue limits */ + __u32 other; /* Drops due to drop() calls */ + __u32 marked; /* Marked packets */ + __u32 matched; /* Drops due to flow match */ +}; + +/* HTB section */ +#define TC_HTB_NUMPRIO 8 +#define TC_HTB_MAXDEPTH 8 +#define TC_HTB_PROTOVER 3 /* the same as HTB and TC's major */ + +struct tc_htb_opt { + struct tc_ratespec rate; + struct tc_ratespec ceil; + __u32 buffer; + __u32 cbuffer; + __u32 quantum; + __u32 level; /* out only */ + __u32 prio; +}; +struct tc_htb_glob { + __u32 version; /* to match HTB/TC */ + __u32 rate2quantum; /* bps->quantum divisor */ + __u32 defcls; /* default class number */ + __u32 debug; /* debug flags */ + + /* stats */ + __u32 direct_pkts; /* count of non shaped packets */ +}; +enum { + TCA_HTB_UNSPEC, + TCA_HTB_PARMS, + TCA_HTB_INIT, + TCA_HTB_CTAB, + TCA_HTB_RTAB, + TCA_HTB_DIRECT_QLEN, + TCA_HTB_RATE64, + TCA_HTB_CEIL64, + TCA_HTB_PAD, + __TCA_HTB_MAX, +}; + +#define TCA_HTB_MAX (__TCA_HTB_MAX - 1) + +struct tc_htb_xstats { + __u32 lends; + __u32 borrows; + __u32 giants; /* unused since 'Make HTB scheduler work with TSO.' */ + __s32 tokens; + __s32 ctokens; +}; + +/* HFSC section */ + +struct tc_hfsc_qopt { + __u16 defcls; /* default class */ +}; + +struct tc_service_curve { + __u32 m1; /* slope of the first segment in bps */ + __u32 d; /* x-projection of the first segment in us */ + __u32 m2; /* slope of the second segment in bps */ +}; + +struct tc_hfsc_stats { + __u64 work; /* total work done */ + __u64 rtwork; /* work done by real-time criteria */ + __u32 period; /* current period */ + __u32 level; /* class level in hierarchy */ +}; + +enum { + TCA_HFSC_UNSPEC, + TCA_HFSC_RSC, + TCA_HFSC_FSC, + TCA_HFSC_USC, + __TCA_HFSC_MAX, +}; + +#define TCA_HFSC_MAX (__TCA_HFSC_MAX - 1) + + +/* CBQ section */ + +#define TC_CBQ_MAXPRIO 8 +#define TC_CBQ_MAXLEVEL 8 +#define TC_CBQ_DEF_EWMA 5 + +struct tc_cbq_lssopt { + unsigned char change; + unsigned char flags; +#define TCF_CBQ_LSS_BOUNDED 1 +#define TCF_CBQ_LSS_ISOLATED 2 + unsigned char ewma_log; + unsigned char level; +#define TCF_CBQ_LSS_FLAGS 1 +#define TCF_CBQ_LSS_EWMA 2 +#define TCF_CBQ_LSS_MAXIDLE 4 +#define TCF_CBQ_LSS_MINIDLE 8 +#define TCF_CBQ_LSS_OFFTIME 0x10 +#define TCF_CBQ_LSS_AVPKT 0x20 + __u32 maxidle; + __u32 minidle; + __u32 offtime; + __u32 avpkt; +}; + +struct tc_cbq_wrropt { + unsigned char flags; + unsigned char priority; + unsigned char cpriority; + unsigned char __reserved; + __u32 allot; + __u32 weight; +}; + +struct tc_cbq_ovl { + unsigned char strategy; +#define TC_CBQ_OVL_CLASSIC 0 +#define TC_CBQ_OVL_DELAY 1 +#define TC_CBQ_OVL_LOWPRIO 2 +#define TC_CBQ_OVL_DROP 3 +#define TC_CBQ_OVL_RCLASSIC 4 + unsigned char priority2; + __u16 pad; + __u32 penalty; +}; + +struct tc_cbq_police { + unsigned char police; + unsigned char __res1; + unsigned short __res2; +}; + +struct tc_cbq_fopt { + __u32 split; + __u32 defmap; + __u32 defchange; +}; + +struct tc_cbq_xstats { + __u32 borrows; + __u32 overactions; + __s32 avgidle; + __s32 undertime; +}; + +enum { + TCA_CBQ_UNSPEC, + TCA_CBQ_LSSOPT, + TCA_CBQ_WRROPT, + TCA_CBQ_FOPT, + TCA_CBQ_OVL_STRATEGY, + TCA_CBQ_RATE, + TCA_CBQ_RTAB, + TCA_CBQ_POLICE, + __TCA_CBQ_MAX, +}; + +#define TCA_CBQ_MAX (__TCA_CBQ_MAX - 1) + +/* dsmark section */ + +enum { + TCA_DSMARK_UNSPEC, + TCA_DSMARK_INDICES, + TCA_DSMARK_DEFAULT_INDEX, + TCA_DSMARK_SET_TC_INDEX, + TCA_DSMARK_MASK, + TCA_DSMARK_VALUE, + __TCA_DSMARK_MAX, +}; + +#define TCA_DSMARK_MAX (__TCA_DSMARK_MAX - 1) + +/* ATM section */ + +enum { + TCA_ATM_UNSPEC, + TCA_ATM_FD, /* file/socket descriptor */ + TCA_ATM_PTR, /* pointer to descriptor - later */ + TCA_ATM_HDR, /* LL header */ + TCA_ATM_EXCESS, /* excess traffic class (0 for CLP) */ + TCA_ATM_ADDR, /* PVC address (for output only) */ + TCA_ATM_STATE, /* VC state (ATM_VS_*; for output only) */ + __TCA_ATM_MAX, +}; + +#define TCA_ATM_MAX (__TCA_ATM_MAX - 1) + +/* Network emulator */ + +enum { + TCA_NETEM_UNSPEC, + TCA_NETEM_CORR, + TCA_NETEM_DELAY_DIST, + TCA_NETEM_REORDER, + TCA_NETEM_CORRUPT, + TCA_NETEM_LOSS, + TCA_NETEM_RATE, + TCA_NETEM_ECN, + TCA_NETEM_RATE64, + TCA_NETEM_PAD, + TCA_NETEM_LATENCY64, + TCA_NETEM_JITTER64, + TCA_NETEM_SLOT, + TCA_NETEM_SLOT_DIST, + __TCA_NETEM_MAX, +}; + +#define TCA_NETEM_MAX (__TCA_NETEM_MAX - 1) + +struct tc_netem_qopt { + __u32 latency; /* added delay (us) */ + __u32 limit; /* fifo limit (packets) */ + __u32 loss; /* random packet loss (0=none ~0=100%) */ + __u32 gap; /* re-ordering gap (0 for none) */ + __u32 duplicate; /* random packet dup (0=none ~0=100%) */ + __u32 jitter; /* random jitter in latency (us) */ +}; + +struct tc_netem_corr { + __u32 delay_corr; /* delay correlation */ + __u32 loss_corr; /* packet loss correlation */ + __u32 dup_corr; /* duplicate correlation */ +}; + +struct tc_netem_reorder { + __u32 probability; + __u32 correlation; +}; + +struct tc_netem_corrupt { + __u32 probability; + __u32 correlation; +}; + +struct tc_netem_rate { + __u32 rate; /* byte/s */ + __s32 packet_overhead; + __u32 cell_size; + __s32 cell_overhead; +}; + +struct tc_netem_slot { + __s64 min_delay; /* nsec */ + __s64 max_delay; + __s32 max_packets; + __s32 max_bytes; + __s64 dist_delay; /* nsec */ + __s64 dist_jitter; /* nsec */ +}; + +enum { + NETEM_LOSS_UNSPEC, + NETEM_LOSS_GI, /* General Intuitive - 4 state model */ + NETEM_LOSS_GE, /* Gilbert Elliot models */ + __NETEM_LOSS_MAX +}; +#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1) + +/* State transition probabilities for 4 state model */ +struct tc_netem_gimodel { + __u32 p13; + __u32 p31; + __u32 p32; + __u32 p14; + __u32 p23; +}; + +/* Gilbert-Elliot models */ +struct tc_netem_gemodel { + __u32 p; + __u32 r; + __u32 h; + __u32 k1; +}; + +#define NETEM_DIST_SCALE 8192 +#define NETEM_DIST_MAX 16384 + +/* DRR */ + +enum { + TCA_DRR_UNSPEC, + TCA_DRR_QUANTUM, + __TCA_DRR_MAX +}; + +#define TCA_DRR_MAX (__TCA_DRR_MAX - 1) + +struct tc_drr_stats { + __u32 deficit; +}; + +/* MQPRIO */ +#define TC_QOPT_BITMASK 15 +#define TC_QOPT_MAX_QUEUE 16 + +enum { + TC_MQPRIO_HW_OFFLOAD_NONE, /* no offload requested */ + TC_MQPRIO_HW_OFFLOAD_TCS, /* offload TCs, no queue counts */ + __TC_MQPRIO_HW_OFFLOAD_MAX +}; + +#define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1) + +enum { + TC_MQPRIO_MODE_DCB, + TC_MQPRIO_MODE_CHANNEL, + __TC_MQPRIO_MODE_MAX +}; + +#define __TC_MQPRIO_MODE_MAX (__TC_MQPRIO_MODE_MAX - 1) + +enum { + TC_MQPRIO_SHAPER_DCB, + TC_MQPRIO_SHAPER_BW_RATE, /* Add new shapers below */ + __TC_MQPRIO_SHAPER_MAX +}; + +#define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1) + +struct tc_mqprio_qopt { + __u8 num_tc; + __u8 prio_tc_map[TC_QOPT_BITMASK + 1]; + __u8 hw; + __u16 count[TC_QOPT_MAX_QUEUE]; + __u16 offset[TC_QOPT_MAX_QUEUE]; +}; + +#define TC_MQPRIO_F_MODE 0x1 +#define TC_MQPRIO_F_SHAPER 0x2 +#define TC_MQPRIO_F_MIN_RATE 0x4 +#define TC_MQPRIO_F_MAX_RATE 0x8 + +enum { + TCA_MQPRIO_UNSPEC, + TCA_MQPRIO_MODE, + TCA_MQPRIO_SHAPER, + TCA_MQPRIO_MIN_RATE64, + TCA_MQPRIO_MAX_RATE64, + __TCA_MQPRIO_MAX, +}; + +#define TCA_MQPRIO_MAX (__TCA_MQPRIO_MAX - 1) + +/* SFB */ + +enum { + TCA_SFB_UNSPEC, + TCA_SFB_PARMS, + __TCA_SFB_MAX, +}; + +#define TCA_SFB_MAX (__TCA_SFB_MAX - 1) + +/* + * Note: increment, decrement are Q0.16 fixed-point values. + */ +struct tc_sfb_qopt { + __u32 rehash_interval; /* delay between hash move, in ms */ + __u32 warmup_time; /* double buffering warmup time in ms (warmup_time < rehash_interval) */ + __u32 max; /* max len of qlen_min */ + __u32 bin_size; /* maximum queue length per bin */ + __u32 increment; /* probability increment, (d1 in Blue) */ + __u32 decrement; /* probability decrement, (d2 in Blue) */ + __u32 limit; /* max SFB queue length */ + __u32 penalty_rate; /* inelastic flows are rate limited to 'rate' pps */ + __u32 penalty_burst; +}; + +struct tc_sfb_xstats { + __u32 earlydrop; + __u32 penaltydrop; + __u32 bucketdrop; + __u32 queuedrop; + __u32 childdrop; /* drops in child qdisc */ + __u32 marked; + __u32 maxqlen; + __u32 maxprob; + __u32 avgprob; +}; + +#define SFB_MAX_PROB 0xFFFF + +/* QFQ */ +enum { + TCA_QFQ_UNSPEC, + TCA_QFQ_WEIGHT, + TCA_QFQ_LMAX, + __TCA_QFQ_MAX +}; + +#define TCA_QFQ_MAX (__TCA_QFQ_MAX - 1) + +struct tc_qfq_stats { + __u32 weight; + __u32 lmax; +}; + +/* CODEL */ + +enum { + TCA_CODEL_UNSPEC, + TCA_CODEL_TARGET, + TCA_CODEL_LIMIT, + TCA_CODEL_INTERVAL, + TCA_CODEL_ECN, + TCA_CODEL_CE_THRESHOLD, + __TCA_CODEL_MAX +}; + +#define TCA_CODEL_MAX (__TCA_CODEL_MAX - 1) + +struct tc_codel_xstats { + __u32 maxpacket; /* largest packet we've seen so far */ + __u32 count; /* how many drops we've done since the last time we + * entered dropping state + */ + __u32 lastcount; /* count at entry to dropping state */ + __u32 ldelay; /* in-queue delay seen by most recently dequeued packet */ + __s32 drop_next; /* time to drop next packet */ + __u32 drop_overlimit; /* number of time max qdisc packet limit was hit */ + __u32 ecn_mark; /* number of packets we ECN marked instead of dropped */ + __u32 dropping; /* are we in dropping state ? */ + __u32 ce_mark; /* number of CE marked packets because of ce_threshold */ +}; + +/* FQ_CODEL */ + +enum { + TCA_FQ_CODEL_UNSPEC, + TCA_FQ_CODEL_TARGET, + TCA_FQ_CODEL_LIMIT, + TCA_FQ_CODEL_INTERVAL, + TCA_FQ_CODEL_ECN, + TCA_FQ_CODEL_FLOWS, + TCA_FQ_CODEL_QUANTUM, + TCA_FQ_CODEL_CE_THRESHOLD, + TCA_FQ_CODEL_DROP_BATCH_SIZE, + TCA_FQ_CODEL_MEMORY_LIMIT, + __TCA_FQ_CODEL_MAX +}; + +#define TCA_FQ_CODEL_MAX (__TCA_FQ_CODEL_MAX - 1) + +enum { + TCA_FQ_CODEL_XSTATS_QDISC, + TCA_FQ_CODEL_XSTATS_CLASS, +}; + +struct tc_fq_codel_qd_stats { + __u32 maxpacket; /* largest packet we've seen so far */ + __u32 drop_overlimit; /* number of time max qdisc + * packet limit was hit + */ + __u32 ecn_mark; /* number of packets we ECN marked + * instead of being dropped + */ + __u32 new_flow_count; /* number of time packets + * created a 'new flow' + */ + __u32 new_flows_len; /* count of flows in new list */ + __u32 old_flows_len; /* count of flows in old list */ + __u32 ce_mark; /* packets above ce_threshold */ + __u32 memory_usage; /* in bytes */ + __u32 drop_overmemory; +}; + +struct tc_fq_codel_cl_stats { + __s32 deficit; + __u32 ldelay; /* in-queue delay seen by most recently + * dequeued packet + */ + __u32 count; + __u32 lastcount; + __u32 dropping; + __s32 drop_next; +}; + +struct tc_fq_codel_xstats { + __u32 type; + union { + struct tc_fq_codel_qd_stats qdisc_stats; + struct tc_fq_codel_cl_stats class_stats; + }; +}; + +/* FQ */ + +enum { + TCA_FQ_UNSPEC, + + TCA_FQ_PLIMIT, /* limit of total number of packets in queue */ + + TCA_FQ_FLOW_PLIMIT, /* limit of packets per flow */ + + TCA_FQ_QUANTUM, /* RR quantum */ + + TCA_FQ_INITIAL_QUANTUM, /* RR quantum for new flow */ + + TCA_FQ_RATE_ENABLE, /* enable/disable rate limiting */ + + TCA_FQ_FLOW_DEFAULT_RATE,/* obsolete, do not use */ + + TCA_FQ_FLOW_MAX_RATE, /* per flow max rate */ + + TCA_FQ_BUCKETS_LOG, /* log2(number of buckets) */ + + TCA_FQ_FLOW_REFILL_DELAY, /* flow credit refill delay in usec */ + + TCA_FQ_ORPHAN_MASK, /* mask applied to orphaned skb hashes */ + + TCA_FQ_LOW_RATE_THRESHOLD, /* per packet delay under this rate */ + + TCA_FQ_CE_THRESHOLD, /* DCTCP-like CE-marking threshold */ + + __TCA_FQ_MAX +}; + +#define TCA_FQ_MAX (__TCA_FQ_MAX - 1) + +struct tc_fq_qd_stats { + __u64 gc_flows; + __u64 highprio_packets; + __u64 tcp_retrans; + __u64 throttled; + __u64 flows_plimit; + __u64 pkts_too_long; + __u64 allocation_errors; + __s64 time_next_delayed_flow; + __u32 flows; + __u32 inactive_flows; + __u32 throttled_flows; + __u32 unthrottle_latency_ns; + __u64 ce_mark; /* packets above ce_threshold */ +}; + +/* Heavy-Hitter Filter */ + +enum { + TCA_HHF_UNSPEC, + TCA_HHF_BACKLOG_LIMIT, + TCA_HHF_QUANTUM, + TCA_HHF_HH_FLOWS_LIMIT, + TCA_HHF_RESET_TIMEOUT, + TCA_HHF_ADMIT_BYTES, + TCA_HHF_EVICT_TIMEOUT, + TCA_HHF_NON_HH_WEIGHT, + __TCA_HHF_MAX +}; + +#define TCA_HHF_MAX (__TCA_HHF_MAX - 1) + +struct tc_hhf_xstats { + __u32 drop_overlimit; /* number of times max qdisc packet limit + * was hit + */ + __u32 hh_overlimit; /* number of times max heavy-hitters was hit */ + __u32 hh_tot_count; /* number of captured heavy-hitters so far */ + __u32 hh_cur_count; /* number of current heavy-hitters */ +}; + +/* PIE */ +enum { + TCA_PIE_UNSPEC, + TCA_PIE_TARGET, + TCA_PIE_LIMIT, + TCA_PIE_TUPDATE, + TCA_PIE_ALPHA, + TCA_PIE_BETA, + TCA_PIE_ECN, + TCA_PIE_BYTEMODE, + __TCA_PIE_MAX +}; +#define TCA_PIE_MAX (__TCA_PIE_MAX - 1) + +struct tc_pie_xstats { + __u64 prob; /* current probability */ + __u32 delay; /* current delay in ms */ + __u32 avg_dq_rate; /* current average dq_rate in bits/pie_time */ + __u32 packets_in; /* total number of packets enqueued */ + __u32 dropped; /* packets dropped due to pie_action */ + __u32 overlimit; /* dropped due to lack of space in queue */ + __u32 maxq; /* maximum queue size */ + __u32 ecn_mark; /* packets marked with ecn*/ +}; + +/* CBS */ +struct tc_cbs_qopt { + __u8 offload; + __u8 _pad[3]; + __s32 hicredit; + __s32 locredit; + __s32 idleslope; + __s32 sendslope; +}; + +enum { + TCA_CBS_UNSPEC, + TCA_CBS_PARMS, + __TCA_CBS_MAX, +}; + +#define TCA_CBS_MAX (__TCA_CBS_MAX - 1) + + +/* ETF */ +struct tc_etf_qopt { + __s32 delta; + __s32 clockid; + __u32 flags; +#define TC_ETF_DEADLINE_MODE_ON _BITUL(0) +#define TC_ETF_OFFLOAD_ON _BITUL(1) +#define TC_ETF_SKIP_SOCK_CHECK _BITUL(2) +}; + +enum { + TCA_ETF_UNSPEC, + TCA_ETF_PARMS, + __TCA_ETF_MAX, +}; + +#define TCA_ETF_MAX (__TCA_ETF_MAX - 1) + + +/* CAKE */ +enum { + TCA_CAKE_UNSPEC, + TCA_CAKE_PAD, + TCA_CAKE_BASE_RATE64, + TCA_CAKE_DIFFSERV_MODE, + TCA_CAKE_ATM, + TCA_CAKE_FLOW_MODE, + TCA_CAKE_OVERHEAD, + TCA_CAKE_RTT, + TCA_CAKE_TARGET, + TCA_CAKE_AUTORATE, + TCA_CAKE_MEMORY, + TCA_CAKE_NAT, + TCA_CAKE_RAW, + TCA_CAKE_WASH, + TCA_CAKE_MPU, + TCA_CAKE_INGRESS, + TCA_CAKE_ACK_FILTER, + TCA_CAKE_SPLIT_GSO, + TCA_CAKE_FWMARK, + __TCA_CAKE_MAX +}; +#define TCA_CAKE_MAX (__TCA_CAKE_MAX - 1) + +enum { + __TCA_CAKE_STATS_INVALID, + TCA_CAKE_STATS_PAD, + TCA_CAKE_STATS_CAPACITY_ESTIMATE64, + TCA_CAKE_STATS_MEMORY_LIMIT, + TCA_CAKE_STATS_MEMORY_USED, + TCA_CAKE_STATS_AVG_NETOFF, + TCA_CAKE_STATS_MIN_NETLEN, + TCA_CAKE_STATS_MAX_NETLEN, + TCA_CAKE_STATS_MIN_ADJLEN, + TCA_CAKE_STATS_MAX_ADJLEN, + TCA_CAKE_STATS_TIN_STATS, + TCA_CAKE_STATS_DEFICIT, + TCA_CAKE_STATS_COBALT_COUNT, + TCA_CAKE_STATS_DROPPING, + TCA_CAKE_STATS_DROP_NEXT_US, + TCA_CAKE_STATS_P_DROP, + TCA_CAKE_STATS_BLUE_TIMER_US, + __TCA_CAKE_STATS_MAX +}; +#define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1) + +enum { + __TCA_CAKE_TIN_STATS_INVALID, + TCA_CAKE_TIN_STATS_PAD, + TCA_CAKE_TIN_STATS_SENT_PACKETS, + TCA_CAKE_TIN_STATS_SENT_BYTES64, + TCA_CAKE_TIN_STATS_DROPPED_PACKETS, + TCA_CAKE_TIN_STATS_DROPPED_BYTES64, + TCA_CAKE_TIN_STATS_ACKS_DROPPED_PACKETS, + TCA_CAKE_TIN_STATS_ACKS_DROPPED_BYTES64, + TCA_CAKE_TIN_STATS_ECN_MARKED_PACKETS, + TCA_CAKE_TIN_STATS_ECN_MARKED_BYTES64, + TCA_CAKE_TIN_STATS_BACKLOG_PACKETS, + TCA_CAKE_TIN_STATS_BACKLOG_BYTES, + TCA_CAKE_TIN_STATS_THRESHOLD_RATE64, + TCA_CAKE_TIN_STATS_TARGET_US, + TCA_CAKE_TIN_STATS_INTERVAL_US, + TCA_CAKE_TIN_STATS_WAY_INDIRECT_HITS, + TCA_CAKE_TIN_STATS_WAY_MISSES, + TCA_CAKE_TIN_STATS_WAY_COLLISIONS, + TCA_CAKE_TIN_STATS_PEAK_DELAY_US, + TCA_CAKE_TIN_STATS_AVG_DELAY_US, + TCA_CAKE_TIN_STATS_BASE_DELAY_US, + TCA_CAKE_TIN_STATS_SPARSE_FLOWS, + TCA_CAKE_TIN_STATS_BULK_FLOWS, + TCA_CAKE_TIN_STATS_UNRESPONSIVE_FLOWS, + TCA_CAKE_TIN_STATS_MAX_SKBLEN, + TCA_CAKE_TIN_STATS_FLOW_QUANTUM, + __TCA_CAKE_TIN_STATS_MAX +}; +#define TCA_CAKE_TIN_STATS_MAX (__TCA_CAKE_TIN_STATS_MAX - 1) +#define TC_CAKE_MAX_TINS (8) + +enum { + CAKE_FLOW_NONE = 0, + CAKE_FLOW_SRC_IP, + CAKE_FLOW_DST_IP, + CAKE_FLOW_HOSTS, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_DST_IP */ + CAKE_FLOW_FLOWS, + CAKE_FLOW_DUAL_SRC, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_FLOWS */ + CAKE_FLOW_DUAL_DST, /* = CAKE_FLOW_DST_IP | CAKE_FLOW_FLOWS */ + CAKE_FLOW_TRIPLE, /* = CAKE_FLOW_HOSTS | CAKE_FLOW_FLOWS */ + CAKE_FLOW_MAX, +}; + +enum { + CAKE_DIFFSERV_DIFFSERV3 = 0, + CAKE_DIFFSERV_DIFFSERV4, + CAKE_DIFFSERV_DIFFSERV8, + CAKE_DIFFSERV_BESTEFFORT, + CAKE_DIFFSERV_PRECEDENCE, + CAKE_DIFFSERV_MAX +}; + +enum { + CAKE_ACK_NONE = 0, + CAKE_ACK_FILTER, + CAKE_ACK_AGGRESSIVE, + CAKE_ACK_MAX +}; + +enum { + CAKE_ATM_NONE = 0, + CAKE_ATM_ATM, + CAKE_ATM_PTM, + CAKE_ATM_MAX +}; + + +/* TAPRIO */ +enum { + TC_TAPRIO_CMD_SET_GATES = 0x00, + TC_TAPRIO_CMD_SET_AND_HOLD = 0x01, + TC_TAPRIO_CMD_SET_AND_RELEASE = 0x02, +}; + +enum { + TCA_TAPRIO_SCHED_ENTRY_UNSPEC, + TCA_TAPRIO_SCHED_ENTRY_INDEX, /* u32 */ + TCA_TAPRIO_SCHED_ENTRY_CMD, /* u8 */ + TCA_TAPRIO_SCHED_ENTRY_GATE_MASK, /* u32 */ + TCA_TAPRIO_SCHED_ENTRY_INTERVAL, /* u32 */ + __TCA_TAPRIO_SCHED_ENTRY_MAX, +}; +#define TCA_TAPRIO_SCHED_ENTRY_MAX (__TCA_TAPRIO_SCHED_ENTRY_MAX - 1) + +/* The format for schedule entry list is: + * [TCA_TAPRIO_SCHED_ENTRY_LIST] + * [TCA_TAPRIO_SCHED_ENTRY] + * [TCA_TAPRIO_SCHED_ENTRY_CMD] + * [TCA_TAPRIO_SCHED_ENTRY_GATES] + * [TCA_TAPRIO_SCHED_ENTRY_INTERVAL] + */ +enum { + TCA_TAPRIO_SCHED_UNSPEC, + TCA_TAPRIO_SCHED_ENTRY, + __TCA_TAPRIO_SCHED_MAX, +}; + +#define TCA_TAPRIO_SCHED_MAX (__TCA_TAPRIO_SCHED_MAX - 1) + +/* The format for the admin sched (dump only): + * [TCA_TAPRIO_SCHED_ADMIN_SCHED] + * [TCA_TAPRIO_ATTR_SCHED_BASE_TIME] + * [TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST] + * [TCA_TAPRIO_ATTR_SCHED_ENTRY] + * [TCA_TAPRIO_ATTR_SCHED_ENTRY_CMD] + * [TCA_TAPRIO_ATTR_SCHED_ENTRY_GATES] + * [TCA_TAPRIO_ATTR_SCHED_ENTRY_INTERVAL] + */ + +#define TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST BIT(0) +#define TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD BIT(1) + +enum { + TCA_TAPRIO_ATTR_UNSPEC, + TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */ + TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST, /* nested of entry */ + TCA_TAPRIO_ATTR_SCHED_BASE_TIME, /* s64 */ + TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY, /* single entry */ + TCA_TAPRIO_ATTR_SCHED_CLOCKID, /* s32 */ + TCA_TAPRIO_PAD, + TCA_TAPRIO_ATTR_ADMIN_SCHED, /* The admin sched, only used in dump */ + TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME, /* s64 */ + TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION, /* s64 */ + TCA_TAPRIO_ATTR_FLAGS, /* u32 */ + TCA_TAPRIO_ATTR_TXTIME_DELAY, /* u32 */ + __TCA_TAPRIO_ATTR_MAX, +}; + +#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1) + +#endif diff --git a/src/basic/linux/rtnetlink.h b/src/basic/linux/rtnetlink.h new file mode 100644 index 00000000..80ad27fc --- /dev/null +++ b/src/basic/linux/rtnetlink.h @@ -0,0 +1,761 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI__LINUX_RTNETLINK_H +#define _UAPI__LINUX_RTNETLINK_H + +#include +#include +#include +#include +#include + +/* rtnetlink families. Values up to 127 are reserved for real address + * families, values above 128 may be used arbitrarily. + */ +#define RTNL_FAMILY_IPMR 128 +#define RTNL_FAMILY_IP6MR 129 +#define RTNL_FAMILY_MAX 129 + +/**** + * Routing/neighbour discovery messages. + ****/ + +/* Types of messages */ + +enum { + RTM_BASE = 16, +#define RTM_BASE RTM_BASE + + RTM_NEWLINK = 16, +#define RTM_NEWLINK RTM_NEWLINK + RTM_DELLINK, +#define RTM_DELLINK RTM_DELLINK + RTM_GETLINK, +#define RTM_GETLINK RTM_GETLINK + RTM_SETLINK, +#define RTM_SETLINK RTM_SETLINK + + RTM_NEWADDR = 20, +#define RTM_NEWADDR RTM_NEWADDR + RTM_DELADDR, +#define RTM_DELADDR RTM_DELADDR + RTM_GETADDR, +#define RTM_GETADDR RTM_GETADDR + + RTM_NEWROUTE = 24, +#define RTM_NEWROUTE RTM_NEWROUTE + RTM_DELROUTE, +#define RTM_DELROUTE RTM_DELROUTE + RTM_GETROUTE, +#define RTM_GETROUTE RTM_GETROUTE + + RTM_NEWNEIGH = 28, +#define RTM_NEWNEIGH RTM_NEWNEIGH + RTM_DELNEIGH, +#define RTM_DELNEIGH RTM_DELNEIGH + RTM_GETNEIGH, +#define RTM_GETNEIGH RTM_GETNEIGH + + RTM_NEWRULE = 32, +#define RTM_NEWRULE RTM_NEWRULE + RTM_DELRULE, +#define RTM_DELRULE RTM_DELRULE + RTM_GETRULE, +#define RTM_GETRULE RTM_GETRULE + + RTM_NEWQDISC = 36, +#define RTM_NEWQDISC RTM_NEWQDISC + RTM_DELQDISC, +#define RTM_DELQDISC RTM_DELQDISC + RTM_GETQDISC, +#define RTM_GETQDISC RTM_GETQDISC + + RTM_NEWTCLASS = 40, +#define RTM_NEWTCLASS RTM_NEWTCLASS + RTM_DELTCLASS, +#define RTM_DELTCLASS RTM_DELTCLASS + RTM_GETTCLASS, +#define RTM_GETTCLASS RTM_GETTCLASS + + RTM_NEWTFILTER = 44, +#define RTM_NEWTFILTER RTM_NEWTFILTER + RTM_DELTFILTER, +#define RTM_DELTFILTER RTM_DELTFILTER + RTM_GETTFILTER, +#define RTM_GETTFILTER RTM_GETTFILTER + + RTM_NEWACTION = 48, +#define RTM_NEWACTION RTM_NEWACTION + RTM_DELACTION, +#define RTM_DELACTION RTM_DELACTION + RTM_GETACTION, +#define RTM_GETACTION RTM_GETACTION + + RTM_NEWPREFIX = 52, +#define RTM_NEWPREFIX RTM_NEWPREFIX + + RTM_GETMULTICAST = 58, +#define RTM_GETMULTICAST RTM_GETMULTICAST + + RTM_GETANYCAST = 62, +#define RTM_GETANYCAST RTM_GETANYCAST + + RTM_NEWNEIGHTBL = 64, +#define RTM_NEWNEIGHTBL RTM_NEWNEIGHTBL + RTM_GETNEIGHTBL = 66, +#define RTM_GETNEIGHTBL RTM_GETNEIGHTBL + RTM_SETNEIGHTBL, +#define RTM_SETNEIGHTBL RTM_SETNEIGHTBL + + RTM_NEWNDUSEROPT = 68, +#define RTM_NEWNDUSEROPT RTM_NEWNDUSEROPT + + RTM_NEWADDRLABEL = 72, +#define RTM_NEWADDRLABEL RTM_NEWADDRLABEL + RTM_DELADDRLABEL, +#define RTM_DELADDRLABEL RTM_DELADDRLABEL + RTM_GETADDRLABEL, +#define RTM_GETADDRLABEL RTM_GETADDRLABEL + + RTM_GETDCB = 78, +#define RTM_GETDCB RTM_GETDCB + RTM_SETDCB, +#define RTM_SETDCB RTM_SETDCB + + RTM_NEWNETCONF = 80, +#define RTM_NEWNETCONF RTM_NEWNETCONF + RTM_DELNETCONF, +#define RTM_DELNETCONF RTM_DELNETCONF + RTM_GETNETCONF = 82, +#define RTM_GETNETCONF RTM_GETNETCONF + + RTM_NEWMDB = 84, +#define RTM_NEWMDB RTM_NEWMDB + RTM_DELMDB = 85, +#define RTM_DELMDB RTM_DELMDB + RTM_GETMDB = 86, +#define RTM_GETMDB RTM_GETMDB + + RTM_NEWNSID = 88, +#define RTM_NEWNSID RTM_NEWNSID + RTM_DELNSID = 89, +#define RTM_DELNSID RTM_DELNSID + RTM_GETNSID = 90, +#define RTM_GETNSID RTM_GETNSID + + RTM_NEWSTATS = 92, +#define RTM_NEWSTATS RTM_NEWSTATS + RTM_GETSTATS = 94, +#define RTM_GETSTATS RTM_GETSTATS + + RTM_NEWCACHEREPORT = 96, +#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT + + RTM_NEWCHAIN = 100, +#define RTM_NEWCHAIN RTM_NEWCHAIN + RTM_DELCHAIN, +#define RTM_DELCHAIN RTM_DELCHAIN + RTM_GETCHAIN, +#define RTM_GETCHAIN RTM_GETCHAIN + + RTM_NEWNEXTHOP = 104, +#define RTM_NEWNEXTHOP RTM_NEWNEXTHOP + RTM_DELNEXTHOP, +#define RTM_DELNEXTHOP RTM_DELNEXTHOP + RTM_GETNEXTHOP, +#define RTM_GETNEXTHOP RTM_GETNEXTHOP + + __RTM_MAX, +#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) +}; + +#define RTM_NR_MSGTYPES (RTM_MAX + 1 - RTM_BASE) +#define RTM_NR_FAMILIES (RTM_NR_MSGTYPES >> 2) +#define RTM_FAM(cmd) (((cmd) - RTM_BASE) >> 2) + +/* + Generic structure for encapsulation of optional route information. + It is reminiscent of sockaddr, but with sa_family replaced + with attribute type. + */ + +struct rtattr { + unsigned short rta_len; + unsigned short rta_type; +}; + +/* Macros to handle rtattributes */ + +#define RTA_ALIGNTO 4U +#define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) ) +#define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \ + (rta)->rta_len >= sizeof(struct rtattr) && \ + (rta)->rta_len <= (len)) +#define RTA_NEXT(rta,attrlen) ((attrlen) -= RTA_ALIGN((rta)->rta_len), \ + (struct rtattr*)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len))) +#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) +#define RTA_SPACE(len) RTA_ALIGN(RTA_LENGTH(len)) +#define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0))) +#define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0)) + + + + +/****************************************************************************** + * Definitions used in routing table administration. + ****/ + +struct rtmsg { + unsigned char rtm_family; + unsigned char rtm_dst_len; + unsigned char rtm_src_len; + unsigned char rtm_tos; + + unsigned char rtm_table; /* Routing table id */ + unsigned char rtm_protocol; /* Routing protocol; see below */ + unsigned char rtm_scope; /* See below */ + unsigned char rtm_type; /* See below */ + + unsigned rtm_flags; +}; + +/* rtm_type */ + +enum { + RTN_UNSPEC, + RTN_UNICAST, /* Gateway or direct route */ + RTN_LOCAL, /* Accept locally */ + RTN_BROADCAST, /* Accept locally as broadcast, + send as broadcast */ + RTN_ANYCAST, /* Accept locally as broadcast, + but send as unicast */ + RTN_MULTICAST, /* Multicast route */ + RTN_BLACKHOLE, /* Drop */ + RTN_UNREACHABLE, /* Destination is unreachable */ + RTN_PROHIBIT, /* Administratively prohibited */ + RTN_THROW, /* Not in this table */ + RTN_NAT, /* Translate this address */ + RTN_XRESOLVE, /* Use external resolver */ + __RTN_MAX +}; + +#define RTN_MAX (__RTN_MAX - 1) + + +/* rtm_protocol */ + +#define RTPROT_UNSPEC 0 +#define RTPROT_REDIRECT 1 /* Route installed by ICMP redirects; + not used by current IPv4 */ +#define RTPROT_KERNEL 2 /* Route installed by kernel */ +#define RTPROT_BOOT 3 /* Route installed during boot */ +#define RTPROT_STATIC 4 /* Route installed by administrator */ + +/* Values of protocol >= RTPROT_STATIC are not interpreted by kernel; + they are just passed from user and back as is. + It will be used by hypothetical multiple routing daemons. + Note that protocol values should be standardized in order to + avoid conflicts. + */ + +#define RTPROT_GATED 8 /* Apparently, GateD */ +#define RTPROT_RA 9 /* RDISC/ND router advertisements */ +#define RTPROT_MRT 10 /* Merit MRT */ +#define RTPROT_ZEBRA 11 /* Zebra */ +#define RTPROT_BIRD 12 /* BIRD */ +#define RTPROT_DNROUTED 13 /* DECnet routing daemon */ +#define RTPROT_XORP 14 /* XORP */ +#define RTPROT_NTK 15 /* Netsukuku */ +#define RTPROT_DHCP 16 /* DHCP client */ +#define RTPROT_MROUTED 17 /* Multicast daemon */ +#define RTPROT_BABEL 42 /* Babel daemon */ +#define RTPROT_BGP 186 /* BGP Routes */ +#define RTPROT_ISIS 187 /* ISIS Routes */ +#define RTPROT_OSPF 188 /* OSPF Routes */ +#define RTPROT_RIP 189 /* RIP Routes */ +#define RTPROT_EIGRP 192 /* EIGRP Routes */ + +/* rtm_scope + + Really it is not scope, but sort of distance to the destination. + NOWHERE are reserved for not existing destinations, HOST is our + local addresses, LINK are destinations, located on directly attached + link and UNIVERSE is everywhere in the Universe. + + Intermediate values are also possible f.e. interior routes + could be assigned a value between UNIVERSE and LINK. +*/ + +enum rt_scope_t { + RT_SCOPE_UNIVERSE=0, +/* User defined values */ + RT_SCOPE_SITE=200, + RT_SCOPE_LINK=253, + RT_SCOPE_HOST=254, + RT_SCOPE_NOWHERE=255 +}; + +/* rtm_flags */ + +#define RTM_F_NOTIFY 0x100 /* Notify user of route change */ +#define RTM_F_CLONED 0x200 /* This route is cloned */ +#define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */ +#define RTM_F_PREFIX 0x800 /* Prefix addresses */ +#define RTM_F_LOOKUP_TABLE 0x1000 /* set rtm_table to FIB lookup result */ +#define RTM_F_FIB_MATCH 0x2000 /* return full fib lookup match */ + +/* Reserved table identifiers */ + +enum rt_class_t { + RT_TABLE_UNSPEC=0, +/* User defined values */ + RT_TABLE_COMPAT=252, + RT_TABLE_DEFAULT=253, + RT_TABLE_MAIN=254, + RT_TABLE_LOCAL=255, + RT_TABLE_MAX=0xFFFFFFFF +}; + + +/* Routing message attributes */ + +enum rtattr_type_t { + RTA_UNSPEC, + RTA_DST, + RTA_SRC, + RTA_IIF, + RTA_OIF, + RTA_GATEWAY, + RTA_PRIORITY, + RTA_PREFSRC, + RTA_METRICS, + RTA_MULTIPATH, + RTA_PROTOINFO, /* no longer used */ + RTA_FLOW, + RTA_CACHEINFO, + RTA_SESSION, /* no longer used */ + RTA_MP_ALGO, /* no longer used */ + RTA_TABLE, + RTA_MARK, + RTA_MFC_STATS, + RTA_VIA, + RTA_NEWDST, + RTA_PREF, + RTA_ENCAP_TYPE, + RTA_ENCAP, + RTA_EXPIRES, + RTA_PAD, + RTA_UID, + RTA_TTL_PROPAGATE, + RTA_IP_PROTO, + RTA_SPORT, + RTA_DPORT, + RTA_NH_ID, + __RTA_MAX +}; + +#define RTA_MAX (__RTA_MAX - 1) + +#define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg)))) +#define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg)) + +/* RTM_MULTIPATH --- array of struct rtnexthop. + * + * "struct rtnexthop" describes all necessary nexthop information, + * i.e. parameters of path to a destination via this nexthop. + * + * At the moment it is impossible to set different prefsrc, mtu, window + * and rtt for different paths from multipath. + */ + +struct rtnexthop { + unsigned short rtnh_len; + unsigned char rtnh_flags; + unsigned char rtnh_hops; + int rtnh_ifindex; +}; + +/* rtnh_flags */ + +#define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */ +#define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */ +#define RTNH_F_ONLINK 4 /* Gateway is forced on link */ +#define RTNH_F_OFFLOAD 8 /* offloaded route */ +#define RTNH_F_LINKDOWN 16 /* carrier-down on nexthop */ +#define RTNH_F_UNRESOLVED 32 /* The entry is unresolved (ipmr) */ + +#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN | RTNH_F_OFFLOAD) + +/* Macros to handle hexthops */ + +#define RTNH_ALIGNTO 4 +#define RTNH_ALIGN(len) ( ((len)+RTNH_ALIGNTO-1) & ~(RTNH_ALIGNTO-1) ) +#define RTNH_OK(rtnh,len) ((rtnh)->rtnh_len >= sizeof(struct rtnexthop) && \ + ((int)(rtnh)->rtnh_len) <= (len)) +#define RTNH_NEXT(rtnh) ((struct rtnexthop*)(((char*)(rtnh)) + RTNH_ALIGN((rtnh)->rtnh_len))) +#define RTNH_LENGTH(len) (RTNH_ALIGN(sizeof(struct rtnexthop)) + (len)) +#define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len)) +#define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0))) + +/* RTA_VIA */ +struct rtvia { + __kernel_sa_family_t rtvia_family; + __u8 rtvia_addr[0]; +}; + +/* RTM_CACHEINFO */ + +struct rta_cacheinfo { + __u32 rta_clntref; + __u32 rta_lastuse; + __s32 rta_expires; + __u32 rta_error; + __u32 rta_used; + +#define RTNETLINK_HAVE_PEERINFO 1 + __u32 rta_id; + __u32 rta_ts; + __u32 rta_tsage; +}; + +/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */ + +enum { + RTAX_UNSPEC, +#define RTAX_UNSPEC RTAX_UNSPEC + RTAX_LOCK, +#define RTAX_LOCK RTAX_LOCK + RTAX_MTU, +#define RTAX_MTU RTAX_MTU + RTAX_WINDOW, +#define RTAX_WINDOW RTAX_WINDOW + RTAX_RTT, +#define RTAX_RTT RTAX_RTT + RTAX_RTTVAR, +#define RTAX_RTTVAR RTAX_RTTVAR + RTAX_SSTHRESH, +#define RTAX_SSTHRESH RTAX_SSTHRESH + RTAX_CWND, +#define RTAX_CWND RTAX_CWND + RTAX_ADVMSS, +#define RTAX_ADVMSS RTAX_ADVMSS + RTAX_REORDERING, +#define RTAX_REORDERING RTAX_REORDERING + RTAX_HOPLIMIT, +#define RTAX_HOPLIMIT RTAX_HOPLIMIT + RTAX_INITCWND, +#define RTAX_INITCWND RTAX_INITCWND + RTAX_FEATURES, +#define RTAX_FEATURES RTAX_FEATURES + RTAX_RTO_MIN, +#define RTAX_RTO_MIN RTAX_RTO_MIN + RTAX_INITRWND, +#define RTAX_INITRWND RTAX_INITRWND + RTAX_QUICKACK, +#define RTAX_QUICKACK RTAX_QUICKACK + RTAX_CC_ALGO, +#define RTAX_CC_ALGO RTAX_CC_ALGO + RTAX_FASTOPEN_NO_COOKIE, +#define RTAX_FASTOPEN_NO_COOKIE RTAX_FASTOPEN_NO_COOKIE + __RTAX_MAX +}; + +#define RTAX_MAX (__RTAX_MAX - 1) + +#define RTAX_FEATURE_ECN (1 << 0) +#define RTAX_FEATURE_SACK (1 << 1) +#define RTAX_FEATURE_TIMESTAMP (1 << 2) +#define RTAX_FEATURE_ALLFRAG (1 << 3) + +#define RTAX_FEATURE_MASK (RTAX_FEATURE_ECN | RTAX_FEATURE_SACK | \ + RTAX_FEATURE_TIMESTAMP | RTAX_FEATURE_ALLFRAG) + +struct rta_session { + __u8 proto; + __u8 pad1; + __u16 pad2; + + union { + struct { + __u16 sport; + __u16 dport; + } ports; + + struct { + __u8 type; + __u8 code; + __u16 ident; + } icmpt; + + __u32 spi; + } u; +}; + +struct rta_mfc_stats { + __u64 mfcs_packets; + __u64 mfcs_bytes; + __u64 mfcs_wrong_if; +}; + +/**** + * General form of address family dependent message. + ****/ + +struct rtgenmsg { + unsigned char rtgen_family; +}; + +/***************************************************************** + * Link layer specific messages. + ****/ + +/* struct ifinfomsg + * passes link level specific information, not dependent + * on network protocol. + */ + +struct ifinfomsg { + unsigned char ifi_family; + unsigned char __ifi_pad; + unsigned short ifi_type; /* ARPHRD_* */ + int ifi_index; /* Link index */ + unsigned ifi_flags; /* IFF_* flags */ + unsigned ifi_change; /* IFF_* change mask */ +}; + +/******************************************************************** + * prefix information + ****/ + +struct prefixmsg { + unsigned char prefix_family; + unsigned char prefix_pad1; + unsigned short prefix_pad2; + int prefix_ifindex; + unsigned char prefix_type; + unsigned char prefix_len; + unsigned char prefix_flags; + unsigned char prefix_pad3; +}; + +enum +{ + PREFIX_UNSPEC, + PREFIX_ADDRESS, + PREFIX_CACHEINFO, + __PREFIX_MAX +}; + +#define PREFIX_MAX (__PREFIX_MAX - 1) + +struct prefix_cacheinfo { + __u32 preferred_time; + __u32 valid_time; +}; + + +/***************************************************************** + * Traffic control messages. + ****/ + +struct tcmsg { + unsigned char tcm_family; + unsigned char tcm__pad1; + unsigned short tcm__pad2; + int tcm_ifindex; + __u32 tcm_handle; + __u32 tcm_parent; +/* tcm_block_index is used instead of tcm_parent + * in case tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK + */ +#define tcm_block_index tcm_parent + __u32 tcm_info; +}; + +/* For manipulation of filters in shared block, tcm_ifindex is set to + * TCM_IFINDEX_MAGIC_BLOCK, and tcm_parent is aliased to tcm_block_index + * which is the block index. + */ +#define TCM_IFINDEX_MAGIC_BLOCK (0xFFFFFFFFU) + +enum { + TCA_UNSPEC, + TCA_KIND, + TCA_OPTIONS, + TCA_STATS, + TCA_XSTATS, + TCA_RATE, + TCA_FCNT, + TCA_STATS2, + TCA_STAB, + TCA_PAD, + TCA_DUMP_INVISIBLE, + TCA_CHAIN, + TCA_HW_OFFLOAD, + TCA_INGRESS_BLOCK, + TCA_EGRESS_BLOCK, + __TCA_MAX +}; + +#define TCA_MAX (__TCA_MAX - 1) + +#define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg)))) +#define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg)) + +/******************************************************************** + * Neighbor Discovery userland options + ****/ + +struct nduseroptmsg { + unsigned char nduseropt_family; + unsigned char nduseropt_pad1; + unsigned short nduseropt_opts_len; /* Total length of options */ + int nduseropt_ifindex; + __u8 nduseropt_icmp_type; + __u8 nduseropt_icmp_code; + unsigned short nduseropt_pad2; + unsigned int nduseropt_pad3; + /* Followed by one or more ND options */ +}; + +enum { + NDUSEROPT_UNSPEC, + NDUSEROPT_SRCADDR, + __NDUSEROPT_MAX +}; + +#define NDUSEROPT_MAX (__NDUSEROPT_MAX - 1) + +#ifndef __KERNEL__ +/* RTnetlink multicast groups - backwards compatibility for userspace */ +#define RTMGRP_LINK 1 +#define RTMGRP_NOTIFY 2 +#define RTMGRP_NEIGH 4 +#define RTMGRP_TC 8 + +#define RTMGRP_IPV4_IFADDR 0x10 +#define RTMGRP_IPV4_MROUTE 0x20 +#define RTMGRP_IPV4_ROUTE 0x40 +#define RTMGRP_IPV4_RULE 0x80 + +#define RTMGRP_IPV6_IFADDR 0x100 +#define RTMGRP_IPV6_MROUTE 0x200 +#define RTMGRP_IPV6_ROUTE 0x400 +#define RTMGRP_IPV6_IFINFO 0x800 + +#define RTMGRP_DECnet_IFADDR 0x1000 +#define RTMGRP_DECnet_ROUTE 0x4000 + +#define RTMGRP_IPV6_PREFIX 0x20000 +#endif + +/* RTnetlink multicast groups */ +enum rtnetlink_groups { + RTNLGRP_NONE, +#define RTNLGRP_NONE RTNLGRP_NONE + RTNLGRP_LINK, +#define RTNLGRP_LINK RTNLGRP_LINK + RTNLGRP_NOTIFY, +#define RTNLGRP_NOTIFY RTNLGRP_NOTIFY + RTNLGRP_NEIGH, +#define RTNLGRP_NEIGH RTNLGRP_NEIGH + RTNLGRP_TC, +#define RTNLGRP_TC RTNLGRP_TC + RTNLGRP_IPV4_IFADDR, +#define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR + RTNLGRP_IPV4_MROUTE, +#define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE + RTNLGRP_IPV4_ROUTE, +#define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE + RTNLGRP_IPV4_RULE, +#define RTNLGRP_IPV4_RULE RTNLGRP_IPV4_RULE + RTNLGRP_IPV6_IFADDR, +#define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR + RTNLGRP_IPV6_MROUTE, +#define RTNLGRP_IPV6_MROUTE RTNLGRP_IPV6_MROUTE + RTNLGRP_IPV6_ROUTE, +#define RTNLGRP_IPV6_ROUTE RTNLGRP_IPV6_ROUTE + RTNLGRP_IPV6_IFINFO, +#define RTNLGRP_IPV6_IFINFO RTNLGRP_IPV6_IFINFO + RTNLGRP_DECnet_IFADDR, +#define RTNLGRP_DECnet_IFADDR RTNLGRP_DECnet_IFADDR + RTNLGRP_NOP2, + RTNLGRP_DECnet_ROUTE, +#define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE + RTNLGRP_DECnet_RULE, +#define RTNLGRP_DECnet_RULE RTNLGRP_DECnet_RULE + RTNLGRP_NOP4, + RTNLGRP_IPV6_PREFIX, +#define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX + RTNLGRP_IPV6_RULE, +#define RTNLGRP_IPV6_RULE RTNLGRP_IPV6_RULE + RTNLGRP_ND_USEROPT, +#define RTNLGRP_ND_USEROPT RTNLGRP_ND_USEROPT + RTNLGRP_PHONET_IFADDR, +#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR + RTNLGRP_PHONET_ROUTE, +#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE + RTNLGRP_DCB, +#define RTNLGRP_DCB RTNLGRP_DCB + RTNLGRP_IPV4_NETCONF, +#define RTNLGRP_IPV4_NETCONF RTNLGRP_IPV4_NETCONF + RTNLGRP_IPV6_NETCONF, +#define RTNLGRP_IPV6_NETCONF RTNLGRP_IPV6_NETCONF + RTNLGRP_MDB, +#define RTNLGRP_MDB RTNLGRP_MDB + RTNLGRP_MPLS_ROUTE, +#define RTNLGRP_MPLS_ROUTE RTNLGRP_MPLS_ROUTE + RTNLGRP_NSID, +#define RTNLGRP_NSID RTNLGRP_NSID + RTNLGRP_MPLS_NETCONF, +#define RTNLGRP_MPLS_NETCONF RTNLGRP_MPLS_NETCONF + RTNLGRP_IPV4_MROUTE_R, +#define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R + RTNLGRP_IPV6_MROUTE_R, +#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R + RTNLGRP_NEXTHOP, +#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP + __RTNLGRP_MAX +}; +#define RTNLGRP_MAX (__RTNLGRP_MAX - 1) + +/* TC action piece */ +struct tcamsg { + unsigned char tca_family; + unsigned char tca__pad1; + unsigned short tca__pad2; +}; + +enum { + TCA_ROOT_UNSPEC, + TCA_ROOT_TAB, +#define TCA_ACT_TAB TCA_ROOT_TAB +#define TCAA_MAX TCA_ROOT_TAB + TCA_ROOT_FLAGS, + TCA_ROOT_COUNT, + TCA_ROOT_TIME_DELTA, /* in msecs */ + __TCA_ROOT_MAX, +#define TCA_ROOT_MAX (__TCA_ROOT_MAX - 1) +}; + +#define TA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcamsg)))) +#define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg)) +/* tcamsg flags stored in attribute TCA_ROOT_FLAGS + * + * TCA_FLAG_LARGE_DUMP_ON user->kernel to request for larger than TCA_ACT_MAX_PRIO + * actions in a dump. All dump responses will contain the number of actions + * being dumped stored in for user app's consumption in TCA_ROOT_COUNT + * + */ +#define TCA_FLAG_LARGE_DUMP_ON (1 << 0) + +/* New extended info filters for IFLA_EXT_MASK */ +#define RTEXT_FILTER_VF (1 << 0) +#define RTEXT_FILTER_BRVLAN (1 << 1) +#define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2) +#define RTEXT_FILTER_SKIP_STATS (1 << 3) + +/* End of information exported to user level */ + + + +#endif /* _UAPI__LINUX_RTNETLINK_H */ diff --git a/src/basic/linux/update.sh b/src/basic/linux/update.sh new file mode 100755 index 00000000..b2320701 --- /dev/null +++ b/src/basic/linux/update.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -eu + +for i in *.h */*.h; do + if [[ $i == 'wireguard.h' ]]; then + curl https://raw.githubusercontent.com/WireGuard/WireGuard/master/src/uapi/$i -o $i + else + curl https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/$i -o $i + fi + + sed -i -e 's/__user //g' -e '/^#include / d' $i +done diff --git a/src/basic/linux/wireguard.h b/src/basic/linux/wireguard.h new file mode 100644 index 00000000..071ce416 --- /dev/null +++ b/src/basic/linux/wireguard.h @@ -0,0 +1,190 @@ +/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT */ +/* + * Copyright (C) 2015-2019 Jason A. Donenfeld . All Rights Reserved. + * + * Documentation + * ============= + * + * The below enums and macros are for interfacing with WireGuard, using generic + * netlink, with family WG_GENL_NAME and version WG_GENL_VERSION. It defines two + * methods: get and set. Note that while they share many common attributes, + * these two functions actually accept a slightly different set of inputs and + * outputs. + * + * WG_CMD_GET_DEVICE + * ----------------- + * + * May only be called via NLM_F_REQUEST | NLM_F_DUMP. The command should contain + * one but not both of: + * + * WGDEVICE_A_IFINDEX: NLA_U32 + * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 + * + * The kernel will then return several messages (NLM_F_MULTI) containing the + * following tree of nested items: + * + * WGDEVICE_A_IFINDEX: NLA_U32 + * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 + * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN + * WGDEVICE_A_PUBLIC_KEY: len WG_KEY_LEN + * WGDEVICE_A_LISTEN_PORT: NLA_U16 + * WGDEVICE_A_FWMARK: NLA_U32 + * WGDEVICE_A_PEERS: NLA_NESTED + * 0: NLA_NESTED + * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN + * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN + * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6 + * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16 + * WGPEER_A_LAST_HANDSHAKE_TIME: struct __kernel_timespec + * WGPEER_A_RX_BYTES: NLA_U64 + * WGPEER_A_TX_BYTES: NLA_U64 + * WGPEER_A_ALLOWEDIPS: NLA_NESTED + * 0: NLA_NESTED + * WGALLOWEDIP_A_FAMILY: NLA_U16 + * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr + * WGALLOWEDIP_A_CIDR_MASK: NLA_U8 + * 0: NLA_NESTED + * ... + * 0: NLA_NESTED + * ... + * ... + * WGPEER_A_PROTOCOL_VERSION: NLA_U32 + * 0: NLA_NESTED + * ... + * ... + * + * It is possible that all of the allowed IPs of a single peer will not + * fit within a single netlink message. In that case, the same peer will + * be written in the following message, except it will only contain + * WGPEER_A_PUBLIC_KEY and WGPEER_A_ALLOWEDIPS. This may occur several + * times in a row for the same peer. It is then up to the receiver to + * coalesce adjacent peers. Likewise, it is possible that all peers will + * not fit within a single message. So, subsequent peers will be sent + * in following messages, except those will only contain WGDEVICE_A_IFNAME + * and WGDEVICE_A_PEERS. It is then up to the receiver to coalesce these + * messages to form the complete list of peers. + * + * Since this is an NLA_F_DUMP command, the final message will always be + * NLMSG_DONE, even if an error occurs. However, this NLMSG_DONE message + * contains an integer error code. It is either zero or a negative error + * code corresponding to the errno. + * + * WG_CMD_SET_DEVICE + * ----------------- + * + * May only be called via NLM_F_REQUEST. The command should contain the + * following tree of nested items, containing one but not both of + * WGDEVICE_A_IFINDEX and WGDEVICE_A_IFNAME: + * + * WGDEVICE_A_IFINDEX: NLA_U32 + * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 + * WGDEVICE_A_FLAGS: NLA_U32, 0 or WGDEVICE_F_REPLACE_PEERS if all current + * peers should be removed prior to adding the list below. + * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN, all zeros to remove + * WGDEVICE_A_LISTEN_PORT: NLA_U16, 0 to choose randomly + * WGDEVICE_A_FWMARK: NLA_U32, 0 to disable + * WGDEVICE_A_PEERS: NLA_NESTED + * 0: NLA_NESTED + * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN + * WGPEER_A_FLAGS: NLA_U32, 0 and/or WGPEER_F_REMOVE_ME if the + * specified peer should be removed rather than + * added/updated and/or WGPEER_F_REPLACE_ALLOWEDIPS + * if all current allowed IPs of this peer should be + * removed prior to adding the list below. + * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN, all zeros to remove + * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6 + * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16, 0 to disable + * WGPEER_A_ALLOWEDIPS: NLA_NESTED + * 0: NLA_NESTED + * WGALLOWEDIP_A_FAMILY: NLA_U16 + * WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr + * WGALLOWEDIP_A_CIDR_MASK: NLA_U8 + * 0: NLA_NESTED + * ... + * 0: NLA_NESTED + * ... + * ... + * WGPEER_A_PROTOCOL_VERSION: NLA_U32, should not be set or used at + * all by most users of this API, as the + * most recent protocol will be used when + * this is unset. Otherwise, must be set + * to 1. + * 0: NLA_NESTED + * ... + * ... + * + * It is possible that the amount of configuration data exceeds that of + * the maximum message length accepted by the kernel. In that case, several + * messages should be sent one after another, with each successive one + * filling in information not contained in the prior. Note that if + * WGDEVICE_F_REPLACE_PEERS is specified in the first message, it probably + * should not be specified in fragments that come after, so that the list + * of peers is only cleared the first time but appened after. Likewise for + * peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in the first message + * of a peer, it likely should not be specified in subsequent fragments. + * + * If an error occurs, NLMSG_ERROR will reply containing an errno. + */ + +#ifndef _WG_UAPI_WIREGUARD_H +#define _WG_UAPI_WIREGUARD_H + +#define WG_GENL_NAME "wireguard" +#define WG_GENL_VERSION 1 + +#define WG_KEY_LEN 32 + +enum wg_cmd { + WG_CMD_GET_DEVICE, + WG_CMD_SET_DEVICE, + __WG_CMD_MAX +}; +#define WG_CMD_MAX (__WG_CMD_MAX - 1) + +enum wgdevice_flag { + WGDEVICE_F_REPLACE_PEERS = 1U << 0 +}; +enum wgdevice_attribute { + WGDEVICE_A_UNSPEC, + WGDEVICE_A_IFINDEX, + WGDEVICE_A_IFNAME, + WGDEVICE_A_PRIVATE_KEY, + WGDEVICE_A_PUBLIC_KEY, + WGDEVICE_A_FLAGS, + WGDEVICE_A_LISTEN_PORT, + WGDEVICE_A_FWMARK, + WGDEVICE_A_PEERS, + __WGDEVICE_A_LAST +}; +#define WGDEVICE_A_MAX (__WGDEVICE_A_LAST - 1) + +enum wgpeer_flag { + WGPEER_F_REMOVE_ME = 1U << 0, + WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1 +}; +enum wgpeer_attribute { + WGPEER_A_UNSPEC, + WGPEER_A_PUBLIC_KEY, + WGPEER_A_PRESHARED_KEY, + WGPEER_A_FLAGS, + WGPEER_A_ENDPOINT, + WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, + WGPEER_A_LAST_HANDSHAKE_TIME, + WGPEER_A_RX_BYTES, + WGPEER_A_TX_BYTES, + WGPEER_A_ALLOWEDIPS, + WGPEER_A_PROTOCOL_VERSION, + __WGPEER_A_LAST +}; +#define WGPEER_A_MAX (__WGPEER_A_LAST - 1) + +enum wgallowedip_attribute { + WGALLOWEDIP_A_UNSPEC, + WGALLOWEDIP_A_FAMILY, + WGALLOWEDIP_A_IPADDR, + WGALLOWEDIP_A_CIDR_MASK, + __WGALLOWEDIP_A_LAST +}; +#define WGALLOWEDIP_A_MAX (__WGALLOWEDIP_A_LAST - 1) + +#endif /* _WG_UAPI_WIREGUARD_H */ diff --git a/src/basic/list.h b/src/basic/list.h new file mode 100644 index 00000000..f7f97000 --- /dev/null +++ b/src/basic/list.h @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "macro.h" + +/* The head of the linked list. Use this in the structure that shall + * contain the head of the linked list */ +#define LIST_HEAD(t,name) \ + t *name + +/* The pointers in the linked list's items. Use this in the item structure */ +#define LIST_FIELDS(t,name) \ + t *name##_next, *name##_prev + +/* Initialize the list's head */ +#define LIST_HEAD_INIT(head) \ + do { \ + (head) = NULL; \ + } while (false) + +/* Initialize a list item */ +#define LIST_INIT(name,item) \ + do { \ + typeof(*(item)) *_item = (item); \ + assert(_item); \ + _item->name##_prev = _item->name##_next = NULL; \ + } while (false) + +/* Prepend an item to the list */ +#define LIST_PREPEND(name,head,item) \ + do { \ + typeof(*(head)) **_head = &(head), *_item = (item); \ + assert(_item); \ + if ((_item->name##_next = *_head)) \ + _item->name##_next->name##_prev = _item; \ + _item->name##_prev = NULL; \ + *_head = _item; \ + } while (false) + +/* Append an item to the list */ +#define LIST_APPEND(name,head,item) \ + do { \ + typeof(*(head)) **_hhead = &(head), *_tail; \ + LIST_FIND_TAIL(name, *_hhead, _tail); \ + LIST_INSERT_AFTER(name, *_hhead, _tail, item); \ + } while (false) + +/* Remove an item from the list */ +#define LIST_REMOVE(name,head,item) \ + do { \ + typeof(*(head)) **_head = &(head), *_item = (item); \ + assert(_item); \ + if (_item->name##_next) \ + _item->name##_next->name##_prev = _item->name##_prev; \ + if (_item->name##_prev) \ + _item->name##_prev->name##_next = _item->name##_next; \ + else { \ + assert(*_head == _item); \ + *_head = _item->name##_next; \ + } \ + _item->name##_next = _item->name##_prev = NULL; \ + } while (false) + +/* Find the head of the list */ +#define LIST_FIND_HEAD(name,item,head) \ + do { \ + typeof(*(item)) *_item = (item); \ + if (!_item) \ + (head) = NULL; \ + else { \ + while (_item->name##_prev) \ + _item = _item->name##_prev; \ + (head) = _item; \ + } \ + } while (false) + +/* Find the tail of the list */ +#define LIST_FIND_TAIL(name,item,tail) \ + do { \ + typeof(*(item)) *_item = (item); \ + if (!_item) \ + (tail) = NULL; \ + else { \ + while (_item->name##_next) \ + _item = _item->name##_next; \ + (tail) = _item; \ + } \ + } while (false) + +/* Insert an item after another one (a = where, b = what) */ +#define LIST_INSERT_AFTER(name,head,a,b) \ + do { \ + typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \ + assert(_b); \ + if (!_a) { \ + if ((_b->name##_next = *_head)) \ + _b->name##_next->name##_prev = _b; \ + _b->name##_prev = NULL; \ + *_head = _b; \ + } else { \ + if ((_b->name##_next = _a->name##_next)) \ + _b->name##_next->name##_prev = _b; \ + _b->name##_prev = _a; \ + _a->name##_next = _b; \ + } \ + } while (false) + +/* Insert an item before another one (a = where, b = what) */ +#define LIST_INSERT_BEFORE(name,head,a,b) \ + do { \ + typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \ + assert(_b); \ + if (!_a) { \ + if (!*_head) { \ + _b->name##_next = NULL; \ + _b->name##_prev = NULL; \ + *_head = _b; \ + } else { \ + typeof(*(head)) *_tail = (head); \ + while (_tail->name##_next) \ + _tail = _tail->name##_next; \ + _b->name##_next = NULL; \ + _b->name##_prev = _tail; \ + _tail->name##_next = _b; \ + } \ + } else { \ + if ((_b->name##_prev = _a->name##_prev)) \ + _b->name##_prev->name##_next = _b; \ + else \ + *_head = _b; \ + _b->name##_next = _a; \ + _a->name##_prev = _b; \ + } \ + } while (false) + +#define LIST_JUST_US(name,item) \ + (!(item)->name##_prev && !(item)->name##_next) \ + +#define LIST_FOREACH(name,i,head) \ + for ((i) = (head); (i); (i) = (i)->name##_next) + +#define LIST_FOREACH_SAFE(name,i,n,head) \ + for ((i) = (head); (i) && (((n) = (i)->name##_next), 1); (i) = (n)) + +#define LIST_FOREACH_BEFORE(name,i,p) \ + for ((i) = (p)->name##_prev; (i); (i) = (i)->name##_prev) + +#define LIST_FOREACH_AFTER(name,i,p) \ + for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next) + +/* Iterate through all the members of the list p is included in, but skip over p */ +#define LIST_FOREACH_OTHERS(name,i,p) \ + for (({ \ + (i) = (p); \ + while ((i) && (i)->name##_prev) \ + (i) = (i)->name##_prev; \ + if ((i) == (p)) \ + (i) = (p)->name##_next; \ + }); \ + (i); \ + (i) = (i)->name##_next == (p) ? (p)->name##_next : (i)->name##_next) + +/* Loop starting from p->next until p->prev. + p can be adjusted meanwhile. */ +#define LIST_LOOP_BUT_ONE(name,i,head,p) \ + for ((i) = (p)->name##_next ? (p)->name##_next : (head); \ + (i) != (p); \ + (i) = (i)->name##_next ? (i)->name##_next : (head)) + +#define LIST_IS_EMPTY(head) \ + (!(head)) diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c new file mode 100644 index 00000000..b3c58057 --- /dev/null +++ b/src/basic/locale-util.c @@ -0,0 +1,417 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "def.h" +#include "dirent-util.h" +#include "env-util.h" +#include "fd-util.h" +#include "hashmap.h" +#include "locale-util.h" +#include "path-util.h" +#include "set.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "utf8.h" + +static char *normalize_locale(const char *name) { + const char *e; + + /* Locale names are weird: glibc has some magic rules when looking for the charset name on disk: it + * lowercases everything, and removes most special chars. This means the official .UTF-8 suffix + * becomes .utf8 when looking things up on disk. When enumerating locales, let's do the reverse + * operation, and go back to ".UTF-8" which appears to be the more commonly accepted name. We only do + * that for UTF-8 however, since it's kinda the only charset that matters. */ + + e = endswith(name, ".utf8"); + if (e) { + _cleanup_free_ char *prefix = NULL; + + prefix = strndup(name, e - name); + if (!prefix) + return NULL; + + return strjoin(prefix, ".UTF-8"); + } + + e = strstr(name, ".utf8@"); + if (e) { + _cleanup_free_ char *prefix = NULL; + + prefix = strndup(name, e - name); + if (!prefix) + return NULL; + + return strjoin(prefix, ".UTF-8@", e + 6); + } + + return strdup(name); +} + +static int add_locales_from_archive(Set *locales) { + /* Stolen from glibc... */ + + struct locarhead { + uint32_t magic; + /* Serial number. */ + uint32_t serial; + /* Name hash table. */ + uint32_t namehash_offset; + uint32_t namehash_used; + uint32_t namehash_size; + /* String table. */ + uint32_t string_offset; + uint32_t string_used; + uint32_t string_size; + /* Table with locale records. */ + uint32_t locrectab_offset; + uint32_t locrectab_used; + uint32_t locrectab_size; + /* MD5 sum hash table. */ + uint32_t sumhash_offset; + uint32_t sumhash_used; + uint32_t sumhash_size; + }; + + struct namehashent { + /* Hash value of the name. */ + uint32_t hashval; + /* Offset of the name in the string table. */ + uint32_t name_offset; + /* Offset of the locale record. */ + uint32_t locrec_offset; + }; + + const struct locarhead *h; + const struct namehashent *e; + const void *p = MAP_FAILED; + _cleanup_close_ int fd = -1; + size_t sz = 0; + struct stat st; + size_t i; + int r; + + fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return errno == ENOENT ? 0 : -errno; + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISREG(st.st_mode)) + return -EBADMSG; + + if (st.st_size < (off_t) sizeof(struct locarhead)) + return -EBADMSG; + + p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (p == MAP_FAILED) + return -errno; + + h = (const struct locarhead *) p; + if (h->magic != 0xde020109 || + h->namehash_offset + h->namehash_size > st.st_size || + h->string_offset + h->string_size > st.st_size || + h->locrectab_offset + h->locrectab_size > st.st_size || + h->sumhash_offset + h->sumhash_size > st.st_size) { + r = -EBADMSG; + goto finish; + } + + e = (const struct namehashent*) ((const uint8_t*) p + h->namehash_offset); + for (i = 0; i < h->namehash_size; i++) { + char *z; + + if (e[i].locrec_offset == 0) + continue; + + if (!utf8_is_valid((char*) p + e[i].name_offset)) + continue; + + z = normalize_locale((char*) p + e[i].name_offset); + if (!z) { + r = -ENOMEM; + goto finish; + } + + r = set_consume(locales, z); + if (r < 0) + goto finish; + } + + r = 0; + + finish: + if (p != MAP_FAILED) + munmap((void*) p, sz); + + return r; +} + +static int add_locales_from_libdir (Set *locales) { + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *entry; + int r; + + dir = opendir("/usr/lib/locale"); + if (!dir) + return errno == ENOENT ? 0 : -errno; + + FOREACH_DIRENT(entry, dir, return -errno) { + char *z; + + dirent_ensure_type(dir, entry); + + if (entry->d_type != DT_DIR) + continue; + + z = normalize_locale(entry->d_name); + if (!z) + return -ENOMEM; + + r = set_consume(locales, z); + if (r < 0 && r != -EEXIST) + return r; + } + + return 0; +} + +int get_locales(char ***ret) { + _cleanup_set_free_ Set *locales = NULL; + _cleanup_strv_free_ char **l = NULL; + int r; + + locales = set_new(&string_hash_ops); + if (!locales) + return -ENOMEM; + + r = add_locales_from_archive(locales); + if (r < 0 && r != -ENOENT) + return r; + + r = add_locales_from_libdir(locales); + if (r < 0) + return r; + + l = set_get_strv(locales); + if (!l) + return -ENOMEM; + + r = getenv_bool("SYSTEMD_LIST_NON_UTF8_LOCALES"); + if (r == -ENXIO || r == 0) { + char **a, **b; + + /* Filter out non-UTF-8 locales, because it's 2019, by default */ + for (a = b = l; *a; a++) { + + if (endswith(*a, "UTF-8") || + strstr(*a, ".UTF-8@")) + *(b++) = *a; + else + free(*a); + } + + *b = NULL; + + } else if (r < 0) + log_debug_errno(r, "Failed to parse $SYSTEMD_LIST_NON_UTF8_LOCALES as boolean"); + + strv_sort(l); + + *ret = TAKE_PTR(l); + + return 0; +} + +bool locale_is_valid(const char *name) { + + if (isempty(name)) + return false; + + if (strlen(name) >= 128) + return false; + + if (!utf8_is_valid(name)) + return false; + + if (!filename_is_valid(name)) + return false; + + if (!string_is_safe(name)) + return false; + + return true; +} + +void init_gettext(void) { + setlocale(LC_ALL, ""); + textdomain(GETTEXT_PACKAGE); +} + +bool is_locale_utf8(void) { + const char *set; + static int cached_answer = -1; + + /* Note that we default to 'true' here, since today UTF8 is + * pretty much supported everywhere. */ + + if (cached_answer >= 0) + goto out; + + if (!setlocale(LC_ALL, "")) { + cached_answer = true; + goto out; + } + + set = nl_langinfo(CODESET); + if (!set) { + cached_answer = true; + goto out; + } + + if (streq(set, "UTF-8")) { + cached_answer = true; + goto out; + } + + /* For LC_CTYPE=="C" return true, because CTYPE is effectively + * unset and everything can do to UTF-8 nowadays. */ + set = setlocale(LC_CTYPE, NULL); + if (!set) { + cached_answer = true; + goto out; + } + + /* Check result, but ignore the result if C was set + * explicitly. */ + cached_answer = + STR_IN_SET(set, "C", "POSIX") && + !getenv("LC_ALL") && + !getenv("LC_CTYPE") && + !getenv("LANG"); + +out: + return (bool) cached_answer; +} + +static bool emoji_enabled(void) { + static int cached_emoji_enabled = -1; + + if (cached_emoji_enabled < 0) { + int val; + + val = getenv_bool("SYSTEMD_EMOJI"); + if (val < 0) + cached_emoji_enabled = + is_locale_utf8() && + !STRPTR_IN_SET(getenv("TERM"), "dumb", "linux"); + else + cached_emoji_enabled = val; + } + + return cached_emoji_enabled; +} + +const char *special_glyph(SpecialGlyph code) { + + /* A list of a number of interesting unicode glyphs we can use to decorate our output. It's probably wise to be + * conservative here, and primarily stick to the glyphs defined in the eurlatgr font, so that display still + * works reasonably well on the Linux console. For details see: + * + * http://git.altlinux.org/people/legion/packages/kbd.git?p=kbd.git;a=blob;f=data/consolefonts/README.eurlatgr + */ + + static const char* const draw_table[2][_SPECIAL_GLYPH_MAX] = { + /* ASCII fallback */ + [false] = { + [SPECIAL_GLYPH_TREE_VERTICAL] = "| ", + [SPECIAL_GLYPH_TREE_BRANCH] = "|-", + [SPECIAL_GLYPH_TREE_RIGHT] = "`-", + [SPECIAL_GLYPH_TREE_SPACE] = " ", + [SPECIAL_GLYPH_TRIANGULAR_BULLET] = ">", + [SPECIAL_GLYPH_BLACK_CIRCLE] = "*", + [SPECIAL_GLYPH_BULLET] = "*", + [SPECIAL_GLYPH_ARROW] = "->", + [SPECIAL_GLYPH_MDASH] = "-", + [SPECIAL_GLYPH_ELLIPSIS] = "...", + [SPECIAL_GLYPH_MU] = "u", + [SPECIAL_GLYPH_CHECK_MARK] = "+", + [SPECIAL_GLYPH_CROSS_MARK] = "-", + [SPECIAL_GLYPH_ECSTATIC_SMILEY] = ":-]", + [SPECIAL_GLYPH_HAPPY_SMILEY] = ":-}", + [SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY] = ":-)", + [SPECIAL_GLYPH_NEUTRAL_SMILEY] = ":-|", + [SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY] = ":-(", + [SPECIAL_GLYPH_UNHAPPY_SMILEY] = ":-{", + [SPECIAL_GLYPH_DEPRESSED_SMILEY] = ":-[", + }, + + /* UTF-8 */ + [true] = { + [SPECIAL_GLYPH_TREE_VERTICAL] = "\342\224\202 ", /* │ */ + [SPECIAL_GLYPH_TREE_BRANCH] = "\342\224\234\342\224\200", /* ├─ */ + [SPECIAL_GLYPH_TREE_RIGHT] = "\342\224\224\342\224\200", /* └─ */ + [SPECIAL_GLYPH_TREE_SPACE] = " ", /* */ + [SPECIAL_GLYPH_TRIANGULAR_BULLET] = "\342\200\243", /* ‣ */ + [SPECIAL_GLYPH_BLACK_CIRCLE] = "\342\227\217", /* ● */ + [SPECIAL_GLYPH_BULLET] = "\342\200\242", /* • */ + [SPECIAL_GLYPH_ARROW] = "\342\206\222", /* → */ + [SPECIAL_GLYPH_MDASH] = "\342\200\223", /* – */ + [SPECIAL_GLYPH_ELLIPSIS] = "\342\200\246", /* … */ + [SPECIAL_GLYPH_MU] = "\316\274", /* μ */ + [SPECIAL_GLYPH_CHECK_MARK] = "\342\234\223", /* ✓ */ + [SPECIAL_GLYPH_CROSS_MARK] = "\342\234\227", /* ✗ */ + [SPECIAL_GLYPH_ECSTATIC_SMILEY] = "\360\237\230\207", /* 😇 */ + [SPECIAL_GLYPH_HAPPY_SMILEY] = "\360\237\230\200", /* 😀 */ + [SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY] = "\360\237\231\202", /* 🙂 */ + [SPECIAL_GLYPH_NEUTRAL_SMILEY] = "\360\237\230\220", /* 😐 */ + [SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY] = "\360\237\231\201", /* 🙁 */ + [SPECIAL_GLYPH_UNHAPPY_SMILEY] = "\360\237\230\250", /* 😨️️ */ + [SPECIAL_GLYPH_DEPRESSED_SMILEY] = "\360\237\244\242", /* 🤢 */ + }, + }; + + assert(code < _SPECIAL_GLYPH_MAX); + + return draw_table[code >= _SPECIAL_GLYPH_FIRST_SMILEY ? emoji_enabled() : is_locale_utf8()][code]; +} + +void locale_variables_free(char *l[_VARIABLE_LC_MAX]) { + LocaleVariable i; + + if (!l) + return; + + for (i = 0; i < _VARIABLE_LC_MAX; i++) + l[i] = mfree(l[i]); +} + +static const char * const locale_variable_table[_VARIABLE_LC_MAX] = { + [VARIABLE_LANG] = "LANG", + [VARIABLE_LANGUAGE] = "LANGUAGE", + [VARIABLE_LC_CTYPE] = "LC_CTYPE", + [VARIABLE_LC_NUMERIC] = "LC_NUMERIC", + [VARIABLE_LC_TIME] = "LC_TIME", + [VARIABLE_LC_COLLATE] = "LC_COLLATE", + [VARIABLE_LC_MONETARY] = "LC_MONETARY", + [VARIABLE_LC_MESSAGES] = "LC_MESSAGES", + [VARIABLE_LC_PAPER] = "LC_PAPER", + [VARIABLE_LC_NAME] = "LC_NAME", + [VARIABLE_LC_ADDRESS] = "LC_ADDRESS", + [VARIABLE_LC_TELEPHONE] = "LC_TELEPHONE", + [VARIABLE_LC_MEASUREMENT] = "LC_MEASUREMENT", + [VARIABLE_LC_IDENTIFICATION] = "LC_IDENTIFICATION" +}; + +DEFINE_STRING_TABLE_LOOKUP(locale_variable, LocaleVariable); diff --git a/src/basic/locale-util.h b/src/basic/locale-util.h new file mode 100644 index 00000000..78abbafd --- /dev/null +++ b/src/basic/locale-util.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "macro.h" + +typedef enum LocaleVariable { + /* We don't list LC_ALL here on purpose. People should be + * using LANG instead. */ + + VARIABLE_LANG, + VARIABLE_LANGUAGE, + VARIABLE_LC_CTYPE, + VARIABLE_LC_NUMERIC, + VARIABLE_LC_TIME, + VARIABLE_LC_COLLATE, + VARIABLE_LC_MONETARY, + VARIABLE_LC_MESSAGES, + VARIABLE_LC_PAPER, + VARIABLE_LC_NAME, + VARIABLE_LC_ADDRESS, + VARIABLE_LC_TELEPHONE, + VARIABLE_LC_MEASUREMENT, + VARIABLE_LC_IDENTIFICATION, + _VARIABLE_LC_MAX, + _VARIABLE_LC_INVALID = -1 +} LocaleVariable; + +int get_locales(char ***l); +bool locale_is_valid(const char *name); + +#define _(String) gettext(String) +#define N_(String) String +void init_gettext(void); + +bool is_locale_utf8(void); + +typedef enum { + SPECIAL_GLYPH_TREE_VERTICAL, + SPECIAL_GLYPH_TREE_BRANCH, + SPECIAL_GLYPH_TREE_RIGHT, + SPECIAL_GLYPH_TREE_SPACE, + SPECIAL_GLYPH_TRIANGULAR_BULLET, + SPECIAL_GLYPH_BLACK_CIRCLE, + SPECIAL_GLYPH_BULLET, + SPECIAL_GLYPH_ARROW, + SPECIAL_GLYPH_MDASH, + SPECIAL_GLYPH_ELLIPSIS, + SPECIAL_GLYPH_MU, + SPECIAL_GLYPH_CHECK_MARK, + SPECIAL_GLYPH_CROSS_MARK, + _SPECIAL_GLYPH_FIRST_SMILEY, + SPECIAL_GLYPH_ECSTATIC_SMILEY = _SPECIAL_GLYPH_FIRST_SMILEY, + SPECIAL_GLYPH_HAPPY_SMILEY, + SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY, + SPECIAL_GLYPH_NEUTRAL_SMILEY, + SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY, + SPECIAL_GLYPH_UNHAPPY_SMILEY, + SPECIAL_GLYPH_DEPRESSED_SMILEY, + _SPECIAL_GLYPH_MAX +} SpecialGlyph; + +const char *special_glyph(SpecialGlyph code) _const_; + +const char* locale_variable_to_string(LocaleVariable i) _const_; +LocaleVariable locale_variable_from_string(const char *s) _pure_; + +static inline void freelocalep(locale_t *p) { + if (*p == (locale_t) 0) + return; + + freelocale(*p); +} + +void locale_variables_free(char* l[_VARIABLE_LC_MAX]); +static inline void locale_variables_freep(char*(*l)[_VARIABLE_LC_MAX]) { + locale_variables_free(*l); +} diff --git a/src/basic/log.c b/src/basic/log.c new file mode 100644 index 00000000..17557e18 --- /dev/null +++ b/src/basic/log.c @@ -0,0 +1,1368 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "io-util.h" +#include "log.h" +#include "macro.h" +#include "parse-util.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "ratelimit.h" +#include "signal-util.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "syslog-util.h" +#include "terminal-util.h" +#include "time-util.h" +#include "utf8.h" + +#define SNDBUF_SIZE (8*1024*1024) + +static LogTarget log_target = LOG_TARGET_CONSOLE; +static int log_max_level[] = {LOG_INFO, LOG_INFO}; +assert_cc(ELEMENTSOF(log_max_level) == _LOG_REALM_MAX); +static int log_facility = LOG_DAEMON; + +static int console_fd = STDERR_FILENO; +static int syslog_fd = -1; +static int kmsg_fd = -1; +static int journal_fd = -1; + +static bool syslog_is_stream = false; + +static bool show_color = false; +static bool show_location = false; + +static bool upgrade_syslog_to_journal = false; +static bool always_reopen_console = false; +static bool open_when_needed = false; +static bool prohibit_ipc = false; + +/* Akin to glibc's __abort_msg; which is private and we hence cannot + * use here. */ +static char *log_abort_msg = NULL; + +/* An assert to use in logging functions that does not call recursively + * into our logging functions (since that might lead to a loop). */ +#define assert_raw(expr) \ + do { \ + if (_unlikely_(!(expr))) { \ + fputs(#expr "\n", stderr); \ + abort(); \ + } \ + } while (false) + +static void log_close_console(void) { + console_fd = safe_close_above_stdio(console_fd); +} + +static int log_open_console(void) { + + if (!always_reopen_console) { + console_fd = STDERR_FILENO; + return 0; + } + + if (console_fd < 3) { + int fd; + + fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return fd; + + console_fd = fd_move_above_stdio(fd); + } + + return 0; +} + +static void log_close_kmsg(void) { + kmsg_fd = safe_close(kmsg_fd); +} + +static int log_open_kmsg(void) { + + if (kmsg_fd >= 0) + return 0; + + kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC); + if (kmsg_fd < 0) + return -errno; + + kmsg_fd = fd_move_above_stdio(kmsg_fd); + return 0; +} + +static void log_close_syslog(void) { + syslog_fd = safe_close(syslog_fd); +} + +static int create_log_socket(int type) { + struct timeval tv; + int fd; + + fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0); + if (fd < 0) + return -errno; + + fd = fd_move_above_stdio(fd); + (void) fd_inc_sndbuf(fd, SNDBUF_SIZE); + + /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever + * in the unlikely case of a deadlock. */ + if (getpid_cached() == 1) + timeval_store(&tv, 10 * USEC_PER_MSEC); + else + timeval_store(&tv, 10 * USEC_PER_SEC); + (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + + return fd; +} + +static int log_open_syslog(void) { + + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/dev/log", + }; + + int r; + + if (syslog_fd >= 0) + return 0; + + syslog_fd = create_log_socket(SOCK_DGRAM); + if (syslog_fd < 0) { + r = syslog_fd; + goto fail; + } + + if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) { + safe_close(syslog_fd); + + /* Some legacy syslog systems still use stream + * sockets. They really shouldn't. But what can we + * do... */ + syslog_fd = create_log_socket(SOCK_STREAM); + if (syslog_fd < 0) { + r = syslog_fd; + goto fail; + } + + if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) { + r = -errno; + goto fail; + } + + syslog_is_stream = true; + } else + syslog_is_stream = false; + + return 0; + +fail: + log_close_syslog(); + return r; +} + +static void log_close_journal(void) { + journal_fd = safe_close(journal_fd); +} + +static int log_open_journal(void) { + + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/socket", + }; + + int r; + + if (journal_fd >= 0) + return 0; + + journal_fd = create_log_socket(SOCK_DGRAM); + if (journal_fd < 0) { + r = journal_fd; + goto fail; + } + + if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + log_close_journal(); + return r; +} + +int log_open(void) { + int r; + + /* Do not call from library code. */ + + /* If we don't use the console we close it here, to not get + * killed by SAK. If we don't use syslog we close it here so + * that we are not confused by somebody deleting the socket in + * the fs, and to make sure we don't use it if prohibit_ipc is + * set. If we don't use /dev/kmsg we still keep it open, + * because there is no reason to close it. */ + + if (log_target == LOG_TARGET_NULL) { + log_close_journal(); + log_close_syslog(); + log_close_console(); + return 0; + } + + if (log_target != LOG_TARGET_AUTO || + getpid_cached() == 1 || + isatty(STDERR_FILENO) <= 0) { + + if (!prohibit_ipc && + IN_SET(log_target, LOG_TARGET_AUTO, + LOG_TARGET_JOURNAL_OR_KMSG, + LOG_TARGET_JOURNAL)) { + r = log_open_journal(); + if (r >= 0) { + log_close_syslog(); + log_close_console(); + return r; + } + } + + if (!prohibit_ipc && + IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG, + LOG_TARGET_SYSLOG)) { + r = log_open_syslog(); + if (r >= 0) { + log_close_journal(); + log_close_console(); + return r; + } + } + + if (IN_SET(log_target, LOG_TARGET_AUTO, + LOG_TARGET_JOURNAL_OR_KMSG, + LOG_TARGET_SYSLOG_OR_KMSG, + LOG_TARGET_KMSG)) { + r = log_open_kmsg(); + if (r >= 0) { + log_close_journal(); + log_close_syslog(); + log_close_console(); + return r; + } + } + } + + log_close_journal(); + log_close_syslog(); + + return log_open_console(); +} + +void log_set_target(LogTarget target) { + assert(target >= 0); + assert(target < _LOG_TARGET_MAX); + + if (upgrade_syslog_to_journal) { + if (target == LOG_TARGET_SYSLOG) + target = LOG_TARGET_JOURNAL; + else if (target == LOG_TARGET_SYSLOG_OR_KMSG) + target = LOG_TARGET_JOURNAL_OR_KMSG; + } + + log_target = target; +} + +void log_close(void) { + /* Do not call from library code. */ + + log_close_journal(); + log_close_syslog(); + log_close_kmsg(); + log_close_console(); +} + +void log_forget_fds(void) { + /* Do not call from library code. */ + + console_fd = kmsg_fd = syslog_fd = journal_fd = -1; +} + +void log_set_max_level_realm(LogRealm realm, int level) { + assert((level & LOG_PRIMASK) == level); + assert(realm < ELEMENTSOF(log_max_level)); + + log_max_level[realm] = level; +} + +void log_set_facility(int facility) { + log_facility = facility; +} + +static int write_to_console( + int level, + int error, + const char *file, + int line, + const char *func, + const char *buffer) { + + char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2]; + struct iovec iovec[6] = {}; + const char *on = NULL, *off = NULL; + size_t n = 0; + + if (console_fd < 0) + return 0; + + if (log_target == LOG_TARGET_CONSOLE_PREFIXED) { + xsprintf(prefix, "<%i>", level); + iovec[n++] = IOVEC_MAKE_STRING(prefix); + } + + if (show_color) + get_log_colors(LOG_PRI(level), &on, &off, NULL); + + if (show_location) { + const char *lon = "", *loff = ""; + if (show_color) { + lon = ANSI_HIGHLIGHT_YELLOW4; + loff = ANSI_NORMAL; + } + + (void) snprintf(location, sizeof location, "%s%s:%i%s: ", lon, file, line, loff); + iovec[n++] = IOVEC_MAKE_STRING(location); + } + + if (on) + iovec[n++] = IOVEC_MAKE_STRING(on); + iovec[n++] = IOVEC_MAKE_STRING(buffer); + if (off) + iovec[n++] = IOVEC_MAKE_STRING(off); + iovec[n++] = IOVEC_MAKE_STRING("\n"); + + if (writev(console_fd, iovec, n) < 0) { + + if (errno == EIO && getpid_cached() == 1) { + + /* If somebody tried to kick us from our console tty (via vhangup() or suchlike), try + * to reconnect. */ + + log_close_console(); + (void) log_open_console(); + if (console_fd < 0) + return 0; + + if (writev(console_fd, iovec, n) < 0) + return -errno; + } else + return -errno; + } + + return 1; +} + +static int write_to_syslog( + int level, + int error, + const char *file, + int line, + const char *func, + const char *buffer) { + + char header_priority[2 + DECIMAL_STR_MAX(int) + 1], + header_time[64], + header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1]; + struct iovec iovec[5] = {}; + struct msghdr msghdr = { + .msg_iov = iovec, + .msg_iovlen = ELEMENTSOF(iovec), + }; + time_t t; + struct tm tm; + + if (syslog_fd < 0) + return 0; + + xsprintf(header_priority, "<%i>", level); + + t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC); + if (!localtime_r(&t, &tm)) + return -EINVAL; + + if (strftime(header_time, sizeof(header_time), "%h %e %T ", &tm) <= 0) + return -EINVAL; + + xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached()); + + iovec[0] = IOVEC_MAKE_STRING(header_priority); + iovec[1] = IOVEC_MAKE_STRING(header_time); + iovec[2] = IOVEC_MAKE_STRING(program_invocation_short_name); + iovec[3] = IOVEC_MAKE_STRING(header_pid); + iovec[4] = IOVEC_MAKE_STRING(buffer); + + /* When using syslog via SOCK_STREAM separate the messages by NUL chars */ + if (syslog_is_stream) + iovec[4].iov_len++; + + for (;;) { + ssize_t n; + + n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL); + if (n < 0) + return -errno; + + if (!syslog_is_stream || + (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec))) + break; + + IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n); + } + + return 1; +} + +static int write_to_kmsg( + int level, + int error, + const char *file, + int line, + const char *func, + const char *buffer) { + + /* Set a ratelimit on the amount of messages logged to /dev/kmsg. This is mostly supposed to be a + * safety catch for the case where start indiscriminately logging in a loop. It will not catch cases + * where we log excessively, but not in a tight loop. + * + * Note that this ratelimit is per-emitter, so we might still overwhelm /dev/kmsg with multiple + * loggers. + */ + static thread_local RateLimit ratelimit = { 5 * USEC_PER_SEC, 200 }; + + char header_priority[2 + DECIMAL_STR_MAX(int) + 1], + header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1]; + struct iovec iovec[5] = {}; + + if (kmsg_fd < 0) + return 0; + + if (!ratelimit_below(&ratelimit)) + return 0; + + xsprintf(header_priority, "<%i>", level); + xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached()); + + iovec[0] = IOVEC_MAKE_STRING(header_priority); + iovec[1] = IOVEC_MAKE_STRING(program_invocation_short_name); + iovec[2] = IOVEC_MAKE_STRING(header_pid); + iovec[3] = IOVEC_MAKE_STRING(buffer); + iovec[4] = IOVEC_MAKE_STRING("\n"); + + if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0) + return -errno; + + return 1; +} + +static int log_do_header( + char *header, + size_t size, + int level, + int error, + const char *file, int line, const char *func, + const char *object_field, const char *object, + const char *extra_field, const char *extra) { + int r; + + error = IS_SYNTHETIC_ERRNO(error) ? 0 : ERRNO_VALUE(error); + + r = snprintf(header, size, + "PRIORITY=%i\n" + "SYSLOG_FACILITY=%i\n" + "%s%.256s%s" /* CODE_FILE */ + "%s%.*i%s" /* CODE_LINE */ + "%s%.256s%s" /* CODE_FUNC */ + "%s%.*i%s" /* ERRNO */ + "%s%.256s%s" /* object */ + "%s%.256s%s" /* extra */ + "SYSLOG_IDENTIFIER=%.256s\n", + LOG_PRI(level), + LOG_FAC(level), + isempty(file) ? "" : "CODE_FILE=", + isempty(file) ? "" : file, + isempty(file) ? "" : "\n", + line ? "CODE_LINE=" : "", + line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */ + line ? "\n" : "", + isempty(func) ? "" : "CODE_FUNC=", + isempty(func) ? "" : func, + isempty(func) ? "" : "\n", + error ? "ERRNO=" : "", + error ? 1 : 0, error, + error ? "\n" : "", + isempty(object) ? "" : object_field, + isempty(object) ? "" : object, + isempty(object) ? "" : "\n", + isempty(extra) ? "" : extra_field, + isempty(extra) ? "" : extra, + isempty(extra) ? "" : "\n", + program_invocation_short_name); + assert_raw((size_t) r < size); + + return 0; +} + +static int write_to_journal( + int level, + int error, + const char *file, + int line, + const char *func, + const char *object_field, + const char *object, + const char *extra_field, + const char *extra, + const char *buffer) { + + char header[LINE_MAX]; + struct iovec iovec[4] = {}; + struct msghdr mh = {}; + + if (journal_fd < 0) + return 0; + + log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra); + + iovec[0] = IOVEC_MAKE_STRING(header); + iovec[1] = IOVEC_MAKE_STRING("MESSAGE="); + iovec[2] = IOVEC_MAKE_STRING(buffer); + iovec[3] = IOVEC_MAKE_STRING("\n"); + + mh.msg_iov = iovec; + mh.msg_iovlen = ELEMENTSOF(iovec); + + if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0) + return -errno; + + return 1; +} + +int log_dispatch_internal( + int level, + int error, + const char *file, + int line, + const char *func, + const char *object_field, + const char *object, + const char *extra_field, + const char *extra, + char *buffer) { + + assert_raw(buffer); + + if (log_target == LOG_TARGET_NULL) + return -ERRNO_VALUE(error); + + /* Patch in LOG_DAEMON facility if necessary */ + if ((level & LOG_FACMASK) == 0) + level |= log_facility; + + if (open_when_needed) + (void) log_open(); + + do { + char *e; + int k = 0; + + buffer += strspn(buffer, NEWLINE); + + if (buffer[0] == 0) + break; + + if ((e = strpbrk(buffer, NEWLINE))) + *(e++) = 0; + + if (IN_SET(log_target, LOG_TARGET_AUTO, + LOG_TARGET_JOURNAL_OR_KMSG, + LOG_TARGET_JOURNAL)) { + + k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer); + if (k < 0 && k != -EAGAIN) + log_close_journal(); + } + + if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG, + LOG_TARGET_SYSLOG)) { + + k = write_to_syslog(level, error, file, line, func, buffer); + if (k < 0 && k != -EAGAIN) + log_close_syslog(); + } + + if (k <= 0 && + IN_SET(log_target, LOG_TARGET_AUTO, + LOG_TARGET_SYSLOG_OR_KMSG, + LOG_TARGET_JOURNAL_OR_KMSG, + LOG_TARGET_KMSG)) { + + if (k < 0) + log_open_kmsg(); + + k = write_to_kmsg(level, error, file, line, func, buffer); + if (k < 0) { + log_close_kmsg(); + (void) log_open_console(); + } + } + + if (k <= 0) + (void) write_to_console(level, error, file, line, func, buffer); + + buffer = e; + } while (buffer); + + if (open_when_needed) + log_close(); + + return -ERRNO_VALUE(error); +} + +int log_dump_internal( + int level, + int error, + const char *file, + int line, + const char *func, + char *buffer) { + + LogRealm realm = LOG_REALM_REMOVE_LEVEL(level); + PROTECT_ERRNO; + + /* This modifies the buffer... */ + + if (_likely_(LOG_PRI(level) > log_max_level[realm])) + return -ERRNO_VALUE(error); + + return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer); +} + +int log_internalv_realm( + int level, + int error, + const char *file, + int line, + const char *func, + const char *format, + va_list ap) { + + LogRealm realm = LOG_REALM_REMOVE_LEVEL(level); + char buffer[LINE_MAX]; + PROTECT_ERRNO; + + if (_likely_(LOG_PRI(level) > log_max_level[realm])) + return -ERRNO_VALUE(error); + + /* Make sure that %m maps to the specified error (or "Success"). */ + errno = ERRNO_VALUE(error); + + (void) vsnprintf(buffer, sizeof buffer, format, ap); + + return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer); +} + +int log_internal_realm( + int level, + int error, + const char *file, + int line, + const char *func, + const char *format, ...) { + + va_list ap; + int r; + + va_start(ap, format); + r = log_internalv_realm(level, error, file, line, func, format, ap); + va_end(ap); + + return r; +} + +int log_object_internalv( + int level, + int error, + const char *file, + int line, + const char *func, + const char *object_field, + const char *object, + const char *extra_field, + const char *extra, + const char *format, + va_list ap) { + + PROTECT_ERRNO; + char *buffer, *b; + + if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD])) + return -ERRNO_VALUE(error); + + /* Make sure that %m maps to the specified error (or "Success"). */ + errno = ERRNO_VALUE(error); + + /* Prepend the object name before the message */ + if (object) { + size_t n; + + n = strlen(object); + buffer = newa(char, n + 2 + LINE_MAX); + b = stpcpy(stpcpy(buffer, object), ": "); + } else + b = buffer = newa(char, LINE_MAX); + + (void) vsnprintf(b, LINE_MAX, format, ap); + + return log_dispatch_internal(level, error, file, line, func, + object_field, object, extra_field, extra, buffer); +} + +int log_object_internal( + int level, + int error, + const char *file, + int line, + const char *func, + const char *object_field, + const char *object, + const char *extra_field, + const char *extra, + const char *format, ...) { + + va_list ap; + int r; + + va_start(ap, format); + r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap); + va_end(ap); + + return r; +} + +static void log_assert( + int level, + const char *text, + const char *file, + int line, + const char *func, + const char *format) { + + static char buffer[LINE_MAX]; + LogRealm realm = LOG_REALM_REMOVE_LEVEL(level); + + if (_likely_(LOG_PRI(level) > log_max_level[realm])) + return; + + DISABLE_WARNING_FORMAT_NONLITERAL; + (void) snprintf(buffer, sizeof buffer, format, text, file, line, func); + REENABLE_WARNING; + + log_abort_msg = buffer; + + log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer); +} + +_noreturn_ void log_assert_failed_realm( + LogRealm realm, + const char *text, + const char *file, + int line, + const char *func) { + (void) log_open(); + log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func, + "Assertion '%s' failed at %s:%u, function %s(). Aborting."); + abort(); +} + +_noreturn_ void log_assert_failed_unreachable_realm( + LogRealm realm, + const char *text, + const char *file, + int line, + const char *func) { + (void) log_open(); + log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func, + "Code should not be reached '%s' at %s:%u, function %s(). Aborting."); + abort(); +} + +void log_assert_failed_return_realm( + LogRealm realm, + const char *text, + const char *file, + int line, + const char *func) { + PROTECT_ERRNO; + log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func, + "Assertion '%s' failed at %s:%u, function %s(). Ignoring."); +} + +int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) { + return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR), + ENOMEM, file, line, func, "Out of memory."); +} + +int log_format_iovec( + struct iovec *iovec, + size_t iovec_len, + size_t *n, + bool newline_separator, + int error, + const char *format, + va_list ap) { + + static const char nl = '\n'; + + while (format && *n + 1 < iovec_len) { + va_list aq; + char *m; + int r; + + /* We need to copy the va_list structure, + * since vasprintf() leaves it afterwards at + * an undefined location */ + + errno = ERRNO_VALUE(error); + + va_copy(aq, ap); + r = vasprintf(&m, format, aq); + va_end(aq); + if (r < 0) + return -EINVAL; + + /* Now, jump enough ahead, so that we point to + * the next format string */ + VA_FORMAT_ADVANCE(format, ap); + + iovec[(*n)++] = IOVEC_MAKE_STRING(m); + + if (newline_separator) { + iovec[*n] = IOVEC_MAKE((char *)&nl, 1); + (*n)++; + } + + format = va_arg(ap, char *); + } + return 0; +} + +int log_struct_internal( + int level, + int error, + const char *file, + int line, + const char *func, + const char *format, ...) { + + LogRealm realm = LOG_REALM_REMOVE_LEVEL(level); + char buf[LINE_MAX]; + bool found = false; + PROTECT_ERRNO; + va_list ap; + + if (_likely_(LOG_PRI(level) > log_max_level[realm]) || + log_target == LOG_TARGET_NULL) + return -ERRNO_VALUE(error); + + if ((level & LOG_FACMASK) == 0) + level |= log_facility; + + if (IN_SET(log_target, + LOG_TARGET_AUTO, + LOG_TARGET_JOURNAL_OR_KMSG, + LOG_TARGET_JOURNAL)) { + + if (open_when_needed) + log_open_journal(); + + if (journal_fd >= 0) { + char header[LINE_MAX]; + struct iovec iovec[17] = {}; + size_t n = 0, i; + int r; + struct msghdr mh = { + .msg_iov = iovec, + }; + bool fallback = false; + + /* If the journal is available do structured logging. + * Do not report the errno if it is synthetic. */ + log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL); + iovec[n++] = IOVEC_MAKE_STRING(header); + + va_start(ap, format); + r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap); + if (r < 0) + fallback = true; + else { + mh.msg_iovlen = n; + (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL); + } + + va_end(ap); + for (i = 1; i < n; i += 2) + free(iovec[i].iov_base); + + if (!fallback) { + if (open_when_needed) + log_close(); + + return -ERRNO_VALUE(error); + } + } + } + + /* Fallback if journal logging is not available or didn't work. */ + + va_start(ap, format); + while (format) { + va_list aq; + + errno = ERRNO_VALUE(error); + + va_copy(aq, ap); + (void) vsnprintf(buf, sizeof buf, format, aq); + va_end(aq); + + if (startswith(buf, "MESSAGE=")) { + found = true; + break; + } + + VA_FORMAT_ADVANCE(format, ap); + + format = va_arg(ap, char *); + } + va_end(ap); + + if (!found) { + if (open_when_needed) + log_close(); + + return -ERRNO_VALUE(error); + } + + return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8); +} + +int log_struct_iovec_internal( + int level, + int error, + const char *file, + int line, + const char *func, + const struct iovec input_iovec[], + size_t n_input_iovec) { + + LogRealm realm = LOG_REALM_REMOVE_LEVEL(level); + PROTECT_ERRNO; + size_t i; + char *m; + + if (_likely_(LOG_PRI(level) > log_max_level[realm]) || + log_target == LOG_TARGET_NULL) + return -ERRNO_VALUE(error); + + if ((level & LOG_FACMASK) == 0) + level |= log_facility; + + if (IN_SET(log_target, LOG_TARGET_AUTO, + LOG_TARGET_JOURNAL_OR_KMSG, + LOG_TARGET_JOURNAL) && + journal_fd >= 0) { + + struct iovec iovec[1 + n_input_iovec*2]; + char header[LINE_MAX]; + struct msghdr mh = { + .msg_iov = iovec, + .msg_iovlen = 1 + n_input_iovec*2, + }; + + log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL); + iovec[0] = IOVEC_MAKE_STRING(header); + + for (i = 0; i < n_input_iovec; i++) { + iovec[1+i*2] = input_iovec[i]; + iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n"); + } + + if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0) + return -ERRNO_VALUE(error); + } + + for (i = 0; i < n_input_iovec; i++) + if (memory_startswith(input_iovec[i].iov_base, input_iovec[i].iov_len, "MESSAGE=")) + break; + + if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */ + return -ERRNO_VALUE(error); + + m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="), + input_iovec[i].iov_len - STRLEN("MESSAGE=")); + + return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m); +} + +int log_set_target_from_string(const char *e) { + LogTarget t; + + t = log_target_from_string(e); + if (t < 0) + return -EINVAL; + + log_set_target(t); + return 0; +} + +int log_set_max_level_from_string_realm(LogRealm realm, const char *e) { + int t; + + t = log_level_from_string(e); + if (t < 0) + return -EINVAL; + + log_set_max_level_realm(realm, t); + return 0; +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + + /* + * The systemd.log_xyz= settings are parsed by all tools, and + * so is "debug". + * + * However, "quiet" is only parsed by PID 1, and only turns of + * status output to /dev/console, but does not alter the log + * level. + */ + + if (streq(key, "debug") && !value) + log_set_max_level(LOG_DEBUG); + + else if (proc_cmdline_key_streq(key, "systemd.log_target")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (log_set_target_from_string(value) < 0) + log_warning("Failed to parse log target '%s'. Ignoring.", value); + + } else if (proc_cmdline_key_streq(key, "systemd.log_level")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (log_set_max_level_from_string(value) < 0) + log_warning("Failed to parse log level '%s'. Ignoring.", value); + + } else if (proc_cmdline_key_streq(key, "systemd.log_color")) { + + if (log_show_color_from_string(value ?: "1") < 0) + log_warning("Failed to parse log color setting '%s'. Ignoring.", value); + + } else if (proc_cmdline_key_streq(key, "systemd.log_location")) { + + if (log_show_location_from_string(value ?: "1") < 0) + log_warning("Failed to parse log location setting '%s'. Ignoring.", value); + } + + return 0; +} + +void log_parse_environment_realm(LogRealm realm) { + /* Do not call from library code. */ + + const char *e; + + if (getpid_cached() == 1 || get_ctty_devnr(0, NULL) < 0) + /* Only try to read the command line in daemons. We assume that anything that has a + * controlling tty is user stuff. For PID1 we do a special check in case it hasn't + * closed the console yet. */ + (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); + + e = getenv("SYSTEMD_LOG_TARGET"); + if (e && log_set_target_from_string(e) < 0) + log_warning("Failed to parse log target '%s'. Ignoring.", e); + + e = getenv("SYSTEMD_LOG_LEVEL"); + if (e && log_set_max_level_from_string_realm(realm, e) < 0) + log_warning("Failed to parse log level '%s'. Ignoring.", e); + + e = getenv("SYSTEMD_LOG_COLOR"); + if (e && log_show_color_from_string(e) < 0) + log_warning("Failed to parse log color '%s'. Ignoring.", e); + + e = getenv("SYSTEMD_LOG_LOCATION"); + if (e && log_show_location_from_string(e) < 0) + log_warning("Failed to parse log location '%s'. Ignoring.", e); +} + +LogTarget log_get_target(void) { + return log_target; +} + +int log_get_max_level_realm(LogRealm realm) { + return log_max_level[realm]; +} + +void log_show_color(bool b) { + show_color = b; +} + +bool log_get_show_color(void) { + return show_color; +} + +void log_show_location(bool b) { + show_location = b; +} + +bool log_get_show_location(void) { + return show_location; +} + +int log_show_color_from_string(const char *e) { + int t; + + t = parse_boolean(e); + if (t < 0) + return t; + + log_show_color(t); + return 0; +} + +int log_show_location_from_string(const char *e) { + int t; + + t = parse_boolean(e); + if (t < 0) + return t; + + log_show_location(t); + return 0; +} + +bool log_on_console(void) { + if (IN_SET(log_target, LOG_TARGET_CONSOLE, + LOG_TARGET_CONSOLE_PREFIXED)) + return true; + + return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0; +} + +static const char *const log_target_table[_LOG_TARGET_MAX] = { + [LOG_TARGET_CONSOLE] = "console", + [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed", + [LOG_TARGET_KMSG] = "kmsg", + [LOG_TARGET_JOURNAL] = "journal", + [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg", + [LOG_TARGET_SYSLOG] = "syslog", + [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg", + [LOG_TARGET_AUTO] = "auto", + [LOG_TARGET_NULL] = "null", +}; + +DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget); + +void log_received_signal(int level, const struct signalfd_siginfo *si) { + assert(si); + + if (pid_is_valid(si->ssi_pid)) { + _cleanup_free_ char *p = NULL; + + (void) get_process_comm(si->ssi_pid, &p); + + log_full(level, + "Received SIG%s from PID %"PRIu32" (%s).", + signal_to_string(si->ssi_signo), + si->ssi_pid, strna(p)); + } else + log_full(level, + "Received SIG%s.", + signal_to_string(si->ssi_signo)); +} + +int log_syntax_internal( + const char *unit, + int level, + const char *config_file, + unsigned config_line, + int error, + const char *file, + int line, + const char *func, + const char *format, ...) { + + PROTECT_ERRNO; + char buffer[LINE_MAX]; + va_list ap; + const char *unit_fmt = NULL; + + if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]) || + log_target == LOG_TARGET_NULL) + return -ERRNO_VALUE(error); + + errno = ERRNO_VALUE(error); + + va_start(ap, format); + (void) vsnprintf(buffer, sizeof buffer, format, ap); + va_end(ap); + + if (unit) + unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s"; + + if (config_file) { + if (config_line > 0) + return log_struct_internal( + LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level), + error, + file, line, func, + "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR, + "CONFIG_FILE=%s", config_file, + "CONFIG_LINE=%u", config_line, + LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer), + unit_fmt, unit, + NULL); + else + return log_struct_internal( + LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level), + error, + file, line, func, + "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR, + "CONFIG_FILE=%s", config_file, + LOG_MESSAGE("%s: %s", config_file, buffer), + unit_fmt, unit, + NULL); + } else if (unit) + return log_struct_internal( + LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level), + error, + file, line, func, + "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR, + LOG_MESSAGE("%s: %s", unit, buffer), + unit_fmt, unit, + NULL); + else + return log_struct_internal( + LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level), + error, + file, line, func, + "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR, + LOG_MESSAGE("%s", buffer), + NULL); +} + +int log_syntax_invalid_utf8_internal( + const char *unit, + int level, + const char *config_file, + unsigned config_line, + const char *file, + int line, + const char *func, + const char *rvalue) { + + _cleanup_free_ char *p = NULL; + + if (rvalue) + p = utf8_escape_invalid(rvalue); + + log_syntax_internal(unit, level, config_file, config_line, 0, file, line, func, + "String is not UTF-8 clean, ignoring assignment: %s", strna(p)); + + return -EINVAL; +} + +void log_set_upgrade_syslog_to_journal(bool b) { + upgrade_syslog_to_journal = b; + + /* Make the change effective immediately */ + if (b) { + if (log_target == LOG_TARGET_SYSLOG) + log_target = LOG_TARGET_JOURNAL; + else if (log_target == LOG_TARGET_SYSLOG_OR_KMSG) + log_target = LOG_TARGET_JOURNAL_OR_KMSG; + } +} + +void log_set_always_reopen_console(bool b) { + always_reopen_console = b; +} + +void log_set_open_when_needed(bool b) { + open_when_needed = b; +} + +void log_set_prohibit_ipc(bool b) { + prohibit_ipc = b; +} + +int log_emergency_level(void) { + /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only + * then the system of the whole system is obviously affected. */ + + return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR; +} + +int log_dup_console(void) { + int copy; + + /* Duplicate the fd we use for fd logging if it's < 3 and use the copy from now on. This call is useful + * whenever we want to continue logging through the original fd, but want to rearrange stderr. */ + + if (console_fd >= 3) + return 0; + + copy = fcntl(console_fd, F_DUPFD_CLOEXEC, 3); + if (copy < 0) + return -errno; + + console_fd = copy; + return 0; +} + +void log_setup_service(void) { + /* Sets up logging the way it is most appropriate for running a program as a service. Note that using this + * doesn't make the binary unsuitable for invocation on the command line, as log output will still go to the + * terminal if invoked interactively. */ + + log_set_target(LOG_TARGET_AUTO); + log_parse_environment(); + (void) log_open(); +} diff --git a/src/basic/log.h b/src/basic/log.h new file mode 100644 index 00000000..625be224 --- /dev/null +++ b/src/basic/log.h @@ -0,0 +1,340 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "macro.h" + +/* Some structures we reference but don't want to pull in headers for */ +struct iovec; +struct signalfd_siginfo; + +typedef enum LogRealm { + LOG_REALM_SYSTEMD, + LOG_REALM_UDEV, + _LOG_REALM_MAX, +} LogRealm; + +#ifndef LOG_REALM +# define LOG_REALM LOG_REALM_SYSTEMD +#endif + +typedef enum LogTarget{ + LOG_TARGET_CONSOLE, + LOG_TARGET_CONSOLE_PREFIXED, + LOG_TARGET_KMSG, + LOG_TARGET_JOURNAL, + LOG_TARGET_JOURNAL_OR_KMSG, + LOG_TARGET_SYSLOG, + LOG_TARGET_SYSLOG_OR_KMSG, + LOG_TARGET_AUTO, /* console if stderr is tty, JOURNAL_OR_KMSG otherwise */ + LOG_TARGET_NULL, + _LOG_TARGET_MAX, + _LOG_TARGET_INVALID = -1 +} LogTarget; + +/* Note to readers: << and >> have lower precedence than & and | */ +#define LOG_REALM_PLUS_LEVEL(realm, level) ((realm) << 10 | (level)) +#define LOG_REALM_REMOVE_LEVEL(realm_level) ((realm_level) >> 10) +#define SYNTHETIC_ERRNO(num) (1 << 30 | (num)) +#define IS_SYNTHETIC_ERRNO(val) ((val) >> 30 & 1) +#define ERRNO_VALUE(val) (abs(val) & 255) + +void log_set_target(LogTarget target); +void log_set_max_level_realm(LogRealm realm, int level); +#define log_set_max_level(level) \ + log_set_max_level_realm(LOG_REALM, (level)) + +void log_set_facility(int facility); + +int log_set_target_from_string(const char *e); +int log_set_max_level_from_string_realm(LogRealm realm, const char *e); +#define log_set_max_level_from_string(e) \ + log_set_max_level_from_string_realm(LOG_REALM, (e)) + +void log_show_color(bool b); +bool log_get_show_color(void) _pure_; +void log_show_location(bool b); +bool log_get_show_location(void) _pure_; + +int log_show_color_from_string(const char *e); +int log_show_location_from_string(const char *e); + +LogTarget log_get_target(void) _pure_; +int log_get_max_level_realm(LogRealm realm) _pure_; +#define log_get_max_level() \ + log_get_max_level_realm(LOG_REALM) + +/* Functions below that open and close logs or configure logging based on the + * environment should not be called from library code — this is always a job + * for the application itself. + */ + +assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1); +#define PROJECT_FILE (__FILE__ + STRLEN(RELATIVE_SOURCE_PATH) + 1) + +int log_open(void); +void log_close(void); +void log_forget_fds(void); + +void log_parse_environment_realm(LogRealm realm); +#define log_parse_environment() \ + log_parse_environment_realm(LOG_REALM) + +int log_dispatch_internal( + int level, + int error, + const char *file, + int line, + const char *func, + const char *object_field, + const char *object, + const char *extra, + const char *extra_field, + char *buffer); + +int log_internal_realm( + int level, + int error, + const char *file, + int line, + const char *func, + const char *format, ...) _printf_(6,7); +#define log_internal(level, ...) \ + log_internal_realm(LOG_REALM_PLUS_LEVEL(LOG_REALM, (level)), __VA_ARGS__) + +int log_internalv_realm( + int level, + int error, + const char *file, + int line, + const char *func, + const char *format, + va_list ap) _printf_(6,0); +#define log_internalv(level, ...) \ + log_internalv_realm(LOG_REALM_PLUS_LEVEL(LOG_REALM, (level)), __VA_ARGS__) + +/* Realm is fixed to LOG_REALM_SYSTEMD for those */ +int log_object_internalv( + int level, + int error, + const char *file, + int line, + const char *func, + const char *object_field, + const char *object, + const char *extra_field, + const char *extra, + const char *format, + va_list ap) _printf_(10,0); + +int log_object_internal( + int level, + int error, + const char *file, + int line, + const char *func, + const char *object_field, + const char *object, + const char *extra_field, + const char *extra, + const char *format, ...) _printf_(10,11); + +int log_struct_internal( + int level, + int error, + const char *file, + int line, + const char *func, + const char *format, ...) _printf_(6,0) _sentinel_; + +int log_oom_internal( + LogRealm realm, + const char *file, + int line, + const char *func); + +int log_format_iovec( + struct iovec *iovec, + size_t iovec_len, + size_t *n, + bool newline_separator, + int error, + const char *format, + va_list ap) _printf_(6, 0); + +int log_struct_iovec_internal( + int level, + int error, + const char *file, + int line, + const char *func, + const struct iovec *input_iovec, + size_t n_input_iovec); + +/* This modifies the buffer passed! */ +int log_dump_internal( + int level, + int error, + const char *file, + int line, + const char *func, + char *buffer); + +/* Logging for various assertions */ +_noreturn_ void log_assert_failed_realm( + LogRealm realm, + const char *text, + const char *file, + int line, + const char *func); +#define log_assert_failed(text, ...) \ + log_assert_failed_realm(LOG_REALM, (text), __VA_ARGS__) + +_noreturn_ void log_assert_failed_unreachable_realm( + LogRealm realm, + const char *text, + const char *file, + int line, + const char *func); +#define log_assert_failed_unreachable(text, ...) \ + log_assert_failed_unreachable_realm(LOG_REALM, (text), __VA_ARGS__) + +void log_assert_failed_return_realm( + LogRealm realm, + const char *text, + const char *file, + int line, + const char *func); +#define log_assert_failed_return(text, ...) \ + log_assert_failed_return_realm(LOG_REALM, (text), __VA_ARGS__) + +#define log_dispatch(level, error, buffer) \ + log_dispatch_internal(level, error, PROJECT_FILE, __LINE__, __func__, NULL, NULL, NULL, NULL, buffer) + +/* Logging with level */ +#define log_full_errno_realm(realm, level, error, ...) \ + ({ \ + int _level = (level), _e = (error), _realm = (realm); \ + (log_get_max_level_realm(_realm) >= LOG_PRI(_level)) \ + ? log_internal_realm(LOG_REALM_PLUS_LEVEL(_realm, _level), _e, \ + PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ + : -ERRNO_VALUE(_e); \ + }) + +#define log_full_errno(level, error, ...) \ + log_full_errno_realm(LOG_REALM, (level), (error), __VA_ARGS__) + +#define log_full(level, ...) log_full_errno((level), 0, __VA_ARGS__) + +int log_emergency_level(void); + +/* Normal logging */ +#define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__) +#define log_info(...) log_full(LOG_INFO, __VA_ARGS__) +#define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__) +#define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__) +#define log_error(...) log_full(LOG_ERR, __VA_ARGS__) +#define log_emergency(...) log_full(log_emergency_level(), __VA_ARGS__) + +/* Logging triggered by an errno-like error */ +#define log_debug_errno(error, ...) log_full_errno(LOG_DEBUG, error, __VA_ARGS__) +#define log_info_errno(error, ...) log_full_errno(LOG_INFO, error, __VA_ARGS__) +#define log_notice_errno(error, ...) log_full_errno(LOG_NOTICE, error, __VA_ARGS__) +#define log_warning_errno(error, ...) log_full_errno(LOG_WARNING, error, __VA_ARGS__) +#define log_error_errno(error, ...) log_full_errno(LOG_ERR, error, __VA_ARGS__) +#define log_emergency_errno(error, ...) log_full_errno(log_emergency_level(), error, __VA_ARGS__) + +#ifdef LOG_TRACE +# define log_trace(...) log_debug(__VA_ARGS__) +#else +# define log_trace(...) do {} while (0) +#endif + +/* Structured logging */ +#define log_struct_errno(level, error, ...) \ + log_struct_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \ + error, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__, NULL) +#define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__) + +#define log_struct_iovec_errno(level, error, iovec, n_iovec) \ + log_struct_iovec_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \ + error, PROJECT_FILE, __LINE__, __func__, iovec, n_iovec) +#define log_struct_iovec(level, iovec, n_iovec) log_struct_iovec_errno(level, 0, iovec, n_iovec) + +/* This modifies the buffer passed! */ +#define log_dump(level, buffer) \ + log_dump_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \ + 0, PROJECT_FILE, __LINE__, __func__, buffer) + +#define log_oom() log_oom_internal(LOG_REALM, PROJECT_FILE, __LINE__, __func__) + +bool log_on_console(void) _pure_; + +const char *log_target_to_string(LogTarget target) _const_; +LogTarget log_target_from_string(const char *s) _pure_; + +/* Helper to prepare various field for structured logging */ +#define LOG_MESSAGE(fmt, ...) "MESSAGE=" fmt, ##__VA_ARGS__ + +void log_received_signal(int level, const struct signalfd_siginfo *si); + +/* If turned on, any requests for a log target involving "syslog" will be implicitly upgraded to the equivalent journal target */ +void log_set_upgrade_syslog_to_journal(bool b); + +/* If turned on, and log_open() is called, we'll not use STDERR_FILENO for logging ever, but rather open /dev/console */ +void log_set_always_reopen_console(bool b); + +/* If turned on, we'll open the log stream implicitly if needed on each individual log call. This is normally not + * desired as we want to reuse our logging streams. It is useful however */ +void log_set_open_when_needed(bool b); + +/* If turned on, then we'll never use IPC-based logging, i.e. never log to syslog or the journal. We'll only log to + * stderr, the console or kmsg */ +void log_set_prohibit_ipc(bool b); + +int log_dup_console(void); + +int log_syntax_internal( + const char *unit, + int level, + const char *config_file, + unsigned config_line, + int error, + const char *file, + int line, + const char *func, + const char *format, ...) _printf_(9, 10); + +int log_syntax_invalid_utf8_internal( + const char *unit, + int level, + const char *config_file, + unsigned config_line, + const char *file, + int line, + const char *func, + const char *rvalue); + +#define log_syntax(unit, level, config_file, config_line, error, ...) \ + ({ \ + int _level = (level), _e = (error); \ + (log_get_max_level() >= LOG_PRI(_level)) \ + ? log_syntax_internal(unit, _level, config_file, config_line, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ + : -ERRNO_VALUE(_e); \ + }) + +#define log_syntax_invalid_utf8(unit, level, config_file, config_line, rvalue) \ + ({ \ + int _level = (level); \ + (log_get_max_level() >= LOG_PRI(_level)) \ + ? log_syntax_invalid_utf8_internal(unit, _level, config_file, config_line, PROJECT_FILE, __LINE__, __func__, rvalue) \ + : -EINVAL; \ + }) + +#define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG) + +void log_setup_service(void); diff --git a/src/basic/login-util.c b/src/basic/login-util.c new file mode 100644 index 00000000..9313926d --- /dev/null +++ b/src/basic/login-util.c @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "login-util.h" +#include "string-util.h" + +bool session_id_valid(const char *id) { + + if (isempty(id)) + return false; + + return id[strspn(id, LETTERS DIGITS)] == '\0'; +} diff --git a/src/basic/login-util.h b/src/basic/login-util.h new file mode 100644 index 00000000..e1e62e12 --- /dev/null +++ b/src/basic/login-util.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +bool session_id_valid(const char *id); + +static inline bool logind_running(void) { + return access("/run/systemd/seats/", F_OK) >= 0; +} diff --git a/src/basic/macro.h b/src/basic/macro.h new file mode 100644 index 00000000..712bb422 --- /dev/null +++ b/src/basic/macro.h @@ -0,0 +1,563 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#define _printf_(a, b) __attribute__((__format__(printf, a, b))) +#ifdef __clang__ +# define _alloc_(...) +#else +# define _alloc_(...) __attribute__((__alloc_size__(__VA_ARGS__))) +#endif +#define _sentinel_ __attribute__((__sentinel__)) +#define _section_(x) __attribute__((__section__(x))) +#define _used_ __attribute__((__used__)) +#define _unused_ __attribute__((__unused__)) +#define _destructor_ __attribute__((__destructor__)) +#define _pure_ __attribute__((__pure__)) +#define _const_ __attribute__((__const__)) +#define _deprecated_ __attribute__((__deprecated__)) +#define _packed_ __attribute__((__packed__)) +#define _malloc_ __attribute__((__malloc__)) +#define _weak_ __attribute__((__weak__)) +#define _likely_(x) (__builtin_expect(!!(x), 1)) +#define _unlikely_(x) (__builtin_expect(!!(x), 0)) +#define _public_ __attribute__((__visibility__("default"))) +#define _hidden_ __attribute__((__visibility__("hidden"))) +#define _weakref_(x) __attribute__((__weakref__(#x))) +#define _align_(x) __attribute__((__aligned__(x))) +#define _alignas_(x) __attribute__((__aligned__(__alignof(x)))) +#define _alignptr_ __attribute__((__aligned__(sizeof(void*)))) +#define _cleanup_(x) __attribute__((__cleanup__(x))) +#if __GNUC__ >= 7 +#define _fallthrough_ __attribute__((__fallthrough__)) +#else +#define _fallthrough_ +#endif +/* Define C11 noreturn without and even on older gcc + * compiler versions */ +#ifndef _noreturn_ +#if __STDC_VERSION__ >= 201112L +#define _noreturn_ _Noreturn +#else +#define _noreturn_ __attribute__((__noreturn__)) +#endif +#endif + +#if !defined(HAS_FEATURE_MEMORY_SANITIZER) +# if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# define HAS_FEATURE_MEMORY_SANITIZER 1 +# endif +# endif +# if !defined(HAS_FEATURE_MEMORY_SANITIZER) +# define HAS_FEATURE_MEMORY_SANITIZER 0 +# endif +#endif + +#if !defined(HAS_FEATURE_ADDRESS_SANITIZER) +# ifdef __SANITIZE_ADDRESS__ +# define HAS_FEATURE_ADDRESS_SANITIZER 1 +# elif defined(__has_feature) +# if __has_feature(address_sanitizer) +# define HAS_FEATURE_ADDRESS_SANITIZER 1 +# endif +# endif +# if !defined(HAS_FEATURE_ADDRESS_SANITIZER) +# define HAS_FEATURE_ADDRESS_SANITIZER 0 +# endif +#endif + +/* Note: on GCC "no_sanitize_address" is a function attribute only, on llvm it may also be applied to global + * variables. We define a specific macro which knows this. Note that on GCC we don't need this decorator so much, since + * our primary usecase for this attribute is registration structures placed in named ELF sections which shall not be + * padded, but GCC doesn't pad those anyway if AddressSanitizer is enabled. */ +#if HAS_FEATURE_ADDRESS_SANITIZER && defined(__clang__) +#define _variable_no_sanitize_address_ __attribute__((__no_sanitize_address__)) +#else +#define _variable_no_sanitize_address_ +#endif + +/* Temporarily disable some warnings */ +#define DISABLE_WARNING_FORMAT_NONLITERAL \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"") + +#define DISABLE_WARNING_MISSING_PROTOTYPES \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wmissing-prototypes\"") + +#define DISABLE_WARNING_NONNULL \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wnonnull\"") + +#define DISABLE_WARNING_SHADOW \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wshadow\"") + +#define DISABLE_WARNING_INCOMPATIBLE_POINTER_TYPES \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wincompatible-pointer-types\"") + +#if HAVE_WSTRINGOP_TRUNCATION +# define DISABLE_WARNING_STRINGOP_TRUNCATION \ + _Pragma("GCC diagnostic push"); \ + _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"") +#else +# define DISABLE_WARNING_STRINGOP_TRUNCATION \ + _Pragma("GCC diagnostic push") +#endif + +#define REENABLE_WARNING \ + _Pragma("GCC diagnostic pop") + +/* automake test harness */ +#define EXIT_TEST_SKIP 77 + +#define XSTRINGIFY(x) #x +#define STRINGIFY(x) XSTRINGIFY(x) + +#define XCONCATENATE(x, y) x ## y +#define CONCATENATE(x, y) XCONCATENATE(x, y) + +#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq)) +#define UNIQ __COUNTER__ + +/* builtins */ +#if __SIZEOF_INT__ == 4 +#define BUILTIN_FFS_U32(x) __builtin_ffs(x); +#elif __SIZEOF_LONG__ == 4 +#define BUILTIN_FFS_U32(x) __builtin_ffsl(x); +#else +#error "neither int nor long are four bytes long?!?" +#endif + +/* Rounds up */ + +#define ALIGN4(l) (((l) + 3) & ~3) +#define ALIGN8(l) (((l) + 7) & ~7) + +#if __SIZEOF_POINTER__ == 8 +#define ALIGN(l) ALIGN8(l) +#elif __SIZEOF_POINTER__ == 4 +#define ALIGN(l) ALIGN4(l) +#else +#error "Wut? Pointers are neither 4 nor 8 bytes long?" +#endif + +#define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) (p))) +#define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) (p))) +#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) (p))) + +static inline size_t ALIGN_TO(size_t l, size_t ali) { + return ((l + ali - 1) & ~(ali - 1)); +} + +#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) (p), (ali))) + +/* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */ +static inline unsigned long ALIGN_POWER2(unsigned long u) { + + /* Avoid subtraction overflow */ + if (u == 0) + return 0; + + /* clz(0) is undefined */ + if (u == 1) + return 1; + + /* left-shift overflow is undefined */ + if (__builtin_clzl(u - 1UL) < 1) + return 0; + + return 1UL << (sizeof(u) * 8 - __builtin_clzl(u - 1UL)); +} + +#ifndef __COVERITY__ +# define VOID_0 ((void)0) +#else +# define VOID_0 ((void*)0) +#endif + +#define ELEMENTSOF(x) \ + (__builtin_choose_expr( \ + !__builtin_types_compatible_p(typeof(x), typeof(&*(x))), \ + sizeof(x)/sizeof((x)[0]), \ + VOID_0)) + +/* + * STRLEN - return the length of a string literal, minus the trailing NUL byte. + * Contrary to strlen(), this is a constant expression. + * @x: a string literal. + */ +#define STRLEN(x) (sizeof(""x"") - 1) + +/* + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + */ +#define container_of(ptr, type, member) __container_of(UNIQ, (ptr), type, member) +#define __container_of(uniq, ptr, type, member) \ + ({ \ + const typeof( ((type*)0)->member ) *UNIQ_T(A, uniq) = (ptr); \ + (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type, member) ); \ + }) + +#undef MAX +#define MAX(a, b) __MAX(UNIQ, (a), UNIQ, (b)) +#define __MAX(aq, a, bq, b) \ + ({ \ + const typeof(a) UNIQ_T(A, aq) = (a); \ + const typeof(b) UNIQ_T(B, bq) = (b); \ + UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \ + }) + +/* evaluates to (void) if _A or _B are not constant or of different types */ +#define CONST_MAX(_A, _B) \ + (__builtin_choose_expr( \ + __builtin_constant_p(_A) && \ + __builtin_constant_p(_B) && \ + __builtin_types_compatible_p(typeof(_A), typeof(_B)), \ + ((_A) > (_B)) ? (_A) : (_B), \ + VOID_0)) + +/* takes two types and returns the size of the larger one */ +#define MAXSIZE(A, B) (sizeof(union _packed_ { typeof(A) a; typeof(B) b; })) + +#define MAX3(x, y, z) \ + ({ \ + const typeof(x) _c = MAX(x, y); \ + MAX(_c, z); \ + }) + +#undef MIN +#define MIN(a, b) __MIN(UNIQ, (a), UNIQ, (b)) +#define __MIN(aq, a, bq, b) \ + ({ \ + const typeof(a) UNIQ_T(A, aq) = (a); \ + const typeof(b) UNIQ_T(B, bq) = (b); \ + UNIQ_T(A, aq) < UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \ + }) + +#define MIN3(x, y, z) \ + ({ \ + const typeof(x) _c = MIN(x, y); \ + MIN(_c, z); \ + }) + +#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b)) +#define __LESS_BY(aq, a, bq, b) \ + ({ \ + const typeof(a) UNIQ_T(A, aq) = (a); \ + const typeof(b) UNIQ_T(B, bq) = (b); \ + UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) - UNIQ_T(B, bq) : 0; \ + }) + +#define CMP(a, b) __CMP(UNIQ, (a), UNIQ, (b)) +#define __CMP(aq, a, bq, b) \ + ({ \ + const typeof(a) UNIQ_T(A, aq) = (a); \ + const typeof(b) UNIQ_T(B, bq) = (b); \ + UNIQ_T(A, aq) < UNIQ_T(B, bq) ? -1 : \ + UNIQ_T(A, aq) > UNIQ_T(B, bq) ? 1 : 0; \ + }) + +#undef CLAMP +#define CLAMP(x, low, high) __CLAMP(UNIQ, (x), UNIQ, (low), UNIQ, (high)) +#define __CLAMP(xq, x, lowq, low, highq, high) \ + ({ \ + const typeof(x) UNIQ_T(X, xq) = (x); \ + const typeof(low) UNIQ_T(LOW, lowq) = (low); \ + const typeof(high) UNIQ_T(HIGH, highq) = (high); \ + UNIQ_T(X, xq) > UNIQ_T(HIGH, highq) ? \ + UNIQ_T(HIGH, highq) : \ + UNIQ_T(X, xq) < UNIQ_T(LOW, lowq) ? \ + UNIQ_T(LOW, lowq) : \ + UNIQ_T(X, xq); \ + }) + +/* [(x + y - 1) / y] suffers from an integer overflow, even though the + * computation should be possible in the given type. Therefore, we use + * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the + * quotient and the remainder, so both should be equally fast. */ +#define DIV_ROUND_UP(x, y) __DIV_ROUND_UP(UNIQ, (x), UNIQ, (y)) +#define __DIV_ROUND_UP(xq, x, yq, y) \ + ({ \ + const typeof(x) UNIQ_T(X, xq) = (x); \ + const typeof(y) UNIQ_T(Y, yq) = (y); \ + (UNIQ_T(X, xq) / UNIQ_T(Y, yq) + !!(UNIQ_T(X, xq) % UNIQ_T(Y, yq))); \ + }) + +#ifdef __COVERITY__ + +/* Use special definitions of assertion macros in order to prevent + * false positives of ASSERT_SIDE_EFFECT on Coverity static analyzer + * for uses of assert_se() and assert_return(). + * + * These definitions make expression go through a (trivial) function + * call to ensure they are not discarded. Also use ! or !! to ensure + * the boolean expressions are seen as such. + * + * This technique has been described and recommended in: + * https://community.synopsys.com/s/question/0D534000046Yuzb/suppressing-assertsideeffect-for-functions-that-allow-for-sideeffects + */ + +extern void __coverity_panic__(void); + +static inline void __coverity_check__(int condition) { + if (!condition) + __coverity_panic__(); +} + +static inline int __coverity_check_and_return__(int condition) { + return condition; +} + +#define assert_message_se(expr, message) __coverity_check__(!!(expr)) + +#define assert_log(expr, message) __coverity_check_and_return__(!!(expr)) + +#else /* ! __COVERITY__ */ + +#define assert_message_se(expr, message) \ + do { \ + if (_unlikely_(!(expr))) \ + log_assert_failed(message, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__); \ + } while (false) + +#define assert_log(expr, message) ((_likely_(expr)) \ + ? (true) \ + : (log_assert_failed_return(message, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__), false)) + +#endif /* __COVERITY__ */ + +#define assert_se(expr) assert_message_se(expr, #expr) + +/* We override the glibc assert() here. */ +#undef assert +#ifdef NDEBUG +#define assert(expr) do {} while (false) +#else +#define assert(expr) assert_message_se(expr, #expr) +#endif + +#define assert_not_reached(t) \ + log_assert_failed_unreachable(t, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__) + +#if defined(static_assert) +#define assert_cc(expr) \ + static_assert(expr, #expr) +#else +#define assert_cc(expr) \ + struct CONCATENATE(_assert_struct_, __COUNTER__) { \ + char x[(expr) ? 0 : -1]; \ + } +#endif + +#define assert_return(expr, r) \ + do { \ + if (!assert_log(expr, #expr)) \ + return (r); \ + } while (false) + +#define assert_return_errno(expr, r, err) \ + do { \ + if (!assert_log(expr, #expr)) { \ + errno = err; \ + return (r); \ + } \ + } while (false) + +#define return_with_errno(r, err) \ + do { \ + errno = abs(err); \ + return r; \ + } while (false) + +#define PTR_TO_INT(p) ((int) ((intptr_t) (p))) +#define INT_TO_PTR(u) ((void *) ((intptr_t) (u))) +#define PTR_TO_UINT(p) ((unsigned) ((uintptr_t) (p))) +#define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u))) + +#define PTR_TO_LONG(p) ((long) ((intptr_t) (p))) +#define LONG_TO_PTR(u) ((void *) ((intptr_t) (u))) +#define PTR_TO_ULONG(p) ((unsigned long) ((uintptr_t) (p))) +#define ULONG_TO_PTR(u) ((void *) ((uintptr_t) (u))) + +#define PTR_TO_INT32(p) ((int32_t) ((intptr_t) (p))) +#define INT32_TO_PTR(u) ((void *) ((intptr_t) (u))) +#define PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p))) +#define UINT32_TO_PTR(u) ((void *) ((uintptr_t) (u))) + +#define PTR_TO_INT64(p) ((int64_t) ((intptr_t) (p))) +#define INT64_TO_PTR(u) ((void *) ((intptr_t) (u))) +#define PTR_TO_UINT64(p) ((uint64_t) ((uintptr_t) (p))) +#define UINT64_TO_PTR(u) ((void *) ((uintptr_t) (u))) + +#define PTR_TO_SIZE(p) ((size_t) ((uintptr_t) (p))) +#define SIZE_TO_PTR(u) ((void *) ((uintptr_t) (u))) + +#define CHAR_TO_STR(x) ((char[2]) { x, 0 }) + +#define char_array_0(x) x[sizeof(x)-1] = 0; + +/* Returns the number of chars needed to format variables of the + * specified type as a decimal string. Adds in extra space for a + * negative '-' prefix (hence works correctly on signed + * types). Includes space for the trailing NUL. */ +#define DECIMAL_STR_MAX(type) \ + (2+(sizeof(type) <= 1 ? 3 : \ + sizeof(type) <= 2 ? 5 : \ + sizeof(type) <= 4 ? 10 : \ + sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)]))) + +#define DECIMAL_STR_WIDTH(x) \ + ({ \ + typeof(x) _x_ = (x); \ + unsigned ans = 1; \ + while ((_x_ /= 10) != 0) \ + ans++; \ + ans; \ + }) + +#define SET_FLAG(v, flag, b) \ + (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag)) +#define FLAGS_SET(v, flags) \ + ((~(v) & (flags)) == 0) + +#define CASE_F(X) case X: +#define CASE_F_1(CASE, X) CASE_F(X) +#define CASE_F_2(CASE, X, ...) CASE(X) CASE_F_1(CASE, __VA_ARGS__) +#define CASE_F_3(CASE, X, ...) CASE(X) CASE_F_2(CASE, __VA_ARGS__) +#define CASE_F_4(CASE, X, ...) CASE(X) CASE_F_3(CASE, __VA_ARGS__) +#define CASE_F_5(CASE, X, ...) CASE(X) CASE_F_4(CASE, __VA_ARGS__) +#define CASE_F_6(CASE, X, ...) CASE(X) CASE_F_5(CASE, __VA_ARGS__) +#define CASE_F_7(CASE, X, ...) CASE(X) CASE_F_6(CASE, __VA_ARGS__) +#define CASE_F_8(CASE, X, ...) CASE(X) CASE_F_7(CASE, __VA_ARGS__) +#define CASE_F_9(CASE, X, ...) CASE(X) CASE_F_8(CASE, __VA_ARGS__) +#define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__) +#define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__) +#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__) +#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__) +#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__) +#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__) +#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__) +#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__) +#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__) +#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__) +#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__) + +#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME +#define FOR_EACH_MAKE_CASE(...) \ + GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \ + CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \ + (CASE_F,__VA_ARGS__) + +#define IN_SET(x, ...) \ + ({ \ + bool _found = false; \ + /* If the build breaks in the line below, you need to extend the case macros. (We use "long double" as \ + * type for the array, in the hope that checkers such as ubsan don't complain that the initializers for \ + * the array are not representable by the base type. Ideally we'd use typeof(x) as base type, but that \ + * doesn't work, as we want to use this on bitfields and gcc refuses typeof() on bitfields.) */ \ + static const long double __assert_in_set[] _unused_ = { __VA_ARGS__ }; \ + assert_cc(ELEMENTSOF(__assert_in_set) <= 20); \ + switch(x) { \ + FOR_EACH_MAKE_CASE(__VA_ARGS__) \ + _found = true; \ + break; \ + default: \ + break; \ + } \ + _found; \ + }) + +#define SWAP_TWO(x, y) do { \ + typeof(x) _t = (x); \ + (x) = (y); \ + (y) = (_t); \ + } while (false) + +/* Define C11 thread_local attribute even on older gcc compiler + * version */ +#ifndef thread_local +/* + * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__ + * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769 + */ +#if __STDC_VERSION__ >= 201112L && !(defined(__STDC_NO_THREADS__) || (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16)) +#define thread_local _Thread_local +#else +#define thread_local __thread +#endif +#endif + +#define DEFINE_TRIVIAL_DESTRUCTOR(name, type, func) \ + static inline void name(type *p) { \ + func(p); \ + } + +#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \ + static inline void func##p(type *p) { \ + if (*p) \ + func(*p); \ + } + +#define _DEFINE_TRIVIAL_REF_FUNC(type, name, scope) \ + scope type *name##_ref(type *p) { \ + if (!p) \ + return NULL; \ + \ + assert(p->n_ref > 0); \ + p->n_ref++; \ + return p; \ + } + +#define _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func, scope) \ + scope type *name##_unref(type *p) { \ + if (!p) \ + return NULL; \ + \ + assert(p->n_ref > 0); \ + p->n_ref--; \ + if (p->n_ref > 0) \ + return NULL; \ + \ + return free_func(p); \ + } + +#define DEFINE_TRIVIAL_REF_FUNC(type, name) \ + _DEFINE_TRIVIAL_REF_FUNC(type, name,) +#define DEFINE_PRIVATE_TRIVIAL_REF_FUNC(type, name) \ + _DEFINE_TRIVIAL_REF_FUNC(type, name, static) +#define DEFINE_PUBLIC_TRIVIAL_REF_FUNC(type, name) \ + _DEFINE_TRIVIAL_REF_FUNC(type, name, _public_) + +#define DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func) \ + _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func,) +#define DEFINE_PRIVATE_TRIVIAL_UNREF_FUNC(type, name, free_func) \ + _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func, static) +#define DEFINE_PUBLIC_TRIVIAL_UNREF_FUNC(type, name, free_func) \ + _DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func, _public_) + +#define DEFINE_TRIVIAL_REF_UNREF_FUNC(type, name, free_func) \ + DEFINE_TRIVIAL_REF_FUNC(type, name); \ + DEFINE_TRIVIAL_UNREF_FUNC(type, name, free_func); + +#define DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(type, name, free_func) \ + DEFINE_PRIVATE_TRIVIAL_REF_FUNC(type, name); \ + DEFINE_PRIVATE_TRIVIAL_UNREF_FUNC(type, name, free_func); + +#define DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(type, name, free_func) \ + DEFINE_PUBLIC_TRIVIAL_REF_FUNC(type, name); \ + DEFINE_PUBLIC_TRIVIAL_UNREF_FUNC(type, name, free_func); + +#include "log.h" diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c new file mode 100644 index 00000000..e06bdcb0 --- /dev/null +++ b/src/basic/memfd-util.c @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#if HAVE_LINUX_MEMFD_H +#include +#endif +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "macro.h" +#include "memfd-util.h" +#include "missing_fcntl.h" +#include "missing_mman.h" +#include "missing_syscall.h" +#include "string-util.h" +#include "utf8.h" + +int memfd_new(const char *name) { + _cleanup_free_ char *g = NULL; + int fd; + + if (!name) { + char pr[17] = {}; + + /* If no name is specified we generate one. We include + * a hint indicating our library implementation, and + * add the thread name to it */ + + assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0); + + if (isempty(pr)) + name = "sd"; + else { + _cleanup_free_ char *e = NULL; + + e = utf8_escape_invalid(pr); + if (!e) + return -ENOMEM; + + g = strjoin("sd-", e); + if (!g) + return -ENOMEM; + + name = g; + } + } + + fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC); + if (fd < 0) + return -errno; + + return fd; +} + +int memfd_map(int fd, uint64_t offset, size_t size, void **p) { + void *q; + int sealed; + + assert(fd >= 0); + assert(size > 0); + assert(p); + + sealed = memfd_get_sealed(fd); + if (sealed < 0) + return sealed; + + if (sealed) + q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset); + else + q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); + + if (q == MAP_FAILED) + return -errno; + + *p = q; + return 0; +} + +int memfd_set_sealed(int fd) { + int r; + + assert(fd >= 0); + + r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL); + if (r < 0) + return -errno; + + return 0; +} + +int memfd_get_sealed(int fd) { + int r; + + assert(fd >= 0); + + r = fcntl(fd, F_GET_SEALS); + if (r < 0) + return -errno; + + return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL); +} + +int memfd_get_size(int fd, uint64_t *sz) { + struct stat stat; + int r; + + assert(fd >= 0); + assert(sz); + + r = fstat(fd, &stat); + if (r < 0) + return -errno; + + *sz = stat.st_size; + return 0; +} + +int memfd_set_size(int fd, uint64_t sz) { + int r; + + assert(fd >= 0); + + r = ftruncate(fd, sz); + if (r < 0) + return -errno; + + return 0; +} + +int memfd_new_and_map(const char *name, size_t sz, void **p) { + _cleanup_close_ int fd = -1; + int r; + + assert(sz > 0); + assert(p); + + fd = memfd_new(name); + if (fd < 0) + return fd; + + r = memfd_set_size(fd, sz); + if (r < 0) + return r; + + r = memfd_map(fd, 0, sz, p); + if (r < 0) + return r; + + return TAKE_FD(fd); +} diff --git a/src/basic/memfd-util.h b/src/basic/memfd-util.h new file mode 100644 index 00000000..5ebb5199 --- /dev/null +++ b/src/basic/memfd-util.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +int memfd_new(const char *name); +int memfd_new_and_map(const char *name, size_t sz, void **p); + +int memfd_map(int fd, uint64_t offset, size_t size, void **p); + +int memfd_set_sealed(int fd); +int memfd_get_sealed(int fd); + +int memfd_get_size(int fd, uint64_t *sz); +int memfd_set_size(int fd, uint64_t sz); diff --git a/src/basic/memory-util.c b/src/basic/memory-util.c new file mode 100644 index 00000000..5f327ef0 --- /dev/null +++ b/src/basic/memory-util.c @@ -0,0 +1,57 @@ +#include + +#include "memory-util.h" + +size_t page_size(void) { + static thread_local size_t pgsz = 0; + long r; + + if (_likely_(pgsz > 0)) + return pgsz; + + r = sysconf(_SC_PAGESIZE); + assert(r > 0); + + pgsz = (size_t) r; + return pgsz; +} + +bool memeqzero(const void *data, size_t length) { + /* Does the buffer consist entirely of NULs? + * Copied from https://github.com/systemd/casync/, copied in turn from + * https://github.com/rustyrussell/ccan/blob/master/ccan/mem/mem.c#L92, + * which is licensed CC-0. + */ + + const uint8_t *p = data; + size_t i; + + /* Check first 16 bytes manually */ + for (i = 0; i < 16; i++, length--) { + if (length == 0) + return true; + if (p[i]) + return false; + } + + /* Now we know first 16 bytes are NUL, memcmp with self. */ + return memcmp(data, p + i, length) == 0; +} + +#if !HAVE_EXPLICIT_BZERO +/* + * The pointer to memset() is volatile so that compiler must de-reference the pointer and can't assume that + * it points to any function in particular (such as memset(), which it then might further "optimize"). This + * approach is inspired by openssl's crypto/mem_clr.c. + */ +typedef void *(*memset_t)(void *,int,size_t); + +static volatile memset_t memset_func = memset; + +void* explicit_bzero_safe(void *p, size_t l) { + if (l > 0) + memset_func(p, '\0', l); + + return p; +} +#endif diff --git a/src/basic/memory-util.h b/src/basic/memory-util.h new file mode 100644 index 00000000..46a6907a --- /dev/null +++ b/src/basic/memory-util.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include + +#include "macro.h" + +size_t page_size(void) _pure_; +#define PAGE_ALIGN(l) ALIGN_TO((l), page_size()) +#define PAGE_ALIGN_DOWN(l) (l & ~(page_size() - 1)) + +/* Normal memcpy requires src to be nonnull. We do nothing if n is 0. */ +static inline void memcpy_safe(void *dst, const void *src, size_t n) { + if (n == 0) + return; + assert(src); + memcpy(dst, src, n); +} + +/* Normal memcmp requires s1 and s2 to be nonnull. We do nothing if n is 0. */ +static inline int memcmp_safe(const void *s1, const void *s2, size_t n) { + if (n == 0) + return 0; + assert(s1); + assert(s2); + return memcmp(s1, s2, n); +} + +/* Compare s1 (length n1) with s2 (length n2) in lexicographic order. */ +static inline int memcmp_nn(const void *s1, size_t n1, const void *s2, size_t n2) { + return memcmp_safe(s1, s2, MIN(n1, n2)) + ?: CMP(n1, n2); +} + +#define memzero(x,l) \ + ({ \ + size_t _l_ = (l); \ + if (_l_ > 0) \ + memset(x, 0, _l_); \ + }) + +#define zero(x) (memzero(&(x), sizeof(x))) + +bool memeqzero(const void *data, size_t length); + +#define eqzero(x) memeqzero(x, sizeof(x)) + +static inline void *mempset(void *s, int c, size_t n) { + memset(s, c, n); + return (uint8_t*)s + n; +} + +/* Normal memmem() requires haystack to be nonnull, which is annoying for zero-length buffers */ +static inline void *memmem_safe(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { + + if (needlelen <= 0) + return (void*) haystack; + + if (haystacklen < needlelen) + return NULL; + + assert(haystack); + assert(needle); + + return memmem(haystack, haystacklen, needle, needlelen); +} + +#if HAVE_EXPLICIT_BZERO +static inline void* explicit_bzero_safe(void *p, size_t l) { + if (l > 0) + explicit_bzero(p, l); + + return p; +} +#else +void *explicit_bzero_safe(void *p, size_t l); +#endif + +static inline void erase_and_freep(void *p) { + void *ptr = *(void**) p; + + if (ptr) { + size_t l = malloc_usable_size(ptr); + explicit_bzero_safe(ptr, l); + free(ptr); + } +} + +/* Use with _cleanup_ to erase a single 'char' when leaving scope */ +static inline void erase_char(char *p) { + explicit_bzero_safe(p, sizeof(char)); +} diff --git a/src/basic/mempool.c b/src/basic/mempool.c new file mode 100644 index 00000000..22df4210 --- /dev/null +++ b/src/basic/mempool.c @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "env-util.h" +#include "macro.h" +#include "memory-util.h" +#include "mempool.h" +#include "process-util.h" +#include "util.h" + +struct pool { + struct pool *next; + size_t n_tiles; + size_t n_used; +}; + +void* mempool_alloc_tile(struct mempool *mp) { + size_t i; + + /* When a tile is released we add it to the list and simply + * place the next pointer at its offset 0. */ + + assert(mp->tile_size >= sizeof(void*)); + assert(mp->at_least > 0); + + if (mp->freelist) { + void *r; + + r = mp->freelist; + mp->freelist = * (void**) mp->freelist; + return r; + } + + if (_unlikely_(!mp->first_pool) || + _unlikely_(mp->first_pool->n_used >= mp->first_pool->n_tiles)) { + size_t size, n; + struct pool *p; + + n = mp->first_pool ? mp->first_pool->n_tiles : 0; + n = MAX(mp->at_least, n * 2); + size = PAGE_ALIGN(ALIGN(sizeof(struct pool)) + n*mp->tile_size); + n = (size - ALIGN(sizeof(struct pool))) / mp->tile_size; + + p = malloc(size); + if (!p) + return NULL; + + p->next = mp->first_pool; + p->n_tiles = n; + p->n_used = 0; + + mp->first_pool = p; + } + + i = mp->first_pool->n_used++; + + return ((uint8_t*) mp->first_pool) + ALIGN(sizeof(struct pool)) + i*mp->tile_size; +} + +void* mempool_alloc0_tile(struct mempool *mp) { + void *p; + + p = mempool_alloc_tile(mp); + if (p) + memzero(p, mp->tile_size); + return p; +} + +void mempool_free_tile(struct mempool *mp, void *p) { + * (void**) p = mp->freelist; + mp->freelist = p; +} + +bool mempool_enabled(void) { + static int b = -1; + + if (!is_main_thread()) + return false; + + if (!mempool_use_allowed) + b = false; + if (b < 0) + b = getenv_bool("SYSTEMD_MEMPOOL") != 0; + + return b; +} + +#if VALGRIND +void mempool_drop(struct mempool *mp) { + struct pool *p = mp->first_pool; + while (p) { + struct pool *n; + n = p->next; + free(p); + p = n; + } +} +#endif diff --git a/src/basic/mempool.h b/src/basic/mempool.h new file mode 100644 index 00000000..0eecca0f --- /dev/null +++ b/src/basic/mempool.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +struct pool; + +struct mempool { + struct pool *first_pool; + void *freelist; + size_t tile_size; + unsigned at_least; +}; + +void* mempool_alloc_tile(struct mempool *mp); +void* mempool_alloc0_tile(struct mempool *mp); +void mempool_free_tile(struct mempool *mp, void *p); + +#define DEFINE_MEMPOOL(pool_name, tile_type, alloc_at_least) \ +static struct mempool pool_name = { \ + .tile_size = sizeof(tile_type), \ + .at_least = alloc_at_least, \ +} + +extern const bool mempool_use_allowed; +bool mempool_enabled(void); + +#if VALGRIND +void mempool_drop(struct mempool *mp); +#endif diff --git a/src/basic/meson.build b/src/basic/meson.build new file mode 100644 index 00000000..f70d1b8b --- /dev/null +++ b/src/basic/meson.build @@ -0,0 +1,337 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +basic_sources = files(''' + MurmurHash2.c + MurmurHash2.h + af-list.c + af-list.h + alloc-util.c + alloc-util.h + architecture.c + architecture.h + arphrd-list.c + arphrd-list.h + async.c + async.h + audit-util.c + audit-util.h + blockdev-util.c + blockdev-util.h + btrfs-util.c + btrfs-util.h + build.h + bus-label.c + bus-label.h + cap-list.c + cap-list.h + capability-util.c + capability-util.h + cgroup-util.c + cgroup-util.h + chattr-util.c + chattr-util.h + conf-files.c + conf-files.h + copy.c + copy.h + def.h + device-nodes.c + device-nodes.h + dirent-util.c + dirent-util.h + efivars.c + efivars.h + env-file.c + env-file.h + env-util.c + env-util.h + errno-list.c + errno-list.h + errno-util.h + escape.c + escape.h + ether-addr-util.c + ether-addr-util.h + extract-word.c + extract-word.h + fd-util.c + fd-util.h + fileio.c + fileio.h + format-util.c + format-util.h + fs-util.c + fs-util.h + glob-util.c + glob-util.h + gunicode.c + gunicode.h + hash-funcs.c + hash-funcs.h + hashmap.c + hashmap.h + hexdecoct.c + hexdecoct.h + hostname-util.c + hostname-util.h + in-addr-util.c + in-addr-util.h + io-util.c + io-util.h + ioprio.h + kbd-util.c + kbd-util.h + khash.c + khash.h + label.c + label.h + limits-util.c + limits-util.h + linux/btrfs.h + linux/btrfs_tree.h + linux/can/vxcan.h + linux/fib_rules.h + linux/fou.h + linux/if.h + linux/if_addr.h + linux/if_arp.h + linux/if_bonding.h + linux/if_bridge.h + linux/if_ether.h + linux/if_link.h + linux/if_macsec.h + linux/if_tun.h + linux/if_tunnel.h + linux/in.h + linux/in6.h + linux/l2tp.h + linux/libc-compat.h + linux/netdevice.h + linux/netlink.h + linux/rtnetlink.h + linux/wireguard.h + list.h + locale-util.c + locale-util.h + log.c + log.h + login-util.c + login-util.h + macro.h + memfd-util.c + memfd-util.h + memory-util.c + memory-util.h + mempool.c + mempool.h + missing_audit.h + missing_capability.h + missing_drm.h + missing_fcntl.h + missing_fs.h + missing_input.h + missing_keyctl.h + missing_magic.h + missing_mman.h + missing_network.h + missing_prctl.h + missing_random.h + missing_resource.h + missing_sched.h + missing_securebits.h + missing_socket.h + missing_stat.h + missing_stdlib.h + missing_syscall.h + missing_timerfd.h + missing_type.h + mkdir-label.c + mkdir.c + mkdir.h + mountpoint-util.c + mountpoint-util.h + namespace-util.c + namespace-util.h + nss-util.h + nulstr-util.c + nulstr-util.h + ordered-set.c + ordered-set.h + parse-util.c + parse-util.h + path-util.c + path-util.h + prioq.c + prioq.h + proc-cmdline.c + proc-cmdline.h + process-util.c + process-util.h + procfs-util.c + procfs-util.h + random-util.c + random-util.h + ratelimit.c + ratelimit.h + raw-clone.h + raw-reboot.h + replace-var.c + replace-var.h + rlimit-util.c + rlimit-util.h + rm-rf.c + rm-rf.h + selinux-util.c + selinux-util.h + set.h + sigbus.c + sigbus.h + signal-util.c + signal-util.h + siphash24.c + siphash24.h + smack-util.c + smack-util.h + socket-label.c + socket-util.c + socket-util.h + sort-util.c + sort-util.h + sparse-endian.h + special.h + stat-util.c + stat-util.h + static-destruct.h + stdio-util.h + strbuf.c + strbuf.h + string-table.c + string-table.h + string-util.c + string-util.h + strv.c + strv.h + strxcpyx.c + strxcpyx.h + syslog-util.c + syslog-util.h + terminal-util.c + terminal-util.h + time-util.c + time-util.h + tmpfile-util.c + tmpfile-util.h + umask-util.h + unaligned.h + unit-def.c + unit-def.h + unit-name.c + unit-name.h + user-util.c + user-util.h + utf8.c + utf8.h + util.c + util.h + virt.c + virt.h + xattr-util.c + xattr-util.h +'''.split()) + +missing_audit_h = files('missing_audit.h') +missing_capability_h = files('missing_capability.h') +missing_socket_h = files('missing_socket.h') + +generate_af_list = find_program('generate-af-list.sh') +af_list_txt = custom_target( + 'af-list.txt', + output : 'af-list.txt', + command : [generate_af_list, cpp, config_h, missing_socket_h], + capture : true) + +generate_arphrd_list = find_program('generate-arphrd-list.sh') +arphrd_list_txt = custom_target( + 'arphrd-list.txt', + output : 'arphrd-list.txt', + command : [generate_arphrd_list, cpp, config_h], + capture : true) + +generate_cap_list = find_program('generate-cap-list.sh') +cap_list_txt = custom_target( + 'cap-list.txt', + output : 'cap-list.txt', + command : [generate_cap_list, cpp, config_h, missing_capability_h], + capture : true) + +generate_errno_list = find_program('generate-errno-list.sh') +errno_list_txt = custom_target( + 'errno-list.txt', + output : 'errno-list.txt', + command : [generate_errno_list, cpp], + capture : true) + +generated_gperf_headers = [] +foreach item : [['af', af_list_txt, 'af', ''], + ['arphrd', arphrd_list_txt, 'arphrd', 'ARPHRD_'], + ['cap', cap_list_txt, 'capability', ''], + ['errno', errno_list_txt, 'errno', '']] + + fname = '@0@-from-name.gperf'.format(item[0]) + gperf_file = custom_target( + fname, + input : item[1], + output : fname, + command : [generate_gperfs, item[2], item[3], '@INPUT@'], + capture : true) + + fname = '@0@-from-name.h'.format(item[0]) + target1 = custom_target( + fname, + input : gperf_file, + output : fname, + command : [gperf, + '-L', 'ANSI-C', '-t', '--ignore-case', + '-N', 'lookup_@0@'.format(item[2]), + '-H', 'hash_@0@_name'.format(item[2]), + '-p', '-C', + '@INPUT@'], + capture : true) + + fname = '@0@-to-name.h'.format(item[0]) + awkscript = '@0@-to-name.awk'.format(item[0]) + target2 = custom_target( + fname, + input : [awkscript, item[1]], + output : fname, + command : [awk, '-f', '@INPUT0@', '@INPUT1@'], + capture : true) + + generated_gperf_headers += [target1, target2] +endforeach + +basic_sources += generated_gperf_headers +basic_gcrypt_sources = files( + 'gcrypt-util.c', + 'gcrypt-util.h') + +libbasic = static_library( + 'basic', + basic_sources, + include_directories : includes, + dependencies : [versiondep, + threads, + libcap, + libselinux, + libm], + c_args : ['-fvisibility=default'], + install : false) + +# A convenience library that is separate from libbasic to avoid +# unnecessary linking to libgcrypt. +libbasic_gcrypt = static_library( + 'basic-gcrypt', + basic_gcrypt_sources, + include_directories : includes, + dependencies : [libgcrypt], + c_args : ['-fvisibility=default']) diff --git a/src/basic/missing_audit.h b/src/basic/missing_audit.h new file mode 100644 index 00000000..b00d537b --- /dev/null +++ b/src/basic/missing_audit.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#if HAVE_AUDIT +#include +#endif + +#ifndef AUDIT_SERVICE_START +#define AUDIT_SERVICE_START 1130 /* Service (daemon) start */ +#endif + +#ifndef AUDIT_SERVICE_STOP +#define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */ +#endif + +#ifndef MAX_AUDIT_MESSAGE_LENGTH +#define MAX_AUDIT_MESSAGE_LENGTH 8970 +#endif + +#ifndef AUDIT_NLGRP_MAX +#define AUDIT_NLGRP_READLOG 1 +#endif diff --git a/src/basic/missing_capability.h b/src/basic/missing_capability.h new file mode 100644 index 00000000..1308a3d6 --- /dev/null +++ b/src/basic/missing_capability.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +/* 3a101b8de0d39403b2c7e5c23fd0b005668acf48 (3.16) */ +#ifndef CAP_AUDIT_READ +#define CAP_AUDIT_READ 37 + +#undef CAP_LAST_CAP +#define CAP_LAST_CAP CAP_AUDIT_READ +#endif diff --git a/src/basic/missing_drm.h b/src/basic/missing_drm.h new file mode 100644 index 00000000..a64f74ef --- /dev/null +++ b/src/basic/missing_drm.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#ifndef DRM_IOCTL_SET_MASTER +#define DRM_IOCTL_SET_MASTER _IO('d', 0x1e) +#endif + +#ifndef DRM_IOCTL_DROP_MASTER +#define DRM_IOCTL_DROP_MASTER _IO('d', 0x1f) +#endif diff --git a/src/basic/missing_fcntl.h b/src/basic/missing_fcntl.h new file mode 100644 index 00000000..5d1c6352 --- /dev/null +++ b/src/basic/missing_fcntl.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#ifndef F_LINUX_SPECIFIC_BASE +#define F_LINUX_SPECIFIC_BASE 1024 +#endif + +#ifndef F_SETPIPE_SZ +#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7) +#endif + +#ifndef F_GETPIPE_SZ +#define F_GETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 8) +#endif + +#ifndef F_ADD_SEALS +#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) +#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) + +#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ +#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ +#define F_SEAL_GROW 0x0004 /* prevent file from growing */ +#define F_SEAL_WRITE 0x0008 /* prevent writes */ +#endif + +#ifndef F_OFD_GETLK +#define F_OFD_GETLK 36 +#define F_OFD_SETLK 37 +#define F_OFD_SETLKW 38 +#endif + +#ifndef MAX_HANDLE_SZ +#define MAX_HANDLE_SZ 128 +#endif + +/* The precise definition of __O_TMPFILE is arch specific; use the + * values defined by the kernel (note: some are hexa, some are octal, + * duplicated as-is from the kernel definitions): + * - alpha, parisc, sparc: each has a specific value; + * - others: they use the "generic" value. + */ + +#ifndef __O_TMPFILE +#if defined(__alpha__) +#define __O_TMPFILE 0100000000 +#elif defined(__parisc__) || defined(__hppa__) +#define __O_TMPFILE 0400000000 +#elif defined(__sparc__) || defined(__sparc64__) +#define __O_TMPFILE 0x2000000 +#else +#define __O_TMPFILE 020000000 +#endif +#endif + +/* a horrid kludge trying to make sure that this will fail on old kernels */ +#ifndef O_TMPFILE +#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) +#endif diff --git a/src/basic/missing_fs.h b/src/basic/missing_fs.h new file mode 100644 index 00000000..c262a918 --- /dev/null +++ b/src/basic/missing_fs.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/* linux/fs.h */ +#ifndef RENAME_NOREPLACE /* 0a7c3937a1f23f8cb5fc77ae01661e9968a51d0c (3.15) */ +#define RENAME_NOREPLACE (1 << 0) +#endif + +/* linux/fs.h or sys/mount.h */ +#ifndef MS_MOVE +#define MS_MOVE 8192 +#endif + +#ifndef MS_REC +#define MS_REC 16384 +#endif + +#ifndef MS_PRIVATE +#define MS_PRIVATE (1<<18) +#endif + +#ifndef MS_SLAVE +#define MS_SLAVE (1<<19) +#endif + +#ifndef MS_SHARED +#define MS_SHARED (1<<20) +#endif + +#ifndef MS_RELATIME +#define MS_RELATIME (1<<21) +#endif + +#ifndef MS_KERNMOUNT +#define MS_KERNMOUNT (1<<22) +#endif + +#ifndef MS_I_VERSION +#define MS_I_VERSION (1<<23) +#endif + +#ifndef MS_STRICTATIME +#define MS_STRICTATIME (1<<24) +#endif + +#ifndef MS_LAZYTIME +#define MS_LAZYTIME (1<<25) +#endif + +/* Not exposed yet. Defined at fs/ext4/ext4.h */ +#ifndef EXT4_IOC_RESIZE_FS +#define EXT4_IOC_RESIZE_FS _IOW('f', 16, __u64) +#endif + +/* Not exposed yet. Defined at fs/cifs/cifsglob.h */ +#ifndef CIFS_MAGIC_NUMBER +#define CIFS_MAGIC_NUMBER 0xFF534D42 +#endif + +/* linux/nsfs.h */ +#ifndef NS_GET_NSTYPE /* d95fa3c76a66b6d76b1e109ea505c55e66360f3c (4.11) */ +#define NS_GET_NSTYPE _IO(0xb7, 0x3) +#endif + +#ifndef FS_PROJINHERIT_FL +#define FS_PROJINHERIT_FL 0x20000000 +#endif diff --git a/src/basic/missing_input.h b/src/basic/missing_input.h new file mode 100644 index 00000000..b91ccb64 --- /dev/null +++ b/src/basic/missing_input.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +/* linux@c7dc65737c9a607d3e6f8478659876074ad129b8 (3.12) */ +#ifndef EVIOCREVOKE +#define EVIOCREVOKE _IOW('E', 0x91, int) +#endif + +/* linux@06a16293f71927f756dcf37558a79c0b05a91641 (4.4) */ +#ifndef EVIOCSMASK +struct input_mask { + __u32 type; + __u32 codes_size; + __u64 codes_ptr; +}; + +#define EVIOCGMASK _IOR('E', 0x92, struct input_mask) +#define EVIOCSMASK _IOW('E', 0x93, struct input_mask) +#endif + +/* linux@7611392fe8ff95ecae528b01a815ae3d72ca6b95 (3.17) */ +#ifndef INPUT_PROP_POINTING_STICK +#define INPUT_PROP_POINTING_STICK 0x05 +#endif + +/* linux@500d4160abe9a2e88b12e319c13ae3ebd1e18108 (4.0) */ +#ifndef INPUT_PROP_ACCELEROMETER +#define INPUT_PROP_ACCELEROMETER 0x06 +#endif + +/* linux@d09bbfd2a8408a995419dff0d2ba906013cf4cc9 (3.11) */ +#ifndef BTN_DPAD_UP +#define BTN_DPAD_UP 0x220 +#define BTN_DPAD_DOWN 0x221 +#define BTN_DPAD_LEFT 0x222 +#define BTN_DPAD_RIGHT 0x223 +#endif + +/* linux@358f24704f2f016af7d504b357cdf32606091d07 (3.13) */ +#ifndef KEY_ALS_TOGGLE +#define KEY_ALS_TOGGLE 0x230 +#endif diff --git a/src/basic/missing_keyctl.h b/src/basic/missing_keyctl.h new file mode 100644 index 00000000..7eb70958 --- /dev/null +++ b/src/basic/missing_keyctl.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#ifndef KEYCTL_JOIN_SESSION_KEYRING +#define KEYCTL_JOIN_SESSION_KEYRING 1 +#endif + +#ifndef KEYCTL_CHOWN +#define KEYCTL_CHOWN 4 +#endif + +#ifndef KEYCTL_SETPERM +#define KEYCTL_SETPERM 5 +#endif + +#ifndef KEYCTL_DESCRIBE +#define KEYCTL_DESCRIBE 6 +#endif + +#ifndef KEYCTL_LINK +#define KEYCTL_LINK 8 +#endif + +#ifndef KEYCTL_READ +#define KEYCTL_READ 11 +#endif + +#ifndef KEYCTL_SET_TIMEOUT +#define KEYCTL_SET_TIMEOUT 15 +#endif + +#ifndef KEY_SPEC_USER_KEYRING +#define KEY_SPEC_USER_KEYRING -4 +#endif + +#ifndef KEY_SPEC_SESSION_KEYRING +#define KEY_SPEC_SESSION_KEYRING -3 +#endif + +/* From linux/key.h */ +#ifndef KEY_POS_VIEW + +typedef int32_t key_serial_t; + +#define KEY_POS_VIEW 0x01000000 +#define KEY_POS_READ 0x02000000 +#define KEY_POS_WRITE 0x04000000 +#define KEY_POS_SEARCH 0x08000000 +#define KEY_POS_LINK 0x10000000 +#define KEY_POS_SETATTR 0x20000000 +#define KEY_POS_ALL 0x3f000000 + +#define KEY_USR_VIEW 0x00010000 +#define KEY_USR_READ 0x00020000 +#define KEY_USR_WRITE 0x00040000 +#define KEY_USR_SEARCH 0x00080000 +#define KEY_USR_LINK 0x00100000 +#define KEY_USR_SETATTR 0x00200000 +#define KEY_USR_ALL 0x003f0000 + +#define KEY_GRP_VIEW 0x00000100 +#define KEY_GRP_READ 0x00000200 +#define KEY_GRP_WRITE 0x00000400 +#define KEY_GRP_SEARCH 0x00000800 +#define KEY_GRP_LINK 0x00001000 +#define KEY_GRP_SETATTR 0x00002000 +#define KEY_GRP_ALL 0x00003f00 + +#define KEY_OTH_VIEW 0x00000001 +#define KEY_OTH_READ 0x00000002 +#define KEY_OTH_WRITE 0x00000004 +#define KEY_OTH_SEARCH 0x00000008 +#define KEY_OTH_LINK 0x00000010 +#define KEY_OTH_SETATTR 0x00000020 +#define KEY_OTH_ALL 0x0000003f +#endif diff --git a/src/basic/missing_magic.h b/src/basic/missing_magic.h new file mode 100644 index 00000000..4910cd36 --- /dev/null +++ b/src/basic/missing_magic.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +/* 62aa81d7c4c24b90fdb61da70ac0dbbc414f9939 (4.13) */ +#ifndef OCFS2_SUPER_MAGIC +#define OCFS2_SUPER_MAGIC 0x7461636f +#endif + +/* 67e9c74b8a873408c27ac9a8e4c1d1c8d72c93ff (4.5) */ +#ifndef CGROUP2_SUPER_MAGIC +#define CGROUP2_SUPER_MAGIC 0x63677270 +#endif + +/* 4282d60689d4f21b40692029080440cc58e8a17d (4.1) */ +#ifndef TRACEFS_MAGIC +#define TRACEFS_MAGIC 0x74726163 +#endif + +/* e149ed2b805fefdccf7ccdfc19eca22fdd4514ac (3.19) */ +#ifndef NSFS_MAGIC +#define NSFS_MAGIC 0x6e736673 +#endif + +/* b2197755b2633e164a439682fb05a9b5ea48f706 (4.4) */ +#ifndef BPF_FS_MAGIC +#define BPF_FS_MAGIC 0xcafe4a11 +#endif + +/* Not exposed yet (4.20). Defined at ipc/mqueue.c */ +#ifndef MQUEUE_MAGIC +#define MQUEUE_MAGIC 0x19800202 +#endif diff --git a/src/basic/missing_mman.h b/src/basic/missing_mman.h new file mode 100644 index 00000000..7ff12f77 --- /dev/null +++ b/src/basic/missing_mman.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#ifndef MFD_ALLOW_SEALING +#define MFD_ALLOW_SEALING 0x0002U +#endif + +#ifndef MFD_CLOEXEC +#define MFD_CLOEXEC 0x0001U +#endif diff --git a/src/basic/missing_network.h b/src/basic/missing_network.h new file mode 100644 index 00000000..25787940 --- /dev/null +++ b/src/basic/missing_network.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/* linux/in6.h or netinet/in.h */ +#ifndef IPV6_UNICAST_IF +#define IPV6_UNICAST_IF 76 +#endif + +/* Not exposed but defined at include/net/ip.h */ +#ifndef IPV4_MIN_MTU +#define IPV4_MIN_MTU 68 +#endif + +/* linux/ipv6.h */ +#ifndef IPV6_MIN_MTU +#define IPV6_MIN_MTU 1280 +#endif + +/* Note that LOOPBACK_IFINDEX is currently not exposed by the + * kernel/glibc, but hardcoded internally by the kernel. However, as + * it is exported to userspace indirectly via rtnetlink and the + * ioctls, and made use of widely we define it here too, in a way that + * is compatible with the kernel's internal definition. */ +#ifndef LOOPBACK_IFINDEX +#define LOOPBACK_IFINDEX 1 +#endif + +/* Not exposed yet. Similar values are defined in net/ethernet.h */ +#ifndef ETHERTYPE_LLDP +#define ETHERTYPE_LLDP 0x88cc +#endif diff --git a/src/basic/missing_prctl.h b/src/basic/missing_prctl.h new file mode 100644 index 00000000..f80cd17f --- /dev/null +++ b/src/basic/missing_prctl.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +/* 58319057b7847667f0c9585b9de0e8932b0fdb08 (4.3) */ +#ifndef PR_CAP_AMBIENT +#define PR_CAP_AMBIENT 47 + +#define PR_CAP_AMBIENT_IS_SET 1 +#define PR_CAP_AMBIENT_RAISE 2 +#define PR_CAP_AMBIENT_LOWER 3 +#define PR_CAP_AMBIENT_CLEAR_ALL 4 +#endif diff --git a/src/basic/missing_random.h b/src/basic/missing_random.h new file mode 100644 index 00000000..2e76031b --- /dev/null +++ b/src/basic/missing_random.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if USE_SYS_RANDOM_H +# include +#else +# include +#endif + +#ifndef GRND_NONBLOCK +#define GRND_NONBLOCK 0x0001 +#endif + +#ifndef GRND_RANDOM +#define GRND_RANDOM 0x0002 +#endif diff --git a/src/basic/missing_resource.h b/src/basic/missing_resource.h new file mode 100644 index 00000000..22ba8abf --- /dev/null +++ b/src/basic/missing_resource.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#ifndef RLIMIT_RTTIME +#define RLIMIT_RTTIME 15 +#endif + +/* If RLIMIT_RTTIME is not defined, then we cannot use RLIMIT_NLIMITS as is */ +#define _RLIMIT_MAX (RLIMIT_RTTIME+1 > RLIMIT_NLIMITS ? RLIMIT_RTTIME+1 : RLIMIT_NLIMITS) diff --git a/src/basic/missing_sched.h b/src/basic/missing_sched.h new file mode 100644 index 00000000..baa39132 --- /dev/null +++ b/src/basic/missing_sched.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#ifndef CLONE_NEWCGROUP +#define CLONE_NEWCGROUP 0x02000000 +#endif + +/* Not exposed yet. Defined at include/linux/sched.h */ +#ifndef PF_KTHREAD +#define PF_KTHREAD 0x00200000 +#endif + +/* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of the same + * name, which we need in userspace at various places but is not defined in userspace currently, neither under this + * name nor any other. */ +/* Not exposed yet. Defined at include/linux/sched.h */ +#ifndef TASK_COMM_LEN +#define TASK_COMM_LEN 16 +#endif diff --git a/src/basic/missing_securebits.h b/src/basic/missing_securebits.h new file mode 100644 index 00000000..40d6ec9d --- /dev/null +++ b/src/basic/missing_securebits.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +/* 746bf6d64275be0c65b0631d8a72b16f1454cfa1 (4.3) */ +#ifndef SECURE_NO_CAP_AMBIENT_RAISE +#define SECURE_NO_CAP_AMBIENT_RAISE 6 +#define SECURE_NO_CAP_AMBIENT_RAISE_LOCKED 7 /* make bit-6 immutable */ +#define SECBIT_NO_CAP_AMBIENT_RAISE (issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE)) +#define SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED (issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE_LOCKED)) + +#undef SECURE_ALL_BITS +#define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \ + issecure_mask(SECURE_NO_SETUID_FIXUP) | \ + issecure_mask(SECURE_KEEP_CAPS) | \ + issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE)) +#endif diff --git a/src/basic/missing_socket.h b/src/basic/missing_socket.h new file mode 100644 index 00000000..276be366 --- /dev/null +++ b/src/basic/missing_socket.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#if HAVE_LINUX_VM_SOCKETS_H +#include +#else +#define VMADDR_CID_ANY -1U +struct sockaddr_vm { + unsigned short svm_family; + unsigned short svm_reserved1; + unsigned int svm_port; + unsigned int svm_cid; + unsigned char svm_zero[sizeof(struct sockaddr) - + sizeof(unsigned short) - + sizeof(unsigned short) - + sizeof(unsigned int) - + sizeof(unsigned int)]; +}; +#endif /* !HAVE_LINUX_VM_SOCKETS_H */ + +#ifndef AF_VSOCK +#define AF_VSOCK 40 +#endif + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + +#ifndef SO_PEERGROUPS +#define SO_PEERGROUPS 59 +#endif + +#ifndef SO_BINDTOIFINDEX +#define SO_BINDTOIFINDEX 62 +#endif + +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +#ifndef SOL_ALG +#define SOL_ALG 279 +#endif + +/* Not exposed yet. Defined in include/linux/socket.h. */ +#ifndef SOL_SCTP +#define SOL_SCTP 132 +#endif + +/* Not exposed yet. Defined in include/linux/socket.h */ +#ifndef SCM_SECURITY +#define SCM_SECURITY 0x03 +#endif + +/* netinet/in.h */ +#ifndef IP_FREEBIND +#define IP_FREEBIND 15 +#endif + +#ifndef IP_TRANSPARENT +#define IP_TRANSPARENT 19 +#endif diff --git a/src/basic/missing_stat.h b/src/basic/missing_stat.h new file mode 100644 index 00000000..5116206a --- /dev/null +++ b/src/basic/missing_stat.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#if WANT_LINUX_STAT_H +#include +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#if !HAVE_STRUCT_STATX +struct statx_timestamp { + __s64 tv_sec; + __u32 tv_nsec; + __s32 __reserved; +}; +struct statx { + __u32 stx_mask; + __u32 stx_blksize; + __u64 stx_attributes; + __u32 stx_nlink; + __u32 stx_uid; + __u32 stx_gid; + __u16 stx_mode; + __u16 __spare0[1]; + __u64 stx_ino; + __u64 stx_size; + __u64 stx_blocks; + __u64 stx_attributes_mask; + struct statx_timestamp stx_atime; + struct statx_timestamp stx_btime; + struct statx_timestamp stx_ctime; + struct statx_timestamp stx_mtime; + __u32 stx_rdev_major; + __u32 stx_rdev_minor; + __u32 stx_dev_major; + __u32 stx_dev_minor; + __u64 __spare2[14]; +}; +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef STATX_BTIME +#define STATX_BTIME 0x00000800U +#endif + +/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */ +#ifndef AT_STATX_DONT_SYNC +#define AT_STATX_DONT_SYNC 0x4000 +#endif diff --git a/src/basic/missing_stdlib.h b/src/basic/missing_stdlib.h new file mode 100644 index 00000000..188a8d44 --- /dev/null +++ b/src/basic/missing_stdlib.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +/* stdlib.h */ +#if !HAVE_SECURE_GETENV +# if HAVE___SECURE_GETENV +# define secure_getenv __secure_getenv +# else +# error "neither secure_getenv nor __secure_getenv are available" +# endif +#endif diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h new file mode 100644 index 00000000..8879422c --- /dev/null +++ b/src/basic/missing_syscall.h @@ -0,0 +1,526 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/* Missing glibc definitions to access certain kernel APIs */ + +#include +#include +#include +#include +#include + +#ifdef ARCH_MIPS +#include +#endif + +#include "missing_keyctl.h" +#include "missing_stat.h" + +/* linux/kcmp.h */ +#ifndef KCMP_FILE /* 3f4994cfc15f38a3159c6e3a4b3ab2e1481a6b02 (3.19) */ +#define KCMP_FILE 0 +#endif + +#if !HAVE_PIVOT_ROOT +static inline int missing_pivot_root(const char *new_root, const char *put_old) { + return syscall(__NR_pivot_root, new_root, put_old); +} + +# define pivot_root missing_pivot_root +#endif + +/* ======================================================================= */ + +#if !HAVE_MEMFD_CREATE +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +# if ! (defined __NR_memfd_create && __NR_memfd_create >= 0) +# if defined __NR_memfd_create +# undef __NR_memfd_create +# endif +# if defined __x86_64__ +# define __NR_memfd_create 319 +# elif defined __arm__ +# define __NR_memfd_create 385 +# elif defined __aarch64__ +# define __NR_memfd_create 279 +# elif defined __s390__ +# define __NR_memfd_create 350 +# elif defined _MIPS_SIM +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define __NR_memfd_create 4354 +# endif +# if _MIPS_SIM == _MIPS_SIM_NABI32 +# define __NR_memfd_create 6318 +# endif +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define __NR_memfd_create 5314 +# endif +# elif defined __i386__ +# define __NR_memfd_create 356 +# elif defined __arc__ +# define __NR_memfd_create 279 +# else +# warning "__NR_memfd_create unknown for your architecture" +# endif +# endif + +static inline int missing_memfd_create(const char *name, unsigned int flags) { +# ifdef __NR_memfd_create + return syscall(__NR_memfd_create, name, flags); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define memfd_create missing_memfd_create +#endif + +/* ======================================================================= */ + +#if !HAVE_GETRANDOM +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +# if ! (defined __NR_getrandom && __NR_getrandom >= 0) +# if defined __NR_getrandom +# undef __NR_getrandom +# endif +# if defined __x86_64__ +# define __NR_getrandom 318 +# elif defined(__i386__) +# define __NR_getrandom 355 +# elif defined(__arm__) +# define __NR_getrandom 384 +# elif defined(__aarch64__) +# define __NR_getrandom 278 +# elif defined(__ia64__) +# define __NR_getrandom 1339 +# elif defined(__m68k__) +# define __NR_getrandom 352 +# elif defined(__s390x__) +# define __NR_getrandom 349 +# elif defined(__powerpc__) +# define __NR_getrandom 359 +# elif defined _MIPS_SIM +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define __NR_getrandom 4353 +# endif +# if _MIPS_SIM == _MIPS_SIM_NABI32 +# define __NR_getrandom 6317 +# endif +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define __NR_getrandom 5313 +# endif +# elif defined(__arc__) +# define __NR_getrandom 278 +# else +# warning "__NR_getrandom unknown for your architecture" +# endif +# endif + +static inline int missing_getrandom(void *buffer, size_t count, unsigned flags) { +# ifdef __NR_getrandom + return syscall(__NR_getrandom, buffer, count, flags); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define getrandom missing_getrandom +#endif + +/* ======================================================================= */ + +#if !HAVE_GETTID +static inline pid_t missing_gettid(void) { + return (pid_t) syscall(__NR_gettid); +} + +# define gettid missing_gettid +#endif + +/* ======================================================================= */ + +#if !HAVE_NAME_TO_HANDLE_AT +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +# if ! (defined __NR_name_to_handle_at && __NR_name_to_handle_at >= 0) +# if defined __NR_name_to_handle_at +# undef __NR_name_to_handle_at +# endif +# if defined(__x86_64__) +# define __NR_name_to_handle_at 303 +# elif defined(__i386__) +# define __NR_name_to_handle_at 341 +# elif defined(__arm__) +# define __NR_name_to_handle_at 370 +# elif defined(__powerpc__) +# define __NR_name_to_handle_at 345 +# elif defined(__arc__) +# define __NR_name_to_handle_at 264 +# else +# error "__NR_name_to_handle_at is not defined" +# endif +# endif + +struct file_handle { + unsigned int handle_bytes; + int handle_type; + unsigned char f_handle[0]; +}; + +static inline int missing_name_to_handle_at(int fd, const char *name, struct file_handle *handle, int *mnt_id, int flags) { +# ifdef __NR_name_to_handle_at + return syscall(__NR_name_to_handle_at, fd, name, handle, mnt_id, flags); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define name_to_handle_at missing_name_to_handle_at +#endif + +/* ======================================================================= */ + +#if !HAVE_SETNS +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +# if ! (defined __NR_setns && __NR_setns >= 0) +# if defined __NR_setns +# undef __NR_setns +# endif +# if defined(__x86_64__) +# define __NR_setns 308 +# elif defined(__i386__) +# define __NR_setns 346 +# elif defined(__arc__) +# define __NR_setns 268 +# else +# error "__NR_setns is not defined" +# endif +# endif + +static inline int missing_setns(int fd, int nstype) { +# ifdef __NR_setns + return syscall(__NR_setns, fd, nstype); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define setns missing_setns +#endif + +/* ======================================================================= */ + +static inline pid_t raw_getpid(void) { +#if defined(__alpha__) + return (pid_t) syscall(__NR_getxpid); +#else + return (pid_t) syscall(__NR_getpid); +#endif +} + +/* ======================================================================= */ + +#if !HAVE_RENAMEAT2 +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +# if ! (defined __NR_renameat2 && __NR_renameat2 >= 0) +# if defined __NR_renameat2 +# undef __NR_renameat2 +# endif +# if defined __x86_64__ +# define __NR_renameat2 316 +# elif defined __arm__ +# define __NR_renameat2 382 +# elif defined __aarch64__ +# define __NR_renameat2 276 +# elif defined _MIPS_SIM +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define __NR_renameat2 4351 +# endif +# if _MIPS_SIM == _MIPS_SIM_NABI32 +# define __NR_renameat2 6315 +# endif +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define __NR_renameat2 5311 +# endif +# elif defined __i386__ +# define __NR_renameat2 353 +# elif defined __powerpc64__ +# define __NR_renameat2 357 +# elif defined __s390__ || defined __s390x__ +# define __NR_renameat2 347 +# elif defined __arc__ +# define __NR_renameat2 276 +# else +# warning "__NR_renameat2 unknown for your architecture" +# endif +# endif + +static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, const char *newname, unsigned flags) { +# ifdef __NR_renameat2 + return syscall(__NR_renameat2, oldfd, oldname, newfd, newname, flags); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define renameat2 missing_renameat2 +#endif + +/* ======================================================================= */ + +#if !HAVE_KCMP +static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) { +# if defined __NR_kcmp && __NR_kcmp >= 0 + return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define kcmp missing_kcmp +#endif + +/* ======================================================================= */ + +#if !HAVE_KEYCTL +static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { +# if defined __NR_keyctl && __NR_keyctl >= 0 + return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); +# else + errno = ENOSYS; + return -1; +# endif + +# define keyctl missing_keyctl +} + +static inline key_serial_t missing_add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) { +# if defined __NR_add_key && __NR_add_key >= 0 + return syscall(__NR_add_key, type, description, payload, plen, ringid); +# else + errno = ENOSYS; + return -1; +# endif + +# define add_key missing_add_key +} + +static inline key_serial_t missing_request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) { +# if defined __NR_request_key && __NR_request_key >= 0 + return syscall(__NR_request_key, type, description, callout_info, destringid); +# else + errno = ENOSYS; + return -1; +# endif + +# define request_key missing_request_key +} +#endif + +/* ======================================================================= */ + +#if !HAVE_COPY_FILE_RANGE +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +# if ! (defined __NR_copy_file_range && __NR_copy_file_range >= 0) +# if defined __NR_copy_file_range +# undef __NR_copy_file_range +# endif +# if defined(__x86_64__) +# define __NR_copy_file_range 326 +# elif defined(__i386__) +# define __NR_copy_file_range 377 +# elif defined __s390__ +# define __NR_copy_file_range 375 +# elif defined __arm__ +# define __NR_copy_file_range 391 +# elif defined __aarch64__ +# define __NR_copy_file_range 285 +# elif defined __powerpc__ +# define __NR_copy_file_range 379 +# elif defined __arc__ +# define __NR_copy_file_range 285 +# else +# warning "__NR_copy_file_range not defined for your architecture" +# endif +# endif + +static inline ssize_t missing_copy_file_range(int fd_in, loff_t *off_in, + int fd_out, loff_t *off_out, + size_t len, + unsigned int flags) { +# ifdef __NR_copy_file_range + return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define copy_file_range missing_copy_file_range +#endif + +/* ======================================================================= */ + +#if !HAVE_BPF +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +# if ! (defined __NR_bpf && __NR_bpf >= 0) +# if defined __NR_bpf +# undef __NR_bpf +# endif +# if defined __i386__ +# define __NR_bpf 357 +# elif defined __x86_64__ +# define __NR_bpf 321 +# elif defined __aarch64__ +# define __NR_bpf 280 +# elif defined __arm__ +# define __NR_bpf 386 +# elif defined __sparc__ +# define __NR_bpf 349 +# elif defined __s390__ +# define __NR_bpf 351 +# elif defined __tilegx__ +# define __NR_bpf 280 +# else +# warning "__NR_bpf not defined for your architecture" +# endif +# endif + +union bpf_attr; + +static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) { +#ifdef __NR_bpf + return (int) syscall(__NR_bpf, cmd, attr, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +# define bpf missing_bpf +#endif + +/* ======================================================================= */ + +#ifndef __IGNORE_pkey_mprotect +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +# if ! (defined __NR_pkey_mprotect && __NR_pkey_mprotect >= 0) +# if defined __NR_pkey_mprotect +# undef __NR_pkey_mprotect +# endif +# if defined __i386__ +# define __NR_pkey_mprotect 380 +# elif defined __x86_64__ +# define __NR_pkey_mprotect 329 +# elif defined __arm__ +# define __NR_pkey_mprotect 394 +# elif defined __aarch64__ +# define __NR_pkey_mprotect 394 +# elif defined __powerpc__ +# define __NR_pkey_mprotect 386 +# elif defined __s390__ +# define __NR_pkey_mprotect 384 +# elif defined _MIPS_SIM +# if _MIPS_SIM == _MIPS_SIM_ABI32 +# define __NR_pkey_mprotect 4363 +# endif +# if _MIPS_SIM == _MIPS_SIM_NABI32 +# define __NR_pkey_mprotect 6327 +# endif +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define __NR_pkey_mprotect 5323 +# endif +# else +# warning "__NR_pkey_mprotect not defined for your architecture" +# endif +# endif +#endif + +/* ======================================================================= */ + +#if !HAVE_STATX +/* may be (invalid) negative number due to libseccomp, see PR 13319 */ +# if ! (defined __NR_statx && __NR_statx >= 0) +# if defined __NR_statx +# undef __NR_statx +# endif +# if defined __aarch64__ || defined __arm__ +# define __NR_statx 397 +# elif defined __alpha__ +# define __NR_statx 522 +# elif defined __i386__ || defined __powerpc64__ +# define __NR_statx 383 +# elif defined __sparc__ +# define __NR_statx 360 +# elif defined __x86_64__ +# define __NR_statx 332 +# else +# warning "__NR_statx not defined for your architecture" +# endif +# endif + +struct statx; +#endif + +/* This typedef is supposed to be always defined. */ +typedef struct statx struct_statx; + +#if !HAVE_STATX +static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) { +# ifdef __NR_statx + return syscall(__NR_statx, dfd, filename, flags, mask, buffer); +# else + errno = ENOSYS; + return -1; +# endif +} + +# define statx missing_statx +#endif + +#if !HAVE_SET_MEMPOLICY + +enum { + MPOL_DEFAULT, + MPOL_PREFERRED, + MPOL_BIND, + MPOL_INTERLEAVE, + MPOL_LOCAL, +}; + +static inline long missing_set_mempolicy(int mode, const unsigned long *nodemask, + unsigned long maxnode) { + long i; +# if defined __NR_set_mempolicy && __NR_set_mempolicy >= 0 + i = syscall(__NR_set_mempolicy, mode, nodemask, maxnode); +# else + errno = ENOSYS; + i = -1; +# endif + return i; +} + +# define set_mempolicy missing_set_mempolicy +#endif + +#if !HAVE_GET_MEMPOLICY +static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask, + unsigned long maxnode, void *addr, + unsigned long flags) { + long i; +# ifdef __NR_get_mempolicy + i = syscall(__NR_get_mempolicy, mode, nodemask, maxnode, addr, flags); +# else + errno = ENOSYS; + i = -1; +# endif + return i; +} + +#define get_mempolicy missing_get_mempolicy +#endif diff --git a/src/basic/missing_timerfd.h b/src/basic/missing_timerfd.h new file mode 100644 index 00000000..6b040445 --- /dev/null +++ b/src/basic/missing_timerfd.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#ifndef TFD_TIMER_CANCEL_ON_SET +#define TFD_TIMER_CANCEL_ON_SET (1 << 1) +#endif diff --git a/src/basic/missing_type.h b/src/basic/missing_type.h new file mode 100644 index 00000000..bf8a6caa --- /dev/null +++ b/src/basic/missing_type.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#if !HAVE_CHAR32_T +#define char32_t uint32_t +#endif + +#if !HAVE_CHAR16_T +#define char16_t uint16_t +#endif diff --git a/src/basic/mkdir-label.c b/src/basic/mkdir-label.c new file mode 100644 index 00000000..0eba7fc5 --- /dev/null +++ b/src/basic/mkdir-label.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "label.h" +#include "macro.h" +#include "mkdir.h" +#include "selinux-util.h" +#include "smack-util.h" + +int mkdir_label(const char *path, mode_t mode) { + int r; + + assert(path); + + r = mac_selinux_create_file_prepare(path, S_IFDIR); + if (r < 0) + return r; + + r = mkdir_errno_wrapper(path, mode); + mac_selinux_create_file_clear(); + if (r < 0) + return r; + + return mac_smack_fix(path, 0); +} + +int mkdirat_label(int dirfd, const char *path, mode_t mode) { + int r; + + assert(path); + + r = mac_selinux_create_file_prepare_at(dirfd, path, S_IFDIR); + if (r < 0) + return r; + + r = mkdirat_errno_wrapper(dirfd, path, mode); + mac_selinux_create_file_clear(); + if (r < 0) + return r; + + return mac_smack_fix_at(dirfd, path, 0); +} + +int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) { + return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_label); +} + +int mkdir_parents_label(const char *path, mode_t mode) { + return mkdir_parents_internal(NULL, path, mode, mkdir_label); +} + +int mkdir_p_label(const char *path, mode_t mode) { + return mkdir_p_internal(NULL, path, mode, mkdir_label); +} diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c new file mode 100644 index 00000000..fa682d4c --- /dev/null +++ b/src/basic/mkdir.c @@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "macro.h" +#include "mkdir.h" +#include "path-util.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "user-util.h" + +int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir) { + struct stat st; + int r; + + assert(_mkdir != mkdir); + + if (_mkdir(path, mode) >= 0) { + r = chmod_and_chown(path, mode, uid, gid); + if (r < 0) + return r; + } + + if (lstat(path, &st) < 0) + return -errno; + + if ((flags & MKDIR_FOLLOW_SYMLINK) && S_ISLNK(st.st_mode)) { + _cleanup_free_ char *p = NULL; + + r = chase_symlinks(path, NULL, CHASE_NONEXISTENT, &p, NULL); + if (r < 0) + return r; + if (r == 0) + return mkdir_safe_internal(p, mode, uid, gid, + flags & ~MKDIR_FOLLOW_SYMLINK, + _mkdir); + + if (lstat(p, &st) < 0) + return -errno; + } + + if (!S_ISDIR(st.st_mode)) { + log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG, + "Path \"%s\" already exists and is not a directory, refusing.", path); + return -ENOTDIR; + } + if ((st.st_mode & 0007) > (mode & 0007) || + (st.st_mode & 0070) > (mode & 0070) || + (st.st_mode & 0700) > (mode & 0700)) { + log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG, + "Directory \"%s\" already exists, but has mode %04o that is too permissive (%04o was requested), refusing.", + path, st.st_mode & 0777, mode); + return -EEXIST; + } + if ((uid != UID_INVALID && st.st_uid != uid) || + (gid != GID_INVALID && st.st_gid != gid)) { + char u[DECIMAL_STR_MAX(uid_t)] = "-", g[DECIMAL_STR_MAX(gid_t)] = "-"; + + if (uid != UID_INVALID) + xsprintf(u, UID_FMT, uid); + if (gid != UID_INVALID) + xsprintf(g, GID_FMT, gid); + log_full(flags & MKDIR_WARN_MODE ? LOG_WARNING : LOG_DEBUG, + "Directory \"%s\" already exists, but is owned by "UID_FMT":"GID_FMT" (%s:%s was requested), refusing.", + path, st.st_uid, st.st_gid, u, g); + return -EEXIST; + } + + return 0; +} + +int mkdir_errno_wrapper(const char *pathname, mode_t mode) { + if (mkdir(pathname, mode) < 0) + return -errno; + return 0; +} + +int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode) { + if (mkdirat(dirfd, pathname, mode) < 0) + return -errno; + return 0; +} + +int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) { + return mkdir_safe_internal(path, mode, uid, gid, flags, mkdir_errno_wrapper); +} + +int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) { + const char *p, *e; + int r; + + assert(path); + assert(_mkdir != mkdir); + + if (prefix && !path_startswith(path, prefix)) + return -ENOTDIR; + + /* return immediately if directory exists */ + e = strrchr(path, '/'); + if (!e) + return -EINVAL; + + if (e == path) + return 0; + + p = strndupa(path, e - path); + r = is_dir(p, true); + if (r > 0) + return 0; + if (r == 0) + return -ENOTDIR; + + /* create every parent directory in the path, except the last component */ + p = path + strspn(path, "/"); + for (;;) { + char t[strlen(path) + 1]; + + e = p + strcspn(p, "/"); + p = e + strspn(e, "/"); + + /* Is this the last component? If so, then we're done */ + if (*p == 0) + return 0; + + memcpy(t, path, e - path); + t[e-path] = 0; + + if (prefix && path_startswith(prefix, t)) + continue; + + r = _mkdir(t, mode); + if (r < 0 && r != -EEXIST) + return r; + } +} + +int mkdir_parents(const char *path, mode_t mode) { + return mkdir_parents_internal(NULL, path, mode, mkdir_errno_wrapper); +} + +int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir) { + int r; + + /* Like mkdir -p */ + + assert(_mkdir != mkdir); + + r = mkdir_parents_internal(prefix, path, mode, _mkdir); + if (r < 0) + return r; + + r = _mkdir(path, mode); + if (r < 0 && (r != -EEXIST || is_dir(path, true) <= 0)) + return r; + + return 0; +} + +int mkdir_p(const char *path, mode_t mode) { + return mkdir_p_internal(NULL, path, mode, mkdir_errno_wrapper); +} diff --git a/src/basic/mkdir.h b/src/basic/mkdir.h new file mode 100644 index 00000000..eb54853e --- /dev/null +++ b/src/basic/mkdir.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +typedef enum MkdirFlags { + MKDIR_FOLLOW_SYMLINK = 1 << 0, + MKDIR_WARN_MODE = 1 << 1, +} MkdirFlags; + +int mkdir_errno_wrapper(const char *pathname, mode_t mode); +int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode); +int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); +int mkdir_parents(const char *path, mode_t mode); +int mkdir_p(const char *path, mode_t mode); + +/* mandatory access control(MAC) versions */ +int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags); +int mkdir_parents_label(const char *path, mode_t mode); +int mkdir_p_label(const char *path, mode_t mode); + +/* internally used */ +typedef int (*mkdir_func_t)(const char *pathname, mode_t mode); +int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdir_func_t _mkdir); +int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir); +int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, mkdir_func_t _mkdir); diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c new file mode 100644 index 00000000..1d8147b2 --- /dev/null +++ b/src/basic/mountpoint-util.c @@ -0,0 +1,443 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "mountpoint-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "stdio-util.h" +#include "strv.h" + +/* This is the original MAX_HANDLE_SZ definition from the kernel, when the API was introduced. We use that in place of + * any more currently defined value to future-proof things: if the size is increased in the API headers, and our code + * is recompiled then it would cease working on old kernels, as those refuse any sizes larger than this value with + * EINVAL right-away. Hence, let's disconnect ourselves from any such API changes, and stick to the original definition + * from when it was introduced. We use it as a start value only anyway (see below), and hence should be able to deal + * with large file handles anyway. */ +#define ORIGINAL_MAX_HANDLE_SZ 128 + +int name_to_handle_at_loop( + int fd, + const char *path, + struct file_handle **ret_handle, + int *ret_mnt_id, + int flags) { + + _cleanup_free_ struct file_handle *h = NULL; + size_t n = ORIGINAL_MAX_HANDLE_SZ; + + /* We need to invoke name_to_handle_at() in a loop, given that it might return EOVERFLOW when the specified + * buffer is too small. Note that in contrast to what the docs might suggest, MAX_HANDLE_SZ is only good as a + * start value, it is not an upper bound on the buffer size required. + * + * This improves on raw name_to_handle_at() also in one other regard: ret_handle and ret_mnt_id can be passed + * as NULL if there's no interest in either. */ + + for (;;) { + int mnt_id = -1; + + h = malloc0(offsetof(struct file_handle, f_handle) + n); + if (!h) + return -ENOMEM; + + h->handle_bytes = n; + + if (name_to_handle_at(fd, path, h, &mnt_id, flags) >= 0) { + + if (ret_handle) + *ret_handle = TAKE_PTR(h); + + if (ret_mnt_id) + *ret_mnt_id = mnt_id; + + return 0; + } + if (errno != EOVERFLOW) + return -errno; + + if (!ret_handle && ret_mnt_id && mnt_id >= 0) { + + /* As it appears, name_to_handle_at() fills in mnt_id even when it returns EOVERFLOW when the + * buffer is too small, but that's undocumented. Hence, let's make use of this if it appears to + * be filled in, and the caller was interested in only the mount ID an nothing else. */ + + *ret_mnt_id = mnt_id; + return 0; + } + + /* If name_to_handle_at() didn't increase the byte size, then this EOVERFLOW is caused by something + * else (apparently EOVERFLOW is returned for untriggered nfs4 mounts sometimes), not by the too small + * buffer. In that case propagate EOVERFLOW */ + if (h->handle_bytes <= n) + return -EOVERFLOW; + + /* The buffer was too small. Size the new buffer by what name_to_handle_at() returned. */ + n = h->handle_bytes; + if (offsetof(struct file_handle, f_handle) + n < n) /* check for addition overflow */ + return -EOVERFLOW; + + h = mfree(h); + } +} + +static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id) { + char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)]; + _cleanup_free_ char *fdinfo = NULL; + _cleanup_close_ int subfd = -1; + char *p; + int r; + + if ((flags & AT_EMPTY_PATH) && isempty(filename)) + xsprintf(path, "/proc/self/fdinfo/%i", fd); + else { + subfd = openat(fd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_FOLLOW ? 0 : O_NOFOLLOW)); + if (subfd < 0) + return -errno; + + xsprintf(path, "/proc/self/fdinfo/%i", subfd); + } + + r = read_full_file(path, &fdinfo, NULL); + if (r == -ENOENT) /* The fdinfo directory is a relatively new addition */ + return -EOPNOTSUPP; + if (r < 0) + return r; + + p = startswith(fdinfo, "mnt_id:"); + if (!p) { + p = strstr(fdinfo, "\nmnt_id:"); + if (!p) /* The mnt_id field is a relatively new addition */ + return -EOPNOTSUPP; + + p += 8; + } + + p += strspn(p, WHITESPACE); + p[strcspn(p, WHITESPACE)] = 0; + + return safe_atoi(p, mnt_id); +} + +int fd_is_mount_point(int fd, const char *filename, int flags) { + _cleanup_free_ struct file_handle *h = NULL, *h_parent = NULL; + int mount_id = -1, mount_id_parent = -1; + bool nosupp = false, check_st_dev = true; + struct stat a, b; + int r; + + assert(fd >= 0); + assert(filename); + + /* First we will try the name_to_handle_at() syscall, which + * tells us the mount id and an opaque file "handle". It is + * not supported everywhere though (kernel compile-time + * option, not all file systems are hooked up). If it works + * the mount id is usually good enough to tell us whether + * something is a mount point. + * + * If that didn't work we will try to read the mount id from + * /proc/self/fdinfo/. This is almost as good as + * name_to_handle_at(), however, does not return the + * opaque file handle. The opaque file handle is pretty useful + * to detect the root directory, which we should always + * consider a mount point. Hence we use this only as + * fallback. Exporting the mnt_id in fdinfo is a pretty recent + * kernel addition. + * + * As last fallback we do traditional fstat() based st_dev + * comparisons. This is how things were traditionally done, + * but unionfs breaks this since it exposes file + * systems with a variety of st_dev reported. Also, btrfs + * subvolumes have different st_dev, even though they aren't + * real mounts of their own. */ + + r = name_to_handle_at_loop(fd, filename, &h, &mount_id, flags); + if (IN_SET(r, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) + /* This kernel does not support name_to_handle_at() at all (ENOSYS), or the syscall was blocked + * (EACCES/EPERM; maybe through seccomp, because we are running inside of a container?), or the mount + * point is not triggered yet (EOVERFLOW, think nfs4), or some general name_to_handle_at() flakiness + * (EINVAL): fall back to simpler logic. */ + goto fallback_fdinfo; + else if (r == -EOPNOTSUPP) + /* This kernel or file system does not support name_to_handle_at(), hence let's see if the upper fs + * supports it (in which case it is a mount point), otherwise fallback to the traditional stat() + * logic */ + nosupp = true; + else if (r < 0) + return r; + + r = name_to_handle_at_loop(fd, "", &h_parent, &mount_id_parent, AT_EMPTY_PATH); + if (r == -EOPNOTSUPP) { + if (nosupp) + /* Neither parent nor child do name_to_handle_at()? We have no choice but to fall back. */ + goto fallback_fdinfo; + else + /* The parent can't do name_to_handle_at() but the directory we are interested in can? If so, + * it must be a mount point. */ + return 1; + } else if (r < 0) + return r; + + /* The parent can do name_to_handle_at() but the + * directory we are interested in can't? If so, it + * must be a mount point. */ + if (nosupp) + return 1; + + /* If the file handle for the directory we are + * interested in and its parent are identical, we + * assume this is the root directory, which is a mount + * point. */ + + if (h->handle_bytes == h_parent->handle_bytes && + h->handle_type == h_parent->handle_type && + memcmp(h->f_handle, h_parent->f_handle, h->handle_bytes) == 0) + return 1; + + return mount_id != mount_id_parent; + +fallback_fdinfo: + r = fd_fdinfo_mnt_id(fd, filename, flags, &mount_id); + if (IN_SET(r, -EOPNOTSUPP, -EACCES, -EPERM)) + goto fallback_fstat; + if (r < 0) + return r; + + r = fd_fdinfo_mnt_id(fd, "", AT_EMPTY_PATH, &mount_id_parent); + if (r < 0) + return r; + + if (mount_id != mount_id_parent) + return 1; + + /* Hmm, so, the mount ids are the same. This leaves one + * special case though for the root file system. For that, + * let's see if the parent directory has the same inode as we + * are interested in. Hence, let's also do fstat() checks now, + * too, but avoid the st_dev comparisons, since they aren't + * that useful on unionfs mounts. */ + check_st_dev = false; + +fallback_fstat: + /* yay for fstatat() taking a different set of flags than the other + * _at() above */ + if (flags & AT_SYMLINK_FOLLOW) + flags &= ~AT_SYMLINK_FOLLOW; + else + flags |= AT_SYMLINK_NOFOLLOW; + if (fstatat(fd, filename, &a, flags) < 0) + return -errno; + + if (fstatat(fd, "", &b, AT_EMPTY_PATH) < 0) + return -errno; + + /* A directory with same device and inode as its parent? Must + * be the root directory */ + if (a.st_dev == b.st_dev && + a.st_ino == b.st_ino) + return 1; + + return check_st_dev && (a.st_dev != b.st_dev); +} + +/* flags can be AT_SYMLINK_FOLLOW or 0 */ +int path_is_mount_point(const char *t, const char *root, int flags) { + _cleanup_free_ char *canonical = NULL; + _cleanup_close_ int fd = -1; + int r; + + assert(t); + assert((flags & ~AT_SYMLINK_FOLLOW) == 0); + + if (path_equal(t, "/")) + return 1; + + /* we need to resolve symlinks manually, we can't just rely on + * fd_is_mount_point() to do that for us; if we have a structure like + * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we + * look at needs to be /usr, not /. */ + if (flags & AT_SYMLINK_FOLLOW) { + r = chase_symlinks(t, root, CHASE_TRAIL_SLASH, &canonical, NULL); + if (r < 0) + return r; + + t = canonical; + } + + fd = open_parent(t, O_PATH|O_CLOEXEC, 0); + if (fd < 0) + return -errno; + + return fd_is_mount_point(fd, last_path_component(t), flags); +} + +int path_get_mnt_id(const char *path, int *ret) { + int r; + + r = name_to_handle_at_loop(AT_FDCWD, path, NULL, ret, 0); + if (IN_SET(r, -EOPNOTSUPP, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) /* kernel/fs don't support this, or seccomp blocks access, or untriggered mount, or name_to_handle_at() is flaky */ + return fd_fdinfo_mnt_id(AT_FDCWD, path, 0, ret); + + return r; +} + +bool fstype_is_network(const char *fstype) { + const char *x; + + x = startswith(fstype, "fuse."); + if (x) + fstype = x; + + return STR_IN_SET(fstype, + "afs", + "ceph", + "cifs", + "smb3", + "smbfs", + "sshfs", + "ncpfs", + "ncp", + "nfs", + "nfs4", + "gfs", + "gfs2", + "glusterfs", + "pvfs2", /* OrangeFS */ + "ocfs2", + "lustre"); +} + +bool fstype_is_api_vfs(const char *fstype) { + return STR_IN_SET(fstype, + "autofs", + "bpf", + "cgroup", + "cgroup2", + "configfs", + "cpuset", + "debugfs", + "devpts", + "devtmpfs", + "efivarfs", + "fusectl", + "hugetlbfs", + "mqueue", + "proc", + "pstore", + "ramfs", + "securityfs", + "sysfs", + "tmpfs", + "tracefs"); +} + +bool fstype_is_ro(const char *fstype) { + /* All Linux file systems that are necessarily read-only */ + return STR_IN_SET(fstype, + "DM_verity_hash", + "iso9660", + "squashfs"); +} + +bool fstype_can_discard(const char *fstype) { + return STR_IN_SET(fstype, + "btrfs", + "ext4", + "vfat", + "xfs"); +} + +bool fstype_can_uid_gid(const char *fstype) { + + /* All file systems that have a uid=/gid= mount option that fixates the owners of all files and directories, + * current and future. */ + + return STR_IN_SET(fstype, + "adfs", + "exfat", + "fat", + "hfs", + "hpfs", + "iso9660", + "msdos", + "ntfs", + "vfat"); +} + +int dev_is_devtmpfs(void) { + _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; + int mount_id, r; + char *e; + + r = path_get_mnt_id("/dev", &mount_id); + if (r < 0) + return r; + + r = fopen_unlocked("/proc/self/mountinfo", "re", &proc_self_mountinfo); + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *line = NULL; + int mid; + + r = read_line(proc_self_mountinfo, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + if (sscanf(line, "%i", &mid) != 1) + continue; + + if (mid != mount_id) + continue; + + e = strstr(line, " - "); + if (!e) + continue; + + /* accept any name that starts with the currently expected type */ + if (startswith(e + 3, "devtmpfs")) + return true; + } + + return false; +} + +const char *mount_propagation_flags_to_string(unsigned long flags) { + + switch (flags & (MS_SHARED|MS_SLAVE|MS_PRIVATE)) { + case 0: + return ""; + case MS_SHARED: + return "shared"; + case MS_SLAVE: + return "slave"; + case MS_PRIVATE: + return "private"; + } + + return NULL; +} + +int mount_propagation_flags_from_string(const char *name, unsigned long *ret) { + + if (isempty(name)) + *ret = 0; + else if (streq(name, "shared")) + *ret = MS_SHARED; + else if (streq(name, "slave")) + *ret = MS_SLAVE; + else if (streq(name, "private")) + *ret = MS_PRIVATE; + else + return -EINVAL; + return 0; +} diff --git a/src/basic/mountpoint-util.h b/src/basic/mountpoint-util.h new file mode 100644 index 00000000..5398836f --- /dev/null +++ b/src/basic/mountpoint-util.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +int name_to_handle_at_loop(int fd, const char *path, struct file_handle **ret_handle, int *ret_mnt_id, int flags); + +int path_get_mnt_id(const char *path, int *ret); + +int fd_is_mount_point(int fd, const char *filename, int flags); +int path_is_mount_point(const char *path, const char *root, int flags); + +bool fstype_is_network(const char *fstype); +bool fstype_is_api_vfs(const char *fstype); +bool fstype_is_ro(const char *fsype); +bool fstype_can_discard(const char *fstype); +bool fstype_can_uid_gid(const char *fstype); + +int dev_is_devtmpfs(void); + +const char *mount_propagation_flags_to_string(unsigned long flags); +int mount_propagation_flags_from_string(const char *name, unsigned long *ret); diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c new file mode 100644 index 00000000..b0168ae2 --- /dev/null +++ b/src/basic/namespace-util.c @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "fd-util.h" +#include "missing_fs.h" +#include "missing_magic.h" +#include "namespace-util.h" +#include "process-util.h" +#include "stat-util.h" +#include "user-util.h" + +int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) { + _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1; + int rfd = -1; + + assert(pid >= 0); + + if (mntns_fd) { + const char *mntns; + + mntns = procfs_file_alloca(pid, "ns/mnt"); + mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (mntnsfd < 0) + return -errno; + } + + if (pidns_fd) { + const char *pidns; + + pidns = procfs_file_alloca(pid, "ns/pid"); + pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (pidnsfd < 0) + return -errno; + } + + if (netns_fd) { + const char *netns; + + netns = procfs_file_alloca(pid, "ns/net"); + netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (netnsfd < 0) + return -errno; + } + + if (userns_fd) { + const char *userns; + + userns = procfs_file_alloca(pid, "ns/user"); + usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (usernsfd < 0 && errno != ENOENT) + return -errno; + } + + if (root_fd) { + const char *root; + + root = procfs_file_alloca(pid, "root"); + rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (rfd < 0) + return -errno; + } + + if (pidns_fd) + *pidns_fd = TAKE_FD(pidnsfd); + + if (mntns_fd) + *mntns_fd = TAKE_FD(mntnsfd); + + if (netns_fd) + *netns_fd = TAKE_FD(netnsfd); + + if (userns_fd) + *userns_fd = TAKE_FD(usernsfd); + + if (root_fd) + *root_fd = TAKE_FD(rfd); + + return 0; +} + +int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) { + if (userns_fd >= 0) { + /* Can't setns to your own userns, since then you could + * escalate from non-root to root in your own namespace, so + * check if namespaces equal before attempting to enter. */ + _cleanup_free_ char *userns_fd_path = NULL; + int r; + if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0) + return -ENOMEM; + + r = files_same(userns_fd_path, "/proc/self/ns/user", 0); + if (r < 0) + return r; + if (r) + userns_fd = -1; + } + + if (pidns_fd >= 0) + if (setns(pidns_fd, CLONE_NEWPID) < 0) + return -errno; + + if (mntns_fd >= 0) + if (setns(mntns_fd, CLONE_NEWNS) < 0) + return -errno; + + if (netns_fd >= 0) + if (setns(netns_fd, CLONE_NEWNET) < 0) + return -errno; + + if (userns_fd >= 0) + if (setns(userns_fd, CLONE_NEWUSER) < 0) + return -errno; + + if (root_fd >= 0) { + if (fchdir(root_fd) < 0) + return -errno; + + if (chroot(".") < 0) + return -errno; + } + + return reset_uid_gid(); +} + +int fd_is_network_ns(int fd) { + struct statfs s; + int r; + + /* Checks whether the specified file descriptor refers to a network namespace. On old kernels there's no nice + * way to detect that, hence on those we'll return a recognizable error (EUCLEAN), so that callers can handle + * this somewhat nicely. + * + * This function returns > 0 if the fd definitely refers to a network namespace, 0 if it definitely does not + * refer to a network namespace, -EUCLEAN if we can't determine, and other negative error codes on error. */ + + if (fstatfs(fd, &s) < 0) + return -errno; + + if (!is_fs_type(&s, NSFS_MAGIC)) { + /* On really old kernels, there was no "nsfs", and network namespace sockets belonged to procfs + * instead. Handle that in a somewhat smart way. */ + + if (is_fs_type(&s, PROC_SUPER_MAGIC)) { + struct statfs t; + + /* OK, so it is procfs. Let's see if our own network namespace is procfs, too. If so, then the + * passed fd might refer to a network namespace, but we can't know for sure. In that case, + * return a recognizable error. */ + + if (statfs("/proc/self/ns/net", &t) < 0) + return -errno; + + if (s.f_type == t.f_type) + return -EUCLEAN; /* It's possible, we simply don't know */ + } + + return 0; /* No! */ + } + + r = ioctl(fd, NS_GET_NSTYPE); + if (r < 0) { + if (errno == ENOTTY) /* Old kernels didn't know this ioctl, let's also return a recognizable error in that case */ + return -EUCLEAN; + + return -errno; + } + + return r == CLONE_NEWNET; +} diff --git a/src/basic/namespace-util.h b/src/basic/namespace-util.h new file mode 100644 index 00000000..8c17ce91 --- /dev/null +++ b/src/basic/namespace-util.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd); +int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd); + +int fd_is_network_ns(int fd); diff --git a/src/basic/nss-util.h b/src/basic/nss-util.h new file mode 100644 index 00000000..2045175d --- /dev/null +++ b/src/basic/nss-util.h @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include + +#define NSS_SIGNALS_BLOCK SIGALRM,SIGVTALRM,SIGPIPE,SIGCHLD,SIGTSTP,SIGIO,SIGHUP,SIGUSR1,SIGUSR2,SIGPROF,SIGURG,SIGWINCH + +#ifndef DEPRECATED_RES_USE_INET6 +# define DEPRECATED_RES_USE_INET6 0x00002000 +#endif + +#define NSS_GETHOSTBYNAME_PROTOTYPES(module) \ +enum nss_status _nss_##module##_gethostbyname4_r( \ + const char *name, \ + struct gaih_addrtuple **pat, \ + char *buffer, size_t buflen, \ + int *errnop, int *h_errnop, \ + int32_t *ttlp) _public_; \ +enum nss_status _nss_##module##_gethostbyname3_r( \ + const char *name, \ + int af, \ + struct hostent *host, \ + char *buffer, size_t buflen, \ + int *errnop, int *h_errnop, \ + int32_t *ttlp, \ + char **canonp) _public_; \ +enum nss_status _nss_##module##_gethostbyname2_r( \ + const char *name, \ + int af, \ + struct hostent *host, \ + char *buffer, size_t buflen, \ + int *errnop, int *h_errnop) _public_; \ +enum nss_status _nss_##module##_gethostbyname_r( \ + const char *name, \ + struct hostent *host, \ + char *buffer, size_t buflen, \ + int *errnop, int *h_errnop) _public_ + +#define NSS_GETHOSTBYADDR_PROTOTYPES(module) \ +enum nss_status _nss_##module##_gethostbyaddr2_r( \ + const void* addr, socklen_t len, \ + int af, \ + struct hostent *host, \ + char *buffer, size_t buflen, \ + int *errnop, int *h_errnop, \ + int32_t *ttlp) _public_; \ +enum nss_status _nss_##module##_gethostbyaddr_r( \ + const void* addr, socklen_t len, \ + int af, \ + struct hostent *host, \ + char *buffer, size_t buflen, \ + int *errnop, int *h_errnop) _public_ + +#define NSS_GETHOSTBYNAME_FALLBACKS(module) \ +enum nss_status _nss_##module##_gethostbyname2_r( \ + const char *name, \ + int af, \ + struct hostent *host, \ + char *buffer, size_t buflen, \ + int *errnop, int *h_errnop) { \ + return _nss_##module##_gethostbyname3_r( \ + name, \ + af, \ + host, \ + buffer, buflen, \ + errnop, h_errnop, \ + NULL, \ + NULL); \ +} \ +enum nss_status _nss_##module##_gethostbyname_r( \ + const char *name, \ + struct hostent *host, \ + char *buffer, size_t buflen, \ + int *errnop, int *h_errnop) { \ + enum nss_status ret = NSS_STATUS_NOTFOUND; \ + \ + if (_res.options & DEPRECATED_RES_USE_INET6) \ + ret = _nss_##module##_gethostbyname3_r( \ + name, \ + AF_INET6, \ + host, \ + buffer, buflen, \ + errnop, h_errnop, \ + NULL, \ + NULL); \ + if (ret == NSS_STATUS_NOTFOUND) \ + ret = _nss_##module##_gethostbyname3_r( \ + name, \ + AF_INET, \ + host, \ + buffer, buflen, \ + errnop, h_errnop, \ + NULL, \ + NULL); \ + return ret; \ +} + +#define NSS_GETHOSTBYADDR_FALLBACKS(module) \ +enum nss_status _nss_##module##_gethostbyaddr_r( \ + const void* addr, socklen_t len, \ + int af, \ + struct hostent *host, \ + char *buffer, size_t buflen, \ + int *errnop, int *h_errnop) { \ + return _nss_##module##_gethostbyaddr2_r( \ + addr, len, \ + af, \ + host, \ + buffer, buflen, \ + errnop, h_errnop, \ + NULL); \ +} + +#define NSS_GETPW_PROTOTYPES(module) \ +enum nss_status _nss_##module##_getpwnam_r( \ + const char *name, \ + struct passwd *pwd, \ + char *buffer, size_t buflen, \ + int *errnop) _public_; \ +enum nss_status _nss_##module##_getpwuid_r( \ + uid_t uid, \ + struct passwd *pwd, \ + char *buffer, size_t buflen, \ + int *errnop) _public_ + +#define NSS_GETGR_PROTOTYPES(module) \ +enum nss_status _nss_##module##_getgrnam_r( \ + const char *name, \ + struct group *gr, \ + char *buffer, size_t buflen, \ + int *errnop) _public_; \ +enum nss_status _nss_##module##_getgrgid_r( \ + gid_t gid, \ + struct group *gr, \ + char *buffer, size_t buflen, \ + int *errnop) _public_ + +typedef enum nss_status (*_nss_gethostbyname4_r_t)( + const char *name, + struct gaih_addrtuple **pat, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp); + +typedef enum nss_status (*_nss_gethostbyname3_r_t)( + const char *name, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp); + +typedef enum nss_status (*_nss_gethostbyname2_r_t)( + const char *name, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop); + +typedef enum nss_status (*_nss_gethostbyname_r_t)( + const char *name, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop); + +typedef enum nss_status (*_nss_gethostbyaddr2_r_t)( + const void* addr, socklen_t len, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp); +typedef enum nss_status (*_nss_gethostbyaddr_r_t)( + const void* addr, socklen_t len, + int af, + struct hostent *host, + char *buffer, size_t buflen, + int *errnop, int *h_errnop); diff --git a/src/basic/nulstr-util.c b/src/basic/nulstr-util.c new file mode 100644 index 00000000..b12d0202 --- /dev/null +++ b/src/basic/nulstr-util.c @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "nulstr-util.h" +#include "string-util.h" + +bool nulstr_contains(const char *nulstr, const char *needle) { + const char *i; + + if (!nulstr) + return false; + + NULSTR_FOREACH(i, nulstr) + if (streq(i, needle)) + return true; + + return false; +} diff --git a/src/basic/nulstr-util.h b/src/basic/nulstr-util.h new file mode 100644 index 00000000..436b271f --- /dev/null +++ b/src/basic/nulstr-util.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#define NULSTR_FOREACH(i, l) \ + for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) + +#define NULSTR_FOREACH_PAIR(i, j, l) \ + for ((i) = (l), (j) = strchr((i), 0)+1; (i) && *(i); (i) = strchr((j), 0)+1, (j) = *(i) ? strchr((i), 0)+1 : (i)) + +bool nulstr_contains(const char *nulstr, const char *needle); diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c new file mode 100644 index 00000000..7fdb47e0 --- /dev/null +++ b/src/basic/ordered-set.c @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fileio.h" +#include "ordered-set.h" +#include "strv.h" + +int ordered_set_consume(OrderedSet *s, void *p) { + int r; + + r = ordered_set_put(s, p); + if (r <= 0) + free(p); + + return r; +} + +int ordered_set_put_strdup(OrderedSet *s, const char *p) { + char *c; + int r; + + assert(s); + assert(p); + + c = strdup(p); + if (!c) + return -ENOMEM; + + r = ordered_set_consume(s, c); + if (r == -EEXIST) + return 0; + + return r; +} + +int ordered_set_put_strdupv(OrderedSet *s, char **l) { + int n = 0, r; + char **i; + + STRV_FOREACH(i, l) { + r = ordered_set_put_strdup(s, *i); + if (r < 0) + return r; + + n += r; + } + + return n; +} + +int ordered_set_put_string_set(OrderedSet *s, OrderedSet *l) { + int n = 0, r; + Iterator i; + char *p; + + /* Like ordered_set_put_strv, but for an OrderedSet of strings */ + + ORDERED_SET_FOREACH(p, l, i) { + r = ordered_set_put_strdup(s, p); + if (r < 0) + return r; + + n += r; + } + + return n; +} + +void ordered_set_print(FILE *f, const char *field, OrderedSet *s) { + bool space = false; + Iterator i; + char *p; + + if (ordered_set_isempty(s)) + return; + + fputs(field, f); + + ORDERED_SET_FOREACH(p, s, i) + fputs_with_space(f, p, NULL, &space); + + fputc('\n', f); +} diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h new file mode 100644 index 00000000..ba43451e --- /dev/null +++ b/src/basic/ordered-set.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "hashmap.h" + +typedef struct OrderedSet OrderedSet; + +static inline OrderedSet* ordered_set_new(const struct hash_ops *ops) { + return (OrderedSet*) ordered_hashmap_new(ops); +} + +static inline int ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops) { + if (*s) + return 0; + + *s = ordered_set_new(ops); + if (!*s) + return -ENOMEM; + + return 0; +} + +static inline OrderedSet* ordered_set_free(OrderedSet *s) { + return (OrderedSet*) ordered_hashmap_free((OrderedHashmap*) s); +} + +static inline OrderedSet* ordered_set_free_free(OrderedSet *s) { + return (OrderedSet*) ordered_hashmap_free_free((OrderedHashmap*) s); +} + +static inline int ordered_set_put(OrderedSet *s, void *p) { + return ordered_hashmap_put((OrderedHashmap*) s, p, p); +} + +static inline unsigned ordered_set_size(OrderedSet *s) { + return ordered_hashmap_size((OrderedHashmap*) s); +} + +static inline bool ordered_set_isempty(OrderedSet *s) { + return ordered_hashmap_isempty((OrderedHashmap*) s); +} + +static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value) { + return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL); +} + +static inline void* ordered_set_remove(OrderedSet *s, void *p) { + return ordered_hashmap_remove((OrderedHashmap*) s, p); +} + +static inline void* ordered_set_steal_first(OrderedSet *s) { + return ordered_hashmap_steal_first((OrderedHashmap*) s); +} + +static inline char **ordered_set_get_strv(OrderedSet *s) { + return internal_hashmap_get_strv(HASHMAP_BASE((OrderedHashmap*) s)); +} + +int ordered_set_consume(OrderedSet *s, void *p); +int ordered_set_put_strdup(OrderedSet *s, const char *p); +int ordered_set_put_strdupv(OrderedSet *s, char **l); +int ordered_set_put_string_set(OrderedSet *s, OrderedSet *l); +void ordered_set_print(FILE *f, const char *field, OrderedSet *s); + +#define ORDERED_SET_FOREACH(e, s, i) \ + for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); ) + +DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free); + +#define _cleanup_ordered_set_free_ _cleanup_(ordered_set_freep) +#define _cleanup_ordered_set_free_free_ _cleanup_(ordered_set_free_freep) diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c new file mode 100644 index 00000000..aec6099c --- /dev/null +++ b/src/basic/parse-util.c @@ -0,0 +1,758 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "errno-list.h" +#include "extract-word.h" +#include "locale-util.h" +#include "macro.h" +#include "missing_network.h" +#include "parse-util.h" +#include "process-util.h" +#include "stat-util.h" +#include "string-util.h" + +int parse_boolean(const char *v) { + if (!v) + return -EINVAL; + + if (streq(v, "1") || strcaseeq(v, "yes") || strcaseeq(v, "y") || strcaseeq(v, "true") || strcaseeq(v, "t") || strcaseeq(v, "on")) + return 1; + else if (streq(v, "0") || strcaseeq(v, "no") || strcaseeq(v, "n") || strcaseeq(v, "false") || strcaseeq(v, "f") || strcaseeq(v, "off")) + return 0; + + return -EINVAL; +} + +int parse_pid(const char *s, pid_t* ret_pid) { + unsigned long ul = 0; + pid_t pid; + int r; + + assert(s); + assert(ret_pid); + + r = safe_atolu(s, &ul); + if (r < 0) + return r; + + pid = (pid_t) ul; + + if ((unsigned long) pid != ul) + return -ERANGE; + + if (!pid_is_valid(pid)) + return -ERANGE; + + *ret_pid = pid; + return 0; +} + +int parse_mode(const char *s, mode_t *ret) { + char *x; + long l; + + assert(s); + assert(ret); + + s += strspn(s, WHITESPACE); + if (s[0] == '-') + return -ERANGE; + + errno = 0; + l = strtol(s, &x, 8); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; + if (l < 0 || l > 07777) + return -ERANGE; + + *ret = (mode_t) l; + return 0; +} + +int parse_ifindex(const char *s, int *ret) { + int ifi, r; + + assert(s); + assert(ret); + + r = safe_atoi(s, &ifi); + if (r < 0) + return r; + if (ifi <= 0) + return -EINVAL; + + *ret = ifi; + return 0; +} + +int parse_ifindex_or_ifname(const char *s, int *ret) { + int r; + + assert(s); + assert(ret); + + r = parse_ifindex(s, ret); + if (r >= 0) + return r; + + r = (int) if_nametoindex(s); + if (r <= 0) + return -errno; + + *ret = r; + return 0; +} + +int parse_mtu(int family, const char *s, uint32_t *ret) { + uint64_t u; + size_t m; + int r; + + r = parse_size(s, 1024, &u); + if (r < 0) + return r; + + if (u > UINT32_MAX) + return -ERANGE; + + if (family == AF_INET6) + m = IPV6_MIN_MTU; /* This is 1280 */ + else + m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */ + + if (u < m) + return -ERANGE; + + *ret = (uint32_t) u; + return 0; +} + +int parse_size(const char *t, uint64_t base, uint64_t *size) { + + /* Soo, sometimes we want to parse IEC binary suffixes, and + * sometimes SI decimal suffixes. This function can parse + * both. Which one is the right way depends on the + * context. Wikipedia suggests that SI is customary for + * hardware metrics and network speeds, while IEC is + * customary for most data sizes used by software and volatile + * (RAM) memory. Hence be careful which one you pick! + * + * In either case we use just K, M, G as suffix, and not Ki, + * Mi, Gi or so (as IEC would suggest). That's because that's + * frickin' ugly. But this means you really need to make sure + * to document which base you are parsing when you use this + * call. */ + + struct table { + const char *suffix; + unsigned long long factor; + }; + + static const struct table iec[] = { + { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL }, + { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL }, + { "T", 1024ULL*1024ULL*1024ULL*1024ULL }, + { "G", 1024ULL*1024ULL*1024ULL }, + { "M", 1024ULL*1024ULL }, + { "K", 1024ULL }, + { "B", 1ULL }, + { "", 1ULL }, + }; + + static const struct table si[] = { + { "E", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL*1000ULL }, + { "P", 1000ULL*1000ULL*1000ULL*1000ULL*1000ULL }, + { "T", 1000ULL*1000ULL*1000ULL*1000ULL }, + { "G", 1000ULL*1000ULL*1000ULL }, + { "M", 1000ULL*1000ULL }, + { "K", 1000ULL }, + { "B", 1ULL }, + { "", 1ULL }, + }; + + const struct table *table; + const char *p; + unsigned long long r = 0; + unsigned n_entries, start_pos = 0; + + assert(t); + assert(IN_SET(base, 1000, 1024)); + assert(size); + + if (base == 1000) { + table = si; + n_entries = ELEMENTSOF(si); + } else { + table = iec; + n_entries = ELEMENTSOF(iec); + } + + p = t; + do { + unsigned long long l, tmp; + double frac = 0; + char *e; + unsigned i; + + p += strspn(p, WHITESPACE); + + errno = 0; + l = strtoull(p, &e, 10); + if (errno > 0) + return -errno; + if (e == p) + return -EINVAL; + if (*p == '-') + return -ERANGE; + + if (*e == '.') { + e++; + + /* strtoull() itself would accept space/+/- */ + if (*e >= '0' && *e <= '9') { + unsigned long long l2; + char *e2; + + l2 = strtoull(e, &e2, 10); + if (errno > 0) + return -errno; + + /* Ignore failure. E.g. 10.M is valid */ + frac = l2; + for (; e < e2; e++) + frac /= 10; + } + } + + e += strspn(e, WHITESPACE); + + for (i = start_pos; i < n_entries; i++) + if (startswith(e, table[i].suffix)) + break; + + if (i >= n_entries) + return -EINVAL; + + if (l + (frac > 0) > ULLONG_MAX / table[i].factor) + return -ERANGE; + + tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor); + if (tmp > ULLONG_MAX - r) + return -ERANGE; + + r += tmp; + if ((unsigned long long) (uint64_t) r != r) + return -ERANGE; + + p = e + strlen(table[i].suffix); + + start_pos = i + 1; + + } while (*p); + + *size = r; + + return 0; +} + +int parse_range(const char *t, unsigned *lower, unsigned *upper) { + _cleanup_free_ char *word = NULL; + unsigned l, u; + int r; + + assert(lower); + assert(upper); + + /* Extract the lower bound. */ + r = extract_first_word(&t, &word, "-", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + r = safe_atou(word, &l); + if (r < 0) + return r; + + /* Check for the upper bound and extract it if needed */ + if (!t) + /* Single number with no dashes. */ + u = l; + else if (!*t) + /* Trailing dash is an error. */ + return -EINVAL; + else { + r = safe_atou(t, &u); + if (r < 0) + return r; + } + + *lower = l; + *upper = u; + return 0; +} + +int parse_errno(const char *t) { + int r, e; + + assert(t); + + r = errno_from_name(t); + if (r > 0) + return r; + + r = safe_atoi(t, &e); + if (r < 0) + return r; + + /* 0 is also allowed here */ + if (!errno_is_valid(e) && e != 0) + return -ERANGE; + + return e; +} + +int parse_syscall_and_errno(const char *in, char **name, int *error) { + _cleanup_free_ char *n = NULL; + char *p; + int e = -1; + + assert(in); + assert(name); + assert(error); + + /* + * This parse "syscall:errno" like "uname:EILSEQ", "@sync:255". + * If errno is omitted, then error is set to -1. + * Empty syscall name is not allowed. + * Here, we do not check that the syscall name is valid or not. + */ + + p = strchr(in, ':'); + if (p) { + e = parse_errno(p + 1); + if (e < 0) + return e; + + n = strndup(in, p - in); + } else + n = strdup(in); + + if (!n) + return -ENOMEM; + + if (isempty(n)) + return -EINVAL; + + *error = e; + *name = TAKE_PTR(n); + + return 0; +} + +int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) { + char *x = NULL; + unsigned long l; + + assert(s); + assert(ret_u); + assert(base <= 16); + + /* strtoul() is happy to parse negative values, and silently + * converts them to unsigned values without generating an + * error. We want a clean error, hence let's look for the "-" + * prefix on our own, and generate an error. But let's do so + * only after strtoul() validated that the string is clean + * otherwise, so that we return EINVAL preferably over + * ERANGE. */ + + s += strspn(s, WHITESPACE); + + errno = 0; + l = strtoul(s, &x, base); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; + if (s[0] == '-') + return -ERANGE; + if ((unsigned long) (unsigned) l != l) + return -ERANGE; + + *ret_u = (unsigned) l; + return 0; +} + +int safe_atoi(const char *s, int *ret_i) { + char *x = NULL; + long l; + + assert(s); + assert(ret_i); + + errno = 0; + l = strtol(s, &x, 0); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; + if ((long) (int) l != l) + return -ERANGE; + + *ret_i = (int) l; + return 0; +} + +int safe_atollu(const char *s, long long unsigned *ret_llu) { + char *x = NULL; + unsigned long long l; + + assert(s); + assert(ret_llu); + + s += strspn(s, WHITESPACE); + + errno = 0; + l = strtoull(s, &x, 0); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; + if (*s == '-') + return -ERANGE; + + *ret_llu = l; + return 0; +} + +int safe_atolli(const char *s, long long int *ret_lli) { + char *x = NULL; + long long l; + + assert(s); + assert(ret_lli); + + errno = 0; + l = strtoll(s, &x, 0); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; + + *ret_lli = l; + return 0; +} + +int safe_atou8(const char *s, uint8_t *ret) { + char *x = NULL; + unsigned long l; + + assert(s); + assert(ret); + + s += strspn(s, WHITESPACE); + + errno = 0; + l = strtoul(s, &x, 0); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; + if (s[0] == '-') + return -ERANGE; + if ((unsigned long) (uint8_t) l != l) + return -ERANGE; + + *ret = (uint8_t) l; + return 0; +} + +int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) { + char *x = NULL; + unsigned long l; + + assert(s); + assert(ret); + assert(base <= 16); + + s += strspn(s, WHITESPACE); + + errno = 0; + l = strtoul(s, &x, base); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; + if (s[0] == '-') + return -ERANGE; + if ((unsigned long) (uint16_t) l != l) + return -ERANGE; + + *ret = (uint16_t) l; + return 0; +} + +int safe_atoi16(const char *s, int16_t *ret) { + char *x = NULL; + long l; + + assert(s); + assert(ret); + + errno = 0; + l = strtol(s, &x, 0); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; + if ((long) (int16_t) l != l) + return -ERANGE; + + *ret = (int16_t) l; + return 0; +} + +int safe_atod(const char *s, double *ret_d) { + _cleanup_(freelocalep) locale_t loc = (locale_t) 0; + char *x = NULL; + double d = 0; + + assert(s); + assert(ret_d); + + loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0); + if (loc == (locale_t) 0) + return -errno; + + errno = 0; + d = strtod_l(s, &x, loc); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; + + *ret_d = (double) d; + return 0; +} + +int parse_fractional_part_u(const char **p, size_t digits, unsigned *res) { + size_t i; + unsigned val = 0; + const char *s; + + s = *p; + + /* accept any number of digits, strtoull is limited to 19 */ + for (i=0; i < digits; i++,s++) { + if (*s < '0' || *s > '9') { + if (i == 0) + return -EINVAL; + + /* too few digits, pad with 0 */ + for (; i < digits; i++) + val *= 10; + + break; + } + + val *= 10; + val += *s - '0'; + } + + /* maybe round up */ + if (*s >= '5' && *s <= '9') + val++; + + s += strspn(s, DIGITS); + + *p = s; + *res = val; + + return 0; +} + +int parse_percent_unbounded(const char *p) { + const char *pc, *n; + int r, v; + + pc = endswith(p, "%"); + if (!pc) + return -EINVAL; + + n = strndupa(p, pc - p); + r = safe_atoi(n, &v); + if (r < 0) + return r; + if (v < 0) + return -ERANGE; + + return v; +} + +int parse_percent(const char *p) { + int v; + + v = parse_percent_unbounded(p); + if (v > 100) + return -ERANGE; + + return v; +} + +int parse_permille_unbounded(const char *p) { + const char *pc, *pm, *dot, *n; + int r, q, v; + + pm = endswith(p, "‰"); + if (pm) { + n = strndupa(p, pm - p); + r = safe_atoi(n, &v); + if (r < 0) + return r; + if (v < 0) + return -ERANGE; + } else { + pc = endswith(p, "%"); + if (!pc) + return -EINVAL; + + dot = memchr(p, '.', pc - p); + if (dot) { + if (dot + 2 != pc) + return -EINVAL; + if (dot[1] < '0' || dot[1] > '9') + return -EINVAL; + q = dot[1] - '0'; + n = strndupa(p, dot - p); + } else { + q = 0; + n = strndupa(p, pc - p); + } + r = safe_atoi(n, &v); + if (r < 0) + return r; + if (v < 0) + return -ERANGE; + if (v > (INT_MAX - q) / 10) + return -ERANGE; + + v = v * 10 + q; + } + + return v; +} + +int parse_permille(const char *p) { + int v; + + v = parse_permille_unbounded(p); + if (v > 1000) + return -ERANGE; + + return v; +} + +int parse_nice(const char *p, int *ret) { + int n, r; + + r = safe_atoi(p, &n); + if (r < 0) + return r; + + if (!nice_is_valid(n)) + return -ERANGE; + + *ret = n; + return 0; +} + +int parse_ip_port(const char *s, uint16_t *ret) { + uint16_t l; + int r; + + r = safe_atou16(s, &l); + if (r < 0) + return r; + + if (l == 0) + return -EINVAL; + + *ret = (uint16_t) l; + + return 0; +} + +int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high) { + unsigned l, h; + int r; + + r = parse_range(s, &l, &h); + if (r < 0) + return r; + + if (l <= 0 || l > 65535 || h <= 0 || h > 65535) + return -EINVAL; + + if (h < l) + return -EINVAL; + + *low = l; + *high = h; + + return 0; +} + +int parse_dev(const char *s, dev_t *ret) { + const char *major; + unsigned x, y; + size_t n; + int r; + + n = strspn(s, DIGITS); + if (n == 0) + return -EINVAL; + if (s[n] != ':') + return -EINVAL; + + major = strndupa(s, n); + r = safe_atou(major, &x); + if (r < 0) + return r; + + r = safe_atou(s + n + 1, &y); + if (r < 0) + return r; + + if (!DEVICE_MAJOR_VALID(x) || !DEVICE_MINOR_VALID(y)) + return -ERANGE; + + *ret = makedev(x, y); + return 0; +} + +int parse_oom_score_adjust(const char *s, int *ret) { + int r, v; + + assert(s); + assert(ret); + + r = safe_atoi(s, &v); + if (r < 0) + return r; + + if (v < OOM_SCORE_ADJ_MIN || v > OOM_SCORE_ADJ_MAX) + return -ERANGE; + + *ret = v; + return 0; +} diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h new file mode 100644 index 00000000..3a70b792 --- /dev/null +++ b/src/basic/parse-util.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include + +#include "macro.h" + +int parse_boolean(const char *v) _pure_; +int parse_dev(const char *s, dev_t *ret); +int parse_pid(const char *s, pid_t* ret_pid); +int parse_mode(const char *s, mode_t *ret); +int parse_ifindex(const char *s, int *ret); +int parse_ifindex_or_ifname(const char *s, int *ret); +int parse_mtu(int family, const char *s, uint32_t *ret); + +int parse_size(const char *t, uint64_t base, uint64_t *size); +int parse_range(const char *t, unsigned *lower, unsigned *upper); +int parse_errno(const char *t); +int parse_syscall_and_errno(const char *in, char **name, int *error); + +int safe_atou_full(const char *s, unsigned base, unsigned *ret_u); + +static inline int safe_atou(const char *s, unsigned *ret_u) { + return safe_atou_full(s, 0, ret_u); +} + +int safe_atoi(const char *s, int *ret_i); +int safe_atollu(const char *s, unsigned long long *ret_u); +int safe_atolli(const char *s, long long int *ret_i); + +int safe_atou8(const char *s, uint8_t *ret); + +int safe_atou16_full(const char *s, unsigned base, uint16_t *ret); + +static inline int safe_atou16(const char *s, uint16_t *ret) { + return safe_atou16_full(s, 0, ret); +} + +static inline int safe_atoux16(const char *s, uint16_t *ret) { + return safe_atou16_full(s, 16, ret); +} + +int safe_atoi16(const char *s, int16_t *ret); + +static inline int safe_atou32(const char *s, uint32_t *ret_u) { + assert_cc(sizeof(uint32_t) == sizeof(unsigned)); + return safe_atou(s, (unsigned*) ret_u); +} + +static inline int safe_atoi32(const char *s, int32_t *ret_i) { + assert_cc(sizeof(int32_t) == sizeof(int)); + return safe_atoi(s, (int*) ret_i); +} + +static inline int safe_atou64(const char *s, uint64_t *ret_u) { + assert_cc(sizeof(uint64_t) == sizeof(unsigned long long)); + return safe_atollu(s, (unsigned long long*) ret_u); +} + +static inline int safe_atoi64(const char *s, int64_t *ret_i) { + assert_cc(sizeof(int64_t) == sizeof(long long int)); + return safe_atolli(s, (long long int*) ret_i); +} + +#if LONG_MAX == INT_MAX +static inline int safe_atolu(const char *s, unsigned long *ret_u) { + assert_cc(sizeof(unsigned long) == sizeof(unsigned)); + return safe_atou(s, (unsigned*) ret_u); +} +static inline int safe_atoli(const char *s, long int *ret_u) { + assert_cc(sizeof(long int) == sizeof(int)); + return safe_atoi(s, (int*) ret_u); +} +#else +static inline int safe_atolu(const char *s, unsigned long *ret_u) { + assert_cc(sizeof(unsigned long) == sizeof(unsigned long long)); + return safe_atollu(s, (unsigned long long*) ret_u); +} +static inline int safe_atoli(const char *s, long int *ret_u) { + assert_cc(sizeof(long int) == sizeof(long long int)); + return safe_atolli(s, (long long int*) ret_u); +} +#endif + +#if SIZE_MAX == UINT_MAX +static inline int safe_atozu(const char *s, size_t *ret_u) { + assert_cc(sizeof(size_t) == sizeof(unsigned)); + return safe_atou(s, (unsigned *) ret_u); +} +#else +static inline int safe_atozu(const char *s, size_t *ret_u) { + assert_cc(sizeof(size_t) == sizeof(long unsigned)); + return safe_atolu(s, ret_u); +} +#endif + +int safe_atod(const char *s, double *ret_d); + +int parse_fractional_part_u(const char **s, size_t digits, unsigned *res); + +int parse_percent_unbounded(const char *p); +int parse_percent(const char *p); + +int parse_permille_unbounded(const char *p); +int parse_permille(const char *p); + +int parse_nice(const char *p, int *ret); + +int parse_ip_port(const char *s, uint16_t *ret); +int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high); + +int parse_oom_score_adjust(const char *s, int *ret); diff --git a/src/basic/path-util.c b/src/basic/path-util.c new file mode 100644 index 00000000..f1be8d09 --- /dev/null +++ b/src/basic/path-util.c @@ -0,0 +1,1117 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +/* When we include libgen.h because we need dirname() we immediately + * undefine basename() since libgen.h defines it as a macro to the + * POSIX version which is really broken. We prefer GNU basename(). */ +#include +#undef basename + +#include "alloc-util.h" +#include "extract-word.h" +#include "fs-util.h" +#include "glob-util.h" +#include "log.h" +#include "macro.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "utf8.h" + +bool path_is_absolute(const char *p) { + return p[0] == '/'; +} + +bool is_path(const char *p) { + return !!strchr(p, '/'); +} + +int path_split_and_make_absolute(const char *p, char ***ret) { + char **l; + int r; + + assert(p); + assert(ret); + + l = strv_split(p, ":"); + if (!l) + return -ENOMEM; + + r = path_strv_make_absolute_cwd(l); + if (r < 0) { + strv_free(l); + return r; + } + + *ret = l; + return r; +} + +char *path_make_absolute(const char *p, const char *prefix) { + assert(p); + + /* Makes every item in the list an absolute path by prepending + * the prefix, if specified and necessary */ + + if (path_is_absolute(p) || isempty(prefix)) + return strdup(p); + + return path_join(prefix, p); +} + +int safe_getcwd(char **ret) { + char *cwd; + + cwd = get_current_dir_name(); + if (!cwd) + return negative_errno(); + + /* Let's make sure the directory is really absolute, to protect us from the logic behind + * CVE-2018-1000001 */ + if (cwd[0] != '/') { + free(cwd); + return -ENOMEDIUM; + } + + *ret = cwd; + return 0; +} + +int path_make_absolute_cwd(const char *p, char **ret) { + char *c; + int r; + + assert(p); + assert(ret); + + /* Similar to path_make_absolute(), but prefixes with the + * current working directory. */ + + if (path_is_absolute(p)) + c = strdup(p); + else { + _cleanup_free_ char *cwd = NULL; + + r = safe_getcwd(&cwd); + if (r < 0) + return r; + + c = path_join(cwd, p); + } + if (!c) + return -ENOMEM; + + *ret = c; + return 0; +} + +int path_make_relative(const char *from_dir, const char *to_path, char **_r) { + char *f, *t, *r, *p; + unsigned n_parents = 0; + + assert(from_dir); + assert(to_path); + assert(_r); + + /* Strips the common part, and adds ".." elements as necessary. */ + + if (!path_is_absolute(from_dir) || !path_is_absolute(to_path)) + return -EINVAL; + + f = strdupa(from_dir); + t = strdupa(to_path); + + path_simplify(f, true); + path_simplify(t, true); + + /* Skip the common part. */ + for (;;) { + size_t a, b; + + f += *f == '/'; + t += *t == '/'; + + if (!*f) { + if (!*t) + /* from_dir equals to_path. */ + r = strdup("."); + else + /* from_dir is a parent directory of to_path. */ + r = strdup(t); + if (!r) + return -ENOMEM; + + *_r = r; + return 0; + } + + if (!*t) + break; + + a = strcspn(f, "/"); + b = strcspn(t, "/"); + + if (a != b || memcmp(f, t, a) != 0) + break; + + f += a; + t += b; + } + + /* If we're here, then "from_dir" has one or more elements that need to + * be replaced with "..". */ + + /* Count the number of necessary ".." elements. */ + for (; *f;) { + size_t w; + + w = strcspn(f, "/"); + + /* If this includes ".." we can't do a simple series of "..", refuse */ + if (w == 2 && f[0] == '.' && f[1] == '.') + return -EINVAL; + + /* Count number of elements */ + n_parents++; + + f += w; + f += *f == '/'; + } + + r = new(char, n_parents * 3 + strlen(t) + 1); + if (!r) + return -ENOMEM; + + for (p = r; n_parents > 0; n_parents--) + p = mempcpy(p, "../", 3); + + if (*t) + strcpy(p, t); + else + /* Remove trailing slash */ + *(--p) = 0; + + *_r = r; + return 0; +} + +char* path_startswith_strv(const char *p, char **set) { + char **s, *t; + + STRV_FOREACH(s, set) { + t = path_startswith(p, *s); + if (t) + return t; + } + + return NULL; +} + +int path_strv_make_absolute_cwd(char **l) { + char **s; + int r; + + /* Goes through every item in the string list and makes it + * absolute. This works in place and won't rollback any + * changes on failure. */ + + STRV_FOREACH(s, l) { + char *t; + + r = path_make_absolute_cwd(*s, &t); + if (r < 0) + return r; + + path_simplify(t, false); + free_and_replace(*s, t); + } + + return 0; +} + +char **path_strv_resolve(char **l, const char *root) { + char **s; + unsigned k = 0; + bool enomem = false; + int r; + + if (strv_isempty(l)) + return l; + + /* Goes through every item in the string list and canonicalize + * the path. This works in place and won't rollback any + * changes on failure. */ + + STRV_FOREACH(s, l) { + _cleanup_free_ char *orig = NULL; + char *t, *u; + + if (!path_is_absolute(*s)) { + free(*s); + continue; + } + + if (root) { + orig = *s; + t = path_join(root, orig); + if (!t) { + enomem = true; + continue; + } + } else + t = *s; + + r = chase_symlinks(t, root, 0, &u, NULL); + if (r == -ENOENT) { + if (root) { + u = TAKE_PTR(orig); + free(t); + } else + u = t; + } else if (r < 0) { + free(t); + + if (r == -ENOMEM) + enomem = true; + + continue; + } else if (root) { + char *x; + + free(t); + x = path_startswith(u, root); + if (x) { + /* restore the slash if it was lost */ + if (!startswith(x, "/")) + *(--x) = '/'; + + t = strdup(x); + free(u); + if (!t) { + enomem = true; + continue; + } + u = t; + } else { + /* canonicalized path goes outside of + * prefix, keep the original path instead */ + free_and_replace(u, orig); + } + } else + free(t); + + l[k++] = u; + } + + l[k] = NULL; + + if (enomem) + return NULL; + + return l; +} + +char **path_strv_resolve_uniq(char **l, const char *root) { + + if (strv_isempty(l)) + return l; + + if (!path_strv_resolve(l, root)) + return NULL; + + return strv_uniq(l); +} + +char *path_simplify(char *path, bool kill_dots) { + char *f, *t; + bool slash = false, ignore_slash = false, absolute; + + assert(path); + + /* Removes redundant inner and trailing slashes. Also removes unnecessary dots + * if kill_dots is true. Modifies the passed string in-place. + * + * ///foo//./bar/. becomes /foo/./bar/. (if kill_dots is false) + * ///foo//./bar/. becomes /foo/bar (if kill_dots is true) + * .//./foo//./bar/. becomes ././foo/./bar/. (if kill_dots is false) + * .//./foo//./bar/. becomes foo/bar (if kill_dots is true) + */ + + if (isempty(path)) + return path; + + absolute = path_is_absolute(path); + + f = path; + if (kill_dots && *f == '.' && IN_SET(f[1], 0, '/')) { + ignore_slash = true; + f++; + } + + for (t = path; *f; f++) { + + if (*f == '/') { + slash = true; + continue; + } + + if (slash) { + if (kill_dots && *f == '.' && IN_SET(f[1], 0, '/')) + continue; + + slash = false; + if (ignore_slash) + ignore_slash = false; + else + *(t++) = '/'; + } + + *(t++) = *f; + } + + /* Special rule, if we stripped everything, we either need a "/" (for the root directory) + * or "." for the current directory */ + if (t == path) { + if (absolute) + *(t++) = '/'; + else + *(t++) = '.'; + } + + *t = 0; + return path; +} + +int path_simplify_and_warn( + char *path, + unsigned flag, + const char *unit, + const char *filename, + unsigned line, + const char *lvalue) { + + bool fatal = flag & PATH_CHECK_FATAL; + + assert(!FLAGS_SET(flag, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)); + + if (!utf8_is_valid(path)) + return log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path); + + if (flag & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) { + bool absolute; + + absolute = path_is_absolute(path); + + if (!absolute && (flag & PATH_CHECK_ABSOLUTE)) + return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), + "%s= path is not absolute%s: %s", + lvalue, fatal ? "" : ", ignoring", path); + + if (absolute && (flag & PATH_CHECK_RELATIVE)) + return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), + "%s= path is absolute%s: %s", + lvalue, fatal ? "" : ", ignoring", path); + } + + path_simplify(path, true); + + if (!path_is_valid(path)) + return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), + "%s= path has invalid length (%zu bytes)%s.", + lvalue, strlen(path), fatal ? "" : ", ignoring"); + + if (!path_is_normalized(path)) + return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), + "%s= path is not normalized%s: %s", + lvalue, fatal ? "" : ", ignoring", path); + + return 0; +} + +char* path_startswith(const char *path, const char *prefix) { + assert(path); + assert(prefix); + + /* Returns a pointer to the start of the first component after the parts matched by + * the prefix, iff + * - both paths are absolute or both paths are relative, + * and + * - each component in prefix in turn matches a component in path at the same position. + * An empty string will be returned when the prefix and path are equivalent. + * + * Returns NULL otherwise. + */ + + if ((path[0] == '/') != (prefix[0] == '/')) + return NULL; + + for (;;) { + size_t a, b; + + path += strspn(path, "/"); + prefix += strspn(prefix, "/"); + + if (*prefix == 0) + return (char*) path; + + if (*path == 0) + return NULL; + + a = strcspn(path, "/"); + b = strcspn(prefix, "/"); + + if (a != b) + return NULL; + + if (memcmp(path, prefix, a) != 0) + return NULL; + + path += a; + prefix += b; + } +} + +int path_compare(const char *a, const char *b) { + int d; + + assert(a); + assert(b); + + /* A relative path and an absolute path must not compare as equal. + * Which one is sorted before the other does not really matter. + * Here a relative path is ordered before an absolute path. */ + d = (a[0] == '/') - (b[0] == '/'); + if (d != 0) + return d; + + for (;;) { + size_t j, k; + + a += strspn(a, "/"); + b += strspn(b, "/"); + + if (*a == 0 && *b == 0) + return 0; + + /* Order prefixes first: "/foo" before "/foo/bar" */ + if (*a == 0) + return -1; + if (*b == 0) + return 1; + + j = strcspn(a, "/"); + k = strcspn(b, "/"); + + /* Alphabetical sort: "/foo/aaa" before "/foo/b" */ + d = memcmp(a, b, MIN(j, k)); + if (d != 0) + return (d > 0) - (d < 0); /* sign of d */ + + /* Sort "/foo/a" before "/foo/aaa" */ + d = (j > k) - (j < k); /* sign of (j - k) */ + if (d != 0) + return d; + + a += j; + b += k; + } +} + +bool path_equal(const char *a, const char *b) { + return path_compare(a, b) == 0; +} + +bool path_equal_or_files_same(const char *a, const char *b, int flags) { + return path_equal(a, b) || files_same(a, b, flags) > 0; +} + +char* path_join_internal(const char *first, ...) { + char *joined, *q; + const char *p; + va_list ap; + bool slash; + size_t sz; + + /* Joins all listed strings until the sentinel and places a "/" between them unless the strings end/begin + * already with one so that it is unnecessary. Note that slashes which are already duplicate won't be + * removed. The string returned is hence always equal to or longer than the sum of the lengths of each + * individual string. + * + * Note: any listed empty string is simply skipped. This can be useful for concatenating strings of which some + * are optional. + * + * Examples: + * + * path_join("foo", "bar") → "foo/bar" + * path_join("foo/", "bar") → "foo/bar" + * path_join("", "foo", "", "bar", "") → "foo/bar" */ + + sz = strlen_ptr(first); + va_start(ap, first); + while ((p = va_arg(ap, char*)) != (const char*) -1) + if (!isempty(p)) + sz += 1 + strlen(p); + va_end(ap); + + joined = new(char, sz + 1); + if (!joined) + return NULL; + + if (!isempty(first)) { + q = stpcpy(joined, first); + slash = endswith(first, "/"); + } else { + /* Skip empty items */ + joined[0] = 0; + q = joined; + slash = true; /* no need to generate a slash anymore */ + } + + va_start(ap, first); + while ((p = va_arg(ap, char*)) != (const char*) -1) { + if (isempty(p)) + continue; + + if (!slash && p[0] != '/') + *(q++) = '/'; + + q = stpcpy(q, p); + slash = endswith(p, "/"); + } + va_end(ap); + + return joined; +} + +int find_binary(const char *name, char **ret) { + int last_error, r; + const char *p; + + assert(name); + + if (is_path(name)) { + if (access(name, X_OK) < 0) + return -errno; + + if (ret) { + r = path_make_absolute_cwd(name, ret); + if (r < 0) + return r; + } + + return 0; + } + + /** + * Plain getenv, not secure_getenv, because we want + * to actually allow the user to pick the binary. + */ + p = getenv("PATH"); + if (!p) + p = DEFAULT_PATH; + + last_error = -ENOENT; + + for (;;) { + _cleanup_free_ char *j = NULL, *element = NULL; + + r = extract_first_word(&p, &element, ":", EXTRACT_RELAX|EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + if (r == 0) + break; + + if (!path_is_absolute(element)) + continue; + + j = path_join(element, name); + if (!j) + return -ENOMEM; + + if (access(j, X_OK) >= 0) { + /* Found it! */ + + if (ret) { + *ret = path_simplify(j, false); + j = NULL; + } + + return 0; + } + + /* PATH entries which we don't have access to are ignored, as per tradition. */ + if (errno != EACCES) + last_error = -errno; + } + + return last_error; +} + +bool paths_check_timestamp(const char* const* paths, usec_t *timestamp, bool update) { + bool changed = false; + const char* const* i; + + assert(timestamp); + + if (!paths) + return false; + + STRV_FOREACH(i, paths) { + struct stat stats; + usec_t u; + + if (stat(*i, &stats) < 0) + continue; + + u = timespec_load(&stats.st_mtim); + + /* first check */ + if (*timestamp >= u) + continue; + + log_debug("timestamp of '%s' changed", *i); + + /* update timestamp */ + if (update) { + *timestamp = u; + changed = true; + } else + return true; + } + + return changed; +} + +static int binary_is_good(const char *binary) { + _cleanup_free_ char *p = NULL, *d = NULL; + int r; + + r = find_binary(binary, &p); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + /* An fsck that is linked to /bin/true is a non-existent + * fsck */ + + r = readlink_malloc(p, &d); + if (r == -EINVAL) /* not a symlink */ + return 1; + if (r < 0) + return r; + + return !PATH_IN_SET(d, "true" + "/bin/true", + "/usr/bin/true", + "/dev/null"); +} + +int fsck_exists(const char *fstype) { + const char *checker; + + assert(fstype); + + if (streq(fstype, "auto")) + return -EINVAL; + + checker = strjoina("fsck.", fstype); + return binary_is_good(checker); +} + +int mkfs_exists(const char *fstype) { + const char *mkfs; + + assert(fstype); + + if (streq(fstype, "auto")) + return -EINVAL; + + mkfs = strjoina("mkfs.", fstype); + return binary_is_good(mkfs); +} + +int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) { + char *p; + int r; + + /* + * This function is intended to be used in command line + * parsers, to handle paths that are passed in. It makes the + * path absolute, and reduces it to NULL if omitted or + * root (the latter optionally). + * + * NOTE THAT THIS WILL FREE THE PREVIOUS ARGUMENT POINTER ON + * SUCCESS! Hence, do not pass in uninitialized pointers. + */ + + if (isempty(path)) { + *arg = mfree(*arg); + return 0; + } + + r = path_make_absolute_cwd(path, &p); + if (r < 0) + return log_error_errno(r, "Failed to parse path \"%s\" and make it absolute: %m", path); + + path_simplify(p, false); + if (suppress_root && empty_or_root(p)) + p = mfree(p); + + free_and_replace(*arg, p); + + return 0; +} + +char* dirname_malloc(const char *path) { + char *d, *dir, *dir2; + + assert(path); + + d = strdup(path); + if (!d) + return NULL; + + dir = dirname(d); + assert(dir); + + if (dir == d) + return d; + + dir2 = strdup(dir); + free(d); + + return dir2; +} + +const char *last_path_component(const char *path) { + + /* Finds the last component of the path, preserving the optional trailing slash that signifies a directory. + * + * a/b/c → c + * a/b/c/ → c/ + * x → x + * x/ → x/ + * /y → y + * /y/ → y/ + * / → / + * // → / + * /foo/a → a + * /foo/a/ → a/ + * + * Also, the empty string is mapped to itself. + * + * This is different than basename(), which returns "" when a trailing slash is present. + */ + + unsigned l, k; + + if (!path) + return NULL; + + l = k = strlen(path); + if (l == 0) /* special case — an empty string */ + return path; + + while (k > 0 && path[k-1] == '/') + k--; + + if (k == 0) /* the root directory */ + return path + l - 1; + + while (k > 0 && path[k-1] != '/') + k--; + + return path + k; +} + +int path_extract_filename(const char *p, char **ret) { + _cleanup_free_ char *a = NULL; + const char *c, *e = NULL, *q; + + /* Extracts the filename part (i.e. right-most component) from a path, i.e. string that passes + * filename_is_valid(). A wrapper around last_path_component(), but eats up trailing slashes. */ + + if (!p) + return -EINVAL; + + c = last_path_component(p); + + for (q = c; *q != 0; q++) + if (*q != '/') + e = q + 1; + + if (!e) /* no valid character? */ + return -EINVAL; + + a = strndup(c, e - c); + if (!a) + return -ENOMEM; + + if (!filename_is_valid(a)) + return -EINVAL; + + *ret = TAKE_PTR(a); + + return 0; +} + +bool filename_is_valid(const char *p) { + const char *e; + + if (isempty(p)) + return false; + + if (dot_or_dot_dot(p)) + return false; + + e = strchrnul(p, '/'); + if (*e != 0) + return false; + + if (e - p > FILENAME_MAX) /* FILENAME_MAX is counted *without* the trailing NUL byte */ + return false; + + return true; +} + +bool path_is_valid(const char *p) { + + if (isempty(p)) + return false; + + if (strlen(p) >= PATH_MAX) /* PATH_MAX is counted *with* the trailing NUL byte */ + return false; + + return true; +} + +bool path_is_normalized(const char *p) { + + if (!path_is_valid(p)) + return false; + + if (dot_or_dot_dot(p)) + return false; + + if (startswith(p, "../") || endswith(p, "/..") || strstr(p, "/../")) + return false; + + if (startswith(p, "./") || endswith(p, "/.") || strstr(p, "/./")) + return false; + + if (strstr(p, "//")) + return false; + + return true; +} + +char *file_in_same_dir(const char *path, const char *filename) { + char *e, *ret; + size_t k; + + assert(path); + assert(filename); + + /* This removes the last component of path and appends + * filename, unless the latter is absolute anyway or the + * former isn't */ + + if (path_is_absolute(filename)) + return strdup(filename); + + e = strrchr(path, '/'); + if (!e) + return strdup(filename); + + k = strlen(filename); + ret = new(char, (e + 1 - path) + k + 1); + if (!ret) + return NULL; + + memcpy(mempcpy(ret, path, e + 1 - path), filename, k + 1); + return ret; +} + +bool hidden_or_backup_file(const char *filename) { + const char *p; + + assert(filename); + + if (filename[0] == '.' || + streq(filename, "lost+found") || + streq(filename, "aquota.user") || + streq(filename, "aquota.group") || + endswith(filename, "~")) + return true; + + p = strrchr(filename, '.'); + if (!p) + return false; + + /* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up + * with always new suffixes and that everybody else should just adjust to that, then it really should be on + * them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt + * one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional + * string. Specifically: there's now: + * + * The generic suffixes "~" and ".bak" for backup files + * The generic prefix "." for hidden files + * + * Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist" + * or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead. + */ + + return STR_IN_SET(p + 1, + "rpmnew", + "rpmsave", + "rpmorig", + "dpkg-old", + "dpkg-new", + "dpkg-tmp", + "dpkg-dist", + "dpkg-bak", + "dpkg-backup", + "dpkg-remove", + "ucf-new", + "ucf-old", + "ucf-dist", + "swp", + "bak", + "old", + "new"); +} + +bool is_device_path(const char *path) { + + /* Returns true on paths that likely refer to a device, either by path in sysfs or to something in /dev */ + + return PATH_STARTSWITH_SET(path, "/dev/", "/sys/"); +} + +bool valid_device_node_path(const char *path) { + + /* Some superficial checks whether the specified path is a valid device node path, all without looking at the + * actual device node. */ + + if (!PATH_STARTSWITH_SET(path, "/dev/", "/run/systemd/inaccessible/")) + return false; + + if (endswith(path, "/")) /* can't be a device node if it ends in a slash */ + return false; + + return path_is_normalized(path); +} + +bool valid_device_allow_pattern(const char *path) { + assert(path); + + /* Like valid_device_node_path(), but also allows full-subsystem expressions, like DeviceAllow= and DeviceDeny= + * accept it */ + + if (STARTSWITH_SET(path, "block-", "char-")) + return true; + + return valid_device_node_path(path); +} + +int systemd_installation_has_version(const char *root, unsigned minimal_version) { + const char *pattern; + int r; + + /* Try to guess if systemd installation is later than the specified version. This + * is hacky and likely to yield false negatives, particularly if the installation + * is non-standard. False positives should be relatively rare. + */ + + NULSTR_FOREACH(pattern, + /* /lib works for systems without usr-merge, and for systems with a sane + * usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary + * for Gentoo which does a merge without making /lib a symlink. + */ + "lib/systemd/libsystemd-shared-*.so\0" + "lib64/systemd/libsystemd-shared-*.so\0" + "usr/lib/systemd/libsystemd-shared-*.so\0" + "usr/lib64/systemd/libsystemd-shared-*.so\0") { + + _cleanup_strv_free_ char **names = NULL; + _cleanup_free_ char *path = NULL; + char *c, **name; + + path = path_join(root, pattern); + if (!path) + return -ENOMEM; + + r = glob_extend(&names, path); + if (r == -ENOENT) + continue; + if (r < 0) + return r; + + assert_se(c = endswith(path, "*.so")); + *c = '\0'; /* truncate the glob part */ + + STRV_FOREACH(name, names) { + /* This is most likely to run only once, hence let's not optimize anything. */ + char *t, *t2; + unsigned version; + + t = startswith(*name, path); + if (!t) + continue; + + t2 = endswith(t, ".so"); + if (!t2) + continue; + + t2[0] = '\0'; /* truncate the suffix */ + + r = safe_atou(t, &version); + if (r < 0) { + log_debug_errno(r, "Found libsystemd shared at \"%s.so\", but failed to parse version: %m", *name); + continue; + } + + log_debug("Found libsystemd shared at \"%s.so\", version %u (%s).", + *name, version, + version >= minimal_version ? "OK" : "too old"); + if (version >= minimal_version) + return true; + } + } + + return false; +} + +bool dot_or_dot_dot(const char *path) { + if (!path) + return false; + if (path[0] != '.') + return false; + if (path[1] == 0) + return true; + if (path[1] != '.') + return false; + + return path[2] == 0; +} + +bool empty_or_root(const char *root) { + + /* For operations relative to some root directory, returns true if the specified root directory is redundant, + * i.e. either / or NULL or the empty string or any equivalent. */ + + if (!root) + return true; + + return root[strspn(root, "/")] == 0; +} diff --git a/src/basic/path-util.h b/src/basic/path-util.h new file mode 100644 index 00000000..111d85d4 --- /dev/null +++ b/src/basic/path-util.h @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "macro.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" + +#define PATH_SPLIT_SBIN_BIN(x) x "sbin:" x "bin" +#define PATH_SPLIT_SBIN_BIN_NULSTR(x) x "sbin\0" x "bin\0" + +#define PATH_NORMAL_SBIN_BIN(x) x "bin" +#define PATH_NORMAL_SBIN_BIN_NULSTR(x) x "bin\0" + +#if HAVE_SPLIT_BIN +# define PATH_SBIN_BIN(x) PATH_SPLIT_SBIN_BIN(x) +# define PATH_SBIN_BIN_NULSTR(x) PATH_SPLIT_SBIN_BIN_NULSTR(x) +#else +# define PATH_SBIN_BIN(x) PATH_NORMAL_SBIN_BIN(x) +# define PATH_SBIN_BIN_NULSTR(x) PATH_NORMAL_SBIN_BIN_NULSTR(x) +#endif + +#define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/") +#define DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/usr/local/") PATH_SBIN_BIN_NULSTR("/usr/") +#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/") +#define DEFAULT_PATH_SPLIT_USR_NULSTR DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/") +#define DEFAULT_PATH_COMPAT PATH_SPLIT_SBIN_BIN("/usr/local/") ":" PATH_SPLIT_SBIN_BIN("/usr/") ":" PATH_SPLIT_SBIN_BIN("/") + +#if HAVE_SPLIT_USR +# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR +# define DEFAULT_PATH_NULSTR DEFAULT_PATH_SPLIT_USR_NULSTR +#else +# define DEFAULT_PATH DEFAULT_PATH_NORMAL +# define DEFAULT_PATH_NULSTR DEFAULT_PATH_NORMAL_NULSTR +#endif + +#ifndef DEFAULT_USER_PATH +# define DEFAULT_USER_PATH DEFAULT_PATH +#endif + +bool is_path(const char *p) _pure_; +int path_split_and_make_absolute(const char *p, char ***ret); +bool path_is_absolute(const char *p) _pure_; +char* path_make_absolute(const char *p, const char *prefix); +int safe_getcwd(char **ret); +int path_make_absolute_cwd(const char *p, char **ret); +int path_make_relative(const char *from_dir, const char *to_path, char **_r); +char* path_startswith(const char *path, const char *prefix) _pure_; +int path_compare(const char *a, const char *b) _pure_; +bool path_equal(const char *a, const char *b) _pure_; +bool path_equal_or_files_same(const char *a, const char *b, int flags); +char* path_join_internal(const char *first, ...); +#define path_join(x, ...) path_join_internal(x, __VA_ARGS__, (const char*) -1) + +char* path_simplify(char *path, bool kill_dots); + +enum { + PATH_CHECK_FATAL = 1 << 0, /* If not set, then error message is appended with 'ignoring'. */ + PATH_CHECK_ABSOLUTE = 1 << 1, + PATH_CHECK_RELATIVE = 1 << 2, +}; + +int path_simplify_and_warn(char *path, unsigned flag, const char *unit, const char *filename, unsigned line, const char *lvalue); + +static inline bool path_equal_ptr(const char *a, const char *b) { + return !!a == !!b && (!a || path_equal(a, b)); +} + +/* Note: the search terminates on the first NULL item. */ +#define PATH_IN_SET(p, ...) \ + ({ \ + char **_s; \ + bool _found = false; \ + STRV_FOREACH(_s, STRV_MAKE(__VA_ARGS__)) \ + if (path_equal(p, *_s)) { \ + _found = true; \ + break; \ + } \ + _found; \ + }) + +char* path_startswith_strv(const char *p, char **set); +#define PATH_STARTSWITH_SET(p, ...) path_startswith_strv(p, STRV_MAKE(__VA_ARGS__)) + +int path_strv_make_absolute_cwd(char **l); +char** path_strv_resolve(char **l, const char *root); +char** path_strv_resolve_uniq(char **l, const char *root); + +int find_binary(const char *name, char **filename); + +bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update); + +int fsck_exists(const char *fstype); +int mkfs_exists(const char *fstype); + +/* Iterates through the path prefixes of the specified path, going up + * the tree, to root. Also returns "" (and not "/"!) for the root + * directory. Excludes the specified directory itself */ +#define PATH_FOREACH_PREFIX(prefix, path) \ + for (char *_slash = ({ \ + path_simplify(strcpy(prefix, path), false); \ + streq(prefix, "/") ? NULL : strrchr(prefix, '/'); \ + }); \ + _slash && ((*_slash = 0), true); \ + _slash = strrchr((prefix), '/')) + +/* Same as PATH_FOREACH_PREFIX but also includes the specified path itself */ +#define PATH_FOREACH_PREFIX_MORE(prefix, path) \ + for (char *_slash = ({ \ + path_simplify(strcpy(prefix, path), false); \ + if (streq(prefix, "/")) \ + prefix[0] = 0; \ + strrchr(prefix, 0); \ + }); \ + _slash && ((*_slash = 0), true); \ + _slash = strrchr((prefix), '/')) + +/* Similar to path_join(), but only works for two components, and only the first one may be NULL and returns + * an alloca() buffer, or possibly a const pointer into the path parameter. */ +#define prefix_roota(root, path) \ + ({ \ + const char* _path = (path), *_root = (root), *_ret; \ + char *_p, *_n; \ + size_t _l; \ + while (_path[0] == '/' && _path[1] == '/') \ + _path ++; \ + if (isempty(_root)) \ + _ret = _path; \ + else { \ + _l = strlen(_root) + 1 + strlen(_path) + 1; \ + _n = newa(char, _l); \ + _p = stpcpy(_n, _root); \ + while (_p > _n && _p[-1] == '/') \ + _p--; \ + if (_path[0] != '/') \ + *(_p++) = '/'; \ + strcpy(_p, _path); \ + _ret = _n; \ + } \ + _ret; \ + }) + +int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg); + +char* dirname_malloc(const char *path); +const char *last_path_component(const char *path); +int path_extract_filename(const char *p, char **ret); + +bool filename_is_valid(const char *p) _pure_; +bool path_is_valid(const char *p) _pure_; +bool path_is_normalized(const char *p) _pure_; + +char *file_in_same_dir(const char *path, const char *filename); + +bool hidden_or_backup_file(const char *filename) _pure_; + +bool is_device_path(const char *path); + +bool valid_device_node_path(const char *path); +bool valid_device_allow_pattern(const char *path); + +int systemd_installation_has_version(const char *root, unsigned minimal_version); + +bool dot_or_dot_dot(const char *path); + +static inline const char *skip_dev_prefix(const char *p) { + const char *e; + + /* Drop any /dev prefix if there is any */ + + e = path_startswith(p, "/dev/"); + + return e ?: p; +} + +bool empty_or_root(const char *root); +static inline const char *empty_to_root(const char *path) { + return isempty(path) ? "/" : path; +} diff --git a/src/basic/prioq.c b/src/basic/prioq.c new file mode 100644 index 00000000..76b27fa0 --- /dev/null +++ b/src/basic/prioq.c @@ -0,0 +1,300 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +/* + * Priority Queue + * The prioq object implements a priority queue. That is, it orders objects by + * their priority and allows O(1) access to the object with the highest + * priority. Insertion and removal are Θ(log n). Optionally, the caller can + * provide a pointer to an index which will be kept up-to-date by the prioq. + * + * The underlying algorithm used in this implementation is a Heap. + */ + +#include +#include + +#include "alloc-util.h" +#include "hashmap.h" +#include "prioq.h" + +struct prioq_item { + void *data; + unsigned *idx; +}; + +struct Prioq { + compare_func_t compare_func; + unsigned n_items, n_allocated; + + struct prioq_item *items; +}; + +Prioq *prioq_new(compare_func_t compare_func) { + Prioq *q; + + q = new(Prioq, 1); + if (!q) + return q; + + *q = (Prioq) { + .compare_func = compare_func, + }; + + return q; +} + +Prioq* prioq_free(Prioq *q) { + if (!q) + return NULL; + + free(q->items); + return mfree(q); +} + +int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func) { + assert(q); + + if (*q) + return 0; + + *q = prioq_new(compare_func); + if (!*q) + return -ENOMEM; + + return 0; +} + +static void swap(Prioq *q, unsigned j, unsigned k) { + assert(q); + assert(j < q->n_items); + assert(k < q->n_items); + + assert(!q->items[j].idx || *(q->items[j].idx) == j); + assert(!q->items[k].idx || *(q->items[k].idx) == k); + + SWAP_TWO(q->items[j].data, q->items[k].data); + SWAP_TWO(q->items[j].idx, q->items[k].idx); + + if (q->items[j].idx) + *q->items[j].idx = j; + + if (q->items[k].idx) + *q->items[k].idx = k; +} + +static unsigned shuffle_up(Prioq *q, unsigned idx) { + assert(q); + assert(idx < q->n_items); + + while (idx > 0) { + unsigned k; + + k = (idx-1)/2; + + if (q->compare_func(q->items[k].data, q->items[idx].data) <= 0) + break; + + swap(q, idx, k); + idx = k; + } + + return idx; +} + +static unsigned shuffle_down(Prioq *q, unsigned idx) { + assert(q); + + for (;;) { + unsigned j, k, s; + + k = (idx+1)*2; /* right child */ + j = k-1; /* left child */ + + if (j >= q->n_items) + break; + + if (q->compare_func(q->items[j].data, q->items[idx].data) < 0) + + /* So our left child is smaller than we are, let's + * remember this fact */ + s = j; + else + s = idx; + + if (k < q->n_items && + q->compare_func(q->items[k].data, q->items[s].data) < 0) + + /* So our right child is smaller than we are, let's + * remember this fact */ + s = k; + + /* s now points to the smallest of the three items */ + + if (s == idx) + /* No swap necessary, we're done */ + break; + + swap(q, idx, s); + idx = s; + } + + return idx; +} + +int prioq_put(Prioq *q, void *data, unsigned *idx) { + struct prioq_item *i; + unsigned k; + + assert(q); + + if (q->n_items >= q->n_allocated) { + unsigned n; + struct prioq_item *j; + + n = MAX((q->n_items+1) * 2, 16u); + j = reallocarray(q->items, n, sizeof(struct prioq_item)); + if (!j) + return -ENOMEM; + + q->items = j; + q->n_allocated = n; + } + + k = q->n_items++; + i = q->items + k; + i->data = data; + i->idx = idx; + + if (idx) + *idx = k; + + shuffle_up(q, k); + + return 0; +} + +static void remove_item(Prioq *q, struct prioq_item *i) { + struct prioq_item *l; + + assert(q); + assert(i); + + l = q->items + q->n_items - 1; + + if (i == l) + /* Last entry, let's just remove it */ + q->n_items--; + else { + unsigned k; + + /* Not last entry, let's replace the last entry with + * this one, and reshuffle */ + + k = i - q->items; + + i->data = l->data; + i->idx = l->idx; + if (i->idx) + *i->idx = k; + q->n_items--; + + k = shuffle_down(q, k); + shuffle_up(q, k); + } +} + +_pure_ static struct prioq_item* find_item(Prioq *q, void *data, unsigned *idx) { + struct prioq_item *i; + + assert(q); + + if (q->n_items <= 0) + return NULL; + + if (idx) { + if (*idx == PRIOQ_IDX_NULL || + *idx >= q->n_items) + return NULL; + + i = q->items + *idx; + if (i->data != data) + return NULL; + + return i; + } else { + for (i = q->items; i < q->items + q->n_items; i++) + if (i->data == data) + return i; + return NULL; + } +} + +int prioq_remove(Prioq *q, void *data, unsigned *idx) { + struct prioq_item *i; + + if (!q) + return 0; + + i = find_item(q, data, idx); + if (!i) + return 0; + + remove_item(q, i); + return 1; +} + +int prioq_reshuffle(Prioq *q, void *data, unsigned *idx) { + struct prioq_item *i; + unsigned k; + + assert(q); + + i = find_item(q, data, idx); + if (!i) + return 0; + + k = i - q->items; + k = shuffle_down(q, k); + shuffle_up(q, k); + return 1; +} + +void *prioq_peek_by_index(Prioq *q, unsigned idx) { + if (!q) + return NULL; + + if (idx >= q->n_items) + return NULL; + + return q->items[idx].data; +} + +void *prioq_pop(Prioq *q) { + void *data; + + if (!q) + return NULL; + + if (q->n_items <= 0) + return NULL; + + data = q->items[0].data; + remove_item(q, q->items); + return data; +} + +unsigned prioq_size(Prioq *q) { + + if (!q) + return 0; + + return q->n_items; +} + +bool prioq_isempty(Prioq *q) { + + if (!q) + return true; + + return q->n_items <= 0; +} diff --git a/src/basic/prioq.h b/src/basic/prioq.h new file mode 100644 index 00000000..1fb57bfa --- /dev/null +++ b/src/basic/prioq.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "hashmap.h" +#include "macro.h" + +typedef struct Prioq Prioq; + +#define PRIOQ_IDX_NULL ((unsigned) -1) + +Prioq *prioq_new(compare_func_t compare); +Prioq *prioq_free(Prioq *q); +DEFINE_TRIVIAL_CLEANUP_FUNC(Prioq*, prioq_free); +int prioq_ensure_allocated(Prioq **q, compare_func_t compare_func); + +int prioq_put(Prioq *q, void *data, unsigned *idx); +int prioq_remove(Prioq *q, void *data, unsigned *idx); +int prioq_reshuffle(Prioq *q, void *data, unsigned *idx); + +void *prioq_peek_by_index(Prioq *q, unsigned idx) _pure_; +static inline void *prioq_peek(Prioq *q) { + return prioq_peek_by_index(q, 0); +} +void *prioq_pop(Prioq *q); + +#define PRIOQ_FOREACH_ITEM(q, p) \ + for (unsigned _i = 0; (p = prioq_peek_by_index(q, _i)); _i++) + +unsigned prioq_size(Prioq *q) _pure_; +bool prioq_isempty(Prioq *q) _pure_; diff --git a/src/basic/proc-cmdline.c b/src/basic/proc-cmdline.c new file mode 100644 index 00000000..1af58717 --- /dev/null +++ b/src/basic/proc-cmdline.c @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "efivars.h" +#include "extract-word.h" +#include "fileio.h" +#include "macro.h" +#include "parse-util.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "special.h" +#include "string-util.h" +#include "util.h" +#include "virt.h" + +int proc_cmdline(char **ret) { + const char *e; + assert(ret); + + /* For testing purposes it is sometimes useful to be able to override what we consider /proc/cmdline to be */ + e = secure_getenv("SYSTEMD_PROC_CMDLINE"); + if (e) { + char *m; + + m = strdup(e); + if (!m) + return -ENOMEM; + + *ret = m; + return 0; + } + + if (detect_container() > 0) + return get_process_cmdline(1, SIZE_MAX, 0, ret); + else + return read_one_line_file("/proc/cmdline", ret); +} + +/* In SecureBoot mode this is probably not what you want. As your cmdline is + * cryptographically signed like when using Type #2 EFI Unified Kernel Images + * (https://systemd.io/BOOT_LOADER_SPECIFICATION/) The user's intention is then + * that the cmdline should not be modified. You want to make sure that the + * system starts up as exactly specified in the signed artifact. */ +static int systemd_options_variable(char **line) { + if (is_efi_secure_boot()) + return -ENODATA; + + return systemd_efi_options_variable(line); +} + +static int proc_cmdline_extract_first(const char **p, char **ret_word, ProcCmdlineFlags flags) { + const char *q = *p; + int r; + + for (;;) { + _cleanup_free_ char *word = NULL; + const char *c; + + r = extract_first_word(&q, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX); + if (r < 0) + return r; + if (r == 0) + break; + + /* Filter out arguments that are intended only for the initrd */ + c = startswith(word, "rd."); + if (c) { + if (!in_initrd()) + continue; + + if (FLAGS_SET(flags, PROC_CMDLINE_STRIP_RD_PREFIX)) { + r = free_and_strdup(&word, c); + if (r < 0) + return r; + } + + } else if (FLAGS_SET(flags, PROC_CMDLINE_RD_STRICT) && in_initrd()) + continue; /* And optionally filter out arguments that are intended only for the host */ + + *p = q; + *ret_word = TAKE_PTR(word); + return 1; + } + + *p = q; + *ret_word = NULL; + return 0; +} + +int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) { + const char *p; + int r; + + assert(parse_item); + + /* The PROC_CMDLINE_VALUE_OPTIONAL flag doesn't really make sense for proc_cmdline_parse(), let's make this + * clear. */ + assert(!FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL)); + + p = line; + for (;;) { + _cleanup_free_ char *word = NULL; + char *value; + + r = proc_cmdline_extract_first(&p, &word, flags); + if (r < 0) + return r; + if (r == 0) + break; + + value = strchr(word, '='); + if (value) + *(value++) = 0; + + r = parse_item(word, value, data); + if (r < 0) + return r; + } + + return 0; +} + +int proc_cmdline_parse(proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags) { + _cleanup_free_ char *line = NULL; + int r; + + assert(parse_item); + + /* We parse the EFI variable first, because later settings have higher priority. */ + + r = systemd_options_variable(&line); + if (r < 0 && r != -ENODATA) + log_debug_errno(r, "Failed to get SystemdOptions EFI variable, ignoring: %m"); + + r = proc_cmdline_parse_given(line, parse_item, data, flags); + if (r < 0) + return r; + + line = mfree(line); + r = proc_cmdline(&line); + if (r < 0) + return r; + + return proc_cmdline_parse_given(line, parse_item, data, flags); +} + +static bool relaxed_equal_char(char a, char b) { + return a == b || + (a == '_' && b == '-') || + (a == '-' && b == '_'); +} + +char *proc_cmdline_key_startswith(const char *s, const char *prefix) { + assert(s); + assert(prefix); + + /* Much like startswith(), but considers "-" and "_" the same */ + + for (; *prefix != 0; s++, prefix++) + if (!relaxed_equal_char(*s, *prefix)) + return NULL; + + return (char*) s; +} + +bool proc_cmdline_key_streq(const char *x, const char *y) { + assert(x); + assert(y); + + /* Much like streq(), but considers "-" and "_" the same */ + + for (; *x != 0 || *y != 0; x++, y++) + if (!relaxed_equal_char(*x, *y)) + return false; + + return true; +} + +static int cmdline_get_key(const char *line, const char *key, ProcCmdlineFlags flags, char **ret_value) { + _cleanup_free_ char *ret = NULL; + bool found = false; + const char *p; + int r; + + assert(line); + assert(key); + + p = line; + for (;;) { + _cleanup_free_ char *word = NULL; + + r = proc_cmdline_extract_first(&p, &word, flags); + if (r < 0) + return r; + if (r == 0) + break; + + if (ret_value) { + const char *e; + + e = proc_cmdline_key_startswith(word, key); + if (!e) + continue; + + if (*e == '=') { + r = free_and_strdup(&ret, e+1); + if (r < 0) + return r; + + found = true; + + } else if (*e == 0 && FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL)) + found = true; + + } else { + if (streq(word, key)) { + found = true; + break; /* we found what we were looking for */ + } + } + } + + if (ret_value) + *ret_value = TAKE_PTR(ret); + + return found; +} + +int proc_cmdline_get_key(const char *key, ProcCmdlineFlags flags, char **ret_value) { + _cleanup_free_ char *line = NULL; + int r; + + /* Looks for a specific key on the kernel command line and (with lower priority) the EFI variable. + * Supports three modes: + * + * a) The "ret_value" parameter is used. In this case a parameter beginning with the "key" string followed by + * "=" is searched for, and the value following it is returned in "ret_value". + * + * b) as above, but the PROC_CMDLINE_VALUE_OPTIONAL flag is set. In this case if the key is found as a separate + * word (i.e. not followed by "=" but instead by whitespace or the end of the command line), then this is + * also accepted, and "value" is returned as NULL. + * + * c) The "ret_value" parameter is NULL. In this case a search for the exact "key" parameter is performed. + * + * In all three cases, > 0 is returned if the key is found, 0 if not. */ + + if (isempty(key)) + return -EINVAL; + + if (FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL) && !ret_value) + return -EINVAL; + + r = proc_cmdline(&line); + if (r < 0) + return r; + + r = cmdline_get_key(line, key, flags, ret_value); + if (r != 0) /* Either error or true if found. */ + return r; + + line = mfree(line); + r = systemd_options_variable(&line); + if (r == -ENODATA) + return false; /* Not found */ + if (r < 0) + return r; + + return cmdline_get_key(line, key, flags, ret_value); +} + +int proc_cmdline_get_bool(const char *key, bool *ret) { + _cleanup_free_ char *v = NULL; + int r; + + assert(ret); + + r = proc_cmdline_get_key(key, PROC_CMDLINE_VALUE_OPTIONAL, &v); + if (r < 0) + return r; + if (r == 0) { + *ret = false; + return 0; + } + + if (v) { /* parameter passed */ + r = parse_boolean(v); + if (r < 0) + return r; + *ret = r; + } else /* no parameter passed */ + *ret = true; + + return 1; +} + +int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...) { + _cleanup_free_ char *line = NULL; + const char *p; + va_list ap; + int r, ret = 0; + + /* The PROC_CMDLINE_VALUE_OPTIONAL flag doesn't really make sense for proc_cmdline_get_key_many(), let's make + * this clear. */ + assert(!FLAGS_SET(flags, PROC_CMDLINE_VALUE_OPTIONAL)); + + /* This call may clobber arguments on failure! */ + + r = proc_cmdline(&line); + if (r < 0) + return r; + + p = line; + for (;;) { + _cleanup_free_ char *word = NULL; + + r = proc_cmdline_extract_first(&p, &word, flags); + if (r < 0) + return r; + if (r == 0) + break; + + va_start(ap, flags); + + for (;;) { + char **v; + const char *k, *e; + + k = va_arg(ap, const char*); + if (!k) + break; + + assert_se(v = va_arg(ap, char**)); + + e = proc_cmdline_key_startswith(word, k); + if (e && *e == '=') { + r = free_and_strdup(v, e + 1); + if (r < 0) { + va_end(ap); + return r; + } + + ret++; + } + } + + va_end(ap); + } + + return ret; +} diff --git a/src/basic/proc-cmdline.h b/src/basic/proc-cmdline.h new file mode 100644 index 00000000..4115fdbc --- /dev/null +++ b/src/basic/proc-cmdline.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "log.h" + +typedef enum ProcCmdlineFlags { + PROC_CMDLINE_STRIP_RD_PREFIX = 1 << 0, + PROC_CMDLINE_VALUE_OPTIONAL = 1 << 1, + PROC_CMDLINE_RD_STRICT = 1 << 2, +} ProcCmdlineFlags; + +typedef int (*proc_cmdline_parse_t)(const char *key, const char *value, void *data); + +int proc_cmdline(char **ret); + +int proc_cmdline_parse_given(const char *line, proc_cmdline_parse_t parse_item, void *data, ProcCmdlineFlags flags); +int proc_cmdline_parse(const proc_cmdline_parse_t parse, void *userdata, ProcCmdlineFlags flags); + +int proc_cmdline_get_key(const char *parameter, ProcCmdlineFlags flags, char **value); +int proc_cmdline_get_bool(const char *key, bool *ret); + +int proc_cmdline_get_key_many_internal(ProcCmdlineFlags flags, ...); +#define proc_cmdline_get_key_many(flags, ...) proc_cmdline_get_key_many_internal(flags, __VA_ARGS__, NULL) + +char *proc_cmdline_key_startswith(const char *s, const char *prefix); +bool proc_cmdline_key_streq(const char *x, const char *y); + +/* A little helper call, to be used in proc_cmdline_parse_t callbacks */ +static inline bool proc_cmdline_value_missing(const char *key, const char *value) { + if (!value) { + log_warning("Missing argument for %s= kernel command line switch, ignoring.", key); + return true; + } + + return false; +} diff --git a/src/basic/process-util.c b/src/basic/process-util.c new file mode 100644 index 00000000..9b6c4c31 --- /dev/null +++ b/src/basic/process-util.c @@ -0,0 +1,1519 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_VALGRIND_VALGRIND_H +#include +#endif + +#include "alloc-util.h" +#include "architecture.h" +#include "env-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "ioprio.h" +#include "locale-util.h" +#include "log.h" +#include "macro.h" +#include "memory-util.h" +#include "missing_sched.h" +#include "missing_syscall.h" +#include "namespace-util.h" +#include "path-util.h" +#include "process-util.h" +#include "raw-clone.h" +#include "rlimit-util.h" +#include "signal-util.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "terminal-util.h" +#include "user-util.h" +#include "utf8.h" + +/* The kernel limits userspace processes to TASK_COMM_LEN (16 bytes), but allows higher values for its own + * workers, e.g. "kworker/u9:3-kcryptd/253:0". Let's pick a fixed smallish limit that will work for the kernel. + */ +#define COMM_MAX_LEN 128 + +static int get_process_state(pid_t pid) { + _cleanup_free_ char *line = NULL; + const char *p; + char state; + int r; + + assert(pid >= 0); + + /* Shortcut: if we are enquired about our own state, we are obviously running */ + if (pid == 0 || pid == getpid_cached()) + return (unsigned char) 'R'; + + p = procfs_file_alloca(pid, "stat"); + + r = read_one_line_file(p, &line); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + + p = strrchr(line, ')'); + if (!p) + return -EIO; + + p++; + + if (sscanf(p, " %c", &state) != 1) + return -EIO; + + return (unsigned char) state; +} + +int get_process_comm(pid_t pid, char **ret) { + _cleanup_free_ char *escaped = NULL, *comm = NULL; + int r; + + assert(ret); + assert(pid >= 0); + + if (pid == 0 || pid == getpid_cached()) { + comm = new0(char, TASK_COMM_LEN + 1); /* Must fit in 16 byte according to prctl(2) */ + if (!comm) + return -ENOMEM; + + if (prctl(PR_GET_NAME, comm) < 0) + return -errno; + } else { + const char *p; + + p = procfs_file_alloca(pid, "comm"); + + /* Note that process names of kernel threads can be much longer than TASK_COMM_LEN */ + r = read_one_line_file(p, &comm); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + } + + escaped = new(char, COMM_MAX_LEN); + if (!escaped) + return -ENOMEM; + + /* Escape unprintable characters, just in case, but don't grow the string beyond the underlying size */ + cellescape(escaped, COMM_MAX_LEN, comm); + + *ret = TAKE_PTR(escaped); + return 0; +} + +int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *t = NULL, *ans = NULL; + const char *p; + int r; + size_t k; + + /* This is supposed to be a safety guard against runaway command lines. */ + size_t max_length = sc_arg_max(); + + assert(line); + assert(pid >= 0); + + /* Retrieves a process' command line. Replaces non-utf8 bytes by replacement character (�). If + * max_columns is != -1 will return a string of the specified console width at most, abbreviated with + * an ellipsis. If PROCESS_CMDLINE_COMM_FALLBACK is specified in flags and the process has no command + * line set (the case for kernel threads), or has a command line that resolves to the empty string + * will return the "comm" name of the process instead. This will use at most _SC_ARG_MAX bytes of + * input data. + * + * Returns -ESRCH if the process doesn't exist, and -ENOENT if the process has no command line (and + * comm_fallback is false). Returns 0 and sets *line otherwise. */ + + p = procfs_file_alloca(pid, "cmdline"); + r = fopen_unlocked(p, "re", &f); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + + /* We assume that each four-byte character uses one or two columns. If we ever check for combining + * characters, this assumption will need to be adjusted. */ + if ((size_t) 4 * max_columns + 1 < max_columns) + max_length = MIN(max_length, (size_t) 4 * max_columns + 1); + + t = new(char, max_length); + if (!t) + return -ENOMEM; + + k = fread(t, 1, max_length, f); + if (k > 0) { + /* Arguments are separated by NULs. Let's replace those with spaces. */ + for (size_t i = 0; i < k - 1; i++) + if (t[i] == '\0') + t[i] = ' '; + + t[k] = '\0'; /* Normally, t[k] is already NUL, so this is just a guard in case of short read */ + } else { + /* We only treat getting nothing as an error. We *could* also get an error after reading some + * data, but we ignore that case, as such an error is rather unlikely and we prefer to get + * some data rather than none. */ + if (ferror(f)) + return -errno; + + if (!(flags & PROCESS_CMDLINE_COMM_FALLBACK)) + return -ENOENT; + + /* Kernel threads have no argv[] */ + _cleanup_free_ char *t2 = NULL; + + r = get_process_comm(pid, &t2); + if (r < 0) + return r; + + mfree(t); + t = strjoin("[", t2, "]"); + if (!t) + return -ENOMEM; + } + + delete_trailing_chars(t, WHITESPACE); + + bool eight_bit = (flags & PROCESS_CMDLINE_USE_LOCALE) && !is_locale_utf8(); + + ans = escape_non_printable_full(t, max_columns, eight_bit); + if (!ans) + return -ENOMEM; + + (void) str_realloc(&ans); + *line = TAKE_PTR(ans); + return 0; +} + +int rename_process(const char name[]) { + static size_t mm_size = 0; + static char *mm = NULL; + bool truncated = false; + size_t l; + + /* This is a like a poor man's setproctitle(). It changes the comm field, argv[0], and also the glibc's + * internally used name of the process. For the first one a limit of 16 chars applies; to the second one in + * many cases one of 10 (i.e. length of "/sbin/init") — however if we have CAP_SYS_RESOURCES it is unbounded; + * to the third one 7 (i.e. the length of "systemd". If you pass a longer string it will likely be + * truncated. + * + * Returns 0 if a name was set but truncated, > 0 if it was set but not truncated. */ + + if (isempty(name)) + return -EINVAL; /* let's not confuse users unnecessarily with an empty name */ + + if (!is_main_thread()) + return -EPERM; /* Let's not allow setting the process name from other threads than the main one, as we + * cache things without locking, and we make assumptions that PR_SET_NAME sets the + * process name that isn't correct on any other threads */ + + l = strlen(name); + + /* First step, change the comm field. The main thread's comm is identical to the process comm. This means we + * can use PR_SET_NAME, which sets the thread name for the calling thread. */ + if (prctl(PR_SET_NAME, name) < 0) + log_debug_errno(errno, "PR_SET_NAME failed: %m"); + if (l >= TASK_COMM_LEN) /* Linux userspace process names can be 15 chars at max */ + truncated = true; + + /* Second step, change glibc's ID of the process name. */ + if (program_invocation_name) { + size_t k; + + k = strlen(program_invocation_name); + strncpy(program_invocation_name, name, k); + if (l > k) + truncated = true; + } + + /* Third step, completely replace the argv[] array the kernel maintains for us. This requires privileges, but + * has the advantage that the argv[] array is exactly what we want it to be, and not filled up with zeros at + * the end. This is the best option for changing /proc/self/cmdline. */ + + /* Let's not bother with this if we don't have euid == 0. Strictly speaking we should check for the + * CAP_SYS_RESOURCE capability which is independent of the euid. In our own code the capability generally is + * present only for euid == 0, hence let's use this as quick bypass check, to avoid calling mmap() if + * PR_SET_MM_ARG_{START,END} fails with EPERM later on anyway. After all geteuid() is dead cheap to call, but + * mmap() is not. */ + if (geteuid() != 0) + log_debug("Skipping PR_SET_MM, as we don't have privileges."); + else if (mm_size < l+1) { + size_t nn_size; + char *nn; + + nn_size = PAGE_ALIGN(l+1); + nn = mmap(NULL, nn_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (nn == MAP_FAILED) { + log_debug_errno(errno, "mmap() failed: %m"); + goto use_saved_argv; + } + + strncpy(nn, name, nn_size); + + /* Now, let's tell the kernel about this new memory */ + if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) { + /* HACK: prctl() API is kind of dumb on this point. The existing end address may already be + * below the desired start address, in which case the kernel may have kicked this back due + * to a range-check failure (see linux/kernel/sys.c:validate_prctl_map() to see this in + * action). The proper solution would be to have a prctl() API that could set both start+end + * simultaneously, or at least let us query the existing address to anticipate this condition + * and respond accordingly. For now, we can only guess at the cause of this failure and try + * a workaround--which will briefly expand the arg space to something potentially huge before + * resizing it to what we want. */ + log_debug_errno(errno, "PR_SET_MM_ARG_START failed, attempting PR_SET_MM_ARG_END hack: %m"); + + if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) { + log_debug_errno(errno, "PR_SET_MM_ARG_END hack failed, proceeding without: %m"); + (void) munmap(nn, nn_size); + goto use_saved_argv; + } + + if (prctl(PR_SET_MM, PR_SET_MM_ARG_START, (unsigned long) nn, 0, 0) < 0) { + log_debug_errno(errno, "PR_SET_MM_ARG_START still failed, proceeding without: %m"); + goto use_saved_argv; + } + } else { + /* And update the end pointer to the new end, too. If this fails, we don't really know what + * to do, it's pretty unlikely that we can rollback, hence we'll just accept the failure, + * and continue. */ + if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) nn + l + 1, 0, 0) < 0) + log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m"); + } + + if (mm) + (void) munmap(mm, mm_size); + + mm = nn; + mm_size = nn_size; + } else { + strncpy(mm, name, mm_size); + + /* Update the end pointer, continuing regardless of any failure. */ + if (prctl(PR_SET_MM, PR_SET_MM_ARG_END, (unsigned long) mm + l + 1, 0, 0) < 0) + log_debug_errno(errno, "PR_SET_MM_ARG_END failed, proceeding without: %m"); + } + +use_saved_argv: + /* Fourth step: in all cases we'll also update the original argv[], so that our own code gets it right too if + * it still looks here */ + + if (saved_argc > 0) { + int i; + + if (saved_argv[0]) { + size_t k; + + k = strlen(saved_argv[0]); + strncpy(saved_argv[0], name, k); + if (l > k) + truncated = true; + } + + for (i = 1; i < saved_argc; i++) { + if (!saved_argv[i]) + break; + + memzero(saved_argv[i], strlen(saved_argv[i])); + } + } + + return !truncated; +} + +int is_kernel_thread(pid_t pid) { + _cleanup_free_ char *line = NULL; + unsigned long long flags; + size_t l, i; + const char *p; + char *q; + int r; + + if (IN_SET(pid, 0, 1) || pid == getpid_cached()) /* pid 1, and we ourselves certainly aren't a kernel thread */ + return 0; + if (!pid_is_valid(pid)) + return -EINVAL; + + p = procfs_file_alloca(pid, "stat"); + r = read_one_line_file(p, &line); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + + /* Skip past the comm field */ + q = strrchr(line, ')'); + if (!q) + return -EINVAL; + q++; + + /* Skip 6 fields to reach the flags field */ + for (i = 0; i < 6; i++) { + l = strspn(q, WHITESPACE); + if (l < 1) + return -EINVAL; + q += l; + + l = strcspn(q, WHITESPACE); + if (l < 1) + return -EINVAL; + q += l; + } + + /* Skip preceding whitespace */ + l = strspn(q, WHITESPACE); + if (l < 1) + return -EINVAL; + q += l; + + /* Truncate the rest */ + l = strcspn(q, WHITESPACE); + if (l < 1) + return -EINVAL; + q[l] = 0; + + r = safe_atollu(q, &flags); + if (r < 0) + return r; + + return !!(flags & PF_KTHREAD); +} + +int get_process_capeff(pid_t pid, char **capeff) { + const char *p; + int r; + + assert(capeff); + assert(pid >= 0); + + p = procfs_file_alloca(pid, "status"); + + r = get_proc_field(p, "CapEff", WHITESPACE, capeff); + if (r == -ENOENT) + return -ESRCH; + + return r; +} + +static int get_process_link_contents(const char *proc_file, char **name) { + int r; + + assert(proc_file); + assert(name); + + r = readlink_malloc(proc_file, name); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + + return 0; +} + +int get_process_exe(pid_t pid, char **name) { + const char *p; + char *d; + int r; + + assert(pid >= 0); + + p = procfs_file_alloca(pid, "exe"); + r = get_process_link_contents(p, name); + if (r < 0) + return r; + + d = endswith(*name, " (deleted)"); + if (d) + *d = '\0'; + + return 0; +} + +static int get_process_id(pid_t pid, const char *field, uid_t *uid) { + _cleanup_fclose_ FILE *f = NULL; + const char *p; + int r; + + assert(field); + assert(uid); + + if (pid < 0) + return -EINVAL; + + p = procfs_file_alloca(pid, "status"); + r = fopen_unlocked(p, "re", &f); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *line = NULL; + char *l; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + l = strstrip(line); + + if (startswith(l, field)) { + l += strlen(field); + l += strspn(l, WHITESPACE); + + l[strcspn(l, WHITESPACE)] = 0; + + return parse_uid(l, uid); + } + } + + return -EIO; +} + +int get_process_uid(pid_t pid, uid_t *uid) { + + if (pid == 0 || pid == getpid_cached()) { + *uid = getuid(); + return 0; + } + + return get_process_id(pid, "Uid:", uid); +} + +int get_process_gid(pid_t pid, gid_t *gid) { + + if (pid == 0 || pid == getpid_cached()) { + *gid = getgid(); + return 0; + } + + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + return get_process_id(pid, "Gid:", gid); +} + +int get_process_cwd(pid_t pid, char **cwd) { + const char *p; + + assert(pid >= 0); + + if (pid == 0 || pid == getpid_cached()) + return safe_getcwd(cwd); + + p = procfs_file_alloca(pid, "cwd"); + + return get_process_link_contents(p, cwd); +} + +int get_process_root(pid_t pid, char **root) { + const char *p; + + assert(pid >= 0); + + p = procfs_file_alloca(pid, "root"); + + return get_process_link_contents(p, root); +} + +#define ENVIRONMENT_BLOCK_MAX (5U*1024U*1024U) + +int get_process_environ(pid_t pid, char **env) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *outcome = NULL; + size_t allocated = 0, sz = 0; + const char *p; + int r; + + assert(pid >= 0); + assert(env); + + p = procfs_file_alloca(pid, "environ"); + + r = fopen_unlocked(p, "re", &f); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + + for (;;) { + char c; + + if (sz >= ENVIRONMENT_BLOCK_MAX) + return -ENOBUFS; + + if (!GREEDY_REALLOC(outcome, allocated, sz + 5)) + return -ENOMEM; + + r = safe_fgetc(f, &c); + if (r < 0) + return r; + if (r == 0) + break; + + if (c == '\0') + outcome[sz++] = '\n'; + else + sz += cescape_char(c, outcome + sz); + } + + outcome[sz] = '\0'; + *env = TAKE_PTR(outcome); + + return 0; +} + +int get_process_ppid(pid_t pid, pid_t *_ppid) { + int r; + _cleanup_free_ char *line = NULL; + long unsigned ppid; + const char *p; + + assert(pid >= 0); + assert(_ppid); + + if (pid == 0 || pid == getpid_cached()) { + *_ppid = getppid(); + return 0; + } + + p = procfs_file_alloca(pid, "stat"); + r = read_one_line_file(p, &line); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + + /* Let's skip the pid and comm fields. The latter is enclosed + * in () but does not escape any () in its value, so let's + * skip over it manually */ + + p = strrchr(line, ')'); + if (!p) + return -EIO; + + p++; + + if (sscanf(p, " " + "%*c " /* state */ + "%lu ", /* ppid */ + &ppid) != 1) + return -EIO; + + if ((long unsigned) (pid_t) ppid != ppid) + return -ERANGE; + + *_ppid = (pid_t) ppid; + + return 0; +} + +int wait_for_terminate(pid_t pid, siginfo_t *status) { + siginfo_t dummy; + + assert(pid >= 1); + + if (!status) + status = &dummy; + + for (;;) { + zero(*status); + + if (waitid(P_PID, pid, status, WEXITED) < 0) { + + if (errno == EINTR) + continue; + + return negative_errno(); + } + + return 0; + } +} + +/* + * Return values: + * < 0 : wait_for_terminate() failed to get the state of the + * process, the process was terminated by a signal, or + * failed for an unknown reason. + * >=0 : The process terminated normally, and its exit code is + * returned. + * + * That is, success is indicated by a return value of zero, and an + * error is indicated by a non-zero value. + * + * A warning is emitted if the process terminates abnormally, + * and also if it returns non-zero unless check_exit_code is true. + */ +int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) { + _cleanup_free_ char *buffer = NULL; + siginfo_t status; + int r, prio; + + assert(pid > 1); + + if (!name) { + r = get_process_comm(pid, &buffer); + if (r < 0) + log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pid); + else + name = buffer; + } + + prio = flags & WAIT_LOG_ABNORMAL ? LOG_ERR : LOG_DEBUG; + + r = wait_for_terminate(pid, &status); + if (r < 0) + return log_full_errno(prio, r, "Failed to wait for %s: %m", strna(name)); + + if (status.si_code == CLD_EXITED) { + if (status.si_status != EXIT_SUCCESS) + log_full(flags & WAIT_LOG_NON_ZERO_EXIT_STATUS ? LOG_ERR : LOG_DEBUG, + "%s failed with exit status %i.", strna(name), status.si_status); + else + log_debug("%s succeeded.", name); + + return status.si_status; + + } else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED)) { + + log_full(prio, "%s terminated by signal %s.", strna(name), signal_to_string(status.si_status)); + return -EPROTO; + } + + log_full(prio, "%s failed due to unknown reason.", strna(name)); + return -EPROTO; +} + +/* + * Return values: + * + * < 0 : wait_for_terminate_with_timeout() failed to get the state of the process, the process timed out, the process + * was terminated by a signal, or failed for an unknown reason. + * + * >=0 : The process terminated normally with no failures. + * + * Success is indicated by a return value of zero, a timeout is indicated by ETIMEDOUT, and all other child failure + * states are indicated by error is indicated by a non-zero value. + * + * This call assumes SIGCHLD has been blocked already, in particular before the child to wait for has been forked off + * to remain entirely race-free. + */ +int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) { + sigset_t mask; + int r; + usec_t until; + + assert_se(sigemptyset(&mask) == 0); + assert_se(sigaddset(&mask, SIGCHLD) == 0); + + /* Drop into a sigtimewait-based timeout. Waiting for the + * pid to exit. */ + until = now(CLOCK_MONOTONIC) + timeout; + for (;;) { + usec_t n; + siginfo_t status = {}; + struct timespec ts; + + n = now(CLOCK_MONOTONIC); + if (n >= until) + break; + + r = sigtimedwait(&mask, NULL, timespec_store(&ts, until - n)) < 0 ? -errno : 0; + /* Assuming we woke due to the child exiting. */ + if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) { + if (status.si_pid == pid) { + /* This is the correct child.*/ + if (status.si_code == CLD_EXITED) + return (status.si_status == 0) ? 0 : -EPROTO; + else + return -EPROTO; + } + } + /* Not the child, check for errors and proceed appropriately */ + if (r < 0) { + switch (r) { + case -EAGAIN: + /* Timed out, child is likely hung. */ + return -ETIMEDOUT; + case -EINTR: + /* Received a different signal and should retry */ + continue; + default: + /* Return any unexpected errors */ + return r; + } + } + } + + return -EPROTO; +} + +void sigkill_wait(pid_t pid) { + assert(pid > 1); + + if (kill(pid, SIGKILL) >= 0) + (void) wait_for_terminate(pid, NULL); +} + +void sigkill_waitp(pid_t *pid) { + PROTECT_ERRNO; + + if (!pid) + return; + if (*pid <= 1) + return; + + sigkill_wait(*pid); +} + +void sigterm_wait(pid_t pid) { + assert(pid > 1); + + if (kill_and_sigcont(pid, SIGTERM) >= 0) + (void) wait_for_terminate(pid, NULL); +} + +int kill_and_sigcont(pid_t pid, int sig) { + int r; + + r = kill(pid, sig) < 0 ? -errno : 0; + + /* If this worked, also send SIGCONT, unless we already just sent a SIGCONT, or SIGKILL was sent which isn't + * affected by a process being suspended anyway. */ + if (r >= 0 && !IN_SET(sig, SIGCONT, SIGKILL)) + (void) kill(pid, SIGCONT); + + return r; +} + +int getenv_for_pid(pid_t pid, const char *field, char **ret) { + _cleanup_fclose_ FILE *f = NULL; + char *value = NULL; + const char *path; + size_t l, sum = 0; + int r; + + assert(pid >= 0); + assert(field); + assert(ret); + + if (pid == 0 || pid == getpid_cached()) { + const char *e; + + e = getenv(field); + if (!e) { + *ret = NULL; + return 0; + } + + value = strdup(e); + if (!value) + return -ENOMEM; + + *ret = value; + return 1; + } + + if (!pid_is_valid(pid)) + return -EINVAL; + + path = procfs_file_alloca(pid, "environ"); + + r = fopen_unlocked(path, "re", &f); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) + return r; + + l = strlen(field); + for (;;) { + _cleanup_free_ char *line = NULL; + + if (sum > ENVIRONMENT_BLOCK_MAX) /* Give up searching eventually */ + return -ENOBUFS; + + r = read_nul_string(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) /* EOF */ + break; + + sum += r; + + if (strneq(line, field, l) && line[l] == '=') { + value = strdup(line + l + 1); + if (!value) + return -ENOMEM; + + *ret = value; + return 1; + } + } + + *ret = NULL; + return 0; +} + +int pid_is_my_child(pid_t pid) { + pid_t ppid; + int r; + + if (pid <= 1) + return false; + + r = get_process_ppid(pid, &ppid); + if (r < 0) + return r; + + return ppid == getpid_cached(); +} + +bool pid_is_unwaited(pid_t pid) { + /* Checks whether a PID is still valid at all, including a zombie */ + + if (pid < 0) + return false; + + if (pid <= 1) /* If we or PID 1 would be dead and have been waited for, this code would not be running */ + return true; + + if (pid == getpid_cached()) + return true; + + if (kill(pid, 0) >= 0) + return true; + + return errno != ESRCH; +} + +bool pid_is_alive(pid_t pid) { + int r; + + /* Checks whether a PID is still valid and not a zombie */ + + if (pid < 0) + return false; + + if (pid <= 1) /* If we or PID 1 would be a zombie, this code would not be running */ + return true; + + if (pid == getpid_cached()) + return true; + + r = get_process_state(pid); + if (IN_SET(r, -ESRCH, 'Z')) + return false; + + return true; +} + +int pid_from_same_root_fs(pid_t pid) { + const char *root; + + if (pid < 0) + return false; + + if (pid == 0 || pid == getpid_cached()) + return true; + + root = procfs_file_alloca(pid, "root"); + + return files_same(root, "/proc/1/root", 0); +} + +bool is_main_thread(void) { + static thread_local int cached = 0; + + if (_unlikely_(cached == 0)) + cached = getpid_cached() == gettid() ? 1 : -1; + + return cached > 0; +} + +_noreturn_ void freeze(void) { + + log_close(); + + /* Make sure nobody waits for us on a socket anymore */ + (void) close_all_fds(NULL, 0); + + sync(); + + /* Let's not freeze right away, but keep reaping zombies. */ + for (;;) { + int r; + siginfo_t si = {}; + + r = waitid(P_ALL, 0, &si, WEXITED); + if (r < 0 && errno != EINTR) + break; + } + + /* waitid() failed with an unexpected error, things are really borked. Freeze now! */ + for (;;) + pause(); +} + +bool oom_score_adjust_is_valid(int oa) { + return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX; +} + +unsigned long personality_from_string(const char *p) { + int architecture; + + if (!p) + return PERSONALITY_INVALID; + + /* Parse a personality specifier. We use our own identifiers that indicate specific ABIs, rather than just + * hints regarding the register size, since we want to keep things open for multiple locally supported ABIs for + * the same register size. */ + + architecture = architecture_from_string(p); + if (architecture < 0) + return PERSONALITY_INVALID; + + if (architecture == native_architecture()) + return PER_LINUX; +#ifdef SECONDARY_ARCHITECTURE + if (architecture == SECONDARY_ARCHITECTURE) + return PER_LINUX32; +#endif + + return PERSONALITY_INVALID; +} + +const char* personality_to_string(unsigned long p) { + int architecture = _ARCHITECTURE_INVALID; + + if (p == PER_LINUX) + architecture = native_architecture(); +#ifdef SECONDARY_ARCHITECTURE + else if (p == PER_LINUX32) + architecture = SECONDARY_ARCHITECTURE; +#endif + + if (architecture < 0) + return NULL; + + return architecture_to_string(architecture); +} + +int safe_personality(unsigned long p) { + int ret; + + /* So here's the deal, personality() is weirdly defined by glibc. In some cases it returns a failure via errno, + * and in others as negative return value containing an errno-like value. Let's work around this: this is a + * wrapper that uses errno if it is set, and uses the return value otherwise. And then it sets both errno and + * the return value indicating the same issue, so that we are definitely on the safe side. + * + * See https://github.com/systemd/systemd/issues/6737 */ + + errno = 0; + ret = personality(p); + if (ret < 0) { + if (errno != 0) + return -errno; + + errno = -ret; + } + + return ret; +} + +int opinionated_personality(unsigned long *ret) { + int current; + + /* Returns the current personality, or PERSONALITY_INVALID if we can't determine it. This function is a bit + * opinionated though, and ignores all the finer-grained bits and exotic personalities, only distinguishing the + * two most relevant personalities: PER_LINUX and PER_LINUX32. */ + + current = safe_personality(PERSONALITY_INVALID); + if (current < 0) + return current; + + if (((unsigned long) current & 0xffff) == PER_LINUX32) + *ret = PER_LINUX32; + else + *ret = PER_LINUX; + + return 0; +} + +void valgrind_summary_hack(void) { +#if HAVE_VALGRIND_VALGRIND_H + if (getpid_cached() == 1 && RUNNING_ON_VALGRIND) { + pid_t pid; + pid = raw_clone(SIGCHLD); + if (pid < 0) + log_emergency_errno(errno, "Failed to fork off valgrind helper: %m"); + else if (pid == 0) + exit(EXIT_SUCCESS); + else { + log_info("Spawned valgrind helper as PID "PID_FMT".", pid); + (void) wait_for_terminate(pid, NULL); + } + } +#endif +} + +int pid_compare_func(const pid_t *a, const pid_t *b) { + /* Suitable for usage in qsort() */ + return CMP(*a, *b); +} + +int ioprio_parse_priority(const char *s, int *ret) { + int i, r; + + assert(s); + assert(ret); + + r = safe_atoi(s, &i); + if (r < 0) + return r; + + if (!ioprio_priority_is_valid(i)) + return -EINVAL; + + *ret = i; + return 0; +} + +/* The cached PID, possible values: + * + * == UNSET [0] → cache not initialized yet + * == BUSY [-1] → some thread is initializing it at the moment + * any other → the cached PID + */ + +#define CACHED_PID_UNSET ((pid_t) 0) +#define CACHED_PID_BUSY ((pid_t) -1) + +static pid_t cached_pid = CACHED_PID_UNSET; + +void reset_cached_pid(void) { + /* Invoked in the child after a fork(), i.e. at the first moment the PID changed */ + cached_pid = CACHED_PID_UNSET; +} + +/* We use glibc __register_atfork() + __dso_handle directly here, as they are not included in the glibc + * headers. __register_atfork() is mostly equivalent to pthread_atfork(), but doesn't require us to link against + * libpthread, as it is part of glibc anyway. */ +extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void (*child) (void), void *dso_handle); +extern void* __dso_handle _weak_; + +pid_t getpid_cached(void) { + static bool installed = false; + pid_t current_value; + + /* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a + * system call each time. This restores glibc behaviour from before 2.24, when getpid() was unconditionally + * cached. Starting with 2.24 getpid() started to become prohibitively expensive when used for detecting when + * objects were used across fork()s. With this caching the old behaviour is somewhat restored. + * + * https://bugzilla.redhat.com/show_bug.cgi?id=1443976 + * https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c579f48edba88380635ab98cb612030e3ed8691e + */ + + current_value = __sync_val_compare_and_swap(&cached_pid, CACHED_PID_UNSET, CACHED_PID_BUSY); + + switch (current_value) { + + case CACHED_PID_UNSET: { /* Not initialized yet, then do so now */ + pid_t new_pid; + + new_pid = raw_getpid(); + + if (!installed) { + /* __register_atfork() either returns 0 or -ENOMEM, in its glibc implementation. Since it's + * only half-documented (glibc doesn't document it but LSB does — though only superficially) + * we'll check for errors only in the most generic fashion possible. */ + + if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) { + /* OOM? Let's try again later */ + cached_pid = CACHED_PID_UNSET; + return new_pid; + } + + installed = true; + } + + cached_pid = new_pid; + return new_pid; + } + + case CACHED_PID_BUSY: /* Somebody else is currently initializing */ + return raw_getpid(); + + default: /* Properly initialized */ + return current_value; + } +} + +int must_be_root(void) { + + if (geteuid() == 0) + return 0; + + return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be root."); +} + +int safe_fork_full( + const char *name, + const int except_fds[], + size_t n_except_fds, + ForkFlags flags, + pid_t *ret_pid) { + + pid_t original_pid, pid; + sigset_t saved_ss, ss; + bool block_signals = false; + int prio, r; + + /* A wrapper around fork(), that does a couple of important initializations in addition to mere forking. Always + * returns the child's PID in *ret_pid. Returns == 0 in the child, and > 0 in the parent. */ + + prio = flags & FORK_LOG ? LOG_ERR : LOG_DEBUG; + + original_pid = getpid_cached(); + + if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG)) { + /* We temporarily block all signals, so that the new child has them blocked initially. This way, we can + * be sure that SIGTERMs are not lost we might send to the child. */ + + assert_se(sigfillset(&ss) >= 0); + block_signals = true; + + } else if (flags & FORK_WAIT) { + /* Let's block SIGCHLD at least, so that we can safely watch for the child process */ + + assert_se(sigemptyset(&ss) >= 0); + assert_se(sigaddset(&ss, SIGCHLD) >= 0); + block_signals = true; + } + + if (block_signals) + if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0) + return log_full_errno(prio, errno, "Failed to set signal mask: %m"); + + if (flags & FORK_NEW_MOUNTNS) + pid = raw_clone(SIGCHLD|CLONE_NEWNS); + else + pid = fork(); + if (pid < 0) { + r = -errno; + + if (block_signals) /* undo what we did above */ + (void) sigprocmask(SIG_SETMASK, &saved_ss, NULL); + + return log_full_errno(prio, r, "Failed to fork: %m"); + } + if (pid > 0) { + /* We are in the parent process */ + + log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid); + + if (flags & FORK_WAIT) { + r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0)); + if (r < 0) + return r; + if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */ + return -EPROTO; + } + + if (block_signals) /* undo what we did above */ + (void) sigprocmask(SIG_SETMASK, &saved_ss, NULL); + + if (ret_pid) + *ret_pid = pid; + + return 1; + } + + /* We are in the child process */ + + if (flags & FORK_REOPEN_LOG) { + /* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */ + log_close(); + log_set_open_when_needed(true); + } + + if (name) { + r = rename_process(name); + if (r < 0) + log_full_errno(flags & FORK_LOG ? LOG_WARNING : LOG_DEBUG, + r, "Failed to rename process, ignoring: %m"); + } + + if (flags & FORK_DEATHSIG) + if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) { + log_full_errno(prio, errno, "Failed to set death signal: %m"); + _exit(EXIT_FAILURE); + } + + if (flags & FORK_RESET_SIGNALS) { + r = reset_all_signal_handlers(); + if (r < 0) { + log_full_errno(prio, r, "Failed to reset signal handlers: %m"); + _exit(EXIT_FAILURE); + } + + /* This implicitly undoes the signal mask stuff we did before the fork()ing above */ + r = reset_signal_mask(); + if (r < 0) { + log_full_errno(prio, r, "Failed to reset signal mask: %m"); + _exit(EXIT_FAILURE); + } + } else if (block_signals) { /* undo what we did above */ + if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) { + log_full_errno(prio, errno, "Failed to restore signal mask: %m"); + _exit(EXIT_FAILURE); + } + } + + if (flags & FORK_DEATHSIG) { + pid_t ppid; + /* Let's see if the parent PID is still the one we started from? If not, then the parent + * already died by the time we set PR_SET_PDEATHSIG, hence let's emulate the effect */ + + ppid = getppid(); + if (ppid == 0) + /* Parent is in a differn't PID namespace. */; + else if (ppid != original_pid) { + log_debug("Parent died early, raising SIGTERM."); + (void) raise(SIGTERM); + _exit(EXIT_FAILURE); + } + } + + if (FLAGS_SET(flags, FORK_NEW_MOUNTNS | FORK_MOUNTNS_SLAVE)) { + + /* Optionally, make sure we never propagate mounts to the host. */ + + if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) { + log_full_errno(prio, errno, "Failed to remount root directory as MS_SLAVE: %m"); + _exit(EXIT_FAILURE); + } + } + + if (flags & FORK_CLOSE_ALL_FDS) { + /* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */ + log_close(); + + r = close_all_fds(except_fds, n_except_fds); + if (r < 0) { + log_full_errno(prio, r, "Failed to close all file descriptors: %m"); + _exit(EXIT_FAILURE); + } + } + + /* When we were asked to reopen the logs, do so again now */ + if (flags & FORK_REOPEN_LOG) { + log_open(); + log_set_open_when_needed(false); + } + + if (flags & FORK_NULL_STDIO) { + r = make_null_stdio(); + if (r < 0) { + log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m"); + _exit(EXIT_FAILURE); + } + } + + if (flags & FORK_RLIMIT_NOFILE_SAFE) { + r = rlimit_nofile_safe(); + if (r < 0) { + log_full_errno(prio, r, "Failed to lower RLIMIT_NOFILE's soft limit to 1K: %m"); + _exit(EXIT_FAILURE); + } + } + + if (ret_pid) + *ret_pid = getpid_cached(); + + return 0; +} + +int namespace_fork( + const char *outer_name, + const char *inner_name, + const int except_fds[], + size_t n_except_fds, + ForkFlags flags, + int pidns_fd, + int mntns_fd, + int netns_fd, + int userns_fd, + int root_fd, + pid_t *ret_pid) { + + int r; + + /* This is much like safe_fork(), but forks twice, and joins the specified namespaces in the middle + * process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that + * /proc/self/fd works correctly. */ + + r = safe_fork_full(outer_name, except_fds, n_except_fds, (flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid); + if (r < 0) + return r; + if (r == 0) { + pid_t pid; + + /* Child */ + + r = namespace_enter(pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd); + if (r < 0) { + log_full_errno(FLAGS_SET(flags, FORK_LOG) ? LOG_ERR : LOG_DEBUG, r, "Failed to join namespace: %m"); + _exit(EXIT_FAILURE); + } + + /* We mask a few flags here that either make no sense for the grandchild, or that we don't have to do again */ + r = safe_fork_full(inner_name, except_fds, n_except_fds, flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NULL_STDIO), &pid); + if (r < 0) + _exit(EXIT_FAILURE); + if (r == 0) { + /* Child */ + if (ret_pid) + *ret_pid = pid; + return 0; + } + + r = wait_for_terminate_and_check(inner_name, pid, FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0); + if (r < 0) + _exit(EXIT_FAILURE); + + _exit(r); + } + + return 1; +} + +int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) { + bool stdout_is_tty, stderr_is_tty; + size_t n, i; + va_list ap; + char **l; + int r; + + assert(path); + + /* Spawns a temporary TTY agent, making sure it goes away when we go away */ + + r = safe_fork_full(name, except, n_except, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS, ret_pid); + if (r < 0) + return r; + if (r > 0) + return 0; + + /* In the child: */ + + stdout_is_tty = isatty(STDOUT_FILENO); + stderr_is_tty = isatty(STDERR_FILENO); + + if (!stdout_is_tty || !stderr_is_tty) { + int fd; + + /* Detach from stdout/stderr. and reopen + * /dev/tty for them. This is important to + * ensure that when systemctl is started via + * popen() or a similar call that expects to + * read EOF we actually do generate EOF and + * not delay this indefinitely by because we + * keep an unused copy of stdin around. */ + fd = open("/dev/tty", O_WRONLY); + if (fd < 0) { + log_error_errno(errno, "Failed to open /dev/tty: %m"); + _exit(EXIT_FAILURE); + } + + if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) { + log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); + _exit(EXIT_FAILURE); + } + + if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) { + log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); + _exit(EXIT_FAILURE); + } + + safe_close_above_stdio(fd); + } + + (void) rlimit_nofile_safe(); + + /* Count arguments */ + va_start(ap, path); + for (n = 0; va_arg(ap, char*); n++) + ; + va_end(ap); + + /* Allocate strv */ + l = newa(char*, n + 1); + + /* Fill in arguments */ + va_start(ap, path); + for (i = 0; i <= n; i++) + l[i] = va_arg(ap, char*); + va_end(ap); + + execv(path, l); + _exit(EXIT_FAILURE); +} + +int set_oom_score_adjust(int value) { + char t[DECIMAL_STR_MAX(int)]; + + sprintf(t, "%i", value); + + return write_string_file("/proc/self/oom_score_adj", t, + WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER); +} + +static const char *const ioprio_class_table[] = { + [IOPRIO_CLASS_NONE] = "none", + [IOPRIO_CLASS_RT] = "realtime", + [IOPRIO_CLASS_BE] = "best-effort", + [IOPRIO_CLASS_IDLE] = "idle", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, IOPRIO_N_CLASSES); + +static const char *const sigchld_code_table[] = { + [CLD_EXITED] = "exited", + [CLD_KILLED] = "killed", + [CLD_DUMPED] = "dumped", + [CLD_TRAPPED] = "trapped", + [CLD_STOPPED] = "stopped", + [CLD_CONTINUED] = "continued", +}; + +DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int); + +static const char* const sched_policy_table[] = { + [SCHED_OTHER] = "other", + [SCHED_BATCH] = "batch", + [SCHED_IDLE] = "idle", + [SCHED_FIFO] = "fifo", + [SCHED_RR] = "rr", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX); diff --git a/src/basic/process-util.h b/src/basic/process-util.h new file mode 100644 index 00000000..5f4e174f --- /dev/null +++ b/src/basic/process-util.h @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "format-util.h" +#include "ioprio.h" +#include "macro.h" +#include "time-util.h" + +#define procfs_file_alloca(pid, field) \ + ({ \ + pid_t _pid_ = (pid); \ + const char *_r_; \ + if (_pid_ == 0) { \ + _r_ = ("/proc/self/" field); \ + } else { \ + _r_ = newa(char, STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \ + sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \ + } \ + _r_; \ + }) + +typedef enum ProcessCmdlineFlags { + PROCESS_CMDLINE_COMM_FALLBACK = 1 << 0, + PROCESS_CMDLINE_USE_LOCALE = 1 << 1, +} ProcessCmdlineFlags; + +int get_process_comm(pid_t pid, char **name); +int get_process_cmdline(pid_t pid, size_t max_columns, ProcessCmdlineFlags flags, char **line); +int get_process_exe(pid_t pid, char **name); +int get_process_uid(pid_t pid, uid_t *uid); +int get_process_gid(pid_t pid, gid_t *gid); +int get_process_capeff(pid_t pid, char **capeff); +int get_process_cwd(pid_t pid, char **cwd); +int get_process_root(pid_t pid, char **root); +int get_process_environ(pid_t pid, char **environ); +int get_process_ppid(pid_t pid, pid_t *ppid); + +int wait_for_terminate(pid_t pid, siginfo_t *status); + +typedef enum WaitFlags { + WAIT_LOG_ABNORMAL = 1 << 0, + WAIT_LOG_NON_ZERO_EXIT_STATUS = 1 << 1, + + /* A shortcut for requesting the most complete logging */ + WAIT_LOG = WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS, +} WaitFlags; + +int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags); +int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout); + +void sigkill_wait(pid_t pid); +void sigkill_waitp(pid_t *pid); +void sigterm_wait(pid_t pid); + +int kill_and_sigcont(pid_t pid, int sig); + +int rename_process(const char name[]); +int is_kernel_thread(pid_t pid); + +int getenv_for_pid(pid_t pid, const char *field, char **_value); + +bool pid_is_alive(pid_t pid); +bool pid_is_unwaited(pid_t pid); +int pid_is_my_child(pid_t pid); +int pid_from_same_root_fs(pid_t pid); + +bool is_main_thread(void); + +_noreturn_ void freeze(void); + +bool oom_score_adjust_is_valid(int oa); + +#ifndef PERSONALITY_INVALID +/* personality(7) documents that 0xffffffffUL is used for querying the + * current personality, hence let's use that here as error + * indicator. */ +#define PERSONALITY_INVALID 0xffffffffLU +#endif + +unsigned long personality_from_string(const char *p); +const char *personality_to_string(unsigned long); + +int safe_personality(unsigned long p); +int opinionated_personality(unsigned long *ret); + +int ioprio_class_to_string_alloc(int i, char **s); +int ioprio_class_from_string(const char *s); + +const char *sigchld_code_to_string(int i) _const_; +int sigchld_code_from_string(const char *s) _pure_; + +int sched_policy_to_string_alloc(int i, char **s); +int sched_policy_from_string(const char *s); + +static inline pid_t PTR_TO_PID(const void *p) { + return (pid_t) ((uintptr_t) p); +} + +static inline void* PID_TO_PTR(pid_t pid) { + return (void*) ((uintptr_t) pid); +} + +void valgrind_summary_hack(void); + +int pid_compare_func(const pid_t *a, const pid_t *b); + +static inline bool nice_is_valid(int n) { + return n >= PRIO_MIN && n < PRIO_MAX; +} + +static inline bool sched_policy_is_valid(int i) { + return IN_SET(i, SCHED_OTHER, SCHED_BATCH, SCHED_IDLE, SCHED_FIFO, SCHED_RR); +} + +static inline bool sched_priority_is_valid(int i) { + return i >= 0 && i <= sched_get_priority_max(SCHED_RR); +} + +static inline bool ioprio_class_is_valid(int i) { + return IN_SET(i, IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE); +} + +static inline bool ioprio_priority_is_valid(int i) { + return i >= 0 && i < IOPRIO_BE_NR; +} + +static inline bool pid_is_valid(pid_t p) { + return p > 0; +} + +int ioprio_parse_priority(const char *s, int *ret); + +pid_t getpid_cached(void); +void reset_cached_pid(void); + +int must_be_root(void); + +typedef enum ForkFlags { + FORK_RESET_SIGNALS = 1 << 0, /* Reset all signal handlers and signal mask */ + FORK_CLOSE_ALL_FDS = 1 << 1, /* Close all open file descriptors in the child, except for 0,1,2 */ + FORK_DEATHSIG = 1 << 2, /* Set PR_DEATHSIG in the child */ + FORK_NULL_STDIO = 1 << 3, /* Connect 0,1,2 to /dev/null */ + FORK_REOPEN_LOG = 1 << 4, /* Reopen log connection */ + FORK_LOG = 1 << 5, /* Log above LOG_DEBUG log level about failures */ + FORK_WAIT = 1 << 6, /* Wait until child exited */ + FORK_NEW_MOUNTNS = 1 << 7, /* Run child in its own mount namespace */ + FORK_MOUNTNS_SLAVE = 1 << 8, /* Make child's mount namespace MS_SLAVE */ + FORK_RLIMIT_NOFILE_SAFE = 1 << 9, /* Set RLIMIT_NOFILE soft limit to 1K for select() compat */ +} ForkFlags; + +int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid); + +static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) { + return safe_fork_full(name, NULL, 0, flags, ret_pid); +} + +int namespace_fork(const char *outer_name, const char *inner_name, const int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd, pid_t *ret_pid); + +int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...) _sentinel_; + +int set_oom_score_adjust(int value); + +#if SIZEOF_PID_T == 4 +/* The highest possibly (theoretic) pid_t value on this architecture. */ +#define PID_T_MAX ((pid_t) INT32_MAX) +/* The maximum number of concurrent processes Linux allows on this architecture, as well as the highest valid PID value + * the kernel will potentially assign. This reflects a value compiled into the kernel (PID_MAX_LIMIT), and sets the + * upper boundary on what may be written to the /proc/sys/kernel/pid_max sysctl (but do note that the sysctl is off by + * 1, since PID 0 can never exist and there can hence only be one process less than the limit would suggest). Since + * these values are documented in proc(5) we feel quite confident that they are stable enough for the near future at + * least to define them here too. */ +#define TASKS_MAX 4194303U +#elif SIZEOF_PID_T == 2 +#define PID_T_MAX ((pid_t) INT16_MAX) +#define TASKS_MAX 32767U +#else +#error "Unknown pid_t size" +#endif + +assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX); + +/* Like TAKE_PTR() but for child PIDs, resetting them to 0 */ +#define TAKE_PID(pid) \ + ({ \ + pid_t _pid_ = (pid); \ + (pid) = 0; \ + _pid_; \ + }) diff --git a/src/basic/procfs-util.c b/src/basic/procfs-util.c new file mode 100644 index 00000000..7aaf95bf --- /dev/null +++ b/src/basic/procfs-util.c @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "def.h" +#include "fd-util.h" +#include "fileio.h" +#include "parse-util.h" +#include "process-util.h" +#include "procfs-util.h" +#include "stdio-util.h" +#include "string-util.h" + +int procfs_tasks_get_limit(uint64_t *ret) { + _cleanup_free_ char *value = NULL; + uint64_t pid_max, threads_max; + int r; + + assert(ret); + + /* So there are two sysctl files that control the system limit of processes: + * + * 1. kernel.threads-max: this is probably the sysctl that makes more sense, as it directly puts a limit on + * concurrent tasks. + * + * 2. kernel.pid_max: this limits the numeric range PIDs can take, and thus indirectly also limits the number + * of concurrent threads. AFAICS it's primarily a compatibility concept: some crappy old code used a signed + * 16bit type for PIDs, hence the kernel provides a way to ensure the PIDs never go beyond INT16_MAX by + * default. + * + * By default #2 is set to much lower values than #1, hence the limit people come into contact with first, as + * it's the lowest boundary they need to bump when they want higher number of processes. + * + * Also note the weird definition of #2: PIDs assigned will be kept below this value, which means the number of + * tasks that can be created is one lower, as PID 0 is not a valid process ID. */ + + r = read_one_line_file("/proc/sys/kernel/pid_max", &value); + if (r < 0) + return r; + + r = safe_atou64(value, &pid_max); + if (r < 0) + return r; + + value = mfree(value); + r = read_one_line_file("/proc/sys/kernel/threads-max", &value); + if (r < 0) + return r; + + r = safe_atou64(value, &threads_max); + if (r < 0) + return r; + + /* Subtract one from pid_max, since PID 0 is not a valid PID */ + *ret = MIN(pid_max-1, threads_max); + return 0; +} + +int procfs_tasks_set_limit(uint64_t limit) { + char buffer[DECIMAL_STR_MAX(uint64_t)+1]; + _cleanup_free_ char *value = NULL; + uint64_t pid_max; + int r; + + if (limit == 0) /* This makes no sense, we are userspace and hence count as tasks too, and we want to live, + * hence the limit conceptually has to be above 0. Also, most likely if anyone asks for a zero + * limit he/she probably means "no limit", hence let's better refuse this to avoid + * confusion. */ + return -EINVAL; + + /* The Linux kernel doesn't allow this value to go below 20, hence don't allow this either, higher values than + * TASKS_MAX are not accepted by the pid_max sysctl. We'll treat anything this high as "unbounded" and hence + * set it to the maximum. */ + limit = CLAMP(limit, 20U, TASKS_MAX); + + r = read_one_line_file("/proc/sys/kernel/pid_max", &value); + if (r < 0) + return r; + r = safe_atou64(value, &pid_max); + if (r < 0) + return r; + + /* As pid_max is about the numeric pid_t range we'll bump it if necessary, but only ever increase it, never + * decrease it, as threads-max is the much more relevant sysctl. */ + if (limit > pid_max-1) { + sprintf(buffer, "%" PRIu64, limit+1); /* Add one, since PID 0 is not a valid PID */ + r = write_string_file("/proc/sys/kernel/pid_max", buffer, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return r; + } + + sprintf(buffer, "%" PRIu64, limit); + r = write_string_file("/proc/sys/kernel/threads-max", buffer, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) { + uint64_t threads_max; + + /* Hmm, we couldn't write this? If so, maybe it was already set properly? In that case let's not + * generate an error */ + + value = mfree(value); + if (read_one_line_file("/proc/sys/kernel/threads-max", &value) < 0) + return r; /* return original error */ + + if (safe_atou64(value, &threads_max) < 0) + return r; /* return original error */ + + if (MIN(pid_max-1, threads_max) != limit) + return r; /* return original error */ + + /* Yay! Value set already matches what we were trying to set, hence consider this a success. */ + } + + return 0; +} + +int procfs_tasks_get_current(uint64_t *ret) { + _cleanup_free_ char *value = NULL; + const char *p, *nr; + size_t n; + int r; + + assert(ret); + + r = read_one_line_file("/proc/loadavg", &value); + if (r < 0) + return r; + + /* Look for the second part of the fourth field, which is separated by a slash from the first part. None of the + * earlier fields use a slash, hence let's use this to find the right spot. */ + p = strchr(value, '/'); + if (!p) + return -EINVAL; + + p++; + n = strspn(p, DIGITS); + nr = strndupa(p, n); + + return safe_atou64(nr, ret); +} + +static uint64_t calc_gcd64(uint64_t a, uint64_t b) { + + while (b > 0) { + uint64_t t; + + t = a % b; + + a = b; + b = t; + } + + return a; +} + +int procfs_cpu_get_usage(nsec_t *ret) { + _cleanup_free_ char *first_line = NULL; + unsigned long user_ticks, nice_ticks, system_ticks, irq_ticks, softirq_ticks, + guest_ticks = 0, guest_nice_ticks = 0; + long ticks_per_second; + uint64_t sum, gcd, a, b; + const char *p; + int r; + + assert(ret); + + r = read_one_line_file("/proc/stat", &first_line); + if (r < 0) + return r; + + p = first_word(first_line, "cpu"); + if (!p) + return -EINVAL; + + if (sscanf(p, "%lu %lu %lu %*u %*u %lu %lu %*u %lu %lu", + &user_ticks, + &nice_ticks, + &system_ticks, + &irq_ticks, + &softirq_ticks, + &guest_ticks, + &guest_nice_ticks) < 5) /* we only insist on the first five fields */ + return -EINVAL; + + ticks_per_second = sysconf(_SC_CLK_TCK); + if (ticks_per_second < 0) + return -errno; + assert(ticks_per_second > 0); + + sum = (uint64_t) user_ticks + (uint64_t) nice_ticks + (uint64_t) system_ticks + + (uint64_t) irq_ticks + (uint64_t) softirq_ticks + + (uint64_t) guest_ticks + (uint64_t) guest_nice_ticks; + + /* Let's reduce this fraction before we apply it to avoid overflows when converting this to µsec */ + gcd = calc_gcd64(NSEC_PER_SEC, ticks_per_second); + + a = (uint64_t) NSEC_PER_SEC / gcd; + b = (uint64_t) ticks_per_second / gcd; + + *ret = DIV_ROUND_UP((nsec_t) sum * (nsec_t) a, (nsec_t) b); + return 0; +} + +int procfs_memory_get(uint64_t *ret_total, uint64_t *ret_used) { + uint64_t mem_total = UINT64_MAX, mem_free = UINT64_MAX; + _cleanup_fclose_ FILE *f = NULL; + int r; + + f = fopen("/proc/meminfo", "re"); + if (!f) + return -errno; + + for (;;) { + _cleanup_free_ char *line = NULL; + uint64_t *v; + char *p, *e; + size_t n; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; /* EOF: Couldn't find one or both fields? */ + + p = first_word(line, "MemTotal:"); + if (p) + v = &mem_total; + else { + p = first_word(line, "MemFree:"); + if (p) + v = &mem_free; + else + continue; + } + + /* Determine length of numeric value */ + n = strspn(p, DIGITS); + if (n == 0) + return -EINVAL; + e = p + n; + + /* Ensure the line ends in " kB" */ + n = strspn(e, WHITESPACE); + if (n == 0) + return -EINVAL; + if (!streq(e + n, "kB")) + return -EINVAL; + + *e = 0; + r = safe_atou64(p, v); + if (r < 0) + return r; + if (*v == UINT64_MAX) + return -EINVAL; + + if (mem_total != UINT64_MAX && mem_free != UINT64_MAX) + break; + } + + if (mem_free > mem_total) + return -EINVAL; + + if (ret_total) + *ret_total = mem_total * 1024U; + if (ret_used) + *ret_used = (mem_total - mem_free) * 1024U; + return 0; +} diff --git a/src/basic/procfs-util.h b/src/basic/procfs-util.h new file mode 100644 index 00000000..5a44e9ef --- /dev/null +++ b/src/basic/procfs-util.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "time-util.h" + +int procfs_tasks_get_limit(uint64_t *ret); +int procfs_tasks_set_limit(uint64_t limit); +int procfs_tasks_get_current(uint64_t *ret); + +int procfs_cpu_get_usage(nsec_t *ret); + +int procfs_memory_get(uint64_t *ret_total, uint64_t *ret_used); +static inline int procfs_memory_get_used(uint64_t *ret) { + return procfs_memory_get(NULL, ret); +} diff --git a/src/basic/random-util.c b/src/basic/random-util.c new file mode 100644 index 00000000..cdc2a164 --- /dev/null +++ b/src/basic/random-util.c @@ -0,0 +1,411 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if defined(__i386__) || defined(__x86_64__) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_SYS_AUXV_H +# include +#endif + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "io-util.h" +#include "missing_random.h" +#include "missing_syscall.h" +#include "parse-util.h" +#include "random-util.h" +#include "siphash24.h" +#include "time-util.h" + +int rdrand(unsigned long *ret) { + + /* So, you are a "security researcher", and you wonder why we bother with using raw RDRAND here, + * instead of sticking to /dev/urandom or getrandom()? + * + * Here's why: early boot. On Linux, during early boot the random pool that backs /dev/urandom and + * getrandom() is generally not initialized yet. It is very common that initialization of the random + * pool takes a longer time (up to many minutes), in particular on embedded devices that have no + * explicit hardware random generator, as well as in virtualized environments such as major cloud + * installations that do not provide virtio-rng or a similar mechanism. + * + * In such an environment using getrandom() synchronously means we'd block the entire system boot-up + * until the pool is initialized, i.e. *very* long. Using getrandom() asynchronously (GRND_NONBLOCK) + * would mean acquiring randomness during early boot would simply fail. Using /dev/urandom would mean + * generating many kmsg log messages about our use of it before the random pool is properly + * initialized. Neither of these outcomes is desirable. + * + * Thus, for very specific purposes we use RDRAND instead of either of these three options. RDRAND + * provides us quickly and relatively reliably with random values, without having to delay boot, + * without triggering warning messages in kmsg. + * + * Note that we use RDRAND only under very specific circumstances, when the requirements on the + * quality of the returned entropy permit it. Specifically, here are some cases where we *do* use + * RDRAND: + * + * • UUID generation: UUIDs are supposed to be universally unique but are not cryptographic + * key material. The quality and trust level of RDRAND should hence be OK: UUIDs should be + * generated in a way that is reliably unique, but they do not require ultimate trust into + * the entropy generator. systemd generates a number of UUIDs during early boot, including + * 'invocation IDs' for every unit spawned that identify the specific invocation of the + * service globally, and a number of others. Other alternatives for generating these UUIDs + * have been considered, but don't really work: for example, hashing uuids from a local + * system identifier combined with a counter falls flat because during early boot disk + * storage is not yet available (think: initrd) and thus a system-specific ID cannot be + * stored or retrieved yet. + * + * • Hash table seed generation: systemd uses many hash tables internally. Hash tables are + * generally assumed to have O(1) access complexity, but can deteriorate to prohibitive + * O(n) access complexity if an attacker manages to trigger a large number of hash + * collisions. Thus, systemd (as any software employing hash tables should) uses seeded + * hash functions for its hash tables, with a seed generated randomly. The hash tables + * systemd employs watch the fill level closely and reseed if necessary. This allows use of + * a low quality RNG initially, as long as it improves should a hash table be under attack: + * the attacker after all needs to to trigger many collisions to exploit it for the purpose + * of DoS, but if doing so improves the seed the attack surface is reduced as the attack + * takes place. + * + * Some cases where we do NOT use RDRAND are: + * + * • Generation of cryptographic key material 🔑 + * + * • Generation of cryptographic salt values 🧂 + * + * This function returns: + * + * -EOPNOTSUPP → RDRAND is not available on this system 😔 + * -EAGAIN → The operation failed this time, but is likely to work if you try again a few + * times ♻ + * -EUCLEAN → We got some random value, but it looked strange, so we refused using it. + * This failure might or might not be temporary. 😕 + */ + +#if defined(__i386__) || defined(__x86_64__) + static int have_rdrand = -1; + unsigned long v; + uint8_t success; + + if (have_rdrand < 0) { + uint32_t eax, ebx, ecx, edx; + + /* Check if RDRAND is supported by the CPU */ + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0) { + have_rdrand = false; + return -EOPNOTSUPP; + } + +/* Compat with old gcc where bit_RDRND didn't exist yet */ +#ifndef bit_RDRND +#define bit_RDRND (1U << 30) +#endif + + have_rdrand = !!(ecx & bit_RDRND); + } + + if (have_rdrand == 0) + return -EOPNOTSUPP; + + asm volatile("rdrand %0;" + "setc %1" + : "=r" (v), + "=qm" (success)); + msan_unpoison(&success, sizeof(success)); + if (!success) + return -EAGAIN; + + /* Apparently on some AMD CPUs RDRAND will sometimes (after a suspend/resume cycle?) report success + * via the carry flag but nonetheless return the same fixed value -1 in all cases. This appears to be + * a bad bug in the CPU or firmware. Let's deal with that and work-around this by explicitly checking + * for this special value (and also 0, just to be sure) and filtering it out. This is a work-around + * only however and something AMD really should fix properly. The Linux kernel should probably work + * around this issue by turning off RDRAND altogether on those CPUs. See: + * https://github.com/systemd/systemd/issues/11810 */ + if (v == 0 || v == ULONG_MAX) + return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), + "RDRAND returned suspicious value %lx, assuming bad hardware RNG, not using value.", v); + + *ret = v; + return 0; +#else + return -EOPNOTSUPP; +#endif +} + +int genuine_random_bytes(void *p, size_t n, RandomFlags flags) { + static int have_syscall = -1; + _cleanup_close_ int fd = -1; + bool got_some = false; + int r; + + /* Gathers some high-quality randomness from the kernel (or potentially mid-quality randomness from + * the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't block, unless the RANDOM_BLOCK + * flag is set. If RANDOM_MAY_FAIL is set, an error is returned if the random pool is not + * initialized. Otherwise it will always return some data from the kernel, regardless of whether the + * random pool is fully initialized or not. If RANDOM_EXTEND_WITH_PSEUDO is set, and some but not + * enough better quality randomness could be acquired, the rest is filled up with low quality + * randomness. + * + * Of course, when creating cryptographic key material you really shouldn't use RANDOM_ALLOW_DRDRAND + * or even RANDOM_EXTEND_WITH_PSEUDO. + * + * When generating UUIDs it's fine to use RANDOM_ALLOW_RDRAND but not OK to use + * RANDOM_EXTEND_WITH_PSEUDO. In fact RANDOM_EXTEND_WITH_PSEUDO is only really fine when invoked via + * an "all bets are off" wrapper, such as random_bytes(), see below. */ + + if (n == 0) + return 0; + + if (FLAGS_SET(flags, RANDOM_ALLOW_RDRAND)) + /* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is + * not required, as we don't trust it (who does?). Note that we only do a single iteration of + * RDRAND here, even though the Intel docs suggest calling this in a tight loop of 10 + * invocations or so. That's because we don't really care about the quality here. We + * generally prefer using RDRAND if the caller allows us to, since this way we won't upset + * the kernel's random subsystem by accessing it before the pool is initialized (after all it + * will kmsg log about every attempt to do so)..*/ + for (;;) { + unsigned long u; + size_t m; + + if (rdrand(&u) < 0) { + if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) { + /* Fill in the remaining bytes using pseudo-random values */ + pseudo_random_bytes(p, n); + return 0; + } + + /* OK, this didn't work, let's go to getrandom() + /dev/urandom instead */ + break; + } + + m = MIN(sizeof(u), n); + memcpy(p, &u, m); + + p = (uint8_t*) p + m; + n -= m; + + if (n == 0) + return 0; /* Yay, success! */ + + got_some = true; + } + + /* Use the getrandom() syscall unless we know we don't have it. */ + if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) { + + for (;;) { + r = getrandom(p, n, FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_NONBLOCK); + if (r > 0) { + have_syscall = true; + + if ((size_t) r == n) + return 0; /* Yay, success! */ + + assert((size_t) r < n); + p = (uint8_t*) p + r; + n -= r; + + if (FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) { + /* Fill in the remaining bytes using pseudo-random values */ + pseudo_random_bytes(p, n); + return 0; + } + + got_some = true; + + /* Hmm, we didn't get enough good data but the caller insists on good data? Then try again */ + if (FLAGS_SET(flags, RANDOM_BLOCK)) + continue; + + /* Fill in the rest with /dev/urandom */ + break; + + } else if (r == 0) { + have_syscall = true; + return -EIO; + + } else if (errno == ENOSYS) { + /* We lack the syscall, continue with reading from /dev/urandom. */ + have_syscall = false; + break; + + } else if (errno == EAGAIN) { + /* The kernel has no entropy whatsoever. Let's remember to use the syscall + * the next time again though. + * + * If RANDOM_MAY_FAIL is set, return an error so that random_bytes() can + * produce some pseudo-random bytes instead. Otherwise, fall back to + * /dev/urandom, which we know is empty, but the kernel will produce some + * bytes for us on a best-effort basis. */ + have_syscall = true; + + if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) { + /* Fill in the remaining bytes using pseudorandom values */ + pseudo_random_bytes(p, n); + return 0; + } + + if (FLAGS_SET(flags, RANDOM_MAY_FAIL)) + return -ENODATA; + + /* Use /dev/urandom instead */ + break; + } else + return -errno; + } + } + + fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return errno == ENOENT ? -ENOSYS : -errno; + + return loop_read_exact(fd, p, n, true); +} + +void initialize_srand(void) { + static bool srand_called = false; + unsigned x; +#if HAVE_SYS_AUXV_H + const void *auxv; +#endif + unsigned long k; + + if (srand_called) + return; + +#if HAVE_SYS_AUXV_H + /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed + * the pseudo-random generator. It's better than nothing... But let's first hash it to make it harder + * to recover the original value by watching any pseudo-random bits we generate. After all the + * AT_RANDOM data might be used by other stuff too (in particular: ASLR), and we probably shouldn't + * leak the seed for that. */ + + auxv = ULONG_TO_PTR(getauxval(AT_RANDOM)); + if (auxv) { + static const uint8_t auxval_hash_key[16] = { + 0x92, 0x6e, 0xfe, 0x1b, 0xcf, 0x00, 0x52, 0x9c, 0xcc, 0x42, 0xcf, 0xdc, 0x94, 0x1f, 0x81, 0x0f + }; + + x = (unsigned) siphash24(auxv, 16, auxval_hash_key); + } else +#endif + x = 0; + + x ^= (unsigned) now(CLOCK_REALTIME); + x ^= (unsigned) gettid(); + + if (rdrand(&k) >= 0) + x ^= (unsigned) k; + + srand(x); + srand_called = true; +} + +/* INT_MAX gives us only 31 bits, so use 24 out of that. */ +#if RAND_MAX >= INT_MAX +# define RAND_STEP 3 +#else +/* SHORT_INT_MAX or lower gives at most 15 bits, we just just 8 out of that. */ +# define RAND_STEP 1 +#endif + +void pseudo_random_bytes(void *p, size_t n) { + uint8_t *q; + + /* This returns pseudo-random data using libc's rand() function. You probably never want to call this + * directly, because why would you use this if you can get better stuff cheaply? Use random_bytes() + * instead, see below: it will fall back to this function if there's nothing better to get, but only + * then. */ + + initialize_srand(); + + for (q = p; q < (uint8_t*) p + n; q += RAND_STEP) { + unsigned rr; + + rr = (unsigned) rand(); + +#if RAND_STEP >= 3 + if ((size_t) (q - (uint8_t*) p + 2) < n) + q[2] = rr >> 16; +#endif +#if RAND_STEP >= 2 + if ((size_t) (q - (uint8_t*) p + 1) < n) + q[1] = rr >> 8; +#endif + q[0] = rr; + } +} + +void random_bytes(void *p, size_t n) { + + /* This returns high quality randomness if we can get it cheaply. If we can't because for some reason + * it is not available we'll try some crappy fallbacks. + * + * What this function will do: + * + * • This function will preferably use the CPU's RDRAND operation, if it is available, in + * order to return "mid-quality" random values cheaply. + * + * • Use getrandom() with GRND_NONBLOCK, to return high-quality random values if they are + * cheaply available. + * + * • This function will return pseudo-random data, generated via libc rand() if nothing + * better is available. + * + * • This function will work fine in early boot + * + * • This function will always succeed + * + * What this function won't do: + * + * • This function will never fail: it will give you randomness no matter what. It might not + * be high quality, but it will return some, possibly generated via libc's rand() call. + * + * • This function will never block: if the only way to get good randomness is a blocking, + * synchronous getrandom() we'll instead provide you with pseudo-random data. + * + * This function is hence great for things like seeding hash tables, generating random numeric UNIX + * user IDs (that are checked for collisions before use) and such. + * + * This function is hence not useful for generating UUIDs or cryptographic key material. + */ + + if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND) >= 0) + return; + + /* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */ + pseudo_random_bytes(p, n); +} + +size_t random_pool_size(void) { + _cleanup_free_ char *s = NULL; + int r; + + /* Read pool size, if possible */ + r = read_one_line_file("/proc/sys/kernel/random/poolsize", &s); + if (r < 0) + log_debug_errno(r, "Failed to read pool size from kernel: %m"); + else { + unsigned sz; + + r = safe_atou(s, &sz); + if (r < 0) + log_debug_errno(r, "Failed to parse pool size: %s", s); + else + /* poolsize is in bits on 2.6, but we want bytes */ + return CLAMP(sz / 8, RANDOM_POOL_SIZE_MIN, RANDOM_POOL_SIZE_MAX); + } + + /* Use the minimum as default, if we can't retrieve the correct value */ + return RANDOM_POOL_SIZE_MIN; +} diff --git a/src/basic/random-util.h b/src/basic/random-util.h new file mode 100644 index 00000000..facc11b9 --- /dev/null +++ b/src/basic/random-util.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +typedef enum RandomFlags { + RANDOM_EXTEND_WITH_PSEUDO = 1 << 0, /* If we can't get enough genuine randomness, but some, fill up the rest with pseudo-randomness */ + RANDOM_BLOCK = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */ + RANDOM_MAY_FAIL = 1 << 2, /* If we can't get any randomness at all, return early with -ENODATA */ + RANDOM_ALLOW_RDRAND = 1 << 3, /* Allow usage of the CPU RNG */ +} RandomFlags; + +int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled up with pseudo random, if not enough is available */ +void pseudo_random_bytes(void *p, size_t n); /* returns only pseudo-randommess (but possibly seeded from something better) */ +void random_bytes(void *p, size_t n); /* returns genuine randomness if cheaply available, and pseudo randomness if not. */ + +void initialize_srand(void); + +static inline uint64_t random_u64(void) { + uint64_t u; + random_bytes(&u, sizeof(u)); + return u; +} + +static inline uint32_t random_u32(void) { + uint32_t u; + random_bytes(&u, sizeof(u)); + return u; +} + +int rdrand(unsigned long *ret); + +/* Some limits on the pool sizes when we deal with the kernel random pool */ +#define RANDOM_POOL_SIZE_MIN 512U +#define RANDOM_POOL_SIZE_MAX (10U*1024U*1024U) + +size_t random_pool_size(void); diff --git a/src/basic/ratelimit.c b/src/basic/ratelimit.c new file mode 100644 index 00000000..4e04e044 --- /dev/null +++ b/src/basic/ratelimit.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "macro.h" +#include "ratelimit.h" + +/* Modelled after Linux' lib/ratelimit.c by Dave Young + * , which is licensed GPLv2. */ + +bool ratelimit_below(RateLimit *r) { + usec_t ts; + + assert(r); + + if (r->interval <= 0 || r->burst <= 0) + return true; + + ts = now(CLOCK_MONOTONIC); + + if (r->begin <= 0 || + r->begin + r->interval < ts) { + r->begin = ts; + + /* Reset counter */ + r->num = 0; + goto good; + } + + if (r->num < r->burst) + goto good; + + return false; + +good: + r->num++; + return true; +} diff --git a/src/basic/ratelimit.h b/src/basic/ratelimit.h new file mode 100644 index 00000000..79e33b6a --- /dev/null +++ b/src/basic/ratelimit.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "time-util.h" +#include "util.h" + +typedef struct RateLimit { + usec_t interval; /* Keep those two fields first so they can be initialized easily: */ + unsigned burst; /* RateLimit rl = { INTERVAL, BURST }; */ + unsigned num; + usec_t begin; +} RateLimit; + +static inline void ratelimit_reset(RateLimit *rl) { + rl->num = rl->begin = 0; +} + +bool ratelimit_below(RateLimit *r); diff --git a/src/basic/raw-clone.h b/src/basic/raw-clone.h new file mode 100644 index 00000000..b12dea2a --- /dev/null +++ b/src/basic/raw-clone.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2016 Michael Karcher +***/ + +#include +#include +#include + +#include "log.h" +#include "macro.h" + +/** + * raw_clone() - uses clone to create a new process with clone flags + * @flags: Flags to pass to the clone system call + * + * Uses the clone system call to create a new process with the cloning flags and termination signal passed in the flags + * parameter. Opposed to glibc's clone function, using this function does not set up a separate stack for the child, but + * relies on copy-on-write semantics on the one stack at a common virtual address, just as fork does. + * + * To obtain copy-on-write semantics, flags must not contain CLONE_VM, and thus CLONE_THREAD and CLONE_SIGHAND (which + * require CLONE_VM) are not usable. + * + * Additionally, as this function does not pass the ptid, newtls and ctid parameters to the kernel, flags must not + * contain CLONE_PARENT_SETTID, CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS. + * + * Returns: 0 in the child process and the child process id in the parent. + */ +static inline pid_t raw_clone(unsigned long flags) { + pid_t ret; + + assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID| + CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0); +#if defined(__s390x__) || defined(__s390__) || defined(__CRIS__) + /* On s390/s390x and cris the order of the first and second arguments + * of the raw clone() system call is reversed. */ + ret = (pid_t) syscall(__NR_clone, NULL, flags); +#elif defined(__sparc__) + { + /** + * sparc always returns the other process id in %o0, and + * a boolean flag whether this is the child or the parent in + * %o1. Inline assembly is needed to get the flag returned + * in %o1. + */ + int in_child, child_pid, error; + + asm volatile("mov %3, %%g1\n\t" + "mov %4, %%o0\n\t" + "mov 0 , %%o1\n\t" +#if defined(__arch64__) + "t 0x6d\n\t" +#else + "t 0x10\n\t" +#endif + "addx %%g0, 0, %2\n\t" + "mov %%o1, %0\n\t" + "mov %%o0, %1" : + "=r"(in_child), "=r"(child_pid), "=r"(error) : + "i"(__NR_clone), "r"(flags) : + "%o1", "%o0", "%g1", "cc" ); + + if (error) { + errno = child_pid; + ret = -1; + } else + ret = in_child ? 0 : child_pid; + } +#else + ret = (pid_t) syscall(__NR_clone, flags, NULL); +#endif + + if (ret == 0) + reset_cached_pid(); + + return ret; +} diff --git a/src/basic/raw-reboot.h b/src/basic/raw-reboot.h new file mode 100644 index 00000000..8ecefe9e --- /dev/null +++ b/src/basic/raw-reboot.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +/* glibc defines the reboot() API call, which is a wrapper around the system call of the same name, but without the + * extra "arg" parameter. Since we need that parameter for some calls, let's add a "raw" wrapper that is defined the + * same way, except it takes the additional argument. */ + +static inline int raw_reboot(int cmd, const void *arg) { + return (int) syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, arg); +} diff --git a/src/basic/replace-var.c b/src/basic/replace-var.c new file mode 100644 index 00000000..5b473750 --- /dev/null +++ b/src/basic/replace-var.c @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "macro.h" +#include "replace-var.h" +#include "string-util.h" + +/* + * Generic infrastructure for replacing @FOO@ style variables in + * strings. Will call a callback for each replacement. + */ + +static int get_variable(const char *b, char **r) { + size_t k; + char *t; + + assert(b); + assert(r); + + if (*b != '@') + return 0; + + k = strspn(b + 1, UPPERCASE_LETTERS "_"); + if (k <= 0 || b[k+1] != '@') + return 0; + + t = strndup(b + 1, k); + if (!t) + return -ENOMEM; + + *r = t; + return 1; +} + +char *replace_var(const char *text, char *(*lookup)(const char *variable, void *userdata), void *userdata) { + char *r, *t; + const char *f; + size_t l; + + assert(text); + assert(lookup); + + l = strlen(text); + r = new(char, l+1); + if (!r) + return NULL; + + f = text; + t = r; + while (*f) { + _cleanup_free_ char *v = NULL, *n = NULL; + char *a; + int k; + size_t skip, d, nl; + + k = get_variable(f, &v); + if (k < 0) + goto oom; + if (k == 0) { + *(t++) = *(f++); + continue; + } + + n = lookup(v, userdata); + if (!n) + goto oom; + + skip = strlen(v) + 2; + + d = t - r; + nl = l - skip + strlen(n); + a = realloc(r, nl + 1); + if (!a) + goto oom; + + l = nl; + r = a; + t = r + d; + + t = stpcpy(t, n); + f += skip; + } + + *t = 0; + return r; + +oom: + return mfree(r); +} diff --git a/src/basic/replace-var.h b/src/basic/replace-var.h new file mode 100644 index 00000000..e6a489fe --- /dev/null +++ b/src/basic/replace-var.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +char *replace_var(const char *text, char *(*lookup)(const char *variable, void *userdata), void *userdata); diff --git a/src/basic/rlimit-util.c b/src/basic/rlimit-util.c new file mode 100644 index 00000000..2dc13eab --- /dev/null +++ b/src/basic/rlimit-util.c @@ -0,0 +1,409 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "extract-word.h" +#include "fd-util.h" +#include "format-util.h" +#include "macro.h" +#include "missing_resource.h" +#include "rlimit-util.h" +#include "string-table.h" +#include "time-util.h" + +int setrlimit_closest(int resource, const struct rlimit *rlim) { + struct rlimit highest, fixed; + + assert(rlim); + + if (setrlimit(resource, rlim) >= 0) + return 0; + + if (errno != EPERM) + return -errno; + + /* So we failed to set the desired setrlimit, then let's try + * to get as close as we can */ + if (getrlimit(resource, &highest) < 0) + return -errno; + + /* If the hard limit is unbounded anyway, then the EPERM had other reasons, let's propagate the original EPERM + * then */ + if (highest.rlim_max == RLIM_INFINITY) + return -EPERM; + + fixed = (struct rlimit) { + .rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max), + .rlim_max = MIN(rlim->rlim_max, highest.rlim_max), + }; + + /* Shortcut things if we wouldn't change anything. */ + if (fixed.rlim_cur == highest.rlim_cur && + fixed.rlim_max == highest.rlim_max) + return 0; + + if (setrlimit(resource, &fixed) < 0) + return -errno; + + return 0; +} + +int setrlimit_closest_all(const struct rlimit *const *rlim, int *which_failed) { + int i, r; + + assert(rlim); + + /* On failure returns the limit's index that failed in *which_failed, but only if non-NULL */ + + for (i = 0; i < _RLIMIT_MAX; i++) { + if (!rlim[i]) + continue; + + r = setrlimit_closest(i, rlim[i]); + if (r < 0) { + if (which_failed) + *which_failed = i; + + return r; + } + } + + if (which_failed) + *which_failed = -1; + + return 0; +} + +static int rlimit_parse_u64(const char *val, rlim_t *ret) { + uint64_t u; + int r; + + assert(val); + assert(ret); + + if (streq(val, "infinity")) { + *ret = RLIM_INFINITY; + return 0; + } + + /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */ + assert_cc(sizeof(rlim_t) == sizeof(uint64_t)); + + r = safe_atou64(val, &u); + if (r < 0) + return r; + if (u >= (uint64_t) RLIM_INFINITY) + return -ERANGE; + + *ret = (rlim_t) u; + return 0; +} + +static int rlimit_parse_size(const char *val, rlim_t *ret) { + uint64_t u; + int r; + + assert(val); + assert(ret); + + if (streq(val, "infinity")) { + *ret = RLIM_INFINITY; + return 0; + } + + r = parse_size(val, 1024, &u); + if (r < 0) + return r; + if (u >= (uint64_t) RLIM_INFINITY) + return -ERANGE; + + *ret = (rlim_t) u; + return 0; +} + +static int rlimit_parse_sec(const char *val, rlim_t *ret) { + uint64_t u; + usec_t t; + int r; + + assert(val); + assert(ret); + + if (streq(val, "infinity")) { + *ret = RLIM_INFINITY; + return 0; + } + + r = parse_sec(val, &t); + if (r < 0) + return r; + if (t == USEC_INFINITY) { + *ret = RLIM_INFINITY; + return 0; + } + + u = (uint64_t) DIV_ROUND_UP(t, USEC_PER_SEC); + if (u >= (uint64_t) RLIM_INFINITY) + return -ERANGE; + + *ret = (rlim_t) u; + return 0; +} + +static int rlimit_parse_usec(const char *val, rlim_t *ret) { + usec_t t; + int r; + + assert(val); + assert(ret); + + if (streq(val, "infinity")) { + *ret = RLIM_INFINITY; + return 0; + } + + r = parse_time(val, &t, 1); + if (r < 0) + return r; + if (t == USEC_INFINITY) { + *ret = RLIM_INFINITY; + return 0; + } + + *ret = (rlim_t) t; + return 0; +} + +static int rlimit_parse_nice(const char *val, rlim_t *ret) { + uint64_t rl; + int r; + + /* So, Linux is weird. The range for RLIMIT_NICE is 40..1, mapping to the nice levels -20..19. However, the + * RLIMIT_NICE limit defaults to 0 by the kernel, i.e. a value that maps to nice level 20, which of course is + * bogus and does not exist. In order to permit parsing the RLIMIT_NICE of 0 here we hence implement a slight + * asymmetry: when parsing as positive nice level we permit 0..19. When parsing as negative nice level, we + * permit -20..0. But when parsing as raw resource limit value then we also allow the special value 0. + * + * Yeah, Linux is quality engineering sometimes... */ + + if (val[0] == '+') { + + /* Prefixed with "+": Parse as positive user-friendly nice value */ + r = safe_atou64(val + 1, &rl); + if (r < 0) + return r; + + if (rl >= PRIO_MAX) + return -ERANGE; + + rl = 20 - rl; + + } else if (val[0] == '-') { + + /* Prefixed with "-": Parse as negative user-friendly nice value */ + r = safe_atou64(val + 1, &rl); + if (r < 0) + return r; + + if (rl > (uint64_t) (-PRIO_MIN)) + return -ERANGE; + + rl = 20 + rl; + } else { + + /* Not prefixed: parse as raw resource limit value */ + r = safe_atou64(val, &rl); + if (r < 0) + return r; + + if (rl > (uint64_t) (20 - PRIO_MIN)) + return -ERANGE; + } + + *ret = (rlim_t) rl; + return 0; +} + +static int (*const rlimit_parse_table[_RLIMIT_MAX])(const char *val, rlim_t *ret) = { + [RLIMIT_CPU] = rlimit_parse_sec, + [RLIMIT_FSIZE] = rlimit_parse_size, + [RLIMIT_DATA] = rlimit_parse_size, + [RLIMIT_STACK] = rlimit_parse_size, + [RLIMIT_CORE] = rlimit_parse_size, + [RLIMIT_RSS] = rlimit_parse_size, + [RLIMIT_NOFILE] = rlimit_parse_u64, + [RLIMIT_AS] = rlimit_parse_size, + [RLIMIT_NPROC] = rlimit_parse_u64, + [RLIMIT_MEMLOCK] = rlimit_parse_size, + [RLIMIT_LOCKS] = rlimit_parse_u64, + [RLIMIT_SIGPENDING] = rlimit_parse_u64, + [RLIMIT_MSGQUEUE] = rlimit_parse_size, + [RLIMIT_NICE] = rlimit_parse_nice, + [RLIMIT_RTPRIO] = rlimit_parse_u64, + [RLIMIT_RTTIME] = rlimit_parse_usec, +}; + +int rlimit_parse_one(int resource, const char *val, rlim_t *ret) { + assert(val); + assert(ret); + + if (resource < 0) + return -EINVAL; + if (resource >= _RLIMIT_MAX) + return -EINVAL; + + return rlimit_parse_table[resource](val, ret); +} + +int rlimit_parse(int resource, const char *val, struct rlimit *ret) { + _cleanup_free_ char *hard = NULL, *soft = NULL; + rlim_t hl, sl; + int r; + + assert(val); + assert(ret); + + r = extract_first_word(&val, &soft, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + r = rlimit_parse_one(resource, soft, &sl); + if (r < 0) + return r; + + r = extract_first_word(&val, &hard, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + if (!isempty(val)) + return -EINVAL; + if (r == 0) + hl = sl; + else { + r = rlimit_parse_one(resource, hard, &hl); + if (r < 0) + return r; + if (sl > hl) + return -EILSEQ; + } + + *ret = (struct rlimit) { + .rlim_cur = sl, + .rlim_max = hl, + }; + + return 0; +} + +int rlimit_format(const struct rlimit *rl, char **ret) { + char *s = NULL; + + assert(rl); + assert(ret); + + if (rl->rlim_cur >= RLIM_INFINITY && rl->rlim_max >= RLIM_INFINITY) + s = strdup("infinity"); + else if (rl->rlim_cur >= RLIM_INFINITY) + (void) asprintf(&s, "infinity:" RLIM_FMT, rl->rlim_max); + else if (rl->rlim_max >= RLIM_INFINITY) + (void) asprintf(&s, RLIM_FMT ":infinity", rl->rlim_cur); + else if (rl->rlim_cur == rl->rlim_max) + (void) asprintf(&s, RLIM_FMT, rl->rlim_cur); + else + (void) asprintf(&s, RLIM_FMT ":" RLIM_FMT, rl->rlim_cur, rl->rlim_max); + + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +static const char* const rlimit_table[_RLIMIT_MAX] = { + [RLIMIT_AS] = "AS", + [RLIMIT_CORE] = "CORE", + [RLIMIT_CPU] = "CPU", + [RLIMIT_DATA] = "DATA", + [RLIMIT_FSIZE] = "FSIZE", + [RLIMIT_LOCKS] = "LOCKS", + [RLIMIT_MEMLOCK] = "MEMLOCK", + [RLIMIT_MSGQUEUE] = "MSGQUEUE", + [RLIMIT_NICE] = "NICE", + [RLIMIT_NOFILE] = "NOFILE", + [RLIMIT_NPROC] = "NPROC", + [RLIMIT_RSS] = "RSS", + [RLIMIT_RTPRIO] = "RTPRIO", + [RLIMIT_RTTIME] = "RTTIME", + [RLIMIT_SIGPENDING] = "SIGPENDING", + [RLIMIT_STACK] = "STACK", +}; + +DEFINE_STRING_TABLE_LOOKUP(rlimit, int); + +int rlimit_from_string_harder(const char *s) { + const char *suffix; + + /* The official prefix */ + suffix = startswith(s, "RLIMIT_"); + if (suffix) + return rlimit_from_string(suffix); + + /* Our own unit file setting prefix */ + suffix = startswith(s, "Limit"); + if (suffix) + return rlimit_from_string(suffix); + + return rlimit_from_string(s); +} + +void rlimit_free_all(struct rlimit **rl) { + int i; + + if (!rl) + return; + + for (i = 0; i < _RLIMIT_MAX; i++) + rl[i] = mfree(rl[i]); +} + +int rlimit_nofile_bump(int limit) { + int r; + + /* Bumps the (soft) RLIMIT_NOFILE resource limit as close as possible to the specified limit. If a negative + * limit is specified, bumps it to the maximum the kernel and the hard resource limit allows. This call should + * be used by all our programs that might need a lot of fds, and that know how to deal with high fd numbers + * (i.e. do not use select() — which chokes on fds >= 1024) */ + + if (limit < 0) + limit = read_nr_open(); + + if (limit < 3) + limit = 3; + + r = setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(limit)); + if (r < 0) + return log_debug_errno(r, "Failed to set RLIMIT_NOFILE: %m"); + + return 0; +} + +int rlimit_nofile_safe(void) { + struct rlimit rl; + + /* Resets RLIMIT_NOFILE's soft limit FD_SETSIZE (i.e. 1024), for compatibility with software still using + * select() */ + + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) + return log_debug_errno(errno, "Failed to query RLIMIT_NOFILE: %m"); + + if (rl.rlim_cur <= FD_SETSIZE) + return 0; + + rl.rlim_cur = FD_SETSIZE; + if (setrlimit(RLIMIT_NOFILE, &rl) < 0) + return log_debug_errno(errno, "Failed to lower RLIMIT_NOFILE's soft limit to " RLIM_FMT ": %m", rl.rlim_cur); + + return 1; +} diff --git a/src/basic/rlimit-util.h b/src/basic/rlimit-util.h new file mode 100644 index 00000000..d4fca2b8 --- /dev/null +++ b/src/basic/rlimit-util.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +const char *rlimit_to_string(int i) _const_; +int rlimit_from_string(const char *s) _pure_; +int rlimit_from_string_harder(const char *s) _pure_; + +int setrlimit_closest(int resource, const struct rlimit *rlim); +int setrlimit_closest_all(const struct rlimit * const *rlim, int *which_failed); + +int rlimit_parse_one(int resource, const char *val, rlim_t *ret); +int rlimit_parse(int resource, const char *val, struct rlimit *ret); + +int rlimit_format(const struct rlimit *rl, char **ret); + +void rlimit_free_all(struct rlimit **rl); + +#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim }) + +int rlimit_nofile_bump(int limit); +int rlimit_nofile_safe(void); diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c new file mode 100644 index 00000000..23cdfa46 --- /dev/null +++ b/src/basic/rm-rf.c @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "cgroup-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "log.h" +#include "macro.h" +#include "mountpoint-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "stat-util.h" +#include "string-util.h" + +static bool is_physical_fs(const struct statfs *sfs) { + return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs); +} + +int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int ret = 0, r; + struct statfs sfs; + + assert(fd >= 0); + + /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed + * fd, in all cases, including on failure.. */ + + if (!(flags & REMOVE_PHYSICAL)) { + + r = fstatfs(fd, &sfs); + if (r < 0) { + safe_close(fd); + return -errno; + } + + if (is_physical_fs(&sfs)) { + /* We refuse to clean physical file systems with this call, + * unless explicitly requested. This is extra paranoia just + * to be sure we never ever remove non-state data. */ + _cleanup_free_ char *path = NULL; + + (void) fd_get_path(fd, &path); + log_error("Attempted to remove disk file system under \"%s\", and we can't allow that.", + strna(path)); + + safe_close(fd); + return -EPERM; + } + } + + d = fdopendir(fd); + if (!d) { + safe_close(fd); + return errno == ENOENT ? 0 : -errno; + } + + FOREACH_DIRENT_ALL(de, d, return -errno) { + bool is_dir; + struct stat st; + + if (dot_or_dot_dot(de->d_name)) + continue; + + if (de->d_type == DT_UNKNOWN || + (de->d_type == DT_DIR && (root_dev || (flags & REMOVE_SUBVOLUME)))) { + if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { + if (ret == 0 && errno != ENOENT) + ret = -errno; + continue; + } + + is_dir = S_ISDIR(st.st_mode); + } else + is_dir = de->d_type == DT_DIR; + + if (is_dir) { + _cleanup_close_ int subdir_fd = -1; + + /* if root_dev is set, remove subdirectories only if device is same */ + if (root_dev && st.st_dev != root_dev->st_dev) + continue; + + subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (subdir_fd < 0) { + if (ret == 0 && errno != ENOENT) + ret = -errno; + continue; + } + + /* Stop at mount points */ + r = fd_is_mount_point(fd, de->d_name, 0); + if (r < 0) { + if (ret == 0 && r != -ENOENT) + ret = r; + + continue; + } + if (r > 0) + continue; + + if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) { + + /* This could be a subvolume, try to remove it */ + + r = btrfs_subvol_remove_fd(fd, de->d_name, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); + if (r < 0) { + if (!IN_SET(r, -ENOTTY, -EINVAL)) { + if (ret == 0) + ret = r; + + continue; + } + + /* ENOTTY, then it wasn't a btrfs subvolume, continue below. */ + } else + /* It was a subvolume, continue. */ + continue; + } + + /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file + * system type again for each directory */ + r = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); + if (r < 0 && ret == 0) + ret = r; + + if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) { + if (ret == 0 && errno != ENOENT) + ret = -errno; + } + + } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { + + if (unlinkat(fd, de->d_name, 0) < 0) { + if (ret == 0 && errno != ENOENT) + ret = -errno; + } + } + } + return ret; +} + +int rm_rf(const char *path, RemoveFlags flags) { + int fd, r; + struct statfs s; + + assert(path); + + /* For now, don't support dropping subvols when also only dropping directories, since we can't do + * this race-freely. */ + if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME)) + return -EINVAL; + + /* We refuse to clean the root file system with this call. This is extra paranoia to never cause a + * really seriously broken system. */ + if (path_equal_or_files_same(path, "/", AT_SYMLINK_NOFOLLOW)) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Attempted to remove entire root file system (\"%s\"), and we can't allow that.", + path); + + if (FLAGS_SET(flags, REMOVE_SUBVOLUME | REMOVE_ROOT | REMOVE_PHYSICAL)) { + /* Try to remove as subvolume first */ + r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); + if (r >= 0) + return r; + + if (FLAGS_SET(flags, REMOVE_MISSING_OK) && r == -ENOENT) + return 0; + + if (!IN_SET(r, -ENOTTY, -EINVAL, -ENOTDIR)) + return r; + + /* Not btrfs or not a subvolume */ + } + + fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (fd < 0) { + if (FLAGS_SET(flags, REMOVE_MISSING_OK) && errno == ENOENT) + return 0; + + if (!IN_SET(errno, ENOTDIR, ELOOP)) + return -errno; + + if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES)) + return 0; + + if (FLAGS_SET(flags, REMOVE_ROOT)) { + + if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) { + if (statfs(path, &s) < 0) + return -errno; + + if (is_physical_fs(&s)) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Attempted to remove files from a disk file system under \"%s\", refusing.", + path); + } + + if (unlink(path) < 0) { + if (FLAGS_SET(flags, REMOVE_MISSING_OK) && errno == ENOENT) + return 0; + + return -errno; + } + } + + return 0; + } + + r = rm_rf_children(fd, flags, NULL); + + if (FLAGS_SET(flags, REMOVE_ROOT) && + rmdir(path) < 0 && + r >= 0 && + (!FLAGS_SET(flags, REMOVE_MISSING_OK) || errno != ENOENT)) + r = -errno; + + return r; +} diff --git a/src/basic/rm-rf.h b/src/basic/rm-rf.h new file mode 100644 index 00000000..40cbff21 --- /dev/null +++ b/src/basic/rm-rf.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "errno-util.h" + +typedef enum RemoveFlags { + REMOVE_ONLY_DIRECTORIES = 1 << 0, /* Only remove empty directories, no files */ + REMOVE_ROOT = 1 << 1, /* Remove the specified directory itself too, not just the contents of it */ + REMOVE_PHYSICAL = 1 << 2, /* If not set, only removes files on tmpfs, never physical file systems */ + REMOVE_SUBVOLUME = 1 << 3, /* Drop btrfs subvolumes in the tree too */ + REMOVE_MISSING_OK = 1 << 4, /* If the top-level directory is missing, ignore the ENOENT for it */ +} RemoveFlags; + +int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev); +int rm_rf(const char *path, RemoveFlags flags); + +/* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */ +static inline void rm_rf_physical_and_free(char *p) { + PROTECT_ERRNO; + (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL); + free(p); +} +DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rm_rf_physical_and_free); + +/* Similar as above, but also has magic btrfs subvolume powers */ +static inline void rm_rf_subvolume_and_free(char *p) { + PROTECT_ERRNO; + (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + free(p); +} +DEFINE_TRIVIAL_CLEANUP_FUNC(char*, rm_rf_subvolume_and_free); diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c new file mode 100644 index 00000000..f35e7602 --- /dev/null +++ b/src/basic/selinux-util.c @@ -0,0 +1,520 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_SELINUX +#include +#include +#include +#endif + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "log.h" +#include "macro.h" +#include "path-util.h" +#include "selinux-util.h" +#include "stdio-util.h" +#include "time-util.h" + +#if HAVE_SELINUX +DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon); +DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free); + +#define _cleanup_freecon_ _cleanup_(freeconp) +#define _cleanup_context_free_ _cleanup_(context_freep) + +static int cached_use = -1; +static struct selabel_handle *label_hnd = NULL; + +#define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__) +#define log_enforcing_errno(r, ...) log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, r, __VA_ARGS__) +#endif + +bool mac_selinux_use(void) { +#if HAVE_SELINUX + if (cached_use < 0) + cached_use = is_selinux_enabled() > 0; + + return cached_use; +#else + return false; +#endif +} + +void mac_selinux_retest(void) { +#if HAVE_SELINUX + cached_use = -1; +#endif +} + +int mac_selinux_init(void) { + int r = 0; + +#if HAVE_SELINUX + usec_t before_timestamp, after_timestamp; + struct mallinfo before_mallinfo, after_mallinfo; + + if (label_hnd) + return 0; + + if (!mac_selinux_use()) + return 0; + + before_mallinfo = mallinfo(); + before_timestamp = now(CLOCK_MONOTONIC); + + label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); + if (!label_hnd) { + log_enforcing_errno(errno, "Failed to initialize SELinux context: %m"); + r = security_getenforce() == 1 ? -errno : 0; + } else { + char timespan[FORMAT_TIMESPAN_MAX]; + int l; + + after_timestamp = now(CLOCK_MONOTONIC); + after_mallinfo = mallinfo(); + + l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0; + + log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.", + format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0), + (l+1023)/1024); + } +#endif + + return r; +} + +void mac_selinux_finish(void) { + +#if HAVE_SELINUX + if (!label_hnd) + return; + + selabel_close(label_hnd); + label_hnd = NULL; +#endif +} + +int mac_selinux_fix(const char *path, LabelFixFlags flags) { + +#if HAVE_SELINUX + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + _cleanup_freecon_ char* fcon = NULL; + _cleanup_close_ int fd = -1; + struct stat st; + int r; + + assert(path); + + /* if mac_selinux_init() wasn't called before we are a NOOP */ + if (!label_hnd) + return 0; + + /* Open the file as O_PATH, to pin it while we determine and adjust the label */ + fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH); + if (fd < 0) { + if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT) + return 0; + + return -errno; + } + + if (fstat(fd, &st) < 0) + return -errno; + + if (selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode) < 0) { + r = -errno; + + /* If there's no label to set, then exit without warning */ + if (r == -ENOENT) + return 0; + + goto fail; + } + + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + if (setfilecon_raw(procfs_path, fcon) < 0) { + _cleanup_freecon_ char *oldcon = NULL; + + r = -errno; + + /* If the FS doesn't support labels, then exit without warning */ + if (r == -EOPNOTSUPP) + return 0; + + /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */ + if (r == -EROFS && (flags & LABEL_IGNORE_EROFS)) + return 0; + + /* If the old label is identical to the new one, suppress any kind of error */ + if (getfilecon_raw(procfs_path, &oldcon) >= 0 && streq(fcon, oldcon)) + return 0; + + goto fail; + } + + return 0; + +fail: + log_enforcing_errno(r, "Unable to fix SELinux security context of %s: %m", path); + if (security_getenforce() == 1) + return r; +#endif + + return 0; +} + +int mac_selinux_apply(const char *path, const char *label) { + +#if HAVE_SELINUX + if (!mac_selinux_use()) + return 0; + + assert(path); + assert(label); + + if (setfilecon(path, label) < 0) { + log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path); + if (security_getenforce() > 0) + return -errno; + } +#endif + return 0; +} + +int mac_selinux_get_create_label_from_exe(const char *exe, char **label) { + int r = -EOPNOTSUPP; + +#if HAVE_SELINUX + _cleanup_freecon_ char *mycon = NULL, *fcon = NULL; + security_class_t sclass; + + assert(exe); + assert(label); + + if (!mac_selinux_use()) + return -EOPNOTSUPP; + + r = getcon_raw(&mycon); + if (r < 0) + return -errno; + + r = getfilecon_raw(exe, &fcon); + if (r < 0) + return -errno; + + sclass = string_to_security_class("process"); + r = security_compute_create_raw(mycon, fcon, sclass, label); + if (r < 0) + return -errno; +#endif + + return r; +} + +int mac_selinux_get_our_label(char **label) { + int r = -EOPNOTSUPP; + + assert(label); + +#if HAVE_SELINUX + if (!mac_selinux_use()) + return -EOPNOTSUPP; + + r = getcon_raw(label); + if (r < 0) + return -errno; +#endif + + return r; +} + +int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) { + int r = -EOPNOTSUPP; + +#if HAVE_SELINUX + _cleanup_freecon_ char *mycon = NULL, *peercon = NULL, *fcon = NULL; + _cleanup_context_free_ context_t pcon = NULL, bcon = NULL; + security_class_t sclass; + const char *range = NULL; + + assert(socket_fd >= 0); + assert(exe); + assert(label); + + if (!mac_selinux_use()) + return -EOPNOTSUPP; + + r = getcon_raw(&mycon); + if (r < 0) + return -errno; + + r = getpeercon_raw(socket_fd, &peercon); + if (r < 0) + return -errno; + + if (!exec_label) { + /* If there is no context set for next exec let's use context + of target executable */ + r = getfilecon_raw(exe, &fcon); + if (r < 0) + return -errno; + } + + bcon = context_new(mycon); + if (!bcon) + return -ENOMEM; + + pcon = context_new(peercon); + if (!pcon) + return -ENOMEM; + + range = context_range_get(pcon); + if (!range) + return -errno; + + r = context_range_set(bcon, range); + if (r) + return -errno; + + freecon(mycon); + mycon = strdup(context_str(bcon)); + if (!mycon) + return -ENOMEM; + + sclass = string_to_security_class("process"); + r = security_compute_create_raw(mycon, fcon, sclass, label); + if (r < 0) + return -errno; +#endif + + return r; +} + +char* mac_selinux_free(char *label) { + +#if HAVE_SELINUX + if (!label) + return NULL; + + if (!mac_selinux_use()) + return NULL; + + freecon(label); +#endif + + return NULL; +} + +#if HAVE_SELINUX +static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode) { + _cleanup_freecon_ char *filecon = NULL; + int r; + + assert(abspath); + assert(path_is_absolute(abspath)); + + r = selabel_lookup_raw(label_hnd, &filecon, abspath, mode); + if (r < 0) { + /* No context specified by the policy? Proceed without setting it. */ + if (errno == ENOENT) + return 0; + + log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath); + } else { + if (setfscreatecon_raw(filecon) >= 0) + return 0; /* Success! */ + + log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath); + } + + if (security_getenforce() > 0) + return -errno; + + return 0; +} +#endif + +int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode) { + int r = 0; + +#if HAVE_SELINUX + _cleanup_free_ char *abspath = NULL; + + assert(path); + + if (!label_hnd) + return 0; + + if (!path_is_absolute(path)) { + _cleanup_free_ char *p = NULL; + + if (dirfd == AT_FDCWD) + r = safe_getcwd(&p); + else + r = fd_get_path(dirfd, &p); + if (r < 0) + return r; + + path = abspath = path_join(p, path); + if (!path) + return -ENOMEM; + } + + r = selinux_create_file_prepare_abspath(path, mode); +#endif + return r; +} + +int mac_selinux_create_file_prepare(const char *path, mode_t mode) { + int r = 0; + +#if HAVE_SELINUX + _cleanup_free_ char *abspath = NULL; + + assert(path); + + if (!label_hnd) + return 0; + + r = path_make_absolute_cwd(path, &abspath); + if (r < 0) + return r; + + r = selinux_create_file_prepare_abspath(abspath, mode); +#endif + return r; +} + +void mac_selinux_create_file_clear(void) { + +#if HAVE_SELINUX + PROTECT_ERRNO; + + if (!mac_selinux_use()) + return; + + setfscreatecon_raw(NULL); +#endif +} + +int mac_selinux_create_socket_prepare(const char *label) { + +#if HAVE_SELINUX + if (!mac_selinux_use()) + return 0; + + assert(label); + + if (setsockcreatecon(label) < 0) { + log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label); + + if (security_getenforce() == 1) + return -errno; + } +#endif + + return 0; +} + +void mac_selinux_create_socket_clear(void) { + +#if HAVE_SELINUX + PROTECT_ERRNO; + + if (!mac_selinux_use()) + return; + + setsockcreatecon_raw(NULL); +#endif +} + +int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { + + /* Binds a socket and label its file system object according to the SELinux policy */ + +#if HAVE_SELINUX + _cleanup_freecon_ char *fcon = NULL; + const struct sockaddr_un *un; + bool context_changed = false; + char *path; + int r; + + assert(fd >= 0); + assert(addr); + assert(addrlen >= sizeof(sa_family_t)); + + if (!label_hnd) + goto skipped; + + /* Filter out non-local sockets */ + if (addr->sa_family != AF_UNIX) + goto skipped; + + /* Filter out anonymous sockets */ + if (addrlen < offsetof(struct sockaddr_un, sun_path) + 1) + goto skipped; + + /* Filter out abstract namespace sockets */ + un = (const struct sockaddr_un*) addr; + if (un->sun_path[0] == 0) + goto skipped; + + path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path)); + + if (path_is_absolute(path)) + r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK); + else { + _cleanup_free_ char *newpath = NULL; + + r = path_make_absolute_cwd(path, &newpath); + if (r < 0) + return r; + + r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK); + } + + if (r < 0) { + /* No context specified by the policy? Proceed without setting it */ + if (errno == ENOENT) + goto skipped; + + log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path); + if (security_getenforce() > 0) + return -errno; + + } else { + if (setfscreatecon_raw(fcon) < 0) { + log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path); + if (security_getenforce() > 0) + return -errno; + } else + context_changed = true; + } + + r = bind(fd, addr, addrlen) < 0 ? -errno : 0; + + if (context_changed) + setfscreatecon_raw(NULL); + + return r; + +skipped: +#endif + if (bind(fd, addr, addrlen) < 0) + return -errno; + + return 0; +} diff --git a/src/basic/selinux-util.h b/src/basic/selinux-util.h new file mode 100644 index 00000000..bd5207c3 --- /dev/null +++ b/src/basic/selinux-util.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "macro.h" +#include "label.h" + +bool mac_selinux_use(void); +void mac_selinux_retest(void); + +int mac_selinux_init(void); +void mac_selinux_finish(void); + +int mac_selinux_fix(const char *path, LabelFixFlags flags); +int mac_selinux_apply(const char *path, const char *label); + +int mac_selinux_get_create_label_from_exe(const char *exe, char **label); +int mac_selinux_get_our_label(char **label); +int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label); +char* mac_selinux_free(char *label); + +int mac_selinux_create_file_prepare(const char *path, mode_t mode); +int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode); +void mac_selinux_create_file_clear(void); + +int mac_selinux_create_socket_prepare(const char *label); +void mac_selinux_create_socket_clear(void); + +int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); + +DEFINE_TRIVIAL_CLEANUP_FUNC(char*, mac_selinux_free); diff --git a/src/basic/set.h b/src/basic/set.h new file mode 100644 index 00000000..5f195617 --- /dev/null +++ b/src/basic/set.h @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "extract-word.h" +#include "hashmap.h" +#include "macro.h" + +Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS) + +static inline Set *set_free(Set *s) { + return (Set*) internal_hashmap_free(HASHMAP_BASE(s), NULL, NULL); +} + +static inline Set *set_free_free(Set *s) { + return (Set*) internal_hashmap_free(HASHMAP_BASE(s), free, NULL); +} + +/* no set_free_free_free */ + +static inline Set *set_copy(Set *s) { + return (Set*) internal_hashmap_copy(HASHMAP_BASE(s)); +} + +int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS); +#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS) + +int set_put(Set *s, const void *key); +/* no set_update */ +/* no set_replace */ +static inline void *set_get(const Set *s, void *key) { + return internal_hashmap_get(HASHMAP_BASE((Set *) s), key); +} +/* no set_get2 */ + +static inline bool set_contains(const Set *s, const void *key) { + return internal_hashmap_contains(HASHMAP_BASE((Set *) s), key); +} + +static inline void *set_remove(Set *s, const void *key) { + return internal_hashmap_remove(HASHMAP_BASE(s), key); +} + +/* no set_remove2 */ +/* no set_remove_value */ +int set_remove_and_put(Set *s, const void *old_key, const void *new_key); +/* no set_remove_and_replace */ +int set_merge(Set *s, Set *other); + +static inline int set_reserve(Set *h, unsigned entries_add) { + return internal_hashmap_reserve(HASHMAP_BASE(h), entries_add); +} + +static inline int set_move(Set *s, Set *other) { + return internal_hashmap_move(HASHMAP_BASE(s), HASHMAP_BASE(other)); +} + +static inline int set_move_one(Set *s, Set *other, const void *key) { + return internal_hashmap_move_one(HASHMAP_BASE(s), HASHMAP_BASE(other), key); +} + +static inline unsigned set_size(const Set *s) { + return internal_hashmap_size(HASHMAP_BASE((Set *) s)); +} + +static inline bool set_isempty(const Set *s) { + return set_size(s) == 0; +} + +static inline unsigned set_buckets(const Set *s) { + return internal_hashmap_buckets(HASHMAP_BASE((Set *) s)); +} + +bool set_iterate(const Set *s, Iterator *i, void **value); + +static inline void set_clear(Set *s) { + internal_hashmap_clear(HASHMAP_BASE(s), NULL, NULL); +} + +static inline void set_clear_free(Set *s) { + internal_hashmap_clear(HASHMAP_BASE(s), free, NULL); +} + +/* no set_clear_free_free */ + +static inline void *set_steal_first(Set *s) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE(s), true, NULL); +} + +#define set_clear_with_destructor(_s, _f) \ + ({ \ + void *_item; \ + while ((_item = set_steal_first(_s))) \ + _f(_item); \ + }) +#define set_free_with_destructor(_s, _f) \ + ({ \ + set_clear_with_destructor(_s, _f); \ + set_free(_s); \ + }) + +/* no set_steal_first_key */ +/* no set_first_key */ + +static inline void *set_first(const Set *s) { + return internal_hashmap_first_key_and_value(HASHMAP_BASE((Set *) s), false, NULL); +} + +/* no set_next */ + +static inline char **set_get_strv(Set *s) { + return internal_hashmap_get_strv(HASHMAP_BASE(s)); +} + +int set_consume(Set *s, void *value); +int set_put_strdup(Set *s, const char *p); +int set_put_strdupv(Set *s, char **l); +int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags); + +#define SET_FOREACH(e, s, i) \ + for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); ) + +#define SET_FOREACH_MOVE(e, d, s) \ + for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); ) + +DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free); + +#define _cleanup_set_free_ _cleanup_(set_freep) +#define _cleanup_set_free_free_ _cleanup_(set_free_freep) diff --git a/src/basic/sigbus.c b/src/basic/sigbus.c new file mode 100644 index 00000000..a065a45a --- /dev/null +++ b/src/basic/sigbus.c @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "macro.h" +#include "memory-util.h" +#include "sigbus.h" + +#define SIGBUS_QUEUE_MAX 64 + +static struct sigaction old_sigaction; +static unsigned n_installed = 0; + +/* We maintain a fixed size list of page addresses that triggered a + SIGBUS. We access with list with atomic operations, so that we + don't have to deal with locks between signal handler and main + programs in possibly multiple threads. */ + +static void* volatile sigbus_queue[SIGBUS_QUEUE_MAX]; +static volatile sig_atomic_t n_sigbus_queue = 0; + +static void sigbus_push(void *addr) { + unsigned u; + + assert(addr); + + /* Find a free place, increase the number of entries and leave, if we can */ + for (u = 0; u < SIGBUS_QUEUE_MAX; u++) + if (__sync_bool_compare_and_swap(&sigbus_queue[u], NULL, addr)) { + __sync_fetch_and_add(&n_sigbus_queue, 1); + return; + } + + /* If we can't, make sure the queue size is out of bounds, to + * mark it as overflow */ + for (;;) { + unsigned c; + + __sync_synchronize(); + c = n_sigbus_queue; + + if (c > SIGBUS_QUEUE_MAX) /* already overflow */ + return; + + if (__sync_bool_compare_and_swap(&n_sigbus_queue, c, c + SIGBUS_QUEUE_MAX)) + return; + } +} + +int sigbus_pop(void **ret) { + assert(ret); + + for (;;) { + unsigned u, c; + + __sync_synchronize(); + c = n_sigbus_queue; + + if (_likely_(c == 0)) + return 0; + + if (_unlikely_(c >= SIGBUS_QUEUE_MAX)) + return -EOVERFLOW; + + for (u = 0; u < SIGBUS_QUEUE_MAX; u++) { + void *addr; + + addr = sigbus_queue[u]; + if (!addr) + continue; + + if (__sync_bool_compare_and_swap(&sigbus_queue[u], addr, NULL)) { + __sync_fetch_and_sub(&n_sigbus_queue, 1); + *ret = addr; + return 1; + } + } + } +} + +static void sigbus_handler(int sn, siginfo_t *si, void *data) { + unsigned long ul; + void *aligned; + + assert(sn == SIGBUS); + assert(si); + + if (si->si_code != BUS_ADRERR || !si->si_addr) { + assert_se(sigaction(SIGBUS, &old_sigaction, NULL) == 0); + raise(SIGBUS); + return; + } + + ul = (unsigned long) si->si_addr; + ul = ul / page_size(); + ul = ul * page_size(); + aligned = (void*) ul; + + /* Let's remember which address failed */ + sigbus_push(aligned); + + /* Replace mapping with an anonymous page, so that the + * execution can continue, however with a zeroed out page */ + assert_se(mmap(aligned, page_size(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == aligned); +} + +void sigbus_install(void) { + struct sigaction sa = { + .sa_sigaction = sigbus_handler, + .sa_flags = SA_SIGINFO, + }; + + /* make sure that sysconf() is not called from a signal handler because + * it is not guaranteed to be async-signal-safe since POSIX.1-2008 */ + (void) page_size(); + + n_installed++; + + if (n_installed == 1) + assert_se(sigaction(SIGBUS, &sa, &old_sigaction) == 0); + + return; +} + +void sigbus_reset(void) { + + if (n_installed <= 0) + return; + + n_installed--; + + if (n_installed == 0) + assert_se(sigaction(SIGBUS, &old_sigaction, NULL) == 0); + + return; +} diff --git a/src/basic/sigbus.h b/src/basic/sigbus.h new file mode 100644 index 00000000..459e19fc --- /dev/null +++ b/src/basic/sigbus.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +void sigbus_install(void); +void sigbus_reset(void); + +int sigbus_pop(void **ret); diff --git a/src/basic/signal-util.c b/src/basic/signal-util.c new file mode 100644 index 00000000..bfb83419 --- /dev/null +++ b/src/basic/signal-util.c @@ -0,0 +1,289 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "macro.h" +#include "parse-util.h" +#include "signal-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" + +int reset_all_signal_handlers(void) { + static const struct sigaction sa = { + .sa_handler = SIG_DFL, + .sa_flags = SA_RESTART, + }; + int sig, r = 0; + + for (sig = 1; sig < _NSIG; sig++) { + + /* These two cannot be caught... */ + if (IN_SET(sig, SIGKILL, SIGSTOP)) + continue; + + /* On Linux the first two RT signals are reserved by + * glibc, and sigaction() will return EINVAL for them. */ + if (sigaction(sig, &sa, NULL) < 0) + if (errno != EINVAL && r >= 0) + r = -errno; + } + + return r; +} + +int reset_signal_mask(void) { + sigset_t ss; + + if (sigemptyset(&ss) < 0) + return -errno; + + if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0) + return -errno; + + return 0; +} + +static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) { + int r = 0; + + /* negative signal ends the list. 0 signal is skipped. */ + + if (sig < 0) + return 0; + + if (sig > 0) { + if (sigaction(sig, sa, NULL) < 0) + r = -errno; + } + + while ((sig = va_arg(ap, int)) >= 0) { + + if (sig == 0) + continue; + + if (sigaction(sig, sa, NULL) < 0) { + if (r >= 0) + r = -errno; + } + } + + return r; +} + +int sigaction_many(const struct sigaction *sa, ...) { + va_list ap; + int r; + + va_start(ap, sa); + r = sigaction_many_ap(sa, 0, ap); + va_end(ap); + + return r; +} + +int ignore_signals(int sig, ...) { + + static const struct sigaction sa = { + .sa_handler = SIG_IGN, + .sa_flags = SA_RESTART, + }; + + va_list ap; + int r; + + va_start(ap, sig); + r = sigaction_many_ap(&sa, sig, ap); + va_end(ap); + + return r; +} + +int default_signals(int sig, ...) { + + static const struct sigaction sa = { + .sa_handler = SIG_DFL, + .sa_flags = SA_RESTART, + }; + + va_list ap; + int r; + + va_start(ap, sig); + r = sigaction_many_ap(&sa, sig, ap); + va_end(ap); + + return r; +} + +static int sigset_add_many_ap(sigset_t *ss, va_list ap) { + int sig, r = 0; + + assert(ss); + + while ((sig = va_arg(ap, int)) >= 0) { + + if (sig == 0) + continue; + + if (sigaddset(ss, sig) < 0) { + if (r >= 0) + r = -errno; + } + } + + return r; +} + +int sigset_add_many(sigset_t *ss, ...) { + va_list ap; + int r; + + va_start(ap, ss); + r = sigset_add_many_ap(ss, ap); + va_end(ap); + + return r; +} + +int sigprocmask_many(int how, sigset_t *old, ...) { + va_list ap; + sigset_t ss; + int r; + + if (sigemptyset(&ss) < 0) + return -errno; + + va_start(ap, old); + r = sigset_add_many_ap(&ss, ap); + va_end(ap); + + if (r < 0) + return r; + + if (sigprocmask(how, &ss, old) < 0) + return -errno; + + return 0; +} + +static const char *const __signal_table[] = { + [SIGHUP] = "HUP", + [SIGINT] = "INT", + [SIGQUIT] = "QUIT", + [SIGILL] = "ILL", + [SIGTRAP] = "TRAP", + [SIGABRT] = "ABRT", + [SIGBUS] = "BUS", + [SIGFPE] = "FPE", + [SIGKILL] = "KILL", + [SIGUSR1] = "USR1", + [SIGSEGV] = "SEGV", + [SIGUSR2] = "USR2", + [SIGPIPE] = "PIPE", + [SIGALRM] = "ALRM", + [SIGTERM] = "TERM", +#ifdef SIGSTKFLT + [SIGSTKFLT] = "STKFLT", /* Linux on SPARC doesn't know SIGSTKFLT */ +#endif + [SIGCHLD] = "CHLD", + [SIGCONT] = "CONT", + [SIGSTOP] = "STOP", + [SIGTSTP] = "TSTP", + [SIGTTIN] = "TTIN", + [SIGTTOU] = "TTOU", + [SIGURG] = "URG", + [SIGXCPU] = "XCPU", + [SIGXFSZ] = "XFSZ", + [SIGVTALRM] = "VTALRM", + [SIGPROF] = "PROF", + [SIGWINCH] = "WINCH", + [SIGIO] = "IO", + [SIGPWR] = "PWR", + [SIGSYS] = "SYS" +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(__signal, int); + +const char *signal_to_string(int signo) { + static thread_local char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1]; + const char *name; + + name = __signal_to_string(signo); + if (name) + return name; + + if (signo >= SIGRTMIN && signo <= SIGRTMAX) + xsprintf(buf, "RTMIN+%d", signo - SIGRTMIN); + else + xsprintf(buf, "%d", signo); + + return buf; +} + +int signal_from_string(const char *s) { + const char *p; + int signo, r; + + /* Check that the input is a signal number. */ + if (safe_atoi(s, &signo) >= 0) { + if (SIGNAL_VALID(signo)) + return signo; + else + return -ERANGE; + } + + /* Drop "SIG" prefix. */ + if (startswith(s, "SIG")) + s += 3; + + /* Check that the input is a signal name. */ + signo = __signal_from_string(s); + if (signo > 0) + return signo; + + /* Check that the input is RTMIN or + * RTMIN+n (0 <= n <= SIGRTMAX-SIGRTMIN). */ + p = startswith(s, "RTMIN"); + if (p) { + if (*p == '\0') + return SIGRTMIN; + if (*p != '+') + return -EINVAL; + + r = safe_atoi(p, &signo); + if (r < 0) + return r; + + if (signo < 0 || signo > SIGRTMAX - SIGRTMIN) + return -ERANGE; + + return signo + SIGRTMIN; + } + + /* Check that the input is RTMAX or + * RTMAX-n (0 <= n <= SIGRTMAX-SIGRTMIN). */ + p = startswith(s, "RTMAX"); + if (p) { + if (*p == '\0') + return SIGRTMAX; + if (*p != '-') + return -EINVAL; + + r = safe_atoi(p, &signo); + if (r < 0) + return r; + + if (signo > 0 || signo < SIGRTMIN - SIGRTMAX) + return -ERANGE; + + return signo + SIGRTMAX; + } + + return -EINVAL; +} + +void nop_signal_handler(int sig) { + /* nothing here */ +} diff --git a/src/basic/signal-util.h b/src/basic/signal-util.h new file mode 100644 index 00000000..92f2804c --- /dev/null +++ b/src/basic/signal-util.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +int reset_all_signal_handlers(void); +int reset_signal_mask(void); + +int ignore_signals(int sig, ...); +int default_signals(int sig, ...); +int sigaction_many(const struct sigaction *sa, ...); + +int sigset_add_many(sigset_t *ss, ...); +int sigprocmask_many(int how, sigset_t *old, ...); + +const char *signal_to_string(int i) _const_; +int signal_from_string(const char *s) _pure_; + +void nop_signal_handler(int sig); + +static inline void block_signals_reset(sigset_t *ss) { + assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0); +} + +#define BLOCK_SIGNALS(...) \ + _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({ \ + sigset_t _t; \ + assert_se(sigprocmask_many(SIG_BLOCK, &_t, __VA_ARGS__, -1) >= 0); \ + _t; \ + }) + +static inline bool SIGNAL_VALID(int signo) { + return signo > 0 && signo < _NSIG; +} + +static inline const char* signal_to_string_with_check(int n) { + if (!SIGNAL_VALID(n)) + return NULL; + + return signal_to_string(n); +} diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c new file mode 100644 index 00000000..666431aa --- /dev/null +++ b/src/basic/siphash24.c @@ -0,0 +1,206 @@ +/* + SipHash reference C implementation + + Written in 2012 by + Jean-Philippe Aumasson + Daniel J. Bernstein + + To the extent possible under law, the author(s) have dedicated all copyright + and related and neighboring rights to this software to the public domain + worldwide. This software is distributed without any warranty. + + You should have received a copy of the CC0 Public Domain Dedication along with + this software. If not, see . + + (Minimal changes made by Lennart Poettering, to make clean for inclusion in systemd) + (Refactored by Tom Gundersen to split up in several functions and follow systemd + coding style) +*/ + +#include + +#include "macro.h" +#include "siphash24.h" +#include "unaligned.h" + +static uint64_t rotate_left(uint64_t x, uint8_t b) { + assert(b < 64); + + return (x << b) | (x >> (64 - b)); +} + +static void sipround(struct siphash *state) { + assert(state); + + state->v0 += state->v1; + state->v1 = rotate_left(state->v1, 13); + state->v1 ^= state->v0; + state->v0 = rotate_left(state->v0, 32); + state->v2 += state->v3; + state->v3 = rotate_left(state->v3, 16); + state->v3 ^= state->v2; + state->v0 += state->v3; + state->v3 = rotate_left(state->v3, 21); + state->v3 ^= state->v0; + state->v2 += state->v1; + state->v1 = rotate_left(state->v1, 17); + state->v1 ^= state->v2; + state->v2 = rotate_left(state->v2, 32); +} + +void siphash24_init(struct siphash *state, const uint8_t k[static 16]) { + uint64_t k0, k1; + + assert(state); + assert(k); + + k0 = unaligned_read_le64(k); + k1 = unaligned_read_le64(k + 8); + + *state = (struct siphash) { + /* "somepseudorandomlygeneratedbytes" */ + .v0 = 0x736f6d6570736575ULL ^ k0, + .v1 = 0x646f72616e646f6dULL ^ k1, + .v2 = 0x6c7967656e657261ULL ^ k0, + .v3 = 0x7465646279746573ULL ^ k1, + .padding = 0, + .inlen = 0, + }; +} + +void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) { + + const uint8_t *in = _in; + const uint8_t *end = in + inlen; + size_t left = state->inlen & 7; + uint64_t m; + + assert(in); + assert(state); + + /* Update total length */ + state->inlen += inlen; + + /* If padding exists, fill it out */ + if (left > 0) { + for ( ; in < end && left < 8; in ++, left ++) + state->padding |= ((uint64_t) *in) << (left * 8); + + if (in == end && left < 8) + /* We did not have enough input to fill out the padding completely */ + return; + +#if ENABLE_DEBUG_SIPHASH + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); + printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding); +#endif + + state->v3 ^= state->padding; + sipround(state); + sipround(state); + state->v0 ^= state->padding; + + state->padding = 0; + } + + end -= (state->inlen % sizeof(uint64_t)); + + for ( ; in < end; in += 8) { + m = unaligned_read_le64(in); +#if ENABLE_DEBUG_SIPHASH + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); + printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m); +#endif + state->v3 ^= m; + sipround(state); + sipround(state); + state->v0 ^= m; + } + + left = state->inlen & 7; + switch (left) { + case 7: + state->padding |= ((uint64_t) in[6]) << 48; + _fallthrough_; + case 6: + state->padding |= ((uint64_t) in[5]) << 40; + _fallthrough_; + case 5: + state->padding |= ((uint64_t) in[4]) << 32; + _fallthrough_; + case 4: + state->padding |= ((uint64_t) in[3]) << 24; + _fallthrough_; + case 3: + state->padding |= ((uint64_t) in[2]) << 16; + _fallthrough_; + case 2: + state->padding |= ((uint64_t) in[1]) << 8; + _fallthrough_; + case 1: + state->padding |= ((uint64_t) in[0]); + _fallthrough_; + case 0: + break; + } +} + +void siphash24_compress_boolean(bool in, struct siphash *state) { + int i = in; + + siphash24_compress(&i, sizeof i, state); +} + +uint64_t siphash24_finalize(struct siphash *state) { + uint64_t b; + + assert(state); + + b = state->padding | (((uint64_t) state->inlen) << 56); + +#if ENABLE_DEBUG_SIPHASH + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); + printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding); +#endif + + state->v3 ^= b; + sipround(state); + sipround(state); + state->v0 ^= b; + +#if ENABLE_DEBUG_SIPHASH + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); +#endif + state->v2 ^= 0xff; + + sipround(state); + sipround(state); + sipround(state); + sipround(state); + + return state->v0 ^ state->v1 ^ state->v2 ^ state->v3; +} + +uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]) { + struct siphash state; + + assert(in); + assert(k); + + siphash24_init(&state, k); + siphash24_compress(in, inlen, &state); + + return siphash24_finalize(&state); +} diff --git a/src/basic/siphash24.h b/src/basic/siphash24.h new file mode 100644 index 00000000..1937fea2 --- /dev/null +++ b/src/basic/siphash24.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include +#include +#include + +struct siphash { + uint64_t v0; + uint64_t v1; + uint64_t v2; + uint64_t v3; + uint64_t padding; + size_t inlen; +}; + +void siphash24_init(struct siphash *state, const uint8_t k[static 16]); +void siphash24_compress(const void *in, size_t inlen, struct siphash *state); +void siphash24_compress_boolean(bool in, struct siphash *state); +#define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state)) + +uint64_t siphash24_finalize(struct siphash *state); + +uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[static 16]); + +static inline uint64_t siphash24_string(const char *s, const uint8_t k[static 16]) { + return siphash24(s, strlen(s) + 1, k); +} diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c new file mode 100644 index 00000000..da9a2139 --- /dev/null +++ b/src/basic/smack-util.c @@ -0,0 +1,288 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Intel Corporation + + Author: Auke Kok +***/ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "macro.h" +#include "path-util.h" +#include "process-util.h" +#include "smack-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "xattr-util.h" + +#if ENABLE_SMACK +bool mac_smack_use(void) { + static int cached_use = -1; + + if (cached_use < 0) + cached_use = access("/sys/fs/smackfs/", F_OK) >= 0; + + return cached_use; +} + +static const char* const smack_attr_table[_SMACK_ATTR_MAX] = { + [SMACK_ATTR_ACCESS] = "security.SMACK64", + [SMACK_ATTR_EXEC] = "security.SMACK64EXEC", + [SMACK_ATTR_MMAP] = "security.SMACK64MMAP", + [SMACK_ATTR_TRANSMUTE] = "security.SMACK64TRANSMUTE", + [SMACK_ATTR_IPIN] = "security.SMACK64IPIN", + [SMACK_ATTR_IPOUT] = "security.SMACK64IPOUT", +}; + +DEFINE_STRING_TABLE_LOOKUP(smack_attr, SmackAttr); + +int mac_smack_read(const char *path, SmackAttr attr, char **label) { + assert(path); + assert(attr >= 0 && attr < _SMACK_ATTR_MAX); + assert(label); + + if (!mac_smack_use()) + return 0; + + return getxattr_malloc(path, smack_attr_to_string(attr), label, true); +} + +int mac_smack_read_fd(int fd, SmackAttr attr, char **label) { + assert(fd >= 0); + assert(attr >= 0 && attr < _SMACK_ATTR_MAX); + assert(label); + + if (!mac_smack_use()) + return 0; + + return fgetxattr_malloc(fd, smack_attr_to_string(attr), label); +} + +int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { + int r; + + assert(path); + assert(attr >= 0 && attr < _SMACK_ATTR_MAX); + + if (!mac_smack_use()) + return 0; + + if (label) + r = lsetxattr(path, smack_attr_to_string(attr), label, strlen(label), 0); + else + r = lremovexattr(path, smack_attr_to_string(attr)); + if (r < 0) + return -errno; + + return 0; +} + +int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { + int r; + + assert(fd >= 0); + assert(attr >= 0 && attr < _SMACK_ATTR_MAX); + + if (!mac_smack_use()) + return 0; + + if (label) + r = fsetxattr(fd, smack_attr_to_string(attr), label, strlen(label), 0); + else + r = fremovexattr(fd, smack_attr_to_string(attr)); + if (r < 0) + return -errno; + + return 0; +} + +int mac_smack_apply_pid(pid_t pid, const char *label) { + const char *p; + int r = 0; + + assert(label); + + if (!mac_smack_use()) + return 0; + + p = procfs_file_alloca(pid, "attr/current"); + r = write_string_file(p, label, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return r; + + return r; +} + +static int smack_fix_fd(int fd , const char *abspath, LabelFixFlags flags) { + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + const char *label; + struct stat st; + int r; + + /* The caller should have done the sanity checks. */ + assert(abspath); + assert(path_is_absolute(abspath)); + + /* Path must be in /dev. */ + if (!path_startswith(abspath, "/dev")) + return 0; + + if (fstat(fd, &st) < 0) + return -errno; + + /* + * Label directories and character devices "*". + * Label symlinks "_". + * Don't change anything else. + */ + + if (S_ISDIR(st.st_mode)) + label = SMACK_STAR_LABEL; + else if (S_ISLNK(st.st_mode)) + label = SMACK_FLOOR_LABEL; + else if (S_ISCHR(st.st_mode)) + label = SMACK_STAR_LABEL; + else + return 0; + + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + if (setxattr(procfs_path, "security.SMACK64", label, strlen(label), 0) < 0) { + _cleanup_free_ char *old_label = NULL; + + r = -errno; + + /* If the FS doesn't support labels, then exit without warning */ + if (r == -EOPNOTSUPP) + return 0; + + /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */ + if (r == -EROFS && (flags & LABEL_IGNORE_EROFS)) + return 0; + + /* If the old label is identical to the new one, suppress any kind of error */ + if (getxattr_malloc(procfs_path, "security.SMACK64", &old_label, false) >= 0 && + streq(old_label, label)) + return 0; + + return log_debug_errno(r, "Unable to fix SMACK label of %s: %m", abspath); + } + + return 0; +} + +int mac_smack_fix_at(int dirfd, const char *path, LabelFixFlags flags) { + _cleanup_free_ char *p = NULL; + _cleanup_close_ int fd = -1; + int r; + + assert(path); + + if (!mac_smack_use()) + return 0; + + fd = openat(dirfd, path, O_NOFOLLOW|O_CLOEXEC|O_PATH); + if (fd < 0) { + if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT) + return 0; + + return -errno; + } + + if (!path_is_absolute(path)) { + r = fd_get_path(fd, &p); + if (r < 0) + return r; + path = p; + } + + return smack_fix_fd(fd, path, flags); +} + +int mac_smack_fix(const char *path, LabelFixFlags flags) { + _cleanup_free_ char *abspath = NULL; + _cleanup_close_ int fd = -1; + int r; + + assert(path); + + if (!mac_smack_use()) + return 0; + + r = path_make_absolute_cwd(path, &abspath); + if (r < 0) + return r; + + fd = open(abspath, O_NOFOLLOW|O_CLOEXEC|O_PATH); + if (fd < 0) { + if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT) + return 0; + + return -errno; + } + + return smack_fix_fd(fd, abspath, flags); +} + +int mac_smack_copy(const char *dest, const char *src) { + int r = 0; + _cleanup_free_ char *label = NULL; + + assert(dest); + assert(src); + + r = mac_smack_read(src, SMACK_ATTR_ACCESS, &label); + if (r < 0) + return r; + + r = mac_smack_apply(dest, SMACK_ATTR_ACCESS, label); + if (r < 0) + return r; + + return r; +} + +#else +bool mac_smack_use(void) { + return false; +} + +int mac_smack_read(const char *path, SmackAttr attr, char **label) { + return -EOPNOTSUPP; +} + +int mac_smack_read_fd(int fd, SmackAttr attr, char **label) { + return -EOPNOTSUPP; +} + +int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { + return 0; +} + +int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { + return 0; +} + +int mac_smack_apply_pid(pid_t pid, const char *label) { + return 0; +} + +int mac_smack_fix(const char *path, LabelFixFlags flags) { + return 0; +} + +int mac_smack_fix_at(int dirfd, const char *path, LabelFixFlags flags) { + return 0; +} + +int mac_smack_copy(const char *dest, const char *src) { + return 0; +} +#endif diff --git a/src/basic/smack-util.h b/src/basic/smack-util.h new file mode 100644 index 00000000..395ec07b --- /dev/null +++ b/src/basic/smack-util.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2013 Intel Corporation + + Author: Auke Kok +***/ + +#include +#include + +#include "label.h" +#include "macro.h" + +#define SMACK_FLOOR_LABEL "_" +#define SMACK_STAR_LABEL "*" + +typedef enum SmackAttr { + SMACK_ATTR_ACCESS, + SMACK_ATTR_EXEC, + SMACK_ATTR_MMAP, + SMACK_ATTR_TRANSMUTE, + SMACK_ATTR_IPIN, + SMACK_ATTR_IPOUT, + _SMACK_ATTR_MAX, + _SMACK_ATTR_INVALID = -1, +} SmackAttr; + +bool mac_smack_use(void); + +int mac_smack_fix(const char *path, LabelFixFlags flags); +int mac_smack_fix_at(int dirfd, const char *path, LabelFixFlags flags); + +const char* smack_attr_to_string(SmackAttr i) _const_; +SmackAttr smack_attr_from_string(const char *s) _pure_; +int mac_smack_read(const char *path, SmackAttr attr, char **label); +int mac_smack_read_fd(int fd, SmackAttr attr, char **label); +int mac_smack_apply(const char *path, SmackAttr attr, const char *label); +int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label); +int mac_smack_apply_pid(pid_t pid, const char *label); +int mac_smack_copy(const char *dest, const char *src); diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c new file mode 100644 index 00000000..8c087268 --- /dev/null +++ b/src/basic/socket-label.c @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "log.h" +#include "macro.h" +#include "missing_socket.h" +#include "mkdir.h" +#include "selinux-util.h" +#include "socket-util.h" +#include "umask-util.h" + +int socket_address_listen( + const SocketAddress *a, + int flags, + int backlog, + SocketAddressBindIPv6Only only, + const char *bind_to_device, + bool reuse_port, + bool free_bind, + bool transparent, + mode_t directory_mode, + mode_t socket_mode, + const char *label) { + + _cleanup_close_ int fd = -1; + const char *p; + int r; + + assert(a); + + r = socket_address_verify(a, true); + if (r < 0) + return r; + + if (socket_address_family(a) == AF_INET6 && !socket_ipv6_is_supported()) + return -EAFNOSUPPORT; + + if (label) { + r = mac_selinux_create_socket_prepare(label); + if (r < 0) + return r; + } + + fd = socket(socket_address_family(a), a->type | flags, a->protocol); + r = fd < 0 ? -errno : 0; + + if (label) + mac_selinux_create_socket_clear(); + + if (r < 0) + return r; + + if (socket_address_family(a) == AF_INET6 && only != SOCKET_ADDRESS_DEFAULT) { + r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_V6ONLY, only == SOCKET_ADDRESS_IPV6_ONLY); + if (r < 0) + return r; + } + + if (IN_SET(socket_address_family(a), AF_INET, AF_INET6)) { + if (bind_to_device) { + r = socket_bind_to_ifname(fd, bind_to_device); + if (r < 0) + return r; + } + + if (reuse_port) { + r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEPORT, true); + if (r < 0) + log_warning_errno(r, "SO_REUSEPORT failed: %m"); + } + + if (free_bind) { + r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true); + if (r < 0) + log_warning_errno(r, "IP_FREEBIND failed: %m"); + } + + if (transparent) { + r = setsockopt_int(fd, IPPROTO_IP, IP_TRANSPARENT, true); + if (r < 0) + log_warning_errno(r, "IP_TRANSPARENT failed: %m"); + } + } + + r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return r; + + p = socket_address_get_path(a); + if (p) { + /* Create parents */ + (void) mkdir_parents_label(p, directory_mode); + + /* Enforce the right access mode for the socket */ + RUN_WITH_UMASK(~socket_mode) { + r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size); + if (r == -EADDRINUSE) { + /* Unlink and try again */ + + if (unlink(p) < 0) + return r; /* didn't work, return original error */ + + r = mac_selinux_bind(fd, &a->sockaddr.sa, a->size); + } + if (r < 0) + return r; + } + } else { + if (bind(fd, &a->sockaddr.sa, a->size) < 0) + return -errno; + } + + if (socket_address_can_accept(a)) + if (listen(fd, backlog) < 0) + return -errno; + + /* Let's trigger an inotify event on the socket node, so that anyone waiting for this socket to be connectable + * gets notified */ + if (p) + (void) touch(p); + + r = fd; + fd = -1; + + return r; +} + +int make_socket_fd(int log_level, const char* address, int type, int flags) { + SocketAddress a; + int fd, r; + + r = socket_address_parse(&a, address); + if (r < 0) + return log_error_errno(r, "Failed to parse socket address \"%s\": %m", address); + + a.type = type; + + fd = socket_address_listen(&a, type | flags, SOMAXCONN, SOCKET_ADDRESS_DEFAULT, + NULL, false, false, false, 0755, 0644, NULL); + if (fd < 0 || log_get_max_level() >= log_level) { + _cleanup_free_ char *p = NULL; + + r = socket_address_print(&a, &p); + if (r < 0) + return log_error_errno(r, "socket_address_print(): %m"); + + if (fd < 0) + log_error_errno(fd, "Failed to listen on %s: %m", p); + else + log_full(log_level, "Listening on %s", p); + } + + return fd; +} diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c new file mode 100644 index 00000000..19dd053e --- /dev/null +++ b/src/basic/socket-util.c @@ -0,0 +1,1414 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "errno-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "log.h" +#include "macro.h" +#include "memory-util.h" +#include "missing_socket.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "socket-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "utf8.h" + +#if ENABLE_IDN +# define IDN_FLAGS NI_IDN +#else +# define IDN_FLAGS 0 +#endif + +static const char* const socket_address_type_table[] = { + [SOCK_STREAM] = "Stream", + [SOCK_DGRAM] = "Datagram", + [SOCK_RAW] = "Raw", + [SOCK_RDM] = "ReliableDatagram", + [SOCK_SEQPACKET] = "SequentialPacket", + [SOCK_DCCP] = "DatagramCongestionControl", +}; + +DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int); + +int socket_address_parse(SocketAddress *a, const char *s) { + _cleanup_free_ char *n = NULL; + char *e; + int r; + + assert(a); + assert(s); + + *a = (SocketAddress) { + .type = SOCK_STREAM, + }; + + if (*s == '[') { + uint16_t port; + + /* IPv6 in [x:.....:z]:p notation */ + + e = strchr(s+1, ']'); + if (!e) + return -EINVAL; + + n = strndup(s+1, e-s-1); + if (!n) + return -ENOMEM; + + errno = 0; + if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0) + return errno_or_else(EINVAL); + + e++; + if (*e != ':') + return -EINVAL; + + e++; + r = parse_ip_port(e, &port); + if (r < 0) + return r; + + a->sockaddr.in6.sin6_family = AF_INET6; + a->sockaddr.in6.sin6_port = htobe16(port); + a->size = sizeof(struct sockaddr_in6); + + } else if (*s == '/') { + /* AF_UNIX socket */ + + size_t l; + + l = strlen(s); + if (l >= sizeof(a->sockaddr.un.sun_path)) /* Note that we refuse non-NUL-terminated sockets when + * parsing (the kernel itself is less strict here in what it + * accepts) */ + return -EINVAL; + + a->sockaddr.un.sun_family = AF_UNIX; + memcpy(a->sockaddr.un.sun_path, s, l); + a->size = offsetof(struct sockaddr_un, sun_path) + l + 1; + + } else if (*s == '@') { + /* Abstract AF_UNIX socket */ + size_t l; + + l = strlen(s+1); + if (l >= sizeof(a->sockaddr.un.sun_path) - 1) /* Note that we refuse non-NUL-terminated sockets here + * when parsing, even though abstract namespace sockets + * explicitly allow embedded NUL bytes and don't consider + * them special. But it's simply annoying to debug such + * sockets. */ + return -EINVAL; + + a->sockaddr.un.sun_family = AF_UNIX; + memcpy(a->sockaddr.un.sun_path+1, s+1, l); + a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l; + + } else if (startswith(s, "vsock:")) { + /* AF_VSOCK socket in vsock:cid:port notation */ + const char *cid_start = s + STRLEN("vsock:"); + unsigned port; + + e = strchr(cid_start, ':'); + if (!e) + return -EINVAL; + + r = safe_atou(e+1, &port); + if (r < 0) + return r; + + n = strndup(cid_start, e - cid_start); + if (!n) + return -ENOMEM; + + if (!isempty(n)) { + r = safe_atou(n, &a->sockaddr.vm.svm_cid); + if (r < 0) + return r; + } else + a->sockaddr.vm.svm_cid = VMADDR_CID_ANY; + + a->sockaddr.vm.svm_family = AF_VSOCK; + a->sockaddr.vm.svm_port = port; + a->size = sizeof(struct sockaddr_vm); + + } else { + uint16_t port; + + e = strchr(s, ':'); + if (e) { + r = parse_ip_port(e + 1, &port); + if (r < 0) + return r; + + n = strndup(s, e-s); + if (!n) + return -ENOMEM; + + /* IPv4 in w.x.y.z:p notation? */ + r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr); + if (r < 0) + return -errno; + + if (r > 0) { + /* Gotcha, it's a traditional IPv4 address */ + a->sockaddr.in.sin_family = AF_INET; + a->sockaddr.in.sin_port = htobe16(port); + a->size = sizeof(struct sockaddr_in); + } else { + unsigned idx; + + if (strlen(n) > IF_NAMESIZE-1) + return -EINVAL; + + /* Uh, our last resort, an interface name */ + idx = if_nametoindex(n); + if (idx == 0) + return -EINVAL; + + a->sockaddr.in6.sin6_family = AF_INET6; + a->sockaddr.in6.sin6_port = htobe16(port); + a->sockaddr.in6.sin6_scope_id = idx; + a->sockaddr.in6.sin6_addr = in6addr_any; + a->size = sizeof(struct sockaddr_in6); + } + } else { + + /* Just a port */ + r = parse_ip_port(s, &port); + if (r < 0) + return r; + + if (socket_ipv6_is_supported()) { + a->sockaddr.in6.sin6_family = AF_INET6; + a->sockaddr.in6.sin6_port = htobe16(port); + a->sockaddr.in6.sin6_addr = in6addr_any; + a->size = sizeof(struct sockaddr_in6); + } else { + a->sockaddr.in.sin_family = AF_INET; + a->sockaddr.in.sin_port = htobe16(port); + a->sockaddr.in.sin_addr.s_addr = INADDR_ANY; + a->size = sizeof(struct sockaddr_in); + } + } + } + + return 0; +} + +int socket_address_parse_and_warn(SocketAddress *a, const char *s) { + SocketAddress b; + int r; + + /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */ + + r = socket_address_parse(&b, s); + if (r < 0) + return r; + + if (!socket_ipv6_is_supported() && b.sockaddr.sa.sa_family == AF_INET6) { + log_warning("Binding to IPv6 address not available since kernel does not support IPv6."); + return -EAFNOSUPPORT; + } + + *a = b; + return 0; +} + +int socket_address_parse_netlink(SocketAddress *a, const char *s) { + _cleanup_free_ char *word = NULL; + unsigned group = 0; + int family, r; + + assert(a); + assert(s); + + zero(*a); + a->type = SOCK_RAW; + + r = extract_first_word(&s, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + family = netlink_family_from_string(word); + if (family < 0) + return -EINVAL; + + if (!isempty(s)) { + r = safe_atou(s, &group); + if (r < 0) + return r; + } + + a->sockaddr.nl.nl_family = AF_NETLINK; + a->sockaddr.nl.nl_groups = group; + + a->type = SOCK_RAW; + a->size = sizeof(struct sockaddr_nl); + a->protocol = family; + + return 0; +} + +int socket_address_verify(const SocketAddress *a, bool strict) { + assert(a); + + /* With 'strict' we enforce additional sanity constraints which are not set by the standard, + * but should only apply to sockets we create ourselves. */ + + switch (socket_address_family(a)) { + + case AF_INET: + if (a->size != sizeof(struct sockaddr_in)) + return -EINVAL; + + if (a->sockaddr.in.sin_port == 0) + return -EINVAL; + + if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) + return -EINVAL; + + return 0; + + case AF_INET6: + if (a->size != sizeof(struct sockaddr_in6)) + return -EINVAL; + + if (a->sockaddr.in6.sin6_port == 0) + return -EINVAL; + + if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) + return -EINVAL; + + return 0; + + case AF_UNIX: + if (a->size < offsetof(struct sockaddr_un, sun_path)) + return -EINVAL; + if (a->size > sizeof(struct sockaddr_un) + !strict) + /* If !strict, allow one extra byte, since getsockname() on Linux will append + * a NUL byte if we have path sockets that are above sun_path's full size. */ + return -EINVAL; + + if (a->size > offsetof(struct sockaddr_un, sun_path) && + a->sockaddr.un.sun_path[0] != 0 && + strict) { + /* Only validate file system sockets here, and only in strict mode */ + const char *e; + + e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path)); + if (e) { + /* If there's an embedded NUL byte, make sure the size of the socket address matches it */ + if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1) + return -EINVAL; + } else { + /* If there's no embedded NUL byte, then then the size needs to match the whole + * structure or the structure with one extra NUL byte suffixed. (Yeah, Linux is awful, + * and considers both equivalent: getsockname() even extends sockaddr_un beyond its + * size if the path is non NUL terminated.)*/ + if (!IN_SET(a->size, sizeof(a->sockaddr.un.sun_path), sizeof(a->sockaddr.un.sun_path)+1)) + return -EINVAL; + } + } + + if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET)) + return -EINVAL; + + return 0; + + case AF_NETLINK: + + if (a->size != sizeof(struct sockaddr_nl)) + return -EINVAL; + + if (!IN_SET(a->type, SOCK_RAW, SOCK_DGRAM)) + return -EINVAL; + + return 0; + + case AF_VSOCK: + if (a->size != sizeof(struct sockaddr_vm)) + return -EINVAL; + + if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM)) + return -EINVAL; + + return 0; + + default: + return -EAFNOSUPPORT; + } +} + +int socket_address_print(const SocketAddress *a, char **ret) { + int r; + + assert(a); + assert(ret); + + r = socket_address_verify(a, false); /* We do non-strict validation, because we want to be + * able to pretty-print any socket the kernel considers + * valid. We still need to do validation to know if we + * can meaningfully print the address. */ + if (r < 0) + return r; + + if (socket_address_family(a) == AF_NETLINK) { + _cleanup_free_ char *sfamily = NULL; + + r = netlink_family_to_string_alloc(a->protocol, &sfamily); + if (r < 0) + return r; + + r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups); + if (r < 0) + return -ENOMEM; + + return 0; + } + + return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret); +} + +bool socket_address_can_accept(const SocketAddress *a) { + assert(a); + + return + IN_SET(a->type, SOCK_STREAM, SOCK_SEQPACKET); +} + +bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) { + assert(a); + assert(b); + + /* Invalid addresses are unequal to all */ + if (socket_address_verify(a, false) < 0 || + socket_address_verify(b, false) < 0) + return false; + + if (a->type != b->type) + return false; + + if (socket_address_family(a) != socket_address_family(b)) + return false; + + switch (socket_address_family(a)) { + + case AF_INET: + if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr) + return false; + + if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port) + return false; + + break; + + case AF_INET6: + if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0) + return false; + + if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port) + return false; + + break; + + case AF_UNIX: + if (a->size <= offsetof(struct sockaddr_un, sun_path) || + b->size <= offsetof(struct sockaddr_un, sun_path)) + return false; + + if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0)) + return false; + + if (a->sockaddr.un.sun_path[0]) { + if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, 0)) + return false; + } else { + if (a->size != b->size) + return false; + + if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0) + return false; + } + + break; + + case AF_NETLINK: + if (a->protocol != b->protocol) + return false; + + if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups) + return false; + + break; + + case AF_VSOCK: + if (a->sockaddr.vm.svm_cid != b->sockaddr.vm.svm_cid) + return false; + + if (a->sockaddr.vm.svm_port != b->sockaddr.vm.svm_port) + return false; + + break; + + default: + /* Cannot compare, so we assume the addresses are different */ + return false; + } + + return true; +} + +bool socket_address_is(const SocketAddress *a, const char *s, int type) { + struct SocketAddress b; + + assert(a); + assert(s); + + if (socket_address_parse(&b, s) < 0) + return false; + + b.type = type; + + return socket_address_equal(a, &b); +} + +bool socket_address_is_netlink(const SocketAddress *a, const char *s) { + struct SocketAddress b; + + assert(a); + assert(s); + + if (socket_address_parse_netlink(&b, s) < 0) + return false; + + return socket_address_equal(a, &b); +} + +const char* socket_address_get_path(const SocketAddress *a) { + assert(a); + + if (socket_address_family(a) != AF_UNIX) + return NULL; + + if (a->sockaddr.un.sun_path[0] == 0) + return NULL; + + /* Note that this is only safe because we know that there's an extra NUL byte after the sockaddr_un + * structure. On Linux AF_UNIX file system socket addresses don't have to be NUL terminated if they take up the + * full sun_path space. */ + assert_cc(sizeof(union sockaddr_union) >= sizeof(struct sockaddr_un)+1); + return a->sockaddr.un.sun_path; +} + +bool socket_ipv6_is_supported(void) { + if (access("/proc/net/if_inet6", F_OK) != 0) + return false; + + return true; +} + +bool socket_address_matches_fd(const SocketAddress *a, int fd) { + SocketAddress b; + socklen_t solen; + + assert(a); + assert(fd >= 0); + + b.size = sizeof(b.sockaddr); + if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0) + return false; + + if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family) + return false; + + solen = sizeof(b.type); + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0) + return false; + + if (b.type != a->type) + return false; + + if (a->protocol != 0) { + solen = sizeof(b.protocol); + if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0) + return false; + + if (b.protocol != a->protocol) + return false; + } + + return socket_address_equal(a, &b); +} + +int sockaddr_port(const struct sockaddr *_sa, unsigned *ret_port) { + union sockaddr_union *sa = (union sockaddr_union*) _sa; + + /* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */ + + assert(sa); + + switch (sa->sa.sa_family) { + + case AF_INET: + *ret_port = be16toh(sa->in.sin_port); + return 0; + + case AF_INET6: + *ret_port = be16toh(sa->in6.sin6_port); + return 0; + + case AF_VSOCK: + *ret_port = sa->vm.svm_port; + return 0; + + default: + return -EAFNOSUPPORT; + } +} + +int sockaddr_pretty( + const struct sockaddr *_sa, + socklen_t salen, + bool translate_ipv6, + bool include_port, + char **ret) { + + union sockaddr_union *sa = (union sockaddr_union*) _sa; + char *p; + int r; + + assert(sa); + assert(salen >= sizeof(sa->sa.sa_family)); + + switch (sa->sa.sa_family) { + + case AF_INET: { + uint32_t a; + + a = be32toh(sa->in.sin_addr.s_addr); + + if (include_port) + r = asprintf(&p, + "%u.%u.%u.%u:%u", + a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF, + be16toh(sa->in.sin_port)); + else + r = asprintf(&p, + "%u.%u.%u.%u", + a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF); + if (r < 0) + return -ENOMEM; + break; + } + + case AF_INET6: { + static const unsigned char ipv4_prefix[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF + }; + + if (translate_ipv6 && + memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) { + const uint8_t *a = sa->in6.sin6_addr.s6_addr+12; + if (include_port) + r = asprintf(&p, + "%u.%u.%u.%u:%u", + a[0], a[1], a[2], a[3], + be16toh(sa->in6.sin6_port)); + else + r = asprintf(&p, + "%u.%u.%u.%u", + a[0], a[1], a[2], a[3]); + if (r < 0) + return -ENOMEM; + } else { + char a[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)); + + if (include_port) { + r = asprintf(&p, + "[%s]:%u", + a, + be16toh(sa->in6.sin6_port)); + if (r < 0) + return -ENOMEM; + } else { + p = strdup(a); + if (!p) + return -ENOMEM; + } + } + + break; + } + + case AF_UNIX: + if (salen <= offsetof(struct sockaddr_un, sun_path) || + (sa->un.sun_path[0] == 0 && salen == offsetof(struct sockaddr_un, sun_path) + 1)) + /* The name must have at least one character (and the leading NUL does not count) */ + p = strdup(""); + else { + /* Note that we calculate the path pointer here through the .un_buffer[] field, in order to + * outtrick bounds checking tools such as ubsan, which are too smart for their own good: on + * Linux the kernel may return sun_path[] data one byte longer than the declared size of the + * field. */ + char *path = (char*) sa->un_buffer + offsetof(struct sockaddr_un, sun_path); + size_t path_len = salen - offsetof(struct sockaddr_un, sun_path); + + if (path[0] == 0) { + /* Abstract socket. When parsing address information from, we + * explicitly reject overly long paths and paths with embedded NULs. + * But we might get such a socket from the outside. Let's return + * something meaningful and printable in this case. */ + + _cleanup_free_ char *e = NULL; + + e = cescape_length(path + 1, path_len - 1); + if (!e) + return -ENOMEM; + + p = strjoin("@", e); + } else { + if (path[path_len - 1] == '\0') + /* We expect a terminating NUL and don't print it */ + path_len --; + + p = cescape_length(path, path_len); + } + } + if (!p) + return -ENOMEM; + + break; + + case AF_VSOCK: + if (include_port) { + if (sa->vm.svm_cid == VMADDR_CID_ANY) + r = asprintf(&p, "vsock::%u", sa->vm.svm_port); + else + r = asprintf(&p, "vsock:%u:%u", sa->vm.svm_cid, sa->vm.svm_port); + } else + r = asprintf(&p, "vsock:%u", sa->vm.svm_cid); + if (r < 0) + return -ENOMEM; + break; + + default: + return -EOPNOTSUPP; + } + + *ret = p; + return 0; +} + +int getpeername_pretty(int fd, bool include_port, char **ret) { + union sockaddr_union sa; + socklen_t salen = sizeof(sa); + int r; + + assert(fd >= 0); + assert(ret); + + if (getpeername(fd, &sa.sa, &salen) < 0) + return -errno; + + if (sa.sa.sa_family == AF_UNIX) { + struct ucred ucred = {}; + + /* UNIX connection sockets are anonymous, so let's use + * PID/UID as pretty credentials instead */ + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0) + return -ENOMEM; + + return 0; + } + + /* For remote sockets we translate IPv6 addresses back to IPv4 + * if applicable, since that's nicer. */ + + return sockaddr_pretty(&sa.sa, salen, true, include_port, ret); +} + +int getsockname_pretty(int fd, char **ret) { + union sockaddr_union sa; + socklen_t salen = sizeof(sa); + + assert(fd >= 0); + assert(ret); + + if (getsockname(fd, &sa.sa, &salen) < 0) + return -errno; + + /* For local sockets we do not translate IPv6 addresses back + * to IPv6 if applicable, since this is usually used for + * listening sockets where the difference between IPv4 and + * IPv6 matters. */ + + return sockaddr_pretty(&sa.sa, salen, false, true, ret); +} + +int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) { + int r; + char host[NI_MAXHOST], *ret; + + assert(_ret); + + r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0, IDN_FLAGS); + if (r != 0) { + int saved_errno = errno; + + r = sockaddr_pretty(&sa->sa, salen, true, true, &ret); + if (r < 0) + return r; + + log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret); + } else { + ret = strdup(host); + if (!ret) + return -ENOMEM; + } + + *_ret = ret; + return 0; +} + +static const char* const netlink_family_table[] = { + [NETLINK_ROUTE] = "route", + [NETLINK_FIREWALL] = "firewall", + [NETLINK_INET_DIAG] = "inet-diag", + [NETLINK_NFLOG] = "nflog", + [NETLINK_XFRM] = "xfrm", + [NETLINK_SELINUX] = "selinux", + [NETLINK_ISCSI] = "iscsi", + [NETLINK_AUDIT] = "audit", + [NETLINK_FIB_LOOKUP] = "fib-lookup", + [NETLINK_CONNECTOR] = "connector", + [NETLINK_NETFILTER] = "netfilter", + [NETLINK_IP6_FW] = "ip6-fw", + [NETLINK_DNRTMSG] = "dnrtmsg", + [NETLINK_KOBJECT_UEVENT] = "kobject-uevent", + [NETLINK_GENERIC] = "generic", + [NETLINK_SCSITRANSPORT] = "scsitransport", + [NETLINK_ECRYPTFS] = "ecryptfs", + [NETLINK_RDMA] = "rdma", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX); + +static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = { + [SOCKET_ADDRESS_DEFAULT] = "default", + [SOCKET_ADDRESS_BOTH] = "both", + [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only" +}; + +DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); + +SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *n) { + int r; + + r = parse_boolean(n); + if (r > 0) + return SOCKET_ADDRESS_IPV6_ONLY; + if (r == 0) + return SOCKET_ADDRESS_BOTH; + + return socket_address_bind_ipv6_only_from_string(n); +} + +bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) { + assert(a); + assert(b); + + if (a->sa.sa_family != b->sa.sa_family) + return false; + + if (a->sa.sa_family == AF_INET) + return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr; + + if (a->sa.sa_family == AF_INET6) + return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0; + + if (a->sa.sa_family == AF_VSOCK) + return a->vm.svm_cid == b->vm.svm_cid; + + return false; +} + +int fd_inc_sndbuf(int fd, size_t n) { + int r, value; + socklen_t l = sizeof(value); + + r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l); + if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) + return 0; + + /* If we have the privileges we will ignore the kernel limit. */ + + if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n) < 0) { + r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n); + if (r < 0) + return r; + } + + return 1; +} + +int fd_inc_rcvbuf(int fd, size_t n) { + int r, value; + socklen_t l = sizeof(value); + + r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l); + if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2) + return 0; + + /* If we have the privileges we will ignore the kernel limit. */ + + if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n) < 0) { + r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n); + if (r < 0) + return r; + } + + return 1; +} + +static const char* const ip_tos_table[] = { + [IPTOS_LOWDELAY] = "low-delay", + [IPTOS_THROUGHPUT] = "throughput", + [IPTOS_RELIABILITY] = "reliability", + [IPTOS_LOWCOST] = "low-cost", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); + +bool ifname_valid(const char *p) { + bool numeric = true; + + /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources + * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We + * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */ + + if (isempty(p)) + return false; + + if (strlen(p) >= IFNAMSIZ) + return false; + + if (dot_or_dot_dot(p)) + return false; + + while (*p) { + if ((unsigned char) *p >= 127U) + return false; + + if ((unsigned char) *p <= 32U) + return false; + + if (IN_SET(*p, ':', '/')) + return false; + + numeric = numeric && (*p >= '0' && *p <= '9'); + p++; + } + + if (numeric) + return false; + + return true; +} + +bool address_label_valid(const char *p) { + + if (isempty(p)) + return false; + + if (strlen(p) >= IFNAMSIZ) + return false; + + while (*p) { + if ((uint8_t) *p >= 127U) + return false; + + if ((uint8_t) *p <= 31U) + return false; + p++; + } + + return true; +} + +int getpeercred(int fd, struct ucred *ucred) { + socklen_t n = sizeof(struct ucred); + struct ucred u; + int r; + + assert(fd >= 0); + assert(ucred); + + r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n); + if (r < 0) + return -errno; + + if (n != sizeof(struct ucred)) + return -EIO; + + /* Check if the data is actually useful and not suppressed due to namespacing issues */ + if (!pid_is_valid(u.pid)) + return -ENODATA; + + /* Note that we don't check UID/GID here, as namespace translation works differently there: instead of + * receiving in "invalid" user/group we get the overflow UID/GID. */ + + *ucred = u; + return 0; +} + +int getpeersec(int fd, char **ret) { + _cleanup_free_ char *s = NULL; + socklen_t n = 64; + + assert(fd >= 0); + assert(ret); + + for (;;) { + s = new0(char, n+1); + if (!s) + return -ENOMEM; + + if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n) >= 0) + break; + + if (errno != ERANGE) + return -errno; + + s = mfree(s); + } + + if (isempty(s)) + return -EOPNOTSUPP; + + *ret = TAKE_PTR(s); + + return 0; +} + +int getpeergroups(int fd, gid_t **ret) { + socklen_t n = sizeof(gid_t) * 64; + _cleanup_free_ gid_t *d = NULL; + + assert(fd >= 0); + assert(ret); + + for (;;) { + d = malloc(n); + if (!d) + return -ENOMEM; + + if (getsockopt(fd, SOL_SOCKET, SO_PEERGROUPS, d, &n) >= 0) + break; + + if (errno != ERANGE) + return -errno; + + d = mfree(d); + } + + assert_se(n % sizeof(gid_t) == 0); + n /= sizeof(gid_t); + + if ((socklen_t) (int) n != n) + return -E2BIG; + + *ret = TAKE_PTR(d); + + return (int) n; +} + +ssize_t send_one_fd_iov_sa( + int transport_fd, + int fd, + struct iovec *iov, size_t iovlen, + const struct sockaddr *sa, socklen_t len, + int flags) { + + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int))]; + } control = {}; + struct msghdr mh = { + .msg_name = (struct sockaddr*) sa, + .msg_namelen = len, + .msg_iov = iov, + .msg_iovlen = iovlen, + }; + ssize_t k; + + assert(transport_fd >= 0); + + /* + * We need either an FD or data to send. + * If there's nothing, return an error. + */ + if (fd < 0 && !iov) + return -EINVAL; + + if (fd >= 0) { + struct cmsghdr *cmsg; + + mh.msg_control = &control; + mh.msg_controllen = sizeof(control); + + cmsg = CMSG_FIRSTHDR(&mh); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); + + mh.msg_controllen = CMSG_SPACE(sizeof(int)); + } + k = sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags); + if (k < 0) + return (ssize_t) -errno; + + return k; +} + +int send_one_fd_sa( + int transport_fd, + int fd, + const struct sockaddr *sa, socklen_t len, + int flags) { + + assert(fd >= 0); + + return (int) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, sa, len, flags); +} + +ssize_t receive_one_fd_iov( + int transport_fd, + struct iovec *iov, size_t iovlen, + int flags, + int *ret_fd) { + + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int))]; + } control = {}; + struct msghdr mh = { + .msg_control = &control, + .msg_controllen = sizeof(control), + .msg_iov = iov, + .msg_iovlen = iovlen, + }; + struct cmsghdr *cmsg, *found = NULL; + ssize_t k; + + assert(transport_fd >= 0); + assert(ret_fd); + + /* + * Receive a single FD via @transport_fd. We don't care for + * the transport-type. We retrieve a single FD at most, so for + * packet-based transports, the caller must ensure to send + * only a single FD per packet. This is best used in + * combination with send_one_fd(). + */ + + k = recvmsg(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags); + if (k < 0) + return (ssize_t) -errno; + + CMSG_FOREACH(cmsg, &mh) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS && + cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { + assert(!found); + found = cmsg; + break; + } + } + + if (!found) + cmsg_close_all(&mh); + + /* If didn't receive an FD or any data, return an error. */ + if (k == 0 && !found) + return -EIO; + + if (found) + *ret_fd = *(int*) CMSG_DATA(found); + else + *ret_fd = -1; + + return k; +} + +int receive_one_fd(int transport_fd, int flags) { + int fd; + ssize_t k; + + k = receive_one_fd_iov(transport_fd, NULL, 0, flags, &fd); + if (k == 0) + return fd; + + /* k must be negative, since receive_one_fd_iov() only returns + * a positive value if data was received through the iov. */ + assert(k < 0); + return (int) k; +} + +ssize_t next_datagram_size_fd(int fd) { + ssize_t l; + int k; + + /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will + * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't + * do. This difference is actually of major importance as we need to be sure that the size returned here + * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of + * the wrong size. */ + + l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC); + if (l < 0) { + if (IN_SET(errno, EOPNOTSUPP, EFAULT)) + goto fallback; + + return -errno; + } + if (l == 0) + goto fallback; + + return l; + +fallback: + k = 0; + + /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD + * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */ + + if (ioctl(fd, FIONREAD, &k) < 0) + return -errno; + + return (ssize_t) k; +} + +/* Put a limit on how many times will attempt to call accept4(). We loop + * only on "transient" errors, but let's make sure we don't loop forever. */ +#define MAX_FLUSH_ITERATIONS 1024 + +int flush_accept(int fd) { + + struct pollfd pollfd = { + .fd = fd, + .events = POLLIN, + }; + int r, b; + socklen_t l = sizeof(b); + + /* Similar to flush_fd() but flushes all incoming connections by accepting and immediately closing + * them. */ + + if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0) + return -errno; + + assert(l == sizeof(b)); + if (!b) /* Let's check if this socket accepts connections before calling accept(). accept4() can + * return EOPNOTSUPP if the fd is not a listening socket, which we should treat as a fatal + * error, or in case the incoming TCP connection triggered a network issue, which we want to + * treat as a transient error. Thus, let's rule out the first reason for EOPNOTSUPP early, so + * we can loop safely on transient errors below. */ + return -ENOTTY; + + for (unsigned iteration = 0;; iteration++) { + int cfd; + + r = poll(&pollfd, 1, 0); + if (r < 0) { + if (errno == EINTR) + continue; + + return -errno; + } + if (r == 0) + return 0; + + if (iteration >= MAX_FLUSH_ITERATIONS) + return log_debug_errno(SYNTHETIC_ERRNO(EBUSY), + "Failed to flush connections within " STRINGIFY(MAX_FLUSH_ITERATIONS) " iterations."); + + cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); + if (cfd < 0) { + if (errno == EAGAIN) + return 0; + + if (ERRNO_IS_ACCEPT_AGAIN(errno)) + continue; + + return -errno; + } + + safe_close(cfd); + } +} + +struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) { + struct cmsghdr *cmsg; + + assert(mh); + + CMSG_FOREACH(cmsg, mh) + if (cmsg->cmsg_level == level && + cmsg->cmsg_type == type && + (length == (socklen_t) -1 || length == cmsg->cmsg_len)) + return cmsg; + + return NULL; +} + +int socket_ioctl_fd(void) { + int fd; + + /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for + * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not + * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more + * generic AF_NETLINK. */ + + fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) + fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_GENERIC); + if (fd < 0) + return -errno; + + return fd; +} + +int sockaddr_un_unlink(const struct sockaddr_un *sa) { + const char *p, * nul; + + assert(sa); + + if (sa->sun_family != AF_UNIX) + return -EPROTOTYPE; + + if (sa->sun_path[0] == 0) /* Nothing to do for abstract sockets */ + return 0; + + /* The path in .sun_path is not necessarily NUL terminated. Let's fix that. */ + nul = memchr(sa->sun_path, 0, sizeof(sa->sun_path)); + if (nul) + p = sa->sun_path; + else + p = memdupa_suffix0(sa->sun_path, sizeof(sa->sun_path)); + + if (unlink(p) < 0) + return -errno; + + return 1; +} + +int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) { + size_t l; + + assert(ret); + assert(path); + + /* Initialize ret->sun_path from the specified argument. This will interpret paths starting with '@' as + * abstract namespace sockets, and those starting with '/' as regular filesystem sockets. It won't accept + * anything else (i.e. no relative paths), to avoid ambiguities. Note that this function cannot be used to + * reference paths in the abstract namespace that include NUL bytes in the name. */ + + l = strlen(path); + if (l == 0) + return -EINVAL; + if (!IN_SET(path[0], '/', '@')) + return -EINVAL; + if (path[1] == 0) + return -EINVAL; + + /* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than + * the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket + * addresses!), which the kernel doesn't. We do this to reduce chance of incompatibility with other apps that + * do not expect non-NUL terminated file system path*/ + if (l+1 > sizeof(ret->sun_path)) + return -EINVAL; + + *ret = (struct sockaddr_un) { + .sun_family = AF_UNIX, + }; + + if (path[0] == '@') { + /* Abstract namespace socket */ + memcpy(ret->sun_path + 1, path + 1, l); /* copy *with* trailing NUL byte */ + return (int) (offsetof(struct sockaddr_un, sun_path) + l); /* 🔥 *don't* 🔥 include trailing NUL in size */ + + } else { + assert(path[0] == '/'); + + /* File system socket */ + memcpy(ret->sun_path, path, l + 1); /* copy *with* trailing NUL byte */ + return (int) (offsetof(struct sockaddr_un, sun_path) + l + 1); /* include trailing NUL in size */ + } +} + +int socket_bind_to_ifname(int fd, const char *ifname) { + assert(fd >= 0); + + /* Call with NULL to drop binding */ + + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen_ptr(ifname)) < 0) + return -errno; + + return 0; +} + +int socket_bind_to_ifindex(int fd, int ifindex) { + char ifname[IF_NAMESIZE + 1]; + + assert(fd >= 0); + + if (ifindex <= 0) { + /* Drop binding */ + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, NULL, 0) < 0) + return -errno; + + return 0; + } + + if (setsockopt(fd, SOL_SOCKET, SO_BINDTOIFINDEX, &ifindex, sizeof(ifindex)) >= 0) + return 0; + if (errno != ENOPROTOOPT) + return -errno; + + /* Fall back to SO_BINDTODEVICE on kernels < 5.0 which didn't have SO_BINDTOIFINDEX */ + if (!format_ifname(ifindex, ifname)) + return -errno; + + return socket_bind_to_ifname(fd, ifname); +} diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h new file mode 100644 index 00000000..48a22415 --- /dev/null +++ b/src/basic/socket-util.h @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "macro.h" +#include "missing_socket.h" +#include "sparse-endian.h" + +union sockaddr_union { + /* The minimal, abstract version */ + struct sockaddr sa; + + /* The libc provided version that allocates "enough room" for every protocol */ + struct sockaddr_storage storage; + + /* Protoctol-specific implementations */ + struct sockaddr_in in; + struct sockaddr_in6 in6; + struct sockaddr_un un; + struct sockaddr_nl nl; + struct sockaddr_ll ll; + struct sockaddr_vm vm; + + /* Ensure there is enough space to store Infiniband addresses */ + uint8_t ll_buffer[offsetof(struct sockaddr_ll, sll_addr) + CONST_MAX(ETH_ALEN, INFINIBAND_ALEN)]; + + /* Ensure there is enough space after the AF_UNIX sun_path for one more NUL byte, just to be sure that the path + * component is always followed by at least one NUL byte. */ + uint8_t un_buffer[sizeof(struct sockaddr_un) + 1]; +}; + +typedef struct SocketAddress { + union sockaddr_union sockaddr; + + /* We store the size here explicitly due to the weird + * sockaddr_un semantics for abstract sockets */ + socklen_t size; + + /* Socket type, i.e. SOCK_STREAM, SOCK_DGRAM, ... */ + int type; + + /* Socket protocol, IPPROTO_xxx, usually 0, except for netlink */ + int protocol; +} SocketAddress; + +typedef enum SocketAddressBindIPv6Only { + SOCKET_ADDRESS_DEFAULT, + SOCKET_ADDRESS_BOTH, + SOCKET_ADDRESS_IPV6_ONLY, + _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX, + _SOCKET_ADDRESS_BIND_IPV6_ONLY_INVALID = -1 +} SocketAddressBindIPv6Only; + +#define socket_address_family(a) ((a)->sockaddr.sa.sa_family) + +const char* socket_address_type_to_string(int t) _const_; +int socket_address_type_from_string(const char *s) _pure_; + +int socket_address_parse(SocketAddress *a, const char *s); +int socket_address_parse_and_warn(SocketAddress *a, const char *s); +int socket_address_parse_netlink(SocketAddress *a, const char *s); +int socket_address_print(const SocketAddress *a, char **p); +int socket_address_verify(const SocketAddress *a, bool strict) _pure_; + +int sockaddr_un_unlink(const struct sockaddr_un *sa); + +static inline int socket_address_unlink(const SocketAddress *a) { + return socket_address_family(a) == AF_UNIX ? sockaddr_un_unlink(&a->sockaddr.un) : 0; +} + +bool socket_address_can_accept(const SocketAddress *a) _pure_; + +int socket_address_listen( + const SocketAddress *a, + int flags, + int backlog, + SocketAddressBindIPv6Only only, + const char *bind_to_device, + bool reuse_port, + bool free_bind, + bool transparent, + mode_t directory_mode, + mode_t socket_mode, + const char *label); +int make_socket_fd(int log_level, const char* address, int type, int flags); + +bool socket_address_is(const SocketAddress *a, const char *s, int type); +bool socket_address_is_netlink(const SocketAddress *a, const char *s); + +bool socket_address_matches_fd(const SocketAddress *a, int fd); + +bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_; + +const char* socket_address_get_path(const SocketAddress *a); + +bool socket_ipv6_is_supported(void); + +int sockaddr_port(const struct sockaddr *_sa, unsigned *port); + +int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret); +int getpeername_pretty(int fd, bool include_port, char **ret); +int getsockname_pretty(int fd, char **ret); + +int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret); + +const char* socket_address_bind_ipv6_only_to_string(SocketAddressBindIPv6Only b) _const_; +SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *s) _pure_; +SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *s); + +int netlink_family_to_string_alloc(int b, char **s); +int netlink_family_from_string(const char *s) _pure_; + +bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b); + +int fd_inc_sndbuf(int fd, size_t n); +int fd_inc_rcvbuf(int fd, size_t n); + +int ip_tos_to_string_alloc(int i, char **s); +int ip_tos_from_string(const char *s); + +bool ifname_valid(const char *p); +bool address_label_valid(const char *p); + +int getpeercred(int fd, struct ucred *ucred); +int getpeersec(int fd, char **ret); +int getpeergroups(int fd, gid_t **ret); + +ssize_t send_one_fd_iov_sa( + int transport_fd, + int fd, + struct iovec *iov, size_t iovlen, + const struct sockaddr *sa, socklen_t len, + int flags); +int send_one_fd_sa(int transport_fd, + int fd, + const struct sockaddr *sa, socklen_t len, + int flags); +#define send_one_fd_iov(transport_fd, fd, iov, iovlen, flags) send_one_fd_iov_sa(transport_fd, fd, iov, iovlen, NULL, 0, flags) +#define send_one_fd(transport_fd, fd, flags) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, NULL, 0, flags) +ssize_t receive_one_fd_iov(int transport_fd, struct iovec *iov, size_t iovlen, int flags, int *ret_fd); +int receive_one_fd(int transport_fd, int flags); + +ssize_t next_datagram_size_fd(int fd); + +int flush_accept(int fd); + +#define CMSG_FOREACH(cmsg, mh) \ + for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) + +struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length); + +/* + * Certain hardware address types (e.g Infiniband) do not fit into sll_addr + * (8 bytes) and run over the structure. This macro returns the correct size that + * must be passed to kernel. + */ +#define SOCKADDR_LL_LEN(sa) \ + ({ \ + const struct sockaddr_ll *_sa = &(sa); \ + size_t _mac_len = sizeof(_sa->sll_addr); \ + assert(_sa->sll_family == AF_PACKET); \ + if (be16toh(_sa->sll_hatype) == ARPHRD_ETHER) \ + _mac_len = MAX(_mac_len, (size_t) ETH_ALEN); \ + if (be16toh(_sa->sll_hatype) == ARPHRD_INFINIBAND) \ + _mac_len = MAX(_mac_len, (size_t) INFINIBAND_ALEN); \ + offsetof(struct sockaddr_ll, sll_addr) + _mac_len; \ + }) + +/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */ +#define SOCKADDR_UN_LEN(sa) \ + ({ \ + const struct sockaddr_un *_sa = &(sa); \ + assert(_sa->sun_family == AF_UNIX); \ + offsetof(struct sockaddr_un, sun_path) + \ + (_sa->sun_path[0] == 0 ? \ + 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \ + strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \ + }) + +int socket_ioctl_fd(void); + +int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path); + +static inline int setsockopt_int(int fd, int level, int optname, int value) { + if (setsockopt(fd, level, optname, &value, sizeof(value)) < 0) + return -errno; + + return 0; +} + +int socket_bind_to_ifname(int fd, const char *ifname); +int socket_bind_to_ifindex(int fd, int ifindex); diff --git a/src/basic/sort-util.c b/src/basic/sort-util.c new file mode 100644 index 00000000..5cf0d1d4 --- /dev/null +++ b/src/basic/sort-util.c @@ -0,0 +1,27 @@ +#include "sort-util.h" +#include "alloc-util.h" + +/* hey glibc, APIs with callbacks without a user pointer are so useless */ +void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, + __compar_d_fn_t compar, void *arg) { + size_t l, u, idx; + const void *p; + int comparison; + + assert(!size_multiply_overflow(nmemb, size)); + + l = 0; + u = nmemb; + while (l < u) { + idx = (l + u) / 2; + p = (const uint8_t*) base + idx * size; + comparison = compar(key, p, arg); + if (comparison < 0) + u = idx; + else if (comparison > 0) + l = idx + 1; + else + return (void *)p; + } + return NULL; +} diff --git a/src/basic/sort-util.h b/src/basic/sort-util.h new file mode 100644 index 00000000..e029f864 --- /dev/null +++ b/src/basic/sort-util.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, + __compar_d_fn_t compar, void *arg); + +#define typesafe_bsearch_r(k, b, n, func, userdata) \ + ({ \ + const typeof(b[0]) *_k = k; \ + int (*_func_)(const typeof(b[0])*, const typeof(b[0])*, typeof(userdata)) = func; \ + xbsearch_r((const void*) _k, (b), (n), sizeof((b)[0]), (__compar_d_fn_t) _func_, userdata); \ + }) + +/** + * Normal bsearch requires base to be nonnull. Here were require + * that only if nmemb > 0. + */ +static inline void* bsearch_safe(const void *key, const void *base, + size_t nmemb, size_t size, __compar_fn_t compar) { + if (nmemb <= 0) + return NULL; + + assert(base); + return bsearch(key, base, nmemb, size, compar); +} + +#define typesafe_bsearch(k, b, n, func) \ + ({ \ + const typeof(b[0]) *_k = k; \ + int (*_func_)(const typeof(b[0])*, const typeof(b[0])*) = func; \ + bsearch_safe((const void*) _k, (b), (n), sizeof((b)[0]), (__compar_fn_t) _func_); \ + }) + +/** + * Normal qsort requires base to be nonnull. Here were require + * that only if nmemb > 0. + */ +static inline void qsort_safe(void *base, size_t nmemb, size_t size, __compar_fn_t compar) { + if (nmemb <= 1) + return; + + assert(base); + qsort(base, nmemb, size, compar); +} + +/* A wrapper around the above, but that adds typesafety: the element size is automatically derived from the type and so + * is the prototype for the comparison function */ +#define typesafe_qsort(p, n, func) \ + ({ \ + int (*_func_)(const typeof(p[0])*, const typeof(p[0])*) = func; \ + qsort_safe((p), (n), sizeof((p)[0]), (__compar_fn_t) _func_); \ + }) + +static inline void qsort_r_safe(void *base, size_t nmemb, size_t size, __compar_d_fn_t compar, void *userdata) { + if (nmemb <= 1) + return; + + assert(base); + qsort_r(base, nmemb, size, compar, userdata); +} + +#define typesafe_qsort_r(p, n, func, userdata) \ + ({ \ + int (*_func_)(const typeof(p[0])*, const typeof(p[0])*, typeof(userdata)) = func; \ + qsort_r_safe((p), (n), sizeof((p)[0]), (__compar_d_fn_t) _func_, userdata); \ + }) diff --git a/src/basic/sparse-endian.h b/src/basic/sparse-endian.h new file mode 100644 index 00000000..9583dda9 --- /dev/null +++ b/src/basic/sparse-endian.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (c) 2012 Josh Triplett + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#pragma once + +#include +#include +#include + +#ifdef __CHECKER__ +#define __sd_bitwise __attribute__((__bitwise__)) +#define __sd_force __attribute__((__force__)) +#else +#define __sd_bitwise +#define __sd_force +#endif + +typedef uint16_t __sd_bitwise le16_t; +typedef uint16_t __sd_bitwise be16_t; +typedef uint32_t __sd_bitwise le32_t; +typedef uint32_t __sd_bitwise be32_t; +typedef uint64_t __sd_bitwise le64_t; +typedef uint64_t __sd_bitwise be64_t; + +#undef htobe16 +#undef htole16 +#undef be16toh +#undef le16toh +#undef htobe32 +#undef htole32 +#undef be32toh +#undef le32toh +#undef htobe64 +#undef htole64 +#undef be64toh +#undef le64toh + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define bswap_16_on_le(x) __bswap_16(x) +#define bswap_32_on_le(x) __bswap_32(x) +#define bswap_64_on_le(x) __bswap_64(x) +#define bswap_16_on_be(x) (x) +#define bswap_32_on_be(x) (x) +#define bswap_64_on_be(x) (x) +#elif __BYTE_ORDER == __BIG_ENDIAN +#define bswap_16_on_le(x) (x) +#define bswap_32_on_le(x) (x) +#define bswap_64_on_le(x) (x) +#define bswap_16_on_be(x) __bswap_16(x) +#define bswap_32_on_be(x) __bswap_32(x) +#define bswap_64_on_be(x) __bswap_64(x) +#endif + +static inline le16_t htole16(uint16_t value) { return (le16_t __sd_force) bswap_16_on_be(value); } +static inline le32_t htole32(uint32_t value) { return (le32_t __sd_force) bswap_32_on_be(value); } +static inline le64_t htole64(uint64_t value) { return (le64_t __sd_force) bswap_64_on_be(value); } + +static inline be16_t htobe16(uint16_t value) { return (be16_t __sd_force) bswap_16_on_le(value); } +static inline be32_t htobe32(uint32_t value) { return (be32_t __sd_force) bswap_32_on_le(value); } +static inline be64_t htobe64(uint64_t value) { return (be64_t __sd_force) bswap_64_on_le(value); } + +static inline uint16_t le16toh(le16_t value) { return bswap_16_on_be((uint16_t __sd_force)value); } +static inline uint32_t le32toh(le32_t value) { return bswap_32_on_be((uint32_t __sd_force)value); } +static inline uint64_t le64toh(le64_t value) { return bswap_64_on_be((uint64_t __sd_force)value); } + +static inline uint16_t be16toh(be16_t value) { return bswap_16_on_le((uint16_t __sd_force)value); } +static inline uint32_t be32toh(be32_t value) { return bswap_32_on_le((uint32_t __sd_force)value); } +static inline uint64_t be64toh(be64_t value) { return bswap_64_on_le((uint64_t __sd_force)value); } + +#undef __sd_bitwise +#undef __sd_force diff --git a/src/basic/special.h b/src/basic/special.h new file mode 100644 index 00000000..add1c1d5 --- /dev/null +++ b/src/basic/special.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#define SPECIAL_DEFAULT_TARGET "default.target" + +/* Shutdown targets */ +#define SPECIAL_UMOUNT_TARGET "umount.target" +/* This is not really intended to be started by directly. This is + * mostly so that other targets (reboot/halt/poweroff) can depend on + * it to bring all services down that want to be brought down on + * system shutdown. */ +#define SPECIAL_SHUTDOWN_TARGET "shutdown.target" +#define SPECIAL_HALT_TARGET "halt.target" +#define SPECIAL_POWEROFF_TARGET "poweroff.target" +#define SPECIAL_REBOOT_TARGET "reboot.target" +#define SPECIAL_KEXEC_TARGET "kexec.target" +#define SPECIAL_EXIT_TARGET "exit.target" +#define SPECIAL_SUSPEND_TARGET "suspend.target" +#define SPECIAL_HIBERNATE_TARGET "hibernate.target" +#define SPECIAL_HYBRID_SLEEP_TARGET "hybrid-sleep.target" +#define SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET "suspend-then-hibernate.target" + +/* Special boot targets */ +#define SPECIAL_RESCUE_TARGET "rescue.target" +#define SPECIAL_EMERGENCY_TARGET "emergency.target" +#define SPECIAL_MULTI_USER_TARGET "multi-user.target" +#define SPECIAL_GRAPHICAL_TARGET "graphical.target" + +/* Early boot targets */ +#define SPECIAL_SYSINIT_TARGET "sysinit.target" +#define SPECIAL_SOCKETS_TARGET "sockets.target" +#define SPECIAL_TIMERS_TARGET "timers.target" +#define SPECIAL_PATHS_TARGET "paths.target" +#define SPECIAL_LOCAL_FS_TARGET "local-fs.target" +#define SPECIAL_LOCAL_FS_PRE_TARGET "local-fs-pre.target" +#define SPECIAL_INITRD_FS_TARGET "initrd-fs.target" +#define SPECIAL_INITRD_ROOT_DEVICE_TARGET "initrd-root-device.target" +#define SPECIAL_INITRD_ROOT_FS_TARGET "initrd-root-fs.target" +#define SPECIAL_REMOTE_FS_TARGET "remote-fs.target" /* LSB's $remote_fs */ +#define SPECIAL_REMOTE_FS_PRE_TARGET "remote-fs-pre.target" +#define SPECIAL_SWAP_TARGET "swap.target" +#define SPECIAL_NETWORK_ONLINE_TARGET "network-online.target" +#define SPECIAL_TIME_SYNC_TARGET "time-sync.target" /* LSB's $time */ +#define SPECIAL_BASIC_TARGET "basic.target" + +/* LSB compatibility */ +#define SPECIAL_NETWORK_TARGET "network.target" /* LSB's $network */ +#define SPECIAL_NSS_LOOKUP_TARGET "nss-lookup.target" /* LSB's $named */ +#define SPECIAL_RPCBIND_TARGET "rpcbind.target" /* LSB's $portmap */ + +/* + * Rules regarding adding further high level targets like the above: + * + * - Be conservative, only add more of these when we really need + * them. We need strong usecases for further additions. + * + * - When there can be multiple implementations running side-by-side, + * it needs to be a .target unit which can pull in all + * implementations. + * + * - If something can be implemented with socket activation, and + * without, it needs to be a .target unit, so that it can pull in + * the appropriate unit. + * + * - Otherwise, it should be a .service unit. + * + * - In some cases it is OK to have both a .service and a .target + * unit, i.e. if there can be multiple parallel implementations, but + * only one is the "system" one. Example: syslog. + * + * Or to put this in other words: .service symlinks can be used to + * arbitrate between multiple implementations if there can be only one + * of a kind. .target units can be used to support multiple + * implementations that can run side-by-side. + */ + +/* Magic early boot services */ +#define SPECIAL_FSCK_SERVICE "systemd-fsck@.service" +#define SPECIAL_FSCK_ROOT_SERVICE "systemd-fsck-root.service" +#define SPECIAL_QUOTACHECK_SERVICE "systemd-quotacheck.service" +#define SPECIAL_QUOTAON_SERVICE "quotaon.service" +#define SPECIAL_REMOUNT_FS_SERVICE "systemd-remount-fs.service" +#define SPECIAL_VOLATILE_ROOT_SERVICE "systemd-volatile-root.service" + +/* Services systemd relies on */ +#define SPECIAL_DBUS_SERVICE "dbus.service" +#define SPECIAL_DBUS_SOCKET "dbus.socket" +#define SPECIAL_JOURNALD_SOCKET "systemd-journald.socket" +#define SPECIAL_JOURNALD_SERVICE "systemd-journald.service" +#define SPECIAL_TMPFILES_SETUP_SERVICE "systemd-tmpfiles-setup.service" + +/* Magic init signals */ +#define SPECIAL_KBREQUEST_TARGET "kbrequest.target" +#define SPECIAL_SIGPWR_TARGET "sigpwr.target" +#define SPECIAL_CTRL_ALT_DEL_TARGET "ctrl-alt-del.target" + +/* Where we add all our system units, users and machines by default */ +#define SPECIAL_SYSTEM_SLICE "system.slice" +#define SPECIAL_USER_SLICE "user.slice" +#define SPECIAL_MACHINE_SLICE "machine.slice" +#define SPECIAL_ROOT_SLICE "-.slice" + +/* The scope unit systemd itself lives in. */ +#define SPECIAL_INIT_SCOPE "init.scope" + +/* The root directory. */ +#define SPECIAL_ROOT_MOUNT "-.mount" diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c new file mode 100644 index 00000000..8ef90e96 --- /dev/null +++ b/src/basic/stat-util.c @@ -0,0 +1,379 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "macro.h" +#include "missing_fs.h" +#include "missing_magic.h" +#include "parse-util.h" +#include "stat-util.h" +#include "string-util.h" + +int is_symlink(const char *path) { + struct stat info; + + assert(path); + + if (lstat(path, &info) < 0) + return -errno; + + return !!S_ISLNK(info.st_mode); +} + +int is_dir(const char* path, bool follow) { + struct stat st; + int r; + + assert(path); + + if (follow) + r = stat(path, &st); + else + r = lstat(path, &st); + if (r < 0) + return -errno; + + return !!S_ISDIR(st.st_mode); +} + +int is_dir_fd(int fd) { + struct stat st; + + if (fstat(fd, &st) < 0) + return -errno; + + return !!S_ISDIR(st.st_mode); +} + +int is_device_node(const char *path) { + struct stat info; + + assert(path); + + if (lstat(path, &info) < 0) + return -errno; + + return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode)); +} + +int dir_is_empty_at(int dir_fd, const char *path) { + _cleanup_close_ int fd = -1; + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + + if (path) + fd = openat(dir_fd, path, O_RDONLY|O_DIRECTORY|O_CLOEXEC); + else + fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (fd < 0) + return -errno; + + d = fdopendir(fd); + if (!d) + return -errno; + fd = -1; + + FOREACH_DIRENT(de, d, return -errno) + return 0; + + return 1; +} + +bool null_or_empty(struct stat *st) { + assert(st); + + if (S_ISREG(st->st_mode) && st->st_size <= 0) + return true; + + /* We don't want to hardcode the major/minor of /dev/null, + * hence we do a simpler "is this a device node?" check. */ + + if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) + return true; + + return false; +} + +int null_or_empty_path(const char *fn) { + struct stat st; + + assert(fn); + + if (stat(fn, &st) < 0) + return -errno; + + return null_or_empty(&st); +} + +int null_or_empty_fd(int fd) { + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + return null_or_empty(&st); +} + +int path_is_read_only_fs(const char *path) { + struct statvfs st; + + assert(path); + + if (statvfs(path, &st) < 0) + return -errno; + + if (st.f_flag & ST_RDONLY) + return true; + + /* On NFS, statvfs() might not reflect whether we can actually + * write to the remote share. Let's try again with + * access(W_OK) which is more reliable, at least sometimes. */ + if (access(path, W_OK) < 0 && errno == EROFS) + return true; + + return false; +} + +int files_same(const char *filea, const char *fileb, int flags) { + struct stat a, b; + + assert(filea); + assert(fileb); + + if (fstatat(AT_FDCWD, filea, &a, flags) < 0) + return -errno; + + if (fstatat(AT_FDCWD, fileb, &b, flags) < 0) + return -errno; + + return a.st_dev == b.st_dev && + a.st_ino == b.st_ino; +} + +bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) { + assert(s); + assert_cc(sizeof(statfs_f_type_t) >= sizeof(s->f_type)); + + return F_TYPE_EQUAL(s->f_type, magic_value); +} + +int fd_is_fs_type(int fd, statfs_f_type_t magic_value) { + struct statfs s; + + if (fstatfs(fd, &s) < 0) + return -errno; + + return is_fs_type(&s, magic_value); +} + +int path_is_fs_type(const char *path, statfs_f_type_t magic_value) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH); + if (fd < 0) + return -errno; + + return fd_is_fs_type(fd, magic_value); +} + +bool is_temporary_fs(const struct statfs *s) { + return is_fs_type(s, TMPFS_MAGIC) || + is_fs_type(s, RAMFS_MAGIC); +} + +bool is_network_fs(const struct statfs *s) { + return is_fs_type(s, CIFS_MAGIC_NUMBER) || + is_fs_type(s, CODA_SUPER_MAGIC) || + is_fs_type(s, NCP_SUPER_MAGIC) || + is_fs_type(s, NFS_SUPER_MAGIC) || + is_fs_type(s, SMB_SUPER_MAGIC) || + is_fs_type(s, V9FS_MAGIC) || + is_fs_type(s, AFS_SUPER_MAGIC) || + is_fs_type(s, OCFS2_SUPER_MAGIC); +} + +int fd_is_temporary_fs(int fd) { + struct statfs s; + + if (fstatfs(fd, &s) < 0) + return -errno; + + return is_temporary_fs(&s); +} + +int fd_is_network_fs(int fd) { + struct statfs s; + + if (fstatfs(fd, &s) < 0) + return -errno; + + return is_network_fs(&s); +} + +int path_is_temporary_fs(const char *path) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH); + if (fd < 0) + return -errno; + + return fd_is_temporary_fs(fd); +} + +int stat_verify_regular(const struct stat *st) { + assert(st); + + /* Checks whether the specified stat() structure refers to a regular file. If not returns an appropriate error + * code. */ + + if (S_ISDIR(st->st_mode)) + return -EISDIR; + + if (S_ISLNK(st->st_mode)) + return -ELOOP; + + if (!S_ISREG(st->st_mode)) + return -EBADFD; + + return 0; +} + +int fd_verify_regular(int fd) { + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + return stat_verify_regular(&st); +} + +int stat_verify_directory(const struct stat *st) { + assert(st); + + if (S_ISLNK(st->st_mode)) + return -ELOOP; + + if (!S_ISDIR(st->st_mode)) + return -ENOTDIR; + + return 0; +} + +int fd_verify_directory(int fd) { + struct stat st; + + assert(fd >= 0); + + if (fstat(fd, &st) < 0) + return -errno; + + return stat_verify_directory(&st); +} + +int device_path_make_major_minor(mode_t mode, dev_t devno, char **ret) { + const char *t; + + /* Generates the /dev/{char|block}/MAJOR:MINOR path for a dev_t */ + + if (S_ISCHR(mode)) + t = "char"; + else if (S_ISBLK(mode)) + t = "block"; + else + return -ENODEV; + + if (asprintf(ret, "/dev/%s/%u:%u", t, major(devno), minor(devno)) < 0) + return -ENOMEM; + + return 0; +} + +int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) { + _cleanup_free_ char *p = NULL; + int r; + + /* Finds the canonical path for a device, i.e. resolves the /dev/{char|block}/MAJOR:MINOR path to the end. */ + + assert(ret); + + if (major(devno) == 0 && minor(devno) == 0) { + char *s; + + /* A special hack to make sure our 'inaccessible' device nodes work. They won't have symlinks in + * /dev/block/ and /dev/char/, hence we handle them specially here. */ + + if (S_ISCHR(mode)) + s = strdup("/run/systemd/inaccessible/chr"); + else if (S_ISBLK(mode)) + s = strdup("/run/systemd/inaccessible/blk"); + else + return -ENODEV; + + if (!s) + return -ENOMEM; + + *ret = s; + return 0; + } + + r = device_path_make_major_minor(mode, devno, &p); + if (r < 0) + return r; + + return chase_symlinks(p, NULL, 0, ret, NULL); +} + +int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno) { + mode_t mode; + dev_t devno; + int r; + + /* Tries to extract the major/minor directly from the device path if we can. Handles /dev/block/ and /dev/char/ + * paths, as well out synthetic inaccessible device nodes. Never goes to disk. Returns -ENODEV if the device + * path cannot be parsed like this. */ + + if (path_equal(path, "/run/systemd/inaccessible/chr")) { + mode = S_IFCHR; + devno = makedev(0, 0); + } else if (path_equal(path, "/run/systemd/inaccessible/blk")) { + mode = S_IFBLK; + devno = makedev(0, 0); + } else { + const char *w; + + w = path_startswith(path, "/dev/block/"); + if (w) + mode = S_IFBLK; + else { + w = path_startswith(path, "/dev/char/"); + if (!w) + return -ENODEV; + + mode = S_IFCHR; + } + + r = parse_dev(w, &devno); + if (r < 0) + return r; + } + + if (ret_mode) + *ret_mode = mode; + if (ret_devno) + *ret_devno = devno; + + return 0; +} diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h new file mode 100644 index 00000000..7824af35 --- /dev/null +++ b/src/basic/stat-util.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "macro.h" + +int is_symlink(const char *path); +int is_dir(const char *path, bool follow); +int is_dir_fd(int fd); +int is_device_node(const char *path); + +int dir_is_empty_at(int dir_fd, const char *path); +static inline int dir_is_empty(const char *path) { + return dir_is_empty_at(AT_FDCWD, path); +} + +static inline int dir_is_populated(const char *path) { + int r; + r = dir_is_empty(path); + if (r < 0) + return r; + return !r; +} + +bool null_or_empty(struct stat *st) _pure_; +int null_or_empty_path(const char *fn); +int null_or_empty_fd(int fd); + +int path_is_read_only_fs(const char *path); + +int files_same(const char *filea, const char *fileb, int flags); + +/* The .f_type field of struct statfs is really weird defined on + * different archs. Let's give its type a name. */ +typedef typeof(((struct statfs*)NULL)->f_type) statfs_f_type_t; + +bool is_fs_type(const struct statfs *s, statfs_f_type_t magic_value) _pure_; +int fd_is_fs_type(int fd, statfs_f_type_t magic_value); +int path_is_fs_type(const char *path, statfs_f_type_t magic_value); + +bool is_temporary_fs(const struct statfs *s) _pure_; +bool is_network_fs(const struct statfs *s) _pure_; + +int fd_is_temporary_fs(int fd); +int fd_is_network_fs(int fd); + +int path_is_temporary_fs(const char *path); + +/* Because statfs.t_type can be int on some architectures, we have to cast + * the const magic to the type, otherwise the compiler warns about + * signed/unsigned comparison, because the magic can be 32 bit unsigned. + */ +#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b) + +int stat_verify_regular(const struct stat *st); +int fd_verify_regular(int fd); + +int stat_verify_directory(const struct stat *st); +int fd_verify_directory(int fd); + +/* glibc and the Linux kernel have different ideas about the major/minor size. These calls will check whether the + * specified major is valid by the Linux kernel's standards, not by glibc's. Linux has 20bits of minor, and 12 bits of + * major space. See MINORBITS in linux/kdev_t.h in the kernel sources. (If you wonder why we define _y here, instead of + * comparing directly >= 0: it's to trick out -Wtype-limits, which would otherwise complain if the type is unsigned, as + * such a test would be pointless in such a case.) */ + +#define DEVICE_MAJOR_VALID(x) \ + ({ \ + typeof(x) _x = (x), _y = 0; \ + _x >= _y && _x < (UINT32_C(1) << 12); \ + \ + }) + +#define DEVICE_MINOR_VALID(x) \ + ({ \ + typeof(x) _x = (x), _y = 0; \ + _x >= _y && _x < (UINT32_C(1) << 20); \ + }) + +int device_path_make_major_minor(mode_t mode, dev_t devno, char **ret); +int device_path_make_canonical(mode_t mode, dev_t devno, char **ret); +int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno); diff --git a/src/basic/static-destruct.h b/src/basic/static-destruct.h new file mode 100644 index 00000000..8fbc07c5 --- /dev/null +++ b/src/basic/static-destruct.h @@ -0,0 +1,56 @@ +#pragma once + +#include "alloc-util.h" +#include "macro.h" + +/* A framework for registering static variables that shall be freed on shutdown of a process. It's a bit like gcc's + * destructor attribute, but allows us to precisely schedule when we want to free the variables. This is supposed to + * feel a bit like the gcc cleanup attribute, but for static variables. Note that this does not work for static + * variables declared in .so's, as the list is private to the same linking unit. But maybe that's a good thing. */ + +typedef struct StaticDestructor { + void *data; + free_func_t destroy; +} StaticDestructor; + +#define STATIC_DESTRUCTOR_REGISTER(variable, func) \ + _STATIC_DESTRUCTOR_REGISTER(UNIQ, variable, func) + +#define _STATIC_DESTRUCTOR_REGISTER(uq, variable, func) \ + /* Type-safe destructor */ \ + static void UNIQ_T(static_destructor_wrapper, uq)(void *p) { \ + typeof(variable) *q = p; \ + func(q); \ + } \ + /* The actual destructor structure we place in a special section to find it */ \ + _section_("SYSTEMD_STATIC_DESTRUCT") \ + /* We pick pointer alignment, since that is apparently what gcc does for static variables */ \ + _alignptr_ \ + /* Make sure this is not dropped from the image because not explicitly referenced */ \ + _used_ \ + /* Make sure that AddressSanitizer doesn't pad this variable: we want everything in this section packed next to each other so that we can enumerate it. */ \ + _variable_no_sanitize_address_ \ + static const StaticDestructor UNIQ_T(static_destructor_entry, uq) = { \ + .data = &(variable), \ + .destroy = UNIQ_T(static_destructor_wrapper, uq), \ + } + +/* Beginning and end of our section listing the destructors. We define these as weak as we want this to work even if + * there's not a single destructor is defined in which case the section will be missing. */ +extern const struct StaticDestructor _weak_ __start_SYSTEMD_STATIC_DESTRUCT[]; +extern const struct StaticDestructor _weak_ __stop_SYSTEMD_STATIC_DESTRUCT[]; + +/* The function to destroy everything. (Note that this must be static inline, as it's key that it remains in + * the same linking unit as the variables we want to destroy.) */ +static inline void static_destruct(void) { + const StaticDestructor *d; + + if (!__start_SYSTEMD_STATIC_DESTRUCT) + return; + + d = ALIGN_TO_PTR(__start_SYSTEMD_STATIC_DESTRUCT, sizeof(void*)); + while (d < __stop_SYSTEMD_STATIC_DESTRUCT) { + d->destroy(d->data); + d = ALIGN_TO_PTR(d + 1, sizeof(void*)); + } +} diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h new file mode 100644 index 00000000..c3b9448d --- /dev/null +++ b/src/basic/stdio-util.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "macro.h" +#include "memory-util.h" + +#define snprintf_ok(buf, len, fmt, ...) \ + ((size_t) snprintf(buf, len, fmt, __VA_ARGS__) < (len)) + +#define xsprintf(buf, fmt, ...) \ + assert_message_se(snprintf_ok(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__), "xsprintf: " #buf "[] must be big enough") + +#define VA_FORMAT_ADVANCE(format, ap) \ +do { \ + int _argtypes[128]; \ + size_t _i, _k; \ + /* See https://github.com/google/sanitizers/issues/992 */ \ + if (HAS_FEATURE_MEMORY_SANITIZER) \ + zero(_argtypes); \ + _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \ + assert(_k < ELEMENTSOF(_argtypes)); \ + for (_i = 0; _i < _k; _i++) { \ + if (_argtypes[_i] & PA_FLAG_PTR) { \ + (void) va_arg(ap, void*); \ + continue; \ + } \ + \ + switch (_argtypes[_i]) { \ + case PA_INT: \ + case PA_INT|PA_FLAG_SHORT: \ + case PA_CHAR: \ + (void) va_arg(ap, int); \ + break; \ + case PA_INT|PA_FLAG_LONG: \ + (void) va_arg(ap, long int); \ + break; \ + case PA_INT|PA_FLAG_LONG_LONG: \ + (void) va_arg(ap, long long int); \ + break; \ + case PA_WCHAR: \ + (void) va_arg(ap, wchar_t); \ + break; \ + case PA_WSTRING: \ + case PA_STRING: \ + case PA_POINTER: \ + (void) va_arg(ap, void*); \ + break; \ + case PA_FLOAT: \ + case PA_DOUBLE: \ + (void) va_arg(ap, double); \ + break; \ + case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \ + (void) va_arg(ap, long double); \ + break; \ + default: \ + assert_not_reached("Unknown format string argument."); \ + } \ + } \ +} while (false) diff --git a/src/basic/strbuf.c b/src/basic/strbuf.c new file mode 100644 index 00000000..769b22ab --- /dev/null +++ b/src/basic/strbuf.c @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "sort-util.h" +#include "strbuf.h" + +/* + * Strbuf stores given strings in a single continuous allocated memory + * area. Identical strings are de-duplicated and return the same offset + * as the first string stored. If the tail of a string already exists + * in the buffer, the tail is returned. + * + * A trie (http://en.wikipedia.org/wiki/Trie) is used to maintain the + * information about the stored strings. + * + * Example of udev rules: + * $ ./udevadm test . + * ... + * read rules file: /usr/lib/udev/rules.d/99-systemd.rules + * rules contain 196608 bytes tokens (16384 * 12 bytes), 39742 bytes strings + * 23939 strings (207859 bytes), 20404 de-duplicated (171653 bytes), 3536 trie nodes used + * ... + */ + +struct strbuf *strbuf_new(void) { + struct strbuf *str; + + str = new(struct strbuf, 1); + if (!str) + return NULL; + *str = (struct strbuf) { + .buf = new0(char, 1), + .root = new0(struct strbuf_node, 1), + .len = 1, + .nodes_count = 1, + }; + if (!str->buf || !str->root) { + free(str->buf); + free(str->root); + return mfree(str); + } + + return str; +} + +static struct strbuf_node* strbuf_node_cleanup(struct strbuf_node *node) { + size_t i; + + for (i = 0; i < node->children_count; i++) + strbuf_node_cleanup(node->children[i].child); + free(node->children); + return mfree(node); +} + +/* clean up trie data, leave only the string buffer */ +void strbuf_complete(struct strbuf *str) { + if (!str) + return; + if (str->root) + str->root = strbuf_node_cleanup(str->root); +} + +/* clean up everything */ +void strbuf_cleanup(struct strbuf *str) { + if (!str) + return; + + strbuf_complete(str); + free(str->buf); + free(str); +} + +static int strbuf_children_cmp(const struct strbuf_child_entry *n1, + const struct strbuf_child_entry *n2) { + return n1->c - n2->c; +} + +static void bubbleinsert(struct strbuf_node *node, + uint8_t c, + struct strbuf_node *node_child) { + + struct strbuf_child_entry new = { + .c = c, + .child = node_child, + }; + int left = 0, right = node->children_count; + + while (right > left) { + int middle = (right + left) / 2 ; + if (strbuf_children_cmp(&node->children[middle], &new) <= 0) + left = middle + 1; + else + right = middle; + } + + memmove(node->children + left + 1, node->children + left, + sizeof(struct strbuf_child_entry) * (node->children_count - left)); + node->children[left] = new; + + node->children_count++; +} + +/* add string, return the index/offset into the buffer */ +ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len) { + uint8_t c; + struct strbuf_node *node; + size_t depth; + char *buf_new; + struct strbuf_child_entry *child; + struct strbuf_node *node_child; + ssize_t off; + + if (!str->root) + return -EINVAL; + + /* search string; start from last character to find possibly matching tails */ + + str->in_count++; + if (len == 0) { + str->dedup_count++; + return 0; + } + str->in_len += len; + + node = str->root; + for (depth = 0; depth <= len; depth++) { + struct strbuf_child_entry search; + + /* match against current node */ + off = node->value_off + node->value_len - len; + if (depth == len || (node->value_len >= len && memcmp(str->buf + off, s, len) == 0)) { + str->dedup_len += len; + str->dedup_count++; + return off; + } + + c = s[len - 1 - depth]; + + /* lookup child node */ + search.c = c; + child = typesafe_bsearch(&search, node->children, node->children_count, strbuf_children_cmp); + if (!child) + break; + node = child->child; + } + + /* add new string */ + buf_new = realloc(str->buf, str->len + len+1); + if (!buf_new) + return -ENOMEM; + str->buf = buf_new; + off = str->len; + memcpy(str->buf + off, s, len); + str->len += len; + str->buf[str->len++] = '\0'; + + /* new node */ + node_child = new(struct strbuf_node, 1); + if (!node_child) + return -ENOMEM; + *node_child = (struct strbuf_node) { + .value_off = off, + .value_len = len, + }; + + /* extend array, add new entry, sort for bisection */ + child = reallocarray(node->children, node->children_count + 1, sizeof(struct strbuf_child_entry)); + if (!child) { + free(node_child); + return -ENOMEM; + } + + str->nodes_count++; + + node->children = child; + bubbleinsert(node, c, node_child); + + return off; +} diff --git a/src/basic/strbuf.h b/src/basic/strbuf.h new file mode 100644 index 00000000..a36944ad --- /dev/null +++ b/src/basic/strbuf.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "macro.h" + +struct strbuf { + char *buf; + size_t len; + struct strbuf_node *root; + + size_t nodes_count; + size_t in_count; + size_t in_len; + size_t dedup_len; + size_t dedup_count; +}; + +struct strbuf_node { + size_t value_off; + size_t value_len; + + struct strbuf_child_entry *children; + uint8_t children_count; +}; + +struct strbuf_child_entry { + uint8_t c; + struct strbuf_node *child; +}; + +struct strbuf *strbuf_new(void); +ssize_t strbuf_add_string(struct strbuf *str, const char *s, size_t len); +void strbuf_complete(struct strbuf *str); +void strbuf_cleanup(struct strbuf *str); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct strbuf*, strbuf_cleanup); diff --git a/src/basic/string-table.c b/src/basic/string-table.c new file mode 100644 index 00000000..34931b03 --- /dev/null +++ b/src/basic/string-table.c @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "string-table.h" +#include "string-util.h" + +ssize_t string_table_lookup(const char * const *table, size_t len, const char *key) { + size_t i; + + if (!key) + return -1; + + for (i = 0; i < len; ++i) + if (streq_ptr(table[i], key)) + return (ssize_t) i; + + return -1; +} diff --git a/src/basic/string-table.h b/src/basic/string-table.h new file mode 100644 index 00000000..2d3cf814 --- /dev/null +++ b/src/basic/string-table.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#pragma once + +#include +#include +#include +#include + +#include "macro.h" +#include "parse-util.h" +#include "string-util.h" + +ssize_t string_table_lookup(const char * const *table, size_t len, const char *key); + +/* For basic lookup tables with strictly enumerated entries */ +#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ + scope const char *name##_to_string(type i) { \ + if (i < 0 || i >= (type) ELEMENTSOF(name##_table)) \ + return NULL; \ + return name##_table[i]; \ + } + +#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ + scope type name##_from_string(const char *s) { \ + return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ + } + +#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \ + scope type name##_from_string(const char *s) { \ + int b; \ + if (!s) \ + return -1; \ + b = parse_boolean(s); \ + if (b == 0) \ + return (type) 0; \ + else if (b > 0) \ + return yes; \ + return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ + } + +#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,scope) \ + scope int name##_to_string_alloc(type i, char **str) { \ + char *s; \ + if (i < 0 || i > max) \ + return -ERANGE; \ + if (i < (type) ELEMENTSOF(name##_table)) { \ + s = strdup(name##_table[i]); \ + if (!s) \ + return -ENOMEM; \ + } else { \ + if (asprintf(&s, "%i", i) < 0) \ + return -ENOMEM; \ + } \ + *str = s; \ + return 0; \ + } + +#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,scope) \ + scope type name##_from_string(const char *s) { \ + unsigned u = 0; \ + type i; \ + if (!s) \ + return (type) -1; \ + i = (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ + if (i >= 0) \ + return i; \ + if (safe_atou(s, &u) >= 0 && u <= max) \ + return (type) u; \ + return (type) -1; \ + } \ + +#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) + +#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) + +#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static) + +#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,) + +/* For string conversions where numbers are also acceptable */ +#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) + +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static) + +#define DUMP_STRING_TABLE(name,type,max) \ + do { \ + type _k; \ + flockfile(stdout); \ + for (_k = 0; _k < (max); _k++) { \ + const char *_t; \ + _t = name##_to_string(_k); \ + if (!_t) \ + continue; \ + fputs_unlocked(_t, stdout); \ + fputc_unlocked('\n', stdout); \ + } \ + funlockfile(stdout); \ + } while(false) diff --git a/src/basic/string-util.c b/src/basic/string-util.c new file mode 100644 index 00000000..8e6aa638 --- /dev/null +++ b/src/basic/string-util.c @@ -0,0 +1,1066 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "escape.h" +#include "fileio.h" +#include "gunicode.h" +#include "locale-util.h" +#include "macro.h" +#include "memory-util.h" +#include "string-util.h" +#include "terminal-util.h" +#include "utf8.h" +#include "util.h" + +int strcmp_ptr(const char *a, const char *b) { + + /* Like strcmp(), but tries to make sense of NULL pointers */ + if (a && b) + return strcmp(a, b); + + if (!a && b) + return -1; + + if (a && !b) + return 1; + + return 0; +} + +char* endswith(const char *s, const char *postfix) { + size_t sl, pl; + + assert(s); + assert(postfix); + + sl = strlen(s); + pl = strlen(postfix); + + if (pl == 0) + return (char*) s + sl; + + if (sl < pl) + return NULL; + + if (memcmp(s + sl - pl, postfix, pl) != 0) + return NULL; + + return (char*) s + sl - pl; +} + +char* endswith_no_case(const char *s, const char *postfix) { + size_t sl, pl; + + assert(s); + assert(postfix); + + sl = strlen(s); + pl = strlen(postfix); + + if (pl == 0) + return (char*) s + sl; + + if (sl < pl) + return NULL; + + if (strcasecmp(s + sl - pl, postfix) != 0) + return NULL; + + return (char*) s + sl - pl; +} + +char* first_word(const char *s, const char *word) { + size_t sl, wl; + const char *p; + + assert(s); + assert(word); + + /* Checks if the string starts with the specified word, either + * followed by NUL or by whitespace. Returns a pointer to the + * NUL or the first character after the whitespace. */ + + sl = strlen(s); + wl = strlen(word); + + if (sl < wl) + return NULL; + + if (wl == 0) + return (char*) s; + + if (memcmp(s, word, wl) != 0) + return NULL; + + p = s + wl; + if (*p == 0) + return (char*) p; + + if (!strchr(WHITESPACE, *p)) + return NULL; + + p += strspn(p, WHITESPACE); + return (char*) p; +} + +static size_t strcspn_escaped(const char *s, const char *reject) { + bool escaped = false; + int n; + + for (n=0; s[n]; n++) { + if (escaped) + escaped = false; + else if (s[n] == '\\') + escaped = true; + else if (strchr(reject, s[n])) + break; + } + + /* if s ends in \, return index of previous char */ + return n - escaped; +} + +/* Split a string into words. */ +const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags) { + const char *current; + + current = *state; + + if (!*current) { + assert(**state == '\0'); + return NULL; + } + + current += strspn(current, separator); + if (!*current) { + *state = current; + return NULL; + } + + if (flags & SPLIT_QUOTES && strchr("\'\"", *current)) { + char quotechars[2] = {*current, '\0'}; + + *l = strcspn_escaped(current + 1, quotechars); + if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] || + (current[*l + 2] && !strchr(separator, current[*l + 2]))) { + /* right quote missing or garbage at the end */ + if (flags & SPLIT_RELAX) { + *state = current + *l + 1 + (current[*l + 1] != '\0'); + return current + 1; + } + *state = current; + return NULL; + } + *state = current++ + *l + 2; + } else if (flags & SPLIT_QUOTES) { + *l = strcspn_escaped(current, separator); + if (current[*l] && !strchr(separator, current[*l]) && !(flags & SPLIT_RELAX)) { + /* unfinished escape */ + *state = current; + return NULL; + } + *state = current + *l; + } else { + *l = strcspn(current, separator); + *state = current + *l; + } + + return current; +} + +char *strnappend(const char *s, const char *suffix, size_t b) { + size_t a; + char *r; + + if (!s && !suffix) + return strdup(""); + + if (!s) + return strndup(suffix, b); + + if (!suffix) + return strdup(s); + + assert(s); + assert(suffix); + + a = strlen(s); + if (b > ((size_t) -1) - a) + return NULL; + + r = new(char, a+b+1); + if (!r) + return NULL; + + memcpy(r, s, a); + memcpy(r+a, suffix, b); + r[a+b] = 0; + + return r; +} + +char *strjoin_real(const char *x, ...) { + va_list ap; + size_t l; + char *r, *p; + + va_start(ap, x); + + if (x) { + l = strlen(x); + + for (;;) { + const char *t; + size_t n; + + t = va_arg(ap, const char *); + if (!t) + break; + + n = strlen(t); + if (n > ((size_t) -1) - l) { + va_end(ap); + return NULL; + } + + l += n; + } + } else + l = 0; + + va_end(ap); + + r = new(char, l+1); + if (!r) + return NULL; + + if (x) { + p = stpcpy(r, x); + + va_start(ap, x); + + for (;;) { + const char *t; + + t = va_arg(ap, const char *); + if (!t) + break; + + p = stpcpy(p, t); + } + + va_end(ap); + } else + r[0] = 0; + + return r; +} + +char *strstrip(char *s) { + if (!s) + return NULL; + + /* Drops trailing whitespace. Modifies the string in place. Returns pointer to first non-space character */ + + return delete_trailing_chars(skip_leading_chars(s, WHITESPACE), WHITESPACE); +} + +char *delete_chars(char *s, const char *bad) { + char *f, *t; + + /* Drops all specified bad characters, regardless where in the string */ + + if (!s) + return NULL; + + if (!bad) + bad = WHITESPACE; + + for (f = s, t = s; *f; f++) { + if (strchr(bad, *f)) + continue; + + *(t++) = *f; + } + + *t = 0; + + return s; +} + +char *delete_trailing_chars(char *s, const char *bad) { + char *p, *c = s; + + /* Drops all specified bad characters, at the end of the string */ + + if (!s) + return NULL; + + if (!bad) + bad = WHITESPACE; + + for (p = s; *p; p++) + if (!strchr(bad, *p)) + c = p + 1; + + *c = 0; + + return s; +} + +char *truncate_nl(char *s) { + assert(s); + + s[strcspn(s, NEWLINE)] = 0; + return s; +} + +char ascii_tolower(char x) { + + if (x >= 'A' && x <= 'Z') + return x - 'A' + 'a'; + + return x; +} + +char ascii_toupper(char x) { + + if (x >= 'a' && x <= 'z') + return x - 'a' + 'A'; + + return x; +} + +char *ascii_strlower(char *t) { + char *p; + + assert(t); + + for (p = t; *p; p++) + *p = ascii_tolower(*p); + + return t; +} + +char *ascii_strupper(char *t) { + char *p; + + assert(t); + + for (p = t; *p; p++) + *p = ascii_toupper(*p); + + return t; +} + +char *ascii_strlower_n(char *t, size_t n) { + size_t i; + + if (n <= 0) + return t; + + for (i = 0; i < n; i++) + t[i] = ascii_tolower(t[i]); + + return t; +} + +int ascii_strcasecmp_n(const char *a, const char *b, size_t n) { + + for (; n > 0; a++, b++, n--) { + int x, y; + + x = (int) (uint8_t) ascii_tolower(*a); + y = (int) (uint8_t) ascii_tolower(*b); + + if (x != y) + return x - y; + } + + return 0; +} + +int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) { + int r; + + r = ascii_strcasecmp_n(a, b, MIN(n, m)); + if (r != 0) + return r; + + return CMP(n, m); +} + +bool chars_intersect(const char *a, const char *b) { + const char *p; + + /* Returns true if any of the chars in a are in b. */ + for (p = a; *p; p++) + if (strchr(b, *p)) + return true; + + return false; +} + +bool string_has_cc(const char *p, const char *ok) { + const char *t; + + assert(p); + + /* + * Check if a string contains control characters. If 'ok' is + * non-NULL it may be a string containing additional CCs to be + * considered OK. + */ + + for (t = p; *t; t++) { + if (ok && strchr(ok, *t)) + continue; + + if (*t > 0 && *t < ' ') + return true; + + if (*t == 127) + return true; + } + + return false; +} + +static int write_ellipsis(char *buf, bool unicode) { + if (unicode || is_locale_utf8()) { + buf[0] = 0xe2; /* tri-dot ellipsis: … */ + buf[1] = 0x80; + buf[2] = 0xa6; + } else { + buf[0] = '.'; + buf[1] = '.'; + buf[2] = '.'; + } + + return 3; +} + +static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) { + size_t x, need_space, suffix_len; + char *t; + + assert(s); + assert(percent <= 100); + assert(new_length != (size_t) -1); + + if (old_length <= new_length) + return strndup(s, old_length); + + /* Special case short ellipsations */ + switch (new_length) { + + case 0: + return strdup(""); + + case 1: + if (is_locale_utf8()) + return strdup("…"); + else + return strdup("."); + + case 2: + if (!is_locale_utf8()) + return strdup(".."); + + break; + + default: + break; + } + + /* Calculate how much space the ellipsis will take up. If we are in UTF-8 mode we only need space for one + * character ("…"), otherwise for three characters ("..."). Note that in both cases we need 3 bytes of storage, + * either for the UTF-8 encoded character or for three ASCII characters. */ + need_space = is_locale_utf8() ? 1 : 3; + + t = new(char, new_length+3); + if (!t) + return NULL; + + assert(new_length >= need_space); + + x = ((new_length - need_space) * percent + 50) / 100; + assert(x <= new_length - need_space); + + memcpy(t, s, x); + write_ellipsis(t + x, false); + suffix_len = new_length - x - need_space; + memcpy(t + x + 3, s + old_length - suffix_len, suffix_len); + *(t + x + 3 + suffix_len) = '\0'; + + return t; +} + +char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) { + size_t x, k, len, len2; + const char *i, *j; + char *e; + int r; + + /* Note that 'old_length' refers to bytes in the string, while 'new_length' refers to character cells taken up + * on screen. This distinction doesn't matter for ASCII strings, but it does matter for non-ASCII UTF-8 + * strings. + * + * Ellipsation is done in a locale-dependent way: + * 1. If the string passed in is fully ASCII and the current locale is not UTF-8, three dots are used ("...") + * 2. Otherwise, a unicode ellipsis is used ("…") + * + * In other words: you'll get a unicode ellipsis as soon as either the string contains non-ASCII characters or + * the current locale is UTF-8. + */ + + assert(s); + assert(percent <= 100); + + if (new_length == (size_t) -1) + return strndup(s, old_length); + + if (new_length == 0) + return strdup(""); + + /* If no multibyte characters use ascii_ellipsize_mem for speed */ + if (ascii_is_valid_n(s, old_length)) + return ascii_ellipsize_mem(s, old_length, new_length, percent); + + x = ((new_length - 1) * percent) / 100; + assert(x <= new_length - 1); + + k = 0; + for (i = s; i < s + old_length; i = utf8_next_char(i)) { + char32_t c; + int w; + + r = utf8_encoded_to_unichar(i, &c); + if (r < 0) + return NULL; + + w = unichar_iswide(c) ? 2 : 1; + if (k + w <= x) + k += w; + else + break; + } + + for (j = s + old_length; j > i; ) { + char32_t c; + int w; + const char *jj; + + jj = utf8_prev_char(j); + r = utf8_encoded_to_unichar(jj, &c); + if (r < 0) + return NULL; + + w = unichar_iswide(c) ? 2 : 1; + if (k + w <= new_length) { + k += w; + j = jj; + } else + break; + } + assert(i <= j); + + /* we don't actually need to ellipsize */ + if (i == j) + return memdup_suffix0(s, old_length); + + /* make space for ellipsis, if possible */ + if (j < s + old_length) + j = utf8_next_char(j); + else if (i > s) + i = utf8_prev_char(i); + + len = i - s; + len2 = s + old_length - j; + e = new(char, len + 3 + len2 + 1); + if (!e) + return NULL; + + /* + printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n", + old_length, new_length, x, len, len2, k); + */ + + memcpy(e, s, len); + write_ellipsis(e + len, true); + memcpy(e + len + 3, j, len2); + *(e + len + 3 + len2) = '\0'; + + return e; +} + +char *cellescape(char *buf, size_t len, const char *s) { + /* Escape and ellipsize s into buffer buf of size len. Only non-control ASCII + * characters are copied as they are, everything else is escaped. The result + * is different then if escaping and ellipsization was performed in two + * separate steps, because each sequence is either stored in full or skipped. + * + * This function should be used for logging about strings which expected to + * be plain ASCII in a safe way. + * + * An ellipsis will be used if s is too long. It was always placed at the + * very end. + */ + + size_t i = 0, last_char_width[4] = {}, k = 0, j; + + assert(len > 0); /* at least a terminating NUL */ + + for (;;) { + char four[4]; + int w; + + if (*s == 0) /* terminating NUL detected? then we are done! */ + goto done; + + w = cescape_char(*s, four); + if (i + w + 1 > len) /* This character doesn't fit into the buffer anymore? In that case let's + * ellipsize at the previous location */ + break; + + /* OK, there was space, let's add this escaped character to the buffer */ + memcpy(buf + i, four, w); + i += w; + + /* And remember its width in the ring buffer */ + last_char_width[k] = w; + k = (k + 1) % 4; + + s++; + } + + /* Ellipsation is necessary. This means we might need to truncate the string again to make space for 4 + * characters ideally, but the buffer is shorter than that in the first place take what we can get */ + for (j = 0; j < ELEMENTSOF(last_char_width); j++) { + + if (i + 4 <= len) /* nice, we reached our space goal */ + break; + + k = k == 0 ? 3 : k - 1; + if (last_char_width[k] == 0) /* bummer, we reached the beginning of the strings */ + break; + + assert(i >= last_char_width[k]); + i -= last_char_width[k]; + } + + if (i + 4 <= len) /* yay, enough space */ + i += write_ellipsis(buf + i, false); + else if (i + 3 <= len) { /* only space for ".." */ + buf[i++] = '.'; + buf[i++] = '.'; + } else if (i + 2 <= len) /* only space for a single "." */ + buf[i++] = '.'; + else + assert(i + 1 <= len); + + done: + buf[i] = '\0'; + return buf; +} + +char* strshorten(char *s, size_t l) { + assert(s); + + if (strnlen(s, l+1) > l) + s[l] = 0; + + return s; +} + +char *strreplace(const char *text, const char *old_string, const char *new_string) { + size_t l, old_len, new_len, allocated = 0; + char *t, *ret = NULL; + const char *f; + + assert(old_string); + assert(new_string); + + if (!text) + return NULL; + + old_len = strlen(old_string); + new_len = strlen(new_string); + + l = strlen(text); + if (!GREEDY_REALLOC(ret, allocated, l+1)) + return NULL; + + f = text; + t = ret; + while (*f) { + size_t d, nl; + + if (!startswith(f, old_string)) { + *(t++) = *(f++); + continue; + } + + d = t - ret; + nl = l - old_len + new_len; + + if (!GREEDY_REALLOC(ret, allocated, nl + 1)) + return mfree(ret); + + l = nl; + t = ret + d; + + t = stpcpy(t, new_string); + f += old_len; + } + + *t = 0; + return ret; +} + +static void advance_offsets( + ssize_t diff, + size_t offsets[2], /* note: we can't use [static 2] here, since this may be NULL */ + size_t shift[static 2], + size_t size) { + + if (!offsets) + return; + + assert(shift); + + if ((size_t) diff < offsets[0]) + shift[0] += size; + if ((size_t) diff < offsets[1]) + shift[1] += size; +} + +char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) { + const char *begin = NULL; + enum { + STATE_OTHER, + STATE_ESCAPE, + STATE_CSI, + STATE_CSO, + } state = STATE_OTHER; + char *obuf = NULL; + size_t osz = 0, isz, shift[2] = {}, n_carriage_returns = 0; + FILE *f; + + assert(ibuf); + assert(*ibuf); + + /* This does three things: + * + * 1. Replaces TABs by 8 spaces + * 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences + * 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences + * 4. Strip trailing \r characters (since they would "move the cursor", but have no + * other effect). + * + * Everything else will be left as it is. In particular other ANSI sequences are left as they are, as + * are any other special characters. Truncated ANSI sequences are left-as is too. This call is + * supposed to suppress the most basic formatting noise, but nothing else. + * + * Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */ + + isz = _isz ? *_isz : strlen(*ibuf); + + /* Note we turn off internal locking on f for performance reasons. It's safe to do so since we + * created f here and it doesn't leave our scope. */ + f = open_memstream_unlocked(&obuf, &osz); + if (!f) + return NULL; + + for (const char *i = *ibuf; i < *ibuf + isz + 1; i++) { + + switch (state) { + + case STATE_OTHER: + if (i >= *ibuf + isz) /* EOT */ + break; + + if (*i == '\r') { + n_carriage_returns++; + break; + } else if (*i == '\n') + /* Ignore carriage returns before new line */ + n_carriage_returns = 0; + for (; n_carriage_returns > 0; n_carriage_returns--) + fputc('\r', f); + + if (*i == '\x1B') + state = STATE_ESCAPE; + else if (*i == '\t') { + fputs(" ", f); + advance_offsets(i - *ibuf, highlight, shift, 7); + } else + fputc(*i, f); + + break; + + case STATE_ESCAPE: + assert(n_carriage_returns == 0); + + if (i >= *ibuf + isz) { /* EOT */ + fputc('\x1B', f); + advance_offsets(i - *ibuf, highlight, shift, 1); + break; + } else if (*i == '[') { /* ANSI CSI */ + state = STATE_CSI; + begin = i + 1; + } else if (*i == ']') { /* ANSI CSO */ + state = STATE_CSO; + begin = i + 1; + } else { + fputc('\x1B', f); + fputc(*i, f); + advance_offsets(i - *ibuf, highlight, shift, 1); + state = STATE_OTHER; + } + + break; + + case STATE_CSI: + assert(n_carriage_returns == 0); + + if (i >= *ibuf + isz || /* EOT … */ + !strchr("01234567890;m", *i)) { /* … or invalid chars in sequence */ + fputc('\x1B', f); + fputc('[', f); + advance_offsets(i - *ibuf, highlight, shift, 2); + state = STATE_OTHER; + i = begin-1; + } else if (*i == 'm') + state = STATE_OTHER; + + break; + + case STATE_CSO: + assert(n_carriage_returns == 0); + + if (i >= *ibuf + isz || /* EOT … */ + (*i != '\a' && (uint8_t) *i < 32U) || (uint8_t) *i > 126U) { /* … or invalid chars in sequence */ + fputc('\x1B', f); + fputc(']', f); + advance_offsets(i - *ibuf, highlight, shift, 2); + state = STATE_OTHER; + i = begin-1; + } else if (*i == '\a') + state = STATE_OTHER; + + break; + } + } + + if (fflush_and_check(f) < 0) { + fclose(f); + return mfree(obuf); + } + fclose(f); + + free_and_replace(*ibuf, obuf); + + if (_isz) + *_isz = osz; + + if (highlight) { + highlight[0] += shift[0]; + highlight[1] += shift[1]; + } + + return *ibuf; +} + +char *strextend_with_separator(char **x, const char *separator, ...) { + bool need_separator; + size_t f, l, l_separator; + char *r, *p; + va_list ap; + + assert(x); + + l = f = strlen_ptr(*x); + + need_separator = !isempty(*x); + l_separator = strlen_ptr(separator); + + va_start(ap, separator); + for (;;) { + const char *t; + size_t n; + + t = va_arg(ap, const char *); + if (!t) + break; + + n = strlen(t); + + if (need_separator) + n += l_separator; + + if (n > ((size_t) -1) - l) { + va_end(ap); + return NULL; + } + + l += n; + need_separator = true; + } + va_end(ap); + + need_separator = !isempty(*x); + + r = realloc(*x, l+1); + if (!r) + return NULL; + + p = r + f; + + va_start(ap, separator); + for (;;) { + const char *t; + + t = va_arg(ap, const char *); + if (!t) + break; + + if (need_separator && separator) + p = stpcpy(p, separator); + + p = stpcpy(p, t); + + need_separator = true; + } + va_end(ap); + + assert(p == r + l); + + *p = 0; + *x = r; + + return r + l; +} + +char *strrep(const char *s, unsigned n) { + size_t l; + char *r, *p; + unsigned i; + + assert(s); + + l = strlen(s); + p = r = malloc(l * n + 1); + if (!r) + return NULL; + + for (i = 0; i < n; i++) + p = stpcpy(p, s); + + *p = 0; + return r; +} + +int split_pair(const char *s, const char *sep, char **l, char **r) { + char *x, *a, *b; + + assert(s); + assert(sep); + assert(l); + assert(r); + + if (isempty(sep)) + return -EINVAL; + + x = strstr(s, sep); + if (!x) + return -EINVAL; + + a = strndup(s, x - s); + if (!a) + return -ENOMEM; + + b = strdup(x + strlen(sep)); + if (!b) { + free(a); + return -ENOMEM; + } + + *l = a; + *r = b; + + return 0; +} + +int free_and_strdup(char **p, const char *s) { + char *t; + + assert(p); + + /* Replaces a string pointer with a strdup()ed new string, + * possibly freeing the old one. */ + + if (streq_ptr(*p, s)) + return 0; + + if (s) { + t = strdup(s); + if (!t) + return -ENOMEM; + } else + t = NULL; + + free(*p); + *p = t; + + return 1; +} + +int free_and_strndup(char **p, const char *s, size_t l) { + char *t; + + assert(p); + assert(s || l == 0); + + /* Replaces a string pointer with a strndup()ed new string, + * freeing the old one. */ + + if (!*p && !s) + return 0; + + if (*p && s && strneq(*p, s, l) && (l > strlen(*p) || (*p)[l] == '\0')) + return 0; + + if (s) { + t = strndup(s, l); + if (!t) + return -ENOMEM; + } else + t = NULL; + + free_and_replace(*p, t); + return 1; +} + +bool string_is_safe(const char *p) { + const char *t; + + if (!p) + return false; + + for (t = p; *t; t++) { + if (*t > 0 && *t < ' ') /* no control characters */ + return false; + + if (strchr(QUOTES "\\\x7f", *t)) + return false; + } + + return true; +} diff --git a/src/basic/string-util.h b/src/basic/string-util.h new file mode 100644 index 00000000..04cc82b3 --- /dev/null +++ b/src/basic/string-util.h @@ -0,0 +1,280 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "alloc-util.h" +#include "macro.h" + +/* What is interpreted as whitespace? */ +#define WHITESPACE " \t\n\r" +#define NEWLINE "\n\r" +#define QUOTES "\"\'" +#define COMMENTS "#;" +#define GLOB_CHARS "*?[" +#define DIGITS "0123456789" +#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz" +#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS +#define ALPHANUMERICAL LETTERS DIGITS +#define HEXDIGITS DIGITS "abcdefABCDEF" + +#define streq(a,b) (strcmp((a),(b)) == 0) +#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) +#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0) +#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0) + +int strcmp_ptr(const char *a, const char *b) _pure_; + +static inline bool streq_ptr(const char *a, const char *b) { + return strcmp_ptr(a, b) == 0; +} + +static inline const char* strempty(const char *s) { + return s ?: ""; +} + +static inline const char* strnull(const char *s) { + return s ?: "(null)"; +} + +static inline const char *strna(const char *s) { + return s ?: "n/a"; +} + +static inline const char* yes_no(bool b) { + return b ? "yes" : "no"; +} + +static inline const char* true_false(bool b) { + return b ? "true" : "false"; +} + +static inline const char* one_zero(bool b) { + return b ? "1" : "0"; +} + +static inline const char* enable_disable(bool b) { + return b ? "enable" : "disable"; +} + +static inline bool isempty(const char *p) { + return !p || !p[0]; +} + +static inline const char *empty_to_null(const char *p) { + return isempty(p) ? NULL : p; +} + +static inline const char *empty_to_dash(const char *str) { + return isempty(str) ? "-" : str; +} + +static inline bool empty_or_dash(const char *str) { + return !str || + str[0] == 0 || + (str[0] == '-' && str[1] == 0); +} + +static inline const char *empty_or_dash_to_null(const char *p) { + return empty_or_dash(p) ? NULL : p; +} + +static inline char *startswith(const char *s, const char *prefix) { + size_t l; + + l = strlen(prefix); + if (strncmp(s, prefix, l) == 0) + return (char*) s + l; + + return NULL; +} + +static inline char *startswith_no_case(const char *s, const char *prefix) { + size_t l; + + l = strlen(prefix); + if (strncasecmp(s, prefix, l) == 0) + return (char*) s + l; + + return NULL; +} + +char *endswith(const char *s, const char *postfix) _pure_; +char *endswith_no_case(const char *s, const char *postfix) _pure_; + +char *first_word(const char *s, const char *word) _pure_; + +typedef enum SplitFlags { + SPLIT_QUOTES = 0x01 << 0, + SPLIT_RELAX = 0x01 << 1, +} SplitFlags; + +const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags); + +#define FOREACH_WORD(word, length, s, state) \ + _FOREACH_WORD(word, length, s, WHITESPACE, 0, state) + +#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state) \ + _FOREACH_WORD(word, length, s, separator, 0, state) + +#define _FOREACH_WORD(word, length, s, separator, flags, state) \ + for ((state) = (s), (word) = split(&(state), &(length), (separator), (flags)); (word); (word) = split(&(state), &(length), (separator), (flags))) + +char *strnappend(const char *s, const char *suffix, size_t length); + +char *strjoin_real(const char *x, ...) _sentinel_; +#define strjoin(a, ...) strjoin_real((a), __VA_ARGS__, NULL) + +#define strjoina(a, ...) \ + ({ \ + const char *_appendees_[] = { a, __VA_ARGS__ }; \ + char *_d_, *_p_; \ + size_t _len_ = 0; \ + size_t _i_; \ + for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ + _len_ += strlen(_appendees_[_i_]); \ + _p_ = _d_ = newa(char, _len_ + 1); \ + for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) && _appendees_[_i_]; _i_++) \ + _p_ = stpcpy(_p_, _appendees_[_i_]); \ + *_p_ = 0; \ + _d_; \ + }) + +char *strstrip(char *s); +char *delete_chars(char *s, const char *bad); +char *delete_trailing_chars(char *s, const char *bad); +char *truncate_nl(char *s); + +static inline char *skip_leading_chars(const char *s, const char *bad) { + + if (!s) + return NULL; + + if (!bad) + bad = WHITESPACE; + + return (char*) s + strspn(s, bad); +} + +char ascii_tolower(char x); +char *ascii_strlower(char *s); +char *ascii_strlower_n(char *s, size_t n); + +char ascii_toupper(char x); +char *ascii_strupper(char *s); + +int ascii_strcasecmp_n(const char *a, const char *b, size_t n); +int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m); + +bool chars_intersect(const char *a, const char *b) _pure_; + +static inline bool _pure_ in_charset(const char *s, const char* charset) { + assert(s); + assert(charset); + return s[strspn(s, charset)] == '\0'; +} + +bool string_has_cc(const char *p, const char *ok) _pure_; + +char *ellipsize_mem(const char *s, size_t old_length_bytes, size_t new_length_columns, unsigned percent); +static inline char *ellipsize(const char *s, size_t length, unsigned percent) { + return ellipsize_mem(s, strlen(s), length, percent); +} + +char *cellescape(char *buf, size_t len, const char *s); + +/* This limit is arbitrary, enough to give some idea what the string contains */ +#define CELLESCAPE_DEFAULT_LENGTH 64 + +char* strshorten(char *s, size_t l); + +char *strreplace(const char *text, const char *old_string, const char *new_string); + +char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]); + +char *strextend_with_separator(char **x, const char *separator, ...) _sentinel_; + +#define strextend(x, ...) strextend_with_separator(x, NULL, __VA_ARGS__) + +char *strrep(const char *s, unsigned n); + +int split_pair(const char *s, const char *sep, char **l, char **r); + +int free_and_strdup(char **p, const char *s); +static inline int free_and_strdup_warn(char **p, const char *s) { + if (free_and_strdup(p, s) < 0) + return log_oom(); + return 0; +} +int free_and_strndup(char **p, const char *s, size_t l); + +bool string_is_safe(const char *p) _pure_; + +static inline size_t strlen_ptr(const char *s) { + if (!s) + return 0; + + return strlen(s); +} + +DISABLE_WARNING_STRINGOP_TRUNCATION; +static inline void strncpy_exact(char *buf, const char *src, size_t buf_len) { + strncpy(buf, src, buf_len); +} +REENABLE_WARNING; + +/* Like startswith(), but operates on arbitrary memory blocks */ +static inline void *memory_startswith(const void *p, size_t sz, const char *token) { + size_t n; + + assert(token); + + n = strlen(token); + if (sz < n) + return NULL; + + assert(p); + + if (memcmp(p, token, n) != 0) + return NULL; + + return (uint8_t*) p + n; +} + +/* Like startswith_no_case(), but operates on arbitrary memory blocks. + * It works only for ASCII strings. + */ +static inline void *memory_startswith_no_case(const void *p, size_t sz, const char *token) { + size_t n, i; + + assert(token); + + n = strlen(token); + if (sz < n) + return NULL; + + assert(p); + + for (i = 0; i < n; i++) { + if (ascii_tolower(((char *)p)[i]) != ascii_tolower(token[i])) + return NULL; + } + + return (uint8_t*) p + n; +} + +static inline char* str_realloc(char **p) { + /* Reallocate *p to actual size */ + + if (!*p) + return NULL; + + char *t = realloc(*p, strlen(*p) + 1); + if (!t) + return NULL; + + return (*p = t); +} diff --git a/src/basic/strv.c b/src/basic/strv.c new file mode 100644 index 00000000..30fab630 --- /dev/null +++ b/src/basic/strv.c @@ -0,0 +1,950 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "escape.h" +#include "extract-word.h" +#include "fileio.h" +#include "memory-util.h" +#include "nulstr-util.h" +#include "sort-util.h" +#include "string-util.h" +#include "strv.h" + +char *strv_find(char **l, const char *name) { + char **i; + + assert(name); + + STRV_FOREACH(i, l) + if (streq(*i, name)) + return *i; + + return NULL; +} + +char *strv_find_prefix(char **l, const char *name) { + char **i; + + assert(name); + + STRV_FOREACH(i, l) + if (startswith(*i, name)) + return *i; + + return NULL; +} + +char *strv_find_startswith(char **l, const char *name) { + char **i, *e; + + assert(name); + + /* Like strv_find_prefix, but actually returns only the + * suffix, not the whole item */ + + STRV_FOREACH(i, l) { + e = startswith(*i, name); + if (e) + return e; + } + + return NULL; +} + +void strv_clear(char **l) { + char **k; + + if (!l) + return; + + for (k = l; *k; k++) + free(*k); + + *l = NULL; +} + +char **strv_free(char **l) { + strv_clear(l); + return mfree(l); +} + +char **strv_free_erase(char **l) { + char **i; + + STRV_FOREACH(i, l) + erase_and_freep(i); + + return mfree(l); +} + +char **strv_copy(char * const *l) { + char **r, **k; + + k = r = new(char*, strv_length(l) + 1); + if (!r) + return NULL; + + if (l) + for (; *l; k++, l++) { + *k = strdup(*l); + if (!*k) { + strv_free(r); + return NULL; + } + } + + *k = NULL; + return r; +} + +size_t strv_length(char * const *l) { + size_t n = 0; + + if (!l) + return 0; + + for (; *l; l++) + n++; + + return n; +} + +char **strv_new_ap(const char *x, va_list ap) { + const char *s; + _cleanup_strv_free_ char **a = NULL; + size_t n = 0, i = 0; + va_list aq; + + /* As a special trick we ignore all listed strings that equal + * STRV_IGNORE. This is supposed to be used with the + * STRV_IFNOTNULL() macro to include possibly NULL strings in + * the string list. */ + + if (x) { + n = x == STRV_IGNORE ? 0 : 1; + + va_copy(aq, ap); + while ((s = va_arg(aq, const char*))) { + if (s == STRV_IGNORE) + continue; + + n++; + } + + va_end(aq); + } + + a = new(char*, n+1); + if (!a) + return NULL; + + if (x) { + if (x != STRV_IGNORE) { + a[i] = strdup(x); + if (!a[i]) + return NULL; + i++; + } + + while ((s = va_arg(ap, const char*))) { + + if (s == STRV_IGNORE) + continue; + + a[i] = strdup(s); + if (!a[i]) + return NULL; + + i++; + } + } + + a[i] = NULL; + + return TAKE_PTR(a); +} + +char **strv_new_internal(const char *x, ...) { + char **r; + va_list ap; + + va_start(ap, x); + r = strv_new_ap(x, ap); + va_end(ap); + + return r; +} + +int strv_extend_strv(char ***a, char **b, bool filter_duplicates) { + char **s, **t; + size_t p, q, i = 0, j; + + assert(a); + + if (strv_isempty(b)) + return 0; + + p = strv_length(*a); + q = strv_length(b); + + t = reallocarray(*a, p + q + 1, sizeof(char *)); + if (!t) + return -ENOMEM; + + t[p] = NULL; + *a = t; + + STRV_FOREACH(s, b) { + + if (filter_duplicates && strv_contains(t, *s)) + continue; + + t[p+i] = strdup(*s); + if (!t[p+i]) + goto rollback; + + i++; + t[p+i] = NULL; + } + + assert(i <= q); + + return (int) i; + +rollback: + for (j = 0; j < i; j++) + free(t[p + j]); + + t[p] = NULL; + return -ENOMEM; +} + +int strv_extend_strv_concat(char ***a, char **b, const char *suffix) { + int r; + char **s; + + STRV_FOREACH(s, b) { + char *v; + + v = strjoin(*s, suffix); + if (!v) + return -ENOMEM; + + r = strv_push(a, v); + if (r < 0) { + free(v); + return r; + } + } + + return 0; +} + +char **strv_split_full(const char *s, const char *separator, SplitFlags flags) { + const char *word, *state; + size_t l; + size_t n, i; + char **r; + + assert(s); + + if (!separator) + separator = WHITESPACE; + + s += strspn(s, separator); + if (isempty(s)) + return new0(char*, 1); + + n = 0; + _FOREACH_WORD(word, l, s, separator, flags, state) + n++; + + r = new(char*, n+1); + if (!r) + return NULL; + + i = 0; + _FOREACH_WORD(word, l, s, separator, flags, state) { + r[i] = strndup(word, l); + if (!r[i]) { + strv_free(r); + return NULL; + } + + i++; + } + + r[i] = NULL; + return r; +} + +char **strv_split_newlines(const char *s) { + char **l; + size_t n; + + assert(s); + + /* Special version of strv_split() that splits on newlines and + * suppresses an empty string at the end */ + + l = strv_split(s, NEWLINE); + if (!l) + return NULL; + + n = strv_length(l); + if (n <= 0) + return l; + + if (isempty(l[n - 1])) + l[n - 1] = mfree(l[n - 1]); + + return l; +} + +int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) { + _cleanup_strv_free_ char **l = NULL; + size_t n = 0, allocated = 0; + int r; + + assert(t); + assert(s); + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&s, &word, separators, flags); + if (r < 0) + return r; + if (r == 0) + break; + + if (!GREEDY_REALLOC(l, allocated, n + 2)) + return -ENOMEM; + + l[n++] = TAKE_PTR(word); + + l[n] = NULL; + } + + if (!l) { + l = new0(char*, 1); + if (!l) + return -ENOMEM; + } + + *t = TAKE_PTR(l); + + return (int) n; +} + +char *strv_join_prefix(char **l, const char *separator, const char *prefix) { + char *r, *e; + char **s; + size_t n, k, m; + + if (!separator) + separator = " "; + + k = strlen(separator); + m = strlen_ptr(prefix); + + n = 0; + STRV_FOREACH(s, l) { + if (s != l) + n += k; + n += m + strlen(*s); + } + + r = new(char, n+1); + if (!r) + return NULL; + + e = r; + STRV_FOREACH(s, l) { + if (s != l) + e = stpcpy(e, separator); + + if (prefix) + e = stpcpy(e, prefix); + + e = stpcpy(e, *s); + } + + *e = 0; + + return r; +} + +int strv_push(char ***l, char *value) { + char **c; + size_t n, m; + + if (!value) + return 0; + + n = strv_length(*l); + + /* Increase and check for overflow */ + m = n + 2; + if (m < n) + return -ENOMEM; + + c = reallocarray(*l, m, sizeof(char*)); + if (!c) + return -ENOMEM; + + c[n] = value; + c[n+1] = NULL; + + *l = c; + return 0; +} + +int strv_push_pair(char ***l, char *a, char *b) { + char **c; + size_t n, m; + + if (!a && !b) + return 0; + + n = strv_length(*l); + + /* increase and check for overflow */ + m = n + !!a + !!b + 1; + if (m < n) + return -ENOMEM; + + c = reallocarray(*l, m, sizeof(char*)); + if (!c) + return -ENOMEM; + + if (a) + c[n++] = a; + if (b) + c[n++] = b; + c[n] = NULL; + + *l = c; + return 0; +} + +int strv_insert(char ***l, size_t position, char *value) { + char **c; + size_t n, m, i; + + if (!value) + return 0; + + n = strv_length(*l); + position = MIN(position, n); + + /* increase and check for overflow */ + m = n + 2; + if (m < n) + return -ENOMEM; + + c = new(char*, m); + if (!c) + return -ENOMEM; + + for (i = 0; i < position; i++) + c[i] = (*l)[i]; + c[position] = value; + for (i = position; i < n; i++) + c[i+1] = (*l)[i]; + + c[n+1] = NULL; + + free(*l); + *l = c; + + return 0; +} + +int strv_consume(char ***l, char *value) { + int r; + + r = strv_push(l, value); + if (r < 0) + free(value); + + return r; +} + +int strv_consume_pair(char ***l, char *a, char *b) { + int r; + + r = strv_push_pair(l, a, b); + if (r < 0) { + free(a); + free(b); + } + + return r; +} + +int strv_consume_prepend(char ***l, char *value) { + int r; + + r = strv_push_prepend(l, value); + if (r < 0) + free(value); + + return r; +} + +int strv_extend(char ***l, const char *value) { + char *v; + + if (!value) + return 0; + + v = strdup(value); + if (!v) + return -ENOMEM; + + return strv_consume(l, v); +} + +int strv_extend_front(char ***l, const char *value) { + size_t n, m; + char *v, **c; + + assert(l); + + /* Like strv_extend(), but prepends rather than appends the new entry */ + + if (!value) + return 0; + + n = strv_length(*l); + + /* Increase and overflow check. */ + m = n + 2; + if (m < n) + return -ENOMEM; + + v = strdup(value); + if (!v) + return -ENOMEM; + + c = reallocarray(*l, m, sizeof(char*)); + if (!c) { + free(v); + return -ENOMEM; + } + + memmove(c+1, c, n * sizeof(char*)); + c[0] = v; + c[n+1] = NULL; + + *l = c; + return 0; +} + +char **strv_uniq(char **l) { + char **i; + + /* Drops duplicate entries. The first identical string will be + * kept, the others dropped */ + + STRV_FOREACH(i, l) + strv_remove(i+1, *i); + + return l; +} + +bool strv_is_uniq(char **l) { + char **i; + + STRV_FOREACH(i, l) + if (strv_find(i+1, *i)) + return false; + + return true; +} + +char **strv_remove(char **l, const char *s) { + char **f, **t; + + if (!l) + return NULL; + + assert(s); + + /* Drops every occurrence of s in the string list, edits + * in-place. */ + + for (f = t = l; *f; f++) + if (streq(*f, s)) + free(*f); + else + *(t++) = *f; + + *t = NULL; + return l; +} + +char **strv_parse_nulstr(const char *s, size_t l) { + /* l is the length of the input data, which will be split at NULs into + * elements of the resulting strv. Hence, the number of items in the resulting strv + * will be equal to one plus the number of NUL bytes in the l bytes starting at s, + * unless s[l-1] is NUL, in which case the final empty string is not stored in + * the resulting strv, and length is equal to the number of NUL bytes. + * + * Note that contrary to a normal nulstr which cannot contain empty strings, because + * the input data is terminated by any two consequent NUL bytes, this parser accepts + * empty strings in s. + */ + + const char *p; + size_t c = 0, i = 0; + char **v; + + assert(s || l <= 0); + + if (l <= 0) + return new0(char*, 1); + + for (p = s; p < s + l; p++) + if (*p == 0) + c++; + + if (s[l-1] != 0) + c++; + + v = new0(char*, c+1); + if (!v) + return NULL; + + p = s; + while (p < s + l) { + const char *e; + + e = memchr(p, 0, s + l - p); + + v[i] = strndup(p, e ? e - p : s + l - p); + if (!v[i]) { + strv_free(v); + return NULL; + } + + i++; + + if (!e) + break; + + p = e + 1; + } + + assert(i == c); + + return v; +} + +char **strv_split_nulstr(const char *s) { + const char *i; + char **r = NULL; + + NULSTR_FOREACH(i, s) + if (strv_extend(&r, i) < 0) { + strv_free(r); + return NULL; + } + + if (!r) + return strv_new(NULL); + + return r; +} + +int strv_make_nulstr(char **l, char **p, size_t *q) { + /* A valid nulstr with two NULs at the end will be created, but + * q will be the length without the two trailing NULs. Thus the output + * string is a valid nulstr and can be iterated over using NULSTR_FOREACH, + * and can also be parsed by strv_parse_nulstr as long as the length + * is provided separately. + */ + + size_t n_allocated = 0, n = 0; + _cleanup_free_ char *m = NULL; + char **i; + + assert(p); + assert(q); + + STRV_FOREACH(i, l) { + size_t z; + + z = strlen(*i); + + if (!GREEDY_REALLOC(m, n_allocated, n + z + 2)) + return -ENOMEM; + + memcpy(m + n, *i, z + 1); + n += z + 1; + } + + if (!m) { + m = new0(char, 1); + if (!m) + return -ENOMEM; + n = 1; + } else + /* make sure there is a second extra NUL at the end of resulting nulstr */ + m[n] = '\0'; + + assert(n > 0); + *p = m; + *q = n - 1; + + m = NULL; + + return 0; +} + +bool strv_overlap(char **a, char **b) { + char **i; + + STRV_FOREACH(i, a) + if (strv_contains(b, *i)) + return true; + + return false; +} + +static int str_compare(char * const *a, char * const *b) { + return strcmp(*a, *b); +} + +char **strv_sort(char **l) { + typesafe_qsort(l, strv_length(l), str_compare); + return l; +} + +bool strv_equal(char **a, char **b) { + + if (strv_isempty(a)) + return strv_isempty(b); + + if (strv_isempty(b)) + return false; + + for ( ; *a || *b; ++a, ++b) + if (!streq_ptr(*a, *b)) + return false; + + return true; +} + +void strv_print(char **l) { + char **s; + + STRV_FOREACH(s, l) + puts(*s); +} + +int strv_extendf(char ***l, const char *format, ...) { + va_list ap; + char *x; + int r; + + va_start(ap, format); + r = vasprintf(&x, format, ap); + va_end(ap); + + if (r < 0) + return -ENOMEM; + + return strv_consume(l, x); +} + +char **strv_reverse(char **l) { + size_t n, i; + + n = strv_length(l); + if (n <= 1) + return l; + + for (i = 0; i < n / 2; i++) + SWAP_TWO(l[i], l[n-1-i]); + + return l; +} + +char **strv_shell_escape(char **l, const char *bad) { + char **s; + + /* Escapes every character in every string in l that is in bad, + * edits in-place, does not roll-back on error. */ + + STRV_FOREACH(s, l) { + char *v; + + v = shell_escape(*s, bad); + if (!v) + return NULL; + + free(*s); + *s = v; + } + + return l; +} + +bool strv_fnmatch(char* const* patterns, const char *s, int flags) { + char* const* p; + + STRV_FOREACH(p, patterns) + if (fnmatch(*p, s, flags) == 0) + return true; + + return false; +} + +char ***strv_free_free(char ***l) { + char ***i; + + if (!l) + return NULL; + + for (i = l; *i; i++) + strv_free(*i); + + return mfree(l); +} + +char **strv_skip(char **l, size_t n) { + + while (n > 0) { + if (strv_isempty(l)) + return l; + + l++, n--; + } + + return l; +} + +int strv_extend_n(char ***l, const char *value, size_t n) { + size_t i, j, k; + char **nl; + + assert(l); + + if (!value) + return 0; + if (n == 0) + return 0; + + /* Adds the value n times to l */ + + k = strv_length(*l); + + nl = reallocarray(*l, k + n + 1, sizeof(char *)); + if (!nl) + return -ENOMEM; + + *l = nl; + + for (i = k; i < k + n; i++) { + nl[i] = strdup(value); + if (!nl[i]) + goto rollback; + } + + nl[i] = NULL; + return 0; + +rollback: + for (j = k; j < i; j++) + free(nl[j]); + + nl[k] = NULL; + return -ENOMEM; +} + +int fputstrv(FILE *f, char **l, const char *separator, bool *space) { + bool b = false; + char **s; + int r; + + /* Like fputs(), but for strv, and with a less stupid argument order */ + + if (!space) + space = &b; + + STRV_FOREACH(s, l) { + r = fputs_with_space(f, *s, separator, space); + if (r < 0) + return r; + } + + return 0; +} + +static int string_strv_hashmap_put_internal(Hashmap *h, const char *key, const char *value) { + char **l; + int r; + + l = hashmap_get(h, key); + if (l) { + /* A list for this key already exists, let's append to it if it is not listed yet */ + if (strv_contains(l, value)) + return 0; + + r = strv_extend(&l, value); + if (r < 0) + return r; + + assert_se(hashmap_update(h, key, l) >= 0); + } else { + /* No list for this key exists yet, create one */ + _cleanup_strv_free_ char **l2 = NULL; + _cleanup_free_ char *t = NULL; + + t = strdup(key); + if (!t) + return -ENOMEM; + + r = strv_extend(&l2, value); + if (r < 0) + return r; + + r = hashmap_put(h, t, l2); + if (r < 0) + return r; + TAKE_PTR(t); + TAKE_PTR(l2); + } + + return 1; +} + +int string_strv_hashmap_put(Hashmap **h, const char *key, const char *value) { + int r; + + r = hashmap_ensure_allocated(h, &string_strv_hash_ops); + if (r < 0) + return r; + + return string_strv_hashmap_put_internal(*h, key, value); +} + +int string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value) { + int r; + + r = ordered_hashmap_ensure_allocated(h, &string_strv_hash_ops); + if (r < 0) + return r; + + return string_strv_hashmap_put_internal(PLAIN_HASHMAP(*h), key, value); +} + +DEFINE_HASH_OPS_FULL(string_strv_hash_ops, char, string_hash_func, string_compare_func, free, char*, strv_free); diff --git a/src/basic/strv.h b/src/basic/strv.h new file mode 100644 index 00000000..fbfa96a5 --- /dev/null +++ b/src/basic/strv.h @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "extract-word.h" +#include "hashmap.h" +#include "macro.h" +#include "string-util.h" + +char *strv_find(char **l, const char *name) _pure_; +char *strv_find_prefix(char **l, const char *name) _pure_; +char *strv_find_startswith(char **l, const char *name) _pure_; + +char **strv_free(char **l); +DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free); +#define _cleanup_strv_free_ _cleanup_(strv_freep) + +char **strv_free_erase(char **l); +DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase); +#define _cleanup_strv_free_erase_ _cleanup_(strv_free_erasep) + +void strv_clear(char **l); + +char **strv_copy(char * const *l); +size_t strv_length(char * const *l) _pure_; + +int strv_extend_strv(char ***a, char **b, bool filter_duplicates); +int strv_extend_strv_concat(char ***a, char **b, const char *suffix); +int strv_extend(char ***l, const char *value); +int strv_extendf(char ***l, const char *format, ...) _printf_(2,0); +int strv_extend_front(char ***l, const char *value); +int strv_push(char ***l, char *value); +int strv_push_pair(char ***l, char *a, char *b); +int strv_insert(char ***l, size_t position, char *value); + +static inline int strv_push_prepend(char ***l, char *value) { + return strv_insert(l, 0, value); +} + +int strv_consume(char ***l, char *value); +int strv_consume_pair(char ***l, char *a, char *b); +int strv_consume_prepend(char ***l, char *value); + +char **strv_remove(char **l, const char *s); +char **strv_uniq(char **l); +bool strv_is_uniq(char **l); + +bool strv_equal(char **a, char **b); + +#define strv_contains(l, s) (!!strv_find((l), (s))) + +char **strv_new_internal(const char *x, ...) _sentinel_; +char **strv_new_ap(const char *x, va_list ap); +#define strv_new(...) strv_new_internal(__VA_ARGS__, NULL) + +#define STRV_IGNORE ((const char *) -1) + +static inline const char* STRV_IFNOTNULL(const char *x) { + return x ? x : STRV_IGNORE; +} + +static inline bool strv_isempty(char * const *l) { + return !l || !*l; +} + +char **strv_split_full(const char *s, const char *separator, SplitFlags flags); +static inline char **strv_split(const char *s, const char *separator) { + return strv_split_full(s, separator, 0); +} +char **strv_split_newlines(const char *s); + +int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags); + +char *strv_join_prefix(char **l, const char *separator, const char *prefix); +static inline char *strv_join(char **l, const char *separator) { + return strv_join_prefix(l, separator, NULL); +} + +char **strv_parse_nulstr(const char *s, size_t l); +char **strv_split_nulstr(const char *s); +int strv_make_nulstr(char **l, char **p, size_t *n); + +bool strv_overlap(char **a, char **b) _pure_; + +#define STRV_FOREACH(s, l) \ + for ((s) = (l); (s) && *(s); (s)++) + +#define STRV_FOREACH_BACKWARDS(s, l) \ + for (s = ({ \ + char **_l = l; \ + _l ? _l + strv_length(_l) - 1U : NULL; \ + }); \ + (l) && ((s) >= (l)); \ + (s)--) + +#define STRV_FOREACH_PAIR(x, y, l) \ + for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1)) + +char **strv_sort(char **l); +void strv_print(char **l); + +#define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL })) + +#define STRV_MAKE_EMPTY ((char*[1]) { NULL }) + +#define strv_from_stdarg_alloca(first) \ + ({ \ + char **_l; \ + \ + if (!first) \ + _l = (char**) &first; \ + else { \ + size_t _n; \ + va_list _ap; \ + \ + _n = 1; \ + va_start(_ap, first); \ + while (va_arg(_ap, char*)) \ + _n++; \ + va_end(_ap); \ + \ + _l = newa(char*, _n+1); \ + _l[_n = 0] = (char*) first; \ + va_start(_ap, first); \ + for (;;) { \ + _l[++_n] = va_arg(_ap, char*); \ + if (!_l[_n]) \ + break; \ + } \ + va_end(_ap); \ + } \ + _l; \ + }) + +#define STR_IN_SET(x, ...) strv_contains(STRV_MAKE(__VA_ARGS__), x) +#define STRPTR_IN_SET(x, ...) \ + ({ \ + const char* _x = (x); \ + _x && strv_contains(STRV_MAKE(__VA_ARGS__), _x); \ + }) + +#define STARTSWITH_SET(p, ...) \ + ({ \ + const char *_p = (p); \ + char *_found = NULL, **_i; \ + STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \ + _found = startswith(_p, *_i); \ + if (_found) \ + break; \ + } \ + _found; \ + }) + +#define ENDSWITH_SET(p, ...) \ + ({ \ + const char *_p = (p); \ + char *_found = NULL, **_i; \ + STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \ + _found = endswith(_p, *_i); \ + if (_found) \ + break; \ + } \ + _found; \ + }) + +#define FOREACH_STRING(x, y, ...) \ + for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \ + x; \ + x = *(++_l)) + +char **strv_reverse(char **l); +char **strv_shell_escape(char **l, const char *bad); + +bool strv_fnmatch(char* const* patterns, const char *s, int flags); + +static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, int flags) { + assert(s); + return strv_isempty(patterns) || + strv_fnmatch(patterns, s, flags); +} + +char ***strv_free_free(char ***l); +DEFINE_TRIVIAL_CLEANUP_FUNC(char***, strv_free_free); + +char **strv_skip(char **l, size_t n); + +int strv_extend_n(char ***l, const char *value, size_t n); + +int fputstrv(FILE *f, char **l, const char *separator, bool *space); + +#define strv_free_and_replace(a, b) \ + ({ \ + strv_free(a); \ + (a) = (b); \ + (b) = NULL; \ + 0; \ + }) + +extern const struct hash_ops string_strv_hash_ops; +int string_strv_hashmap_put(Hashmap **h, const char *key, const char *value); +int string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value); diff --git a/src/basic/strxcpyx.c b/src/basic/strxcpyx.c new file mode 100644 index 00000000..ef6d3fa3 --- /dev/null +++ b/src/basic/strxcpyx.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +/* + * Concatenates/copies strings. In any case, terminates in all cases + * with '\0' and moves the @dest pointer forward to the added '\0'. + * Returns the remaining size, and 0 if the string was truncated. + * + * Due to the intended usage, these helpers silently noop invocations + * having zero size. This is technically an exception to the above + * statement "terminates in all cases". It's unexpected for such calls to + * occur outside of a loop where this is the preferred behavior. + */ + +#include +#include +#include + +#include "strxcpyx.h" + +size_t strnpcpy(char **dest, size_t size, const char *src, size_t len) { + assert(dest); + assert(src); + + if (size == 0) + return 0; + + if (len >= size) { + if (size > 1) + *dest = mempcpy(*dest, src, size-1); + size = 0; + } else if (len > 0) { + *dest = mempcpy(*dest, src, len); + size -= len; + } + + *dest[0] = '\0'; + return size; +} + +size_t strpcpy(char **dest, size_t size, const char *src) { + assert(dest); + assert(src); + + return strnpcpy(dest, size, src, strlen(src)); +} + +size_t strpcpyf(char **dest, size_t size, const char *src, ...) { + va_list va; + int i; + + assert(dest); + assert(src); + + if (size == 0) + return 0; + + va_start(va, src); + i = vsnprintf(*dest, size, src, va); + if (i < (int)size) { + *dest += i; + size -= i; + } else + size = 0; + va_end(va); + return size; +} + +size_t strpcpyl(char **dest, size_t size, const char *src, ...) { + va_list va; + + assert(dest); + assert(src); + + va_start(va, src); + do { + size = strpcpy(dest, size, src); + src = va_arg(va, char *); + } while (src); + va_end(va); + return size; +} + +size_t strnscpy(char *dest, size_t size, const char *src, size_t len) { + char *s; + + assert(dest); + assert(src); + + s = dest; + return strnpcpy(&s, size, src, len); +} + +size_t strscpy(char *dest, size_t size, const char *src) { + assert(dest); + assert(src); + + return strnscpy(dest, size, src, strlen(src)); +} + +size_t strscpyl(char *dest, size_t size, const char *src, ...) { + va_list va; + char *s; + + assert(dest); + assert(src); + + va_start(va, src); + s = dest; + do { + size = strpcpy(&s, size, src); + src = va_arg(va, char *); + } while (src); + va_end(va); + + return size; +} diff --git a/src/basic/strxcpyx.h b/src/basic/strxcpyx.h new file mode 100644 index 00000000..9b668412 --- /dev/null +++ b/src/basic/strxcpyx.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +size_t strnpcpy(char **dest, size_t size, const char *src, size_t len); +size_t strpcpy(char **dest, size_t size, const char *src); +size_t strpcpyf(char **dest, size_t size, const char *src, ...) _printf_(3, 4); +size_t strpcpyl(char **dest, size_t size, const char *src, ...) _sentinel_; +size_t strnscpy(char *dest, size_t size, const char *src, size_t len); +size_t strscpy(char *dest, size_t size, const char *src); +size_t strscpyl(char *dest, size_t size, const char *src, ...) _sentinel_; diff --git a/src/basic/syslog-util.c b/src/basic/syslog-util.c new file mode 100644 index 00000000..29c9ec9a --- /dev/null +++ b/src/basic/syslog-util.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "hexdecoct.h" +#include "macro.h" +#include "string-table.h" +#include "syslog-util.h" + +int syslog_parse_priority(const char **p, int *priority, bool with_facility) { + int a = 0, b = 0, c = 0; + const char *end; + size_t k; + + assert(p); + assert(*p); + assert(priority); + + if ((*p)[0] != '<') + return 0; + + end = strchr(*p, '>'); + if (!end) + return 0; + + k = end - *p; + assert(k > 0); + + if (k == 2) + c = undecchar((*p)[1]); + else if (k == 3) { + b = undecchar((*p)[1]); + c = undecchar((*p)[2]); + } else if (k == 4) { + a = undecchar((*p)[1]); + b = undecchar((*p)[2]); + c = undecchar((*p)[3]); + } else + return 0; + + if (a < 0 || b < 0 || c < 0 || + (!with_facility && (a || b || c > 7))) + return 0; + + if (with_facility) + *priority = a*100 + b*10 + c; + else + *priority = (*priority & LOG_FACMASK) | c; + + *p += k + 1; + return 1; +} + +static const char *const log_facility_unshifted_table[LOG_NFACILITIES] = { + [LOG_FAC(LOG_KERN)] = "kern", + [LOG_FAC(LOG_USER)] = "user", + [LOG_FAC(LOG_MAIL)] = "mail", + [LOG_FAC(LOG_DAEMON)] = "daemon", + [LOG_FAC(LOG_AUTH)] = "auth", + [LOG_FAC(LOG_SYSLOG)] = "syslog", + [LOG_FAC(LOG_LPR)] = "lpr", + [LOG_FAC(LOG_NEWS)] = "news", + [LOG_FAC(LOG_UUCP)] = "uucp", + [LOG_FAC(LOG_CRON)] = "cron", + [LOG_FAC(LOG_AUTHPRIV)] = "authpriv", + [LOG_FAC(LOG_FTP)] = "ftp", + [LOG_FAC(LOG_LOCAL0)] = "local0", + [LOG_FAC(LOG_LOCAL1)] = "local1", + [LOG_FAC(LOG_LOCAL2)] = "local2", + [LOG_FAC(LOG_LOCAL3)] = "local3", + [LOG_FAC(LOG_LOCAL4)] = "local4", + [LOG_FAC(LOG_LOCAL5)] = "local5", + [LOG_FAC(LOG_LOCAL6)] = "local6", + [LOG_FAC(LOG_LOCAL7)] = "local7" +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_facility_unshifted, int, LOG_FAC(~0)); + +bool log_facility_unshifted_is_valid(int facility) { + return facility >= 0 && facility <= LOG_FAC(~0); +} + +static const char *const log_level_table[] = { + [LOG_EMERG] = "emerg", + [LOG_ALERT] = "alert", + [LOG_CRIT] = "crit", + [LOG_ERR] = "err", + [LOG_WARNING] = "warning", + [LOG_NOTICE] = "notice", + [LOG_INFO] = "info", + [LOG_DEBUG] = "debug" +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(log_level, int, LOG_DEBUG); + +bool log_level_is_valid(int level) { + return level >= 0 && level <= LOG_DEBUG; +} diff --git a/src/basic/syslog-util.h b/src/basic/syslog-util.h new file mode 100644 index 00000000..8f419e81 --- /dev/null +++ b/src/basic/syslog-util.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int log_facility_unshifted_to_string_alloc(int i, char **s); +int log_facility_unshifted_from_string(const char *s); +bool log_facility_unshifted_is_valid(int faciliy); + +int log_level_to_string_alloc(int i, char **s); +int log_level_from_string(const char *s); +bool log_level_is_valid(int level); + +int syslog_parse_priority(const char **p, int *priority, bool with_facility); diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c new file mode 100644 index 00000000..511734cb --- /dev/null +++ b/src/basic/terminal-util.c @@ -0,0 +1,1372 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "copy.h" +#include "def.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "io-util.h" +#include "log.h" +#include "macro.h" +#include "namespace-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "socket-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "time-util.h" +#include "util.h" + +static volatile unsigned cached_columns = 0; +static volatile unsigned cached_lines = 0; + +static volatile int cached_on_tty = -1; +static volatile int cached_colors_enabled = -1; +static volatile int cached_underline_enabled = -1; + +int chvt(int vt) { + _cleanup_close_ int fd; + + /* Switch to the specified vt number. If the VT is specified <= 0 switch to the VT the kernel log messages go, + * if that's configured. */ + + fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) + return -errno; + + if (vt <= 0) { + int tiocl[2] = { + TIOCL_GETKMSGREDIRECT, + 0 + }; + + if (ioctl(fd, TIOCLINUX, tiocl) < 0) + return -errno; + + vt = tiocl[0] <= 0 ? 1 : tiocl[0]; + } + + if (ioctl(fd, VT_ACTIVATE, vt) < 0) + return -errno; + + return 0; +} + +int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) { + _cleanup_free_ char *line = NULL; + struct termios old_termios; + int r; + + assert(f); + assert(ret); + + /* If this is a terminal, then switch canonical mode off, so that we can read a single character */ + if (tcgetattr(fileno(f), &old_termios) >= 0) { + struct termios new_termios = old_termios; + + new_termios.c_lflag &= ~ICANON; + new_termios.c_cc[VMIN] = 1; + new_termios.c_cc[VTIME] = 0; + + if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) { + char c; + + if (t != USEC_INFINITY) { + if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) { + (void) tcsetattr(fileno(f), TCSADRAIN, &old_termios); + return -ETIMEDOUT; + } + } + + r = safe_fgetc(f, &c); + (void) tcsetattr(fileno(f), TCSADRAIN, &old_termios); + if (r < 0) + return r; + if (r == 0) + return -EIO; + + if (need_nl) + *need_nl = c != '\n'; + + *ret = c; + return 0; + } + } + + if (t != USEC_INFINITY) { + if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) + return -ETIMEDOUT; + } + + /* If this is not a terminal, then read a full line instead */ + + r = read_line(f, 16, &line); /* longer than necessary, to eat up UTF-8 chars/vt100 key sequences */ + if (r < 0) + return r; + if (r == 0) + return -EIO; + + if (strlen(line) != 1) + return -EBADMSG; + + if (need_nl) + *need_nl = false; + + *ret = line[0]; + return 0; +} + +#define DEFAULT_ASK_REFRESH_USEC (2*USEC_PER_SEC) + +int ask_char(char *ret, const char *replies, const char *fmt, ...) { + int r; + + assert(ret); + assert(replies); + assert(fmt); + + for (;;) { + va_list ap; + char c; + bool need_nl = true; + + if (colors_enabled()) + fputs(ANSI_HIGHLIGHT, stdout); + + putchar('\r'); + + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + + if (colors_enabled()) + fputs(ANSI_NORMAL, stdout); + + fflush(stdout); + + r = read_one_char(stdin, &c, DEFAULT_ASK_REFRESH_USEC, &need_nl); + if (r < 0) { + + if (r == -ETIMEDOUT) + continue; + + if (r == -EBADMSG) { + puts("Bad input, please try again."); + continue; + } + + putchar('\n'); + return r; + } + + if (need_nl) + putchar('\n'); + + if (strchr(replies, c)) { + *ret = c; + return 0; + } + + puts("Read unexpected character, please try again."); + } +} + +int ask_string(char **ret, const char *text, ...) { + _cleanup_free_ char *line = NULL; + va_list ap; + int r; + + assert(ret); + assert(text); + + if (colors_enabled()) + fputs(ANSI_HIGHLIGHT, stdout); + + va_start(ap, text); + vprintf(text, ap); + va_end(ap); + + if (colors_enabled()) + fputs(ANSI_NORMAL, stdout); + + fflush(stdout); + + r = read_line(stdin, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + return -EIO; + + *ret = TAKE_PTR(line); + return 0; +} + +int reset_terminal_fd(int fd, bool switch_to_text) { + struct termios termios; + int r = 0; + + /* Set terminal to some sane defaults */ + + assert(fd >= 0); + + /* We leave locked terminal attributes untouched, so that + * Plymouth may set whatever it wants to set, and we don't + * interfere with that. */ + + /* Disable exclusive mode, just in case */ + (void) ioctl(fd, TIOCNXCL); + + /* Switch to text mode */ + if (switch_to_text) + (void) ioctl(fd, KDSETMODE, KD_TEXT); + + /* Set default keyboard mode */ + (void) vt_reset_keyboard(fd); + + if (tcgetattr(fd, &termios) < 0) { + r = -errno; + goto finish; + } + + /* We only reset the stuff that matters to the software. How + * hardware is set up we don't touch assuming that somebody + * else will do that for us */ + + termios.c_iflag &= ~(IGNBRK | BRKINT | ISTRIP | INLCR | IGNCR | IUCLC); + termios.c_iflag |= ICRNL | IMAXBEL | IUTF8; + termios.c_oflag |= ONLCR; + termios.c_cflag |= CREAD; + termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOPRT | ECHOKE; + + termios.c_cc[VINTR] = 03; /* ^C */ + termios.c_cc[VQUIT] = 034; /* ^\ */ + termios.c_cc[VERASE] = 0177; + termios.c_cc[VKILL] = 025; /* ^X */ + termios.c_cc[VEOF] = 04; /* ^D */ + termios.c_cc[VSTART] = 021; /* ^Q */ + termios.c_cc[VSTOP] = 023; /* ^S */ + termios.c_cc[VSUSP] = 032; /* ^Z */ + termios.c_cc[VLNEXT] = 026; /* ^V */ + termios.c_cc[VWERASE] = 027; /* ^W */ + termios.c_cc[VREPRINT] = 022; /* ^R */ + termios.c_cc[VEOL] = 0; + termios.c_cc[VEOL2] = 0; + + termios.c_cc[VTIME] = 0; + termios.c_cc[VMIN] = 1; + + if (tcsetattr(fd, TCSANOW, &termios) < 0) + r = -errno; + +finish: + /* Just in case, flush all crap out */ + (void) tcflush(fd, TCIOFLUSH); + + return r; +} + +int reset_terminal(const char *name) { + _cleanup_close_ int fd = -1; + + /* We open the terminal with O_NONBLOCK here, to ensure we + * don't block on carrier if this is a terminal with carrier + * configured. */ + + fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) + return fd; + + return reset_terminal_fd(fd, true); +} + +int open_terminal(const char *name, int mode) { + unsigned c = 0; + int fd; + + /* + * If a TTY is in the process of being closed opening it might + * cause EIO. This is horribly awful, but unlikely to be + * changed in the kernel. Hence we work around this problem by + * retrying a couple of times. + * + * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245 + */ + + if (mode & O_CREAT) + return -EINVAL; + + for (;;) { + fd = open(name, mode, 0); + if (fd >= 0) + break; + + if (errno != EIO) + return -errno; + + /* Max 1s in total */ + if (c >= 20) + return -errno; + + usleep(50 * USEC_PER_MSEC); + c++; + } + + if (isatty(fd) <= 0) { + safe_close(fd); + return -ENOTTY; + } + + return fd; +} + +int acquire_terminal( + const char *name, + AcquireTerminalFlags flags, + usec_t timeout) { + + _cleanup_close_ int notify = -1, fd = -1; + usec_t ts = USEC_INFINITY; + int r, wd = -1; + + assert(name); + assert(IN_SET(flags & ~ACQUIRE_TERMINAL_PERMISSIVE, ACQUIRE_TERMINAL_TRY, ACQUIRE_TERMINAL_FORCE, ACQUIRE_TERMINAL_WAIT)); + + /* We use inotify to be notified when the tty is closed. We create the watch before checking if we can actually + * acquire it, so that we don't lose any event. + * + * Note: strictly speaking this actually watches for the device being closed, it does *not* really watch + * whether a tty loses its controlling process. However, unless some rogue process uses TIOCNOTTY on /dev/tty + * *after* closing its tty otherwise this will not become a problem. As long as the administrator makes sure to + * not configure any service on the same tty as an untrusted user this should not be a problem. (Which they + * probably should not do anyway.) */ + + if ((flags & ~ACQUIRE_TERMINAL_PERMISSIVE) == ACQUIRE_TERMINAL_WAIT) { + notify = inotify_init1(IN_CLOEXEC | (timeout != USEC_INFINITY ? IN_NONBLOCK : 0)); + if (notify < 0) + return -errno; + + wd = inotify_add_watch(notify, name, IN_CLOSE); + if (wd < 0) + return -errno; + + if (timeout != USEC_INFINITY) + ts = now(CLOCK_MONOTONIC); + } + + for (;;) { + struct sigaction sa_old, sa_new = { + .sa_handler = SIG_IGN, + .sa_flags = SA_RESTART, + }; + + if (notify >= 0) { + r = flush_fd(notify); + if (r < 0) + return r; + } + + /* We pass here O_NOCTTY only so that we can check the return value TIOCSCTTY and have a reliable way + * to figure out if we successfully became the controlling process of the tty */ + fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return fd; + + /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed if we already own the tty. */ + assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0); + + /* First, try to get the tty */ + r = ioctl(fd, TIOCSCTTY, + (flags & ~ACQUIRE_TERMINAL_PERMISSIVE) == ACQUIRE_TERMINAL_FORCE) < 0 ? -errno : 0; + + /* Reset signal handler to old value */ + assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0); + + /* Success? Exit the loop now! */ + if (r >= 0) + break; + + /* Any failure besides -EPERM? Fail, regardless of the mode. */ + if (r != -EPERM) + return r; + + if (flags & ACQUIRE_TERMINAL_PERMISSIVE) /* If we are in permissive mode, then EPERM is fine, turn this + * into a success. Note that EPERM is also returned if we + * already are the owner of the TTY. */ + break; + + if (flags != ACQUIRE_TERMINAL_WAIT) /* If we are in TRY or FORCE mode, then propagate EPERM as EPERM */ + return r; + + assert(notify >= 0); + assert(wd >= 0); + + for (;;) { + union inotify_event_buffer buffer; + struct inotify_event *e; + ssize_t l; + + if (timeout != USEC_INFINITY) { + usec_t n; + + assert(ts != USEC_INFINITY); + + n = now(CLOCK_MONOTONIC); + if (ts + timeout < n) + return -ETIMEDOUT; + + r = fd_wait_for_event(notify, POLLIN, ts + timeout - n); + if (r < 0) + return r; + if (r == 0) + return -ETIMEDOUT; + } + + l = read(notify, &buffer, sizeof(buffer)); + if (l < 0) { + if (IN_SET(errno, EINTR, EAGAIN)) + continue; + + return -errno; + } + + FOREACH_INOTIFY_EVENT(e, buffer, l) { + if (e->mask & IN_Q_OVERFLOW) /* If we hit an inotify queue overflow, simply check if the terminal is up for grabs now. */ + break; + + if (e->wd != wd || !(e->mask & IN_CLOSE)) /* Safety checks */ + return -EIO; + } + + break; + } + + /* We close the tty fd here since if the old session ended our handle will be dead. It's important that + * we do this after sleeping, so that we don't enter an endless loop. */ + fd = safe_close(fd); + } + + return TAKE_FD(fd); +} + +int release_terminal(void) { + static const struct sigaction sa_new = { + .sa_handler = SIG_IGN, + .sa_flags = SA_RESTART, + }; + + _cleanup_close_ int fd = -1; + struct sigaction sa_old; + int r; + + fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) + return -errno; + + /* Temporarily ignore SIGHUP, so that we don't get SIGHUP'ed + * by our own TIOCNOTTY */ + assert_se(sigaction(SIGHUP, &sa_new, &sa_old) == 0); + + r = ioctl(fd, TIOCNOTTY) < 0 ? -errno : 0; + + assert_se(sigaction(SIGHUP, &sa_old, NULL) == 0); + + return r; +} + +int terminal_vhangup_fd(int fd) { + assert(fd >= 0); + + if (ioctl(fd, TIOCVHANGUP) < 0) + return -errno; + + return 0; +} + +int terminal_vhangup(const char *name) { + _cleanup_close_ int fd; + + fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) + return fd; + + return terminal_vhangup_fd(fd); +} + +int vt_disallocate(const char *name) { + const char *e; + int r; + + /* Deallocate the VT if possible. If not possible + * (i.e. because it is the active one), at least clear it + * entirely (including the scrollback buffer). */ + + e = path_startswith(name, "/dev/"); + if (!e) + return -EINVAL; + + if (tty_is_vc(name)) { + _cleanup_close_ int fd = -1; + unsigned u; + const char *n; + + n = startswith(e, "tty"); + if (!n) + return -EINVAL; + + r = safe_atou(n, &u); + if (r < 0) + return r; + + if (u <= 0) + return -EINVAL; + + /* Try to deallocate */ + fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) + return fd; + + r = ioctl(fd, VT_DISALLOCATE, u); + if (r >= 0) + return 0; + if (errno != EBUSY) + return -errno; + } + + /* So this is not a VT (in which case we cannot deallocate it), + * or we failed to deallocate. Let's at least clear the screen. */ + + _cleanup_close_ int fd2 = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC); + if (fd2 < 0) + return fd2; + + (void) loop_write(fd2, + "\033[r" /* clear scrolling region */ + "\033[H" /* move home */ + "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */ + 10, false); + return 0; +} + +int make_console_stdio(void) { + int fd, r; + + /* Make /dev/console the controlling terminal and stdin/stdout/stderr, if we can. If we can't use + * /dev/null instead. This is particularly useful if /dev/console is turned off, e.g. if console=null + * is specified on the kernel command line. */ + + fd = acquire_terminal("/dev/console", ACQUIRE_TERMINAL_FORCE|ACQUIRE_TERMINAL_PERMISSIVE, USEC_INFINITY); + if (fd < 0) { + log_warning_errno(fd, "Failed to acquire terminal, using /dev/null stdin/stdout/stderr instead: %m"); + + r = make_null_stdio(); + if (r < 0) + return log_error_errno(r, "Failed to make /dev/null stdin/stdout/stderr: %m"); + + } else { + r = reset_terminal_fd(fd, true); + if (r < 0) + log_warning_errno(r, "Failed to reset terminal, ignoring: %m"); + + r = rearrange_stdio(fd, fd, fd); /* This invalidates 'fd' both on success and on failure. */ + if (r < 0) + return log_error_errno(r, "Failed to make terminal stdin/stdout/stderr: %m"); + } + + reset_terminal_feature_caches(); + return 0; +} + +bool tty_is_vc(const char *tty) { + assert(tty); + + return vtnr_from_tty(tty) >= 0; +} + +bool tty_is_console(const char *tty) { + assert(tty); + + return streq(skip_dev_prefix(tty), "console"); +} + +int vtnr_from_tty(const char *tty) { + int i, r; + + assert(tty); + + tty = skip_dev_prefix(tty); + + if (!startswith(tty, "tty") ) + return -EINVAL; + + if (tty[3] < '0' || tty[3] > '9') + return -EINVAL; + + r = safe_atoi(tty+3, &i); + if (r < 0) + return r; + + if (i < 0 || i > 63) + return -EINVAL; + + return i; +} + + int resolve_dev_console(char **ret) { + _cleanup_free_ char *active = NULL; + char *tty; + int r; + + assert(ret); + + /* Resolve where /dev/console is pointing to, if /sys is actually ours (i.e. not read-only-mounted which is a + * sign for container setups) */ + + if (path_is_read_only_fs("/sys") > 0) + return -ENOMEDIUM; + + r = read_one_line_file("/sys/class/tty/console/active", &active); + if (r < 0) + return r; + + /* If multiple log outputs are configured the last one is what /dev/console points to */ + tty = strrchr(active, ' '); + if (tty) + tty++; + else + tty = active; + + if (streq(tty, "tty0")) { + active = mfree(active); + + /* Get the active VC (e.g. tty1) */ + r = read_one_line_file("/sys/class/tty/tty0/active", &active); + if (r < 0) + return r; + + tty = active; + } + + if (tty == active) + *ret = TAKE_PTR(active); + else { + char *tmp; + + tmp = strdup(tty); + if (!tmp) + return -ENOMEM; + + *ret = tmp; + } + + return 0; +} + +int get_kernel_consoles(char ***ret) { + _cleanup_strv_free_ char **l = NULL; + _cleanup_free_ char *line = NULL; + const char *p; + int r; + + assert(ret); + + /* If /sys is mounted read-only this means we are running in some kind of container environment. In that + * case /sys would reflect the host system, not us, hence ignore the data we can read from it. */ + if (path_is_read_only_fs("/sys") > 0) + goto fallback; + + r = read_one_line_file("/sys/class/tty/console/active", &line); + if (r < 0) + return r; + + p = line; + for (;;) { + _cleanup_free_ char *tty = NULL, *path = NULL; + + r = extract_first_word(&p, &tty, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + if (streq(tty, "tty0")) { + tty = mfree(tty); + r = read_one_line_file("/sys/class/tty/tty0/active", &tty); + if (r < 0) + return r; + } + + path = path_join("/dev", tty); + if (!path) + return -ENOMEM; + + if (access(path, F_OK) < 0) { + log_debug_errno(errno, "Console device %s is not accessible, skipping: %m", path); + continue; + } + + r = strv_consume(&l, TAKE_PTR(path)); + if (r < 0) + return r; + } + + if (strv_isempty(l)) { + log_debug("No devices found for system console"); + goto fallback; + } + + *ret = TAKE_PTR(l); + + return 0; + +fallback: + r = strv_extend(&l, "/dev/console"); + if (r < 0) + return r; + + *ret = TAKE_PTR(l); + + return 0; +} + +bool tty_is_vc_resolve(const char *tty) { + _cleanup_free_ char *resolved = NULL; + + assert(tty); + + tty = skip_dev_prefix(tty); + + if (streq(tty, "console")) { + if (resolve_dev_console(&resolved) < 0) + return false; + + tty = resolved; + } + + return tty_is_vc(tty); +} + +const char *default_term_for_tty(const char *tty) { + return tty && tty_is_vc_resolve(tty) ? "linux" : "vt220"; +} + +int fd_columns(int fd) { + struct winsize ws = {}; + + if (ioctl(fd, TIOCGWINSZ, &ws) < 0) + return -errno; + + if (ws.ws_col <= 0) + return -EIO; + + return ws.ws_col; +} + +unsigned columns(void) { + const char *e; + int c; + + if (cached_columns > 0) + return cached_columns; + + c = 0; + e = getenv("COLUMNS"); + if (e) + (void) safe_atoi(e, &c); + + if (c <= 0 || c > USHRT_MAX) { + c = fd_columns(STDOUT_FILENO); + if (c <= 0) + c = 80; + } + + cached_columns = c; + return cached_columns; +} + +int fd_lines(int fd) { + struct winsize ws = {}; + + if (ioctl(fd, TIOCGWINSZ, &ws) < 0) + return -errno; + + if (ws.ws_row <= 0) + return -EIO; + + return ws.ws_row; +} + +unsigned lines(void) { + const char *e; + int l; + + if (cached_lines > 0) + return cached_lines; + + l = 0; + e = getenv("LINES"); + if (e) + (void) safe_atoi(e, &l); + + if (l <= 0 || l > USHRT_MAX) { + l = fd_lines(STDOUT_FILENO); + if (l <= 0) + l = 24; + } + + cached_lines = l; + return cached_lines; +} + +/* intended to be used as a SIGWINCH sighandler */ +void columns_lines_cache_reset(int signum) { + cached_columns = 0; + cached_lines = 0; +} + +void reset_terminal_feature_caches(void) { + cached_columns = 0; + cached_lines = 0; + + cached_colors_enabled = -1; + cached_underline_enabled = -1; + cached_on_tty = -1; +} + +bool on_tty(void) { + + /* We check both stdout and stderr, so that situations where pipes on the shell are used are reliably + * recognized, regardless if only the output or the errors are piped to some place. Since on_tty() is generally + * used to default to a safer, non-interactive, non-color mode of operation it's probably good to be defensive + * here, and check for both. Note that we don't check for STDIN_FILENO, because it should fine to use fancy + * terminal functionality when outputting stuff, even if the input is piped to us. */ + + if (cached_on_tty < 0) + cached_on_tty = + isatty(STDOUT_FILENO) > 0 && + isatty(STDERR_FILENO) > 0; + + return cached_on_tty; +} + +int getttyname_malloc(int fd, char **ret) { + char path[PATH_MAX], *c; /* PATH_MAX is counted *with* the trailing NUL byte */ + int r; + + assert(fd >= 0); + assert(ret); + + r = ttyname_r(fd, path, sizeof path); /* positive error */ + assert(r >= 0); + if (r == ERANGE) + return -ENAMETOOLONG; + if (r > 0) + return -r; + + c = strdup(skip_dev_prefix(path)); + if (!c) + return -ENOMEM; + + *ret = c; + return 0; +} + +int getttyname_harder(int fd, char **ret) { + _cleanup_free_ char *s = NULL; + int r; + + r = getttyname_malloc(fd, &s); + if (r < 0) + return r; + + if (streq(s, "tty")) + return get_ctty(0, NULL, ret); + + *ret = TAKE_PTR(s); + return 0; +} + +int get_ctty_devnr(pid_t pid, dev_t *d) { + int r; + _cleanup_free_ char *line = NULL; + const char *p; + unsigned long ttynr; + + assert(pid >= 0); + + p = procfs_file_alloca(pid, "stat"); + r = read_one_line_file(p, &line); + if (r < 0) + return r; + + p = strrchr(line, ')'); + if (!p) + return -EIO; + + p++; + + if (sscanf(p, " " + "%*c " /* state */ + "%*d " /* ppid */ + "%*d " /* pgrp */ + "%*d " /* session */ + "%lu ", /* ttynr */ + &ttynr) != 1) + return -EIO; + + if (major(ttynr) == 0 && minor(ttynr) == 0) + return -ENXIO; + + if (d) + *d = (dev_t) ttynr; + + return 0; +} + +int get_ctty(pid_t pid, dev_t *ret_devnr, char **ret) { + _cleanup_free_ char *fn = NULL, *b = NULL; + dev_t devnr; + int r; + + r = get_ctty_devnr(pid, &devnr); + if (r < 0) + return r; + + r = device_path_make_canonical(S_IFCHR, devnr, &fn); + if (r < 0) { + if (r != -ENOENT) /* No symlink for this in /dev/char/? */ + return r; + + if (major(devnr) == 136) { + /* This is an ugly hack: PTY devices are not listed in /dev/char/, as they don't follow the + * Linux device model. This means we have no nice way to match them up against their actual + * device node. Let's hence do the check by the fixed, assigned major number. Normally we try + * to avoid such fixed major/minor matches, but there appears to nother nice way to handle + * this. */ + + if (asprintf(&b, "pts/%u", minor(devnr)) < 0) + return -ENOMEM; + } else { + /* Probably something similar to the ptys which have no symlink in /dev/char/. Let's return + * something vaguely useful. */ + + r = device_path_make_major_minor(S_IFCHR, devnr, &fn); + if (r < 0) + return r; + } + } + + if (!b) { + const char *w; + + w = path_startswith(fn, "/dev/"); + if (w) { + b = strdup(w); + if (!b) + return -ENOMEM; + } else + b = TAKE_PTR(fn); + } + + if (ret) + *ret = TAKE_PTR(b); + + if (ret_devnr) + *ret_devnr = devnr; + + return 0; +} + +int ptsname_malloc(int fd, char **ret) { + size_t l = 100; + + assert(fd >= 0); + assert(ret); + + for (;;) { + char *c; + + c = new(char, l); + if (!c) + return -ENOMEM; + + if (ptsname_r(fd, c, l) == 0) { + *ret = c; + return 0; + } + if (errno != ERANGE) { + free(c); + return -errno; + } + + free(c); + + if (l > SIZE_MAX / 2) + return -ENOMEM; + + l *= 2; + } +} + +int openpt_allocate(int flags, char **ret_slave) { + _cleanup_close_ int fd = -1; + _cleanup_free_ char *p = NULL; + int r; + + fd = posix_openpt(flags|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return -errno; + + if (ret_slave) { + r = ptsname_malloc(fd, &p); + if (r < 0) + return r; + + if (!path_startswith(p, "/dev/pts/")) + return -EINVAL; + } + + if (unlockpt(fd) < 0) + return -errno; + + if (ret_slave) + *ret_slave = TAKE_PTR(p); + + return TAKE_FD(fd); +} + +static int ptsname_namespace(int pty, char **ret) { + int no = -1, r; + + /* Like ptsname(), but doesn't assume that the path is + * accessible in the local namespace. */ + + r = ioctl(pty, TIOCGPTN, &no); + if (r < 0) + return -errno; + + if (no < 0) + return -EIO; + + if (asprintf(ret, "/dev/pts/%i", no) < 0) + return -ENOMEM; + + return 0; +} + +int openpt_allocate_in_namespace(pid_t pid, int flags, char **ret_slave) { + _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1, fd = -1; + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + pid_t child; + int r; + + assert(pid > 0); + + r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd); + if (r < 0) + return r; + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0) + return -errno; + + r = namespace_fork("(sd-openptns)", "(sd-openpt)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG, + pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child); + if (r < 0) + return r; + if (r == 0) { + pair[0] = safe_close(pair[0]); + + fd = openpt_allocate(flags, NULL); + if (fd < 0) + _exit(EXIT_FAILURE); + + if (send_one_fd(pair[1], fd, 0) < 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + r = wait_for_terminate_and_check("(sd-openptns)", child, 0); + if (r < 0) + return r; + if (r != EXIT_SUCCESS) + return -EIO; + + fd = receive_one_fd(pair[0], 0); + if (fd < 0) + return fd; + + if (ret_slave) { + r = ptsname_namespace(fd, ret_slave); + if (r < 0) + return r; + } + + return TAKE_FD(fd); +} + +int open_terminal_in_namespace(pid_t pid, const char *name, int mode) { + _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1; + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + pid_t child; + int r; + + r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd); + if (r < 0) + return r; + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0) + return -errno; + + r = namespace_fork("(sd-terminalns)", "(sd-terminal)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG, + pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child); + if (r < 0) + return r; + if (r == 0) { + int master; + + pair[0] = safe_close(pair[0]); + + master = open_terminal(name, mode|O_NOCTTY|O_CLOEXEC); + if (master < 0) + _exit(EXIT_FAILURE); + + if (send_one_fd(pair[1], master, 0) < 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + r = wait_for_terminate_and_check("(sd-terminalns)", child, 0); + if (r < 0) + return r; + if (r != EXIT_SUCCESS) + return -EIO; + + return receive_one_fd(pair[0], 0); +} + +static bool getenv_terminal_is_dumb(void) { + const char *e; + + e = getenv("TERM"); + if (!e) + return true; + + return streq(e, "dumb"); +} + +bool terminal_is_dumb(void) { + if (!on_tty()) + return true; + + return getenv_terminal_is_dumb(); +} + +bool colors_enabled(void) { + + /* Returns true if colors are considered supported on our stdout. For that we check $SYSTEMD_COLORS first + * (which is the explicit way to turn colors on/off). If that didn't work we turn colors off unless we are on a + * TTY. And if we are on a TTY we turn it off if $TERM is set to "dumb". There's one special tweak though: if + * we are PID 1 then we do not check whether we are connected to a TTY, because we don't keep /dev/console open + * continuously due to fear of SAK, and hence things are a bit weird. */ + + if (cached_colors_enabled < 0) { + int val; + + val = getenv_bool("SYSTEMD_COLORS"); + if (val >= 0) + cached_colors_enabled = val; + + else if (getenv("NO_COLOR")) + /* We only check for the presence of the variable; value is ignored. */ + cached_colors_enabled = false; + + else if (getpid_cached() == 1) + /* PID1 outputs to the console without holding it open all the time */ + cached_colors_enabled = !getenv_terminal_is_dumb(); + else + cached_colors_enabled = !terminal_is_dumb(); + } + + return cached_colors_enabled; +} + +bool dev_console_colors_enabled(void) { + _cleanup_free_ char *s = NULL; + int b; + + /* Returns true if we assume that color is supported on /dev/console. + * + * For that we first check if we explicitly got told to use colors or not, by checking $SYSTEMD_COLORS. If that + * isn't set we check whether PID 1 has $TERM set, and if not, whether TERM is set on the kernel command + * line. If we find $TERM set we assume color if it's not set to "dumb", similarly to how regular + * colors_enabled() operates. */ + + b = getenv_bool("SYSTEMD_COLORS"); + if (b >= 0) + return b; + + if (getenv("NO_COLOR")) + return false; + + if (getenv_for_pid(1, "TERM", &s) <= 0) + (void) proc_cmdline_get_key("TERM", 0, &s); + + return !streq_ptr(s, "dumb"); +} + +bool underline_enabled(void) { + + if (cached_underline_enabled < 0) { + + /* The Linux console doesn't support underlining, turn it off, but only there. */ + + if (colors_enabled()) + cached_underline_enabled = !streq_ptr(getenv("TERM"), "linux"); + else + cached_underline_enabled = false; + } + + return cached_underline_enabled; +} + +int vt_default_utf8(void) { + _cleanup_free_ char *b = NULL; + int r; + + /* Read the default VT UTF8 setting from the kernel */ + + r = read_one_line_file("/sys/module/vt/parameters/default_utf8", &b); + if (r < 0) + return r; + + return parse_boolean(b); +} + +int vt_reset_keyboard(int fd) { + int kb; + + /* If we can't read the default, then default to unicode. It's 2017 after all. */ + kb = vt_default_utf8() != 0 ? K_UNICODE : K_XLATE; + + if (ioctl(fd, KDSKBMODE, kb) < 0) + return -errno; + + return 0; +} + +int vt_restore(int fd) { + static const struct vt_mode mode = { + .mode = VT_AUTO, + }; + int r, q = 0; + + if (ioctl(fd, KDSETMODE, KD_TEXT) < 0) + q = log_debug_errno(errno, "Failed to set VT in text mode, ignoring: %m"); + + r = vt_reset_keyboard(fd); + if (r < 0) { + log_debug_errno(r, "Failed to reset keyboard mode, ignoring: %m"); + if (q >= 0) + q = r; + } + + if (ioctl(fd, VT_SETMODE, &mode) < 0) { + log_debug_errno(errno, "Failed to set VT_AUTO mode, ignoring: %m"); + if (q >= 0) + q = -errno; + } + + r = fchmod_and_chown(fd, TTY_MODE, 0, (gid_t) -1); + if (r < 0) { + log_debug_errno(r, "Failed to chmod()/chown() VT, ignoring: %m"); + if (q >= 0) + q = r; + } + + return q; +} + +int vt_release(int fd, bool restore) { + assert(fd >= 0); + + /* This function releases the VT by acknowledging the VT-switch signal + * sent by the kernel and optionally reset the VT in text and auto + * VT-switching modes. */ + + if (ioctl(fd, VT_RELDISP, 1) < 0) + return -errno; + + if (restore) + return vt_restore(fd); + + return 0; +} + +void get_log_colors(int priority, const char **on, const char **off, const char **highlight) { + /* Note that this will initialize output variables only when there's something to output. + * The caller must pre-initalize to "" or NULL as appropriate. */ + + if (priority <= LOG_ERR) { + if (on) + *on = ANSI_HIGHLIGHT_RED; + if (off) + *off = ANSI_NORMAL; + if (highlight) + *highlight = ANSI_HIGHLIGHT; + + } else if (priority <= LOG_WARNING) { + if (on) + *on = ANSI_HIGHLIGHT_YELLOW; + if (off) + *off = ANSI_NORMAL; + if (highlight) + *highlight = ANSI_HIGHLIGHT; + + } else if (priority <= LOG_NOTICE) { + if (on) + *on = ANSI_HIGHLIGHT; + if (off) + *off = ANSI_NORMAL; + if (highlight) + *highlight = ANSI_HIGHLIGHT_RED; + + } else if (priority >= LOG_DEBUG) { + if (on) + *on = ANSI_GREY; + if (off) + *off = ANSI_NORMAL; + if (highlight) + *highlight = ANSI_HIGHLIGHT_RED; + } +} diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h new file mode 100644 index 00000000..efc22b15 --- /dev/null +++ b/src/basic/terminal-util.h @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include + +#include "macro.h" +#include "time-util.h" + +/* Regular colors */ +#define ANSI_RED "\x1B[0;31m" +#define ANSI_GREEN "\x1B[0;32m" +#define ANSI_YELLOW "\x1B[0;33m" +#define ANSI_BLUE "\x1B[0;34m" +#define ANSI_MAGENTA "\x1B[0;35m" +#define ANSI_GREY "\x1B[0;38;5;245m" + +/* Bold/highlighted */ +#define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m" +#define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m" +#define ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;38;5;185m" +#define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m" +#define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m" +#define ANSI_HIGHLIGHT_GREY "\x1B[0;1;38;5;245m" +#define ANSI_HIGHLIGHT_YELLOW4 "\x1B[0;1;38;5;100m" + +/* Underlined */ +#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m" +#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m" +#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;33m" +#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m" +#define ANSI_HIGHLIGHT_MAGENTA_UNDERLINE "\x1B[0;1;4;35m" +#define ANSI_HIGHLIGHT_GREY_UNDERLINE "\x1B[0;1;4;38;5;245m" + +/* Other ANSI codes */ +#define ANSI_UNDERLINE "\x1B[0;4m" +#define ANSI_HIGHLIGHT "\x1B[0;1;39m" +#define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m" + +/* Reset/clear ANSI styles */ +#define ANSI_NORMAL "\x1B[0m" + +/* Erase characters until the end of the line */ +#define ANSI_ERASE_TO_END_OF_LINE "\x1B[K" + +/* Move cursor up one line */ +#define ANSI_REVERSE_LINEFEED "\x1BM" + +/* Set cursor to top left corner and clear screen */ +#define ANSI_HOME_CLEAR "\x1B[H\x1B[2J" + +int reset_terminal_fd(int fd, bool switch_to_text); +int reset_terminal(const char *name); + +int open_terminal(const char *name, int mode); + +/* Flags for tweaking the way we become the controlling process of a terminal. */ +typedef enum AcquireTerminalFlags { + /* Try to become the controlling process of the TTY. If we can't return -EPERM. */ + ACQUIRE_TERMINAL_TRY = 0, + + /* Tell the kernel to forcibly make us the controlling process of the TTY. Returns -EPERM if the kernel doesn't allow that. */ + ACQUIRE_TERMINAL_FORCE = 1, + + /* If we can't become the controlling process of the TTY right-away, then wait until we can. */ + ACQUIRE_TERMINAL_WAIT = 2, + + /* Pick one of the above, and then OR this flag in, in order to request permissive behaviour, if we can't become controlling process then don't mind */ + ACQUIRE_TERMINAL_PERMISSIVE = 1 << 2, +} AcquireTerminalFlags; + +int acquire_terminal(const char *name, AcquireTerminalFlags flags, usec_t timeout); +int release_terminal(void); + +int terminal_vhangup_fd(int fd); +int terminal_vhangup(const char *name); + +int chvt(int vt); + +int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl); +int ask_char(char *ret, const char *replies, const char *text, ...) _printf_(3, 4); +int ask_string(char **ret, const char *text, ...) _printf_(2, 3); + +int vt_disallocate(const char *name); + +int resolve_dev_console(char **ret); +int get_kernel_consoles(char ***ret); +bool tty_is_vc(const char *tty); +bool tty_is_vc_resolve(const char *tty); +bool tty_is_console(const char *tty) _pure_; +int vtnr_from_tty(const char *tty); +const char *default_term_for_tty(const char *tty); + +int make_console_stdio(void); + +int fd_columns(int fd); +unsigned columns(void); +int fd_lines(int fd); +unsigned lines(void); + +void columns_lines_cache_reset(int _unused_ signum); +void reset_terminal_feature_caches(void); + +bool on_tty(void); +bool terminal_is_dumb(void); +bool colors_enabled(void); +bool underline_enabled(void); +bool dev_console_colors_enabled(void); + +#define DEFINE_ANSI_FUNC(name, NAME) \ + static inline const char *ansi_##name(void) { \ + return colors_enabled() ? ANSI_##NAME : ""; \ + } + +#define DEFINE_ANSI_FUNC_UNDERLINE(name, NAME, REPLACEMENT) \ + static inline const char *ansi_##name(void) { \ + return underline_enabled() ? ANSI_##NAME : \ + colors_enabled() ? ANSI_##REPLACEMENT : ""; \ + } + +DEFINE_ANSI_FUNC(normal, NORMAL); +DEFINE_ANSI_FUNC(highlight, HIGHLIGHT); +DEFINE_ANSI_FUNC(red, RED); +DEFINE_ANSI_FUNC(green, GREEN); +DEFINE_ANSI_FUNC(yellow, YELLOW); +DEFINE_ANSI_FUNC(blue, BLUE); +DEFINE_ANSI_FUNC(magenta, MAGENTA); +DEFINE_ANSI_FUNC(grey, GREY); +DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED); +DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN); +DEFINE_ANSI_FUNC(highlight_yellow, HIGHLIGHT_YELLOW); +DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE); +DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA); +DEFINE_ANSI_FUNC(highlight_grey, HIGHLIGHT_GREY); + +DEFINE_ANSI_FUNC_UNDERLINE(underline, UNDERLINE, NORMAL); +DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline, HIGHLIGHT_UNDERLINE, HIGHLIGHT); +DEFINE_ANSI_FUNC_UNDERLINE(highlight_red_underline, HIGHLIGHT_RED_UNDERLINE, HIGHLIGHT_RED); +DEFINE_ANSI_FUNC_UNDERLINE(highlight_green_underline, HIGHLIGHT_GREEN_UNDERLINE, HIGHLIGHT_GREEN); +DEFINE_ANSI_FUNC_UNDERLINE(highlight_yellow_underline, HIGHLIGHT_YELLOW_UNDERLINE, HIGHLIGHT_YELLOW); +DEFINE_ANSI_FUNC_UNDERLINE(highlight_blue_underline, HIGHLIGHT_BLUE_UNDERLINE, HIGHLIGHT_BLUE); +DEFINE_ANSI_FUNC_UNDERLINE(highlight_magenta_underline, HIGHLIGHT_MAGENTA_UNDERLINE, HIGHLIGHT_MAGENTA); +DEFINE_ANSI_FUNC_UNDERLINE(highlight_grey_underline, HIGHLIGHT_GREY_UNDERLINE, HIGHLIGHT_GREY); + +int get_ctty_devnr(pid_t pid, dev_t *d); +int get_ctty(pid_t, dev_t *_devnr, char **r); + +int getttyname_malloc(int fd, char **r); +int getttyname_harder(int fd, char **r); + +int ptsname_malloc(int fd, char **ret); + +int openpt_allocate(int flags, char **ret_slave); +int openpt_allocate_in_namespace(pid_t pid, int flags, char **ret_slave); +int open_terminal_in_namespace(pid_t pid, const char *name, int mode); + +int vt_default_utf8(void); +int vt_reset_keyboard(int fd); +int vt_restore(int fd); +int vt_release(int fd, bool restore_vt); + +void get_log_colors(int priority, const char **on, const char **off, const char **highlight); + +/* This assumes there is a 'tty' group */ +#define TTY_MODE 0620 diff --git a/src/basic/time-util.c b/src/basic/time-util.c new file mode 100644 index 00000000..105584e2 --- /dev/null +++ b/src/basic/time-util.c @@ -0,0 +1,1528 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "io-util.h" +#include "log.h" +#include "macro.h" +#include "missing_timerfd.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" + +static clockid_t map_clock_id(clockid_t c) { + + /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will + * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is + * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on + * those archs. */ + + switch (c) { + + case CLOCK_BOOTTIME_ALARM: + return CLOCK_BOOTTIME; + + case CLOCK_REALTIME_ALARM: + return CLOCK_REALTIME; + + default: + return c; + } +} + +usec_t now(clockid_t clock_id) { + struct timespec ts; + + assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0); + + return timespec_load(&ts); +} + +nsec_t now_nsec(clockid_t clock_id) { + struct timespec ts; + + assert_se(clock_gettime(map_clock_id(clock_id), &ts) == 0); + + return timespec_load_nsec(&ts); +} + +dual_timestamp* dual_timestamp_get(dual_timestamp *ts) { + assert(ts); + + ts->realtime = now(CLOCK_REALTIME); + ts->monotonic = now(CLOCK_MONOTONIC); + + return ts; +} + +triple_timestamp* triple_timestamp_get(triple_timestamp *ts) { + assert(ts); + + ts->realtime = now(CLOCK_REALTIME); + ts->monotonic = now(CLOCK_MONOTONIC); + ts->boottime = clock_boottime_supported() ? now(CLOCK_BOOTTIME) : USEC_INFINITY; + + return ts; +} + +dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) { + int64_t delta; + assert(ts); + + if (u == USEC_INFINITY || u <= 0) { + ts->realtime = ts->monotonic = u; + return ts; + } + + ts->realtime = u; + + delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u; + ts->monotonic = usec_sub_signed(now(CLOCK_MONOTONIC), delta); + + return ts; +} + +triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u) { + int64_t delta; + + assert(ts); + + if (u == USEC_INFINITY || u <= 0) { + ts->realtime = ts->monotonic = ts->boottime = u; + return ts; + } + + ts->realtime = u; + delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u; + ts->monotonic = usec_sub_signed(now(CLOCK_MONOTONIC), delta); + ts->boottime = clock_boottime_supported() ? usec_sub_signed(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY; + + return ts; +} + +dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) { + int64_t delta; + assert(ts); + + if (u == USEC_INFINITY) { + ts->realtime = ts->monotonic = USEC_INFINITY; + return ts; + } + + ts->monotonic = u; + delta = (int64_t) now(CLOCK_MONOTONIC) - (int64_t) u; + ts->realtime = usec_sub_signed(now(CLOCK_REALTIME), delta); + + return ts; +} + +dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u) { + int64_t delta; + + if (u == USEC_INFINITY) { + ts->realtime = ts->monotonic = USEC_INFINITY; + return ts; + } + + dual_timestamp_get(ts); + delta = (int64_t) now(clock_boottime_or_monotonic()) - (int64_t) u; + ts->realtime = usec_sub_signed(ts->realtime, delta); + ts->monotonic = usec_sub_signed(ts->monotonic, delta); + + return ts; +} + +usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock) { + + switch (clock) { + + case CLOCK_REALTIME: + case CLOCK_REALTIME_ALARM: + return ts->realtime; + + case CLOCK_MONOTONIC: + return ts->monotonic; + + case CLOCK_BOOTTIME: + case CLOCK_BOOTTIME_ALARM: + return ts->boottime; + + default: + return USEC_INFINITY; + } +} + +usec_t timespec_load(const struct timespec *ts) { + assert(ts); + + if (ts->tv_sec < 0 || ts->tv_nsec < 0) + return USEC_INFINITY; + + if ((usec_t) ts->tv_sec > (UINT64_MAX - (ts->tv_nsec / NSEC_PER_USEC)) / USEC_PER_SEC) + return USEC_INFINITY; + + return + (usec_t) ts->tv_sec * USEC_PER_SEC + + (usec_t) ts->tv_nsec / NSEC_PER_USEC; +} + +nsec_t timespec_load_nsec(const struct timespec *ts) { + assert(ts); + + if (ts->tv_sec < 0 || ts->tv_nsec < 0) + return NSEC_INFINITY; + + if ((nsec_t) ts->tv_sec >= (UINT64_MAX - ts->tv_nsec) / NSEC_PER_SEC) + return NSEC_INFINITY; + + return (nsec_t) ts->tv_sec * NSEC_PER_SEC + (nsec_t) ts->tv_nsec; +} + +struct timespec *timespec_store(struct timespec *ts, usec_t u) { + assert(ts); + + if (u == USEC_INFINITY || + u / USEC_PER_SEC >= TIME_T_MAX) { + ts->tv_sec = (time_t) -1; + ts->tv_nsec = (long) -1; + return ts; + } + + ts->tv_sec = (time_t) (u / USEC_PER_SEC); + ts->tv_nsec = (long int) ((u % USEC_PER_SEC) * NSEC_PER_USEC); + + return ts; +} + +usec_t timeval_load(const struct timeval *tv) { + assert(tv); + + if (tv->tv_sec < 0 || tv->tv_usec < 0) + return USEC_INFINITY; + + if ((usec_t) tv->tv_sec > (UINT64_MAX - tv->tv_usec) / USEC_PER_SEC) + return USEC_INFINITY; + + return + (usec_t) tv->tv_sec * USEC_PER_SEC + + (usec_t) tv->tv_usec; +} + +struct timeval *timeval_store(struct timeval *tv, usec_t u) { + assert(tv); + + if (u == USEC_INFINITY || + u / USEC_PER_SEC > TIME_T_MAX) { + tv->tv_sec = (time_t) -1; + tv->tv_usec = (suseconds_t) -1; + } else { + tv->tv_sec = (time_t) (u / USEC_PER_SEC); + tv->tv_usec = (suseconds_t) (u % USEC_PER_SEC); + } + + return tv; +} + +static char *format_timestamp_internal( + char *buf, + size_t l, + usec_t t, + bool utc, + bool us) { + + /* The weekdays in non-localized (English) form. We use this instead of the localized form, so that our + * generated timestamps may be parsed with parse_timestamp(), and always read the same. */ + static const char * const weekdays[] = { + [0] = "Sun", + [1] = "Mon", + [2] = "Tue", + [3] = "Wed", + [4] = "Thu", + [5] = "Fri", + [6] = "Sat", + }; + + struct tm tm; + time_t sec; + size_t n; + + assert(buf); + + if (l < (size_t) (3 + /* week day */ + 1 + 10 + /* space and date */ + 1 + 8 + /* space and time */ + (us ? 1 + 6 : 0) + /* "." and microsecond part */ + 1 + 1 + /* space and shortest possible zone */ + 1)) + return NULL; /* Not enough space even for the shortest form. */ + if (t <= 0 || t == USEC_INFINITY) + return NULL; /* Timestamp is unset */ + + /* Let's not format times with years > 9999 */ + if (t > USEC_TIMESTAMP_FORMATTABLE_MAX) { + assert(l >= STRLEN("--- XXXX-XX-XX XX:XX:XX") + 1); + strcpy(buf, "--- XXXX-XX-XX XX:XX:XX"); + return buf; + } + + sec = (time_t) (t / USEC_PER_SEC); /* Round down */ + + if (!localtime_or_gmtime_r(&sec, &tm, utc)) + return NULL; + + /* Start with the week day */ + assert((size_t) tm.tm_wday < ELEMENTSOF(weekdays)); + memcpy(buf, weekdays[tm.tm_wday], 4); + + /* Add the main components */ + if (strftime(buf + 3, l - 3, " %Y-%m-%d %H:%M:%S", &tm) <= 0) + return NULL; /* Doesn't fit */ + + /* Append the microseconds part, if that's requested */ + if (us) { + n = strlen(buf); + if (n + 8 > l) + return NULL; /* Microseconds part doesn't fit. */ + + sprintf(buf + n, ".%06"PRI_USEC, t % USEC_PER_SEC); + } + + /* Append the timezone */ + n = strlen(buf); + if (utc) { + /* If this is UTC then let's explicitly use the "UTC" string here, because gmtime_r() normally uses the + * obsolete "GMT" instead. */ + if (n + 5 > l) + return NULL; /* "UTC" doesn't fit. */ + + strcpy(buf + n, " UTC"); + + } else if (!isempty(tm.tm_zone)) { + size_t tn; + + /* An explicit timezone is specified, let's use it, if it fits */ + tn = strlen(tm.tm_zone); + if (n + 1 + tn + 1 > l) { + /* The full time zone does not fit in. Yuck. */ + + if (n + 1 + _POSIX_TZNAME_MAX + 1 > l) + return NULL; /* Not even enough space for the POSIX minimum (of 6)? In that case, complain that it doesn't fit */ + + /* So the time zone doesn't fit in fully, but the caller passed enough space for the POSIX + * minimum time zone length. In this case suppress the timezone entirely, in order not to dump + * an overly long, hard to read string on the user. This should be safe, because the user will + * assume the local timezone anyway if none is shown. And so does parse_timestamp(). */ + } else { + buf[n++] = ' '; + strcpy(buf + n, tm.tm_zone); + } + } + + return buf; +} + +char *format_timestamp(char *buf, size_t l, usec_t t) { + return format_timestamp_internal(buf, l, t, false, false); +} + +char *format_timestamp_utc(char *buf, size_t l, usec_t t) { + return format_timestamp_internal(buf, l, t, true, false); +} + +char *format_timestamp_us(char *buf, size_t l, usec_t t) { + return format_timestamp_internal(buf, l, t, false, true); +} + +char *format_timestamp_us_utc(char *buf, size_t l, usec_t t) { + return format_timestamp_internal(buf, l, t, true, true); +} + +char *format_timestamp_relative(char *buf, size_t l, usec_t t) { + const char *s; + usec_t n, d; + + if (t <= 0 || t == USEC_INFINITY) + return NULL; + + n = now(CLOCK_REALTIME); + if (n > t) { + d = n - t; + s = "ago"; + } else { + d = t - n; + s = "left"; + } + + if (d >= USEC_PER_YEAR) + snprintf(buf, l, USEC_FMT " years " USEC_FMT " months %s", + d / USEC_PER_YEAR, + (d % USEC_PER_YEAR) / USEC_PER_MONTH, s); + else if (d >= USEC_PER_MONTH) + snprintf(buf, l, USEC_FMT " months " USEC_FMT " days %s", + d / USEC_PER_MONTH, + (d % USEC_PER_MONTH) / USEC_PER_DAY, s); + else if (d >= USEC_PER_WEEK) + snprintf(buf, l, USEC_FMT " weeks " USEC_FMT " days %s", + d / USEC_PER_WEEK, + (d % USEC_PER_WEEK) / USEC_PER_DAY, s); + else if (d >= 2*USEC_PER_DAY) + snprintf(buf, l, USEC_FMT " days %s", d / USEC_PER_DAY, s); + else if (d >= 25*USEC_PER_HOUR) + snprintf(buf, l, "1 day " USEC_FMT "h %s", + (d - USEC_PER_DAY) / USEC_PER_HOUR, s); + else if (d >= 6*USEC_PER_HOUR) + snprintf(buf, l, USEC_FMT "h %s", + d / USEC_PER_HOUR, s); + else if (d >= USEC_PER_HOUR) + snprintf(buf, l, USEC_FMT "h " USEC_FMT "min %s", + d / USEC_PER_HOUR, + (d % USEC_PER_HOUR) / USEC_PER_MINUTE, s); + else if (d >= 5*USEC_PER_MINUTE) + snprintf(buf, l, USEC_FMT "min %s", + d / USEC_PER_MINUTE, s); + else if (d >= USEC_PER_MINUTE) + snprintf(buf, l, USEC_FMT "min " USEC_FMT "s %s", + d / USEC_PER_MINUTE, + (d % USEC_PER_MINUTE) / USEC_PER_SEC, s); + else if (d >= USEC_PER_SEC) + snprintf(buf, l, USEC_FMT "s %s", + d / USEC_PER_SEC, s); + else if (d >= USEC_PER_MSEC) + snprintf(buf, l, USEC_FMT "ms %s", + d / USEC_PER_MSEC, s); + else if (d > 0) + snprintf(buf, l, USEC_FMT"us %s", + d, s); + else + snprintf(buf, l, "now"); + + buf[l-1] = 0; + return buf; +} + +char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) { + static const struct { + const char *suffix; + usec_t usec; + } table[] = { + { "y", USEC_PER_YEAR }, + { "month", USEC_PER_MONTH }, + { "w", USEC_PER_WEEK }, + { "d", USEC_PER_DAY }, + { "h", USEC_PER_HOUR }, + { "min", USEC_PER_MINUTE }, + { "s", USEC_PER_SEC }, + { "ms", USEC_PER_MSEC }, + { "us", 1 }, + }; + + size_t i; + char *p = buf; + bool something = false; + + assert(buf); + assert(l > 0); + + if (t == USEC_INFINITY) { + strncpy(p, "infinity", l-1); + p[l-1] = 0; + return p; + } + + if (t <= 0) { + strncpy(p, "0", l-1); + p[l-1] = 0; + return p; + } + + /* The result of this function can be parsed with parse_sec */ + + for (i = 0; i < ELEMENTSOF(table); i++) { + int k = 0; + size_t n; + bool done = false; + usec_t a, b; + + if (t <= 0) + break; + + if (t < accuracy && something) + break; + + if (t < table[i].usec) + continue; + + if (l <= 1) + break; + + a = t / table[i].usec; + b = t % table[i].usec; + + /* Let's see if we should shows this in dot notation */ + if (t < USEC_PER_MINUTE && b > 0) { + usec_t cc; + signed char j; + + j = 0; + for (cc = table[i].usec; cc > 1; cc /= 10) + j++; + + for (cc = accuracy; cc > 1; cc /= 10) { + b /= 10; + j--; + } + + if (j > 0) { + k = snprintf(p, l, + "%s"USEC_FMT".%0*"PRI_USEC"%s", + p > buf ? " " : "", + a, + j, + b, + table[i].suffix); + + t = 0; + done = true; + } + } + + /* No? Then let's show it normally */ + if (!done) { + k = snprintf(p, l, + "%s"USEC_FMT"%s", + p > buf ? " " : "", + a, + table[i].suffix); + + t = b; + } + + n = MIN((size_t) k, l); + + l -= n; + p += n; + + something = true; + } + + *p = 0; + + return buf; +} + +static int parse_timestamp_impl(const char *t, usec_t *usec, bool with_tz) { + static const struct { + const char *name; + const int nr; + } day_nr[] = { + { "Sunday", 0 }, + { "Sun", 0 }, + { "Monday", 1 }, + { "Mon", 1 }, + { "Tuesday", 2 }, + { "Tue", 2 }, + { "Wednesday", 3 }, + { "Wed", 3 }, + { "Thursday", 4 }, + { "Thu", 4 }, + { "Friday", 5 }, + { "Fri", 5 }, + { "Saturday", 6 }, + { "Sat", 6 }, + }; + + const char *k, *utc = NULL, *tzn = NULL; + struct tm tm, copy; + time_t x; + usec_t x_usec, plus = 0, minus = 0, ret; + int r, weekday = -1, dst = -1; + size_t i; + + /* Allowed syntaxes: + * + * 2012-09-22 16:34:22 + * 2012-09-22 16:34 (seconds will be set to 0) + * 2012-09-22 (time will be set to 00:00:00) + * 16:34:22 (date will be set to today) + * 16:34 (date will be set to today, seconds to 0) + * now + * yesterday (time is set to 00:00:00) + * today (time is set to 00:00:00) + * tomorrow (time is set to 00:00:00) + * +5min + * -5days + * @2147483647 (seconds since epoch) + */ + + assert(t); + + if (t[0] == '@' && !with_tz) + return parse_sec(t + 1, usec); + + ret = now(CLOCK_REALTIME); + + if (!with_tz) { + if (streq(t, "now")) + goto finish; + + else if (t[0] == '+') { + r = parse_sec(t+1, &plus); + if (r < 0) + return r; + + goto finish; + + } else if (t[0] == '-') { + r = parse_sec(t+1, &minus); + if (r < 0) + return r; + + goto finish; + + } else if ((k = endswith(t, " ago"))) { + t = strndupa(t, k - t); + + r = parse_sec(t, &minus); + if (r < 0) + return r; + + goto finish; + + } else if ((k = endswith(t, " left"))) { + t = strndupa(t, k - t); + + r = parse_sec(t, &plus); + if (r < 0) + return r; + + goto finish; + } + + /* See if the timestamp is suffixed with UTC */ + utc = endswith_no_case(t, " UTC"); + if (utc) + t = strndupa(t, utc - t); + else { + const char *e = NULL; + int j; + + tzset(); + + /* See if the timestamp is suffixed by either the DST or non-DST local timezone. Note that we only + * support the local timezones here, nothing else. Not because we wouldn't want to, but simply because + * there are no nice APIs available to cover this. By accepting the local time zone strings, we make + * sure that all timestamps written by format_timestamp() can be parsed correctly, even though we don't + * support arbitrary timezone specifications. */ + + for (j = 0; j <= 1; j++) { + + if (isempty(tzname[j])) + continue; + + e = endswith_no_case(t, tzname[j]); + if (!e) + continue; + if (e == t) + continue; + if (e[-1] != ' ') + continue; + + break; + } + + if (IN_SET(j, 0, 1)) { + /* Found one of the two timezones specified. */ + t = strndupa(t, e - t - 1); + dst = j; + tzn = tzname[j]; + } + } + } + + x = (time_t) (ret / USEC_PER_SEC); + x_usec = 0; + + if (!localtime_or_gmtime_r(&x, &tm, utc)) + return -EINVAL; + + tm.tm_isdst = dst; + if (!with_tz && tzn) + tm.tm_zone = tzn; + + if (streq(t, "today")) { + tm.tm_sec = tm.tm_min = tm.tm_hour = 0; + goto from_tm; + + } else if (streq(t, "yesterday")) { + tm.tm_mday--; + tm.tm_sec = tm.tm_min = tm.tm_hour = 0; + goto from_tm; + + } else if (streq(t, "tomorrow")) { + tm.tm_mday++; + tm.tm_sec = tm.tm_min = tm.tm_hour = 0; + goto from_tm; + } + + for (i = 0; i < ELEMENTSOF(day_nr); i++) { + size_t skip; + + if (!startswith_no_case(t, day_nr[i].name)) + continue; + + skip = strlen(day_nr[i].name); + if (t[skip] != ' ') + continue; + + weekday = day_nr[i].nr; + t += skip + 1; + break; + } + + copy = tm; + k = strptime(t, "%y-%m-%d %H:%M:%S", &tm); + if (k) { + if (*k == '.') + goto parse_usec; + else if (*k == 0) + goto from_tm; + } + + tm = copy; + k = strptime(t, "%Y-%m-%d %H:%M:%S", &tm); + if (k) { + if (*k == '.') + goto parse_usec; + else if (*k == 0) + goto from_tm; + } + + tm = copy; + k = strptime(t, "%y-%m-%d %H:%M", &tm); + if (k && *k == 0) { + tm.tm_sec = 0; + goto from_tm; + } + + tm = copy; + k = strptime(t, "%Y-%m-%d %H:%M", &tm); + if (k && *k == 0) { + tm.tm_sec = 0; + goto from_tm; + } + + tm = copy; + k = strptime(t, "%y-%m-%d", &tm); + if (k && *k == 0) { + tm.tm_sec = tm.tm_min = tm.tm_hour = 0; + goto from_tm; + } + + tm = copy; + k = strptime(t, "%Y-%m-%d", &tm); + if (k && *k == 0) { + tm.tm_sec = tm.tm_min = tm.tm_hour = 0; + goto from_tm; + } + + tm = copy; + k = strptime(t, "%H:%M:%S", &tm); + if (k) { + if (*k == '.') + goto parse_usec; + else if (*k == 0) + goto from_tm; + } + + tm = copy; + k = strptime(t, "%H:%M", &tm); + if (k && *k == 0) { + tm.tm_sec = 0; + goto from_tm; + } + + return -EINVAL; + +parse_usec: + { + unsigned add; + + k++; + r = parse_fractional_part_u(&k, 6, &add); + if (r < 0) + return -EINVAL; + + if (*k) + return -EINVAL; + + x_usec = add; + } + +from_tm: + if (weekday >= 0 && tm.tm_wday != weekday) + return -EINVAL; + + x = mktime_or_timegm(&tm, utc); + if (x < 0) + return -EINVAL; + + ret = (usec_t) x * USEC_PER_SEC + x_usec; + if (ret > USEC_TIMESTAMP_FORMATTABLE_MAX) + return -EINVAL; + +finish: + if (ret + plus < ret) /* overflow? */ + return -EINVAL; + ret += plus; + if (ret > USEC_TIMESTAMP_FORMATTABLE_MAX) + return -EINVAL; + + if (ret >= minus) + ret -= minus; + else + return -EINVAL; + + if (usec) + *usec = ret; + return 0; +} + +typedef struct ParseTimestampResult { + usec_t usec; + int return_value; +} ParseTimestampResult; + +int parse_timestamp(const char *t, usec_t *usec) { + char *last_space, *tz = NULL; + ParseTimestampResult *shared, tmp; + int r; + + last_space = strrchr(t, ' '); + if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG)) + tz = last_space + 1; + + if (!tz || endswith_no_case(t, " UTC")) + return parse_timestamp_impl(t, usec, false); + + shared = mmap(NULL, sizeof *shared, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); + if (shared == MAP_FAILED) + return negative_errno(); + + r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT, NULL); + if (r < 0) { + (void) munmap(shared, sizeof *shared); + return r; + } + if (r == 0) { + bool with_tz = true; + char *colon_tz; + + /* tzset(3) says $TZ should be prefixed with ":" if we reference timezone files */ + colon_tz = strjoina(":", tz); + + if (setenv("TZ", colon_tz, 1) != 0) { + shared->return_value = negative_errno(); + _exit(EXIT_FAILURE); + } + + tzset(); + + /* If there is a timezone that matches the tzname fields, leave the parsing to the implementation. + * Otherwise just cut it off. */ + with_tz = !STR_IN_SET(tz, tzname[0], tzname[1]); + + /* Cut off the timezone if we don't need it. */ + if (with_tz) + t = strndupa(t, last_space - t); + + shared->return_value = parse_timestamp_impl(t, &shared->usec, with_tz); + + _exit(EXIT_SUCCESS); + } + + tmp = *shared; + if (munmap(shared, sizeof *shared) != 0) + return negative_errno(); + + if (tmp.return_value == 0 && usec) + *usec = tmp.usec; + + return tmp.return_value; +} + +static const char* extract_multiplier(const char *p, usec_t *multiplier) { + static const struct { + const char *suffix; + usec_t usec; + } table[] = { + { "seconds", USEC_PER_SEC }, + { "second", USEC_PER_SEC }, + { "sec", USEC_PER_SEC }, + { "s", USEC_PER_SEC }, + { "minutes", USEC_PER_MINUTE }, + { "minute", USEC_PER_MINUTE }, + { "min", USEC_PER_MINUTE }, + { "months", USEC_PER_MONTH }, + { "month", USEC_PER_MONTH }, + { "M", USEC_PER_MONTH }, + { "msec", USEC_PER_MSEC }, + { "ms", USEC_PER_MSEC }, + { "m", USEC_PER_MINUTE }, + { "hours", USEC_PER_HOUR }, + { "hour", USEC_PER_HOUR }, + { "hr", USEC_PER_HOUR }, + { "h", USEC_PER_HOUR }, + { "days", USEC_PER_DAY }, + { "day", USEC_PER_DAY }, + { "d", USEC_PER_DAY }, + { "weeks", USEC_PER_WEEK }, + { "week", USEC_PER_WEEK }, + { "w", USEC_PER_WEEK }, + { "years", USEC_PER_YEAR }, + { "year", USEC_PER_YEAR }, + { "y", USEC_PER_YEAR }, + { "usec", 1ULL }, + { "us", 1ULL }, + { "µs", 1ULL }, + }; + size_t i; + + for (i = 0; i < ELEMENTSOF(table); i++) { + char *e; + + e = startswith(p, table[i].suffix); + if (e) { + *multiplier = table[i].usec; + return e; + } + } + + return p; +} + +int parse_time(const char *t, usec_t *usec, usec_t default_unit) { + const char *p, *s; + usec_t r = 0; + bool something = false; + + assert(t); + assert(default_unit > 0); + + p = t; + + p += strspn(p, WHITESPACE); + s = startswith(p, "infinity"); + if (s) { + s += strspn(s, WHITESPACE); + if (*s != 0) + return -EINVAL; + + if (usec) + *usec = USEC_INFINITY; + return 0; + } + + for (;;) { + usec_t multiplier = default_unit, k; + long long l; + char *e; + + p += strspn(p, WHITESPACE); + + if (*p == 0) { + if (!something) + return -EINVAL; + + break; + } + + if (*p == '-') /* Don't allow "-0" */ + return -ERANGE; + + errno = 0; + l = strtoll(p, &e, 10); + if (errno > 0) + return -errno; + if (l < 0) + return -ERANGE; + + if (*e == '.') { + p = e + 1; + p += strspn(p, DIGITS); + } else if (e == p) + return -EINVAL; + else + p = e; + + s = extract_multiplier(p + strspn(p, WHITESPACE), &multiplier); + if (s == p && *s != '\0') + /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56'*/ + return -EINVAL; + + p = s; + + if ((usec_t) l >= USEC_INFINITY / multiplier) + return -ERANGE; + + k = (usec_t) l * multiplier; + if (k >= USEC_INFINITY - r) + return -ERANGE; + + r += k; + + something = true; + + if (*e == '.') { + usec_t m = multiplier / 10; + const char *b; + + for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) { + k = (usec_t) (*b - '0') * m; + if (k >= USEC_INFINITY - r) + return -ERANGE; + + r += k; + } + + /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge"*/ + if (b == e + 1) + return -EINVAL; + } + } + + if (usec) + *usec = r; + return 0; +} + +int parse_sec(const char *t, usec_t *usec) { + return parse_time(t, usec, USEC_PER_SEC); +} + +int parse_sec_fix_0(const char *t, usec_t *ret) { + usec_t k; + int r; + + assert(t); + assert(ret); + + r = parse_sec(t, &k); + if (r < 0) + return r; + + *ret = k == 0 ? USEC_INFINITY : k; + return r; +} + +int parse_sec_def_infinity(const char *t, usec_t *ret) { + t += strspn(t, WHITESPACE); + if (isempty(t)) { + *ret = USEC_INFINITY; + return 0; + } + return parse_sec(t, ret); +} + +static const char* extract_nsec_multiplier(const char *p, nsec_t *multiplier) { + static const struct { + const char *suffix; + nsec_t nsec; + } table[] = { + { "seconds", NSEC_PER_SEC }, + { "second", NSEC_PER_SEC }, + { "sec", NSEC_PER_SEC }, + { "s", NSEC_PER_SEC }, + { "minutes", NSEC_PER_MINUTE }, + { "minute", NSEC_PER_MINUTE }, + { "min", NSEC_PER_MINUTE }, + { "months", NSEC_PER_MONTH }, + { "month", NSEC_PER_MONTH }, + { "M", NSEC_PER_MONTH }, + { "msec", NSEC_PER_MSEC }, + { "ms", NSEC_PER_MSEC }, + { "m", NSEC_PER_MINUTE }, + { "hours", NSEC_PER_HOUR }, + { "hour", NSEC_PER_HOUR }, + { "hr", NSEC_PER_HOUR }, + { "h", NSEC_PER_HOUR }, + { "days", NSEC_PER_DAY }, + { "day", NSEC_PER_DAY }, + { "d", NSEC_PER_DAY }, + { "weeks", NSEC_PER_WEEK }, + { "week", NSEC_PER_WEEK }, + { "w", NSEC_PER_WEEK }, + { "years", NSEC_PER_YEAR }, + { "year", NSEC_PER_YEAR }, + { "y", NSEC_PER_YEAR }, + { "usec", NSEC_PER_USEC }, + { "us", NSEC_PER_USEC }, + { "µs", NSEC_PER_USEC }, + { "nsec", 1ULL }, + { "ns", 1ULL }, + { "", 1ULL }, /* default is nsec */ + }; + size_t i; + + for (i = 0; i < ELEMENTSOF(table); i++) { + char *e; + + e = startswith(p, table[i].suffix); + if (e) { + *multiplier = table[i].nsec; + return e; + } + } + + return p; +} + +int parse_nsec(const char *t, nsec_t *nsec) { + const char *p, *s; + nsec_t r = 0; + bool something = false; + + assert(t); + assert(nsec); + + p = t; + + p += strspn(p, WHITESPACE); + s = startswith(p, "infinity"); + if (s) { + s += strspn(s, WHITESPACE); + if (*s != 0) + return -EINVAL; + + *nsec = NSEC_INFINITY; + return 0; + } + + for (;;) { + nsec_t multiplier = 1, k; + long long l; + char *e; + + p += strspn(p, WHITESPACE); + + if (*p == 0) { + if (!something) + return -EINVAL; + + break; + } + + if (*p == '-') /* Don't allow "-0" */ + return -ERANGE; + + errno = 0; + l = strtoll(p, &e, 10); + if (errno > 0) + return -errno; + if (l < 0) + return -ERANGE; + + if (*e == '.') { + p = e + 1; + p += strspn(p, DIGITS); + } else if (e == p) + return -EINVAL; + else + p = e; + + s = extract_nsec_multiplier(p + strspn(p, WHITESPACE), &multiplier); + if (s == p && *s != '\0') + /* Don't allow '12.34.56', but accept '12.34 .56' or '12.34s.56'*/ + return -EINVAL; + + p = s; + + if ((nsec_t) l >= NSEC_INFINITY / multiplier) + return -ERANGE; + + k = (nsec_t) l * multiplier; + if (k >= NSEC_INFINITY - r) + return -ERANGE; + + r += k; + + something = true; + + if (*e == '.') { + nsec_t m = multiplier / 10; + const char *b; + + for (b = e + 1; *b >= '0' && *b <= '9'; b++, m /= 10) { + k = (nsec_t) (*b - '0') * m; + if (k >= NSEC_INFINITY - r) + return -ERANGE; + + r += k; + } + + /* Don't allow "0.-0", "3.+1", "3. 1", "3.sec" or "3.hoge"*/ + if (b == e + 1) + return -EINVAL; + } + } + + *nsec = r; + + return 0; +} + +bool ntp_synced(void) { + struct timex txc = {}; + + if (adjtimex(&txc) < 0) + return false; + + /* Consider the system clock synchronized if the reported maximum error is smaller than the maximum + * value (16 seconds). Ignore the STA_UNSYNC flag as it may have been set to prevent the kernel from + * touching the RTC. */ + if (txc.maxerror >= 16000000) + return false; + + return true; +} + +int get_timezones(char ***ret) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_strv_free_ char **zones = NULL; + size_t n_zones = 0, n_allocated = 0; + int r; + + assert(ret); + + zones = strv_new("UTC"); + if (!zones) + return -ENOMEM; + + n_allocated = 2; + n_zones = 1; + + f = fopen("/usr/share/zoneinfo/zone1970.tab", "re"); + if (f) { + for (;;) { + _cleanup_free_ char *line = NULL; + char *p, *w; + size_t k; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + p = strstrip(line); + + if (isempty(p) || *p == '#') + continue; + + /* Skip over country code */ + p += strcspn(p, WHITESPACE); + p += strspn(p, WHITESPACE); + + /* Skip over coordinates */ + p += strcspn(p, WHITESPACE); + p += strspn(p, WHITESPACE); + + /* Found timezone name */ + k = strcspn(p, WHITESPACE); + if (k <= 0) + continue; + + w = strndup(p, k); + if (!w) + return -ENOMEM; + + if (!GREEDY_REALLOC(zones, n_allocated, n_zones + 2)) { + free(w); + return -ENOMEM; + } + + zones[n_zones++] = w; + zones[n_zones] = NULL; + } + + strv_sort(zones); + strv_uniq(zones); + + } else if (errno != ENOENT) + return -errno; + + *ret = TAKE_PTR(zones); + + return 0; +} + +bool timezone_is_valid(const char *name, int log_level) { + bool slash = false; + const char *p, *t; + _cleanup_close_ int fd = -1; + char buf[4]; + int r; + + if (isempty(name)) + return false; + + /* Always accept "UTC" as valid timezone, since it's the fallback, even if user has no timezones installed. */ + if (streq(name, "UTC")) + return true; + + if (name[0] == '/') + return false; + + for (p = name; *p; p++) { + if (!(*p >= '0' && *p <= '9') && + !(*p >= 'a' && *p <= 'z') && + !(*p >= 'A' && *p <= 'Z') && + !IN_SET(*p, '-', '_', '+', '/')) + return false; + + if (*p == '/') { + + if (slash) + return false; + + slash = true; + } else + slash = false; + } + + if (slash) + return false; + + if (p - name >= PATH_MAX) + return false; + + t = strjoina("/usr/share/zoneinfo/", name); + + fd = open(t, O_RDONLY|O_CLOEXEC); + if (fd < 0) { + log_full_errno(log_level, errno, "Failed to open timezone file '%s': %m", t); + return false; + } + + r = fd_verify_regular(fd); + if (r < 0) { + log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t); + return false; + } + + r = loop_read_exact(fd, buf, 4, false); + if (r < 0) { + log_full_errno(log_level, r, "Failed to read from timezone file '%s': %m", t); + return false; + } + + /* Magic from tzfile(5) */ + if (memcmp(buf, "TZif", 4) != 0) { + log_full(log_level, "Timezone file '%s' has wrong magic bytes", t); + return false; + } + + return true; +} + +bool clock_boottime_supported(void) { + static int supported = -1; + + /* Note that this checks whether CLOCK_BOOTTIME is available in general as well as available for timerfds()! */ + + if (supported < 0) { + int fd; + + fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC); + if (fd < 0) + supported = false; + else { + safe_close(fd); + supported = true; + } + } + + return supported; +} + +clockid_t clock_boottime_or_monotonic(void) { + if (clock_boottime_supported()) + return CLOCK_BOOTTIME; + else + return CLOCK_MONOTONIC; +} + +bool clock_supported(clockid_t clock) { + struct timespec ts; + + switch (clock) { + + case CLOCK_MONOTONIC: + case CLOCK_REALTIME: + return true; + + case CLOCK_BOOTTIME: + return clock_boottime_supported(); + + case CLOCK_BOOTTIME_ALARM: + if (!clock_boottime_supported()) + return false; + + _fallthrough_; + default: + /* For everything else, check properly */ + return clock_gettime(clock, &ts) >= 0; + } +} + +int get_timezone(char **ret) { + _cleanup_free_ char *t = NULL; + const char *e; + char *z; + int r; + + r = readlink_malloc("/etc/localtime", &t); + if (r == -ENOENT) { + /* If the symlink does not exist, assume "UTC", like glibc does*/ + z = strdup("UTC"); + if (!z) + return -ENOMEM; + + *ret = z; + return 0; + } + if (r < 0) + return r; /* returns EINVAL if not a symlink */ + + e = PATH_STARTSWITH_SET(t, "/usr/share/zoneinfo/", "../usr/share/zoneinfo/"); + if (!e) + return -EINVAL; + + if (!timezone_is_valid(e, LOG_DEBUG)) + return -EINVAL; + + z = strdup(e); + if (!z) + return -ENOMEM; + + *ret = z; + return 0; +} + +time_t mktime_or_timegm(struct tm *tm, bool utc) { + return utc ? timegm(tm) : mktime(tm); +} + +struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc) { + return utc ? gmtime_r(t, tm) : localtime_r(t, tm); +} + +static uint32_t sysconf_clock_ticks_cached(void) { + static thread_local uint32_t hz = 0; + long r; + + if (hz == 0) { + r = sysconf(_SC_CLK_TCK); + + assert(r > 0); + hz = r; + } + + return hz; +} + +uint32_t usec_to_jiffies(usec_t u) { + uint32_t hz = sysconf_clock_ticks_cached(); + return DIV_ROUND_UP(u, USEC_PER_SEC / hz); +} + +usec_t jiffies_to_usec(uint32_t j) { + uint32_t hz = sysconf_clock_ticks_cached(); + return DIV_ROUND_UP(j * USEC_PER_SEC, hz); +} + +usec_t usec_shift_clock(usec_t x, clockid_t from, clockid_t to) { + usec_t a, b; + + if (x == USEC_INFINITY) + return USEC_INFINITY; + if (map_clock_id(from) == map_clock_id(to)) + return x; + + a = now(from); + b = now(to); + + if (x > a) + /* x lies in the future */ + return usec_add(b, usec_sub_unsigned(x, a)); + else + /* x lies in the past */ + return usec_sub_unsigned(b, usec_sub_unsigned(a, x)); +} + +bool in_utc_timezone(void) { + tzset(); + + return timezone == 0 && daylight == 0; +} + +int time_change_fd(void) { + + /* We only care for the cancellation event, hence we set the timeout to the latest possible value. */ + static const struct itimerspec its = { + .it_value.tv_sec = TIME_T_MAX, + }; + + _cleanup_close_ int fd; + + assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX)); + + /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever CLOCK_REALTIME makes a jump relative to + * CLOCK_MONOTONIC. */ + + fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC); + if (fd < 0) + return -errno; + + if (timerfd_settime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) >= 0) + return TAKE_FD(fd); + + /* So apparently there are systems where time_t is 64bit, but the kernel actually doesn't support + * 64bit time_t. In that case configuring a timer to TIME_T_MAX will fail with EOPNOTSUPP or a + * similar error. If that's the case let's try with INT32_MAX instead, maybe that works. It's a bit + * of a black magic thing though, but what can we do? + * + * We don't want this code on x86-64, hence let's conditionalize this for systems with 64bit time_t + * but where "long" is shorter than 64bit, i.e. 32bit archs. + * + * See: https://github.com/systemd/systemd/issues/14362 */ + +#if SIZEOF_TIME_T == 8 && ULONG_MAX < UINT64_MAX + if (ERRNO_IS_NOT_SUPPORTED(errno) || errno == EOVERFLOW) { + static const struct itimerspec its32 = { + .it_value.tv_sec = INT32_MAX, + }; + + if (timerfd_settime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its32, NULL) >= 0) + return TAKE_FD(fd); + } +#endif + + return -errno; +} diff --git a/src/basic/time-util.h b/src/basic/time-util.h new file mode 100644 index 00000000..4c371257 --- /dev/null +++ b/src/basic/time-util.h @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include +#include + +typedef uint64_t usec_t; +typedef uint64_t nsec_t; + +#define PRI_NSEC PRIu64 +#define PRI_USEC PRIu64 +#define NSEC_FMT "%" PRI_NSEC +#define USEC_FMT "%" PRI_USEC + +#include "macro.h" + +typedef struct dual_timestamp { + usec_t realtime; + usec_t monotonic; +} dual_timestamp; + +typedef struct triple_timestamp { + usec_t realtime; + usec_t monotonic; + usec_t boottime; +} triple_timestamp; + +#define USEC_INFINITY ((usec_t) -1) +#define NSEC_INFINITY ((nsec_t) -1) + +#define MSEC_PER_SEC 1000ULL +#define USEC_PER_SEC ((usec_t) 1000000ULL) +#define USEC_PER_MSEC ((usec_t) 1000ULL) +#define NSEC_PER_SEC ((nsec_t) 1000000000ULL) +#define NSEC_PER_MSEC ((nsec_t) 1000000ULL) +#define NSEC_PER_USEC ((nsec_t) 1000ULL) + +#define USEC_PER_MINUTE ((usec_t) (60ULL*USEC_PER_SEC)) +#define NSEC_PER_MINUTE ((nsec_t) (60ULL*NSEC_PER_SEC)) +#define USEC_PER_HOUR ((usec_t) (60ULL*USEC_PER_MINUTE)) +#define NSEC_PER_HOUR ((nsec_t) (60ULL*NSEC_PER_MINUTE)) +#define USEC_PER_DAY ((usec_t) (24ULL*USEC_PER_HOUR)) +#define NSEC_PER_DAY ((nsec_t) (24ULL*NSEC_PER_HOUR)) +#define USEC_PER_WEEK ((usec_t) (7ULL*USEC_PER_DAY)) +#define NSEC_PER_WEEK ((nsec_t) (7ULL*NSEC_PER_DAY)) +#define USEC_PER_MONTH ((usec_t) (2629800ULL*USEC_PER_SEC)) +#define NSEC_PER_MONTH ((nsec_t) (2629800ULL*NSEC_PER_SEC)) +#define USEC_PER_YEAR ((usec_t) (31557600ULL*USEC_PER_SEC)) +#define NSEC_PER_YEAR ((nsec_t) (31557600ULL*NSEC_PER_SEC)) + +/* We assume a maximum timezone length of 6. TZNAME_MAX is not defined on Linux, but glibc internally initializes this + * to 6. Let's rely on that. */ +#define FORMAT_TIMESTAMP_MAX (3+1+10+1+8+1+6+1+6+1) +#define FORMAT_TIMESTAMP_WIDTH 28 /* when outputting, assume this width */ +#define FORMAT_TIMESTAMP_RELATIVE_MAX 256 +#define FORMAT_TIMESPAN_MAX 64 + +#define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1) + +#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) {}) +#define TRIPLE_TIMESTAMP_NULL ((struct triple_timestamp) {}) + +usec_t now(clockid_t clock); +nsec_t now_nsec(clockid_t clock); + +dual_timestamp* dual_timestamp_get(dual_timestamp *ts); +dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u); +dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u); +dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u); + +triple_timestamp* triple_timestamp_get(triple_timestamp *ts); +triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u); + +#define DUAL_TIMESTAMP_HAS_CLOCK(clock) \ + IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC) + +#define TRIPLE_TIMESTAMP_HAS_CLOCK(clock) \ + IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) + +static inline bool timestamp_is_set(usec_t timestamp) { + return timestamp > 0 && timestamp != USEC_INFINITY; +} + +static inline bool dual_timestamp_is_set(const dual_timestamp *ts) { + return timestamp_is_set(ts->realtime) || + timestamp_is_set(ts->monotonic); +} + +static inline bool triple_timestamp_is_set(const triple_timestamp *ts) { + return timestamp_is_set(ts->realtime) || + timestamp_is_set(ts->monotonic) || + timestamp_is_set(ts->boottime); +} + +usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock); + +usec_t timespec_load(const struct timespec *ts) _pure_; +nsec_t timespec_load_nsec(const struct timespec *ts) _pure_; +struct timespec *timespec_store(struct timespec *ts, usec_t u); + +usec_t timeval_load(const struct timeval *tv) _pure_; +struct timeval *timeval_store(struct timeval *tv, usec_t u); + +char *format_timestamp(char *buf, size_t l, usec_t t); +char *format_timestamp_utc(char *buf, size_t l, usec_t t); +char *format_timestamp_us(char *buf, size_t l, usec_t t); +char *format_timestamp_us_utc(char *buf, size_t l, usec_t t); +char *format_timestamp_relative(char *buf, size_t l, usec_t t); +char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy); + +int parse_timestamp(const char *t, usec_t *usec); + +int parse_sec(const char *t, usec_t *usec); +int parse_sec_fix_0(const char *t, usec_t *usec); +int parse_sec_def_infinity(const char *t, usec_t *usec); +int parse_time(const char *t, usec_t *usec, usec_t default_unit); +int parse_nsec(const char *t, nsec_t *nsec); + +bool ntp_synced(void); + +int get_timezones(char ***l); +bool timezone_is_valid(const char *name, int log_level); + +bool clock_boottime_supported(void); +bool clock_supported(clockid_t clock); +clockid_t clock_boottime_or_monotonic(void); + +usec_t usec_shift_clock(usec_t, clockid_t from, clockid_t to); + +int get_timezone(char **timezone); + +time_t mktime_or_timegm(struct tm *tm, bool utc); +struct tm *localtime_or_gmtime_r(const time_t *t, struct tm *tm, bool utc); + +uint32_t usec_to_jiffies(usec_t usec); +usec_t jiffies_to_usec(uint32_t jiffies); + +bool in_utc_timezone(void); + +static inline usec_t usec_add(usec_t a, usec_t b) { + usec_t c; + + /* Adds two time values, and makes sure USEC_INFINITY as input results as USEC_INFINITY in output, and doesn't + * overflow. */ + + c = a + b; + if (c < a || c < b) /* overflow check */ + return USEC_INFINITY; + + return c; +} + +static inline usec_t usec_sub_unsigned(usec_t timestamp, usec_t delta) { + + if (timestamp == USEC_INFINITY) /* Make sure infinity doesn't degrade */ + return USEC_INFINITY; + if (timestamp < delta) + return 0; + + return timestamp - delta; +} + +static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) { + if (delta < 0) + return usec_add(timestamp, (usec_t) (-delta)); + else + return usec_sub_unsigned(timestamp, (usec_t) delta); +} + +#if SIZEOF_TIME_T == 8 +/* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit year + * territory. However, since we want to stay away from this in all timezones we take one day off. */ +#define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 253402214399000000) +#elif SIZEOF_TIME_T == 4 +/* With a 32bit time_t we can't go beyond 2038... */ +#define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 2147483647000000) +#else +#error "Yuck, time_t is neither 4 nor 8 bytes wide?" +#endif + +int time_change_fd(void); diff --git a/src/basic/tmpfile-util.c b/src/basic/tmpfile-util.c new file mode 100644 index 00000000..7cdaca4e --- /dev/null +++ b/src/basic/tmpfile-util.c @@ -0,0 +1,332 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hexdecoct.h" +#include "macro.h" +#include "memfd-util.h" +#include "missing_fcntl.h" +#include "missing_syscall.h" +#include "path-util.h" +#include "process-util.h" +#include "random-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "umask-util.h" + +int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { + FILE *f; + char *t; + int r, fd; + + assert(path); + assert(_f); + assert(_temp_path); + + r = tempfn_xxxxxx(path, NULL, &t); + if (r < 0) + return r; + + fd = mkostemp_safe(t); + if (fd < 0) { + free(t); + return -errno; + } + + /* This assumes that returned FILE object is short-lived and used within the same single-threaded + * context and never shared externally, hence locking is not necessary. */ + + r = fdopen_unlocked(fd, "w", &f); + if (r < 0) { + unlink(t); + free(t); + safe_close(fd); + return r; + } + + *_f = f; + *_temp_path = t; + + return 0; +} + +/* This is much like mkostemp() but is subject to umask(). */ +int mkostemp_safe(char *pattern) { + _unused_ _cleanup_umask_ mode_t u = umask(0077); + int fd; + + assert(pattern); + + fd = mkostemp(pattern, O_CLOEXEC); + if (fd < 0) + return -errno; + + return fd; +} + +int fmkostemp_safe(char *pattern, const char *mode, FILE **ret_f) { + int fd; + FILE *f; + + fd = mkostemp_safe(pattern); + if (fd < 0) + return fd; + + f = fdopen(fd, mode); + if (!f) { + safe_close(fd); + return -errno; + } + + *ret_f = f; + return 0; +} + +int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { + const char *fn; + char *t; + + assert(ret); + + if (isempty(p)) + return -EINVAL; + if (path_equal(p, "/")) + return -EINVAL; + + /* + * Turns this: + * /foo/bar/waldo + * + * Into this: + * /foo/bar/.#waldoXXXXXX + */ + + fn = basename(p); + if (!filename_is_valid(fn)) + return -EINVAL; + + extra = strempty(extra); + + t = new(char, strlen(p) + 2 + strlen(extra) + 6 + 1); + if (!t) + return -ENOMEM; + + strcpy(stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn), "XXXXXX"); + + *ret = path_simplify(t, false); + return 0; +} + +int tempfn_random(const char *p, const char *extra, char **ret) { + const char *fn; + char *t, *x; + uint64_t u; + unsigned i; + + assert(ret); + + if (isempty(p)) + return -EINVAL; + if (path_equal(p, "/")) + return -EINVAL; + + /* + * Turns this: + * /foo/bar/waldo + * + * Into this: + * /foo/bar/.#waldobaa2a261115984a9 + */ + + fn = basename(p); + if (!filename_is_valid(fn)) + return -EINVAL; + + extra = strempty(extra); + + t = new(char, strlen(p) + 2 + strlen(extra) + 16 + 1); + if (!t) + return -ENOMEM; + + x = stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), extra), fn); + + u = random_u64(); + for (i = 0; i < 16; i++) { + *(x++) = hexchar(u & 0xF); + u >>= 4; + } + + *x = 0; + + *ret = path_simplify(t, false); + return 0; +} + +int tempfn_random_child(const char *p, const char *extra, char **ret) { + char *t, *x; + uint64_t u; + unsigned i; + int r; + + assert(ret); + + /* Turns this: + * /foo/bar/waldo + * Into this: + * /foo/bar/waldo/.#3c2b6219aa75d7d0 + */ + + if (!p) { + r = tmp_dir(&p); + if (r < 0) + return r; + } + + extra = strempty(extra); + + t = new(char, strlen(p) + 3 + strlen(extra) + 16 + 1); + if (!t) + return -ENOMEM; + + if (isempty(p)) + x = stpcpy(stpcpy(t, ".#"), extra); + else + x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra); + + u = random_u64(); + for (i = 0; i < 16; i++) { + *(x++) = hexchar(u & 0xF); + u >>= 4; + } + + *x = 0; + + *ret = path_simplify(t, false); + return 0; +} + +int open_tmpfile_unlinkable(const char *directory, int flags) { + char *p; + int fd, r; + + if (!directory) { + r = tmp_dir(&directory); + if (r < 0) + return r; + } else if (isempty(directory)) + return -EINVAL; + + /* Returns an unlinked temporary file that cannot be linked into the file system anymore */ + + /* Try O_TMPFILE first, if it is supported */ + fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR); + if (fd >= 0) + return fd; + + /* Fall back to unguessable name + unlinking */ + p = strjoina(directory, "/systemd-tmp-XXXXXX"); + + fd = mkostemp_safe(p); + if (fd < 0) + return fd; + + (void) unlink(p); + + return fd; +} + +int open_tmpfile_linkable(const char *target, int flags, char **ret_path) { + _cleanup_free_ char *tmp = NULL; + int r, fd; + + assert(target); + assert(ret_path); + + /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */ + assert((flags & O_EXCL) == 0); + + /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in + * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in + * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */ + + fd = open_parent(target, O_TMPFILE|flags, 0640); + if (fd >= 0) { + *ret_path = NULL; + return fd; + } + + log_debug_errno(fd, "Failed to use O_TMPFILE for %s: %m", target); + + r = tempfn_random(target, NULL, &tmp); + if (r < 0) + return r; + + fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640); + if (fd < 0) + return -errno; + + *ret_path = TAKE_PTR(tmp); + + return fd; +} + +int link_tmpfile(int fd, const char *path, const char *target) { + int r; + + assert(fd >= 0); + assert(target); + + /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd + * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported + * on the directory, and renameat2() is used instead. + * + * Note that in both cases we will not replace existing files. This is because linkat() does not support this + * operation currently (renameat2() does), and there is no nice way to emulate this. */ + + if (path) { + r = rename_noreplace(AT_FDCWD, path, AT_FDCWD, target); + if (r < 0) + return r; + } else { + char proc_fd_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; + + xsprintf(proc_fd_path, "/proc/self/fd/%i", fd); + + if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0) + return -errno; + } + + return 0; +} + +int mkdtemp_malloc(const char *template, char **ret) { + _cleanup_free_ char *p = NULL; + int r; + + assert(ret); + + if (template) + p = strdup(template); + else { + const char *tmp; + + r = tmp_dir(&tmp); + if (r < 0) + return r; + + p = path_join(tmp, "XXXXXX"); + } + if (!p) + return -ENOMEM; + + if (!mkdtemp(p)) + return -errno; + + *ret = TAKE_PTR(p); + return 0; +} diff --git a/src/basic/tmpfile-util.h b/src/basic/tmpfile-util.h new file mode 100644 index 00000000..802c85d6 --- /dev/null +++ b/src/basic/tmpfile-util.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int fopen_temporary(const char *path, FILE **_f, char **_temp_path); +int mkostemp_safe(char *pattern); +int fmkostemp_safe(char *pattern, const char *mode, FILE**_f); + +int tempfn_xxxxxx(const char *p, const char *extra, char **ret); +int tempfn_random(const char *p, const char *extra, char **ret); +int tempfn_random_child(const char *p, const char *extra, char **ret); + +int open_tmpfile_unlinkable(const char *directory, int flags); +int open_tmpfile_linkable(const char *target, int flags, char **ret_path); + +int link_tmpfile(int fd, const char *path, const char *target); + +int mkdtemp_malloc(const char *template, char **ret); diff --git a/src/basic/umask-util.h b/src/basic/umask-util.h new file mode 100644 index 00000000..cad74517 --- /dev/null +++ b/src/basic/umask-util.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "macro.h" + +static inline void umaskp(mode_t *u) { + umask(*u & 0777); +} + +#define _cleanup_umask_ _cleanup_(umaskp) + +/* We make use of the fact here that the umask() concept is using only the lower 9 bits of mode_t, although + * mode_t has space for the file type in the bits further up. We simply OR in the file type mask S_IFMT to + * distinguish the first and the second iteration of the RUN_WITH_UMASK() loop, so that we can run the first + * one, and exit on the second. */ + +assert_cc((S_IFMT & 0777) == 0); + +#define RUN_WITH_UMASK(mask) \ + for (_cleanup_umask_ mode_t _saved_umask_ = umask(mask) | S_IFMT; \ + FLAGS_SET(_saved_umask_, S_IFMT); \ + _saved_umask_ &= 0777) diff --git a/src/basic/unaligned.h b/src/basic/unaligned.h new file mode 100644 index 00000000..00c17f87 --- /dev/null +++ b/src/basic/unaligned.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +/* BE */ + +static inline uint16_t unaligned_read_be16(const void *_u) { + const struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u; + + return be16toh(u->x); +} + +static inline uint32_t unaligned_read_be32(const void *_u) { + const struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u; + + return be32toh(u->x); +} + +static inline uint64_t unaligned_read_be64(const void *_u) { + const struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u; + + return be64toh(u->x); +} + +static inline void unaligned_write_be16(void *_u, uint16_t a) { + struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u; + + u->x = be16toh(a); +} + +static inline void unaligned_write_be32(void *_u, uint32_t a) { + struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u; + + u->x = be32toh(a); +} + +static inline void unaligned_write_be64(void *_u, uint64_t a) { + struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u; + + u->x = be64toh(a); +} + +/* LE */ + +static inline uint16_t unaligned_read_le16(const void *_u) { + const struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u; + + return le16toh(u->x); +} + +static inline uint32_t unaligned_read_le32(const void *_u) { + const struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u; + + return le32toh(u->x); +} + +static inline uint64_t unaligned_read_le64(const void *_u) { + const struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u; + + return le64toh(u->x); +} + +static inline void unaligned_write_le16(void *_u, uint16_t a) { + struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u; + + u->x = le16toh(a); +} + +static inline void unaligned_write_le32(void *_u, uint32_t a) { + struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u; + + u->x = le32toh(a); +} + +static inline void unaligned_write_le64(void *_u, uint64_t a) { + struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u; + + u->x = le64toh(a); +} + +#if __BYTE_ORDER == __BIG_ENDIAN +#define unaligned_read_ne16 unaligned_read_be16 +#define unaligned_read_ne32 unaligned_read_be32 +#define unaligned_read_ne64 unaligned_read_be64 + +#define unaligned_write_ne16 unaligned_write_be16 +#define unaligned_write_ne32 unaligned_write_be32 +#define unaligned_write_ne64 unaligned_write_be64 +#else +#define unaligned_read_ne16 unaligned_read_le16 +#define unaligned_read_ne32 unaligned_read_le32 +#define unaligned_read_ne64 unaligned_read_le64 + +#define unaligned_write_ne16 unaligned_write_le16 +#define unaligned_write_ne32 unaligned_write_le32 +#define unaligned_write_ne64 unaligned_write_le64 +#endif diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c new file mode 100644 index 00000000..dba218b3 --- /dev/null +++ b/src/basic/unit-def.c @@ -0,0 +1,279 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-label.h" +#include "string-table.h" +#include "unit-def.h" +#include "unit-name.h" + +char *unit_dbus_path_from_name(const char *name) { + _cleanup_free_ char *e = NULL; + + assert(name); + + e = bus_label_escape(name); + if (!e) + return NULL; + + return strjoin("/org/freedesktop/systemd1/unit/", e); +} + +int unit_name_from_dbus_path(const char *path, char **name) { + const char *e; + char *n; + + e = startswith(path, "/org/freedesktop/systemd1/unit/"); + if (!e) + return -EINVAL; + + n = bus_label_unescape(e); + if (!n) + return -ENOMEM; + + *name = n; + return 0; +} + +const char* unit_dbus_interface_from_type(UnitType t) { + + static const char *const table[_UNIT_TYPE_MAX] = { + [UNIT_SERVICE] = "org.freedesktop.systemd1.Service", + [UNIT_SOCKET] = "org.freedesktop.systemd1.Socket", + [UNIT_TARGET] = "org.freedesktop.systemd1.Target", + [UNIT_DEVICE] = "org.freedesktop.systemd1.Device", + [UNIT_MOUNT] = "org.freedesktop.systemd1.Mount", + [UNIT_AUTOMOUNT] = "org.freedesktop.systemd1.Automount", + [UNIT_SWAP] = "org.freedesktop.systemd1.Swap", + [UNIT_TIMER] = "org.freedesktop.systemd1.Timer", + [UNIT_PATH] = "org.freedesktop.systemd1.Path", + [UNIT_SLICE] = "org.freedesktop.systemd1.Slice", + [UNIT_SCOPE] = "org.freedesktop.systemd1.Scope", + }; + + if (t < 0) + return NULL; + if (t >= _UNIT_TYPE_MAX) + return NULL; + + return table[t]; +} + +const char *unit_dbus_interface_from_name(const char *name) { + UnitType t; + + t = unit_name_to_type(name); + if (t < 0) + return NULL; + + return unit_dbus_interface_from_type(t); +} + +static const char* const unit_type_table[_UNIT_TYPE_MAX] = { + [UNIT_SERVICE] = "service", + [UNIT_SOCKET] = "socket", + [UNIT_TARGET] = "target", + [UNIT_DEVICE] = "device", + [UNIT_MOUNT] = "mount", + [UNIT_AUTOMOUNT] = "automount", + [UNIT_SWAP] = "swap", + [UNIT_TIMER] = "timer", + [UNIT_PATH] = "path", + [UNIT_SLICE] = "slice", + [UNIT_SCOPE] = "scope", +}; + +DEFINE_STRING_TABLE_LOOKUP(unit_type, UnitType); + +static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = { + [UNIT_STUB] = "stub", + [UNIT_LOADED] = "loaded", + [UNIT_NOT_FOUND] = "not-found", + [UNIT_BAD_SETTING] = "bad-setting", + [UNIT_ERROR] = "error", + [UNIT_MERGED] = "merged", + [UNIT_MASKED] = "masked" +}; + +DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState); + +static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = { + [UNIT_ACTIVE] = "active", + [UNIT_RELOADING] = "reloading", + [UNIT_INACTIVE] = "inactive", + [UNIT_FAILED] = "failed", + [UNIT_ACTIVATING] = "activating", + [UNIT_DEACTIVATING] = "deactivating", + [UNIT_MAINTENANCE] = "maintenance", +}; + +DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState); + +static const char* const automount_state_table[_AUTOMOUNT_STATE_MAX] = { + [AUTOMOUNT_DEAD] = "dead", + [AUTOMOUNT_WAITING] = "waiting", + [AUTOMOUNT_RUNNING] = "running", + [AUTOMOUNT_FAILED] = "failed" +}; + +DEFINE_STRING_TABLE_LOOKUP(automount_state, AutomountState); + +static const char* const device_state_table[_DEVICE_STATE_MAX] = { + [DEVICE_DEAD] = "dead", + [DEVICE_TENTATIVE] = "tentative", + [DEVICE_PLUGGED] = "plugged", +}; + +DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState); + +static const char* const mount_state_table[_MOUNT_STATE_MAX] = { + [MOUNT_DEAD] = "dead", + [MOUNT_MOUNTING] = "mounting", + [MOUNT_MOUNTING_DONE] = "mounting-done", + [MOUNT_MOUNTED] = "mounted", + [MOUNT_REMOUNTING] = "remounting", + [MOUNT_UNMOUNTING] = "unmounting", + [MOUNT_REMOUNTING_SIGTERM] = "remounting-sigterm", + [MOUNT_REMOUNTING_SIGKILL] = "remounting-sigkill", + [MOUNT_UNMOUNTING_SIGTERM] = "unmounting-sigterm", + [MOUNT_UNMOUNTING_SIGKILL] = "unmounting-sigkill", + [MOUNT_FAILED] = "failed", + [MOUNT_CLEANING] = "cleaning", +}; + +DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState); + +static const char* const path_state_table[_PATH_STATE_MAX] = { + [PATH_DEAD] = "dead", + [PATH_WAITING] = "waiting", + [PATH_RUNNING] = "running", + [PATH_FAILED] = "failed" +}; + +DEFINE_STRING_TABLE_LOOKUP(path_state, PathState); + +static const char* const scope_state_table[_SCOPE_STATE_MAX] = { + [SCOPE_DEAD] = "dead", + [SCOPE_RUNNING] = "running", + [SCOPE_ABANDONED] = "abandoned", + [SCOPE_STOP_SIGTERM] = "stop-sigterm", + [SCOPE_STOP_SIGKILL] = "stop-sigkill", + [SCOPE_FAILED] = "failed", +}; + +DEFINE_STRING_TABLE_LOOKUP(scope_state, ScopeState); + +static const char* const service_state_table[_SERVICE_STATE_MAX] = { + [SERVICE_DEAD] = "dead", + [SERVICE_CONDITION] = "condition", + [SERVICE_START_PRE] = "start-pre", + [SERVICE_START] = "start", + [SERVICE_START_POST] = "start-post", + [SERVICE_RUNNING] = "running", + [SERVICE_EXITED] = "exited", + [SERVICE_RELOAD] = "reload", + [SERVICE_STOP] = "stop", + [SERVICE_STOP_WATCHDOG] = "stop-watchdog", + [SERVICE_STOP_SIGTERM] = "stop-sigterm", + [SERVICE_STOP_SIGKILL] = "stop-sigkill", + [SERVICE_STOP_POST] = "stop-post", + [SERVICE_FINAL_SIGTERM] = "final-sigterm", + [SERVICE_FINAL_SIGKILL] = "final-sigkill", + [SERVICE_FAILED] = "failed", + [SERVICE_AUTO_RESTART] = "auto-restart", + [SERVICE_CLEANING] = "cleaning", +}; + +DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState); + +static const char* const slice_state_table[_SLICE_STATE_MAX] = { + [SLICE_DEAD] = "dead", + [SLICE_ACTIVE] = "active" +}; + +DEFINE_STRING_TABLE_LOOKUP(slice_state, SliceState); + +static const char* const socket_state_table[_SOCKET_STATE_MAX] = { + [SOCKET_DEAD] = "dead", + [SOCKET_START_PRE] = "start-pre", + [SOCKET_START_CHOWN] = "start-chown", + [SOCKET_START_POST] = "start-post", + [SOCKET_LISTENING] = "listening", + [SOCKET_RUNNING] = "running", + [SOCKET_STOP_PRE] = "stop-pre", + [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm", + [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill", + [SOCKET_STOP_POST] = "stop-post", + [SOCKET_FINAL_SIGTERM] = "final-sigterm", + [SOCKET_FINAL_SIGKILL] = "final-sigkill", + [SOCKET_FAILED] = "failed", + [SOCKET_CLEANING] = "cleaning", +}; + +DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState); + +static const char* const swap_state_table[_SWAP_STATE_MAX] = { + [SWAP_DEAD] = "dead", + [SWAP_ACTIVATING] = "activating", + [SWAP_ACTIVATING_DONE] = "activating-done", + [SWAP_ACTIVE] = "active", + [SWAP_DEACTIVATING] = "deactivating", + [SWAP_DEACTIVATING_SIGTERM] = "deactivating-sigterm", + [SWAP_DEACTIVATING_SIGKILL] = "deactivating-sigkill", + [SWAP_FAILED] = "failed", + [SWAP_CLEANING] = "cleaning", +}; + +DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState); + +static const char* const target_state_table[_TARGET_STATE_MAX] = { + [TARGET_DEAD] = "dead", + [TARGET_ACTIVE] = "active" +}; + +DEFINE_STRING_TABLE_LOOKUP(target_state, TargetState); + +static const char* const timer_state_table[_TIMER_STATE_MAX] = { + [TIMER_DEAD] = "dead", + [TIMER_WAITING] = "waiting", + [TIMER_RUNNING] = "running", + [TIMER_ELAPSED] = "elapsed", + [TIMER_FAILED] = "failed" +}; + +DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState); + +static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = { + [UNIT_REQUIRES] = "Requires", + [UNIT_REQUISITE] = "Requisite", + [UNIT_WANTS] = "Wants", + [UNIT_BINDS_TO] = "BindsTo", + [UNIT_PART_OF] = "PartOf", + [UNIT_REQUIRED_BY] = "RequiredBy", + [UNIT_REQUISITE_OF] = "RequisiteOf", + [UNIT_WANTED_BY] = "WantedBy", + [UNIT_BOUND_BY] = "BoundBy", + [UNIT_CONSISTS_OF] = "ConsistsOf", + [UNIT_CONFLICTS] = "Conflicts", + [UNIT_CONFLICTED_BY] = "ConflictedBy", + [UNIT_BEFORE] = "Before", + [UNIT_AFTER] = "After", + [UNIT_ON_FAILURE] = "OnFailure", + [UNIT_TRIGGERS] = "Triggers", + [UNIT_TRIGGERED_BY] = "TriggeredBy", + [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo", + [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom", + [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf", + [UNIT_REFERENCES] = "References", + [UNIT_REFERENCED_BY] = "ReferencedBy", +}; + +DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency); + +static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = { + [NOTIFY_NONE] = "none", + [NOTIFY_MAIN] = "main", + [NOTIFY_EXEC] = "exec", + [NOTIFY_ALL] = "all" +}; + +DEFINE_STRING_TABLE_LOOKUP(notify_access, NotifyAccess); diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h new file mode 100644 index 00000000..5979819d --- /dev/null +++ b/src/basic/unit-def.h @@ -0,0 +1,293 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +/* The enum order is used to order unit jobs in the job queue + * when other criteria (cpu weight, nice level) are identical. + * In this case service units have the hightest priority. */ +typedef enum UnitType { + UNIT_SERVICE = 0, + UNIT_MOUNT, + UNIT_SWAP, + UNIT_SOCKET, + UNIT_TARGET, + UNIT_DEVICE, + UNIT_AUTOMOUNT, + UNIT_TIMER, + UNIT_PATH, + UNIT_SLICE, + UNIT_SCOPE, + _UNIT_TYPE_MAX, + _UNIT_TYPE_INVALID = -1 +} UnitType; + +typedef enum UnitLoadState { + UNIT_STUB = 0, + UNIT_LOADED, + UNIT_NOT_FOUND, /* error condition #1: unit file not found */ + UNIT_BAD_SETTING, /* error condition #2: we couldn't parse some essential unit file setting */ + UNIT_ERROR, /* error condition #3: other "system" error, catchall for the rest */ + UNIT_MERGED, + UNIT_MASKED, + _UNIT_LOAD_STATE_MAX, + _UNIT_LOAD_STATE_INVALID = -1 +} UnitLoadState; + +typedef enum UnitActiveState { + UNIT_ACTIVE, + UNIT_RELOADING, + UNIT_INACTIVE, + UNIT_FAILED, + UNIT_ACTIVATING, + UNIT_DEACTIVATING, + UNIT_MAINTENANCE, + _UNIT_ACTIVE_STATE_MAX, + _UNIT_ACTIVE_STATE_INVALID = -1 +} UnitActiveState; + +typedef enum AutomountState { + AUTOMOUNT_DEAD, + AUTOMOUNT_WAITING, + AUTOMOUNT_RUNNING, + AUTOMOUNT_FAILED, + _AUTOMOUNT_STATE_MAX, + _AUTOMOUNT_STATE_INVALID = -1 +} AutomountState; + +/* We simply watch devices, we cannot plug/unplug them. That + * simplifies the state engine greatly */ +typedef enum DeviceState { + DEVICE_DEAD, + DEVICE_TENTATIVE, /* mounted or swapped, but not (yet) announced by udev */ + DEVICE_PLUGGED, /* announced by udev */ + _DEVICE_STATE_MAX, + _DEVICE_STATE_INVALID = -1 +} DeviceState; + +typedef enum MountState { + MOUNT_DEAD, + MOUNT_MOUNTING, /* /usr/bin/mount is running, but the mount is not done yet. */ + MOUNT_MOUNTING_DONE, /* /usr/bin/mount is running, and the mount is done. */ + MOUNT_MOUNTED, + MOUNT_REMOUNTING, + MOUNT_UNMOUNTING, + MOUNT_REMOUNTING_SIGTERM, + MOUNT_REMOUNTING_SIGKILL, + MOUNT_UNMOUNTING_SIGTERM, + MOUNT_UNMOUNTING_SIGKILL, + MOUNT_FAILED, + MOUNT_CLEANING, + _MOUNT_STATE_MAX, + _MOUNT_STATE_INVALID = -1 +} MountState; + +typedef enum PathState { + PATH_DEAD, + PATH_WAITING, + PATH_RUNNING, + PATH_FAILED, + _PATH_STATE_MAX, + _PATH_STATE_INVALID = -1 +} PathState; + +typedef enum ScopeState { + SCOPE_DEAD, + SCOPE_RUNNING, + SCOPE_ABANDONED, + SCOPE_STOP_SIGTERM, + SCOPE_STOP_SIGKILL, + SCOPE_FAILED, + _SCOPE_STATE_MAX, + _SCOPE_STATE_INVALID = -1 +} ScopeState; + +typedef enum ServiceState { + SERVICE_DEAD, + SERVICE_CONDITION, + SERVICE_START_PRE, + SERVICE_START, + SERVICE_START_POST, + SERVICE_RUNNING, + SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */ + SERVICE_RELOAD, + SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */ + SERVICE_STOP_WATCHDOG, + SERVICE_STOP_SIGTERM, + SERVICE_STOP_SIGKILL, + SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, /* In case the STOP_POST executable hangs, we shoot that down, too */ + SERVICE_FINAL_SIGKILL, + SERVICE_FAILED, + SERVICE_AUTO_RESTART, + SERVICE_CLEANING, + _SERVICE_STATE_MAX, + _SERVICE_STATE_INVALID = -1 +} ServiceState; + +typedef enum SliceState { + SLICE_DEAD, + SLICE_ACTIVE, + _SLICE_STATE_MAX, + _SLICE_STATE_INVALID = -1 +} SliceState; + +typedef enum SocketState { + SOCKET_DEAD, + SOCKET_START_PRE, + SOCKET_START_CHOWN, + SOCKET_START_POST, + SOCKET_LISTENING, + SOCKET_RUNNING, + SOCKET_STOP_PRE, + SOCKET_STOP_PRE_SIGTERM, + SOCKET_STOP_PRE_SIGKILL, + SOCKET_STOP_POST, + SOCKET_FINAL_SIGTERM, + SOCKET_FINAL_SIGKILL, + SOCKET_FAILED, + SOCKET_CLEANING, + _SOCKET_STATE_MAX, + _SOCKET_STATE_INVALID = -1 +} SocketState; + +typedef enum SwapState { + SWAP_DEAD, + SWAP_ACTIVATING, /* /sbin/swapon is running, but the swap not yet enabled. */ + SWAP_ACTIVATING_DONE, /* /sbin/swapon is running, and the swap is done. */ + SWAP_ACTIVE, + SWAP_DEACTIVATING, + SWAP_DEACTIVATING_SIGTERM, + SWAP_DEACTIVATING_SIGKILL, + SWAP_FAILED, + SWAP_CLEANING, + _SWAP_STATE_MAX, + _SWAP_STATE_INVALID = -1 +} SwapState; + +typedef enum TargetState { + TARGET_DEAD, + TARGET_ACTIVE, + _TARGET_STATE_MAX, + _TARGET_STATE_INVALID = -1 +} TargetState; + +typedef enum TimerState { + TIMER_DEAD, + TIMER_WAITING, + TIMER_RUNNING, + TIMER_ELAPSED, + TIMER_FAILED, + _TIMER_STATE_MAX, + _TIMER_STATE_INVALID = -1 +} TimerState; + +typedef enum UnitDependency { + /* Positive dependencies */ + UNIT_REQUIRES, + UNIT_REQUISITE, + UNIT_WANTS, + UNIT_BINDS_TO, + UNIT_PART_OF, + + /* Inverse of the above */ + UNIT_REQUIRED_BY, /* inverse of 'requires' is 'required_by' */ + UNIT_REQUISITE_OF, /* inverse of 'requisite' is 'requisite_of' */ + UNIT_WANTED_BY, /* inverse of 'wants' */ + UNIT_BOUND_BY, /* inverse of 'binds_to' */ + UNIT_CONSISTS_OF, /* inverse of 'part_of' */ + + /* Negative dependencies */ + UNIT_CONFLICTS, /* inverse of 'conflicts' is 'conflicted_by' */ + UNIT_CONFLICTED_BY, + + /* Order */ + UNIT_BEFORE, /* inverse of 'before' is 'after' and vice versa */ + UNIT_AFTER, + + /* On Failure */ + UNIT_ON_FAILURE, + + /* Triggers (i.e. a socket triggers a service) */ + UNIT_TRIGGERS, + UNIT_TRIGGERED_BY, + + /* Propagate reloads */ + UNIT_PROPAGATES_RELOAD_TO, + UNIT_RELOAD_PROPAGATED_FROM, + + /* Joins namespace of */ + UNIT_JOINS_NAMESPACE_OF, + + /* Reference information for GC logic */ + UNIT_REFERENCES, /* Inverse of 'references' is 'referenced_by' */ + UNIT_REFERENCED_BY, + + _UNIT_DEPENDENCY_MAX, + _UNIT_DEPENDENCY_INVALID = -1 +} UnitDependency; + +typedef enum NotifyAccess { + NOTIFY_NONE, + NOTIFY_ALL, + NOTIFY_MAIN, + NOTIFY_EXEC, + _NOTIFY_ACCESS_MAX, + _NOTIFY_ACCESS_INVALID = -1 +} NotifyAccess; + +char *unit_dbus_path_from_name(const char *name); +int unit_name_from_dbus_path(const char *path, char **name); + +const char* unit_dbus_interface_from_type(UnitType t); +const char *unit_dbus_interface_from_name(const char *name); + +const char *unit_type_to_string(UnitType i) _const_; +UnitType unit_type_from_string(const char *s) _pure_; + +const char *unit_load_state_to_string(UnitLoadState i) _const_; +UnitLoadState unit_load_state_from_string(const char *s) _pure_; + +const char *unit_active_state_to_string(UnitActiveState i) _const_; +UnitActiveState unit_active_state_from_string(const char *s) _pure_; + +const char* automount_state_to_string(AutomountState i) _const_; +AutomountState automount_state_from_string(const char *s) _pure_; + +const char* device_state_to_string(DeviceState i) _const_; +DeviceState device_state_from_string(const char *s) _pure_; + +const char* mount_state_to_string(MountState i) _const_; +MountState mount_state_from_string(const char *s) _pure_; + +const char* path_state_to_string(PathState i) _const_; +PathState path_state_from_string(const char *s) _pure_; + +const char* scope_state_to_string(ScopeState i) _const_; +ScopeState scope_state_from_string(const char *s) _pure_; + +const char* service_state_to_string(ServiceState i) _const_; +ServiceState service_state_from_string(const char *s) _pure_; + +const char* slice_state_to_string(SliceState i) _const_; +SliceState slice_state_from_string(const char *s) _pure_; + +const char* socket_state_to_string(SocketState i) _const_; +SocketState socket_state_from_string(const char *s) _pure_; + +const char* swap_state_to_string(SwapState i) _const_; +SwapState swap_state_from_string(const char *s) _pure_; + +const char* target_state_to_string(TargetState i) _const_; +TargetState target_state_from_string(const char *s) _pure_; + +const char *timer_state_to_string(TimerState i) _const_; +TimerState timer_state_from_string(const char *s) _pure_; + +const char *unit_dependency_to_string(UnitDependency i) _const_; +UnitDependency unit_dependency_from_string(const char *s) _pure_; + +const char* notify_access_to_string(NotifyAccess i) _const_; +NotifyAccess notify_access_from_string(const char *s) _pure_; diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c new file mode 100644 index 00000000..680e8eb4 --- /dev/null +++ b/src/basic/unit-name.c @@ -0,0 +1,773 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "glob-util.h" +#include "hexdecoct.h" +#include "path-util.h" +#include "special.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" + +/* Characters valid in a unit name. */ +#define VALID_CHARS \ + DIGITS \ + LETTERS \ + ":-_.\\" + +/* The same, but also permits the single @ character that may appear */ +#define VALID_CHARS_WITH_AT \ + "@" \ + VALID_CHARS + +/* All chars valid in a unit name glob */ +#define VALID_CHARS_GLOB \ + VALID_CHARS_WITH_AT \ + "[]!-*?" + +bool unit_name_is_valid(const char *n, UnitNameFlags flags) { + const char *e, *i, *at; + + assert((flags & ~(UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) == 0); + + if (_unlikely_(flags == 0)) + return false; + + if (isempty(n)) + return false; + + if (strlen(n) >= UNIT_NAME_MAX) + return false; + + e = strrchr(n, '.'); + if (!e || e == n) + return false; + + if (unit_type_from_string(e + 1) < 0) + return false; + + for (i = n, at = NULL; i < e; i++) { + + if (*i == '@' && !at) + at = i; + + if (!strchr("@" VALID_CHARS, *i)) + return false; + } + + if (at == n) + return false; + + if (flags & UNIT_NAME_PLAIN) + if (!at) + return true; + + if (flags & UNIT_NAME_INSTANCE) + if (at && e > at + 1) + return true; + + if (flags & UNIT_NAME_TEMPLATE) + if (at && e == at + 1) + return true; + + return false; +} + +bool unit_prefix_is_valid(const char *p) { + + /* We don't allow additional @ in the prefix string */ + + if (isempty(p)) + return false; + + return in_charset(p, VALID_CHARS); +} + +bool unit_instance_is_valid(const char *i) { + + /* The max length depends on the length of the string, so we + * don't really check this here. */ + + if (isempty(i)) + return false; + + /* We allow additional @ in the instance string, we do not + * allow them in the prefix! */ + + return in_charset(i, "@" VALID_CHARS); +} + +bool unit_suffix_is_valid(const char *s) { + if (isempty(s)) + return false; + + if (s[0] != '.') + return false; + + if (unit_type_from_string(s + 1) < 0) + return false; + + return true; +} + +int unit_name_to_prefix(const char *n, char **ret) { + const char *p; + char *s; + + assert(n); + assert(ret); + + if (!unit_name_is_valid(n, UNIT_NAME_ANY)) + return -EINVAL; + + p = strchr(n, '@'); + if (!p) + p = strrchr(n, '.'); + + assert_se(p); + + s = strndup(n, p - n); + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +int unit_name_to_instance(const char *n, char **ret) { + const char *p, *d; + + assert(n); + + if (!unit_name_is_valid(n, UNIT_NAME_ANY)) + return -EINVAL; + + /* Everything past the first @ and before the last . is the instance */ + p = strchr(n, '@'); + if (!p) { + if (ret) + *ret = NULL; + return UNIT_NAME_PLAIN; + } + + p++; + + d = strrchr(p, '.'); + if (!d) + return -EINVAL; + + if (ret) { + char *i = strndup(p, d-p); + if (!i) + return -ENOMEM; + + *ret = i; + } + return d > p ? UNIT_NAME_INSTANCE : UNIT_NAME_TEMPLATE; +} + +int unit_name_to_prefix_and_instance(const char *n, char **ret) { + const char *d; + char *s; + + assert(n); + assert(ret); + + if (!unit_name_is_valid(n, UNIT_NAME_ANY)) + return -EINVAL; + + d = strrchr(n, '.'); + if (!d) + return -EINVAL; + + s = strndup(n, d - n); + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +UnitType unit_name_to_type(const char *n) { + const char *e; + + assert(n); + + if (!unit_name_is_valid(n, UNIT_NAME_ANY)) + return _UNIT_TYPE_INVALID; + + assert_se(e = strrchr(n, '.')); + + return unit_type_from_string(e + 1); +} + +int unit_name_change_suffix(const char *n, const char *suffix, char **ret) { + char *e, *s; + size_t a, b; + + assert(n); + assert(suffix); + assert(ret); + + if (!unit_name_is_valid(n, UNIT_NAME_ANY)) + return -EINVAL; + + if (!unit_suffix_is_valid(suffix)) + return -EINVAL; + + assert_se(e = strrchr(n, '.')); + + a = e - n; + b = strlen(suffix); + + s = new(char, a + b + 1); + if (!s) + return -ENOMEM; + + strcpy(mempcpy(s, n, a), suffix); + *ret = s; + + return 0; +} + +int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret) { + UnitType type; + + assert(prefix); + assert(suffix); + assert(ret); + + if (suffix[0] != '.') + return -EINVAL; + + type = unit_type_from_string(suffix + 1); + if (type < 0) + return -EINVAL; + + return unit_name_build_from_type(prefix, instance, type, ret); +} + +int unit_name_build_from_type(const char *prefix, const char *instance, UnitType type, char **ret) { + const char *ut; + char *s; + + assert(prefix); + assert(type >= 0); + assert(type < _UNIT_TYPE_MAX); + assert(ret); + + if (!unit_prefix_is_valid(prefix)) + return -EINVAL; + + if (instance && !unit_instance_is_valid(instance)) + return -EINVAL; + + ut = unit_type_to_string(type); + + if (!instance) + s = strjoin(prefix, ".", ut); + else + s = strjoin(prefix, "@", instance, ".", ut); + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +static char *do_escape_char(char c, char *t) { + assert(t); + + *(t++) = '\\'; + *(t++) = 'x'; + *(t++) = hexchar(c >> 4); + *(t++) = hexchar(c); + + return t; +} + +static char *do_escape(const char *f, char *t) { + assert(f); + assert(t); + + /* do not create units with a leading '.', like for "/.dotdir" mount points */ + if (*f == '.') { + t = do_escape_char(*f, t); + f++; + } + + for (; *f; f++) { + if (*f == '/') + *(t++) = '-'; + else if (IN_SET(*f, '-', '\\') || !strchr(VALID_CHARS, *f)) + t = do_escape_char(*f, t); + else + *(t++) = *f; + } + + return t; +} + +char *unit_name_escape(const char *f) { + char *r, *t; + + assert(f); + + r = new(char, strlen(f)*4+1); + if (!r) + return NULL; + + t = do_escape(f, r); + *t = 0; + + return r; +} + +int unit_name_unescape(const char *f, char **ret) { + _cleanup_free_ char *r = NULL; + char *t; + + assert(f); + + r = strdup(f); + if (!r) + return -ENOMEM; + + for (t = r; *f; f++) { + if (*f == '-') + *(t++) = '/'; + else if (*f == '\\') { + int a, b; + + if (f[1] != 'x') + return -EINVAL; + + a = unhexchar(f[2]); + if (a < 0) + return -EINVAL; + + b = unhexchar(f[3]); + if (b < 0) + return -EINVAL; + + *(t++) = (char) (((uint8_t) a << 4U) | (uint8_t) b); + f += 3; + } else + *(t++) = *f; + } + + *t = 0; + + *ret = TAKE_PTR(r); + + return 0; +} + +int unit_name_path_escape(const char *f, char **ret) { + char *p, *s; + + assert(f); + assert(ret); + + p = strdupa(f); + if (!p) + return -ENOMEM; + + path_simplify(p, false); + + if (empty_or_root(p)) + s = strdup("-"); + else { + if (!path_is_normalized(p)) + return -EINVAL; + + /* Truncate trailing slashes */ + delete_trailing_chars(p, "/"); + + /* Truncate leading slashes */ + p = skip_leading_chars(p, "/"); + + s = unit_name_escape(p); + } + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +int unit_name_path_unescape(const char *f, char **ret) { + _cleanup_free_ char *s = NULL; + int r; + + assert(f); + + if (isempty(f)) + return -EINVAL; + + if (streq(f, "-")) { + s = strdup("/"); + if (!s) + return -ENOMEM; + } else { + _cleanup_free_ char *w = NULL; + + r = unit_name_unescape(f, &w); + if (r < 0) + return r; + + /* Don't accept trailing or leading slashes */ + if (startswith(w, "/") || endswith(w, "/")) + return -EINVAL; + + /* Prefix a slash again */ + s = strjoin("/", w); + if (!s) + return -ENOMEM; + + if (!path_is_normalized(s)) + return -EINVAL; + } + + if (ret) + *ret = TAKE_PTR(s); + + return 0; +} + +int unit_name_replace_instance(const char *f, const char *i, char **ret) { + const char *p, *e; + char *s; + size_t a, b; + + assert(f); + assert(i); + assert(ret); + + if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) + return -EINVAL; + if (!unit_instance_is_valid(i)) + return -EINVAL; + + assert_se(p = strchr(f, '@')); + assert_se(e = strrchr(f, '.')); + + a = p - f; + b = strlen(i); + + s = new(char, a + 1 + b + strlen(e) + 1); + if (!s) + return -ENOMEM; + + strcpy(mempcpy(mempcpy(s, f, a + 1), i, b), e); + + *ret = s; + return 0; +} + +int unit_name_template(const char *f, char **ret) { + const char *p, *e; + char *s; + size_t a; + + assert(f); + assert(ret); + + if (!unit_name_is_valid(f, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) + return -EINVAL; + + assert_se(p = strchr(f, '@')); + assert_se(e = strrchr(f, '.')); + + a = p - f; + + s = new(char, a + 1 + strlen(e) + 1); + if (!s) + return -ENOMEM; + + strcpy(mempcpy(s, f, a + 1), e); + + *ret = s; + return 0; +} + +int unit_name_from_path(const char *path, const char *suffix, char **ret) { + _cleanup_free_ char *p = NULL; + char *s = NULL; + int r; + + assert(path); + assert(suffix); + assert(ret); + + if (!unit_suffix_is_valid(suffix)) + return -EINVAL; + + r = unit_name_path_escape(path, &p); + if (r < 0) + return r; + + s = strjoin(p, suffix); + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret) { + _cleanup_free_ char *p = NULL; + char *s; + int r; + + assert(prefix); + assert(path); + assert(suffix); + assert(ret); + + if (!unit_prefix_is_valid(prefix)) + return -EINVAL; + + if (!unit_suffix_is_valid(suffix)) + return -EINVAL; + + r = unit_name_path_escape(path, &p); + if (r < 0) + return r; + + s = strjoin(prefix, "@", p, suffix); + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +int unit_name_to_path(const char *name, char **ret) { + _cleanup_free_ char *prefix = NULL; + int r; + + assert(name); + + r = unit_name_to_prefix(name, &prefix); + if (r < 0) + return r; + + return unit_name_path_unescape(prefix, ret); +} + +static bool do_escape_mangle(const char *f, bool allow_globs, char *t) { + const char *valid_chars; + bool mangled = false; + + assert(f); + assert(t); + + /* We'll only escape the obvious characters here, to play safe. + * + * Returns true if any characters were mangled, false otherwise. + */ + + valid_chars = allow_globs ? VALID_CHARS_GLOB : VALID_CHARS_WITH_AT; + + for (; *f; f++) + if (*f == '/') { + *(t++) = '-'; + mangled = true; + } else if (!strchr(valid_chars, *f)) { + t = do_escape_char(*f, t); + mangled = true; + } else + *(t++) = *f; + *t = 0; + + return mangled; +} + +/** + * Convert a string to a unit name. /dev/blah is converted to dev-blah.device, + * /blah/blah is converted to blah-blah.mount, anything else is left alone, + * except that @suffix is appended if a valid unit suffix is not present. + * + * If @allow_globs, globs characters are preserved. Otherwise, they are escaped. + */ +int unit_name_mangle_with_suffix(const char *name, const char *operation, UnitNameMangle flags, const char *suffix, char **ret) { + char *s; + int r; + bool mangled, suggest_escape = true; + + assert(name); + assert(suffix); + assert(ret); + + if (isempty(name)) /* We cannot mangle empty unit names to become valid, sorry. */ + return -EINVAL; + + if (!unit_suffix_is_valid(suffix)) + return -EINVAL; + + /* Already a fully valid unit name? If so, no mangling is necessary... */ + if (unit_name_is_valid(name, UNIT_NAME_ANY)) + goto good; + + /* Already a fully valid globbing expression? If so, no mangling is necessary either... */ + if (string_is_glob(name) && in_charset(name, VALID_CHARS_GLOB)) { + if (flags & UNIT_NAME_MANGLE_GLOB) + goto good; + log_full(flags & UNIT_NAME_MANGLE_WARN ? LOG_NOTICE : LOG_DEBUG, + "Glob pattern passed%s%s, but globs are not supported for this.", + operation ? " " : "", operation ?: ""); + suggest_escape = false; + } + + if (is_device_path(name)) { + r = unit_name_from_path(name, ".device", ret); + if (r >= 0) + return 1; + if (r != -EINVAL) + return r; + } + + if (path_is_absolute(name)) { + r = unit_name_from_path(name, ".mount", ret); + if (r >= 0) + return 1; + if (r != -EINVAL) + return r; + } + + s = new(char, strlen(name) * 4 + strlen(suffix) + 1); + if (!s) + return -ENOMEM; + + mangled = do_escape_mangle(name, flags & UNIT_NAME_MANGLE_GLOB, s); + if (mangled) + log_full(flags & UNIT_NAME_MANGLE_WARN ? LOG_NOTICE : LOG_DEBUG, + "Invalid unit name \"%s\" escaped as \"%s\"%s.", + name, s, + suggest_escape ? " (maybe you should use systemd-escape?)" : ""); + + /* Append a suffix if it doesn't have any, but only if this is not a glob, so that we can allow + * "foo.*" as a valid glob. */ + if ((!(flags & UNIT_NAME_MANGLE_GLOB) || !string_is_glob(s)) && unit_name_to_type(s) < 0) + strcat(s, suffix); + + *ret = s; + return 1; + +good: + s = strdup(name); + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +int slice_build_parent_slice(const char *slice, char **ret) { + char *s, *dash; + int r; + + assert(slice); + assert(ret); + + if (!slice_name_is_valid(slice)) + return -EINVAL; + + if (streq(slice, SPECIAL_ROOT_SLICE)) { + *ret = NULL; + return 0; + } + + s = strdup(slice); + if (!s) + return -ENOMEM; + + dash = strrchr(s, '-'); + if (dash) + strcpy(dash, ".slice"); + else { + r = free_and_strdup(&s, SPECIAL_ROOT_SLICE); + if (r < 0) { + free(s); + return r; + } + } + + *ret = s; + return 1; +} + +int slice_build_subslice(const char *slice, const char *name, char **ret) { + char *subslice; + + assert(slice); + assert(name); + assert(ret); + + if (!slice_name_is_valid(slice)) + return -EINVAL; + + if (!unit_prefix_is_valid(name)) + return -EINVAL; + + if (streq(slice, SPECIAL_ROOT_SLICE)) + subslice = strjoin(name, ".slice"); + else { + char *e; + + assert_se(e = endswith(slice, ".slice")); + + subslice = new(char, (e - slice) + 1 + strlen(name) + 6 + 1); + if (!subslice) + return -ENOMEM; + + stpcpy(stpcpy(stpcpy(mempcpy(subslice, slice, e - slice), "-"), name), ".slice"); + } + + *ret = subslice; + return 0; +} + +bool slice_name_is_valid(const char *name) { + const char *p, *e; + bool dash = false; + + if (!unit_name_is_valid(name, UNIT_NAME_PLAIN)) + return false; + + if (streq(name, SPECIAL_ROOT_SLICE)) + return true; + + e = endswith(name, ".slice"); + if (!e) + return false; + + for (p = name; p < e; p++) { + + if (*p == '-') { + + /* Don't allow initial dash */ + if (p == name) + return false; + + /* Don't allow multiple dashes */ + if (dash) + return false; + + dash = true; + } else + dash = false; + } + + /* Don't allow trailing hash */ + if (dash) + return false; + + return true; +} diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h new file mode 100644 index 00000000..15ce4e24 --- /dev/null +++ b/src/basic/unit-name.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" +#include "unit-def.h" + +#define UNIT_NAME_MAX 256 + +typedef enum UnitNameFlags { + UNIT_NAME_PLAIN = 1 << 0, /* Allow foo.service */ + UNIT_NAME_TEMPLATE = 1 << 1, /* Allow foo@.service */ + UNIT_NAME_INSTANCE = 1 << 2, /* Allow foo@bar.service */ + UNIT_NAME_ANY = UNIT_NAME_PLAIN|UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE, +} UnitNameFlags; + +bool unit_name_is_valid(const char *n, UnitNameFlags flags) _pure_; +bool unit_prefix_is_valid(const char *p) _pure_; +bool unit_instance_is_valid(const char *i) _pure_; +bool unit_suffix_is_valid(const char *s) _pure_; + +int unit_name_to_prefix(const char *n, char **ret); +int unit_name_to_instance(const char *n, char **ret); +static inline int unit_name_classify(const char *n) { + return unit_name_to_instance(n, NULL); +} +int unit_name_to_prefix_and_instance(const char *n, char **ret); + +UnitType unit_name_to_type(const char *n) _pure_; + +int unit_name_change_suffix(const char *n, const char *suffix, char **ret); + +int unit_name_build(const char *prefix, const char *instance, const char *suffix, char **ret); +int unit_name_build_from_type(const char *prefix, const char *instance, UnitType, char **ret); + +char *unit_name_escape(const char *f); +int unit_name_unescape(const char *f, char **ret); +int unit_name_path_escape(const char *f, char **ret); +int unit_name_path_unescape(const char *f, char **ret); + +int unit_name_replace_instance(const char *f, const char *i, char **ret); + +int unit_name_template(const char *f, char **ret); + +int unit_name_from_path(const char *path, const char *suffix, char **ret); +int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret); +int unit_name_to_path(const char *name, char **ret); + +typedef enum UnitNameMangle { + UNIT_NAME_MANGLE_GLOB = 1 << 0, + UNIT_NAME_MANGLE_WARN = 1 << 1, +} UnitNameMangle; + +int unit_name_mangle_with_suffix(const char *name, const char *operation, UnitNameMangle flags, const char *suffix, char **ret); + +static inline int unit_name_mangle(const char *name, UnitNameMangle flags, char **ret) { + return unit_name_mangle_with_suffix(name, NULL, flags, ".service", ret); +} + +int slice_build_parent_slice(const char *slice, char **ret); +int slice_build_subslice(const char *slice, const char *name, char **subslice); +bool slice_name_is_valid(const char *name); diff --git a/src/basic/user-util.c b/src/basic/user-util.c new file mode 100644 index 00000000..93ba4eed --- /dev/null +++ b/src/basic/user-util.c @@ -0,0 +1,942 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "macro.h" +#include "parse-util.h" +#include "path-util.h" +#include "random-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "utf8.h" + +bool uid_is_valid(uid_t uid) { + + /* Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, 3.436. */ + + /* Some libc APIs use UID_INVALID as special placeholder */ + if (uid == (uid_t) UINT32_C(0xFFFFFFFF)) + return false; + + /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */ + if (uid == (uid_t) UINT32_C(0xFFFF)) + return false; + + return true; +} + +int parse_uid(const char *s, uid_t *ret) { + uint32_t uid = 0; + int r; + + assert(s); + + assert_cc(sizeof(uid_t) == sizeof(uint32_t)); + r = safe_atou32(s, &uid); + if (r < 0) + return r; + + if (!uid_is_valid(uid)) + return -ENXIO; /* we return ENXIO instead of EINVAL + * here, to make it easy to distinguish + * invalid numeric uids from invalid + * strings. */ + + if (ret) + *ret = uid; + + return 0; +} + +char* getlogname_malloc(void) { + uid_t uid; + struct stat st; + + if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0) + uid = st.st_uid; + else + uid = getuid(); + + return uid_to_name(uid); +} + +char *getusername_malloc(void) { + const char *e; + + e = secure_getenv("USER"); + if (e) + return strdup(e); + + return uid_to_name(getuid()); +} + +static bool is_nologin_shell(const char *shell) { + + return PATH_IN_SET(shell, + /* 'nologin' is the friendliest way to disable logins for a user account. It prints a nice + * message and exits. Different distributions place the binary at different places though, + * hence let's list them all. */ + "/bin/nologin", + "/sbin/nologin", + "/usr/bin/nologin", + "/usr/sbin/nologin", + /* 'true' and 'false' work too for the same purpose, but are less friendly as they don't do + * any message printing. Different distributions place the binary at various places but at + * least not in the 'sbin' directory. */ + "/bin/false", + "/usr/bin/false", + "/bin/true", + "/usr/bin/true"); +} + +static int synthesize_user_creds( + const char **username, + uid_t *uid, gid_t *gid, + const char **home, + const char **shell, + UserCredsFlags flags) { + + /* We enforce some special rules for uid=0 and uid=65534: in order to avoid NSS lookups for root we hardcode + * their user record data. */ + + if (STR_IN_SET(*username, "root", "0")) { + *username = "root"; + + if (uid) + *uid = 0; + if (gid) + *gid = 0; + + if (home) + *home = "/root"; + + if (shell) + *shell = "/bin/sh"; + + return 0; + } + + if (synthesize_nobody() && + STR_IN_SET(*username, NOBODY_USER_NAME, "65534")) { + *username = NOBODY_USER_NAME; + + if (uid) + *uid = UID_NOBODY; + if (gid) + *gid = GID_NOBODY; + + if (home) + *home = FLAGS_SET(flags, USER_CREDS_CLEAN) ? NULL : "/"; + + if (shell) + *shell = FLAGS_SET(flags, USER_CREDS_CLEAN) ? NULL : NOLOGIN; + + return 0; + } + + return -ENOMEDIUM; +} + +int get_user_creds( + const char **username, + uid_t *uid, gid_t *gid, + const char **home, + const char **shell, + UserCredsFlags flags) { + + uid_t u = UID_INVALID; + struct passwd *p; + int r; + + assert(username); + assert(*username); + + if (!FLAGS_SET(flags, USER_CREDS_PREFER_NSS) || + (!home && !shell)) { + + /* So here's the deal: normally, we'll try to synthesize all records we can synthesize, and override + * the user database with that. However, if the user specifies USER_CREDS_PREFER_NSS then the + * user database will override the synthetic records instead — except if the user is only interested in + * the UID and/or GID (but not the home directory, or the shell), in which case we'll always override + * the user database (i.e. the USER_CREDS_PREFER_NSS flag has no effect in this case). Why? + * Simply because there are valid usecase where the user might change the home directory or the shell + * of the relevant users, but changing the UID/GID mappings for them is something we explicitly don't + * support. */ + + r = synthesize_user_creds(username, uid, gid, home, shell, flags); + if (r >= 0) + return 0; + if (r != -ENOMEDIUM) /* not a username we can synthesize */ + return r; + } + + if (parse_uid(*username, &u) >= 0) { + errno = 0; + p = getpwuid(u); + + /* If there are multiple users with the same id, make sure to leave $USER to the configured value + * instead of the first occurrence in the database. However if the uid was configured by a numeric uid, + * then let's pick the real username from /etc/passwd. */ + if (p) + *username = p->pw_name; + else if (FLAGS_SET(flags, USER_CREDS_ALLOW_MISSING) && !gid && !home && !shell) { + + /* If the specified user is a numeric UID and it isn't in the user database, and the caller + * passed USER_CREDS_ALLOW_MISSING and was only interested in the UID, then juts return that + * and don't complain. */ + + if (uid) + *uid = u; + + return 0; + } + } else { + errno = 0; + p = getpwnam(*username); + } + if (!p) { + r = errno_or_else(ESRCH); + + /* If the user requested that we only synthesize as fallback, do so now */ + if (FLAGS_SET(flags, USER_CREDS_PREFER_NSS)) { + if (synthesize_user_creds(username, uid, gid, home, shell, flags) >= 0) + return 0; + } + + return r; + } + + if (uid) { + if (!uid_is_valid(p->pw_uid)) + return -EBADMSG; + + *uid = p->pw_uid; + } + + if (gid) { + if (!gid_is_valid(p->pw_gid)) + return -EBADMSG; + + *gid = p->pw_gid; + } + + if (home) { + if (FLAGS_SET(flags, USER_CREDS_CLEAN) && + (empty_or_root(p->pw_dir) || + !path_is_valid(p->pw_dir) || + !path_is_absolute(p->pw_dir))) + *home = NULL; /* Note: we don't insist on normalized paths, since there are setups that have /./ in the path */ + else + *home = p->pw_dir; + } + + if (shell) { + if (FLAGS_SET(flags, USER_CREDS_CLEAN) && + (isempty(p->pw_shell) || + !path_is_valid(p->pw_dir) || + !path_is_absolute(p->pw_shell) || + is_nologin_shell(p->pw_shell))) + *shell = NULL; + else + *shell = p->pw_shell; + } + + return 0; +} + +int get_group_creds(const char **groupname, gid_t *gid, UserCredsFlags flags) { + struct group *g; + gid_t id; + + assert(groupname); + + /* We enforce some special rules for gid=0: in order to avoid NSS lookups for root we hardcode its data. */ + + if (STR_IN_SET(*groupname, "root", "0")) { + *groupname = "root"; + + if (gid) + *gid = 0; + + return 0; + } + + if (synthesize_nobody() && + STR_IN_SET(*groupname, NOBODY_GROUP_NAME, "65534")) { + *groupname = NOBODY_GROUP_NAME; + + if (gid) + *gid = GID_NOBODY; + + return 0; + } + + if (parse_gid(*groupname, &id) >= 0) { + errno = 0; + g = getgrgid(id); + + if (g) + *groupname = g->gr_name; + else if (FLAGS_SET(flags, USER_CREDS_ALLOW_MISSING)) { + if (gid) + *gid = id; + + return 0; + } + } else { + errno = 0; + g = getgrnam(*groupname); + } + + if (!g) + return errno_or_else(ESRCH); + + if (gid) { + if (!gid_is_valid(g->gr_gid)) + return -EBADMSG; + + *gid = g->gr_gid; + } + + return 0; +} + +char* uid_to_name(uid_t uid) { + char *ret; + int r; + + /* Shortcut things to avoid NSS lookups */ + if (uid == 0) + return strdup("root"); + if (synthesize_nobody() && + uid == UID_NOBODY) + return strdup(NOBODY_USER_NAME); + + if (uid_is_valid(uid)) { + long bufsize; + + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize <= 0) + bufsize = 4096; + + for (;;) { + struct passwd pwbuf, *pw = NULL; + _cleanup_free_ char *buf = NULL; + + buf = malloc(bufsize); + if (!buf) + return NULL; + + r = getpwuid_r(uid, &pwbuf, buf, (size_t) bufsize, &pw); + if (r == 0 && pw) + return strdup(pw->pw_name); + if (r != ERANGE) + break; + + if (bufsize > LONG_MAX/2) /* overflow check */ + return NULL; + + bufsize *= 2; + } + } + + if (asprintf(&ret, UID_FMT, uid) < 0) + return NULL; + + return ret; +} + +char* gid_to_name(gid_t gid) { + char *ret; + int r; + + if (gid == 0) + return strdup("root"); + if (synthesize_nobody() && + gid == GID_NOBODY) + return strdup(NOBODY_GROUP_NAME); + + if (gid_is_valid(gid)) { + long bufsize; + + bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); + if (bufsize <= 0) + bufsize = 4096; + + for (;;) { + struct group grbuf, *gr = NULL; + _cleanup_free_ char *buf = NULL; + + buf = malloc(bufsize); + if (!buf) + return NULL; + + r = getgrgid_r(gid, &grbuf, buf, (size_t) bufsize, &gr); + if (r == 0 && gr) + return strdup(gr->gr_name); + if (r != ERANGE) + break; + + if (bufsize > LONG_MAX/2) /* overflow check */ + return NULL; + + bufsize *= 2; + } + } + + if (asprintf(&ret, GID_FMT, gid) < 0) + return NULL; + + return ret; +} + +int in_gid(gid_t gid) { + _cleanup_free_ gid_t *allocated = NULL; + gid_t local[16], *p = local; + int ngroups = ELEMENTSOF(local); + unsigned attempt = 0; + + if (getgid() == gid) + return 1; + + if (getegid() == gid) + return 1; + + if (!gid_is_valid(gid)) + return -EINVAL; + + for (;;) { + ngroups = getgroups(ngroups, p); + if (ngroups >= 0) + break; + if (errno != EINVAL) + return -errno; + + /* Give up eventually */ + if (attempt++ > 10) + return -EINVAL; + + /* Get actual size needed, and size the array explicitly. Note that this is potentially racy + * to use (in multi-threaded programs), hence let's call this in a loop. */ + ngroups = getgroups(0, NULL); + if (ngroups < 0) + return -errno; + if (ngroups == 0) + return false; + + free(allocated); + + allocated = new(gid_t, ngroups); + if (!allocated) + return -ENOMEM; + + p = allocated; + } + + for (int i = 0; i < ngroups; i++) + if (p[i] == gid) + return true; + + return false; +} + +int in_group(const char *name) { + int r; + gid_t gid; + + r = get_group_creds(&name, &gid, 0); + if (r < 0) + return r; + + return in_gid(gid); +} + +int get_home_dir(char **_h) { + struct passwd *p; + const char *e; + char *h; + uid_t u; + + assert(_h); + + /* Take the user specified one */ + e = secure_getenv("HOME"); + if (e && path_is_valid(e) && path_is_absolute(e)) { + h = strdup(e); + if (!h) + return -ENOMEM; + + *_h = path_simplify(h, true); + return 0; + } + + /* Hardcode home directory for root and nobody to avoid NSS */ + u = getuid(); + if (u == 0) { + h = strdup("/root"); + if (!h) + return -ENOMEM; + + *_h = h; + return 0; + } + if (synthesize_nobody() && + u == UID_NOBODY) { + h = strdup("/"); + if (!h) + return -ENOMEM; + + *_h = h; + return 0; + } + + /* Check the database... */ + errno = 0; + p = getpwuid(u); + if (!p) + return errno_or_else(ESRCH); + + if (!path_is_valid(p->pw_dir) || + !path_is_absolute(p->pw_dir)) + return -EINVAL; + + h = strdup(p->pw_dir); + if (!h) + return -ENOMEM; + + *_h = path_simplify(h, true); + return 0; +} + +int get_shell(char **_s) { + struct passwd *p; + const char *e; + char *s; + uid_t u; + + assert(_s); + + /* Take the user specified one */ + e = secure_getenv("SHELL"); + if (e && path_is_valid(e) && path_is_absolute(e)) { + s = strdup(e); + if (!s) + return -ENOMEM; + + *_s = path_simplify(s, true); + return 0; + } + + /* Hardcode shell for root and nobody to avoid NSS */ + u = getuid(); + if (u == 0) { + s = strdup("/bin/sh"); + if (!s) + return -ENOMEM; + + *_s = s; + return 0; + } + if (synthesize_nobody() && + u == UID_NOBODY) { + s = strdup(NOLOGIN); + if (!s) + return -ENOMEM; + + *_s = s; + return 0; + } + + /* Check the database... */ + errno = 0; + p = getpwuid(u); + if (!p) + return errno_or_else(ESRCH); + + if (!path_is_valid(p->pw_shell) || + !path_is_absolute(p->pw_shell)) + return -EINVAL; + + s = strdup(p->pw_shell); + if (!s) + return -ENOMEM; + + *_s = path_simplify(s, true); + return 0; +} + +int reset_uid_gid(void) { + int r; + + r = maybe_setgroups(0, NULL); + if (r < 0) + return r; + + if (setresgid(0, 0, 0) < 0) + return -errno; + + if (setresuid(0, 0, 0) < 0) + return -errno; + + return 0; +} + +int take_etc_passwd_lock(const char *root) { + + struct flock flock = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, + }; + + const char *path; + int fd, r; + + /* This is roughly the same as lckpwdf(), but not as awful. We + * don't want to use alarm() and signals, hence we implement + * our own trivial version of this. + * + * Note that shadow-utils also takes per-database locks in + * addition to lckpwdf(). However, we don't given that they + * are redundant as they invoke lckpwdf() first and keep + * it during everything they do. The per-database locks are + * awfully racy, and thus we just won't do them. */ + + if (root) + path = prefix_roota(root, ETC_PASSWD_LOCK_PATH); + else + path = ETC_PASSWD_LOCK_PATH; + + fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600); + if (fd < 0) + return log_debug_errno(errno, "Cannot open %s: %m", path); + + r = fcntl(fd, F_SETLKW, &flock); + if (r < 0) { + safe_close(fd); + return log_debug_errno(errno, "Locking %s failed: %m", path); + } + + return fd; +} + +bool valid_user_group_name_full(const char *u, bool strict) { + const char *i; + long sz; + + /* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, + * 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules: + * + * - We require that names fit into the appropriate utmp field + * - We don't allow empty user names + * - No dots or digits in the first character + * + * If strict==true, additionally: + * - We don't allow any dots (this conflicts with chown syntax which permits dots as user/group name separator) + * + * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters. + */ + + if (isempty(u)) + return false; + + if (!(u[0] >= 'a' && u[0] <= 'z') && + !(u[0] >= 'A' && u[0] <= 'Z') && + u[0] != '_') + return false; + + bool warned = false; + + for (i = u+1; *i; i++) { + if (((*i >= 'a' && *i <= 'z') || + (*i >= 'A' && *i <= 'Z') || + (*i >= '0' && *i <= '9') || + IN_SET(*i, '_', '-'))) + continue; + + if (*i == '.' && !strict) { + if (!warned) { + log_warning("Bad user or group name \"%s\", accepting for compatibility.", u); + warned = true; + } + + continue; + } + + return false; + } + + sz = sysconf(_SC_LOGIN_NAME_MAX); + assert_se(sz > 0); + + if ((size_t) (i-u) > (size_t) sz) + return false; + + if ((size_t) (i-u) > UT_NAMESIZE - 1) + return false; + + return true; +} + +bool valid_user_group_name_or_id_full(const char *u, bool strict) { + + /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the + * right range, and not the invalid user ids. */ + + if (isempty(u)) + return false; + + if (valid_user_group_name_full(u, strict)) + return true; + + return parse_uid(u, NULL) >= 0; +} + +bool valid_gecos(const char *d) { + + if (!d) + return false; + + if (!utf8_is_valid(d)) + return false; + + if (string_has_cc(d, NULL)) + return false; + + /* Colons are used as field separators, and hence not OK */ + if (strchr(d, ':')) + return false; + + return true; +} + +bool valid_home(const char *p) { + /* Note that this function is also called by valid_shell(), any + * changes must account for that. */ + + if (isempty(p)) + return false; + + if (!utf8_is_valid(p)) + return false; + + if (string_has_cc(p, NULL)) + return false; + + if (!path_is_absolute(p)) + return false; + + if (!path_is_normalized(p)) + return false; + + /* Colons are used as field separators, and hence not OK */ + if (strchr(p, ':')) + return false; + + return true; +} + +int maybe_setgroups(size_t size, const gid_t *list) { + int r; + + /* Check if setgroups is allowed before we try to drop all the auxiliary groups */ + if (size == 0) { /* Dropping all aux groups? */ + _cleanup_free_ char *setgroups_content = NULL; + bool can_setgroups; + + r = read_one_line_file("/proc/self/setgroups", &setgroups_content); + if (r == -ENOENT) + /* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */ + can_setgroups = true; + else if (r < 0) + return r; + else + can_setgroups = streq(setgroups_content, "allow"); + + if (!can_setgroups) { + log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'"); + return 0; + } + } + + if (setgroups(size, list) < 0) + return -errno; + + return 0; +} + +bool synthesize_nobody(void) { + /* Returns true when we shall synthesize the "nobody" user (which we do by default). This can be turned off by + * touching /etc/systemd/dont-synthesize-nobody in order to provide upgrade compatibility with legacy systems + * that used the "nobody" user name and group name for other UIDs/GIDs than 65534. + * + * Note that we do not employ any kind of synchronization on the following caching variable. If the variable is + * accessed in multi-threaded programs in the worst case it might happen that we initialize twice, but that + * shouldn't matter as each initialization should come to the same result. */ + static int cache = -1; + + if (cache < 0) + cache = access("/etc/systemd/dont-synthesize-nobody", F_OK) < 0; + + return cache; +} + +int putpwent_sane(const struct passwd *pw, FILE *stream) { + assert(pw); + assert(stream); + + errno = 0; + if (putpwent(pw, stream) != 0) + return errno_or_else(EIO); + + return 0; +} + +int putspent_sane(const struct spwd *sp, FILE *stream) { + assert(sp); + assert(stream); + + errno = 0; + if (putspent(sp, stream) != 0) + return errno_or_else(EIO); + + return 0; +} + +int putgrent_sane(const struct group *gr, FILE *stream) { + assert(gr); + assert(stream); + + errno = 0; + if (putgrent(gr, stream) != 0) + return errno_or_else(EIO); + + return 0; +} + +#if ENABLE_GSHADOW +int putsgent_sane(const struct sgrp *sg, FILE *stream) { + assert(sg); + assert(stream); + + errno = 0; + if (putsgent(sg, stream) != 0) + return errno_or_else(EIO); + + return 0; +} +#endif + +int fgetpwent_sane(FILE *stream, struct passwd **pw) { + struct passwd *p; + + assert(pw); + assert(stream); + + errno = 0; + p = fgetpwent(stream); + if (!p && errno != ENOENT) + return errno_or_else(EIO); + + *pw = p; + return !!p; +} + +int fgetspent_sane(FILE *stream, struct spwd **sp) { + struct spwd *s; + + assert(sp); + assert(stream); + + errno = 0; + s = fgetspent(stream); + if (!s && errno != ENOENT) + return errno_or_else(EIO); + + *sp = s; + return !!s; +} + +int fgetgrent_sane(FILE *stream, struct group **gr) { + struct group *g; + + assert(gr); + assert(stream); + + errno = 0; + g = fgetgrent(stream); + if (!g && errno != ENOENT) + return errno_or_else(EIO); + + *gr = g; + return !!g; +} + +#if ENABLE_GSHADOW +int fgetsgent_sane(FILE *stream, struct sgrp **sg) { + struct sgrp *s; + + assert(sg); + assert(stream); + + errno = 0; + s = fgetsgent(stream); + if (!s && errno != ENOENT) + return errno_or_else(EIO); + + *sg = s; + return !!s; +} +#endif + +int make_salt(char **ret) { + static const char table[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "./"; + + uint8_t raw[16]; + char *salt, *j; + size_t i; + int r; + + /* This is a bit like crypt_gensalt_ra(), but doesn't require libcrypt, and doesn't do anything but + * SHA512, i.e. is legacy-free and minimizes our deps. */ + + assert_cc(sizeof(table) == 64U + 1U); + + /* Insist on the best randomness by setting RANDOM_BLOCK, this is about keeping passwords secret after all. */ + r = genuine_random_bytes(raw, sizeof(raw), RANDOM_BLOCK); + if (r < 0) + return r; + + salt = new(char, 3+sizeof(raw)+1+1); + if (!salt) + return -ENOMEM; + + /* We only bother with SHA512 hashed passwords, the rest is legacy, and we don't do legacy. */ + j = stpcpy(salt, "$6$"); + for (i = 0; i < sizeof(raw); i++) + j[i] = table[raw[i] & 63]; + j[i++] = '$'; + j[i] = 0; + + *ret = salt; + return 0; +} diff --git a/src/basic/user-util.h b/src/basic/user-util.h new file mode 100644 index 00000000..cfa515f5 --- /dev/null +++ b/src/basic/user-util.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#if ENABLE_GSHADOW +#include +#endif +#include +#include +#include +#include +#include +#include + +bool uid_is_valid(uid_t uid); + +static inline bool gid_is_valid(gid_t gid) { + return uid_is_valid((uid_t) gid); +} + +int parse_uid(const char *s, uid_t* ret_uid); + +static inline int parse_gid(const char *s, gid_t *ret_gid) { + return parse_uid(s, (uid_t*) ret_gid); +} + +char* getlogname_malloc(void); +char* getusername_malloc(void); + +typedef enum UserCredsFlags { + USER_CREDS_PREFER_NSS = 1 << 0, /* if set, only synthesize user records if database lacks them. Normally we bypass the userdb entirely for the records we can synthesize */ + USER_CREDS_ALLOW_MISSING = 1 << 1, /* if a numeric UID string is resolved, be OK if there's no record for it */ + USER_CREDS_CLEAN = 1 << 2, /* try to clean up shell and home fields with invalid data */ +} UserCredsFlags; + +int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell, UserCredsFlags flags); +int get_group_creds(const char **groupname, gid_t *gid, UserCredsFlags flags); + +char* uid_to_name(uid_t uid); +char* gid_to_name(gid_t gid); + +int in_gid(gid_t gid); +int in_group(const char *name); + +int get_home_dir(char **ret); +int get_shell(char **_ret); + +int reset_uid_gid(void); + +int take_etc_passwd_lock(const char *root); + +#define UID_INVALID ((uid_t) -1) +#define GID_INVALID ((gid_t) -1) + +#define UID_NOBODY ((uid_t) 65534U) +#define GID_NOBODY ((gid_t) 65534U) + +#define ETC_PASSWD_LOCK_PATH "/etc/.pwd.lock" + +static inline bool uid_is_dynamic(uid_t uid) { + return DYNAMIC_UID_MIN <= uid && uid <= DYNAMIC_UID_MAX; +} + +static inline bool gid_is_dynamic(gid_t gid) { + return uid_is_dynamic((uid_t) gid); +} + +static inline bool uid_is_system(uid_t uid) { + return uid <= SYSTEM_UID_MAX; +} + +static inline bool gid_is_system(gid_t gid) { + return gid <= SYSTEM_GID_MAX; +} + +/* The following macros add 1 when converting things, since UID 0 is a valid UID, while the pointer + * NULL is special */ +#define PTR_TO_UID(p) ((uid_t) (((uintptr_t) (p))-1)) +#define UID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1)) + +#define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1)) +#define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1)) + +static inline bool userns_supported(void) { + return access("/proc/self/uid_map", F_OK) >= 0; +} + +bool valid_user_group_name_full(const char *u, bool strict); +bool valid_user_group_name_or_id_full(const char *u, bool strict); +static inline bool valid_user_group_name(const char *u) { + return valid_user_group_name_full(u, true); +} +static inline bool valid_user_group_name_or_id(const char *u) { + return valid_user_group_name_or_id_full(u, true); +} +static inline bool valid_user_group_name_compat(const char *u) { + return valid_user_group_name_full(u, false); +} +static inline bool valid_user_group_name_or_id_compat(const char *u) { + return valid_user_group_name_or_id_full(u, false); +} +bool valid_gecos(const char *d); +bool valid_home(const char *p); + +static inline bool valid_shell(const char *p) { + /* We have the same requirements, so just piggy-back on the home check. + * + * Let's ignore /etc/shells because this is only applicable to real and + * not system users. It is also incompatible with the idea of empty /etc. + */ + return valid_home(p); +} + +int maybe_setgroups(size_t size, const gid_t *list); + +bool synthesize_nobody(void); + +int fgetpwent_sane(FILE *stream, struct passwd **pw); +int fgetspent_sane(FILE *stream, struct spwd **sp); +int fgetgrent_sane(FILE *stream, struct group **gr); +int putpwent_sane(const struct passwd *pw, FILE *stream); +int putspent_sane(const struct spwd *sp, FILE *stream); +int putgrent_sane(const struct group *gr, FILE *stream); +#if ENABLE_GSHADOW +int fgetsgent_sane(FILE *stream, struct sgrp **sg); +int putsgent_sane(const struct sgrp *sg, FILE *stream); +#endif + +int make_salt(char **ret); diff --git a/src/basic/utf8.c b/src/basic/utf8.c new file mode 100644 index 00000000..c857185e --- /dev/null +++ b/src/basic/utf8.c @@ -0,0 +1,581 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +/* Parts of this file are based on the GLIB utf8 validation functions. The + * original license text follows. */ + +/* gutf8.c - Operations on UTF-8 strings. + * + * Copyright (C) 1999 Tom Tromey + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "alloc-util.h" +#include "gunicode.h" +#include "hexdecoct.h" +#include "macro.h" +#include "string-util.h" +#include "utf8.h" + +bool unichar_is_valid(char32_t ch) { + + if (ch >= 0x110000) /* End of unicode space */ + return false; + if ((ch & 0xFFFFF800) == 0xD800) /* Reserved area for UTF-16 */ + return false; + if ((ch >= 0xFDD0) && (ch <= 0xFDEF)) /* Reserved */ + return false; + if ((ch & 0xFFFE) == 0xFFFE) /* BOM (Byte Order Mark) */ + return false; + + return true; +} + +static bool unichar_is_control(char32_t ch) { + + /* + 0 to ' '-1 is the C0 range. + DEL=0x7F, and DEL+1 to 0x9F is C1 range. + '\t' is in C0 range, but more or less harmless and commonly used. + */ + + return (ch < ' ' && !IN_SET(ch, '\t', '\n')) || + (0x7F <= ch && ch <= 0x9F); +} + +/* count of characters used to encode one unicode char */ +static size_t utf8_encoded_expected_len(uint8_t c) { + if (c < 0x80) + return 1; + if ((c & 0xe0) == 0xc0) + return 2; + if ((c & 0xf0) == 0xe0) + return 3; + if ((c & 0xf8) == 0xf0) + return 4; + if ((c & 0xfc) == 0xf8) + return 5; + if ((c & 0xfe) == 0xfc) + return 6; + + return 0; +} + +/* decode one unicode char */ +int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) { + char32_t unichar; + size_t len, i; + + assert(str); + + len = utf8_encoded_expected_len(str[0]); + + switch (len) { + case 1: + *ret_unichar = (char32_t)str[0]; + return 0; + case 2: + unichar = str[0] & 0x1f; + break; + case 3: + unichar = (char32_t)str[0] & 0x0f; + break; + case 4: + unichar = (char32_t)str[0] & 0x07; + break; + case 5: + unichar = (char32_t)str[0] & 0x03; + break; + case 6: + unichar = (char32_t)str[0] & 0x01; + break; + default: + return -EINVAL; + } + + for (i = 1; i < len; i++) { + if (((char32_t)str[i] & 0xc0) != 0x80) + return -EINVAL; + + unichar <<= 6; + unichar |= (char32_t)str[i] & 0x3f; + } + + *ret_unichar = unichar; + + return 0; +} + +bool utf8_is_printable_newline(const char* str, size_t length, bool newline) { + const char *p; + + assert(str); + + for (p = str; length > 0;) { + int encoded_len, r; + char32_t val; + + encoded_len = utf8_encoded_valid_unichar(p, length); + if (encoded_len < 0) + return false; + assert(encoded_len > 0 && (size_t) encoded_len <= length); + + r = utf8_encoded_to_unichar(p, &val); + if (r < 0 || + unichar_is_control(val) || + (!newline && val == '\n')) + return false; + + length -= encoded_len; + p += encoded_len; + } + + return true; +} + +char *utf8_is_valid(const char *str) { + const char *p; + + assert(str); + + p = str; + while (*p) { + int len; + + len = utf8_encoded_valid_unichar(p, (size_t) -1); + if (len < 0) + return NULL; + + p += len; + } + + return (char*) str; +} + +char *utf8_escape_invalid(const char *str) { + char *p, *s; + + assert(str); + + p = s = malloc(strlen(str) * 4 + 1); + if (!p) + return NULL; + + while (*str) { + int len; + + len = utf8_encoded_valid_unichar(str, (size_t) -1); + if (len > 0) { + s = mempcpy(s, str, len); + str += len; + } else { + s = stpcpy(s, UTF8_REPLACEMENT_CHARACTER); + str += 1; + } + } + + *s = '\0'; + (void) str_realloc(&p); + return p; +} + +static int utf8_char_console_width(const char *str) { + char32_t c; + int r; + + r = utf8_encoded_to_unichar(str, &c); + if (r < 0) + return r; + + /* TODO: we should detect combining characters */ + + return unichar_iswide(c) ? 2 : 1; +} + +char *utf8_escape_non_printable_full(const char *str, size_t console_width) { + char *p, *s, *prev_s; + size_t n = 0; /* estimated print width */ + + assert(str); + + if (console_width == 0) + return strdup(""); + + p = s = prev_s = malloc(strlen(str) * 4 + 1); + if (!p) + return NULL; + + for (;;) { + int len; + char *saved_s = s; + + if (!*str) /* done! */ + goto finish; + + len = utf8_encoded_valid_unichar(str, (size_t) -1); + if (len > 0) { + if (utf8_is_printable(str, len)) { + int w; + + w = utf8_char_console_width(str); + assert(w >= 0); + if (n + w > console_width) + goto truncation; + + s = mempcpy(s, str, len); + str += len; + n += w; + + } else { + for (; len > 0; len--) { + if (n + 4 > console_width) + goto truncation; + + *(s++) = '\\'; + *(s++) = 'x'; + *(s++) = hexchar((int) *str >> 4); + *(s++) = hexchar((int) *str); + + str += 1; + n += 4; + } + } + } else { + if (n + 1 > console_width) + goto truncation; + + s = mempcpy(s, UTF8_REPLACEMENT_CHARACTER, strlen(UTF8_REPLACEMENT_CHARACTER)); + str += 1; + n += 1; + } + + prev_s = saved_s; + } + + truncation: + /* Try to go back one if we don't have enough space for the ellipsis */ + if (n + 1 >= console_width) + s = prev_s; + + s = mempcpy(s, "…", strlen("…")); + + finish: + *s = '\0'; + (void) str_realloc(&p); + return p; +} + +char *ascii_is_valid(const char *str) { + const char *p; + + /* Check whether the string consists of valid ASCII bytes, + * i.e values between 0 and 127, inclusive. */ + + assert(str); + + for (p = str; *p; p++) + if ((unsigned char) *p >= 128) + return NULL; + + return (char*) str; +} + +char *ascii_is_valid_n(const char *str, size_t len) { + size_t i; + + /* Very similar to ascii_is_valid(), but checks exactly len + * bytes and rejects any NULs in that range. */ + + assert(str); + + for (i = 0; i < len; i++) + if ((unsigned char) str[i] >= 128 || str[i] == 0) + return NULL; + + return (char*) str; +} + +/** + * utf8_encode_unichar() - Encode single UCS-4 character as UTF-8 + * @out_utf8: output buffer of at least 4 bytes or NULL + * @g: UCS-4 character to encode + * + * This encodes a single UCS-4 character as UTF-8 and writes it into @out_utf8. + * The length of the character is returned. It is not zero-terminated! If the + * output buffer is NULL, only the length is returned. + * + * Returns: The length in bytes that the UTF-8 representation does or would + * occupy. + */ +size_t utf8_encode_unichar(char *out_utf8, char32_t g) { + + if (g < (1 << 7)) { + if (out_utf8) + out_utf8[0] = g & 0x7f; + return 1; + } else if (g < (1 << 11)) { + if (out_utf8) { + out_utf8[0] = 0xc0 | ((g >> 6) & 0x1f); + out_utf8[1] = 0x80 | (g & 0x3f); + } + return 2; + } else if (g < (1 << 16)) { + if (out_utf8) { + out_utf8[0] = 0xe0 | ((g >> 12) & 0x0f); + out_utf8[1] = 0x80 | ((g >> 6) & 0x3f); + out_utf8[2] = 0x80 | (g & 0x3f); + } + return 3; + } else if (g < (1 << 21)) { + if (out_utf8) { + out_utf8[0] = 0xf0 | ((g >> 18) & 0x07); + out_utf8[1] = 0x80 | ((g >> 12) & 0x3f); + out_utf8[2] = 0x80 | ((g >> 6) & 0x3f); + out_utf8[3] = 0x80 | (g & 0x3f); + } + return 4; + } + + return 0; +} + +char *utf16_to_utf8(const char16_t *s, size_t length /* bytes! */) { + const uint8_t *f; + char *r, *t; + + assert(s); + + /* Input length is in bytes, i.e. the shortest possible character takes 2 bytes. Each unicode character may + * take up to 4 bytes in UTF-8. Let's also account for a trailing NUL byte. */ + if (length * 2 < length) + return NULL; /* overflow */ + + r = new(char, length * 2 + 1); + if (!r) + return NULL; + + f = (const uint8_t*) s; + t = r; + + while (f + 1 < (const uint8_t*) s + length) { + char16_t w1, w2; + + /* see RFC 2781 section 2.2 */ + + w1 = f[1] << 8 | f[0]; + f += 2; + + if (!utf16_is_surrogate(w1)) { + t += utf8_encode_unichar(t, w1); + continue; + } + + if (utf16_is_trailing_surrogate(w1)) + continue; /* spurious trailing surrogate, ignore */ + + if (f + 1 >= (const uint8_t*) s + length) + break; + + w2 = f[1] << 8 | f[0]; + f += 2; + + if (!utf16_is_trailing_surrogate(w2)) { + f -= 2; + continue; /* surrogate missing its trailing surrogate, ignore */ + } + + t += utf8_encode_unichar(t, utf16_surrogate_pair_to_unichar(w1, w2)); + } + + *t = 0; + return r; +} + +size_t utf16_encode_unichar(char16_t *out, char32_t c) { + + /* Note that this encodes as little-endian. */ + + switch (c) { + + case 0 ... 0xd7ffU: + case 0xe000U ... 0xffffU: + out[0] = htole16(c); + return 1; + + case 0x10000U ... 0x10ffffU: + c -= 0x10000U; + out[0] = htole16((c >> 10) + 0xd800U); + out[1] = htole16((c & 0x3ffU) + 0xdc00U); + return 2; + + default: /* A surrogate (invalid) */ + return 0; + } +} + +char16_t *utf8_to_utf16(const char *s, size_t length) { + char16_t *n, *p; + size_t i; + int r; + + assert(s); + + n = new(char16_t, length + 1); + if (!n) + return NULL; + + p = n; + + for (i = 0; i < length;) { + char32_t unichar; + size_t e; + + e = utf8_encoded_expected_len(s[i]); + if (e <= 1) /* Invalid and single byte characters are copied as they are */ + goto copy; + + if (i + e > length) /* sequence longer than input buffer, then copy as-is */ + goto copy; + + r = utf8_encoded_to_unichar(s + i, &unichar); + if (r < 0) /* sequence invalid, then copy as-is */ + goto copy; + + p += utf16_encode_unichar(p, unichar); + i += e; + continue; + + copy: + *(p++) = htole16(s[i++]); + } + + *p = 0; + return n; +} + +size_t char16_strlen(const char16_t *s) { + size_t n = 0; + + assert(s); + + while (*s != 0) + n++, s++; + + return n; +} + +/* expected size used to encode one unicode char */ +static int utf8_unichar_to_encoded_len(char32_t unichar) { + + if (unichar < 0x80) + return 1; + if (unichar < 0x800) + return 2; + if (unichar < 0x10000) + return 3; + if (unichar < 0x200000) + return 4; + if (unichar < 0x4000000) + return 5; + + return 6; +} + +/* validate one encoded unicode char and return its length */ +int utf8_encoded_valid_unichar(const char *str, size_t length /* bytes */) { + char32_t unichar; + size_t len, i; + int r; + + assert(str); + assert(length > 0); + + /* We read until NUL, at most length bytes. (size_t) -1 may be used to disable the length check. */ + + len = utf8_encoded_expected_len(str[0]); + if (len == 0) + return -EINVAL; + + /* Do we have a truncated multi-byte character? */ + if (len > length) + return -EINVAL; + + /* ascii is valid */ + if (len == 1) + return 1; + + /* check if expected encoded chars are available */ + for (i = 0; i < len; i++) + if ((str[i] & 0x80) != 0x80) + return -EINVAL; + + r = utf8_encoded_to_unichar(str, &unichar); + if (r < 0) + return r; + + /* check if encoded length matches encoded value */ + if (utf8_unichar_to_encoded_len(unichar) != (int) len) + return -EINVAL; + + /* check if value has valid range */ + if (!unichar_is_valid(unichar)) + return -EINVAL; + + return (int) len; +} + +size_t utf8_n_codepoints(const char *str) { + size_t n = 0; + + /* Returns the number of UTF-8 codepoints in this string, or (size_t) -1 if the string is not valid UTF-8. */ + + while (*str != 0) { + int k; + + k = utf8_encoded_valid_unichar(str, (size_t) -1); + if (k < 0) + return (size_t) -1; + + str += k; + n++; + } + + return n; +} + +size_t utf8_console_width(const char *str) { + size_t n = 0; + + /* Returns the approximate width a string will take on screen when printed on a character cell + * terminal/console. */ + + while (*str) { + int w; + + w = utf8_char_console_width(str); + if (w < 0) + return (size_t) -1; + + n += w; + str = utf8_next_char(str); + } + + return n; +} diff --git a/src/basic/utf8.h b/src/basic/utf8.h new file mode 100644 index 00000000..62e99b72 --- /dev/null +++ b/src/basic/utf8.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "macro.h" +#include "missing_type.h" + +#define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd" +#define UTF8_BYTE_ORDER_MARK "\xef\xbb\xbf" + +bool unichar_is_valid(char32_t c); + +char *utf8_is_valid(const char *s) _pure_; +char *ascii_is_valid(const char *s) _pure_; +char *ascii_is_valid_n(const char *str, size_t len); + +bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_; +#define utf8_is_printable(str, length) utf8_is_printable_newline(str, length, true) + +char *utf8_escape_invalid(const char *s); +char *utf8_escape_non_printable_full(const char *str, size_t console_width); +static inline char *utf8_escape_non_printable(const char *str) { + return utf8_escape_non_printable_full(str, (size_t) -1); +} + +size_t utf8_encode_unichar(char *out_utf8, char32_t g); +size_t utf16_encode_unichar(char16_t *out, char32_t c); + +char *utf16_to_utf8(const char16_t *s, size_t length /* bytes! */); +char16_t *utf8_to_utf16(const char *s, size_t length); + +size_t char16_strlen(const char16_t *s); /* returns the number of 16bit words in the string (not bytes!) */ + +int utf8_encoded_valid_unichar(const char *str, size_t length); +int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar); + +static inline bool utf16_is_surrogate(char16_t c) { + return c >= 0xd800U && c <= 0xdfffU; +} + +static inline bool utf16_is_trailing_surrogate(char16_t c) { + return c >= 0xdc00U && c <= 0xdfffU; +} + +static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail) { + return ((((char32_t) lead - 0xd800U) << 10) + ((char32_t) trail - 0xdc00U) + 0x10000U); +} + +size_t utf8_n_codepoints(const char *str); +size_t utf8_console_width(const char *str); diff --git a/src/basic/util.c b/src/basic/util.c new file mode 100644 index 00000000..2b3b3918 --- /dev/null +++ b/src/basic/util.c @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "build.h" +#include "dirent-util.h" +#include "env-file.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "hostname-util.h" +#include "log.h" +#include "macro.h" +#include "parse-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "util.h" +#include "virt.h" + +int saved_argc = 0; +char **saved_argv = NULL; +static int saved_in_initrd = -1; + +bool kexec_loaded(void) { + _cleanup_free_ char *s = NULL; + + if (read_one_line_file("/sys/kernel/kexec_loaded", &s) < 0) + return false; + + return s[0] == '1'; +} + +int prot_from_flags(int flags) { + + switch (flags & O_ACCMODE) { + + case O_RDONLY: + return PROT_READ; + + case O_WRONLY: + return PROT_WRITE; + + case O_RDWR: + return PROT_READ|PROT_WRITE; + + default: + return -EINVAL; + } +} + +bool in_initrd(void) { + struct statfs s; + int r; + + if (saved_in_initrd >= 0) + return saved_in_initrd; + + /* We make two checks here: + * + * 1. the flag file /etc/initrd-release must exist + * 2. the root file system must be a memory file system + * + * The second check is extra paranoia, since misdetecting an + * initrd can have bad consequences due the initrd + * emptying when transititioning to the main systemd. + */ + + r = getenv_bool_secure("SYSTEMD_IN_INITRD"); + if (r < 0 && r != -ENXIO) + log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m"); + + if (r >= 0) + saved_in_initrd = r > 0; + else + saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 && + statfs("/", &s) >= 0 && + is_temporary_fs(&s); + + return saved_in_initrd; +} + +void in_initrd_force(bool value) { + saved_in_initrd = value; +} + +int on_ac_power(void) { + bool found_offline = false, found_online = false; + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + + d = opendir("/sys/class/power_supply"); + if (!d) + return errno == ENOENT ? true : -errno; + + FOREACH_DIRENT(de, d, return -errno) { + _cleanup_close_ int fd = -1, device = -1; + char contents[6]; + ssize_t n; + + device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (device < 0) { + if (IN_SET(errno, ENOENT, ENOTDIR)) + continue; + + return -errno; + } + + fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + if (errno == ENOENT) + continue; + + return -errno; + } + + n = read(fd, contents, sizeof(contents)); + if (n < 0) + return -errno; + + if (n != 6 || memcmp(contents, "Mains\n", 6)) + continue; + + safe_close(fd); + fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + if (errno == ENOENT) + continue; + + return -errno; + } + + n = read(fd, contents, sizeof(contents)); + if (n < 0) + return -errno; + + if (n != 2 || contents[1] != '\n') + return -EIO; + + if (contents[0] == '1') { + found_online = true; + break; + } else if (contents[0] == '0') + found_offline = true; + else + return -EIO; + } + + return found_online || !found_offline; +} + +int container_get_leader(const char *machine, pid_t *pid) { + _cleanup_free_ char *s = NULL, *class = NULL; + const char *p; + pid_t leader; + int r; + + assert(machine); + assert(pid); + + if (streq(machine, ".host")) { + *pid = 1; + return 0; + } + + if (!machine_name_is_valid(machine)) + return -EINVAL; + + p = strjoina("/run/systemd/machines/", machine); + r = parse_env_file(NULL, p, + "LEADER", &s, + "CLASS", &class); + if (r == -ENOENT) + return -EHOSTDOWN; + if (r < 0) + return r; + if (!s) + return -EIO; + + if (!streq_ptr(class, "container")) + return -EIO; + + r = parse_pid(s, &leader); + if (r < 0) + return r; + if (leader <= 1) + return -EIO; + + *pid = leader; + return 0; +} + +int version(void) { + puts("systemd " STRINGIFY(PROJECT_VERSION) " (" GIT_VERSION ")\n" + SYSTEMD_FEATURES); + return 0; +} + +/* This is a direct translation of str_verscmp from boot.c */ +static bool is_digit(int c) { + return c >= '0' && c <= '9'; +} + +static int c_order(int c) { + if (c == 0 || is_digit(c)) + return 0; + + if ((c >= 'a') && (c <= 'z')) + return c; + + return c + 0x10000; +} + +int str_verscmp(const char *s1, const char *s2) { + const char *os1, *os2; + + assert(s1); + assert(s2); + + os1 = s1; + os2 = s2; + + while (*s1 || *s2) { + int first; + + while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) { + int order; + + order = c_order(*s1) - c_order(*s2); + if (order != 0) + return order; + s1++; + s2++; + } + + while (*s1 == '0') + s1++; + while (*s2 == '0') + s2++; + + first = 0; + while (is_digit(*s1) && is_digit(*s2)) { + if (first == 0) + first = *s1 - *s2; + s1++; + s2++; + } + + if (is_digit(*s1)) + return 1; + if (is_digit(*s2)) + return -1; + + if (first != 0) + return first; + } + + return strcmp(os1, os2); +} + +/* Turn off core dumps but only if we're running outside of a container. */ +void disable_coredumps(void) { + int r; + + if (detect_container() > 0) + return; + + r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m"); +} diff --git a/src/basic/util.h b/src/basic/util.h new file mode 100644 index 00000000..6fc7480f --- /dev/null +++ b/src/basic/util.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +extern int saved_argc; +extern char **saved_argv; + +static inline void save_argc_argv(int argc, char **argv) { + saved_argc = argc; + saved_argv = argv; +} + +bool kexec_loaded(void); + +int prot_from_flags(int flags) _const_; + +bool in_initrd(void); +void in_initrd_force(bool value); + +int on_ac_power(void); + +static inline unsigned u64log2(uint64_t n) { +#if __SIZEOF_LONG_LONG__ == 8 + return (n > 1) ? (unsigned) __builtin_clzll(n) ^ 63U : 0; +#else +#error "Wut?" +#endif +} + +static inline unsigned u32ctz(uint32_t n) { +#if __SIZEOF_INT__ == 4 + return n != 0 ? __builtin_ctz(n) : 32; +#else +#error "Wut?" +#endif +} + +static inline unsigned log2i(int x) { + assert(x > 0); + + return __SIZEOF_INT__ * 8 - __builtin_clz(x) - 1; +} + +static inline unsigned log2u(unsigned x) { + assert(x > 0); + + return sizeof(unsigned) * 8 - __builtin_clz(x) - 1; +} + +static inline unsigned log2u_round_up(unsigned x) { + assert(x > 0); + + if (x == 1) + return 0; + + return log2u(x - 1) + 1; +} + +int container_get_leader(const char *machine, pid_t *pid); + +int version(void); + +int str_verscmp(const char *s1, const char *s2); + +void disable_coredumps(void); diff --git a/src/basic/virt.c b/src/basic/virt.c new file mode 100644 index 00000000..6ba880db --- /dev/null +++ b/src/basic/virt.c @@ -0,0 +1,670 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if defined(__i386__) || defined(__x86_64__) +#include +#endif +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dirent-util.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "macro.h" +#include "process-util.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "virt.h" + +static int detect_vm_cpuid(void) { + + /* CPUID is an x86 specific interface. */ +#if defined(__i386__) || defined(__x86_64__) + + static const struct { + const char *cpuid; + int id; + } cpuid_vendor_table[] = { + { "XenVMMXenVMM", VIRTUALIZATION_XEN }, + { "KVMKVMKVM", VIRTUALIZATION_KVM }, + { "TCGTCGTCGTCG", VIRTUALIZATION_QEMU }, + /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */ + { "VMwareVMware", VIRTUALIZATION_VMWARE }, + /* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs */ + { "Microsoft Hv", VIRTUALIZATION_MICROSOFT }, + /* https://wiki.freebsd.org/bhyve */ + { "bhyve bhyve ", VIRTUALIZATION_BHYVE }, + { "QNXQVMBSQG", VIRTUALIZATION_QNX }, + /* https://projectacrn.org */ + { "ACRNACRNACRN", VIRTUALIZATION_ACRN }, + }; + + uint32_t eax, ebx, ecx, edx; + bool hypervisor; + + /* http://lwn.net/Articles/301888/ */ + + /* First detect whether there is a hypervisor */ + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0) + return VIRTUALIZATION_NONE; + + hypervisor = ecx & 0x80000000U; + + if (hypervisor) { + union { + uint32_t sig32[3]; + char text[13]; + } sig = {}; + unsigned j; + + /* There is a hypervisor, see what it is */ + __cpuid(0x40000000U, eax, ebx, ecx, edx); + + sig.sig32[0] = ebx; + sig.sig32[1] = ecx; + sig.sig32[2] = edx; + + log_debug("Virtualization found, CPUID=%s", sig.text); + + for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++) + if (streq(sig.text, cpuid_vendor_table[j].cpuid)) + return cpuid_vendor_table[j].id; + + return VIRTUALIZATION_VM_OTHER; + } +#endif + log_debug("No virtualization found in CPUID"); + + return VIRTUALIZATION_NONE; +} + +static int detect_vm_device_tree(void) { +#if defined(__arm__) || defined(__aarch64__) || defined(__powerpc__) || defined(__powerpc64__) + _cleanup_free_ char *hvtype = NULL; + int r; + + r = read_one_line_file("/proc/device-tree/hypervisor/compatible", &hvtype); + if (r == -ENOENT) { + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *dent; + + dir = opendir("/proc/device-tree"); + if (!dir) { + if (errno == ENOENT) { + log_debug_errno(errno, "/proc/device-tree: %m"); + return VIRTUALIZATION_NONE; + } + return -errno; + } + + FOREACH_DIRENT(dent, dir, return -errno) + if (strstr(dent->d_name, "fw-cfg")) { + log_debug("Virtualization QEMU: \"fw-cfg\" present in /proc/device-tree/%s", dent->d_name); + return VIRTUALIZATION_QEMU; + } + + log_debug("No virtualization found in /proc/device-tree/*"); + return VIRTUALIZATION_NONE; + } else if (r < 0) + return r; + + log_debug("Virtualization %s found in /proc/device-tree/hypervisor/compatible", hvtype); + if (streq(hvtype, "linux,kvm")) + return VIRTUALIZATION_KVM; + else if (strstr(hvtype, "xen")) + return VIRTUALIZATION_XEN; + else if (strstr(hvtype, "vmware")) + return VIRTUALIZATION_VMWARE; + else + return VIRTUALIZATION_VM_OTHER; +#else + log_debug("This platform does not support /proc/device-tree"); + return VIRTUALIZATION_NONE; +#endif +} + +static int detect_vm_dmi(void) { +#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) + + static const char *const dmi_vendors[] = { + "/sys/class/dmi/id/product_name", /* Test this before sys_vendor to detect KVM over QEMU */ + "/sys/class/dmi/id/sys_vendor", + "/sys/class/dmi/id/board_vendor", + "/sys/class/dmi/id/bios_vendor" + }; + + static const struct { + const char *vendor; + int id; + } dmi_vendor_table[] = { + { "KVM", VIRTUALIZATION_KVM }, + { "QEMU", VIRTUALIZATION_QEMU }, + { "VMware", VIRTUALIZATION_VMWARE }, /* https://kb.vmware.com/s/article/1009458 */ + { "VMW", VIRTUALIZATION_VMWARE }, + { "innotek GmbH", VIRTUALIZATION_ORACLE }, + { "Oracle Corporation", VIRTUALIZATION_ORACLE }, + { "Xen", VIRTUALIZATION_XEN }, + { "Bochs", VIRTUALIZATION_BOCHS }, + { "Parallels", VIRTUALIZATION_PARALLELS }, + /* https://wiki.freebsd.org/bhyve */ + { "BHYVE", VIRTUALIZATION_BHYVE }, + }; + unsigned i; + int r; + + for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) { + _cleanup_free_ char *s = NULL; + unsigned j; + + r = read_one_line_file(dmi_vendors[i], &s); + if (r < 0) { + if (r == -ENOENT) + continue; + + return r; + } + + for (j = 0; j < ELEMENTSOF(dmi_vendor_table); j++) + if (startswith(s, dmi_vendor_table[j].vendor)) { + log_debug("Virtualization %s found in DMI (%s)", s, dmi_vendors[i]); + return dmi_vendor_table[j].id; + } + } +#endif + + log_debug("No virtualization found in DMI"); + + return VIRTUALIZATION_NONE; +} + +static int detect_vm_xen(void) { + + /* Check for Dom0 will be executed later in detect_vm_xen_dom0 + The presence of /proc/xen indicates some form of a Xen domain */ + if (access("/proc/xen", F_OK) < 0) { + log_debug("Virtualization XEN not found, /proc/xen does not exist"); + return VIRTUALIZATION_NONE; + } + + log_debug("Virtualization XEN found (/proc/xen exists)"); + return VIRTUALIZATION_XEN; +} + +#define XENFEAT_dom0 11 /* xen/include/public/features.h */ +#define PATH_FEATURES "/sys/hypervisor/properties/features" +/* Returns -errno, or 0 for domU, or 1 for dom0 */ +static int detect_vm_xen_dom0(void) { + _cleanup_free_ char *domcap = NULL; + int r; + + r = read_one_line_file(PATH_FEATURES, &domcap); + if (r < 0 && r != -ENOENT) + return r; + if (r >= 0) { + unsigned long features; + + /* Here, we need to use sscanf() instead of safe_atoul() + * as the string lacks the leading "0x". */ + r = sscanf(domcap, "%lx", &features); + if (r == 1) { + r = !!(features & (1U << XENFEAT_dom0)); + log_debug("Virtualization XEN, found %s with value %08lx, " + "XENFEAT_dom0 (indicating the 'hardware domain') is%s set.", + PATH_FEATURES, features, r ? "" : " not"); + return r; + } + log_debug("Virtualization XEN, found %s, unhandled content '%s'", + PATH_FEATURES, domcap); + } + + r = read_one_line_file("/proc/xen/capabilities", &domcap); + if (r == -ENOENT) { + log_debug("Virtualization XEN because /proc/xen/capabilities does not exist"); + return 0; + } + if (r < 0) + return r; + + for (const char *i = domcap;;) { + _cleanup_free_ char *cap = NULL; + + r = extract_first_word(&i, &cap, ",", 0); + if (r < 0) + return r; + if (r == 0) { + log_debug("Virtualization XEN DomU found (/proc/xen/capabilities)"); + return 0; + } + + if (streq(cap, "control_d")) { + log_debug("Virtualization XEN Dom0 ignored (/proc/xen/capabilities)"); + return 1; + } + } +} + +static int detect_vm_hypervisor(void) { + _cleanup_free_ char *hvtype = NULL; + int r; + + r = read_one_line_file("/sys/hypervisor/type", &hvtype); + if (r == -ENOENT) + return VIRTUALIZATION_NONE; + if (r < 0) + return r; + + log_debug("Virtualization %s found in /sys/hypervisor/type", hvtype); + + if (streq(hvtype, "xen")) + return VIRTUALIZATION_XEN; + else + return VIRTUALIZATION_VM_OTHER; +} + +static int detect_vm_uml(void) { + _cleanup_fclose_ FILE *f = NULL; + int r; + + /* Detect User-Mode Linux by reading /proc/cpuinfo */ + f = fopen("/proc/cpuinfo", "re"); + if (!f) { + if (errno == ENOENT) { + log_debug("/proc/cpuinfo not found, assuming no UML virtualization."); + return VIRTUALIZATION_NONE; + } + return -errno; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *t; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + t = startswith(line, "vendor_id\t: "); + if (t) { + if (startswith(t, "User Mode Linux")) { + log_debug("UML virtualization found in /proc/cpuinfo"); + return VIRTUALIZATION_UML; + } + + break; + } + } + + log_debug("UML virtualization not found in /proc/cpuinfo."); + return VIRTUALIZATION_NONE; +} + +static int detect_vm_zvm(void) { + +#if defined(__s390__) + _cleanup_free_ char *t = NULL; + int r; + + r = get_proc_field("/proc/sysinfo", "VM00 Control Program", WHITESPACE, &t); + if (r == -ENOENT) + return VIRTUALIZATION_NONE; + if (r < 0) + return r; + + log_debug("Virtualization %s found in /proc/sysinfo", t); + if (streq(t, "z/VM")) + return VIRTUALIZATION_ZVM; + else + return VIRTUALIZATION_KVM; +#else + log_debug("This platform does not support /proc/sysinfo"); + return VIRTUALIZATION_NONE; +#endif +} + +/* Returns a short identifier for the various VM implementations */ +int detect_vm(void) { + static thread_local int cached_found = _VIRTUALIZATION_INVALID; + bool other = false; + int r, dmi; + + if (cached_found >= 0) + return cached_found; + + /* We have to use the correct order here: + * + * → First, try to detect Oracle Virtualbox, even if it uses KVM, as well as Xen even if it cloaks as Microsoft + * Hyper-V. + * + * → Second, try to detect from CPUID, this will report KVM for whatever software is used even if info in DMI is + * overwritten. + * + * → Third, try to detect from DMI. */ + + dmi = detect_vm_dmi(); + if (IN_SET(dmi, VIRTUALIZATION_ORACLE, VIRTUALIZATION_XEN)) { + r = dmi; + goto finish; + } + + r = detect_vm_cpuid(); + if (r < 0) + return r; + if (r == VIRTUALIZATION_VM_OTHER) + other = true; + else if (r != VIRTUALIZATION_NONE) + goto finish; + + /* Now, let's get back to DMI */ + if (dmi < 0) + return dmi; + if (dmi == VIRTUALIZATION_VM_OTHER) + other = true; + else if (dmi != VIRTUALIZATION_NONE) { + r = dmi; + goto finish; + } + + /* x86 xen will most likely be detected by cpuid. If not (most likely + * because we're not an x86 guest), then we should try the /proc/xen + * directory next. If that's not found, then we check for the high-level + * hypervisor sysfs file. + */ + + r = detect_vm_xen(); + if (r < 0) + return r; + if (r == VIRTUALIZATION_VM_OTHER) + other = true; + else if (r != VIRTUALIZATION_NONE) + goto finish; + + r = detect_vm_hypervisor(); + if (r < 0) + return r; + if (r == VIRTUALIZATION_VM_OTHER) + other = true; + else if (r != VIRTUALIZATION_NONE) + goto finish; + + r = detect_vm_device_tree(); + if (r < 0) + return r; + if (r == VIRTUALIZATION_VM_OTHER) + other = true; + else if (r != VIRTUALIZATION_NONE) + goto finish; + + r = detect_vm_uml(); + if (r < 0) + return r; + if (r == VIRTUALIZATION_VM_OTHER) + other = true; + else if (r != VIRTUALIZATION_NONE) + goto finish; + + r = detect_vm_zvm(); + if (r < 0) + return r; + +finish: + /* x86 xen Dom0 is detected as XEN in hypervisor and maybe others. + * In order to detect the Dom0 as not virtualization we need to + * double-check it */ + if (r == VIRTUALIZATION_XEN) { + int dom0; + + dom0 = detect_vm_xen_dom0(); + if (dom0 < 0) + return dom0; + if (dom0 > 0) + r = VIRTUALIZATION_NONE; + } else if (r == VIRTUALIZATION_NONE && other) + r = VIRTUALIZATION_VM_OTHER; + + cached_found = r; + log_debug("Found VM virtualization %s", virtualization_to_string(r)); + return r; +} + +int detect_container(void) { + static const struct { + const char *value; + int id; + } value_table[] = { + { "lxc", VIRTUALIZATION_LXC }, + { "lxc-libvirt", VIRTUALIZATION_LXC_LIBVIRT }, + { "systemd-nspawn", VIRTUALIZATION_SYSTEMD_NSPAWN }, + { "docker", VIRTUALIZATION_DOCKER }, + { "podman", VIRTUALIZATION_PODMAN }, + { "rkt", VIRTUALIZATION_RKT }, + { "wsl", VIRTUALIZATION_WSL }, + }; + + static thread_local int cached_found = _VIRTUALIZATION_INVALID; + _cleanup_free_ char *m = NULL; + _cleanup_free_ char *o = NULL; + const char *e = NULL; + unsigned j; + int r; + + if (cached_found >= 0) + return cached_found; + + /* /proc/vz exists in container and outside of the container, /proc/bc only outside of the container. */ + if (access("/proc/vz", F_OK) >= 0 && + access("/proc/bc", F_OK) < 0) { + r = VIRTUALIZATION_OPENVZ; + goto finish; + } + + /* "Official" way of detecting WSL https://github.com/Microsoft/WSL/issues/423#issuecomment-221627364 */ + r = read_one_line_file("/proc/sys/kernel/osrelease", &o); + if (r >= 0) { + if (strstr(o, "Microsoft") || strstr(o, "WSL")) { + r = VIRTUALIZATION_WSL; + goto finish; + } + } + + if (getpid_cached() == 1) { + /* If we are PID 1 we can just check our own environment variable, and that's authoritative. + * We distinguish three cases: + * - the variable is not defined → we jump to other checks + * - the variable is defined to an empty value → we are not in a container + * - anything else → some container, either one of the known ones or "container-other" + */ + e = getenv("container"); + if (!e) + goto check_sched; + if (isempty(e)) { + r = VIRTUALIZATION_NONE; + goto finish; + } + + goto translate_name; + } + + /* Otherwise, PID 1 might have dropped this information into a file in /run. This is better than accessing + * /proc/1/environ, since we don't need CAP_SYS_PTRACE for that. */ + r = read_one_line_file("/run/systemd/container", &m); + if (r > 0) { + e = m; + goto translate_name; + } + if (!IN_SET(r, -ENOENT, 0)) + return log_debug_errno(r, "Failed to read /run/systemd/container: %m"); + + /* Fallback for cases where PID 1 was not systemd (for example, cases where init=/bin/sh is used. */ + r = getenv_for_pid(1, "container", &m); + if (r > 0) { + e = m; + goto translate_name; + } + if (r < 0) /* This only works if we have CAP_SYS_PTRACE, hence let's better ignore failures here */ + log_debug_errno(r, "Failed to read $container of PID 1, ignoring: %m"); + + /* Interestingly /proc/1/sched actually shows the host's PID for what we see as PID 1. If the PID + * shown there is not 1, we know we are in a PID namespace and hence a container. */ + check_sched: + r = read_one_line_file("/proc/1/sched", &m); + if (r >= 0) { + const char *t; + + t = strrchr(m, '('); + if (!t) + return -EIO; + + if (!startswith(t, "(1,")) { + r = VIRTUALIZATION_CONTAINER_OTHER; + goto finish; + } + } else if (r != -ENOENT) + return r; + + /* If that didn't work, give up, assume no container manager. */ + r = VIRTUALIZATION_NONE; + goto finish; + +translate_name: + for (j = 0; j < ELEMENTSOF(value_table); j++) + if (streq(e, value_table[j].value)) { + r = value_table[j].id; + goto finish; + } + + r = VIRTUALIZATION_CONTAINER_OTHER; + +finish: + log_debug("Found container virtualization %s.", virtualization_to_string(r)); + cached_found = r; + return r; +} + +int detect_virtualization(void) { + int r; + + r = detect_container(); + if (r == 0) + r = detect_vm(); + + return r; +} + +static int userns_has_mapping(const char *name) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *buf = NULL; + size_t n_allocated = 0; + ssize_t n; + uint32_t a, b, c; + int r; + + f = fopen(name, "re"); + if (!f) { + log_debug_errno(errno, "Failed to open %s: %m", name); + return errno == ENOENT ? false : -errno; + } + + n = getline(&buf, &n_allocated, f); + if (n < 0) { + if (feof(f)) { + log_debug("%s is empty, we're in an uninitialized user namespace", name); + return true; + } + + return log_debug_errno(errno, "Failed to read %s: %m", name); + } + + r = sscanf(buf, "%"PRIu32" %"PRIu32" %"PRIu32, &a, &b, &c); + if (r < 3) + return log_debug_errno(errno, "Failed to parse %s: %m", name); + + if (a == 0 && b == 0 && c == UINT32_MAX) { + /* The kernel calls mappings_overlap() and does not allow overlaps */ + log_debug("%s has a full 1:1 mapping", name); + return false; + } + + /* Anything else implies that we are in a user namespace */ + log_debug("Mapping found in %s, we're in a user namespace", name); + return true; +} + +int running_in_userns(void) { + _cleanup_free_ char *line = NULL; + int r; + + r = userns_has_mapping("/proc/self/uid_map"); + if (r != 0) + return r; + + r = userns_has_mapping("/proc/self/gid_map"); + if (r != 0) + return r; + + /* "setgroups" file was added in kernel v3.18-rc6-15-g9cc46516dd. It is also + * possible to compile a kernel without CONFIG_USER_NS, in which case "setgroups" + * also does not exist. We cannot distinguish those two cases, so assume that + * we're running on a stripped-down recent kernel, rather than on an old one, + * and if the file is not found, return false. + */ + r = read_one_line_file("/proc/self/setgroups", &line); + if (r < 0) { + log_debug_errno(r, "/proc/self/setgroups: %m"); + return r == -ENOENT ? false : r; + } + + truncate_nl(line); + r = streq(line, "deny"); + /* See user_namespaces(7) for a description of this "setgroups" contents. */ + log_debug("/proc/self/setgroups contains \"%s\", %s user namespace", line, r ? "in" : "not in"); + return r; +} + +int running_in_chroot(void) { + int r; + + if (getenv_bool("SYSTEMD_IGNORE_CHROOT") > 0) + return 0; + + r = files_same("/proc/1/root", "/", 0); + if (r < 0) + return r; + + return r == 0; +} + +static const char *const virtualization_table[_VIRTUALIZATION_MAX] = { + [VIRTUALIZATION_NONE] = "none", + [VIRTUALIZATION_KVM] = "kvm", + [VIRTUALIZATION_QEMU] = "qemu", + [VIRTUALIZATION_BOCHS] = "bochs", + [VIRTUALIZATION_XEN] = "xen", + [VIRTUALIZATION_UML] = "uml", + [VIRTUALIZATION_VMWARE] = "vmware", + [VIRTUALIZATION_ORACLE] = "oracle", + [VIRTUALIZATION_MICROSOFT] = "microsoft", + [VIRTUALIZATION_ZVM] = "zvm", + [VIRTUALIZATION_PARALLELS] = "parallels", + [VIRTUALIZATION_BHYVE] = "bhyve", + [VIRTUALIZATION_QNX] = "qnx", + [VIRTUALIZATION_ACRN] = "acrn", + [VIRTUALIZATION_VM_OTHER] = "vm-other", + + [VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn", + [VIRTUALIZATION_LXC_LIBVIRT] = "lxc-libvirt", + [VIRTUALIZATION_LXC] = "lxc", + [VIRTUALIZATION_OPENVZ] = "openvz", + [VIRTUALIZATION_DOCKER] = "docker", + [VIRTUALIZATION_PODMAN] = "podman", + [VIRTUALIZATION_RKT] = "rkt", + [VIRTUALIZATION_WSL] = "wsl", + [VIRTUALIZATION_CONTAINER_OTHER] = "container-other", +}; + +DEFINE_STRING_TABLE_LOOKUP(virtualization, int); diff --git a/src/basic/virt.h b/src/basic/virt.h new file mode 100644 index 00000000..26f409af --- /dev/null +++ b/src/basic/virt.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +enum { + VIRTUALIZATION_NONE = 0, + + VIRTUALIZATION_VM_FIRST, + VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST, + VIRTUALIZATION_QEMU, + VIRTUALIZATION_BOCHS, + VIRTUALIZATION_XEN, + VIRTUALIZATION_UML, + VIRTUALIZATION_VMWARE, + VIRTUALIZATION_ORACLE, + VIRTUALIZATION_MICROSOFT, + VIRTUALIZATION_ZVM, + VIRTUALIZATION_PARALLELS, + VIRTUALIZATION_BHYVE, + VIRTUALIZATION_QNX, + VIRTUALIZATION_ACRN, + VIRTUALIZATION_VM_OTHER, + VIRTUALIZATION_VM_LAST = VIRTUALIZATION_VM_OTHER, + + VIRTUALIZATION_CONTAINER_FIRST, + VIRTUALIZATION_SYSTEMD_NSPAWN = VIRTUALIZATION_CONTAINER_FIRST, + VIRTUALIZATION_LXC_LIBVIRT, + VIRTUALIZATION_LXC, + VIRTUALIZATION_OPENVZ, + VIRTUALIZATION_DOCKER, + VIRTUALIZATION_PODMAN, + VIRTUALIZATION_RKT, + VIRTUALIZATION_WSL, + VIRTUALIZATION_CONTAINER_OTHER, + VIRTUALIZATION_CONTAINER_LAST = VIRTUALIZATION_CONTAINER_OTHER, + + _VIRTUALIZATION_MAX, + _VIRTUALIZATION_INVALID = -1 +}; + +static inline bool VIRTUALIZATION_IS_VM(int x) { + return x >= VIRTUALIZATION_VM_FIRST && x <= VIRTUALIZATION_VM_LAST; +} + +static inline bool VIRTUALIZATION_IS_CONTAINER(int x) { + return x >= VIRTUALIZATION_CONTAINER_FIRST && x <= VIRTUALIZATION_CONTAINER_LAST; +} + +int detect_vm(void); +int detect_container(void); +int detect_virtualization(void); + +int running_in_userns(void); +int running_in_chroot(void); + +const char *virtualization_to_string(int v) _const_; +int virtualization_from_string(const char *s) _pure_; diff --git a/src/basic/xattr-util.c b/src/basic/xattr-util.c new file mode 100644 index 00000000..0125a9c2 --- /dev/null +++ b/src/basic/xattr-util.c @@ -0,0 +1,270 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "macro.h" +#include "missing_syscall.h" +#include "sparse-endian.h" +#include "stdio-util.h" +#include "string-util.h" +#include "time-util.h" +#include "xattr-util.h" + +int getxattr_malloc( + const char *path, + const char *name, + char **ret, + bool allow_symlink) { + + size_t l = 100; + + assert(path); + assert(name); + assert(ret); + + for(;;) { + _cleanup_free_ char *v = NULL; + ssize_t n; + + v = new0(char, l+1); + if (!v) + return -ENOMEM; + + if (allow_symlink) + n = lgetxattr(path, name, v, l); + else + n = getxattr(path, name, v, l); + if (n < 0) { + if (errno != ERANGE) + return -errno; + } else { + v[n] = 0; /* NUL terminate */ + *ret = TAKE_PTR(v); + return (int) n; + } + + if (allow_symlink) + n = lgetxattr(path, name, NULL, 0); + else + n = getxattr(path, name, NULL, 0); + if (n < 0) + return -errno; + if (n > INT_MAX) /* We couldn't return this as 'int' anymore */ + return -E2BIG; + + l = (size_t) n; + } +} + +int fgetxattr_malloc( + int fd, + const char *name, + char **ret) { + + size_t l = 100; + + assert(fd >= 0); + assert(name); + assert(ret); + + for (;;) { + _cleanup_free_ char *v = NULL; + ssize_t n; + + v = new(char, l+1); + if (!v) + return -ENOMEM; + + n = fgetxattr(fd, name, v, l); + if (n < 0) { + if (errno != ERANGE) + return -errno; + } else { + v[n] = 0; /* NUL terminate */ + *ret = TAKE_PTR(v); + return (int) n; + } + + n = fgetxattr(fd, name, NULL, 0); + if (n < 0) + return -errno; + if (n > INT_MAX) /* We couldn't return this as 'int' anymore */ + return -E2BIG; + + l = (size_t) n; + } +} + +int fgetxattrat_fake( + int dirfd, + const char *filename, + const char *attribute, + void *value, size_t size, + int flags, + size_t *ret_size) { + + char fn[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; + _cleanup_close_ int fd = -1; + ssize_t l; + + /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */ + + if (flags & ~(AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH)) + return -EINVAL; + + if (isempty(filename)) { + if (!(flags & AT_EMPTY_PATH)) + return -EINVAL; + + xsprintf(fn, "/proc/self/fd/%i", dirfd); + } else { + fd = openat(dirfd, filename, O_CLOEXEC|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0)); + if (fd < 0) + return -errno; + + xsprintf(fn, "/proc/self/fd/%i", fd); + } + + l = getxattr(fn, attribute, value, size); + if (l < 0) + return -errno; + + *ret_size = l; + return 0; +} + +static int parse_crtime(le64_t le, usec_t *usec) { + uint64_t u; + + assert(usec); + + u = le64toh(le); + if (IN_SET(u, 0, (uint64_t) -1)) + return -EIO; + + *usec = (usec_t) u; + return 0; +} + +int fd_getcrtime_at(int dirfd, const char *name, usec_t *ret, int flags) { + struct_statx sx +#if HAS_FEATURE_MEMORY_SANITIZER + = {} +# warning "Explicitly initializing struct statx, to work around msan limitation. Please remove as soon as msan has been updated to not require this." +#endif + ; + usec_t a, b; + le64_t le; + size_t n; + int r; + + assert(ret); + + if (flags & ~(AT_EMPTY_PATH|AT_SYMLINK_NOFOLLOW)) + return -EINVAL; + + /* So here's the deal: the creation/birth time (crtime/btime) of a file is a relatively newly supported concept + * on Linux (or more strictly speaking: a concept that only recently got supported in the API, it was + * implemented on various file systems on the lower level since a while, but never was accessible). However, we + * needed a concept like that for vaccuuming algorithms and such, hence we emulated it via a user xattr for a + * long time. Starting with Linux 4.11 there's statx() which exposes the timestamp to userspace for the first + * time, where it is available. Thius function will read it, but it tries to keep some compatibility with older + * systems: we try to read both the crtime/btime and the xattr, and then use whatever is older. After all the + * concept is useful for determining how "old" a file really is, and hence using the older of the two makes + * most sense. */ + + if (statx(dirfd, strempty(name), flags|AT_STATX_DONT_SYNC, STATX_BTIME, &sx) >= 0 && + (sx.stx_mask & STATX_BTIME) && + sx.stx_btime.tv_sec != 0) + a = (usec_t) sx.stx_btime.tv_sec * USEC_PER_SEC + + (usec_t) sx.stx_btime.tv_nsec / NSEC_PER_USEC; + else + a = USEC_INFINITY; + + r = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags, &n); + if (r >= 0) { + if (n != sizeof(le)) + r = -EIO; + else + r = parse_crtime(le, &b); + } + if (r < 0) { + if (a != USEC_INFINITY) { + *ret = a; + return 0; + } + + return r; + } + + if (a != USEC_INFINITY) + *ret = MIN(a, b); + else + *ret = b; + + return 0; +} + +int fd_getcrtime(int fd, usec_t *ret) { + return fd_getcrtime_at(fd, NULL, ret, AT_EMPTY_PATH); +} + +int path_getcrtime(const char *p, usec_t *ret) { + return fd_getcrtime_at(AT_FDCWD, p, ret, 0); +} + +int fd_setcrtime(int fd, usec_t usec) { + le64_t le; + + assert(fd >= 0); + + if (IN_SET(usec, 0, USEC_INFINITY)) + usec = now(CLOCK_REALTIME); + + le = htole64((uint64_t) usec); + if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0) + return -errno; + + return 0; +} + +int flistxattr_malloc(int fd, char **ret) { + size_t l = 100; + + assert(fd >= 0); + assert(ret); + + for (;;) { + _cleanup_free_ char *v = NULL; + ssize_t n; + + v = new(char, l+1); + if (!v) + return -ENOMEM; + + n = flistxattr(fd, v, l); + if (n < 0) { + if (errno != ERANGE) + return -errno; + } else { + v[n] = 0; /* NUL terminate */ + *ret = TAKE_PTR(v); + return (int) n; + } + + n = flistxattr(fd, NULL, 0); + if (n < 0) + return -errno; + if (n > INT_MAX) /* We couldn't return this as 'int' anymore */ + return -E2BIG; + + l = (size_t) n; + } +} diff --git a/src/basic/xattr-util.h b/src/basic/xattr-util.h new file mode 100644 index 00000000..a69e913b --- /dev/null +++ b/src/basic/xattr-util.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "time-util.h" + +int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink); +int fgetxattr_malloc(int fd, const char *name, char **value); + +int fgetxattrat_fake( + int dirfd, + const char *filename, + const char *attribute, + void *value, size_t size, + int flags, + size_t *ret_size); + +int fd_setcrtime(int fd, usec_t usec); + +int fd_getcrtime(int fd, usec_t *usec); +int path_getcrtime(const char *p, usec_t *usec); +int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags); + +int flistxattr_malloc(int fd, char **ret); diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c new file mode 100644 index 00000000..7ff844c7 --- /dev/null +++ b/src/binfmt/binfmt.c @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "conf-files.h" +#include "def.h" +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "main-func.h" +#include "pager.h" +#include "path-util.h" +#include "pretty-print.h" +#include "string-util.h" +#include "strv.h" + +static bool arg_cat_config = false; +static PagerFlags arg_pager_flags = 0; + +static int delete_rule(const char *rule) { + _cleanup_free_ char *x = NULL, *fn = NULL; + char *e; + + assert(rule); + assert(rule[0]); + + x = strdup(rule); + if (!x) + return log_oom(); + + e = strchrnul(x+1, x[0]); + *e = 0; + + if (!filename_is_valid(x + 1)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Rule file name '%s' is not valid, refusing.", x + 1); + + fn = path_join("/proc/sys/fs/binfmt_misc", x+1); + if (!fn) + return log_oom(); + + return write_string_file(fn, "-1", WRITE_STRING_FILE_DISABLE_BUFFER); +} + +static int apply_rule(const char *rule) { + int r; + + (void) delete_rule(rule); + + r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return log_error_errno(r, "Failed to add binary format: %m"); + + return 0; +} + +static int apply_file(const char *path, bool ignore_enoent) { + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(path); + + r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("binfmt.d"), &f); + if (r < 0) { + if (ignore_enoent && r == -ENOENT) + return 0; + + return log_error_errno(r, "Failed to open file '%s': %m", path); + } + + log_debug("apply: %s", path); + for (;;) { + _cleanup_free_ char *line = NULL; + char *p; + int k; + + k = read_line(f, LONG_LINE_MAX, &line); + if (k < 0) + return log_error_errno(k, "Failed to read file '%s': %m", path); + if (k == 0) + break; + + p = strstrip(line); + if (isempty(p)) + continue; + if (strchr(COMMENTS, p[0])) + continue; + + k = apply_rule(p); + if (k < 0 && r == 0) + r = k; + } + + return r; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-binfmt.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" + "Registers binary formats with the kernel.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --cat-config Show configuration files\n" + " --no-pager Do not pipe output into a pager\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_CAT_CONFIG, + ARG_NO_PAGER, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_CAT_CONFIG: + arg_cat_config = true; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_cat_config && argc > optind) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Positional arguments are not allowed with --cat-config"); + + return 1; +} + +static int run(int argc, char *argv[]) { + int r, k; + + r = parse_argv(argc, argv); + if (r <= 0) + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + + log_setup_service(); + + umask(0022); + + r = 0; + + if (argc > optind) { + int i; + + for (i = optind; i < argc; i++) { + k = apply_file(argv[i], false); + if (k < 0 && r == 0) + r = k; + } + } else { + _cleanup_strv_free_ char **files = NULL; + char **f; + + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("binfmt.d")); + if (r < 0) + return log_error_errno(r, "Failed to enumerate binfmt.d files: %m"); + + if (arg_cat_config) { + (void) pager_open(arg_pager_flags); + + return cat_files(NULL, files, 0); + } + + /* Flush out all rules */ + (void) write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", WRITE_STRING_FILE_DISABLE_BUFFER); + + STRV_FOREACH(f, files) { + k = apply_file(*f, true); + if (k < 0 && r == 0) + r = k; + } + } + + return r; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/boot/bless-boot-generator.c b/src/boot/bless-boot-generator.c new file mode 100644 index 00000000..c59d8aed --- /dev/null +++ b/src/boot/bless-boot-generator.c @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "efi-loader.h" +#include "generator.h" +#include "log.h" +#include "mkdir.h" +#include "special.h" +#include "string-util.h" +#include "util.h" +#include "virt.h" + +/* This generator pulls systemd-bless-boot.service into the initial transaction if the "LoaderBootCountPath" EFI + * variable is set, i.e. the system boots up with boot counting in effect, which means we should mark the boot as + * "good" if we manage to boot up far enough. */ + +static const char *arg_dest = "/tmp"; + +int main(int argc, char *argv[]) { + const char *p; + + log_setup_generator(); + + if (argc > 1 && argc != 4) { + log_error("This program takes three or no arguments."); + return EXIT_FAILURE; + } + + if (argc > 1) + arg_dest = argv[2]; + + if (in_initrd() > 0) { + log_debug("Skipping generator, running in the initrd."); + return EXIT_SUCCESS; + } + + if (detect_container() > 0) { + log_debug("Skipping generator, running in a container."); + return EXIT_SUCCESS; + } + + if (!is_efi_boot()) { + log_debug("Skipping generator, not an EFI boot."); + return EXIT_SUCCESS; + } + + if (access("/sys/firmware/efi/efivars/LoaderBootCountPath-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", F_OK) < 0) { + + if (errno == ENOENT) { + log_debug_errno(errno, "Skipping generator, not booted with boot counting in effect."); + return EXIT_SUCCESS; + } + + log_error_errno(errno, "Failed to check if LoaderBootCountPath EFI variable exists: %m"); + return EXIT_FAILURE; + } + + /* We pull this in from basic.target so that it ends up in all "regular" boot ups, but not in rescue.target or + * even emergency.target. */ + p = strjoina(arg_dest, "/" SPECIAL_BASIC_TARGET ".wants/systemd-bless-boot.service"); + (void) mkdir_parents(p, 0755); + if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-bless-boot.service", p) < 0) { + log_error_errno(errno, "Failed to create symlink '%s': %m", p); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/boot/bless-boot.c b/src/boot/bless-boot.c new file mode 100644 index 00000000..b96e1f92 --- /dev/null +++ b/src/boot/bless-boot.c @@ -0,0 +1,525 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "bootspec.h" +#include "efi-loader.h" +#include "efivars.h" +#include "fd-util.h" +#include "fs-util.h" +#include "log.h" +#include "main-func.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "terminal-util.h" +#include "util.h" +#include "verbs.h" +#include "virt.h" + +static char **arg_path = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_path, strv_freep); + +static int help(int argc, char *argv[], void *userdata) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-bless-boot.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND\n" + "\n%sMark the boot process as good or bad.%s\n" + "\nCommands:\n" + " good Mark this boot as good\n" + " bad Mark this boot as bad\n" + " indeterminate Undo any marking as good or bad\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Print version\n" + " --path=PATH Path to the $BOOT partition (may be used multiple times)\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_PATH = 0x100, + ARG_VERSION, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "path", required_argument, NULL, ARG_PATH }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + switch (c) { + + case 'h': + help(0, NULL, NULL); + return 0; + + case ARG_VERSION: + return version(); + + case ARG_PATH: + r = strv_extend(&arg_path, optarg); + if (r < 0) + return log_oom(); + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unknown option"); + } + + return 1; +} + +static int acquire_path(void) { + _cleanup_free_ char *esp_path = NULL, *xbootldr_path = NULL; + char **a; + int r; + + if (!strv_isempty(arg_path)) + return 0; + + r = find_esp_and_warn(NULL, false, &esp_path, NULL, NULL, NULL, NULL); + if (r < 0 && r != -ENOKEY) /* ENOKEY means not found, and is the only error the function won't log about on its own */ + return r; + + r = find_xbootldr_and_warn(NULL, false, &xbootldr_path, NULL); + if (r < 0 && r != -ENOKEY) + return r; + + if (!esp_path && !xbootldr_path) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), + "Couldn't find $BOOT partition. It is recommended to mount it to /boot.\n" + "Alternatively, use --path= to specify path to mount point."); + + if (esp_path) + a = strv_new(esp_path, xbootldr_path); + else + a = strv_new(xbootldr_path); + if (!a) + return log_oom(); + + strv_free_and_replace(arg_path, a); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *j; + + j = strv_join(arg_path, ":"); + log_debug("Using %s as boot loader drop-in search path.", j); + } + + return 0; +} + +static int parse_counter( + const char *path, + const char **p, + uint64_t *ret_left, + uint64_t *ret_done) { + + uint64_t left, done; + const char *z, *e; + size_t k; + int r; + + assert(path); + assert(p); + + e = *p; + assert(e); + assert(*e == '+'); + + e++; + + k = strspn(e, DIGITS); + if (k == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Can't parse empty 'tries left' counter from LoaderBootCountPath: %s", + path); + + z = strndupa(e, k); + r = safe_atou64(z, &left); + if (r < 0) + return log_error_errno(r, "Failed to parse 'tries left' counter from LoaderBootCountPath: %s", path); + + e += k; + + if (*e == '-') { + e++; + + k = strspn(e, DIGITS); + if (k == 0) /* If there's a "-" there also needs to be at least one digit */ + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Can't parse empty 'tries done' counter from LoaderBootCountPath: %s", + path); + + z = strndupa(e, k); + r = safe_atou64(z, &done); + if (r < 0) + return log_error_errno(r, "Failed to parse 'tries done' counter from LoaderBootCountPath: %s", path); + + e += k; + } else + done = 0; + + if (done == 0) + log_warning("The 'tries done' counter is currently at zero. This can't really be, after all we are running, and this boot must hence count as one. Proceeding anyway."); + + *p = e; + + if (ret_left) + *ret_left = left; + + if (ret_done) + *ret_done = done; + + return 0; +} + +static int acquire_boot_count_path( + char **ret_path, + char **ret_prefix, + uint64_t *ret_left, + uint64_t *ret_done, + char **ret_suffix) { + + _cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL; + const char *last, *e; + uint64_t left, done; + int r; + + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderBootCountPath", &path); + if (r == -ENOENT) + return -EUNATCH; /* in this case, let the caller print a message */ + if (r < 0) + return log_error_errno(r, "Failed to read LoaderBootCountPath EFI variable: %m"); + + efi_tilt_backslashes(path); + + if (!path_is_normalized(path)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Path read from LoaderBootCountPath is not normalized, refusing: %s", + path); + + if (!path_is_absolute(path)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Path read from LoaderBootCountPath is not absolute, refusing: %s", + path); + + last = last_path_component(path); + e = strrchr(last, '+'); + if (!e) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Path read from LoaderBootCountPath does not contain a counter, refusing: %s", + path); + + if (ret_prefix) { + prefix = strndup(path, e - path); + if (!prefix) + return log_oom(); + } + + r = parse_counter(path, &e, &left, &done); + if (r < 0) + return r; + + if (ret_suffix) { + suffix = strdup(e); + if (!suffix) + return log_oom(); + + *ret_suffix = TAKE_PTR(suffix); + } + + if (ret_path) + *ret_path = TAKE_PTR(path); + if (ret_prefix) + *ret_prefix = TAKE_PTR(prefix); + if (ret_left) + *ret_left = left; + if (ret_done) + *ret_done = done; + + return 0; +} + +static int make_good(const char *prefix, const char *suffix, char **ret) { + _cleanup_free_ char *good = NULL; + + assert(prefix); + assert(suffix); + assert(ret); + + /* Generate the path we'd use on good boots. This one is easy. If we are successful, we simple drop the counter + * pair entirely from the name. After all, we know all is good, and the logs will contain information about the + * tries we needed to come here, hence it's safe to drop the counters from the name. */ + + good = strjoin(prefix, suffix); + if (!good) + return -ENOMEM; + + *ret = TAKE_PTR(good); + return 0; +} + +static int make_bad(const char *prefix, uint64_t done, const char *suffix, char **ret) { + _cleanup_free_ char *bad = NULL; + + assert(prefix); + assert(suffix); + assert(ret); + + /* Generate the path we'd use on bad boots. Let's simply set the 'left' counter to zero, and keep the 'done' + * counter. The information might be interesting to boot loaders, after all. */ + + if (done == 0) { + bad = strjoin(prefix, "+0", suffix); + if (!bad) + return -ENOMEM; + } else { + if (asprintf(&bad, "%s+0-%" PRIu64 "%s", prefix, done, suffix) < 0) + return -ENOMEM; + } + + *ret = TAKE_PTR(bad); + return 0; +} + +static const char *skip_slash(const char *path) { + assert(path); + assert(path[0] == '/'); + + return path + 1; +} + +static int verb_status(int argc, char *argv[], void *userdata) { + _cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL, *good = NULL, *bad = NULL; + uint64_t left, done; + char **p; + int r; + + r = acquire_boot_count_path(&path, &prefix, &left, &done, &suffix); + if (r == -EUNATCH) { /* No boot count in place, then let's consider this a "clean" boot, as "good", "bad" or "indeterminate" don't apply. */ + puts("clean"); + return 0; + } + if (r < 0) + return r; + + r = acquire_path(); + if (r < 0) + return r; + + r = make_good(prefix, suffix, &good); + if (r < 0) + return log_oom(); + + r = make_bad(prefix, done, suffix, &bad); + if (r < 0) + return log_oom(); + + log_debug("Booted file: %s\n" + "The same modified for 'good': %s\n" + "The same modified for 'bad': %s\n", + path, + good, + bad); + + log_debug("Tries left: %" PRIu64"\n" + "Tries done: %" PRIu64"\n", + left, done); + + STRV_FOREACH(p, arg_path) { + _cleanup_close_ int fd = -1; + + fd = open(*p, O_DIRECTORY|O_CLOEXEC|O_RDONLY); + if (fd < 0) { + if (errno == ENOENT) + continue; + + return log_error_errno(errno, "Failed to open $BOOT partition '%s': %m", *p); + } + + if (faccessat(fd, skip_slash(path), F_OK, 0) >= 0) { + puts("indeterminate"); + return 0; + } + if (errno != ENOENT) + return log_error_errno(errno, "Failed to check if '%s' exists: %m", path); + + if (faccessat(fd, skip_slash(good), F_OK, 0) >= 0) { + puts("good"); + return 0; + } + + if (errno != ENOENT) + return log_error_errno(errno, "Failed to check if '%s' exists: %m", good); + + if (faccessat(fd, skip_slash(bad), F_OK, 0) >= 0) { + puts("bad"); + return 0; + } + if (errno != ENOENT) + return log_error_errno(errno, "Failed to check if '%s' exists: %m", bad); + + /* We didn't find any of the three? If so, let's try the next directory, before we give up. */ + } + + return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Couldn't determine boot state: %m"); +} + +static int verb_set(int argc, char *argv[], void *userdata) { + _cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL, *good = NULL, *bad = NULL, *parent = NULL; + const char *target, *source1, *source2; + uint64_t done; + char **p; + int r; + + r = acquire_boot_count_path(&path, &prefix, NULL, &done, &suffix); + if (r == -EUNATCH) /* acquire_boot_count_path() won't log on its own for this specific error */ + return log_error_errno(r, "Not booted with boot counting in effect."); + if (r < 0) + return r; + + r = acquire_path(); + if (r < 0) + return r; + + r = make_good(prefix, suffix, &good); + if (r < 0) + return log_oom(); + + r = make_bad(prefix, done, suffix, &bad); + if (r < 0) + return log_oom(); + + /* Figure out what rename to what */ + if (streq(argv[0], "good")) { + target = good; + source1 = path; + source2 = bad; /* Maybe this boot was previously marked as 'bad'? */ + } else if (streq(argv[0], "bad")) { + target = bad; + source1 = path; + source2 = good; /* Maybe this boot was previously marked as 'good'? */ + } else { + assert(streq(argv[0], "indeterminate")); + target = path; + source1 = good; + source2 = bad; + } + + STRV_FOREACH(p, arg_path) { + _cleanup_close_ int fd = -1; + + fd = open(*p, O_DIRECTORY|O_CLOEXEC|O_RDONLY); + if (fd < 0) + return log_error_errno(errno, "Failed to open $BOOT partition '%s': %m", *p); + + r = rename_noreplace(fd, skip_slash(source1), fd, skip_slash(target)); + if (r == -EEXIST) + goto exists; + else if (r == -ENOENT) { + + r = rename_noreplace(fd, skip_slash(source2), fd, skip_slash(target)); + if (r == -EEXIST) + goto exists; + else if (r == -ENOENT) { + + if (faccessat(fd, skip_slash(target), F_OK, 0) >= 0) /* Hmm, if we can't find either source file, maybe the destination already exists? */ + goto exists; + + if (errno != ENOENT) + return log_error_errno(errno, "Failed to determine if %s already exists: %m", target); + + /* We found none of the snippets here, try the next directory */ + continue; + } else if (r < 0) + return log_error_errno(r, "Failed to rename '%s' to '%s': %m", source2, target); + else + log_debug("Successfully renamed '%s' to '%s'.", source2, target); + + } else if (r < 0) + return log_error_errno(r, "Failed to rename '%s' to '%s': %m", source1, target); + else + log_debug("Successfully renamed '%s' to '%s'.", source1, target); + + /* First, fsync() the directory these files are located in */ + parent = dirname_malloc(target); + if (!parent) + return log_oom(); + + r = fsync_path_at(fd, skip_slash(parent)); + if (r < 0) + log_debug_errno(errno, "Failed to synchronize image directory, ignoring: %m"); + + /* Secondly, syncfs() the whole file system these files are located in */ + if (syncfs(fd) < 0) + log_debug_errno(errno, "Failed to synchronize $BOOT partition, ignoring: %m"); + + log_info("Marked boot as '%s'. (Boot attempt counter is at %" PRIu64".)", argv[0], done); + } + + log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Can't find boot counter source file for '%s': %m", target); + return 1; + +exists: + log_debug("Operation already executed before, not doing anything."); + return 0; +} + +static int run(int argc, char *argv[]) { + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status }, + { "good", VERB_ANY, 1, 0, verb_set }, + { "bad", VERB_ANY, 1, 0, verb_set }, + { "indeterminate", VERB_ANY, 1, 0, verb_set }, + {} + }; + + int r; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (detect_container() > 0) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Marking a boot is not supported in containers."); + + if (!is_efi_boot()) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Marking a boot is only supported on EFI systems."); + + return dispatch_verb(argc, argv, verbs, NULL); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/boot/boot-check-no-failures.c b/src/boot/boot-check-no-failures.c new file mode 100644 index 00000000..038ce295 --- /dev/null +++ b/src/boot/boot-check-no-failures.c @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "log.h" +#include "main-func.h" +#include "pretty-print.h" +#include "terminal-util.h" +#include "util.h" + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-boot-check-no-failures.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n" + "\n%sVerify system operational state.%s\n\n" + " -h --help Show this help\n" + " --version Print version\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_PATH = 0x100, + ARG_VERSION, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + switch (c) { + + case 'h': + help(); + return 0; + + case ARG_VERSION: + return version(); + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unknown option"); + } + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + uint32_t n; + int r; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to connect to system bus: %m"); + + r = sd_bus_get_property_trivial( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "NFailedUnits", + &error, + 'u', + &n); + if (r < 0) + return log_error_errno(r, "Failed to get failed units counter: %s", bus_error_message(&error, r)); + + if (n > 0) + log_notice("Health check: %" PRIu32 " units have failed.", n); + else + log_info("Health check: no failed units."); + + return n > 0; +} + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c new file mode 100644 index 00000000..a90502b4 --- /dev/null +++ b/src/boot/bootctl.c @@ -0,0 +1,1800 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "blkid-util.h" +#include "bootspec.h" +#include "copy.h" +#include "dirent-util.h" +#include "efi-loader.h" +#include "efivars.h" +#include "env-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "locale-util.h" +#include "main-func.h" +#include "mkdir.h" +#include "pager.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "random-util.h" +#include "rm-rf.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "umask-util.h" +#include "utf8.h" +#include "util.h" +#include "verbs.h" +#include "virt.h" + +static char *arg_esp_path = NULL; +static char *arg_xbootldr_path = NULL; +static bool arg_print_esp_path = false; +static bool arg_print_dollar_boot_path = false; +static bool arg_touch_variables = true; +static PagerFlags arg_pager_flags = 0; +static bool arg_graceful = false; + +STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep); +STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep); + +static const char *arg_dollar_boot_path(void) { + /* $BOOT shall be the XBOOTLDR partition if it exists, and otherwise the ESP */ + return arg_xbootldr_path ?: arg_esp_path; +} + +static int acquire_esp( + bool unprivileged_mode, + uint32_t *ret_part, + uint64_t *ret_pstart, + uint64_t *ret_psize, + sd_id128_t *ret_uuid) { + + char *np; + int r; + + /* Find the ESP, and log about errors. Note that find_esp_and_warn() will log in all error cases on + * its own, except for ENOKEY (which is good, we want to show our own message in that case, + * suggesting use of --esp-path=) and EACCESS (only when we request unprivileged mode; in this case + * we simply eat up the error here, so that --list and --status work too, without noise about + * this). */ + + r = find_esp_and_warn(arg_esp_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid); + if (r == -ENOKEY) + return log_error_errno(r, + "Couldn't find EFI system partition. It is recommended to mount it to /boot or /efi.\n" + "Alternatively, use --esp-path= to specify path to mount point."); + if (r < 0) + return r; + + free_and_replace(arg_esp_path, np); + log_debug("Using EFI System Partition at %s.", arg_esp_path); + + return 1; +} + +static int acquire_xbootldr(bool unprivileged_mode, sd_id128_t *ret_uuid) { + char *np; + int r; + + r = find_xbootldr_and_warn(arg_xbootldr_path, unprivileged_mode, &np, ret_uuid); + if (r == -ENOKEY) { + log_debug_errno(r, "Didn't find an XBOOTLDR partition, using the ESP as $BOOT."); + if (ret_uuid) + *ret_uuid = SD_ID128_NULL; + arg_xbootldr_path = mfree(arg_xbootldr_path); + return 0; + } + if (r < 0) + return r; + + free_and_replace(arg_xbootldr_path, np); + log_debug("Using XBOOTLDR partition at %s as $BOOT.", arg_xbootldr_path); + + return 1; +} + +/* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */ +static int get_file_version(int fd, char **v) { + struct stat st; + char *buf; + const char *s, *e; + char *x = NULL; + int r = 0; + + assert(fd >= 0); + assert(v); + + if (fstat(fd, &st) < 0) + return log_error_errno(errno, "Failed to stat EFI binary: %m"); + + r = stat_verify_regular(&st); + if (r < 0) + return log_error_errno(r, "EFI binary is not a regular file: %m"); + + if (st.st_size < 27) { + *v = NULL; + return 0; + } + + buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (buf == MAP_FAILED) + return log_error_errno(errno, "Failed to memory map EFI binary: %m"); + + s = memmem(buf, st.st_size - 8, "#### LoaderInfo: ", 17); + if (!s) + goto finish; + s += 17; + + e = memmem(s, st.st_size - (s - buf), " ####", 5); + if (!e || e - s < 3) { + r = log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Malformed version string."); + goto finish; + } + + x = strndup(s, e - s); + if (!x) { + r = log_oom(); + goto finish; + } + r = 1; + +finish: + (void) munmap(buf, st.st_size); + *v = x; + return r; +} + +static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + const char *p; + int c = 0, r; + + assert(esp_path); + assert(path); + + p = prefix_roota(esp_path, path); + d = opendir(p); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to read \"%s\": %m", p); + } + + FOREACH_DIRENT(de, d, break) { + _cleanup_free_ char *v = NULL; + _cleanup_close_ int fd = -1; + + if (!endswith_no_case(de->d_name, ".efi")) + continue; + + if (prefix && !startswith_no_case(de->d_name, prefix)) + continue; + + fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name); + + r = get_file_version(fd, &v); + if (r < 0) + return r; + if (r > 0) + printf(" File: %s/%s/%s (%s%s%s)\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), path, de->d_name, ansi_highlight(), v, ansi_normal()); + else + printf(" File: %s/%s/%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), path, de->d_name); + + c++; + } + + return c; +} + +static int status_binaries(const char *esp_path, sd_id128_t partition) { + int r; + + printf("Available Boot Loaders on ESP:\n"); + + if (!esp_path) { + printf(" ESP: Cannot find or access mount point of ESP.\n\n"); + return -ENOENT; + } + + printf(" ESP: %s", esp_path); + if (!sd_id128_is_null(partition)) + printf(" (/dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR ")", SD_ID128_FORMAT_VAL(partition)); + printf("\n"); + + r = enumerate_binaries(esp_path, "EFI/systemd", NULL); + if (r < 0) + goto finish; + if (r == 0) + log_info("systemd-boot not installed in ESP."); + + r = enumerate_binaries(esp_path, "EFI/BOOT", "boot"); + if (r < 0) + goto finish; + if (r == 0) + log_info("No default/fallback boot loader installed in ESP."); + + r = 0; + +finish: + printf("\n"); + return r; +} + +static int print_efi_option(uint16_t id, bool in_order) { + _cleanup_free_ char *title = NULL; + _cleanup_free_ char *path = NULL; + sd_id128_t partition; + bool active; + int r = 0; + + r = efi_get_boot_option(id, &title, &partition, &path, &active); + if (r < 0) + return r; + + /* print only configured entries with partition information */ + if (!path || sd_id128_is_null(partition)) + return 0; + + efi_tilt_backslashes(path); + + printf(" Title: %s%s%s\n", ansi_highlight(), strna(title), ansi_normal()); + printf(" ID: 0x%04X\n", id); + printf(" Status: %sactive%s\n", active ? "" : "in", in_order ? ", boot-order" : ""); + printf(" Partition: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n", + SD_ID128_FORMAT_VAL(partition)); + printf(" File: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), path); + printf("\n"); + + return 0; +} + +static int status_variables(void) { + _cleanup_free_ uint16_t *options = NULL, *order = NULL; + int n_options, n_order, i; + + n_options = efi_get_boot_options(&options); + if (n_options == -ENOENT) + return log_error_errno(n_options, + "Failed to access EFI variables, efivarfs" + " needs to be available at /sys/firmware/efi/efivars/."); + if (n_options < 0) + return log_error_errno(n_options, "Failed to read EFI boot entries: %m"); + + n_order = efi_get_boot_order(&order); + if (n_order == -ENOENT) + n_order = 0; + else if (n_order < 0) + return log_error_errno(n_order, "Failed to read EFI boot order: %m"); + + /* print entries in BootOrder first */ + printf("Boot Loaders Listed in EFI Variables:\n"); + for (i = 0; i < n_order; i++) + print_efi_option(order[i], true); + + /* print remaining entries */ + for (i = 0; i < n_options; i++) { + int j; + + for (j = 0; j < n_order; j++) + if (options[i] == order[j]) + goto next_option; + + print_efi_option(options[i], false); + + next_option: + continue; + } + + return 0; +} + +static int boot_entry_file_check(const char *root, const char *p) { + _cleanup_free_ char *path; + + path = path_join(root, p); + if (!path) + return log_oom(); + + if (access(path, F_OK) < 0) + return -errno; + + return 0; +} + +static void boot_entry_file_list(const char *field, const char *root, const char *p, int *ret_status) { + int status = boot_entry_file_check(root, p); + + printf("%13s%s ", strempty(field), field ? ":" : " "); + if (status < 0) { + errno = -status; + printf("%s%s%s (%m)\n", ansi_highlight_red(), p, ansi_normal()); + } else + printf("%s\n", p); + + if (*ret_status == 0 && status < 0) + *ret_status = status; +} + +static int boot_entry_show(const BootEntry *e, bool show_as_default) { + int status = 0; + + /* Returns 0 on success, negative on processing error, and positive if something is wrong with the + boot entry itself. */ + + assert(e); + + printf(" title: %s%s%s" "%s%s%s\n", + ansi_highlight(), boot_entry_title(e), ansi_normal(), + ansi_highlight_green(), show_as_default ? " (default)" : "", ansi_normal()); + + if (e->id) + printf(" id: %s\n", e->id); + if (e->path) { + _cleanup_free_ char *link = NULL; + + /* Let's urlify the link to make it easy to view in an editor, but only if it is a text + * file. Unified images are binary ELFs, and EFI variables are not pure text either. */ + if (e->type == BOOT_ENTRY_CONF) + (void) terminal_urlify_path(e->path, NULL, &link); + + printf(" source: %s\n", link ?: e->path); + } + if (e->version) + printf(" version: %s\n", e->version); + if (e->machine_id) + printf(" machine-id: %s\n", e->machine_id); + if (e->architecture) + printf(" architecture: %s\n", e->architecture); + if (e->kernel) + boot_entry_file_list("linux", e->root, e->kernel, &status); + + char **s; + STRV_FOREACH(s, e->initrd) + boot_entry_file_list(s == e->initrd ? "initrd" : NULL, + e->root, + *s, + &status); + if (!strv_isempty(e->options)) { + _cleanup_free_ char *t = NULL, *t2 = NULL; + _cleanup_strv_free_ char **ts = NULL; + + t = strv_join(e->options, " "); + if (!t) + return log_oom(); + + ts = strv_split_newlines(t); + if (!ts) + return log_oom(); + + t2 = strv_join(ts, "\n "); + if (!t2) + return log_oom(); + + printf(" options: %s\n", t2); + } + if (e->device_tree) + boot_entry_file_list("devicetree", e->root, e->device_tree, &status); + + return -status; +} + +static int status_entries( + const char *esp_path, + sd_id128_t esp_partition_uuid, + const char *xbootldr_path, + sd_id128_t xbootldr_partition_uuid) { + + _cleanup_(boot_config_free) BootConfig config = {}; + sd_id128_t dollar_boot_partition_uuid; + const char *dollar_boot_path; + int r; + + assert(esp_path || xbootldr_path); + + if (xbootldr_path) { + dollar_boot_path = xbootldr_path; + dollar_boot_partition_uuid = xbootldr_partition_uuid; + } else { + dollar_boot_path = esp_path; + dollar_boot_partition_uuid = esp_partition_uuid; + } + + printf("Boot Loader Entries:\n" + " $BOOT: %s", dollar_boot_path); + if (!sd_id128_is_null(dollar_boot_partition_uuid)) + printf(" (/dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR ")", + SD_ID128_FORMAT_VAL(dollar_boot_partition_uuid)); + printf("\n\n"); + + r = boot_entries_load_config(esp_path, xbootldr_path, &config); + if (r < 0) + return r; + + if (config.default_entry < 0) + printf("%zu entries, no entry could be determined as default.\n", config.n_entries); + else { + printf("Default Boot Loader Entry:\n"); + + r = boot_entry_show(config.entries + config.default_entry, false); + if (r > 0) + /* < 0 is already logged by the function itself, let's just emit an extra warning if + the default entry is broken */ + printf("\nWARNING: default boot entry is broken\n"); + } + + return 0; +} + +static int compare_product(const char *a, const char *b) { + size_t x, y; + + assert(a); + assert(b); + + x = strcspn(a, " "); + y = strcspn(b, " "); + if (x != y) + return x < y ? -1 : x > y ? 1 : 0; + + return strncmp(a, b, x); +} + +static int compare_version(const char *a, const char *b) { + assert(a); + assert(b); + + a += strcspn(a, " "); + a += strspn(a, " "); + b += strcspn(b, " "); + b += strspn(b, " "); + + return strverscmp(a, b); +} + +static int version_check(int fd_from, const char *from, int fd_to, const char *to) { + _cleanup_free_ char *a = NULL, *b = NULL; + int r; + + assert(fd_from >= 0); + assert(from); + assert(fd_to >= 0); + assert(to); + + r = get_file_version(fd_from, &a); + if (r < 0) + return r; + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Source file \"%s\" does not carry version information!", + from); + + r = get_file_version(fd_to, &b); + if (r < 0) + return r; + if (r == 0 || compare_product(a, b) != 0) + return log_notice_errno(SYNTHETIC_ERRNO(EEXIST), + "Skipping \"%s\", since it's owned by another boot loader.", + to); + + if (compare_version(a, b) < 0) + return log_warning_errno(SYNTHETIC_ERRNO(ESTALE), "Skipping \"%s\", since a newer boot loader version exists already.", to); + + return 0; +} + +static int copy_file_with_version_check(const char *from, const char *to, bool force) { + _cleanup_close_ int fd_from = -1, fd_to = -1; + _cleanup_free_ char *t = NULL; + int r; + + fd_from = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd_from < 0) + return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", from); + + if (!force) { + fd_to = open(to, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd_to < 0) { + if (errno != -ENOENT) + return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", to); + } else { + r = version_check(fd_from, from, fd_to, to); + if (r < 0) + return r; + + if (lseek(fd_from, 0, SEEK_SET) == (off_t) -1) + return log_error_errno(errno, "Failed to seek in \"%s\": %m", from); + + fd_to = safe_close(fd_to); + } + } + + r = tempfn_random(to, NULL, &t); + if (r < 0) + return log_oom(); + + RUN_WITH_UMASK(0000) { + fd_to = open(t, O_WRONLY|O_CREAT|O_CLOEXEC|O_EXCL|O_NOFOLLOW, 0644); + if (fd_to < 0) + return log_error_errno(errno, "Failed to open \"%s\" for writing: %m", t); + } + + r = copy_bytes(fd_from, fd_to, (uint64_t) -1, COPY_REFLINK); + if (r < 0) { + (void) unlink(t); + return log_error_errno(r, "Failed to copy data from \"%s\" to \"%s\": %m", from, t); + } + + (void) copy_times(fd_from, fd_to, 0); + + if (fsync(fd_to) < 0) { + (void) unlink_noerrno(t); + return log_error_errno(errno, "Failed to copy data from \"%s\" to \"%s\": %m", from, t); + } + + (void) fsync_directory_of_file(fd_to); + + if (renameat(AT_FDCWD, t, AT_FDCWD, to) < 0) { + (void) unlink_noerrno(t); + return log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", t, to); + } + + log_info("Copied \"%s\" to \"%s\".", from, to); + + return 0; +} + +static int mkdir_one(const char *prefix, const char *suffix) { + _cleanup_free_ char *p = NULL; + + p = path_join(prefix, suffix); + if (mkdir(p, 0700) < 0) { + if (errno != EEXIST) + return log_error_errno(errno, "Failed to create \"%s\": %m", p); + } else + log_info("Created \"%s\".", p); + + return 0; +} + +static const char *const esp_subdirs[] = { + /* The directories to place in the ESP */ + "EFI", + "EFI/systemd", + "EFI/BOOT", + "loader", + NULL +}; + +static const char *const dollar_boot_subdirs[] = { + /* The directories to place in the XBOOTLDR partition or the ESP, depending what exists */ + "loader", + "loader/entries", /* Type #1 entries */ + "EFI", + "EFI/Linux", /* Type #2 entries */ + NULL +}; + +static int create_subdirs(const char *root, const char * const *subdirs) { + const char *const *i; + int r; + + STRV_FOREACH(i, subdirs) { + r = mkdir_one(root, *i); + if (r < 0) + return r; + } + + return 0; +} + +static int copy_one_file(const char *esp_path, const char *name, bool force) { + const char *e; + char *p, *q; + int r; + + p = strjoina(BOOTLIBDIR "/", name); + q = strjoina(esp_path, "/EFI/systemd/", name); + r = copy_file_with_version_check(p, q, force); + + e = startswith(name, "systemd-boot"); + if (e) { + int k; + char *v; + + /* Create the EFI default boot loader name (specified for removable devices) */ + v = strjoina(esp_path, "/EFI/BOOT/BOOT", e); + ascii_strupper(strrchr(v, '/') + 1); + + k = copy_file_with_version_check(p, v, force); + if (k < 0 && r == 0) + r = k; + } + + return r; +} + +static int install_binaries(const char *esp_path, bool force) { + struct dirent *de; + _cleanup_closedir_ DIR *d = NULL; + int r = 0; + + d = opendir(BOOTLIBDIR); + if (!d) + return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m"); + + FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read \""BOOTLIBDIR"\": %m")) { + int k; + + if (!endswith_no_case(de->d_name, ".efi")) + continue; + + k = copy_one_file(esp_path, de->d_name, force); + if (k < 0 && r == 0) + r = k; + } + + return r; +} + +static bool same_entry(uint16_t id, sd_id128_t uuid, const char *path) { + _cleanup_free_ char *opath = NULL; + sd_id128_t ouuid; + int r; + + r = efi_get_boot_option(id, NULL, &ouuid, &opath, NULL); + if (r < 0) + return false; + if (!sd_id128_equal(uuid, ouuid)) + return false; + if (!streq_ptr(path, opath)) + return false; + + return true; +} + +static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) { + _cleanup_free_ uint16_t *options = NULL; + int n, i; + + n = efi_get_boot_options(&options); + if (n < 0) + return n; + + /* find already existing systemd-boot entry */ + for (i = 0; i < n; i++) + if (same_entry(options[i], uuid, path)) { + *id = options[i]; + return 1; + } + + /* find free slot in the sorted BootXXXX variable list */ + for (i = 0; i < n; i++) + if (i != options[i]) { + *id = i; + return 1; + } + + /* use the next one */ + if (i == 0xffff) + return -ENOSPC; + *id = i; + return 0; +} + +static int insert_into_order(uint16_t slot, bool first) { + _cleanup_free_ uint16_t *order = NULL; + uint16_t *t; + int n, i; + + n = efi_get_boot_order(&order); + if (n <= 0) + /* no entry, add us */ + return efi_set_boot_order(&slot, 1); + + /* are we the first and only one? */ + if (n == 1 && order[0] == slot) + return 0; + + /* are we already in the boot order? */ + for (i = 0; i < n; i++) { + if (order[i] != slot) + continue; + + /* we do not require to be the first one, all is fine */ + if (!first) + return 0; + + /* move us to the first slot */ + memmove(order + 1, order, i * sizeof(uint16_t)); + order[0] = slot; + return efi_set_boot_order(order, n); + } + + /* extend array */ + t = reallocarray(order, n + 1, sizeof(uint16_t)); + if (!t) + return -ENOMEM; + order = t; + + /* add us to the top or end of the list */ + if (first) { + memmove(order + 1, order, n * sizeof(uint16_t)); + order[0] = slot; + } else + order[n] = slot; + + return efi_set_boot_order(order, n + 1); +} + +static int remove_from_order(uint16_t slot) { + _cleanup_free_ uint16_t *order = NULL; + int n, i; + + n = efi_get_boot_order(&order); + if (n <= 0) + return n; + + for (i = 0; i < n; i++) { + if (order[i] != slot) + continue; + + if (i + 1 < n) + memmove(order + i, order + i+1, (n - i) * sizeof(uint16_t)); + return efi_set_boot_order(order, n - 1); + } + + return 0; +} + +static int install_variables(const char *esp_path, + uint32_t part, uint64_t pstart, uint64_t psize, + sd_id128_t uuid, const char *path, + bool first) { + const char *p; + uint16_t slot; + int r; + + if (!is_efi_boot()) { + log_warning("Not booted with EFI, skipping EFI variable setup."); + return 0; + } + + p = prefix_roota(esp_path, path); + if (access(p, F_OK) < 0) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Cannot access \"%s\": %m", p); + } + + r = find_slot(uuid, path, &slot); + if (r < 0) + return log_error_errno(r, + r == -ENOENT ? + "Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?" : + "Failed to determine current boot order: %m"); + + if (first || r == 0) { + r = efi_add_boot_option(slot, "Linux Boot Manager", + part, pstart, psize, + uuid, path); + if (r < 0) + return log_error_errno(r, "Failed to create EFI Boot variable entry: %m"); + + log_info("Created EFI boot entry \"Linux Boot Manager\"."); + } + + return insert_into_order(slot, first); +} + +static int remove_boot_efi(const char *esp_path) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + const char *p; + int r, c = 0; + + p = prefix_roota(esp_path, "/EFI/BOOT"); + d = opendir(p); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open directory \"%s\": %m", p); + } + + FOREACH_DIRENT(de, d, break) { + _cleanup_close_ int fd = -1; + _cleanup_free_ char *v = NULL; + + if (!endswith_no_case(de->d_name, ".efi")) + continue; + + if (!startswith_no_case(de->d_name, "boot")) + continue; + + fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return log_error_errno(errno, "Failed to open \"%s/%s\" for reading: %m", p, de->d_name); + + r = get_file_version(fd, &v); + if (r < 0) + return r; + if (r > 0 && startswith(v, "systemd-boot ")) { + r = unlinkat(dirfd(d), de->d_name, 0); + if (r < 0) + return log_error_errno(errno, "Failed to remove \"%s/%s\": %m", p, de->d_name); + + log_info("Removed \"%s/%s\".", p, de->d_name); + } + + c++; + } + + return c; +} + +static int rmdir_one(const char *prefix, const char *suffix) { + const char *p; + + p = prefix_roota(prefix, suffix); + if (rmdir(p) < 0) { + bool ignore = IN_SET(errno, ENOENT, ENOTEMPTY); + + log_full_errno(ignore ? LOG_DEBUG : LOG_ERR, errno, + "Failed to remove directory \"%s\": %m", p); + if (!ignore) + return -errno; + } else + log_info("Removed \"%s\".", p); + + return 0; +} + +static int remove_subdirs(const char *root, const char *const *subdirs) { + int r, q; + + /* We use recursion here to destroy the directories in reverse order. Which should be safe given how + * short the array is. */ + + if (!subdirs[0]) /* A the end of the list */ + return 0; + + r = remove_subdirs(root, subdirs + 1); + q = rmdir_one(root, subdirs[0]); + + return r < 0 ? r : q; +} + +static int remove_machine_id_directory(const char *root, sd_id128_t machine_id) { + char buf[SD_ID128_STRING_MAX]; + + assert(root); + + return rmdir_one(root, sd_id128_to_string(machine_id, buf)); +} + +static int remove_binaries(const char *esp_path) { + const char *p; + int r, q; + + p = prefix_roota(esp_path, "/EFI/systemd"); + r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL); + + q = remove_boot_efi(esp_path); + if (q < 0 && r == 0) + r = q; + + return r; +} + +static int remove_file(const char *root, const char *file) { + const char *p; + + assert(root); + assert(file); + + p = prefix_roota(root, file); + if (unlink(p) < 0) { + log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, + "Failed to unlink file \"%s\": %m", p); + + return errno == ENOENT ? 0 : -errno; + } + + log_info("Removed \"%s\".", p); + return 1; +} + +static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) { + uint16_t slot; + int r; + + if (!is_efi_boot()) + return 0; + + r = find_slot(uuid, path, &slot); + if (r != 1) + return 0; + + r = efi_remove_boot_option(slot); + if (r < 0) + return r; + + if (in_order) + return remove_from_order(slot); + + return 0; +} + +static int remove_loader_variables(void) { + const char *p; + int r = 0; + + /* Remove all persistent loader variables we define */ + + FOREACH_STRING(p, + "LoaderConfigTimeout", + "LoaderConfigTimeoutOneShot", + "LoaderEntryDefault", + "LoaderEntryOneShot", + "LoaderSystemToken") { + + int q; + + q = efi_set_variable(EFI_VENDOR_LOADER, p, NULL, 0); + if (q == -ENOENT) + continue; + if (q < 0) { + log_warning_errno(q, "Failed to remove %s variable: %m", p); + if (r >= 0) + r = q; + } else + log_info("Removed EFI variable %s.", p); + } + + return r; +} + +static int install_loader_config(const char *esp_path, sd_id128_t machine_id) { + char machine_string[SD_ID128_STRING_MAX]; + _cleanup_(unlink_and_freep) char *t = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *p; + int r, fd; + + p = prefix_roota(esp_path, "/loader/loader.conf"); + if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */ + return 0; + + fd = open_tmpfile_linkable(p, O_WRONLY|O_CLOEXEC, &t); + if (fd < 0) + return log_error_errno(fd, "Failed to open \"%s\" for writing: %m", p); + + f = fdopen(fd, "w"); + if (!f) { + safe_close(fd); + return log_oom(); + } + + fprintf(f, "#timeout 3\n" + "#console-mode keep\n" + "default %s-*\n", sd_id128_to_string(machine_id, machine_string)); + + r = fflush_sync_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write \"%s\": %m", p); + + r = link_tmpfile(fd, t, p); + if (r == -EEXIST) + return 0; /* Silently skip creation if the file exists now (recheck) */ + if (r < 0) + return log_error_errno(r, "Failed to move \"%s\" into place: %m", p); + + t = mfree(t); + return 1; +} + +static int install_machine_id_directory(const char *root, sd_id128_t machine_id) { + char buf[SD_ID128_STRING_MAX]; + + assert(root); + + return mkdir_one(root, sd_id128_to_string(machine_id, buf)); +} + +static int help(int argc, char *argv[], void *userdata) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("bootctl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n" + "\n%sInstall/update/remove the systemd-boot EFI boot manager and list/select entries.%s\n" + "\nBoot Loader Commands:\n" + " status Show status of installed systemd-boot and EFI variables\n" + " install Install systemd-boot to the ESP and EFI variables\n" + " update Update systemd-boot in the ESP and EFI variables\n" + " remove Remove systemd-boot from the ESP and EFI variables\n" + " is-installed Test whether systemd-boot is installed in the ESP\n" + " random-seed Initialize random seed in ESP and EFI variables\n" + " systemd-efi-options Query or set system options string in EFI variable\n" + "\nBoot Loader Entries Commands:\n" + " list List boot loader entries\n" + " set-default ID Set default boot loader entry\n" + " set-oneshot ID Set default boot loader entry, for next boot only\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Print version\n" + " --esp-path=PATH Path to the EFI System Partition (ESP)\n" + " --boot-path=PATH Path to the $BOOT partition\n" + " -p --print-esp-path Print path to the EFI System Partition\n" + " -x --print-boot-path Print path to the $BOOT partition\n" + " --no-variables Don't touch EFI variables\n" + " --no-pager Do not pipe output into a pager\n" + " --graceful Don't fail when the ESP cannot be found or EFI\n" + " variables cannot be written\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_ESP_PATH = 0x100, + ARG_BOOT_PATH, + ARG_VERSION, + ARG_NO_VARIABLES, + ARG_NO_PAGER, + ARG_GRACEFUL, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "esp-path", required_argument, NULL, ARG_ESP_PATH }, + { "path", required_argument, NULL, ARG_ESP_PATH }, /* Compatibility alias */ + { "boot-path", required_argument, NULL, ARG_BOOT_PATH }, + { "print-esp-path", no_argument, NULL, 'p' }, + { "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */ + { "print-boot-path", no_argument, NULL, 'x' }, + { "no-variables", no_argument, NULL, ARG_NO_VARIABLES }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "graceful", no_argument, NULL, ARG_GRACEFUL }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hpx", options, NULL)) >= 0) + switch (c) { + + case 'h': + help(0, NULL, NULL); + return 0; + + case ARG_VERSION: + return version(); + + case ARG_ESP_PATH: + r = free_and_strdup(&arg_esp_path, optarg); + if (r < 0) + return log_oom(); + break; + + case ARG_BOOT_PATH: + r = free_and_strdup(&arg_xbootldr_path, optarg); + if (r < 0) + return log_oom(); + break; + + case 'p': + if (arg_print_dollar_boot_path) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--print-boot-path/-x cannot be combined with --print-esp-path/-p"); + arg_print_esp_path = true; + break; + + case 'x': + if (arg_print_esp_path) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--print-boot-path/-x cannot be combined with --print-esp-path/-p"); + arg_print_dollar_boot_path = true; + break; + + case ARG_NO_VARIABLES: + arg_touch_variables = false; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_GRACEFUL: + arg_graceful = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unknown option"); + } + + return 1; +} + +static void read_loader_efi_var(const char *name, char **var) { + int r; + + r = efi_get_variable_string(EFI_VENDOR_LOADER, name, var); + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to read EFI variable %s: %m", name); +} + +static int verb_status(int argc, char *argv[], void *userdata) { + sd_id128_t esp_uuid = SD_ID128_NULL, xbootldr_uuid = SD_ID128_NULL; + int r, k; + + r = acquire_esp(geteuid() != 0, NULL, NULL, NULL, &esp_uuid); + if (arg_print_esp_path) { + if (r == -EACCES) /* If we couldn't acquire the ESP path, log about access errors (which is the only + * error the find_esp_and_warn() won't log on its own) */ + return log_error_errno(r, "Failed to determine ESP location: %m"); + if (r < 0) + return r; + + puts(arg_esp_path); + } + + r = acquire_xbootldr(geteuid() != 0, &xbootldr_uuid); + if (arg_print_dollar_boot_path) { + if (r == -EACCES) + return log_error_errno(r, "Failed to determine XBOOTLDR location: %m"); + if (r < 0) + return r; + + const char *path = arg_dollar_boot_path(); + if (!path) + return log_error_errno(SYNTHETIC_ERRNO(EACCES), "Failed to determine XBOOTLDR location: %m"); + + puts(path); + } + + if (arg_print_esp_path || arg_print_dollar_boot_path) + return 0; + + r = 0; /* If we couldn't determine the path, then don't consider that a problem from here on, just show what we + * can show */ + + (void) pager_open(arg_pager_flags); + + if (is_efi_boot()) { + static const struct { + uint64_t flag; + const char *name; + } flags[] = { + { EFI_LOADER_FEATURE_BOOT_COUNTING, "Boot counting" }, + { EFI_LOADER_FEATURE_CONFIG_TIMEOUT, "Menu timeout control" }, + { EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT, "One-shot menu timeout control" }, + { EFI_LOADER_FEATURE_ENTRY_DEFAULT, "Default entry control" }, + { EFI_LOADER_FEATURE_ENTRY_ONESHOT, "One-shot entry control" }, + { EFI_LOADER_FEATURE_XBOOTLDR, "Support for XBOOTLDR partition" }, + { EFI_LOADER_FEATURE_RANDOM_SEED, "Support for passing random seed to OS" }, + }; + + _cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL, *stub = NULL; + sd_id128_t loader_part_uuid = SD_ID128_NULL; + uint64_t loader_features = 0; + size_t i; + + read_loader_efi_var("LoaderFirmwareType", &fw_type); + read_loader_efi_var("LoaderFirmwareInfo", &fw_info); + read_loader_efi_var("LoaderInfo", &loader); + read_loader_efi_var("StubInfo", &stub); + read_loader_efi_var("LoaderImageIdentifier", &loader_path); + (void) efi_loader_get_features(&loader_features); + + if (loader_path) + efi_tilt_backslashes(loader_path); + + k = efi_loader_get_device_part_uuid(&loader_part_uuid); + if (k < 0 && k != -ENOENT) + r = log_warning_errno(k, "Failed to read EFI variable LoaderDevicePartUUID: %m"); + + printf("System:\n"); + printf(" Firmware: %s%s (%s)%s\n", ansi_highlight(), strna(fw_type), strna(fw_info), ansi_normal()); + printf(" Secure Boot: %sd\n", enable_disable(is_efi_secure_boot())); + printf(" Setup Mode: %s\n", is_efi_secure_boot_setup_mode() ? "setup" : "user"); + printf("\n"); + + printf("Current Boot Loader:\n"); + printf(" Product: %s%s%s\n", ansi_highlight(), strna(loader), ansi_normal()); + + for (i = 0; i < ELEMENTSOF(flags); i++) { + + if (i == 0) + printf(" Features: "); + else + printf(" "); + + if (FLAGS_SET(loader_features, flags[i].flag)) + printf("%s%s%s %s\n", ansi_highlight_green(), special_glyph(SPECIAL_GLYPH_CHECK_MARK), ansi_normal(), flags[i].name); + else + printf("%s%s%s %s\n", ansi_highlight_red(), special_glyph(SPECIAL_GLYPH_CROSS_MARK), ansi_normal(), flags[i].name); + } + + if (stub) + printf(" Stub: %s\n", stub); + if (!sd_id128_is_null(loader_part_uuid)) + printf(" ESP: /dev/disk/by-partuuid/" SD_ID128_UUID_FORMAT_STR "\n", + SD_ID128_FORMAT_VAL(loader_part_uuid)); + else + printf(" ESP: n/a\n"); + printf(" File: %s%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), strna(loader_path)); + printf("\n"); + + printf("Random Seed:\n"); + printf(" Passed to OS: %s\n", yes_no(access("/sys/firmware/efi/efivars/LoaderRandomSeed-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", F_OK) >= 0)); + printf(" System Token: %s\n", access("/sys/firmware/efi/efivars/LoaderSystemToken-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", F_OK) >= 0 ? "set" : "not set"); + + if (arg_esp_path) { + _cleanup_free_ char *p = NULL; + + p = path_join(arg_esp_path, "/loader/random-seed"); + if (!p) + return log_oom(); + + printf(" Exists: %s\n", yes_no(access(p, F_OK) >= 0)); + } + + printf("\n"); + } else + printf("System:\n Not booted with EFI\n\n"); + + if (arg_esp_path) { + k = status_binaries(arg_esp_path, esp_uuid); + if (k < 0) + r = k; + } + + if (is_efi_boot()) { + k = status_variables(); + if (k < 0) + r = k; + } + + if (arg_esp_path || arg_xbootldr_path) { + k = status_entries(arg_esp_path, esp_uuid, arg_xbootldr_path, xbootldr_uuid); + if (k < 0) + r = k; + } + + return r; +} + +static int verb_list(int argc, char *argv[], void *userdata) { + _cleanup_(boot_config_free) BootConfig config = {}; + int r; + + /* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn + * off logging about access errors and turn off potentially privileged device probing. Here we're interested in + * the latter but not the former, hence request the mode, and log about EACCES. */ + + r = acquire_esp(geteuid() != 0, NULL, NULL, NULL, NULL); + if (r == -EACCES) /* We really need the ESP path for this call, hence also log about access errors */ + return log_error_errno(r, "Failed to determine ESP: %m"); + if (r < 0) + return r; + + r = acquire_xbootldr(geteuid() != 0, NULL); + if (r == -EACCES) + return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m"); + if (r < 0) + return r; + + r = boot_entries_load_config(arg_esp_path, arg_xbootldr_path, &config); + if (r < 0) + return r; + + (void) boot_entries_augment_from_loader(&config, false); + + if (config.n_entries == 0) + log_info("No boot loader entries found."); + else { + size_t n; + + (void) pager_open(arg_pager_flags); + + printf("Boot Loader Entries:\n"); + + for (n = 0; n < config.n_entries; n++) { + r = boot_entry_show(config.entries + n, n == (size_t) config.default_entry); + if (r < 0) + return r; + + if (n+1 < config.n_entries) + putchar('\n'); + } + } + + return 0; +} + +static int install_random_seed(const char *esp) { + _cleanup_(unlink_and_freep) char *tmp = NULL; + _cleanup_free_ void *buffer = NULL; + _cleanup_free_ char *path = NULL; + _cleanup_close_ int fd = -1; + size_t sz, token_size; + ssize_t n; + int r; + + assert(esp); + + path = path_join(esp, "/loader/random-seed"); + if (!path) + return log_oom(); + + sz = random_pool_size(); + + buffer = malloc(sz); + if (!buffer) + return log_oom(); + + r = genuine_random_bytes(buffer, sz, RANDOM_BLOCK); + if (r < 0) + return log_error_errno(r, "Failed to acquire random seed: %m"); + + /* Normally create_subdirs() should already have created everything we need, but in case "bootctl + * random-seed" is called we want to just create the minimum we need for it, and not the full + * list. */ + r = mkdir_parents(path, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create parent directory for %s: %m", path); + + r = tempfn_random(path, "bootctl", &tmp); + if (r < 0) + return log_oom(); + + fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|O_WRONLY|O_CLOEXEC, 0600); + if (fd < 0) { + tmp = mfree(tmp); + return log_error_errno(fd, "Failed to open random seed file for writing: %m"); + } + + n = write(fd, buffer, sz); + if (n < 0) + return log_error_errno(errno, "Failed to write random seed file: %m"); + if ((size_t) n != sz) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write while writing random seed file."); + + if (rename(tmp, path) < 0) + return log_error_errno(r, "Failed to move random seed file into place: %m"); + + tmp = mfree(tmp); + + log_info("Random seed file %s successfully written (%zu bytes).", path, sz); + + if (!arg_touch_variables) + return 0; + + if (!is_efi_boot()) { + log_notice("Not booted with EFI, skipping EFI variable setup."); + return 0; + } + + r = getenv_bool("SYSTEMD_WRITE_SYSTEM_TOKEN"); + if (r < 0) { + if (r != -ENXIO) + log_warning_errno(r, "Failed to parse $SYSTEMD_WRITE_SYSTEM_TOKEN, ignoring."); + + if (detect_vm() > 0) { + /* Let's not write a system token if we detect we are running in a VM + * environment. Why? Our default security model for the random seed uses the system + * token as a mechanism to ensure we are not vulnerable to golden master sloppiness + * issues, i.e. that people initialize the random seed file, then copy the image to + * many systems and end up with the same random seed in each that is assumed to be + * valid but in reality is the same for all machines. By storing a system token in + * the EFI variable space we can make sure that even though the random seeds on disk + * are all the same they will be different on each system under the assumption that + * the EFI variable space is maintained separate from the random seed storage. That + * is generally the case on physical systems, as the ESP is stored on persistant + * storage, and the EFI variables in NVRAM. However in virtualized environments this + * is generally not true: the EFI variable set is typically stored along with the + * disk image itself. For example, using the OVMF EFI firmware the EFI variables are + * stored in a file in the ESP itself. */ + + log_notice("Not installing system token, since we are running in a virtualized environment."); + return 0; + } + } else if (r == 0) { + log_notice("Not writing system token, because $SYSTEMD_WRITE_SYSTEM_TOKEN is set to false."); + return 0; + } + + r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderSystemToken", NULL, NULL, &token_size); + if (r < 0) { + if (r != -ENOENT) + return log_error_errno(r, "Failed to test system token validity: %m"); + } else { + if (token_size >= sz) { + /* Let's avoid writes if we can, and initialize this only once. */ + log_debug("System token already written, not updating."); + return 0; + } + + log_debug("Existing system token size (%zu) does not match our expectations (%zu), replacing.", token_size, sz); + } + + r = genuine_random_bytes(buffer, sz, RANDOM_BLOCK); + if (r < 0) + return log_error_errno(r, "Failed to acquire random seed: %m"); + + /* Let's write this variable with an umask in effect, so that unprivileged users can't see the token + * and possibly get identification information or too much insight into the kernel's entropy pool + * state. */ + RUN_WITH_UMASK(0077) { + r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderSystemToken", buffer, sz); + if (r < 0) { + if (!arg_graceful) + return log_error_errno(r, "Failed to write 'LoaderSystemToken' EFI variable: %m"); + + if (r == -EINVAL) + log_warning_errno(r, "Unable to write 'LoaderSystemToken' EFI variable (firmware problem?), ignoring: %m"); + else + log_warning_errno(r, "Unable to write 'LoaderSystemToken' EFI variable, ignoring: %m"); + } else + log_info("Successfully initialized system token in EFI variable with %zu bytes.", sz); + } + + return 0; +} + +static int sync_everything(void) { + int ret = 0, k; + + if (arg_esp_path) { + k = syncfs_path(AT_FDCWD, arg_esp_path); + if (k < 0) + ret = log_error_errno(k, "Failed to synchronize the ESP '%s': %m", arg_esp_path); + } + + if (arg_xbootldr_path) { + k = syncfs_path(AT_FDCWD, arg_xbootldr_path); + if (k < 0) + ret = log_error_errno(k, "Failed to synchronize $BOOT '%s': %m", arg_xbootldr_path); + } + + return ret; +} + +static int verb_install(int argc, char *argv[], void *userdata) { + sd_id128_t uuid = SD_ID128_NULL; + uint64_t pstart = 0, psize = 0; + uint32_t part = 0; + sd_id128_t machine_id; + bool install; + int r; + + r = acquire_esp(false, &part, &pstart, &psize, &uuid); + if (r < 0) + return r; + + r = acquire_xbootldr(false, NULL); + if (r < 0) + return r; + + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return log_error_errno(r, "Failed to get machine id: %m"); + + install = streq(argv[0], "install"); + + RUN_WITH_UMASK(0002) { + if (install) { + /* Don't create any of these directories when we are just updating. When we update + * we'll drop-in our files (unless there are newer ones already), but we won't create + * the directories for them in the first place. */ + r = create_subdirs(arg_esp_path, esp_subdirs); + if (r < 0) + return r; + + r = create_subdirs(arg_dollar_boot_path(), dollar_boot_subdirs); + if (r < 0) + return r; + } + + r = install_binaries(arg_esp_path, install); + if (r < 0) + return r; + + if (install) { + r = install_loader_config(arg_esp_path, machine_id); + if (r < 0) + return r; + + r = install_machine_id_directory(arg_dollar_boot_path(), machine_id); + if (r < 0) + return r; + + r = install_random_seed(arg_esp_path); + if (r < 0) + return r; + } + } + + (void) sync_everything(); + + if (arg_touch_variables) + r = install_variables(arg_esp_path, + part, pstart, psize, uuid, + "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", + install); + + return r; +} + +static int verb_remove(int argc, char *argv[], void *userdata) { + sd_id128_t uuid = SD_ID128_NULL, machine_id; + int r, q; + + r = acquire_esp(false, NULL, NULL, NULL, &uuid); + if (r < 0) + return r; + + r = acquire_xbootldr(false, NULL); + if (r < 0) + return r; + + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return log_error_errno(r, "Failed to get machine id: %m"); + + r = remove_binaries(arg_esp_path); + + q = remove_file(arg_esp_path, "/loader/loader.conf"); + if (q < 0 && r >= 0) + r = q; + + q = remove_file(arg_esp_path, "/loader/random-seed"); + if (q < 0 && r >= 0) + r = q; + + q = remove_subdirs(arg_esp_path, esp_subdirs); + if (q < 0 && r >= 0) + r = q; + + q = remove_subdirs(arg_esp_path, dollar_boot_subdirs); + if (q < 0 && r >= 0) + r = q; + + q = remove_machine_id_directory(arg_esp_path, machine_id); + if (q < 0 && r >= 0) + r = 1; + + if (arg_xbootldr_path) { + /* Remove the latter two also in the XBOOTLDR partition if it exists */ + q = remove_subdirs(arg_xbootldr_path, dollar_boot_subdirs); + if (q < 0 && r >= 0) + r = q; + + q = remove_machine_id_directory(arg_xbootldr_path, machine_id); + if (q < 0 && r >= 0) + r = q; + } + + (void) sync_everything(); + + if (!arg_touch_variables) + return r; + + q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true); + if (q < 0 && r >= 0) + r = q; + + q = remove_loader_variables(); + if (q < 0 && r >= 0) + r = q; + + return r; +} + +static int verb_is_installed(int argc, char *argv[], void *userdata) { + _cleanup_free_ char *p = NULL; + int r; + + r = acquire_esp(false, NULL, NULL, NULL, NULL); + if (r < 0) + return r; + + /* Tests whether systemd-boot is installed. It's not obvious what to use as check here: we could + * check EFI variables, we could check what binary /EFI/BOOT/BOOT*.EFI points to, or whether the + * loader entries directory exists. Here we opted to check whether /EFI/systemd/ is non-empty, which + * should be a suitable and very minimal check for a number of reasons: + * + * → The check is architecture independent (i.e. we check if any systemd-boot loader is installed, not a + * specific one.) + * + * → It doesn't assume we are the only boot loader (i.e doesn't check if we own the main + * /EFI/BOOT/BOOT*.EFI fallback binary. + * + * → It specifically checks for systemd-boot, not for other boot loaders (which a check for + * /boot/loader/entries would do). */ + + p = path_join(arg_esp_path, "/EFI/systemd/"); + if (!p) + return log_oom(); + + r = dir_is_empty(p); + if (r > 0 || r == -ENOENT) { + puts("no"); + return EXIT_FAILURE; + } + if (r < 0) + return log_error_errno(r, "Failed to detect whether systemd-boot is installed: %m"); + + puts("yes"); + return EXIT_SUCCESS; +} + +static int verb_set_default(int argc, char *argv[], void *userdata) { + const char *name; + int r; + + if (!is_efi_boot()) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Not booted with UEFI."); + + if (access("/sys/firmware/efi/efivars/LoaderInfo-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", F_OK) < 0) { + if (errno == ENOENT) { + log_error_errno(errno, "Not booted with a supported boot loader."); + return -EOPNOTSUPP; + } + + return log_error_errno(errno, "Failed to detect whether boot loader supports '%s' operation: %m", argv[0]); + } + + if (detect_container() > 0) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "'%s' operation not supported in a container.", + argv[0]); + + if (!arg_touch_variables) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "'%s' operation cannot be combined with --touch-variables=no.", + argv[0]); + + name = streq(argv[0], "set-default") ? "LoaderEntryDefault" : "LoaderEntryOneShot"; + + if (isempty(argv[1])) { + r = efi_set_variable(EFI_VENDOR_LOADER, name, NULL, 0); + if (r < 0 && r != -ENOENT) + return log_error_errno(r, "Failed to remove EFI variale: %m"); + } else { + _cleanup_free_ char16_t *encoded = NULL; + + encoded = utf8_to_utf16(argv[1], strlen(argv[1])); + if (!encoded) + return log_oom(); + + r = efi_set_variable(EFI_VENDOR_LOADER, name, encoded, char16_strlen(encoded) * 2 + 2); + if (r < 0) + return log_error_errno(r, "Failed to update EFI variable: %m"); + } + + return 0; +} + +static int verb_random_seed(int argc, char *argv[], void *userdata) { + int r; + + r = find_esp_and_warn(arg_esp_path, false, &arg_esp_path, NULL, NULL, NULL, NULL); + if (r == -ENOKEY) { + /* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */ + if (!arg_graceful) + return log_error_errno(r, "Unable to find ESP."); + + log_notice("No ESP found, not initializing random seed."); + return 0; + } + if (r < 0) + return r; + + r = install_random_seed(arg_esp_path); + if (r < 0) + return r; + + (void) sync_everything(); + return 0; +} + +static int verb_systemd_efi_options(int argc, char *argv[], void *userdata) { + int r; + + if (argc == 1) { + _cleanup_free_ char *line = NULL; + + r = systemd_efi_options_variable(&line); + if (r < 0) + return log_error_errno(r, "Failed to query SystemdOptions EFI variable: %m"); + + puts(line); + + } else { + r = efi_set_variable_string(EFI_VENDOR_SYSTEMD, "SystemdOptions", argv[1]); + if (r < 0) + return log_error_errno(r, "Failed to set SystemdOptions EFI variable: %m"); + } + + return 0; +} + +static int bootctl_main(int argc, char *argv[]) { + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "status", VERB_ANY, 1, VERB_DEFAULT, verb_status }, + { "install", VERB_ANY, 1, 0, verb_install }, + { "update", VERB_ANY, 1, 0, verb_install }, + { "remove", VERB_ANY, 1, 0, verb_remove }, + { "is-installed", VERB_ANY, 1, 0, verb_is_installed }, + { "list", VERB_ANY, 1, 0, verb_list }, + { "set-default", 2, 2, 0, verb_set_default }, + { "set-oneshot", 2, 2, 0, verb_set_default }, + { "random-seed", VERB_ANY, 1, 0, verb_random_seed }, + { "systemd-efi-options", VERB_ANY, 2, 0, verb_systemd_efi_options }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static int run(int argc, char *argv[]) { + int r; + + log_parse_environment(); + log_open(); + + /* If we run in a container, automatically turn off EFI file system access */ + if (detect_container() > 0) + arg_touch_variables = false; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + return bootctl_main(argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c new file mode 100644 index 00000000..9e976ca6 --- /dev/null +++ b/src/boot/efi/boot.c @@ -0,0 +1,2512 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "console.h" +#include "crc32.h" +#include "disk.h" +#include "graphics.h" +#include "linux.h" +#include "loader-features.h" +#include "measure.h" +#include "pe.h" +#include "random-seed.h" +#include "shim.h" +#include "util.h" + +#ifndef EFI_OS_INDICATIONS_BOOT_TO_FW_UI +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL +#endif + +/* magic string to find in the binary image */ +static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " GIT_VERSION " ####"; + +static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE; + +enum loader_type { + LOADER_UNDEFINED, + LOADER_EFI, + LOADER_LINUX, +}; + +typedef struct { + CHAR16 *id; /* The identifier for this entry (note that this id is not necessarily unique though!) */ + CHAR16 *title_show; + CHAR16 *title; + CHAR16 *version; + CHAR16 *machine_id; + EFI_HANDLE *device; + enum loader_type type; + CHAR16 *loader; + CHAR16 *options; + CHAR16 key; + EFI_STATUS (*call)(VOID); + BOOLEAN no_autoselect; + BOOLEAN non_unique; + UINTN tries_done; + UINTN tries_left; + CHAR16 *path; + CHAR16 *current_name; + CHAR16 *next_name; +} ConfigEntry; + +typedef struct { + ConfigEntry **entries; + UINTN entry_count; + INTN idx_default; + INTN idx_default_efivar; + UINTN timeout_sec; + UINTN timeout_sec_config; + INTN timeout_sec_efivar; + CHAR16 *entry_default_pattern; + CHAR16 *entry_oneshot; + CHAR16 *options_edit; + BOOLEAN editor; + BOOLEAN auto_entries; + BOOLEAN auto_firmware; + BOOLEAN force_menu; + UINTN console_mode; + enum console_mode_change_type console_mode_change; + RandomSeedMode random_seed_mode; +} Config; + +static VOID cursor_left(UINTN *cursor, UINTN *first) { + if ((*cursor) > 0) + (*cursor)--; + else if ((*first) > 0) + (*first)--; +} + +static VOID cursor_right( + UINTN *cursor, + UINTN *first, + UINTN x_max, + UINTN len) { + + if ((*cursor)+1 < x_max) + (*cursor)++; + else if ((*first) + (*cursor) < len) + (*first)++; +} + +static BOOLEAN line_edit( + CHAR16 *line_in, + CHAR16 **line_out, + UINTN x_max, + UINTN y_pos) { + + _cleanup_freepool_ CHAR16 *line = NULL, *print = NULL; + UINTN size, len, first, cursor, clear; + BOOLEAN exit, enter; + + if (!line_in) + line_in = L""; + size = StrLen(line_in) + 1024; + line = AllocatePool(size * sizeof(CHAR16)); + StrCpy(line, line_in); + len = StrLen(line); + print = AllocatePool((x_max+1) * sizeof(CHAR16)); + + uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE); + + first = 0; + cursor = 0; + clear = 0; + enter = FALSE; + exit = FALSE; + while (!exit) { + EFI_STATUS err; + UINT64 key; + UINTN i; + + i = len - first; + if (i >= x_max-1) + i = x_max-1; + CopyMem(print, line + first, i * sizeof(CHAR16)); + while (clear > 0 && i < x_max-1) { + clear--; + print[i++] = ' '; + } + print[i] = '\0'; + + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_pos); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, print); + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); + + err = console_key_read(&key, TRUE); + if (EFI_ERROR(err)) + continue; + + switch (key) { + case KEYPRESS(0, SCAN_ESC, 0): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'c'): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'g'): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('c')): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('g')): + exit = TRUE; + break; + + case KEYPRESS(0, SCAN_HOME, 0): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'a'): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('a')): + /* beginning-of-line */ + cursor = 0; + first = 0; + continue; + + case KEYPRESS(0, SCAN_END, 0): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'e'): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('e')): + /* end-of-line */ + cursor = len - first; + if (cursor+1 >= x_max) { + cursor = x_max-1; + first = len - (x_max-1); + } + continue; + + case KEYPRESS(0, SCAN_DOWN, 0): + case KEYPRESS(EFI_ALT_PRESSED, 0, 'f'): + case KEYPRESS(EFI_CONTROL_PRESSED, SCAN_RIGHT, 0): + /* forward-word */ + while (line[first + cursor] == ' ') + cursor_right(&cursor, &first, x_max, len); + while (line[first + cursor] && line[first + cursor] != ' ') + cursor_right(&cursor, &first, x_max, len); + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); + continue; + + case KEYPRESS(0, SCAN_UP, 0): + case KEYPRESS(EFI_ALT_PRESSED, 0, 'b'): + case KEYPRESS(EFI_CONTROL_PRESSED, SCAN_LEFT, 0): + /* backward-word */ + if ((first + cursor) > 0 && line[first + cursor-1] == ' ') { + cursor_left(&cursor, &first); + while ((first + cursor) > 0 && line[first + cursor] == ' ') + cursor_left(&cursor, &first); + } + while ((first + cursor) > 0 && line[first + cursor-1] != ' ') + cursor_left(&cursor, &first); + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); + continue; + + case KEYPRESS(0, SCAN_RIGHT, 0): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'f'): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('f')): + /* forward-char */ + if (first + cursor == len) + continue; + cursor_right(&cursor, &first, x_max, len); + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); + continue; + + case KEYPRESS(0, SCAN_LEFT, 0): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'b'): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('b')): + /* backward-char */ + cursor_left(&cursor, &first); + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); + continue; + + case KEYPRESS(EFI_ALT_PRESSED, 0, 'd'): + /* kill-word */ + clear = 0; + for (i = first + cursor; i < len && line[i] == ' '; i++) + clear++; + for (; i < len && line[i] != ' '; i++) + clear++; + + for (i = first + cursor; i + clear < len; i++) + line[i] = line[i + clear]; + len -= clear; + line[len] = '\0'; + continue; + + case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'w'): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('w')): + case KEYPRESS(EFI_ALT_PRESSED, 0, CHAR_BACKSPACE): + /* backward-kill-word */ + clear = 0; + if ((first + cursor) > 0 && line[first + cursor-1] == ' ') { + cursor_left(&cursor, &first); + clear++; + while ((first + cursor) > 0 && line[first + cursor] == ' ') { + cursor_left(&cursor, &first); + clear++; + } + } + while ((first + cursor) > 0 && line[first + cursor-1] != ' ') { + cursor_left(&cursor, &first); + clear++; + } + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); + + for (i = first + cursor; i + clear < len; i++) + line[i] = line[i + clear]; + len -= clear; + line[len] = '\0'; + continue; + + case KEYPRESS(0, SCAN_DELETE, 0): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'd'): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('d')): + if (len == 0) + continue; + if (first + cursor == len) + continue; + for (i = first + cursor; i < len; i++) + line[i] = line[i+1]; + clear = 1; + len--; + continue; + + case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'k'): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('k')): + /* kill-line */ + line[first + cursor] = '\0'; + clear = len - (first + cursor); + len = first + cursor; + continue; + + case KEYPRESS(0, 0, CHAR_LINEFEED): + case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN): + if (StrCmp(line, line_in) != 0) + *line_out = TAKE_PTR(line); + enter = TRUE; + exit = TRUE; + break; + + case KEYPRESS(0, 0, CHAR_BACKSPACE): + if (len == 0) + continue; + if (first == 0 && cursor == 0) + continue; + for (i = first + cursor-1; i < len; i++) + line[i] = line[i+1]; + clear = 1; + len--; + if (cursor > 0) + cursor--; + if (cursor > 0 || first == 0) + continue; + /* show full line if it fits */ + if (len < x_max) { + cursor = first; + first = 0; + continue; + } + /* jump left to see what we delete */ + if (first > 10) { + first -= 10; + cursor = 10; + } else { + cursor = first; + first = 0; + } + continue; + + case KEYPRESS(0, 0, ' ') ... KEYPRESS(0, 0, '~'): + case KEYPRESS(0, 0, 0x80) ... KEYPRESS(0, 0, 0xffff): + if (len+1 == size) + continue; + for (i = len; i > first + cursor; i--) + line[i] = line[i-1]; + line[first + cursor] = KEYCHAR(key); + len++; + line[len] = '\0'; + if (cursor+1 < x_max) + cursor++; + else if (first + cursor < len) + first++; + continue; + } + } + + uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); + return enter; +} + +static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) { + UINTN i; + + if (key == 0) + return -1; + + /* select entry by number key */ + if (key >= '1' && key <= '9') { + i = key - '0'; + if (i > config->entry_count) + i = config->entry_count; + return i-1; + } + + /* find matching key in config entries */ + for (i = start; i < config->entry_count; i++) + if (config->entries[i]->key == key) + return i; + + for (i = 0; i < start; i++) + if (config->entries[i]->key == key) + return i; + + return -1; +} + +static VOID print_status(Config *config, CHAR16 *loaded_image_path) { + UINT64 key; + UINTN i; + _cleanup_freepool_ CHAR8 *bootvar = NULL, *modevar = NULL, *indvar = NULL; + _cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL; + UINTN x, y, size; + + uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + + Print(L"systemd-boot version: " GIT_VERSION "\n"); + Print(L"architecture: " EFI_MACHINE_TYPE_NAME "\n"); + Print(L"loaded image: %s\n", loaded_image_path); + Print(L"UEFI specification: %d.%02d\n", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); + Print(L"firmware vendor: %s\n", ST->FirmwareVendor); + Print(L"firmware version: %d.%02d\n", ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + + if (uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x, &y) == EFI_SUCCESS) + Print(L"console size: %d x %d\n", x, y); + + if (efivar_get_raw(&global_guid, L"SecureBoot", &bootvar, &size) == EFI_SUCCESS) + Print(L"SecureBoot: %s\n", yes_no(*bootvar > 0)); + + if (efivar_get_raw(&global_guid, L"SetupMode", &modevar, &size) == EFI_SUCCESS) + Print(L"SetupMode: %s\n", *modevar > 0 ? L"setup" : L"user"); + + if (shim_loaded()) + Print(L"Shim: present\n"); + + if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &indvar, &size) == EFI_SUCCESS) + Print(L"OsIndicationsSupported: %d\n", (UINT64)*indvar); + + Print(L"\n--- press key ---\n\n"); + console_key_read(&key, TRUE); + + Print(L"timeout: %u\n", config->timeout_sec); + if (config->timeout_sec_efivar >= 0) + Print(L"timeout (EFI var): %d\n", config->timeout_sec_efivar); + Print(L"timeout (config): %u\n", config->timeout_sec_config); + if (config->entry_default_pattern) + Print(L"default pattern: '%s'\n", config->entry_default_pattern); + Print(L"editor: %s\n", yes_no(config->editor)); + Print(L"auto-entries: %s\n", yes_no(config->auto_entries)); + Print(L"auto-firmware: %s\n", yes_no(config->auto_firmware)); + + switch (config->random_seed_mode) { + case RANDOM_SEED_OFF: + Print(L"random-seed-mode: off\n"); + break; + case RANDOM_SEED_WITH_SYSTEM_TOKEN: + Print(L"random-seed-mode: with-system-token\n"); + break; + case RANDOM_SEED_ALWAYS: + Print(L"random-seed-mode: always\n"); + break; + default: + ; + } + + Print(L"\n"); + + Print(L"config entry count: %d\n", config->entry_count); + Print(L"entry selected idx: %d\n", config->idx_default); + if (config->idx_default_efivar >= 0) + Print(L"entry EFI var idx: %d\n", config->idx_default_efivar); + Print(L"\n"); + + if (efivar_get_int(L"LoaderConfigTimeout", &i) == EFI_SUCCESS) + Print(L"LoaderConfigTimeout: %u\n", i); + + if (config->entry_oneshot) + Print(L"LoaderEntryOneShot: %s\n", config->entry_oneshot); + if (efivar_get(L"LoaderDevicePartUUID", &partstr) == EFI_SUCCESS) + Print(L"LoaderDevicePartUUID: %s\n", partstr); + if (efivar_get(L"LoaderEntryDefault", &defaultstr) == EFI_SUCCESS) + Print(L"LoaderEntryDefault: %s\n", defaultstr); + + Print(L"\n--- press key ---\n\n"); + console_key_read(&key, TRUE); + + for (i = 0; i < config->entry_count; i++) { + ConfigEntry *entry; + + if (key == KEYPRESS(0, SCAN_ESC, 0) || key == KEYPRESS(0, 0, 'q')) + break; + + entry = config->entries[i]; + Print(L"config entry: %d/%d\n", i+1, config->entry_count); + if (entry->id) + Print(L"id '%s'\n", entry->id); + Print(L"title show '%s'\n", entry->title_show); + if (entry->title) + Print(L"title '%s'\n", entry->title); + if (entry->version) + Print(L"version '%s'\n", entry->version); + if (entry->machine_id) + Print(L"machine-id '%s'\n", entry->machine_id); + if (entry->device) { + EFI_DEVICE_PATH *device_path; + + device_path = DevicePathFromHandle(entry->device); + if (device_path) { + _cleanup_freepool_ CHAR16 *str; + + str = DevicePathToStr(device_path); + Print(L"device handle '%s'\n", str); + } + } + if (entry->loader) + Print(L"loader '%s'\n", entry->loader); + if (entry->options) + Print(L"options '%s'\n", entry->options); + Print(L"auto-select %s\n", yes_no(!entry->no_autoselect)); + if (entry->call) + Print(L"internal call yes\n"); + + if (entry->tries_left != (UINTN) -1) + Print(L"counting boots yes\n" + "tries done %u\n" + "tries left %u\n" + "current path %s\\%s\n" + "next path %s\\%s\n", + entry->tries_done, + entry->tries_left, + entry->path, entry->current_name, + entry->path, entry->next_name); + + Print(L"\n--- press key ---\n\n"); + console_key_read(&key, TRUE); + } + + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); +} + +static BOOLEAN menu_run( + Config *config, + ConfigEntry **chosen_entry, + CHAR16 *loaded_image_path) { + + EFI_STATUS err; + UINTN visible_max; + UINTN idx_highlight; + UINTN idx_highlight_prev; + UINTN idx_first; + UINTN idx_last; + BOOLEAN refresh; + BOOLEAN highlight; + UINTN i; + UINTN line_width; + CHAR16 **lines; + UINTN x_start; + UINTN y_start; + UINTN x_max; + UINTN y_max; + CHAR16 *status; + CHAR16 *clearline; + INTN timeout_remain; + INT16 idx; + BOOLEAN exit = FALSE; + BOOLEAN run = TRUE; + BOOLEAN wait = FALSE; + + graphics_mode(FALSE); + uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE); + uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); + uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); + + /* draw a single character to make ClearScreen work on some firmware */ + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L" "); + + if (config->console_mode_change != CONSOLE_MODE_KEEP) { + err = console_set_mode(&config->console_mode, config->console_mode_change); + if (EFI_ERROR(err)) { + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + Print(L"Error switching console mode to %ld: %r.\r", (UINT64)config->console_mode, err); + } + } else + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + + err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x_max, &y_max); + if (EFI_ERROR(err)) { + x_max = 80; + y_max = 25; + } + + /* we check 10 times per second for a keystroke */ + if (config->timeout_sec > 0) + timeout_remain = config->timeout_sec * 10; + else + timeout_remain = -1; + + idx_highlight = config->idx_default; + idx_highlight_prev = 0; + + visible_max = y_max - 2; + + if ((UINTN)config->idx_default >= visible_max) + idx_first = config->idx_default-1; + else + idx_first = 0; + + idx_last = idx_first + visible_max-1; + + refresh = TRUE; + highlight = FALSE; + + /* length of the longest entry */ + line_width = 5; + for (i = 0; i < config->entry_count; i++) { + UINTN entry_len; + + entry_len = StrLen(config->entries[i]->title_show); + if (line_width < entry_len) + line_width = entry_len; + } + if (line_width > x_max-6) + line_width = x_max-6; + + /* offsets to center the entries on the screen */ + x_start = (x_max - (line_width)) / 2; + if (config->entry_count < visible_max) + y_start = ((visible_max - config->entry_count) / 2) + 1; + else + y_start = 0; + + /* menu entries title lines */ + lines = AllocatePool(sizeof(CHAR16 *) * config->entry_count); + for (i = 0; i < config->entry_count; i++) { + UINTN j, k; + + lines[i] = AllocatePool(((x_max+1) * sizeof(CHAR16))); + for (j = 0; j < x_start; j++) + lines[i][j] = ' '; + + for (k = 0; config->entries[i]->title_show[k] != '\0' && j < x_max; j++, k++) + lines[i][j] = config->entries[i]->title_show[k]; + + for (; j < x_max; j++) + lines[i][j] = ' '; + lines[i][x_max] = '\0'; + } + + status = NULL; + clearline = AllocatePool((x_max+1) * sizeof(CHAR16)); + for (i = 0; i < x_max; i++) + clearline[i] = ' '; + clearline[i] = 0; + + while (!exit) { + UINT64 key; + + if (refresh) { + for (i = 0; i < config->entry_count; i++) { + if (i < idx_first || i > idx_last) + continue; + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + i - idx_first); + if (i == idx_highlight) + uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, + EFI_BLACK|EFI_BACKGROUND_LIGHTGRAY); + else + uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, + EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, lines[i]); + if ((INTN)i == config->idx_default_efivar) { + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, x_start-3, y_start + i - idx_first); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"=>"); + } + } + refresh = FALSE; + } else if (highlight) { + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + idx_highlight_prev - idx_first); + uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, lines[idx_highlight_prev]); + if ((INTN)idx_highlight_prev == config->idx_default_efivar) { + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, x_start-3, y_start + idx_highlight_prev - idx_first); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"=>"); + } + + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + idx_highlight - idx_first); + uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_BLACK|EFI_BACKGROUND_LIGHTGRAY); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, lines[idx_highlight]); + if ((INTN)idx_highlight == config->idx_default_efivar) { + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, x_start-3, y_start + idx_highlight - idx_first); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"=>"); + } + highlight = FALSE; + } + + if (timeout_remain > 0) { + FreePool(status); + status = PoolPrint(L"Boot in %d sec.", (timeout_remain + 5) / 10); + } + + /* print status at last line of screen */ + if (status) { + UINTN len; + UINTN x; + + /* center line */ + len = StrLen(status); + if (len < x_max) + x = (x_max - len) / 2; + else + x = 0; + uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline + (x_max - x)); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, status); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1 + x + len); + } + + err = console_key_read(&key, wait); + if (EFI_ERROR(err)) { + /* timeout reached */ + if (timeout_remain == 0) { + exit = TRUE; + break; + } + + /* sleep and update status */ + if (timeout_remain > 0) { + uefi_call_wrapper(BS->Stall, 1, 100 * 1000); + timeout_remain--; + continue; + } + + /* timeout disabled, wait for next key */ + wait = TRUE; + continue; + } + + timeout_remain = -1; + + /* clear status after keystroke */ + if (status) { + FreePool(status); + status = NULL; + uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1); + } + + idx_highlight_prev = idx_highlight; + + switch (key) { + case KEYPRESS(0, SCAN_UP, 0): + case KEYPRESS(0, 0, 'k'): + if (idx_highlight > 0) + idx_highlight--; + break; + + case KEYPRESS(0, SCAN_DOWN, 0): + case KEYPRESS(0, 0, 'j'): + if (idx_highlight < config->entry_count-1) + idx_highlight++; + break; + + case KEYPRESS(0, SCAN_HOME, 0): + case KEYPRESS(EFI_ALT_PRESSED, 0, '<'): + if (idx_highlight > 0) { + refresh = TRUE; + idx_highlight = 0; + } + break; + + case KEYPRESS(0, SCAN_END, 0): + case KEYPRESS(EFI_ALT_PRESSED, 0, '>'): + if (idx_highlight < config->entry_count-1) { + refresh = TRUE; + idx_highlight = config->entry_count-1; + } + break; + + case KEYPRESS(0, SCAN_PAGE_UP, 0): + if (idx_highlight > visible_max) + idx_highlight -= visible_max; + else + idx_highlight = 0; + break; + + case KEYPRESS(0, SCAN_PAGE_DOWN, 0): + idx_highlight += visible_max; + if (idx_highlight > config->entry_count-1) + idx_highlight = config->entry_count-1; + break; + + case KEYPRESS(0, 0, CHAR_LINEFEED): + case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN): + exit = TRUE; + break; + + case KEYPRESS(0, SCAN_F1, 0): + case KEYPRESS(0, 0, 'h'): + case KEYPRESS(0, 0, '?'): + status = StrDuplicate(L"(d)efault, (t/T)timeout, (e)dit, (v)ersion (Q)uit (P)rint (h)elp"); + break; + + case KEYPRESS(0, 0, 'Q'): + exit = TRUE; + run = FALSE; + break; + + case KEYPRESS(0, 0, 'd'): + if (config->idx_default_efivar != (INTN)idx_highlight) { + /* store the selected entry in a persistent EFI variable */ + efivar_set(L"LoaderEntryDefault", config->entries[idx_highlight]->id, TRUE); + config->idx_default_efivar = idx_highlight; + status = StrDuplicate(L"Default boot entry selected."); + } else { + /* clear the default entry EFI variable */ + efivar_set(L"LoaderEntryDefault", NULL, TRUE); + config->idx_default_efivar = -1; + status = StrDuplicate(L"Default boot entry cleared."); + } + refresh = TRUE; + break; + + case KEYPRESS(0, 0, '-'): + case KEYPRESS(0, 0, 'T'): + if (config->timeout_sec_efivar > 0) { + config->timeout_sec_efivar--; + efivar_set_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE); + if (config->timeout_sec_efivar > 0) + status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar); + else + status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); + } else if (config->timeout_sec_efivar <= 0){ + config->timeout_sec_efivar = -1; + efivar_set(L"LoaderConfigTimeout", NULL, TRUE); + if (config->timeout_sec_config > 0) + status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.", + config->timeout_sec_config); + else + status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); + } + break; + + case KEYPRESS(0, 0, '+'): + case KEYPRESS(0, 0, 't'): + if (config->timeout_sec_efivar == -1 && config->timeout_sec_config == 0) + config->timeout_sec_efivar++; + config->timeout_sec_efivar++; + efivar_set_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE); + if (config->timeout_sec_efivar > 0) + status = PoolPrint(L"Menu timeout set to %d sec.", + config->timeout_sec_efivar); + else + status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); + break; + + case KEYPRESS(0, 0, 'e'): + /* only the options of configured entries can be edited */ + if (!config->editor || config->entries[idx_highlight]->type == LOADER_UNDEFINED) + break; + uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1); + if (line_edit(config->entries[idx_highlight]->options, &config->options_edit, x_max-1, y_max-1)) + exit = TRUE; + uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_max-1); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, clearline+1); + break; + + case KEYPRESS(0, 0, 'v'): + status = PoolPrint(L"systemd-boot " GIT_VERSION " (" EFI_MACHINE_TYPE_NAME "), UEFI Specification %d.%02d, Vendor %s %d.%02d", + ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff, + ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + break; + + case KEYPRESS(0, 0, 'P'): + print_status(config, loaded_image_path); + refresh = TRUE; + break; + + case KEYPRESS(EFI_CONTROL_PRESSED, 0, 'l'): + case KEYPRESS(EFI_CONTROL_PRESSED, 0, CHAR_CTRL('l')): + refresh = TRUE; + break; + + default: + /* jump with a hotkey directly to a matching entry */ + idx = entry_lookup_key(config, idx_highlight+1, KEYCHAR(key)); + if (idx < 0) + break; + idx_highlight = idx; + refresh = TRUE; + } + + if (idx_highlight > idx_last) { + idx_last = idx_highlight; + idx_first = 1 + idx_highlight - visible_max; + refresh = TRUE; + } else if (idx_highlight < idx_first) { + idx_first = idx_highlight; + idx_last = idx_highlight + visible_max-1; + refresh = TRUE; + } + + if (!refresh && idx_highlight != idx_highlight_prev) + highlight = TRUE; + } + + *chosen_entry = config->entries[idx_highlight]; + + for (i = 0; i < config->entry_count; i++) + FreePool(lines[i]); + FreePool(lines); + FreePool(clearline); + + uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_WHITE|EFI_BACKGROUND_BLACK); + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + return run; +} + +static VOID config_add_entry(Config *config, ConfigEntry *entry) { + if ((config->entry_count & 15) == 0) { + UINTN i; + + i = config->entry_count + 16; + if (config->entry_count == 0) + config->entries = AllocatePool(sizeof(VOID *) * i); + else + config->entries = ReallocatePool(config->entries, + sizeof(VOID *) * config->entry_count, sizeof(VOID *) * i); + } + config->entries[config->entry_count++] = entry; +} + +static VOID config_entry_free(ConfigEntry *entry) { + if (!entry) + return; + + FreePool(entry->id); + FreePool(entry->title_show); + FreePool(entry->title); + FreePool(entry->version); + FreePool(entry->machine_id); + FreePool(entry->loader); + FreePool(entry->options); + FreePool(entry->path); + FreePool(entry->current_name); + FreePool(entry->next_name); + FreePool(entry); +} + +static BOOLEAN is_digit(CHAR16 c) { + return (c >= '0') && (c <= '9'); +} + +static UINTN c_order(CHAR16 c) { + if (c == '\0') + return 0; + if (is_digit(c)) + return 0; + else if ((c >= 'a') && (c <= 'z')) + return c; + else + return c + 0x10000; +} + +static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2) { + CHAR16 *os1 = s1; + CHAR16 *os2 = s2; + + while (*s1 || *s2) { + INTN first; + + while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) { + INTN order; + + order = c_order(*s1) - c_order(*s2); + if (order != 0) + return order; + s1++; + s2++; + } + + while (*s1 == '0') + s1++; + while (*s2 == '0') + s2++; + + first = 0; + while (is_digit(*s1) && is_digit(*s2)) { + if (first == 0) + first = *s1 - *s2; + s1++; + s2++; + } + + if (is_digit(*s1)) + return 1; + if (is_digit(*s2)) + return -1; + + if (first != 0) + return first; + } + + return StrCmp(os1, os2); +} + +static CHAR8 *line_get_key_value( + CHAR8 *content, + CHAR8 *sep, + UINTN *pos, + CHAR8 **key_ret, + CHAR8 **value_ret) { + + CHAR8 *line; + UINTN linelen; + CHAR8 *value; + +skip: + line = content + *pos; + if (*line == '\0') + return NULL; + + linelen = 0; + while (line[linelen] && !strchra((CHAR8 *)"\n\r", line[linelen])) + linelen++; + + /* move pos to next line */ + *pos += linelen; + if (content[*pos]) + (*pos)++; + + /* empty line */ + if (linelen == 0) + goto skip; + + /* terminate line */ + line[linelen] = '\0'; + + /* remove leading whitespace */ + while (strchra((CHAR8 *)" \t", *line)) { + line++; + linelen--; + } + + /* remove trailing whitespace */ + while (linelen > 0 && strchra((CHAR8 *)" \t", line[linelen-1])) + linelen--; + line[linelen] = '\0'; + + if (*line == '#') + goto skip; + + /* split key/value */ + value = line; + while (*value && !strchra(sep, *value)) + value++; + if (*value == '\0') + goto skip; + *value = '\0'; + value++; + while (*value && strchra(sep, *value)) + value++; + + /* unquote */ + if (value[0] == '"' && line[linelen-1] == '"') { + value++; + line[linelen-1] = '\0'; + } + + *key_ret = line; + *value_ret = value; + return line; +} + +static VOID config_defaults_load_from_file(Config *config, CHAR8 *content) { + CHAR8 *line; + UINTN pos = 0; + CHAR8 *key, *value; + + while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) { + if (strcmpa((CHAR8 *)"timeout", key) == 0) { + _cleanup_freepool_ CHAR16 *s = NULL; + + s = stra_to_str(value); + config->timeout_sec_config = Atoi(s); + config->timeout_sec = config->timeout_sec_config; + continue; + } + + if (strcmpa((CHAR8 *)"default", key) == 0) { + FreePool(config->entry_default_pattern); + config->entry_default_pattern = stra_to_str(value); + StrLwr(config->entry_default_pattern); + continue; + } + + if (strcmpa((CHAR8 *)"editor", key) == 0) { + BOOLEAN on; + + if (EFI_ERROR(parse_boolean(value, &on))) + continue; + + config->editor = on; + continue; + } + + if (strcmpa((CHAR8 *)"auto-entries", key) == 0) { + BOOLEAN on; + + if (EFI_ERROR(parse_boolean(value, &on))) + continue; + + config->auto_entries = on; + continue; + } + + if (strcmpa((CHAR8 *)"auto-firmware", key) == 0) { + BOOLEAN on; + + if (EFI_ERROR(parse_boolean(value, &on))) + continue; + + config->auto_firmware = on; + continue; + } + + if (strcmpa((CHAR8 *)"console-mode", key) == 0) { + if (strcmpa((CHAR8 *)"auto", value) == 0) + config->console_mode_change = CONSOLE_MODE_AUTO; + else if (strcmpa((CHAR8 *)"max", value) == 0) + config->console_mode_change = CONSOLE_MODE_MAX; + else if (strcmpa((CHAR8 *)"keep", value) == 0) + config->console_mode_change = CONSOLE_MODE_KEEP; + else { + _cleanup_freepool_ CHAR16 *s = NULL; + + s = stra_to_str(value); + config->console_mode = Atoi(s); + config->console_mode_change = CONSOLE_MODE_SET; + } + + continue; + } + + if (strcmpa((CHAR8*) "random-seed-mode", key) == 0) { + if (strcmpa((CHAR8*) "off", value) == 0) + config->random_seed_mode = RANDOM_SEED_OFF; + else if (strcmpa((CHAR8*) "with-system-token", value) == 0) + config->random_seed_mode = RANDOM_SEED_WITH_SYSTEM_TOKEN; + else if (strcmpa((CHAR8*) "always", value) == 0) + config->random_seed_mode = RANDOM_SEED_ALWAYS; + else { + BOOLEAN on; + + if (EFI_ERROR(parse_boolean(value, &on))) + continue; + + config->random_seed_mode = on ? RANDOM_SEED_ALWAYS : RANDOM_SEED_OFF; + } + } + } +} + +static VOID config_entry_parse_tries( + ConfigEntry *entry, + CHAR16 *path, + CHAR16 *file, + CHAR16 *suffix) { + + UINTN left = (UINTN) -1, done = (UINTN) -1, factor = 1, i, next_left, next_done; + _cleanup_freepool_ CHAR16 *prefix = NULL; + + /* + * Parses a suffix of two counters (one going down, one going up) in the form "+LEFT-DONE" from the end of the + * filename (but before the .efi/.conf suffix), where the "-DONE" part is optional and may be left out (in + * which case that counter as assumed to be zero, i.e. the missing part is synonymous to "-0"). + * + * Names we grok, and the series they result in: + * + * foobar+3.efi → foobar+2-1.efi → foobar+1-2.efi → foobar+0-3.efi → STOP! + * foobar+4-0.efi → foobar+3-1.efi → foobar+2-2.efi → foobar+1-3.efi → foobar+0-4.efi → STOP! + */ + + i = StrLen(file); + + /* Chop off any suffix such as ".conf" or ".efi" */ + if (suffix) { + UINTN suffix_length; + + suffix_length = StrLen(suffix); + if (i < suffix_length) + return; + + i -= suffix_length; + } + + /* Go backwards through the string and parse everything we encounter */ + for (;;) { + if (i == 0) + return; + + i--; + + switch (file[i]) { + + case '+': + if (left == (UINTN) -1) /* didn't read at least one digit for 'left'? */ + return; + + if (done == (UINTN) -1) /* no 'done' counter? If so, it's equivalent to 0 */ + done = 0; + + goto good; + + case '-': + if (left == (UINTN) -1) /* didn't parse any digit yet? */ + return; + + if (done != (UINTN) -1) /* already encountered a dash earlier? */ + return; + + /* So we encountered a dash. This means this counter is of the form +LEFT-DONE. Let's assign + * what we already parsed to 'done', and start fresh for the 'left' part. */ + + done = left; + left = (UINTN) -1; + factor = 1; + break; + + case '0'...'9': { + UINTN new_factor; + + if (left == (UINTN) -1) + left = file[i] - '0'; + else { + UINTN new_left, digit; + + digit = file[i] - '0'; + if (digit > (UINTN) -1 / factor) /* overflow check */ + return; + + new_left = left + digit * factor; + if (new_left < left) /* overflow check */ + return; + + if (new_left == (UINTN) -1) /* don't allow us to be confused */ + return; + } + + new_factor = factor * 10; + if (new_factor < factor) /* overflow chck */ + return; + + factor = new_factor; + break; + } + + default: + return; + } + } + +good: + entry->tries_left = left; + entry->tries_done = done; + + entry->path = StrDuplicate(path); + entry->current_name = StrDuplicate(file); + + next_left = left <= 0 ? 0 : left - 1; + next_done = done >= (UINTN) -2 ? (UINTN) -2 : done + 1; + + prefix = StrDuplicate(file); + prefix[i] = 0; + + entry->next_name = PoolPrint(L"%s+%u-%u%s", prefix, next_left, next_done, suffix ?: L""); +} + +static VOID config_entry_bump_counters( + ConfigEntry *entry, + EFI_FILE_HANDLE root_dir) { + + _cleanup_freepool_ CHAR16* old_path = NULL, *new_path = NULL; + _cleanup_(FileHandleClosep) EFI_FILE_HANDLE handle = NULL; + static EFI_GUID EfiFileInfoGuid = EFI_FILE_INFO_ID; + _cleanup_freepool_ EFI_FILE_INFO *file_info = NULL; + UINTN file_info_size, a, b; + EFI_STATUS r; + + if (entry->tries_left == (UINTN) -1) + return; + + if (!entry->path || !entry->current_name || !entry->next_name) + return; + + old_path = PoolPrint(L"%s\\%s", entry->path, entry->current_name); + + r = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, old_path, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0ULL); + if (EFI_ERROR(r)) + return; + + a = StrLen(entry->current_name); + b = StrLen(entry->next_name); + + file_info_size = OFFSETOF(EFI_FILE_INFO, FileName) + (a > b ? a : b) + 1; + + for (;;) { + file_info = AllocatePool(file_info_size); + + r = uefi_call_wrapper(handle->GetInfo, 4, handle, &EfiFileInfoGuid, &file_info_size, file_info); + if (!EFI_ERROR(r)) + break; + + if (r != EFI_BUFFER_TOO_SMALL || file_info_size * 2 < file_info_size) { + Print(L"\nFailed to get file info for '%s': %r\n", old_path, r); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return; + } + + file_info_size *= 2; + FreePool(file_info); + } + + /* And rename the file */ + StrCpy(file_info->FileName, entry->next_name); + r = uefi_call_wrapper(handle->SetInfo, 4, handle, &EfiFileInfoGuid, file_info_size, file_info); + if (EFI_ERROR(r)) { + Print(L"\nFailed to rename '%s' to '%s', ignoring: %r\n", old_path, entry->next_name, r); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return; + } + + /* Flush everything to disk, just in case… */ + (void) uefi_call_wrapper(handle->Flush, 1, handle); + + /* Let's tell the OS that we renamed this file, so that it knows what to rename to the counter-less name on + * success */ + new_path = PoolPrint(L"%s\\%s", entry->path, entry->next_name); + efivar_set(L"LoaderBootCountPath", new_path, FALSE); + + /* If the file we just renamed is the loader path, then let's update that. */ + if (StrCmp(entry->loader, old_path) == 0) { + FreePool(entry->loader); + entry->loader = TAKE_PTR(new_path); + } +} + +static VOID config_entry_add_from_file( + Config *config, + EFI_HANDLE *device, + EFI_FILE *root_dir, + CHAR16 *path, + CHAR16 *file, + CHAR8 *content, + CHAR16 *loaded_image_path) { + + ConfigEntry *entry; + CHAR8 *line; + UINTN pos = 0; + CHAR8 *key, *value; + UINTN len; + EFI_STATUS err; + EFI_FILE_HANDLE handle; + _cleanup_freepool_ CHAR16 *initrd = NULL; + + entry = AllocatePool(sizeof(ConfigEntry)); + + *entry = (ConfigEntry) { + .tries_done = (UINTN) -1, + .tries_left = (UINTN) -1, + }; + + while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) { + if (strcmpa((CHAR8 *)"title", key) == 0) { + FreePool(entry->title); + entry->title = stra_to_str(value); + continue; + } + + if (strcmpa((CHAR8 *)"version", key) == 0) { + FreePool(entry->version); + entry->version = stra_to_str(value); + continue; + } + + if (strcmpa((CHAR8 *)"machine-id", key) == 0) { + FreePool(entry->machine_id); + entry->machine_id = stra_to_str(value); + continue; + } + + if (strcmpa((CHAR8 *)"linux", key) == 0) { + FreePool(entry->loader); + entry->type = LOADER_LINUX; + entry->loader = stra_to_path(value); + entry->key = 'l'; + continue; + } + + if (strcmpa((CHAR8 *)"efi", key) == 0) { + entry->type = LOADER_EFI; + FreePool(entry->loader); + entry->loader = stra_to_path(value); + + /* do not add an entry for ourselves */ + if (loaded_image_path && StriCmp(entry->loader, loaded_image_path) == 0) { + entry->type = LOADER_UNDEFINED; + break; + } + continue; + } + + if (strcmpa((CHAR8 *)"architecture", key) == 0) { + /* do not add an entry for an EFI image of architecture not matching with that of the image */ + if (strcmpa((CHAR8 *)EFI_MACHINE_TYPE_NAME, value) != 0) { + entry->type = LOADER_UNDEFINED; + break; + } + continue; + } + + if (strcmpa((CHAR8 *)"initrd", key) == 0) { + _cleanup_freepool_ CHAR16 *new = NULL; + + new = stra_to_path(value); + if (initrd) { + CHAR16 *s; + + s = PoolPrint(L"%s initrd=%s", initrd, new); + FreePool(initrd); + initrd = s; + } else + initrd = PoolPrint(L"initrd=%s", new); + + continue; + } + + if (strcmpa((CHAR8 *)"options", key) == 0) { + _cleanup_freepool_ CHAR16 *new = NULL; + + new = stra_to_str(value); + if (entry->options) { + CHAR16 *s; + + s = PoolPrint(L"%s %s", entry->options, new); + FreePool(entry->options); + entry->options = s; + } else + entry->options = TAKE_PTR(new); + + continue; + } + } + + if (entry->type == LOADER_UNDEFINED) { + config_entry_free(entry); + return; + } + + /* check existence */ + err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, entry->loader, EFI_FILE_MODE_READ, 0ULL); + if (EFI_ERROR(err)) { + config_entry_free(entry); + return; + } + uefi_call_wrapper(handle->Close, 1, handle); + + /* add initrd= to options */ + if (entry->type == LOADER_LINUX && initrd) { + if (entry->options) { + CHAR16 *s; + + s = PoolPrint(L"%s %s", initrd, entry->options); + FreePool(entry->options); + entry->options = s; + } else + entry->options = TAKE_PTR(initrd); + } + + entry->device = device; + entry->id = StrDuplicate(file); + len = StrLen(entry->id); + /* remove ".conf" */ + if (len > 5) + entry->id[len - 5] = '\0'; + StrLwr(entry->id); + + config_add_entry(config, entry); + + config_entry_parse_tries(entry, path, file, L".conf"); +} + +static VOID config_load_defaults(Config *config, EFI_FILE *root_dir) { + _cleanup_freepool_ CHAR8 *content = NULL; + UINTN sec; + EFI_STATUS err; + + *config = (Config) { + .editor = TRUE, + .auto_entries = TRUE, + .auto_firmware = TRUE, + .random_seed_mode = RANDOM_SEED_WITH_SYSTEM_TOKEN, + }; + + err = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content, NULL); + if (!EFI_ERROR(err)) + config_defaults_load_from_file(config, content); + + err = efivar_get_int(L"LoaderConfigTimeout", &sec); + if (!EFI_ERROR(err)) { + config->timeout_sec_efivar = sec > INTN_MAX ? INTN_MAX : sec; + config->timeout_sec = sec; + } else + config->timeout_sec_efivar = -1; + + err = efivar_get_int(L"LoaderConfigTimeoutOneShot", &sec); + if (!EFI_ERROR(err)) { + /* Unset variable now, after all it's "one shot". */ + (void) efivar_set(L"LoaderConfigTimeoutOneShot", NULL, TRUE); + + config->timeout_sec = sec; + config->force_menu = TRUE; /* force the menu when this is set */ + } +} + +static VOID config_load_entries( + Config *config, + EFI_HANDLE *device, + EFI_FILE *root_dir, + CHAR16 *loaded_image_path) { + + EFI_FILE_HANDLE entries_dir; + EFI_STATUS err; + + err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &entries_dir, L"\\loader\\entries", EFI_FILE_MODE_READ, 0ULL); + if (!EFI_ERROR(err)) { + for (;;) { + CHAR16 buf[256]; + UINTN bufsize; + EFI_FILE_INFO *f; + _cleanup_freepool_ CHAR8 *content = NULL; + UINTN len; + + bufsize = sizeof(buf); + err = uefi_call_wrapper(entries_dir->Read, 3, entries_dir, &bufsize, buf); + if (bufsize == 0 || EFI_ERROR(err)) + break; + + f = (EFI_FILE_INFO *) buf; + if (f->FileName[0] == '.') + continue; + if (f->Attribute & EFI_FILE_DIRECTORY) + continue; + + len = StrLen(f->FileName); + if (len < 6) + continue; + if (StriCmp(f->FileName + len - 5, L".conf") != 0) + continue; + if (StrnCmp(f->FileName, L"auto-", 5) == 0) + continue; + + err = file_read(entries_dir, f->FileName, 0, 0, &content, NULL); + if (!EFI_ERROR(err)) + config_entry_add_from_file(config, device, root_dir, L"\\loader\\entries", f->FileName, content, loaded_image_path); + } + uefi_call_wrapper(entries_dir->Close, 1, entries_dir); + } +} + +static INTN config_entry_compare(ConfigEntry *a, ConfigEntry *b) { + INTN r; + + /* Order entries that have no tries left to the end of the list */ + if (a->tries_left != 0 && b->tries_left == 0) + return -1; + if (a->tries_left == 0 && b->tries_left != 0) + return 1; + + r = str_verscmp(a->id, b->id); + if (r != 0) + return r; + + if (a->tries_left == (UINTN) -1 || + b->tries_left == (UINTN) -1) + return 0; + + /* If both items have boot counting, and otherwise are identical, put the entry with more tries left first */ + if (a->tries_left > b->tries_left) + return -1; + if (a->tries_left < b->tries_left) + return 1; + + /* If they have the same number of tries left, then let the one win which was tried fewer times so far */ + if (a->tries_done < b->tries_done) + return -1; + if (a->tries_done > b->tries_done) + return 1; + + return 0; +} + +static VOID config_sort_entries(Config *config) { + UINTN i; + + for (i = 1; i < config->entry_count; i++) { + BOOLEAN more; + UINTN k; + + more = FALSE; + for (k = 0; k < config->entry_count - i; k++) { + ConfigEntry *entry; + + if (config_entry_compare(config->entries[k], config->entries[k+1]) <= 0) + continue; + + entry = config->entries[k]; + config->entries[k] = config->entries[k+1]; + config->entries[k+1] = entry; + more = TRUE; + } + if (!more) + break; + } +} + +static INTN config_entry_find(Config *config, CHAR16 *id) { + UINTN i; + + for (i = 0; i < config->entry_count; i++) + if (StrCmp(config->entries[i]->id, id) == 0) + return (INTN) i; + + return -1; +} + +static VOID config_default_entry_select(Config *config) { + _cleanup_freepool_ CHAR16 *entry_oneshot = NULL, *entry_default = NULL; + EFI_STATUS err; + INTN i; + + /* + * The EFI variable to specify a boot entry for the next, and only the + * next reboot. The variable is always cleared directly after it is read. + */ + err = efivar_get(L"LoaderEntryOneShot", &entry_oneshot); + if (!EFI_ERROR(err)) { + + config->entry_oneshot = StrDuplicate(entry_oneshot); + efivar_set(L"LoaderEntryOneShot", NULL, TRUE); + + i = config_entry_find(config, entry_oneshot); + if (i >= 0) { + config->idx_default = i; + return; + } + } + + /* + * The EFI variable to select the default boot entry overrides the + * configured pattern. The variable can be set and cleared by pressing + * the 'd' key in the loader selection menu, the entry is marked with + * an '*'. + */ + err = efivar_get(L"LoaderEntryDefault", &entry_default); + if (!EFI_ERROR(err)) { + + i = config_entry_find(config, entry_default); + if (i >= 0) { + config->idx_default = i; + config->idx_default_efivar = i; + return; + } + } + config->idx_default_efivar = -1; + + if (config->entry_count == 0) + return; + + /* + * Match the pattern from the end of the list to the start, find last + * entry (largest number) matching the given pattern. + */ + if (config->entry_default_pattern) { + i = config->entry_count; + while (i--) { + if (config->entries[i]->no_autoselect) + continue; + if (MetaiMatch(config->entries[i]->id, config->entry_default_pattern)) { + config->idx_default = i; + return; + } + } + } + + /* select the last suitable entry */ + i = config->entry_count; + while (i--) { + if (config->entries[i]->no_autoselect) + continue; + config->idx_default = i; + return; + } + + /* no entry found */ + config->idx_default = -1; +} + +static BOOLEAN find_nonunique(ConfigEntry **entries, UINTN entry_count) { + BOOLEAN non_unique = FALSE; + UINTN i, k; + + for (i = 0; i < entry_count; i++) + entries[i]->non_unique = FALSE; + + for (i = 0; i < entry_count; i++) + for (k = 0; k < entry_count; k++) { + if (i == k) + continue; + if (StrCmp(entries[i]->title_show, entries[k]->title_show) != 0) + continue; + + non_unique = entries[i]->non_unique = entries[k]->non_unique = TRUE; + } + + return non_unique; +} + +/* generate a unique title, avoiding non-distinguishable menu entries */ +static VOID config_title_generate(Config *config) { + UINTN i; + + /* set title */ + for (i = 0; i < config->entry_count; i++) { + CHAR16 *title; + + FreePool(config->entries[i]->title_show); + title = config->entries[i]->title; + if (!title) + title = config->entries[i]->id; + config->entries[i]->title_show = StrDuplicate(title); + } + + if (!find_nonunique(config->entries, config->entry_count)) + return; + + /* add version to non-unique titles */ + for (i = 0; i < config->entry_count; i++) { + CHAR16 *s; + + if (!config->entries[i]->non_unique) + continue; + if (!config->entries[i]->version) + continue; + + s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, config->entries[i]->version); + FreePool(config->entries[i]->title_show); + config->entries[i]->title_show = s; + } + + if (!find_nonunique(config->entries, config->entry_count)) + return; + + /* add machine-id to non-unique titles */ + for (i = 0; i < config->entry_count; i++) { + CHAR16 *s; + _cleanup_freepool_ CHAR16 *m = NULL; + + if (!config->entries[i]->non_unique) + continue; + if (!config->entries[i]->machine_id) + continue; + + m = StrDuplicate(config->entries[i]->machine_id); + m[8] = '\0'; + s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, m); + FreePool(config->entries[i]->title_show); + config->entries[i]->title_show = s; + } + + if (!find_nonunique(config->entries, config->entry_count)) + return; + + /* add file name to non-unique titles */ + for (i = 0; i < config->entry_count; i++) { + CHAR16 *s; + + if (!config->entries[i]->non_unique) + continue; + s = PoolPrint(L"%s (%s)", config->entries[i]->title_show, config->entries[i]->id); + FreePool(config->entries[i]->title_show); + config->entries[i]->title_show = s; + config->entries[i]->non_unique = FALSE; + } +} + +static BOOLEAN config_entry_add_call( + Config *config, + CHAR16 *id, + CHAR16 *title, + EFI_STATUS (*call)(VOID)) { + + ConfigEntry *entry; + + entry = AllocatePool(sizeof(ConfigEntry)); + *entry = (ConfigEntry) { + .id = StrDuplicate(id), + .title = StrDuplicate(title), + .call = call, + .no_autoselect = TRUE, + .tries_done = (UINTN) -1, + .tries_left = (UINTN) -1, + }; + + config_add_entry(config, entry); + return TRUE; +} + +static ConfigEntry *config_entry_add_loader( + Config *config, + EFI_HANDLE *device, + enum loader_type type, + CHAR16 *id, + CHAR16 key, + CHAR16 *title, + CHAR16 *loader) { + + ConfigEntry *entry; + + entry = AllocatePool(sizeof(ConfigEntry)); + *entry = (ConfigEntry) { + .type = type, + .title = StrDuplicate(title), + .device = device, + .loader = StrDuplicate(loader), + .id = StrDuplicate(id), + .key = key, + .tries_done = (UINTN) -1, + .tries_left = (UINTN) -1, + }; + + StrLwr(entry->id); + + config_add_entry(config, entry); + return entry; +} + +static BOOLEAN config_entry_add_loader_auto( + Config *config, + EFI_HANDLE *device, + EFI_FILE *root_dir, + CHAR16 *loaded_image_path, + CHAR16 *id, + CHAR16 key, + CHAR16 *title, + CHAR16 *loader) { + + EFI_FILE_HANDLE handle; + ConfigEntry *entry; + EFI_STATUS err; + + if (!config->auto_entries) + return FALSE; + + /* do not add an entry for ourselves */ + if (loaded_image_path) { + UINTN len; + _cleanup_freepool_ CHAR8 *content = NULL; + + if (StriCmp(loader, loaded_image_path) == 0) + return FALSE; + + /* look for systemd-boot magic string */ + err = file_read(root_dir, loader, 0, 100*1024, &content, &len); + if (!EFI_ERROR(err)) { + CHAR8 *start = content; + CHAR8 *last = content + len - sizeof(magic) - 1; + + for (; start <= last; start++) + if (start[0] == magic[0] && CompareMem(start, magic, sizeof(magic) - 1) == 0) + return FALSE; + } + } + + /* check existence */ + err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, loader, EFI_FILE_MODE_READ, 0ULL); + if (EFI_ERROR(err)) + return FALSE; + uefi_call_wrapper(handle->Close, 1, handle); + + entry = config_entry_add_loader(config, device, LOADER_UNDEFINED, id, key, title, loader); + if (!entry) + return FALSE; + + /* do not boot right away into auto-detected entries */ + entry->no_autoselect = TRUE; + + return TRUE; +} + +static VOID config_entry_add_osx(Config *config) { + EFI_STATUS err; + UINTN handle_count = 0; + _cleanup_freepool_ EFI_HANDLE *handles = NULL; + + if (!config->auto_entries) + return; + + err = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &handle_count, &handles); + if (!EFI_ERROR(err)) { + UINTN i; + + for (i = 0; i < handle_count; i++) { + EFI_FILE *root; + BOOLEAN found; + + root = LibOpenRoot(handles[i]); + if (!root) + continue; + found = config_entry_add_loader_auto(config, handles[i], root, NULL, L"auto-osx", 'a', L"macOS", + L"\\System\\Library\\CoreServices\\boot.efi"); + uefi_call_wrapper(root->Close, 1, root); + if (found) + break; + } + } +} + +static VOID config_entry_add_linux( + Config *config, + EFI_HANDLE *device, + EFI_FILE *root_dir) { + + EFI_FILE_HANDLE linux_dir; + EFI_STATUS err; + ConfigEntry *entry; + + err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &linux_dir, L"\\EFI\\Linux", EFI_FILE_MODE_READ, 0ULL); + if (EFI_ERROR(err)) + return; + + for (;;) { + CHAR16 buf[256]; + UINTN bufsize = sizeof buf; + EFI_FILE_INFO *f; + CHAR8 *sections[] = { + (UINT8 *)".osrel", + (UINT8 *)".cmdline", + NULL + }; + UINTN offs[ELEMENTSOF(sections)-1] = {}; + UINTN szs[ELEMENTSOF(sections)-1] = {}; + UINTN addrs[ELEMENTSOF(sections)-1] = {}; + CHAR8 *content = NULL; + UINTN len; + CHAR8 *line; + UINTN pos = 0; + CHAR8 *key, *value; + CHAR16 *os_name = NULL; + CHAR16 *os_id = NULL; + CHAR16 *os_version = NULL; + CHAR16 *os_build = NULL; + + err = uefi_call_wrapper(linux_dir->Read, 3, linux_dir, &bufsize, buf); + if (bufsize == 0 || EFI_ERROR(err)) + break; + + f = (EFI_FILE_INFO *) buf; + if (f->FileName[0] == '.') + continue; + if (f->Attribute & EFI_FILE_DIRECTORY) + continue; + len = StrLen(f->FileName); + if (len < 5) + continue; + if (StriCmp(f->FileName + len - 4, L".efi") != 0) + continue; + + /* look for .osrel and .cmdline sections in the .efi binary */ + err = pe_file_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs); + if (EFI_ERROR(err)) + continue; + + err = file_read(linux_dir, f->FileName, offs[0], szs[0], &content, NULL); + if (EFI_ERROR(err)) + continue; + + /* read properties from the embedded os-release file */ + while ((line = line_get_key_value(content, (CHAR8 *)"=", &pos, &key, &value))) { + if (strcmpa((CHAR8 *)"PRETTY_NAME", key) == 0) { + FreePool(os_name); + os_name = stra_to_str(value); + continue; + } + + if (strcmpa((CHAR8 *)"ID", key) == 0) { + FreePool(os_id); + os_id = stra_to_str(value); + continue; + } + + if (strcmpa((CHAR8 *)"VERSION", key) == 0) { + FreePool(os_version); + os_version = stra_to_str(value); + continue; + } + + if (strcmpa((CHAR8 *)"BUILD_ID", key) == 0) { + FreePool(os_build); + os_build = stra_to_str(value); + continue; + } + } + + if (os_name && os_id && (os_version || os_build)) { + _cleanup_freepool_ CHAR16 *conf = NULL, *path = NULL; + + conf = PoolPrint(L"%s-%s", os_id, os_version ? : os_build); + path = PoolPrint(L"\\EFI\\Linux\\%s", f->FileName); + + entry = config_entry_add_loader(config, device, LOADER_LINUX, conf, 'l', os_name, path); + + FreePool(content); + content = NULL; + + /* read the embedded cmdline file */ + err = file_read(linux_dir, f->FileName, offs[1], szs[1], &content, NULL); + if (!EFI_ERROR(err)) { + + /* chomp the newline */ + if (content[szs[1]-1] == '\n') + content[szs[1]-1] = '\0'; + + entry->options = stra_to_str(content); + } + + config_entry_parse_tries(entry, L"\\EFI\\Linux", f->FileName, L".efi"); + } + + FreePool(os_name); + FreePool(os_id); + FreePool(os_version); + FreePool(os_build); + FreePool(content); + } + + uefi_call_wrapper(linux_dir->Close, 1, linux_dir); +} + +/* Note that this is in GUID format, i.e. the first 32bit, and the following pair of 16bit are byteswapped. */ +static const UINT8 xbootldr_guid[16] = { + 0xff, 0xc2, 0x13, 0xbc, 0xe6, 0x59, 0x62, 0x42, 0xa3, 0x52, 0xb2, 0x75, 0xfd, 0x6f, 0x71, 0x72 +}; + +EFI_DEVICE_PATH *path_parent(EFI_DEVICE_PATH *path, EFI_DEVICE_PATH *node) { + EFI_DEVICE_PATH *parent; + UINTN len; + + len = (UINT8*) NextDevicePathNode(node) - (UINT8*) path; + parent = (EFI_DEVICE_PATH*) AllocatePool(len + sizeof(EFI_DEVICE_PATH)); + CopyMem(parent, path, len); + CopyMem((UINT8*) parent + len, EndDevicePath, sizeof(EFI_DEVICE_PATH)); + + return parent; +} + +static VOID config_load_xbootldr( + Config *config, + EFI_HANDLE *device) { + + EFI_DEVICE_PATH *partition_path, *node, *disk_path, *copy; + UINT32 found_partition_number = (UINT32) -1; + UINT64 found_partition_start = (UINT64) -1; + UINT64 found_partition_size = (UINT64) -1; + UINT8 found_partition_signature[16] = {}; + EFI_HANDLE new_device; + EFI_FILE *root_dir; + EFI_STATUS r; + + partition_path = DevicePathFromHandle(device); + if (!partition_path) + return; + + for (node = partition_path; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) { + EFI_HANDLE disk_handle; + EFI_BLOCK_IO *block_io; + EFI_DEVICE_PATH *p; + UINTN nr; + + /* First, Let's look for the SCSI/SATA/USB/… device path node, i.e. one above the media + * devices */ + if (DevicePathType(node) != MESSAGING_DEVICE_PATH) + continue; + + /* Determine the device path one level up */ + disk_path = path_parent(partition_path, node); + p = disk_path; + r = uefi_call_wrapper(BS->LocateDevicePath, 3, &BlockIoProtocol, &p, &disk_handle); + if (EFI_ERROR(r)) + continue; + + r = uefi_call_wrapper(BS->HandleProtocol, 3, disk_handle, &BlockIoProtocol, (VOID **)&block_io); + if (EFI_ERROR(r)) + continue; + + /* Filter out some block devices early. (We only care about block devices that aren't + * partitions themselves — we look for GPT partition tables to parse after all —, and only + * those which contain a medium and have at least 2 blocks.) */ + if (block_io->Media->LogicalPartition || + !block_io->Media->MediaPresent || + block_io->Media->LastBlock <= 1) + continue; + + /* Try both copies of the GPT header, in case one is corrupted */ + for (nr = 0; nr < 2; nr++) { + _cleanup_freepool_ EFI_PARTITION_ENTRY* entries = NULL; + union { + EFI_PARTITION_TABLE_HEADER gpt_header; + uint8_t space[((sizeof(EFI_PARTITION_TABLE_HEADER) + 511) / 512) * 512]; + } gpt_header_buffer; + const EFI_PARTITION_TABLE_HEADER *h = &gpt_header_buffer.gpt_header; + UINT64 where; + UINTN i, sz; + UINT32 c; + + if (nr == 0) + /* Read the first copy at LBA 1 */ + where = 1; + else + /* Read the second copy at the very last LBA of this block device */ + where = block_io->Media->LastBlock; + + /* Read the GPT header */ + r = uefi_call_wrapper(block_io->ReadBlocks, 5, + block_io, + block_io->Media->MediaId, + where, + sizeof(gpt_header_buffer), &gpt_header_buffer); + if (EFI_ERROR(r)) + continue; + + /* Some superficial validation of the GPT header */ + c = CompareMem(&h->Header.Signature, "EFI PART", sizeof(h->Header.Signature)); + if (c != 0) + continue; + + if (h->Header.HeaderSize < 92 || + h->Header.HeaderSize > 512) + continue; + + if (h->Header.Revision != 0x00010000U) + continue; + + /* Calculate CRC check */ + c = ~crc32_exclude_offset((UINT32) -1, + (const UINT8*) &gpt_header_buffer, + h->Header.HeaderSize, + OFFSETOF(EFI_PARTITION_TABLE_HEADER, Header.CRC32), + sizeof(h->Header.CRC32)); + if (c != h->Header.CRC32) + continue; + + if (h->MyLBA != where) + continue; + + if (h->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY)) + continue; + + if (h->NumberOfPartitionEntries <= 0 || + h->NumberOfPartitionEntries > 1024) + continue; + + if (h->SizeOfPartitionEntry > UINTN_MAX / h->NumberOfPartitionEntries) /* overflow check */ + continue; + + /* Now load the GPT entry table */ + sz = ALIGN_TO((UINTN) h->SizeOfPartitionEntry * (UINTN) h->NumberOfPartitionEntries, 512); + entries = AllocatePool(sz); + + r = uefi_call_wrapper(block_io->ReadBlocks, 5, + block_io, + block_io->Media->MediaId, + h->PartitionEntryLBA, + sz, entries); + if (EFI_ERROR(r)) + continue; + + /* Calculate CRC of entries array, too */ + c = ~crc32((UINT32) -1, entries, sz); + if (c != h->PartitionEntryArrayCRC32) + continue; + + for (i = 0; i < h->NumberOfPartitionEntries; i++) { + EFI_PARTITION_ENTRY *entry; + + entry = (EFI_PARTITION_ENTRY*) ((UINT8*) entries + h->SizeOfPartitionEntry * i); + + if (CompareMem(&entry->PartitionTypeGUID, xbootldr_guid, 16) == 0) { + UINT64 end; + + /* Let's use memcpy(), in case the structs are not aligned (they really should be though) */ + CopyMem(&found_partition_start, &entry->StartingLBA, sizeof(found_partition_start)); + CopyMem(&end, &entry->EndingLBA, sizeof(end)); + + if (end < found_partition_start) /* Bogus? */ + continue; + + found_partition_size = end - found_partition_start + 1; + CopyMem(found_partition_signature, &entry->UniquePartitionGUID, sizeof(found_partition_signature)); + + found_partition_number = i + 1; + goto found; + } + } + + break; /* This GPT was fully valid, but we didn't find what we are looking for. This + * means there's no reason to check the second copy of the GPT header */ + } + } + + return; /* Not found */ + +found: + copy = DuplicateDevicePath(partition_path); + + /* Patch in the data we found */ + for (node = copy; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) { + HARDDRIVE_DEVICE_PATH *hd; + + if (DevicePathType(node) != MEDIA_DEVICE_PATH) + continue; + + if (DevicePathSubType(node) != MEDIA_HARDDRIVE_DP) + continue; + + hd = (HARDDRIVE_DEVICE_PATH*) node; + hd->PartitionNumber = found_partition_number; + hd->PartitionStart = found_partition_start; + hd->PartitionSize = found_partition_size; + CopyMem(hd->Signature, found_partition_signature, sizeof(hd->Signature)); + hd->MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; + hd->SignatureType = SIGNATURE_TYPE_GUID; + } + + r = uefi_call_wrapper(BS->LocateDevicePath, 3, &BlockIoProtocol, ©, &new_device); + if (EFI_ERROR(r)) + return; + + root_dir = LibOpenRoot(new_device); + if (!root_dir) + return; + + config_entry_add_linux(config, new_device, root_dir); + config_load_entries(config, new_device, root_dir, NULL); +} + +static EFI_STATUS image_start( + EFI_HANDLE parent_image, + const Config *config, + const ConfigEntry *entry) { + + EFI_HANDLE image; + _cleanup_freepool_ EFI_DEVICE_PATH *path = NULL; + CHAR16 *options; + EFI_STATUS err; + + path = FileDevicePath(entry->device, entry->loader); + if (!path) { + Print(L"Error getting device path."); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return EFI_INVALID_PARAMETER; + } + + err = uefi_call_wrapper(BS->LoadImage, 6, FALSE, parent_image, path, NULL, 0, &image); + if (EFI_ERROR(err)) { + Print(L"Error loading %s: %r", entry->loader, err); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return err; + } + + if (config->options_edit) + options = config->options_edit; + else if (entry->options) + options = entry->options; + else + options = NULL; + if (options) { + EFI_LOADED_IMAGE *loaded_image; + + err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, + parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(err)) { + Print(L"Error getting LoadedImageProtocol handle: %r", err); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + goto out_unload; + } + loaded_image->LoadOptions = options; + loaded_image->LoadOptionsSize = (StrLen(loaded_image->LoadOptions)+1) * sizeof(CHAR16); + +#if ENABLE_TPM + /* Try to log any options to the TPM, especially to catch manually edited options */ + err = tpm_log_event(SD_TPM_PCR, + (EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions, + loaded_image->LoadOptionsSize, loaded_image->LoadOptions); + if (EFI_ERROR(err)) { + Print(L"Unable to add image options measurement: %r", err); + uefi_call_wrapper(BS->Stall, 1, 200 * 1000); + } +#endif + } + + efivar_set_time_usec(L"LoaderTimeExecUSec", 0); + err = uefi_call_wrapper(BS->StartImage, 3, image, NULL, NULL); +out_unload: + uefi_call_wrapper(BS->UnloadImage, 1, image); + return err; +} + +static EFI_STATUS reboot_into_firmware(VOID) { + _cleanup_freepool_ CHAR8 *b = NULL; + UINTN size; + UINT64 osind; + EFI_STATUS err; + + osind = EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + + err = efivar_get_raw(&global_guid, L"OsIndications", &b, &size); + if (!EFI_ERROR(err)) + osind |= (UINT64)*b; + + err = efivar_set_raw(&global_guid, L"OsIndications", &osind, sizeof(UINT64), TRUE); + if (EFI_ERROR(err)) + return err; + + err = uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, 0, NULL); + Print(L"Error calling ResetSystem: %r", err); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return err; +} + +static VOID config_free(Config *config) { + UINTN i; + + for (i = 0; i < config->entry_count; i++) + config_entry_free(config->entries[i]); + FreePool(config->entries); + FreePool(config->entry_default_pattern); + FreePool(config->options_edit); + FreePool(config->entry_oneshot); +} + +static VOID config_write_entries_to_variable(Config *config) { + _cleanup_freepool_ CHAR16 *buffer = NULL; + UINTN i, sz = 0; + CHAR16 *p; + + for (i = 0; i < config->entry_count; i++) + sz += StrLen(config->entries[i]->id) + 1; + + p = buffer = AllocatePool(sz * sizeof(CHAR16)); + + for (i = 0; i < config->entry_count; i++) { + UINTN l; + + l = StrLen(config->entries[i]->id) + 1; + CopyMem(p, config->entries[i]->id, l * sizeof(CHAR16)); + + p += l; + } + + /* Store the full list of discovered entries. */ + (void) efivar_set_raw(&loader_guid, L"LoaderEntries", buffer, (UINT8*) p - (UINT8*) buffer, FALSE); +} + +EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + static const UINT64 loader_features = + EFI_LOADER_FEATURE_CONFIG_TIMEOUT | + EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT | + EFI_LOADER_FEATURE_ENTRY_DEFAULT | + EFI_LOADER_FEATURE_ENTRY_ONESHOT | + EFI_LOADER_FEATURE_BOOT_COUNTING | + EFI_LOADER_FEATURE_XBOOTLDR | + EFI_LOADER_FEATURE_RANDOM_SEED | + 0; + + _cleanup_freepool_ CHAR16 *infostr = NULL, *typestr = NULL; + CHAR8 *b; + UINTN size; + EFI_LOADED_IMAGE *loaded_image; + EFI_FILE *root_dir; + CHAR16 *loaded_image_path; + EFI_STATUS err; + Config config; + UINT64 init_usec; + BOOLEAN menu = FALSE; + CHAR16 uuid[37]; + + InitializeLib(image, sys_table); + init_usec = time_usec(); + efivar_set_time_usec(L"LoaderTimeInitUSec", init_usec); + efivar_set(L"LoaderInfo", L"systemd-boot " GIT_VERSION, FALSE); + + infostr = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + efivar_set(L"LoaderFirmwareInfo", infostr, FALSE); + + typestr = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); + efivar_set(L"LoaderFirmwareType", typestr, FALSE); + + (void) efivar_set_raw(&loader_guid, L"LoaderFeatures", &loader_features, sizeof(loader_features), FALSE); + + err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, + image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(err)) { + Print(L"Error getting a LoadedImageProtocol handle: %r", err); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return err; + } + + /* export the device path this image is started from */ + if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) + efivar_set(L"LoaderDevicePartUUID", uuid, FALSE); + + root_dir = LibOpenRoot(loaded_image->DeviceHandle); + if (!root_dir) { + Print(L"Unable to open root directory."); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return EFI_LOAD_ERROR; + } + + if (secure_boot_enabled() && shim_loaded()) { + err = security_policy_install(); + if (EFI_ERROR(err)) { + Print(L"Error installing security policy: %r ", err); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return err; + } + } + + /* the filesystem path to this image, to prevent adding ourselves to the menu */ + loaded_image_path = DevicePathToStr(loaded_image->FilePath); + efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE); + + config_load_defaults(&config, root_dir); + + /* scan /EFI/Linux/ directory */ + config_entry_add_linux(&config, loaded_image->DeviceHandle, root_dir); + + /* scan /loader/entries/\*.conf files */ + config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path); + + /* Similar, but on any XBOOTLDR partition */ + config_load_xbootldr(&config, loaded_image->DeviceHandle); + + /* sort entries after version number */ + config_sort_entries(&config); + + /* if we find some well-known loaders, add them to the end of the list */ + config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, NULL, + L"auto-windows", 'w', L"Windows Boot Manager", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi"); + config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, NULL, + L"auto-efi-shell", 's', L"EFI Shell", L"\\shell" EFI_MACHINE_TYPE_NAME ".efi"); + config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path, + L"auto-efi-default", '\0', L"EFI Default Loader", L"\\EFI\\Boot\\boot" EFI_MACHINE_TYPE_NAME ".efi"); + config_entry_add_osx(&config); + + if (config.auto_firmware && efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) { + UINT64 osind = (UINT64)*b; + + if (osind & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) + config_entry_add_call(&config, + L"auto-reboot-to-firmware-setup", + L"Reboot Into Firmware Interface", + reboot_into_firmware); + FreePool(b); + } + + if (config.entry_count == 0) { + Print(L"No loader found. Configuration files in \\loader\\entries\\*.conf are needed."); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + goto out; + } + + config_write_entries_to_variable(&config); + + config_title_generate(&config); + + /* select entry by configured pattern or EFI LoaderDefaultEntry= variable */ + config_default_entry_select(&config); + + /* if no configured entry to select from was found, enable the menu */ + if (config.idx_default == -1) { + config.idx_default = 0; + if (config.timeout_sec == 0) + config.timeout_sec = 10; + } + + /* select entry or show menu when key is pressed or timeout is set */ + if (config.force_menu || config.timeout_sec > 0) + menu = TRUE; + else { + UINT64 key; + + err = console_key_read(&key, FALSE); + if (!EFI_ERROR(err)) { + INT16 idx; + + /* find matching key in config entries */ + idx = entry_lookup_key(&config, config.idx_default, KEYCHAR(key)); + if (idx >= 0) + config.idx_default = idx; + else + menu = TRUE; + } + } + + for (;;) { + ConfigEntry *entry; + + entry = config.entries[config.idx_default]; + if (menu) { + efivar_set_time_usec(L"LoaderTimeMenuUSec", 0); + uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x10000, 0, NULL); + if (!menu_run(&config, &entry, loaded_image_path)) + break; + } + + /* run special entry like "reboot" */ + if (entry->call) { + entry->call(); + continue; + } + + config_entry_bump_counters(entry, root_dir); + + /* Export the selected boot entry to the system */ + (VOID) efivar_set(L"LoaderEntrySelected", entry->id, FALSE); + + /* Optionally, read a random seed off the ESP and pass it to the OS */ + (VOID) process_random_seed(root_dir, config.random_seed_mode); + + uefi_call_wrapper(BS->SetWatchdogTimer, 4, 5 * 60, 0x10000, 0, NULL); + err = image_start(image, &config, entry); + if (EFI_ERROR(err)) { + graphics_mode(FALSE); + Print(L"\nFailed to execute %s (%s): %r\n", entry->title, entry->loader, err); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + goto out; + } + + menu = TRUE; + config.timeout_sec = 0; + } + err = EFI_SUCCESS; +out: + FreePool(loaded_image_path); + config_free(&config); + uefi_call_wrapper(root_dir->Close, 1, root_dir); + uefi_call_wrapper(BS->CloseProtocol, 4, image, &LoadedImageProtocol, image, NULL); + return err; +} diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c new file mode 100644 index 00000000..7f6bad15 --- /dev/null +++ b/src/boot/efi/console.c @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "console.h" +#include "util.h" + +#define SYSTEM_FONT_WIDTH 8 +#define SYSTEM_FONT_HEIGHT 19 + +#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ + { 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } } + +struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; + +typedef EFI_STATUS (EFIAPI *EFI_INPUT_RESET_EX)( + struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + BOOLEAN ExtendedVerification +); + +typedef UINT8 EFI_KEY_TOGGLE_STATE; + +typedef struct { + UINT32 KeyShiftState; + EFI_KEY_TOGGLE_STATE KeyToggleState; +} EFI_KEY_STATE; + +typedef struct { + EFI_INPUT_KEY Key; + EFI_KEY_STATE KeyState; +} EFI_KEY_DATA; + +typedef EFI_STATUS (EFIAPI *EFI_INPUT_READ_KEY_EX)( + struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + EFI_KEY_DATA *KeyData +); + +typedef EFI_STATUS (EFIAPI *EFI_SET_STATE)( + struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + EFI_KEY_TOGGLE_STATE *KeyToggleState +); + +typedef EFI_STATUS (EFIAPI *EFI_KEY_NOTIFY_FUNCTION)( + EFI_KEY_DATA *KeyData +); + +typedef EFI_STATUS (EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)( + struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + EFI_KEY_DATA KeyData, + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + VOID **NotifyHandle +); + +typedef EFI_STATUS (EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)( + struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + VOID *NotificationHandle +); + +typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL { + EFI_INPUT_RESET_EX Reset; + EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx; + EFI_EVENT WaitForKeyEx; + EFI_SET_STATE SetState; + EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify; + EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify; +} EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; + +EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) { + EFI_GUID EfiSimpleTextInputExProtocolGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; + static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx; + static BOOLEAN checked; + UINTN index; + EFI_INPUT_KEY k; + EFI_STATUS err; + + if (!checked) { + err = LibLocateProtocol(&EfiSimpleTextInputExProtocolGuid, (VOID **)&TextInputEx); + if (EFI_ERROR(err)) + TextInputEx = NULL; + + checked = TRUE; + } + + /* wait until key is pressed */ + if (wait) + uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index); + + if (TextInputEx) { + EFI_KEY_DATA keydata; + UINT64 keypress; + + err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata); + if (!EFI_ERROR(err)) { + UINT32 shift = 0; + + /* do not distinguish between left and right keys */ + if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) { + if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED)) + shift |= EFI_CONTROL_PRESSED; + if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED)) + shift |= EFI_ALT_PRESSED; + }; + + /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */ + keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar); + if (keypress > 0) { + *key = keypress; + return 0; + } + } + } + + /* fallback for firmware which does not support SimpleTextInputExProtocol + * + * This is also called in case ReadKeyStrokeEx did not return a key, because + * some broken firmwares offer SimpleTextInputExProtocol, but never actually + * handle any key. */ + err = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k); + if (EFI_ERROR(err)) + return err; + + *key = KEYPRESS(0, k.ScanCode, k.UnicodeChar); + return 0; +} + +static EFI_STATUS change_mode(UINTN mode) { + EFI_STATUS err; + + err = uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, mode); + + /* Special case mode 1: when using OVMF and qemu, setting it returns error + * and breaks console output. */ + if (EFI_ERROR(err) && mode == 1) + uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, (UINTN)0); + + return err; +} + +static UINT64 text_area_from_font_size(void) { + EFI_STATUS err; + UINT64 text_area; + UINTN rows, columns; + + err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &columns, &rows); + if (EFI_ERROR(err)) { + columns = 80; + rows = 25; + } + + text_area = SYSTEM_FONT_WIDTH * SYSTEM_FONT_HEIGHT * (UINT64)rows * (UINT64)columns; + + return text_area; +} + +static EFI_STATUS mode_auto(UINTN *mode) { + const UINT32 HORIZONTAL_MAX_OK = 1920; + const UINT32 VERTICAL_MAX_OK = 1080; + const UINT64 VIEWPORT_RATIO = 10; + UINT64 screen_area, text_area; + EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + EFI_STATUS err; + BOOLEAN keep = FALSE; + + err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput); + if (!EFI_ERROR(err) && GraphicsOutput->Mode && GraphicsOutput->Mode->Info) { + Info = GraphicsOutput->Mode->Info; + + /* Start verifying if we are in a resolution larger than Full HD + * (1920x1080). If we're not, assume we're in a good mode and do not + * try to change it. */ + if (Info->HorizontalResolution <= HORIZONTAL_MAX_OK && Info->VerticalResolution <= VERTICAL_MAX_OK) + keep = TRUE; + /* For larger resolutions, calculate the ratio of the total screen + * area to the text viewport area. If it's less than 10 times bigger, + * then assume the text is readable and keep the text mode. */ + else { + screen_area = (UINT64)Info->HorizontalResolution * (UINT64)Info->VerticalResolution; + text_area = text_area_from_font_size(); + + if (text_area != 0 && screen_area/text_area < VIEWPORT_RATIO) + keep = TRUE; + } + } + + if (keep) { + /* Just clear the screen instead of changing the mode and return. */ + *mode = ST->ConOut->Mode->Mode; + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + return EFI_SUCCESS; + } + + /* If we reached here, then we have a high resolution screen and the text + * viewport is less than 10% the screen area, so the firmware developer + * screwed up. Try to switch to a better mode. Mode number 2 is first non + * standard mode, which is provided by the device manufacturer, so it should + * be a good mode. + * Note: MaxMode is the number of modes, not the last mode. */ + if (ST->ConOut->Mode->MaxMode > 2) + *mode = 2; + /* Try again with mode different than zero (assume user requests + * auto mode due to some problem with mode zero). */ + else if (ST->ConOut->Mode->MaxMode == 2) + *mode = 1; + /* Else force mode change to zero. */ + else + *mode = 0; + + return change_mode(*mode); +} + +EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how) { + if (how == CONSOLE_MODE_AUTO) + return mode_auto(mode); + + if (how == CONSOLE_MODE_MAX) { + /* Note: MaxMode is the number of modes, not the last mode. */ + if (ST->ConOut->Mode->MaxMode > 0) + *mode = ST->ConOut->Mode->MaxMode-1; + else + *mode = 0; + } + + return change_mode(*mode); +} diff --git a/src/boot/efi/console.h b/src/boot/efi/console.h new file mode 100644 index 00000000..b9ed6c70 --- /dev/null +++ b/src/boot/efi/console.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#define EFI_SHIFT_STATE_VALID 0x80000000 +#define EFI_RIGHT_CONTROL_PRESSED 0x00000004 +#define EFI_LEFT_CONTROL_PRESSED 0x00000008 +#define EFI_RIGHT_ALT_PRESSED 0x00000010 +#define EFI_LEFT_ALT_PRESSED 0x00000020 + +#define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED) +#define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED) +#define KEYPRESS(keys, scan, uni) ((((UINT64)keys) << 32) | (((UINT64)scan) << 16) | (uni)) +#define KEYCHAR(k) ((k) & 0xffff) +#define CHAR_CTRL(c) ((c) - 'a' + 1) + +enum console_mode_change_type { + CONSOLE_MODE_KEEP = 0, + CONSOLE_MODE_SET, + CONSOLE_MODE_AUTO, + CONSOLE_MODE_MAX, +}; + +EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait); +EFI_STATUS console_set_mode(UINTN *mode, enum console_mode_change_type how); diff --git a/src/boot/efi/crc32.c b/src/boot/efi/crc32.c new file mode 100644 index 00000000..46b9aeea --- /dev/null +++ b/src/boot/efi/crc32.c @@ -0,0 +1,142 @@ +/* This is copied from util-linux, which in turn copied in the version from Gary S. Brown */ + +/* + * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or + * code or tables extracted from it, as desired without restriction. + * + * First, the polynomial itself and its table of feedback terms. The + * polynomial is + * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 + * + * Note that we take it "backwards" and put the highest-order term in + * the lowest-order bit. The X^32 term is "implied"; the LSB is the + * X^31 term, etc. The X^0 term (usually shown as "+1") results in + * the MSB being 1. + * + * Note that the usual hardware shift register implementation, which + * is what we're using (we're merely optimizing it by doing eight-bit + * chunks at a time) shifts bits into the lowest-order term. In our + * implementation, that means shifting towards the right. Why do we + * do it this way? Because the calculated CRC must be transmitted in + * order from highest-order term to lowest-order term. UARTs transmit + * characters in order from LSB to MSB. By storing the CRC this way, + * we hand it to the UART in the order low-byte to high-byte; the UART + * sends each low-bit to high-bit; and the result is transmission bit + * by bit from highest- to lowest-order term without requiring any bit + * shuffling on our part. Reception works similarly. + * + * The feedback terms table consists of 256, 32-bit entries. Notes + * + * The table can be generated at runtime if desired; code to do so + * is shown later. It might not be obvious, but the feedback + * terms simply represent the results of eight shift/xor opera- + * tions for all combinations of data and CRC register values. + * + * The values must be right-shifted by eight bits by the "updcrc" + * logic; the shift must be unsigned (bring in zeroes). On some + * hardware you could probably optimize the shift in assembler by + * using byte-swap instructions. + * polynomial $edb88320 + * + */ + +#include "crc32.h" + +static const UINT32 crc32_tab[] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; + +static inline UINT32 crc32_add_char(UINT32 crc, UINT8 c) { + return crc32_tab[(crc ^ c) & 0xff] ^ (crc >> 8); +} + +/* + * This a generic crc32() function, it takes seed as an argument, + * and does __not__ xor at the end. Then individual users can do + * whatever they need. + */ +UINT32 crc32(UINT32 seed, const VOID *buf, UINTN len) { + const UINT8 *p = buf; + UINT32 crc = seed; + + while (len > 0) { + crc = crc32_add_char(crc, *p++); + len--; + } + + return crc; +} + +UINT32 crc32_exclude_offset( + UINT32 seed, + const VOID *buf, + UINTN len, + UINTN exclude_off, + UINTN exclude_len) { + + const UINT8 *p = buf; + UINT32 crc = seed; + UINTN i; + + for (i = 0; i < len; i++) { + UINT8 x = *p++; + + if (i >= exclude_off && i < exclude_off + exclude_len) + x = 0; + + crc = crc32_add_char(crc, x); + } + + return crc; +} diff --git a/src/boot/efi/crc32.h b/src/boot/efi/crc32.h new file mode 100644 index 00000000..64150ee9 --- /dev/null +++ b/src/boot/efi/crc32.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +UINT32 crc32(UINT32 seed, const VOID *buf, UINTN len); +UINT32 crc32_exclude_offset(UINT32 seed, const VOID *buf, UINTN len, UINTN exclude_off, UINTN exclude_len); diff --git a/src/boot/efi/disk.c b/src/boot/efi/disk.c new file mode 100644 index 00000000..49ee81b4 --- /dev/null +++ b/src/boot/efi/disk.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "util.h" + +EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]) { + EFI_DEVICE_PATH *device_path; + + /* export the device path this image is started from */ + device_path = DevicePathFromHandle(handle); + if (device_path) { + _cleanup_freepool_ EFI_DEVICE_PATH *paths = NULL; + EFI_DEVICE_PATH *path; + + paths = UnpackDevicePath(device_path); + for (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) { + HARDDRIVE_DEVICE_PATH *drive; + + if (DevicePathType(path) != MEDIA_DEVICE_PATH) + continue; + if (DevicePathSubType(path) != MEDIA_HARDDRIVE_DP) + continue; + drive = (HARDDRIVE_DEVICE_PATH *)path; + if (drive->SignatureType != SIGNATURE_TYPE_GUID) + continue; + + GuidToString(uuid, (EFI_GUID *)&drive->Signature); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} diff --git a/src/boot/efi/disk.h b/src/boot/efi/disk.h new file mode 100644 index 00000000..41c4cce4 --- /dev/null +++ b/src/boot/efi/disk.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]); diff --git a/src/boot/efi/graphics.c b/src/boot/efi/graphics.c new file mode 100644 index 00000000..9b5003a8 --- /dev/null +++ b/src/boot/efi/graphics.c @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/* + * Copyright © 2013 Intel Corporation + * Authored by Joonas Lahtinen + */ + +#include +#include + +#include "graphics.h" +#include "util.h" + +EFI_STATUS graphics_mode(BOOLEAN on) { + #define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \ + { 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } }; + + struct _EFI_CONSOLE_CONTROL_PROTOCOL; + + typedef enum { + EfiConsoleControlScreenText, + EfiConsoleControlScreenGraphics, + EfiConsoleControlScreenMaxValue, + } EFI_CONSOLE_CONTROL_SCREEN_MODE; + + typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE)( + struct _EFI_CONSOLE_CONTROL_PROTOCOL *This, + EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + BOOLEAN *UgaExists, + BOOLEAN *StdInLocked + ); + + typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE)( + struct _EFI_CONSOLE_CONTROL_PROTOCOL *This, + EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ); + + typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN)( + struct _EFI_CONSOLE_CONTROL_PROTOCOL *This, + CHAR16 *Password + ); + + typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL { + EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; + } EFI_CONSOLE_CONTROL_PROTOCOL; + + EFI_GUID ConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; + EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; + EFI_CONSOLE_CONTROL_SCREEN_MODE new; + EFI_CONSOLE_CONTROL_SCREEN_MODE current; + BOOLEAN uga_exists; + BOOLEAN stdin_locked; + EFI_STATUS err; + + err = LibLocateProtocol(&ConsoleControlProtocolGuid, (VOID **)&ConsoleControl); + if (EFI_ERROR(err)) + /* console control protocol is nonstandard and might not exist. */ + return err == EFI_NOT_FOUND ? EFI_SUCCESS : err; + + /* check current mode */ + err = uefi_call_wrapper(ConsoleControl->GetMode, 4, ConsoleControl, ¤t, &uga_exists, &stdin_locked); + if (EFI_ERROR(err)) + return err; + + /* do not touch the mode */ + new = on ? EfiConsoleControlScreenGraphics : EfiConsoleControlScreenText; + if (new == current) + return EFI_SUCCESS; + + err = uefi_call_wrapper(ConsoleControl->SetMode, 2, ConsoleControl, new); + + /* some firmware enables the cursor when switching modes */ + uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); + + return err; +} diff --git a/src/boot/efi/graphics.h b/src/boot/efi/graphics.h new file mode 100644 index 00000000..809e878d --- /dev/null +++ b/src/boot/efi/graphics.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/* + * Copyright © 2013 Intel Corporation + * Authored by Joonas Lahtinen + */ +#pragma once + +EFI_STATUS graphics_mode(BOOLEAN on); diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c new file mode 100644 index 00000000..00a3551e --- /dev/null +++ b/src/boot/efi/linux.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "linux.h" +#include "util.h" + +#ifdef __i386__ +#define __regparm0__ __attribute__((regparm(0))) +#else +#define __regparm0__ +#endif + +typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct boot_params *params) __regparm0__; +static VOID linux_efi_handover(EFI_HANDLE image, struct boot_params *params) { + handover_f handover; + UINTN start = (UINTN)params->hdr.code32_start; + +#ifdef __x86_64__ + asm volatile ("cli"); + start += 512; +#endif + handover = (handover_f)(start + params->hdr.handover_offset); + handover(image, ST, params); +} + +EFI_STATUS linux_exec(EFI_HANDLE *image, + CHAR8 *cmdline, UINTN cmdline_len, + UINTN linux_addr, + UINTN initrd_addr, UINTN initrd_size) { + struct boot_params *image_params; + struct boot_params *boot_params; + UINT8 setup_sectors; + EFI_PHYSICAL_ADDRESS addr; + EFI_STATUS err; + + image_params = (struct boot_params *) linux_addr; + + if (image_params->hdr.boot_flag != 0xAA55 || + image_params->hdr.header != SETUP_MAGIC || + image_params->hdr.version < 0x20b || + !image_params->hdr.relocatable_kernel) + return EFI_LOAD_ERROR; + + boot_params = (struct boot_params *) 0xFFFFFFFF; + err = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData, + EFI_SIZE_TO_PAGES(0x4000), (EFI_PHYSICAL_ADDRESS*) &boot_params); + if (EFI_ERROR(err)) + return err; + + ZeroMem(boot_params, 0x4000); + CopyMem(&boot_params->hdr, &image_params->hdr, sizeof(struct setup_header)); + boot_params->hdr.type_of_loader = 0xff; + setup_sectors = image_params->hdr.setup_sects > 0 ? image_params->hdr.setup_sects : 4; + boot_params->hdr.code32_start = (UINT32)linux_addr + (setup_sectors + 1) * 512; + + if (cmdline) { + addr = 0xA0000; + err = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData, + EFI_SIZE_TO_PAGES(cmdline_len + 1), &addr); + if (EFI_ERROR(err)) + return err; + CopyMem((VOID *)(UINTN)addr, cmdline, cmdline_len); + ((CHAR8 *)(UINTN)addr)[cmdline_len] = 0; + boot_params->hdr.cmd_line_ptr = (UINT32)addr; + } + + boot_params->hdr.ramdisk_image = (UINT32)initrd_addr; + boot_params->hdr.ramdisk_size = (UINT32)initrd_size; + + linux_efi_handover(image, boot_params); + return EFI_LOAD_ERROR; +} diff --git a/src/boot/efi/linux.h b/src/boot/efi/linux.h new file mode 100644 index 00000000..ec655ce6 --- /dev/null +++ b/src/boot/efi/linux.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#define SETUP_MAGIC 0x53726448 /* "HdrS" */ + +struct setup_header { + UINT8 setup_sects; + UINT16 root_flags; + UINT32 syssize; + UINT16 ram_size; + UINT16 vid_mode; + UINT16 root_dev; + UINT16 boot_flag; + UINT16 jump; + UINT32 header; + UINT16 version; + UINT32 realmode_swtch; + UINT16 start_sys_seg; + UINT16 kernel_version; + UINT8 type_of_loader; + UINT8 loadflags; + UINT16 setup_move_size; + UINT32 code32_start; + UINT32 ramdisk_image; + UINT32 ramdisk_size; + UINT32 bootsect_kludge; + UINT16 heap_end_ptr; + UINT8 ext_loader_ver; + UINT8 ext_loader_type; + UINT32 cmd_line_ptr; + UINT32 initrd_addr_max; + UINT32 kernel_alignment; + UINT8 relocatable_kernel; + UINT8 min_alignment; + UINT16 xloadflags; + UINT32 cmdline_size; + UINT32 hardware_subarch; + UINT64 hardware_subarch_data; + UINT32 payload_offset; + UINT32 payload_length; + UINT64 setup_data; + UINT64 pref_address; + UINT32 init_size; + UINT32 handover_offset; +} __attribute__((packed)); + +/* adapted from linux' bootparam.h */ +struct boot_params { + UINT8 screen_info[64]; // was: struct screen_info + UINT8 apm_bios_info[20]; // was: struct apm_bios_info + UINT8 _pad2[4]; + UINT64 tboot_addr; + UINT8 ist_info[16]; // was: struct ist_info + UINT8 _pad3[16]; + UINT8 hd0_info[16]; + UINT8 hd1_info[16]; + UINT8 sys_desc_table[16]; // was: struct sys_desc_table + UINT8 olpc_ofw_header[16]; // was: struct olpc_ofw_header + UINT32 ext_ramdisk_image; + UINT32 ext_ramdisk_size; + UINT32 ext_cmd_line_ptr; + UINT8 _pad4[116]; + UINT8 edid_info[128]; // was: struct edid_info + UINT8 efi_info[32]; // was: struct efi_info + UINT32 alt_mem_k; + UINT32 scratch; + UINT8 e820_entries; + UINT8 eddbuf_entries; + UINT8 edd_mbr_sig_buf_entries; + UINT8 kbd_status; + UINT8 secure_boot; + UINT8 _pad5[2]; + UINT8 sentinel; + UINT8 _pad6[1]; + struct setup_header hdr; + UINT8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; + UINT32 edd_mbr_sig_buffer[16]; // was: edd_mbr_sig_buffer[EDD_MBR_SIG_MAX] + UINT8 e820_table[20*128]; // was: struct boot_e820_entry e820_table[E820_MAX_ENTRIES_ZEROPAGE] + UINT8 _pad8[48]; + UINT8 eddbuf[6*82]; // was: struct edd_info eddbuf[EDDMAXNR] + UINT8 _pad9[276]; +} __attribute__((packed)); + +EFI_STATUS linux_exec(EFI_HANDLE *image, + CHAR8 *cmdline, UINTN cmdline_size, + UINTN linux_addr, + UINTN initrd_addr, UINTN initrd_size); diff --git a/src/boot/efi/loader-features.h b/src/boot/efi/loader-features.h new file mode 100644 index 00000000..b3a1f79d --- /dev/null +++ b/src/boot/efi/loader-features.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#ifndef UINT64_C +# define UINT64_C(c) (c ## ULL) +#endif + +#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT (UINT64_C(1) << 0) +#define EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT (UINT64_C(1) << 1) +#define EFI_LOADER_FEATURE_ENTRY_DEFAULT (UINT64_C(1) << 2) +#define EFI_LOADER_FEATURE_ENTRY_ONESHOT (UINT64_C(1) << 3) +#define EFI_LOADER_FEATURE_BOOT_COUNTING (UINT64_C(1) << 4) +#define EFI_LOADER_FEATURE_XBOOTLDR (UINT64_C(1) << 5) +#define EFI_LOADER_FEATURE_RANDOM_SEED (UINT64_C(1) << 6) diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c new file mode 100644 index 00000000..768cb51d --- /dev/null +++ b/src/boot/efi/measure.c @@ -0,0 +1,317 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if ENABLE_TPM + +#include +#include +#include "measure.h" + +#define EFI_TCG_PROTOCOL_GUID { 0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd} } + +typedef struct _TCG_VERSION { + UINT8 Major; + UINT8 Minor; + UINT8 RevMajor; + UINT8 RevMinor; +} TCG_VERSION; + +typedef struct tdEFI_TCG2_VERSION { + UINT8 Major; + UINT8 Minor; +} EFI_TCG2_VERSION; + +typedef struct _TCG_BOOT_SERVICE_CAPABILITY { + UINT8 Size; + struct _TCG_VERSION StructureVersion; + struct _TCG_VERSION ProtocolSpecVersion; + UINT8 HashAlgorithmBitmap; + BOOLEAN TPMPresentFlag; + BOOLEAN TPMDeactivatedFlag; +} TCG_BOOT_SERVICE_CAPABILITY; + +typedef struct tdTREE_BOOT_SERVICE_CAPABILITY { + UINT8 Size; + EFI_TCG2_VERSION StructureVersion; + EFI_TCG2_VERSION ProtocolVersion; + UINT32 HashAlgorithmBitmap; + UINT32 SupportedEventLogs; + BOOLEAN TrEEPresentFlag; + UINT16 MaxCommandSize; + UINT16 MaxResponseSize; + UINT32 ManufacturerID; +} TREE_BOOT_SERVICE_CAPABILITY; + +typedef UINT32 TCG_ALGORITHM_ID; +#define TCG_ALG_SHA 0x00000004 // The SHA1 algorithm + +#define SHA1_DIGEST_SIZE 20 + +typedef struct _TCG_DIGEST { + UINT8 Digest[SHA1_DIGEST_SIZE]; +} TCG_DIGEST; + +#define EV_IPL 13 + +typedef struct _TCG_PCR_EVENT { + UINT32 PCRIndex; + UINT32 EventType; + struct _TCG_DIGEST digest; + UINT32 EventSize; + UINT8 Event[1]; +} TCG_PCR_EVENT; + +INTERFACE_DECL(_EFI_TCG); + +typedef EFI_STATUS(EFIAPI * EFI_TCG_STATUS_CHECK) (IN struct _EFI_TCG * This, + OUT struct _TCG_BOOT_SERVICE_CAPABILITY * ProtocolCapability, + OUT UINT32 * TCGFeatureFlags, + OUT EFI_PHYSICAL_ADDRESS * EventLogLocation, + OUT EFI_PHYSICAL_ADDRESS * EventLogLastEntry); + +typedef EFI_STATUS(EFIAPI * EFI_TCG_HASH_ALL) (IN struct _EFI_TCG * This, + IN UINT8 * HashData, + IN UINT64 HashDataLen, + IN TCG_ALGORITHM_ID AlgorithmId, + IN OUT UINT64 * HashedDataLen, IN OUT UINT8 ** HashedDataResult); + +typedef EFI_STATUS(EFIAPI * EFI_TCG_LOG_EVENT) (IN struct _EFI_TCG * This, + IN struct _TCG_PCR_EVENT * TCGLogData, + IN OUT UINT32 * EventNumber, IN UINT32 Flags); + +typedef EFI_STATUS(EFIAPI * EFI_TCG_PASS_THROUGH_TO_TPM) (IN struct _EFI_TCG * This, + IN UINT32 TpmInputParameterBlockSize, + IN UINT8 * TpmInputParameterBlock, + IN UINT32 TpmOutputParameterBlockSize, + IN UINT8 * TpmOutputParameterBlock); + +typedef EFI_STATUS(EFIAPI * EFI_TCG_HASH_LOG_EXTEND_EVENT) (IN struct _EFI_TCG * This, + IN EFI_PHYSICAL_ADDRESS HashData, + IN UINT64 HashDataLen, + IN TCG_ALGORITHM_ID AlgorithmId, + IN struct _TCG_PCR_EVENT * TCGLogData, + IN OUT UINT32 * EventNumber, + OUT EFI_PHYSICAL_ADDRESS * EventLogLastEntry); + +typedef struct _EFI_TCG { + EFI_TCG_STATUS_CHECK StatusCheck; + EFI_TCG_HASH_ALL HashAll; + EFI_TCG_LOG_EVENT LogEvent; + EFI_TCG_PASS_THROUGH_TO_TPM PassThroughToTPM; + EFI_TCG_HASH_LOG_EXTEND_EVENT HashLogExtendEvent; +} EFI_TCG; + +#define EFI_TCG2_PROTOCOL_GUID {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }} + +typedef struct tdEFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL; + +typedef UINT32 EFI_TCG2_EVENT_LOG_BITMAP; +typedef UINT32 EFI_TCG2_EVENT_LOG_FORMAT; +typedef UINT32 EFI_TCG2_EVENT_ALGORITHM_BITMAP; + +typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY { + UINT8 Size; + EFI_TCG2_VERSION StructureVersion; + EFI_TCG2_VERSION ProtocolVersion; + EFI_TCG2_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap; + EFI_TCG2_EVENT_LOG_BITMAP SupportedEventLogs; + BOOLEAN TPMPresentFlag; + UINT16 MaxCommandSize; + UINT16 MaxResponseSize; + UINT32 ManufacturerID; + UINT32 NumberOfPCRBanks; + EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrBanks; +} EFI_TCG2_BOOT_SERVICE_CAPABILITY; + +#define EFI_TCG2_EVENT_HEADER_VERSION 1 + +typedef struct { + UINT32 HeaderSize; + UINT16 HeaderVersion; + UINT32 PCRIndex; + UINT32 EventType; +} __attribute__((packed)) EFI_TCG2_EVENT_HEADER; + +typedef struct tdEFI_TCG2_EVENT { + UINT32 Size; + EFI_TCG2_EVENT_HEADER Header; + UINT8 Event[1]; +} __attribute__((packed)) EFI_TCG2_EVENT; + +typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_CAPABILITY) (IN EFI_TCG2_PROTOCOL * This, + IN OUT EFI_TCG2_BOOT_SERVICE_CAPABILITY * ProtocolCapability); + +typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_EVENT_LOG) (IN EFI_TCG2_PROTOCOL * This, + IN EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat, + OUT EFI_PHYSICAL_ADDRESS * EventLogLocation, + OUT EFI_PHYSICAL_ADDRESS * EventLogLastEntry, + OUT BOOLEAN * EventLogTruncated); + +typedef EFI_STATUS(EFIAPI * EFI_TCG2_HASH_LOG_EXTEND_EVENT) (IN EFI_TCG2_PROTOCOL * This, + IN UINT64 Flags, + IN EFI_PHYSICAL_ADDRESS DataToHash, + IN UINT64 DataToHashLen, IN EFI_TCG2_EVENT * EfiTcgEvent); + +typedef EFI_STATUS(EFIAPI * EFI_TCG2_SUBMIT_COMMAND) (IN EFI_TCG2_PROTOCOL * This, + IN UINT32 InputParameterBlockSize, + IN UINT8 * InputParameterBlock, + IN UINT32 OutputParameterBlockSize, IN UINT8 * OutputParameterBlock); + +typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This, OUT UINT32 * ActivePcrBanks); + +typedef EFI_STATUS(EFIAPI * EFI_TCG2_SET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This, IN UINT32 ActivePcrBanks); + +typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This, + OUT UINT32 * OperationPresent, OUT UINT32 * Response); + +typedef struct tdEFI_TCG2_PROTOCOL { + EFI_TCG2_GET_CAPABILITY GetCapability; + EFI_TCG2_GET_EVENT_LOG GetEventLog; + EFI_TCG2_HASH_LOG_EXTEND_EVENT HashLogExtendEvent; + EFI_TCG2_SUBMIT_COMMAND SubmitCommand; + EFI_TCG2_GET_ACTIVE_PCR_BANKS GetActivePcrBanks; + EFI_TCG2_SET_ACTIVE_PCR_BANKS SetActivePcrBanks; + EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS GetResultOfSetActivePcrBanks; +} EFI_TCG2; + +static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, + UINTN buffer_size, const CHAR16 *description) { + EFI_STATUS status; + TCG_PCR_EVENT *tcg_event; + UINT32 event_number; + EFI_PHYSICAL_ADDRESS event_log_last; + UINTN desc_len; + + desc_len = (StrLen(description) + 1) * sizeof(CHAR16); + + tcg_event = AllocateZeroPool(desc_len + sizeof(TCG_PCR_EVENT)); + + if (!tcg_event) + return EFI_OUT_OF_RESOURCES; + + tcg_event->EventSize = desc_len; + CopyMem((VOID *) & tcg_event->Event[0], (VOID *) description, desc_len); + + tcg_event->PCRIndex = pcrindex; + tcg_event->EventType = EV_IPL; + + event_number = 1; + status = uefi_call_wrapper(tcg->HashLogExtendEvent, 7, + (EFI_TCG *) tcg, buffer, buffer_size, TCG_ALG_SHA, tcg_event, &event_number, &event_log_last); + + if (EFI_ERROR(status)) + return status; + + uefi_call_wrapper(BS->FreePool, 1, tcg_event); + + return EFI_SUCCESS; +} + +static EFI_STATUS tpm2_measure_to_pcr_and_event_log(const EFI_TCG2 *tcg, UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, + UINT64 buffer_size, const CHAR16 *description) { + EFI_STATUS status; + EFI_TCG2_EVENT *tcg_event; + UINTN desc_len; + + desc_len = StrLen(description) * sizeof(CHAR16); + + tcg_event = AllocateZeroPool(sizeof(*tcg_event) - sizeof(tcg_event->Event) + desc_len + 1); + + if (!tcg_event) + return EFI_OUT_OF_RESOURCES; + + tcg_event->Size = sizeof(*tcg_event) - sizeof(tcg_event->Event) + desc_len + 1; + tcg_event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER); + tcg_event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION; + tcg_event->Header.PCRIndex = pcrindex; + tcg_event->Header.EventType = EV_IPL; + + CopyMem((VOID *) tcg_event->Event, (VOID *) description, desc_len); + + status = uefi_call_wrapper(tcg->HashLogExtendEvent, 5, (EFI_TCG2 *) tcg, 0, buffer, (UINT64) buffer_size, tcg_event); + + uefi_call_wrapper(BS->FreePool, 1, tcg_event); + + if (EFI_ERROR(status)) + return status; + + return EFI_SUCCESS; +} + +static EFI_TCG * tcg1_interface_check(void) { + EFI_GUID tpm_guid = EFI_TCG_PROTOCOL_GUID; + EFI_STATUS status; + EFI_TCG *tcg; + TCG_BOOT_SERVICE_CAPABILITY capability; + UINT32 features; + EFI_PHYSICAL_ADDRESS event_log_location; + EFI_PHYSICAL_ADDRESS event_log_last_entry; + + status = LibLocateProtocol(&tpm_guid, (void **) &tcg); + + if (EFI_ERROR(status)) + return NULL; + + capability.Size = (UINT8) sizeof(capability); + status = uefi_call_wrapper(tcg->StatusCheck, 5, tcg, &capability, &features, &event_log_location, &event_log_last_entry); + + if (EFI_ERROR(status)) + return NULL; + + if (capability.TPMDeactivatedFlag) + return NULL; + + if (!capability.TPMPresentFlag) + return NULL; + + return tcg; +} + +static EFI_TCG2 * tcg2_interface_check() { + EFI_GUID tpm2_guid = EFI_TCG2_PROTOCOL_GUID; + EFI_STATUS status; + EFI_TCG2 *tcg; + EFI_TCG2_BOOT_SERVICE_CAPABILITY capability; + + status = LibLocateProtocol(&tpm2_guid, (void **) &tcg); + + if (EFI_ERROR(status)) + return NULL; + + capability.Size = (UINT8) sizeof(EFI_TCG2_BOOT_SERVICE_CAPABILITY); + status = uefi_call_wrapper(tcg->GetCapability, 2, tcg, &capability); + + if (EFI_ERROR(status)) + return NULL; + + if (capability.StructureVersion.Major == 1 && + capability.StructureVersion.Minor == 0) { + TCG_BOOT_SERVICE_CAPABILITY *caps_1_0; + caps_1_0 = (TCG_BOOT_SERVICE_CAPABILITY *)&capability; + if (caps_1_0->TPMPresentFlag) + return tcg; + } + + if (!capability.TPMPresentFlag) + return NULL; + + return tcg; +} + +EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description) { + EFI_TCG *tpm1; + EFI_TCG2 *tpm2; + + tpm2 = tcg2_interface_check(); + if (tpm2) { + return tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description); + } + + tpm1 = tcg1_interface_check(); + if (tpm1) + return tpm1_measure_to_pcr_and_event_log(tpm1, pcrindex, buffer, buffer_size, description); + + /* No active TPM found, so don't return an error */ + return EFI_SUCCESS; +} + +#endif diff --git a/src/boot/efi/measure.h b/src/boot/efi/measure.h new file mode 100644 index 00000000..ebb6406e --- /dev/null +++ b/src/boot/efi/measure.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description); diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build new file mode 100644 index 00000000..c1fe0459 --- /dev/null +++ b/src/boot/efi/meson.build @@ -0,0 +1,252 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +efi_headers = files(''' + console.h + crc32.h + disk.h + graphics.h + linux.h + measure.h + missing_efi.h + pe.h + random-seed.h + sha256.h + shim.h + splash.h + util.h +'''.split()) + +common_sources = ''' + disk.c + graphics.c + measure.c + pe.c + util.c +'''.split() + +systemd_boot_sources = ''' + boot.c + console.c + crc32.c + random-seed.c + sha256.c + shim.c +'''.split() + +stub_sources = ''' + linux.c + splash.c + stub.c +'''.split() + +if conf.get('ENABLE_EFI') == 1 and get_option('gnu-efi') != 'false' + efi_cc = get_option('efi-cc') + if efi_cc.length() == 0 + efi_cc = cc.cmd_array() + endif + efi_ld = get_option('efi-ld') + if efi_ld == '' + efi_ld = find_program('ld', required: true) + endif + efi_incdir = get_option('efi-includedir') + + gnu_efi_path_arch = '' + foreach name : [gnu_efi_arch, EFI_MACHINE_TYPE_NAME] + if (gnu_efi_path_arch == '' and name != '' and + cc.has_header('@0@/@1@/efibind.h'.format(efi_incdir, name))) + gnu_efi_path_arch = name + endif + endforeach + + if gnu_efi_path_arch != '' and EFI_MACHINE_TYPE_NAME == '' + error('gnu-efi is available, but EFI_MACHINE_TYPE_NAME is unknown') + endif + + efi_libdir = get_option('efi-libdir') + if efi_libdir == '' + # New location first introduced with gnu-efi 3.0.11 + efi_libdir = join_paths('/usr/lib/gnuefi', EFI_MACHINE_TYPE_NAME) + cmd = run_command('test', '-e', efi_libdir) + + if cmd.returncode() != 0 + # Fall back to the old approach + cmd = run_command(efi_cc + ['-print-multi-os-directory']) + if cmd.returncode() == 0 + path = join_paths('/usr/lib', cmd.stdout().strip()) + cmd = run_command('realpath', '-e', path) + if cmd.returncode() == 0 + efi_libdir = cmd.stdout().strip() + endif + endif + endif + endif + + have_gnu_efi = gnu_efi_path_arch != '' and efi_libdir != '' +else + have_gnu_efi = false +endif + +if get_option('gnu-efi') == 'true' and not have_gnu_efi + error('gnu-efi support requested, but headers were not found') +endif + +if have_gnu_efi + efi_conf = configuration_data() + efi_conf.set_quoted('EFI_MACHINE_TYPE_NAME', EFI_MACHINE_TYPE_NAME) + efi_conf.set10('ENABLE_TPM', get_option('tpm')) + efi_conf.set('SD_TPM_PCR', get_option('tpm-pcrindex')) + + efi_config_h = configure_file( + output : 'efi_config.h', + configuration : efi_conf) + + objcopy = find_program('objcopy') + + efi_location_map = [ + # New locations first introduced with gnu-efi 3.0.11 + [join_paths(efi_libdir, 'efi.lds'), + join_paths(efi_libdir, 'crt0.o')], + # Older locations... + [join_paths(efi_libdir, 'gnuefi', 'elf_@0@_efi.lds'.format(gnu_efi_path_arch)), + join_paths(efi_libdir, 'gnuefi', 'crt0-efi-@0@.o'.format(gnu_efi_path_arch))], + [join_paths(efi_libdir, 'elf_@0@_efi.lds'.format(gnu_efi_path_arch)), + join_paths(efi_libdir, 'crt0-efi-@0@.o'.format(gnu_efi_path_arch))]] + efi_lds = '' + foreach location : efi_location_map + if efi_lds == '' + cmd = run_command('test', '-f', location[0]) + if cmd.returncode() == 0 + efi_lds = location[0] + efi_crt0 = location[1] + endif + endif + endforeach + if efi_lds == '' + if get_option('gnu-efi') == 'true' + error('gnu-efi support requested, but cannot find efi.lds') + else + have_gnu_efi = false + endif + endif +endif + +if have_gnu_efi + compile_args = ['-Wall', + '-Wextra', + '-std=gnu90', + '-nostdinc', + '-fpic', + '-fshort-wchar', + '-ffreestanding', + '-fno-strict-aliasing', + '-fno-stack-protector', + '-Wsign-compare', + '-Wno-missing-field-initializers', + '-isystem', efi_incdir, + '-isystem', join_paths(efi_incdir, gnu_efi_path_arch), + '-include', efi_config_h, + '-include', version_h] + if efi_arch == 'x86_64' + compile_args += ['-mno-red-zone', + '-mno-sse', + '-mno-mmx', + '-DEFI_FUNCTION_WRAPPER', + '-DGNU_EFI_USE_MS_ABI'] + elif efi_arch == 'ia32' + compile_args += ['-mno-sse', + '-mno-mmx'] + endif + if get_option('werror') == true + compile_args += ['-Werror'] + endif + if get_option('buildtype') == 'debug' + compile_args += ['-ggdb', '-O0'] + elif get_option('buildtype') == 'debugoptimized' + compile_args += ['-ggdb', '-Og'] + else + compile_args += ['-O2'] + endif + + efi_ldflags = ['-T', efi_lds, + '-shared', + '-Bsymbolic', + '-nostdlib', + '-znocombreloc', + '-L', efi_libdir, + efi_crt0] + if efi_arch == 'aarch64' or efi_arch == 'arm' + # Aarch64 and ARM32 don't have an EFI capable objcopy. Use 'binary' + # instead, and add required symbols manually. + efi_ldflags += ['--defsym=EFI_SUBSYSTEM=0xa'] + efi_format = ['-O', 'binary'] + else + efi_format = ['--target=efi-app-@0@'.format(gnu_efi_arch)] + endif + + systemd_boot_objects = [] + stub_objects = [] + foreach file : common_sources + systemd_boot_sources + stub_sources + o_file = custom_target(file + '.o', + input : file, + output : file + '.o', + command : efi_cc + ['-c', '@INPUT@', '-o', '@OUTPUT@'] + + compile_args, + depend_files : efi_headers) + if (common_sources + systemd_boot_sources).contains(file) + systemd_boot_objects += o_file + endif + if (common_sources + stub_sources).contains(file) + stub_objects += o_file + endif + endforeach + + libgcc_file_name = run_command(efi_cc + ['-print-libgcc-file-name']).stdout().strip() + systemd_boot_efi_name = 'systemd-boot@0@.efi'.format(EFI_MACHINE_TYPE_NAME) + stub_efi_name = 'linux@0@.efi.stub'.format(EFI_MACHINE_TYPE_NAME) + no_undefined_symbols = find_program('no-undefined-symbols.sh') + + foreach tuple : [['systemd_boot.so', systemd_boot_efi_name, systemd_boot_objects], + ['stub.so', stub_efi_name, stub_objects]] + so = custom_target( + tuple[0], + input : tuple[2], + output : tuple[0], + command : [efi_ld, '-o', '@OUTPUT@'] + + efi_ldflags + tuple[2] + + ['-lefi', '-lgnuefi', libgcc_file_name]) + + if want_tests != 'false' + test('no-undefined-symbols-' + tuple[0], + no_undefined_symbols, + args : [so]) + endif + + stub = custom_target( + tuple[1], + input : so, + output : tuple[1], + command : [objcopy, + '-j', '.text', + '-j', '.sdata', + '-j', '.data', + '-j', '.dynamic', + '-j', '.dynsym', + '-j', '.rel*'] + + efi_format + + ['@INPUT@', '@OUTPUT@'], + install : true, + install_dir : bootlibdir) + + set_variable(tuple[0].underscorify(), so) + set_variable(tuple[0].underscorify() + '_stub', stub) + endforeach + + ############################################################ + + test_efi_disk_img = custom_target( + 'test-efi-disk.img', + input : [systemd_boot_so, stub_so_stub], + output : 'test-efi-disk.img', + command : [test_efi_create_disk_sh, '@OUTPUT@', + '@INPUT0@', '@INPUT1@', splash_bmp]) +endif diff --git a/src/boot/efi/missing_efi.h b/src/boot/efi/missing_efi.h new file mode 100644 index 00000000..cf301a13 --- /dev/null +++ b/src/boot/efi/missing_efi.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#ifndef EFI_RNG_PROTOCOL_GUID + +#define EFI_RNG_PROTOCOL_GUID \ + { 0x3152bca5, 0xeade, 0x433d, {0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44} } + +typedef EFI_GUID EFI_RNG_ALGORITHM; + +#define EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID \ + {0xa7af67cb, 0x603b, 0x4d42, {0xba, 0x21, 0x70, 0xbf, 0xb6, 0x29, 0x3f, 0x96} } + +#define EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID \ + {0xc5149b43, 0xae85, 0x4f53, {0x99, 0x82, 0xb9, 0x43, 0x35, 0xd3, 0xa9, 0xe7} } + +#define EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID \ + {0x44f0de6e, 0x4d8c, 0x4045, {0xa8, 0xc7, 0x4d, 0xd1, 0x68, 0x85, 0x6b, 0x9e} } + +#define EFI_RNG_ALGORITHM_X9_31_3DES_GUID \ + {0x63c4785a, 0xca34, 0x4012, {0xa3, 0xc8, 0x0b, 0x6a, 0x32, 0x4f, 0x55, 0x46} } + +#define EFI_RNG_ALGORITHM_X9_31_AES_GUID \ + {0xacd03321, 0x777e, 0x4d3d, {0xb1, 0xc8, 0x20, 0xcf, 0xd8, 0x88, 0x20, 0xc9} } + +#define EFI_RNG_ALGORITHM_RAW \ + {0xe43176d7, 0xb6e8, 0x4827, {0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61} } + +INTERFACE_DECL(_EFI_RNG_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_RNG_GET_INFO) ( + IN struct _EFI_RNG_PROTOCOL *This, + IN OUT UINTN *RNGAlgorithmListSize, + OUT EFI_RNG_ALGORITHM *RNGAlgorithmList +); + +typedef +EFI_STATUS +(EFIAPI *EFI_RNG_GET_RNG) ( + IN struct _EFI_RNG_PROTOCOL *This, + IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL + IN UINTN RNGValueLength, + OUT UINT8 *RNGValue +); + +typedef struct _EFI_RNG_PROTOCOL { + EFI_RNG_GET_INFO GetInfo; + EFI_RNG_GET_RNG GetRNG; +} EFI_RNG_PROTOCOL; + +#endif diff --git a/src/boot/efi/no-undefined-symbols.sh b/src/boot/efi/no-undefined-symbols.sh new file mode 100755 index 00000000..84cbd5b4 --- /dev/null +++ b/src/boot/efi/no-undefined-symbols.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -eu + +if nm -D -u "$1" | grep ' U '; then + echo "Undefined symbols detected!" + exit 1 +fi diff --git a/src/boot/efi/pe.c b/src/boot/efi/pe.c new file mode 100644 index 00000000..68f50aec --- /dev/null +++ b/src/boot/efi/pe.c @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "pe.h" +#include "util.h" + +struct DosFileHeader { + UINT8 Magic[2]; + UINT16 LastSize; + UINT16 nBlocks; + UINT16 nReloc; + UINT16 HdrSize; + UINT16 MinAlloc; + UINT16 MaxAlloc; + UINT16 ss; + UINT16 sp; + UINT16 Checksum; + UINT16 ip; + UINT16 cs; + UINT16 RelocPos; + UINT16 nOverlay; + UINT16 reserved[4]; + UINT16 OEMId; + UINT16 OEMInfo; + UINT16 reserved2[10]; + UINT32 ExeHeader; +} __attribute__((packed)); + +#define PE_HEADER_MACHINE_I386 0x014c +#define PE_HEADER_MACHINE_X64 0x8664 +#define PE_HEADER_MACHINE_ARM64 0xaa64 +struct PeFileHeader { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} __attribute__((packed)); + +struct PeHeader { + UINT8 Magic[4]; + struct PeFileHeader FileHeader; +} __attribute__((packed)); + +struct PeSectionHeader { + UINT8 Name[8]; + UINT32 VirtualSize; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} __attribute__((packed)); + +EFI_STATUS pe_memory_locate_sections(CHAR8 *base, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) { + struct DosFileHeader *dos; + struct PeHeader *pe; + UINTN i; + UINTN offset; + + dos = (struct DosFileHeader *)base; + + if (CompareMem(dos->Magic, "MZ", 2) != 0) + return EFI_LOAD_ERROR; + + pe = (struct PeHeader *)&base[dos->ExeHeader]; + if (CompareMem(pe->Magic, "PE\0\0", 4) != 0) + return EFI_LOAD_ERROR; + + /* PE32+ Subsystem type */ + if (pe->FileHeader.Machine != PE_HEADER_MACHINE_X64 && + pe->FileHeader.Machine != PE_HEADER_MACHINE_ARM64 && + pe->FileHeader.Machine != PE_HEADER_MACHINE_I386) + return EFI_LOAD_ERROR; + + if (pe->FileHeader.NumberOfSections > 96) + return EFI_LOAD_ERROR; + + offset = dos->ExeHeader + sizeof(*pe) + pe->FileHeader.SizeOfOptionalHeader; + + for (i = 0; i < pe->FileHeader.NumberOfSections; i++) { + struct PeSectionHeader *sect; + UINTN j; + + sect = (struct PeSectionHeader *)&base[offset]; + for (j = 0; sections[j]; j++) { + if (CompareMem(sect->Name, sections[j], strlena(sections[j])) != 0) + continue; + + if (addrs) + addrs[j] = (UINTN)sect->VirtualAddress; + if (offsets) + offsets[j] = (UINTN)sect->PointerToRawData; + if (sizes) + sizes[j] = (UINTN)sect->VirtualSize; + } + offset += sizeof(*sect); + } + + return EFI_SUCCESS; +} + +EFI_STATUS pe_file_locate_sections(EFI_FILE *dir, CHAR16 *path, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) { + EFI_FILE_HANDLE handle; + struct DosFileHeader dos; + struct PeHeader pe; + UINTN len; + UINTN headerlen; + EFI_STATUS err; + _cleanup_freepool_ CHAR8 *header = NULL; + + err = uefi_call_wrapper(dir->Open, 5, dir, &handle, path, EFI_FILE_MODE_READ, 0ULL); + if (EFI_ERROR(err)) + return err; + + /* MS-DOS stub */ + len = sizeof(dos); + err = uefi_call_wrapper(handle->Read, 3, handle, &len, &dos); + if (EFI_ERROR(err)) + goto out; + if (len != sizeof(dos)) { + err = EFI_LOAD_ERROR; + goto out; + } + + err = uefi_call_wrapper(handle->SetPosition, 2, handle, dos.ExeHeader); + if (EFI_ERROR(err)) + goto out; + + len = sizeof(pe); + err = uefi_call_wrapper(handle->Read, 3, handle, &len, &pe); + if (EFI_ERROR(err)) + goto out; + if (len != sizeof(pe)) { + err = EFI_LOAD_ERROR; + goto out; + } + + headerlen = sizeof(dos) + sizeof(pe) + pe.FileHeader.SizeOfOptionalHeader + pe.FileHeader.NumberOfSections * sizeof(struct PeSectionHeader); + header = AllocatePool(headerlen); + if (!header) { + err = EFI_OUT_OF_RESOURCES; + goto out; + } + len = headerlen; + err = uefi_call_wrapper(handle->SetPosition, 2, handle, 0); + if (EFI_ERROR(err)) + goto out; + + err = uefi_call_wrapper(handle->Read, 3, handle, &len, header); + if (EFI_ERROR(err)) + goto out; + + if (len != headerlen) { + err = EFI_LOAD_ERROR; + goto out; + } + + err = pe_memory_locate_sections(header, sections, addrs, offsets, sizes); +out: + uefi_call_wrapper(handle->Close, 1, handle); + return err; +} diff --git a/src/boot/efi/pe.h b/src/boot/efi/pe.h new file mode 100644 index 00000000..bfbb8d9b --- /dev/null +++ b/src/boot/efi/pe.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +EFI_STATUS pe_memory_locate_sections(CHAR8 *base, + CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes); +EFI_STATUS pe_file_locate_sections(EFI_FILE *dir, CHAR16 *path, + CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes); diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c new file mode 100644 index 00000000..cc747993 --- /dev/null +++ b/src/boot/efi/random-seed.c @@ -0,0 +1,326 @@ +#include +#include + +#include "missing_efi.h" +#include "random-seed.h" +#include "sha256.h" +#include "util.h" +#include "shim.h" + +#define RANDOM_MAX_SIZE_MIN (32U) +#define RANDOM_MAX_SIZE_MAX (32U*1024U) + +static const EFI_GUID rng_protocol_guid = EFI_RNG_PROTOCOL_GUID; + +/* SHA256 gives us 256/8=32 bytes */ +#define HASH_VALUE_SIZE 32 + +static EFI_STATUS acquire_rng(UINTN size, VOID **ret) { + _cleanup_freepool_ VOID *data = NULL; + EFI_RNG_PROTOCOL *rng; + EFI_STATUS err; + + /* Try to acquire the specified number of bytes from the UEFI RNG */ + + err = LibLocateProtocol((EFI_GUID*) &rng_protocol_guid, (VOID**) &rng); + if (EFI_ERROR(err)) + return err; + if (!rng) + return EFI_UNSUPPORTED; + + data = AllocatePool(size); + if (!data) + return log_oom(); + + err = uefi_call_wrapper(rng->GetRNG, 3, rng, NULL, size, data); + if (EFI_ERROR(err)) { + Print(L"Failed to acquire RNG data: %r\n", err); + return err; + } + + *ret = TAKE_PTR(data); + return EFI_SUCCESS; +} + +static VOID hash_once( + const VOID *old_seed, + const VOID *rng, + UINTN size, + const VOID *system_token, + UINTN system_token_size, + UINTN counter, + UINT8 ret[static HASH_VALUE_SIZE]) { + + /* This hashes together: + * + * 1. The contents of the old seed file + * 2. Some random data acquired from the UEFI RNG (optional) + * 3. Some 'system token' the installer installed as EFI variable (optional) + * 4. A counter value + * + * And writes the result to the specified buffer. + */ + + struct sha256_ctx hash; + + sha256_init_ctx(&hash); + sha256_process_bytes(old_seed, size, &hash); + if (rng) + sha256_process_bytes(rng, size, &hash); + if (system_token_size > 0) + sha256_process_bytes(system_token, system_token_size, &hash); + sha256_process_bytes(&counter, sizeof(counter), &hash); + sha256_finish_ctx(&hash, ret); +} + +static EFI_STATUS hash_many( + const VOID *old_seed, + const VOID *rng, + UINTN size, + const VOID *system_token, + UINTN system_token_size, + UINTN counter_start, + UINTN n, + VOID **ret) { + + _cleanup_freepool_ VOID *output = NULL; + UINTN i; + + /* Hashes the specified parameters in counter mode, generating n hash values, with the counter in the + * range counter_start…counter_start+n-1. */ + + output = AllocatePool(n * HASH_VALUE_SIZE); + if (!output) + return log_oom(); + + for (i = 0; i < n; i++) + hash_once(old_seed, rng, size, + system_token, system_token_size, + counter_start + i, + (UINT8*) output + (i * HASH_VALUE_SIZE)); + + *ret = TAKE_PTR(output); + return EFI_SUCCESS; +} + +static EFI_STATUS mangle_random_seed( + const VOID *old_seed, + const VOID *rng, + UINTN size, + const VOID *system_token, + UINTN system_token_size, + VOID **ret_new_seed, + VOID **ret_for_kernel) { + + _cleanup_freepool_ VOID *new_seed = NULL, *for_kernel = NULL; + EFI_STATUS err; + UINTN n; + + /* This takes the old seed file contents, an (optional) random number acquired from the UEFI RNG, an + * (optional) system 'token' installed once by the OS installer in an EFI variable, and hashes them + * together in counter mode, generating a new seed (to replace the file on disk) and the seed for the + * kernel. To keep things simple, the new seed and kernel data have the same size as the old seed and + * RNG data. */ + + n = (size + HASH_VALUE_SIZE - 1) / HASH_VALUE_SIZE; + + /* Begin hashing in counter mode at counter 0 for the new seed for the disk */ + err = hash_many(old_seed, rng, size, system_token, system_token_size, 0, n, &new_seed); + if (EFI_ERROR(err)) + return err; + + /* Continue counting at 'n' for the seed for the kernel */ + err = hash_many(old_seed, rng, size, system_token, system_token_size, n, n, &for_kernel); + if (EFI_ERROR(err)) + return err; + + *ret_new_seed = TAKE_PTR(new_seed); + *ret_for_kernel = TAKE_PTR(for_kernel); + + return EFI_SUCCESS; +} + +EFI_STATUS acquire_system_token(VOID **ret, UINTN *ret_size) { + _cleanup_freepool_ CHAR8 *data = NULL; + EFI_STATUS err; + UINTN size; + + err = efivar_get_raw(&loader_guid, L"LoaderSystemToken", &data, &size); + if (EFI_ERROR(err)) { + if (err != EFI_NOT_FOUND) + Print(L"Failed to read LoaderSystemToken EFI variable: %r", err); + return err; + } + + if (size <= 0) { + Print(L"System token too short, ignoring."); + return EFI_NOT_FOUND; + } + + *ret = TAKE_PTR(data); + *ret_size = size; + + return EFI_SUCCESS; +} + +static VOID validate_sha256(void) { + +#ifndef __OPTIMIZE__ + /* Let's validate our SHA256 implementation. We stole it from glibc, and converted it to UEFI + * style. We better check whether it does the right stuff. We use the simpler test vectors from the + * SHA spec. Note that we strip this out in optimization builds. */ + + static const struct { + const char *string; + uint8_t hash[HASH_VALUE_SIZE]; + } array[] = { + { "abc", + { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }}, + + { "", + { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }}, + + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }}, + + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0xcf, 0x5b, 0x16, 0xa7, 0x78, 0xaf, 0x83, 0x80, + 0x03, 0x6c, 0xe5, 0x9e, 0x7b, 0x04, 0x92, 0x37, + 0x0b, 0x24, 0x9b, 0x11, 0xe8, 0xf0, 0x7a, 0x51, + 0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1 }}, + }; + + UINTN i; + + for (i = 0; i < ELEMENTSOF(array); i++) { + struct sha256_ctx hash; + uint8_t result[HASH_VALUE_SIZE]; + + sha256_init_ctx(&hash); + sha256_process_bytes(array[i].string, strlena((const CHAR8*) array[i].string), &hash); + sha256_finish_ctx(&hash, result); + + if (CompareMem(result, array[i].hash, HASH_VALUE_SIZE) != 0) { + Print(L"SHA256 failed validation.\n"); + uefi_call_wrapper(BS->Stall, 1, 120 * 1000 * 1000); + return; + } + } + + Print(L"SHA256 validated\n"); +#endif +} + +EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) { + _cleanup_freepool_ VOID *seed = NULL, *new_seed = NULL, *rng = NULL, *for_kernel = NULL, *system_token = NULL; + _cleanup_(FileHandleClosep) EFI_FILE_HANDLE handle = NULL; + UINTN size, rsize, wsize, system_token_size = 0; + _cleanup_freepool_ EFI_FILE_INFO *info = NULL; + EFI_STATUS err; + + validate_sha256(); + + if (mode == RANDOM_SEED_OFF) + return EFI_NOT_FOUND; + + /* Let's better be safe than sorry, and for now disable this logic in SecureBoot mode, so that we + * don't credit a random seed that is not authenticated. */ + if (secure_boot_enabled()) + return EFI_NOT_FOUND; + + /* Get some system specific seed that the installer might have placed in an EFI variable. We include + * it in our hash. This is protection against golden master image sloppiness, and it remains on the + * system, even when disk images are duplicated or swapped out. */ + err = acquire_system_token(&system_token, &system_token_size); + if (mode != RANDOM_SEED_ALWAYS && EFI_ERROR(err)) + return err; + + err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, L"\\loader\\random-seed", EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0ULL); + if (EFI_ERROR(err)) { + if (err != EFI_NOT_FOUND) + Print(L"Failed to open random seed file: %r\n", err); + return err; + } + + info = LibFileInfo(handle); + if (!info) + return log_oom(); + + size = info->FileSize; + if (size < RANDOM_MAX_SIZE_MIN) { + Print(L"Random seed file is too short?\n"); + return EFI_INVALID_PARAMETER; + } + + if (size > RANDOM_MAX_SIZE_MAX) { + Print(L"Random seed file is too large?\n"); + return EFI_INVALID_PARAMETER; + } + + seed = AllocatePool(size); + if (!seed) + return log_oom(); + + rsize = size; + err = uefi_call_wrapper(handle->Read, 3, handle, &rsize, seed); + if (EFI_ERROR(err)) { + Print(L"Failed to read random seed file: %r\n", err); + return err; + } + if (rsize != size) { + Print(L"Short read on random seed file\n"); + return EFI_PROTOCOL_ERROR; + } + + err = uefi_call_wrapper(handle->SetPosition, 2, handle, 0); + if (EFI_ERROR(err)) { + Print(L"Failed to seek to beginning of random seed file: %r\n", err); + return err; + } + + /* Request some random data from the UEFI RNG. We don't need this to work safely, but it's a good + * idea to use it because it helps us for cases where users mistakenly include a random seed in + * golden master images that are replicated many times. */ + (VOID) acquire_rng(size, &rng); /* It's fine if this fails */ + + /* Calculate new random seed for the disk and what to pass to the kernel */ + err = mangle_random_seed(seed, rng, size, system_token, system_token_size, &new_seed, &for_kernel); + if (EFI_ERROR(err)) + return err; + + /* Update the random seed on disk before we use it */ + wsize = size; + err = uefi_call_wrapper(handle->Write, 3, handle, &wsize, new_seed); + if (EFI_ERROR(err)) { + Print(L"Failed to write random seed file: %r\n", err); + return err; + } + if (wsize != size) { + Print(L"Short write on random seed file\n"); + return EFI_PROTOCOL_ERROR; + } + + err = uefi_call_wrapper(handle->Flush, 1, handle); + if (EFI_ERROR(err)) { + Print(L"Failed to flush random seed file: %r\n"); + return err; + } + + /* We are good to go */ + err = efivar_set_raw(&loader_guid, L"LoaderRandomSeed", for_kernel, size, FALSE); + if (EFI_ERROR(err)) { + Print(L"Failed to write random seed to EFI variable: %r\n", err); + return err; + } + + return EFI_SUCCESS; +} diff --git a/src/boot/efi/random-seed.h b/src/boot/efi/random-seed.h new file mode 100644 index 00000000..0f750716 --- /dev/null +++ b/src/boot/efi/random-seed.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +typedef enum RandomSeedMode { + RANDOM_SEED_OFF, + RANDOM_SEED_WITH_SYSTEM_TOKEN, + RANDOM_SEED_ALWAYS, + _RANDOM_SEED_MODE_MAX, + _RANDOM_SEED_MODE_INVALID = -1, +} RandomSeedMode; + +EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode); diff --git a/src/boot/efi/sha256.c b/src/boot/efi/sha256.c new file mode 100644 index 00000000..40da636d --- /dev/null +++ b/src/boot/efi/sha256.c @@ -0,0 +1,275 @@ +/* Stolen from glibc and converted to UEFI style. In glibc it comes with the following copyright blurb: */ + +/* Functions to compute SHA256 message digest of files or memory blocks. + according to the definition of SHA256 in FIPS 180-2. + Copyright (C) 2007-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* Written by Ulrich Drepper , 2007. */ + +#include "sha256.h" + +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +# define SWAP64(n) \ + (((n) << 56) \ + | (((n) & 0xff00) << 40) \ + | (((n) & 0xff0000) << 24) \ + | (((n) & 0xff000000) << 8) \ + | (((n) >> 8) & 0xff000000) \ + | (((n) >> 24) & 0xff0000) \ + | (((n) >> 40) & 0xff00) \ + | ((n) >> 56)) +#else +# define SWAP(n) (n) +# define SWAP64(n) (n) +#endif + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (FIPS 180-2:5.1.1) */ +static const UINT8 fillbuf[64] = { + 0x80, 0 /* , 0, 0, ... */ +}; + +/* Constants for SHA256 from FIPS 180-2:4.2.2. */ +static const UINT32 K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static void sha256_process_block(const void *, UINTN, struct sha256_ctx *); + +/* Initialize structure containing state of computation. + (FIPS 180-2:5.3.2) */ +void sha256_init_ctx(struct sha256_ctx *ctx) { + ctx->H[0] = 0x6a09e667; + ctx->H[1] = 0xbb67ae85; + ctx->H[2] = 0x3c6ef372; + ctx->H[3] = 0xa54ff53a; + ctx->H[4] = 0x510e527f; + ctx->H[5] = 0x9b05688c; + ctx->H[6] = 0x1f83d9ab; + ctx->H[7] = 0x5be0cd19; + + ctx->total64 = 0; + ctx->buflen = 0; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) { + /* Take yet unprocessed bytes into account. */ + UINT32 bytes = ctx->buflen; + UINTN pad, i; + + /* Now count remaining bytes. */ + ctx->total64 += bytes; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + CopyMem (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + ctx->buffer32[(bytes + pad + 4) / 4] = SWAP (ctx->total[TOTAL64_low] << 3); + ctx->buffer32[(bytes + pad) / 4] = SWAP ((ctx->total[TOTAL64_high] << 3) + | (ctx->total[TOTAL64_low] >> 29)); + + /* Process last bytes. */ + sha256_process_block (ctx->buffer, bytes + pad + 8, ctx); + + /* Put result from CTX in first 32 bytes following RESBUF. */ + for (i = 0; i < 8; ++i) + ((UINT32 *) resbuf)[i] = SWAP (ctx->H[i]); + + return resbuf; +} + +void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx) { + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + + if (ctx->buflen != 0) { + UINTN left_over = ctx->buflen; + UINTN add = 128 - left_over > len ? len : 128 - left_over; + + CopyMem (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) { + sha256_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + CopyMem (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) { +#if !_STRING_ARCH_unaligned +/* To check alignment gcc has an appropriate operator. Other + compilers don't. */ +# if __GNUC__ >= 2 +# define UNALIGNED_P(p) (((UINTN) p) % __alignof__ (UINT32) != 0) +# else +# define UNALIGNED_P(p) (((UINTN) p) % sizeof (UINT32) != 0) +# endif + if (UNALIGNED_P (buffer)) + while (len > 64) { + CopyMem (ctx->buffer, buffer, 64); + sha256_process_block (ctx->buffer, 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + sha256_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes into internal buffer. */ + if (len > 0) { + UINTN left_over = ctx->buflen; + + CopyMem (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) { + sha256_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + CopyMem (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ +static void sha256_process_block(const void *buffer, UINTN len, struct sha256_ctx *ctx) { + const UINT32 *words = buffer; + UINTN nwords = len / sizeof (UINT32); + UINT32 a = ctx->H[0]; + UINT32 b = ctx->H[1]; + UINT32 c = ctx->H[2]; + UINT32 d = ctx->H[3]; + UINT32 e = ctx->H[4]; + UINT32 f = ctx->H[5]; + UINT32 g = ctx->H[6]; + UINT32 h = ctx->H[7]; + + /* First increment the byte count. FIPS 180-2 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. */ + ctx->total64 += len; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (nwords > 0) { + UINT32 W[64]; + UINT32 a_save = a; + UINT32 b_save = b; + UINT32 c_save = c; + UINT32 d_save = d; + UINT32 e_save = e; + UINT32 f_save = f; + UINT32 g_save = g; + UINT32 h_save = h; + UINTN t; + + /* Operators defined in FIPS 180-2:4.1.2. */ +#define Ch(x, y, z) ((x & y) ^ (~x & z)) +#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) +#define S0(x) (CYCLIC (x, 2) ^ CYCLIC (x, 13) ^ CYCLIC (x, 22)) +#define S1(x) (CYCLIC (x, 6) ^ CYCLIC (x, 11) ^ CYCLIC (x, 25)) +#define R0(x) (CYCLIC (x, 7) ^ CYCLIC (x, 18) ^ (x >> 3)) +#define R1(x) (CYCLIC (x, 17) ^ CYCLIC (x, 19) ^ (x >> 10)) + + /* It is unfortunate that C does not provide an operator for + cyclic rotation. Hope the C compiler is smart enough. */ +#define CYCLIC(w, s) ((w >> s) | (w << (32 - s))) + + /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ + for (t = 0; t < 16; ++t) { + W[t] = SWAP (*words); + ++words; + } + for (t = 16; t < 64; ++t) + W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16]; + + /* The actual computation according to FIPS 180-2:6.2.2 step 3. */ + for (t = 0; t < 64; ++t) { + UINT32 T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t]; + UINT32 T2 = S0 (a) + Maj (a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + /* Add the starting values of the context according to FIPS 180-2:6.2.2 + step 4. */ + a += a_save; + b += b_save; + c += c_save; + d += d_save; + e += e_save; + f += f_save; + g += g_save; + h += h_save; + + /* Prepare for the next round. */ + nwords -= 16; + } + + /* Put checksum in context given as argument. */ + ctx->H[0] = a; + ctx->H[1] = b; + ctx->H[2] = c; + ctx->H[3] = d; + ctx->H[4] = e; + ctx->H[5] = f; + ctx->H[6] = g; + ctx->H[7] = h; +} diff --git a/src/boot/efi/sha256.h b/src/boot/efi/sha256.h new file mode 100644 index 00000000..ca9f2859 --- /dev/null +++ b/src/boot/efi/sha256.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +struct sha256_ctx { + UINT32 H[8]; + + union { + UINT64 total64; +#define TOTAL64_low (1 - (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) +#define TOTAL64_high (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + UINT32 total[2]; + }; + + UINT32 buflen; + + union { + UINT8 buffer[128]; /* NB: always correctly aligned for UINT32. */ + UINT32 buffer32[32]; + UINT64 buffer64[16]; + }; +}; + +void sha256_init_ctx(struct sha256_ctx *ctx); +void *sha256_finish_ctx(struct sha256_ctx *ctx, VOID *resbuf); +void sha256_process_bytes(const void *buffer, UINTN len, struct sha256_ctx *ctx); diff --git a/src/boot/efi/shim.c b/src/boot/efi/shim.c new file mode 100644 index 00000000..8db27547 --- /dev/null +++ b/src/boot/efi/shim.c @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/* + * Port to systemd-boot + * Copyright © 2017 Max Resch + * + * Security Policy Handling + * Copyright © 2012 + * https://github.com/mjg59/efitools + */ + +#include +#include + +#include "util.h" +#include "shim.h" + +#if defined(__x86_64__) || defined(__i386__) +#define __sysv_abi__ __attribute__((sysv_abi)) +#else +#define __sysv_abi__ +#endif + +struct ShimLock { + EFI_STATUS __sysv_abi__ (*shim_verify) (VOID *buffer, UINT32 size); + + /* context is actually a struct for the PE header, but it isn't needed so void is sufficient just do define the interface + * see shim.c/shim.h and PeHeader.h in the github shim repo */ + EFI_STATUS __sysv_abi__ (*generate_hash) (VOID *data, UINT32 datasize, VOID *context, UINT8 *sha256hash, UINT8 *sha1hash); + + EFI_STATUS __sysv_abi__ (*read_header) (VOID *data, UINT32 datasize, VOID *context); +}; + +static const EFI_GUID simple_fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL; +static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE; + +static const EFI_GUID security_protocol_guid = { 0xa46423e3, 0x4617, 0x49f1, {0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } }; +static const EFI_GUID security2_protocol_guid = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } }; +static const EFI_GUID shim_lock_guid = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; + +BOOLEAN shim_loaded(void) { + struct ShimLock *shim_lock; + + return uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &shim_lock_guid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS; +} + +static BOOLEAN shim_validate(VOID *data, UINT32 size) { + struct ShimLock *shim_lock; + + if (!data) + return FALSE; + + if (uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &shim_lock_guid, NULL, (VOID**) &shim_lock) != EFI_SUCCESS) + return FALSE; + + if (!shim_lock) + return FALSE; + + return shim_lock->shim_verify(data, size) == EFI_SUCCESS; +} + +BOOLEAN secure_boot_enabled(void) { + _cleanup_freepool_ CHAR8 *b = NULL; + UINTN size; + + if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) + return *b > 0; + + return FALSE; +} + +/* + * See the UEFI Platform Initialization manual (Vol2: DXE) for this + */ +struct _EFI_SECURITY2_PROTOCOL; +struct _EFI_SECURITY_PROTOCOL; +struct _EFI_DEVICE_PATH_PROTOCOL; + +typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL; +typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL; +typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL; + +typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) ( + const EFI_SECURITY_PROTOCOL *This, + UINT32 AuthenticationStatus, + const EFI_DEVICE_PATH_PROTOCOL *File +); + +typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) ( + const EFI_SECURITY2_PROTOCOL *This, + const EFI_DEVICE_PATH_PROTOCOL *DevicePath, + VOID *FileBuffer, + UINTN FileSize, + BOOLEAN BootPolicy +); + +struct _EFI_SECURITY2_PROTOCOL { + EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication; +}; + +struct _EFI_SECURITY_PROTOCOL { + EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState; +}; + +/* Handle to the original authenticator for security1 protocol */ +static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL; + +/* Handle to the original authenticator for security2 protocol */ +static EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL; + +/* + * Perform shim/MOK and Secure Boot authentication on a binary that's already been + * loaded into memory. This function does the platform SB authentication first + * but preserves its return value in case of its failure, so that it can be + * returned in case of a shim/MOK authentication failure. This is done because + * the SB failure code seems to vary from one implementation to another, and I + * don't want to interfere with that at this time. + */ +static EFIAPI EFI_STATUS security2_policy_authentication (const EFI_SECURITY2_PROTOCOL *this, + const EFI_DEVICE_PATH_PROTOCOL *device_path, + VOID *file_buffer, UINTN file_size, BOOLEAN boot_policy) { + EFI_STATUS status; + + /* Chain original security policy */ + status = uefi_call_wrapper(es2fa, 5, this, device_path, file_buffer, file_size, boot_policy); + + /* if OK, don't bother with MOK check */ + if (status == EFI_SUCCESS) + return status; + + if (shim_validate(file_buffer, file_size)) + return EFI_SUCCESS; + + return status; +} + +/* + * Perform both shim/MOK and platform Secure Boot authentication. This function loads + * the file and performs shim/MOK authentication first simply to avoid double loads + * of Linux kernels, which are much more likely to be shim/MOK-signed than platform-signed, + * since kernels are big and can take several seconds to load on some computers and + * filesystems. This also has the effect of returning whatever the platform code is for + * authentication failure, be it EFI_ACCESS_DENIED, EFI_SECURITY_VIOLATION, or something + * else. (This seems to vary between implementations.) + */ +static EFIAPI EFI_STATUS security_policy_authentication (const EFI_SECURITY_PROTOCOL *this, UINT32 authentication_status, + const EFI_DEVICE_PATH_PROTOCOL *device_path_const) { + EFI_STATUS status; + _cleanup_freepool_ EFI_DEVICE_PATH *dev_path = NULL; + _cleanup_freepool_ CHAR16 *dev_path_str = NULL; + EFI_HANDLE h; + EFI_FILE *root; + _cleanup_freepool_ CHAR8 *file_buffer = NULL; + UINTN file_size; + + if (!device_path_const) + return EFI_INVALID_PARAMETER; + + dev_path = DuplicateDevicePath((EFI_DEVICE_PATH*) device_path_const); + + status = uefi_call_wrapper(BS->LocateDevicePath, 3, (EFI_GUID*) &simple_fs_guid, &dev_path, &h); + if (status != EFI_SUCCESS) + return status; + + /* No need to check return value, this already happened in efi_main() */ + root = LibOpenRoot(h); + dev_path_str = DevicePathToStr(dev_path); + + status = file_read(root, dev_path_str, 0, 0, &file_buffer, &file_size); + if (EFI_ERROR(status)) + return status; + uefi_call_wrapper(root->Close, 1, root); + + if (shim_validate(file_buffer, file_size)) + return EFI_SUCCESS; + + /* Try using the platform's native policy.... */ + return uefi_call_wrapper(esfas, 3, this, authentication_status, device_path_const); +} + +EFI_STATUS security_policy_install(void) { + EFI_SECURITY_PROTOCOL *security_protocol; + EFI_SECURITY2_PROTOCOL *security2_protocol = NULL; + EFI_STATUS status; + + /* Already Installed */ + if (esfas) + return EFI_ALREADY_STARTED; + + /* + * Don't bother with status here. The call is allowed + * to fail, since SECURITY2 was introduced in PI 1.2.1. + * Use security2_protocol == NULL as indicator. + */ + uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security2_protocol_guid, NULL, (VOID**) &security2_protocol); + + status = uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security_protocol_guid, NULL, (VOID**) &security_protocol); + /* This one is mandatory, so there's a serious problem */ + if (status != EFI_SUCCESS) + return status; + + esfas = security_protocol->FileAuthenticationState; + security_protocol->FileAuthenticationState = security_policy_authentication; + + if (security2_protocol) { + es2fa = security2_protocol->FileAuthentication; + security2_protocol->FileAuthentication = security2_policy_authentication; + } + + return EFI_SUCCESS; +} diff --git a/src/boot/efi/shim.h b/src/boot/efi/shim.h new file mode 100644 index 00000000..209c9d4c --- /dev/null +++ b/src/boot/efi/shim.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/* + * Port to systemd-boot + * Copyright © 2017 Max Resch + * + * Security Policy Handling + * Copyright © 2012 + * https://github.com/mjg59/efitools + */ +#pragma once + +BOOLEAN shim_loaded(void); + +BOOLEAN secure_boot_enabled(void); + +EFI_STATUS security_policy_install(void); diff --git a/src/boot/efi/splash.c b/src/boot/efi/splash.c new file mode 100644 index 00000000..ba4a2c5d --- /dev/null +++ b/src/boot/efi/splash.c @@ -0,0 +1,305 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "graphics.h" +#include "splash.h" +#include "util.h" + +struct bmp_file { + CHAR8 signature[2]; + UINT32 size; + UINT16 reserved[2]; + UINT32 offset; +} __attribute__((packed)); + +/* we require at least BITMAPINFOHEADER, later versions are + accepted, but their features ignored */ +struct bmp_dib { + UINT32 size; + UINT32 x; + UINT32 y; + UINT16 planes; + UINT16 depth; + UINT32 compression; + UINT32 image_size; + INT32 x_pixel_meter; + INT32 y_pixel_meter; + UINT32 colors_used; + UINT32 colors_important; +} __attribute__((packed)); + +struct bmp_map { + UINT8 blue; + UINT8 green; + UINT8 red; + UINT8 reserved; +} __attribute__((packed)); + +EFI_STATUS bmp_parse_header(UINT8 *bmp, UINTN size, struct bmp_dib **ret_dib, + struct bmp_map **ret_map, UINT8 **pixmap) { + struct bmp_file *file; + struct bmp_dib *dib; + struct bmp_map *map; + UINTN row_size; + + if (size < sizeof(struct bmp_file) + sizeof(struct bmp_dib)) + return EFI_INVALID_PARAMETER; + + /* check file header */ + file = (struct bmp_file *)bmp; + if (file->signature[0] != 'B' || file->signature[1] != 'M') + return EFI_INVALID_PARAMETER; + if (file->size != size) + return EFI_INVALID_PARAMETER; + if (file->size < file->offset) + return EFI_INVALID_PARAMETER; + + /* check device-independent bitmap */ + dib = (struct bmp_dib *)(bmp + sizeof(struct bmp_file)); + if (dib->size < sizeof(struct bmp_dib)) + return EFI_UNSUPPORTED; + + switch (dib->depth) { + case 1: + case 4: + case 8: + case 24: + if (dib->compression != 0) + return EFI_UNSUPPORTED; + + break; + + case 16: + case 32: + if (dib->compression != 0 && dib->compression != 3) + return EFI_UNSUPPORTED; + + break; + + default: + return EFI_UNSUPPORTED; + } + + row_size = ((UINTN) dib->depth * dib->x + 31) / 32 * 4; + if (file->size - file->offset < dib->y * row_size) + return EFI_INVALID_PARAMETER; + if (row_size * dib->y > 64 * 1024 * 1024) + return EFI_INVALID_PARAMETER; + + /* check color table */ + map = (struct bmp_map *)(bmp + sizeof(struct bmp_file) + dib->size); + if (file->offset < sizeof(struct bmp_file) + dib->size) + return EFI_INVALID_PARAMETER; + + if (file->offset > sizeof(struct bmp_file) + dib->size) { + UINT32 map_count; + UINTN map_size; + + if (dib->colors_used) + map_count = dib->colors_used; + else { + switch (dib->depth) { + case 1: + case 4: + case 8: + map_count = 1 << dib->depth; + break; + + default: + map_count = 0; + break; + } + } + + map_size = file->offset - (sizeof(struct bmp_file) + dib->size); + if (map_size != sizeof(struct bmp_map) * map_count) + return EFI_INVALID_PARAMETER; + } + + *ret_map = map; + *ret_dib = dib; + *pixmap = bmp + file->offset; + + return EFI_SUCCESS; +} + +static VOID pixel_blend(UINT32 *dst, const UINT32 source) { + UINT32 alpha, src, src_rb, src_g, dst_rb, dst_g, rb, g; + + alpha = (source & 0xff); + + /* convert src from RGBA to XRGB */ + src = source >> 8; + + /* decompose into RB and G components */ + src_rb = (src & 0xff00ff); + src_g = (src & 0x00ff00); + + dst_rb = (*dst & 0xff00ff); + dst_g = (*dst & 0x00ff00); + + /* blend */ + rb = ((((src_rb - dst_rb) * alpha + 0x800080) >> 8) + dst_rb) & 0xff00ff; + g = ((((src_g - dst_g) * alpha + 0x008000) >> 8) + dst_g) & 0x00ff00; + + *dst = (rb | g); +} + +EFI_STATUS bmp_to_blt(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf, + struct bmp_dib *dib, struct bmp_map *map, + UINT8 *pixmap) { + UINT8 *in; + UINTN y; + + /* transform and copy pixels */ + in = pixmap; + for (y = 0; y < dib->y; y++) { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *out; + UINTN row_size; + UINTN x; + + out = &buf[(dib->y - y - 1) * dib->x]; + for (x = 0; x < dib->x; x++, in++, out++) { + switch (dib->depth) { + case 1: { + UINTN i; + + for (i = 0; i < 8 && x < dib->x; i++) { + out->Red = map[((*in) >> (7 - i)) & 1].red; + out->Green = map[((*in) >> (7 - i)) & 1].green; + out->Blue = map[((*in) >> (7 - i)) & 1].blue; + out++; + x++; + } + out--; + x--; + break; + } + + case 4: { + UINTN i; + + i = (*in) >> 4; + out->Red = map[i].red; + out->Green = map[i].green; + out->Blue = map[i].blue; + if (x < (dib->x - 1)) { + out++; + x++; + i = (*in) & 0x0f; + out->Red = map[i].red; + out->Green = map[i].green; + out->Blue = map[i].blue; + } + break; + } + + case 8: + out->Red = map[*in].red; + out->Green = map[*in].green; + out->Blue = map[*in].blue; + break; + + case 16: { + UINT16 i = *(UINT16 *) in; + + out->Red = (i & 0x7c00) >> 7; + out->Green = (i & 0x3e0) >> 2; + out->Blue = (i & 0x1f) << 3; + in += 1; + break; + } + + case 24: + out->Red = in[2]; + out->Green = in[1]; + out->Blue = in[0]; + in += 2; + break; + + case 32: { + UINT32 i = *(UINT32 *) in; + + pixel_blend((UINT32 *)out, i); + + in += 3; + break; + } + } + } + + /* add row padding; new lines always start at 32 bit boundary */ + row_size = in - pixmap; + in += ((row_size + 3) & ~3) - row_size; + } + + return EFI_SUCCESS; +} + +EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background) { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL pixel = {}; + EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = NULL; + struct bmp_dib *dib; + struct bmp_map *map; + UINT8 *pixmap; + UINT64 blt_size; + _cleanup_freepool_ VOID *blt = NULL; + UINTN x_pos = 0; + UINTN y_pos = 0; + EFI_STATUS err; + + if (!background) { + if (StriCmp(L"Apple", ST->FirmwareVendor) == 0) { + pixel.Red = 0xc0; + pixel.Green = 0xc0; + pixel.Blue = 0xc0; + } + background = &pixel; + } + + err = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput); + if (EFI_ERROR(err)) + return err; + + err = bmp_parse_header(content, len, &dib, &map, &pixmap); + if (EFI_ERROR(err)) + return err; + + if (dib->x < GraphicsOutput->Mode->Info->HorizontalResolution) + x_pos = (GraphicsOutput->Mode->Info->HorizontalResolution - dib->x) / 2; + if (dib->y < GraphicsOutput->Mode->Info->VerticalResolution) + y_pos = (GraphicsOutput->Mode->Info->VerticalResolution - dib->y) / 2; + + uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)background, + EfiBltVideoFill, 0, 0, 0, 0, + GraphicsOutput->Mode->Info->HorizontalResolution, + GraphicsOutput->Mode->Info->VerticalResolution, 0); + + /* EFI buffer */ + blt_size = sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * dib->x * dib->y; + blt = AllocatePool(blt_size); + if (!blt) + return EFI_OUT_OF_RESOURCES; + + err = uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput, + blt, EfiBltVideoToBltBuffer, x_pos, y_pos, 0, 0, + dib->x, dib->y, 0); + if (EFI_ERROR(err)) + return err; + + err = bmp_to_blt(blt, dib, map, pixmap); + if (EFI_ERROR(err)) + return err; + + err = graphics_mode(TRUE); + if (EFI_ERROR(err)) + return err; + + return uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput, + blt, EfiBltBufferToVideo, 0, 0, x_pos, y_pos, + dib->x, dib->y, 0); +} diff --git a/src/boot/efi/splash.h b/src/boot/efi/splash.h new file mode 100644 index 00000000..8928b069 --- /dev/null +++ b/src/boot/efi/splash.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_BLT_PIXEL *background); diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c new file mode 100644 index 00000000..6a10caff --- /dev/null +++ b/src/boot/efi/stub.c @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "disk.h" +#include "graphics.h" +#include "linux.h" +#include "measure.h" +#include "pe.h" +#include "splash.h" +#include "util.h" + +/* magic string to find in the binary image */ +static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####"; + +static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE; + +EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { + EFI_LOADED_IMAGE *loaded_image; + _cleanup_freepool_ CHAR8 *b = NULL; + UINTN size; + BOOLEAN secure = FALSE; + CHAR8 *sections[] = { + (UINT8 *)".cmdline", + (UINT8 *)".linux", + (UINT8 *)".initrd", + (UINT8 *)".splash", + NULL + }; + UINTN addrs[ELEMENTSOF(sections)-1] = {}; + UINTN offs[ELEMENTSOF(sections)-1] = {}; + UINTN szs[ELEMENTSOF(sections)-1] = {}; + CHAR8 *cmdline = NULL; + UINTN cmdline_len; + CHAR16 uuid[37]; + EFI_STATUS err; + + InitializeLib(image, sys_table); + + err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, + image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(err)) { + Print(L"Error getting a LoadedImageProtocol handle: %r ", err); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return err; + } + + if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) + if (*b > 0) + secure = TRUE; + + err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs); + if (EFI_ERROR(err)) { + Print(L"Unable to locate embedded .linux section: %r ", err); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return err; + } + + if (szs[0] > 0) + cmdline = (CHAR8 *)(loaded_image->ImageBase + addrs[0]); + + cmdline_len = szs[0]; + + /* if we are not in secure boot mode, or none was provided, accept a custom command line and replace the built-in one */ + if ((!secure || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions > 0x1F) { + CHAR16 *options; + CHAR8 *line; + UINTN i; + + options = (CHAR16 *)loaded_image->LoadOptions; + cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8); + line = AllocatePool(cmdline_len); + for (i = 0; i < cmdline_len; i++) + line[i] = options[i]; + cmdline = line; + +#if ENABLE_TPM + /* Try to log any options to the TPM, especially manually edited options */ + err = tpm_log_event(SD_TPM_PCR, + (EFI_PHYSICAL_ADDRESS) (UINTN) loaded_image->LoadOptions, + loaded_image->LoadOptionsSize, loaded_image->LoadOptions); + if (EFI_ERROR(err)) { + Print(L"Unable to add image options measurement: %r", err); + uefi_call_wrapper(BS->Stall, 1, 200 * 1000); + } +#endif + } + + /* Export the device path this image is started from, if it's not set yet */ + if (efivar_get_raw(&loader_guid, L"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS) + if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) + efivar_set(L"LoaderDevicePartUUID", uuid, FALSE); + + /* if LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from UEFI */ + if (efivar_get_raw(&loader_guid, L"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS) { + _cleanup_freepool_ CHAR16 *s; + + s = DevicePathToStr(loaded_image->FilePath); + efivar_set(L"LoaderImageIdentifier", s, FALSE); + } + + /* if LoaderFirmwareInfo is not set, let's set it */ + if (efivar_get_raw(&loader_guid, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) { + _cleanup_freepool_ CHAR16 *s; + + s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + efivar_set(L"LoaderFirmwareInfo", s, FALSE); + } + + /* ditto for LoaderFirmwareType */ + if (efivar_get_raw(&loader_guid, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) { + _cleanup_freepool_ CHAR16 *s; + + s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); + efivar_set(L"LoaderFirmwareType", s, FALSE); + } + + /* add StubInfo */ + if (efivar_get_raw(&loader_guid, L"StubInfo", NULL, NULL) != EFI_SUCCESS) + efivar_set(L"StubInfo", L"systemd-stub " GIT_VERSION, FALSE); + + if (szs[3] > 0) + graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL); + + err = linux_exec(image, cmdline, cmdline_len, + (UINTN)loaded_image->ImageBase + addrs[1], + (UINTN)loaded_image->ImageBase + addrs[2], szs[2]); + + graphics_mode(FALSE); + Print(L"Execution of embedded linux image failed: %r\n", err); + uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return err; +} diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c new file mode 100644 index 00000000..da743dcb --- /dev/null +++ b/src/boot/efi/util.c @@ -0,0 +1,358 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "util.h" + +/* + * Allocated random UUID, intended to be shared across tools that implement + * the (ESP)\loader\entries\-.conf convention and the + * associated EFI variables. + */ +const EFI_GUID loader_guid = { 0x4a67b082, 0x0a4c, 0x41cf, {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f} }; + +#ifdef __x86_64__ +UINT64 ticks_read(VOID) { + UINT64 a, d; + __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d)); + return (d << 32) | a; +} +#elif defined(__i386__) +UINT64 ticks_read(VOID) { + UINT64 val; + __asm__ volatile ("rdtsc" : "=A" (val)); + return val; +} +#else +UINT64 ticks_read(VOID) { + UINT64 val = 1; + return val; +} +#endif + +/* count TSC ticks during a millisecond delay */ +UINT64 ticks_freq(VOID) { + UINT64 ticks_start, ticks_end; + + ticks_start = ticks_read(); + uefi_call_wrapper(BS->Stall, 1, 1000); + ticks_end = ticks_read(); + + return (ticks_end - ticks_start) * 1000UL; +} + +UINT64 time_usec(VOID) { + UINT64 ticks; + static UINT64 freq; + + ticks = ticks_read(); + if (ticks == 0) + return 0; + + if (freq == 0) { + freq = ticks_freq(); + if (freq == 0) + return 0; + } + + return 1000UL * 1000UL * ticks / freq; +} + +EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b) { + if (!v) + return EFI_INVALID_PARAMETER; + + if (strcmpa(v, (CHAR8 *)"1") == 0 || + strcmpa(v, (CHAR8 *)"yes") == 0 || + strcmpa(v, (CHAR8 *)"y") == 0 || + strcmpa(v, (CHAR8 *)"true") == 0) { + *b = TRUE; + return EFI_SUCCESS; + } + + if (strcmpa(v, (CHAR8 *)"0") == 0 || + strcmpa(v, (CHAR8 *)"no") == 0 || + strcmpa(v, (CHAR8 *)"n") == 0 || + strcmpa(v, (CHAR8 *)"false") == 0) { + *b = FALSE; + return EFI_SUCCESS; + } + + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, BOOLEAN persistent) { + UINT32 flags; + + flags = EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS; + if (persistent) + flags |= EFI_VARIABLE_NON_VOLATILE; + + return uefi_call_wrapper(RT->SetVariable, 5, (CHAR16*) name, (EFI_GUID *)vendor, flags, size, (VOID*) buf); +} + +EFI_STATUS efivar_set(const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent) { + return efivar_set_raw(&loader_guid, name, value, value ? (StrLen(value)+1) * sizeof(CHAR16) : 0, persistent); +} + +EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent) { + CHAR16 str[32]; + + SPrint(str, 32, L"%u", i); + return efivar_set(name, str, persistent); +} + +EFI_STATUS efivar_get(const CHAR16 *name, CHAR16 **value) { + _cleanup_freepool_ CHAR8 *buf = NULL; + EFI_STATUS err; + CHAR16 *val; + UINTN size; + + err = efivar_get_raw(&loader_guid, name, &buf, &size); + if (EFI_ERROR(err)) + return err; + + /* Make sure there are no incomplete characters in the buffer */ + if ((size % 2) != 0) + return EFI_INVALID_PARAMETER; + + if (!value) + return EFI_SUCCESS; + + /* Return buffer directly if it happens to be NUL terminated already */ + if (size >= 2 && buf[size-2] == 0 && buf[size-1] == 0) { + *value = (CHAR16*) TAKE_PTR(buf); + return EFI_SUCCESS; + } + + /* Make sure a terminating NUL is available at the end */ + val = AllocatePool(size + 2); + if (!val) + return EFI_OUT_OF_RESOURCES; + + CopyMem(val, buf, size); + val[size/2] = 0; /* NUL terminate */ + + *value = val; + return EFI_SUCCESS; +} + +EFI_STATUS efivar_get_int(const CHAR16 *name, UINTN *i) { + _cleanup_freepool_ CHAR16 *val = NULL; + EFI_STATUS err; + + err = efivar_get(name, &val); + if (!EFI_ERROR(err) && i) + *i = Atoi(val); + + return err; +} + +EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size) { + _cleanup_freepool_ CHAR8 *buf = NULL; + UINTN l; + EFI_STATUS err; + + l = sizeof(CHAR16 *) * EFI_MAXIMUM_VARIABLE_SIZE; + buf = AllocatePool(l); + if (!buf) + return EFI_OUT_OF_RESOURCES; + + err = uefi_call_wrapper(RT->GetVariable, 5, (CHAR16*) name, (EFI_GUID *)vendor, NULL, &l, buf); + if (!EFI_ERROR(err)) { + + if (buffer) + *buffer = TAKE_PTR(buf); + + if (size) + *size = l; + } + + return err; +} + +VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) { + CHAR16 str[32]; + + if (usec == 0) + usec = time_usec(); + if (usec == 0) + return; + + SPrint(str, 32, L"%ld", usec); + efivar_set(name, str, FALSE); +} + +static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) { + CHAR16 unichar; + UINTN len; + UINTN i; + + if (stra[0] < 0x80) + len = 1; + else if ((stra[0] & 0xe0) == 0xc0) + len = 2; + else if ((stra[0] & 0xf0) == 0xe0) + len = 3; + else if ((stra[0] & 0xf8) == 0xf0) + len = 4; + else if ((stra[0] & 0xfc) == 0xf8) + len = 5; + else if ((stra[0] & 0xfe) == 0xfc) + len = 6; + else + return -1; + + switch (len) { + case 1: + unichar = stra[0]; + break; + case 2: + unichar = stra[0] & 0x1f; + break; + case 3: + unichar = stra[0] & 0x0f; + break; + case 4: + unichar = stra[0] & 0x07; + break; + case 5: + unichar = stra[0] & 0x03; + break; + case 6: + unichar = stra[0] & 0x01; + break; + } + + for (i = 1; i < len; i++) { + if ((stra[i] & 0xc0) != 0x80) + return -1; + unichar <<= 6; + unichar |= stra[i] & 0x3f; + } + + *c = unichar; + return len; +} + +CHAR16 *stra_to_str(CHAR8 *stra) { + UINTN strlen; + UINTN len; + UINTN i; + CHAR16 *str; + + len = strlena(stra); + str = AllocatePool((len + 1) * sizeof(CHAR16)); + + strlen = 0; + i = 0; + while (i < len) { + INTN utf8len; + + utf8len = utf8_to_16(stra + i, str + strlen); + if (utf8len <= 0) { + /* invalid utf8 sequence, skip the garbage */ + i++; + continue; + } + + strlen++; + i += utf8len; + } + str[strlen] = '\0'; + return str; +} + +CHAR16 *stra_to_path(CHAR8 *stra) { + CHAR16 *str; + UINTN strlen; + UINTN len; + UINTN i; + + len = strlena(stra); + str = AllocatePool((len + 2) * sizeof(CHAR16)); + + str[0] = '\\'; + strlen = 1; + i = 0; + while (i < len) { + INTN utf8len; + + utf8len = utf8_to_16(stra + i, str + strlen); + if (utf8len <= 0) { + /* invalid utf8 sequence, skip the garbage */ + i++; + continue; + } + + if (str[strlen] == '/') + str[strlen] = '\\'; + if (str[strlen] == '\\' && str[strlen-1] == '\\') { + /* skip double slashes */ + i += utf8len; + continue; + } + + strlen++; + i += utf8len; + } + str[strlen] = '\0'; + return str; +} + +CHAR8 *strchra(CHAR8 *s, CHAR8 c) { + do { + if (*s == c) + return s; + } while (*s++); + return NULL; +} + +EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **ret, UINTN *ret_size) { + _cleanup_(FileHandleClosep) EFI_FILE_HANDLE handle = NULL; + _cleanup_freepool_ CHAR8 *buf = NULL; + EFI_STATUS err; + + err = uefi_call_wrapper(dir->Open, 5, dir, &handle, (CHAR16*) name, EFI_FILE_MODE_READ, 0ULL); + if (EFI_ERROR(err)) + return err; + + if (size == 0) { + _cleanup_freepool_ EFI_FILE_INFO *info; + + info = LibFileInfo(handle); + if (!info) + return EFI_OUT_OF_RESOURCES; + + size = info->FileSize+1; + } + + if (off > 0) { + err = uefi_call_wrapper(handle->SetPosition, 2, handle, off); + if (EFI_ERROR(err)) + return err; + } + + buf = AllocatePool(size + 1); + if (!buf) + return EFI_OUT_OF_RESOURCES; + + err = uefi_call_wrapper(handle->Read, 3, handle, &size, buf); + if (EFI_ERROR(err)) + return err; + + buf[size] = '\0'; + + *ret = TAKE_PTR(buf); + if (ret_size) + *ret_size = size; + + return err; +} + +EFI_STATUS log_oom(void) { + Print(L"Out of memory."); + (void) uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000); + return EFI_OUT_OF_RESOURCES; +} diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h new file mode 100644 index 00000000..b13f2247 --- /dev/null +++ b/src/boot/efi/util.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0])) +#define OFFSETOF(x,y) __builtin_offsetof(x,y) + +static inline UINTN ALIGN_TO(UINTN l, UINTN ali) { + return ((l + ali - 1) & ~(ali - 1)); +} + +static inline const CHAR16 *yes_no(BOOLEAN b) { + return b ? L"yes" : L"no"; +} + +EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b); + +UINT64 ticks_read(void); +UINT64 ticks_freq(void); +UINT64 time_usec(void); + +EFI_STATUS efivar_set(const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent); +EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, BOOLEAN persistent); +EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent); +VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec); + +EFI_STATUS efivar_get(const CHAR16 *name, CHAR16 **value); +EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size); +EFI_STATUS efivar_get_int(const CHAR16 *name, UINTN *i); + +CHAR8 *strchra(CHAR8 *s, CHAR8 c); +CHAR16 *stra_to_path(CHAR8 *stra); +CHAR16 *stra_to_str(CHAR8 *stra); + +EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **content, UINTN *content_size); + +static inline void FreePoolp(void *p) { + void *q = *(void**) p; + + if (!q) + return; + + FreePool(q); +} + +#define _cleanup_(x) __attribute__((__cleanup__(x))) +#define _cleanup_freepool_ _cleanup_(FreePoolp) + +static inline void FileHandleClosep(EFI_FILE_HANDLE *handle) { + if (!*handle) + return; + + uefi_call_wrapper((*handle)->Close, 1, *handle); +} + +extern const EFI_GUID loader_guid; + +#define UINTN_MAX (~(UINTN)0) +#define INTN_MAX ((INTN)(UINTN_MAX>>1)) + +#define TAKE_PTR(ptr) \ + ({ \ + typeof(ptr) _ptr_ = (ptr); \ + (ptr) = NULL; \ + _ptr_; \ + }) + +EFI_STATUS log_oom(void); diff --git a/src/busctl/busctl-introspect.c b/src/busctl/busctl-introspect.c new file mode 100644 index 00000000..7016c90d --- /dev/null +++ b/src/busctl/busctl-introspect.c @@ -0,0 +1,730 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "busctl-introspect.h" +#include "path-util.h" +#include "string-util.h" +#include "util.h" +#include "xml.h" + +#define NODE_DEPTH_MAX 16 + +typedef struct Context { + const XMLIntrospectOps *ops; + void *userdata; + + char *interface_name; + uint64_t interface_flags; + + char *member_name; + char *member_signature; + char *member_result; + uint64_t member_flags; + bool member_writable; + + const char *current; + void *xml_state; +} Context; + +static void context_reset_member(Context *c) { + free(c->member_name); + free(c->member_signature); + free(c->member_result); + + c->member_name = c->member_signature = c->member_result = NULL; + c->member_flags = 0; + c->member_writable = false; +} + +static void context_reset_interface(Context *c) { + c->interface_name = mfree(c->interface_name); + c->interface_flags = 0; + + context_reset_member(c); +} + +static int parse_xml_annotation(Context *context, uint64_t *flags) { + + enum { + STATE_ANNOTATION, + STATE_NAME, + STATE_VALUE + } state = STATE_ANNOTATION; + + _cleanup_free_ char *field = NULL, *value = NULL; + + assert(context); + + for (;;) { + _cleanup_free_ char *name = NULL; + + int t; + + t = xml_tokenize(&context->current, &name, &context->xml_state, NULL); + if (t < 0) { + log_error("XML parse error."); + return t; + } + + if (t == XML_END) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Premature end of XML data."); + + switch (state) { + + case STATE_ANNOTATION: + + if (t == XML_ATTRIBUTE_NAME) { + + if (streq_ptr(name, "name")) + state = STATE_NAME; + + else if (streq_ptr(name, "value")) + state = STATE_VALUE; + + else + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Unexpected attribute %s.", + name); + + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq_ptr(name, "annotation"))) { + + if (flags) { + if (streq_ptr(field, "org.freedesktop.DBus.Deprecated")) { + + if (streq_ptr(value, "true")) + *flags |= SD_BUS_VTABLE_DEPRECATED; + + } else if (streq_ptr(field, "org.freedesktop.DBus.Method.NoReply")) { + + if (streq_ptr(value, "true")) + *flags |= SD_BUS_VTABLE_METHOD_NO_REPLY; + + } else if (streq_ptr(field, "org.freedesktop.DBus.Property.EmitsChangedSignal")) { + + if (streq_ptr(value, "const")) + *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) | SD_BUS_VTABLE_PROPERTY_CONST; + else if (streq_ptr(value, "invalidates")) + *flags = (*flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST)) | SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION; + else if (streq_ptr(value, "false")) + *flags = *flags & ~(SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION); + } + } + + return 0; + + } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (1)"); + + break; + + case STATE_NAME: + + if (t == XML_ATTRIBUTE_VALUE) { + free_and_replace(field, name); + + state = STATE_ANNOTATION; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (2)"); + + break; + + case STATE_VALUE: + + if (t == XML_ATTRIBUTE_VALUE) { + free_and_replace(value, name); + + state = STATE_ANNOTATION; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (3)"); + + break; + + default: + assert_not_reached("Bad state"); + } + } +} + +static int parse_xml_node(Context *context, const char *prefix, unsigned n_depth) { + + enum { + STATE_NODE, + STATE_NODE_NAME, + STATE_INTERFACE, + STATE_INTERFACE_NAME, + STATE_METHOD, + STATE_METHOD_NAME, + STATE_METHOD_ARG, + STATE_METHOD_ARG_NAME, + STATE_METHOD_ARG_TYPE, + STATE_METHOD_ARG_DIRECTION, + STATE_SIGNAL, + STATE_SIGNAL_NAME, + STATE_SIGNAL_ARG, + STATE_SIGNAL_ARG_NAME, + STATE_SIGNAL_ARG_TYPE, + STATE_SIGNAL_ARG_DIRECTION, + STATE_PROPERTY, + STATE_PROPERTY_NAME, + STATE_PROPERTY_TYPE, + STATE_PROPERTY_ACCESS, + } state = STATE_NODE; + + _cleanup_free_ char *node_path = NULL, *argument_type = NULL, *argument_direction = NULL; + const char *np = prefix; + int r; + + assert(context); + assert(prefix); + + if (n_depth > NODE_DEPTH_MAX) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), " depth too high."); + + for (;;) { + _cleanup_free_ char *name = NULL; + int t; + + t = xml_tokenize(&context->current, &name, &context->xml_state, NULL); + if (t < 0) { + log_error("XML parse error."); + return t; + } + + if (t == XML_END) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Premature end of XML data."); + + switch (state) { + + case STATE_NODE: + if (t == XML_ATTRIBUTE_NAME) { + + if (streq_ptr(name, "name")) + state = STATE_NODE_NAME; + else + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Unexpected attribute %s.", name); + + } else if (t == XML_TAG_OPEN) { + + if (streq_ptr(name, "interface")) + state = STATE_INTERFACE; + else if (streq_ptr(name, "node")) { + + r = parse_xml_node(context, np, n_depth+1); + if (r < 0) + return r; + } else + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Unexpected tag %s.", name); + + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq_ptr(name, "node"))) { + + if (context->ops->on_path) { + r = context->ops->on_path(node_path ? node_path : np, context->userdata); + if (r < 0) + return r; + } + + return 0; + + } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (1)"); + + break; + + case STATE_NODE_NAME: + + if (t == XML_ATTRIBUTE_VALUE) { + + free(node_path); + + if (name[0] == '/') + node_path = TAKE_PTR(name); + else { + + node_path = path_join(prefix, name); + if (!node_path) + return log_oom(); + } + + np = node_path; + state = STATE_NODE; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (2)"); + + break; + + case STATE_INTERFACE: + + if (t == XML_ATTRIBUTE_NAME) { + if (streq_ptr(name, "name")) + state = STATE_INTERFACE_NAME; + else + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Unexpected attribute %s.", + name); + + } else if (t == XML_TAG_OPEN) { + if (streq_ptr(name, "method")) + state = STATE_METHOD; + else if (streq_ptr(name, "signal")) + state = STATE_SIGNAL; + else if (streq_ptr(name, "property")) { + context->member_flags |= SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE; + state = STATE_PROPERTY; + } else if (streq_ptr(name, "annotation")) { + r = parse_xml_annotation(context, &context->interface_flags); + if (r < 0) + return r; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected tag %s.", name); + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq_ptr(name, "interface"))) { + + if (n_depth == 0) { + if (context->ops->on_interface) { + r = context->ops->on_interface(context->interface_name, context->interface_flags, context->userdata); + if (r < 0) + return r; + } + + context_reset_interface(context); + } + + state = STATE_NODE; + + } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (1)"); + + break; + + case STATE_INTERFACE_NAME: + + if (t == XML_ATTRIBUTE_VALUE) { + if (n_depth == 0) + free_and_replace(context->interface_name, name); + + state = STATE_INTERFACE; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (2)"); + + break; + + case STATE_METHOD: + + if (t == XML_ATTRIBUTE_NAME) { + if (streq_ptr(name, "name")) + state = STATE_METHOD_NAME; + else + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Unexpected attribute %s", + name); + } else if (t == XML_TAG_OPEN) { + if (streq_ptr(name, "arg")) + state = STATE_METHOD_ARG; + else if (streq_ptr(name, "annotation")) { + r = parse_xml_annotation(context, &context->member_flags); + if (r < 0) + return r; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected tag %s.", + name); + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq_ptr(name, "method"))) { + + if (n_depth == 0) { + if (context->ops->on_method) { + r = context->ops->on_method(context->interface_name, context->member_name, context->member_signature, context->member_result, context->member_flags, context->userdata); + if (r < 0) + return r; + } + + context_reset_member(context); + } + + state = STATE_INTERFACE; + + } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in (1)."); + + break; + + case STATE_METHOD_NAME: + + if (t == XML_ATTRIBUTE_VALUE) { + if (n_depth == 0) + free_and_replace(context->member_name, name); + + state = STATE_METHOD; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in (2)."); + + break; + + case STATE_METHOD_ARG: + + if (t == XML_ATTRIBUTE_NAME) { + if (streq_ptr(name, "name")) + state = STATE_METHOD_ARG_NAME; + else if (streq_ptr(name, "type")) + state = STATE_METHOD_ARG_TYPE; + else if (streq_ptr(name, "direction")) + state = STATE_METHOD_ARG_DIRECTION; + else + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Unexpected method attribute %s.", + name); + } else if (t == XML_TAG_OPEN) { + if (streq_ptr(name, "annotation")) { + r = parse_xml_annotation(context, NULL); + if (r < 0) + return r; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected method tag %s.", + name); + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) { + + if (n_depth == 0) { + + if (argument_type) { + if (!argument_direction || streq(argument_direction, "in")) { + if (!strextend(&context->member_signature, argument_type, NULL)) + return log_oom(); + } else if (streq(argument_direction, "out")) { + if (!strextend(&context->member_result, argument_type, NULL)) + return log_oom(); + } else + log_error("Unexpected method direction value '%s'.", argument_direction); + } + + argument_type = mfree(argument_type); + argument_direction = mfree(argument_direction); + } + + state = STATE_METHOD; + } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in method . (1)"); + + break; + + case STATE_METHOD_ARG_NAME: + + if (t == XML_ATTRIBUTE_VALUE) + state = STATE_METHOD_ARG; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in method . (2)"); + + break; + + case STATE_METHOD_ARG_TYPE: + + if (t == XML_ATTRIBUTE_VALUE) { + free_and_replace(argument_type, name); + + state = STATE_METHOD_ARG; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in method . (3)"); + + break; + + case STATE_METHOD_ARG_DIRECTION: + + if (t == XML_ATTRIBUTE_VALUE) { + free_and_replace(argument_direction, name); + + state = STATE_METHOD_ARG; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in method . (4)"); + + break; + + case STATE_SIGNAL: + + if (t == XML_ATTRIBUTE_NAME) { + if (streq_ptr(name, "name")) + state = STATE_SIGNAL_NAME; + else + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Unexpected attribute %s.", + name); + } else if (t == XML_TAG_OPEN) { + if (streq_ptr(name, "arg")) + state = STATE_SIGNAL_ARG; + else if (streq_ptr(name, "annotation")) { + r = parse_xml_annotation(context, &context->member_flags); + if (r < 0) + return r; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected tag %s.", + name); + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq_ptr(name, "signal"))) { + + if (n_depth == 0) { + if (context->ops->on_signal) { + r = context->ops->on_signal(context->interface_name, context->member_name, context->member_signature, context->member_flags, context->userdata); + if (r < 0) + return r; + } + + context_reset_member(context); + } + + state = STATE_INTERFACE; + + } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (1)"); + + break; + + case STATE_SIGNAL_NAME: + + if (t == XML_ATTRIBUTE_VALUE) { + if (n_depth == 0) + free_and_replace(context->member_name, name); + + state = STATE_SIGNAL; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (2)"); + + break; + + case STATE_SIGNAL_ARG: + + if (t == XML_ATTRIBUTE_NAME) { + if (streq_ptr(name, "name")) + state = STATE_SIGNAL_ARG_NAME; + else if (streq_ptr(name, "type")) + state = STATE_SIGNAL_ARG_TYPE; + else if (streq_ptr(name, "direction")) + state = STATE_SIGNAL_ARG_DIRECTION; + else + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Unexpected signal attribute %s.", + name); + } else if (t == XML_TAG_OPEN) { + if (streq_ptr(name, "annotation")) { + r = parse_xml_annotation(context, NULL); + if (r < 0) + return r; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected signal tag %s.", + name); + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq_ptr(name, "arg"))) { + + if (argument_type) { + if (!argument_direction || streq(argument_direction, "out")) { + if (!strextend(&context->member_signature, argument_type, NULL)) + return log_oom(); + } else + log_error("Unexpected signal direction value '%s'.", argument_direction); + + argument_type = mfree(argument_type); + } + + state = STATE_SIGNAL; + } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in signal (1)."); + + break; + + case STATE_SIGNAL_ARG_NAME: + + if (t == XML_ATTRIBUTE_VALUE) + state = STATE_SIGNAL_ARG; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in signal (2)."); + + break; + + case STATE_SIGNAL_ARG_TYPE: + + if (t == XML_ATTRIBUTE_VALUE) { + free_and_replace(argument_type, name); + + state = STATE_SIGNAL_ARG; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in signal (3)."); + + break; + + case STATE_SIGNAL_ARG_DIRECTION: + + if (t == XML_ATTRIBUTE_VALUE) { + free_and_replace(argument_direction, name); + + state = STATE_SIGNAL_ARG; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in signal . (4)"); + + break; + + case STATE_PROPERTY: + + if (t == XML_ATTRIBUTE_NAME) { + if (streq_ptr(name, "name")) + state = STATE_PROPERTY_NAME; + else if (streq_ptr(name, "type")) + state = STATE_PROPERTY_TYPE; + else if (streq_ptr(name, "access")) + state = STATE_PROPERTY_ACCESS; + else + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Unexpected attribute %s.", + name); + } else if (t == XML_TAG_OPEN) { + + if (streq_ptr(name, "annotation")) { + r = parse_xml_annotation(context, &context->member_flags); + if (r < 0) + return r; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected tag %s.", + name); + + } else if (t == XML_TAG_CLOSE_EMPTY || + (t == XML_TAG_CLOSE && streq_ptr(name, "property"))) { + + if (n_depth == 0) { + if (context->ops->on_property) { + r = context->ops->on_property(context->interface_name, context->member_name, context->member_signature, context->member_writable, context->member_flags, context->userdata); + if (r < 0) + return r; + } + + context_reset_member(context); + } + + state = STATE_INTERFACE; + + } else if (t != XML_TEXT || !in_charset(name, WHITESPACE)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (1)"); + + break; + + case STATE_PROPERTY_NAME: + + if (t == XML_ATTRIBUTE_VALUE) { + if (n_depth == 0) + free_and_replace(context->member_name, name); + + state = STATE_PROPERTY; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (2)"); + + break; + + case STATE_PROPERTY_TYPE: + + if (t == XML_ATTRIBUTE_VALUE) { + if (n_depth == 0) + free_and_replace(context->member_signature, name); + + state = STATE_PROPERTY; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (3)"); + + break; + + case STATE_PROPERTY_ACCESS: + + if (t == XML_ATTRIBUTE_VALUE) { + + if (streq(name, "readwrite") || streq(name, "write")) + context->member_writable = true; + + state = STATE_PROPERTY; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected token in . (4)"); + + break; + } + } +} + +int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata) { + Context context = { + .ops = ops, + .userdata = userdata, + .current = xml, + }; + + int r; + + assert(prefix); + assert(xml); + assert(ops); + + for (;;) { + _cleanup_free_ char *name = NULL; + + r = xml_tokenize(&context.current, &name, &context.xml_state, NULL); + if (r < 0) { + log_error("XML parse error"); + goto finish; + } + + if (r == XML_END) { + r = 0; + break; + } + + if (r == XML_TAG_OPEN) { + + if (streq(name, "node")) { + r = parse_xml_node(&context, prefix, 0); + if (r < 0) + goto finish; + } else { + log_error("Unexpected tag '%s' in introspection data.", name); + r = -EBADMSG; + goto finish; + } + } else if (r != XML_TEXT || !in_charset(name, WHITESPACE)) { + log_error("Unexpected token."); + r = -EBADMSG; + goto finish; + } + } + +finish: + context_reset_interface(&context); + + return r; +} diff --git a/src/busctl/busctl-introspect.h b/src/busctl/busctl-introspect.h new file mode 100644 index 00000000..b17800e8 --- /dev/null +++ b/src/busctl/busctl-introspect.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +typedef struct XMLIntrospectOps { + int (*on_path)(const char *path, void *userdata); + int (*on_interface)(const char *name, uint64_t flags, void *userdata); + int (*on_method)(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata); + int (*on_signal)(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata); + int (*on_property)(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata); +} XMLIntrospectOps; + +int parse_xml_introspect(const char *prefix, const char *xml, const XMLIntrospectOps *ops, void *userdata); diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c new file mode 100644 index 00000000..878837eb --- /dev/null +++ b/src/busctl/busctl.c @@ -0,0 +1,2567 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-dump.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-signature.h" +#include "bus-type.h" +#include "bus-util.h" +#include "busctl-introspect.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-table.h" +#include "json.h" +#include "locale-util.h" +#include "log.h" +#include "main-func.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "set.h" +#include "sort-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "user-util.h" +#include "verbs.h" + +static enum { + JSON_OFF, + JSON_SHORT, + JSON_PRETTY, +} arg_json = JSON_OFF; +static PagerFlags arg_pager_flags = 0; +static bool arg_legend = true; +static const char *arg_address = NULL; +static bool arg_unique = false; +static bool arg_acquired = false; +static bool arg_activatable = false; +static bool arg_show_machine = false; +static char **arg_matches = NULL; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static const char *arg_host = NULL; +static bool arg_user = false; +static size_t arg_snaplen = 4096; +static bool arg_list = false; +static bool arg_quiet = false; +static bool arg_verbose = false; +static bool arg_xml_interface = false; +static bool arg_expect_reply = true; +static bool arg_auto_start = true; +static bool arg_allow_interactive_authorization = true; +static bool arg_augment_creds = true; +static bool arg_watch_bind = false; +static usec_t arg_timeout = 0; +static const char *arg_destination = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_matches, strv_freep); + +#define NAME_IS_ACQUIRED INT_TO_PTR(1) +#define NAME_IS_ACTIVATABLE INT_TO_PTR(2) + +static int json_transform_message(sd_bus_message *m, JsonVariant **ret); +static void json_dump_with_flags(JsonVariant *v, FILE *f); + +static int acquire_bus(bool set_monitor, sd_bus **ret) { + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; + int r; + + r = sd_bus_new(&bus); + if (r < 0) + return log_error_errno(r, "Failed to allocate bus: %m"); + + if (set_monitor) { + r = sd_bus_set_monitor(bus, true); + if (r < 0) + return log_error_errno(r, "Failed to set monitor mode: %m"); + + r = sd_bus_negotiate_creds(bus, true, _SD_BUS_CREDS_ALL); + if (r < 0) + return log_error_errno(r, "Failed to enable credentials: %m"); + + r = sd_bus_negotiate_timestamp(bus, true); + if (r < 0) + return log_error_errno(r, "Failed to enable timestamps: %m"); + + r = sd_bus_negotiate_fds(bus, true); + if (r < 0) + return log_error_errno(r, "Failed to enable fds: %m"); + } + + r = sd_bus_set_bus_client(bus, true); + if (r < 0) + return log_error_errno(r, "Failed to set bus client: %m"); + + r = sd_bus_set_watch_bind(bus, arg_watch_bind); + if (r < 0) + return log_error_errno(r, "Failed to set watch-bind setting to '%s': %m", yes_no(arg_watch_bind)); + + if (arg_address) + r = sd_bus_set_address(bus, arg_address); + else { + switch (arg_transport) { + + case BUS_TRANSPORT_LOCAL: + if (arg_user) { + bus->is_user = true; + r = bus_set_address_user(bus); + } else { + bus->is_system = true; + r = bus_set_address_system(bus); + } + break; + + case BUS_TRANSPORT_REMOTE: + r = bus_set_address_system_remote(bus, arg_host); + break; + + case BUS_TRANSPORT_MACHINE: + r = bus_set_address_system_machine(bus, arg_host); + break; + + default: + assert_not_reached("Hmm, unknown transport type."); + } + } + if (r < 0) + return log_error_errno(r, "Failed to set address: %m"); + + r = sd_bus_start(bus); + if (r < 0) + return log_error_errno(r, "Failed to connect to bus: %m"); + + *ret = TAKE_PTR(bus); + + return 0; +} + +static int list_bus_names(int argc, char **argv, void *userdata) { + _cleanup_strv_free_ char **acquired = NULL, **activatable = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_hashmap_free_ Hashmap *names = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + Iterator iterator; + char **i, *k; + void *v; + int r; + + enum { + COLUMN_ACTIVATABLE, + COLUMN_NAME, + COLUMN_PID, + COLUMN_PROCESS, + COLUMN_USER, + COLUMN_CONNECTION, + COLUMN_UNIT, + COLUMN_SESSION, + COLUMN_DESCRIPTION, + COLUMN_MACHINE, + }; + + if (!arg_unique && !arg_acquired && !arg_activatable) + arg_unique = arg_acquired = arg_activatable = true; + + r = acquire_bus(false, &bus); + if (r < 0) + return r; + + r = sd_bus_list_names(bus, (arg_acquired || arg_unique) ? &acquired : NULL, arg_activatable ? &activatable : NULL); + if (r < 0) + return log_error_errno(r, "Failed to list names: %m"); + + names = hashmap_new(&string_hash_ops); + if (!names) + return log_oom(); + + STRV_FOREACH(i, acquired) { + r = hashmap_put(names, *i, NAME_IS_ACQUIRED); + if (r < 0) + return log_error_errno(r, "Failed to add to hashmap: %m"); + } + + STRV_FOREACH(i, activatable) { + r = hashmap_put(names, *i, NAME_IS_ACTIVATABLE); + if (r < 0 && r != -EEXIST) + return log_error_errno(r, "Failed to add to hashmap: %m"); + } + + table = table_new("activatable", "name", "pid", "process", "user", "connection", "unit", "session", "description", "machine"); + if (!table) + return log_oom(); + + r = table_set_align_percent(table, table_get_cell(table, 0, COLUMN_PID), 100); + if (r < 0) + return log_error_errno(r, "Failed to set alignment: %m"); + + r = table_set_empty_string(table, "-"); + if (r < 0) + return log_error_errno(r, "Failed to set empty string: %m"); + + r = table_set_sort(table, COLUMN_NAME, (size_t) -1); + if (r < 0) + return log_error_errno(r, "Failed to set sort column: %m"); + + if (arg_show_machine) + r = table_set_display(table, COLUMN_NAME, COLUMN_PID, COLUMN_PROCESS, COLUMN_USER, COLUMN_CONNECTION, COLUMN_UNIT, COLUMN_SESSION, COLUMN_DESCRIPTION, COLUMN_MACHINE, (size_t) -1); + else + r = table_set_display(table, COLUMN_NAME, COLUMN_PID, COLUMN_PROCESS, COLUMN_USER, COLUMN_CONNECTION, COLUMN_UNIT, COLUMN_SESSION, COLUMN_DESCRIPTION, (size_t) -1); + if (r < 0) + return log_error_errno(r, "Failed to set columns to display: %m"); + + table_set_header(table, arg_legend); + + HASHMAP_FOREACH_KEY(v, k, names, iterator) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + + if (v == NAME_IS_ACTIVATABLE) { + r = table_add_many( + table, + TABLE_INT, PTR_TO_INT(v), + TABLE_STRING, k, + TABLE_EMPTY, + TABLE_EMPTY, + TABLE_EMPTY, + TABLE_STRING, "(activatable)", TABLE_SET_COLOR, ansi_grey(), + TABLE_EMPTY, + TABLE_EMPTY, + TABLE_EMPTY, + TABLE_EMPTY); + if (r < 0) + return log_error_errno(r, "Failed to fill line: %m"); + + continue; + } + + assert(v == NAME_IS_ACQUIRED); + + if (!arg_unique && k[0] == ':') + continue; + + if (!arg_acquired && k[0] != ':') + continue; + + r = table_add_many(table, + TABLE_INT, PTR_TO_INT(v), + TABLE_STRING, k); + if (r < 0) + return log_error_errno(r, "Failed to add name %s to table: %m", k); + + r = sd_bus_get_name_creds( + bus, k, + (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | + SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM| + SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_SESSION| + SD_BUS_CREDS_DESCRIPTION, &creds); + if (r < 0) { + log_debug_errno(r, "Failed to acquire credentials of service %s, ignoring: %m", k); + + r = table_fill_empty(table, COLUMN_MACHINE); + } else { + const char *unique = NULL, *session = NULL, *unit = NULL, *cn = NULL; + pid_t pid; + uid_t uid; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r >= 0) { + const char *comm = NULL; + + (void) sd_bus_creds_get_comm(creds, &comm); + + r = table_add_many(table, + TABLE_PID, pid, + TABLE_STRING, strna(comm)); + } else + r = table_add_many(table, TABLE_EMPTY, TABLE_EMPTY); + if (r < 0) + return log_error_errno(r, "Failed to add fields to table: %m"); + + r = sd_bus_creds_get_euid(creds, &uid); + if (r >= 0) { + _cleanup_free_ char *u = NULL; + + u = uid_to_name(uid); + if (!u) + return log_oom(); + + r = table_add_cell(table, NULL, TABLE_STRING, u); + } else + r = table_add_cell(table, NULL, TABLE_EMPTY, NULL); + if (r < 0) + return log_error_errno(r, "Failed to add field to table: %m"); + + (void) sd_bus_creds_get_unique_name(creds, &unique); + (void) sd_bus_creds_get_unit(creds, &unit); + (void) sd_bus_creds_get_session(creds, &session); + (void) sd_bus_creds_get_description(creds, &cn); + + r = table_add_many( + table, + TABLE_STRING, unique, + TABLE_STRING, unit, + TABLE_STRING, session, + TABLE_STRING, cn); + } + if (r < 0) + return log_error_errno(r, "Failed to add fields to table: %m"); + + if (arg_show_machine) { + sd_id128_t mid; + + r = sd_bus_get_name_machine_id(bus, k, &mid); + if (r < 0) + log_debug_errno(r, "Failed to acquire credentials of service %s, ignoring: %m", k); + else { + char m[SD_ID128_STRING_MAX]; + + r = table_add_cell(table, NULL, TABLE_STRING, sd_id128_to_string(mid, m)); + if (r < 0) + return log_error_errno(r, "Failed to add field to table: %m"); + + continue; /* line fully filled, no need to fill the remainder below */ + } + } + + r = table_fill_empty(table, 0); + if (r < 0) + return log_error_errno(r, "Failed to fill line: %m"); + } + + if (IN_SET(arg_json, JSON_OFF, JSON_PRETTY)) + (void) pager_open(arg_pager_flags); + + if (arg_json) + r = table_print_json(table, stdout, (arg_json == JSON_PRETTY ? JSON_FORMAT_PRETTY : JSON_FORMAT_NEWLINE) | JSON_FORMAT_COLOR_AUTO); + else + r = table_print(table, stdout); + if (r < 0) + return log_error_errno(r, "Failed to show table: %m"); + + return 0; +} + +static void print_subtree(const char *prefix, const char *path, char **l) { + const char *vertical, *space; + char **n; + + /* We assume the list is sorted. Let's first skip over the + * entry we are looking at. */ + for (;;) { + if (!*l) + return; + + if (!streq(*l, path)) + break; + + l++; + } + + vertical = strjoina(prefix, special_glyph(SPECIAL_GLYPH_TREE_VERTICAL)); + space = strjoina(prefix, special_glyph(SPECIAL_GLYPH_TREE_SPACE)); + + for (;;) { + bool has_more = false; + + if (!*l || !path_startswith(*l, path)) + break; + + n = l + 1; + for (;;) { + if (!*n || !path_startswith(*n, path)) + break; + + if (!path_startswith(*n, *l)) { + has_more = true; + break; + } + + n++; + } + + printf("%s%s%s\n", prefix, special_glyph(has_more ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT), *l); + + print_subtree(has_more ? vertical : space, *l, l); + l = n; + } +} + +static void print_tree(const char *prefix, char **l) { + + prefix = strempty(prefix); + + if (arg_list) { + char **i; + + STRV_FOREACH(i, l) + printf("%s%s\n", prefix, *i); + return; + } + + if (strv_isempty(l)) { + printf("No objects discovered.\n"); + return; + } + + if (streq(l[0], "/") && !l[1]) { + printf("Only root object discovered.\n"); + return; + } + + print_subtree(prefix, "/", l); +} + +static int on_path(const char *path, void *userdata) { + Set *paths = userdata; + int r; + + assert(paths); + + r = set_put_strdup(paths, path); + if (r < 0) + return log_oom(); + + return 0; +} + +static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths, bool many) { + static const XMLIntrospectOps ops = { + .on_path = on_path, + }; + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *xml; + int r; + + r = sd_bus_call_method(bus, service, path, "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); + if (r < 0) { + if (many) + printf("Failed to introspect object %s of service %s: %s\n", path, service, bus_error_message(&error, r)); + else + log_error_errno(r, "Failed to introspect object %s of service %s: %s", path, service, bus_error_message(&error, r)); + return r; + } + + r = sd_bus_message_read(reply, "s", &xml); + if (r < 0) + return bus_log_parse_error(r); + + return parse_xml_introspect(path, xml, &ops, paths); +} + +static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool many) { + _cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL; + _cleanup_free_ char **l = NULL; + char *m; + int r; + + paths = set_new(&string_hash_ops); + if (!paths) + return log_oom(); + + done = set_new(&string_hash_ops); + if (!done) + return log_oom(); + + failed = set_new(&string_hash_ops); + if (!failed) + return log_oom(); + + m = strdup("/"); + if (!m) + return log_oom(); + + r = set_put(paths, m); + if (r < 0) { + free(m); + return log_oom(); + } + + for (;;) { + _cleanup_free_ char *p = NULL; + int q; + + p = set_steal_first(paths); + if (!p) + break; + + if (set_contains(done, p) || + set_contains(failed, p)) + continue; + + q = find_nodes(bus, service, p, paths, many); + if (q < 0) { + if (r >= 0) + r = q; + + q = set_put(failed, p); + } else + q = set_put(done, p); + + if (q < 0) + return log_oom(); + + assert(q != 0); + p = NULL; + } + + (void) pager_open(arg_pager_flags); + + l = set_get_strv(done); + if (!l) + return log_oom(); + + strv_sort(l); + print_tree(prefix, l); + + fflush(stdout); + + return r; +} + +static int tree(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + char **i; + int r = 0; + + if (!arg_unique && !arg_acquired) + arg_acquired = true; + + r = acquire_bus(false, &bus); + if (r < 0) + return r; + + if (argc <= 1) { + _cleanup_strv_free_ char **names = NULL; + bool not_first = false; + + r = sd_bus_list_names(bus, &names, NULL); + if (r < 0) + return log_error_errno(r, "Failed to get name list: %m"); + + (void) pager_open(arg_pager_flags); + + STRV_FOREACH(i, names) { + int q; + + if (!arg_unique && (*i)[0] == ':') + continue; + + if (!arg_acquired && (*i)[0] == ':') + continue; + + if (not_first) + printf("\n"); + + printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal()); + + q = tree_one(bus, *i, NULL, true); + if (q < 0 && r >= 0) + r = q; + + not_first = true; + } + } else { + STRV_FOREACH(i, argv+1) { + int q; + + if (i > argv+1) + printf("\n"); + + if (argv[2]) { + (void) pager_open(arg_pager_flags); + printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal()); + } + + q = tree_one(bus, *i, NULL, !!argv[2]); + if (q < 0 && r >= 0) + r = q; + } + } + + return r; +} + +static int format_cmdline(sd_bus_message *m, FILE *f, bool needs_space) { + int r; + + for (;;) { + const char *contents = NULL; + char type; + union { + uint8_t u8; + uint16_t u16; + int16_t s16; + uint32_t u32; + int32_t s32; + uint64_t u64; + int64_t s64; + double d64; + const char *string; + int i; + } basic; + + r = sd_bus_message_peek_type(m, &type, &contents); + if (r < 0) + return r; + if (r == 0) + return needs_space; + + if (bus_type_is_container(type) > 0) { + + r = sd_bus_message_enter_container(m, type, contents); + if (r < 0) + return r; + + if (type == SD_BUS_TYPE_ARRAY) { + unsigned n = 0; + + /* count array entries */ + for (;;) { + + r = sd_bus_message_skip(m, contents); + if (r < 0) + return r; + if (r == 0) + break; + + n++; + } + + r = sd_bus_message_rewind(m, false); + if (r < 0) + return r; + + if (needs_space) + fputc(' ', f); + + fprintf(f, "%u", n); + needs_space = true; + + } else if (type == SD_BUS_TYPE_VARIANT) { + + if (needs_space) + fputc(' ', f); + + fprintf(f, "%s", contents); + needs_space = true; + } + + r = format_cmdline(m, f, needs_space); + if (r < 0) + return r; + + needs_space = r > 0; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + continue; + } + + r = sd_bus_message_read_basic(m, type, &basic); + if (r < 0) + return r; + + if (needs_space) + fputc(' ', f); + + switch (type) { + case SD_BUS_TYPE_BYTE: + fprintf(f, "%u", basic.u8); + break; + + case SD_BUS_TYPE_BOOLEAN: + fputs(true_false(basic.i), f); + break; + + case SD_BUS_TYPE_INT16: + fprintf(f, "%i", basic.s16); + break; + + case SD_BUS_TYPE_UINT16: + fprintf(f, "%u", basic.u16); + break; + + case SD_BUS_TYPE_INT32: + fprintf(f, "%i", basic.s32); + break; + + case SD_BUS_TYPE_UINT32: + fprintf(f, "%u", basic.u32); + break; + + case SD_BUS_TYPE_INT64: + fprintf(f, "%" PRIi64, basic.s64); + break; + + case SD_BUS_TYPE_UINT64: + fprintf(f, "%" PRIu64, basic.u64); + break; + + case SD_BUS_TYPE_DOUBLE: + fprintf(f, "%g", basic.d64); + break; + + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: { + _cleanup_free_ char *b = NULL; + + b = cescape(basic.string); + if (!b) + return -ENOMEM; + + fprintf(f, "\"%s\"", b); + break; + } + + case SD_BUS_TYPE_UNIX_FD: + fprintf(f, "%i", basic.i); + break; + + default: + assert_not_reached("Unknown basic type."); + } + + needs_space = true; + } +} + +typedef struct Member { + const char *type; + char *interface; + char *name; + char *signature; + char *result; + char *value; + bool writable; + uint64_t flags; +} Member; + +static void member_hash_func(const Member *m, struct siphash *state) { + uint64_t arity = 1; + + assert(m); + assert(m->type); + + string_hash_func(m->type, state); + + arity += !!m->name + !!m->interface; + + uint64_hash_func(&arity, state); + + if (m->name) + string_hash_func(m->name, state); + + if (m->interface) + string_hash_func(m->interface, state); +} + +static int member_compare_func(const Member *x, const Member *y) { + int d; + + assert(x); + assert(y); + assert(x->type); + assert(y->type); + + d = strcmp_ptr(x->interface, y->interface); + if (d != 0) + return d; + + d = strcmp(x->type, y->type); + if (d != 0) + return d; + + return strcmp_ptr(x->name, y->name); +} + +static int member_compare_funcp(Member * const *a, Member * const *b) { + return member_compare_func(*a, *b); +} + +static void member_free(Member *m) { + if (!m) + return; + + free(m->interface); + free(m->name); + free(m->signature); + free(m->result); + free(m->value); + free(m); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Member*, member_free); + +static void member_set_free(Set *s) { + set_free_with_destructor(s, member_free); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, member_set_free); + +static int on_interface(const char *interface, uint64_t flags, void *userdata) { + _cleanup_(member_freep) Member *m; + Set *members = userdata; + int r; + + assert(interface); + assert(members); + + m = new0(Member, 1); + if (!m) + return log_oom(); + + m->type = "interface"; + m->flags = flags; + + r = free_and_strdup(&m->interface, interface); + if (r < 0) + return log_oom(); + + r = set_put(members, m); + if (r <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate interface"); + + m = NULL; + return 0; +} + +static int on_method(const char *interface, const char *name, const char *signature, const char *result, uint64_t flags, void *userdata) { + _cleanup_(member_freep) Member *m; + Set *members = userdata; + int r; + + assert(interface); + assert(name); + + m = new0(Member, 1); + if (!m) + return log_oom(); + + m->type = "method"; + m->flags = flags; + + r = free_and_strdup(&m->interface, interface); + if (r < 0) + return log_oom(); + + r = free_and_strdup(&m->name, name); + if (r < 0) + return log_oom(); + + r = free_and_strdup(&m->signature, signature); + if (r < 0) + return log_oom(); + + r = free_and_strdup(&m->result, result); + if (r < 0) + return log_oom(); + + r = set_put(members, m); + if (r <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate method"); + + m = NULL; + return 0; +} + +static int on_signal(const char *interface, const char *name, const char *signature, uint64_t flags, void *userdata) { + _cleanup_(member_freep) Member *m; + Set *members = userdata; + int r; + + assert(interface); + assert(name); + + m = new0(Member, 1); + if (!m) + return log_oom(); + + m->type = "signal"; + m->flags = flags; + + r = free_and_strdup(&m->interface, interface); + if (r < 0) + return log_oom(); + + r = free_and_strdup(&m->name, name); + if (r < 0) + return log_oom(); + + r = free_and_strdup(&m->signature, signature); + if (r < 0) + return log_oom(); + + r = set_put(members, m); + if (r <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate signal"); + + m = NULL; + return 0; +} + +static int on_property(const char *interface, const char *name, const char *signature, bool writable, uint64_t flags, void *userdata) { + _cleanup_(member_freep) Member *m; + Set *members = userdata; + int r; + + assert(interface); + assert(name); + + m = new0(Member, 1); + if (!m) + return log_oom(); + + m->type = "property"; + m->flags = flags; + m->writable = writable; + + r = free_and_strdup(&m->interface, interface); + if (r < 0) + return log_oom(); + + r = free_and_strdup(&m->name, name); + if (r < 0) + return log_oom(); + + r = free_and_strdup(&m->signature, signature); + if (r < 0) + return log_oom(); + + r = set_put(members, m); + if (r <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Duplicate property"); + + m = NULL; + return 0; +} + +DEFINE_PRIVATE_HASH_OPS(member_hash_ops, Member, member_hash_func, member_compare_func); + +static int introspect(int argc, char **argv, void *userdata) { + static const XMLIntrospectOps ops = { + .on_interface = on_interface, + .on_method = on_method, + .on_signal = on_signal, + .on_property = on_property, + }; + + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_xml = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(member_set_freep) Set *members = NULL; + unsigned name_width, type_width, signature_width, result_width, j, k = 0; + Member *m, **sorted = NULL; + Iterator i; + const char *xml; + int r; + + r = acquire_bus(false, &bus); + if (r < 0) + return r; + + members = set_new(&member_hash_ops); + if (!members) + return log_oom(); + + r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply_xml, ""); + if (r < 0) + return log_error_errno(r, "Failed to introspect object %s of service %s: %s", argv[2], argv[1], bus_error_message(&error, r)); + + r = sd_bus_message_read(reply_xml, "s", &xml); + if (r < 0) + return bus_log_parse_error(r); + + if (arg_xml_interface) { + /* Just dump the received XML and finish */ + puts(xml); + return 0; + } + + /* First, get list of all properties */ + r = parse_xml_introspect(argv[2], xml, &ops, members); + if (r < 0) + return r; + + /* Second, find the current values for them */ + SET_FOREACH(m, members, i) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + + if (!streq(m->type, "property")) + continue; + + if (m->value) + continue; + + if (argv[3] && !streq(argv[3], m->interface)) + continue; + + r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", m->interface); + if (r < 0) + return log_error_errno(r, "Failed to get all properties on interface %s: %s", + m->interface, bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, 'a', "{sv}"); + if (r < 0) + return bus_log_parse_error(r); + + for (;;) { + Member *z; + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *mf = NULL; + size_t sz = 0; + const char *name; + + r = sd_bus_message_enter_container(reply, 'e', "sv"); + if (r < 0) + return bus_log_parse_error(r); + + if (r == 0) + break; + + r = sd_bus_message_read(reply, "s", &name); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_enter_container(reply, 'v', NULL); + if (r < 0) + return bus_log_parse_error(r); + + mf = open_memstream_unlocked(&buf, &sz); + if (!mf) + return log_oom(); + + r = format_cmdline(reply, mf, false); + if (r < 0) + return bus_log_parse_error(r); + + mf = safe_fclose(mf); + + z = set_get(members, &((Member) { + .type = "property", + .interface = m->interface, + .name = (char*) name })); + if (z) + free_and_replace(z->value, buf); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + } + + (void) pager_open(arg_pager_flags); + + name_width = STRLEN("NAME"); + type_width = STRLEN("TYPE"); + signature_width = STRLEN("SIGNATURE"); + result_width = STRLEN("RESULT/VALUE"); + + sorted = newa(Member*, set_size(members)); + + SET_FOREACH(m, members, i) { + + if (argv[3] && !streq(argv[3], m->interface)) + continue; + + if (m->interface) + name_width = MAX(name_width, strlen(m->interface)); + if (m->name) + name_width = MAX(name_width, strlen(m->name) + 1); + if (m->type) + type_width = MAX(type_width, strlen(m->type)); + if (m->signature) + signature_width = MAX(signature_width, strlen(m->signature)); + if (m->result) + result_width = MAX(result_width, strlen(m->result)); + if (m->value) + result_width = MAX(result_width, strlen(m->value)); + + sorted[k++] = m; + } + + if (result_width > 40) + result_width = 40; + + typesafe_qsort(sorted, k, member_compare_funcp); + + if (arg_legend) { + printf("%-*s %-*s %-*s %-*s %s\n", + (int) name_width, "NAME", + (int) type_width, "TYPE", + (int) signature_width, "SIGNATURE", + (int) result_width, "RESULT/VALUE", + "FLAGS"); + } + + for (j = 0; j < k; j++) { + _cleanup_free_ char *ellipsized = NULL; + const char *rv; + bool is_interface; + + m = sorted[j]; + + if (argv[3] && !streq(argv[3], m->interface)) + continue; + + is_interface = streq(m->type, "interface"); + + if (argv[3] && is_interface) + continue; + + if (m->value) { + ellipsized = ellipsize(m->value, result_width, 100); + if (!ellipsized) + return log_oom(); + + rv = ellipsized; + } else + rv = empty_to_dash(m->result); + + printf("%s%s%-*s%s %-*s %-*s %-*s%s%s%s%s%s%s\n", + is_interface ? ansi_highlight() : "", + is_interface ? "" : ".", + - !is_interface + (int) name_width, empty_to_dash(streq_ptr(m->type, "interface") ? m->interface : m->name), + is_interface ? ansi_normal() : "", + (int) type_width, empty_to_dash(m->type), + (int) signature_width, empty_to_dash(m->signature), + (int) result_width, rv, + (m->flags & SD_BUS_VTABLE_DEPRECATED) ? " deprecated" : (m->flags || m->writable ? "" : " -"), + (m->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) ? " no-reply" : "", + (m->flags & SD_BUS_VTABLE_PROPERTY_CONST) ? " const" : "", + (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) ? " emits-change" : "", + (m->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) ? " emits-invalidation" : "", + m->writable ? " writable" : ""); + } + + return 0; +} + +static int message_dump(sd_bus_message *m, FILE *f) { + return bus_message_dump(m, f, BUS_MESSAGE_DUMP_WITH_HEADER); +} + +static int message_pcap(sd_bus_message *m, FILE *f) { + return bus_message_pcap_frame(m, arg_snaplen, f); +} + +static int message_json(sd_bus_message *m, FILE *f) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL; + char e[2]; + int r; + + r = json_transform_message(m, &v); + if (r < 0) + return r; + + e[0] = m->header->endian; + e[1] = 0; + + r = json_build(&w, JSON_BUILD_OBJECT( + JSON_BUILD_PAIR("type", JSON_BUILD_STRING(bus_message_type_to_string(m->header->type))), + JSON_BUILD_PAIR("endian", JSON_BUILD_STRING(e)), + JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(m->header->flags)), + JSON_BUILD_PAIR("version", JSON_BUILD_INTEGER(m->header->version)), + JSON_BUILD_PAIR_CONDITION(m->priority != 0, "priority", JSON_BUILD_INTEGER(m->priority)), + JSON_BUILD_PAIR("cookie", JSON_BUILD_INTEGER(BUS_MESSAGE_COOKIE(m))), + JSON_BUILD_PAIR_CONDITION(m->reply_cookie != 0, "reply_cookie", JSON_BUILD_INTEGER(m->reply_cookie)), + JSON_BUILD_PAIR_CONDITION(m->sender, "sender", JSON_BUILD_STRING(m->sender)), + JSON_BUILD_PAIR_CONDITION(m->destination, "destination", JSON_BUILD_STRING(m->destination)), + JSON_BUILD_PAIR_CONDITION(m->path, "path", JSON_BUILD_STRING(m->path)), + JSON_BUILD_PAIR_CONDITION(m->interface, "interface", JSON_BUILD_STRING(m->interface)), + JSON_BUILD_PAIR_CONDITION(m->member, "member", JSON_BUILD_STRING(m->member)), + JSON_BUILD_PAIR_CONDITION(m->monotonic != 0, "monotonic", JSON_BUILD_INTEGER(m->monotonic)), + JSON_BUILD_PAIR_CONDITION(m->realtime != 0, "realtime", JSON_BUILD_INTEGER(m->realtime)), + JSON_BUILD_PAIR_CONDITION(m->seqnum != 0, "seqnum", JSON_BUILD_INTEGER(m->seqnum)), + JSON_BUILD_PAIR_CONDITION(m->error.name, "error_name", JSON_BUILD_STRING(m->error.name)), + JSON_BUILD_PAIR("payload", JSON_BUILD_VARIANT(v)))); + if (r < 0) + return log_error_errno(r, "Failed to build JSON object: %m"); + + json_dump_with_flags(w, f); + return 0; +} + +static int monitor(int argc, char **argv, int (*dump)(sd_bus_message *m, FILE *f)) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + char **i; + uint32_t flags = 0; + const char *unique_name; + bool is_monitor = false; + int r; + + r = acquire_bus(true, &bus); + if (r < 0) + return r; + + /* upgrade connection; it's not used for anything else after this call */ + r = sd_bus_message_new_method_call(bus, + &message, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus.Monitoring", + "BecomeMonitor"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(message, 'a', "s"); + if (r < 0) + return bus_log_create_error(r); + + STRV_FOREACH(i, argv+1) { + _cleanup_free_ char *m = NULL; + + if (!service_name_is_valid(*i)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid service name '%s'", *i); + + m = strjoin("sender='", *i, "'"); + if (!m) + return log_oom(); + + r = sd_bus_message_append_basic(message, 's', m); + if (r < 0) + return bus_log_create_error(r); + + free(m); + m = strjoin("destination='", *i, "'"); + if (!m) + return log_oom(); + + r = sd_bus_message_append_basic(message, 's', m); + if (r < 0) + return bus_log_create_error(r); + } + + STRV_FOREACH(i, arg_matches) { + r = sd_bus_message_append_basic(message, 's', *i); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(message); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(message, 'u', &flags); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, message, arg_timeout, &error, NULL); + if (r < 0) + return log_error_errno(r, "Call to org.freedesktop.DBus.Monitoring.BecomeMonitor failed: %s", + bus_error_message(&error, r)); + + r = sd_bus_get_unique_name(bus, &unique_name); + if (r < 0) + return log_error_errno(r, "Failed to get unique name: %m"); + + log_info("Monitoring bus message stream."); + + for (;;) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + r = sd_bus_process(bus, &m); + if (r < 0) + return log_error_errno(r, "Failed to process bus: %m"); + + if (!is_monitor) { + const char *name; + + /* wait until we lose our unique name */ + if (sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameLost") <= 0) + continue; + + r = sd_bus_message_read(m, "s", &name); + if (r < 0) + return log_error_errno(r, "Failed to read lost name: %m"); + + if (streq(name, unique_name)) + is_monitor = true; + + continue; + } + + if (m) { + dump(m, stdout); + fflush(stdout); + + if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected") > 0) { + log_info("Connection terminated, exiting."); + return 0; + } + + continue; + } + + if (r > 0) + continue; + + r = sd_bus_wait(bus, (uint64_t) -1); + if (r < 0) + return log_error_errno(r, "Failed to wait for bus: %m"); + } +} + +static int verb_monitor(int argc, char **argv, void *userdata) { + return monitor(argc, argv, arg_json != JSON_OFF ? message_json : message_dump); +} + +static int verb_capture(int argc, char **argv, void *userdata) { + int r; + + if (isatty(fileno(stdout)) > 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Refusing to write message data to console, please redirect output to a file."); + + bus_pcap_header(arg_snaplen, stdout); + + r = monitor(argc, argv, message_pcap); + if (r < 0) + return r; + + r = fflush_and_check(stdout); + if (r < 0) + return log_error_errno(r, "Couldn't write capture file: %m"); + + return r; +} + +static int status(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + pid_t pid; + int r; + + r = acquire_bus(false, &bus); + if (r < 0) + return r; + + if (!isempty(argv[1])) { + r = parse_pid(argv[1], &pid); + if (r < 0) + r = sd_bus_get_name_creds( + bus, + argv[1], + (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL, + &creds); + else + r = sd_bus_creds_new_from_pid( + &creds, + pid, + _SD_BUS_CREDS_ALL); + } else { + const char *scope, *address; + sd_id128_t bus_id; + + r = sd_bus_get_address(bus, &address); + if (r >= 0) + printf("BusAddress=%s%s%s\n", ansi_highlight(), address, ansi_normal()); + + r = sd_bus_get_scope(bus, &scope); + if (r >= 0) + printf("BusScope=%s%s%s\n", ansi_highlight(), scope, ansi_normal()); + + r = sd_bus_get_bus_id(bus, &bus_id); + if (r >= 0) + printf("BusID=%s" SD_ID128_FORMAT_STR "%s\n", ansi_highlight(), SD_ID128_FORMAT_VAL(bus_id), ansi_normal()); + + r = sd_bus_get_owner_creds( + bus, + (arg_augment_creds ? SD_BUS_CREDS_AUGMENT : 0) | _SD_BUS_CREDS_ALL, + &creds); + } + + if (r < 0) + return log_error_errno(r, "Failed to get credentials: %m"); + + bus_creds_dump(creds, NULL, false); + return 0; +} + +static int message_append_cmdline(sd_bus_message *m, const char *signature, char ***x) { + char **p; + int r; + + assert(m); + assert(signature); + assert(x); + + p = *x; + + for (;;) { + const char *v; + char t; + + t = *signature; + v = *p; + + if (t == 0) + break; + if (!v) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too few parameters for signature."); + + signature++; + p++; + + switch (t) { + + case SD_BUS_TYPE_BOOLEAN: + + r = parse_boolean(v); + if (r < 0) + return log_error_errno(r, "Failed to parse '%s' as boolean: %m", v); + + r = sd_bus_message_append_basic(m, t, &r); + break; + + case SD_BUS_TYPE_BYTE: { + uint8_t z; + + r = safe_atou8(v, &z); + if (r < 0) + return log_error_errno(r, "Failed to parse '%s' as byte (unsigned 8bit integer): %m", v); + + r = sd_bus_message_append_basic(m, t, &z); + break; + } + + case SD_BUS_TYPE_INT16: { + int16_t z; + + r = safe_atoi16(v, &z); + if (r < 0) + return log_error_errno(r, "Failed to parse '%s' as signed 16bit integer: %m", v); + + r = sd_bus_message_append_basic(m, t, &z); + break; + } + + case SD_BUS_TYPE_UINT16: { + uint16_t z; + + r = safe_atou16(v, &z); + if (r < 0) + return log_error_errno(r, "Failed to parse '%s' as unsigned 16bit integer: %m", v); + + r = sd_bus_message_append_basic(m, t, &z); + break; + } + + case SD_BUS_TYPE_INT32: { + int32_t z; + + r = safe_atoi32(v, &z); + if (r < 0) + return log_error_errno(r, "Failed to parse '%s' as signed 32bit integer: %m", v); + + r = sd_bus_message_append_basic(m, t, &z); + break; + } + + case SD_BUS_TYPE_UINT32: { + uint32_t z; + + r = safe_atou32(v, &z); + if (r < 0) + return log_error_errno(r, "Failed to parse '%s' as unsigned 32bit integer: %m", v); + + r = sd_bus_message_append_basic(m, t, &z); + break; + } + + case SD_BUS_TYPE_INT64: { + int64_t z; + + r = safe_atoi64(v, &z); + if (r < 0) + return log_error_errno(r, "Failed to parse '%s' as signed 64bit integer: %m", v); + + r = sd_bus_message_append_basic(m, t, &z); + break; + } + + case SD_BUS_TYPE_UINT64: { + uint64_t z; + + r = safe_atou64(v, &z); + if (r < 0) + return log_error_errno(r, "Failed to parse '%s' as unsigned 64bit integer: %m", v); + + r = sd_bus_message_append_basic(m, t, &z); + break; + } + + case SD_BUS_TYPE_DOUBLE: { + double z; + + r = safe_atod(v, &z); + if (r < 0) + return log_error_errno(r, "Failed to parse '%s' as double precision floating point: %m", v); + + r = sd_bus_message_append_basic(m, t, &z); + break; + } + + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: + + r = sd_bus_message_append_basic(m, t, v); + break; + + case SD_BUS_TYPE_ARRAY: { + uint32_t n; + size_t k; + + r = safe_atou32(v, &n); + if (r < 0) + return log_error_errno(r, "Failed to parse '%s' number of array entries: %m", v); + + r = signature_element_length(signature, &k); + if (r < 0) + return log_error_errno(r, "Invalid array signature: %m"); + + { + unsigned i; + char s[k + 1]; + memcpy(s, signature, k); + s[k] = 0; + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s); + if (r < 0) + return bus_log_create_error(r); + + for (i = 0; i < n; i++) { + r = message_append_cmdline(m, s, &p); + if (r < 0) + return r; + } + } + + signature += k; + + r = sd_bus_message_close_container(m); + break; + } + + case SD_BUS_TYPE_VARIANT: + r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, v); + if (r < 0) + return bus_log_create_error(r); + + r = message_append_cmdline(m, v, &p); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + break; + + case SD_BUS_TYPE_STRUCT_BEGIN: + case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { + size_t k; + + signature--; + p--; + + r = signature_element_length(signature, &k); + if (r < 0) + return log_error_errno(r, "Invalid struct/dict entry signature: %m"); + + { + char s[k-1]; + memcpy(s, signature + 1, k - 2); + s[k - 2] = 0; + + r = sd_bus_message_open_container(m, t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s); + if (r < 0) + return bus_log_create_error(r); + + r = message_append_cmdline(m, s, &p); + if (r < 0) + return r; + } + + signature += k; + + r = sd_bus_message_close_container(m); + break; + } + + case SD_BUS_TYPE_UNIX_FD: + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "UNIX file descriptor not supported as type."); + + default: + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown signature type %c.", t); + } + + if (r < 0) + return bus_log_create_error(r); + } + + *x = p; + return 0; +} + +static int json_transform_one(sd_bus_message *m, JsonVariant **ret); + +static int json_transform_array_or_struct(sd_bus_message *m, JsonVariant **ret) { + size_t n_elements = 0, n_allocated = 0; + JsonVariant **elements = NULL; + int r; + + assert(m); + assert(ret); + + for (;;) { + r = sd_bus_message_at_end(m, false); + if (r < 0) { + bus_log_parse_error(r); + goto finish; + } + if (r > 0) + break; + + if (!GREEDY_REALLOC(elements, n_allocated, n_elements + 1)) { + r = log_oom(); + goto finish; + } + + r = json_transform_one(m, elements + n_elements); + if (r < 0) + goto finish; + + n_elements++; + } + + r = json_variant_new_array(ret, elements, n_elements); + +finish: + json_variant_unref_many(elements, n_elements); + free(elements); + + return r; +} + +static int json_transform_variant(sd_bus_message *m, const char *contents, JsonVariant **ret) { + _cleanup_(json_variant_unrefp) JsonVariant *value = NULL; + int r; + + assert(m); + assert(contents); + assert(ret); + + r = json_transform_one(m, &value); + if (r < 0) + return r; + + r = json_build(ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("type", JSON_BUILD_STRING(contents)), + JSON_BUILD_PAIR("data", JSON_BUILD_VARIANT(value)))); + if (r < 0) + return log_oom(); + + return r; +} + +static int json_transform_dict_array(sd_bus_message *m, JsonVariant **ret) { + size_t n_elements = 0, n_allocated = 0; + JsonVariant **elements = NULL; + int r; + + assert(m); + assert(ret); + + for (;;) { + const char *contents; + char type; + + r = sd_bus_message_at_end(m, false); + if (r < 0) { + bus_log_parse_error(r); + goto finish; + } + if (r > 0) + break; + + r = sd_bus_message_peek_type(m, &type, &contents); + if (r < 0) + return r; + + assert(type == 'e'); + + if (!GREEDY_REALLOC(elements, n_allocated, n_elements + 2)) { + r = log_oom(); + goto finish; + } + + r = sd_bus_message_enter_container(m, type, contents); + if (r < 0) { + bus_log_parse_error(r); + goto finish; + } + + r = json_transform_one(m, elements + n_elements); + if (r < 0) + goto finish; + + n_elements++; + + r = json_transform_one(m, elements + n_elements); + if (r < 0) + goto finish; + + n_elements++; + + r = sd_bus_message_exit_container(m); + if (r < 0) { + bus_log_parse_error(r); + goto finish; + } + } + + r = json_variant_new_object(ret, elements, n_elements); + +finish: + json_variant_unref_many(elements, n_elements); + free(elements); + + return r; +} + +static int json_transform_one(sd_bus_message *m, JsonVariant **ret) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + const char *contents; + char type; + int r; + + assert(m); + assert(ret); + + r = sd_bus_message_peek_type(m, &type, &contents); + if (r < 0) + return bus_log_parse_error(r); + + switch (type) { + + case SD_BUS_TYPE_BYTE: { + uint8_t b; + + r = sd_bus_message_read_basic(m, type, &b); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_unsigned(&v, b); + if (r < 0) + return log_error_errno(r, "Failed to transform byte: %m"); + + break; + } + + case SD_BUS_TYPE_BOOLEAN: { + int b; + + r = sd_bus_message_read_basic(m, type, &b); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_boolean(&v, b); + if (r < 0) + return log_error_errno(r, "Failed to transform boolean: %m"); + + break; + } + + case SD_BUS_TYPE_INT16: { + int16_t b; + + r = sd_bus_message_read_basic(m, type, &b); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_integer(&v, b); + if (r < 0) + return log_error_errno(r, "Failed to transform int16: %m"); + + break; + } + + case SD_BUS_TYPE_UINT16: { + uint16_t b; + + r = sd_bus_message_read_basic(m, type, &b); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_unsigned(&v, b); + if (r < 0) + return log_error_errno(r, "Failed to transform uint16: %m"); + + break; + } + + case SD_BUS_TYPE_INT32: { + int32_t b; + + r = sd_bus_message_read_basic(m, type, &b); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_integer(&v, b); + if (r < 0) + return log_error_errno(r, "Failed to transform int32: %m"); + + break; + } + + case SD_BUS_TYPE_UINT32: { + uint32_t b; + + r = sd_bus_message_read_basic(m, type, &b); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_unsigned(&v, b); + if (r < 0) + return log_error_errno(r, "Failed to transform uint32: %m"); + + break; + } + + case SD_BUS_TYPE_INT64: { + int64_t b; + + r = sd_bus_message_read_basic(m, type, &b); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_integer(&v, b); + if (r < 0) + return log_error_errno(r, "Failed to transform int64: %m"); + + break; + } + + case SD_BUS_TYPE_UINT64: { + uint64_t b; + + r = sd_bus_message_read_basic(m, type, &b); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_unsigned(&v, b); + if (r < 0) + return log_error_errno(r, "Failed to transform uint64: %m"); + + break; + } + + case SD_BUS_TYPE_DOUBLE: { + double d; + + r = sd_bus_message_read_basic(m, type, &d); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_real(&v, d); + if (r < 0) + return log_error_errno(r, "Failed to transform double: %m"); + + break; + } + + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: { + const char *s; + + r = sd_bus_message_read_basic(m, type, &s); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_string(&v, s); + if (r < 0) + return log_error_errno(r, "Failed to transform double: %m"); + + break; + } + + case SD_BUS_TYPE_UNIX_FD: + r = sd_bus_message_read_basic(m, type, NULL); + if (r < 0) + return bus_log_parse_error(r); + + r = json_variant_new_null(&v); + if (r < 0) + return log_error_errno(r, "Failed to transform fd: %m"); + + break; + + case SD_BUS_TYPE_ARRAY: + case SD_BUS_TYPE_VARIANT: + case SD_BUS_TYPE_STRUCT: + r = sd_bus_message_enter_container(m, type, contents); + if (r < 0) + return bus_log_parse_error(r); + + if (type == SD_BUS_TYPE_VARIANT) + r = json_transform_variant(m, contents, &v); + else if (type == SD_BUS_TYPE_ARRAY && contents[0] == '{') + r = json_transform_dict_array(m, &v); + else + r = json_transform_array_or_struct(m, &v); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + break; + + default: + assert_not_reached("Unexpected element type"); + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int json_transform_message(sd_bus_message *m, JsonVariant **ret) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + const char *type; + int r; + + assert(m); + assert(ret); + + assert_se(type = sd_bus_message_get_signature(m, false)); + + r = json_transform_array_or_struct(m, &v); + if (r < 0) + return r; + + r = json_build(ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("type", JSON_BUILD_STRING(type)), + JSON_BUILD_PAIR("data", JSON_BUILD_VARIANT(v)))); + if (r < 0) + return log_oom(); + + return 0; +} + +static void json_dump_with_flags(JsonVariant *v, FILE *f) { + + json_variant_dump(v, + (arg_json == JSON_PRETTY ? JSON_FORMAT_PRETTY : JSON_FORMAT_NEWLINE) | + JSON_FORMAT_COLOR_AUTO, + f, NULL); +} + +static int call(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + int r; + + r = acquire_bus(false, &bus); + if (r < 0) + return r; + + r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], argv[3], argv[4]); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_expect_reply(m, arg_expect_reply); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_auto_start(m, arg_auto_start); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, arg_allow_interactive_authorization); + if (r < 0) + return bus_log_create_error(r); + + if (!isempty(argv[5])) { + char **p; + + p = argv+6; + + r = message_append_cmdline(m, argv[5], &p); + if (r < 0) + return r; + + if (*p) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many parameters for signature."); + } + + if (!arg_expect_reply) { + r = sd_bus_send(bus, m, NULL); + if (r < 0) + return log_error_errno(r, "Failed to send message: %m"); + + return 0; + } + + r = sd_bus_call(bus, m, arg_timeout, &error, &reply); + if (r < 0) + return log_error_errno(r, "Call failed: %s", bus_error_message(&error, r)); + + r = sd_bus_message_is_empty(reply); + if (r < 0) + return bus_log_parse_error(r); + + if (r == 0 && !arg_quiet) { + + if (arg_json != JSON_OFF) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + + if (arg_json != JSON_SHORT) + (void) pager_open(arg_pager_flags); + + r = json_transform_message(reply, &v); + if (r < 0) + return r; + + json_dump_with_flags(v, stdout); + + } else if (arg_verbose) { + (void) pager_open(arg_pager_flags); + + r = bus_message_dump(reply, stdout, 0); + if (r < 0) + return r; + } else { + + fputs(sd_bus_message_get_signature(reply, true), stdout); + fputc(' ', stdout); + + r = format_cmdline(reply, stdout, false); + if (r < 0) + return bus_log_parse_error(r); + + fputc('\n', stdout); + } + } + + return 0; +} + +static int emit_signal(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + r = acquire_bus(false, &bus); + if (r < 0) + return r; + + r = sd_bus_message_new_signal(bus, &m, argv[1], argv[2], argv[3]); + if (r < 0) + return bus_log_create_error(r); + + if (arg_destination) { + r = sd_bus_message_set_destination(m, arg_destination); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_set_auto_start(m, arg_auto_start); + if (r < 0) + return bus_log_create_error(r); + + if (!isempty(argv[4])) { + char **p; + + p = argv+5; + + r = message_append_cmdline(m, argv[4], &p); + if (r < 0) + return r; + + if (*p) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many parameters for signature."); + } + + r = sd_bus_send(bus, m, NULL); + if (r < 0) + return log_error_errno(r, "Failed to send signal: %m"); + + return 0; +} + +static int get_property(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + char **i; + int r; + + r = acquire_bus(false, &bus); + if (r < 0) + return r; + + STRV_FOREACH(i, argv + 4) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *contents = NULL; + char type; + + r = sd_bus_call_method(bus, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Get", &error, &reply, "ss", argv[3], *i); + if (r < 0) + return log_error_errno(r, "Failed to get property %s on interface %s: %s", + *i, argv[3], + bus_error_message(&error, r)); + + r = sd_bus_message_peek_type(reply, &type, &contents); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_enter_container(reply, 'v', contents); + if (r < 0) + return bus_log_parse_error(r); + + if (arg_json != JSON_OFF) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + + if (arg_json != JSON_SHORT) + (void) pager_open(arg_pager_flags); + + r = json_transform_variant(reply, contents, &v); + if (r < 0) + return r; + + json_dump_with_flags(v, stdout); + + } else if (arg_verbose) { + (void) pager_open(arg_pager_flags); + + r = bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_SUBTREE_ONLY); + if (r < 0) + return r; + } else { + fputs(contents, stdout); + fputc(' ', stdout); + + r = format_cmdline(reply, stdout, false); + if (r < 0) + return bus_log_parse_error(r); + + fputc('\n', stdout); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + } + + return 0; +} + +static int set_property(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + char **p; + int r; + + r = acquire_bus(false, &bus); + if (r < 0) + return r; + + r = sd_bus_message_new_method_call(bus, &m, argv[1], argv[2], "org.freedesktop.DBus.Properties", "Set"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "ss", argv[3], argv[4]); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', argv[5]); + if (r < 0) + return bus_log_create_error(r); + + p = argv + 6; + r = message_append_cmdline(m, argv[5], &p); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + if (*p) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Too many parameters for signature."); + + r = sd_bus_call(bus, m, arg_timeout, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to set property %s on interface %s: %s", + argv[4], argv[3], + bus_error_message(&error, r)); + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("busctl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n\n" + "%sIntrospect the D-Bus IPC bus.%s\n" + "\nCommands:\n" + " list List bus names\n" + " status [SERVICE] Show bus service, process or bus owner credentials\n" + " monitor [SERVICE...] Show bus traffic\n" + " capture [SERVICE...] Capture bus traffic as pcap\n" + " tree [SERVICE...] Show object tree of service\n" + " introspect SERVICE OBJECT [INTERFACE]\n" + " call SERVICE OBJECT INTERFACE METHOD [SIGNATURE [ARGUMENT...]]\n" + " Call a method\n" + " emit OBJECT INTERFACE SIGNAL [SIGNATURE [ARGUMENT...]]\n" + " Emit a signal\n" + " get-property SERVICE OBJECT INTERFACE PROPERTY...\n" + " Get property value\n" + " set-property SERVICE OBJECT INTERFACE PROPERTY SIGNATURE ARGUMENT...\n" + " Set property value\n" + " help Show this help\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --no-legend Do not show the headers and footers\n" + " --system Connect to system bus\n" + " --user Connect to user bus\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " --address=ADDRESS Connect to bus specified by address\n" + " --show-machine Show machine ID column in list\n" + " --unique Only show unique names\n" + " --acquired Only show acquired names\n" + " --activatable Only show activatable names\n" + " --match=MATCH Only show matching messages\n" + " --size=SIZE Maximum length of captured packet\n" + " --list Don't show tree, but simple object path list\n" + " -q --quiet Don't show method call reply\n" + " --verbose Show result values in long format\n" + " --json=MODE Output as JSON\n" + " -j Same as --json=pretty on tty, --json=short otherwise\n" + " --expect-reply=BOOL Expect a method call reply\n" + " --auto-start=BOOL Auto-start destination service\n" + " --allow-interactive-authorization=BOOL\n" + " Allow interactive authorization for operation\n" + " --timeout=SECS Maximum time to wait for method call completion\n" + " --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n" + " --watch-bind=BOOL Wait for bus AF_UNIX socket to be bound in the file\n" + " system\n" + " --destination=SERVICE Destination service of a signal\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int verb_help(int argc, char **argv, void *userdata) { + return help(); +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_PAGER, + ARG_NO_LEGEND, + ARG_SYSTEM, + ARG_USER, + ARG_ADDRESS, + ARG_MATCH, + ARG_SHOW_MACHINE, + ARG_UNIQUE, + ARG_ACQUIRED, + ARG_ACTIVATABLE, + ARG_SIZE, + ARG_LIST, + ARG_VERBOSE, + ARG_XML_INTERFACE, + ARG_EXPECT_REPLY, + ARG_AUTO_START, + ARG_ALLOW_INTERACTIVE_AUTHORIZATION, + ARG_TIMEOUT, + ARG_AUGMENT_CREDS, + ARG_WATCH_BIND, + ARG_JSON, + ARG_DESTINATION, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "user", no_argument, NULL, ARG_USER }, + { "address", required_argument, NULL, ARG_ADDRESS }, + { "show-machine", no_argument, NULL, ARG_SHOW_MACHINE }, + { "unique", no_argument, NULL, ARG_UNIQUE }, + { "acquired", no_argument, NULL, ARG_ACQUIRED }, + { "activatable", no_argument, NULL, ARG_ACTIVATABLE }, + { "match", required_argument, NULL, ARG_MATCH }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "size", required_argument, NULL, ARG_SIZE }, + { "list", no_argument, NULL, ARG_LIST }, + { "quiet", no_argument, NULL, 'q' }, + { "verbose", no_argument, NULL, ARG_VERBOSE }, + { "xml-interface", no_argument, NULL, ARG_XML_INTERFACE }, + { "expect-reply", required_argument, NULL, ARG_EXPECT_REPLY }, + { "auto-start", required_argument, NULL, ARG_AUTO_START }, + { "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION }, + { "timeout", required_argument, NULL, ARG_TIMEOUT }, + { "augment-creds", required_argument, NULL, ARG_AUGMENT_CREDS }, + { "watch-bind", required_argument, NULL, ARG_WATCH_BIND }, + { "json", required_argument, NULL, ARG_JSON }, + { "destination", required_argument, NULL, ARG_DESTINATION }, + {}, + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hH:M:qj", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_NO_LEGEND: + arg_legend = false; + break; + + case ARG_USER: + arg_user = true; + break; + + case ARG_SYSTEM: + arg_user = false; + break; + + case ARG_ADDRESS: + arg_address = optarg; + break; + + case ARG_SHOW_MACHINE: + arg_show_machine = true; + break; + + case ARG_UNIQUE: + arg_unique = true; + break; + + case ARG_ACQUIRED: + arg_acquired = true; + break; + + case ARG_ACTIVATABLE: + arg_activatable = true; + break; + + case ARG_MATCH: + if (strv_extend(&arg_matches, optarg) < 0) + return log_oom(); + break; + + case ARG_SIZE: { + uint64_t sz; + + r = parse_size(optarg, 1024, &sz); + if (r < 0) + return log_error_errno(r, "Failed to parse size '%s': %m", optarg); + + if ((uint64_t) (size_t) sz != sz) + return log_error_errno(SYNTHETIC_ERRNO(E2BIG), + "Size out of range."); + + arg_snaplen = (size_t) sz; + break; + } + + case ARG_LIST: + arg_list = true; + break; + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case 'q': + arg_quiet = true; + break; + + case ARG_VERBOSE: + arg_verbose = true; + break; + + case ARG_XML_INTERFACE: + arg_xml_interface = true; + break; + + case ARG_EXPECT_REPLY: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --expect-reply= parameter '%s': %m", optarg); + + arg_expect_reply = r; + break; + + case ARG_AUTO_START: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --auto-start= parameter '%s': %m", optarg); + + arg_auto_start = r; + break; + + case ARG_ALLOW_INTERACTIVE_AUTHORIZATION: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --allow-interactive-authorization= parameter '%s': %m", optarg); + + arg_allow_interactive_authorization = r; + break; + + case ARG_TIMEOUT: + r = parse_sec(optarg, &arg_timeout); + if (r < 0) + return log_error_errno(r, "Failed to parse --timeout= parameter '%s': %m", optarg); + + break; + + case ARG_AUGMENT_CREDS: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --augment-creds= parameter '%s': %m", optarg); + + arg_augment_creds = r; + break; + + case ARG_WATCH_BIND: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --watch-bind= parameter '%s': %m", optarg); + + arg_watch_bind = r; + break; + + case 'j': + if (on_tty()) + arg_json = JSON_PRETTY; + else + arg_json = JSON_SHORT; + break; + + case ARG_JSON: + if (streq(optarg, "short")) + arg_json = JSON_SHORT; + else if (streq(optarg, "pretty")) + arg_json = JSON_PRETTY; + else if (streq(optarg, "help")) { + fputs("short\n" + "pretty\n", stdout); + return 0; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown JSON out mode: %s", + optarg); + + break; + + case ARG_DESTINATION: + arg_destination = optarg; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int busctl_main(int argc, char *argv[]) { + + static const Verb verbs[] = { + { "list", VERB_ANY, 1, VERB_DEFAULT, list_bus_names }, + { "status", VERB_ANY, 2, 0, status }, + { "monitor", VERB_ANY, VERB_ANY, 0, verb_monitor }, + { "capture", VERB_ANY, VERB_ANY, 0, verb_capture }, + { "tree", VERB_ANY, VERB_ANY, 0, tree }, + { "introspect", 3, 4, 0, introspect }, + { "call", 5, VERB_ANY, 0, call }, + { "emit", 4, VERB_ANY, 0, emit_signal }, + { "get-property", 5, VERB_ANY, 0, get_property }, + { "set-property", 6, VERB_ANY, 0, set_property }, + { "help", VERB_ANY, VERB_ANY, 0, verb_help }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static int run(int argc, char *argv[]) { + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + return busctl_main(argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c new file mode 100644 index 00000000..b55d7299 --- /dev/null +++ b/src/cgls/cgls.c @@ -0,0 +1,302 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-util.h" +#include "cgroup-show.h" +#include "cgroup-util.h" +#include "fileio.h" +#include "log.h" +#include "main-func.h" +#include "output-mode.h" +#include "pager.h" +#include "path-util.h" +#include "pretty-print.h" +#include "strv.h" +#include "unit-name.h" +#include "util.h" + +static PagerFlags arg_pager_flags = 0; +static bool arg_kernel_threads = false; +static bool arg_all = false; + +static enum { + SHOW_UNIT_NONE, + SHOW_UNIT_SYSTEM, + SHOW_UNIT_USER, +} arg_show_unit = SHOW_UNIT_NONE; +static char **arg_names = NULL; + +static int arg_full = -1; +static const char* arg_machine = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_names, freep); /* don't free the strings */ + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-cgls", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [CGROUP...]\n\n" + "Recursively show control group contents.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " -a --all Show all groups, including empty\n" + " -u --unit Show the subtrees of specified system units\n" + " --user-unit Show the subtrees of specified user units\n" + " -l --full Do not ellipsize output\n" + " -k Include kernel threads in output\n" + " -M --machine= Show container\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_NO_PAGER = 0x100, + ARG_VERSION, + ARG_USER_UNIT, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "all", no_argument, NULL, 'a' }, + { "full", no_argument, NULL, 'l' }, + { "machine", required_argument, NULL, 'M' }, + { "unit", optional_argument, NULL, 'u' }, + { "user-unit", optional_argument, NULL, ARG_USER_UNIT }, + {} + }; + + int c; + + assert(argc >= 1); + assert(argv); + + while ((c = getopt_long(argc, argv, "-hkalM:u::", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case 'a': + arg_all = true; + break; + + case 'u': + arg_show_unit = SHOW_UNIT_SYSTEM; + if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */ + return log_oom(); + break; + + case ARG_USER_UNIT: + arg_show_unit = SHOW_UNIT_USER; + if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */ + return log_oom(); + break; + + case 1: + /* positional argument */ + if (strv_push(&arg_names, optarg) < 0) + return log_oom(); + break; + + case 'l': + arg_full = true; + break; + + case 'k': + arg_kernel_threads = true; + break; + + case 'M': + arg_machine = optarg; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_machine && arg_show_unit != SHOW_UNIT_NONE) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot combine --unit or --user-unit with --machine=."); + + return 1; +} + +static void show_cg_info(const char *controller, const char *path) { + + if (cg_all_unified() == 0 && controller && !streq(controller, SYSTEMD_CGROUP_CONTROLLER)) + printf("Controller %s; ", controller); + + printf("Control group %s:\n", empty_to_root(path)); + fflush(stdout); +} + +static int run(int argc, char *argv[]) { + int r, output_flags; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = pager_open(arg_pager_flags); + if (r > 0 && arg_full < 0) + arg_full = true; + + output_flags = + arg_all * OUTPUT_SHOW_ALL | + (arg_full > 0) * OUTPUT_FULL_WIDTH | + arg_kernel_threads * OUTPUT_KERNEL_THREADS; + + if (arg_names) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *root = NULL; + char **name; + + STRV_FOREACH(name, arg_names) { + int q; + + if (arg_show_unit != SHOW_UNIT_NONE) { + /* Command line arguments are unit names */ + _cleanup_free_ char *cgroup = NULL; + + if (!bus) { + /* Connect to the bus only if necessary */ + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, + arg_show_unit == SHOW_UNIT_USER, + &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + } + + q = show_cgroup_get_unit_path_and_warn(bus, *name, &cgroup); + if (q < 0) + goto failed; + + if (isempty(cgroup)) { + log_warning("Unit %s not found.", *name); + q = -ENOENT; + goto failed; + } + + printf("Unit %s (%s):\n", *name, cgroup); + fflush(stdout); + + q = show_cgroup_by_path(cgroup, NULL, 0, output_flags); + + } else if (path_startswith(*name, "/sys/fs/cgroup")) { + + printf("Directory %s:\n", *name); + fflush(stdout); + + q = show_cgroup_by_path(*name, NULL, 0, output_flags); + } else { + _cleanup_free_ char *c = NULL, *p = NULL, *j = NULL; + const char *controller, *path; + + if (!root) { + /* Query root only if needed, treat error as fatal */ + r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root); + if (r < 0) + return log_error_errno(r, "Failed to list cgroup tree: %m"); + } + + q = cg_split_spec(*name, &c, &p); + if (q < 0) { + log_error_errno(q, "Failed to split argument %s: %m", *name); + goto failed; + } + + controller = c ?: SYSTEMD_CGROUP_CONTROLLER; + if (p) { + j = path_join(root, p); + if (!j) + return log_oom(); + + path_simplify(j, false); + path = j; + } else + path = root; + + show_cg_info(controller, path); + + q = show_cgroup(controller, path, NULL, 0, output_flags); + } + + failed: + if (q < 0 && r >= 0) + r = q; + } + + } else { + bool done = false; + + if (!arg_machine) { + _cleanup_free_ char *cwd = NULL; + + r = safe_getcwd(&cwd); + if (r < 0) + return log_error_errno(r, "Cannot determine current working directory: %m"); + + if (path_startswith(cwd, "/sys/fs/cgroup")) { + printf("Working directory %s:\n", cwd); + fflush(stdout); + + r = show_cgroup_by_path(cwd, NULL, 0, output_flags); + done = true; + } + } + + if (!done) { + _cleanup_free_ char *root = NULL; + + r = show_cgroup_get_path_and_warn(arg_machine, NULL, &root); + if (r < 0) + return log_error_errno(r, "Failed to list cgroup tree: %m"); + + show_cg_info(SYSTEMD_CGROUP_CONTROLLER, root); + + printf("-.slice\n"); + r = show_cgroup(SYSTEMD_CGROUP_CONTROLLER, root, NULL, 0, output_flags); + } + } + if (r < 0) + return log_error_errno(r, "Failed to list cgroup tree: %m"); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/cgroups-agent/cgroups-agent.c b/src/cgroups-agent/cgroups-agent.c new file mode 100644 index 00000000..ace7d6c5 --- /dev/null +++ b/src/cgroups-agent/cgroups-agent.c @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "fd-util.h" +#include "log.h" +#include "socket-util.h" + +int main(int argc, char *argv[]) { + + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/cgroups-agent", + }; + + _cleanup_close_ int fd = -1; + ssize_t n; + size_t l; + + if (argc != 2) { + log_error("Incorrect number of arguments."); + return EXIT_FAILURE; + } + + log_setup_service(); + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) { + log_debug_errno(errno, "Failed to allocate socket: %m"); + return EXIT_FAILURE; + } + + l = strlen(argv[1]); + + n = sendto(fd, argv[1], l, 0, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (n < 0) { + log_debug_errno(errno, "Failed to send cgroups agent message: %m"); + return EXIT_FAILURE; + } + + if ((size_t) n != l) { + log_debug("Datagram size mismatch"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/cgtop/cgtop.c b/src/cgtop/cgtop.c new file mode 100644 index 00000000..de25aaae --- /dev/null +++ b/src/cgtop/cgtop.c @@ -0,0 +1,1103 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "cgroup-show.h" +#include "cgroup-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "hashmap.h" +#include "main-func.h" +#include "missing_sched.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "process-util.h" +#include "procfs-util.h" +#include "sort-util.h" +#include "stdio-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "unit-name.h" +#include "virt.h" + +typedef struct Group { + char *path; + + bool n_tasks_valid:1; + bool cpu_valid:1; + bool memory_valid:1; + bool io_valid:1; + + uint64_t n_tasks; + + unsigned cpu_iteration; + nsec_t cpu_usage; + nsec_t cpu_timestamp; + double cpu_fraction; + + uint64_t memory; + + unsigned io_iteration; + uint64_t io_input, io_output; + nsec_t io_timestamp; + uint64_t io_input_bps, io_output_bps; +} Group; + +static unsigned arg_depth = 3; +static unsigned arg_iterations = (unsigned) -1; +static bool arg_batch = false; +static bool arg_raw = false; +static usec_t arg_delay = 1*USEC_PER_SEC; +static char* arg_machine = NULL; +static char* arg_root = NULL; +static bool arg_recursive = true; +static bool arg_recursive_unset = false; + +static enum { + COUNT_PIDS, + COUNT_USERSPACE_PROCESSES, + COUNT_ALL_PROCESSES, +} arg_count = COUNT_PIDS; + +static enum { + ORDER_PATH, + ORDER_TASKS, + ORDER_CPU, + ORDER_MEMORY, + ORDER_IO, +} arg_order = ORDER_CPU; + +static enum { + CPU_PERCENT, + CPU_TIME, +} arg_cpu_type = CPU_PERCENT; + +static Group *group_free(Group *g) { + if (!g) + return NULL; + + free(g->path); + return mfree(g); +} + +static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, uint64_t t) { + if (!is_valid) + return "-"; + if (arg_raw) { + snprintf(buf, l, "%" PRIu64, t); + return buf; + } + return format_bytes(buf, l, t); +} + +static bool is_root_cgroup(const char *path) { + + /* Returns true if the specified path belongs to the root cgroup. The root cgroup is special on cgroup v2 as it + * carries only very few attributes in order not to export multiple truth about system state as most + * information is available elsewhere in /proc anyway. We need to be able to deal with that, and need to get + * our data from different sources in that case. + * + * There's one extra complication in all of this, though 😣: if the path to the cgroup indicates we are in the + * root cgroup this might actually not be the case, because cgroup namespacing might be in effect + * (CLONE_NEWCGROUP). Since there's no nice way to distinguish a real cgroup root from a fake namespaced one we + * do an explicit container check here, under the assumption that CLONE_NEWCGROUP is generally used when + * container managers are used too. + * + * Note that checking for a container environment is kinda ugly, since in theory people could use cgtop from + * inside a container where cgroup namespacing is turned off to watch the host system. However, that's mostly a + * theoretic usecase, and if people actually try all they'll lose is accounting for the top-level cgroup. Which + * isn't too bad. */ + + if (detect_container() > 0) + return false; + + return empty_or_root(path); +} + +static int process( + const char *controller, + const char *path, + Hashmap *a, + Hashmap *b, + unsigned iteration, + Group **ret) { + + Group *g; + int r, all_unified; + + assert(controller); + assert(path); + assert(a); + + all_unified = cg_all_unified(); + if (all_unified < 0) + return all_unified; + + g = hashmap_get(a, path); + if (!g) { + g = hashmap_get(b, path); + if (!g) { + g = new0(Group, 1); + if (!g) + return -ENOMEM; + + g->path = strdup(path); + if (!g->path) { + group_free(g); + return -ENOMEM; + } + + r = hashmap_put(a, g->path, g); + if (r < 0) { + group_free(g); + return r; + } + } else { + r = hashmap_move_one(a, b, path); + if (r < 0) + return r; + + g->cpu_valid = g->memory_valid = g->io_valid = g->n_tasks_valid = false; + } + } + + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && + IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES)) { + _cleanup_fclose_ FILE *f = NULL; + pid_t pid; + + r = cg_enumerate_processes(controller, path, &f); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + g->n_tasks = 0; + while (cg_read_pid(f, &pid) > 0) { + + if (arg_count == COUNT_USERSPACE_PROCESSES && is_kernel_thread(pid) > 0) + continue; + + g->n_tasks++; + } + + if (g->n_tasks > 0) + g->n_tasks_valid = true; + + } else if (streq(controller, "pids") && arg_count == COUNT_PIDS) { + + if (is_root_cgroup(path)) { + r = procfs_tasks_get_current(&g->n_tasks); + if (r < 0) + return r; + } else { + _cleanup_free_ char *p = NULL, *v = NULL; + + r = cg_get_path(controller, path, "pids.current", &p); + if (r < 0) + return r; + + r = read_one_line_file(p, &v); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + r = safe_atou64(v, &g->n_tasks); + if (r < 0) + return r; + } + + if (g->n_tasks > 0) + g->n_tasks_valid = true; + + } else if (streq(controller, "memory")) { + + if (is_root_cgroup(path)) { + r = procfs_memory_get_used(&g->memory); + if (r < 0) + return r; + } else { + _cleanup_free_ char *p = NULL, *v = NULL; + + if (all_unified) + r = cg_get_path(controller, path, "memory.current", &p); + else + r = cg_get_path(controller, path, "memory.usage_in_bytes", &p); + if (r < 0) + return r; + + r = read_one_line_file(p, &v); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + r = safe_atou64(v, &g->memory); + if (r < 0) + return r; + } + + if (g->memory > 0) + g->memory_valid = true; + + } else if ((streq(controller, "io") && all_unified) || + (streq(controller, "blkio") && !all_unified)) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *p = NULL; + uint64_t wr = 0, rd = 0; + nsec_t timestamp; + + r = cg_get_path(controller, path, all_unified ? "io.stat" : "blkio.io_service_bytes", &p); + if (r < 0) + return r; + + f = fopen(p, "re"); + if (!f) { + if (errno == ENOENT) + return 0; + return -errno; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + uint64_t k, *q; + char *l; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + /* Trim and skip the device */ + l = strstrip(line); + l += strcspn(l, WHITESPACE); + l += strspn(l, WHITESPACE); + + if (all_unified) { + while (!isempty(l)) { + if (sscanf(l, "rbytes=%" SCNu64, &k)) + rd += k; + else if (sscanf(l, "wbytes=%" SCNu64, &k)) + wr += k; + + l += strcspn(l, WHITESPACE); + l += strspn(l, WHITESPACE); + } + } else { + if (first_word(l, "Read")) { + l += 4; + q = &rd; + } else if (first_word(l, "Write")) { + l += 5; + q = ≀ + } else + continue; + + l += strspn(l, WHITESPACE); + r = safe_atou64(l, &k); + if (r < 0) + continue; + + *q += k; + } + } + + timestamp = now_nsec(CLOCK_MONOTONIC); + + if (g->io_iteration == iteration - 1) { + uint64_t x, yr, yw; + + x = (uint64_t) (timestamp - g->io_timestamp); + if (x < 1) + x = 1; + + if (rd > g->io_input) + yr = rd - g->io_input; + else + yr = 0; + + if (wr > g->io_output) + yw = wr - g->io_output; + else + yw = 0; + + if (yr > 0 || yw > 0) { + g->io_input_bps = (yr * 1000000000ULL) / x; + g->io_output_bps = (yw * 1000000000ULL) / x; + g->io_valid = true; + } + } + + g->io_input = rd; + g->io_output = wr; + g->io_timestamp = timestamp; + g->io_iteration = iteration; + } else if (STR_IN_SET(controller, "cpu", "cpuacct") || cpu_accounting_is_cheap()) { + _cleanup_free_ char *p = NULL, *v = NULL; + uint64_t new_usage; + nsec_t timestamp; + + if (is_root_cgroup(path)) { + r = procfs_cpu_get_usage(&new_usage); + if (r < 0) + return r; + } else if (all_unified) { + _cleanup_free_ char *val = NULL; + + if (!streq(controller, "cpu")) + return 0; + + r = cg_get_keyed_attribute("cpu", path, "cpu.stat", STRV_MAKE("usage_usec"), &val); + if (IN_SET(r, -ENOENT, -ENXIO)) + return 0; + if (r < 0) + return r; + + r = safe_atou64(val, &new_usage); + if (r < 0) + return r; + + new_usage *= NSEC_PER_USEC; + } else { + if (!streq(controller, "cpuacct")) + return 0; + + r = cg_get_path(controller, path, "cpuacct.usage", &p); + if (r < 0) + return r; + + r = read_one_line_file(p, &v); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + r = safe_atou64(v, &new_usage); + if (r < 0) + return r; + } + + timestamp = now_nsec(CLOCK_MONOTONIC); + + if (g->cpu_iteration == iteration - 1 && + (nsec_t) new_usage > g->cpu_usage) { + + nsec_t x, y; + + x = timestamp - g->cpu_timestamp; + if (x < 1) + x = 1; + + y = (nsec_t) new_usage - g->cpu_usage; + g->cpu_fraction = (double) y / (double) x; + g->cpu_valid = true; + } + + g->cpu_usage = (nsec_t) new_usage; + g->cpu_timestamp = timestamp; + g->cpu_iteration = iteration; + + } + + if (ret) + *ret = g; + + return 0; +} + +static int refresh_one( + const char *controller, + const char *path, + Hashmap *a, + Hashmap *b, + unsigned iteration, + unsigned depth, + Group **ret) { + + _cleanup_closedir_ DIR *d = NULL; + Group *ours = NULL; + int r; + + assert(controller); + assert(path); + assert(a); + + if (depth > arg_depth) + return 0; + + r = process(controller, path, a, b, iteration, &ours); + if (r < 0) + return r; + + r = cg_enumerate_subgroups(controller, path, &d); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *fn = NULL, *p = NULL; + Group *child = NULL; + + r = cg_read_subgroup(d, &fn); + if (r < 0) + return r; + if (r == 0) + break; + + p = path_join(path, fn); + if (!p) + return -ENOMEM; + + path_simplify(p, false); + + r = refresh_one(controller, p, a, b, iteration, depth + 1, &child); + if (r < 0) + return r; + + if (arg_recursive && + IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES) && + child && + child->n_tasks_valid && + streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { + + /* Recursively sum up processes */ + + if (ours->n_tasks_valid) + ours->n_tasks += child->n_tasks; + else { + ours->n_tasks = child->n_tasks; + ours->n_tasks_valid = true; + } + } + } + + if (ret) + *ret = ours; + + return 1; +} + +static int refresh(const char *root, Hashmap *a, Hashmap *b, unsigned iteration) { + const char *c; + int r; + + FOREACH_STRING(c, SYSTEMD_CGROUP_CONTROLLER, "cpu", "cpuacct", "memory", "io", "blkio", "pids") { + r = refresh_one(c, root, a, b, iteration, 0, NULL); + if (r < 0) + return r; + } + + return 0; +} + +static int group_compare(Group * const *a, Group * const *b) { + const Group *x = *a, *y = *b; + int r; + + if (arg_order != ORDER_TASKS || arg_recursive) { + /* Let's make sure that the parent is always before + * the child. Except when ordering by tasks and + * recursive summing is off, since that is actually + * not accumulative for all children. */ + + if (path_startswith(empty_to_root(y->path), empty_to_root(x->path))) + return -1; + if (path_startswith(empty_to_root(x->path), empty_to_root(y->path))) + return 1; + } + + switch (arg_order) { + + case ORDER_PATH: + break; + + case ORDER_CPU: + if (arg_cpu_type == CPU_PERCENT) { + if (x->cpu_valid && y->cpu_valid) { + r = CMP(y->cpu_fraction, x->cpu_fraction); + if (r != 0) + return r; + } else if (x->cpu_valid) + return -1; + else if (y->cpu_valid) + return 1; + } else { + r = CMP(y->cpu_usage, x->cpu_usage); + if (r != 0) + return r; + } + + break; + + case ORDER_TASKS: + if (x->n_tasks_valid && y->n_tasks_valid) { + r = CMP(y->n_tasks, x->n_tasks); + if (r != 0) + return r; + } else if (x->n_tasks_valid) + return -1; + else if (y->n_tasks_valid) + return 1; + + break; + + case ORDER_MEMORY: + if (x->memory_valid && y->memory_valid) { + r = CMP(y->memory, x->memory); + if (r != 0) + return r; + } else if (x->memory_valid) + return -1; + else if (y->memory_valid) + return 1; + + break; + + case ORDER_IO: + if (x->io_valid && y->io_valid) { + r = CMP(y->io_input_bps + y->io_output_bps, x->io_input_bps + x->io_output_bps); + if (r != 0) + return r; + } else if (x->io_valid) + return -1; + else if (y->io_valid) + return 1; + } + + return path_compare(x->path, y->path); +} + +static void display(Hashmap *a) { + Iterator i; + Group *g; + Group **array; + signed path_columns; + unsigned rows, n = 0, j, maxtcpu = 0, maxtpath = 3; /* 3 for ellipsize() to work properly */ + char buffer[MAX3(21, FORMAT_BYTES_MAX, FORMAT_TIMESPAN_MAX)]; + + assert(a); + + if (!terminal_is_dumb()) + fputs(ANSI_HOME_CLEAR, stdout); + + array = newa(Group*, hashmap_size(a)); + + HASHMAP_FOREACH(g, a, i) + if (g->n_tasks_valid || g->cpu_valid || g->memory_valid || g->io_valid) + array[n++] = g; + + typesafe_qsort(array, n, group_compare); + + /* Find the longest names in one run */ + for (j = 0; j < n; j++) { + unsigned cputlen, pathtlen; + + format_timespan(buffer, sizeof(buffer), (usec_t) (array[j]->cpu_usage / NSEC_PER_USEC), 0); + cputlen = strlen(buffer); + maxtcpu = MAX(maxtcpu, cputlen); + + pathtlen = strlen(array[j]->path); + maxtpath = MAX(maxtpath, pathtlen); + } + + if (arg_cpu_type == CPU_PERCENT) + xsprintf(buffer, "%6s", "%CPU"); + else + xsprintf(buffer, "%*s", maxtcpu, "CPU Time"); + + rows = lines(); + if (rows <= 10) + rows = 10; + + if (on_tty()) { + const char *on, *off; + + path_columns = columns() - 36 - strlen(buffer); + if (path_columns < 10) + path_columns = 10; + + on = ansi_highlight_underline(); + off = ansi_underline(); + + printf("%s%s%-*s%s %s%7s%s %s%s%s %s%8s%s %s%8s%s %s%8s%s%s\n", + ansi_underline(), + arg_order == ORDER_PATH ? on : "", path_columns, "Control Group", + arg_order == ORDER_PATH ? off : "", + arg_order == ORDER_TASKS ? on : "", arg_count == COUNT_PIDS ? "Tasks" : arg_count == COUNT_USERSPACE_PROCESSES ? "Procs" : "Proc+", + arg_order == ORDER_TASKS ? off : "", + arg_order == ORDER_CPU ? on : "", buffer, + arg_order == ORDER_CPU ? off : "", + arg_order == ORDER_MEMORY ? on : "", "Memory", + arg_order == ORDER_MEMORY ? off : "", + arg_order == ORDER_IO ? on : "", "Input/s", + arg_order == ORDER_IO ? off : "", + arg_order == ORDER_IO ? on : "", "Output/s", + arg_order == ORDER_IO ? off : "", + ansi_normal()); + } else + path_columns = maxtpath; + + for (j = 0; j < n; j++) { + _cleanup_free_ char *ellipsized = NULL; + const char *path; + + if (on_tty() && j + 6 > rows) + break; + + g = array[j]; + + path = empty_to_root(g->path); + ellipsized = ellipsize(path, path_columns, 33); + printf("%-*s", path_columns, ellipsized ?: path); + + if (g->n_tasks_valid) + printf(" %7" PRIu64, g->n_tasks); + else + fputs(" -", stdout); + + if (arg_cpu_type == CPU_PERCENT) { + if (g->cpu_valid) + printf(" %6.1f", g->cpu_fraction*100); + else + fputs(" -", stdout); + } else + printf(" %*s", maxtcpu, format_timespan(buffer, sizeof(buffer), (usec_t) (g->cpu_usage / NSEC_PER_USEC), 0)); + + printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->memory_valid, g->memory)); + printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_input_bps)); + printf(" %8s", maybe_format_bytes(buffer, sizeof(buffer), g->io_valid, g->io_output_bps)); + + putchar('\n'); + } +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-cgtop", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [CGROUP]\n\n" + "Show top control groups by their resource usage.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -p --order=path Order by path\n" + " -t --order=tasks Order by number of tasks/processes\n" + " -c --order=cpu Order by CPU load (default)\n" + " -m --order=memory Order by memory load\n" + " -i --order=io Order by IO load\n" + " -r --raw Provide raw (not human-readable) numbers\n" + " --cpu=percentage Show CPU usage as percentage (default)\n" + " --cpu=time Show CPU usage as time\n" + " -P Count userspace processes instead of tasks (excl. kernel)\n" + " -k Count all processes instead of tasks (incl. kernel)\n" + " --recursive=BOOL Sum up process count recursively\n" + " -d --delay=DELAY Delay between updates\n" + " -n --iterations=N Run for N iterations before exiting\n" + " -1 Shortcut for --iterations=1\n" + " -b --batch Run in batch mode, accepting no input\n" + " --depth=DEPTH Maximum traversal depth (default: %u)\n" + " -M --machine= Show container\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , arg_depth + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_DEPTH, + ARG_CPU_TYPE, + ARG_ORDER, + ARG_RECURSIVE, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "delay", required_argument, NULL, 'd' }, + { "iterations", required_argument, NULL, 'n' }, + { "batch", no_argument, NULL, 'b' }, + { "raw", no_argument, NULL, 'r' }, + { "depth", required_argument, NULL, ARG_DEPTH }, + { "cpu", optional_argument, NULL, ARG_CPU_TYPE }, + { "order", required_argument, NULL, ARG_ORDER }, + { "recursive", required_argument, NULL, ARG_RECURSIVE }, + { "machine", required_argument, NULL, 'M' }, + {} + }; + + int c, r; + + assert(argc >= 1); + assert(argv); + + while ((c = getopt_long(argc, argv, "hptcmin:brd:kPM:1", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_CPU_TYPE: + if (optarg) { + if (streq(optarg, "time")) + arg_cpu_type = CPU_TIME; + else if (streq(optarg, "percentage")) + arg_cpu_type = CPU_PERCENT; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown argument to --cpu=: %s", + optarg); + } else + arg_cpu_type = CPU_TIME; + + break; + + case ARG_DEPTH: + r = safe_atou(optarg, &arg_depth); + if (r < 0) + return log_error_errno(r, "Failed to parse depth parameter '%s': %m", optarg); + + break; + + case 'd': + r = parse_sec(optarg, &arg_delay); + if (r < 0) + return log_error_errno(r, "Failed to parse delay parameter '%s': %m", optarg); + if (arg_delay <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid delay parameter '%s'", + optarg); + + break; + + case 'n': + r = safe_atou(optarg, &arg_iterations); + if (r < 0) + return log_error_errno(r, "Failed to parse iterations parameter '%s': %m", optarg); + + break; + + case '1': + arg_iterations = 1; + break; + + case 'b': + arg_batch = true; + break; + + case 'r': + arg_raw = true; + break; + + case 'p': + arg_order = ORDER_PATH; + break; + + case 't': + arg_order = ORDER_TASKS; + break; + + case 'c': + arg_order = ORDER_CPU; + break; + + case 'm': + arg_order = ORDER_MEMORY; + break; + + case 'i': + arg_order = ORDER_IO; + break; + + case ARG_ORDER: + if (streq(optarg, "path")) + arg_order = ORDER_PATH; + else if (streq(optarg, "tasks")) + arg_order = ORDER_TASKS; + else if (streq(optarg, "cpu")) + arg_order = ORDER_CPU; + else if (streq(optarg, "memory")) + arg_order = ORDER_MEMORY; + else if (streq(optarg, "io")) + arg_order = ORDER_IO; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid argument to --order=: %s", + optarg); + break; + + case 'k': + arg_count = COUNT_ALL_PROCESSES; + break; + + case 'P': + arg_count = COUNT_USERSPACE_PROCESSES; + break; + + case ARG_RECURSIVE: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --recursive= argument '%s': %m", optarg); + + arg_recursive = r; + arg_recursive_unset = r == 0; + break; + + case 'M': + arg_machine = optarg; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind == argc - 1) + arg_root = argv[optind]; + else if (optind < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many arguments."); + + return 1; +} + +static const char* counting_what(void) { + if (arg_count == COUNT_PIDS) + return "tasks"; + else if (arg_count == COUNT_ALL_PROCESSES) + return "all processes (incl. kernel)"; + else + return "userspace processes (excl. kernel)"; +} + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(group_hash_ops, char, path_hash_func, path_compare, Group, group_free); + +static int run(int argc, char *argv[]) { + _cleanup_hashmap_free_ Hashmap *a = NULL, *b = NULL; + unsigned iteration = 0; + usec_t last_refresh = 0; + bool quit = false, immediate_refresh = false; + _cleanup_free_ char *root = NULL; + CGroupMask mask; + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = cg_mask_supported(&mask); + if (r < 0) + return log_error_errno(r, "Failed to determine supported controllers: %m"); + + arg_count = (mask & CGROUP_MASK_PIDS) ? COUNT_PIDS : COUNT_USERSPACE_PROCESSES; + + if (arg_recursive_unset && arg_count == COUNT_PIDS) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k."); + + r = show_cgroup_get_path_and_warn(arg_machine, arg_root, &root); + if (r < 0) + return log_error_errno(r, "Failed to get root control group path: %m"); + log_debug("CGroup path: %s", root); + + a = hashmap_new(&group_hash_ops); + b = hashmap_new(&group_hash_ops); + if (!a || !b) + return log_oom(); + + signal(SIGWINCH, columns_lines_cache_reset); + + if (arg_iterations == (unsigned) -1) + arg_iterations = on_tty() ? 0 : 1; + + while (!quit) { + usec_t t; + char key; + char h[FORMAT_TIMESPAN_MAX]; + + t = now(CLOCK_MONOTONIC); + + if (t >= last_refresh + arg_delay || immediate_refresh) { + + r = refresh(root, a, b, iteration++); + if (r < 0) + return log_error_errno(r, "Failed to refresh: %m"); + + hashmap_clear(b); + SWAP_TWO(a, b); + + last_refresh = t; + immediate_refresh = false; + } + + display(b); + + if (arg_iterations && iteration >= arg_iterations) + break; + + if (!on_tty()) /* non-TTY: Empty newline as delimiter between polls */ + fputs("\n", stdout); + fflush(stdout); + + if (arg_batch) + (void) usleep(last_refresh + arg_delay - t); + else { + r = read_one_char(stdin, &key, last_refresh + arg_delay - t, NULL); + if (r == -ETIMEDOUT) + continue; + if (r < 0) + return log_error_errno(r, "Couldn't read key: %m"); + } + + if (on_tty()) { /* TTY: Clear any user keystroke */ + fputs("\r \r", stdout); + fflush(stdout); + } + + if (arg_batch) + continue; + + switch (key) { + + case ' ': + immediate_refresh = true; + break; + + case 'q': + quit = true; + break; + + case 'p': + arg_order = ORDER_PATH; + break; + + case 't': + arg_order = ORDER_TASKS; + break; + + case 'c': + arg_order = ORDER_CPU; + break; + + case 'm': + arg_order = ORDER_MEMORY; + break; + + case 'i': + arg_order = ORDER_IO; + break; + + case '%': + arg_cpu_type = arg_cpu_type == CPU_TIME ? CPU_PERCENT : CPU_TIME; + break; + + case 'k': + arg_count = arg_count != COUNT_ALL_PROCESSES ? COUNT_ALL_PROCESSES : COUNT_PIDS; + fprintf(stdout, "\nCounting: %s.", counting_what()); + fflush(stdout); + sleep(1); + break; + + case 'P': + arg_count = arg_count != COUNT_USERSPACE_PROCESSES ? COUNT_USERSPACE_PROCESSES : COUNT_PIDS; + fprintf(stdout, "\nCounting: %s.", counting_what()); + fflush(stdout); + sleep(1); + break; + + case 'r': + if (arg_count == COUNT_PIDS) + fprintf(stdout, "\n\aCannot toggle recursive counting, not available in task counting mode."); + else { + arg_recursive = !arg_recursive; + fprintf(stdout, "\nRecursive process counting: %s", yes_no(arg_recursive)); + } + fflush(stdout); + sleep(1); + break; + + case '+': + if (arg_delay < USEC_PER_SEC) + arg_delay += USEC_PER_MSEC*250; + else + arg_delay += USEC_PER_SEC; + + fprintf(stdout, "\nIncreased delay to %s.", format_timespan(h, sizeof(h), arg_delay, 0)); + fflush(stdout); + sleep(1); + break; + + case '-': + if (arg_delay <= USEC_PER_MSEC*500) + arg_delay = USEC_PER_MSEC*250; + else if (arg_delay < USEC_PER_MSEC*1250) + arg_delay -= USEC_PER_MSEC*250; + else + arg_delay -= USEC_PER_SEC; + + fprintf(stdout, "\nDecreased delay to %s.", format_timespan(h, sizeof(h), arg_delay, 0)); + fflush(stdout); + sleep(1); + break; + + case '?': + case 'h': + +#define ON ANSI_HIGHLIGHT +#define OFF ANSI_NORMAL + + fprintf(stdout, + "\t<" ON "p" OFF "> By path; <" ON "t" OFF "> By tasks/procs; <" ON "c" OFF "> By CPU; <" ON "m" OFF "> By memory; <" ON "i" OFF "> By I/O\n" + "\t<" ON "+" OFF "> Inc. delay; <" ON "-" OFF "> Dec. delay; <" ON "%%" OFF "> Toggle time; <" ON "SPACE" OFF "> Refresh\n" + "\t<" ON "P" OFF "> Toggle count userspace processes; <" ON "k" OFF "> Toggle count all processes\n" + "\t<" ON "r" OFF "> Count processes recursively; <" ON "q" OFF "> Quit"); + fflush(stdout); + sleep(3); + break; + + default: + if (key < ' ') + fprintf(stdout, "\nUnknown key '\\x%x'. Ignoring.", key); + else + fprintf(stdout, "\nUnknown key '%c'. Ignoring.", key); + fflush(stdout); + sleep(1); + break; + } + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/core/all-units.h b/src/core/all-units.h new file mode 100644 index 00000000..23c1999b --- /dev/null +++ b/src/core/all-units.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "unit.h" + +#include "automount.h" +#include "device.h" +#include "path.h" +#include "scope.h" +#include "service.h" +#include "slice.h" +#include "socket.h" +#include "swap.h" +#include "target.h" +#include "timer.h" diff --git a/src/core/audit-fd.c b/src/core/audit-fd.c new file mode 100644 index 00000000..fdef4339 --- /dev/null +++ b/src/core/audit-fd.c @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "audit-fd.h" + +#if HAVE_AUDIT + +#include +#include + +#include "capability-util.h" +#include "fd-util.h" +#include "log.h" +#include "util.h" + +static bool initialized = false; +static int audit_fd; + +int get_audit_fd(void) { + + if (!initialized) { + if (have_effective_cap(CAP_AUDIT_WRITE) == 0) { + audit_fd = -EPERM; + initialized = true; + + return audit_fd; + } + + audit_fd = audit_open(); + + if (audit_fd < 0) { + if (!IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT)) + log_error_errno(errno, "Failed to connect to audit log: %m"); + + audit_fd = errno ? -errno : -EINVAL; + } + + initialized = true; + } + + return audit_fd; +} + +void close_audit_fd(void) { + + if (initialized && audit_fd >= 0) + safe_close(audit_fd); + + initialized = true; + audit_fd = -ECONNRESET; +} + +#else + +int get_audit_fd(void) { + return -EAFNOSUPPORT; +} + +void close_audit_fd(void) { +} + +#endif diff --git a/src/core/audit-fd.h b/src/core/audit-fd.h new file mode 100644 index 00000000..8c1e471b --- /dev/null +++ b/src/core/audit-fd.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int get_audit_fd(void); +void close_audit_fd(void); diff --git a/src/core/automount.c b/src/core/automount.c new file mode 100644 index 00000000..091b59fe --- /dev/null +++ b/src/core/automount.c @@ -0,0 +1,1150 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "async.h" +#include "automount.h" +#include "bus-error.h" +#include "bus-util.h" +#include "dbus-automount.h" +#include "dbus-unit.h" +#include "fd-util.h" +#include "format-util.h" +#include "io-util.h" +#include "label.h" +#include "mkdir.h" +#include "mount-util.h" +#include "mount.h" +#include "mountpoint-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "serialize.h" +#include "special.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "unit-name.h" +#include "unit.h" + +static const UnitActiveState state_translation_table[_AUTOMOUNT_STATE_MAX] = { + [AUTOMOUNT_DEAD] = UNIT_INACTIVE, + [AUTOMOUNT_WAITING] = UNIT_ACTIVE, + [AUTOMOUNT_RUNNING] = UNIT_ACTIVE, + [AUTOMOUNT_FAILED] = UNIT_FAILED +}; + +struct expire_data { + int dev_autofs_fd; + int ioctl_fd; +}; + +static void expire_data_free(struct expire_data *data) { + if (!data) + return; + + safe_close(data->dev_autofs_fd); + safe_close(data->ioctl_fd); + free(data); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct expire_data*, expire_data_free); + +static int open_dev_autofs(Manager *m); +static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata); +static int automount_start_expire(Automount *a); +static void automount_stop_expire(Automount *a); +static int automount_send_ready(Automount *a, Set *tokens, int status); + +static void automount_init(Unit *u) { + Automount *a = AUTOMOUNT(u); + + assert(u); + assert(u->load_state == UNIT_STUB); + + a->pipe_fd = -1; + a->directory_mode = 0755; + UNIT(a)->ignore_on_isolate = true; +} + +static void unmount_autofs(Automount *a) { + int r; + + assert(a); + + if (a->pipe_fd < 0) + return; + + a->pipe_event_source = sd_event_source_unref(a->pipe_event_source); + a->pipe_fd = safe_close(a->pipe_fd); + + /* If we reload/reexecute things we keep the mount point around */ + if (!IN_SET(UNIT(a)->manager->objective, MANAGER_RELOAD, MANAGER_REEXECUTE)) { + + automount_send_ready(a, a->tokens, -EHOSTDOWN); + automount_send_ready(a, a->expire_tokens, -EHOSTDOWN); + + if (a->where) { + r = repeat_unmount(a->where, MNT_DETACH); + if (r < 0) + log_error_errno(r, "Failed to unmount: %m"); + } + } +} + +static void automount_done(Unit *u) { + Automount *a = AUTOMOUNT(u); + + assert(a); + + unmount_autofs(a); + + a->where = mfree(a->where); + + a->tokens = set_free(a->tokens); + a->expire_tokens = set_free(a->expire_tokens); + + a->expire_event_source = sd_event_source_unref(a->expire_event_source); +} + +static int automount_add_trigger_dependencies(Automount *a) { + Unit *x; + int r; + + assert(a); + + r = unit_load_related_unit(UNIT(a), ".mount", &x); + if (r < 0) + return r; + + return unit_add_two_dependencies(UNIT(a), UNIT_BEFORE, UNIT_TRIGGERS, x, true, UNIT_DEPENDENCY_IMPLICIT); +} + +static int automount_add_mount_dependencies(Automount *a) { + _cleanup_free_ char *parent = NULL; + + assert(a); + + parent = dirname_malloc(a->where); + if (!parent) + return -ENOMEM; + + return unit_require_mounts_for(UNIT(a), parent, UNIT_DEPENDENCY_IMPLICIT); +} + +static int automount_add_default_dependencies(Automount *a) { + int r; + + assert(a); + + if (!UNIT(a)->default_dependencies) + return 0; + + if (!MANAGER_IS_SYSTEM(UNIT(a)->manager)) + return 0; + + r = unit_add_dependency_by_name(UNIT(a), UNIT_AFTER, SPECIAL_LOCAL_FS_PRE_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + r = unit_add_two_dependencies_by_name(UNIT(a), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + return 0; +} + +static int automount_verify(Automount *a) { + _cleanup_free_ char *e = NULL; + int r; + + assert(a); + assert(UNIT(a)->load_state == UNIT_LOADED); + + if (path_equal(a->where, "/")) { + log_unit_error(UNIT(a), "Cannot have an automount unit for the root directory. Refusing."); + return -ENOEXEC; + } + + r = unit_name_from_path(a->where, ".automount", &e); + if (r < 0) + return log_unit_error_errno(UNIT(a), r, "Failed to generate unit name from path: %m"); + + if (!unit_has_name(UNIT(a), e)) { + log_unit_error(UNIT(a), "Where= setting doesn't match unit name. Refusing."); + return -ENOEXEC; + } + + return 0; +} + +static int automount_set_where(Automount *a) { + int r; + + assert(a); + + if (a->where) + return 0; + + r = unit_name_to_path(UNIT(a)->id, &a->where); + if (r < 0) + return r; + + path_simplify(a->where, false); + return 1; +} + +static int automount_add_extras(Automount *a) { + int r; + + r = automount_set_where(a); + if (r < 0) + return r; + + r = automount_add_trigger_dependencies(a); + if (r < 0) + return r; + + r = automount_add_mount_dependencies(a); + if (r < 0) + return r; + + return automount_add_default_dependencies(a); +} + +static int automount_load(Unit *u) { + Automount *a = AUTOMOUNT(u); + int r; + + assert(u); + assert(u->load_state == UNIT_STUB); + + /* Load a .automount file */ + r = unit_load_fragment_and_dropin(u, true); + if (r < 0) + return r; + + if (u->load_state != UNIT_LOADED) + return 0; + + r = automount_add_extras(a); + if (r < 0) + return r; + + return automount_verify(a); +} + +static void automount_set_state(Automount *a, AutomountState state) { + AutomountState old_state; + assert(a); + + if (a->state != state) + bus_unit_send_pending_change_signal(UNIT(a), false); + + old_state = a->state; + a->state = state; + + if (state != AUTOMOUNT_RUNNING) + automount_stop_expire(a); + + if (!IN_SET(state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)) + unmount_autofs(a); + + if (state != old_state) + log_unit_debug(UNIT(a), "Changed %s -> %s", automount_state_to_string(old_state), automount_state_to_string(state)); + + unit_notify(UNIT(a), state_translation_table[old_state], state_translation_table[state], 0); +} + +static int automount_coldplug(Unit *u) { + Automount *a = AUTOMOUNT(u); + int r; + + assert(a); + assert(a->state == AUTOMOUNT_DEAD); + + if (a->deserialized_state == a->state) + return 0; + + if (IN_SET(a->deserialized_state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)) { + + r = automount_set_where(a); + if (r < 0) + return r; + + r = open_dev_autofs(u->manager); + if (r < 0) + return r; + + assert(a->pipe_fd >= 0); + + r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u); + if (r < 0) + return r; + + (void) sd_event_source_set_description(a->pipe_event_source, "automount-io"); + if (a->deserialized_state == AUTOMOUNT_RUNNING) { + r = automount_start_expire(a); + if (r < 0) + log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m"); + } + + automount_set_state(a, a->deserialized_state); + } + + return 0; +} + +static void automount_dump(Unit *u, FILE *f, const char *prefix) { + char time_string[FORMAT_TIMESPAN_MAX]; + Automount *a = AUTOMOUNT(u); + + assert(a); + + fprintf(f, + "%sAutomount State: %s\n" + "%sResult: %s\n" + "%sWhere: %s\n" + "%sDirectoryMode: %04o\n" + "%sTimeoutIdleUSec: %s\n", + prefix, automount_state_to_string(a->state), + prefix, automount_result_to_string(a->result), + prefix, a->where, + prefix, a->directory_mode, + prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, a->timeout_idle_usec, USEC_PER_SEC)); +} + +static void automount_enter_dead(Automount *a, AutomountResult f) { + assert(a); + + if (a->result == AUTOMOUNT_SUCCESS) + a->result = f; + + unit_log_result(UNIT(a), a->result == AUTOMOUNT_SUCCESS, automount_result_to_string(a->result)); + automount_set_state(a, a->result != AUTOMOUNT_SUCCESS ? AUTOMOUNT_FAILED : AUTOMOUNT_DEAD); +} + +static int open_dev_autofs(Manager *m) { + struct autofs_dev_ioctl param; + + assert(m); + + if (m->dev_autofs_fd >= 0) + return m->dev_autofs_fd; + + (void) label_fix("/dev/autofs", 0); + + m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY); + if (m->dev_autofs_fd < 0) + return log_error_errno(errno, "Failed to open /dev/autofs: %m"); + + init_autofs_dev_ioctl(¶m); + if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, ¶m) < 0) { + m->dev_autofs_fd = safe_close(m->dev_autofs_fd); + return -errno; + } + + log_debug("Autofs kernel version %i.%i", param.ver_major, param.ver_minor); + + return m->dev_autofs_fd; +} + +static int open_ioctl_fd(int dev_autofs_fd, const char *where, dev_t devid) { + struct autofs_dev_ioctl *param; + size_t l; + + assert(dev_autofs_fd >= 0); + assert(where); + + l = sizeof(struct autofs_dev_ioctl) + strlen(where) + 1; + param = alloca(l); + + init_autofs_dev_ioctl(param); + param->size = l; + param->ioctlfd = -1; + param->openmount.devid = devid; + strcpy(param->path, where); + + if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) < 0) + return -errno; + + if (param->ioctlfd < 0) + return -EIO; + + (void) fd_cloexec(param->ioctlfd, true); + return param->ioctlfd; +} + +static int autofs_protocol(int dev_autofs_fd, int ioctl_fd) { + uint32_t major, minor; + struct autofs_dev_ioctl param; + + assert(dev_autofs_fd >= 0); + assert(ioctl_fd >= 0); + + init_autofs_dev_ioctl(¶m); + param.ioctlfd = ioctl_fd; + + if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOVER, ¶m) < 0) + return -errno; + + major = param.protover.version; + + init_autofs_dev_ioctl(¶m); + param.ioctlfd = ioctl_fd; + + if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_PROTOSUBVER, ¶m) < 0) + return -errno; + + minor = param.protosubver.sub_version; + + log_debug("Autofs protocol version %i.%i", major, minor); + return 0; +} + +static int autofs_set_timeout(int dev_autofs_fd, int ioctl_fd, usec_t usec) { + struct autofs_dev_ioctl param; + + assert(dev_autofs_fd >= 0); + assert(ioctl_fd >= 0); + + init_autofs_dev_ioctl(¶m); + param.ioctlfd = ioctl_fd; + + if (usec == USEC_INFINITY) + param.timeout.timeout = 0; + else + /* Convert to seconds, rounding up. */ + param.timeout.timeout = DIV_ROUND_UP(usec, USEC_PER_SEC); + + if (ioctl(dev_autofs_fd, AUTOFS_DEV_IOCTL_TIMEOUT, ¶m) < 0) + return -errno; + + return 0; +} + +static int autofs_send_ready(int dev_autofs_fd, int ioctl_fd, uint32_t token, int status) { + struct autofs_dev_ioctl param; + + assert(dev_autofs_fd >= 0); + assert(ioctl_fd >= 0); + + init_autofs_dev_ioctl(¶m); + param.ioctlfd = ioctl_fd; + + if (status != 0) { + param.fail.token = token; + param.fail.status = status; + } else + param.ready.token = token; + + if (ioctl(dev_autofs_fd, status ? AUTOFS_DEV_IOCTL_FAIL : AUTOFS_DEV_IOCTL_READY, ¶m) < 0) + return -errno; + + return 0; +} + +static int automount_send_ready(Automount *a, Set *tokens, int status) { + _cleanup_close_ int ioctl_fd = -1; + unsigned token; + int r; + + assert(a); + assert(status <= 0); + + if (set_isempty(tokens)) + return 0; + + ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id); + if (ioctl_fd < 0) + return ioctl_fd; + + if (status != 0) + log_unit_debug_errno(UNIT(a), status, "Sending failure: %m"); + else + log_unit_debug(UNIT(a), "Sending success."); + + r = 0; + + /* Autofs thankfully does not hand out 0 as a token */ + while ((token = PTR_TO_UINT(set_steal_first(tokens)))) { + int k; + + /* Autofs fun fact: + * + * if you pass a positive status code here, kernels + * prior to 4.12 will freeze! Yay! */ + + k = autofs_send_ready(UNIT(a)->manager->dev_autofs_fd, + ioctl_fd, + token, + status); + if (k < 0) + r = k; + } + + return r; +} + +static void automount_trigger_notify(Unit *u, Unit *other) { + Automount *a = AUTOMOUNT(u); + int r; + + assert(a); + assert(other); + + /* Filter out invocations with bogus state */ + if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT) + return; + + /* Don't propagate state changes from the mount if we are already down */ + if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)) + return; + + /* Propagate start limit hit state */ + if (other->start_limit_hit) { + automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT); + return; + } + + /* Don't propagate anything if there's still a job queued */ + if (other->job) + return; + + /* The mount is successfully established */ + if (IN_SET(MOUNT(other)->state, MOUNT_MOUNTED, MOUNT_REMOUNTING)) { + (void) automount_send_ready(a, a->tokens, 0); + + r = automount_start_expire(a); + if (r < 0) + log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m"); + + automount_set_state(a, AUTOMOUNT_RUNNING); + } + + if (IN_SET(MOUNT(other)->state, + MOUNT_MOUNTING, MOUNT_MOUNTING_DONE, + MOUNT_MOUNTED, MOUNT_REMOUNTING, + MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL, + MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, + MOUNT_FAILED)) { + + (void) automount_send_ready(a, a->expire_tokens, -ENODEV); + } + + if (MOUNT(other)->state == MOUNT_DEAD) + (void) automount_send_ready(a, a->expire_tokens, 0); + + /* The mount is in some unhappy state now, let's unfreeze any waiting clients */ + if (IN_SET(MOUNT(other)->state, + MOUNT_DEAD, MOUNT_UNMOUNTING, + MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL, + MOUNT_UNMOUNTING_SIGTERM, MOUNT_UNMOUNTING_SIGKILL, + MOUNT_FAILED)) { + + (void) automount_send_ready(a, a->tokens, -ENODEV); + + automount_set_state(a, AUTOMOUNT_WAITING); + } +} + +static void automount_enter_waiting(Automount *a) { + _cleanup_close_ int ioctl_fd = -1; + int p[2] = { -1, -1 }; + char name[STRLEN("systemd-") + DECIMAL_STR_MAX(pid_t) + 1]; + char options[STRLEN("fd=,pgrp=,minproto=5,maxproto=5,direct") + + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1]; + bool mounted = false; + int r, dev_autofs_fd; + struct stat st; + + assert(a); + assert(a->pipe_fd < 0); + assert(a->where); + + set_clear(a->tokens); + + r = unit_fail_if_noncanonical(UNIT(a), a->where); + if (r < 0) + goto fail; + + (void) mkdir_p_label(a->where, a->directory_mode); + + unit_warn_if_dir_nonempty(UNIT(a), a->where); + + dev_autofs_fd = open_dev_autofs(UNIT(a)->manager); + if (dev_autofs_fd < 0) { + r = dev_autofs_fd; + goto fail; + } + + if (pipe2(p, O_CLOEXEC) < 0) { + r = -errno; + goto fail; + } + r = fd_nonblock(p[0], true); + if (r < 0) + goto fail; + + xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp()); + xsprintf(name, "systemd-"PID_FMT, getpid_cached()); + if (mount(name, a->where, "autofs", 0, options) < 0) { + r = -errno; + goto fail; + } + + mounted = true; + + p[1] = safe_close(p[1]); + + if (stat(a->where, &st) < 0) { + r = -errno; + goto fail; + } + + ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev); + if (ioctl_fd < 0) { + r = ioctl_fd; + goto fail; + } + + r = autofs_protocol(dev_autofs_fd, ioctl_fd); + if (r < 0) + goto fail; + + r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec); + if (r < 0) + goto fail; + + r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(a->pipe_event_source, "automount-io"); + + a->pipe_fd = p[0]; + a->dev_id = st.st_dev; + + automount_set_state(a, AUTOMOUNT_WAITING); + + return; + +fail: + log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m"); + + safe_close_pair(p); + + if (mounted) { + r = repeat_unmount(a->where, MNT_DETACH); + if (r < 0) + log_error_errno(r, "Failed to unmount, ignoring: %m"); + } + + automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); +} + +static void *expire_thread(void *p) { + struct autofs_dev_ioctl param; + _cleanup_(expire_data_freep) struct expire_data *data = (struct expire_data*)p; + int r; + + assert(data->dev_autofs_fd >= 0); + assert(data->ioctl_fd >= 0); + + init_autofs_dev_ioctl(¶m); + param.ioctlfd = data->ioctl_fd; + + do { + r = ioctl(data->dev_autofs_fd, AUTOFS_DEV_IOCTL_EXPIRE, ¶m); + } while (r >= 0); + + if (errno != EAGAIN) + log_warning_errno(errno, "Failed to expire automount, ignoring: %m"); + + return NULL; +} + +static int automount_dispatch_expire(sd_event_source *source, usec_t usec, void *userdata) { + Automount *a = AUTOMOUNT(userdata); + _cleanup_(expire_data_freep) struct expire_data *data = NULL; + int r; + + assert(a); + assert(source == a->expire_event_source); + + data = new0(struct expire_data, 1); + if (!data) + return log_oom(); + + data->ioctl_fd = -1; + + data->dev_autofs_fd = fcntl(UNIT(a)->manager->dev_autofs_fd, F_DUPFD_CLOEXEC, 3); + if (data->dev_autofs_fd < 0) + return log_unit_error_errno(UNIT(a), errno, "Failed to duplicate autofs fd: %m"); + + data->ioctl_fd = open_ioctl_fd(UNIT(a)->manager->dev_autofs_fd, a->where, a->dev_id); + if (data->ioctl_fd < 0) + return log_unit_error_errno(UNIT(a), data->ioctl_fd, "Couldn't open autofs ioctl fd: %m"); + + r = asynchronous_job(expire_thread, data); + if (r < 0) + return log_unit_error_errno(UNIT(a), r, "Failed to start expire job: %m"); + + data = NULL; + + return automount_start_expire(a); +} + +static int automount_start_expire(Automount *a) { + int r; + usec_t timeout; + + assert(a); + + if (a->timeout_idle_usec == 0) + return 0; + + timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/3, USEC_PER_SEC); + + if (a->expire_event_source) { + r = sd_event_source_set_time(a->expire_event_source, timeout); + if (r < 0) + return r; + + return sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_ONESHOT); + } + + r = sd_event_add_time( + UNIT(a)->manager->event, + &a->expire_event_source, + CLOCK_MONOTONIC, timeout, 0, + automount_dispatch_expire, a); + if (r < 0) + return r; + + (void) sd_event_source_set_description(a->expire_event_source, "automount-expire"); + + return 0; +} + +static void automount_stop_expire(Automount *a) { + assert(a); + + if (!a->expire_event_source) + return; + + (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF); +} + +static void automount_enter_running(Automount *a) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + Unit *trigger; + struct stat st; + int r; + + assert(a); + + /* If the user masked our unit in the meantime, fail */ + if (UNIT(a)->load_state != UNIT_LOADED) { + log_unit_error(UNIT(a), "Suppressing automount event since unit is no longer loaded."); + goto fail; + } + + /* We don't take mount requests anymore if we are supposed to + * shut down anyway */ + if (unit_stop_pending(UNIT(a))) { + log_unit_debug(UNIT(a), "Suppressing automount request since unit stop is scheduled."); + automount_send_ready(a, a->tokens, -EHOSTDOWN); + automount_send_ready(a, a->expire_tokens, -EHOSTDOWN); + return; + } + + (void) mkdir_p_label(a->where, a->directory_mode); + + /* Before we do anything, let's see if somebody is playing games with us? */ + if (lstat(a->where, &st) < 0) { + log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m"); + goto fail; + } + + /* The mount unit may have been explicitly started before we got the + * autofs request. Ack it to unblock anything waiting on the mount point. */ + if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id) { + log_unit_info(UNIT(a), "Automount point already active?"); + automount_send_ready(a, a->tokens, 0); + return; + } + + trigger = UNIT_TRIGGER(UNIT(a)); + if (!trigger) { + log_unit_error(UNIT(a), "Unit to trigger vanished."); + goto fail; + } + + r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL); + if (r < 0) { + log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r)); + goto fail; + } + + automount_set_state(a, AUTOMOUNT_RUNNING); + return; + +fail: + automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); +} + +static int automount_start(Unit *u) { + Automount *a = AUTOMOUNT(u); + int r; + + assert(a); + assert(IN_SET(a->state, AUTOMOUNT_DEAD, AUTOMOUNT_FAILED)); + + if (path_is_mount_point(a->where, NULL, 0) > 0) { + log_unit_error(u, "Path %s is already a mount point, refusing start.", a->where); + return -EEXIST; + } + + r = unit_test_trigger_loaded(u); + if (r < 0) + return r; + + r = unit_test_start_limit(u); + if (r < 0) { + automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT); + return r; + } + + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + + a->result = AUTOMOUNT_SUCCESS; + automount_enter_waiting(a); + return 1; +} + +static int automount_stop(Unit *u) { + Automount *a = AUTOMOUNT(u); + + assert(a); + assert(IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)); + + automount_enter_dead(a, AUTOMOUNT_SUCCESS); + return 1; +} + +static int automount_serialize(Unit *u, FILE *f, FDSet *fds) { + Automount *a = AUTOMOUNT(u); + Iterator i; + void *p; + int r; + + assert(a); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", automount_state_to_string(a->state)); + (void) serialize_item(f, "result", automount_result_to_string(a->result)); + (void) serialize_item_format(f, "dev-id", "%lu", (unsigned long) a->dev_id); + + SET_FOREACH(p, a->tokens, i) + (void) serialize_item_format(f, "token", "%u", PTR_TO_UINT(p)); + SET_FOREACH(p, a->expire_tokens, i) + (void) serialize_item_format(f, "expire-token", "%u", PTR_TO_UINT(p)); + + r = serialize_fd(f, fds, "pipe-fd", a->pipe_fd); + if (r < 0) + return r; + + return 0; +} + +static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Automount *a = AUTOMOUNT(u); + int r; + + assert(a); + assert(fds); + + if (streq(key, "state")) { + AutomountState state; + + state = automount_state_from_string(value); + if (state < 0) + log_unit_debug(u, "Failed to parse state value: %s", value); + else + a->deserialized_state = state; + } else if (streq(key, "result")) { + AutomountResult f; + + f = automount_result_from_string(value); + if (f < 0) + log_unit_debug(u, "Failed to parse result value: %s", value); + else if (f != AUTOMOUNT_SUCCESS) + a->result = f; + + } else if (streq(key, "dev-id")) { + unsigned long d; + + if (safe_atolu(value, &d) < 0) + log_unit_debug(u, "Failed to parse dev-id value: %s", value); + else + a->dev_id = (dev_t) d; + + } else if (streq(key, "token")) { + unsigned token; + + if (safe_atou(value, &token) < 0) + log_unit_debug(u, "Failed to parse token value: %s", value); + else { + r = set_ensure_allocated(&a->tokens, NULL); + if (r < 0) { + log_oom(); + return 0; + } + + r = set_put(a->tokens, UINT_TO_PTR(token)); + if (r < 0) + log_unit_error_errno(u, r, "Failed to add token to set: %m"); + } + } else if (streq(key, "expire-token")) { + unsigned token; + + if (safe_atou(value, &token) < 0) + log_unit_debug(u, "Failed to parse token value: %s", value); + else { + r = set_ensure_allocated(&a->expire_tokens, NULL); + if (r < 0) { + log_oom(); + return 0; + } + + r = set_put(a->expire_tokens, UINT_TO_PTR(token)); + if (r < 0) + log_unit_error_errno(u, r, "Failed to add expire token to set: %m"); + } + } else if (streq(key, "pipe-fd")) { + int fd; + + if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse pipe-fd value: %s", value); + else { + safe_close(a->pipe_fd); + a->pipe_fd = fdset_remove(fds, fd); + } + } else + log_unit_debug(u, "Unknown serialization key: %s", key); + + return 0; +} + +static UnitActiveState automount_active_state(Unit *u) { + assert(u); + + return state_translation_table[AUTOMOUNT(u)->state]; +} + +static const char *automount_sub_state_to_string(Unit *u) { + assert(u); + + return automount_state_to_string(AUTOMOUNT(u)->state); +} + +static bool automount_may_gc(Unit *u) { + Unit *t; + + assert(u); + + t = UNIT_TRIGGER(u); + if (!t) + return true; + + return UNIT_VTABLE(t)->may_gc(t); +} + +static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + union autofs_v5_packet_union packet; + Automount *a = AUTOMOUNT(userdata); + Unit *trigger; + int r; + + assert(a); + assert(fd == a->pipe_fd); + + if (events != EPOLLIN) { + log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd); + goto fail; + } + + r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true); + if (r < 0) { + log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m"); + goto fail; + } + + switch (packet.hdr.type) { + + case autofs_ptype_missing_direct: + + if (packet.v5_packet.pid > 0) { + _cleanup_free_ char *p = NULL; + + get_process_comm(packet.v5_packet.pid, &p); + log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p)); + } else + log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where); + + r = set_ensure_allocated(&a->tokens, NULL); + if (r < 0) { + log_unit_error(UNIT(a), "Failed to allocate token set."); + goto fail; + } + + r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token)); + if (r < 0) { + log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m"); + goto fail; + } + + automount_enter_running(a); + break; + + case autofs_ptype_expire_direct: + log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where); + + automount_stop_expire(a); + + r = set_ensure_allocated(&a->expire_tokens, NULL); + if (r < 0) { + log_unit_error(UNIT(a), "Failed to allocate token set."); + goto fail; + } + + r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token)); + if (r < 0) { + log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m"); + goto fail; + } + + trigger = UNIT_TRIGGER(UNIT(a)); + if (!trigger) { + log_unit_error(UNIT(a), "Unit to trigger vanished."); + goto fail; + } + + r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, NULL, &error, NULL); + if (r < 0) { + log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r)); + goto fail; + } + break; + + default: + log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type); + break; + } + + return 0; + +fail: + automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES); + return 0; +} + +static void automount_shutdown(Manager *m) { + assert(m); + + m->dev_autofs_fd = safe_close(m->dev_autofs_fd); +} + +static void automount_reset_failed(Unit *u) { + Automount *a = AUTOMOUNT(u); + + assert(a); + + if (a->state == AUTOMOUNT_FAILED) + automount_set_state(a, AUTOMOUNT_DEAD); + + a->result = AUTOMOUNT_SUCCESS; +} + +static bool automount_supported(void) { + static int supported = -1; + + if (supported < 0) + supported = access("/dev/autofs", F_OK) >= 0; + + return supported; +} + +static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = { + [AUTOMOUNT_SUCCESS] = "success", + [AUTOMOUNT_FAILURE_RESOURCES] = "resources", + [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit", + [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit", +}; + +DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult); + +const UnitVTable automount_vtable = { + .object_size = sizeof(Automount), + + .sections = + "Unit\0" + "Automount\0" + "Install\0", + + .init = automount_init, + .load = automount_load, + .done = automount_done, + + .coldplug = automount_coldplug, + + .dump = automount_dump, + + .start = automount_start, + .stop = automount_stop, + + .serialize = automount_serialize, + .deserialize_item = automount_deserialize_item, + + .active_state = automount_active_state, + .sub_state_to_string = automount_sub_state_to_string, + + .may_gc = automount_may_gc, + + .trigger_notify = automount_trigger_notify, + + .reset_failed = automount_reset_failed, + + .bus_vtable = bus_automount_vtable, + .bus_set_property = bus_automount_set_property, + + .can_transient = true, + + .shutdown = automount_shutdown, + .supported = automount_supported, + + .status_message_formats = { + .finished_start_job = { + [JOB_DONE] = "Set up automount %s.", + [JOB_FAILED] = "Failed to set up automount %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Unset automount %s.", + [JOB_FAILED] = "Failed to unset automount %s.", + }, + }, +}; diff --git a/src/core/automount.h b/src/core/automount.h new file mode 100644 index 00000000..21dd1c07 --- /dev/null +++ b/src/core/automount.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Automount Automount; + +#include "unit.h" + +typedef enum AutomountResult { + AUTOMOUNT_SUCCESS, + AUTOMOUNT_FAILURE_RESOURCES, + AUTOMOUNT_FAILURE_START_LIMIT_HIT, + AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT, + _AUTOMOUNT_RESULT_MAX, + _AUTOMOUNT_RESULT_INVALID = -1 +} AutomountResult; + +struct Automount { + Unit meta; + + AutomountState state, deserialized_state; + + char *where; + usec_t timeout_idle_usec; + + int pipe_fd; + sd_event_source *pipe_event_source; + mode_t directory_mode; + dev_t dev_id; + + Set *tokens; + Set *expire_tokens; + + sd_event_source *expire_event_source; + + AutomountResult result; +}; + +extern const UnitVTable automount_vtable; + +const char* automount_result_to_string(AutomountResult i) _const_; +AutomountResult automount_result_from_string(const char *s) _pure_; + +DEFINE_CAST(AUTOMOUNT, Automount); diff --git a/src/core/bpf-devices.c b/src/core/bpf-devices.c new file mode 100644 index 00000000..98460300 --- /dev/null +++ b/src/core/bpf-devices.c @@ -0,0 +1,489 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "bpf-devices.h" +#include "bpf-program.h" +#include "fd-util.h" +#include "fileio.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-util.h" + +#define PASS_JUMP_OFF 4096 + +static int bpf_access_type(const char *acc) { + int r = 0; + + assert(acc); + + for (; *acc; acc++) + switch(*acc) { + case 'r': + r |= BPF_DEVCG_ACC_READ; + break; + case 'w': + r |= BPF_DEVCG_ACC_WRITE; + break; + case 'm': + r |= BPF_DEVCG_ACC_MKNOD; + break; + default: + return -EINVAL; + } + + return r; +} + +static int bpf_prog_whitelist_device(BPFProgram *prog, char type, int major, int minor, const char *acc) { + int r, access; + + assert(prog); + assert(acc); + + log_trace("%s: %c %d:%d %s", __func__, type, major, minor, acc); + + access = bpf_access_type(acc); + if (access <= 0) + return -EINVAL; + + assert(IN_SET(type, 'b', 'c')); + const int bpf_type = type == 'c' ? BPF_DEVCG_DEV_CHAR : BPF_DEVCG_DEV_BLOCK; + + const struct bpf_insn insn[] = { + BPF_MOV32_REG(BPF_REG_1, BPF_REG_3), + BPF_ALU32_IMM(BPF_AND, BPF_REG_1, access), + BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, 4), /* compare access type */ + + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, bpf_type, 3), /* compare device type */ + BPF_JMP_IMM(BPF_JNE, BPF_REG_4, major, 2), /* compare major */ + BPF_JMP_IMM(BPF_JNE, BPF_REG_5, minor, 1), /* compare minor */ + BPF_JMP_A(PASS_JUMP_OFF), /* jump to PASS */ + }; + + if (FLAGS_SET(access, BPF_DEVCG_ACC_READ | BPF_DEVCG_ACC_WRITE | BPF_DEVCG_ACC_MKNOD)) + r = bpf_program_add_instructions(prog, insn + 3, ELEMENTSOF(insn) - 3); + else + r = bpf_program_add_instructions(prog, insn, ELEMENTSOF(insn)); + if (r < 0) + log_error_errno(r, "Extending device control BPF program failed: %m"); + + return r; +} + +static int bpf_prog_whitelist_major(BPFProgram *prog, char type, int major, const char *acc) { + int r, access; + + assert(prog); + assert(acc); + + log_trace("%s: %c %d:* %s", __func__, type, major, acc); + + access = bpf_access_type(acc); + if (access <= 0) + return -EINVAL; + + assert(IN_SET(type, 'b', 'c')); + const int bpf_type = type == 'c' ? BPF_DEVCG_DEV_CHAR : BPF_DEVCG_DEV_BLOCK; + + const struct bpf_insn insn[] = { + BPF_MOV32_REG(BPF_REG_1, BPF_REG_3), + BPF_ALU32_IMM(BPF_AND, BPF_REG_1, access), + BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, 3), /* compare access type */ + + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, bpf_type, 2), /* compare device type */ + BPF_JMP_IMM(BPF_JNE, BPF_REG_4, major, 1), /* compare major */ + BPF_JMP_A(PASS_JUMP_OFF), /* jump to PASS */ + }; + + if (FLAGS_SET(access, BPF_DEVCG_ACC_READ | BPF_DEVCG_ACC_WRITE | BPF_DEVCG_ACC_MKNOD)) + r = bpf_program_add_instructions(prog, insn + 3, ELEMENTSOF(insn) - 3); + else + r = bpf_program_add_instructions(prog, insn, ELEMENTSOF(insn)); + if (r < 0) + log_error_errno(r, "Extending device control BPF program failed: %m"); + + return r; +} + +static int bpf_prog_whitelist_class(BPFProgram *prog, char type, const char *acc) { + int r, access; + + assert(prog); + assert(acc); + + log_trace("%s: %c *:* %s", __func__, type, acc); + + access = bpf_access_type(acc); + if (access <= 0) + return -EINVAL; + + assert(IN_SET(type, 'b', 'c')); + const int bpf_type = type == 'c' ? BPF_DEVCG_DEV_CHAR : BPF_DEVCG_DEV_BLOCK; + + const struct bpf_insn insn[] = { + BPF_MOV32_REG(BPF_REG_1, BPF_REG_3), + BPF_ALU32_IMM(BPF_AND, BPF_REG_1, access), + BPF_JMP_REG(BPF_JNE, BPF_REG_1, BPF_REG_3, 2), /* compare access type */ + + BPF_JMP_IMM(BPF_JNE, BPF_REG_2, bpf_type, 1), /* compare device type */ + BPF_JMP_A(PASS_JUMP_OFF), /* jump to PASS */ + }; + + if (FLAGS_SET(access, BPF_DEVCG_ACC_READ | BPF_DEVCG_ACC_WRITE | BPF_DEVCG_ACC_MKNOD)) + r = bpf_program_add_instructions(prog, insn + 3, ELEMENTSOF(insn) - 3); + else + r = bpf_program_add_instructions(prog, insn, ELEMENTSOF(insn)); + if (r < 0) + log_error_errno(r, "Extending device control BPF program failed: %m"); + + return r; +} + +int bpf_devices_cgroup_init(BPFProgram **ret, CGroupDevicePolicy policy, bool whitelist) { + const struct bpf_insn pre_insn[] = { + /* load device type to r2 */ + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, + offsetof(struct bpf_cgroup_dev_ctx, access_type)), + BPF_ALU32_IMM(BPF_AND, BPF_REG_2, 0xFFFF), + + /* load access type to r3 */ + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, + offsetof(struct bpf_cgroup_dev_ctx, access_type)), + BPF_ALU32_IMM(BPF_RSH, BPF_REG_3, 16), + + /* load major number to r4 */ + BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, + offsetof(struct bpf_cgroup_dev_ctx, major)), + + /* load minor number to r5 */ + BPF_LDX_MEM(BPF_W, BPF_REG_5, BPF_REG_1, + offsetof(struct bpf_cgroup_dev_ctx, minor)), + }; + + _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL; + int r; + + assert(ret); + + if (policy == CGROUP_DEVICE_POLICY_AUTO && !whitelist) + return 0; + + r = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE, &prog); + if (r < 0) + return log_error_errno(r, "Loading device control BPF program failed: %m"); + + if (policy == CGROUP_DEVICE_POLICY_CLOSED || whitelist) { + r = bpf_program_add_instructions(prog, pre_insn, ELEMENTSOF(pre_insn)); + if (r < 0) + return log_error_errno(r, "Extending device control BPF program failed: %m"); + } + + *ret = TAKE_PTR(prog); + + return 0; +} + +int bpf_devices_apply_policy( + BPFProgram *prog, + CGroupDevicePolicy policy, + bool whitelist, + const char *cgroup_path, + BPFProgram **prog_installed) { + + _cleanup_free_ char *controller_path = NULL; + int r; + + /* This will assign *keep_program if everything goes well. */ + + if (!prog) + goto finish; + + const bool deny_everything = policy == CGROUP_DEVICE_POLICY_STRICT && !whitelist; + + const struct bpf_insn post_insn[] = { + /* return DENY */ + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_JMP_A(1), + }; + + const struct bpf_insn exit_insn[] = { + /* finally return DENY if deny_everything else ALLOW */ + BPF_MOV64_IMM(BPF_REG_0, deny_everything ? 0 : 1), + BPF_EXIT_INSN() + }; + + if (!deny_everything) { + r = bpf_program_add_instructions(prog, post_insn, ELEMENTSOF(post_insn)); + if (r < 0) + return log_error_errno(r, "Extending device control BPF program failed: %m"); + + /* Fixup PASS_JUMP_OFF jump offsets. */ + for (size_t off = 0; off < prog->n_instructions; off++) { + struct bpf_insn *ins = &prog->instructions[off]; + + if (ins->code == (BPF_JMP | BPF_JA) && ins->off == PASS_JUMP_OFF) + ins->off = prog->n_instructions - off - 1; + } + } + + r = bpf_program_add_instructions(prog, exit_insn, ELEMENTSOF(exit_insn)); + if (r < 0) + return log_error_errno(r, "Extending device control BPF program failed: %m"); + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, NULL, &controller_path); + if (r < 0) + return log_error_errno(r, "Failed to determine cgroup path: %m"); + + r = bpf_program_cgroup_attach(prog, BPF_CGROUP_DEVICE, controller_path, BPF_F_ALLOW_MULTI); + if (r < 0) + return log_error_errno(r, "Attaching device control BPF program to cgroup %s failed: %m", + cgroup_path); + + finish: + /* Unref the old BPF program (which will implicitly detach it) right before attaching the new program. */ + if (prog_installed) { + bpf_program_unref(*prog_installed); + *prog_installed = bpf_program_ref(prog); + } + return 0; +} + +int bpf_devices_supported(void) { + const struct bpf_insn trivial[] = { + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN() + }; + + _cleanup_(bpf_program_unrefp) BPFProgram *program = NULL; + static int supported = -1; + int r; + + /* Checks whether BPF device controller is supported. For this, we check five things: + * + * a) whether we are privileged + * b) whether the unified hierarchy is being used + * c) the BPF implementation in the kernel supports BPF_PROG_TYPE_CGROUP_DEVICE programs, which we require + */ + + if (supported >= 0) + return supported; + + if (geteuid() != 0) { + log_debug("Not enough privileges, BPF device control is not supported."); + return supported = 0; + } + + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) + return log_error_errno(r, "Can't determine whether the unified hierarchy is used: %m"); + if (r == 0) { + log_debug("Not running with unified cgroups, BPF device control is not supported."); + return supported = 0; + } + + r = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE, &program); + if (r < 0) { + log_debug_errno(r, "Can't allocate CGROUP DEVICE BPF program, BPF device control is not supported: %m"); + return supported = 0; + } + + r = bpf_program_add_instructions(program, trivial, ELEMENTSOF(trivial)); + if (r < 0) { + log_debug_errno(r, "Can't add trivial instructions to CGROUP DEVICE BPF program, BPF device control is not supported: %m"); + return supported = 0; + } + + r = bpf_program_load_kernel(program, NULL, 0); + if (r < 0) { + log_debug_errno(r, "Can't load kernel CGROUP DEVICE BPF program, BPF device control is not supported: %m"); + return supported = 0; + } + + return supported = 1; +} + +static int whitelist_device_pattern(BPFProgram *prog, const char *path, char type, const unsigned *maj, const unsigned *min, const char *acc) { + assert(IN_SET(type, 'b', 'c')); + + if (cg_all_unified() > 0) { + if (!prog) + return 0; + + if (maj && min) + return bpf_prog_whitelist_device(prog, type, *maj, *min, acc); + else if (maj) + return bpf_prog_whitelist_major(prog, type, *maj, acc); + else + return bpf_prog_whitelist_class(prog, type, acc); + + } else { + char buf[2+DECIMAL_STR_MAX(unsigned)*2+2+4]; + int r; + + if (maj && min) + xsprintf(buf, "%c %u:%u %s", type, *maj, *min, acc); + else if (maj) + xsprintf(buf, "%c %u:* %s", type, *maj, acc); + else + xsprintf(buf, "%c *:* %s", type, acc); + + /* Changing the devices list of a populated cgroup might result in EINVAL, hence ignore + * EINVAL here. */ + + r = cg_set_attribute("devices", path, "devices.allow", buf); + if (r < 0) + log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, + r, "Failed to set devices.allow on %s: %m", path); + + return r; + } +} + +int bpf_devices_whitelist_device(BPFProgram *prog, const char *path, const char *node, const char *acc) { + mode_t mode; + dev_t rdev; + int r; + + assert(path); + assert(acc); + assert(strlen(acc) <= 3); + + log_trace("%s: %s %s", __func__, node, acc); + + /* Some special handling for /dev/block/%u:%u, /dev/char/%u:%u, /run/systemd/inaccessible/chr and + * /run/systemd/inaccessible/blk paths. Instead of stat()ing these we parse out the major/minor directly. This + * means clients can use these path without the device node actually around */ + r = device_path_parse_major_minor(node, &mode, &rdev); + if (r < 0) { + if (r != -ENODEV) + return log_warning_errno(r, "Couldn't parse major/minor from device path '%s': %m", node); + + struct stat st; + if (stat(node, &st) < 0) + return log_warning_errno(errno, "Couldn't stat device %s: %m", node); + + if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) + return log_warning_errno(SYNTHETIC_ERRNO(ENODEV), "%s is not a device.", node); + + mode = st.st_mode; + rdev = (dev_t) st.st_rdev; + } + + unsigned maj = major(rdev), min = minor(rdev); + return whitelist_device_pattern(prog, path, S_ISCHR(mode) ? 'c' : 'b', &maj, &min, acc); +} + +int bpf_devices_whitelist_major(BPFProgram *prog, const char *path, const char *name, char type, const char *acc) { + unsigned maj; + int r; + + assert(path); + assert(acc); + assert(IN_SET(type, 'b', 'c')); + + if (streq(name, "*")) + /* If the name is a wildcard, then apply this list to all devices of this type */ + return whitelist_device_pattern(prog, path, type, NULL, NULL, acc); + + if (safe_atou(name, &maj) >= 0 && DEVICE_MAJOR_VALID(maj)) + /* The name is numeric and suitable as major. In that case, let's take its major, and create + * the entry directly. */ + return whitelist_device_pattern(prog, path, type, &maj, NULL, acc); + + _cleanup_fclose_ FILE *f = NULL; + bool good = false, any = false; + + f = fopen("/proc/devices", "re"); + if (!f) + return log_warning_errno(errno, "Cannot open /proc/devices to resolve %s: %m", name); + + for (;;) { + _cleanup_free_ char *line = NULL; + char *w, *p; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_warning_errno(r, "Failed to read /proc/devices: %m"); + if (r == 0) + break; + + if (type == 'c' && streq(line, "Character devices:")) { + good = true; + continue; + } + + if (type == 'b' && streq(line, "Block devices:")) { + good = true; + continue; + } + + if (isempty(line)) { + good = false; + continue; + } + + if (!good) + continue; + + p = strstrip(line); + + w = strpbrk(p, WHITESPACE); + if (!w) + continue; + *w = 0; + + r = safe_atou(p, &maj); + if (r < 0) + continue; + if (maj <= 0) + continue; + + w++; + w += strspn(w, WHITESPACE); + + if (fnmatch(name, w, 0) != 0) + continue; + + any = true; + (void) whitelist_device_pattern(prog, path, type, &maj, NULL, acc); + } + + if (!any) + return log_debug_errno(SYNTHETIC_ERRNO(ENOENT), + "Device whitelist pattern \"%s\" did not match anything.", name); + + return 0; +} + +int bpf_devices_whitelist_static(BPFProgram *prog, const char *path) { + static const char auto_devices[] = + "/dev/null\0" "rwm\0" + "/dev/zero\0" "rwm\0" + "/dev/full\0" "rwm\0" + "/dev/random\0" "rwm\0" + "/dev/urandom\0" "rwm\0" + "/dev/tty\0" "rwm\0" + "/dev/ptmx\0" "rwm\0" + /* Allow /run/systemd/inaccessible/{chr,blk} devices for mapping InaccessiblePaths */ + "/run/systemd/inaccessible/chr\0" "rwm\0" + "/run/systemd/inaccessible/blk\0" "rwm\0"; + int r = 0, k; + + const char *node, *acc; + NULSTR_FOREACH_PAIR(node, acc, auto_devices) { + k = bpf_devices_whitelist_device(prog, path, node, acc); + if (r >= 0 && k < 0) + r = k; + } + + /* PTS (/dev/pts) devices may not be duplicated, but accessed */ + k = bpf_devices_whitelist_major(prog, path, "pts", 'c', "rw"); + if (r >= 0 && k < 0) + r = k; + + return r; +} diff --git a/src/core/bpf-devices.h b/src/core/bpf-devices.h new file mode 100644 index 00000000..4a5f4b1f --- /dev/null +++ b/src/core/bpf-devices.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "cgroup.h" + +typedef struct BPFProgram BPFProgram; + +int bpf_devices_cgroup_init(BPFProgram **ret, CGroupDevicePolicy policy, bool whitelist); +int bpf_devices_apply_policy( + BPFProgram *prog, + CGroupDevicePolicy policy, + bool whitelist, + const char *cgroup_path, + BPFProgram **prog_installed); + +int bpf_devices_supported(void); +int bpf_devices_whitelist_device(BPFProgram *prog, const char *path, const char *node, const char *acc); +int bpf_devices_whitelist_major(BPFProgram *prog, const char *path, const char *name, char type, const char *acc); +int bpf_devices_whitelist_static(BPFProgram *prog, const char *path); diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c new file mode 100644 index 00000000..96c1a28b --- /dev/null +++ b/src/core/bpf-firewall.c @@ -0,0 +1,918 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "bpf-firewall.h" +#include "bpf-program.h" +#include "fd-util.h" +#include "ip-address-access.h" +#include "memory-util.h" +#include "missing_syscall.h" +#include "unit.h" +#include "strv.h" +#include "virt.h" + +enum { + MAP_KEY_PACKETS, + MAP_KEY_BYTES, +}; + +enum { + ACCESS_ALLOWED = 1, + ACCESS_DENIED = 2, +}; + +/* Compile instructions for one list of addresses, one direction and one specific verdict on matches. */ + +static int add_lookup_instructions( + BPFProgram *p, + int map_fd, + int protocol, + bool is_ingress, + int verdict) { + + int r, addr_offset, addr_size; + + assert(p); + assert(map_fd >= 0); + + switch (protocol) { + + case ETH_P_IP: + addr_size = sizeof(uint32_t); + addr_offset = is_ingress ? + offsetof(struct iphdr, saddr) : + offsetof(struct iphdr, daddr); + break; + + case ETH_P_IPV6: + addr_size = 4 * sizeof(uint32_t); + addr_offset = is_ingress ? + offsetof(struct ip6_hdr, ip6_src.s6_addr) : + offsetof(struct ip6_hdr, ip6_dst.s6_addr); + break; + + default: + return -EAFNOSUPPORT; + } + + do { + /* Compare IPv4 with one word instruction (32bit) */ + struct bpf_insn insn[] = { + /* If skb->protocol != ETH_P_IP, skip this whole block. The offset will be set later. */ + BPF_JMP_IMM(BPF_JNE, BPF_REG_7, htobe16(protocol), 0), + + /* + * Call into BPF_FUNC_skb_load_bytes to load the dst/src IP address + * + * R1: Pointer to the skb + * R2: Data offset + * R3: Destination buffer on the stack (r10 - 4) + * R4: Number of bytes to read (4) + */ + + BPF_MOV64_REG(BPF_REG_1, BPF_REG_6), + BPF_MOV32_IMM(BPF_REG_2, addr_offset), + + BPF_MOV64_REG(BPF_REG_3, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, -addr_size), + + BPF_MOV32_IMM(BPF_REG_4, addr_size), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_skb_load_bytes), + + /* + * Call into BPF_FUNC_map_lookup_elem to see if the address matches any entry in the + * LPM trie map. For this to work, the prefixlen field of 'struct bpf_lpm_trie_key' + * has to be set to the maximum possible value. + * + * On success, the looked up value is stored in R0. For this application, the actual + * value doesn't matter, however; we just set the bit in @verdict in R8 if we found any + * matching value. + */ + + BPF_LD_MAP_FD(BPF_REG_1, map_fd), + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -addr_size - sizeof(uint32_t)), + BPF_ST_MEM(BPF_W, BPF_REG_2, 0, addr_size * 8), + + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), + BPF_ALU32_IMM(BPF_OR, BPF_REG_8, verdict), + }; + + /* Jump label fixup */ + insn[0].off = ELEMENTSOF(insn) - 1; + + r = bpf_program_add_instructions(p, insn, ELEMENTSOF(insn)); + if (r < 0) + return r; + + } while (false); + + return 0; +} + +static int add_instructions_for_ip_any( + BPFProgram *p, + int verdict) { + int r; + + assert(p); + + const struct bpf_insn insn[] = { + BPF_ALU32_IMM(BPF_OR, BPF_REG_8, verdict), + }; + + r = bpf_program_add_instructions(p, insn, 1); + if (r < 0) + return r; + + return 0; +} + +static int bpf_firewall_compile_bpf( + Unit *u, + bool is_ingress, + BPFProgram **ret, + bool ip_allow_any, + bool ip_deny_any) { + + const struct bpf_insn pre_insn[] = { + /* + * When the eBPF program is entered, R1 contains the address of the skb. + * However, R1-R5 are scratch registers that are not preserved when calling + * into kernel functions, so we need to save anything that's supposed to + * stay around to R6-R9. Save the skb to R6. + */ + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), + + /* + * Although we cannot access the skb data directly from eBPF programs used in this + * scenario, the kernel has prepared some fields for us to access through struct __sk_buff. + * Load the protocol (IPv4, IPv6) used by the packet in flight once and cache it in R7 + * for later use. + */ + BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, offsetof(struct __sk_buff, protocol)), + + /* + * R8 is used to keep track of whether any address check has explicitly allowed or denied the packet + * through ACCESS_DENIED or ACCESS_ALLOWED bits. Reset them both to 0 in the beginning. + */ + BPF_MOV32_IMM(BPF_REG_8, 0), + }; + + /* + * The access checkers compiled for the configured allowance and denial lists + * write to R8 at runtime. The following code prepares for an early exit that + * skip the accounting if the packet is denied. + * + * R0 = 1 + * if (R8 == ACCESS_DENIED) + * R0 = 0 + * + * This means that if both ACCESS_DENIED and ACCESS_ALLOWED are set, the packet + * is allowed to pass. + */ + const struct bpf_insn post_insn[] = { + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_JMP_IMM(BPF_JNE, BPF_REG_8, ACCESS_DENIED, 1), + BPF_MOV64_IMM(BPF_REG_0, 0), + }; + + _cleanup_(bpf_program_unrefp) BPFProgram *p = NULL; + int accounting_map_fd, r; + bool access_enabled; + + assert(u); + assert(ret); + + accounting_map_fd = is_ingress ? + u->ip_accounting_ingress_map_fd : + u->ip_accounting_egress_map_fd; + + access_enabled = + u->ipv4_allow_map_fd >= 0 || + u->ipv6_allow_map_fd >= 0 || + u->ipv4_deny_map_fd >= 0 || + u->ipv6_deny_map_fd >= 0 || + ip_allow_any || + ip_deny_any; + + if (accounting_map_fd < 0 && !access_enabled) { + *ret = NULL; + return 0; + } + + r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &p); + if (r < 0) + return r; + + r = bpf_program_add_instructions(p, pre_insn, ELEMENTSOF(pre_insn)); + if (r < 0) + return r; + + if (access_enabled) { + /* + * The simple rule this function translates into eBPF instructions is: + * + * - Access will be granted when an address matches an entry in @list_allow + * - Otherwise, access will be denied when an address matches an entry in @list_deny + * - Otherwise, access will be granted + */ + + if (u->ipv4_deny_map_fd >= 0) { + r = add_lookup_instructions(p, u->ipv4_deny_map_fd, ETH_P_IP, is_ingress, ACCESS_DENIED); + if (r < 0) + return r; + } + + if (u->ipv6_deny_map_fd >= 0) { + r = add_lookup_instructions(p, u->ipv6_deny_map_fd, ETH_P_IPV6, is_ingress, ACCESS_DENIED); + if (r < 0) + return r; + } + + if (u->ipv4_allow_map_fd >= 0) { + r = add_lookup_instructions(p, u->ipv4_allow_map_fd, ETH_P_IP, is_ingress, ACCESS_ALLOWED); + if (r < 0) + return r; + } + + if (u->ipv6_allow_map_fd >= 0) { + r = add_lookup_instructions(p, u->ipv6_allow_map_fd, ETH_P_IPV6, is_ingress, ACCESS_ALLOWED); + if (r < 0) + return r; + } + + if (ip_allow_any) { + r = add_instructions_for_ip_any(p, ACCESS_ALLOWED); + if (r < 0) + return r; + } + + if (ip_deny_any) { + r = add_instructions_for_ip_any(p, ACCESS_DENIED); + if (r < 0) + return r; + } + } + + r = bpf_program_add_instructions(p, post_insn, ELEMENTSOF(post_insn)); + if (r < 0) + return r; + + if (accounting_map_fd >= 0) { + struct bpf_insn insn[] = { + /* + * If R0 == 0, the packet will be denied; skip the accounting instructions in this case. + * The jump label will be fixed up later. + */ + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 0), + + /* Count packets */ + BPF_MOV64_IMM(BPF_REG_0, MAP_KEY_PACKETS), /* r0 = 0 */ + BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */ + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ + BPF_LD_MAP_FD(BPF_REG_1, accounting_map_fd), /* load map fd to r1 */ + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), + BPF_MOV64_IMM(BPF_REG_1, 1), /* r1 = 1 */ + BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */ + + /* Count bytes */ + BPF_MOV64_IMM(BPF_REG_0, MAP_KEY_BYTES), /* r0 = 1 */ + BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */ + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */ + BPF_LD_MAP_FD(BPF_REG_1, accounting_map_fd), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), + BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_6, offsetof(struct __sk_buff, len)), /* r1 = skb->len */ + BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */ + + /* Allow the packet to pass */ + BPF_MOV64_IMM(BPF_REG_0, 1), + }; + + /* Jump label fixup */ + insn[0].off = ELEMENTSOF(insn) - 1; + + r = bpf_program_add_instructions(p, insn, ELEMENTSOF(insn)); + if (r < 0) + return r; + } + + do { + /* + * Exit from the eBPF program, R0 contains the verdict. + * 0 means the packet is denied, 1 means the packet may pass. + */ + const struct bpf_insn insn[] = { + BPF_EXIT_INSN() + }; + + r = bpf_program_add_instructions(p, insn, ELEMENTSOF(insn)); + if (r < 0) + return r; + } while (false); + + *ret = TAKE_PTR(p); + + return 0; +} + +static int bpf_firewall_count_access_items(IPAddressAccessItem *list, size_t *n_ipv4, size_t *n_ipv6) { + IPAddressAccessItem *a; + + assert(n_ipv4); + assert(n_ipv6); + + LIST_FOREACH(items, a, list) { + switch (a->family) { + + case AF_INET: + (*n_ipv4)++; + break; + + case AF_INET6: + (*n_ipv6)++; + break; + + default: + return -EAFNOSUPPORT; + } + } + + return 0; +} + +static int bpf_firewall_add_access_items( + IPAddressAccessItem *list, + int ipv4_map_fd, + int ipv6_map_fd, + int verdict) { + + struct bpf_lpm_trie_key *key_ipv4, *key_ipv6; + uint64_t value = verdict; + IPAddressAccessItem *a; + int r; + + key_ipv4 = alloca0(offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t)); + key_ipv6 = alloca0(offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t) * 4); + + LIST_FOREACH(items, a, list) { + switch (a->family) { + + case AF_INET: + key_ipv4->prefixlen = a->prefixlen; + memcpy(key_ipv4->data, &a->address, sizeof(uint32_t)); + + r = bpf_map_update_element(ipv4_map_fd, key_ipv4, &value); + if (r < 0) + return r; + + break; + + case AF_INET6: + key_ipv6->prefixlen = a->prefixlen; + memcpy(key_ipv6->data, &a->address, 4 * sizeof(uint32_t)); + + r = bpf_map_update_element(ipv6_map_fd, key_ipv6, &value); + if (r < 0) + return r; + + break; + + default: + return -EAFNOSUPPORT; + } + } + + return 0; +} + +static int bpf_firewall_prepare_access_maps( + Unit *u, + int verdict, + int *ret_ipv4_map_fd, + int *ret_ipv6_map_fd, + bool *ret_has_any) { + + _cleanup_close_ int ipv4_map_fd = -1, ipv6_map_fd = -1; + size_t n_ipv4 = 0, n_ipv6 = 0; + IPAddressAccessItem *list; + Unit *p; + int r; + + assert(ret_ipv4_map_fd); + assert(ret_ipv6_map_fd); + assert(ret_has_any); + + for (p = u; p; p = UNIT_DEREF(p->slice)) { + CGroupContext *cc; + + cc = unit_get_cgroup_context(p); + if (!cc) + continue; + + list = verdict == ACCESS_ALLOWED ? cc->ip_address_allow : cc->ip_address_deny; + + bpf_firewall_count_access_items(list, &n_ipv4, &n_ipv6); + + /* Skip making the LPM trie map in cases where we are using "any" in order to hack around + * needing CAP_SYS_ADMIN for allocating LPM trie map. */ + if (ip_address_access_item_is_any(list)) { + *ret_has_any = true; + return 0; + } + } + + if (n_ipv4 > 0) { + ipv4_map_fd = bpf_map_new( + BPF_MAP_TYPE_LPM_TRIE, + offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t), + sizeof(uint64_t), + n_ipv4, + BPF_F_NO_PREALLOC); + if (ipv4_map_fd < 0) + return ipv4_map_fd; + } + + if (n_ipv6 > 0) { + ipv6_map_fd = bpf_map_new( + BPF_MAP_TYPE_LPM_TRIE, + offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t)*4, + sizeof(uint64_t), + n_ipv6, + BPF_F_NO_PREALLOC); + if (ipv6_map_fd < 0) + return ipv6_map_fd; + } + + for (p = u; p; p = UNIT_DEREF(p->slice)) { + CGroupContext *cc; + + cc = unit_get_cgroup_context(p); + if (!cc) + continue; + + r = bpf_firewall_add_access_items(verdict == ACCESS_ALLOWED ? cc->ip_address_allow : cc->ip_address_deny, + ipv4_map_fd, ipv6_map_fd, verdict); + if (r < 0) + return r; + } + + *ret_ipv4_map_fd = TAKE_FD(ipv4_map_fd); + *ret_ipv6_map_fd = TAKE_FD(ipv6_map_fd); + *ret_has_any = false; + return 0; +} + +static int bpf_firewall_prepare_accounting_maps(Unit *u, bool enabled, int *fd_ingress, int *fd_egress) { + int r; + + assert(u); + assert(fd_ingress); + assert(fd_egress); + + if (enabled) { + if (*fd_ingress < 0) { + r = bpf_map_new(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(uint64_t), 2, 0); + if (r < 0) + return r; + + *fd_ingress = r; + } + + if (*fd_egress < 0) { + + r = bpf_map_new(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(uint64_t), 2, 0); + if (r < 0) + return r; + + *fd_egress = r; + } + + } else { + *fd_ingress = safe_close(*fd_ingress); + *fd_egress = safe_close(*fd_egress); + + zero(u->ip_accounting_extra); + } + + return 0; +} + +int bpf_firewall_compile(Unit *u) { + CGroupContext *cc; + int r, supported; + bool ip_allow_any = false, ip_deny_any = false; + + assert(u); + + cc = unit_get_cgroup_context(u); + if (!cc) + return -EINVAL; + + supported = bpf_firewall_supported(); + if (supported < 0) + return supported; + if (supported == BPF_FIREWALL_UNSUPPORTED) + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "BPF firewalling not supported on this manager, proceeding without."); + if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && u->type == UNIT_SLICE) + /* If BPF_F_ALLOW_MULTI is not supported we don't support any BPF magic on inner nodes (i.e. on slice + * units), since that would mean leaf nodes couldn't do any BPF anymore at all. Under the assumption + * that BPF is more interesting on leaf nodes we hence avoid it on inner nodes in that case. This is + * consistent with old systemd behaviour from before v238, where BPF wasn't supported in inner nodes at + * all, either. */ + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "BPF_F_ALLOW_MULTI is not supported on this manager, not doing BPF firewall on slice units."); + + /* Note that when we compile a new firewall we first flush out the access maps and the BPF programs themselves, + * but we reuse the the accounting maps. That way the firewall in effect always maps to the actual + * configuration, but we don't flush out the accounting unnecessarily */ + + u->ip_bpf_ingress = bpf_program_unref(u->ip_bpf_ingress); + u->ip_bpf_egress = bpf_program_unref(u->ip_bpf_egress); + + u->ipv4_allow_map_fd = safe_close(u->ipv4_allow_map_fd); + u->ipv4_deny_map_fd = safe_close(u->ipv4_deny_map_fd); + + u->ipv6_allow_map_fd = safe_close(u->ipv6_allow_map_fd); + u->ipv6_deny_map_fd = safe_close(u->ipv6_deny_map_fd); + + if (u->type != UNIT_SLICE) { + /* In inner nodes we only do accounting, we do not actually bother with access control. However, leaf + * nodes will incorporate all IP access rules set on all their parent nodes. This has the benefit that + * they can optionally cancel out system-wide rules. Since inner nodes can't contain processes this + * means that all configure IP access rules *will* take effect on processes, even though we never + * compile them for inner nodes. */ + + r = bpf_firewall_prepare_access_maps(u, ACCESS_ALLOWED, &u->ipv4_allow_map_fd, &u->ipv6_allow_map_fd, &ip_allow_any); + if (r < 0) + return log_unit_error_errno(u, r, "Preparation of eBPF allow maps failed: %m"); + + r = bpf_firewall_prepare_access_maps(u, ACCESS_DENIED, &u->ipv4_deny_map_fd, &u->ipv6_deny_map_fd, &ip_deny_any); + if (r < 0) + return log_unit_error_errno(u, r, "Preparation of eBPF deny maps failed: %m"); + } + + r = bpf_firewall_prepare_accounting_maps(u, cc->ip_accounting, &u->ip_accounting_ingress_map_fd, &u->ip_accounting_egress_map_fd); + if (r < 0) + return log_unit_error_errno(u, r, "Preparation of eBPF accounting maps failed: %m"); + + r = bpf_firewall_compile_bpf(u, true, &u->ip_bpf_ingress, ip_allow_any, ip_deny_any); + if (r < 0) + return log_unit_error_errno(u, r, "Compilation for ingress BPF program failed: %m"); + + r = bpf_firewall_compile_bpf(u, false, &u->ip_bpf_egress, ip_allow_any, ip_deny_any); + if (r < 0) + return log_unit_error_errno(u, r, "Compilation for egress BPF program failed: %m"); + + return 0; +} + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(filter_prog_hash_ops, void, trivial_hash_func, trivial_compare_func, BPFProgram, bpf_program_unref); + +static int load_bpf_progs_from_fs_to_set(Unit *u, char **filter_paths, Set **set) { + char **bpf_fs_path; + + set_clear(*set); + + STRV_FOREACH(bpf_fs_path, filter_paths) { + _cleanup_free_ BPFProgram *prog = NULL; + int r; + + r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &prog); + if (r < 0) + return log_unit_error_errno(u, r, "Can't allocate CGROUP SKB BPF program: %m"); + + r = bpf_program_load_from_bpf_fs(prog, *bpf_fs_path); + if (r < 0) + return log_unit_error_errno(u, r, "Loading of ingress BPF program %s failed: %m", *bpf_fs_path); + + r = set_ensure_allocated(set, &filter_prog_hash_ops); + if (r < 0) + return log_unit_error_errno(u, r, "Can't allocate BPF program set: %m"); + + r = set_put(*set, prog); + if (r < 0) + return log_unit_error_errno(u, r, "Can't add program to BPF program set: %m"); + TAKE_PTR(prog); + } + + return 0; +} + +int bpf_firewall_load_custom(Unit *u) { + CGroupContext *cc; + int r, supported; + + assert(u); + + cc = unit_get_cgroup_context(u); + if (!cc) + return 0; + + if (!(cc->ip_filters_ingress || cc->ip_filters_egress)) + return 0; + + supported = bpf_firewall_supported(); + if (supported < 0) + return supported; + + if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI) + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI not supported on this manager, cannot attach custom BPF programs."); + + r = load_bpf_progs_from_fs_to_set(u, cc->ip_filters_ingress, &u->ip_bpf_custom_ingress); + if (r < 0) + return r; + r = load_bpf_progs_from_fs_to_set(u, cc->ip_filters_egress, &u->ip_bpf_custom_egress); + if (r < 0) + return r; + + return 0; +} + +static int attach_custom_bpf_progs(Unit *u, const char *path, int attach_type, Set **set, Set **set_installed) { + BPFProgram *prog; + Iterator i; + int r; + + assert(u); + + set_clear(*set_installed); + + SET_FOREACH(prog, *set, i) { + r = bpf_program_cgroup_attach(prog, attach_type, path, BPF_F_ALLOW_MULTI); + if (r < 0) + return log_unit_error_errno(u, r, "Attaching custom egress BPF program to cgroup %s failed: %m", path); + /* Remember that these BPF programs are installed now. */ + r = set_ensure_allocated(set_installed, &filter_prog_hash_ops); + if (r < 0) + return log_unit_error_errno(u, r, "Can't allocate BPF program set: %m"); + + r = set_put(*set_installed, prog); + if (r < 0) + return log_unit_error_errno(u, r, "Can't add program to BPF program set: %m"); + bpf_program_ref(prog); + } + + return 0; +} + +int bpf_firewall_install(Unit *u) { + _cleanup_free_ char *path = NULL; + CGroupContext *cc; + int r, supported; + uint32_t flags; + + assert(u); + + cc = unit_get_cgroup_context(u); + if (!cc) + return -EINVAL; + if (!u->cgroup_path) + return -EINVAL; + if (!u->cgroup_realized) + return -EINVAL; + + supported = bpf_firewall_supported(); + if (supported < 0) + return supported; + if (supported == BPF_FIREWALL_UNSUPPORTED) { + log_unit_debug(u, "BPF firewalling not supported on this manager, proceeding without."); + return -EOPNOTSUPP; + } + if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && u->type == UNIT_SLICE) { + log_unit_debug(u, "BPF_F_ALLOW_MULTI is not supported on this manager, not doing BPF firewall on slice units."); + return -EOPNOTSUPP; + } + if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && + (!set_isempty(u->ip_bpf_custom_ingress) || !set_isempty(u->ip_bpf_custom_egress))) + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI not supported on this manager, cannot attach custom BPF programs."); + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &path); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to determine cgroup path: %m"); + + flags = (supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI && + (u->type == UNIT_SLICE || unit_cgroup_delegate(u))) ? BPF_F_ALLOW_MULTI : 0; + + /* Unref the old BPF program (which will implicitly detach it) right before attaching the new program, to + * minimize the time window when we don't account for IP traffic. */ + u->ip_bpf_egress_installed = bpf_program_unref(u->ip_bpf_egress_installed); + u->ip_bpf_ingress_installed = bpf_program_unref(u->ip_bpf_ingress_installed); + + if (u->ip_bpf_egress) { + r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path, + flags | (set_isempty(u->ip_bpf_custom_egress) ? 0 : BPF_F_ALLOW_MULTI)); + if (r < 0) + return log_unit_error_errno(u, r, "Attaching egress BPF program to cgroup %s failed: %m", path); + + /* Remember that this BPF program is installed now. */ + u->ip_bpf_egress_installed = bpf_program_ref(u->ip_bpf_egress); + } + + if (u->ip_bpf_ingress) { + r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path, + flags | (set_isempty(u->ip_bpf_custom_ingress) ? 0 : BPF_F_ALLOW_MULTI)); + if (r < 0) + return log_unit_error_errno(u, r, "Attaching ingress BPF program to cgroup %s failed: %m", path); + + u->ip_bpf_ingress_installed = bpf_program_ref(u->ip_bpf_ingress); + } + + r = attach_custom_bpf_progs(u, path, BPF_CGROUP_INET_EGRESS, &u->ip_bpf_custom_egress, &u->ip_bpf_custom_egress_installed); + if (r < 0) + return r; + + r = attach_custom_bpf_progs(u, path, BPF_CGROUP_INET_INGRESS, &u->ip_bpf_custom_ingress, &u->ip_bpf_custom_ingress_installed); + if (r < 0) + return r; + + return 0; +} + +int bpf_firewall_read_accounting(int map_fd, uint64_t *ret_bytes, uint64_t *ret_packets) { + uint64_t key, packets; + int r; + + if (map_fd < 0) + return -EBADF; + + if (ret_packets) { + key = MAP_KEY_PACKETS; + r = bpf_map_lookup_element(map_fd, &key, &packets); + if (r < 0) + return r; + } + + if (ret_bytes) { + key = MAP_KEY_BYTES; + r = bpf_map_lookup_element(map_fd, &key, ret_bytes); + if (r < 0) + return r; + } + + if (ret_packets) + *ret_packets = packets; + + return 0; +} + +int bpf_firewall_reset_accounting(int map_fd) { + uint64_t key, value = 0; + int r; + + if (map_fd < 0) + return -EBADF; + + key = MAP_KEY_PACKETS; + r = bpf_map_update_element(map_fd, &key, &value); + if (r < 0) + return r; + + key = MAP_KEY_BYTES; + return bpf_map_update_element(map_fd, &key, &value); +} + +static int bpf_firewall_unsupported_reason = 0; + +int bpf_firewall_supported(void) { + const struct bpf_insn trivial[] = { + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN() + }; + + _cleanup_(bpf_program_unrefp) BPFProgram *program = NULL; + static int supported = -1; + union bpf_attr attr; + int r; + + /* Checks whether BPF firewalling is supported. For this, we check the following things: + * + * - whether the unified hierarchy is being used + * - the BPF implementation in the kernel supports BPF_PROG_TYPE_CGROUP_SKB programs, which we require + * - the BPF implementation in the kernel supports the BPF_PROG_DETACH call, which we require + */ + if (supported >= 0) + return supported; + + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) + return log_error_errno(r, "Can't determine whether the unified hierarchy is used: %m"); + if (r == 0) { + bpf_firewall_unsupported_reason = + log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), + "Not running with unified cgroups, BPF firewalling is not supported."); + return supported = BPF_FIREWALL_UNSUPPORTED; + } + + r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &program); + if (r < 0) { + bpf_firewall_unsupported_reason = + log_debug_errno(r, "Can't allocate CGROUP SKB BPF program, BPF firewalling is not supported: %m"); + return supported = BPF_FIREWALL_UNSUPPORTED; + } + + r = bpf_program_add_instructions(program, trivial, ELEMENTSOF(trivial)); + if (r < 0) { + bpf_firewall_unsupported_reason = + log_debug_errno(r, "Can't add trivial instructions to CGROUP SKB BPF program, BPF firewalling is not supported: %m"); + return supported = BPF_FIREWALL_UNSUPPORTED; + } + + r = bpf_program_load_kernel(program, NULL, 0); + if (r < 0) { + bpf_firewall_unsupported_reason = + log_debug_errno(r, "Can't load kernel CGROUP SKB BPF program, BPF firewalling is not supported: %m"); + return supported = BPF_FIREWALL_UNSUPPORTED; + } + + /* Unfortunately the kernel allows us to create BPF_PROG_TYPE_CGROUP_SKB programs even when CONFIG_CGROUP_BPF + * is turned off at kernel compilation time. This sucks of course: why does it allow us to create a cgroup BPF + * program if we can't do a thing with it later? + * + * We detect this case by issuing the BPF_PROG_DETACH bpf() call with invalid file descriptors: if + * CONFIG_CGROUP_BPF is turned off, then the call will fail early with EINVAL. If it is turned on the + * parameters are validated however, and that'll fail with EBADF then. */ + + attr = (union bpf_attr) { + .attach_type = BPF_CGROUP_INET_EGRESS, + .target_fd = -1, + .attach_bpf_fd = -1, + }; + + if (bpf(BPF_PROG_DETACH, &attr, sizeof(attr)) < 0) { + if (errno != EBADF) { + bpf_firewall_unsupported_reason = + log_debug_errno(errno, "Didn't get EBADF from BPF_PROG_DETACH, BPF firewalling is not supported: %m"); + return supported = BPF_FIREWALL_UNSUPPORTED; + } + + /* YAY! */ + } else { + log_debug("Wut? Kernel accepted our invalid BPF_PROG_DETACH call? Something is weird, assuming BPF firewalling is broken and hence not supported."); + return supported = BPF_FIREWALL_UNSUPPORTED; + } + + /* So now we know that the BPF program is generally available, let's see if BPF_F_ALLOW_MULTI is also supported + * (which was added in kernel 4.15). We use a similar logic as before, but this time we use the BPF_PROG_ATTACH + * bpf() call and the BPF_F_ALLOW_MULTI flags value. Since the flags are checked early in the system call we'll + * get EINVAL if it's not supported, and EBADF as before if it is available. */ + + attr = (union bpf_attr) { + .attach_type = BPF_CGROUP_INET_EGRESS, + .target_fd = -1, + .attach_bpf_fd = -1, + .attach_flags = BPF_F_ALLOW_MULTI, + }; + + if (bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)) < 0) { + if (errno == EBADF) { + log_debug_errno(errno, "Got EBADF when using BPF_F_ALLOW_MULTI, which indicates it is supported. Yay!"); + return supported = BPF_FIREWALL_SUPPORTED_WITH_MULTI; + } + + if (errno == EINVAL) + log_debug_errno(errno, "Got EINVAL error when using BPF_F_ALLOW_MULTI, which indicates it's not supported."); + else + log_debug_errno(errno, "Got unexpected error when using BPF_F_ALLOW_MULTI, assuming it's not supported: %m"); + + return supported = BPF_FIREWALL_SUPPORTED; + } else { + log_debug("Wut? Kernel accepted our invalid BPF_PROG_ATTACH+BPF_F_ALLOW_MULTI call? Something is weird, assuming BPF firewalling is broken and hence not supported."); + return supported = BPF_FIREWALL_UNSUPPORTED; + } +} + +void emit_bpf_firewall_warning(Unit *u) { + static bool warned = false; + + if (!warned) { + bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container(); + + log_unit_full(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason, + "unit configures an IP firewall, but %s.\n" + "(This warning is only shown for the first unit using IP firewalling.)", + getuid() != 0 ? "not running as root" : + "the local system does not support BPF/cgroup firewalling"); + warned = true; + } +} diff --git a/src/core/bpf-firewall.h b/src/core/bpf-firewall.h new file mode 100644 index 00000000..f1460d98 --- /dev/null +++ b/src/core/bpf-firewall.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "unit.h" + +enum { + BPF_FIREWALL_UNSUPPORTED = 0, + BPF_FIREWALL_SUPPORTED = 1, + BPF_FIREWALL_SUPPORTED_WITH_MULTI = 2, +}; + +int bpf_firewall_supported(void); + +int bpf_firewall_compile(Unit *u); +int bpf_firewall_install(Unit *u); +int bpf_firewall_load_custom(Unit *u); + +int bpf_firewall_read_accounting(int map_fd, uint64_t *ret_bytes, uint64_t *ret_packets); +int bpf_firewall_reset_accounting(int map_fd); + +void emit_bpf_firewall_warning(Unit *u); diff --git a/src/core/cgroup.c b/src/core/cgroup.c new file mode 100644 index 00000000..ef6e56a9 --- /dev/null +++ b/src/core/cgroup.c @@ -0,0 +1,3635 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "blockdev-util.h" +#include "bpf-devices.h" +#include "bpf-firewall.h" +#include "btrfs-util.h" +#include "bus-error.h" +#include "cgroup-setup.h" +#include "cgroup-util.h" +#include "cgroup.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "limits-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "procfs-util.h" +#include "special.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "virt.h" + +#define CGROUP_CPU_QUOTA_DEFAULT_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC) + +/* Returns the log level to use when cgroup attribute writes fail. When an attribute is missing or we have access + * problems we downgrade to LOG_DEBUG. This is supposed to be nice to container managers and kernels which want to mask + * out specific attributes from us. */ +#define LOG_LEVEL_CGROUP_WRITE(r) (IN_SET(abs(r), ENOENT, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING) + +uint64_t tasks_max_resolve(const TasksMax *tasks_max) { + if (tasks_max->scale == 0) + return tasks_max->value; + + return system_tasks_max_scale(tasks_max->value, tasks_max->scale); +} + +bool manager_owns_host_root_cgroup(Manager *m) { + assert(m); + + /* Returns true if we are managing the root cgroup. Note that it isn't sufficient to just check whether the + * group root path equals "/" since that will also be the case if CLONE_NEWCGROUP is in the mix. Since there's + * appears to be no nice way to detect whether we are in a CLONE_NEWCGROUP namespace we instead just check if + * we run in any kind of container virtualization. */ + + if (MANAGER_IS_USER(m)) + return false; + + if (detect_container() > 0) + return false; + + return empty_or_root(m->cgroup_root); +} + +bool unit_has_host_root_cgroup(Unit *u) { + assert(u); + + /* Returns whether this unit manages the root cgroup. This will return true if this unit is the root slice and + * the manager manages the root cgroup. */ + + if (!manager_owns_host_root_cgroup(u->manager)) + return false; + + return unit_has_name(u, SPECIAL_ROOT_SLICE); +} + +static int set_attribute_and_warn(Unit *u, const char *controller, const char *attribute, const char *value) { + int r; + + r = cg_set_attribute(controller, u->cgroup_path, attribute, value); + if (r < 0) + log_unit_full(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m", + strna(attribute), isempty(u->cgroup_path) ? "/" : u->cgroup_path, (int) strcspn(value, NEWLINE), value); + + return r; +} + +static void cgroup_compat_warn(void) { + static bool cgroup_compat_warned = false; + + if (cgroup_compat_warned) + return; + + log_warning("cgroup compatibility translation between legacy and unified hierarchy settings activated. " + "See cgroup-compat debug messages for details."); + + cgroup_compat_warned = true; +} + +#define log_cgroup_compat(unit, fmt, ...) do { \ + cgroup_compat_warn(); \ + log_unit_debug(unit, "cgroup-compat: " fmt, ##__VA_ARGS__); \ + } while (false) + +void cgroup_context_init(CGroupContext *c) { + assert(c); + + /* Initialize everything to the kernel defaults. */ + + *c = (CGroupContext) { + .cpu_weight = CGROUP_WEIGHT_INVALID, + .startup_cpu_weight = CGROUP_WEIGHT_INVALID, + .cpu_quota_per_sec_usec = USEC_INFINITY, + .cpu_quota_period_usec = USEC_INFINITY, + + .cpu_shares = CGROUP_CPU_SHARES_INVALID, + .startup_cpu_shares = CGROUP_CPU_SHARES_INVALID, + + .memory_high = CGROUP_LIMIT_MAX, + .memory_max = CGROUP_LIMIT_MAX, + .memory_swap_max = CGROUP_LIMIT_MAX, + + .memory_limit = CGROUP_LIMIT_MAX, + + .io_weight = CGROUP_WEIGHT_INVALID, + .startup_io_weight = CGROUP_WEIGHT_INVALID, + + .blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID, + .startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID, + + .tasks_max = TASKS_MAX_UNSET, + }; +} + +void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) { + assert(c); + assert(a); + + LIST_REMOVE(device_allow, c->device_allow, a); + free(a->path); + free(a); +} + +void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w) { + assert(c); + assert(w); + + LIST_REMOVE(device_weights, c->io_device_weights, w); + free(w->path); + free(w); +} + +void cgroup_context_free_io_device_latency(CGroupContext *c, CGroupIODeviceLatency *l) { + assert(c); + assert(l); + + LIST_REMOVE(device_latencies, c->io_device_latencies, l); + free(l->path); + free(l); +} + +void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l) { + assert(c); + assert(l); + + LIST_REMOVE(device_limits, c->io_device_limits, l); + free(l->path); + free(l); +} + +void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) { + assert(c); + assert(w); + + LIST_REMOVE(device_weights, c->blockio_device_weights, w); + free(w->path); + free(w); +} + +void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) { + assert(c); + assert(b); + + LIST_REMOVE(device_bandwidths, c->blockio_device_bandwidths, b); + free(b->path); + free(b); +} + +void cgroup_context_done(CGroupContext *c) { + assert(c); + + while (c->io_device_weights) + cgroup_context_free_io_device_weight(c, c->io_device_weights); + + while (c->io_device_latencies) + cgroup_context_free_io_device_latency(c, c->io_device_latencies); + + while (c->io_device_limits) + cgroup_context_free_io_device_limit(c, c->io_device_limits); + + while (c->blockio_device_weights) + cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights); + + while (c->blockio_device_bandwidths) + cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths); + + while (c->device_allow) + cgroup_context_free_device_allow(c, c->device_allow); + + c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow); + c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny); + + c->ip_filters_ingress = strv_free(c->ip_filters_ingress); + c->ip_filters_egress = strv_free(c->ip_filters_egress); + + cpu_set_reset(&c->cpuset_cpus); + cpu_set_reset(&c->cpuset_mems); +} + +static int unit_get_kernel_memory_limit(Unit *u, const char *file, uint64_t *ret) { + _cleanup_free_ char *raw_kval = NULL; + uint64_t kval; + int r; + + assert(u); + + if (!u->cgroup_realized) + return -EOWNERDEAD; + + r = cg_get_attribute("memory", u->cgroup_path, file, &raw_kval); + if (r < 0) + return r; + + if (streq(raw_kval, "max")) { + *ret = CGROUP_LIMIT_MAX; + return 0; + } + + r = safe_atou64(raw_kval, &kval); + if (r < 0) + return r; + + *ret = kval; + + return 0; +} + +static int unit_compare_memory_limit(Unit *u, const char *property_name, uint64_t *ret_unit_value, uint64_t *ret_kernel_value) { + CGroupContext *c; + CGroupMask m; + const char *file; + uint64_t unit_value; + int r; + + /* Compare kernel memcg configuration against our internal systemd state. Unsupported (and will + * return -ENODATA) on cgroup v1. + * + * Returns: + * + * <0: On error. + * 0: If the kernel memory setting doesn't match our configuration. + * >0: If the kernel memory setting matches our configuration. + * + * The following values are only guaranteed to be populated on return >=0: + * + * - ret_unit_value will contain our internal expected value for the unit, page-aligned. + * - ret_kernel_value will contain the actual value presented by the kernel. */ + + assert(u); + + r = cg_all_unified(); + if (r < 0) + return log_debug_errno(r, "Failed to determine cgroup hierarchy version: %m"); + + /* Unsupported on v1. + * + * We don't return ENOENT, since that could actually mask a genuine problem where somebody else has + * silently masked the controller. */ + if (r == 0) + return -ENODATA; + + /* The root slice doesn't have any controller files, so we can't compare anything. */ + if (unit_has_name(u, SPECIAL_ROOT_SLICE)) + return -ENODATA; + + /* It's possible to have MemoryFoo set without systemd wanting to have the memory controller enabled, + * for example, in the case of DisableControllers= or cgroup_disable on the kernel command line. To + * avoid specious errors in these scenarios, check that we even expect the memory controller to be + * enabled at all. */ + m = unit_get_target_mask(u); + if (!FLAGS_SET(m, CGROUP_MASK_MEMORY)) + return -ENODATA; + + c = unit_get_cgroup_context(u); + assert(c); + + if (streq(property_name, "MemoryLow")) { + unit_value = unit_get_ancestor_memory_low(u); + file = "memory.low"; + } else if (streq(property_name, "MemoryMin")) { + unit_value = unit_get_ancestor_memory_min(u); + file = "memory.min"; + } else if (streq(property_name, "MemoryHigh")) { + unit_value = c->memory_high; + file = "memory.high"; + } else if (streq(property_name, "MemoryMax")) { + unit_value = c->memory_max; + file = "memory.max"; + } else if (streq(property_name, "MemorySwapMax")) { + unit_value = c->memory_swap_max; + file = "memory.swap.max"; + } else + return -EINVAL; + + r = unit_get_kernel_memory_limit(u, file, ret_kernel_value); + if (r < 0) + return log_unit_debug_errno(u, r, "Failed to parse %s: %m", file); + + /* It's intended (soon) in a future kernel to not expose cgroup memory limits rounded to page + * boundaries, but instead separate the user-exposed limit, which is whatever userspace told us, from + * our internal page-counting. To support those future kernels, just check the value itself first + * without any page-alignment. */ + if (*ret_kernel_value == unit_value) { + *ret_unit_value = unit_value; + return 1; + } + + /* The current kernel behaviour, by comparison, is that even if you write a particular number of + * bytes into a cgroup memory file, it always returns that number page-aligned down (since the kernel + * internally stores cgroup limits in pages). As such, so long as it aligns properly, everything is + * cricket. */ + if (unit_value != CGROUP_LIMIT_MAX) + unit_value = PAGE_ALIGN_DOWN(unit_value); + + *ret_unit_value = unit_value; + + return *ret_kernel_value == *ret_unit_value; +} + +#define FORMAT_CGROUP_DIFF_MAX 128 + +static char *format_cgroup_memory_limit_comparison(char *buf, size_t l, Unit *u, const char *property_name) { + uint64_t kval, sval; + int r; + + assert(u); + assert(buf); + assert(l > 0); + + r = unit_compare_memory_limit(u, property_name, &sval, &kval); + + /* memory.swap.max is special in that it relies on CONFIG_MEMCG_SWAP (and the default swapaccount=1). + * In the absence of reliably being able to detect whether memcg swap support is available or not, + * only complain if the error is not ENOENT. */ + if (r > 0 || IN_SET(r, -ENODATA, -EOWNERDEAD) || + (r == -ENOENT && streq(property_name, "MemorySwapMax"))) { + buf[0] = 0; + return buf; + } + + if (r < 0) { + snprintf(buf, l, " (error getting kernel value: %s)", strerror_safe(r)); + return buf; + } + + snprintf(buf, l, " (different value in kernel: %" PRIu64 ")", kval); + + return buf; +} + +void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { + _cleanup_free_ char *disable_controllers_str = NULL, *cpuset_cpus = NULL, *cpuset_mems = NULL; + CGroupIODeviceLimit *il; + CGroupIODeviceWeight *iw; + CGroupIODeviceLatency *l; + CGroupBlockIODeviceBandwidth *b; + CGroupBlockIODeviceWeight *w; + CGroupDeviceAllow *a; + CGroupContext *c; + IPAddressAccessItem *iaai; + char **path; + char q[FORMAT_TIMESPAN_MAX]; + char v[FORMAT_TIMESPAN_MAX]; + + char cda[FORMAT_CGROUP_DIFF_MAX]; + char cdb[FORMAT_CGROUP_DIFF_MAX]; + char cdc[FORMAT_CGROUP_DIFF_MAX]; + char cdd[FORMAT_CGROUP_DIFF_MAX]; + char cde[FORMAT_CGROUP_DIFF_MAX]; + + assert(u); + assert(f); + + c = unit_get_cgroup_context(u); + assert(c); + + prefix = strempty(prefix); + + (void) cg_mask_to_string(c->disable_controllers, &disable_controllers_str); + + cpuset_cpus = cpu_set_to_range_string(&c->cpuset_cpus); + cpuset_mems = cpu_set_to_range_string(&c->cpuset_mems); + + fprintf(f, + "%sCPUAccounting: %s\n" + "%sIOAccounting: %s\n" + "%sBlockIOAccounting: %s\n" + "%sMemoryAccounting: %s\n" + "%sTasksAccounting: %s\n" + "%sIPAccounting: %s\n" + "%sCPUWeight: %" PRIu64 "\n" + "%sStartupCPUWeight: %" PRIu64 "\n" + "%sCPUShares: %" PRIu64 "\n" + "%sStartupCPUShares: %" PRIu64 "\n" + "%sCPUQuotaPerSecSec: %s\n" + "%sCPUQuotaPeriodSec: %s\n" + "%sAllowedCPUs: %s\n" + "%sAllowedMemoryNodes: %s\n" + "%sIOWeight: %" PRIu64 "\n" + "%sStartupIOWeight: %" PRIu64 "\n" + "%sBlockIOWeight: %" PRIu64 "\n" + "%sStartupBlockIOWeight: %" PRIu64 "\n" + "%sDefaultMemoryMin: %" PRIu64 "\n" + "%sDefaultMemoryLow: %" PRIu64 "\n" + "%sMemoryMin: %" PRIu64 "%s\n" + "%sMemoryLow: %" PRIu64 "%s\n" + "%sMemoryHigh: %" PRIu64 "%s\n" + "%sMemoryMax: %" PRIu64 "%s\n" + "%sMemorySwapMax: %" PRIu64 "%s\n" + "%sMemoryLimit: %" PRIu64 "\n" + "%sTasksMax: %" PRIu64 "\n" + "%sDevicePolicy: %s\n" + "%sDisableControllers: %s\n" + "%sDelegate: %s\n", + prefix, yes_no(c->cpu_accounting), + prefix, yes_no(c->io_accounting), + prefix, yes_no(c->blockio_accounting), + prefix, yes_no(c->memory_accounting), + prefix, yes_no(c->tasks_accounting), + prefix, yes_no(c->ip_accounting), + prefix, c->cpu_weight, + prefix, c->startup_cpu_weight, + prefix, c->cpu_shares, + prefix, c->startup_cpu_shares, + prefix, format_timespan(q, sizeof(q), c->cpu_quota_per_sec_usec, 1), + prefix, format_timespan(v, sizeof(v), c->cpu_quota_period_usec, 1), + prefix, strempty(cpuset_cpus), + prefix, strempty(cpuset_mems), + prefix, c->io_weight, + prefix, c->startup_io_weight, + prefix, c->blockio_weight, + prefix, c->startup_blockio_weight, + prefix, c->default_memory_min, + prefix, c->default_memory_low, + prefix, c->memory_min, format_cgroup_memory_limit_comparison(cda, sizeof(cda), u, "MemoryMin"), + prefix, c->memory_low, format_cgroup_memory_limit_comparison(cdb, sizeof(cdb), u, "MemoryLow"), + prefix, c->memory_high, format_cgroup_memory_limit_comparison(cdc, sizeof(cdc), u, "MemoryHigh"), + prefix, c->memory_max, format_cgroup_memory_limit_comparison(cdd, sizeof(cdd), u, "MemoryMax"), + prefix, c->memory_swap_max, format_cgroup_memory_limit_comparison(cde, sizeof(cde), u, "MemorySwapMax"), + prefix, c->memory_limit, + prefix, tasks_max_resolve(&c->tasks_max), + prefix, cgroup_device_policy_to_string(c->device_policy), + prefix, strempty(disable_controllers_str), + prefix, yes_no(c->delegate)); + + if (c->delegate) { + _cleanup_free_ char *t = NULL; + + (void) cg_mask_to_string(c->delegate_controllers, &t); + + fprintf(f, "%sDelegateControllers: %s\n", + prefix, + strempty(t)); + } + + LIST_FOREACH(device_allow, a, c->device_allow) + fprintf(f, + "%sDeviceAllow: %s %s%s%s\n", + prefix, + a->path, + a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : ""); + + LIST_FOREACH(device_weights, iw, c->io_device_weights) + fprintf(f, + "%sIODeviceWeight: %s %" PRIu64 "\n", + prefix, + iw->path, + iw->weight); + + LIST_FOREACH(device_latencies, l, c->io_device_latencies) + fprintf(f, + "%sIODeviceLatencyTargetSec: %s %s\n", + prefix, + l->path, + format_timespan(q, sizeof(q), l->target_usec, 1)); + + LIST_FOREACH(device_limits, il, c->io_device_limits) { + char buf[FORMAT_BYTES_MAX]; + CGroupIOLimitType type; + + for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++) + if (il->limits[type] != cgroup_io_limit_defaults[type]) + fprintf(f, + "%s%s: %s %s\n", + prefix, + cgroup_io_limit_type_to_string(type), + il->path, + format_bytes(buf, sizeof(buf), il->limits[type])); + } + + LIST_FOREACH(device_weights, w, c->blockio_device_weights) + fprintf(f, + "%sBlockIODeviceWeight: %s %" PRIu64, + prefix, + w->path, + w->weight); + + LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { + char buf[FORMAT_BYTES_MAX]; + + if (b->rbps != CGROUP_LIMIT_MAX) + fprintf(f, + "%sBlockIOReadBandwidth: %s %s\n", + prefix, + b->path, + format_bytes(buf, sizeof(buf), b->rbps)); + if (b->wbps != CGROUP_LIMIT_MAX) + fprintf(f, + "%sBlockIOWriteBandwidth: %s %s\n", + prefix, + b->path, + format_bytes(buf, sizeof(buf), b->wbps)); + } + + LIST_FOREACH(items, iaai, c->ip_address_allow) { + _cleanup_free_ char *k = NULL; + + (void) in_addr_to_string(iaai->family, &iaai->address, &k); + fprintf(f, "%sIPAddressAllow: %s/%u\n", prefix, strnull(k), iaai->prefixlen); + } + + LIST_FOREACH(items, iaai, c->ip_address_deny) { + _cleanup_free_ char *k = NULL; + + (void) in_addr_to_string(iaai->family, &iaai->address, &k); + fprintf(f, "%sIPAddressDeny: %s/%u\n", prefix, strnull(k), iaai->prefixlen); + } + + STRV_FOREACH(path, c->ip_filters_ingress) + fprintf(f, "%sIPIngressFilterPath: %s\n", prefix, *path); + + STRV_FOREACH(path, c->ip_filters_egress) + fprintf(f, "%sIPEgressFilterPath: %s\n", prefix, *path); +} + +int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode) { + _cleanup_free_ CGroupDeviceAllow *a = NULL; + _cleanup_free_ char *d = NULL; + + assert(c); + assert(dev); + assert(isempty(mode) || in_charset(mode, "rwm")); + + a = new(CGroupDeviceAllow, 1); + if (!a) + return -ENOMEM; + + d = strdup(dev); + if (!d) + return -ENOMEM; + + *a = (CGroupDeviceAllow) { + .path = TAKE_PTR(d), + .r = isempty(mode) || strchr(mode, 'r'), + .w = isempty(mode) || strchr(mode, 'w'), + .m = isempty(mode) || strchr(mode, 'm'), + }; + + LIST_PREPEND(device_allow, c->device_allow, a); + TAKE_PTR(a); + + return 0; +} + +#define UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(entry) \ + uint64_t unit_get_ancestor_##entry(Unit *u) { \ + CGroupContext *c; \ + \ + /* 1. Is entry set in this unit? If so, use that. \ + * 2. Is the default for this entry set in any \ + * ancestor? If so, use that. \ + * 3. Otherwise, return CGROUP_LIMIT_MIN. */ \ + \ + assert(u); \ + \ + c = unit_get_cgroup_context(u); \ + if (c && c->entry##_set) \ + return c->entry; \ + \ + while ((u = UNIT_DEREF(u->slice))) { \ + c = unit_get_cgroup_context(u); \ + if (c && c->default_##entry##_set) \ + return c->default_##entry; \ + } \ + \ + /* We've reached the root, but nobody had default for \ + * this entry set, so set it to the kernel default. */ \ + return CGROUP_LIMIT_MIN; \ +} + +UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_low); +UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_min); + +static void cgroup_xattr_apply(Unit *u) { + char ids[SD_ID128_STRING_MAX]; + int r; + + assert(u); + + if (!MANAGER_IS_SYSTEM(u->manager)) + return; + + if (!sd_id128_is_null(u->invocation_id)) { + r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, + "trusted.invocation_id", + sd_id128_to_string(u->invocation_id, ids), 32, + 0); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", u->cgroup_path); + } + + if (unit_cgroup_delegate(u)) { + r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, + "trusted.delegate", + "1", 1, + 0); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to set delegate flag on control group %s, ignoring: %m", u->cgroup_path); + } else { + r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "trusted.delegate"); + if (r != -ENODATA) + log_unit_debug_errno(u, r, "Failed to remove delegate flag on control group %s, ignoring: %m", u->cgroup_path); + } +} + +static int lookup_block_device(const char *p, dev_t *ret) { + dev_t rdev, dev = 0; + mode_t mode; + int r; + + assert(p); + assert(ret); + + r = device_path_parse_major_minor(p, &mode, &rdev); + if (r == -ENODEV) { /* not a parsable device node, need to go to disk */ + struct stat st; + if (stat(p, &st) < 0) + return log_warning_errno(errno, "Couldn't stat device '%s': %m", p); + rdev = (dev_t)st.st_rdev; + dev = (dev_t)st.st_dev; + mode = st.st_mode; + } else if (r < 0) + return log_warning_errno(r, "Failed to parse major/minor from path '%s': %m", p); + + if (S_ISCHR(mode)) { + log_warning("Device node '%s' is a character device, but block device needed.", p); + return -ENOTBLK; + } else if (S_ISBLK(mode)) + *ret = rdev; + else if (major(dev) != 0) + *ret = dev; /* If this is not a device node then use the block device this file is stored on */ + else { + /* If this is btrfs, getting the backing block device is a bit harder */ + r = btrfs_get_block_device(p, ret); + if (r < 0 && r != -ENOTTY) + return log_warning_errno(r, "Failed to determine block device backing btrfs file system '%s': %m", p); + if (r == -ENOTTY) { + log_warning("'%s' is not a block device node, and file system block device cannot be determined or is not local.", p); + return -ENODEV; + } + } + + /* If this is a LUKS device, try to get the originating block device */ + (void) block_get_originating(*ret, ret); + + /* If this is a partition, try to get the originating block device */ + (void) block_get_whole_disk(*ret, ret); + return 0; +} + +static bool cgroup_context_has_cpu_weight(CGroupContext *c) { + return c->cpu_weight != CGROUP_WEIGHT_INVALID || + c->startup_cpu_weight != CGROUP_WEIGHT_INVALID; +} + +static bool cgroup_context_has_cpu_shares(CGroupContext *c) { + return c->cpu_shares != CGROUP_CPU_SHARES_INVALID || + c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID; +} + +static uint64_t cgroup_context_cpu_weight(CGroupContext *c, ManagerState state) { + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + c->startup_cpu_weight != CGROUP_WEIGHT_INVALID) + return c->startup_cpu_weight; + else if (c->cpu_weight != CGROUP_WEIGHT_INVALID) + return c->cpu_weight; + else + return CGROUP_WEIGHT_DEFAULT; +} + +static uint64_t cgroup_context_cpu_shares(CGroupContext *c, ManagerState state) { + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID) + return c->startup_cpu_shares; + else if (c->cpu_shares != CGROUP_CPU_SHARES_INVALID) + return c->cpu_shares; + else + return CGROUP_CPU_SHARES_DEFAULT; +} + +usec_t cgroup_cpu_adjust_period(usec_t period, usec_t quota, usec_t resolution, usec_t max_period) { + /* kernel uses a minimum resolution of 1ms, so both period and (quota * period) + * need to be higher than that boundary. quota is specified in USecPerSec. + * Additionally, period must be at most max_period. */ + assert(quota > 0); + + return MIN(MAX3(period, resolution, resolution * USEC_PER_SEC / quota), max_period); +} + +static usec_t cgroup_cpu_adjust_period_and_log(Unit *u, usec_t period, usec_t quota) { + usec_t new_period; + + if (quota == USEC_INFINITY) + /* Always use default period for infinity quota. */ + return CGROUP_CPU_QUOTA_DEFAULT_PERIOD_USEC; + + if (period == USEC_INFINITY) + /* Default period was requested. */ + period = CGROUP_CPU_QUOTA_DEFAULT_PERIOD_USEC; + + /* Clamp to interval [1ms, 1s] */ + new_period = cgroup_cpu_adjust_period(period, quota, USEC_PER_MSEC, USEC_PER_SEC); + + if (new_period != period) { + char v[FORMAT_TIMESPAN_MAX]; + log_unit_full(u, u->warned_clamping_cpu_quota_period ? LOG_DEBUG : LOG_WARNING, 0, + "Clamping CPU interval for cpu.max: period is now %s", + format_timespan(v, sizeof(v), new_period, 1)); + u->warned_clamping_cpu_quota_period = true; + } + + return new_period; +} + +static void cgroup_apply_unified_cpu_weight(Unit *u, uint64_t weight) { + char buf[DECIMAL_STR_MAX(uint64_t) + 2]; + + xsprintf(buf, "%" PRIu64 "\n", weight); + (void) set_attribute_and_warn(u, "cpu", "cpu.weight", buf); +} + +static void cgroup_apply_unified_cpu_quota(Unit *u, usec_t quota, usec_t period) { + char buf[(DECIMAL_STR_MAX(usec_t) + 1) * 2 + 1]; + + period = cgroup_cpu_adjust_period_and_log(u, period, quota); + if (quota != USEC_INFINITY) + xsprintf(buf, USEC_FMT " " USEC_FMT "\n", + MAX(quota * period / USEC_PER_SEC, USEC_PER_MSEC), period); + else + xsprintf(buf, "max " USEC_FMT "\n", period); + (void) set_attribute_and_warn(u, "cpu", "cpu.max", buf); +} + +static void cgroup_apply_legacy_cpu_shares(Unit *u, uint64_t shares) { + char buf[DECIMAL_STR_MAX(uint64_t) + 2]; + + xsprintf(buf, "%" PRIu64 "\n", shares); + (void) set_attribute_and_warn(u, "cpu", "cpu.shares", buf); +} + +static void cgroup_apply_legacy_cpu_quota(Unit *u, usec_t quota, usec_t period) { + char buf[DECIMAL_STR_MAX(usec_t) + 2]; + + period = cgroup_cpu_adjust_period_and_log(u, period, quota); + + xsprintf(buf, USEC_FMT "\n", period); + (void) set_attribute_and_warn(u, "cpu", "cpu.cfs_period_us", buf); + + if (quota != USEC_INFINITY) { + xsprintf(buf, USEC_FMT "\n", MAX(quota * period / USEC_PER_SEC, USEC_PER_MSEC)); + (void) set_attribute_and_warn(u, "cpu", "cpu.cfs_quota_us", buf); + } else + (void) set_attribute_and_warn(u, "cpu", "cpu.cfs_quota_us", "-1\n"); +} + +static uint64_t cgroup_cpu_shares_to_weight(uint64_t shares) { + return CLAMP(shares * CGROUP_WEIGHT_DEFAULT / CGROUP_CPU_SHARES_DEFAULT, + CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_MAX); +} + +static uint64_t cgroup_cpu_weight_to_shares(uint64_t weight) { + return CLAMP(weight * CGROUP_CPU_SHARES_DEFAULT / CGROUP_WEIGHT_DEFAULT, + CGROUP_CPU_SHARES_MIN, CGROUP_CPU_SHARES_MAX); +} + +static void cgroup_apply_unified_cpuset(Unit *u, const CPUSet *cpus, const char *name) { + _cleanup_free_ char *buf = NULL; + + buf = cpu_set_to_range_string(cpus); + if (!buf) { + log_oom(); + return; + } + + (void) set_attribute_and_warn(u, "cpuset", name, buf); +} + +static bool cgroup_context_has_io_config(CGroupContext *c) { + return c->io_accounting || + c->io_weight != CGROUP_WEIGHT_INVALID || + c->startup_io_weight != CGROUP_WEIGHT_INVALID || + c->io_device_weights || + c->io_device_latencies || + c->io_device_limits; +} + +static bool cgroup_context_has_blockio_config(CGroupContext *c) { + return c->blockio_accounting || + c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID || + c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID || + c->blockio_device_weights || + c->blockio_device_bandwidths; +} + +static uint64_t cgroup_context_io_weight(CGroupContext *c, ManagerState state) { + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + c->startup_io_weight != CGROUP_WEIGHT_INVALID) + return c->startup_io_weight; + else if (c->io_weight != CGROUP_WEIGHT_INVALID) + return c->io_weight; + else + return CGROUP_WEIGHT_DEFAULT; +} + +static uint64_t cgroup_context_blkio_weight(CGroupContext *c, ManagerState state) { + if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) && + c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID) + return c->startup_blockio_weight; + else if (c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID) + return c->blockio_weight; + else + return CGROUP_BLKIO_WEIGHT_DEFAULT; +} + +static uint64_t cgroup_weight_blkio_to_io(uint64_t blkio_weight) { + return CLAMP(blkio_weight * CGROUP_WEIGHT_DEFAULT / CGROUP_BLKIO_WEIGHT_DEFAULT, + CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_MAX); +} + +static uint64_t cgroup_weight_io_to_blkio(uint64_t io_weight) { + return CLAMP(io_weight * CGROUP_BLKIO_WEIGHT_DEFAULT / CGROUP_WEIGHT_DEFAULT, + CGROUP_BLKIO_WEIGHT_MIN, CGROUP_BLKIO_WEIGHT_MAX); +} + +static void cgroup_apply_io_device_weight(Unit *u, const char *dev_path, uint64_t io_weight) { + char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1]; + dev_t dev; + int r; + + r = lookup_block_device(dev_path, &dev); + if (r < 0) + return; + + xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), io_weight); + (void) set_attribute_and_warn(u, "io", "io.weight", buf); +} + +static void cgroup_apply_blkio_device_weight(Unit *u, const char *dev_path, uint64_t blkio_weight) { + char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1]; + dev_t dev; + int r; + + r = lookup_block_device(dev_path, &dev); + if (r < 0) + return; + + xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), blkio_weight); + (void) set_attribute_and_warn(u, "blkio", "blkio.weight_device", buf); +} + +static void cgroup_apply_io_device_latency(Unit *u, const char *dev_path, usec_t target) { + char buf[DECIMAL_STR_MAX(dev_t)*2+2+7+DECIMAL_STR_MAX(uint64_t)+1]; + dev_t dev; + int r; + + r = lookup_block_device(dev_path, &dev); + if (r < 0) + return; + + if (target != USEC_INFINITY) + xsprintf(buf, "%u:%u target=%" PRIu64 "\n", major(dev), minor(dev), target); + else + xsprintf(buf, "%u:%u target=max\n", major(dev), minor(dev)); + + (void) set_attribute_and_warn(u, "io", "io.latency", buf); +} + +static void cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) { + char limit_bufs[_CGROUP_IO_LIMIT_TYPE_MAX][DECIMAL_STR_MAX(uint64_t)]; + char buf[DECIMAL_STR_MAX(dev_t)*2+2+(6+DECIMAL_STR_MAX(uint64_t)+1)*4]; + CGroupIOLimitType type; + dev_t dev; + int r; + + r = lookup_block_device(dev_path, &dev); + if (r < 0) + return; + + for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++) + if (limits[type] != cgroup_io_limit_defaults[type]) + xsprintf(limit_bufs[type], "%" PRIu64, limits[type]); + else + xsprintf(limit_bufs[type], "%s", limits[type] == CGROUP_LIMIT_MAX ? "max" : "0"); + + xsprintf(buf, "%u:%u rbps=%s wbps=%s riops=%s wiops=%s\n", major(dev), minor(dev), + limit_bufs[CGROUP_IO_RBPS_MAX], limit_bufs[CGROUP_IO_WBPS_MAX], + limit_bufs[CGROUP_IO_RIOPS_MAX], limit_bufs[CGROUP_IO_WIOPS_MAX]); + (void) set_attribute_and_warn(u, "io", "io.max", buf); +} + +static void cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint64_t rbps, uint64_t wbps) { + char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1]; + dev_t dev; + int r; + + r = lookup_block_device(dev_path, &dev); + if (r < 0) + return; + + sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), rbps); + (void) set_attribute_and_warn(u, "blkio", "blkio.throttle.read_bps_device", buf); + + sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), wbps); + (void) set_attribute_and_warn(u, "blkio", "blkio.throttle.write_bps_device", buf); +} + +static bool unit_has_unified_memory_config(Unit *u) { + CGroupContext *c; + + assert(u); + + c = unit_get_cgroup_context(u); + assert(c); + + return unit_get_ancestor_memory_min(u) > 0 || unit_get_ancestor_memory_low(u) > 0 || + c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX || + c->memory_swap_max != CGROUP_LIMIT_MAX; +} + +static void cgroup_apply_unified_memory_limit(Unit *u, const char *file, uint64_t v) { + char buf[DECIMAL_STR_MAX(uint64_t) + 1] = "max\n"; + + if (v != CGROUP_LIMIT_MAX) + xsprintf(buf, "%" PRIu64 "\n", v); + + (void) set_attribute_and_warn(u, "memory", file, buf); +} + +static void cgroup_apply_firewall(Unit *u) { + assert(u); + + /* Best-effort: let's apply IP firewalling and/or accounting if that's enabled */ + + if (bpf_firewall_compile(u) < 0) + return; + + (void) bpf_firewall_load_custom(u); + (void) bpf_firewall_install(u); +} + +static int cgroup_apply_devices(Unit *u) { + _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL; + const char *path; + CGroupContext *c; + CGroupDeviceAllow *a; + CGroupDevicePolicy policy; + int r; + + assert_se(c = unit_get_cgroup_context(u)); + assert_se(path = u->cgroup_path); + + policy = c->device_policy; + + if (cg_all_unified() > 0) { + r = bpf_devices_cgroup_init(&prog, policy, c->device_allow); + if (r < 0) + return log_unit_warning_errno(u, r, "Failed to initialize device control bpf program: %m"); + + } else { + /* Changing the devices list of a populated cgroup might result in EINVAL, hence ignore + * EINVAL here. */ + + if (c->device_allow || policy != CGROUP_DEVICE_POLICY_AUTO) + r = cg_set_attribute("devices", path, "devices.deny", "a"); + else + r = cg_set_attribute("devices", path, "devices.allow", "a"); + if (r < 0) + log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to reset devices.allow/devices.deny: %m"); + } + + bool whitelist_static = policy == CGROUP_DEVICE_POLICY_CLOSED || + (policy == CGROUP_DEVICE_POLICY_AUTO && c->device_allow); + if (whitelist_static) + (void) bpf_devices_whitelist_static(prog, path); + + bool any = whitelist_static; + LIST_FOREACH(device_allow, a, c->device_allow) { + char acc[4], *val; + unsigned k = 0; + + if (a->r) + acc[k++] = 'r'; + if (a->w) + acc[k++] = 'w'; + if (a->m) + acc[k++] = 'm'; + if (k == 0) + continue; + acc[k++] = 0; + + if (path_startswith(a->path, "/dev/")) + r = bpf_devices_whitelist_device(prog, path, a->path, acc); + else if ((val = startswith(a->path, "block-"))) + r = bpf_devices_whitelist_major(prog, path, val, 'b', acc); + else if ((val = startswith(a->path, "char-"))) + r = bpf_devices_whitelist_major(prog, path, val, 'c', acc); + else { + log_unit_debug(u, "Ignoring device '%s' while writing cgroup attribute.", a->path); + continue; + } + + if (r >= 0) + any = true; + } + + if (prog && !any) { + log_unit_warning_errno(u, SYNTHETIC_ERRNO(ENODEV), "No devices matched by device filter."); + + /* The kernel verifier would reject a program we would build with the normal intro and outro + but no whitelisting rules (outro would contain an unreachable instruction for successful + return). */ + policy = CGROUP_DEVICE_POLICY_STRICT; + } + + r = bpf_devices_apply_policy(prog, policy, any, path, &u->bpf_device_control_installed); + if (r < 0) { + static bool warned = false; + + log_full_errno(warned ? LOG_DEBUG : LOG_WARNING, r, + "Unit %s configures device ACL, but the local system doesn't seem to support the BPF-based device controller.\n" + "Proceeding WITHOUT applying ACL (all devices will be accessible)!\n" + "(This warning is only shown for the first loaded unit using device ACL.)", u->id); + + warned = true; + } + return r; +} + +static void cgroup_context_apply( + Unit *u, + CGroupMask apply_mask, + ManagerState state) { + + const char *path; + CGroupContext *c; + bool is_host_root, is_local_root; + int r; + + assert(u); + + /* Nothing to do? Exit early! */ + if (apply_mask == 0) + return; + + /* Some cgroup attributes are not supported on the host root cgroup, hence silently ignore them here. And other + * attributes should only be managed for cgroups further down the tree. */ + is_local_root = unit_has_name(u, SPECIAL_ROOT_SLICE); + is_host_root = unit_has_host_root_cgroup(u); + + assert_se(c = unit_get_cgroup_context(u)); + assert_se(path = u->cgroup_path); + + if (is_local_root) /* Make sure we don't try to display messages with an empty path. */ + path = "/"; + + /* We generally ignore errors caused by read-only mounted cgroup trees (assuming we are running in a container + * then), and missing cgroups, i.e. EROFS and ENOENT. */ + + /* In fully unified mode these attributes don't exist on the host cgroup root. On legacy the weights exist, but + * setting the weight makes very little sense on the host root cgroup, as there are no other cgroups at this + * level. The quota exists there too, but any attempt to write to it is refused with EINVAL. Inside of + * containers we want to leave control of these to the container manager (and if cgroup v2 delegation is used + * we couldn't even write to them if we wanted to). */ + if ((apply_mask & CGROUP_MASK_CPU) && !is_local_root) { + + if (cg_all_unified() > 0) { + uint64_t weight; + + if (cgroup_context_has_cpu_weight(c)) + weight = cgroup_context_cpu_weight(c, state); + else if (cgroup_context_has_cpu_shares(c)) { + uint64_t shares; + + shares = cgroup_context_cpu_shares(c, state); + weight = cgroup_cpu_shares_to_weight(shares); + + log_cgroup_compat(u, "Applying [Startup]CPUShares=%" PRIu64 " as [Startup]CPUWeight=%" PRIu64 " on %s", + shares, weight, path); + } else + weight = CGROUP_WEIGHT_DEFAULT; + + cgroup_apply_unified_cpu_weight(u, weight); + cgroup_apply_unified_cpu_quota(u, c->cpu_quota_per_sec_usec, c->cpu_quota_period_usec); + + } else { + uint64_t shares; + + if (cgroup_context_has_cpu_weight(c)) { + uint64_t weight; + + weight = cgroup_context_cpu_weight(c, state); + shares = cgroup_cpu_weight_to_shares(weight); + + log_cgroup_compat(u, "Applying [Startup]CPUWeight=%" PRIu64 " as [Startup]CPUShares=%" PRIu64 " on %s", + weight, shares, path); + } else if (cgroup_context_has_cpu_shares(c)) + shares = cgroup_context_cpu_shares(c, state); + else + shares = CGROUP_CPU_SHARES_DEFAULT; + + cgroup_apply_legacy_cpu_shares(u, shares); + cgroup_apply_legacy_cpu_quota(u, c->cpu_quota_per_sec_usec, c->cpu_quota_period_usec); + } + } + + if ((apply_mask & CGROUP_MASK_CPUSET) && !is_local_root) { + cgroup_apply_unified_cpuset(u, &c->cpuset_cpus, "cpuset.cpus"); + cgroup_apply_unified_cpuset(u, &c->cpuset_mems, "cpuset.mems"); + } + + /* The 'io' controller attributes are not exported on the host's root cgroup (being a pure cgroup v2 + * controller), and in case of containers we want to leave control of these attributes to the container manager + * (and we couldn't access that stuff anyway, even if we tried if proper delegation is used). */ + if ((apply_mask & CGROUP_MASK_IO) && !is_local_root) { + char buf[8+DECIMAL_STR_MAX(uint64_t)+1]; + bool has_io, has_blockio; + uint64_t weight; + + has_io = cgroup_context_has_io_config(c); + has_blockio = cgroup_context_has_blockio_config(c); + + if (has_io) + weight = cgroup_context_io_weight(c, state); + else if (has_blockio) { + uint64_t blkio_weight; + + blkio_weight = cgroup_context_blkio_weight(c, state); + weight = cgroup_weight_blkio_to_io(blkio_weight); + + log_cgroup_compat(u, "Applying [Startup]BlockIOWeight=%" PRIu64 " as [Startup]IOWeight=%" PRIu64, + blkio_weight, weight); + } else + weight = CGROUP_WEIGHT_DEFAULT; + + xsprintf(buf, "default %" PRIu64 "\n", weight); + (void) set_attribute_and_warn(u, "io", "io.weight", buf); + + /* FIXME: drop this when distro kernels properly support BFQ through "io.weight" + * See also: https://github.com/systemd/systemd/pull/13335 */ + xsprintf(buf, "%" PRIu64 "\n", weight); + (void) set_attribute_and_warn(u, "io", "io.bfq.weight", buf); + + if (has_io) { + CGroupIODeviceLatency *latency; + CGroupIODeviceLimit *limit; + CGroupIODeviceWeight *w; + + LIST_FOREACH(device_weights, w, c->io_device_weights) + cgroup_apply_io_device_weight(u, w->path, w->weight); + + LIST_FOREACH(device_limits, limit, c->io_device_limits) + cgroup_apply_io_device_limit(u, limit->path, limit->limits); + + LIST_FOREACH(device_latencies, latency, c->io_device_latencies) + cgroup_apply_io_device_latency(u, latency->path, latency->target_usec); + + } else if (has_blockio) { + CGroupBlockIODeviceWeight *w; + CGroupBlockIODeviceBandwidth *b; + + LIST_FOREACH(device_weights, w, c->blockio_device_weights) { + weight = cgroup_weight_blkio_to_io(w->weight); + + log_cgroup_compat(u, "Applying BlockIODeviceWeight=%" PRIu64 " as IODeviceWeight=%" PRIu64 " for %s", + w->weight, weight, w->path); + + cgroup_apply_io_device_weight(u, w->path, weight); + } + + LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { + uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX]; + CGroupIOLimitType type; + + for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++) + limits[type] = cgroup_io_limit_defaults[type]; + + limits[CGROUP_IO_RBPS_MAX] = b->rbps; + limits[CGROUP_IO_WBPS_MAX] = b->wbps; + + log_cgroup_compat(u, "Applying BlockIO{Read|Write}Bandwidth=%" PRIu64 " %" PRIu64 " as IO{Read|Write}BandwidthMax= for %s", + b->rbps, b->wbps, b->path); + + cgroup_apply_io_device_limit(u, b->path, limits); + } + } + } + + if (apply_mask & CGROUP_MASK_BLKIO) { + bool has_io, has_blockio; + + has_io = cgroup_context_has_io_config(c); + has_blockio = cgroup_context_has_blockio_config(c); + + /* Applying a 'weight' never makes sense for the host root cgroup, and for containers this should be + * left to our container manager, too. */ + if (!is_local_root) { + char buf[DECIMAL_STR_MAX(uint64_t)+1]; + uint64_t weight; + + if (has_io) { + uint64_t io_weight; + + io_weight = cgroup_context_io_weight(c, state); + weight = cgroup_weight_io_to_blkio(cgroup_context_io_weight(c, state)); + + log_cgroup_compat(u, "Applying [Startup]IOWeight=%" PRIu64 " as [Startup]BlockIOWeight=%" PRIu64, + io_weight, weight); + } else if (has_blockio) + weight = cgroup_context_blkio_weight(c, state); + else + weight = CGROUP_BLKIO_WEIGHT_DEFAULT; + + xsprintf(buf, "%" PRIu64 "\n", weight); + (void) set_attribute_and_warn(u, "blkio", "blkio.weight", buf); + + if (has_io) { + CGroupIODeviceWeight *w; + + LIST_FOREACH(device_weights, w, c->io_device_weights) { + weight = cgroup_weight_io_to_blkio(w->weight); + + log_cgroup_compat(u, "Applying IODeviceWeight=%" PRIu64 " as BlockIODeviceWeight=%" PRIu64 " for %s", + w->weight, weight, w->path); + + cgroup_apply_blkio_device_weight(u, w->path, weight); + } + } else if (has_blockio) { + CGroupBlockIODeviceWeight *w; + + LIST_FOREACH(device_weights, w, c->blockio_device_weights) + cgroup_apply_blkio_device_weight(u, w->path, w->weight); + } + } + + /* The bandwidth limits are something that make sense to be applied to the host's root but not container + * roots, as there we want the container manager to handle it */ + if (is_host_root || !is_local_root) { + if (has_io) { + CGroupIODeviceLimit *l; + + LIST_FOREACH(device_limits, l, c->io_device_limits) { + log_cgroup_compat(u, "Applying IO{Read|Write}Bandwidth=%" PRIu64 " %" PRIu64 " as BlockIO{Read|Write}BandwidthMax= for %s", + l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX], l->path); + + cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX]); + } + } else if (has_blockio) { + CGroupBlockIODeviceBandwidth *b; + + LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) + cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps); + } + } + } + + /* In unified mode 'memory' attributes do not exist on the root cgroup. In legacy mode 'memory.limit_in_bytes' + * exists on the root cgroup, but any writes to it are refused with EINVAL. And if we run in a container we + * want to leave control to the container manager (and if proper cgroup v2 delegation is used we couldn't even + * write to this if we wanted to.) */ + if ((apply_mask & CGROUP_MASK_MEMORY) && !is_local_root) { + + if (cg_all_unified() > 0) { + uint64_t max, swap_max = CGROUP_LIMIT_MAX; + + if (unit_has_unified_memory_config(u)) { + max = c->memory_max; + swap_max = c->memory_swap_max; + } else { + max = c->memory_limit; + + if (max != CGROUP_LIMIT_MAX) + log_cgroup_compat(u, "Applying MemoryLimit=%" PRIu64 " as MemoryMax=", max); + } + + cgroup_apply_unified_memory_limit(u, "memory.min", unit_get_ancestor_memory_min(u)); + cgroup_apply_unified_memory_limit(u, "memory.low", unit_get_ancestor_memory_low(u)); + cgroup_apply_unified_memory_limit(u, "memory.high", c->memory_high); + cgroup_apply_unified_memory_limit(u, "memory.max", max); + cgroup_apply_unified_memory_limit(u, "memory.swap.max", swap_max); + + (void) set_attribute_and_warn(u, "memory", "memory.oom.group", one_zero(c->memory_oom_group)); + + } else { + char buf[DECIMAL_STR_MAX(uint64_t) + 1]; + uint64_t val; + + if (unit_has_unified_memory_config(u)) { + val = c->memory_max; + log_cgroup_compat(u, "Applying MemoryMax=%" PRIi64 " as MemoryLimit=", val); + } else + val = c->memory_limit; + + if (val == CGROUP_LIMIT_MAX) + strncpy(buf, "-1\n", sizeof(buf)); + else + xsprintf(buf, "%" PRIu64 "\n", val); + + (void) set_attribute_and_warn(u, "memory", "memory.limit_in_bytes", buf); + } + } + + /* On cgroup v2 we can apply BPF everywhere. On cgroup v1 we apply it everywhere except for the root of + * containers, where we leave this to the manager */ + if ((apply_mask & (CGROUP_MASK_DEVICES | CGROUP_MASK_BPF_DEVICES)) && + (is_host_root || cg_all_unified() > 0 || !is_local_root)) + (void) cgroup_apply_devices(u); + + if (apply_mask & CGROUP_MASK_PIDS) { + + if (is_host_root) { + /* So, the "pids" controller does not expose anything on the root cgroup, in order not to + * replicate knobs exposed elsewhere needlessly. We abstract this away here however, and when + * the knobs of the root cgroup are modified propagate this to the relevant sysctls. There's a + * non-obvious asymmetry however: unlike the cgroup properties we don't really want to take + * exclusive ownership of the sysctls, but we still want to honour things if the user sets + * limits. Hence we employ sort of a one-way strategy: when the user sets a bounded limit + * through us it counts. When the user afterwards unsets it again (i.e. sets it to unbounded) + * it also counts. But if the user never set a limit through us (i.e. we are the default of + * "unbounded") we leave things unmodified. For this we manage a global boolean that we turn on + * the first time we set a limit. Note that this boolean is flushed out on manager reload, + * which is desirable so that there's an official way to release control of the sysctl from + * systemd: set the limit to unbounded and reload. */ + + if (tasks_max_isset(&c->tasks_max)) { + u->manager->sysctl_pid_max_changed = true; + r = procfs_tasks_set_limit(tasks_max_resolve(&c->tasks_max)); + } else if (u->manager->sysctl_pid_max_changed) + r = procfs_tasks_set_limit(TASKS_MAX); + else + r = 0; + if (r < 0) + log_unit_full(u, LOG_LEVEL_CGROUP_WRITE(r), r, + "Failed to write to tasks limit sysctls: %m"); + } + + /* The attribute itself is not available on the host root cgroup, and in the container case we want to + * leave it for the container manager. */ + if (!is_local_root) { + if (tasks_max_isset(&c->tasks_max)) { + char buf[DECIMAL_STR_MAX(uint64_t) + 1]; + + xsprintf(buf, "%" PRIu64 "\n", tasks_max_resolve(&c->tasks_max)); + (void) set_attribute_and_warn(u, "pids", "pids.max", buf); + } else + (void) set_attribute_and_warn(u, "pids", "pids.max", "max\n"); + } + } + + if (apply_mask & CGROUP_MASK_BPF_FIREWALL) + cgroup_apply_firewall(u); +} + +static bool unit_get_needs_bpf_firewall(Unit *u) { + CGroupContext *c; + Unit *p; + assert(u); + + c = unit_get_cgroup_context(u); + if (!c) + return false; + + if (c->ip_accounting || + c->ip_address_allow || + c->ip_address_deny || + c->ip_filters_ingress || + c->ip_filters_egress) + return true; + + /* If any parent slice has an IP access list defined, it applies too */ + for (p = UNIT_DEREF(u->slice); p; p = UNIT_DEREF(p->slice)) { + c = unit_get_cgroup_context(p); + if (!c) + return false; + + if (c->ip_address_allow || + c->ip_address_deny) + return true; + } + + return false; +} + +static CGroupMask unit_get_cgroup_mask(Unit *u) { + CGroupMask mask = 0; + CGroupContext *c; + + assert(u); + + c = unit_get_cgroup_context(u); + + assert(c); + + /* Figure out which controllers we need, based on the cgroup context object */ + + if (c->cpu_accounting) + mask |= get_cpu_accounting_mask(); + + if (cgroup_context_has_cpu_weight(c) || + cgroup_context_has_cpu_shares(c) || + c->cpu_quota_per_sec_usec != USEC_INFINITY) + mask |= CGROUP_MASK_CPU; + + if (c->cpuset_cpus.set || c->cpuset_mems.set) + mask |= CGROUP_MASK_CPUSET; + + if (cgroup_context_has_io_config(c) || cgroup_context_has_blockio_config(c)) + mask |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO; + + if (c->memory_accounting || + c->memory_limit != CGROUP_LIMIT_MAX || + unit_has_unified_memory_config(u)) + mask |= CGROUP_MASK_MEMORY; + + if (c->device_allow || + c->device_policy != CGROUP_DEVICE_POLICY_AUTO) + mask |= CGROUP_MASK_DEVICES | CGROUP_MASK_BPF_DEVICES; + + if (c->tasks_accounting || + tasks_max_isset(&c->tasks_max)) + mask |= CGROUP_MASK_PIDS; + + return CGROUP_MASK_EXTEND_JOINED(mask); +} + +static CGroupMask unit_get_bpf_mask(Unit *u) { + CGroupMask mask = 0; + + /* Figure out which controllers we need, based on the cgroup context, possibly taking into account children + * too. */ + + if (unit_get_needs_bpf_firewall(u)) + mask |= CGROUP_MASK_BPF_FIREWALL; + + return mask; +} + +CGroupMask unit_get_own_mask(Unit *u) { + CGroupContext *c; + + /* Returns the mask of controllers the unit needs for itself. If a unit is not properly loaded, return an empty + * mask, as we shouldn't reflect it in the cgroup hierarchy then. */ + + if (u->load_state != UNIT_LOADED) + return 0; + + c = unit_get_cgroup_context(u); + if (!c) + return 0; + + return (unit_get_cgroup_mask(u) | unit_get_bpf_mask(u) | unit_get_delegate_mask(u)) & ~unit_get_ancestor_disable_mask(u); +} + +CGroupMask unit_get_delegate_mask(Unit *u) { + CGroupContext *c; + + /* If delegation is turned on, then turn on selected controllers, unless we are on the legacy hierarchy and the + * process we fork into is known to drop privileges, and hence shouldn't get access to the controllers. + * + * Note that on the unified hierarchy it is safe to delegate controllers to unprivileged services. */ + + if (!unit_cgroup_delegate(u)) + return 0; + + if (cg_all_unified() <= 0) { + ExecContext *e; + + e = unit_get_exec_context(u); + if (e && !exec_context_maintains_privileges(e)) + return 0; + } + + assert_se(c = unit_get_cgroup_context(u)); + return CGROUP_MASK_EXTEND_JOINED(c->delegate_controllers); +} + +CGroupMask unit_get_members_mask(Unit *u) { + assert(u); + + /* Returns the mask of controllers all of the unit's children require, merged */ + + if (u->cgroup_members_mask_valid) + return u->cgroup_members_mask; /* Use cached value if possible */ + + u->cgroup_members_mask = 0; + + if (u->type == UNIT_SLICE) { + void *v; + Unit *member; + Iterator i; + + HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) { + if (UNIT_DEREF(member->slice) == u) + u->cgroup_members_mask |= unit_get_subtree_mask(member); /* note that this calls ourselves again, for the children */ + } + } + + u->cgroup_members_mask_valid = true; + return u->cgroup_members_mask; +} + +CGroupMask unit_get_siblings_mask(Unit *u) { + assert(u); + + /* Returns the mask of controllers all of the unit's siblings + * require, i.e. the members mask of the unit's parent slice + * if there is one. */ + + if (UNIT_ISSET(u->slice)) + return unit_get_members_mask(UNIT_DEREF(u->slice)); + + return unit_get_subtree_mask(u); /* we are the top-level slice */ +} + +CGroupMask unit_get_disable_mask(Unit *u) { + CGroupContext *c; + + c = unit_get_cgroup_context(u); + if (!c) + return 0; + + return c->disable_controllers; +} + +CGroupMask unit_get_ancestor_disable_mask(Unit *u) { + CGroupMask mask; + + assert(u); + mask = unit_get_disable_mask(u); + + /* Returns the mask of controllers which are marked as forcibly + * disabled in any ancestor unit or the unit in question. */ + + if (UNIT_ISSET(u->slice)) + mask |= unit_get_ancestor_disable_mask(UNIT_DEREF(u->slice)); + + return mask; +} + +CGroupMask unit_get_subtree_mask(Unit *u) { + + /* Returns the mask of this subtree, meaning of the group + * itself and its children. */ + + return unit_get_own_mask(u) | unit_get_members_mask(u); +} + +CGroupMask unit_get_target_mask(Unit *u) { + CGroupMask mask; + + /* This returns the cgroup mask of all controllers to enable + * for a specific cgroup, i.e. everything it needs itself, + * plus all that its children need, plus all that its siblings + * need. This is primarily useful on the legacy cgroup + * hierarchy, where we need to duplicate each cgroup in each + * hierarchy that shall be enabled for it. */ + + mask = unit_get_own_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u); + + if (mask & CGROUP_MASK_BPF_FIREWALL & ~u->manager->cgroup_supported) + emit_bpf_firewall_warning(u); + + mask &= u->manager->cgroup_supported; + mask &= ~unit_get_ancestor_disable_mask(u); + + return mask; +} + +CGroupMask unit_get_enable_mask(Unit *u) { + CGroupMask mask; + + /* This returns the cgroup mask of all controllers to enable + * for the children of a specific cgroup. This is primarily + * useful for the unified cgroup hierarchy, where each cgroup + * controls which controllers are enabled for its children. */ + + mask = unit_get_members_mask(u); + mask &= u->manager->cgroup_supported; + mask &= ~unit_get_ancestor_disable_mask(u); + + return mask; +} + +void unit_invalidate_cgroup_members_masks(Unit *u) { + assert(u); + + /* Recurse invalidate the member masks cache all the way up the tree */ + u->cgroup_members_mask_valid = false; + + if (UNIT_ISSET(u->slice)) + unit_invalidate_cgroup_members_masks(UNIT_DEREF(u->slice)); +} + +const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask) { + + /* Returns the realized cgroup path of the specified unit where all specified controllers are available. */ + + while (u) { + + if (u->cgroup_path && + u->cgroup_realized && + FLAGS_SET(u->cgroup_realized_mask, mask)) + return u->cgroup_path; + + u = UNIT_DEREF(u->slice); + } + + return NULL; +} + +static const char *migrate_callback(CGroupMask mask, void *userdata) { + return unit_get_realized_cgroup_path(userdata, mask); +} + +char *unit_default_cgroup_path(const Unit *u) { + _cleanup_free_ char *escaped = NULL, *slice = NULL; + int r; + + assert(u); + + if (unit_has_name(u, SPECIAL_ROOT_SLICE)) + return strdup(u->manager->cgroup_root); + + if (UNIT_ISSET(u->slice) && !unit_has_name(UNIT_DEREF(u->slice), SPECIAL_ROOT_SLICE)) { + r = cg_slice_to_path(UNIT_DEREF(u->slice)->id, &slice); + if (r < 0) + return NULL; + } + + escaped = cg_escape(u->id); + if (!escaped) + return NULL; + + return path_join(empty_to_root(u->manager->cgroup_root), slice, escaped); +} + +int unit_set_cgroup_path(Unit *u, const char *path) { + _cleanup_free_ char *p = NULL; + int r; + + assert(u); + + if (streq_ptr(u->cgroup_path, path)) + return 0; + + if (path) { + p = strdup(path); + if (!p) + return -ENOMEM; + } + + if (p) { + r = hashmap_put(u->manager->cgroup_unit, p, u); + if (r < 0) + return r; + } + + unit_release_cgroup(u); + u->cgroup_path = TAKE_PTR(p); + + return 1; +} + +int unit_watch_cgroup(Unit *u) { + _cleanup_free_ char *events = NULL; + int r; + + assert(u); + + /* Watches the "cgroups.events" attribute of this unit's cgroup for "empty" events, but only if + * cgroupv2 is available. */ + + if (!u->cgroup_path) + return 0; + + if (u->cgroup_control_inotify_wd >= 0) + return 0; + + /* Only applies to the unified hierarchy */ + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) + return log_error_errno(r, "Failed to determine whether the name=systemd hierarchy is unified: %m"); + if (r == 0) + return 0; + + /* No point in watch the top-level slice, it's never going to run empty. */ + if (unit_has_name(u, SPECIAL_ROOT_SLICE)) + return 0; + + r = hashmap_ensure_allocated(&u->manager->cgroup_control_inotify_wd_unit, &trivial_hash_ops); + if (r < 0) + return log_oom(); + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.events", &events); + if (r < 0) + return log_oom(); + + u->cgroup_control_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, events, IN_MODIFY); + if (u->cgroup_control_inotify_wd < 0) { + + if (errno == ENOENT) /* If the directory is already gone we don't need to track it, so this + * is not an error */ + return 0; + + return log_unit_error_errno(u, errno, "Failed to add control inotify watch descriptor for control group %s: %m", u->cgroup_path); + } + + r = hashmap_put(u->manager->cgroup_control_inotify_wd_unit, INT_TO_PTR(u->cgroup_control_inotify_wd), u); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to add control inotify watch descriptor to hash map: %m"); + + return 0; +} + +int unit_watch_cgroup_memory(Unit *u) { + _cleanup_free_ char *events = NULL; + CGroupContext *c; + int r; + + assert(u); + + /* Watches the "memory.events" attribute of this unit's cgroup for "oom_kill" events, but only if + * cgroupv2 is available. */ + + if (!u->cgroup_path) + return 0; + + c = unit_get_cgroup_context(u); + if (!c) + return 0; + + /* The "memory.events" attribute is only available if the memory controller is on. Let's hence tie + * this to memory accounting, in a way watching for OOM kills is a form of memory accounting after + * all. */ + if (!c->memory_accounting) + return 0; + + /* Don't watch inner nodes, as the kernel doesn't report oom_kill events recursively currently, and + * we also don't want to generate a log message for each parent cgroup of a process. */ + if (u->type == UNIT_SLICE) + return 0; + + if (u->cgroup_memory_inotify_wd >= 0) + return 0; + + /* Only applies to the unified hierarchy */ + r = cg_all_unified(); + if (r < 0) + return log_error_errno(r, "Failed to determine whether the memory controller is unified: %m"); + if (r == 0) + return 0; + + r = hashmap_ensure_allocated(&u->manager->cgroup_memory_inotify_wd_unit, &trivial_hash_ops); + if (r < 0) + return log_oom(); + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "memory.events", &events); + if (r < 0) + return log_oom(); + + u->cgroup_memory_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, events, IN_MODIFY); + if (u->cgroup_memory_inotify_wd < 0) { + + if (errno == ENOENT) /* If the directory is already gone we don't need to track it, so this + * is not an error */ + return 0; + + return log_unit_error_errno(u, errno, "Failed to add memory inotify watch descriptor for control group %s: %m", u->cgroup_path); + } + + r = hashmap_put(u->manager->cgroup_memory_inotify_wd_unit, INT_TO_PTR(u->cgroup_memory_inotify_wd), u); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to add memory inotify watch descriptor to hash map: %m"); + + return 0; +} + +int unit_pick_cgroup_path(Unit *u) { + _cleanup_free_ char *path = NULL; + int r; + + assert(u); + + if (u->cgroup_path) + return 0; + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return -EINVAL; + + path = unit_default_cgroup_path(u); + if (!path) + return log_oom(); + + r = unit_set_cgroup_path(u, path); + if (r == -EEXIST) + return log_unit_error_errno(u, r, "Control group %s exists already.", path); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to set unit's control group path to %s: %m", path); + + return 0; +} + +static int unit_create_cgroup( + Unit *u, + CGroupMask target_mask, + CGroupMask enable_mask, + ManagerState state) { + + bool created; + int r; + + assert(u); + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return 0; + + /* Figure out our cgroup path */ + r = unit_pick_cgroup_path(u); + if (r < 0) + return r; + + /* First, create our own group */ + r = cg_create_everywhere(u->manager->cgroup_supported, target_mask, u->cgroup_path); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to create cgroup %s: %m", u->cgroup_path); + created = r; + + /* Start watching it */ + (void) unit_watch_cgroup(u); + (void) unit_watch_cgroup_memory(u); + + /* Preserve enabled controllers in delegated units, adjust others. */ + if (created || !u->cgroup_realized || !unit_cgroup_delegate(u)) { + CGroupMask result_mask = 0; + + /* Enable all controllers we need */ + r = cg_enable_everywhere(u->manager->cgroup_supported, enable_mask, u->cgroup_path, &result_mask); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to enable/disable controllers on cgroup %s, ignoring: %m", u->cgroup_path); + + /* If we just turned off a controller, this might release the controller for our parent too, let's + * enqueue the parent for re-realization in that case again. */ + if (UNIT_ISSET(u->slice)) { + CGroupMask turned_off; + + turned_off = (u->cgroup_realized ? u->cgroup_enabled_mask & ~result_mask : 0); + if (turned_off != 0) { + Unit *parent; + + /* Force the parent to propagate the enable mask to the kernel again, by invalidating + * the controller we just turned off. */ + + for (parent = UNIT_DEREF(u->slice); parent; parent = UNIT_DEREF(parent->slice)) + unit_invalidate_cgroup(parent, turned_off); + } + } + + /* Remember what's actually enabled now */ + u->cgroup_enabled_mask = result_mask; + } + + /* Keep track that this is now realized */ + u->cgroup_realized = true; + u->cgroup_realized_mask = target_mask; + + if (u->type != UNIT_SLICE && !unit_cgroup_delegate(u)) { + + /* Then, possibly move things over, but not if + * subgroups may contain processes, which is the case + * for slice and delegation units. */ + r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->cgroup_path, migrate_callback, u); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to migrate cgroup from to %s, ignoring: %m", u->cgroup_path); + } + + /* Set attributes */ + cgroup_context_apply(u, target_mask, state); + cgroup_xattr_apply(u); + + return 0; +} + +static int unit_attach_pid_to_cgroup_via_bus(Unit *u, pid_t pid, const char *suffix_path) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + char *pp; + int r; + + assert(u); + + if (MANAGER_IS_SYSTEM(u->manager)) + return -EINVAL; + + if (!u->manager->system_bus) + return -EIO; + + if (!u->cgroup_path) + return -EINVAL; + + /* Determine this unit's cgroup path relative to our cgroup root */ + pp = path_startswith(u->cgroup_path, u->manager->cgroup_root); + if (!pp) + return -EINVAL; + + pp = strjoina("/", pp, suffix_path); + path_simplify(pp, false); + + r = sd_bus_call_method(u->manager->system_bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "AttachProcessesToUnit", + &error, NULL, + "ssau", + NULL /* empty unit name means client's unit, i.e. us */, pp, 1, (uint32_t) pid); + if (r < 0) + return log_unit_debug_errno(u, r, "Failed to attach unit process " PID_FMT " via the bus: %s", pid, bus_error_message(&error, r)); + + return 0; +} + +int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) { + CGroupMask delegated_mask; + const char *p; + Iterator i; + void *pidp; + int r, q; + + assert(u); + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return -EINVAL; + + if (set_isempty(pids)) + return 0; + + /* Load any custom firewall BPF programs here once to test if they are existing and actually loadable. + * Fail here early since later errors in the call chain unit_realize_cgroup to cgroup_context_apply are ignored. */ + r = bpf_firewall_load_custom(u); + if (r < 0) + return r; + + r = unit_realize_cgroup(u); + if (r < 0) + return r; + + if (isempty(suffix_path)) + p = u->cgroup_path; + else + p = prefix_roota(u->cgroup_path, suffix_path); + + delegated_mask = unit_get_delegate_mask(u); + + r = 0; + SET_FOREACH(pidp, pids, i) { + pid_t pid = PTR_TO_PID(pidp); + CGroupController c; + + /* First, attach the PID to the main cgroup hierarchy */ + q = cg_attach(SYSTEMD_CGROUP_CONTROLLER, p, pid); + if (q < 0) { + log_unit_debug_errno(u, q, "Couldn't move process " PID_FMT " to requested cgroup '%s': %m", pid, p); + + if (MANAGER_IS_USER(u->manager) && IN_SET(q, -EPERM, -EACCES)) { + int z; + + /* If we are in a user instance, and we can't move the process ourselves due to + * permission problems, let's ask the system instance about it instead. Since it's more + * privileged it might be able to move the process across the leaves of a subtree who's + * top node is not owned by us. */ + + z = unit_attach_pid_to_cgroup_via_bus(u, pid, suffix_path); + if (z < 0) + log_unit_debug_errno(u, z, "Couldn't move process " PID_FMT " to requested cgroup '%s' via the system bus either: %m", pid, p); + else + continue; /* When the bus thing worked via the bus we are fully done for this PID. */ + } + + if (r >= 0) + r = q; /* Remember first error */ + + continue; + } + + q = cg_all_unified(); + if (q < 0) + return q; + if (q > 0) + continue; + + /* In the legacy hierarchy, attach the process to the request cgroup if possible, and if not to the + * innermost realized one */ + + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { + CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); + const char *realized; + + if (!(u->manager->cgroup_supported & bit)) + continue; + + /* If this controller is delegated and realized, honour the caller's request for the cgroup suffix. */ + if (delegated_mask & u->cgroup_realized_mask & bit) { + q = cg_attach(cgroup_controller_to_string(c), p, pid); + if (q >= 0) + continue; /* Success! */ + + log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to requested cgroup %s in controller %s, falling back to unit's cgroup: %m", + pid, p, cgroup_controller_to_string(c)); + } + + /* So this controller is either not delegate or realized, or something else weird happened. In + * that case let's attach the PID at least to the closest cgroup up the tree that is + * realized. */ + realized = unit_get_realized_cgroup_path(u, bit); + if (!realized) + continue; /* Not even realized in the root slice? Then let's not bother */ + + q = cg_attach(cgroup_controller_to_string(c), realized, pid); + if (q < 0) + log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to realized cgroup %s in controller %s, ignoring: %m", + pid, realized, cgroup_controller_to_string(c)); + } + } + + return r; +} + +static bool unit_has_mask_realized( + Unit *u, + CGroupMask target_mask, + CGroupMask enable_mask) { + + assert(u); + + /* Returns true if this unit is fully realized. We check four things: + * + * 1. Whether the cgroup was created at all + * 2. Whether the cgroup was created in all the hierarchies we need it to be created in (in case of cgroup v1) + * 3. Whether the cgroup has all the right controllers enabled (in case of cgroup v2) + * 4. Whether the invalidation mask is currently zero + * + * If you wonder why we mask the target realization and enable mask with CGROUP_MASK_V1/CGROUP_MASK_V2: note + * that there are three sets of bitmasks: CGROUP_MASK_V1 (for real cgroup v1 controllers), CGROUP_MASK_V2 (for + * real cgroup v2 controllers) and CGROUP_MASK_BPF (for BPF-based pseudo-controllers). Now, cgroup_realized_mask + * is only matters for cgroup v1 controllers, and cgroup_enabled_mask only used for cgroup v2, and if they + * differ in the others, we don't really care. (After all, the cgroup_enabled_mask tracks with controllers are + * enabled through cgroup.subtree_control, and since the BPF pseudo-controllers don't show up there, they + * simply don't matter. */ + + return u->cgroup_realized && + ((u->cgroup_realized_mask ^ target_mask) & CGROUP_MASK_V1) == 0 && + ((u->cgroup_enabled_mask ^ enable_mask) & CGROUP_MASK_V2) == 0 && + u->cgroup_invalidated_mask == 0; +} + +static bool unit_has_mask_disables_realized( + Unit *u, + CGroupMask target_mask, + CGroupMask enable_mask) { + + assert(u); + + /* Returns true if all controllers which should be disabled are indeed disabled. + * + * Unlike unit_has_mask_realized, we don't care what was enabled, only that anything we want to remove is + * already removed. */ + + return !u->cgroup_realized || + (FLAGS_SET(u->cgroup_realized_mask, target_mask & CGROUP_MASK_V1) && + FLAGS_SET(u->cgroup_enabled_mask, enable_mask & CGROUP_MASK_V2)); +} + +static bool unit_has_mask_enables_realized( + Unit *u, + CGroupMask target_mask, + CGroupMask enable_mask) { + + assert(u); + + /* Returns true if all controllers which should be enabled are indeed enabled. + * + * Unlike unit_has_mask_realized, we don't care about the controllers that are not present, only that anything + * we want to add is already added. */ + + return u->cgroup_realized && + ((u->cgroup_realized_mask | target_mask) & CGROUP_MASK_V1) == (u->cgroup_realized_mask & CGROUP_MASK_V1) && + ((u->cgroup_enabled_mask | enable_mask) & CGROUP_MASK_V2) == (u->cgroup_enabled_mask & CGROUP_MASK_V2); +} + +void unit_add_to_cgroup_realize_queue(Unit *u) { + assert(u); + + if (u->in_cgroup_realize_queue) + return; + + LIST_PREPEND(cgroup_realize_queue, u->manager->cgroup_realize_queue, u); + u->in_cgroup_realize_queue = true; +} + +static void unit_remove_from_cgroup_realize_queue(Unit *u) { + assert(u); + + if (!u->in_cgroup_realize_queue) + return; + + LIST_REMOVE(cgroup_realize_queue, u->manager->cgroup_realize_queue, u); + u->in_cgroup_realize_queue = false; +} + +/* Controllers can only be enabled breadth-first, from the root of the + * hierarchy downwards to the unit in question. */ +static int unit_realize_cgroup_now_enable(Unit *u, ManagerState state) { + CGroupMask target_mask, enable_mask, new_target_mask, new_enable_mask; + int r; + + assert(u); + + /* First go deal with this unit's parent, or we won't be able to enable + * any new controllers at this layer. */ + if (UNIT_ISSET(u->slice)) { + r = unit_realize_cgroup_now_enable(UNIT_DEREF(u->slice), state); + if (r < 0) + return r; + } + + target_mask = unit_get_target_mask(u); + enable_mask = unit_get_enable_mask(u); + + /* We can only enable in this direction, don't try to disable anything. + */ + if (unit_has_mask_enables_realized(u, target_mask, enable_mask)) + return 0; + + new_target_mask = u->cgroup_realized_mask | target_mask; + new_enable_mask = u->cgroup_enabled_mask | enable_mask; + + return unit_create_cgroup(u, new_target_mask, new_enable_mask, state); +} + +/* Controllers can only be disabled depth-first, from the leaves of the + * hierarchy upwards to the unit in question. */ +static int unit_realize_cgroup_now_disable(Unit *u, ManagerState state) { + Iterator i; + Unit *m; + void *v; + + assert(u); + + if (u->type != UNIT_SLICE) + return 0; + + HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE], i) { + CGroupMask target_mask, enable_mask, new_target_mask, new_enable_mask; + int r; + + if (UNIT_DEREF(m->slice) != u) + continue; + + /* The cgroup for this unit might not actually be fully + * realised yet, in which case it isn't holding any controllers + * open anyway. */ + if (!m->cgroup_path) + continue; + + /* We must disable those below us first in order to release the + * controller. */ + if (m->type == UNIT_SLICE) + (void) unit_realize_cgroup_now_disable(m, state); + + target_mask = unit_get_target_mask(m); + enable_mask = unit_get_enable_mask(m); + + /* We can only disable in this direction, don't try to enable + * anything. */ + if (unit_has_mask_disables_realized(m, target_mask, enable_mask)) + continue; + + new_target_mask = m->cgroup_realized_mask & target_mask; + new_enable_mask = m->cgroup_enabled_mask & enable_mask; + + r = unit_create_cgroup(m, new_target_mask, new_enable_mask, state); + if (r < 0) + return r; + } + + return 0; +} + +/* Check if necessary controllers and attributes for a unit are in place. + * + * - If so, do nothing. + * - If not, create paths, move processes over, and set attributes. + * + * Controllers can only be *enabled* in a breadth-first way, and *disabled* in + * a depth-first way. As such the process looks like this: + * + * Suppose we have a cgroup hierarchy which looks like this: + * + * root + * / \ + * / \ + * / \ + * a b + * / \ / \ + * / \ / \ + * c d e f + * / \ / \ / \ / \ + * h i j k l m n o + * + * 1. We want to realise cgroup "d" now. + * 2. cgroup "a" has DisableControllers=cpu in the associated unit. + * 3. cgroup "k" just started requesting the memory controller. + * + * To make this work we must do the following in order: + * + * 1. Disable CPU controller in k, j + * 2. Disable CPU controller in d + * 3. Enable memory controller in root + * 4. Enable memory controller in a + * 5. Enable memory controller in d + * 6. Enable memory controller in k + * + * Notice that we need to touch j in one direction, but not the other. We also + * don't go beyond d when disabling -- it's up to "a" to get realized if it + * wants to disable further. The basic rules are therefore: + * + * - If you're disabling something, you need to realise all of the cgroups from + * your recursive descendants to the root. This starts from the leaves. + * - If you're enabling something, you need to realise from the root cgroup + * downwards, but you don't need to iterate your recursive descendants. + * + * Returns 0 on success and < 0 on failure. */ +static int unit_realize_cgroup_now(Unit *u, ManagerState state) { + CGroupMask target_mask, enable_mask; + int r; + + assert(u); + + unit_remove_from_cgroup_realize_queue(u); + + target_mask = unit_get_target_mask(u); + enable_mask = unit_get_enable_mask(u); + + if (unit_has_mask_realized(u, target_mask, enable_mask)) + return 0; + + /* Disable controllers below us, if there are any */ + r = unit_realize_cgroup_now_disable(u, state); + if (r < 0) + return r; + + /* Enable controllers above us, if there are any */ + if (UNIT_ISSET(u->slice)) { + r = unit_realize_cgroup_now_enable(UNIT_DEREF(u->slice), state); + if (r < 0) + return r; + } + + /* Now actually deal with the cgroup we were trying to realise and set attributes */ + r = unit_create_cgroup(u, target_mask, enable_mask, state); + if (r < 0) + return r; + + /* Now, reset the invalidation mask */ + u->cgroup_invalidated_mask = 0; + return 0; +} + +unsigned manager_dispatch_cgroup_realize_queue(Manager *m) { + ManagerState state; + unsigned n = 0; + Unit *i; + int r; + + assert(m); + + state = manager_state(m); + + while ((i = m->cgroup_realize_queue)) { + assert(i->in_cgroup_realize_queue); + + if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(i))) { + /* Maybe things changed, and the unit is not actually active anymore? */ + unit_remove_from_cgroup_realize_queue(i); + continue; + } + + r = unit_realize_cgroup_now(i, state); + if (r < 0) + log_warning_errno(r, "Failed to realize cgroups for queued unit %s, ignoring: %m", i->id); + + n++; + } + + return n; +} + +static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) { + Unit *slice; + + /* This adds the siblings of the specified unit and the siblings of all parent units to the cgroup + * queue. (But neither the specified unit itself nor the parents.) + * + * Propagation of realization "side-ways" (i.e. towards siblings) is in relevant on cgroup-v1 where + * scheduling become very weird if two units that own processes reside in the same slice, but one is + * realized in the "cpu" hierarchy and once is not (for example because one has CPUWeight= set and + * the other does not), because that means processes need to be scheduled against groups. Let's avoid + * this asymmetry by always ensuring that units below a slice that are realized at all are hence + * always realized in *all* their hierarchies, and it is sufficient for a unit's sibling to be + * realized for a unit to be realized too. */ + + while ((slice = UNIT_DEREF(u->slice))) { + Iterator i; + Unit *m; + void *v; + + HASHMAP_FOREACH_KEY(v, m, slice->dependencies[UNIT_BEFORE], i) { + + /* Skip units that have a dependency on the slice but aren't actually in it. */ + if (UNIT_DEREF(m->slice) != slice) + continue; + + /* No point in doing cgroup application for units without active processes. */ + if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m))) + continue; + + /* We only enqueue siblings if they were realized once at least, in the main + * hierarchy. */ + if (!m->cgroup_realized) + continue; + + /* If the unit doesn't need any new controllers and has current ones realized, it + * doesn't need any changes. */ + if (unit_has_mask_realized(m, + unit_get_target_mask(m), + unit_get_enable_mask(m))) + continue; + + unit_add_to_cgroup_realize_queue(m); + } + + u = slice; + } +} + +int unit_realize_cgroup(Unit *u) { + assert(u); + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return 0; + + /* So, here's the deal: when realizing the cgroups for this + * unit, we need to first create all parents, but there's more + * actually: for the weight-based controllers we also need to + * make sure that all our siblings (i.e. units that are in the + * same slice as we are) have cgroups, too. Otherwise, things + * would become very uneven as each of their processes would + * get as much resources as all our group together. This call + * will synchronously create the parent cgroups, but will + * defer work on the siblings to the next event loop + * iteration. */ + + /* Add all sibling slices to the cgroup queue. */ + unit_add_siblings_to_cgroup_realize_queue(u); + + /* And realize this one now (and apply the values) */ + return unit_realize_cgroup_now(u, manager_state(u->manager)); +} + +void unit_release_cgroup(Unit *u) { + assert(u); + + /* Forgets all cgroup details for this cgroup — but does *not* destroy the cgroup. This is hence OK to call + * when we close down everything for reexecution, where we really want to leave the cgroup in place. */ + + if (u->cgroup_path) { + (void) hashmap_remove(u->manager->cgroup_unit, u->cgroup_path); + u->cgroup_path = mfree(u->cgroup_path); + } + + if (u->cgroup_control_inotify_wd >= 0) { + if (inotify_rm_watch(u->manager->cgroup_inotify_fd, u->cgroup_control_inotify_wd) < 0) + log_unit_debug_errno(u, errno, "Failed to remove cgroup control inotify watch %i for %s, ignoring: %m", u->cgroup_control_inotify_wd, u->id); + + (void) hashmap_remove(u->manager->cgroup_control_inotify_wd_unit, INT_TO_PTR(u->cgroup_control_inotify_wd)); + u->cgroup_control_inotify_wd = -1; + } + + if (u->cgroup_memory_inotify_wd >= 0) { + if (inotify_rm_watch(u->manager->cgroup_inotify_fd, u->cgroup_memory_inotify_wd) < 0) + log_unit_debug_errno(u, errno, "Failed to remove cgroup memory inotify watch %i for %s, ignoring: %m", u->cgroup_memory_inotify_wd, u->id); + + (void) hashmap_remove(u->manager->cgroup_memory_inotify_wd_unit, INT_TO_PTR(u->cgroup_memory_inotify_wd)); + u->cgroup_memory_inotify_wd = -1; + } +} + +void unit_prune_cgroup(Unit *u) { + int r; + bool is_root_slice; + + assert(u); + + /* Removes the cgroup, if empty and possible, and stops watching it. */ + + if (!u->cgroup_path) + return; + + (void) unit_get_cpu_usage(u, NULL); /* Cache the last CPU usage value before we destroy the cgroup */ + + is_root_slice = unit_has_name(u, SPECIAL_ROOT_SLICE); + + r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !is_root_slice); + if (r < 0) + /* One reason we could have failed here is, that the cgroup still contains a process. + * However, if the cgroup becomes removable at a later time, it might be removed when + * the containing slice is stopped. So even if we failed now, this unit shouldn't assume + * that the cgroup is still realized the next time it is started. Do not return early + * on error, continue cleanup. */ + log_unit_full(u, r == -EBUSY ? LOG_DEBUG : LOG_WARNING, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path); + + if (is_root_slice) + return; + + unit_release_cgroup(u); + + u->cgroup_realized = false; + u->cgroup_realized_mask = 0; + u->cgroup_enabled_mask = 0; + + u->bpf_device_control_installed = bpf_program_unref(u->bpf_device_control_installed); +} + +int unit_search_main_pid(Unit *u, pid_t *ret) { + _cleanup_fclose_ FILE *f = NULL; + pid_t pid = 0, npid; + int r; + + assert(u); + assert(ret); + + if (!u->cgroup_path) + return -ENXIO; + + r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f); + if (r < 0) + return r; + + while (cg_read_pid(f, &npid) > 0) { + + if (npid == pid) + continue; + + if (pid_is_my_child(npid) == 0) + continue; + + if (pid != 0) + /* Dang, there's more than one daemonized PID + in this group, so we don't know what process + is the main process. */ + + return -ENODATA; + + pid = npid; + } + + *ret = pid; + return 0; +} + +static int unit_watch_pids_in_path(Unit *u, const char *path) { + _cleanup_closedir_ DIR *d = NULL; + _cleanup_fclose_ FILE *f = NULL; + int ret = 0, r; + + assert(u); + assert(path); + + r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, path, &f); + if (r < 0) + ret = r; + else { + pid_t pid; + + while ((r = cg_read_pid(f, &pid)) > 0) { + r = unit_watch_pid(u, pid, false); + if (r < 0 && ret >= 0) + ret = r; + } + + if (r < 0 && ret >= 0) + ret = r; + } + + r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d); + if (r < 0) { + if (ret >= 0) + ret = r; + } else { + char *fn; + + while ((r = cg_read_subgroup(d, &fn)) > 0) { + _cleanup_free_ char *p = NULL; + + p = path_join(empty_to_root(path), fn); + free(fn); + + if (!p) + return -ENOMEM; + + r = unit_watch_pids_in_path(u, p); + if (r < 0 && ret >= 0) + ret = r; + } + + if (r < 0 && ret >= 0) + ret = r; + } + + return ret; +} + +int unit_synthesize_cgroup_empty_event(Unit *u) { + int r; + + assert(u); + + /* Enqueue a synthetic cgroup empty event if this unit doesn't watch any PIDs anymore. This is compatibility + * support for non-unified systems where notifications aren't reliable, and hence need to take whatever we can + * get as notification source as soon as we stopped having any useful PIDs to watch for. */ + + if (!u->cgroup_path) + return -ENOENT; + + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) + return r; + if (r > 0) /* On unified we have reliable notifications, and don't need this */ + return 0; + + if (!set_isempty(u->pids)) + return 0; + + unit_add_to_cgroup_empty_queue(u); + return 0; +} + +int unit_watch_all_pids(Unit *u) { + int r; + + assert(u); + + /* Adds all PIDs from our cgroup to the set of PIDs we + * watch. This is a fallback logic for cases where we do not + * get reliable cgroup empty notifications: we try to use + * SIGCHLD as replacement. */ + + if (!u->cgroup_path) + return -ENOENT; + + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) + return r; + if (r > 0) /* On unified we can use proper notifications */ + return 0; + + return unit_watch_pids_in_path(u, u->cgroup_path); +} + +static int on_cgroup_empty_event(sd_event_source *s, void *userdata) { + Manager *m = userdata; + Unit *u; + int r; + + assert(s); + assert(m); + + u = m->cgroup_empty_queue; + if (!u) + return 0; + + assert(u->in_cgroup_empty_queue); + u->in_cgroup_empty_queue = false; + LIST_REMOVE(cgroup_empty_queue, m->cgroup_empty_queue, u); + + if (m->cgroup_empty_queue) { + /* More stuff queued, let's make sure we remain enabled */ + r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT); + if (r < 0) + log_debug_errno(r, "Failed to reenable cgroup empty event source, ignoring: %m"); + } + + unit_add_to_gc_queue(u); + + if (UNIT_VTABLE(u)->notify_cgroup_empty) + UNIT_VTABLE(u)->notify_cgroup_empty(u); + + return 0; +} + +void unit_add_to_cgroup_empty_queue(Unit *u) { + int r; + + assert(u); + + /* Note that there are four different ways how cgroup empty events reach us: + * + * 1. On the unified hierarchy we get an inotify event on the cgroup + * + * 2. On the legacy hierarchy, when running in system mode, we get a datagram on the cgroup agent socket + * + * 3. On the legacy hierarchy, when running in user mode, we get a D-Bus signal on the system bus + * + * 4. On the legacy hierarchy, in service units we start watching all processes of the cgroup for SIGCHLD as + * soon as we get one SIGCHLD, to deal with unreliable cgroup notifications. + * + * Regardless which way we got the notification, we'll verify it here, and then add it to a separate + * queue. This queue will be dispatched at a lower priority than the SIGCHLD handler, so that we always use + * SIGCHLD if we can get it first, and only use the cgroup empty notifications if there's no SIGCHLD pending + * (which might happen if the cgroup doesn't contain processes that are our own child, which is typically the + * case for scope units). */ + + if (u->in_cgroup_empty_queue) + return; + + /* Let's verify that the cgroup is really empty */ + if (!u->cgroup_path) + return; + + r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path); + if (r < 0) { + log_unit_debug_errno(u, r, "Failed to determine whether cgroup %s is empty: %m", u->cgroup_path); + return; + } + if (r == 0) + return; + + LIST_PREPEND(cgroup_empty_queue, u->manager->cgroup_empty_queue, u); + u->in_cgroup_empty_queue = true; + + /* Trigger the defer event */ + r = sd_event_source_set_enabled(u->manager->cgroup_empty_event_source, SD_EVENT_ONESHOT); + if (r < 0) + log_debug_errno(r, "Failed to enable cgroup empty event source: %m"); +} + +int unit_check_oom(Unit *u) { + _cleanup_free_ char *oom_kill = NULL; + bool increased; + uint64_t c; + int r; + + if (!u->cgroup_path) + return 0; + + r = cg_get_keyed_attribute("memory", u->cgroup_path, "memory.events", STRV_MAKE("oom_kill"), &oom_kill); + if (r < 0) + return log_unit_debug_errno(u, r, "Failed to read oom_kill field of memory.events cgroup attribute: %m"); + + r = safe_atou64(oom_kill, &c); + if (r < 0) + return log_unit_debug_errno(u, r, "Failed to parse oom_kill field: %m"); + + increased = c > u->oom_kill_last; + u->oom_kill_last = c; + + if (!increased) + return 0; + + log_struct(LOG_NOTICE, + "MESSAGE_ID=" SD_MESSAGE_UNIT_OUT_OF_MEMORY_STR, + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u), + LOG_UNIT_MESSAGE(u, "A process of this unit has been killed by the OOM killer.")); + + if (UNIT_VTABLE(u)->notify_cgroup_oom) + UNIT_VTABLE(u)->notify_cgroup_oom(u); + + return 1; +} + +static int on_cgroup_oom_event(sd_event_source *s, void *userdata) { + Manager *m = userdata; + Unit *u; + int r; + + assert(s); + assert(m); + + u = m->cgroup_oom_queue; + if (!u) + return 0; + + assert(u->in_cgroup_oom_queue); + u->in_cgroup_oom_queue = false; + LIST_REMOVE(cgroup_oom_queue, m->cgroup_oom_queue, u); + + if (m->cgroup_oom_queue) { + /* More stuff queued, let's make sure we remain enabled */ + r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT); + if (r < 0) + log_debug_errno(r, "Failed to reenable cgroup oom event source, ignoring: %m"); + } + + (void) unit_check_oom(u); + return 0; +} + +static void unit_add_to_cgroup_oom_queue(Unit *u) { + int r; + + assert(u); + + if (u->in_cgroup_oom_queue) + return; + if (!u->cgroup_path) + return; + + LIST_PREPEND(cgroup_oom_queue, u->manager->cgroup_oom_queue, u); + u->in_cgroup_oom_queue = true; + + /* Trigger the defer event */ + if (!u->manager->cgroup_oom_event_source) { + _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL; + + r = sd_event_add_defer(u->manager->event, &s, on_cgroup_oom_event, u->manager); + if (r < 0) { + log_error_errno(r, "Failed to create cgroup oom event source: %m"); + return; + } + + r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_NORMAL-8); + if (r < 0) { + log_error_errno(r, "Failed to set priority of cgroup oom event source: %m"); + return; + } + + (void) sd_event_source_set_description(s, "cgroup-oom"); + u->manager->cgroup_oom_event_source = TAKE_PTR(s); + } + + r = sd_event_source_set_enabled(u->manager->cgroup_oom_event_source, SD_EVENT_ONESHOT); + if (r < 0) + log_error_errno(r, "Failed to enable cgroup oom event source: %m"); +} + +static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + + assert(s); + assert(fd >= 0); + assert(m); + + for (;;) { + union inotify_event_buffer buffer; + struct inotify_event *e; + ssize_t l; + + l = read(fd, &buffer, sizeof(buffer)); + if (l < 0) { + if (IN_SET(errno, EINTR, EAGAIN)) + return 0; + + return log_error_errno(errno, "Failed to read control group inotify events: %m"); + } + + FOREACH_INOTIFY_EVENT(e, buffer, l) { + Unit *u; + + if (e->wd < 0) + /* Queue overflow has no watch descriptor */ + continue; + + if (e->mask & IN_IGNORED) + /* The watch was just removed */ + continue; + + /* Note that inotify might deliver events for a watch even after it was removed, + * because it was queued before the removal. Let's ignore this here safely. */ + + u = hashmap_get(m->cgroup_control_inotify_wd_unit, INT_TO_PTR(e->wd)); + if (u) + unit_add_to_cgroup_empty_queue(u); + + u = hashmap_get(m->cgroup_memory_inotify_wd_unit, INT_TO_PTR(e->wd)); + if (u) + unit_add_to_cgroup_oom_queue(u); + } + } +} + +static int cg_bpf_mask_supported(CGroupMask *ret) { + CGroupMask mask = 0; + int r; + + /* BPF-based firewall */ + r = bpf_firewall_supported(); + if (r > 0) + mask |= CGROUP_MASK_BPF_FIREWALL; + + /* BPF-based device access control */ + r = bpf_devices_supported(); + if (r > 0) + mask |= CGROUP_MASK_BPF_DEVICES; + + *ret = mask; + return 0; +} + +int manager_setup_cgroup(Manager *m) { + _cleanup_free_ char *path = NULL; + const char *scope_path; + CGroupController c; + int r, all_unified; + CGroupMask mask; + char *e; + + assert(m); + + /* 1. Determine hierarchy */ + m->cgroup_root = mfree(m->cgroup_root); + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root); + if (r < 0) + return log_error_errno(r, "Cannot determine cgroup we are running in: %m"); + + /* Chop off the init scope, if we are already located in it */ + e = endswith(m->cgroup_root, "/" SPECIAL_INIT_SCOPE); + + /* LEGACY: Also chop off the system slice if we are in + * it. This is to support live upgrades from older systemd + * versions where PID 1 was moved there. Also see + * cg_get_root_path(). */ + if (!e && MANAGER_IS_SYSTEM(m)) { + e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE); + if (!e) + e = endswith(m->cgroup_root, "/system"); /* even more legacy */ + } + if (e) + *e = 0; + + /* And make sure to store away the root value without trailing slash, even for the root dir, so that we can + * easily prepend it everywhere. */ + delete_trailing_chars(m->cgroup_root, "/"); + + /* 2. Show data */ + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path); + if (r < 0) + return log_error_errno(r, "Cannot find cgroup mount point: %m"); + + r = cg_unified(); + if (r < 0) + return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m"); + + all_unified = cg_all_unified(); + if (all_unified < 0) + return log_error_errno(all_unified, "Couldn't determine whether we are in all unified mode: %m"); + if (all_unified > 0) + log_debug("Unified cgroup hierarchy is located at %s.", path); + else { + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) + return log_error_errno(r, "Failed to determine whether systemd's own controller is in unified mode: %m"); + if (r > 0) + log_debug("Unified cgroup hierarchy is located at %s. Controllers are on legacy hierarchies.", path); + else + log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER_LEGACY ". File system hierarchy is at %s.", path); + } + + /* 3. Allocate cgroup empty defer event source */ + m->cgroup_empty_event_source = sd_event_source_unref(m->cgroup_empty_event_source); + r = sd_event_add_defer(m->event, &m->cgroup_empty_event_source, on_cgroup_empty_event, m); + if (r < 0) + return log_error_errno(r, "Failed to create cgroup empty event source: %m"); + + /* Schedule cgroup empty checks early, but after having processed service notification messages or + * SIGCHLD signals, so that a cgroup running empty is always just the last safety net of + * notification, and we collected the metadata the notification and SIGCHLD stuff offers first. */ + r = sd_event_source_set_priority(m->cgroup_empty_event_source, SD_EVENT_PRIORITY_NORMAL-5); + if (r < 0) + return log_error_errno(r, "Failed to set priority of cgroup empty event source: %m"); + + r = sd_event_source_set_enabled(m->cgroup_empty_event_source, SD_EVENT_OFF); + if (r < 0) + return log_error_errno(r, "Failed to disable cgroup empty event source: %m"); + + (void) sd_event_source_set_description(m->cgroup_empty_event_source, "cgroup-empty"); + + /* 4. Install notifier inotify object, or agent */ + if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0) { + + /* In the unified hierarchy we can get cgroup empty notifications via inotify. */ + + m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source); + safe_close(m->cgroup_inotify_fd); + + m->cgroup_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (m->cgroup_inotify_fd < 0) + return log_error_errno(errno, "Failed to create control group inotify object: %m"); + + r = sd_event_add_io(m->event, &m->cgroup_inotify_event_source, m->cgroup_inotify_fd, EPOLLIN, on_cgroup_inotify_event, m); + if (r < 0) + return log_error_errno(r, "Failed to watch control group inotify object: %m"); + + /* Process cgroup empty notifications early. Note that when this event is dispatched it'll + * just add the unit to a cgroup empty queue, hence let's run earlier than that. Also see + * handling of cgroup agent notifications, for the classic cgroup hierarchy support. */ + r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_NORMAL-9); + if (r < 0) + return log_error_errno(r, "Failed to set priority of inotify event source: %m"); + + (void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify"); + + } else if (MANAGER_IS_SYSTEM(m) && manager_owns_host_root_cgroup(m) && !MANAGER_IS_TEST_RUN(m)) { + + /* On the legacy hierarchy we only get notifications via cgroup agents. (Which isn't really reliable, + * since it does not generate events when control groups with children run empty. */ + + r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH); + if (r < 0) + log_warning_errno(r, "Failed to install release agent, ignoring: %m"); + else if (r > 0) + log_debug("Installed release agent."); + else if (r == 0) + log_debug("Release agent already installed."); + } + + /* 5. Make sure we are in the special "init.scope" unit in the root slice. */ + scope_path = strjoina(m->cgroup_root, "/" SPECIAL_INIT_SCOPE); + r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0); + if (r >= 0) { + /* Also, move all other userspace processes remaining in the root cgroup into that scope. */ + r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, 0); + if (r < 0) + log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m"); + + /* 6. And pin it, so that it cannot be unmounted */ + safe_close(m->pin_cgroupfs_fd); + m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK); + if (m->pin_cgroupfs_fd < 0) + return log_error_errno(errno, "Failed to open pin file: %m"); + + } else if (!MANAGER_IS_TEST_RUN(m)) + return log_error_errno(r, "Failed to create %s control group: %m", scope_path); + + /* 7. Always enable hierarchical support if it exists... */ + if (!all_unified && !MANAGER_IS_TEST_RUN(m)) + (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1"); + + /* 8. Figure out which controllers are supported */ + r = cg_mask_supported(&m->cgroup_supported); + if (r < 0) + return log_error_errno(r, "Failed to determine supported controllers: %m"); + + /* 9. Figure out which bpf-based pseudo-controllers are supported */ + r = cg_bpf_mask_supported(&mask); + if (r < 0) + return log_error_errno(r, "Failed to determine supported bpf-based pseudo-controllers: %m"); + m->cgroup_supported |= mask; + + /* 10. Log which controllers are supported */ + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) + log_debug("Controller '%s' supported: %s", cgroup_controller_to_string(c), yes_no(m->cgroup_supported & CGROUP_CONTROLLER_TO_MASK(c))); + + return 0; +} + +void manager_shutdown_cgroup(Manager *m, bool delete) { + assert(m); + + /* We can't really delete the group, since we are in it. But + * let's trim it. */ + if (delete && m->cgroup_root && m->test_run_flags != MANAGER_TEST_RUN_MINIMAL) + (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false); + + m->cgroup_empty_event_source = sd_event_source_unref(m->cgroup_empty_event_source); + + m->cgroup_control_inotify_wd_unit = hashmap_free(m->cgroup_control_inotify_wd_unit); + m->cgroup_memory_inotify_wd_unit = hashmap_free(m->cgroup_memory_inotify_wd_unit); + + m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source); + m->cgroup_inotify_fd = safe_close(m->cgroup_inotify_fd); + + m->pin_cgroupfs_fd = safe_close(m->pin_cgroupfs_fd); + + m->cgroup_root = mfree(m->cgroup_root); +} + +Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) { + char *p; + Unit *u; + + assert(m); + assert(cgroup); + + u = hashmap_get(m->cgroup_unit, cgroup); + if (u) + return u; + + p = strdupa(cgroup); + for (;;) { + char *e; + + e = strrchr(p, '/'); + if (!e || e == p) + return hashmap_get(m->cgroup_unit, SPECIAL_ROOT_SLICE); + + *e = 0; + + u = hashmap_get(m->cgroup_unit, p); + if (u) + return u; + } +} + +Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid) { + _cleanup_free_ char *cgroup = NULL; + + assert(m); + + if (!pid_is_valid(pid)) + return NULL; + + if (cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup) < 0) + return NULL; + + return manager_get_unit_by_cgroup(m, cgroup); +} + +Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) { + Unit *u, **array; + + assert(m); + + /* Note that a process might be owned by multiple units, we return only one here, which is good enough for most + * cases, though not strictly correct. We prefer the one reported by cgroup membership, as that's the most + * relevant one as children of the process will be assigned to that one, too, before all else. */ + + if (!pid_is_valid(pid)) + return NULL; + + if (pid == getpid_cached()) + return hashmap_get(m->units, SPECIAL_INIT_SCOPE); + + u = manager_get_unit_by_pid_cgroup(m, pid); + if (u) + return u; + + u = hashmap_get(m->watch_pids, PID_TO_PTR(pid)); + if (u) + return u; + + array = hashmap_get(m->watch_pids, PID_TO_PTR(-pid)); + if (array) + return array[0]; + + return NULL; +} + +int manager_notify_cgroup_empty(Manager *m, const char *cgroup) { + Unit *u; + + assert(m); + assert(cgroup); + + /* Called on the legacy hierarchy whenever we get an explicit cgroup notification from the cgroup agent process + * or from the --system instance */ + + log_debug("Got cgroup empty notification for: %s", cgroup); + + u = manager_get_unit_by_cgroup(m, cgroup); + if (!u) + return 0; + + unit_add_to_cgroup_empty_queue(u); + return 1; +} + +int unit_get_memory_current(Unit *u, uint64_t *ret) { + _cleanup_free_ char *v = NULL; + int r; + + assert(u); + assert(ret); + + if (!UNIT_CGROUP_BOOL(u, memory_accounting)) + return -ENODATA; + + if (!u->cgroup_path) + return -ENODATA; + + /* The root cgroup doesn't expose this information, let's get it from /proc instead */ + if (unit_has_host_root_cgroup(u)) + return procfs_memory_get_used(ret); + + if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0) + return -ENODATA; + + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) + r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v); + else + r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + + return safe_atou64(v, ret); +} + +int unit_get_tasks_current(Unit *u, uint64_t *ret) { + _cleanup_free_ char *v = NULL; + int r; + + assert(u); + assert(ret); + + if (!UNIT_CGROUP_BOOL(u, tasks_accounting)) + return -ENODATA; + + if (!u->cgroup_path) + return -ENODATA; + + /* The root cgroup doesn't expose this information, let's get it from /proc instead */ + if (unit_has_host_root_cgroup(u)) + return procfs_tasks_get_current(ret); + + if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0) + return -ENODATA; + + r = cg_get_attribute("pids", u->cgroup_path, "pids.current", &v); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + + return safe_atou64(v, ret); +} + +static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) { + _cleanup_free_ char *v = NULL; + uint64_t ns; + int r; + + assert(u); + assert(ret); + + if (!u->cgroup_path) + return -ENODATA; + + /* The root cgroup doesn't expose this information, let's get it from /proc instead */ + if (unit_has_host_root_cgroup(u)) + return procfs_cpu_get_usage(ret); + + /* Requisite controllers for CPU accounting are not enabled */ + if ((get_cpu_accounting_mask() & ~u->cgroup_realized_mask) != 0) + return -ENODATA; + + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) { + _cleanup_free_ char *val = NULL; + uint64_t us; + + r = cg_get_keyed_attribute("cpu", u->cgroup_path, "cpu.stat", STRV_MAKE("usage_usec"), &val); + if (IN_SET(r, -ENOENT, -ENXIO)) + return -ENODATA; + if (r < 0) + return r; + + r = safe_atou64(val, &us); + if (r < 0) + return r; + + ns = us * NSEC_PER_USEC; + } else { + r = cg_get_attribute("cpuacct", u->cgroup_path, "cpuacct.usage", &v); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + + r = safe_atou64(v, &ns); + if (r < 0) + return r; + } + + *ret = ns; + return 0; +} + +int unit_get_cpu_usage(Unit *u, nsec_t *ret) { + nsec_t ns; + int r; + + assert(u); + + /* Retrieve the current CPU usage counter. This will subtract the CPU counter taken when the unit was + * started. If the cgroup has been removed already, returns the last cached value. To cache the value, simply + * call this function with a NULL return value. */ + + if (!UNIT_CGROUP_BOOL(u, cpu_accounting)) + return -ENODATA; + + r = unit_get_cpu_usage_raw(u, &ns); + if (r == -ENODATA && u->cpu_usage_last != NSEC_INFINITY) { + /* If we can't get the CPU usage anymore (because the cgroup was already removed, for example), use our + * cached value. */ + + if (ret) + *ret = u->cpu_usage_last; + return 0; + } + if (r < 0) + return r; + + if (ns > u->cpu_usage_base) + ns -= u->cpu_usage_base; + else + ns = 0; + + u->cpu_usage_last = ns; + if (ret) + *ret = ns; + + return 0; +} + +int unit_get_ip_accounting( + Unit *u, + CGroupIPAccountingMetric metric, + uint64_t *ret) { + + uint64_t value; + int fd, r; + + assert(u); + assert(metric >= 0); + assert(metric < _CGROUP_IP_ACCOUNTING_METRIC_MAX); + assert(ret); + + if (!UNIT_CGROUP_BOOL(u, ip_accounting)) + return -ENODATA; + + fd = IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_INGRESS_PACKETS) ? + u->ip_accounting_ingress_map_fd : + u->ip_accounting_egress_map_fd; + if (fd < 0) + return -ENODATA; + + if (IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_EGRESS_BYTES)) + r = bpf_firewall_read_accounting(fd, &value, NULL); + else + r = bpf_firewall_read_accounting(fd, NULL, &value); + if (r < 0) + return r; + + /* Add in additional metrics from a previous runtime. Note that when reexecing/reloading the daemon we compile + * all BPF programs and maps anew, but serialize the old counters. When deserializing we store them in the + * ip_accounting_extra[] field, and add them in here transparently. */ + + *ret = value + u->ip_accounting_extra[metric]; + + return r; +} + +static int unit_get_io_accounting_raw(Unit *u, uint64_t ret[static _CGROUP_IO_ACCOUNTING_METRIC_MAX]) { + static const char *const field_names[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = { + [CGROUP_IO_READ_BYTES] = "rbytes=", + [CGROUP_IO_WRITE_BYTES] = "wbytes=", + [CGROUP_IO_READ_OPERATIONS] = "rios=", + [CGROUP_IO_WRITE_OPERATIONS] = "wios=", + }; + uint64_t acc[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {}; + _cleanup_free_ char *path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(u); + + if (!u->cgroup_path) + return -ENODATA; + + if (unit_has_host_root_cgroup(u)) + return -ENODATA; /* TODO: return useful data for the top-level cgroup */ + + r = cg_all_unified(); + if (r < 0) + return r; + if (r == 0) /* TODO: support cgroupv1 */ + return -ENODATA; + + if (!FLAGS_SET(u->cgroup_realized_mask, CGROUP_MASK_IO)) + return -ENODATA; + + r = cg_get_path("io", u->cgroup_path, "io.stat", &path); + if (r < 0) + return r; + + f = fopen(path, "re"); + if (!f) + return -errno; + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *p; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + p = line; + p += strcspn(p, WHITESPACE); /* Skip over device major/minor */ + p += strspn(p, WHITESPACE); /* Skip over following whitespace */ + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE); + if (r < 0) + return r; + if (r == 0) + break; + + for (CGroupIOAccountingMetric i = 0; i < _CGROUP_IO_ACCOUNTING_METRIC_MAX; i++) { + const char *x; + + x = startswith(word, field_names[i]); + if (x) { + uint64_t w; + + r = safe_atou64(x, &w); + if (r < 0) + return r; + + /* Sum up the stats of all devices */ + acc[i] += w; + break; + } + } + } + } + + memcpy(ret, acc, sizeof(acc)); + return 0; +} + +int unit_get_io_accounting( + Unit *u, + CGroupIOAccountingMetric metric, + bool allow_cache, + uint64_t *ret) { + + uint64_t raw[_CGROUP_IO_ACCOUNTING_METRIC_MAX]; + int r; + + /* Retrieve an IO account parameter. This will subtract the counter when the unit was started. */ + + if (!UNIT_CGROUP_BOOL(u, io_accounting)) + return -ENODATA; + + if (allow_cache && u->io_accounting_last[metric] != UINT64_MAX) + goto done; + + r = unit_get_io_accounting_raw(u, raw); + if (r == -ENODATA && u->io_accounting_last[metric] != UINT64_MAX) + goto done; + if (r < 0) + return r; + + for (CGroupIOAccountingMetric i = 0; i < _CGROUP_IO_ACCOUNTING_METRIC_MAX; i++) { + /* Saturated subtraction */ + if (raw[i] > u->io_accounting_base[i]) + u->io_accounting_last[i] = raw[i] - u->io_accounting_base[i]; + else + u->io_accounting_last[i] = 0; + } + +done: + if (ret) + *ret = u->io_accounting_last[metric]; + + return 0; +} + +int unit_reset_cpu_accounting(Unit *u) { + int r; + + assert(u); + + u->cpu_usage_last = NSEC_INFINITY; + + r = unit_get_cpu_usage_raw(u, &u->cpu_usage_base); + if (r < 0) { + u->cpu_usage_base = 0; + return r; + } + + return 0; +} + +int unit_reset_ip_accounting(Unit *u) { + int r = 0, q = 0; + + assert(u); + + if (u->ip_accounting_ingress_map_fd >= 0) + r = bpf_firewall_reset_accounting(u->ip_accounting_ingress_map_fd); + + if (u->ip_accounting_egress_map_fd >= 0) + q = bpf_firewall_reset_accounting(u->ip_accounting_egress_map_fd); + + zero(u->ip_accounting_extra); + + return r < 0 ? r : q; +} + +int unit_reset_io_accounting(Unit *u) { + int r; + + assert(u); + + for (CGroupIOAccountingMetric i = 0; i < _CGROUP_IO_ACCOUNTING_METRIC_MAX; i++) + u->io_accounting_last[i] = UINT64_MAX; + + r = unit_get_io_accounting_raw(u, u->io_accounting_base); + if (r < 0) { + zero(u->io_accounting_base); + return r; + } + + return 0; +} + +int unit_reset_accounting(Unit *u) { + int r, q, v; + + assert(u); + + r = unit_reset_cpu_accounting(u); + q = unit_reset_io_accounting(u); + v = unit_reset_ip_accounting(u); + + return r < 0 ? r : q < 0 ? q : v; +} + +void unit_invalidate_cgroup(Unit *u, CGroupMask m) { + assert(u); + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return; + + if (m == 0) + return; + + /* always invalidate compat pairs together */ + if (m & (CGROUP_MASK_IO | CGROUP_MASK_BLKIO)) + m |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO; + + if (m & (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT)) + m |= CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT; + + if (FLAGS_SET(u->cgroup_invalidated_mask, m)) /* NOP? */ + return; + + u->cgroup_invalidated_mask |= m; + unit_add_to_cgroup_realize_queue(u); +} + +void unit_invalidate_cgroup_bpf(Unit *u) { + assert(u); + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return; + + if (u->cgroup_invalidated_mask & CGROUP_MASK_BPF_FIREWALL) /* NOP? */ + return; + + u->cgroup_invalidated_mask |= CGROUP_MASK_BPF_FIREWALL; + unit_add_to_cgroup_realize_queue(u); + + /* If we are a slice unit, we also need to put compile a new BPF program for all our children, as the IP access + * list of our children includes our own. */ + if (u->type == UNIT_SLICE) { + Unit *member; + Iterator i; + void *v; + + HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) { + if (UNIT_DEREF(member->slice) == u) + unit_invalidate_cgroup_bpf(member); + } + } +} + +bool unit_cgroup_delegate(Unit *u) { + CGroupContext *c; + + assert(u); + + if (!UNIT_VTABLE(u)->can_delegate) + return false; + + c = unit_get_cgroup_context(u); + if (!c) + return false; + + return c->delegate; +} + +void manager_invalidate_startup_units(Manager *m) { + Iterator i; + Unit *u; + + assert(m); + + SET_FOREACH(u, m->startup_units, i) + unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_BLKIO); +} + +static int unit_get_nice(Unit *u) { + ExecContext *ec; + + ec = unit_get_exec_context(u); + return ec ? ec->nice : 0; +} + +static uint64_t unit_get_cpu_weight(Unit *u) { + ManagerState state = manager_state(u->manager); + CGroupContext *cc; + + cc = unit_get_cgroup_context(u); + return cc ? cgroup_context_cpu_weight(cc, state) : CGROUP_WEIGHT_DEFAULT; +} + +int compare_job_priority(const void *a, const void *b) { + const Job *x = a, *y = b; + int nice_x, nice_y; + uint64_t weight_x, weight_y; + int ret; + + if ((ret = CMP(x->unit->type, y->unit->type)) != 0) + return -ret; + + weight_x = unit_get_cpu_weight(x->unit); + weight_y = unit_get_cpu_weight(y->unit); + + if ((ret = CMP(weight_x, weight_y)) != 0) + return -ret; + + nice_x = unit_get_nice(x->unit); + nice_y = unit_get_nice(y->unit); + + if ((ret = CMP(nice_x, nice_y)) != 0) + return ret; + + return strcmp(x->unit->id, y->unit->id); +} + +static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = { + [CGROUP_DEVICE_POLICY_AUTO] = "auto", + [CGROUP_DEVICE_POLICY_CLOSED] = "closed", + [CGROUP_DEVICE_POLICY_STRICT] = "strict", +}; + +int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) { + _cleanup_free_ char *v = NULL; + int r; + + assert(u); + assert(cpus); + + if (!u->cgroup_path) + return -ENODATA; + + if ((u->cgroup_realized_mask & CGROUP_MASK_CPUSET) == 0) + return -ENODATA; + + r = cg_all_unified(); + if (r < 0) + return r; + if (r == 0) + return -ENODATA; + if (r > 0) + r = cg_get_attribute("cpuset", u->cgroup_path, name, &v); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + + return parse_cpu_set_full(v, cpus, false, NULL, NULL, 0, NULL); +} + +DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy); diff --git a/src/core/cgroup.h b/src/core/cgroup.h new file mode 100644 index 00000000..b6bd4e0d --- /dev/null +++ b/src/core/cgroup.h @@ -0,0 +1,276 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "cgroup-util.h" +#include "cpu-set-util.h" +#include "ip-address-access.h" +#include "list.h" +#include "time-util.h" + +typedef struct TasksMax { + /* If scale == 0, just use value; otherwise, value / scale. + * See tasks_max_resolve(). */ + uint64_t value; + uint64_t scale; +} TasksMax; + +#define TASKS_MAX_UNSET ((TasksMax) { .value = UINT64_MAX, .scale = 0 }) + +static inline bool tasks_max_isset(const TasksMax *tasks_max) { + return tasks_max->value != UINT64_MAX || tasks_max->scale != 0; +} + +uint64_t tasks_max_resolve(const TasksMax *tasks_max); + +typedef struct CGroupContext CGroupContext; +typedef struct CGroupDeviceAllow CGroupDeviceAllow; +typedef struct CGroupIODeviceWeight CGroupIODeviceWeight; +typedef struct CGroupIODeviceLimit CGroupIODeviceLimit; +typedef struct CGroupIODeviceLatency CGroupIODeviceLatency; +typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight; +typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth; + +typedef enum CGroupDevicePolicy { + /* When devices listed, will allow those, plus built-in ones, if none are listed will allow + * everything. */ + CGROUP_DEVICE_POLICY_AUTO, + + /* Everything forbidden, except built-in ones and listed ones. */ + CGROUP_DEVICE_POLICY_CLOSED, + + /* Everything forbidden, except for the listed devices */ + CGROUP_DEVICE_POLICY_STRICT, + + _CGROUP_DEVICE_POLICY_MAX, + _CGROUP_DEVICE_POLICY_INVALID = -1 +} CGroupDevicePolicy; + +struct CGroupDeviceAllow { + LIST_FIELDS(CGroupDeviceAllow, device_allow); + char *path; + bool r:1; + bool w:1; + bool m:1; +}; + +struct CGroupIODeviceWeight { + LIST_FIELDS(CGroupIODeviceWeight, device_weights); + char *path; + uint64_t weight; +}; + +struct CGroupIODeviceLimit { + LIST_FIELDS(CGroupIODeviceLimit, device_limits); + char *path; + uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX]; +}; + +struct CGroupIODeviceLatency { + LIST_FIELDS(CGroupIODeviceLatency, device_latencies); + char *path; + usec_t target_usec; +}; + +struct CGroupBlockIODeviceWeight { + LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights); + char *path; + uint64_t weight; +}; + +struct CGroupBlockIODeviceBandwidth { + LIST_FIELDS(CGroupBlockIODeviceBandwidth, device_bandwidths); + char *path; + uint64_t rbps; + uint64_t wbps; +}; + +struct CGroupContext { + bool cpu_accounting; + bool io_accounting; + bool blockio_accounting; + bool memory_accounting; + bool tasks_accounting; + bool ip_accounting; + + /* Configures the memory.oom.group attribute (on unified) */ + bool memory_oom_group; + + bool delegate; + CGroupMask delegate_controllers; + CGroupMask disable_controllers; + + /* For unified hierarchy */ + uint64_t cpu_weight; + uint64_t startup_cpu_weight; + usec_t cpu_quota_per_sec_usec; + usec_t cpu_quota_period_usec; + + CPUSet cpuset_cpus; + CPUSet cpuset_mems; + + uint64_t io_weight; + uint64_t startup_io_weight; + LIST_HEAD(CGroupIODeviceWeight, io_device_weights); + LIST_HEAD(CGroupIODeviceLimit, io_device_limits); + LIST_HEAD(CGroupIODeviceLatency, io_device_latencies); + + uint64_t default_memory_min; + uint64_t default_memory_low; + uint64_t memory_min; + uint64_t memory_low; + uint64_t memory_high; + uint64_t memory_max; + uint64_t memory_swap_max; + + bool default_memory_min_set; + bool default_memory_low_set; + bool memory_min_set; + bool memory_low_set; + + LIST_HEAD(IPAddressAccessItem, ip_address_allow); + LIST_HEAD(IPAddressAccessItem, ip_address_deny); + + char **ip_filters_ingress; + char **ip_filters_egress; + + /* For legacy hierarchies */ + uint64_t cpu_shares; + uint64_t startup_cpu_shares; + + uint64_t blockio_weight; + uint64_t startup_blockio_weight; + LIST_HEAD(CGroupBlockIODeviceWeight, blockio_device_weights); + LIST_HEAD(CGroupBlockIODeviceBandwidth, blockio_device_bandwidths); + + uint64_t memory_limit; + + CGroupDevicePolicy device_policy; + LIST_HEAD(CGroupDeviceAllow, device_allow); + + /* Common */ + TasksMax tasks_max; +}; + +/* Used when querying IP accounting data */ +typedef enum CGroupIPAccountingMetric { + CGROUP_IP_INGRESS_BYTES, + CGROUP_IP_INGRESS_PACKETS, + CGROUP_IP_EGRESS_BYTES, + CGROUP_IP_EGRESS_PACKETS, + _CGROUP_IP_ACCOUNTING_METRIC_MAX, + _CGROUP_IP_ACCOUNTING_METRIC_INVALID = -1, +} CGroupIPAccountingMetric; + +/* Used when querying IO accounting data */ +typedef enum CGroupIOAccountingMetric { + CGROUP_IO_READ_BYTES, + CGROUP_IO_WRITE_BYTES, + CGROUP_IO_READ_OPERATIONS, + CGROUP_IO_WRITE_OPERATIONS, + _CGROUP_IO_ACCOUNTING_METRIC_MAX, + _CGROUP_IO_ACCOUNTING_METRIC_INVALID = -1, +} CGroupIOAccountingMetric; + +typedef struct Unit Unit; +typedef struct Manager Manager; + +usec_t cgroup_cpu_adjust_period(usec_t period, usec_t quota, usec_t resolution, usec_t max_period); + +void cgroup_context_init(CGroupContext *c); +void cgroup_context_done(CGroupContext *c); +void cgroup_context_dump(Unit *u, FILE* f, const char *prefix); + +void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a); +void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w); +void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l); +void cgroup_context_free_io_device_latency(CGroupContext *c, CGroupIODeviceLatency *l); +void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w); +void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b); + +int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode); + +CGroupMask unit_get_own_mask(Unit *u); +CGroupMask unit_get_delegate_mask(Unit *u); +CGroupMask unit_get_members_mask(Unit *u); +CGroupMask unit_get_siblings_mask(Unit *u); +CGroupMask unit_get_subtree_mask(Unit *u); +CGroupMask unit_get_disable_mask(Unit *u); +CGroupMask unit_get_ancestor_disable_mask(Unit *u); + +CGroupMask unit_get_target_mask(Unit *u); +CGroupMask unit_get_enable_mask(Unit *u); + +void unit_invalidate_cgroup_members_masks(Unit *u); + +void unit_add_to_cgroup_realize_queue(Unit *u); + +const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask); +char *unit_default_cgroup_path(const Unit *u); +int unit_set_cgroup_path(Unit *u, const char *path); +int unit_pick_cgroup_path(Unit *u); + +int unit_realize_cgroup(Unit *u); +void unit_release_cgroup(Unit *u); +void unit_prune_cgroup(Unit *u); +int unit_watch_cgroup(Unit *u); +int unit_watch_cgroup_memory(Unit *u); + +void unit_add_to_cgroup_empty_queue(Unit *u); +int unit_check_oom(Unit *u); + +int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path); + +int manager_setup_cgroup(Manager *m); +void manager_shutdown_cgroup(Manager *m, bool delete); + +unsigned manager_dispatch_cgroup_realize_queue(Manager *m); + +Unit *manager_get_unit_by_cgroup(Manager *m, const char *cgroup); +Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid); +Unit* manager_get_unit_by_pid(Manager *m, pid_t pid); + +uint64_t unit_get_ancestor_memory_min(Unit *u); +uint64_t unit_get_ancestor_memory_low(Unit *u); + +int unit_search_main_pid(Unit *u, pid_t *ret); +int unit_watch_all_pids(Unit *u); + +int unit_synthesize_cgroup_empty_event(Unit *u); + +int unit_get_memory_current(Unit *u, uint64_t *ret); +int unit_get_tasks_current(Unit *u, uint64_t *ret); +int unit_get_cpu_usage(Unit *u, nsec_t *ret); +int unit_get_io_accounting(Unit *u, CGroupIOAccountingMetric metric, bool allow_cache, uint64_t *ret); +int unit_get_ip_accounting(Unit *u, CGroupIPAccountingMetric metric, uint64_t *ret); + +int unit_reset_cpu_accounting(Unit *u); +int unit_reset_ip_accounting(Unit *u); +int unit_reset_io_accounting(Unit *u); +int unit_reset_accounting(Unit *u); + +#define UNIT_CGROUP_BOOL(u, name) \ + ({ \ + CGroupContext *cc = unit_get_cgroup_context(u); \ + cc ? cc->name : false; \ + }) + +bool manager_owns_host_root_cgroup(Manager *m); +bool unit_has_host_root_cgroup(Unit *u); + +int manager_notify_cgroup_empty(Manager *m, const char *group); + +void unit_invalidate_cgroup(Unit *u, CGroupMask m); +void unit_invalidate_cgroup_bpf(Unit *u); + +void manager_invalidate_startup_units(Manager *m); + +const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_; +CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_; + +bool unit_cgroup_delegate(Unit *u); + +int compare_job_priority(const void *a, const void *b); + +int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name); diff --git a/src/core/chown-recursive.c b/src/core/chown-recursive.c new file mode 100644 index 00000000..24cdf25b --- /dev/null +++ b/src/core/chown-recursive.c @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "chown-recursive.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "macro.h" +#include "stdio-util.h" +#include "strv.h" +#include "user-util.h" + +static int chown_one( + int fd, + const struct stat *st, + uid_t uid, + gid_t gid, + mode_t mask) { + + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; + const char *n; + int r; + + assert(fd >= 0); + assert(st); + + /* We change ACLs through the /proc/self/fd/%i path, so that we have a stable reference that works + * with O_PATH. */ + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + + /* Drop any ACL if there is one */ + FOREACH_STRING(n, "system.posix_acl_access", "system.posix_acl_default") + if (removexattr(procfs_path, n) < 0) + if (!IN_SET(errno, ENODATA, EOPNOTSUPP, ENOSYS, ENOTTY)) + return -errno; + + r = fchmod_and_chown(fd, st->st_mode & mask, uid, gid); + if (r < 0) + return r; + + return 1; +} + +static int chown_recursive_internal( + int fd, + const struct stat *st, + uid_t uid, + gid_t gid, + mode_t mask) { + + _cleanup_closedir_ DIR *d = NULL; + bool changed = false; + struct dirent *de; + int r; + + assert(fd >= 0); + assert(st); + + d = fdopendir(fd); + if (!d) { + safe_close(fd); + return -errno; + } + + FOREACH_DIRENT_ALL(de, d, return -errno) { + _cleanup_close_ int path_fd = -1; + struct stat fst; + + if (dot_or_dot_dot(de->d_name)) + continue; + + /* Let's pin the child inode we want to fix now with an O_PATH fd, so that it cannot be swapped out + * while we manipulate it. */ + path_fd = openat(dirfd(d), de->d_name, O_PATH|O_CLOEXEC|O_NOFOLLOW); + if (path_fd < 0) + return -errno; + + if (fstat(path_fd, &fst) < 0) + return -errno; + + if (S_ISDIR(fst.st_mode)) { + int subdir_fd; + + /* Convert it to a "real" (i.e. non-O_PATH) fd now */ + subdir_fd = fd_reopen(path_fd, O_RDONLY|O_CLOEXEC|O_NOATIME); + if (subdir_fd < 0) + return subdir_fd; + + r = chown_recursive_internal(subdir_fd, &fst, uid, gid, mask); /* takes possession of subdir_fd even on failure */ + if (r < 0) + return r; + if (r > 0) + changed = true; + } else { + r = chown_one(path_fd, &fst, uid, gid, mask); + if (r < 0) + return r; + if (r > 0) + changed = true; + } + } + + r = chown_one(dirfd(d), st, uid, gid, mask); + if (r < 0) + return r; + + return r > 0 || changed; +} + +int path_chown_recursive( + const char *path, + uid_t uid, + gid_t gid, + mode_t mask) { + + _cleanup_close_ int fd = -1; + struct stat st; + + fd = open(path, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (fd < 0) + return -errno; + + if (!uid_is_valid(uid) && !gid_is_valid(gid) && (mask & 07777) == 07777) + return 0; /* nothing to do */ + + if (fstat(fd, &st) < 0) + return -errno; + + /* Let's take a shortcut: if the top-level directory is properly owned, we don't descend into the + * whole tree, under the assumption that all is OK anyway. */ + if ((!uid_is_valid(uid) || st.st_uid == uid) && + (!gid_is_valid(gid) || st.st_gid == gid) && + ((st.st_mode & ~mask & 07777) == 0)) + return 0; + + return chown_recursive_internal(TAKE_FD(fd), &st, uid, gid, mask); /* we donate the fd to the call, regardless if it succeeded or failed */ +} diff --git a/src/core/chown-recursive.h b/src/core/chown-recursive.h new file mode 100644 index 00000000..bfee05f3 --- /dev/null +++ b/src/core/chown-recursive.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int path_chown_recursive(const char *path, uid_t uid, gid_t gid, mode_t mask); diff --git a/src/core/dbus-automount.c b/src/core/dbus-automount.c new file mode 100644 index 00000000..bd6e6a9d --- /dev/null +++ b/src/core/dbus-automount.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "automount.h" +#include "bus-util.h" +#include "dbus-automount.h" +#include "dbus-util.h" +#include "string-util.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, automount_result, AutomountResult); + +const sd_bus_vtable bus_automount_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Where", "s", NULL, offsetof(Automount, where), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Automount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Automount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("TimeoutIdleUSec", "t", bus_property_get_usec, offsetof(Automount, timeout_idle_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_VTABLE_END +}; + +static int bus_automount_set_transient_property( + Automount *a, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Unit *u = UNIT(a); + + assert(a); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "Where")) + return bus_set_transient_path(u, name, &a->where, message, flags, error); + + if (streq(name, "TimeoutIdleUSec")) + return bus_set_transient_usec_fix_0(u, name, &a->timeout_idle_usec, message, flags, error); + + if (streq(name, "DirectoryMode")) + return bus_set_transient_mode_t(u, name, &a->directory_mode, message, flags, error); + + return 0; +} + +int bus_automount_set_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Automount *a = AUTOMOUNT(u); + + assert(a); + assert(name); + assert(message); + + if (u->transient && u->load_state == UNIT_STUB) /* This is a transient unit? let's load a little more */ + return bus_automount_set_transient_property(a, name, message, flags, error); + + return 0; +} diff --git a/src/core/dbus-automount.h b/src/core/dbus-automount.h new file mode 100644 index 00000000..3e165b05 --- /dev/null +++ b/src/core/dbus-automount.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" + +extern const sd_bus_vtable bus_automount_vtable[]; + +int bus_automount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c new file mode 100644 index 00000000..27dc9e43 --- /dev/null +++ b/src/core/dbus-cgroup.c @@ -0,0 +1,1675 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "af-list.h" +#include "alloc-util.h" +#include "bpf-firewall.h" +#include "bus-util.h" +#include "cgroup-util.h" +#include "cgroup.h" +#include "dbus-cgroup.h" +#include "dbus-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "limits-util.h" +#include "path-util.h" + +BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_resolve); + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy); + +static int property_get_cgroup_mask( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + CGroupMask *mask = userdata; + CGroupController ctrl; + int r; + + assert(bus); + assert(reply); + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + for (ctrl = 0; ctrl < _CGROUP_CONTROLLER_MAX; ctrl++) { + if ((*mask & CGROUP_CONTROLLER_TO_MASK(ctrl)) == 0) + continue; + + r = sd_bus_message_append(reply, "s", cgroup_controller_to_string(ctrl)); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_delegate_controllers( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + CGroupContext *c = userdata; + + assert(bus); + assert(reply); + assert(c); + + if (!c->delegate) + return sd_bus_message_append(reply, "as", 0); + + return property_get_cgroup_mask(bus, path, interface, property, reply, &c->delegate_controllers, error); +} + +static int property_get_cpuset( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + CPUSet *cpus = userdata; + _cleanup_free_ uint8_t *array = NULL; + size_t allocated; + + assert(bus); + assert(reply); + assert(cpus); + + (void) cpu_set_to_dbus(cpus, &array, &allocated); + return sd_bus_message_append_array(reply, 'y', array, allocated); +} + +static int property_get_io_device_weight( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + CGroupContext *c = userdata; + CGroupIODeviceWeight *w; + int r; + + assert(bus); + assert(reply); + assert(c); + + r = sd_bus_message_open_container(reply, 'a', "(st)"); + if (r < 0) + return r; + + LIST_FOREACH(device_weights, w, c->io_device_weights) { + r = sd_bus_message_append(reply, "(st)", w->path, w->weight); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_io_device_limits( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + CGroupContext *c = userdata; + CGroupIODeviceLimit *l; + int r; + + assert(bus); + assert(reply); + assert(c); + + r = sd_bus_message_open_container(reply, 'a', "(st)"); + if (r < 0) + return r; + + LIST_FOREACH(device_limits, l, c->io_device_limits) { + CGroupIOLimitType type; + + type = cgroup_io_limit_type_from_string(property); + if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type]) + continue; + + r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_io_device_latency( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + CGroupContext *c = userdata; + CGroupIODeviceLatency *l; + int r; + + assert(bus); + assert(reply); + assert(c); + + r = sd_bus_message_open_container(reply, 'a', "(st)"); + if (r < 0) + return r; + + LIST_FOREACH(device_latencies, l, c->io_device_latencies) { + r = sd_bus_message_append(reply, "(st)", l->path, l->target_usec); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_blockio_device_weight( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + CGroupContext *c = userdata; + CGroupBlockIODeviceWeight *w; + int r; + + assert(bus); + assert(reply); + assert(c); + + r = sd_bus_message_open_container(reply, 'a', "(st)"); + if (r < 0) + return r; + + LIST_FOREACH(device_weights, w, c->blockio_device_weights) { + r = sd_bus_message_append(reply, "(st)", w->path, w->weight); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_blockio_device_bandwidths( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + CGroupContext *c = userdata; + CGroupBlockIODeviceBandwidth *b; + int r; + + assert(bus); + assert(reply); + assert(c); + + r = sd_bus_message_open_container(reply, 'a', "(st)"); + if (r < 0) + return r; + + LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { + uint64_t v; + + if (streq(property, "BlockIOReadBandwidth")) + v = b->rbps; + else + v = b->wbps; + + if (v == CGROUP_LIMIT_MAX) + continue; + + r = sd_bus_message_append(reply, "(st)", b->path, v); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_device_allow( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + CGroupContext *c = userdata; + CGroupDeviceAllow *a; + int r; + + assert(bus); + assert(reply); + assert(c); + + r = sd_bus_message_open_container(reply, 'a', "(ss)"); + if (r < 0) + return r; + + LIST_FOREACH(device_allow, a, c->device_allow) { + unsigned k = 0; + char rwm[4]; + + if (a->r) + rwm[k++] = 'r'; + if (a->w) + rwm[k++] = 'w'; + if (a->m) + rwm[k++] = 'm'; + + rwm[k] = 0; + + r = sd_bus_message_append(reply, "(ss)", a->path, rwm); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_ip_address_access( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + IPAddressAccessItem** items = userdata, *i; + int r; + + r = sd_bus_message_open_container(reply, 'a', "(iayu)"); + if (r < 0) + return r; + + LIST_FOREACH(items, i, *items) { + + r = sd_bus_message_open_container(reply, 'r', "iayu"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "i", i->family); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', &i->address, FAMILY_ADDRESS_SIZE(i->family)); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "u", (uint32_t) i->prefixlen); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +const sd_bus_vtable bus_cgroup_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0), + SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers, 0, 0), + SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0), + SD_BUS_PROPERTY("CPUWeight", "t", NULL, offsetof(CGroupContext, cpu_weight), 0), + SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL, offsetof(CGroupContext, startup_cpu_weight), 0), + SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0), + SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0), + SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0), + SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_period_usec), 0), + SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_cpus), 0), + SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset, offsetof(CGroupContext, cpuset_mems), 0), + SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0), + SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0), + SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0), + SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight, 0, 0), + SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0), + SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0), + SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits, 0, 0), + SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits, 0, 0), + SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency, 0, 0), + SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0), + SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0), + SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0), + SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0), + SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0), + SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0), + SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0), + SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL, offsetof(CGroupContext, default_memory_low), 0), + SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL, offsetof(CGroupContext, default_memory_min), 0), + SD_BUS_PROPERTY("MemoryMin", "t", NULL, offsetof(CGroupContext, memory_min), 0), + SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0), + SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0), + SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0), + SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0), + SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0), + SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0), + SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0), + SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0), + SD_BUS_PROPERTY("TasksMax", "t", bus_property_get_tasks_max, offsetof(CGroupContext, tasks_max), 0), + SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, ip_accounting), 0), + SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_allow), 0), + SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_deny), 0), + SD_BUS_PROPERTY("IPIngressFilterPath", "as", NULL, offsetof(CGroupContext, ip_filters_ingress), 0), + SD_BUS_PROPERTY("IPEgressFilterPath", "as", NULL, offsetof(CGroupContext, ip_filters_egress), 0), + SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask, offsetof(CGroupContext, disable_controllers), 0), + SD_BUS_VTABLE_END +}; + +static int bus_cgroup_set_transient_property( + Unit *u, + CGroupContext *c, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + int r; + + assert(u); + assert(c); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "Delegate")) { + int b; + + if (!UNIT_VTABLE(u)->can_delegate) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type"); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->delegate = b; + c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0; + + unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b)); + } + + return 1; + + } else if (STR_IN_SET(name, "DelegateControllers", "DisableControllers")) { + CGroupMask mask = 0; + + if (streq(name, "DelegateControllers") && !UNIT_VTABLE(u)->can_delegate) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type"); + + r = sd_bus_message_enter_container(message, 'a', "s"); + if (r < 0) + return r; + + for (;;) { + CGroupController cc; + const char *t; + + r = sd_bus_message_read(message, "s", &t); + if (r < 0) + return r; + if (r == 0) + break; + + cc = cgroup_controller_from_string(t); + if (cc < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown cgroup controller '%s'", t); + + mask |= CGROUP_CONTROLLER_TO_MASK(cc); + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *t = NULL; + + r = cg_mask_to_string(mask, &t); + if (r < 0) + return r; + + if (streq(name, "DelegateControllers")) { + + c->delegate = true; + if (mask == 0) + c->delegate_controllers = 0; + else + c->delegate_controllers |= mask; + + unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t)); + + } else if (streq(name, "DisableControllers")) { + + if (mask == 0) + c->disable_controllers = 0; + else + c->disable_controllers |= mask; + + unit_write_settingf(u, flags, name, "%s=%s", name, strempty(t)); + } + } + + return 1; + } else if (STR_IN_SET(name, "IPIngressFilterPath", "IPEgressFilterPath")) { + char ***filters; + size_t n = 0; + + filters = streq(name, "IPIngressFilterPath") ? &c->ip_filters_ingress : &c->ip_filters_egress; + r = sd_bus_message_enter_container(message, 'a', "s"); + if (r < 0) + return r; + + for (;;) { + const char *path; + + r = sd_bus_message_read(message, "s", &path); + if (r < 0) + return r; + if (r == 0) + break; + + if (!path_is_normalized(path) || !path_is_absolute(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects a normalized absolute path.", name); + + if (!UNIT_WRITE_FLAGS_NOOP(flags) && !strv_contains(*filters, path)) { + r = strv_extend(filters, path); + if (r < 0) + return log_oom(); + } + n++; + } + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + char **entry; + size_t size = 0; + + if (n == 0) + *filters = strv_free(*filters); + + unit_invalidate_cgroup_bpf(u); + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + fputs(name, f); + fputs("=\n", f); + + STRV_FOREACH(entry, *filters) + fprintf(f, "%s=%s\n", name, *entry); + + r = fflush_and_check(f); + if (r < 0) + return r; + + unit_write_setting(u, flags, name, buf); + + if (*filters) { + r = bpf_firewall_supported(); + if (r < 0) + return r; + if (r != BPF_FIREWALL_SUPPORTED_WITH_MULTI) { + static bool warned = false; + + log_full(warned ? LOG_DEBUG : LOG_WARNING, + "Transient unit %s configures an IP firewall with BPF, but the local system does not support BPF/cgroup firewalling with multiple filters.\n" + "Starting this unit will fail! (This warning is only shown for the first started transient unit using IP firewalling.)", u->id); + warned = true; + } + } + } + + return 1; + } + + return 0; +} + +static int bus_cgroup_set_boolean( + Unit *u, + const char *name, + bool *p, + CGroupMask mask, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + int b, r; + + assert(p); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + *p = b; + unit_invalidate_cgroup(u, mask); + unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b)); + } + + return 1; +} + +#define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \ + static int bus_cgroup_set_##function( \ + Unit *u, \ + const char *name, \ + uint64_t *p, \ + sd_bus_message *message, \ + UnitWriteFlags flags, \ + sd_bus_error *error) { \ + \ + uint64_t v; \ + int r; \ + \ + assert(p); \ + \ + r = sd_bus_message_read(message, "t", &v); \ + if (r < 0) \ + return r; \ + \ + if (!check(v)) \ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \ + "Value specified in %s is out of range", name); \ + \ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \ + *p = v; \ + unit_invalidate_cgroup(u, mask); \ + \ + if (v == (val)) \ + unit_write_settingf(u, flags, name, \ + "%s=", name); \ + else \ + unit_write_settingf(u, flags, name, \ + "%s=%" PRIu64, name, v); \ + } \ + \ + return 1; \ + } + +#define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \ + static int bus_cgroup_set_##function( \ + Unit *u, \ + const char *name, \ + uint64_t *p, \ + sd_bus_message *message, \ + UnitWriteFlags flags, \ + sd_bus_error *error) { \ + \ + uint64_t v; \ + int r; \ + \ + assert(p); \ + \ + r = sd_bus_message_read(message, "t", &v); \ + if (r < 0) \ + return r; \ + \ + if (v < minimum) \ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \ + "Value specified in %s is out of range", name); \ + \ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \ + *p = v; \ + unit_invalidate_cgroup(u, mask); \ + \ + if (v == CGROUP_LIMIT_MAX) \ + unit_write_settingf(u, flags, name, \ + "%s=infinity", name); \ + else \ + unit_write_settingf(u, flags, name, \ + "%s=%" PRIu64, name, v); \ + } \ + \ + return 1; \ + } \ + static int bus_cgroup_set_##function##_scale( \ + Unit *u, \ + const char *name, \ + uint64_t *p, \ + sd_bus_message *message, \ + UnitWriteFlags flags, \ + sd_bus_error *error) { \ + \ + uint64_t v; \ + uint32_t raw; \ + int r; \ + \ + assert(p); \ + \ + r = sd_bus_message_read(message, "u", &raw); \ + if (r < 0) \ + return r; \ + \ + v = scale(raw, UINT32_MAX); \ + if (v < minimum || v >= UINT64_MAX) \ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \ + "Value specified in %s is out of range", name); \ + \ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \ + *p = v; \ + unit_invalidate_cgroup(u, mask); \ + \ + /* Prepare to chop off suffix */ \ + assert_se(endswith(name, "Scale")); \ + \ + uint32_t scaled = DIV_ROUND_UP((uint64_t) raw * 1000, (uint64_t) UINT32_MAX); \ + unit_write_settingf(u, flags, name, "%.*s=%" PRIu32 ".%" PRIu32 "%%", \ + (int)(strlen(name) - strlen("Scale")), name, \ + scaled / 10, scaled % 10); \ + } \ + \ + return 1; \ + } + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" +BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID); +BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID); +BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID); +BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID); +BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1); +BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection, CGROUP_MASK_MEMORY, physical_memory_scale, 0); +BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0); +#pragma GCC diagnostic pop + +static int bus_cgroup_set_tasks_max( + Unit *u, + const char *name, + TasksMax *p, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + uint64_t v; + int r; + + assert(p); + + r = sd_bus_message_read(message, "t", &v); + if (r < 0) + return r; + + if (v < 1) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Value specified in %s is out of range", name); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + *p = (TasksMax) { .value = v, .scale = 0 }; /* When .scale==0, .value is the absolute value */ + unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); + + if (v == CGROUP_LIMIT_MAX) + unit_write_settingf(u, flags, name, + "%s=infinity", name); + else + unit_write_settingf(u, flags, name, + "%s=%" PRIu64, name, v); + } + + return 1; +} + +static int bus_cgroup_set_tasks_max_scale( + Unit *u, + const char *name, + TasksMax *p, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + uint32_t v; + int r; + + assert(p); + + r = sd_bus_message_read(message, "u", &v); + if (r < 0) + return r; + + if (v < 1 || v >= UINT32_MAX) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Value specified in %s is out of range", name); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + *p = (TasksMax) { v, UINT32_MAX }; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */ + unit_invalidate_cgroup(u, CGROUP_MASK_PIDS); + + uint32_t scaled = DIV_ROUND_UP((uint64_t) v * 100U, (uint64_t) UINT32_MAX); + unit_write_settingf(u, flags, name, "%s=%" PRIu32 ".%" PRIu32 "%%", "TasksMax", + scaled / 10, scaled % 10); + } + + return 1; +} + +int bus_cgroup_set_property( + Unit *u, + CGroupContext *c, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + CGroupIOLimitType iol_type; + int r; + + assert(u); + assert(c); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "CPUAccounting")) + return bus_cgroup_set_boolean(u, name, &c->cpu_accounting, get_cpu_accounting_mask(), message, flags, error); + + if (streq(name, "CPUWeight")) + return bus_cgroup_set_cpu_weight(u, name, &c->cpu_weight, message, flags, error); + + if (streq(name, "StartupCPUWeight")) + return bus_cgroup_set_cpu_weight(u, name, &c->startup_cpu_weight, message, flags, error); + + if (streq(name, "CPUShares")) + return bus_cgroup_set_cpu_shares(u, name, &c->cpu_shares, message, flags, error); + + if (streq(name, "StartupCPUShares")) + return bus_cgroup_set_cpu_shares(u, name, &c->startup_cpu_shares, message, flags, error); + + if (streq(name, "IOAccounting")) + return bus_cgroup_set_boolean(u, name, &c->io_accounting, CGROUP_MASK_IO, message, flags, error); + + if (streq(name, "IOWeight")) + return bus_cgroup_set_io_weight(u, name, &c->io_weight, message, flags, error); + + if (streq(name, "StartupIOWeight")) + return bus_cgroup_set_io_weight(u, name, &c->startup_io_weight, message, flags, error); + + if (streq(name, "BlockIOAccounting")) + return bus_cgroup_set_boolean(u, name, &c->blockio_accounting, CGROUP_MASK_BLKIO, message, flags, error); + + if (streq(name, "BlockIOWeight")) + return bus_cgroup_set_blockio_weight(u, name, &c->blockio_weight, message, flags, error); + + if (streq(name, "StartupBlockIOWeight")) + return bus_cgroup_set_blockio_weight(u, name, &c->startup_blockio_weight, message, flags, error); + + if (streq(name, "MemoryAccounting")) + return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error); + + if (streq(name, "MemoryMin")) { + r = bus_cgroup_set_memory_protection(u, name, &c->memory_min, message, flags, error); + if (r > 0) + c->memory_min_set = true; + return r; + } + + if (streq(name, "MemoryLow")) { + r = bus_cgroup_set_memory_protection(u, name, &c->memory_low, message, flags, error); + if (r > 0) + c->memory_low_set = true; + return r; + } + + if (streq(name, "DefaultMemoryMin")) { + r = bus_cgroup_set_memory_protection(u, name, &c->default_memory_min, message, flags, error); + if (r > 0) + c->default_memory_min_set = true; + return r; + } + + if (streq(name, "DefaultMemoryLow")) { + r = bus_cgroup_set_memory_protection(u, name, &c->default_memory_low, message, flags, error); + if (r > 0) + c->default_memory_low_set = true; + return r; + } + + if (streq(name, "MemoryHigh")) + return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error); + + if (streq(name, "MemorySwapMax")) + return bus_cgroup_set_swap(u, name, &c->memory_swap_max, message, flags, error); + + if (streq(name, "MemoryMax")) + return bus_cgroup_set_memory(u, name, &c->memory_max, message, flags, error); + + if (streq(name, "MemoryLimit")) + return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error); + + if (streq(name, "MemoryMinScale")) { + r = bus_cgroup_set_memory_protection_scale(u, name, &c->memory_min, message, flags, error); + if (r > 0) + c->memory_min_set = true; + return r; + } + + if (streq(name, "MemoryLowScale")) { + r = bus_cgroup_set_memory_protection_scale(u, name, &c->memory_low, message, flags, error); + if (r > 0) + c->memory_low_set = true; + return r; + } + + if (streq(name, "DefaultMemoryMinScale")) { + r = bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_min, message, flags, error); + if (r > 0) + c->default_memory_min_set = true; + return r; + } + + if (streq(name, "DefaultMemoryLowScale")) { + r = bus_cgroup_set_memory_protection_scale(u, name, &c->default_memory_low, message, flags, error); + if (r > 0) + c->default_memory_low_set = true; + return r; + } + + if (streq(name, "MemoryHighScale")) + return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, error); + + if (streq(name, "MemorySwapMaxScale")) + return bus_cgroup_set_swap_scale(u, name, &c->memory_swap_max, message, flags, error); + + if (streq(name, "MemoryMaxScale")) + return bus_cgroup_set_memory_scale(u, name, &c->memory_max, message, flags, error); + + if (streq(name, "MemoryLimitScale")) + return bus_cgroup_set_memory_scale(u, name, &c->memory_limit, message, flags, error); + + if (streq(name, "TasksAccounting")) + return bus_cgroup_set_boolean(u, name, &c->tasks_accounting, CGROUP_MASK_PIDS, message, flags, error); + + if (streq(name, "TasksMax")) + return bus_cgroup_set_tasks_max(u, name, &c->tasks_max, message, flags, error); + + if (streq(name, "TasksMaxScale")) + return bus_cgroup_set_tasks_max_scale(u, name, &c->tasks_max, message, flags, error); + + if (streq(name, "CPUQuotaPerSecUSec")) { + uint64_t u64; + + r = sd_bus_message_read(message, "t", &u64); + if (r < 0) + return r; + + if (u64 <= 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "CPUQuotaPerSecUSec= value out of range"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->cpu_quota_per_sec_usec = u64; + u->warned_clamping_cpu_quota_period = false; + unit_invalidate_cgroup(u, CGROUP_MASK_CPU); + + if (c->cpu_quota_per_sec_usec == USEC_INFINITY) + unit_write_setting(u, flags, "CPUQuota", "CPUQuota="); + else + /* config_parse_cpu_quota() requires an integer, so truncating division is used on + * purpose here. */ + unit_write_settingf(u, flags, "CPUQuota", + "CPUQuota=%0.f%%", + (double) (c->cpu_quota_per_sec_usec / 10000)); + } + + return 1; + + } else if (streq(name, "CPUQuotaPeriodUSec")) { + uint64_t u64; + + r = sd_bus_message_read(message, "t", &u64); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->cpu_quota_period_usec = u64; + u->warned_clamping_cpu_quota_period = false; + unit_invalidate_cgroup(u, CGROUP_MASK_CPU); + if (c->cpu_quota_period_usec == USEC_INFINITY) + unit_write_setting(u, flags, "CPUQuotaPeriodSec", "CPUQuotaPeriodSec="); + else { + char v[FORMAT_TIMESPAN_MAX]; + unit_write_settingf(u, flags, "CPUQuotaPeriodSec", + "CPUQuotaPeriodSec=%s", + format_timespan(v, sizeof(v), c->cpu_quota_period_usec, 1)); + } + } + + return 1; + + } else if (STR_IN_SET(name, "AllowedCPUs", "AllowedMemoryNodes")) { + const void *a; + size_t n; + _cleanup_(cpu_set_reset) CPUSet new_set = {}; + + r = sd_bus_message_read_array(message, 'y', &a, &n); + if (r < 0) + return r; + + r = cpu_set_from_dbus(a, n, &new_set); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *setstr = NULL; + CPUSet *set; + + setstr = cpu_set_to_range_string(&new_set); + if (!setstr) + return -ENOMEM; + + if (streq(name, "AllowedCPUs")) + set = &c->cpuset_cpus; + else + set = &c->cpuset_mems; + + cpu_set_reset(set); + *set = new_set; + new_set = (CPUSet) {}; + + unit_invalidate_cgroup(u, CGROUP_MASK_CPUSET); + unit_write_settingf(u, flags, name, "%s=%s", name, setstr); + } + + return 1; + + } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) { + const char *path; + unsigned n = 0; + uint64_t u64; + + r = sd_bus_message_enter_container(message, 'a', "(st)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) { + + if (!path_is_normalized(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + CGroupIODeviceLimit *a = NULL, *b; + + LIST_FOREACH(device_limits, b, c->io_device_limits) { + if (path_equal(path, b->path)) { + a = b; + break; + } + } + + if (!a) { + CGroupIOLimitType type; + + a = new0(CGroupIODeviceLimit, 1); + if (!a) + return -ENOMEM; + + a->path = strdup(path); + if (!a->path) { + free(a); + return -ENOMEM; + } + + for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++) + a->limits[type] = cgroup_io_limit_defaults[type]; + + LIST_PREPEND(device_limits, c->io_device_limits, a); + } + + a->limits[iol_type] = u64; + } + + n++; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + CGroupIODeviceLimit *a; + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + size_t size = 0; + + if (n == 0) { + LIST_FOREACH(device_limits, a, c->io_device_limits) + a->limits[iol_type] = cgroup_io_limit_defaults[iol_type]; + } + + unit_invalidate_cgroup(u, CGROUP_MASK_IO); + + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + fprintf(f, "%s=\n", name); + LIST_FOREACH(device_limits, a, c->io_device_limits) + if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type]) + fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]); + + r = fflush_and_check(f); + if (r < 0) + return r; + unit_write_setting(u, flags, name, buf); + } + + return 1; + + } else if (streq(name, "IODeviceWeight")) { + const char *path; + uint64_t weight; + unsigned n = 0; + + r = sd_bus_message_enter_container(message, 'a', "(st)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) { + + if (!path_is_normalized(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path); + + if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + CGroupIODeviceWeight *a = NULL, *b; + + LIST_FOREACH(device_weights, b, c->io_device_weights) { + if (path_equal(b->path, path)) { + a = b; + break; + } + } + + if (!a) { + a = new0(CGroupIODeviceWeight, 1); + if (!a) + return -ENOMEM; + + a->path = strdup(path); + if (!a->path) { + free(a); + return -ENOMEM; + } + LIST_PREPEND(device_weights, c->io_device_weights, a); + } + + a->weight = weight; + } + + n++; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + CGroupIODeviceWeight *a; + size_t size = 0; + + if (n == 0) { + while (c->io_device_weights) + cgroup_context_free_io_device_weight(c, c->io_device_weights); + } + + unit_invalidate_cgroup(u, CGROUP_MASK_IO); + + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + fputs("IODeviceWeight=\n", f); + LIST_FOREACH(device_weights, a, c->io_device_weights) + fprintf(f, "IODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight); + + r = fflush_and_check(f); + if (r < 0) + return r; + unit_write_setting(u, flags, name, buf); + } + + return 1; + + } else if (streq(name, "IODeviceLatencyTargetUSec")) { + const char *path; + uint64_t target; + unsigned n = 0; + + r = sd_bus_message_enter_container(message, 'a', "(st)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(st)", &path, &target)) > 0) { + + if (!path_is_normalized(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + CGroupIODeviceLatency *a = NULL, *b; + + LIST_FOREACH(device_latencies, b, c->io_device_latencies) { + if (path_equal(b->path, path)) { + a = b; + break; + } + } + + if (!a) { + a = new0(CGroupIODeviceLatency, 1); + if (!a) + return -ENOMEM; + + a->path = strdup(path); + if (!a->path) { + free(a); + return -ENOMEM; + } + LIST_PREPEND(device_latencies, c->io_device_latencies, a); + } + + a->target_usec = target; + } + + n++; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + char ts[FORMAT_TIMESPAN_MAX]; + CGroupIODeviceLatency *a; + size_t size = 0; + + if (n == 0) { + while (c->io_device_latencies) + cgroup_context_free_io_device_latency(c, c->io_device_latencies); + } + + unit_invalidate_cgroup(u, CGROUP_MASK_IO); + + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + fputs("IODeviceLatencyTargetSec=\n", f); + LIST_FOREACH(device_latencies, a, c->io_device_latencies) + fprintf(f, "IODeviceLatencyTargetSec=%s %s\n", + a->path, format_timespan(ts, sizeof(ts), a->target_usec, 1)); + + r = fflush_and_check(f); + if (r < 0) + return r; + unit_write_setting(u, flags, name, buf); + } + + return 1; + + } else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) { + const char *path; + bool read = true; + unsigned n = 0; + uint64_t u64; + + if (streq(name, "BlockIOWriteBandwidth")) + read = false; + + r = sd_bus_message_enter_container(message, 'a', "(st)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) { + + if (!path_is_normalized(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + CGroupBlockIODeviceBandwidth *a = NULL, *b; + + LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { + if (path_equal(path, b->path)) { + a = b; + break; + } + } + + if (!a) { + a = new0(CGroupBlockIODeviceBandwidth, 1); + if (!a) + return -ENOMEM; + + a->rbps = CGROUP_LIMIT_MAX; + a->wbps = CGROUP_LIMIT_MAX; + a->path = strdup(path); + if (!a->path) { + free(a); + return -ENOMEM; + } + + LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a); + } + + if (read) + a->rbps = u64; + else + a->wbps = u64; + } + + n++; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + CGroupBlockIODeviceBandwidth *a; + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + size_t size = 0; + + if (n == 0) { + LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) { + if (read) + a->rbps = CGROUP_LIMIT_MAX; + else + a->wbps = CGROUP_LIMIT_MAX; + } + } + + unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); + + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + if (read) { + fputs("BlockIOReadBandwidth=\n", f); + LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) + if (a->rbps != CGROUP_LIMIT_MAX) + fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->rbps); + } else { + fputs("BlockIOWriteBandwidth=\n", f); + LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) + if (a->wbps != CGROUP_LIMIT_MAX) + fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->wbps); + } + + r = fflush_and_check(f); + if (r < 0) + return r; + + unit_write_setting(u, flags, name, buf); + } + + return 1; + + } else if (streq(name, "BlockIODeviceWeight")) { + const char *path; + uint64_t weight; + unsigned n = 0; + + r = sd_bus_message_enter_container(message, 'a', "(st)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) { + + if (!path_is_normalized(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path '%s' specified in %s= is not normalized.", name, path); + + if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + CGroupBlockIODeviceWeight *a = NULL, *b; + + LIST_FOREACH(device_weights, b, c->blockio_device_weights) { + if (path_equal(b->path, path)) { + a = b; + break; + } + } + + if (!a) { + a = new0(CGroupBlockIODeviceWeight, 1); + if (!a) + return -ENOMEM; + + a->path = strdup(path); + if (!a->path) { + free(a); + return -ENOMEM; + } + LIST_PREPEND(device_weights, c->blockio_device_weights, a); + } + + a->weight = weight; + } + + n++; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + CGroupBlockIODeviceWeight *a; + size_t size = 0; + + if (n == 0) { + while (c->blockio_device_weights) + cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights); + } + + unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO); + + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + fputs("BlockIODeviceWeight=\n", f); + LIST_FOREACH(device_weights, a, c->blockio_device_weights) + fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight); + + r = fflush_and_check(f); + if (r < 0) + return r; + + unit_write_setting(u, flags, name, buf); + } + + return 1; + + } else if (streq(name, "DevicePolicy")) { + const char *policy; + CGroupDevicePolicy p; + + r = sd_bus_message_read(message, "s", &policy); + if (r < 0) + return r; + + p = cgroup_device_policy_from_string(policy); + if (p < 0) + return -EINVAL; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->device_policy = p; + unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES); + unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy); + } + + return 1; + + } else if (streq(name, "DeviceAllow")) { + const char *path, *rwm; + unsigned n = 0; + + r = sd_bus_message_enter_container(message, 'a', "(ss)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) { + + if (!valid_device_allow_pattern(path) || strpbrk(path, WHITESPACE)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node or pattern"); + + if (isempty(rwm)) + rwm = "rwm"; + else if (!in_charset(rwm, "rwm")) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + CGroupDeviceAllow *a = NULL, *b; + + LIST_FOREACH(device_allow, b, c->device_allow) { + if (path_equal(b->path, path)) { + a = b; + break; + } + } + + if (!a) { + a = new0(CGroupDeviceAllow, 1); + if (!a) + return -ENOMEM; + + a->path = strdup(path); + if (!a->path) { + free(a); + return -ENOMEM; + } + + LIST_PREPEND(device_allow, c->device_allow, a); + } + + a->r = !!strchr(rwm, 'r'); + a->w = !!strchr(rwm, 'w'); + a->m = !!strchr(rwm, 'm'); + } + + n++; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + CGroupDeviceAllow *a; + size_t size = 0; + + if (n == 0) { + while (c->device_allow) + cgroup_context_free_device_allow(c, c->device_allow); + } + + unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES); + + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + fputs("DeviceAllow=\n", f); + LIST_FOREACH(device_allow, a, c->device_allow) + fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : ""); + + r = fflush_and_check(f); + if (r < 0) + return r; + unit_write_setting(u, flags, name, buf); + } + + return 1; + + } else if (streq(name, "IPAccounting")) { + int b; + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->ip_accounting = b; + + unit_invalidate_cgroup_bpf(u); + unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b)); + } + + return 1; + + } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) { + IPAddressAccessItem **list; + size_t n = 0; + + list = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny; + + r = sd_bus_message_enter_container(message, 'a', "(iayu)"); + if (r < 0) + return r; + + for (;;) { + const void *ap; + int32_t family; + uint32_t prefixlen; + size_t an; + + r = sd_bus_message_enter_container(message, 'r', "iayu"); + if (r < 0) + return r; + if (r == 0) + break; + + r = sd_bus_message_read(message, "i", &family); + if (r < 0) + return r; + + if (!IN_SET(family, AF_INET, AF_INET6)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects IPv4 or IPv6 addresses only.", name); + + r = sd_bus_message_read_array(message, 'y', &ap, &an); + if (r < 0) + return r; + + if (an != FAMILY_ADDRESS_SIZE(family)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IP address has wrong size for family (%s, expected %zu, got %zu)", + af_to_name(family), FAMILY_ADDRESS_SIZE(family), an); + + r = sd_bus_message_read(message, "u", &prefixlen); + if (r < 0) + return r; + + if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family)); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + IPAddressAccessItem *item; + + item = new0(IPAddressAccessItem, 1); + if (!item) + return -ENOMEM; + + item->family = family; + item->prefixlen = prefixlen; + memcpy(&item->address, ap, an); + + LIST_PREPEND(items, *list, item); + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + n++; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + *list = ip_address_access_reduce(*list); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + IPAddressAccessItem *item; + size_t size = 0; + + if (n == 0) + *list = ip_address_access_free_all(*list); + + unit_invalidate_cgroup_bpf(u); + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + fputs(name, f); + fputs("=\n", f); + + LIST_FOREACH(items, item, *list) { + char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; + + errno = 0; + if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer))) + return errno_or_else(EINVAL); + + fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen); + } + + r = fflush_and_check(f); + if (r < 0) + return r; + + unit_write_setting(u, flags, name, buf); + } + + return 1; + } + + if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB)) + return bus_cgroup_set_transient_property(u, c, name, message, flags, error); + + return 0; +} diff --git a/src/core/dbus-cgroup.h b/src/core/dbus-cgroup.h new file mode 100644 index 00000000..5ca68a63 --- /dev/null +++ b/src/core/dbus-cgroup.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" +#include "cgroup.h" + +extern const sd_bus_vtable bus_cgroup_vtable[]; + +int bus_property_get_tasks_max(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); + +int bus_cgroup_set_property(Unit *u, CGroupContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); diff --git a/src/core/dbus-device.c b/src/core/dbus-device.c new file mode 100644 index 00000000..6cf7f58e --- /dev/null +++ b/src/core/dbus-device.c @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "dbus-device.h" +#include "device.h" +#include "unit.h" + +const sd_bus_vtable bus_device_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("SysFSPath", "s", NULL, offsetof(Device, sysfs), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_VTABLE_END +}; diff --git a/src/core/dbus-device.h b/src/core/dbus-device.h new file mode 100644 index 00000000..077a2bf1 --- /dev/null +++ b/src/core/dbus-device.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus-vtable.h" + +extern const sd_bus_vtable bus_device_vtable[]; diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c new file mode 100644 index 00000000..1d0bc1ed --- /dev/null +++ b/src/core/dbus-execute.c @@ -0,0 +1,2559 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#if HAVE_SECCOMP +#include +#endif + +#include "af-list.h" +#include "alloc-util.h" +#include "bus-util.h" +#include "cap-list.h" +#include "capability-util.h" +#include "cpu-set-util.h" +#include "dbus-execute.h" +#include "dbus-util.h" +#include "env-util.h" +#include "errno-list.h" +#include "escape.h" +#include "execute.h" +#include "fd-util.h" +#include "fileio.h" +#include "hexdecoct.h" +#include "io-util.h" +#include "ioprio.h" +#include "journal-util.h" +#include "mountpoint-util.h" +#include "namespace.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "rlimit-util.h" +#if HAVE_SECCOMP +#include "seccomp-util.h" +#endif +#include "securebits-util.h" +#include "specifier.h" +#include "strv.h" +#include "syslog-util.h" +#include "unit-printf.h" +#include "user-util.h" +#include "utf8.h" + +BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_home, protect_home, ProtectHome); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_system, protect_system, ProtectSystem); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_personality, personality, unsigned long); +static BUS_DEFINE_PROPERTY_GET(property_get_ioprio, "i", ExecContext, exec_context_get_effective_ioprio); +static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_class, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_CLASS); +static BUS_DEFINE_PROPERTY_GET2(property_get_ioprio_priority, "i", ExecContext, exec_context_get_effective_ioprio, IOPRIO_PRIO_DATA); +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_string, "s", NULL); +static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_level, "i", int, LOG_PRI); +static BUS_DEFINE_PROPERTY_GET_REF(property_get_syslog_facility, "i", int, LOG_FAC); + +static int property_get_environment_files( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + char **j; + int r; + + assert(bus); + assert(reply); + assert(c); + + r = sd_bus_message_open_container(reply, 'a', "(sb)"); + if (r < 0) + return r; + + STRV_FOREACH(j, c->environment_files) { + const char *fn = *j; + + r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-'); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_oom_score_adjust( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + int32_t n; + + assert(bus); + assert(reply); + assert(c); + + if (c->oom_score_adjust_set) + n = c->oom_score_adjust; + else { + _cleanup_free_ char *t = NULL; + + n = 0; + if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) + safe_atoi32(t, &n); + } + + return sd_bus_message_append(reply, "i", n); +} + +static int property_get_nice( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + int32_t n; + + assert(bus); + assert(reply); + assert(c); + + if (c->nice_set) + n = c->nice; + else { + errno = 0; + n = getpriority(PRIO_PROCESS, 0); + if (errno > 0) + n = 0; + } + + return sd_bus_message_append(reply, "i", n); +} + +static int property_get_cpu_sched_policy( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + int32_t n; + + assert(bus); + assert(reply); + assert(c); + + if (c->cpu_sched_set) + n = c->cpu_sched_policy; + else { + n = sched_getscheduler(0); + if (n < 0) + n = SCHED_OTHER; + } + + return sd_bus_message_append(reply, "i", n); +} + +static int property_get_cpu_sched_priority( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + int32_t n; + + assert(bus); + assert(reply); + assert(c); + + if (c->cpu_sched_set) + n = c->cpu_sched_priority; + else { + struct sched_param p = {}; + + if (sched_getparam(0, &p) >= 0) + n = p.sched_priority; + else + n = 0; + } + + return sd_bus_message_append(reply, "i", n); +} + +static int property_get_cpu_affinity( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + _cleanup_free_ uint8_t *array = NULL; + size_t allocated; + + assert(bus); + assert(reply); + assert(c); + + (void) cpu_set_to_dbus(&c->cpu_set, &array, &allocated); + return sd_bus_message_append_array(reply, 'y', array, allocated); +} + +static int property_get_numa_mask( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + _cleanup_free_ uint8_t *array = NULL; + size_t allocated; + + assert(bus); + assert(reply); + assert(c); + + (void) cpu_set_to_dbus(&c->numa_policy.nodes, &array, &allocated); + + return sd_bus_message_append_array(reply, 'y', array, allocated); +} + +static int property_get_numa_policy( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + ExecContext *c = userdata; + int32_t policy; + + assert(bus); + assert(reply); + assert(c); + + policy = numa_policy_get_type(&c->numa_policy); + + return sd_bus_message_append_basic(reply, 'i', &policy); +} + +static int property_get_timer_slack_nsec( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + uint64_t u; + + assert(bus); + assert(reply); + assert(c); + + if (c->timer_slack_nsec != NSEC_INFINITY) + u = (uint64_t) c->timer_slack_nsec; + else + u = (uint64_t) prctl(PR_GET_TIMERSLACK); + + return sd_bus_message_append(reply, "t", u); +} + +static int property_get_syscall_filter( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + _cleanup_strv_free_ char **l = NULL; + int r; + +#if HAVE_SECCOMP + Iterator i; + void *id, *val; +#endif + + assert(bus); + assert(reply); + assert(c); + + r = sd_bus_message_open_container(reply, 'r', "bas"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "b", c->syscall_whitelist); + if (r < 0) + return r; + +#if HAVE_SECCOMP + HASHMAP_FOREACH_KEY(val, id, c->syscall_filter, i) { + _cleanup_free_ char *name = NULL; + const char *e = NULL; + char *s; + int num = PTR_TO_INT(val); + + name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1); + if (!name) + continue; + + if (num >= 0) { + e = errno_to_name(num); + if (e) { + s = strjoin(name, ":", e); + if (!s) + return -ENOMEM; + } else { + r = asprintf(&s, "%s:%d", name, num); + if (r < 0) + return -ENOMEM; + } + } else + s = TAKE_PTR(name); + + r = strv_consume(&l, s); + if (r < 0) + return r; + } +#endif + + strv_sort(l); + + r = sd_bus_message_append_strv(reply, l); + if (r < 0) + return r; + + return sd_bus_message_close_container(reply); +} + +static int property_get_syscall_archs( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + _cleanup_strv_free_ char **l = NULL; + int r; + +#if HAVE_SECCOMP + Iterator i; + void *id; +#endif + + assert(bus); + assert(reply); + assert(c); + +#if HAVE_SECCOMP + SET_FOREACH(id, c->syscall_archs, i) { + const char *name; + + name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1); + if (!name) + continue; + + r = strv_extend(&l, name); + if (r < 0) + return -ENOMEM; + } +#endif + + strv_sort(l); + + r = sd_bus_message_append_strv(reply, l); + if (r < 0) + return r; + + return 0; +} + +static int property_get_selinux_context( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + + assert(bus); + assert(reply); + assert(c); + + return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context); +} + +static int property_get_apparmor_profile( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + + assert(bus); + assert(reply); + assert(c); + + return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile); +} + +static int property_get_smack_process_label( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + + assert(bus); + assert(reply); + assert(c); + + return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label); +} + +static int property_get_address_families( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + _cleanup_strv_free_ char **l = NULL; + Iterator i; + void *af; + int r; + + assert(bus); + assert(reply); + assert(c); + + r = sd_bus_message_open_container(reply, 'r', "bas"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "b", c->address_families_whitelist); + if (r < 0) + return r; + + SET_FOREACH(af, c->address_families, i) { + const char *name; + + name = af_to_name(PTR_TO_INT(af)); + if (!name) + continue; + + r = strv_extend(&l, name); + if (r < 0) + return -ENOMEM; + } + + strv_sort(l); + + r = sd_bus_message_append_strv(reply, l); + if (r < 0) + return r; + + return sd_bus_message_close_container(reply); +} + +static int property_get_working_directory( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + const char *wd; + + assert(bus); + assert(reply); + assert(c); + + if (c->working_directory_home) + wd = "~"; + else + wd = c->working_directory; + + if (c->working_directory_missing_ok) + wd = strjoina("!", wd); + + return sd_bus_message_append(reply, "s", wd); +} + +static int property_get_stdio_fdname( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + int fileno; + + assert(bus); + assert(c); + assert(property); + assert(reply); + + if (streq(property, "StandardInputFileDescriptorName")) + fileno = STDIN_FILENO; + else if (streq(property, "StandardOutputFileDescriptorName")) + fileno = STDOUT_FILENO; + else { + assert(streq(property, "StandardErrorFileDescriptorName")); + fileno = STDERR_FILENO; + } + + return sd_bus_message_append(reply, "s", exec_context_fdname(c, fileno)); +} + +static int property_get_input_data( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + + assert(bus); + assert(c); + assert(property); + assert(reply); + + return sd_bus_message_append_array(reply, 'y', c->stdin_data, c->stdin_data_size); +} + +static int property_get_bind_paths( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + unsigned i; + bool ro; + int r; + + assert(bus); + assert(c); + assert(property); + assert(reply); + + ro = strstr(property, "ReadOnly"); + + r = sd_bus_message_open_container(reply, 'a', "(ssbt)"); + if (r < 0) + return r; + + for (i = 0; i < c->n_bind_mounts; i++) { + + if (ro != c->bind_mounts[i].read_only) + continue; + + r = sd_bus_message_append( + reply, "(ssbt)", + c->bind_mounts[i].source, + c->bind_mounts[i].destination, + c->bind_mounts[i].ignore_enoent, + c->bind_mounts[i].recursive ? (uint64_t) MS_REC : (uint64_t) 0); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_temporary_filesystems( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + unsigned i; + int r; + + assert(bus); + assert(c); + assert(property); + assert(reply); + + r = sd_bus_message_open_container(reply, 'a', "(ss)"); + if (r < 0) + return r; + + for (i = 0; i < c->n_temporary_filesystems; i++) { + TemporaryFileSystem *t = c->temporary_filesystems + i; + + r = sd_bus_message_append( + reply, "(ss)", + t->path, + t->options); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_log_extra_fields( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + size_t i; + int r; + + assert(bus); + assert(c); + assert(property); + assert(reply); + + r = sd_bus_message_open_container(reply, 'a', "ay"); + if (r < 0) + return r; + + for (i = 0; i < c->n_log_extra_fields; i++) { + r = sd_bus_message_append_array(reply, 'y', c->log_extra_fields[i].iov_base, c->log_extra_fields[i].iov_len); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +const sd_bus_vtable bus_exec_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UnsetEnvironment", "as", NULL, offsetof(ExecContext, unset_environment), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NUMAPolicy", "i", property_get_numa_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NUMAMask", "ay", property_get_numa_mask, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardInputFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardInputData", "ay", property_get_input_data, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardOutputFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StandardErrorFileDescriptorName", "s", property_get_stdio_fdname, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LogLevelMax", "i", bus_property_get_int, offsetof(ExecContext, log_level_max), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LogRateLimitIntervalUSec", "t", bus_property_get_usec, offsetof(ExecContext, log_ratelimit_interval_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LogRateLimitBurst", "u", bus_property_get_unsigned, offsetof(ExecContext, log_ratelimit_burst), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LogExtraFields", "aay", property_get_log_extra_fields, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CapabilityBoundingSet", "t", NULL, offsetof(ExecContext, capability_bounding_set), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("AmbientCapabilities", "t", NULL, offsetof(ExecContext, capability_ambient_set), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DynamicUser", "b", bus_property_get_bool, offsetof(ExecContext, dynamic_user), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(ExecContext, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ReadWritePaths", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ReadOnlyPaths", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ProtectKernelTunables", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_tunables), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ProtectKernelModules", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_modules), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ProtectKernelLogs", "b", bus_property_get_bool, offsetof(ExecContext, protect_kernel_logs), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ProtectControlGroups", "b", bus_property_get_bool, offsetof(ExecContext, protect_control_groups), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PrivateMounts", "b", bus_property_get_bool, offsetof(ExecContext, private_mounts), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ProtectHome", "s", property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ProtectSystem", "s", property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SystemCallErrorNumber", "i", bus_property_get_int, offsetof(ExecContext, syscall_errno), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].paths), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StateDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].paths), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CacheDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].paths), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LogsDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].paths), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TimeoutCleanUSec", "t", bus_property_get_usec, offsetof(ExecContext, timeout_clean_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestrictSUIDSGID", "b", bus_property_get_bool, offsetof(ExecContext, restrict_suid_sgid), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("BindPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("BindReadOnlyPaths", "a(ssbt)", property_get_bind_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TemporaryFileSystem", "a(ss)", property_get_temporary_filesystems, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL, offsetof(ExecContext, network_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST), + + /* Obsolete/redundant properties: */ + SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + + SD_BUS_VTABLE_END +}; + +static int append_exec_command(sd_bus_message *reply, ExecCommand *c) { + int r; + + assert(reply); + assert(c); + + if (!c->path) + return 0; + + r = sd_bus_message_open_container(reply, 'r', "sasbttttuii"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "s", c->path); + if (r < 0) + return r; + + r = sd_bus_message_append_strv(reply, c->argv); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "bttttuii", + !!(c->flags & EXEC_COMMAND_IGNORE_FAILURE), + c->exec_status.start_timestamp.realtime, + c->exec_status.start_timestamp.monotonic, + c->exec_status.exit_timestamp.realtime, + c->exec_status.exit_timestamp.monotonic, + (uint32_t) c->exec_status.pid, + (int32_t) c->exec_status.code, + (int32_t) c->exec_status.status); + if (r < 0) + return r; + + return sd_bus_message_close_container(reply); +} + +static int append_exec_ex_command(sd_bus_message *reply, ExecCommand *c) { + _cleanup_strv_free_ char **ex_opts = NULL; + int r; + + assert(reply); + assert(c); + + if (!c->path) + return 0; + + r = sd_bus_message_open_container(reply, 'r', "sasasttttuii"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "s", c->path); + if (r < 0) + return r; + + r = sd_bus_message_append_strv(reply, c->argv); + if (r < 0) + return r; + + r = exec_command_flags_to_strv(c->flags, &ex_opts); + if (r < 0) + return r; + + r = sd_bus_message_append_strv(reply, ex_opts); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "ttttuii", + c->exec_status.start_timestamp.realtime, + c->exec_status.start_timestamp.monotonic, + c->exec_status.exit_timestamp.realtime, + c->exec_status.exit_timestamp.monotonic, + (uint32_t) c->exec_status.pid, + (int32_t) c->exec_status.code, + (int32_t) c->exec_status.status); + if (r < 0) + return r; + + return sd_bus_message_close_container(reply); +} + +int bus_property_get_exec_command( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *ret_error) { + + ExecCommand *c = (ExecCommand*) userdata; + int r; + + assert(bus); + assert(reply); + + r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)"); + if (r < 0) + return r; + + r = append_exec_command(reply, c); + if (r < 0) + return r; + + return sd_bus_message_close_container(reply); +} + +int bus_property_get_exec_command_list( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *ret_error) { + + ExecCommand *c = *(ExecCommand**) userdata; + int r; + + assert(bus); + assert(reply); + + r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)"); + if (r < 0) + return r; + + LIST_FOREACH(command, c, c) { + r = append_exec_command(reply, c); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +int bus_property_get_exec_ex_command_list( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *ret_error) { + + ExecCommand *c, *exec_command = *(ExecCommand**) userdata; + int r; + + assert(bus); + assert(reply); + + r = sd_bus_message_open_container(reply, 'a', "(sasasttttuii)"); + if (r < 0) + return r; + + LIST_FOREACH(command, c, exec_command) { + r = append_exec_ex_command(reply, c); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static char *exec_command_flags_to_exec_chars(ExecCommandFlags flags) { + return strjoin(FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE) ? "-" : "", + FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND) ? ":" : "", + FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED) ? "+" : "", + FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID) ? "!" : "", + FLAGS_SET(flags, EXEC_COMMAND_AMBIENT_MAGIC) ? "!!" : ""); +} + +int bus_set_transient_exec_command( + Unit *u, + const char *name, + ExecCommand **exec_command, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + bool is_ex_prop = endswith(name, "Ex"); + unsigned n = 0; + int r; + + r = sd_bus_message_enter_container(message, 'a', is_ex_prop ? "(sasas)" : "(sasb)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_enter_container(message, 'r', is_ex_prop ? "sasas" : "sasb")) > 0) { + _cleanup_strv_free_ char **argv = NULL, **ex_opts = NULL; + const char *path; + int b; + + r = sd_bus_message_read(message, "s", &path); + if (r < 0) + return r; + + if (!path_is_absolute(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path); + + r = sd_bus_message_read_strv(message, &argv); + if (r < 0) + return r; + + r = is_ex_prop ? sd_bus_message_read_strv(message, &ex_opts) : sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + ExecCommand *c; + + c = new0(ExecCommand, 1); + if (!c) + return -ENOMEM; + + c->path = strdup(path); + if (!c->path) { + free(c); + return -ENOMEM; + } + + c->argv = TAKE_PTR(argv); + + if (is_ex_prop) { + r = exec_command_flags_from_strv(ex_opts, &c->flags); + if (r < 0) + return r; + } else + c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0; + + path_simplify(c->path, false); + exec_command_append_list(exec_command, c); + } + + n++; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + ExecCommand *c; + size_t size = 0; + + if (n == 0) + *exec_command = exec_command_free_list(*exec_command); + + f = open_memstream_unlocked(&buf, &size); + if (!f) + return -ENOMEM; + + fprintf(f, "%s=\n", name); + + LIST_FOREACH(command, c, *exec_command) { + _cleanup_free_ char *a = NULL, *exec_chars = NULL; + + exec_chars = exec_command_flags_to_exec_chars(c->flags); + if (!exec_chars) + return -ENOMEM; + + a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS); + if (!a) + return -ENOMEM; + + if (streq_ptr(c->path, c->argv ? c->argv[0] : NULL)) + fprintf(f, "%s=%s%s\n", name, exec_chars, a); + else { + _cleanup_free_ char *t = NULL; + const char *p; + + p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t); + if (!p) + return -ENOMEM; + + fprintf(f, "%s=%s@%s %s\n", name, exec_chars, p, a); + } + } + + r = fflush_and_check(f); + if (r < 0) + return r; + + unit_write_setting(u, flags, name, buf); + } + + return 1; +} + +static int parse_personality(const char *s, unsigned long *p) { + unsigned long v; + + assert(p); + + v = personality_from_string(s); + if (v == PERSONALITY_INVALID) + return -EINVAL; + + *p = v; + return 0; +} + +static const char* mount_propagation_flags_to_string_with_check(unsigned long n) { + if (!IN_SET(n, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE)) + return NULL; + + return mount_propagation_flags_to_string(n); +} + +static BUS_DEFINE_SET_TRANSIENT(nsec, "t", uint64_t, nsec_t, NSEC_FMT); +static BUS_DEFINE_SET_TRANSIENT_IS_VALID(log_level, "i", int32_t, int, "%" PRIi32, log_level_is_valid); +#if HAVE_SECCOMP +static BUS_DEFINE_SET_TRANSIENT_IS_VALID(errno, "i", int32_t, int, "%" PRIi32, errno_is_valid); +#endif +static BUS_DEFINE_SET_TRANSIENT_PARSE(std_input, ExecInput, exec_input_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(std_output, ExecOutput, exec_output_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(utmp_mode, ExecUtmpMode, exec_utmp_mode_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_system, ProtectSystem, protect_system_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, protect_home_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode, ExecKeyringMode, exec_keyring_mode_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality); +static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits, "i", int32_t, int, "%" PRIi32, secure_bits_to_string_alloc_with_check); +static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint64_t, "%" PRIu64, capability_set_to_string_alloc); +static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(namespace_flag, "t", uint64_t, unsigned long, "%" PRIu64, namespace_flags_to_string); +static BUS_DEFINE_SET_TRANSIENT_TO_STRING(mount_flags, "t", uint64_t, unsigned long, "%" PRIu64, mount_propagation_flags_to_string_with_check); + +int bus_exec_context_set_transient_property( + Unit *u, + ExecContext *c, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + const char *suffix; + int r; + + assert(u); + assert(c); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "User")) + return bus_set_transient_user_compat(u, name, &c->user, message, flags, error); + + if (streq(name, "Group")) + return bus_set_transient_user_compat(u, name, &c->group, message, flags, error); + + if (streq(name, "TTYPath")) + return bus_set_transient_path(u, name, &c->tty_path, message, flags, error); + + if (streq(name, "RootImage")) + return bus_set_transient_path(u, name, &c->root_image, message, flags, error); + + if (streq(name, "RootDirectory")) + return bus_set_transient_path(u, name, &c->root_directory, message, flags, error); + + if (streq(name, "SyslogIdentifier")) + return bus_set_transient_string(u, name, &c->syslog_identifier, message, flags, error); + + if (streq(name, "LogLevelMax")) + return bus_set_transient_log_level(u, name, &c->log_level_max, message, flags, error); + + if (streq(name, "LogRateLimitIntervalUSec")) + return bus_set_transient_usec(u, name, &c->log_ratelimit_interval_usec, message, flags, error); + + if (streq(name, "LogRateLimitBurst")) + return bus_set_transient_unsigned(u, name, &c->log_ratelimit_burst, message, flags, error); + + if (streq(name, "Personality")) + return bus_set_transient_personality(u, name, &c->personality, message, flags, error); + + if (streq(name, "StandardInput")) + return bus_set_transient_std_input(u, name, &c->std_input, message, flags, error); + + if (streq(name, "StandardOutput")) + return bus_set_transient_std_output(u, name, &c->std_output, message, flags, error); + + if (streq(name, "StandardError")) + return bus_set_transient_std_output(u, name, &c->std_error, message, flags, error); + + if (streq(name, "IgnoreSIGPIPE")) + return bus_set_transient_bool(u, name, &c->ignore_sigpipe, message, flags, error); + + if (streq(name, "TTYVHangup")) + return bus_set_transient_bool(u, name, &c->tty_vhangup, message, flags, error); + + if (streq(name, "TTYReset")) + return bus_set_transient_bool(u, name, &c->tty_reset, message, flags, error); + + if (streq(name, "TTYVTDisallocate")) + return bus_set_transient_bool(u, name, &c->tty_vt_disallocate, message, flags, error); + + if (streq(name, "PrivateTmp")) + return bus_set_transient_bool(u, name, &c->private_tmp, message, flags, error); + + if (streq(name, "PrivateDevices")) + return bus_set_transient_bool(u, name, &c->private_devices, message, flags, error); + + if (streq(name, "PrivateMounts")) + return bus_set_transient_bool(u, name, &c->private_mounts, message, flags, error); + + if (streq(name, "PrivateNetwork")) + return bus_set_transient_bool(u, name, &c->private_network, message, flags, error); + + if (streq(name, "PrivateUsers")) + return bus_set_transient_bool(u, name, &c->private_users, message, flags, error); + + if (streq(name, "NoNewPrivileges")) + return bus_set_transient_bool(u, name, &c->no_new_privileges, message, flags, error); + + if (streq(name, "SyslogLevelPrefix")) + return bus_set_transient_bool(u, name, &c->syslog_level_prefix, message, flags, error); + + if (streq(name, "MemoryDenyWriteExecute")) + return bus_set_transient_bool(u, name, &c->memory_deny_write_execute, message, flags, error); + + if (streq(name, "RestrictRealtime")) + return bus_set_transient_bool(u, name, &c->restrict_realtime, message, flags, error); + + if (streq(name, "RestrictSUIDSGID")) + return bus_set_transient_bool(u, name, &c->restrict_suid_sgid, message, flags, error); + + if (streq(name, "DynamicUser")) + return bus_set_transient_bool(u, name, &c->dynamic_user, message, flags, error); + + if (streq(name, "RemoveIPC")) + return bus_set_transient_bool(u, name, &c->remove_ipc, message, flags, error); + + if (streq(name, "ProtectKernelTunables")) + return bus_set_transient_bool(u, name, &c->protect_kernel_tunables, message, flags, error); + + if (streq(name, "ProtectKernelModules")) + return bus_set_transient_bool(u, name, &c->protect_kernel_modules, message, flags, error); + + if (streq(name, "ProtectKernelLogs")) + return bus_set_transient_bool(u, name, &c->protect_kernel_logs, message, flags, error); + + if (streq(name, "ProtectControlGroups")) + return bus_set_transient_bool(u, name, &c->protect_control_groups, message, flags, error); + + if (streq(name, "MountAPIVFS")) + return bus_set_transient_bool(u, name, &c->mount_apivfs, message, flags, error); + + if (streq(name, "CPUSchedulingResetOnFork")) + return bus_set_transient_bool(u, name, &c->cpu_sched_reset_on_fork, message, flags, error); + + if (streq(name, "NonBlocking")) + return bus_set_transient_bool(u, name, &c->non_blocking, message, flags, error); + + if (streq(name, "LockPersonality")) + return bus_set_transient_bool(u, name, &c->lock_personality, message, flags, error); + + if (streq(name, "ProtectHostname")) + return bus_set_transient_bool(u, name, &c->protect_hostname, message, flags, error); + + if (streq(name, "UtmpIdentifier")) + return bus_set_transient_string(u, name, &c->utmp_id, message, flags, error); + + if (streq(name, "UtmpMode")) + return bus_set_transient_utmp_mode(u, name, &c->utmp_mode, message, flags, error); + + if (streq(name, "PAMName")) + return bus_set_transient_string(u, name, &c->pam_name, message, flags, error); + + if (streq(name, "TimerSlackNSec")) + return bus_set_transient_nsec(u, name, &c->timer_slack_nsec, message, flags, error); + + if (streq(name, "ProtectSystem")) + return bus_set_transient_protect_system(u, name, &c->protect_system, message, flags, error); + + if (streq(name, "ProtectHome")) + return bus_set_transient_protect_home(u, name, &c->protect_home, message, flags, error); + + if (streq(name, "KeyringMode")) + return bus_set_transient_keyring_mode(u, name, &c->keyring_mode, message, flags, error); + + if (streq(name, "RuntimeDirectoryPreserve")) + return bus_set_transient_preserve_mode(u, name, &c->runtime_directory_preserve_mode, message, flags, error); + + if (streq(name, "UMask")) + return bus_set_transient_mode_t(u, name, &c->umask, message, flags, error); + + if (streq(name, "RuntimeDirectoryMode")) + return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_RUNTIME].mode, message, flags, error); + + if (streq(name, "StateDirectoryMode")) + return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_STATE].mode, message, flags, error); + + if (streq(name, "CacheDirectoryMode")) + return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CACHE].mode, message, flags, error); + + if (streq(name, "LogsDirectoryMode")) + return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_LOGS].mode, message, flags, error); + + if (streq(name, "ConfigurationDirectoryMode")) + return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_CONFIGURATION].mode, message, flags, error); + + if (streq(name, "SELinuxContext")) + return bus_set_transient_string(u, name, &c->selinux_context, message, flags, error); + + if (streq(name, "SecureBits")) + return bus_set_transient_secure_bits(u, name, &c->secure_bits, message, flags, error); + + if (streq(name, "CapabilityBoundingSet")) + return bus_set_transient_capability(u, name, &c->capability_bounding_set, message, flags, error); + + if (streq(name, "AmbientCapabilities")) + return bus_set_transient_capability(u, name, &c->capability_ambient_set, message, flags, error); + + if (streq(name, "RestrictNamespaces")) + return bus_set_transient_namespace_flag(u, name, &c->restrict_namespaces, message, flags, error); + + if (streq(name, "MountFlags")) + return bus_set_transient_mount_flags(u, name, &c->mount_flags, message, flags, error); + + if (streq(name, "NetworkNamespacePath")) + return bus_set_transient_path(u, name, &c->network_namespace_path, message, flags, error); + + if (streq(name, "SupplementaryGroups")) { + _cleanup_strv_free_ char **l = NULL; + char **p; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + STRV_FOREACH(p, l) + if (!isempty(*p) && !valid_user_group_name_or_id_compat(*p)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Invalid supplementary group names"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (strv_isempty(l)) { + c->supplementary_groups = strv_free(c->supplementary_groups); + unit_write_settingf(u, flags, name, "%s=", name); + } else { + _cleanup_free_ char *joined = NULL; + + r = strv_extend_strv(&c->supplementary_groups, l, true); + if (r < 0) + return -ENOMEM; + + joined = strv_join(c->supplementary_groups, " "); + if (!joined) + return -ENOMEM; + + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, joined); + } + } + + return 1; + + } else if (streq(name, "SyslogLevel")) { + int32_t level; + + r = sd_bus_message_read(message, "i", &level); + if (r < 0) + return r; + + if (!log_level_is_valid(level)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level; + unit_write_settingf(u, flags, name, "SyslogLevel=%i", level); + } + + return 1; + + } else if (streq(name, "SyslogFacility")) { + int32_t facility; + + r = sd_bus_message_read(message, "i", &facility); + if (r < 0) + return r; + + if (!log_facility_unshifted_is_valid(facility)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority); + unit_write_settingf(u, flags, name, "SyslogFacility=%i", facility); + } + + return 1; + + } else if (streq(name, "LogExtraFields")) { + size_t n = 0; + + r = sd_bus_message_enter_container(message, 'a', "ay"); + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ void *copy = NULL; + struct iovec *t; + const char *eq; + const void *p; + size_t sz; + + /* Note that we expect a byte array for each field, instead of a string. That's because on the + * lower-level journal fields can actually contain binary data and are not restricted to text, + * and we should not "lose precision" in our types on the way. That said, I am pretty sure + * actually encoding binary data as unit metadata is not a good idea. Hence we actually refuse + * any actual binary data, and only accept UTF-8. This allows us to eventually lift this + * limitation, should a good, valid usecase arise. */ + + r = sd_bus_message_read_array(message, 'y', &p, &sz); + if (r < 0) + return r; + if (r == 0) + break; + + if (memchr(p, 0, sz)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains zero byte"); + + eq = memchr(p, '=', sz); + if (!eq) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field contains no '=' character"); + if (!journal_field_valid(p, eq - (const char*) p, false)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field invalid"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + t = reallocarray(c->log_extra_fields, c->n_log_extra_fields+1, sizeof(struct iovec)); + if (!t) + return -ENOMEM; + c->log_extra_fields = t; + } + + copy = malloc(sz + 1); + if (!copy) + return -ENOMEM; + + memcpy(copy, p, sz); + ((uint8_t*) copy)[sz] = 0; + + if (!utf8_is_valid(copy)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Journal field is not valid UTF-8"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->log_extra_fields[c->n_log_extra_fields++] = IOVEC_MAKE(copy, sz); + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C, name, "LogExtraFields=%s", (char*) copy); + + copy = NULL; + } + + n++; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags) && n == 0) { + exec_context_free_log_extra_fields(c); + unit_write_setting(u, flags, name, "LogExtraFields="); + } + + return 1; + } + +#if HAVE_SECCOMP + + if (streq(name, "SystemCallErrorNumber")) + return bus_set_transient_errno(u, name, &c->syscall_errno, message, flags, error); + + if (streq(name, "SystemCallFilter")) { + int whitelist; + _cleanup_strv_free_ char **l = NULL; + + r = sd_bus_message_enter_container(message, 'r', "bas"); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "b", &whitelist); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *joined = NULL; + SeccompParseFlags invert_flag = whitelist ? 0 : SECCOMP_PARSE_INVERT; + char **s; + + if (strv_isempty(l)) { + c->syscall_whitelist = false; + c->syscall_filter = hashmap_free(c->syscall_filter); + + unit_write_settingf(u, flags, name, "SystemCallFilter="); + return 1; + } + + if (!c->syscall_filter) { + c->syscall_filter = hashmap_new(NULL); + if (!c->syscall_filter) + return log_oom(); + + c->syscall_whitelist = whitelist; + + if (c->syscall_whitelist) { + r = seccomp_parse_syscall_filter("@default", + -1, + c->syscall_filter, + SECCOMP_PARSE_WHITELIST | invert_flag, + u->id, + NULL, 0); + if (r < 0) + return r; + } + } + + STRV_FOREACH(s, l) { + _cleanup_free_ char *n = NULL; + int e; + + r = parse_syscall_and_errno(*s, &n, &e); + if (r < 0) + return r; + + r = seccomp_parse_syscall_filter(n, + e, + c->syscall_filter, + (c->syscall_whitelist ? SECCOMP_PARSE_WHITELIST : 0) | invert_flag, + u->id, + NULL, 0); + if (r < 0) + return r; + } + + joined = strv_join(l, " "); + if (!joined) + return -ENOMEM; + + unit_write_settingf(u, flags, name, "SystemCallFilter=%s%s", whitelist ? "" : "~", joined); + } + + return 1; + + } else if (streq(name, "SystemCallArchitectures")) { + _cleanup_strv_free_ char **l = NULL; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *joined = NULL; + + if (strv_isempty(l)) + c->syscall_archs = set_free(c->syscall_archs); + else { + char **s; + + r = set_ensure_allocated(&c->syscall_archs, NULL); + if (r < 0) + return r; + + STRV_FOREACH(s, l) { + uint32_t a; + + r = seccomp_arch_from_string(*s, &a); + if (r < 0) + return r; + + r = set_put(c->syscall_archs, UINT32_TO_PTR(a + 1)); + if (r < 0) + return r; + } + + } + + joined = strv_join(l, " "); + if (!joined) + return -ENOMEM; + + unit_write_settingf(u, flags, name, "%s=%s", name, joined); + } + + return 1; + + } else if (streq(name, "RestrictAddressFamilies")) { + int whitelist; + _cleanup_strv_free_ char **l = NULL; + + r = sd_bus_message_enter_container(message, 'r', "bas"); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "b", &whitelist); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *joined = NULL; + char **s; + + if (strv_isempty(l)) { + c->address_families_whitelist = false; + c->address_families = set_free(c->address_families); + + unit_write_settingf(u, flags, name, "RestrictAddressFamilies="); + return 1; + } + + if (!c->address_families) { + c->address_families = set_new(NULL); + if (!c->address_families) + return log_oom(); + + c->address_families_whitelist = whitelist; + } + + STRV_FOREACH(s, l) { + int af; + + af = af_from_name(*s); + if (af < 0) + return af; + + if (whitelist == c->address_families_whitelist) { + r = set_put(c->address_families, INT_TO_PTR(af)); + if (r < 0) + return r; + } else + (void) set_remove(c->address_families, INT_TO_PTR(af)); + } + + joined = strv_join(l, " "); + if (!joined) + return -ENOMEM; + + unit_write_settingf(u, flags, name, "RestrictAddressFamilies=%s%s", whitelist ? "" : "~", joined); + } + + return 1; + } +#endif + if (STR_IN_SET(name, "CPUAffinity", "NUMAMask")) { + const void *a; + size_t n; + bool affinity = streq(name, "CPUAffinity"); + _cleanup_(cpu_set_reset) CPUSet set = {}; + + r = sd_bus_message_read_array(message, 'y', &a, &n); + if (r < 0) + return r; + + r = cpu_set_from_dbus(a, n, &set); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (n == 0) { + cpu_set_reset(affinity ? &c->cpu_set : &c->numa_policy.nodes); + unit_write_settingf(u, flags, name, "%s=", name); + } else { + _cleanup_free_ char *str = NULL; + + str = cpu_set_to_string(&set); + if (!str) + return -ENOMEM; + + /* We forego any optimizations here, and always create the structure using + * cpu_set_add_all(), because we don't want to care if the existing size we + * got over dbus is appropriate. */ + r = cpu_set_add_all(affinity ? &c->cpu_set : &c->numa_policy.nodes, &set); + if (r < 0) + return r; + + unit_write_settingf(u, flags, name, "%s=%s", name, str); + } + } + + return 1; + + } else if (streq(name, "NUMAPolicy")) { + int32_t type; + + r = sd_bus_message_read(message, "i", &type); + if (r < 0) + return r; + + if (!mpol_is_valid(type)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NUMAPolicy value: %i", type); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) + c->numa_policy.type = type; + + return 1; + } else if (streq(name, "Nice")) { + int32_t q; + + r = sd_bus_message_read(message, "i", &q); + if (r < 0) + return r; + + if (!nice_is_valid(q)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Nice value: %i", q); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->nice = q; + c->nice_set = true; + + unit_write_settingf(u, flags, name, "Nice=%i", q); + } + + return 1; + + } else if (streq(name, "CPUSchedulingPolicy")) { + int32_t q; + + r = sd_bus_message_read(message, "i", &q); + if (r < 0) + return r; + + if (!sched_policy_is_valid(q)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling policy: %i", q); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *s = NULL; + + r = sched_policy_to_string_alloc(q, &s); + if (r < 0) + return r; + + c->cpu_sched_policy = q; + c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(q), sched_get_priority_max(q)); + c->cpu_sched_set = true; + + unit_write_settingf(u, flags, name, "CPUSchedulingPolicy=%s", s); + } + + return 1; + + } else if (streq(name, "CPUSchedulingPriority")) { + int32_t p, min, max; + + r = sd_bus_message_read(message, "i", &p); + if (r < 0) + return r; + + min = sched_get_priority_min(c->cpu_sched_policy); + max = sched_get_priority_max(c->cpu_sched_policy); + if (p < min || p > max) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority: %i", p); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->cpu_sched_priority = p; + c->cpu_sched_set = true; + + unit_write_settingf(u, flags, name, "CPUSchedulingPriority=%i", p); + } + + return 1; + + } else if (streq(name, "IOSchedulingClass")) { + int32_t q; + + r = sd_bus_message_read(message, "i", &q); + if (r < 0) + return r; + + if (!ioprio_class_is_valid(q)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling class: %i", q); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *s = NULL; + + r = ioprio_class_to_string_alloc(q, &s); + if (r < 0) + return r; + + c->ioprio = IOPRIO_PRIO_VALUE(q, IOPRIO_PRIO_DATA(c->ioprio)); + c->ioprio_set = true; + + unit_write_settingf(u, flags, name, "IOSchedulingClass=%s", s); + } + + return 1; + + } else if (streq(name, "IOSchedulingPriority")) { + int32_t p; + + r = sd_bus_message_read(message, "i", &p); + if (r < 0) + return r; + + if (!ioprio_priority_is_valid(p)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid IO scheduling priority: %i", p); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), p); + c->ioprio_set = true; + + unit_write_settingf(u, flags, name, "IOSchedulingPriority=%i", p); + } + + return 1; + + } else if (streq(name, "WorkingDirectory")) { + const char *s; + bool missing_ok; + + r = sd_bus_message_read(message, "s", &s); + if (r < 0) + return r; + + if (s[0] == '-') { + missing_ok = true; + s++; + } else + missing_ok = false; + + if (!isempty(s) && !streq(s, "~") && !path_is_absolute(s)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (streq(s, "~")) { + c->working_directory = mfree(c->working_directory); + c->working_directory_home = true; + } else { + r = free_and_strdup(&c->working_directory, empty_to_null(s)); + if (r < 0) + return r; + + c->working_directory_home = false; + } + + c->working_directory_missing_ok = missing_ok; + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s); + } + + return 1; + + } else if (STR_IN_SET(name, + "StandardInputFileDescriptorName", "StandardOutputFileDescriptorName", "StandardErrorFileDescriptorName")) { + const char *s; + + r = sd_bus_message_read(message, "s", &s); + if (r < 0) + return r; + + if (!isempty(s) && !fdname_is_valid(s)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + + if (streq(name, "StandardInputFileDescriptorName")) { + r = free_and_strdup(c->stdio_fdname + STDIN_FILENO, empty_to_null(s)); + if (r < 0) + return r; + + c->std_input = EXEC_INPUT_NAMED_FD; + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=fd:%s", exec_context_fdname(c, STDIN_FILENO)); + + } else if (streq(name, "StandardOutputFileDescriptorName")) { + r = free_and_strdup(c->stdio_fdname + STDOUT_FILENO, empty_to_null(s)); + if (r < 0) + return r; + + c->std_output = EXEC_OUTPUT_NAMED_FD; + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=fd:%s", exec_context_fdname(c, STDOUT_FILENO)); + + } else { + assert(streq(name, "StandardErrorFileDescriptorName")); + + r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], empty_to_null(s)); + if (r < 0) + return r; + + c->std_error = EXEC_OUTPUT_NAMED_FD; + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=fd:%s", exec_context_fdname(c, STDERR_FILENO)); + } + } + + return 1; + + } else if (STR_IN_SET(name, + "StandardInputFile", + "StandardOutputFile", "StandardOutputFileToAppend", + "StandardErrorFile", "StandardErrorFileToAppend")) { + const char *s; + + r = sd_bus_message_read(message, "s", &s); + if (r < 0) + return r; + + if (!isempty(s)) { + if (!path_is_absolute(s)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute", s); + if (!path_is_normalized(s)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", s); + } + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + + if (streq(name, "StandardInputFile")) { + r = free_and_strdup(&c->stdio_file[STDIN_FILENO], empty_to_null(s)); + if (r < 0) + return r; + + c->std_input = EXEC_INPUT_FILE; + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=file:%s", s); + + } else if (STR_IN_SET(name, "StandardOutputFile", "StandardOutputFileToAppend")) { + r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], empty_to_null(s)); + if (r < 0) + return r; + + if (streq(name, "StandardOutputFile")) { + c->std_output = EXEC_OUTPUT_FILE; + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s); + } else { + assert(streq(name, "StandardOutputFileToAppend")); + c->std_output = EXEC_OUTPUT_FILE_APPEND; + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s); + } + } else { + assert(STR_IN_SET(name, "StandardErrorFile", "StandardErrorFileToAppend")); + + r = free_and_strdup(&c->stdio_file[STDERR_FILENO], empty_to_null(s)); + if (r < 0) + return r; + + if (streq(name, "StandardErrorFile")) { + c->std_error = EXEC_OUTPUT_FILE; + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=file:%s", s); + } else { + assert(streq(name, "StandardErrorFileToAppend")); + c->std_error = EXEC_OUTPUT_FILE_APPEND; + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=append:%s", s); + } + } + } + + return 1; + + } else if (streq(name, "StandardInputData")) { + const void *p; + size_t sz; + + r = sd_bus_message_read_array(message, 'y', &p, &sz); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *encoded = NULL; + + if (sz == 0) { + c->stdin_data = mfree(c->stdin_data); + c->stdin_data_size = 0; + + unit_write_settingf(u, flags, name, "StandardInputData="); + } else { + void *q; + ssize_t n; + + if (c->stdin_data_size + sz < c->stdin_data_size || /* check for overflow */ + c->stdin_data_size + sz > EXEC_STDIN_DATA_MAX) + return -E2BIG; + + n = base64mem(p, sz, &encoded); + if (n < 0) + return (int) n; + + q = realloc(c->stdin_data, c->stdin_data_size + sz); + if (!q) + return -ENOMEM; + + memcpy((uint8_t*) q + c->stdin_data_size, p, sz); + + c->stdin_data = q; + c->stdin_data_size += sz; + + unit_write_settingf(u, flags, name, "StandardInputData=%s", encoded); + } + } + + return 1; + + } else if (streq(name, "Environment")) { + + _cleanup_strv_free_ char **l = NULL; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + if (!strv_env_is_valid(l)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block."); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (strv_isempty(l)) { + c->environment = strv_free(c->environment); + unit_write_setting(u, flags, name, "Environment="); + } else { + _cleanup_free_ char *joined = NULL; + char **e; + + joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C); + if (!joined) + return -ENOMEM; + + e = strv_env_merge(2, c->environment, l); + if (!e) + return -ENOMEM; + + strv_free_and_replace(c->environment, e); + unit_write_settingf(u, flags, name, "Environment=%s", joined); + } + } + + return 1; + + } else if (streq(name, "UnsetEnvironment")) { + + _cleanup_strv_free_ char **l = NULL; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + if (!strv_env_name_or_assignment_is_valid(l)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UnsetEnvironment= list."); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (strv_isempty(l)) { + c->unset_environment = strv_free(c->unset_environment); + unit_write_setting(u, flags, name, "UnsetEnvironment="); + } else { + _cleanup_free_ char *joined = NULL; + char **e; + + joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS|UNIT_ESCAPE_C); + if (!joined) + return -ENOMEM; + + e = strv_env_merge(2, c->unset_environment, l); + if (!e) + return -ENOMEM; + + strv_free_and_replace(c->unset_environment, e); + unit_write_settingf(u, flags, name, "UnsetEnvironment=%s", joined); + } + } + + return 1; + + } else if (streq(name, "OOMScoreAdjust")) { + int oa; + + r = sd_bus_message_read(message, "i", &oa); + if (r < 0) + return r; + + if (!oom_score_adjust_is_valid(oa)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range"); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->oom_score_adjust = oa; + c->oom_score_adjust_set = true; + unit_write_settingf(u, flags, name, "OOMScoreAdjust=%i", oa); + } + + return 1; + + } else if (streq(name, "EnvironmentFiles")) { + + _cleanup_free_ char *joined = NULL; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_strv_free_ char **l = NULL; + size_t size = 0; + char **i; + + r = sd_bus_message_enter_container(message, 'a', "(sb)"); + if (r < 0) + return r; + + f = open_memstream_unlocked(&joined, &size); + if (!f) + return -ENOMEM; + + fputs("EnvironmentFile=\n", f); + + STRV_FOREACH(i, c->environment_files) { + _cleanup_free_ char *q = NULL; + + q = specifier_escape(*i); + if (!q) + return -ENOMEM; + + fprintf(f, "EnvironmentFile=%s\n", q); + } + + while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) { + const char *path; + int b; + + r = sd_bus_message_read(message, "sb", &path, &b); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!path_is_absolute(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *q = NULL, *buf = NULL; + + buf = strjoin(b ? "-" : "", path); + if (!buf) + return -ENOMEM; + + q = specifier_escape(buf); + if (!q) + return -ENOMEM; + + fprintf(f, "EnvironmentFile=%s\n", q); + + r = strv_consume(&l, TAKE_PTR(buf)); + if (r < 0) + return r; + } + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + r = fflush_and_check(f); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (strv_isempty(l)) { + c->environment_files = strv_free(c->environment_files); + unit_write_setting(u, flags, name, "EnvironmentFile="); + } else { + r = strv_extend_strv(&c->environment_files, l, true); + if (r < 0) + return r; + + unit_write_setting(u, flags, name, joined); + } + } + + return 1; + + } else if (streq(name, "PassEnvironment")) { + + _cleanup_strv_free_ char **l = NULL; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + if (!strv_env_name_is_valid(l)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment= block."); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (strv_isempty(l)) { + c->pass_environment = strv_free(c->pass_environment); + unit_write_setting(u, flags, name, "PassEnvironment="); + } else { + _cleanup_free_ char *joined = NULL; + + r = strv_extend_strv(&c->pass_environment, l, true); + if (r < 0) + return r; + + /* We write just the new settings out to file, with unresolved specifiers. */ + joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS); + if (!joined) + return -ENOMEM; + + unit_write_settingf(u, flags, name, "PassEnvironment=%s", joined); + } + } + + return 1; + + } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories", + "ReadWritePaths", "ReadOnlyPaths", "InaccessiblePaths")) { + _cleanup_strv_free_ char **l = NULL; + char ***dirs; + char **p; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + STRV_FOREACH(p, l) { + char *i = *p; + size_t offset; + + offset = i[0] == '-'; + offset += i[offset] == '+'; + if (!path_is_absolute(i + offset)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name); + + path_simplify(i + offset, false); + } + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (STR_IN_SET(name, "ReadWriteDirectories", "ReadWritePaths")) + dirs = &c->read_write_paths; + else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths")) + dirs = &c->read_only_paths; + else /* "InaccessiblePaths" */ + dirs = &c->inaccessible_paths; + + if (strv_isempty(l)) { + *dirs = strv_free(*dirs); + unit_write_settingf(u, flags, name, "%s=", name); + } else { + _cleanup_free_ char *joined = NULL; + + joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS); + if (!joined) + return -ENOMEM; + + r = strv_extend_strv(dirs, l, true); + if (r < 0) + return -ENOMEM; + + unit_write_settingf(u, flags, name, "%s=%s", name, joined); + } + } + + return 1; + + } else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) { + _cleanup_strv_free_ char **l = NULL; + char **p; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + STRV_FOREACH(p, l) { + if (!path_is_normalized(*p)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is not normalized: %s", name, *p); + + if (path_is_absolute(*p)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path is absolute: %s", name, *p); + + if (path_startswith(*p, "private")) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= path can't be 'private': %s", name, *p); + } + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + ExecDirectoryType i; + ExecDirectory *d; + + assert_se((i = exec_directory_type_from_string(name)) >= 0); + d = c->directories + i; + + if (strv_isempty(l)) { + d->paths = strv_free(d->paths); + unit_write_settingf(u, flags, name, "%s=", name); + } else { + _cleanup_free_ char *joined = NULL; + + r = strv_extend_strv(&d->paths, l, true); + if (r < 0) + return r; + + joined = unit_concat_strv(l, UNIT_ESCAPE_SPECIFIERS); + if (!joined) + return -ENOMEM; + + unit_write_settingf(u, flags, name, "%s=%s", name, joined); + } + } + + return 1; + + } else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) { + int ignore; + const char *s; + + r = sd_bus_message_read(message, "(bs)", &ignore, &s); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + char **p; + bool *b; + + if (streq(name, "AppArmorProfile")) { + p = &c->apparmor_profile; + b = &c->apparmor_profile_ignore; + } else { /* "SmackProcessLabel" */ + p = &c->smack_process_label; + b = &c->smack_process_label_ignore; + } + + if (isempty(s)) { + *p = mfree(*p); + *b = false; + } else { + if (free_and_strdup(p, s) < 0) + return -ENOMEM; + *b = ignore; + } + + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s)); + } + + return 1; + + } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) { + const char *source, *destination; + int ignore_enoent; + uint64_t mount_flags; + bool empty = true; + + r = sd_bus_message_enter_container(message, 'a', "(ssbt)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(ssbt)", &source, &destination, &ignore_enoent, &mount_flags)) > 0) { + + if (!path_is_absolute(source)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source); + if (!path_is_absolute(destination)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination); + if (!IN_SET(mount_flags, 0, MS_REC)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount flags."); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts, + &(BindMount) { + .source = strdup(source), + .destination = strdup(destination), + .read_only = !!strstr(name, "ReadOnly"), + .recursive = !!(mount_flags & MS_REC), + .ignore_enoent = ignore_enoent, + }); + if (r < 0) + return r; + + unit_write_settingf( + u, flags|UNIT_ESCAPE_SPECIFIERS, name, + "%s=%s%s:%s:%s", + name, + ignore_enoent ? "-" : "", + source, + destination, + (mount_flags & MS_REC) ? "rbind" : "norbind"); + } + + empty = false; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (empty) { + bind_mount_free_many(c->bind_mounts, c->n_bind_mounts); + c->bind_mounts = NULL; + c->n_bind_mounts = 0; + + unit_write_settingf(u, flags, name, "%s=", name); + } + + return 1; + + } else if (streq(name, "TemporaryFileSystem")) { + const char *path, *options; + bool empty = true; + + r = sd_bus_message_enter_container(message, 'a', "(ss)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(ss)", &path, &options)) > 0) { + + if (!path_is_absolute(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Mount point %s is not absolute.", path); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = temporary_filesystem_add(&c->temporary_filesystems, &c->n_temporary_filesystems, path, options); + if (r < 0) + return r; + + unit_write_settingf( + u, flags|UNIT_ESCAPE_SPECIFIERS, name, + "%s=%s:%s", + name, + path, + options); + } + + empty = false; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (empty) { + temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems); + c->temporary_filesystems = NULL; + c->n_temporary_filesystems = 0; + + unit_write_settingf(u, flags, name, "%s=", name); + } + + return 1; + + } else if ((suffix = startswith(name, "Limit"))) { + const char *soft = NULL; + int ri; + + ri = rlimit_from_string(suffix); + if (ri < 0) { + soft = endswith(suffix, "Soft"); + if (soft) { + const char *n; + + n = strndupa(suffix, soft - suffix); + ri = rlimit_from_string(n); + if (ri >= 0) + name = strjoina("Limit", n); + } + } + + if (ri >= 0) { + uint64_t rl; + rlim_t x; + + r = sd_bus_message_read(message, "t", &rl); + if (r < 0) + return r; + + if (rl == (uint64_t) -1) + x = RLIM_INFINITY; + else { + x = (rlim_t) rl; + + if ((uint64_t) x != rl) + return -ERANGE; + } + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *f = NULL; + struct rlimit nl; + + if (c->rlimit[ri]) { + nl = *c->rlimit[ri]; + + if (soft) + nl.rlim_cur = x; + else + nl.rlim_max = x; + } else + /* When the resource limit is not initialized yet, then assign the value to both fields */ + nl = (struct rlimit) { + .rlim_cur = x, + .rlim_max = x, + }; + + r = rlimit_format(&nl, &f); + if (r < 0) + return r; + + if (c->rlimit[ri]) + *c->rlimit[ri] = nl; + else { + c->rlimit[ri] = newdup(struct rlimit, &nl, 1); + if (!c->rlimit[ri]) + return -ENOMEM; + } + + unit_write_settingf(u, flags, name, "%s=%s", name, f); + } + + return 1; + } + + } + + return 0; +} diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h new file mode 100644 index 00000000..cbb2f97c --- /dev/null +++ b/src/core/dbus-execute.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "execute.h" + +#define BUS_EXEC_STATUS_VTABLE(prefix, offset, flags) \ + BUS_PROPERTY_DUAL_TIMESTAMP(prefix "StartTimestamp", (offset) + offsetof(ExecStatus, start_timestamp), flags), \ + BUS_PROPERTY_DUAL_TIMESTAMP(prefix "ExitTimestamp", (offset) + offsetof(ExecStatus, exit_timestamp), flags), \ + SD_BUS_PROPERTY(prefix "PID", "u", bus_property_get_pid, (offset) + offsetof(ExecStatus, pid), flags), \ + SD_BUS_PROPERTY(prefix "Code", "i", bus_property_get_int, (offset) + offsetof(ExecStatus, code), flags), \ + SD_BUS_PROPERTY(prefix "Status", "i", bus_property_get_int, (offset) + offsetof(ExecStatus, status), flags) + +#define BUS_EXEC_COMMAND_VTABLE(name, offset, flags) \ + SD_BUS_PROPERTY(name, "a(sasbttttuii)", bus_property_get_exec_command, offset, flags) + +#define BUS_EXEC_COMMAND_LIST_VTABLE(name, offset, flags) \ + SD_BUS_PROPERTY(name, "a(sasbttttuii)", bus_property_get_exec_command_list, offset, flags) + +#define BUS_EXEC_EX_COMMAND_LIST_VTABLE(name, offset, flags) \ + SD_BUS_PROPERTY(name, "a(sasasttttuii)", bus_property_get_exec_ex_command_list, offset, flags) + +extern const sd_bus_vtable bus_exec_vtable[]; + +int bus_property_get_exec_output(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); +int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); +int bus_property_get_exec_command_list(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); +int bus_property_get_exec_ex_command_list(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); + +int bus_exec_context_set_transient_property(Unit *u, ExecContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_set_transient_exec_command(Unit *u, const char *name, ExecCommand **exec_command, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c new file mode 100644 index 00000000..a7d34225 --- /dev/null +++ b/src/core/dbus-job.c @@ -0,0 +1,313 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "dbus-job.h" +#include "dbus-unit.h" +#include "dbus.h" +#include "job.h" +#include "log.h" +#include "selinux-access.h" +#include "string-util.h" +#include "strv.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState); + +static int property_get_unit( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *p = NULL; + Job *j = userdata; + + assert(bus); + assert(reply); + assert(j); + + p = unit_dbus_path(j->unit); + if (!p) + return -ENOMEM; + + return sd_bus_message_append(reply, "(so)", j->unit->id, p); +} + +int bus_job_method_cancel(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Job *j = userdata; + int r; + + assert(message); + assert(j); + + r = mac_selinux_unit_access_check(j->unit, message, "stop", error); + if (r < 0) + return r; + + /* Access is granted to the job owner */ + if (!sd_bus_track_contains(j->bus_track, sd_bus_message_get_sender(message))) { + + /* And for everybody else consult polkit */ + r = bus_verify_manage_units_async(j->unit->manager, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + } + + job_finish_and_invalidate(j, JOB_CANCELED, true, false); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_job_method_get_waiting_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ Job **list = NULL; + Job *j = userdata; + int r, i, n; + + if (strstr(sd_bus_message_get_member(message), "After")) + n = job_get_after(j, &list); + else + n = job_get_before(j, &list); + if (n < 0) + return n; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(usssoo)"); + if (r < 0) + return r; + + for (i = 0; i < n; i ++) { + _cleanup_free_ char *unit_path = NULL, *job_path = NULL; + + job_path = job_dbus_path(list[i]); + if (!job_path) + return -ENOMEM; + + unit_path = unit_dbus_path(list[i]->unit); + if (!unit_path) + return -ENOMEM; + + r = sd_bus_message_append(reply, "(usssoo)", + list[i]->id, + list[i]->unit->id, + job_type_to_string(list[i]->type), + job_state_to_string(list[i]->state), + job_path, + unit_path); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +const sd_bus_vtable bus_job_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD("Cancel", NULL, NULL, bus_job_method_cancel, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetAfter", NULL, "a(usssoo)", bus_job_method_get_waiting_jobs, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetBefore", NULL, "a(usssoo)", bus_job_method_get_waiting_jobs, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Job, id), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_VTABLE_END +}; + +static int send_new_signal(sd_bus *bus, void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *p = NULL; + Job *j = userdata; + int r; + + assert(bus); + assert(j); + + p = job_dbus_path(j); + if (!p) + return -ENOMEM; + + r = sd_bus_message_new_signal( + bus, + &m, + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "JobNew"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "uos", j->id, p, j->unit->id); + if (r < 0) + return r; + + return sd_bus_send(bus, m, NULL); +} + +static int send_changed_signal(sd_bus *bus, void *userdata) { + _cleanup_free_ char *p = NULL; + Job *j = userdata; + + assert(bus); + assert(j); + + p = job_dbus_path(j); + if (!p) + return -ENOMEM; + + return sd_bus_emit_properties_changed(bus, p, "org.freedesktop.systemd1.Job", "State", NULL); +} + +void bus_job_send_change_signal(Job *j) { + int r; + + assert(j); + + /* Make sure that any change signal on the unit is reflected before we send out the change signal on the job */ + bus_unit_send_pending_change_signal(j->unit, true); + + if (j->in_dbus_queue) { + LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j); + j->in_dbus_queue = false; + } + + r = bus_foreach_bus(j->manager, j->bus_track, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal, j); + if (r < 0) + log_debug_errno(r, "Failed to send job change signal for %u: %m", j->id); + + j->sent_dbus_new_signal = true; +} + +void bus_job_send_pending_change_signal(Job *j, bool including_new) { + assert(j); + + if (!j->in_dbus_queue) + return; + + if (!j->sent_dbus_new_signal && !including_new) + return; + + if (MANAGER_IS_RELOADING(j->unit->manager)) + return; + + bus_job_send_change_signal(j); +} + +static int send_removed_signal(sd_bus *bus, void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *p = NULL; + Job *j = userdata; + int r; + + assert(bus); + assert(j); + + p = job_dbus_path(j); + if (!p) + return -ENOMEM; + + r = sd_bus_message_new_signal( + bus, + &m, + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "JobRemoved"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "uoss", j->id, p, j->unit->id, job_result_to_string(j->result)); + if (r < 0) + return r; + + return sd_bus_send(bus, m, NULL); +} + +void bus_job_send_removed_signal(Job *j) { + int r; + + assert(j); + + if (!j->sent_dbus_new_signal) + bus_job_send_change_signal(j); + + /* Make sure that any change signal on the unit is reflected before we send out the change signal on the job */ + bus_unit_send_pending_change_signal(j->unit, true); + + r = bus_foreach_bus(j->manager, j->bus_track, send_removed_signal, j); + if (r < 0) + log_debug_errno(r, "Failed to send job remove signal for %u: %m", j->id); +} + +static int bus_job_track_handler(sd_bus_track *t, void *userdata) { + Job *j = userdata; + + assert(t); + assert(j); + + j->bus_track = sd_bus_track_unref(j->bus_track); /* make sure we aren't called again */ + + /* Last client dropped off the bus, maybe we should GC this now? */ + job_add_to_gc_queue(j); + return 0; +} + +static int bus_job_allocate_bus_track(Job *j) { + + assert(j); + + if (j->bus_track) + return 0; + + return sd_bus_track_new(j->unit->manager->api_bus, &j->bus_track, bus_job_track_handler, j); +} + +int bus_job_coldplug_bus_track(Job *j) { + int r = 0; + _cleanup_strv_free_ char **deserialized_clients = NULL; + + assert(j); + + deserialized_clients = TAKE_PTR(j->deserialized_clients); + + if (strv_isempty(deserialized_clients)) + return 0; + + if (!j->manager->api_bus) + return 0; + + r = bus_job_allocate_bus_track(j); + if (r < 0) + return r; + + return bus_track_add_name_many(j->bus_track, deserialized_clients); +} + +int bus_job_track_sender(Job *j, sd_bus_message *m) { + int r; + + assert(j); + assert(m); + + if (sd_bus_message_get_bus(m) != j->unit->manager->api_bus) { + j->ref_by_private_bus = true; + return 0; + } + + r = bus_job_allocate_bus_track(j); + if (r < 0) + return r; + + return sd_bus_track_add_sender(j->bus_track, m); +} diff --git a/src/core/dbus-job.h b/src/core/dbus-job.h new file mode 100644 index 00000000..380e117f --- /dev/null +++ b/src/core/dbus-job.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" + +extern const sd_bus_vtable bus_job_vtable[]; + +int bus_job_method_cancel(sd_bus_message *message, void *job, sd_bus_error *error); +int bus_job_method_get_waiting_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error); + +void bus_job_send_change_signal(Job *j); +void bus_job_send_pending_change_signal(Job *j, bool including_new); +void bus_job_send_removed_signal(Job *j); + +int bus_job_coldplug_bus_track(Job *j); +int bus_job_track_sender(Job *j, sd_bus_message *m); diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c new file mode 100644 index 00000000..30597e86 --- /dev/null +++ b/src/core/dbus-kill.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-util.h" +#include "dbus-kill.h" +#include "dbus-util.h" +#include "kill.h" +#include "signal-util.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_kill_mode, kill_mode, KillMode); + +static int property_get_restart_kill_signal( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + KillContext *c = userdata; + int s; + + assert(c); + + s = restart_kill_signal(c); + return sd_bus_message_append_basic(reply, 'i', &s); +} + +const sd_bus_vtable bus_kill_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("KillMode", "s", property_get_kill_mode, offsetof(KillContext, kill_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KillSignal", "i", bus_property_get_int, offsetof(KillContext, kill_signal), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestartKillSignal", "i", property_get_restart_kill_signal, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("FinalKillSignal", "i", bus_property_get_int, offsetof(KillContext, final_kill_signal), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SendSIGKILL", "b", bus_property_get_bool, offsetof(KillContext, send_sigkill), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SendSIGHUP", "b", bus_property_get_bool, offsetof(KillContext, send_sighup), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("WatchdogSignal", "i", bus_property_get_int, offsetof(KillContext, watchdog_signal), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_VTABLE_END +}; + +static BUS_DEFINE_SET_TRANSIENT_PARSE(kill_mode, KillMode, kill_mode_from_string); +static BUS_DEFINE_SET_TRANSIENT_TO_STRING(kill_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check); +static BUS_DEFINE_SET_TRANSIENT_TO_STRING(restart_kill_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check); +static BUS_DEFINE_SET_TRANSIENT_TO_STRING(final_kill_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check); +static BUS_DEFINE_SET_TRANSIENT_TO_STRING(watchdog_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check); + +int bus_kill_context_set_transient_property( + Unit *u, + KillContext *c, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + assert(u); + assert(c); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "KillMode")) + return bus_set_transient_kill_mode(u, name, &c->kill_mode, message, flags, error); + + if (streq(name, "SendSIGHUP")) + return bus_set_transient_bool(u, name, &c->send_sighup, message, flags, error); + + if (streq(name, "SendSIGKILL")) + return bus_set_transient_bool(u, name, &c->send_sigkill, message, flags, error); + + if (streq(name, "KillSignal")) + return bus_set_transient_kill_signal(u, name, &c->kill_signal, message, flags, error); + + if (streq(name, "RestartKillSignal")) + return bus_set_transient_restart_kill_signal(u, name, &c->restart_kill_signal, message, flags, error); + + if (streq(name, "FinalKillSignal")) + return bus_set_transient_final_kill_signal(u, name, &c->final_kill_signal, message, flags, error); + + if (streq(name, "WatchdogSignal")) + return bus_set_transient_watchdog_signal(u, name, &c->watchdog_signal, message, flags, error); + + return 0; +} diff --git a/src/core/dbus-kill.h b/src/core/dbus-kill.h new file mode 100644 index 00000000..8192e94f --- /dev/null +++ b/src/core/dbus-kill.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "kill.h" +#include "unit.h" + +extern const sd_bus_vtable bus_kill_vtable[]; + +int bus_kill_context_set_transient_property(Unit *u, KillContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c new file mode 100644 index 00000000..c751e842 --- /dev/null +++ b/src/core/dbus-manager.c @@ -0,0 +1,2656 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "architecture.h" +#include "build.h" +#include "bus-common-errors.h" +#include "dbus-cgroup.h" +#include "dbus-execute.h" +#include "dbus-job.h" +#include "dbus-manager.h" +#include "dbus-scope.h" +#include "dbus-unit.h" +#include "dbus.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "install.h" +#include "log.h" +#include "os-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "selinux-access.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "syslog-util.h" +#include "user-util.h" +#include "virt.h" +#include "watchdog.h" + +/* Require 16MiB free in /run/systemd for reloading/reexecing. After all we need to serialize our state there, and if + * we can't we'll fail badly. */ +#define RELOAD_DISK_SPACE_MIN (UINT64_C(16) * UINT64_C(1024) * UINT64_C(1024)) + +static UnitFileFlags unit_file_bools_to_flags(bool runtime, bool force) { + return (runtime ? UNIT_FILE_RUNTIME : 0) | + (force ? UNIT_FILE_FORCE : 0); +} + +BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_oom_policy, oom_policy, OOMPolicy); + +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_version, "s", GIT_VERSION); +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_features, "s", SYSTEMD_FEATURES); +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_architecture, "s", architecture_to_string(uname_architecture())); +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_log_target, "s", log_target_to_string(log_get_target())); +static BUS_DEFINE_PROPERTY_GET2(property_get_system_state, "s", Manager, manager_state, manager_state_to_string); +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_timer_slack_nsec, "t", (uint64_t) prctl(PR_GET_TIMERSLACK)); +static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "u", Hashmap *, hashmap_size); +static BUS_DEFINE_PROPERTY_GET_REF(property_get_set_size, "u", Set *, set_size); +static BUS_DEFINE_PROPERTY_GET(property_get_default_timeout_abort_usec, "t", Manager, manager_default_timeout_abort_usec); + +static int property_get_virtualization( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + int v; + + assert(bus); + assert(reply); + + v = detect_virtualization(); + + /* Make sure to return the empty string when we detect no virtualization, as that is the API. + * + * https://github.com/systemd/systemd/issues/1423 + */ + + return sd_bus_message_append( + reply, "s", + v == VIRTUALIZATION_NONE ? NULL : virtualization_to_string(v)); +} + +static int property_get_tainted( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *s = NULL; + Manager *m = userdata; + + assert(bus); + assert(reply); + assert(m); + + s = manager_taint_string(m); + if (!s) + return log_oom(); + + return sd_bus_message_append(reply, "s", s); +} + +static int property_set_log_target( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *value, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + const char *t; + int r; + + assert(bus); + assert(value); + + r = sd_bus_message_read(value, "s", &t); + if (r < 0) + return r; + + if (isempty(t)) + manager_restore_original_log_target(m); + else { + LogTarget target; + + target = log_target_from_string(t); + if (target < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log target '%s'", t); + + manager_override_log_target(m, target); + } + + return 0; +} + +static int property_get_log_level( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *t = NULL; + int r; + + assert(bus); + assert(reply); + + r = log_level_to_string_alloc(log_get_max_level(), &t); + if (r < 0) + return r; + + return sd_bus_message_append(reply, "s", t); +} + +static int property_set_log_level( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *value, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + const char *t; + int r; + + assert(bus); + assert(value); + + r = sd_bus_message_read(value, "s", &t); + if (r < 0) + return r; + + if (isempty(t)) + manager_restore_original_log_level(m); + else { + int level; + + level = log_level_from_string(t); + if (level < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log level '%s'", t); + + manager_override_log_level(m, level); + } + + return 0; +} + +static int property_get_progress( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + double d; + + assert(bus); + assert(reply); + assert(m); + + if (MANAGER_IS_FINISHED(m)) + d = 1.0; + else + d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs); + + return sd_bus_message_append(reply, "d", d); +} + +static int property_get_environment( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + int r; + + assert(bus); + assert(reply); + assert(m); + + r = manager_get_effective_environment(m, &l); + if (r < 0) + return r; + + return sd_bus_message_append_strv(reply, l); +} + +static int property_get_show_status( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + int b; + + assert(bus); + assert(reply); + assert(m); + + b = IN_SET(m->show_status, SHOW_STATUS_TEMPORARY, SHOW_STATUS_YES); + return sd_bus_message_append_basic(reply, 'b', &b); +} + +static int property_set_runtime_watchdog( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *value, + void *userdata, + sd_bus_error *error) { + + usec_t *t = userdata; + int r; + + assert(bus); + assert(value); + + assert_cc(sizeof(usec_t) == sizeof(uint64_t)); + + r = sd_bus_message_read(value, "t", t); + if (r < 0) + return r; + + return watchdog_set_timeout(t); +} + +static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) { + Unit *u; + int r; + + assert(m); + assert(message); + assert(ret_unit); + + /* More or less a wrapper around manager_get_unit() that generates nice errors and has one trick up its sleeve: + * if the name is specified empty we use the client's unit. */ + + if (isempty(name)) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + pid_t pid; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + + u = manager_get_unit_by_pid(m, pid); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit."); + } else { + u = manager_get_unit(m, name); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name); + } + + *ret_unit = u; + return 0; +} + +static int bus_load_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) { + assert(m); + assert(message); + assert(ret_unit); + + /* Pretty much the same as bus_get_unit_by_name(), but we also load the unit if necessary. */ + + if (isempty(name)) + return bus_get_unit_by_name(m, message, name, ret_unit, error); + + return manager_load_unit(m, name, NULL, error, ret_unit); +} + +static int reply_unit_path(Unit *u, sd_bus_message *message, sd_bus_error *error) { + _cleanup_free_ char *path = NULL; + int r; + + assert(u); + assert(message); + + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + + path = unit_dbus_path(u); + if (!path) + return log_oom(); + + return sd_bus_reply_method_return(message, "o", path); +} + +static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = bus_get_unit_by_name(m, message, name, &u, error); + if (r < 0) + return r; + + return reply_unit_path(u, message, error); +} + +static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + pid_t pid; + Unit *u; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(pid_t) == sizeof(uint32_t)); + + /* Anyone can call this method */ + + r = sd_bus_message_read(message, "u", &pid); + if (r < 0) + return r; + if (pid < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PID " PID_FMT, pid); + + if (pid == 0) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + } + + u = manager_get_unit_by_pid(m, pid); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid); + + return reply_unit_path(u, message, error); +} + +static int method_get_unit_by_invocation_id(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *path = NULL; + Manager *m = userdata; + sd_id128_t id; + const void *a; + Unit *u; + size_t sz; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = sd_bus_message_read_array(message, 'y', &a, &sz); + if (r < 0) + return r; + if (sz == 0) + id = SD_ID128_NULL; + else if (sz == 16) + memcpy(&id, a, sz); + else + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid invocation ID"); + + if (sd_id128_is_null(id)) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + pid_t pid; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + + u = manager_get_unit_by_pid(m, pid); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client " PID_FMT " not member of any unit.", pid); + } else { + u = hashmap_get(m->units_by_invocation_id, &id); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.", SD_ID128_FORMAT_VAL(id)); + } + + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + + /* So here's a special trick: the bus path we return actually references the unit by its invocation ID instead + * of the unit name. This means it stays valid only as long as the invocation ID stays the same. */ + path = unit_dbus_path_invocation_id(u); + if (!path) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", path); +} + +static int method_get_unit_by_control_group(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *cgroup; + Unit *u; + int r; + + r = sd_bus_message_read(message, "s", &cgroup); + if (r < 0) + return r; + + u = manager_get_unit_by_cgroup(m, cgroup); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Control group '%s' is not valid or not managed by this instance", cgroup); + + return reply_unit_path(u, message, error); +} + +static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = bus_load_unit_by_name(m, message, name, &u, error); + if (r < 0) + return r; + + return reply_unit_path(u, message, error); +} + +static int method_start_unit_generic(sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible, sd_bus_error *error) { + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_load_unit(m, name, NULL, error, &u); + if (r < 0) + return r; + + return bus_unit_method_start_generic(message, u, job_type, reload_if_possible, error); +} + +static int method_start_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_start_unit_generic(message, userdata, JOB_START, false, error); +} + +static int method_stop_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_start_unit_generic(message, userdata, JOB_STOP, false, error); +} + +static int method_reload_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_start_unit_generic(message, userdata, JOB_RELOAD, false, error); +} + +static int method_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_start_unit_generic(message, userdata, JOB_RESTART, false, error); +} + +static int method_try_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, false, error); +} + +static int method_reload_or_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_start_unit_generic(message, userdata, JOB_RESTART, true, error); +} + +static int method_reload_or_try_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, true, error); +} + +typedef enum GenericUnitOperationFlags { + GENERIC_UNIT_LOAD = 1 << 0, /* Load if the unit is not loaded yet */ + GENERIC_UNIT_VALIDATE_LOADED = 1 << 1, /* Verify unit is properly loaded before forwarding call */ +} GenericUnitOperationFlags; + +static int method_generic_unit_operation( + sd_bus_message *message, + Manager *m, + sd_bus_error *error, + sd_bus_message_handler_t handler, + GenericUnitOperationFlags flags) { + + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + /* Read the first argument from the command and pass the operation to the specified per-unit + * method. */ + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + if (!isempty(name) && FLAGS_SET(flags, GENERIC_UNIT_LOAD)) + r = manager_load_unit(m, name, NULL, error, &u); + else + r = bus_get_unit_by_name(m, message, name, &u, error); + if (r < 0) + return r; + + if (FLAGS_SET(flags, GENERIC_UNIT_VALIDATE_LOADED)) { + r = bus_unit_validate_load_state(u, error); + if (r < 0) + return r; + } + + return handler(message, u, error); +} + +static int method_enqueue_unit_job(sd_bus_message *message, void *userdata, sd_bus_error *error) { + /* We don't bother with GENERIC_UNIT_VALIDATE_LOADED here, as the job logic validates that anyway */ + return method_generic_unit_operation(message, userdata, error, bus_unit_method_enqueue_job, GENERIC_UNIT_LOAD); +} + +static int method_start_unit_replace(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *old_name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &old_name); + if (r < 0) + return r; + + r = bus_get_unit_by_name(m, message, old_name, &u, error); + if (r < 0) + return r; + if (!u->job || u->job->type != JOB_START) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name); + + return method_start_unit_generic(message, m, JOB_START, false, error); +} + +static int method_kill_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + /* We don't bother with GENERIC_UNIT_LOAD nor GENERIC_UNIT_VALIDATE_LOADED here, as it shouldn't + * matter whether a unit is loaded for killing any processes possibly in the unit's cgroup. */ + return method_generic_unit_operation(message, userdata, error, bus_unit_method_kill, 0); +} + +static int method_clean_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + /* Load the unit if necessary, in order to load it, and insist on the unit being loaded to be + * cleaned */ + return method_generic_unit_operation(message, userdata, error, bus_unit_method_clean, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); +} + +static int method_reset_failed_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + /* Don't load the unit (because unloaded units can't be in failed state), and don't insist on the + * unit to be loaded properly (since a failed unit might have its unit file disappeared) */ + return method_generic_unit_operation(message, userdata, error, bus_unit_method_reset_failed, 0); +} + +static int method_set_unit_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) { + /* Only change properties on fully loaded units, and load them in order to set properties */ + return method_generic_unit_operation(message, userdata, error, bus_unit_method_set_properties, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); +} + +static int method_ref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + /* Only allow reffing of fully loaded units, and make sure reffing a unit loads it. */ + return method_generic_unit_operation(message, userdata, error, bus_unit_method_ref, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED); +} + +static int method_unref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + /* Dropping a ref OTOH should not require the unit to still be loaded. And since a reffed unit is a + * loaded unit there's no need to load the unit for unreffing it. */ + return method_generic_unit_operation(message, userdata, error, bus_unit_method_unref, 0); +} + +static int reply_unit_info(sd_bus_message *reply, Unit *u) { + _cleanup_free_ char *unit_path = NULL, *job_path = NULL; + Unit *following; + + following = unit_following(u); + + unit_path = unit_dbus_path(u); + if (!unit_path) + return -ENOMEM; + + if (u->job) { + job_path = job_dbus_path(u->job); + if (!job_path) + return -ENOMEM; + } + + return sd_bus_message_append( + reply, "(ssssssouso)", + u->id, + unit_description(u), + unit_load_state_to_string(u->load_state), + unit_active_state_to_string(unit_active_state(u)), + unit_sub_state_to_string(u), + following ? following->id : "", + unit_path, + u->job ? u->job->id : 0, + u->job ? job_type_to_string(u->job->type) : "", + empty_to_root(job_path)); +} + +static int method_list_units_by_names(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + int r; + char **unit; + _cleanup_strv_free_ char **units = NULL; + + assert(message); + assert(m); + + r = sd_bus_message_read_strv(message, &units); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)"); + if (r < 0) + return r; + + STRV_FOREACH(unit, units) { + Unit *u; + + if (!unit_name_is_valid(*unit, UNIT_NAME_ANY)) + continue; + + r = bus_load_unit_by_name(m, message, *unit, &u, error); + if (r < 0) + return r; + + r = reply_unit_info(reply, u); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_get_unit_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) { + /* Don't load a unit (since it won't have any processes if it's not loaded), but don't insist on the + * unit being loaded (because even improperly loaded units might still have processes around */ + return method_generic_unit_operation(message, userdata, error, bus_unit_method_get_processes, 0); +} + +static int method_attach_processes_to_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + /* Don't allow attaching new processes to units that aren't loaded. Don't bother with loading a unit + * for this purpose though, as an unloaded unit is a stopped unit, and we don't allow attaching + * processes to stopped units anyway. */ + return method_generic_unit_operation(message, userdata, error, bus_unit_method_attach_processes, GENERIC_UNIT_VALIDATE_LOADED); +} + +static int transient_unit_from_message( + Manager *m, + sd_bus_message *message, + const char *name, + Unit **unit, + sd_bus_error *error) { + + UnitType t; + Unit *u; + int r; + + assert(m); + assert(message); + assert(name); + + t = unit_name_to_type(name); + if (t < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name or type."); + + if (!unit_vtable[t]->can_transient) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t)); + + r = manager_load_unit(m, name, NULL, error, &u); + if (r < 0) + return r; + + if (!unit_is_pristine(u)) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name); + + /* OK, the unit failed to load and is unreferenced, now let's + * fill in the transient data instead */ + r = unit_make_transient(u); + if (r < 0) + return r; + + /* Set our properties */ + r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, error); + if (r < 0) + return r; + + /* If the client asked for it, automatically add a reference to this unit. */ + if (u->bus_track_add) { + r = bus_unit_track_add_sender(u, message); + if (r < 0) + return log_error_errno(r, "Failed to watch sender: %m"); + } + + /* Now load the missing bits of the unit we just created */ + unit_add_to_load_queue(u); + manager_dispatch_load_queue(m); + + *unit = u; + + return 0; +} + +static int transient_aux_units_from_message( + Manager *m, + sd_bus_message *message, + sd_bus_error *error) { + + int r; + + assert(m); + assert(message); + + r = sd_bus_message_enter_container(message, 'a', "(sa(sv))"); + if (r < 0) + return r; + + while ((r = sd_bus_message_enter_container(message, 'r', "sa(sv)")) > 0) { + const char *name = NULL; + Unit *u; + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = transient_unit_from_message(m, message, name, &u, error); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + return 0; +} + +static int method_start_transient_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *name, *smode; + Manager *m = userdata; + JobMode mode; + Unit *u; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "start", error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "ss", &name, &smode); + if (r < 0) + return r; + + mode = job_mode_from_string(smode); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode); + + r = bus_verify_manage_units_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = transient_unit_from_message(m, message, name, &u, error); + if (r < 0) + return r; + + r = transient_aux_units_from_message(m, message, error); + if (r < 0) + return r; + + /* Finally, start it */ + return bus_unit_queue_job(message, u, JOB_START, mode, 0, error); +} + +static int method_get_job(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *path = NULL; + Manager *m = userdata; + uint32_t id; + Job *j; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = sd_bus_message_read(message, "u", &id); + if (r < 0) + return r; + + j = manager_get_job(m, id); + if (!j) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id); + + r = mac_selinux_unit_access_check(j->unit, message, "status", error); + if (r < 0) + return r; + + path = job_dbus_path(j); + if (!path) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", path); +} + +static int method_cancel_job(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + uint32_t id; + Job *j; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "u", &id); + if (r < 0) + return r; + + j = manager_get_job(m, id); + if (!j) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id); + + return bus_job_method_cancel(message, j, error); +} + +static int method_clear_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "reload", error); + if (r < 0) + return r; + + r = bus_verify_manage_units_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + manager_clear_jobs(m); + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "reload", error); + if (r < 0) + return r; + + r = bus_verify_manage_units_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + manager_reset_failed(m); + + return sd_bus_reply_method_return(message, NULL); +} + +static int list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + const char *k; + Iterator i; + Unit *u; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)"); + if (r < 0) + return r; + + HASHMAP_FOREACH_KEY(u, k, m->units, i) { + if (k != u->id) + continue; + + if (!strv_isempty(states) && + !strv_contains(states, unit_load_state_to_string(u->load_state)) && + !strv_contains(states, unit_active_state_to_string(unit_active_state(u))) && + !strv_contains(states, unit_sub_state_to_string(u))) + continue; + + if (!strv_isempty(patterns) && + !strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE)) + continue; + + r = reply_unit_info(reply, u); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_list_units(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return list_units_filtered(message, userdata, error, NULL, NULL); +} + +static int method_list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **states = NULL; + int r; + + r = sd_bus_message_read_strv(message, &states); + if (r < 0) + return r; + + return list_units_filtered(message, userdata, error, states, NULL); +} + +static int method_list_units_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **states = NULL; + _cleanup_strv_free_ char **patterns = NULL; + int r; + + r = sd_bus_message_read_strv(message, &states); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(message, &patterns); + if (r < 0) + return r; + + return list_units_filtered(message, userdata, error, states, patterns); +} + +static int method_list_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + Iterator i; + Job *j; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(usssoo)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(j, m->jobs, i) { + _cleanup_free_ char *unit_path = NULL, *job_path = NULL; + + job_path = job_dbus_path(j); + if (!job_path) + return -ENOMEM; + + unit_path = unit_dbus_path(j->unit); + if (!unit_path) + return -ENOMEM; + + r = sd_bus_message_append( + reply, "(usssoo)", + j->id, + j->unit->id, + job_type_to_string(j->type), + job_state_to_string(j->state), + job_path, + unit_path); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_subscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + + if (sd_bus_message_get_bus(message) == m->api_bus) { + + /* Note that direct bus connection subscribe by + * default, we only track peers on the API bus here */ + + if (!m->subscribed) { + r = sd_bus_track_new(sd_bus_message_get_bus(message), &m->subscribed, NULL, NULL); + if (r < 0) + return r; + } + + r = sd_bus_track_add_sender(m->subscribed, message); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed."); + } + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_unsubscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + + if (sd_bus_message_get_bus(message) == m->api_bus) { + r = sd_bus_track_remove_sender(m->subscribed, message); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed."); + } + + return sd_bus_reply_method_return(message, NULL); +} + +static int dump_impl(sd_bus_message *message, void *userdata, sd_bus_error *error, int (*reply)(sd_bus_message *, char *)) { + _cleanup_free_ char *dump = NULL; + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + + r = manager_get_dump_string(m, &dump); + if (r < 0) + return r; + + return reply(message, dump); +} + +static int reply_dump(sd_bus_message *message, char *dump) { + return sd_bus_reply_method_return(message, "s", dump); +} + +static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return dump_impl(message, userdata, error, reply_dump); +} + +static int reply_dump_by_fd(sd_bus_message *message, char *dump) { + _cleanup_close_ int fd = -1; + + fd = acquire_data_fd(dump, strlen(dump), 0); + if (fd < 0) + return fd; + + return sd_bus_reply_method_return(message, "h", fd); +} + +static int method_dump_by_fd(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return dump_impl(message, userdata, error, reply_dump_by_fd); +} + +static int method_refuse_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for snapshots has been removed."); +} + +static int verify_run_space(const char *message, sd_bus_error *error) { + struct statvfs svfs; + uint64_t available; + + if (statvfs("/run/systemd", &svfs) < 0) + return sd_bus_error_set_errnof(error, errno, "Failed to statvfs(/run/systemd): %m"); + + available = (uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize; + + if (available < RELOAD_DISK_SPACE_MIN) { + char fb_available[FORMAT_BYTES_MAX], fb_need[FORMAT_BYTES_MAX]; + return sd_bus_error_setf(error, + BUS_ERROR_DISK_FULL, + "%s, not enough space available on /run/systemd. " + "Currently, %s are free, but a safety buffer of %s is enforced.", + message, + format_bytes(fb_available, sizeof(fb_available), available), + format_bytes(fb_need, sizeof(fb_need), RELOAD_DISK_SPACE_MIN)); + } + + return 0; +} + +int verify_run_space_and_log(const char *message) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + r = verify_run_space(message, &error); + if (r < 0) + return log_error_errno(r, "%s", bus_error_message(&error, r)); + + return 0; +} + +static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = verify_run_space("Refusing to reload", error); + if (r < 0) + return r; + + r = mac_selinux_access_check(message, "reload", error); + if (r < 0) + return r; + + r = bus_verify_reload_daemon_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + /* Instead of sending the reply back right away, we just + * remember that we need to and then send it after the reload + * is finished. That way the caller knows when the reload + * finished. */ + + assert(!m->pending_reload_message); + r = sd_bus_message_new_method_return(message, &m->pending_reload_message); + if (r < 0) + return r; + + m->objective = MANAGER_RELOAD; + + return 1; +} + +static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = verify_run_space("Refusing to reexecute", error); + if (r < 0) + return r; + + r = mac_selinux_access_check(message, "reload", error); + if (r < 0) + return r; + + r = bus_verify_reload_daemon_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + /* We don't send a reply back here, the client should + * just wait for us disconnecting. */ + + m->objective = MANAGER_REEXECUTE; + return 1; +} + +static int method_exit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "halt", error); + if (r < 0) + return r; + + /* Exit() (in contrast to SetExitCode()) is actually allowed even if + * we are running on the host. It will fall back on reboot() in + * systemd-shutdown if it cannot do the exit() because it isn't a + * container. */ + + m->objective = MANAGER_EXIT; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "reboot", error); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers."); + + m->objective = MANAGER_REBOOT; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "halt", error); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers."); + + m->objective = MANAGER_POWEROFF; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "halt", error); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers."); + + m->objective = MANAGER_HALT; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "reboot", error); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers."); + + m->objective = MANAGER_KEXEC; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *ri = NULL, *rt = NULL; + const char *root, *init; + Manager *m = userdata; + struct statvfs svfs; + uint64_t available; + int r; + + assert(message); + assert(m); + + if (statvfs("/run/systemd", &svfs) < 0) + return sd_bus_error_set_errnof(error, errno, "Failed to statvfs(/run/systemd): %m"); + + available = (uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize; + + if (available < RELOAD_DISK_SPACE_MIN) { + char fb_available[FORMAT_BYTES_MAX], fb_need[FORMAT_BYTES_MAX]; + log_warning("Dangerously low amount of free space on /run/systemd, root switching operation might not complete successfully. " + "Currently, %s are free, but %s are suggested. Proceeding anyway.", + format_bytes(fb_available, sizeof(fb_available), available), + format_bytes(fb_need, sizeof(fb_need), RELOAD_DISK_SPACE_MIN)); + } + + r = mac_selinux_access_check(message, "reboot", error); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager."); + + r = sd_bus_message_read(message, "ss", &root, &init); + if (r < 0) + return r; + + if (isempty(root)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root directory may not be the empty string."); + if (!path_is_absolute(root)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root path '%s' is not absolute.", root); + if (path_equal(root, "/")) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New root directory cannot be the old root directory."); + + /* Safety check */ + if (isempty(init)) { + r = path_is_os_tree(root); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to determine whether root path '%s' contains an OS tree: %m", root); + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path '%s' does not seem to be an OS tree. os-release file is missing.", root); + } else { + _cleanup_free_ char *chased = NULL; + + if (!path_is_absolute(init)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path to init binary '%s' not absolute.", init); + + r = chase_symlinks(init, root, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &chased, NULL); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Could not resolve init executable %s: %m", init); + + if (laccess(chased, X_OK) < 0) { + if (errno == EACCES) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Init binary %s is not executable.", init); + + return sd_bus_error_set_errnof(error, r, "Could not check whether init binary %s is executable: %m", init); + } + } + + rt = strdup(root); + if (!rt) + return -ENOMEM; + + if (!isempty(init)) { + ri = strdup(init); + if (!ri) + return -ENOMEM; + } + + free_and_replace(m->switch_root, rt); + free_and_replace(m->switch_root_init, ri); + + m->objective = MANAGER_SWITCH_ROOT; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **plus = NULL; + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "reload", error); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(message, &plus); + if (r < 0) + return r; + if (!strv_env_is_valid(plus)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments"); + + r = bus_verify_set_environment_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = manager_client_environment_modify(m, NULL, plus); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_unset_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **minus = NULL; + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "reload", error); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(message, &minus); + if (r < 0) + return r; + + if (!strv_env_name_or_assignment_is_valid(minus)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments"); + + r = bus_verify_set_environment_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = manager_client_environment_modify(m, minus, NULL); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_unset_and_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **minus = NULL, **plus = NULL; + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "reload", error); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(message, &minus); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(message, &plus); + if (r < 0) + return r; + + if (!strv_env_name_or_assignment_is_valid(minus)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments"); + if (!strv_env_is_valid(plus)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments"); + + r = bus_verify_set_environment_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = manager_client_environment_modify(m, minus, plus); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + uint8_t code; + int r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "exit", error); + if (r < 0) + return r; + + r = sd_bus_message_read_basic(message, 'y', &code); + if (r < 0) + return r; + + if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "ExitCode can only be set for user service managers or in containers."); + + m->return_value = code; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_lookup_dynamic_user_by_name(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + uid_t uid; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read_basic(message, 's', &name); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance."); + if (!valid_user_group_name(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User name invalid: %s", name); + + r = dynamic_user_lookup_name(m, name, &uid); + if (r == -ESRCH) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER, "Dynamic user %s does not exist.", name); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "u", (uint32_t) uid); +} + +static int method_lookup_dynamic_user_by_uid(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *name = NULL; + Manager *m = userdata; + uid_t uid; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(uid) == sizeof(uint32_t)); + r = sd_bus_message_read_basic(message, 'u', &uid); + if (r < 0) + return r; + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance."); + if (!uid_is_valid(uid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User ID invalid: " UID_FMT, uid); + + r = dynamic_user_lookup_uid(m, uid, &name); + if (r == -ESRCH) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DYNAMIC_USER, "Dynamic user ID " UID_FMT " does not exist.", uid); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "s", name); +} + +static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + DynamicUser *d; + Iterator i; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(uid_t) == sizeof(uint32_t)); + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance."); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(us)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(d, m->dynamic_users, i) { + uid_t uid; + + r = dynamic_user_current(d, &uid); + if (r == -EAGAIN) /* not realized yet? */ + continue; + if (r < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to lookup a dynamic user."); + + r = sd_bus_message_append(reply, "(us)", uid, d->name); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states, char **patterns) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + UnitFileList *item; + Hashmap *h; + Iterator i; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + h = hashmap_new(&string_hash_ops); + if (!h) + return -ENOMEM; + + r = unit_file_get_list(m->unit_file_scope, NULL, h, states, patterns); + if (r < 0) + goto fail; + + r = sd_bus_message_open_container(reply, 'a', "(ss)"); + if (r < 0) + goto fail; + + HASHMAP_FOREACH(item, h, i) { + + r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state)); + if (r < 0) + goto fail; + } + + unit_file_list_free(h); + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); + +fail: + unit_file_list_free(h); + return r; +} + +static int method_list_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return list_unit_files_by_patterns(message, userdata, error, NULL, NULL); +} + +static int method_list_unit_files_by_patterns(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **states = NULL; + _cleanup_strv_free_ char **patterns = NULL; + int r; + + r = sd_bus_message_read_strv(message, &states); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(message, &patterns); + if (r < 0) + return r; + + return list_unit_files_by_patterns(message, userdata, error, states, patterns); +} + +static int method_get_unit_file_state(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + UnitFileState state; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = unit_file_get_state(m->unit_file_scope, NULL, name, &state); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state)); +} + +static int method_get_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *default_target = NULL; + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + /* Anyone can call this method */ + + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + + r = unit_file_get_default(m->unit_file_scope, NULL, &default_target); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "s", default_target); +} + +static int send_unit_files_changed(sd_bus *bus, void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL; + int r; + + assert(bus); + + r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged"); + if (r < 0) + return r; + + return sd_bus_send(bus, message, NULL); +} + +/* Create an error reply, using the error information from changes[] + * if possible, and fall back to generating an error from error code c. + * The error message only describes the first error. + * + * Coordinate with unit_file_dump_changes() in install.c. + */ +static int install_error( + sd_bus_error *error, + int c, + UnitFileChange *changes, + size_t n_changes) { + + size_t i; + int r; + + for (i = 0; i < n_changes; i++) + + switch(changes[i].type) { + + case 0 ... INT_MAX: + continue; + + case -EEXIST: + if (changes[i].source) + r = sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, + "File %s already exists and is a symlink to %s.", + changes[i].path, changes[i].source); + else + r = sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, + "File %s already exists.", + changes[i].path); + goto found; + + case -ERFKILL: + r = sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, + "Unit file %s is masked.", changes[i].path); + goto found; + + case -EADDRNOTAVAIL: + r = sd_bus_error_setf(error, BUS_ERROR_UNIT_GENERATED, + "Unit %s is transient or generated.", changes[i].path); + goto found; + + case -EUCLEAN: + r = sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, + "\"%s\" is not a valid unit name.", + changes[i].path); + goto found; + + case -ELOOP: + r = sd_bus_error_setf(error, BUS_ERROR_UNIT_LINKED, + "Refusing to operate on alias name or linked unit file: %s", + changes[i].path); + goto found; + + case -ENOENT: + r = sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, + "Unit file %s does not exist.", changes[i].path); + goto found; + + default: + r = sd_bus_error_set_errnof(error, changes[i].type, "File %s: %m", changes[i].path); + goto found; + } + + r = c < 0 ? c : -EINVAL; + + found: + unit_file_changes_free(changes, n_changes); + return r; +} + +static int reply_unit_file_changes_and_free( + Manager *m, + sd_bus_message *message, + int carries_install_info, + UnitFileChange *changes, + size_t n_changes, + sd_bus_error *error) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + bool bad = false, good = false; + size_t i; + int r; + + if (unit_file_changes_have_modification(changes, n_changes)) { + r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL); + if (r < 0) + log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m"); + } + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + goto fail; + + if (carries_install_info >= 0) { + r = sd_bus_message_append(reply, "b", carries_install_info); + if (r < 0) + goto fail; + } + + r = sd_bus_message_open_container(reply, 'a', "(sss)"); + if (r < 0) + goto fail; + + for (i = 0; i < n_changes; i++) { + + if (changes[i].type < 0) { + bad = true; + continue; + } + + r = sd_bus_message_append( + reply, "(sss)", + unit_file_change_type_to_string(changes[i].type), + changes[i].path, + changes[i].source); + if (r < 0) + goto fail; + + good = true; + } + + /* If there was a failed change, and no successful change, then return the first failure as proper method call + * error. */ + if (bad && !good) + return install_error(error, 0, changes, n_changes); + + r = sd_bus_message_close_container(reply); + if (r < 0) + goto fail; + + unit_file_changes_free(changes, n_changes); + return sd_bus_send(NULL, reply, NULL); + +fail: + unit_file_changes_free(changes, n_changes); + return r; +} + +static int method_enable_unit_files_generic( + sd_bus_message *message, + Manager *m, + int (*call)(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, size_t *n_changes), + bool carries_install_info, + sd_bus_error *error) { + + _cleanup_strv_free_ char **l = NULL; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + UnitFileFlags flags; + int runtime, force, r; + + assert(message); + assert(m); + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "bb", &runtime, &force); + if (r < 0) + return r; + + flags = unit_file_bools_to_flags(runtime, force); + + r = bus_verify_manage_unit_files_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = call(m->unit_file_scope, flags, NULL, l, &changes, &n_changes); + if (r < 0) + return install_error(error, r, changes, n_changes); + + return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes, error); +} + +static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_enable_unit_files_generic(message, userdata, unit_file_enable, true, error); +} + +static int method_reenable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_enable_unit_files_generic(message, userdata, unit_file_reenable, true, error); +} + +static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_enable_unit_files_generic(message, userdata, unit_file_link, false, error); +} + +static int unit_file_preset_without_mode(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, size_t *n_changes) { + return unit_file_preset(scope, flags, root_dir, files, UNIT_FILE_PRESET_FULL, changes, n_changes); +} + +static int method_preset_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_enable_unit_files_generic(message, userdata, unit_file_preset_without_mode, true, error); +} + +static int method_mask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_enable_unit_files_generic(message, userdata, unit_file_mask, false, error); +} + +static int method_preset_unit_files_with_mode(sd_bus_message *message, void *userdata, sd_bus_error *error) { + + _cleanup_strv_free_ char **l = NULL; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + Manager *m = userdata; + UnitFilePresetMode mm; + int runtime, force, r; + UnitFileFlags flags; + const char *mode; + + assert(message); + assert(m); + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force); + if (r < 0) + return r; + + flags = unit_file_bools_to_flags(runtime, force); + + if (isempty(mode)) + mm = UNIT_FILE_PRESET_FULL; + else { + mm = unit_file_preset_mode_from_string(mode); + if (mm < 0) + return -EINVAL; + } + + r = bus_verify_manage_unit_files_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = unit_file_preset(m->unit_file_scope, flags, NULL, l, mm, &changes, &n_changes); + if (r < 0) + return install_error(error, r, changes, n_changes); + + return reply_unit_file_changes_and_free(m, message, r, changes, n_changes, error); +} + +static int method_disable_unit_files_generic( + sd_bus_message *message, + Manager *m, + int (*call)(UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char *files[], UnitFileChange **changes, size_t *n_changes), + sd_bus_error *error) { + + _cleanup_strv_free_ char **l = NULL; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + int r, runtime; + + assert(message); + assert(m); + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "b", &runtime); + if (r < 0) + return r; + + r = bus_verify_manage_unit_files_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = call(m->unit_file_scope, runtime ? UNIT_FILE_RUNTIME : 0, NULL, l, &changes, &n_changes); + if (r < 0) + return install_error(error, r, changes, n_changes); + + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); +} + +static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_disable_unit_files_generic(message, userdata, unit_file_disable, error); +} + +static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_disable_unit_files_generic(message, userdata, unit_file_unmask, error); +} + +static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + r = bus_verify_manage_unit_files_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = unit_file_revert(m->unit_file_scope, NULL, l, &changes, &n_changes); + if (r < 0) + return install_error(error, r, changes, n_changes); + + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); +} + +static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) { + UnitFileChange *changes = NULL; + size_t n_changes = 0; + Manager *m = userdata; + const char *name; + int force, r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "enable", error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "sb", &name, &force); + if (r < 0) + return r; + + r = bus_verify_manage_unit_files_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = unit_file_set_default(m->unit_file_scope, force ? UNIT_FILE_FORCE : 0, NULL, name, &changes, &n_changes); + if (r < 0) + return install_error(error, r, changes, n_changes); + + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); +} + +static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + UnitFileChange *changes = NULL; + size_t n_changes = 0; + Manager *m = userdata; + UnitFilePresetMode mm; + const char *mode; + UnitFileFlags flags; + int force, runtime, r; + + assert(message); + assert(m); + + r = mac_selinux_access_check(message, "enable", error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force); + if (r < 0) + return r; + + flags = unit_file_bools_to_flags(runtime, force); + + if (isempty(mode)) + mm = UNIT_FILE_PRESET_FULL; + else { + mm = unit_file_preset_mode_from_string(mode); + if (mm < 0) + return -EINVAL; + } + + r = bus_verify_manage_unit_files_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = unit_file_preset_all(m->unit_file_scope, flags, NULL, mm, &changes, &n_changes); + if (r < 0) + return install_error(error, r, changes, n_changes); + + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); +} + +static int method_add_dependency_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + int runtime, force, r; + char *target, *type; + UnitDependency dep; + UnitFileFlags flags; + + assert(message); + assert(m); + + r = bus_verify_manage_unit_files_async(m, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "ssbb", &target, &type, &runtime, &force); + if (r < 0) + return r; + + flags = unit_file_bools_to_flags(runtime, force); + + dep = unit_dependency_from_string(type); + if (dep < 0) + return -EINVAL; + + r = unit_file_add_dependency(m->unit_file_scope, flags, NULL, l, target, dep, &changes, &n_changes); + if (r < 0) + return install_error(error, r, changes, n_changes); + + return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error); +} + +static int method_get_unit_file_links(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + UnitFileChange *changes = NULL; + size_t n_changes = 0, i; + UnitFileFlags flags; + const char *name; + char **p; + int runtime, r; + + r = sd_bus_message_read(message, "sb", &name, &runtime); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, SD_BUS_TYPE_ARRAY, "s"); + if (r < 0) + return r; + + p = STRV_MAKE(name); + flags = UNIT_FILE_DRY_RUN | + (runtime ? UNIT_FILE_RUNTIME : 0); + + r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes); + if (r < 0) + return log_error_errno(r, "Failed to get file links for %s: %m", name); + + for (i = 0; i < n_changes; i++) + if (changes[i].type == UNIT_FILE_UNLINK) { + r = sd_bus_message_append(reply, "s", changes[i].path); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_get_job_waiting(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + uint32_t id; + Job *j; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "u", &id); + if (r < 0) + return r; + + j = manager_get_job(m, id); + if (!j) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id); + + return bus_job_method_get_waiting_jobs(message, j, error); +} + +static int method_abandon_scope(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = bus_get_unit_by_name(m, message, name, &u, error); + if (r < 0) + return r; + + if (u->type != UNIT_SCOPE) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit '%s' is not a scope unit, refusing.", name); + + return bus_scope_method_abandon(message, u, error); +} + +const sd_bus_vtable bus_manager_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("Version", "s", property_get_version, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Features", "s", property_get_features, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Architecture", "s", property_get_architecture, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_FIRMWARE]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_LOADER]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_KERNEL]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_USERSPACE]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_SECURITY_START]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_SECURITY_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_GENERATORS_START]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_GENERATORS_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_UNITS_LOAD_START]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_UNITS_LOAD_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("InitRDSecurityStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_SECURITY_START]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("InitRDSecurityFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_SECURITY_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("InitRDGeneratorsStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_GENERATORS_START]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("InitRDGeneratorsFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_GENERATORS_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("InitRDUnitsLoadStartTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_START]), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("InitRDUnitsLoadFinishTimestamp", offsetof(Manager, timestamps[MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_FINISH]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0), + SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0), + SD_BUS_PROPERTY("NNames", "u", property_get_hashmap_size, offsetof(Manager, units), 0), + SD_BUS_PROPERTY("NFailedUnits", "u", property_get_set_size, offsetof(Manager, failed_units), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("NJobs", "u", property_get_hashmap_size, offsetof(Manager, jobs), 0), + SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0), + SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0), + SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0), + SD_BUS_PROPERTY("Environment", "as", property_get_environment, 0, 0), + SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ShowStatus", "b", property_get_show_status, 0, 0), + SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.search_path), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0), + SD_BUS_WRITABLE_PROPERTY("RebootWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, reboot_watchdog), 0), + /* The following item is an obsolete alias */ + SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, reboot_watchdog), SD_BUS_VTABLE_HIDDEN), + SD_BUS_WRITABLE_PROPERTY("KExecWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, kexec_watchdog), 0), + SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0), + SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0), + SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0), + SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0), + SD_BUS_PROPERTY("DefaultTimerAccuracyUSec", "t", bus_property_get_usec, offsetof(Manager, default_timer_accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultTimeoutAbortUSec", "t", property_get_default_timeout_abort_usec, 0, 0), + SD_BUS_PROPERTY("DefaultRestartUSec", "t", bus_property_get_usec, offsetof(Manager, default_restart_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultStartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST), + /* The following two items are obsolete alias */ + SD_BUS_PROPERTY("DefaultStartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("DefaultStartLimitBurst", "u", bus_property_get_unsigned, offsetof(Manager, default_start_limit_burst), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultCPUAccounting", "b", bus_property_get_bool, offsetof(Manager, default_cpu_accounting), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultBlockIOAccounting", "b", bus_property_get_bool, offsetof(Manager, default_blockio_accounting), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultMemoryAccounting", "b", bus_property_get_bool, offsetof(Manager, default_memory_accounting), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultTasksAccounting", "b", bus_property_get_bool, offsetof(Manager, default_tasks_accounting), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitCPU", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitCPUSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitFSIZE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitDATA", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitDATASoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitSTACK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitCORE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitCORESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitRSS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitRSSSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitNOFILE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitAS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitASSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitNPROC", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitLOCKS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitNICE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitNICESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitRTPRIO", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultLimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultTasksMax", "t", bus_property_get_tasks_max, offsetof(Manager, default_tasks_max), 0), + SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultOOMPolicy", "s", bus_property_get_oom_policy, offsetof(Manager, default_oom_policy), SD_BUS_VTABLE_PROPERTY_CONST), + + SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitByInvocationID", "ay", "o", method_get_unit_by_invocation_id, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitByControlGroup", "s", "o", method_get_unit_by_control_group, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("EnqueueUnitJob", "sss", "uososa(uosos)", method_enqueue_unit_job, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CleanUnit", "sas", NULL, method_clean_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RefUnit", "s", NULL, method_ref_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnrefUnit", "s", NULL, method_unref_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitProcesses", "s", "a(sus)", method_get_unit_processes, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("AttachProcessesToUnit", "ssau", NULL, method_attach_processes_to_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("AbandonScope", "s", NULL, method_abandon_scope, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetJobAfter", "u", "a(usssoo)", method_get_job_waiting, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetJobBefore", "u", "a(usssoo)", method_get_job_waiting, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListUnitsFiltered", "as", "a(ssssssouso)", method_list_units_filtered, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListUnitsByPatterns", "asas", "a(ssssssouso)", method_list_units_by_patterns, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListUnitsByNames", "as", "a(ssssssouso)", method_list_units_by_names, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("DumpByFileDescriptor", NULL, "h", method_dump_by_fd, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_HIDDEN), + SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_HIDDEN), + SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0), + SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), + SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), + SD_BUS_METHOD("Halt", NULL, NULL, method_halt, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), + SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), + SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), + SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListUnitFilesByPatterns", "asas", "a(ss)", method_list_unit_files_by_patterns, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RevertUnitFiles", "as", "a(sss)", method_revert_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitFileLinks", "sb", "as", method_get_unit_file_links, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LookupDynamicUserByName", "s", "u", method_lookup_dynamic_user_by_name, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LookupDynamicUserByUID", "u", "s", method_lookup_dynamic_user_by_uid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetDynamicUsers", NULL, "a(us)", method_get_dynamic_users, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_SIGNAL("UnitNew", "so", 0), + SD_BUS_SIGNAL("UnitRemoved", "so", 0), + SD_BUS_SIGNAL("JobNew", "uos", 0), + SD_BUS_SIGNAL("JobRemoved", "uoss", 0), + SD_BUS_SIGNAL("StartupFinished", "tttttt", 0), + SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0), + SD_BUS_SIGNAL("Reloading", "b", 0), + + SD_BUS_VTABLE_END +}; + +static int send_finished(sd_bus *bus, void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL; + usec_t *times = userdata; + int r; + + assert(bus); + assert(times); + + r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished"); + if (r < 0) + return r; + + r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]); + if (r < 0) + return r; + + return sd_bus_send(bus, message, NULL); +} + +void bus_manager_send_finished( + Manager *m, + usec_t firmware_usec, + usec_t loader_usec, + usec_t kernel_usec, + usec_t initrd_usec, + usec_t userspace_usec, + usec_t total_usec) { + + int r; + + assert(m); + + r = bus_foreach_bus( + m, + NULL, + send_finished, + (usec_t[6]) { + firmware_usec, + loader_usec, + kernel_usec, + initrd_usec, + userspace_usec, + total_usec + }); + if (r < 0) + log_debug_errno(r, "Failed to send finished signal: %m"); +} + +static int send_reloading(sd_bus *bus, void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL; + int r; + + assert(bus); + + r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading"); + if (r < 0) + return r; + + r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata)); + if (r < 0) + return r; + + return sd_bus_send(bus, message, NULL); +} + +void bus_manager_send_reloading(Manager *m, bool active) { + int r; + + assert(m); + + r = bus_foreach_bus(m, NULL, send_reloading, INT_TO_PTR(active)); + if (r < 0) + log_debug_errno(r, "Failed to send reloading signal: %m"); +} + +static int send_changed_signal(sd_bus *bus, void *userdata) { + assert(bus); + + return sd_bus_emit_properties_changed_strv(bus, + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + NULL); +} + +void bus_manager_send_change_signal(Manager *m) { + int r; + + assert(m); + + r = bus_foreach_bus(m, NULL, send_changed_signal, NULL); + if (r < 0) + log_debug_errno(r, "Failed to send manager change signal: %m"); +} diff --git a/src/core/dbus-manager.h b/src/core/dbus-manager.h new file mode 100644 index 00000000..10aa2ecc --- /dev/null +++ b/src/core/dbus-manager.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus-vtable.h" + +#include "manager.h" + +extern const sd_bus_vtable bus_manager_vtable[]; + +void bus_manager_send_finished(Manager *m, usec_t firmware_usec, usec_t loader_usec, usec_t kernel_usec, usec_t initrd_usec, usec_t userspace_usec, usec_t total_usec); +void bus_manager_send_reloading(Manager *m, bool active); +void bus_manager_send_change_signal(Manager *m); + +int verify_run_space_and_log(const char *message); + +int bus_property_get_oom_policy(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c new file mode 100644 index 00000000..b6d61627 --- /dev/null +++ b/src/core/dbus-mount.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-util.h" +#include "dbus-cgroup.h" +#include "dbus-execute.h" +#include "dbus-kill.h" +#include "dbus-mount.h" +#include "dbus-util.h" +#include "mount.h" +#include "string-util.h" +#include "unit.h" + +static const char *mount_get_what(const Mount *m) { + if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.what) + return m->parameters_proc_self_mountinfo.what; + if (m->from_fragment && m->parameters_fragment.what) + return m->parameters_fragment.what; + return NULL; +} + +static const char *mount_get_options(const Mount *m) { + if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.options) + return m->parameters_proc_self_mountinfo.options; + if (m->from_fragment && m->parameters_fragment.options) + return m->parameters_fragment.options; + return NULL; +} + +static const char *mount_get_fstype(const Mount *m) { + if (m->from_proc_self_mountinfo && m->parameters_proc_self_mountinfo.fstype) + return m->parameters_proc_self_mountinfo.fstype; + else if (m->from_fragment && m->parameters_fragment.fstype) + return m->parameters_fragment.fstype; + return NULL; +} + +static BUS_DEFINE_PROPERTY_GET(property_get_what, "s", Mount, mount_get_what); +static BUS_DEFINE_PROPERTY_GET(property_get_options, "s", Mount, mount_get_options); +static BUS_DEFINE_PROPERTY_GET(property_get_type, "s", Mount, mount_get_fstype); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, mount_result, MountResult); + +const sd_bus_vtable bus_mount_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Where", "s", NULL, offsetof(Mount, where), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("What", "s", property_get_what, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Options","s", property_get_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Type", "s", property_get_type, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Mount, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Mount, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Mount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SloppyOptions", "b", bus_property_get_bool, offsetof(Mount, sloppy_options), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LazyUnmount", "b", bus_property_get_bool, offsetof(Mount, lazy_unmount), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ForceUnmount", "b", bus_property_get_bool, offsetof(Mount, force_unmount), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_EXEC_COMMAND_VTABLE("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_VTABLE("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_VTABLE("ExecRemount", offsetof(Mount, exec_command[MOUNT_EXEC_REMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_VTABLE_END +}; + +static int bus_mount_set_transient_property( + Mount *m, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Unit *u = UNIT(m); + + assert(m); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "Where")) + return bus_set_transient_path(u, name, &m->where, message, flags, error); + + if (streq(name, "What")) + return bus_set_transient_string(u, name, &m->parameters_fragment.what, message, flags, error); + + if (streq(name, "Options")) + return bus_set_transient_string(u, name, &m->parameters_fragment.options, message, flags, error); + + if (streq(name, "Type")) + return bus_set_transient_string(u, name, &m->parameters_fragment.fstype, message, flags, error); + + if (streq(name, "TimeoutUSec")) + return bus_set_transient_usec_fix_0(u, name, &m->timeout_usec, message, flags, error); + + if (streq(name, "DirectoryMode")) + return bus_set_transient_mode_t(u, name, &m->directory_mode, message, flags, error); + + if (streq(name, "SloppyOptions")) + return bus_set_transient_bool(u, name, &m->sloppy_options, message, flags, error); + + if (streq(name, "LazyUnmount")) + return bus_set_transient_bool(u, name, &m->lazy_unmount, message, flags, error); + + if (streq(name, "ForceUnmount")) + return bus_set_transient_bool(u, name, &m->force_unmount, message, flags, error); + + return 0; +} + +int bus_mount_set_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Mount *m = MOUNT(u); + int r; + + assert(m); + assert(name); + assert(message); + + r = bus_cgroup_set_property(u, &m->cgroup_context, name, message, flags, error); + if (r != 0) + return r; + + if (u->transient && u->load_state == UNIT_STUB) { + /* This is a transient unit, let's load a little more */ + + r = bus_mount_set_transient_property(m, name, message, flags, error); + if (r != 0) + return r; + + r = bus_exec_context_set_transient_property(u, &m->exec_context, name, message, flags, error); + if (r != 0) + return r; + + r = bus_kill_context_set_transient_property(u, &m->kill_context, name, message, flags, error); + if (r != 0) + return r; + } + + return 0; +} + +int bus_mount_commit_properties(Unit *u) { + assert(u); + + unit_invalidate_cgroup_members_masks(u); + unit_realize_cgroup(u); + + return 0; +} diff --git a/src/core/dbus-mount.h b/src/core/dbus-mount.h new file mode 100644 index 00000000..f7112a9f --- /dev/null +++ b/src/core/dbus-mount.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" + +extern const sd_bus_vtable bus_mount_vtable[]; + +int bus_mount_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_mount_commit_properties(Unit *u); diff --git a/src/core/dbus-path.c b/src/core/dbus-path.c new file mode 100644 index 00000000..1a97d624 --- /dev/null +++ b/src/core/dbus-path.c @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-util.h" +#include "dbus-path.h" +#include "dbus-util.h" +#include "list.h" +#include "path.h" +#include "path-util.h" +#include "string-util.h" +#include "unit.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, path_result, PathResult); + +static int property_get_paths( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Path *p = userdata; + PathSpec *k; + int r; + + assert(bus); + assert(reply); + assert(p); + + r = sd_bus_message_open_container(reply, 'a', "(ss)"); + if (r < 0) + return r; + + LIST_FOREACH(spec, k, p->specs) { + r = sd_bus_message_append(reply, "(ss)", path_type_to_string(k->type), k->path); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +const sd_bus_vtable bus_path_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Unit", "s", bus_property_get_triggered_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Paths", "a(ss)", property_get_paths, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MakeDirectory", "b", bus_property_get_bool, offsetof(Path, make_directory), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Path, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Path, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_VTABLE_END +}; + +static int bus_path_set_transient_property( + Path *p, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Unit *u = UNIT(p); + int r; + + assert(p); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "MakeDirectory")) + return bus_set_transient_bool(u, name, &p->make_directory, message, flags, error); + + if (streq(name, "DirectoryMode")) + return bus_set_transient_mode_t(u, name, &p->directory_mode, message, flags, error); + + if (streq(name, "Paths")) { + const char *type_name, *path; + bool empty = true; + + r = sd_bus_message_enter_container(message, 'a', "(ss)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(ss)", &type_name, &path)) > 0) { + PathType t; + + t = path_type_from_string(type_name); + if (t < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown path type: %s", type_name); + + if (isempty(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in %s is empty", type_name); + + if (!path_is_absolute(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in %s is not absolute: %s", type_name, path); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *k; + PathSpec *s; + + k = strdup(path); + if (!k) + return -ENOMEM; + + path_simplify(k, false); + + s = new0(PathSpec, 1); + if (!s) + return -ENOMEM; + + s->unit = u; + s->path = TAKE_PTR(k); + s->type = t; + s->inotify_fd = -1; + + LIST_PREPEND(spec, p->specs, s); + + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", type_name, path); + } + + empty = false; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) { + path_free_specs(p); + unit_write_settingf(u, flags, name, "PathExists="); + } + + return 1; + } + + return 0; +} + +int bus_path_set_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags mode, + sd_bus_error *error) { + + Path *p = PATH(u); + + assert(p); + assert(name); + assert(message); + + if (u->transient && u->load_state == UNIT_STUB) + return bus_path_set_transient_property(p, name, message, mode, error); + + return 0; +} diff --git a/src/core/dbus-path.h b/src/core/dbus-path.h new file mode 100644 index 00000000..ad42b236 --- /dev/null +++ b/src/core/dbus-path.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" + +extern const sd_bus_vtable bus_path_vtable[]; + +int bus_path_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error); diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c new file mode 100644 index 00000000..84d91dcf --- /dev/null +++ b/src/core/dbus-scope.c @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-internal.h" +#include "bus-util.h" +#include "dbus-cgroup.h" +#include "dbus-kill.h" +#include "dbus-scope.h" +#include "dbus-unit.h" +#include "dbus-util.h" +#include "dbus.h" +#include "scope.h" +#include "selinux-access.h" +#include "unit.h" + +int bus_scope_method_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Scope *s = userdata; + int r; + + assert(message); + assert(s); + + r = mac_selinux_unit_access_check(UNIT(s), message, "stop", error); + if (r < 0) + return r; + + r = bus_verify_manage_units_async(UNIT(s)->manager, message, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = scope_abandon(s); + if (r == -ESTALE) + return sd_bus_error_setf(error, BUS_ERROR_SCOPE_NOT_RUNNING, "Scope %s is not running, cannot abandon.", UNIT(s)->id); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, scope_result, ScopeResult); + +const sd_bus_vtable bus_scope_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Controller", "s", NULL, offsetof(Scope, controller), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Scope, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_SIGNAL("RequestStop", NULL, 0), + SD_BUS_METHOD("Abandon", NULL, NULL, bus_scope_method_abandon, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END +}; + +static int bus_scope_set_transient_property( + Scope *s, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Unit *u = UNIT(s); + int r; + + assert(s); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "TimeoutStopUSec")) + return bus_set_transient_usec(u, name, &s->timeout_stop_usec, message, flags, error); + + if (streq(name, "RuntimeMaxUSec")) + return bus_set_transient_usec(u, name, &s->runtime_max_usec, message, flags, error); + + if (streq(name, "PIDs")) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + unsigned n = 0; + + r = sd_bus_message_enter_container(message, 'a', "u"); + if (r < 0) + return r; + + for (;;) { + uint32_t upid; + pid_t pid; + + r = sd_bus_message_read(message, "u", &upid); + if (r < 0) + return r; + if (r == 0) + break; + + if (upid == 0) { + if (!creds) { + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + } + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + } else + pid = (uid_t) upid; + + r = unit_pid_attachable(u, pid, error); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = unit_watch_pid(u, pid, false); + if (r < 0 && r != -EEXIST) + return r; + } + + n++; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (n <= 0) + return -EINVAL; + + return 1; + + } else if (streq(name, "Controller")) { + const char *controller; + + /* We can't support direct connections with this, as direct connections know no service or unique name + * concept, but the Controller field stores exactly that. */ + if (sd_bus_message_get_bus(message) != u->manager->api_bus) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Sorry, Controller= logic only supported via the bus."); + + r = sd_bus_message_read(message, "s", &controller); + if (r < 0) + return r; + + if (!isempty(controller) && !service_name_is_valid(controller)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = free_and_strdup(&s->controller, empty_to_null(controller)); + if (r < 0) + return r; + } + + return 1; + } + + return 0; +} + +int bus_scope_set_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Scope *s = SCOPE(u); + int r; + + assert(s); + assert(name); + assert(message); + + r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error); + if (r != 0) + return r; + + if (u->load_state == UNIT_STUB) { + /* While we are created we still accept PIDs */ + + r = bus_scope_set_transient_property(s, name, message, flags, error); + if (r != 0) + return r; + + r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error); + if (r != 0) + return r; + } + + return 0; +} + +int bus_scope_commit_properties(Unit *u) { + assert(u); + + unit_invalidate_cgroup_members_masks(u); + unit_realize_cgroup(u); + + return 0; +} + +int bus_scope_send_request_stop(Scope *s) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *p = NULL; + int r; + + assert(s); + + if (!s->controller) + return 0; + + p = unit_dbus_path(UNIT(s)); + if (!p) + return -ENOMEM; + + r = sd_bus_message_new_signal( + UNIT(s)->manager->api_bus, + &m, + p, + "org.freedesktop.systemd1.Scope", + "RequestStop"); + if (r < 0) + return r; + + return sd_bus_send_to(UNIT(s)->manager->api_bus, m, s->controller, NULL); +} + +static int on_controller_gone(sd_bus_track *track, void *userdata) { + Scope *s = userdata; + + assert(track); + + if (s->controller) { + log_unit_debug(UNIT(s), "Controller %s disappeared from bus.", s->controller); + unit_add_to_dbus_queue(UNIT(s)); + s->controller = mfree(s->controller); + } + + s->controller_track = sd_bus_track_unref(s->controller_track); + + return 0; +} + +int bus_scope_track_controller(Scope *s) { + int r; + + assert(s); + + if (!s->controller || s->controller_track) + return 0; + + r = sd_bus_track_new(UNIT(s)->manager->api_bus, &s->controller_track, on_controller_gone, s); + if (r < 0) + return r; + + r = sd_bus_track_add_name(s->controller_track, s->controller); + if (r < 0) { + s->controller_track = sd_bus_track_unref(s->controller_track); + return r; + } + + return 0; +} diff --git a/src/core/dbus-scope.h b/src/core/dbus-scope.h new file mode 100644 index 00000000..702f5589 --- /dev/null +++ b/src/core/dbus-scope.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "scope.h" +#include "unit.h" + +extern const sd_bus_vtable bus_scope_vtable[]; + +int bus_scope_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error); +int bus_scope_commit_properties(Unit *u); + +int bus_scope_send_request_stop(Scope *s); + +int bus_scope_method_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error); + +int bus_scope_track_controller(Scope *s); diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c new file mode 100644 index 00000000..5cf9b218 --- /dev/null +++ b/src/core/dbus-service.c @@ -0,0 +1,454 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "async.h" +#include "bus-internal.h" +#include "bus-util.h" +#include "dbus-cgroup.h" +#include "dbus-execute.h" +#include "dbus-kill.h" +#include "dbus-manager.h" +#include "dbus-service.h" +#include "dbus-util.h" +#include "exit-status.h" +#include "fd-util.h" +#include "fileio.h" +#include "parse-util.h" +#include "path-util.h" +#include "service.h" +#include "signal-util.h" +#include "string-util.h" +#include "strv.h" +#include "unit.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction); +static BUS_DEFINE_PROPERTY_GET(property_get_timeout_abort_usec, "t", Service, service_timeout_abort_usec); + +static int property_get_exit_status_set( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + const ExitStatusSet *status_set = userdata; + unsigned n; + Iterator i; + int r; + + assert(bus); + assert(reply); + assert(status_set); + + r = sd_bus_message_open_container(reply, 'r', "aiai"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "i"); + if (r < 0) + return r; + + BITMAP_FOREACH(n, &status_set->status, i) { + assert(n < 256); + + r = sd_bus_message_append_basic(reply, 'i', &n); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "i"); + if (r < 0) + return r; + + BITMAP_FOREACH(n, &status_set->signal, i) { + const char *str; + + str = signal_to_string(n); + if (!str) + continue; + + r = sd_bus_message_append_basic(reply, 'i', &n); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_message_close_container(reply); +} + +const sd_bus_vtable bus_service_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TimeoutAbortUSec", "t", property_get_timeout_abort_usec, 0, 0), + SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0), + SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* 😷 deprecated */ + SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestartPreventExitStatus", "(aiai)", property_get_exit_status_set, offsetof(Service, restart_prevent_status), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestartForceExitStatus", "(aiai)", property_get_exit_status_set, offsetof(Service, restart_force_status), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SuccessExitStatus", "(aiai)", property_get_exit_status_set, offsetof(Service, success_status), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store), 0), + SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("StatusErrno", "i", bus_property_get_int, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("ReloadResult", "s", property_get_result, offsetof(Service, reload_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("CleanResult", "s", property_get_result, offsetof(Service, clean_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL, offsetof(Service, usb_function_descriptors), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL, offsetof(Service, usb_function_strings), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned, offsetof(Service, n_restarts), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("OOMPolicy", "s", bus_property_get_oom_policy, offsetof(Service, oom_policy), SD_BUS_VTABLE_PROPERTY_CONST), + + BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecCondition", offsetof(Service, exec_command[SERVICE_EXEC_CONDITION]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_EX_COMMAND_LIST_VTABLE("ExecConditionEx", offsetof(Service, exec_command[SERVICE_EXEC_CONDITION]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_EX_COMMAND_LIST_VTABLE("ExecStartPreEx", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_EX_COMMAND_LIST_VTABLE("ExecStartEx", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_EX_COMMAND_LIST_VTABLE("ExecStartPostEx", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_EX_COMMAND_LIST_VTABLE("ExecReloadEx", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_EX_COMMAND_LIST_VTABLE("ExecStopEx", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_EX_COMMAND_LIST_VTABLE("ExecStopPostEx", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + + /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */ + SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_ratelimit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_VTABLE_END +}; + +static int bus_set_transient_exit_status( + Unit *u, + const char *name, + ExitStatusSet *status_set, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + const int32_t *status, *signal; + size_t n_status, n_signal, i; + int r; + + r = sd_bus_message_enter_container(message, 'r', "aiai"); + if (r < 0) + return r; + + r = sd_bus_message_read_array(message, 'i', (const void **) &status, &n_status); + if (r < 0) + return r; + + r = sd_bus_message_read_array(message, 'i', (const void **) &signal, &n_signal); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + n_status /= sizeof(int32_t); + n_signal /= sizeof(int32_t); + + if (n_status == 0 && n_signal == 0 && !UNIT_WRITE_FLAGS_NOOP(flags)) { + exit_status_set_free(status_set); + unit_write_settingf(u, flags, name, "%s=", name); + return 1; + } + + for (i = 0; i < n_status; i++) { + if (status[i] < 0 || status[i] > 255) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid status code in %s: %"PRIi32, name, status[i]); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = bitmap_set(&status_set->status, status[i]); + if (r < 0) + return r; + + unit_write_settingf(u, flags, name, "%s=%"PRIi32, name, status[i]); + } + } + + for (i = 0; i < n_signal; i++) { + const char *str; + + str = signal_to_string((int) signal[i]); + if (!str) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal in %s: %"PRIi32, name, signal[i]); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = bitmap_set(&status_set->signal, signal[i]); + if (r < 0) + return r; + + unit_write_settingf(u, flags, name, "%s=%s", name, str); + } + } + + return 1; +} + +static int bus_set_transient_std_fd( + Unit *u, + const char *name, + int *p, + bool *b, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + int fd, r; + + assert(p); + assert(b); + + r = sd_bus_message_read(message, "h", &fd); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + int copy; + + copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (copy < 0) + return -errno; + + asynchronous_close(*p); + *p = copy; + *b = true; + } + + return 1; +} +static BUS_DEFINE_SET_TRANSIENT_PARSE(notify_access, NotifyAccess, notify_access_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(service_type, ServiceType, service_type_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_restart_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string); +static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, service_name_is_valid); + +static int bus_service_set_transient_property( + Service *s, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Unit *u = UNIT(s); + ServiceExecCommand ci; + int r; + + assert(s); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "PermissionsStartOnly")) + return bus_set_transient_bool(u, name, &s->permissions_start_only, message, flags, error); + + if (streq(name, "RootDirectoryStartOnly")) + return bus_set_transient_bool(u, name, &s->root_directory_start_only, message, flags, error); + + if (streq(name, "RemainAfterExit")) + return bus_set_transient_bool(u, name, &s->remain_after_exit, message, flags, error); + + if (streq(name, "GuessMainPID")) + return bus_set_transient_bool(u, name, &s->guess_main_pid, message, flags, error); + + if (streq(name, "Type")) + return bus_set_transient_service_type(u, name, &s->type, message, flags, error); + + if (streq(name, "OOMPolicy")) + return bus_set_transient_oom_policy(u, name, &s->oom_policy, message, flags, error); + + if (streq(name, "RestartUSec")) + return bus_set_transient_usec(u, name, &s->restart_usec, message, flags, error); + + if (streq(name, "TimeoutStartUSec")) { + r = bus_set_transient_usec(u, name, &s->timeout_start_usec, message, flags, error); + if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags)) + s->start_timeout_defined = true; + + return r; + } + + if (streq(name, "TimeoutStopUSec")) + return bus_set_transient_usec(u, name, &s->timeout_stop_usec, message, flags, error); + + if (streq(name, "TimeoutAbortUSec")) { + r = bus_set_transient_usec(u, name, &s->timeout_abort_usec, message, flags, error); + if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags)) + s->timeout_abort_set = true; + return r; + } + + if (streq(name, "RuntimeMaxUSec")) + return bus_set_transient_usec(u, name, &s->runtime_max_usec, message, flags, error); + + if (streq(name, "WatchdogUSec")) + return bus_set_transient_usec(u, name, &s->watchdog_usec, message, flags, error); + + if (streq(name, "FileDescriptorStoreMax")) + return bus_set_transient_unsigned(u, name, &s->n_fd_store_max, message, flags, error); + + if (streq(name, "NotifyAccess")) + return bus_set_transient_notify_access(u, name, &s->notify_access, message, flags, error); + + if (streq(name, "PIDFile")) { + _cleanup_free_ char *n = NULL; + const char *v, *e; + + r = sd_bus_message_read(message, "s", &v); + if (r < 0) + return r; + + if (!isempty(v)) { + n = path_make_absolute(v, u->manager->prefix[EXEC_DIRECTORY_RUNTIME]); + if (!n) + return -ENOMEM; + + path_simplify(n, true); + + if (!path_is_normalized(n)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PIDFile= path '%s' is not valid", n); + + e = path_startswith(n, "/var/run/"); + if (e) { + char *z; + + z = path_join("/run", e); + if (!z) + return log_oom(); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) + log_unit_notice(u, "Transient unit's PIDFile= property references path below legacy directory /var/run, updating %s → %s; please update client accordingly.", n, z); + + free_and_replace(n, z); + } + } + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + free_and_replace(s->pid_file, n); + unit_write_settingf(u, flags, name, "%s=%s", name, strempty(s->pid_file)); + } + + return 1; + } + + if (streq(name, "USBFunctionDescriptors")) + return bus_set_transient_path(u, name, &s->usb_function_descriptors, message, flags, error); + + if (streq(name, "USBFunctionStrings")) + return bus_set_transient_path(u, name, &s->usb_function_strings, message, flags, error); + + if (streq(name, "BusName")) + return bus_set_transient_bus_name(u, name, &s->bus_name, message, flags, error); + + if (streq(name, "Restart")) + return bus_set_transient_service_restart(u, name, &s->restart, message, flags, error); + + if (streq(name, "RestartPreventExitStatus")) + return bus_set_transient_exit_status(u, name, &s->restart_prevent_status, message, flags, error); + + if (streq(name, "RestartForceExitStatus")) + return bus_set_transient_exit_status(u, name, &s->restart_force_status, message, flags, error); + + if (streq(name, "SuccessExitStatus")) + return bus_set_transient_exit_status(u, name, &s->success_status, message, flags, error); + + ci = service_exec_command_from_string(name); + ci = (ci >= 0) ? ci : service_exec_ex_command_from_string(name); + if (ci >= 0) + return bus_set_transient_exec_command(u, name, &s->exec_command[ci], message, flags, error); + + if (streq(name, "StandardInputFileDescriptor")) + return bus_set_transient_std_fd(u, name, &s->stdin_fd, &s->exec_context.stdio_as_fds, message, flags, error); + + if (streq(name, "StandardOutputFileDescriptor")) + return bus_set_transient_std_fd(u, name, &s->stdout_fd, &s->exec_context.stdio_as_fds, message, flags, error); + + if (streq(name, "StandardErrorFileDescriptor")) + return bus_set_transient_std_fd(u, name, &s->stderr_fd, &s->exec_context.stdio_as_fds, message, flags, error); + + return 0; +} + +int bus_service_set_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Service *s = SERVICE(u); + int r; + + assert(s); + assert(name); + assert(message); + + r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error); + if (r != 0) + return r; + + if (u->transient && u->load_state == UNIT_STUB) { + /* This is a transient unit, let's load a little more */ + + r = bus_service_set_transient_property(s, name, message, flags, error); + if (r != 0) + return r; + + r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, flags, error); + if (r != 0) + return r; + + r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error); + if (r != 0) + return r; + } + + return 0; +} + +int bus_service_commit_properties(Unit *u) { + assert(u); + + unit_invalidate_cgroup_members_masks(u); + unit_realize_cgroup(u); + + return 0; +} diff --git a/src/core/dbus-service.h b/src/core/dbus-service.h new file mode 100644 index 00000000..22d2b887 --- /dev/null +++ b/src/core/dbus-service.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" + +extern const sd_bus_vtable bus_service_vtable[]; + +int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error); +int bus_service_commit_properties(Unit *u); diff --git a/src/core/dbus-slice.c b/src/core/dbus-slice.c new file mode 100644 index 00000000..effd5fa5 --- /dev/null +++ b/src/core/dbus-slice.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "dbus-cgroup.h" +#include "dbus-slice.h" +#include "slice.h" +#include "unit.h" + +const sd_bus_vtable bus_slice_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_VTABLE_END +}; + +int bus_slice_set_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Slice *s = SLICE(u); + + assert(name); + assert(u); + + return bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error); +} + +int bus_slice_commit_properties(Unit *u) { + assert(u); + + unit_invalidate_cgroup_members_masks(u); + unit_realize_cgroup(u); + + return 0; +} diff --git a/src/core/dbus-slice.h b/src/core/dbus-slice.h new file mode 100644 index 00000000..88cc48c8 --- /dev/null +++ b/src/core/dbus-slice.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" + +extern const sd_bus_vtable bus_slice_vtable[]; + +int bus_slice_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_slice_commit_properties(Unit *u); diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c new file mode 100644 index 00000000..25d3d713 --- /dev/null +++ b/src/core/dbus-socket.c @@ -0,0 +1,471 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-util.h" +#include "dbus-cgroup.h" +#include "dbus-execute.h" +#include "dbus-kill.h" +#include "dbus-socket.h" +#include "dbus-util.h" +#include "fd-util.h" +#include "ip-protocol-list.h" +#include "parse-util.h" +#include "path-util.h" +#include "socket.h" +#include "socket-util.h" +#include "string-util.h" +#include "unit.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); +static BUS_DEFINE_PROPERTY_GET(property_get_fdname, "s", Socket, socket_fdname); + +static int property_get_listen( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Socket *s = SOCKET(userdata); + SocketPort *p; + int r; + + assert(bus); + assert(reply); + assert(s); + + r = sd_bus_message_open_container(reply, 'a', "(ss)"); + if (r < 0) + return r; + + LIST_FOREACH(port, p, s->ports) { + _cleanup_free_ char *address = NULL; + const char *a; + + switch (p->type) { + case SOCKET_SOCKET: { + r = socket_address_print(&p->address, &address); + if (r) + return r; + + a = address; + break; + } + + case SOCKET_SPECIAL: + case SOCKET_MQUEUE: + case SOCKET_FIFO: + case SOCKET_USB_FUNCTION: + a = p->path; + break; + + default: + assert_not_reached("Unknown socket type"); + } + + r = sd_bus_message_append(reply, "(ss)", socket_port_type_to_string(p), a); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +const sd_bus_vtable bus_socket_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("BindIPv6Only", "s", property_get_bind_ipv6_only, offsetof(Socket, bind_ipv6_only), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Backlog", "u", bus_property_get_unsigned, offsetof(Socket, backlog), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Socket, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("BindToDevice", "s", NULL, offsetof(Socket, bind_to_device), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SocketUser", "s", NULL, offsetof(Socket, user), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SocketGroup", "s", NULL, offsetof(Socket, group), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SocketMode", "u", bus_property_get_mode, offsetof(Socket, socket_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Socket, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Accept", "b", bus_property_get_bool, offsetof(Socket, accept), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Writable", "b", bus_property_get_bool, offsetof(Socket, writable), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KeepAlive", "b", bus_property_get_bool, offsetof(Socket, keep_alive), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KeepAliveTimeUSec", "t", bus_property_get_usec, offsetof(Socket, keep_alive_time), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KeepAliveIntervalUSec", "t", bus_property_get_usec, offsetof(Socket, keep_alive_interval), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KeepAliveProbes", "u", bus_property_get_unsigned, offsetof(Socket, keep_alive_cnt), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DeferAcceptUSec" , "t", bus_property_get_usec, offsetof(Socket, defer_accept), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NoDelay", "b", bus_property_get_bool, offsetof(Socket, no_delay), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Priority", "i", bus_property_get_int, offsetof(Socket, priority), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ReceiveBuffer", "t", bus_property_get_size, offsetof(Socket, receive_buffer), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SendBuffer", "t", bus_property_get_size, offsetof(Socket, send_buffer), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IPTOS", "i", bus_property_get_int, offsetof(Socket, ip_tos), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IPTTL", "i", bus_property_get_int, offsetof(Socket, ip_ttl), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PipeSize", "t", bus_property_get_size, offsetof(Socket, pipe_size), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("FreeBind", "b", bus_property_get_bool, offsetof(Socket, free_bind), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Transparent", "b", bus_property_get_bool, offsetof(Socket, transparent), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Broadcast", "b", bus_property_get_bool, offsetof(Socket, broadcast), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PassCredentials", "b", bus_property_get_bool, offsetof(Socket, pass_cred), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PassSecurity", "b", bus_property_get_bool, offsetof(Socket, pass_sec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RemoveOnStop", "b", bus_property_get_bool, offsetof(Socket, remove_on_stop), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Listen", "a(ss)", property_get_listen, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Symlinks", "as", NULL, offsetof(Socket, symlinks), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Mark", "i", bus_property_get_int, offsetof(Socket, mark), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MaxConnections", "u", bus_property_get_unsigned, offsetof(Socket, max_connections), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MaxConnectionsPerSource", "u", bus_property_get_unsigned, offsetof(Socket, max_connections_per_source), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MessageQueueMaxMessages", "x", bus_property_get_long, offsetof(Socket, mq_maxmsg), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MessageQueueMessageSize", "x", bus_property_get_long, offsetof(Socket, mq_msgsize), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TCPCongestion", "s", NULL, offsetof(Socket, tcp_congestion), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ReusePort", "b", bus_property_get_bool, offsetof(Socket, reuse_port), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SmackLabel", "s", NULL, offsetof(Socket, smack), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SmackLabelIPIn", "s", NULL, offsetof(Socket, smack_ip_in), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SmackLabelIPOut", "s", NULL, offsetof(Socket, smack_ip_out), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Socket, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Socket, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("NConnections", "u", bus_property_get_unsigned, offsetof(Socket, n_connections), 0), + SD_BUS_PROPERTY("NAccepted", "u", bus_property_get_unsigned, offsetof(Socket, n_accepted), 0), + SD_BUS_PROPERTY("NRefused", "u", bus_property_get_unsigned, offsetof(Socket, n_refused), 0), + SD_BUS_PROPERTY("FileDescriptorName", "s", property_get_fdname, 0, 0), + SD_BUS_PROPERTY("SocketProtocol", "i", bus_property_get_int, offsetof(Socket, socket_protocol), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TriggerLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Socket, trigger_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TriggerLimitBurst", "u", bus_property_get_unsigned, offsetof(Socket, trigger_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPre", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Socket, exec_command[SOCKET_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_VTABLE_END +}; + +static bool check_size_t_truncation(uint64_t t) { + return (size_t) t == t; +} + +static const char* socket_protocol_to_string(int32_t i) { + if (i == IPPROTO_IP) + return ""; + + if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP)) + return NULL; + + return ip_protocol_to_name(i); +} + +static BUS_DEFINE_SET_TRANSIENT(int, "i", int32_t, int, "%" PRIi32); +static BUS_DEFINE_SET_TRANSIENT(message_queue, "x", int64_t, long, "%" PRIi64); +static BUS_DEFINE_SET_TRANSIENT_IS_VALID(size_t_check_truncation, "t", uint64_t, size_t, "%" PRIu64, check_size_t_truncation); +static BUS_DEFINE_SET_TRANSIENT_PARSE(bind_ipv6_only, SocketAddressBindIPv6Only, socket_address_bind_ipv6_only_or_bool_from_string); +static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(fdname, fdname_is_valid); +static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(ifname, ifname_valid); +static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(ip_tos, "i", int32_t, int, "%" PRIi32, ip_tos_to_string_alloc); +static BUS_DEFINE_SET_TRANSIENT_TO_STRING(socket_protocol, "i", int32_t, int, "%" PRIi32, socket_protocol_to_string); + +static int bus_socket_set_transient_property( + Socket *s, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + SocketExecCommand ci; + Unit *u = UNIT(s); + int r; + + assert(s); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "Accept")) + return bus_set_transient_bool(u, name, &s->accept, message, flags, error); + + if (streq(name, "Writable")) + return bus_set_transient_bool(u, name, &s->writable, message, flags, error); + + if (streq(name, "KeepAlive")) + return bus_set_transient_bool(u, name, &s->keep_alive, message, flags, error); + + if (streq(name, "NoDelay")) + return bus_set_transient_bool(u, name, &s->no_delay, message, flags, error); + + if (streq(name, "FreeBind")) + return bus_set_transient_bool(u, name, &s->free_bind, message, flags, error); + + if (streq(name, "Transparent")) + return bus_set_transient_bool(u, name, &s->transparent, message, flags, error); + + if (streq(name, "Broadcast")) + return bus_set_transient_bool(u, name, &s->broadcast, message, flags, error); + + if (streq(name, "PassCredentials")) + return bus_set_transient_bool(u, name, &s->pass_cred, message, flags, error); + + if (streq(name, "PassSecurity")) + return bus_set_transient_bool(u, name, &s->pass_sec, message, flags, error); + + if (streq(name, "ReusePort")) + return bus_set_transient_bool(u, name, &s->reuse_port, message, flags, error); + + if (streq(name, "RemoveOnStop")) + return bus_set_transient_bool(u, name, &s->remove_on_stop, message, flags, error); + + if (streq(name, "SELinuxContextFromNet")) + return bus_set_transient_bool(u, name, &s->selinux_context_from_net, message, flags, error); + + if (streq(name, "Priority")) + return bus_set_transient_int(u, name, &s->priority, message, flags, error); + + if (streq(name, "IPTTL")) + return bus_set_transient_int(u, name, &s->ip_ttl, message, flags, error); + + if (streq(name, "Mark")) + return bus_set_transient_int(u, name, &s->mark, message, flags, error); + + if (streq(name, "Backlog")) + return bus_set_transient_unsigned(u, name, &s->backlog, message, flags, error); + + if (streq(name, "MaxConnections")) + return bus_set_transient_unsigned(u, name, &s->max_connections, message, flags, error); + + if (streq(name, "MaxConnectionsPerSource")) + return bus_set_transient_unsigned(u, name, &s->max_connections_per_source, message, flags, error); + + if (streq(name, "KeepAliveProbes")) + return bus_set_transient_unsigned(u, name, &s->keep_alive_cnt, message, flags, error); + + if (streq(name, "TriggerLimitBurst")) + return bus_set_transient_unsigned(u, name, &s->trigger_limit.burst, message, flags, error); + + if (streq(name, "SocketMode")) + return bus_set_transient_mode_t(u, name, &s->socket_mode, message, flags, error); + + if (streq(name, "DirectoryMode")) + return bus_set_transient_mode_t(u, name, &s->directory_mode, message, flags, error); + + if (streq(name, "MessageQueueMaxMessages")) + return bus_set_transient_message_queue(u, name, &s->mq_maxmsg, message, flags, error); + + if (streq(name, "MessageQueueMessageSize")) + return bus_set_transient_message_queue(u, name, &s->mq_msgsize, message, flags, error); + + if (streq(name, "TimeoutUSec")) + return bus_set_transient_usec_fix_0(u, name, &s->timeout_usec, message, flags, error); + + if (streq(name, "KeepAliveTimeUSec")) + return bus_set_transient_usec(u, name, &s->keep_alive_time, message, flags, error); + + if (streq(name, "KeepAliveIntervalUSec")) + return bus_set_transient_usec(u, name, &s->keep_alive_interval, message, flags, error); + + if (streq(name, "DeferAcceptUSec")) + return bus_set_transient_usec(u, name, &s->defer_accept, message, flags, error); + + if (streq(name, "TriggerLimitIntervalUSec")) + return bus_set_transient_usec(u, name, &s->trigger_limit.interval, message, flags, error); + + if (streq(name, "SmackLabel")) + return bus_set_transient_string(u, name, &s->smack, message, flags, error); + + if (streq(name, "SmackLabelIPin")) + return bus_set_transient_string(u, name, &s->smack_ip_in, message, flags, error); + + if (streq(name, "SmackLabelIPOut")) + return bus_set_transient_string(u, name, &s->smack_ip_out, message, flags, error); + + if (streq(name, "TCPCongestion")) + return bus_set_transient_string(u, name, &s->tcp_congestion, message, flags, error); + + if (streq(name, "FileDescriptorName")) + return bus_set_transient_fdname(u, name, &s->fdname, message, flags, error); + + if (streq(name, "SocketUser")) + return bus_set_transient_user_compat(u, name, &s->user, message, flags, error); + + if (streq(name, "SocketGroup")) + return bus_set_transient_user_compat(u, name, &s->group, message, flags, error); + + if (streq(name, "BindIPv6Only")) + return bus_set_transient_bind_ipv6_only(u, name, &s->bind_ipv6_only, message, flags, error); + + if (streq(name, "ReceiveBuffer")) + return bus_set_transient_size_t_check_truncation(u, name, &s->receive_buffer, message, flags, error); + + if (streq(name, "SendBuffer")) + return bus_set_transient_size_t_check_truncation(u, name, &s->send_buffer, message, flags, error); + + if (streq(name, "PipeSize")) + return bus_set_transient_size_t_check_truncation(u, name, &s->pipe_size, message, flags, error); + + if (streq(name, "BindToDevice")) + return bus_set_transient_ifname(u, name, &s->bind_to_device, message, flags, error); + + if (streq(name, "IPTOS")) + return bus_set_transient_ip_tos(u, name, &s->ip_tos, message, flags, error); + + if (streq(name, "SocketProtocol")) + return bus_set_transient_socket_protocol(u, name, &s->socket_protocol, message, flags, error); + + ci = socket_exec_command_from_string(name); + if (ci >= 0) + return bus_set_transient_exec_command(u, name, + &s->exec_command[ci], + message, flags, error); + + if (streq(name, "Symlinks")) { + _cleanup_strv_free_ char **l = NULL; + char **p; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + STRV_FOREACH(p, l) { + if (!path_is_absolute(*p)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Symlink path is not absolute: %s", *p); + } + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (strv_isempty(l)) { + s->symlinks = strv_free(s->symlinks); + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=", name); + } else { + _cleanup_free_ char *joined = NULL; + + r = strv_extend_strv(&s->symlinks, l, true); + if (r < 0) + return -ENOMEM; + + joined = strv_join(l, " "); + if (!joined) + return -ENOMEM; + + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, joined); + } + } + + return 1; + + } else if (streq(name, "Listen")) { + const char *t, *a; + bool empty = true; + + r = sd_bus_message_enter_container(message, 'a', "(ss)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(ss)", &t, &a)) > 0) { + _cleanup_free_ SocketPort *p = NULL; + + p = new(SocketPort, 1); + if (!p) + return log_oom(); + + *p = (SocketPort) { + .fd = -1, + .socket = s, + }; + + p->type = socket_port_type_from_string(t); + if (p->type < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown Socket type: %s", t); + + if (p->type != SOCKET_SOCKET) { + if (!path_is_valid(p->path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid socket path: %s", t); + + p->path = strdup(a); + if (!p->path) + return log_oom(); + + path_simplify(p->path, false); + + } else if (streq(t, "Netlink")) { + r = socket_address_parse_netlink(&p->address, a); + if (r < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid netlink address: %s", a); + + } else { + r = socket_address_parse(&p->address, a); + if (r < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address: %s", a); + + p->address.type = socket_address_type_from_string(t); + if (p->address.type < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address type: %s", t); + + if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Address family not supported: %s", a); + } + + empty = false; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + LIST_APPEND(port, s->ports, TAKE_PTR(p)); + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Listen%s=%s", t, a); + } + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) { + socket_free_ports(s); + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "ListenStream="); + } + + return 1; + } + + return 0; +} + +int bus_socket_set_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Socket *s = SOCKET(u); + int r; + + assert(s); + assert(name); + assert(message); + + assert(s); + assert(name); + assert(message); + + r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error); + if (r != 0) + return r; + + if (u->transient && u->load_state == UNIT_STUB) { + /* This is a transient unit, let's load a little more */ + + r = bus_socket_set_transient_property(s, name, message, flags, error); + if (r != 0) + return r; + + r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, flags, error); + if (r != 0) + return r; + + r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error); + if (r != 0) + return r; + } + + return 0; +} + +int bus_socket_commit_properties(Unit *u) { + assert(u); + + unit_invalidate_cgroup_members_masks(u); + unit_realize_cgroup(u); + + return 0; +} diff --git a/src/core/dbus-socket.h b/src/core/dbus-socket.h new file mode 100644 index 00000000..9aa8133d --- /dev/null +++ b/src/core/dbus-socket.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" + +extern const sd_bus_vtable bus_socket_vtable[]; + +int bus_socket_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_socket_commit_properties(Unit *u); diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c new file mode 100644 index 00000000..353fa201 --- /dev/null +++ b/src/core/dbus-swap.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2010 Maarten Lankhorst +***/ + +#include "bus-util.h" +#include "dbus-cgroup.h" +#include "dbus-execute.h" +#include "dbus-swap.h" +#include "string-util.h" +#include "swap.h" +#include "unit.h" + +static int swap_get_priority(Swap *s) { + if (s->from_proc_swaps) + return s->parameters_proc_swaps.priority; + if (s->from_fragment) + return s->parameters_fragment.priority; + return -1; +} + +static const char *swap_get_options(Swap *s) { + if (s->from_fragment) + return s->parameters_fragment.options; + return NULL; +} + +static BUS_DEFINE_PROPERTY_GET(property_get_priority, "i", Swap, swap_get_priority); +static BUS_DEFINE_PROPERTY_GET(property_get_options, "s", Swap, swap_get_options); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, swap_result, SwapResult); + +const sd_bus_vtable bus_swap_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("What", "s", NULL, offsetof(Swap, what), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Priority", "i", property_get_priority, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Options", "s", property_get_options, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("TimeoutUSec", "t", bus_property_get_usec, offsetof(Swap, timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Swap, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Swap, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_EXEC_COMMAND_VTABLE("ExecActivate", offsetof(Swap, exec_command[SWAP_EXEC_ACTIVATE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_VTABLE("ExecDeactivate", offsetof(Swap, exec_command[SWAP_EXEC_DEACTIVATE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_VTABLE_END +}; + +int bus_swap_set_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Swap *s = SWAP(u); + + assert(s); + assert(name); + assert(message); + + return bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error); +} + +int bus_swap_commit_properties(Unit *u) { + assert(u); + + unit_invalidate_cgroup_members_masks(u); + unit_realize_cgroup(u); + + return 0; +} diff --git a/src/core/dbus-swap.h b/src/core/dbus-swap.h new file mode 100644 index 00000000..b114fe04 --- /dev/null +++ b/src/core/dbus-swap.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2010 Maarten Lankhorst +***/ + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" + +extern const sd_bus_vtable bus_swap_vtable[]; + +int bus_swap_set_property(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_swap_commit_properties(Unit *u); diff --git a/src/core/dbus-target.c b/src/core/dbus-target.c new file mode 100644 index 00000000..ba501136 --- /dev/null +++ b/src/core/dbus-target.c @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "dbus-target.h" +#include "unit.h" + +const sd_bus_vtable bus_target_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_VTABLE_END +}; diff --git a/src/core/dbus-target.h b/src/core/dbus-target.h new file mode 100644 index 00000000..ad02a1db --- /dev/null +++ b/src/core/dbus-target.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus-vtable.h" + +extern const sd_bus_vtable bus_target_vtable[]; diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c new file mode 100644 index 00000000..439c276f --- /dev/null +++ b/src/core/dbus-timer.c @@ -0,0 +1,378 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-util.h" +#include "dbus-timer.h" +#include "dbus-util.h" +#include "strv.h" +#include "timer.h" +#include "unit.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult); + +static int property_get_monotonic_timers( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Timer *t = userdata; + TimerValue *v; + int r; + + assert(bus); + assert(reply); + assert(t); + + r = sd_bus_message_open_container(reply, 'a', "(stt)"); + if (r < 0) + return r; + + LIST_FOREACH(value, v, t->values) { + _cleanup_free_ char *buf = NULL; + const char *s; + size_t l; + + if (v->base == TIMER_CALENDAR) + continue; + + s = timer_base_to_string(v->base); + assert(endswith(s, "Sec")); + + /* s/Sec/USec/ */ + l = strlen(s); + buf = new(char, l+2); + if (!buf) + return -ENOMEM; + + memcpy(buf, s, l-3); + memcpy(buf+l-3, "USec", 5); + + r = sd_bus_message_append(reply, "(stt)", buf, v->value, v->next_elapse); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_calendar_timers( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Timer *t = userdata; + TimerValue *v; + int r; + + assert(bus); + assert(reply); + assert(t); + + r = sd_bus_message_open_container(reply, 'a', "(sst)"); + if (r < 0) + return r; + + LIST_FOREACH(value, v, t->values) { + _cleanup_free_ char *buf = NULL; + + if (v->base != TIMER_CALENDAR) + continue; + + r = calendar_spec_to_string(v->calendar_spec, &buf); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "(sst)", timer_base_to_string(v->base), buf, v->next_elapse); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_next_elapse_monotonic( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Timer *t = userdata; + + assert(bus); + assert(reply); + assert(t); + + return sd_bus_message_append(reply, "t", + (uint64_t) usec_shift_clock(t->next_elapse_monotonic_or_boottime, + TIMER_MONOTONIC_CLOCK(t), CLOCK_MONOTONIC)); +} + +const sd_bus_vtable bus_timer_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Unit", "s", bus_property_get_triggered_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_PROPERTY("OnClockChange", "b", bus_property_get_bool, offsetof(Timer, on_clock_change), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("OnTimezoneChange", "b", bus_property_get_bool, offsetof(Timer, on_timezone_change), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", property_get_next_elapse_monotonic, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_VTABLE_END +}; + +static int timer_add_one_monotonic_spec( + Timer *t, + const char *name, + TimerBase base, + UnitWriteFlags flags, + usec_t usec, + sd_bus_error *error) { + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + char ts[FORMAT_TIMESPAN_MAX]; + TimerValue *v; + + unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name, + "%s=%s", + timer_base_to_string(base), + format_timespan(ts, sizeof ts, usec, USEC_PER_MSEC)); + + v = new(TimerValue, 1); + if (!v) + return -ENOMEM; + + *v = (TimerValue) { + .base = base, + .value = usec, + }; + + LIST_PREPEND(value, t->values, v); + } + + return 1; +} + +static int timer_add_one_calendar_spec( + Timer *t, + const char *name, + TimerBase base, + UnitWriteFlags flags, + const char *str, + sd_bus_error *error) { + + _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL; + int r; + + r = calendar_spec_from_string(str, &c); + if (r == -EINVAL) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid calendar spec"); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name, + "%s=%s", timer_base_to_string(base), str); + + TimerValue *v = new(TimerValue, 1); + if (!v) + return -ENOMEM; + + *v = (TimerValue) { + .base = base, + .calendar_spec = TAKE_PTR(c), + }; + + LIST_PREPEND(value, t->values, v); + } + + return 1; +}; + +static int bus_timer_set_transient_property( + Timer *t, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + Unit *u = UNIT(t); + int r; + + assert(t); + assert(name); + assert(message); + + flags |= UNIT_PRIVATE; + + if (streq(name, "AccuracyUSec")) + return bus_set_transient_usec(u, name, &t->accuracy_usec, message, flags, error); + + if (streq(name, "AccuracySec")) { + log_notice("Client is using obsolete AccuracySec= transient property, please use AccuracyUSec= instead."); + return bus_set_transient_usec(u, "AccuracyUSec", &t->accuracy_usec, message, flags, error); + } + + if (streq(name, "RandomizedDelayUSec")) + return bus_set_transient_usec(u, name, &t->random_usec, message, flags, error); + + if (streq(name, "WakeSystem")) + return bus_set_transient_bool(u, name, &t->wake_system, message, flags, error); + + if (streq(name, "Persistent")) + return bus_set_transient_bool(u, name, &t->persistent, message, flags, error); + + if (streq(name, "RemainAfterElapse")) + return bus_set_transient_bool(u, name, &t->remain_after_elapse, message, flags, error); + + if (streq(name, "OnTimezoneChange")) + return bus_set_transient_bool(u, name, &t->on_timezone_change, message, flags, error); + + if (streq(name, "OnClockChange")) + return bus_set_transient_bool(u, name, &t->on_clock_change, message, flags, error); + + if (streq(name, "TimersMonotonic")) { + const char *base_name; + usec_t usec; + bool empty = true; + + r = sd_bus_message_enter_container(message, 'a', "(st)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(st)", &base_name, &usec)) > 0) { + TimerBase b; + + b = timer_base_from_string(base_name); + if (b < 0 || b == TIMER_CALENDAR) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Invalid timer base: %s", base_name); + + r = timer_add_one_monotonic_spec(t, name, b, flags, usec, error); + if (r < 0) + return r; + + empty = false; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) { + timer_free_values(t); + unit_write_setting(u, flags, name, "OnActiveSec="); + } + + return 1; + + } else if (streq(name, "TimersCalendar")) { + const char *base_name, *str; + bool empty = true; + + r = sd_bus_message_enter_container(message, 'a', "(ss)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(ss)", &base_name, &str)) > 0) { + TimerBase b; + + b = timer_base_from_string(base_name); + if (b != TIMER_CALENDAR) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Invalid timer base: %s", base_name); + + r = timer_add_one_calendar_spec(t, name, b, flags, str, error); + if (r < 0) + return r; + + empty = false; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) { + timer_free_values(t); + unit_write_setting(u, flags, name, "OnCalendar="); + } + + return 1; + + } else if (STR_IN_SET(name, + "OnActiveSec", + "OnBootSec", + "OnStartupSec", + "OnUnitActiveSec", + "OnUnitInactiveSec")) { + + TimerBase b; + usec_t usec; + + log_notice("Client is using obsolete %s= transient property, please use TimersMonotonic= instead.", name); + + b = timer_base_from_string(name); + if (b < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown timer base"); + + r = sd_bus_message_read(message, "t", &usec); + if (r < 0) + return r; + + return timer_add_one_monotonic_spec(t, name, b, flags, usec, error); + + } else if (streq(name, "OnCalendar")) { + + const char *str; + + log_notice("Client is using obsolete %s= transient property, please use TimersCalendar= instead.", name); + + r = sd_bus_message_read(message, "s", &str); + if (r < 0) + return r; + + return timer_add_one_calendar_spec(t, name, TIMER_CALENDAR, flags, str, error); + } + + return 0; +} + +int bus_timer_set_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags mode, + sd_bus_error *error) { + + Timer *t = TIMER(u); + + assert(t); + assert(name); + assert(message); + + if (u->transient && u->load_state == UNIT_STUB) + return bus_timer_set_transient_property(t, name, message, mode, error); + + return 0; +} diff --git a/src/core/dbus-timer.h b/src/core/dbus-timer.h new file mode 100644 index 00000000..bb126b22 --- /dev/null +++ b/src/core/dbus-timer.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" + +extern const sd_bus_vtable bus_timer_vtable[]; + +int bus_timer_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error); diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c new file mode 100644 index 00000000..73d5b2ee --- /dev/null +++ b/src/core/dbus-unit.c @@ -0,0 +1,2280 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bpf-firewall.h" +#include "bus-common-errors.h" +#include "bus-polkit.h" +#include "cgroup-util.h" +#include "condition.h" +#include "dbus-job.h" +#include "dbus-unit.h" +#include "dbus-util.h" +#include "dbus.h" +#include "fd-util.h" +#include "install.h" +#include "locale-util.h" +#include "log.h" +#include "path-util.h" +#include "process-util.h" +#include "selinux-access.h" +#include "signal-util.h" +#include "special.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "web-util.h" + +static bool unit_can_start_refuse_manual(Unit *u) { + return unit_can_start(u) && !u->refuse_manual_start; +} + +static bool unit_can_stop_refuse_manual(Unit *u) { + return unit_can_stop(u) && !u->refuse_manual_stop; +} + +static bool unit_can_isolate_refuse_manual(Unit *u) { + return unit_can_isolate(u) && !u->refuse_manual_start; +} + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction); +static BUS_DEFINE_PROPERTY_GET(property_get_description, "s", Unit, unit_description); +static BUS_DEFINE_PROPERTY_GET2(property_get_active_state, "s", Unit, unit_active_state, unit_active_state_to_string); +static BUS_DEFINE_PROPERTY_GET(property_get_sub_state, "s", Unit, unit_sub_state_to_string); +static BUS_DEFINE_PROPERTY_GET2(property_get_unit_file_state, "s", Unit, unit_get_unit_file_state, unit_file_state_to_string); +static BUS_DEFINE_PROPERTY_GET(property_get_can_reload, "b", Unit, unit_can_reload); +static BUS_DEFINE_PROPERTY_GET(property_get_can_start, "b", Unit, unit_can_start_refuse_manual); +static BUS_DEFINE_PROPERTY_GET(property_get_can_stop, "b", Unit, unit_can_stop_refuse_manual); +static BUS_DEFINE_PROPERTY_GET(property_get_can_isolate, "b", Unit, unit_can_isolate_refuse_manual); +static BUS_DEFINE_PROPERTY_GET(property_get_need_daemon_reload, "b", Unit, unit_need_daemon_reload); +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_empty_strv, "as", 0); + +static int property_get_can_clean( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = userdata; + ExecCleanMask mask; + int r; + + assert(bus); + assert(reply); + + r = unit_can_clean(u, &mask); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { + if (!FLAGS_SET(mask, 1U << t)) + continue; + + r = sd_bus_message_append(reply, "s", exec_resource_type_to_string(t)); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_names( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Set **s = userdata; + Iterator i; + const char *t; + int r; + + assert(bus); + assert(reply); + assert(s); + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + SET_FOREACH(t, *s, i) { + r = sd_bus_message_append(reply, "s", t); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_following( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = userdata, *f; + + assert(bus); + assert(reply); + assert(u); + + f = unit_following(u); + return sd_bus_message_append(reply, "s", f ? f->id : NULL); +} + +static int property_get_dependencies( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Hashmap **h = userdata; + Iterator j; + Unit *u; + void *v; + int r; + + assert(bus); + assert(reply); + assert(h); + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + HASHMAP_FOREACH_KEY(v, u, *h, j) { + r = sd_bus_message_append(reply, "s", u->id); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_requires_mounts_for( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Hashmap **h = userdata; + const char *p; + Iterator j; + void *v; + int r; + + assert(bus); + assert(reply); + assert(h); + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + HASHMAP_FOREACH_KEY(v, p, *h, j) { + r = sd_bus_message_append(reply, "s", p); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_unit_file_preset( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = userdata; + int r; + + assert(bus); + assert(reply); + assert(u); + + r = unit_get_unit_file_preset(u); + + return sd_bus_message_append(reply, "s", + r < 0 ? NULL: + r > 0 ? "enabled" : "disabled"); +} + +static int property_get_job( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *p = NULL; + Job **j = userdata; + + assert(bus); + assert(reply); + assert(j); + + if (!*j) + return sd_bus_message_append(reply, "(uo)", 0, "/"); + + p = job_dbus_path(*j); + if (!p) + return -ENOMEM; + + return sd_bus_message_append(reply, "(uo)", (*j)->id, p); +} + +static int property_get_conditions( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + const char *(*to_string)(ConditionType type) = NULL; + Condition **list = userdata, *c; + int r; + + assert(bus); + assert(reply); + assert(list); + + to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string; + + r = sd_bus_message_open_container(reply, 'a', "(sbbsi)"); + if (r < 0) + return r; + + LIST_FOREACH(conditions, c, *list) { + int tristate; + + tristate = + c->result == CONDITION_UNTESTED ? 0 : + c->result == CONDITION_SUCCEEDED ? 1 : -1; + + r = sd_bus_message_append(reply, "(sbbsi)", + to_string(c->type), + c->trigger, c->negate, + c->parameter, tristate); + if (r < 0) + return r; + + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_load_error( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL; + Unit *u = userdata; + int r; + + assert(bus); + assert(reply); + assert(u); + + r = bus_unit_validate_load_state(u, &e); + if (r < 0) + return sd_bus_message_append(reply, "(ss)", e.name, e.message); + + return sd_bus_message_append(reply, "(ss)", NULL, NULL); +} + +static int bus_verify_manage_units_async_full( + Unit *u, + const char *verb, + int capability, + const char *polkit_message, + bool interactive, + sd_bus_message *call, + sd_bus_error *error) { + + const char *details[9] = { + "unit", u->id, + "verb", verb, + }; + + if (polkit_message) { + details[4] = "polkit.message"; + details[5] = polkit_message; + details[6] = "polkit.gettext_domain"; + details[7] = GETTEXT_PACKAGE; + } + + return bus_verify_polkit_async( + call, + capability, + "org.freedesktop.systemd1.manage-units", + details, + interactive, + UID_INVALID, + &u->manager->polkit_registry, + error); +} + +static const char *const polkit_message_for_job[_JOB_TYPE_MAX] = { + [JOB_START] = N_("Authentication is required to start '$(unit)'."), + [JOB_STOP] = N_("Authentication is required to stop '$(unit)'."), + [JOB_RELOAD] = N_("Authentication is required to reload '$(unit)'."), + [JOB_RESTART] = N_("Authentication is required to restart '$(unit)'."), + [JOB_TRY_RESTART] = N_("Authentication is required to restart '$(unit)'."), +}; + +int bus_unit_method_start_generic( + sd_bus_message *message, + Unit *u, + JobType job_type, + bool reload_if_possible, + sd_bus_error *error) { + + const char *smode, *verb; + JobMode mode; + int r; + + assert(message); + assert(u); + assert(job_type >= 0 && job_type < _JOB_TYPE_MAX); + + r = mac_selinux_unit_access_check( + u, message, + job_type_to_access_method(job_type), + error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &smode); + if (r < 0) + return r; + + mode = job_mode_from_string(smode); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode); + + if (reload_if_possible) + verb = strjoina("reload-or-", job_type_to_string(job_type)); + else + verb = job_type_to_string(job_type); + + r = bus_verify_manage_units_async_full( + u, + verb, + CAP_SYS_ADMIN, + polkit_message_for_job[job_type], + true, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + return bus_unit_queue_job(message, u, job_type, mode, + reload_if_possible ? BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE : 0, error); +} + +static int method_start(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_unit_method_start_generic(message, userdata, JOB_START, false, error); +} + +static int method_stop(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_unit_method_start_generic(message, userdata, JOB_STOP, false, error); +} + +static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_unit_method_start_generic(message, userdata, JOB_RELOAD, false, error); +} + +static int method_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_unit_method_start_generic(message, userdata, JOB_RESTART, false, error); +} + +static int method_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, false, error); +} + +static int method_reload_or_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_unit_method_start_generic(message, userdata, JOB_RESTART, true, error); +} + +static int method_reload_or_try_restart(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_unit_method_start_generic(message, userdata, JOB_TRY_RESTART, true, error); +} + +int bus_unit_method_enqueue_job(sd_bus_message *message, void *userdata, sd_bus_error *error) { + BusUnitQueueFlags flags = BUS_UNIT_QUEUE_VERBOSE_REPLY; + const char *jtype, *smode; + Unit *u = userdata; + JobType type; + JobMode mode; + int r; + + assert(message); + assert(u); + + r = sd_bus_message_read(message, "ss", &jtype, &smode); + if (r < 0) + return r; + + /* Parse the two magic reload types "reload-or-…" manually */ + if (streq(jtype, "reload-or-restart")) { + type = JOB_RESTART; + flags |= BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE; + } else if (streq(jtype, "reload-or-try-restart")) { + type = JOB_TRY_RESTART; + flags |= BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE; + } else { + /* And the rest generically */ + type = job_type_from_string(jtype); + if (type < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job type %s invalid", jtype); + } + + mode = job_mode_from_string(smode); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode); + + r = mac_selinux_unit_access_check( + u, message, + job_type_to_access_method(type), + error); + if (r < 0) + return r; + + r = bus_verify_manage_units_async_full( + u, + jtype, + CAP_SYS_ADMIN, + polkit_message_for_job[type], + true, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + return bus_unit_queue_job(message, u, type, mode, flags, error); +} + +int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + const char *swho; + int32_t signo; + KillWho who; + int r; + + assert(message); + assert(u); + + r = mac_selinux_unit_access_check(u, message, "stop", error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "si", &swho, &signo); + if (r < 0) + return r; + + if (isempty(swho)) + who = KILL_ALL; + else { + who = kill_who_from_string(swho); + if (who < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho); + } + + if (!SIGNAL_VALID(signo)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range."); + + r = bus_verify_manage_units_async_full( + u, + "kill", + CAP_KILL, + N_("Authentication is required to send a UNIX signal to the processes of '$(unit)'."), + true, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = unit_kill(u, who, signo, error); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = mac_selinux_unit_access_check(u, message, "reload", error); + if (r < 0) + return r; + + r = bus_verify_manage_units_async_full( + u, + "reset-failed", + CAP_SYS_ADMIN, + N_("Authentication is required to reset the \"failed\" state of '$(unit)'."), + true, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + unit_reset_failed(u); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + int runtime, r; + + assert(message); + assert(u); + + r = mac_selinux_unit_access_check(u, message, "start", error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "b", &runtime); + if (r < 0) + return r; + + r = bus_verify_manage_units_async_full( + u, + "set-property", + CAP_SYS_ADMIN, + N_("Authentication is required to set properties on '$(unit)'."), + true, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = mac_selinux_unit_access_check(u, message, "start", error); + if (r < 0) + return r; + + r = bus_verify_manage_units_async_full( + u, + "ref", + CAP_SYS_ADMIN, + NULL, + false, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = bus_unit_track_add_sender(u, message); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = bus_unit_track_remove_sender(u, message); + if (r == -EUNATCH) + return sd_bus_error_setf(error, BUS_ERROR_NOT_REFERENCED, "Unit has not been referenced yet."); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error *error) { + ExecCleanMask mask = 0; + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = mac_selinux_unit_access_check(u, message, "stop", error); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(message, 'a', "s"); + if (r < 0) + return r; + + for (;;) { + const char *i; + + r = sd_bus_message_read(message, "s", &i); + if (r < 0) + return r; + if (r == 0) + break; + + if (streq(i, "all")) + mask |= EXEC_CLEAN_ALL; + else { + ExecDirectoryType t; + + t = exec_resource_type_from_string(i); + if (t < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid resource type: %s", i); + + mask |= 1U << t; + } + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + r = bus_verify_manage_units_async_full( + u, + "clean", + CAP_DAC_OVERRIDE, + N_("Authentication is required to delete files and directories associated with '$(unit)'."), + true, + message, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = unit_clean(u, mask); + if (r == -EOPNOTSUPP) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit '%s' does not supporting cleaning.", u->id); + if (r == -EUNATCH) + return sd_bus_error_setf(error, BUS_ERROR_NOTHING_TO_CLEAN, "No matching resources found."); + if (r == -EBUSY) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_BUSY, "Unit is not inactive or has pending job."); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int property_get_refs( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = userdata; + const char *i; + int r; + + assert(bus); + assert(reply); + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + for (i = sd_bus_track_first(u->bus_track); i; i = sd_bus_track_next(u->bus_track)) { + int c, k; + + c = sd_bus_track_count_name(u->bus_track, i); + if (c < 0) + return c; + + /* Add the item multiple times if the ref count for each is above 1 */ + for (k = 0; k < c; k++) { + r = sd_bus_message_append(reply, "s", i); + if (r < 0) + return r; + } + } + + return sd_bus_message_close_container(reply); +} + +const sd_bus_vtable bus_unit_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Names", "as", property_get_names, offsetof(Unit, names), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0), + SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RequisiteOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OF]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RequiresMountsFor", "as", property_get_requires_mounts_for, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0), + SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset, 0, 0), + BUS_PROPERTY_DUAL_TIMESTAMP("StateChangeTimestamp", offsetof(Unit, state_change_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CanClean", "as", property_get_can_clean, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Job", "(uo)", property_get_job, offsetof(Unit, job), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("JobRunningTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_running_timeout), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_emergency_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Perpetual", "b", bus_property_get_bool, offsetof(Unit, perpetual), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_ratelimit.burst), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("FailureActionExitStatus", "i", bus_property_get_int, offsetof(Unit, failure_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SuccessAction", "s", property_get_emergency_action, offsetof(Unit, success_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SuccessActionExitStatus", "i", bus_property_get_int, offsetof(Unit, success_action_exit_status), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Refs", "as", property_get_refs, 0, 0), + + SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Reload", "s", "o", method_reload, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Restart", "s", "o", method_restart, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("EnqueueJob", "ss", "uososa(uosos)", bus_unit_method_enqueue_job, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Clean", "as", NULL, bus_unit_method_clean, SD_BUS_VTABLE_UNPRIVILEGED), + + /* For dependency types we don't support anymore always return an empty array */ + SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_empty_strv, 0, SD_BUS_VTABLE_HIDDEN), + /* Obsolete alias names */ + SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_VTABLE_END +}; + +static int property_get_slice( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = userdata; + + assert(bus); + assert(reply); + assert(u); + + return sd_bus_message_append(reply, "s", unit_slice_name(u)); +} + +static int property_get_current_memory( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + uint64_t sz = (uint64_t) -1; + Unit *u = userdata; + int r; + + assert(bus); + assert(reply); + assert(u); + + r = unit_get_memory_current(u, &sz); + if (r < 0 && r != -ENODATA) + log_unit_warning_errno(u, r, "Failed to get memory.usage_in_bytes attribute: %m"); + + return sd_bus_message_append(reply, "t", sz); +} + +static int property_get_current_tasks( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + uint64_t cn = (uint64_t) -1; + Unit *u = userdata; + int r; + + assert(bus); + assert(reply); + assert(u); + + r = unit_get_tasks_current(u, &cn); + if (r < 0 && r != -ENODATA) + log_unit_warning_errno(u, r, "Failed to get pids.current attribute: %m"); + + return sd_bus_message_append(reply, "t", cn); +} + +static int property_get_cpu_usage( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + nsec_t ns = (nsec_t) -1; + Unit *u = userdata; + int r; + + assert(bus); + assert(reply); + assert(u); + + r = unit_get_cpu_usage(u, &ns); + if (r < 0 && r != -ENODATA) + log_unit_warning_errno(u, r, "Failed to get cpuacct.usage attribute: %m"); + + return sd_bus_message_append(reply, "t", ns); +} + +static int property_get_cpuset_cpus( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = userdata; + _cleanup_(cpu_set_reset) CPUSet cpus = {}; + _cleanup_free_ uint8_t *array = NULL; + size_t allocated; + + assert(bus); + assert(reply); + assert(u); + + (void) unit_get_cpuset(u, &cpus, "cpuset.cpus.effective"); + (void) cpu_set_to_dbus(&cpus, &array, &allocated); + return sd_bus_message_append_array(reply, 'y', array, allocated); +} + +static int property_get_cpuset_mems( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = userdata; + _cleanup_(cpu_set_reset) CPUSet mems = {}; + _cleanup_free_ uint8_t *array = NULL; + size_t allocated; + + assert(bus); + assert(reply); + assert(u); + + (void) unit_get_cpuset(u, &mems, "cpuset.mems.effective"); + (void) cpu_set_to_dbus(&mems, &array, &allocated); + return sd_bus_message_append_array(reply, 'y', array, allocated); +} + +static int property_get_cgroup( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = userdata; + const char *t = NULL; + + assert(bus); + assert(reply); + assert(u); + + /* Three cases: a) u->cgroup_path is NULL, in which case the + * unit has no control group, which we report as the empty + * string. b) u->cgroup_path is the empty string, which + * indicates the root cgroup, which we report as "/". c) all + * other cases we report as-is. */ + + if (u->cgroup_path) + t = empty_to_root(u->cgroup_path); + + return sd_bus_message_append(reply, "s", t); +} + +static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set *pids) { + _cleanup_free_ char *buf = NULL, *cmdline = NULL; + int r; + + assert(reply); + assert(pid > 0); + + r = set_put(pids, PID_TO_PTR(pid)); + if (IN_SET(r, 0, -EEXIST)) + return 0; + if (r < 0) + return r; + + if (!p) { + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf); + if (r == -ESRCH) + return 0; + if (r < 0) + return r; + + p = buf; + } + + (void) get_process_cmdline(pid, SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &cmdline); + + return sd_bus_message_append(reply, + "(sus)", + p, + (uint32_t) pid, + cmdline); +} + +static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) { + _cleanup_closedir_ DIR *d = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(reply); + assert(p); + + r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + for (;;) { + pid_t pid; + + r = cg_read_pid(f, &pid); + if (r < 0) + return r; + if (r == 0) + break; + + if (is_kernel_thread(pid) > 0) + continue; + + r = append_process(reply, p, pid, pids); + if (r < 0) + return r; + } + + r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, p, &d); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *g = NULL, *j = NULL; + + r = cg_read_subgroup(d, &g); + if (r < 0) + return r; + if (r == 0) + break; + + j = path_join(empty_to_root(p), g); + if (!j) + return -ENOMEM; + + r = append_cgroup(reply, j, pids); + if (r < 0) + return r; + } + + return 0; +} + +int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_set_free_ Set *pids = NULL; + Unit *u = userdata; + pid_t pid; + int r; + + assert(message); + + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + + pids = set_new(NULL); + if (!pids) + return -ENOMEM; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(sus)"); + if (r < 0) + return r; + + if (u->cgroup_path) { + r = append_cgroup(reply, u->cgroup_path, pids); + if (r < 0) + return r; + } + + /* The main and control pids might live outside of the cgroup, hence fetch them separately */ + pid = unit_main_pid(u); + if (pid > 0) { + r = append_process(reply, NULL, pid, pids); + if (r < 0) + return r; + } + + pid = unit_control_pid(u); + if (pid > 0) { + r = append_process(reply, NULL, pid, pids); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int property_get_ip_counter( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + static const char *const table[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = { + [CGROUP_IP_INGRESS_BYTES] = "IPIngressBytes", + [CGROUP_IP_EGRESS_BYTES] = "IPEgressBytes", + [CGROUP_IP_INGRESS_PACKETS] = "IPIngressPackets", + [CGROUP_IP_EGRESS_PACKETS] = "IPEgressPackets", + }; + + uint64_t value = UINT64_MAX; + Unit *u = userdata; + ssize_t metric; + + assert(bus); + assert(reply); + assert(property); + assert(u); + + assert_se((metric = string_table_lookup(table, ELEMENTSOF(table), property)) >= 0); + (void) unit_get_ip_accounting(u, metric, &value); + return sd_bus_message_append(reply, "t", value); +} + +static int property_get_io_counter( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + static const char *const table[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = { + [CGROUP_IO_READ_BYTES] = "IOReadBytes", + [CGROUP_IO_WRITE_BYTES] = "IOWriteBytes", + [CGROUP_IO_READ_OPERATIONS] = "IOReadOperations", + [CGROUP_IO_WRITE_OPERATIONS] = "IOWriteOperations", + }; + + uint64_t value = UINT64_MAX; + Unit *u = userdata; + ssize_t metric; + + assert(bus); + assert(reply); + assert(property); + assert(u); + + assert_se((metric = string_table_lookup(table, ELEMENTSOF(table), property)) >= 0); + (void) unit_get_io_accounting(u, metric, false, &value); + return sd_bus_message_append(reply, "t", value); +} + +int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) { + + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + _cleanup_set_free_ Set *pids = NULL; + Unit *u = userdata; + const char *path; + int r; + + assert(message); + + /* This migrates the processes with the specified PIDs into the cgroup of this unit, optionally below a + * specified cgroup path. Obviously this only works for units that actually maintain a cgroup + * representation. If a process is already in the cgroup no operation is executed – in this case the specified + * subcgroup path has no effect! */ + + r = mac_selinux_unit_access_check(u, message, "start", error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &path); + if (r < 0) + return r; + + path = empty_to_null(path); + if (path) { + if (!path_is_absolute(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not absolute: %s", path); + + if (!path_is_normalized(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not normalized: %s", path); + } + + if (!unit_cgroup_delegate(u)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process migration not available on non-delegated units."); + + if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u))) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not active, refusing."); + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(message, 'a', "u"); + if (r < 0) + return r; + for (;;) { + uid_t process_uid, sender_uid; + uint32_t upid; + pid_t pid; + + r = sd_bus_message_read(message, "u", &upid); + if (r < 0) + return r; + if (r == 0) + break; + + if (upid == 0) { + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + } else + pid = (uid_t) upid; + + /* Filter out duplicates */ + if (set_contains(pids, PID_TO_PTR(pid))) + continue; + + /* Check if this process is suitable for attaching to this unit */ + r = unit_pid_attachable(u, pid, error); + if (r < 0) + return r; + + /* Let's query the sender's UID, so that we can make our security decisions */ + r = sd_bus_creds_get_euid(creds, &sender_uid); + if (r < 0) + return r; + + /* Let's validate security: if the sender is root, then all is OK. If the sender is any other unit, + * then the process' UID and the target unit's UID have to match the sender's UID */ + if (sender_uid != 0 && sender_uid != getuid()) { + r = get_process_uid(pid, &process_uid); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to retrieve process UID: %m"); + + if (process_uid != sender_uid) + return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by client's UID. Refusing.", pid); + if (process_uid != u->ref_uid) + return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Process " PID_FMT " not owned by target unit's UID. Refusing.", pid); + } + + if (!pids) { + pids = set_new(NULL); + if (!pids) + return -ENOMEM; + } + + r = set_put(pids, PID_TO_PTR(pid)); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + r = unit_attach_pids_to_cgroup(u, pids, path); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to attach processes to control group: %m"); + + return sd_bus_reply_method_return(message, NULL); +} + +const sd_bus_vtable bus_unit_cgroup_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0), + SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0), + SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0), + SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0), + SD_BUS_PROPERTY("EffectiveCPUs", "ay", property_get_cpuset_cpus, 0, 0), + SD_BUS_PROPERTY("EffectiveMemoryNodes", "ay", property_get_cpuset_mems, 0, 0), + SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0), + SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0), + SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0), + SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter, 0, 0), + SD_BUS_PROPERTY("IPEgressPackets", "t", property_get_ip_counter, 0, 0), + SD_BUS_PROPERTY("IOReadBytes", "t", property_get_io_counter, 0, 0), + SD_BUS_PROPERTY("IOReadOperations", "t", property_get_io_counter, 0, 0), + SD_BUS_PROPERTY("IOWriteBytes", "t", property_get_io_counter, 0, 0), + SD_BUS_PROPERTY("IOWriteOperations", "t", property_get_io_counter, 0, 0), + SD_BUS_METHOD("GetProcesses", NULL, "a(sus)", bus_unit_method_get_processes, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("AttachProcesses", "sau", NULL, bus_unit_method_attach_processes, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END +}; + +static int send_new_signal(sd_bus *bus, void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *p = NULL; + Unit *u = userdata; + int r; + + assert(bus); + assert(u); + + p = unit_dbus_path(u); + if (!p) + return -ENOMEM; + + r = sd_bus_message_new_signal( + bus, + &m, + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "UnitNew"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "so", u->id, p); + if (r < 0) + return r; + + return sd_bus_send(bus, m, NULL); +} + +static int send_changed_signal(sd_bus *bus, void *userdata) { + _cleanup_free_ char *p = NULL; + Unit *u = userdata; + int r; + + assert(bus); + assert(u); + + p = unit_dbus_path(u); + if (!p) + return -ENOMEM; + + /* Send a properties changed signal. First for the specific + * type, then for the generic unit. The clients may rely on + * this order to get atomic behavior if needed. */ + + r = sd_bus_emit_properties_changed_strv( + bus, p, + unit_dbus_interface_from_type(u->type), + NULL); + if (r < 0) + return r; + + return sd_bus_emit_properties_changed_strv( + bus, p, + "org.freedesktop.systemd1.Unit", + NULL); +} + +void bus_unit_send_change_signal(Unit *u) { + int r; + assert(u); + + if (u->in_dbus_queue) { + LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u); + u->in_dbus_queue = false; + } + + if (!u->id) + return; + + r = bus_foreach_bus(u->manager, u->bus_track, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to send unit change signal for %s: %m", u->id); + + u->sent_dbus_new_signal = true; +} + +void bus_unit_send_pending_change_signal(Unit *u, bool including_new) { + + /* Sends out any pending change signals, but only if they really are pending. This call is used when we are + * about to change state in order to force out a PropertiesChanged signal beforehand if there was one pending + * so that clients can follow the full state transition */ + + if (!u->in_dbus_queue) /* If not enqueued, don't bother */ + return; + + if (!u->sent_dbus_new_signal && !including_new) /* If the unit was never announced, don't bother, it's fine if + * the unit appears in the new state right-away (except if the + * caller explicitly asked us to send it anyway) */ + return; + + if (MANAGER_IS_RELOADING(u->manager)) /* Don't generate unnecessary PropertiesChanged signals for the same unit + * when we are reloading. */ + return; + + bus_unit_send_change_signal(u); +} + +static int send_removed_signal(sd_bus *bus, void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *p = NULL; + Unit *u = userdata; + int r; + + assert(bus); + assert(u); + + p = unit_dbus_path(u); + if (!p) + return -ENOMEM; + + r = sd_bus_message_new_signal( + bus, + &m, + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "UnitRemoved"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "so", u->id, p); + if (r < 0) + return r; + + return sd_bus_send(bus, m, NULL); +} + +void bus_unit_send_removed_signal(Unit *u) { + int r; + assert(u); + + if (!u->sent_dbus_new_signal || u->in_dbus_queue) + bus_unit_send_change_signal(u); + + if (!u->id) + return; + + r = bus_foreach_bus(u->manager, u->bus_track, send_removed_signal, u); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to send unit remove signal for %s: %m", u->id); +} + +int bus_unit_queue_job( + sd_bus_message *message, + Unit *u, + JobType type, + JobMode mode, + BusUnitQueueFlags flags, + sd_bus_error *error) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *job_path = NULL, *unit_path = NULL; + _cleanup_(set_freep) Set *affected = NULL; + Iterator i; + Job *j, *a; + int r; + + assert(message); + assert(u); + assert(type >= 0 && type < _JOB_TYPE_MAX); + assert(mode >= 0 && mode < _JOB_MODE_MAX); + + r = mac_selinux_unit_access_check( + u, message, + job_type_to_access_method(type), + error); + if (r < 0) + return r; + + if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) { + if (type == JOB_RESTART) + type = JOB_RELOAD_OR_START; + else if (type == JOB_TRY_RESTART) + type = JOB_TRY_RELOAD; + } + + if (type == JOB_STOP && + IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) && + unit_active_state(u) == UNIT_INACTIVE) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id); + + if ((type == JOB_START && u->refuse_manual_start) || + (type == JOB_STOP && u->refuse_manual_stop) || + (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) || + (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start)) + return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id); + + if (FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY)) { + affected = set_new(NULL); + if (!affected) + return -ENOMEM; + } + + r = manager_add_job(u->manager, type, u, mode, affected, error, &j); + if (r < 0) + return r; + + r = bus_job_track_sender(j, message); + if (r < 0) + return r; + + /* Before we send the method reply, force out the announcement JobNew for this job */ + bus_job_send_pending_change_signal(j, true); + + job_path = job_dbus_path(j); + if (!job_path) + return -ENOMEM; + + /* The classic response is just a job object path */ + if (!FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY)) + return sd_bus_reply_method_return(message, "o", job_path); + + /* In verbose mode respond with the anchor job plus everything that has been affected */ + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + unit_path = unit_dbus_path(j->unit); + if (!unit_path) + return -ENOMEM; + + r = sd_bus_message_append(reply, "uosos", + j->id, job_path, + j->unit->id, unit_path, + job_type_to_string(j->type)); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(uosos)"); + if (r < 0) + return r; + + SET_FOREACH(a, affected, i) { + + if (a->id == j->id) + continue; + + /* Free paths from previous iteration */ + job_path = mfree(job_path); + unit_path = mfree(unit_path); + + job_path = job_dbus_path(a); + if (!job_path) + return -ENOMEM; + + unit_path = unit_dbus_path(a->unit); + if (!unit_path) + return -ENOMEM; + + r = sd_bus_message_append(reply, "(uosos)", + a->id, job_path, + a->unit->id, unit_path, + job_type_to_string(a->type)); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int bus_unit_set_live_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + int r; + + assert(u); + assert(name); + assert(message); + + /* Handles setting properties both "live" (i.e. at any time during runtime), and during creation (for transient + * units that are being created). */ + + if (streq(name, "Description")) { + const char *d; + + r = sd_bus_message_read(message, "s", &d); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = unit_set_description(u, d); + if (r < 0) + return r; + + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Description=%s", d); + } + + return 1; + } + + return 0; +} + +static int bus_set_transient_emergency_action( + Unit *u, + const char *name, + EmergencyAction *p, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + const char *s; + EmergencyAction v; + int r; + bool system; + + assert(p); + + r = sd_bus_message_read(message, "s", &s); + if (r < 0) + return r; + + system = MANAGER_IS_SYSTEM(u->manager); + r = parse_emergency_action(s, system, &v); + if (r < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + r == -EOPNOTSUPP ? "%s setting invalid for manager type: %s" + : "Invalid %s setting: %s", + name, s); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + *p = v; + unit_write_settingf(u, flags, name, + "%s=%s", name, s); + } + + return 1; +} + +static int bus_set_transient_exit_status( + Unit *u, + const char *name, + int *p, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + int32_t k; + int r; + + assert(p); + + r = sd_bus_message_read(message, "i", &k); + if (r < 0) + return r; + + if (k > 255) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Exit status must be in range 0…255 or negative."); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + *p = k < 0 ? -1 : k; + + if (k < 0) + unit_write_settingf(u, flags, name, "%s=", name); + else + unit_write_settingf(u, flags, name, "%s=%i", name, k); + } + + return 1; +} + +static BUS_DEFINE_SET_TRANSIENT_PARSE(collect_mode, CollectMode, collect_mode_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(job_mode, JobMode, job_mode_from_string); + +static int bus_set_transient_conditions( + Unit *u, + const char *name, + Condition **list, + bool is_condition, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + const char *type_name, *param; + int trigger, negate, r; + bool empty = true; + + assert(list); + + r = sd_bus_message_enter_container(message, 'a', "(sbbs)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "(sbbs)", &type_name, &trigger, &negate, ¶m)) > 0) { + ConditionType t; + + t = is_condition ? condition_type_from_string(type_name) : assert_type_from_string(type_name); + if (t < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid condition type: %s", type_name); + + if (t != CONDITION_NULL) { + if (isempty(param)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name); + + if (condition_takes_path(t) && !path_is_absolute(param)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param); + } else + param = NULL; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + Condition *c; + + c = condition_new(t, param, trigger, negate); + if (!c) + return -ENOMEM; + + LIST_PREPEND(conditions, *list, c); + + if (t != CONDITION_NULL) + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, + "%s=%s%s%s", type_name, + trigger ? "|" : "", negate ? "!" : "", param); + else + unit_write_settingf(u, flags, name, + "%s=%s%s", type_name, + trigger ? "|" : "", yes_no(!negate)); + } + + empty = false; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) { + *list = condition_free_list(*list); + unit_write_settingf(u, flags, name, "%sNull=", is_condition ? "Condition" : "Assert"); + } + + return 1; +} + +static int bus_unit_set_transient_property( + Unit *u, + const char *name, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + UnitDependency d = _UNIT_DEPENDENCY_INVALID; + int r; + + assert(u); + assert(name); + assert(message); + + /* Handles settings when transient units are created. This settings cannot be altered anymore after the unit + * has been created. */ + + if (streq(name, "SourcePath")) + return bus_set_transient_path(u, name, &u->source_path, message, flags, error); + + if (streq(name, "StopWhenUnneeded")) + return bus_set_transient_bool(u, name, &u->stop_when_unneeded, message, flags, error); + + if (streq(name, "RefuseManualStart")) + return bus_set_transient_bool(u, name, &u->refuse_manual_start, message, flags, error); + + if (streq(name, "RefuseManualStop")) + return bus_set_transient_bool(u, name, &u->refuse_manual_stop, message, flags, error); + + if (streq(name, "AllowIsolate")) + return bus_set_transient_bool(u, name, &u->allow_isolate, message, flags, error); + + if (streq(name, "DefaultDependencies")) + return bus_set_transient_bool(u, name, &u->default_dependencies, message, flags, error); + + if (streq(name, "OnFailureJobMode")) + return bus_set_transient_job_mode(u, name, &u->on_failure_job_mode, message, flags, error); + + if (streq(name, "IgnoreOnIsolate")) + return bus_set_transient_bool(u, name, &u->ignore_on_isolate, message, flags, error); + + if (streq(name, "JobTimeoutUSec")) { + r = bus_set_transient_usec_fix_0(u, name, &u->job_timeout, message, flags, error); + if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags) && !u->job_running_timeout_set) + u->job_running_timeout = u->job_timeout; + } + + if (streq(name, "JobRunningTimeoutUSec")) { + r = bus_set_transient_usec_fix_0(u, name, &u->job_running_timeout, message, flags, error); + if (r >= 0 && !UNIT_WRITE_FLAGS_NOOP(flags)) + u->job_running_timeout_set = true; + + return r; + } + + if (streq(name, "JobTimeoutAction")) + return bus_set_transient_emergency_action(u, name, &u->job_timeout_action, message, flags, error); + + if (streq(name, "JobTimeoutRebootArgument")) + return bus_set_transient_string(u, name, &u->job_timeout_reboot_arg, message, flags, error); + + if (streq(name, "StartLimitIntervalUSec")) + return bus_set_transient_usec(u, name, &u->start_ratelimit.interval, message, flags, error); + + if (streq(name, "StartLimitBurst")) + return bus_set_transient_unsigned(u, name, &u->start_ratelimit.burst, message, flags, error); + + if (streq(name, "StartLimitAction")) + return bus_set_transient_emergency_action(u, name, &u->start_limit_action, message, flags, error); + + if (streq(name, "FailureAction")) + return bus_set_transient_emergency_action(u, name, &u->failure_action, message, flags, error); + + if (streq(name, "SuccessAction")) + return bus_set_transient_emergency_action(u, name, &u->success_action, message, flags, error); + + if (streq(name, "FailureActionExitStatus")) + return bus_set_transient_exit_status(u, name, &u->failure_action_exit_status, message, flags, error); + + if (streq(name, "SuccessActionExitStatus")) + return bus_set_transient_exit_status(u, name, &u->success_action_exit_status, message, flags, error); + + if (streq(name, "RebootArgument")) + return bus_set_transient_string(u, name, &u->reboot_arg, message, flags, error); + + if (streq(name, "CollectMode")) + return bus_set_transient_collect_mode(u, name, &u->collect_mode, message, flags, error); + + if (streq(name, "Conditions")) + return bus_set_transient_conditions(u, name, &u->conditions, true, message, flags, error); + + if (streq(name, "Asserts")) + return bus_set_transient_conditions(u, name, &u->asserts, false, message, flags, error); + + if (streq(name, "Documentation")) { + _cleanup_strv_free_ char **l = NULL; + char **p; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + STRV_FOREACH(p, l) { + if (!documentation_url_is_valid(*p)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid URL in %s: %s", name, *p); + } + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + if (strv_isempty(l)) { + u->documentation = strv_free(u->documentation); + unit_write_settingf(u, flags, name, "%s=", name); + } else { + strv_extend_strv(&u->documentation, l, false); + + STRV_FOREACH(p, l) + unit_write_settingf(u, flags, name, "%s=%s", name, *p); + } + } + + return 1; + + } else if (streq(name, "Slice")) { + Unit *slice; + const char *s; + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "The slice property is only available for units with control groups."); + if (u->type == UNIT_SLICE) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Slice may not be set for slice units."); + if (unit_has_name(u, SPECIAL_INIT_SCOPE)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set slice for init.scope"); + + r = sd_bus_message_read(message, "s", &s); + if (r < 0) + return r; + + if (!unit_name_is_valid(s, UNIT_NAME_PLAIN)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name '%s'", s); + + /* Note that we do not dispatch the load queue here yet, as we don't want our own transient unit to be + * loaded while we are still setting it up. Or in other words, we use manager_load_unit_prepare() + * instead of manager_load_unit() on purpose, here. */ + r = manager_load_unit_prepare(u->manager, s, NULL, error, &slice); + if (r < 0) + return r; + + if (slice->type != UNIT_SLICE) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = unit_set_slice(u, slice); + if (r < 0) + return r; + + unit_write_settingf(u, flags|UNIT_PRIVATE, name, "Slice=%s", s); + } + + return 1; + + } else if (streq(name, "RequiresMountsFor")) { + _cleanup_strv_free_ char **l = NULL; + char **p; + + r = sd_bus_message_read_strv(message, &l); + if (r < 0) + return r; + + STRV_FOREACH(p, l) { + path_simplify(*p, true); + + if (!path_is_absolute(*p)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not absolute: %s", name, *p); + + if (!path_is_valid(*p)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s has invalid length: %s", name, *p); + + if (!path_is_normalized(*p)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path specified in %s is not normalized: %s", name, *p); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = unit_require_mounts_for(u, *p, UNIT_DEPENDENCY_FILE); + if (r < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to add required mount \"%s\": %m", *p); + + unit_write_settingf(u, flags, name, "%s=%s", name, *p); + } + } + + return 1; + } + + if (streq(name, "RequiresOverridable")) + d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */ + else if (streq(name, "RequisiteOverridable")) + d = UNIT_REQUISITE; /* same here */ + else + d = unit_dependency_from_string(name); + + if (d >= 0) { + const char *other; + + if (!IN_SET(d, + UNIT_REQUIRES, + UNIT_REQUISITE, + UNIT_WANTS, + UNIT_BINDS_TO, + UNIT_PART_OF, + UNIT_CONFLICTS, + UNIT_BEFORE, + UNIT_AFTER, + UNIT_ON_FAILURE, + UNIT_PROPAGATES_RELOAD_TO, + UNIT_RELOAD_PROPAGATED_FROM, + UNIT_JOINS_NAMESPACE_OF)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Dependency type %s may not be created transiently.", unit_dependency_to_string(d)); + + r = sd_bus_message_enter_container(message, 'a', "s"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(message, "s", &other)) > 0) { + if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other); + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *label = NULL; + + r = unit_add_dependency_by_name(u, d, other, true, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + + label = strjoin(name, "-", other); + if (!label) + return -ENOMEM; + + unit_write_settingf(u, flags, label, "%s=%s", unit_dependency_to_string(d), other); + } + + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + return 1; + + } else if (streq(name, "AddRef")) { + + int b; + + /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method + * on the Unit interface, and it's probably not a good idea to expose a property and a method on the + * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for + * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference + * dependency type, hence let's not confuse things with that. + * + * Note that we don't actually add the reference to the bus track. We do that only after the setup of + * the transient unit is complete, so that setting this property multiple times in the same transient + * unit creation call doesn't count as individual references. */ + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) + u->bus_track_add = b; + + return 1; + } + + return 0; +} + +int bus_unit_set_properties( + Unit *u, + sd_bus_message *message, + UnitWriteFlags flags, + bool commit, + sd_bus_error *error) { + + bool for_real = false; + unsigned n = 0; + int r; + + assert(u); + assert(message); + + /* We iterate through the array twice. First run we just check + * if all passed data is valid, second run actually applies + * it. This is to implement transaction-like behaviour without + * actually providing full transactions. */ + + r = sd_bus_message_enter_container(message, 'a', "(sv)"); + if (r < 0) + return r; + + for (;;) { + const char *name; + UnitWriteFlags f; + + r = sd_bus_message_enter_container(message, 'r', "sv"); + if (r < 0) + return r; + if (r == 0) { + if (for_real || UNIT_WRITE_FLAGS_NOOP(flags)) + break; + + /* Reached EOF. Let's try again, and this time for realz... */ + r = sd_bus_message_rewind(message, false); + if (r < 0) + return r; + + for_real = true; + continue; + } + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + if (!UNIT_VTABLE(u)->bus_set_property) + return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties."); + + r = sd_bus_message_enter_container(message, 'v', NULL); + if (r < 0) + return r; + + /* If not for real, then mask out the two target flags */ + f = for_real ? flags : (flags & ~(UNIT_RUNTIME|UNIT_PERSISTENT)); + + r = UNIT_VTABLE(u)->bus_set_property(u, name, message, f, error); + if (r == 0 && u->transient && u->load_state == UNIT_STUB) + r = bus_unit_set_transient_property(u, name, message, f, error); + if (r == 0) + r = bus_unit_set_live_property(u, name, message, f, error); + if (r < 0) + return r; + + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name); + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + n += for_real; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties) + UNIT_VTABLE(u)->bus_commit_properties(u); + + return n; +} + +int bus_unit_validate_load_state(Unit *u, sd_bus_error *error) { + assert(u); + + /* Generates a pretty error if a unit isn't properly loaded. */ + + switch (u->load_state) { + + case UNIT_LOADED: + return 0; + + case UNIT_NOT_FOUND: + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id); + + case UNIT_BAD_SETTING: + return sd_bus_error_setf(error, BUS_ERROR_BAD_UNIT_SETTING, "Unit %s has a bad unit file setting.", u->id); + + case UNIT_ERROR: /* Only show .load_error in UNIT_ERROR state */ + return sd_bus_error_set_errnof(error, u->load_error, "Unit %s failed to load properly: %m.", u->id); + + case UNIT_MASKED: + return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id); + + case UNIT_STUB: + case UNIT_MERGED: + default: + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unexpected load state of unit %s", u->id); + } +} + +static int bus_unit_track_handler(sd_bus_track *t, void *userdata) { + Unit *u = userdata; + + assert(t); + assert(u); + + u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */ + + /* If the client that tracks us disappeared, then there's reason to believe that the cgroup is empty now too, + * let's see */ + unit_add_to_cgroup_empty_queue(u); + + /* Also add the unit to the GC queue, after all if the client left it might be time to GC this unit */ + unit_add_to_gc_queue(u); + + return 0; +} + +static int bus_unit_allocate_bus_track(Unit *u) { + int r; + + assert(u); + + if (u->bus_track) + return 0; + + r = sd_bus_track_new(u->manager->api_bus, &u->bus_track, bus_unit_track_handler, u); + if (r < 0) + return r; + + r = sd_bus_track_set_recursive(u->bus_track, true); + if (r < 0) { + u->bus_track = sd_bus_track_unref(u->bus_track); + return r; + } + + return 0; +} + +int bus_unit_track_add_name(Unit *u, const char *name) { + int r; + + assert(u); + + r = bus_unit_allocate_bus_track(u); + if (r < 0) + return r; + + return sd_bus_track_add_name(u->bus_track, name); +} + +int bus_unit_track_add_sender(Unit *u, sd_bus_message *m) { + int r; + + assert(u); + + r = bus_unit_allocate_bus_track(u); + if (r < 0) + return r; + + return sd_bus_track_add_sender(u->bus_track, m); +} + +int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) { + assert(u); + + /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an + * error */ + if (!u->bus_track) + return -EUNATCH; + + return sd_bus_track_remove_sender(u->bus_track, m); +} diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h new file mode 100644 index 00000000..91711311 --- /dev/null +++ b/src/core/dbus-unit.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-bus-vtable.h" + +#include "unit.h" + +extern const sd_bus_vtable bus_unit_vtable[]; +extern const sd_bus_vtable bus_unit_cgroup_vtable[]; + +void bus_unit_send_change_signal(Unit *u); +void bus_unit_send_pending_change_signal(Unit *u, bool including_new); +void bus_unit_send_removed_signal(Unit *u); + +int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error); +int bus_unit_method_enqueue_job(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error); + +int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitWriteFlags flags, bool commit, sd_bus_error *error); +int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_attach_processes(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_ref(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error *error); + +typedef enum BusUnitQueueFlags { + BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE = 1 << 0, + BUS_UNIT_QUEUE_VERBOSE_REPLY = 1 << 1, +} BusUnitQueueFlags; + +int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, BusUnitQueueFlags flags, sd_bus_error *error); +int bus_unit_validate_load_state(Unit *u, sd_bus_error *error); + +int bus_unit_track_add_name(Unit *u, const char *name); +int bus_unit_track_add_sender(Unit *u, sd_bus_message *m); +int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m); diff --git a/src/core/dbus-util.c b/src/core/dbus-util.c new file mode 100644 index 00000000..7862beaa --- /dev/null +++ b/src/core/dbus-util.c @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-util.h" +#include "dbus-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "unit-printf.h" +#include "user-util.h" +#include "unit.h" + +int bus_property_get_triggered_unit( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Unit *u = userdata, *trigger; + + assert(bus); + assert(reply); + assert(u); + + trigger = UNIT_TRIGGER(u); + + return sd_bus_message_append(reply, "s", trigger ? trigger->id : NULL); +} + +BUS_DEFINE_SET_TRANSIENT(mode_t, "u", uint32_t, mode_t, "%040o"); +BUS_DEFINE_SET_TRANSIENT(unsigned, "u", uint32_t, unsigned, "%" PRIu32); +BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(user_compat, valid_user_group_name_or_id_compat); +BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(path, path_is_absolute); + +int bus_set_transient_string( + Unit *u, + const char *name, + char **p, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + const char *v; + int r; + + assert(p); + + r = sd_bus_message_read(message, "s", &v); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = free_and_strdup(p, empty_to_null(v)); + if (r < 0) + return r; + + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, + "%s=%s", name, strempty(v)); + } + + return 1; +} + +int bus_set_transient_bool( + Unit *u, + const char *name, + bool *p, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + int v, r; + + assert(p); + + r = sd_bus_message_read(message, "b", &v); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + *p = v; + unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(v)); + } + + return 1; +} + +int bus_set_transient_usec_internal( + Unit *u, + const char *name, + usec_t *p, + bool fix_0, + sd_bus_message *message, + UnitWriteFlags flags, + sd_bus_error *error) { + + uint64_t v; + int r; + + assert(p); + + r = sd_bus_message_read(message, "t", &v); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + char *n, ts[FORMAT_TIMESPAN_MAX]; + + if (fix_0) + *p = v != 0 ? v: USEC_INFINITY; + else + *p = v; + + n = strndupa(name, strlen(name) - 4); + unit_write_settingf(u, flags, name, "%sSec=%s", n, + format_timespan(ts, sizeof(ts), v, USEC_PER_MSEC)); + } + + return 1; +} diff --git a/src/core/dbus-util.h b/src/core/dbus-util.h new file mode 100644 index 00000000..a3316c67 --- /dev/null +++ b/src/core/dbus-util.h @@ -0,0 +1,248 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "unit.h" + +int bus_property_get_triggered_unit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); + +#define BUS_DEFINE_SET_TRANSIENT(function, bus_type, type, cast_type, fmt) \ + int bus_set_transient_##function( \ + Unit *u, \ + const char *name, \ + cast_type *p, \ + sd_bus_message *message, \ + UnitWriteFlags flags, \ + sd_bus_error *error) { \ + \ + type v; \ + int r; \ + \ + assert(p); \ + \ + r = sd_bus_message_read(message, bus_type, &v); \ + if (r < 0) \ + return r; \ + \ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \ + *p = (cast_type) v; \ + unit_write_settingf(u, flags, name, \ + "%s=" fmt, name, v); \ + } \ + \ + return 1; \ + } + +#define BUS_DEFINE_SET_TRANSIENT_IS_VALID(function, bus_type, type, cast_type, fmt, check) \ + int bus_set_transient_##function( \ + Unit *u, \ + const char *name, \ + cast_type *p, \ + sd_bus_message *message, \ + UnitWriteFlags flags, \ + sd_bus_error *error) { \ + \ + type v; \ + int r; \ + \ + assert(p); \ + \ + r = sd_bus_message_read(message, bus_type, &v); \ + if (r < 0) \ + return r; \ + \ + if (!check(v)) \ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \ + "Invalid %s setting: " fmt, name, v); \ + \ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \ + *p = (cast_type) v; \ + unit_write_settingf(u, flags, name, \ + "%s=" fmt, name, v); \ + } \ + \ + return 1; \ + } + +#define BUS_DEFINE_SET_TRANSIENT_TO_STRING(function, bus_type, type, cast_type, fmt, to_string) \ + int bus_set_transient_##function( \ + Unit *u, \ + const char *name, \ + cast_type *p, \ + sd_bus_message *message, \ + UnitWriteFlags flags, \ + sd_bus_error *error) { \ + \ + const char *s; \ + type v; \ + int r; \ + \ + assert(p); \ + \ + r = sd_bus_message_read(message, bus_type, &v); \ + if (r < 0) \ + return r; \ + \ + s = to_string(v); \ + if (!s) \ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \ + "Invalid %s setting: " fmt, name, v); \ + \ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \ + *p = (cast_type) v; \ + unit_write_settingf(u, flags, name, \ + "%s=%s", name, s); \ + } \ + \ + return 1; \ + } + +#define BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(function, bus_type, type, cast_type, fmt, to_string) \ + int bus_set_transient_##function( \ + Unit *u, \ + const char *name, \ + cast_type *p, \ + sd_bus_message *message, \ + UnitWriteFlags flags, \ + sd_bus_error *error) { \ + \ + _cleanup_free_ char *s = NULL; \ + type v; \ + int r; \ + \ + assert(p); \ + \ + r = sd_bus_message_read(message, bus_type, &v); \ + if (r < 0) \ + return r; \ + \ + r = to_string(v, &s); \ + if (r == -EINVAL) \ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \ + "Invalid %s setting: " fmt, name, v); \ + if (r < 0) \ + return r; \ + \ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \ + *p = (cast_type) v; \ + unit_write_settingf(u, flags, name, \ + "%s=%s", name, s); \ + } \ + \ + return 1; \ + } + +#define BUS_DEFINE_SET_TRANSIENT_PARSE(function, type, parse) \ + int bus_set_transient_##function( \ + Unit *u, \ + const char *name, \ + type *p, \ + sd_bus_message *message, \ + UnitWriteFlags flags, \ + sd_bus_error *error) { \ + \ + const char *s; \ + type v; \ + int r; \ + \ + assert(p); \ + \ + r = sd_bus_message_read(message, "s", &s); \ + if (r < 0) \ + return r; \ + \ + v = parse(s); \ + if (v < 0) \ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \ + "Invalid %s setting: %s", name, s); \ + \ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \ + *p = v; \ + unit_write_settingf(u, flags, name, \ + "%s=%s", name, s); \ + } \ + \ + return 1; \ + } + +#define BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(function, type, parse) \ + int bus_set_transient_##function( \ + Unit *u, \ + const char *name, \ + type *p, \ + sd_bus_message *message, \ + UnitWriteFlags flags, \ + sd_bus_error *error) { \ + \ + const char *s; \ + type v; \ + int r; \ + \ + assert(p); \ + \ + r = sd_bus_message_read(message, "s", &s); \ + if (r < 0) \ + return r; \ + \ + r = parse(s, &v); \ + if (r < 0) \ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \ + "Invalid %s setting: %s", name, s); \ + \ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \ + *p = v; \ + unit_write_settingf(u, flags, name, \ + "%s=%s", name, strempty(s)); \ + } \ + \ + return 1; \ + } + +#define BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(function, check) \ + int bus_set_transient_##function( \ + Unit *u, \ + const char *name, \ + char **p, \ + sd_bus_message *message, \ + UnitWriteFlags flags, \ + sd_bus_error *error) { \ + \ + const char *v; \ + int r; \ + \ + assert(p); \ + \ + r = sd_bus_message_read(message, "s", &v); \ + if (r < 0) \ + return r; \ + \ + if (!isempty(v) && !check(v)) \ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \ + "Invalid %s setting: %s", name, v); \ + \ + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \ + r = free_and_strdup(p, empty_to_null(v)); \ + if (r < 0) \ + return r; \ + \ + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, \ + "%s=%s", name, strempty(v)); \ + } \ + \ + return 1; \ + } + +int bus_set_transient_mode_t(Unit *u, const char *name, mode_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_set_transient_unsigned(Unit *u, const char *name, unsigned *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_set_transient_user_compat(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_set_transient_path(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_set_transient_string(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_set_transient_bool(Unit *u, const char *name, bool *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +int bus_set_transient_usec_internal(Unit *u, const char *name, usec_t *p, bool fix_0, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +static inline int bus_set_transient_usec(Unit *u, const char *name, usec_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error) { + return bus_set_transient_usec_internal(u, name, p, false, message, flags, error); +} +static inline int bus_set_transient_usec_fix_0(Unit *u, const char *name, usec_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error) { + return bus_set_transient_usec_internal(u, name, p, true, message, flags, error); +} diff --git a/src/core/dbus.c b/src/core/dbus.c new file mode 100644 index 00000000..78b30c50 --- /dev/null +++ b/src/core/dbus.c @@ -0,0 +1,1317 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-internal.h" +#include "bus-polkit.h" +#include "dbus-automount.h" +#include "dbus-cgroup.h" +#include "dbus-device.h" +#include "dbus-execute.h" +#include "dbus-job.h" +#include "dbus-kill.h" +#include "dbus-manager.h" +#include "dbus-mount.h" +#include "dbus-path.h" +#include "dbus-scope.h" +#include "dbus-service.h" +#include "dbus-slice.h" +#include "dbus-socket.h" +#include "dbus-swap.h" +#include "dbus-target.h" +#include "dbus-timer.h" +#include "dbus-unit.h" +#include "dbus.h" +#include "fd-util.h" +#include "fs-util.h" +#include "log.h" +#include "mkdir.h" +#include "process-util.h" +#include "selinux-access.h" +#include "serialize.h" +#include "service.h" +#include "special.h" +#include "string-util.h" +#include "strv.h" +#include "strxcpyx.h" +#include "user-util.h" + +#define CONNECTIONS_MAX 4096 + +static void destroy_bus(Manager *m, sd_bus **bus); + +int bus_send_pending_reload_message(Manager *m) { + int r; + + assert(m); + + if (!m->pending_reload_message) + return 0; + + /* If we cannot get rid of this message we won't dispatch any D-Bus messages, so that we won't end up wanting + * to queue another message. */ + + r = sd_bus_send(NULL, m->pending_reload_message, NULL); + if (r < 0) + log_warning_errno(r, "Failed to send queued message, ignoring: %m"); + + m->pending_reload_message = sd_bus_message_unref(m->pending_reload_message); + + return 0; +} + +int bus_forward_agent_released(Manager *m, const char *path) { + int r; + + assert(m); + assert(path); + + if (!MANAGER_IS_SYSTEM(m)) + return 0; + + if (!m->system_bus) + return 0; + + /* If we are running a system instance we forward the agent message on the system bus, so that the user + * instances get notified about this, too */ + + r = sd_bus_emit_signal(m->system_bus, + "/org/freedesktop/systemd1/agent", + "org.freedesktop.systemd1.Agent", + "Released", + "s", path); + if (r < 0) + return log_debug_errno(r, "Failed to propagate agent release message: %m"); + + return 1; +} + +static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + Manager *m = userdata; + const char *cgroup; + uid_t sender_uid; + int r; + + assert(message); + assert(m); + + /* only accept org.freedesktop.systemd1.Agent from UID=0 */ + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_euid(creds, &sender_uid); + if (r < 0 || sender_uid != 0) + return 0; + + /* parse 'cgroup-empty' notification */ + r = sd_bus_message_read(message, "s", &cgroup); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + manager_notify_cgroup_empty(m, cgroup); + return 0; +} + +static int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + sd_bus *bus; + + assert(message); + assert(m); + assert_se(bus = sd_bus_message_get_bus(message)); + + if (bus == m->api_bus) + bus_done_api(m); + if (bus == m->system_bus) + bus_done_system(m); + + if (set_remove(m->private_buses, bus)) { + log_debug("Got disconnect on private connection."); + destroy_bus(m, &bus); + } + + return 0; +} + +static int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + const char *name; + Unit *u; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) || + manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) { + r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down."); + goto failed; + } + + r = manager_load_unit(m, name, NULL, &error, &u); + if (r < 0) + goto failed; + + if (u->refuse_manual_start) { + r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id); + goto failed; + } + + r = manager_add_job(m, JOB_START, u, JOB_REPLACE, NULL, &error, NULL); + if (r < 0) + goto failed; + + /* Successfully queued, that's it for us */ + return 0; + +failed: + if (!sd_bus_error_is_set(&error)) + sd_bus_error_set_errno(&error, r); + + log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r)); + + r = sd_bus_message_new_signal(sd_bus_message_get_bus(message), &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure"); + if (r < 0) { + bus_log_create_error(r); + return 0; + } + + r = sd_bus_message_append(reply, "sss", name, error.name, error.message); + if (r < 0) { + bus_log_create_error(r); + return 0; + } + + r = sd_bus_send_to(NULL, reply, "org.freedesktop.DBus", NULL); + if (r < 0) + return log_error_errno(r, "Failed to respond with to bus activation request: %m"); + + return 0; +} + +#if HAVE_SELINUX +static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *verb, *path; + Unit *u = NULL; + Job *j; + int r; + + assert(message); + + /* Our own method calls are all protected individually with + * selinux checks, but the built-in interfaces need to be + * protected too. */ + + if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set")) + verb = "reload"; + else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) || + sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) || + sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) || + sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL)) + verb = "status"; + else + return 0; + + path = sd_bus_message_get_path(message); + + if (object_path_startswith("/org/freedesktop/systemd1", path)) { + r = mac_selinux_access_check(message, verb, error); + if (r < 0) + return r; + + return 0; + } + + if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + pid_t pid; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return 0; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return 0; + + u = manager_get_unit_by_pid(m, pid); + } else { + r = manager_get_job_from_dbus_path(m, path, &j); + if (r >= 0) + u = j->unit; + else + manager_load_unit_from_dbus_path(m, path, NULL, &u); + } + if (!u) + return 0; + + r = mac_selinux_unit_access_check(u, message, verb, error); + if (r < 0) + return r; + + return 0; +} +#endif + +static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + Job *j; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + r = manager_get_job_from_dbus_path(m, path, &j); + if (r < 0) + return 0; + + *found = j; + return 1; +} + +static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) { + Unit *u = NULL; /* just to appease gcc, initialization is not really necessary */ + int r; + + assert(m); + assert(bus); + assert(path); + + if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + sd_bus_message *message; + pid_t pid; + + message = sd_bus_get_current_message(bus); + if (!message) + return 0; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + + u = manager_get_unit_by_pid(m, pid); + if (!u) + return 0; + } else { + r = manager_load_unit_from_dbus_path(m, path, error, &u); + if (r < 0) + return 0; + assert(u); + } + + *unit = u; + return 1; +} + +static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + return find_unit(m, bus, path, (Unit**) found, error); +} + +static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + Unit *u; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + r = find_unit(m, bus, path, &u, error); + if (r <= 0) + return r; + + if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) + return 0; + + *found = u; + return 1; +} + +static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + Unit *u; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + r = find_unit(m, bus, path, &u, error); + if (r <= 0) + return r; + + if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) + return 0; + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return 0; + + *found = u; + return 1; +} + +static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + CGroupContext *c; + Unit *u; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + r = find_unit(m, bus, path, &u, error); + if (r <= 0) + return r; + + if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) + return 0; + + c = unit_get_cgroup_context(u); + if (!c) + return 0; + + *found = c; + return 1; +} + +static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + ExecContext *c; + Unit *u; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + r = find_unit(m, bus, path, &u, error); + if (r <= 0) + return r; + + if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) + return 0; + + c = unit_get_exec_context(u); + if (!c) + return 0; + + *found = c; + return 1; +} + +static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + KillContext *c; + Unit *u; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + r = find_unit(m, bus, path, &u, error); + if (r <= 0) + return r; + + if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) + return 0; + + c = unit_get_kill_context(u); + if (!c) + return 0; + + *found = c; + return 1; +} + +static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + unsigned k = 0; + Iterator i; + Job *j; + + l = new0(char*, hashmap_size(m->jobs)+1); + if (!l) + return -ENOMEM; + + HASHMAP_FOREACH(j, m->jobs, i) { + l[k] = job_dbus_path(j); + if (!l[k]) + return -ENOMEM; + + k++; + } + + assert(hashmap_size(m->jobs) == k); + + *nodes = TAKE_PTR(l); + + return k; +} + +static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + unsigned k = 0; + Iterator i; + Unit *u; + + l = new0(char*, hashmap_size(m->units)+1); + if (!l) + return -ENOMEM; + + HASHMAP_FOREACH(u, m->units, i) { + l[k] = unit_dbus_path(u); + if (!l[k]) + return -ENOMEM; + + k++; + } + + *nodes = TAKE_PTR(l); + + return k; +} + +static int bus_setup_api_vtables(Manager *m, sd_bus *bus) { + UnitType t; + int r; + + assert(m); + assert(bus); + +#if HAVE_SELINUX + r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m); + if (r < 0) + return log_error_errno(r, "Failed to add SELinux access filter: %m"); +#endif + + r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m); + if (r < 0) + return log_error_errno(r, "Failed to register Manager vtable: %m"); + + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m); + if (r < 0) + return log_error_errno(r, "Failed to register Job vtable: %m"); + + r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m); + if (r < 0) + return log_error_errno(r, "Failed to add job enumerator: %m"); + + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m); + if (r < 0) + return log_error_errno(r, "Failed to register Unit vtable: %m"); + + r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m); + if (r < 0) + return log_error_errno(r, "Failed to add job enumerator: %m"); + + for (t = 0; t < _UNIT_TYPE_MAX; t++) { + const char *interface; + + assert_se(interface = unit_dbus_interface_from_type(t)); + + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m); + if (r < 0) + return log_error_errno(r, "Failed to register type specific vtable for %s: %m", interface); + + if (unit_vtable[t]->cgroup_context_offset > 0) { + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m); + if (r < 0) + return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", interface); + + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_cgroup_vtable, bus_cgroup_context_find, m); + if (r < 0) + return log_error_errno(r, "Failed to register control group vtable for %s: %m", interface); + } + + if (unit_vtable[t]->exec_context_offset > 0) { + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_exec_vtable, bus_exec_context_find, m); + if (r < 0) + return log_error_errno(r, "Failed to register execute vtable for %s: %m", interface); + } + + if (unit_vtable[t]->kill_context_offset > 0) { + r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_kill_vtable, bus_kill_context_find, m); + if (r < 0) + return log_error_errno(r, "Failed to register kill vtable for %s: %m", interface); + } + } + + return 0; +} + +static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) { + int r; + + assert(m); + assert(bus); + + r = sd_bus_match_signal_async( + bus, + NULL, + "org.freedesktop.DBus.Local", + "/org/freedesktop/DBus/Local", + "org.freedesktop.DBus.Local", + "Disconnected", + signal_disconnected, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to request match for Disconnected message: %m"); + + return 0; +} + +static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; + _cleanup_close_ int nfd = -1; + Manager *m = userdata; + sd_id128_t id; + int r; + + assert(s); + assert(m); + + nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); + if (nfd < 0) { + if (ERRNO_IS_ACCEPT_AGAIN(errno)) + return 0; + + log_warning_errno(errno, "Failed to accept private connection, ignoring: %m"); + return 0; + } + + if (set_size(m->private_buses) >= CONNECTIONS_MAX) { + log_warning("Too many concurrent connections, refusing"); + return 0; + } + + r = set_ensure_allocated(&m->private_buses, NULL); + if (r < 0) { + log_oom(); + return 0; + } + + r = sd_bus_new(&bus); + if (r < 0) { + log_warning_errno(r, "Failed to allocate new private connection bus: %m"); + return 0; + } + + (void) sd_bus_set_description(bus, "private-bus-connection"); + + r = sd_bus_set_fd(bus, nfd, nfd); + if (r < 0) { + log_warning_errno(r, "Failed to set fd on new connection bus: %m"); + return 0; + } + + nfd = -1; + + r = bus_check_peercred(bus); + if (r < 0) { + log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m"); + return 0; + } + + assert_se(sd_id128_randomize(&id) >= 0); + + r = sd_bus_set_server(bus, 1, id); + if (r < 0) { + log_warning_errno(r, "Failed to enable server support for new connection bus: %m"); + return 0; + } + + r = sd_bus_negotiate_creds(bus, 1, + SD_BUS_CREDS_PID|SD_BUS_CREDS_UID| + SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS| + SD_BUS_CREDS_SELINUX_CONTEXT); + if (r < 0) { + log_warning_errno(r, "Failed to enable credentials for new connection: %m"); + return 0; + } + + r = sd_bus_set_sender(bus, "org.freedesktop.systemd1"); + if (r < 0) { + log_warning_errno(r, "Failed to set direct connection sender: %m"); + return 0; + } + + r = sd_bus_start(bus); + if (r < 0) { + log_warning_errno(r, "Failed to start new connection bus: %m"); + return 0; + } + + r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL); + if (r < 0) { + log_warning_errno(r, "Failed to attach new connection bus to event loop: %m"); + return 0; + } + + r = bus_setup_disconnected_match(m, bus); + if (r < 0) + return 0; + + r = bus_setup_api_vtables(m, bus); + if (r < 0) { + log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m"); + return 0; + } + + r = set_put(m->private_buses, bus); + if (r < 0) { + log_warning_errno(r, "Failed to add new connection bus to set: %m"); + return 0; + } + + bus = NULL; + + log_debug("Accepted new private connection."); + + return 0; +} + +static int manager_dispatch_sync_bus_names(sd_event_source *es, void *userdata) { + _cleanup_strv_free_ char **names = NULL; + Manager *m = userdata; + const char *name; + Iterator i; + Unit *u; + int r; + + assert(es); + assert(m); + assert(m->sync_bus_names_event_source == es); + + /* First things first, destroy the defer event so that we aren't triggered again */ + m->sync_bus_names_event_source = sd_event_source_unref(m->sync_bus_names_event_source); + + /* Let's see if there's anything to do still? */ + if (!m->api_bus) + return 0; + if (hashmap_isempty(m->watch_bus)) + return 0; + + /* OK, let's sync up the names. Let's see which names are currently on the bus. */ + r = sd_bus_list_names(m->api_bus, &names, NULL); + if (r < 0) + return log_error_errno(r, "Failed to get initial list of names: %m"); + + /* We have to synchronize the current bus names with the + * list of active services. To do this, walk the list of + * all units with bus names. */ + HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) { + Service *s = SERVICE(u); + + assert(s); + + if (!streq_ptr(s->bus_name, name)) { + log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name); + continue; + } + + /* Check if a service's bus name is in the list of currently + * active names */ + if (strv_contains(names, name)) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + const char *unique; + + /* If it is, determine its current owner */ + r = sd_bus_get_name_creds(m->api_bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds); + if (r < 0) { + log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get bus name owner %s: %m", name); + continue; + } + + r = sd_bus_creds_get_unique_name(creds, &unique); + if (r < 0) { + log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get unique name for %s: %m", name); + continue; + } + + /* Now, let's compare that to the previous bus owner, and + * if it's still the same, all is fine, so just don't + * bother the service. Otherwise, the name has apparently + * changed, so synthesize a name owner changed signal. */ + + if (!streq_ptr(unique, s->bus_name_owner)) + UNIT_VTABLE(u)->bus_name_owner_change(u, s->bus_name_owner, unique); + } else { + /* So, the name we're watching is not on the bus. + * This either means it simply hasn't appeared yet, + * or it was lost during the daemon reload. + * Check if the service has a stored name owner, + * and synthesize a name loss signal in this case. */ + + if (s->bus_name_owner) + UNIT_VTABLE(u)->bus_name_owner_change(u, s->bus_name_owner, NULL); + } + } + + return 0; +} + +int manager_enqueue_sync_bus_names(Manager *m) { + int r; + + assert(m); + + /* Enqueues a request to synchronize the bus names in a later event loop iteration. The callers generally don't + * want us to invoke ->bus_name_owner_change() unit calls from their stack frames as this might result in event + * dispatching on its own creating loops, hence we simply create a defer event for the event loop and exit. */ + + if (m->sync_bus_names_event_source) + return 0; + + r = sd_event_add_defer(m->event, &m->sync_bus_names_event_source, manager_dispatch_sync_bus_names, m); + if (r < 0) + return log_error_errno(r, "Failed to create bus name synchronization event: %m"); + + r = sd_event_source_set_priority(m->sync_bus_names_event_source, SD_EVENT_PRIORITY_IDLE); + if (r < 0) + return log_error_errno(r, "Failed to set event priority: %m"); + + r = sd_event_source_set_enabled(m->sync_bus_names_event_source, SD_EVENT_ONESHOT); + if (r < 0) + return log_error_errno(r, "Failed to set even to oneshot: %m"); + + (void) sd_event_source_set_description(m->sync_bus_names_event_source, "manager-sync-bus-names"); + return 0; +} + +static int bus_setup_api(Manager *m, sd_bus *bus) { + Iterator i; + char *name; + Unit *u; + int r; + + assert(m); + assert(bus); + + /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */ + r = sd_bus_negotiate_creds(bus, 1, + SD_BUS_CREDS_PID|SD_BUS_CREDS_UID| + SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS| + SD_BUS_CREDS_SELINUX_CONTEXT); + if (r < 0) + log_warning_errno(r, "Failed to enable credential passing, ignoring: %m"); + + r = bus_setup_api_vtables(m, bus); + if (r < 0) + return r; + + HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) { + r = unit_install_bus_match(u, bus, name); + if (r < 0) + log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name); + } + + r = sd_bus_match_signal_async( + bus, + NULL, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.systemd1.Activator", + "ActivationRequest", + signal_activation_request, NULL, m); + if (r < 0) + log_warning_errno(r, "Failed to subscribe to activation signal: %m"); + + /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open + * until after the new connection is set up and the name installed to allow clients to synchronously wait for + * reexecution to finish */ + r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + log_debug("Successfully connected to API bus."); + + return 0; +} + +int bus_init_api(Manager *m) { + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; + int r; + + if (m->api_bus) + return 0; + + /* The API and system bus is the same if we are running in system mode */ + if (MANAGER_IS_SYSTEM(m) && m->system_bus) + bus = sd_bus_ref(m->system_bus); + else { + if (MANAGER_IS_SYSTEM(m)) + r = sd_bus_open_system_with_description(&bus, "bus-api-system"); + else + r = sd_bus_open_user_with_description(&bus, "bus-api-user"); + if (r < 0) + return log_error_errno(r, "Failed to connect to API bus: %m"); + + r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL); + if (r < 0) + return log_error_errno(r, "Failed to attach API bus to event loop: %m"); + + r = bus_setup_disconnected_match(m, bus); + if (r < 0) + return r; + } + + r = bus_setup_api(m, bus); + if (r < 0) + return log_error_errno(r, "Failed to set up API bus: %m"); + + m->api_bus = TAKE_PTR(bus); + + r = manager_enqueue_sync_bus_names(m); + if (r < 0) + return r; + + return 0; +} + +static int bus_setup_system(Manager *m, sd_bus *bus) { + int r; + + assert(m); + assert(bus); + + /* if we are a user instance we get the Released message via the system bus */ + if (MANAGER_IS_USER(m)) { + r = sd_bus_match_signal_async( + bus, + NULL, + NULL, + "/org/freedesktop/systemd1/agent", + "org.freedesktop.systemd1.Agent", + "Released", + signal_agent_released, NULL, m); + if (r < 0) + log_warning_errno(r, "Failed to request Released match on system bus: %m"); + } + + log_debug("Successfully connected to system bus."); + return 0; +} + +int bus_init_system(Manager *m) { + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; + int r; + + if (m->system_bus) + return 0; + + /* The API and system bus is the same if we are running in system mode */ + if (MANAGER_IS_SYSTEM(m) && m->api_bus) + bus = sd_bus_ref(m->api_bus); + else { + r = sd_bus_open_system_with_description(&bus, "bus-system"); + if (r < 0) + return log_error_errno(r, "Failed to connect to system bus: %m"); + + r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL); + if (r < 0) + return log_error_errno(r, "Failed to attach system bus to event loop: %m"); + + r = bus_setup_disconnected_match(m, bus); + if (r < 0) + return r; + } + + r = bus_setup_system(m, bus); + if (r < 0) + return log_error_errno(r, "Failed to set up system bus: %m"); + + m->system_bus = TAKE_PTR(bus); + + return 0; +} + +int bus_init_private(Manager *m) { + _cleanup_close_ int fd = -1; + union sockaddr_union sa = {}; + sd_event_source *s; + int r, salen; + + assert(m); + + if (m->private_listen_fd >= 0) + return 0; + + if (MANAGER_IS_SYSTEM(m)) { + + /* We want the private bus only when running as init */ + if (getpid_cached() != 1) + return 0; + + salen = sockaddr_un_set_path(&sa.un, "/run/systemd/private"); + } else { + const char *e, *joined; + + e = secure_getenv("XDG_RUNTIME_DIR"); + if (!e) + return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN), + "XDG_RUNTIME_DIR is not set, refusing."); + + joined = strjoina(e, "/systemd/private"); + salen = sockaddr_un_set_path(&sa.un, joined); + } + if (salen < 0) + return log_error_errno(salen, "Can't set path for AF_UNIX socket to bind to: %m"); + + (void) mkdir_parents_label(sa.un.sun_path, 0755); + (void) sockaddr_un_unlink(&sa.un); + + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return log_error_errno(errno, "Failed to allocate private socket: %m"); + + r = bind(fd, &sa.sa, salen); + if (r < 0) + return log_error_errno(errno, "Failed to bind private socket: %m"); + + r = listen(fd, SOMAXCONN); + if (r < 0) + return log_error_errno(errno, "Failed to make private socket listening: %m"); + + /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */ + (void) touch(sa.un.sun_path); + + r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m); + if (r < 0) + return log_error_errno(r, "Failed to allocate event source: %m"); + + (void) sd_event_source_set_description(s, "bus-connection"); + + m->private_listen_fd = TAKE_FD(fd); + m->private_listen_event_source = s; + + log_debug("Successfully created private D-Bus server."); + + return 0; +} + +static void destroy_bus(Manager *m, sd_bus **bus) { + Iterator i; + Unit *u; + Job *j; + + assert(m); + assert(bus); + + if (!*bus) + return; + + /* Make sure all bus slots watching names are released. */ + HASHMAP_FOREACH(u, m->watch_bus, i) { + if (!u->match_bus_slot) + continue; + + if (sd_bus_slot_get_bus(u->match_bus_slot) != *bus) + continue; + + u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); + } + + /* Get rid of tracked clients on this bus */ + if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus) + m->subscribed = sd_bus_track_unref(m->subscribed); + + HASHMAP_FOREACH(j, m->jobs, i) + if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus) + j->bus_track = sd_bus_track_unref(j->bus_track); + + HASHMAP_FOREACH(u, m->units, i) + if (u->bus_track && sd_bus_track_get_bus(u->bus_track) == *bus) + u->bus_track = sd_bus_track_unref(u->bus_track); + + /* Get rid of queued message on this bus */ + if (m->pending_reload_message && sd_bus_message_get_bus(m->pending_reload_message) == *bus) + m->pending_reload_message = sd_bus_message_unref(m->pending_reload_message); + + /* Possibly flush unwritten data, but only if we are + * unprivileged, since we don't want to sync here */ + if (!MANAGER_IS_SYSTEM(m)) + sd_bus_flush(*bus); + + /* And destroy the object */ + *bus = sd_bus_close_unref(*bus); +} + +void bus_done_api(Manager *m) { + destroy_bus(m, &m->api_bus); +} + +void bus_done_system(Manager *m) { + destroy_bus(m, &m->system_bus); +} + +void bus_done_private(Manager *m) { + sd_bus *b; + + assert(m); + + while ((b = set_steal_first(m->private_buses))) + destroy_bus(m, &b); + + m->private_buses = set_free(m->private_buses); + + m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source); + m->private_listen_fd = safe_close(m->private_listen_fd); +} + +void bus_done(Manager *m) { + assert(m); + + bus_done_api(m); + bus_done_system(m); + bus_done_private(m); + + assert(!m->subscribed); + + m->deserialized_subscribed = strv_free(m->deserialized_subscribed); + bus_verify_polkit_async_registry_free(m->polkit_registry); +} + +int bus_fdset_add_all(Manager *m, FDSet *fds) { + Iterator i; + sd_bus *b; + int fd; + + assert(m); + assert(fds); + + /* When we are about to reexecute we add all D-Bus fds to the + * set to pass over to the newly executed systemd. They won't + * be used there however, except thatt they are closed at the + * very end of deserialization, those making it possible for + * clients to synchronously wait for systemd to reexec by + * simply waiting for disconnection */ + + if (m->api_bus) { + fd = sd_bus_get_fd(m->api_bus); + if (fd >= 0) { + fd = fdset_put_dup(fds, fd); + if (fd < 0) + return fd; + } + } + + SET_FOREACH(b, m->private_buses, i) { + fd = sd_bus_get_fd(b); + if (fd >= 0) { + fd = fdset_put_dup(fds, fd); + if (fd < 0) + return fd; + } + } + + /* We don't offer any APIs on the system bus (well, unless it + * is the same as the API bus) hence we don't bother with it + * here */ + + return 0; +} + +int bus_foreach_bus( + Manager *m, + sd_bus_track *subscribed2, + int (*send_message)(sd_bus *bus, void *userdata), + void *userdata) { + + Iterator i; + sd_bus *b; + int r, ret = 0; + + /* Send to all direct buses, unconditionally */ + SET_FOREACH(b, m->private_buses, i) { + + /* Don't bother with enqueing these messages to clients that haven't started yet */ + if (sd_bus_is_ready(b) <= 0) + continue; + + r = send_message(b, userdata); + if (r < 0) + ret = r; + } + + /* Send to API bus, but only if somebody is subscribed */ + if (m->api_bus && + (sd_bus_track_count(m->subscribed) > 0 || + sd_bus_track_count(subscribed2) > 0)) { + r = send_message(m->api_bus, userdata); + if (r < 0) + ret = r; + } + + return ret; +} + +void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) { + const char *n; + + assert(f); + assert(prefix); + + for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) { + int c, j; + + c = sd_bus_track_count_name(t, n); + for (j = 0; j < c; j++) + (void) serialize_item(f, prefix, n); + } +} + +int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) { + int r = 0; + + assert(m); + assert(t); + + if (strv_isempty(l)) + return 0; + + if (!m->api_bus) + return 0; + + if (!*t) { + r = sd_bus_track_new(m->api_bus, t, NULL, NULL); + if (r < 0) + return r; + } + + r = sd_bus_track_set_recursive(*t, recursive); + if (r < 0) + return r; + + return bus_track_add_name_many(*t, l); +} + +int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { + return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", NULL, false, UID_INVALID, &m->polkit_registry, error); +} + +int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { + return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", NULL, false, UID_INVALID, &m->polkit_registry, error); +} + +int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { + return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", NULL, false, UID_INVALID, &m->polkit_registry, error); +} + +int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { + return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", NULL, false, UID_INVALID, &m->polkit_registry, error); +} + +uint64_t manager_bus_n_queued_write(Manager *m) { + uint64_t c = 0; + Iterator i; + sd_bus *b; + int r; + + /* Returns the total number of messages queued for writing on all our direct and API buses. */ + + SET_FOREACH(b, m->private_buses, i) { + uint64_t k; + + r = sd_bus_get_n_queued_write(b, &k); + if (r < 0) + log_debug_errno(r, "Failed to query queued messages for private bus: %m"); + else + c += k; + } + + if (m->api_bus) { + uint64_t k; + + r = sd_bus_get_n_queued_write(m->api_bus, &k); + if (r < 0) + log_debug_errno(r, "Failed to query queued messages for API bus: %m"); + else + c += k; + } + + return c; +} + +static void vtable_dump_bus_properties(FILE *f, const sd_bus_vtable *table) { + const sd_bus_vtable *i; + + for (i = table; i->type != _SD_BUS_VTABLE_END; i++) { + if (!IN_SET(i->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY) || + (i->flags & (SD_BUS_VTABLE_DEPRECATED | SD_BUS_VTABLE_HIDDEN)) != 0) + continue; + + fprintf(f, "%s\n", i->x.property.member); + } +} + +void dump_bus_properties(FILE *f) { + assert(f); + + vtable_dump_bus_properties(f, bus_automount_vtable); + vtable_dump_bus_properties(f, bus_cgroup_vtable); + vtable_dump_bus_properties(f, bus_device_vtable); + vtable_dump_bus_properties(f, bus_exec_vtable); + vtable_dump_bus_properties(f, bus_job_vtable); + vtable_dump_bus_properties(f, bus_kill_vtable); + vtable_dump_bus_properties(f, bus_manager_vtable); + vtable_dump_bus_properties(f, bus_mount_vtable); + vtable_dump_bus_properties(f, bus_path_vtable); + vtable_dump_bus_properties(f, bus_scope_vtable); + vtable_dump_bus_properties(f, bus_service_vtable); + vtable_dump_bus_properties(f, bus_slice_vtable); + vtable_dump_bus_properties(f, bus_socket_vtable); + vtable_dump_bus_properties(f, bus_swap_vtable); + vtable_dump_bus_properties(f, bus_target_vtable); + vtable_dump_bus_properties(f, bus_timer_vtable); + vtable_dump_bus_properties(f, bus_unit_vtable); + vtable_dump_bus_properties(f, bus_unit_cgroup_vtable); +} diff --git a/src/core/dbus.h b/src/core/dbus.h new file mode 100644 index 00000000..f1c0fa86 --- /dev/null +++ b/src/core/dbus.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "manager.h" + +int bus_send_pending_reload_message(Manager *m); + +int bus_init_private(Manager *m); +int bus_init_api(Manager *m); +int bus_init_system(Manager *m); + +void bus_done_private(Manager *m); +void bus_done_api(Manager *m); +void bus_done_system(Manager *m); +void bus_done(Manager *m); + +int bus_fdset_add_all(Manager *m, FDSet *fds); + +void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix); +int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l); + +int manager_enqueue_sync_bus_names(Manager *m); + +int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata); + +int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error); +int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error); +int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error); +int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error); + +int bus_forward_agent_released(Manager *m, const char *path); + +uint64_t manager_bus_n_queued_write(Manager *m); + +void dump_bus_properties(FILE *f); diff --git a/src/core/device.c b/src/core/device.c new file mode 100644 index 00000000..45149e75 --- /dev/null +++ b/src/core/device.c @@ -0,0 +1,1102 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "bus-error.h" +#include "dbus-device.h" +#include "dbus-unit.h" +#include "device-private.h" +#include "device-util.h" +#include "device.h" +#include "log.h" +#include "parse-util.h" +#include "path-util.h" +#include "serialize.h" +#include "stat-util.h" +#include "string-util.h" +#include "swap.h" +#include "udev-util.h" +#include "unit-name.h" +#include "unit.h" + +static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = { + [DEVICE_DEAD] = UNIT_INACTIVE, + [DEVICE_TENTATIVE] = UNIT_ACTIVATING, + [DEVICE_PLUGGED] = UNIT_ACTIVE, +}; + +static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata); +static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask); + +static void device_unset_sysfs(Device *d) { + Hashmap *devices; + Device *first; + + assert(d); + + if (!d->sysfs) + return; + + /* Remove this unit from the chain of devices which share the + * same sysfs path. */ + devices = UNIT(d)->manager->devices_by_sysfs; + first = hashmap_get(devices, d->sysfs); + LIST_REMOVE(same_sysfs, first, d); + + if (first) + hashmap_remove_and_replace(devices, d->sysfs, first->sysfs, first); + else + hashmap_remove(devices, d->sysfs); + + d->sysfs = mfree(d->sysfs); +} + +static int device_set_sysfs(Device *d, const char *sysfs) { + _cleanup_free_ char *copy = NULL; + Device *first; + int r; + + assert(d); + + if (streq_ptr(d->sysfs, sysfs)) + return 0; + + r = hashmap_ensure_allocated(&UNIT(d)->manager->devices_by_sysfs, &path_hash_ops); + if (r < 0) + return r; + + copy = strdup(sysfs); + if (!copy) + return -ENOMEM; + + device_unset_sysfs(d); + + first = hashmap_get(UNIT(d)->manager->devices_by_sysfs, sysfs); + LIST_PREPEND(same_sysfs, first, d); + + r = hashmap_replace(UNIT(d)->manager->devices_by_sysfs, copy, first); + if (r < 0) { + LIST_REMOVE(same_sysfs, first, d); + return r; + } + + d->sysfs = TAKE_PTR(copy); + return 0; +} + +static void device_init(Unit *u) { + Device *d = DEVICE(u); + + assert(d); + assert(UNIT(d)->load_state == UNIT_STUB); + + /* In contrast to all other unit types we timeout jobs waiting + * for devices by default. This is because they otherwise wait + * indefinitely for plugged in devices, something which cannot + * happen for the other units since their operations time out + * anyway. */ + u->job_running_timeout = u->manager->default_timeout_start_usec; + + u->ignore_on_isolate = true; + + d->deserialized_state = _DEVICE_STATE_INVALID; +} + +static void device_done(Unit *u) { + Device *d = DEVICE(u); + + assert(d); + + device_unset_sysfs(d); + d->wants_property = strv_free(d->wants_property); +} + +static int device_load(Unit *u) { + int r; + + r = unit_load_fragment_and_dropin(u, false); + if (r < 0) + return r; + + if (!u->description) { + /* Generate a description based on the path, to be used until the + device is initialized properly */ + r = unit_name_to_path(u->id, &u->description); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to unescape name: %m"); + } + + return 0; +} + +static void device_set_state(Device *d, DeviceState state) { + DeviceState old_state; + assert(d); + + if (d->state != state) + bus_unit_send_pending_change_signal(UNIT(d), false); + + old_state = d->state; + d->state = state; + + if (state == DEVICE_DEAD) + device_unset_sysfs(d); + + if (state != old_state) + log_unit_debug(UNIT(d), "Changed %s -> %s", device_state_to_string(old_state), device_state_to_string(state)); + + unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], 0); +} + +static int device_coldplug(Unit *u) { + Device *d = DEVICE(u); + + assert(d); + assert(d->state == DEVICE_DEAD); + + /* First, let's put the deserialized state and found mask into effect, if we have it. */ + + if (d->deserialized_state < 0 || + (d->deserialized_state == d->state && + d->deserialized_found == d->found)) + return 0; + + d->found = d->deserialized_found; + device_set_state(d, d->deserialized_state); + return 0; +} + +static void device_catchup(Unit *u) { + Device *d = DEVICE(u); + + assert(d); + + /* Second, let's update the state with the enumerated state if it's different */ + if (d->enumerated_found == d->found) + return; + + device_update_found_one(d, d->enumerated_found, DEVICE_FOUND_MASK); +} + +static const struct { + DeviceFound flag; + const char *name; +} device_found_map[] = { + { DEVICE_FOUND_UDEV, "found-udev" }, + { DEVICE_FOUND_MOUNT, "found-mount" }, + { DEVICE_FOUND_SWAP, "found-swap" }, +}; + +static int device_found_to_string_many(DeviceFound flags, char **ret) { + _cleanup_free_ char *s = NULL; + unsigned i; + + assert(ret); + + for (i = 0; i < ELEMENTSOF(device_found_map); i++) { + if (!FLAGS_SET(flags, device_found_map[i].flag)) + continue; + + if (!strextend_with_separator(&s, ",", device_found_map[i].name, NULL)) + return -ENOMEM; + } + + *ret = TAKE_PTR(s); + + return 0; +} + +static int device_found_from_string_many(const char *name, DeviceFound *ret) { + DeviceFound flags = 0; + int r; + + assert(ret); + + for (;;) { + _cleanup_free_ char *word = NULL; + DeviceFound f = 0; + unsigned i; + + r = extract_first_word(&name, &word, ",", 0); + if (r < 0) + return r; + if (r == 0) + break; + + for (i = 0; i < ELEMENTSOF(device_found_map); i++) + if (streq(word, device_found_map[i].name)) { + f = device_found_map[i].flag; + break; + } + + if (f == 0) + return -EINVAL; + + flags |= f; + } + + *ret = flags; + return 0; +} + +static int device_serialize(Unit *u, FILE *f, FDSet *fds) { + _cleanup_free_ char *s = NULL; + Device *d = DEVICE(u); + + assert(u); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", device_state_to_string(d->state)); + + if (device_found_to_string_many(d->found, &s) >= 0) + (void) serialize_item(f, "found", s); + + return 0; +} + +static int device_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Device *d = DEVICE(u); + int r; + + assert(u); + assert(key); + assert(value); + assert(fds); + + if (streq(key, "state")) { + DeviceState state; + + state = device_state_from_string(value); + if (state < 0) + log_unit_debug(u, "Failed to parse state value, ignoring: %s", value); + else + d->deserialized_state = state; + + } else if (streq(key, "found")) { + r = device_found_from_string_many(value, &d->deserialized_found); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to parse found value '%s', ignoring: %m", value); + + } else + log_unit_debug(u, "Unknown serialization key: %s", key); + + return 0; +} + +static void device_dump(Unit *u, FILE *f, const char *prefix) { + Device *d = DEVICE(u); + _cleanup_free_ char *s = NULL; + + assert(d); + + (void) device_found_to_string_many(d->found, &s); + + fprintf(f, + "%sDevice State: %s\n" + "%sSysfs Path: %s\n" + "%sFound: %s\n", + prefix, device_state_to_string(d->state), + prefix, strna(d->sysfs), + prefix, strna(s)); + + if (!strv_isempty(d->wants_property)) { + char **i; + + STRV_FOREACH(i, d->wants_property) + fprintf(f, "%sudev SYSTEMD_WANTS: %s\n", + prefix, *i); + } +} + +_pure_ static UnitActiveState device_active_state(Unit *u) { + assert(u); + + return state_translation_table[DEVICE(u)->state]; +} + +_pure_ static const char *device_sub_state_to_string(Unit *u) { + assert(u); + + return device_state_to_string(DEVICE(u)->state); +} + +static int device_update_description(Unit *u, sd_device *dev, const char *path) { + _cleanup_free_ char *j = NULL; + const char *model, *label, *desc; + int r; + + assert(u); + assert(path); + + desc = path; + + if (dev && + (sd_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE", &model) >= 0 || + sd_device_get_property_value(dev, "ID_MODEL", &model) >= 0)) { + desc = model; + + /* Try to concatenate the device model string with a label, if there is one */ + if (sd_device_get_property_value(dev, "ID_FS_LABEL", &label) >= 0 || + sd_device_get_property_value(dev, "ID_PART_ENTRY_NAME", &label) >= 0 || + sd_device_get_property_value(dev, "ID_PART_ENTRY_NUMBER", &label) >= 0) { + + desc = j = strjoin(model, " ", label); + if (!j) + return log_oom(); + } + } + + r = unit_set_description(u, desc); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to set device description: %m"); + + return 0; +} + +static int device_add_udev_wants(Unit *u, sd_device *dev) { + _cleanup_strv_free_ char **added = NULL; + const char *wants, *property; + Device *d = DEVICE(u); + int r; + + assert(d); + assert(dev); + + property = MANAGER_IS_USER(u->manager) ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS"; + + r = sd_device_get_property_value(dev, property, &wants); + if (r < 0) + return 0; + + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&wants, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to parse property %s with value %s: %m", property, wants); + + if (unit_name_is_valid(word, UNIT_NAME_TEMPLATE) && d->sysfs) { + _cleanup_free_ char *escaped = NULL; + + /* If the unit name is specified as template, then automatically fill in the sysfs path of the + * device as instance name, properly escaped. */ + + r = unit_name_path_escape(d->sysfs, &escaped); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to escape %s: %m", d->sysfs); + + r = unit_name_replace_instance(word, escaped, &k); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to build %s instance of template %s: %m", escaped, word); + } else { + /* If this is not a template, then let's mangle it so, that it becomes a valid unit name. */ + + r = unit_name_mangle(word, UNIT_NAME_MANGLE_WARN, &k); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to mangle unit name \"%s\": %m", word); + } + + r = unit_add_dependency_by_name(u, UNIT_WANTS, k, true, UNIT_DEPENDENCY_UDEV); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to add Wants= dependency: %m"); + + r = strv_push(&added, k); + if (r < 0) + return log_oom(); + + k = NULL; + } + + if (d->state != DEVICE_DEAD) { + char **i; + + /* So here's a special hack, to compensate for the fact that the udev database's reload cycles are not + * synchronized with our own reload cycles: when we detect that the SYSTEMD_WANTS property of a device + * changes while the device unit is already up, let's manually trigger any new units listed in it not + * seen before. This typically happens during the boot-time switch root transition, as udev devices + * will generally already be up in the initrd, but SYSTEMD_WANTS properties get then added through udev + * rules only available on the host system, and thus only when the initial udev coldplug trigger runs. + * + * We do this only if the device has been up already when we parse this, as otherwise the usual + * dependency logic that is run from the dead → plugged transition will trigger these deps. */ + + STRV_FOREACH(i, added) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + if (strv_contains(d->wants_property, *i)) /* Was this unit already listed before? */ + continue; + + r = manager_add_job_by_name(u->manager, JOB_START, *i, JOB_FAIL, NULL, &error, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to enqueue SYSTEMD_WANTS= job, ignoring: %s", bus_error_message(&error, r)); + } + } + + strv_free(d->wants_property); + d->wants_property = TAKE_PTR(added); + + return 0; +} + +static bool device_is_bound_by_mounts(Device *d, sd_device *dev) { + const char *bound_by; + int r; + + assert(d); + assert(dev); + + if (sd_device_get_property_value(dev, "SYSTEMD_MOUNT_DEVICE_BOUND", &bound_by) >= 0) { + r = parse_boolean(bound_by); + if (r < 0) + log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_MOUNT_DEVICE_BOUND='%s' udev property, ignoring: %m", bound_by); + + d->bind_mounts = r > 0; + } else + d->bind_mounts = false; + + return d->bind_mounts; +} + +static void device_upgrade_mount_deps(Unit *u) { + Unit *other; + Iterator i; + void *v; + int r; + + /* Let's upgrade Requires= to BindsTo= on us. (Used when SYSTEMD_MOUNT_DEVICE_BOUND is set) */ + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRED_BY], i) { + if (other->type != UNIT_MOUNT) + continue; + + r = unit_add_dependency(other, UNIT_BINDS_TO, u, true, UNIT_DEPENDENCY_UDEV); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to add BindsTo= dependency between device and mount unit, ignoring: %m"); + } +} + +static int device_setup_unit(Manager *m, sd_device *dev, const char *path, bool main) { + _cleanup_free_ char *e = NULL; + const char *sysfs = NULL; + Unit *u = NULL; + bool delete; + int r; + + assert(m); + assert(path); + + if (dev) { + r = sd_device_get_syspath(dev, &sysfs); + if (r < 0) { + log_device_debug_errno(dev, r, "Couldn't get syspath from device, ignoring: %m"); + return 0; + } + } + + r = unit_name_from_path(path, ".device", &e); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to generate unit name from device path: %m"); + + u = manager_get_unit(m, e); + if (u) { + /* The device unit can still be present even if the device was unplugged: a mount unit can reference it + * hence preventing the GC to have garbaged it. That's desired since the device unit may have a + * dependency on the mount unit which was added during the loading of the later. When the device is + * plugged the sysfs might not be initialized yet, as we serialize the device's state but do not + * serialize the sysfs path across reloads/reexecs. Hence, when coming back from a reload/restart we + * might have the state valid, but not the sysfs path. Hence, let's filter out conflicting devices, but + * let's accept devices in any state with no sysfs path set. */ + + if (DEVICE(u)->state == DEVICE_PLUGGED && + DEVICE(u)->sysfs && + sysfs && + !path_equal(DEVICE(u)->sysfs, sysfs)) { + log_unit_debug(u, "Device %s appeared twice with different sysfs paths %s and %s, ignoring the latter.", + e, DEVICE(u)->sysfs, sysfs); + return -EEXIST; + } + + delete = false; + + /* Let's remove all dependencies generated due to udev properties. We'll re-add whatever is configured + * now below. */ + unit_remove_dependencies(u, UNIT_DEPENDENCY_UDEV); + } else { + delete = true; + + r = unit_new_for_name(m, sizeof(Device), e, &u); + if (r < 0) { + log_device_error_errno(dev, r, "Failed to allocate device unit %s: %m", e); + goto fail; + } + + unit_add_to_load_queue(u); + } + + /* If this was created via some dependency and has not actually been seen yet ->sysfs will not be + * initialized. Hence initialize it if necessary. */ + if (sysfs) { + r = device_set_sysfs(DEVICE(u), sysfs); + if (r < 0) { + log_unit_error_errno(u, r, "Failed to set sysfs path %s: %m", sysfs); + goto fail; + } + + /* The additional systemd udev properties we only interpret for the main object */ + if (main) + (void) device_add_udev_wants(u, dev); + } + + (void) device_update_description(u, dev, path); + + /* So the user wants the mount units to be bound to the device but a mount unit might has been seen by systemd + * before the device appears on its radar. In this case the device unit is partially initialized and includes + * the deps on the mount unit but at that time the "bind mounts" flag wasn't not present. Fix this up now. */ + if (dev && device_is_bound_by_mounts(DEVICE(u), dev)) + device_upgrade_mount_deps(u); + + /* Note that this won't dispatch the load queue, the caller has to do that if needed and appropriate */ + unit_add_to_dbus_queue(u); + + return 0; + +fail: + if (delete) + unit_free(u); + + return r; +} + +static int device_process_new(Manager *m, sd_device *dev) { + const char *sysfs, *dn, *alias; + dev_t devnum; + int r; + + assert(m); + + if (sd_device_get_syspath(dev, &sysfs) < 0) + return 0; + + /* Add the main unit named after the sysfs path */ + r = device_setup_unit(m, dev, sysfs, true); + if (r < 0) + return r; + + /* Add an additional unit for the device node */ + if (sd_device_get_devname(dev, &dn) >= 0) + (void) device_setup_unit(m, dev, dn, false); + + /* Add additional units for all symlinks */ + if (sd_device_get_devnum(dev, &devnum) >= 0) { + const char *p; + + FOREACH_DEVICE_DEVLINK(dev, p) { + struct stat st; + + if (PATH_STARTSWITH_SET(p, "/dev/block/", "/dev/char/")) + continue; + + /* Verify that the symlink in the FS actually belongs + * to this device. This is useful to deal with + * conflicting devices, e.g. when two disks want the + * same /dev/disk/by-label/xxx link because they have + * the same label. We want to make sure that the same + * device that won the symlink wins in systemd, so we + * check the device node major/minor */ + if (stat(p, &st) >= 0 && + ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) || + st.st_rdev != devnum)) + continue; + + (void) device_setup_unit(m, dev, p, false); + } + } + + /* Add additional units for all explicitly configured aliases */ + if (sd_device_get_property_value(dev, "SYSTEMD_ALIAS", &alias) < 0) + return 0; + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&alias, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_device_warning_errno(dev, r, "Failed to parse SYSTEMD_ALIAS property: %m"); + + if (!path_is_absolute(word)) + log_device_warning(dev, "SYSTEMD_ALIAS is not an absolute path, ignoring: %s", word); + else if (!path_is_normalized(word)) + log_device_warning(dev, "SYSTEMD_ALIAS is not a normalized path, ignoring: %s", word); + else + (void) device_setup_unit(m, dev, word, false); + } + + return 0; +} + +static void device_found_changed(Device *d, DeviceFound previous, DeviceFound now) { + assert(d); + + /* Didn't exist before, but does now? if so, generate a new invocation ID for it */ + if (previous == DEVICE_NOT_FOUND && now != DEVICE_NOT_FOUND) + (void) unit_acquire_invocation_id(UNIT(d)); + + if (FLAGS_SET(now, DEVICE_FOUND_UDEV)) + /* When the device is known to udev we consider it plugged. */ + device_set_state(d, DEVICE_PLUGGED); + else if (now != DEVICE_NOT_FOUND && !FLAGS_SET(previous, DEVICE_FOUND_UDEV)) + /* If the device has not been seen by udev yet, but is now referenced by the kernel, then we assume the + * kernel knows it now, and udev might soon too. */ + device_set_state(d, DEVICE_TENTATIVE); + else + /* If nobody sees the device, or if the device was previously seen by udev and now is only referenced + * from the kernel, then we consider the device is gone, the kernel just hasn't noticed it yet. */ + device_set_state(d, DEVICE_DEAD); +} + +static void device_update_found_one(Device *d, DeviceFound found, DeviceFound mask) { + Manager *m; + + assert(d); + + m = UNIT(d)->manager; + + if (MANAGER_IS_RUNNING(m) && (m->honor_device_enumeration || MANAGER_IS_USER(m))) { + DeviceFound n, previous; + + /* When we are already running, then apply the new mask right-away, and trigger state changes + * right-away */ + + n = (d->found & ~mask) | (found & mask); + if (n == d->found) + return; + + previous = d->found; + d->found = n; + + device_found_changed(d, previous, n); + } else + /* We aren't running yet, let's apply the new mask to the shadow variable instead, which we'll apply as + * soon as we catch-up with the state. */ + d->enumerated_found = (d->enumerated_found & ~mask) | (found & mask); +} + +static void device_update_found_by_sysfs(Manager *m, const char *sysfs, DeviceFound found, DeviceFound mask) { + Device *d, *l, *n; + + assert(m); + assert(sysfs); + + if (mask == 0) + return; + + l = hashmap_get(m->devices_by_sysfs, sysfs); + LIST_FOREACH_SAFE(same_sysfs, d, n, l) + device_update_found_one(d, found, mask); +} + +static int device_update_found_by_name(Manager *m, const char *path, DeviceFound found, DeviceFound mask) { + _cleanup_free_ char *e = NULL; + Unit *u; + int r; + + assert(m); + assert(path); + + if (mask == 0) + return 0; + + r = unit_name_from_path(path, ".device", &e); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name from device path: %m"); + + u = manager_get_unit(m, e); + if (!u) + return 0; + + device_update_found_one(DEVICE(u), found, mask); + return 0; +} + +static bool device_is_ready(sd_device *dev) { + const char *ready; + + assert(dev); + + if (device_is_renaming(dev) > 0) + return false; + + if (sd_device_get_property_value(dev, "SYSTEMD_READY", &ready) < 0) + return true; + + return parse_boolean(ready) != 0; +} + +static Unit *device_following(Unit *u) { + Device *d = DEVICE(u); + Device *other, *first = NULL; + + assert(d); + + if (startswith(u->id, "sys-")) + return NULL; + + /* Make everybody follow the unit that's named after the sysfs path */ + LIST_FOREACH_AFTER(same_sysfs, other, d) + if (startswith(UNIT(other)->id, "sys-")) + return UNIT(other); + + LIST_FOREACH_BEFORE(same_sysfs, other, d) { + if (startswith(UNIT(other)->id, "sys-")) + return UNIT(other); + + first = other; + } + + return UNIT(first); +} + +static int device_following_set(Unit *u, Set **_set) { + Device *d = DEVICE(u), *other; + _cleanup_set_free_ Set *set = NULL; + int r; + + assert(d); + assert(_set); + + if (LIST_JUST_US(same_sysfs, d)) { + *_set = NULL; + return 0; + } + + set = set_new(NULL); + if (!set) + return -ENOMEM; + + LIST_FOREACH_AFTER(same_sysfs, other, d) { + r = set_put(set, other); + if (r < 0) + return r; + } + + LIST_FOREACH_BEFORE(same_sysfs, other, d) { + r = set_put(set, other); + if (r < 0) + return r; + } + + *_set = TAKE_PTR(set); + return 1; +} + +static void device_shutdown(Manager *m) { + assert(m); + + m->device_monitor = sd_device_monitor_unref(m->device_monitor); + m->devices_by_sysfs = hashmap_free(m->devices_by_sysfs); +} + +static void device_enumerate(Manager *m) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *dev; + int r; + + assert(m); + + if (!m->device_monitor) { + r = sd_device_monitor_new(&m->device_monitor); + if (r < 0) { + log_error_errno(r, "Failed to allocate device monitor: %m"); + goto fail; + } + + /* This will fail if we are unprivileged, but that + * should not matter much, as user instances won't run + * during boot. */ + (void) sd_device_monitor_set_receive_buffer_size(m->device_monitor, 128*1024*1024); + + r = sd_device_monitor_filter_add_match_tag(m->device_monitor, "systemd"); + if (r < 0) { + log_error_errno(r, "Failed to add udev tag match: %m"); + goto fail; + } + + r = sd_device_monitor_attach_event(m->device_monitor, m->event); + if (r < 0) { + log_error_errno(r, "Failed to attach event to device monitor: %m"); + goto fail; + } + + r = sd_device_monitor_start(m->device_monitor, device_dispatch_io, m); + if (r < 0) { + log_error_errno(r, "Failed to start device monitor: %m"); + goto fail; + } + } + + r = sd_device_enumerator_new(&e); + if (r < 0) { + log_error_errno(r, "Failed to allocate device enumerator: %m"); + goto fail; + } + + r = sd_device_enumerator_add_match_tag(e, "systemd"); + if (r < 0) { + log_error_errno(r, "Failed to set tag for device enumeration: %m"); + goto fail; + } + + FOREACH_DEVICE(e, dev) { + const char *sysfs; + + if (!device_is_ready(dev)) + continue; + + (void) device_process_new(m, dev); + + if (sd_device_get_syspath(dev, &sysfs) < 0) + continue; + + device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV); + } + + return; + +fail: + device_shutdown(m); +} + +static void device_propagate_reload_by_sysfs(Manager *m, const char *sysfs) { + Device *d, *l, *n; + int r; + + assert(m); + assert(sysfs); + + l = hashmap_get(m->devices_by_sysfs, sysfs); + LIST_FOREACH_SAFE(same_sysfs, d, n, l) { + if (d->state == DEVICE_DEAD) + continue; + + r = manager_propagate_reload(m, UNIT(d), JOB_REPLACE, NULL); + if (r < 0) + log_warning_errno(r, "Failed to propagate reload, ignoring: %m"); + } +} + +static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) { + Manager *m = userdata; + DeviceAction action; + const char *sysfs; + int r; + + assert(m); + assert(dev); + + r = sd_device_get_syspath(dev, &sysfs); + if (r < 0) { + log_device_error_errno(dev, r, "Failed to get device sys path: %m"); + return 0; + } + + r = device_get_action(dev, &action); + if (r < 0) { + log_device_error_errno(dev, r, "Failed to get udev action: %m"); + return 0; + } + + if (action == DEVICE_ACTION_CHANGE) + device_propagate_reload_by_sysfs(m, sysfs); + + /* A change event can signal that a device is becoming ready, in particular if + * the device is using the SYSTEMD_READY logic in udev + * so we need to reach the else block of the following if, even for change events */ + if (action == DEVICE_ACTION_REMOVE) { + r = swap_process_device_remove(m, dev); + if (r < 0) + log_device_warning_errno(dev, r, "Failed to process swap device remove event, ignoring: %m"); + + /* If we get notified that a device was removed by + * udev, then it's completely gone, hence unset all + * found bits */ + device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP); + + } else if (device_is_ready(dev)) { + + (void) device_process_new(m, dev); + + r = swap_process_device_new(m, dev); + if (r < 0) + log_device_warning_errno(dev, r, "Failed to process swap device new event, ignoring: %m"); + + manager_dispatch_load_queue(m); + + /* The device is found now, set the udev found bit */ + device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV); + + } else { + /* The device is nominally around, but not ready for + * us. Hence unset the udev bit, but leave the rest + * around. */ + + device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV); + } + + return 0; +} + +static bool device_supported(void) { + static int read_only = -1; + + /* If /sys is read-only we don't support device units, and any + * attempts to start one should fail immediately. */ + + if (read_only < 0) + read_only = path_is_read_only_fs("/sys"); + + return read_only <= 0; +} + +static int validate_node(Manager *m, const char *node, sd_device **ret) { + struct stat st; + int r; + + assert(m); + assert(node); + assert(ret); + + /* Validates a device node that showed up in /proc/swaps or /proc/self/mountinfo if it makes sense for us to + * track. Note that this validator is fine within missing device nodes, but not with badly set up ones! */ + + if (!path_startswith(node, "/dev")) { + *ret = NULL; + return 0; /* bad! */ + } + + if (stat(node, &st) < 0) { + if (errno != ENOENT) + return log_error_errno(errno, "Failed to stat() device node file %s: %m", node); + + *ret = NULL; + return 1; /* good! (though missing) */ + + } else { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + + r = device_new_from_stat_rdev(&dev, &st); + if (r == -ENOENT) { + *ret = NULL; + return 1; /* good! (though missing) */ + } else if (r == -ENOTTY) { + *ret = NULL; + return 0; /* bad! (not a device node but some other kind of file system node) */ + } else if (r < 0) + return log_error_errno(r, "Failed to get udev device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev)); + + *ret = TAKE_PTR(dev); + return 1; /* good! */ + } +} + +void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask) { + int r; + + assert(m); + assert(node); + + if (!device_supported()) + return; + + if (mask == 0) + return; + + /* This is called whenever we find a device referenced in /proc/swaps or /proc/self/mounts. Such a device might + * be mounted/enabled at a time where udev has not finished probing it yet, and we thus haven't learned about + * it yet. In this case we will set the device unit to "tentative" state. + * + * This takes a pair of DeviceFound flags parameters. The 'mask' parameter is a bit mask that indicates which + * bits of 'found' to copy into the per-device DeviceFound flags field. Thus, this function may be used to set + * and unset individual bits in a single call, while merging partially with previous state. */ + + if ((found & mask) != 0) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + + /* If the device is known in the kernel and newly appeared, then we'll create a device unit for it, + * under the name referenced in /proc/swaps or /proc/self/mountinfo. But first, let's validate if + * everything is alright with the device node. */ + + r = validate_node(m, node, &dev); + if (r <= 0) + return; /* Don't create a device unit for this if the device node is borked. */ + + (void) device_setup_unit(m, dev, node, false); + } + + /* Update the device unit's state, should it exist */ + (void) device_update_found_by_name(m, node, found, mask); +} + +bool device_shall_be_bound_by(Unit *device, Unit *u) { + assert(device); + assert(u); + + if (u->type != UNIT_MOUNT) + return false; + + return DEVICE(device)->bind_mounts; +} + +const UnitVTable device_vtable = { + .object_size = sizeof(Device), + .sections = + "Unit\0" + "Device\0" + "Install\0", + + .gc_jobs = true, + + .init = device_init, + .done = device_done, + .load = device_load, + + .coldplug = device_coldplug, + .catchup = device_catchup, + + .serialize = device_serialize, + .deserialize_item = device_deserialize_item, + + .dump = device_dump, + + .active_state = device_active_state, + .sub_state_to_string = device_sub_state_to_string, + + .bus_vtable = bus_device_vtable, + + .following = device_following, + .following_set = device_following_set, + + .enumerate = device_enumerate, + .shutdown = device_shutdown, + .supported = device_supported, + + .status_message_formats = { + .starting_stopping = { + [0] = "Expecting device %s...", + }, + .finished_start_job = { + [JOB_DONE] = "Found device %s.", + [JOB_TIMEOUT] = "Timed out waiting for device %s.", + }, + }, +}; diff --git a/src/core/device.h b/src/core/device.h new file mode 100644 index 00000000..3062be78 --- /dev/null +++ b/src/core/device.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "unit.h" + +typedef struct Device Device; + +/* A mask specifying where we have seen the device currently. This is a bitmask because the device might show up + * asynchronously from each other at various places. For example, in very common case a device might already be mounted + * before udev finished probing it (think: a script setting up a loopback block device, formatting it and mounting it + * in quick succession). Hence we need to track precisely where it is already visible and where not. */ +typedef enum DeviceFound { + DEVICE_NOT_FOUND = 0, + DEVICE_FOUND_UDEV = 1 << 0, /* The device has shown up in the udev database */ + DEVICE_FOUND_MOUNT = 1 << 1, /* The device has shown up in /proc/self/mountinfo */ + DEVICE_FOUND_SWAP = 1 << 2, /* The device has shown up in /proc/swaps */ + DEVICE_FOUND_MASK = DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP, +} DeviceFound; + +struct Device { + Unit meta; + + char *sysfs; + + /* In order to be able to distinguish dependencies on different device nodes we might end up creating multiple + * devices for the same sysfs path. We chain them up here. */ + LIST_FIELDS(struct Device, same_sysfs); + + DeviceState state, deserialized_state; + DeviceFound found, deserialized_found, enumerated_found; + + bool bind_mounts; + + /* The SYSTEMD_WANTS udev property for this device the last time we saw it */ + char **wants_property; +}; + +extern const UnitVTable device_vtable; + +void device_found_node(Manager *m, const char *node, DeviceFound found, DeviceFound mask); +bool device_shall_be_bound_by(Unit *device, Unit *u); + +DEFINE_CAST(DEVICE, Device); diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c new file mode 100644 index 00000000..75373407 --- /dev/null +++ b/src/core/dynamic-user.c @@ -0,0 +1,826 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "clean-ipc.h" +#include "dynamic-user.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "io-util.h" +#include "nscd-flush.h" +#include "parse-util.h" +#include "random-util.h" +#include "serialize.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" + +/* Takes a value generated randomly or by hashing and turns it into a UID in the right range */ +#define UID_CLAMP_INTO_RANGE(rnd) (((uid_t) (rnd) % (DYNAMIC_UID_MAX - DYNAMIC_UID_MIN + 1)) + DYNAMIC_UID_MIN) + +DEFINE_PRIVATE_TRIVIAL_REF_FUNC(DynamicUser, dynamic_user); + +static DynamicUser* dynamic_user_free(DynamicUser *d) { + if (!d) + return NULL; + + if (d->manager) + (void) hashmap_remove(d->manager->dynamic_users, d->name); + + safe_close_pair(d->storage_socket); + return mfree(d); +} + +static int dynamic_user_add(Manager *m, const char *name, int storage_socket[static 2], DynamicUser **ret) { + DynamicUser *d; + int r; + + assert(m); + assert(name); + assert(storage_socket); + + r = hashmap_ensure_allocated(&m->dynamic_users, &string_hash_ops); + if (r < 0) + return r; + + d = malloc0(offsetof(DynamicUser, name) + strlen(name) + 1); + if (!d) + return -ENOMEM; + + strcpy(d->name, name); + + d->storage_socket[0] = storage_socket[0]; + d->storage_socket[1] = storage_socket[1]; + + r = hashmap_put(m->dynamic_users, d->name, d); + if (r < 0) { + free(d); + return r; + } + + d->manager = m; + + if (ret) + *ret = d; + + return 0; +} + +static int dynamic_user_acquire(Manager *m, const char *name, DynamicUser** ret) { + _cleanup_close_pair_ int storage_socket[2] = { -1, -1 }; + DynamicUser *d; + int r; + + assert(m); + assert(name); + + /* Return the DynamicUser structure for a specific user name. Note that this won't actually allocate a UID for + * it, but just prepare the data structure for it. The UID is allocated only on demand, when it's really + * needed, and in the child process we fork off, since allocation involves NSS checks which are not OK to do + * from PID 1. To allow the children and PID 1 share information about allocated UIDs we use an anonymous + * AF_UNIX/SOCK_DGRAM socket (called the "storage socket") that contains at most one datagram with the + * allocated UID number, plus an fd referencing the lock file for the UID + * (i.e. /run/systemd/dynamic-uid/$UID). Why involve the socket pair? So that PID 1 and all its children can + * share the same storage for the UID and lock fd, simply by inheriting the storage socket fds. The socket pair + * may exist in three different states: + * + * a) no datagram stored. This is the initial state. In this case the dynamic user was never realized. + * + * b) a datagram containing a UID stored, but no lock fd attached to it. In this case there was already a + * statically assigned UID by the same name, which we are reusing. + * + * c) a datagram containing a UID stored, and a lock fd is attached to it. In this case we allocated a dynamic + * UID and locked it in the file system, using the lock fd. + * + * As PID 1 and various children might access the socket pair simultaneously, and pop the datagram or push it + * back in any time, we also maintain a lock on the socket pair. Note one peculiarity regarding locking here: + * the UID lock on disk is protected via a BSD file lock (i.e. an fd-bound lock), so that the lock is kept in + * place as long as there's a reference to the fd open. The lock on the storage socket pair however is a POSIX + * file lock (i.e. a process-bound lock), as all users share the same fd of this (after all it is anonymous, + * nobody else could get any access to it except via our own fd) and we want to synchronize access between all + * processes that have access to it. */ + + d = hashmap_get(m->dynamic_users, name); + if (d) { + if (ret) { + /* We already have a structure for the dynamic user, let's increase the ref count and reuse it */ + d->n_ref++; + *ret = d; + } + return 0; + } + + if (!valid_user_group_name_or_id(name)) + return -EINVAL; + + if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, storage_socket) < 0) + return -errno; + + r = dynamic_user_add(m, name, storage_socket, &d); + if (r < 0) + return r; + + storage_socket[0] = storage_socket[1] = -1; + + if (ret) { + d->n_ref++; + *ret = d; + } + + return 1; +} + +static int make_uid_symlinks(uid_t uid, const char *name, bool b) { + + char path1[STRLEN("/run/systemd/dynamic-uid/direct:") + DECIMAL_STR_MAX(uid_t) + 1]; + const char *path2; + int r = 0, k; + + /* Add direct additional symlinks for direct lookups of dynamic UIDs and their names by userspace code. The + * only reason we have this is because dbus-daemon cannot use D-Bus for resolving users and groups (since it + * would be its own client then). We hence keep these world-readable symlinks in place, so that the + * unprivileged dbus user can read the mappings when it needs them via these symlinks instead of having to go + * via the bus. Ideally, we'd use the lock files we keep for this anyway, but we can't since we use BSD locks + * on them and as those may be taken by any user with read access we can't make them world-readable. */ + + xsprintf(path1, "/run/systemd/dynamic-uid/direct:" UID_FMT, uid); + if (unlink(path1) < 0 && errno != ENOENT) + r = -errno; + + if (b && symlink(name, path1) < 0) { + k = log_warning_errno(errno, "Failed to symlink \"%s\": %m", path1); + if (r == 0) + r = k; + } + + path2 = strjoina("/run/systemd/dynamic-uid/direct:", name); + if (unlink(path2) < 0 && errno != ENOENT) { + k = -errno; + if (r == 0) + r = k; + } + + if (b && symlink(path1 + STRLEN("/run/systemd/dynamic-uid/direct:"), path2) < 0) { + k = log_warning_errno(errno, "Failed to symlink \"%s\": %m", path2); + if (r == 0) + r = k; + } + + return r; +} + +static int pick_uid(char **suggested_paths, const char *name, uid_t *ret_uid) { + + /* Find a suitable free UID. We use the following strategy to find a suitable UID: + * + * 1. Initially, we try to read the UID of a number of specified paths. If any of these UIDs works, we use + * them. We use in order to increase the chance of UID reuse, if StateDirectory=, CacheDirectory= or + * LogsDirectory= are used, as reusing the UID these directories are owned by saves us from having to + * recursively chown() them to new users. + * + * 2. If that didn't yield a currently unused UID, we hash the user name, and try to use that. This should be + * pretty good, as the use ris by default derived from the unit name, and hence the same service and same + * user should usually get the same UID as long as our hashing doesn't clash. + * + * 3. Finally, if that didn't work, we randomly pick UIDs, until we find one that is empty. + * + * Since the dynamic UID space is relatively small we'll stop trying after 100 iterations, giving up. */ + + enum { + PHASE_SUGGESTED, /* the first phase, reusing directory ownership UIDs */ + PHASE_HASHED, /* the second phase, deriving a UID from the username by hashing */ + PHASE_RANDOM, /* the last phase, randomly picking UIDs */ + } phase = PHASE_SUGGESTED; + + static const uint8_t hash_key[] = { + 0x37, 0x53, 0x7e, 0x31, 0xcf, 0xce, 0x48, 0xf5, + 0x8a, 0xbb, 0x39, 0x57, 0x8d, 0xd9, 0xec, 0x59 + }; + + unsigned n_tries = 100, current_suggested = 0; + int r; + + (void) mkdir("/run/systemd/dynamic-uid", 0755); + + for (;;) { + char lock_path[STRLEN("/run/systemd/dynamic-uid/") + DECIMAL_STR_MAX(uid_t) + 1]; + _cleanup_close_ int lock_fd = -1; + uid_t candidate; + ssize_t l; + + if (--n_tries <= 0) /* Give up retrying eventually */ + return -EBUSY; + + switch (phase) { + + case PHASE_SUGGESTED: { + struct stat st; + + if (!suggested_paths || !suggested_paths[current_suggested]) { + /* We reached the end of the suggested paths list, let's try by hashing the name */ + phase = PHASE_HASHED; + continue; + } + + if (stat(suggested_paths[current_suggested++], &st) < 0) + continue; /* We can't read the UID of this path, but that doesn't matter, just try the next */ + + candidate = st.st_uid; + break; + } + + case PHASE_HASHED: + /* A static user by this name does not exist yet. Let's find a free ID then, and use that. We + * start with a UID generated as hash from the user name. */ + candidate = UID_CLAMP_INTO_RANGE(siphash24(name, strlen(name), hash_key)); + + /* If this one fails, we should proceed with random tries */ + phase = PHASE_RANDOM; + break; + + case PHASE_RANDOM: + + /* Pick another random UID, and see if that works for us. */ + random_bytes(&candidate, sizeof(candidate)); + candidate = UID_CLAMP_INTO_RANGE(candidate); + break; + + default: + assert_not_reached("unknown phase"); + } + + /* Make sure whatever we picked here actually is in the right range */ + if (!uid_is_dynamic(candidate)) + continue; + + xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, candidate); + + for (;;) { + struct stat st; + + lock_fd = open(lock_path, O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY, 0600); + if (lock_fd < 0) + return -errno; + + r = flock(lock_fd, LOCK_EX|LOCK_NB); /* Try to get a BSD file lock on the UID lock file */ + if (r < 0) { + if (IN_SET(errno, EBUSY, EAGAIN)) + goto next; /* already in use */ + + return -errno; + } + + if (fstat(lock_fd, &st) < 0) + return -errno; + if (st.st_nlink > 0) + break; + + /* Oh, bummer, we got the lock, but the file was unlinked between the time we opened it and + * got the lock. Close it, and try again. */ + lock_fd = safe_close(lock_fd); + } + + /* Some superficial check whether this UID/GID might already be taken by some static user */ + if (getpwuid(candidate) || + getgrgid((gid_t) candidate) || + search_ipc(candidate, (gid_t) candidate) != 0) { + (void) unlink(lock_path); + continue; + } + + /* Let's store the user name in the lock file, so that we can use it for looking up the username for a UID */ + l = pwritev(lock_fd, + (struct iovec[2]) { + IOVEC_INIT_STRING(name), + IOVEC_INIT((char[1]) { '\n' }, 1), + }, 2, 0); + if (l < 0) { + r = -errno; + (void) unlink(lock_path); + return r; + } + + (void) ftruncate(lock_fd, l); + (void) make_uid_symlinks(candidate, name, true); /* also add direct lookup symlinks */ + + *ret_uid = candidate; + return TAKE_FD(lock_fd); + + next: + ; + } +} + +static int dynamic_user_pop(DynamicUser *d, uid_t *ret_uid, int *ret_lock_fd) { + uid_t uid = UID_INVALID; + struct iovec iov = IOVEC_INIT(&uid, sizeof(uid)); + int lock_fd; + ssize_t k; + + assert(d); + assert(ret_uid); + assert(ret_lock_fd); + + /* Read the UID and lock fd that is stored in the storage AF_UNIX socket. This should be called with the lock + * on the socket taken. */ + + k = receive_one_fd_iov(d->storage_socket[0], &iov, 1, MSG_DONTWAIT, &lock_fd); + if (k < 0) + return (int) k; + + *ret_uid = uid; + *ret_lock_fd = lock_fd; + + return 0; +} + +static int dynamic_user_push(DynamicUser *d, uid_t uid, int lock_fd) { + struct iovec iov = IOVEC_INIT(&uid, sizeof(uid)); + + assert(d); + + /* Store the UID and lock_fd in the storage socket. This should be called with the socket pair lock taken. */ + return send_one_fd_iov(d->storage_socket[1], lock_fd, &iov, 1, MSG_DONTWAIT); +} + +static void unlink_uid_lock(int lock_fd, uid_t uid, const char *name) { + char lock_path[STRLEN("/run/systemd/dynamic-uid/") + DECIMAL_STR_MAX(uid_t) + 1]; + + if (lock_fd < 0) + return; + + xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, uid); + (void) unlink(lock_path); + + (void) make_uid_symlinks(uid, name, false); /* remove direct lookup symlinks */ +} + +static int lockfp(int fd, int *fd_lock) { + if (lockf(fd, F_LOCK, 0) < 0) + return -errno; + *fd_lock = fd; + return 0; +} + +static void unlockfp(int *fd_lock) { + if (*fd_lock < 0) + return; + lockf(*fd_lock, F_ULOCK, 0); + *fd_lock = -1; +} + +static int dynamic_user_realize( + DynamicUser *d, + char **suggested_dirs, + uid_t *ret_uid, gid_t *ret_gid, + bool is_user) { + + _cleanup_(unlockfp) int storage_socket0_lock = -1; + _cleanup_close_ int uid_lock_fd = -1; + _cleanup_close_ int etc_passwd_lock_fd = -1; + uid_t num = UID_INVALID; /* a uid if is_user, and a gid otherwise */ + gid_t gid = GID_INVALID; /* a gid if is_user, ignored otherwise */ + bool flush_cache = false; + int r; + + assert(d); + assert(is_user == !!ret_uid); + assert(ret_gid); + + /* Acquire a UID for the user name. This will allocate a UID for the user name if the user doesn't exist + * yet. If it already exists its existing UID/GID will be reused. */ + + r = lockfp(d->storage_socket[0], &storage_socket0_lock); + if (r < 0) + return r; + + r = dynamic_user_pop(d, &num, &uid_lock_fd); + if (r < 0) { + int new_uid_lock_fd; + uid_t new_uid; + + if (r != -EAGAIN) + return r; + + /* OK, nothing stored yet, let's try to find something useful. While we are working on this release the + * lock however, so that nobody else blocks on our NSS lookups. */ + unlockfp(&storage_socket0_lock); + + /* Let's see if a proper, static user or group by this name exists. Try to take the lock on + * /etc/passwd, if that fails with EROFS then /etc is read-only. In that case it's fine if we don't + * take the lock, given that users can't be added there anyway in this case. */ + etc_passwd_lock_fd = take_etc_passwd_lock(NULL); + if (etc_passwd_lock_fd < 0 && etc_passwd_lock_fd != -EROFS) + return etc_passwd_lock_fd; + + /* First, let's parse this as numeric UID */ + r = parse_uid(d->name, &num); + if (r < 0) { + struct passwd *p; + struct group *g; + + if (is_user) { + /* OK, this is not a numeric UID. Let's see if there's a user by this name */ + p = getpwnam(d->name); + if (p) { + num = p->pw_uid; + gid = p->pw_gid; + } else { + /* if the user does not exist but the group with the same name exists, refuse operation */ + g = getgrnam(d->name); + if (g) + return -EILSEQ; + } + } else { + /* Let's see if there's a group by this name */ + g = getgrnam(d->name); + if (g) + num = (uid_t) g->gr_gid; + else { + /* if the group does not exist but the user with the same name exists, refuse operation */ + p = getpwnam(d->name); + if (p) + return -EILSEQ; + } + } + } + + if (num == UID_INVALID) { + /* No static UID assigned yet, excellent. Let's pick a new dynamic one, and lock it. */ + + uid_lock_fd = pick_uid(suggested_dirs, d->name, &num); + if (uid_lock_fd < 0) + return uid_lock_fd; + } + + /* So, we found a working UID/lock combination. Let's see if we actually still need it. */ + r = lockfp(d->storage_socket[0], &storage_socket0_lock); + if (r < 0) { + unlink_uid_lock(uid_lock_fd, num, d->name); + return r; + } + + r = dynamic_user_pop(d, &new_uid, &new_uid_lock_fd); + if (r < 0) { + if (r != -EAGAIN) { + /* OK, something bad happened, let's get rid of the bits we acquired. */ + unlink_uid_lock(uid_lock_fd, num, d->name); + return r; + } + + /* Great! Nothing is stored here, still. Store our newly acquired data. */ + flush_cache = true; + } else { + /* Hmm, so as it appears there's now something stored in the storage socket. Throw away what we + * acquired, and use what's stored now. */ + + unlink_uid_lock(uid_lock_fd, num, d->name); + safe_close(uid_lock_fd); + + num = new_uid; + uid_lock_fd = new_uid_lock_fd; + } + } else if (is_user && !uid_is_dynamic(num)) { + struct passwd *p; + + /* Statically allocated user may have different uid and gid. So, let's obtain the gid. */ + errno = 0; + p = getpwuid(num); + if (!p) + return errno_or_else(ESRCH); + + gid = p->pw_gid; + } + + /* If the UID/GID was already allocated dynamically, push the data we popped out back in. If it was already + * allocated statically, push the UID back too, but do not push the lock fd in. If we allocated the UID + * dynamically right here, push that in along with the lock fd for it. */ + r = dynamic_user_push(d, num, uid_lock_fd); + if (r < 0) + return r; + + if (flush_cache) { + /* If we allocated a new dynamic UID, refresh nscd, so that it forgets about potentially cached + * negative entries. But let's do so after we release the /etc/passwd lock, so that there's no + * potential for nscd wanting to lock that for completing the invalidation. */ + etc_passwd_lock_fd = safe_close(etc_passwd_lock_fd); + (void) nscd_flush_cache(STRV_MAKE("passwd", "group")); + } + + if (is_user) { + *ret_uid = num; + *ret_gid = gid != GID_INVALID ? gid : num; + } else + *ret_gid = num; + + return 0; +} + +int dynamic_user_current(DynamicUser *d, uid_t *ret) { + _cleanup_(unlockfp) int storage_socket0_lock = -1; + _cleanup_close_ int lock_fd = -1; + uid_t uid; + int r; + + assert(d); + assert(ret); + + /* Get the currently assigned UID for the user, if there's any. This simply pops the data from the storage socket, and pushes it back in right-away. */ + + r = lockfp(d->storage_socket[0], &storage_socket0_lock); + if (r < 0) + return r; + + r = dynamic_user_pop(d, &uid, &lock_fd); + if (r < 0) + return r; + + r = dynamic_user_push(d, uid, lock_fd); + if (r < 0) + return r; + + *ret = uid; + return 0; +} + +static DynamicUser* dynamic_user_unref(DynamicUser *d) { + if (!d) + return NULL; + + /* Note that this doesn't actually release any resources itself. If a dynamic user should be fully destroyed + * and its UID released, use dynamic_user_destroy() instead. NB: the dynamic user table may contain entries + * with no references, which is commonly the case right before a daemon reload. */ + + assert(d->n_ref > 0); + d->n_ref--; + + return NULL; +} + +static int dynamic_user_close(DynamicUser *d) { + _cleanup_(unlockfp) int storage_socket0_lock = -1; + _cleanup_close_ int lock_fd = -1; + uid_t uid; + int r; + + /* Release the user ID, by releasing the lock on it, and emptying the storage socket. After this the user is + * unrealized again, much like it was after it the DynamicUser object was first allocated. */ + + r = lockfp(d->storage_socket[0], &storage_socket0_lock); + if (r < 0) + return r; + + r = dynamic_user_pop(d, &uid, &lock_fd); + if (r == -EAGAIN) + /* User wasn't realized yet, nothing to do. */ + return 0; + if (r < 0) + return r; + + /* This dynamic user was realized and dynamically allocated. In this case, let's remove the lock file. */ + unlink_uid_lock(lock_fd, uid, d->name); + + (void) nscd_flush_cache(STRV_MAKE("passwd", "group")); + return 1; +} + +static DynamicUser* dynamic_user_destroy(DynamicUser *d) { + if (!d) + return NULL; + + /* Drop a reference to a DynamicUser object, and destroy the user completely if this was the last + * reference. This is called whenever a service is shut down and wants its dynamic UID gone. Note that + * dynamic_user_unref() is what is called whenever a service is simply freed, for example during a reload + * cycle, where the dynamic users should not be destroyed, but our datastructures should. */ + + dynamic_user_unref(d); + + if (d->n_ref > 0) + return NULL; + + (void) dynamic_user_close(d); + return dynamic_user_free(d); +} + +int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds) { + DynamicUser *d; + Iterator i; + + assert(m); + assert(f); + assert(fds); + + /* Dump the dynamic user database into the manager serialization, to deal with daemon reloads. */ + + HASHMAP_FOREACH(d, m->dynamic_users, i) { + int copy0, copy1; + + copy0 = fdset_put_dup(fds, d->storage_socket[0]); + if (copy0 < 0) + return log_error_errno(copy0, "Failed to add dynamic user storage fd to serialization: %m"); + + copy1 = fdset_put_dup(fds, d->storage_socket[1]); + if (copy1 < 0) + return log_error_errno(copy1, "Failed to add dynamic user storage fd to serialization: %m"); + + (void) serialize_item_format(f, "dynamic-user", "%s %i %i", d->name, copy0, copy1); + } + + return 0; +} + +void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds) { + _cleanup_free_ char *name = NULL, *s0 = NULL, *s1 = NULL; + int r, fd0, fd1; + + assert(m); + assert(value); + assert(fds); + + /* Parse the serialization again, after a daemon reload */ + + r = extract_many_words(&value, NULL, 0, &name, &s0, &s1, NULL); + if (r != 3 || !isempty(value)) { + log_debug("Unable to parse dynamic user line."); + return; + } + + if (safe_atoi(s0, &fd0) < 0 || !fdset_contains(fds, fd0)) { + log_debug("Unable to process dynamic user fd specification."); + return; + } + + if (safe_atoi(s1, &fd1) < 0 || !fdset_contains(fds, fd1)) { + log_debug("Unable to process dynamic user fd specification."); + return; + } + + r = dynamic_user_add(m, name, (int[]) { fd0, fd1 }, NULL); + if (r < 0) { + log_debug_errno(r, "Failed to add dynamic user: %m"); + return; + } + + (void) fdset_remove(fds, fd0); + (void) fdset_remove(fds, fd1); +} + +void dynamic_user_vacuum(Manager *m, bool close_user) { + DynamicUser *d; + Iterator i; + + assert(m); + + /* Empty the dynamic user database, optionally cleaning up orphaned dynamic users, i.e. destroy and free users + * to which no reference exist. This is called after a daemon reload finished, in order to destroy users which + * might not be referenced anymore. */ + + HASHMAP_FOREACH(d, m->dynamic_users, i) { + if (d->n_ref > 0) + continue; + + if (close_user) { + log_debug("Removing orphaned dynamic user %s", d->name); + (void) dynamic_user_close(d); + } + + dynamic_user_free(d); + } +} + +int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret) { + char lock_path[STRLEN("/run/systemd/dynamic-uid/") + DECIMAL_STR_MAX(uid_t) + 1]; + _cleanup_free_ char *user = NULL; + uid_t check_uid; + int r; + + assert(m); + assert(ret); + + /* A friendly way to translate a dynamic user's UID into a name. */ + if (!uid_is_dynamic(uid)) + return -ESRCH; + + xsprintf(lock_path, "/run/systemd/dynamic-uid/" UID_FMT, uid); + r = read_one_line_file(lock_path, &user); + if (IN_SET(r, -ENOENT, 0)) + return -ESRCH; + if (r < 0) + return r; + + /* The lock file might be stale, hence let's verify the data before we return it */ + r = dynamic_user_lookup_name(m, user, &check_uid); + if (r < 0) + return r; + if (check_uid != uid) /* lock file doesn't match our own idea */ + return -ESRCH; + + *ret = TAKE_PTR(user); + + return 0; +} + +int dynamic_user_lookup_name(Manager *m, const char *name, uid_t *ret) { + DynamicUser *d; + int r; + + assert(m); + assert(name); + assert(ret); + + /* A friendly call for translating a dynamic user's name into its UID */ + + d = hashmap_get(m->dynamic_users, name); + if (!d) + return -ESRCH; + + r = dynamic_user_current(d, ret); + if (r == -EAGAIN) /* not realized yet? */ + return -ESRCH; + + return r; +} + +int dynamic_creds_acquire(DynamicCreds *creds, Manager *m, const char *user, const char *group) { + bool acquired = false; + int r; + + assert(creds); + assert(m); + + /* A DynamicUser object encapsulates an allocation of both a UID and a GID for a specific name. However, some + * services use different user and groups. For cases like that there's DynamicCreds containing a pair of user + * and group. This call allocates a pair. */ + + if (!creds->user && user) { + r = dynamic_user_acquire(m, user, &creds->user); + if (r < 0) + return r; + + acquired = true; + } + + if (!creds->group) { + + if (creds->user && (!group || streq_ptr(user, group))) + creds->group = dynamic_user_ref(creds->user); + else { + r = dynamic_user_acquire(m, group, &creds->group); + if (r < 0) { + if (acquired) + creds->user = dynamic_user_unref(creds->user); + return r; + } + } + } + + return 0; +} + +int dynamic_creds_realize(DynamicCreds *creds, char **suggested_paths, uid_t *uid, gid_t *gid) { + uid_t u = UID_INVALID; + gid_t g = GID_INVALID; + int r; + + assert(creds); + assert(uid); + assert(gid); + + /* Realize both the referenced user and group */ + + if (creds->user) { + r = dynamic_user_realize(creds->user, suggested_paths, &u, &g, true); + if (r < 0) + return r; + } + + if (creds->group && creds->group != creds->user) { + r = dynamic_user_realize(creds->group, suggested_paths, NULL, &g, false); + if (r < 0) + return r; + } + + *uid = u; + *gid = g; + return 0; +} + +void dynamic_creds_unref(DynamicCreds *creds) { + assert(creds); + + creds->user = dynamic_user_unref(creds->user); + creds->group = dynamic_user_unref(creds->group); +} + +void dynamic_creds_destroy(DynamicCreds *creds) { + assert(creds); + + creds->user = dynamic_user_destroy(creds->user); + creds->group = dynamic_user_destroy(creds->group); +} diff --git a/src/core/dynamic-user.h b/src/core/dynamic-user.h new file mode 100644 index 00000000..0a55630a --- /dev/null +++ b/src/core/dynamic-user.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct DynamicUser DynamicUser; + +typedef struct DynamicCreds { + /* A combination of a dynamic user and group */ + DynamicUser *user; + DynamicUser *group; +} DynamicCreds; + +#include "manager.h" + +/* Note that this object always allocates a pair of user and group under the same name, even if one of them isn't + * used. This means, if you want to allocate a group and user pair, and they might have two different names, then you + * need to allocated two of these objects. DynamicCreds below makes that easy. */ +struct DynamicUser { + Manager *manager; + unsigned n_ref; + + /* An AF_UNIX socket pair that contains a datagram containing both the numeric ID assigned, as well as a lock + * file fd locking the user ID we picked. */ + int storage_socket[2]; + + char name[]; +}; + +int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds); +void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds); +void dynamic_user_vacuum(Manager *m, bool close_user); + +int dynamic_user_current(DynamicUser *d, uid_t *ret); +int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret); +int dynamic_user_lookup_name(Manager *m, const char *name, uid_t *ret); + +int dynamic_creds_acquire(DynamicCreds *creds, Manager *m, const char *user, const char *group); +int dynamic_creds_realize(DynamicCreds *creds, char **suggested_paths, uid_t *uid, gid_t *gid); + +void dynamic_creds_unref(DynamicCreds *creds); +void dynamic_creds_destroy(DynamicCreds *creds); diff --git a/src/core/efi-random.c b/src/core/efi-random.c new file mode 100644 index 00000000..c4d25d68 --- /dev/null +++ b/src/core/efi-random.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "chattr-util.h" +#include "efi-random.h" +#include "efivars.h" +#include "fd-util.h" +#include "fs-util.h" +#include "strv.h" + +/* If a random seed was passed by the boot loader in the LoaderRandomSeed EFI variable, let's credit it to + * the kernel's random pool, but only once per boot. If this is run very early during initialization we can + * instantly boot up with a filled random pool. + * + * This makes no judgement on the entropy passed, it's the job of the boot loader to only pass us a seed that + * is suitably validated. */ + +static void lock_down_efi_variables(void) { + const char *p; + int r; + + /* Paranoia: let's restrict access modes of these a bit, so that unprivileged users can't use them to + * identify the system or gain too much insight into what we might have credited to the entropy + * pool. */ + FOREACH_STRING(p, + "/sys/firmware/efi/efivars/LoaderRandomSeed-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f", + "/sys/firmware/efi/efivars/LoaderSystemToken-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f") { + + r = chattr_path(p, 0, FS_IMMUTABLE_FL, NULL); + if (r == -ENOENT) + continue; + if (r < 0) + log_warning_errno(r, "Failed to drop FS_IMMUTABLE_FL from %s, ignoring: %m", p); + + if (chmod(p, 0600) < 0) + log_warning_errno(errno, "Failed to reduce access mode of %s, ignoring: %m", p); + } +} + +int efi_take_random_seed(void) { + _cleanup_free_ struct rand_pool_info *info = NULL; + _cleanup_free_ void *value = NULL; + _cleanup_close_ int random_fd = -1; + size_t size; + int r; + + /* Paranoia comes first. */ + lock_down_efi_variables(); + + if (access("/run/systemd/efi-random-seed-taken", F_OK) < 0) { + if (errno != ENOENT) { + log_warning_errno(errno, "Failed to determine whether we already used the random seed token, not using it."); + return 0; + } + + /* ENOENT means we haven't used it yet. */ + } else { + log_debug("EFI random seed already used, not using again."); + return 0; + } + + r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderRandomSeed", NULL, &value, &size); + if (r == -EOPNOTSUPP) { + log_debug_errno(r, "System lacks EFI support, not initializing random seed from EFI variable."); + return 0; + } + if (r == -ENOENT) { + log_debug_errno(r, "Boot loader did not pass LoaderRandomSeed EFI variable, not crediting any entropy."); + return 0; + } + if (r < 0) + return log_warning_errno(r, "Failed to read LoaderRandomSeed EFI variable, ignoring: %m"); + + if (size == 0) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Random seed passed from boot loader has zero size? Ignoring."); + + /* The kernel API only accepts "int" as entropy count (which is in bits), let's avoid any chance for + * confusion here. */ + if (size > INT_MAX / 8) + size = INT_MAX / 8; + + random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY); + if (random_fd < 0) + return log_warning_errno(errno, "Failed to open /dev/urandom for writing, ignoring: %m"); + + /* Before we use the seed, let's mark it as used, so that we never credit it twice. Also, it's a nice + * way to let users known that we successfully acquired entropy from the boot laoder. */ + r = touch("/run/systemd/efi-random-seed-taken"); + if (r < 0) + return log_warning_errno(r, "Unable to mark EFI random seed as used, not using it: %m"); + + info = malloc(offsetof(struct rand_pool_info, buf) + size); + if (!info) + return log_oom(); + + info->entropy_count = size * 8; + info->buf_size = size; + memcpy(info->buf, value, size); + + if (ioctl(random_fd, RNDADDENTROPY, info) < 0) + return log_warning_errno(errno, "Failed to credit entropy, ignoring: %m"); + + log_info("Successfully credited entropy passed from boot loader."); + return 1; +} diff --git a/src/core/efi-random.h b/src/core/efi-random.h new file mode 100644 index 00000000..c1de8671 --- /dev/null +++ b/src/core/efi-random.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int efi_take_random_seed(void); diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c new file mode 100644 index 00000000..4330c0f2 --- /dev/null +++ b/src/core/emergency-action.c @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "bus-error.h" +#include "bus-util.h" +#include "emergency-action.h" +#include "raw-reboot.h" +#include "reboot-util.h" +#include "special.h" +#include "string-table.h" +#include "terminal-util.h" +#include "virt.h" + +static void log_and_status(Manager *m, bool warn, const char *message, const char *reason) { + log_full(warn ? LOG_WARNING : LOG_DEBUG, "%s: %s", message, reason); + if (warn) + manager_status_printf(m, STATUS_TYPE_EMERGENCY, + ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, + "%s: %s", message, reason); +} + +void emergency_action( + Manager *m, + EmergencyAction action, + EmergencyActionFlags options, + const char *reboot_arg, + int exit_status, + const char *reason) { + + assert(m); + assert(action >= 0); + assert(action < _EMERGENCY_ACTION_MAX); + + if (action == EMERGENCY_ACTION_NONE) + return; + + if (FLAGS_SET(options, EMERGENCY_ACTION_IS_WATCHDOG) && !m->service_watchdogs) { + log_warning("Watchdog disabled! Not acting on: %s", reason); + return; + } + + bool warn = FLAGS_SET(options, EMERGENCY_ACTION_WARN); + + switch (action) { + + case EMERGENCY_ACTION_REBOOT: + log_and_status(m, warn, "Rebooting", reason); + + (void) update_reboot_parameter_and_warn(reboot_arg, true); + (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL); + break; + + case EMERGENCY_ACTION_REBOOT_FORCE: + log_and_status(m, warn, "Forcibly rebooting", reason); + + (void) update_reboot_parameter_and_warn(reboot_arg, true); + m->objective = MANAGER_REBOOT; + + break; + + case EMERGENCY_ACTION_REBOOT_IMMEDIATE: + log_and_status(m, warn, "Rebooting immediately", reason); + + sync(); + + if (!isempty(reboot_arg)) { + log_info("Rebooting with argument '%s'.", reboot_arg); + (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, reboot_arg); + log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m"); + } + + log_info("Rebooting."); + (void) reboot(RB_AUTOBOOT); + break; + + case EMERGENCY_ACTION_EXIT: + + if (exit_status >= 0) + m->return_value = exit_status; + + if (MANAGER_IS_USER(m) || detect_container() > 0) { + log_and_status(m, warn, "Exiting", reason); + (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL); + break; + } + + log_notice("Doing \"poweroff\" action instead of an \"exit\" emergency action."); + _fallthrough_; + + case EMERGENCY_ACTION_POWEROFF: + log_and_status(m, warn, "Powering off", reason); + (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL); + break; + + case EMERGENCY_ACTION_EXIT_FORCE: + + if (exit_status >= 0) + m->return_value = exit_status; + + if (MANAGER_IS_USER(m) || detect_container() > 0) { + log_and_status(m, warn, "Exiting immediately", reason); + m->objective = MANAGER_EXIT; + break; + } + + log_notice("Doing \"poweroff-force\" action instead of an \"exit-force\" emergency action."); + _fallthrough_; + + case EMERGENCY_ACTION_POWEROFF_FORCE: + log_and_status(m, warn, "Forcibly powering off", reason); + m->objective = MANAGER_POWEROFF; + break; + + case EMERGENCY_ACTION_POWEROFF_IMMEDIATE: + log_and_status(m, warn, "Powering off immediately", reason); + + sync(); + + log_info("Powering off."); + (void) reboot(RB_POWER_OFF); + break; + + default: + assert_not_reached("Unknown emergency action"); + } +} + +static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = { + [EMERGENCY_ACTION_NONE] = "none", + [EMERGENCY_ACTION_REBOOT] = "reboot", + [EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force", + [EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate", + [EMERGENCY_ACTION_POWEROFF] = "poweroff", + [EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force", + [EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate", + [EMERGENCY_ACTION_EXIT] = "exit", + [EMERGENCY_ACTION_EXIT_FORCE] = "exit-force", +}; +DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction); + +int parse_emergency_action( + const char *value, + bool system, + EmergencyAction *ret) { + + EmergencyAction x; + + x = emergency_action_from_string(value); + if (x < 0) + return -EINVAL; + + if (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION) + return -EOPNOTSUPP; + + *ret = x; + return 0; +} diff --git a/src/core/emergency-action.h b/src/core/emergency-action.h new file mode 100644 index 00000000..706c38a7 --- /dev/null +++ b/src/core/emergency-action.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef enum EmergencyAction { + EMERGENCY_ACTION_NONE, + EMERGENCY_ACTION_REBOOT, + EMERGENCY_ACTION_REBOOT_FORCE, + EMERGENCY_ACTION_REBOOT_IMMEDIATE, + EMERGENCY_ACTION_POWEROFF, + EMERGENCY_ACTION_POWEROFF_FORCE, + EMERGENCY_ACTION_POWEROFF_IMMEDIATE, + EMERGENCY_ACTION_EXIT, + _EMERGENCY_ACTION_FIRST_USER_ACTION = EMERGENCY_ACTION_EXIT, + EMERGENCY_ACTION_EXIT_FORCE, + _EMERGENCY_ACTION_MAX, + _EMERGENCY_ACTION_INVALID = -1 +} EmergencyAction; + +typedef enum EmergencyActionFlags { + EMERGENCY_ACTION_IS_WATCHDOG = 1 << 0, + EMERGENCY_ACTION_WARN = 1 << 1, +} EmergencyActionFlags; + +#include "macro.h" +#include "manager.h" + +void emergency_action(Manager *m, + EmergencyAction action, EmergencyActionFlags options, + const char *reboot_arg, int exit_status, const char *reason); + +const char* emergency_action_to_string(EmergencyAction i) _const_; +EmergencyAction emergency_action_from_string(const char *s) _pure_; + +int parse_emergency_action(const char *value, bool system, EmergencyAction *ret); diff --git a/src/core/execute.c b/src/core/execute.c new file mode 100644 index 00000000..abc164ff --- /dev/null +++ b/src/core/execute.c @@ -0,0 +1,5636 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_PAM +#include +#endif + +#if HAVE_SELINUX +#include +#endif + +#if HAVE_SECCOMP +#include +#endif + +#if HAVE_APPARMOR +#include +#endif + +#include "sd-messages.h" + +#include "af-list.h" +#include "alloc-util.h" +#if HAVE_APPARMOR +#include "apparmor-util.h" +#endif +#include "async.h" +#include "barrier.h" +#include "cap-list.h" +#include "capability-util.h" +#include "chown-recursive.h" +#include "cgroup-setup.h" +#include "cpu-set-util.h" +#include "def.h" +#include "env-file.h" +#include "env-util.h" +#include "errno-list.h" +#include "execute.h" +#include "exit-status.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "glob-util.h" +#include "io-util.h" +#include "ioprio.h" +#include "label.h" +#include "log.h" +#include "macro.h" +#include "manager.h" +#include "memory-util.h" +#include "missing_fs.h" +#include "mkdir.h" +#include "namespace.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "rm-rf.h" +#if HAVE_SECCOMP +#include "seccomp-util.h" +#endif +#include "securebits-util.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "smack-util.h" +#include "socket-util.h" +#include "special.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "syslog-util.h" +#include "terminal-util.h" +#include "umask-util.h" +#include "unit.h" +#include "user-util.h" +#include "utmp-wtmp.h" + +#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC) +#define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC) + +#define SNDBUF_SIZE (8*1024*1024) + +static int shift_fds(int fds[], size_t n_fds) { + int start, restart_from; + + if (n_fds <= 0) + return 0; + + /* Modifies the fds array! (sorts it) */ + + assert(fds); + + start = 0; + for (;;) { + int i; + + restart_from = -1; + + for (i = start; i < (int) n_fds; i++) { + int nfd; + + /* Already at right index? */ + if (fds[i] == i+3) + continue; + + nfd = fcntl(fds[i], F_DUPFD, i + 3); + if (nfd < 0) + return -errno; + + safe_close(fds[i]); + fds[i] = nfd; + + /* Hmm, the fd we wanted isn't free? Then + * let's remember that and try again from here */ + if (nfd != i+3 && restart_from < 0) + restart_from = i; + } + + if (restart_from < 0) + break; + + start = restart_from; + } + + return 0; +} + +static int flags_fds(const int fds[], size_t n_socket_fds, size_t n_storage_fds, bool nonblock) { + size_t i, n_fds; + int r; + + n_fds = n_socket_fds + n_storage_fds; + if (n_fds <= 0) + return 0; + + assert(fds); + + /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags. + * O_NONBLOCK only applies to socket activation though. */ + + for (i = 0; i < n_fds; i++) { + + if (i < n_socket_fds) { + r = fd_nonblock(fds[i], nonblock); + if (r < 0) + return r; + } + + /* We unconditionally drop FD_CLOEXEC from the fds, + * since after all we want to pass these fds to our + * children */ + + r = fd_cloexec(fds[i], false); + if (r < 0) + return r; + } + + return 0; +} + +static const char *exec_context_tty_path(const ExecContext *context) { + assert(context); + + if (context->stdio_as_fds) + return NULL; + + if (context->tty_path) + return context->tty_path; + + return "/dev/console"; +} + +static void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) { + const char *path; + + assert(context); + + path = exec_context_tty_path(context); + + if (context->tty_vhangup) { + if (p && p->stdin_fd >= 0) + (void) terminal_vhangup_fd(p->stdin_fd); + else if (path) + (void) terminal_vhangup(path); + } + + if (context->tty_reset) { + if (p && p->stdin_fd >= 0) + (void) reset_terminal_fd(p->stdin_fd, true); + else if (path) + (void) reset_terminal(path); + } + + if (context->tty_vt_disallocate && path) + (void) vt_disallocate(path); +} + +static bool is_terminal_input(ExecInput i) { + return IN_SET(i, + EXEC_INPUT_TTY, + EXEC_INPUT_TTY_FORCE, + EXEC_INPUT_TTY_FAIL); +} + +static bool is_terminal_output(ExecOutput o) { + return IN_SET(o, + EXEC_OUTPUT_TTY, + EXEC_OUTPUT_SYSLOG_AND_CONSOLE, + EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_JOURNAL_AND_CONSOLE); +} + +static bool is_syslog_output(ExecOutput o) { + return IN_SET(o, + EXEC_OUTPUT_SYSLOG, + EXEC_OUTPUT_SYSLOG_AND_CONSOLE); +} + +static bool is_kmsg_output(ExecOutput o) { + return IN_SET(o, + EXEC_OUTPUT_KMSG, + EXEC_OUTPUT_KMSG_AND_CONSOLE); +} + +static bool exec_context_needs_term(const ExecContext *c) { + assert(c); + + /* Return true if the execution context suggests we should set $TERM to something useful. */ + + if (is_terminal_input(c->std_input)) + return true; + + if (is_terminal_output(c->std_output)) + return true; + + if (is_terminal_output(c->std_error)) + return true; + + return !!c->tty_path; +} + +static int open_null_as(int flags, int nfd) { + int fd; + + assert(nfd >= 0); + + fd = open("/dev/null", flags|O_NOCTTY); + if (fd < 0) + return -errno; + + return move_fd(fd, nfd, false); +} + +static int connect_journal_socket(int fd, uid_t uid, gid_t gid) { + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/stdout", + }; + uid_t olduid = UID_INVALID; + gid_t oldgid = GID_INVALID; + int r; + + if (gid_is_valid(gid)) { + oldgid = getgid(); + + if (setegid(gid) < 0) + return -errno; + } + + if (uid_is_valid(uid)) { + olduid = getuid(); + + if (seteuid(uid) < 0) { + r = -errno; + goto restore_gid; + } + } + + r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0 ? -errno : 0; + + /* If we fail to restore the uid or gid, things will likely + fail later on. This should only happen if an LSM interferes. */ + + if (uid_is_valid(uid)) + (void) seteuid(olduid); + + restore_gid: + if (gid_is_valid(gid)) + (void) setegid(oldgid); + + return r; +} + +static int connect_logger_as( + const Unit *unit, + const ExecContext *context, + const ExecParameters *params, + ExecOutput output, + const char *ident, + int nfd, + uid_t uid, + gid_t gid) { + + _cleanup_close_ int fd = -1; + int r; + + assert(context); + assert(params); + assert(output < _EXEC_OUTPUT_MAX); + assert(ident); + assert(nfd >= 0); + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + return -errno; + + r = connect_journal_socket(fd, uid, gid); + if (r < 0) + return r; + + if (shutdown(fd, SHUT_RD) < 0) + return -errno; + + (void) fd_inc_sndbuf(fd, SNDBUF_SIZE); + + if (dprintf(fd, + "%s\n" + "%s\n" + "%i\n" + "%i\n" + "%i\n" + "%i\n" + "%i\n", + context->syslog_identifier ?: ident, + params->flags & EXEC_PASS_LOG_UNIT ? unit->id : "", + context->syslog_priority, + !!context->syslog_level_prefix, + is_syslog_output(output), + is_kmsg_output(output), + is_terminal_output(output)) < 0) + return -errno; + + return move_fd(TAKE_FD(fd), nfd, false); +} + +static int open_terminal_as(const char *path, int flags, int nfd) { + int fd; + + assert(path); + assert(nfd >= 0); + + fd = open_terminal(path, flags | O_NOCTTY); + if (fd < 0) + return fd; + + return move_fd(fd, nfd, false); +} + +static int acquire_path(const char *path, int flags, mode_t mode) { + union sockaddr_union sa = {}; + _cleanup_close_ int fd = -1; + int r, salen; + + assert(path); + + if (IN_SET(flags & O_ACCMODE, O_WRONLY, O_RDWR)) + flags |= O_CREAT; + + fd = open(path, flags|O_NOCTTY, mode); + if (fd >= 0) + return TAKE_FD(fd); + + if (errno != ENXIO) /* ENXIO is returned when we try to open() an AF_UNIX file system socket on Linux */ + return -errno; + if (strlen(path) >= sizeof(sa.un.sun_path)) /* Too long, can't be a UNIX socket */ + return -ENXIO; + + /* So, it appears the specified path could be an AF_UNIX socket. Let's see if we can connect to it. */ + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + return -errno; + + salen = sockaddr_un_set_path(&sa.un, path); + if (salen < 0) + return salen; + + if (connect(fd, &sa.sa, salen) < 0) + return errno == EINVAL ? -ENXIO : -errno; /* Propagate initial error if we get EINVAL, i.e. we have + * indication that his wasn't an AF_UNIX socket after all */ + + if ((flags & O_ACCMODE) == O_RDONLY) + r = shutdown(fd, SHUT_WR); + else if ((flags & O_ACCMODE) == O_WRONLY) + r = shutdown(fd, SHUT_RD); + else + return TAKE_FD(fd); + if (r < 0) + return -errno; + + return TAKE_FD(fd); +} + +static int fixup_input( + const ExecContext *context, + int socket_fd, + bool apply_tty_stdin) { + + ExecInput std_input; + + assert(context); + + std_input = context->std_input; + + if (is_terminal_input(std_input) && !apply_tty_stdin) + return EXEC_INPUT_NULL; + + if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0) + return EXEC_INPUT_NULL; + + if (std_input == EXEC_INPUT_DATA && context->stdin_data_size == 0) + return EXEC_INPUT_NULL; + + return std_input; +} + +static int fixup_output(ExecOutput std_output, int socket_fd) { + + if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0) + return EXEC_OUTPUT_INHERIT; + + return std_output; +} + +static int setup_input( + const ExecContext *context, + const ExecParameters *params, + int socket_fd, + const int named_iofds[static 3]) { + + ExecInput i; + + assert(context); + assert(params); + assert(named_iofds); + + if (params->stdin_fd >= 0) { + if (dup2(params->stdin_fd, STDIN_FILENO) < 0) + return -errno; + + /* Try to make this the controlling tty, if it is a tty, and reset it */ + if (isatty(STDIN_FILENO)) { + (void) ioctl(STDIN_FILENO, TIOCSCTTY, context->std_input == EXEC_INPUT_TTY_FORCE); + (void) reset_terminal_fd(STDIN_FILENO, true); + } + + return STDIN_FILENO; + } + + i = fixup_input(context, socket_fd, params->flags & EXEC_APPLY_TTY_STDIN); + + switch (i) { + + case EXEC_INPUT_NULL: + return open_null_as(O_RDONLY, STDIN_FILENO); + + case EXEC_INPUT_TTY: + case EXEC_INPUT_TTY_FORCE: + case EXEC_INPUT_TTY_FAIL: { + int fd; + + fd = acquire_terminal(exec_context_tty_path(context), + i == EXEC_INPUT_TTY_FAIL ? ACQUIRE_TERMINAL_TRY : + i == EXEC_INPUT_TTY_FORCE ? ACQUIRE_TERMINAL_FORCE : + ACQUIRE_TERMINAL_WAIT, + USEC_INFINITY); + if (fd < 0) + return fd; + + return move_fd(fd, STDIN_FILENO, false); + } + + case EXEC_INPUT_SOCKET: + assert(socket_fd >= 0); + + return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO; + + case EXEC_INPUT_NAMED_FD: + assert(named_iofds[STDIN_FILENO] >= 0); + + (void) fd_nonblock(named_iofds[STDIN_FILENO], false); + return dup2(named_iofds[STDIN_FILENO], STDIN_FILENO) < 0 ? -errno : STDIN_FILENO; + + case EXEC_INPUT_DATA: { + int fd; + + fd = acquire_data_fd(context->stdin_data, context->stdin_data_size, 0); + if (fd < 0) + return fd; + + return move_fd(fd, STDIN_FILENO, false); + } + + case EXEC_INPUT_FILE: { + bool rw; + int fd; + + assert(context->stdio_file[STDIN_FILENO]); + + rw = (context->std_output == EXEC_OUTPUT_FILE && streq_ptr(context->stdio_file[STDIN_FILENO], context->stdio_file[STDOUT_FILENO])) || + (context->std_error == EXEC_OUTPUT_FILE && streq_ptr(context->stdio_file[STDIN_FILENO], context->stdio_file[STDERR_FILENO])); + + fd = acquire_path(context->stdio_file[STDIN_FILENO], rw ? O_RDWR : O_RDONLY, 0666 & ~context->umask); + if (fd < 0) + return fd; + + return move_fd(fd, STDIN_FILENO, false); + } + + default: + assert_not_reached("Unknown input type"); + } +} + +static bool can_inherit_stderr_from_stdout( + const ExecContext *context, + ExecOutput o, + ExecOutput e) { + + assert(context); + + /* Returns true, if given the specified STDERR and STDOUT output we can directly dup() the stdout fd to the + * stderr fd */ + + if (e == EXEC_OUTPUT_INHERIT) + return true; + if (e != o) + return false; + + if (e == EXEC_OUTPUT_NAMED_FD) + return streq_ptr(context->stdio_fdname[STDOUT_FILENO], context->stdio_fdname[STDERR_FILENO]); + + if (IN_SET(e, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND)) + return streq_ptr(context->stdio_file[STDOUT_FILENO], context->stdio_file[STDERR_FILENO]); + + return true; +} + +static int setup_output( + const Unit *unit, + const ExecContext *context, + const ExecParameters *params, + int fileno, + int socket_fd, + const int named_iofds[static 3], + const char *ident, + uid_t uid, + gid_t gid, + dev_t *journal_stream_dev, + ino_t *journal_stream_ino) { + + ExecOutput o; + ExecInput i; + int r; + + assert(unit); + assert(context); + assert(params); + assert(ident); + assert(journal_stream_dev); + assert(journal_stream_ino); + + if (fileno == STDOUT_FILENO && params->stdout_fd >= 0) { + + if (dup2(params->stdout_fd, STDOUT_FILENO) < 0) + return -errno; + + return STDOUT_FILENO; + } + + if (fileno == STDERR_FILENO && params->stderr_fd >= 0) { + if (dup2(params->stderr_fd, STDERR_FILENO) < 0) + return -errno; + + return STDERR_FILENO; + } + + i = fixup_input(context, socket_fd, params->flags & EXEC_APPLY_TTY_STDIN); + o = fixup_output(context->std_output, socket_fd); + + if (fileno == STDERR_FILENO) { + ExecOutput e; + e = fixup_output(context->std_error, socket_fd); + + /* This expects the input and output are already set up */ + + /* Don't change the stderr file descriptor if we inherit all + * the way and are not on a tty */ + if (e == EXEC_OUTPUT_INHERIT && + o == EXEC_OUTPUT_INHERIT && + i == EXEC_INPUT_NULL && + !is_terminal_input(context->std_input) && + getppid () != 1) + return fileno; + + /* Duplicate from stdout if possible */ + if (can_inherit_stderr_from_stdout(context, o, e)) + return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno; + + o = e; + + } else if (o == EXEC_OUTPUT_INHERIT) { + /* If input got downgraded, inherit the original value */ + if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input)) + return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno); + + /* If the input is connected to anything that's not a /dev/null or a data fd, inherit that... */ + if (!IN_SET(i, EXEC_INPUT_NULL, EXEC_INPUT_DATA)) + return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno; + + /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */ + if (getppid() != 1) + return fileno; + + /* We need to open /dev/null here anew, to get the right access mode. */ + return open_null_as(O_WRONLY, fileno); + } + + switch (o) { + + case EXEC_OUTPUT_NULL: + return open_null_as(O_WRONLY, fileno); + + case EXEC_OUTPUT_TTY: + if (is_terminal_input(i)) + return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno; + + /* We don't reset the terminal if this is just about output */ + return open_terminal_as(exec_context_tty_path(context), O_WRONLY, fileno); + + case EXEC_OUTPUT_SYSLOG: + case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: + case EXEC_OUTPUT_KMSG: + case EXEC_OUTPUT_KMSG_AND_CONSOLE: + case EXEC_OUTPUT_JOURNAL: + case EXEC_OUTPUT_JOURNAL_AND_CONSOLE: + r = connect_logger_as(unit, context, params, o, ident, fileno, uid, gid); + if (r < 0) { + log_unit_warning_errno(unit, r, "Failed to connect %s to the journal socket, ignoring: %m", fileno == STDOUT_FILENO ? "stdout" : "stderr"); + r = open_null_as(O_WRONLY, fileno); + } else { + struct stat st; + + /* If we connected this fd to the journal via a stream, patch the device/inode into the passed + * parameters, but only then. This is useful so that we can set $JOURNAL_STREAM that permits + * services to detect whether they are connected to the journal or not. + * + * If both stdout and stderr are connected to a stream then let's make sure to store the data + * about STDERR as that's usually the best way to do logging. */ + + if (fstat(fileno, &st) >= 0 && + (*journal_stream_ino == 0 || fileno == STDERR_FILENO)) { + *journal_stream_dev = st.st_dev; + *journal_stream_ino = st.st_ino; + } + } + return r; + + case EXEC_OUTPUT_SOCKET: + assert(socket_fd >= 0); + + return dup2(socket_fd, fileno) < 0 ? -errno : fileno; + + case EXEC_OUTPUT_NAMED_FD: + assert(named_iofds[fileno] >= 0); + + (void) fd_nonblock(named_iofds[fileno], false); + return dup2(named_iofds[fileno], fileno) < 0 ? -errno : fileno; + + case EXEC_OUTPUT_FILE: + case EXEC_OUTPUT_FILE_APPEND: { + bool rw; + int fd, flags; + + assert(context->stdio_file[fileno]); + + rw = context->std_input == EXEC_INPUT_FILE && + streq_ptr(context->stdio_file[fileno], context->stdio_file[STDIN_FILENO]); + + if (rw) + return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno; + + flags = O_WRONLY; + if (o == EXEC_OUTPUT_FILE_APPEND) + flags |= O_APPEND; + + fd = acquire_path(context->stdio_file[fileno], flags, 0666 & ~context->umask); + if (fd < 0) + return fd; + + return move_fd(fd, fileno, 0); + } + + default: + assert_not_reached("Unknown error type"); + } +} + +static int chown_terminal(int fd, uid_t uid) { + int r; + + assert(fd >= 0); + + /* Before we chown/chmod the TTY, let's ensure this is actually a tty */ + if (isatty(fd) < 1) { + if (IN_SET(errno, EINVAL, ENOTTY)) + return 0; /* not a tty */ + + return -errno; + } + + /* This might fail. What matters are the results. */ + r = fchmod_and_chown(fd, TTY_MODE, uid, -1); + if (r < 0) + return r; + + return 1; +} + +static int setup_confirm_stdio(const char *vc, int *_saved_stdin, int *_saved_stdout) { + _cleanup_close_ int fd = -1, saved_stdin = -1, saved_stdout = -1; + int r; + + assert(_saved_stdin); + assert(_saved_stdout); + + saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3); + if (saved_stdin < 0) + return -errno; + + saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3); + if (saved_stdout < 0) + return -errno; + + fd = acquire_terminal(vc, ACQUIRE_TERMINAL_WAIT, DEFAULT_CONFIRM_USEC); + if (fd < 0) + return fd; + + r = chown_terminal(fd, getuid()); + if (r < 0) + return r; + + r = reset_terminal_fd(fd, true); + if (r < 0) + return r; + + r = rearrange_stdio(fd, fd, STDERR_FILENO); + fd = -1; + if (r < 0) + return r; + + *_saved_stdin = saved_stdin; + *_saved_stdout = saved_stdout; + + saved_stdin = saved_stdout = -1; + + return 0; +} + +static void write_confirm_error_fd(int err, int fd, const Unit *u) { + assert(err < 0); + + if (err == -ETIMEDOUT) + dprintf(fd, "Confirmation question timed out for %s, assuming positive response.\n", u->id); + else { + errno = -err; + dprintf(fd, "Couldn't ask confirmation for %s: %m, assuming positive response.\n", u->id); + } +} + +static void write_confirm_error(int err, const char *vc, const Unit *u) { + _cleanup_close_ int fd = -1; + + assert(vc); + + fd = open_terminal(vc, O_WRONLY|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return; + + write_confirm_error_fd(err, fd, u); +} + +static int restore_confirm_stdio(int *saved_stdin, int *saved_stdout) { + int r = 0; + + assert(saved_stdin); + assert(saved_stdout); + + release_terminal(); + + if (*saved_stdin >= 0) + if (dup2(*saved_stdin, STDIN_FILENO) < 0) + r = -errno; + + if (*saved_stdout >= 0) + if (dup2(*saved_stdout, STDOUT_FILENO) < 0) + r = -errno; + + *saved_stdin = safe_close(*saved_stdin); + *saved_stdout = safe_close(*saved_stdout); + + return r; +} + +enum { + CONFIRM_PRETEND_FAILURE = -1, + CONFIRM_PRETEND_SUCCESS = 0, + CONFIRM_EXECUTE = 1, +}; + +static int ask_for_confirmation(const char *vc, Unit *u, const char *cmdline) { + int saved_stdout = -1, saved_stdin = -1, r; + _cleanup_free_ char *e = NULL; + char c; + + /* For any internal errors, assume a positive response. */ + r = setup_confirm_stdio(vc, &saved_stdin, &saved_stdout); + if (r < 0) { + write_confirm_error(r, vc, u); + return CONFIRM_EXECUTE; + } + + /* confirm_spawn might have been disabled while we were sleeping. */ + if (manager_is_confirm_spawn_disabled(u->manager)) { + r = 1; + goto restore_stdio; + } + + e = ellipsize(cmdline, 60, 100); + if (!e) { + log_oom(); + r = CONFIRM_EXECUTE; + goto restore_stdio; + } + + for (;;) { + r = ask_char(&c, "yfshiDjcn", "Execute %s? [y, f, s – h for help] ", e); + if (r < 0) { + write_confirm_error_fd(r, STDOUT_FILENO, u); + r = CONFIRM_EXECUTE; + goto restore_stdio; + } + + switch (c) { + case 'c': + printf("Resuming normal execution.\n"); + manager_disable_confirm_spawn(); + r = 1; + break; + case 'D': + unit_dump(u, stdout, " "); + continue; /* ask again */ + case 'f': + printf("Failing execution.\n"); + r = CONFIRM_PRETEND_FAILURE; + break; + case 'h': + printf(" c - continue, proceed without asking anymore\n" + " D - dump, show the state of the unit\n" + " f - fail, don't execute the command and pretend it failed\n" + " h - help\n" + " i - info, show a short summary of the unit\n" + " j - jobs, show jobs that are in progress\n" + " s - skip, don't execute the command and pretend it succeeded\n" + " y - yes, execute the command\n"); + continue; /* ask again */ + case 'i': + printf(" Description: %s\n" + " Unit: %s\n" + " Command: %s\n", + u->id, u->description, cmdline); + continue; /* ask again */ + case 'j': + manager_dump_jobs(u->manager, stdout, " "); + continue; /* ask again */ + case 'n': + /* 'n' was removed in favor of 'f'. */ + printf("Didn't understand 'n', did you mean 'f'?\n"); + continue; /* ask again */ + case 's': + printf("Skipping execution.\n"); + r = CONFIRM_PRETEND_SUCCESS; + break; + case 'y': + r = CONFIRM_EXECUTE; + break; + default: + assert_not_reached("Unhandled choice"); + } + break; + } + +restore_stdio: + restore_confirm_stdio(&saved_stdin, &saved_stdout); + return r; +} + +static int get_fixed_user(const ExecContext *c, const char **user, + uid_t *uid, gid_t *gid, + const char **home, const char **shell) { + int r; + const char *name; + + assert(c); + + if (!c->user) + return 0; + + /* Note that we don't set $HOME or $SHELL if they are not particularly enlightening anyway + * (i.e. are "/" or "/bin/nologin"). */ + + name = c->user; + r = get_user_creds(&name, uid, gid, home, shell, USER_CREDS_CLEAN); + if (r < 0) + return r; + + *user = name; + return 0; +} + +static int get_fixed_group(const ExecContext *c, const char **group, gid_t *gid) { + int r; + const char *name; + + assert(c); + + if (!c->group) + return 0; + + name = c->group; + r = get_group_creds(&name, gid, 0); + if (r < 0) + return r; + + *group = name; + return 0; +} + +static int get_supplementary_groups(const ExecContext *c, const char *user, + const char *group, gid_t gid, + gid_t **supplementary_gids, int *ngids) { + char **i; + int r, k = 0; + int ngroups_max; + bool keep_groups = false; + gid_t *groups = NULL; + _cleanup_free_ gid_t *l_gids = NULL; + + assert(c); + + /* + * If user is given, then lookup GID and supplementary groups list. + * We avoid NSS lookups for gid=0. Also we have to initialize groups + * here and as early as possible so we keep the list of supplementary + * groups of the caller. + */ + if (user && gid_is_valid(gid) && gid != 0) { + /* First step, initialize groups from /etc/groups */ + if (initgroups(user, gid) < 0) + return -errno; + + keep_groups = true; + } + + if (strv_isempty(c->supplementary_groups)) + return 0; + + /* + * If SupplementaryGroups= was passed then NGROUPS_MAX has to + * be positive, otherwise fail. + */ + errno = 0; + ngroups_max = (int) sysconf(_SC_NGROUPS_MAX); + if (ngroups_max <= 0) + return errno_or_else(EOPNOTSUPP); + + l_gids = new(gid_t, ngroups_max); + if (!l_gids) + return -ENOMEM; + + if (keep_groups) { + /* + * Lookup the list of groups that the user belongs to, we + * avoid NSS lookups here too for gid=0. + */ + k = ngroups_max; + if (getgrouplist(user, gid, l_gids, &k) < 0) + return -EINVAL; + } else + k = 0; + + STRV_FOREACH(i, c->supplementary_groups) { + const char *g; + + if (k >= ngroups_max) + return -E2BIG; + + g = *i; + r = get_group_creds(&g, l_gids+k, 0); + if (r < 0) + return r; + + k++; + } + + /* + * Sets ngids to zero to drop all supplementary groups, happens + * when we are under root and SupplementaryGroups= is empty. + */ + if (k == 0) { + *ngids = 0; + return 0; + } + + /* Otherwise get the final list of supplementary groups */ + groups = memdup(l_gids, sizeof(gid_t) * k); + if (!groups) + return -ENOMEM; + + *supplementary_gids = groups; + *ngids = k; + + groups = NULL; + + return 0; +} + +static int enforce_groups(gid_t gid, const gid_t *supplementary_gids, int ngids) { + int r; + + /* Handle SupplementaryGroups= if it is not empty */ + if (ngids > 0) { + r = maybe_setgroups(ngids, supplementary_gids); + if (r < 0) + return r; + } + + if (gid_is_valid(gid)) { + /* Then set our gids */ + if (setresgid(gid, gid, gid) < 0) + return -errno; + } + + return 0; +} + +static int enforce_user(const ExecContext *context, uid_t uid) { + assert(context); + + if (!uid_is_valid(uid)) + return 0; + + /* Sets (but doesn't look up) the uid and make sure we keep the + * capabilities while doing so. */ + + if (context->capability_ambient_set != 0) { + + /* First step: If we need to keep capabilities but + * drop privileges we need to make sure we keep our + * caps, while we drop privileges. */ + if (uid != 0) { + int sb = context->secure_bits | 1<= 0) + tty = strjoina("/dev/", q); + } + + if (tty) { + pam_code = pam_set_item(handle, PAM_TTY, tty); + if (pam_code != PAM_SUCCESS) + goto fail; + } + + STRV_FOREACH(nv, *env) { + pam_code = pam_putenv(handle, *nv); + if (pam_code != PAM_SUCCESS) + goto fail; + } + + pam_code = pam_acct_mgmt(handle, flags); + if (pam_code != PAM_SUCCESS) + goto fail; + + pam_code = pam_open_session(handle, flags); + if (pam_code != PAM_SUCCESS) + goto fail; + + close_session = true; + + e = pam_getenvlist(handle); + if (!e) { + pam_code = PAM_BUF_ERR; + goto fail; + } + + /* Block SIGTERM, so that we know that it won't get lost in + * the child */ + + assert_se(sigprocmask_many(SIG_BLOCK, &old_ss, SIGTERM, -1) >= 0); + + parent_pid = getpid_cached(); + + r = safe_fork("(sd-pam)", 0, &pam_pid); + if (r < 0) + goto fail; + if (r == 0) { + int sig, ret = EXIT_PAM; + + /* The child's job is to reset the PAM session on + * termination */ + barrier_set_role(&barrier, BARRIER_CHILD); + + /* Make sure we don't keep open the passed fds in this child. We assume that otherwise only those fds + * are open here that have been opened by PAM. */ + (void) close_many(fds, n_fds); + + /* Drop privileges - we don't need any to pam_close_session + * and this will make PR_SET_PDEATHSIG work in most cases. + * If this fails, ignore the error - but expect sd-pam threads + * to fail to exit normally */ + + r = maybe_setgroups(0, NULL); + if (r < 0) + log_warning_errno(r, "Failed to setgroups() in sd-pam: %m"); + if (setresgid(gid, gid, gid) < 0) + log_warning_errno(errno, "Failed to setresgid() in sd-pam: %m"); + if (setresuid(uid, uid, uid) < 0) + log_warning_errno(errno, "Failed to setresuid() in sd-pam: %m"); + + (void) ignore_signals(SIGPIPE, -1); + + /* Wait until our parent died. This will only work if + * the above setresuid() succeeds, otherwise the kernel + * will not allow unprivileged parents kill their privileged + * children this way. We rely on the control groups kill logic + * to do the rest for us. */ + if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) + goto child_finish; + + /* Tell the parent that our setup is done. This is especially + * important regarding dropping privileges. Otherwise, unit + * setup might race against our setresuid(2) call. + * + * If the parent aborted, we'll detect this below, hence ignore + * return failure here. */ + (void) barrier_place(&barrier); + + /* Check if our parent process might already have died? */ + if (getppid() == parent_pid) { + sigset_t ss; + + assert_se(sigemptyset(&ss) >= 0); + assert_se(sigaddset(&ss, SIGTERM) >= 0); + + for (;;) { + if (sigwait(&ss, &sig) < 0) { + if (errno == EINTR) + continue; + + goto child_finish; + } + + assert(sig == SIGTERM); + break; + } + } + + /* If our parent died we'll end the session */ + if (getppid() != parent_pid) { + pam_code = pam_close_session(handle, flags); + if (pam_code != PAM_SUCCESS) + goto child_finish; + } + + ret = 0; + + child_finish: + pam_end(handle, pam_code | flags); + _exit(ret); + } + + barrier_set_role(&barrier, BARRIER_PARENT); + + /* If the child was forked off successfully it will do all the + * cleanups, so forget about the handle here. */ + handle = NULL; + + /* Unblock SIGTERM again in the parent */ + assert_se(sigprocmask(SIG_SETMASK, &old_ss, NULL) >= 0); + + /* We close the log explicitly here, since the PAM modules + * might have opened it, but we don't want this fd around. */ + closelog(); + + /* Synchronously wait for the child to initialize. We don't care for + * errors as we cannot recover. However, warn loudly if it happens. */ + if (!barrier_place_and_sync(&barrier)) + log_error("PAM initialization failed"); + + return strv_free_and_replace(*env, e); + +fail: + if (pam_code != PAM_SUCCESS) { + log_error("PAM failed: %s", pam_strerror(handle, pam_code)); + r = -EPERM; /* PAM errors do not map to errno */ + } else + log_error_errno(r, "PAM failed: %m"); + + if (handle) { + if (close_session) + pam_code = pam_close_session(handle, flags); + + pam_end(handle, pam_code | flags); + } + + strv_free(e); + closelog(); + + return r; +#else + return 0; +#endif +} + +static void rename_process_from_path(const char *path) { + char process_name[11]; + const char *p; + size_t l; + + /* This resulting string must fit in 10 chars (i.e. the length + * of "/sbin/init") to look pretty in /bin/ps */ + + p = basename(path); + if (isempty(p)) { + rename_process("(...)"); + return; + } + + l = strlen(p); + if (l > 8) { + /* The end of the process name is usually more + * interesting, since the first bit might just be + * "systemd-" */ + p = p + l - 8; + l = 8; + } + + process_name[0] = '('; + memcpy(process_name+1, p, l); + process_name[1+l] = ')'; + process_name[1+l+1] = 0; + + rename_process(process_name); +} + +static bool context_has_address_families(const ExecContext *c) { + assert(c); + + return c->address_families_whitelist || + !set_isempty(c->address_families); +} + +static bool context_has_syscall_filters(const ExecContext *c) { + assert(c); + + return c->syscall_whitelist || + !hashmap_isempty(c->syscall_filter); +} + +static bool context_has_no_new_privileges(const ExecContext *c) { + assert(c); + + if (c->no_new_privileges) + return true; + + if (have_effective_cap(CAP_SYS_ADMIN)) /* if we are privileged, we don't need NNP */ + return false; + + /* We need NNP if we have any form of seccomp and are unprivileged */ + return context_has_address_families(c) || + c->memory_deny_write_execute || + c->restrict_realtime || + c->restrict_suid_sgid || + exec_context_restrict_namespaces_set(c) || + c->protect_kernel_tunables || + c->protect_kernel_modules || + c->protect_kernel_logs || + c->private_devices || + context_has_syscall_filters(c) || + !set_isempty(c->syscall_archs) || + c->lock_personality || + c->protect_hostname; +} + +#if HAVE_SECCOMP + +static bool skip_seccomp_unavailable(const Unit* u, const char* msg) { + + if (is_seccomp_available()) + return false; + + log_unit_debug(u, "SECCOMP features not detected in the kernel, skipping %s", msg); + return true; +} + +static int apply_syscall_filter(const Unit* u, const ExecContext *c, bool needs_ambient_hack) { + uint32_t negative_action, default_action, action; + int r; + + assert(u); + assert(c); + + if (!context_has_syscall_filters(c)) + return 0; + + if (skip_seccomp_unavailable(u, "SystemCallFilter=")) + return 0; + + negative_action = c->syscall_errno == 0 ? scmp_act_kill_process() : SCMP_ACT_ERRNO(c->syscall_errno); + + if (c->syscall_whitelist) { + default_action = negative_action; + action = SCMP_ACT_ALLOW; + } else { + default_action = SCMP_ACT_ALLOW; + action = negative_action; + } + + if (needs_ambient_hack) { + r = seccomp_filter_set_add(c->syscall_filter, c->syscall_whitelist, syscall_filter_sets + SYSCALL_FILTER_SET_SETUID); + if (r < 0) + return r; + } + + return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action, false); +} + +static int apply_syscall_archs(const Unit *u, const ExecContext *c) { + assert(u); + assert(c); + + if (set_isempty(c->syscall_archs)) + return 0; + + if (skip_seccomp_unavailable(u, "SystemCallArchitectures=")) + return 0; + + return seccomp_restrict_archs(c->syscall_archs); +} + +static int apply_address_families(const Unit* u, const ExecContext *c) { + assert(u); + assert(c); + + if (!context_has_address_families(c)) + return 0; + + if (skip_seccomp_unavailable(u, "RestrictAddressFamilies=")) + return 0; + + return seccomp_restrict_address_families(c->address_families, c->address_families_whitelist); +} + +static int apply_memory_deny_write_execute(const Unit* u, const ExecContext *c) { + assert(u); + assert(c); + + if (!c->memory_deny_write_execute) + return 0; + + if (skip_seccomp_unavailable(u, "MemoryDenyWriteExecute=")) + return 0; + + return seccomp_memory_deny_write_execute(); +} + +static int apply_restrict_realtime(const Unit* u, const ExecContext *c) { + assert(u); + assert(c); + + if (!c->restrict_realtime) + return 0; + + if (skip_seccomp_unavailable(u, "RestrictRealtime=")) + return 0; + + return seccomp_restrict_realtime(); +} + +static int apply_restrict_suid_sgid(const Unit* u, const ExecContext *c) { + assert(u); + assert(c); + + if (!c->restrict_suid_sgid) + return 0; + + if (skip_seccomp_unavailable(u, "RestrictSUIDSGID=")) + return 0; + + return seccomp_restrict_suid_sgid(); +} + +static int apply_protect_sysctl(const Unit *u, const ExecContext *c) { + assert(u); + assert(c); + + /* Turn off the legacy sysctl() system call. Many distributions turn this off while building the kernel, but + * let's protect even those systems where this is left on in the kernel. */ + + if (!c->protect_kernel_tunables) + return 0; + + if (skip_seccomp_unavailable(u, "ProtectKernelTunables=")) + return 0; + + return seccomp_protect_sysctl(); +} + +static int apply_protect_kernel_modules(const Unit *u, const ExecContext *c) { + assert(u); + assert(c); + + /* Turn off module syscalls on ProtectKernelModules=yes */ + + if (!c->protect_kernel_modules) + return 0; + + if (skip_seccomp_unavailable(u, "ProtectKernelModules=")) + return 0; + + return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM), false); +} + +static int apply_protect_kernel_logs(const Unit *u, const ExecContext *c) { + assert(u); + assert(c); + + if (!c->protect_kernel_logs) + return 0; + + if (skip_seccomp_unavailable(u, "ProtectKernelLogs=")) + return 0; + + return seccomp_protect_syslog(); +} + +static int apply_private_devices(const Unit *u, const ExecContext *c) { + assert(u); + assert(c); + + /* If PrivateDevices= is set, also turn off iopl and all @raw-io syscalls. */ + + if (!c->private_devices) + return 0; + + if (skip_seccomp_unavailable(u, "PrivateDevices=")) + return 0; + + return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO, SCMP_ACT_ERRNO(EPERM), false); +} + +static int apply_restrict_namespaces(const Unit *u, const ExecContext *c) { + assert(u); + assert(c); + + if (!exec_context_restrict_namespaces_set(c)) + return 0; + + if (skip_seccomp_unavailable(u, "RestrictNamespaces=")) + return 0; + + return seccomp_restrict_namespaces(c->restrict_namespaces); +} + +static int apply_lock_personality(const Unit* u, const ExecContext *c) { + unsigned long personality; + int r; + + assert(u); + assert(c); + + if (!c->lock_personality) + return 0; + + if (skip_seccomp_unavailable(u, "LockPersonality=")) + return 0; + + personality = c->personality; + + /* If personality is not specified, use either PER_LINUX or PER_LINUX32 depending on what is currently set. */ + if (personality == PERSONALITY_INVALID) { + + r = opinionated_personality(&personality); + if (r < 0) + return r; + } + + return seccomp_lock_personality(personality); +} + +#endif + +static void do_idle_pipe_dance(int idle_pipe[static 4]) { + assert(idle_pipe); + + idle_pipe[1] = safe_close(idle_pipe[1]); + idle_pipe[2] = safe_close(idle_pipe[2]); + + if (idle_pipe[0] >= 0) { + int r; + + r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC); + + if (idle_pipe[3] >= 0 && r == 0 /* timeout */) { + ssize_t n; + + /* Signal systemd that we are bored and want to continue. */ + n = write(idle_pipe[3], "x", 1); + if (n > 0) + /* Wait for systemd to react to the signal above. */ + (void) fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC); + } + + idle_pipe[0] = safe_close(idle_pipe[0]); + + } + + idle_pipe[3] = safe_close(idle_pipe[3]); +} + +static const char *exec_directory_env_name_to_string(ExecDirectoryType t); + +static int build_environment( + const Unit *u, + const ExecContext *c, + const ExecParameters *p, + size_t n_fds, + const char *home, + const char *username, + const char *shell, + dev_t journal_stream_dev, + ino_t journal_stream_ino, + char ***ret) { + + _cleanup_strv_free_ char **our_env = NULL; + ExecDirectoryType t; + size_t n_env = 0; + char *x; + + assert(u); + assert(c); + assert(p); + assert(ret); + + our_env = new0(char*, 14 + _EXEC_DIRECTORY_TYPE_MAX); + if (!our_env) + return -ENOMEM; + + if (n_fds > 0) { + _cleanup_free_ char *joined = NULL; + + if (asprintf(&x, "LISTEN_PID="PID_FMT, getpid_cached()) < 0) + return -ENOMEM; + our_env[n_env++] = x; + + if (asprintf(&x, "LISTEN_FDS=%zu", n_fds) < 0) + return -ENOMEM; + our_env[n_env++] = x; + + joined = strv_join(p->fd_names, ":"); + if (!joined) + return -ENOMEM; + + x = strjoin("LISTEN_FDNAMES=", joined); + if (!x) + return -ENOMEM; + our_env[n_env++] = x; + } + + if ((p->flags & EXEC_SET_WATCHDOG) && p->watchdog_usec > 0) { + if (asprintf(&x, "WATCHDOG_PID="PID_FMT, getpid_cached()) < 0) + return -ENOMEM; + our_env[n_env++] = x; + + if (asprintf(&x, "WATCHDOG_USEC="USEC_FMT, p->watchdog_usec) < 0) + return -ENOMEM; + our_env[n_env++] = x; + } + + /* If this is D-Bus, tell the nss-systemd module, since it relies on being able to use D-Bus look up dynamic + * users via PID 1, possibly dead-locking the dbus daemon. This way it will not use D-Bus to resolve names, but + * check the database directly. */ + if (p->flags & EXEC_NSS_BYPASS_BUS) { + x = strdup("SYSTEMD_NSS_BYPASS_BUS=1"); + if (!x) + return -ENOMEM; + our_env[n_env++] = x; + } + + if (home) { + x = strjoin("HOME=", home); + if (!x) + return -ENOMEM; + + path_simplify(x + 5, true); + our_env[n_env++] = x; + } + + if (username) { + x = strjoin("LOGNAME=", username); + if (!x) + return -ENOMEM; + our_env[n_env++] = x; + + x = strjoin("USER=", username); + if (!x) + return -ENOMEM; + our_env[n_env++] = x; + } + + if (shell) { + x = strjoin("SHELL=", shell); + if (!x) + return -ENOMEM; + + path_simplify(x + 6, true); + our_env[n_env++] = x; + } + + if (!sd_id128_is_null(u->invocation_id)) { + if (asprintf(&x, "INVOCATION_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id)) < 0) + return -ENOMEM; + + our_env[n_env++] = x; + } + + if (exec_context_needs_term(c)) { + const char *tty_path, *term = NULL; + + tty_path = exec_context_tty_path(c); + + /* If we are forked off PID 1 and we are supposed to operate on /dev/console, then let's try to inherit + * the $TERM set for PID 1. This is useful for containers so that the $TERM the container manager + * passes to PID 1 ends up all the way in the console login shown. */ + + if (path_equal(tty_path, "/dev/console") && getppid() == 1) + term = getenv("TERM"); + if (!term) + term = default_term_for_tty(tty_path); + + x = strjoin("TERM=", term); + if (!x) + return -ENOMEM; + our_env[n_env++] = x; + } + + if (journal_stream_dev != 0 && journal_stream_ino != 0) { + if (asprintf(&x, "JOURNAL_STREAM=" DEV_FMT ":" INO_FMT, journal_stream_dev, journal_stream_ino) < 0) + return -ENOMEM; + + our_env[n_env++] = x; + } + + for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { + _cleanup_free_ char *pre = NULL, *joined = NULL; + const char *n; + + if (!p->prefix[t]) + continue; + + if (strv_isempty(c->directories[t].paths)) + continue; + + n = exec_directory_env_name_to_string(t); + if (!n) + continue; + + pre = strjoin(p->prefix[t], "/"); + if (!pre) + return -ENOMEM; + + joined = strv_join_prefix(c->directories[t].paths, ":", pre); + if (!joined) + return -ENOMEM; + + x = strjoin(n, "=", joined); + if (!x) + return -ENOMEM; + + our_env[n_env++] = x; + } + + our_env[n_env++] = NULL; + assert(n_env <= 14 + _EXEC_DIRECTORY_TYPE_MAX); + + *ret = TAKE_PTR(our_env); + + return 0; +} + +static int build_pass_environment(const ExecContext *c, char ***ret) { + _cleanup_strv_free_ char **pass_env = NULL; + size_t n_env = 0, n_bufsize = 0; + char **i; + + STRV_FOREACH(i, c->pass_environment) { + _cleanup_free_ char *x = NULL; + char *v; + + v = getenv(*i); + if (!v) + continue; + x = strjoin(*i, "=", v); + if (!x) + return -ENOMEM; + + if (!GREEDY_REALLOC(pass_env, n_bufsize, n_env + 2)) + return -ENOMEM; + + pass_env[n_env++] = TAKE_PTR(x); + pass_env[n_env] = NULL; + } + + *ret = TAKE_PTR(pass_env); + + return 0; +} + +static bool exec_needs_mount_namespace( + const ExecContext *context, + const ExecParameters *params, + const ExecRuntime *runtime) { + + assert(context); + assert(params); + + if (context->root_image) + return true; + + if (!strv_isempty(context->read_write_paths) || + !strv_isempty(context->read_only_paths) || + !strv_isempty(context->inaccessible_paths)) + return true; + + if (context->n_bind_mounts > 0) + return true; + + if (context->n_temporary_filesystems > 0) + return true; + + if (!IN_SET(context->mount_flags, 0, MS_SHARED)) + return true; + + if (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir)) + return true; + + if (context->private_devices || + context->private_mounts || + context->protect_system != PROTECT_SYSTEM_NO || + context->protect_home != PROTECT_HOME_NO || + context->protect_kernel_tunables || + context->protect_kernel_modules || + context->protect_kernel_logs || + context->protect_control_groups) + return true; + + if (context->root_directory) { + ExecDirectoryType t; + + if (context->mount_apivfs) + return true; + + for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { + if (!params->prefix[t]) + continue; + + if (!strv_isempty(context->directories[t].paths)) + return true; + } + } + + if (context->dynamic_user && + (!strv_isempty(context->directories[EXEC_DIRECTORY_STATE].paths) || + !strv_isempty(context->directories[EXEC_DIRECTORY_CACHE].paths) || + !strv_isempty(context->directories[EXEC_DIRECTORY_LOGS].paths))) + return true; + + return false; +} + +static int setup_private_users(uid_t uid, gid_t gid) { + _cleanup_free_ char *uid_map = NULL, *gid_map = NULL; + _cleanup_close_pair_ int errno_pipe[2] = { -1, -1 }; + _cleanup_close_ int unshare_ready_fd = -1; + _cleanup_(sigkill_waitp) pid_t pid = 0; + uint64_t c = 1; + ssize_t n; + int r; + + /* Set up a user namespace and map root to root, the selected UID/GID to itself, and everything else to + * nobody. In order to be able to write this mapping we need CAP_SETUID in the original user namespace, which + * we however lack after opening the user namespace. To work around this we fork() a temporary child process, + * which waits for the parent to create the new user namespace while staying in the original namespace. The + * child then writes the UID mapping, under full privileges. The parent waits for the child to finish and + * continues execution normally. */ + + if (uid != 0 && uid_is_valid(uid)) { + r = asprintf(&uid_map, + "0 0 1\n" /* Map root → root */ + UID_FMT " " UID_FMT " 1\n", /* Map $UID → $UID */ + uid, uid); + if (r < 0) + return -ENOMEM; + } else { + uid_map = strdup("0 0 1\n"); /* The case where the above is the same */ + if (!uid_map) + return -ENOMEM; + } + + if (gid != 0 && gid_is_valid(gid)) { + r = asprintf(&gid_map, + "0 0 1\n" /* Map root → root */ + GID_FMT " " GID_FMT " 1\n", /* Map $GID → $GID */ + gid, gid); + if (r < 0) + return -ENOMEM; + } else { + gid_map = strdup("0 0 1\n"); /* The case where the above is the same */ + if (!gid_map) + return -ENOMEM; + } + + /* Create a communication channel so that the parent can tell the child when it finished creating the user + * namespace. */ + unshare_ready_fd = eventfd(0, EFD_CLOEXEC); + if (unshare_ready_fd < 0) + return -errno; + + /* Create a communication channel so that the child can tell the parent a proper error code in case it + * failed. */ + if (pipe2(errno_pipe, O_CLOEXEC) < 0) + return -errno; + + r = safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid); + if (r < 0) + return r; + if (r == 0) { + _cleanup_close_ int fd = -1; + const char *a; + pid_t ppid; + + /* Child process, running in the original user namespace. Let's update the parent's UID/GID map from + * here, after the parent opened its own user namespace. */ + + ppid = getppid(); + errno_pipe[0] = safe_close(errno_pipe[0]); + + /* Wait until the parent unshared the user namespace */ + if (read(unshare_ready_fd, &c, sizeof(c)) < 0) { + r = -errno; + goto child_fail; + } + + /* Disable the setgroups() system call in the child user namespace, for good. */ + a = procfs_file_alloca(ppid, "setgroups"); + fd = open(a, O_WRONLY|O_CLOEXEC); + if (fd < 0) { + if (errno != ENOENT) { + r = -errno; + goto child_fail; + } + + /* If the file is missing the kernel is too old, let's continue anyway. */ + } else { + if (write(fd, "deny\n", 5) < 0) { + r = -errno; + goto child_fail; + } + + fd = safe_close(fd); + } + + /* First write the GID map */ + a = procfs_file_alloca(ppid, "gid_map"); + fd = open(a, O_WRONLY|O_CLOEXEC); + if (fd < 0) { + r = -errno; + goto child_fail; + } + if (write(fd, gid_map, strlen(gid_map)) < 0) { + r = -errno; + goto child_fail; + } + fd = safe_close(fd); + + /* The write the UID map */ + a = procfs_file_alloca(ppid, "uid_map"); + fd = open(a, O_WRONLY|O_CLOEXEC); + if (fd < 0) { + r = -errno; + goto child_fail; + } + if (write(fd, uid_map, strlen(uid_map)) < 0) { + r = -errno; + goto child_fail; + } + + _exit(EXIT_SUCCESS); + + child_fail: + (void) write(errno_pipe[1], &r, sizeof(r)); + _exit(EXIT_FAILURE); + } + + errno_pipe[1] = safe_close(errno_pipe[1]); + + if (unshare(CLONE_NEWUSER) < 0) + return -errno; + + /* Let the child know that the namespace is ready now */ + if (write(unshare_ready_fd, &c, sizeof(c)) < 0) + return -errno; + + /* Try to read an error code from the child */ + n = read(errno_pipe[0], &r, sizeof(r)); + if (n < 0) + return -errno; + if (n == sizeof(r)) { /* an error code was sent to us */ + if (r < 0) + return r; + return -EIO; + } + if (n != 0) /* on success we should have read 0 bytes */ + return -EIO; + + r = wait_for_terminate_and_check("(sd-userns)", pid, 0); + pid = 0; + if (r < 0) + return r; + if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */ + return -EIO; + + return 0; +} + +static bool exec_directory_is_private(const ExecContext *context, ExecDirectoryType type) { + if (!context->dynamic_user) + return false; + + if (type == EXEC_DIRECTORY_CONFIGURATION) + return false; + + if (type == EXEC_DIRECTORY_RUNTIME && context->runtime_directory_preserve_mode == EXEC_PRESERVE_NO) + return false; + + return true; +} + +static int setup_exec_directory( + const ExecContext *context, + const ExecParameters *params, + uid_t uid, + gid_t gid, + ExecDirectoryType type, + int *exit_status) { + + static const int exit_status_table[_EXEC_DIRECTORY_TYPE_MAX] = { + [EXEC_DIRECTORY_RUNTIME] = EXIT_RUNTIME_DIRECTORY, + [EXEC_DIRECTORY_STATE] = EXIT_STATE_DIRECTORY, + [EXEC_DIRECTORY_CACHE] = EXIT_CACHE_DIRECTORY, + [EXEC_DIRECTORY_LOGS] = EXIT_LOGS_DIRECTORY, + [EXEC_DIRECTORY_CONFIGURATION] = EXIT_CONFIGURATION_DIRECTORY, + }; + char **rt; + int r; + + assert(context); + assert(params); + assert(type >= 0 && type < _EXEC_DIRECTORY_TYPE_MAX); + assert(exit_status); + + if (!params->prefix[type]) + return 0; + + if (params->flags & EXEC_CHOWN_DIRECTORIES) { + if (!uid_is_valid(uid)) + uid = 0; + if (!gid_is_valid(gid)) + gid = 0; + } + + STRV_FOREACH(rt, context->directories[type].paths) { + _cleanup_free_ char *p = NULL, *pp = NULL; + + p = path_join(params->prefix[type], *rt); + if (!p) { + r = -ENOMEM; + goto fail; + } + + r = mkdir_parents_label(p, 0755); + if (r < 0) + goto fail; + + if (exec_directory_is_private(context, type)) { + _cleanup_free_ char *private_root = NULL; + + /* So, here's one extra complication when dealing with DynamicUser=1 units. In that + * case we want to avoid leaving a directory around fully accessible that is owned by + * a dynamic user whose UID is later on reused. To lock this down we use the same + * trick used by container managers to prohibit host users to get access to files of + * the same UID in containers: we place everything inside a directory that has an + * access mode of 0700 and is owned root:root, so that it acts as security boundary + * for unprivileged host code. We then use fs namespacing to make this directory + * permeable for the service itself. + * + * Specifically: for a service which wants a special directory "foo/" we first create + * a directory "private/" with access mode 0700 owned by root:root. Then we place + * "foo" inside of that directory (i.e. "private/foo/"), and make "foo" a symlink to + * "private/foo". This way, privileged host users can access "foo/" as usual, but + * unprivileged host users can't look into it. Inside of the namespace of the unit + * "private/" is replaced by a more liberally accessible tmpfs, into which the host's + * "private/foo/" is mounted under the same name, thus disabling the access boundary + * for the service and making sure it only gets access to the dirs it needs but no + * others. Tricky? Yes, absolutely, but it works! + * + * Note that we don't do this for EXEC_DIRECTORY_CONFIGURATION as that's assumed not + * to be owned by the service itself. + * + * Also, note that we don't do this for EXEC_DIRECTORY_RUNTIME as that's often used + * for sharing files or sockets with other services. */ + + private_root = path_join(params->prefix[type], "private"); + if (!private_root) { + r = -ENOMEM; + goto fail; + } + + /* First set up private root if it doesn't exist yet, with access mode 0700 and owned by root:root */ + r = mkdir_safe_label(private_root, 0700, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + goto fail; + + pp = path_join(private_root, *rt); + if (!pp) { + r = -ENOMEM; + goto fail; + } + + /* Create all directories between the configured directory and this private root, and mark them 0755 */ + r = mkdir_parents_label(pp, 0755); + if (r < 0) + goto fail; + + if (is_dir(p, false) > 0 && + (laccess(pp, F_OK) < 0 && errno == ENOENT)) { + + /* Hmm, the private directory doesn't exist yet, but the normal one exists? If so, move + * it over. Most likely the service has been upgraded from one that didn't use + * DynamicUser=1, to one that does. */ + + log_info("Found pre-existing public %s= directory %s, migrating to %s.\n" + "Apparently, service previously had DynamicUser= turned off, and has now turned it on.", + exec_directory_type_to_string(type), p, pp); + + if (rename(p, pp) < 0) { + r = -errno; + goto fail; + } + } else { + /* Otherwise, create the actual directory for the service */ + + r = mkdir_label(pp, context->directories[type].mode); + if (r < 0 && r != -EEXIST) + goto fail; + } + + /* And link it up from the original place */ + r = symlink_idempotent(pp, p, true); + if (r < 0) + goto fail; + + } else { + _cleanup_free_ char *target = NULL; + + if (type != EXEC_DIRECTORY_CONFIGURATION && + readlink_and_make_absolute(p, &target) >= 0) { + _cleanup_free_ char *q = NULL; + + /* This already exists and is a symlink? Interesting. Maybe it's one created + * by DynamicUser=1 (see above)? + * + * We do this for all directory types except for ConfigurationDirectory=, + * since they all support the private/ symlink logic at least in some + * configurations, see above. */ + + q = path_join(params->prefix[type], "private", *rt); + if (!q) { + r = -ENOMEM; + goto fail; + } + + if (path_equal(q, target)) { + + /* Hmm, apparently DynamicUser= was once turned on for this service, + * but is no longer. Let's move the directory back up. */ + + log_info("Found pre-existing private %s= directory %s, migrating to %s.\n" + "Apparently, service previously had DynamicUser= turned on, and has now turned it off.", + exec_directory_type_to_string(type), q, p); + + if (unlink(p) < 0) { + r = -errno; + goto fail; + } + + if (rename(q, p) < 0) { + r = -errno; + goto fail; + } + } + } + + r = mkdir_label(p, context->directories[type].mode); + if (r < 0) { + if (r != -EEXIST) + goto fail; + + if (type == EXEC_DIRECTORY_CONFIGURATION) { + struct stat st; + + /* Don't change the owner/access mode of the configuration directory, + * as in the common case it is not written to by a service, and shall + * not be writable. */ + + if (stat(p, &st) < 0) { + r = -errno; + goto fail; + } + + /* Still complain if the access mode doesn't match */ + if (((st.st_mode ^ context->directories[type].mode) & 07777) != 0) + log_warning("%s \'%s\' already exists but the mode is different. " + "(File system: %o %sMode: %o)", + exec_directory_type_to_string(type), *rt, + st.st_mode & 07777, exec_directory_type_to_string(type), context->directories[type].mode & 07777); + + continue; + } + } + } + + /* Lock down the access mode (we use chmod_and_chown() to make this idempotent. We don't + * specify UID/GID here, so that path_chown_recursive() can optimize things depending on the + * current UID/GID ownership.) */ + r = chmod_and_chown(pp ?: p, context->directories[type].mode, UID_INVALID, GID_INVALID); + if (r < 0) + goto fail; + + /* Then, change the ownership of the whole tree, if necessary. When dynamic users are used we + * drop the suid/sgid bits, since we really don't want SUID/SGID files for dynamic UID/GID + * assignments to exist.*/ + r = path_chown_recursive(pp ?: p, uid, gid, context->dynamic_user ? 01777 : 07777); + if (r < 0) + goto fail; + } + + return 0; + +fail: + *exit_status = exit_status_table[type]; + return r; +} + +#if ENABLE_SMACK +static int setup_smack( + const ExecContext *context, + const ExecCommand *command) { + + int r; + + assert(context); + assert(command); + + if (context->smack_process_label) { + r = mac_smack_apply_pid(0, context->smack_process_label); + if (r < 0) + return r; + } +#ifdef SMACK_DEFAULT_PROCESS_LABEL + else { + _cleanup_free_ char *exec_label = NULL; + + r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label); + if (r < 0 && !IN_SET(r, -ENODATA, -EOPNOTSUPP)) + return r; + + r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL); + if (r < 0) + return r; + } +#endif + + return 0; +} +#endif + +static int compile_bind_mounts( + const ExecContext *context, + const ExecParameters *params, + BindMount **ret_bind_mounts, + size_t *ret_n_bind_mounts, + char ***ret_empty_directories) { + + _cleanup_strv_free_ char **empty_directories = NULL; + BindMount *bind_mounts; + size_t n, h = 0, i; + ExecDirectoryType t; + int r; + + assert(context); + assert(params); + assert(ret_bind_mounts); + assert(ret_n_bind_mounts); + assert(ret_empty_directories); + + n = context->n_bind_mounts; + for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { + if (!params->prefix[t]) + continue; + + n += strv_length(context->directories[t].paths); + } + + if (n <= 0) { + *ret_bind_mounts = NULL; + *ret_n_bind_mounts = 0; + *ret_empty_directories = NULL; + return 0; + } + + bind_mounts = new(BindMount, n); + if (!bind_mounts) + return -ENOMEM; + + for (i = 0; i < context->n_bind_mounts; i++) { + BindMount *item = context->bind_mounts + i; + char *s, *d; + + s = strdup(item->source); + if (!s) { + r = -ENOMEM; + goto finish; + } + + d = strdup(item->destination); + if (!d) { + free(s); + r = -ENOMEM; + goto finish; + } + + bind_mounts[h++] = (BindMount) { + .source = s, + .destination = d, + .read_only = item->read_only, + .recursive = item->recursive, + .ignore_enoent = item->ignore_enoent, + }; + } + + for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { + char **suffix; + + if (!params->prefix[t]) + continue; + + if (strv_isempty(context->directories[t].paths)) + continue; + + if (exec_directory_is_private(context, t) && + !(context->root_directory || context->root_image)) { + char *private_root; + + /* So this is for a dynamic user, and we need to make sure the process can access its own + * directory. For that we overmount the usually inaccessible "private" subdirectory with a + * tmpfs that makes it accessible and is empty except for the submounts we do this for. */ + + private_root = path_join(params->prefix[t], "private"); + if (!private_root) { + r = -ENOMEM; + goto finish; + } + + r = strv_consume(&empty_directories, private_root); + if (r < 0) + goto finish; + } + + STRV_FOREACH(suffix, context->directories[t].paths) { + char *s, *d; + + if (exec_directory_is_private(context, t)) + s = path_join(params->prefix[t], "private", *suffix); + else + s = path_join(params->prefix[t], *suffix); + if (!s) { + r = -ENOMEM; + goto finish; + } + + if (exec_directory_is_private(context, t) && + (context->root_directory || context->root_image)) + /* When RootDirectory= or RootImage= are set, then the symbolic link to the private + * directory is not created on the root directory. So, let's bind-mount the directory + * on the 'non-private' place. */ + d = path_join(params->prefix[t], *suffix); + else + d = strdup(s); + if (!d) { + free(s); + r = -ENOMEM; + goto finish; + } + + bind_mounts[h++] = (BindMount) { + .source = s, + .destination = d, + .read_only = false, + .nosuid = context->dynamic_user, /* don't allow suid/sgid when DynamicUser= is on */ + .recursive = true, + .ignore_enoent = false, + }; + } + } + + assert(h == n); + + *ret_bind_mounts = bind_mounts; + *ret_n_bind_mounts = n; + *ret_empty_directories = TAKE_PTR(empty_directories); + + return (int) n; + +finish: + bind_mount_free_many(bind_mounts, h); + return r; +} + +static bool insist_on_sandboxing( + const ExecContext *context, + const char *root_dir, + const char *root_image, + const BindMount *bind_mounts, + size_t n_bind_mounts) { + + size_t i; + + assert(context); + assert(n_bind_mounts == 0 || bind_mounts); + + /* Checks whether we need to insist on fs namespacing. i.e. whether we have settings configured that + * would alter the view on the file system beyond making things read-only or invisble, i.e. would + * rearrange stuff in a way we cannot ignore gracefully. */ + + if (context->n_temporary_filesystems > 0) + return true; + + if (root_dir || root_image) + return true; + + if (context->dynamic_user) + return true; + + /* If there are any bind mounts set that don't map back onto themselves, fs namespacing becomes + * essential. */ + for (i = 0; i < n_bind_mounts; i++) + if (!path_equal(bind_mounts[i].source, bind_mounts[i].destination)) + return true; + + return false; +} + +static int apply_mount_namespace( + const Unit *u, + const ExecCommand *command, + const ExecContext *context, + const ExecParameters *params, + const ExecRuntime *runtime, + char **error_path) { + + _cleanup_strv_free_ char **empty_directories = NULL; + char *tmp = NULL, *var = NULL; + const char *root_dir = NULL, *root_image = NULL; + NamespaceInfo ns_info; + bool needs_sandboxing; + BindMount *bind_mounts = NULL; + size_t n_bind_mounts = 0; + int r; + + assert(context); + + /* The runtime struct only contains the parent of the private /tmp, + * which is non-accessible to world users. Inside of it there's a /tmp + * that is sticky, and that's the one we want to use here. */ + + if (context->private_tmp && runtime) { + if (runtime->tmp_dir) + tmp = strjoina(runtime->tmp_dir, "/tmp"); + if (runtime->var_tmp_dir) + var = strjoina(runtime->var_tmp_dir, "/tmp"); + } + + if (params->flags & EXEC_APPLY_CHROOT) { + root_image = context->root_image; + + if (!root_image) + root_dir = context->root_directory; + } + + r = compile_bind_mounts(context, params, &bind_mounts, &n_bind_mounts, &empty_directories); + if (r < 0) + return r; + + needs_sandboxing = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & EXEC_COMMAND_FULLY_PRIVILEGED); + if (needs_sandboxing) + ns_info = (NamespaceInfo) { + .ignore_protect_paths = false, + .private_dev = context->private_devices, + .protect_control_groups = context->protect_control_groups, + .protect_kernel_tunables = context->protect_kernel_tunables, + .protect_kernel_modules = context->protect_kernel_modules, + .protect_kernel_logs = context->protect_kernel_logs, + .protect_hostname = context->protect_hostname, + .mount_apivfs = context->mount_apivfs, + .private_mounts = context->private_mounts, + }; + else if (!context->dynamic_user && root_dir) + /* + * If DynamicUser=no and RootDirectory= is set then lets pass a relaxed + * sandbox info, otherwise enforce it, don't ignore protected paths and + * fail if we are enable to apply the sandbox inside the mount namespace. + */ + ns_info = (NamespaceInfo) { + .ignore_protect_paths = true, + }; + else + ns_info = (NamespaceInfo) {}; + + if (context->mount_flags == MS_SHARED) + log_unit_debug(u, "shared mount propagation hidden by other fs namespacing unit settings: ignoring"); + + r = setup_namespace(root_dir, root_image, + &ns_info, context->read_write_paths, + needs_sandboxing ? context->read_only_paths : NULL, + needs_sandboxing ? context->inaccessible_paths : NULL, + empty_directories, + bind_mounts, + n_bind_mounts, + context->temporary_filesystems, + context->n_temporary_filesystems, + tmp, + var, + needs_sandboxing ? context->protect_home : PROTECT_HOME_NO, + needs_sandboxing ? context->protect_system : PROTECT_SYSTEM_NO, + context->mount_flags, + DISSECT_IMAGE_DISCARD_ON_LOOP, + error_path); + + /* If we couldn't set up the namespace this is probably due to a missing capability. setup_namespace() reports + * that with a special, recognizable error ENOANO. In this case, silently proceed, but only if exclusively + * sandboxing options were used, i.e. nothing such as RootDirectory= or BindMount= that would result in a + * completely different execution environment. */ + if (r == -ENOANO) { + if (insist_on_sandboxing( + context, + root_dir, root_image, + bind_mounts, + n_bind_mounts)) { + log_unit_debug(u, "Failed to set up namespace, and refusing to continue since the selected namespacing options alter mount environment non-trivially.\n" + "Bind mounts: %zu, temporary filesystems: %zu, root directory: %s, root image: %s, dynamic user: %s", + n_bind_mounts, context->n_temporary_filesystems, yes_no(root_dir), yes_no(root_image), yes_no(context->dynamic_user)); + + r = -EOPNOTSUPP; + } else { + log_unit_debug(u, "Failed to set up namespace, assuming containerized execution and ignoring."); + r = 0; + } + } + + bind_mount_free_many(bind_mounts, n_bind_mounts); + return r; +} + +static int apply_working_directory( + const ExecContext *context, + const ExecParameters *params, + const char *home, + int *exit_status) { + + const char *d, *wd; + + assert(context); + assert(exit_status); + + if (context->working_directory_home) { + + if (!home) { + *exit_status = EXIT_CHDIR; + return -ENXIO; + } + + wd = home; + + } else if (context->working_directory) + wd = context->working_directory; + else + wd = "/"; + + if (params->flags & EXEC_APPLY_CHROOT) + d = wd; + else + d = prefix_roota(context->root_directory, wd); + + if (chdir(d) < 0 && !context->working_directory_missing_ok) { + *exit_status = EXIT_CHDIR; + return -errno; + } + + return 0; +} + +static int apply_root_directory( + const ExecContext *context, + const ExecParameters *params, + const bool needs_mount_ns, + int *exit_status) { + + assert(context); + assert(exit_status); + + if (params->flags & EXEC_APPLY_CHROOT) { + if (!needs_mount_ns && context->root_directory) + if (chroot(context->root_directory) < 0) { + *exit_status = EXIT_CHROOT; + return -errno; + } + } + + return 0; +} + +static int setup_keyring( + const Unit *u, + const ExecContext *context, + const ExecParameters *p, + uid_t uid, gid_t gid) { + + key_serial_t keyring; + int r = 0; + uid_t saved_uid; + gid_t saved_gid; + + assert(u); + assert(context); + assert(p); + + /* Let's set up a new per-service "session" kernel keyring for each system service. This has the benefit that + * each service runs with its own keyring shared among all processes of the service, but with no hook-up beyond + * that scope, and in particular no link to the per-UID keyring. If we don't do this the keyring will be + * automatically created on-demand and then linked to the per-UID keyring, by the kernel. The kernel's built-in + * on-demand behaviour is very appropriate for login users, but probably not so much for system services, where + * UIDs are not necessarily specific to a service but reused (at least in the case of UID 0). */ + + if (context->keyring_mode == EXEC_KEYRING_INHERIT) + return 0; + + /* Acquiring a reference to the user keyring is nasty. We briefly change identity in order to get things set up + * properly by the kernel. If we don't do that then we can't create it atomically, and that sucks for parallel + * execution. This mimics what pam_keyinit does, too. Setting up session keyring, to be owned by the right user + * & group is just as nasty as acquiring a reference to the user keyring. */ + + saved_uid = getuid(); + saved_gid = getgid(); + + if (gid_is_valid(gid) && gid != saved_gid) { + if (setregid(gid, -1) < 0) + return log_unit_error_errno(u, errno, "Failed to change GID for user keyring: %m"); + } + + if (uid_is_valid(uid) && uid != saved_uid) { + if (setreuid(uid, -1) < 0) { + r = log_unit_error_errno(u, errno, "Failed to change UID for user keyring: %m"); + goto out; + } + } + + keyring = keyctl(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0); + if (keyring == -1) { + if (errno == ENOSYS) + log_unit_debug_errno(u, errno, "Kernel keyring not supported, ignoring."); + else if (IN_SET(errno, EACCES, EPERM)) + log_unit_debug_errno(u, errno, "Kernel keyring access prohibited, ignoring."); + else if (errno == EDQUOT) + log_unit_debug_errno(u, errno, "Out of kernel keyrings to allocate, ignoring."); + else + r = log_unit_error_errno(u, errno, "Setting up kernel keyring failed: %m"); + + goto out; + } + + /* When requested link the user keyring into the session keyring. */ + if (context->keyring_mode == EXEC_KEYRING_SHARED) { + + if (keyctl(KEYCTL_LINK, + KEY_SPEC_USER_KEYRING, + KEY_SPEC_SESSION_KEYRING, 0, 0) < 0) { + r = log_unit_error_errno(u, errno, "Failed to link user keyring into session keyring: %m"); + goto out; + } + } + + /* Restore uid/gid back */ + if (uid_is_valid(uid) && uid != saved_uid) { + if (setreuid(saved_uid, -1) < 0) { + r = log_unit_error_errno(u, errno, "Failed to change UID back for user keyring: %m"); + goto out; + } + } + + if (gid_is_valid(gid) && gid != saved_gid) { + if (setregid(saved_gid, -1) < 0) + return log_unit_error_errno(u, errno, "Failed to change GID back for user keyring: %m"); + } + + /* Populate they keyring with the invocation ID by default, as original saved_uid. */ + if (!sd_id128_is_null(u->invocation_id)) { + key_serial_t key; + + key = add_key("user", "invocation_id", &u->invocation_id, sizeof(u->invocation_id), KEY_SPEC_SESSION_KEYRING); + if (key == -1) + log_unit_debug_errno(u, errno, "Failed to add invocation ID to keyring, ignoring: %m"); + else { + if (keyctl(KEYCTL_SETPERM, key, + KEY_POS_VIEW|KEY_POS_READ|KEY_POS_SEARCH| + KEY_USR_VIEW|KEY_USR_READ|KEY_USR_SEARCH, 0, 0) < 0) + r = log_unit_error_errno(u, errno, "Failed to restrict invocation ID permission: %m"); + } + } + +out: + /* Revert back uid & gid for the the last time, and exit */ + /* no extra logging, as only the first already reported error matters */ + if (getuid() != saved_uid) + (void) setreuid(saved_uid, -1); + + if (getgid() != saved_gid) + (void) setregid(saved_gid, -1); + + return r; +} + +static void append_socket_pair(int *array, size_t *n, const int pair[static 2]) { + assert(array); + assert(n); + assert(pair); + + if (pair[0] >= 0) + array[(*n)++] = pair[0]; + if (pair[1] >= 0) + array[(*n)++] = pair[1]; +} + +static int close_remaining_fds( + const ExecParameters *params, + const ExecRuntime *runtime, + const DynamicCreds *dcreds, + int user_lookup_fd, + int socket_fd, + int exec_fd, + int *fds, size_t n_fds) { + + size_t n_dont_close = 0; + int dont_close[n_fds + 12]; + + assert(params); + + if (params->stdin_fd >= 0) + dont_close[n_dont_close++] = params->stdin_fd; + if (params->stdout_fd >= 0) + dont_close[n_dont_close++] = params->stdout_fd; + if (params->stderr_fd >= 0) + dont_close[n_dont_close++] = params->stderr_fd; + + if (socket_fd >= 0) + dont_close[n_dont_close++] = socket_fd; + if (exec_fd >= 0) + dont_close[n_dont_close++] = exec_fd; + if (n_fds > 0) { + memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds); + n_dont_close += n_fds; + } + + if (runtime) + append_socket_pair(dont_close, &n_dont_close, runtime->netns_storage_socket); + + if (dcreds) { + if (dcreds->user) + append_socket_pair(dont_close, &n_dont_close, dcreds->user->storage_socket); + if (dcreds->group) + append_socket_pair(dont_close, &n_dont_close, dcreds->group->storage_socket); + } + + if (user_lookup_fd >= 0) + dont_close[n_dont_close++] = user_lookup_fd; + + return close_all_fds(dont_close, n_dont_close); +} + +static int send_user_lookup( + Unit *unit, + int user_lookup_fd, + uid_t uid, + gid_t gid) { + + assert(unit); + + /* Send the resolved UID/GID to PID 1 after we learnt it. We send a single datagram, containing the UID/GID + * data as well as the unit name. Note that we suppress sending this if no user/group to resolve was + * specified. */ + + if (user_lookup_fd < 0) + return 0; + + if (!uid_is_valid(uid) && !gid_is_valid(gid)) + return 0; + + if (writev(user_lookup_fd, + (struct iovec[]) { + IOVEC_INIT(&uid, sizeof(uid)), + IOVEC_INIT(&gid, sizeof(gid)), + IOVEC_INIT_STRING(unit->id) }, 3) < 0) + return -errno; + + return 0; +} + +static int acquire_home(const ExecContext *c, uid_t uid, const char** home, char **buf) { + int r; + + assert(c); + assert(home); + assert(buf); + + /* If WorkingDirectory=~ is set, try to acquire a usable home directory. */ + + if (*home) + return 0; + + if (!c->working_directory_home) + return 0; + + r = get_home_dir(buf); + if (r < 0) + return r; + + *home = *buf; + return 1; +} + +static int compile_suggested_paths(const ExecContext *c, const ExecParameters *p, char ***ret) { + _cleanup_strv_free_ char ** list = NULL; + ExecDirectoryType t; + int r; + + assert(c); + assert(p); + assert(ret); + + assert(c->dynamic_user); + + /* Compile a list of paths that it might make sense to read the owning UID from to use as initial candidate for + * dynamic UID allocation, in order to save us from doing costly recursive chown()s of the special + * directories. */ + + for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { + char **i; + + if (t == EXEC_DIRECTORY_CONFIGURATION) + continue; + + if (!p->prefix[t]) + continue; + + STRV_FOREACH(i, c->directories[t].paths) { + char *e; + + if (exec_directory_is_private(c, t)) + e = path_join(p->prefix[t], "private", *i); + else + e = path_join(p->prefix[t], *i); + if (!e) + return -ENOMEM; + + r = strv_consume(&list, e); + if (r < 0) + return r; + } + } + + *ret = TAKE_PTR(list); + + return 0; +} + +static char *exec_command_line(char **argv); + +static int exec_parameters_get_cgroup_path(const ExecParameters *params, char **ret) { + bool using_subcgroup; + char *p; + + assert(params); + assert(ret); + + if (!params->cgroup_path) + return -EINVAL; + + /* If we are called for a unit where cgroup delegation is on, and the payload created its own populated + * subcgroup (which we expect it to do, after all it asked for delegation), then we cannot place the control + * processes started after the main unit's process in the unit's main cgroup because it is now an inner one, + * and inner cgroups may not contain processes. Hence, if delegation is on, and this is a control process, + * let's use ".control" as subcgroup instead. Note that we do so only for ExecStartPost=, ExecReload=, + * ExecStop=, ExecStopPost=, i.e. for the commands where the main process is already forked. For ExecStartPre= + * this is not necessary, the cgroup is still empty. We distinguish these cases with the EXEC_CONTROL_CGROUP + * flag, which is only passed for the former statements, not for the latter. */ + + using_subcgroup = FLAGS_SET(params->flags, EXEC_CONTROL_CGROUP|EXEC_CGROUP_DELEGATE|EXEC_IS_CONTROL); + if (using_subcgroup) + p = path_join(params->cgroup_path, ".control"); + else + p = strdup(params->cgroup_path); + if (!p) + return -ENOMEM; + + *ret = p; + return using_subcgroup; +} + +static int exec_child( + Unit *unit, + const ExecCommand *command, + const ExecContext *context, + const ExecParameters *params, + ExecRuntime *runtime, + DynamicCreds *dcreds, + int socket_fd, + const int named_iofds[static 3], + int *fds, + size_t n_socket_fds, + size_t n_storage_fds, + char **files_env, + int user_lookup_fd, + int *exit_status) { + + _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **replaced_argv = NULL; + int *fds_with_exec_fd, n_fds_with_exec_fd, r, ngids = 0, exec_fd = -1; + _cleanup_free_ gid_t *supplementary_gids = NULL; + const char *username = NULL, *groupname = NULL; + _cleanup_free_ char *home_buffer = NULL; + const char *home = NULL, *shell = NULL; + char **final_argv = NULL; + dev_t journal_stream_dev = 0; + ino_t journal_stream_ino = 0; + bool needs_sandboxing, /* Do we need to set up full sandboxing? (i.e. all namespacing, all MAC stuff, caps, yadda yadda */ + needs_setuid, /* Do we need to do the actual setresuid()/setresgid() calls? */ + needs_mount_namespace, /* Do we need to set up a mount namespace for this kernel? */ + needs_ambient_hack; /* Do we need to apply the ambient capabilities hack? */ +#if HAVE_SELINUX + _cleanup_free_ char *mac_selinux_context_net = NULL; + bool use_selinux = false; +#endif +#if ENABLE_SMACK + bool use_smack = false; +#endif +#if HAVE_APPARMOR + bool use_apparmor = false; +#endif + uid_t uid = UID_INVALID; + gid_t gid = GID_INVALID; + size_t n_fds; + ExecDirectoryType dt; + int secure_bits; + + assert(unit); + assert(command); + assert(context); + assert(params); + assert(exit_status); + + rename_process_from_path(command->path); + + /* We reset exactly these signals, since they are the + * only ones we set to SIG_IGN in the main daemon. All + * others we leave untouched because we set them to + * SIG_DFL or a valid handler initially, both of which + * will be demoted to SIG_DFL. */ + (void) default_signals(SIGNALS_CRASH_HANDLER, + SIGNALS_IGNORE, -1); + + if (context->ignore_sigpipe) + (void) ignore_signals(SIGPIPE, -1); + + r = reset_signal_mask(); + if (r < 0) { + *exit_status = EXIT_SIGNAL_MASK; + return log_unit_error_errno(unit, r, "Failed to set process signal mask: %m"); + } + + if (params->idle_pipe) + do_idle_pipe_dance(params->idle_pipe); + + /* Close fds we don't need very early to make sure we don't block init reexecution because it cannot bind its + * sockets. Among the fds we close are the logging fds, and we want to keep them closed, so that we don't have + * any fds open we don't really want open during the transition. In order to make logging work, we switch the + * log subsystem into open_when_needed mode, so that it reopens the logs on every single log call. */ + + log_forget_fds(); + log_set_open_when_needed(true); + + /* In case anything used libc syslog(), close this here, too */ + closelog(); + + n_fds = n_socket_fds + n_storage_fds; + r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, params->exec_fd, fds, n_fds); + if (r < 0) { + *exit_status = EXIT_FDS; + return log_unit_error_errno(unit, r, "Failed to close unwanted file descriptors: %m"); + } + + if (!context->same_pgrp) + if (setsid() < 0) { + *exit_status = EXIT_SETSID; + return log_unit_error_errno(unit, errno, "Failed to create new process session: %m"); + } + + exec_context_tty_reset(context, params); + + if (unit_shall_confirm_spawn(unit)) { + const char *vc = params->confirm_spawn; + _cleanup_free_ char *cmdline = NULL; + + cmdline = exec_command_line(command->argv); + if (!cmdline) { + *exit_status = EXIT_MEMORY; + return log_oom(); + } + + r = ask_for_confirmation(vc, unit, cmdline); + if (r != CONFIRM_EXECUTE) { + if (r == CONFIRM_PRETEND_SUCCESS) { + *exit_status = EXIT_SUCCESS; + return 0; + } + *exit_status = EXIT_CONFIRM; + log_unit_error(unit, "Execution cancelled by the user"); + return -ECANCELED; + } + } + + /* We are about to invoke NSS and PAM modules. Let's tell them what we are doing here, maybe they care. This is + * used by nss-resolve to disable itself when we are about to start systemd-resolved, to avoid deadlocks. Note + * that these env vars do not survive the execve(), which means they really only apply to the PAM and NSS + * invocations themselves. Also note that while we'll only invoke NSS modules involved in user management they + * might internally call into other NSS modules that are involved in hostname resolution, we never know. */ + if (setenv("SYSTEMD_ACTIVATION_UNIT", unit->id, true) != 0 || + setenv("SYSTEMD_ACTIVATION_SCOPE", MANAGER_IS_SYSTEM(unit->manager) ? "system" : "user", true) != 0) { + *exit_status = EXIT_MEMORY; + return log_unit_error_errno(unit, errno, "Failed to update environment: %m"); + } + + if (context->dynamic_user && dcreds) { + _cleanup_strv_free_ char **suggested_paths = NULL; + + /* On top of that, make sure we bypass our own NSS module nss-systemd comprehensively for any NSS + * checks, if DynamicUser=1 is used, as we shouldn't create a feedback loop with ourselves here.*/ + if (putenv((char*) "SYSTEMD_NSS_DYNAMIC_BYPASS=1") != 0) { + *exit_status = EXIT_USER; + return log_unit_error_errno(unit, errno, "Failed to update environment: %m"); + } + + r = compile_suggested_paths(context, params, &suggested_paths); + if (r < 0) { + *exit_status = EXIT_MEMORY; + return log_oom(); + } + + r = dynamic_creds_realize(dcreds, suggested_paths, &uid, &gid); + if (r < 0) { + *exit_status = EXIT_USER; + if (r == -EILSEQ) { + log_unit_error(unit, "Failed to update dynamic user credentials: User or group with specified name already exists."); + return -EOPNOTSUPP; + } + return log_unit_error_errno(unit, r, "Failed to update dynamic user credentials: %m"); + } + + if (!uid_is_valid(uid)) { + *exit_status = EXIT_USER; + log_unit_error(unit, "UID validation failed for \""UID_FMT"\"", uid); + return -ESRCH; + } + + if (!gid_is_valid(gid)) { + *exit_status = EXIT_USER; + log_unit_error(unit, "GID validation failed for \""GID_FMT"\"", gid); + return -ESRCH; + } + + if (dcreds->user) + username = dcreds->user->name; + + } else { + r = get_fixed_user(context, &username, &uid, &gid, &home, &shell); + if (r < 0) { + *exit_status = EXIT_USER; + return log_unit_error_errno(unit, r, "Failed to determine user credentials: %m"); + } + + r = get_fixed_group(context, &groupname, &gid); + if (r < 0) { + *exit_status = EXIT_GROUP; + return log_unit_error_errno(unit, r, "Failed to determine group credentials: %m"); + } + } + + /* Initialize user supplementary groups and get SupplementaryGroups= ones */ + r = get_supplementary_groups(context, username, groupname, gid, + &supplementary_gids, &ngids); + if (r < 0) { + *exit_status = EXIT_GROUP; + return log_unit_error_errno(unit, r, "Failed to determine supplementary groups: %m"); + } + + r = send_user_lookup(unit, user_lookup_fd, uid, gid); + if (r < 0) { + *exit_status = EXIT_USER; + return log_unit_error_errno(unit, r, "Failed to send user credentials to PID1: %m"); + } + + user_lookup_fd = safe_close(user_lookup_fd); + + r = acquire_home(context, uid, &home, &home_buffer); + if (r < 0) { + *exit_status = EXIT_CHDIR; + return log_unit_error_errno(unit, r, "Failed to determine $HOME for user: %m"); + } + + /* If a socket is connected to STDIN/STDOUT/STDERR, we + * must sure to drop O_NONBLOCK */ + if (socket_fd >= 0) + (void) fd_nonblock(socket_fd, false); + + /* Journald will try to look-up our cgroup in order to populate _SYSTEMD_CGROUP and _SYSTEMD_UNIT fields. + * Hence we need to migrate to the target cgroup from init.scope before connecting to journald */ + if (params->cgroup_path) { + _cleanup_free_ char *p = NULL; + + r = exec_parameters_get_cgroup_path(params, &p); + if (r < 0) { + *exit_status = EXIT_CGROUP; + return log_unit_error_errno(unit, r, "Failed to acquire cgroup path: %m"); + } + + r = cg_attach_everywhere(params->cgroup_supported, p, 0, NULL, NULL); + if (r < 0) { + *exit_status = EXIT_CGROUP; + return log_unit_error_errno(unit, r, "Failed to attach to cgroup %s: %m", p); + } + } + + if (context->network_namespace_path && runtime && runtime->netns_storage_socket[0] >= 0) { + r = open_netns_path(runtime->netns_storage_socket, context->network_namespace_path); + if (r < 0) { + *exit_status = EXIT_NETWORK; + return log_unit_error_errno(unit, r, "Failed to open network namespace path %s: %m", context->network_namespace_path); + } + } + + r = setup_input(context, params, socket_fd, named_iofds); + if (r < 0) { + *exit_status = EXIT_STDIN; + return log_unit_error_errno(unit, r, "Failed to set up standard input: %m"); + } + + r = setup_output(unit, context, params, STDOUT_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino); + if (r < 0) { + *exit_status = EXIT_STDOUT; + return log_unit_error_errno(unit, r, "Failed to set up standard output: %m"); + } + + r = setup_output(unit, context, params, STDERR_FILENO, socket_fd, named_iofds, basename(command->path), uid, gid, &journal_stream_dev, &journal_stream_ino); + if (r < 0) { + *exit_status = EXIT_STDERR; + return log_unit_error_errno(unit, r, "Failed to set up standard error output: %m"); + } + + if (context->oom_score_adjust_set) { + /* When we can't make this change due to EPERM, then let's silently skip over it. User namespaces + * prohibit write access to this file, and we shouldn't trip up over that. */ + r = set_oom_score_adjust(context->oom_score_adjust); + if (IN_SET(r, -EPERM, -EACCES)) + log_unit_debug_errno(unit, r, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m"); + else if (r < 0) { + *exit_status = EXIT_OOM_ADJUST; + return log_unit_error_errno(unit, r, "Failed to adjust OOM setting: %m"); + } + } + + if (context->nice_set) + if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) { + *exit_status = EXIT_NICE; + return log_unit_error_errno(unit, errno, "Failed to set up process scheduling priority (nice level): %m"); + } + + if (context->cpu_sched_set) { + struct sched_param param = { + .sched_priority = context->cpu_sched_priority, + }; + + r = sched_setscheduler(0, + context->cpu_sched_policy | + (context->cpu_sched_reset_on_fork ? + SCHED_RESET_ON_FORK : 0), + ¶m); + if (r < 0) { + *exit_status = EXIT_SETSCHEDULER; + return log_unit_error_errno(unit, errno, "Failed to set up CPU scheduling: %m"); + } + } + + if (context->cpu_set.set) + if (sched_setaffinity(0, context->cpu_set.allocated, context->cpu_set.set) < 0) { + *exit_status = EXIT_CPUAFFINITY; + return log_unit_error_errno(unit, errno, "Failed to set up CPU affinity: %m"); + } + + if (mpol_is_valid(numa_policy_get_type(&context->numa_policy))) { + r = apply_numa_policy(&context->numa_policy); + if (r == -EOPNOTSUPP) + log_unit_debug_errno(unit, r, "NUMA support not available, ignoring."); + else if (r < 0) { + *exit_status = EXIT_NUMA_POLICY; + return log_unit_error_errno(unit, r, "Failed to set NUMA memory policy: %m"); + } + } + + if (context->ioprio_set) + if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) { + *exit_status = EXIT_IOPRIO; + return log_unit_error_errno(unit, errno, "Failed to set up IO scheduling priority: %m"); + } + + if (context->timer_slack_nsec != NSEC_INFINITY) + if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) { + *exit_status = EXIT_TIMERSLACK; + return log_unit_error_errno(unit, errno, "Failed to set up timer slack: %m"); + } + + if (context->personality != PERSONALITY_INVALID) { + r = safe_personality(context->personality); + if (r < 0) { + *exit_status = EXIT_PERSONALITY; + return log_unit_error_errno(unit, r, "Failed to set up execution domain (personality): %m"); + } + } + + if (context->utmp_id) + utmp_put_init_process(context->utmp_id, getpid_cached(), getsid(0), + context->tty_path, + context->utmp_mode == EXEC_UTMP_INIT ? INIT_PROCESS : + context->utmp_mode == EXEC_UTMP_LOGIN ? LOGIN_PROCESS : + USER_PROCESS, + username); + + if (uid_is_valid(uid)) { + r = chown_terminal(STDIN_FILENO, uid); + if (r < 0) { + *exit_status = EXIT_STDIN; + return log_unit_error_errno(unit, r, "Failed to change ownership of terminal: %m"); + } + } + + /* If delegation is enabled we'll pass ownership of the cgroup to the user of the new process. On cgroup v1 + * this is only about systemd's own hierarchy, i.e. not the controller hierarchies, simply because that's not + * safe. On cgroup v2 there's only one hierarchy anyway, and delegation is safe there, hence in that case only + * touch a single hierarchy too. */ + if (params->cgroup_path && context->user && (params->flags & EXEC_CGROUP_DELEGATE)) { + r = cg_set_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, uid, gid); + if (r < 0) { + *exit_status = EXIT_CGROUP; + return log_unit_error_errno(unit, r, "Failed to adjust control group access: %m"); + } + } + + for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { + r = setup_exec_directory(context, params, uid, gid, dt, exit_status); + if (r < 0) + return log_unit_error_errno(unit, r, "Failed to set up special execution directory in %s: %m", params->prefix[dt]); + } + + r = build_environment( + unit, + context, + params, + n_fds, + home, + username, + shell, + journal_stream_dev, + journal_stream_ino, + &our_env); + if (r < 0) { + *exit_status = EXIT_MEMORY; + return log_oom(); + } + + r = build_pass_environment(context, &pass_env); + if (r < 0) { + *exit_status = EXIT_MEMORY; + return log_oom(); + } + + accum_env = strv_env_merge(5, + params->environment, + our_env, + pass_env, + context->environment, + files_env, + NULL); + if (!accum_env) { + *exit_status = EXIT_MEMORY; + return log_oom(); + } + accum_env = strv_env_clean(accum_env); + + (void) umask(context->umask); + + r = setup_keyring(unit, context, params, uid, gid); + if (r < 0) { + *exit_status = EXIT_KEYRING; + return log_unit_error_errno(unit, r, "Failed to set up kernel keyring: %m"); + } + + /* We need sandboxing if the caller asked us to apply it and the command isn't explicitly excepted from it */ + needs_sandboxing = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & EXEC_COMMAND_FULLY_PRIVILEGED); + + /* We need the ambient capability hack, if the caller asked us to apply it and the command is marked for it, and the kernel doesn't actually support ambient caps */ + needs_ambient_hack = (params->flags & EXEC_APPLY_SANDBOXING) && (command->flags & EXEC_COMMAND_AMBIENT_MAGIC) && !ambient_capabilities_supported(); + + /* We need setresuid() if the caller asked us to apply sandboxing and the command isn't explicitly excepted from either whole sandboxing or just setresuid() itself, and the ambient hack is not desired */ + if (needs_ambient_hack) + needs_setuid = false; + else + needs_setuid = (params->flags & EXEC_APPLY_SANDBOXING) && !(command->flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID)); + + if (needs_sandboxing) { + /* MAC enablement checks need to be done before a new mount ns is created, as they rely on /sys being + * present. The actual MAC context application will happen later, as late as possible, to avoid + * impacting our own code paths. */ + +#if HAVE_SELINUX + use_selinux = mac_selinux_use(); +#endif +#if ENABLE_SMACK + use_smack = mac_smack_use(); +#endif +#if HAVE_APPARMOR + use_apparmor = mac_apparmor_use(); +#endif + } + + if (needs_sandboxing) { + int which_failed; + + /* Let's set the resource limits before we call into PAM, so that pam_limits wins over what + * is set here. (See below.) */ + + r = setrlimit_closest_all((const struct rlimit* const *) context->rlimit, &which_failed); + if (r < 0) { + *exit_status = EXIT_LIMITS; + return log_unit_error_errno(unit, r, "Failed to adjust resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed)); + } + } + + if (needs_setuid) { + + /* Let's call into PAM after we set up our own idea of resource limits to that pam_limits + * wins here. (See above.) */ + + if (context->pam_name && username) { + r = setup_pam(context->pam_name, username, uid, gid, context->tty_path, &accum_env, fds, n_fds); + if (r < 0) { + *exit_status = EXIT_PAM; + return log_unit_error_errno(unit, r, "Failed to set up PAM session: %m"); + } + } + } + + if ((context->private_network || context->network_namespace_path) && runtime && runtime->netns_storage_socket[0] >= 0) { + + if (ns_type_supported(NAMESPACE_NET)) { + r = setup_netns(runtime->netns_storage_socket); + if (r < 0) { + *exit_status = EXIT_NETWORK; + return log_unit_error_errno(unit, r, "Failed to set up network namespacing: %m"); + } + } else if (context->network_namespace_path) { + *exit_status = EXIT_NETWORK; + return log_unit_error_errno(unit, SYNTHETIC_ERRNO(EOPNOTSUPP), "NetworkNamespacePath= is not supported, refusing."); + } else + log_unit_warning(unit, "PrivateNetwork=yes is configured, but the kernel does not support network namespaces, ignoring."); + } + + needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime); + if (needs_mount_namespace) { + _cleanup_free_ char *error_path = NULL; + + r = apply_mount_namespace(unit, command, context, params, runtime, &error_path); + if (r < 0) { + *exit_status = EXIT_NAMESPACE; + return log_unit_error_errno(unit, r, "Failed to set up mount namespacing%s%s: %m", + error_path ? ": " : "", strempty(error_path)); + } + } + + if (context->protect_hostname) { + if (ns_type_supported(NAMESPACE_UTS)) { + if (unshare(CLONE_NEWUTS) < 0) { + if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno)) { + *exit_status = EXIT_NAMESPACE; + return log_unit_error_errno(unit, errno, "Failed to set up UTS namespacing: %m"); + } + + log_unit_warning(unit, "ProtectHostname=yes is configured, but UTS namespace setup is prohibited (container manager?), ignoring namespace setup."); + } + } else + log_unit_warning(unit, "ProtectHostname=yes is configured, but the kernel does not support UTS namespaces, ignoring namespace setup."); +#if HAVE_SECCOMP + r = seccomp_protect_hostname(); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to apply hostname restrictions: %m"); + } +#endif + } + + /* Drop groups as early as possbile */ + if (needs_setuid) { + r = enforce_groups(gid, supplementary_gids, ngids); + if (r < 0) { + *exit_status = EXIT_GROUP; + return log_unit_error_errno(unit, r, "Changing group credentials failed: %m"); + } + } + + if (needs_sandboxing) { +#if HAVE_SELINUX + if (use_selinux && params->selinux_context_net && socket_fd >= 0) { + r = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net); + if (r < 0) { + *exit_status = EXIT_SELINUX_CONTEXT; + return log_unit_error_errno(unit, r, "Failed to determine SELinux context: %m"); + } + } +#endif + + if (context->private_users) { + r = setup_private_users(uid, gid); + if (r < 0) { + *exit_status = EXIT_USER; + return log_unit_error_errno(unit, r, "Failed to set up user namespacing: %m"); + } + } + } + + /* We repeat the fd closing here, to make sure that nothing is leaked from the PAM modules. Note that we are + * more aggressive this time since socket_fd and the netns fds we don't need anymore. We do keep the exec_fd + * however if we have it as we want to keep it open until the final execve(). */ + + if (params->exec_fd >= 0) { + exec_fd = params->exec_fd; + + if (exec_fd < 3 + (int) n_fds) { + int moved_fd; + + /* Let's move the exec fd far up, so that it's outside of the fd range we want to pass to the + * process we are about to execute. */ + + moved_fd = fcntl(exec_fd, F_DUPFD_CLOEXEC, 3 + (int) n_fds); + if (moved_fd < 0) { + *exit_status = EXIT_FDS; + return log_unit_error_errno(unit, errno, "Couldn't move exec fd up: %m"); + } + + safe_close(exec_fd); + exec_fd = moved_fd; + } else { + /* This fd should be FD_CLOEXEC already, but let's make sure. */ + r = fd_cloexec(exec_fd, true); + if (r < 0) { + *exit_status = EXIT_FDS; + return log_unit_error_errno(unit, r, "Failed to make exec fd FD_CLOEXEC: %m"); + } + } + + fds_with_exec_fd = newa(int, n_fds + 1); + memcpy_safe(fds_with_exec_fd, fds, n_fds * sizeof(int)); + fds_with_exec_fd[n_fds] = exec_fd; + n_fds_with_exec_fd = n_fds + 1; + } else { + fds_with_exec_fd = fds; + n_fds_with_exec_fd = n_fds; + } + + r = close_all_fds(fds_with_exec_fd, n_fds_with_exec_fd); + if (r >= 0) + r = shift_fds(fds, n_fds); + if (r >= 0) + r = flags_fds(fds, n_socket_fds, n_storage_fds, context->non_blocking); + if (r < 0) { + *exit_status = EXIT_FDS; + return log_unit_error_errno(unit, r, "Failed to adjust passed file descriptors: %m"); + } + + /* At this point, the fds we want to pass to the program are all ready and set up, with O_CLOEXEC turned off + * and at the right fd numbers. The are no other fds open, with one exception: the exec_fd if it is defined, + * and it has O_CLOEXEC set, after all we want it to be closed by the execve(), so that our parent knows we + * came this far. */ + + secure_bits = context->secure_bits; + + if (needs_sandboxing) { + uint64_t bset; + + /* Set the RTPRIO resource limit to 0, but only if nothing else was explicitly + * requested. (Note this is placed after the general resource limit initialization, see + * above, in order to take precedence.) */ + if (context->restrict_realtime && !context->rlimit[RLIMIT_RTPRIO]) { + if (setrlimit(RLIMIT_RTPRIO, &RLIMIT_MAKE_CONST(0)) < 0) { + *exit_status = EXIT_LIMITS; + return log_unit_error_errno(unit, errno, "Failed to adjust RLIMIT_RTPRIO resource limit: %m"); + } + } + +#if ENABLE_SMACK + /* LSM Smack needs the capability CAP_MAC_ADMIN to change the current execution security context of the + * process. This is the latest place before dropping capabilities. Other MAC context are set later. */ + if (use_smack) { + r = setup_smack(context, command); + if (r < 0) { + *exit_status = EXIT_SMACK_PROCESS_LABEL; + return log_unit_error_errno(unit, r, "Failed to set SMACK process label: %m"); + } + } +#endif + + bset = context->capability_bounding_set; + /* If the ambient caps hack is enabled (which means the kernel can't do them, and the user asked for + * our magic fallback), then let's add some extra caps, so that the service can drop privs of its own, + * instead of us doing that */ + if (needs_ambient_hack) + bset |= (UINT64_C(1) << CAP_SETPCAP) | + (UINT64_C(1) << CAP_SETUID) | + (UINT64_C(1) << CAP_SETGID); + + if (!cap_test_all(bset)) { + r = capability_bounding_set_drop(bset, false); + if (r < 0) { + *exit_status = EXIT_CAPABILITIES; + return log_unit_error_errno(unit, r, "Failed to drop capabilities: %m"); + } + } + + /* This is done before enforce_user, but ambient set + * does not survive over setresuid() if keep_caps is not set. */ + if (!needs_ambient_hack && + context->capability_ambient_set != 0) { + r = capability_ambient_set_apply(context->capability_ambient_set, true); + if (r < 0) { + *exit_status = EXIT_CAPABILITIES; + return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (before UID change): %m"); + } + } + } + + /* chroot to root directory first, before we lose the ability to chroot */ + r = apply_root_directory(context, params, needs_mount_namespace, exit_status); + if (r < 0) + return log_unit_error_errno(unit, r, "Chrooting to the requested root directory failed: %m"); + + if (needs_setuid) { + if (uid_is_valid(uid)) { + r = enforce_user(context, uid); + if (r < 0) { + *exit_status = EXIT_USER; + return log_unit_error_errno(unit, r, "Failed to change UID to " UID_FMT ": %m", uid); + } + + if (!needs_ambient_hack && + context->capability_ambient_set != 0) { + + /* Fix the ambient capabilities after user change. */ + r = capability_ambient_set_apply(context->capability_ambient_set, false); + if (r < 0) { + *exit_status = EXIT_CAPABILITIES; + return log_unit_error_errno(unit, r, "Failed to apply ambient capabilities (after UID change): %m"); + } + + /* If we were asked to change user and ambient capabilities + * were requested, we had to add keep-caps to the securebits + * so that we would maintain the inherited capability set + * through the setresuid(). Make sure that the bit is added + * also to the context secure_bits so that we don't try to + * drop the bit away next. */ + + secure_bits |= 1<selinux_context; + + if (exec_context) { + r = setexeccon(exec_context); + if (r < 0) { + *exit_status = EXIT_SELINUX_CONTEXT; + return log_unit_error_errno(unit, r, "Failed to change SELinux context to %s: %m", exec_context); + } + } + } +#endif + +#if HAVE_APPARMOR + if (use_apparmor && context->apparmor_profile) { + r = aa_change_onexec(context->apparmor_profile); + if (r < 0 && !context->apparmor_profile_ignore) { + *exit_status = EXIT_APPARMOR_PROFILE; + return log_unit_error_errno(unit, errno, "Failed to prepare AppArmor profile change to %s: %m", context->apparmor_profile); + } + } +#endif + + /* PR_GET_SECUREBITS is not privileged, while PR_SET_SECUREBITS is. So to suppress potential EPERMs + * we'll try not to call PR_SET_SECUREBITS unless necessary. */ + if (prctl(PR_GET_SECUREBITS) != secure_bits) + if (prctl(PR_SET_SECUREBITS, secure_bits) < 0) { + *exit_status = EXIT_SECUREBITS; + return log_unit_error_errno(unit, errno, "Failed to set process secure bits: %m"); + } + + if (context_has_no_new_privileges(context)) + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { + *exit_status = EXIT_NO_NEW_PRIVILEGES; + return log_unit_error_errno(unit, errno, "Failed to disable new privileges: %m"); + } + +#if HAVE_SECCOMP + r = apply_address_families(unit, context); + if (r < 0) { + *exit_status = EXIT_ADDRESS_FAMILIES; + return log_unit_error_errno(unit, r, "Failed to restrict address families: %m"); + } + + r = apply_memory_deny_write_execute(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to disable writing to executable memory: %m"); + } + + r = apply_restrict_realtime(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to apply realtime restrictions: %m"); + } + + r = apply_restrict_suid_sgid(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to apply SUID/SGID restrictions: %m"); + } + + r = apply_restrict_namespaces(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to apply namespace restrictions: %m"); + } + + r = apply_protect_sysctl(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to apply sysctl restrictions: %m"); + } + + r = apply_protect_kernel_modules(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to apply module loading restrictions: %m"); + } + + r = apply_protect_kernel_logs(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to apply kernel log restrictions: %m"); + } + + r = apply_private_devices(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to set up private devices: %m"); + } + + r = apply_syscall_archs(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to apply syscall architecture restrictions: %m"); + } + + r = apply_lock_personality(unit, context); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to lock personalities: %m"); + } + + /* This really should remain the last step before the execve(), to make sure our own code is unaffected + * by the filter as little as possible. */ + r = apply_syscall_filter(unit, context, needs_ambient_hack); + if (r < 0) { + *exit_status = EXIT_SECCOMP; + return log_unit_error_errno(unit, r, "Failed to apply system call filters: %m"); + } +#endif + } + + if (!strv_isempty(context->unset_environment)) { + char **ee = NULL; + + ee = strv_env_delete(accum_env, 1, context->unset_environment); + if (!ee) { + *exit_status = EXIT_MEMORY; + return log_oom(); + } + + strv_free_and_replace(accum_env, ee); + } + + if (!FLAGS_SET(command->flags, EXEC_COMMAND_NO_ENV_EXPAND)) { + replaced_argv = replace_env_argv(command->argv, accum_env); + if (!replaced_argv) { + *exit_status = EXIT_MEMORY; + return log_oom(); + } + final_argv = replaced_argv; + } else + final_argv = command->argv; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *line; + + line = exec_command_line(final_argv); + if (line) + log_struct(LOG_DEBUG, + "EXECUTABLE=%s", command->path, + LOG_UNIT_MESSAGE(unit, "Executing: %s", line), + LOG_UNIT_ID(unit), + LOG_UNIT_INVOCATION_ID(unit)); + } + + if (exec_fd >= 0) { + uint8_t hot = 1; + + /* We have finished with all our initializations. Let's now let the manager know that. From this point + * on, if the manager sees POLLHUP on the exec_fd, then execve() was successful. */ + + if (write(exec_fd, &hot, sizeof(hot)) < 0) { + *exit_status = EXIT_EXEC; + return log_unit_error_errno(unit, errno, "Failed to enable exec_fd: %m"); + } + } + + execve(command->path, final_argv, accum_env); + r = -errno; + + if (exec_fd >= 0) { + uint8_t hot = 0; + + /* The execve() failed. This means the exec_fd is still open. Which means we need to tell the manager + * that POLLHUP on it no longer means execve() succeeded. */ + + if (write(exec_fd, &hot, sizeof(hot)) < 0) { + *exit_status = EXIT_EXEC; + return log_unit_error_errno(unit, errno, "Failed to disable exec_fd: %m"); + } + } + + if (r == -ENOENT && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) { + log_struct_errno(LOG_INFO, r, + "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR, + LOG_UNIT_ID(unit), + LOG_UNIT_INVOCATION_ID(unit), + LOG_UNIT_MESSAGE(unit, "Executable %s missing, skipping: %m", + command->path), + "EXECUTABLE=%s", command->path); + return 0; + } + + *exit_status = EXIT_EXEC; + return log_unit_error_errno(unit, r, "Failed to execute command: %m"); +} + +static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***l); +static int exec_context_named_iofds(const ExecContext *c, const ExecParameters *p, int named_iofds[static 3]); + +int exec_spawn(Unit *unit, + ExecCommand *command, + const ExecContext *context, + const ExecParameters *params, + ExecRuntime *runtime, + DynamicCreds *dcreds, + pid_t *ret) { + + int socket_fd, r, named_iofds[3] = { -1, -1, -1 }, *fds = NULL; + _cleanup_free_ char *subcgroup_path = NULL; + _cleanup_strv_free_ char **files_env = NULL; + size_t n_storage_fds = 0, n_socket_fds = 0; + _cleanup_free_ char *line = NULL; + pid_t pid; + + assert(unit); + assert(command); + assert(context); + assert(ret); + assert(params); + assert(params->fds || (params->n_socket_fds + params->n_storage_fds <= 0)); + + if (context->std_input == EXEC_INPUT_SOCKET || + context->std_output == EXEC_OUTPUT_SOCKET || + context->std_error == EXEC_OUTPUT_SOCKET) { + + if (params->n_socket_fds > 1) { + log_unit_error(unit, "Got more than one socket."); + return -EINVAL; + } + + if (params->n_socket_fds == 0) { + log_unit_error(unit, "Got no socket."); + return -EINVAL; + } + + socket_fd = params->fds[0]; + } else { + socket_fd = -1; + fds = params->fds; + n_socket_fds = params->n_socket_fds; + n_storage_fds = params->n_storage_fds; + } + + r = exec_context_named_iofds(context, params, named_iofds); + if (r < 0) + return log_unit_error_errno(unit, r, "Failed to load a named file descriptor: %m"); + + r = exec_context_load_environment(unit, context, &files_env); + if (r < 0) + return log_unit_error_errno(unit, r, "Failed to load environment files: %m"); + + line = exec_command_line(command->argv); + if (!line) + return log_oom(); + + log_struct(LOG_DEBUG, + LOG_UNIT_MESSAGE(unit, "About to execute: %s", line), + "EXECUTABLE=%s", command->path, + LOG_UNIT_ID(unit), + LOG_UNIT_INVOCATION_ID(unit)); + + if (params->cgroup_path) { + r = exec_parameters_get_cgroup_path(params, &subcgroup_path); + if (r < 0) + return log_unit_error_errno(unit, r, "Failed to acquire subcgroup path: %m"); + if (r > 0) { /* We are using a child cgroup */ + r = cg_create(SYSTEMD_CGROUP_CONTROLLER, subcgroup_path); + if (r < 0) + return log_unit_error_errno(unit, r, "Failed to create control group '%s': %m", subcgroup_path); + } + } + + pid = fork(); + if (pid < 0) + return log_unit_error_errno(unit, errno, "Failed to fork: %m"); + + if (pid == 0) { + int exit_status = EXIT_SUCCESS; + + r = exec_child(unit, + command, + context, + params, + runtime, + dcreds, + socket_fd, + named_iofds, + fds, + n_socket_fds, + n_storage_fds, + files_env, + unit->manager->user_lookup_fds[1], + &exit_status); + + if (r < 0) { + const char *status = + exit_status_to_string(exit_status, + EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD); + + log_struct_errno(LOG_ERR, r, + "MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR, + LOG_UNIT_ID(unit), + LOG_UNIT_INVOCATION_ID(unit), + LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m", + status, command->path), + "EXECUTABLE=%s", command->path); + } + + _exit(exit_status); + } + + log_unit_debug(unit, "Forked %s as "PID_FMT, command->path, pid); + + /* We add the new process to the cgroup both in the child (so that we can be sure that no user code is ever + * executed outside of the cgroup) and in the parent (so that we can be sure that when we kill the cgroup the + * process will be killed too). */ + if (subcgroup_path) + (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER, subcgroup_path, pid); + + exec_status_start(&command->exec_status, pid); + + *ret = pid; + return 0; +} + +void exec_context_init(ExecContext *c) { + ExecDirectoryType i; + + assert(c); + + c->umask = 0022; + c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0); + c->cpu_sched_policy = SCHED_OTHER; + c->syslog_priority = LOG_DAEMON|LOG_INFO; + c->syslog_level_prefix = true; + c->ignore_sigpipe = true; + c->timer_slack_nsec = NSEC_INFINITY; + c->personality = PERSONALITY_INVALID; + for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) + c->directories[i].mode = 0755; + c->timeout_clean_usec = USEC_INFINITY; + c->capability_bounding_set = CAP_ALL; + assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL); + c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL; + c->log_level_max = -1; + numa_policy_reset(&c->numa_policy); +} + +void exec_context_done(ExecContext *c) { + ExecDirectoryType i; + size_t l; + + assert(c); + + c->environment = strv_free(c->environment); + c->environment_files = strv_free(c->environment_files); + c->pass_environment = strv_free(c->pass_environment); + c->unset_environment = strv_free(c->unset_environment); + + rlimit_free_all(c->rlimit); + + for (l = 0; l < 3; l++) { + c->stdio_fdname[l] = mfree(c->stdio_fdname[l]); + c->stdio_file[l] = mfree(c->stdio_file[l]); + } + + c->working_directory = mfree(c->working_directory); + c->root_directory = mfree(c->root_directory); + c->root_image = mfree(c->root_image); + c->tty_path = mfree(c->tty_path); + c->syslog_identifier = mfree(c->syslog_identifier); + c->user = mfree(c->user); + c->group = mfree(c->group); + + c->supplementary_groups = strv_free(c->supplementary_groups); + + c->pam_name = mfree(c->pam_name); + + c->read_only_paths = strv_free(c->read_only_paths); + c->read_write_paths = strv_free(c->read_write_paths); + c->inaccessible_paths = strv_free(c->inaccessible_paths); + + bind_mount_free_many(c->bind_mounts, c->n_bind_mounts); + c->bind_mounts = NULL; + c->n_bind_mounts = 0; + temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems); + c->temporary_filesystems = NULL; + c->n_temporary_filesystems = 0; + + cpu_set_reset(&c->cpu_set); + numa_policy_reset(&c->numa_policy); + + c->utmp_id = mfree(c->utmp_id); + c->selinux_context = mfree(c->selinux_context); + c->apparmor_profile = mfree(c->apparmor_profile); + c->smack_process_label = mfree(c->smack_process_label); + + c->syscall_filter = hashmap_free(c->syscall_filter); + c->syscall_archs = set_free(c->syscall_archs); + c->address_families = set_free(c->address_families); + + for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) + c->directories[i].paths = strv_free(c->directories[i].paths); + + c->log_level_max = -1; + + exec_context_free_log_extra_fields(c); + + c->log_ratelimit_interval_usec = 0; + c->log_ratelimit_burst = 0; + + c->stdin_data = mfree(c->stdin_data); + c->stdin_data_size = 0; + + c->network_namespace_path = mfree(c->network_namespace_path); +} + +int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_prefix) { + char **i; + + assert(c); + + if (!runtime_prefix) + return 0; + + STRV_FOREACH(i, c->directories[EXEC_DIRECTORY_RUNTIME].paths) { + _cleanup_free_ char *p; + + if (exec_directory_is_private(c, EXEC_DIRECTORY_RUNTIME)) + p = path_join(runtime_prefix, "private", *i); + else + p = path_join(runtime_prefix, *i); + if (!p) + return -ENOMEM; + + /* We execute this synchronously, since we need to be sure this is gone when we start the + * service next. */ + (void) rm_rf(p, REMOVE_ROOT); + } + + return 0; +} + +static void exec_command_done(ExecCommand *c) { + assert(c); + + c->path = mfree(c->path); + c->argv = strv_free(c->argv); +} + +void exec_command_done_array(ExecCommand *c, size_t n) { + size_t i; + + for (i = 0; i < n; i++) + exec_command_done(c+i); +} + +ExecCommand* exec_command_free_list(ExecCommand *c) { + ExecCommand *i; + + while ((i = c)) { + LIST_REMOVE(command, c, i); + exec_command_done(i); + free(i); + } + + return NULL; +} + +void exec_command_free_array(ExecCommand **c, size_t n) { + size_t i; + + for (i = 0; i < n; i++) + c[i] = exec_command_free_list(c[i]); +} + +void exec_command_reset_status_array(ExecCommand *c, size_t n) { + size_t i; + + for (i = 0; i < n; i++) + exec_status_reset(&c[i].exec_status); +} + +void exec_command_reset_status_list_array(ExecCommand **c, size_t n) { + size_t i; + + for (i = 0; i < n; i++) { + ExecCommand *z; + + LIST_FOREACH(command, z, c[i]) + exec_status_reset(&z->exec_status); + } +} + +typedef struct InvalidEnvInfo { + const Unit *unit; + const char *path; +} InvalidEnvInfo; + +static void invalid_env(const char *p, void *userdata) { + InvalidEnvInfo *info = userdata; + + log_unit_error(info->unit, "Ignoring invalid environment assignment '%s': %s", p, info->path); +} + +const char* exec_context_fdname(const ExecContext *c, int fd_index) { + assert(c); + + switch (fd_index) { + + case STDIN_FILENO: + if (c->std_input != EXEC_INPUT_NAMED_FD) + return NULL; + + return c->stdio_fdname[STDIN_FILENO] ?: "stdin"; + + case STDOUT_FILENO: + if (c->std_output != EXEC_OUTPUT_NAMED_FD) + return NULL; + + return c->stdio_fdname[STDOUT_FILENO] ?: "stdout"; + + case STDERR_FILENO: + if (c->std_error != EXEC_OUTPUT_NAMED_FD) + return NULL; + + return c->stdio_fdname[STDERR_FILENO] ?: "stderr"; + + default: + return NULL; + } +} + +static int exec_context_named_iofds( + const ExecContext *c, + const ExecParameters *p, + int named_iofds[static 3]) { + + size_t i, targets; + const char* stdio_fdname[3]; + size_t n_fds; + + assert(c); + assert(p); + assert(named_iofds); + + targets = (c->std_input == EXEC_INPUT_NAMED_FD) + + (c->std_output == EXEC_OUTPUT_NAMED_FD) + + (c->std_error == EXEC_OUTPUT_NAMED_FD); + + for (i = 0; i < 3; i++) + stdio_fdname[i] = exec_context_fdname(c, i); + + n_fds = p->n_storage_fds + p->n_socket_fds; + + for (i = 0; i < n_fds && targets > 0; i++) + if (named_iofds[STDIN_FILENO] < 0 && + c->std_input == EXEC_INPUT_NAMED_FD && + stdio_fdname[STDIN_FILENO] && + streq(p->fd_names[i], stdio_fdname[STDIN_FILENO])) { + + named_iofds[STDIN_FILENO] = p->fds[i]; + targets--; + + } else if (named_iofds[STDOUT_FILENO] < 0 && + c->std_output == EXEC_OUTPUT_NAMED_FD && + stdio_fdname[STDOUT_FILENO] && + streq(p->fd_names[i], stdio_fdname[STDOUT_FILENO])) { + + named_iofds[STDOUT_FILENO] = p->fds[i]; + targets--; + + } else if (named_iofds[STDERR_FILENO] < 0 && + c->std_error == EXEC_OUTPUT_NAMED_FD && + stdio_fdname[STDERR_FILENO] && + streq(p->fd_names[i], stdio_fdname[STDERR_FILENO])) { + + named_iofds[STDERR_FILENO] = p->fds[i]; + targets--; + } + + return targets == 0 ? 0 : -ENOENT; +} + +static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***l) { + char **i, **r = NULL; + + assert(c); + assert(l); + + STRV_FOREACH(i, c->environment_files) { + char *fn; + int k; + unsigned n; + bool ignore = false; + char **p; + _cleanup_globfree_ glob_t pglob = {}; + + fn = *i; + + if (fn[0] == '-') { + ignore = true; + fn++; + } + + if (!path_is_absolute(fn)) { + if (ignore) + continue; + + strv_free(r); + return -EINVAL; + } + + /* Filename supports globbing, take all matching files */ + k = safe_glob(fn, 0, &pglob); + if (k < 0) { + if (ignore) + continue; + + strv_free(r); + return k; + } + + /* When we don't match anything, -ENOENT should be returned */ + assert(pglob.gl_pathc > 0); + + for (n = 0; n < pglob.gl_pathc; n++) { + k = load_env_file(NULL, pglob.gl_pathv[n], &p); + if (k < 0) { + if (ignore) + continue; + + strv_free(r); + return k; + } + /* Log invalid environment variables with filename */ + if (p) { + InvalidEnvInfo info = { + .unit = unit, + .path = pglob.gl_pathv[n] + }; + + p = strv_env_clean_with_callback(p, invalid_env, &info); + } + + if (!r) + r = p; + else { + char **m; + + m = strv_env_merge(2, r, p); + strv_free(r); + strv_free(p); + if (!m) + return -ENOMEM; + + r = m; + } + } + } + + *l = r; + + return 0; +} + +static bool tty_may_match_dev_console(const char *tty) { + _cleanup_free_ char *resolved = NULL; + + if (!tty) + return true; + + tty = skip_dev_prefix(tty); + + /* trivial identity? */ + if (streq(tty, "console")) + return true; + + if (resolve_dev_console(&resolved) < 0) + return true; /* if we could not resolve, assume it may */ + + /* "tty0" means the active VC, so it may be the same sometimes */ + return path_equal(resolved, tty) || (streq(resolved, "tty0") && tty_is_vc(tty)); +} + +static bool exec_context_may_touch_tty(const ExecContext *ec) { + assert(ec); + + return ec->tty_reset || + ec->tty_vhangup || + ec->tty_vt_disallocate || + is_terminal_input(ec->std_input) || + is_terminal_output(ec->std_output) || + is_terminal_output(ec->std_error); +} + +bool exec_context_may_touch_console(const ExecContext *ec) { + + return exec_context_may_touch_tty(ec) && + tty_may_match_dev_console(exec_context_tty_path(ec)); +} + +static void strv_fprintf(FILE *f, char **l) { + char **g; + + assert(f); + + STRV_FOREACH(g, l) + fprintf(f, " %s", *g); +} + +void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { + char **e, **d, buf_clean[FORMAT_TIMESPAN_MAX]; + ExecDirectoryType dt; + unsigned i; + int r; + + assert(c); + assert(f); + + prefix = strempty(prefix); + + fprintf(f, + "%sUMask: %04o\n" + "%sWorkingDirectory: %s\n" + "%sRootDirectory: %s\n" + "%sNonBlocking: %s\n" + "%sPrivateTmp: %s\n" + "%sPrivateDevices: %s\n" + "%sProtectKernelTunables: %s\n" + "%sProtectKernelModules: %s\n" + "%sProtectKernelLogs: %s\n" + "%sProtectControlGroups: %s\n" + "%sPrivateNetwork: %s\n" + "%sPrivateUsers: %s\n" + "%sProtectHome: %s\n" + "%sProtectSystem: %s\n" + "%sMountAPIVFS: %s\n" + "%sIgnoreSIGPIPE: %s\n" + "%sMemoryDenyWriteExecute: %s\n" + "%sRestrictRealtime: %s\n" + "%sRestrictSUIDSGID: %s\n" + "%sKeyringMode: %s\n" + "%sProtectHostname: %s\n", + prefix, c->umask, + prefix, c->working_directory ? c->working_directory : "/", + prefix, c->root_directory ? c->root_directory : "/", + prefix, yes_no(c->non_blocking), + prefix, yes_no(c->private_tmp), + prefix, yes_no(c->private_devices), + prefix, yes_no(c->protect_kernel_tunables), + prefix, yes_no(c->protect_kernel_modules), + prefix, yes_no(c->protect_kernel_logs), + prefix, yes_no(c->protect_control_groups), + prefix, yes_no(c->private_network), + prefix, yes_no(c->private_users), + prefix, protect_home_to_string(c->protect_home), + prefix, protect_system_to_string(c->protect_system), + prefix, yes_no(c->mount_apivfs), + prefix, yes_no(c->ignore_sigpipe), + prefix, yes_no(c->memory_deny_write_execute), + prefix, yes_no(c->restrict_realtime), + prefix, yes_no(c->restrict_suid_sgid), + prefix, exec_keyring_mode_to_string(c->keyring_mode), + prefix, yes_no(c->protect_hostname)); + + if (c->root_image) + fprintf(f, "%sRootImage: %s\n", prefix, c->root_image); + + STRV_FOREACH(e, c->environment) + fprintf(f, "%sEnvironment: %s\n", prefix, *e); + + STRV_FOREACH(e, c->environment_files) + fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e); + + STRV_FOREACH(e, c->pass_environment) + fprintf(f, "%sPassEnvironment: %s\n", prefix, *e); + + STRV_FOREACH(e, c->unset_environment) + fprintf(f, "%sUnsetEnvironment: %s\n", prefix, *e); + + fprintf(f, "%sRuntimeDirectoryPreserve: %s\n", prefix, exec_preserve_mode_to_string(c->runtime_directory_preserve_mode)); + + for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { + fprintf(f, "%s%sMode: %04o\n", prefix, exec_directory_type_to_string(dt), c->directories[dt].mode); + + STRV_FOREACH(d, c->directories[dt].paths) + fprintf(f, "%s%s: %s\n", prefix, exec_directory_type_to_string(dt), *d); + } + + fprintf(f, + "%sTimeoutCleanSec: %s\n", + prefix, format_timespan(buf_clean, sizeof(buf_clean), c->timeout_clean_usec, USEC_PER_SEC)); + + if (c->nice_set) + fprintf(f, + "%sNice: %i\n", + prefix, c->nice); + + if (c->oom_score_adjust_set) + fprintf(f, + "%sOOMScoreAdjust: %i\n", + prefix, c->oom_score_adjust); + + for (i = 0; i < RLIM_NLIMITS; i++) + if (c->rlimit[i]) { + fprintf(f, "%sLimit%s: " RLIM_FMT "\n", + prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max); + fprintf(f, "%sLimit%sSoft: " RLIM_FMT "\n", + prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur); + } + + if (c->ioprio_set) { + _cleanup_free_ char *class_str = NULL; + + r = ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str); + if (r >= 0) + fprintf(f, "%sIOSchedulingClass: %s\n", prefix, class_str); + + fprintf(f, "%sIOPriority: %lu\n", prefix, IOPRIO_PRIO_DATA(c->ioprio)); + } + + if (c->cpu_sched_set) { + _cleanup_free_ char *policy_str = NULL; + + r = sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str); + if (r >= 0) + fprintf(f, "%sCPUSchedulingPolicy: %s\n", prefix, policy_str); + + fprintf(f, + "%sCPUSchedulingPriority: %i\n" + "%sCPUSchedulingResetOnFork: %s\n", + prefix, c->cpu_sched_priority, + prefix, yes_no(c->cpu_sched_reset_on_fork)); + } + + if (c->cpu_set.set) { + _cleanup_free_ char *affinity = NULL; + + affinity = cpu_set_to_range_string(&c->cpu_set); + fprintf(f, "%sCPUAffinity: %s\n", prefix, affinity); + } + + if (mpol_is_valid(numa_policy_get_type(&c->numa_policy))) { + _cleanup_free_ char *nodes = NULL; + + nodes = cpu_set_to_range_string(&c->numa_policy.nodes); + fprintf(f, "%sNUMAPolicy: %s\n", prefix, mpol_to_string(numa_policy_get_type(&c->numa_policy))); + fprintf(f, "%sNUMAMask: %s\n", prefix, strnull(nodes)); + } + + if (c->timer_slack_nsec != NSEC_INFINITY) + fprintf(f, "%sTimerSlackNSec: "NSEC_FMT "\n", prefix, c->timer_slack_nsec); + + fprintf(f, + "%sStandardInput: %s\n" + "%sStandardOutput: %s\n" + "%sStandardError: %s\n", + prefix, exec_input_to_string(c->std_input), + prefix, exec_output_to_string(c->std_output), + prefix, exec_output_to_string(c->std_error)); + + if (c->std_input == EXEC_INPUT_NAMED_FD) + fprintf(f, "%sStandardInputFileDescriptorName: %s\n", prefix, c->stdio_fdname[STDIN_FILENO]); + if (c->std_output == EXEC_OUTPUT_NAMED_FD) + fprintf(f, "%sStandardOutputFileDescriptorName: %s\n", prefix, c->stdio_fdname[STDOUT_FILENO]); + if (c->std_error == EXEC_OUTPUT_NAMED_FD) + fprintf(f, "%sStandardErrorFileDescriptorName: %s\n", prefix, c->stdio_fdname[STDERR_FILENO]); + + if (c->std_input == EXEC_INPUT_FILE) + fprintf(f, "%sStandardInputFile: %s\n", prefix, c->stdio_file[STDIN_FILENO]); + if (c->std_output == EXEC_OUTPUT_FILE) + fprintf(f, "%sStandardOutputFile: %s\n", prefix, c->stdio_file[STDOUT_FILENO]); + if (c->std_output == EXEC_OUTPUT_FILE_APPEND) + fprintf(f, "%sStandardOutputFileToAppend: %s\n", prefix, c->stdio_file[STDOUT_FILENO]); + if (c->std_error == EXEC_OUTPUT_FILE) + fprintf(f, "%sStandardErrorFile: %s\n", prefix, c->stdio_file[STDERR_FILENO]); + if (c->std_error == EXEC_OUTPUT_FILE_APPEND) + fprintf(f, "%sStandardErrorFileToAppend: %s\n", prefix, c->stdio_file[STDERR_FILENO]); + + if (c->tty_path) + fprintf(f, + "%sTTYPath: %s\n" + "%sTTYReset: %s\n" + "%sTTYVHangup: %s\n" + "%sTTYVTDisallocate: %s\n", + prefix, c->tty_path, + prefix, yes_no(c->tty_reset), + prefix, yes_no(c->tty_vhangup), + prefix, yes_no(c->tty_vt_disallocate)); + + if (IN_SET(c->std_output, + EXEC_OUTPUT_SYSLOG, + EXEC_OUTPUT_KMSG, + EXEC_OUTPUT_JOURNAL, + EXEC_OUTPUT_SYSLOG_AND_CONSOLE, + EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_JOURNAL_AND_CONSOLE) || + IN_SET(c->std_error, + EXEC_OUTPUT_SYSLOG, + EXEC_OUTPUT_KMSG, + EXEC_OUTPUT_JOURNAL, + EXEC_OUTPUT_SYSLOG_AND_CONSOLE, + EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_JOURNAL_AND_CONSOLE)) { + + _cleanup_free_ char *fac_str = NULL, *lvl_str = NULL; + + r = log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str); + if (r >= 0) + fprintf(f, "%sSyslogFacility: %s\n", prefix, fac_str); + + r = log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str); + if (r >= 0) + fprintf(f, "%sSyslogLevel: %s\n", prefix, lvl_str); + } + + if (c->log_level_max >= 0) { + _cleanup_free_ char *t = NULL; + + (void) log_level_to_string_alloc(c->log_level_max, &t); + + fprintf(f, "%sLogLevelMax: %s\n", prefix, strna(t)); + } + + if (c->log_ratelimit_interval_usec > 0) { + char buf_timespan[FORMAT_TIMESPAN_MAX]; + + fprintf(f, + "%sLogRateLimitIntervalSec: %s\n", + prefix, format_timespan(buf_timespan, sizeof(buf_timespan), c->log_ratelimit_interval_usec, USEC_PER_SEC)); + } + + if (c->log_ratelimit_burst > 0) + fprintf(f, "%sLogRateLimitBurst: %u\n", prefix, c->log_ratelimit_burst); + + if (c->n_log_extra_fields > 0) { + size_t j; + + for (j = 0; j < c->n_log_extra_fields; j++) { + fprintf(f, "%sLogExtraFields: ", prefix); + fwrite(c->log_extra_fields[j].iov_base, + 1, c->log_extra_fields[j].iov_len, + f); + fputc('\n', f); + } + } + + if (c->secure_bits) { + _cleanup_free_ char *str = NULL; + + r = secure_bits_to_string_alloc(c->secure_bits, &str); + if (r >= 0) + fprintf(f, "%sSecure Bits: %s\n", prefix, str); + } + + if (c->capability_bounding_set != CAP_ALL) { + _cleanup_free_ char *str = NULL; + + r = capability_set_to_string_alloc(c->capability_bounding_set, &str); + if (r >= 0) + fprintf(f, "%sCapabilityBoundingSet: %s\n", prefix, str); + } + + if (c->capability_ambient_set != 0) { + _cleanup_free_ char *str = NULL; + + r = capability_set_to_string_alloc(c->capability_ambient_set, &str); + if (r >= 0) + fprintf(f, "%sAmbientCapabilities: %s\n", prefix, str); + } + + if (c->user) + fprintf(f, "%sUser: %s\n", prefix, c->user); + if (c->group) + fprintf(f, "%sGroup: %s\n", prefix, c->group); + + fprintf(f, "%sDynamicUser: %s\n", prefix, yes_no(c->dynamic_user)); + + if (!strv_isempty(c->supplementary_groups)) { + fprintf(f, "%sSupplementaryGroups:", prefix); + strv_fprintf(f, c->supplementary_groups); + fputs("\n", f); + } + + if (c->pam_name) + fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name); + + if (!strv_isempty(c->read_write_paths)) { + fprintf(f, "%sReadWritePaths:", prefix); + strv_fprintf(f, c->read_write_paths); + fputs("\n", f); + } + + if (!strv_isempty(c->read_only_paths)) { + fprintf(f, "%sReadOnlyPaths:", prefix); + strv_fprintf(f, c->read_only_paths); + fputs("\n", f); + } + + if (!strv_isempty(c->inaccessible_paths)) { + fprintf(f, "%sInaccessiblePaths:", prefix); + strv_fprintf(f, c->inaccessible_paths); + fputs("\n", f); + } + + if (c->n_bind_mounts > 0) + for (i = 0; i < c->n_bind_mounts; i++) + fprintf(f, "%s%s: %s%s:%s:%s\n", prefix, + c->bind_mounts[i].read_only ? "BindReadOnlyPaths" : "BindPaths", + c->bind_mounts[i].ignore_enoent ? "-": "", + c->bind_mounts[i].source, + c->bind_mounts[i].destination, + c->bind_mounts[i].recursive ? "rbind" : "norbind"); + + if (c->n_temporary_filesystems > 0) + for (i = 0; i < c->n_temporary_filesystems; i++) { + TemporaryFileSystem *t = c->temporary_filesystems + i; + + fprintf(f, "%sTemporaryFileSystem: %s%s%s\n", prefix, + t->path, + isempty(t->options) ? "" : ":", + strempty(t->options)); + } + + if (c->utmp_id) + fprintf(f, + "%sUtmpIdentifier: %s\n", + prefix, c->utmp_id); + + if (c->selinux_context) + fprintf(f, + "%sSELinuxContext: %s%s\n", + prefix, c->selinux_context_ignore ? "-" : "", c->selinux_context); + + if (c->apparmor_profile) + fprintf(f, + "%sAppArmorProfile: %s%s\n", + prefix, c->apparmor_profile_ignore ? "-" : "", c->apparmor_profile); + + if (c->smack_process_label) + fprintf(f, + "%sSmackProcessLabel: %s%s\n", + prefix, c->smack_process_label_ignore ? "-" : "", c->smack_process_label); + + if (c->personality != PERSONALITY_INVALID) + fprintf(f, + "%sPersonality: %s\n", + prefix, strna(personality_to_string(c->personality))); + + fprintf(f, + "%sLockPersonality: %s\n", + prefix, yes_no(c->lock_personality)); + + if (c->syscall_filter) { +#if HAVE_SECCOMP + Iterator j; + void *id, *val; + bool first = true; +#endif + + fprintf(f, + "%sSystemCallFilter: ", + prefix); + + if (!c->syscall_whitelist) + fputc('~', f); + +#if HAVE_SECCOMP + HASHMAP_FOREACH_KEY(val, id, c->syscall_filter, j) { + _cleanup_free_ char *name = NULL; + const char *errno_name = NULL; + int num = PTR_TO_INT(val); + + if (first) + first = false; + else + fputc(' ', f); + + name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1); + fputs(strna(name), f); + + if (num >= 0) { + errno_name = errno_to_name(num); + if (errno_name) + fprintf(f, ":%s", errno_name); + else + fprintf(f, ":%d", num); + } + } +#endif + + fputc('\n', f); + } + + if (c->syscall_archs) { +#if HAVE_SECCOMP + Iterator j; + void *id; +#endif + + fprintf(f, + "%sSystemCallArchitectures:", + prefix); + +#if HAVE_SECCOMP + SET_FOREACH(id, c->syscall_archs, j) + fprintf(f, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id) - 1))); +#endif + fputc('\n', f); + } + + if (exec_context_restrict_namespaces_set(c)) { + _cleanup_free_ char *s = NULL; + + r = namespace_flags_to_string(c->restrict_namespaces, &s); + if (r >= 0) + fprintf(f, "%sRestrictNamespaces: %s\n", + prefix, s); + } + + if (c->network_namespace_path) + fprintf(f, + "%sNetworkNamespacePath: %s\n", + prefix, c->network_namespace_path); + + if (c->syscall_errno > 0) { + const char *errno_name; + + fprintf(f, "%sSystemCallErrorNumber: ", prefix); + + errno_name = errno_to_name(c->syscall_errno); + if (errno_name) + fprintf(f, "%s\n", errno_name); + else + fprintf(f, "%d\n", c->syscall_errno); + } +} + +bool exec_context_maintains_privileges(const ExecContext *c) { + assert(c); + + /* Returns true if the process forked off would run under + * an unchanged UID or as root. */ + + if (!c->user) + return true; + + if (streq(c->user, "root") || streq(c->user, "0")) + return true; + + return false; +} + +int exec_context_get_effective_ioprio(const ExecContext *c) { + int p; + + assert(c); + + if (c->ioprio_set) + return c->ioprio; + + p = ioprio_get(IOPRIO_WHO_PROCESS, 0); + if (p < 0) + return IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4); + + return p; +} + +void exec_context_free_log_extra_fields(ExecContext *c) { + size_t l; + + assert(c); + + for (l = 0; l < c->n_log_extra_fields; l++) + free(c->log_extra_fields[l].iov_base); + c->log_extra_fields = mfree(c->log_extra_fields); + c->n_log_extra_fields = 0; +} + +void exec_context_revert_tty(ExecContext *c) { + int r; + + assert(c); + + /* First, reset the TTY (possibly kicking everybody else from the TTY) */ + exec_context_tty_reset(c, NULL); + + /* And then undo what chown_terminal() did earlier. Note that we only do this if we have a path + * configured. If the TTY was passed to us as file descriptor we assume the TTY is opened and managed + * by whoever passed it to us and thus knows better when and how to chmod()/chown() it back. */ + + if (exec_context_may_touch_tty(c)) { + const char *path; + + path = exec_context_tty_path(c); + if (path) { + r = chmod_and_chown(path, TTY_MODE, 0, TTY_GID); + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to reset TTY ownership/access mode of %s, ignoring: %m", path); + } + } +} + +int exec_context_get_clean_directories( + ExecContext *c, + char **prefix, + ExecCleanMask mask, + char ***ret) { + + _cleanup_strv_free_ char **l = NULL; + ExecDirectoryType t; + int r; + + assert(c); + assert(prefix); + assert(ret); + + for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { + char **i; + + if (!FLAGS_SET(mask, 1U << t)) + continue; + + if (!prefix[t]) + continue; + + STRV_FOREACH(i, c->directories[t].paths) { + char *j; + + j = path_join(prefix[t], *i); + if (!j) + return -ENOMEM; + + r = strv_consume(&l, j); + if (r < 0) + return r; + + /* Also remove private directories unconditionally. */ + if (t != EXEC_DIRECTORY_CONFIGURATION) { + j = path_join(prefix[t], "private", *i); + if (!j) + return -ENOMEM; + + r = strv_consume(&l, j); + if (r < 0) + return r; + } + } + } + + *ret = TAKE_PTR(l); + return 0; +} + +int exec_context_get_clean_mask(ExecContext *c, ExecCleanMask *ret) { + ExecCleanMask mask = 0; + + assert(c); + assert(ret); + + for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) + if (!strv_isempty(c->directories[t].paths)) + mask |= 1U << t; + + *ret = mask; + return 0; +} + +void exec_status_start(ExecStatus *s, pid_t pid) { + assert(s); + + *s = (ExecStatus) { + .pid = pid, + }; + + dual_timestamp_get(&s->start_timestamp); +} + +void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int code, int status) { + assert(s); + + if (s->pid != pid) { + *s = (ExecStatus) { + .pid = pid, + }; + } + + dual_timestamp_get(&s->exit_timestamp); + + s->code = code; + s->status = status; + + if (context && context->utmp_id) + (void) utmp_put_dead_process(context->utmp_id, pid, code, status); +} + +void exec_status_reset(ExecStatus *s) { + assert(s); + + *s = (ExecStatus) {}; +} + +void exec_status_dump(const ExecStatus *s, FILE *f, const char *prefix) { + char buf[FORMAT_TIMESTAMP_MAX]; + + assert(s); + assert(f); + + if (s->pid <= 0) + return; + + prefix = strempty(prefix); + + fprintf(f, + "%sPID: "PID_FMT"\n", + prefix, s->pid); + + if (dual_timestamp_is_set(&s->start_timestamp)) + fprintf(f, + "%sStart Timestamp: %s\n", + prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime)); + + if (dual_timestamp_is_set(&s->exit_timestamp)) + fprintf(f, + "%sExit Timestamp: %s\n" + "%sExit Code: %s\n" + "%sExit Status: %i\n", + prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime), + prefix, sigchld_code_to_string(s->code), + prefix, s->status); +} + +static char *exec_command_line(char **argv) { + size_t k; + char *n, *p, **a; + bool first = true; + + assert(argv); + + k = 1; + STRV_FOREACH(a, argv) + k += strlen(*a)+3; + + n = new(char, k); + if (!n) + return NULL; + + p = n; + STRV_FOREACH(a, argv) { + + if (!first) + *(p++) = ' '; + else + first = false; + + if (strpbrk(*a, WHITESPACE)) { + *(p++) = '\''; + p = stpcpy(p, *a); + *(p++) = '\''; + } else + p = stpcpy(p, *a); + + } + + *p = 0; + + /* FIXME: this doesn't really handle arguments that have + * spaces and ticks in them */ + + return n; +} + +static void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) { + _cleanup_free_ char *cmd = NULL; + const char *prefix2; + + assert(c); + assert(f); + + prefix = strempty(prefix); + prefix2 = strjoina(prefix, "\t"); + + cmd = exec_command_line(c->argv); + fprintf(f, + "%sCommand Line: %s\n", + prefix, cmd ? cmd : strerror_safe(ENOMEM)); + + exec_status_dump(&c->exec_status, f, prefix2); +} + +void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) { + assert(f); + + prefix = strempty(prefix); + + LIST_FOREACH(command, c, c) + exec_command_dump(c, f, prefix); +} + +void exec_command_append_list(ExecCommand **l, ExecCommand *e) { + ExecCommand *end; + + assert(l); + assert(e); + + if (*l) { + /* It's kind of important, that we keep the order here */ + LIST_FIND_TAIL(command, *l, end); + LIST_INSERT_AFTER(command, *l, end, e); + } else + *l = e; +} + +int exec_command_set(ExecCommand *c, const char *path, ...) { + va_list ap; + char **l, *p; + + assert(c); + assert(path); + + va_start(ap, path); + l = strv_new_ap(path, ap); + va_end(ap); + + if (!l) + return -ENOMEM; + + p = strdup(path); + if (!p) { + strv_free(l); + return -ENOMEM; + } + + free_and_replace(c->path, p); + + return strv_free_and_replace(c->argv, l); +} + +int exec_command_append(ExecCommand *c, const char *path, ...) { + _cleanup_strv_free_ char **l = NULL; + va_list ap; + int r; + + assert(c); + assert(path); + + va_start(ap, path); + l = strv_new_ap(path, ap); + va_end(ap); + + if (!l) + return -ENOMEM; + + r = strv_extend_strv(&c->argv, l, false); + if (r < 0) + return r; + + return 0; +} + +static void *remove_tmpdir_thread(void *p) { + _cleanup_free_ char *path = p; + + (void) rm_rf(path, REMOVE_ROOT|REMOVE_PHYSICAL); + return NULL; +} + +static ExecRuntime* exec_runtime_free(ExecRuntime *rt, bool destroy) { + int r; + + if (!rt) + return NULL; + + if (rt->manager) + (void) hashmap_remove(rt->manager->exec_runtime_by_id, rt->id); + + /* When destroy is true, then rm_rf tmp_dir and var_tmp_dir. */ + if (destroy && rt->tmp_dir) { + log_debug("Spawning thread to nuke %s", rt->tmp_dir); + + r = asynchronous_job(remove_tmpdir_thread, rt->tmp_dir); + if (r < 0) { + log_warning_errno(r, "Failed to nuke %s: %m", rt->tmp_dir); + free(rt->tmp_dir); + } + + rt->tmp_dir = NULL; + } + + if (destroy && rt->var_tmp_dir) { + log_debug("Spawning thread to nuke %s", rt->var_tmp_dir); + + r = asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir); + if (r < 0) { + log_warning_errno(r, "Failed to nuke %s: %m", rt->var_tmp_dir); + free(rt->var_tmp_dir); + } + + rt->var_tmp_dir = NULL; + } + + rt->id = mfree(rt->id); + rt->tmp_dir = mfree(rt->tmp_dir); + rt->var_tmp_dir = mfree(rt->var_tmp_dir); + safe_close_pair(rt->netns_storage_socket); + return mfree(rt); +} + +static void exec_runtime_freep(ExecRuntime **rt) { + (void) exec_runtime_free(*rt, false); +} + +static int exec_runtime_allocate(ExecRuntime **ret) { + ExecRuntime *n; + + assert(ret); + + n = new(ExecRuntime, 1); + if (!n) + return -ENOMEM; + + *n = (ExecRuntime) { + .netns_storage_socket = { -1, -1 }, + }; + + *ret = n; + return 0; +} + +static int exec_runtime_add( + Manager *m, + const char *id, + const char *tmp_dir, + const char *var_tmp_dir, + const int netns_storage_socket[2], + ExecRuntime **ret) { + + _cleanup_(exec_runtime_freep) ExecRuntime *rt = NULL; + int r; + + assert(m); + assert(id); + + r = hashmap_ensure_allocated(&m->exec_runtime_by_id, &string_hash_ops); + if (r < 0) + return r; + + r = exec_runtime_allocate(&rt); + if (r < 0) + return r; + + rt->id = strdup(id); + if (!rt->id) + return -ENOMEM; + + if (tmp_dir) { + rt->tmp_dir = strdup(tmp_dir); + if (!rt->tmp_dir) + return -ENOMEM; + + /* When tmp_dir is set, then we require var_tmp_dir is also set. */ + assert(var_tmp_dir); + rt->var_tmp_dir = strdup(var_tmp_dir); + if (!rt->var_tmp_dir) + return -ENOMEM; + } + + if (netns_storage_socket) { + rt->netns_storage_socket[0] = netns_storage_socket[0]; + rt->netns_storage_socket[1] = netns_storage_socket[1]; + } + + r = hashmap_put(m->exec_runtime_by_id, rt->id, rt); + if (r < 0) + return r; + + rt->manager = m; + + if (ret) + *ret = rt; + + /* do not remove created ExecRuntime object when the operation succeeds. */ + rt = NULL; + return 0; +} + +static int exec_runtime_make(Manager *m, const ExecContext *c, const char *id, ExecRuntime **ret) { + _cleanup_free_ char *tmp_dir = NULL, *var_tmp_dir = NULL; + _cleanup_close_pair_ int netns_storage_socket[2] = { -1, -1 }; + int r; + + assert(m); + assert(c); + assert(id); + + /* It is not necessary to create ExecRuntime object. */ + if (!c->private_network && !c->private_tmp && !c->network_namespace_path) + return 0; + + if (c->private_tmp) { + r = setup_tmp_dirs(id, &tmp_dir, &var_tmp_dir); + if (r < 0) + return r; + } + + if (c->private_network || c->network_namespace_path) { + if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, netns_storage_socket) < 0) + return -errno; + } + + r = exec_runtime_add(m, id, tmp_dir, var_tmp_dir, netns_storage_socket, ret); + if (r < 0) + return r; + + /* Avoid cleanup */ + netns_storage_socket[0] = netns_storage_socket[1] = -1; + return 1; +} + +int exec_runtime_acquire(Manager *m, const ExecContext *c, const char *id, bool create, ExecRuntime **ret) { + ExecRuntime *rt; + int r; + + assert(m); + assert(id); + assert(ret); + + rt = hashmap_get(m->exec_runtime_by_id, id); + if (rt) + /* We already have a ExecRuntime object, let's increase the ref count and reuse it */ + goto ref; + + if (!create) + return 0; + + /* If not found, then create a new object. */ + r = exec_runtime_make(m, c, id, &rt); + if (r <= 0) + /* When r == 0, it is not necessary to create ExecRuntime object. */ + return r; + +ref: + /* increment reference counter. */ + rt->n_ref++; + *ret = rt; + return 1; +} + +ExecRuntime *exec_runtime_unref(ExecRuntime *rt, bool destroy) { + if (!rt) + return NULL; + + assert(rt->n_ref > 0); + + rt->n_ref--; + if (rt->n_ref > 0) + return NULL; + + return exec_runtime_free(rt, destroy); +} + +int exec_runtime_serialize(const Manager *m, FILE *f, FDSet *fds) { + ExecRuntime *rt; + Iterator i; + + assert(m); + assert(f); + assert(fds); + + HASHMAP_FOREACH(rt, m->exec_runtime_by_id, i) { + fprintf(f, "exec-runtime=%s", rt->id); + + if (rt->tmp_dir) + fprintf(f, " tmp-dir=%s", rt->tmp_dir); + + if (rt->var_tmp_dir) + fprintf(f, " var-tmp-dir=%s", rt->var_tmp_dir); + + if (rt->netns_storage_socket[0] >= 0) { + int copy; + + copy = fdset_put_dup(fds, rt->netns_storage_socket[0]); + if (copy < 0) + return copy; + + fprintf(f, " netns-socket-0=%i", copy); + } + + if (rt->netns_storage_socket[1] >= 0) { + int copy; + + copy = fdset_put_dup(fds, rt->netns_storage_socket[1]); + if (copy < 0) + return copy; + + fprintf(f, " netns-socket-1=%i", copy); + } + + fputc('\n', f); + } + + return 0; +} + +int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value, FDSet *fds) { + _cleanup_(exec_runtime_freep) ExecRuntime *rt_create = NULL; + ExecRuntime *rt; + int r; + + /* This is for the migration from old (v237 or earlier) deserialization text. + * Due to the bug #7790, this may not work with the units that use JoinsNamespaceOf=. + * Even if the ExecRuntime object originally created by the other unit, we cannot judge + * so or not from the serialized text, then we always creates a new object owned by this. */ + + assert(u); + assert(key); + assert(value); + + /* Manager manages ExecRuntime objects by the unit id. + * So, we omit the serialized text when the unit does not have id (yet?)... */ + if (isempty(u->id)) { + log_unit_debug(u, "Invocation ID not found. Dropping runtime parameter."); + return 0; + } + + r = hashmap_ensure_allocated(&u->manager->exec_runtime_by_id, &string_hash_ops); + if (r < 0) { + log_unit_debug_errno(u, r, "Failed to allocate storage for runtime parameter: %m"); + return 0; + } + + rt = hashmap_get(u->manager->exec_runtime_by_id, u->id); + if (!rt) { + r = exec_runtime_allocate(&rt_create); + if (r < 0) + return log_oom(); + + rt_create->id = strdup(u->id); + if (!rt_create->id) + return log_oom(); + + rt = rt_create; + } + + if (streq(key, "tmp-dir")) { + char *copy; + + copy = strdup(value); + if (!copy) + return log_oom(); + + free_and_replace(rt->tmp_dir, copy); + + } else if (streq(key, "var-tmp-dir")) { + char *copy; + + copy = strdup(value); + if (!copy) + return log_oom(); + + free_and_replace(rt->var_tmp_dir, copy); + + } else if (streq(key, "netns-socket-0")) { + int fd; + + if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) { + log_unit_debug(u, "Failed to parse netns socket value: %s", value); + return 0; + } + + safe_close(rt->netns_storage_socket[0]); + rt->netns_storage_socket[0] = fdset_remove(fds, fd); + + } else if (streq(key, "netns-socket-1")) { + int fd; + + if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) { + log_unit_debug(u, "Failed to parse netns socket value: %s", value); + return 0; + } + + safe_close(rt->netns_storage_socket[1]); + rt->netns_storage_socket[1] = fdset_remove(fds, fd); + } else + return 0; + + /* If the object is newly created, then put it to the hashmap which manages ExecRuntime objects. */ + if (rt_create) { + r = hashmap_put(u->manager->exec_runtime_by_id, rt_create->id, rt_create); + if (r < 0) { + log_unit_debug_errno(u, r, "Failed to put runtime parameter to manager's storage: %m"); + return 0; + } + + rt_create->manager = u->manager; + + /* Avoid cleanup */ + rt_create = NULL; + } + + return 1; +} + +void exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) { + char *id = NULL, *tmp_dir = NULL, *var_tmp_dir = NULL; + int r, fd0 = -1, fd1 = -1; + const char *p, *v = value; + size_t n; + + assert(m); + assert(value); + assert(fds); + + n = strcspn(v, " "); + id = strndupa(v, n); + if (v[n] != ' ') + goto finalize; + p = v + n + 1; + + v = startswith(p, "tmp-dir="); + if (v) { + n = strcspn(v, " "); + tmp_dir = strndupa(v, n); + if (v[n] != ' ') + goto finalize; + p = v + n + 1; + } + + v = startswith(p, "var-tmp-dir="); + if (v) { + n = strcspn(v, " "); + var_tmp_dir = strndupa(v, n); + if (v[n] != ' ') + goto finalize; + p = v + n + 1; + } + + v = startswith(p, "netns-socket-0="); + if (v) { + char *buf; + + n = strcspn(v, " "); + buf = strndupa(v, n); + if (safe_atoi(buf, &fd0) < 0 || !fdset_contains(fds, fd0)) { + log_debug("Unable to process exec-runtime netns fd specification."); + return; + } + fd0 = fdset_remove(fds, fd0); + if (v[n] != ' ') + goto finalize; + p = v + n + 1; + } + + v = startswith(p, "netns-socket-1="); + if (v) { + char *buf; + + n = strcspn(v, " "); + buf = strndupa(v, n); + if (safe_atoi(buf, &fd1) < 0 || !fdset_contains(fds, fd1)) { + log_debug("Unable to process exec-runtime netns fd specification."); + return; + } + fd1 = fdset_remove(fds, fd1); + } + +finalize: + + r = exec_runtime_add(m, id, tmp_dir, var_tmp_dir, (int[]) { fd0, fd1 }, NULL); + if (r < 0) + log_debug_errno(r, "Failed to add exec-runtime: %m"); +} + +void exec_runtime_vacuum(Manager *m) { + ExecRuntime *rt; + Iterator i; + + assert(m); + + /* Free unreferenced ExecRuntime objects. This is used after manager deserialization process. */ + + HASHMAP_FOREACH(rt, m->exec_runtime_by_id, i) { + if (rt->n_ref > 0) + continue; + + (void) exec_runtime_free(rt, false); + } +} + +void exec_params_clear(ExecParameters *p) { + if (!p) + return; + + strv_free(p->environment); +} + +static const char* const exec_input_table[_EXEC_INPUT_MAX] = { + [EXEC_INPUT_NULL] = "null", + [EXEC_INPUT_TTY] = "tty", + [EXEC_INPUT_TTY_FORCE] = "tty-force", + [EXEC_INPUT_TTY_FAIL] = "tty-fail", + [EXEC_INPUT_SOCKET] = "socket", + [EXEC_INPUT_NAMED_FD] = "fd", + [EXEC_INPUT_DATA] = "data", + [EXEC_INPUT_FILE] = "file", +}; + +DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput); + +static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = { + [EXEC_OUTPUT_INHERIT] = "inherit", + [EXEC_OUTPUT_NULL] = "null", + [EXEC_OUTPUT_TTY] = "tty", + [EXEC_OUTPUT_SYSLOG] = "syslog", + [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console", + [EXEC_OUTPUT_KMSG] = "kmsg", + [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console", + [EXEC_OUTPUT_JOURNAL] = "journal", + [EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console", + [EXEC_OUTPUT_SOCKET] = "socket", + [EXEC_OUTPUT_NAMED_FD] = "fd", + [EXEC_OUTPUT_FILE] = "file", + [EXEC_OUTPUT_FILE_APPEND] = "append", +}; + +DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput); + +static const char* const exec_utmp_mode_table[_EXEC_UTMP_MODE_MAX] = { + [EXEC_UTMP_INIT] = "init", + [EXEC_UTMP_LOGIN] = "login", + [EXEC_UTMP_USER] = "user", +}; + +DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode, ExecUtmpMode); + +static const char* const exec_preserve_mode_table[_EXEC_PRESERVE_MODE_MAX] = { + [EXEC_PRESERVE_NO] = "no", + [EXEC_PRESERVE_YES] = "yes", + [EXEC_PRESERVE_RESTART] = "restart", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode, ExecPreserveMode, EXEC_PRESERVE_YES); + +/* This table maps ExecDirectoryType to the setting it is configured with in the unit */ +static const char* const exec_directory_type_table[_EXEC_DIRECTORY_TYPE_MAX] = { + [EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory", + [EXEC_DIRECTORY_STATE] = "StateDirectory", + [EXEC_DIRECTORY_CACHE] = "CacheDirectory", + [EXEC_DIRECTORY_LOGS] = "LogsDirectory", + [EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectory", +}; + +DEFINE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType); + +/* And this table maps ExecDirectoryType too, but to a generic term identifying the type of resource. This + * one is supposed to be generic enough to be used for unit types that don't use ExecContext and per-unit + * directories, specifically .timer units with their timestamp touch file. */ +static const char* const exec_resource_type_table[_EXEC_DIRECTORY_TYPE_MAX] = { + [EXEC_DIRECTORY_RUNTIME] = "runtime", + [EXEC_DIRECTORY_STATE] = "state", + [EXEC_DIRECTORY_CACHE] = "cache", + [EXEC_DIRECTORY_LOGS] = "logs", + [EXEC_DIRECTORY_CONFIGURATION] = "configuration", +}; + +DEFINE_STRING_TABLE_LOOKUP(exec_resource_type, ExecDirectoryType); + +/* And this table also maps ExecDirectoryType, to the environment variable we pass the selected directory to + * the service payload in. */ +static const char* const exec_directory_env_name_table[_EXEC_DIRECTORY_TYPE_MAX] = { + [EXEC_DIRECTORY_RUNTIME] = "RUNTIME_DIRECTORY", + [EXEC_DIRECTORY_STATE] = "STATE_DIRECTORY", + [EXEC_DIRECTORY_CACHE] = "CACHE_DIRECTORY", + [EXEC_DIRECTORY_LOGS] = "LOGS_DIRECTORY", + [EXEC_DIRECTORY_CONFIGURATION] = "CONFIGURATION_DIRECTORY", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(exec_directory_env_name, ExecDirectoryType); + +static const char* const exec_keyring_mode_table[_EXEC_KEYRING_MODE_MAX] = { + [EXEC_KEYRING_INHERIT] = "inherit", + [EXEC_KEYRING_PRIVATE] = "private", + [EXEC_KEYRING_SHARED] = "shared", +}; + +DEFINE_STRING_TABLE_LOOKUP(exec_keyring_mode, ExecKeyringMode); diff --git a/src/core/execute.h b/src/core/execute.h new file mode 100644 index 00000000..c923b1fa --- /dev/null +++ b/src/core/execute.h @@ -0,0 +1,424 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct ExecStatus ExecStatus; +typedef struct ExecCommand ExecCommand; +typedef struct ExecContext ExecContext; +typedef struct ExecRuntime ExecRuntime; +typedef struct ExecParameters ExecParameters; +typedef struct Manager Manager; + +#include +#include +#include +#include + +#include "cgroup-util.h" +#include "cpu-set-util.h" +#include "exec-util.h" +#include "fdset.h" +#include "list.h" +#include "missing_resource.h" +#include "namespace.h" +#include "nsflags.h" +#include "time-util.h" + +#define EXEC_STDIN_DATA_MAX (64U*1024U*1024U) + +typedef enum ExecUtmpMode { + EXEC_UTMP_INIT, + EXEC_UTMP_LOGIN, + EXEC_UTMP_USER, + _EXEC_UTMP_MODE_MAX, + _EXEC_UTMP_MODE_INVALID = -1 +} ExecUtmpMode; + +typedef enum ExecInput { + EXEC_INPUT_NULL, + EXEC_INPUT_TTY, + EXEC_INPUT_TTY_FORCE, + EXEC_INPUT_TTY_FAIL, + EXEC_INPUT_SOCKET, + EXEC_INPUT_NAMED_FD, + EXEC_INPUT_DATA, + EXEC_INPUT_FILE, + _EXEC_INPUT_MAX, + _EXEC_INPUT_INVALID = -1 +} ExecInput; + +typedef enum ExecOutput { + EXEC_OUTPUT_INHERIT, + EXEC_OUTPUT_NULL, + EXEC_OUTPUT_TTY, + EXEC_OUTPUT_SYSLOG, + EXEC_OUTPUT_SYSLOG_AND_CONSOLE, + EXEC_OUTPUT_KMSG, + EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_JOURNAL, + EXEC_OUTPUT_JOURNAL_AND_CONSOLE, + EXEC_OUTPUT_SOCKET, + EXEC_OUTPUT_NAMED_FD, + EXEC_OUTPUT_FILE, + EXEC_OUTPUT_FILE_APPEND, + _EXEC_OUTPUT_MAX, + _EXEC_OUTPUT_INVALID = -1 +} ExecOutput; + +typedef enum ExecPreserveMode { + EXEC_PRESERVE_NO, + EXEC_PRESERVE_YES, + EXEC_PRESERVE_RESTART, + _EXEC_PRESERVE_MODE_MAX, + _EXEC_PRESERVE_MODE_INVALID = -1 +} ExecPreserveMode; + +typedef enum ExecKeyringMode { + EXEC_KEYRING_INHERIT, + EXEC_KEYRING_PRIVATE, + EXEC_KEYRING_SHARED, + _EXEC_KEYRING_MODE_MAX, + _EXEC_KEYRING_MODE_INVALID = -1, +} ExecKeyringMode; + +/* Contains start and exit information about an executed command. */ +struct ExecStatus { + dual_timestamp start_timestamp; + dual_timestamp exit_timestamp; + pid_t pid; + int code; /* as in siginfo_t::si_code */ + int status; /* as in sigingo_t::si_status */ +}; + +/* Stores information about commands we execute. Covers both configuration settings as well as runtime data. */ +struct ExecCommand { + char *path; + char **argv; + ExecStatus exec_status; + ExecCommandFlags flags; + LIST_FIELDS(ExecCommand, command); /* useful for chaining commands */ +}; + +/* Encapsulates certain aspects of the runtime environment that is to be shared between multiple otherwise separate + * invocations of commands. Specifically, this allows sharing of /tmp and /var/tmp data as well as network namespaces + * between invocations of commands. This is a reference counted object, with one reference taken by each currently + * active command invocation that wants to share this runtime. */ +struct ExecRuntime { + unsigned n_ref; + + Manager *manager; + + char *id; /* Unit id of the owner */ + + char *tmp_dir; + char *var_tmp_dir; + + /* An AF_UNIX socket pair, that contains a datagram containing a file descriptor referring to the network + * namespace. */ + int netns_storage_socket[2]; +}; + +typedef enum ExecDirectoryType { + EXEC_DIRECTORY_RUNTIME = 0, + EXEC_DIRECTORY_STATE, + EXEC_DIRECTORY_CACHE, + EXEC_DIRECTORY_LOGS, + EXEC_DIRECTORY_CONFIGURATION, + _EXEC_DIRECTORY_TYPE_MAX, + _EXEC_DIRECTORY_TYPE_INVALID = -1, +} ExecDirectoryType; + +typedef struct ExecDirectory { + char **paths; + mode_t mode; +} ExecDirectory; + +typedef enum ExecCleanMask { + /* In case you wonder why the bitmask below doesn't use "directory" in its name: we want to keep this + * generic so that .timer timestamp files can nicely be covered by this too, and similar. */ + EXEC_CLEAN_RUNTIME = 1U << EXEC_DIRECTORY_RUNTIME, + EXEC_CLEAN_STATE = 1U << EXEC_DIRECTORY_STATE, + EXEC_CLEAN_CACHE = 1U << EXEC_DIRECTORY_CACHE, + EXEC_CLEAN_LOGS = 1U << EXEC_DIRECTORY_LOGS, + EXEC_CLEAN_CONFIGURATION = 1U << EXEC_DIRECTORY_CONFIGURATION, + EXEC_CLEAN_NONE = 0, + EXEC_CLEAN_ALL = (1U << _EXEC_DIRECTORY_TYPE_MAX) - 1, + _EXEC_CLEAN_MASK_INVALID = -1, +} ExecCleanMask; + +/* Encodes configuration parameters applied to invoked commands. Does not carry runtime data, but only configuration + * changes sourced from unit files and suchlike. ExecContext objects are usually embedded into Unit objects, and do not + * change after being loaded. */ +struct ExecContext { + char **environment; + char **environment_files; + char **pass_environment; + char **unset_environment; + + struct rlimit *rlimit[_RLIMIT_MAX]; + char *working_directory, *root_directory, *root_image; + bool working_directory_missing_ok:1; + bool working_directory_home:1; + + bool oom_score_adjust_set:1; + bool nice_set:1; + bool ioprio_set:1; + bool cpu_sched_set:1; + + /* This is not exposed to the user but available internally. We need it to make sure that whenever we + * spawn /usr/bin/mount it is run in the same process group as us so that the autofs logic detects + * that it belongs to us and we don't enter a trigger loop. */ + bool same_pgrp; + + bool cpu_sched_reset_on_fork; + bool non_blocking; + + mode_t umask; + int oom_score_adjust; + int nice; + int ioprio; + int cpu_sched_policy; + int cpu_sched_priority; + + CPUSet cpu_set; + NUMAPolicy numa_policy; + + ExecInput std_input; + ExecOutput std_output; + ExecOutput std_error; + bool stdio_as_fds; + char *stdio_fdname[3]; + char *stdio_file[3]; + + void *stdin_data; + size_t stdin_data_size; + + nsec_t timer_slack_nsec; + + char *tty_path; + + bool tty_reset; + bool tty_vhangup; + bool tty_vt_disallocate; + + bool ignore_sigpipe; + + ExecKeyringMode keyring_mode; + + /* Since resolving these names might involve socket + * connections and we don't want to deadlock ourselves these + * names are resolved on execution only and in the child + * process. */ + char *user; + char *group; + char **supplementary_groups; + + char *pam_name; + + char *utmp_id; + ExecUtmpMode utmp_mode; + + bool no_new_privileges; + + bool selinux_context_ignore; + bool apparmor_profile_ignore; + bool smack_process_label_ignore; + + char *selinux_context; + char *apparmor_profile; + char *smack_process_label; + + char **read_write_paths, **read_only_paths, **inaccessible_paths; + unsigned long mount_flags; + BindMount *bind_mounts; + size_t n_bind_mounts; + TemporaryFileSystem *temporary_filesystems; + size_t n_temporary_filesystems; + + uint64_t capability_bounding_set; + uint64_t capability_ambient_set; + int secure_bits; + + int syslog_priority; + bool syslog_level_prefix; + char *syslog_identifier; + + struct iovec* log_extra_fields; + size_t n_log_extra_fields; + + usec_t log_ratelimit_interval_usec; + unsigned log_ratelimit_burst; + + int log_level_max; + + bool private_tmp; + bool private_network; + bool private_devices; + bool private_users; + bool private_mounts; + bool protect_kernel_tunables; + bool protect_kernel_modules; + bool protect_kernel_logs; + bool protect_control_groups; + ProtectSystem protect_system; + ProtectHome protect_home; + bool protect_hostname; + bool mount_apivfs; + + bool dynamic_user; + bool remove_ipc; + + bool memory_deny_write_execute; + bool restrict_realtime; + bool restrict_suid_sgid; + + bool lock_personality; + unsigned long personality; + + unsigned long restrict_namespaces; /* The CLONE_NEWxyz flags permitted to the unit's processes */ + + Hashmap *syscall_filter; + Set *syscall_archs; + int syscall_errno; + bool syscall_whitelist:1; + + bool address_families_whitelist:1; + Set *address_families; + + char *network_namespace_path; + + ExecDirectory directories[_EXEC_DIRECTORY_TYPE_MAX]; + ExecPreserveMode runtime_directory_preserve_mode; + usec_t timeout_clean_usec; +}; + +static inline bool exec_context_restrict_namespaces_set(const ExecContext *c) { + assert(c); + + return (c->restrict_namespaces & NAMESPACE_FLAGS_ALL) != NAMESPACE_FLAGS_ALL; +} + +typedef enum ExecFlags { + EXEC_APPLY_SANDBOXING = 1 << 0, + EXEC_APPLY_CHROOT = 1 << 1, + EXEC_APPLY_TTY_STDIN = 1 << 2, + EXEC_PASS_LOG_UNIT = 1 << 3, /* Whether to pass the unit name to the service's journal stream connection */ + EXEC_CHOWN_DIRECTORIES = 1 << 4, /* chown() the runtime/state/cache/log directories to the user we run as, under all conditions */ + EXEC_NSS_BYPASS_BUS = 1 << 5, /* Set the SYSTEMD_NSS_BYPASS_BUS environment variable, to disable nss-systemd for dbus */ + EXEC_CGROUP_DELEGATE = 1 << 6, + EXEC_IS_CONTROL = 1 << 7, + EXEC_CONTROL_CGROUP = 1 << 8, /* Place the process not in the indicated cgroup but in a subcgroup '/.control', but only EXEC_CGROUP_DELEGATE and EXEC_IS_CONTROL is set, too */ + + /* The following are not used by execute.c, but by consumers internally */ + EXEC_PASS_FDS = 1 << 9, + EXEC_SETENV_RESULT = 1 << 10, + EXEC_SET_WATCHDOG = 1 << 11, +} ExecFlags; + +/* Parameters for a specific invocation of a command. This structure is put together right before a command is + * executed. */ +struct ExecParameters { + char **environment; + + int *fds; + char **fd_names; + size_t n_socket_fds; + size_t n_storage_fds; + + ExecFlags flags; + bool selinux_context_net:1; + + CGroupMask cgroup_supported; + const char *cgroup_path; + + char **prefix; + + const char *confirm_spawn; + + usec_t watchdog_usec; + + int *idle_pipe; + + int stdin_fd; + int stdout_fd; + int stderr_fd; + + /* An fd that is closed by the execve(), and thus will result in EOF when the execve() is done */ + int exec_fd; +}; + +#include "unit.h" +#include "dynamic-user.h" + +int exec_spawn(Unit *unit, + ExecCommand *command, + const ExecContext *context, + const ExecParameters *exec_params, + ExecRuntime *runtime, + DynamicCreds *dynamic_creds, + pid_t *ret); + +void exec_command_done_array(ExecCommand *c, size_t n); +ExecCommand* exec_command_free_list(ExecCommand *c); +void exec_command_free_array(ExecCommand **c, size_t n); +void exec_command_reset_status_array(ExecCommand *c, size_t n); +void exec_command_reset_status_list_array(ExecCommand **c, size_t n); +void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix); +void exec_command_append_list(ExecCommand **l, ExecCommand *e); +int exec_command_set(ExecCommand *c, const char *path, ...) _sentinel_; +int exec_command_append(ExecCommand *c, const char *path, ...) _sentinel_; + +void exec_context_init(ExecContext *c); +void exec_context_done(ExecContext *c); +void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix); + +int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_root); + +const char* exec_context_fdname(const ExecContext *c, int fd_index); + +bool exec_context_may_touch_console(const ExecContext *c); +bool exec_context_maintains_privileges(const ExecContext *c); + +int exec_context_get_effective_ioprio(const ExecContext *c); + +void exec_context_free_log_extra_fields(ExecContext *c); + +void exec_context_revert_tty(ExecContext *c); + +int exec_context_get_clean_directories(ExecContext *c, char **prefix, ExecCleanMask mask, char ***ret); +int exec_context_get_clean_mask(ExecContext *c, ExecCleanMask *ret); + +void exec_status_start(ExecStatus *s, pid_t pid); +void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int code, int status); +void exec_status_dump(const ExecStatus *s, FILE *f, const char *prefix); +void exec_status_reset(ExecStatus *s); + +int exec_runtime_acquire(Manager *m, const ExecContext *c, const char *name, bool create, ExecRuntime **ret); +ExecRuntime *exec_runtime_unref(ExecRuntime *r, bool destroy); + +int exec_runtime_serialize(const Manager *m, FILE *f, FDSet *fds); +int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value, FDSet *fds); +void exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds); +void exec_runtime_vacuum(Manager *m); + +void exec_params_clear(ExecParameters *p); + +const char* exec_output_to_string(ExecOutput i) _const_; +ExecOutput exec_output_from_string(const char *s) _pure_; + +const char* exec_input_to_string(ExecInput i) _const_; +ExecInput exec_input_from_string(const char *s) _pure_; + +const char* exec_utmp_mode_to_string(ExecUtmpMode i) _const_; +ExecUtmpMode exec_utmp_mode_from_string(const char *s) _pure_; + +const char* exec_preserve_mode_to_string(ExecPreserveMode i) _const_; +ExecPreserveMode exec_preserve_mode_from_string(const char *s) _pure_; + +const char* exec_keyring_mode_to_string(ExecKeyringMode i) _const_; +ExecKeyringMode exec_keyring_mode_from_string(const char *s) _pure_; + +const char* exec_directory_type_to_string(ExecDirectoryType i) _const_; +ExecDirectoryType exec_directory_type_from_string(const char *s) _pure_; + +const char* exec_resource_type_to_string(ExecDirectoryType i) _const_; +ExecDirectoryType exec_resource_type_from_string(const char *s) _pure_; diff --git a/src/core/hostname-setup.c b/src/core/hostname-setup.c new file mode 100644 index 00000000..83cce881 --- /dev/null +++ b/src/core/hostname-setup.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fileio.h" +#include "hostname-setup.h" +#include "hostname-util.h" +#include "log.h" +#include "macro.h" +#include "string-util.h" +#include "util.h" + +int hostname_setup(void) { + _cleanup_free_ char *b = NULL; + bool enoent = false; + const char *hn; + int r; + + r = read_etc_hostname(NULL, &b); + if (r < 0) { + if (r == -ENOENT) + enoent = true; + else + log_warning_errno(r, "Failed to read configured hostname: %m"); + + hn = NULL; + } else + hn = b; + + if (isempty(hn)) { + /* Don't override the hostname if it is already set + * and not explicitly configured */ + if (hostname_is_set()) + return 0; + + if (enoent) + log_info("No hostname configured."); + + hn = FALLBACK_HOSTNAME; + } + + r = sethostname_idempotent(hn); + if (r < 0) + return log_warning_errno(r, "Failed to set hostname to <%s>: %m", hn); + + log_info("Set hostname to <%s>.", hn); + return 0; +} diff --git a/src/core/hostname-setup.h b/src/core/hostname-setup.h new file mode 100644 index 00000000..dc7b9a62 --- /dev/null +++ b/src/core/hostname-setup.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int hostname_setup(void); diff --git a/src/core/ima-setup.c b/src/core/ima-setup.c new file mode 100644 index 00000000..17072b09 --- /dev/null +++ b/src/core/ima-setup.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2012 Roberto Sassu - Politecnico di Torino, Italy + TORSEC group — http://security.polito.it +***/ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "ima-setup.h" +#include "log.h" + +#define IMA_SECFS_DIR "/sys/kernel/security/ima" +#define IMA_SECFS_POLICY IMA_SECFS_DIR "/policy" +#define IMA_POLICY_PATH "/etc/ima/ima-policy" + +int ima_setup(void) { +#if ENABLE_IMA + _cleanup_fclose_ FILE *input = NULL; + _cleanup_close_ int imafd = -1; + unsigned lineno = 0; + int r; + + if (access(IMA_SECFS_DIR, F_OK) < 0) { + log_debug_errno(errno, "IMA support is disabled in the kernel, ignoring: %m"); + return 0; + } + + if (access(IMA_SECFS_POLICY, W_OK) < 0) { + log_warning_errno(errno, "Another IMA custom policy has already been loaded, ignoring: %m"); + return 0; + } + + if (access(IMA_POLICY_PATH, F_OK) < 0) { + log_debug_errno(errno, "No IMA custom policy file "IMA_POLICY_PATH", ignoring: %m"); + return 0; + } + + imafd = open(IMA_SECFS_POLICY, O_WRONLY|O_CLOEXEC); + if (imafd < 0) { + log_error_errno(errno, "Failed to open the IMA kernel interface "IMA_SECFS_POLICY", ignoring: %m"); + return 0; + } + + /* attempt to write the name of the policy file into sysfs file */ + if (write(imafd, IMA_POLICY_PATH, STRLEN(IMA_POLICY_PATH)) > 0) + goto done; + + /* fall back to copying the policy line-by-line */ + input = fopen(IMA_POLICY_PATH, "re"); + if (!input) { + log_warning_errno(errno, "Failed to open the IMA custom policy file "IMA_POLICY_PATH", ignoring: %m"); + return 0; + } + + safe_close(imafd); + + imafd = open(IMA_SECFS_POLICY, O_WRONLY|O_CLOEXEC); + if (imafd < 0) { + log_error_errno(errno, "Failed to open the IMA kernel interface "IMA_SECFS_POLICY", ignoring: %m"); + return 0; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + size_t len; + + r = read_line(input, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read the IMA custom policy file "IMA_POLICY_PATH": %m"); + if (r == 0) + break; + + len = strlen(line); + lineno++; + + if (len > 0 && write(imafd, line, len) < 0) + return log_error_errno(errno, "Failed to load the IMA custom policy file "IMA_POLICY_PATH"%u: %m", + lineno); + } + +done: + log_info("Successfully loaded the IMA custom policy "IMA_POLICY_PATH"."); +#endif /* ENABLE_IMA */ + return 0; +} diff --git a/src/core/ima-setup.h b/src/core/ima-setup.h new file mode 100644 index 00000000..cf478795 --- /dev/null +++ b/src/core/ima-setup.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2012 Roberto Sassu - Politecnico di Torino, Italy + TORSEC group — http://security.polito.it +***/ + +int ima_setup(void); diff --git a/src/core/ip-address-access.c b/src/core/ip-address-access.c new file mode 100644 index 00000000..db87b12a --- /dev/null +++ b/src/core/ip-address-access.c @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "bpf-firewall.h" +#include "extract-word.h" +#include "hostname-util.h" +#include "ip-address-access.h" +#include "parse-util.h" +#include "string-util.h" + +int config_parse_ip_address_access( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + IPAddressAccessItem **list = data; + const char *p; + int r; + + assert(list); + + if (isempty(rvalue)) { + *list = ip_address_access_free_all(*list); + return 0; + } + + p = rvalue; + + for (;;) { + _cleanup_free_ IPAddressAccessItem *a = NULL; + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + break; + } + + a = new0(IPAddressAccessItem, 1); + if (!a) + return log_oom(); + + if (streq(word, "any")) { + /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */ + + a->family = AF_INET; + LIST_APPEND(items, *list, a); + + a = new0(IPAddressAccessItem, 1); + if (!a) + return log_oom(); + + a->family = AF_INET6; + + } else if (is_localhost(word)) { + /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */ + + a->family = AF_INET; + a->address.in.s_addr = htobe32(0x7f000000); + a->prefixlen = 8; + LIST_APPEND(items, *list, a); + + a = new0(IPAddressAccessItem, 1); + if (!a) + return log_oom(); + + a->family = AF_INET6; + a->address.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT; + a->prefixlen = 128; + + } else if (streq(word, "link-local")) { + + /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */ + + a->family = AF_INET; + a->address.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16)); + a->prefixlen = 16; + LIST_APPEND(items, *list, a); + + a = new0(IPAddressAccessItem, 1); + if (!a) + return log_oom(); + + a->family = AF_INET6; + a->address.in6 = (struct in6_addr) { + .s6_addr32[0] = htobe32(0xfe800000) + }; + a->prefixlen = 64; + + } else if (streq(word, "multicast")) { + + /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */ + + a->family = AF_INET; + a->address.in.s_addr = htobe32((UINT32_C(224) << 24)); + a->prefixlen = 4; + LIST_APPEND(items, *list, a); + + a = new0(IPAddressAccessItem, 1); + if (!a) + return log_oom(); + + a->family = AF_INET6; + a->address.in6 = (struct in6_addr) { + .s6_addr32[0] = htobe32(0xff000000) + }; + a->prefixlen = 8; + + } else { + r = in_addr_prefix_from_string_auto(word, &a->family, &a->address, &a->prefixlen); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Address prefix is invalid, ignoring assignment: %s", word); + return 0; + } + } + + LIST_APPEND(items, *list, a); + a = NULL; + } + + *list = ip_address_access_reduce(*list); + + return 0; +} + +IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first) { + IPAddressAccessItem *next, *p = first; + + while (p) { + next = p->items_next; + free(p); + + p = next; + } + + return NULL; +} + +IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first) { + IPAddressAccessItem *a, *b, *tmp; + int r; + + /* Drops all entries from the list that are covered by another entry in full, thus removing all redundant + * entries. */ + + LIST_FOREACH_SAFE(items, a, tmp, first) { + + /* Drop irrelevant bits */ + (void) in_addr_mask(a->family, &a->address, a->prefixlen); + + LIST_FOREACH(items, b, first) { + + if (a == b) + continue; + + if (a->family != b->family) + continue; + + if (b->prefixlen > a->prefixlen) + continue; + + r = in_addr_prefix_covers(b->family, + &b->address, + b->prefixlen, + &a->address); + if (r > 0) { + /* b covers a fully, then let's drop a */ + LIST_REMOVE(items, first, a); + free(a); + break; + } + } + } + + return first; +} + +bool ip_address_access_item_is_any(IPAddressAccessItem *first) { + /* Check for exactly two entries */ + if (!first || !first->items_next || first->items_next->items_next) + return false; + + /* Check both entries cover the full range */ + if (first->prefixlen != 0 || first->items_next->prefixlen != 0) + return false; + + /* Check that one of them is the IPv4 and the other IPv6 */ + if (!((first->family == AF_INET && first->items_next->family == AF_INET6) || + (first->family == AF_INET6 && first->items_next->family == AF_INET))) + return false; + + /* No need to check the actual addresses, they don't matter if the prefix is zero */ + return true; +} diff --git a/src/core/ip-address-access.h b/src/core/ip-address-access.h new file mode 100644 index 00000000..8d3ab731 --- /dev/null +++ b/src/core/ip-address-access.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "in-addr-util.h" +#include "list.h" + +typedef struct IPAddressAccessItem IPAddressAccessItem; + +struct IPAddressAccessItem { + int family; + unsigned char prefixlen; + union in_addr_union address; + LIST_FIELDS(IPAddressAccessItem, items); +}; + +CONFIG_PARSER_PROTOTYPE(config_parse_ip_address_access); + +IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first); + +IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first); + +/* Returns true if a list consists of only the two items necessary for "any" + * (0.0.0.0/0 and ::/0). */ +bool ip_address_access_item_is_any(IPAddressAccessItem *first); diff --git a/src/core/job.c b/src/core/job.c new file mode 100644 index 00000000..5048a509 --- /dev/null +++ b/src/core/job.c @@ -0,0 +1,1686 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-id128.h" +#include "sd-messages.h" + +#include "alloc-util.h" +#include "async.h" +#include "cgroup.h" +#include "dbus-job.h" +#include "dbus.h" +#include "escape.h" +#include "fileio.h" +#include "job.h" +#include "log.h" +#include "macro.h" +#include "parse-util.h" +#include "serialize.h" +#include "set.h" +#include "sort-util.h" +#include "special.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "unit.h" +#include "virt.h" + +Job* job_new_raw(Unit *unit) { + Job *j; + + /* used for deserialization */ + + assert(unit); + + j = new(Job, 1); + if (!j) + return NULL; + + *j = (Job) { + .manager = unit->manager, + .unit = unit, + .type = _JOB_TYPE_INVALID, + }; + + return j; +} + +Job* job_new(Unit *unit, JobType type) { + Job *j; + + assert(type < _JOB_TYPE_MAX); + + j = job_new_raw(unit); + if (!j) + return NULL; + + j->id = j->manager->current_job_id++; + j->type = type; + + /* We don't link it here, that's what job_dependency() is for */ + + return j; +} + +void job_unlink(Job *j) { + assert(j); + assert(!j->installed); + assert(!j->transaction_prev); + assert(!j->transaction_next); + assert(!j->subject_list); + assert(!j->object_list); + + if (j->in_run_queue) { + prioq_remove(j->manager->run_queue, j, &j->run_queue_idx); + j->in_run_queue = false; + } + + if (j->in_dbus_queue) { + LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j); + j->in_dbus_queue = false; + } + + if (j->in_gc_queue) { + LIST_REMOVE(gc_queue, j->manager->gc_job_queue, j); + j->in_gc_queue = false; + } + + j->timer_event_source = sd_event_source_unref(j->timer_event_source); +} + +Job* job_free(Job *j) { + assert(j); + assert(!j->installed); + assert(!j->transaction_prev); + assert(!j->transaction_next); + assert(!j->subject_list); + assert(!j->object_list); + + job_unlink(j); + + sd_bus_track_unref(j->bus_track); + strv_free(j->deserialized_clients); + + return mfree(j); +} + +static void job_set_state(Job *j, JobState state) { + assert(j); + assert(state >= 0); + assert(state < _JOB_STATE_MAX); + + if (j->state == state) + return; + + j->state = state; + + if (!j->installed) + return; + + if (j->state == JOB_RUNNING) + j->unit->manager->n_running_jobs++; + else { + assert(j->state == JOB_WAITING); + assert(j->unit->manager->n_running_jobs > 0); + + j->unit->manager->n_running_jobs--; + + if (j->unit->manager->n_running_jobs <= 0) + j->unit->manager->jobs_in_progress_event_source = sd_event_source_unref(j->unit->manager->jobs_in_progress_event_source); + } +} + +void job_uninstall(Job *j) { + Job **pj; + + assert(j->installed); + + job_set_state(j, JOB_WAITING); + + pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job; + assert(*pj == j); + + /* Detach from next 'bigger' objects */ + + /* daemon-reload should be transparent to job observers */ + if (!MANAGER_IS_RELOADING(j->manager)) + bus_job_send_removed_signal(j); + + *pj = NULL; + + unit_add_to_gc_queue(j->unit); + + unit_add_to_dbus_queue(j->unit); /* The Job property of the unit has changed now */ + + hashmap_remove_value(j->manager->jobs, UINT32_TO_PTR(j->id), j); + j->installed = false; +} + +static bool job_type_allows_late_merge(JobType t) { + /* Tells whether it is OK to merge a job of type 't' with an already + * running job. + * Reloads cannot be merged this way. Think of the sequence: + * 1. Reload of a daemon is in progress; the daemon has already loaded + * its config file, but hasn't completed the reload operation yet. + * 2. Edit foo's config file. + * 3. Trigger another reload to have the daemon use the new config. + * Should the second reload job be merged into the first one, the daemon + * would not know about the new config. + * JOB_RESTART jobs on the other hand can be merged, because they get + * patched into JOB_START after stopping the unit. So if we see a + * JOB_RESTART running, it means the unit hasn't stopped yet and at + * this time the merge is still allowed. */ + return t != JOB_RELOAD; +} + +static void job_merge_into_installed(Job *j, Job *other) { + assert(j->installed); + assert(j->unit == other->unit); + + if (j->type != JOB_NOP) + assert_se(job_type_merge_and_collapse(&j->type, other->type, j->unit) == 0); + else + assert(other->type == JOB_NOP); + + j->irreversible = j->irreversible || other->irreversible; + j->ignore_order = j->ignore_order || other->ignore_order; +} + +Job* job_install(Job *j) { + Job **pj; + Job *uj; + + assert(!j->installed); + assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION); + assert(j->state == JOB_WAITING); + + pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job; + uj = *pj; + + if (uj) { + if (job_type_is_conflicting(uj->type, j->type)) + job_finish_and_invalidate(uj, JOB_CANCELED, false, false); + else { + /* not conflicting, i.e. mergeable */ + + if (uj->state == JOB_WAITING || + (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) { + job_merge_into_installed(uj, j); + log_unit_debug(uj->unit, + "Merged %s/%s into installed job %s/%s as %"PRIu32, + j->unit->id, job_type_to_string(j->type), uj->unit->id, + job_type_to_string(uj->type), uj->id); + return uj; + } else { + /* already running and not safe to merge into */ + /* Patch uj to become a merged job and re-run it. */ + /* XXX It should be safer to queue j to run after uj finishes, but it is + * not currently possible to have more than one installed job per unit. */ + job_merge_into_installed(uj, j); + log_unit_debug(uj->unit, + "Merged into running job, re-running: %s/%s as %"PRIu32, + uj->unit->id, job_type_to_string(uj->type), uj->id); + + job_set_state(uj, JOB_WAITING); + return uj; + } + } + } + + /* Install the job */ + *pj = j; + j->installed = true; + + j->manager->n_installed_jobs++; + log_unit_debug(j->unit, + "Installed new job %s/%s as %u", + j->unit->id, job_type_to_string(j->type), (unsigned) j->id); + + job_add_to_gc_queue(j); + + job_add_to_dbus_queue(j); /* announce this job to clients */ + unit_add_to_dbus_queue(j->unit); /* The Job property of the unit has changed now */ + + return j; +} + +int job_install_deserialized(Job *j) { + Job **pj; + int r; + + assert(!j->installed); + + if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) + return log_unit_debug_errno(j->unit, SYNTHETIC_ERRNO(EINVAL), + "Invalid job type %s in deserialization.", + strna(job_type_to_string(j->type))); + + pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job; + if (*pj) + return log_unit_debug_errno(j->unit, SYNTHETIC_ERRNO(EEXIST), + "Unit already has a job installed. Not installing deserialized job."); + + r = hashmap_put(j->manager->jobs, UINT32_TO_PTR(j->id), j); + if (r == -EEXIST) + return log_unit_debug_errno(j->unit, r, "Job ID %" PRIu32 " already used, cannot deserialize job.", j->id); + if (r < 0) + return log_unit_debug_errno(j->unit, r, "Failed to insert job into jobs hash table: %m"); + + *pj = j; + j->installed = true; + + if (j->state == JOB_RUNNING) + j->unit->manager->n_running_jobs++; + + log_unit_debug(j->unit, + "Reinstalled deserialized job %s/%s as %u", + j->unit->id, job_type_to_string(j->type), (unsigned) j->id); + return 0; +} + +JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) { + JobDependency *l; + + assert(object); + + /* Adds a new job link, which encodes that the 'subject' job + * needs the 'object' job in some way. If 'subject' is NULL + * this means the 'anchor' job (i.e. the one the user + * explicitly asked for) is the requester. */ + + l = new0(JobDependency, 1); + if (!l) + return NULL; + + l->subject = subject; + l->object = object; + l->matters = matters; + l->conflicts = conflicts; + + if (subject) + LIST_PREPEND(subject, subject->subject_list, l); + + LIST_PREPEND(object, object->object_list, l); + + return l; +} + +void job_dependency_free(JobDependency *l) { + assert(l); + + if (l->subject) + LIST_REMOVE(subject, l->subject->subject_list, l); + + LIST_REMOVE(object, l->object->object_list, l); + + free(l); +} + +void job_dump(Job *j, FILE *f, const char *prefix) { + assert(j); + assert(f); + + prefix = strempty(prefix); + + fprintf(f, + "%s-> Job %u:\n" + "%s\tAction: %s -> %s\n" + "%s\tState: %s\n" + "%s\tIrreversible: %s\n" + "%s\tMay GC: %s\n", + prefix, j->id, + prefix, j->unit->id, job_type_to_string(j->type), + prefix, job_state_to_string(j->state), + prefix, yes_no(j->irreversible), + prefix, yes_no(job_may_gc(j))); +} + +/* + * Merging is commutative, so imagine the matrix as symmetric. We store only + * its lower triangle to avoid duplication. We don't store the main diagonal, + * because A merged with A is simply A. + * + * If the resulting type is collapsed immediately afterwards (to get rid of + * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain), + * the following properties hold: + * + * Merging is associative! A merged with B, and then merged with C is the same + * as A merged with the result of B merged with C. + * + * Mergeability is transitive! If A can be merged with B and B with C then + * A also with C. + * + * Also, if A merged with B cannot be merged with C, then either A or B cannot + * be merged with C either. + */ +static const JobType job_merging_table[] = { +/* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */ +/*********************************************************************************/ +/*JOB_START */ +/*JOB_VERIFY_ACTIVE */ JOB_START, +/*JOB_STOP */ -1, -1, +/*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1, +/*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART, +}; + +JobType job_type_lookup_merge(JobType a, JobType b) { + assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2); + assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING); + assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING); + + if (a == b) + return a; + + if (a < b) { + JobType tmp = a; + a = b; + b = tmp; + } + + return job_merging_table[(a - 1) * a / 2 + b]; +} + +bool job_type_is_redundant(JobType a, UnitActiveState b) { + switch (a) { + + case JOB_START: + return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING); + + case JOB_STOP: + return IN_SET(b, UNIT_INACTIVE, UNIT_FAILED); + + case JOB_VERIFY_ACTIVE: + return IN_SET(b, UNIT_ACTIVE, UNIT_RELOADING); + + case JOB_RELOAD: + return + b == UNIT_RELOADING; + + case JOB_RESTART: + return + b == UNIT_ACTIVATING; + + case JOB_NOP: + return true; + + default: + assert_not_reached("Invalid job type"); + } +} + +JobType job_type_collapse(JobType t, Unit *u) { + UnitActiveState s; + + switch (t) { + + case JOB_TRY_RESTART: + s = unit_active_state(u); + if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) + return JOB_NOP; + + return JOB_RESTART; + + case JOB_TRY_RELOAD: + s = unit_active_state(u); + if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) + return JOB_NOP; + + return JOB_RELOAD; + + case JOB_RELOAD_OR_START: + s = unit_active_state(u); + if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) + return JOB_START; + + return JOB_RELOAD; + + default: + return t; + } +} + +int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) { + JobType t; + + t = job_type_lookup_merge(*a, b); + if (t < 0) + return -EEXIST; + + *a = job_type_collapse(t, u); + return 0; +} + +static bool job_is_runnable(Job *j) { + Iterator i; + Unit *other; + void *v; + + assert(j); + assert(j->installed); + + /* Checks whether there is any job running for the units this + * job needs to be running after (in the case of a 'positive' + * job type) or before (in the case of a 'negative' job + * type. */ + + /* Note that unit types have a say in what is runnable, + * too. For example, if they return -EAGAIN from + * unit_start() they can indicate they are not + * runnable yet. */ + + /* First check if there is an override */ + if (j->ignore_order) + return true; + + if (j->type == JOB_NOP) + return true; + + HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) + if (other->job && job_compare(j, other->job, UNIT_AFTER) > 0) + return false; + + HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) + if (other->job && job_compare(j, other->job, UNIT_BEFORE) > 0) + return false; + + return true; +} + +static void job_change_type(Job *j, JobType newtype) { + assert(j); + + log_unit_debug(j->unit, + "Converting job %s/%s -> %s/%s", + j->unit->id, job_type_to_string(j->type), + j->unit->id, job_type_to_string(newtype)); + + j->type = newtype; +} + +_pure_ static const char* job_get_begin_status_message_format(Unit *u, JobType t) { + const char *format; + + assert(u); + + if (t == JOB_RELOAD) + return "Reloading %s."; + + assert(IN_SET(t, JOB_START, JOB_STOP)); + + format = UNIT_VTABLE(u)->status_message_formats.starting_stopping[t == JOB_STOP]; + if (format) + return format; + + /* Return generic strings */ + if (t == JOB_START) + return "Starting %s."; + else { + assert(t == JOB_STOP); + return "Stopping %s."; + } +} + +static void job_print_begin_status_message(Unit *u, JobType t) { + const char *format; + + assert(u); + + /* Reload status messages have traditionally not been printed to console. */ + if (!IN_SET(t, JOB_START, JOB_STOP)) + return; + + format = job_get_begin_status_message_format(u, t); + + DISABLE_WARNING_FORMAT_NONLITERAL; + unit_status_printf(u, "", format); + REENABLE_WARNING; +} + +static void job_log_begin_status_message(Unit *u, uint32_t job_id, JobType t) { + const char *format, *mid; + char buf[LINE_MAX]; + + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + + if (!IN_SET(t, JOB_START, JOB_STOP, JOB_RELOAD)) + return; + + if (log_on_console()) /* Skip this if it would only go on the console anyway */ + return; + + /* We log status messages for all units and all operations. */ + + format = job_get_begin_status_message_format(u, t); + + DISABLE_WARNING_FORMAT_NONLITERAL; + (void) snprintf(buf, sizeof buf, format, unit_status_string(u)); + REENABLE_WARNING; + + mid = t == JOB_START ? "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTING_STR : + t == JOB_STOP ? "MESSAGE_ID=" SD_MESSAGE_UNIT_STOPPING_STR : + "MESSAGE_ID=" SD_MESSAGE_UNIT_RELOADING_STR; + + /* Note that we deliberately use LOG_MESSAGE() instead of + * LOG_UNIT_MESSAGE() here, since this is supposed to mimic + * closely what is written to screen using the status output, + * which is supposed the highest level, friendliest output + * possible, which means we should avoid the low-level unit + * name. */ + log_struct(LOG_INFO, + LOG_MESSAGE("%s", buf), + "JOB_ID=%" PRIu32, job_id, + "JOB_TYPE=%s", job_type_to_string(t), + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u), + mid); +} + +static void job_emit_begin_status_message(Unit *u, uint32_t job_id, JobType t) { + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + + job_log_begin_status_message(u, job_id, t); + job_print_begin_status_message(u, t); +} + +static int job_perform_on_unit(Job **j) { + uint32_t id; + Manager *m; + JobType t; + Unit *u; + int r; + + /* While we execute this operation the job might go away (for + * example: because it finishes immediately or is replaced by + * a new, conflicting job.) To make sure we don't access a + * freed job later on we store the id here, so that we can + * verify the job is still valid. */ + + assert(j); + assert(*j); + + m = (*j)->manager; + u = (*j)->unit; + t = (*j)->type; + id = (*j)->id; + + switch (t) { + case JOB_START: + r = unit_start(u); + break; + + case JOB_RESTART: + t = JOB_STOP; + _fallthrough_; + case JOB_STOP: + r = unit_stop(u); + break; + + case JOB_RELOAD: + r = unit_reload(u); + break; + + default: + assert_not_reached("Invalid job type"); + } + + /* Log if the job still exists and the start/stop/reload function actually did something. Note that this means + * for units for which there's no 'activating' phase (i.e. because we transition directly from 'inactive' to + * 'active') we'll possibly skip the "Starting..." message. */ + *j = manager_get_job(m, id); + if (*j && r > 0) + job_emit_begin_status_message(u, id, t); + + return r; +} + +int job_run_and_invalidate(Job *j) { + int r; + + assert(j); + assert(j->installed); + assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION); + assert(j->in_run_queue); + + prioq_remove(j->manager->run_queue, j, &j->run_queue_idx); + j->in_run_queue = false; + + if (j->state != JOB_WAITING) + return 0; + + if (!job_is_runnable(j)) + return -EAGAIN; + + job_start_timer(j, true); + job_set_state(j, JOB_RUNNING); + job_add_to_dbus_queue(j); + + switch (j->type) { + + case JOB_VERIFY_ACTIVE: { + UnitActiveState t; + + t = unit_active_state(j->unit); + if (UNIT_IS_ACTIVE_OR_RELOADING(t)) + r = -EALREADY; + else if (t == UNIT_ACTIVATING) + r = -EAGAIN; + else + r = -EBADR; + break; + } + + case JOB_START: + case JOB_STOP: + case JOB_RESTART: + r = job_perform_on_unit(&j); + + /* If the unit type does not support starting/stopping, then simply wait. */ + if (r == -EBADR) + r = 0; + break; + + case JOB_RELOAD: + r = job_perform_on_unit(&j); + break; + + case JOB_NOP: + r = -EALREADY; + break; + + default: + assert_not_reached("Unknown job type"); + } + + if (j) { + if (r == -EAGAIN) + job_set_state(j, JOB_WAITING); /* Hmm, not ready after all, let's return to JOB_WAITING state */ + else if (r == -EALREADY) /* already being executed */ + r = job_finish_and_invalidate(j, JOB_DONE, true, true); + else if (r == -ECOMM) /* condition failed, but all is good */ + r = job_finish_and_invalidate(j, JOB_DONE, true, false); + else if (r == -EBADR) + r = job_finish_and_invalidate(j, JOB_SKIPPED, true, false); + else if (r == -ENOEXEC) + r = job_finish_and_invalidate(j, JOB_INVALID, true, false); + else if (r == -EPROTO) + r = job_finish_and_invalidate(j, JOB_ASSERT, true, false); + else if (r == -EOPNOTSUPP) + r = job_finish_and_invalidate(j, JOB_UNSUPPORTED, true, false); + else if (r == -ENOLINK) + r = job_finish_and_invalidate(j, JOB_DEPENDENCY, true, false); + else if (r == -ESTALE) + r = job_finish_and_invalidate(j, JOB_ONCE, true, false); + else if (r < 0) + r = job_finish_and_invalidate(j, JOB_FAILED, true, false); + } + + return r; +} + +_pure_ static const char *job_get_done_status_message_format(Unit *u, JobType t, JobResult result) { + + static const char *const generic_finished_start_job[_JOB_RESULT_MAX] = { + [JOB_DONE] = "Started %s.", + [JOB_TIMEOUT] = "Timed out starting %s.", + [JOB_FAILED] = "Failed to start %s.", + [JOB_DEPENDENCY] = "Dependency failed for %s.", + [JOB_ASSERT] = "Assertion failed for %s.", + [JOB_UNSUPPORTED] = "Starting of %s not supported.", + [JOB_COLLECTED] = "Unnecessary job for %s was removed.", + [JOB_ONCE] = "Unit %s has been started before and cannot be started again." + }; + static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = { + [JOB_DONE] = "Stopped %s.", + [JOB_FAILED] = "Stopped (with error) %s.", + [JOB_TIMEOUT] = "Timed out stopping %s.", + }; + static const char *const generic_finished_reload_job[_JOB_RESULT_MAX] = { + [JOB_DONE] = "Reloaded %s.", + [JOB_FAILED] = "Reload failed for %s.", + [JOB_TIMEOUT] = "Timed out reloading %s.", + }; + /* When verify-active detects the unit is inactive, report it. + * Most likely a DEPEND warning from a requisiting unit will + * occur next and it's nice to see what was requisited. */ + static const char *const generic_finished_verify_active_job[_JOB_RESULT_MAX] = { + [JOB_SKIPPED] = "%s is not active.", + }; + + const char *format; + + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + + if (IN_SET(t, JOB_START, JOB_STOP, JOB_RESTART)) { + format = t == JOB_START ? + UNIT_VTABLE(u)->status_message_formats.finished_start_job[result] : + UNIT_VTABLE(u)->status_message_formats.finished_stop_job[result]; + if (format) + return format; + } + + /* Return generic strings */ + if (t == JOB_START) + return generic_finished_start_job[result]; + else if (IN_SET(t, JOB_STOP, JOB_RESTART)) + return generic_finished_stop_job[result]; + else if (t == JOB_RELOAD) + return generic_finished_reload_job[result]; + else if (t == JOB_VERIFY_ACTIVE) + return generic_finished_verify_active_job[result]; + + return NULL; +} + +static const struct { + const char *color, *word; +} job_print_done_status_messages[_JOB_RESULT_MAX] = { + [JOB_DONE] = { ANSI_OK_COLOR, " OK " }, + [JOB_TIMEOUT] = { ANSI_HIGHLIGHT_RED, " TIME " }, + [JOB_FAILED] = { ANSI_HIGHLIGHT_RED, "FAILED" }, + [JOB_DEPENDENCY] = { ANSI_HIGHLIGHT_YELLOW, "DEPEND" }, + [JOB_SKIPPED] = { ANSI_HIGHLIGHT, " INFO " }, + [JOB_ASSERT] = { ANSI_HIGHLIGHT_YELLOW, "ASSERT" }, + [JOB_UNSUPPORTED] = { ANSI_HIGHLIGHT_YELLOW, "UNSUPP" }, + /* JOB_COLLECTED */ + [JOB_ONCE] = { ANSI_HIGHLIGHT_RED, " ONCE " }, +}; + +static void job_print_done_status_message(Unit *u, JobType t, JobResult result) { + const char *format; + const char *status; + + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + + /* Reload status messages have traditionally not been printed to console. */ + if (t == JOB_RELOAD) + return; + + /* No message if the job did not actually do anything due to failed condition. */ + if (t == JOB_START && result == JOB_DONE && !u->condition_result) + return; + + if (!job_print_done_status_messages[result].word) + return; + + format = job_get_done_status_message_format(u, t, result); + if (!format) + return; + + if (log_get_show_color()) + status = strjoina(job_print_done_status_messages[result].color, + job_print_done_status_messages[result].word, + ANSI_NORMAL); + else + status = job_print_done_status_messages[result].word; + + if (result != JOB_DONE) + manager_flip_auto_status(u->manager, true); + + DISABLE_WARNING_FORMAT_NONLITERAL; + unit_status_printf(u, status, format); + REENABLE_WARNING; + + if (t == JOB_START && result == JOB_FAILED) { + _cleanup_free_ char *quoted; + + quoted = shell_maybe_quote(u->id, ESCAPE_BACKSLASH); + manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted)); + } +} + +static void job_log_done_status_message(Unit *u, uint32_t job_id, JobType t, JobResult result) { + const char *format, *mid; + char buf[LINE_MAX]; + static const int job_result_log_level[_JOB_RESULT_MAX] = { + [JOB_DONE] = LOG_INFO, + [JOB_CANCELED] = LOG_INFO, + [JOB_TIMEOUT] = LOG_ERR, + [JOB_FAILED] = LOG_ERR, + [JOB_DEPENDENCY] = LOG_WARNING, + [JOB_SKIPPED] = LOG_NOTICE, + [JOB_INVALID] = LOG_INFO, + [JOB_ASSERT] = LOG_WARNING, + [JOB_UNSUPPORTED] = LOG_WARNING, + [JOB_COLLECTED] = LOG_INFO, + [JOB_ONCE] = LOG_ERR, + }; + + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + + /* Skip printing if output goes to the console, and job_print_status_message() + will actually print something to the console. */ + if (log_on_console() && job_print_done_status_messages[result].word) + return; + + /* Show condition check message if the job did not actually do anything due to failed condition. */ + if ((t == JOB_START && result == JOB_DONE && !u->condition_result) || + (t == JOB_START && result == JOB_SKIPPED)) { + log_struct(LOG_INFO, + "MESSAGE=Condition check resulted in %s being skipped.", unit_status_string(u), + "JOB_ID=%" PRIu32, job_id, + "JOB_TYPE=%s", job_type_to_string(t), + "JOB_RESULT=%s", job_result_to_string(result), + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u), + "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTED_STR); + + return; + } + + format = job_get_done_status_message_format(u, t, result); + if (!format) + return; + + /* The description might be longer than the buffer, but that's OK, + * we'll just truncate it here. Note that we use snprintf() rather than + * xsprintf() on purpose here: we are fine with truncation and don't + * consider that an error. */ + DISABLE_WARNING_FORMAT_NONLITERAL; + (void) snprintf(buf, sizeof(buf), format, unit_status_string(u)); + REENABLE_WARNING; + + switch (t) { + + case JOB_START: + if (result == JOB_DONE) + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_STARTED_STR; + else + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_FAILED_STR; + break; + + case JOB_RELOAD: + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_RELOADED_STR; + break; + + case JOB_STOP: + case JOB_RESTART: + mid = "MESSAGE_ID=" SD_MESSAGE_UNIT_STOPPED_STR; + break; + + default: + log_struct(job_result_log_level[result], + LOG_MESSAGE("%s", buf), + "JOB_ID=%" PRIu32, job_id, + "JOB_TYPE=%s", job_type_to_string(t), + "JOB_RESULT=%s", job_result_to_string(result), + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u)); + return; + } + + log_struct(job_result_log_level[result], + LOG_MESSAGE("%s", buf), + "JOB_ID=%" PRIu32, job_id, + "JOB_TYPE=%s", job_type_to_string(t), + "JOB_RESULT=%s", job_result_to_string(result), + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u), + mid); +} + +static void job_emit_done_status_message(Unit *u, uint32_t job_id, JobType t, JobResult result) { + assert(u); + + job_log_done_status_message(u, job_id, t, result); + job_print_done_status_message(u, t, result); +} + +static void job_fail_dependencies(Unit *u, UnitDependency d) { + Unit *other; + Iterator i; + void *v; + + assert(u); + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[d], i) { + Job *j = other->job; + + if (!j) + continue; + if (!IN_SET(j->type, JOB_START, JOB_VERIFY_ACTIVE)) + continue; + + job_finish_and_invalidate(j, JOB_DEPENDENCY, true, false); + } +} + +int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already) { + Unit *u; + Unit *other; + JobType t; + Iterator i; + void *v; + + assert(j); + assert(j->installed); + assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION); + + u = j->unit; + t = j->type; + + j->result = result; + + log_unit_debug(u, "Job %" PRIu32 " %s/%s finished, result=%s", j->id, u->id, job_type_to_string(t), job_result_to_string(result)); + + /* If this job did nothing to respective unit we don't log the status message */ + if (!already) + job_emit_done_status_message(u, j->id, t, result); + + /* Patch restart jobs so that they become normal start jobs */ + if (result == JOB_DONE && t == JOB_RESTART) { + + job_change_type(j, JOB_START); + job_set_state(j, JOB_WAITING); + + job_add_to_dbus_queue(j); + job_add_to_run_queue(j); + job_add_to_gc_queue(j); + + goto finish; + } + + if (IN_SET(result, JOB_FAILED, JOB_INVALID)) + j->manager->n_failed_jobs++; + + job_uninstall(j); + job_free(j); + + /* Fail depending jobs on failure */ + if (result != JOB_DONE && recursive) { + if (IN_SET(t, JOB_START, JOB_VERIFY_ACTIVE)) { + job_fail_dependencies(u, UNIT_REQUIRED_BY); + job_fail_dependencies(u, UNIT_REQUISITE_OF); + job_fail_dependencies(u, UNIT_BOUND_BY); + } else if (t == JOB_STOP) + job_fail_dependencies(u, UNIT_CONFLICTED_BY); + } + + /* A special check to make sure we take down anything RequisiteOf if we + * aren't active. This is when the verify-active job merges with a + * satisfying job type, and then loses it's invalidation effect, as the + * result there is JOB_DONE for the start job we merged into, while we + * should be failing the depending job if the said unit isn't infact + * active. Oneshots are an example of this, where going directly from + * activating to inactive is success. + * + * This happens when you use ConditionXYZ= in a unit too, since in that + * case the job completes with the JOB_DONE result, but the unit never + * really becomes active. Note that such a case still involves merging: + * + * A start job waits for something else, and a verify-active comes in + * and merges in the installed job. Then, later, when it becomes + * runnable, it finishes with JOB_DONE result as execution on conditions + * not being met is skipped, breaking our dependency semantics. + * + * Also, depending on if start job waits or not, the merging may or may + * not happen (the verify-active job may trigger after it finishes), so + * you get undeterministic results without this check. + */ + if (result == JOB_DONE && recursive && !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) { + if (IN_SET(t, JOB_START, JOB_RELOAD)) + job_fail_dependencies(u, UNIT_REQUISITE_OF); + } + /* Trigger OnFailure dependencies that are not generated by + * the unit itself. We don't treat JOB_CANCELED as failure in + * this context. And JOB_FAILURE is already handled by the + * unit itself. */ + if (IN_SET(result, JOB_TIMEOUT, JOB_DEPENDENCY)) { + log_struct(LOG_NOTICE, + "JOB_TYPE=%s", job_type_to_string(t), + "JOB_RESULT=%s", job_result_to_string(result), + LOG_UNIT_ID(u), + LOG_UNIT_MESSAGE(u, "Job %s/%s failed with result '%s'.", + u->id, + job_type_to_string(t), + job_result_to_string(result))); + + unit_start_on_failure(u); + } + + unit_trigger_notify(u); + +finish: + /* Try to start the next jobs that can be started */ + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_AFTER], i) + if (other->job) { + job_add_to_run_queue(other->job); + job_add_to_gc_queue(other->job); + } + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BEFORE], i) + if (other->job) { + job_add_to_run_queue(other->job); + job_add_to_gc_queue(other->job); + } + + manager_check_finished(u->manager); + + return 0; +} + +static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *userdata) { + Job *j = userdata; + Unit *u; + + assert(j); + assert(s == j->timer_event_source); + + log_unit_warning(j->unit, "Job %s/%s timed out.", j->unit->id, job_type_to_string(j->type)); + + u = j->unit; + job_finish_and_invalidate(j, JOB_TIMEOUT, true, false); + + emergency_action(u->manager, u->job_timeout_action, + EMERGENCY_ACTION_IS_WATCHDOG|EMERGENCY_ACTION_WARN, + u->job_timeout_reboot_arg, -1, "job timed out"); + + return 0; +} + +int job_start_timer(Job *j, bool job_running) { + int r; + usec_t timeout_time, old_timeout_time; + + if (job_running) { + j->begin_running_usec = now(CLOCK_MONOTONIC); + + if (j->unit->job_running_timeout == USEC_INFINITY) + return 0; + + timeout_time = usec_add(j->begin_running_usec, j->unit->job_running_timeout); + + if (j->timer_event_source) { + /* Update only if JobRunningTimeoutSec= results in earlier timeout */ + r = sd_event_source_get_time(j->timer_event_source, &old_timeout_time); + if (r < 0) + return r; + + if (old_timeout_time <= timeout_time) + return 0; + + return sd_event_source_set_time(j->timer_event_source, timeout_time); + } + } else { + if (j->timer_event_source) + return 0; + + j->begin_usec = now(CLOCK_MONOTONIC); + + if (j->unit->job_timeout == USEC_INFINITY) + return 0; + + timeout_time = usec_add(j->begin_usec, j->unit->job_timeout); + } + + r = sd_event_add_time( + j->manager->event, + &j->timer_event_source, + CLOCK_MONOTONIC, + timeout_time, 0, + job_dispatch_timer, j); + if (r < 0) + return r; + + (void) sd_event_source_set_description(j->timer_event_source, "job-start"); + + return 0; +} + +void job_add_to_run_queue(Job *j) { + int r; + + assert(j); + assert(j->installed); + + if (j->in_run_queue) + return; + + if (prioq_isempty(j->manager->run_queue)) { + r = sd_event_source_set_enabled(j->manager->run_queue_event_source, SD_EVENT_ONESHOT); + if (r < 0) + log_warning_errno(r, "Failed to enable job run queue event source, ignoring: %m"); + } + + r = prioq_put(j->manager->run_queue, j, &j->run_queue_idx); + if (r < 0) + log_warning_errno(r, "Failed put job in run queue, ignoring: %m"); + else + j->in_run_queue = true; +} + +void job_add_to_dbus_queue(Job *j) { + assert(j); + assert(j->installed); + + if (j->in_dbus_queue) + return; + + /* We don't check if anybody is subscribed here, since this + * job might just have been created and not yet assigned to a + * connection/client. */ + + LIST_PREPEND(dbus_queue, j->manager->dbus_job_queue, j); + j->in_dbus_queue = true; +} + +char *job_dbus_path(Job *j) { + char *p; + + assert(j); + + if (asprintf(&p, "/org/freedesktop/systemd1/job/%"PRIu32, j->id) < 0) + return NULL; + + return p; +} + +int job_serialize(Job *j, FILE *f) { + assert(j); + assert(f); + + (void) serialize_item_format(f, "job-id", "%u", j->id); + (void) serialize_item(f, "job-type", job_type_to_string(j->type)); + (void) serialize_item(f, "job-state", job_state_to_string(j->state)); + (void) serialize_bool(f, "job-irreversible", j->irreversible); + (void) serialize_bool(f, "job-sent-dbus-new-signal", j->sent_dbus_new_signal); + (void) serialize_bool(f, "job-ignore-order", j->ignore_order); + + if (j->begin_usec > 0) + (void) serialize_usec(f, "job-begin", j->begin_usec); + if (j->begin_running_usec > 0) + (void) serialize_usec(f, "job-begin-running", j->begin_running_usec); + + bus_track_serialize(j->bus_track, f, "subscribed"); + + /* End marker */ + fputc('\n', f); + return 0; +} + +int job_deserialize(Job *j, FILE *f) { + int r; + + assert(j); + assert(f); + + for (;;) { + _cleanup_free_ char *line = NULL; + char *l, *v; + size_t k; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) + return 0; + + l = strstrip(line); + + /* End marker */ + if (isempty(l)) + return 0; + + k = strcspn(l, "="); + + if (l[k] == '=') { + l[k] = 0; + v = l+k+1; + } else + v = l+k; + + if (streq(l, "job-id")) { + + if (safe_atou32(v, &j->id) < 0) + log_debug("Failed to parse job id value: %s", v); + + } else if (streq(l, "job-type")) { + JobType t; + + t = job_type_from_string(v); + if (t < 0) + log_debug("Failed to parse job type: %s", v); + else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION) + log_debug("Cannot deserialize job of type: %s", v); + else + j->type = t; + + } else if (streq(l, "job-state")) { + JobState s; + + s = job_state_from_string(v); + if (s < 0) + log_debug("Failed to parse job state: %s", v); + else + job_set_state(j, s); + + } else if (streq(l, "job-irreversible")) { + int b; + + b = parse_boolean(v); + if (b < 0) + log_debug("Failed to parse job irreversible flag: %s", v); + else + j->irreversible = j->irreversible || b; + + } else if (streq(l, "job-sent-dbus-new-signal")) { + int b; + + b = parse_boolean(v); + if (b < 0) + log_debug("Failed to parse job sent_dbus_new_signal flag: %s", v); + else + j->sent_dbus_new_signal = j->sent_dbus_new_signal || b; + + } else if (streq(l, "job-ignore-order")) { + int b; + + b = parse_boolean(v); + if (b < 0) + log_debug("Failed to parse job ignore_order flag: %s", v); + else + j->ignore_order = j->ignore_order || b; + + } else if (streq(l, "job-begin")) + (void) deserialize_usec(v, &j->begin_usec); + + else if (streq(l, "job-begin-running")) + (void) deserialize_usec(v, &j->begin_running_usec); + + else if (streq(l, "subscribed")) { + if (strv_extend(&j->deserialized_clients, v) < 0) + return log_oom(); + } else + log_debug("Unknown job serialization key: %s", l); + } +} + +int job_coldplug(Job *j) { + int r; + usec_t timeout_time = USEC_INFINITY; + + assert(j); + + /* After deserialization is complete and the bus connection + * set up again, let's start watching our subscribers again */ + (void) bus_job_coldplug_bus_track(j); + + if (j->state == JOB_WAITING) + job_add_to_run_queue(j); + + /* Maybe due to new dependencies we don't actually need this job anymore? */ + job_add_to_gc_queue(j); + + /* Create timer only when job began or began running and the respective timeout is finite. + * Follow logic of job_start_timer() if both timeouts are finite */ + if (j->begin_usec == 0) + return 0; + + if (j->unit->job_timeout != USEC_INFINITY) + timeout_time = usec_add(j->begin_usec, j->unit->job_timeout); + + if (timestamp_is_set(j->begin_running_usec)) + timeout_time = MIN(timeout_time, usec_add(j->begin_running_usec, j->unit->job_running_timeout)); + + if (timeout_time == USEC_INFINITY) + return 0; + + j->timer_event_source = sd_event_source_unref(j->timer_event_source); + + r = sd_event_add_time( + j->manager->event, + &j->timer_event_source, + CLOCK_MONOTONIC, + timeout_time, 0, + job_dispatch_timer, j); + if (r < 0) + log_debug_errno(r, "Failed to restart timeout for job: %m"); + + (void) sd_event_source_set_description(j->timer_event_source, "job-timeout"); + + return r; +} + +void job_shutdown_magic(Job *j) { + assert(j); + + /* The shutdown target gets some special treatment here: we + * tell the kernel to begin with flushing its disk caches, to + * optimize shutdown time a bit. Ideally we wouldn't hardcode + * this magic into PID 1. However all other processes aren't + * options either since they'd exit much sooner than PID 1 and + * asynchronous sync() would cause their exit to be + * delayed. */ + + if (j->type != JOB_START) + return; + + if (!MANAGER_IS_SYSTEM(j->unit->manager)) + return; + + if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET)) + return; + + /* In case messages on console has been disabled on boot */ + j->unit->manager->no_console_output = false; + + if (detect_container() > 0) + return; + + (void) asynchronous_sync(NULL); +} + +int job_get_timeout(Job *j, usec_t *timeout) { + usec_t x = USEC_INFINITY, y = USEC_INFINITY; + Unit *u = j->unit; + int r; + + assert(u); + + if (j->timer_event_source) { + r = sd_event_source_get_time(j->timer_event_source, &x); + if (r < 0) + return r; + } + + if (UNIT_VTABLE(u)->get_timeout) { + r = UNIT_VTABLE(u)->get_timeout(u, &y); + if (r < 0) + return r; + } + + if (x == USEC_INFINITY && y == USEC_INFINITY) + return 0; + + *timeout = MIN(x, y); + return 1; +} + +bool job_may_gc(Job *j) { + Unit *other; + Iterator i; + void *v; + + assert(j); + + /* Checks whether this job should be GC'ed away. We only do this for jobs of units that have no effect on their + * own and just track external state. For now the only unit type that qualifies for this are .device units. + * Returns true if the job can be collected. */ + + if (!UNIT_VTABLE(j->unit)->gc_jobs) + return false; + + if (sd_bus_track_count(j->bus_track) > 0) + return false; + + /* FIXME: So this is a bit ugly: for now we don't properly track references made via private bus connections + * (because it's nasty, as sd_bus_track doesn't apply to it). We simply remember that the job was once + * referenced by one, and reset this whenever we notice that no private bus connections are around. This means + * the GC is a bit too conservative when it comes to jobs created by private bus connections. */ + if (j->ref_by_private_bus) { + if (set_isempty(j->unit->manager->private_buses)) + j->ref_by_private_bus = false; + else + return false; + } + + if (j->type == JOB_NOP) + return false; + + /* The logic is inverse to job_is_runnable, we cannot GC as long as we block any job. */ + HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) + if (other->job && job_compare(j, other->job, UNIT_BEFORE) < 0) + return false; + + HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) + if (other->job && job_compare(j, other->job, UNIT_AFTER) < 0) + return false; + + return true; +} + +void job_add_to_gc_queue(Job *j) { + assert(j); + + if (j->in_gc_queue) + return; + + if (!job_may_gc(j)) + return; + + LIST_PREPEND(gc_queue, j->unit->manager->gc_job_queue, j); + j->in_gc_queue = true; +} + +static int job_compare_id(Job * const *a, Job * const *b) { + return CMP((*a)->id, (*b)->id); +} + +static size_t sort_job_list(Job **list, size_t n) { + Job *previous = NULL; + size_t a, b; + + /* Order by numeric IDs */ + typesafe_qsort(list, n, job_compare_id); + + /* Filter out duplicates */ + for (a = 0, b = 0; a < n; a++) { + + if (previous == list[a]) + continue; + + previous = list[b++] = list[a]; + } + + return b; +} + +int job_get_before(Job *j, Job*** ret) { + _cleanup_free_ Job** list = NULL; + size_t n = 0, n_allocated = 0; + Unit *other = NULL; + Iterator i; + void *v; + + /* Returns a list of all pending jobs that need to finish before this job may be started. */ + + assert(j); + assert(ret); + + if (j->ignore_order) { + *ret = NULL; + return 0; + } + + HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) { + if (!other->job) + continue; + if (job_compare(j, other->job, UNIT_AFTER) <= 0) + continue; + + if (!GREEDY_REALLOC(list, n_allocated, n+1)) + return -ENOMEM; + list[n++] = other->job; + } + + HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) { + if (!other->job) + continue; + if (job_compare(j, other->job, UNIT_BEFORE) <= 0) + continue; + + if (!GREEDY_REALLOC(list, n_allocated, n+1)) + return -ENOMEM; + list[n++] = other->job; + } + + n = sort_job_list(list, n); + + *ret = TAKE_PTR(list); + + return (int) n; +} + +int job_get_after(Job *j, Job*** ret) { + _cleanup_free_ Job** list = NULL; + size_t n = 0, n_allocated = 0; + Unit *other = NULL; + void *v; + Iterator i; + + assert(j); + assert(ret); + + /* Returns a list of all pending jobs that are waiting for this job to finish. */ + + HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) { + if (!other->job) + continue; + + if (other->job->ignore_order) + continue; + + if (job_compare(j, other->job, UNIT_BEFORE) >= 0) + continue; + + if (!GREEDY_REALLOC(list, n_allocated, n+1)) + return -ENOMEM; + list[n++] = other->job; + } + + HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) { + if (!other->job) + continue; + + if (other->job->ignore_order) + continue; + + if (job_compare(j, other->job, UNIT_AFTER) >= 0) + continue; + + if (!GREEDY_REALLOC(list, n_allocated, n+1)) + return -ENOMEM; + list[n++] = other->job; + } + + n = sort_job_list(list, n); + + *ret = TAKE_PTR(list); + + return (int) n; +} + +static const char* const job_state_table[_JOB_STATE_MAX] = { + [JOB_WAITING] = "waiting", + [JOB_RUNNING] = "running", +}; + +DEFINE_STRING_TABLE_LOOKUP(job_state, JobState); + +static const char* const job_type_table[_JOB_TYPE_MAX] = { + [JOB_START] = "start", + [JOB_VERIFY_ACTIVE] = "verify-active", + [JOB_STOP] = "stop", + [JOB_RELOAD] = "reload", + [JOB_RELOAD_OR_START] = "reload-or-start", + [JOB_RESTART] = "restart", + [JOB_TRY_RESTART] = "try-restart", + [JOB_TRY_RELOAD] = "try-reload", + [JOB_NOP] = "nop", +}; + +DEFINE_STRING_TABLE_LOOKUP(job_type, JobType); + +static const char* const job_mode_table[_JOB_MODE_MAX] = { + [JOB_FAIL] = "fail", + [JOB_REPLACE] = "replace", + [JOB_REPLACE_IRREVERSIBLY] = "replace-irreversibly", + [JOB_ISOLATE] = "isolate", + [JOB_FLUSH] = "flush", + [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies", + [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements", + [JOB_TRIGGERING] = "triggering", +}; + +DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode); + +static const char* const job_result_table[_JOB_RESULT_MAX] = { + [JOB_DONE] = "done", + [JOB_CANCELED] = "canceled", + [JOB_TIMEOUT] = "timeout", + [JOB_FAILED] = "failed", + [JOB_DEPENDENCY] = "dependency", + [JOB_SKIPPED] = "skipped", + [JOB_INVALID] = "invalid", + [JOB_ASSERT] = "assert", + [JOB_UNSUPPORTED] = "unsupported", + [JOB_COLLECTED] = "collected", + [JOB_ONCE] = "once", +}; + +DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult); + +const char* job_type_to_access_method(JobType t) { + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + + if (IN_SET(t, JOB_START, JOB_RESTART, JOB_TRY_RESTART)) + return "start"; + else if (t == JOB_STOP) + return "stop"; + else + return "reload"; +} + +/* + * assume_dep assumed dependency between units (a is before/after b) + * + * Returns + * 0 jobs are independent, + * >0 a should run after b, + * <0 a should run before b, + * + * The logic means that for a service a and a service b where b.After=a: + * + * start a + start b → 1st step start a, 2nd step start b + * start a + stop b → 1st step stop b, 2nd step start a + * stop a + start b → 1st step stop a, 2nd step start b + * stop a + stop b → 1st step stop b, 2nd step stop a + * + * This has the side effect that restarts are properly + * synchronized too. + */ +int job_compare(Job *a, Job *b, UnitDependency assume_dep) { + assert(a->type < _JOB_TYPE_MAX_IN_TRANSACTION); + assert(b->type < _JOB_TYPE_MAX_IN_TRANSACTION); + assert(IN_SET(assume_dep, UNIT_AFTER, UNIT_BEFORE)); + + /* Trivial cases first */ + if (a->type == JOB_NOP || b->type == JOB_NOP) + return 0; + + if (a->ignore_order || b->ignore_order) + return 0; + + if (assume_dep == UNIT_AFTER) + return -job_compare(b, a, UNIT_BEFORE); + + /* Let's make it simple, JOB_STOP goes always first (in case both ua and ub stop, + * then ub's stop goes first anyway). + * JOB_RESTART is JOB_STOP in disguise (before it is patched to JOB_START). */ + if (IN_SET(b->type, JOB_STOP, JOB_RESTART)) + return 1; + else + return -1; +} diff --git a/src/core/job.h b/src/core/job.h new file mode 100644 index 00000000..03ad6406 --- /dev/null +++ b/src/core/job.h @@ -0,0 +1,243 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-event.h" + +#include "list.h" +#include "unit-name.h" + +typedef struct Job Job; +typedef struct JobDependency JobDependency; +typedef enum JobType JobType; +typedef enum JobState JobState; +typedef enum JobMode JobMode; +typedef enum JobResult JobResult; + +/* Be careful when changing the job types! Adjust job_merging_table[] accordingly! */ +enum JobType { + JOB_START, /* if a unit does not support being started, we'll just wait until it becomes active */ + JOB_VERIFY_ACTIVE, + + JOB_STOP, + + JOB_RELOAD, /* if running, reload */ + + /* Note that restarts are first treated like JOB_STOP, but + * then instead of finishing are patched to become + * JOB_START. */ + JOB_RESTART, /* If running, stop. Then start unconditionally. */ + + _JOB_TYPE_MAX_MERGING, + + /* JOB_NOP can enter into a transaction, but as it won't pull in + * any dependencies and it uses the special 'nop_job' slot in Unit, + * it won't have to merge with anything (except possibly into another + * JOB_NOP, previously installed). JOB_NOP is special-cased in + * job_type_is_*() functions so that the transaction can be + * activated. */ + JOB_NOP = _JOB_TYPE_MAX_MERGING, /* do nothing */ + + _JOB_TYPE_MAX_IN_TRANSACTION, + + /* JOB_TRY_RESTART can never appear in a transaction, because + * it always collapses into JOB_RESTART or JOB_NOP before entering. + * Thus we never need to merge it with anything. */ + JOB_TRY_RESTART = _JOB_TYPE_MAX_IN_TRANSACTION, /* if running, stop and then start */ + + /* Similar to JOB_TRY_RESTART but collapses to JOB_RELOAD or JOB_NOP */ + JOB_TRY_RELOAD, + + /* JOB_RELOAD_OR_START won't enter into a transaction and cannot result + * from transaction merging (there's no way for JOB_RELOAD and + * JOB_START to meet in one transaction). It can result from a merge + * during job installation, but then it will immediately collapse into + * one of the two simpler types. */ + JOB_RELOAD_OR_START, /* if running, reload, otherwise start */ + + _JOB_TYPE_MAX, + _JOB_TYPE_INVALID = -1 +}; + +enum JobState { + JOB_WAITING, + JOB_RUNNING, + _JOB_STATE_MAX, + _JOB_STATE_INVALID = -1 +}; + +enum JobMode { + JOB_FAIL, /* Fail if a conflicting job is already queued */ + JOB_REPLACE, /* Replace an existing conflicting job */ + JOB_REPLACE_IRREVERSIBLY,/* Like JOB_REPLACE + produce irreversible jobs */ + JOB_ISOLATE, /* Start a unit, and stop all others */ + JOB_FLUSH, /* Flush out all other queued jobs when queueing this one */ + JOB_IGNORE_DEPENDENCIES, /* Ignore both requirement and ordering dependencies */ + JOB_IGNORE_REQUIREMENTS, /* Ignore requirement dependencies */ + JOB_TRIGGERING, /* Adds TRIGGERED_BY dependencies to the same transaction */ + _JOB_MODE_MAX, + _JOB_MODE_INVALID = -1 +}; + +enum JobResult { + JOB_DONE, /* Job completed successfully (or skipped due to a failed ConditionXYZ=) */ + JOB_CANCELED, /* Job canceled by a conflicting job installation or by explicit cancel request */ + JOB_TIMEOUT, /* Job timeout elapsed */ + JOB_FAILED, /* Job failed */ + JOB_DEPENDENCY, /* A required dependency job did not result in JOB_DONE */ + JOB_SKIPPED, /* Negative result of JOB_VERIFY_ACTIVE or skip due to ExecCondition= */ + JOB_INVALID, /* JOB_RELOAD of inactive unit */ + JOB_ASSERT, /* Couldn't start a unit, because an assert didn't hold */ + JOB_UNSUPPORTED, /* Couldn't start a unit, because the unit type is not supported on the system */ + JOB_COLLECTED, /* Job was garbage collected, since nothing needed it anymore */ + JOB_ONCE, /* Unit was started before, and hence can't be started again */ + _JOB_RESULT_MAX, + _JOB_RESULT_INVALID = -1 +}; + +#include "unit.h" + +struct JobDependency { + /* Encodes that the 'subject' job needs the 'object' job in + * some way. This structure is used only while building a transaction. */ + Job *subject; + Job *object; + + LIST_FIELDS(JobDependency, subject); + LIST_FIELDS(JobDependency, object); + + bool matters:1; + bool conflicts:1; +}; + +struct Job { + Manager *manager; + Unit *unit; + + LIST_FIELDS(Job, transaction); + LIST_FIELDS(Job, dbus_queue); + LIST_FIELDS(Job, gc_queue); + + LIST_HEAD(JobDependency, subject_list); + LIST_HEAD(JobDependency, object_list); + + /* Used for graph algs as a "I have been here" marker */ + Job* marker; + unsigned generation; + + uint32_t id; + + JobType type; + JobState state; + + sd_event_source *timer_event_source; + usec_t begin_usec; + usec_t begin_running_usec; + + /* + * This tracks where to send signals, and also which clients + * are allowed to call DBus methods on the job (other than + * root). + * + * There can be more than one client, because of job merging. + */ + sd_bus_track *bus_track; + char **deserialized_clients; + + JobResult result; + + unsigned run_queue_idx; + + bool installed:1; + bool in_run_queue:1; + bool matters_to_anchor:1; + bool in_dbus_queue:1; + bool sent_dbus_new_signal:1; + bool ignore_order:1; + bool irreversible:1; + bool in_gc_queue:1; + bool ref_by_private_bus:1; +}; + +Job* job_new(Unit *unit, JobType type); +Job* job_new_raw(Unit *unit); +void job_unlink(Job *job); +Job* job_free(Job *job); +Job* job_install(Job *j); +int job_install_deserialized(Job *j); +void job_uninstall(Job *j); +void job_dump(Job *j, FILE *f, const char *prefix); +int job_serialize(Job *j, FILE *f); +int job_deserialize(Job *j, FILE *f); +int job_coldplug(Job *j); + +JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts); +void job_dependency_free(JobDependency *l); + +int job_merge(Job *j, Job *other); + +JobType job_type_lookup_merge(JobType a, JobType b) _pure_; + +_pure_ static inline bool job_type_is_mergeable(JobType a, JobType b) { + return job_type_lookup_merge(a, b) >= 0; +} + +_pure_ static inline bool job_type_is_conflicting(JobType a, JobType b) { + return a != JOB_NOP && b != JOB_NOP && !job_type_is_mergeable(a, b); +} + +_pure_ static inline bool job_type_is_superset(JobType a, JobType b) { + /* Checks whether operation a is a "superset" of b in its actions */ + if (b == JOB_NOP) + return true; + if (a == JOB_NOP) + return false; + return a == job_type_lookup_merge(a, b); +} + +bool job_type_is_redundant(JobType a, UnitActiveState b) _pure_; + +/* Collapses a state-dependent job type into a simpler type by observing + * the state of the unit which it is going to be applied to. */ +JobType job_type_collapse(JobType t, Unit *u); + +int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u); + +void job_add_to_run_queue(Job *j); +void job_add_to_dbus_queue(Job *j); + +int job_start_timer(Job *j, bool job_running); + +int job_run_and_invalidate(Job *j); +int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already); + +char *job_dbus_path(Job *j); + +void job_shutdown_magic(Job *j); + +int job_get_timeout(Job *j, usec_t *timeout) _pure_; + +bool job_may_gc(Job *j); +void job_add_to_gc_queue(Job *j); + +int job_get_before(Job *j, Job*** ret); +int job_get_after(Job *j, Job*** ret); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Job*, job_free); + +const char* job_type_to_string(JobType t) _const_; +JobType job_type_from_string(const char *s) _pure_; + +const char* job_state_to_string(JobState t) _const_; +JobState job_state_from_string(const char *s) _pure_; + +const char* job_mode_to_string(JobMode t) _const_; +JobMode job_mode_from_string(const char *s) _pure_; + +const char* job_result_to_string(JobResult t) _const_; +JobResult job_result_from_string(const char *s) _pure_; + +const char* job_type_to_access_method(JobType t); + +int job_compare(Job *a, Job *b, UnitDependency assume_dep); diff --git a/src/core/kill.c b/src/core/kill.c new file mode 100644 index 00000000..a9f468e2 --- /dev/null +++ b/src/core/kill.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "kill.h" +#include "signal-util.h" +#include "string-table.h" +#include "util.h" + +void kill_context_init(KillContext *c) { + assert(c); + + c->kill_signal = SIGTERM; + /* restart_kill_signal is unset by default and we fall back to kill_signal */ + c->final_kill_signal = SIGKILL; + c->send_sigkill = true; + c->send_sighup = false; + c->watchdog_signal = SIGABRT; +} + +void kill_context_dump(KillContext *c, FILE *f, const char *prefix) { + assert(c); + + prefix = strempty(prefix); + + fprintf(f, + "%sKillMode: %s\n" + "%sKillSignal: SIG%s\n" + "%sRestartKillSignal: SIG%s\n" + "%sFinalKillSignal: SIG%s\n" + "%sSendSIGKILL: %s\n" + "%sSendSIGHUP: %s\n", + prefix, kill_mode_to_string(c->kill_mode), + prefix, signal_to_string(c->kill_signal), + prefix, signal_to_string(restart_kill_signal(c)), + prefix, signal_to_string(c->final_kill_signal), + prefix, yes_no(c->send_sigkill), + prefix, yes_no(c->send_sighup)); +} + +static const char* const kill_mode_table[_KILL_MODE_MAX] = { + [KILL_CONTROL_GROUP] = "control-group", + [KILL_PROCESS] = "process", + [KILL_MIXED] = "mixed", + [KILL_NONE] = "none", +}; + +DEFINE_STRING_TABLE_LOOKUP(kill_mode, KillMode); + +static const char* const kill_who_table[_KILL_WHO_MAX] = { + [KILL_MAIN] = "main", + [KILL_CONTROL] = "control", + [KILL_ALL] = "all", + [KILL_MAIN_FAIL] = "main-fail", + [KILL_CONTROL_FAIL] = "control-fail", + [KILL_ALL_FAIL] = "all-fail", +}; + +DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho); diff --git a/src/core/kill.h b/src/core/kill.h new file mode 100644 index 00000000..1deb0aff --- /dev/null +++ b/src/core/kill.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct KillContext KillContext; + +#include +#include + +#include "macro.h" + +typedef enum KillMode { + /* The kill mode is a property of a unit. */ + KILL_CONTROL_GROUP = 0, + KILL_PROCESS, + KILL_MIXED, + KILL_NONE, + _KILL_MODE_MAX, + _KILL_MODE_INVALID = -1 +} KillMode; + +struct KillContext { + KillMode kill_mode; + int kill_signal; + int restart_kill_signal; + int final_kill_signal; + int watchdog_signal; + bool send_sigkill; + bool send_sighup; +}; + +typedef enum KillWho { + /* Kill who is a property of an operation */ + KILL_MAIN, + KILL_CONTROL, + KILL_ALL, + KILL_MAIN_FAIL, + KILL_CONTROL_FAIL, + KILL_ALL_FAIL, + _KILL_WHO_MAX, + _KILL_WHO_INVALID = -1 +} KillWho; + +void kill_context_init(KillContext *c); +void kill_context_dump(KillContext *c, FILE *f, const char *prefix); + +const char *kill_mode_to_string(KillMode k) _const_; +KillMode kill_mode_from_string(const char *s) _pure_; + +const char *kill_who_to_string(KillWho k) _const_; +KillWho kill_who_from_string(const char *s) _pure_; + +static inline int restart_kill_signal(const KillContext *c) { + if (c->restart_kill_signal != 0) + return c->restart_kill_signal; + return c->kill_signal; +} diff --git a/src/core/killall.c b/src/core/killall.c new file mode 100644 index 00000000..81dc1a7b --- /dev/null +++ b/src/core/killall.c @@ -0,0 +1,285 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2010 ProFUSION embedded systems +***/ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "def.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "killall.h" +#include "parse-util.h" +#include "process-util.h" +#include "set.h" +#include "string-util.h" +#include "terminal-util.h" +#include "util.h" + +static bool ignore_proc(pid_t pid, bool warn_rootfs) { + _cleanup_fclose_ FILE *f = NULL; + const char *p; + char c = 0; + uid_t uid; + int r; + + /* We are PID 1, let's not commit suicide */ + if (pid <= 1) + return true; + + /* Ignore kernel threads */ + r = is_kernel_thread(pid); + if (r != 0) + return true; /* also ignore processes where we can't determine this */ + + r = get_process_uid(pid, &uid); + if (r < 0) + return true; /* not really, but better safe than sorry */ + + /* Non-root processes otherwise are always subject to be killed */ + if (uid != 0) + return false; + + p = procfs_file_alloca(pid, "cmdline"); + f = fopen(p, "re"); + if (!f) + return true; /* not really, but has the desired effect */ + + /* Try to read the first character of the command line. If the cmdline is empty (which might be the case for + * kernel threads but potentially also other stuff), this line won't do anything, but we don't care much, as + * actual kernel threads are already filtered out above. */ + (void) fread(&c, 1, 1, f); + + /* Processes with argv[0][0] = '@' we ignore from the killing spree. + * + * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons */ + if (c != '@') + return false; + + if (warn_rootfs && + pid_from_same_root_fs(pid) == 0) { + + _cleanup_free_ char *comm = NULL; + + (void) get_process_comm(pid, &comm); + + log_notice("Process " PID_FMT " (%s) has been marked to be excluded from killing. It is " + "running from the root file system, and thus likely to block re-mounting of the " + "root file system to read-only. Please consider moving it into an initrd file " + "system instead.", pid, strna(comm)); + } + + return true; +} + +static void log_children_no_yet_killed(Set *pids) { + _cleanup_free_ char *lst_child = NULL; + Iterator i; + void *p; + + SET_FOREACH(p, pids, i) { + _cleanup_free_ char *s = NULL; + + if (get_process_comm(PTR_TO_PID(p), &s) < 0) + (void) asprintf(&s, PID_FMT, PTR_TO_PID(p)); + + if (!strextend(&lst_child, ", ", s, NULL)) { + log_oom(); + return; + } + } + + if (isempty(lst_child)) + return; + + log_warning("Waiting for process: %s", lst_child + 2); +} + +static int wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) { + usec_t until, date_log_child, n; + + assert(mask); + + /* Return the number of children remaining in the pids set: That correspond to the number + * of processes still "alive" after the timeout */ + + if (set_isempty(pids)) + return 0; + + n = now(CLOCK_MONOTONIC); + until = usec_add(n, timeout); + date_log_child = usec_add(n, 10u * USEC_PER_SEC); + if (date_log_child > until) + date_log_child = usec_add(n, timeout / 2u); + + for (;;) { + struct timespec ts; + int k; + void *p; + Iterator i; + + /* First, let the kernel inform us about killed + * children. Most processes will probably be our + * children, but some are not (might be our + * grandchildren instead...). */ + for (;;) { + pid_t pid; + + pid = waitpid(-1, NULL, WNOHANG); + if (pid == 0) + break; + if (pid < 0) { + if (errno == ECHILD) + break; + + return log_error_errno(errno, "waitpid() failed: %m"); + } + + (void) set_remove(pids, PID_TO_PTR(pid)); + } + + /* Now explicitly check who might be remaining, who + * might not be our child. */ + SET_FOREACH(p, pids, i) { + + /* kill(pid, 0) sends no signal, but it tells + * us whether the process still exists. */ + if (kill(PTR_TO_PID(p), 0) == 0) + continue; + + if (errno != ESRCH) + continue; + + set_remove(pids, p); + } + + if (set_isempty(pids)) + return 0; + + n = now(CLOCK_MONOTONIC); + if (date_log_child > 0 && n >= date_log_child) { + log_children_no_yet_killed(pids); + /* Log the children not yet killed only once */ + date_log_child = 0; + } + + if (n >= until) + return set_size(pids); + + if (date_log_child > 0) + timespec_store(&ts, MIN(until - n, date_log_child - n)); + else + timespec_store(&ts, until - n); + + k = sigtimedwait(mask, NULL, &ts); + if (k != SIGCHLD) { + + if (k < 0 && errno != EAGAIN) + return log_error_errno(errno, "sigtimedwait() failed: %m"); + + if (k >= 0) + log_warning("sigtimedwait() returned unexpected signal."); + } + } +} + +static int killall(int sig, Set *pids, bool send_sighup) { + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *d; + int n_killed = 0; + + /* Send the specified signal to all remaining processes, if not excluded by ignore_proc(). + * Returns the number of processes to which the specified signal was sent */ + + dir = opendir("/proc"); + if (!dir) + return log_warning_errno(errno, "opendir(/proc) failed: %m"); + + FOREACH_DIRENT_ALL(d, dir, break) { + pid_t pid; + int r; + + if (!IN_SET(d->d_type, DT_DIR, DT_UNKNOWN)) + continue; + + if (parse_pid(d->d_name, &pid) < 0) + continue; + + if (ignore_proc(pid, sig == SIGKILL && !in_initrd())) + continue; + + if (sig == SIGKILL) { + _cleanup_free_ char *s = NULL; + + get_process_comm(pid, &s); + log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pid, strna(s)); + } + + if (kill(pid, sig) >= 0) { + n_killed++; + if (pids) { + r = set_put(pids, PID_TO_PTR(pid)); + if (r < 0) + log_oom(); + } + } else if (errno != ENOENT) + log_warning_errno(errno, "Could not kill %d: %m", pid); + + if (send_sighup) { + /* Optionally, also send a SIGHUP signal, but + only if the process has a controlling + tty. This is useful to allow handling of + shells which ignore SIGTERM but react to + SIGHUP. We do not send this to processes that + have no controlling TTY since we don't want to + trigger reloads of daemon processes. Also we + make sure to only send this after SIGTERM so + that SIGTERM is always first in the queue. */ + + if (get_ctty_devnr(pid, NULL) >= 0) + /* it's OK if the process is gone, just ignore the result */ + (void) kill(pid, SIGHUP); + } + } + + return n_killed; +} + +int broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout) { + int n_children_left; + sigset_t mask, oldmask; + _cleanup_set_free_ Set *pids = NULL; + + /* Send the specified signal to all remaining processes, if not excluded by ignore_proc(). + * Return: + * - The number of processes still "alive" after the timeout (that should have been killed) + * if the function needs to wait for the end of the processes (wait_for_exit). + * - Otherwise, the number of processes to which the specified signal was sent */ + + if (wait_for_exit) + pids = set_new(NULL); + + assert_se(sigemptyset(&mask) == 0); + assert_se(sigaddset(&mask, SIGCHLD) == 0); + assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) == 0); + + if (kill(-1, SIGSTOP) < 0 && errno != ESRCH) + log_warning_errno(errno, "kill(-1, SIGSTOP) failed: %m"); + + n_children_left = killall(sig, pids, send_sighup); + + if (kill(-1, SIGCONT) < 0 && errno != ESRCH) + log_warning_errno(errno, "kill(-1, SIGCONT) failed: %m"); + + if (wait_for_exit && n_children_left > 0) + n_children_left = wait_for_children(pids, &mask, timeout); + + assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0); + + return n_children_left; +} diff --git a/src/core/killall.h b/src/core/killall.h new file mode 100644 index 00000000..08ae28d0 --- /dev/null +++ b/src/core/killall.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "time-util.h" + +int broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout); diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c new file mode 100644 index 00000000..12867432 --- /dev/null +++ b/src/core/kmod-setup.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "bus-util.h" +#include "capability-util.h" +#include "fileio.h" +#include "kmod-setup.h" +#include "macro.h" +#include "string-util.h" + +#if HAVE_KMOD +#include "module-util.h" + +static void systemd_kmod_log( + void *data, + int priority, + const char *file, int line, + const char *fn, + const char *format, + va_list args) { + + /* library logging is enabled at debug only */ + DISABLE_WARNING_FORMAT_NONLITERAL; + log_internalv(LOG_DEBUG, 0, file, line, fn, format, args); + REENABLE_WARNING; +} + +static int has_virtio_rng_nftw_cb( + const char *fpath, + const struct stat *sb, + int tflag, + struct FTW *ftwbuf) { + + _cleanup_free_ char *alias = NULL; + int r; + + if ((FTW_D == tflag) && (ftwbuf->level > 2)) + return FTW_SKIP_SUBTREE; + + if (FTW_F != tflag) + return FTW_CONTINUE; + + if (!endswith(fpath, "/modalias")) + return FTW_CONTINUE; + + r = read_one_line_file(fpath, &alias); + if (r < 0) + return FTW_SKIP_SIBLINGS; + + if (startswith(alias, "pci:v00001AF4d00001005")) + return FTW_STOP; + + if (startswith(alias, "pci:v00001AF4d00001044")) + return FTW_STOP; + + return FTW_SKIP_SIBLINGS; +} + +static bool has_virtio_rng(void) { + return (nftw("/sys/devices/pci0000:00", has_virtio_rng_nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL) == FTW_STOP); +} +#endif + +int kmod_setup(void) { +#if HAVE_KMOD + + static const struct { + const char *module; + const char *path; + bool warn_if_unavailable:1; + bool warn_if_module:1; + bool (*condition_fn)(void); + } kmod_table[] = { + /* This one we need to load explicitly, since auto-loading on use doesn't work + * before udev created the ghost device nodes, and we need it earlier than that. */ + { "autofs4", "/sys/class/misc/autofs", true, false, NULL }, + + /* This one we need to load explicitly, since auto-loading of IPv6 is not done when + * we try to configure ::1 on the loopback device. */ + { "ipv6", "/sys/module/ipv6", false, true, NULL }, + + /* This should never be a module */ + { "unix", "/proc/net/unix", true, true, NULL }, + +#if HAVE_LIBIPTC + /* netfilter is needed by networkd, nspawn among others, and cannot be autoloaded */ + { "ip_tables", "/proc/net/ip_tables_names", false, false, NULL }, +#endif + /* virtio_rng would be loaded by udev later, but real entropy might be needed very early */ + { "virtio_rng", NULL, false, false, has_virtio_rng }, + }; + _cleanup_(kmod_unrefp) struct kmod_ctx *ctx = NULL; + unsigned i; + + if (have_effective_cap(CAP_SYS_MODULE) == 0) + return 0; + + for (i = 0; i < ELEMENTSOF(kmod_table); i++) { + if (kmod_table[i].path && access(kmod_table[i].path, F_OK) >= 0) + continue; + + if (kmod_table[i].condition_fn && !kmod_table[i].condition_fn()) + continue; + + if (kmod_table[i].warn_if_module) + log_debug("Your kernel apparently lacks built-in %s support. Might be " + "a good idea to compile it in. We'll now try to work around " + "this by loading the module...", kmod_table[i].module); + + if (!ctx) { + ctx = kmod_new(NULL, NULL); + if (!ctx) + return log_oom(); + + kmod_set_log_fn(ctx, systemd_kmod_log, NULL); + kmod_load_resources(ctx); + } + + (void) module_load_and_warn(ctx, kmod_table[i].module, kmod_table[i].warn_if_unavailable); + } + +#endif + return 0; +} diff --git a/src/core/kmod-setup.h b/src/core/kmod-setup.h new file mode 100644 index 00000000..801c7bf6 --- /dev/null +++ b/src/core/kmod-setup.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int kmod_setup(void); diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c new file mode 100644 index 00000000..a50b200f --- /dev/null +++ b/src/core/load-dropin.c @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "conf-parser.h" +#include "fs-util.h" +#include "load-dropin.h" +#include "load-fragment.h" +#include "log.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "unit.h" + +static int unit_name_compatible(const char *a, const char *b) { + _cleanup_free_ char *template = NULL; + int r; + + /* The straightforward case: the symlink name matches the target */ + if (streq(a, b)) + return 1; + + r = unit_name_template(a, &template); + if (r == -EINVAL) + return 0; /* Not a template */ + if (r < 0) + return r; /* OOM, or some other failure. Just skip the warning. */ + + /* An instance name points to a target that is just the template name */ + return streq(template, b); +} + +static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suffix) { + _cleanup_strv_free_ char **paths = NULL; + char **p; + int r; + + r = unit_file_find_dropin_paths(NULL, + u->manager->lookup_paths.search_path, + u->manager->unit_path_cache, + dir_suffix, + NULL, + u->names, + &paths); + if (r < 0) + return r; + + STRV_FOREACH(p, paths) { + _cleanup_free_ char *target = NULL; + const char *entry; + + entry = basename(*p); + + if (null_or_empty_path(*p) > 0) { + /* an error usually means an invalid symlink, which is not a mask */ + log_unit_debug(u, "%s dependency on %s is masked by %s, ignoring.", + unit_dependency_to_string(dependency), entry, *p); + continue; + } + + r = is_symlink(*p); + if (r < 0) { + log_unit_warning_errno(u, r, "%s dropin %s unreadable, ignoring: %m", + unit_dependency_to_string(dependency), *p); + continue; + } + if (r == 0) { + log_unit_warning(u, "%s dependency dropin %s is not a symlink, ignoring.", + unit_dependency_to_string(dependency), *p); + continue; + } + + if (!unit_name_is_valid(entry, UNIT_NAME_ANY)) { + log_unit_warning(u, "%s dependency dropin %s is not a valid unit name, ignoring.", + unit_dependency_to_string(dependency), *p); + continue; + } + + r = readlink_malloc(*p, &target); + if (r < 0) { + log_unit_warning_errno(u, r, "readlink(\"%s\") failed, ignoring: %m", *p); + continue; + } + + /* We don't treat this as an error, especially because we didn't check this for a + * long time. Nevertheless, we warn, because such mismatch can be mighty confusing. */ + r = unit_name_compatible(entry, basename(target)); + if (r < 0) { + log_unit_warning_errno(u, r, "Can't check if names %s and %s are compatible, ignoring: %m", entry, basename(target)); + continue; + } + if (r == 0) + log_unit_warning(u, "%s dependency dropin %s target %s has different name", + unit_dependency_to_string(dependency), *p, target); + + r = unit_add_dependency_by_name(u, dependency, entry, true, UNIT_DEPENDENCY_FILE); + if (r < 0) + log_unit_warning_errno(u, r, "Cannot add %s dependency on %s, ignoring: %m", + unit_dependency_to_string(dependency), entry); + } + + return 0; +} + +int unit_load_dropin(Unit *u) { + _cleanup_strv_free_ char **l = NULL; + char **f; + int r; + + assert(u); + + /* Load dependencies from .wants and .requires directories */ + r = process_deps(u, UNIT_WANTS, ".wants"); + if (r < 0) + return r; + + r = process_deps(u, UNIT_REQUIRES, ".requires"); + if (r < 0) + return r; + + /* Load .conf dropins */ + r = unit_find_dropin_paths(u, &l); + if (r <= 0) + return 0; + + if (!u->dropin_paths) + u->dropin_paths = TAKE_PTR(l); + else { + r = strv_extend_strv(&u->dropin_paths, l, true); + if (r < 0) + return log_oom(); + } + + STRV_FOREACH(f, u->dropin_paths) + (void) config_parse(u->id, *f, NULL, + UNIT_VTABLE(u)->sections, + config_item_perf_lookup, load_fragment_gperf_lookup, + 0, u); + + u->dropin_mtime = now(CLOCK_REALTIME); + + return 0; +} diff --git a/src/core/load-dropin.h b/src/core/load-dropin.h new file mode 100644 index 00000000..ea15554d --- /dev/null +++ b/src/core/load-dropin.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "dropin.h" +#include "unit.h" + +/* Read service data supplementary drop-in directories */ + +static inline int unit_find_dropin_paths(Unit *u, char ***paths) { + assert(u); + + return unit_file_find_dropin_paths(NULL, + u->manager->lookup_paths.search_path, + u->manager->unit_path_cache, + ".d", ".conf", + u->names, + paths); +} + +int unit_load_dropin(Unit *u); diff --git a/src/core/load-fragment-gperf-nulstr.awk b/src/core/load-fragment-gperf-nulstr.awk new file mode 100644 index 00000000..44bc1fb6 --- /dev/null +++ b/src/core/load-fragment-gperf-nulstr.awk @@ -0,0 +1,14 @@ +BEGIN{ + keywords=0 ; FS="," ; + print "extern const char load_fragment_gperf_nulstr[];" ; + print "const char load_fragment_gperf_nulstr[] =" +} +keyword==1 { + print "\"" $1 "\\0\"" +} +/%%/ { + keyword=1 +} +END { + print ";" +} diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 new file mode 100644 index 00000000..de08f7d0 --- /dev/null +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -0,0 +1,480 @@ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif +#include +#include "all-units.h" +#include "conf-parser.h" +#include "load-fragment.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name load_fragment_gperf_hash +%define lookup-function-name load_fragment_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +m4_dnl Define the context options only once +m4_define(`EXEC_CONTEXT_CONFIG_ITEMS', +`$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context) +$1.RootDirectory, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_directory) +$1.RootImage, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_image) +$1.User, config_parse_user_group_compat, 0, offsetof($1, exec_context.user) +$1.Group, config_parse_user_group_compat, 0, offsetof($1, exec_context.group) +$1.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof($1, exec_context.supplementary_groups) +$1.Nice, config_parse_exec_nice, 0, offsetof($1, exec_context) +$1.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 0, offsetof($1, exec_context) +$1.IOSchedulingClass, config_parse_exec_io_class, 0, offsetof($1, exec_context) +$1.IOSchedulingPriority, config_parse_exec_io_priority, 0, offsetof($1, exec_context) +$1.CPUSchedulingPolicy, config_parse_exec_cpu_sched_policy, 0, offsetof($1, exec_context) +$1.CPUSchedulingPriority, config_parse_exec_cpu_sched_prio, 0, offsetof($1, exec_context) +$1.CPUSchedulingResetOnFork, config_parse_bool, 0, offsetof($1, exec_context.cpu_sched_reset_on_fork) +$1.CPUAffinity, config_parse_exec_cpu_affinity, 0, offsetof($1, exec_context) +$1.NUMAPolicy, config_parse_numa_policy, 0, offsetof($1, exec_context.numa_policy.type) +$1.NUMAMask, config_parse_numa_mask, 0, offsetof($1, exec_context.numa_policy) +$1.UMask, config_parse_mode, 0, offsetof($1, exec_context.umask) +$1.Environment, config_parse_environ, 0, offsetof($1, exec_context.environment) +$1.EnvironmentFile, config_parse_unit_env_file, 0, offsetof($1, exec_context.environment_files) +$1.PassEnvironment, config_parse_pass_environ, 0, offsetof($1, exec_context.pass_environment) +$1.UnsetEnvironment, config_parse_unset_environ, 0, offsetof($1, exec_context.unset_environment) +$1.DynamicUser, config_parse_bool, true, offsetof($1, exec_context.dynamic_user) +$1.RemoveIPC, config_parse_bool, 0, offsetof($1, exec_context.remove_ipc) +$1.StandardInput, config_parse_exec_input, 0, offsetof($1, exec_context) +$1.StandardOutput, config_parse_exec_output, 0, offsetof($1, exec_context) +$1.StandardError, config_parse_exec_output, 0, offsetof($1, exec_context) +$1.StandardInputText, config_parse_exec_input_text, 0, offsetof($1, exec_context) +$1.StandardInputData, config_parse_exec_input_data, 0, offsetof($1, exec_context) +$1.TTYPath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.tty_path) +$1.TTYReset, config_parse_bool, 0, offsetof($1, exec_context.tty_reset) +$1.TTYVHangup, config_parse_bool, 0, offsetof($1, exec_context.tty_vhangup) +$1.TTYVTDisallocate, config_parse_bool, 0, offsetof($1, exec_context.tty_vt_disallocate) +$1.SyslogIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.syslog_identifier) +$1.SyslogFacility, config_parse_log_facility, 0, offsetof($1, exec_context.syslog_priority) +$1.SyslogLevel, config_parse_log_level, 0, offsetof($1, exec_context.syslog_priority) +$1.SyslogLevelPrefix, config_parse_bool, 0, offsetof($1, exec_context.syslog_level_prefix) +$1.LogLevelMax, config_parse_log_level, 0, offsetof($1, exec_context.log_level_max) +$1.LogRateLimitIntervalSec, config_parse_sec, 0, offsetof($1, exec_context.log_ratelimit_interval_usec) +$1.LogRateLimitBurst, config_parse_unsigned, 0, offsetof($1, exec_context.log_ratelimit_burst) +$1.LogExtraFields, config_parse_log_extra_fields, 0, offsetof($1, exec_context) +$1.Capabilities, config_parse_warn_compat, DISABLED_LEGACY, offsetof($1, exec_context) +$1.SecureBits, config_parse_exec_secure_bits, 0, offsetof($1, exec_context.secure_bits) +$1.CapabilityBoundingSet, config_parse_capability_set, 0, offsetof($1, exec_context.capability_bounding_set) +$1.AmbientCapabilities, config_parse_capability_set, 0, offsetof($1, exec_context.capability_ambient_set) +$1.TimerSlackNSec, config_parse_nsec, 0, offsetof($1, exec_context.timer_slack_nsec) +$1.NoNewPrivileges, config_parse_bool, 0, offsetof($1, exec_context.no_new_privileges) +$1.KeyringMode, config_parse_exec_keyring_mode, 0, offsetof($1, exec_context.keyring_mode) +m4_ifdef(`HAVE_SECCOMP', +`$1.SystemCallFilter, config_parse_syscall_filter, 0, offsetof($1, exec_context) +$1.SystemCallArchitectures, config_parse_syscall_archs, 0, offsetof($1, exec_context.syscall_archs) +$1.SystemCallErrorNumber, config_parse_syscall_errno, 0, offsetof($1, exec_context) +$1.MemoryDenyWriteExecute, config_parse_bool, 0, offsetof($1, exec_context.memory_deny_write_execute) +$1.RestrictNamespaces, config_parse_restrict_namespaces, 0, offsetof($1, exec_context) +$1.RestrictRealtime, config_parse_bool, 0, offsetof($1, exec_context.restrict_realtime) +$1.RestrictSUIDSGID, config_parse_bool, 0, offsetof($1, exec_context.restrict_suid_sgid) +$1.RestrictAddressFamilies, config_parse_address_families, 0, offsetof($1, exec_context) +$1.LockPersonality, config_parse_bool, 0, offsetof($1, exec_context.lock_personality)', +`$1.SystemCallFilter, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +$1.SystemCallArchitectures, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +$1.SystemCallErrorNumber, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +$1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +$1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +$1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +$1.RestrictSUIDSGID, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +$1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +$1.LockPersonality, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') +$1.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof($1, exec_context.rlimit) +$1.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof($1, exec_context.rlimit) +$1.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof($1, exec_context.rlimit) +$1.LimitSTACK, config_parse_rlimit, RLIMIT_STACK, offsetof($1, exec_context.rlimit) +$1.LimitCORE, config_parse_rlimit, RLIMIT_CORE, offsetof($1, exec_context.rlimit) +$1.LimitRSS, config_parse_rlimit, RLIMIT_RSS, offsetof($1, exec_context.rlimit) +$1.LimitNOFILE, config_parse_rlimit, RLIMIT_NOFILE, offsetof($1, exec_context.rlimit) +$1.LimitAS, config_parse_rlimit, RLIMIT_AS, offsetof($1, exec_context.rlimit) +$1.LimitNPROC, config_parse_rlimit, RLIMIT_NPROC, offsetof($1, exec_context.rlimit) +$1.LimitMEMLOCK, config_parse_rlimit, RLIMIT_MEMLOCK, offsetof($1, exec_context.rlimit) +$1.LimitLOCKS, config_parse_rlimit, RLIMIT_LOCKS, offsetof($1, exec_context.rlimit) +$1.LimitSIGPENDING, config_parse_rlimit, RLIMIT_SIGPENDING, offsetof($1, exec_context.rlimit) +$1.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, offsetof($1, exec_context.rlimit) +$1.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof($1, exec_context.rlimit) +$1.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof($1, exec_context.rlimit) +$1.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof($1, exec_context.rlimit) +$1.ReadWriteDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_write_paths) +$1.ReadOnlyDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_paths) +$1.InaccessibleDirectories, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_paths) +$1.ReadWritePaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_write_paths) +$1.ReadOnlyPaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.read_only_paths) +$1.InaccessiblePaths, config_parse_namespace_path_strv, 0, offsetof($1, exec_context.inaccessible_paths) +$1.BindPaths, config_parse_bind_paths, 0, offsetof($1, exec_context) +$1.BindReadOnlyPaths, config_parse_bind_paths, 0, offsetof($1, exec_context) +$1.TemporaryFileSystem, config_parse_temporary_filesystems, 0, offsetof($1, exec_context) +$1.PrivateTmp, config_parse_bool, 0, offsetof($1, exec_context.private_tmp) +$1.PrivateDevices, config_parse_bool, 0, offsetof($1, exec_context.private_devices) +$1.ProtectKernelTunables, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_tunables) +$1.ProtectKernelModules, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_modules) +$1.ProtectKernelLogs, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_logs) +$1.ProtectControlGroups, config_parse_bool, 0, offsetof($1, exec_context.protect_control_groups) +$1.NetworkNamespacePath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.network_namespace_path) +$1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network) +$1.PrivateUsers, config_parse_bool, 0, offsetof($1, exec_context.private_users) +$1.PrivateMounts, config_parse_bool, 0, offsetof($1, exec_context.private_mounts) +$1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context.protect_system) +$1.ProtectHome, config_parse_protect_home, 0, offsetof($1, exec_context.protect_home) +$1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context.mount_flags) +$1.MountAPIVFS, config_parse_bool, 0, offsetof($1, exec_context.mount_apivfs) +$1.Personality, config_parse_personality, 0, offsetof($1, exec_context.personality) +$1.RuntimeDirectoryPreserve, config_parse_runtime_preserve_mode, 0, offsetof($1, exec_context.runtime_directory_preserve_mode) +$1.RuntimeDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_RUNTIME].mode) +$1.RuntimeDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_RUNTIME].paths) +$1.StateDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_STATE].mode) +$1.StateDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_STATE].paths) +$1.CacheDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CACHE].mode) +$1.CacheDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CACHE].paths) +$1.LogsDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_LOGS].mode) +$1.LogsDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_LOGS].paths) +$1.ConfigurationDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].mode) +$1.ConfigurationDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].paths) +$1.TimeoutCleanSec, config_parse_sec, 0, offsetof($1, exec_context.timeout_clean_usec) +$1.ProtectHostname, config_parse_bool, 0, offsetof($1, exec_context.protect_hostname) +m4_ifdef(`HAVE_PAM', +`$1.PAMName, config_parse_unit_string_printf, 0, offsetof($1, exec_context.pam_name)', +`$1.PAMName, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') +$1.IgnoreSIGPIPE, config_parse_bool, 0, offsetof($1, exec_context.ignore_sigpipe) +$1.UtmpIdentifier, config_parse_unit_string_printf, 0, offsetof($1, exec_context.utmp_id) +$1.UtmpMode, config_parse_exec_utmp_mode, 0, offsetof($1, exec_context.utmp_mode) +m4_ifdef(`HAVE_SELINUX', +`$1.SELinuxContext, config_parse_exec_selinux_context, 0, offsetof($1, exec_context)', +`$1.SELinuxContext, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') +m4_ifdef(`HAVE_APPARMOR', +`$1.AppArmorProfile, config_parse_exec_apparmor_profile, 0, offsetof($1, exec_context)', +`$1.AppArmorProfile, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') +m4_ifdef(`ENABLE_SMACK', +`$1.SmackProcessLabel, config_parse_exec_smack_process_label, 0, offsetof($1, exec_context)', +`$1.SmackProcessLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')' +)m4_dnl +m4_define(`KILL_CONTEXT_CONFIG_ITEMS', +`$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, kill_context.send_sigkill) +$1.SendSIGHUP, config_parse_bool, 0, offsetof($1, kill_context.send_sighup) +$1.KillMode, config_parse_kill_mode, 0, offsetof($1, kill_context.kill_mode) +$1.KillSignal, config_parse_signal, 0, offsetof($1, kill_context.kill_signal) +$1.RestartKillSignal, config_parse_signal, 0, offsetof($1, kill_context.restart_kill_signal) +$1.FinalKillSignal, config_parse_signal, 0, offsetof($1, kill_context.final_kill_signal) +$1.WatchdogSignal, config_parse_signal, 0, offsetof($1, kill_context.watchdog_signal)' +)m4_dnl +m4_define(`CGROUP_CONTEXT_CONFIG_ITEMS', +`$1.Slice, config_parse_unit_slice, 0, 0 +$1.AllowedCPUs, config_parse_allowed_cpus, 0, offsetof($1, cgroup_context) +$1.AllowedMemoryNodes, config_parse_allowed_mems, 0, offsetof($1, cgroup_context) +$1.CPUAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.cpu_accounting) +$1.CPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.cpu_weight) +$1.StartupCPUWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_cpu_weight) +$1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares) +$1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares) +$1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context) +$1.CPUQuotaPeriodSec, config_parse_sec_def_infinity, 0, offsetof($1, cgroup_context.cpu_quota_period_usec) +$1.MemoryAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.memory_accounting) +$1.MemoryMin, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +$1.DefaultMemoryMin, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +$1.DefaultMemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +$1.MemoryLow, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +$1.MemoryHigh, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +$1.MemoryMax, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +$1.MemorySwapMax, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +$1.MemoryLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context) +$1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context) +$1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy) +$1.IOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.io_accounting) +$1.IOWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.io_weight) +$1.StartupIOWeight, config_parse_cg_weight, 0, offsetof($1, cgroup_context.startup_io_weight) +$1.IODeviceWeight, config_parse_io_device_weight, 0, offsetof($1, cgroup_context) +$1.IOReadBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context) +$1.IOWriteBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context) +$1.IOReadIOPSMax, config_parse_io_limit, 0, offsetof($1, cgroup_context) +$1.IOWriteIOPSMax, config_parse_io_limit, 0, offsetof($1, cgroup_context) +$1.IODeviceLatencyTargetSec, config_parse_io_device_latency, 0, offsetof($1, cgroup_context) +$1.BlockIOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.blockio_accounting) +$1.BlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.blockio_weight) +$1.StartupBlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.startup_blockio_weight) +$1.BlockIODeviceWeight, config_parse_blockio_device_weight, 0, offsetof($1, cgroup_context) +$1.BlockIOReadBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context) +$1.BlockIOWriteBandwidth, config_parse_blockio_bandwidth, 0, offsetof($1, cgroup_context) +$1.TasksAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.tasks_accounting) +$1.TasksMax, config_parse_tasks_max, 0, offsetof($1, cgroup_context.tasks_max) +$1.Delegate, config_parse_delegate, 0, offsetof($1, cgroup_context) +$1.DisableControllers, config_parse_disable_controllers, 0, offsetof($1, cgroup_context) +$1.IPAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.ip_accounting) +$1.IPAddressAllow, config_parse_ip_address_access, 0, offsetof($1, cgroup_context.ip_address_allow) +$1.IPAddressDeny, config_parse_ip_address_access, 0, offsetof($1, cgroup_context.ip_address_deny) +$1.IPIngressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof($1, cgroup_context.ip_filters_ingress) +$1.IPEgressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof($1, cgroup_context.ip_filters_egress) +$1.NetClass, config_parse_warn_compat, DISABLED_LEGACY, 0' +)m4_dnl +Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description) +Unit.Documentation, config_parse_documentation, 0, offsetof(Unit, documentation) +Unit.SourcePath, config_parse_unit_path_printf, 0, offsetof(Unit, source_path) +Unit.Requires, config_parse_unit_deps, UNIT_REQUIRES, 0 +Unit.Requisite, config_parse_unit_deps, UNIT_REQUISITE, 0 +Unit.Wants, config_parse_unit_deps, UNIT_WANTS, 0 +Unit.BindsTo, config_parse_unit_deps, UNIT_BINDS_TO, 0 +Unit.BindTo, config_parse_unit_deps, UNIT_BINDS_TO, 0 +Unit.Conflicts, config_parse_unit_deps, UNIT_CONFLICTS, 0 +Unit.Before, config_parse_unit_deps, UNIT_BEFORE, 0 +Unit.After, config_parse_unit_deps, UNIT_AFTER, 0 +Unit.OnFailure, config_parse_unit_deps, UNIT_ON_FAILURE, 0 +Unit.PropagatesReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0 +Unit.PropagateReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0 +Unit.ReloadPropagatedFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0 +Unit.PropagateReloadFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0 +Unit.PartOf, config_parse_unit_deps, UNIT_PART_OF, 0 +Unit.JoinsNamespaceOf, config_parse_unit_deps, UNIT_JOINS_NAMESPACE_OF, 0 +Unit.RequiresOverridable, config_parse_obsolete_unit_deps, UNIT_REQUIRES, 0 +Unit.RequisiteOverridable, config_parse_obsolete_unit_deps, UNIT_REQUISITE, 0 +Unit.RequiresMountsFor, config_parse_unit_requires_mounts_for, 0, 0 +Unit.StopWhenUnneeded, config_parse_bool, 0, offsetof(Unit, stop_when_unneeded) +Unit.RefuseManualStart, config_parse_bool, 0, offsetof(Unit, refuse_manual_start) +Unit.RefuseManualStop, config_parse_bool, 0, offsetof(Unit, refuse_manual_stop) +Unit.AllowIsolate, config_parse_bool, 0, offsetof(Unit, allow_isolate) +Unit.DefaultDependencies, config_parse_bool, 0, offsetof(Unit, default_dependencies) +Unit.OnFailureJobMode, config_parse_job_mode, 0, offsetof(Unit, on_failure_job_mode) +m4_dnl The following is a legacy alias name for compatibility +Unit.OnFailureIsolate, config_parse_job_mode_isolate, 0, offsetof(Unit, on_failure_job_mode) +Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate) +Unit.IgnoreOnSnapshot, config_parse_warn_compat, DISABLED_LEGACY, 0 +Unit.JobTimeoutSec, config_parse_job_timeout_sec, 0, 0 +Unit.JobRunningTimeoutSec, config_parse_job_running_timeout_sec, 0, 0 +Unit.JobTimeoutAction, config_parse_emergency_action, 0, offsetof(Unit, job_timeout_action) +Unit.JobTimeoutRebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, job_timeout_reboot_arg) +Unit.StartLimitIntervalSec, config_parse_sec, 0, offsetof(Unit, start_ratelimit.interval) +m4_dnl The following is a legacy alias name for compatibility +Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_ratelimit.interval) +Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_ratelimit.burst) +Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action) +Unit.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action) +Unit.SuccessAction, config_parse_emergency_action, 0, offsetof(Unit, success_action) +Unit.FailureActionExitStatus, config_parse_exit_status, 0, offsetof(Unit, failure_action_exit_status) +Unit.SuccessActionExitStatus, config_parse_exit_status, 0, offsetof(Unit, success_action_exit_status) +Unit.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg) +m4_dnl Also add any conditions to condition_definitions[] in src/analyze/analyze-condition.c. +Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions) +Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions) +Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, conditions) +Unit.ConditionPathIsSymbolicLink,config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, conditions) +Unit.ConditionPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, conditions) +Unit.ConditionPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, conditions) +Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, conditions) +Unit.ConditionFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, conditions) +Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, conditions) +Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, conditions) +Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, conditions) +Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions) +Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, conditions) +Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, conditions) +Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions) +Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, conditions) +Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, conditions) +Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions) +Unit.ConditionACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, conditions) +Unit.ConditionUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, conditions) +Unit.ConditionGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, conditions) +Unit.ConditionControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, conditions) +Unit.ConditionNull, config_parse_unit_condition_null, 0, offsetof(Unit, conditions) +Unit.AssertPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, asserts) +Unit.AssertPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, asserts) +Unit.AssertPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, asserts) +Unit.AssertPathIsSymbolicLink, config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, asserts) +Unit.AssertPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, asserts) +Unit.AssertPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, asserts) +Unit.AssertDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, asserts) +Unit.AssertFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, asserts) +Unit.AssertFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, asserts) +Unit.AssertNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, asserts) +Unit.AssertFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, asserts) +Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts) +Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, asserts) +Unit.AssertArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, asserts) +Unit.AssertVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, asserts) +Unit.AssertSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, asserts) +Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, asserts) +Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts) +Unit.AssertACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, asserts) +Unit.AssertUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, asserts) +Unit.AssertGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, asserts) +Unit.AssertControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, asserts) +Unit.AssertNull, config_parse_unit_condition_null, 0, offsetof(Unit, asserts) +Unit.CollectMode, config_parse_collect_mode, 0, offsetof(Unit, collect_mode) +m4_dnl +Service.PIDFile, config_parse_pid_file, 0, offsetof(Service, pid_file) +Service.ExecCondition, config_parse_exec, SERVICE_EXEC_CONDITION, offsetof(Service, exec_command) +Service.ExecStartPre, config_parse_exec, SERVICE_EXEC_START_PRE, offsetof(Service, exec_command) +Service.ExecStart, config_parse_exec, SERVICE_EXEC_START, offsetof(Service, exec_command) +Service.ExecStartPost, config_parse_exec, SERVICE_EXEC_START_POST, offsetof(Service, exec_command) +Service.ExecReload, config_parse_exec, SERVICE_EXEC_RELOAD, offsetof(Service, exec_command) +Service.ExecStop, config_parse_exec, SERVICE_EXEC_STOP, offsetof(Service, exec_command) +Service.ExecStopPost, config_parse_exec, SERVICE_EXEC_STOP_POST, offsetof(Service, exec_command) +Service.RestartSec, config_parse_sec, 0, offsetof(Service, restart_usec) +Service.TimeoutSec, config_parse_service_timeout, 0, 0 +Service.TimeoutStartSec, config_parse_service_timeout, 0, 0 +Service.TimeoutStopSec, config_parse_sec_fix_0, 0, offsetof(Service, timeout_stop_usec) +Service.TimeoutAbortSec, config_parse_service_timeout_abort, 0, 0 +Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec) +Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec) +m4_dnl The following five only exist for compatibility, they moved into Unit, see above +Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_ratelimit.interval) +Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_ratelimit.burst) +Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action) +Service.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action) +Service.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg) +Service.Type, config_parse_service_type, 0, offsetof(Service, type) +Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart) +Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only) +Service.RootDirectoryStartOnly, config_parse_bool, 0, offsetof(Service, root_directory_start_only) +Service.RemainAfterExit, config_parse_bool, 0, offsetof(Service, remain_after_exit) +Service.GuessMainPID, config_parse_bool, 0, offsetof(Service, guess_main_pid) +Service.RestartPreventExitStatus, config_parse_set_status, 0, offsetof(Service, restart_prevent_status) +Service.RestartForceExitStatus, config_parse_set_status, 0, offsetof(Service, restart_force_status) +Service.SuccessExitStatus, config_parse_set_status, 0, offsetof(Service, success_status) +Service.SysVStartPriority, config_parse_warn_compat, DISABLED_LEGACY, 0 +Service.NonBlocking, config_parse_bool, 0, offsetof(Service, exec_context.non_blocking) +Service.BusName, config_parse_bus_name, 0, offsetof(Service, bus_name) +Service.FileDescriptorStoreMax, config_parse_unsigned, 0, offsetof(Service, n_fd_store_max) +Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access) +Service.Sockets, config_parse_service_sockets, 0, 0 +Service.BusPolicy, config_parse_warn_compat, DISABLED_LEGACY, 0 +Service.USBFunctionDescriptors, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_descriptors) +Service.USBFunctionStrings, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_strings) +Service.OOMPolicy, config_parse_oom_policy, 0, offsetof(Service, oom_policy) +EXEC_CONTEXT_CONFIG_ITEMS(Service)m4_dnl +CGROUP_CONTEXT_CONFIG_ITEMS(Service)m4_dnl +KILL_CONTEXT_CONFIG_ITEMS(Service)m4_dnl +m4_dnl +Socket.ListenStream, config_parse_socket_listen, SOCKET_SOCKET, 0 +Socket.ListenDatagram, config_parse_socket_listen, SOCKET_SOCKET, 0 +Socket.ListenSequentialPacket, config_parse_socket_listen, SOCKET_SOCKET, 0 +Socket.ListenFIFO, config_parse_socket_listen, SOCKET_FIFO, 0 +Socket.ListenNetlink, config_parse_socket_listen, SOCKET_SOCKET, 0 +Socket.ListenSpecial, config_parse_socket_listen, SOCKET_SPECIAL, 0 +Socket.ListenMessageQueue, config_parse_socket_listen, SOCKET_MQUEUE, 0 +Socket.ListenUSBFunction, config_parse_socket_listen, SOCKET_USB_FUNCTION, 0 +Socket.SocketProtocol, config_parse_socket_protocol, 0, offsetof(Socket, socket_protocol) +Socket.BindIPv6Only, config_parse_socket_bind, 0, offsetof(Socket, bind_ipv6_only) +Socket.Backlog, config_parse_unsigned, 0, offsetof(Socket, backlog) +Socket.BindToDevice, config_parse_socket_bindtodevice, 0, 0 +Socket.ExecStartPre, config_parse_exec, SOCKET_EXEC_START_PRE, offsetof(Socket, exec_command) +Socket.ExecStartPost, config_parse_exec, SOCKET_EXEC_START_POST, offsetof(Socket, exec_command) +Socket.ExecStopPre, config_parse_exec, SOCKET_EXEC_STOP_PRE, offsetof(Socket, exec_command) +Socket.ExecStopPost, config_parse_exec, SOCKET_EXEC_STOP_POST, offsetof(Socket, exec_command) +Socket.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Socket, timeout_usec) +Socket.SocketUser, config_parse_user_group_compat, 0, offsetof(Socket, user) +Socket.SocketGroup, config_parse_user_group_compat, 0, offsetof(Socket, group) +Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode) +Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode) +Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept) +Socket.Writable, config_parse_bool, 0, offsetof(Socket, writable) +Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections) +Socket.MaxConnectionsPerSource, config_parse_unsigned, 0, offsetof(Socket, max_connections_per_source) +Socket.KeepAlive, config_parse_bool, 0, offsetof(Socket, keep_alive) +Socket.KeepAliveTimeSec, config_parse_sec, 0, offsetof(Socket, keep_alive_time) +Socket.KeepAliveIntervalSec, config_parse_sec, 0, offsetof(Socket, keep_alive_interval) +Socket.KeepAliveProbes, config_parse_unsigned, 0, offsetof(Socket, keep_alive_cnt) +Socket.DeferAcceptSec, config_parse_sec, 0, offsetof(Socket, defer_accept) +Socket.NoDelay, config_parse_bool, 0, offsetof(Socket, no_delay) +Socket.Priority, config_parse_int, 0, offsetof(Socket, priority) +Socket.ReceiveBuffer, config_parse_iec_size, 0, offsetof(Socket, receive_buffer) +Socket.SendBuffer, config_parse_iec_size, 0, offsetof(Socket, send_buffer) +Socket.IPTOS, config_parse_ip_tos, 0, offsetof(Socket, ip_tos) +Socket.IPTTL, config_parse_int, 0, offsetof(Socket, ip_ttl) +Socket.Mark, config_parse_int, 0, offsetof(Socket, mark) +Socket.PipeSize, config_parse_iec_size, 0, offsetof(Socket, pipe_size) +Socket.FreeBind, config_parse_bool, 0, offsetof(Socket, free_bind) +Socket.Transparent, config_parse_bool, 0, offsetof(Socket, transparent) +Socket.Broadcast, config_parse_bool, 0, offsetof(Socket, broadcast) +Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred) +Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) +Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion) +Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port) +Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) +Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize) +Socket.RemoveOnStop, config_parse_bool, 0, offsetof(Socket, remove_on_stop) +Socket.Symlinks, config_parse_unit_path_strv_printf, 0, offsetof(Socket, symlinks) +Socket.FileDescriptorName, config_parse_fdname, 0, 0 +Socket.Service, config_parse_socket_service, 0, 0 +Socket.TriggerLimitIntervalSec, config_parse_sec, 0, offsetof(Socket, trigger_limit.interval) +Socket.TriggerLimitBurst, config_parse_unsigned, 0, offsetof(Socket, trigger_limit.burst) +m4_ifdef(`ENABLE_SMACK', +`Socket.SmackLabel, config_parse_unit_string_printf, 0, offsetof(Socket, smack) +Socket.SmackLabelIPIn, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_in) +Socket.SmackLabelIPOut, config_parse_unit_string_printf, 0, offsetof(Socket, smack_ip_out)', +`Socket.SmackLabel, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +Socket.SmackLabelIPIn, config_parse_warn_compat, DISABLED_CONFIGURATION, 0 +Socket.SmackLabelIPOut, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') +m4_ifdef(`HAVE_SELINUX', +`Socket.SELinuxContextFromNet, config_parse_bool, 0, offsetof(Socket, selinux_context_from_net)', +`Socket.SELinuxContextFromNet, config_parse_warn_compat, DISABLED_CONFIGURATION, 0') +EXEC_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl +CGROUP_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl +KILL_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl +m4_dnl +Mount.What, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.what) +Mount.Where, config_parse_unit_path_printf, 0, offsetof(Mount, where) +Mount.Options, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.options) +Mount.Type, config_parse_unit_string_printf, 0, offsetof(Mount, parameters_fragment.fstype) +Mount.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Mount, timeout_usec) +Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode) +Mount.SloppyOptions, config_parse_bool, 0, offsetof(Mount, sloppy_options) +Mount.LazyUnmount, config_parse_bool, 0, offsetof(Mount, lazy_unmount) +Mount.ForceUnmount, config_parse_bool, 0, offsetof(Mount, force_unmount) +EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl +CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl +KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl +m4_dnl +Automount.Where, config_parse_unit_path_printf, 0, offsetof(Automount, where) +Automount.DirectoryMode, config_parse_mode, 0, offsetof(Automount, directory_mode) +Automount.TimeoutIdleSec, config_parse_sec_fix_0, 0, offsetof(Automount, timeout_idle_usec) +m4_dnl +Swap.What, config_parse_unit_path_printf, 0, offsetof(Swap, parameters_fragment.what) +Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority) +Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options) +Swap.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Swap, timeout_usec) +EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl +CGROUP_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl +KILL_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl +m4_dnl +Timer.OnCalendar, config_parse_timer, TIMER_CALENDAR, 0 +Timer.OnActiveSec, config_parse_timer, TIMER_ACTIVE, 0 +Timer.OnBootSec, config_parse_timer, TIMER_BOOT, 0 +Timer.OnStartupSec, config_parse_timer, TIMER_STARTUP, 0 +Timer.OnUnitActiveSec, config_parse_timer, TIMER_UNIT_ACTIVE, 0 +Timer.OnUnitInactiveSec, config_parse_timer, TIMER_UNIT_INACTIVE, 0 +Timer.OnClockChange, config_parse_bool, 0, offsetof(Timer, on_clock_change) +Timer.OnTimezoneChange, config_parse_bool, 0, offsetof(Timer, on_timezone_change) +Timer.Persistent, config_parse_bool, 0, offsetof(Timer, persistent) +Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system) +Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse) +Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec) +Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_usec) +Timer.Unit, config_parse_trigger_unit, 0, 0 +m4_dnl +Path.PathExists, config_parse_path_spec, 0, 0 +Path.PathExistsGlob, config_parse_path_spec, 0, 0 +Path.PathChanged, config_parse_path_spec, 0, 0 +Path.PathModified, config_parse_path_spec, 0, 0 +Path.DirectoryNotEmpty, config_parse_path_spec, 0, 0 +Path.Unit, config_parse_trigger_unit, 0, 0 +Path.MakeDirectory, config_parse_bool, 0, offsetof(Path, make_directory) +Path.DirectoryMode, config_parse_mode, 0, offsetof(Path, directory_mode) +m4_dnl +CGROUP_CONTEXT_CONFIG_ITEMS(Slice)m4_dnl +m4_dnl +CGROUP_CONTEXT_CONFIG_ITEMS(Scope)m4_dnl +KILL_CONTEXT_CONFIG_ITEMS(Scope)m4_dnl +Scope.RuntimeMaxSec, config_parse_sec, 0, offsetof(Scope, runtime_max_usec) +Scope.TimeoutStopSec, config_parse_sec, 0, offsetof(Scope, timeout_stop_usec) +m4_dnl The [Install] section is ignored here. +Install.Alias, NULL, 0, 0 +Install.WantedBy, NULL, 0, 0 +Install.RequiredBy, NULL, 0, 0 +Install.Also, NULL, 0, 0 +Install.DefaultInstance, NULL, 0, 0 diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c new file mode 100644 index 00000000..95345668 --- /dev/null +++ b/src/core/load-fragment.c @@ -0,0 +1,5006 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2012 Holger Hans Peter Freyther +***/ + +#include +#include +#include +#include +#if HAVE_SECCOMP +#include +#endif +#include +#include + +#include "af-list.h" +#include "alloc-util.h" +#include "all-units.h" +#include "bpf-firewall.h" +#include "bus-error.h" +#include "bus-internal.h" +#include "bus-util.h" +#include "cap-list.h" +#include "capability-util.h" +#include "cgroup-setup.h" +#include "conf-parser.h" +#include "cpu-set-util.h" +#include "env-util.h" +#include "errno-list.h" +#include "escape.h" +#include "fd-util.h" +#include "fs-util.h" +#include "hexdecoct.h" +#include "io-util.h" +#include "ioprio.h" +#include "ip-protocol-list.h" +#include "journal-util.h" +#include "limits-util.h" +#include "load-fragment.h" +#include "log.h" +#include "mountpoint-util.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#if HAVE_SECCOMP +#include "seccomp-util.h" +#endif +#include "securebits-util.h" +#include "signal-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "unit-printf.h" +#include "user-util.h" +#include "time-util.h" +#include "web-util.h" + +static int parse_socket_protocol(const char *s) { + int r; + + r = parse_ip_protocol(s); + if (r < 0) + return r; + if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP)) + return -EPROTONOSUPPORT; + + return r; +} + +int parse_crash_chvt(const char *value, int *data) { + int b; + + if (safe_atoi(value, data) >= 0) + return 0; + + b = parse_boolean(value); + if (b < 0) + return b; + + if (b > 0) + *data = 0; /* switch to where kmsg goes */ + else + *data = -1; /* turn off switching */ + + return 0; +} + +int parse_confirm_spawn(const char *value, char **console) { + char *s; + int r; + + r = value ? parse_boolean(value) : 1; + if (r == 0) { + *console = NULL; + return 0; + } else if (r > 0) /* on with default tty */ + s = strdup("/dev/console"); + else if (is_path(value)) /* on with fully qualified path */ + s = strdup(value); + else /* on with only a tty file name, not a fully qualified path */ + s = path_join("/dev/", value); + if (!s) + return -ENOMEM; + + *console = s; + return 0; +} + +DEFINE_CONFIG_PARSE(config_parse_socket_protocol, parse_socket_protocol, "Failed to parse socket protocol"); +DEFINE_CONFIG_PARSE(config_parse_exec_secure_bits, secure_bits_from_string, "Failed to parse secure bits"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_collect_mode, collect_mode, CollectMode, "Failed to parse garbage collection mode"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome, "Failed to parse protect home value"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem, "Failed to parse protect system value"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_oom_policy, oom_policy, OOMPolicy, "Failed to parse OOM policy"); +DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1, "Failed to parse IP TOS value"); +DEFINE_CONFIG_PARSE_PTR(config_parse_blockio_weight, cg_blkio_weight_parse, uint64_t, "Invalid block IO weight"); +DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t, "Invalid weight"); +DEFINE_CONFIG_PARSE_PTR(config_parse_cpu_shares, cg_cpu_shares_parse, uint64_t, "Invalid CPU shares"); +DEFINE_CONFIG_PARSE_PTR(config_parse_exec_mount_flags, mount_propagation_flags_from_string, unsigned long, "Failed to parse mount flag"); +DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_numa_policy, mpol, int, -1, "Invalid NUMA policy type"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_status_unit_format, status_unit_format, StatusUnitFormat, "Failed to parse status unit format"); + +int config_parse_unit_deps( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + UnitDependency d = ltype; + Unit *u = userdata; + const char *p; + + assert(filename); + assert(lvalue); + assert(rvalue); + + p = rvalue; + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + int r; + + r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + break; + } + + r = unit_name_printf(u, word, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); + continue; + } + + r = unit_add_dependency_by_name(u, d, k, true, UNIT_DEPENDENCY_FILE); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); + } + + return 0; +} + +int config_parse_obsolete_unit_deps( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Unit dependency type %s= is obsolete, replacing by %s=, please update your unit file", lvalue, unit_dependency_to_string(ltype)); + + return config_parse_unit_deps(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata); +} + +int config_parse_unit_string_printf( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *k = NULL; + const Unit *u = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata); +} + +int config_parse_unit_strv_printf( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const Unit *u = userdata; + _cleanup_free_ char *k = NULL; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + return config_parse_strv(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata); +} + +int config_parse_unit_path_printf( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *k = NULL; + const Unit *u = userdata; + int r; + bool fatal = ltype; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + /* Let's not bother with anything that is too long */ + if (strlen(rvalue) >= PATH_MAX) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "%s value too long%s.", + lvalue, fatal ? "" : ", ignoring"); + return fatal ? -ENAMETOOLONG : 0; + } + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in '%s'%s: %m", + rvalue, fatal ? "" : ", ignoring"); + return fatal ? -ENOEXEC : 0; + } + + return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata); +} + +int config_parse_unit_path_strv_printf( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char ***x = data; + const Unit *u = userdata; + int r; + const char *p; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + if (isempty(rvalue)) { + *x = strv_free(*x); + return 0; + } + + for (p = rvalue;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + r = unit_full_printf(u, word, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in '%s', ignoring: %m", word); + return 0; + } + + r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + return 0; + + r = strv_consume(x, TAKE_PTR(k)); + if (r < 0) + return log_oom(); + } +} + +static int patch_var_run( + const char *unit, + const char *filename, + unsigned line, + const char *lvalue, + char **path) { + + const char *e; + char *z; + + e = path_startswith(*path, "/var/run/"); + if (!e) + return 0; + + z = path_join("/run/", e); + if (!z) + return log_oom(); + + log_syntax(unit, LOG_NOTICE, filename, line, 0, + "%s= references a path below legacy directory /var/run/, updating %s → %s; " + "please update the unit file accordingly.", lvalue, *path, z); + + free_and_replace(*path, z); + + return 1; +} + +int config_parse_socket_listen( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ SocketPort *p = NULL; + SocketPort *tail; + Socket *s; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + s = SOCKET(data); + + if (isempty(rvalue)) { + /* An empty assignment removes all ports */ + socket_free_ports(s); + return 0; + } + + p = new0(SocketPort, 1); + if (!p) + return log_oom(); + + if (ltype != SOCKET_SOCKET) { + _cleanup_free_ char *k = NULL; + + r = unit_full_printf(UNIT(s), rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + return 0; + + if (ltype == SOCKET_FIFO) { + r = patch_var_run(unit, filename, line, lvalue, &k); + if (r < 0) + return r; + } + + free_and_replace(p->path, k); + p->type = ltype; + + } else if (streq(lvalue, "ListenNetlink")) { + _cleanup_free_ char *k = NULL; + + r = unit_full_printf(UNIT(s), rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + r = socket_address_parse_netlink(&p->address, k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k); + return 0; + } + + p->type = SOCKET_SOCKET; + + } else { + _cleanup_free_ char *k = NULL; + + r = unit_full_printf(UNIT(s), rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + if (k[0] == '/') { /* Only for AF_UNIX file system sockets… */ + r = patch_var_run(unit, filename, line, lvalue, &k); + if (r < 0) + return r; + } + + r = socket_address_parse_and_warn(&p->address, k); + if (r < 0) { + if (r != -EAFNOSUPPORT) + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value in '%s', ignoring: %m", k); + return 0; + } + + if (streq(lvalue, "ListenStream")) + p->address.type = SOCK_STREAM; + else if (streq(lvalue, "ListenDatagram")) + p->address.type = SOCK_DGRAM; + else { + assert(streq(lvalue, "ListenSequentialPacket")); + p->address.type = SOCK_SEQPACKET; + } + + if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Address family not supported, ignoring: %s", rvalue); + return 0; + } + + p->type = SOCKET_SOCKET; + } + + p->fd = -1; + p->auxiliary_fds = NULL; + p->n_auxiliary_fds = 0; + p->socket = s; + + LIST_FIND_TAIL(port, s->ports, tail); + LIST_INSERT_AFTER(port, s->ports, tail, p); + + p = NULL; + + return 0; +} + +int config_parse_exec_nice( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + int priority, r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + c->nice_set = false; + return 0; + } + + r = parse_nice(rvalue, &priority); + if (r < 0) { + if (r == -ERANGE) + log_syntax(unit, LOG_ERR, filename, line, r, "Nice priority out of range, ignoring: %s", rvalue); + else + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority '%s', ignoring: %m", rvalue); + return 0; + } + + c->nice = priority; + c->nice_set = true; + + return 0; +} + +int config_parse_exec_oom_score_adjust( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + int oa, r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + c->oom_score_adjust_set = false; + return 0; + } + + r = parse_oom_score_adjust(rvalue, &oa); + if (r < 0) { + if (r == -ERANGE) + log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue); + else + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value '%s', ignoring: %m", rvalue); + return 0; + } + + c->oom_score_adjust = oa; + c->oom_score_adjust_set = true; + + return 0; +} + +int config_parse_exec( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecCommand **e = data; + const Unit *u = userdata; + const char *p; + bool semicolon; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(e); + + e += ltype; + + if (isempty(rvalue)) { + /* An empty assignment resets the list */ + *e = exec_command_free_list(*e); + return 0; + } + + p = rvalue; + do { + _cleanup_free_ char *path = NULL, *firstword = NULL; + ExecCommandFlags flags = 0; + bool ignore = false, separate_argv0 = false; + _cleanup_free_ ExecCommand *nce = NULL; + _cleanup_strv_free_ char **n = NULL; + size_t nlen = 0, nbufsize = 0; + const char *f; + + semicolon = false; + + r = extract_first_word_and_warn(&p, &firstword, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE, unit, filename, line, rvalue); + if (r <= 0) + return 0; + + f = firstword; + for (;;) { + /* We accept an absolute path as first argument. If it's prefixed with - and the path doesn't + * exist, we ignore it instead of erroring out; if it's prefixed with @, we allow overriding of + * argv[0]; if it's prefixed with :, we will not do environment variable substitution; + * if it's prefixed with +, it will be run with full privileges and no sandboxing; if + * it's prefixed with '!' we apply sandboxing, but do not change user/group credentials; if + * it's prefixed with '!!', then we apply user/group credentials if the kernel supports ambient + * capabilities -- if it doesn't we don't apply the credentials themselves, but do apply most + * other sandboxing, with some special exceptions for changing UID. + * + * The idea is that '!!' may be used to write services that can take benefit of systemd's + * UID/GID dropping if the kernel supports ambient creds, but provide an automatic fallback to + * privilege dropping within the daemon if the kernel does not offer that. */ + + if (*f == '-' && !(flags & EXEC_COMMAND_IGNORE_FAILURE)) { + flags |= EXEC_COMMAND_IGNORE_FAILURE; + ignore = true; + } else if (*f == '@' && !separate_argv0) + separate_argv0 = true; + else if (*f == ':' && !(flags & EXEC_COMMAND_NO_ENV_EXPAND)) + flags |= EXEC_COMMAND_NO_ENV_EXPAND; + else if (*f == '+' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC))) + flags |= EXEC_COMMAND_FULLY_PRIVILEGED; + else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC))) + flags |= EXEC_COMMAND_NO_SETUID; + else if (*f == '!' && !(flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_AMBIENT_MAGIC))) { + flags &= ~EXEC_COMMAND_NO_SETUID; + flags |= EXEC_COMMAND_AMBIENT_MAGIC; + } else + break; + f++; + } + + r = unit_full_printf(u, f, &path); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in '%s'%s: %m", + f, ignore ? ", ignoring" : ""); + return ignore ? 0 : -ENOEXEC; + } + + if (isempty(path)) { + /* First word is either "-" or "@" with no command. */ + log_syntax(unit, LOG_ERR, filename, line, 0, + "Empty path in command line%s: '%s'", + ignore ? ", ignoring" : "", rvalue); + return ignore ? 0 : -ENOEXEC; + } + if (!string_is_safe(path)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Executable name contains special characters%s: %s", + ignore ? ", ignoring" : "", path); + return ignore ? 0 : -ENOEXEC; + } + if (endswith(path, "/")) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Executable path specifies a directory%s: %s", + ignore ? ", ignoring" : "", path); + return ignore ? 0 : -ENOEXEC; + } + + if (!path_is_absolute(path)) { + const char *prefix; + bool found = false; + + if (!filename_is_valid(path)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Neither a valid executable name nor an absolute path%s: %s", + ignore ? ", ignoring" : "", path); + return ignore ? 0 : -ENOEXEC; + } + + /* Resolve a single-component name to a full path */ + NULSTR_FOREACH(prefix, DEFAULT_PATH_NULSTR) { + _cleanup_free_ char *fullpath = NULL; + + fullpath = path_join(prefix, path); + if (!fullpath) + return log_oom(); + + if (access(fullpath, F_OK) >= 0) { + free_and_replace(path, fullpath); + found = true; + break; + } + } + + if (!found) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Executable \"%s\" not found in path \"%s\"%s", + path, DEFAULT_PATH, ignore ? ", ignoring" : ""); + return ignore ? 0 : -ENOEXEC; + } + } + + if (!separate_argv0) { + char *w = NULL; + + if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) + return log_oom(); + + w = strdup(path); + if (!w) + return log_oom(); + n[nlen++] = w; + n[nlen] = NULL; + } + + path_simplify(path, false); + + while (!isempty(p)) { + _cleanup_free_ char *word = NULL, *resolved = NULL; + + /* Check explicitly for an unquoted semicolon as + * command separator token. */ + if (p[0] == ';' && (!p[1] || strchr(WHITESPACE, p[1]))) { + p++; + p += strspn(p, WHITESPACE); + semicolon = true; + break; + } + + /* Check for \; explicitly, to not confuse it with \\; or "\;" or "\\;" etc. + * extract_first_word() would return the same for all of those. */ + if (p[0] == '\\' && p[1] == ';' && (!p[2] || strchr(WHITESPACE, p[2]))) { + char *w; + + p += 2; + p += strspn(p, WHITESPACE); + + if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) + return log_oom(); + + w = strdup(";"); + if (!w) + return log_oom(); + n[nlen++] = w; + n[nlen] = NULL; + continue; + } + + r = extract_first_word_and_warn(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE, unit, filename, line, rvalue); + if (r == 0) + break; + if (r < 0) + return ignore ? 0 : -ENOEXEC; + + r = unit_full_printf(u, word, &resolved); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in %s%s: %m", + word, ignore ? ", ignoring" : ""); + return ignore ? 0 : -ENOEXEC; + } + + if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) + return log_oom(); + + n[nlen++] = TAKE_PTR(resolved); + n[nlen] = NULL; + } + + if (!n || !n[0]) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Empty executable name or zeroeth argument%s: %s", + ignore ? ", ignoring" : "", rvalue); + return ignore ? 0 : -ENOEXEC; + } + + nce = new0(ExecCommand, 1); + if (!nce) + return log_oom(); + + nce->argv = TAKE_PTR(n); + nce->path = TAKE_PTR(path); + nce->flags = flags; + + exec_command_append_list(e, nce); + + /* Do not _cleanup_free_ these. */ + nce = NULL; + + rvalue = p; + } while (semicolon); + + return 0; +} + +int config_parse_socket_bindtodevice( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Socket *s = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue) || streq(rvalue, "*")) { + s->bind_to_device = mfree(s->bind_to_device); + return 0; + } + + if (!ifname_valid(rvalue)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid interface name, ignoring: %s", rvalue); + return 0; + } + + if (free_and_strdup(&s->bind_to_device, rvalue) < 0) + return log_oom(); + + return 0; +} + +int config_parse_exec_input( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + const Unit *u = userdata; + const char *n; + ExecInput ei; + int r; + + assert(data); + assert(filename); + assert(line); + assert(rvalue); + + n = startswith(rvalue, "fd:"); + if (n) { + _cleanup_free_ char *resolved = NULL; + + r = unit_full_printf(u, n, &resolved); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", n); + + if (isempty(resolved)) + resolved = mfree(resolved); + else if (!fdname_is_valid(resolved)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name: %s", resolved); + return -ENOEXEC; + } + + free_and_replace(c->stdio_fdname[STDIN_FILENO], resolved); + + ei = EXEC_INPUT_NAMED_FD; + + } else if ((n = startswith(rvalue, "file:"))) { + _cleanup_free_ char *resolved = NULL; + + r = unit_full_printf(u, n, &resolved); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", n); + + r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue); + if (r < 0) + return -ENOEXEC; + + free_and_replace(c->stdio_file[STDIN_FILENO], resolved); + + ei = EXEC_INPUT_FILE; + + } else { + ei = exec_input_from_string(rvalue); + if (ei < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse input specifier, ignoring: %s", rvalue); + return 0; + } + } + + c->std_input = ei; + return 0; +} + +int config_parse_exec_input_text( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *unescaped = NULL, *resolved = NULL; + ExecContext *c = data; + const Unit *u = userdata; + size_t sz; + void *p; + int r; + + assert(data); + assert(filename); + assert(line); + assert(rvalue); + + if (isempty(rvalue)) { + /* Reset if the empty string is assigned */ + c->stdin_data = mfree(c->stdin_data); + c->stdin_data_size = 0; + return 0; + } + + r = cunescape(rvalue, 0, &unescaped); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode C escaped text '%s': %m", rvalue); + + r = unit_full_printf(u, unescaped, &resolved); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s': %m", unescaped); + + sz = strlen(resolved); + if (c->stdin_data_size + sz + 1 < c->stdin_data_size || /* check for overflow */ + c->stdin_data_size + sz + 1 > EXEC_STDIN_DATA_MAX) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Standard input data too large (%zu), maximum of %zu permitted, ignoring.", c->stdin_data_size + sz, (size_t) EXEC_STDIN_DATA_MAX); + return -E2BIG; + } + + p = realloc(c->stdin_data, c->stdin_data_size + sz + 1); + if (!p) + return log_oom(); + + *((char*) mempcpy((char*) p + c->stdin_data_size, resolved, sz)) = '\n'; + + c->stdin_data = p; + c->stdin_data_size += sz + 1; + + return 0; +} + +int config_parse_exec_input_data( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ void *p = NULL; + ExecContext *c = data; + size_t sz; + void *q; + int r; + + assert(data); + assert(filename); + assert(line); + assert(rvalue); + + if (isempty(rvalue)) { + /* Reset if the empty string is assigned */ + c->stdin_data = mfree(c->stdin_data); + c->stdin_data_size = 0; + return 0; + } + + r = unbase64mem(rvalue, (size_t) -1, &p, &sz); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode base64 data, ignoring: %s", rvalue); + + assert(sz > 0); + + if (c->stdin_data_size + sz < c->stdin_data_size || /* check for overflow */ + c->stdin_data_size + sz > EXEC_STDIN_DATA_MAX) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Standard input data too large (%zu), maximum of %zu permitted, ignoring.", c->stdin_data_size + sz, (size_t) EXEC_STDIN_DATA_MAX); + return -E2BIG; + } + + q = realloc(c->stdin_data, c->stdin_data_size + sz); + if (!q) + return log_oom(); + + memcpy((uint8_t*) q + c->stdin_data_size, p, sz); + + c->stdin_data = q; + c->stdin_data_size += sz; + + return 0; +} + +int config_parse_exec_output( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *resolved = NULL; + const char *n; + ExecContext *c = data; + const Unit *u = userdata; + ExecOutput eo; + int r; + + assert(data); + assert(filename); + assert(line); + assert(lvalue); + assert(rvalue); + + n = startswith(rvalue, "fd:"); + if (n) { + r = unit_full_printf(u, n, &resolved); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n); + + if (isempty(resolved)) + resolved = mfree(resolved); + else if (!fdname_is_valid(resolved)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name: %s", resolved); + return -ENOEXEC; + } + + eo = EXEC_OUTPUT_NAMED_FD; + + } else if ((n = startswith(rvalue, "file:"))) { + + r = unit_full_printf(u, n, &resolved); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n); + + r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue); + if (r < 0) + return -ENOEXEC; + + eo = EXEC_OUTPUT_FILE; + + } else if ((n = startswith(rvalue, "append:"))) { + + r = unit_full_printf(u, n, &resolved); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n); + + r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE | PATH_CHECK_FATAL, unit, filename, line, lvalue); + if (r < 0) + return -ENOEXEC; + + eo = EXEC_OUTPUT_FILE_APPEND; + } else { + eo = exec_output_from_string(rvalue); + if (eo < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output specifier, ignoring: %s", rvalue); + return 0; + } + } + + if (streq(lvalue, "StandardOutput")) { + if (eo == EXEC_OUTPUT_NAMED_FD) + free_and_replace(c->stdio_fdname[STDOUT_FILENO], resolved); + else + free_and_replace(c->stdio_file[STDOUT_FILENO], resolved); + + c->std_output = eo; + + } else { + assert(streq(lvalue, "StandardError")); + + if (eo == EXEC_OUTPUT_NAMED_FD) + free_and_replace(c->stdio_fdname[STDERR_FILENO], resolved); + else + free_and_replace(c->stdio_file[STDERR_FILENO], resolved); + + c->std_error = eo; + } + + return 0; +} + +int config_parse_exec_io_class(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + int x; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + c->ioprio_set = false; + c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0); + return 0; + } + + x = ioprio_class_from_string(rvalue); + if (x < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IO scheduling class, ignoring: %s", rvalue); + return 0; + } + + c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio)); + c->ioprio_set = true; + + return 0; +} + +int config_parse_exec_io_priority(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + int i, r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + c->ioprio_set = false; + c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0); + return 0; + } + + r = ioprio_parse_priority(rvalue, &i); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IO priority, ignoring: %s", rvalue); + return 0; + } + + c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i); + c->ioprio_set = true; + + return 0; +} + +int config_parse_exec_cpu_sched_policy(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + int x; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + c->cpu_sched_set = false; + c->cpu_sched_policy = SCHED_OTHER; + c->cpu_sched_priority = 0; + return 0; + } + + x = sched_policy_from_string(rvalue); + if (x < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse CPU scheduling policy, ignoring: %s", rvalue); + return 0; + } + + c->cpu_sched_policy = x; + /* Moving to or from real-time policy? We need to adjust the priority */ + c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x)); + c->cpu_sched_set = true; + + return 0; +} + +int config_parse_numa_mask(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + int r; + NUMAPolicy *p = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_cpu_set_extend(rvalue, &p->nodes, true, unit, filename, line, lvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse NUMA node mask, ignoring: %s", rvalue); + return 0; + } + + return r; +} + +int config_parse_exec_cpu_sched_prio(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + int i, min, max, r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atoi(rvalue, &i); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU scheduling priority, ignoring: %s", rvalue); + return 0; + } + + /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */ + min = sched_get_priority_min(c->cpu_sched_policy); + max = sched_get_priority_max(c->cpu_sched_policy); + + if (i < min || i > max) { + log_syntax(unit, LOG_ERR, filename, line, 0, "CPU scheduling priority is out of range, ignoring: %s", rvalue); + return 0; + } + + c->cpu_sched_priority = i; + c->cpu_sched_set = true; + + return 0; +} + +int config_parse_exec_cpu_affinity(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + return parse_cpu_set_extend(rvalue, &c->cpu_set, true, unit, filename, line, lvalue); +} + +int config_parse_capability_set( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint64_t *capability_set = data; + uint64_t sum = 0, initial = 0; + bool invert = false; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (rvalue[0] == '~') { + invert = true; + rvalue++; + } + + if (streq(lvalue, "CapabilityBoundingSet")) + initial = CAP_ALL; /* initialized to all bits on */ + /* else "AmbientCapabilities" initialized to all bits off */ + + r = capability_set_from_string(rvalue, &sum); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= specifier '%s', ignoring: %m", lvalue, rvalue); + return 0; + } + + if (sum == 0 || *capability_set == initial) + /* "", "~" or uninitialized data -> replace */ + *capability_set = invert ? ~sum : sum; + else { + /* previous data -> merge */ + if (invert) + *capability_set &= ~sum; + else + *capability_set |= sum; + } + + return 0; +} + +int config_parse_exec_selinux_context( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + const Unit *u = userdata; + bool ignore; + char *k; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + c->selinux_context = mfree(c->selinux_context); + c->selinux_context_ignore = false; + return 0; + } + + if (rvalue[0] == '-') { + ignore = true; + rvalue++; + } else + ignore = false; + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in '%s'%s: %m", + rvalue, ignore ? ", ignoring" : ""); + return ignore ? 0 : -ENOEXEC; + } + + free_and_replace(c->selinux_context, k); + c->selinux_context_ignore = ignore; + + return 0; +} + +int config_parse_exec_apparmor_profile( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + const Unit *u = userdata; + bool ignore; + char *k; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + c->apparmor_profile = mfree(c->apparmor_profile); + c->apparmor_profile_ignore = false; + return 0; + } + + if (rvalue[0] == '-') { + ignore = true; + rvalue++; + } else + ignore = false; + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in '%s'%s: %m", + rvalue, ignore ? ", ignoring" : ""); + return ignore ? 0 : -ENOEXEC; + } + + free_and_replace(c->apparmor_profile, k); + c->apparmor_profile_ignore = ignore; + + return 0; +} + +int config_parse_exec_smack_process_label( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + const Unit *u = userdata; + bool ignore; + char *k; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + c->smack_process_label = mfree(c->smack_process_label); + c->smack_process_label_ignore = false; + return 0; + } + + if (rvalue[0] == '-') { + ignore = true; + rvalue++; + } else + ignore = false; + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in '%s'%s: %m", + rvalue, ignore ? ", ignoring" : ""); + return ignore ? 0 : -ENOEXEC; + } + + free_and_replace(c->smack_process_label, k); + c->smack_process_label_ignore = ignore; + + return 0; +} + +int config_parse_timer( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL; + _cleanup_free_ char *k = NULL; + const Unit *u = userdata; + Timer *t = data; + usec_t usec = 0; + TimerValue *v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets list */ + timer_free_values(t); + return 0; + } + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + if (ltype == TIMER_CALENDAR) { + r = calendar_spec_from_string(k, &c); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse calendar specification, ignoring: %s", k); + return 0; + } + } else { + r = parse_sec(k, &usec); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse timer value, ignoring: %s", k); + return 0; + } + } + + v = new(TimerValue, 1); + if (!v) + return log_oom(); + + *v = (TimerValue) { + .base = ltype, + .value = usec, + .calendar_spec = TAKE_PTR(c), + }; + + LIST_PREPEND(value, t->values, v); + + return 0; +} + +int config_parse_trigger_unit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *p = NULL; + Unit *u = data; + UnitType type; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (!hashmap_isempty(u->dependencies[UNIT_TRIGGERS])) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Multiple units to trigger specified, ignoring: %s", rvalue); + return 0; + } + + r = unit_name_printf(u, rvalue, &p); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); + return 0; + } + + type = unit_name_to_type(p); + if (type < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Unit type not valid, ignoring: %s", rvalue); + return 0; + } + if (unit_has_name(u, p)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Units cannot trigger themselves, ignoring: %s", rvalue); + return 0; + } + + r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p, true, UNIT_DEPENDENCY_FILE); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add trigger on %s, ignoring: %m", p); + return 0; + } + + return 0; +} + +int config_parse_path_spec(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Path *p = data; + PathSpec *s; + PathType b; + _cleanup_free_ char *k = NULL; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment clears list */ + path_free_specs(p); + return 0; + } + + b = path_type_from_string(lvalue); + if (b < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse path type, ignoring: %s", lvalue); + return 0; + } + + r = unit_full_printf(UNIT(p), rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); + return 0; + } + + r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + return 0; + + s = new0(PathSpec, 1); + if (!s) + return log_oom(); + + s->unit = UNIT(p); + s->path = TAKE_PTR(k); + s->type = b; + s->inotify_fd = -1; + + LIST_PREPEND(spec, p->specs, s); + + return 0; +} + +int config_parse_socket_service( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *p = NULL; + Socket *s = data; + Unit *x; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = unit_name_printf(UNIT(s), rvalue, &p); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue); + return -ENOEXEC; + } + + if (!endswith(p, ".service")) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service: %s", rvalue); + return -ENOEXEC; + } + + r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s: %s", rvalue, bus_error_message(&error, r)); + return -ENOEXEC; + } + + unit_ref_set(&s->service, UNIT(s), x); + + return 0; +} + +int config_parse_fdname( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *p = NULL; + Socket *s = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + s->fdname = mfree(s->fdname); + return 0; + } + + r = unit_full_printf(UNIT(s), rvalue, &p); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + if (!fdname_is_valid(p)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid file descriptor name, ignoring: %s", p); + return 0; + } + + return free_and_replace(s->fdname, p); +} + +int config_parse_service_sockets( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Service *s = data; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + p = rvalue; + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Trailing garbage in sockets, ignoring: %s", rvalue); + break; + } + + r = unit_name_printf(UNIT(s), word, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); + continue; + } + + if (!endswith(k, ".socket")) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type socket, ignoring: %s", k); + continue; + } + + r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, true, UNIT_DEPENDENCY_FILE); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); + + r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, true, UNIT_DEPENDENCY_FILE); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k); + } + + return 0; +} + +int config_parse_bus_name( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *k = NULL; + const Unit *u = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); + return 0; + } + + if (!service_name_is_valid(k)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name, ignoring: %s", k); + return 0; + } + + return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata); +} + +int config_parse_service_timeout( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Service *s = userdata; + usec_t usec; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(s); + + /* This is called for two cases: TimeoutSec= and TimeoutStartSec=. */ + + /* Traditionally, these options accepted 0 to disable the timeouts. However, a timeout of 0 suggests it happens + * immediately, hence fix this to become USEC_INFINITY instead. This is in-line with how we internally handle + * all other timeouts. */ + r = parse_sec_fix_0(rvalue, &usec); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue); + return 0; + } + + s->start_timeout_defined = true; + s->timeout_start_usec = usec; + + if (streq(lvalue, "TimeoutSec")) + s->timeout_stop_usec = usec; + + return 0; +} + +int config_parse_timeout_abort( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + usec_t *ret = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(ret); + + /* Note: apart from setting the arg, this returns an extra bit of information in the return value. */ + + if (isempty(rvalue)) { + *ret = 0; + return 0; /* "not set" */ + } + + r = parse_sec(rvalue, ret); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= setting, ignoring: %s", lvalue, rvalue); + + return 1; /* "set" */ +} + +int config_parse_service_timeout_abort( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Service *s = userdata; + int r; + + assert(s); + + r = config_parse_timeout_abort(unit, filename, line, section, section_line, lvalue, ltype, rvalue, + &s->timeout_abort_usec, s); + if (r >= 0) + s->timeout_abort_set = r; + return 0; +} + +int config_parse_sec_fix_0( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + usec_t *usec = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(usec); + + /* This is pretty much like config_parse_sec(), except that this treats a time of 0 as infinity, for + * compatibility with older versions of systemd where 0 instead of infinity was used as indicator to turn off a + * timeout. */ + + r = parse_sec_fix_0(rvalue, usec); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue); + return 0; + } + + return 0; +} + +int config_parse_user_group_compat( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *k = NULL; + char **user = data; + const Unit *u = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + if (isempty(rvalue)) { + *user = mfree(*user); + return 0; + } + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue); + return -ENOEXEC; + } + + if (!valid_user_group_name_or_id_compat(k)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k); + return -ENOEXEC; + } + + return free_and_replace(*user, k); +} + +int config_parse_user_group_strv_compat( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char ***users = data; + const Unit *u = userdata; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + if (isempty(rvalue)) { + *users = strv_free(*users); + return 0; + } + + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax: %s", rvalue); + return -ENOEXEC; + } + + r = unit_full_printf(u, word, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", word); + return -ENOEXEC; + } + + if (!valid_user_group_name_or_id_compat(k)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k); + return -ENOEXEC; + } + + r = strv_push(users, k); + if (r < 0) + return log_oom(); + + k = NULL; + } + + return 0; +} + +int config_parse_working_directory( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + const Unit *u = userdata; + bool missing_ok; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(c); + assert(u); + + if (isempty(rvalue)) { + c->working_directory_home = false; + c->working_directory = mfree(c->working_directory); + return 0; + } + + if (rvalue[0] == '-') { + missing_ok = true; + rvalue++; + } else + missing_ok = false; + + if (streq(rvalue, "~")) { + c->working_directory_home = true; + c->working_directory = mfree(c->working_directory); + } else { + _cleanup_free_ char *k = NULL; + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in working directory path '%s'%s: %m", + rvalue, missing_ok ? ", ignoring" : ""); + return missing_ok ? 0 : -ENOEXEC; + } + + r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE | (missing_ok ? 0 : PATH_CHECK_FATAL), unit, filename, line, lvalue); + if (r < 0) + return missing_ok ? 0 : -ENOEXEC; + + c->working_directory_home = false; + free_and_replace(c->working_directory, k); + } + + c->working_directory_missing_ok = missing_ok; + return 0; +} + +int config_parse_unit_env_file(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char ***env = data; + const Unit *u = userdata; + _cleanup_free_ char *n = NULL; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment frees the list */ + *env = strv_free(*env); + return 0; + } + + r = unit_full_printf(u, rvalue, &n); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + r = path_simplify_and_warn(n[0] == '-' ? n + 1 : n, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + return 0; + + r = strv_push(env, n); + if (r < 0) + return log_oom(); + + n = NULL; + + return 0; +} + +int config_parse_environ( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const Unit *u = userdata; + char ***env = data; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + *env = strv_free(*env); + return 0; + } + + for (p = rvalue;; ) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + if (u) { + r = unit_full_printf(u, word, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in %s, ignoring: %m", word); + continue; + } + } else + k = TAKE_PTR(word); + + if (!env_assignment_is_valid(k)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid environment assignment, ignoring: %s", k); + continue; + } + + r = strv_env_replace(env, k); + if (r < 0) + return log_oom(); + + k = NULL; + } +} + +int config_parse_pass_environ( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_strv_free_ char **n = NULL; + size_t nlen = 0, nbufsize = 0; + char*** passenv = data; + const char *p = rvalue; + const Unit *u = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + *passenv = strv_free(*passenv); + return 0; + } + + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Trailing garbage in %s, ignoring: %s", lvalue, rvalue); + break; + } + + if (u) { + r = unit_full_printf(u, word, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve specifiers in %s, ignoring: %m", word); + continue; + } + } else + k = TAKE_PTR(word); + + if (!env_name_is_valid(k)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid environment name for %s, ignoring: %s", lvalue, k); + continue; + } + + if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) + return log_oom(); + + n[nlen++] = TAKE_PTR(k); + n[nlen] = NULL; + } + + if (n) { + r = strv_extend_strv(passenv, n, true); + if (r < 0) + return r; + } + + return 0; +} + +int config_parse_unset_environ( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_strv_free_ char **n = NULL; + size_t nlen = 0, nbufsize = 0; + char*** unsetenv = data; + const char *p = rvalue; + const Unit *u = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + *unsetenv = strv_free(*unsetenv); + return 0; + } + + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Trailing garbage in %s, ignoring: %s", lvalue, rvalue); + break; + } + + if (u) { + r = unit_full_printf(u, word, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in %s, ignoring: %m", word); + continue; + } + } else + k = TAKE_PTR(word); + + if (!env_assignment_is_valid(k) && !env_name_is_valid(k)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid environment name or assignment %s, ignoring: %s", lvalue, k); + continue; + } + + if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) + return log_oom(); + + n[nlen++] = TAKE_PTR(k); + n[nlen] = NULL; + } + + if (n) { + r = strv_extend_strv(unsetenv, n, true); + if (r < 0) + return r; + } + + return 0; +} + +int config_parse_log_extra_fields( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + const Unit *u = userdata; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(c); + + if (isempty(rvalue)) { + exec_context_free_log_extra_fields(c); + return 0; + } + + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + struct iovec *t; + const char *eq; + + r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + r = unit_full_printf(u, word, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word); + continue; + } + + eq = strchr(k, '='); + if (!eq) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Log field lacks '=' character, ignoring: %s", k); + continue; + } + + if (!journal_field_valid(k, eq-k, false)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Log field name is invalid, ignoring: %s", k); + continue; + } + + t = reallocarray(c->log_extra_fields, c->n_log_extra_fields+1, sizeof(struct iovec)); + if (!t) + return log_oom(); + + c->log_extra_fields = t; + c->log_extra_fields[c->n_log_extra_fields++] = IOVEC_MAKE_STRING(k); + + k = NULL; + } +} + +int config_parse_unit_condition_path( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *p = NULL; + Condition **list = data, *c; + ConditionType t = ltype; + bool trigger, negate; + const Unit *u = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + *list = condition_free_list(*list); + return 0; + } + + trigger = rvalue[0] == '|'; + if (trigger) + rvalue++; + + negate = rvalue[0] == '!'; + if (negate) + rvalue++; + + r = unit_full_printf(u, rvalue, &p); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); + return 0; + } + + r = path_simplify_and_warn(p, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + return 0; + + c = condition_new(t, p, trigger, negate); + if (!c) + return log_oom(); + + LIST_PREPEND(conditions, *list, c); + return 0; +} + +int config_parse_unit_condition_string( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *s = NULL; + Condition **list = data, *c; + ConditionType t = ltype; + bool trigger, negate; + const Unit *u = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + *list = condition_free_list(*list); + return 0; + } + + trigger = *rvalue == '|'; + if (trigger) + rvalue += 1 + strspn(rvalue + 1, WHITESPACE); + + negate = *rvalue == '!'; + if (negate) + rvalue += 1 + strspn(rvalue + 1, WHITESPACE); + + r = unit_full_printf(u, rvalue, &s); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + c = condition_new(t, s, trigger, negate); + if (!c) + return log_oom(); + + LIST_PREPEND(conditions, *list, c); + return 0; +} + +int config_parse_unit_condition_null( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Condition **list = data, *c; + bool trigger, negate; + int b; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is deprecated, please do not use.", lvalue); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + *list = condition_free_list(*list); + return 0; + } + + trigger = rvalue[0] == '|'; + if (trigger) + rvalue++; + + negate = rvalue[0] == '!'; + if (negate) + rvalue++; + + b = parse_boolean(rvalue); + if (b < 0) { + log_syntax(unit, LOG_ERR, filename, line, b, "Failed to parse boolean value in condition, ignoring: %s", rvalue); + return 0; + } + + if (!b) + negate = !negate; + + c = condition_new(CONDITION_NULL, NULL, trigger, negate); + if (!c) + return log_oom(); + + LIST_PREPEND(conditions, *list, c); + return 0; +} + +int config_parse_unit_requires_mounts_for( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const char *p = rvalue; + Unit *u = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + for (;;) { + _cleanup_free_ char *word = NULL, *resolved = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + r = unit_full_printf(u, word, &resolved); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); + continue; + } + + r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + continue; + + r = unit_require_mounts_for(u, resolved, UNIT_DEPENDENCY_FILE); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add required mount '%s', ignoring: %m", resolved); + continue; + } + } +} + +int config_parse_documentation(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Unit *u = userdata; + int r; + char **a, **b; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + u->documentation = strv_free(u->documentation); + return 0; + } + + r = config_parse_unit_strv_printf(unit, filename, line, section, section_line, lvalue, ltype, + rvalue, data, userdata); + if (r < 0) + return r; + + for (a = b = u->documentation; a && *a; a++) { + + if (documentation_url_is_valid(*a)) + *(b++) = *a; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid URL, ignoring: %s", *a); + free(*a); + } + } + if (b) + *b = NULL; + + return r; +} + +#if HAVE_SECCOMP +int config_parse_syscall_filter( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + const Unit *u = userdata; + bool invert = false; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + c->syscall_filter = hashmap_free(c->syscall_filter); + c->syscall_whitelist = false; + return 0; + } + + if (rvalue[0] == '~') { + invert = true; + rvalue++; + } + + if (!c->syscall_filter) { + c->syscall_filter = hashmap_new(NULL); + if (!c->syscall_filter) + return log_oom(); + + if (invert) + /* Allow everything but the ones listed */ + c->syscall_whitelist = false; + else { + /* Allow nothing but the ones listed */ + c->syscall_whitelist = true; + + /* Accept default syscalls if we are on a whitelist */ + r = seccomp_parse_syscall_filter( + "@default", -1, c->syscall_filter, + SECCOMP_PARSE_PERMISSIVE|SECCOMP_PARSE_WHITELIST, + unit, + NULL, 0); + if (r < 0) + return r; + } + } + + p = rvalue; + for (;;) { + _cleanup_free_ char *word = NULL, *name = NULL; + int num; + + r = extract_first_word(&p, &word, NULL, 0); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + r = parse_syscall_and_errno(word, &name, &num); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse syscall:errno, ignoring: %s", word); + continue; + } + + r = seccomp_parse_syscall_filter( + name, num, c->syscall_filter, + SECCOMP_PARSE_LOG|SECCOMP_PARSE_PERMISSIVE| + (invert ? SECCOMP_PARSE_INVERT : 0)| + (c->syscall_whitelist ? SECCOMP_PARSE_WHITELIST : 0), + unit, filename, line); + if (r < 0) + return r; + } +} + +int config_parse_syscall_archs( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const char *p = rvalue; + Set **archs = data; + int r; + + if (isempty(rvalue)) { + *archs = set_free(*archs); + return 0; + } + + r = set_ensure_allocated(archs, NULL); + if (r < 0) + return log_oom(); + + for (;;) { + _cleanup_free_ char *word = NULL; + uint32_t a; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + r = seccomp_arch_from_string(word, &a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse system call architecture \"%s\", ignoring: %m", word); + continue; + } + + r = set_put(*archs, UINT32_TO_PTR(a + 1)); + if (r < 0) + return log_oom(); + } +} + +int config_parse_syscall_errno( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + int e; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + /* Empty assignment resets to KILL */ + c->syscall_errno = 0; + return 0; + } + + e = parse_errno(rvalue); + if (e <= 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse error number, ignoring: %s", rvalue); + return 0; + } + + c->syscall_errno = e; + return 0; +} + +int config_parse_address_families( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + bool invert = false; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + c->address_families = set_free(c->address_families); + c->address_families_whitelist = false; + return 0; + } + + if (rvalue[0] == '~') { + invert = true; + rvalue++; + } + + if (!c->address_families) { + c->address_families = set_new(NULL); + if (!c->address_families) + return log_oom(); + + c->address_families_whitelist = !invert; + } + + for (p = rvalue;;) { + _cleanup_free_ char *word = NULL; + int af; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + af = af_from_name(word); + if (af < 0) { + log_syntax(unit, LOG_ERR, filename, line, af, + "Failed to parse address family, ignoring: %s", word); + continue; + } + + /* If we previously wanted to forbid an address family and now + * we want to allow it, then just remove it from the list. + */ + if (!invert == c->address_families_whitelist) { + r = set_put(c->address_families, INT_TO_PTR(af)); + if (r < 0) + return log_oom(); + } else + set_remove(c->address_families, INT_TO_PTR(af)); + } +} + +int config_parse_restrict_namespaces( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + unsigned long flags; + bool invert = false; + int r; + + if (isempty(rvalue)) { + /* Reset to the default. */ + c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL; + return 0; + } + + /* Boolean parameter ignores the previous settings */ + r = parse_boolean(rvalue); + if (r > 0) { + c->restrict_namespaces = 0; + return 0; + } else if (r == 0) { + c->restrict_namespaces = NAMESPACE_FLAGS_ALL; + return 0; + } + + if (rvalue[0] == '~') { + invert = true; + rvalue++; + } + + /* Not a boolean argument, in this case it's a list of namespace types. */ + r = namespace_flags_from_string(rvalue, &flags); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse namespace type string, ignoring: %s", rvalue); + return 0; + } + + if (c->restrict_namespaces == NAMESPACE_FLAGS_INITIAL) + /* Initial assignment. Just set the value. */ + c->restrict_namespaces = invert ? (~flags) & NAMESPACE_FLAGS_ALL : flags; + else + /* Merge the value with the previous one. */ + SET_FLAG(c->restrict_namespaces, flags, !invert); + + return 0; +} +#endif + +int config_parse_unit_slice( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *k = NULL; + Unit *u = userdata, *slice; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + r = unit_name_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); + return 0; + } + + r = manager_load_unit(u->manager, k, NULL, &error, &slice); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load slice unit %s, ignoring: %s", k, bus_error_message(&error, r)); + return 0; + } + + r = unit_set_slice(u, slice); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to assign slice %s to unit %s, ignoring: %m", slice->id, u->id); + return 0; + } + + return 0; +} + +int config_parse_cpu_quota( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + c->cpu_quota_per_sec_usec = USEC_INFINITY; + return 0; + } + + r = parse_permille_unbounded(rvalue); + if (r <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid CPU quota '%s', ignoring.", rvalue); + return 0; + } + + c->cpu_quota_per_sec_usec = ((usec_t) r * USEC_PER_SEC) / 1000U; + return 0; +} + +int config_parse_allowed_cpus( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + + (void) parse_cpu_set_extend(rvalue, &c->cpuset_cpus, true, unit, filename, line, lvalue); + + return 0; +} + +int config_parse_allowed_mems( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + + (void) parse_cpu_set_extend(rvalue, &c->cpuset_mems, true, unit, filename, line, lvalue); + + return 0; +} + +int config_parse_memory_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + uint64_t bytes = CGROUP_LIMIT_MAX; + int r; + + if (!isempty(rvalue) && !streq(rvalue, "infinity")) { + + r = parse_permille(rvalue); + if (r < 0) { + r = parse_size(rvalue, 1024, &bytes); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid memory limit '%s', ignoring: %m", rvalue); + return 0; + } + } else + bytes = physical_memory_scale(r, 1000U); + + if (bytes >= UINT64_MAX || + (bytes <= 0 && !STR_IN_SET(lvalue, "MemorySwapMax", "MemoryLow", "MemoryMin", "DefaultMemoryLow", "DefaultMemoryMin"))) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range, ignoring.", rvalue); + return 0; + } + } + + if (streq(lvalue, "DefaultMemoryLow")) { + c->default_memory_low_set = true; + if (isempty(rvalue)) + c->default_memory_low = CGROUP_LIMIT_MIN; + else + c->default_memory_low = bytes; + } else if (streq(lvalue, "DefaultMemoryMin")) { + c->default_memory_min_set = true; + if (isempty(rvalue)) + c->default_memory_min = CGROUP_LIMIT_MIN; + else + c->default_memory_min = bytes; + } else if (streq(lvalue, "MemoryMin")) { + c->memory_min = bytes; + c->memory_min_set = true; + } else if (streq(lvalue, "MemoryLow")) { + c->memory_low = bytes; + c->memory_low_set = true; + } else if (streq(lvalue, "MemoryHigh")) + c->memory_high = bytes; + else if (streq(lvalue, "MemoryMax")) + c->memory_max = bytes; + else if (streq(lvalue, "MemorySwapMax")) + c->memory_swap_max = bytes; + else if (streq(lvalue, "MemoryLimit")) + c->memory_limit = bytes; + else + return -EINVAL; + + return 0; +} + +int config_parse_tasks_max( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const Unit *u = userdata; + TasksMax *tasks_max = data; + uint64_t v; + int r; + + if (isempty(rvalue)) { + *tasks_max = u ? u->manager->default_tasks_max : TASKS_MAX_UNSET; + return 0; + } + + if (streq(rvalue, "infinity")) { + *tasks_max = TASKS_MAX_UNSET; + return 0; + } + + r = parse_permille(rvalue); + if (r >= 0) + *tasks_max = (TasksMax) { r, 1000U }; /* r‰ */ + else { + r = safe_atou64(rvalue, &v); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid maximum tasks value '%s', ignoring: %m", rvalue); + return 0; + } + + if (v <= 0 || v >= UINT64_MAX) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range, ignoring.", rvalue); + return 0; + } + + *tasks_max = (TasksMax) { v }; + } + + return 0; +} + +int config_parse_delegate( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CGroupContext *c = data; + UnitType t; + int r; + + t = unit_name_to_type(unit); + assert(t != _UNIT_TYPE_INVALID); + + if (!unit_vtable[t]->can_delegate) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Delegate= setting not supported for this unit type, ignoring."); + return 0; + } + + /* We either accept a boolean value, which may be used to turn on delegation for all controllers, or turn it + * off for all. Or it takes a list of controller names, in which case we add the specified controllers to the + * mask to delegate. */ + + if (isempty(rvalue)) { + /* An empty string resets controllers and set Delegate=yes. */ + c->delegate = true; + c->delegate_controllers = 0; + return 0; + } + + r = parse_boolean(rvalue); + if (r < 0) { + const char *p = rvalue; + CGroupMask mask = 0; + + for (;;) { + _cleanup_free_ char *word = NULL; + CGroupController cc; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + cc = cgroup_controller_from_string(word); + if (cc < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid controller name '%s', ignoring", word); + continue; + } + + mask |= CGROUP_CONTROLLER_TO_MASK(cc); + } + + c->delegate = true; + c->delegate_controllers |= mask; + + } else if (r > 0) { + c->delegate = true; + c->delegate_controllers = _CGROUP_MASK_ALL; + } else { + c->delegate = false; + c->delegate_controllers = 0; + } + + return 0; +} + +int config_parse_device_allow( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *path = NULL, *resolved = NULL; + CGroupContext *c = data; + const char *p = rvalue; + int r; + + if (isempty(rvalue)) { + while (c->device_allow) + cgroup_context_free_device_allow(c, c->device_allow); + + return 0; + } + + r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + if (r == 0) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to extract device path and rights from '%s', ignoring.", rvalue); + return 0; + } + + r = unit_full_printf(userdata, path, &resolved); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to resolve unit specifiers in '%s', ignoring: %m", path); + return 0; + } + + if (!STARTSWITH_SET(resolved, "block-", "char-")) { + + r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue); + if (r < 0) + return 0; + + if (!valid_device_node_path(resolved)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s', ignoring.", resolved); + return 0; + } + } + + if (!isempty(p) && !in_charset(p, "rwm")) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device rights '%s', ignoring.", p); + return 0; + } + + return cgroup_add_device_allow(c, resolved, p); +} + +int config_parse_io_device_weight( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *path = NULL, *resolved = NULL; + CGroupIODeviceWeight *w; + CGroupContext *c = data; + const char *p = rvalue; + uint64_t u; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + while (c->io_device_weights) + cgroup_context_free_io_device_weight(c, c->io_device_weights); + + return 0; + } + + r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + if (r == 0 || isempty(p)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to extract device path and weight from '%s', ignoring.", rvalue); + return 0; + } + + r = unit_full_printf(userdata, path, &resolved); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to resolve unit specifiers in '%s', ignoring: %m", path); + return 0; + } + + r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue); + if (r < 0) + return 0; + + r = cg_weight_parse(p, &u); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid, ignoring: %m", p); + return 0; + } + + assert(u != CGROUP_WEIGHT_INVALID); + + w = new0(CGroupIODeviceWeight, 1); + if (!w) + return log_oom(); + + w->path = TAKE_PTR(resolved); + w->weight = u; + + LIST_PREPEND(device_weights, c->io_device_weights, w); + return 0; +} + +int config_parse_io_device_latency( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *path = NULL, *resolved = NULL; + CGroupIODeviceLatency *l; + CGroupContext *c = data; + const char *p = rvalue; + usec_t usec; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + while (c->io_device_latencies) + cgroup_context_free_io_device_latency(c, c->io_device_latencies); + + return 0; + } + + r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + if (r == 0 || isempty(p)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to extract device path and latency from '%s', ignoring.", rvalue); + return 0; + } + + r = unit_full_printf(userdata, path, &resolved); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to resolve unit specifiers in '%s', ignoring: %m", path); + return 0; + } + + r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue); + if (r < 0) + return 0; + + if (parse_sec(p, &usec) < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse timer value, ignoring: %s", p); + return 0; + } + + l = new0(CGroupIODeviceLatency, 1); + if (!l) + return log_oom(); + + l->path = TAKE_PTR(resolved); + l->target_usec = usec; + + LIST_PREPEND(device_latencies, c->io_device_latencies, l); + return 0; +} + +int config_parse_io_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *path = NULL, *resolved = NULL; + CGroupIODeviceLimit *l = NULL, *t; + CGroupContext *c = data; + CGroupIOLimitType type; + const char *p = rvalue; + uint64_t num; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + type = cgroup_io_limit_type_from_string(lvalue); + assert(type >= 0); + + if (isempty(rvalue)) { + LIST_FOREACH(device_limits, l, c->io_device_limits) + l->limits[type] = cgroup_io_limit_defaults[type]; + return 0; + } + + r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + if (r == 0 || isempty(p)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to extract device node and bandwidth from '%s', ignoring.", rvalue); + return 0; + } + + r = unit_full_printf(userdata, path, &resolved); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to resolve unit specifiers in '%s', ignoring: %m", path); + return 0; + } + + r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue); + if (r < 0) + return 0; + + if (streq("infinity", p)) + num = CGROUP_LIMIT_MAX; + else { + r = parse_size(p, 1000, &num); + if (r < 0 || num <= 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid IO limit '%s', ignoring.", p); + return 0; + } + } + + LIST_FOREACH(device_limits, t, c->io_device_limits) { + if (path_equal(resolved, t->path)) { + l = t; + break; + } + } + + if (!l) { + CGroupIOLimitType ttype; + + l = new0(CGroupIODeviceLimit, 1); + if (!l) + return log_oom(); + + l->path = TAKE_PTR(resolved); + for (ttype = 0; ttype < _CGROUP_IO_LIMIT_TYPE_MAX; ttype++) + l->limits[ttype] = cgroup_io_limit_defaults[ttype]; + + LIST_PREPEND(device_limits, c->io_device_limits, l); + } + + l->limits[type] = num; + + return 0; +} + +int config_parse_blockio_device_weight( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *path = NULL, *resolved = NULL; + CGroupBlockIODeviceWeight *w; + CGroupContext *c = data; + const char *p = rvalue; + uint64_t u; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + while (c->blockio_device_weights) + cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights); + + return 0; + } + + r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + if (r == 0 || isempty(p)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to extract device node and weight from '%s', ignoring.", rvalue); + return 0; + } + + r = unit_full_printf(userdata, path, &resolved); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to resolve unit specifiers in '%s', ignoring: %m", path); + return 0; + } + + r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue); + if (r < 0) + return 0; + + r = cg_blkio_weight_parse(p, &u); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid block IO weight '%s', ignoring: %m", p); + return 0; + } + + assert(u != CGROUP_BLKIO_WEIGHT_INVALID); + + w = new0(CGroupBlockIODeviceWeight, 1); + if (!w) + return log_oom(); + + w->path = TAKE_PTR(resolved); + w->weight = u; + + LIST_PREPEND(device_weights, c->blockio_device_weights, w); + return 0; +} + +int config_parse_blockio_bandwidth( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *path = NULL, *resolved = NULL; + CGroupBlockIODeviceBandwidth *b = NULL, *t; + CGroupContext *c = data; + const char *p = rvalue; + uint64_t bytes; + bool read; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + read = streq("BlockIOReadBandwidth", lvalue); + + if (isempty(rvalue)) { + LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) { + b->rbps = CGROUP_LIMIT_MAX; + b->wbps = CGROUP_LIMIT_MAX; + } + return 0; + } + + r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + if (r == 0 || isempty(p)) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to extract device node and bandwidth from '%s', ignoring.", rvalue); + return 0; + } + + r = unit_full_printf(userdata, path, &resolved); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to resolve unit specifiers in '%s', ignoring: %m", path); + return 0; + } + + r = path_simplify_and_warn(resolved, 0, unit, filename, line, lvalue); + if (r < 0) + return 0; + + r = parse_size(p, 1000, &bytes); + if (r < 0 || bytes <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid Block IO Bandwidth '%s', ignoring.", p); + return 0; + } + + LIST_FOREACH(device_bandwidths, t, c->blockio_device_bandwidths) { + if (path_equal(resolved, t->path)) { + b = t; + break; + } + } + + if (!t) { + b = new0(CGroupBlockIODeviceBandwidth, 1); + if (!b) + return log_oom(); + + b->path = TAKE_PTR(resolved); + b->rbps = CGROUP_LIMIT_MAX; + b->wbps = CGROUP_LIMIT_MAX; + + LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b); + } + + if (read) + b->rbps = bytes; + else + b->wbps = bytes; + + return 0; +} + +int config_parse_job_mode_isolate( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + JobMode *m = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse boolean, ignoring: %s", rvalue); + return 0; + } + + log_notice("%s is deprecated. Please use OnFailureJobMode= instead", lvalue); + + *m = r ? JOB_ISOLATE : JOB_REPLACE; + return 0; +} + +int config_parse_exec_directories( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char***rt = data; + const Unit *u = userdata; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + *rt = strv_free(*rt); + return 0; + } + + for (p = rvalue;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + return 0; + + r = unit_full_printf(u, word, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word); + continue; + } + + r = path_simplify_and_warn(k, PATH_CHECK_RELATIVE, unit, filename, line, lvalue); + if (r < 0) + continue; + + if (path_startswith(k, "private")) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "%s= path can't be 'private', ignoring assignment: %s", lvalue, word); + continue; + } + + r = strv_push(rt, k); + if (r < 0) + return log_oom(); + k = NULL; + } +} + +int config_parse_set_status( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + size_t l; + const char *word, *state; + int r; + ExitStatusSet *status_set = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* Empty assignment resets the list */ + if (isempty(rvalue)) { + exit_status_set_free(status_set); + return 0; + } + + FOREACH_WORD(word, l, rvalue, state) { + _cleanup_free_ char *temp; + Bitmap *bitmap; + + temp = strndup(word, l); + if (!temp) + return log_oom(); + + /* We need to call exit_status_from_string() first, because we want + * to parse numbers as exit statuses, not signals. */ + + r = exit_status_from_string(temp); + if (r >= 0) { + assert(r >= 0 && r < 256); + bitmap = &status_set->status; + } else { + r = signal_from_string(temp); + + if (r <= 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse value, ignoring: %s", word); + continue; + } + bitmap = &status_set->signal; + } + + r = bitmap_set(bitmap, r); + if (r < 0) + return log_error_errno(r, "Failed to set signal or status %s: %m", word); + } + if (!isempty(state)) + log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring."); + + return 0; +} + +int config_parse_namespace_path_strv( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const Unit *u = userdata; + char*** sv = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + *sv = strv_free(*sv); + return 0; + } + + for (;;) { + _cleanup_free_ char *word = NULL, *resolved = NULL, *joined = NULL; + const char *w; + bool ignore_enoent = false, shall_prefix = false; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue); + return 0; + } + + w = word; + if (startswith(w, "-")) { + ignore_enoent = true; + w++; + } + if (startswith(w, "+")) { + shall_prefix = true; + w++; + } + + r = unit_full_printf(u, w, &resolved); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", w); + continue; + } + + r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + continue; + + joined = strjoin(ignore_enoent ? "-" : "", + shall_prefix ? "+" : "", + resolved); + + r = strv_push(sv, joined); + if (r < 0) + return log_oom(); + + joined = NULL; + } + + return 0; +} + +int config_parse_temporary_filesystems( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const Unit *u = userdata; + ExecContext *c = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems); + c->temporary_filesystems = NULL; + c->n_temporary_filesystems = 0; + return 0; + } + + for (;;) { + _cleanup_free_ char *word = NULL, *path = NULL, *resolved = NULL; + const char *w; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue); + return 0; + } + + w = word; + r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", word); + continue; + } + if (r == 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring: %s", word); + continue; + } + + r = unit_full_printf(u, path, &resolved); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", path); + continue; + } + + r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + continue; + + r = temporary_filesystem_add(&c->temporary_filesystems, &c->n_temporary_filesystems, resolved, w); + if (r < 0) + return log_oom(); + } +} + +int config_parse_bind_paths( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + const Unit *u = userdata; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + bind_mount_free_many(c->bind_mounts, c->n_bind_mounts); + c->bind_mounts = NULL; + c->n_bind_mounts = 0; + return 0; + } + + p = rvalue; + for (;;) { + _cleanup_free_ char *source = NULL, *destination = NULL; + _cleanup_free_ char *sresolved = NULL, *dresolved = NULL; + char *s = NULL, *d = NULL; + bool rbind = true, ignore_enoent = false; + + r = extract_first_word(&p, &source, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue); + return 0; + } + + r = unit_full_printf(u, source, &sresolved); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolved unit specifiers in \"%s\", ignoring: %m", source); + continue; + } + + s = sresolved; + if (s[0] == '-') { + ignore_enoent = true; + s++; + } + + r = path_simplify_and_warn(s, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + continue; + + /* Optionally, the destination is specified. */ + if (p && p[-1] == ':') { + r = extract_first_word(&p, &destination, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue); + return 0; + } + if (r == 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Missing argument after ':', ignoring: %s", s); + continue; + } + + r = unit_full_printf(u, destination, &dresolved); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to resolved specifiers in \"%s\", ignoring: %m", destination); + continue; + } + + r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + continue; + + d = dresolved; + + /* Optionally, there's also a short option string specified */ + if (p && p[-1] == ':') { + _cleanup_free_ char *options = NULL; + + r = extract_first_word(&p, &options, NULL, EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s: %s", lvalue, rvalue); + return 0; + } + + if (isempty(options) || streq(options, "rbind")) + rbind = true; + else if (streq(options, "norbind")) + rbind = false; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid option string, ignoring setting: %s", options); + continue; + } + } + } else + d = s; + + r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts, + &(BindMount) { + .source = s, + .destination = d, + .read_only = !!strstr(lvalue, "ReadOnly"), + .recursive = rbind, + .ignore_enoent = ignore_enoent, + }); + if (r < 0) + return log_oom(); + } + + return 0; +} + +int config_parse_job_timeout_sec( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Unit *u = data; + usec_t usec; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + r = parse_sec_fix_0(rvalue, &usec); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse JobTimeoutSec= parameter, ignoring: %s", rvalue); + return 0; + } + + /* If the user explicitly changed JobTimeoutSec= also change JobRunningTimeoutSec=, for compatibility with old + * versions. If JobRunningTimeoutSec= was explicitly set, avoid this however as whatever the user picked should + * count. */ + + if (!u->job_running_timeout_set) + u->job_running_timeout = usec; + + u->job_timeout = usec; + + return 0; +} + +int config_parse_job_running_timeout_sec( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Unit *u = data; + usec_t usec; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + r = parse_sec_fix_0(rvalue, &usec); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse JobRunningTimeoutSec= parameter, ignoring: %s", rvalue); + return 0; + } + + u->job_running_timeout = usec; + u->job_running_timeout_set = true; + + return 0; +} + +int config_parse_emergency_action( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Manager *m = NULL; + EmergencyAction *x = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (unit) + m = ((Unit*) userdata)->manager; + else + m = data; + + r = parse_emergency_action(rvalue, MANAGER_IS_SYSTEM(m), x); + if (r < 0) { + if (r == -EOPNOTSUPP && MANAGER_IS_USER(m)) { + /* Compat mode: remove for systemd 241. */ + + log_syntax(unit, LOG_INFO, filename, line, r, + "%s= in user mode specified as \"%s\", using \"exit-force\" instead.", + lvalue, rvalue); + *x = EMERGENCY_ACTION_EXIT_FORCE; + return 0; + } + + if (r == -EOPNOTSUPP) + log_syntax(unit, LOG_ERR, filename, line, r, + "%s= specified as %s mode action, ignoring: %s", + lvalue, MANAGER_IS_SYSTEM(m) ? "user" : "system", rvalue); + else + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse %s=, ignoring: %s", lvalue, rvalue); + return 0; + } + + return 0; +} + +int config_parse_pid_file( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *k = NULL, *n = NULL; + const Unit *u = userdata; + char **s = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(u); + + if (isempty(rvalue)) { + /* An empty assignment removes already set value. */ + *s = mfree(*s); + return 0; + } + + r = unit_full_printf(u, rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + /* If this is a relative path make it absolute by prefixing the /run */ + n = path_make_absolute(k, u->manager->prefix[EXEC_DIRECTORY_RUNTIME]); + if (!n) + return log_oom(); + + /* Check that the result is a sensible path */ + r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + return r; + + r = patch_var_run(unit, filename, line, lvalue, &n); + if (r < 0) + return r; + + free_and_replace(*s, n); + return 0; +} + +int config_parse_exit_status( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int *exit_status = data, r; + uint8_t u; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(exit_status); + + if (isempty(rvalue)) { + *exit_status = -1; + return 0; + } + + r = safe_atou8(rvalue, &u); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse exit status '%s', ignoring: %m", rvalue); + return 0; + } + + *exit_status = u; + return 0; +} + +int config_parse_disable_controllers( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int r; + CGroupContext *c = data; + CGroupMask disabled_mask; + + /* 1. If empty, make all controllers eligible for use again. + * 2. If non-empty, merge all listed controllers, space separated. */ + + if (isempty(rvalue)) { + c->disable_controllers = 0; + return 0; + } + + r = cg_mask_from_string(rvalue, &disabled_mask); + if (r < 0 || disabled_mask <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid cgroup string: %s, ignoring", rvalue); + return 0; + } + + c->disable_controllers |= disabled_mask; + + return 0; +} + +int config_parse_ip_filter_bpf_progs( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *resolved = NULL; + const Unit *u = userdata; + char ***paths = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(paths); + + if (isempty(rvalue)) { + *paths = strv_free(*paths); + return 0; + } + + r = unit_full_printf(u, rvalue, &resolved); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); + return 0; + } + + r = path_simplify_and_warn(resolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue); + if (r < 0) + return 0; + + if (strv_contains(*paths, resolved)) + return 0; + + r = strv_extend(paths, resolved); + if (r < 0) + return log_oom(); + + r = bpf_firewall_supported(); + if (r < 0) + return r; + if (r != BPF_FIREWALL_SUPPORTED_WITH_MULTI) { + static bool warned = false; + + log_full(warned ? LOG_DEBUG : LOG_WARNING, + "File %s:%u configures an IP firewall with BPF programs (%s=%s), but the local system does not support BPF/cgroup based firewalling with multiple filters.\n" + "Starting this unit will fail! (This warning is only shown for the first loaded unit using IP firewalling.)", filename, line, lvalue, rvalue); + + warned = true; + } + + return 0; +} + +static int merge_by_names(Unit **u, Set *names, const char *id) { + char *k; + int r; + + assert(u); + assert(*u); + + /* Let's try to add in all names that are aliases of this unit */ + while ((k = set_steal_first(names))) { + _cleanup_free_ _unused_ char *free_k = k; + + /* First try to merge in the other name into our unit */ + r = unit_merge_by_name(*u, k); + if (r < 0) { + Unit *other; + + /* Hmm, we couldn't merge the other unit into ours? Then let's try it the other way + * round. */ + + other = manager_get_unit((*u)->manager, k); + if (!other) + return r; /* return previous failure */ + + r = unit_merge(other, *u); + if (r < 0) + return r; + + *u = other; + return merge_by_names(u, names, NULL); + } + + if (streq_ptr(id, k)) + unit_choose_id(*u, id); + } + + return 0; +} + +int unit_load_fragment(Unit *u) { + const char *fragment; + _cleanup_set_free_free_ Set *names = NULL; + struct stat st; + int r; + + assert(u); + assert(u->load_state == UNIT_STUB); + assert(u->id); + + if (u->transient) { + u->load_state = UNIT_LOADED; + return 0; + } + + /* Possibly rebuild the fragment map to catch new units */ + r = unit_file_build_name_map(&u->manager->lookup_paths, + &u->manager->unit_cache_mtime, + &u->manager->unit_id_map, + &u->manager->unit_name_map, + &u->manager->unit_path_cache); + if (r < 0) + log_error_errno(r, "Failed to rebuild name map: %m"); + + r = unit_file_find_fragment(u->manager->unit_id_map, + u->manager->unit_name_map, + u->id, + &fragment, + &names); + if (r < 0 && r != -ENOENT) + return r; + + if (fragment) { + /* Open the file, check if this is a mask, otherwise read. */ + _cleanup_fclose_ FILE *f = NULL; + + /* Try to open the file name. A symlink is OK, for example for linked files or masks. We + * expect that all symlinks within the lookup paths have been already resolved, but we don't + * verify this here. */ + f = fopen(fragment, "re"); + if (!f) + return log_unit_notice_errno(u, errno, "Failed to open %s: %m", fragment); + + if (fstat(fileno(f), &st) < 0) + return -errno; + + r = free_and_strdup(&u->fragment_path, fragment); + if (r < 0) + return r; + + if (null_or_empty(&st)) { + /* Unit file is masked */ + + u->load_state = u->perpetual ? UNIT_LOADED : UNIT_MASKED; /* don't allow perpetual units to ever be masked */ + u->fragment_mtime = 0; + } else { + u->load_state = UNIT_LOADED; + u->fragment_mtime = timespec_load(&st.st_mtim); + + /* Now, parse the file contents */ + r = config_parse(u->id, fragment, f, + UNIT_VTABLE(u)->sections, + config_item_perf_lookup, load_fragment_gperf_lookup, + CONFIG_PARSE_ALLOW_INCLUDE, u); + if (r == -ENOEXEC) + log_unit_notice_errno(u, r, "Unit configuration has fatal error, unit will not be started."); + if (r < 0) + return r; + } + } + + if (u->source_path) { + if (stat(u->source_path, &st) >= 0) + u->source_mtime = timespec_load(&st.st_mtim); + else + u->source_mtime = 0; + } + + /* We do the merge dance here because for some unit types, the unit might have aliases which are not + * declared in the file system. In particular, this is true (and frequent) for device and swap units. + */ + Unit *merged; + const char *id = u->id; + _cleanup_free_ char *free_id = NULL; + + if (fragment) { + id = basename(fragment); + if (unit_name_is_valid(id, UNIT_NAME_TEMPLATE)) { + assert(u->instance); /* If we're not trying to use a template for non-instanced unit, + * this must be set. */ + + r = unit_name_replace_instance(id, u->instance, &free_id); + if (r < 0) + return log_debug_errno(r, "Failed to build id (%s + %s): %m", id, u->instance); + id = free_id; + } + } + + merged = u; + r = merge_by_names(&merged, names, id); + if (r < 0) + return r; + + if (merged != u) + u->load_state = UNIT_MERGED; + + return 0; +} + +void unit_dump_config_items(FILE *f) { + static const struct { + const ConfigParserCallback callback; + const char *rvalue; + } table[] = { + { config_parse_warn_compat, "NOTSUPPORTED" }, + { config_parse_int, "INTEGER" }, + { config_parse_unsigned, "UNSIGNED" }, + { config_parse_iec_size, "SIZE" }, + { config_parse_iec_uint64, "SIZE" }, + { config_parse_si_size, "SIZE" }, + { config_parse_bool, "BOOLEAN" }, + { config_parse_string, "STRING" }, + { config_parse_path, "PATH" }, + { config_parse_unit_path_printf, "PATH" }, + { config_parse_strv, "STRING [...]" }, + { config_parse_exec_nice, "NICE" }, + { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" }, + { config_parse_exec_io_class, "IOCLASS" }, + { config_parse_exec_io_priority, "IOPRIORITY" }, + { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" }, + { config_parse_exec_cpu_sched_prio, "CPUSCHEDPRIO" }, + { config_parse_exec_cpu_affinity, "CPUAFFINITY" }, + { config_parse_mode, "MODE" }, + { config_parse_unit_env_file, "FILE" }, + { config_parse_exec_output, "OUTPUT" }, + { config_parse_exec_input, "INPUT" }, + { config_parse_log_facility, "FACILITY" }, + { config_parse_log_level, "LEVEL" }, + { config_parse_exec_secure_bits, "SECUREBITS" }, + { config_parse_capability_set, "BOUNDINGSET" }, + { config_parse_rlimit, "LIMIT" }, + { config_parse_unit_deps, "UNIT [...]" }, + { config_parse_exec, "PATH [ARGUMENT [...]]" }, + { config_parse_service_type, "SERVICETYPE" }, + { config_parse_service_restart, "SERVICERESTART" }, + { config_parse_kill_mode, "KILLMODE" }, + { config_parse_signal, "SIGNAL" }, + { config_parse_socket_listen, "SOCKET [...]" }, + { config_parse_socket_bind, "SOCKETBIND" }, + { config_parse_socket_bindtodevice, "NETWORKINTERFACE" }, + { config_parse_sec, "SECONDS" }, + { config_parse_nsec, "NANOSECONDS" }, + { config_parse_namespace_path_strv, "PATH [...]" }, + { config_parse_bind_paths, "PATH[:PATH[:OPTIONS]] [...]" }, + { config_parse_unit_requires_mounts_for, "PATH [...]" }, + { config_parse_exec_mount_flags, "MOUNTFLAG [...]" }, + { config_parse_unit_string_printf, "STRING" }, + { config_parse_trigger_unit, "UNIT" }, + { config_parse_timer, "TIMER" }, + { config_parse_path_spec, "PATH" }, + { config_parse_notify_access, "ACCESS" }, + { config_parse_ip_tos, "TOS" }, + { config_parse_unit_condition_path, "CONDITION" }, + { config_parse_unit_condition_string, "CONDITION" }, + { config_parse_unit_condition_null, "CONDITION" }, + { config_parse_unit_slice, "SLICE" }, + { config_parse_documentation, "URL" }, + { config_parse_service_timeout, "SECONDS" }, + { config_parse_emergency_action, "ACTION" }, + { config_parse_set_status, "STATUS" }, + { config_parse_service_sockets, "SOCKETS" }, + { config_parse_environ, "ENVIRON" }, +#if HAVE_SECCOMP + { config_parse_syscall_filter, "SYSCALLS" }, + { config_parse_syscall_archs, "ARCHS" }, + { config_parse_syscall_errno, "ERRNO" }, + { config_parse_address_families, "FAMILIES" }, + { config_parse_restrict_namespaces, "NAMESPACES" }, +#endif + { config_parse_cpu_shares, "SHARES" }, + { config_parse_cg_weight, "WEIGHT" }, + { config_parse_memory_limit, "LIMIT" }, + { config_parse_device_allow, "DEVICE" }, + { config_parse_device_policy, "POLICY" }, + { config_parse_io_limit, "LIMIT" }, + { config_parse_io_device_weight, "DEVICEWEIGHT" }, + { config_parse_io_device_latency, "DEVICELATENCY" }, + { config_parse_blockio_bandwidth, "BANDWIDTH" }, + { config_parse_blockio_weight, "WEIGHT" }, + { config_parse_blockio_device_weight, "DEVICEWEIGHT" }, + { config_parse_long, "LONG" }, + { config_parse_socket_service, "SERVICE" }, +#if HAVE_SELINUX + { config_parse_exec_selinux_context, "LABEL" }, +#endif + { config_parse_job_mode, "MODE" }, + { config_parse_job_mode_isolate, "BOOLEAN" }, + { config_parse_personality, "PERSONALITY" }, + }; + + const char *prev = NULL; + const char *i; + + assert(f); + + NULSTR_FOREACH(i, load_fragment_gperf_nulstr) { + const char *rvalue = "OTHER", *lvalue; + const ConfigPerfItem *p; + size_t prefix_len; + const char *dot; + unsigned j; + + assert_se(p = load_fragment_gperf_lookup(i, strlen(i))); + + /* Hide legacy settings */ + if (p->parse == config_parse_warn_compat && + p->ltype == DISABLED_LEGACY) + continue; + + for (j = 0; j < ELEMENTSOF(table); j++) + if (p->parse == table[j].callback) { + rvalue = table[j].rvalue; + break; + } + + dot = strchr(i, '.'); + lvalue = dot ? dot + 1 : i; + prefix_len = dot-i; + + if (dot) + if (!prev || !strneq(prev, i, prefix_len+1)) { + if (prev) + fputc('\n', f); + + fprintf(f, "[%.*s]\n", (int) prefix_len, i); + } + + fprintf(f, "%s=%s\n", lvalue, rvalue); + prev = i; + } +} + +int config_parse_cpu_affinity2( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + CPUSet *affinity = data; + + assert(affinity); + + (void) parse_cpu_set_extend(rvalue, affinity, true, unit, filename, line, lvalue); + + return 0; +} + +int config_parse_show_status( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int k; + ShowStatus *b = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + k = parse_show_status(rvalue, b); + if (k < 0) { + log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse show status setting, ignoring: %s", rvalue); + return 0; + } + + return 0; +} + +int config_parse_output_restricted( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecOutput t, *eo = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + t = exec_output_from_string(rvalue); + if (t < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse output type, ignoring: %s", rvalue); + return 0; + } + + if (IN_SET(t, EXEC_OUTPUT_SOCKET, EXEC_OUTPUT_NAMED_FD, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Standard output types socket, fd:, file:, append: are not supported as defaults, ignoring: %s", rvalue); + return 0; + } + + *eo = t; + return 0; +} + +int config_parse_crash_chvt( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_crash_chvt(rvalue, data); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CrashChangeVT= setting, ignoring: %s", rvalue); + return 0; + } + + return 0; +} diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h new file mode 100644 index 00000000..b81887d5 --- /dev/null +++ b/src/core/load-fragment.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "unit.h" + +/* Config-parsing helpers relevant only for sources under src/core/ */ +int parse_crash_chvt(const char *value, int *data); +int parse_confirm_spawn(const char *value, char **console); + +/* Read service data from .desktop file style configuration fragments */ + +int unit_load_fragment(Unit *u); + +void unit_dump_config_items(FILE *f); + +CONFIG_PARSER_PROTOTYPE(config_parse_unit_deps); +CONFIG_PARSER_PROTOTYPE(config_parse_obsolete_unit_deps); +CONFIG_PARSER_PROTOTYPE(config_parse_unit_string_printf); +CONFIG_PARSER_PROTOTYPE(config_parse_unit_strv_printf); +CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_printf); +CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_strv_printf); +CONFIG_PARSER_PROTOTYPE(config_parse_documentation); +CONFIG_PARSER_PROTOTYPE(config_parse_socket_listen); +CONFIG_PARSER_PROTOTYPE(config_parse_socket_protocol); +CONFIG_PARSER_PROTOTYPE(config_parse_socket_bind); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_nice); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_oom_score_adjust); +CONFIG_PARSER_PROTOTYPE(config_parse_exec); +CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout); +CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_abort); +CONFIG_PARSER_PROTOTYPE(config_parse_service_type); +CONFIG_PARSER_PROTOTYPE(config_parse_service_restart); +CONFIG_PARSER_PROTOTYPE(config_parse_socket_bindtodevice); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_output); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_input); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_input_text); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_input_data); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_io_class); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_io_priority); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_policy); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_prio); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits); +CONFIG_PARSER_PROTOTYPE(config_parse_capability_set); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_flags); +CONFIG_PARSER_PROTOTYPE(config_parse_timer); +CONFIG_PARSER_PROTOTYPE(config_parse_trigger_unit); +CONFIG_PARSER_PROTOTYPE(config_parse_path_spec); +CONFIG_PARSER_PROTOTYPE(config_parse_socket_service); +CONFIG_PARSER_PROTOTYPE(config_parse_service_sockets); +CONFIG_PARSER_PROTOTYPE(config_parse_unit_env_file); +CONFIG_PARSER_PROTOTYPE(config_parse_ip_tos); +CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_path); +CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_string); +CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_null); +CONFIG_PARSER_PROTOTYPE(config_parse_kill_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_notify_access); +CONFIG_PARSER_PROTOTYPE(config_parse_emergency_action); +CONFIG_PARSER_PROTOTYPE(config_parse_unit_requires_mounts_for); +CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter); +CONFIG_PARSER_PROTOTYPE(config_parse_syscall_archs); +CONFIG_PARSER_PROTOTYPE(config_parse_syscall_errno); +CONFIG_PARSER_PROTOTYPE(config_parse_environ); +CONFIG_PARSER_PROTOTYPE(config_parse_pass_environ); +CONFIG_PARSER_PROTOTYPE(config_parse_unset_environ); +CONFIG_PARSER_PROTOTYPE(config_parse_unit_slice); +CONFIG_PARSER_PROTOTYPE(config_parse_cg_weight); +CONFIG_PARSER_PROTOTYPE(config_parse_cpu_shares); +CONFIG_PARSER_PROTOTYPE(config_parse_memory_limit); +CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max); +CONFIG_PARSER_PROTOTYPE(config_parse_delegate); +CONFIG_PARSER_PROTOTYPE(config_parse_device_policy); +CONFIG_PARSER_PROTOTYPE(config_parse_device_allow); +CONFIG_PARSER_PROTOTYPE(config_parse_io_device_latency); +CONFIG_PARSER_PROTOTYPE(config_parse_io_device_weight); +CONFIG_PARSER_PROTOTYPE(config_parse_io_limit); +CONFIG_PARSER_PROTOTYPE(config_parse_blockio_weight); +CONFIG_PARSER_PROTOTYPE(config_parse_blockio_device_weight); +CONFIG_PARSER_PROTOTYPE(config_parse_blockio_bandwidth); +CONFIG_PARSER_PROTOTYPE(config_parse_job_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_job_mode_isolate); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_selinux_context); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_apparmor_profile); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_smack_process_label); +CONFIG_PARSER_PROTOTYPE(config_parse_address_families); +CONFIG_PARSER_PROTOTYPE(config_parse_runtime_preserve_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_directories); +CONFIG_PARSER_PROTOTYPE(config_parse_set_status); +CONFIG_PARSER_PROTOTYPE(config_parse_namespace_path_strv); +CONFIG_PARSER_PROTOTYPE(config_parse_temporary_filesystems); +CONFIG_PARSER_PROTOTYPE(config_parse_cpu_quota); +CONFIG_PARSER_PROTOTYPE(config_parse_allowed_cpus); +CONFIG_PARSER_PROTOTYPE(config_parse_allowed_mems); +CONFIG_PARSER_PROTOTYPE(config_parse_protect_home); +CONFIG_PARSER_PROTOTYPE(config_parse_protect_system); +CONFIG_PARSER_PROTOTYPE(config_parse_bus_name); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_utmp_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_working_directory); +CONFIG_PARSER_PROTOTYPE(config_parse_fdname); +CONFIG_PARSER_PROTOTYPE(config_parse_sec_fix_0); +CONFIG_PARSER_PROTOTYPE(config_parse_user_group_compat); +CONFIG_PARSER_PROTOTYPE(config_parse_user_group_strv_compat); +CONFIG_PARSER_PROTOTYPE(config_parse_restrict_namespaces); +CONFIG_PARSER_PROTOTYPE(config_parse_bind_paths); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_keyring_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_job_timeout_sec); +CONFIG_PARSER_PROTOTYPE(config_parse_job_running_timeout_sec); +CONFIG_PARSER_PROTOTYPE(config_parse_log_extra_fields); +CONFIG_PARSER_PROTOTYPE(config_parse_collect_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_pid_file); +CONFIG_PARSER_PROTOTYPE(config_parse_exit_status); +CONFIG_PARSER_PROTOTYPE(config_parse_disable_controllers); +CONFIG_PARSER_PROTOTYPE(config_parse_oom_policy); +CONFIG_PARSER_PROTOTYPE(config_parse_numa_policy); +CONFIG_PARSER_PROTOTYPE(config_parse_numa_mask); +CONFIG_PARSER_PROTOTYPE(config_parse_ip_filter_bpf_progs); +CONFIG_PARSER_PROTOTYPE(config_parse_cpu_affinity2); +CONFIG_PARSER_PROTOTYPE(config_parse_show_status); +CONFIG_PARSER_PROTOTYPE(config_parse_status_unit_format); +CONFIG_PARSER_PROTOTYPE(config_parse_output_restricted); +CONFIG_PARSER_PROTOTYPE(config_parse_crash_chvt); +CONFIG_PARSER_PROTOTYPE(config_parse_timeout_abort); + +/* gperf prototypes */ +const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length); +extern const char load_fragment_gperf_nulstr[]; diff --git a/src/core/locale-setup.c b/src/core/locale-setup.c new file mode 100644 index 00000000..33728b0f --- /dev/null +++ b/src/core/locale-setup.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "env-file.h" +#include "env-util.h" +#include "locale-setup.h" +#include "locale-util.h" +#include "proc-cmdline.h" +#include "string-util.h" +#include "strv.h" +#include "util.h" +#include "virt.h" + +int locale_setup(char ***environment) { + _cleanup_(locale_variables_freep) char *variables[_VARIABLE_LC_MAX] = {}; + _cleanup_strv_free_ char **add = NULL; + LocaleVariable i; + int r; + + r = proc_cmdline_get_key_many(PROC_CMDLINE_STRIP_RD_PREFIX, + "locale.LANG", &variables[VARIABLE_LANG], + "locale.LANGUAGE", &variables[VARIABLE_LANGUAGE], + "locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE], + "locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC], + "locale.LC_TIME", &variables[VARIABLE_LC_TIME], + "locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE], + "locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY], + "locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES], + "locale.LC_PAPER", &variables[VARIABLE_LC_PAPER], + "locale.LC_NAME", &variables[VARIABLE_LC_NAME], + "locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS], + "locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE], + "locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT], + "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION]); + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to read /proc/cmdline: %m"); + + /* Hmm, nothing set on the kernel cmd line? Then let's try /etc/locale.conf */ + if (r <= 0) { + r = parse_env_file(NULL, "/etc/locale.conf", + "LANG", &variables[VARIABLE_LANG], + "LANGUAGE", &variables[VARIABLE_LANGUAGE], + "LC_CTYPE", &variables[VARIABLE_LC_CTYPE], + "LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC], + "LC_TIME", &variables[VARIABLE_LC_TIME], + "LC_COLLATE", &variables[VARIABLE_LC_COLLATE], + "LC_MONETARY", &variables[VARIABLE_LC_MONETARY], + "LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES], + "LC_PAPER", &variables[VARIABLE_LC_PAPER], + "LC_NAME", &variables[VARIABLE_LC_NAME], + "LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS], + "LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE], + "LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT], + "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION]); + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to read /etc/locale.conf: %m"); + } + + for (i = 0; i < _VARIABLE_LC_MAX; i++) { + char *s; + + if (!variables[i]) + continue; + + s = strjoin(locale_variable_to_string(i), "=", variables[i]); + if (!s) + return -ENOMEM; + + if (strv_consume(&add, s) < 0) + return -ENOMEM; + } + + if (strv_isempty(add)) { + /* If no locale is configured then default to compile-time default. */ + + add = strv_new("LANG=" SYSTEMD_DEFAULT_LOCALE); + if (!add) + return -ENOMEM; + } + + if (strv_isempty(*environment)) + strv_free_and_replace(*environment, add); + else { + char **merged; + + merged = strv_env_merge(2, *environment, add); + if (!merged) + return -ENOMEM; + + strv_free_and_replace(*environment, merged); + } + + return 0; +} diff --git a/src/core/locale-setup.h b/src/core/locale-setup.h new file mode 100644 index 00000000..01fadd06 --- /dev/null +++ b/src/core/locale-setup.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int locale_setup(char ***environment); diff --git a/src/core/loopback-setup.c b/src/core/loopback-setup.c new file mode 100644 index 00000000..27d5a11d --- /dev/null +++ b/src/core/loopback-setup.c @@ -0,0 +1,213 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-netlink.h" + +#include "loopback-setup.h" +#include "missing_network.h" +#include "netlink-util.h" +#include "time-util.h" + +#define LOOPBACK_SETUP_TIMEOUT_USEC (5 * USEC_PER_SEC) + +struct state { + unsigned n_messages; + int rcode; + const char *error_message; + const char *success_message; +}; + +static int generic_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { + struct state *s = userdata; + int r; + + assert(s); + assert(s->n_messages > 0); + s->n_messages--; + + errno = 0; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_debug_errno(r, "%s: %m", s->error_message); + else + log_debug("%s", s->success_message); + + s->rcode = r; + return 0; +} + +static int start_loopback(sd_netlink *rtnl, struct state *s) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(rtnl); + assert(s); + + r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, LOOPBACK_IFINDEX); + if (r < 0) + return r; + + r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP); + if (r < 0) + return r; + + r = sd_netlink_call_async(rtnl, NULL, req, generic_handler, NULL, s, LOOPBACK_SETUP_TIMEOUT_USEC, "systemd-start-loopback"); + if (r < 0) + return r; + + s->n_messages ++; + return 0; +} + +static int add_ipv4_address(sd_netlink *rtnl, struct state *s) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(rtnl); + assert(s); + + r = sd_rtnl_message_new_addr(rtnl, &req, RTM_NEWADDR, LOOPBACK_IFINDEX, AF_INET); + if (r < 0) + return r; + + r = sd_rtnl_message_addr_set_prefixlen(req, 8); + if (r < 0) + return r; + + r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT); + if (r < 0) + return r; + + r = sd_rtnl_message_addr_set_scope(req, RT_SCOPE_HOST); + if (r < 0) + return r; + + r = sd_netlink_message_append_in_addr(req, IFA_LOCAL, &(struct in_addr) { .s_addr = htobe32(INADDR_LOOPBACK) } ); + if (r < 0) + return r; + + r = sd_netlink_call_async(rtnl, NULL, req, generic_handler, NULL, s, USEC_INFINITY, "systemd-loopback-ipv4"); + if (r < 0) + return r; + + s->n_messages ++; + return 0; +} + +static int add_ipv6_address(sd_netlink *rtnl, struct state *s) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(rtnl); + assert(s); + + r = sd_rtnl_message_new_addr(rtnl, &req, RTM_NEWADDR, LOOPBACK_IFINDEX, AF_INET6); + if (r < 0) + return r; + + r = sd_rtnl_message_addr_set_prefixlen(req, 128); + if (r < 0) + return r; + + r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT); + if (r < 0) + return r; + + r = sd_rtnl_message_addr_set_scope(req, RT_SCOPE_HOST); + if (r < 0) + return r; + + r = sd_netlink_message_append_in6_addr(req, IFA_LOCAL, &in6addr_loopback); + if (r < 0) + return r; + + r = sd_netlink_call_async(rtnl, NULL, req, generic_handler, NULL, s, USEC_INFINITY, "systemd-loopback-ipv6"); + if (r < 0) + return r; + + s->n_messages ++; + return 0; +} + +static bool check_loopback(sd_netlink *rtnl) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + unsigned flags; + int r; + + r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, LOOPBACK_IFINDEX); + if (r < 0) + return false; + + r = sd_netlink_call(rtnl, req, USEC_INFINITY, &reply); + if (r < 0) + return false; + + r = sd_rtnl_message_link_get_flags(reply, &flags); + if (r < 0) + return false; + + return flags & IFF_UP; +} + +int loopback_setup(void) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + struct state state_4 = { + .error_message = "Failed to add address 127.0.0.1 to loopback interface", + .success_message = "Successfully added address 127.0.0.1 to loopback interface", + }, state_6 = { + .error_message = "Failed to add address ::1 to loopback interface", + .success_message = "Successfully added address ::1 to loopback interface", + }, state_up = { + .error_message = "Failed to bring loopback interface up", + .success_message = "Successfully brought loopback interface up", + }; + int r; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to open netlink: %m"); + + /* Note that we add the IP addresses here explicitly even though the kernel does that too implicitly when + * setting up the loopback device. The reason we do this here a second time (and possibly race against the + * kernel) is that we want to synchronously wait until the IP addresses are set up correctly, see + * + * https://github.com/systemd/systemd/issues/5641 */ + + r = add_ipv4_address(rtnl, &state_4); + if (r < 0) + return log_error_errno(r, "Failed to enqueue IPv4 loopback address add request: %m"); + + r = add_ipv6_address(rtnl, &state_6); + if (r < 0) + return log_error_errno(r, "Failed to enqueue IPv6 loopback address add request: %m"); + + r = start_loopback(rtnl, &state_up); + if (r < 0) + return log_error_errno(r, "Failed to enqueue loopback interface start request: %m"); + + while (state_4.n_messages + state_6.n_messages + state_up.n_messages > 0) { + r = sd_netlink_wait(rtnl, LOOPBACK_SETUP_TIMEOUT_USEC); + if (r < 0) + return log_error_errno(r, "Failed to wait for netlink event: %m"); + + r = sd_netlink_process(rtnl, NULL); + if (r < 0) + return log_warning_errno(r, "Failed to process netlink event: %m"); + } + + /* Note that we don't really care whether the addresses could be added or not */ + if (state_up.rcode != 0) { + /* If we lack the permissions to configure the loopback device, + * but we find it to be already configured, let's exit cleanly, + * in order to supported unprivileged containers. */ + if (state_up.rcode == -EPERM && check_loopback(rtnl)) + return 0; + + return log_warning_errno(state_up.rcode, "Failed to configure loopback device: %m"); + } + + return 0; +} diff --git a/src/core/loopback-setup.h b/src/core/loopback-setup.h new file mode 100644 index 00000000..c0eea100 --- /dev/null +++ b/src/core/loopback-setup.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int loopback_setup(void); diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c new file mode 100644 index 00000000..284b77c1 --- /dev/null +++ b/src/core/machine-id-setup.c @@ -0,0 +1,249 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "id128-util.h" +#include "log.h" +#include "machine-id-setup.h" +#include "macro.h" +#include "mkdir.h" +#include "mountpoint-util.h" +#include "namespace-util.h" +#include "path-util.h" +#include "process-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "umask-util.h" +#include "util.h" +#include "virt.h" + +static int generate_machine_id(const char *root, sd_id128_t *ret) { + const char *dbus_machine_id; + _cleanup_close_ int fd = -1; + int r; + + assert(ret); + + /* First, try reading the D-Bus machine id, unless it is a symlink */ + dbus_machine_id = prefix_roota(root, "/var/lib/dbus/machine-id"); + fd = open(dbus_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd >= 0) { + if (id128_read_fd(fd, ID128_PLAIN, ret) >= 0) { + log_info("Initializing machine ID from D-Bus machine ID."); + return 0; + } + + fd = safe_close(fd); + } + + if (isempty(root)) { + /* If that didn't work, see if we are running in a container, + * and a machine ID was passed in via $container_uuid the way + * libvirt/LXC does it */ + + if (detect_container() > 0) { + _cleanup_free_ char *e = NULL; + + if (getenv_for_pid(1, "container_uuid", &e) > 0 && + sd_id128_from_string(e, ret) >= 0) { + log_info("Initializing machine ID from container UUID."); + return 0; + } + + } else if (detect_vm() == VIRTUALIZATION_KVM) { + + /* If we are not running in a container, see if we are + * running in qemu/kvm and a machine ID was passed in + * via -uuid on the qemu/kvm command line */ + + if (id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, ret) >= 0) { + log_info("Initializing machine ID from KVM UUID."); + return 0; + } + /* on POWER, it's exported here instead */ + if (id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, ret) >= 0) { + log_info("Initializing machine ID from KVM UUID."); + return 0; + } + } + } + + /* If that didn't work, generate a random machine id */ + r = sd_id128_randomize(ret); + if (r < 0) + return log_error_errno(r, "Failed to generate randomized machine ID: %m"); + + log_info("Initializing machine ID from random generator."); + return 0; +} + +int machine_id_setup(const char *root, sd_id128_t machine_id, sd_id128_t *ret) { + const char *etc_machine_id, *run_machine_id; + _cleanup_close_ int fd = -1; + bool writable; + int r; + + etc_machine_id = prefix_roota(root, "/etc/machine-id"); + + RUN_WITH_UMASK(0000) { + /* We create this 0444, to indicate that this isn't really + * something you should ever modify. Of course, since the file + * will be owned by root it doesn't matter much, but maybe + * people look. */ + + (void) mkdir_parents(etc_machine_id, 0755); + fd = open(etc_machine_id, O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY, 0444); + if (fd < 0) { + int old_errno = errno; + + fd = open(etc_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + if (old_errno == EROFS && errno == ENOENT) + return log_error_errno(errno, + "System cannot boot: Missing /etc/machine-id and /etc is mounted read-only.\n" + "Booting up is supported only when:\n" + "1) /etc/machine-id exists and is populated.\n" + "2) /etc/machine-id exists and is empty.\n" + "3) /etc/machine-id is missing and /etc is writable.\n"); + else + return log_error_errno(errno, "Cannot open %s: %m", etc_machine_id); + } + + writable = false; + } else + writable = true; + } + + /* A we got a valid machine ID argument, that's what counts */ + if (sd_id128_is_null(machine_id)) { + + /* Try to read any existing machine ID */ + if (id128_read_fd(fd, ID128_PLAIN, ret) >= 0) + return 0; + + /* Hmm, so, the id currently stored is not useful, then let's generate one */ + r = generate_machine_id(root, &machine_id); + if (r < 0) + return r; + } + + if (writable) { + if (lseek(fd, 0, SEEK_SET) == (off_t) -1) + return log_error_errno(errno, "Failed to seek %s: %m", etc_machine_id); + + if (ftruncate(fd, 0) < 0) + return log_error_errno(errno, "Failed to truncate %s: %m", etc_machine_id); + + if (id128_write_fd(fd, ID128_PLAIN, machine_id, true) >= 0) + goto finish; + } + + fd = safe_close(fd); + + /* Hmm, we couldn't write it? So let's write it to /run/machine-id as a replacement */ + + run_machine_id = prefix_roota(root, "/run/machine-id"); + + RUN_WITH_UMASK(0022) + r = id128_write(run_machine_id, ID128_PLAIN, machine_id, false); + if (r < 0) { + (void) unlink(run_machine_id); + return log_error_errno(r, "Cannot write %s: %m", run_machine_id); + } + + /* And now, let's mount it over */ + if (mount(run_machine_id, etc_machine_id, NULL, MS_BIND, NULL) < 0) { + (void) unlink_noerrno(run_machine_id); + return log_error_errno(errno, "Failed to mount %s: %m", etc_machine_id); + } + + log_info("Installed transient %s file.", etc_machine_id); + + /* Mark the mount read-only */ + if (mount(NULL, etc_machine_id, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL) < 0) + log_warning_errno(errno, "Failed to make transient %s read-only, ignoring: %m", etc_machine_id); + +finish: + if (ret) + *ret = machine_id; + + return 0; +} + +int machine_id_commit(const char *root) { + _cleanup_close_ int fd = -1, initial_mntns_fd = -1; + const char *etc_machine_id; + sd_id128_t id; + int r; + + /* Replaces a tmpfs bind mount of /etc/machine-id by a proper file, atomically. For this, the umount is removed + * in a mount namespace, a new file is created at the right place. Afterwards the mount is also removed in the + * original mount namespace, thus revealing the file that was just created. */ + + etc_machine_id = prefix_roota(root, "/etc/machine-id"); + + r = path_is_mount_point(etc_machine_id, NULL, 0); + if (r < 0) + return log_error_errno(r, "Failed to determine whether %s is a mount point: %m", etc_machine_id); + if (r == 0) { + log_debug("%s is not a mount point. Nothing to do.", etc_machine_id); + return 0; + } + + /* Read existing machine-id */ + fd = open(etc_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return log_error_errno(errno, "Cannot open %s: %m", etc_machine_id); + + r = fd_is_temporary_fs(fd); + if (r < 0) + return log_error_errno(r, "Failed to determine whether %s is on a temporary file system: %m", etc_machine_id); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EROFS), + "%s is not on a temporary file system.", + etc_machine_id); + + r = id128_read_fd(fd, ID128_PLAIN, &id); + if (r < 0) + return log_error_errno(r, "We didn't find a valid machine ID in %s: %m", etc_machine_id); + + fd = safe_close(fd); + + /* Store current mount namespace */ + r = namespace_open(0, NULL, &initial_mntns_fd, NULL, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Can't fetch current mount namespace: %m"); + + /* Switch to a new mount namespace, isolate ourself and unmount etc_machine_id in our new namespace */ + if (unshare(CLONE_NEWNS) < 0) + return log_error_errno(errno, "Failed to enter new namespace: %m"); + + if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) + return log_error_errno(errno, "Couldn't make-rslave / mountpoint in our private namespace: %m"); + + if (umount(etc_machine_id) < 0) + return log_error_errno(errno, "Failed to unmount transient %s file in our private namespace: %m", etc_machine_id); + + /* Update a persistent version of etc_machine_id */ + r = id128_write(etc_machine_id, ID128_PLAIN, id, true); + if (r < 0) + return log_error_errno(r, "Cannot write %s. This is mandatory to get a persistent machine ID: %m", etc_machine_id); + + /* Return to initial namespace and proceed a lazy tmpfs unmount */ + r = namespace_enter(-1, initial_mntns_fd, -1, -1, -1); + if (r < 0) + return log_warning_errno(r, "Failed to switch back to initial mount namespace: %m.\nWe'll keep transient %s file until next reboot.", etc_machine_id); + + if (umount2(etc_machine_id, MNT_DETACH) < 0) + return log_warning_errno(errno, "Failed to unmount transient %s file: %m.\nWe keep that mount until next reboot.", etc_machine_id); + + return 0; +} diff --git a/src/core/machine-id-setup.h b/src/core/machine-id-setup.h new file mode 100644 index 00000000..d6ac62a8 --- /dev/null +++ b/src/core/machine-id-setup.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int machine_id_commit(const char *root); +int machine_id_setup(const char *root, sd_id128_t requested, sd_id128_t *ret); diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in new file mode 100644 index 00000000..9b310c48 --- /dev/null +++ b/src/core/macros.systemd.in @@ -0,0 +1,158 @@ +# -*- Mode: rpm-spec; indent-tabs-mode: nil -*- */ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. + +# RPM macros for packages installing systemd unit files + +%_unitdir @systemunitdir@ +%_userunitdir @userunitdir@ +%_presetdir @systempresetdir@ +%_userpresetdir @userpresetdir@ +%_udevhwdbdir @udevhwdbdir@ +%_udevrulesdir @udevrulesdir@ +%_journalcatalogdir @catalogdir@ +%_binfmtdir @binfmtdir@ +%_sysctldir @sysctldir@ +%_sysusersdir @sysusersdir@ +%_tmpfilesdir @tmpfilesdir@ +%_environmentdir @environmentdir@ +%_modulesloaddir @modulesloaddir@ +%_modprobedir @modprobedir@ +%_systemdgeneratordir @systemgeneratordir@ +%_systemdusergeneratordir @usergeneratordir@ +%_systemd_system_env_generator_dir @systemenvgeneratordir@ +%_systemd_user_env_generator_dir @userenvgeneratordir@ + +# Because we had one release with a typo... +# This is temporary (Remove after systemd 240 is released) +%_environmnentdir %{warn:Use %%_environmentdir instead}%_environmentdir + +%systemd_requires \ +Requires(post): systemd \ +Requires(preun): systemd \ +Requires(postun): systemd \ +%{nil} + +%systemd_ordering \ +OrderWithRequires(post): systemd \ +OrderWithRequires(preun): systemd \ +OrderWithRequires(postun): systemd \ +%{nil} + +%__systemd_someargs_0() %{error:This macro requires some arguments} +%__systemd_twoargs_2() %{nil} + +%systemd_post() \ +%{expand:%%{?__systemd_someargs_%#}} \ +if [ $1 -eq 1 ] && [ -x @bindir@/systemctl ] ; then \ + # Initial installation \ + @bindir@/systemctl --no-reload preset %{?*} || : \ +fi \ +%{nil} + +%systemd_user_post() %{expand:%systemd_post \\--global %%{?*}} + +%systemd_preun() \ +%{expand:%%{?__systemd_someargs_%#}} \ +if [ $1 -eq 0 ] && [ -x @bindir@/systemctl ] ; then \ + # Package removal, not upgrade \ + @bindir@/systemctl --no-reload disable --now %{?*} || : \ +fi \ +%{nil} + +%systemd_user_preun() \ +%{expand:%%{?__systemd_someargs_%#}} \ +if [ $1 -eq 0 ] && [ -x @bindir@/systemctl ] ; then \ + # Package removal, not upgrade \ + @bindir@/systemctl --global disable %{?*} || : \ +fi \ +%{nil} + +%systemd_postun() %{expand:%%{?__systemd_someargs_%#}}%{nil} + +%systemd_user_postun() %{expand:%%{?__systemd_someargs_%#}}%{nil} + +%systemd_postun_with_restart() \ +%{expand:%%{?__systemd_someargs_%#}} \ +if [ $1 -ge 1 ] && [ -x @bindir@/systemctl ] ; then \ + # Package upgrade, not uninstall \ + @bindir@/systemctl try-restart %{?*} || : \ +fi \ +%{nil} + +%systemd_user_postun_with_restart() %{expand:%%{?__systemd_someargs_%#}}%{nil} + +%udev_hwdb_update() %{nil} + +%udev_rules_update() %{nil} + +%journal_catalog_update() %{nil} + +# Deprecated. Use %tmpfiles_create_package instead +%tmpfiles_create() \ +%{expand:%%{?__systemd_someargs_%#}} \ +[ -x @bindir@/systemd-tmpfiles ] && @bindir@/systemd-tmpfiles --create %{?*} || : \ +%{nil} + +# Deprecated. Use %sysusers_create_package instead +%sysusers_create() \ +%{expand:%%{?__systemd_someargs_%#}} \ +[ -x @bindir@/systemd-sysusers ] && @bindir@/systemd-sysusers %{?*} || : \ +%{nil} + +%sysusers_create_inline() \ +[ -x @bindir@/systemd-sysusers ] && @bindir@/systemd-sysusers - </dev/null 2>&1 || : \ +%(cat %2) \ +SYSTEMD_INLINE_EOF \ +%{nil} + +# This may be used by package installation scripts to create files according to +# their tmpfiles configuration from a package installation script, even before +# the files of that package are installed on disk. +# +# Example: +# Source1: %{name}-tmpfiles.conf +# ... +# %install +# install -D %SOURCE1 %{buildroot}%{_tmpfilesdir}/%{name}.conf +# %pre +# %tmpfiles_create_package %{name} %SOURCE1 +# %files +# %{_tmpfilesdir}/%{name}.conf +%tmpfiles_create_package() \ +%{expand:%%{?!__systemd_twoargs_%#:%%{error:This macro requires two arguments}}} \ +systemd-tmpfiles --replace=%_tmpfilesdir/%1.conf --create - </dev/null 2>&1 || : \ +%(cat %2) \ +SYSTEMD_INLINE_EOF \ +%{nil} + +%sysctl_apply() \ +%{expand:%%{?__systemd_someargs_%#}} \ +[ -x @rootlibexecdir@/systemd-sysctl ] && @rootlibexecdir@/systemd-sysctl %{?*} || : \ +%{nil} + +%binfmt_apply() \ +%{expand:%%{?__systemd_someargs_%#}} \ +[ -x @rootlibexecdir@/systemd-binfmt ] && @rootlibexecdir@/systemd-binfmt %{?*} || : \ +%{nil} diff --git a/src/core/main.c b/src/core/main.c new file mode 100644 index 00000000..c24b696b --- /dev/null +++ b/src/core/main.c @@ -0,0 +1,2757 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#if HAVE_SECCOMP +#include +#endif +#if HAVE_VALGRIND_VALGRIND_H +#include +#endif + +#include "sd-bus.h" +#include "sd-daemon.h" +#include "sd-messages.h" + +#include "alloc-util.h" +#include "architecture.h" +#include "build.h" +#include "bus-error.h" +#include "bus-util.h" +#include "capability-util.h" +#include "cgroup-util.h" +#include "clock-util.h" +#include "conf-parser.h" +#include "cpu-set-util.h" +#include "dbus-manager.h" +#include "dbus.h" +#include "def.h" +#include "efi-random.h" +#include "emergency-action.h" +#include "env-util.h" +#include "exit-status.h" +#include "fd-util.h" +#include "fdset.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "hostname-setup.h" +#include "ima-setup.h" +#include "killall.h" +#include "kmod-setup.h" +#include "limits-util.h" +#include "load-fragment.h" +#include "log.h" +#include "loopback-setup.h" +#include "machine-id-setup.h" +#include "manager.h" +#include "mount-setup.h" +#include "os-util.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "raw-clone.h" +#include "rlimit-util.h" +#if HAVE_SECCOMP +#include "seccomp-util.h" +#endif +#include "selinux-setup.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "smack-setup.h" +#include "special.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "strv.h" +#include "switch-root.h" +#include "sysctl-util.h" +#include "terminal-util.h" +#include "umask-util.h" +#include "user-util.h" +#include "util.h" +#include "virt.h" +#include "watchdog.h" + +#if HAS_FEATURE_ADDRESS_SANITIZER +#include +#endif + +#define DEFAULT_TASKS_MAX ((TasksMax) { 15U, 100U }) /* 15% */ + +static enum { + ACTION_RUN, + ACTION_HELP, + ACTION_VERSION, + ACTION_TEST, + ACTION_DUMP_CONFIGURATION_ITEMS, + ACTION_DUMP_BUS_PROPERTIES, +} arg_action = ACTION_RUN; + +/* Those variables are initalized to 0 automatically, so we avoid uninitialized memory access. + * Real defaults are assigned in reset_arguments() below. */ +static char *arg_default_unit; +static bool arg_system; +static bool arg_dump_core; +static int arg_crash_chvt; +static bool arg_crash_shell; +static bool arg_crash_reboot; +static char *arg_confirm_spawn; +static ShowStatus arg_show_status; +static StatusUnitFormat arg_status_unit_format; +static bool arg_switched_root; +static PagerFlags arg_pager_flags; +static bool arg_service_watchdogs; +static ExecOutput arg_default_std_output; +static ExecOutput arg_default_std_error; +static usec_t arg_default_restart_usec; +static usec_t arg_default_timeout_start_usec; +static usec_t arg_default_timeout_stop_usec; +static usec_t arg_default_timeout_abort_usec; +static bool arg_default_timeout_abort_set; +static usec_t arg_default_start_limit_interval; +static unsigned arg_default_start_limit_burst; +static usec_t arg_runtime_watchdog; +static usec_t arg_reboot_watchdog; +static usec_t arg_kexec_watchdog; +static char *arg_early_core_pattern; +static char *arg_watchdog_device; +static char **arg_default_environment; +static struct rlimit *arg_default_rlimit[_RLIMIT_MAX]; +static uint64_t arg_capability_bounding_set; +static bool arg_no_new_privs; +static nsec_t arg_timer_slack_nsec; +static usec_t arg_default_timer_accuracy_usec; +static Set* arg_syscall_archs; +static FILE* arg_serialization; +static int arg_default_cpu_accounting; +static bool arg_default_io_accounting; +static bool arg_default_ip_accounting; +static bool arg_default_blockio_accounting; +static bool arg_default_memory_accounting; +static bool arg_default_tasks_accounting; +static TasksMax arg_default_tasks_max; +static sd_id128_t arg_machine_id; +static EmergencyAction arg_cad_burst_action; +static OOMPolicy arg_default_oom_policy; +static CPUSet arg_cpu_affinity; +static NUMAPolicy arg_numa_policy; + +/* A copy of the original environment block */ +static char **saved_env = NULL; + +static int parse_configuration(const struct rlimit *saved_rlimit_nofile, + const struct rlimit *saved_rlimit_memlock); + +_noreturn_ static void freeze_or_exit_or_reboot(void) { + + /* If we are running in a container, let's prefer exiting, after all we can propagate an exit code to + * the container manager, and thus inform it that something went wrong. */ + if (detect_container() > 0) { + log_emergency("Exiting PID 1..."); + _exit(EXIT_EXCEPTION); + } + + if (arg_crash_reboot) { + log_notice("Rebooting in 10s..."); + (void) sleep(10); + + log_notice("Rebooting now..."); + (void) reboot(RB_AUTOBOOT); + log_emergency_errno(errno, "Failed to reboot: %m"); + } + + log_emergency("Freezing execution."); + freeze(); +} + +_noreturn_ static void crash(int sig) { + struct sigaction sa; + pid_t pid; + + if (getpid_cached() != 1) + /* Pass this on immediately, if this is not PID 1 */ + (void) raise(sig); + else if (!arg_dump_core) + log_emergency("Caught <%s>, not dumping core.", signal_to_string(sig)); + else { + sa = (struct sigaction) { + .sa_handler = nop_signal_handler, + .sa_flags = SA_NOCLDSTOP|SA_RESTART, + }; + + /* We want to wait for the core process, hence let's enable SIGCHLD */ + (void) sigaction(SIGCHLD, &sa, NULL); + + pid = raw_clone(SIGCHLD); + if (pid < 0) + log_emergency_errno(errno, "Caught <%s>, cannot fork for core dump: %m", signal_to_string(sig)); + else if (pid == 0) { + /* Enable default signal handler for core dump */ + + sa = (struct sigaction) { + .sa_handler = SIG_DFL, + }; + (void) sigaction(sig, &sa, NULL); + + /* Don't limit the coredump size */ + (void) setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)); + + /* Just to be sure... */ + (void) chdir("/"); + + /* Raise the signal again */ + pid = raw_getpid(); + (void) kill(pid, sig); /* raise() would kill the parent */ + + assert_not_reached("We shouldn't be here..."); + _exit(EXIT_EXCEPTION); + } else { + siginfo_t status; + int r; + + /* Order things nicely. */ + r = wait_for_terminate(pid, &status); + if (r < 0) + log_emergency_errno(r, "Caught <%s>, waitpid() failed: %m", signal_to_string(sig)); + else if (status.si_code != CLD_DUMPED) { + const char *s = status.si_code == CLD_EXITED + ? exit_status_to_string(status.si_status, EXIT_STATUS_LIBC) + : signal_to_string(status.si_status); + + log_emergency("Caught <%s>, core dump failed (child "PID_FMT", code=%s, status=%i/%s).", + signal_to_string(sig), + pid, + sigchld_code_to_string(status.si_code), + status.si_status, strna(s)); + } else + log_emergency("Caught <%s>, dumped core as pid "PID_FMT".", + signal_to_string(sig), pid); + } + } + + if (arg_crash_chvt >= 0) + (void) chvt(arg_crash_chvt); + + sa = (struct sigaction) { + .sa_handler = SIG_IGN, + .sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART, + }; + + /* Let the kernel reap children for us */ + (void) sigaction(SIGCHLD, &sa, NULL); + + if (arg_crash_shell) { + log_notice("Executing crash shell in 10s..."); + (void) sleep(10); + + pid = raw_clone(SIGCHLD); + if (pid < 0) + log_emergency_errno(errno, "Failed to fork off crash shell: %m"); + else if (pid == 0) { + (void) setsid(); + (void) make_console_stdio(); + (void) rlimit_nofile_safe(); + (void) execle("/bin/sh", "/bin/sh", NULL, environ); + + log_emergency_errno(errno, "execle() failed: %m"); + _exit(EXIT_EXCEPTION); + } else { + log_info("Spawned crash shell as PID "PID_FMT".", pid); + (void) wait_for_terminate(pid, NULL); + } + } + + freeze_or_exit_or_reboot(); +} + +static void install_crash_handler(void) { + static const struct sigaction sa = { + .sa_handler = crash, + .sa_flags = SA_NODEFER, /* So that we can raise the signal again from the signal handler */ + }; + int r; + + /* We ignore the return value here, since, we don't mind if we + * cannot set up a crash handler */ + r = sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1); + if (r < 0) + log_debug_errno(r, "I had trouble setting up the crash handler, ignoring: %m"); +} + +static int console_setup(void) { + _cleanup_close_ int tty_fd = -1; + int r; + + tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); + if (tty_fd < 0) + return log_error_errno(tty_fd, "Failed to open /dev/console: %m"); + + /* We don't want to force text mode. plymouth may be showing + * pictures already from initrd. */ + r = reset_terminal_fd(tty_fd, false); + if (r < 0) + return log_error_errno(r, "Failed to reset /dev/console: %m"); + + return 0; +} + +static int set_machine_id(const char *m) { + sd_id128_t t; + assert(m); + + if (sd_id128_from_string(m, &t) < 0) + return -EINVAL; + + if (sd_id128_is_null(t)) + return -EINVAL; + + arg_machine_id = t; + return 0; +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + + int r; + + assert(key); + + if (STR_IN_SET(key, "systemd.unit", "rd.systemd.unit")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) + log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value); + else if (in_initrd() == !!startswith(key, "rd.")) { + if (free_and_strdup(&arg_default_unit, value) < 0) + return log_oom(); + } + + } else if (proc_cmdline_key_streq(key, "systemd.dump_core")) { + + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning_errno(r, "Failed to parse dump core switch %s, ignoring: %m", value); + else + arg_dump_core = r; + + } else if (proc_cmdline_key_streq(key, "systemd.early_core_pattern")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (path_is_absolute(value)) + (void) parse_path_argument_and_warn(value, false, &arg_early_core_pattern); + else + log_warning("Specified core pattern '%s' is not an absolute path, ignoring.", value); + + } else if (proc_cmdline_key_streq(key, "systemd.crash_chvt")) { + + if (!value) + arg_crash_chvt = 0; /* turn on */ + else { + r = parse_crash_chvt(value, &arg_crash_chvt); + if (r < 0) + log_warning_errno(r, "Failed to parse crash chvt switch %s, ignoring: %m", value); + } + + } else if (proc_cmdline_key_streq(key, "systemd.crash_shell")) { + + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning_errno(r, "Failed to parse crash shell switch %s, ignoring: %m", value); + else + arg_crash_shell = r; + + } else if (proc_cmdline_key_streq(key, "systemd.crash_reboot")) { + + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning_errno(r, "Failed to parse crash reboot switch %s, ignoring: %m", value); + else + arg_crash_reboot = r; + + } else if (proc_cmdline_key_streq(key, "systemd.confirm_spawn")) { + char *s; + + r = parse_confirm_spawn(value, &s); + if (r < 0) + log_warning_errno(r, "Failed to parse confirm_spawn switch %s, ignoring: %m", value); + else + free_and_replace(arg_confirm_spawn, s); + + } else if (proc_cmdline_key_streq(key, "systemd.service_watchdogs")) { + + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning_errno(r, "Failed to parse service watchdog switch %s, ignoring: %m", value); + else + arg_service_watchdogs = r; + + } else if (proc_cmdline_key_streq(key, "systemd.show_status")) { + + if (value) { + r = parse_show_status(value, &arg_show_status); + if (r < 0) + log_warning_errno(r, "Failed to parse show status switch %s, ignoring: %m", value); + } else + arg_show_status = SHOW_STATUS_YES; + + } else if (proc_cmdline_key_streq(key, "systemd.status_unit_format")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = status_unit_format_from_string(value); + if (r < 0) + log_warning_errno(r, "Failed to parse %s=%s, ignoring: %m", key, value); + else + arg_status_unit_format = r; + + } else if (proc_cmdline_key_streq(key, "systemd.default_standard_output")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = exec_output_from_string(value); + if (r < 0) + log_warning_errno(r, "Failed to parse default standard output switch %s, ignoring: %m", value); + else + arg_default_std_output = r; + + } else if (proc_cmdline_key_streq(key, "systemd.default_standard_error")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = exec_output_from_string(value); + if (r < 0) + log_warning_errno(r, "Failed to parse default standard error switch %s, ignoring: %m", value); + else + arg_default_std_error = r; + + } else if (streq(key, "systemd.setenv")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (env_assignment_is_valid(value)) { + char **env; + + env = strv_env_set(arg_default_environment, value); + if (!env) + return log_oom(); + + arg_default_environment = env; + } else + log_warning("Environment variable name '%s' is not valid. Ignoring.", value); + + } else if (proc_cmdline_key_streq(key, "systemd.machine_id")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = set_machine_id(value); + if (r < 0) + log_warning_errno(r, "MachineID '%s' is not valid, ignoring: %m", value); + + } else if (proc_cmdline_key_streq(key, "systemd.default_timeout_start_sec")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = parse_sec(value, &arg_default_timeout_start_usec); + if (r < 0) + log_warning_errno(r, "Failed to parse default start timeout '%s', ignoring: %m", value); + + if (arg_default_timeout_start_usec <= 0) + arg_default_timeout_start_usec = USEC_INFINITY; + + } else if (proc_cmdline_key_streq(key, "systemd.watchdog_device")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + (void) parse_path_argument_and_warn(value, false, &arg_watchdog_device); + + } else if (streq(key, "quiet") && !value) { + + if (arg_show_status == _SHOW_STATUS_INVALID) + arg_show_status = SHOW_STATUS_AUTO; + + } else if (streq(key, "debug") && !value) { + + /* Note that log_parse_environment() handles 'debug' + * too, and sets the log level to LOG_DEBUG. */ + + if (detect_container() > 0) + log_set_target(LOG_TARGET_CONSOLE); + + } else if (!value) { + const char *target; + + /* SysV compatibility */ + target = runlevel_to_target(key); + if (target) + return free_and_strdup(&arg_default_unit, target); + } + + return 0; +} + +#define DEFINE_SETTER(name, func, descr) \ + static int name(const char *unit, \ + const char *filename, \ + unsigned line, \ + const char *section, \ + unsigned section_line, \ + const char *lvalue, \ + int ltype, \ + const char *rvalue, \ + void *data, \ + void *userdata) { \ + \ + int r; \ + \ + assert(filename); \ + assert(lvalue); \ + assert(rvalue); \ + \ + r = func(rvalue); \ + if (r < 0) \ + log_syntax(unit, LOG_ERR, filename, line, r, \ + "Invalid " descr "'%s': %m", \ + rvalue); \ + \ + return 0; \ + } + +DEFINE_SETTER(config_parse_level2, log_set_max_level_from_string, "log level"); +DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target"); +DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" ); +DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location"); + +static int config_parse_default_timeout_abort( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + int r; + + r = config_parse_timeout_abort(unit, filename, line, section, section_line, lvalue, ltype, rvalue, + &arg_default_timeout_abort_usec, userdata); + if (r >= 0) + arg_default_timeout_abort_set = r; + return 0; +} + +static int parse_config_file(void) { + const ConfigTableItem items[] = { + { "Manager", "LogLevel", config_parse_level2, 0, NULL }, + { "Manager", "LogTarget", config_parse_target, 0, NULL }, + { "Manager", "LogColor", config_parse_color, 0, NULL }, + { "Manager", "LogLocation", config_parse_location, 0, NULL }, + { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core }, + { "Manager", "CrashChVT", /* legacy */ config_parse_crash_chvt, 0, &arg_crash_chvt }, + { "Manager", "CrashChangeVT", config_parse_crash_chvt, 0, &arg_crash_chvt }, + { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell }, + { "Manager", "CrashReboot", config_parse_bool, 0, &arg_crash_reboot }, + { "Manager", "ShowStatus", config_parse_show_status, 0, &arg_show_status }, + { "Manager", "StatusUnitFormat", config_parse_status_unit_format, 0, &arg_status_unit_format }, + { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, &arg_cpu_affinity }, + { "Manager", "NUMAPolicy", config_parse_numa_policy, 0, &arg_numa_policy.type }, + { "Manager", "NUMAMask", config_parse_numa_mask, 0, &arg_numa_policy }, + { "Manager", "JoinControllers", config_parse_warn_compat, DISABLED_CONFIGURATION, NULL }, + { "Manager", "RuntimeWatchdogSec", config_parse_sec, 0, &arg_runtime_watchdog }, + { "Manager", "RebootWatchdogSec", config_parse_sec, 0, &arg_reboot_watchdog }, + { "Manager", "ShutdownWatchdogSec", config_parse_sec, 0, &arg_reboot_watchdog }, /* obsolete alias */ + { "Manager", "KExecWatchdogSec", config_parse_sec, 0, &arg_kexec_watchdog }, + { "Manager", "WatchdogDevice", config_parse_path, 0, &arg_watchdog_device }, + { "Manager", "CapabilityBoundingSet", config_parse_capability_set, 0, &arg_capability_bounding_set }, + { "Manager", "NoNewPrivileges", config_parse_bool, 0, &arg_no_new_privs }, +#if HAVE_SECCOMP + { "Manager", "SystemCallArchitectures", config_parse_syscall_archs, 0, &arg_syscall_archs }, +#endif + { "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec }, + { "Manager", "DefaultTimerAccuracySec", config_parse_sec, 0, &arg_default_timer_accuracy_usec }, + { "Manager", "DefaultStandardOutput", config_parse_output_restricted, 0, &arg_default_std_output }, + { "Manager", "DefaultStandardError", config_parse_output_restricted, 0, &arg_default_std_error }, + { "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec }, + { "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec }, + { "Manager", "DefaultTimeoutAbortSec", config_parse_default_timeout_abort, 0, NULL }, + { "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec }, + { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, /* obsolete alias */ + { "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_default_start_limit_interval }, + { "Manager", "DefaultStartLimitBurst", config_parse_unsigned, 0, &arg_default_start_limit_burst }, + { "Manager", "DefaultEnvironment", config_parse_environ, 0, &arg_default_environment }, + { "Manager", "DefaultLimitCPU", config_parse_rlimit, RLIMIT_CPU, arg_default_rlimit }, + { "Manager", "DefaultLimitFSIZE", config_parse_rlimit, RLIMIT_FSIZE, arg_default_rlimit }, + { "Manager", "DefaultLimitDATA", config_parse_rlimit, RLIMIT_DATA, arg_default_rlimit }, + { "Manager", "DefaultLimitSTACK", config_parse_rlimit, RLIMIT_STACK, arg_default_rlimit }, + { "Manager", "DefaultLimitCORE", config_parse_rlimit, RLIMIT_CORE, arg_default_rlimit }, + { "Manager", "DefaultLimitRSS", config_parse_rlimit, RLIMIT_RSS, arg_default_rlimit }, + { "Manager", "DefaultLimitNOFILE", config_parse_rlimit, RLIMIT_NOFILE, arg_default_rlimit }, + { "Manager", "DefaultLimitAS", config_parse_rlimit, RLIMIT_AS, arg_default_rlimit }, + { "Manager", "DefaultLimitNPROC", config_parse_rlimit, RLIMIT_NPROC, arg_default_rlimit }, + { "Manager", "DefaultLimitMEMLOCK", config_parse_rlimit, RLIMIT_MEMLOCK, arg_default_rlimit }, + { "Manager", "DefaultLimitLOCKS", config_parse_rlimit, RLIMIT_LOCKS, arg_default_rlimit }, + { "Manager", "DefaultLimitSIGPENDING", config_parse_rlimit, RLIMIT_SIGPENDING, arg_default_rlimit }, + { "Manager", "DefaultLimitMSGQUEUE", config_parse_rlimit, RLIMIT_MSGQUEUE, arg_default_rlimit }, + { "Manager", "DefaultLimitNICE", config_parse_rlimit, RLIMIT_NICE, arg_default_rlimit }, + { "Manager", "DefaultLimitRTPRIO", config_parse_rlimit, RLIMIT_RTPRIO, arg_default_rlimit }, + { "Manager", "DefaultLimitRTTIME", config_parse_rlimit, RLIMIT_RTTIME, arg_default_rlimit }, + { "Manager", "DefaultCPUAccounting", config_parse_tristate, 0, &arg_default_cpu_accounting }, + { "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_default_io_accounting }, + { "Manager", "DefaultIPAccounting", config_parse_bool, 0, &arg_default_ip_accounting }, + { "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting }, + { "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting }, + { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting }, + { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max }, + { "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, 0, &arg_cad_burst_action }, + { "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_default_oom_policy }, + {} + }; + + const char *fn, *conf_dirs_nulstr; + + fn = arg_system ? + PKGSYSCONFDIR "/system.conf" : + PKGSYSCONFDIR "/user.conf"; + + conf_dirs_nulstr = arg_system ? + CONF_PATHS_NULSTR("systemd/system.conf.d") : + CONF_PATHS_NULSTR("systemd/user.conf.d"); + + (void) config_parse_many_nulstr(fn, conf_dirs_nulstr, "Manager\0", config_item_table_lookup, items, CONFIG_PARSE_WARN, NULL); + + /* Traditionally "0" was used to turn off the default unit timeouts. Fix this up so that we used USEC_INFINITY + * like everywhere else. */ + if (arg_default_timeout_start_usec <= 0) + arg_default_timeout_start_usec = USEC_INFINITY; + if (arg_default_timeout_stop_usec <= 0) + arg_default_timeout_stop_usec = USEC_INFINITY; + + return 0; +} + +static void set_manager_defaults(Manager *m) { + + assert(m); + + /* Propagates the various default unit property settings into the manager object, i.e. properties that do not + * affect the manager itself, but are just what newly allocated units will have set if they haven't set + * anything else. (Also see set_manager_settings() for the settings that affect the manager's own behaviour) */ + + m->default_timer_accuracy_usec = arg_default_timer_accuracy_usec; + m->default_std_output = arg_default_std_output; + m->default_std_error = arg_default_std_error; + m->default_timeout_start_usec = arg_default_timeout_start_usec; + m->default_timeout_stop_usec = arg_default_timeout_stop_usec; + m->default_timeout_abort_usec = arg_default_timeout_abort_usec; + m->default_timeout_abort_set = arg_default_timeout_abort_set; + m->default_restart_usec = arg_default_restart_usec; + m->default_start_limit_interval = arg_default_start_limit_interval; + m->default_start_limit_burst = arg_default_start_limit_burst; + + /* On 4.15+ with unified hierarchy, CPU accounting is essentially free as it doesn't require the CPU + * controller to be enabled, so the default is to enable it unless we got told otherwise. */ + if (arg_default_cpu_accounting >= 0) + m->default_cpu_accounting = arg_default_cpu_accounting; + else + m->default_cpu_accounting = cpu_accounting_is_cheap(); + + m->default_io_accounting = arg_default_io_accounting; + m->default_ip_accounting = arg_default_ip_accounting; + m->default_blockio_accounting = arg_default_blockio_accounting; + m->default_memory_accounting = arg_default_memory_accounting; + m->default_tasks_accounting = arg_default_tasks_accounting; + m->default_tasks_max = arg_default_tasks_max; + m->default_oom_policy = arg_default_oom_policy; + + (void) manager_set_default_rlimits(m, arg_default_rlimit); + + (void) manager_default_environment(m); + (void) manager_transient_environment_add(m, arg_default_environment); +} + +static void set_manager_settings(Manager *m) { + + assert(m); + + /* Propagates the various manager settings into the manager object, i.e. properties that effect the manager + * itself (as opposed to just being inherited into newly allocated units, see set_manager_defaults() above). */ + + m->confirm_spawn = arg_confirm_spawn; + m->service_watchdogs = arg_service_watchdogs; + m->runtime_watchdog = arg_runtime_watchdog; + m->reboot_watchdog = arg_reboot_watchdog; + m->kexec_watchdog = arg_kexec_watchdog; + m->cad_burst_action = arg_cad_burst_action; + + manager_set_show_status(m, arg_show_status); + m->status_unit_format = arg_status_unit_format; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_LOG_LEVEL = 0x100, + ARG_LOG_TARGET, + ARG_LOG_COLOR, + ARG_LOG_LOCATION, + ARG_UNIT, + ARG_SYSTEM, + ARG_USER, + ARG_TEST, + ARG_NO_PAGER, + ARG_VERSION, + ARG_DUMP_CONFIGURATION_ITEMS, + ARG_DUMP_BUS_PROPERTIES, + ARG_DUMP_CORE, + ARG_CRASH_CHVT, + ARG_CRASH_SHELL, + ARG_CRASH_REBOOT, + ARG_CONFIRM_SPAWN, + ARG_SHOW_STATUS, + ARG_DESERIALIZE, + ARG_SWITCHED_ROOT, + ARG_DEFAULT_STD_OUTPUT, + ARG_DEFAULT_STD_ERROR, + ARG_MACHINE_ID, + ARG_SERVICE_WATCHDOGS, + }; + + static const struct option options[] = { + { "log-level", required_argument, NULL, ARG_LOG_LEVEL }, + { "log-target", required_argument, NULL, ARG_LOG_TARGET }, + { "log-color", optional_argument, NULL, ARG_LOG_COLOR }, + { "log-location", optional_argument, NULL, ARG_LOG_LOCATION }, + { "unit", required_argument, NULL, ARG_UNIT }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "user", no_argument, NULL, ARG_USER }, + { "test", no_argument, NULL, ARG_TEST }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS }, + { "dump-bus-properties", no_argument, NULL, ARG_DUMP_BUS_PROPERTIES }, + { "dump-core", optional_argument, NULL, ARG_DUMP_CORE }, + { "crash-chvt", required_argument, NULL, ARG_CRASH_CHVT }, + { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL }, + { "crash-reboot", optional_argument, NULL, ARG_CRASH_REBOOT }, + { "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN }, + { "show-status", optional_argument, NULL, ARG_SHOW_STATUS }, + { "deserialize", required_argument, NULL, ARG_DESERIALIZE }, + { "switched-root", no_argument, NULL, ARG_SWITCHED_ROOT }, + { "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, }, + { "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, }, + { "machine-id", required_argument, NULL, ARG_MACHINE_ID }, + { "service-watchdogs", required_argument, NULL, ARG_SERVICE_WATCHDOGS }, + {} + }; + + int c, r; + + assert(argc >= 1); + assert(argv); + + if (getpid_cached() == 1) + opterr = 0; + + while ((c = getopt_long(argc, argv, "hDbsz:", options, NULL)) >= 0) + + switch (c) { + + case ARG_LOG_LEVEL: + r = log_set_max_level_from_string(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse log level \"%s\": %m", optarg); + + break; + + case ARG_LOG_TARGET: + r = log_set_target_from_string(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse log target \"%s\": %m", optarg); + + break; + + case ARG_LOG_COLOR: + + if (optarg) { + r = log_show_color_from_string(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse log color setting \"%s\": %m", + optarg); + } else + log_show_color(true); + + break; + + case ARG_LOG_LOCATION: + if (optarg) { + r = log_show_location_from_string(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse log location setting \"%s\": %m", + optarg); + } else + log_show_location(true); + + break; + + case ARG_DEFAULT_STD_OUTPUT: + r = exec_output_from_string(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse default standard output setting \"%s\": %m", + optarg); + arg_default_std_output = r; + break; + + case ARG_DEFAULT_STD_ERROR: + r = exec_output_from_string(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse default standard error output setting \"%s\": %m", + optarg); + arg_default_std_error = r; + break; + + case ARG_UNIT: + r = free_and_strdup(&arg_default_unit, optarg); + if (r < 0) + return log_error_errno(r, "Failed to set default unit \"%s\": %m", optarg); + + break; + + case ARG_SYSTEM: + arg_system = true; + break; + + case ARG_USER: + arg_system = false; + break; + + case ARG_TEST: + arg_action = ACTION_TEST; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_VERSION: + arg_action = ACTION_VERSION; + break; + + case ARG_DUMP_CONFIGURATION_ITEMS: + arg_action = ACTION_DUMP_CONFIGURATION_ITEMS; + break; + + case ARG_DUMP_BUS_PROPERTIES: + arg_action = ACTION_DUMP_BUS_PROPERTIES; + break; + + case ARG_DUMP_CORE: + if (!optarg) + arg_dump_core = true; + else { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse dump core boolean: \"%s\": %m", + optarg); + arg_dump_core = r; + } + break; + + case ARG_CRASH_CHVT: + r = parse_crash_chvt(optarg, &arg_crash_chvt); + if (r < 0) + return log_error_errno(r, "Failed to parse crash virtual terminal index: \"%s\": %m", + optarg); + break; + + case ARG_CRASH_SHELL: + if (!optarg) + arg_crash_shell = true; + else { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse crash shell boolean: \"%s\": %m", + optarg); + arg_crash_shell = r; + } + break; + + case ARG_CRASH_REBOOT: + if (!optarg) + arg_crash_reboot = true; + else { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse crash shell boolean: \"%s\": %m", + optarg); + arg_crash_reboot = r; + } + break; + + case ARG_CONFIRM_SPAWN: + arg_confirm_spawn = mfree(arg_confirm_spawn); + + r = parse_confirm_spawn(optarg, &arg_confirm_spawn); + if (r < 0) + return log_error_errno(r, "Failed to parse confirm spawn option: \"%s\": %m", + optarg); + break; + + case ARG_SERVICE_WATCHDOGS: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse service watchdogs boolean: \"%s\": %m", + optarg); + arg_service_watchdogs = r; + break; + + case ARG_SHOW_STATUS: + if (optarg) { + r = parse_show_status(optarg, &arg_show_status); + if (r < 0) + return log_error_errno(r, "Failed to parse show status boolean: \"%s\": %m", + optarg); + } else + arg_show_status = SHOW_STATUS_YES; + break; + + case ARG_DESERIALIZE: { + int fd; + FILE *f; + + r = safe_atoi(optarg, &fd); + if (r < 0) + log_error_errno(r, "Failed to parse deserialize option \"%s\": %m", optarg); + if (fd < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid deserialize fd: %d", + fd); + + (void) fd_cloexec(fd, true); + + f = fdopen(fd, "r"); + if (!f) + return log_error_errno(errno, "Failed to open serialization fd %d: %m", fd); + + safe_fclose(arg_serialization); + arg_serialization = f; + + break; + } + + case ARG_SWITCHED_ROOT: + arg_switched_root = true; + break; + + case ARG_MACHINE_ID: + r = set_machine_id(optarg); + if (r < 0) + return log_error_errno(r, "MachineID '%s' is not valid: %m", optarg); + break; + + case 'h': + arg_action = ACTION_HELP; + break; + + case 'D': + log_set_max_level(LOG_DEBUG); + break; + + case 'b': + case 's': + case 'z': + /* Just to eat away the sysvinit kernel + * cmdline args without getopt() error + * messages that we'll parse in + * parse_proc_cmdline_word() or ignore. */ + + case '?': + if (getpid_cached() != 1) + return -EINVAL; + else + return 0; + + default: + assert_not_reached("Unhandled option code."); + } + + if (optind < argc && getpid_cached() != 1) { + /* Hmm, when we aren't run as init system + * let's complain about excess arguments */ + + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Excess arguments."); + } + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n\n" + "Starts up and maintains the system or user services.\n\n" + " -h --help Show this help\n" + " --version Show version\n" + " --test Determine initial transaction, dump it and exit\n" + " --system In combination with --test: operate as system service manager\n" + " --user In combination with --test: operate as per-user service manager\n" + " --no-pager Do not pipe output into a pager\n" + " --dump-configuration-items Dump understood unit configuration items\n" + " --dump-bus-properties Dump exposed bus properties\n" + " --unit=UNIT Set default unit\n" + " --dump-core[=BOOL] Dump core on crash\n" + " --crash-vt=NR Change to specified VT on crash\n" + " --crash-reboot[=BOOL] Reboot on crash\n" + " --crash-shell[=BOOL] Run shell on crash\n" + " --confirm-spawn[=BOOL] Ask for confirmation when spawning processes\n" + " --show-status[=BOOL] Show status updates on the console during bootup\n" + " --log-target=TARGET Set log target (console, journal, kmsg, journal-or-kmsg, null)\n" + " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n" + " --log-color[=BOOL] Highlight important log messages\n" + " --log-location[=BOOL] Include code location in log messages\n" + " --default-standard-output= Set default standard output for services\n" + " --default-standard-error= Set default standard error output for services\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int prepare_reexecute( + Manager *m, + FILE **ret_f, + FDSet **ret_fds, + bool switching_root) { + + _cleanup_fdset_free_ FDSet *fds = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(m); + assert(ret_f); + assert(ret_fds); + + r = manager_open_serialization(m, &f); + if (r < 0) + return log_error_errno(r, "Failed to create serialization file: %m"); + + /* Make sure nothing is really destructed when we shut down */ + m->n_reloading++; + bus_manager_send_reloading(m, true); + + fds = fdset_new(); + if (!fds) + return log_oom(); + + r = manager_serialize(m, f, fds, switching_root); + if (r < 0) + return r; + + if (fseeko(f, 0, SEEK_SET) == (off_t) -1) + return log_error_errno(errno, "Failed to rewind serialization fd: %m"); + + r = fd_cloexec(fileno(f), false); + if (r < 0) + return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization: %m"); + + r = fdset_cloexec(fds, false); + if (r < 0) + return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m"); + + *ret_f = TAKE_PTR(f); + *ret_fds = TAKE_PTR(fds); + + return 0; +} + +static void bump_file_max_and_nr_open(void) { + + /* Let's bump fs.file-max and fs.nr_open to their respective maximums. On current kernels large numbers of file + * descriptors are no longer a performance problem and their memory is properly tracked by memcg, thus counting + * them and limiting them in another two layers of limits is unnecessary and just complicates things. This + * function hence turns off 2 of the 4 levels of limits on file descriptors, and makes RLIMIT_NOLIMIT (soft + + * hard) the only ones that really matter. */ + +#if BUMP_PROC_SYS_FS_FILE_MAX || BUMP_PROC_SYS_FS_NR_OPEN + int r; +#endif + +#if BUMP_PROC_SYS_FS_FILE_MAX + /* The maximum the kernel allows for this since 5.2 is LONG_MAX, use that. (Previously thing where + * different but the operation would fail silently.) */ + r = sysctl_writef("fs/file-max", "%li\n", LONG_MAX); + if (r < 0) + log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to bump fs.file-max, ignoring: %m"); +#endif + +#if BUMP_PROC_SYS_FS_NR_OPEN + int v = INT_MAX; + + /* Arg! The kernel enforces maximum and minimum values on the fs.nr_open, but we don't really know what they + * are. The expression by which the maximum is determined is dependent on the architecture, and is something we + * don't really want to copy to userspace, as it is dependent on implementation details of the kernel. Since + * the kernel doesn't expose the maximum value to us, we can only try and hope. Hence, let's start with + * INT_MAX, and then keep halving the value until we find one that works. Ugly? Yes, absolutely, but kernel + * APIs are kernel APIs, so what do can we do... 🤯 */ + + for (;;) { + int k; + + v &= ~(__SIZEOF_POINTER__ - 1); /* Round down to next multiple of the pointer size */ + if (v < 1024) { + log_warning("Can't bump fs.nr_open, value too small."); + break; + } + + k = read_nr_open(); + if (k < 0) { + log_error_errno(k, "Failed to read fs.nr_open: %m"); + break; + } + if (k >= v) { /* Already larger */ + log_debug("Skipping bump, value is already larger."); + break; + } + + r = sysctl_writef("fs/nr_open", "%i\n", v); + if (r == -EINVAL) { + log_debug("Couldn't write fs.nr_open as %i, halving it.", v); + v /= 2; + continue; + } + if (r < 0) { + log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, "Failed to bump fs.nr_open, ignoring: %m"); + break; + } + + log_debug("Successfully bumped fs.nr_open to %i", v); + break; + } +#endif +} + +static int bump_rlimit_nofile(struct rlimit *saved_rlimit) { + struct rlimit new_rlimit; + int r, nr; + + /* Get the underlying absolute limit the kernel enforces */ + nr = read_nr_open(); + + /* Calculate the new limits to use for us. Never lower from what we inherited. */ + new_rlimit = (struct rlimit) { + .rlim_cur = MAX((rlim_t) nr, saved_rlimit->rlim_cur), + .rlim_max = MAX((rlim_t) nr, saved_rlimit->rlim_max), + }; + + /* Shortcut if nothing changes. */ + if (saved_rlimit->rlim_max >= new_rlimit.rlim_max && + saved_rlimit->rlim_cur >= new_rlimit.rlim_cur) { + log_debug("RLIMIT_NOFILE is already as high or higher than we need it, not bumping."); + return 0; + } + + /* Bump up the resource limit for ourselves substantially, all the way to the maximum the kernel allows, for + * both hard and soft. */ + r = setrlimit_closest(RLIMIT_NOFILE, &new_rlimit); + if (r < 0) + return log_warning_errno(r, "Setting RLIMIT_NOFILE failed, ignoring: %m"); + + return 0; +} + +static int bump_rlimit_memlock(struct rlimit *saved_rlimit) { + struct rlimit new_rlimit; + int r; + + /* BPF_MAP_TYPE_LPM_TRIE bpf maps are charged against RLIMIT_MEMLOCK, even if we have CAP_IPC_LOCK which should + * normally disable such checks. We need them to implement IPAccessAllow= and IPAccessDeny=, hence let's bump + * the value high enough for our user. */ + + /* Using MAX() on resource limits only is safe if RLIM_INFINITY is > 0. POSIX declares that rlim_t + * must be unsigned, hence this is a given, but let's make this clear here. */ + assert_cc(RLIM_INFINITY > 0); + + new_rlimit = (struct rlimit) { + .rlim_cur = MAX(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_cur), + .rlim_max = MAX(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_max), + }; + + if (saved_rlimit->rlim_max >= new_rlimit.rlim_cur && + saved_rlimit->rlim_cur >= new_rlimit.rlim_max) { + log_debug("RLIMIT_MEMLOCK is already as high or higher than we need it, not bumping."); + return 0; + } + + r = setrlimit_closest(RLIMIT_MEMLOCK, &new_rlimit); + if (r < 0) + return log_warning_errno(r, "Setting RLIMIT_MEMLOCK failed, ignoring: %m"); + + return 0; +} + +static void test_usr(void) { + + /* Check that /usr is either on the same file system as / or mounted already. */ + + if (dir_is_empty("/usr") <= 0) + return; + + log_warning("/usr appears to be on its own filesystem and is not already mounted. This is not a supported setup. " + "Some things will probably break (sometimes even silently) in mysterious ways. " + "Consult http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken for more information."); +} + +static int enforce_syscall_archs(Set *archs) { +#if HAVE_SECCOMP + int r; + + if (!is_seccomp_available()) + return 0; + + r = seccomp_restrict_archs(arg_syscall_archs); + if (r < 0) + return log_error_errno(r, "Failed to enforce system call architecture restrication: %m"); +#endif + return 0; +} + +static int status_welcome(void) { + _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL; + int r; + + if (IN_SET(arg_show_status, SHOW_STATUS_NO, SHOW_STATUS_AUTO)) + return 0; + + r = parse_os_release(NULL, + "PRETTY_NAME", &pretty_name, + "ANSI_COLOR", &ansi_color, + NULL); + if (r < 0) + log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, + "Failed to read os-release file, ignoring: %m"); + + if (log_get_show_color()) + return status_printf(NULL, 0, + "\nWelcome to \x1B[%sm%s\x1B[0m!\n", + isempty(ansi_color) ? "1" : ansi_color, + isempty(pretty_name) ? "Linux" : pretty_name); + else + return status_printf(NULL, 0, + "\nWelcome to %s!\n", + isempty(pretty_name) ? "Linux" : pretty_name); +} + +static int write_container_id(void) { + const char *c; + int r; + + c = getenv("container"); + if (isempty(c)) + return 0; + + RUN_WITH_UMASK(0022) + r = write_string_file("/run/systemd/container", c, WRITE_STRING_FILE_CREATE); + if (r < 0) + return log_warning_errno(r, "Failed to write /run/systemd/container, ignoring: %m"); + + return 1; +} + +static int bump_unix_max_dgram_qlen(void) { + _cleanup_free_ char *qlen = NULL; + unsigned long v; + int r; + + /* Let's bump the net.unix.max_dgram_qlen sysctl. The kernel default of 16 is simply too low. We set the value + * really really early during boot, so that it is actually applied to all our sockets, including the + * $NOTIFY_SOCKET one. */ + + r = read_one_line_file("/proc/sys/net/unix/max_dgram_qlen", &qlen); + if (r < 0) + return log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, "Failed to read AF_UNIX datagram queue length, ignoring: %m"); + + r = safe_atolu(qlen, &v); + if (r < 0) + return log_warning_errno(r, "Failed to parse AF_UNIX datagram queue length '%s', ignoring: %m", qlen); + + if (v >= DEFAULT_UNIX_MAX_DGRAM_QLEN) + return 0; + + r = write_string_filef("/proc/sys/net/unix/max_dgram_qlen", WRITE_STRING_FILE_DISABLE_BUFFER, "%lu", DEFAULT_UNIX_MAX_DGRAM_QLEN); + if (r < 0) + return log_full_errno(IN_SET(r, -EROFS, -EPERM, -EACCES) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to bump AF_UNIX datagram queue length, ignoring: %m"); + + return 1; +} + +static int fixup_environment(void) { + _cleanup_free_ char *term = NULL; + const char *t; + int r; + + /* Only fix up the environment when we are started as PID 1 */ + if (getpid_cached() != 1) + return 0; + + /* We expect the environment to be set correctly if run inside a container. */ + if (detect_container() > 0) + return 0; + + /* When started as PID1, the kernel uses /dev/console for our stdios and uses TERM=linux whatever the backend + * device used by the console. We try to make a better guess here since some consoles might not have support + * for color mode for example. + * + * However if TERM was configured through the kernel command line then leave it alone. */ + r = proc_cmdline_get_key("TERM", 0, &term); + if (r < 0) + return r; + + t = term ?: default_term_for_tty("/dev/console"); + + if (setenv("TERM", t, 1) < 0) + return -errno; + + /* The kernels sets HOME=/ for init. Let's undo this. */ + if (path_equal_ptr(getenv("HOME"), "/") && + unsetenv("HOME") < 0) + log_warning_errno(errno, "Failed to unset $HOME: %m"); + + return 0; +} + +static void redirect_telinit(int argc, char *argv[]) { + + /* This is compatibility support for SysV, where calling init as a user is identical to telinit. */ + +#if HAVE_SYSV_COMPAT + if (getpid_cached() == 1) + return; + + if (!strstr(program_invocation_short_name, "init")) + return; + + execv(SYSTEMCTL_BINARY_PATH, argv); + log_error_errno(errno, "Failed to exec " SYSTEMCTL_BINARY_PATH ": %m"); + exit(EXIT_FAILURE); +#endif +} + +static int become_shutdown( + const char *shutdown_verb, + int retval) { + + char log_level[DECIMAL_STR_MAX(int) + 1], + exit_code[DECIMAL_STR_MAX(uint8_t) + 1], + timeout[DECIMAL_STR_MAX(usec_t) + 1]; + + const char* command_line[13] = { + SYSTEMD_SHUTDOWN_BINARY_PATH, + shutdown_verb, + "--timeout", timeout, + "--log-level", log_level, + "--log-target", + }; + + _cleanup_strv_free_ char **env_block = NULL; + size_t pos = 7; + int r; + usec_t watchdog_timer = 0; + + assert(shutdown_verb); + assert(!command_line[pos]); + env_block = strv_copy(environ); + + xsprintf(log_level, "%d", log_get_max_level()); + xsprintf(timeout, "%" PRI_USEC "us", arg_default_timeout_stop_usec); + + switch (log_get_target()) { + + case LOG_TARGET_KMSG: + case LOG_TARGET_JOURNAL_OR_KMSG: + case LOG_TARGET_SYSLOG_OR_KMSG: + command_line[pos++] = "kmsg"; + break; + + case LOG_TARGET_NULL: + command_line[pos++] = "null"; + break; + + case LOG_TARGET_CONSOLE: + default: + command_line[pos++] = "console"; + break; + }; + + if (log_get_show_color()) + command_line[pos++] = "--log-color"; + + if (log_get_show_location()) + command_line[pos++] = "--log-location"; + + if (streq(shutdown_verb, "exit")) { + command_line[pos++] = "--exit-code"; + command_line[pos++] = exit_code; + xsprintf(exit_code, "%d", retval); + } + + assert(pos < ELEMENTSOF(command_line)); + + if (streq(shutdown_verb, "reboot")) + watchdog_timer = arg_reboot_watchdog; + else if (streq(shutdown_verb, "kexec")) + watchdog_timer = arg_kexec_watchdog; + + if (watchdog_timer > 0 && watchdog_timer != USEC_INFINITY) { + + char *e; + + /* If we reboot or kexec let's set the shutdown + * watchdog and tell the shutdown binary to + * repeatedly ping it */ + r = watchdog_set_timeout(&watchdog_timer); + watchdog_close(r < 0); + + /* Tell the binary how often to ping, ignore failure */ + if (asprintf(&e, "WATCHDOG_USEC="USEC_FMT, watchdog_timer) > 0) + (void) strv_consume(&env_block, e); + + if (arg_watchdog_device && + asprintf(&e, "WATCHDOG_DEVICE=%s", arg_watchdog_device) > 0) + (void) strv_consume(&env_block, e); + } else + watchdog_close(true); + + /* Avoid the creation of new processes forked by the + * kernel; at this point, we will not listen to the + * signals anyway */ + if (detect_container() <= 0) + (void) cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER); + + execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block); + return -errno; +} + +static void initialize_clock(void) { + int r; + + if (clock_is_localtime(NULL) > 0) { + int min; + + /* + * The very first call of settimeofday() also does a time warp in the kernel. + * + * In the rtc-in-local time mode, we set the kernel's timezone, and rely on external tools to take care + * of maintaining the RTC and do all adjustments. This matches the behavior of Windows, which leaves + * the RTC alone if the registry tells that the RTC runs in UTC. + */ + r = clock_set_timezone(&min); + if (r < 0) + log_error_errno(r, "Failed to apply local time delta, ignoring: %m"); + else + log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min); + + } else if (!in_initrd()) { + /* + * Do a dummy very first call to seal the kernel's time warp magic. + * + * Do not call this from inside the initrd. The initrd might not carry /etc/adjtime with LOCAL, but the + * real system could be set up that way. In such case, we need to delay the time-warp or the sealing + * until we reach the real system. + * + * Do no set the kernel's timezone. The concept of local time cannot be supported reliably, the time + * will jump or be incorrect at every daylight saving time change. All kernel local time concepts will + * be treated as UTC that way. + */ + (void) clock_reset_timewarp(); + } + + r = clock_apply_epoch(); + if (r < 0) + log_error_errno(r, "Current system time is before build time, but cannot correct: %m"); + else if (r > 0) + log_info("System time before build time, advancing clock."); +} + +static void initialize_coredump(bool skip_setup) { +#if ENABLE_COREDUMP + if (getpid_cached() != 1) + return; + + /* Don't limit the core dump size, so that coredump handlers such as systemd-coredump (which honour the limit) + * will process core dumps for system services by default. */ + if (setrlimit(RLIMIT_CORE, &RLIMIT_MAKE_CONST(RLIM_INFINITY)) < 0) + log_warning_errno(errno, "Failed to set RLIMIT_CORE: %m"); + + /* But at the same time, turn off the core_pattern logic by default, so that no + * coredumps are stored until the systemd-coredump tool is enabled via + * sysctl. However it can be changed via the kernel command line later so core + * dumps can still be generated during early startup and in initramfs. */ + if (!skip_setup) + disable_coredumps(); +#endif +} + +static void initialize_core_pattern(bool skip_setup) { + int r; + + if (skip_setup || !arg_early_core_pattern) + return; + + if (getpid_cached() != 1) + return; + + r = write_string_file("/proc/sys/kernel/core_pattern", arg_early_core_pattern, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + log_warning_errno(r, "Failed to write '%s' to /proc/sys/kernel/core_pattern, ignoring: %m", arg_early_core_pattern); +} + +static void update_cpu_affinity(bool skip_setup) { + _cleanup_free_ char *mask = NULL; + + if (skip_setup || !arg_cpu_affinity.set) + return; + + assert(arg_cpu_affinity.allocated > 0); + + mask = cpu_set_to_string(&arg_cpu_affinity); + log_debug("Setting CPU affinity to %s.", strnull(mask)); + + if (sched_setaffinity(0, arg_cpu_affinity.allocated, arg_cpu_affinity.set) < 0) + log_warning_errno(errno, "Failed to set CPU affinity: %m"); +} + +static void update_numa_policy(bool skip_setup) { + int r; + _cleanup_free_ char *nodes = NULL; + const char * policy = NULL; + + if (skip_setup || !mpol_is_valid(numa_policy_get_type(&arg_numa_policy))) + return; + + if (DEBUG_LOGGING) { + policy = mpol_to_string(numa_policy_get_type(&arg_numa_policy)); + nodes = cpu_set_to_range_string(&arg_numa_policy.nodes); + log_debug("Setting NUMA policy to %s, with nodes %s.", strnull(policy), strnull(nodes)); + } + + r = apply_numa_policy(&arg_numa_policy); + if (r == -EOPNOTSUPP) + log_debug_errno(r, "NUMA support not available, ignoring."); + else if (r < 0) + log_warning_errno(r, "Failed to set NUMA memory policy: %m"); +} + +static void do_reexecute( + int argc, + char *argv[], + const struct rlimit *saved_rlimit_nofile, + const struct rlimit *saved_rlimit_memlock, + FDSet *fds, + const char *switch_root_dir, + const char *switch_root_init, + const char **ret_error_message) { + + unsigned i, j, args_size; + const char **args; + int r; + + assert(saved_rlimit_nofile); + assert(saved_rlimit_memlock); + assert(ret_error_message); + + /* Close and disarm the watchdog, so that the new instance can reinitialize it, but doesn't get rebooted while + * we do that */ + watchdog_close(true); + + /* Reset RLIMIT_NOFILE + RLIMIT_MEMLOCK back to the kernel defaults, so that the new systemd can pass + * the kernel default to its child processes */ + if (saved_rlimit_nofile->rlim_cur != 0) + (void) setrlimit(RLIMIT_NOFILE, saved_rlimit_nofile); + if (saved_rlimit_memlock->rlim_cur != RLIM_INFINITY) + (void) setrlimit(RLIMIT_MEMLOCK, saved_rlimit_memlock); + + if (switch_root_dir) { + /* Kill all remaining processes from the initrd, but don't wait for them, so that we can handle the + * SIGCHLD for them after deserializing. */ + broadcast_signal(SIGTERM, false, true, arg_default_timeout_stop_usec); + + /* And switch root with MS_MOVE, because we remove the old directory afterwards and detach it. */ + r = switch_root(switch_root_dir, "/mnt", true, MS_MOVE); + if (r < 0) + log_error_errno(r, "Failed to switch root, trying to continue: %m"); + } + + args_size = MAX(6, argc+1); + args = newa(const char*, args_size); + + if (!switch_root_init) { + char sfd[DECIMAL_STR_MAX(int) + 1]; + + /* First try to spawn ourselves with the right path, and with full serialization. We do this only if + * the user didn't specify an explicit init to spawn. */ + + assert(arg_serialization); + assert(fds); + + xsprintf(sfd, "%i", fileno(arg_serialization)); + + i = 0; + args[i++] = SYSTEMD_BINARY_PATH; + if (switch_root_dir) + args[i++] = "--switched-root"; + args[i++] = arg_system ? "--system" : "--user"; + args[i++] = "--deserialize"; + args[i++] = sfd; + args[i++] = NULL; + + assert(i <= args_size); + + /* + * We want valgrind to print its memory usage summary before reexecution. Valgrind won't do this is on + * its own on exec(), but it will do it on exit(). Hence, to ensure we get a summary here, fork() off + * a child, let it exit() cleanly, so that it prints the summary, and wait() for it in the parent, + * before proceeding into the exec(). + */ + valgrind_summary_hack(); + + (void) execv(args[0], (char* const*) args); + log_debug_errno(errno, "Failed to execute our own binary, trying fallback: %m"); + } + + /* Try the fallback, if there is any, without any serialization. We pass the original argv[] and envp[]. (Well, + * modulo the ordering changes due to getopt() in argv[], and some cleanups in envp[], but let's hope that + * doesn't matter.) */ + + arg_serialization = safe_fclose(arg_serialization); + fds = fdset_free(fds); + + /* Reopen the console */ + (void) make_console_stdio(); + + for (j = 1, i = 1; j < (unsigned) argc; j++) + args[i++] = argv[j]; + args[i++] = NULL; + assert(i <= args_size); + + /* Re-enable any blocked signals, especially important if we switch from initial ramdisk to init=... */ + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + (void) rlimit_nofile_safe(); + + if (switch_root_init) { + args[0] = switch_root_init; + (void) execve(args[0], (char* const*) args, saved_env); + log_warning_errno(errno, "Failed to execute configured init, trying fallback: %m"); + } + + args[0] = "/sbin/init"; + (void) execv(args[0], (char* const*) args); + r = -errno; + + manager_status_printf(NULL, STATUS_TYPE_EMERGENCY, + ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, + "Failed to execute /sbin/init"); + + if (r == -ENOENT) { + log_warning("No /sbin/init, trying fallback"); + + args[0] = "/bin/sh"; + args[1] = NULL; + (void) execve(args[0], (char* const*) args, saved_env); + log_error_errno(errno, "Failed to execute /bin/sh, giving up: %m"); + } else + log_warning_errno(r, "Failed to execute /sbin/init, giving up: %m"); + + *ret_error_message = "Failed to execute fallback shell"; +} + +static int invoke_main_loop( + Manager *m, + const struct rlimit *saved_rlimit_nofile, + const struct rlimit *saved_rlimit_memlock, + bool *ret_reexecute, + int *ret_retval, /* Return parameters relevant for shutting down */ + const char **ret_shutdown_verb, /* … */ + FDSet **ret_fds, /* Return parameters for reexecuting */ + char **ret_switch_root_dir, /* … */ + char **ret_switch_root_init, /* … */ + const char **ret_error_message) { + + int r; + + assert(m); + assert(saved_rlimit_nofile); + assert(saved_rlimit_memlock); + assert(ret_reexecute); + assert(ret_retval); + assert(ret_shutdown_verb); + assert(ret_fds); + assert(ret_switch_root_dir); + assert(ret_switch_root_init); + assert(ret_error_message); + + for (;;) { + r = manager_loop(m); + if (r < 0) { + *ret_error_message = "Failed to run main loop"; + return log_emergency_errno(r, "Failed to run main loop: %m"); + } + + switch ((ManagerObjective) r) { + + case MANAGER_RELOAD: { + LogTarget saved_log_target; + int saved_log_level; + + log_info("Reloading."); + + /* First, save any overridden log level/target, then parse the configuration file, which might + * change the log level to new settings. */ + + saved_log_level = m->log_level_overridden ? log_get_max_level() : -1; + saved_log_target = m->log_target_overridden ? log_get_target() : _LOG_TARGET_INVALID; + + (void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock); + + set_manager_defaults(m); + + update_cpu_affinity(false); + update_numa_policy(false); + + if (saved_log_level >= 0) + manager_override_log_level(m, saved_log_level); + if (saved_log_target >= 0) + manager_override_log_target(m, saved_log_target); + + r = manager_reload(m); + if (r < 0) + /* Reloading failed before the point of no return. Let's continue running as if nothing happened. */ + m->objective = MANAGER_OK; + + break; + } + + case MANAGER_REEXECUTE: + + r = prepare_reexecute(m, &arg_serialization, ret_fds, false); + if (r < 0) { + *ret_error_message = "Failed to prepare for reexecution"; + return r; + } + + log_notice("Reexecuting."); + + *ret_reexecute = true; + *ret_retval = EXIT_SUCCESS; + *ret_shutdown_verb = NULL; + *ret_switch_root_dir = *ret_switch_root_init = NULL; + + return 0; + + case MANAGER_SWITCH_ROOT: + if (!m->switch_root_init) { + r = prepare_reexecute(m, &arg_serialization, ret_fds, true); + if (r < 0) { + *ret_error_message = "Failed to prepare for reexecution"; + return r; + } + } else + *ret_fds = NULL; + + log_notice("Switching root."); + + *ret_reexecute = true; + *ret_retval = EXIT_SUCCESS; + *ret_shutdown_verb = NULL; + + /* Steal the switch root parameters */ + *ret_switch_root_dir = TAKE_PTR(m->switch_root); + *ret_switch_root_init = TAKE_PTR(m->switch_root_init); + + return 0; + + case MANAGER_EXIT: + + if (MANAGER_IS_USER(m)) { + log_debug("Exit."); + + *ret_reexecute = false; + *ret_retval = m->return_value; + *ret_shutdown_verb = NULL; + *ret_fds = NULL; + *ret_switch_root_dir = *ret_switch_root_init = NULL; + + return 0; + } + + _fallthrough_; + case MANAGER_REBOOT: + case MANAGER_POWEROFF: + case MANAGER_HALT: + case MANAGER_KEXEC: { + static const char * const table[_MANAGER_OBJECTIVE_MAX] = { + [MANAGER_EXIT] = "exit", + [MANAGER_REBOOT] = "reboot", + [MANAGER_POWEROFF] = "poweroff", + [MANAGER_HALT] = "halt", + [MANAGER_KEXEC] = "kexec", + }; + + log_notice("Shutting down."); + + *ret_reexecute = false; + *ret_retval = m->return_value; + assert_se(*ret_shutdown_verb = table[m->objective]); + *ret_fds = NULL; + *ret_switch_root_dir = *ret_switch_root_init = NULL; + + return 0; + } + + default: + assert_not_reached("Unknown or unexpected manager objective."); + } + } +} + +static void log_execution_mode(bool *ret_first_boot) { + assert(ret_first_boot); + + if (arg_system) { + int v; + + log_info("systemd " GIT_VERSION " running in %ssystem mode. (" SYSTEMD_FEATURES ")", + arg_action == ACTION_TEST ? "test " : "" ); + + v = detect_virtualization(); + if (v > 0) + log_info("Detected virtualization %s.", virtualization_to_string(v)); + + log_info("Detected architecture %s.", architecture_to_string(uname_architecture())); + + if (in_initrd()) { + *ret_first_boot = false; + log_info("Running in initial RAM disk."); + } else { + /* Let's check whether we are in first boot, i.e. whether /etc is still unpopulated. We use + * /etc/machine-id as flag file, for this: if it exists we assume /etc is populated, if it + * doesn't it's unpopulated. This allows container managers and installers to provision a + * couple of files already. If the container manager wants to provision the machine ID itself + * it should pass $container_uuid to PID 1. */ + + *ret_first_boot = access("/etc/machine-id", F_OK) < 0; + if (*ret_first_boot) + log_info("Running with unpopulated /etc."); + } + } else { + if (DEBUG_LOGGING) { + _cleanup_free_ char *t; + + t = uid_to_name(getuid()); + log_debug("systemd " GIT_VERSION " running in %suser mode for user " UID_FMT "/%s. (" SYSTEMD_FEATURES ")", + arg_action == ACTION_TEST ? " test" : "", getuid(), strna(t)); + } + + *ret_first_boot = false; + } +} + +static int initialize_runtime( + bool skip_setup, + struct rlimit *saved_rlimit_nofile, + struct rlimit *saved_rlimit_memlock, + const char **ret_error_message) { + int r; + + assert(ret_error_message); + + /* Sets up various runtime parameters. Many of these initializations are conditionalized: + * + * - Some only apply to --system instances + * - Some only apply to --user instances + * - Some only apply when we first start up, but not when we reexecute + */ + + if (arg_action != ACTION_RUN) + return 0; + + update_cpu_affinity(skip_setup); + update_numa_policy(skip_setup); + + if (arg_system) { + /* Make sure we leave a core dump without panicking the kernel. */ + install_crash_handler(); + + if (!skip_setup) { + r = mount_cgroup_controllers(); + if (r < 0) { + *ret_error_message = "Failed to mount cgroup hierarchies"; + return r; + } + + status_welcome(); + hostname_setup(); + machine_id_setup(NULL, arg_machine_id, NULL); + loopback_setup(); + bump_unix_max_dgram_qlen(); + bump_file_max_and_nr_open(); + test_usr(); + write_container_id(); + } + + if (arg_watchdog_device) { + r = watchdog_set_device(arg_watchdog_device); + if (r < 0) + log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m", arg_watchdog_device); + } + + if (timestamp_is_set(arg_runtime_watchdog)) + watchdog_set_timeout(&arg_runtime_watchdog); + } + + if (arg_timer_slack_nsec != NSEC_INFINITY) + if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0) + log_warning_errno(errno, "Failed to adjust timer slack, ignoring: %m"); + + if (arg_system && !cap_test_all(arg_capability_bounding_set)) { + r = capability_bounding_set_drop_usermode(arg_capability_bounding_set); + if (r < 0) { + *ret_error_message = "Failed to drop capability bounding set of usermode helpers"; + return log_emergency_errno(r, "Failed to drop capability bounding set of usermode helpers: %m"); + } + + r = capability_bounding_set_drop(arg_capability_bounding_set, true); + if (r < 0) { + *ret_error_message = "Failed to drop capability bounding set"; + return log_emergency_errno(r, "Failed to drop capability bounding set: %m"); + } + } + + if (arg_system && arg_no_new_privs) { + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { + *ret_error_message = "Failed to disable new privileges"; + return log_emergency_errno(errno, "Failed to disable new privileges: %m"); + } + } + + if (arg_syscall_archs) { + r = enforce_syscall_archs(arg_syscall_archs); + if (r < 0) { + *ret_error_message = "Failed to set syscall architectures"; + return r; + } + } + + if (!arg_system) + /* Become reaper of our children */ + if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) + log_warning_errno(errno, "Failed to make us a subreaper: %m"); + + /* Bump up RLIMIT_NOFILE for systemd itself */ + (void) bump_rlimit_nofile(saved_rlimit_nofile); + (void) bump_rlimit_memlock(saved_rlimit_memlock); + + return 0; +} + +static int do_queue_default_job( + Manager *m, + const char **ret_error_message) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + Job *default_unit_job; + Unit *target = NULL; + int r; + + log_debug("Activating default unit: %s", arg_default_unit); + + r = manager_load_startable_unit_or_warn(m, arg_default_unit, NULL, &target); + if (r < 0) { + log_info("Falling back to rescue target: " SPECIAL_RESCUE_TARGET); + + r = manager_load_startable_unit_or_warn(m, SPECIAL_RESCUE_TARGET, NULL, &target); + if (r < 0) { + *ret_error_message = r == -ERFKILL ? "Rescue target masked" + : "Failed to load rescue target"; + return r; + } + } + + assert(target->load_state == UNIT_LOADED); + + r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, NULL, &error, &default_unit_job); + if (r == -EPERM) { + log_debug_errno(r, "Default target could not be isolated, starting instead: %s", bus_error_message(&error, r)); + + sd_bus_error_free(&error); + + r = manager_add_job(m, JOB_START, target, JOB_REPLACE, NULL, &error, &default_unit_job); + if (r < 0) { + *ret_error_message = "Failed to start default target"; + return log_emergency_errno(r, "Failed to start default target: %s", bus_error_message(&error, r)); + } + + } else if (r < 0) { + *ret_error_message = "Failed to isolate default target"; + return log_emergency_errno(r, "Failed to isolate default target: %s", bus_error_message(&error, r)); + } + + m->default_unit_job_id = default_unit_job->id; + + return 0; +} + +static void save_rlimits(struct rlimit *saved_rlimit_nofile, + struct rlimit *saved_rlimit_memlock) { + + assert(saved_rlimit_nofile); + assert(saved_rlimit_memlock); + + if (getrlimit(RLIMIT_NOFILE, saved_rlimit_nofile) < 0) + log_warning_errno(errno, "Reading RLIMIT_NOFILE failed, ignoring: %m"); + + if (getrlimit(RLIMIT_MEMLOCK, saved_rlimit_memlock) < 0) + log_warning_errno(errno, "Reading RLIMIT_MEMLOCK failed, ignoring: %m"); +} + +static void fallback_rlimit_nofile(const struct rlimit *saved_rlimit_nofile) { + struct rlimit *rl; + + if (arg_default_rlimit[RLIMIT_NOFILE]) + return; + + /* Make sure forked processes get limits based on the original kernel setting */ + + rl = newdup(struct rlimit, saved_rlimit_nofile, 1); + if (!rl) { + log_oom(); + return; + } + + /* Bump the hard limit for system services to a substantially higher value. The default + * hard limit current kernels set is pretty low (4K), mostly for historical + * reasons. According to kernel developers, the fd handling in recent kernels has been + * optimized substantially enough, so that we can bump the limit now, without paying too + * high a price in memory or performance. Note however that we only bump the hard limit, + * not the soft limit. That's because select() works the way it works, and chokes on fds + * >= 1024. If we'd bump the soft limit globally, it might accidentally happen to + * unexpecting programs that they get fds higher than what they can process using + * select(). By only bumping the hard limit but leaving the low limit as it is we avoid + * this pitfall: programs that are written by folks aware of the select() problem in mind + * (and thus use poll()/epoll instead of select(), the way everybody should) can + * explicitly opt into high fds by bumping their soft limit beyond 1024, to the hard limit + * we pass. */ + if (arg_system) { + int nr; + + /* Get the underlying absolute limit the kernel enforces */ + nr = read_nr_open(); + + rl->rlim_max = MIN((rlim_t) nr, MAX(rl->rlim_max, (rlim_t) HIGH_RLIMIT_NOFILE)); + } + + /* If for some reason we were invoked with a soft limit above 1024 (which should never + * happen!, but who knows what we get passed in from pam_limit when invoked as --user + * instance), then lower what we pass on to not confuse our children */ + rl->rlim_cur = MIN(rl->rlim_cur, (rlim_t) FD_SETSIZE); + + arg_default_rlimit[RLIMIT_NOFILE] = rl; +} + +static void fallback_rlimit_memlock(const struct rlimit *saved_rlimit_memlock) { + struct rlimit *rl; + + /* Pass the original value down to invoked processes */ + + if (arg_default_rlimit[RLIMIT_MEMLOCK]) + return; + + rl = newdup(struct rlimit, saved_rlimit_memlock, 1); + if (!rl) { + log_oom(); + return; + } + + arg_default_rlimit[RLIMIT_MEMLOCK] = rl; +} + +static void reset_arguments(void) { + /* Frees/resets arg_* variables, with a few exceptions commented below. */ + + arg_default_unit = mfree(arg_default_unit); + + /* arg_system — ignore */ + + arg_dump_core = true; + arg_crash_chvt = -1; + arg_crash_shell = false; + arg_crash_reboot = false; + arg_confirm_spawn = mfree(arg_confirm_spawn); + arg_show_status = _SHOW_STATUS_INVALID; + arg_status_unit_format = STATUS_UNIT_FORMAT_DEFAULT; + arg_switched_root = false; + arg_pager_flags = 0; + arg_service_watchdogs = true; + arg_default_std_output = EXEC_OUTPUT_JOURNAL; + arg_default_std_error = EXEC_OUTPUT_INHERIT; + arg_default_restart_usec = DEFAULT_RESTART_USEC; + arg_default_timeout_start_usec = DEFAULT_TIMEOUT_USEC; + arg_default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC; + arg_default_timeout_abort_usec = DEFAULT_TIMEOUT_USEC; + arg_default_timeout_abort_set = false; + arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL; + arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST; + arg_runtime_watchdog = 0; + arg_reboot_watchdog = 10 * USEC_PER_MINUTE; + arg_kexec_watchdog = 0; + arg_early_core_pattern = NULL; + arg_watchdog_device = NULL; + + arg_default_environment = strv_free(arg_default_environment); + rlimit_free_all(arg_default_rlimit); + + arg_capability_bounding_set = CAP_ALL; + arg_no_new_privs = false; + arg_timer_slack_nsec = NSEC_INFINITY; + arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE; + + arg_syscall_archs = set_free(arg_syscall_archs); + + /* arg_serialization — ignore */ + + arg_default_cpu_accounting = -1; + arg_default_io_accounting = false; + arg_default_ip_accounting = false; + arg_default_blockio_accounting = false; + arg_default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT; + arg_default_tasks_accounting = true; + arg_default_tasks_max = DEFAULT_TASKS_MAX; + arg_machine_id = (sd_id128_t) {}; + arg_cad_burst_action = EMERGENCY_ACTION_REBOOT_FORCE; + arg_default_oom_policy = OOM_STOP; + + cpu_set_reset(&arg_cpu_affinity); + numa_policy_reset(&arg_numa_policy); +} + +static int parse_configuration(const struct rlimit *saved_rlimit_nofile, + const struct rlimit *saved_rlimit_memlock) { + int r; + + assert(saved_rlimit_nofile); + assert(saved_rlimit_memlock); + + /* Assign configuration defaults */ + reset_arguments(); + + r = parse_config_file(); + if (r < 0) + log_warning_errno(r, "Failed to parse config file, ignoring: %m"); + + if (arg_system) { + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + } + + /* Initialize some default rlimits for services if they haven't been configured */ + fallback_rlimit_nofile(saved_rlimit_nofile); + fallback_rlimit_memlock(saved_rlimit_memlock); + + /* Note that this also parses bits from the kernel command line, including "debug". */ + log_parse_environment(); + + return 0; +} + +static int load_configuration( + int argc, + char **argv, + const struct rlimit *saved_rlimit_nofile, + const struct rlimit *saved_rlimit_memlock, + const char **ret_error_message) { + int r; + + assert(saved_rlimit_nofile); + assert(saved_rlimit_memlock); + assert(ret_error_message); + + (void) parse_configuration(saved_rlimit_nofile, saved_rlimit_memlock); + + r = parse_argv(argc, argv); + if (r < 0) { + *ret_error_message = "Failed to parse commandline arguments"; + return r; + } + + /* Initialize default unit */ + if (!arg_default_unit) { + arg_default_unit = strdup(SPECIAL_DEFAULT_TARGET); + if (!arg_default_unit) { + *ret_error_message = "Failed to set default unit"; + return log_oom(); + } + } + + /* Initialize the show status setting if it hasn't been set explicitly yet */ + if (arg_show_status == _SHOW_STATUS_INVALID) + arg_show_status = SHOW_STATUS_YES; + + return 0; +} + +static int safety_checks(void) { + + if (getpid_cached() == 1 && + arg_action != ACTION_RUN) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Unsupported execution mode while PID 1."); + + if (getpid_cached() == 1 && + !arg_system) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Can't run --user mode as PID 1."); + + if (arg_action == ACTION_RUN && + arg_system && + getpid_cached() != 1) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Can't run system mode unless PID 1."); + + if (arg_action == ACTION_TEST && + geteuid() == 0) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Don't run test mode as root."); + + if (!arg_system && + arg_action == ACTION_RUN && + sd_booted() <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Trying to run as user instance, but the system has not been booted with systemd."); + + if (!arg_system && + arg_action == ACTION_RUN && + !getenv("XDG_RUNTIME_DIR")) + return log_error_errno(SYNTHETIC_ERRNO(EUNATCH), + "Trying to run as user instance, but $XDG_RUNTIME_DIR is not set."); + + if (arg_system && + arg_action == ACTION_RUN && + running_in_chroot() > 0) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Cannot be run in a chroot() environment."); + + return 0; +} + +static int initialize_security( + bool *loaded_policy, + dual_timestamp *security_start_timestamp, + dual_timestamp *security_finish_timestamp, + const char **ret_error_message) { + + int r; + + assert(loaded_policy); + assert(security_start_timestamp); + assert(security_finish_timestamp); + assert(ret_error_message); + + dual_timestamp_get(security_start_timestamp); + + r = mac_selinux_setup(loaded_policy); + if (r < 0) { + *ret_error_message = "Failed to load SELinux policy"; + return r; + } + + r = mac_smack_setup(loaded_policy); + if (r < 0) { + *ret_error_message = "Failed to load SMACK policy"; + return r; + } + + r = ima_setup(); + if (r < 0) { + *ret_error_message = "Failed to load IMA policy"; + return r; + } + + dual_timestamp_get(security_finish_timestamp); + return 0; +} + +static void test_summary(Manager *m) { + assert(m); + + printf("-> By units:\n"); + manager_dump_units(m, stdout, "\t"); + + printf("-> By jobs:\n"); + manager_dump_jobs(m, stdout, "\t"); +} + +static int collect_fds(FDSet **ret_fds, const char **ret_error_message) { + int r; + + assert(ret_fds); + assert(ret_error_message); + + r = fdset_new_fill(ret_fds); + if (r < 0) { + *ret_error_message = "Failed to allocate fd set"; + return log_emergency_errno(r, "Failed to allocate fd set: %m"); + } + + fdset_cloexec(*ret_fds, true); + + if (arg_serialization) + assert_se(fdset_remove(*ret_fds, fileno(arg_serialization)) >= 0); + + return 0; +} + +static void setup_console_terminal(bool skip_setup) { + + if (!arg_system) + return; + + /* Become a session leader if we aren't one yet. */ + (void) setsid(); + + /* If we are init, we connect stdin/stdout/stderr to /dev/null and make sure we don't have a controlling + * tty. */ + (void) release_terminal(); + + /* Reset the console, but only if this is really init and we are freshly booted */ + if (getpid_cached() == 1 && !skip_setup) + (void) console_setup(); +} + +static bool early_skip_setup_check(int argc, char *argv[]) { + bool found_deserialize = false; + int i; + + /* Determine if this is a reexecution or normal bootup. We do the full command line parsing much later, so + * let's just have a quick peek here. Note that if we have switched root, do all the special setup things + * anyway, even if in that case we also do deserialization. */ + + for (i = 1; i < argc; i++) { + if (streq(argv[i], "--switched-root")) + return false; /* If we switched root, don't skip the setup. */ + else if (streq(argv[i], "--deserialize")) + found_deserialize = true; + } + + return found_deserialize; /* When we are deserializing, then we are reexecuting, hence avoid the extensive setup */ +} + +static int save_env(void) { + char **l; + + l = strv_copy(environ); + if (!l) + return -ENOMEM; + + strv_free_and_replace(saved_env, l); + return 0; +} + +int main(int argc, char *argv[]) { + + dual_timestamp initrd_timestamp = DUAL_TIMESTAMP_NULL, userspace_timestamp = DUAL_TIMESTAMP_NULL, kernel_timestamp = DUAL_TIMESTAMP_NULL, + security_start_timestamp = DUAL_TIMESTAMP_NULL, security_finish_timestamp = DUAL_TIMESTAMP_NULL; + struct rlimit saved_rlimit_nofile = RLIMIT_MAKE_CONST(0), + saved_rlimit_memlock = RLIMIT_MAKE_CONST(RLIM_INFINITY); /* The original rlimits we passed + * in. Note we use different values + * for the two that indicate whether + * these fields are initialized! */ + bool skip_setup, loaded_policy = false, queue_default_job = false, first_boot = false, reexecute = false; + char *switch_root_dir = NULL, *switch_root_init = NULL; + usec_t before_startup, after_startup; + static char systemd[] = "systemd"; + char timespan[FORMAT_TIMESPAN_MAX]; + const char *shutdown_verb = NULL, *error_message = NULL; + int r, retval = EXIT_FAILURE; + Manager *m = NULL; + FDSet *fds = NULL; + + /* SysV compatibility: redirect init → telinit */ + redirect_telinit(argc, argv); + + /* Take timestamps early on */ + dual_timestamp_from_monotonic(&kernel_timestamp, 0); + dual_timestamp_get(&userspace_timestamp); + + /* Figure out whether we need to do initialize the system, or if we already did that because we are + * reexecuting */ + skip_setup = early_skip_setup_check(argc, argv); + + /* If we get started via the /sbin/init symlink then we are called 'init'. After a subsequent reexecution we + * are then called 'systemd'. That is confusing, hence let's call us systemd right-away. */ + program_invocation_short_name = systemd; + (void) prctl(PR_SET_NAME, systemd); + + /* Save the original command line */ + save_argc_argv(argc, argv); + + /* Save the original environment as we might need to restore it if we're requested to execute another + * system manager later. */ + r = save_env(); + if (r < 0) { + error_message = "Failed to copy environment block"; + goto finish; + } + + /* Make sure that if the user says "syslog" we actually log to the journal. */ + log_set_upgrade_syslog_to_journal(true); + + if (getpid_cached() == 1) { + /* When we run as PID 1 force system mode */ + arg_system = true; + + /* Disable the umask logic */ + umask(0); + + /* Make sure that at least initially we do not ever log to journald/syslogd, because it might not be + * activated yet (even though the log socket for it exists). */ + log_set_prohibit_ipc(true); + + /* Always reopen /dev/console when running as PID 1 or one of its pre-execve() children. This is + * important so that we never end up logging to any foreign stderr, for example if we have to log in a + * child process right before execve()'ing the actual binary, at a point in time where socket + * activation stderr/stdout area already set up. */ + log_set_always_reopen_console(true); + + if (detect_container() <= 0) { + + /* Running outside of a container as PID 1 */ + log_set_target(LOG_TARGET_KMSG); + log_open(); + + if (in_initrd()) + initrd_timestamp = userspace_timestamp; + + if (!skip_setup) { + r = mount_setup_early(); + if (r < 0) { + error_message = "Failed to mount early API filesystems"; + goto finish; + } + + /* Let's open the log backend a second time, in case the first time didn't + * work. Quite possibly we have mounted /dev just now, so /dev/kmsg became + * available, and it previously wasn't. */ + log_open(); + + disable_printk_ratelimit(); + + r = initialize_security( + &loaded_policy, + &security_start_timestamp, + &security_finish_timestamp, + &error_message); + if (r < 0) + goto finish; + } + + if (mac_selinux_init() < 0) { + error_message = "Failed to initialize SELinux policy"; + goto finish; + } + + if (!skip_setup) + initialize_clock(); + + /* Set the default for later on, but don't actually open the logs like this for now. Note that + * if we are transitioning from the initrd there might still be journal fd open, and we + * shouldn't attempt opening that before we parsed /proc/cmdline which might redirect output + * elsewhere. */ + log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); + + } else { + /* Running inside a container, as PID 1 */ + log_set_target(LOG_TARGET_CONSOLE); + log_open(); + + /* For later on, see above... */ + log_set_target(LOG_TARGET_JOURNAL); + + /* clear the kernel timestamp, + * because we are in a container */ + kernel_timestamp = DUAL_TIMESTAMP_NULL; + } + + initialize_coredump(skip_setup); + + r = fixup_environment(); + if (r < 0) { + log_emergency_errno(r, "Failed to fix up PID 1 environment: %m"); + error_message = "Failed to fix up PID1 environment"; + goto finish; + } + + } else { + /* Running as user instance */ + arg_system = false; + log_set_target(LOG_TARGET_AUTO); + log_open(); + + /* clear the kernel timestamp, + * because we are not PID 1 */ + kernel_timestamp = DUAL_TIMESTAMP_NULL; + } + + if (arg_system) { + /* Try to figure out if we can use colors with the console. No need to do that for user instances since + * they never log into the console. */ + log_show_color(colors_enabled()); + + r = make_null_stdio(); + if (r < 0) + log_warning_errno(r, "Failed to redirect standard streams to /dev/null, ignoring: %m"); + } + + /* Mount /proc, /sys and friends, so that /proc/cmdline and + * /proc/$PID/fd is available. */ + if (getpid_cached() == 1) { + + /* Load the kernel modules early. */ + if (!skip_setup) + kmod_setup(); + + r = mount_setup(loaded_policy); + if (r < 0) { + error_message = "Failed to mount API filesystems"; + goto finish; + } + + /* The efivarfs is now mounted, let's read the random seed off it */ + (void) efi_take_random_seed(); + } + + /* Save the original RLIMIT_NOFILE/RLIMIT_MEMLOCK so that we can reset it later when + * transitioning from the initrd to the main systemd or suchlike. */ + save_rlimits(&saved_rlimit_nofile, &saved_rlimit_memlock); + + /* Reset all signal handlers. */ + (void) reset_all_signal_handlers(); + (void) ignore_signals(SIGNALS_IGNORE, -1); + + r = load_configuration(argc, argv, &saved_rlimit_nofile, &saved_rlimit_memlock, &error_message); + if (r < 0) + goto finish; + + r = safety_checks(); + if (r < 0) + goto finish; + + if (IN_SET(arg_action, ACTION_TEST, ACTION_HELP, ACTION_DUMP_CONFIGURATION_ITEMS, ACTION_DUMP_BUS_PROPERTIES)) + (void) pager_open(arg_pager_flags); + + if (arg_action != ACTION_RUN) + skip_setup = true; + + if (arg_action == ACTION_HELP) { + retval = help() < 0 ? EXIT_FAILURE : EXIT_SUCCESS; + goto finish; + } else if (arg_action == ACTION_VERSION) { + retval = version(); + goto finish; + } else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) { + unit_dump_config_items(stdout); + retval = EXIT_SUCCESS; + goto finish; + } else if (arg_action == ACTION_DUMP_BUS_PROPERTIES) { + dump_bus_properties(stdout); + retval = EXIT_SUCCESS; + goto finish; + } + + assert_se(IN_SET(arg_action, ACTION_RUN, ACTION_TEST)); + + /* Move out of the way, so that we won't block unmounts */ + assert_se(chdir("/") == 0); + + if (arg_action == ACTION_RUN) { + + /* A core pattern might have been specified via the cmdline. */ + initialize_core_pattern(skip_setup); + + /* Close logging fds, in order not to confuse collecting passed fds and terminal logic below */ + log_close(); + + /* Remember open file descriptors for later deserialization */ + r = collect_fds(&fds, &error_message); + if (r < 0) + goto finish; + + /* Give up any control of the console, but make sure its initialized. */ + setup_console_terminal(skip_setup); + + /* Open the logging devices, if possible and necessary */ + log_open(); + } + + log_execution_mode(&first_boot); + + r = initialize_runtime(skip_setup, + &saved_rlimit_nofile, + &saved_rlimit_memlock, + &error_message); + if (r < 0) + goto finish; + + r = manager_new(arg_system ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, + arg_action == ACTION_TEST ? MANAGER_TEST_FULL : 0, + &m); + if (r < 0) { + log_emergency_errno(r, "Failed to allocate manager object: %m"); + error_message = "Failed to allocate manager object"; + goto finish; + } + + m->timestamps[MANAGER_TIMESTAMP_KERNEL] = kernel_timestamp; + m->timestamps[MANAGER_TIMESTAMP_INITRD] = initrd_timestamp; + m->timestamps[MANAGER_TIMESTAMP_USERSPACE] = userspace_timestamp; + m->timestamps[manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_SECURITY_START)] = security_start_timestamp; + m->timestamps[manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_SECURITY_FINISH)] = security_finish_timestamp; + + set_manager_defaults(m); + set_manager_settings(m); + manager_set_first_boot(m, first_boot); + + /* Remember whether we should queue the default job */ + queue_default_job = !arg_serialization || arg_switched_root; + + before_startup = now(CLOCK_MONOTONIC); + + r = manager_startup(m, arg_serialization, fds); + if (r < 0) { + error_message = "Failed to start up manager"; + goto finish; + } + + /* This will close all file descriptors that were opened, but not claimed by any unit. */ + fds = fdset_free(fds); + arg_serialization = safe_fclose(arg_serialization); + + if (queue_default_job) { + r = do_queue_default_job(m, &error_message); + if (r < 0) + goto finish; + } + + after_startup = now(CLOCK_MONOTONIC); + + log_full(arg_action == ACTION_TEST ? LOG_INFO : LOG_DEBUG, + "Loaded units and determined initial transaction in %s.", + format_timespan(timespan, sizeof(timespan), after_startup - before_startup, 100 * USEC_PER_MSEC)); + + if (arg_action == ACTION_TEST) { + test_summary(m); + retval = EXIT_SUCCESS; + goto finish; + } + + (void) invoke_main_loop(m, + &saved_rlimit_nofile, + &saved_rlimit_memlock, + &reexecute, + &retval, + &shutdown_verb, + &fds, + &switch_root_dir, + &switch_root_init, + &error_message); + +finish: + pager_close(); + + if (m) { + arg_reboot_watchdog = m->reboot_watchdog; + arg_kexec_watchdog = m->kexec_watchdog; + m = manager_free(m); + } + + reset_arguments(); + mac_selinux_finish(); + + if (reexecute) + do_reexecute(argc, argv, + &saved_rlimit_nofile, + &saved_rlimit_memlock, + fds, + switch_root_dir, + switch_root_init, + &error_message); /* This only returns if reexecution failed */ + + arg_serialization = safe_fclose(arg_serialization); + fds = fdset_free(fds); + + saved_env = strv_free(saved_env); + +#if HAVE_VALGRIND_VALGRIND_H + /* If we are PID 1 and running under valgrind, then let's exit + * here explicitly. valgrind will only generate nice output on + * exit(), not on exec(), hence let's do the former not the + * latter here. */ + if (getpid_cached() == 1 && RUNNING_ON_VALGRIND) { + /* Cleanup watchdog_device strings for valgrind. We need them + * in become_shutdown() so normally we cannot free them yet. */ + watchdog_free_device(); + arg_watchdog_device = mfree(arg_watchdog_device); + return retval; + } +#endif + +#if HAS_FEATURE_ADDRESS_SANITIZER + __lsan_do_leak_check(); +#endif + + if (shutdown_verb) { + r = become_shutdown(shutdown_verb, retval); + log_error_errno(r, "Failed to execute shutdown binary, %s: %m", getpid_cached() == 1 ? "freezing" : "quitting"); + error_message = "Failed to execute shutdown binary"; + } + + watchdog_free_device(); + arg_watchdog_device = mfree(arg_watchdog_device); + + if (getpid_cached() == 1) { + if (error_message) + manager_status_printf(NULL, STATUS_TYPE_EMERGENCY, + ANSI_HIGHLIGHT_RED "!!!!!!" ANSI_NORMAL, + "%s.", error_message); + freeze_or_exit_or_reboot(); + } + + return retval; +} diff --git a/src/core/manager.c b/src/core/manager.c new file mode 100644 index 00000000..13a6b49a --- /dev/null +++ b/src/core/manager.c @@ -0,0 +1,4732 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_AUDIT +#include +#endif + +#include "sd-daemon.h" +#include "sd-messages.h" +#include "sd-path.h" + +#include "all-units.h" +#include "alloc-util.h" +#include "audit-fd.h" +#include "boot-timestamps.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-kernel.h" +#include "bus-util.h" +#include "clean-ipc.h" +#include "clock-util.h" +#include "dbus-job.h" +#include "dbus-manager.h" +#include "dbus-unit.h" +#include "dbus.h" +#include "def.h" +#include "dirent-util.h" +#include "env-util.h" +#include "escape.h" +#include "exec-util.h" +#include "execute.h" +#include "exit-status.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hashmap.h" +#include "io-util.h" +#include "install.h" +#include "label.h" +#include "locale-setup.h" +#include "log.h" +#include "macro.h" +#include "manager.h" +#include "memory-util.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-lookup.h" +#include "path-util.h" +#include "process-util.h" +#include "ratelimit.h" +#include "rlimit-util.h" +#include "rm-rf.h" +#include "serialize.h" +#include "signal-util.h" +#include "socket-util.h" +#include "special.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "strxcpyx.h" +#include "sysctl-util.h" +#include "syslog-util.h" +#include "terminal-util.h" +#include "time-util.h" +#include "transaction.h" +#include "umask-util.h" +#include "unit-name.h" +#include "user-util.h" +#include "virt.h" +#include "watchdog.h" + +#define NOTIFY_RCVBUF_SIZE (8*1024*1024) +#define CGROUPS_AGENT_RCVBUF_SIZE (8*1024*1024) + +/* Initial delay and the interval for printing status messages about running jobs */ +#define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC) +#define JOBS_IN_PROGRESS_PERIOD_USEC (USEC_PER_SEC / 3) +#define JOBS_IN_PROGRESS_PERIOD_DIVISOR 3 + +/* If there are more than 1K bus messages queue across our API and direct buses, then let's not add more on top until + * the queue gets more empty. */ +#define MANAGER_BUS_BUSY_THRESHOLD 1024LU + +/* How many units and jobs to process of the bus queue before returning to the event loop. */ +#define MANAGER_BUS_MESSAGE_BUDGET 100U + +static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); +static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); +static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); +static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); +static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); +static int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata); +static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata); +static int manager_dispatch_run_queue(sd_event_source *source, void *userdata); +static int manager_dispatch_sigchld(sd_event_source *source, void *userdata); +static int manager_dispatch_timezone_change(sd_event_source *source, const struct inotify_event *event, void *userdata); +static int manager_run_environment_generators(Manager *m); +static int manager_run_generators(Manager *m); + +static void manager_watch_jobs_in_progress(Manager *m) { + usec_t next; + int r; + + assert(m); + + /* We do not want to show the cylon animation if the user + * needs to confirm service executions otherwise confirmation + * messages will be screwed by the cylon animation. */ + if (!manager_is_confirm_spawn_disabled(m)) + return; + + if (m->jobs_in_progress_event_source) + return; + + next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC; + r = sd_event_add_time( + m->event, + &m->jobs_in_progress_event_source, + CLOCK_MONOTONIC, + next, 0, + manager_dispatch_jobs_in_progress, m); + if (r < 0) + return; + + (void) sd_event_source_set_description(m->jobs_in_progress_event_source, "manager-jobs-in-progress"); +} + +#define CYLON_BUFFER_EXTRA (2*STRLEN(ANSI_RED) + STRLEN(ANSI_HIGHLIGHT_RED) + 2*STRLEN(ANSI_NORMAL)) + +static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) { + char *p = buffer; + + assert(buflen >= CYLON_BUFFER_EXTRA + width + 1); + assert(pos <= width+1); /* 0 or width+1 mean that the center light is behind the corner */ + + if (pos > 1) { + if (pos > 2) + p = mempset(p, ' ', pos-2); + if (log_get_show_color()) + p = stpcpy(p, ANSI_RED); + *p++ = '*'; + } + + if (pos > 0 && pos <= width) { + if (log_get_show_color()) + p = stpcpy(p, ANSI_HIGHLIGHT_RED); + *p++ = '*'; + } + + if (log_get_show_color()) + p = stpcpy(p, ANSI_NORMAL); + + if (pos < width) { + if (log_get_show_color()) + p = stpcpy(p, ANSI_RED); + *p++ = '*'; + if (pos < width-1) + p = mempset(p, ' ', width-1-pos); + if (log_get_show_color()) + strcpy(p, ANSI_NORMAL); + } +} + +void manager_flip_auto_status(Manager *m, bool enable) { + assert(m); + + if (enable) { + if (m->show_status == SHOW_STATUS_AUTO) + manager_set_show_status(m, SHOW_STATUS_TEMPORARY); + } else { + if (m->show_status == SHOW_STATUS_TEMPORARY) + manager_set_show_status(m, SHOW_STATUS_AUTO); + } +} + +static void manager_print_jobs_in_progress(Manager *m) { + _cleanup_free_ char *job_of_n = NULL; + Iterator i; + Job *j; + unsigned counter = 0, print_nr; + char cylon[6 + CYLON_BUFFER_EXTRA + 1]; + unsigned cylon_pos; + char time[FORMAT_TIMESPAN_MAX], limit[FORMAT_TIMESPAN_MAX] = "no limit"; + uint64_t x; + + assert(m); + assert(m->n_running_jobs > 0); + + manager_flip_auto_status(m, true); + + print_nr = (m->jobs_in_progress_iteration / JOBS_IN_PROGRESS_PERIOD_DIVISOR) % m->n_running_jobs; + + HASHMAP_FOREACH(j, m->jobs, i) + if (j->state == JOB_RUNNING && counter++ == print_nr) + break; + + /* m->n_running_jobs must be consistent with the contents of m->jobs, + * so the above loop must have succeeded in finding j. */ + assert(counter == print_nr + 1); + assert(j); + + cylon_pos = m->jobs_in_progress_iteration % 14; + if (cylon_pos >= 8) + cylon_pos = 14 - cylon_pos; + draw_cylon(cylon, sizeof(cylon), 6, cylon_pos); + + m->jobs_in_progress_iteration++; + + if (m->n_running_jobs > 1) { + if (asprintf(&job_of_n, "(%u of %u) ", counter, m->n_running_jobs) < 0) + job_of_n = NULL; + } + + format_timespan(time, sizeof(time), now(CLOCK_MONOTONIC) - j->begin_usec, 1*USEC_PER_SEC); + if (job_get_timeout(j, &x) > 0) + format_timespan(limit, sizeof(limit), x - j->begin_usec, 1*USEC_PER_SEC); + + manager_status_printf(m, STATUS_TYPE_EPHEMERAL, cylon, + "%sA %s job is running for %s (%s / %s)", + strempty(job_of_n), + job_type_to_string(j->type), + unit_status_string(j->unit), + time, limit); +} + +static int have_ask_password(void) { + _cleanup_closedir_ DIR *dir; + struct dirent *de; + + dir = opendir("/run/systemd/ask-password"); + if (!dir) { + if (errno == ENOENT) + return false; + else + return -errno; + } + + FOREACH_DIRENT_ALL(de, dir, return -errno) { + if (startswith(de->d_name, "ask.")) + return true; + } + return false; +} + +static int manager_dispatch_ask_password_fd(sd_event_source *source, + int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + + assert(m); + + (void) flush_fd(fd); + + m->have_ask_password = have_ask_password(); + if (m->have_ask_password < 0) + /* Log error but continue. Negative have_ask_password + * is treated as unknown status. */ + log_error_errno(m->have_ask_password, "Failed to list /run/systemd/ask-password: %m"); + + return 0; +} + +static void manager_close_ask_password(Manager *m) { + assert(m); + + m->ask_password_event_source = sd_event_source_unref(m->ask_password_event_source); + m->ask_password_inotify_fd = safe_close(m->ask_password_inotify_fd); + m->have_ask_password = -EINVAL; +} + +static int manager_check_ask_password(Manager *m) { + int r; + + assert(m); + + if (!m->ask_password_event_source) { + assert(m->ask_password_inotify_fd < 0); + + (void) mkdir_p_label("/run/systemd/ask-password", 0755); + + m->ask_password_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (m->ask_password_inotify_fd < 0) + return log_error_errno(errno, "Failed to create inotify object: %m"); + + r = inotify_add_watch_and_warn(m->ask_password_inotify_fd, + "/run/systemd/ask-password", + IN_CREATE|IN_DELETE|IN_MOVE); + if (r < 0) { + manager_close_ask_password(m); + return r; + } + + r = sd_event_add_io(m->event, &m->ask_password_event_source, + m->ask_password_inotify_fd, EPOLLIN, + manager_dispatch_ask_password_fd, m); + if (r < 0) { + log_error_errno(errno, "Failed to add event source for /run/systemd/ask-password: %m"); + manager_close_ask_password(m); + return -errno; + } + + (void) sd_event_source_set_description(m->ask_password_event_source, "manager-ask-password"); + + /* Queries might have been added meanwhile... */ + manager_dispatch_ask_password_fd(m->ask_password_event_source, + m->ask_password_inotify_fd, EPOLLIN, m); + } + + return m->have_ask_password; +} + +static int manager_watch_idle_pipe(Manager *m) { + int r; + + assert(m); + + if (m->idle_pipe_event_source) + return 0; + + if (m->idle_pipe[2] < 0) + return 0; + + r = sd_event_add_io(m->event, &m->idle_pipe_event_source, m->idle_pipe[2], EPOLLIN, manager_dispatch_idle_pipe_fd, m); + if (r < 0) + return log_error_errno(r, "Failed to watch idle pipe: %m"); + + (void) sd_event_source_set_description(m->idle_pipe_event_source, "manager-idle-pipe"); + + return 0; +} + +static void manager_close_idle_pipe(Manager *m) { + assert(m); + + m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source); + + safe_close_pair(m->idle_pipe); + safe_close_pair(m->idle_pipe + 2); +} + +static int manager_setup_time_change(Manager *m) { + int r; + + assert(m); + + if (MANAGER_IS_TEST_RUN(m)) + return 0; + + m->time_change_event_source = sd_event_source_unref(m->time_change_event_source); + m->time_change_fd = safe_close(m->time_change_fd); + + m->time_change_fd = time_change_fd(); + if (m->time_change_fd < 0) + return log_error_errno(m->time_change_fd, "Failed to create timer change timer fd: %m"); + + r = sd_event_add_io(m->event, &m->time_change_event_source, m->time_change_fd, EPOLLIN, manager_dispatch_time_change_fd, m); + if (r < 0) + return log_error_errno(r, "Failed to create time change event source: %m"); + + /* Schedule this slightly earlier than the .timer event sources */ + r = sd_event_source_set_priority(m->time_change_event_source, SD_EVENT_PRIORITY_NORMAL-1); + if (r < 0) + return log_error_errno(r, "Failed to set priority of time change event sources: %m"); + + (void) sd_event_source_set_description(m->time_change_event_source, "manager-time-change"); + + log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd."); + + return 0; +} + +static int manager_read_timezone_stat(Manager *m) { + struct stat st; + bool changed; + + assert(m); + + /* Read the current stat() data of /etc/localtime so that we detect changes */ + if (lstat("/etc/localtime", &st) < 0) { + log_debug_errno(errno, "Failed to stat /etc/localtime, ignoring: %m"); + changed = m->etc_localtime_accessible; + m->etc_localtime_accessible = false; + } else { + usec_t k; + + k = timespec_load(&st.st_mtim); + changed = !m->etc_localtime_accessible || k != m->etc_localtime_mtime; + + m->etc_localtime_mtime = k; + m->etc_localtime_accessible = true; + } + + return changed; +} + +static int manager_setup_timezone_change(Manager *m) { + _cleanup_(sd_event_source_unrefp) sd_event_source *new_event = NULL; + int r; + + assert(m); + + if (MANAGER_IS_TEST_RUN(m)) + return 0; + + /* We watch /etc/localtime for three events: change of the link count (which might mean removal from /etc even + * though another link might be kept), renames, and file close operations after writing. Note we don't bother + * with IN_DELETE_SELF, as that would just report when the inode is removed entirely, i.e. after the link count + * went to zero and all fds to it are closed. + * + * Note that we never follow symlinks here. This is a simplification, but should cover almost all cases + * correctly. + * + * Note that we create the new event source first here, before releasing the old one. This should optimize + * behaviour as this way sd-event can reuse the old watch in case the inode didn't change. */ + + r = sd_event_add_inotify(m->event, &new_event, "/etc/localtime", + IN_ATTRIB|IN_MOVE_SELF|IN_CLOSE_WRITE|IN_DONT_FOLLOW, manager_dispatch_timezone_change, m); + if (r == -ENOENT) { + /* If the file doesn't exist yet, subscribe to /etc instead, and wait until it is created either by + * O_CREATE or by rename() */ + + log_debug_errno(r, "/etc/localtime doesn't exist yet, watching /etc instead."); + r = sd_event_add_inotify(m->event, &new_event, "/etc", + IN_CREATE|IN_MOVED_TO|IN_ONLYDIR, manager_dispatch_timezone_change, m); + } + if (r < 0) + return log_error_errno(r, "Failed to create timezone change event source: %m"); + + /* Schedule this slightly earlier than the .timer event sources */ + r = sd_event_source_set_priority(new_event, SD_EVENT_PRIORITY_NORMAL-1); + if (r < 0) + return log_error_errno(r, "Failed to set priority of timezone change event sources: %m"); + + sd_event_source_unref(m->timezone_change_event_source); + m->timezone_change_event_source = TAKE_PTR(new_event); + + return 0; +} + +static int enable_special_signals(Manager *m) { + _cleanup_close_ int fd = -1; + + assert(m); + + if (MANAGER_IS_TEST_RUN(m)) + return 0; + + /* Enable that we get SIGINT on control-alt-del. In containers + * this will fail with EPERM (older) or EINVAL (newer), so + * ignore that. */ + if (reboot(RB_DISABLE_CAD) < 0 && !IN_SET(errno, EPERM, EINVAL)) + log_warning_errno(errno, "Failed to enable ctrl-alt-del handling: %m"); + + fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC); + if (fd < 0) { + /* Support systems without virtual console */ + if (fd != -ENOENT) + log_warning_errno(errno, "Failed to open /dev/tty0: %m"); + } else { + /* Enable that we get SIGWINCH on kbrequest */ + if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0) + log_warning_errno(errno, "Failed to enable kbrequest handling: %m"); + } + + return 0; +} + +#define RTSIG_IF_AVAILABLE(signum) (signum <= SIGRTMAX ? signum : -1) + +static int manager_setup_signals(Manager *m) { + struct sigaction sa = { + .sa_handler = SIG_DFL, + .sa_flags = SA_NOCLDSTOP|SA_RESTART, + }; + sigset_t mask; + int r; + + assert(m); + + assert_se(sigaction(SIGCHLD, &sa, NULL) == 0); + + /* We make liberal use of realtime signals here. On + * Linux/glibc we have 30 of them (with the exception of Linux + * on hppa, see below), between SIGRTMIN+0 ... SIGRTMIN+30 + * (aka SIGRTMAX). */ + + assert_se(sigemptyset(&mask) == 0); + sigset_add_many(&mask, + SIGCHLD, /* Child died */ + SIGTERM, /* Reexecute daemon */ + SIGHUP, /* Reload configuration */ + SIGUSR1, /* systemd/upstart: reconnect to D-Bus */ + SIGUSR2, /* systemd: dump status */ + SIGINT, /* Kernel sends us this on control-alt-del */ + SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */ + SIGPWR, /* Some kernel drivers and upsd send us this on power failure */ + + SIGRTMIN+0, /* systemd: start default.target */ + SIGRTMIN+1, /* systemd: isolate rescue.target */ + SIGRTMIN+2, /* systemd: isolate emergency.target */ + SIGRTMIN+3, /* systemd: start halt.target */ + SIGRTMIN+4, /* systemd: start poweroff.target */ + SIGRTMIN+5, /* systemd: start reboot.target */ + SIGRTMIN+6, /* systemd: start kexec.target */ + + /* ... space for more special targets ... */ + + SIGRTMIN+13, /* systemd: Immediate halt */ + SIGRTMIN+14, /* systemd: Immediate poweroff */ + SIGRTMIN+15, /* systemd: Immediate reboot */ + SIGRTMIN+16, /* systemd: Immediate kexec */ + + /* ... space for more immediate system state changes ... */ + + SIGRTMIN+20, /* systemd: enable status messages */ + SIGRTMIN+21, /* systemd: disable status messages */ + SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */ + SIGRTMIN+23, /* systemd: set log level to LOG_INFO */ + SIGRTMIN+24, /* systemd: Immediate exit (--user only) */ + + /* .. one free signal here ... */ + + /* Apparently Linux on hppa had fewer RT signals until v3.18, + * SIGRTMAX was SIGRTMIN+25, and then SIGRTMIN was lowered, + * see commit v3.17-7614-g1f25df2eff. + * + * We cannot unconditionally make use of those signals here, + * so let's use a runtime check. Since these commands are + * accessible by different means and only really a safety + * net, the missing functionality on hppa shouldn't matter. + */ + + RTSIG_IF_AVAILABLE(SIGRTMIN+26), /* systemd: set log target to journal-or-kmsg */ + RTSIG_IF_AVAILABLE(SIGRTMIN+27), /* systemd: set log target to console */ + RTSIG_IF_AVAILABLE(SIGRTMIN+28), /* systemd: set log target to kmsg */ + RTSIG_IF_AVAILABLE(SIGRTMIN+29), /* systemd: set log target to syslog-or-kmsg (obsolete) */ + + /* ... one free signal here SIGRTMIN+30 ... */ + -1); + assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); + + m->signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); + if (m->signal_fd < 0) + return -errno; + + r = sd_event_add_io(m->event, &m->signal_event_source, m->signal_fd, EPOLLIN, manager_dispatch_signal_fd, m); + if (r < 0) + return r; + + (void) sd_event_source_set_description(m->signal_event_source, "manager-signal"); + + /* Process signals a bit earlier than the rest of things, but later than notify_fd processing, so that the + * notify processing can still figure out to which process/service a message belongs, before we reap the + * process. Also, process this before handling cgroup notifications, so that we always collect child exit + * status information before detecting that there's no process in a cgroup. */ + r = sd_event_source_set_priority(m->signal_event_source, SD_EVENT_PRIORITY_NORMAL-6); + if (r < 0) + return r; + + if (MANAGER_IS_SYSTEM(m)) + return enable_special_signals(m); + + return 0; +} + +static char** sanitize_environment(char **l) { + + /* Let's remove some environment variables that we need ourselves to communicate with our clients */ + strv_env_unset_many( + l, + "EXIT_CODE", + "EXIT_STATUS", + "INVOCATION_ID", + "JOURNAL_STREAM", + "LISTEN_FDNAMES", + "LISTEN_FDS", + "LISTEN_PID", + "MAINPID", + "MANAGERPID", + "NOTIFY_SOCKET", + "PIDFILE", + "REMOTE_ADDR", + "REMOTE_PORT", + "SERVICE_RESULT", + "WATCHDOG_PID", + "WATCHDOG_USEC", + NULL); + + /* Let's order the environment alphabetically, just to make it pretty */ + strv_sort(l); + + return l; +} + +int manager_default_environment(Manager *m) { + int r; + + assert(m); + + m->transient_environment = strv_free(m->transient_environment); + + if (MANAGER_IS_SYSTEM(m)) { + /* The system manager always starts with a clean + * environment for its children. It does not import + * the kernel's or the parents' exported variables. + * + * The initial passed environment is untouched to keep + * /proc/self/environ valid; it is used for tagging + * the init process inside containers. */ + m->transient_environment = strv_new("PATH=" DEFAULT_PATH); + if (!m->transient_environment) + return log_oom(); + + /* Import locale variables LC_*= from configuration */ + (void) locale_setup(&m->transient_environment); + } else { + _cleanup_free_ char *k = NULL; + + /* The user manager passes its own environment + * along to its children, except for $PATH. */ + m->transient_environment = strv_copy(environ); + if (!m->transient_environment) + return log_oom(); + + k = strdup("PATH=" DEFAULT_USER_PATH); + if (!k) + return log_oom(); + + r = strv_env_replace(&m->transient_environment, k); + if (r < 0) + return log_oom(); + TAKE_PTR(k); + } + + sanitize_environment(m->transient_environment); + + return 0; +} + +static int manager_setup_prefix(Manager *m) { + struct table_entry { + uint64_t type; + const char *suffix; + }; + + static const struct table_entry paths_system[_EXEC_DIRECTORY_TYPE_MAX] = { + [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_SYSTEM_RUNTIME, NULL }, + [EXEC_DIRECTORY_STATE] = { SD_PATH_SYSTEM_STATE_PRIVATE, NULL }, + [EXEC_DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE, NULL }, + [EXEC_DIRECTORY_LOGS] = { SD_PATH_SYSTEM_STATE_LOGS, NULL }, + [EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_SYSTEM_CONFIGURATION, NULL }, + }; + + static const struct table_entry paths_user[_EXEC_DIRECTORY_TYPE_MAX] = { + [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_USER_RUNTIME, NULL }, + [EXEC_DIRECTORY_STATE] = { SD_PATH_USER_CONFIGURATION, NULL }, + [EXEC_DIRECTORY_CACHE] = { SD_PATH_USER_STATE_CACHE, NULL }, + [EXEC_DIRECTORY_LOGS] = { SD_PATH_USER_CONFIGURATION, "log" }, + [EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_USER_CONFIGURATION, NULL }, + }; + + const struct table_entry *p; + ExecDirectoryType i; + int r; + + assert(m); + + if (MANAGER_IS_SYSTEM(m)) + p = paths_system; + else + p = paths_user; + + for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) { + r = sd_path_home(p[i].type, p[i].suffix, &m->prefix[i]); + if (r < 0) + return r; + } + + return 0; +} + +static void manager_free_unit_name_maps(Manager *m) { + m->unit_id_map = hashmap_free(m->unit_id_map); + m->unit_name_map = hashmap_free(m->unit_name_map); + m->unit_path_cache = set_free_free(m->unit_path_cache); + m->unit_cache_mtime = 0; +} + +static int manager_setup_run_queue(Manager *m) { + int r; + + assert(m); + assert(!m->run_queue_event_source); + + r = sd_event_add_defer(m->event, &m->run_queue_event_source, manager_dispatch_run_queue, m); + if (r < 0) + return r; + + r = sd_event_source_set_priority(m->run_queue_event_source, SD_EVENT_PRIORITY_IDLE); + if (r < 0) + return r; + + r = sd_event_source_set_enabled(m->run_queue_event_source, SD_EVENT_OFF); + if (r < 0) + return r; + + (void) sd_event_source_set_description(m->run_queue_event_source, "manager-run-queue"); + + return 0; +} + +static int manager_setup_sigchld_event_source(Manager *m) { + int r; + + assert(m); + assert(!m->sigchld_event_source); + + r = sd_event_add_defer(m->event, &m->sigchld_event_source, manager_dispatch_sigchld, m); + if (r < 0) + return r; + + r = sd_event_source_set_priority(m->sigchld_event_source, SD_EVENT_PRIORITY_NORMAL-7); + if (r < 0) + return r; + + r = sd_event_source_set_enabled(m->sigchld_event_source, SD_EVENT_OFF); + if (r < 0) + return r; + + (void) sd_event_source_set_description(m->sigchld_event_source, "manager-sigchld"); + + return 0; +} + +int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager **_m) { + _cleanup_(manager_freep) Manager *m = NULL; + int r; + + assert(_m); + assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER)); + + m = new(Manager, 1); + if (!m) + return -ENOMEM; + + *m = (Manager) { + .unit_file_scope = scope, + .objective = _MANAGER_OBJECTIVE_INVALID, + + .status_unit_format = STATUS_UNIT_FORMAT_DEFAULT, + + .default_timer_accuracy_usec = USEC_PER_MINUTE, + .default_memory_accounting = MEMORY_ACCOUNTING_DEFAULT, + .default_tasks_accounting = true, + .default_tasks_max = TASKS_MAX_UNSET, + .default_timeout_start_usec = DEFAULT_TIMEOUT_USEC, + .default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC, + .default_restart_usec = DEFAULT_RESTART_USEC, + + .original_log_level = -1, + .original_log_target = _LOG_TARGET_INVALID, + + .notify_fd = -1, + .cgroups_agent_fd = -1, + .signal_fd = -1, + .time_change_fd = -1, + .user_lookup_fds = { -1, -1 }, + .private_listen_fd = -1, + .dev_autofs_fd = -1, + .cgroup_inotify_fd = -1, + .pin_cgroupfs_fd = -1, + .ask_password_inotify_fd = -1, + .idle_pipe = { -1, -1, -1, -1}, + + /* start as id #1, so that we can leave #0 around as "null-like" value */ + .current_job_id = 1, + + .have_ask_password = -EINVAL, /* we don't know */ + .first_boot = -1, + .test_run_flags = test_run_flags, + + .default_oom_policy = OOM_STOP, + }; + +#if ENABLE_EFI + if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0) + boot_timestamps(m->timestamps + MANAGER_TIMESTAMP_USERSPACE, + m->timestamps + MANAGER_TIMESTAMP_FIRMWARE, + m->timestamps + MANAGER_TIMESTAMP_LOADER); +#endif + + /* Prepare log fields we can use for structured logging */ + if (MANAGER_IS_SYSTEM(m)) { + m->unit_log_field = "UNIT="; + m->unit_log_format_string = "UNIT=%s"; + + m->invocation_log_field = "INVOCATION_ID="; + m->invocation_log_format_string = "INVOCATION_ID=%s"; + } else { + m->unit_log_field = "USER_UNIT="; + m->unit_log_format_string = "USER_UNIT=%s"; + + m->invocation_log_field = "USER_INVOCATION_ID="; + m->invocation_log_format_string = "USER_INVOCATION_ID=%s"; + } + + /* Reboot immediately if the user hits C-A-D more often than 7x per 2s */ + m->ctrl_alt_del_ratelimit = (RateLimit) { .interval = 2 * USEC_PER_SEC, .burst = 7 }; + + r = manager_default_environment(m); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&m->units, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&m->jobs, NULL); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&m->cgroup_unit, &path_hash_ops); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&m->watch_bus, &string_hash_ops); + if (r < 0) + return r; + + r = prioq_ensure_allocated(&m->run_queue, compare_job_priority); + if (r < 0) + return r; + + r = manager_setup_prefix(m); + if (r < 0) + return r; + + r = sd_event_default(&m->event); + if (r < 0) + return r; + + r = manager_setup_run_queue(m); + if (r < 0) + return r; + + if (test_run_flags == MANAGER_TEST_RUN_MINIMAL) { + m->cgroup_root = strdup(""); + if (!m->cgroup_root) + return -ENOMEM; + } else { + r = manager_setup_signals(m); + if (r < 0) + return r; + + r = manager_setup_cgroup(m); + if (r < 0) + return r; + + r = manager_setup_time_change(m); + if (r < 0) + return r; + + r = manager_read_timezone_stat(m); + if (r < 0) + return r; + + (void) manager_setup_timezone_change(m); + + r = manager_setup_sigchld_event_source(m); + if (r < 0) + return r; + } + + if (MANAGER_IS_SYSTEM(m) && test_run_flags == 0) { + r = mkdir_label("/run/systemd/units", 0755); + if (r < 0 && r != -EEXIST) + return r; + } + + m->taint_usr = + !in_initrd() && + dir_is_empty("/usr") > 0; + + /* Note that we do not set up the notify fd here. We do that after deserialization, + * since they might have gotten serialized across the reexec. */ + + *_m = TAKE_PTR(m); + + return 0; +} + +static int manager_setup_notify(Manager *m) { + int r; + + if (MANAGER_IS_TEST_RUN(m)) + return 0; + + if (m->notify_fd < 0) { + _cleanup_close_ int fd = -1; + union sockaddr_union sa = {}; + int salen; + + /* First free all secondary fields */ + m->notify_socket = mfree(m->notify_socket); + m->notify_event_source = sd_event_source_unref(m->notify_event_source); + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return log_error_errno(errno, "Failed to allocate notification socket: %m"); + + fd_inc_rcvbuf(fd, NOTIFY_RCVBUF_SIZE); + + m->notify_socket = path_join(m->prefix[EXEC_DIRECTORY_RUNTIME], "systemd/notify"); + if (!m->notify_socket) + return log_oom(); + + salen = sockaddr_un_set_path(&sa.un, m->notify_socket); + if (salen < 0) + return log_error_errno(salen, "Notify socket '%s' not valid for AF_UNIX socket address, refusing.", m->notify_socket); + + (void) mkdir_parents_label(m->notify_socket, 0755); + (void) sockaddr_un_unlink(&sa.un); + + r = bind(fd, &sa.sa, salen); + if (r < 0) + return log_error_errno(errno, "bind(%s) failed: %m", m->notify_socket); + + r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return log_error_errno(r, "SO_PASSCRED failed: %m"); + + m->notify_fd = TAKE_FD(fd); + + log_debug("Using notification socket %s", m->notify_socket); + } + + if (!m->notify_event_source) { + r = sd_event_add_io(m->event, &m->notify_event_source, m->notify_fd, EPOLLIN, manager_dispatch_notify_fd, m); + if (r < 0) + return log_error_errno(r, "Failed to allocate notify event source: %m"); + + /* Process notification messages a bit earlier than SIGCHLD, so that we can still identify to which + * service an exit message belongs. */ + r = sd_event_source_set_priority(m->notify_event_source, SD_EVENT_PRIORITY_NORMAL-8); + if (r < 0) + return log_error_errno(r, "Failed to set priority of notify event source: %m"); + + (void) sd_event_source_set_description(m->notify_event_source, "manager-notify"); + } + + return 0; +} + +static int manager_setup_cgroups_agent(Manager *m) { + + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/cgroups-agent", + }; + int r; + + /* This creates a listening socket we receive cgroups agent messages on. We do not use D-Bus for delivering + * these messages from the cgroups agent binary to PID 1, as the cgroups agent binary is very short-living, and + * each instance of it needs a new D-Bus connection. Since D-Bus connections are SOCK_STREAM/AF_UNIX, on + * overloaded systems the backlog of the D-Bus socket becomes relevant, as not more than the configured number + * of D-Bus connections may be queued until the kernel will start dropping further incoming connections, + * possibly resulting in lost cgroups agent messages. To avoid this, we'll use a private SOCK_DGRAM/AF_UNIX + * socket, where no backlog is relevant as communication may take place without an actual connect() cycle, and + * we thus won't lose messages. + * + * Note that PID 1 will forward the agent message to system bus, so that the user systemd instance may listen + * to it. The system instance hence listens on this special socket, but the user instances listen on the system + * bus for these messages. */ + + if (MANAGER_IS_TEST_RUN(m)) + return 0; + + if (!MANAGER_IS_SYSTEM(m)) + return 0; + + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) + return log_error_errno(r, "Failed to determine whether unified cgroups hierarchy is used: %m"); + if (r > 0) /* We don't need this anymore on the unified hierarchy */ + return 0; + + if (m->cgroups_agent_fd < 0) { + _cleanup_close_ int fd = -1; + + /* First free all secondary fields */ + m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source); + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return log_error_errno(errno, "Failed to allocate cgroups agent socket: %m"); + + fd_inc_rcvbuf(fd, CGROUPS_AGENT_RCVBUF_SIZE); + + (void) sockaddr_un_unlink(&sa.un); + + /* Only allow root to connect to this socket */ + RUN_WITH_UMASK(0077) + r = bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); + + m->cgroups_agent_fd = TAKE_FD(fd); + } + + if (!m->cgroups_agent_event_source) { + r = sd_event_add_io(m->event, &m->cgroups_agent_event_source, m->cgroups_agent_fd, EPOLLIN, manager_dispatch_cgroups_agent_fd, m); + if (r < 0) + return log_error_errno(r, "Failed to allocate cgroups agent event source: %m"); + + /* Process cgroups notifications early. Note that when the agent notification is received + * we'll just enqueue the unit in the cgroup empty queue, hence pick a high priority than + * that. Also see handling of cgroup inotify for the unified cgroup stuff. */ + r = sd_event_source_set_priority(m->cgroups_agent_event_source, SD_EVENT_PRIORITY_NORMAL-9); + if (r < 0) + return log_error_errno(r, "Failed to set priority of cgroups agent event source: %m"); + + (void) sd_event_source_set_description(m->cgroups_agent_event_source, "manager-cgroups-agent"); + } + + return 0; +} + +static int manager_setup_user_lookup_fd(Manager *m) { + int r; + + assert(m); + + /* Set up the socket pair used for passing UID/GID resolution results from forked off processes to PID + * 1. Background: we can't do name lookups (NSS) from PID 1, since it might involve IPC and thus activation, + * and we might hence deadlock on ourselves. Hence we do all user/group lookups asynchronously from the forked + * off processes right before executing the binaries to start. In order to be able to clean up any IPC objects + * created by a unit (see RemoveIPC=) we need to know in PID 1 the used UID/GID of the executed processes, + * hence we establish this communication channel so that forked off processes can pass their UID/GID + * information back to PID 1. The forked off processes send their resolved UID/GID to PID 1 in a simple + * datagram, along with their unit name, so that we can share one communication socket pair among all units for + * this purpose. + * + * You might wonder why we need a communication channel for this that is independent of the usual notification + * socket scheme (i.e. $NOTIFY_SOCKET). The primary difference is about trust: data sent via the $NOTIFY_SOCKET + * channel is only accepted if it originates from the right unit and if reception was enabled for it. The user + * lookup socket OTOH is only accessible by PID 1 and its children until they exec(), and always available. + * + * Note that this function is called under two circumstances: when we first initialize (in which case we + * allocate both the socket pair and the event source to listen on it), and when we deserialize after a reload + * (in which case the socket pair already exists but we still need to allocate the event source for it). */ + + if (m->user_lookup_fds[0] < 0) { + + /* Free all secondary fields */ + safe_close_pair(m->user_lookup_fds); + m->user_lookup_event_source = sd_event_source_unref(m->user_lookup_event_source); + + if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, m->user_lookup_fds) < 0) + return log_error_errno(errno, "Failed to allocate user lookup socket: %m"); + + (void) fd_inc_rcvbuf(m->user_lookup_fds[0], NOTIFY_RCVBUF_SIZE); + } + + if (!m->user_lookup_event_source) { + r = sd_event_add_io(m->event, &m->user_lookup_event_source, m->user_lookup_fds[0], EPOLLIN, manager_dispatch_user_lookup_fd, m); + if (r < 0) + return log_error_errno(errno, "Failed to allocate user lookup event source: %m"); + + /* Process even earlier than the notify event source, so that we always know first about valid UID/GID + * resolutions */ + r = sd_event_source_set_priority(m->user_lookup_event_source, SD_EVENT_PRIORITY_NORMAL-11); + if (r < 0) + return log_error_errno(errno, "Failed to set priority of user lookup event source: %m"); + + (void) sd_event_source_set_description(m->user_lookup_event_source, "user-lookup"); + } + + return 0; +} + +static unsigned manager_dispatch_cleanup_queue(Manager *m) { + Unit *u; + unsigned n = 0; + + assert(m); + + while ((u = m->cleanup_queue)) { + assert(u->in_cleanup_queue); + + unit_free(u); + n++; + } + + return n; +} + +enum { + GC_OFFSET_IN_PATH, /* This one is on the path we were traveling */ + GC_OFFSET_UNSURE, /* No clue */ + GC_OFFSET_GOOD, /* We still need this unit */ + GC_OFFSET_BAD, /* We don't need this unit anymore */ + _GC_OFFSET_MAX +}; + +static void unit_gc_mark_good(Unit *u, unsigned gc_marker) { + Unit *other; + Iterator i; + void *v; + + u->gc_marker = gc_marker + GC_OFFSET_GOOD; + + /* Recursively mark referenced units as GOOD as well */ + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REFERENCES], i) + if (other->gc_marker == gc_marker + GC_OFFSET_UNSURE) + unit_gc_mark_good(other, gc_marker); +} + +static void unit_gc_sweep(Unit *u, unsigned gc_marker) { + Unit *other; + bool is_bad; + Iterator i; + void *v; + + assert(u); + + if (IN_SET(u->gc_marker - gc_marker, + GC_OFFSET_GOOD, GC_OFFSET_BAD, GC_OFFSET_UNSURE, GC_OFFSET_IN_PATH)) + return; + + if (u->in_cleanup_queue) + goto bad; + + if (!unit_may_gc(u)) + goto good; + + u->gc_marker = gc_marker + GC_OFFSET_IN_PATH; + + is_bad = true; + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REFERENCED_BY], i) { + unit_gc_sweep(other, gc_marker); + + if (other->gc_marker == gc_marker + GC_OFFSET_GOOD) + goto good; + + if (other->gc_marker != gc_marker + GC_OFFSET_BAD) + is_bad = false; + } + + if (u->refs_by_target) { + const UnitRef *ref; + + LIST_FOREACH(refs_by_target, ref, u->refs_by_target) { + unit_gc_sweep(ref->source, gc_marker); + + if (ref->source->gc_marker == gc_marker + GC_OFFSET_GOOD) + goto good; + + if (ref->source->gc_marker != gc_marker + GC_OFFSET_BAD) + is_bad = false; + } + } + + if (is_bad) + goto bad; + + /* We were unable to find anything out about this entry, so + * let's investigate it later */ + u->gc_marker = gc_marker + GC_OFFSET_UNSURE; + unit_add_to_gc_queue(u); + return; + +bad: + /* We definitely know that this one is not useful anymore, so + * let's mark it for deletion */ + u->gc_marker = gc_marker + GC_OFFSET_BAD; + unit_add_to_cleanup_queue(u); + return; + +good: + unit_gc_mark_good(u, gc_marker); +} + +static unsigned manager_dispatch_gc_unit_queue(Manager *m) { + unsigned n = 0, gc_marker; + Unit *u; + + assert(m); + + /* log_debug("Running GC..."); */ + + m->gc_marker += _GC_OFFSET_MAX; + if (m->gc_marker + _GC_OFFSET_MAX <= _GC_OFFSET_MAX) + m->gc_marker = 1; + + gc_marker = m->gc_marker; + + while ((u = m->gc_unit_queue)) { + assert(u->in_gc_queue); + + unit_gc_sweep(u, gc_marker); + + LIST_REMOVE(gc_queue, m->gc_unit_queue, u); + u->in_gc_queue = false; + + n++; + + if (IN_SET(u->gc_marker - gc_marker, + GC_OFFSET_BAD, GC_OFFSET_UNSURE)) { + if (u->id) + log_unit_debug(u, "Collecting."); + u->gc_marker = gc_marker + GC_OFFSET_BAD; + unit_add_to_cleanup_queue(u); + } + } + + return n; +} + +static unsigned manager_dispatch_gc_job_queue(Manager *m) { + unsigned n = 0; + Job *j; + + assert(m); + + while ((j = m->gc_job_queue)) { + assert(j->in_gc_queue); + + LIST_REMOVE(gc_queue, m->gc_job_queue, j); + j->in_gc_queue = false; + + n++; + + if (!job_may_gc(j)) + continue; + + log_unit_debug(j->unit, "Collecting job."); + (void) job_finish_and_invalidate(j, JOB_COLLECTED, false, false); + } + + return n; +} + +static unsigned manager_dispatch_stop_when_unneeded_queue(Manager *m) { + unsigned n = 0; + Unit *u; + int r; + + assert(m); + + while ((u = m->stop_when_unneeded_queue)) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + assert(m->stop_when_unneeded_queue); + + assert(u->in_stop_when_unneeded_queue); + LIST_REMOVE(stop_when_unneeded_queue, m->stop_when_unneeded_queue, u); + u->in_stop_when_unneeded_queue = false; + + n++; + + if (!unit_is_unneeded(u)) + continue; + + log_unit_debug(u, "Unit is not needed anymore."); + + /* If stopping a unit fails continuously we might enter a stop loop here, hence stop acting on the + * service being unnecessary after a while. */ + + if (!ratelimit_below(&u->auto_stop_ratelimit)) { + log_unit_warning(u, "Unit not needed anymore, but not stopping since we tried this too often recently."); + continue; + } + + /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ + r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, NULL, &error, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r)); + } + + return n; +} + +static void manager_clear_jobs_and_units(Manager *m) { + Unit *u; + + assert(m); + + while ((u = hashmap_first(m->units))) + unit_free(u); + + manager_dispatch_cleanup_queue(m); + + assert(!m->load_queue); + assert(prioq_isempty(m->run_queue)); + assert(!m->dbus_unit_queue); + assert(!m->dbus_job_queue); + assert(!m->cleanup_queue); + assert(!m->gc_unit_queue); + assert(!m->gc_job_queue); + assert(!m->stop_when_unneeded_queue); + + assert(hashmap_isempty(m->jobs)); + assert(hashmap_isempty(m->units)); + + m->n_on_console = 0; + m->n_running_jobs = 0; + m->n_installed_jobs = 0; + m->n_failed_jobs = 0; +} + +Manager* manager_free(Manager *m) { + ExecDirectoryType dt; + UnitType c; + + if (!m) + return NULL; + + manager_clear_jobs_and_units(m); + + for (c = 0; c < _UNIT_TYPE_MAX; c++) + if (unit_vtable[c]->shutdown) + unit_vtable[c]->shutdown(m); + + /* Keep the cgroup hierarchy in place except when we know we are going down for good */ + manager_shutdown_cgroup(m, IN_SET(m->objective, MANAGER_EXIT, MANAGER_REBOOT, MANAGER_POWEROFF, MANAGER_HALT, MANAGER_KEXEC)); + + lookup_paths_flush_generator(&m->lookup_paths); + + bus_done(m); + + exec_runtime_vacuum(m); + hashmap_free(m->exec_runtime_by_id); + + dynamic_user_vacuum(m, false); + hashmap_free(m->dynamic_users); + + hashmap_free(m->units); + hashmap_free(m->units_by_invocation_id); + hashmap_free(m->jobs); + hashmap_free(m->watch_pids); + hashmap_free(m->watch_bus); + + prioq_free(m->run_queue); + + set_free(m->startup_units); + set_free(m->failed_units); + + sd_event_source_unref(m->signal_event_source); + sd_event_source_unref(m->sigchld_event_source); + sd_event_source_unref(m->notify_event_source); + sd_event_source_unref(m->cgroups_agent_event_source); + sd_event_source_unref(m->time_change_event_source); + sd_event_source_unref(m->timezone_change_event_source); + sd_event_source_unref(m->jobs_in_progress_event_source); + sd_event_source_unref(m->run_queue_event_source); + sd_event_source_unref(m->user_lookup_event_source); + sd_event_source_unref(m->sync_bus_names_event_source); + + safe_close(m->signal_fd); + safe_close(m->notify_fd); + safe_close(m->cgroups_agent_fd); + safe_close(m->time_change_fd); + safe_close_pair(m->user_lookup_fds); + + manager_close_ask_password(m); + + manager_close_idle_pipe(m); + + sd_event_unref(m->event); + + free(m->notify_socket); + + lookup_paths_free(&m->lookup_paths); + strv_free(m->transient_environment); + strv_free(m->client_environment); + + hashmap_free(m->cgroup_unit); + manager_free_unit_name_maps(m); + + free(m->switch_root); + free(m->switch_root_init); + + rlimit_free_all(m->rlimit); + + assert(hashmap_isempty(m->units_requiring_mounts_for)); + hashmap_free(m->units_requiring_mounts_for); + + hashmap_free(m->uid_refs); + hashmap_free(m->gid_refs); + + for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) + m->prefix[dt] = mfree(m->prefix[dt]); + + return mfree(m); +} + +static void manager_enumerate_perpetual(Manager *m) { + UnitType c; + + assert(m); + + if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL) + return; + + /* Let's ask every type to load all units from disk/kernel that it might know */ + for (c = 0; c < _UNIT_TYPE_MAX; c++) { + if (!unit_type_supported(c)) { + log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c)); + continue; + } + + if (unit_vtable[c]->enumerate_perpetual) + unit_vtable[c]->enumerate_perpetual(m); + } +} + +static void manager_enumerate(Manager *m) { + UnitType c; + + assert(m); + + if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL) + return; + + /* Let's ask every type to load all units from disk/kernel that it might know */ + for (c = 0; c < _UNIT_TYPE_MAX; c++) { + if (!unit_type_supported(c)) { + log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c)); + continue; + } + + if (unit_vtable[c]->enumerate) + unit_vtable[c]->enumerate(m); + } + + manager_dispatch_load_queue(m); +} + +static void manager_coldplug(Manager *m) { + Iterator i; + Unit *u; + char *k; + int r; + + assert(m); + + log_debug("Invoking unit coldplug() handlers…"); + + /* Let's place the units back into their deserialized state */ + HASHMAP_FOREACH_KEY(u, k, m->units, i) { + + /* ignore aliases */ + if (u->id != k) + continue; + + r = unit_coldplug(u); + if (r < 0) + log_warning_errno(r, "We couldn't coldplug %s, proceeding anyway: %m", u->id); + } +} + +static void manager_catchup(Manager *m) { + Iterator i; + Unit *u; + char *k; + + assert(m); + + log_debug("Invoking unit catchup() handlers…"); + + /* Let's catch up on any state changes that happened while we were reloading/reexecing */ + HASHMAP_FOREACH_KEY(u, k, m->units, i) { + + /* ignore aliases */ + if (u->id != k) + continue; + + unit_catchup(u); + } +} + +static void manager_distribute_fds(Manager *m, FDSet *fds) { + Iterator i; + Unit *u; + + assert(m); + + HASHMAP_FOREACH(u, m->units, i) { + + if (fdset_size(fds) <= 0) + break; + + if (!UNIT_VTABLE(u)->distribute_fds) + continue; + + UNIT_VTABLE(u)->distribute_fds(u, fds); + } +} + +static bool manager_dbus_is_running(Manager *m, bool deserialized) { + Unit *u; + + assert(m); + + /* This checks whether the dbus instance we are supposed to expose our APIs on is up. We check both the socket + * and the service unit. If the 'deserialized' parameter is true we'll check the deserialized state of the unit + * rather than the current one. */ + + if (MANAGER_IS_TEST_RUN(m)) + return false; + + u = manager_get_unit(m, SPECIAL_DBUS_SOCKET); + if (!u) + return false; + if ((deserialized ? SOCKET(u)->deserialized_state : SOCKET(u)->state) != SOCKET_RUNNING) + return false; + + u = manager_get_unit(m, SPECIAL_DBUS_SERVICE); + if (!u) + return false; + if (!IN_SET((deserialized ? SERVICE(u)->deserialized_state : SERVICE(u)->state), SERVICE_RUNNING, SERVICE_RELOAD)) + return false; + + return true; +} + +static void manager_setup_bus(Manager *m) { + assert(m); + + /* Let's set up our private bus connection now, unconditionally */ + (void) bus_init_private(m); + + /* If we are in --user mode also connect to the system bus now */ + if (MANAGER_IS_USER(m)) + (void) bus_init_system(m); + + /* Let's connect to the bus now, but only if the unit is supposed to be up */ + if (manager_dbus_is_running(m, MANAGER_IS_RELOADING(m))) { + (void) bus_init_api(m); + + if (MANAGER_IS_SYSTEM(m)) + (void) bus_init_system(m); + } +} + +static void manager_preset_all(Manager *m) { + int r; + + assert(m); + + if (m->first_boot <= 0) + return; + + if (!MANAGER_IS_SYSTEM(m)) + return; + + if (MANAGER_IS_TEST_RUN(m)) + return; + + /* If this is the first boot, and we are in the host system, then preset everything */ + r = unit_file_preset_all(UNIT_FILE_SYSTEM, 0, NULL, UNIT_FILE_PRESET_ENABLE_ONLY, NULL, 0); + if (r < 0) + log_full_errno(r == -EEXIST ? LOG_NOTICE : LOG_WARNING, r, + "Failed to populate /etc with preset unit settings, ignoring: %m"); + else + log_info("Populated /etc with preset unit settings."); +} + +static void manager_vacuum(Manager *m) { + assert(m); + + /* Release any dynamic users no longer referenced */ + dynamic_user_vacuum(m, true); + + /* Release any references to UIDs/GIDs no longer referenced, and destroy any IPC owned by them */ + manager_vacuum_uid_refs(m); + manager_vacuum_gid_refs(m); + + /* Release any runtimes no longer referenced */ + exec_runtime_vacuum(m); +} + +static void manager_ready(Manager *m) { + assert(m); + + /* After having loaded everything, do the final round of catching up with what might have changed */ + + m->objective = MANAGER_OK; /* Tell everyone we are up now */ + + /* It might be safe to log to the journal now and connect to dbus */ + manager_recheck_journal(m); + manager_recheck_dbus(m); + + /* Sync current state of bus names with our set of listening units */ + (void) manager_enqueue_sync_bus_names(m); + + /* Let's finally catch up with any changes that took place while we were reloading/reexecing */ + manager_catchup(m); + + m->honor_device_enumeration = true; +} + +static Manager* manager_reloading_start(Manager *m) { + m->n_reloading++; + return m; +} +static void manager_reloading_stopp(Manager **m) { + if (*m) { + assert((*m)->n_reloading > 0); + (*m)->n_reloading--; + } +} + +int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { + int r; + + assert(m); + + /* If we are running in test mode, we still want to run the generators, + * but we should not touch the real generator directories. */ + r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, + MANAGER_IS_TEST_RUN(m) ? LOOKUP_PATHS_TEMPORARY_GENERATED : 0, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to initialize path lookup table: %m"); + + dual_timestamp_get(m->timestamps + manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_GENERATORS_START)); + r = manager_run_environment_generators(m); + if (r >= 0) + r = manager_run_generators(m); + dual_timestamp_get(m->timestamps + manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_GENERATORS_FINISH)); + if (r < 0) + return r; + + manager_preset_all(m); + + lookup_paths_log(&m->lookup_paths); + + { + /* This block is (optionally) done with the reloading counter bumped */ + _cleanup_(manager_reloading_stopp) Manager *reloading = NULL; + + /* If we will deserialize make sure that during enumeration this is already known, so we increase the + * counter here already */ + if (serialization) + reloading = manager_reloading_start(m); + + /* First, enumerate what we can from all config files */ + dual_timestamp_get(m->timestamps + manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_UNITS_LOAD_START)); + manager_enumerate_perpetual(m); + manager_enumerate(m); + dual_timestamp_get(m->timestamps + manager_timestamp_initrd_mangle(MANAGER_TIMESTAMP_UNITS_LOAD_FINISH)); + + /* Second, deserialize if there is something to deserialize */ + if (serialization) { + r = manager_deserialize(m, serialization, fds); + if (r < 0) + return log_error_errno(r, "Deserialization failed: %m"); + } + + /* Any fds left? Find some unit which wants them. This is useful to allow container managers to pass + * some file descriptors to us pre-initialized. This enables socket-based activation of entire + * containers. */ + manager_distribute_fds(m, fds); + + /* We might have deserialized the notify fd, but if we didn't then let's create the bus now */ + r = manager_setup_notify(m); + if (r < 0) + /* No sense to continue without notifications, our children would fail anyway. */ + return r; + + r = manager_setup_cgroups_agent(m); + if (r < 0) + /* Likewise, no sense to continue without empty cgroup notifications. */ + return r; + + r = manager_setup_user_lookup_fd(m); + if (r < 0) + /* This shouldn't fail, except if things are really broken. */ + return r; + + /* Connect to the bus if we are good for it */ + manager_setup_bus(m); + + /* Now that we are connected to all possible buses, let's deserialize who is tracking us. */ + r = bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed); + if (r < 0) + log_warning_errno(r, "Failed to deserialized tracked clients, ignoring: %m"); + m->deserialized_subscribed = strv_free(m->deserialized_subscribed); + + /* Third, fire things up! */ + manager_coldplug(m); + + /* Clean up runtime objects */ + manager_vacuum(m); + + if (serialization) + /* Let's wait for the UnitNew/JobNew messages being sent, before we notify that the + * reload is finished */ + m->send_reloading_done = true; + } + + manager_ready(m); + + return 0; +} + +int manager_add_job( + Manager *m, + JobType type, + Unit *unit, + JobMode mode, + Set *affected_jobs, + sd_bus_error *error, + Job **ret) { + + Transaction *tr; + int r; + + assert(m); + assert(type < _JOB_TYPE_MAX); + assert(unit); + assert(mode < _JOB_MODE_MAX); + + if (mode == JOB_ISOLATE && type != JOB_START) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start."); + + if (mode == JOB_ISOLATE && !unit->allow_isolate) + return sd_bus_error_setf(error, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated."); + + if (mode == JOB_TRIGGERING && type != JOB_STOP) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "--job-mode=triggering is only valid for stop."); + + log_unit_debug(unit, "Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode)); + + type = job_type_collapse(type, unit); + + tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY); + if (!tr) + return -ENOMEM; + + r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, false, + IN_SET(mode, JOB_IGNORE_DEPENDENCIES, JOB_IGNORE_REQUIREMENTS), + mode == JOB_IGNORE_DEPENDENCIES, error); + if (r < 0) + goto tr_abort; + + if (mode == JOB_ISOLATE) { + r = transaction_add_isolate_jobs(tr, m); + if (r < 0) + goto tr_abort; + } + + if (mode == JOB_TRIGGERING) { + r = transaction_add_triggering_jobs(tr, unit); + if (r < 0) + goto tr_abort; + } + + r = transaction_activate(tr, m, mode, affected_jobs, error); + if (r < 0) + goto tr_abort; + + log_unit_debug(unit, + "Enqueued job %s/%s as %u", unit->id, + job_type_to_string(type), (unsigned) tr->anchor_job->id); + + if (ret) + *ret = tr->anchor_job; + + transaction_free(tr); + return 0; + +tr_abort: + transaction_abort(tr); + transaction_free(tr); + return r; +} + +int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **ret) { + Unit *unit = NULL; /* just to appease gcc, initialization is not really necessary */ + int r; + + assert(m); + assert(type < _JOB_TYPE_MAX); + assert(name); + assert(mode < _JOB_MODE_MAX); + + r = manager_load_unit(m, name, NULL, NULL, &unit); + if (r < 0) + return r; + assert(unit); + + return manager_add_job(m, type, unit, mode, affected_jobs, e, ret); +} + +int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(m); + assert(type < _JOB_TYPE_MAX); + assert(name); + assert(mode < _JOB_MODE_MAX); + + r = manager_add_job_by_name(m, type, name, mode, affected_jobs, &error, ret); + if (r < 0) + return log_warning_errno(r, "Failed to enqueue %s job for %s: %s", job_mode_to_string(mode), name, bus_error_message(&error, r)); + + return r; +} + +int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e) { + int r; + Transaction *tr; + + assert(m); + assert(unit); + assert(mode < _JOB_MODE_MAX); + assert(mode != JOB_ISOLATE); /* Isolate is only valid for start */ + + tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY); + if (!tr) + return -ENOMEM; + + /* We need an anchor job */ + r = transaction_add_job_and_dependencies(tr, JOB_NOP, unit, NULL, false, false, true, true, e); + if (r < 0) + goto tr_abort; + + /* Failure in adding individual dependencies is ignored, so this always succeeds. */ + transaction_add_propagate_reload_jobs(tr, unit, tr->anchor_job, mode == JOB_IGNORE_DEPENDENCIES, e); + + r = transaction_activate(tr, m, mode, NULL, e); + if (r < 0) + goto tr_abort; + + transaction_free(tr); + return 0; + +tr_abort: + transaction_abort(tr); + transaction_free(tr); + return r; +} + +Job *manager_get_job(Manager *m, uint32_t id) { + assert(m); + + return hashmap_get(m->jobs, UINT32_TO_PTR(id)); +} + +Unit *manager_get_unit(Manager *m, const char *name) { + assert(m); + assert(name); + + return hashmap_get(m->units, name); +} + +static int manager_dispatch_target_deps_queue(Manager *m) { + Unit *u; + unsigned k; + int r = 0; + + static const UnitDependency deps[] = { + UNIT_REQUIRED_BY, + UNIT_REQUISITE_OF, + UNIT_WANTED_BY, + UNIT_BOUND_BY + }; + + assert(m); + + while ((u = m->target_deps_queue)) { + assert(u->in_target_deps_queue); + + LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u); + u->in_target_deps_queue = false; + + for (k = 0; k < ELEMENTSOF(deps); k++) { + Unit *target; + Iterator i; + void *v; + + HASHMAP_FOREACH_KEY(v, target, u->dependencies[deps[k]], i) { + r = unit_add_default_target_dependency(u, target); + if (r < 0) + return r; + } + } + } + + return r; +} + +unsigned manager_dispatch_load_queue(Manager *m) { + Unit *u; + unsigned n = 0; + + assert(m); + + /* Make sure we are not run recursively */ + if (m->dispatching_load_queue) + return 0; + + m->dispatching_load_queue = true; + + /* Dispatches the load queue. Takes a unit from the queue and + * tries to load its data until the queue is empty */ + + while ((u = m->load_queue)) { + assert(u->in_load_queue); + + unit_load(u); + n++; + } + + m->dispatching_load_queue = false; + + /* Dispatch the units waiting for their target dependencies to be added now, as all targets that we know about + * should be loaded and have aliases resolved */ + (void) manager_dispatch_target_deps_queue(m); + + return n; +} + +int manager_load_unit_prepare( + Manager *m, + const char *name, + const char *path, + sd_bus_error *e, + Unit **_ret) { + + _cleanup_(unit_freep) Unit *cleanup_ret = NULL; + Unit *ret; + UnitType t; + int r; + + assert(m); + assert(name || path); + assert(_ret); + + /* This will prepare the unit for loading, but not actually + * load anything from disk. */ + + if (path && !is_path(path)) + return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path); + + if (!name) + name = basename(path); + + t = unit_name_to_type(name); + + if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) { + if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) + return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is missing the instance name.", name); + + return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name); + } + + ret = manager_get_unit(m, name); + if (ret) { + *_ret = ret; + return 1; + } + + ret = cleanup_ret = unit_new(m, unit_vtable[t]->object_size); + if (!ret) + return -ENOMEM; + + if (path) { + ret->fragment_path = strdup(path); + if (!ret->fragment_path) + return -ENOMEM; + } + + r = unit_add_name(ret, name); + if (r < 0) + return r; + + unit_add_to_load_queue(ret); + unit_add_to_dbus_queue(ret); + unit_add_to_gc_queue(ret); + + *_ret = ret; + cleanup_ret = NULL; + + return 0; +} + +int manager_load_unit( + Manager *m, + const char *name, + const char *path, + sd_bus_error *e, + Unit **_ret) { + + int r; + + assert(m); + assert(_ret); + + /* This will load the service information files, but not actually + * start any services or anything. */ + + r = manager_load_unit_prepare(m, name, path, e, _ret); + if (r != 0) + return r; + + manager_dispatch_load_queue(m); + + *_ret = unit_follow_merge(*_ret); + return 0; +} + +int manager_load_startable_unit_or_warn( + Manager *m, + const char *name, + const char *path, + Unit **ret) { + + /* Load a unit, make sure it loaded fully and is not masked. */ + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + Unit *unit; + int r; + + r = manager_load_unit(m, name, path, &error, &unit); + if (r < 0) + return log_error_errno(r, "Failed to load %s %s: %s", + name ? "unit" : "unit file", name ?: path, + bus_error_message(&error, r)); + + r = bus_unit_validate_load_state(unit, &error); + if (r < 0) + return log_error_errno(r, "%s", bus_error_message(&error, r)); + + *ret = unit; + return 0; +} + +void manager_dump_jobs(Manager *s, FILE *f, const char *prefix) { + Iterator i; + Job *j; + + assert(s); + assert(f); + + HASHMAP_FOREACH(j, s->jobs, i) + job_dump(j, f, prefix); +} + +void manager_dump_units(Manager *s, FILE *f, const char *prefix) { + Iterator i; + Unit *u; + const char *t; + + assert(s); + assert(f); + + HASHMAP_FOREACH_KEY(u, t, s->units, i) + if (u->id == t) + unit_dump(u, f, prefix); +} + +void manager_dump(Manager *m, FILE *f, const char *prefix) { + ManagerTimestamp q; + + assert(m); + assert(f); + + for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { + const dual_timestamp *t = m->timestamps + q; + char buf[CONST_MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)]; + + if (dual_timestamp_is_set(t)) + fprintf(f, "%sTimestamp %s: %s\n", + strempty(prefix), + manager_timestamp_to_string(q), + timestamp_is_set(t->realtime) ? format_timestamp(buf, sizeof buf, t->realtime) : + format_timespan(buf, sizeof buf, t->monotonic, 1)); + } + + manager_dump_units(m, f, prefix); + manager_dump_jobs(m, f, prefix); +} + +int manager_get_dump_string(Manager *m, char **ret) { + _cleanup_free_ char *dump = NULL; + _cleanup_fclose_ FILE *f = NULL; + size_t size; + int r; + + assert(m); + assert(ret); + + f = open_memstream_unlocked(&dump, &size); + if (!f) + return -errno; + + manager_dump(m, f, NULL); + + r = fflush_and_check(f); + if (r < 0) + return r; + + f = safe_fclose(f); + + *ret = TAKE_PTR(dump); + + return 0; +} + +void manager_clear_jobs(Manager *m) { + Job *j; + + assert(m); + + while ((j = hashmap_first(m->jobs))) + /* No need to recurse. We're cancelling all jobs. */ + job_finish_and_invalidate(j, JOB_CANCELED, false, false); +} + +void manager_unwatch_pid(Manager *m, pid_t pid) { + assert(m); + + /* First let's drop the unit keyed as "pid". */ + (void) hashmap_remove(m->watch_pids, PID_TO_PTR(pid)); + + /* Then, let's also drop the array keyed by -pid. */ + free(hashmap_remove(m->watch_pids, PID_TO_PTR(-pid))); +} + +static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) { + Manager *m = userdata; + Job *j; + + assert(source); + assert(m); + + while ((j = prioq_peek(m->run_queue))) { + assert(j->installed); + assert(j->in_run_queue); + + (void) job_run_and_invalidate(j); + } + + if (m->n_running_jobs > 0) + manager_watch_jobs_in_progress(m); + + if (m->n_on_console > 0) + manager_watch_idle_pipe(m); + + return 1; +} + +static unsigned manager_dispatch_dbus_queue(Manager *m) { + unsigned n = 0, budget; + Unit *u; + Job *j; + + assert(m); + + /* When we are reloading, let's not wait with generating signals, since we need to exit the manager as quickly + * as we can. There's no point in throttling generation of signals in that case. */ + if (MANAGER_IS_RELOADING(m) || m->send_reloading_done || m->pending_reload_message) + budget = (unsigned) -1; /* infinite budget in this case */ + else { + /* Anything to do at all? */ + if (!m->dbus_unit_queue && !m->dbus_job_queue) + return 0; + + /* Do we have overly many messages queued at the moment? If so, let's not enqueue more on top, let's + * sit this cycle out, and process things in a later cycle when the queues got a bit emptier. */ + if (manager_bus_n_queued_write(m) > MANAGER_BUS_BUSY_THRESHOLD) + return 0; + + /* Only process a certain number of units/jobs per event loop iteration. Even if the bus queue wasn't + * overly full before this call we shouldn't increase it in size too wildly in one step, and we + * shouldn't monopolize CPU time with generating these messages. Note the difference in counting of + * this "budget" and the "threshold" above: the "budget" is decreased only once per generated message, + * regardless how many buses/direct connections it is enqueued on, while the "threshold" is applied to + * each queued instance of bus message, i.e. if the same message is enqueued to five buses/direct + * connections it will be counted five times. This difference in counting ("references" + * vs. "instances") is primarily a result of the fact that it's easier to implement it this way, + * however it also reflects the thinking that the "threshold" should put a limit on used queue memory, + * i.e. space, while the "budget" should put a limit on time. Also note that the "threshold" is + * currently chosen much higher than the "budget". */ + budget = MANAGER_BUS_MESSAGE_BUDGET; + } + + while (budget != 0 && (u = m->dbus_unit_queue)) { + + assert(u->in_dbus_queue); + + bus_unit_send_change_signal(u); + n++; + + if (budget != (unsigned) -1) + budget--; + } + + while (budget != 0 && (j = m->dbus_job_queue)) { + assert(j->in_dbus_queue); + + bus_job_send_change_signal(j); + n++; + + if (budget != (unsigned) -1) + budget--; + } + + if (m->send_reloading_done) { + m->send_reloading_done = false; + bus_manager_send_reloading(m, false); + n++; + } + + if (m->pending_reload_message) { + bus_send_pending_reload_message(m); + n++; + } + + return n; +} + +static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + char buf[PATH_MAX]; + ssize_t n; + + n = recv(fd, buf, sizeof(buf), 0); + if (n < 0) + return log_error_errno(errno, "Failed to read cgroups agent message: %m"); + if (n == 0) { + log_error("Got zero-length cgroups agent message, ignoring."); + return 0; + } + if ((size_t) n >= sizeof(buf)) { + log_error("Got overly long cgroups agent message, ignoring."); + return 0; + } + + if (memchr(buf, 0, n)) { + log_error("Got cgroups agent message with embedded NUL byte, ignoring."); + return 0; + } + buf[n] = 0; + + manager_notify_cgroup_empty(m, buf); + (void) bus_forward_agent_released(m, buf); + + return 0; +} + +static void manager_invoke_notify_message( + Manager *m, + Unit *u, + const struct ucred *ucred, + const char *buf, + FDSet *fds) { + + assert(m); + assert(u); + assert(ucred); + assert(buf); + + if (u->notifygen == m->notifygen) /* Already invoked on this same unit in this same iteration? */ + return; + u->notifygen = m->notifygen; + + if (UNIT_VTABLE(u)->notify_message) { + _cleanup_strv_free_ char **tags = NULL; + + tags = strv_split(buf, NEWLINE); + if (!tags) { + log_oom(); + return; + } + + UNIT_VTABLE(u)->notify_message(u, ucred, tags, fds); + + } else if (DEBUG_LOGGING) { + _cleanup_free_ char *x = NULL, *y = NULL; + + x = ellipsize(buf, 20, 90); + if (x) + y = cescape(x); + + log_unit_debug(u, "Got notification message \"%s\", ignoring.", strnull(y)); + } +} + +static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + + _cleanup_fdset_free_ FDSet *fds = NULL; + Manager *m = userdata; + char buf[NOTIFY_BUFFER_MAX+1]; + struct iovec iovec = { + .iov_base = buf, + .iov_len = sizeof(buf)-1, + }; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + + CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)]; + } control = {}; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + + struct cmsghdr *cmsg; + struct ucred *ucred = NULL; + _cleanup_free_ Unit **array_copy = NULL; + Unit *u1, *u2, **array; + int r, *fd_array = NULL; + size_t n_fds = 0; + bool found = false; + ssize_t n; + + assert(m); + assert(m->notify_fd == fd); + + if (revents != EPOLLIN) { + log_warning("Got unexpected poll event for notify fd."); + return 0; + } + + n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; /* Spurious wakeup, try again */ + + /* If this is any other, real error, then let's stop processing this socket. This of course means we + * won't take notification messages anymore, but that's still better than busy looping around this: + * being woken up over and over again but being unable to actually read the message off the socket. */ + return log_error_errno(errno, "Failed to receive notification message: %m"); + } + + CMSG_FOREACH(cmsg, &msghdr) { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + + fd_array = (int*) CMSG_DATA(cmsg); + n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); + + } else if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + + ucred = (struct ucred*) CMSG_DATA(cmsg); + } + } + + if (n_fds > 0) { + assert(fd_array); + + r = fdset_new_array(&fds, fd_array, n_fds); + if (r < 0) { + close_many(fd_array, n_fds); + log_oom(); + return 0; + } + } + + if (!ucred || !pid_is_valid(ucred->pid)) { + log_warning("Received notify message without valid credentials. Ignoring."); + return 0; + } + + if ((size_t) n >= sizeof(buf) || (msghdr.msg_flags & MSG_TRUNC)) { + log_warning("Received notify message exceeded maximum size. Ignoring."); + return 0; + } + + /* As extra safety check, let's make sure the string we get doesn't contain embedded NUL bytes. We permit one + * trailing NUL byte in the message, but don't expect it. */ + if (n > 1 && memchr(buf, 0, n-1)) { + log_warning("Received notify message with embedded NUL bytes. Ignoring."); + return 0; + } + + /* Make sure it's NUL-terminated. */ + buf[n] = 0; + + /* Increase the generation counter used for filtering out duplicate unit invocations. */ + m->notifygen++; + + /* Notify every unit that might be interested, which might be multiple. */ + u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid); + u2 = hashmap_get(m->watch_pids, PID_TO_PTR(ucred->pid)); + array = hashmap_get(m->watch_pids, PID_TO_PTR(-ucred->pid)); + if (array) { + size_t k = 0; + + while (array[k]) + k++; + + array_copy = newdup(Unit*, array, k+1); + if (!array_copy) + log_oom(); + } + /* And now invoke the per-unit callbacks. Note that manager_invoke_notify_message() will handle duplicate units + * make sure we only invoke each unit's handler once. */ + if (u1) { + manager_invoke_notify_message(m, u1, ucred, buf, fds); + found = true; + } + if (u2) { + manager_invoke_notify_message(m, u2, ucred, buf, fds); + found = true; + } + if (array_copy) + for (size_t i = 0; array_copy[i]; i++) { + manager_invoke_notify_message(m, array_copy[i], ucred, buf, fds); + found = true; + } + + if (!found) + log_warning("Cannot find unit for notify message of PID "PID_FMT", ignoring.", ucred->pid); + + if (fdset_size(fds) > 0) + log_warning("Got extra auxiliary fds with notification message, closing them."); + + return 0; +} + +static void manager_invoke_sigchld_event( + Manager *m, + Unit *u, + const siginfo_t *si) { + + assert(m); + assert(u); + assert(si); + + /* Already invoked the handler of this unit in this iteration? Then don't process this again */ + if (u->sigchldgen == m->sigchldgen) + return; + u->sigchldgen = m->sigchldgen; + + log_unit_debug(u, "Child "PID_FMT" belongs to %s.", si->si_pid, u->id); + unit_unwatch_pid(u, si->si_pid); + + if (UNIT_VTABLE(u)->sigchld_event) + UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status); +} + +static int manager_dispatch_sigchld(sd_event_source *source, void *userdata) { + Manager *m = userdata; + siginfo_t si = {}; + int r; + + assert(source); + assert(m); + + /* First we call waitid() for a PID and do not reap the zombie. That way we can still access /proc/$PID for it + * while it is a zombie. */ + + if (waitid(P_ALL, 0, &si, WEXITED|WNOHANG|WNOWAIT) < 0) { + + if (errno != ECHILD) + log_error_errno(errno, "Failed to peek for child with waitid(), ignoring: %m"); + + goto turn_off; + } + + if (si.si_pid <= 0) + goto turn_off; + + if (IN_SET(si.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED)) { + _cleanup_free_ Unit **array_copy = NULL; + _cleanup_free_ char *name = NULL; + Unit *u1, *u2, **array; + + (void) get_process_comm(si.si_pid, &name); + + log_debug("Child "PID_FMT" (%s) died (code=%s, status=%i/%s)", + si.si_pid, strna(name), + sigchld_code_to_string(si.si_code), + si.si_status, + strna(si.si_code == CLD_EXITED + ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL) + : signal_to_string(si.si_status))); + + /* Increase the generation counter used for filtering out duplicate unit invocations */ + m->sigchldgen++; + + /* And now figure out the unit this belongs to, it might be multiple... */ + u1 = manager_get_unit_by_pid_cgroup(m, si.si_pid); + u2 = hashmap_get(m->watch_pids, PID_TO_PTR(si.si_pid)); + array = hashmap_get(m->watch_pids, PID_TO_PTR(-si.si_pid)); + if (array) { + size_t n = 0; + + /* Count how many entries the array has */ + while (array[n]) + n++; + + /* Make a copy of the array so that we don't trip up on the array changing beneath us */ + array_copy = newdup(Unit*, array, n+1); + if (!array_copy) + log_oom(); + } + + /* Finally, execute them all. Note that u1, u2 and the array might contain duplicates, but + * that's fine, manager_invoke_sigchld_event() will ensure we only invoke the handlers once for + * each iteration. */ + if (u1) { + /* We check for oom condition, in case we got SIGCHLD before the oom notification. + * We only do this for the cgroup the PID belonged to. */ + (void) unit_check_oom(u1); + + manager_invoke_sigchld_event(m, u1, &si); + } + if (u2) + manager_invoke_sigchld_event(m, u2, &si); + if (array_copy) + for (size_t i = 0; array_copy[i]; i++) + manager_invoke_sigchld_event(m, array_copy[i], &si); + } + + /* And now, we actually reap the zombie. */ + if (waitid(P_PID, si.si_pid, &si, WEXITED) < 0) { + log_error_errno(errno, "Failed to dequeue child, ignoring: %m"); + return 0; + } + + return 0; + +turn_off: + /* All children processed for now, turn off event source */ + + r = sd_event_source_set_enabled(m->sigchld_event_source, SD_EVENT_OFF); + if (r < 0) + return log_error_errno(r, "Failed to disable SIGCHLD event source: %m"); + + return 0; +} + +static void manager_start_target(Manager *m, const char *name, JobMode mode) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + log_debug("Activating special unit %s", name); + + r = manager_add_job_by_name(m, JOB_START, name, mode, NULL, &error, NULL); + if (r < 0) + log_error("Failed to enqueue %s job: %s", name, bus_error_message(&error, r)); +} + +static void manager_handle_ctrl_alt_del(Manager *m) { + /* If the user presses C-A-D more than + * 7 times within 2s, we reboot/shutdown immediately, + * unless it was disabled in system.conf */ + + if (ratelimit_below(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE) + manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY); + else + emergency_action(m, m->cad_burst_action, EMERGENCY_ACTION_WARN, NULL, -1, + "Ctrl-Alt-Del was pressed more than 7 times within 2s"); +} + +static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + ssize_t n; + struct signalfd_siginfo sfsi; + int r; + + assert(m); + assert(m->signal_fd == fd); + + if (revents != EPOLLIN) { + log_warning("Got unexpected events from signal file descriptor."); + return 0; + } + + n = read(m->signal_fd, &sfsi, sizeof(sfsi)); + if (n != sizeof(sfsi)) { + if (n >= 0) { + log_warning("Truncated read from signal fd (%zu bytes), ignoring!", n); + return 0; + } + + if (IN_SET(errno, EINTR, EAGAIN)) + return 0; + + /* We return an error here, which will kill this handler, + * to avoid a busy loop on read error. */ + return log_error_errno(errno, "Reading from signal fd failed: %m"); + } + + log_received_signal(sfsi.ssi_signo == SIGCHLD || + (sfsi.ssi_signo == SIGTERM && MANAGER_IS_USER(m)) + ? LOG_DEBUG : LOG_INFO, + &sfsi); + + switch (sfsi.ssi_signo) { + + case SIGCHLD: + r = sd_event_source_set_enabled(m->sigchld_event_source, SD_EVENT_ON); + if (r < 0) + log_warning_errno(r, "Failed to enable SIGCHLD event source, ignoring: %m"); + + break; + + case SIGTERM: + if (MANAGER_IS_SYSTEM(m)) { + /* This is for compatibility with the original sysvinit */ + if (verify_run_space_and_log("Refusing to reexecute") < 0) + break; + + m->objective = MANAGER_REEXECUTE; + break; + } + + _fallthrough_; + case SIGINT: + if (MANAGER_IS_SYSTEM(m)) + manager_handle_ctrl_alt_del(m); + else + manager_start_target(m, SPECIAL_EXIT_TARGET, + JOB_REPLACE_IRREVERSIBLY); + break; + + case SIGWINCH: + /* This is a nop on non-init */ + if (MANAGER_IS_SYSTEM(m)) + manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE); + + break; + + case SIGPWR: + /* This is a nop on non-init */ + if (MANAGER_IS_SYSTEM(m)) + manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE); + + break; + + case SIGUSR1: + if (manager_dbus_is_running(m, false)) { + log_info("Trying to reconnect to bus..."); + + (void) bus_init_api(m); + + if (MANAGER_IS_SYSTEM(m)) + (void) bus_init_system(m); + } else { + log_info("Starting D-Bus service..."); + manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE); + } + + break; + + case SIGUSR2: { + _cleanup_free_ char *dump = NULL; + + r = manager_get_dump_string(m, &dump); + if (r < 0) { + log_warning_errno(errno, "Failed to acquire manager dump: %m"); + break; + } + + log_dump(LOG_INFO, dump); + break; + } + + case SIGHUP: + if (verify_run_space_and_log("Refusing to reload") < 0) + break; + + m->objective = MANAGER_RELOAD; + break; + + default: { + + /* Starting SIGRTMIN+0 */ + static const struct { + const char *target; + JobMode mode; + } target_table[] = { + [0] = { SPECIAL_DEFAULT_TARGET, JOB_ISOLATE }, + [1] = { SPECIAL_RESCUE_TARGET, JOB_ISOLATE }, + [2] = { SPECIAL_EMERGENCY_TARGET, JOB_ISOLATE }, + [3] = { SPECIAL_HALT_TARGET, JOB_REPLACE_IRREVERSIBLY }, + [4] = { SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY }, + [5] = { SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY }, + [6] = { SPECIAL_KEXEC_TARGET, JOB_REPLACE_IRREVERSIBLY }, + }; + + /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */ + static const ManagerObjective objective_table[] = { + [0] = MANAGER_HALT, + [1] = MANAGER_POWEROFF, + [2] = MANAGER_REBOOT, + [3] = MANAGER_KEXEC, + }; + + if ((int) sfsi.ssi_signo >= SIGRTMIN+0 && + (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) { + int idx = (int) sfsi.ssi_signo - SIGRTMIN; + manager_start_target(m, target_table[idx].target, + target_table[idx].mode); + break; + } + + if ((int) sfsi.ssi_signo >= SIGRTMIN+13 && + (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(objective_table)) { + m->objective = objective_table[sfsi.ssi_signo - SIGRTMIN - 13]; + break; + } + + switch (sfsi.ssi_signo - SIGRTMIN) { + + case 20: + manager_set_show_status(m, SHOW_STATUS_YES); + break; + + case 21: + manager_set_show_status(m, SHOW_STATUS_NO); + break; + + case 22: + manager_override_log_level(m, LOG_DEBUG); + break; + + case 23: + manager_restore_original_log_level(m); + break; + + case 24: + if (MANAGER_IS_USER(m)) { + m->objective = MANAGER_EXIT; + return 0; + } + + /* This is a nop on init */ + break; + + case 26: + case 29: /* compatibility: used to be mapped to LOG_TARGET_SYSLOG_OR_KMSG */ + manager_restore_original_log_target(m); + break; + + case 27: + manager_override_log_target(m, LOG_TARGET_CONSOLE); + break; + + case 28: + manager_override_log_target(m, LOG_TARGET_KMSG); + break; + + default: + log_warning("Got unhandled signal <%s>.", signal_to_string(sfsi.ssi_signo)); + } + }} + + return 0; +} + +static int manager_dispatch_time_change_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + Iterator i; + Unit *u; + + assert(m); + assert(m->time_change_fd == fd); + + log_struct(LOG_DEBUG, + "MESSAGE_ID=" SD_MESSAGE_TIME_CHANGE_STR, + LOG_MESSAGE("Time has been changed")); + + /* Restart the watch */ + (void) manager_setup_time_change(m); + + HASHMAP_FOREACH(u, m->units, i) + if (UNIT_VTABLE(u)->time_change) + UNIT_VTABLE(u)->time_change(u); + + return 0; +} + +static int manager_dispatch_timezone_change( + sd_event_source *source, + const struct inotify_event *e, + void *userdata) { + + Manager *m = userdata; + int changed; + Iterator i; + Unit *u; + + assert(m); + + log_debug("inotify event for /etc/localtime"); + + changed = manager_read_timezone_stat(m); + if (changed <= 0) + return changed; + + /* Something changed, restart the watch, to ensure we watch the new /etc/localtime if it changed */ + (void) manager_setup_timezone_change(m); + + /* Read the new timezone */ + tzset(); + + log_debug("Timezone has been changed (now: %s).", tzname[daylight]); + + HASHMAP_FOREACH(u, m->units, i) + if (UNIT_VTABLE(u)->timezone_change) + UNIT_VTABLE(u)->timezone_change(u); + + return 0; +} + +static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + + assert(m); + assert(m->idle_pipe[2] == fd); + + /* There's at least one Type=idle child that just gave up on us waiting for the boot process to complete. Let's + * now turn off any further console output if there's at least one service that needs console access, so that + * from now on our own output should not spill into that service's output anymore. After all, we support + * Type=idle only to beautify console output and it generally is set on services that want to own the console + * exclusively without our interference. */ + m->no_console_output = m->n_on_console > 0; + + /* Acknowledge the child's request, and let all all other children know too that they shouldn't wait any longer + * by closing the pipes towards them, which is what they are waiting for. */ + manager_close_idle_pipe(m); + + return 0; +} + +static int manager_dispatch_jobs_in_progress(sd_event_source *source, usec_t usec, void *userdata) { + Manager *m = userdata; + int r; + uint64_t next; + + assert(m); + assert(source); + + manager_print_jobs_in_progress(m); + + next = now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_PERIOD_USEC; + r = sd_event_source_set_time(source, next); + if (r < 0) + return r; + + return sd_event_source_set_enabled(source, SD_EVENT_ONESHOT); +} + +int manager_loop(Manager *m) { + RateLimit rl = { .interval = 1*USEC_PER_SEC, .burst = 50000 }; + int r; + + assert(m); + assert(m->objective == MANAGER_OK); /* Ensure manager_startup() has been called */ + + manager_check_finished(m); + + /* There might still be some zombies hanging around from before we were exec()'ed. Let's reap them. */ + r = sd_event_source_set_enabled(m->sigchld_event_source, SD_EVENT_ON); + if (r < 0) + return log_error_errno(r, "Failed to enable SIGCHLD event source: %m"); + + while (m->objective == MANAGER_OK) { + usec_t wait_usec; + + if (timestamp_is_set(m->runtime_watchdog) && MANAGER_IS_SYSTEM(m)) + watchdog_ping(); + + if (!ratelimit_below(&rl)) { + /* Yay, something is going seriously wrong, pause a little */ + log_warning("Looping too fast. Throttling execution a little."); + sleep(1); + } + + if (manager_dispatch_load_queue(m) > 0) + continue; + + if (manager_dispatch_gc_job_queue(m) > 0) + continue; + + if (manager_dispatch_gc_unit_queue(m) > 0) + continue; + + if (manager_dispatch_cleanup_queue(m) > 0) + continue; + + if (manager_dispatch_cgroup_realize_queue(m) > 0) + continue; + + if (manager_dispatch_stop_when_unneeded_queue(m) > 0) + continue; + + if (manager_dispatch_dbus_queue(m) > 0) + continue; + + /* Sleep for half the watchdog time */ + if (timestamp_is_set(m->runtime_watchdog) && MANAGER_IS_SYSTEM(m)) { + wait_usec = m->runtime_watchdog / 2; + if (wait_usec <= 0) + wait_usec = 1; + } else + wait_usec = USEC_INFINITY; + + r = sd_event_run(m->event, wait_usec); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + } + + return m->objective; +} + +int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u) { + _cleanup_free_ char *n = NULL; + sd_id128_t invocation_id; + Unit *u; + int r; + + assert(m); + assert(s); + assert(_u); + + r = unit_name_from_dbus_path(s, &n); + if (r < 0) + return r; + + /* Permit addressing units by invocation ID: if the passed bus path is suffixed by a 128bit ID then we use it + * as invocation ID. */ + r = sd_id128_from_string(n, &invocation_id); + if (r >= 0) { + u = hashmap_get(m->units_by_invocation_id, &invocation_id); + if (u) { + *_u = u; + return 0; + } + + return sd_bus_error_setf(e, BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, + "No unit with the specified invocation ID " SD_ID128_FORMAT_STR " known.", + SD_ID128_FORMAT_VAL(invocation_id)); + } + + /* If this didn't work, we check if this is a unit name */ + if (!unit_name_is_valid(n, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) { + _cleanup_free_ char *nn = NULL; + + nn = cescape(n); + return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, + "Unit name %s is neither a valid invocation ID nor unit name.", strnull(nn)); + } + + r = manager_load_unit(m, n, NULL, e, &u); + if (r < 0) + return r; + + *_u = u; + return 0; +} + +int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) { + const char *p; + unsigned id; + Job *j; + int r; + + assert(m); + assert(s); + assert(_j); + + p = startswith(s, "/org/freedesktop/systemd1/job/"); + if (!p) + return -EINVAL; + + r = safe_atou(p, &id); + if (r < 0) + return r; + + j = manager_get_job(m, id); + if (!j) + return -ENOENT; + + *_j = j; + + return 0; +} + +void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { + +#if HAVE_AUDIT + _cleanup_free_ char *p = NULL; + const char *msg; + int audit_fd, r; + + if (!MANAGER_IS_SYSTEM(m)) + return; + + audit_fd = get_audit_fd(); + if (audit_fd < 0) + return; + + /* Don't generate audit events if the service was already + * started and we're just deserializing */ + if (MANAGER_IS_RELOADING(m)) + return; + + if (u->type != UNIT_SERVICE) + return; + + r = unit_name_to_prefix_and_instance(u->id, &p); + if (r < 0) { + log_error_errno(r, "Failed to extract prefix and instance of unit name: %m"); + return; + } + + msg = strjoina("unit=", p); + if (audit_log_user_comm_message(audit_fd, type, msg, "systemd", NULL, NULL, NULL, success) < 0) { + if (errno == EPERM) + /* We aren't allowed to send audit messages? + * Then let's not retry again. */ + close_audit_fd(); + else + log_warning_errno(errno, "Failed to send audit message: %m"); + } +#endif + +} + +void manager_send_unit_plymouth(Manager *m, Unit *u) { + static const union sockaddr_union sa = PLYMOUTH_SOCKET; + _cleanup_free_ char *message = NULL; + _cleanup_close_ int fd = -1; + int n = 0; + + /* Don't generate plymouth events if the service was already + * started and we're just deserializing */ + if (MANAGER_IS_RELOADING(m)) + return; + + if (!MANAGER_IS_SYSTEM(m)) + return; + + if (detect_container() > 0) + return; + + if (!IN_SET(u->type, UNIT_SERVICE, UNIT_MOUNT, UNIT_SWAP)) + return; + + /* We set SOCK_NONBLOCK here so that we rather drop the + * message then wait for plymouth */ + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) { + log_error_errno(errno, "socket() failed: %m"); + return; + } + + if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) { + if (!IN_SET(errno, EAGAIN, ENOENT) && !ERRNO_IS_DISCONNECT(errno)) + log_error_errno(errno, "connect() failed: %m"); + return; + } + + if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) { + log_oom(); + return; + } + + errno = 0; + if (write(fd, message, n + 1) != n + 1) + if (!IN_SET(errno, EAGAIN, ENOENT) && !ERRNO_IS_DISCONNECT(errno)) + log_error_errno(errno, "Failed to write Plymouth message: %m"); +} + +int manager_open_serialization(Manager *m, FILE **_f) { + int fd; + FILE *f; + + assert(_f); + + fd = open_serialization_fd("systemd-state"); + if (fd < 0) + return fd; + + f = fdopen(fd, "w+"); + if (!f) { + safe_close(fd); + return -errno; + } + + *_f = f; + return 0; +} + +static bool manager_timestamp_shall_serialize(ManagerTimestamp t) { + + if (!in_initrd()) + return true; + + /* The following timestamps only apply to the host system, hence only serialize them there */ + return !IN_SET(t, + MANAGER_TIMESTAMP_USERSPACE, MANAGER_TIMESTAMP_FINISH, + MANAGER_TIMESTAMP_SECURITY_START, MANAGER_TIMESTAMP_SECURITY_FINISH, + MANAGER_TIMESTAMP_GENERATORS_START, MANAGER_TIMESTAMP_GENERATORS_FINISH, + MANAGER_TIMESTAMP_UNITS_LOAD_START, MANAGER_TIMESTAMP_UNITS_LOAD_FINISH); +} + +int manager_serialize( + Manager *m, + FILE *f, + FDSet *fds, + bool switching_root) { + + ManagerTimestamp q; + const char *t; + Iterator i; + Unit *u; + int r; + + assert(m); + assert(f); + assert(fds); + + _cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m); + + (void) serialize_item_format(f, "current-job-id", "%" PRIu32, m->current_job_id); + (void) serialize_item_format(f, "n-installed-jobs", "%u", m->n_installed_jobs); + (void) serialize_item_format(f, "n-failed-jobs", "%u", m->n_failed_jobs); + (void) serialize_bool(f, "taint-usr", m->taint_usr); + (void) serialize_bool(f, "ready-sent", m->ready_sent); + (void) serialize_bool(f, "taint-logged", m->taint_logged); + (void) serialize_bool(f, "service-watchdogs", m->service_watchdogs); + + /* After switching root, udevd has not been started yet. So, enumeration results should not be emitted. */ + (void) serialize_bool(f, "honor-device-enumeration", !switching_root); + + t = show_status_to_string(m->show_status); + if (t) + (void) serialize_item(f, "show-status", t); + + if (m->log_level_overridden) + (void) serialize_item_format(f, "log-level-override", "%i", log_get_max_level()); + if (m->log_target_overridden) + (void) serialize_item(f, "log-target-override", log_target_to_string(log_get_target())); + + for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { + _cleanup_free_ char *joined = NULL; + + if (!manager_timestamp_shall_serialize(q)) + continue; + + joined = strjoin(manager_timestamp_to_string(q), "-timestamp"); + if (!joined) + return log_oom(); + + (void) serialize_dual_timestamp(f, joined, m->timestamps + q); + } + + if (!switching_root) + (void) serialize_strv(f, "env", m->client_environment); + + if (m->notify_fd >= 0) { + r = serialize_fd(f, fds, "notify-fd", m->notify_fd); + if (r < 0) + return r; + + (void) serialize_item(f, "notify-socket", m->notify_socket); + } + + if (m->cgroups_agent_fd >= 0) { + r = serialize_fd(f, fds, "cgroups-agent-fd", m->cgroups_agent_fd); + if (r < 0) + return r; + } + + if (m->user_lookup_fds[0] >= 0) { + int copy0, copy1; + + copy0 = fdset_put_dup(fds, m->user_lookup_fds[0]); + if (copy0 < 0) + return log_error_errno(copy0, "Failed to add user lookup fd to serialization: %m"); + + copy1 = fdset_put_dup(fds, m->user_lookup_fds[1]); + if (copy1 < 0) + return log_error_errno(copy1, "Failed to add user lookup fd to serialization: %m"); + + (void) serialize_item_format(f, "user-lookup", "%i %i", copy0, copy1); + } + + bus_track_serialize(m->subscribed, f, "subscribed"); + + r = dynamic_user_serialize(m, f, fds); + if (r < 0) + return r; + + manager_serialize_uid_refs(m, f); + manager_serialize_gid_refs(m, f); + + r = exec_runtime_serialize(m, f, fds); + if (r < 0) + return r; + + (void) fputc('\n', f); + + HASHMAP_FOREACH_KEY(u, t, m->units, i) { + if (u->id != t) + continue; + + /* Start marker */ + fputs(u->id, f); + fputc('\n', f); + + r = unit_serialize(u, f, fds, !switching_root); + if (r < 0) + return r; + } + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to flush serialization: %m"); + + r = bus_fdset_add_all(m, fds); + if (r < 0) + return log_error_errno(r, "Failed to add bus sockets to serialization: %m"); + + return 0; +} + +static int manager_deserialize_one_unit(Manager *m, const char *name, FILE *f, FDSet *fds) { + Unit *u; + int r; + + r = manager_load_unit(m, name, NULL, NULL, &u); + if (r < 0) { + if (r == -ENOMEM) + return r; + return log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", name); + } + + r = unit_deserialize(u, f, fds); + if (r < 0) { + if (r == -ENOMEM) + return r; + return log_notice_errno(r, "Failed to deserialize unit \"%s\", skipping: %m", name); + } + + return 0; +} + +static int manager_deserialize_units(Manager *m, FILE *f, FDSet *fds) { + const char *unit_name; + int r; + + for (;;) { + _cleanup_free_ char *line = NULL; + /* Start marker */ + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) + break; + + unit_name = strstrip(line); + + r = manager_deserialize_one_unit(m, unit_name, f, fds); + if (r == -ENOMEM) + return r; + if (r < 0) { + r = unit_deserialize_skip(f); + if (r < 0) + return r; + } + } + + return 0; +} + +int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { + int r = 0; + + assert(m); + assert(f); + + log_debug("Deserializing state..."); + + /* If we are not in reload mode yet, enter it now. Not that this is recursive, a caller might already have + * increased it to non-zero, which is why we just increase it by one here and down again at the end of this + * call. */ + _cleanup_(manager_reloading_stopp) _unused_ Manager *reloading = manager_reloading_start(m); + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *val, *l; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) + break; + + l = strstrip(line); + if (isempty(l)) /* end marker */ + break; + + if ((val = startswith(l, "current-job-id="))) { + uint32_t id; + + if (safe_atou32(val, &id) < 0) + log_notice("Failed to parse current job id value '%s', ignoring.", val); + else + m->current_job_id = MAX(m->current_job_id, id); + + } else if ((val = startswith(l, "n-installed-jobs="))) { + uint32_t n; + + if (safe_atou32(val, &n) < 0) + log_notice("Failed to parse installed jobs counter '%s', ignoring.", val); + else + m->n_installed_jobs += n; + + } else if ((val = startswith(l, "n-failed-jobs="))) { + uint32_t n; + + if (safe_atou32(val, &n) < 0) + log_notice("Failed to parse failed jobs counter '%s', ignoring.", val); + else + m->n_failed_jobs += n; + + } else if ((val = startswith(l, "taint-usr="))) { + int b; + + b = parse_boolean(val); + if (b < 0) + log_notice("Failed to parse taint /usr flag '%s', ignoring.", val); + else + m->taint_usr = m->taint_usr || b; + + } else if ((val = startswith(l, "ready-sent="))) { + int b; + + b = parse_boolean(val); + if (b < 0) + log_notice("Failed to parse ready-sent flag '%s', ignoring.", val); + else + m->ready_sent = m->ready_sent || b; + + } else if ((val = startswith(l, "taint-logged="))) { + int b; + + b = parse_boolean(val); + if (b < 0) + log_notice("Failed to parse taint-logged flag '%s', ignoring.", val); + else + m->taint_logged = m->taint_logged || b; + + } else if ((val = startswith(l, "service-watchdogs="))) { + int b; + + b = parse_boolean(val); + if (b < 0) + log_notice("Failed to parse service-watchdogs flag '%s', ignoring.", val); + else + m->service_watchdogs = b; + + } else if ((val = startswith(l, "honor-device-enumeration="))) { + int b; + + b = parse_boolean(val); + if (b < 0) + log_notice("Failed to parse honor-device-enumeration flag '%s', ignoring.", val); + else + m->honor_device_enumeration = b; + + } else if ((val = startswith(l, "show-status="))) { + ShowStatus s; + + s = show_status_from_string(val); + if (s < 0) + log_notice("Failed to parse show-status flag '%s', ignoring.", val); + else + manager_set_show_status(m, s); + + } else if ((val = startswith(l, "log-level-override="))) { + int level; + + level = log_level_from_string(val); + if (level < 0) + log_notice("Failed to parse log-level-override value '%s', ignoring.", val); + else + manager_override_log_level(m, level); + + } else if ((val = startswith(l, "log-target-override="))) { + LogTarget target; + + target = log_target_from_string(val); + if (target < 0) + log_notice("Failed to parse log-target-override value '%s', ignoring.", val); + else + manager_override_log_target(m, target); + + } else if (startswith(l, "env=")) { + r = deserialize_environment(l + 4, &m->client_environment); + if (r < 0) + log_notice_errno(r, "Failed to parse environment entry: \"%s\", ignoring: %m", l); + + } else if ((val = startswith(l, "notify-fd="))) { + int fd; + + if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_notice("Failed to parse notify fd, ignoring: \"%s\"", val); + else { + m->notify_event_source = sd_event_source_unref(m->notify_event_source); + safe_close(m->notify_fd); + m->notify_fd = fdset_remove(fds, fd); + } + + } else if ((val = startswith(l, "notify-socket="))) { + r = free_and_strdup(&m->notify_socket, val); + if (r < 0) + return r; + + } else if ((val = startswith(l, "cgroups-agent-fd="))) { + int fd; + + if (safe_atoi(val, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_notice("Failed to parse cgroups agent fd, ignoring.: %s", val); + else { + m->cgroups_agent_event_source = sd_event_source_unref(m->cgroups_agent_event_source); + safe_close(m->cgroups_agent_fd); + m->cgroups_agent_fd = fdset_remove(fds, fd); + } + + } else if ((val = startswith(l, "user-lookup="))) { + int fd0, fd1; + + if (sscanf(val, "%i %i", &fd0, &fd1) != 2 || fd0 < 0 || fd1 < 0 || fd0 == fd1 || !fdset_contains(fds, fd0) || !fdset_contains(fds, fd1)) + log_notice("Failed to parse user lookup fd, ignoring: %s", val); + else { + m->user_lookup_event_source = sd_event_source_unref(m->user_lookup_event_source); + safe_close_pair(m->user_lookup_fds); + m->user_lookup_fds[0] = fdset_remove(fds, fd0); + m->user_lookup_fds[1] = fdset_remove(fds, fd1); + } + + } else if ((val = startswith(l, "dynamic-user="))) + dynamic_user_deserialize_one(m, val, fds); + else if ((val = startswith(l, "destroy-ipc-uid="))) + manager_deserialize_uid_refs_one(m, val); + else if ((val = startswith(l, "destroy-ipc-gid="))) + manager_deserialize_gid_refs_one(m, val); + else if ((val = startswith(l, "exec-runtime="))) + exec_runtime_deserialize_one(m, val, fds); + else if ((val = startswith(l, "subscribed="))) { + + if (strv_extend(&m->deserialized_subscribed, val) < 0) + return -ENOMEM; + + } else { + ManagerTimestamp q; + + for (q = 0; q < _MANAGER_TIMESTAMP_MAX; q++) { + val = startswith(l, manager_timestamp_to_string(q)); + if (!val) + continue; + + val = startswith(val, "-timestamp="); + if (val) + break; + } + + if (q < _MANAGER_TIMESTAMP_MAX) /* found it */ + (void) deserialize_dual_timestamp(val, m->timestamps + q); + else if (!startswith(l, "kdbus-fd=")) /* ignore kdbus */ + log_notice("Unknown serialization item '%s', ignoring.", l); + } + } + + return manager_deserialize_units(m, f, fds); +} + +int manager_reload(Manager *m) { + _cleanup_(manager_reloading_stopp) Manager *reloading = NULL; + _cleanup_fdset_free_ FDSet *fds = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(m); + + r = manager_open_serialization(m, &f); + if (r < 0) + return log_error_errno(r, "Failed to create serialization file: %m"); + + fds = fdset_new(); + if (!fds) + return log_oom(); + + /* We are officially in reload mode from here on. */ + reloading = manager_reloading_start(m); + + r = manager_serialize(m, f, fds, false); + if (r < 0) + return r; + + if (fseeko(f, 0, SEEK_SET) < 0) + return log_error_errno(errno, "Failed to seek to beginning of serialization: %m"); + + /* 💀 This is the point of no return, from here on there is no way back. 💀 */ + reloading = NULL; + + bus_manager_send_reloading(m, true); + + /* Start by flushing out all jobs and units, all generated units, all runtime environments, all dynamic users + * and everything else that is worth flushing out. We'll get it all back from the serialization — if we need + * it.*/ + + manager_clear_jobs_and_units(m); + lookup_paths_flush_generator(&m->lookup_paths); + lookup_paths_free(&m->lookup_paths); + exec_runtime_vacuum(m); + dynamic_user_vacuum(m, false); + m->uid_refs = hashmap_free(m->uid_refs); + m->gid_refs = hashmap_free(m->gid_refs); + + r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL); + if (r < 0) + log_warning_errno(r, "Failed to initialize path lookup table, ignoring: %m"); + + (void) manager_run_environment_generators(m); + (void) manager_run_generators(m); + + lookup_paths_log(&m->lookup_paths); + + /* We flushed out generated files, for which we don't watch mtime, so we should flush the old map. */ + manager_free_unit_name_maps(m); + + /* First, enumerate what we can from kernel and suchlike */ + manager_enumerate_perpetual(m); + manager_enumerate(m); + + /* Second, deserialize our stored data */ + r = manager_deserialize(m, f, fds); + if (r < 0) + log_warning_errno(r, "Deserialization failed, proceeding anyway: %m"); + + /* We don't need the serialization anymore */ + f = safe_fclose(f); + + /* Re-register notify_fd as event source, and set up other sockets/communication channels we might need */ + (void) manager_setup_notify(m); + (void) manager_setup_cgroups_agent(m); + (void) manager_setup_user_lookup_fd(m); + + /* Third, fire things up! */ + manager_coldplug(m); + + /* Clean up runtime objects no longer referenced */ + manager_vacuum(m); + + /* Consider the reload process complete now. */ + assert(m->n_reloading > 0); + m->n_reloading--; + + /* On manager reloading, device tag data should exists, thus, we should honor the results of device + * enumeration. The flag should be always set correctly by the serialized data, but it may fail. So, + * let's always set the flag here for safety. */ + m->honor_device_enumeration = true; + + manager_ready(m); + + m->send_reloading_done = true; + return 0; +} + +void manager_reset_failed(Manager *m) { + Unit *u; + Iterator i; + + assert(m); + + HASHMAP_FOREACH(u, m->units, i) + unit_reset_failed(u); +} + +bool manager_unit_inactive_or_pending(Manager *m, const char *name) { + Unit *u; + + assert(m); + assert(name); + + /* Returns true if the unit is inactive or going down */ + u = manager_get_unit(m, name); + if (!u) + return true; + + return unit_inactive_or_pending(u); +} + +static void log_taint_string(Manager *m) { + _cleanup_free_ char *taint = NULL; + + assert(m); + + if (MANAGER_IS_USER(m) || m->taint_logged) + return; + + m->taint_logged = true; /* only check for taint once */ + + taint = manager_taint_string(m); + if (isempty(taint)) + return; + + log_struct(LOG_NOTICE, + LOG_MESSAGE("System is tainted: %s", taint), + "TAINT=%s", taint, + "MESSAGE_ID=" SD_MESSAGE_TAINTED_STR); +} + +static void manager_notify_finished(Manager *m) { + char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX]; + usec_t firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec; + + if (MANAGER_IS_TEST_RUN(m)) + return; + + if (MANAGER_IS_SYSTEM(m) && detect_container() <= 0) { + char ts[FORMAT_TIMESPAN_MAX]; + char buf[FORMAT_TIMESPAN_MAX + STRLEN(" (firmware) + ") + FORMAT_TIMESPAN_MAX + STRLEN(" (loader) + ")] + = {}; + char *p = buf; + size_t size = sizeof buf; + + /* Note that MANAGER_TIMESTAMP_KERNEL's monotonic value is always at 0, and + * MANAGER_TIMESTAMP_FIRMWARE's and MANAGER_TIMESTAMP_LOADER's monotonic value should be considered + * negative values. */ + + firmware_usec = m->timestamps[MANAGER_TIMESTAMP_FIRMWARE].monotonic - m->timestamps[MANAGER_TIMESTAMP_LOADER].monotonic; + loader_usec = m->timestamps[MANAGER_TIMESTAMP_LOADER].monotonic - m->timestamps[MANAGER_TIMESTAMP_KERNEL].monotonic; + userspace_usec = m->timestamps[MANAGER_TIMESTAMP_FINISH].monotonic - m->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic; + total_usec = m->timestamps[MANAGER_TIMESTAMP_FIRMWARE].monotonic + m->timestamps[MANAGER_TIMESTAMP_FINISH].monotonic; + + if (firmware_usec > 0) + size = strpcpyf(&p, size, "%s (firmware) + ", format_timespan(ts, sizeof(ts), firmware_usec, USEC_PER_MSEC)); + if (loader_usec > 0) + size = strpcpyf(&p, size, "%s (loader) + ", format_timespan(ts, sizeof(ts), loader_usec, USEC_PER_MSEC)); + + if (dual_timestamp_is_set(&m->timestamps[MANAGER_TIMESTAMP_INITRD])) { + + /* The initrd case on bare-metal*/ + kernel_usec = m->timestamps[MANAGER_TIMESTAMP_INITRD].monotonic - m->timestamps[MANAGER_TIMESTAMP_KERNEL].monotonic; + initrd_usec = m->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic - m->timestamps[MANAGER_TIMESTAMP_INITRD].monotonic; + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_STARTUP_FINISHED_STR, + "KERNEL_USEC="USEC_FMT, kernel_usec, + "INITRD_USEC="USEC_FMT, initrd_usec, + "USERSPACE_USEC="USEC_FMT, userspace_usec, + LOG_MESSAGE("Startup finished in %s%s (kernel) + %s (initrd) + %s (userspace) = %s.", + buf, + format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC), + format_timespan(initrd, sizeof(initrd), initrd_usec, USEC_PER_MSEC), + format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC), + format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC))); + } else { + /* The initrd-less case on bare-metal*/ + + kernel_usec = m->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic - m->timestamps[MANAGER_TIMESTAMP_KERNEL].monotonic; + initrd_usec = 0; + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_STARTUP_FINISHED_STR, + "KERNEL_USEC="USEC_FMT, kernel_usec, + "USERSPACE_USEC="USEC_FMT, userspace_usec, + LOG_MESSAGE("Startup finished in %s%s (kernel) + %s (userspace) = %s.", + buf, + format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC), + format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC), + format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC))); + } + } else { + /* The container and --user case */ + firmware_usec = loader_usec = initrd_usec = kernel_usec = 0; + total_usec = userspace_usec = m->timestamps[MANAGER_TIMESTAMP_FINISH].monotonic - m->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic; + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_USER_STARTUP_FINISHED_STR, + "USERSPACE_USEC="USEC_FMT, userspace_usec, + LOG_MESSAGE("Startup finished in %s.", + format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC))); + } + + bus_manager_send_finished(m, firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec); + + sd_notifyf(false, + m->ready_sent ? "STATUS=Startup finished in %s." + : "READY=1\n" + "STATUS=Startup finished in %s.", + format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC)); + m->ready_sent = true; + + log_taint_string(m); +} + +static void manager_send_ready(Manager *m) { + assert(m); + + /* We send READY=1 on reaching basic.target only when running in --user mode. */ + if (!MANAGER_IS_USER(m) || m->ready_sent) + return; + + m->ready_sent = true; + + sd_notifyf(false, + "READY=1\n" + "STATUS=Reached " SPECIAL_BASIC_TARGET "."); +} + +static void manager_check_basic_target(Manager *m) { + Unit *u; + + assert(m); + + /* Small shortcut */ + if (m->ready_sent && m->taint_logged) + return; + + u = manager_get_unit(m, SPECIAL_BASIC_TARGET); + if (!u || !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) + return; + + /* For user managers, send out READY=1 as soon as we reach basic.target */ + manager_send_ready(m); + + /* Log the taint string as soon as we reach basic.target */ + log_taint_string(m); +} + +void manager_check_finished(Manager *m) { + assert(m); + + if (MANAGER_IS_RELOADING(m)) + return; + + /* Verify that we have entered the event loop already, and not left it again. */ + if (!MANAGER_IS_RUNNING(m)) + return; + + manager_check_basic_target(m); + + if (hashmap_size(m->jobs) > 0) { + if (m->jobs_in_progress_event_source) + /* Ignore any failure, this is only for feedback */ + (void) sd_event_source_set_time(m->jobs_in_progress_event_source, now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC); + + return; + } + + manager_flip_auto_status(m, false); + + /* Notify Type=idle units that we are done now */ + manager_close_idle_pipe(m); + + /* Turn off confirm spawn now */ + m->confirm_spawn = NULL; + + /* No need to update ask password status when we're going non-interactive */ + manager_close_ask_password(m); + + /* This is no longer the first boot */ + manager_set_first_boot(m, false); + + if (MANAGER_IS_FINISHED(m)) + return; + + dual_timestamp_get(m->timestamps + MANAGER_TIMESTAMP_FINISH); + + manager_notify_finished(m); + + manager_invalidate_startup_units(m); +} + +static bool generator_path_any(const char* const* paths) { + char **path; + bool found = false; + + /* Optimize by skipping the whole process by not creating output directories + * if no generators are found. */ + STRV_FOREACH(path, (char**) paths) + if (access(*path, F_OK) == 0) + found = true; + else if (errno != ENOENT) + log_warning_errno(errno, "Failed to open generator directory %s: %m", *path); + + return found; +} + +static const char *const system_env_generator_binary_paths[] = { + "/run/systemd/system-environment-generators", + "/etc/systemd/system-environment-generators", + "/usr/local/lib/systemd/system-environment-generators", + SYSTEM_ENV_GENERATOR_PATH, + NULL +}; + +static const char *const user_env_generator_binary_paths[] = { + "/run/systemd/user-environment-generators", + "/etc/systemd/user-environment-generators", + "/usr/local/lib/systemd/user-environment-generators", + USER_ENV_GENERATOR_PATH, + NULL +}; + +static int manager_run_environment_generators(Manager *m) { + char **tmp = NULL; /* this is only used in the forked process, no cleanup here */ + const char *const *paths; + void* args[] = { + [STDOUT_GENERATE] = &tmp, + [STDOUT_COLLECT] = &tmp, + [STDOUT_CONSUME] = &m->transient_environment, + }; + int r; + + if (MANAGER_IS_TEST_RUN(m) && !(m->test_run_flags & MANAGER_TEST_RUN_ENV_GENERATORS)) + return 0; + + paths = MANAGER_IS_SYSTEM(m) ? system_env_generator_binary_paths : user_env_generator_binary_paths; + + if (!generator_path_any(paths)) + return 0; + + RUN_WITH_UMASK(0022) + r = execute_directories(paths, DEFAULT_TIMEOUT_USEC, gather_environment, + args, NULL, m->transient_environment, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + return r; +} + +static int manager_run_generators(Manager *m) { + _cleanup_strv_free_ char **paths = NULL; + const char *argv[5]; + int r; + + assert(m); + + if (MANAGER_IS_TEST_RUN(m) && !(m->test_run_flags & MANAGER_TEST_RUN_GENERATORS)) + return 0; + + paths = generator_binary_paths(m->unit_file_scope); + if (!paths) + return log_oom(); + + if (!generator_path_any((const char* const*) paths)) + return 0; + + r = lookup_paths_mkdir_generator(&m->lookup_paths); + if (r < 0) { + log_error_errno(r, "Failed to create generator directories: %m"); + goto finish; + } + + argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */ + argv[1] = m->lookup_paths.generator; + argv[2] = m->lookup_paths.generator_early; + argv[3] = m->lookup_paths.generator_late; + argv[4] = NULL; + + RUN_WITH_UMASK(0022) + (void) execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, NULL, NULL, + (char**) argv, m->transient_environment, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + + r = 0; + +finish: + lookup_paths_trim_generator(&m->lookup_paths); + return r; +} + +int manager_transient_environment_add(Manager *m, char **plus) { + char **a; + + assert(m); + + if (strv_isempty(plus)) + return 0; + + a = strv_env_merge(2, m->transient_environment, plus); + if (!a) + return log_oom(); + + sanitize_environment(a); + + return strv_free_and_replace(m->transient_environment, a); +} + +int manager_client_environment_modify( + Manager *m, + char **minus, + char **plus) { + + char **a = NULL, **b = NULL, **l; + + assert(m); + + if (strv_isempty(minus) && strv_isempty(plus)) + return 0; + + l = m->client_environment; + + if (!strv_isempty(minus)) { + a = strv_env_delete(l, 1, minus); + if (!a) + return -ENOMEM; + + l = a; + } + + if (!strv_isempty(plus)) { + b = strv_env_merge(2, l, plus); + if (!b) { + strv_free(a); + return -ENOMEM; + } + + l = b; + } + + if (m->client_environment != l) + strv_free(m->client_environment); + + if (a != l) + strv_free(a); + if (b != l) + strv_free(b); + + m->client_environment = sanitize_environment(l); + return 0; +} + +int manager_get_effective_environment(Manager *m, char ***ret) { + char **l; + + assert(m); + assert(ret); + + l = strv_env_merge(2, m->transient_environment, m->client_environment); + if (!l) + return -ENOMEM; + + *ret = l; + return 0; +} + +int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) { + int i; + + assert(m); + + for (i = 0; i < _RLIMIT_MAX; i++) { + m->rlimit[i] = mfree(m->rlimit[i]); + + if (!default_rlimit[i]) + continue; + + m->rlimit[i] = newdup(struct rlimit, default_rlimit[i], 1); + if (!m->rlimit[i]) + return log_oom(); + } + + return 0; +} + +void manager_recheck_dbus(Manager *m) { + assert(m); + + /* Connects to the bus if the dbus service and socket are running. If we are running in user mode this is all + * it does. In system mode we'll also connect to the system bus (which will most likely just reuse the + * connection of the API bus). That's because the system bus after all runs as service of the system instance, + * while in the user instance we can assume it's already there. */ + + if (MANAGER_IS_RELOADING(m)) + return; /* don't check while we are reloading… */ + + if (manager_dbus_is_running(m, false)) { + (void) bus_init_api(m); + + if (MANAGER_IS_SYSTEM(m)) + (void) bus_init_system(m); + } else { + (void) bus_done_api(m); + + if (MANAGER_IS_SYSTEM(m)) + (void) bus_done_system(m); + } +} + +static bool manager_journal_is_running(Manager *m) { + Unit *u; + + assert(m); + + if (MANAGER_IS_TEST_RUN(m)) + return false; + + /* If we are the user manager we can safely assume that the journal is up */ + if (!MANAGER_IS_SYSTEM(m)) + return true; + + /* Check that the socket is not only up, but in RUNNING state */ + u = manager_get_unit(m, SPECIAL_JOURNALD_SOCKET); + if (!u) + return false; + if (SOCKET(u)->state != SOCKET_RUNNING) + return false; + + /* Similar, check if the daemon itself is fully up, too */ + u = manager_get_unit(m, SPECIAL_JOURNALD_SERVICE); + if (!u) + return false; + if (!IN_SET(SERVICE(u)->state, SERVICE_RELOAD, SERVICE_RUNNING)) + return false; + + return true; +} + +void disable_printk_ratelimit(void) { + /* Disable kernel's printk ratelimit. + * + * Logging to /dev/kmsg is most useful during early boot and shutdown, where normal logging + * mechanisms are not available. The semantics of this sysctl are such that any kernel command-line + * setting takes precedence. */ + int r; + + r = sysctl_write("kernel/printk_devkmsg", "on"); + if (r < 0) + log_debug_errno(r, "Failed to set sysctl kernel.printk_devkmsg=on: %m"); +} + +void manager_recheck_journal(Manager *m) { + + assert(m); + + /* Don't bother with this unless we are in the special situation of being PID 1 */ + if (getpid_cached() != 1) + return; + + /* Don't check this while we are reloading, things might still change */ + if (MANAGER_IS_RELOADING(m)) + return; + + /* The journal is fully and entirely up? If so, let's permit logging to it, if that's configured. If the + * journal is down, don't ever log to it, otherwise we might end up deadlocking ourselves as we might trigger + * an activation ourselves we can't fulfill. */ + log_set_prohibit_ipc(!manager_journal_is_running(m)); + log_open(); +} + +void manager_set_show_status(Manager *m, ShowStatus mode) { + assert(m); + assert(IN_SET(mode, SHOW_STATUS_AUTO, SHOW_STATUS_NO, SHOW_STATUS_YES, SHOW_STATUS_TEMPORARY)); + + if (!MANAGER_IS_SYSTEM(m)) + return; + + if (m->show_status != mode) + log_debug("%s showing of status.", + mode == SHOW_STATUS_NO ? "Disabling" : "Enabling"); + m->show_status = mode; + + if (IN_SET(mode, SHOW_STATUS_TEMPORARY, SHOW_STATUS_YES)) + (void) touch("/run/systemd/show-status"); + else + (void) unlink("/run/systemd/show-status"); +} + +static bool manager_get_show_status(Manager *m, StatusType type) { + assert(m); + + if (!MANAGER_IS_SYSTEM(m)) + return false; + + if (m->no_console_output) + return false; + + if (!IN_SET(manager_state(m), MANAGER_INITIALIZING, MANAGER_STARTING, MANAGER_STOPPING)) + return false; + + /* If we cannot find out the status properly, just proceed. */ + if (type != STATUS_TYPE_EMERGENCY && manager_check_ask_password(m) > 0) + return false; + + return IN_SET(m->show_status, SHOW_STATUS_TEMPORARY, SHOW_STATUS_YES); +} + +const char *manager_get_confirm_spawn(Manager *m) { + static int last_errno = 0; + struct stat st; + int r; + + assert(m); + + /* Here's the deal: we want to test the validity of the console but don't want + * PID1 to go through the whole console process which might block. But we also + * want to warn the user only once if something is wrong with the console so we + * cannot do the sanity checks after spawning our children. So here we simply do + * really basic tests to hopefully trap common errors. + * + * If the console suddenly disappear at the time our children will really it + * then they will simply fail to acquire it and a positive answer will be + * assumed. New children will fallback to /dev/console though. + * + * Note: TTYs are devices that can come and go any time, and frequently aren't + * available yet during early boot (consider a USB rs232 dongle...). If for any + * reason the configured console is not ready, we fallback to the default + * console. */ + + if (!m->confirm_spawn || path_equal(m->confirm_spawn, "/dev/console")) + return m->confirm_spawn; + + if (stat(m->confirm_spawn, &st) < 0) { + r = -errno; + goto fail; + } + + if (!S_ISCHR(st.st_mode)) { + r = -ENOTTY; + goto fail; + } + + last_errno = 0; + return m->confirm_spawn; + +fail: + if (last_errno != r) + last_errno = log_warning_errno(r, "Failed to open %s, using default console: %m", m->confirm_spawn); + + return "/dev/console"; +} + +void manager_set_first_boot(Manager *m, bool b) { + assert(m); + + if (!MANAGER_IS_SYSTEM(m)) + return; + + if (m->first_boot != (int) b) { + if (b) + (void) touch("/run/systemd/first-boot"); + else + (void) unlink("/run/systemd/first-boot"); + } + + m->first_boot = b; +} + +void manager_disable_confirm_spawn(void) { + (void) touch("/run/systemd/confirm_spawn_disabled"); +} + +bool manager_is_confirm_spawn_disabled(Manager *m) { + if (!m->confirm_spawn) + return true; + + return access("/run/systemd/confirm_spawn_disabled", F_OK) >= 0; +} + +void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) { + va_list ap; + + /* If m is NULL, assume we're after shutdown and let the messages through. */ + + if (m && !manager_get_show_status(m, type)) + return; + + /* XXX We should totally drop the check for ephemeral here + * and thus effectively make 'Type=idle' pointless. */ + if (type == STATUS_TYPE_EPHEMERAL && m && m->n_on_console > 0) + return; + + va_start(ap, format); + status_vprintf(status, SHOW_STATUS_ELLIPSIZE|(type == STATUS_TYPE_EPHEMERAL ? SHOW_STATUS_EPHEMERAL : 0), format, ap); + va_end(ap); +} + +Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) { + char p[strlen(path)+1]; + + assert(m); + assert(path); + + strcpy(p, path); + path_simplify(p, false); + + return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p); +} + +int manager_update_failed_units(Manager *m, Unit *u, bool failed) { + unsigned size; + int r; + + assert(m); + assert(u->manager == m); + + size = set_size(m->failed_units); + + if (failed) { + r = set_ensure_allocated(&m->failed_units, NULL); + if (r < 0) + return log_oom(); + + if (set_put(m->failed_units, u) < 0) + return log_oom(); + } else + (void) set_remove(m->failed_units, u); + + if (set_size(m->failed_units) != size) + bus_manager_send_change_signal(m); + + return 0; +} + +ManagerState manager_state(Manager *m) { + Unit *u; + + assert(m); + + /* Did we ever finish booting? If not then we are still starting up */ + if (!MANAGER_IS_FINISHED(m)) { + + u = manager_get_unit(m, SPECIAL_BASIC_TARGET); + if (!u || !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) + return MANAGER_INITIALIZING; + + return MANAGER_STARTING; + } + + /* Is the special shutdown target active or queued? If so, we are in shutdown state */ + u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET); + if (u && unit_active_or_pending(u)) + return MANAGER_STOPPING; + + if (MANAGER_IS_SYSTEM(m)) { + /* Are the rescue or emergency targets active or queued? If so we are in maintenance state */ + u = manager_get_unit(m, SPECIAL_RESCUE_TARGET); + if (u && unit_active_or_pending(u)) + return MANAGER_MAINTENANCE; + + u = manager_get_unit(m, SPECIAL_EMERGENCY_TARGET); + if (u && unit_active_or_pending(u)) + return MANAGER_MAINTENANCE; + } + + /* Are there any failed units? If so, we are in degraded mode */ + if (set_size(m->failed_units) > 0) + return MANAGER_DEGRADED; + + return MANAGER_RUNNING; +} + +#define DESTROY_IPC_FLAG (UINT32_C(1) << 31) + +static void manager_unref_uid_internal( + Manager *m, + Hashmap **uid_refs, + uid_t uid, + bool destroy_now, + int (*_clean_ipc)(uid_t uid)) { + + uint32_t c, n; + + assert(m); + assert(uid_refs); + assert(uid_is_valid(uid)); + assert(_clean_ipc); + + /* A generic implementation, covering both manager_unref_uid() and manager_unref_gid(), under the assumption + * that uid_t and gid_t are actually defined the same way, with the same validity rules. + * + * We store a hashmap where the UID/GID is they key and the value is a 32bit reference counter, whose highest + * bit is used as flag for marking UIDs/GIDs whose IPC objects to remove when the last reference to the UID/GID + * is dropped. The flag is set to on, once at least one reference from a unit where RemoveIPC= is set is added + * on a UID/GID. It is reset when the UID's/GID's reference counter drops to 0 again. */ + + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + assert_cc(UID_INVALID == (uid_t) GID_INVALID); + + if (uid == 0) /* We don't keep track of root, and will never destroy it */ + return; + + c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid))); + + n = c & ~DESTROY_IPC_FLAG; + assert(n > 0); + n--; + + if (destroy_now && n == 0) { + hashmap_remove(*uid_refs, UID_TO_PTR(uid)); + + if (c & DESTROY_IPC_FLAG) { + log_debug("%s " UID_FMT " is no longer referenced, cleaning up its IPC.", + _clean_ipc == clean_ipc_by_uid ? "UID" : "GID", + uid); + (void) _clean_ipc(uid); + } + } else { + c = n | (c & DESTROY_IPC_FLAG); + assert_se(hashmap_update(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c)) >= 0); + } +} + +void manager_unref_uid(Manager *m, uid_t uid, bool destroy_now) { + manager_unref_uid_internal(m, &m->uid_refs, uid, destroy_now, clean_ipc_by_uid); +} + +void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now) { + manager_unref_uid_internal(m, &m->gid_refs, (uid_t) gid, destroy_now, clean_ipc_by_gid); +} + +static int manager_ref_uid_internal( + Manager *m, + Hashmap **uid_refs, + uid_t uid, + bool clean_ipc) { + + uint32_t c, n; + int r; + + assert(m); + assert(uid_refs); + assert(uid_is_valid(uid)); + + /* A generic implementation, covering both manager_ref_uid() and manager_ref_gid(), under the assumption + * that uid_t and gid_t are actually defined the same way, with the same validity rules. */ + + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + assert_cc(UID_INVALID == (uid_t) GID_INVALID); + + if (uid == 0) /* We don't keep track of root, and will never destroy it */ + return 0; + + r = hashmap_ensure_allocated(uid_refs, &trivial_hash_ops); + if (r < 0) + return r; + + c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid))); + + n = c & ~DESTROY_IPC_FLAG; + n++; + + if (n & DESTROY_IPC_FLAG) /* check for overflow */ + return -EOVERFLOW; + + c = n | (c & DESTROY_IPC_FLAG) | (clean_ipc ? DESTROY_IPC_FLAG : 0); + + return hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c)); +} + +int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc) { + return manager_ref_uid_internal(m, &m->uid_refs, uid, clean_ipc); +} + +int manager_ref_gid(Manager *m, gid_t gid, bool clean_ipc) { + return manager_ref_uid_internal(m, &m->gid_refs, (uid_t) gid, clean_ipc); +} + +static void manager_vacuum_uid_refs_internal( + Manager *m, + Hashmap **uid_refs, + int (*_clean_ipc)(uid_t uid)) { + + Iterator i; + void *p, *k; + + assert(m); + assert(uid_refs); + assert(_clean_ipc); + + HASHMAP_FOREACH_KEY(p, k, *uid_refs, i) { + uint32_t c, n; + uid_t uid; + + uid = PTR_TO_UID(k); + c = PTR_TO_UINT32(p); + + n = c & ~DESTROY_IPC_FLAG; + if (n > 0) + continue; + + if (c & DESTROY_IPC_FLAG) { + log_debug("Found unreferenced %s " UID_FMT " after reload/reexec. Cleaning up.", + _clean_ipc == clean_ipc_by_uid ? "UID" : "GID", + uid); + (void) _clean_ipc(uid); + } + + assert_se(hashmap_remove(*uid_refs, k) == p); + } +} + +void manager_vacuum_uid_refs(Manager *m) { + manager_vacuum_uid_refs_internal(m, &m->uid_refs, clean_ipc_by_uid); +} + +void manager_vacuum_gid_refs(Manager *m) { + manager_vacuum_uid_refs_internal(m, &m->gid_refs, clean_ipc_by_gid); +} + +static void manager_serialize_uid_refs_internal( + Manager *m, + FILE *f, + Hashmap **uid_refs, + const char *field_name) { + + Iterator i; + void *p, *k; + + assert(m); + assert(f); + assert(uid_refs); + assert(field_name); + + /* Serialize the UID reference table. Or actually, just the IPC destruction flag of it, as the actual counter + * of it is better rebuild after a reload/reexec. */ + + HASHMAP_FOREACH_KEY(p, k, *uid_refs, i) { + uint32_t c; + uid_t uid; + + uid = PTR_TO_UID(k); + c = PTR_TO_UINT32(p); + + if (!(c & DESTROY_IPC_FLAG)) + continue; + + (void) serialize_item_format(f, field_name, UID_FMT, uid); + } +} + +void manager_serialize_uid_refs(Manager *m, FILE *f) { + manager_serialize_uid_refs_internal(m, f, &m->uid_refs, "destroy-ipc-uid"); +} + +void manager_serialize_gid_refs(Manager *m, FILE *f) { + manager_serialize_uid_refs_internal(m, f, &m->gid_refs, "destroy-ipc-gid"); +} + +static void manager_deserialize_uid_refs_one_internal( + Manager *m, + Hashmap** uid_refs, + const char *value) { + + uid_t uid; + uint32_t c; + int r; + + assert(m); + assert(uid_refs); + assert(value); + + r = parse_uid(value, &uid); + if (r < 0 || uid == 0) { + log_debug("Unable to parse UID reference serialization"); + return; + } + + r = hashmap_ensure_allocated(uid_refs, &trivial_hash_ops); + if (r < 0) { + log_oom(); + return; + } + + c = PTR_TO_UINT32(hashmap_get(*uid_refs, UID_TO_PTR(uid))); + if (c & DESTROY_IPC_FLAG) + return; + + c |= DESTROY_IPC_FLAG; + + r = hashmap_replace(*uid_refs, UID_TO_PTR(uid), UINT32_TO_PTR(c)); + if (r < 0) { + log_debug_errno(r, "Failed to add UID reference entry: %m"); + return; + } +} + +void manager_deserialize_uid_refs_one(Manager *m, const char *value) { + manager_deserialize_uid_refs_one_internal(m, &m->uid_refs, value); +} + +void manager_deserialize_gid_refs_one(Manager *m, const char *value) { + manager_deserialize_uid_refs_one_internal(m, &m->gid_refs, value); +} + +int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + struct buffer { + uid_t uid; + gid_t gid; + char unit_name[UNIT_NAME_MAX+1]; + } _packed_ buffer; + + Manager *m = userdata; + ssize_t l; + size_t n; + Unit *u; + + assert_se(source); + assert_se(m); + + /* Invoked whenever a child process succeeded resolving its user/group to use and sent us the resulting UID/GID + * in a datagram. We parse the datagram here and pass it off to the unit, so that it can add a reference to the + * UID/GID so that it can destroy the UID/GID's IPC objects when the reference counter drops to 0. */ + + l = recv(fd, &buffer, sizeof(buffer), MSG_DONTWAIT); + if (l < 0) { + if (IN_SET(errno, EINTR, EAGAIN)) + return 0; + + return log_error_errno(errno, "Failed to read from user lookup fd: %m"); + } + + if ((size_t) l <= offsetof(struct buffer, unit_name)) { + log_warning("Received too short user lookup message, ignoring."); + return 0; + } + + if ((size_t) l > offsetof(struct buffer, unit_name) + UNIT_NAME_MAX) { + log_warning("Received too long user lookup message, ignoring."); + return 0; + } + + if (!uid_is_valid(buffer.uid) && !gid_is_valid(buffer.gid)) { + log_warning("Got user lookup message with invalid UID/GID pair, ignoring."); + return 0; + } + + n = (size_t) l - offsetof(struct buffer, unit_name); + if (memchr(buffer.unit_name, 0, n)) { + log_warning("Received lookup message with embedded NUL character, ignoring."); + return 0; + } + + buffer.unit_name[n] = 0; + u = manager_get_unit(m, buffer.unit_name); + if (!u) { + log_debug("Got user lookup message but unit doesn't exist, ignoring."); + return 0; + } + + log_unit_debug(u, "User lookup succeeded: uid=" UID_FMT " gid=" GID_FMT, buffer.uid, buffer.gid); + + unit_notify_user_lookup(u, buffer.uid, buffer.gid); + return 0; +} + +char *manager_taint_string(Manager *m) { + _cleanup_free_ char *destination = NULL, *overflowuid = NULL, *overflowgid = NULL; + char *buf, *e; + int r; + + /* Returns a "taint string", e.g. "local-hwclock:var-run-bad". + * Only things that are detected at runtime should be tagged + * here. For stuff that is set during compilation, emit a warning + * in the configuration phase. */ + + assert(m); + + buf = new(char, sizeof("split-usr:" + "cgroups-missing:" + "local-hwclock:" + "var-run-bad:" + "overflowuid-not-65534:" + "overflowgid-not-65534:")); + if (!buf) + return NULL; + + e = buf; + buf[0] = 0; + + if (m->taint_usr) + e = stpcpy(e, "split-usr:"); + + if (access("/proc/cgroups", F_OK) < 0) + e = stpcpy(e, "cgroups-missing:"); + + if (clock_is_localtime(NULL) > 0) + e = stpcpy(e, "local-hwclock:"); + + r = readlink_malloc("/var/run", &destination); + if (r < 0 || !PATH_IN_SET(destination, "../run", "/run")) + e = stpcpy(e, "var-run-bad:"); + + r = read_one_line_file("/proc/sys/kernel/overflowuid", &overflowuid); + if (r >= 0 && !streq(overflowuid, "65534")) + e = stpcpy(e, "overflowuid-not-65534:"); + + r = read_one_line_file("/proc/sys/kernel/overflowgid", &overflowgid); + if (r >= 0 && !streq(overflowgid, "65534")) + e = stpcpy(e, "overflowgid-not-65534:"); + + /* remove the last ':' */ + if (e != buf) + e[-1] = 0; + + return buf; +} + +void manager_ref_console(Manager *m) { + assert(m); + + m->n_on_console++; +} + +void manager_unref_console(Manager *m) { + + assert(m->n_on_console > 0); + m->n_on_console--; + + if (m->n_on_console == 0) + m->no_console_output = false; /* unset no_console_output flag, since the console is definitely free now */ +} + +void manager_override_log_level(Manager *m, int level) { + _cleanup_free_ char *s = NULL; + assert(m); + + if (!m->log_level_overridden) { + m->original_log_level = log_get_max_level(); + m->log_level_overridden = true; + } + + (void) log_level_to_string_alloc(level, &s); + log_info("Setting log level to %s.", strna(s)); + + log_set_max_level(level); +} + +void manager_restore_original_log_level(Manager *m) { + _cleanup_free_ char *s = NULL; + assert(m); + + if (!m->log_level_overridden) + return; + + (void) log_level_to_string_alloc(m->original_log_level, &s); + log_info("Restoring log level to original (%s).", strna(s)); + + log_set_max_level(m->original_log_level); + m->log_level_overridden = false; +} + +void manager_override_log_target(Manager *m, LogTarget target) { + assert(m); + + if (!m->log_target_overridden) { + m->original_log_target = log_get_target(); + m->log_target_overridden = true; + } + + log_info("Setting log target to %s.", log_target_to_string(target)); + log_set_target(target); +} + +void manager_restore_original_log_target(Manager *m) { + assert(m); + + if (!m->log_target_overridden) + return; + + log_info("Restoring log target to original %s.", log_target_to_string(m->original_log_target)); + + log_set_target(m->original_log_target); + m->log_target_overridden = false; +} + +ManagerTimestamp manager_timestamp_initrd_mangle(ManagerTimestamp s) { + if (in_initrd() && + s >= MANAGER_TIMESTAMP_SECURITY_START && + s <= MANAGER_TIMESTAMP_UNITS_LOAD_FINISH) + return s - MANAGER_TIMESTAMP_SECURITY_START + MANAGER_TIMESTAMP_INITRD_SECURITY_START; + return s; +} + +static const char *const manager_state_table[_MANAGER_STATE_MAX] = { + [MANAGER_INITIALIZING] = "initializing", + [MANAGER_STARTING] = "starting", + [MANAGER_RUNNING] = "running", + [MANAGER_DEGRADED] = "degraded", + [MANAGER_MAINTENANCE] = "maintenance", + [MANAGER_STOPPING] = "stopping", +}; + +DEFINE_STRING_TABLE_LOOKUP(manager_state, ManagerState); + +static const char *const manager_timestamp_table[_MANAGER_TIMESTAMP_MAX] = { + [MANAGER_TIMESTAMP_FIRMWARE] = "firmware", + [MANAGER_TIMESTAMP_LOADER] = "loader", + [MANAGER_TIMESTAMP_KERNEL] = "kernel", + [MANAGER_TIMESTAMP_INITRD] = "initrd", + [MANAGER_TIMESTAMP_USERSPACE] = "userspace", + [MANAGER_TIMESTAMP_FINISH] = "finish", + [MANAGER_TIMESTAMP_SECURITY_START] = "security-start", + [MANAGER_TIMESTAMP_SECURITY_FINISH] = "security-finish", + [MANAGER_TIMESTAMP_GENERATORS_START] = "generators-start", + [MANAGER_TIMESTAMP_GENERATORS_FINISH] = "generators-finish", + [MANAGER_TIMESTAMP_UNITS_LOAD_START] = "units-load-start", + [MANAGER_TIMESTAMP_UNITS_LOAD_FINISH] = "units-load-finish", + [MANAGER_TIMESTAMP_INITRD_SECURITY_START] = "initrd-security-start", + [MANAGER_TIMESTAMP_INITRD_SECURITY_FINISH] = "initrd-security-finish", + [MANAGER_TIMESTAMP_INITRD_GENERATORS_START] = "initrd-generators-start", + [MANAGER_TIMESTAMP_INITRD_GENERATORS_FINISH] = "initrd-generators-finish", + [MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_START] = "initrd-units-load-start", + [MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_FINISH] = "initrd-units-load-finish", +}; + +DEFINE_STRING_TABLE_LOOKUP(manager_timestamp, ManagerTimestamp); + +static const char* const oom_policy_table[_OOM_POLICY_MAX] = { + [OOM_CONTINUE] = "continue", + [OOM_STOP] = "stop", + [OOM_KILL] = "kill", +}; + +DEFINE_STRING_TABLE_LOOKUP(oom_policy, OOMPolicy); diff --git a/src/core/manager.h b/src/core/manager.h new file mode 100644 index 00000000..51df7f8c --- /dev/null +++ b/src/core/manager.h @@ -0,0 +1,557 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-bus.h" +#include "sd-device.h" +#include "sd-event.h" + +#include "cgroup-util.h" +#include "cgroup.h" +#include "fdset.h" +#include "hashmap.h" +#include "ip-address-access.h" +#include "list.h" +#include "prioq.h" +#include "ratelimit.h" + +struct libmnt_monitor; +typedef struct Unit Unit; + +/* Enforce upper limit how many names we allow */ +#define MANAGER_MAX_NAMES 131072 /* 128K */ + +typedef struct Manager Manager; + +/* An externally visible state. We don't actually maintain this as state variable, but derive it from various fields + * when requested */ +typedef enum ManagerState { + MANAGER_INITIALIZING, + MANAGER_STARTING, + MANAGER_RUNNING, + MANAGER_DEGRADED, + MANAGER_MAINTENANCE, + MANAGER_STOPPING, + _MANAGER_STATE_MAX, + _MANAGER_STATE_INVALID = -1 +} ManagerState; + +typedef enum ManagerObjective { + MANAGER_OK, + MANAGER_EXIT, + MANAGER_RELOAD, + MANAGER_REEXECUTE, + MANAGER_REBOOT, + MANAGER_POWEROFF, + MANAGER_HALT, + MANAGER_KEXEC, + MANAGER_SWITCH_ROOT, + _MANAGER_OBJECTIVE_MAX, + _MANAGER_OBJECTIVE_INVALID = -1 +} ManagerObjective; + +typedef enum StatusType { + STATUS_TYPE_EPHEMERAL, + STATUS_TYPE_NORMAL, + STATUS_TYPE_EMERGENCY, +} StatusType; + +typedef enum OOMPolicy { + OOM_CONTINUE, /* The kernel kills the process it wants to kill, and that's it */ + OOM_STOP, /* The kernel kills the process it wants to kill, and we stop the unit */ + OOM_KILL, /* The kernel kills the process it wants to kill, and all others in the unit, and we stop the unit */ + _OOM_POLICY_MAX, + _OOM_POLICY_INVALID = -1 +} OOMPolicy; + +/* Notes: + * 1. TIMESTAMP_FIRMWARE, TIMESTAMP_LOADER, TIMESTAMP_KERNEL, TIMESTAMP_INITRD, + * TIMESTAMP_SECURITY_START, and TIMESTAMP_SECURITY_FINISH are set only when + * the manager is system and not running under container environment. + * + * 2. The monotonic timestamp of TIMESTAMP_KERNEL is always zero. + * + * 3. The realtime timestamp of TIMESTAMP_KERNEL will be unset if the system does not + * have RTC. + * + * 4. TIMESTAMP_FIRMWARE and TIMESTAMP_LOADER will be unset if the system does not + * have RTC, or systemd is built without EFI support. + * + * 5. The monotonic timestamps of TIMESTAMP_FIRMWARE and TIMESTAMP_LOADER are stored as + * negative of the actual value. + * + * 6. TIMESTAMP_USERSPACE is the timestamp of when the manager was started. + * + * 7. TIMESTAMP_INITRD_* are set only when the system is booted with an initrd. + */ + +typedef enum ManagerTimestamp { + MANAGER_TIMESTAMP_FIRMWARE, + MANAGER_TIMESTAMP_LOADER, + MANAGER_TIMESTAMP_KERNEL, + MANAGER_TIMESTAMP_INITRD, + MANAGER_TIMESTAMP_USERSPACE, + MANAGER_TIMESTAMP_FINISH, + + MANAGER_TIMESTAMP_SECURITY_START, + MANAGER_TIMESTAMP_SECURITY_FINISH, + MANAGER_TIMESTAMP_GENERATORS_START, + MANAGER_TIMESTAMP_GENERATORS_FINISH, + MANAGER_TIMESTAMP_UNITS_LOAD_START, + MANAGER_TIMESTAMP_UNITS_LOAD_FINISH, + + MANAGER_TIMESTAMP_INITRD_SECURITY_START, + MANAGER_TIMESTAMP_INITRD_SECURITY_FINISH, + MANAGER_TIMESTAMP_INITRD_GENERATORS_START, + MANAGER_TIMESTAMP_INITRD_GENERATORS_FINISH, + MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_START, + MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_FINISH, + _MANAGER_TIMESTAMP_MAX, + _MANAGER_TIMESTAMP_INVALID = -1, +} ManagerTimestamp; + +#include "execute.h" +#include "job.h" +#include "path-lookup.h" +#include "show-status.h" +#include "unit-name.h" + +typedef enum ManagerTestRunFlags { + MANAGER_TEST_NORMAL = 0, /* run normally */ + MANAGER_TEST_RUN_MINIMAL = 1 << 0, /* create basic data structures */ + MANAGER_TEST_RUN_BASIC = 1 << 1, /* interact with the environment */ + MANAGER_TEST_RUN_ENV_GENERATORS = 1 << 2, /* also run env generators */ + MANAGER_TEST_RUN_GENERATORS = 1 << 3, /* also run unit generators */ + MANAGER_TEST_FULL = MANAGER_TEST_RUN_BASIC | MANAGER_TEST_RUN_ENV_GENERATORS | MANAGER_TEST_RUN_GENERATORS, +} ManagerTestRunFlags; + +assert_cc((MANAGER_TEST_FULL & UINT8_MAX) == MANAGER_TEST_FULL); + +struct Manager { + /* Note that the set of units we know of is allowed to be + * inconsistent. However the subset of it that is loaded may + * not, and the list of jobs may neither. */ + + /* Active jobs and units */ + Hashmap *units; /* name string => Unit object n:1 */ + Hashmap *units_by_invocation_id; + Hashmap *jobs; /* job id => Job object 1:1 */ + + /* To make it easy to iterate through the units of a specific + * type we maintain a per type linked list */ + LIST_HEAD(Unit, units_by_type[_UNIT_TYPE_MAX]); + + /* Units that need to be loaded */ + LIST_HEAD(Unit, load_queue); /* this is actually more a stack than a queue, but uh. */ + + /* Jobs that need to be run */ + struct Prioq *run_queue; + + /* Units and jobs that have not yet been announced via + * D-Bus. When something about a job changes it is added here + * if it is not in there yet. This allows easy coalescing of + * D-Bus change signals. */ + LIST_HEAD(Unit, dbus_unit_queue); + LIST_HEAD(Job, dbus_job_queue); + + /* Units to remove */ + LIST_HEAD(Unit, cleanup_queue); + + /* Units and jobs to check when doing GC */ + LIST_HEAD(Unit, gc_unit_queue); + LIST_HEAD(Job, gc_job_queue); + + /* Units that should be realized */ + LIST_HEAD(Unit, cgroup_realize_queue); + + /* Units whose cgroup ran empty */ + LIST_HEAD(Unit, cgroup_empty_queue); + + /* Units whose memory.event fired */ + LIST_HEAD(Unit, cgroup_oom_queue); + + /* Target units whose default target dependencies haven't been set yet */ + LIST_HEAD(Unit, target_deps_queue); + + /* Units that might be subject to StopWhenUnneeded= clean-up */ + LIST_HEAD(Unit, stop_when_unneeded_queue); + + sd_event *event; + + /* This maps PIDs we care about to units that are interested in. We allow multiple units to he interested in + * the same PID and multiple PIDs to be relevant to the same unit. Since in most cases only a single unit will + * be interested in the same PID we use a somewhat special encoding here: the first unit interested in a PID is + * stored directly in the hashmap, keyed by the PID unmodified. If there are other units interested too they'll + * be stored in a NULL-terminated array, and keyed by the negative PID. This is safe as pid_t is signed and + * negative PIDs are not used for regular processes but process groups, which we don't care about in this + * context, but this allows us to use the negative range for our own purposes. */ + Hashmap *watch_pids; /* pid => unit as well as -pid => array of units */ + + /* A set contains all units which cgroup should be refreshed after startup */ + Set *startup_units; + + /* A set which contains all currently failed units */ + Set *failed_units; + + sd_event_source *run_queue_event_source; + + char *notify_socket; + int notify_fd; + sd_event_source *notify_event_source; + + int cgroups_agent_fd; + sd_event_source *cgroups_agent_event_source; + + int signal_fd; + sd_event_source *signal_event_source; + + sd_event_source *sigchld_event_source; + + int time_change_fd; + sd_event_source *time_change_event_source; + + sd_event_source *timezone_change_event_source; + + sd_event_source *jobs_in_progress_event_source; + + int user_lookup_fds[2]; + sd_event_source *user_lookup_event_source; + + sd_event_source *sync_bus_names_event_source; + + UnitFileScope unit_file_scope; + LookupPaths lookup_paths; + Hashmap *unit_id_map; + Hashmap *unit_name_map; + Set *unit_path_cache; + usec_t unit_cache_mtime; + + char **transient_environment; /* The environment, as determined from config files, kernel cmdline and environment generators */ + char **client_environment; /* Environment variables created by clients through the bus API */ + + usec_t runtime_watchdog; + usec_t reboot_watchdog; + usec_t kexec_watchdog; + + dual_timestamp timestamps[_MANAGER_TIMESTAMP_MAX]; + + /* Data specific to the device subsystem */ + sd_device_monitor *device_monitor; + Hashmap *devices_by_sysfs; + + /* Data specific to the mount subsystem */ + struct libmnt_monitor *mount_monitor; + sd_event_source *mount_event_source; + + /* Data specific to the swap filesystem */ + FILE *proc_swaps; + sd_event_source *swap_event_source; + Hashmap *swaps_by_devnode; + + /* Data specific to the D-Bus subsystem */ + sd_bus *api_bus, *system_bus; + Set *private_buses; + int private_listen_fd; + sd_event_source *private_listen_event_source; + + /* Contains all the clients that are subscribed to signals via + the API bus. Note that private bus connections are always + considered subscribes, since they last for very short only, + and it is much simpler that way. */ + sd_bus_track *subscribed; + char **deserialized_subscribed; + + /* This is used during reloading: before the reload we queue + * the reply message here, and afterwards we send it */ + sd_bus_message *pending_reload_message; + + Hashmap *watch_bus; /* D-Bus names => Unit object n:1 */ + + bool send_reloading_done; + + uint32_t current_job_id; + uint32_t default_unit_job_id; + + /* Data specific to the Automount subsystem */ + int dev_autofs_fd; + + /* Data specific to the cgroup subsystem */ + Hashmap *cgroup_unit; + CGroupMask cgroup_supported; + char *cgroup_root; + + /* Notifications from cgroups, when the unified hierarchy is used is done via inotify. */ + int cgroup_inotify_fd; + sd_event_source *cgroup_inotify_event_source; + + /* Maps for finding the unit for each inotify watch descriptor for the cgroup.events and + * memory.events cgroupv2 attributes. */ + Hashmap *cgroup_control_inotify_wd_unit; + Hashmap *cgroup_memory_inotify_wd_unit; + + /* A defer event for handling cgroup empty events and processing them after SIGCHLD in all cases. */ + sd_event_source *cgroup_empty_event_source; + sd_event_source *cgroup_oom_event_source; + + /* Make sure the user cannot accidentally unmount our cgroup + * file system */ + int pin_cgroupfs_fd; + + unsigned gc_marker; + + /* The stat() data the last time we saw /etc/localtime */ + usec_t etc_localtime_mtime; + bool etc_localtime_accessible:1; + + ManagerObjective objective:5; + + /* Flags */ + bool dispatching_load_queue:1; + + bool taint_usr:1; + + /* Have we already sent out the READY=1 notification? */ + bool ready_sent:1; + + /* Have we already printed the taint line if necessary? */ + bool taint_logged:1; + + /* Have we ever changed the "kernel.pid_max" sysctl? */ + bool sysctl_pid_max_changed:1; + + ManagerTestRunFlags test_run_flags:8; + + /* If non-zero, exit with the following value when the systemd + * process terminate. Useful for containers: systemd-nspawn could get + * the return value. */ + uint8_t return_value; + + ShowStatus show_status; + StatusUnitFormat status_unit_format; + char *confirm_spawn; + bool no_console_output; + bool service_watchdogs; + + ExecOutput default_std_output, default_std_error; + + usec_t default_restart_usec, default_timeout_start_usec, default_timeout_stop_usec; + usec_t default_timeout_abort_usec; + bool default_timeout_abort_set; + + usec_t default_start_limit_interval; + unsigned default_start_limit_burst; + + bool default_cpu_accounting; + bool default_memory_accounting; + bool default_io_accounting; + bool default_blockio_accounting; + bool default_tasks_accounting; + bool default_ip_accounting; + + TasksMax default_tasks_max; + usec_t default_timer_accuracy_usec; + + OOMPolicy default_oom_policy; + + int original_log_level; + LogTarget original_log_target; + bool log_level_overridden:1; + bool log_target_overridden:1; + + struct rlimit *rlimit[_RLIMIT_MAX]; + + /* non-zero if we are reloading or reexecuting, */ + int n_reloading; + + unsigned n_installed_jobs; + unsigned n_failed_jobs; + + /* Jobs in progress watching */ + unsigned n_running_jobs; + unsigned n_on_console; + unsigned jobs_in_progress_iteration; + + /* Do we have any outstanding password prompts? */ + int have_ask_password; + int ask_password_inotify_fd; + sd_event_source *ask_password_event_source; + + /* Type=idle pipes */ + int idle_pipe[4]; + sd_event_source *idle_pipe_event_source; + + char *switch_root; + char *switch_root_init; + + /* This maps all possible path prefixes to the units needing + * them. It's a hashmap with a path string as key and a Set as + * value where Unit objects are contained. */ + Hashmap *units_requiring_mounts_for; + + /* Used for processing polkit authorization responses */ + Hashmap *polkit_registry; + + /* Dynamic users/groups, indexed by their name */ + Hashmap *dynamic_users; + + /* Keep track of all UIDs and GIDs any of our services currently use. This is useful for the RemoveIPC= logic. */ + Hashmap *uid_refs; + Hashmap *gid_refs; + + /* ExecRuntime, indexed by their owner unit id */ + Hashmap *exec_runtime_by_id; + + /* When the user hits C-A-D more than 7 times per 2s, do something immediately... */ + RateLimit ctrl_alt_del_ratelimit; + EmergencyAction cad_burst_action; + + const char *unit_log_field; + const char *unit_log_format_string; + + const char *invocation_log_field; + const char *invocation_log_format_string; + + int first_boot; /* tri-state */ + + /* Prefixes of e.g. RuntimeDirectory= */ + char *prefix[_EXEC_DIRECTORY_TYPE_MAX]; + + /* Used in the SIGCHLD and sd_notify() message invocation logic to avoid that we dispatch the same event + * multiple times on the same unit. */ + unsigned sigchldgen; + unsigned notifygen; + + bool honor_device_enumeration; +}; + +static inline usec_t manager_default_timeout_abort_usec(Manager *m) { + assert(m); + return m->default_timeout_abort_set ? m->default_timeout_abort_usec : m->default_timeout_stop_usec; +} + +#define MANAGER_IS_SYSTEM(m) ((m)->unit_file_scope == UNIT_FILE_SYSTEM) +#define MANAGER_IS_USER(m) ((m)->unit_file_scope != UNIT_FILE_SYSTEM) + +#define MANAGER_IS_RELOADING(m) ((m)->n_reloading > 0) + +#define MANAGER_IS_FINISHED(m) (dual_timestamp_is_set((m)->timestamps + MANAGER_TIMESTAMP_FINISH)) + +/* The objective is set to OK as soon as we enter the main loop, and set otherwise as soon as we are done with it */ +#define MANAGER_IS_RUNNING(m) ((m)->objective == MANAGER_OK) + +#define MANAGER_IS_TEST_RUN(m) ((m)->test_run_flags != 0) + +int manager_new(UnitFileScope scope, ManagerTestRunFlags test_run_flags, Manager **m); +Manager* manager_free(Manager *m); +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); + +int manager_startup(Manager *m, FILE *serialization, FDSet *fds); + +Job *manager_get_job(Manager *m, uint32_t id); +Unit *manager_get_unit(Manager *m, const char *name); + +int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j); + +int manager_load_unit_prepare(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret); +int manager_load_unit(Manager *m, const char *name, const char *path, sd_bus_error *e, Unit **_ret); +int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret); +int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u); + +int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **_ret); +int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **_ret); +int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret); +int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e); + +void manager_dump_units(Manager *s, FILE *f, const char *prefix); +void manager_dump_jobs(Manager *s, FILE *f, const char *prefix); +void manager_dump(Manager *s, FILE *f, const char *prefix); +int manager_get_dump_string(Manager *m, char **ret); + +void manager_clear_jobs(Manager *m); + +void manager_unwatch_pid(Manager *m, pid_t pid); + +unsigned manager_dispatch_load_queue(Manager *m); + +int manager_default_environment(Manager *m); +int manager_transient_environment_add(Manager *m, char **plus); +int manager_client_environment_modify(Manager *m, char **minus, char **plus); +int manager_get_effective_environment(Manager *m, char ***ret); + +int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit); + +int manager_loop(Manager *m); + +int manager_open_serialization(Manager *m, FILE **_f); + +int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root); +int manager_deserialize(Manager *m, FILE *f, FDSet *fds); + +int manager_reload(Manager *m); + +void manager_reset_failed(Manager *m); + +void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success); +void manager_send_unit_plymouth(Manager *m, Unit *u); + +bool manager_unit_inactive_or_pending(Manager *m, const char *name); + +void manager_check_finished(Manager *m); + +void disable_printk_ratelimit(void); +void manager_recheck_dbus(Manager *m); +void manager_recheck_journal(Manager *m); + +void manager_set_show_status(Manager *m, ShowStatus mode); +void manager_set_first_boot(Manager *m, bool b); + +void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) _printf_(4,5); +void manager_flip_auto_status(Manager *m, bool enable); + +Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path); + +ManagerState manager_state(Manager *m); + +int manager_update_failed_units(Manager *m, Unit *u, bool failed); + +void manager_unref_uid(Manager *m, uid_t uid, bool destroy_now); +int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc); + +void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now); +int manager_ref_gid(Manager *m, gid_t gid, bool destroy_now); + +void manager_vacuum_uid_refs(Manager *m); +void manager_vacuum_gid_refs(Manager *m); + +void manager_serialize_uid_refs(Manager *m, FILE *f); +void manager_deserialize_uid_refs_one(Manager *m, const char *value); + +void manager_serialize_gid_refs(Manager *m, FILE *f); +void manager_deserialize_gid_refs_one(Manager *m, const char *value); + +char *manager_taint_string(Manager *m); + +void manager_ref_console(Manager *m); +void manager_unref_console(Manager *m); + +void manager_override_log_level(Manager *m, int level); +void manager_restore_original_log_level(Manager *m); + +void manager_override_log_target(Manager *m, LogTarget target); +void manager_restore_original_log_target(Manager *m); + +const char *manager_state_to_string(ManagerState m) _const_; +ManagerState manager_state_from_string(const char *s) _pure_; + +const char *manager_get_confirm_spawn(Manager *m); +bool manager_is_confirm_spawn_disabled(Manager *m); +void manager_disable_confirm_spawn(void); + +const char *manager_timestamp_to_string(ManagerTimestamp m) _const_; +ManagerTimestamp manager_timestamp_from_string(const char *s) _pure_; +ManagerTimestamp manager_timestamp_initrd_mangle(ManagerTimestamp s); + +const char* oom_policy_to_string(OOMPolicy i) _const_; +OOMPolicy oom_policy_from_string(const char *s) _pure_; diff --git a/src/core/meson.build b/src/core/meson.build new file mode 100644 index 00000000..fb6820e1 --- /dev/null +++ b/src/core/meson.build @@ -0,0 +1,217 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +libcore_shared_sources = ''' + killall.c + killall.h + loopback-setup.c + loopback-setup.h + machine-id-setup.c + machine-id-setup.h + mount-setup.c + mount-setup.h +'''.split() + +libcore_sources = ''' + audit-fd.c + audit-fd.h + automount.c + automount.h + bpf-devices.c + bpf-devices.h + bpf-firewall.c + bpf-firewall.h + cgroup.c + cgroup.h + chown-recursive.c + chown-recursive.h + dbus-automount.c + dbus-automount.h + dbus-cgroup.c + dbus-cgroup.h + dbus-device.c + dbus-device.h + dbus-execute.c + dbus-execute.h + dbus-job.c + dbus-job.h + dbus-kill.c + dbus-kill.h + dbus-manager.c + dbus-manager.h + dbus-mount.c + dbus-mount.h + dbus-path.c + dbus-path.h + dbus-scope.c + dbus-scope.h + dbus-service.c + dbus-service.h + dbus-slice.c + dbus-slice.h + dbus-socket.c + dbus-socket.h + dbus-swap.c + dbus-swap.h + dbus-target.c + dbus-target.h + dbus-timer.c + dbus-timer.h + dbus-unit.c + dbus-unit.h + dbus-util.c + dbus-util.h + dbus.c + dbus.h + device.c + device.h + dynamic-user.c + dynamic-user.h + efi-random.c + efi-random.h + emergency-action.c + emergency-action.h + execute.c + execute.h + hostname-setup.c + hostname-setup.h + ima-setup.c + ima-setup.h + ip-address-access.c + ip-address-access.h + job.c + job.h + kill.c + kill.h + kmod-setup.c + kmod-setup.h + load-dropin.c + load-dropin.h + load-fragment.c + load-fragment.h + locale-setup.c + locale-setup.h + manager.c + manager.h + mount.c + mount.h + namespace.c + namespace.h + path.c + path.h + scope.c + scope.h + selinux-access.c + selinux-access.h + selinux-setup.c + selinux-setup.h + service.c + service.h + show-status.c + show-status.h + slice.c + slice.h + smack-setup.c + smack-setup.h + socket.c + socket.h + swap.c + swap.h + target.c + target.h + timer.c + timer.h + transaction.c + transaction.h + unit-printf.c + unit-printf.h + unit.c + unit.h +'''.split() + +load_fragment_gperf_gperf = custom_target( + 'load-fragment-gperf.gperf', + input : 'load-fragment-gperf.gperf.m4', + output: 'load-fragment-gperf.gperf', + command : [meson_apply_m4, config_h, '@INPUT@'], + capture : true) + +load_fragment_gperf_c = custom_target( + 'load-fragment-gperf.c', + input : load_fragment_gperf_gperf, + output : 'load-fragment-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + +awkscript = 'load-fragment-gperf-nulstr.awk' +load_fragment_gperf_nulstr_c = custom_target( + 'load-fragment-gperf-nulstr.c', + input : [awkscript, load_fragment_gperf_gperf], + output : 'load-fragment-gperf-nulstr.c', + command : [awk, '-f', '@INPUT0@', '@INPUT1@'], + capture : true) + +# A convenience library to share code with other binaries: +# systemd-shutdown, systemd-remount-fs, systemd-machine-id-setup, … +libcore_shared = static_library( + 'core-shared', + libcore_shared_sources, + include_directories : includes, + dependencies : [versiondep, + libmount]) + +libcore = static_library( + 'core', + libcore_sources, + load_fragment_gperf_c, + load_fragment_gperf_nulstr_c, + include_directories : includes, + link_whole : libcore_shared, + dependencies : [versiondep, + threads, + librt, + libseccomp, + libpam, + libaudit, + libkmod, + libapparmor, + libselinux, + libmount]) + +systemd_sources = files('main.c') + +in_files = [['macros.systemd', rpmmacrosdir], + ['system.conf', pkgsysconfdir], + ['user.conf', pkgsysconfdir], + ['systemd.pc', pkgconfigdatadir], + ['triggers.systemd', '']] + +foreach item : in_files + file = item[0] + dir = item[1] + + configure_file( + input : file + '.in', + output : file, + configuration : substs, + install_dir : dir == 'no' ? '' : dir) +endforeach + +install_data('org.freedesktop.systemd1.conf', + install_dir : dbuspolicydir) +install_data('org.freedesktop.systemd1.service', + install_dir : dbussystemservicedir) + +policy = configure_file( + input : 'org.freedesktop.systemd1.policy.in', + output : 'org.freedesktop.systemd1.policy', + configuration : substs) +install_data(policy, + install_dir : polkitpolicydir) + +meson.add_install_script('sh', '-c', mkdir_p.format(systemshutdowndir)) +meson.add_install_script('sh', '-c', mkdir_p.format(systemsleepdir)) +meson.add_install_script('sh', '-c', mkdir_p.format(systemgeneratordir)) +meson.add_install_script('sh', '-c', mkdir_p.format(usergeneratordir)) + +meson.add_install_script('sh', '-c', mkdir_p.format(join_paths(pkgsysconfdir, 'system'))) +meson.add_install_script('sh', '-c', mkdir_p.format(join_paths(pkgsysconfdir, 'user'))) +meson.add_install_script('sh', '-c', mkdir_p.format(join_paths(sysconfdir, 'xdg/systemd'))) diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c new file mode 100644 index 00000000..7ef5b127 --- /dev/null +++ b/src/core/mount-setup.c @@ -0,0 +1,542 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "bus-util.h" +#include "cgroup-util.h" +#include "conf-files.h" +#include "cgroup-setup.h" +#include "dev-setup.h" +#include "dirent-util.h" +#include "efi-loader.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "label.h" +#include "log.h" +#include "macro.h" +#include "mkdir.h" +#include "mount-setup.h" +#include "mountpoint-util.h" +#include "nulstr-util.h" +#include "path-util.h" +#include "set.h" +#include "smack-util.h" +#include "strv.h" +#include "user-util.h" +#include "virt.h" + +typedef enum MountMode { + MNT_NONE = 0, + MNT_FATAL = 1 << 0, + MNT_IN_CONTAINER = 1 << 1, + MNT_CHECK_WRITABLE = 1 << 2, +} MountMode; + +typedef struct MountPoint { + const char *what; + const char *where; + const char *type; + const char *options; + unsigned long flags; + bool (*condition_fn)(void); + MountMode mode; +} MountPoint; + +/* The first three entries we might need before SELinux is up. The + * fourth (securityfs) is needed by IMA to load a custom policy. The + * other ones we can delay until SELinux and IMA are loaded. When + * SMACK is enabled we need smackfs, too, so it's a fifth one. */ +#if ENABLE_SMACK +#define N_EARLY_MOUNT 5 +#else +#define N_EARLY_MOUNT 4 +#endif + +static const MountPoint mount_table[] = { + { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, + { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, + { "devtmpfs", "/dev", "devtmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, + { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + NULL, MNT_NONE }, +#if ENABLE_SMACK + { "smackfs", "/sys/fs/smackfs", "smackfs", "smackfsdef=*", MS_NOSUID|MS_NOEXEC|MS_NODEV, + mac_smack_use, MNT_FATAL }, + { "tmpfs", "/dev/shm", "tmpfs", "mode=1777,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + mac_smack_use, MNT_FATAL }, +#endif + { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, + { "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, + NULL, MNT_IN_CONTAINER }, +#if ENABLE_SMACK + { "tmpfs", "/run", "tmpfs", "mode=755,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + mac_smack_use, MNT_FATAL }, +#endif + { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, + { "cgroup2", "/sys/fs/cgroup", "cgroup2", "nsdelegate", MS_NOSUID|MS_NOEXEC|MS_NODEV, + cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, + { "cgroup2", "/sys/fs/cgroup", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + cg_is_unified_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, + { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, + cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER }, + { "cgroup2", "/sys/fs/cgroup/unified", "cgroup2", "nsdelegate", MS_NOSUID|MS_NOEXEC|MS_NODEV, + cg_is_hybrid_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, + { "cgroup2", "/sys/fs/cgroup/unified", "cgroup2", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + cg_is_hybrid_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE }, + { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd,xattr", MS_NOSUID|MS_NOEXEC|MS_NODEV, + cg_is_legacy_wanted, MNT_IN_CONTAINER }, + { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, + cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER }, + { "pstore", "/sys/fs/pstore", "pstore", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + NULL, MNT_NONE }, +#if ENABLE_EFI + { "efivarfs", "/sys/firmware/efi/efivars", "efivarfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + is_efi_boot, MNT_NONE }, +#endif + { "bpf", "/sys/fs/bpf", "bpf", "mode=700", MS_NOSUID|MS_NOEXEC|MS_NODEV, + NULL, MNT_NONE, }, +}; + +/* These are API file systems that might be mounted by other software, + * we just list them here so that we know that we should ignore them */ + +static const char ignore_paths[] = + /* SELinux file systems */ + "/sys/fs/selinux\0" + /* Container bind mounts */ + "/proc/sys\0" + "/dev/console\0" + "/proc/kmsg\0"; + +bool mount_point_is_api(const char *path) { + unsigned i; + + /* Checks if this mount point is considered "API", and hence + * should be ignored */ + + for (i = 0; i < ELEMENTSOF(mount_table); i ++) + if (path_equal(path, mount_table[i].where)) + return true; + + return path_startswith(path, "/sys/fs/cgroup/"); +} + +bool mount_point_ignore(const char *path) { + const char *i; + + NULSTR_FOREACH(i, ignore_paths) + if (path_equal(path, i)) + return true; + + return false; +} + +static int mount_one(const MountPoint *p, bool relabel) { + int r, priority; + + assert(p); + + priority = (p->mode & MNT_FATAL) ? LOG_ERR : LOG_DEBUG; + + if (p->condition_fn && !p->condition_fn()) + return 0; + + /* Relabel first, just in case */ + if (relabel) + (void) label_fix(p->where, LABEL_IGNORE_ENOENT|LABEL_IGNORE_EROFS); + + r = path_is_mount_point(p->where, NULL, AT_SYMLINK_FOLLOW); + if (r < 0 && r != -ENOENT) { + log_full_errno(priority, r, "Failed to determine whether %s is a mount point: %m", p->where); + return (p->mode & MNT_FATAL) ? r : 0; + } + if (r > 0) + return 0; + + /* Skip securityfs in a container */ + if (!(p->mode & MNT_IN_CONTAINER) && detect_container() > 0) + return 0; + + /* The access mode here doesn't really matter too much, since + * the mounted file system will take precedence anyway. */ + if (relabel) + (void) mkdir_p_label(p->where, 0755); + else + (void) mkdir_p(p->where, 0755); + + log_debug("Mounting %s to %s of type %s with options %s.", + p->what, + p->where, + p->type, + strna(p->options)); + + if (mount(p->what, + p->where, + p->type, + p->flags, + p->options) < 0) { + log_full_errno(priority, errno, "Failed to mount %s at %s: %m", p->type, p->where); + return (p->mode & MNT_FATAL) ? -errno : 0; + } + + /* Relabel again, since we now mounted something fresh here */ + if (relabel) + (void) label_fix(p->where, 0); + + if (p->mode & MNT_CHECK_WRITABLE) { + if (access(p->where, W_OK) < 0) { + r = -errno; + + (void) umount(p->where); + (void) rmdir(p->where); + + log_full_errno(priority, r, "Mount point %s not writable after mounting: %m", p->where); + return (p->mode & MNT_FATAL) ? r : 0; + } + } + + return 1; +} + +static int mount_points_setup(unsigned n, bool loaded_policy) { + unsigned i; + int r = 0; + + for (i = 0; i < n; i ++) { + int j; + + j = mount_one(mount_table + i, loaded_policy); + if (j != 0 && r >= 0) + r = j; + } + + return r; +} + +int mount_setup_early(void) { + assert_cc(N_EARLY_MOUNT <= ELEMENTSOF(mount_table)); + + /* Do a minimal mount of /proc and friends to enable the most + * basic stuff, such as SELinux */ + return mount_points_setup(N_EARLY_MOUNT, false); +} + +static const char *join_with(const char *controller) { + + static const char* const pairs[] = { + "cpu", "cpuacct", + "net_cls", "net_prio", + NULL + }; + + const char *const *x, *const *y; + + assert(controller); + + /* This will lookup which controller to mount another controller with. Input is a controller name, and output + * is the other controller name. The function works both ways: you can input one and get the other, and input + * the other to get the one. */ + + STRV_FOREACH_PAIR(x, y, pairs) { + if (streq(controller, *x)) + return *y; + if (streq(controller, *y)) + return *x; + } + + return NULL; +} + +static int symlink_controller(const char *target, const char *alias) { + const char *a; + int r; + + assert(target); + assert(alias); + + a = strjoina("/sys/fs/cgroup/", alias); + + r = symlink_idempotent(target, a, false); + if (r < 0) + return log_error_errno(r, "Failed to create symlink %s: %m", a); + +#ifdef SMACK_RUN_LABEL + const char *p; + + p = strjoina("/sys/fs/cgroup/", target); + + r = mac_smack_copy(a, p); + if (r < 0 && r != -EOPNOTSUPP) + return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", p, a); +#endif + + return 0; +} + +int mount_cgroup_controllers(void) { + _cleanup_set_free_free_ Set *controllers = NULL; + int r; + + if (!cg_is_legacy_wanted()) + return 0; + + /* Mount all available cgroup controllers that are built into the kernel. */ + r = cg_kernel_controllers(&controllers); + if (r < 0) + return log_error_errno(r, "Failed to enumerate cgroup controllers: %m"); + + for (;;) { + _cleanup_free_ char *options = NULL, *controller = NULL, *where = NULL; + const char *other_controller; + MountPoint p = { + .what = "cgroup", + .type = "cgroup", + .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV, + .mode = MNT_IN_CONTAINER, + }; + + controller = set_steal_first(controllers); + if (!controller) + break; + + /* Check if we shall mount this together with another controller */ + other_controller = join_with(controller); + if (other_controller) { + _cleanup_free_ char *c = NULL; + + /* Check if the other controller is actually available in the kernel too */ + c = set_remove(controllers, other_controller); + if (c) { + + /* Join the two controllers into one string, and maintain a stable ordering */ + if (strcmp(controller, other_controller) < 0) + options = strjoin(controller, ",", other_controller); + else + options = strjoin(other_controller, ",", controller); + if (!options) + return log_oom(); + } + } + + /* The simple case, where there's only one controller to mount together */ + if (!options) + options = TAKE_PTR(controller); + + where = path_join("/sys/fs/cgroup", options); + if (!where) + return log_oom(); + + p.where = where; + p.options = options; + + r = mount_one(&p, true); + if (r < 0) + return r; + + /* Create symlinks from the individual controller names, in case we have a joined mount */ + if (controller) + (void) symlink_controller(options, controller); + if (other_controller) + (void) symlink_controller(options, other_controller); + } + + /* Now that we mounted everything, let's make the tmpfs the cgroup file systems are mounted into read-only. */ + (void) mount("tmpfs", "/sys/fs/cgroup", "tmpfs", MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); + + return 0; +} + +#if HAVE_SELINUX || ENABLE_SMACK +static int nftw_cb( + const char *fpath, + const struct stat *sb, + int tflag, + struct FTW *ftwbuf) { + + /* No need to label /dev twice in a row... */ + if (_unlikely_(ftwbuf->level == 0)) + return FTW_CONTINUE; + + (void) label_fix(fpath, 0); + + /* /run/initramfs is static data and big, no need to + * dynamically relabel its contents at boot... */ + if (_unlikely_(ftwbuf->level == 1 && + tflag == FTW_D && + streq(fpath, "/run/initramfs"))) + return FTW_SKIP_SUBTREE; + + return FTW_CONTINUE; +}; + +static int relabel_cgroup_filesystems(void) { + int r; + struct statfs st; + + r = cg_all_unified(); + if (r == 0) { + /* Temporarily remount the root cgroup filesystem to give it a proper label. Do this + only when the filesystem has been already populated by a previous instance of systemd + running from initrd. Otherwise don't remount anything and leave the filesystem read-write + for the cgroup filesystems to be mounted inside. */ + if (statfs("/sys/fs/cgroup", &st) < 0) + return log_error_errno(errno, "Failed to determine mount flags for /sys/fs/cgroup: %m"); + + if (st.f_flags & ST_RDONLY) + (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL); + + (void) label_fix("/sys/fs/cgroup", 0); + (void) nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); + + if (st.f_flags & ST_RDONLY) + (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL); + + } else if (r < 0) + return log_error_errno(r, "Failed to determine whether we are in all unified mode: %m"); + + return 0; +} + +static int relabel_extra(void) { + _cleanup_strv_free_ char **files = NULL; + char **file; + int r, c = 0; + + /* Support for relabelling additional files or directories after loading the policy. For this, code in the + * initrd simply has to drop in *.relabel files into /run/systemd/relabel-extra.d/. We'll read all such files + * expecting one absolute path by line and will relabel each (and everyone below that in case the path refers + * to a directory). These drop-in files are supposed to be absolutely minimal, and do not understand comments + * and such. After the operation succeeded the files are removed, and the drop-in directory as well, if + * possible. + */ + + r = conf_files_list(&files, ".relabel", NULL, + CONF_FILES_FILTER_MASKED | CONF_FILES_REGULAR, + "/run/systemd/relabel-extra.d/"); + if (r < 0) + return log_error_errno(r, "Failed to enumerate /run/systemd/relabel-extra.d/, ignoring: %m"); + + STRV_FOREACH(file, files) { + _cleanup_fclose_ FILE *f = NULL; + + f = fopen(*file, "re"); + if (!f) { + log_warning_errno(errno, "Failed to open %s, ignoring: %m", *file); + continue; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) { + log_warning_errno(r, "Failed to read %s, ignoring: %m", *file); + break; + } + if (r == 0) /* EOF */ + break; + + path_simplify(line, true); + + if (!path_is_normalized(line)) { + log_warning("Path to relabel is not normalized, ignoring: %s", line); + continue; + } + + if (!path_is_absolute(line)) { + log_warning("Path to relabel is not absolute, ignoring: %s", line); + continue; + } + + log_debug("Relabelling additional file/directory '%s'.", line); + (void) label_fix(line, 0); + (void) nftw(line, nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); + c++; + } + + if (unlink(*file) < 0) + log_warning_errno(errno, "Failed to remove %s, ignoring: %m", *file); + } + + /* Remove when we complete things. */ + if (rmdir("/run/systemd/relabel-extra.d") < 0 && + errno != ENOENT) + log_warning_errno(errno, "Failed to remove /run/systemd/relabel-extra.d/ directory: %m"); + + return c; +} +#endif + +int mount_setup(bool loaded_policy) { + int r = 0; + + r = mount_points_setup(ELEMENTSOF(mount_table), loaded_policy); + if (r < 0) + return r; + +#if HAVE_SELINUX || ENABLE_SMACK + /* Nodes in devtmpfs and /run need to be manually updated for + * the appropriate labels, after mounting. The other virtual + * API file systems like /sys and /proc do not need that, they + * use the same label for all their files. */ + if (loaded_policy) { + usec_t before_relabel, after_relabel; + char timespan[FORMAT_TIMESPAN_MAX]; + const char *i; + int n_extra; + + before_relabel = now(CLOCK_MONOTONIC); + + FOREACH_STRING(i, "/dev", "/dev/shm", "/run") + (void) nftw(i, nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); + + (void) relabel_cgroup_filesystems(); + + n_extra = relabel_extra(); + + after_relabel = now(CLOCK_MONOTONIC); + + log_info("Relabelled /dev, /dev/shm, /run, /sys/fs/cgroup%s in %s.", + n_extra > 0 ? ", additional files" : "", + format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel, 0)); + } +#endif + + /* Create a few default symlinks, which are normally created + * by udevd, but some scripts might need them before we start + * udevd. */ + dev_setup(NULL, UID_INVALID, GID_INVALID); + + /* Mark the root directory as shared in regards to mount propagation. The kernel defaults to "private", but we + * think it makes more sense to have a default of "shared" so that nspawn and the container tools work out of + * the box. If specific setups need other settings they can reset the propagation mode to private if + * needed. Note that we set this only when we are invoked directly by the kernel. If we are invoked by a + * container manager we assume the container manager knows what it is doing (for example, because it set up + * some directories with different propagation modes). */ + if (detect_container() <= 0) + if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0) + log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m"); + + /* Create a few directories we always want around, Note that sd_booted() checks for /run/systemd/system, so + * this mkdir really needs to stay for good, otherwise software that copied sd-daemon.c into their sources will + * misdetect systemd. */ + (void) mkdir_label("/run/systemd", 0755); + (void) mkdir_label("/run/systemd/system", 0755); + + /* Also create /run/systemd/inaccessible nodes, so that we always have something to mount inaccessible nodes + * from. */ + (void) make_inaccessible_nodes(NULL, UID_INVALID, GID_INVALID); + + return 0; +} diff --git a/src/core/mount-setup.h b/src/core/mount-setup.h new file mode 100644 index 00000000..b4ca2cf4 --- /dev/null +++ b/src/core/mount-setup.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int mount_setup_early(void); +int mount_setup(bool loaded_policy); + +int mount_cgroup_controllers(void); + +bool mount_point_is_api(const char *path); +bool mount_point_ignore(const char *path); diff --git a/src/core/mount.c b/src/core/mount.c new file mode 100644 index 00000000..a0dfa6a1 --- /dev/null +++ b/src/core/mount.c @@ -0,0 +1,2127 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "dbus-mount.h" +#include "dbus-unit.h" +#include "device.h" +#include "exit-status.h" +#include "format-util.h" +#include "fstab-util.h" +#include "libmount-util.h" +#include "log.h" +#include "manager.h" +#include "mkdir.h" +#include "mount-setup.h" +#include "mount.h" +#include "mountpoint-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "serialize.h" +#include "special.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "unit.h" + +#define RETRY_UMOUNT_MAX 32 + +static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = { + [MOUNT_DEAD] = UNIT_INACTIVE, + [MOUNT_MOUNTING] = UNIT_ACTIVATING, + [MOUNT_MOUNTING_DONE] = UNIT_ACTIVATING, + [MOUNT_MOUNTED] = UNIT_ACTIVE, + [MOUNT_REMOUNTING] = UNIT_RELOADING, + [MOUNT_UNMOUNTING] = UNIT_DEACTIVATING, + [MOUNT_REMOUNTING_SIGTERM] = UNIT_RELOADING, + [MOUNT_REMOUNTING_SIGKILL] = UNIT_RELOADING, + [MOUNT_UNMOUNTING_SIGTERM] = UNIT_DEACTIVATING, + [MOUNT_UNMOUNTING_SIGKILL] = UNIT_DEACTIVATING, + [MOUNT_FAILED] = UNIT_FAILED, + [MOUNT_CLEANING] = UNIT_MAINTENANCE, +}; + +static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); +static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); +static int mount_process_proc_self_mountinfo(Manager *m); + +static bool MOUNT_STATE_WITH_PROCESS(MountState state) { + return IN_SET(state, + MOUNT_MOUNTING, + MOUNT_MOUNTING_DONE, + MOUNT_REMOUNTING, + MOUNT_REMOUNTING_SIGTERM, + MOUNT_REMOUNTING_SIGKILL, + MOUNT_UNMOUNTING, + MOUNT_UNMOUNTING_SIGTERM, + MOUNT_UNMOUNTING_SIGKILL, + MOUNT_CLEANING); +} + +static bool mount_is_network(const MountParameters *p) { + assert(p); + + if (fstab_test_option(p->options, "_netdev\0")) + return true; + + if (p->fstype && fstype_is_network(p->fstype)) + return true; + + return false; +} + +static bool mount_is_loop(const MountParameters *p) { + assert(p); + + if (fstab_test_option(p->options, "loop\0")) + return true; + + return false; +} + +static bool mount_is_bind(const MountParameters *p) { + assert(p); + + if (fstab_test_option(p->options, "bind\0" "rbind\0")) + return true; + + if (p->fstype && STR_IN_SET(p->fstype, "bind", "rbind")) + return true; + + return false; +} + +static bool mount_is_bound_to_device(const Mount *m) { + const MountParameters *p; + + if (m->from_fragment) + return true; + + p = &m->parameters_proc_self_mountinfo; + return fstab_test_option(p->options, "x-systemd.device-bound\0"); +} + +static bool mount_needs_quota(const MountParameters *p) { + assert(p); + + /* Quotas are not enabled on network filesystems, but we want them, for example, on storage connected via + * iscsi. We hence don't use mount_is_network() here, as that would also return true for _netdev devices. */ + if (p->fstype && fstype_is_network(p->fstype)) + return false; + + if (mount_is_bind(p)) + return false; + + return fstab_test_option(p->options, + "usrquota\0" "grpquota\0" "quota\0" "usrjquota\0" "grpjquota\0"); +} + +static void mount_init(Unit *u) { + Mount *m = MOUNT(u); + + assert(u); + assert(u->load_state == UNIT_STUB); + + m->timeout_usec = u->manager->default_timeout_start_usec; + + m->exec_context.std_output = u->manager->default_std_output; + m->exec_context.std_error = u->manager->default_std_error; + + m->directory_mode = 0755; + + /* We need to make sure that /usr/bin/mount is always called + * in the same process group as us, so that the autofs kernel + * side doesn't send us another mount request while we are + * already trying to comply its last one. */ + m->exec_context.same_pgrp = true; + + m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; + + u->ignore_on_isolate = true; +} + +static int mount_arm_timer(Mount *m, usec_t usec) { + int r; + + assert(m); + + if (m->timer_event_source) { + r = sd_event_source_set_time(m->timer_event_source, usec); + if (r < 0) + return r; + + return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT); + } + + if (usec == USEC_INFINITY) + return 0; + + r = sd_event_add_time( + UNIT(m)->manager->event, + &m->timer_event_source, + CLOCK_MONOTONIC, + usec, 0, + mount_dispatch_timer, m); + if (r < 0) + return r; + + (void) sd_event_source_set_description(m->timer_event_source, "mount-timer"); + + return 0; +} + +static void mount_unwatch_control_pid(Mount *m) { + assert(m); + + if (m->control_pid <= 0) + return; + + unit_unwatch_pid(UNIT(m), m->control_pid); + m->control_pid = 0; +} + +static void mount_parameters_done(MountParameters *p) { + assert(p); + + p->what = mfree(p->what); + p->options = mfree(p->options); + p->fstype = mfree(p->fstype); +} + +static void mount_done(Unit *u) { + Mount *m = MOUNT(u); + + assert(m); + + m->where = mfree(m->where); + + mount_parameters_done(&m->parameters_proc_self_mountinfo); + mount_parameters_done(&m->parameters_fragment); + + m->exec_runtime = exec_runtime_unref(m->exec_runtime, false); + exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX); + m->control_command = NULL; + + dynamic_creds_unref(&m->dynamic_creds); + + mount_unwatch_control_pid(m); + + m->timer_event_source = sd_event_source_unref(m->timer_event_source); +} + +_pure_ static MountParameters* get_mount_parameters_fragment(Mount *m) { + assert(m); + + if (m->from_fragment) + return &m->parameters_fragment; + + return NULL; +} + +_pure_ static MountParameters* get_mount_parameters(Mount *m) { + assert(m); + + if (m->from_proc_self_mountinfo) + return &m->parameters_proc_self_mountinfo; + + return get_mount_parameters_fragment(m); +} + +static int update_parameters_proc_self_mountinfo( + Mount *m, + const char *what, + const char *options, + const char *fstype) { + + MountParameters *p; + int r, q, w; + + p = &m->parameters_proc_self_mountinfo; + + r = free_and_strdup(&p->what, what); + if (r < 0) + return r; + + q = free_and_strdup(&p->options, options); + if (q < 0) + return q; + + w = free_and_strdup(&p->fstype, fstype); + if (w < 0) + return w; + + return r > 0 || q > 0 || w > 0; +} + +static int mount_add_mount_dependencies(Mount *m) { + MountParameters *pm; + Unit *other; + Iterator i; + Set *s; + int r; + + assert(m); + + if (!path_equal(m->where, "/")) { + _cleanup_free_ char *parent = NULL; + + /* Adds in links to other mount points that might lie further up in the hierarchy */ + + parent = dirname_malloc(m->where); + if (!parent) + return -ENOMEM; + + r = unit_require_mounts_for(UNIT(m), parent, UNIT_DEPENDENCY_IMPLICIT); + if (r < 0) + return r; + } + + /* Adds in dependencies to other mount points that might be needed for the source path (if this is a bind mount + * or a loop mount) to be available. */ + pm = get_mount_parameters_fragment(m); + if (pm && pm->what && + path_is_absolute(pm->what) && + (mount_is_bind(pm) || mount_is_loop(pm) || !mount_is_network(pm))) { + + r = unit_require_mounts_for(UNIT(m), pm->what, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + } + + /* Adds in dependencies to other units that use this path or paths further down in the hierarchy */ + s = manager_get_units_requiring_mounts_for(UNIT(m)->manager, m->where); + SET_FOREACH(other, s, i) { + + if (other->load_state != UNIT_LOADED) + continue; + + if (other == UNIT(m)) + continue; + + r = unit_add_dependency(other, UNIT_AFTER, UNIT(m), true, UNIT_DEPENDENCY_PATH); + if (r < 0) + return r; + + if (UNIT(m)->fragment_path) { + /* If we have fragment configuration, then make this dependency required */ + r = unit_add_dependency(other, UNIT_REQUIRES, UNIT(m), true, UNIT_DEPENDENCY_PATH); + if (r < 0) + return r; + } + } + + return 0; +} + +static int mount_add_device_dependencies(Mount *m) { + UnitDependencyMask mask; + MountParameters *p; + UnitDependency dep; + int r; + + assert(m); + + p = get_mount_parameters(m); + if (!p) + return 0; + + if (!p->what) + return 0; + + if (mount_is_bind(p)) + return 0; + + if (!is_device_path(p->what)) + return 0; + + /* /dev/root is a really weird thing, it's not a real device, + * but just a path the kernel exports for the root file system + * specified on the kernel command line. Ignore it here. */ + if (path_equal(p->what, "/dev/root")) + return 0; + + if (path_equal(m->where, "/")) + return 0; + + /* Mount units from /proc/self/mountinfo are not bound to devices + * by default since they're subject to races when devices are + * unplugged. But the user can still force this dep with an + * appropriate option (or udev property) so the mount units are + * automatically stopped when the device disappears suddenly. */ + dep = mount_is_bound_to_device(m) ? UNIT_BINDS_TO : UNIT_REQUIRES; + + /* We always use 'what' from /proc/self/mountinfo if mounted */ + mask = m->from_proc_self_mountinfo ? UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT : UNIT_DEPENDENCY_FILE; + + r = unit_add_node_dependency(UNIT(m), p->what, dep, mask); + if (r < 0) + return r; + + return 0; +} + +static int mount_add_quota_dependencies(Mount *m) { + UnitDependencyMask mask; + MountParameters *p; + int r; + + assert(m); + + if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) + return 0; + + p = get_mount_parameters_fragment(m); + if (!p) + return 0; + + if (!mount_needs_quota(p)) + return 0; + + mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT; + + r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTACHECK_SERVICE, true, mask); + if (r < 0) + return r; + + r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_WANTS, SPECIAL_QUOTAON_SERVICE, true, mask); + if (r < 0) + return r; + + return 0; +} + +static bool mount_is_extrinsic(Mount *m) { + MountParameters *p; + assert(m); + + /* Returns true for all units that are "magic" and should be excluded from the usual start-up and shutdown + * dependencies. We call them "extrinsic" here, as they are generally mounted outside of the systemd dependency + * logic. We shouldn't attempt to manage them ourselves but it's fine if the user operates on them with us. */ + + if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) /* We only automatically manage mounts if we are in system mode */ + return true; + + if (UNIT(m)->perpetual) /* All perpetual units never change state */ + return true; + + if (PATH_IN_SET(m->where, /* Don't bother with the OS data itself */ + "/", /* (strictly speaking redundant: should already be covered by the perpetual flag check above) */ + "/usr", + "/etc")) + return true; + + if (PATH_STARTSWITH_SET(m->where, + "/run/initramfs", /* This should stay around from before we boot until after we shutdown */ + "/proc", /* All of this is API VFS */ + "/sys", /* … dito … */ + "/dev")) /* … dito … */ + return true; + + /* If this is an initrd mount, and we are not in the initrd, then leave this around forever, too. */ + p = get_mount_parameters(m); + if (p && fstab_test_option(p->options, "x-initrd.mount\0") && !in_initrd()) + return true; + + return false; +} + +static int mount_add_default_dependencies(Mount *m) { + const char *after, *before; + UnitDependencyMask mask; + MountParameters *p; + bool nofail; + int r; + + assert(m); + + if (!UNIT(m)->default_dependencies) + return 0; + + /* We do not add any default dependencies to /, /usr or /run/initramfs/, since they are guaranteed to stay + * mounted the whole time, since our system is on it. Also, don't bother with anything mounted below virtual + * file systems, it's also going to be virtual, and hence not worth the effort. */ + if (mount_is_extrinsic(m)) + return 0; + + p = get_mount_parameters(m); + if (!p) + return 0; + + mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT; + nofail = m->from_fragment ? fstab_test_yes_no_option(m->parameters_fragment.options, "nofail\0" "fail\0") : false; + + if (mount_is_network(p)) { + /* We order ourselves after network.target. This is + * primarily useful at shutdown: services that take + * down the network should order themselves before + * network.target, so that they are shut down only + * after this mount unit is stopped. */ + + r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, true, mask); + if (r < 0) + return r; + + /* We pull in network-online.target, and order + * ourselves after it. This is useful at start-up to + * actively pull in tools that want to be started + * before we start mounting network file systems, and + * whose purpose it is to delay this until the network + * is "up". */ + + r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, true, mask); + if (r < 0) + return r; + + after = SPECIAL_REMOTE_FS_PRE_TARGET; + before = SPECIAL_REMOTE_FS_TARGET; + } else { + after = SPECIAL_LOCAL_FS_PRE_TARGET; + before = SPECIAL_LOCAL_FS_TARGET; + } + + if (!nofail) { + r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask); + if (r < 0) + return r; + } + + r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask); + if (r < 0) + return r; + + r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, mask); + if (r < 0) + return r; + + /* If this is a tmpfs mount then we have to unmount it before we try to deactivate swaps */ + if (streq_ptr(p->fstype, "tmpfs")) { + r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, true, mask); + if (r < 0) + return r; + } + + return 0; +} + +static int mount_verify(Mount *m) { + _cleanup_free_ char *e = NULL; + MountParameters *p; + int r; + + assert(m); + assert(UNIT(m)->load_state == UNIT_LOADED); + + if (!m->from_fragment && !m->from_proc_self_mountinfo && !UNIT(m)->perpetual) + return -ENOENT; + + r = unit_name_from_path(m->where, ".mount", &e); + if (r < 0) + return log_unit_error_errno(UNIT(m), r, "Failed to generate unit name from mount path: %m"); + + if (!unit_has_name(UNIT(m), e)) { + log_unit_error(UNIT(m), "Where= setting doesn't match unit name. Refusing."); + return -ENOEXEC; + } + + if (mount_point_is_api(m->where) || mount_point_ignore(m->where)) { + log_unit_error(UNIT(m), "Cannot create mount unit for API file system %s. Refusing.", m->where); + return -ENOEXEC; + } + + p = get_mount_parameters_fragment(m); + if (p && !p->what && !UNIT(m)->perpetual) + return log_unit_error_errno(UNIT(m), SYNTHETIC_ERRNO(ENOEXEC), + "What= setting is missing. Refusing."); + + if (m->exec_context.pam_name && m->kill_context.kill_mode != KILL_CONTROL_GROUP) { + log_unit_error(UNIT(m), "Unit has PAM enabled. Kill mode must be set to control-group'. Refusing."); + return -ENOEXEC; + } + + return 0; +} + +static int mount_add_non_exec_dependencies(Mount *m) { + int r; + assert(m); + + /* Adds in all dependencies directly responsible for ordering the mount, as opposed to dependencies + * resulting from the ExecContext and such. */ + + r = mount_add_device_dependencies(m); + if (r < 0) + return r; + + r = mount_add_mount_dependencies(m); + if (r < 0) + return r; + + r = mount_add_quota_dependencies(m); + if (r < 0) + return r; + + r = mount_add_default_dependencies(m); + if (r < 0) + return r; + + return 0; +} + +static int mount_add_extras(Mount *m) { + Unit *u = UNIT(m); + int r; + + assert(m); + + /* Note: this call might be called after we already have been loaded once (and even when it has already been + * activated), in case data from /proc/self/mountinfo has changed. This means all code here needs to be ready + * to run with an already set up unit. */ + + if (u->fragment_path) + m->from_fragment = true; + + if (!m->where) { + r = unit_name_to_path(u->id, &m->where); + if (r < 0) + return r; + } + + path_simplify(m->where, false); + + if (!u->description) { + r = unit_set_description(u, m->where); + if (r < 0) + return r; + } + + r = unit_patch_contexts(u); + if (r < 0) + return r; + + r = unit_add_exec_dependencies(u, &m->exec_context); + if (r < 0) + return r; + + r = unit_set_default_slice(u); + if (r < 0) + return r; + + r = mount_add_non_exec_dependencies(m); + if (r < 0) + return r; + + return 0; +} + +static void mount_load_root_mount(Unit *u) { + assert(u); + + if (!unit_has_name(u, SPECIAL_ROOT_MOUNT)) + return; + + u->perpetual = true; + u->default_dependencies = false; + + /* The stdio/kmsg bridge socket is on /, in order to avoid a dep loop, don't use kmsg logging for -.mount */ + MOUNT(u)->exec_context.std_output = EXEC_OUTPUT_NULL; + MOUNT(u)->exec_context.std_input = EXEC_INPUT_NULL; + + if (!u->description) + u->description = strdup("Root Mount"); +} + +static int mount_load(Unit *u) { + Mount *m = MOUNT(u); + int r, q = 0; + + assert(u); + assert(u->load_state == UNIT_STUB); + + mount_load_root_mount(u); + + bool fragment_optional = m->from_proc_self_mountinfo || u->perpetual; + r = unit_load_fragment_and_dropin(u, !fragment_optional); + + /* Add in some extras. Note we do this in all cases (even if we failed to load the unit) when announced by the + * kernel, because we need some things to be set up no matter what when the kernel establishes a mount and thus + * we need to update the state in our unit to track it. After all, consider that we don't allow changing the + * 'slice' field for a unit once it is active. */ + if (u->load_state == UNIT_LOADED || m->from_proc_self_mountinfo || u->perpetual) + q = mount_add_extras(m); + + if (r < 0) + return r; + if (q < 0) + return q; + if (u->load_state != UNIT_LOADED) + return 0; + + return mount_verify(m); +} + +static void mount_set_state(Mount *m, MountState state) { + MountState old_state; + assert(m); + + if (m->state != state) + bus_unit_send_pending_change_signal(UNIT(m), false); + + old_state = m->state; + m->state = state; + + if (!MOUNT_STATE_WITH_PROCESS(state)) { + m->timer_event_source = sd_event_source_unref(m->timer_event_source); + mount_unwatch_control_pid(m); + m->control_command = NULL; + m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; + } + + if (state != old_state) + log_unit_debug(UNIT(m), "Changed %s -> %s", mount_state_to_string(old_state), mount_state_to_string(state)); + + unit_notify(UNIT(m), state_translation_table[old_state], state_translation_table[state], + m->reload_result == MOUNT_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE); +} + +static int mount_coldplug(Unit *u) { + Mount *m = MOUNT(u); + MountState new_state = MOUNT_DEAD; + int r; + + assert(m); + assert(m->state == MOUNT_DEAD); + + if (m->deserialized_state != m->state) + new_state = m->deserialized_state; + else if (m->from_proc_self_mountinfo) + new_state = MOUNT_MOUNTED; + + if (new_state == m->state) + return 0; + + if (m->control_pid > 0 && + pid_is_unwaited(m->control_pid) && + MOUNT_STATE_WITH_PROCESS(new_state)) { + + r = unit_watch_pid(UNIT(m), m->control_pid, false); + if (r < 0) + return r; + + r = mount_arm_timer(m, usec_add(u->state_change_timestamp.monotonic, m->timeout_usec)); + if (r < 0) + return r; + } + + if (!IN_SET(new_state, MOUNT_DEAD, MOUNT_FAILED)) { + (void) unit_setup_dynamic_creds(u); + (void) unit_setup_exec_runtime(u); + } + + mount_set_state(m, new_state); + return 0; +} + +static void mount_dump(Unit *u, FILE *f, const char *prefix) { + char buf[FORMAT_TIMESPAN_MAX]; + Mount *m = MOUNT(u); + MountParameters *p; + + assert(m); + assert(f); + + p = get_mount_parameters(m); + + fprintf(f, + "%sMount State: %s\n" + "%sResult: %s\n" + "%sClean Result: %s\n" + "%sWhere: %s\n" + "%sWhat: %s\n" + "%sFile System Type: %s\n" + "%sOptions: %s\n" + "%sFrom /proc/self/mountinfo: %s\n" + "%sFrom fragment: %s\n" + "%sExtrinsic: %s\n" + "%sDirectoryMode: %04o\n" + "%sSloppyOptions: %s\n" + "%sLazyUnmount: %s\n" + "%sForceUnmount: %s\n" + "%sTimeoutSec: %s\n", + prefix, mount_state_to_string(m->state), + prefix, mount_result_to_string(m->result), + prefix, mount_result_to_string(m->clean_result), + prefix, m->where, + prefix, p ? strna(p->what) : "n/a", + prefix, p ? strna(p->fstype) : "n/a", + prefix, p ? strna(p->options) : "n/a", + prefix, yes_no(m->from_proc_self_mountinfo), + prefix, yes_no(m->from_fragment), + prefix, yes_no(mount_is_extrinsic(m)), + prefix, m->directory_mode, + prefix, yes_no(m->sloppy_options), + prefix, yes_no(m->lazy_unmount), + prefix, yes_no(m->force_unmount), + prefix, format_timespan(buf, sizeof(buf), m->timeout_usec, USEC_PER_SEC)); + + if (m->control_pid > 0) + fprintf(f, + "%sControl PID: "PID_FMT"\n", + prefix, m->control_pid); + + exec_context_dump(&m->exec_context, f, prefix); + kill_context_dump(&m->kill_context, f, prefix); + cgroup_context_dump(UNIT(m), f, prefix); +} + +static int mount_spawn(Mount *m, ExecCommand *c, pid_t *_pid) { + + _cleanup_(exec_params_clear) ExecParameters exec_params = { + .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + .stdin_fd = -1, + .stdout_fd = -1, + .stderr_fd = -1, + .exec_fd = -1, + }; + pid_t pid; + int r; + + assert(m); + assert(c); + assert(_pid); + + r = unit_prepare_exec(UNIT(m)); + if (r < 0) + return r; + + r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec)); + if (r < 0) + return r; + + r = unit_set_exec_params(UNIT(m), &exec_params); + if (r < 0) + return r; + + r = exec_spawn(UNIT(m), + c, + &m->exec_context, + &exec_params, + m->exec_runtime, + &m->dynamic_creds, + &pid); + if (r < 0) + return r; + + r = unit_watch_pid(UNIT(m), pid, true); + if (r < 0) + return r; + + *_pid = pid; + + return 0; +} + +static void mount_enter_dead(Mount *m, MountResult f) { + assert(m); + + if (m->result == MOUNT_SUCCESS) + m->result = f; + + unit_log_result(UNIT(m), m->result == MOUNT_SUCCESS, mount_result_to_string(m->result)); + mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD); + + m->exec_runtime = exec_runtime_unref(m->exec_runtime, true); + + unit_destroy_runtime_directory(UNIT(m), &m->exec_context); + + unit_unref_uid_gid(UNIT(m), true); + + dynamic_creds_destroy(&m->dynamic_creds); + + /* Any dependencies based on /proc/self/mountinfo are now stale */ + unit_remove_dependencies(UNIT(m), UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT); +} + +static void mount_enter_mounted(Mount *m, MountResult f) { + assert(m); + + if (m->result == MOUNT_SUCCESS) + m->result = f; + + mount_set_state(m, MOUNT_MOUNTED); +} + +static void mount_enter_dead_or_mounted(Mount *m, MountResult f) { + assert(m); + + /* Enter DEAD or MOUNTED state, depending on what the kernel currently says about the mount point. We use this + * whenever we executed an operation, so that our internal state reflects what the kernel says again, after all + * ultimately we just mirror the kernel's internal state on this. */ + + if (m->from_proc_self_mountinfo) + mount_enter_mounted(m, f); + else + mount_enter_dead(m, f); +} + +static int state_to_kill_operation(MountState state) { + switch (state) { + + case MOUNT_REMOUNTING_SIGTERM: + return KILL_RESTART; + + case MOUNT_UNMOUNTING_SIGTERM: + return KILL_TERMINATE; + + case MOUNT_REMOUNTING_SIGKILL: + case MOUNT_UNMOUNTING_SIGKILL: + return KILL_KILL; + + default: + return _KILL_OPERATION_INVALID; + } +} + +static void mount_enter_signal(Mount *m, MountState state, MountResult f) { + int r; + + assert(m); + + if (m->result == MOUNT_SUCCESS) + m->result = f; + + r = unit_kill_context( + UNIT(m), + &m->kill_context, + state_to_kill_operation(state), + -1, + m->control_pid, + false); + if (r < 0) + goto fail; + + if (r > 0) { + r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec)); + if (r < 0) + goto fail; + + mount_set_state(m, state); + } else if (state == MOUNT_REMOUNTING_SIGTERM && m->kill_context.send_sigkill) + mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS); + else if (IN_SET(state, MOUNT_REMOUNTING_SIGTERM, MOUNT_REMOUNTING_SIGKILL)) + mount_enter_mounted(m, MOUNT_SUCCESS); + else if (state == MOUNT_UNMOUNTING_SIGTERM && m->kill_context.send_sigkill) + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS); + else + mount_enter_dead_or_mounted(m, MOUNT_SUCCESS); + + return; + +fail: + log_unit_warning_errno(UNIT(m), r, "Failed to kill processes: %m"); + mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES); +} + +static void mount_enter_unmounting(Mount *m) { + int r; + + assert(m); + + /* Start counting our attempts */ + if (!IN_SET(m->state, + MOUNT_UNMOUNTING, + MOUNT_UNMOUNTING_SIGTERM, + MOUNT_UNMOUNTING_SIGKILL)) + m->n_retry_umount = 0; + + m->control_command_id = MOUNT_EXEC_UNMOUNT; + m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT; + + r = exec_command_set(m->control_command, UMOUNT_PATH, m->where, "-c", NULL); + if (r >= 0 && m->lazy_unmount) + r = exec_command_append(m->control_command, "-l", NULL); + if (r >= 0 && m->force_unmount) + r = exec_command_append(m->control_command, "-f", NULL); + if (r < 0) + goto fail; + + mount_unwatch_control_pid(m); + + r = mount_spawn(m, m->control_command, &m->control_pid); + if (r < 0) + goto fail; + + mount_set_state(m, MOUNT_UNMOUNTING); + + return; + +fail: + log_unit_warning_errno(UNIT(m), r, "Failed to run 'umount' task: %m"); + mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES); +} + +static void mount_enter_mounting(Mount *m) { + int r; + MountParameters *p; + + assert(m); + + r = unit_fail_if_noncanonical(UNIT(m), m->where); + if (r < 0) + goto fail; + + (void) mkdir_p_label(m->where, m->directory_mode); + + unit_warn_if_dir_nonempty(UNIT(m), m->where); + unit_warn_leftover_processes(UNIT(m)); + + m->control_command_id = MOUNT_EXEC_MOUNT; + m->control_command = m->exec_command + MOUNT_EXEC_MOUNT; + + /* Create the source directory for bind-mounts if needed */ + p = get_mount_parameters_fragment(m); + if (p && mount_is_bind(p)) + (void) mkdir_p_label(p->what, m->directory_mode); + + if (p) { + _cleanup_free_ char *opts = NULL; + + r = fstab_filter_options(p->options, "nofail\0" "noauto\0" "auto\0", NULL, NULL, &opts); + if (r < 0) + goto fail; + + r = exec_command_set(m->control_command, MOUNT_PATH, p->what, m->where, NULL); + if (r >= 0 && m->sloppy_options) + r = exec_command_append(m->control_command, "-s", NULL); + if (r >= 0 && p->fstype) + r = exec_command_append(m->control_command, "-t", p->fstype, NULL); + if (r >= 0 && !isempty(opts)) + r = exec_command_append(m->control_command, "-o", opts, NULL); + } else + r = -ENOENT; + if (r < 0) + goto fail; + + mount_unwatch_control_pid(m); + + r = mount_spawn(m, m->control_command, &m->control_pid); + if (r < 0) + goto fail; + + mount_set_state(m, MOUNT_MOUNTING); + + return; + +fail: + log_unit_warning_errno(UNIT(m), r, "Failed to run 'mount' task: %m"); + mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES); +} + +static void mount_set_reload_result(Mount *m, MountResult result) { + assert(m); + + /* Only store the first error we encounter */ + if (m->reload_result != MOUNT_SUCCESS) + return; + + m->reload_result = result; +} + +static void mount_enter_remounting(Mount *m) { + int r; + MountParameters *p; + + assert(m); + + /* Reset reload result when we are about to start a new remount operation */ + m->reload_result = MOUNT_SUCCESS; + + m->control_command_id = MOUNT_EXEC_REMOUNT; + m->control_command = m->exec_command + MOUNT_EXEC_REMOUNT; + + p = get_mount_parameters_fragment(m); + if (p) { + const char *o; + + if (p->options) + o = strjoina("remount,", p->options); + else + o = "remount"; + + r = exec_command_set(m->control_command, MOUNT_PATH, + p->what, m->where, + "-o", o, NULL); + if (r >= 0 && m->sloppy_options) + r = exec_command_append(m->control_command, "-s", NULL); + if (r >= 0 && p->fstype) + r = exec_command_append(m->control_command, "-t", p->fstype, NULL); + } else + r = -ENOENT; + if (r < 0) + goto fail; + + mount_unwatch_control_pid(m); + + r = mount_spawn(m, m->control_command, &m->control_pid); + if (r < 0) + goto fail; + + mount_set_state(m, MOUNT_REMOUNTING); + + return; + +fail: + log_unit_warning_errno(UNIT(m), r, "Failed to run 'remount' task: %m"); + mount_set_reload_result(m, MOUNT_FAILURE_RESOURCES); + mount_enter_dead_or_mounted(m, MOUNT_SUCCESS); +} + +static void mount_cycle_clear(Mount *m) { + assert(m); + + /* Clear all state we shall forget for this new cycle */ + + m->result = MOUNT_SUCCESS; + m->reload_result = MOUNT_SUCCESS; + exec_command_reset_status_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX); + UNIT(m)->reset_accounting = true; +} + +static int mount_start(Unit *u) { + Mount *m = MOUNT(u); + int r; + + assert(m); + + /* We cannot fulfill this request right now, try again later + * please! */ + if (IN_SET(m->state, + MOUNT_UNMOUNTING, + MOUNT_UNMOUNTING_SIGTERM, + MOUNT_UNMOUNTING_SIGKILL, + MOUNT_CLEANING)) + return -EAGAIN; + + /* Already on it! */ + if (m->state == MOUNT_MOUNTING) + return 0; + + assert(IN_SET(m->state, MOUNT_DEAD, MOUNT_FAILED)); + + r = unit_test_start_limit(u); + if (r < 0) { + mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT); + return r; + } + + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + + mount_cycle_clear(m); + mount_enter_mounting(m); + + return 1; +} + +static int mount_stop(Unit *u) { + Mount *m = MOUNT(u); + + assert(m); + + switch (m->state) { + + case MOUNT_UNMOUNTING: + case MOUNT_UNMOUNTING_SIGKILL: + case MOUNT_UNMOUNTING_SIGTERM: + /* Already on it */ + return 0; + + case MOUNT_MOUNTING: + case MOUNT_MOUNTING_DONE: + case MOUNT_REMOUNTING: + /* If we are still waiting for /bin/mount, we go directly into kill mode. */ + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_SUCCESS); + return 0; + + case MOUNT_REMOUNTING_SIGTERM: + /* If we are already waiting for a hung remount, convert this to the matching unmounting state */ + mount_set_state(m, MOUNT_UNMOUNTING_SIGTERM); + return 0; + + case MOUNT_REMOUNTING_SIGKILL: + /* as above */ + mount_set_state(m, MOUNT_UNMOUNTING_SIGKILL); + return 0; + + case MOUNT_MOUNTED: + mount_enter_unmounting(m); + return 1; + + case MOUNT_CLEANING: + /* If we are currently cleaning, then abort it, brutally. */ + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS); + return 0; + + default: + assert_not_reached("Unexpected state."); + } +} + +static int mount_reload(Unit *u) { + Mount *m = MOUNT(u); + + assert(m); + assert(m->state == MOUNT_MOUNTED); + + mount_enter_remounting(m); + + return 1; +} + +static int mount_serialize(Unit *u, FILE *f, FDSet *fds) { + Mount *m = MOUNT(u); + + assert(m); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", mount_state_to_string(m->state)); + (void) serialize_item(f, "result", mount_result_to_string(m->result)); + (void) serialize_item(f, "reload-result", mount_result_to_string(m->reload_result)); + (void) serialize_item_format(f, "n-retry-umount", "%u", m->n_retry_umount); + + if (m->control_pid > 0) + (void) serialize_item_format(f, "control-pid", PID_FMT, m->control_pid); + + if (m->control_command_id >= 0) + (void) serialize_item(f, "control-command", mount_exec_command_to_string(m->control_command_id)); + + return 0; +} + +static int mount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Mount *m = MOUNT(u); + int r; + + assert(u); + assert(key); + assert(value); + assert(fds); + + if (streq(key, "state")) { + MountState state; + + if ((state = mount_state_from_string(value)) < 0) + log_unit_debug(u, "Failed to parse state value: %s", value); + else + m->deserialized_state = state; + + } else if (streq(key, "result")) { + MountResult f; + + f = mount_result_from_string(value); + if (f < 0) + log_unit_debug(u, "Failed to parse result value: %s", value); + else if (f != MOUNT_SUCCESS) + m->result = f; + + } else if (streq(key, "reload-result")) { + MountResult f; + + f = mount_result_from_string(value); + if (f < 0) + log_unit_debug(u, "Failed to parse reload result value: %s", value); + else if (f != MOUNT_SUCCESS) + m->reload_result = f; + + } else if (streq(key, "n-retry-umount")) { + + r = safe_atou(value, &m->n_retry_umount); + if (r < 0) + log_unit_debug(u, "Failed to parse n-retry-umount value: %s", value); + + } else if (streq(key, "control-pid")) { + + if (parse_pid(value, &m->control_pid) < 0) + log_unit_debug(u, "Failed to parse control-pid value: %s", value); + + } else if (streq(key, "control-command")) { + MountExecCommand id; + + id = mount_exec_command_from_string(value); + if (id < 0) + log_unit_debug(u, "Failed to parse exec-command value: %s", value); + else { + m->control_command_id = id; + m->control_command = m->exec_command + id; + } + } else + log_unit_debug(u, "Unknown serialization key: %s", key); + + return 0; +} + +_pure_ static UnitActiveState mount_active_state(Unit *u) { + assert(u); + + return state_translation_table[MOUNT(u)->state]; +} + +_pure_ static const char *mount_sub_state_to_string(Unit *u) { + assert(u); + + return mount_state_to_string(MOUNT(u)->state); +} + +_pure_ static bool mount_may_gc(Unit *u) { + Mount *m = MOUNT(u); + + assert(m); + + if (m->from_proc_self_mountinfo) + return false; + + return true; +} + +static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { + Mount *m = MOUNT(u); + MountResult f; + + assert(m); + assert(pid >= 0); + + if (pid != m->control_pid) + return; + + /* So here's the thing, we really want to know before /usr/bin/mount or /usr/bin/umount exit whether + * they established/remove a mount. This is important when mounting, but even more so when unmounting + * since we need to deal with nested mounts and otherwise cannot safely determine whether to repeat + * the unmounts. In theory, the kernel fires /proc/self/mountinfo changes off before returning from + * the mount() or umount() syscalls, and thus we should see the changes to the proc file before we + * process the waitid() for the /usr/bin/(u)mount processes. However, this is unfortunately racy: we + * have to waitid() for processes using P_ALL (since we need to reap unexpected children that got + * reparented to PID 1), but when using P_ALL we might end up reaping processes that terminated just + * instants ago, i.e. already after our last event loop iteration (i.e. after the last point we might + * have noticed /proc/self/mountinfo events via epoll). This means event loop priorities for + * processing SIGCHLD vs. /proc/self/mountinfo IO events are not as relevant as we want. To fix that + * race, let's explicitly scan /proc/self/mountinfo before we start processing /usr/bin/(u)mount + * dying. It's ugly, but it makes our ordering systematic again, and makes sure we always see + * /proc/self/mountinfo changes before our mount/umount exits. */ + (void) mount_process_proc_self_mountinfo(u->manager); + + m->control_pid = 0; + + if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL)) + f = MOUNT_SUCCESS; + else if (code == CLD_EXITED) + f = MOUNT_FAILURE_EXIT_CODE; + else if (code == CLD_KILLED) + f = MOUNT_FAILURE_SIGNAL; + else if (code == CLD_DUMPED) + f = MOUNT_FAILURE_CORE_DUMP; + else + assert_not_reached("Unknown code"); + + if (IN_SET(m->state, MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGKILL, MOUNT_REMOUNTING_SIGTERM)) + mount_set_reload_result(m, f); + else if (m->result == MOUNT_SUCCESS) + m->result = f; + + if (m->control_command) { + exec_status_exit(&m->control_command->exec_status, &m->exec_context, pid, code, status); + + m->control_command = NULL; + m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; + } + + unit_log_process_exit( + u, + "Mount process", + mount_exec_command_to_string(m->control_command_id), + f == MOUNT_SUCCESS, + code, status); + + /* Note that due to the io event priority logic, we can be sure the new mountinfo is loaded + * before we process the SIGCHLD for the mount command. */ + + switch (m->state) { + + case MOUNT_MOUNTING: + /* Our mount point has not appeared in mountinfo. Something went wrong. */ + + if (f == MOUNT_SUCCESS) { + /* Either /bin/mount has an unexpected definition of success, + * or someone raced us and we lost. */ + log_unit_warning(UNIT(m), "Mount process finished, but there is no mount."); + f = MOUNT_FAILURE_PROTOCOL; + } + mount_enter_dead(m, f); + break; + + case MOUNT_MOUNTING_DONE: + mount_enter_mounted(m, f); + break; + + case MOUNT_REMOUNTING: + case MOUNT_REMOUNTING_SIGTERM: + case MOUNT_REMOUNTING_SIGKILL: + mount_enter_dead_or_mounted(m, MOUNT_SUCCESS); + break; + + case MOUNT_UNMOUNTING: + + if (f == MOUNT_SUCCESS && m->from_proc_self_mountinfo) { + + /* Still a mount point? If so, let's try again. Most likely there were multiple mount points + * stacked on top of each other. We might exceed the timeout specified by the user overall, + * but we will stop as soon as any one umount times out. */ + + if (m->n_retry_umount < RETRY_UMOUNT_MAX) { + log_unit_debug(u, "Mount still present, trying again."); + m->n_retry_umount++; + mount_enter_unmounting(m); + } else { + log_unit_warning(u, "Mount still present after %u attempts to unmount, giving up.", m->n_retry_umount); + mount_enter_mounted(m, f); + } + } else + mount_enter_dead_or_mounted(m, f); + + break; + + case MOUNT_UNMOUNTING_SIGKILL: + case MOUNT_UNMOUNTING_SIGTERM: + mount_enter_dead_or_mounted(m, f); + break; + + case MOUNT_CLEANING: + if (m->clean_result == MOUNT_SUCCESS) + m->clean_result = f; + + mount_enter_dead(m, MOUNT_SUCCESS); + break; + + default: + assert_not_reached("Uh, control process died at wrong time."); + } + + /* Notify clients about changed exit status */ + unit_add_to_dbus_queue(u); +} + +static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { + Mount *m = MOUNT(userdata); + + assert(m); + assert(m->timer_event_source == source); + + switch (m->state) { + + case MOUNT_MOUNTING: + case MOUNT_MOUNTING_DONE: + log_unit_warning(UNIT(m), "Mounting timed out. Terminating."); + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT); + break; + + case MOUNT_REMOUNTING: + log_unit_warning(UNIT(m), "Remounting timed out. Terminating remount process."); + mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT); + mount_enter_signal(m, MOUNT_REMOUNTING_SIGTERM, MOUNT_SUCCESS); + break; + + case MOUNT_REMOUNTING_SIGTERM: + mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT); + + if (m->kill_context.send_sigkill) { + log_unit_warning(UNIT(m), "Remounting timed out. Killing."); + mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS); + } else { + log_unit_warning(UNIT(m), "Remounting timed out. Skipping SIGKILL. Ignoring."); + mount_enter_dead_or_mounted(m, MOUNT_SUCCESS); + } + break; + + case MOUNT_REMOUNTING_SIGKILL: + mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT); + + log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring."); + mount_enter_dead_or_mounted(m, MOUNT_SUCCESS); + break; + + case MOUNT_UNMOUNTING: + log_unit_warning(UNIT(m), "Unmounting timed out. Terminating."); + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_FAILURE_TIMEOUT); + break; + + case MOUNT_UNMOUNTING_SIGTERM: + if (m->kill_context.send_sigkill) { + log_unit_warning(UNIT(m), "Mount process timed out. Killing."); + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT); + } else { + log_unit_warning(UNIT(m), "Mount process timed out. Skipping SIGKILL. Ignoring."); + mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT); + } + break; + + case MOUNT_UNMOUNTING_SIGKILL: + log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring."); + mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT); + break; + + case MOUNT_CLEANING: + log_unit_warning(UNIT(m), "Cleaning timed out. killing."); + + if (m->clean_result == MOUNT_SUCCESS) + m->clean_result = MOUNT_FAILURE_TIMEOUT; + + mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, 0); + break; + + default: + assert_not_reached("Timeout at wrong time."); + } + + return 0; +} + +static int mount_setup_new_unit( + Manager *m, + const char *name, + const char *what, + const char *where, + const char *options, + const char *fstype, + MountProcFlags *ret_flags, + Unit **ret) { + + _cleanup_(unit_freep) Unit *u = NULL; + int r; + + assert(m); + assert(name); + assert(ret_flags); + assert(ret); + + r = unit_new_for_name(m, sizeof(Mount), name, &u); + if (r < 0) + return r; + + r = free_and_strdup(&u->source_path, "/proc/self/mountinfo"); + if (r < 0) + return r; + + r = free_and_strdup(&MOUNT(u)->where, where); + if (r < 0) + return r; + + r = update_parameters_proc_self_mountinfo(MOUNT(u), what, options, fstype); + if (r < 0) + return r; + + /* This unit was generated because /proc/self/mountinfo reported it. Remember this, so that by the time we load + * the unit file for it (and thus add in extra deps right after) we know what source to attributes the deps + * to.*/ + MOUNT(u)->from_proc_self_mountinfo = true; + + /* We have only allocated the stub now, let's enqueue this unit for loading now, so that everything else is + * loaded in now. */ + unit_add_to_load_queue(u); + + *ret_flags = MOUNT_PROC_IS_MOUNTED | MOUNT_PROC_JUST_MOUNTED | MOUNT_PROC_JUST_CHANGED; + *ret = TAKE_PTR(u); + return 0; +} + +static int mount_setup_existing_unit( + Unit *u, + const char *what, + const char *where, + const char *options, + const char *fstype, + MountProcFlags *ret_flags) { + + MountProcFlags flags = MOUNT_PROC_IS_MOUNTED; + int r; + + assert(u); + assert(flags); + + if (!MOUNT(u)->where) { + MOUNT(u)->where = strdup(where); + if (!MOUNT(u)->where) + return -ENOMEM; + } + + r = update_parameters_proc_self_mountinfo(MOUNT(u), what, options, fstype); + if (r < 0) + return r; + if (r > 0) + flags |= MOUNT_PROC_JUST_CHANGED; + + if (!MOUNT(u)->from_proc_self_mountinfo || FLAGS_SET(MOUNT(u)->proc_flags, MOUNT_PROC_JUST_MOUNTED) || MOUNT(u)->state == MOUNT_MOUNTING) + flags |= MOUNT_PROC_JUST_MOUNTED; + + MOUNT(u)->from_proc_self_mountinfo = true; + + if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) { + /* The unit was previously not found or otherwise not loaded. Now that the unit shows up in + * /proc/self/mountinfo we should reconsider it this, hence set it to UNIT_LOADED. */ + u->load_state = UNIT_LOADED; + u->load_error = 0; + + flags |= MOUNT_PROC_JUST_CHANGED; + } + + if (FLAGS_SET(flags, MOUNT_PROC_JUST_CHANGED)) { + /* If things changed, then make sure that all deps are regenerated. Let's + * first remove all automatic deps, and then add in the new ones. */ + + unit_remove_dependencies(u, UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT); + + r = mount_add_non_exec_dependencies(MOUNT(u)); + if (r < 0) + return r; + } + + *ret_flags = flags; + return 0; +} + +static int mount_setup_unit( + Manager *m, + const char *what, + const char *where, + const char *options, + const char *fstype, + bool set_flags) { + + _cleanup_free_ char *e = NULL; + MountProcFlags flags; + Unit *u; + int r; + + assert(m); + assert(what); + assert(where); + assert(options); + assert(fstype); + + /* Ignore API mount points. They should never be referenced in + * dependencies ever. */ + if (mount_point_is_api(where) || mount_point_ignore(where)) + return 0; + + if (streq(fstype, "autofs")) + return 0; + + /* probably some kind of swap, ignore */ + if (!is_path(where)) + return 0; + + r = unit_name_from_path(where, ".mount", &e); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name from path '%s': %m", where); + + u = manager_get_unit(m, e); + if (u) + r = mount_setup_existing_unit(u, what, where, options, fstype, &flags); + else + /* First time we see this mount point meaning that it's not been initiated by a mount unit but rather + * by the sysadmin having called mount(8) directly. */ + r = mount_setup_new_unit(m, e, what, where, options, fstype, &flags, &u); + if (r < 0) + return log_warning_errno(r, "Failed to set up mount unit: %m"); + + /* If the mount changed properties or state, let's notify our clients */ + if (flags & (MOUNT_PROC_JUST_CHANGED|MOUNT_PROC_JUST_MOUNTED)) + unit_add_to_dbus_queue(u); + + if (set_flags) + MOUNT(u)->proc_flags = flags; + + return 0; +} + +static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; + int r; + + assert(m); + + r = libmount_parse(NULL, NULL, &table, &iter); + if (r < 0) + return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); + + for (;;) { + struct libmnt_fs *fs; + const char *device, *path, *options, *fstype; + + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) + break; + if (r < 0) + return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m"); + + device = mnt_fs_get_source(fs); + path = mnt_fs_get_target(fs); + options = mnt_fs_get_options(fs); + fstype = mnt_fs_get_fstype(fs); + + if (!device || !path) + continue; + + device_found_node(m, device, DEVICE_FOUND_MOUNT, DEVICE_FOUND_MOUNT); + + (void) mount_setup_unit(m, device, path, options, fstype, set_flags); + } + + return 0; +} + +static void mount_shutdown(Manager *m) { + assert(m); + + m->mount_event_source = sd_event_source_unref(m->mount_event_source); + + mnt_unref_monitor(m->mount_monitor); + m->mount_monitor = NULL; +} + +static int mount_get_timeout(Unit *u, usec_t *timeout) { + Mount *m = MOUNT(u); + usec_t t; + int r; + + if (!m->timer_event_source) + return 0; + + r = sd_event_source_get_time(m->timer_event_source, &t); + if (r < 0) + return r; + if (t == USEC_INFINITY) + return 0; + + *timeout = t; + return 1; +} + +static void mount_enumerate_perpetual(Manager *m) { + Unit *u; + int r; + + assert(m); + + /* Whatever happens, we know for sure that the root directory is around, and cannot go away. Let's + * unconditionally synthesize it here and mark it as perpetual. */ + + u = manager_get_unit(m, SPECIAL_ROOT_MOUNT); + if (!u) { + r = unit_new_for_name(m, sizeof(Mount), SPECIAL_ROOT_MOUNT, &u); + if (r < 0) { + log_error_errno(r, "Failed to allocate the special " SPECIAL_ROOT_MOUNT " unit: %m"); + return; + } + } + + u->perpetual = true; + MOUNT(u)->deserialized_state = MOUNT_MOUNTED; + + unit_add_to_load_queue(u); + unit_add_to_dbus_queue(u); +} + +static bool mount_is_mounted(Mount *m) { + assert(m); + + return UNIT(m)->perpetual || FLAGS_SET(m->proc_flags, MOUNT_PROC_IS_MOUNTED); +} + +static void mount_enumerate(Manager *m) { + int r; + + assert(m); + + mnt_init_debug(0); + + if (!m->mount_monitor) { + int fd; + + m->mount_monitor = mnt_new_monitor(); + if (!m->mount_monitor) { + log_oom(); + goto fail; + } + + r = mnt_monitor_enable_kernel(m->mount_monitor, 1); + if (r < 0) { + log_error_errno(r, "Failed to enable watching of kernel mount events: %m"); + goto fail; + } + + r = mnt_monitor_enable_userspace(m->mount_monitor, 1, NULL); + if (r < 0) { + log_error_errno(r, "Failed to enable watching of userspace mount events: %m"); + goto fail; + } + + /* mnt_unref_monitor() will close the fd */ + fd = r = mnt_monitor_get_fd(m->mount_monitor); + if (r < 0) { + log_error_errno(r, "Failed to acquire watch file descriptor: %m"); + goto fail; + } + + r = sd_event_add_io(m->event, &m->mount_event_source, fd, EPOLLIN, mount_dispatch_io, m); + if (r < 0) { + log_error_errno(r, "Failed to watch mount file descriptor: %m"); + goto fail; + } + + r = sd_event_source_set_priority(m->mount_event_source, SD_EVENT_PRIORITY_NORMAL-10); + if (r < 0) { + log_error_errno(r, "Failed to adjust mount watch priority: %m"); + goto fail; + } + + (void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch"); + } + + r = mount_load_proc_self_mountinfo(m, false); + if (r < 0) + goto fail; + + return; + +fail: + mount_shutdown(m); +} + +static int drain_libmount(Manager *m) { + bool rescan = false; + int r; + + assert(m); + + /* Drain all events and verify that the event is valid. + * + * Note that libmount also monitors /run/mount mkdir if the directory does not exist yet. The mkdir + * may generate event which is irrelevant for us. + * + * error: r < 0; valid: r == 0, false positive: r == 1 */ + do { + r = mnt_monitor_next_change(m->mount_monitor, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to drain libmount events: %m"); + if (r == 0) + rescan = true; + } while (r == 0); + + return rescan; +} + +static int mount_process_proc_self_mountinfo(Manager *m) { + _cleanup_set_free_free_ Set *around = NULL, *gone = NULL; + const char *what; + Iterator i; + Unit *u; + int r; + + assert(m); + + r = drain_libmount(m); + if (r <= 0) + return r; + + r = mount_load_proc_self_mountinfo(m, true); + if (r < 0) { + /* Reset flags, just in case, for later calls */ + LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) + MOUNT(u)->proc_flags = 0; + + return 0; + } + + manager_dispatch_load_queue(m); + + LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) { + Mount *mount = MOUNT(u); + + if (!mount_is_mounted(mount)) { + + /* A mount point is not around right now. It + * might be gone, or might never have + * existed. */ + + if (mount->from_proc_self_mountinfo && + mount->parameters_proc_self_mountinfo.what) { + + /* Remember that this device might just have disappeared */ + if (set_ensure_allocated(&gone, &path_hash_ops) < 0 || + set_put_strdup(gone, mount->parameters_proc_self_mountinfo.what) < 0) + log_oom(); /* we don't care too much about OOM here... */ + } + + mount->from_proc_self_mountinfo = false; + assert_se(update_parameters_proc_self_mountinfo(mount, NULL, NULL, NULL) >= 0); + + switch (mount->state) { + + case MOUNT_MOUNTED: + /* This has just been unmounted by somebody else, follow the state change. */ + mount_enter_dead(mount, MOUNT_SUCCESS); + break; + + default: + break; + } + + } else if (mount->proc_flags & (MOUNT_PROC_JUST_MOUNTED|MOUNT_PROC_JUST_CHANGED)) { + + /* A mount point was added or changed */ + + switch (mount->state) { + + case MOUNT_DEAD: + case MOUNT_FAILED: + + /* This has just been mounted by somebody else, follow the state change, but let's + * generate a new invocation ID for this implicitly and automatically. */ + (void) unit_acquire_invocation_id(u); + mount_cycle_clear(mount); + mount_enter_mounted(mount, MOUNT_SUCCESS); + break; + + case MOUNT_MOUNTING: + mount_set_state(mount, MOUNT_MOUNTING_DONE); + break; + + default: + /* Nothing really changed, but let's + * issue an notification call + * nonetheless, in case somebody is + * waiting for this. (e.g. file system + * ro/rw remounts.) */ + mount_set_state(mount, mount->state); + break; + } + } + + if (mount_is_mounted(mount) && + mount->from_proc_self_mountinfo && + mount->parameters_proc_self_mountinfo.what) { + /* Track devices currently used */ + + if (set_ensure_allocated(&around, &path_hash_ops) < 0 || + set_put_strdup(around, mount->parameters_proc_self_mountinfo.what) < 0) + log_oom(); + } + + /* Reset the flags for later calls */ + mount->proc_flags = 0; + } + + SET_FOREACH(what, gone, i) { + if (set_contains(around, what)) + continue; + + /* Let the device units know that the device is no longer mounted */ + device_found_node(m, what, 0, DEVICE_FOUND_MOUNT); + } + + return 0; +} + +static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + + assert(m); + assert(revents & EPOLLIN); + + return mount_process_proc_self_mountinfo(m); +} + +static void mount_reset_failed(Unit *u) { + Mount *m = MOUNT(u); + + assert(m); + + if (m->state == MOUNT_FAILED) + mount_set_state(m, MOUNT_DEAD); + + m->result = MOUNT_SUCCESS; + m->reload_result = MOUNT_SUCCESS; + m->clean_result = MOUNT_SUCCESS; +} + +static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { + Mount *m = MOUNT(u); + + assert(m); + + return unit_kill_common(u, who, signo, -1, m->control_pid, error); +} + +static int mount_control_pid(Unit *u) { + Mount *m = MOUNT(u); + + assert(m); + + return m->control_pid; +} + +static int mount_clean(Unit *u, ExecCleanMask mask) { + _cleanup_strv_free_ char **l = NULL; + Mount *m = MOUNT(u); + int r; + + assert(m); + assert(mask != 0); + + if (m->state != MOUNT_DEAD) + return -EBUSY; + + r = exec_context_get_clean_directories(&m->exec_context, u->manager->prefix, mask, &l); + if (r < 0) + return r; + + if (strv_isempty(l)) + return -EUNATCH; + + mount_unwatch_control_pid(m); + m->clean_result = MOUNT_SUCCESS; + m->control_command = NULL; + m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID; + + r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->exec_context.timeout_clean_usec)); + if (r < 0) + goto fail; + + r = unit_fork_and_watch_rm_rf(u, l, &m->control_pid); + if (r < 0) + goto fail; + + mount_set_state(m, MOUNT_CLEANING); + + return 0; + +fail: + log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m"); + m->clean_result = MOUNT_FAILURE_RESOURCES; + m->timer_event_source = sd_event_source_unref(m->timer_event_source); + return r; +} + +static int mount_can_clean(Unit *u, ExecCleanMask *ret) { + Mount *m = MOUNT(u); + + assert(m); + + return exec_context_get_clean_mask(&m->exec_context, ret); +} + +static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = { + [MOUNT_EXEC_MOUNT] = "ExecMount", + [MOUNT_EXEC_UNMOUNT] = "ExecUnmount", + [MOUNT_EXEC_REMOUNT] = "ExecRemount", +}; + +DEFINE_STRING_TABLE_LOOKUP(mount_exec_command, MountExecCommand); + +static const char* const mount_result_table[_MOUNT_RESULT_MAX] = { + [MOUNT_SUCCESS] = "success", + [MOUNT_FAILURE_RESOURCES] = "resources", + [MOUNT_FAILURE_TIMEOUT] = "timeout", + [MOUNT_FAILURE_EXIT_CODE] = "exit-code", + [MOUNT_FAILURE_SIGNAL] = "signal", + [MOUNT_FAILURE_CORE_DUMP] = "core-dump", + [MOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit", + [MOUNT_FAILURE_PROTOCOL] = "protocol", +}; + +DEFINE_STRING_TABLE_LOOKUP(mount_result, MountResult); + +const UnitVTable mount_vtable = { + .object_size = sizeof(Mount), + .exec_context_offset = offsetof(Mount, exec_context), + .cgroup_context_offset = offsetof(Mount, cgroup_context), + .kill_context_offset = offsetof(Mount, kill_context), + .exec_runtime_offset = offsetof(Mount, exec_runtime), + .dynamic_creds_offset = offsetof(Mount, dynamic_creds), + + .sections = + "Unit\0" + "Mount\0" + "Install\0", + .private_section = "Mount", + + .init = mount_init, + .load = mount_load, + .done = mount_done, + + .coldplug = mount_coldplug, + + .dump = mount_dump, + + .start = mount_start, + .stop = mount_stop, + .reload = mount_reload, + + .kill = mount_kill, + .clean = mount_clean, + .can_clean = mount_can_clean, + + .serialize = mount_serialize, + .deserialize_item = mount_deserialize_item, + + .active_state = mount_active_state, + .sub_state_to_string = mount_sub_state_to_string, + + .will_restart = unit_will_restart_default, + + .may_gc = mount_may_gc, + + .sigchld_event = mount_sigchld_event, + + .reset_failed = mount_reset_failed, + + .control_pid = mount_control_pid, + + .bus_vtable = bus_mount_vtable, + .bus_set_property = bus_mount_set_property, + .bus_commit_properties = bus_mount_commit_properties, + + .get_timeout = mount_get_timeout, + + .can_transient = true, + + .enumerate_perpetual = mount_enumerate_perpetual, + .enumerate = mount_enumerate, + .shutdown = mount_shutdown, + + .status_message_formats = { + .starting_stopping = { + [0] = "Mounting %s...", + [1] = "Unmounting %s...", + }, + .finished_start_job = { + [JOB_DONE] = "Mounted %s.", + [JOB_FAILED] = "Failed to mount %s.", + [JOB_TIMEOUT] = "Timed out mounting %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Unmounted %s.", + [JOB_FAILED] = "Failed unmounting %s.", + [JOB_TIMEOUT] = "Timed out unmounting %s.", + }, + }, +}; diff --git a/src/core/mount.h b/src/core/mount.h new file mode 100644 index 00000000..07fa05f3 --- /dev/null +++ b/src/core/mount.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Mount Mount; + +#include "kill.h" +#include "dynamic-user.h" +#include "unit.h" + +typedef enum MountExecCommand { + MOUNT_EXEC_MOUNT, + MOUNT_EXEC_UNMOUNT, + MOUNT_EXEC_REMOUNT, + _MOUNT_EXEC_COMMAND_MAX, + _MOUNT_EXEC_COMMAND_INVALID = -1 +} MountExecCommand; + +typedef enum MountResult { + MOUNT_SUCCESS, + MOUNT_FAILURE_RESOURCES, /* a bit of a misnomer, just our catch-all error for errnos we didn't expect */ + MOUNT_FAILURE_TIMEOUT, + MOUNT_FAILURE_EXIT_CODE, + MOUNT_FAILURE_SIGNAL, + MOUNT_FAILURE_CORE_DUMP, + MOUNT_FAILURE_START_LIMIT_HIT, + MOUNT_FAILURE_PROTOCOL, + _MOUNT_RESULT_MAX, + _MOUNT_RESULT_INVALID = -1 +} MountResult; + +typedef struct MountParameters { + char *what; + char *options; + char *fstype; +} MountParameters; + +/* Used while looking for mount points that vanished or got added from/to /proc/self/mountinfo */ +typedef enum MountProcFlags { + MOUNT_PROC_IS_MOUNTED = 1 << 0, + MOUNT_PROC_JUST_MOUNTED = 1 << 1, + MOUNT_PROC_JUST_CHANGED = 1 << 2, +} MountProcFlags; + +struct Mount { + Unit meta; + + char *where; + + MountParameters parameters_proc_self_mountinfo; + MountParameters parameters_fragment; + + bool from_proc_self_mountinfo:1; + bool from_fragment:1; + + MountProcFlags proc_flags; + + bool sloppy_options; + + bool lazy_unmount; + bool force_unmount; + + MountResult result; + MountResult reload_result; + MountResult clean_result; + + mode_t directory_mode; + + usec_t timeout_usec; + + ExecCommand exec_command[_MOUNT_EXEC_COMMAND_MAX]; + + ExecContext exec_context; + KillContext kill_context; + CGroupContext cgroup_context; + + ExecRuntime *exec_runtime; + DynamicCreds dynamic_creds; + + MountState state, deserialized_state; + + ExecCommand* control_command; + MountExecCommand control_command_id; + pid_t control_pid; + + sd_event_source *timer_event_source; + + unsigned n_retry_umount; +}; + +extern const UnitVTable mount_vtable; + +void mount_fd_event(Manager *m, int events); + +const char* mount_exec_command_to_string(MountExecCommand i) _const_; +MountExecCommand mount_exec_command_from_string(const char *s) _pure_; + +const char* mount_result_to_string(MountResult i) _const_; +MountResult mount_result_from_string(const char *s) _pure_; + +DEFINE_CAST(MOUNT, Mount); diff --git a/src/core/namespace.c b/src/core/namespace.c new file mode 100644 index 00000000..c0ff44c5 --- /dev/null +++ b/src/core/namespace.c @@ -0,0 +1,1910 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "base-filesystem.h" +#include "dev-setup.h" +#include "fd-util.h" +#include "fs-util.h" +#include "label.h" +#include "loop-util.h" +#include "loopback-setup.h" +#include "mkdir.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "namespace-util.h" +#include "namespace.h" +#include "nulstr-util.h" +#include "path-util.h" +#include "selinux-util.h" +#include "socket-util.h" +#include "sort-util.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "umask-util.h" +#include "user-util.h" + +#define DEV_MOUNT_OPTIONS (MS_NOSUID|MS_STRICTATIME|MS_NOEXEC) + +typedef enum MountMode { + /* This is ordered by priority! */ + INACCESSIBLE, + BIND_MOUNT, + BIND_MOUNT_RECURSIVE, + PRIVATE_TMP, + PRIVATE_DEV, + BIND_DEV, + EMPTY_DIR, + SYSFS, + PROCFS, + READONLY, + READWRITE, + TMPFS, + READWRITE_IMPLICIT, /* Should have the lowest priority. */ + _MOUNT_MODE_MAX, +} MountMode; + +typedef struct MountEntry { + const char *path_const; /* Memory allocated on stack or static */ + MountMode mode:5; + bool ignore:1; /* Ignore if path does not exist? */ + bool has_prefix:1; /* Already is prefixed by the root dir? */ + bool read_only:1; /* Shall this mount point be read-only? */ + bool nosuid:1; /* Shall set MS_NOSUID on the mount itself */ + bool applied:1; /* Already applied */ + char *path_malloc; /* Use this instead of 'path_const' if we had to allocate memory */ + const char *source_const; /* The source path, for bind mounts */ + char *source_malloc; + const char *options_const;/* Mount options for tmpfs */ + char *options_malloc; + unsigned long flags; /* Mount flags used by EMPTY_DIR and TMPFS. Do not include MS_RDONLY here, but please use read_only. */ + unsigned n_followed; +} MountEntry; + +/* If MountAPIVFS= is used, let's mount /sys and /proc into the it, but only as a fallback if the user hasn't mounted + * something there already. These mounts are hence overridden by any other explicitly configured mounts. */ +static const MountEntry apivfs_table[] = { + { "/proc", PROCFS, false }, + { "/dev", BIND_DEV, false }, + { "/sys", SYSFS, false }, +}; + +/* ProtectKernelTunables= option and the related filesystem APIs */ +static const MountEntry protect_kernel_tunables_table[] = { + { "/proc/acpi", READONLY, true }, + { "/proc/apm", READONLY, true }, /* Obsolete API, there's no point in permitting access to this, ever */ + { "/proc/asound", READONLY, true }, + { "/proc/bus", READONLY, true }, + { "/proc/fs", READONLY, true }, + { "/proc/irq", READONLY, true }, + { "/proc/kallsyms", INACCESSIBLE, true }, + { "/proc/kcore", INACCESSIBLE, true }, + { "/proc/latency_stats", READONLY, true }, + { "/proc/mtrr", READONLY, true }, + { "/proc/scsi", READONLY, true }, + { "/proc/sys", READONLY, false }, + { "/proc/sysrq-trigger", READONLY, true }, + { "/proc/timer_stats", READONLY, true }, + { "/sys", READONLY, false }, + { "/sys/fs/bpf", READONLY, true }, + { "/sys/fs/cgroup", READWRITE_IMPLICIT, false }, /* READONLY is set by ProtectControlGroups= option */ + { "/sys/fs/selinux", READWRITE_IMPLICIT, true }, + { "/sys/kernel/debug", READONLY, true }, + { "/sys/kernel/tracing", READONLY, true }, +}; + +/* ProtectKernelModules= option */ +static const MountEntry protect_kernel_modules_table[] = { +#if HAVE_SPLIT_USR + { "/lib/modules", INACCESSIBLE, true }, +#endif + { "/usr/lib/modules", INACCESSIBLE, true }, +}; + +/* ProtectKernelLogs= option */ +static const MountEntry protect_kernel_logs_table[] = { + { "/proc/kmsg", INACCESSIBLE, true }, + { "/dev/kmsg", INACCESSIBLE, true }, +}; + +/* + * ProtectHome=read-only table, protect $HOME and $XDG_RUNTIME_DIR and rest of + * system should be protected by ProtectSystem= + */ +static const MountEntry protect_home_read_only_table[] = { + { "/home", READONLY, true }, + { "/run/user", READONLY, true }, + { "/root", READONLY, true }, +}; + +/* ProtectHome=tmpfs table */ +static const MountEntry protect_home_tmpfs_table[] = { + { "/home", TMPFS, true, .read_only = true, .options_const = "mode=0755", .flags = MS_NODEV|MS_STRICTATIME }, + { "/run/user", TMPFS, true, .read_only = true, .options_const = "mode=0755", .flags = MS_NODEV|MS_STRICTATIME }, + { "/root", TMPFS, true, .read_only = true, .options_const = "mode=0700", .flags = MS_NODEV|MS_STRICTATIME }, +}; + +/* ProtectHome=yes table */ +static const MountEntry protect_home_yes_table[] = { + { "/home", INACCESSIBLE, true }, + { "/run/user", INACCESSIBLE, true }, + { "/root", INACCESSIBLE, true }, +}; + +/* ProtectSystem=yes table */ +static const MountEntry protect_system_yes_table[] = { + { "/usr", READONLY, false }, + { "/boot", READONLY, true }, + { "/efi", READONLY, true }, +#if HAVE_SPLIT_USR + { "/lib", READONLY, true }, + { "/lib64", READONLY, true }, + { "/bin", READONLY, true }, +# if HAVE_SPLIT_BIN + { "/sbin", READONLY, true }, +# endif +#endif +}; + +/* ProtectSystem=full includes ProtectSystem=yes */ +static const MountEntry protect_system_full_table[] = { + { "/usr", READONLY, false }, + { "/boot", READONLY, true }, + { "/efi", READONLY, true }, + { "/etc", READONLY, false }, +#if HAVE_SPLIT_USR + { "/lib", READONLY, true }, + { "/lib64", READONLY, true }, + { "/bin", READONLY, true }, +# if HAVE_SPLIT_BIN + { "/sbin", READONLY, true }, +# endif +#endif +}; + +/* + * ProtectSystem=strict table. In this strict mode, we mount everything + * read-only, except for /proc, /dev, /sys which are the kernel API VFS, + * which are left writable, but PrivateDevices= + ProtectKernelTunables= + * protect those, and these options should be fully orthogonal. + * (And of course /home and friends are also left writable, as ProtectHome= + * shall manage those, orthogonally). + */ +static const MountEntry protect_system_strict_table[] = { + { "/", READONLY, false }, + { "/proc", READWRITE_IMPLICIT, false }, /* ProtectKernelTunables= */ + { "/sys", READWRITE_IMPLICIT, false }, /* ProtectKernelTunables= */ + { "/dev", READWRITE_IMPLICIT, false }, /* PrivateDevices= */ + { "/home", READWRITE_IMPLICIT, true }, /* ProtectHome= */ + { "/run/user", READWRITE_IMPLICIT, true }, /* ProtectHome= */ + { "/root", READWRITE_IMPLICIT, true }, /* ProtectHome= */ +}; + +static const char * const mount_mode_table[_MOUNT_MODE_MAX] = { + [INACCESSIBLE] = "inaccessible", + [BIND_MOUNT] = "bind", + [BIND_MOUNT_RECURSIVE] = "rbind", + [PRIVATE_TMP] = "private-tmp", + [PRIVATE_DEV] = "private-dev", + [BIND_DEV] = "bind-dev", + [EMPTY_DIR] = "empty", + [SYSFS] = "sysfs", + [PROCFS] = "procfs", + [READONLY] = "read-only", + [READWRITE] = "read-write", + [TMPFS] = "tmpfs", + [READWRITE_IMPLICIT] = "rw-implicit", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(mount_mode, MountMode); + +static const char *mount_entry_path(const MountEntry *p) { + assert(p); + + /* Returns the path of this bind mount. If the malloc()-allocated ->path_buffer field is set we return that, + * otherwise the stack/static ->path field is returned. */ + + return p->path_malloc ?: p->path_const; +} + +static bool mount_entry_read_only(const MountEntry *p) { + assert(p); + + return p->read_only || IN_SET(p->mode, READONLY, INACCESSIBLE); +} + +static const char *mount_entry_source(const MountEntry *p) { + assert(p); + + return p->source_malloc ?: p->source_const; +} + +static const char *mount_entry_options(const MountEntry *p) { + assert(p); + + return p->options_malloc ?: p->options_const; +} + +static void mount_entry_done(MountEntry *p) { + assert(p); + + p->path_malloc = mfree(p->path_malloc); + p->source_malloc = mfree(p->source_malloc); + p->options_malloc = mfree(p->options_malloc); +} + +static int append_access_mounts(MountEntry **p, char **strv, MountMode mode, bool forcibly_require_prefix) { + char **i; + + assert(p); + + /* Adds a list of user-supplied READWRITE/READWRITE_IMPLICIT/READONLY/INACCESSIBLE entries */ + + STRV_FOREACH(i, strv) { + bool ignore = false, needs_prefix = false; + const char *e = *i; + + /* Look for any prefixes */ + if (startswith(e, "-")) { + e++; + ignore = true; + } + if (startswith(e, "+")) { + e++; + needs_prefix = true; + } + + if (!path_is_absolute(e)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Path is not absolute: %s", e); + + *((*p)++) = (MountEntry) { + .path_const = e, + .mode = mode, + .ignore = ignore, + .has_prefix = !needs_prefix && !forcibly_require_prefix, + }; + } + + return 0; +} + +static int append_empty_dir_mounts(MountEntry **p, char **strv) { + char **i; + + assert(p); + + /* Adds tmpfs mounts to provide readable but empty directories. This is primarily used to implement the + * "/private/" boundary directories for DynamicUser=1. */ + + STRV_FOREACH(i, strv) { + + *((*p)++) = (MountEntry) { + .path_const = *i, + .mode = EMPTY_DIR, + .ignore = false, + .read_only = true, + .options_const = "mode=755", + .flags = MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, + }; + } + + return 0; +} + +static int append_bind_mounts(MountEntry **p, const BindMount *binds, size_t n) { + size_t i; + + assert(p); + + for (i = 0; i < n; i++) { + const BindMount *b = binds + i; + + *((*p)++) = (MountEntry) { + .path_const = b->destination, + .mode = b->recursive ? BIND_MOUNT_RECURSIVE : BIND_MOUNT, + .read_only = b->read_only, + .nosuid = b->nosuid, + .source_const = b->source, + .ignore = b->ignore_enoent, + }; + } + + return 0; +} + +static int append_tmpfs_mounts(MountEntry **p, const TemporaryFileSystem *tmpfs, size_t n) { + size_t i; + int r; + + assert(p); + + for (i = 0; i < n; i++) { + const TemporaryFileSystem *t = tmpfs + i; + _cleanup_free_ char *o = NULL, *str = NULL; + unsigned long flags; + bool ro = false; + + if (!path_is_absolute(t->path)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Path is not absolute: %s", + t->path); + + str = strjoin("mode=0755,", t->options); + if (!str) + return -ENOMEM; + + r = mount_option_mangle(str, MS_NODEV|MS_STRICTATIME, &flags, &o); + if (r < 0) + return log_debug_errno(r, "Failed to parse mount option '%s': %m", str); + + ro = flags & MS_RDONLY; + if (ro) + flags ^= MS_RDONLY; + + *((*p)++) = (MountEntry) { + .path_const = t->path, + .mode = TMPFS, + .read_only = ro, + .options_malloc = TAKE_PTR(o), + .flags = flags, + }; + } + + return 0; +} + +static int append_static_mounts(MountEntry **p, const MountEntry *mounts, size_t n, bool ignore_protect) { + size_t i; + + assert(p); + assert(mounts); + + /* Adds a list of static pre-defined entries */ + + for (i = 0; i < n; i++) + *((*p)++) = (MountEntry) { + .path_const = mount_entry_path(mounts+i), + .mode = mounts[i].mode, + .ignore = mounts[i].ignore || ignore_protect, + }; + + return 0; +} + +static int append_protect_home(MountEntry **p, ProtectHome protect_home, bool ignore_protect) { + assert(p); + + switch (protect_home) { + + case PROTECT_HOME_NO: + return 0; + + case PROTECT_HOME_READ_ONLY: + return append_static_mounts(p, protect_home_read_only_table, ELEMENTSOF(protect_home_read_only_table), ignore_protect); + + case PROTECT_HOME_TMPFS: + return append_static_mounts(p, protect_home_tmpfs_table, ELEMENTSOF(protect_home_tmpfs_table), ignore_protect); + + case PROTECT_HOME_YES: + return append_static_mounts(p, protect_home_yes_table, ELEMENTSOF(protect_home_yes_table), ignore_protect); + + default: + assert_not_reached("Unexpected ProtectHome= value"); + } +} + +static int append_protect_system(MountEntry **p, ProtectSystem protect_system, bool ignore_protect) { + assert(p); + + switch (protect_system) { + + case PROTECT_SYSTEM_NO: + return 0; + + case PROTECT_SYSTEM_STRICT: + return append_static_mounts(p, protect_system_strict_table, ELEMENTSOF(protect_system_strict_table), ignore_protect); + + case PROTECT_SYSTEM_YES: + return append_static_mounts(p, protect_system_yes_table, ELEMENTSOF(protect_system_yes_table), ignore_protect); + + case PROTECT_SYSTEM_FULL: + return append_static_mounts(p, protect_system_full_table, ELEMENTSOF(protect_system_full_table), ignore_protect); + + default: + assert_not_reached("Unexpected ProtectSystem= value"); + } +} + +static int mount_path_compare(const MountEntry *a, const MountEntry *b) { + int d; + + /* If the paths are not equal, then order prefixes first */ + d = path_compare(mount_entry_path(a), mount_entry_path(b)); + if (d != 0) + return d; + + /* If the paths are equal, check the mode */ + return CMP((int) a->mode, (int) b->mode); +} + +static int prefix_where_needed(MountEntry *m, size_t n, const char *root_directory) { + size_t i; + + /* Prefixes all paths in the bind mount table with the root directory if the entry needs that. */ + + for (i = 0; i < n; i++) { + char *s; + + if (m[i].has_prefix) + continue; + + s = path_join(root_directory, mount_entry_path(m+i)); + if (!s) + return -ENOMEM; + + free_and_replace(m[i].path_malloc, s); + m[i].has_prefix = true; + } + + return 0; +} + +static void drop_duplicates(MountEntry *m, size_t *n) { + MountEntry *f, *t, *previous; + + assert(m); + assert(n); + + /* Drops duplicate entries. Expects that the array is properly ordered already. */ + + for (f = m, t = m, previous = NULL; f < m + *n; f++) { + + /* The first one wins (which is the one with the more restrictive mode), see mount_path_compare() + * above. Note that we only drop duplicates that haven't been mounted yet. */ + if (previous && + path_equal(mount_entry_path(f), mount_entry_path(previous)) && + !f->applied && !previous->applied) { + log_debug("%s (%s) is duplicate.", mount_entry_path(f), mount_mode_to_string(f->mode)); + previous->read_only = previous->read_only || mount_entry_read_only(f); /* Propagate the read-only flag to the remaining entry */ + mount_entry_done(f); + continue; + } + + *t = *f; + previous = t; + t++; + } + + *n = t - m; +} + +static void drop_inaccessible(MountEntry *m, size_t *n) { + MountEntry *f, *t; + const char *clear = NULL; + + assert(m); + assert(n); + + /* Drops all entries obstructed by another entry further up the tree. Expects that the array is properly + * ordered already. */ + + for (f = m, t = m; f < m + *n; f++) { + + /* If we found a path set for INACCESSIBLE earlier, and this entry has it as prefix we should drop + * it, as inaccessible paths really should drop the entire subtree. */ + if (clear && path_startswith(mount_entry_path(f), clear)) { + log_debug("%s is masked by %s.", mount_entry_path(f), clear); + mount_entry_done(f); + continue; + } + + clear = f->mode == INACCESSIBLE ? mount_entry_path(f) : NULL; + + *t = *f; + t++; + } + + *n = t - m; +} + +static void drop_nop(MountEntry *m, size_t *n) { + MountEntry *f, *t; + + assert(m); + assert(n); + + /* Drops all entries which have an immediate parent that has the same type, as they are redundant. Assumes the + * list is ordered by prefixes. */ + + for (f = m, t = m; f < m + *n; f++) { + + /* Only suppress such subtrees for READONLY, READWRITE and READWRITE_IMPLICIT entries */ + if (IN_SET(f->mode, READONLY, READWRITE, READWRITE_IMPLICIT)) { + MountEntry *p; + bool found = false; + + /* Now let's find the first parent of the entry we are looking at. */ + for (p = t-1; p >= m; p--) { + if (path_startswith(mount_entry_path(f), mount_entry_path(p))) { + found = true; + break; + } + } + + /* We found it, let's see if it's the same mode, if so, we can drop this entry */ + if (found && p->mode == f->mode) { + log_debug("%s (%s) is made redundant by %s (%s)", + mount_entry_path(f), mount_mode_to_string(f->mode), + mount_entry_path(p), mount_mode_to_string(p->mode)); + mount_entry_done(f); + continue; + } + } + + *t = *f; + t++; + } + + *n = t - m; +} + +static void drop_outside_root(const char *root_directory, MountEntry *m, size_t *n) { + MountEntry *f, *t; + + assert(m); + assert(n); + + /* Nothing to do */ + if (!root_directory) + return; + + /* Drops all mounts that are outside of the root directory. */ + + for (f = m, t = m; f < m + *n; f++) { + + if (!path_startswith(mount_entry_path(f), root_directory)) { + log_debug("%s is outside of root directory.", mount_entry_path(f)); + mount_entry_done(f); + continue; + } + + *t = *f; + t++; + } + + *n = t - m; +} + +static int clone_device_node( + const char *d, + const char *temporary_mount, + bool *make_devnode) { + + _cleanup_free_ char *sl = NULL; + const char *dn, *bn, *t; + struct stat st; + int r; + + if (stat(d, &st) < 0) { + if (errno == ENOENT) { + log_debug_errno(errno, "Device node '%s' to clone does not exist, ignoring.", d); + return -ENXIO; + } + + return log_debug_errno(errno, "Failed to stat() device node '%s' to clone, ignoring: %m", d); + } + + if (!S_ISBLK(st.st_mode) && + !S_ISCHR(st.st_mode)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Device node '%s' to clone is not a device node, ignoring.", + d); + + dn = strjoina(temporary_mount, d); + + /* First, try to create device node properly */ + if (*make_devnode) { + mac_selinux_create_file_prepare(d, st.st_mode); + r = mknod(dn, st.st_mode, st.st_rdev); + mac_selinux_create_file_clear(); + if (r >= 0) + goto add_symlink; + if (errno != EPERM) + return log_debug_errno(errno, "mknod failed for %s: %m", d); + + /* This didn't work, let's not try this again for the next iterations. */ + *make_devnode = false; + } + + /* We're about to fallback to bind-mounting the device + * node. So create a dummy bind-mount target. */ + mac_selinux_create_file_prepare(d, 0); + r = mknod(dn, S_IFREG, 0); + mac_selinux_create_file_clear(); + if (r < 0 && errno != EEXIST) + return log_debug_errno(errno, "mknod() fallback failed for '%s': %m", d); + + /* Fallback to bind-mounting: + * The assumption here is that all used device nodes carry standard + * properties. Specifically, the devices nodes we bind-mount should + * either be owned by root:root or root:tty (e.g. /dev/tty, /dev/ptmx) + * and should not carry ACLs. */ + if (mount(d, dn, NULL, MS_BIND, NULL) < 0) + return log_debug_errno(errno, "Bind mounting failed for '%s': %m", d); + +add_symlink: + bn = path_startswith(d, "/dev/"); + if (!bn) + return 0; + + /* Create symlinks like /dev/char/1:9 → ../urandom */ + if (asprintf(&sl, "%s/dev/%s/%u:%u", temporary_mount, S_ISCHR(st.st_mode) ? "char" : "block", major(st.st_rdev), minor(st.st_rdev)) < 0) + return log_oom(); + + (void) mkdir_parents(sl, 0755); + + t = strjoina("../", bn); + + if (symlink(t, sl) < 0) + log_debug_errno(errno, "Failed to symlink '%s' to '%s', ignoring: %m", t, sl); + + return 0; +} + +static int mount_private_dev(MountEntry *m) { + static const char devnodes[] = + "/dev/null\0" + "/dev/zero\0" + "/dev/full\0" + "/dev/random\0" + "/dev/urandom\0" + "/dev/tty\0"; + + char temporary_mount[] = "/tmp/namespace-dev-XXXXXX"; + const char *d, *dev = NULL, *devpts = NULL, *devshm = NULL, *devhugepages = NULL, *devmqueue = NULL, *devlog = NULL, *devptmx = NULL; + bool can_mknod = true; + _cleanup_umask_ mode_t u; + int r; + + assert(m); + + u = umask(0000); + + if (!mkdtemp(temporary_mount)) + return log_debug_errno(errno, "Failed to create temporary directory '%s': %m", temporary_mount); + + dev = strjoina(temporary_mount, "/dev"); + (void) mkdir(dev, 0755); + if (mount("tmpfs", dev, "tmpfs", DEV_MOUNT_OPTIONS, "mode=755") < 0) { + r = log_debug_errno(errno, "Failed to mount tmpfs on '%s': %m", dev); + goto fail; + } + + devpts = strjoina(temporary_mount, "/dev/pts"); + (void) mkdir(devpts, 0755); + if (mount("/dev/pts", devpts, NULL, MS_BIND, NULL) < 0) { + r = log_debug_errno(errno, "Failed to bind mount /dev/pts on '%s': %m", devpts); + goto fail; + } + + /* /dev/ptmx can either be a device node or a symlink to /dev/pts/ptmx. + * When /dev/ptmx a device node, /dev/pts/ptmx has 000 permissions making it inaccessible. + * Thus, in that case make a clone. + * In nspawn and other containers it will be a symlink, in that case make it a symlink. */ + r = is_symlink("/dev/ptmx"); + if (r < 0) { + log_debug_errno(r, "Failed to detect whether /dev/ptmx is a symlink or not: %m"); + goto fail; + } else if (r > 0) { + devptmx = strjoina(temporary_mount, "/dev/ptmx"); + if (symlink("pts/ptmx", devptmx) < 0) { + r = log_debug_errno(errno, "Failed to create a symlink '%s' to pts/ptmx: %m", devptmx); + goto fail; + } + } else { + r = clone_device_node("/dev/ptmx", temporary_mount, &can_mknod); + if (r < 0) + goto fail; + } + + devshm = strjoina(temporary_mount, "/dev/shm"); + (void) mkdir(devshm, 0755); + r = mount("/dev/shm", devshm, NULL, MS_BIND, NULL); + if (r < 0) { + r = log_debug_errno(errno, "Failed to bind mount /dev/shm on '%s': %m", devshm); + goto fail; + } + + devmqueue = strjoina(temporary_mount, "/dev/mqueue"); + (void) mkdir(devmqueue, 0755); + if (mount("/dev/mqueue", devmqueue, NULL, MS_BIND, NULL) < 0) + log_debug_errno(errno, "Failed to bind mount /dev/mqueue on '%s', ignoring: %m", devmqueue); + + devhugepages = strjoina(temporary_mount, "/dev/hugepages"); + (void) mkdir(devhugepages, 0755); + if (mount("/dev/hugepages", devhugepages, NULL, MS_BIND, NULL) < 0) + log_debug_errno(errno, "Failed to bind mount /dev/hugepages on '%s', ignoring: %m", devhugepages); + + devlog = strjoina(temporary_mount, "/dev/log"); + if (symlink("/run/systemd/journal/dev-log", devlog) < 0) + log_debug_errno(errno, "Failed to create a symlink '%s' to /run/systemd/journal/dev-log, ignoring: %m", devlog); + + NULSTR_FOREACH(d, devnodes) { + r = clone_device_node(d, temporary_mount, &can_mknod); + /* ENXIO means the the *source* is not a device file, skip creation in that case */ + if (r < 0 && r != -ENXIO) + goto fail; + } + + r = dev_setup(temporary_mount, UID_INVALID, GID_INVALID); + if (r < 0) + log_debug_errno(r, "Failed to setup basic device tree at '%s', ignoring: %m", temporary_mount); + + /* Create the /dev directory if missing. It is more likely to be + * missing when the service is started with RootDirectory. This is + * consistent with mount units creating the mount points when missing. + */ + (void) mkdir_p_label(mount_entry_path(m), 0755); + + /* Unmount everything in old /dev */ + r = umount_recursive(mount_entry_path(m), 0); + if (r < 0) + log_debug_errno(r, "Failed to unmount directories below '%s', ignoring: %m", mount_entry_path(m)); + + if (mount(dev, mount_entry_path(m), NULL, MS_MOVE, NULL) < 0) { + r = log_debug_errno(errno, "Failed to move mount point '%s' to '%s': %m", dev, mount_entry_path(m)); + goto fail; + } + + (void) rmdir(dev); + (void) rmdir(temporary_mount); + + return 0; + +fail: + if (devpts) + (void) umount(devpts); + + if (devshm) + (void) umount(devshm); + + if (devhugepages) + (void) umount(devhugepages); + + if (devmqueue) + (void) umount(devmqueue); + + (void) umount(dev); + (void) rmdir(dev); + (void) rmdir(temporary_mount); + + return r; +} + +static int mount_bind_dev(const MountEntry *m) { + int r; + + assert(m); + + /* Implements the little brother of mount_private_dev(): simply bind mounts the host's /dev into the service's + * /dev. This is only used when RootDirectory= is set. */ + + (void) mkdir_p_label(mount_entry_path(m), 0755); + + r = path_is_mount_point(mount_entry_path(m), NULL, 0); + if (r < 0) + return log_debug_errno(r, "Unable to determine whether /dev is already mounted: %m"); + if (r > 0) /* make this a NOP if /dev is already a mount point */ + return 0; + + if (mount("/dev", mount_entry_path(m), NULL, MS_BIND|MS_REC, NULL) < 0) + return log_debug_errno(errno, "Failed to bind mount %s: %m", mount_entry_path(m)); + + return 1; +} + +static int mount_sysfs(const MountEntry *m) { + int r; + + assert(m); + + (void) mkdir_p_label(mount_entry_path(m), 0755); + + r = path_is_mount_point(mount_entry_path(m), NULL, 0); + if (r < 0) + return log_debug_errno(r, "Unable to determine whether /sys is already mounted: %m"); + if (r > 0) /* make this a NOP if /sys is already a mount point */ + return 0; + + /* Bind mount the host's version so that we get all child mounts of it, too. */ + if (mount("/sys", mount_entry_path(m), NULL, MS_BIND|MS_REC, NULL) < 0) + return log_debug_errno(errno, "Failed to mount %s: %m", mount_entry_path(m)); + + return 1; +} + +static int mount_procfs(const MountEntry *m) { + int r; + + assert(m); + + (void) mkdir_p_label(mount_entry_path(m), 0755); + + r = path_is_mount_point(mount_entry_path(m), NULL, 0); + if (r < 0) + return log_debug_errno(r, "Unable to determine whether /proc is already mounted: %m"); + if (r > 0) /* make this a NOP if /proc is already a mount point */ + return 0; + + /* Mount a new instance, so that we get the one that matches our user namespace, if we are running in one */ + if (mount("proc", mount_entry_path(m), "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0) + return log_debug_errno(errno, "Failed to mount %s: %m", mount_entry_path(m)); + + return 1; +} + +static int mount_tmpfs(const MountEntry *m) { + assert(m); + + /* First, get rid of everything that is below if there is anything. Then, overmount with our new tmpfs */ + + (void) mkdir_p_label(mount_entry_path(m), 0755); + (void) umount_recursive(mount_entry_path(m), 0); + + if (mount("tmpfs", mount_entry_path(m), "tmpfs", m->flags, mount_entry_options(m)) < 0) + return log_debug_errno(errno, "Failed to mount %s: %m", mount_entry_path(m)); + + return 1; +} + +static int follow_symlink( + const char *root_directory, + MountEntry *m) { + + _cleanup_free_ char *target = NULL; + int r; + + /* Let's chase symlinks, but only one step at a time. That's because depending where the symlink points we + * might need to change the order in which we mount stuff. Hence: let's normalize piecemeal, and do one step at + * a time by specifying CHASE_STEP. This function returns 0 if we resolved one step, and > 0 if we reached the + * end and already have a fully normalized name. */ + + r = chase_symlinks(mount_entry_path(m), root_directory, CHASE_STEP|CHASE_NONEXISTENT, &target, NULL); + if (r < 0) + return log_debug_errno(r, "Failed to chase symlinks '%s': %m", mount_entry_path(m)); + if (r > 0) /* Reached the end, nothing more to resolve */ + return 1; + + if (m->n_followed >= CHASE_SYMLINKS_MAX) /* put a boundary on things */ + return log_debug_errno(SYNTHETIC_ERRNO(ELOOP), + "Symlink loop on '%s'.", + mount_entry_path(m)); + + log_debug("Followed mount entry path symlink %s → %s.", mount_entry_path(m), target); + + free_and_replace(m->path_malloc, target); + m->has_prefix = true; + + m->n_followed ++; + + return 0; +} + +static int apply_mount( + const char *root_directory, + MountEntry *m) { + + bool rbind = true, make = false; + const char *what; + int r; + + assert(m); + + log_debug("Applying namespace mount on %s", mount_entry_path(m)); + + switch (m->mode) { + + case INACCESSIBLE: { + struct stat target; + + /* First, get rid of everything that is below if there + * is anything... Then, overmount it with an + * inaccessible path. */ + (void) umount_recursive(mount_entry_path(m), 0); + + if (lstat(mount_entry_path(m), &target) < 0) { + if (errno == ENOENT && m->ignore) + return 0; + + return log_debug_errno(errno, "Failed to lstat() %s to determine what to mount over it: %m", mount_entry_path(m)); + } + + what = mode_to_inaccessible_node(target.st_mode); + if (!what) + return log_debug_errno(SYNTHETIC_ERRNO(ELOOP), + "File type not supported for inaccessible mounts. Note that symlinks are not allowed"); + break; + } + + case READONLY: + case READWRITE: + case READWRITE_IMPLICIT: + r = path_is_mount_point(mount_entry_path(m), root_directory, 0); + if (r == -ENOENT && m->ignore) + return 0; + if (r < 0) + return log_debug_errno(r, "Failed to determine whether %s is already a mount point: %m", mount_entry_path(m)); + if (r > 0) /* Nothing to do here, it is already a mount. We just later toggle the MS_RDONLY bit for the mount point if needed. */ + return 0; + /* This isn't a mount point yet, let's make it one. */ + what = mount_entry_path(m); + break; + + case BIND_MOUNT: + rbind = false; + + _fallthrough_; + case BIND_MOUNT_RECURSIVE: { + _cleanup_free_ char *chased = NULL; + + /* Since mount() will always follow symlinks we chase the symlinks on our own first. Note that bind + * mount source paths are always relative to the host root, hence we pass NULL as root directory to + * chase_symlinks() here. */ + + r = chase_symlinks(mount_entry_source(m), NULL, CHASE_TRAIL_SLASH, &chased, NULL); + if (r == -ENOENT && m->ignore) { + log_debug_errno(r, "Path %s does not exist, ignoring.", mount_entry_source(m)); + return 0; + } + if (r < 0) + return log_debug_errno(r, "Failed to follow symlinks on %s: %m", mount_entry_source(m)); + + log_debug("Followed source symlinks %s → %s.", mount_entry_source(m), chased); + + free_and_replace(m->source_malloc, chased); + + what = mount_entry_source(m); + make = true; + break; + } + + case EMPTY_DIR: + case TMPFS: + return mount_tmpfs(m); + + case PRIVATE_TMP: + what = mount_entry_source(m); + make = true; + break; + + case PRIVATE_DEV: + return mount_private_dev(m); + + case BIND_DEV: + return mount_bind_dev(m); + + case SYSFS: + return mount_sysfs(m); + + case PROCFS: + return mount_procfs(m); + + default: + assert_not_reached("Unknown mode"); + } + + assert(what); + + if (mount(what, mount_entry_path(m), NULL, MS_BIND|(rbind ? MS_REC : 0), NULL) < 0) { + bool try_again = false; + r = -errno; + + if (r == -ENOENT && make) { + struct stat st; + + /* Hmm, either the source or the destination are missing. Let's see if we can create the destination, then try again */ + + if (stat(what, &st) < 0) + log_debug_errno(errno, "Mount point source '%s' is not accessible: %m", what); + else { + int q; + + (void) mkdir_parents(mount_entry_path(m), 0755); + + if (S_ISDIR(st.st_mode)) + q = mkdir(mount_entry_path(m), 0755) < 0 ? -errno : 0; + else + q = touch(mount_entry_path(m)); + + if (q < 0) + log_debug_errno(q, "Failed to create destination mount point node '%s': %m", mount_entry_path(m)); + else + try_again = true; + } + } + + if (try_again) { + if (mount(what, mount_entry_path(m), NULL, MS_BIND|(rbind ? MS_REC : 0), NULL) < 0) + r = -errno; + else + r = 0; + } + + if (r < 0) + return log_debug_errno(r, "Failed to mount %s to %s: %m", what, mount_entry_path(m)); + } + + log_debug("Successfully mounted %s to %s", what, mount_entry_path(m)); + return 0; +} + +/* Change per-mount flags on an existing mount */ +static int bind_remount_one(const char *path, unsigned long orig_flags, unsigned long new_flags, unsigned long flags_mask) { + if (mount(NULL, path, NULL, (orig_flags & ~flags_mask) | MS_REMOUNT | MS_BIND | new_flags, NULL) < 0) + return -errno; + + return 0; +} + +static int make_read_only(const MountEntry *m, char **blacklist, FILE *proc_self_mountinfo) { + unsigned long new_flags = 0, flags_mask = 0; + bool submounts = false; + int r = 0; + + assert(m); + assert(proc_self_mountinfo); + + if (mount_entry_read_only(m) || m->mode == PRIVATE_DEV) { + new_flags |= MS_RDONLY; + flags_mask |= MS_RDONLY; + } + + if (m->nosuid) { + new_flags |= MS_NOSUID; + flags_mask |= MS_NOSUID; + } + + if (flags_mask == 0) /* No Change? */ + return 0; + + /* We generally apply these changes recursively, except for /dev, and the cases we know there's + * nothing further down. Set /dev readonly, but not submounts like /dev/shm. Also, we only set the + * per-mount read-only flag. We can't set it on the superblock, if we are inside a user namespace + * and running Linux <= 4.17. */ + submounts = + mount_entry_read_only(m) && + !IN_SET(m->mode, EMPTY_DIR, TMPFS); + if (submounts) + r = bind_remount_recursive_with_mountinfo(mount_entry_path(m), new_flags, flags_mask, blacklist, proc_self_mountinfo); + else + r = bind_remount_one(mount_entry_path(m), m->flags, new_flags, flags_mask); + + /* Not that we only turn on the MS_RDONLY flag here, we never turn it off. Something that was marked + * read-only already stays this way. This improves compatibility with container managers, where we + * won't attempt to undo read-only mounts already applied. */ + + if (r == -ENOENT && m->ignore) + return 0; + if (r < 0) + return log_debug_errno(r, "Failed to re-mount '%s'%s: %m", mount_entry_path(m), + submounts ? " and its submounts" : ""); + return 0; +} + +static bool namespace_info_mount_apivfs(const NamespaceInfo *ns_info) { + assert(ns_info); + + /* + * ProtectControlGroups= and ProtectKernelTunables= imply MountAPIVFS=, + * since to protect the API VFS mounts, they need to be around in the + * first place... + */ + + return ns_info->mount_apivfs || + ns_info->protect_control_groups || + ns_info->protect_kernel_tunables; +} + +static size_t namespace_calculate_mounts( + const NamespaceInfo *ns_info, + char** read_write_paths, + char** read_only_paths, + char** inaccessible_paths, + char** empty_directories, + size_t n_bind_mounts, + size_t n_temporary_filesystems, + const char* tmp_dir, + const char* var_tmp_dir, + ProtectHome protect_home, + ProtectSystem protect_system) { + + size_t protect_home_cnt; + size_t protect_system_cnt = + (protect_system == PROTECT_SYSTEM_STRICT ? + ELEMENTSOF(protect_system_strict_table) : + ((protect_system == PROTECT_SYSTEM_FULL) ? + ELEMENTSOF(protect_system_full_table) : + ((protect_system == PROTECT_SYSTEM_YES) ? + ELEMENTSOF(protect_system_yes_table) : 0))); + + protect_home_cnt = + (protect_home == PROTECT_HOME_YES ? + ELEMENTSOF(protect_home_yes_table) : + ((protect_home == PROTECT_HOME_READ_ONLY) ? + ELEMENTSOF(protect_home_read_only_table) : + ((protect_home == PROTECT_HOME_TMPFS) ? + ELEMENTSOF(protect_home_tmpfs_table) : 0))); + + return !!tmp_dir + !!var_tmp_dir + + strv_length(read_write_paths) + + strv_length(read_only_paths) + + strv_length(inaccessible_paths) + + strv_length(empty_directories) + + n_bind_mounts + + n_temporary_filesystems + + ns_info->private_dev + + (ns_info->protect_kernel_tunables ? ELEMENTSOF(protect_kernel_tunables_table) : 0) + + (ns_info->protect_kernel_modules ? ELEMENTSOF(protect_kernel_modules_table) : 0) + + (ns_info->protect_kernel_logs ? ELEMENTSOF(protect_kernel_logs_table) : 0) + + (ns_info->protect_control_groups ? 1 : 0) + + protect_home_cnt + protect_system_cnt + + (ns_info->protect_hostname ? 2 : 0) + + (namespace_info_mount_apivfs(ns_info) ? ELEMENTSOF(apivfs_table) : 0); +} + +static void normalize_mounts(const char *root_directory, MountEntry *mounts, size_t *n_mounts) { + assert(root_directory); + assert(n_mounts); + assert(mounts || *n_mounts == 0); + + typesafe_qsort(mounts, *n_mounts, mount_path_compare); + + drop_duplicates(mounts, n_mounts); + drop_outside_root(root_directory, mounts, n_mounts); + drop_inaccessible(mounts, n_mounts); + drop_nop(mounts, n_mounts); +} + +int setup_namespace( + const char* root_directory, + const char* root_image, + const NamespaceInfo *ns_info, + char** read_write_paths, + char** read_only_paths, + char** inaccessible_paths, + char** empty_directories, + const BindMount *bind_mounts, + size_t n_bind_mounts, + const TemporaryFileSystem *temporary_filesystems, + size_t n_temporary_filesystems, + const char* tmp_dir, + const char* var_tmp_dir, + ProtectHome protect_home, + ProtectSystem protect_system, + unsigned long mount_flags, + DissectImageFlags dissect_image_flags, + char **error_path) { + + _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; + _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL; + _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL; + _cleanup_free_ void *root_hash = NULL; + MountEntry *m = NULL, *mounts = NULL; + size_t n_mounts, root_hash_size = 0; + bool require_prefix = false; + const char *root; + int r = 0; + + assert(ns_info); + + if (mount_flags == 0) + mount_flags = MS_SHARED; + + if (root_image) { + dissect_image_flags |= DISSECT_IMAGE_REQUIRE_ROOT; + + if (protect_system == PROTECT_SYSTEM_STRICT && + protect_home != PROTECT_HOME_NO && + strv_isempty(read_write_paths)) + dissect_image_flags |= DISSECT_IMAGE_READ_ONLY; + + r = loop_device_make_by_path(root_image, + dissect_image_flags & DISSECT_IMAGE_READ_ONLY ? O_RDONLY : O_RDWR, + &loop_device); + if (r < 0) + return log_debug_errno(r, "Failed to create loop device for root image: %m"); + + r = root_hash_load(root_image, &root_hash, &root_hash_size); + if (r < 0) + return log_debug_errno(r, "Failed to load root hash: %m"); + + r = dissect_image(loop_device->fd, root_hash, root_hash_size, dissect_image_flags, &dissected_image); + if (r < 0) + return log_debug_errno(r, "Failed to dissect image: %m"); + + r = dissected_image_decrypt(dissected_image, NULL, root_hash, root_hash_size, dissect_image_flags, &decrypted_image); + if (r < 0) + return log_debug_errno(r, "Failed to decrypt dissected image: %m"); + } + + if (root_directory) + root = root_directory; + else { + /* Always create the mount namespace in a temporary directory, instead of operating + * directly in the root. The temporary directory prevents any mounts from being + * potentially obscured my other mounts we already applied. + * We use the same mount point for all images, which is safe, since they all live + * in their own namespaces after all, and hence won't see each other. */ + + root = "/run/systemd/unit-root"; + (void) mkdir_label(root, 0700); + require_prefix = true; + } + + n_mounts = namespace_calculate_mounts( + ns_info, + read_write_paths, + read_only_paths, + inaccessible_paths, + empty_directories, + n_bind_mounts, + n_temporary_filesystems, + tmp_dir, var_tmp_dir, + protect_home, protect_system); + + if (n_mounts > 0) { + m = mounts = new0(MountEntry, n_mounts); + if (!mounts) + return -ENOMEM; + + r = append_access_mounts(&m, read_write_paths, READWRITE, require_prefix); + if (r < 0) + goto finish; + + r = append_access_mounts(&m, read_only_paths, READONLY, require_prefix); + if (r < 0) + goto finish; + + r = append_access_mounts(&m, inaccessible_paths, INACCESSIBLE, require_prefix); + if (r < 0) + goto finish; + + r = append_empty_dir_mounts(&m, empty_directories); + if (r < 0) + goto finish; + + r = append_bind_mounts(&m, bind_mounts, n_bind_mounts); + if (r < 0) + goto finish; + + r = append_tmpfs_mounts(&m, temporary_filesystems, n_temporary_filesystems); + if (r < 0) + goto finish; + + if (tmp_dir) { + *(m++) = (MountEntry) { + .path_const = "/tmp", + .mode = PRIVATE_TMP, + .source_const = tmp_dir, + }; + } + + if (var_tmp_dir) { + *(m++) = (MountEntry) { + .path_const = "/var/tmp", + .mode = PRIVATE_TMP, + .source_const = var_tmp_dir, + }; + } + + if (ns_info->private_dev) { + *(m++) = (MountEntry) { + .path_const = "/dev", + .mode = PRIVATE_DEV, + .flags = DEV_MOUNT_OPTIONS, + }; + } + + if (ns_info->protect_kernel_tunables) { + r = append_static_mounts(&m, protect_kernel_tunables_table, ELEMENTSOF(protect_kernel_tunables_table), ns_info->ignore_protect_paths); + if (r < 0) + goto finish; + } + + if (ns_info->protect_kernel_modules) { + r = append_static_mounts(&m, protect_kernel_modules_table, ELEMENTSOF(protect_kernel_modules_table), ns_info->ignore_protect_paths); + if (r < 0) + goto finish; + } + + if (ns_info->protect_kernel_logs) { + r = append_static_mounts(&m, protect_kernel_logs_table, ELEMENTSOF(protect_kernel_logs_table), ns_info->ignore_protect_paths); + if (r < 0) + goto finish; + } + + if (ns_info->protect_control_groups) { + *(m++) = (MountEntry) { + .path_const = "/sys/fs/cgroup", + .mode = READONLY, + }; + } + + r = append_protect_home(&m, protect_home, ns_info->ignore_protect_paths); + if (r < 0) + goto finish; + + r = append_protect_system(&m, protect_system, false); + if (r < 0) + goto finish; + + if (namespace_info_mount_apivfs(ns_info)) { + r = append_static_mounts(&m, apivfs_table, ELEMENTSOF(apivfs_table), ns_info->ignore_protect_paths); + if (r < 0) + goto finish; + } + + if (ns_info->protect_hostname) { + *(m++) = (MountEntry) { + .path_const = "/proc/sys/kernel/hostname", + .mode = READONLY, + }; + *(m++) = (MountEntry) { + .path_const = "/proc/sys/kernel/domainname", + .mode = READONLY, + }; + } + + assert(mounts + n_mounts == m); + + /* Prepend the root directory where that's necessary */ + r = prefix_where_needed(mounts, n_mounts, root); + if (r < 0) + goto finish; + + normalize_mounts(root, mounts, &n_mounts); + } + + /* All above is just preparation, figuring out what to do. Let's now actually start doing something. */ + + if (unshare(CLONE_NEWNS) < 0) { + r = log_debug_errno(errno, "Failed to unshare the mount namespace: %m"); + if (IN_SET(r, -EACCES, -EPERM, -EOPNOTSUPP, -ENOSYS)) + /* If the kernel doesn't support namespaces, or when there's a MAC or seccomp filter in place + * that doesn't allow us to create namespaces (or a missing cap), then propagate a recognizable + * error back, which the caller can use to detect this case (and only this) and optionally + * continue without namespacing applied. */ + r = -ENOANO; + + goto finish; + } + + /* Remount / as SLAVE so that nothing now mounted in the namespace + * shows up in the parent */ + if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) { + r = log_debug_errno(errno, "Failed to remount '/' as SLAVE: %m"); + goto finish; + } + + if (root_image) { + /* A root image is specified, mount it to the right place */ + r = dissected_image_mount(dissected_image, root, UID_INVALID, dissect_image_flags); + if (r < 0) { + log_debug_errno(r, "Failed to mount root image: %m"); + goto finish; + } + + if (decrypted_image) { + r = decrypted_image_relinquish(decrypted_image); + if (r < 0) { + log_debug_errno(r, "Failed to relinquish decrypted image: %m"); + goto finish; + } + } + + loop_device_relinquish(loop_device); + + } else if (root_directory) { + + /* A root directory is specified. Turn its directory into bind mount, if it isn't one yet. */ + r = path_is_mount_point(root, NULL, AT_SYMLINK_FOLLOW); + if (r < 0) { + log_debug_errno(r, "Failed to detect that %s is a mount point or not: %m", root); + goto finish; + } + if (r == 0) { + if (mount(root, root, NULL, MS_BIND|MS_REC, NULL) < 0) { + r = log_debug_errno(errno, "Failed to bind mount '%s': %m", root); + goto finish; + } + } + + } else { + + /* Let's mount the main root directory to the root directory to use */ + if (mount("/", root, NULL, MS_BIND|MS_REC, NULL) < 0) { + r = log_debug_errno(errno, "Failed to bind mount '/' on '%s': %m", root); + goto finish; + } + } + + /* Try to set up the new root directory before mounting anything else there. */ + if (root_image || root_directory) + (void) base_filesystem_create(root, UID_INVALID, GID_INVALID); + + if (n_mounts > 0) { + _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; + _cleanup_free_ char **blacklist = NULL; + size_t j; + + /* Open /proc/self/mountinfo now as it may become unavailable if we mount anything on top of /proc. + * For example, this is the case with the option: 'InaccessiblePaths=/proc' */ + proc_self_mountinfo = fopen("/proc/self/mountinfo", "re"); + if (!proc_self_mountinfo) { + r = log_debug_errno(errno, "Failed to open /proc/self/mountinfo: %m"); + if (error_path) + *error_path = strdup("/proc/self/mountinfo"); + goto finish; + } + + /* First round, establish all mounts we need */ + for (;;) { + bool again = false; + + for (m = mounts; m < mounts + n_mounts; ++m) { + + if (m->applied) + continue; + + r = follow_symlink(root, m); + if (r < 0) { + if (error_path && mount_entry_path(m)) + *error_path = strdup(mount_entry_path(m)); + goto finish; + } + if (r == 0) { + /* We hit a symlinked mount point. The entry got rewritten and might point to a + * very different place now. Let's normalize the changed list, and start from + * the beginning. After all to mount the entry at the new location we might + * need some other mounts first */ + again = true; + break; + } + + r = apply_mount(root, m); + if (r < 0) { + if (error_path && mount_entry_path(m)) + *error_path = strdup(mount_entry_path(m)); + goto finish; + } + + m->applied = true; + } + + if (!again) + break; + + normalize_mounts(root, mounts, &n_mounts); + } + + /* Create a blacklist we can pass to bind_mount_recursive() */ + blacklist = new(char*, n_mounts+1); + if (!blacklist) { + r = -ENOMEM; + goto finish; + } + for (j = 0; j < n_mounts; j++) + blacklist[j] = (char*) mount_entry_path(mounts+j); + blacklist[j] = NULL; + + /* Second round, flip the ro bits if necessary. */ + for (m = mounts; m < mounts + n_mounts; ++m) { + r = make_read_only(m, blacklist, proc_self_mountinfo); + if (r < 0) { + if (error_path && mount_entry_path(m)) + *error_path = strdup(mount_entry_path(m)); + goto finish; + } + } + } + + /* MS_MOVE does not work on MS_SHARED so the remount MS_SHARED will be done later */ + r = mount_move_root(root); + if (r < 0) { + log_debug_errno(r, "Failed to mount root with MS_MOVE: %m"); + goto finish; + } + + /* Remount / as the desired mode. Note that this will not + * reestablish propagation from our side to the host, since + * what's disconnected is disconnected. */ + if (mount(NULL, "/", NULL, mount_flags | MS_REC, NULL) < 0) { + r = log_debug_errno(errno, "Failed to remount '/' with desired mount flags: %m"); + goto finish; + } + + r = 0; + +finish: + for (m = mounts; m < mounts + n_mounts; m++) + mount_entry_done(m); + + free(mounts); + + return r; +} + +void bind_mount_free_many(BindMount *b, size_t n) { + size_t i; + + assert(b || n == 0); + + for (i = 0; i < n; i++) { + free(b[i].source); + free(b[i].destination); + } + + free(b); +} + +int bind_mount_add(BindMount **b, size_t *n, const BindMount *item) { + _cleanup_free_ char *s = NULL, *d = NULL; + BindMount *c; + + assert(b); + assert(n); + assert(item); + + s = strdup(item->source); + if (!s) + return -ENOMEM; + + d = strdup(item->destination); + if (!d) + return -ENOMEM; + + c = reallocarray(*b, *n + 1, sizeof(BindMount)); + if (!c) + return -ENOMEM; + + *b = c; + + c[(*n) ++] = (BindMount) { + .source = TAKE_PTR(s), + .destination = TAKE_PTR(d), + .read_only = item->read_only, + .nosuid = item->nosuid, + .recursive = item->recursive, + .ignore_enoent = item->ignore_enoent, + }; + + return 0; +} + +void temporary_filesystem_free_many(TemporaryFileSystem *t, size_t n) { + size_t i; + + assert(t || n == 0); + + for (i = 0; i < n; i++) { + free(t[i].path); + free(t[i].options); + } + + free(t); +} + +int temporary_filesystem_add( + TemporaryFileSystem **t, + size_t *n, + const char *path, + const char *options) { + + _cleanup_free_ char *p = NULL, *o = NULL; + TemporaryFileSystem *c; + + assert(t); + assert(n); + assert(path); + + p = strdup(path); + if (!p) + return -ENOMEM; + + if (!isempty(options)) { + o = strdup(options); + if (!o) + return -ENOMEM; + } + + c = reallocarray(*t, *n + 1, sizeof(TemporaryFileSystem)); + if (!c) + return -ENOMEM; + + *t = c; + + c[(*n) ++] = (TemporaryFileSystem) { + .path = TAKE_PTR(p), + .options = TAKE_PTR(o), + }; + + return 0; +} + +static int make_tmp_prefix(const char *prefix) { + _cleanup_free_ char *t = NULL; + int r; + + /* Don't do anything unless we know the dir is actually missing */ + r = access(prefix, F_OK); + if (r >= 0) + return 0; + if (errno != ENOENT) + return -errno; + + r = mkdir_parents(prefix, 0755); + if (r < 0) + return r; + + r = tempfn_random(prefix, NULL, &t); + if (r < 0) + return r; + + if (mkdir(t, 0777) < 0) + return -errno; + + if (chmod(t, 01777) < 0) { + r = -errno; + (void) rmdir(t); + return r; + } + + if (rename(t, prefix) < 0) { + r = -errno; + (void) rmdir(t); + return r == -EEXIST ? 0 : r; /* it's fine if someone else created the dir by now */ + } + + return 0; + +} + +static int setup_one_tmp_dir(const char *id, const char *prefix, char **path) { + _cleanup_free_ char *x = NULL; + char bid[SD_ID128_STRING_MAX]; + sd_id128_t boot_id; + int r; + + assert(id); + assert(prefix); + assert(path); + + /* We include the boot id in the directory so that after a + * reboot we can easily identify obsolete directories. */ + + r = sd_id128_get_boot(&boot_id); + if (r < 0) + return r; + + x = strjoin(prefix, "/systemd-private-", sd_id128_to_string(boot_id, bid), "-", id, "-XXXXXX"); + if (!x) + return -ENOMEM; + + r = make_tmp_prefix(prefix); + if (r < 0) + return r; + + RUN_WITH_UMASK(0077) + if (!mkdtemp(x)) + return -errno; + + RUN_WITH_UMASK(0000) { + char *y; + + y = strjoina(x, "/tmp"); + + if (mkdir(y, 0777 | S_ISVTX) < 0) + return -errno; + } + + *path = TAKE_PTR(x); + + return 0; +} + +int setup_tmp_dirs(const char *id, char **tmp_dir, char **var_tmp_dir) { + char *a, *b; + int r; + + assert(id); + assert(tmp_dir); + assert(var_tmp_dir); + + r = setup_one_tmp_dir(id, "/tmp", &a); + if (r < 0) + return r; + + r = setup_one_tmp_dir(id, "/var/tmp", &b); + if (r < 0) { + char *t; + + t = strjoina(a, "/tmp"); + (void) rmdir(t); + (void) rmdir(a); + + free(a); + return r; + } + + *tmp_dir = a; + *var_tmp_dir = b; + + return 0; +} + +int setup_netns(const int netns_storage_socket[static 2]) { + _cleanup_close_ int netns = -1; + int r, q; + + assert(netns_storage_socket); + assert(netns_storage_socket[0] >= 0); + assert(netns_storage_socket[1] >= 0); + + /* We use the passed socketpair as a storage buffer for our + * namespace reference fd. Whatever process runs this first + * shall create a new namespace, all others should just join + * it. To serialize that we use a file lock on the socket + * pair. + * + * It's a bit crazy, but hey, works great! */ + + if (lockf(netns_storage_socket[0], F_LOCK, 0) < 0) + return -errno; + + netns = receive_one_fd(netns_storage_socket[0], MSG_DONTWAIT); + if (netns == -EAGAIN) { + /* Nothing stored yet, so let's create a new namespace. */ + + if (unshare(CLONE_NEWNET) < 0) { + r = -errno; + goto fail; + } + + (void) loopback_setup(); + + netns = open("/proc/self/ns/net", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (netns < 0) { + r = -errno; + goto fail; + } + + r = 1; + + } else if (netns < 0) { + r = netns; + goto fail; + + } else { + /* Yay, found something, so let's join the namespace */ + if (setns(netns, CLONE_NEWNET) < 0) { + r = -errno; + goto fail; + } + + r = 0; + } + + q = send_one_fd(netns_storage_socket[1], netns, MSG_DONTWAIT); + if (q < 0) { + r = q; + goto fail; + } + +fail: + (void) lockf(netns_storage_socket[0], F_ULOCK, 0); + return r; +} + +int open_netns_path(const int netns_storage_socket[static 2], const char *path) { + _cleanup_close_ int netns = -1; + int q, r; + + assert(netns_storage_socket); + assert(netns_storage_socket[0] >= 0); + assert(netns_storage_socket[1] >= 0); + assert(path); + + /* If the storage socket doesn't contain a netns fd yet, open one via the file system and store it in + * it. This is supposed to be called ahead of time, i.e. before setup_netns() which will allocate a + * new anonymous netns if needed. */ + + if (lockf(netns_storage_socket[0], F_LOCK, 0) < 0) + return -errno; + + netns = receive_one_fd(netns_storage_socket[0], MSG_DONTWAIT); + if (netns == -EAGAIN) { + /* Nothing stored yet. Open the file from the file system. */ + + netns = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (netns < 0) { + r = -errno; + goto fail; + } + + r = fd_is_network_ns(netns); + if (r == 0) { /* Not a netns? Refuse early. */ + r = -EINVAL; + goto fail; + } + if (r < 0 && r != -EUCLEAN) /* EUCLEAN: we don't know */ + goto fail; + + r = 1; + + } else if (netns < 0) { + r = netns; + goto fail; + } else + r = 0; /* Already allocated */ + + q = send_one_fd(netns_storage_socket[1], netns, MSG_DONTWAIT); + if (q < 0) { + r = q; + goto fail; + } + +fail: + (void) lockf(netns_storage_socket[0], F_ULOCK, 0); + return r; +} + +bool ns_type_supported(NamespaceType type) { + const char *t, *ns_proc; + + t = namespace_type_to_string(type); + if (!t) /* Don't know how to translate this? Then it's not supported */ + return false; + + ns_proc = strjoina("/proc/self/ns/", t); + return access(ns_proc, F_OK) == 0; +} + +static const char *const protect_home_table[_PROTECT_HOME_MAX] = { + [PROTECT_HOME_NO] = "no", + [PROTECT_HOME_YES] = "yes", + [PROTECT_HOME_READ_ONLY] = "read-only", + [PROTECT_HOME_TMPFS] = "tmpfs", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(protect_home, ProtectHome, PROTECT_HOME_YES); + +static const char *const protect_system_table[_PROTECT_SYSTEM_MAX] = { + [PROTECT_SYSTEM_NO] = "no", + [PROTECT_SYSTEM_YES] = "yes", + [PROTECT_SYSTEM_FULL] = "full", + [PROTECT_SYSTEM_STRICT] = "strict", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(protect_system, ProtectSystem, PROTECT_SYSTEM_YES); + +static const char* const namespace_type_table[] = { + [NAMESPACE_MOUNT] = "mnt", + [NAMESPACE_CGROUP] = "cgroup", + [NAMESPACE_UTS] = "uts", + [NAMESPACE_IPC] = "ipc", + [NAMESPACE_USER] = "user", + [NAMESPACE_PID] = "pid", + [NAMESPACE_NET] = "net", +}; + +DEFINE_STRING_TABLE_LOOKUP(namespace_type, NamespaceType); diff --git a/src/core/namespace.h b/src/core/namespace.h new file mode 100644 index 00000000..60a6abcd --- /dev/null +++ b/src/core/namespace.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2016 Djalal Harouni +***/ + +typedef struct NamespaceInfo NamespaceInfo; +typedef struct BindMount BindMount; +typedef struct TemporaryFileSystem TemporaryFileSystem; + +#include + +#include "dissect-image.h" +#include "macro.h" + +typedef enum ProtectHome { + PROTECT_HOME_NO, + PROTECT_HOME_YES, + PROTECT_HOME_READ_ONLY, + PROTECT_HOME_TMPFS, + _PROTECT_HOME_MAX, + _PROTECT_HOME_INVALID = -1 +} ProtectHome; + +typedef enum NamespaceType { + NAMESPACE_MOUNT, + NAMESPACE_CGROUP, + NAMESPACE_UTS, + NAMESPACE_IPC, + NAMESPACE_USER, + NAMESPACE_PID, + NAMESPACE_NET, + _NAMESPACE_TYPE_MAX, + _NAMESPACE_TYPE_INVALID = -1, +} NamespaceType; + +typedef enum ProtectSystem { + PROTECT_SYSTEM_NO, + PROTECT_SYSTEM_YES, + PROTECT_SYSTEM_FULL, + PROTECT_SYSTEM_STRICT, + _PROTECT_SYSTEM_MAX, + _PROTECT_SYSTEM_INVALID = -1 +} ProtectSystem; + +struct NamespaceInfo { + bool ignore_protect_paths:1; + bool private_dev:1; + bool private_mounts:1; + bool protect_control_groups:1; + bool protect_kernel_tunables:1; + bool protect_kernel_modules:1; + bool protect_kernel_logs:1; + bool mount_apivfs:1; + bool protect_hostname:1; +}; + +struct BindMount { + char *source; + char *destination; + bool read_only:1; + bool nosuid:1; + bool recursive:1; + bool ignore_enoent:1; +}; + +struct TemporaryFileSystem { + char *path; + char *options; +}; + +int setup_namespace( + const char *root_directory, + const char *root_image, + const NamespaceInfo *ns_info, + char **read_write_paths, + char **read_only_paths, + char **inaccessible_paths, + char **empty_directories, + const BindMount *bind_mounts, + size_t n_bind_mounts, + const TemporaryFileSystem *temporary_filesystems, + size_t n_temporary_filesystems, + const char *tmp_dir, + const char *var_tmp_dir, + ProtectHome protect_home, + ProtectSystem protect_system, + unsigned long mount_flags, + DissectImageFlags dissected_image_flags, + char **error_path); + +int setup_tmp_dirs( + const char *id, + char **tmp_dir, + char **var_tmp_dir); + +int setup_netns(const int netns_storage_socket[static 2]); +int open_netns_path(const int netns_storage_socket[static 2], const char *path); + +const char* protect_home_to_string(ProtectHome p) _const_; +ProtectHome protect_home_from_string(const char *s) _pure_; + +const char* protect_system_to_string(ProtectSystem p) _const_; +ProtectSystem protect_system_from_string(const char *s) _pure_; + +void bind_mount_free_many(BindMount *b, size_t n); +int bind_mount_add(BindMount **b, size_t *n, const BindMount *item); + +void temporary_filesystem_free_many(TemporaryFileSystem *t, size_t n); +int temporary_filesystem_add(TemporaryFileSystem **t, size_t *n, + const char *path, const char *options); + +const char* namespace_type_to_string(NamespaceType t) _const_; +NamespaceType namespace_type_from_string(const char *s) _pure_; + +bool ns_type_supported(NamespaceType type); diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf new file mode 100644 index 00000000..415b3f5d --- /dev/null +++ b/src/core/org.freedesktop.systemd1.conf @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/core/org.freedesktop.systemd1.policy.in b/src/core/org.freedesktop.systemd1.policy.in new file mode 100644 index 00000000..001408d3 --- /dev/null +++ b/src/core/org.freedesktop.systemd1.policy.in @@ -0,0 +1,73 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Send passphrase back to system + Authentication is required to send the entered passphrase back to the system. + + no + no + auth_admin_keep + + @rootlibexecdir@/systemd-reply-password + + + + Manage system services or other units + Authentication is required to manage system services or other units. + + auth_admin + auth_admin + auth_admin_keep + + + + + Manage system service or unit files + Authentication is required to manage system service or unit files. + + auth_admin + auth_admin + auth_admin_keep + + org.freedesktop.systemd1.reload-daemon org.freedesktop.systemd1.manage-units + + + + Set or unset system and service manager environment variables + Authentication is required to set or unset system and service manager environment variables. + + auth_admin + auth_admin + auth_admin_keep + + + + + Reload the systemd state + Authentication is required to reload the systemd state. + + auth_admin + auth_admin + auth_admin_keep + + + + diff --git a/src/core/org.freedesktop.systemd1.service b/src/core/org.freedesktop.systemd1.service new file mode 100644 index 00000000..8bd7302d --- /dev/null +++ b/src/core/org.freedesktop.systemd1.service @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.systemd1 +Exec=/bin/false +User=root diff --git a/src/core/path.c b/src/core/path.c new file mode 100644 index 00000000..ca15ca88 --- /dev/null +++ b/src/core/path.c @@ -0,0 +1,833 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "bus-error.h" +#include "bus-util.h" +#include "dbus-path.h" +#include "dbus-unit.h" +#include "escape.h" +#include "fd-util.h" +#include "fs-util.h" +#include "glob-util.h" +#include "macro.h" +#include "mkdir.h" +#include "path.h" +#include "path-util.h" +#include "serialize.h" +#include "special.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "unit-name.h" +#include "unit.h" + +static const UnitActiveState state_translation_table[_PATH_STATE_MAX] = { + [PATH_DEAD] = UNIT_INACTIVE, + [PATH_WAITING] = UNIT_ACTIVE, + [PATH_RUNNING] = UNIT_ACTIVE, + [PATH_FAILED] = UNIT_FAILED, +}; + +static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); + +int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) { + static const int flags_table[_PATH_TYPE_MAX] = { + [PATH_EXISTS] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, + [PATH_EXISTS_GLOB] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB, + [PATH_CHANGED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO, + [PATH_MODIFIED] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO|IN_MODIFY, + [PATH_DIRECTORY_NOT_EMPTY] = IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO, + }; + + bool exists = false; + char *slash, *oldslash = NULL; + int r; + + assert(s); + assert(s->unit); + assert(handler); + + path_spec_unwatch(s); + + s->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (s->inotify_fd < 0) { + r = -errno; + goto fail; + } + + r = sd_event_add_io(s->unit->manager->event, &s->event_source, s->inotify_fd, EPOLLIN, handler, s); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(s->event_source, "path"); + + /* This function assumes the path was passed through path_simplify()! */ + assert(!strstr(s->path, "//")); + + for (slash = strchr(s->path, '/'); ; slash = strchr(slash+1, '/')) { + char *cut = NULL; + int flags; + char tmp; + + if (slash) { + cut = slash + (slash == s->path); + tmp = *cut; + *cut = '\0'; + + flags = IN_MOVE_SELF | IN_DELETE_SELF | IN_ATTRIB | IN_CREATE | IN_MOVED_TO; + } else + flags = flags_table[s->type]; + + r = inotify_add_watch(s->inotify_fd, s->path, flags); + if (r < 0) { + if (IN_SET(errno, EACCES, ENOENT)) { + if (cut) + *cut = tmp; + break; + } + + /* This second call to inotify_add_watch() should fail like the previous + * one and is done for logging the error in a comprehensive way. */ + r = inotify_add_watch_and_warn(s->inotify_fd, s->path, flags); + if (r < 0) { + if (cut) + *cut = tmp; + goto fail; + } + + /* Hmm, we succeeded in adding the watch this time... let's continue. */ + } + exists = true; + + /* Path exists, we don't need to watch parent too closely. */ + if (oldslash) { + char *cut2 = oldslash + (oldslash == s->path); + char tmp2 = *cut2; + *cut2 = '\0'; + + (void) inotify_add_watch(s->inotify_fd, s->path, IN_MOVE_SELF); + /* Error is ignored, the worst can happen is we get spurious events. */ + + *cut2 = tmp2; + } + + if (cut) + *cut = tmp; + + if (slash) + oldslash = slash; + else { + /* whole path has been iterated over */ + s->primary_wd = r; + break; + } + } + + if (!exists) { + r = log_error_errno(errno, "Failed to add watch on any of the components of %s: %m", s->path); + /* either EACCESS or ENOENT */ + goto fail; + } + + return 0; + +fail: + path_spec_unwatch(s); + return r; +} + +void path_spec_unwatch(PathSpec *s) { + assert(s); + + s->event_source = sd_event_source_unref(s->event_source); + s->inotify_fd = safe_close(s->inotify_fd); +} + +int path_spec_fd_event(PathSpec *s, uint32_t revents) { + union inotify_event_buffer buffer; + struct inotify_event *e; + ssize_t l; + int r = 0; + + if (revents != EPOLLIN) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Got invalid poll event on inotify."); + + l = read(s->inotify_fd, &buffer, sizeof(buffer)); + if (l < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + return log_error_errno(errno, "Failed to read inotify event: %m"); + } + + FOREACH_INOTIFY_EVENT(e, buffer, l) { + if (IN_SET(s->type, PATH_CHANGED, PATH_MODIFIED) && + s->primary_wd == e->wd) + r = 1; + } + + return r; +} + +static bool path_spec_check_good(PathSpec *s, bool initial) { + bool b, good = false; + + switch (s->type) { + + case PATH_EXISTS: + b = access(s->path, F_OK) >= 0; + good = b && !s->previous_exists; + s->previous_exists = b; + break; + + case PATH_EXISTS_GLOB: + good = glob_exists(s->path) > 0; + break; + + case PATH_DIRECTORY_NOT_EMPTY: { + int k; + + k = dir_is_empty(s->path); + good = !(k == -ENOENT || k > 0); + break; + } + + case PATH_CHANGED: + case PATH_MODIFIED: + b = access(s->path, F_OK) >= 0; + good = !initial && b != s->previous_exists; + s->previous_exists = b; + break; + + default: + ; + } + + return good; +} + +static void path_spec_mkdir(PathSpec *s, mode_t mode) { + int r; + + if (IN_SET(s->type, PATH_EXISTS, PATH_EXISTS_GLOB)) + return; + + r = mkdir_p_label(s->path, mode); + if (r < 0) + log_warning_errno(r, "mkdir(%s) failed: %m", s->path); +} + +static void path_spec_dump(PathSpec *s, FILE *f, const char *prefix) { + fprintf(f, + "%s%s: %s\n", + prefix, + path_type_to_string(s->type), + s->path); +} + +void path_spec_done(PathSpec *s) { + assert(s); + assert(s->inotify_fd == -1); + + free(s->path); +} + +static void path_init(Unit *u) { + Path *p = PATH(u); + + assert(u); + assert(u->load_state == UNIT_STUB); + + p->directory_mode = 0755; +} + +void path_free_specs(Path *p) { + PathSpec *s; + + assert(p); + + while ((s = p->specs)) { + path_spec_unwatch(s); + LIST_REMOVE(spec, p->specs, s); + path_spec_done(s); + free(s); + } +} + +static void path_done(Unit *u) { + Path *p = PATH(u); + + assert(p); + + path_free_specs(p); +} + +static int path_add_mount_dependencies(Path *p) { + PathSpec *s; + int r; + + assert(p); + + LIST_FOREACH(spec, s, p->specs) { + r = unit_require_mounts_for(UNIT(p), s->path, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + } + + return 0; +} + +static int path_verify(Path *p) { + assert(p); + assert(UNIT(p)->load_state == UNIT_LOADED); + + if (!p->specs) { + log_unit_error(UNIT(p), "Path unit lacks path setting. Refusing."); + return -ENOEXEC; + } + + return 0; +} + +static int path_add_default_dependencies(Path *p) { + int r; + + assert(p); + + if (!UNIT(p)->default_dependencies) + return 0; + + r = unit_add_dependency_by_name(UNIT(p), UNIT_BEFORE, SPECIAL_PATHS_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + if (MANAGER_IS_SYSTEM(UNIT(p)->manager)) { + r = unit_add_two_dependencies_by_name(UNIT(p), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + } + + return unit_add_two_dependencies_by_name(UNIT(p), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT); +} + +static int path_add_trigger_dependencies(Path *p) { + Unit *x; + int r; + + assert(p); + + if (!hashmap_isempty(UNIT(p)->dependencies[UNIT_TRIGGERS])) + return 0; + + r = unit_load_related_unit(UNIT(p), ".service", &x); + if (r < 0) + return r; + + return unit_add_two_dependencies(UNIT(p), UNIT_BEFORE, UNIT_TRIGGERS, x, true, UNIT_DEPENDENCY_IMPLICIT); +} + +static int path_add_extras(Path *p) { + int r; + + r = path_add_trigger_dependencies(p); + if (r < 0) + return r; + + r = path_add_mount_dependencies(p); + if (r < 0) + return r; + + return path_add_default_dependencies(p); +} + +static int path_load(Unit *u) { + Path *p = PATH(u); + int r; + + assert(u); + assert(u->load_state == UNIT_STUB); + + r = unit_load_fragment_and_dropin(u, true); + if (r < 0) + return r; + + if (u->load_state != UNIT_LOADED) + return 0; + + r = path_add_extras(p); + if (r < 0) + return r; + + return path_verify(p); +} + +static void path_dump(Unit *u, FILE *f, const char *prefix) { + Path *p = PATH(u); + Unit *trigger; + PathSpec *s; + + assert(p); + assert(f); + + trigger = UNIT_TRIGGER(u); + + fprintf(f, + "%sPath State: %s\n" + "%sResult: %s\n" + "%sUnit: %s\n" + "%sMakeDirectory: %s\n" + "%sDirectoryMode: %04o\n", + prefix, path_state_to_string(p->state), + prefix, path_result_to_string(p->result), + prefix, trigger ? trigger->id : "n/a", + prefix, yes_no(p->make_directory), + prefix, p->directory_mode); + + LIST_FOREACH(spec, s, p->specs) + path_spec_dump(s, f, prefix); +} + +static void path_unwatch(Path *p) { + PathSpec *s; + + assert(p); + + LIST_FOREACH(spec, s, p->specs) + path_spec_unwatch(s); +} + +static int path_watch(Path *p) { + int r; + PathSpec *s; + + assert(p); + + LIST_FOREACH(spec, s, p->specs) { + r = path_spec_watch(s, path_dispatch_io); + if (r < 0) + return r; + } + + return 0; +} + +static void path_set_state(Path *p, PathState state) { + PathState old_state; + assert(p); + + if (p->state != state) + bus_unit_send_pending_change_signal(UNIT(p), false); + + old_state = p->state; + p->state = state; + + if (state != PATH_WAITING && + (state != PATH_RUNNING || p->inotify_triggered)) + path_unwatch(p); + + if (state != old_state) + log_unit_debug(UNIT(p), "Changed %s -> %s", path_state_to_string(old_state), path_state_to_string(state)); + + unit_notify(UNIT(p), state_translation_table[old_state], state_translation_table[state], 0); +} + +static void path_enter_waiting(Path *p, bool initial, bool recheck); + +static int path_coldplug(Unit *u) { + Path *p = PATH(u); + + assert(p); + assert(p->state == PATH_DEAD); + + if (p->deserialized_state != p->state) { + + if (IN_SET(p->deserialized_state, PATH_WAITING, PATH_RUNNING)) + path_enter_waiting(p, true, true); + else + path_set_state(p, p->deserialized_state); + } + + return 0; +} + +static void path_enter_dead(Path *p, PathResult f) { + assert(p); + + if (p->result == PATH_SUCCESS) + p->result = f; + + unit_log_result(UNIT(p), p->result == PATH_SUCCESS, path_result_to_string(p->result)); + path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD); +} + +static void path_enter_running(Path *p) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + Unit *trigger; + int r; + + assert(p); + + /* Don't start job if we are supposed to go down */ + if (unit_stop_pending(UNIT(p))) + return; + + trigger = UNIT_TRIGGER(UNIT(p)); + if (!trigger) { + log_unit_error(UNIT(p), "Unit to trigger vanished."); + path_enter_dead(p, PATH_FAILURE_RESOURCES); + return; + } + + r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL); + if (r < 0) + goto fail; + + p->inotify_triggered = false; + + path_set_state(p, PATH_RUNNING); + path_unwatch(p); + + return; + +fail: + log_unit_warning(UNIT(p), "Failed to queue unit startup job: %s", bus_error_message(&error, r)); + path_enter_dead(p, PATH_FAILURE_RESOURCES); +} + +static bool path_check_good(Path *p, bool initial) { + PathSpec *s; + + assert(p); + + LIST_FOREACH(spec, s, p->specs) + if (path_spec_check_good(s, initial)) + return true; + + return false; +} + +static void path_enter_waiting(Path *p, bool initial, bool recheck) { + int r; + + if (recheck) + if (path_check_good(p, initial)) { + log_unit_debug(UNIT(p), "Got triggered."); + path_enter_running(p); + return; + } + + r = path_watch(p); + if (r < 0) + goto fail; + + /* Hmm, so now we have created inotify watches, but the file + * might have appeared/been removed by now, so we must + * recheck */ + + if (recheck) + if (path_check_good(p, false)) { + log_unit_debug(UNIT(p), "Got triggered."); + path_enter_running(p); + return; + } + + path_set_state(p, PATH_WAITING); + return; + +fail: + log_unit_warning_errno(UNIT(p), r, "Failed to enter waiting state: %m"); + path_enter_dead(p, PATH_FAILURE_RESOURCES); +} + +static void path_mkdir(Path *p) { + PathSpec *s; + + assert(p); + + if (!p->make_directory) + return; + + LIST_FOREACH(spec, s, p->specs) + path_spec_mkdir(s, p->directory_mode); +} + +static int path_start(Unit *u) { + Path *p = PATH(u); + int r; + + assert(p); + assert(IN_SET(p->state, PATH_DEAD, PATH_FAILED)); + + r = unit_test_trigger_loaded(u); + if (r < 0) + return r; + + r = unit_test_start_limit(u); + if (r < 0) { + path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT); + return r; + } + + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + + path_mkdir(p); + + p->result = PATH_SUCCESS; + path_enter_waiting(p, true, true); + + return 1; +} + +static int path_stop(Unit *u) { + Path *p = PATH(u); + + assert(p); + assert(IN_SET(p->state, PATH_WAITING, PATH_RUNNING)); + + path_enter_dead(p, PATH_SUCCESS); + return 1; +} + +static int path_serialize(Unit *u, FILE *f, FDSet *fds) { + Path *p = PATH(u); + PathSpec *s; + + assert(u); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", path_state_to_string(p->state)); + (void) serialize_item(f, "result", path_result_to_string(p->result)); + + LIST_FOREACH(spec, s, p->specs) { + _cleanup_free_ char *escaped = NULL; + + escaped = cescape(s->path); + if (!escaped) + return log_oom(); + + (void) serialize_item_format(f, "path-spec", "%s %i %s", + path_type_to_string(s->type), + s->previous_exists, + s->path); + } + + return 0; +} + +static int path_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Path *p = PATH(u); + + assert(u); + assert(key); + assert(value); + assert(fds); + + if (streq(key, "state")) { + PathState state; + + state = path_state_from_string(value); + if (state < 0) + log_unit_debug(u, "Failed to parse state value: %s", value); + else + p->deserialized_state = state; + + } else if (streq(key, "result")) { + PathResult f; + + f = path_result_from_string(value); + if (f < 0) + log_unit_debug(u, "Failed to parse result value: %s", value); + else if (f != PATH_SUCCESS) + p->result = f; + + } else if (streq(key, "path-spec")) { + int previous_exists, skip = 0, r; + _cleanup_free_ char *type_str = NULL; + + if (sscanf(value, "%ms %i %n", &type_str, &previous_exists, &skip) < 2) + log_unit_debug(u, "Failed to parse path-spec value: %s", value); + else { + _cleanup_free_ char *unescaped = NULL; + PathType type; + PathSpec *s; + + type = path_type_from_string(type_str); + if (type < 0) { + log_unit_warning(u, "Unknown path type \"%s\", ignoring.", type_str); + return 0; + } + + r = cunescape(value+skip, 0, &unescaped); + if (r < 0) { + log_unit_warning_errno(u, r, "Failed to unescape serialize path: %m"); + return 0; + } + + LIST_FOREACH(spec, s, p->specs) + if (s->type == type && + path_equal(s->path, unescaped)) { + + s->previous_exists = previous_exists; + break; + } + } + + } else + log_unit_debug(u, "Unknown serialization key: %s", key); + + return 0; +} + +_pure_ static UnitActiveState path_active_state(Unit *u) { + assert(u); + + return state_translation_table[PATH(u)->state]; +} + +_pure_ static const char *path_sub_state_to_string(Unit *u) { + assert(u); + + return path_state_to_string(PATH(u)->state); +} + +static int path_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + PathSpec *s = userdata; + Path *p; + int changed; + + assert(s); + assert(s->unit); + assert(fd >= 0); + + p = PATH(s->unit); + + if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING)) + return 0; + + /* log_debug("inotify wakeup on %s.", UNIT(p)->id); */ + + LIST_FOREACH(spec, s, p->specs) + if (path_spec_owns_inotify_fd(s, fd)) + break; + + if (!s) { + log_error("Got event on unknown fd."); + goto fail; + } + + changed = path_spec_fd_event(s, revents); + if (changed < 0) + goto fail; + + /* If we are already running, then remember that one event was + * dispatched so that we restart the service only if something + * actually changed on disk */ + p->inotify_triggered = true; + + if (changed) + path_enter_running(p); + else + path_enter_waiting(p, false, true); + + return 0; + +fail: + path_enter_dead(p, PATH_FAILURE_RESOURCES); + return 0; +} + +static void path_trigger_notify(Unit *u, Unit *other) { + Path *p = PATH(u); + + assert(u); + assert(other); + + /* Invoked whenever the unit we trigger changes state or gains + * or loses a job */ + + if (other->load_state != UNIT_LOADED) + return; + + if (p->state == PATH_RUNNING && + UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) { + log_unit_debug(UNIT(p), "Got notified about unit deactivation."); + + /* Hmm, so inotify was triggered since the + * last activation, so I guess we need to + * recheck what is going on. */ + path_enter_waiting(p, false, p->inotify_triggered); + } +} + +static void path_reset_failed(Unit *u) { + Path *p = PATH(u); + + assert(p); + + if (p->state == PATH_FAILED) + path_set_state(p, PATH_DEAD); + + p->result = PATH_SUCCESS; +} + +static const char* const path_type_table[_PATH_TYPE_MAX] = { + [PATH_EXISTS] = "PathExists", + [PATH_EXISTS_GLOB] = "PathExistsGlob", + [PATH_DIRECTORY_NOT_EMPTY] = "DirectoryNotEmpty", + [PATH_CHANGED] = "PathChanged", + [PATH_MODIFIED] = "PathModified", +}; + +DEFINE_STRING_TABLE_LOOKUP(path_type, PathType); + +static const char* const path_result_table[_PATH_RESULT_MAX] = { + [PATH_SUCCESS] = "success", + [PATH_FAILURE_RESOURCES] = "resources", + [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", +}; + +DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult); + +const UnitVTable path_vtable = { + .object_size = sizeof(Path), + + .sections = + "Unit\0" + "Path\0" + "Install\0", + .private_section = "Path", + + .can_transient = true, + + .init = path_init, + .done = path_done, + .load = path_load, + + .coldplug = path_coldplug, + + .dump = path_dump, + + .start = path_start, + .stop = path_stop, + + .serialize = path_serialize, + .deserialize_item = path_deserialize_item, + + .active_state = path_active_state, + .sub_state_to_string = path_sub_state_to_string, + + .trigger_notify = path_trigger_notify, + + .reset_failed = path_reset_failed, + + .bus_vtable = bus_path_vtable, + .bus_set_property = bus_path_set_property, +}; diff --git a/src/core/path.h b/src/core/path.h new file mode 100644 index 00000000..4d4b6236 --- /dev/null +++ b/src/core/path.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Path Path; +typedef struct PathSpec PathSpec; + +#include "unit.h" + +typedef enum PathType { + PATH_EXISTS, + PATH_EXISTS_GLOB, + PATH_DIRECTORY_NOT_EMPTY, + PATH_CHANGED, + PATH_MODIFIED, + _PATH_TYPE_MAX, + _PATH_TYPE_INVALID = -1 +} PathType; + +typedef struct PathSpec { + Unit *unit; + + char *path; + + sd_event_source *event_source; + + LIST_FIELDS(struct PathSpec, spec); + + PathType type; + int inotify_fd; + int primary_wd; + + bool previous_exists; +} PathSpec; + +int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler); +void path_spec_unwatch(PathSpec *s); +int path_spec_fd_event(PathSpec *s, uint32_t events); +void path_spec_done(PathSpec *s); + +static inline bool path_spec_owns_inotify_fd(PathSpec *s, int fd) { + return s->inotify_fd == fd; +} + +typedef enum PathResult { + PATH_SUCCESS, + PATH_FAILURE_RESOURCES, + PATH_FAILURE_START_LIMIT_HIT, + _PATH_RESULT_MAX, + _PATH_RESULT_INVALID = -1 +} PathResult; + +struct Path { + Unit meta; + + LIST_HEAD(PathSpec, specs); + + PathState state, deserialized_state; + + bool inotify_triggered; + + bool make_directory; + mode_t directory_mode; + + PathResult result; +}; + +void path_free_specs(Path *p); + +extern const UnitVTable path_vtable; + +const char* path_type_to_string(PathType i) _const_; +PathType path_type_from_string(const char *s) _pure_; + +const char* path_result_to_string(PathResult i) _const_; +PathResult path_result_from_string(const char *s) _pure_; + +DEFINE_CAST(PATH, Path); diff --git a/src/core/scope.c b/src/core/scope.c new file mode 100644 index 00000000..e8cfedb0 --- /dev/null +++ b/src/core/scope.c @@ -0,0 +1,656 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "dbus-scope.h" +#include "dbus-unit.h" +#include "load-dropin.h" +#include "log.h" +#include "scope.h" +#include "serialize.h" +#include "special.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "unit.h" + +static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = { + [SCOPE_DEAD] = UNIT_INACTIVE, + [SCOPE_RUNNING] = UNIT_ACTIVE, + [SCOPE_ABANDONED] = UNIT_ACTIVE, + [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING, + [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING, + [SCOPE_FAILED] = UNIT_FAILED +}; + +static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); + +static void scope_init(Unit *u) { + Scope *s = SCOPE(u); + + assert(u); + assert(u->load_state == UNIT_STUB); + + s->runtime_max_usec = USEC_INFINITY; + s->timeout_stop_usec = u->manager->default_timeout_stop_usec; + u->ignore_on_isolate = true; +} + +static void scope_done(Unit *u) { + Scope *s = SCOPE(u); + + assert(u); + + s->controller = mfree(s->controller); + s->controller_track = sd_bus_track_unref(s->controller_track); + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); +} + +static int scope_arm_timer(Scope *s, usec_t usec) { + int r; + + assert(s); + + if (s->timer_event_source) { + r = sd_event_source_set_time(s->timer_event_source, usec); + if (r < 0) + return r; + + return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); + } + + if (usec == USEC_INFINITY) + return 0; + + r = sd_event_add_time( + UNIT(s)->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + usec, 0, + scope_dispatch_timer, s); + if (r < 0) + return r; + + (void) sd_event_source_set_description(s->timer_event_source, "scope-timer"); + + return 0; +} + +static void scope_set_state(Scope *s, ScopeState state) { + ScopeState old_state; + assert(s); + + if (s->state != state) + bus_unit_send_pending_change_signal(UNIT(s), false); + + old_state = s->state; + s->state = state; + + if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + + if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED)) { + unit_unwatch_all_pids(UNIT(s)); + unit_dequeue_rewatch_pids(UNIT(s)); + } + + if (state != old_state) + log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state)); + + unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0); +} + +static int scope_add_default_dependencies(Scope *s) { + int r; + + assert(s); + + if (!UNIT(s)->default_dependencies) + return 0; + + /* Make sure scopes are unloaded on shutdown */ + r = unit_add_two_dependencies_by_name( + UNIT(s), + UNIT_BEFORE, UNIT_CONFLICTS, + SPECIAL_SHUTDOWN_TARGET, true, + UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + return 0; +} + +static int scope_verify(Scope *s) { + assert(s); + assert(UNIT(s)->load_state == UNIT_LOADED); + + if (set_isempty(UNIT(s)->pids) && + !MANAGER_IS_RELOADING(UNIT(s)->manager) && + !unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) { + log_unit_error(UNIT(s), "Scope has no PIDs. Refusing."); + return -ENOENT; + } + + return 0; +} + +static int scope_load_init_scope(Unit *u) { + assert(u); + + if (!unit_has_name(u, SPECIAL_INIT_SCOPE)) + return 0; + + u->transient = true; + u->perpetual = true; + + /* init.scope is a bit special, as it has to stick around forever. Because of its special semantics we + * synthesize it here, instead of relying on the unit file on disk. */ + + u->default_dependencies = false; + + /* Prettify things, if we can. */ + if (!u->description) + u->description = strdup("System and Service Manager"); + if (!u->documentation) + (void) strv_extend(&u->documentation, "man:systemd(1)"); + + return 1; +} + +static int scope_add_extras(Scope *s) { + int r; + + r = unit_patch_contexts(UNIT(s)); + if (r < 0) + return r; + + r = unit_set_default_slice(UNIT(s)); + if (r < 0) + return r; + + return scope_add_default_dependencies(s); +} + +static int scope_load(Unit *u) { + Scope *s = SCOPE(u); + int r; + + assert(s); + assert(u->load_state == UNIT_STUB); + + if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) + /* Refuse to load non-transient scope units, but allow them while reloading. */ + return -ENOENT; + + r = scope_load_init_scope(u); + if (r < 0) + return r; + + r = unit_load_fragment_and_dropin(u, false); + if (r < 0) + return r; + + if (u->load_state != UNIT_LOADED) + return 0; + + r = scope_add_extras(s); + if (r < 0) + return r; + + return scope_verify(s); +} + +static usec_t scope_coldplug_timeout(Scope *s) { + assert(s); + + switch (s->deserialized_state) { + + case SCOPE_RUNNING: + return usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec); + + case SCOPE_STOP_SIGKILL: + case SCOPE_STOP_SIGTERM: + return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_stop_usec); + + default: + return USEC_INFINITY; + } +} + +static int scope_coldplug(Unit *u) { + Scope *s = SCOPE(u); + int r; + + assert(s); + assert(s->state == SCOPE_DEAD); + + if (s->deserialized_state == s->state) + return 0; + + r = scope_arm_timer(s, scope_coldplug_timeout(s)); + if (r < 0) + return r; + + if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED)) + (void) unit_enqueue_rewatch_pids(u); + + bus_scope_track_controller(s); + + scope_set_state(s, s->deserialized_state); + return 0; +} + +static void scope_dump(Unit *u, FILE *f, const char *prefix) { + Scope *s = SCOPE(u); + char buf_runtime[FORMAT_TIMESPAN_MAX]; + + assert(s); + assert(f); + + fprintf(f, + "%sScope State: %s\n" + "%sResult: %s\n" + "%sRuntimeMaxSec: %s\n", + prefix, scope_state_to_string(s->state), + prefix, scope_result_to_string(s->result), + prefix, format_timespan(buf_runtime, sizeof(buf_runtime), s->runtime_max_usec, USEC_PER_SEC)); + + cgroup_context_dump(UNIT(s), f, prefix); + kill_context_dump(&s->kill_context, f, prefix); +} + +static void scope_enter_dead(Scope *s, ScopeResult f) { + assert(s); + + if (s->result == SCOPE_SUCCESS) + s->result = f; + + unit_log_result(UNIT(s), s->result == SCOPE_SUCCESS, scope_result_to_string(s->result)); + scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD); +} + +static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) { + bool skip_signal = false; + int r; + + assert(s); + + if (s->result == SCOPE_SUCCESS) + s->result = f; + + /* Before sending any signal, make sure we track all members of this cgroup */ + (void) unit_watch_all_pids(UNIT(s)); + + /* Also, enqueue a job that we recheck all our PIDs a bit later, given that it's likely some processes have + * died now */ + (void) unit_enqueue_rewatch_pids(UNIT(s)); + + /* If we have a controller set let's ask the controller nicely to terminate the scope, instead of us going + * directly into SIGTERM berserk mode */ + if (state == SCOPE_STOP_SIGTERM) + skip_signal = bus_scope_send_request_stop(s) > 0; + + if (skip_signal) + r = 1; /* wait */ + else { + r = unit_kill_context( + UNIT(s), + &s->kill_context, + state != SCOPE_STOP_SIGTERM ? KILL_KILL : + s->was_abandoned ? KILL_TERMINATE_AND_LOG : + KILL_TERMINATE, + -1, -1, false); + if (r < 0) + goto fail; + } + + if (r > 0) { + r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec)); + if (r < 0) + goto fail; + + scope_set_state(s, state); + } else if (state == SCOPE_STOP_SIGTERM) + scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS); + else + scope_enter_dead(s, SCOPE_SUCCESS); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); + + scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); +} + +static int scope_start(Unit *u) { + Scope *s = SCOPE(u); + int r; + + assert(s); + + if (unit_has_name(u, SPECIAL_INIT_SCOPE)) + return -EPERM; + + if (s->state == SCOPE_FAILED) + return -EPERM; + + /* We can't fulfill this right now, please try again later */ + if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) + return -EAGAIN; + + assert(s->state == SCOPE_DEAD); + + if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) + return -ENOENT; + + (void) bus_scope_track_controller(s); + + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + + (void) unit_realize_cgroup(u); + (void) unit_reset_accounting(u); + + unit_export_state_files(u); + + r = unit_attach_pids_to_cgroup(u, u->pids, NULL); + if (r < 0) { + log_unit_warning_errno(u, r, "Failed to add PIDs to scope's control group: %m"); + scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); + return r; + } + + s->result = SCOPE_SUCCESS; + + scope_set_state(s, SCOPE_RUNNING); + + /* Set the maximum runtime timeout. */ + scope_arm_timer(s, usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec)); + + /* Start watching the PIDs currently in the scope */ + (void) unit_enqueue_rewatch_pids(u); + return 1; +} + +static int scope_stop(Unit *u) { + Scope *s = SCOPE(u); + + assert(s); + + if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) + return 0; + + assert(IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED)); + + scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS); + return 1; +} + +static void scope_reset_failed(Unit *u) { + Scope *s = SCOPE(u); + + assert(s); + + if (s->state == SCOPE_FAILED) + scope_set_state(s, SCOPE_DEAD); + + s->result = SCOPE_SUCCESS; +} + +static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { + return unit_kill_common(u, who, signo, -1, -1, error); +} + +static int scope_get_timeout(Unit *u, usec_t *timeout) { + Scope *s = SCOPE(u); + usec_t t; + int r; + + if (!s->timer_event_source) + return 0; + + r = sd_event_source_get_time(s->timer_event_source, &t); + if (r < 0) + return r; + if (t == USEC_INFINITY) + return 0; + + *timeout = t; + return 1; +} + +static int scope_serialize(Unit *u, FILE *f, FDSet *fds) { + Scope *s = SCOPE(u); + + assert(s); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", scope_state_to_string(s->state)); + (void) serialize_bool(f, "was-abandoned", s->was_abandoned); + + if (s->controller) + (void) serialize_item(f, "controller", s->controller); + + return 0; +} + +static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Scope *s = SCOPE(u); + int r; + + assert(u); + assert(key); + assert(value); + assert(fds); + + if (streq(key, "state")) { + ScopeState state; + + state = scope_state_from_string(value); + if (state < 0) + log_unit_debug(u, "Failed to parse state value: %s", value); + else + s->deserialized_state = state; + + } else if (streq(key, "was-abandoned")) { + int k; + + k = parse_boolean(value); + if (k < 0) + log_unit_debug(u, "Failed to parse boolean value: %s", value); + else + s->was_abandoned = k; + } else if (streq(key, "controller")) { + + r = free_and_strdup(&s->controller, value); + if (r < 0) + return log_oom(); + + } else + log_unit_debug(u, "Unknown serialization key: %s", key); + + return 0; +} + +static void scope_notify_cgroup_empty_event(Unit *u) { + Scope *s = SCOPE(u); + assert(u); + + log_unit_debug(u, "cgroup is empty"); + + if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) + scope_enter_dead(s, SCOPE_SUCCESS); +} + +static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) { + assert(u); + + /* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to + * watch, under the assumption that we'll sooner or later get a SIGCHLD for them, as the original + * process we watched was probably the parent of them, and they are hence now our children. */ + + (void) unit_enqueue_rewatch_pids(u); +} + +static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { + Scope *s = SCOPE(userdata); + + assert(s); + assert(s->timer_event_source == source); + + switch (s->state) { + + case SCOPE_RUNNING: + log_unit_warning(UNIT(s), "Scope reached runtime time limit. Stopping."); + scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_FAILURE_TIMEOUT); + break; + + case SCOPE_STOP_SIGTERM: + if (s->kill_context.send_sigkill) { + log_unit_warning(UNIT(s), "Stopping timed out. Killing."); + scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT); + } else { + log_unit_warning(UNIT(s), "Stopping timed out. Skipping SIGKILL."); + scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT); + } + + break; + + case SCOPE_STOP_SIGKILL: + log_unit_warning(UNIT(s), "Still around after SIGKILL. Ignoring."); + scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT); + break; + + default: + assert_not_reached("Timeout at wrong time."); + } + + return 0; +} + +int scope_abandon(Scope *s) { + assert(s); + + if (unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) + return -EPERM; + + if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED)) + return -ESTALE; + + s->was_abandoned = true; + + s->controller = mfree(s->controller); + s->controller_track = sd_bus_track_unref(s->controller_track); + + scope_set_state(s, SCOPE_ABANDONED); + + /* The client is no longer watching the remaining processes, so let's step in here, under the assumption that + * the remaining processes will be sooner or later reassigned to us as parent. */ + (void) unit_enqueue_rewatch_pids(UNIT(s)); + + return 0; +} + +_pure_ static UnitActiveState scope_active_state(Unit *u) { + assert(u); + + return state_translation_table[SCOPE(u)->state]; +} + +_pure_ static const char *scope_sub_state_to_string(Unit *u) { + assert(u); + + return scope_state_to_string(SCOPE(u)->state); +} + +static void scope_enumerate_perpetual(Manager *m) { + Unit *u; + int r; + + assert(m); + + /* Let's unconditionally add the "init.scope" special unit + * that encapsulates PID 1. Note that PID 1 already is in the + * cgroup for this, we hence just need to allocate the object + * for it and that's it. */ + + u = manager_get_unit(m, SPECIAL_INIT_SCOPE); + if (!u) { + r = unit_new_for_name(m, sizeof(Scope), SPECIAL_INIT_SCOPE, &u); + if (r < 0) { + log_error_errno(r, "Failed to allocate the special " SPECIAL_INIT_SCOPE " unit: %m"); + return; + } + } + + u->transient = true; + u->perpetual = true; + SCOPE(u)->deserialized_state = SCOPE_RUNNING; + + unit_add_to_load_queue(u); + unit_add_to_dbus_queue(u); +} + +static const char* const scope_result_table[_SCOPE_RESULT_MAX] = { + [SCOPE_SUCCESS] = "success", + [SCOPE_FAILURE_RESOURCES] = "resources", + [SCOPE_FAILURE_TIMEOUT] = "timeout", +}; + +DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult); + +const UnitVTable scope_vtable = { + .object_size = sizeof(Scope), + .cgroup_context_offset = offsetof(Scope, cgroup_context), + .kill_context_offset = offsetof(Scope, kill_context), + + .sections = + "Unit\0" + "Scope\0" + "Install\0", + .private_section = "Scope", + + .can_transient = true, + .can_delegate = true, + .once_only = true, + + .init = scope_init, + .load = scope_load, + .done = scope_done, + + .coldplug = scope_coldplug, + + .dump = scope_dump, + + .start = scope_start, + .stop = scope_stop, + + .kill = scope_kill, + + .get_timeout = scope_get_timeout, + + .serialize = scope_serialize, + .deserialize_item = scope_deserialize_item, + + .active_state = scope_active_state, + .sub_state_to_string = scope_sub_state_to_string, + + .sigchld_event = scope_sigchld_event, + + .reset_failed = scope_reset_failed, + + .notify_cgroup_empty = scope_notify_cgroup_empty_event, + + .bus_vtable = bus_scope_vtable, + .bus_set_property = bus_scope_set_property, + .bus_commit_properties = bus_scope_commit_properties, + + .enumerate_perpetual = scope_enumerate_perpetual, +}; diff --git a/src/core/scope.h b/src/core/scope.h new file mode 100644 index 00000000..ae2bb80e --- /dev/null +++ b/src/core/scope.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Scope Scope; + +#include "cgroup.h" +#include "kill.h" +#include "unit.h" + +typedef enum ScopeResult { + SCOPE_SUCCESS, + SCOPE_FAILURE_RESOURCES, + SCOPE_FAILURE_TIMEOUT, + _SCOPE_RESULT_MAX, + _SCOPE_RESULT_INVALID = -1 +} ScopeResult; + +struct Scope { + Unit meta; + + CGroupContext cgroup_context; + KillContext kill_context; + + ScopeState state, deserialized_state; + ScopeResult result; + + usec_t runtime_max_usec; + usec_t timeout_stop_usec; + + char *controller; + sd_bus_track *controller_track; + + bool was_abandoned; + + sd_event_source *timer_event_source; +}; + +extern const UnitVTable scope_vtable; + +int scope_abandon(Scope *s); + +const char* scope_result_to_string(ScopeResult i) _const_; +ScopeResult scope_result_from_string(const char *s) _pure_; + +DEFINE_CAST(SCOPE, Scope); diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c new file mode 100644 index 00000000..9fd3099f --- /dev/null +++ b/src/core/selinux-access.c @@ -0,0 +1,276 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "selinux-access.h" + +#if HAVE_SELINUX + +#include +#include +#include +#if HAVE_AUDIT +#include +#endif + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "audit-fd.h" +#include "bus-util.h" +#include "errno-util.h" +#include "format-util.h" +#include "log.h" +#include "path-util.h" +#include "selinux-util.h" +#include "stdio-util.h" +#include "strv.h" +#include "util.h" + +static bool initialized = false; + +struct audit_info { + sd_bus_creds *creds; + const char *path; + const char *cmdline; +}; + +/* + Any time an access gets denied this callback will be called + with the audit data. We then need to just copy the audit data into the msgbuf. +*/ +static int audit_callback( + void *auditdata, + security_class_t cls, + char *msgbuf, + size_t msgbufsize) { + + const struct audit_info *audit = auditdata; + uid_t uid = 0, login_uid = 0; + gid_t gid = 0; + char login_uid_buf[DECIMAL_STR_MAX(uid_t) + 1] = "n/a"; + char uid_buf[DECIMAL_STR_MAX(uid_t) + 1] = "n/a"; + char gid_buf[DECIMAL_STR_MAX(gid_t) + 1] = "n/a"; + + if (sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid) >= 0) + xsprintf(login_uid_buf, UID_FMT, login_uid); + if (sd_bus_creds_get_euid(audit->creds, &uid) >= 0) + xsprintf(uid_buf, UID_FMT, uid); + if (sd_bus_creds_get_egid(audit->creds, &gid) >= 0) + xsprintf(gid_buf, GID_FMT, gid); + + snprintf(msgbuf, msgbufsize, + "auid=%s uid=%s gid=%s%s%s%s%s%s%s", + login_uid_buf, uid_buf, gid_buf, + audit->path ? " path=\"" : "", strempty(audit->path), audit->path ? "\"" : "", + audit->cmdline ? " cmdline=\"" : "", strempty(audit->cmdline), audit->cmdline ? "\"" : ""); + + return 0; +} + +static int callback_type_to_priority(int type) { + switch(type) { + + case SELINUX_ERROR: + return LOG_ERR; + + case SELINUX_WARNING: + return LOG_WARNING; + + case SELINUX_INFO: + return LOG_INFO; + + case SELINUX_AVC: + default: + return LOG_NOTICE; + } +} + +/* + libselinux uses this callback when access gets denied or other + events happen. If audit is turned on, messages will be reported + using audit netlink, otherwise they will be logged using the usual + channels. + + Code copied from dbus and modified. +*/ +_printf_(2, 3) static int log_callback(int type, const char *fmt, ...) { + va_list ap; + const char *fmt2; + +#if HAVE_AUDIT + int fd; + + fd = get_audit_fd(); + + if (fd >= 0) { + _cleanup_free_ char *buf = NULL; + int r; + + va_start(ap, fmt); + r = vasprintf(&buf, fmt, ap); + va_end(ap); + + if (r >= 0) { + if (type == SELINUX_AVC) + audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0); + else if (type == SELINUX_ERROR) + audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_SELINUX_ERR, buf, NULL, NULL, NULL, 0); + + return 0; + } + } +#endif + + fmt2 = strjoina("selinux: ", fmt); + + va_start(ap, fmt); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + log_internalv(LOG_AUTH | callback_type_to_priority(type), + 0, PROJECT_FILE, __LINE__, __FUNCTION__, + fmt2, ap); +#pragma GCC diagnostic pop + va_end(ap); + + return 0; +} + +static int access_init(sd_bus_error *error) { + + if (!mac_selinux_use()) + return 0; + + if (initialized) + return 1; + + if (avc_open(NULL, 0) != 0) { + int enforce, saved_errno = errno; + + enforce = security_getenforce(); + log_full_errno(enforce != 0 ? LOG_ERR : LOG_WARNING, saved_errno, "Failed to open the SELinux AVC: %m"); + + /* If enforcement isn't on, then let's suppress this + * error, and just don't do any AVC checks. The + * warning we printed is hence all the admin will + * see. */ + if (enforce == 0) + return 0; + + /* Return an access denied error, if we couldn't load + * the AVC but enforcing mode was on, or we couldn't + * determine whether it is one. */ + return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to open the SELinux AVC: %s", strerror_safe(saved_errno)); + } + + selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback); + selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback); + + initialized = true; + return 1; +} + +/* + This function communicates with the kernel to check whether or not it should + allow the access. + If the machine is in permissive mode it will return ok. Audit messages will + still be generated if the access would be denied in enforcing mode. +*/ +int mac_selinux_generic_access_check( + sd_bus_message *message, + const char *path, + const char *permission, + sd_bus_error *error) { + + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + const char *tclass = NULL, *scon = NULL; + struct audit_info audit_info = {}; + _cleanup_free_ char *cl = NULL; + char *fcon = NULL; + char **cmdline = NULL; + int r = 0; + + assert(message); + assert(permission); + assert(error); + + r = access_init(error); + if (r <= 0) + return r; + + r = sd_bus_query_sender_creds( + message, + SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID| + SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_AUDIT_LOGIN_UID| + SD_BUS_CREDS_SELINUX_CONTEXT| + SD_BUS_CREDS_AUGMENT /* get more bits from /proc */, + &creds); + if (r < 0) + goto finish; + + /* The SELinux context is something we really should have + * gotten directly from the message or sender, and not be an + * augmented field. If it was augmented we cannot use it for + * authorization, since this is racy and vulnerable. Let's add + * an extra check, just in case, even though this really + * shouldn't be possible. */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_SELINUX_CONTEXT) == 0, -EPERM); + + r = sd_bus_creds_get_selinux_context(creds, &scon); + if (r < 0) + goto finish; + + if (path) { + /* Get the file context of the unit file */ + + r = getfilecon_raw(path, &fcon); + if (r < 0) { + r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path); + goto finish; + } + + tclass = "service"; + } else { + r = getcon_raw(&fcon); + if (r < 0) { + r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context."); + goto finish; + } + + tclass = "system"; + } + + sd_bus_creds_get_cmdline(creds, &cmdline); + cl = strv_join(cmdline, " "); + + audit_info.creds = creds; + audit_info.path = path; + audit_info.cmdline = cl; + + r = selinux_check_access(scon, fcon, tclass, permission, &audit_info); + if (r < 0) + r = sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access."); + + log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, cl, r); + +finish: + freecon(fcon); + + if (r < 0 && security_getenforce() != 1) { + sd_bus_error_free(error); + r = 0; + } + + return r; +} + +#else + +int mac_selinux_generic_access_check( + sd_bus_message *message, + const char *path, + const char *permission, + sd_bus_error *error) { + + return 0; +} + +#endif diff --git a/src/core/selinux-access.h b/src/core/selinux-access.h new file mode 100644 index 00000000..1e75930f --- /dev/null +++ b/src/core/selinux-access.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "bus-util.h" +#include "manager.h" + +int mac_selinux_generic_access_check(sd_bus_message *message, const char *path, const char *permission, sd_bus_error *error); + +#if HAVE_SELINUX + +#define mac_selinux_access_check(message, permission, error) \ + mac_selinux_generic_access_check((message), NULL, (permission), (error)) + +#define mac_selinux_unit_access_check(unit, message, permission, error) \ + mac_selinux_generic_access_check((message), unit_label_path(unit), (permission), (error)) + +#else + +#define mac_selinux_access_check(message, permission, error) 0 +#define mac_selinux_unit_access_check(unit, message, permission, error) 0 + +#endif diff --git a/src/core/selinux-setup.c b/src/core/selinux-setup.c new file mode 100644 index 00000000..b8a94a52 --- /dev/null +++ b/src/core/selinux-setup.c @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#if HAVE_SELINUX +#include +#endif + +#include "log.h" +#include "macro.h" +#include "selinux-setup.h" +#include "selinux-util.h" +#include "string-util.h" +#include "time-util.h" +#include "util.h" + +#if HAVE_SELINUX +_printf_(2,3) +static int null_log(int type, const char *fmt, ...) { + return 0; +} +#endif + +int mac_selinux_setup(bool *loaded_policy) { + +#if HAVE_SELINUX + int enforce = 0; + usec_t before_load, after_load; + char *con; + int r; + static const union selinux_callback cb = { + .func_log = null_log, + }; + + bool initialized = false; + + assert(loaded_policy); + + /* Turn off all of SELinux' own logging, we want to do that */ + selinux_set_callback(SELINUX_CB_LOG, cb); + + /* Don't load policy in the initrd if we don't appear to have + * it. For the real root, we check below if we've already + * loaded policy, and return gracefully. + */ + if (in_initrd() && access(selinux_path(), F_OK) < 0) + return 0; + + /* Already initialized by somebody else? */ + r = getcon_raw(&con); + if (r == 0) { + initialized = !streq(con, "kernel"); + freecon(con); + } + + /* Make sure we have no fds open while loading the policy and + * transitioning */ + log_close(); + + /* Now load the policy */ + before_load = now(CLOCK_MONOTONIC); + r = selinux_init_load_policy(&enforce); + if (r == 0) { + _cleanup_(mac_selinux_freep) char *label = NULL; + char timespan[FORMAT_TIMESPAN_MAX]; + + mac_selinux_retest(); + + /* Transition to the new context */ + r = mac_selinux_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label); + if (r < 0 || !label) { + log_open(); + log_error("Failed to compute init label, ignoring."); + } else { + r = setcon_raw(label); + + log_open(); + if (r < 0) + log_error("Failed to transition into init label '%s', ignoring.", label); + } + + after_load = now(CLOCK_MONOTONIC); + + log_info("Successfully loaded SELinux policy in %s.", + format_timespan(timespan, sizeof(timespan), after_load - before_load, 0)); + + *loaded_policy = true; + + } else { + log_open(); + + if (enforce > 0) { + if (!initialized) { + log_emergency("Failed to load SELinux policy."); + return -EIO; + } + + log_warning("Failed to load new SELinux policy. Continuing with old policy."); + } else + log_debug("Unable to load SELinux policy. Ignoring."); + } +#endif + + return 0; +} diff --git a/src/core/selinux-setup.h b/src/core/selinux-setup.h new file mode 100644 index 00000000..ad0d4f65 --- /dev/null +++ b/src/core/selinux-setup.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int mac_selinux_setup(bool *loaded_policy); diff --git a/src/core/service.c b/src/core/service.c new file mode 100644 index 00000000..f3df541f --- /dev/null +++ b/src/core/service.c @@ -0,0 +1,4473 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "async.h" +#include "bus-error.h" +#include "bus-kernel.h" +#include "bus-util.h" +#include "dbus-service.h" +#include "dbus-unit.h" +#include "def.h" +#include "env-util.h" +#include "escape.h" +#include "exit-status.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "load-dropin.h" +#include "load-fragment.h" +#include "log.h" +#include "manager.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "serialize.h" +#include "service.h" +#include "signal-util.h" +#include "special.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "unit.h" +#include "utf8.h" +#include "util.h" + +static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = { + [SERVICE_DEAD] = UNIT_INACTIVE, + [SERVICE_CONDITION] = UNIT_ACTIVATING, + [SERVICE_START_PRE] = UNIT_ACTIVATING, + [SERVICE_START] = UNIT_ACTIVATING, + [SERVICE_START_POST] = UNIT_ACTIVATING, + [SERVICE_RUNNING] = UNIT_ACTIVE, + [SERVICE_EXITED] = UNIT_ACTIVE, + [SERVICE_RELOAD] = UNIT_RELOADING, + [SERVICE_STOP] = UNIT_DEACTIVATING, + [SERVICE_STOP_WATCHDOG] = UNIT_DEACTIVATING, + [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING, + [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING, + [SERVICE_STOP_POST] = UNIT_DEACTIVATING, + [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING, + [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING, + [SERVICE_FAILED] = UNIT_FAILED, + [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING, + [SERVICE_CLEANING] = UNIT_MAINTENANCE, +}; + +/* For Type=idle we never want to delay any other jobs, hence we + * consider idle jobs active as soon as we start working on them */ +static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] = { + [SERVICE_DEAD] = UNIT_INACTIVE, + [SERVICE_CONDITION] = UNIT_ACTIVE, + [SERVICE_START_PRE] = UNIT_ACTIVE, + [SERVICE_START] = UNIT_ACTIVE, + [SERVICE_START_POST] = UNIT_ACTIVE, + [SERVICE_RUNNING] = UNIT_ACTIVE, + [SERVICE_EXITED] = UNIT_ACTIVE, + [SERVICE_RELOAD] = UNIT_RELOADING, + [SERVICE_STOP] = UNIT_DEACTIVATING, + [SERVICE_STOP_WATCHDOG] = UNIT_DEACTIVATING, + [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING, + [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING, + [SERVICE_STOP_POST] = UNIT_DEACTIVATING, + [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING, + [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING, + [SERVICE_FAILED] = UNIT_FAILED, + [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING, + [SERVICE_CLEANING] = UNIT_MAINTENANCE, +}; + +static int service_dispatch_inotify_io(sd_event_source *source, int fd, uint32_t events, void *userdata); +static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); +static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata); +static int service_dispatch_exec_io(sd_event_source *source, int fd, uint32_t events, void *userdata); + +static void service_enter_signal(Service *s, ServiceState state, ServiceResult f); +static void service_enter_reload_by_notify(Service *s); + +static void service_init(Unit *u) { + Service *s = SERVICE(u); + + assert(u); + assert(u->load_state == UNIT_STUB); + + s->timeout_start_usec = u->manager->default_timeout_start_usec; + s->timeout_stop_usec = u->manager->default_timeout_stop_usec; + s->timeout_abort_usec = u->manager->default_timeout_abort_usec; + s->timeout_abort_set = u->manager->default_timeout_abort_set; + s->restart_usec = u->manager->default_restart_usec; + s->runtime_max_usec = USEC_INFINITY; + s->type = _SERVICE_TYPE_INVALID; + s->socket_fd = -1; + s->stdin_fd = s->stdout_fd = s->stderr_fd = -1; + s->guess_main_pid = true; + + s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; + + s->exec_context.keyring_mode = MANAGER_IS_SYSTEM(u->manager) ? + EXEC_KEYRING_PRIVATE : EXEC_KEYRING_INHERIT; + + s->watchdog_original_usec = USEC_INFINITY; + + s->oom_policy = _OOM_POLICY_INVALID; +} + +static void service_unwatch_control_pid(Service *s) { + assert(s); + + if (s->control_pid <= 0) + return; + + unit_unwatch_pid(UNIT(s), s->control_pid); + s->control_pid = 0; +} + +static void service_unwatch_main_pid(Service *s) { + assert(s); + + if (s->main_pid <= 0) + return; + + unit_unwatch_pid(UNIT(s), s->main_pid); + s->main_pid = 0; +} + +static void service_unwatch_pid_file(Service *s) { + if (!s->pid_file_pathspec) + return; + + log_unit_debug(UNIT(s), "Stopping watch for PID file %s", s->pid_file_pathspec->path); + path_spec_unwatch(s->pid_file_pathspec); + path_spec_done(s->pid_file_pathspec); + s->pid_file_pathspec = mfree(s->pid_file_pathspec); +} + +static int service_set_main_pid(Service *s, pid_t pid) { + assert(s); + + if (pid <= 1) + return -EINVAL; + + if (pid == getpid_cached()) + return -EINVAL; + + if (s->main_pid == pid && s->main_pid_known) + return 0; + + if (s->main_pid != pid) { + service_unwatch_main_pid(s); + exec_status_start(&s->main_exec_status, pid); + } + + s->main_pid = pid; + s->main_pid_known = true; + s->main_pid_alien = pid_is_my_child(pid) == 0; + + if (s->main_pid_alien) + log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", pid); + + return 0; +} + +void service_close_socket_fd(Service *s) { + assert(s); + + /* Undo the effect of service_set_socket_fd(). */ + + s->socket_fd = asynchronous_close(s->socket_fd); + + if (UNIT_ISSET(s->accept_socket)) { + socket_connection_unref(SOCKET(UNIT_DEREF(s->accept_socket))); + unit_ref_unset(&s->accept_socket); + } +} + +static void service_stop_watchdog(Service *s) { + assert(s); + + s->watchdog_event_source = sd_event_source_unref(s->watchdog_event_source); + s->watchdog_timestamp = DUAL_TIMESTAMP_NULL; +} + +static usec_t service_get_watchdog_usec(Service *s) { + assert(s); + + if (s->watchdog_override_enable) + return s->watchdog_override_usec; + + return s->watchdog_original_usec; +} + +static void service_start_watchdog(Service *s) { + usec_t watchdog_usec; + int r; + + assert(s); + + watchdog_usec = service_get_watchdog_usec(s); + if (IN_SET(watchdog_usec, 0, USEC_INFINITY)) { + service_stop_watchdog(s); + return; + } + + if (s->watchdog_event_source) { + r = sd_event_source_set_time(s->watchdog_event_source, usec_add(s->watchdog_timestamp.monotonic, watchdog_usec)); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to reset watchdog timer: %m"); + return; + } + + r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ONESHOT); + } else { + r = sd_event_add_time( + UNIT(s)->manager->event, + &s->watchdog_event_source, + CLOCK_MONOTONIC, + usec_add(s->watchdog_timestamp.monotonic, watchdog_usec), 0, + service_dispatch_watchdog, s); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to add watchdog timer: %m"); + return; + } + + (void) sd_event_source_set_description(s->watchdog_event_source, "service-watchdog"); + + /* Let's process everything else which might be a sign + * of living before we consider a service died. */ + r = sd_event_source_set_priority(s->watchdog_event_source, SD_EVENT_PRIORITY_IDLE); + } + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "Failed to install watchdog timer: %m"); +} + +static void service_extend_event_source_timeout(Service *s, sd_event_source *source, usec_t extended) { + usec_t current; + int r; + + assert(s); + + /* Extends the specified event source timer to at least the specified time, unless it is already later + * anyway. */ + + if (!source) + return; + + r = sd_event_source_get_time(source, ¤t); + if (r < 0) { + const char *desc; + (void) sd_event_source_get_description(s->timer_event_source, &desc); + log_unit_warning_errno(UNIT(s), r, "Failed to retrieve timeout time for event source '%s', ignoring: %m", strna(desc)); + return; + } + + if (current >= extended) /* Current timeout is already longer, ignore this. */ + return; + + r = sd_event_source_set_time(source, extended); + if (r < 0) { + const char *desc; + (void) sd_event_source_get_description(s->timer_event_source, &desc); + log_unit_warning_errno(UNIT(s), r, "Failed to set timeout time for even source '%s', ignoring %m", strna(desc)); + } +} + +static void service_extend_timeout(Service *s, usec_t extend_timeout_usec) { + usec_t extended; + + assert(s); + + if (IN_SET(extend_timeout_usec, 0, USEC_INFINITY)) + return; + + extended = usec_add(now(CLOCK_MONOTONIC), extend_timeout_usec); + + service_extend_event_source_timeout(s, s->timer_event_source, extended); + service_extend_event_source_timeout(s, s->watchdog_event_source, extended); +} + +static void service_reset_watchdog(Service *s) { + assert(s); + + dual_timestamp_get(&s->watchdog_timestamp); + service_start_watchdog(s); +} + +static void service_override_watchdog_timeout(Service *s, usec_t watchdog_override_usec) { + assert(s); + + s->watchdog_override_enable = true; + s->watchdog_override_usec = watchdog_override_usec; + service_reset_watchdog(s); + + log_unit_debug(UNIT(s), "watchdog_usec="USEC_FMT, s->watchdog_usec); + log_unit_debug(UNIT(s), "watchdog_override_usec="USEC_FMT, s->watchdog_override_usec); +} + +static void service_fd_store_unlink(ServiceFDStore *fs) { + + if (!fs) + return; + + if (fs->service) { + assert(fs->service->n_fd_store > 0); + LIST_REMOVE(fd_store, fs->service->fd_store, fs); + fs->service->n_fd_store--; + } + + sd_event_source_disable_unref(fs->event_source); + + free(fs->fdname); + safe_close(fs->fd); + free(fs); +} + +static void service_release_fd_store(Service *s) { + assert(s); + + if (s->n_keep_fd_store > 0) + return; + + log_unit_debug(UNIT(s), "Releasing all stored fds"); + while (s->fd_store) + service_fd_store_unlink(s->fd_store); + + assert(s->n_fd_store == 0); +} + +static void service_release_resources(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + if (!s->fd_store && s->stdin_fd < 0 && s->stdout_fd < 0 && s->stderr_fd < 0) + return; + + log_unit_debug(u, "Releasing resources."); + + s->stdin_fd = safe_close(s->stdin_fd); + s->stdout_fd = safe_close(s->stdout_fd); + s->stderr_fd = safe_close(s->stderr_fd); + + service_release_fd_store(s); +} + +static void service_done(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + s->pid_file = mfree(s->pid_file); + s->status_text = mfree(s->status_text); + + s->exec_runtime = exec_runtime_unref(s->exec_runtime, false); + exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX); + s->control_command = NULL; + s->main_command = NULL; + + dynamic_creds_unref(&s->dynamic_creds); + + exit_status_set_free(&s->restart_prevent_status); + exit_status_set_free(&s->restart_force_status); + exit_status_set_free(&s->success_status); + + /* This will leak a process, but at least no memory or any of + * our resources */ + service_unwatch_main_pid(s); + service_unwatch_control_pid(s); + service_unwatch_pid_file(s); + + if (s->bus_name) { + unit_unwatch_bus_name(u, s->bus_name); + s->bus_name = mfree(s->bus_name); + } + + s->bus_name_owner = mfree(s->bus_name_owner); + + s->usb_function_descriptors = mfree(s->usb_function_descriptors); + s->usb_function_strings = mfree(s->usb_function_strings); + + service_close_socket_fd(s); + s->peer = socket_peer_unref(s->peer); + + unit_ref_unset(&s->accept_socket); + + service_stop_watchdog(s); + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + s->exec_fd_event_source = sd_event_source_unref(s->exec_fd_event_source); + + service_release_resources(u); +} + +static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) { + ServiceFDStore *fs = userdata; + + assert(e); + assert(fs); + + /* If we get either EPOLLHUP or EPOLLERR, it's time to remove this entry from the fd store */ + log_unit_debug(UNIT(fs->service), + "Received %s on stored fd %d (%s), closing.", + revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP", + fs->fd, strna(fs->fdname)); + service_fd_store_unlink(fs); + return 0; +} + +static int service_add_fd_store(Service *s, int fd, const char *name) { + ServiceFDStore *fs; + int r; + + /* fd is always consumed if we return >= 0 */ + + assert(s); + assert(fd >= 0); + + if (s->n_fd_store >= s->n_fd_store_max) + return -EXFULL; /* Our store is full. + * Use this errno rather than E[NM]FILE to distinguish from + * the case where systemd itself hits the file limit. */ + + LIST_FOREACH(fd_store, fs, s->fd_store) { + r = same_fd(fs->fd, fd); + if (r < 0) + return r; + if (r > 0) { + safe_close(fd); + return 0; /* fd already included */ + } + } + + fs = new0(ServiceFDStore, 1); + if (!fs) + return -ENOMEM; + + fs->fd = fd; + fs->service = s; + fs->fdname = strdup(name ?: "stored"); + if (!fs->fdname) { + free(fs); + return -ENOMEM; + } + + r = sd_event_add_io(UNIT(s)->manager->event, &fs->event_source, fd, 0, on_fd_store_io, fs); + if (r < 0 && r != -EPERM) { /* EPERM indicates fds that aren't pollable, which is OK */ + free(fs->fdname); + free(fs); + return r; + } else if (r >= 0) + (void) sd_event_source_set_description(fs->event_source, "service-fd-store"); + + LIST_PREPEND(fd_store, s->fd_store, fs); + s->n_fd_store++; + + return 1; /* fd newly stored */ +} + +static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { + int r; + + assert(s); + + while (fdset_size(fds) > 0) { + _cleanup_close_ int fd = -1; + + fd = fdset_steal_first(fds); + if (fd < 0) + break; + + r = service_add_fd_store(s, fd, name); + if (r == -EXFULL) + return log_unit_warning_errno(UNIT(s), r, + "Cannot store more fds than FileDescriptorStoreMax=%u, closing remaining.", + s->n_fd_store_max); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to add fd to store: %m"); + if (r > 0) + log_unit_debug(UNIT(s), "Added fd %u (%s) to fd store.", fd, strna(name)); + fd = -1; + } + + return 0; +} + +static void service_remove_fd_store(Service *s, const char *name) { + ServiceFDStore *fs, *n; + + assert(s); + assert(name); + + LIST_FOREACH_SAFE(fd_store, fs, n, s->fd_store) { + if (!streq(fs->fdname, name)) + continue; + + log_unit_debug(UNIT(s), "Got explicit request to remove fd %i (%s), closing.", fs->fd, name); + service_fd_store_unlink(fs); + } +} + +static int service_arm_timer(Service *s, usec_t usec) { + int r; + + assert(s); + + if (s->timer_event_source) { + r = sd_event_source_set_time(s->timer_event_source, usec); + if (r < 0) + return r; + + return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); + } + + if (usec == USEC_INFINITY) + return 0; + + r = sd_event_add_time( + UNIT(s)->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + usec, 0, + service_dispatch_timer, s); + if (r < 0) + return r; + + (void) sd_event_source_set_description(s->timer_event_source, "service-timer"); + + return 0; +} + +static int service_verify(Service *s) { + assert(s); + assert(UNIT(s)->load_state == UNIT_LOADED); + + if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP] + && UNIT(s)->success_action == EMERGENCY_ACTION_NONE) { + /* FailureAction= only makes sense if one of the start or stop commands is specified. + * SuccessAction= will be executed unconditionally if no commands are specified. Hence, + * either a command or SuccessAction= are required. */ + + log_unit_error(UNIT(s), "Service has no ExecStart=, ExecStop=, or SuccessAction=. Refusing."); + return -ENOEXEC; + } + + if (s->type != SERVICE_ONESHOT && !s->exec_command[SERVICE_EXEC_START]) { + log_unit_error(UNIT(s), "Service has no ExecStart= setting, which is only allowed for Type=oneshot services. Refusing."); + return -ENOEXEC; + } + + if (!s->remain_after_exit && !s->exec_command[SERVICE_EXEC_START] && UNIT(s)->success_action == EMERGENCY_ACTION_NONE) { + log_unit_error(UNIT(s), "Service has no ExecStart= and no SuccessAction= settings and does not have RemainAfterExit=yes set. Refusing."); + return -ENOEXEC; + } + + if (s->type != SERVICE_ONESHOT && s->exec_command[SERVICE_EXEC_START]->command_next) { + log_unit_error(UNIT(s), "Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing."); + return -ENOEXEC; + } + + if (s->type == SERVICE_ONESHOT + && !IN_SET(s->restart, SERVICE_RESTART_NO, SERVICE_RESTART_ON_FAILURE, SERVICE_RESTART_ON_ABNORMAL, SERVICE_RESTART_ON_WATCHDOG, SERVICE_RESTART_ON_ABORT)) { + log_unit_error(UNIT(s), "Service has Restart= set to either always or on-success, which isn't allowed for Type=oneshot services. Refusing."); + return -ENOEXEC; + } + + if (s->type == SERVICE_ONESHOT && !exit_status_set_is_empty(&s->restart_force_status)) { + log_unit_error(UNIT(s), "Service has RestartForceStatus= set, which isn't allowed for Type=oneshot services. Refusing."); + return -ENOEXEC; + } + + if (s->type == SERVICE_DBUS && !s->bus_name) { + log_unit_error(UNIT(s), "Service is of type D-Bus but no D-Bus service name has been specified. Refusing."); + return -ENOEXEC; + } + + if (s->bus_name && s->type != SERVICE_DBUS) + log_unit_warning(UNIT(s), "Service has a D-Bus service name specified, but is not of type dbus. Ignoring."); + + if (s->exec_context.pam_name && !IN_SET(s->kill_context.kill_mode, KILL_CONTROL_GROUP, KILL_MIXED)) { + log_unit_error(UNIT(s), "Service has PAM enabled. Kill mode must be set to 'control-group' or 'mixed'. Refusing."); + return -ENOEXEC; + } + + if (s->usb_function_descriptors && !s->usb_function_strings) + log_unit_warning(UNIT(s), "Service has USBFunctionDescriptors= setting, but no USBFunctionStrings=. Ignoring."); + + if (!s->usb_function_descriptors && s->usb_function_strings) + log_unit_warning(UNIT(s), "Service has USBFunctionStrings= setting, but no USBFunctionDescriptors=. Ignoring."); + + if (s->runtime_max_usec != USEC_INFINITY && s->type == SERVICE_ONESHOT) + log_unit_warning(UNIT(s), "RuntimeMaxSec= has no effect in combination with Type=oneshot. Ignoring."); + + return 0; +} + +static int service_add_default_dependencies(Service *s) { + int r; + + assert(s); + + if (!UNIT(s)->default_dependencies) + return 0; + + /* Add a number of automatic dependencies useful for the + * majority of services. */ + + if (MANAGER_IS_SYSTEM(UNIT(s)->manager)) { + /* First, pull in the really early boot stuff, and + * require it, so that we fail if we can't acquire + * it. */ + + r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + } else { + + /* In the --user instance there's no sysinit.target, + * in that case require basic.target instead. */ + + r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_BASIC_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + } + + /* Second, if the rest of the base system is in the same + * transaction, order us after it, but do not pull it in or + * even require it. */ + r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_BASIC_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + /* Third, add us in for normal shutdown. */ + return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT); +} + +static void service_fix_stdio(Service *s) { + assert(s); + + /* Note that EXEC_INPUT_NULL and EXEC_OUTPUT_INHERIT play a special role here: they are both the + * default value that is subject to automatic overriding triggered by other settings and an explicit + * choice the user can make. We don't distuingish between these cases currently. */ + + if (s->exec_context.std_input == EXEC_INPUT_NULL && + s->exec_context.stdin_data_size > 0) + s->exec_context.std_input = EXEC_INPUT_DATA; + + if (IN_SET(s->exec_context.std_input, + EXEC_INPUT_TTY, + EXEC_INPUT_TTY_FORCE, + EXEC_INPUT_TTY_FAIL, + EXEC_INPUT_SOCKET, + EXEC_INPUT_NAMED_FD)) + return; + + /* We assume these listed inputs refer to bidirectional streams, and hence duplicating them from + * stdin to stdout/stderr makes sense and hence leaving EXEC_OUTPUT_INHERIT in place makes sense, + * too. Outputs such as regular files or sealed data memfds otoh don't really make sense to be + * duplicated for both input and output at the same time (since they then would cause a feedback + * loop), hence override EXEC_OUTPUT_INHERIT with the default stderr/stdout setting. */ + + if (s->exec_context.std_error == EXEC_OUTPUT_INHERIT && + s->exec_context.std_output == EXEC_OUTPUT_INHERIT) + s->exec_context.std_error = UNIT(s)->manager->default_std_error; + + if (s->exec_context.std_output == EXEC_OUTPUT_INHERIT) + s->exec_context.std_output = UNIT(s)->manager->default_std_output; +} + +static int service_setup_bus_name(Service *s) { + int r; + + assert(s); + + if (!s->bus_name) + return 0; + + r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, true, UNIT_DEPENDENCY_FILE); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m"); + + /* We always want to be ordered against dbus.socket if both are in the transaction. */ + r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_DBUS_SOCKET, true, UNIT_DEPENDENCY_FILE); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m"); + + r = unit_watch_bus_name(UNIT(s), s->bus_name); + if (r == -EEXIST) + return log_unit_error_errno(UNIT(s), r, "Two services allocated for the same bus name %s, refusing operation.", s->bus_name); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Cannot watch bus name %s: %m", s->bus_name); + + return 0; +} + +static int service_add_extras(Service *s) { + int r; + + assert(s); + + if (s->type == _SERVICE_TYPE_INVALID) { + /* Figure out a type automatically */ + if (s->bus_name) + s->type = SERVICE_DBUS; + else if (s->exec_command[SERVICE_EXEC_START]) + s->type = SERVICE_SIMPLE; + else + s->type = SERVICE_ONESHOT; + } + + /* Oneshot services have disabled start timeout by default */ + if (s->type == SERVICE_ONESHOT && !s->start_timeout_defined) + s->timeout_start_usec = USEC_INFINITY; + + service_fix_stdio(s); + + r = unit_patch_contexts(UNIT(s)); + if (r < 0) + return r; + + r = unit_add_exec_dependencies(UNIT(s), &s->exec_context); + if (r < 0) + return r; + + r = unit_set_default_slice(UNIT(s)); + if (r < 0) + return r; + + /* If the service needs the notify socket, let's enable it automatically. */ + if (s->notify_access == NOTIFY_NONE && + (s->type == SERVICE_NOTIFY || s->watchdog_usec > 0 || s->n_fd_store_max > 0)) + s->notify_access = NOTIFY_MAIN; + + /* If no OOM policy was explicitly set, then default to the configure default OOM policy. Except when + * delegation is on, in that case it we assume the payload knows better what to do and can process + * things in a more focused way. */ + if (s->oom_policy < 0) + s->oom_policy = s->cgroup_context.delegate ? OOM_CONTINUE : UNIT(s)->manager->default_oom_policy; + + /* Let the kernel do the killing if that's requested. */ + s->cgroup_context.memory_oom_group = s->oom_policy == OOM_KILL; + + r = service_add_default_dependencies(s); + if (r < 0) + return r; + + r = service_setup_bus_name(s); + if (r < 0) + return r; + + return 0; +} + +static int service_load(Unit *u) { + Service *s = SERVICE(u); + int r; + + r = unit_load_fragment_and_dropin(u, true); + if (r < 0) + return r; + + if (u->load_state != UNIT_LOADED) + return 0; + + /* This is a new unit? Then let's add in some extras */ + r = service_add_extras(s); + if (r < 0) + return r; + + return service_verify(s); +} + +static void service_dump(Unit *u, FILE *f, const char *prefix) { + char buf_restart[FORMAT_TIMESPAN_MAX], buf_start[FORMAT_TIMESPAN_MAX], buf_stop[FORMAT_TIMESPAN_MAX], + buf_runtime[FORMAT_TIMESPAN_MAX], buf_watchdog[FORMAT_TIMESPAN_MAX], buf_abort[FORMAT_TIMESPAN_MAX]; + ServiceExecCommand c; + Service *s = SERVICE(u); + const char *prefix2; + + assert(s); + + prefix = strempty(prefix); + prefix2 = strjoina(prefix, "\t"); + + fprintf(f, + "%sService State: %s\n" + "%sResult: %s\n" + "%sReload Result: %s\n" + "%sClean Result: %s\n" + "%sPermissionsStartOnly: %s\n" + "%sRootDirectoryStartOnly: %s\n" + "%sRemainAfterExit: %s\n" + "%sGuessMainPID: %s\n" + "%sType: %s\n" + "%sRestart: %s\n" + "%sNotifyAccess: %s\n" + "%sNotifyState: %s\n" + "%sOOMPolicy: %s\n", + prefix, service_state_to_string(s->state), + prefix, service_result_to_string(s->result), + prefix, service_result_to_string(s->reload_result), + prefix, service_result_to_string(s->clean_result), + prefix, yes_no(s->permissions_start_only), + prefix, yes_no(s->root_directory_start_only), + prefix, yes_no(s->remain_after_exit), + prefix, yes_no(s->guess_main_pid), + prefix, service_type_to_string(s->type), + prefix, service_restart_to_string(s->restart), + prefix, notify_access_to_string(s->notify_access), + prefix, notify_state_to_string(s->notify_state), + prefix, oom_policy_to_string(s->oom_policy)); + + if (s->control_pid > 0) + fprintf(f, + "%sControl PID: "PID_FMT"\n", + prefix, s->control_pid); + + if (s->main_pid > 0) + fprintf(f, + "%sMain PID: "PID_FMT"\n" + "%sMain PID Known: %s\n" + "%sMain PID Alien: %s\n", + prefix, s->main_pid, + prefix, yes_no(s->main_pid_known), + prefix, yes_no(s->main_pid_alien)); + + if (s->pid_file) + fprintf(f, + "%sPIDFile: %s\n", + prefix, s->pid_file); + + if (s->bus_name) + fprintf(f, + "%sBusName: %s\n" + "%sBus Name Good: %s\n", + prefix, s->bus_name, + prefix, yes_no(s->bus_name_good)); + + if (UNIT_ISSET(s->accept_socket)) + fprintf(f, + "%sAccept Socket: %s\n", + prefix, UNIT_DEREF(s->accept_socket)->id); + + fprintf(f, + "%sRestartSec: %s\n" + "%sTimeoutStartSec: %s\n" + "%sTimeoutStopSec: %s\n", + prefix, format_timespan(buf_restart, sizeof(buf_restart), s->restart_usec, USEC_PER_SEC), + prefix, format_timespan(buf_start, sizeof(buf_start), s->timeout_start_usec, USEC_PER_SEC), + prefix, format_timespan(buf_stop, sizeof(buf_stop), s->timeout_stop_usec, USEC_PER_SEC)); + + if (s->timeout_abort_set) + fprintf(f, + "%sTimeoutAbortSec: %s\n", + prefix, format_timespan(buf_abort, sizeof(buf_abort), s->timeout_abort_usec, USEC_PER_SEC)); + + fprintf(f, + "%sRuntimeMaxSec: %s\n" + "%sWatchdogSec: %s\n", + prefix, format_timespan(buf_runtime, sizeof(buf_runtime), s->runtime_max_usec, USEC_PER_SEC), + prefix, format_timespan(buf_watchdog, sizeof(buf_watchdog), s->watchdog_usec, USEC_PER_SEC)); + + kill_context_dump(&s->kill_context, f, prefix); + exec_context_dump(&s->exec_context, f, prefix); + + for (c = 0; c < _SERVICE_EXEC_COMMAND_MAX; c++) { + + if (!s->exec_command[c]) + continue; + + fprintf(f, "%s-> %s:\n", + prefix, service_exec_command_to_string(c)); + + exec_command_dump_list(s->exec_command[c], f, prefix2); + } + + if (s->status_text) + fprintf(f, "%sStatus Text: %s\n", + prefix, s->status_text); + + if (s->n_fd_store_max > 0) + fprintf(f, + "%sFile Descriptor Store Max: %u\n" + "%sFile Descriptor Store Current: %zu\n", + prefix, s->n_fd_store_max, + prefix, s->n_fd_store); + + cgroup_context_dump(UNIT(s), f, prefix); +} + +static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) { + Unit *owner; + + assert(s); + assert(pid_is_valid(pid)); + + /* Checks whether the specified PID is suitable as main PID for this service. returns negative if not, 0 if the + * PID is questionnable but should be accepted if the source of configuration is trusted. > 0 if the PID is + * good */ + + if (pid == getpid_cached() || pid == 1) { + log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the manager, refusing.", pid); + return -EPERM; + } + + if (pid == s->control_pid) { + log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the control process, refusing.", pid); + return -EPERM; + } + + if (!pid_is_alive(pid)) { + log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" does not exist or is a zombie.", pid); + return -ESRCH; + } + + owner = manager_get_unit_by_pid(UNIT(s)->manager, pid); + if (owner == UNIT(s)) { + log_unit_debug(UNIT(s), "New main PID "PID_FMT" belongs to service, we are happy.", pid); + return 1; /* Yay, it's definitely a good PID */ + } + + return 0; /* Hmm it's a suspicious PID, let's accept it if configuration source is trusted */ +} + +static int service_load_pid_file(Service *s, bool may_warn) { + char procfs[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + bool questionable_pid_file = false; + _cleanup_free_ char *k = NULL; + _cleanup_close_ int fd = -1; + int r, prio; + pid_t pid; + + assert(s); + + if (!s->pid_file) + return -ENOENT; + + prio = may_warn ? LOG_INFO : LOG_DEBUG; + + r = chase_symlinks(s->pid_file, NULL, CHASE_SAFE, NULL, &fd); + if (r == -ENOLINK) { + log_unit_full(UNIT(s), LOG_DEBUG, r, + "Potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file); + + questionable_pid_file = true; + + r = chase_symlinks(s->pid_file, NULL, 0, NULL, &fd); + } + if (r < 0) + return log_unit_full(UNIT(s), prio, fd, + "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); + + /* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd + * chase_symlinks() returned us into a proper fd first. */ + xsprintf(procfs, "/proc/self/fd/%i", fd); + r = read_one_line_file(procfs, &k); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, + "Can't convert PID files %s O_PATH file descriptor to proper file descriptor: %m", + s->pid_file); + + r = parse_pid(k, &pid); + if (r < 0) + return log_unit_full(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file); + + if (s->main_pid_known && pid == s->main_pid) + return 0; + + r = service_is_suitable_main_pid(s, pid, prio); + if (r < 0) + return r; + if (r == 0) { + struct stat st; + + if (questionable_pid_file) { + log_unit_error(UNIT(s), "Refusing to accept PID outside of service control group, acquired through unsafe symlink chain: %s", s->pid_file); + return -EPERM; + } + + /* Hmm, it's not clear if the new main PID is safe. Let's allow this if the PID file is owned by root */ + + if (fstat(fd, &st) < 0) + return log_unit_error_errno(UNIT(s), errno, "Failed to fstat() PID file O_PATH fd: %m"); + + if (st.st_uid != 0) { + log_unit_error(UNIT(s), "New main PID "PID_FMT" does not belong to service, and PID file is not owned by root. Refusing.", pid); + return -EPERM; + } + + log_unit_debug(UNIT(s), "New main PID "PID_FMT" does not belong to service, but we'll accept it since PID file is owned by root.", pid); + } + + if (s->main_pid_known) { + log_unit_debug(UNIT(s), "Main PID changing: "PID_FMT" -> "PID_FMT, s->main_pid, pid); + + service_unwatch_main_pid(s); + s->main_pid_known = false; + } else + log_unit_debug(UNIT(s), "Main PID loaded: "PID_FMT, pid); + + r = service_set_main_pid(s, pid); + if (r < 0) + return r; + + r = unit_watch_pid(UNIT(s), pid, false); + if (r < 0) /* FIXME: we need to do something here */ + return log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" for service: %m", pid); + + return 1; +} + +static void service_search_main_pid(Service *s) { + pid_t pid = 0; + int r; + + assert(s); + + /* If we know it anyway, don't ever fallback to unreliable + * heuristics */ + if (s->main_pid_known) + return; + + if (!s->guess_main_pid) + return; + + assert(s->main_pid <= 0); + + if (unit_search_main_pid(UNIT(s), &pid) < 0) + return; + + log_unit_debug(UNIT(s), "Main PID guessed: "PID_FMT, pid); + if (service_set_main_pid(s, pid) < 0) + return; + + r = unit_watch_pid(UNIT(s), pid, false); + if (r < 0) + /* FIXME: we need to do something here */ + log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" from: %m", pid); +} + +static void service_set_state(Service *s, ServiceState state) { + ServiceState old_state; + const UnitActiveState *table; + + assert(s); + + if (s->state != state) + bus_unit_send_pending_change_signal(UNIT(s), false); + + table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table; + + old_state = s->state; + s->state = state; + + service_unwatch_pid_file(s); + + if (!IN_SET(state, + SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, + SERVICE_RUNNING, + SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, + SERVICE_AUTO_RESTART, + SERVICE_CLEANING)) + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + + if (!IN_SET(state, + SERVICE_START, SERVICE_START_POST, + SERVICE_RUNNING, SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) { + service_unwatch_main_pid(s); + s->main_command = NULL; + } + + if (!IN_SET(state, + SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, + SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, + SERVICE_CLEANING)) { + service_unwatch_control_pid(s); + s->control_command = NULL; + s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; + } + + if (IN_SET(state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) { + unit_unwatch_all_pids(UNIT(s)); + unit_dequeue_rewatch_pids(UNIT(s)); + } + + if (!IN_SET(state, + SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, + SERVICE_RUNNING, SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL) && + !(state == SERVICE_DEAD && UNIT(s)->job)) + service_close_socket_fd(s); + + if (state != SERVICE_START) + s->exec_fd_event_source = sd_event_source_unref(s->exec_fd_event_source); + + if (!IN_SET(state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) + service_stop_watchdog(s); + + /* For the inactive states unit_notify() will trim the cgroup, + * but for exit we have to do that ourselves... */ + if (state == SERVICE_EXITED && !MANAGER_IS_RELOADING(UNIT(s)->manager)) + unit_prune_cgroup(UNIT(s)); + + if (old_state != state) + log_unit_debug(UNIT(s), "Changed %s -> %s", service_state_to_string(old_state), service_state_to_string(state)); + + unit_notify(UNIT(s), table[old_state], table[state], + (s->reload_result == SERVICE_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE) | + (s->will_auto_restart ? UNIT_NOTIFY_WILL_AUTO_RESTART : 0) | + (s->result == SERVICE_SKIP_CONDITION ? UNIT_NOTIFY_SKIP_CONDITION : 0)); +} + +static usec_t service_coldplug_timeout(Service *s) { + assert(s); + + switch (s->deserialized_state) { + + case SERVICE_CONDITION: + case SERVICE_START_PRE: + case SERVICE_START: + case SERVICE_START_POST: + case SERVICE_RELOAD: + return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_start_usec); + + case SERVICE_RUNNING: + return usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec); + + case SERVICE_STOP: + case SERVICE_STOP_SIGTERM: + case SERVICE_STOP_SIGKILL: + case SERVICE_STOP_POST: + case SERVICE_FINAL_SIGTERM: + case SERVICE_FINAL_SIGKILL: + return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_stop_usec); + + case SERVICE_STOP_WATCHDOG: + return usec_add(UNIT(s)->state_change_timestamp.monotonic, service_timeout_abort_usec(s)); + + case SERVICE_AUTO_RESTART: + return usec_add(UNIT(s)->inactive_enter_timestamp.monotonic, s->restart_usec); + + case SERVICE_CLEANING: + return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->exec_context.timeout_clean_usec); + + default: + return USEC_INFINITY; + } +} + +static int service_coldplug(Unit *u) { + Service *s = SERVICE(u); + int r; + + assert(s); + assert(s->state == SERVICE_DEAD); + + if (s->deserialized_state == s->state) + return 0; + + r = service_arm_timer(s, service_coldplug_timeout(s)); + if (r < 0) + return r; + + if (s->main_pid > 0 && + pid_is_unwaited(s->main_pid) && + (IN_SET(s->deserialized_state, + SERVICE_START, SERVICE_START_POST, + SERVICE_RUNNING, SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) { + r = unit_watch_pid(UNIT(s), s->main_pid, false); + if (r < 0) + return r; + } + + if (s->control_pid > 0 && + pid_is_unwaited(s->control_pid) && + IN_SET(s->deserialized_state, + SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, + SERVICE_RELOAD, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, + SERVICE_CLEANING)) { + r = unit_watch_pid(UNIT(s), s->control_pid, false); + if (r < 0) + return r; + } + + if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART, SERVICE_CLEANING)) { + (void) unit_enqueue_rewatch_pids(u); + (void) unit_setup_dynamic_creds(u); + (void) unit_setup_exec_runtime(u); + } + + if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) + service_start_watchdog(s); + + if (UNIT_ISSET(s->accept_socket)) { + Socket* socket = SOCKET(UNIT_DEREF(s->accept_socket)); + + if (socket->max_connections_per_source > 0) { + SocketPeer *peer; + + /* Make a best-effort attempt at bumping the connection count */ + if (socket_acquire_peer(socket, s->socket_fd, &peer) > 0) { + socket_peer_unref(s->peer); + s->peer = peer; + } + } + } + + service_set_state(s, s->deserialized_state); + return 0; +} + +static int service_collect_fds( + Service *s, + int **fds, + char ***fd_names, + size_t *n_socket_fds, + size_t *n_storage_fds) { + + _cleanup_strv_free_ char **rfd_names = NULL; + _cleanup_free_ int *rfds = NULL; + size_t rn_socket_fds = 0, rn_storage_fds = 0; + int r; + + assert(s); + assert(fds); + assert(fd_names); + assert(n_socket_fds); + assert(n_storage_fds); + + if (s->socket_fd >= 0) { + + /* Pass the per-connection socket */ + + rfds = new(int, 1); + if (!rfds) + return -ENOMEM; + rfds[0] = s->socket_fd; + + rfd_names = strv_new("connection"); + if (!rfd_names) + return -ENOMEM; + + rn_socket_fds = 1; + } else { + Iterator i; + void *v; + Unit *u; + + /* Pass all our configured sockets for singleton services */ + + HASHMAP_FOREACH_KEY(v, u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i) { + _cleanup_free_ int *cfds = NULL; + Socket *sock; + int cn_fds; + + if (u->type != UNIT_SOCKET) + continue; + + sock = SOCKET(u); + + cn_fds = socket_collect_fds(sock, &cfds); + if (cn_fds < 0) + return cn_fds; + + if (cn_fds <= 0) + continue; + + if (!rfds) { + rfds = TAKE_PTR(cfds); + rn_socket_fds = cn_fds; + } else { + int *t; + + t = reallocarray(rfds, rn_socket_fds + cn_fds, sizeof(int)); + if (!t) + return -ENOMEM; + + memcpy(t + rn_socket_fds, cfds, cn_fds * sizeof(int)); + + rfds = t; + rn_socket_fds += cn_fds; + } + + r = strv_extend_n(&rfd_names, socket_fdname(sock), cn_fds); + if (r < 0) + return r; + } + } + + if (s->n_fd_store > 0) { + ServiceFDStore *fs; + size_t n_fds; + char **nl; + int *t; + + t = reallocarray(rfds, rn_socket_fds + s->n_fd_store, sizeof(int)); + if (!t) + return -ENOMEM; + + rfds = t; + + nl = reallocarray(rfd_names, rn_socket_fds + s->n_fd_store + 1, sizeof(char *)); + if (!nl) + return -ENOMEM; + + rfd_names = nl; + n_fds = rn_socket_fds; + + LIST_FOREACH(fd_store, fs, s->fd_store) { + rfds[n_fds] = fs->fd; + rfd_names[n_fds] = strdup(strempty(fs->fdname)); + if (!rfd_names[n_fds]) + return -ENOMEM; + + rn_storage_fds++; + n_fds++; + } + + rfd_names[n_fds] = NULL; + } + + *fds = TAKE_PTR(rfds); + *fd_names = TAKE_PTR(rfd_names); + *n_socket_fds = rn_socket_fds; + *n_storage_fds = rn_storage_fds; + + return 0; +} + +static int service_allocate_exec_fd_event_source( + Service *s, + int fd, + sd_event_source **ret_event_source) { + + _cleanup_(sd_event_source_unrefp) sd_event_source *source = NULL; + int r; + + assert(s); + assert(fd >= 0); + assert(ret_event_source); + + r = sd_event_add_io(UNIT(s)->manager->event, &source, fd, 0, service_dispatch_exec_io, s); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to allocate exec_fd event source: %m"); + + /* This is a bit lower priority than SIGCHLD, as that carries a lot more interesting failure information */ + + r = sd_event_source_set_priority(source, SD_EVENT_PRIORITY_NORMAL-3); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to adjust priority of exec_fd event source: %m"); + + (void) sd_event_source_set_description(source, "service event_fd"); + + r = sd_event_source_set_io_fd_own(source, true); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to pass ownership of fd to event source: %m"); + + *ret_event_source = TAKE_PTR(source); + return 0; +} + +static int service_allocate_exec_fd( + Service *s, + sd_event_source **ret_event_source, + int* ret_exec_fd) { + + _cleanup_close_pair_ int p[2] = { -1, -1 }; + int r; + + assert(s); + assert(ret_event_source); + assert(ret_exec_fd); + + if (pipe2(p, O_CLOEXEC|O_NONBLOCK) < 0) + return log_unit_error_errno(UNIT(s), errno, "Failed to allocate exec_fd pipe: %m"); + + r = service_allocate_exec_fd_event_source(s, p[0], ret_event_source); + if (r < 0) + return r; + + p[0] = -1; + *ret_exec_fd = TAKE_FD(p[1]); + + return 0; +} + +static bool service_exec_needs_notify_socket(Service *s, ExecFlags flags) { + assert(s); + + /* Notifications are accepted depending on the process and + * the access setting of the service: + * process: \ access: NONE MAIN EXEC ALL + * main no yes yes yes + * control no no yes yes + * other (forked) no no no yes */ + + if (flags & EXEC_IS_CONTROL) + /* A control process */ + return IN_SET(s->notify_access, NOTIFY_EXEC, NOTIFY_ALL); + + /* We only spawn main processes and control processes, so any + * process that is not a control process is a main process */ + return s->notify_access != NOTIFY_NONE; +} + +static int service_spawn( + Service *s, + ExecCommand *c, + usec_t timeout, + ExecFlags flags, + pid_t *_pid) { + + _cleanup_(exec_params_clear) ExecParameters exec_params = { + .flags = flags, + .stdin_fd = -1, + .stdout_fd = -1, + .stderr_fd = -1, + .exec_fd = -1, + }; + _cleanup_strv_free_ char **final_env = NULL, **our_env = NULL, **fd_names = NULL; + _cleanup_(sd_event_source_unrefp) sd_event_source *exec_fd_source = NULL; + size_t n_socket_fds = 0, n_storage_fds = 0, n_env = 0; + _cleanup_close_ int exec_fd = -1; + _cleanup_free_ int *fds = NULL; + pid_t pid; + int r; + + assert(s); + assert(c); + assert(_pid); + + r = unit_prepare_exec(UNIT(s)); /* This realizes the cgroup, among other things */ + if (r < 0) + return r; + + if (flags & EXEC_IS_CONTROL) { + /* If this is a control process, mask the permissions/chroot application if this is requested. */ + if (s->permissions_start_only) + exec_params.flags &= ~EXEC_APPLY_SANDBOXING; + if (s->root_directory_start_only) + exec_params.flags &= ~EXEC_APPLY_CHROOT; + } + + if ((flags & EXEC_PASS_FDS) || + s->exec_context.std_input == EXEC_INPUT_SOCKET || + s->exec_context.std_output == EXEC_OUTPUT_SOCKET || + s->exec_context.std_error == EXEC_OUTPUT_SOCKET) { + + r = service_collect_fds(s, &fds, &fd_names, &n_socket_fds, &n_storage_fds); + if (r < 0) + return r; + + log_unit_debug(UNIT(s), "Passing %zu fds to service", n_socket_fds + n_storage_fds); + } + + if (!FLAGS_SET(flags, EXEC_IS_CONTROL) && s->type == SERVICE_EXEC) { + assert(!s->exec_fd_event_source); + + r = service_allocate_exec_fd(s, &exec_fd_source, &exec_fd); + if (r < 0) + return r; + } + + r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), timeout)); + if (r < 0) + return r; + + our_env = new0(char*, 10); + if (!our_env) + return -ENOMEM; + + if (service_exec_needs_notify_socket(s, flags)) + if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)->manager->notify_socket) < 0) + return -ENOMEM; + + if (s->main_pid > 0) + if (asprintf(our_env + n_env++, "MAINPID="PID_FMT, s->main_pid) < 0) + return -ENOMEM; + + if (MANAGER_IS_USER(UNIT(s)->manager)) + if (asprintf(our_env + n_env++, "MANAGERPID="PID_FMT, getpid_cached()) < 0) + return -ENOMEM; + + if (s->pid_file) + if (asprintf(our_env + n_env++, "PIDFILE=%s", s->pid_file) < 0) + return -ENOMEM; + + if (s->socket_fd >= 0) { + union sockaddr_union sa; + socklen_t salen = sizeof(sa); + + /* If this is a per-connection service instance, let's set $REMOTE_ADDR and $REMOTE_PORT to something + * useful. Note that we do this only when we are still connected at this point in time, which we might + * very well not be. Hence we ignore all errors when retrieving peer information (as that might result + * in ENOTCONN), and just use whate we can use. */ + + if (getpeername(s->socket_fd, &sa.sa, &salen) >= 0 && + IN_SET(sa.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) { + + _cleanup_free_ char *addr = NULL; + char *t; + unsigned port; + + r = sockaddr_pretty(&sa.sa, salen, true, false, &addr); + if (r < 0) + return r; + + t = strjoin("REMOTE_ADDR=", addr); + if (!t) + return -ENOMEM; + our_env[n_env++] = t; + + r = sockaddr_port(&sa.sa, &port); + if (r < 0) + return r; + + if (asprintf(&t, "REMOTE_PORT=%u", port) < 0) + return -ENOMEM; + our_env[n_env++] = t; + } + } + + if (flags & EXEC_SETENV_RESULT) { + if (asprintf(our_env + n_env++, "SERVICE_RESULT=%s", service_result_to_string(s->result)) < 0) + return -ENOMEM; + + if (s->main_exec_status.pid > 0 && + dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) { + if (asprintf(our_env + n_env++, "EXIT_CODE=%s", sigchld_code_to_string(s->main_exec_status.code)) < 0) + return -ENOMEM; + + if (s->main_exec_status.code == CLD_EXITED) + r = asprintf(our_env + n_env++, "EXIT_STATUS=%i", s->main_exec_status.status); + else + r = asprintf(our_env + n_env++, "EXIT_STATUS=%s", signal_to_string(s->main_exec_status.status)); + if (r < 0) + return -ENOMEM; + } + } + + r = unit_set_exec_params(UNIT(s), &exec_params); + if (r < 0) + return r; + + final_env = strv_env_merge(2, exec_params.environment, our_env, NULL); + if (!final_env) + return -ENOMEM; + + /* System D-Bus needs nss-systemd disabled, so that we don't deadlock */ + SET_FLAG(exec_params.flags, EXEC_NSS_BYPASS_BUS, + MANAGER_IS_SYSTEM(UNIT(s)->manager) && unit_has_name(UNIT(s), SPECIAL_DBUS_SERVICE)); + + strv_free_and_replace(exec_params.environment, final_env); + exec_params.fds = fds; + exec_params.fd_names = fd_names; + exec_params.n_socket_fds = n_socket_fds; + exec_params.n_storage_fds = n_storage_fds; + exec_params.watchdog_usec = service_get_watchdog_usec(s); + exec_params.selinux_context_net = s->socket_fd_selinux_context_net; + if (s->type == SERVICE_IDLE) + exec_params.idle_pipe = UNIT(s)->manager->idle_pipe; + exec_params.stdin_fd = s->stdin_fd; + exec_params.stdout_fd = s->stdout_fd; + exec_params.stderr_fd = s->stderr_fd; + exec_params.exec_fd = exec_fd; + + r = exec_spawn(UNIT(s), + c, + &s->exec_context, + &exec_params, + s->exec_runtime, + &s->dynamic_creds, + &pid); + if (r < 0) + return r; + + s->exec_fd_event_source = TAKE_PTR(exec_fd_source); + s->exec_fd_hot = false; + + r = unit_watch_pid(UNIT(s), pid, true); + if (r < 0) + return r; + + *_pid = pid; + + return 0; +} + +static int main_pid_good(Service *s) { + assert(s); + + /* Returns 0 if the pid is dead, > 0 if it is good, < 0 if we don't know */ + + /* If we know the pid file, then let's just check if it is + * still valid */ + if (s->main_pid_known) { + + /* If it's an alien child let's check if it is still + * alive ... */ + if (s->main_pid_alien && s->main_pid > 0) + return pid_is_alive(s->main_pid); + + /* .. otherwise assume we'll get a SIGCHLD for it, + * which we really should wait for to collect exit + * status and code */ + return s->main_pid > 0; + } + + /* We don't know the pid */ + return -EAGAIN; +} + +static int control_pid_good(Service *s) { + assert(s); + + /* Returns 0 if the control PID is dead, > 0 if it is good. We never actually return < 0 here, but in order to + * make this function as similar as possible to main_pid_good() and cgroup_good(), we pretend that < 0 also + * means: we can't figure it out. */ + + return s->control_pid > 0; +} + +static int cgroup_good(Service *s) { + int r; + + assert(s); + + /* Returns 0 if the cgroup is empty or doesn't exist, > 0 if it is exists and is populated, < 0 if we can't + * figure it out */ + + if (!UNIT(s)->cgroup_path) + return 0; + + r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path); + if (r < 0) + return r; + + return r == 0; +} + +static bool service_shall_restart(Service *s, const char **reason) { + assert(s); + + /* Don't restart after manual stops */ + if (s->forbid_restart) { + *reason = "manual stop"; + return false; + } + + /* Never restart if this is configured as special exception */ + if (exit_status_set_test(&s->restart_prevent_status, s->main_exec_status.code, s->main_exec_status.status)) { + *reason = "prevented by exit status"; + return false; + } + + /* Restart if the exit code/status are configured as restart triggers */ + if (exit_status_set_test(&s->restart_force_status, s->main_exec_status.code, s->main_exec_status.status)) { + *reason = "forced by exit status"; + return true; + } + + *reason = "restart setting"; + switch (s->restart) { + + case SERVICE_RESTART_NO: + return false; + + case SERVICE_RESTART_ALWAYS: + return true; + + case SERVICE_RESTART_ON_SUCCESS: + return s->result == SERVICE_SUCCESS; + + case SERVICE_RESTART_ON_FAILURE: + return s->result != SERVICE_SUCCESS; + + case SERVICE_RESTART_ON_ABNORMAL: + return !IN_SET(s->result, SERVICE_SUCCESS, SERVICE_FAILURE_EXIT_CODE); + + case SERVICE_RESTART_ON_WATCHDOG: + return s->result == SERVICE_FAILURE_WATCHDOG; + + case SERVICE_RESTART_ON_ABORT: + return IN_SET(s->result, SERVICE_FAILURE_SIGNAL, SERVICE_FAILURE_CORE_DUMP); + + default: + assert_not_reached("unknown restart setting"); + } +} + +static bool service_will_restart(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + if (s->will_auto_restart) + return true; + if (s->state == SERVICE_AUTO_RESTART) + return true; + + return unit_will_restart_default(u); +} + +static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) { + ServiceState end_state; + int r; + + assert(s); + + /* If there's a stop job queued before we enter the DEAD state, we shouldn't act on Restart=, in order to not + * undo what has already been enqueued. */ + if (unit_stop_pending(UNIT(s))) + allow_restart = false; + + if (s->result == SERVICE_SUCCESS) + s->result = f; + + if (s->result == SERVICE_SUCCESS) { + unit_log_success(UNIT(s)); + end_state = SERVICE_DEAD; + } else if (s->result == SERVICE_SKIP_CONDITION) { + unit_log_skip(UNIT(s), service_result_to_string(s->result)); + end_state = SERVICE_DEAD; + } else { + unit_log_failure(UNIT(s), service_result_to_string(s->result)); + end_state = SERVICE_FAILED; + } + + if (!allow_restart) + log_unit_debug(UNIT(s), "Service restart not allowed."); + else { + const char *reason; + bool shall_restart; + + shall_restart = service_shall_restart(s, &reason); + log_unit_debug(UNIT(s), "Service will %srestart (%s)", + shall_restart ? "" : "not ", + reason); + if (shall_restart) + s->will_auto_restart = true; + } + + /* Make sure service_release_resources() doesn't destroy our FD store, while we are changing through + * SERVICE_FAILED/SERVICE_DEAD before entering into SERVICE_AUTO_RESTART. */ + s->n_keep_fd_store ++; + + service_set_state(s, end_state); + + if (s->will_auto_restart) { + s->will_auto_restart = false; + + r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec)); + if (r < 0) { + s->n_keep_fd_store--; + goto fail; + } + + service_set_state(s, SERVICE_AUTO_RESTART); + } else + /* If we shan't restart, then flush out the restart counter. But don't do that immediately, so that the + * user can still introspect the counter. Do so on the next start. */ + s->flush_n_restarts = true; + + /* The new state is in effect, let's decrease the fd store ref counter again. Let's also re-add us to the GC + * queue, so that the fd store is possibly gc'ed again */ + s->n_keep_fd_store--; + unit_add_to_gc_queue(UNIT(s)); + + /* The next restart might not be a manual stop, hence reset the flag indicating manual stops */ + s->forbid_restart = false; + + /* We want fresh tmpdirs in case service is started again immediately */ + s->exec_runtime = exec_runtime_unref(s->exec_runtime, true); + + /* Also, remove the runtime directory */ + unit_destroy_runtime_directory(UNIT(s), &s->exec_context); + + /* Get rid of the IPC bits of the user */ + unit_unref_uid_gid(UNIT(s), true); + + /* Release the user, and destroy it if we are the only remaining owner */ + dynamic_creds_destroy(&s->dynamic_creds); + + /* Try to delete the pid file. At this point it will be + * out-of-date, and some software might be confused by it, so + * let's remove it. */ + if (s->pid_file) + (void) unlink(s->pid_file); + + /* Reset TTY ownership if necessary */ + exec_context_revert_tty(&s->exec_context); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run install restart timer: %m"); + service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false); +} + +static void service_enter_stop_post(Service *s, ServiceResult f) { + int r; + assert(s); + + if (s->result == SERVICE_SUCCESS) + s->result = f; + + service_unwatch_control_pid(s); + (void) unit_enqueue_rewatch_pids(UNIT(s)); + + s->control_command = s->exec_command[SERVICE_EXEC_STOP_POST]; + if (s->control_command) { + s->control_command_id = SERVICE_EXEC_STOP_POST; + + r = service_spawn(s, + s->control_command, + s->timeout_stop_usec, + EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_IS_CONTROL|EXEC_SETENV_RESULT|EXEC_CONTROL_CGROUP, + &s->control_pid); + if (r < 0) + goto fail; + + service_set_state(s, SERVICE_STOP_POST); + } else + service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_SUCCESS); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-post' task: %m"); + service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES); +} + +static int state_to_kill_operation(Service *s, ServiceState state) { + switch (state) { + + case SERVICE_STOP_WATCHDOG: + return KILL_WATCHDOG; + + case SERVICE_STOP_SIGTERM: + if (unit_has_job_type(UNIT(s), JOB_RESTART)) + return KILL_RESTART; + _fallthrough_; + + case SERVICE_FINAL_SIGTERM: + return KILL_TERMINATE; + + case SERVICE_STOP_SIGKILL: + case SERVICE_FINAL_SIGKILL: + return KILL_KILL; + + default: + return _KILL_OPERATION_INVALID; + } +} + +static void service_enter_signal(Service *s, ServiceState state, ServiceResult f) { + int r; + + assert(s); + + if (s->result == SERVICE_SUCCESS) + s->result = f; + + /* Before sending any signal, make sure we track all members of this cgroup */ + (void) unit_watch_all_pids(UNIT(s)); + + /* Also, enqueue a job that we recheck all our PIDs a bit later, given that it's likely some processes have + * died now */ + (void) unit_enqueue_rewatch_pids(UNIT(s)); + + r = unit_kill_context( + UNIT(s), + &s->kill_context, + state_to_kill_operation(s, state), + s->main_pid, + s->control_pid, + s->main_pid_alien); + if (r < 0) + goto fail; + + if (r > 0) { + r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), + state == SERVICE_STOP_WATCHDOG ? service_timeout_abort_usec(s) : s->timeout_stop_usec)); + if (r < 0) + goto fail; + + service_set_state(s, state); + } else if (IN_SET(state, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM) && s->kill_context.send_sigkill) + service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_SUCCESS); + else if (IN_SET(state, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL)) + service_enter_stop_post(s, SERVICE_SUCCESS); + else if (state == SERVICE_FINAL_SIGTERM && s->kill_context.send_sigkill) + service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_SUCCESS); + else + service_enter_dead(s, SERVICE_SUCCESS, true); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); + + if (IN_SET(state, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL)) + service_enter_stop_post(s, SERVICE_FAILURE_RESOURCES); + else + service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true); +} + +static void service_enter_stop_by_notify(Service *s) { + assert(s); + + (void) unit_enqueue_rewatch_pids(UNIT(s)); + + service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec)); + + /* The service told us it's stopping, so it's as if we SIGTERM'd it. */ + service_set_state(s, SERVICE_STOP_SIGTERM); +} + +static void service_enter_stop(Service *s, ServiceResult f) { + int r; + + assert(s); + + if (s->result == SERVICE_SUCCESS) + s->result = f; + + service_unwatch_control_pid(s); + (void) unit_enqueue_rewatch_pids(UNIT(s)); + + s->control_command = s->exec_command[SERVICE_EXEC_STOP]; + if (s->control_command) { + s->control_command_id = SERVICE_EXEC_STOP; + + r = service_spawn(s, + s->control_command, + s->timeout_stop_usec, + EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_SETENV_RESULT|EXEC_CONTROL_CGROUP, + &s->control_pid); + if (r < 0) + goto fail; + + service_set_state(s, SERVICE_STOP); + } else + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop' task: %m"); + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); +} + +static bool service_good(Service *s) { + int main_pid_ok; + assert(s); + + if (s->type == SERVICE_DBUS && !s->bus_name_good) + return false; + + main_pid_ok = main_pid_good(s); + if (main_pid_ok > 0) /* It's alive */ + return true; + if (main_pid_ok == 0) /* It's dead */ + return false; + + /* OK, we don't know anything about the main PID, maybe + * because there is none. Let's check the control group + * instead. */ + + return cgroup_good(s) != 0; +} + +static void service_enter_running(Service *s, ServiceResult f) { + assert(s); + + if (s->result == SERVICE_SUCCESS) + s->result = f; + + service_unwatch_control_pid(s); + + if (s->result != SERVICE_SUCCESS) + service_enter_signal(s, SERVICE_STOP_SIGTERM, f); + else if (service_good(s)) { + + /* If there are any queued up sd_notify() notifications, process them now */ + if (s->notify_state == NOTIFY_RELOADING) + service_enter_reload_by_notify(s); + else if (s->notify_state == NOTIFY_STOPPING) + service_enter_stop_by_notify(s); + else { + service_set_state(s, SERVICE_RUNNING); + service_arm_timer(s, usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec)); + } + + } else if (s->remain_after_exit) + service_set_state(s, SERVICE_EXITED); + else + service_enter_stop(s, SERVICE_SUCCESS); +} + +static void service_enter_start_post(Service *s) { + int r; + assert(s); + + service_unwatch_control_pid(s); + service_reset_watchdog(s); + + s->control_command = s->exec_command[SERVICE_EXEC_START_POST]; + if (s->control_command) { + s->control_command_id = SERVICE_EXEC_START_POST; + + r = service_spawn(s, + s->control_command, + s->timeout_start_usec, + EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_CONTROL_CGROUP, + &s->control_pid); + if (r < 0) + goto fail; + + service_set_state(s, SERVICE_START_POST); + } else + service_enter_running(s, SERVICE_SUCCESS); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-post' task: %m"); + service_enter_stop(s, SERVICE_FAILURE_RESOURCES); +} + +static void service_kill_control_process(Service *s) { + int r; + + assert(s); + + if (s->control_pid <= 0) + return; + + r = kill_and_sigcont(s->control_pid, SIGKILL); + if (r < 0) { + _cleanup_free_ char *comm = NULL; + + (void) get_process_comm(s->control_pid, &comm); + + log_unit_debug_errno(UNIT(s), r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", + s->control_pid, strna(comm)); + } +} + +static int service_adverse_to_leftover_processes(Service *s) { + assert(s); + + /* KillMode=mixed and control group are used to indicate that all process should be killed off. + * SendSIGKILL is used for services that require a clean shutdown. These are typically database + * service where a SigKilled process would result in a lengthy recovery and who's shutdown or + * startup time is quite variable (so Timeout settings aren't of use). + * + * Here we take these two factors and refuse to start a service if there are existing processes + * within a control group. Databases, while generally having some protection against multiple + * instances running, lets not stress the rigor of these. Also ExecStartPre parts of the service + * aren't as rigoriously written to protect aganst against multiple use. */ + if (unit_warn_leftover_processes(UNIT(s)) && + IN_SET(s->kill_context.kill_mode, KILL_MIXED, KILL_CONTROL_GROUP) && + !s->kill_context.send_sigkill) + return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EBUSY), + "Will not start SendSIGKILL=no service of type KillMode=control-group or mixed while processes exist"); + + return 0; +} + +static void service_enter_start(Service *s) { + ExecCommand *c; + usec_t timeout; + pid_t pid; + int r; + + assert(s); + + service_unwatch_control_pid(s); + service_unwatch_main_pid(s); + + r = service_adverse_to_leftover_processes(s); + if (r < 0) + goto fail; + + if (s->type == SERVICE_FORKING) { + s->control_command_id = SERVICE_EXEC_START; + c = s->control_command = s->exec_command[SERVICE_EXEC_START]; + + s->main_command = NULL; + } else { + s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; + s->control_command = NULL; + + c = s->main_command = s->exec_command[SERVICE_EXEC_START]; + } + + if (!c) { + if (s->type != SERVICE_ONESHOT) { + /* There's no command line configured for the main command? Hmm, that is strange. This can only + * happen if the configuration changes at runtime. In this case, let's enter a failure + * state. */ + log_unit_error(UNIT(s), "There's no 'start' task anymore we could start."); + r = -ENXIO; + goto fail; + } + + /* We force a fake state transition here. Otherwise, the unit would go directly from + * SERVICE_DEAD to SERVICE_DEAD without SERVICE_ACTIVATING or SERVICE_ACTIVE + * in between. This way we can later trigger actions that depend on the state + * transition, including SuccessAction=. */ + service_set_state(s, SERVICE_START); + + service_enter_start_post(s); + return; + } + + if (IN_SET(s->type, SERVICE_SIMPLE, SERVICE_IDLE)) + /* For simple + idle this is the main process. We don't apply any timeout here, but + * service_enter_running() will later apply the .runtime_max_usec timeout. */ + timeout = USEC_INFINITY; + else + timeout = s->timeout_start_usec; + + r = service_spawn(s, + c, + timeout, + EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG, + &pid); + if (r < 0) + goto fail; + + if (IN_SET(s->type, SERVICE_SIMPLE, SERVICE_IDLE)) { + /* For simple services we immediately start + * the START_POST binaries. */ + + service_set_main_pid(s, pid); + service_enter_start_post(s); + + } else if (s->type == SERVICE_FORKING) { + + /* For forking services we wait until the start + * process exited. */ + + s->control_pid = pid; + service_set_state(s, SERVICE_START); + + } else if (IN_SET(s->type, SERVICE_ONESHOT, SERVICE_DBUS, SERVICE_NOTIFY, SERVICE_EXEC)) { + + /* For oneshot services we wait until the start process exited, too, but it is our main process. */ + + /* For D-Bus services we know the main pid right away, but wait for the bus name to appear on the + * bus. 'notify' and 'exec' services are similar. */ + + service_set_main_pid(s, pid); + service_set_state(s, SERVICE_START); + } else + assert_not_reached("Unknown service type"); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'start' task: %m"); + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); +} + +static void service_enter_start_pre(Service *s) { + int r; + + assert(s); + + service_unwatch_control_pid(s); + + s->control_command = s->exec_command[SERVICE_EXEC_START_PRE]; + if (s->control_command) { + + r = service_adverse_to_leftover_processes(s); + if (r < 0) + goto fail; + + s->control_command_id = SERVICE_EXEC_START_PRE; + + r = service_spawn(s, + s->control_command, + s->timeout_start_usec, + EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN, + &s->control_pid); + if (r < 0) + goto fail; + + service_set_state(s, SERVICE_START_PRE); + } else + service_enter_start(s); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-pre' task: %m"); + service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true); +} + +static void service_enter_condition(Service *s) { + int r; + + assert(s); + + service_unwatch_control_pid(s); + + s->control_command = s->exec_command[SERVICE_EXEC_CONDITION]; + if (s->control_command) { + + r = service_adverse_to_leftover_processes(s); + if (r < 0) + goto fail; + + s->control_command_id = SERVICE_EXEC_CONDITION; + + r = service_spawn(s, + s->control_command, + s->timeout_start_usec, + EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN, + &s->control_pid); + + if (r < 0) + goto fail; + + service_set_state(s, SERVICE_CONDITION); + } else + service_enter_start_pre(s); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'exec-condition' task: %m"); + service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true); +} + +static void service_enter_restart(Service *s) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(s); + + if (unit_has_job_type(UNIT(s), JOB_STOP)) { + /* Don't restart things if we are going down anyway */ + log_unit_info(UNIT(s), "Stop job pending for unit, delaying automatic restart."); + + r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec)); + if (r < 0) + goto fail; + + return; + } + + /* Any units that are bound to this service must also be + * restarted. We use JOB_RESTART (instead of the more obvious + * JOB_START) here so that those dependency jobs will be added + * as well. */ + r = manager_add_job(UNIT(s)->manager, JOB_RESTART, UNIT(s), JOB_REPLACE, NULL, &error, NULL); + if (r < 0) + goto fail; + + /* Count the jobs we enqueue for restarting. This counter is maintained as long as the unit isn't fully + * stopped, i.e. as long as it remains up or remains in auto-start states. The use can reset the counter + * explicitly however via the usual "systemctl reset-failure" logic. */ + s->n_restarts ++; + s->flush_n_restarts = false; + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_UNIT_RESTART_SCHEDULED_STR, + LOG_UNIT_ID(UNIT(s)), + LOG_UNIT_INVOCATION_ID(UNIT(s)), + LOG_UNIT_MESSAGE(UNIT(s), "Scheduled restart job, restart counter is at %u.", s->n_restarts), + "N_RESTARTS=%u", s->n_restarts); + + /* Notify clients about changed restart counter */ + unit_add_to_dbus_queue(UNIT(s)); + + /* Note that we stay in the SERVICE_AUTO_RESTART state here, + * it will be canceled as part of the service_stop() call that + * is executed as part of JOB_RESTART. */ + + return; + +fail: + log_unit_warning(UNIT(s), "Failed to schedule restart job: %s", bus_error_message(&error, -r)); + service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false); +} + +static void service_enter_reload_by_notify(Service *s) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(s); + + service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_start_usec)); + service_set_state(s, SERVICE_RELOAD); + + /* service_enter_reload_by_notify is never called during a reload, thus no loops are possible. */ + r = manager_propagate_reload(UNIT(s)->manager, UNIT(s), JOB_FAIL, &error); + if (r < 0) + log_unit_warning(UNIT(s), "Failed to schedule propagation of reload: %s", bus_error_message(&error, -r)); +} + +static void service_enter_reload(Service *s) { + int r; + + assert(s); + + service_unwatch_control_pid(s); + s->reload_result = SERVICE_SUCCESS; + + s->control_command = s->exec_command[SERVICE_EXEC_RELOAD]; + if (s->control_command) { + s->control_command_id = SERVICE_EXEC_RELOAD; + + r = service_spawn(s, + s->control_command, + s->timeout_start_usec, + EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_CONTROL_CGROUP, + &s->control_pid); + if (r < 0) + goto fail; + + service_set_state(s, SERVICE_RELOAD); + } else + service_enter_running(s, SERVICE_SUCCESS); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'reload' task: %m"); + s->reload_result = SERVICE_FAILURE_RESOURCES; + service_enter_running(s, SERVICE_SUCCESS); +} + +static void service_run_next_control(Service *s) { + usec_t timeout; + int r; + + assert(s); + assert(s->control_command); + assert(s->control_command->command_next); + + assert(s->control_command_id != SERVICE_EXEC_START); + + s->control_command = s->control_command->command_next; + service_unwatch_control_pid(s); + + if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) + timeout = s->timeout_start_usec; + else + timeout = s->timeout_stop_usec; + + r = service_spawn(s, + s->control_command, + timeout, + EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL| + (IN_SET(s->control_command_id, SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST) ? EXEC_APPLY_TTY_STDIN : 0)| + (IN_SET(s->control_command_id, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST) ? EXEC_SETENV_RESULT : 0)| + (IN_SET(s->control_command_id, SERVICE_EXEC_START_POST, SERVICE_EXEC_RELOAD, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST) ? EXEC_CONTROL_CGROUP : 0), + &s->control_pid); + if (r < 0) + goto fail; + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run next control task: %m"); + + if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START_POST, SERVICE_STOP)) + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); + else if (s->state == SERVICE_STOP_POST) + service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true); + else if (s->state == SERVICE_RELOAD) { + s->reload_result = SERVICE_FAILURE_RESOURCES; + service_enter_running(s, SERVICE_SUCCESS); + } else + service_enter_stop(s, SERVICE_FAILURE_RESOURCES); +} + +static void service_run_next_main(Service *s) { + pid_t pid; + int r; + + assert(s); + assert(s->main_command); + assert(s->main_command->command_next); + assert(s->type == SERVICE_ONESHOT); + + s->main_command = s->main_command->command_next; + service_unwatch_main_pid(s); + + r = service_spawn(s, + s->main_command, + s->timeout_start_usec, + EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG, + &pid); + if (r < 0) + goto fail; + + service_set_main_pid(s, pid); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run next main task: %m"); + service_enter_stop(s, SERVICE_FAILURE_RESOURCES); +} + +static int service_start(Unit *u) { + Service *s = SERVICE(u); + int r; + + assert(s); + + /* We cannot fulfill this request right now, try again later + * please! */ + if (IN_SET(s->state, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, SERVICE_CLEANING)) + return -EAGAIN; + + /* Already on it! */ + if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST)) + return 0; + + /* A service that will be restarted must be stopped first to + * trigger BindsTo and/or OnFailure dependencies. If a user + * does not want to wait for the holdoff time to elapse, the + * service should be manually restarted, not started. We + * simply return EAGAIN here, so that any start jobs stay + * queued, and assume that the auto restart timer will + * eventually trigger the restart. */ + if (s->state == SERVICE_AUTO_RESTART) + return -EAGAIN; + + assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED)); + + /* Make sure we don't enter a busy loop of some kind. */ + r = unit_test_start_limit(u); + if (r < 0) { + service_enter_dead(s, SERVICE_FAILURE_START_LIMIT_HIT, false); + return r; + } + + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + + s->result = SERVICE_SUCCESS; + s->reload_result = SERVICE_SUCCESS; + s->main_pid_known = false; + s->main_pid_alien = false; + s->forbid_restart = false; + + s->status_text = mfree(s->status_text); + s->status_errno = 0; + + s->notify_state = NOTIFY_UNKNOWN; + + s->watchdog_original_usec = s->watchdog_usec; + s->watchdog_override_enable = false; + s->watchdog_override_usec = USEC_INFINITY; + + exec_command_reset_status_list_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX); + exec_status_reset(&s->main_exec_status); + + /* This is not an automatic restart? Flush the restart counter then */ + if (s->flush_n_restarts) { + s->n_restarts = 0; + s->flush_n_restarts = false; + } + + u->reset_accounting = true; + + service_enter_condition(s); + return 1; +} + +static int service_stop(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + /* Don't create restart jobs from manual stops. */ + s->forbid_restart = true; + + /* Already on it */ + if (IN_SET(s->state, + SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) + return 0; + + /* A restart will be scheduled or is in progress. */ + if (s->state == SERVICE_AUTO_RESTART) { + service_set_state(s, SERVICE_DEAD); + return 0; + } + + /* If there's already something running we go directly into + * kill mode. */ + if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP_WATCHDOG)) { + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS); + return 0; + } + + /* If we are currently cleaning, then abort it, brutally. */ + if (s->state == SERVICE_CLEANING) { + service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_SUCCESS); + return 0; + } + + assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED)); + + service_enter_stop(s, SERVICE_SUCCESS); + return 1; +} + +static int service_reload(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED)); + + service_enter_reload(s); + return 1; +} + +_pure_ static bool service_can_reload(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + return !!s->exec_command[SERVICE_EXEC_RELOAD]; +} + +static unsigned service_exec_command_index(Unit *u, ServiceExecCommand id, ExecCommand *current) { + Service *s = SERVICE(u); + unsigned idx = 0; + ExecCommand *first, *c; + + assert(s); + + first = s->exec_command[id]; + + /* Figure out where we are in the list by walking back to the beginning */ + for (c = current; c != first; c = c->command_prev) + idx++; + + return idx; +} + +static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command) { + _cleanup_free_ char *args = NULL, *p = NULL; + size_t allocated = 0, length = 0; + Service *s = SERVICE(u); + const char *type, *key; + ServiceExecCommand id; + unsigned idx; + char **arg; + + assert(s); + assert(f); + + if (!command) + return 0; + + if (command == s->control_command) { + type = "control"; + id = s->control_command_id; + } else { + type = "main"; + id = SERVICE_EXEC_START; + } + + idx = service_exec_command_index(u, id, command); + + STRV_FOREACH(arg, command->argv) { + _cleanup_free_ char *e = NULL; + size_t n; + + e = cescape(*arg); + if (!e) + return log_oom(); + + n = strlen(e); + if (!GREEDY_REALLOC(args, allocated, length + 2 + n + 2)) + return log_oom(); + + if (length > 0) + args[length++] = ' '; + + args[length++] = '"'; + memcpy(args + length, e, n); + length += n; + args[length++] = '"'; + } + + if (!GREEDY_REALLOC(args, allocated, length + 1)) + return log_oom(); + + args[length++] = 0; + + p = cescape(command->path); + if (!p) + return -ENOMEM; + + key = strjoina(type, "-command"); + return serialize_item_format(f, key, "%s %u %s %s", service_exec_command_to_string(id), idx, p, args); +} + +static int service_serialize(Unit *u, FILE *f, FDSet *fds) { + Service *s = SERVICE(u); + ServiceFDStore *fs; + int r; + + assert(u); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", service_state_to_string(s->state)); + (void) serialize_item(f, "result", service_result_to_string(s->result)); + (void) serialize_item(f, "reload-result", service_result_to_string(s->reload_result)); + + if (s->control_pid > 0) + (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid); + + if (s->main_pid_known && s->main_pid > 0) + (void) serialize_item_format(f, "main-pid", PID_FMT, s->main_pid); + + (void) serialize_bool(f, "main-pid-known", s->main_pid_known); + (void) serialize_bool(f, "bus-name-good", s->bus_name_good); + (void) serialize_bool(f, "bus-name-owner", s->bus_name_owner); + + (void) serialize_item_format(f, "n-restarts", "%u", s->n_restarts); + (void) serialize_bool(f, "flush-n-restarts", s->flush_n_restarts); + + r = serialize_item_escaped(f, "status-text", s->status_text); + if (r < 0) + return r; + + service_serialize_exec_command(u, f, s->control_command); + service_serialize_exec_command(u, f, s->main_command); + + r = serialize_fd(f, fds, "stdin-fd", s->stdin_fd); + if (r < 0) + return r; + r = serialize_fd(f, fds, "stdout-fd", s->stdout_fd); + if (r < 0) + return r; + r = serialize_fd(f, fds, "stderr-fd", s->stderr_fd); + if (r < 0) + return r; + + if (s->exec_fd_event_source) { + r = serialize_fd(f, fds, "exec-fd", sd_event_source_get_io_fd(s->exec_fd_event_source)); + if (r < 0) + return r; + + (void) serialize_bool(f, "exec-fd-hot", s->exec_fd_hot); + } + + if (UNIT_ISSET(s->accept_socket)) { + r = serialize_item(f, "accept-socket", UNIT_DEREF(s->accept_socket)->id); + if (r < 0) + return r; + } + + r = serialize_fd(f, fds, "socket-fd", s->socket_fd); + if (r < 0) + return r; + + LIST_FOREACH(fd_store, fs, s->fd_store) { + _cleanup_free_ char *c = NULL; + int copy; + + copy = fdset_put_dup(fds, fs->fd); + if (copy < 0) + return log_error_errno(copy, "Failed to copy file descriptor for serialization: %m"); + + c = cescape(fs->fdname); + if (!c) + return log_oom(); + + (void) serialize_item_format(f, "fd-store-fd", "%i %s", copy, c); + } + + if (s->main_exec_status.pid > 0) { + (void) serialize_item_format(f, "main-exec-status-pid", PID_FMT, s->main_exec_status.pid); + (void) serialize_dual_timestamp(f, "main-exec-status-start", &s->main_exec_status.start_timestamp); + (void) serialize_dual_timestamp(f, "main-exec-status-exit", &s->main_exec_status.exit_timestamp); + + if (dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) { + (void) serialize_item_format(f, "main-exec-status-code", "%i", s->main_exec_status.code); + (void) serialize_item_format(f, "main-exec-status-status", "%i", s->main_exec_status.status); + } + } + + (void) serialize_dual_timestamp(f, "watchdog-timestamp", &s->watchdog_timestamp); + (void) serialize_bool(f, "forbid-restart", s->forbid_restart); + + if (s->watchdog_override_enable) + (void) serialize_item_format(f, "watchdog-override-usec", USEC_FMT, s->watchdog_override_usec); + + if (s->watchdog_original_usec != USEC_INFINITY) + (void) serialize_item_format(f, "watchdog-original-usec", USEC_FMT, s->watchdog_original_usec); + + return 0; +} + +static int service_deserialize_exec_command(Unit *u, const char *key, const char *value) { + Service *s = SERVICE(u); + int r; + unsigned idx = 0, i; + bool control, found = false; + ServiceExecCommand id = _SERVICE_EXEC_COMMAND_INVALID; + ExecCommand *command = NULL; + _cleanup_free_ char *path = NULL; + _cleanup_strv_free_ char **argv = NULL; + + enum ExecCommandState { + STATE_EXEC_COMMAND_TYPE, + STATE_EXEC_COMMAND_INDEX, + STATE_EXEC_COMMAND_PATH, + STATE_EXEC_COMMAND_ARGS, + _STATE_EXEC_COMMAND_MAX, + _STATE_EXEC_COMMAND_INVALID = -1, + } state; + + assert(s); + assert(key); + assert(value); + + control = streq(key, "control-command"); + + state = STATE_EXEC_COMMAND_TYPE; + + for (;;) { + _cleanup_free_ char *arg = NULL; + + r = extract_first_word(&value, &arg, NULL, EXTRACT_CUNESCAPE | EXTRACT_UNQUOTE); + if (r < 0) + return r; + if (r == 0) + break; + + switch (state) { + case STATE_EXEC_COMMAND_TYPE: + id = service_exec_command_from_string(arg); + if (id < 0) + return -EINVAL; + + state = STATE_EXEC_COMMAND_INDEX; + break; + case STATE_EXEC_COMMAND_INDEX: + r = safe_atou(arg, &idx); + if (r < 0) + return -EINVAL; + + state = STATE_EXEC_COMMAND_PATH; + break; + case STATE_EXEC_COMMAND_PATH: + path = TAKE_PTR(arg); + state = STATE_EXEC_COMMAND_ARGS; + + if (!path_is_absolute(path)) + return -EINVAL; + break; + case STATE_EXEC_COMMAND_ARGS: + r = strv_extend(&argv, arg); + if (r < 0) + return -ENOMEM; + break; + default: + assert_not_reached("Unknown error at deserialization of exec command"); + break; + } + } + + if (state != STATE_EXEC_COMMAND_ARGS) + return -EINVAL; + + /* Let's check whether exec command on given offset matches data that we just deserialized */ + for (command = s->exec_command[id], i = 0; command; command = command->command_next, i++) { + if (i != idx) + continue; + + found = strv_equal(argv, command->argv) && streq(command->path, path); + break; + } + + if (!found) { + /* Command at the index we serialized is different, let's look for command that exactly + * matches but is on different index. If there is no such command we will not resume execution. */ + for (command = s->exec_command[id]; command; command = command->command_next) + if (strv_equal(command->argv, argv) && streq(command->path, path)) + break; + } + + if (command && control) + s->control_command = command; + else if (command) + s->main_command = command; + else + log_unit_warning(u, "Current command vanished from the unit file, execution of the command list won't be resumed."); + + return 0; +} + +static int service_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Service *s = SERVICE(u); + int r; + + assert(u); + assert(key); + assert(value); + assert(fds); + + if (streq(key, "state")) { + ServiceState state; + + state = service_state_from_string(value); + if (state < 0) + log_unit_debug(u, "Failed to parse state value: %s", value); + else + s->deserialized_state = state; + } else if (streq(key, "result")) { + ServiceResult f; + + f = service_result_from_string(value); + if (f < 0) + log_unit_debug(u, "Failed to parse result value: %s", value); + else if (f != SERVICE_SUCCESS) + s->result = f; + + } else if (streq(key, "reload-result")) { + ServiceResult f; + + f = service_result_from_string(value); + if (f < 0) + log_unit_debug(u, "Failed to parse reload result value: %s", value); + else if (f != SERVICE_SUCCESS) + s->reload_result = f; + + } else if (streq(key, "control-pid")) { + pid_t pid; + + if (parse_pid(value, &pid) < 0) + log_unit_debug(u, "Failed to parse control-pid value: %s", value); + else + s->control_pid = pid; + } else if (streq(key, "main-pid")) { + pid_t pid; + + if (parse_pid(value, &pid) < 0) + log_unit_debug(u, "Failed to parse main-pid value: %s", value); + else + (void) service_set_main_pid(s, pid); + } else if (streq(key, "main-pid-known")) { + int b; + + b = parse_boolean(value); + if (b < 0) + log_unit_debug(u, "Failed to parse main-pid-known value: %s", value); + else + s->main_pid_known = b; + } else if (streq(key, "bus-name-good")) { + int b; + + b = parse_boolean(value); + if (b < 0) + log_unit_debug(u, "Failed to parse bus-name-good value: %s", value); + else + s->bus_name_good = b; + } else if (streq(key, "bus-name-owner")) { + r = free_and_strdup(&s->bus_name_owner, value); + if (r < 0) + log_unit_error_errno(u, r, "Unable to deserialize current bus owner %s: %m", value); + } else if (streq(key, "status-text")) { + char *t; + + r = cunescape(value, 0, &t); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to unescape status text '%s': %m", value); + else + free_and_replace(s->status_text, t); + + } else if (streq(key, "accept-socket")) { + Unit *socket; + + r = manager_load_unit(u->manager, value, NULL, NULL, &socket); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to load accept-socket unit '%s': %m", value); + else { + unit_ref_set(&s->accept_socket, u, socket); + SOCKET(socket)->n_connections++; + } + + } else if (streq(key, "socket-fd")) { + int fd; + + if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse socket-fd value: %s", value); + else { + asynchronous_close(s->socket_fd); + s->socket_fd = fdset_remove(fds, fd); + } + } else if (streq(key, "fd-store-fd")) { + const char *fdv; + size_t pf; + int fd; + + pf = strcspn(value, WHITESPACE); + fdv = strndupa(value, pf); + + if (safe_atoi(fdv, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse fd-store-fd value: %s", value); + else { + _cleanup_free_ char *t = NULL; + const char *fdn; + + fdn = value + pf; + fdn += strspn(fdn, WHITESPACE); + (void) cunescape(fdn, 0, &t); + + r = service_add_fd_store(s, fd, t); + if (r < 0) + log_unit_error_errno(u, r, "Failed to add fd to store: %m"); + else + fdset_remove(fds, fd); + } + + } else if (streq(key, "main-exec-status-pid")) { + pid_t pid; + + if (parse_pid(value, &pid) < 0) + log_unit_debug(u, "Failed to parse main-exec-status-pid value: %s", value); + else + s->main_exec_status.pid = pid; + } else if (streq(key, "main-exec-status-code")) { + int i; + + if (safe_atoi(value, &i) < 0) + log_unit_debug(u, "Failed to parse main-exec-status-code value: %s", value); + else + s->main_exec_status.code = i; + } else if (streq(key, "main-exec-status-status")) { + int i; + + if (safe_atoi(value, &i) < 0) + log_unit_debug(u, "Failed to parse main-exec-status-status value: %s", value); + else + s->main_exec_status.status = i; + } else if (streq(key, "main-exec-status-start")) + deserialize_dual_timestamp(value, &s->main_exec_status.start_timestamp); + else if (streq(key, "main-exec-status-exit")) + deserialize_dual_timestamp(value, &s->main_exec_status.exit_timestamp); + else if (streq(key, "watchdog-timestamp")) + deserialize_dual_timestamp(value, &s->watchdog_timestamp); + else if (streq(key, "forbid-restart")) { + int b; + + b = parse_boolean(value); + if (b < 0) + log_unit_debug(u, "Failed to parse forbid-restart value: %s", value); + else + s->forbid_restart = b; + } else if (streq(key, "stdin-fd")) { + int fd; + + if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse stdin-fd value: %s", value); + else { + asynchronous_close(s->stdin_fd); + s->stdin_fd = fdset_remove(fds, fd); + s->exec_context.stdio_as_fds = true; + } + } else if (streq(key, "stdout-fd")) { + int fd; + + if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse stdout-fd value: %s", value); + else { + asynchronous_close(s->stdout_fd); + s->stdout_fd = fdset_remove(fds, fd); + s->exec_context.stdio_as_fds = true; + } + } else if (streq(key, "stderr-fd")) { + int fd; + + if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse stderr-fd value: %s", value); + else { + asynchronous_close(s->stderr_fd); + s->stderr_fd = fdset_remove(fds, fd); + s->exec_context.stdio_as_fds = true; + } + } else if (streq(key, "exec-fd")) { + int fd; + + if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse exec-fd value: %s", value); + else { + s->exec_fd_event_source = sd_event_source_unref(s->exec_fd_event_source); + + fd = fdset_remove(fds, fd); + if (service_allocate_exec_fd_event_source(s, fd, &s->exec_fd_event_source) < 0) + safe_close(fd); + } + } else if (streq(key, "watchdog-override-usec")) { + if (deserialize_usec(value, &s->watchdog_override_usec) < 0) + log_unit_debug(u, "Failed to parse watchdog_override_usec value: %s", value); + else + s->watchdog_override_enable = true; + + } else if (streq(key, "watchdog-original-usec")) { + if (deserialize_usec(value, &s->watchdog_original_usec) < 0) + log_unit_debug(u, "Failed to parse watchdog_original_usec value: %s", value); + + } else if (STR_IN_SET(key, "main-command", "control-command")) { + r = service_deserialize_exec_command(u, key, value); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to parse serialized command \"%s\": %m", value); + + } else if (streq(key, "n-restarts")) { + r = safe_atou(value, &s->n_restarts); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to parse serialized restart counter '%s': %m", value); + + } else if (streq(key, "flush-n-restarts")) { + r = parse_boolean(value); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to parse serialized flush restart counter setting '%s': %m", value); + else + s->flush_n_restarts = r; + } else + log_unit_debug(u, "Unknown serialization key: %s", key); + + return 0; +} + +_pure_ static UnitActiveState service_active_state(Unit *u) { + const UnitActiveState *table; + + assert(u); + + table = SERVICE(u)->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table; + + return table[SERVICE(u)->state]; +} + +static const char *service_sub_state_to_string(Unit *u) { + assert(u); + + return service_state_to_string(SERVICE(u)->state); +} + +static bool service_may_gc(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + /* Never clean up services that still have a process around, even if the service is formally dead. Note that + * unit_may_gc() already checked our cgroup for us, we just check our two additional PIDs, too, in case they + * have moved outside of the cgroup. */ + + if (main_pid_good(s) > 0 || + control_pid_good(s) > 0) + return false; + + return true; +} + +static int service_retry_pid_file(Service *s) { + int r; + + assert(s->pid_file); + assert(IN_SET(s->state, SERVICE_START, SERVICE_START_POST)); + + r = service_load_pid_file(s, false); + if (r < 0) + return r; + + service_unwatch_pid_file(s); + + service_enter_running(s, SERVICE_SUCCESS); + return 0; +} + +static int service_watch_pid_file(Service *s) { + int r; + + log_unit_debug(UNIT(s), "Setting watch for PID file %s", s->pid_file_pathspec->path); + + r = path_spec_watch(s->pid_file_pathspec, service_dispatch_inotify_io); + if (r < 0) + goto fail; + + /* the pidfile might have appeared just before we set the watch */ + log_unit_debug(UNIT(s), "Trying to read PID file %s in case it changed", s->pid_file_pathspec->path); + service_retry_pid_file(s); + + return 0; +fail: + log_unit_error_errno(UNIT(s), r, "Failed to set a watch for PID file %s: %m", s->pid_file_pathspec->path); + service_unwatch_pid_file(s); + return r; +} + +static int service_demand_pid_file(Service *s) { + PathSpec *ps; + + assert(s->pid_file); + assert(!s->pid_file_pathspec); + + ps = new0(PathSpec, 1); + if (!ps) + return -ENOMEM; + + ps->unit = UNIT(s); + ps->path = strdup(s->pid_file); + if (!ps->path) { + free(ps); + return -ENOMEM; + } + + path_simplify(ps->path, false); + + /* PATH_CHANGED would not be enough. There are daemons (sendmail) that + * keep their PID file open all the time. */ + ps->type = PATH_MODIFIED; + ps->inotify_fd = -1; + + s->pid_file_pathspec = ps; + + return service_watch_pid_file(s); +} + +static int service_dispatch_inotify_io(sd_event_source *source, int fd, uint32_t events, void *userdata) { + PathSpec *p = userdata; + Service *s; + + assert(p); + + s = SERVICE(p->unit); + + assert(s); + assert(fd >= 0); + assert(IN_SET(s->state, SERVICE_START, SERVICE_START_POST)); + assert(s->pid_file_pathspec); + assert(path_spec_owns_inotify_fd(s->pid_file_pathspec, fd)); + + log_unit_debug(UNIT(s), "inotify event"); + + if (path_spec_fd_event(p, events) < 0) + goto fail; + + if (service_retry_pid_file(s) == 0) + return 0; + + if (service_watch_pid_file(s) < 0) + goto fail; + + return 0; + +fail: + service_unwatch_pid_file(s); + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); + return 0; +} + +static int service_dispatch_exec_io(sd_event_source *source, int fd, uint32_t events, void *userdata) { + Service *s = SERVICE(userdata); + + assert(s); + + log_unit_debug(UNIT(s), "got exec-fd event"); + + /* If Type=exec is set, we'll consider a service started successfully the instant we invoked execve() + * successfully for it. We implement this through a pipe() towards the child, which the kernel automatically + * closes for us due to O_CLOEXEC on execve() in the child, which then triggers EOF on the pipe in the + * parent. We need to be careful however, as there are other reasons that we might cause the child's side of + * the pipe to be closed (for example, a simple exit()). To deal with that we'll ignore EOFs on the pipe unless + * the child signalled us first that it is about to call the execve(). It does so by sending us a simple + * non-zero byte via the pipe. We also provide the child with a way to inform us in case execve() failed: if it + * sends a zero byte we'll ignore POLLHUP on the fd again. */ + + for (;;) { + uint8_t x; + ssize_t n; + + n = read(fd, &x, sizeof(x)); + if (n < 0) { + if (errno == EAGAIN) /* O_NONBLOCK in effect → everything queued has now been processed. */ + return 0; + + return log_unit_error_errno(UNIT(s), errno, "Failed to read from exec_fd: %m"); + } + if (n == 0) { /* EOF → the event we are waiting for */ + + s->exec_fd_event_source = sd_event_source_unref(s->exec_fd_event_source); + + if (s->exec_fd_hot) { /* Did the child tell us to expect EOF now? */ + log_unit_debug(UNIT(s), "Got EOF on exec-fd"); + + s->exec_fd_hot = false; + + /* Nice! This is what we have been waiting for. Transition to next state. */ + if (s->type == SERVICE_EXEC && s->state == SERVICE_START) + service_enter_start_post(s); + } else + log_unit_debug(UNIT(s), "Got EOF on exec-fd while it was disabled, ignoring."); + + return 0; + } + + /* A byte was read → this turns on/off the exec fd logic */ + assert(n == sizeof(x)); + s->exec_fd_hot = x; + } + + return 0; +} + +static void service_notify_cgroup_empty_event(Unit *u) { + Service *s = SERVICE(u); + + assert(u); + + log_unit_debug(u, "Control group is empty."); + + switch (s->state) { + + /* Waiting for SIGCHLD is usually more interesting, + * because it includes return codes/signals. Which is + * why we ignore the cgroup events for most cases, + * except when we don't know pid which to expect the + * SIGCHLD for. */ + + case SERVICE_START: + if (s->type == SERVICE_NOTIFY && + main_pid_good(s) == 0 && + control_pid_good(s) == 0) { + /* No chance of getting a ready notification anymore */ + service_enter_stop_post(s, SERVICE_FAILURE_PROTOCOL); + break; + } + + _fallthrough_; + case SERVICE_START_POST: + if (s->pid_file_pathspec && + main_pid_good(s) == 0 && + control_pid_good(s) == 0) { + + /* Give up hoping for the daemon to write its PID file */ + log_unit_warning(u, "Daemon never wrote its PID file. Failing."); + + service_unwatch_pid_file(s); + if (s->state == SERVICE_START) + service_enter_stop_post(s, SERVICE_FAILURE_PROTOCOL); + else + service_enter_stop(s, SERVICE_FAILURE_PROTOCOL); + } + break; + + case SERVICE_RUNNING: + /* service_enter_running() will figure out what to do */ + service_enter_running(s, SERVICE_SUCCESS); + break; + + case SERVICE_STOP_WATCHDOG: + case SERVICE_STOP_SIGTERM: + case SERVICE_STOP_SIGKILL: + + if (main_pid_good(s) <= 0 && control_pid_good(s) <= 0) + service_enter_stop_post(s, SERVICE_SUCCESS); + + break; + + case SERVICE_STOP_POST: + case SERVICE_FINAL_SIGTERM: + case SERVICE_FINAL_SIGKILL: + if (main_pid_good(s) <= 0 && control_pid_good(s) <= 0) + service_enter_dead(s, SERVICE_SUCCESS, true); + + break; + + default: + ; + } +} + +static void service_notify_cgroup_oom_event(Unit *u) { + Service *s = SERVICE(u); + + log_unit_debug(u, "Process of control group was killed by the OOM killer."); + + if (s->oom_policy == OOM_CONTINUE) + return; + + switch (s->state) { + + case SERVICE_CONDITION: + case SERVICE_START_PRE: + case SERVICE_START: + case SERVICE_START_POST: + case SERVICE_STOP: + if (s->oom_policy == OOM_STOP) + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_OOM_KILL); + else if (s->oom_policy == OOM_KILL) + service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_OOM_KILL); + + break; + + case SERVICE_EXITED: + case SERVICE_RUNNING: + if (s->oom_policy == OOM_STOP) + service_enter_stop(s, SERVICE_FAILURE_OOM_KILL); + else if (s->oom_policy == OOM_KILL) + service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_OOM_KILL); + + break; + + case SERVICE_STOP_WATCHDOG: + case SERVICE_STOP_SIGTERM: + service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_OOM_KILL); + break; + + case SERVICE_STOP_SIGKILL: + case SERVICE_FINAL_SIGKILL: + if (s->result == SERVICE_SUCCESS) + s->result = SERVICE_FAILURE_OOM_KILL; + break; + + case SERVICE_STOP_POST: + case SERVICE_FINAL_SIGTERM: + service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_OOM_KILL); + break; + + default: + ; + } +} + +static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + bool notify_dbus = true; + Service *s = SERVICE(u); + ServiceResult f; + ExitClean clean_mode; + + assert(s); + assert(pid >= 0); + + /* Oneshot services and non-SERVICE_EXEC_START commands should not be + * considered daemons as they are typically not long running. */ + if (s->type == SERVICE_ONESHOT || (s->control_pid == pid && s->control_command_id != SERVICE_EXEC_START)) + clean_mode = EXIT_CLEAN_COMMAND; + else + clean_mode = EXIT_CLEAN_DAEMON; + + if (is_clean_exit(code, status, clean_mode, &s->success_status)) + f = SERVICE_SUCCESS; + else if (code == CLD_EXITED) + f = SERVICE_FAILURE_EXIT_CODE; + else if (code == CLD_KILLED) + f = SERVICE_FAILURE_SIGNAL; + else if (code == CLD_DUMPED) + f = SERVICE_FAILURE_CORE_DUMP; + else + assert_not_reached("Unknown code"); + + if (s->main_pid == pid) { + /* Forking services may occasionally move to a new PID. + * As long as they update the PID file before exiting the old + * PID, they're fine. */ + if (service_load_pid_file(s, false) > 0) + return; + + s->main_pid = 0; + exec_status_exit(&s->main_exec_status, &s->exec_context, pid, code, status); + + if (s->main_command) { + /* If this is not a forking service than the + * main process got started and hence we copy + * the exit status so that it is recorded both + * as main and as control process exit + * status */ + + s->main_command->exec_status = s->main_exec_status; + + if (s->main_command->flags & EXEC_COMMAND_IGNORE_FAILURE) + f = SERVICE_SUCCESS; + } else if (s->exec_command[SERVICE_EXEC_START]) { + + /* If this is a forked process, then we should + * ignore the return value if this was + * configured for the starter process */ + + if (s->exec_command[SERVICE_EXEC_START]->flags & EXEC_COMMAND_IGNORE_FAILURE) + f = SERVICE_SUCCESS; + } + + unit_log_process_exit( + u, + "Main process", + service_exec_command_to_string(SERVICE_EXEC_START), + f == SERVICE_SUCCESS, + code, status); + + if (s->result == SERVICE_SUCCESS) + s->result = f; + + if (s->main_command && + s->main_command->command_next && + s->type == SERVICE_ONESHOT && + f == SERVICE_SUCCESS) { + + /* There is another command to * + * execute, so let's do that. */ + + log_unit_debug(u, "Running next main command for state %s.", service_state_to_string(s->state)); + service_run_next_main(s); + + } else { + + /* The service exited, so the service is officially + * gone. */ + s->main_command = NULL; + + switch (s->state) { + + case SERVICE_START_POST: + case SERVICE_RELOAD: + case SERVICE_STOP: + /* Need to wait until the operation is + * done */ + break; + + case SERVICE_START: + if (s->type == SERVICE_ONESHOT) { + /* This was our main goal, so let's go on */ + if (f == SERVICE_SUCCESS) + service_enter_start_post(s); + else + service_enter_signal(s, SERVICE_STOP_SIGTERM, f); + break; + } else if (s->type == SERVICE_NOTIFY) { + /* Only enter running through a notification, so that the + * SERVICE_START state signifies that no ready notification + * has been received */ + if (f != SERVICE_SUCCESS) + service_enter_signal(s, SERVICE_STOP_SIGTERM, f); + else if (!s->remain_after_exit || s->notify_access == NOTIFY_MAIN) + /* The service has never been and will never be active */ + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL); + break; + } + + _fallthrough_; + case SERVICE_RUNNING: + service_enter_running(s, f); + break; + + case SERVICE_STOP_WATCHDOG: + case SERVICE_STOP_SIGTERM: + case SERVICE_STOP_SIGKILL: + + if (control_pid_good(s) <= 0) + service_enter_stop_post(s, f); + + /* If there is still a control process, wait for that first */ + break; + + case SERVICE_STOP_POST: + case SERVICE_FINAL_SIGTERM: + case SERVICE_FINAL_SIGKILL: + + if (control_pid_good(s) <= 0) + service_enter_dead(s, f, true); + break; + + default: + assert_not_reached("Uh, main process died at wrong time."); + } + } + + } else if (s->control_pid == pid) { + s->control_pid = 0; + + /* ExecCondition= calls that exit with (0, 254] should invoke skip-like behavior instead of failing */ + if (f == SERVICE_FAILURE_EXIT_CODE && s->state == SERVICE_CONDITION && status < 255) + f = SERVICE_SKIP_CONDITION; + + if (s->control_command) { + exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status); + + if (s->control_command->flags & EXEC_COMMAND_IGNORE_FAILURE) + f = SERVICE_SUCCESS; + } + + unit_log_process_exit( + u, + "Control process", + service_exec_command_to_string(s->control_command_id), + f == SERVICE_SUCCESS, + code, status); + + if (s->state != SERVICE_RELOAD && s->result == SERVICE_SUCCESS) + s->result = f; + + if (s->control_command && + s->control_command->command_next && + f == SERVICE_SUCCESS) { + + /* There is another command to * + * execute, so let's do that. */ + + log_unit_debug(u, "Running next control command for state %s.", service_state_to_string(s->state)); + service_run_next_control(s); + + } else { + /* No further commands for this step, so let's + * figure out what to do next */ + + s->control_command = NULL; + s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; + + log_unit_debug(u, "Got final SIGCHLD for state %s.", service_state_to_string(s->state)); + + switch (s->state) { + + case SERVICE_CONDITION: + if (f == SERVICE_SUCCESS) + service_enter_start_pre(s); + else + service_enter_signal(s, SERVICE_STOP_SIGTERM, f); + break; + + case SERVICE_START_PRE: + if (f == SERVICE_SUCCESS) + service_enter_start(s); + else + service_enter_signal(s, SERVICE_STOP_SIGTERM, f); + break; + + case SERVICE_START: + if (s->type != SERVICE_FORKING) + /* Maybe spurious event due to a reload that changed the type? */ + break; + + if (f != SERVICE_SUCCESS) { + service_enter_signal(s, SERVICE_STOP_SIGTERM, f); + break; + } + + if (s->pid_file) { + bool has_start_post; + int r; + + /* Let's try to load the pid file here if we can. + * The PID file might actually be created by a START_POST + * script. In that case don't worry if the loading fails. */ + + has_start_post = s->exec_command[SERVICE_EXEC_START_POST]; + r = service_load_pid_file(s, !has_start_post); + if (!has_start_post && r < 0) { + r = service_demand_pid_file(s); + if (r < 0 || cgroup_good(s) == 0) + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL); + break; + } + } else + service_search_main_pid(s); + + service_enter_start_post(s); + break; + + case SERVICE_START_POST: + if (f != SERVICE_SUCCESS) { + service_enter_signal(s, SERVICE_STOP_SIGTERM, f); + break; + } + + if (s->pid_file) { + int r; + + r = service_load_pid_file(s, true); + if (r < 0) { + r = service_demand_pid_file(s); + if (r < 0 || cgroup_good(s) == 0) + service_enter_stop(s, SERVICE_FAILURE_PROTOCOL); + break; + } + } else + service_search_main_pid(s); + + service_enter_running(s, SERVICE_SUCCESS); + break; + + case SERVICE_RELOAD: + if (f == SERVICE_SUCCESS) + if (service_load_pid_file(s, true) < 0) + service_search_main_pid(s); + + s->reload_result = f; + service_enter_running(s, SERVICE_SUCCESS); + break; + + case SERVICE_STOP: + service_enter_signal(s, SERVICE_STOP_SIGTERM, f); + break; + + case SERVICE_STOP_WATCHDOG: + case SERVICE_STOP_SIGTERM: + case SERVICE_STOP_SIGKILL: + if (main_pid_good(s) <= 0) + service_enter_stop_post(s, f); + + /* If there is still a service process around, wait until + * that one quit, too */ + break; + + case SERVICE_STOP_POST: + case SERVICE_FINAL_SIGTERM: + case SERVICE_FINAL_SIGKILL: + if (main_pid_good(s) <= 0) + service_enter_dead(s, f, true); + break; + + case SERVICE_CLEANING: + + if (s->clean_result == SERVICE_SUCCESS) + s->clean_result = f; + + service_enter_dead(s, SERVICE_SUCCESS, false); + break; + + default: + assert_not_reached("Uh, control process died at wrong time."); + } + } + } else /* Neither control nor main PID? If so, don't notify about anything */ + notify_dbus = false; + + /* Notify clients about changed exit status */ + if (notify_dbus) + unit_add_to_dbus_queue(u); + + /* We watch the main/control process otherwise we can't retrieve the unit they + * belong to with cgroupv1. But if they are not our direct child, we won't get a + * SIGCHLD for them. Therefore we need to look for others to watch so we can + * detect when the cgroup becomes empty. Note that the control process is always + * our child so it's pointless to watch all other processes. */ + if (!control_pid_good(s)) + if (!s->main_pid_known || s->main_pid_alien) + (void) unit_enqueue_rewatch_pids(u); +} + +static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { + Service *s = SERVICE(userdata); + + assert(s); + assert(source == s->timer_event_source); + + switch (s->state) { + + case SERVICE_CONDITION: + case SERVICE_START_PRE: + case SERVICE_START: + log_unit_warning(UNIT(s), "%s operation timed out. Terminating.", service_state_to_string(s->state)); + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); + break; + + case SERVICE_START_POST: + log_unit_warning(UNIT(s), "Start-post operation timed out. Stopping."); + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); + break; + + case SERVICE_RUNNING: + log_unit_warning(UNIT(s), "Service reached runtime time limit. Stopping."); + service_enter_stop(s, SERVICE_FAILURE_TIMEOUT); + break; + + case SERVICE_RELOAD: + log_unit_warning(UNIT(s), "Reload operation timed out. Killing reload process."); + service_kill_control_process(s); + s->reload_result = SERVICE_FAILURE_TIMEOUT; + service_enter_running(s, SERVICE_SUCCESS); + break; + + case SERVICE_STOP: + log_unit_warning(UNIT(s), "Stopping timed out. Terminating."); + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); + break; + + case SERVICE_STOP_WATCHDOG: + log_unit_warning(UNIT(s), "State 'stop-watchdog' timed out. Terminating."); + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); + break; + + case SERVICE_STOP_SIGTERM: + if (s->kill_context.send_sigkill) { + log_unit_warning(UNIT(s), "State 'stop-sigterm' timed out. Killing."); + service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT); + } else { + log_unit_warning(UNIT(s), "State 'stop-sigterm' timed out. Skipping SIGKILL."); + service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT); + } + + break; + + case SERVICE_STOP_SIGKILL: + /* Uh, we sent a SIGKILL and it is still not gone? + * Must be something we cannot kill, so let's just be + * weirded out and continue */ + + log_unit_warning(UNIT(s), "Processes still around after SIGKILL. Ignoring."); + service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT); + break; + + case SERVICE_STOP_POST: + log_unit_warning(UNIT(s), "State 'stop-post' timed out. Terminating."); + service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT); + break; + + case SERVICE_FINAL_SIGTERM: + if (s->kill_context.send_sigkill) { + log_unit_warning(UNIT(s), "State 'stop-final-sigterm' timed out. Killing."); + service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT); + } else { + log_unit_warning(UNIT(s), "State 'stop-final-sigterm' timed out. Skipping SIGKILL. Entering failed mode."); + service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false); + } + + break; + + case SERVICE_FINAL_SIGKILL: + log_unit_warning(UNIT(s), "Processes still around after final SIGKILL. Entering failed mode."); + service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, true); + break; + + case SERVICE_AUTO_RESTART: + if (s->restart_usec > 0) { + char buf_restart[FORMAT_TIMESPAN_MAX]; + log_unit_debug(UNIT(s), + "Service RestartSec=%s expired, scheduling restart.", + format_timespan(buf_restart, sizeof buf_restart, s->restart_usec, USEC_PER_SEC)); + } else + log_unit_debug(UNIT(s), + "Service has no hold-off time (RestartSec=0), scheduling restart."); + + service_enter_restart(s); + break; + + case SERVICE_CLEANING: + log_unit_warning(UNIT(s), "Cleaning timed out. killing."); + + if (s->clean_result == SERVICE_SUCCESS) + s->clean_result = SERVICE_FAILURE_TIMEOUT; + + service_enter_signal(s, SERVICE_FINAL_SIGKILL, 0); + break; + + default: + assert_not_reached("Timeout at wrong time."); + } + + return 0; +} + +static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata) { + Service *s = SERVICE(userdata); + char t[FORMAT_TIMESPAN_MAX]; + usec_t watchdog_usec; + + assert(s); + assert(source == s->watchdog_event_source); + + watchdog_usec = service_get_watchdog_usec(s); + + if (UNIT(s)->manager->service_watchdogs) { + log_unit_error(UNIT(s), "Watchdog timeout (limit %s)!", + format_timespan(t, sizeof(t), watchdog_usec, 1)); + + service_enter_signal(s, SERVICE_STOP_WATCHDOG, SERVICE_FAILURE_WATCHDOG); + } else + log_unit_warning(UNIT(s), "Watchdog disabled! Ignoring watchdog timeout (limit %s)!", + format_timespan(t, sizeof(t), watchdog_usec, 1)); + + return 0; +} + +static bool service_notify_message_authorized(Service *s, pid_t pid, char **tags, FDSet *fds) { + assert(s); + + if (s->notify_access == NOTIFY_NONE) { + log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception is disabled.", pid); + return false; + } + + if (s->notify_access == NOTIFY_MAIN && pid != s->main_pid) { + if (s->main_pid != 0) + log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid); + else + log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID which is currently not known", pid); + + return false; + } + + if (s->notify_access == NOTIFY_EXEC && pid != s->main_pid && pid != s->control_pid) { + if (s->main_pid != 0 && s->control_pid != 0) + log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT" and control PID "PID_FMT, + pid, s->main_pid, s->control_pid); + else if (s->main_pid != 0) + log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid); + else if (s->control_pid != 0) + log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for control PID "PID_FMT, pid, s->control_pid); + else + log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID and control PID which are currently not known", pid); + + return false; + } + + return true; +} + +static void service_force_watchdog(Service *s) { + if (!UNIT(s)->manager->service_watchdogs) + return; + + log_unit_error(UNIT(s), "Watchdog request (last status: %s)!", + s->status_text ? s->status_text : ""); + + service_enter_signal(s, SERVICE_STOP_WATCHDOG, SERVICE_FAILURE_WATCHDOG); +} + +static void service_notify_message( + Unit *u, + const struct ucred *ucred, + char **tags, + FDSet *fds) { + + Service *s = SERVICE(u); + bool notify_dbus = false; + const char *e; + char **i; + int r; + + assert(u); + assert(ucred); + + if (!service_notify_message_authorized(SERVICE(u), ucred->pid, tags, fds)) + return; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *cc = NULL; + + cc = strv_join(tags, ", "); + log_unit_debug(u, "Got notification message from PID "PID_FMT" (%s)", ucred->pid, isempty(cc) ? "n/a" : cc); + } + + /* Interpret MAINPID= */ + e = strv_find_startswith(tags, "MAINPID="); + if (e && IN_SET(s->state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) { + pid_t new_main_pid; + + if (parse_pid(e, &new_main_pid) < 0) + log_unit_warning(u, "Failed to parse MAINPID= field in notification message, ignoring: %s", e); + else if (!s->main_pid_known || new_main_pid != s->main_pid) { + + r = service_is_suitable_main_pid(s, new_main_pid, LOG_WARNING); + if (r == 0) { + /* The new main PID is a bit suspicious, which is OK if the sender is privileged. */ + + if (ucred->uid == 0) { + log_unit_debug(u, "New main PID "PID_FMT" does not belong to service, but we'll accept it as the request to change it came from a privileged process.", new_main_pid); + r = 1; + } else + log_unit_debug(u, "New main PID "PID_FMT" does not belong to service, refusing.", new_main_pid); + } + if (r > 0) { + service_set_main_pid(s, new_main_pid); + + r = unit_watch_pid(UNIT(s), new_main_pid, false); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "Failed to watch new main PID "PID_FMT" for service: %m", new_main_pid); + + notify_dbus = true; + } + } + } + + /* Interpret READY=/STOPPING=/RELOADING=. Last one wins. */ + STRV_FOREACH_BACKWARDS(i, tags) { + + if (streq(*i, "READY=1")) { + s->notify_state = NOTIFY_READY; + + /* Type=notify services inform us about completed + * initialization with READY=1 */ + if (s->type == SERVICE_NOTIFY && s->state == SERVICE_START) + service_enter_start_post(s); + + /* Sending READY=1 while we are reloading informs us + * that the reloading is complete */ + if (s->state == SERVICE_RELOAD && s->control_pid == 0) + service_enter_running(s, SERVICE_SUCCESS); + + notify_dbus = true; + break; + + } else if (streq(*i, "RELOADING=1")) { + s->notify_state = NOTIFY_RELOADING; + + if (s->state == SERVICE_RUNNING) + service_enter_reload_by_notify(s); + + notify_dbus = true; + break; + + } else if (streq(*i, "STOPPING=1")) { + s->notify_state = NOTIFY_STOPPING; + + if (s->state == SERVICE_RUNNING) + service_enter_stop_by_notify(s); + + notify_dbus = true; + break; + } + } + + /* Interpret STATUS= */ + e = strv_find_startswith(tags, "STATUS="); + if (e) { + _cleanup_free_ char *t = NULL; + + if (!isempty(e)) { + /* Note that this size limit check is mostly paranoia: since the datagram size we are willing + * to process is already limited to NOTIFY_BUFFER_MAX, this limit here should never be hit. */ + if (strlen(e) > STATUS_TEXT_MAX) + log_unit_warning(u, "Status message overly long (%zu > %u), ignoring.", strlen(e), STATUS_TEXT_MAX); + else if (!utf8_is_valid(e)) + log_unit_warning(u, "Status message in notification message is not UTF-8 clean, ignoring."); + else { + t = strdup(e); + if (!t) + log_oom(); + } + } + + if (!streq_ptr(s->status_text, t)) { + free_and_replace(s->status_text, t); + notify_dbus = true; + } + } + + /* Interpret ERRNO= */ + e = strv_find_startswith(tags, "ERRNO="); + if (e) { + int status_errno; + + status_errno = parse_errno(e); + if (status_errno < 0) + log_unit_warning_errno(u, status_errno, + "Failed to parse ERRNO= field value '%s' in notification message: %m", e); + else if (s->status_errno != status_errno) { + s->status_errno = status_errno; + notify_dbus = true; + } + } + + /* Interpret EXTEND_TIMEOUT= */ + e = strv_find_startswith(tags, "EXTEND_TIMEOUT_USEC="); + if (e) { + usec_t extend_timeout_usec; + if (safe_atou64(e, &extend_timeout_usec) < 0) + log_unit_warning(u, "Failed to parse EXTEND_TIMEOUT_USEC=%s", e); + else + service_extend_timeout(s, extend_timeout_usec); + } + + /* Interpret WATCHDOG= */ + e = strv_find_startswith(tags, "WATCHDOG="); + if (e) { + if (streq(e, "1")) + service_reset_watchdog(s); + else if (streq(e, "trigger")) + service_force_watchdog(s); + else + log_unit_warning(u, "Passed WATCHDOG= field is invalid, ignoring."); + } + + e = strv_find_startswith(tags, "WATCHDOG_USEC="); + if (e) { + usec_t watchdog_override_usec; + if (safe_atou64(e, &watchdog_override_usec) < 0) + log_unit_warning(u, "Failed to parse WATCHDOG_USEC=%s", e); + else + service_override_watchdog_timeout(s, watchdog_override_usec); + } + + /* Process FD store messages. Either FDSTOREREMOVE=1 for removal, or FDSTORE=1 for addition. In both cases, + * process FDNAME= for picking the file descriptor name to use. Note that FDNAME= is required when removing + * fds, but optional when pushing in new fds, for compatibility reasons. */ + if (strv_find(tags, "FDSTOREREMOVE=1")) { + const char *name; + + name = strv_find_startswith(tags, "FDNAME="); + if (!name || !fdname_is_valid(name)) + log_unit_warning(u, "FDSTOREREMOVE=1 requested, but no valid file descriptor name passed, ignoring."); + else + service_remove_fd_store(s, name); + + } else if (strv_find(tags, "FDSTORE=1")) { + const char *name; + + name = strv_find_startswith(tags, "FDNAME="); + if (name && !fdname_is_valid(name)) { + log_unit_warning(u, "Passed FDNAME= name is invalid, ignoring."); + name = NULL; + } + + (void) service_add_fd_store_set(s, fds, name); + } + + /* Notify clients about changed status or main pid */ + if (notify_dbus) + unit_add_to_dbus_queue(u); +} + +static int service_get_timeout(Unit *u, usec_t *timeout) { + Service *s = SERVICE(u); + uint64_t t; + int r; + + if (!s->timer_event_source) + return 0; + + r = sd_event_source_get_time(s->timer_event_source, &t); + if (r < 0) + return r; + if (t == USEC_INFINITY) + return 0; + + *timeout = t; + return 1; +} + +static void service_bus_name_owner_change( + Unit *u, + const char *old_owner, + const char *new_owner) { + + Service *s = SERVICE(u); + int r; + + assert(s); + + assert(old_owner || new_owner); + + if (old_owner && new_owner) + log_unit_debug(u, "D-Bus name %s changed owner from %s to %s", s->bus_name, old_owner, new_owner); + else if (old_owner) + log_unit_debug(u, "D-Bus name %s no longer registered by %s", s->bus_name, old_owner); + else + log_unit_debug(u, "D-Bus name %s now registered by %s", s->bus_name, new_owner); + + s->bus_name_good = !!new_owner; + + /* Track the current owner, so we can reconstruct changes after a daemon reload */ + r = free_and_strdup(&s->bus_name_owner, new_owner); + if (r < 0) { + log_unit_error_errno(u, r, "Unable to set new bus name owner %s: %m", new_owner); + return; + } + + if (s->type == SERVICE_DBUS) { + + /* service_enter_running() will figure out what to + * do */ + if (s->state == SERVICE_RUNNING) + service_enter_running(s, SERVICE_SUCCESS); + else if (s->state == SERVICE_START && new_owner) + service_enter_start_post(s); + + } else if (new_owner && + s->main_pid <= 0 && + IN_SET(s->state, + SERVICE_START, + SERVICE_START_POST, + SERVICE_RUNNING, + SERVICE_RELOAD)) { + + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + pid_t pid; + + /* Try to acquire PID from bus service */ + + r = sd_bus_get_name_creds(u->manager->api_bus, s->bus_name, SD_BUS_CREDS_PID, &creds); + if (r >= 0) + r = sd_bus_creds_get_pid(creds, &pid); + if (r >= 0) { + log_unit_debug(u, "D-Bus name %s is now owned by process " PID_FMT, s->bus_name, pid); + + service_set_main_pid(s, pid); + unit_watch_pid(UNIT(s), pid, false); + } + } +} + +int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context_net) { + _cleanup_free_ char *peer = NULL; + int r; + + assert(s); + assert(fd >= 0); + + /* This is called by the socket code when instantiating a new service for a stream socket and the socket needs + * to be configured. We take ownership of the passed fd on success. */ + + if (UNIT(s)->load_state != UNIT_LOADED) + return -EINVAL; + + if (s->socket_fd >= 0) + return -EBUSY; + + if (s->state != SERVICE_DEAD) + return -EAGAIN; + + if (getpeername_pretty(fd, true, &peer) >= 0) { + + if (UNIT(s)->description) { + _cleanup_free_ char *a; + + a = strjoin(UNIT(s)->description, " (", peer, ")"); + if (!a) + return -ENOMEM; + + r = unit_set_description(UNIT(s), a); + } else + r = unit_set_description(UNIT(s), peer); + + if (r < 0) + return r; + } + + r = unit_add_two_dependencies(UNIT(sock), UNIT_BEFORE, UNIT_TRIGGERS, UNIT(s), false, UNIT_DEPENDENCY_IMPLICIT); + if (r < 0) + return r; + + s->socket_fd = fd; + s->socket_fd_selinux_context_net = selinux_context_net; + + unit_ref_set(&s->accept_socket, UNIT(s), UNIT(sock)); + return 0; +} + +static void service_reset_failed(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + if (s->state == SERVICE_FAILED) + service_set_state(s, SERVICE_DEAD); + + s->result = SERVICE_SUCCESS; + s->reload_result = SERVICE_SUCCESS; + s->clean_result = SERVICE_SUCCESS; + s->n_restarts = 0; + s->flush_n_restarts = false; +} + +static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { + Service *s = SERVICE(u); + + assert(s); + + return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error); +} + +static int service_main_pid(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + return s->main_pid; +} + +static int service_control_pid(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + return s->control_pid; +} + +static bool service_needs_console(Unit *u) { + Service *s = SERVICE(u); + + assert(s); + + /* We provide our own implementation of this here, instead of relying of the generic implementation + * unit_needs_console() provides, since we want to return false if we are in SERVICE_EXITED state. */ + + if (!exec_context_may_touch_console(&s->exec_context)) + return false; + + return IN_SET(s->state, + SERVICE_CONDITION, + SERVICE_START_PRE, + SERVICE_START, + SERVICE_START_POST, + SERVICE_RUNNING, + SERVICE_RELOAD, + SERVICE_STOP, + SERVICE_STOP_WATCHDOG, + SERVICE_STOP_SIGTERM, + SERVICE_STOP_SIGKILL, + SERVICE_STOP_POST, + SERVICE_FINAL_SIGTERM, + SERVICE_FINAL_SIGKILL); +} + +static int service_exit_status(Unit *u) { + Service *s = SERVICE(u); + + assert(u); + + if (s->main_exec_status.pid <= 0 || + !dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) + return -ENODATA; + + if (s->main_exec_status.code != CLD_EXITED) + return -EBADE; + + return s->main_exec_status.status; +} + +static int service_clean(Unit *u, ExecCleanMask mask) { + _cleanup_strv_free_ char **l = NULL; + Service *s = SERVICE(u); + int r; + + assert(s); + assert(mask != 0); + + if (s->state != SERVICE_DEAD) + return -EBUSY; + + r = exec_context_get_clean_directories(&s->exec_context, u->manager->prefix, mask, &l); + if (r < 0) + return r; + + if (strv_isempty(l)) + return -EUNATCH; + + service_unwatch_control_pid(s); + s->clean_result = SERVICE_SUCCESS; + s->control_command = NULL; + s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; + + r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec)); + if (r < 0) + goto fail; + + r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid); + if (r < 0) + goto fail; + + service_set_state(s, SERVICE_CLEANING); + + return 0; + +fail: + log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m"); + s->clean_result = SERVICE_FAILURE_RESOURCES; + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + return r; +} + +static int service_can_clean(Unit *u, ExecCleanMask *ret) { + Service *s = SERVICE(u); + + assert(s); + + return exec_context_get_clean_mask(&s->exec_context, ret); +} + +static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { + [SERVICE_RESTART_NO] = "no", + [SERVICE_RESTART_ON_SUCCESS] = "on-success", + [SERVICE_RESTART_ON_FAILURE] = "on-failure", + [SERVICE_RESTART_ON_ABNORMAL] = "on-abnormal", + [SERVICE_RESTART_ON_WATCHDOG] = "on-watchdog", + [SERVICE_RESTART_ON_ABORT] = "on-abort", + [SERVICE_RESTART_ALWAYS] = "always", +}; + +DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart); + +static const char* const service_type_table[_SERVICE_TYPE_MAX] = { + [SERVICE_SIMPLE] = "simple", + [SERVICE_FORKING] = "forking", + [SERVICE_ONESHOT] = "oneshot", + [SERVICE_DBUS] = "dbus", + [SERVICE_NOTIFY] = "notify", + [SERVICE_IDLE] = "idle", + [SERVICE_EXEC] = "exec", +}; + +DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType); + +static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] = { + [SERVICE_EXEC_CONDITION] = "ExecCondition", + [SERVICE_EXEC_START_PRE] = "ExecStartPre", + [SERVICE_EXEC_START] = "ExecStart", + [SERVICE_EXEC_START_POST] = "ExecStartPost", + [SERVICE_EXEC_RELOAD] = "ExecReload", + [SERVICE_EXEC_STOP] = "ExecStop", + [SERVICE_EXEC_STOP_POST] = "ExecStopPost", +}; + +DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand); + +static const char* const service_exec_ex_command_table[_SERVICE_EXEC_COMMAND_MAX] = { + [SERVICE_EXEC_CONDITION] = "ExecConditionEx", + [SERVICE_EXEC_START_PRE] = "ExecStartPreEx", + [SERVICE_EXEC_START] = "ExecStartEx", + [SERVICE_EXEC_START_POST] = "ExecStartPostEx", + [SERVICE_EXEC_RELOAD] = "ExecReloadEx", + [SERVICE_EXEC_STOP] = "ExecStopEx", + [SERVICE_EXEC_STOP_POST] = "ExecStopPostEx", +}; + +DEFINE_STRING_TABLE_LOOKUP(service_exec_ex_command, ServiceExecCommand); + +static const char* const notify_state_table[_NOTIFY_STATE_MAX] = { + [NOTIFY_UNKNOWN] = "unknown", + [NOTIFY_READY] = "ready", + [NOTIFY_RELOADING] = "reloading", + [NOTIFY_STOPPING] = "stopping", +}; + +DEFINE_STRING_TABLE_LOOKUP(notify_state, NotifyState); + +static const char* const service_result_table[_SERVICE_RESULT_MAX] = { + [SERVICE_SUCCESS] = "success", + [SERVICE_FAILURE_RESOURCES] = "resources", + [SERVICE_FAILURE_PROTOCOL] = "protocol", + [SERVICE_FAILURE_TIMEOUT] = "timeout", + [SERVICE_FAILURE_EXIT_CODE] = "exit-code", + [SERVICE_FAILURE_SIGNAL] = "signal", + [SERVICE_FAILURE_CORE_DUMP] = "core-dump", + [SERVICE_FAILURE_WATCHDOG] = "watchdog", + [SERVICE_FAILURE_START_LIMIT_HIT] = "start-limit-hit", + [SERVICE_FAILURE_OOM_KILL] = "oom-kill", + [SERVICE_SKIP_CONDITION] = "exec-condition", +}; + +DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult); + +const UnitVTable service_vtable = { + .object_size = sizeof(Service), + .exec_context_offset = offsetof(Service, exec_context), + .cgroup_context_offset = offsetof(Service, cgroup_context), + .kill_context_offset = offsetof(Service, kill_context), + .exec_runtime_offset = offsetof(Service, exec_runtime), + .dynamic_creds_offset = offsetof(Service, dynamic_creds), + + .sections = + "Unit\0" + "Service\0" + "Install\0", + .private_section = "Service", + + .can_transient = true, + .can_delegate = true, + + .init = service_init, + .done = service_done, + .load = service_load, + .release_resources = service_release_resources, + + .coldplug = service_coldplug, + + .dump = service_dump, + + .start = service_start, + .stop = service_stop, + .reload = service_reload, + + .can_reload = service_can_reload, + + .kill = service_kill, + .clean = service_clean, + .can_clean = service_can_clean, + + .serialize = service_serialize, + .deserialize_item = service_deserialize_item, + + .active_state = service_active_state, + .sub_state_to_string = service_sub_state_to_string, + + .will_restart = service_will_restart, + + .may_gc = service_may_gc, + + .sigchld_event = service_sigchld_event, + + .reset_failed = service_reset_failed, + + .notify_cgroup_empty = service_notify_cgroup_empty_event, + .notify_cgroup_oom = service_notify_cgroup_oom_event, + .notify_message = service_notify_message, + + .main_pid = service_main_pid, + .control_pid = service_control_pid, + + .bus_name_owner_change = service_bus_name_owner_change, + + .bus_vtable = bus_service_vtable, + .bus_set_property = bus_service_set_property, + .bus_commit_properties = bus_service_commit_properties, + + .get_timeout = service_get_timeout, + .needs_console = service_needs_console, + .exit_status = service_exit_status, + + .status_message_formats = { + .starting_stopping = { + [0] = "Starting %s...", + [1] = "Stopping %s...", + }, + .finished_start_job = { + [JOB_DONE] = "Started %s.", + [JOB_FAILED] = "Failed to start %s.", + [JOB_SKIPPED] = "Skipped %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Stopped %s.", + [JOB_FAILED] = "Stopped (with error) %s.", + }, + }, +}; diff --git a/src/core/service.h b/src/core/service.h new file mode 100644 index 00000000..11e861a3 --- /dev/null +++ b/src/core/service.h @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Service Service; +typedef struct ServiceFDStore ServiceFDStore; + +#include "exit-status.h" +#include "kill.h" +#include "path.h" +#include "ratelimit.h" +#include "socket.h" +#include "unit.h" + +typedef enum ServiceRestart { + SERVICE_RESTART_NO, + SERVICE_RESTART_ON_SUCCESS, + SERVICE_RESTART_ON_FAILURE, + SERVICE_RESTART_ON_ABNORMAL, + SERVICE_RESTART_ON_WATCHDOG, + SERVICE_RESTART_ON_ABORT, + SERVICE_RESTART_ALWAYS, + _SERVICE_RESTART_MAX, + _SERVICE_RESTART_INVALID = -1 +} ServiceRestart; + +typedef enum ServiceType { + SERVICE_SIMPLE, /* we fork and go on right-away (i.e. modern socket activated daemons) */ + SERVICE_FORKING, /* forks by itself (i.e. traditional daemons) */ + SERVICE_ONESHOT, /* we fork and wait until the program finishes (i.e. programs like fsck which run and need to finish before we continue) */ + SERVICE_DBUS, /* we fork and wait until a specific D-Bus name appears on the bus */ + SERVICE_NOTIFY, /* we fork and wait until a daemon sends us a ready message with sd_notify() */ + SERVICE_IDLE, /* much like simple, but delay exec() until all jobs are dispatched. */ + SERVICE_EXEC, /* we fork and wait until we execute exec() (this means our own setup is waited for) */ + _SERVICE_TYPE_MAX, + _SERVICE_TYPE_INVALID = -1 +} ServiceType; + +typedef enum ServiceExecCommand { + SERVICE_EXEC_CONDITION, + SERVICE_EXEC_START_PRE, + SERVICE_EXEC_START, + SERVICE_EXEC_START_POST, + SERVICE_EXEC_RELOAD, + SERVICE_EXEC_STOP, + SERVICE_EXEC_STOP_POST, + _SERVICE_EXEC_COMMAND_MAX, + _SERVICE_EXEC_COMMAND_INVALID = -1 +} ServiceExecCommand; + +typedef enum NotifyState { + NOTIFY_UNKNOWN, + NOTIFY_READY, + NOTIFY_RELOADING, + NOTIFY_STOPPING, + _NOTIFY_STATE_MAX, + _NOTIFY_STATE_INVALID = -1 +} NotifyState; + +/* The values of this enum are referenced in man/systemd.exec.xml and src/shared/bus-unit-util.c. + * Update those sources for each change to this enum. */ +typedef enum ServiceResult { + SERVICE_SUCCESS, + SERVICE_FAILURE_RESOURCES, /* a bit of a misnomer, just our catch-all error for errnos we didn't expect */ + SERVICE_FAILURE_PROTOCOL, + SERVICE_FAILURE_TIMEOUT, + SERVICE_FAILURE_EXIT_CODE, + SERVICE_FAILURE_SIGNAL, + SERVICE_FAILURE_CORE_DUMP, + SERVICE_FAILURE_WATCHDOG, + SERVICE_FAILURE_START_LIMIT_HIT, + SERVICE_FAILURE_OOM_KILL, + SERVICE_SKIP_CONDITION, + _SERVICE_RESULT_MAX, + _SERVICE_RESULT_INVALID = -1 +} ServiceResult; + +struct ServiceFDStore { + Service *service; + + int fd; + char *fdname; + sd_event_source *event_source; + + LIST_FIELDS(ServiceFDStore, fd_store); +}; + +struct Service { + Unit meta; + + ServiceType type; + ServiceRestart restart; + ExitStatusSet restart_prevent_status; + ExitStatusSet restart_force_status; + ExitStatusSet success_status; + + /* If set we'll read the main daemon PID from this file */ + char *pid_file; + + usec_t restart_usec; + usec_t timeout_start_usec; + usec_t timeout_stop_usec; + usec_t timeout_abort_usec; + bool timeout_abort_set; + usec_t runtime_max_usec; + + dual_timestamp watchdog_timestamp; + usec_t watchdog_usec; /* the requested watchdog timeout in the unit file */ + usec_t watchdog_original_usec; /* the watchdog timeout that was in effect when the unit was started, i.e. the timeout the forked off processes currently see */ + usec_t watchdog_override_usec; /* the watchdog timeout requested by the service itself through sd_notify() */ + bool watchdog_override_enable; + sd_event_source *watchdog_event_source; + + ExecCommand* exec_command[_SERVICE_EXEC_COMMAND_MAX]; + + ExecContext exec_context; + KillContext kill_context; + CGroupContext cgroup_context; + + ServiceState state, deserialized_state; + + /* The exit status of the real main process */ + ExecStatus main_exec_status; + + /* The currently executed control process */ + ExecCommand *control_command; + + /* The currently executed main process, which may be NULL if + * the main process got started via forking mode and not by + * us */ + ExecCommand *main_command; + + /* The ID of the control command currently being executed */ + ServiceExecCommand control_command_id; + + /* Runtime data of the execution context */ + ExecRuntime *exec_runtime; + DynamicCreds dynamic_creds; + + pid_t main_pid, control_pid; + int socket_fd; + SocketPeer *peer; + bool socket_fd_selinux_context_net; + + bool permissions_start_only; + bool root_directory_start_only; + bool remain_after_exit; + bool guess_main_pid; + + /* If we shut down, remember why */ + ServiceResult result; + ServiceResult reload_result; + ServiceResult clean_result; + + bool main_pid_known:1; + bool main_pid_alien:1; + bool bus_name_good:1; + bool forbid_restart:1; + /* Keep restart intention between UNIT_FAILED and UNIT_ACTIVATING */ + bool will_auto_restart:1; + bool start_timeout_defined:1; + bool exec_fd_hot:1; + + char *bus_name; + char *bus_name_owner; /* unique name of the current owner */ + + char *status_text; + int status_errno; + + UnitRef accept_socket; + + sd_event_source *timer_event_source; + PathSpec *pid_file_pathspec; + + NotifyAccess notify_access; + NotifyState notify_state; + + sd_event_source *exec_fd_event_source; + + ServiceFDStore *fd_store; + size_t n_fd_store; + unsigned n_fd_store_max; + unsigned n_keep_fd_store; + + char *usb_function_descriptors; + char *usb_function_strings; + + int stdin_fd; + int stdout_fd; + int stderr_fd; + + unsigned n_restarts; + bool flush_n_restarts; + + OOMPolicy oom_policy; +}; + +static inline usec_t service_timeout_abort_usec(Service *s) { + assert(s); + return s->timeout_abort_set ? s->timeout_abort_usec : s->timeout_stop_usec; +} + +extern const UnitVTable service_vtable; + +int service_set_socket_fd(Service *s, int fd, struct Socket *socket, bool selinux_context_net); +void service_close_socket_fd(Service *s); + +const char* service_restart_to_string(ServiceRestart i) _const_; +ServiceRestart service_restart_from_string(const char *s) _pure_; + +const char* service_type_to_string(ServiceType i) _const_; +ServiceType service_type_from_string(const char *s) _pure_; + +const char* service_exec_command_to_string(ServiceExecCommand i) _const_; +ServiceExecCommand service_exec_command_from_string(const char *s) _pure_; + +const char* service_exec_ex_command_to_string(ServiceExecCommand i) _const_; +ServiceExecCommand service_exec_ex_command_from_string(const char *s) _pure_; + +const char* notify_state_to_string(NotifyState i) _const_; +NotifyState notify_state_from_string(const char *s) _pure_; + +const char* service_result_to_string(ServiceResult i) _const_; +ServiceResult service_result_from_string(const char *s) _pure_; + +DEFINE_CAST(SERVICE, Service); + +#define STATUS_TEXT_MAX (16U*1024U) diff --git a/src/core/show-status.c b/src/core/show-status.c new file mode 100644 index 00000000..c998b51a --- /dev/null +++ b/src/core/show-status.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "io-util.h" +#include "parse-util.h" +#include "show-status.h" +#include "string-table.h" +#include "string-util.h" +#include "terminal-util.h" +#include "util.h" + +static const char* const show_status_table[_SHOW_STATUS_MAX] = { + [SHOW_STATUS_NO] = "no", + [SHOW_STATUS_AUTO] = "auto", + [SHOW_STATUS_TEMPORARY] = "temporary", + [SHOW_STATUS_YES] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(show_status, ShowStatus, SHOW_STATUS_YES); + +int parse_show_status(const char *v, ShowStatus *ret) { + ShowStatus s; + + assert(ret); + + s = show_status_from_string(v); + if (s < 0 || s == SHOW_STATUS_TEMPORARY) + return -EINVAL; + + *ret = s; + return 0; +} + +int status_vprintf(const char *status, ShowStatusFlags flags, const char *format, va_list ap) { + static const char status_indent[] = " "; /* "[" STATUS "] " */ + _cleanup_free_ char *s = NULL; + _cleanup_close_ int fd = -1; + struct iovec iovec[7] = {}; + int n = 0; + static bool prev_ephemeral; + + assert(format); + + /* This is independent of logging, as status messages are + * optional and go exclusively to the console. */ + + if (vasprintf(&s, format, ap) < 0) + return log_oom(); + + /* Before you ask: yes, on purpose we open/close the console for each status line we write individually. This + * is a good strategy to avoid PID 1 getting killed by the kernel's SAK concept (it doesn't fix this entirely, + * but minimizes the time window the kernel might end up killing PID 1 due to SAK). It also makes things easier + * for us so that we don't have to recover from hangups and suchlike triggered on the console. */ + + fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return fd; + + if (FLAGS_SET(flags, SHOW_STATUS_ELLIPSIZE)) { + char *e; + size_t emax, sl; + int c; + + c = fd_columns(fd); + if (c <= 0) + c = 80; + + sl = status ? sizeof(status_indent)-1 : 0; + + emax = c - sl - 1; + if (emax < 3) + emax = 3; + + e = ellipsize(s, emax, 50); + if (e) + free_and_replace(s, e); + } + + if (prev_ephemeral) + iovec[n++] = IOVEC_MAKE_STRING(ANSI_REVERSE_LINEFEED "\r" ANSI_ERASE_TO_END_OF_LINE); + + if (status) { + if (!isempty(status)) { + iovec[n++] = IOVEC_MAKE_STRING("["); + iovec[n++] = IOVEC_MAKE_STRING(status); + iovec[n++] = IOVEC_MAKE_STRING("] "); + } else + iovec[n++] = IOVEC_MAKE_STRING(status_indent); + } + + iovec[n++] = IOVEC_MAKE_STRING(s); + iovec[n++] = IOVEC_MAKE_STRING("\n"); + + if (prev_ephemeral && !FLAGS_SET(flags, SHOW_STATUS_EPHEMERAL)) + iovec[n++] = IOVEC_MAKE_STRING(ANSI_ERASE_TO_END_OF_LINE); + prev_ephemeral = FLAGS_SET(flags, SHOW_STATUS_EPHEMERAL) ; + + if (writev(fd, iovec, n) < 0) + return -errno; + + return 0; +} + +int status_printf(const char *status, ShowStatusFlags flags, const char *format, ...) { + va_list ap; + int r; + + assert(format); + + va_start(ap, format); + r = status_vprintf(status, flags, format, ap); + va_end(ap); + + return r; +} + +static const char* const status_unit_format_table[_STATUS_UNIT_FORMAT_MAX] = { + [STATUS_UNIT_FORMAT_NAME] = "name", + [STATUS_UNIT_FORMAT_DESCRIPTION] = "description", +}; + +DEFINE_STRING_TABLE_LOOKUP(status_unit_format, StatusUnitFormat); diff --git a/src/core/show-status.h b/src/core/show-status.h new file mode 100644 index 00000000..247caec7 --- /dev/null +++ b/src/core/show-status.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +/* Manager status */ + +typedef enum ShowStatus { + SHOW_STATUS_NO, + SHOW_STATUS_AUTO, + SHOW_STATUS_TEMPORARY, + SHOW_STATUS_YES, + _SHOW_STATUS_MAX, + _SHOW_STATUS_INVALID = -1, +} ShowStatus; + +typedef enum ShowStatusFlags { + SHOW_STATUS_ELLIPSIZE = 1 << 0, + SHOW_STATUS_EPHEMERAL = 1 << 1, +} ShowStatusFlags; + +typedef enum StatusUnitFormat { + STATUS_UNIT_FORMAT_NAME, + STATUS_UNIT_FORMAT_DESCRIPTION, + _STATUS_UNIT_FORMAT_MAX, + _STATUS_UNIT_FORMAT_INVALID = -1, +} StatusUnitFormat; + +ShowStatus show_status_from_string(const char *v) _const_; +const char* show_status_to_string(ShowStatus s) _pure_; +int parse_show_status(const char *v, ShowStatus *ret); + +StatusUnitFormat status_unit_format_from_string(const char *v) _const_; +const char* status_unit_format_to_string(StatusUnitFormat s) _pure_; + +int status_vprintf(const char *status, ShowStatusFlags flags, const char *format, va_list ap) _printf_(3,0); +int status_printf(const char *status, ShowStatusFlags flags, const char *format, ...) _printf_(3,4); diff --git a/src/core/slice.c b/src/core/slice.c new file mode 100644 index 00000000..d97a2627 --- /dev/null +++ b/src/core/slice.c @@ -0,0 +1,394 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "dbus-slice.h" +#include "dbus-unit.h" +#include "log.h" +#include "serialize.h" +#include "slice.h" +#include "special.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "unit.h" + +static const UnitActiveState state_translation_table[_SLICE_STATE_MAX] = { + [SLICE_DEAD] = UNIT_INACTIVE, + [SLICE_ACTIVE] = UNIT_ACTIVE +}; + +static void slice_init(Unit *u) { + assert(u); + assert(u->load_state == UNIT_STUB); + + u->ignore_on_isolate = true; +} + +static void slice_set_state(Slice *t, SliceState state) { + SliceState old_state; + assert(t); + + if (t->state != state) + bus_unit_send_pending_change_signal(UNIT(t), false); + + old_state = t->state; + t->state = state; + + if (state != old_state) + log_debug("%s changed %s -> %s", + UNIT(t)->id, + slice_state_to_string(old_state), + slice_state_to_string(state)); + + unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0); +} + +static int slice_add_parent_slice(Slice *s) { + Unit *u = UNIT(s), *parent; + _cleanup_free_ char *a = NULL; + int r; + + assert(s); + + if (UNIT_ISSET(u->slice)) + return 0; + + r = slice_build_parent_slice(u->id, &a); + if (r <= 0) /* 0 means root slice */ + return r; + + r = manager_load_unit(u->manager, a, NULL, NULL, &parent); + if (r < 0) + return r; + + unit_ref_set(&u->slice, u, parent); + return 0; +} + +static int slice_add_default_dependencies(Slice *s) { + int r; + + assert(s); + + if (!UNIT(s)->default_dependencies) + return 0; + + /* Make sure slices are unloaded on shutdown */ + r = unit_add_two_dependencies_by_name( + UNIT(s), + UNIT_BEFORE, UNIT_CONFLICTS, + SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + return 0; +} + +static int slice_verify(Slice *s) { + _cleanup_free_ char *parent = NULL; + int r; + + assert(s); + assert(UNIT(s)->load_state == UNIT_LOADED); + + if (!slice_name_is_valid(UNIT(s)->id)) { + log_unit_error(UNIT(s), "Slice name %s is not valid. Refusing.", UNIT(s)->id); + return -ENOEXEC; + } + + r = slice_build_parent_slice(UNIT(s)->id, &parent); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to determine parent slice: %m"); + + if (parent ? !unit_has_name(UNIT_DEREF(UNIT(s)->slice), parent) : UNIT_ISSET(UNIT(s)->slice)) { + log_unit_error(UNIT(s), "Located outside of parent slice. Refusing."); + return -ENOEXEC; + } + + return 0; +} + +static int slice_load_root_slice(Unit *u) { + assert(u); + + if (!unit_has_name(u, SPECIAL_ROOT_SLICE)) + return 0; + + u->perpetual = true; + + /* The root slice is a bit special. For example it is always running and cannot be terminated. Because of its + * special semantics we synthesize it here, instead of relying on the unit file on disk. */ + + u->default_dependencies = false; + + if (!u->description) + u->description = strdup("Root Slice"); + if (!u->documentation) + u->documentation = strv_new("man:systemd.special(7)"); + + return 1; +} + +static int slice_load_system_slice(Unit *u) { + assert(u); + + if (!MANAGER_IS_SYSTEM(u->manager)) + return 0; + if (!unit_has_name(u, SPECIAL_SYSTEM_SLICE)) + return 0; + + u->perpetual = true; + + /* The system slice is a bit special. For example it is always running and cannot be terminated. Because of its + * special semantics we synthesize it here, instead of relying on the unit file on disk. */ + + u->default_dependencies = false; + + if (!u->description) + u->description = strdup("System Slice"); + if (!u->documentation) + u->documentation = strv_new("man:systemd.special(7)"); + + return 1; +} + +static int slice_load(Unit *u) { + Slice *s = SLICE(u); + int r; + + assert(s); + assert(u->load_state == UNIT_STUB); + + r = slice_load_root_slice(u); + if (r < 0) + return r; + r = slice_load_system_slice(u); + if (r < 0) + return r; + + r = unit_load_fragment_and_dropin(u, false); + if (r < 0) + return r; + + if (u->load_state != UNIT_LOADED) + return 0; + + /* This is a new unit? Then let's add in some extras */ + r = unit_patch_contexts(u); + if (r < 0) + return r; + + r = slice_add_parent_slice(s); + if (r < 0) + return r; + + r = slice_add_default_dependencies(s); + if (r < 0) + return r; + + return slice_verify(s); +} + +static int slice_coldplug(Unit *u) { + Slice *t = SLICE(u); + + assert(t); + assert(t->state == SLICE_DEAD); + + if (t->deserialized_state != t->state) + slice_set_state(t, t->deserialized_state); + + return 0; +} + +static void slice_dump(Unit *u, FILE *f, const char *prefix) { + Slice *t = SLICE(u); + + assert(t); + assert(f); + + fprintf(f, + "%sSlice State: %s\n", + prefix, slice_state_to_string(t->state)); + + cgroup_context_dump(UNIT(t), f, prefix); +} + +static int slice_start(Unit *u) { + Slice *t = SLICE(u); + int r; + + assert(t); + assert(t->state == SLICE_DEAD); + + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + + (void) unit_realize_cgroup(u); + (void) unit_reset_accounting(u); + + slice_set_state(t, SLICE_ACTIVE); + return 1; +} + +static int slice_stop(Unit *u) { + Slice *t = SLICE(u); + + assert(t); + assert(t->state == SLICE_ACTIVE); + + /* We do not need to destroy the cgroup explicitly, + * unit_notify() will do that for us anyway. */ + + slice_set_state(t, SLICE_DEAD); + return 1; +} + +static int slice_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { + return unit_kill_common(u, who, signo, -1, -1, error); +} + +static int slice_serialize(Unit *u, FILE *f, FDSet *fds) { + Slice *s = SLICE(u); + + assert(s); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", slice_state_to_string(s->state)); + + return 0; +} + +static int slice_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Slice *s = SLICE(u); + + assert(u); + assert(key); + assert(value); + assert(fds); + + if (streq(key, "state")) { + SliceState state; + + state = slice_state_from_string(value); + if (state < 0) + log_debug("Failed to parse state value %s", value); + else + s->deserialized_state = state; + + } else + log_debug("Unknown serialization key '%s'", key); + + return 0; +} + +_pure_ static UnitActiveState slice_active_state(Unit *u) { + assert(u); + + return state_translation_table[SLICE(u)->state]; +} + +_pure_ static const char *slice_sub_state_to_string(Unit *u) { + assert(u); + + return slice_state_to_string(SLICE(u)->state); +} + +static int slice_make_perpetual(Manager *m, const char *name, Unit **ret) { + Unit *u; + int r; + + assert(m); + assert(name); + + u = manager_get_unit(m, name); + if (!u) { + r = unit_new_for_name(m, sizeof(Slice), name, &u); + if (r < 0) + return log_error_errno(r, "Failed to allocate the special %s unit: %m", name); + } + + u->perpetual = true; + SLICE(u)->deserialized_state = SLICE_ACTIVE; + + unit_add_to_load_queue(u); + unit_add_to_dbus_queue(u); + + if (ret) + *ret = u; + + return 0; +} + +static void slice_enumerate_perpetual(Manager *m) { + Unit *u; + int r; + + assert(m); + + r = slice_make_perpetual(m, SPECIAL_ROOT_SLICE, &u); + if (r >= 0 && manager_owns_host_root_cgroup(m)) { + Slice *s = SLICE(u); + + /* If we are managing the root cgroup then this means our root slice covers the whole system, which + * means the kernel will track CPU/tasks/memory for us anyway, and it is all available in /proc. Let's + * hence turn accounting on here, so that our APIs to query this data are available. */ + + s->cgroup_context.cpu_accounting = true; + s->cgroup_context.tasks_accounting = true; + s->cgroup_context.memory_accounting = true; + } + + if (MANAGER_IS_SYSTEM(m)) + (void) slice_make_perpetual(m, SPECIAL_SYSTEM_SLICE, NULL); +} + +const UnitVTable slice_vtable = { + .object_size = sizeof(Slice), + .cgroup_context_offset = offsetof(Slice, cgroup_context), + + .sections = + "Unit\0" + "Slice\0" + "Install\0", + .private_section = "Slice", + + .can_transient = true, + + .init = slice_init, + .load = slice_load, + + .coldplug = slice_coldplug, + + .dump = slice_dump, + + .start = slice_start, + .stop = slice_stop, + + .kill = slice_kill, + + .serialize = slice_serialize, + .deserialize_item = slice_deserialize_item, + + .active_state = slice_active_state, + .sub_state_to_string = slice_sub_state_to_string, + + .bus_vtable = bus_slice_vtable, + .bus_set_property = bus_slice_set_property, + .bus_commit_properties = bus_slice_commit_properties, + + .enumerate_perpetual = slice_enumerate_perpetual, + + .status_message_formats = { + .finished_start_job = { + [JOB_DONE] = "Created slice %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Removed slice %s.", + }, + }, +}; diff --git a/src/core/slice.h b/src/core/slice.h new file mode 100644 index 00000000..4678c085 --- /dev/null +++ b/src/core/slice.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "unit.h" + +typedef struct Slice Slice; + +struct Slice { + Unit meta; + + SliceState state, deserialized_state; + + CGroupContext cgroup_context; +}; + +extern const UnitVTable slice_vtable; + +DEFINE_CAST(SLICE, Slice); diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c new file mode 100644 index 00000000..4427397f --- /dev/null +++ b/src/core/smack-setup.c @@ -0,0 +1,396 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Intel Corporation + Authors: + Nathaniel Chen +***/ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "macro.h" +#include "smack-setup.h" +#include "string-util.h" +#include "util.h" + +#if ENABLE_SMACK + +static int fdopen_unlocked_at(int dfd, const char *dir, const char *name, int *status, FILE **ret_file) { + int fd, r; + FILE *f; + + fd = openat(dfd, name, O_RDONLY|O_CLOEXEC); + if (fd < 0) { + if (*status == 0) + *status = -errno; + + return log_warning_errno(errno, "Failed to open \"%s/%s\": %m", dir, name); + } + + r = fdopen_unlocked(fd, "r", &f); + if (r < 0) { + if (*status == 0) + *status = r; + + safe_close(fd); + return log_error_errno(r, "Failed to open \"%s/%s\": %m", dir, name); + } + + *ret_file = f; + return 0; +} + +static int write_access2_rules(const char *srcdir) { + _cleanup_close_ int load2_fd = -1, change_fd = -1; + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *entry; + int dfd = -1, r = 0; + + load2_fd = open("/sys/fs/smackfs/load2", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (load2_fd < 0) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/load2': %m"); + return -errno; /* negative error */ + } + + change_fd = open("/sys/fs/smackfs/change-rule", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (change_fd < 0) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/change-rule': %m"); + return -errno; /* negative error */ + } + + /* write rules to load2 or change-rule from every file in the directory */ + dir = opendir(srcdir); + if (!dir) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to opendir '%s': %m", srcdir); + return errno; /* positive on purpose */ + } + + dfd = dirfd(dir); + assert(dfd >= 0); + + FOREACH_DIRENT(entry, dir, return 0) { + _cleanup_fclose_ FILE *policy = NULL; + + dirent_ensure_type(dir, entry); + if (!dirent_is_file(entry)) + continue; + + if (fdopen_unlocked_at(dfd, srcdir, entry->d_name, &r, &policy) < 0) + continue; + + /* load2 write rules in the kernel require a line buffered stream */ + for (;;) { + _cleanup_free_ char *buf = NULL, *sbj = NULL, *obj = NULL, *acc1 = NULL, *acc2 = NULL; + int q; + + q = read_line(policy, NAME_MAX, &buf); + if (q < 0) + return log_error_errno(q, "Failed to read line from '%s': %m", entry->d_name); + if (q == 0) + break; + + if (isempty(buf) || strchr(COMMENTS, buf[0])) + continue; + + /* if 3 args -> load rule : subject object access1 */ + /* if 4 args -> change rule : subject object access1 access2 */ + if (sscanf(buf, "%ms %ms %ms %ms", &sbj, &obj, &acc1, &acc2) < 3) { + log_error_errno(errno, "Failed to parse rule '%s' in '%s', ignoring.", buf, entry->d_name); + continue; + } + + if (write(isempty(acc2) ? load2_fd : change_fd, buf, strlen(buf)) < 0) { + if (r == 0) + r = -errno; + log_error_errno(errno, "Failed to write '%s' to '%s' in '%s': %m", + buf, isempty(acc2) ? "/sys/fs/smackfs/load2" : "/sys/fs/smackfs/change-rule", entry->d_name); + } + } + } + + return r; +} + +static int write_cipso2_rules(const char *srcdir) { + _cleanup_close_ int cipso2_fd = -1; + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *entry; + int dfd = -1, r = 0; + + cipso2_fd = open("/sys/fs/smackfs/cipso2", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (cipso2_fd < 0) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/cipso2': %m"); + return -errno; /* negative error */ + } + + /* write rules to cipso2 from every file in the directory */ + dir = opendir(srcdir); + if (!dir) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to opendir '%s': %m", srcdir); + return errno; /* positive on purpose */ + } + + dfd = dirfd(dir); + assert(dfd >= 0); + + FOREACH_DIRENT(entry, dir, return 0) { + _cleanup_fclose_ FILE *policy = NULL; + + dirent_ensure_type(dir, entry); + if (!dirent_is_file(entry)) + continue; + + if (fdopen_unlocked_at(dfd, srcdir, entry->d_name, &r, &policy) < 0) + continue; + + /* cipso2 write rules in the kernel require a line buffered stream */ + for (;;) { + _cleanup_free_ char *buf = NULL; + int q; + + q = read_line(policy, NAME_MAX, &buf); + if (q < 0) + return log_error_errno(q, "Failed to read line from '%s': %m", entry->d_name); + if (q == 0) + break; + + if (isempty(buf) || strchr(COMMENTS, buf[0])) + continue; + + if (write(cipso2_fd, buf, strlen(buf)) < 0) { + if (r == 0) + r = -errno; + log_error_errno(errno, "Failed to write '%s' to '/sys/fs/smackfs/cipso2' in '%s': %m", + buf, entry->d_name); + break; + } + } + } + + return r; +} + +static int write_netlabel_rules(const char *srcdir) { + _cleanup_fclose_ FILE *dst = NULL; + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *entry; + int dfd = -1, r = 0; + + dst = fopen("/sys/fs/smackfs/netlabel", "we"); + if (!dst) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to open /sys/fs/smackfs/netlabel: %m"); + return -errno; /* negative error */ + } + + /* write rules to dst from every file in the directory */ + dir = opendir(srcdir); + if (!dir) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to opendir %s: %m", srcdir); + return errno; /* positive on purpose */ + } + + dfd = dirfd(dir); + assert(dfd >= 0); + + FOREACH_DIRENT(entry, dir, return 0) { + _cleanup_fclose_ FILE *policy = NULL; + + if (fdopen_unlocked_at(dfd, srcdir, entry->d_name, &r, &policy) < 0) + continue; + + /* load2 write rules in the kernel require a line buffered stream */ + for (;;) { + _cleanup_free_ char *buf = NULL; + int q; + + q = read_line(policy, NAME_MAX, &buf); + if (q < 0) + return log_error_errno(q, "Failed to read line from %s: %m", entry->d_name); + if (q == 0) + break; + + if (!fputs(buf, dst)) { + if (r == 0) + r = -EINVAL; + log_error_errno(errno, "Failed to write line to /sys/fs/smackfs/netlabel: %m"); + break; + } + q = fflush_and_check(dst); + if (q < 0) { + if (r == 0) + r = q; + log_error_errno(q, "Failed to flush writes to /sys/fs/smackfs/netlabel: %m"); + break; + } + } + } + + return r; +} + +static int write_onlycap_list(void) { + _cleanup_close_ int onlycap_fd = -1; + _cleanup_free_ char *list = NULL; + _cleanup_fclose_ FILE *f = NULL; + size_t len = 0, allocated = 0; + int r; + + f = fopen("/etc/smack/onlycap", "re"); + if (!f) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to read '/etc/smack/onlycap': %m"); + + return errno == ENOENT ? ENOENT : -errno; + } + + for (;;) { + _cleanup_free_ char *buf = NULL; + size_t l; + + r = read_line(f, LONG_LINE_MAX, &buf); + if (r < 0) + return log_error_errno(r, "Failed to read line from /etc/smack/onlycap: %m"); + if (r == 0) + break; + + if (isempty(buf) || strchr(COMMENTS, *buf)) + continue; + + l = strlen(buf); + if (!GREEDY_REALLOC(list, allocated, len + l + 1)) + return log_oom(); + + stpcpy(list + len, buf)[0] = ' '; + len += l + 1; + } + + if (len == 0) + return 0; + + list[len - 1] = 0; + + onlycap_fd = open("/sys/fs/smackfs/onlycap", O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (onlycap_fd < 0) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/onlycap': %m"); + return -errno; /* negative error */ + } + + r = write(onlycap_fd, list, len); + if (r < 0) + return log_error_errno(errno, "Failed to write onlycap list(%s) to '/sys/fs/smackfs/onlycap': %m", list); + + return 0; +} + +#endif + +int mac_smack_setup(bool *loaded_policy) { + +#if ENABLE_SMACK + + int r; + + assert(loaded_policy); + + r = write_access2_rules("/etc/smack/accesses.d/"); + switch(r) { + case -ENOENT: + log_debug("Smack is not enabled in the kernel."); + return 0; + case ENOENT: + log_debug("Smack access rules directory '/etc/smack/accesses.d/' not found"); + return 0; + case 0: + log_info("Successfully loaded Smack policies."); + break; + default: + log_warning_errno(r, "Failed to load Smack access rules, ignoring: %m"); + return 0; + } + +#ifdef SMACK_RUN_LABEL + r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + log_warning_errno(r, "Failed to set SMACK label \"" SMACK_RUN_LABEL "\" on self: %m"); + r = write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + log_warning_errno(r, "Failed to set SMACK ambient label \"" SMACK_RUN_LABEL "\": %m"); + r = write_string_file("/sys/fs/smackfs/netlabel", + "0.0.0.0/0 " SMACK_RUN_LABEL, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + log_warning_errno(r, "Failed to set SMACK netlabel rule \"0.0.0.0/0 " SMACK_RUN_LABEL "\": %m"); + r = write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO", WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + log_warning_errno(r, "Failed to set SMACK netlabel rule \"127.0.0.1 -CIPSO\": %m"); +#endif + + r = write_cipso2_rules("/etc/smack/cipso.d/"); + switch(r) { + case -ENOENT: + log_debug("Smack/CIPSO is not enabled in the kernel."); + return 0; + case ENOENT: + log_debug("Smack/CIPSO access rules directory '/etc/smack/cipso.d/' not found"); + break; + case 0: + log_info("Successfully loaded Smack/CIPSO policies."); + break; + default: + log_warning_errno(r, "Failed to load Smack/CIPSO access rules, ignoring: %m"); + break; + } + + r = write_netlabel_rules("/etc/smack/netlabel.d/"); + switch(r) { + case -ENOENT: + log_debug("Smack/CIPSO is not enabled in the kernel."); + return 0; + case ENOENT: + log_debug("Smack network host rules directory '/etc/smack/netlabel.d/' not found"); + break; + case 0: + log_info("Successfully loaded Smack network host rules."); + break; + default: + log_warning_errno(r, "Failed to load Smack network host rules: %m, ignoring."); + break; + } + + r = write_onlycap_list(); + switch(r) { + case -ENOENT: + log_debug("Smack is not enabled in the kernel."); + break; + case ENOENT: + log_debug("Smack onlycap list file '/etc/smack/onlycap' not found"); + break; + case 0: + log_info("Successfully wrote Smack onlycap list."); + break; + default: + log_emergency_errno(r, "Failed to write Smack onlycap list: %m"); + return r; + } + + *loaded_policy = true; + +#endif + + return 0; +} diff --git a/src/core/smack-setup.h b/src/core/smack-setup.h new file mode 100644 index 00000000..b65daafc --- /dev/null +++ b/src/core/smack-setup.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2013 Intel Corporation + Authors: + Nathaniel Chen +***/ + +int mac_smack_setup(bool *loaded_policy); diff --git a/src/core/socket.c b/src/core/socket.c new file mode 100644 index 00000000..c587eaeb --- /dev/null +++ b/src/core/socket.c @@ -0,0 +1,3482 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "bpf-firewall.h" +#include "bus-error.h" +#include "bus-util.h" +#include "copy.h" +#include "dbus-socket.h" +#include "dbus-unit.h" +#include "def.h" +#include "exit-status.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "in-addr-util.h" +#include "io-util.h" +#include "ip-protocol-list.h" +#include "label.h" +#include "log.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "selinux-util.h" +#include "serialize.h" +#include "signal-util.h" +#include "smack-util.h" +#include "socket.h" +#include "special.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "unit.h" +#include "user-util.h" + +struct SocketPeer { + unsigned n_ref; + + Socket *socket; + union sockaddr_union peer; + socklen_t peer_salen; +}; + +static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { + [SOCKET_DEAD] = UNIT_INACTIVE, + [SOCKET_START_PRE] = UNIT_ACTIVATING, + [SOCKET_START_CHOWN] = UNIT_ACTIVATING, + [SOCKET_START_POST] = UNIT_ACTIVATING, + [SOCKET_LISTENING] = UNIT_ACTIVE, + [SOCKET_RUNNING] = UNIT_ACTIVE, + [SOCKET_STOP_PRE] = UNIT_DEACTIVATING, + [SOCKET_STOP_PRE_SIGTERM] = UNIT_DEACTIVATING, + [SOCKET_STOP_PRE_SIGKILL] = UNIT_DEACTIVATING, + [SOCKET_STOP_POST] = UNIT_DEACTIVATING, + [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING, + [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING, + [SOCKET_FAILED] = UNIT_FAILED, + [SOCKET_CLEANING] = UNIT_MAINTENANCE, +}; + +static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); +static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); + +static void socket_init(Unit *u) { + Socket *s = SOCKET(u); + + assert(u); + assert(u->load_state == UNIT_STUB); + + s->backlog = SOMAXCONN; + s->timeout_usec = u->manager->default_timeout_start_usec; + s->directory_mode = 0755; + s->socket_mode = 0666; + + s->max_connections = 64; + + s->priority = -1; + s->ip_tos = -1; + s->ip_ttl = -1; + s->mark = -1; + + s->exec_context.std_output = u->manager->default_std_output; + s->exec_context.std_error = u->manager->default_std_error; + + s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; + + s->trigger_limit.interval = USEC_INFINITY; + s->trigger_limit.burst = (unsigned) -1; +} + +static void socket_unwatch_control_pid(Socket *s) { + assert(s); + + if (s->control_pid <= 0) + return; + + unit_unwatch_pid(UNIT(s), s->control_pid); + s->control_pid = 0; +} + +static void socket_cleanup_fd_list(SocketPort *p) { + assert(p); + + close_many(p->auxiliary_fds, p->n_auxiliary_fds); + p->auxiliary_fds = mfree(p->auxiliary_fds); + p->n_auxiliary_fds = 0; +} + +void socket_free_ports(Socket *s) { + SocketPort *p; + + assert(s); + + while ((p = s->ports)) { + LIST_REMOVE(port, s->ports, p); + + sd_event_source_unref(p->event_source); + + socket_cleanup_fd_list(p); + safe_close(p->fd); + free(p->path); + free(p); + } +} + +static void socket_done(Unit *u) { + Socket *s = SOCKET(u); + SocketPeer *p; + + assert(s); + + socket_free_ports(s); + + while ((p = set_steal_first(s->peers_by_address))) + p->socket = NULL; + + s->peers_by_address = set_free(s->peers_by_address); + + s->exec_runtime = exec_runtime_unref(s->exec_runtime, false); + exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); + s->control_command = NULL; + + dynamic_creds_unref(&s->dynamic_creds); + + socket_unwatch_control_pid(s); + + unit_ref_unset(&s->service); + + s->tcp_congestion = mfree(s->tcp_congestion); + s->bind_to_device = mfree(s->bind_to_device); + + s->smack = mfree(s->smack); + s->smack_ip_in = mfree(s->smack_ip_in); + s->smack_ip_out = mfree(s->smack_ip_out); + + strv_free(s->symlinks); + + s->user = mfree(s->user); + s->group = mfree(s->group); + + s->fdname = mfree(s->fdname); + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); +} + +static int socket_arm_timer(Socket *s, usec_t usec) { + int r; + + assert(s); + + if (s->timer_event_source) { + r = sd_event_source_set_time(s->timer_event_source, usec); + if (r < 0) + return r; + + return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); + } + + if (usec == USEC_INFINITY) + return 0; + + r = sd_event_add_time( + UNIT(s)->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + usec, 0, + socket_dispatch_timer, s); + if (r < 0) + return r; + + (void) sd_event_source_set_description(s->timer_event_source, "socket-timer"); + + return 0; +} + +int socket_instantiate_service(Socket *s) { + _cleanup_free_ char *prefix = NULL, *name = NULL; + int r; + Unit *u; + + assert(s); + + /* This fills in s->service if it isn't filled in yet. For + * Accept=yes sockets we create the next connection service + * here. For Accept=no this is mostly a NOP since the service + * is figured out at load time anyway. */ + + if (UNIT_DEREF(s->service)) + return 0; + + if (!s->accept) + return 0; + + r = unit_name_to_prefix(UNIT(s)->id, &prefix); + if (r < 0) + return r; + + if (asprintf(&name, "%s@%u.service", prefix, s->n_accepted) < 0) + return -ENOMEM; + + r = manager_load_unit(UNIT(s)->manager, name, NULL, NULL, &u); + if (r < 0) + return r; + + unit_ref_set(&s->service, UNIT(s), u); + + return unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, u, false, UNIT_DEPENDENCY_IMPLICIT); +} + +static bool have_non_accept_socket(Socket *s) { + SocketPort *p; + + assert(s); + + if (!s->accept) + return true; + + LIST_FOREACH(port, p, s->ports) { + + if (p->type != SOCKET_SOCKET) + return true; + + if (!socket_address_can_accept(&p->address)) + return true; + } + + return false; +} + +static int socket_add_mount_dependencies(Socket *s) { + SocketPort *p; + int r; + + assert(s); + + LIST_FOREACH(port, p, s->ports) { + const char *path = NULL; + + if (p->type == SOCKET_SOCKET) + path = socket_address_get_path(&p->address); + else if (IN_SET(p->type, SOCKET_FIFO, SOCKET_SPECIAL, SOCKET_USB_FUNCTION)) + path = p->path; + + if (!path) + continue; + + r = unit_require_mounts_for(UNIT(s), path, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + } + + return 0; +} + +static int socket_add_device_dependencies(Socket *s) { + char *t; + + assert(s); + + if (!s->bind_to_device || streq(s->bind_to_device, "lo")) + return 0; + + t = strjoina("/sys/subsystem/net/devices/", s->bind_to_device); + return unit_add_node_dependency(UNIT(s), t, UNIT_BINDS_TO, UNIT_DEPENDENCY_FILE); +} + +static int socket_add_default_dependencies(Socket *s) { + int r; + assert(s); + + if (!UNIT(s)->default_dependencies) + return 0; + + r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SOCKETS_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + if (MANAGER_IS_SYSTEM(UNIT(s)->manager)) { + r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + } + + return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT); +} + +_pure_ static bool socket_has_exec(Socket *s) { + unsigned i; + assert(s); + + for (i = 0; i < _SOCKET_EXEC_COMMAND_MAX; i++) + if (s->exec_command[i]) + return true; + + return false; +} + +static int socket_add_extras(Socket *s) { + Unit *u = UNIT(s); + int r; + + assert(s); + + /* Pick defaults for the trigger limit, if nothing was explicitly configured. We pick a relatively high limit + * in Accept=yes mode, and a lower limit for Accept=no. Reason: in Accept=yes mode we are invoking accept() + * ourselves before the trigger limit can hit, thus incoming connections are taken off the socket queue quickly + * and reliably. This is different for Accept=no, where the spawned service has to take the incoming traffic + * off the queues, which it might not necessarily do. Moreover, while Accept=no services are supposed to + * process whatever is queued in one go, and thus should normally never have to be started frequently. This is + * different for Accept=yes where each connection is processed by a new service instance, and thus frequent + * service starts are typical. */ + + if (s->trigger_limit.interval == USEC_INFINITY) + s->trigger_limit.interval = 2 * USEC_PER_SEC; + + if (s->trigger_limit.burst == (unsigned) -1) { + if (s->accept) + s->trigger_limit.burst = 200; + else + s->trigger_limit.burst = 20; + } + + if (have_non_accept_socket(s)) { + + if (!UNIT_DEREF(s->service)) { + Unit *x; + + r = unit_load_related_unit(u, ".service", &x); + if (r < 0) + return r; + + unit_ref_set(&s->service, u, x); + } + + r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(s->service), true, UNIT_DEPENDENCY_IMPLICIT); + if (r < 0) + return r; + } + + r = socket_add_mount_dependencies(s); + if (r < 0) + return r; + + r = socket_add_device_dependencies(s); + if (r < 0) + return r; + + r = unit_patch_contexts(u); + if (r < 0) + return r; + + if (socket_has_exec(s)) { + r = unit_add_exec_dependencies(u, &s->exec_context); + if (r < 0) + return r; + } + + r = unit_set_default_slice(u); + if (r < 0) + return r; + + r = socket_add_default_dependencies(s); + if (r < 0) + return r; + + return 0; +} + +static const char *socket_find_symlink_target(Socket *s) { + const char *found = NULL; + SocketPort *p; + + LIST_FOREACH(port, p, s->ports) { + const char *f = NULL; + + switch (p->type) { + + case SOCKET_FIFO: + f = p->path; + break; + + case SOCKET_SOCKET: + f = socket_address_get_path(&p->address); + break; + + default: + break; + } + + if (f) { + if (found) + return NULL; + + found = f; + } + } + + return found; +} + +static int socket_verify(Socket *s) { + assert(s); + assert(UNIT(s)->load_state == UNIT_LOADED); + + if (!s->ports) { + log_unit_error(UNIT(s), "Unit has no Listen setting (ListenStream=, ListenDatagram=, ListenFIFO=, ...). Refusing."); + return -ENOEXEC; + } + + if (s->accept && have_non_accept_socket(s)) { + log_unit_error(UNIT(s), "Unit configured for accepting sockets, but sockets are non-accepting. Refusing."); + return -ENOEXEC; + } + + if (s->accept && s->max_connections <= 0) { + log_unit_error(UNIT(s), "MaxConnection= setting too small. Refusing."); + return -ENOEXEC; + } + + if (s->accept && UNIT_DEREF(s->service)) { + log_unit_error(UNIT(s), "Explicit service configuration for accepting socket units not supported. Refusing."); + return -ENOEXEC; + } + + if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) { + log_unit_error(UNIT(s), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing."); + return -ENOEXEC; + } + + if (!strv_isempty(s->symlinks) && !socket_find_symlink_target(s)) { + log_unit_error(UNIT(s), "Unit has symlinks set but none or more than one node in the file system. Refusing."); + return -ENOEXEC; + } + + return 0; +} + +static void peer_address_hash_func(const SocketPeer *s, struct siphash *state) { + assert(s); + + if (s->peer.sa.sa_family == AF_INET) + siphash24_compress(&s->peer.in.sin_addr, sizeof(s->peer.in.sin_addr), state); + else if (s->peer.sa.sa_family == AF_INET6) + siphash24_compress(&s->peer.in6.sin6_addr, sizeof(s->peer.in6.sin6_addr), state); + else if (s->peer.sa.sa_family == AF_VSOCK) + siphash24_compress(&s->peer.vm.svm_cid, sizeof(s->peer.vm.svm_cid), state); + else + assert_not_reached("Unknown address family."); +} + +static int peer_address_compare_func(const SocketPeer *x, const SocketPeer *y) { + int r; + + r = CMP(x->peer.sa.sa_family, y->peer.sa.sa_family); + if (r != 0) + return r; + + switch(x->peer.sa.sa_family) { + case AF_INET: + return memcmp(&x->peer.in.sin_addr, &y->peer.in.sin_addr, sizeof(x->peer.in.sin_addr)); + case AF_INET6: + return memcmp(&x->peer.in6.sin6_addr, &y->peer.in6.sin6_addr, sizeof(x->peer.in6.sin6_addr)); + case AF_VSOCK: + return CMP(x->peer.vm.svm_cid, y->peer.vm.svm_cid); + } + assert_not_reached("Black sheep in the family!"); +} + +DEFINE_PRIVATE_HASH_OPS(peer_address_hash_ops, SocketPeer, peer_address_hash_func, peer_address_compare_func); + +static int socket_load(Unit *u) { + Socket *s = SOCKET(u); + int r; + + assert(u); + assert(u->load_state == UNIT_STUB); + + r = set_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops); + if (r < 0) + return r; + + r = unit_load_fragment_and_dropin(u, true); + if (r < 0) + return r; + + if (u->load_state != UNIT_LOADED) + return 0; + + /* This is a new unit? Then let's add in some extras */ + r = socket_add_extras(s); + if (r < 0) + return r; + + return socket_verify(s); +} + +static SocketPeer *socket_peer_new(void) { + SocketPeer *p; + + p = new0(SocketPeer, 1); + if (!p) + return NULL; + + p->n_ref = 1; + + return p; +} + +static SocketPeer *socket_peer_free(SocketPeer *p) { + assert(p); + + if (p->socket) + set_remove(p->socket->peers_by_address, p); + + return mfree(p); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(SocketPeer, socket_peer, socket_peer_free); + +int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) { + _cleanup_(socket_peer_unrefp) SocketPeer *remote = NULL; + SocketPeer sa = {}, *i; + socklen_t salen = sizeof(sa.peer); + int r; + + assert(fd >= 0); + assert(s); + + r = getpeername(fd, &sa.peer.sa, &salen); + if (r < 0) + return log_unit_error_errno(UNIT(s), errno, "getpeername failed: %m"); + + if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) { + *p = NULL; + return 0; + } + + i = set_get(s->peers_by_address, &sa); + if (i) { + *p = socket_peer_ref(i); + return 1; + } + + remote = socket_peer_new(); + if (!remote) + return log_oom(); + + remote->peer = sa.peer; + remote->peer_salen = salen; + + r = set_put(s->peers_by_address, remote); + if (r < 0) + return r; + + remote->socket = s; + + *p = TAKE_PTR(remote); + + return 1; +} + +_const_ static const char* listen_lookup(int family, int type) { + + if (family == AF_NETLINK) + return "ListenNetlink"; + + if (type == SOCK_STREAM) + return "ListenStream"; + else if (type == SOCK_DGRAM) + return "ListenDatagram"; + else if (type == SOCK_SEQPACKET) + return "ListenSequentialPacket"; + + assert_not_reached("Unknown socket type"); + return NULL; +} + +static void socket_dump(Unit *u, FILE *f, const char *prefix) { + char time_string[FORMAT_TIMESPAN_MAX]; + SocketExecCommand c; + Socket *s = SOCKET(u); + SocketPort *p; + const char *prefix2, *str; + + assert(s); + assert(f); + + prefix = strempty(prefix); + prefix2 = strjoina(prefix, "\t"); + + fprintf(f, + "%sSocket State: %s\n" + "%sResult: %s\n" + "%sClean Result: %s\n" + "%sBindIPv6Only: %s\n" + "%sBacklog: %u\n" + "%sSocketMode: %04o\n" + "%sDirectoryMode: %04o\n" + "%sKeepAlive: %s\n" + "%sNoDelay: %s\n" + "%sFreeBind: %s\n" + "%sTransparent: %s\n" + "%sBroadcast: %s\n" + "%sPassCredentials: %s\n" + "%sPassSecurity: %s\n" + "%sTCPCongestion: %s\n" + "%sRemoveOnStop: %s\n" + "%sWritable: %s\n" + "%sFileDescriptorName: %s\n" + "%sSELinuxContextFromNet: %s\n", + prefix, socket_state_to_string(s->state), + prefix, socket_result_to_string(s->result), + prefix, socket_result_to_string(s->clean_result), + prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only), + prefix, s->backlog, + prefix, s->socket_mode, + prefix, s->directory_mode, + prefix, yes_no(s->keep_alive), + prefix, yes_no(s->no_delay), + prefix, yes_no(s->free_bind), + prefix, yes_no(s->transparent), + prefix, yes_no(s->broadcast), + prefix, yes_no(s->pass_cred), + prefix, yes_no(s->pass_sec), + prefix, strna(s->tcp_congestion), + prefix, yes_no(s->remove_on_stop), + prefix, yes_no(s->writable), + prefix, socket_fdname(s), + prefix, yes_no(s->selinux_context_from_net)); + + if (s->control_pid > 0) + fprintf(f, + "%sControl PID: "PID_FMT"\n", + prefix, s->control_pid); + + if (s->bind_to_device) + fprintf(f, + "%sBindToDevice: %s\n", + prefix, s->bind_to_device); + + if (s->accept) + fprintf(f, + "%sAccepted: %u\n" + "%sNConnections: %u\n" + "%sMaxConnections: %u\n" + "%sMaxConnectionsPerSource: %u\n", + prefix, s->n_accepted, + prefix, s->n_connections, + prefix, s->max_connections, + prefix, s->max_connections_per_source); + + if (s->priority >= 0) + fprintf(f, + "%sPriority: %i\n", + prefix, s->priority); + + if (s->receive_buffer > 0) + fprintf(f, + "%sReceiveBuffer: %zu\n", + prefix, s->receive_buffer); + + if (s->send_buffer > 0) + fprintf(f, + "%sSendBuffer: %zu\n", + prefix, s->send_buffer); + + if (s->ip_tos >= 0) + fprintf(f, + "%sIPTOS: %i\n", + prefix, s->ip_tos); + + if (s->ip_ttl >= 0) + fprintf(f, + "%sIPTTL: %i\n", + prefix, s->ip_ttl); + + if (s->pipe_size > 0) + fprintf(f, + "%sPipeSize: %zu\n", + prefix, s->pipe_size); + + if (s->mark >= 0) + fprintf(f, + "%sMark: %i\n", + prefix, s->mark); + + if (s->mq_maxmsg > 0) + fprintf(f, + "%sMessageQueueMaxMessages: %li\n", + prefix, s->mq_maxmsg); + + if (s->mq_msgsize > 0) + fprintf(f, + "%sMessageQueueMessageSize: %li\n", + prefix, s->mq_msgsize); + + if (s->reuse_port) + fprintf(f, + "%sReusePort: %s\n", + prefix, yes_no(s->reuse_port)); + + if (s->smack) + fprintf(f, + "%sSmackLabel: %s\n", + prefix, s->smack); + + if (s->smack_ip_in) + fprintf(f, + "%sSmackLabelIPIn: %s\n", + prefix, s->smack_ip_in); + + if (s->smack_ip_out) + fprintf(f, + "%sSmackLabelIPOut: %s\n", + prefix, s->smack_ip_out); + + if (!isempty(s->user) || !isempty(s->group)) + fprintf(f, + "%sSocketUser: %s\n" + "%sSocketGroup: %s\n", + prefix, strna(s->user), + prefix, strna(s->group)); + + if (s->keep_alive_time > 0) + fprintf(f, + "%sKeepAliveTimeSec: %s\n", + prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->keep_alive_time, USEC_PER_SEC)); + + if (s->keep_alive_interval > 0) + fprintf(f, + "%sKeepAliveIntervalSec: %s\n", + prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->keep_alive_interval, USEC_PER_SEC)); + + if (s->keep_alive_cnt > 0) + fprintf(f, + "%sKeepAliveProbes: %u\n", + prefix, s->keep_alive_cnt); + + if (s->defer_accept > 0) + fprintf(f, + "%sDeferAcceptSec: %s\n", + prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->defer_accept, USEC_PER_SEC)); + + LIST_FOREACH(port, p, s->ports) { + + switch (p->type) { + case SOCKET_SOCKET: { + _cleanup_free_ char *k = NULL; + const char *t; + int r; + + r = socket_address_print(&p->address, &k); + if (r < 0) + t = strerror_safe(r); + else + t = k; + + fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type), t); + break; + } + case SOCKET_SPECIAL: + fprintf(f, "%sListenSpecial: %s\n", prefix, p->path); + break; + case SOCKET_USB_FUNCTION: + fprintf(f, "%sListenUSBFunction: %s\n", prefix, p->path); + break; + case SOCKET_MQUEUE: + fprintf(f, "%sListenMessageQueue: %s\n", prefix, p->path); + break; + default: + fprintf(f, "%sListenFIFO: %s\n", prefix, p->path); + } + } + + fprintf(f, + "%sTriggerLimitIntervalSec: %s\n" + "%sTriggerLimitBurst: %u\n", + prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->trigger_limit.interval, USEC_PER_SEC), + prefix, s->trigger_limit.burst); + + str = ip_protocol_to_name(s->socket_protocol); + if (str) + fprintf(f, "%sSocketProtocol: %s\n", prefix, str); + + if (!strv_isempty(s->symlinks)) { + char **q; + + fprintf(f, "%sSymlinks:", prefix); + STRV_FOREACH(q, s->symlinks) + fprintf(f, " %s", *q); + + fprintf(f, "\n"); + } + + fprintf(f, + "%sTimeoutSec: %s\n", + prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->timeout_usec, USEC_PER_SEC)); + + exec_context_dump(&s->exec_context, f, prefix); + kill_context_dump(&s->kill_context, f, prefix); + + for (c = 0; c < _SOCKET_EXEC_COMMAND_MAX; c++) { + if (!s->exec_command[c]) + continue; + + fprintf(f, "%s-> %s:\n", + prefix, socket_exec_command_to_string(c)); + + exec_command_dump_list(s->exec_command[c], f, prefix2); + } + + cgroup_context_dump(UNIT(s), f, prefix); +} + +static int instance_from_socket(int fd, unsigned nr, char **instance) { + socklen_t l; + char *r; + union sockaddr_union local, remote; + + assert(fd >= 0); + assert(instance); + + l = sizeof(local); + if (getsockname(fd, &local.sa, &l) < 0) + return -errno; + + l = sizeof(remote); + if (getpeername(fd, &remote.sa, &l) < 0) + return -errno; + + switch (local.sa.sa_family) { + + case AF_INET: { + uint32_t + a = be32toh(local.in.sin_addr.s_addr), + b = be32toh(remote.in.sin_addr.s_addr); + + if (asprintf(&r, + "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u", + nr, + a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF, + be16toh(local.in.sin_port), + b >> 24, (b >> 16) & 0xFF, (b >> 8) & 0xFF, b & 0xFF, + be16toh(remote.in.sin_port)) < 0) + return -ENOMEM; + + break; + } + + case AF_INET6: { + static const unsigned char ipv4_prefix[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF + }; + + if (memcmp(&local.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0 && + memcmp(&remote.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) { + const uint8_t + *a = local.in6.sin6_addr.s6_addr+12, + *b = remote.in6.sin6_addr.s6_addr+12; + + if (asprintf(&r, + "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u", + nr, + a[0], a[1], a[2], a[3], + be16toh(local.in6.sin6_port), + b[0], b[1], b[2], b[3], + be16toh(remote.in6.sin6_port)) < 0) + return -ENOMEM; + } else { + char a[INET6_ADDRSTRLEN], b[INET6_ADDRSTRLEN]; + + if (asprintf(&r, + "%u-%s:%u-%s:%u", + nr, + inet_ntop(AF_INET6, &local.in6.sin6_addr, a, sizeof(a)), + be16toh(local.in6.sin6_port), + inet_ntop(AF_INET6, &remote.in6.sin6_addr, b, sizeof(b)), + be16toh(remote.in6.sin6_port)) < 0) + return -ENOMEM; + } + + break; + } + + case AF_UNIX: { + struct ucred ucred; + int k; + + k = getpeercred(fd, &ucred); + if (k >= 0) { + if (asprintf(&r, + "%u-"PID_FMT"-"UID_FMT, + nr, ucred.pid, ucred.uid) < 0) + return -ENOMEM; + } else if (k == -ENODATA) { + /* This handles the case where somebody is + * connecting from another pid/uid namespace + * (e.g. from outside of our container). */ + if (asprintf(&r, + "%u-unknown", + nr) < 0) + return -ENOMEM; + } else + return k; + + break; + } + + case AF_VSOCK: + if (asprintf(&r, + "%u-%u:%u-%u:%u", + nr, + local.vm.svm_cid, local.vm.svm_port, + remote.vm.svm_cid, remote.vm.svm_port) < 0) + return -ENOMEM; + + break; + + default: + assert_not_reached("Unhandled socket type."); + } + + *instance = r; + return 0; +} + +static void socket_close_fds(Socket *s) { + SocketPort *p; + char **i; + + assert(s); + + LIST_FOREACH(port, p, s->ports) { + bool was_open; + + was_open = p->fd >= 0; + + p->event_source = sd_event_source_unref(p->event_source); + p->fd = safe_close(p->fd); + socket_cleanup_fd_list(p); + + /* One little note: we should normally not delete any sockets in the file system here! After all some + * other process we spawned might still have a reference of this fd and wants to continue to use + * it. Therefore we normally delete sockets in the file system before we create a new one, not after we + * stopped using one! That all said, if the user explicitly requested this, we'll delete them here + * anyway, but only then. */ + + if (!was_open || !s->remove_on_stop) + continue; + + switch (p->type) { + + case SOCKET_FIFO: + (void) unlink(p->path); + break; + + case SOCKET_MQUEUE: + (void) mq_unlink(p->path); + break; + + case SOCKET_SOCKET: + (void) socket_address_unlink(&p->address); + break; + + default: + break; + } + } + + if (s->remove_on_stop) + STRV_FOREACH(i, s->symlinks) + (void) unlink(*i); +} + +static void socket_apply_socket_options(Socket *s, int fd) { + int r; + + assert(s); + assert(fd >= 0); + + if (s->keep_alive) { + r = setsockopt_int(fd, SOL_SOCKET, SO_KEEPALIVE, true); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "SO_KEEPALIVE failed: %m"); + } + + if (s->keep_alive_time > 0) { + r = setsockopt_int(fd, SOL_TCP, TCP_KEEPIDLE, s->keep_alive_time / USEC_PER_SEC); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "TCP_KEEPIDLE failed: %m"); + } + + if (s->keep_alive_interval > 0) { + r = setsockopt_int(fd, SOL_TCP, TCP_KEEPINTVL, s->keep_alive_interval / USEC_PER_SEC); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "TCP_KEEPINTVL failed: %m"); + } + + if (s->keep_alive_cnt > 0) { + r = setsockopt_int(fd, SOL_TCP, TCP_KEEPCNT, s->keep_alive_cnt); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "TCP_KEEPCNT failed: %m"); + } + + if (s->defer_accept > 0) { + r = setsockopt_int(fd, SOL_TCP, TCP_DEFER_ACCEPT, s->defer_accept / USEC_PER_SEC); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "TCP_DEFER_ACCEPT failed: %m"); + } + + if (s->no_delay) { + if (s->socket_protocol == IPPROTO_SCTP) { + r = setsockopt_int(fd, SOL_SCTP, SCTP_NODELAY, true); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "SCTP_NODELAY failed: %m"); + } else { + r = setsockopt_int(fd, SOL_TCP, TCP_NODELAY, true); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "TCP_NODELAY failed: %m"); + } + } + + if (s->broadcast) { + r = setsockopt_int(fd, SOL_SOCKET, SO_BROADCAST, true); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "SO_BROADCAST failed: %m"); + } + + if (s->pass_cred) { + r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "SO_PASSCRED failed: %m"); + } + + if (s->pass_sec) { + r = setsockopt_int(fd, SOL_SOCKET, SO_PASSSEC, true); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "SO_PASSSEC failed: %m"); + } + + if (s->priority >= 0) { + r = setsockopt_int(fd, SOL_SOCKET, SO_PRIORITY, s->priority); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "SO_PRIORITY failed: %m"); + } + + if (s->receive_buffer > 0) { + /* We first try with SO_RCVBUFFORCE, in case we have the perms for that */ + if (setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, s->receive_buffer) < 0) { + r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, s->receive_buffer); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "SO_RCVBUF failed: %m"); + } + } + + if (s->send_buffer > 0) { + if (setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, s->send_buffer) < 0) { + r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, s->send_buffer); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "SO_SNDBUF failed: %m"); + } + } + + if (s->mark >= 0) { + r = setsockopt_int(fd, SOL_SOCKET, SO_MARK, s->mark); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "SO_MARK failed: %m"); + } + + if (s->ip_tos >= 0) { + r = setsockopt_int(fd, IPPROTO_IP, IP_TOS, s->ip_tos); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "IP_TOS failed: %m"); + } + + if (s->ip_ttl >= 0) { + int x; + + r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, s->ip_ttl); + + if (socket_ipv6_is_supported()) + x = setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, s->ip_ttl); + else + x = -EAFNOSUPPORT; + + if (r < 0 && x < 0) + log_unit_warning_errno(UNIT(s), r, "IP_TTL/IPV6_UNICAST_HOPS failed: %m"); + } + + if (s->tcp_congestion) + if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0) + log_unit_warning_errno(UNIT(s), errno, "TCP_CONGESTION failed: %m"); + + if (s->smack_ip_in) { + r = mac_smack_apply_fd(fd, SMACK_ATTR_IPIN, s->smack_ip_in); + if (r < 0) + log_unit_error_errno(UNIT(s), r, "mac_smack_apply_ip_in_fd: %m"); + } + + if (s->smack_ip_out) { + r = mac_smack_apply_fd(fd, SMACK_ATTR_IPOUT, s->smack_ip_out); + if (r < 0) + log_unit_error_errno(UNIT(s), r, "mac_smack_apply_ip_out_fd: %m"); + } +} + +static void socket_apply_fifo_options(Socket *s, int fd) { + int r; + + assert(s); + assert(fd >= 0); + + if (s->pipe_size > 0) + if (fcntl(fd, F_SETPIPE_SZ, s->pipe_size) < 0) + log_unit_warning_errno(UNIT(s), errno, "Setting pipe size failed, ignoring: %m"); + + if (s->smack) { + r = mac_smack_apply_fd(fd, SMACK_ATTR_ACCESS, s->smack); + if (r < 0) + log_unit_error_errno(UNIT(s), r, "SMACK relabelling failed, ignoring: %m"); + } +} + +static int fifo_address_create( + const char *path, + mode_t directory_mode, + mode_t socket_mode) { + + _cleanup_close_ int fd = -1; + mode_t old_mask; + struct stat st; + int r; + + assert(path); + + (void) mkdir_parents_label(path, directory_mode); + + r = mac_selinux_create_file_prepare(path, S_IFIFO); + if (r < 0) + return r; + + /* Enforce the right access mode for the fifo */ + old_mask = umask(~socket_mode); + + /* Include the original umask in our mask */ + (void) umask(~socket_mode | old_mask); + + r = mkfifo(path, socket_mode); + (void) umask(old_mask); + + if (r < 0 && errno != EEXIST) { + r = -errno; + goto fail; + } + + fd = open(path, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK | O_NOFOLLOW); + if (fd < 0) { + r = -errno; + goto fail; + } + + mac_selinux_create_file_clear(); + + if (fstat(fd, &st) < 0) { + r = -errno; + goto fail; + } + + if (!S_ISFIFO(st.st_mode) || + (st.st_mode & 0777) != (socket_mode & ~old_mask) || + st.st_uid != getuid() || + st.st_gid != getgid()) { + r = -EEXIST; + goto fail; + } + + return TAKE_FD(fd); + +fail: + mac_selinux_create_file_clear(); + return r; +} + +static int special_address_create(const char *path, bool writable) { + _cleanup_close_ int fd = -1; + struct stat st; + + assert(path); + + fd = open(path, (writable ? O_RDWR : O_RDONLY)|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW); + if (fd < 0) + return -errno; + + if (fstat(fd, &st) < 0) + return -errno; + + /* Check whether this is a /proc, /sys or /dev file or char device */ + if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) + return -EEXIST; + + return TAKE_FD(fd); +} + +static int usbffs_address_create(const char *path) { + _cleanup_close_ int fd = -1; + struct stat st; + + assert(path); + + fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW); + if (fd < 0) + return -errno; + + if (fstat(fd, &st) < 0) + return -errno; + + /* Check whether this is a regular file (ffs endpoint) */ + if (!S_ISREG(st.st_mode)) + return -EEXIST; + + return TAKE_FD(fd); +} + +static int mq_address_create( + const char *path, + mode_t mq_mode, + long maxmsg, + long msgsize) { + + _cleanup_close_ int fd = -1; + struct stat st; + mode_t old_mask; + struct mq_attr _attr, *attr = NULL; + + assert(path); + + if (maxmsg > 0 && msgsize > 0) { + _attr = (struct mq_attr) { + .mq_flags = O_NONBLOCK, + .mq_maxmsg = maxmsg, + .mq_msgsize = msgsize, + }; + attr = &_attr; + } + + /* Enforce the right access mode for the mq */ + old_mask = umask(~mq_mode); + + /* Include the original umask in our mask */ + (void) umask(~mq_mode | old_mask); + fd = mq_open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_CREAT, mq_mode, attr); + (void) umask(old_mask); + + if (fd < 0) + return -errno; + + if (fstat(fd, &st) < 0) + return -errno; + + if ((st.st_mode & 0777) != (mq_mode & ~old_mask) || + st.st_uid != getuid() || + st.st_gid != getgid()) + return -EEXIST; + + return TAKE_FD(fd); +} + +static int socket_symlink(Socket *s) { + const char *p; + char **i; + int r; + + assert(s); + + p = socket_find_symlink_target(s); + if (!p) + return 0; + + STRV_FOREACH(i, s->symlinks) { + (void) mkdir_parents_label(*i, s->directory_mode); + + r = symlink_idempotent(p, *i, false); + + if (r == -EEXIST && s->remove_on_stop) { + /* If there's already something where we want to create the symlink, and the destructive + * RemoveOnStop= mode is set, then we might as well try to remove what already exists and try + * again. */ + + if (unlink(*i) >= 0) + r = symlink_idempotent(p, *i, false); + } + + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "Failed to create symlink %s → %s, ignoring: %m", p, *i); + } + + return 0; +} + +static int usbffs_write_descs(int fd, Service *s) { + int r; + + if (!s->usb_function_descriptors || !s->usb_function_strings) + return -EINVAL; + + r = copy_file_fd(s->usb_function_descriptors, fd, 0); + if (r < 0) + return r; + + return copy_file_fd(s->usb_function_strings, fd, 0); +} + +static int usbffs_select_ep(const struct dirent *d) { + return d->d_name[0] != '.' && !streq(d->d_name, "ep0"); +} + +static int usbffs_dispatch_eps(SocketPort *p) { + _cleanup_free_ struct dirent **ent = NULL; + size_t n, k, i; + int r; + + r = scandir(p->path, &ent, usbffs_select_ep, alphasort); + if (r < 0) + return -errno; + + n = (size_t) r; + p->auxiliary_fds = new(int, n); + if (!p->auxiliary_fds) { + r = -ENOMEM; + goto clear; + } + + p->n_auxiliary_fds = n; + + k = 0; + for (i = 0; i < n; ++i) { + _cleanup_free_ char *ep = NULL; + + ep = path_make_absolute(ent[i]->d_name, p->path); + if (!ep) { + r = -ENOMEM; + goto fail; + } + + path_simplify(ep, false); + + r = usbffs_address_create(ep); + if (r < 0) + goto fail; + + p->auxiliary_fds[k++] = r; + } + + r = 0; + goto clear; + +fail: + close_many(p->auxiliary_fds, k); + p->auxiliary_fds = mfree(p->auxiliary_fds); + p->n_auxiliary_fds = 0; + +clear: + for (i = 0; i < n; ++i) + free(ent[i]); + + return r; +} + +static int socket_determine_selinux_label(Socket *s, char **ret) { + Service *service; + ExecCommand *c; + _cleanup_free_ char *path = NULL; + int r; + + assert(s); + assert(ret); + + if (s->selinux_context_from_net) { + /* If this is requested, get label from the network label */ + + r = mac_selinux_get_our_label(ret); + if (r == -EOPNOTSUPP) + goto no_label; + + } else { + /* Otherwise, get it from the executable we are about to start */ + r = socket_instantiate_service(s); + if (r < 0) + return r; + + if (!UNIT_ISSET(s->service)) + goto no_label; + + service = SERVICE(UNIT_DEREF(s->service)); + c = service->exec_command[SERVICE_EXEC_START]; + if (!c) + goto no_label; + + r = chase_symlinks(c->path, service->exec_context.root_directory, CHASE_PREFIX_ROOT, &path, NULL); + if (r < 0) + goto no_label; + + r = mac_selinux_get_create_label_from_exe(path, ret); + if (IN_SET(r, -EPERM, -EOPNOTSUPP)) + goto no_label; + } + + return r; + +no_label: + *ret = NULL; + return 0; +} + +static int socket_address_listen_do( + Socket *s, + const SocketAddress *address, + const char *label) { + + assert(s); + assert(address); + + return socket_address_listen( + address, + SOCK_CLOEXEC|SOCK_NONBLOCK, + s->backlog, + s->bind_ipv6_only, + s->bind_to_device, + s->reuse_port, + s->free_bind, + s->transparent, + s->directory_mode, + s->socket_mode, + label); +} + +#define log_address_error_errno(u, address, error, fmt) \ + ({ \ + _cleanup_free_ char *_t = NULL; \ + \ + (void) socket_address_print(address, &_t); \ + log_unit_error_errno(u, error, fmt, strna(_t)); \ + }) + +static int fork_needed(const SocketAddress *address, const ExecContext *context) { + int r; + + assert(address); + assert(context); + + /* Check if we need to do the cgroup or netns stuff. If not we can do things much simpler. */ + + if (IN_SET(address->sockaddr.sa.sa_family, AF_INET, AF_INET6)) { + r = bpf_firewall_supported(); + if (r < 0) + return r; + if (r != BPF_FIREWALL_UNSUPPORTED) /* If BPF firewalling isn't supported anyway — there's no point in this forking complexity */ + return true; + } + + return context->private_network || context->network_namespace_path; +} + +static int socket_address_listen_in_cgroup( + Socket *s, + const SocketAddress *address, + const char *label) { + + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + int fd, r; + pid_t pid; + + assert(s); + assert(address); + + /* This is a wrapper around socket_address_listen(), that forks off a helper process inside the + * socket's cgroup and network namespace in which the socket is actually created. This way we ensure + * the socket is actually properly attached to the unit's cgroup for the purpose of BPF filtering and + * such. */ + + r = fork_needed(address, &s->exec_context); + if (r < 0) + return r; + if (r == 0) { + /* Shortcut things... */ + fd = socket_address_listen_do(s, address, label); + if (fd < 0) + return log_address_error_errno(UNIT(s), address, fd, "Failed to create listening socket (%s): %m"); + + return fd; + } + + r = unit_setup_exec_runtime(UNIT(s)); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed acquire runtime: %m"); + + if (s->exec_context.network_namespace_path && + s->exec_runtime && + s->exec_runtime->netns_storage_socket[0] >= 0) { + r = open_netns_path(s->exec_runtime->netns_storage_socket, s->exec_context.network_namespace_path); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to open network namespace path %s: %m", s->exec_context.network_namespace_path); + } + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0) + return log_unit_error_errno(UNIT(s), errno, "Failed to create communication channel: %m"); + + r = unit_fork_helper_process(UNIT(s), "(sd-listen)", &pid); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to fork off listener stub process: %m"); + if (r == 0) { + /* Child */ + + pair[0] = safe_close(pair[0]); + + if ((s->exec_context.private_network || s->exec_context.network_namespace_path) && + s->exec_runtime && + s->exec_runtime->netns_storage_socket[0] >= 0) { + + if (ns_type_supported(NAMESPACE_NET)) { + r = setup_netns(s->exec_runtime->netns_storage_socket); + if (r < 0) { + log_unit_error_errno(UNIT(s), r, "Failed to join network namespace: %m"); + _exit(EXIT_NETWORK); + } + } else if (s->exec_context.network_namespace_path) { + log_unit_error(UNIT(s), "Network namespace path configured but network namespaces not supported."); + _exit(EXIT_NETWORK); + } else + log_unit_warning(UNIT(s), "PrivateNetwork=yes is configured, but the kernel does not support network namespaces, ignoring."); + } + + fd = socket_address_listen_do(s, address, label); + if (fd < 0) { + log_address_error_errno(UNIT(s), address, fd, "Failed to create listening socket (%s): %m"); + _exit(EXIT_FAILURE); + } + + r = send_one_fd(pair[1], fd, 0); + if (r < 0) { + log_address_error_errno(UNIT(s), address, r, "Failed to send listening socket (%s) to parent: %m"); + _exit(EXIT_FAILURE); + } + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + fd = receive_one_fd(pair[0], 0); + + /* We synchronously wait for the helper, as it shouldn't be slow */ + r = wait_for_terminate_and_check("(sd-listen)", pid, WAIT_LOG_ABNORMAL); + if (r < 0) { + safe_close(fd); + return r; + } + + if (fd < 0) + return log_address_error_errno(UNIT(s), address, fd, "Failed to receive listening socket (%s): %m"); + + return fd; +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Socket *, socket_close_fds); + +static int socket_open_fds(Socket *_s) { + _cleanup_(socket_close_fdsp) Socket *s = _s; + _cleanup_(mac_selinux_freep) char *label = NULL; + bool know_label = false; + SocketPort *p; + int r; + + assert(s); + + LIST_FOREACH(port, p, s->ports) { + + if (p->fd >= 0) + continue; + + switch (p->type) { + + case SOCKET_SOCKET: + + if (!know_label) { + /* Figure out label, if we don't it know yet. We do it once, for the first socket where + * we need this and remember it for the rest. */ + + r = socket_determine_selinux_label(s, &label); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to determine SELinux label: %m"); + + know_label = true; + } + + /* Apply the socket protocol */ + switch (p->address.type) { + + case SOCK_STREAM: + case SOCK_SEQPACKET: + if (s->socket_protocol == IPPROTO_SCTP) + p->address.protocol = s->socket_protocol; + break; + + case SOCK_DGRAM: + if (s->socket_protocol == IPPROTO_UDPLITE) + p->address.protocol = s->socket_protocol; + break; + } + + p->fd = socket_address_listen_in_cgroup(s, &p->address, label); + if (p->fd < 0) + return p->fd; + + socket_apply_socket_options(s, p->fd); + socket_symlink(s); + break; + + case SOCKET_SPECIAL: + + p->fd = special_address_create(p->path, s->writable); + if (p->fd < 0) + return log_unit_error_errno(UNIT(s), p->fd, "Failed to open special file %s: %m", p->path); + break; + + case SOCKET_FIFO: + + p->fd = fifo_address_create( + p->path, + s->directory_mode, + s->socket_mode); + if (p->fd < 0) + return log_unit_error_errno(UNIT(s), p->fd, "Failed to open FIFO %s: %m", p->path); + + socket_apply_fifo_options(s, p->fd); + socket_symlink(s); + break; + + case SOCKET_MQUEUE: + + p->fd = mq_address_create( + p->path, + s->socket_mode, + s->mq_maxmsg, + s->mq_msgsize); + if (p->fd < 0) + return log_unit_error_errno(UNIT(s), p->fd, "Failed to open message queue %s: %m", p->path); + break; + + case SOCKET_USB_FUNCTION: { + _cleanup_free_ char *ep = NULL; + + ep = path_make_absolute("ep0", p->path); + + p->fd = usbffs_address_create(ep); + if (p->fd < 0) + return p->fd; + + r = usbffs_write_descs(p->fd, SERVICE(UNIT_DEREF(s->service))); + if (r < 0) + return r; + + r = usbffs_dispatch_eps(p); + if (r < 0) + return r; + + break; + } + default: + assert_not_reached("Unknown port type"); + } + } + + s = NULL; + return 0; +} + +static void socket_unwatch_fds(Socket *s) { + SocketPort *p; + int r; + + assert(s); + + LIST_FOREACH(port, p, s->ports) { + if (p->fd < 0) + continue; + + if (!p->event_source) + continue; + + r = sd_event_source_set_enabled(p->event_source, SD_EVENT_OFF); + if (r < 0) + log_unit_debug_errno(UNIT(s), r, "Failed to disable event source: %m"); + } +} + +static int socket_watch_fds(Socket *s) { + SocketPort *p; + int r; + + assert(s); + + LIST_FOREACH(port, p, s->ports) { + if (p->fd < 0) + continue; + + if (p->event_source) { + r = sd_event_source_set_enabled(p->event_source, SD_EVENT_ON); + if (r < 0) + goto fail; + } else { + r = sd_event_add_io(UNIT(s)->manager->event, &p->event_source, p->fd, EPOLLIN, socket_dispatch_io, p); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(p->event_source, "socket-port-io"); + } + } + + return 0; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to watch listening fds: %m"); + socket_unwatch_fds(s); + return r; +} + +enum { + SOCKET_OPEN_NONE, + SOCKET_OPEN_SOME, + SOCKET_OPEN_ALL, +}; + +static int socket_check_open(Socket *s) { + bool have_open = false, have_closed = false; + SocketPort *p; + + assert(s); + + LIST_FOREACH(port, p, s->ports) { + if (p->fd < 0) + have_closed = true; + else + have_open = true; + + if (have_open && have_closed) + return SOCKET_OPEN_SOME; + } + + if (have_open) + return SOCKET_OPEN_ALL; + + return SOCKET_OPEN_NONE; +} + +static void socket_set_state(Socket *s, SocketState state) { + SocketState old_state; + assert(s); + + if (s->state != state) + bus_unit_send_pending_change_signal(UNIT(s), false); + + old_state = s->state; + s->state = state; + + if (!IN_SET(state, + SOCKET_START_PRE, + SOCKET_START_CHOWN, + SOCKET_START_POST, + SOCKET_STOP_PRE, + SOCKET_STOP_PRE_SIGTERM, + SOCKET_STOP_PRE_SIGKILL, + SOCKET_STOP_POST, + SOCKET_FINAL_SIGTERM, + SOCKET_FINAL_SIGKILL, + SOCKET_CLEANING)) { + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + socket_unwatch_control_pid(s); + s->control_command = NULL; + s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; + } + + if (state != SOCKET_LISTENING) + socket_unwatch_fds(s); + + if (!IN_SET(state, + SOCKET_START_CHOWN, + SOCKET_START_POST, + SOCKET_LISTENING, + SOCKET_RUNNING, + SOCKET_STOP_PRE, + SOCKET_STOP_PRE_SIGTERM, + SOCKET_STOP_PRE_SIGKILL, + SOCKET_CLEANING)) + socket_close_fds(s); + + if (state != old_state) + log_unit_debug(UNIT(s), "Changed %s -> %s", socket_state_to_string(old_state), socket_state_to_string(state)); + + unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0); +} + +static int socket_coldplug(Unit *u) { + Socket *s = SOCKET(u); + int r; + + assert(s); + assert(s->state == SOCKET_DEAD); + + if (s->deserialized_state == s->state) + return 0; + + if (s->control_pid > 0 && + pid_is_unwaited(s->control_pid) && + IN_SET(s->deserialized_state, + SOCKET_START_PRE, + SOCKET_START_CHOWN, + SOCKET_START_POST, + SOCKET_STOP_PRE, + SOCKET_STOP_PRE_SIGTERM, + SOCKET_STOP_PRE_SIGKILL, + SOCKET_STOP_POST, + SOCKET_FINAL_SIGTERM, + SOCKET_FINAL_SIGKILL, + SOCKET_CLEANING)) { + + r = unit_watch_pid(UNIT(s), s->control_pid, false); + if (r < 0) + return r; + + r = socket_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec)); + if (r < 0) + return r; + } + + if (IN_SET(s->deserialized_state, + SOCKET_START_CHOWN, + SOCKET_START_POST, + SOCKET_LISTENING, + SOCKET_RUNNING)) { + + /* Originally, we used to simply reopen all sockets here that we didn't have file descriptors + * for. However, this is problematic, as we won't traverse through the SOCKET_START_CHOWN state for + * them, and thus the UID/GID wouldn't be right. Hence, instead simply check if we have all fds open, + * and if there's a mismatch, warn loudly. */ + + r = socket_check_open(s); + if (r == SOCKET_OPEN_NONE) + log_unit_warning(UNIT(s), + "Socket unit configuration has changed while unit has been running, " + "no open socket file descriptor left. " + "The socket unit is not functional until restarted."); + else if (r == SOCKET_OPEN_SOME) + log_unit_warning(UNIT(s), + "Socket unit configuration has changed while unit has been running, " + "and some socket file descriptors have not been opened yet. " + "The socket unit is not fully functional until restarted."); + } + + if (s->deserialized_state == SOCKET_LISTENING) { + r = socket_watch_fds(s); + if (r < 0) + return r; + } + + if (!IN_SET(s->deserialized_state, SOCKET_DEAD, SOCKET_FAILED, SOCKET_CLEANING)) { + (void) unit_setup_dynamic_creds(u); + (void) unit_setup_exec_runtime(u); + } + + socket_set_state(s, s->deserialized_state); + return 0; +} + +static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { + + _cleanup_(exec_params_clear) ExecParameters exec_params = { + .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + .stdin_fd = -1, + .stdout_fd = -1, + .stderr_fd = -1, + .exec_fd = -1, + }; + pid_t pid; + int r; + + assert(s); + assert(c); + assert(_pid); + + r = unit_prepare_exec(UNIT(s)); + if (r < 0) + return r; + + r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); + if (r < 0) + return r; + + r = unit_set_exec_params(UNIT(s), &exec_params); + if (r < 0) + return r; + + r = exec_spawn(UNIT(s), + c, + &s->exec_context, + &exec_params, + s->exec_runtime, + &s->dynamic_creds, + &pid); + if (r < 0) + return r; + + r = unit_watch_pid(UNIT(s), pid, true); + if (r < 0) + return r; + + *_pid = pid; + + return 0; +} + +static int socket_chown(Socket *s, pid_t *_pid) { + pid_t pid; + int r; + + r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); + if (r < 0) + goto fail; + + /* We have to resolve the user names out-of-process, hence + * let's fork here. It's messy, but well, what can we do? */ + + r = unit_fork_helper_process(UNIT(s), "(sd-chown)", &pid); + if (r < 0) + return r; + if (r == 0) { + uid_t uid = UID_INVALID; + gid_t gid = GID_INVALID; + SocketPort *p; + + /* Child */ + + if (!isempty(s->user)) { + const char *user = s->user; + + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); + if (r < 0) { + log_unit_error_errno(UNIT(s), r, "Failed to resolve user %s: %m", user); + _exit(EXIT_USER); + } + } + + if (!isempty(s->group)) { + const char *group = s->group; + + r = get_group_creds(&group, &gid, 0); + if (r < 0) { + log_unit_error_errno(UNIT(s), r, "Failed to resolve group %s: %m", group); + _exit(EXIT_GROUP); + } + } + + LIST_FOREACH(port, p, s->ports) { + const char *path = NULL; + + if (p->type == SOCKET_SOCKET) + path = socket_address_get_path(&p->address); + else if (p->type == SOCKET_FIFO) + path = p->path; + + if (!path) + continue; + + if (chown(path, uid, gid) < 0) { + log_unit_error_errno(UNIT(s), errno, "Failed to chown(): %m"); + _exit(EXIT_CHOWN); + } + } + + _exit(EXIT_SUCCESS); + } + + r = unit_watch_pid(UNIT(s), pid, true); + if (r < 0) + goto fail; + + *_pid = pid; + return 0; + +fail: + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + return r; +} + +static void socket_enter_dead(Socket *s, SocketResult f) { + assert(s); + + if (s->result == SOCKET_SUCCESS) + s->result = f; + + if (s->result == SOCKET_SUCCESS) + unit_log_success(UNIT(s)); + else + unit_log_failure(UNIT(s), socket_result_to_string(s->result)); + + socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD); + + s->exec_runtime = exec_runtime_unref(s->exec_runtime, true); + + unit_destroy_runtime_directory(UNIT(s), &s->exec_context); + + unit_unref_uid_gid(UNIT(s), true); + + dynamic_creds_destroy(&s->dynamic_creds); +} + +static void socket_enter_signal(Socket *s, SocketState state, SocketResult f); + +static void socket_enter_stop_post(Socket *s, SocketResult f) { + int r; + assert(s); + + if (s->result == SOCKET_SUCCESS) + s->result = f; + + socket_unwatch_control_pid(s); + s->control_command_id = SOCKET_EXEC_STOP_POST; + s->control_command = s->exec_command[SOCKET_EXEC_STOP_POST]; + + if (s->control_command) { + r = socket_spawn(s, s->control_command, &s->control_pid); + if (r < 0) + goto fail; + + socket_set_state(s, SOCKET_STOP_POST); + } else + socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_SUCCESS); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-post' task: %m"); + socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES); +} + +static int state_to_kill_operation(Socket *s, SocketState state) { + if (state == SOCKET_STOP_PRE_SIGTERM && unit_has_job_type(UNIT(s), JOB_RESTART)) + return KILL_RESTART; + + if (state == SOCKET_FINAL_SIGTERM) + return KILL_TERMINATE; + + return KILL_KILL; +} + +static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) { + int r; + + assert(s); + + if (s->result == SOCKET_SUCCESS) + s->result = f; + + r = unit_kill_context( + UNIT(s), + &s->kill_context, + state_to_kill_operation(s, state), + -1, + s->control_pid, + false); + if (r < 0) + goto fail; + + if (r > 0) { + r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); + if (r < 0) + goto fail; + + socket_set_state(s, state); + } else if (state == SOCKET_STOP_PRE_SIGTERM) + socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, SOCKET_SUCCESS); + else if (state == SOCKET_STOP_PRE_SIGKILL) + socket_enter_stop_post(s, SOCKET_SUCCESS); + else if (state == SOCKET_FINAL_SIGTERM) + socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_SUCCESS); + else + socket_enter_dead(s, SOCKET_SUCCESS); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); + + if (IN_SET(state, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL)) + socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES); + else + socket_enter_dead(s, SOCKET_FAILURE_RESOURCES); +} + +static void socket_enter_stop_pre(Socket *s, SocketResult f) { + int r; + assert(s); + + if (s->result == SOCKET_SUCCESS) + s->result = f; + + socket_unwatch_control_pid(s); + s->control_command_id = SOCKET_EXEC_STOP_PRE; + s->control_command = s->exec_command[SOCKET_EXEC_STOP_PRE]; + + if (s->control_command) { + r = socket_spawn(s, s->control_command, &s->control_pid); + if (r < 0) + goto fail; + + socket_set_state(s, SOCKET_STOP_PRE); + } else + socket_enter_stop_post(s, SOCKET_SUCCESS); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-pre' task: %m"); + socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES); +} + +static void socket_enter_listening(Socket *s) { + int r; + assert(s); + + r = socket_watch_fds(s); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to watch sockets: %m"); + goto fail; + } + + socket_set_state(s, SOCKET_LISTENING); + return; + +fail: + socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); +} + +static void socket_enter_start_post(Socket *s) { + int r; + assert(s); + + socket_unwatch_control_pid(s); + s->control_command_id = SOCKET_EXEC_START_POST; + s->control_command = s->exec_command[SOCKET_EXEC_START_POST]; + + if (s->control_command) { + r = socket_spawn(s, s->control_command, &s->control_pid); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-post' task: %m"); + goto fail; + } + + socket_set_state(s, SOCKET_START_POST); + } else + socket_enter_listening(s); + + return; + +fail: + socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); +} + +static void socket_enter_start_chown(Socket *s) { + int r; + + assert(s); + + r = socket_open_fds(s); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to listen on sockets: %m"); + goto fail; + } + + if (!isempty(s->user) || !isempty(s->group)) { + + socket_unwatch_control_pid(s); + s->control_command_id = SOCKET_EXEC_START_CHOWN; + s->control_command = NULL; + + r = socket_chown(s, &s->control_pid); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to fork 'start-chown' task: %m"); + goto fail; + } + + socket_set_state(s, SOCKET_START_CHOWN); + } else + socket_enter_start_post(s); + + return; + +fail: + socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); +} + +static void socket_enter_start_pre(Socket *s) { + int r; + assert(s); + + socket_unwatch_control_pid(s); + + unit_warn_leftover_processes(UNIT(s)); + + s->control_command_id = SOCKET_EXEC_START_PRE; + s->control_command = s->exec_command[SOCKET_EXEC_START_PRE]; + + if (s->control_command) { + r = socket_spawn(s, s->control_command, &s->control_pid); + if (r < 0) { + log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-pre' task: %m"); + goto fail; + } + + socket_set_state(s, SOCKET_START_PRE); + } else + socket_enter_start_chown(s); + + return; + +fail: + socket_enter_dead(s, SOCKET_FAILURE_RESOURCES); +} + +static void flush_ports(Socket *s) { + SocketPort *p; + + /* Flush all incoming traffic, regardless if actual bytes or new connections, so that this socket isn't busy + * anymore */ + + LIST_FOREACH(port, p, s->ports) { + if (p->fd < 0) + continue; + + (void) flush_accept(p->fd); + (void) flush_fd(p->fd); + } +} + +static void socket_enter_running(Socket *s, int cfd) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + /* Note that this call takes possession of the connection fd passed. It either has to assign it somewhere or + * close it. */ + + assert(s); + + /* We don't take connections anymore if we are supposed to shut down anyway */ + if (unit_stop_pending(UNIT(s))) { + + log_unit_debug(UNIT(s), "Suppressing connection request since unit stop is scheduled."); + + if (cfd >= 0) + goto refuse; + else + flush_ports(s); + + return; + } + + if (!ratelimit_below(&s->trigger_limit)) { + log_unit_warning(UNIT(s), "Trigger limit hit, refusing further activation."); + socket_enter_stop_pre(s, SOCKET_FAILURE_TRIGGER_LIMIT_HIT); + goto refuse; + } + + if (cfd < 0) { + bool pending = false; + Unit *other; + Iterator i; + void *v; + + /* If there's already a start pending don't bother to + * do anything */ + HASHMAP_FOREACH_KEY(v, other, UNIT(s)->dependencies[UNIT_TRIGGERS], i) + if (unit_active_or_pending(other)) { + pending = true; + break; + } + + if (!pending) { + if (!UNIT_ISSET(s->service)) { + log_unit_error(UNIT(s), "Service to activate vanished, refusing activation."); + r = -ENOENT; + goto fail; + } + + r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, NULL, &error, NULL); + if (r < 0) + goto fail; + } + + socket_set_state(s, SOCKET_RUNNING); + } else { + _cleanup_free_ char *prefix = NULL, *instance = NULL, *name = NULL; + _cleanup_(socket_peer_unrefp) SocketPeer *p = NULL; + Service *service; + + if (s->n_connections >= s->max_connections) { + log_unit_warning(UNIT(s), "Too many incoming connections (%u), dropping connection.", + s->n_connections); + goto refuse; + } + + if (s->max_connections_per_source > 0) { + r = socket_acquire_peer(s, cfd, &p); + if (r < 0) { + goto refuse; + } else if (r > 0 && p->n_ref > s->max_connections_per_source) { + _cleanup_free_ char *t = NULL; + + (void) sockaddr_pretty(&p->peer.sa, p->peer_salen, true, false, &t); + + log_unit_warning(UNIT(s), + "Too many incoming connections (%u) from source %s, dropping connection.", + p->n_ref, strnull(t)); + goto refuse; + } + } + + r = socket_instantiate_service(s); + if (r < 0) + goto fail; + + r = instance_from_socket(cfd, s->n_accepted, &instance); + if (r < 0) { + if (r != -ENOTCONN) + goto fail; + + /* ENOTCONN is legitimate if TCP RST was received. + * This connection is over, but the socket unit lives on. */ + log_unit_debug(UNIT(s), "Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring."); + goto refuse; + } + + r = unit_name_to_prefix(UNIT(s)->id, &prefix); + if (r < 0) + goto fail; + + r = unit_name_build(prefix, instance, ".service", &name); + if (r < 0) + goto fail; + + r = unit_add_name(UNIT_DEREF(s->service), name); + if (r < 0) + goto fail; + + service = SERVICE(UNIT_DEREF(s->service)); + unit_ref_unset(&s->service); + + s->n_accepted++; + unit_choose_id(UNIT(service), name); + + r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net); + if (r < 0) + goto fail; + + cfd = -1; /* We passed ownership of the fd to the service now. Forget it here. */ + s->n_connections++; + + service->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */ + + r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, NULL, &error, NULL); + if (r < 0) { + /* We failed to activate the new service, but it still exists. Let's make sure the service + * closes and forgets the connection fd again, immediately. */ + service_close_socket_fd(service); + goto fail; + } + + /* Notify clients about changed counters */ + unit_add_to_dbus_queue(UNIT(s)); + } + + return; + +refuse: + s->n_refused++; + safe_close(cfd); + return; + +fail: + log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s", + cfd >= 0 ? "template" : "non-template", + bus_error_message(&error, r)); + + socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); + safe_close(cfd); +} + +static void socket_run_next(Socket *s) { + int r; + + assert(s); + assert(s->control_command); + assert(s->control_command->command_next); + + socket_unwatch_control_pid(s); + + s->control_command = s->control_command->command_next; + + r = socket_spawn(s, s->control_command, &s->control_pid); + if (r < 0) + goto fail; + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run next task: %m"); + + if (s->state == SOCKET_START_POST) + socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); + else if (s->state == SOCKET_STOP_POST) + socket_enter_dead(s, SOCKET_FAILURE_RESOURCES); + else + socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES); +} + +static int socket_start(Unit *u) { + Socket *s = SOCKET(u); + int r; + + assert(s); + + /* We cannot fulfill this request right now, try again later + * please! */ + if (IN_SET(s->state, + SOCKET_STOP_PRE, + SOCKET_STOP_PRE_SIGKILL, + SOCKET_STOP_PRE_SIGTERM, + SOCKET_STOP_POST, + SOCKET_FINAL_SIGTERM, + SOCKET_FINAL_SIGKILL, + SOCKET_CLEANING)) + return -EAGAIN; + + /* Already on it! */ + if (IN_SET(s->state, + SOCKET_START_PRE, + SOCKET_START_CHOWN, + SOCKET_START_POST)) + return 0; + + /* Cannot run this without the service being around */ + if (UNIT_ISSET(s->service)) { + Service *service; + + service = SERVICE(UNIT_DEREF(s->service)); + + if (UNIT(service)->load_state != UNIT_LOADED) { + log_unit_error(u, "Socket service %s not loaded, refusing.", UNIT(service)->id); + return -ENOENT; + } + + /* If the service is already active we cannot start the + * socket */ + if (!IN_SET(service->state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) { + log_unit_error(u, "Socket service %s already active, refusing.", UNIT(service)->id); + return -EBUSY; + } + } + + assert(IN_SET(s->state, SOCKET_DEAD, SOCKET_FAILED)); + + r = unit_test_start_limit(u); + if (r < 0) { + socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT); + return r; + } + + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + + s->result = SOCKET_SUCCESS; + exec_command_reset_status_list_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX); + + u->reset_accounting = true; + + socket_enter_start_pre(s); + return 1; +} + +static int socket_stop(Unit *u) { + Socket *s = SOCKET(u); + + assert(s); + + /* Already on it */ + if (IN_SET(s->state, + SOCKET_STOP_PRE, + SOCKET_STOP_PRE_SIGTERM, + SOCKET_STOP_PRE_SIGKILL, + SOCKET_STOP_POST, + SOCKET_FINAL_SIGTERM, + SOCKET_FINAL_SIGKILL)) + return 0; + + /* If there's already something running we go directly into + * kill mode. */ + if (IN_SET(s->state, + SOCKET_START_PRE, + SOCKET_START_CHOWN, + SOCKET_START_POST)) { + socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, SOCKET_SUCCESS); + return -EAGAIN; + } + + /* If we are currently cleaning, then abort it, brutally. */ + if (s->state == SOCKET_CLEANING) { + socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_SUCCESS); + return 0; + } + + assert(IN_SET(s->state, SOCKET_LISTENING, SOCKET_RUNNING)); + + socket_enter_stop_pre(s, SOCKET_SUCCESS); + return 1; +} + +static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { + Socket *s = SOCKET(u); + SocketPort *p; + int r; + + assert(u); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", socket_state_to_string(s->state)); + (void) serialize_item(f, "result", socket_result_to_string(s->result)); + (void) serialize_item_format(f, "n-accepted", "%u", s->n_accepted); + (void) serialize_item_format(f, "n-refused", "%u", s->n_refused); + + if (s->control_pid > 0) + (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid); + + if (s->control_command_id >= 0) + (void) serialize_item(f, "control-command", socket_exec_command_to_string(s->control_command_id)); + + LIST_FOREACH(port, p, s->ports) { + int copy; + + if (p->fd < 0) + continue; + + copy = fdset_put_dup(fds, p->fd); + if (copy < 0) + return log_unit_warning_errno(u, copy, "Failed to serialize socket fd: %m"); + + if (p->type == SOCKET_SOCKET) { + _cleanup_free_ char *t = NULL; + + r = socket_address_print(&p->address, &t); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to format socket address: %m"); + + if (socket_address_family(&p->address) == AF_NETLINK) + (void) serialize_item_format(f, "netlink", "%i %s", copy, t); + else + (void) serialize_item_format(f, "socket", "%i %i %s", copy, p->address.type, t); + } else if (p->type == SOCKET_SPECIAL) + (void) serialize_item_format(f, "special", "%i %s", copy, p->path); + else if (p->type == SOCKET_MQUEUE) + (void) serialize_item_format(f, "mqueue", "%i %s", copy, p->path); + else if (p->type == SOCKET_USB_FUNCTION) + (void) serialize_item_format(f, "ffs", "%i %s", copy, p->path); + else { + assert(p->type == SOCKET_FIFO); + (void) serialize_item_format(f, "fifo", "%i %s", copy, p->path); + } + } + + return 0; +} + +static void socket_port_take_fd(SocketPort *p, FDSet *fds, int fd) { + assert(p); + + safe_close(p->fd); + p->fd = fdset_remove(fds, fd); +} + +static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Socket *s = SOCKET(u); + + assert(u); + assert(key); + assert(value); + + if (streq(key, "state")) { + SocketState state; + + state = socket_state_from_string(value); + if (state < 0) + log_unit_debug(u, "Failed to parse state value: %s", value); + else + s->deserialized_state = state; + } else if (streq(key, "result")) { + SocketResult f; + + f = socket_result_from_string(value); + if (f < 0) + log_unit_debug(u, "Failed to parse result value: %s", value); + else if (f != SOCKET_SUCCESS) + s->result = f; + + } else if (streq(key, "n-accepted")) { + unsigned k; + + if (safe_atou(value, &k) < 0) + log_unit_debug(u, "Failed to parse n-accepted value: %s", value); + else + s->n_accepted += k; + } else if (streq(key, "n-refused")) { + unsigned k; + + if (safe_atou(value, &k) < 0) + log_unit_debug(u, "Failed to parse n-refused value: %s", value); + else + s->n_refused += k; + } else if (streq(key, "control-pid")) { + pid_t pid; + + if (parse_pid(value, &pid) < 0) + log_unit_debug(u, "Failed to parse control-pid value: %s", value); + else + s->control_pid = pid; + } else if (streq(key, "control-command")) { + SocketExecCommand id; + + id = socket_exec_command_from_string(value); + if (id < 0) + log_unit_debug(u, "Failed to parse exec-command value: %s", value); + else { + s->control_command_id = id; + s->control_command = s->exec_command[id]; + } + } else if (streq(key, "fifo")) { + int fd, skip = 0; + SocketPort *p; + + if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse fifo value: %s", value); + else + LIST_FOREACH(port, p, s->ports) + if (p->type == SOCKET_FIFO && + path_equal_or_files_same(p->path, value+skip, 0)) { + socket_port_take_fd(p, fds, fd); + break; + } + + } else if (streq(key, "special")) { + int fd, skip = 0; + SocketPort *p; + + if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse special value: %s", value); + else + LIST_FOREACH(port, p, s->ports) + if (p->type == SOCKET_SPECIAL && + path_equal_or_files_same(p->path, value+skip, 0)) { + socket_port_take_fd(p, fds, fd); + break; + } + + } else if (streq(key, "mqueue")) { + int fd, skip = 0; + SocketPort *p; + + if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse mqueue value: %s", value); + else + LIST_FOREACH(port, p, s->ports) + if (p->type == SOCKET_MQUEUE && + streq(p->path, value+skip)) { + socket_port_take_fd(p, fds, fd); + break; + } + + } else if (streq(key, "socket")) { + int fd, type, skip = 0; + SocketPort *p; + + if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse socket value: %s", value); + else + LIST_FOREACH(port, p, s->ports) + if (socket_address_is(&p->address, value+skip, type)) { + socket_port_take_fd(p, fds, fd); + break; + } + + } else if (streq(key, "netlink")) { + int fd, skip = 0; + SocketPort *p; + + if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse socket value: %s", value); + else + LIST_FOREACH(port, p, s->ports) + if (socket_address_is_netlink(&p->address, value+skip)) { + socket_port_take_fd(p, fds, fd); + break; + } + + } else if (streq(key, "ffs")) { + int fd, skip = 0; + SocketPort *p; + + if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) + log_unit_debug(u, "Failed to parse ffs value: %s", value); + else + LIST_FOREACH(port, p, s->ports) + if (p->type == SOCKET_USB_FUNCTION && + path_equal_or_files_same(p->path, value+skip, 0)) { + socket_port_take_fd(p, fds, fd); + break; + } + + } else + log_unit_debug(UNIT(s), "Unknown serialization key: %s", key); + + return 0; +} + +static void socket_distribute_fds(Unit *u, FDSet *fds) { + Socket *s = SOCKET(u); + SocketPort *p; + + assert(u); + + LIST_FOREACH(port, p, s->ports) { + Iterator i; + int fd; + + if (p->type != SOCKET_SOCKET) + continue; + + if (p->fd >= 0) + continue; + + FDSET_FOREACH(fd, fds, i) { + if (socket_address_matches_fd(&p->address, fd)) { + p->fd = fdset_remove(fds, fd); + s->deserialized_state = SOCKET_LISTENING; + break; + } + } + } +} + +_pure_ static UnitActiveState socket_active_state(Unit *u) { + assert(u); + + return state_translation_table[SOCKET(u)->state]; +} + +_pure_ static const char *socket_sub_state_to_string(Unit *u) { + assert(u); + + return socket_state_to_string(SOCKET(u)->state); +} + +const char* socket_port_type_to_string(SocketPort *p) { + + assert(p); + + switch (p->type) { + + case SOCKET_SOCKET: + + switch (p->address.type) { + + case SOCK_STREAM: + return "Stream"; + + case SOCK_DGRAM: + return "Datagram"; + + case SOCK_SEQPACKET: + return "SequentialPacket"; + + case SOCK_RAW: + if (socket_address_family(&p->address) == AF_NETLINK) + return "Netlink"; + + _fallthrough_; + default: + return NULL; + } + + case SOCKET_SPECIAL: + return "Special"; + + case SOCKET_MQUEUE: + return "MessageQueue"; + + case SOCKET_FIFO: + return "FIFO"; + + case SOCKET_USB_FUNCTION: + return "USBFunction"; + + default: + return NULL; + } +} + +SocketType socket_port_type_from_string(const char *s) { + assert(s); + + if (STR_IN_SET(s, "Stream", "Datagram", "SequentialPacket", "Netlink")) + return SOCKET_SOCKET; + else if (streq(s, "Special")) + return SOCKET_SPECIAL; + else if (streq(s, "MessageQueue")) + return SOCKET_MQUEUE; + else if (streq(s, "FIFO")) + return SOCKET_FIFO; + else if (streq(s, "USBFunction")) + return SOCKET_USB_FUNCTION; + else + return _SOCKET_TYPE_INVALID; +} + +_pure_ static bool socket_may_gc(Unit *u) { + Socket *s = SOCKET(u); + + assert(u); + + return s->n_connections == 0; +} + +static int socket_accept_do(Socket *s, int fd) { + int cfd; + + assert(s); + assert(fd >= 0); + + cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); + if (cfd < 0) + /* Convert transient network errors into clean and well-defined EAGAIN */ + return ERRNO_IS_ACCEPT_AGAIN(errno) ? -EAGAIN : -errno; + + return cfd; +} + +static int socket_accept_in_cgroup(Socket *s, SocketPort *p, int fd) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + int cfd, r; + pid_t pid; + + assert(s); + assert(p); + assert(fd >= 0); + + /* Similar to socket_address_listen_in_cgroup(), but for accept() rather than socket(): make sure that any + * connection socket is also properly associated with the cgroup. */ + + if (!IN_SET(p->address.sockaddr.sa.sa_family, AF_INET, AF_INET6)) + goto shortcut; + + r = bpf_firewall_supported(); + if (r < 0) + return r; + if (r == BPF_FIREWALL_UNSUPPORTED) + goto shortcut; + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0) + return log_unit_error_errno(UNIT(s), errno, "Failed to create communication channel: %m"); + + r = unit_fork_helper_process(UNIT(s), "(sd-accept)", &pid); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to fork off accept stub process: %m"); + if (r == 0) { + /* Child */ + + pair[0] = safe_close(pair[0]); + + cfd = socket_accept_do(s, fd); + if (cfd == -EAGAIN) /* spurious accept() */ + _exit(EXIT_SUCCESS); + if (cfd < 0) { + log_unit_error_errno(UNIT(s), cfd, "Failed to accept connection socket: %m"); + _exit(EXIT_FAILURE); + } + + r = send_one_fd(pair[1], cfd, 0); + if (r < 0) { + log_unit_error_errno(UNIT(s), r, "Failed to send connection socket to parent: %m"); + _exit(EXIT_FAILURE); + } + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + cfd = receive_one_fd(pair[0], 0); + + /* We synchronously wait for the helper, as it shouldn't be slow */ + r = wait_for_terminate_and_check("(sd-accept)", pid, WAIT_LOG_ABNORMAL); + if (r < 0) { + safe_close(cfd); + return r; + } + + /* If we received no fd, we got EIO here. If this happens with a process exit code of EXIT_SUCCESS + * this is a spurious accept(), let's convert that back to EAGAIN here. */ + if (cfd == -EIO) + return -EAGAIN; + if (cfd < 0) + return log_unit_error_errno(UNIT(s), cfd, "Failed to receive connection socket: %m"); + + return cfd; + +shortcut: + cfd = socket_accept_do(s, fd); + if (cfd == -EAGAIN) /* spurious accept(), skip it silently */ + return -EAGAIN; + if (cfd < 0) + return log_unit_error_errno(UNIT(s), cfd, "Failed to accept connection socket: %m"); + + return cfd; +} + +static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + SocketPort *p = userdata; + int cfd = -1; + + assert(p); + assert(fd >= 0); + + if (p->socket->state != SOCKET_LISTENING) + return 0; + + log_unit_debug(UNIT(p->socket), "Incoming traffic"); + + if (revents != EPOLLIN) { + if (revents & EPOLLHUP) + log_unit_error(UNIT(p->socket), "Got POLLHUP on a listening socket. The service probably invoked shutdown() on it, and should better not do that."); + else + log_unit_error(UNIT(p->socket), "Got unexpected poll event (0x%x) on socket.", revents); + goto fail; + } + + if (p->socket->accept && + p->type == SOCKET_SOCKET && + socket_address_can_accept(&p->address)) { + + cfd = socket_accept_in_cgroup(p->socket, p, fd); + if (cfd == -EAGAIN) /* Spurious accept() */ + return 0; + if (cfd < 0) + goto fail; + + socket_apply_socket_options(p->socket, cfd); + } + + socket_enter_running(p->socket, cfd); + return 0; + +fail: + socket_enter_stop_pre(p->socket, SOCKET_FAILURE_RESOURCES); + return 0; +} + +static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) { + Socket *s = SOCKET(u); + SocketResult f; + + assert(s); + assert(pid >= 0); + + if (pid != s->control_pid) + return; + + s->control_pid = 0; + + if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL)) + f = SOCKET_SUCCESS; + else if (code == CLD_EXITED) + f = SOCKET_FAILURE_EXIT_CODE; + else if (code == CLD_KILLED) + f = SOCKET_FAILURE_SIGNAL; + else if (code == CLD_DUMPED) + f = SOCKET_FAILURE_CORE_DUMP; + else + assert_not_reached("Unknown sigchld code"); + + if (s->control_command) { + exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status); + + if (s->control_command->flags & EXEC_COMMAND_IGNORE_FAILURE) + f = SOCKET_SUCCESS; + } + + unit_log_process_exit( + u, + "Control process", + socket_exec_command_to_string(s->control_command_id), + f == SOCKET_SUCCESS, + code, status); + + if (s->result == SOCKET_SUCCESS) + s->result = f; + + if (s->control_command && + s->control_command->command_next && + f == SOCKET_SUCCESS) { + + log_unit_debug(u, "Running next command for state %s", socket_state_to_string(s->state)); + socket_run_next(s); + } else { + s->control_command = NULL; + s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; + + /* No further commands for this step, so let's figure + * out what to do next */ + + log_unit_debug(u, "Got final SIGCHLD for state %s", socket_state_to_string(s->state)); + + switch (s->state) { + + case SOCKET_START_PRE: + if (f == SOCKET_SUCCESS) + socket_enter_start_chown(s); + else + socket_enter_signal(s, SOCKET_FINAL_SIGTERM, f); + break; + + case SOCKET_START_CHOWN: + if (f == SOCKET_SUCCESS) + socket_enter_start_post(s); + else + socket_enter_stop_pre(s, f); + break; + + case SOCKET_START_POST: + if (f == SOCKET_SUCCESS) + socket_enter_listening(s); + else + socket_enter_stop_pre(s, f); + break; + + case SOCKET_STOP_PRE: + case SOCKET_STOP_PRE_SIGTERM: + case SOCKET_STOP_PRE_SIGKILL: + socket_enter_stop_post(s, f); + break; + + case SOCKET_STOP_POST: + case SOCKET_FINAL_SIGTERM: + case SOCKET_FINAL_SIGKILL: + socket_enter_dead(s, f); + break; + + case SOCKET_CLEANING: + + if (s->clean_result == SOCKET_SUCCESS) + s->clean_result = f; + + socket_enter_dead(s, SOCKET_SUCCESS); + break; + + default: + assert_not_reached("Uh, control process died at wrong time."); + } + } + + /* Notify clients about changed exit status */ + unit_add_to_dbus_queue(u); +} + +static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { + Socket *s = SOCKET(userdata); + + assert(s); + assert(s->timer_event_source == source); + + switch (s->state) { + + case SOCKET_START_PRE: + log_unit_warning(UNIT(s), "Starting timed out. Terminating."); + socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT); + break; + + case SOCKET_START_CHOWN: + case SOCKET_START_POST: + log_unit_warning(UNIT(s), "Starting timed out. Stopping."); + socket_enter_stop_pre(s, SOCKET_FAILURE_TIMEOUT); + break; + + case SOCKET_STOP_PRE: + log_unit_warning(UNIT(s), "Stopping timed out. Terminating."); + socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, SOCKET_FAILURE_TIMEOUT); + break; + + case SOCKET_STOP_PRE_SIGTERM: + if (s->kill_context.send_sigkill) { + log_unit_warning(UNIT(s), "Stopping timed out. Killing."); + socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, SOCKET_FAILURE_TIMEOUT); + } else { + log_unit_warning(UNIT(s), "Stopping timed out. Skipping SIGKILL. Ignoring."); + socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT); + } + break; + + case SOCKET_STOP_PRE_SIGKILL: + log_unit_warning(UNIT(s), "Processes still around after SIGKILL. Ignoring."); + socket_enter_stop_post(s, SOCKET_FAILURE_TIMEOUT); + break; + + case SOCKET_STOP_POST: + log_unit_warning(UNIT(s), "Stopping timed out (2). Terminating."); + socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_TIMEOUT); + break; + + case SOCKET_FINAL_SIGTERM: + if (s->kill_context.send_sigkill) { + log_unit_warning(UNIT(s), "Stopping timed out (2). Killing."); + socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_FAILURE_TIMEOUT); + } else { + log_unit_warning(UNIT(s), "Stopping timed out (2). Skipping SIGKILL. Ignoring."); + socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT); + } + break; + + case SOCKET_FINAL_SIGKILL: + log_unit_warning(UNIT(s), "Still around after SIGKILL (2). Entering failed mode."); + socket_enter_dead(s, SOCKET_FAILURE_TIMEOUT); + break; + + case SOCKET_CLEANING: + log_unit_warning(UNIT(s), "Cleaning timed out. killing."); + + if (s->clean_result == SOCKET_SUCCESS) + s->clean_result = SOCKET_FAILURE_TIMEOUT; + + socket_enter_signal(s, SOCKET_FINAL_SIGKILL, 0); + break; + + default: + assert_not_reached("Timeout at wrong time."); + } + + return 0; +} + +int socket_collect_fds(Socket *s, int **fds) { + size_t k = 0, n = 0; + SocketPort *p; + int *rfds; + + assert(s); + assert(fds); + + /* Called from the service code for requesting our fds */ + + LIST_FOREACH(port, p, s->ports) { + if (p->fd >= 0) + n++; + n += p->n_auxiliary_fds; + } + + if (n <= 0) { + *fds = NULL; + return 0; + } + + rfds = new(int, n); + if (!rfds) + return -ENOMEM; + + LIST_FOREACH(port, p, s->ports) { + size_t i; + + if (p->fd >= 0) + rfds[k++] = p->fd; + for (i = 0; i < p->n_auxiliary_fds; ++i) + rfds[k++] = p->auxiliary_fds[i]; + } + + assert(k == n); + + *fds = rfds; + return (int) n; +} + +static void socket_reset_failed(Unit *u) { + Socket *s = SOCKET(u); + + assert(s); + + if (s->state == SOCKET_FAILED) + socket_set_state(s, SOCKET_DEAD); + + s->result = SOCKET_SUCCESS; + s->clean_result = SOCKET_SUCCESS; +} + +void socket_connection_unref(Socket *s) { + assert(s); + + /* The service is dead. Yay! + * + * This is strictly for one-instance-per-connection + * services. */ + + assert(s->n_connections > 0); + s->n_connections--; + + log_unit_debug(UNIT(s), "One connection closed, %u left.", s->n_connections); +} + +static void socket_trigger_notify(Unit *u, Unit *other) { + Socket *s = SOCKET(u); + + assert(u); + assert(other); + + /* Filter out invocations with bogus state */ + if (!IN_SET(other->load_state, + UNIT_LOADED, + UNIT_NOT_FOUND, + UNIT_BAD_SETTING, + UNIT_ERROR, + UNIT_MASKED) || other->type != UNIT_SERVICE) + return; + + /* Don't propagate state changes from the service if we are already down */ + if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING)) + return; + + /* We don't care for the service state if we are in Accept=yes mode */ + if (s->accept) + return; + + /* Propagate start limit hit state */ + if (other->start_limit_hit) { + socket_enter_stop_pre(s, SOCKET_FAILURE_SERVICE_START_LIMIT_HIT); + return; + } + + /* Don't propagate anything if there's still a job queued */ + if (other->job) + return; + + if (IN_SET(SERVICE(other)->state, + SERVICE_DEAD, SERVICE_FAILED, + SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, + SERVICE_AUTO_RESTART)) + socket_enter_listening(s); + + if (SERVICE(other)->state == SERVICE_RUNNING) + socket_set_state(s, SOCKET_RUNNING); +} + +static int socket_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { + return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error); +} + +static int socket_get_timeout(Unit *u, usec_t *timeout) { + Socket *s = SOCKET(u); + usec_t t; + int r; + + if (!s->timer_event_source) + return 0; + + r = sd_event_source_get_time(s->timer_event_source, &t); + if (r < 0) + return r; + if (t == USEC_INFINITY) + return 0; + + *timeout = t; + return 1; +} + +char *socket_fdname(Socket *s) { + assert(s); + + /* Returns the name to use for $LISTEN_NAMES. If the user + * didn't specify anything specifically, use the socket unit's + * name as fallback. */ + + return s->fdname ?: UNIT(s)->id; +} + +static int socket_control_pid(Unit *u) { + Socket *s = SOCKET(u); + + assert(s); + + return s->control_pid; +} + +static int socket_clean(Unit *u, ExecCleanMask mask) { + _cleanup_strv_free_ char **l = NULL; + Socket *s = SOCKET(u); + int r; + + assert(s); + assert(mask != 0); + + if (s->state != SOCKET_DEAD) + return -EBUSY; + + r = exec_context_get_clean_directories(&s->exec_context, u->manager->prefix, mask, &l); + if (r < 0) + return r; + + if (strv_isempty(l)) + return -EUNATCH; + + socket_unwatch_control_pid(s); + s->clean_result = SOCKET_SUCCESS; + s->control_command = NULL; + s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; + + r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec)); + if (r < 0) + goto fail; + + r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid); + if (r < 0) + goto fail; + + socket_set_state(s, SOCKET_CLEANING); + + return 0; + +fail: + log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m"); + s->clean_result = SOCKET_FAILURE_RESOURCES; + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + return r; +} + +static int socket_can_clean(Unit *u, ExecCleanMask *ret) { + Socket *s = SOCKET(u); + + assert(s); + + return exec_context_get_clean_mask(&s->exec_context, ret); +} + +static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = { + [SOCKET_EXEC_START_PRE] = "ExecStartPre", + [SOCKET_EXEC_START_CHOWN] = "ExecStartChown", + [SOCKET_EXEC_START_POST] = "ExecStartPost", + [SOCKET_EXEC_STOP_PRE] = "ExecStopPre", + [SOCKET_EXEC_STOP_POST] = "ExecStopPost" +}; + +DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand); + +static const char* const socket_result_table[_SOCKET_RESULT_MAX] = { + [SOCKET_SUCCESS] = "success", + [SOCKET_FAILURE_RESOURCES] = "resources", + [SOCKET_FAILURE_TIMEOUT] = "timeout", + [SOCKET_FAILURE_EXIT_CODE] = "exit-code", + [SOCKET_FAILURE_SIGNAL] = "signal", + [SOCKET_FAILURE_CORE_DUMP] = "core-dump", + [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit", + [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit", + [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit" +}; + +DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult); + +const UnitVTable socket_vtable = { + .object_size = sizeof(Socket), + .exec_context_offset = offsetof(Socket, exec_context), + .cgroup_context_offset = offsetof(Socket, cgroup_context), + .kill_context_offset = offsetof(Socket, kill_context), + .exec_runtime_offset = offsetof(Socket, exec_runtime), + .dynamic_creds_offset = offsetof(Socket, dynamic_creds), + + .sections = + "Unit\0" + "Socket\0" + "Install\0", + .private_section = "Socket", + + .can_transient = true, + + .init = socket_init, + .done = socket_done, + .load = socket_load, + + .coldplug = socket_coldplug, + + .dump = socket_dump, + + .start = socket_start, + .stop = socket_stop, + + .kill = socket_kill, + .clean = socket_clean, + .can_clean = socket_can_clean, + + .get_timeout = socket_get_timeout, + + .serialize = socket_serialize, + .deserialize_item = socket_deserialize_item, + .distribute_fds = socket_distribute_fds, + + .active_state = socket_active_state, + .sub_state_to_string = socket_sub_state_to_string, + + .will_restart = unit_will_restart_default, + + .may_gc = socket_may_gc, + + .sigchld_event = socket_sigchld_event, + + .trigger_notify = socket_trigger_notify, + + .reset_failed = socket_reset_failed, + + .control_pid = socket_control_pid, + + .bus_vtable = bus_socket_vtable, + .bus_set_property = bus_socket_set_property, + .bus_commit_properties = bus_socket_commit_properties, + + .status_message_formats = { + /*.starting_stopping = { + [0] = "Starting socket %s...", + [1] = "Stopping socket %s...", + },*/ + .finished_start_job = { + [JOB_DONE] = "Listening on %s.", + [JOB_FAILED] = "Failed to listen on %s.", + [JOB_TIMEOUT] = "Timed out starting %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Closed %s.", + [JOB_FAILED] = "Failed stopping %s.", + [JOB_TIMEOUT] = "Timed out stopping %s.", + }, + }, +}; diff --git a/src/core/socket.h b/src/core/socket.h new file mode 100644 index 00000000..9e0be15b --- /dev/null +++ b/src/core/socket.h @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Socket Socket; +typedef struct SocketPeer SocketPeer; + +#include "mount.h" +#include "service.h" +#include "socket-util.h" +#include "unit.h" + +typedef enum SocketExecCommand { + SOCKET_EXEC_START_PRE, + SOCKET_EXEC_START_CHOWN, + SOCKET_EXEC_START_POST, + SOCKET_EXEC_STOP_PRE, + SOCKET_EXEC_STOP_POST, + _SOCKET_EXEC_COMMAND_MAX, + _SOCKET_EXEC_COMMAND_INVALID = -1 +} SocketExecCommand; + +typedef enum SocketType { + SOCKET_SOCKET, + SOCKET_FIFO, + SOCKET_SPECIAL, + SOCKET_MQUEUE, + SOCKET_USB_FUNCTION, + _SOCKET_TYPE_MAX, + _SOCKET_TYPE_INVALID = -1 +} SocketType; + +typedef enum SocketResult { + SOCKET_SUCCESS, + SOCKET_FAILURE_RESOURCES, + SOCKET_FAILURE_TIMEOUT, + SOCKET_FAILURE_EXIT_CODE, + SOCKET_FAILURE_SIGNAL, + SOCKET_FAILURE_CORE_DUMP, + SOCKET_FAILURE_START_LIMIT_HIT, + SOCKET_FAILURE_TRIGGER_LIMIT_HIT, + SOCKET_FAILURE_SERVICE_START_LIMIT_HIT, + _SOCKET_RESULT_MAX, + _SOCKET_RESULT_INVALID = -1 +} SocketResult; + +typedef struct SocketPort { + Socket *socket; + + SocketType type; + int fd; + int *auxiliary_fds; + size_t n_auxiliary_fds; + + SocketAddress address; + char *path; + sd_event_source *event_source; + + LIST_FIELDS(struct SocketPort, port); +} SocketPort; + +struct Socket { + Unit meta; + + LIST_HEAD(SocketPort, ports); + + Set *peers_by_address; + + unsigned n_accepted; + unsigned n_connections; + unsigned n_refused; + unsigned max_connections; + unsigned max_connections_per_source; + + unsigned backlog; + unsigned keep_alive_cnt; + usec_t timeout_usec; + usec_t keep_alive_time; + usec_t keep_alive_interval; + usec_t defer_accept; + + ExecCommand* exec_command[_SOCKET_EXEC_COMMAND_MAX]; + ExecContext exec_context; + KillContext kill_context; + CGroupContext cgroup_context; + + ExecRuntime *exec_runtime; + DynamicCreds dynamic_creds; + + /* For Accept=no sockets refers to the one service we'll + * activate. For Accept=yes sockets is either NULL, or filled + * to refer to the next service we spawn. */ + UnitRef service; + + SocketState state, deserialized_state; + + sd_event_source *timer_event_source; + + ExecCommand* control_command; + SocketExecCommand control_command_id; + pid_t control_pid; + + mode_t directory_mode; + mode_t socket_mode; + + SocketResult result; + SocketResult clean_result; + + char **symlinks; + + bool accept; + bool remove_on_stop; + bool writable; + + int socket_protocol; + + /* Socket options */ + bool keep_alive; + bool no_delay; + bool free_bind; + bool transparent; + bool broadcast; + bool pass_cred; + bool pass_sec; + + /* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */ + SocketAddressBindIPv6Only bind_ipv6_only; + + int priority; + int mark; + size_t receive_buffer; + size_t send_buffer; + int ip_tos; + int ip_ttl; + size_t pipe_size; + char *bind_to_device; + char *tcp_congestion; + bool reuse_port; + long mq_maxmsg; + long mq_msgsize; + + char *smack; + char *smack_ip_in; + char *smack_ip_out; + + bool selinux_context_from_net; + + char *user, *group; + + char *fdname; + + RateLimit trigger_limit; +}; + +SocketPeer *socket_peer_ref(SocketPeer *p); +SocketPeer *socket_peer_unref(SocketPeer *p); +int socket_acquire_peer(Socket *s, int fd, SocketPeer **p); + +DEFINE_TRIVIAL_CLEANUP_FUNC(SocketPeer*, socket_peer_unref); + +/* Called from the service code when collecting fds */ +int socket_collect_fds(Socket *s, int **fds); + +/* Called from the service code when a per-connection service ended */ +void socket_connection_unref(Socket *s); + +void socket_free_ports(Socket *s); + +int socket_instantiate_service(Socket *s); + +char *socket_fdname(Socket *s); + +extern const UnitVTable socket_vtable; + +const char* socket_exec_command_to_string(SocketExecCommand i) _const_; +SocketExecCommand socket_exec_command_from_string(const char *s) _pure_; + +const char* socket_result_to_string(SocketResult i) _const_; +SocketResult socket_result_from_string(const char *s) _pure_; + +const char* socket_port_type_to_string(SocketPort *p) _pure_; +SocketType socket_port_type_from_string(const char *p) _pure_; + +DEFINE_CAST(SOCKET, Socket); diff --git a/src/core/swap.c b/src/core/swap.c new file mode 100644 index 00000000..03f443da --- /dev/null +++ b/src/core/swap.c @@ -0,0 +1,1656 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-device.h" + +#include "alloc-util.h" +#include "dbus-swap.h" +#include "dbus-unit.h" +#include "device-private.h" +#include "device-util.h" +#include "device.h" +#include "escape.h" +#include "exit-status.h" +#include "fd-util.h" +#include "format-util.h" +#include "fstab-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "serialize.h" +#include "special.h" +#include "string-table.h" +#include "string-util.h" +#include "swap.h" +#include "unit-name.h" +#include "unit.h" +#include "virt.h" + +static const UnitActiveState state_translation_table[_SWAP_STATE_MAX] = { + [SWAP_DEAD] = UNIT_INACTIVE, + [SWAP_ACTIVATING] = UNIT_ACTIVATING, + [SWAP_ACTIVATING_DONE] = UNIT_ACTIVE, + [SWAP_ACTIVE] = UNIT_ACTIVE, + [SWAP_DEACTIVATING] = UNIT_DEACTIVATING, + [SWAP_DEACTIVATING_SIGTERM] = UNIT_DEACTIVATING, + [SWAP_DEACTIVATING_SIGKILL] = UNIT_DEACTIVATING, + [SWAP_FAILED] = UNIT_FAILED, + [SWAP_CLEANING] = UNIT_MAINTENANCE, +}; + +static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); +static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata); +static int swap_process_proc_swaps(Manager *m); + +static bool SWAP_STATE_WITH_PROCESS(SwapState state) { + return IN_SET(state, + SWAP_ACTIVATING, + SWAP_ACTIVATING_DONE, + SWAP_DEACTIVATING, + SWAP_DEACTIVATING_SIGTERM, + SWAP_DEACTIVATING_SIGKILL, + SWAP_CLEANING); +} + +static void swap_unset_proc_swaps(Swap *s) { + assert(s); + + if (!s->from_proc_swaps) + return; + + s->parameters_proc_swaps.what = mfree(s->parameters_proc_swaps.what); + + s->from_proc_swaps = false; +} + +static int swap_set_devnode(Swap *s, const char *devnode) { + Hashmap *swaps; + Swap *first; + int r; + + assert(s); + + r = hashmap_ensure_allocated(&UNIT(s)->manager->swaps_by_devnode, &path_hash_ops); + if (r < 0) + return r; + + swaps = UNIT(s)->manager->swaps_by_devnode; + + if (s->devnode) { + first = hashmap_get(swaps, s->devnode); + + LIST_REMOVE(same_devnode, first, s); + if (first) + hashmap_replace(swaps, first->devnode, first); + else + hashmap_remove(swaps, s->devnode); + + s->devnode = mfree(s->devnode); + } + + if (devnode) { + s->devnode = strdup(devnode); + if (!s->devnode) + return -ENOMEM; + + first = hashmap_get(swaps, s->devnode); + LIST_PREPEND(same_devnode, first, s); + + return hashmap_replace(swaps, first->devnode, first); + } + + return 0; +} + +static void swap_init(Unit *u) { + Swap *s = SWAP(u); + + assert(s); + assert(UNIT(s)->load_state == UNIT_STUB); + + s->timeout_usec = u->manager->default_timeout_start_usec; + + s->exec_context.std_output = u->manager->default_std_output; + s->exec_context.std_error = u->manager->default_std_error; + + s->parameters_proc_swaps.priority = s->parameters_fragment.priority = 0; + s->parameters_fragment.priority_set = false; + + s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; + + u->ignore_on_isolate = true; +} + +static void swap_unwatch_control_pid(Swap *s) { + assert(s); + + if (s->control_pid <= 0) + return; + + unit_unwatch_pid(UNIT(s), s->control_pid); + s->control_pid = 0; +} + +static void swap_done(Unit *u) { + Swap *s = SWAP(u); + + assert(s); + + swap_unset_proc_swaps(s); + swap_set_devnode(s, NULL); + + s->what = mfree(s->what); + s->parameters_fragment.what = mfree(s->parameters_fragment.what); + s->parameters_fragment.options = mfree(s->parameters_fragment.options); + + s->exec_runtime = exec_runtime_unref(s->exec_runtime, false); + exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX); + s->control_command = NULL; + + dynamic_creds_unref(&s->dynamic_creds); + + swap_unwatch_control_pid(s); + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); +} + +static int swap_arm_timer(Swap *s, usec_t usec) { + int r; + + assert(s); + + if (s->timer_event_source) { + r = sd_event_source_set_time(s->timer_event_source, usec); + if (r < 0) + return r; + + return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); + } + + if (usec == USEC_INFINITY) + return 0; + + r = sd_event_add_time( + UNIT(s)->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + usec, 0, + swap_dispatch_timer, s); + if (r < 0) + return r; + + (void) sd_event_source_set_description(s->timer_event_source, "swap-timer"); + + return 0; +} + +static int swap_add_device_dependencies(Swap *s) { + assert(s); + + if (!s->what) + return 0; + + if (!s->from_fragment) + return 0; + + if (is_device_path(s->what)) + return unit_add_node_dependency(UNIT(s), s->what, UNIT_BINDS_TO, UNIT_DEPENDENCY_FILE); + + /* File based swap devices need to be ordered after systemd-remount-fs.service, + * since they might need a writable file system. */ + return unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_REMOUNT_FS_SERVICE, true, UNIT_DEPENDENCY_FILE); +} + +static int swap_add_default_dependencies(Swap *s) { + int r; + + assert(s); + + if (!UNIT(s)->default_dependencies) + return 0; + + if (!MANAGER_IS_SYSTEM(UNIT(s)->manager)) + return 0; + + if (detect_container() > 0) + return 0; + + /* swap units generated for the swap dev links are missing the + * ordering dep against the swap target. */ + r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SWAP_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_DEFAULT); +} + +static int swap_verify(Swap *s) { + _cleanup_free_ char *e = NULL; + int r; + + assert(UNIT(s)->load_state == UNIT_LOADED); + + r = unit_name_from_path(s->what, ".swap", &e); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to generate unit name from path: %m"); + + if (!unit_has_name(UNIT(s), e)) { + log_unit_error(UNIT(s), "Value of What= and unit name do not match, not loading."); + return -ENOEXEC; + } + + if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) { + log_unit_error(UNIT(s), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing to load."); + return -ENOEXEC; + } + + return 0; +} + +static int swap_load_devnode(Swap *s) { + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + struct stat st; + const char *p; + int r; + + assert(s); + + if (stat(s->what, &st) < 0 || !S_ISBLK(st.st_mode)) + return 0; + + r = device_new_from_stat_rdev(&d, &st); + if (r < 0) { + log_unit_full(UNIT(s), r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, + "Failed to allocate device for swap %s: %m", s->what); + return 0; + } + + if (sd_device_get_devname(d, &p) < 0) + return 0; + + return swap_set_devnode(s, p); +} + +static int swap_add_extras(Swap *s) { + int r; + + assert(s); + + if (UNIT(s)->fragment_path) + s->from_fragment = true; + + if (!s->what) { + if (s->parameters_fragment.what) + s->what = strdup(s->parameters_fragment.what); + else if (s->parameters_proc_swaps.what) + s->what = strdup(s->parameters_proc_swaps.what); + else { + r = unit_name_to_path(UNIT(s)->id, &s->what); + if (r < 0) + return r; + } + + if (!s->what) + return -ENOMEM; + } + + path_simplify(s->what, false); + + if (!UNIT(s)->description) { + r = unit_set_description(UNIT(s), s->what); + if (r < 0) + return r; + } + + r = unit_require_mounts_for(UNIT(s), s->what, UNIT_DEPENDENCY_IMPLICIT); + if (r < 0) + return r; + + r = swap_add_device_dependencies(s); + if (r < 0) + return r; + + r = swap_load_devnode(s); + if (r < 0) + return r; + + r = unit_patch_contexts(UNIT(s)); + if (r < 0) + return r; + + r = unit_add_exec_dependencies(UNIT(s), &s->exec_context); + if (r < 0) + return r; + + r = unit_set_default_slice(UNIT(s)); + if (r < 0) + return r; + + r = swap_add_default_dependencies(s); + if (r < 0) + return r; + + return 0; +} + +static int swap_load(Unit *u) { + Swap *s = SWAP(u); + int r, q = 0; + + assert(s); + assert(u->load_state == UNIT_STUB); + + /* Load a .swap file */ + bool fragment_optional = s->from_proc_swaps; + r = unit_load_fragment_and_dropin(u, !fragment_optional); + + /* Add in some extras, and do so either when we successfully loaded something or when /proc/swaps is + * already active. */ + if (u->load_state == UNIT_LOADED || s->from_proc_swaps) + q = swap_add_extras(s); + + if (r < 0) + return r; + if (q < 0) + return q; + if (u->load_state != UNIT_LOADED) + return 0; + + return swap_verify(s); +} + +static int swap_setup_unit( + Manager *m, + const char *what, + const char *what_proc_swaps, + int priority, + bool set_flags) { + + _cleanup_free_ char *e = NULL; + bool delete = false; + Unit *u = NULL; + int r; + SwapParameters *p; + + assert(m); + assert(what); + assert(what_proc_swaps); + + r = unit_name_from_path(what, ".swap", &e); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to generate unit name from path: %m"); + + u = manager_get_unit(m, e); + if (u && + SWAP(u)->from_proc_swaps && + !path_equal(SWAP(u)->parameters_proc_swaps.what, what_proc_swaps)) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "Swap %s appeared twice with different device paths %s and %s", + e, SWAP(u)->parameters_proc_swaps.what, what_proc_swaps); + + if (!u) { + delete = true; + + r = unit_new_for_name(m, sizeof(Swap), e, &u); + if (r < 0) + goto fail; + + SWAP(u)->what = strdup(what); + if (!SWAP(u)->what) { + r = -ENOMEM; + goto fail; + } + + unit_add_to_load_queue(u); + } else + delete = false; + + p = &SWAP(u)->parameters_proc_swaps; + + if (!p->what) { + p->what = strdup(what_proc_swaps); + if (!p->what) { + r = -ENOMEM; + goto fail; + } + } + + /* The unit is definitely around now, mark it as loaded if it was previously referenced but could not be + * loaded. After all we can load it now, from the data in /proc/swaps. */ + if (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_ERROR)) { + u->load_state = UNIT_LOADED; + u->load_error = 0; + } + + if (set_flags) { + SWAP(u)->is_active = true; + SWAP(u)->just_activated = !SWAP(u)->from_proc_swaps; + } + + SWAP(u)->from_proc_swaps = true; + + p->priority = priority; + p->priority_set = true; + + unit_add_to_dbus_queue(u); + return 0; + +fail: + log_unit_warning_errno(u, r, "Failed to load swap unit: %m"); + + if (delete) + unit_free(u); + + return r; +} + +static int swap_process_new(Manager *m, const char *device, int prio, bool set_flags) { + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + const char *dn, *devlink; + struct stat st, st_link; + int r; + + assert(m); + + r = swap_setup_unit(m, device, device, prio, set_flags); + if (r < 0) + return r; + + /* If this is a block device, then let's add duplicates for + * all other names of this block device */ + if (stat(device, &st) < 0 || !S_ISBLK(st.st_mode)) + return 0; + + r = device_new_from_stat_rdev(&d, &st); + if (r < 0) { + log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, + "Failed to allocate device for swap %s: %m", device); + return 0; + } + + /* Add the main device node */ + if (sd_device_get_devname(d, &dn) >= 0 && !streq(dn, device)) + swap_setup_unit(m, dn, device, prio, set_flags); + + /* Add additional units for all symlinks */ + FOREACH_DEVICE_DEVLINK(d, devlink) { + + /* Don't bother with the /dev/block links */ + if (streq(devlink, device)) + continue; + + if (path_startswith(devlink, "/dev/block/")) + continue; + + if (stat(devlink, &st_link) >= 0 && + (!S_ISBLK(st_link.st_mode) || + st_link.st_rdev != st.st_rdev)) + continue; + + swap_setup_unit(m, devlink, device, prio, set_flags); + } + + return 0; +} + +static void swap_set_state(Swap *s, SwapState state) { + SwapState old_state; + Swap *other; + + assert(s); + + if (s->state != state) + bus_unit_send_pending_change_signal(UNIT(s), false); + + old_state = s->state; + s->state = state; + + if (!SWAP_STATE_WITH_PROCESS(state)) { + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + swap_unwatch_control_pid(s); + s->control_command = NULL; + s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; + } + + if (state != old_state) + log_unit_debug(UNIT(s), "Changed %s -> %s", swap_state_to_string(old_state), swap_state_to_string(state)); + + unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0); + + /* If there other units for the same device node have a job + queued it might be worth checking again if it is runnable + now. This is necessary, since swap_start() refuses + operation with EAGAIN if there's already another job for + the same device node queued. */ + LIST_FOREACH_OTHERS(same_devnode, other, s) + if (UNIT(other)->job) + job_add_to_run_queue(UNIT(other)->job); +} + +static int swap_coldplug(Unit *u) { + Swap *s = SWAP(u); + SwapState new_state = SWAP_DEAD; + int r; + + assert(s); + assert(s->state == SWAP_DEAD); + + if (s->deserialized_state != s->state) + new_state = s->deserialized_state; + else if (s->from_proc_swaps) + new_state = SWAP_ACTIVE; + + if (new_state == s->state) + return 0; + + if (s->control_pid > 0 && + pid_is_unwaited(s->control_pid) && + SWAP_STATE_WITH_PROCESS(new_state)) { + + r = unit_watch_pid(UNIT(s), s->control_pid, false); + if (r < 0) + return r; + + r = swap_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec)); + if (r < 0) + return r; + } + + if (!IN_SET(new_state, SWAP_DEAD, SWAP_FAILED)) { + (void) unit_setup_dynamic_creds(u); + (void) unit_setup_exec_runtime(u); + } + + swap_set_state(s, new_state); + return 0; +} + +static void swap_dump(Unit *u, FILE *f, const char *prefix) { + char buf[FORMAT_TIMESPAN_MAX]; + Swap *s = SWAP(u); + SwapParameters *p; + + assert(s); + assert(f); + + if (s->from_proc_swaps) + p = &s->parameters_proc_swaps; + else if (s->from_fragment) + p = &s->parameters_fragment; + else + p = NULL; + + fprintf(f, + "%sSwap State: %s\n" + "%sResult: %s\n" + "%sClean Result: %s\n" + "%sWhat: %s\n" + "%sFrom /proc/swaps: %s\n" + "%sFrom fragment: %s\n", + prefix, swap_state_to_string(s->state), + prefix, swap_result_to_string(s->result), + prefix, swap_result_to_string(s->clean_result), + prefix, s->what, + prefix, yes_no(s->from_proc_swaps), + prefix, yes_no(s->from_fragment)); + + if (s->devnode) + fprintf(f, "%sDevice Node: %s\n", prefix, s->devnode); + + if (p) + fprintf(f, + "%sPriority: %i\n" + "%sOptions: %s\n", + prefix, p->priority, + prefix, strempty(p->options)); + + fprintf(f, + "%sTimeoutSec: %s\n", + prefix, format_timespan(buf, sizeof(buf), s->timeout_usec, USEC_PER_SEC)); + + if (s->control_pid > 0) + fprintf(f, + "%sControl PID: "PID_FMT"\n", + prefix, s->control_pid); + + exec_context_dump(&s->exec_context, f, prefix); + kill_context_dump(&s->kill_context, f, prefix); + cgroup_context_dump(UNIT(s), f, prefix); +} + +static int swap_spawn(Swap *s, ExecCommand *c, pid_t *_pid) { + + _cleanup_(exec_params_clear) ExecParameters exec_params = { + .flags = EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN, + .stdin_fd = -1, + .stdout_fd = -1, + .stderr_fd = -1, + .exec_fd = -1, + }; + pid_t pid; + int r; + + assert(s); + assert(c); + assert(_pid); + + r = unit_prepare_exec(UNIT(s)); + if (r < 0) + return r; + + r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); + if (r < 0) + goto fail; + + r = unit_set_exec_params(UNIT(s), &exec_params); + if (r < 0) + goto fail; + + r = exec_spawn(UNIT(s), + c, + &s->exec_context, + &exec_params, + s->exec_runtime, + &s->dynamic_creds, + &pid); + if (r < 0) + goto fail; + + r = unit_watch_pid(UNIT(s), pid, true); + if (r < 0) + goto fail; + + *_pid = pid; + + return 0; + +fail: + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + + return r; +} + +static void swap_enter_dead(Swap *s, SwapResult f) { + assert(s); + + if (s->result == SWAP_SUCCESS) + s->result = f; + + unit_log_result(UNIT(s), s->result == SWAP_SUCCESS, swap_result_to_string(s->result)); + swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD); + + s->exec_runtime = exec_runtime_unref(s->exec_runtime, true); + + unit_destroy_runtime_directory(UNIT(s), &s->exec_context); + + unit_unref_uid_gid(UNIT(s), true); + + dynamic_creds_destroy(&s->dynamic_creds); +} + +static void swap_enter_active(Swap *s, SwapResult f) { + assert(s); + + if (s->result == SWAP_SUCCESS) + s->result = f; + + swap_set_state(s, SWAP_ACTIVE); +} + +static void swap_enter_dead_or_active(Swap *s, SwapResult f) { + assert(s); + + if (s->from_proc_swaps) + swap_enter_active(s, f); + else + swap_enter_dead(s, f); +} + +static int state_to_kill_operation(Swap *s, SwapState state) { + if (state == SWAP_DEACTIVATING_SIGTERM) { + if (unit_has_job_type(UNIT(s), JOB_RESTART)) + return KILL_RESTART; + else + return KILL_TERMINATE; + } + + return KILL_KILL; +} + +static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) { + int r; + + assert(s); + + if (s->result == SWAP_SUCCESS) + s->result = f; + + r = unit_kill_context(UNIT(s), + &s->kill_context, + state_to_kill_operation(s, state), + -1, + s->control_pid, + false); + if (r < 0) + goto fail; + + if (r > 0) { + r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec)); + if (r < 0) + goto fail; + + swap_set_state(s, state); + } else if (state == SWAP_DEACTIVATING_SIGTERM && s->kill_context.send_sigkill) + swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS); + else + swap_enter_dead_or_active(s, SWAP_SUCCESS); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m"); + swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES); +} + +static void swap_enter_activating(Swap *s) { + _cleanup_free_ char *opts = NULL; + int r; + + assert(s); + + unit_warn_leftover_processes(UNIT(s)); + + s->control_command_id = SWAP_EXEC_ACTIVATE; + s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE; + + if (s->from_fragment) { + int priority = 0; + + r = fstab_find_pri(s->parameters_fragment.options, &priority); + if (r < 0) + log_warning_errno(r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options); + else if (r == 1 && s->parameters_fragment.priority_set) + log_warning("Duplicate swap priority configuration by Priority and Options fields."); + + if (r <= 0 && s->parameters_fragment.priority_set) { + if (s->parameters_fragment.options) + r = asprintf(&opts, "%s,pri=%i", s->parameters_fragment.options, s->parameters_fragment.priority); + else + r = asprintf(&opts, "pri=%i", s->parameters_fragment.priority); + if (r < 0) + goto fail; + } + } + + r = exec_command_set(s->control_command, "/sbin/swapon", NULL); + if (r < 0) + goto fail; + + if (s->parameters_fragment.options || opts) { + r = exec_command_append(s->control_command, "-o", + opts ? : s->parameters_fragment.options, NULL); + if (r < 0) + goto fail; + } + + r = exec_command_append(s->control_command, s->what, NULL); + if (r < 0) + goto fail; + + swap_unwatch_control_pid(s); + + r = swap_spawn(s, s->control_command, &s->control_pid); + if (r < 0) + goto fail; + + swap_set_state(s, SWAP_ACTIVATING); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapon' task: %m"); + swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES); +} + +static void swap_enter_deactivating(Swap *s) { + int r; + + assert(s); + + s->control_command_id = SWAP_EXEC_DEACTIVATE; + s->control_command = s->exec_command + SWAP_EXEC_DEACTIVATE; + + r = exec_command_set(s->control_command, + "/sbin/swapoff", + s->what, + NULL); + if (r < 0) + goto fail; + + swap_unwatch_control_pid(s); + + r = swap_spawn(s, s->control_command, &s->control_pid); + if (r < 0) + goto fail; + + swap_set_state(s, SWAP_DEACTIVATING); + + return; + +fail: + log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapoff' task: %m"); + swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES); +} + +static void swap_cycle_clear(Swap *s) { + assert(s); + + s->result = SWAP_SUCCESS; + exec_command_reset_status_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX); + UNIT(s)->reset_accounting = true; +} + +static int swap_start(Unit *u) { + Swap *s = SWAP(u), *other; + int r; + + assert(s); + + /* We cannot fulfill this request right now, try again later please! */ + if (IN_SET(s->state, + SWAP_DEACTIVATING, + SWAP_DEACTIVATING_SIGTERM, + SWAP_DEACTIVATING_SIGKILL, + SWAP_CLEANING)) + return -EAGAIN; + + /* Already on it! */ + if (s->state == SWAP_ACTIVATING) + return 0; + + assert(IN_SET(s->state, SWAP_DEAD, SWAP_FAILED)); + + if (detect_container() > 0) + return -EPERM; + + /* If there's a job for another swap unit for the same node + * running, then let's not dispatch this one for now, and wait + * until that other job has finished. */ + LIST_FOREACH_OTHERS(same_devnode, other, s) + if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING) + return -EAGAIN; + + r = unit_test_start_limit(u); + if (r < 0) { + swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT); + return r; + } + + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + + swap_cycle_clear(s); + swap_enter_activating(s); + return 1; +} + +static int swap_stop(Unit *u) { + Swap *s = SWAP(u); + + assert(s); + + switch (s->state) { + + case SWAP_DEACTIVATING: + case SWAP_DEACTIVATING_SIGTERM: + case SWAP_DEACTIVATING_SIGKILL: + /* Already on it */ + return 0; + + case SWAP_ACTIVATING: + case SWAP_ACTIVATING_DONE: + /* There's a control process pending, directly enter kill mode */ + swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_SUCCESS); + return 0; + + case SWAP_ACTIVE: + if (detect_container() > 0) + return -EPERM; + + swap_enter_deactivating(s); + return 1; + + case SWAP_CLEANING: + /* If we are currently cleaning, then abort it, brutally. */ + swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_SUCCESS); + return 0; + + default: + assert_not_reached("Unexpected state."); + } +} + +static int swap_serialize(Unit *u, FILE *f, FDSet *fds) { + Swap *s = SWAP(u); + + assert(s); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", swap_state_to_string(s->state)); + (void) serialize_item(f, "result", swap_result_to_string(s->result)); + + if (s->control_pid > 0) + (void) serialize_item_format(f, "control-pid", PID_FMT, s->control_pid); + + if (s->control_command_id >= 0) + (void) serialize_item(f, "control-command", swap_exec_command_to_string(s->control_command_id)); + + return 0; +} + +static int swap_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Swap *s = SWAP(u); + + assert(s); + assert(fds); + + if (streq(key, "state")) { + SwapState state; + + state = swap_state_from_string(value); + if (state < 0) + log_unit_debug(u, "Failed to parse state value: %s", value); + else + s->deserialized_state = state; + } else if (streq(key, "result")) { + SwapResult f; + + f = swap_result_from_string(value); + if (f < 0) + log_unit_debug(u, "Failed to parse result value: %s", value); + else if (f != SWAP_SUCCESS) + s->result = f; + } else if (streq(key, "control-pid")) { + pid_t pid; + + if (parse_pid(value, &pid) < 0) + log_unit_debug(u, "Failed to parse control-pid value: %s", value); + else + s->control_pid = pid; + + } else if (streq(key, "control-command")) { + SwapExecCommand id; + + id = swap_exec_command_from_string(value); + if (id < 0) + log_unit_debug(u, "Failed to parse exec-command value: %s", value); + else { + s->control_command_id = id; + s->control_command = s->exec_command + id; + } + } else + log_unit_debug(u, "Unknown serialization key: %s", key); + + return 0; +} + +_pure_ static UnitActiveState swap_active_state(Unit *u) { + assert(u); + + return state_translation_table[SWAP(u)->state]; +} + +_pure_ static const char *swap_sub_state_to_string(Unit *u) { + assert(u); + + return swap_state_to_string(SWAP(u)->state); +} + +_pure_ static bool swap_may_gc(Unit *u) { + Swap *s = SWAP(u); + + assert(s); + + if (s->from_proc_swaps) + return false; + + return true; +} + +static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) { + Swap *s = SWAP(u); + SwapResult f; + + assert(s); + assert(pid >= 0); + + if (pid != s->control_pid) + return; + + /* Let's scan /proc/swaps before we process SIGCHLD. For the reasoning see the similar code in + * mount.c */ + (void) swap_process_proc_swaps(u->manager); + + s->control_pid = 0; + + if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL)) + f = SWAP_SUCCESS; + else if (code == CLD_EXITED) + f = SWAP_FAILURE_EXIT_CODE; + else if (code == CLD_KILLED) + f = SWAP_FAILURE_SIGNAL; + else if (code == CLD_DUMPED) + f = SWAP_FAILURE_CORE_DUMP; + else + assert_not_reached("Unknown code"); + + if (s->result == SWAP_SUCCESS) + s->result = f; + + if (s->control_command) { + exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status); + + s->control_command = NULL; + s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; + } + + unit_log_process_exit( + u, + "Swap process", + swap_exec_command_to_string(s->control_command_id), + f == SWAP_SUCCESS, + code, status); + + switch (s->state) { + + case SWAP_ACTIVATING: + case SWAP_ACTIVATING_DONE: + + if (f == SWAP_SUCCESS || s->from_proc_swaps) + swap_enter_active(s, f); + else + swap_enter_dead(s, f); + break; + + case SWAP_DEACTIVATING: + case SWAP_DEACTIVATING_SIGKILL: + case SWAP_DEACTIVATING_SIGTERM: + + swap_enter_dead_or_active(s, f); + break; + + case SWAP_CLEANING: + if (s->clean_result == SWAP_SUCCESS) + s->clean_result = f; + + swap_enter_dead(s, SWAP_SUCCESS); + break; + + default: + assert_not_reached("Uh, control process died at wrong time."); + } + + /* Notify clients about changed exit status */ + unit_add_to_dbus_queue(u); +} + +static int swap_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { + Swap *s = SWAP(userdata); + + assert(s); + assert(s->timer_event_source == source); + + switch (s->state) { + + case SWAP_ACTIVATING: + case SWAP_ACTIVATING_DONE: + log_unit_warning(UNIT(s), "Activation timed out. Stopping."); + swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT); + break; + + case SWAP_DEACTIVATING: + log_unit_warning(UNIT(s), "Deactivation timed out. Stopping."); + swap_enter_signal(s, SWAP_DEACTIVATING_SIGTERM, SWAP_FAILURE_TIMEOUT); + break; + + case SWAP_DEACTIVATING_SIGTERM: + if (s->kill_context.send_sigkill) { + log_unit_warning(UNIT(s), "Swap process timed out. Killing."); + swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, SWAP_FAILURE_TIMEOUT); + } else { + log_unit_warning(UNIT(s), "Swap process timed out. Skipping SIGKILL. Ignoring."); + swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT); + } + break; + + case SWAP_DEACTIVATING_SIGKILL: + log_unit_warning(UNIT(s), "Swap process still around after SIGKILL. Ignoring."); + swap_enter_dead_or_active(s, SWAP_FAILURE_TIMEOUT); + break; + + case SWAP_CLEANING: + log_unit_warning(UNIT(s), "Cleaning timed out. killing."); + + if (s->clean_result == SWAP_SUCCESS) + s->clean_result = SWAP_FAILURE_TIMEOUT; + + swap_enter_signal(s, SWAP_DEACTIVATING_SIGKILL, 0); + break; + + default: + assert_not_reached("Timeout at wrong time."); + } + + return 0; +} + +static int swap_load_proc_swaps(Manager *m, bool set_flags) { + unsigned i; + + assert(m); + + rewind(m->proc_swaps); + + (void) fscanf(m->proc_swaps, "%*s %*s %*s %*s %*s\n"); + + for (i = 1;; i++) { + _cleanup_free_ char *dev = NULL, *d = NULL; + int prio = 0, k; + + k = fscanf(m->proc_swaps, + "%ms " /* device/file */ + "%*s " /* type of swap */ + "%*s " /* swap size */ + "%*s " /* used */ + "%i\n", /* priority */ + &dev, &prio); + if (k != 2) { + if (k == EOF) + break; + + log_warning("Failed to parse /proc/swaps:%u.", i); + continue; + } + + if (cunescape(dev, UNESCAPE_RELAX, &d) < 0) + return log_oom(); + + device_found_node(m, d, DEVICE_FOUND_SWAP, DEVICE_FOUND_SWAP); + + (void) swap_process_new(m, d, prio, set_flags); + } + + return 0; +} + +static int swap_process_proc_swaps(Manager *m) { + Unit *u; + int r; + + assert(m); + + r = swap_load_proc_swaps(m, true); + if (r < 0) { + log_error_errno(r, "Failed to reread /proc/swaps: %m"); + + /* Reset flags, just in case, for late calls */ + LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) { + Swap *swap = SWAP(u); + + swap->is_active = swap->just_activated = false; + } + + return 0; + } + + manager_dispatch_load_queue(m); + + LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) { + Swap *swap = SWAP(u); + + if (!swap->is_active) { + + swap_unset_proc_swaps(swap); + + switch (swap->state) { + + case SWAP_ACTIVE: + /* This has just been deactivated */ + swap_enter_dead(swap, SWAP_SUCCESS); + break; + + default: + /* Fire again */ + swap_set_state(swap, swap->state); + break; + } + + if (swap->what) + device_found_node(m, swap->what, 0, DEVICE_FOUND_SWAP); + + } else if (swap->just_activated) { + + /* New swap entry */ + + switch (swap->state) { + + case SWAP_DEAD: + case SWAP_FAILED: + (void) unit_acquire_invocation_id(u); + swap_cycle_clear(swap); + swap_enter_active(swap, SWAP_SUCCESS); + break; + + case SWAP_ACTIVATING: + swap_set_state(swap, SWAP_ACTIVATING_DONE); + break; + + default: + /* Nothing really changed, but let's + * issue an notification call + * nonetheless, in case somebody is + * waiting for this. */ + swap_set_state(swap, swap->state); + break; + } + } + + /* Reset the flags for later calls */ + swap->is_active = swap->just_activated = false; + } + + return 1; +} + +static int swap_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + + assert(m); + assert(revents & EPOLLPRI); + + return swap_process_proc_swaps(m); +} + +static Unit *swap_following(Unit *u) { + Swap *s = SWAP(u); + Swap *other, *first = NULL; + + assert(s); + + /* If the user configured the swap through /etc/fstab or + * a device unit, follow that. */ + + if (s->from_fragment) + return NULL; + + LIST_FOREACH_OTHERS(same_devnode, other, s) + if (other->from_fragment) + return UNIT(other); + + /* Otherwise, make everybody follow the unit that's named after + * the swap device in the kernel */ + + if (streq_ptr(s->what, s->devnode)) + return NULL; + + LIST_FOREACH_AFTER(same_devnode, other, s) + if (streq_ptr(other->what, other->devnode)) + return UNIT(other); + + LIST_FOREACH_BEFORE(same_devnode, other, s) { + if (streq_ptr(other->what, other->devnode)) + return UNIT(other); + + first = other; + } + + /* Fall back to the first on the list */ + return UNIT(first); +} + +static int swap_following_set(Unit *u, Set **_set) { + Swap *s = SWAP(u), *other; + _cleanup_set_free_ Set *set = NULL; + int r; + + assert(s); + assert(_set); + + if (LIST_JUST_US(same_devnode, s)) { + *_set = NULL; + return 0; + } + + set = set_new(NULL); + if (!set) + return -ENOMEM; + + LIST_FOREACH_OTHERS(same_devnode, other, s) { + r = set_put(set, other); + if (r < 0) + return r; + } + + *_set = TAKE_PTR(set); + return 1; +} + +static void swap_shutdown(Manager *m) { + assert(m); + + m->swap_event_source = sd_event_source_unref(m->swap_event_source); + m->proc_swaps = safe_fclose(m->proc_swaps); + m->swaps_by_devnode = hashmap_free(m->swaps_by_devnode); +} + +static void swap_enumerate(Manager *m) { + int r; + + assert(m); + + if (!m->proc_swaps) { + m->proc_swaps = fopen("/proc/swaps", "re"); + if (!m->proc_swaps) { + if (errno == ENOENT) + log_debug_errno(errno, "Not swap enabled, skipping enumeration."); + else + log_warning_errno(errno, "Failed to open /proc/swaps, ignoring: %m"); + + return; + } + + r = sd_event_add_io(m->event, &m->swap_event_source, fileno(m->proc_swaps), EPOLLPRI, swap_dispatch_io, m); + if (r < 0) { + log_error_errno(r, "Failed to watch /proc/swaps: %m"); + goto fail; + } + + /* Dispatch this before we dispatch SIGCHLD, so that + * we always get the events from /proc/swaps before + * the SIGCHLD of /sbin/swapon. */ + r = sd_event_source_set_priority(m->swap_event_source, SD_EVENT_PRIORITY_NORMAL-10); + if (r < 0) { + log_error_errno(r, "Failed to change /proc/swaps priority: %m"); + goto fail; + } + + (void) sd_event_source_set_description(m->swap_event_source, "swap-proc"); + } + + r = swap_load_proc_swaps(m, false); + if (r < 0) + goto fail; + + return; + +fail: + swap_shutdown(m); +} + +int swap_process_device_new(Manager *m, sd_device *dev) { + _cleanup_free_ char *e = NULL; + const char *dn, *devlink; + Unit *u; + int r = 0; + + assert(m); + assert(dev); + + r = sd_device_get_devname(dev, &dn); + if (r < 0) + return 0; + + r = unit_name_from_path(dn, ".swap", &e); + if (r < 0) + return r; + + u = manager_get_unit(m, e); + if (u) + r = swap_set_devnode(SWAP(u), dn); + + FOREACH_DEVICE_DEVLINK(dev, devlink) { + _cleanup_free_ char *n = NULL; + int q; + + q = unit_name_from_path(devlink, ".swap", &n); + if (q < 0) + return q; + + u = manager_get_unit(m, n); + if (u) { + q = swap_set_devnode(SWAP(u), dn); + if (q < 0) + r = q; + } + } + + return r; +} + +int swap_process_device_remove(Manager *m, sd_device *dev) { + const char *dn; + int r = 0; + Swap *s; + + r = sd_device_get_devname(dev, &dn); + if (r < 0) + return 0; + + while ((s = hashmap_get(m->swaps_by_devnode, dn))) { + int q; + + q = swap_set_devnode(s, NULL); + if (q < 0) + r = q; + } + + return r; +} + +static void swap_reset_failed(Unit *u) { + Swap *s = SWAP(u); + + assert(s); + + if (s->state == SWAP_FAILED) + swap_set_state(s, SWAP_DEAD); + + s->result = SWAP_SUCCESS; + s->clean_result = SWAP_SUCCESS; +} + +static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { + return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error); +} + +static int swap_get_timeout(Unit *u, usec_t *timeout) { + Swap *s = SWAP(u); + usec_t t; + int r; + + if (!s->timer_event_source) + return 0; + + r = sd_event_source_get_time(s->timer_event_source, &t); + if (r < 0) + return r; + if (t == USEC_INFINITY) + return 0; + + *timeout = t; + return 1; +} + +static bool swap_supported(void) { + static int supported = -1; + + /* If swap support is not available in the kernel, or we are + * running in a container we don't support swap units, and any + * attempts to starting one should fail immediately. */ + + if (supported < 0) + supported = + access("/proc/swaps", F_OK) >= 0 && + detect_container() <= 0; + + return supported; +} + +static int swap_control_pid(Unit *u) { + Swap *s = SWAP(u); + + assert(s); + + return s->control_pid; +} + +static int swap_clean(Unit *u, ExecCleanMask mask) { + _cleanup_strv_free_ char **l = NULL; + Swap *s = SWAP(u); + int r; + + assert(s); + assert(mask != 0); + + if (s->state != SWAP_DEAD) + return -EBUSY; + + r = exec_context_get_clean_directories(&s->exec_context, u->manager->prefix, mask, &l); + if (r < 0) + return r; + + if (strv_isempty(l)) + return -EUNATCH; + + swap_unwatch_control_pid(s); + s->clean_result = SWAP_SUCCESS; + s->control_command = NULL; + s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; + + r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec)); + if (r < 0) + goto fail; + + r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid); + if (r < 0) + goto fail; + + swap_set_state(s, SWAP_CLEANING); + + return 0; + +fail: + log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m"); + s->clean_result = SWAP_FAILURE_RESOURCES; + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + return r; +} + +static int swap_can_clean(Unit *u, ExecCleanMask *ret) { + Swap *s = SWAP(u); + + assert(s); + + return exec_context_get_clean_mask(&s->exec_context, ret); +} + +static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = { + [SWAP_EXEC_ACTIVATE] = "ExecActivate", + [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate", +}; + +DEFINE_STRING_TABLE_LOOKUP(swap_exec_command, SwapExecCommand); + +static const char* const swap_result_table[_SWAP_RESULT_MAX] = { + [SWAP_SUCCESS] = "success", + [SWAP_FAILURE_RESOURCES] = "resources", + [SWAP_FAILURE_TIMEOUT] = "timeout", + [SWAP_FAILURE_EXIT_CODE] = "exit-code", + [SWAP_FAILURE_SIGNAL] = "signal", + [SWAP_FAILURE_CORE_DUMP] = "core-dump", + [SWAP_FAILURE_START_LIMIT_HIT] = "start-limit-hit", +}; + +DEFINE_STRING_TABLE_LOOKUP(swap_result, SwapResult); + +const UnitVTable swap_vtable = { + .object_size = sizeof(Swap), + .exec_context_offset = offsetof(Swap, exec_context), + .cgroup_context_offset = offsetof(Swap, cgroup_context), + .kill_context_offset = offsetof(Swap, kill_context), + .exec_runtime_offset = offsetof(Swap, exec_runtime), + .dynamic_creds_offset = offsetof(Swap, dynamic_creds), + + .sections = + "Unit\0" + "Swap\0" + "Install\0", + .private_section = "Swap", + + .init = swap_init, + .load = swap_load, + .done = swap_done, + + .coldplug = swap_coldplug, + + .dump = swap_dump, + + .start = swap_start, + .stop = swap_stop, + + .kill = swap_kill, + .clean = swap_clean, + .can_clean = swap_can_clean, + + .get_timeout = swap_get_timeout, + + .serialize = swap_serialize, + .deserialize_item = swap_deserialize_item, + + .active_state = swap_active_state, + .sub_state_to_string = swap_sub_state_to_string, + + .will_restart = unit_will_restart_default, + + .may_gc = swap_may_gc, + + .sigchld_event = swap_sigchld_event, + + .reset_failed = swap_reset_failed, + + .control_pid = swap_control_pid, + + .bus_vtable = bus_swap_vtable, + .bus_set_property = bus_swap_set_property, + .bus_commit_properties = bus_swap_commit_properties, + + .following = swap_following, + .following_set = swap_following_set, + + .enumerate = swap_enumerate, + .shutdown = swap_shutdown, + .supported = swap_supported, + + .status_message_formats = { + .starting_stopping = { + [0] = "Activating swap %s...", + [1] = "Deactivating swap %s...", + }, + .finished_start_job = { + [JOB_DONE] = "Activated swap %s.", + [JOB_FAILED] = "Failed to activate swap %s.", + [JOB_TIMEOUT] = "Timed out activating swap %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Deactivated swap %s.", + [JOB_FAILED] = "Failed deactivating swap %s.", + [JOB_TIMEOUT] = "Timed out deactivating swap %s.", + }, + }, +}; diff --git a/src/core/swap.h b/src/core/swap.h new file mode 100644 index 00000000..cb24cec7 --- /dev/null +++ b/src/core/swap.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2010 Maarten Lankhorst +***/ + +#include "sd-device.h" +#include "unit.h" + +typedef struct Swap Swap; + +typedef enum SwapExecCommand { + SWAP_EXEC_ACTIVATE, + SWAP_EXEC_DEACTIVATE, + _SWAP_EXEC_COMMAND_MAX, + _SWAP_EXEC_COMMAND_INVALID = -1 +} SwapExecCommand; + +typedef enum SwapResult { + SWAP_SUCCESS, + SWAP_FAILURE_RESOURCES, + SWAP_FAILURE_TIMEOUT, + SWAP_FAILURE_EXIT_CODE, + SWAP_FAILURE_SIGNAL, + SWAP_FAILURE_CORE_DUMP, + SWAP_FAILURE_START_LIMIT_HIT, + _SWAP_RESULT_MAX, + _SWAP_RESULT_INVALID = -1 +} SwapResult; + +typedef struct SwapParameters { + char *what; + char *options; + int priority; + bool priority_set; +} SwapParameters; + +struct Swap { + Unit meta; + + char *what; + + /* If the device has already shown up, this is the device + * node, which might be different from what, due to + * symlinks */ + char *devnode; + + SwapParameters parameters_proc_swaps; + SwapParameters parameters_fragment; + + bool from_proc_swaps:1; + bool from_fragment:1; + + /* Used while looking for swaps that vanished or got added + * from/to /proc/swaps */ + bool is_active:1; + bool just_activated:1; + + SwapResult result; + SwapResult clean_result; + + usec_t timeout_usec; + + ExecCommand exec_command[_SWAP_EXEC_COMMAND_MAX]; + ExecContext exec_context; + KillContext kill_context; + CGroupContext cgroup_context; + + ExecRuntime *exec_runtime; + DynamicCreds dynamic_creds; + + SwapState state, deserialized_state; + + ExecCommand* control_command; + SwapExecCommand control_command_id; + pid_t control_pid; + + sd_event_source *timer_event_source; + + /* In order to be able to distinguish dependencies on + different device nodes we might end up creating multiple + devices for the same swap. We chain them up here. */ + + LIST_FIELDS(struct Swap, same_devnode); +}; + +extern const UnitVTable swap_vtable; + +int swap_process_device_new(Manager *m, sd_device *dev); +int swap_process_device_remove(Manager *m, sd_device *dev); + +const char* swap_exec_command_to_string(SwapExecCommand i) _const_; +SwapExecCommand swap_exec_command_from_string(const char *s) _pure_; + +const char* swap_result_to_string(SwapResult i) _const_; +SwapResult swap_result_from_string(const char *s) _pure_; + +DEFINE_CAST(SWAP, Swap); diff --git a/src/core/system.conf.in b/src/core/system.conf.in new file mode 100644 index 00000000..81121254 --- /dev/null +++ b/src/core/system.conf.in @@ -0,0 +1,70 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See systemd-system.conf(5) for details. + +[Manager] +#LogLevel=info +#LogTarget=journal-or-kmsg +#LogColor=yes +#LogLocation=no +#DumpCore=yes +#ShowStatus=yes +#CrashChangeVT=no +#CrashShell=no +#CrashReboot=no +#CtrlAltDelBurstAction=reboot-force +#CPUAffinity=1 2 +#NUMAPolicy=default +#NUMAMask= +#RuntimeWatchdogSec=0 +#RebootWatchdogSec=10min +#ShutdownWatchdogSec=10min +#KExecWatchdogSec=0 +#WatchdogDevice= +#CapabilityBoundingSet= +#NoNewPrivileges=no +#SystemCallArchitectures= +#TimerSlackNSec= +#StatusUnitFormat=@STATUS_UNIT_FORMAT_DEFAULT@ +#DefaultTimerAccuracySec=1min +#DefaultStandardOutput=journal +#DefaultStandardError=inherit +#DefaultTimeoutStartSec=90s +#DefaultTimeoutStopSec=90s +#DefaultTimeoutAbortSec= +#DefaultRestartSec=100ms +#DefaultStartLimitIntervalSec=10s +#DefaultStartLimitBurst=5 +#DefaultEnvironment= +#DefaultCPUAccounting=no +#DefaultIOAccounting=no +#DefaultIPAccounting=no +#DefaultBlockIOAccounting=no +#DefaultMemoryAccounting=@MEMORY_ACCOUNTING_DEFAULT@ +#DefaultTasksAccounting=yes +#DefaultTasksMax=15% +#DefaultLimitCPU= +#DefaultLimitFSIZE= +#DefaultLimitDATA= +#DefaultLimitSTACK= +#DefaultLimitCORE= +#DefaultLimitRSS= +#DefaultLimitNOFILE=1024:@HIGH_RLIMIT_NOFILE@ +#DefaultLimitAS= +#DefaultLimitNPROC= +#DefaultLimitMEMLOCK= +#DefaultLimitLOCKS= +#DefaultLimitSIGPENDING= +#DefaultLimitMSGQUEUE= +#DefaultLimitNICE= +#DefaultLimitRTPRIO= +#DefaultLimitRTTIME= diff --git a/src/core/systemd.pc.in b/src/core/systemd.pc.in new file mode 100644 index 00000000..8331832c --- /dev/null +++ b/src/core/systemd.pc.in @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +prefix=@prefix@ +rootprefix=@rootprefix_noslash@ +sysconfdir=@sysconfdir@ +systemdutildir=${rootprefix}/lib/systemd +systemdsystemunitdir=${rootprefix}/lib/systemd/system +systemdsystempresetdir=${rootprefix}/lib/systemd/system-preset +systemduserunitdir=${prefix}/lib/systemd/user +systemduserpresetdir=${prefix}/lib/systemd/user-preset +systemdsystemconfdir=${sysconfdir}/systemd/system +systemduserconfdir=${sysconfdir}/systemd/user +systemdsystemunitpath=${systemdsystemconfdir}:/etc/systemd/system:/run/systemd/system:/usr/local/lib/systemd/system:${systemdsystemunitdir}:/usr/lib/systemd/system:/lib/systemd/system +systemduserunitpath=${systemduserconfdir}:/etc/systemd/user:/run/systemd/user:/usr/local/lib/systemd/user:/usr/local/share/systemd/user:${systemduserunitdir}:/usr/lib/systemd/user:/usr/share/systemd/user +systemdsystemgeneratordir=${rootprefix}/lib/systemd/system-generators +systemdusergeneratordir=${prefix}/lib/systemd/user-generators +systemdsystemgeneratorpath=/run/systemd/system-generators:/etc/systemd/system-generators:/usr/local/lib/systemd/system-generators:${systemdsystemgeneratordir} +systemdusergeneratorpath=/run/systemd/user-generators:/etc/systemd/user-generators:/usr/local/lib/systemd/user-generators:${systemdusergeneratordir} +systemdsleepdir=${rootprefix}/lib/systemd/system-sleep +systemdshutdowndir=${rootprefix}/lib/systemd/system-shutdown +tmpfilesdir=${prefix}/lib/tmpfiles.d +sysusersdir=${prefix}/lib/sysusers.d +sysctldir=${prefix}/lib/sysctl.d +binfmtdir=${prefix}/lib/binfmt.d +modulesloaddir=${prefix}/lib/modules-load.d +catalogdir=${prefix}/lib/systemd/catalog +systemuidmax=@systemuidmax@ +systemgidmax=@systemgidmax@ +dynamicuidmin=@dynamicuidmin@ +dynamicuidmax=@dynamicuidmax@ +containeruidbasemin=@containeruidbasemin@ +containeruidbasemax=@containeruidbasemax@ + +Name: systemd +Description: systemd System and Service Manager +URL: @PROJECT_URL@ +Version: @PROJECT_VERSION@ diff --git a/src/core/target.c b/src/core/target.c new file mode 100644 index 00000000..357ca70e --- /dev/null +++ b/src/core/target.c @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "dbus-target.h" +#include "dbus-unit.h" +#include "log.h" +#include "serialize.h" +#include "special.h" +#include "string-util.h" +#include "target.h" +#include "unit-name.h" +#include "unit.h" + +static const UnitActiveState state_translation_table[_TARGET_STATE_MAX] = { + [TARGET_DEAD] = UNIT_INACTIVE, + [TARGET_ACTIVE] = UNIT_ACTIVE +}; + +static void target_set_state(Target *t, TargetState state) { + TargetState old_state; + assert(t); + + if (t->state != state) + bus_unit_send_pending_change_signal(UNIT(t), false); + + old_state = t->state; + t->state = state; + + if (state != old_state) + log_debug("%s changed %s -> %s", + UNIT(t)->id, + target_state_to_string(old_state), + target_state_to_string(state)); + + unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0); +} + +static int target_add_default_dependencies(Target *t) { + + static const UnitDependency deps[] = { + UNIT_REQUIRES, + UNIT_REQUISITE, + UNIT_WANTS, + UNIT_BINDS_TO, + UNIT_PART_OF + }; + + int r; + unsigned k; + + assert(t); + + if (!UNIT(t)->default_dependencies) + return 0; + + /* Imply ordering for requirement dependencies on target units. Note that when the user created a contradicting + * ordering manually we won't add anything in here to make sure we don't create a loop. */ + + for (k = 0; k < ELEMENTSOF(deps); k++) { + Unit *other; + Iterator i; + void *v; + + HASHMAP_FOREACH_KEY(v, other, UNIT(t)->dependencies[deps[k]], i) { + r = unit_add_default_target_dependency(other, UNIT(t)); + if (r < 0) + return r; + } + } + + if (unit_has_name(UNIT(t), SPECIAL_SHUTDOWN_TARGET)) + return 0; + + /* Make sure targets are unloaded on shutdown */ + return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT); +} + +static int target_load(Unit *u) { + Target *t = TARGET(u); + int r; + + assert(t); + + r = unit_load_fragment_and_dropin(u, true); + if (r < 0) + return r; + + if (u->load_state != UNIT_LOADED) + return 0; + + /* This is a new unit? Then let's add in some extras */ + return target_add_default_dependencies(t); +} + +static int target_coldplug(Unit *u) { + Target *t = TARGET(u); + + assert(t); + assert(t->state == TARGET_DEAD); + + if (t->deserialized_state != t->state) + target_set_state(t, t->deserialized_state); + + return 0; +} + +static void target_dump(Unit *u, FILE *f, const char *prefix) { + Target *t = TARGET(u); + + assert(t); + assert(f); + + fprintf(f, + "%sTarget State: %s\n", + prefix, target_state_to_string(t->state)); +} + +static int target_start(Unit *u) { + Target *t = TARGET(u); + int r; + + assert(t); + assert(t->state == TARGET_DEAD); + + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + + target_set_state(t, TARGET_ACTIVE); + return 1; +} + +static int target_stop(Unit *u) { + Target *t = TARGET(u); + + assert(t); + assert(t->state == TARGET_ACTIVE); + + target_set_state(t, TARGET_DEAD); + return 1; +} + +static int target_serialize(Unit *u, FILE *f, FDSet *fds) { + Target *s = TARGET(u); + + assert(s); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", target_state_to_string(s->state)); + return 0; +} + +static int target_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Target *s = TARGET(u); + + assert(u); + assert(key); + assert(value); + assert(fds); + + if (streq(key, "state")) { + TargetState state; + + state = target_state_from_string(value); + if (state < 0) + log_debug("Failed to parse state value %s", value); + else + s->deserialized_state = state; + + } else + log_debug("Unknown serialization key '%s'", key); + + return 0; +} + +_pure_ static UnitActiveState target_active_state(Unit *u) { + assert(u); + + return state_translation_table[TARGET(u)->state]; +} + +_pure_ static const char *target_sub_state_to_string(Unit *u) { + assert(u); + + return target_state_to_string(TARGET(u)->state); +} + +const UnitVTable target_vtable = { + .object_size = sizeof(Target), + + .sections = + "Unit\0" + "Target\0" + "Install\0", + + .load = target_load, + .coldplug = target_coldplug, + + .dump = target_dump, + + .start = target_start, + .stop = target_stop, + + .serialize = target_serialize, + .deserialize_item = target_deserialize_item, + + .active_state = target_active_state, + .sub_state_to_string = target_sub_state_to_string, + + .bus_vtable = bus_target_vtable, + + .status_message_formats = { + .finished_start_job = { + [JOB_DONE] = "Reached target %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Stopped target %s.", + }, + }, +}; diff --git a/src/core/target.h b/src/core/target.h new file mode 100644 index 00000000..28f78888 --- /dev/null +++ b/src/core/target.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "unit.h" + +typedef struct Target Target; + +struct Target { + Unit meta; + + TargetState state, deserialized_state; +}; + +extern const UnitVTable target_vtable; + +DEFINE_CAST(TARGET, Target); diff --git a/src/core/timer.c b/src/core/timer.c new file mode 100644 index 00000000..051ca762 --- /dev/null +++ b/src/core/timer.c @@ -0,0 +1,928 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "dbus-timer.h" +#include "dbus-unit.h" +#include "fs-util.h" +#include "parse-util.h" +#include "random-util.h" +#include "serialize.h" +#include "special.h" +#include "string-table.h" +#include "string-util.h" +#include "timer.h" +#include "unit-name.h" +#include "unit.h" +#include "user-util.h" +#include "virt.h" + +static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = { + [TIMER_DEAD] = UNIT_INACTIVE, + [TIMER_WAITING] = UNIT_ACTIVE, + [TIMER_RUNNING] = UNIT_ACTIVE, + [TIMER_ELAPSED] = UNIT_ACTIVE, + [TIMER_FAILED] = UNIT_FAILED +}; + +static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata); + +static void timer_init(Unit *u) { + Timer *t = TIMER(u); + + assert(u); + assert(u->load_state == UNIT_STUB); + + t->next_elapse_monotonic_or_boottime = USEC_INFINITY; + t->next_elapse_realtime = USEC_INFINITY; + t->accuracy_usec = u->manager->default_timer_accuracy_usec; + t->remain_after_elapse = true; +} + +void timer_free_values(Timer *t) { + TimerValue *v; + + assert(t); + + while ((v = t->values)) { + LIST_REMOVE(value, t->values, v); + calendar_spec_free(v->calendar_spec); + free(v); + } +} + +static void timer_done(Unit *u) { + Timer *t = TIMER(u); + + assert(t); + + timer_free_values(t); + + t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source); + t->realtime_event_source = sd_event_source_unref(t->realtime_event_source); + + free(t->stamp_path); +} + +static int timer_verify(Timer *t) { + assert(t); + assert(UNIT(t)->load_state == UNIT_LOADED); + + if (!t->values && !t->on_clock_change && !t->on_timezone_change) { + log_unit_error(UNIT(t), "Timer unit lacks value setting. Refusing."); + return -ENOEXEC; + } + + return 0; +} + +static int timer_add_default_dependencies(Timer *t) { + int r; + TimerValue *v; + + assert(t); + + if (!UNIT(t)->default_dependencies) + return 0; + + r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_TIMERS_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) { + r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + + LIST_FOREACH(value, v, t->values) { + if (v->base == TIMER_CALENDAR) { + r = unit_add_dependency_by_name(UNIT(t), UNIT_AFTER, SPECIAL_TIME_SYNC_TARGET, true, UNIT_DEPENDENCY_DEFAULT); + if (r < 0) + return r; + break; + } + } + } + + return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT); +} + +static int timer_add_trigger_dependencies(Timer *t) { + Unit *x; + int r; + + assert(t); + + if (!hashmap_isempty(UNIT(t)->dependencies[UNIT_TRIGGERS])) + return 0; + + r = unit_load_related_unit(UNIT(t), ".service", &x); + if (r < 0) + return r; + + return unit_add_two_dependencies(UNIT(t), UNIT_BEFORE, UNIT_TRIGGERS, x, true, UNIT_DEPENDENCY_IMPLICIT); +} + +static int timer_setup_persistent(Timer *t) { + int r; + + assert(t); + + if (!t->persistent) + return 0; + + if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) { + + r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers", UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + + t->stamp_path = strjoin("/var/lib/systemd/timers/stamp-", UNIT(t)->id); + } else { + const char *e; + + e = getenv("XDG_DATA_HOME"); + if (e) + t->stamp_path = strjoin(e, "/systemd/timers/stamp-", UNIT(t)->id); + else { + + _cleanup_free_ char *h = NULL; + + r = get_home_dir(&h); + if (r < 0) + return log_unit_error_errno(UNIT(t), r, "Failed to determine home directory: %m"); + + t->stamp_path = strjoin(h, "/.local/share/systemd/timers/stamp-", UNIT(t)->id); + } + } + + if (!t->stamp_path) + return log_oom(); + + return 0; +} + +static int timer_load(Unit *u) { + Timer *t = TIMER(u); + int r; + + assert(u); + assert(u->load_state == UNIT_STUB); + + r = unit_load_fragment_and_dropin(u, true); + if (r < 0) + return r; + + if (u->load_state != UNIT_LOADED) + return 0; + + /* This is a new unit? Then let's add in some extras */ + r = timer_add_trigger_dependencies(t); + if (r < 0) + return r; + + r = timer_setup_persistent(t); + if (r < 0) + return r; + + r = timer_add_default_dependencies(t); + if (r < 0) + return r; + + return timer_verify(t); +} + +static void timer_dump(Unit *u, FILE *f, const char *prefix) { + char buf[FORMAT_TIMESPAN_MAX]; + Timer *t = TIMER(u); + Unit *trigger; + TimerValue *v; + + trigger = UNIT_TRIGGER(u); + + fprintf(f, + "%sTimer State: %s\n" + "%sResult: %s\n" + "%sUnit: %s\n" + "%sPersistent: %s\n" + "%sWakeSystem: %s\n" + "%sAccuracy: %s\n" + "%sRemainAfterElapse: %s\n" + "%sOnClockChange: %s\n" + "%sOnTimeZoneChange: %s\n", + prefix, timer_state_to_string(t->state), + prefix, timer_result_to_string(t->result), + prefix, trigger ? trigger->id : "n/a", + prefix, yes_no(t->persistent), + prefix, yes_no(t->wake_system), + prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1), + prefix, yes_no(t->remain_after_elapse), + prefix, yes_no(t->on_clock_change), + prefix, yes_no(t->on_timezone_change)); + + LIST_FOREACH(value, v, t->values) { + + if (v->base == TIMER_CALENDAR) { + _cleanup_free_ char *p = NULL; + + (void) calendar_spec_to_string(v->calendar_spec, &p); + + fprintf(f, + "%s%s: %s\n", + prefix, + timer_base_to_string(v->base), + strna(p)); + } else { + char timespan1[FORMAT_TIMESPAN_MAX]; + + fprintf(f, + "%s%s: %s\n", + prefix, + timer_base_to_string(v->base), + format_timespan(timespan1, sizeof(timespan1), v->value, 0)); + } + } +} + +static void timer_set_state(Timer *t, TimerState state) { + TimerState old_state; + assert(t); + + if (t->state != state) + bus_unit_send_pending_change_signal(UNIT(t), false); + + old_state = t->state; + t->state = state; + + if (state != TIMER_WAITING) { + t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source); + t->realtime_event_source = sd_event_source_unref(t->realtime_event_source); + t->next_elapse_monotonic_or_boottime = USEC_INFINITY; + t->next_elapse_realtime = USEC_INFINITY; + } + + if (state != old_state) + log_unit_debug(UNIT(t), "Changed %s -> %s", timer_state_to_string(old_state), timer_state_to_string(state)); + + unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0); +} + +static void timer_enter_waiting(Timer *t, bool time_change); + +static int timer_coldplug(Unit *u) { + Timer *t = TIMER(u); + + assert(t); + assert(t->state == TIMER_DEAD); + + if (t->deserialized_state == t->state) + return 0; + + if (t->deserialized_state == TIMER_WAITING) + timer_enter_waiting(t, false); + else + timer_set_state(t, t->deserialized_state); + + return 0; +} + +static void timer_enter_dead(Timer *t, TimerResult f) { + assert(t); + + if (t->result == TIMER_SUCCESS) + t->result = f; + + unit_log_result(UNIT(t), t->result == TIMER_SUCCESS, timer_result_to_string(t->result)); + timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD); +} + +static void timer_enter_elapsed(Timer *t, bool leave_around) { + assert(t); + + /* If a unit is marked with RemainAfterElapse=yes we leave it + * around even after it elapsed once, so that starting it + * later again does not necessarily mean immediate + * retriggering. We unconditionally leave units with + * TIMER_UNIT_ACTIVE or TIMER_UNIT_INACTIVE triggers around, + * since they might be restarted automatically at any time + * later on. */ + + if (t->remain_after_elapse || leave_around) + timer_set_state(t, TIMER_ELAPSED); + else + timer_enter_dead(t, TIMER_SUCCESS); +} + +static void add_random(Timer *t, usec_t *v) { + char s[FORMAT_TIMESPAN_MAX]; + usec_t add; + + assert(t); + assert(v); + + if (t->random_usec == 0) + return; + if (*v == USEC_INFINITY) + return; + + add = random_u64() % t->random_usec; + + if (*v + add < *v) /* overflow */ + *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */ + else + *v += add; + + log_unit_debug(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0)); +} + +static void timer_enter_waiting(Timer *t, bool time_change) { + bool found_monotonic = false, found_realtime = false; + bool leave_around = false; + triple_timestamp ts; + TimerValue *v; + Unit *trigger; + int r; + + assert(t); + + trigger = UNIT_TRIGGER(UNIT(t)); + if (!trigger) { + log_unit_error(UNIT(t), "Unit to trigger vanished."); + timer_enter_dead(t, TIMER_FAILURE_RESOURCES); + return; + } + + triple_timestamp_get(&ts); + t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0; + + LIST_FOREACH(value, v, t->values) { + if (v->disabled) + continue; + + if (v->base == TIMER_CALENDAR) { + usec_t b; + + /* If we know the last time this was + * triggered, schedule the job based relative + * to that. If we don't, just start from + * the activation time. */ + + if (t->last_trigger.realtime > 0) + b = t->last_trigger.realtime; + else { + if (state_translation_table[t->state] == UNIT_ACTIVE) + b = UNIT(t)->inactive_exit_timestamp.realtime; + else + b = ts.realtime; + } + + r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse); + if (r < 0) + continue; + + /* To make the delay due to RandomizedDelaySec= work even at boot, + * if the scheduled time has already passed, set the time when systemd + * first started as the scheduled time. + * Also, we don't have to check t->persistent since the logic implicitly express true. */ + if (v->next_elapse < UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].realtime) + v->next_elapse = UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].realtime; + + if (!found_realtime) + t->next_elapse_realtime = v->next_elapse; + else + t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse); + + found_realtime = true; + + } else { + usec_t base; + + switch (v->base) { + + case TIMER_ACTIVE: + if (state_translation_table[t->state] == UNIT_ACTIVE) + base = UNIT(t)->inactive_exit_timestamp.monotonic; + else + base = ts.monotonic; + break; + + case TIMER_BOOT: + if (detect_container() <= 0) { + /* CLOCK_MONOTONIC equals the uptime on Linux */ + base = 0; + break; + } + /* In a container we don't want to include the time the host + * was already up when the container started, so count from + * our own startup. */ + _fallthrough_; + case TIMER_STARTUP: + base = UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic; + break; + + case TIMER_UNIT_ACTIVE: + leave_around = true; + base = MAX(trigger->inactive_exit_timestamp.monotonic, t->last_trigger.monotonic); + if (base <= 0) + continue; + break; + + case TIMER_UNIT_INACTIVE: + leave_around = true; + base = MAX(trigger->inactive_enter_timestamp.monotonic, t->last_trigger.monotonic); + if (base <= 0) + continue; + break; + + default: + assert_not_reached("Unknown timer base"); + } + + v->next_elapse = usec_add(usec_shift_clock(base, CLOCK_MONOTONIC, TIMER_MONOTONIC_CLOCK(t)), v->value); + + if (dual_timestamp_is_set(&t->last_trigger) && + !time_change && + v->next_elapse < triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)) && + IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) { + /* This is a one time trigger, disable it now */ + v->disabled = true; + continue; + } + + if (!found_monotonic) + t->next_elapse_monotonic_or_boottime = v->next_elapse; + else + t->next_elapse_monotonic_or_boottime = MIN(t->next_elapse_monotonic_or_boottime, v->next_elapse); + + found_monotonic = true; + } + } + + if (!found_monotonic && !found_realtime && !t->on_timezone_change && !t->on_clock_change) { + log_unit_debug(UNIT(t), "Timer is elapsed."); + timer_enter_elapsed(t, leave_around); + return; + } + + if (found_monotonic) { + char buf[FORMAT_TIMESPAN_MAX]; + usec_t left; + + add_random(t, &t->next_elapse_monotonic_or_boottime); + + left = usec_sub_unsigned(t->next_elapse_monotonic_or_boottime, triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t))); + log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0)); + + if (t->monotonic_event_source) { + r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime); + if (r < 0) + goto fail; + + r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT); + if (r < 0) + goto fail; + } else { + + r = sd_event_add_time( + UNIT(t)->manager->event, + &t->monotonic_event_source, + t->wake_system ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC, + t->next_elapse_monotonic_or_boottime, t->accuracy_usec, + timer_dispatch, t); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(t->monotonic_event_source, "timer-monotonic"); + } + + } else if (t->monotonic_event_source) { + + r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF); + if (r < 0) + goto fail; + } + + if (found_realtime) { + char buf[FORMAT_TIMESTAMP_MAX]; + + add_random(t, &t->next_elapse_realtime); + + log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime)); + + if (t->realtime_event_source) { + r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime); + if (r < 0) + goto fail; + + r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT); + if (r < 0) + goto fail; + } else { + r = sd_event_add_time( + UNIT(t)->manager->event, + &t->realtime_event_source, + t->wake_system ? CLOCK_REALTIME_ALARM : CLOCK_REALTIME, + t->next_elapse_realtime, t->accuracy_usec, + timer_dispatch, t); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(t->realtime_event_source, "timer-realtime"); + } + + } else if (t->realtime_event_source) { + + r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF); + if (r < 0) + goto fail; + } + + timer_set_state(t, TIMER_WAITING); + return; + +fail: + log_unit_warning_errno(UNIT(t), r, "Failed to enter waiting state: %m"); + timer_enter_dead(t, TIMER_FAILURE_RESOURCES); +} + +static void timer_enter_running(Timer *t) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + Unit *trigger; + int r; + + assert(t); + + /* Don't start job if we are supposed to go down */ + if (unit_stop_pending(UNIT(t))) + return; + + trigger = UNIT_TRIGGER(UNIT(t)); + if (!trigger) { + log_unit_error(UNIT(t), "Unit to trigger vanished."); + timer_enter_dead(t, TIMER_FAILURE_RESOURCES); + return; + } + + r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL); + if (r < 0) + goto fail; + + dual_timestamp_get(&t->last_trigger); + + if (t->stamp_path) + touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, MODE_INVALID); + + timer_set_state(t, TIMER_RUNNING); + return; + +fail: + log_unit_warning(UNIT(t), "Failed to queue unit startup job: %s", bus_error_message(&error, r)); + timer_enter_dead(t, TIMER_FAILURE_RESOURCES); +} + +static int timer_start(Unit *u) { + Timer *t = TIMER(u); + TimerValue *v; + int r; + + assert(t); + assert(IN_SET(t->state, TIMER_DEAD, TIMER_FAILED)); + + r = unit_test_trigger_loaded(u); + if (r < 0) + return r; + + r = unit_test_start_limit(u); + if (r < 0) { + timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT); + return r; + } + + r = unit_acquire_invocation_id(u); + if (r < 0) + return r; + + t->last_trigger = DUAL_TIMESTAMP_NULL; + + /* Reenable all timers that depend on unit activation time */ + LIST_FOREACH(value, v, t->values) + if (v->base == TIMER_ACTIVE) + v->disabled = false; + + if (t->stamp_path) { + struct stat st; + + if (stat(t->stamp_path, &st) >= 0) { + usec_t ft; + + /* Load the file timestamp, but only if it is actually in the past. If it is in the future, + * something is wrong with the system clock. */ + + ft = timespec_load(&st.st_mtim); + if (ft < now(CLOCK_REALTIME)) + t->last_trigger.realtime = ft; + else { + char z[FORMAT_TIMESTAMP_MAX]; + + log_unit_warning(u, "Not using persistent file timestamp %s as it is in the future.", + format_timestamp(z, sizeof(z), ft)); + } + + } else if (errno == ENOENT) + /* The timer has never run before, + * make sure a stamp file exists. + */ + (void) touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID); + } + + t->result = TIMER_SUCCESS; + timer_enter_waiting(t, false); + return 1; +} + +static int timer_stop(Unit *u) { + Timer *t = TIMER(u); + + assert(t); + assert(IN_SET(t->state, TIMER_WAITING, TIMER_RUNNING, TIMER_ELAPSED)); + + timer_enter_dead(t, TIMER_SUCCESS); + return 1; +} + +static int timer_serialize(Unit *u, FILE *f, FDSet *fds) { + Timer *t = TIMER(u); + + assert(u); + assert(f); + assert(fds); + + (void) serialize_item(f, "state", timer_state_to_string(t->state)); + (void) serialize_item(f, "result", timer_result_to_string(t->result)); + + if (t->last_trigger.realtime > 0) + (void) serialize_usec(f, "last-trigger-realtime", t->last_trigger.realtime); + + if (t->last_trigger.monotonic > 0) + (void) serialize_usec(f, "last-trigger-monotonic", t->last_trigger.monotonic); + + return 0; +} + +static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { + Timer *t = TIMER(u); + + assert(u); + assert(key); + assert(value); + assert(fds); + + if (streq(key, "state")) { + TimerState state; + + state = timer_state_from_string(value); + if (state < 0) + log_unit_debug(u, "Failed to parse state value: %s", value); + else + t->deserialized_state = state; + + } else if (streq(key, "result")) { + TimerResult f; + + f = timer_result_from_string(value); + if (f < 0) + log_unit_debug(u, "Failed to parse result value: %s", value); + else if (f != TIMER_SUCCESS) + t->result = f; + + } else if (streq(key, "last-trigger-realtime")) + (void) deserialize_usec(value, &t->last_trigger.realtime); + else if (streq(key, "last-trigger-monotonic")) + (void) deserialize_usec(value, &t->last_trigger.monotonic); + else + log_unit_debug(u, "Unknown serialization key: %s", key); + + return 0; +} + +_pure_ static UnitActiveState timer_active_state(Unit *u) { + assert(u); + + return state_translation_table[TIMER(u)->state]; +} + +_pure_ static const char *timer_sub_state_to_string(Unit *u) { + assert(u); + + return timer_state_to_string(TIMER(u)->state); +} + +static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) { + Timer *t = TIMER(userdata); + + assert(t); + + if (t->state != TIMER_WAITING) + return 0; + + log_unit_debug(UNIT(t), "Timer elapsed."); + timer_enter_running(t); + return 0; +} + +static void timer_trigger_notify(Unit *u, Unit *other) { + Timer *t = TIMER(u); + TimerValue *v; + + assert(u); + assert(other); + + if (other->load_state != UNIT_LOADED) + return; + + /* Reenable all timers that depend on unit state */ + LIST_FOREACH(value, v, t->values) + if (IN_SET(v->base, TIMER_UNIT_ACTIVE, TIMER_UNIT_INACTIVE)) + v->disabled = false; + + switch (t->state) { + + case TIMER_WAITING: + case TIMER_ELAPSED: + + /* Recalculate sleep time */ + timer_enter_waiting(t, false); + break; + + case TIMER_RUNNING: + + if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) { + log_unit_debug(UNIT(t), "Got notified about unit deactivation."); + timer_enter_waiting(t, false); + } + break; + + case TIMER_DEAD: + case TIMER_FAILED: + break; + + default: + assert_not_reached("Unknown timer state"); + } +} + +static void timer_reset_failed(Unit *u) { + Timer *t = TIMER(u); + + assert(t); + + if (t->state == TIMER_FAILED) + timer_set_state(t, TIMER_DEAD); + + t->result = TIMER_SUCCESS; +} + +static void timer_time_change(Unit *u) { + Timer *t = TIMER(u); + usec_t ts; + + assert(u); + + if (t->state != TIMER_WAITING) + return; + + /* If we appear to have triggered in the future, the system clock must + * have been set backwards. So let's rewind our own clock and allow + * the future trigger(s) to happen again :). Exactly the same as when + * you start a timer unit with Persistent=yes. */ + ts = now(CLOCK_REALTIME); + if (t->last_trigger.realtime > ts) + t->last_trigger.realtime = ts; + + if (t->on_clock_change) { + log_unit_debug(u, "Time change, triggering activation."); + timer_enter_running(t); + } else { + log_unit_debug(u, "Time change, recalculating next elapse."); + timer_enter_waiting(t, true); + } +} + +static void timer_timezone_change(Unit *u) { + Timer *t = TIMER(u); + + assert(u); + + if (t->state != TIMER_WAITING) + return; + + if (t->on_timezone_change) { + log_unit_debug(u, "Timezone change, triggering activation."); + timer_enter_running(t); + } else { + log_unit_debug(u, "Timezone change, recalculating next elapse."); + timer_enter_waiting(t, false); + } +} + +static int timer_clean(Unit *u, ExecCleanMask mask) { + Timer *t = TIMER(u); + int r; + + assert(t); + assert(mask != 0); + + if (t->state != TIMER_DEAD) + return -EBUSY; + + if (!IN_SET(mask, EXEC_CLEAN_STATE)) + return -EUNATCH; + + r = timer_setup_persistent(t); + if (r < 0) + return r; + + if (!t->stamp_path) + return -EUNATCH; + + if (unlink(t->stamp_path) && errno != ENOENT) + return log_unit_error_errno(u, errno, "Failed to clean stamp file of timer: %m"); + + return 0; +} + +static int timer_can_clean(Unit *u, ExecCleanMask *ret) { + Timer *t = TIMER(u); + + assert(t); + + *ret = t->persistent ? EXEC_CLEAN_STATE : 0; + return 0; +} + +static const char* const timer_base_table[_TIMER_BASE_MAX] = { + [TIMER_ACTIVE] = "OnActiveSec", + [TIMER_BOOT] = "OnBootSec", + [TIMER_STARTUP] = "OnStartupSec", + [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec", + [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec", + [TIMER_CALENDAR] = "OnCalendar" +}; + +DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase); + +static const char* const timer_result_table[_TIMER_RESULT_MAX] = { + [TIMER_SUCCESS] = "success", + [TIMER_FAILURE_RESOURCES] = "resources", + [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit", +}; + +DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult); + +const UnitVTable timer_vtable = { + .object_size = sizeof(Timer), + + .sections = + "Unit\0" + "Timer\0" + "Install\0", + .private_section = "Timer", + + .init = timer_init, + .done = timer_done, + .load = timer_load, + + .coldplug = timer_coldplug, + + .dump = timer_dump, + + .start = timer_start, + .stop = timer_stop, + + .clean = timer_clean, + .can_clean = timer_can_clean, + + .serialize = timer_serialize, + .deserialize_item = timer_deserialize_item, + + .active_state = timer_active_state, + .sub_state_to_string = timer_sub_state_to_string, + + .trigger_notify = timer_trigger_notify, + + .reset_failed = timer_reset_failed, + .time_change = timer_time_change, + .timezone_change = timer_timezone_change, + + .bus_vtable = bus_timer_vtable, + .bus_set_property = bus_timer_set_property, + + .can_transient = true, +}; diff --git a/src/core/timer.h b/src/core/timer.h new file mode 100644 index 00000000..ab66a201 --- /dev/null +++ b/src/core/timer.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Timer Timer; + +#include "calendarspec.h" +#include "unit.h" + +typedef enum TimerBase { + TIMER_ACTIVE, + TIMER_BOOT, + TIMER_STARTUP, + TIMER_UNIT_ACTIVE, + TIMER_UNIT_INACTIVE, + TIMER_CALENDAR, + _TIMER_BASE_MAX, + _TIMER_BASE_INVALID = -1 +} TimerBase; + +typedef struct TimerValue { + TimerBase base; + bool disabled; + + usec_t value; /* only for monotonic events */ + CalendarSpec *calendar_spec; /* only for calendar events */ + usec_t next_elapse; + + LIST_FIELDS(struct TimerValue, value); +} TimerValue; + +typedef enum TimerResult { + TIMER_SUCCESS, + TIMER_FAILURE_RESOURCES, + TIMER_FAILURE_START_LIMIT_HIT, + _TIMER_RESULT_MAX, + _TIMER_RESULT_INVALID = -1 +} TimerResult; + +struct Timer { + Unit meta; + + usec_t accuracy_usec; + usec_t random_usec; + + LIST_HEAD(TimerValue, values); + usec_t next_elapse_realtime; + usec_t next_elapse_monotonic_or_boottime; + dual_timestamp last_trigger; + + TimerState state, deserialized_state; + + sd_event_source *monotonic_event_source; + sd_event_source *realtime_event_source; + + TimerResult result; + + bool persistent; + bool wake_system; + bool remain_after_elapse; + bool on_clock_change; + bool on_timezone_change; + + char *stamp_path; +}; + +#define TIMER_MONOTONIC_CLOCK(t) ((t)->wake_system && clock_boottime_supported() ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC) + +void timer_free_values(Timer *t); + +extern const UnitVTable timer_vtable; + +const char *timer_base_to_string(TimerBase i) _const_; +TimerBase timer_base_from_string(const char *s) _pure_; + +const char* timer_result_to_string(TimerResult i) _const_; +TimerResult timer_result_from_string(const char *s) _pure_; + +DEFINE_CAST(TIMER, Timer); diff --git a/src/core/transaction.c b/src/core/transaction.c new file mode 100644 index 00000000..a0ea0f04 --- /dev/null +++ b/src/core/transaction.c @@ -0,0 +1,1190 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "dbus-unit.h" +#include "strv.h" +#include "terminal-util.h" +#include "transaction.h" + +static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies); + +static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependencies) { + assert(tr); + assert(j); + + /* Deletes one job from the transaction */ + + transaction_unlink_job(tr, j, delete_dependencies); + + job_free(j); +} + +static void transaction_delete_unit(Transaction *tr, Unit *u) { + Job *j; + + /* Deletes all jobs associated with a certain unit from the + * transaction */ + + while ((j = hashmap_get(tr->jobs, u))) + transaction_delete_job(tr, j, true); +} + +void transaction_abort(Transaction *tr) { + Job *j; + + assert(tr); + + while ((j = hashmap_first(tr->jobs))) + transaction_delete_job(tr, j, false); + + assert(hashmap_isempty(tr->jobs)); +} + +static void transaction_find_jobs_that_matter_to_anchor(Job *j, unsigned generation) { + JobDependency *l; + + /* A recursive sweep through the graph that marks all units + * that matter to the anchor job, i.e. are directly or + * indirectly a dependency of the anchor job via paths that + * are fully marked as mattering. */ + + j->matters_to_anchor = true; + j->generation = generation; + + LIST_FOREACH(subject, l, j->subject_list) { + + /* This link does not matter */ + if (!l->matters) + continue; + + /* This unit has already been marked */ + if (l->object->generation == generation) + continue; + + transaction_find_jobs_that_matter_to_anchor(l->object, generation); + } +} + +static void transaction_merge_and_delete_job(Transaction *tr, Job *j, Job *other, JobType t) { + JobDependency *l, *last; + + assert(j); + assert(other); + assert(j->unit == other->unit); + assert(!j->installed); + + /* Merges 'other' into 'j' and then deletes 'other'. */ + + j->type = t; + j->state = JOB_WAITING; + j->irreversible = j->irreversible || other->irreversible; + j->matters_to_anchor = j->matters_to_anchor || other->matters_to_anchor; + + /* Patch us in as new owner of the JobDependency objects */ + last = NULL; + LIST_FOREACH(subject, l, other->subject_list) { + assert(l->subject == other); + l->subject = j; + last = l; + } + + /* Merge both lists */ + if (last) { + last->subject_next = j->subject_list; + if (j->subject_list) + j->subject_list->subject_prev = last; + j->subject_list = other->subject_list; + } + + /* Patch us in as new owner of the JobDependency objects */ + last = NULL; + LIST_FOREACH(object, l, other->object_list) { + assert(l->object == other); + l->object = j; + last = l; + } + + /* Merge both lists */ + if (last) { + last->object_next = j->object_list; + if (j->object_list) + j->object_list->object_prev = last; + j->object_list = other->object_list; + } + + /* Kill the other job */ + other->subject_list = NULL; + other->object_list = NULL; + transaction_delete_job(tr, other, true); +} + +_pure_ static bool job_is_conflicted_by(Job *j) { + JobDependency *l; + + assert(j); + + /* Returns true if this job is pulled in by a least one + * ConflictedBy dependency. */ + + LIST_FOREACH(object, l, j->object_list) + if (l->conflicts) + return true; + + return false; +} + +static int delete_one_unmergeable_job(Transaction *tr, Job *j) { + Job *k; + + assert(j); + + /* Tries to delete one item in the linked list + * j->transaction_next->transaction_next->... that conflicts + * with another one, in an attempt to make an inconsistent + * transaction work. */ + + /* We rely here on the fact that if a merged with b does not + * merge with c, either a or b merge with c neither */ + LIST_FOREACH(transaction, j, j) + LIST_FOREACH(transaction, k, j->transaction_next) { + Job *d; + + /* Is this one mergeable? Then skip it */ + if (job_type_is_mergeable(j->type, k->type)) + continue; + + /* Ok, we found two that conflict, let's see if we can + * drop one of them */ + if (!j->matters_to_anchor && !k->matters_to_anchor) { + + /* Both jobs don't matter, so let's + * find the one that is smarter to + * remove. Let's think positive and + * rather remove stops then starts -- + * except if something is being + * stopped because it is conflicted by + * another unit in which case we + * rather remove the start. */ + + log_unit_debug(j->unit, + "Looking at job %s/%s conflicted_by=%s", + j->unit->id, job_type_to_string(j->type), + yes_no(j->type == JOB_STOP && job_is_conflicted_by(j))); + log_unit_debug(k->unit, + "Looking at job %s/%s conflicted_by=%s", + k->unit->id, job_type_to_string(k->type), + yes_no(k->type == JOB_STOP && job_is_conflicted_by(k))); + + if (j->type == JOB_STOP) { + + if (job_is_conflicted_by(j)) + d = k; + else + d = j; + + } else if (k->type == JOB_STOP) { + + if (job_is_conflicted_by(k)) + d = j; + else + d = k; + } else + d = j; + + } else if (!j->matters_to_anchor) + d = j; + else if (!k->matters_to_anchor) + d = k; + else + return -ENOEXEC; + + /* Ok, we can drop one, so let's do so. */ + log_unit_debug(d->unit, + "Fixing conflicting jobs %s/%s,%s/%s by deleting job %s/%s", + j->unit->id, job_type_to_string(j->type), + k->unit->id, job_type_to_string(k->type), + d->unit->id, job_type_to_string(d->type)); + transaction_delete_job(tr, d, true); + return 0; + } + + return -EINVAL; +} + +static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) { + Job *j; + Iterator i; + int r; + + assert(tr); + + /* First step, check whether any of the jobs for one specific + * task conflict. If so, try to drop one of them. */ + HASHMAP_FOREACH(j, tr->jobs, i) { + JobType t; + Job *k; + + t = j->type; + LIST_FOREACH(transaction, k, j->transaction_next) { + if (job_type_merge_and_collapse(&t, k->type, j->unit) >= 0) + continue; + + /* OK, we could not merge all jobs for this + * action. Let's see if we can get rid of one + * of them */ + + r = delete_one_unmergeable_job(tr, j); + if (r >= 0) + /* Ok, we managed to drop one, now + * let's ask our callers to call us + * again after garbage collecting */ + return -EAGAIN; + + /* We couldn't merge anything. Failure */ + return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, + "Transaction contains conflicting jobs '%s' and '%s' for %s. " + "Probably contradicting requirement dependencies configured.", + job_type_to_string(t), + job_type_to_string(k->type), + k->unit->id); + } + } + + /* Second step, merge the jobs. */ + HASHMAP_FOREACH(j, tr->jobs, i) { + JobType t = j->type; + Job *k; + + /* Merge all transaction jobs for j->unit */ + LIST_FOREACH(transaction, k, j->transaction_next) + assert_se(job_type_merge_and_collapse(&t, k->type, j->unit) == 0); + + while ((k = j->transaction_next)) { + if (tr->anchor_job == k) { + transaction_merge_and_delete_job(tr, k, j, t); + j = k; + } else + transaction_merge_and_delete_job(tr, j, k, t); + } + + assert(!j->transaction_next); + assert(!j->transaction_prev); + } + + return 0; +} + +static void transaction_drop_redundant(Transaction *tr) { + bool again; + + /* Goes through the transaction and removes all jobs of the units whose jobs are all noops. If not + * all of a unit's jobs are redundant, they are kept. */ + + assert(tr); + + do { + Iterator i; + Job *j; + + again = false; + + HASHMAP_FOREACH(j, tr->jobs, i) { + bool keep = false; + Job *k; + + LIST_FOREACH(transaction, k, j) + if (tr->anchor_job == k || + !job_type_is_redundant(k->type, unit_active_state(k->unit)) || + (k->unit->job && job_type_is_conflicting(k->type, k->unit->job->type))) { + keep = true; + break; + } + + if (!keep) { + log_trace("Found redundant job %s/%s, dropping from transaction.", + j->unit->id, job_type_to_string(j->type)); + transaction_delete_job(tr, j, false); + again = true; + break; + } + } + } while (again); +} + +_pure_ static bool unit_matters_to_anchor(Unit *u, Job *j) { + assert(u); + assert(!j->transaction_prev); + + /* Checks whether at least one of the jobs for this unit + * matters to the anchor. */ + + LIST_FOREACH(transaction, j, j) + if (j->matters_to_anchor) + return true; + + return false; +} + +static char* merge_unit_ids(const char* unit_log_field, char **pairs) { + char **unit_id, **job_type, *ans = NULL; + size_t alloc = 0, size = 0, next; + + STRV_FOREACH_PAIR(unit_id, job_type, pairs) { + next = strlen(unit_log_field) + strlen(*unit_id); + if (!GREEDY_REALLOC(ans, alloc, size + next + 1)) { + return mfree(ans); + } + + sprintf(ans + size, "%s%s", unit_log_field, *unit_id); + if (*(unit_id+1)) + ans[size + next] = '\n'; + size += next + 1; + } + + return ans; +} + +static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsigned generation, sd_bus_error *e) { + Iterator i; + Unit *u; + void *v; + int r; + static const UnitDependency directions[] = { + UNIT_BEFORE, + UNIT_AFTER, + }; + size_t d; + + assert(tr); + assert(j); + assert(!j->transaction_prev); + + /* Does a recursive sweep through the ordering graph, looking + * for a cycle. If we find a cycle we try to break it. */ + + /* Have we seen this before? */ + if (j->generation == generation) { + Job *k, *delete = NULL; + _cleanup_free_ char **array = NULL, *unit_ids = NULL; + char **unit_id, **job_type; + + /* If the marker is NULL we have been here already and + * decided the job was loop-free from here. Hence + * shortcut things and return right-away. */ + if (!j->marker) + return 0; + + /* So, the marker is not NULL and we already have been here. We have + * a cycle. Let's try to break it. We go backwards in our path and + * try to find a suitable job to remove. We use the marker to find + * our way back, since smart how we are we stored our way back in + * there. */ + + for (k = from; k; k = ((k->generation == generation && k->marker != k) ? k->marker : NULL)) { + + /* For logging below */ + if (strv_push_pair(&array, k->unit->id, (char*) job_type_to_string(k->type)) < 0) + log_oom(); + + if (!delete && hashmap_get(tr->jobs, k->unit) && !unit_matters_to_anchor(k->unit, k)) + /* Ok, we can drop this one, so let's do so. */ + delete = k; + + /* Check if this in fact was the beginning of the cycle */ + if (k == j) + break; + } + + unit_ids = merge_unit_ids(j->manager->unit_log_field, array); /* ignore error */ + + STRV_FOREACH_PAIR(unit_id, job_type, array) + /* logging for j not k here to provide a consistent narrative */ + log_struct(LOG_WARNING, + "MESSAGE=%s: Found %s on %s/%s", + j->unit->id, + unit_id == array ? "ordering cycle" : "dependency", + *unit_id, *job_type, + unit_ids); + + if (delete) { + const char *status; + /* logging for j not k here to provide a consistent narrative */ + log_struct(LOG_ERR, + "MESSAGE=%s: Job %s/%s deleted to break ordering cycle starting with %s/%s", + j->unit->id, delete->unit->id, job_type_to_string(delete->type), + j->unit->id, job_type_to_string(j->type), + unit_ids); + + if (log_get_show_color()) + status = ANSI_HIGHLIGHT_RED " SKIP " ANSI_NORMAL; + else + status = " SKIP "; + + unit_status_printf(delete->unit, status, + "Ordering cycle found, skipping %s"); + transaction_delete_unit(tr, delete->unit); + return -EAGAIN; + } + + log_struct(LOG_ERR, + "MESSAGE=%s: Unable to break cycle starting with %s/%s", + j->unit->id, j->unit->id, job_type_to_string(j->type), + unit_ids); + + return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, + "Transaction order is cyclic. See system logs for details."); + } + + /* Make the marker point to where we come from, so that we can + * find our way backwards if we want to break a cycle. We use + * a special marker for the beginning: we point to + * ourselves. */ + j->marker = from ? from : j; + j->generation = generation; + + /* Actual ordering of jobs depends on the unit ordering dependency and job types. We need to traverse + * the graph over 'before' edges in the actual job execution order. We traverse over both unit + * ordering dependencies and we test with job_compare() whether it is the 'before' edge in the job + * execution ordering. */ + for (d = 0; d < ELEMENTSOF(directions); d++) { + HASHMAP_FOREACH_KEY(v, u, j->unit->dependencies[directions[d]], i) { + Job *o; + + /* Is there a job for this unit? */ + o = hashmap_get(tr->jobs, u); + if (!o) { + /* Ok, there is no job for this in the + * transaction, but maybe there is already one + * running? */ + o = u->job; + if (!o) + continue; + } + + /* Cut traversing if the job j is not really *before* o. */ + if (job_compare(j, o, directions[d]) >= 0) + continue; + + r = transaction_verify_order_one(tr, o, j, generation, e); + if (r < 0) + return r; + } + } + + /* Ok, let's backtrack, and remember that this entry is not on + * our path anymore. */ + j->marker = NULL; + + return 0; +} + +static int transaction_verify_order(Transaction *tr, unsigned *generation, sd_bus_error *e) { + Job *j; + int r; + Iterator i; + unsigned g; + + assert(tr); + assert(generation); + + /* Check if the ordering graph is cyclic. If it is, try to fix + * that up by dropping one of the jobs. */ + + g = (*generation)++; + + HASHMAP_FOREACH(j, tr->jobs, i) { + r = transaction_verify_order_one(tr, j, NULL, g, e); + if (r < 0) + return r; + } + + return 0; +} + +static void transaction_collect_garbage(Transaction *tr) { + bool again; + + assert(tr); + + /* Drop jobs that are not required by any other job */ + + do { + Iterator i; + Job *j; + + again = false; + + HASHMAP_FOREACH(j, tr->jobs, i) { + if (tr->anchor_job == j) + continue; + + if (!j->object_list) { + log_trace("Garbage collecting job %s/%s", j->unit->id, job_type_to_string(j->type)); + transaction_delete_job(tr, j, true); + again = true; + break; + } + + log_trace("Keeping job %s/%s because of %s/%s", + j->unit->id, job_type_to_string(j->type), + j->object_list->subject ? j->object_list->subject->unit->id : "root", + j->object_list->subject ? job_type_to_string(j->object_list->subject->type) : "root"); + } + + } while (again); +} + +static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_error *e) { + Iterator i; + Job *j; + + assert(tr); + + /* Checks whether applying this transaction means that + * existing jobs would be replaced */ + + HASHMAP_FOREACH(j, tr->jobs, i) { + + /* Assume merged */ + assert(!j->transaction_prev); + assert(!j->transaction_next); + + if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) && + job_type_is_conflicting(j->unit->job->type, j->type)) + return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, + "Transaction for %s/%s is destructive (%s has '%s' job queued, but '%s' is included in transaction).", + tr->anchor_job->unit->id, job_type_to_string(tr->anchor_job->type), + j->unit->id, job_type_to_string(j->unit->job->type), job_type_to_string(j->type)); + } + + return 0; +} + +static void transaction_minimize_impact(Transaction *tr) { + Job *j; + Iterator i; + + assert(tr); + + /* Drops all unnecessary jobs that reverse already active jobs + * or that stop a running service. */ + +rescan: + HASHMAP_FOREACH(j, tr->jobs, i) { + LIST_FOREACH(transaction, j, j) { + bool stops_running_service, changes_existing_job; + + /* If it matters, we shouldn't drop it */ + if (j->matters_to_anchor) + continue; + + /* Would this stop a running service? + * Would this change an existing job? + * If so, let's drop this entry */ + + stops_running_service = + j->type == JOB_STOP && UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(j->unit)); + + changes_existing_job = + j->unit->job && + job_type_is_conflicting(j->type, j->unit->job->type); + + if (!stops_running_service && !changes_existing_job) + continue; + + if (stops_running_service) + log_unit_debug(j->unit, + "%s/%s would stop a running service.", + j->unit->id, job_type_to_string(j->type)); + + if (changes_existing_job) + log_unit_debug(j->unit, + "%s/%s would change existing job.", + j->unit->id, job_type_to_string(j->type)); + + /* Ok, let's get rid of this */ + log_unit_debug(j->unit, + "Deleting %s/%s to minimize impact.", + j->unit->id, job_type_to_string(j->type)); + + transaction_delete_job(tr, j, true); + goto rescan; + } + } +} + +static int transaction_apply( + Transaction *tr, + Manager *m, + JobMode mode, + Set *affected_jobs) { + + Iterator i; + Job *j; + int r; + + /* Moves the transaction jobs to the set of active jobs */ + + if (IN_SET(mode, JOB_ISOLATE, JOB_FLUSH)) { + + /* When isolating first kill all installed jobs which + * aren't part of the new transaction */ + HASHMAP_FOREACH(j, m->jobs, i) { + assert(j->installed); + + if (j->unit->ignore_on_isolate) + continue; + + if (hashmap_get(tr->jobs, j->unit)) + continue; + + /* Not invalidating recursively. Avoids triggering + * OnFailure= actions of dependent jobs. Also avoids + * invalidating our iterator. */ + job_finish_and_invalidate(j, JOB_CANCELED, false, false); + } + } + + HASHMAP_FOREACH(j, tr->jobs, i) { + /* Assume merged */ + assert(!j->transaction_prev); + assert(!j->transaction_next); + + r = hashmap_put(m->jobs, UINT32_TO_PTR(j->id), j); + if (r < 0) + goto rollback; + } + + while ((j = hashmap_steal_first(tr->jobs))) { + Job *installed_job; + + /* Clean the job dependencies */ + transaction_unlink_job(tr, j, false); + + installed_job = job_install(j); + if (installed_job != j) { + /* j has been merged into a previously installed job */ + if (tr->anchor_job == j) + tr->anchor_job = installed_job; + hashmap_remove(m->jobs, UINT32_TO_PTR(j->id)); + job_free(j); + j = installed_job; + } + + job_add_to_run_queue(j); + job_add_to_dbus_queue(j); + job_start_timer(j, false); + job_shutdown_magic(j); + + /* When 'affected' is specified, let's track all in it all jobs that were touched because of + * this transaction. */ + if (affected_jobs) + (void) set_put(affected_jobs, j); + } + + return 0; + +rollback: + + HASHMAP_FOREACH(j, tr->jobs, i) + hashmap_remove(m->jobs, UINT32_TO_PTR(j->id)); + + return r; +} + +int transaction_activate( + Transaction *tr, + Manager *m, + JobMode mode, + Set *affected_jobs, + sd_bus_error *e) { + + Iterator i; + Job *j; + int r; + unsigned generation = 1; + + assert(tr); + + /* This applies the changes recorded in tr->jobs to + * the actual list of jobs, if possible. */ + + /* Reset the generation counter of all installed jobs. The detection of cycles + * looks at installed jobs. If they had a non-zero generation from some previous + * walk of the graph, the algorithm would break. */ + HASHMAP_FOREACH(j, m->jobs, i) + j->generation = 0; + + /* First step: figure out which jobs matter */ + transaction_find_jobs_that_matter_to_anchor(tr->anchor_job, generation++); + + /* Second step: Try not to stop any running services if + * we don't have to. Don't try to reverse running + * jobs if we don't have to. */ + if (mode == JOB_FAIL) + transaction_minimize_impact(tr); + + /* Third step: Drop redundant jobs */ + transaction_drop_redundant(tr); + + for (;;) { + /* Fourth step: Let's remove unneeded jobs that might + * be lurking. */ + if (mode != JOB_ISOLATE) + transaction_collect_garbage(tr); + + /* Fifth step: verify order makes sense and correct + * cycles if necessary and possible */ + r = transaction_verify_order(tr, &generation, e); + if (r >= 0) + break; + + if (r != -EAGAIN) + return log_warning_errno(r, "Requested transaction contains an unfixable cyclic ordering dependency: %s", bus_error_message(e, r)); + + /* Let's see if the resulting transaction ordering + * graph is still cyclic... */ + } + + for (;;) { + /* Sixth step: let's drop unmergeable entries if + * necessary and possible, merge entries we can + * merge */ + r = transaction_merge_jobs(tr, e); + if (r >= 0) + break; + + if (r != -EAGAIN) + return log_warning_errno(r, "Requested transaction contains unmergeable jobs: %s", bus_error_message(e, r)); + + /* Seventh step: an entry got dropped, let's garbage + * collect its dependencies. */ + if (mode != JOB_ISOLATE) + transaction_collect_garbage(tr); + + /* Let's see if the resulting transaction still has + * unmergeable entries ... */ + } + + /* Eights step: Drop redundant jobs again, if the merging now allows us to drop more. */ + transaction_drop_redundant(tr); + + /* Ninth step: check whether we can actually apply this */ + r = transaction_is_destructive(tr, mode, e); + if (r < 0) + return log_notice_errno(r, "Requested transaction contradicts existing jobs: %s", bus_error_message(e, r)); + + /* Tenth step: apply changes */ + r = transaction_apply(tr, m, mode, affected_jobs); + if (r < 0) + return log_warning_errno(r, "Failed to apply transaction: %m"); + + assert(hashmap_isempty(tr->jobs)); + + if (!hashmap_isempty(m->jobs)) { + /* Are there any jobs now? Then make sure we have the + * idle pipe around. We don't really care too much + * whether this works or not, as the idle pipe is a + * feature for cosmetics, not actually useful for + * anything beyond that. */ + + if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0 && + m->idle_pipe[2] < 0 && m->idle_pipe[3] < 0) { + (void) pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC); + (void) pipe2(m->idle_pipe + 2, O_NONBLOCK|O_CLOEXEC); + } + } + + return 0; +} + +static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, bool *is_new) { + Job *j, *f; + + assert(tr); + assert(unit); + + /* Looks for an existing prospective job and returns that. If + * it doesn't exist it is created and added to the prospective + * jobs list. */ + + f = hashmap_get(tr->jobs, unit); + + LIST_FOREACH(transaction, j, f) { + assert(j->unit == unit); + + if (j->type == type) { + if (is_new) + *is_new = false; + return j; + } + } + + j = job_new(unit, type); + if (!j) + return NULL; + + j->generation = 0; + j->marker = NULL; + j->matters_to_anchor = false; + j->irreversible = tr->irreversible; + + LIST_PREPEND(transaction, f, j); + + if (hashmap_replace(tr->jobs, unit, f) < 0) { + LIST_REMOVE(transaction, f, j); + job_free(j); + return NULL; + } + + if (is_new) + *is_new = true; + + log_trace("Added job %s/%s to transaction.", unit->id, job_type_to_string(type)); + + return j; +} + +static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies) { + assert(tr); + assert(j); + + if (j->transaction_prev) + j->transaction_prev->transaction_next = j->transaction_next; + else if (j->transaction_next) + hashmap_replace(tr->jobs, j->unit, j->transaction_next); + else + hashmap_remove_value(tr->jobs, j->unit, j); + + if (j->transaction_next) + j->transaction_next->transaction_prev = j->transaction_prev; + + j->transaction_prev = j->transaction_next = NULL; + + while (j->subject_list) + job_dependency_free(j->subject_list); + + while (j->object_list) { + Job *other = j->object_list->matters ? j->object_list->subject : NULL; + + job_dependency_free(j->object_list); + + if (other && delete_dependencies) { + log_unit_debug(other->unit, + "Deleting job %s/%s as dependency of job %s/%s", + other->unit->id, job_type_to_string(other->type), + j->unit->id, job_type_to_string(j->type)); + transaction_delete_job(tr, other, delete_dependencies); + } + } +} + +void transaction_add_propagate_reload_jobs(Transaction *tr, Unit *unit, Job *by, bool ignore_order, sd_bus_error *e) { + Iterator i; + JobType nt; + Unit *dep; + void *v; + int r; + + assert(tr); + assert(unit); + + HASHMAP_FOREACH_KEY(v, dep, unit->dependencies[UNIT_PROPAGATES_RELOAD_TO], i) { + nt = job_type_collapse(JOB_TRY_RELOAD, dep); + if (nt == JOB_NOP) + continue; + + r = transaction_add_job_and_dependencies(tr, nt, dep, by, false, false, false, ignore_order, e); + if (r < 0) { + log_unit_warning(dep, + "Cannot add dependency reload job, ignoring: %s", + bus_error_message(e, r)); + sd_bus_error_free(e); + } + } +} + +int transaction_add_job_and_dependencies( + Transaction *tr, + JobType type, + Unit *unit, + Job *by, + bool matters, + bool conflicts, + bool ignore_requirements, + bool ignore_order, + sd_bus_error *e) { + + bool is_new; + Iterator i; + Unit *dep; + Job *ret; + void *v; + int r; + + assert(tr); + assert(type < _JOB_TYPE_MAX); + assert(type < _JOB_TYPE_MAX_IN_TRANSACTION); + assert(unit); + + /* Before adding jobs for this unit, let's ensure that its state has been loaded + * This matters when jobs are spawned as part of coldplugging itself (see e. g. path_coldplug()). + * This way, we "recursively" coldplug units, ensuring that we do not look at state of + * not-yet-coldplugged units. */ + if (MANAGER_IS_RELOADING(unit->manager)) + unit_coldplug(unit); + + if (by) + log_trace("Pulling in %s/%s from %s/%s", unit->id, job_type_to_string(type), by->unit->id, job_type_to_string(by->type)); + + /* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set + * temporarily. */ + if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED)) + return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id); + + if (type != JOB_STOP) { + r = bus_unit_validate_load_state(unit, e); + if (r < 0) + return r; + } + + if (!unit_job_is_applicable(unit, type)) + return sd_bus_error_setf(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, + "Job type %s is not applicable for unit %s.", + job_type_to_string(type), unit->id); + + /* First add the job. */ + ret = transaction_add_one_job(tr, type, unit, &is_new); + if (!ret) + return -ENOMEM; + + ret->ignore_order = ret->ignore_order || ignore_order; + + /* Then, add a link to the job. */ + if (by) { + if (!job_dependency_new(by, ret, matters, conflicts)) + return -ENOMEM; + } else { + /* If the job has no parent job, it is the anchor job. */ + assert(!tr->anchor_job); + tr->anchor_job = ret; + } + + if (is_new && !ignore_requirements && type != JOB_NOP) { + Set *following; + + /* If we are following some other unit, make sure we + * add all dependencies of everybody following. */ + if (unit_following_set(ret->unit, &following) > 0) { + SET_FOREACH(dep, following, i) { + r = transaction_add_job_and_dependencies(tr, type, dep, ret, false, false, false, ignore_order, e); + if (r < 0) { + log_unit_full(dep, + r == -ERFKILL ? LOG_INFO : LOG_WARNING, + r, "Cannot add dependency job, ignoring: %s", + bus_error_message(e, r)); + sd_bus_error_free(e); + } + } + + set_free(following); + } + + /* Finally, recursively add in all dependencies. */ + if (IN_SET(type, JOB_START, JOB_RESTART)) { + HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_REQUIRES], i) { + r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e); + if (r < 0) { + if (r != -EBADR) /* job type not applicable */ + goto fail; + + sd_bus_error_free(e); + } + } + + HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_BINDS_TO], i) { + r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, false, false, ignore_order, e); + if (r < 0) { + if (r != -EBADR) /* job type not applicable */ + goto fail; + + sd_bus_error_free(e); + } + } + + HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_WANTS], i) { + r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, false, false, false, ignore_order, e); + if (r < 0) { + /* unit masked, job type not applicable and unit not found are not considered as errors. */ + log_unit_full(dep, + IN_SET(r, -ERFKILL, -EBADR, -ENOENT) ? LOG_DEBUG : LOG_WARNING, + r, "Cannot add dependency job, ignoring: %s", + bus_error_message(e, r)); + sd_bus_error_free(e); + } + } + + HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_REQUISITE], i) { + r = transaction_add_job_and_dependencies(tr, JOB_VERIFY_ACTIVE, dep, ret, true, false, false, ignore_order, e); + if (r < 0) { + if (r != -EBADR) /* job type not applicable */ + goto fail; + + sd_bus_error_free(e); + } + } + + HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_CONFLICTS], i) { + r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, true, true, false, ignore_order, e); + if (r < 0) { + if (r != -EBADR) /* job type not applicable */ + goto fail; + + sd_bus_error_free(e); + } + } + + HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[UNIT_CONFLICTED_BY], i) { + r = transaction_add_job_and_dependencies(tr, JOB_STOP, dep, ret, false, false, false, ignore_order, e); + if (r < 0) { + log_unit_warning(dep, + "Cannot add dependency job, ignoring: %s", + bus_error_message(e, r)); + sd_bus_error_free(e); + } + } + + } + + if (IN_SET(type, JOB_STOP, JOB_RESTART)) { + static const UnitDependency propagate_deps[] = { + UNIT_REQUIRED_BY, + UNIT_REQUISITE_OF, + UNIT_BOUND_BY, + UNIT_CONSISTS_OF, + }; + + JobType ptype; + unsigned j; + + /* We propagate STOP as STOP, but RESTART only + * as TRY_RESTART, in order not to start + * dependencies that are not around. */ + ptype = type == JOB_RESTART ? JOB_TRY_RESTART : type; + + for (j = 0; j < ELEMENTSOF(propagate_deps); j++) + HASHMAP_FOREACH_KEY(v, dep, ret->unit->dependencies[propagate_deps[j]], i) { + JobType nt; + + nt = job_type_collapse(ptype, dep); + if (nt == JOB_NOP) + continue; + + r = transaction_add_job_and_dependencies(tr, nt, dep, ret, true, false, false, ignore_order, e); + if (r < 0) { + if (r != -EBADR) /* job type not applicable */ + goto fail; + + sd_bus_error_free(e); + } + } + } + + if (type == JOB_RELOAD) + transaction_add_propagate_reload_jobs(tr, ret->unit, ret, ignore_order, e); + + /* JOB_VERIFY_ACTIVE requires no dependency handling */ + } + + return 0; + +fail: + return r; +} + +int transaction_add_isolate_jobs(Transaction *tr, Manager *m) { + Iterator i; + Unit *u; + char *k; + int r; + + assert(tr); + assert(m); + + HASHMAP_FOREACH_KEY(u, k, m->units, i) { + + /* ignore aliases */ + if (u->id != k) + continue; + + if (u->ignore_on_isolate) + continue; + + /* No need to stop inactive jobs */ + if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)) && !u->job) + continue; + + /* Is there already something listed for this? */ + if (hashmap_get(tr->jobs, u)) + continue; + + r = transaction_add_job_and_dependencies(tr, JOB_STOP, u, tr->anchor_job, true, false, false, false, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Cannot add isolate job, ignoring: %m"); + } + + return 0; +} + +int transaction_add_triggering_jobs(Transaction *tr, Unit *u) { + Iterator i; + void *v; + Unit *trigger; + int r; + + assert(tr); + assert(u); + + HASHMAP_FOREACH_KEY(v, trigger, u->dependencies[UNIT_TRIGGERED_BY], i) { + /* No need to stop inactive jobs */ + if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(trigger)) && !trigger->job) + continue; + + /* Is there already something listed for this? */ + if (hashmap_get(tr->jobs, trigger)) + continue; + + r = transaction_add_job_and_dependencies(tr, JOB_STOP, trigger, tr->anchor_job, true, false, false, false, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Cannot add triggered by job, ignoring: %m"); + } + + return 0; +} + +Transaction *transaction_new(bool irreversible) { + Transaction *tr; + + tr = new0(Transaction, 1); + if (!tr) + return NULL; + + tr->jobs = hashmap_new(NULL); + if (!tr->jobs) + return mfree(tr); + + tr->irreversible = irreversible; + + return tr; +} + +void transaction_free(Transaction *tr) { + assert(hashmap_isempty(tr->jobs)); + hashmap_free(tr->jobs); + free(tr); +} diff --git a/src/core/transaction.h b/src/core/transaction.h new file mode 100644 index 00000000..ba42f58e --- /dev/null +++ b/src/core/transaction.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Transaction Transaction; + +#include "hashmap.h" +#include "job.h" +#include "manager.h" +#include "unit.h" + +struct Transaction { + /* Jobs to be added */ + Hashmap *jobs; /* Unit object => Job object list 1:1 */ + Job *anchor_job; /* the job the user asked for */ + bool irreversible; +}; + +Transaction *transaction_new(bool irreversible); +void transaction_free(Transaction *tr); + +void transaction_add_propagate_reload_jobs(Transaction *tr, Unit *unit, Job *by, bool ignore_order, sd_bus_error *e); +int transaction_add_job_and_dependencies( + Transaction *tr, + JobType type, + Unit *unit, + Job *by, + bool matters, + bool conflicts, + bool ignore_requirements, + bool ignore_order, + sd_bus_error *e); +int transaction_activate(Transaction *tr, Manager *m, JobMode mode, Set *affected, sd_bus_error *e); +int transaction_add_isolate_jobs(Transaction *tr, Manager *m); +int transaction_add_triggering_jobs(Transaction *tr, Unit *u); +void transaction_abort(Transaction *tr); diff --git a/src/core/triggers.systemd.in b/src/core/triggers.systemd.in new file mode 100644 index 00000000..10b1889b --- /dev/null +++ b/src/core/triggers.systemd.in @@ -0,0 +1,143 @@ +# -*- Mode: rpm-spec; indent-tabs-mode: nil -*- */ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# Copyright © 2018 Neal Gompa + +# The contents of this are an example to be copied into systemd.spec. +# +# Minimum rpm version supported: 4.13.0 + +%transfiletriggerin -P 900900 -p -- @systemunitdir@ /etc/systemd/system +-- This script will run after any package is initially installed or +-- upgraded. We care about the case where a package is initially +-- installed, because other cases are covered by the *un scriptlets, +-- so sometimes we will reload needlessly. + +if posix.access("/run/systemd/system") then + pid = posix.fork() + if pid == 0 then + assert(posix.exec("%{_bindir}/systemctl", "daemon-reload")) + elseif pid > 0 then + posix.wait(pid) + end +end + +%transfiletriggerun -p -- @systemunitdir@ /etc/systemd/system +-- On removal, we need to run daemon-reload after any units have been +-- removed. %transfiletriggerpostun would be ideal, but it does not get +-- executed for some reason. +-- On upgrade, we need to run daemon-reload after any new unit files +-- have been installed, but before %postun scripts in packages get +-- executed. %transfiletriggerun gets the right list of files +-- but it is invoked too early (before changes happen). +-- %filetriggerpostun happens at the right time, but it fires for +-- every package. +-- To execute the reload at the right time, we create a state +-- file in %transfiletriggerun and execute the daemon-reload in +-- the first %filetriggerpostun. + +if posix.access("/run/systemd/system") then + posix.mkdir("%{_localstatedir}/lib") + posix.mkdir("%{_localstatedir}/lib/rpm-state") + posix.mkdir("%{_localstatedir}/lib/rpm-state/systemd") + io.open("%{_localstatedir}/lib/rpm-state/systemd/needs-reload", "w") +end + +%filetriggerpostun -P 1000100 -p -- @systemunitdir@ /etc/systemd/system +if posix.access("%{_localstatedir}/lib/rpm-state/systemd/needs-reload") then + posix.unlink("%{_localstatedir}/lib/rpm-state/systemd/needs-reload") + posix.rmdir("%{_localstatedir}/lib/rpm-state/systemd") + pid = posix.fork() + if pid == 0 then + assert(posix.exec("%{_bindir}/systemctl", "daemon-reload")) + elseif pid > 0 then + posix.wait(pid) + end +end + +%transfiletriggerin -P 100700 -p -- @sysusersdir@ +-- This script will process files installed in @sysusersdir@ to create +-- specified users automatically. The priority is set such that it +-- will run before the tmpfiles file trigger. +if posix.access("/run/systemd/system") then + pid = posix.fork() + if pid == 0 then + assert(posix.exec("%{_bindir}/systemd-sysusers")) + elseif pid > 0 then + posix.wait(pid) + end +end + +%transfiletriggerin -P 100500 -p -- @tmpfilesdir@ +-- This script will process files installed in @tmpfilesdir@ to create +-- tmpfiles automatically. The priority is set such that it will run +-- after the sysusers file trigger, but before any other triggers. +if posix.access("/run/systemd/system") then + pid = posix.fork() + if pid == 0 then + assert(posix.exec("%{_bindir}/systemd-tmpfiles", "--create")) + elseif pid > 0 then + posix.wait(pid) + end +end + +%transfiletriggerin -p -- @udevhwdbdir@ +-- This script will automatically invoke hwdb update if files have been +-- installed or updated in @udevhwdbdir@. +if posix.access("/run/systemd/system") then + pid = posix.fork() + if pid == 0 then + assert(posix.exec("%{_bindir}/systemd-hwdb", "update")) + elseif pid > 0 then + posix.wait(pid) + end +end + +%transfiletriggerin -p -- @catalogdir@ +-- This script will automatically invoke journal catalog update if files +-- have been installed or updated in @catalogdir@. +if posix.access("/run/systemd/system") then + pid = posix.fork() + if pid == 0 then + assert(posix.exec("%{_bindir}/journalctl", "--update-catalog")) + elseif pid > 0 then + posix.wait(pid) + end +end + +%transfiletriggerin -p -- @udevrulesdir@ +-- This script will automatically update udev with new rules if files +-- have been installed or updated in @udevrulesdir@. +if posix.access("/run/systemd/system") then + pid = posix.fork() + if pid == 0 then + assert(posix.exec("%{_bindir}/udevadm", "control", "--reload")) + elseif pid > 0 then + posix.wait(pid) + end +end + +%transfiletriggerin -p -- @sysctldir@ +-- This script will automatically apply sysctl rules if files have been +-- installed or updated in @sysctldir@. +if posix.access("/run/systemd/system") then + pid = posix.fork() + if pid == 0 then + assert(posix.exec("@rootlibexecdir@/systemd-sysctl")) + elseif pid > 0 then + posix.wait(pid) + end +end + +%transfiletriggerin -p -- @binfmtdir@ +-- This script will automatically apply binfmt rules if files have been +-- installed or updated in @binfmtdir@. +if posix.access("/run/systemd/system") then + pid = posix.fork() + if pid == 0 then + assert(posix.exec("@rootlibexecdir@/systemd-binfmt")) + elseif pid > 0 then + posix.wait(pid) + end +end diff --git a/src/core/unit-printf.c b/src/core/unit-printf.c new file mode 100644 index 00000000..2daaaf99 --- /dev/null +++ b/src/core/unit-printf.c @@ -0,0 +1,288 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "cgroup-util.h" +#include "format-util.h" +#include "macro.h" +#include "specifier.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "unit-printf.h" +#include "unit.h" +#include "user-util.h" + +static int specifier_prefix_and_instance(char specifier, const void *data, const void *userdata, char **ret) { + const Unit *u = userdata; + + assert(u); + + return unit_name_to_prefix_and_instance(u->id, ret); +} + +static int specifier_prefix(char specifier, const void *data, const void *userdata, char **ret) { + const Unit *u = userdata; + + assert(u); + + return unit_name_to_prefix(u->id, ret); +} + +static int specifier_prefix_unescaped(char specifier, const void *data, const void *userdata, char **ret) { + _cleanup_free_ char *p = NULL; + const Unit *u = userdata; + int r; + + assert(u); + + r = unit_name_to_prefix(u->id, &p); + if (r < 0) + return r; + + return unit_name_unescape(p, ret); +} + +static int specifier_instance_unescaped(char specifier, const void *data, const void *userdata, char **ret) { + const Unit *u = userdata; + + assert(u); + + return unit_name_unescape(strempty(u->instance), ret); +} + +static int specifier_last_component(char specifier, const void *data, const void *userdata, char **ret) { + const Unit *u = userdata; + _cleanup_free_ char *prefix = NULL; + char *dash; + int r; + + assert(u); + + r = unit_name_to_prefix(u->id, &prefix); + if (r < 0) + return r; + + dash = strrchr(prefix, '-'); + if (dash) + return specifier_string(specifier, dash + 1, userdata, ret); + + *ret = TAKE_PTR(prefix); + return 0; +} + +static int specifier_last_component_unescaped(char specifier, const void *data, const void *userdata, char **ret) { + _cleanup_free_ char *p = NULL; + int r; + + r = specifier_last_component(specifier, data, userdata, &p); + if (r < 0) + return r; + + return unit_name_unescape(p, ret); +} + +static int specifier_filename(char specifier, const void *data, const void *userdata, char **ret) { + const Unit *u = userdata; + + assert(u); + + if (u->instance) + return unit_name_path_unescape(u->instance, ret); + else + return unit_name_to_path(u->id, ret); +} + +static void bad_specifier(const Unit *u, char specifier) { + log_unit_warning(u, "Specifier '%%%c' used in unit configuration, which is deprecated. Please update your unit file, as it does not work as intended.", specifier); +} + +static int specifier_cgroup(char specifier, const void *data, const void *userdata, char **ret) { + const Unit *u = userdata; + char *n; + + assert(u); + + bad_specifier(u, specifier); + + if (u->cgroup_path) + n = strdup(u->cgroup_path); + else + n = unit_default_cgroup_path(u); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; +} + +static int specifier_cgroup_root(char specifier, const void *data, const void *userdata, char **ret) { + const Unit *u = userdata; + char *n; + + assert(u); + + bad_specifier(u, specifier); + + n = strdup(u->manager->cgroup_root); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; +} + +static int specifier_cgroup_slice(char specifier, const void *data, const void *userdata, char **ret) { + const Unit *u = userdata; + char *n; + + assert(u); + + bad_specifier(u, specifier); + + if (UNIT_ISSET(u->slice)) { + const Unit *slice; + + slice = UNIT_DEREF(u->slice); + + if (slice->cgroup_path) + n = strdup(slice->cgroup_path); + else + n = unit_default_cgroup_path(slice); + } else + n = strdup(u->manager->cgroup_root); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; +} + +static int specifier_special_directory(char specifier, const void *data, const void *userdata, char **ret) { + const Unit *u = userdata; + char *n = NULL; + + assert(u); + + n = strdup(u->manager->prefix[PTR_TO_UINT(data)]); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; +} + +int unit_name_printf(const Unit *u, const char* format, char **ret) { + + /* + * This will use the passed string as format string and replace the following specifiers (which should all be + * safe for inclusion in unit names): + * + * %n: the full id of the unit (foo@bar.waldo) + * %N: the id of the unit without the suffix (foo@bar) + * %p: the prefix (foo) + * %i: the instance (bar) + * + * %U: the UID of the running user + * %u: the username of the running user + * + * %m: the machine ID of the running system + * %H: the host name of the running system + * %b: the boot ID of the running system + */ + + const Specifier table[] = { + { 'n', specifier_string, u->id }, + { 'N', specifier_prefix_and_instance, NULL }, + { 'p', specifier_prefix, NULL }, + { 'i', specifier_string, u->instance }, + { 'j', specifier_last_component, NULL }, + + { 'g', specifier_group_name, NULL }, + { 'G', specifier_group_id, NULL }, + { 'U', specifier_user_id, NULL }, + { 'u', specifier_user_name, NULL }, + + { 'm', specifier_machine_id, NULL }, + { 'H', specifier_host_name, NULL }, + { 'b', specifier_boot_id, NULL }, + {} + }; + + assert(u); + assert(format); + assert(ret); + + return specifier_printf(format, table, u, ret); +} + +int unit_full_printf(const Unit *u, const char *format, char **ret) { + /* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of additional codes + * (which are likely not suitable for unescaped inclusion in unit names): + * + * %f: the unescaped instance if set, otherwise the id unescaped as path + * + * %c: cgroup path of unit (deprecated) + * %r: where units in this slice are placed in the cgroup tree (deprecated) + * %R: the root of this systemd's instance tree (deprecated) + * + * %t: the runtime directory root (e.g. /run or $XDG_RUNTIME_DIR) + * %S: the state directory root (e.g. /var/lib or $XDG_CONFIG_HOME) + * %C: the cache directory root (e.g. /var/cache or $XDG_CACHE_HOME) + * %L: the log directory root (e.g. /var/log or $XDG_CONFIG_HOME/log) + * %E: the configuration directory root (e.g. /etc or $XDG_CONFIG_HOME) + * %T: the temporary directory (e.g. /tmp, or $TMPDIR, $TEMP, $TMP) + * %V: the temporary directory for large, persistent stuff (e.g. /var/tmp, or $TMPDIR, $TEMP, $TMP) + * + * %h: the homedir of the running user + * %s: the shell of the running user + * + * %v: `uname -r` of the running system + * + * NOTICE: When you add new entries here, please be careful: specifiers which depend on settings of the unit + * file itself are broken by design, as they would resolve differently depending on whether they are used + * before or after the relevant configuration setting. Hence: don't add them. + */ + + assert(u); + assert(format); + assert(ret); + + const Specifier table[] = { + { 'n', specifier_string, u->id }, + { 'N', specifier_prefix_and_instance, NULL }, + { 'p', specifier_prefix, NULL }, + { 'P', specifier_prefix_unescaped, NULL }, + { 'i', specifier_string, u->instance }, + { 'I', specifier_instance_unescaped, NULL }, + { 'j', specifier_last_component, NULL }, + { 'J', specifier_last_component_unescaped, NULL }, + + { 'f', specifier_filename, NULL }, + { 'c', specifier_cgroup, NULL }, + { 'r', specifier_cgroup_slice, NULL }, + { 'R', specifier_cgroup_root, NULL }, + + { 't', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_RUNTIME) }, + { 'S', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_STATE) }, + { 'C', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_CACHE) }, + { 'L', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_LOGS) }, + { 'E', specifier_special_directory, UINT_TO_PTR(EXEC_DIRECTORY_CONFIGURATION) }, + { 'T', specifier_tmp_dir, NULL }, + { 'V', specifier_var_tmp_dir, NULL }, + + { 'g', specifier_group_name, NULL }, + { 'G', specifier_group_id, NULL }, + { 'U', specifier_user_id, NULL }, + { 'u', specifier_user_name, NULL }, + { 'h', specifier_user_home, NULL }, + { 's', specifier_user_shell, NULL }, + + { 'm', specifier_machine_id, NULL }, + { 'H', specifier_host_name, NULL }, + { 'b', specifier_boot_id, NULL }, + { 'v', specifier_kernel_release, NULL }, + {} + }; + + return specifier_printf(format, table, u, ret); +} diff --git a/src/core/unit-printf.h b/src/core/unit-printf.h new file mode 100644 index 00000000..cb75448a --- /dev/null +++ b/src/core/unit-printf.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "unit.h" + +int unit_name_printf(const Unit *u, const char* text, char **ret); +int unit_full_printf(const Unit *u, const char *text, char **ret); diff --git a/src/core/unit.c b/src/core/unit.c new file mode 100644 index 00000000..c406bb7a --- /dev/null +++ b/src/core/unit.c @@ -0,0 +1,5942 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-id128.h" +#include "sd-messages.h" + +#include "all-units.h" +#include "alloc-util.h" +#include "bpf-firewall.h" +#include "bus-common-errors.h" +#include "bus-util.h" +#include "cgroup-setup.h" +#include "cgroup-util.h" +#include "dbus-unit.h" +#include "dbus.h" +#include "dropin.h" +#include "escape.h" +#include "execute.h" +#include "fd-util.h" +#include "fileio-label.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "id128-util.h" +#include "io-util.h" +#include "install.h" +#include "load-dropin.h" +#include "load-fragment.h" +#include "log.h" +#include "macro.h" +#include "missing_audit.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "rm-rf.h" +#include "serialize.h" +#include "set.h" +#include "signal-util.h" +#include "sparse-endian.h" +#include "special.h" +#include "specifier.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "umask-util.h" +#include "unit-name.h" +#include "unit.h" +#include "user-util.h" +#include "virt.h" + +/* Thresholds for logging at INFO level about resource consumption */ +#define MENTIONWORTHY_CPU_NSEC (1 * NSEC_PER_SEC) +#define MENTIONWORTHY_IO_BYTES (1024 * 1024ULL) +#define MENTIONWORTHY_IP_BYTES (0ULL) + +/* Thresholds for logging at INFO level about resource consumption */ +#define NOTICEWORTHY_CPU_NSEC (10*60 * NSEC_PER_SEC) /* 10 minutes */ +#define NOTICEWORTHY_IO_BYTES (10 * 1024 * 1024ULL) /* 10 MB */ +#define NOTICEWORTHY_IP_BYTES (128 * 1024 * 1024ULL) /* 128 MB */ + +const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { + [UNIT_SERVICE] = &service_vtable, + [UNIT_SOCKET] = &socket_vtable, + [UNIT_TARGET] = &target_vtable, + [UNIT_DEVICE] = &device_vtable, + [UNIT_MOUNT] = &mount_vtable, + [UNIT_AUTOMOUNT] = &automount_vtable, + [UNIT_SWAP] = &swap_vtable, + [UNIT_TIMER] = &timer_vtable, + [UNIT_PATH] = &path_vtable, + [UNIT_SLICE] = &slice_vtable, + [UNIT_SCOPE] = &scope_vtable, +}; + +static void maybe_warn_about_dependency(Unit *u, const char *other, UnitDependency dependency); + +Unit *unit_new(Manager *m, size_t size) { + Unit *u; + + assert(m); + assert(size >= sizeof(Unit)); + + u = malloc0(size); + if (!u) + return NULL; + + u->names = set_new(&string_hash_ops); + if (!u->names) + return mfree(u); + + u->manager = m; + u->type = _UNIT_TYPE_INVALID; + u->default_dependencies = true; + u->unit_file_state = _UNIT_FILE_STATE_INVALID; + u->unit_file_preset = -1; + u->on_failure_job_mode = JOB_REPLACE; + u->cgroup_control_inotify_wd = -1; + u->cgroup_memory_inotify_wd = -1; + u->job_timeout = USEC_INFINITY; + u->job_running_timeout = USEC_INFINITY; + u->ref_uid = UID_INVALID; + u->ref_gid = GID_INVALID; + u->cpu_usage_last = NSEC_INFINITY; + u->cgroup_invalidated_mask |= CGROUP_MASK_BPF_FIREWALL; + u->failure_action_exit_status = u->success_action_exit_status = -1; + + u->ip_accounting_ingress_map_fd = -1; + u->ip_accounting_egress_map_fd = -1; + u->ipv4_allow_map_fd = -1; + u->ipv6_allow_map_fd = -1; + u->ipv4_deny_map_fd = -1; + u->ipv6_deny_map_fd = -1; + + u->last_section_private = -1; + + u->start_ratelimit = (RateLimit) { m->default_start_limit_interval, m->default_start_limit_burst }; + u->auto_stop_ratelimit = (RateLimit) { 10 * USEC_PER_SEC, 16 }; + + for (CGroupIOAccountingMetric i = 0; i < _CGROUP_IO_ACCOUNTING_METRIC_MAX; i++) + u->io_accounting_last[i] = UINT64_MAX; + + return u; +} + +int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret) { + _cleanup_(unit_freep) Unit *u = NULL; + int r; + + u = unit_new(m, size); + if (!u) + return -ENOMEM; + + r = unit_add_name(u, name); + if (r < 0) + return r; + + *ret = TAKE_PTR(u); + + return r; +} + +bool unit_has_name(const Unit *u, const char *name) { + assert(u); + assert(name); + + return set_contains(u->names, (char*) name); +} + +static void unit_init(Unit *u) { + CGroupContext *cc; + ExecContext *ec; + KillContext *kc; + + assert(u); + assert(u->manager); + assert(u->type >= 0); + + cc = unit_get_cgroup_context(u); + if (cc) { + cgroup_context_init(cc); + + /* Copy in the manager defaults into the cgroup + * context, _before_ the rest of the settings have + * been initialized */ + + cc->cpu_accounting = u->manager->default_cpu_accounting; + cc->io_accounting = u->manager->default_io_accounting; + cc->blockio_accounting = u->manager->default_blockio_accounting; + cc->memory_accounting = u->manager->default_memory_accounting; + cc->tasks_accounting = u->manager->default_tasks_accounting; + cc->ip_accounting = u->manager->default_ip_accounting; + + if (u->type != UNIT_SLICE) + cc->tasks_max = u->manager->default_tasks_max; + } + + ec = unit_get_exec_context(u); + if (ec) { + exec_context_init(ec); + + ec->keyring_mode = MANAGER_IS_SYSTEM(u->manager) ? + EXEC_KEYRING_SHARED : EXEC_KEYRING_INHERIT; + } + + kc = unit_get_kill_context(u); + if (kc) + kill_context_init(kc); + + if (UNIT_VTABLE(u)->init) + UNIT_VTABLE(u)->init(u); +} + +int unit_add_name(Unit *u, const char *text) { + _cleanup_free_ char *s = NULL, *i = NULL; + UnitType t; + int r; + + assert(u); + assert(text); + + if (unit_name_is_valid(text, UNIT_NAME_TEMPLATE)) { + + if (!u->instance) + return -EINVAL; + + r = unit_name_replace_instance(text, u->instance, &s); + if (r < 0) + return r; + } else { + s = strdup(text); + if (!s) + return -ENOMEM; + } + + if (set_contains(u->names, s)) + return 0; + if (hashmap_contains(u->manager->units, s)) + return -EEXIST; + + if (!unit_name_is_valid(s, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) + return -EINVAL; + + t = unit_name_to_type(s); + if (t < 0) + return -EINVAL; + + if (u->type != _UNIT_TYPE_INVALID && t != u->type) + return -EINVAL; + + r = unit_name_to_instance(s, &i); + if (r < 0) + return r; + + if (i && !unit_type_may_template(t)) + return -EINVAL; + + /* Ensure that this unit is either instanced or not instanced, + * but not both. Note that we do allow names with different + * instance names however! */ + if (u->type != _UNIT_TYPE_INVALID && !u->instance != !i) + return -EINVAL; + + if (!unit_type_may_alias(t) && !set_isempty(u->names)) + return -EEXIST; + + if (hashmap_size(u->manager->units) >= MANAGER_MAX_NAMES) + return -E2BIG; + + r = set_put(u->names, s); + if (r < 0) + return r; + assert(r > 0); + + r = hashmap_put(u->manager->units, s, u); + if (r < 0) { + (void) set_remove(u->names, s); + return r; + } + + if (u->type == _UNIT_TYPE_INVALID) { + u->type = t; + u->id = s; + u->instance = TAKE_PTR(i); + + LIST_PREPEND(units_by_type, u->manager->units_by_type[t], u); + + unit_init(u); + } + + s = NULL; + + unit_add_to_dbus_queue(u); + return 0; +} + +int unit_choose_id(Unit *u, const char *name) { + _cleanup_free_ char *t = NULL; + char *s, *i; + int r; + + assert(u); + assert(name); + + if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { + + if (!u->instance) + return -EINVAL; + + r = unit_name_replace_instance(name, u->instance, &t); + if (r < 0) + return r; + + name = t; + } + + /* Selects one of the names of this unit as the id */ + s = set_get(u->names, (char*) name); + if (!s) + return -ENOENT; + + /* Determine the new instance from the new id */ + r = unit_name_to_instance(s, &i); + if (r < 0) + return r; + + u->id = s; + + free(u->instance); + u->instance = i; + + unit_add_to_dbus_queue(u); + + return 0; +} + +int unit_set_description(Unit *u, const char *description) { + int r; + + assert(u); + + r = free_and_strdup(&u->description, empty_to_null(description)); + if (r < 0) + return r; + if (r > 0) + unit_add_to_dbus_queue(u); + + return 0; +} + +bool unit_may_gc(Unit *u) { + UnitActiveState state; + int r; + + assert(u); + + /* Checks whether the unit is ready to be unloaded for garbage collection. + * Returns true when the unit may be collected, and false if there's some + * reason to keep it loaded. + * + * References from other units are *not* checked here. Instead, this is done + * in unit_gc_sweep(), but using markers to properly collect dependency loops. + */ + + if (u->job) + return false; + + if (u->nop_job) + return false; + + state = unit_active_state(u); + + /* If the unit is inactive and failed and no job is queued for it, then release its runtime resources */ + if (UNIT_IS_INACTIVE_OR_FAILED(state) && + UNIT_VTABLE(u)->release_resources) + UNIT_VTABLE(u)->release_resources(u); + + if (u->perpetual) + return false; + + if (sd_bus_track_count(u->bus_track) > 0) + return false; + + /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */ + switch (u->collect_mode) { + + case COLLECT_INACTIVE: + if (state != UNIT_INACTIVE) + return false; + + break; + + case COLLECT_INACTIVE_OR_FAILED: + if (!IN_SET(state, UNIT_INACTIVE, UNIT_FAILED)) + return false; + + break; + + default: + assert_not_reached("Unknown garbage collection mode"); + } + + if (u->cgroup_path) { + /* If the unit has a cgroup, then check whether there's anything in it. If so, we should stay + * around. Units with active processes should never be collected. */ + + r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to determine whether cgroup %s is empty: %m", u->cgroup_path); + if (r <= 0) + return false; + } + + if (UNIT_VTABLE(u)->may_gc && !UNIT_VTABLE(u)->may_gc(u)) + return false; + + return true; +} + +void unit_add_to_load_queue(Unit *u) { + assert(u); + assert(u->type != _UNIT_TYPE_INVALID); + + if (u->load_state != UNIT_STUB || u->in_load_queue) + return; + + LIST_PREPEND(load_queue, u->manager->load_queue, u); + u->in_load_queue = true; +} + +void unit_add_to_cleanup_queue(Unit *u) { + assert(u); + + if (u->in_cleanup_queue) + return; + + LIST_PREPEND(cleanup_queue, u->manager->cleanup_queue, u); + u->in_cleanup_queue = true; +} + +void unit_add_to_gc_queue(Unit *u) { + assert(u); + + if (u->in_gc_queue || u->in_cleanup_queue) + return; + + if (!unit_may_gc(u)) + return; + + LIST_PREPEND(gc_queue, u->manager->gc_unit_queue, u); + u->in_gc_queue = true; +} + +void unit_add_to_dbus_queue(Unit *u) { + assert(u); + assert(u->type != _UNIT_TYPE_INVALID); + + if (u->load_state == UNIT_STUB || u->in_dbus_queue) + return; + + /* Shortcut things if nobody cares */ + if (sd_bus_track_count(u->manager->subscribed) <= 0 && + sd_bus_track_count(u->bus_track) <= 0 && + set_isempty(u->manager->private_buses)) { + u->sent_dbus_new_signal = true; + return; + } + + LIST_PREPEND(dbus_queue, u->manager->dbus_unit_queue, u); + u->in_dbus_queue = true; +} + +void unit_submit_to_stop_when_unneeded_queue(Unit *u) { + assert(u); + + if (u->in_stop_when_unneeded_queue) + return; + + if (!u->stop_when_unneeded) + return; + + if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) + return; + + LIST_PREPEND(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u); + u->in_stop_when_unneeded_queue = true; +} + +static void bidi_set_free(Unit *u, Hashmap *h) { + Unit *other; + Iterator i; + void *v; + + assert(u); + + /* Frees the hashmap and makes sure we are dropped from the inverse pointers */ + + HASHMAP_FOREACH_KEY(v, other, h, i) { + UnitDependency d; + + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) + hashmap_remove(other->dependencies[d], u); + + unit_add_to_gc_queue(other); + } + + hashmap_free(h); +} + +static void unit_remove_transient(Unit *u) { + char **i; + + assert(u); + + if (!u->transient) + return; + + if (u->fragment_path) + (void) unlink(u->fragment_path); + + STRV_FOREACH(i, u->dropin_paths) { + _cleanup_free_ char *p = NULL, *pp = NULL; + + p = dirname_malloc(*i); /* Get the drop-in directory from the drop-in file */ + if (!p) + continue; + + pp = dirname_malloc(p); /* Get the config directory from the drop-in directory */ + if (!pp) + continue; + + /* Only drop transient drop-ins */ + if (!path_equal(u->manager->lookup_paths.transient, pp)) + continue; + + (void) unlink(*i); + (void) rmdir(p); + } +} + +static void unit_free_requires_mounts_for(Unit *u) { + assert(u); + + for (;;) { + _cleanup_free_ char *path; + + path = hashmap_steal_first_key(u->requires_mounts_for); + if (!path) + break; + else { + char s[strlen(path) + 1]; + + PATH_FOREACH_PREFIX_MORE(s, path) { + char *y; + Set *x; + + x = hashmap_get2(u->manager->units_requiring_mounts_for, s, (void**) &y); + if (!x) + continue; + + (void) set_remove(x, u); + + if (set_isempty(x)) { + (void) hashmap_remove(u->manager->units_requiring_mounts_for, y); + free(y); + set_free(x); + } + } + } + } + + u->requires_mounts_for = hashmap_free(u->requires_mounts_for); +} + +static void unit_done(Unit *u) { + ExecContext *ec; + CGroupContext *cc; + + assert(u); + + if (u->type < 0) + return; + + if (UNIT_VTABLE(u)->done) + UNIT_VTABLE(u)->done(u); + + ec = unit_get_exec_context(u); + if (ec) + exec_context_done(ec); + + cc = unit_get_cgroup_context(u); + if (cc) + cgroup_context_done(cc); +} + +void unit_free(Unit *u) { + UnitDependency d; + Iterator i; + char *t; + + if (!u) + return; + + if (UNIT_ISSET(u->slice)) { + /* A unit is being dropped from the tree, make sure our parent slice recalculates the member mask */ + unit_invalidate_cgroup_members_masks(UNIT_DEREF(u->slice)); + + /* And make sure the parent is realized again, updating cgroup memberships */ + unit_add_to_cgroup_realize_queue(UNIT_DEREF(u->slice)); + } + + u->transient_file = safe_fclose(u->transient_file); + + if (!MANAGER_IS_RELOADING(u->manager)) + unit_remove_transient(u); + + bus_unit_send_removed_signal(u); + + unit_done(u); + + unit_dequeue_rewatch_pids(u); + + sd_bus_slot_unref(u->match_bus_slot); + sd_bus_track_unref(u->bus_track); + u->deserialized_refs = strv_free(u->deserialized_refs); + + unit_free_requires_mounts_for(u); + + SET_FOREACH(t, u->names, i) + hashmap_remove_value(u->manager->units, t, u); + + if (!sd_id128_is_null(u->invocation_id)) + hashmap_remove_value(u->manager->units_by_invocation_id, &u->invocation_id, u); + + if (u->job) { + Job *j = u->job; + job_uninstall(j); + job_free(j); + } + + if (u->nop_job) { + Job *j = u->nop_job; + job_uninstall(j); + job_free(j); + } + + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) + bidi_set_free(u, u->dependencies[d]); + + if (u->on_console) + manager_unref_console(u->manager); + + unit_release_cgroup(u); + + if (!MANAGER_IS_RELOADING(u->manager)) + unit_unlink_state_files(u); + + unit_unref_uid_gid(u, false); + + (void) manager_update_failed_units(u->manager, u, false); + set_remove(u->manager->startup_units, u); + + unit_unwatch_all_pids(u); + + unit_ref_unset(&u->slice); + while (u->refs_by_target) + unit_ref_unset(u->refs_by_target); + + if (u->type != _UNIT_TYPE_INVALID) + LIST_REMOVE(units_by_type, u->manager->units_by_type[u->type], u); + + if (u->in_load_queue) + LIST_REMOVE(load_queue, u->manager->load_queue, u); + + if (u->in_dbus_queue) + LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u); + + if (u->in_gc_queue) + LIST_REMOVE(gc_queue, u->manager->gc_unit_queue, u); + + if (u->in_cgroup_realize_queue) + LIST_REMOVE(cgroup_realize_queue, u->manager->cgroup_realize_queue, u); + + if (u->in_cgroup_empty_queue) + LIST_REMOVE(cgroup_empty_queue, u->manager->cgroup_empty_queue, u); + + if (u->in_cleanup_queue) + LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u); + + if (u->in_target_deps_queue) + LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u); + + if (u->in_stop_when_unneeded_queue) + LIST_REMOVE(stop_when_unneeded_queue, u->manager->stop_when_unneeded_queue, u); + + safe_close(u->ip_accounting_ingress_map_fd); + safe_close(u->ip_accounting_egress_map_fd); + + safe_close(u->ipv4_allow_map_fd); + safe_close(u->ipv6_allow_map_fd); + safe_close(u->ipv4_deny_map_fd); + safe_close(u->ipv6_deny_map_fd); + + bpf_program_unref(u->ip_bpf_ingress); + bpf_program_unref(u->ip_bpf_ingress_installed); + bpf_program_unref(u->ip_bpf_egress); + bpf_program_unref(u->ip_bpf_egress_installed); + + set_free(u->ip_bpf_custom_ingress); + set_free(u->ip_bpf_custom_egress); + set_free(u->ip_bpf_custom_ingress_installed); + set_free(u->ip_bpf_custom_egress_installed); + + bpf_program_unref(u->bpf_device_control_installed); + + condition_free_list(u->conditions); + condition_free_list(u->asserts); + + free(u->description); + strv_free(u->documentation); + free(u->fragment_path); + free(u->source_path); + strv_free(u->dropin_paths); + free(u->instance); + + free(u->job_timeout_reboot_arg); + + set_free_free(u->names); + + free(u->reboot_arg); + + free(u); +} + +UnitActiveState unit_active_state(Unit *u) { + assert(u); + + if (u->load_state == UNIT_MERGED) + return unit_active_state(unit_follow_merge(u)); + + /* After a reload it might happen that a unit is not correctly + * loaded but still has a process around. That's why we won't + * shortcut failed loading to UNIT_INACTIVE_FAILED. */ + + return UNIT_VTABLE(u)->active_state(u); +} + +const char* unit_sub_state_to_string(Unit *u) { + assert(u); + + return UNIT_VTABLE(u)->sub_state_to_string(u); +} + +static int set_complete_move(Set **s, Set **other) { + assert(s); + assert(other); + + if (!other) + return 0; + + if (*s) + return set_move(*s, *other); + else + *s = TAKE_PTR(*other); + + return 0; +} + +static int hashmap_complete_move(Hashmap **s, Hashmap **other) { + assert(s); + assert(other); + + if (!*other) + return 0; + + if (*s) + return hashmap_move(*s, *other); + else + *s = TAKE_PTR(*other); + + return 0; +} + +static int merge_names(Unit *u, Unit *other) { + char *t; + Iterator i; + int r; + + assert(u); + assert(other); + + r = set_complete_move(&u->names, &other->names); + if (r < 0) + return r; + + set_free_free(other->names); + other->names = NULL; + other->id = NULL; + + SET_FOREACH(t, u->names, i) + assert_se(hashmap_replace(u->manager->units, t, u) == 0); + + return 0; +} + +static int reserve_dependencies(Unit *u, Unit *other, UnitDependency d) { + unsigned n_reserve; + + assert(u); + assert(other); + assert(d < _UNIT_DEPENDENCY_MAX); + + /* + * If u does not have this dependency set allocated, there is no need + * to reserve anything. In that case other's set will be transferred + * as a whole to u by complete_move(). + */ + if (!u->dependencies[d]) + return 0; + + /* merge_dependencies() will skip a u-on-u dependency */ + n_reserve = hashmap_size(other->dependencies[d]) - !!hashmap_get(other->dependencies[d], u); + + return hashmap_reserve(u->dependencies[d], n_reserve); +} + +static void merge_dependencies(Unit *u, Unit *other, const char *other_id, UnitDependency d) { + Iterator i; + Unit *back; + void *v; + int r; + + /* Merges all dependencies of type 'd' of the unit 'other' into the deps of the unit 'u' */ + + assert(u); + assert(other); + assert(d < _UNIT_DEPENDENCY_MAX); + + /* Fix backwards pointers. Let's iterate through all dependent units of the other unit. */ + HASHMAP_FOREACH_KEY(v, back, other->dependencies[d], i) { + UnitDependency k; + + /* Let's now iterate through the dependencies of that dependencies of the other units, looking for + * pointers back, and let's fix them up, to instead point to 'u'. */ + + for (k = 0; k < _UNIT_DEPENDENCY_MAX; k++) { + if (back == u) { + /* Do not add dependencies between u and itself. */ + if (hashmap_remove(back->dependencies[k], other)) + maybe_warn_about_dependency(u, other_id, k); + } else { + UnitDependencyInfo di_u, di_other, di_merged; + + /* Let's drop this dependency between "back" and "other", and let's create it between + * "back" and "u" instead. Let's merge the bit masks of the dependency we are moving, + * and any such dependency which might already exist */ + + di_other.data = hashmap_get(back->dependencies[k], other); + if (!di_other.data) + continue; /* dependency isn't set, let's try the next one */ + + di_u.data = hashmap_get(back->dependencies[k], u); + + di_merged = (UnitDependencyInfo) { + .origin_mask = di_u.origin_mask | di_other.origin_mask, + .destination_mask = di_u.destination_mask | di_other.destination_mask, + }; + + r = hashmap_remove_and_replace(back->dependencies[k], other, u, di_merged.data); + if (r < 0) + log_warning_errno(r, "Failed to remove/replace: back=%s other=%s u=%s: %m", back->id, other_id, u->id); + assert(r >= 0); + + /* assert_se(hashmap_remove_and_replace(back->dependencies[k], other, u, di_merged.data) >= 0); */ + } + } + + } + + /* Also do not move dependencies on u to itself */ + back = hashmap_remove(other->dependencies[d], u); + if (back) + maybe_warn_about_dependency(u, other_id, d); + + /* The move cannot fail. The caller must have performed a reservation. */ + assert_se(hashmap_complete_move(&u->dependencies[d], &other->dependencies[d]) == 0); + + other->dependencies[d] = hashmap_free(other->dependencies[d]); +} + +int unit_merge(Unit *u, Unit *other) { + UnitDependency d; + const char *other_id = NULL; + int r; + + assert(u); + assert(other); + assert(u->manager == other->manager); + assert(u->type != _UNIT_TYPE_INVALID); + + other = unit_follow_merge(other); + + if (other == u) + return 0; + + if (u->type != other->type) + return -EINVAL; + + if (!u->instance != !other->instance) + return -EINVAL; + + if (!unit_type_may_alias(u->type)) /* Merging only applies to unit names that support aliases */ + return -EEXIST; + + if (!IN_SET(other->load_state, UNIT_STUB, UNIT_NOT_FOUND)) + return -EEXIST; + + if (other->job) + return -EEXIST; + + if (other->nop_job) + return -EEXIST; + + if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) + return -EEXIST; + + if (other->id) + other_id = strdupa(other->id); + + /* Make reservations to ensure merge_dependencies() won't fail */ + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) { + r = reserve_dependencies(u, other, d); + /* + * We don't rollback reservations if we fail. We don't have + * a way to undo reservations. A reservation is not a leak. + */ + if (r < 0) + return r; + } + + /* Merge names */ + r = merge_names(u, other); + if (r < 0) + return r; + + /* Redirect all references */ + while (other->refs_by_target) + unit_ref_set(other->refs_by_target, other->refs_by_target->source, u); + + /* Merge dependencies */ + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) + merge_dependencies(u, other, other_id, d); + + other->load_state = UNIT_MERGED; + other->merged_into = u; + + /* If there is still some data attached to the other node, we + * don't need it anymore, and can free it. */ + if (other->load_state != UNIT_STUB) + if (UNIT_VTABLE(other)->done) + UNIT_VTABLE(other)->done(other); + + unit_add_to_dbus_queue(u); + unit_add_to_cleanup_queue(other); + + return 0; +} + +int unit_merge_by_name(Unit *u, const char *name) { + _cleanup_free_ char *s = NULL; + Unit *other; + int r; + + /* Either add name to u, or if a unit with name already exists, merge it with u. + * If name is a template, do the same for name@instance, where instance is u's instance. */ + + assert(u); + assert(name); + + if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { + if (!u->instance) + return -EINVAL; + + r = unit_name_replace_instance(name, u->instance, &s); + if (r < 0) + return r; + + name = s; + } + + other = manager_get_unit(u->manager, name); + if (other) + return unit_merge(u, other); + + return unit_add_name(u, name); +} + +Unit* unit_follow_merge(Unit *u) { + assert(u); + + while (u->load_state == UNIT_MERGED) + assert_se(u = u->merged_into); + + return u; +} + +int unit_add_exec_dependencies(Unit *u, ExecContext *c) { + ExecDirectoryType dt; + char **dp; + int r; + + assert(u); + assert(c); + + if (c->working_directory && !c->working_directory_missing_ok) { + r = unit_require_mounts_for(u, c->working_directory, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + } + + if (c->root_directory) { + r = unit_require_mounts_for(u, c->root_directory, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + } + + if (c->root_image) { + r = unit_require_mounts_for(u, c->root_image, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + } + + for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) { + if (!u->manager->prefix[dt]) + continue; + + STRV_FOREACH(dp, c->directories[dt].paths) { + _cleanup_free_ char *p; + + p = path_join(u->manager->prefix[dt], *dp); + if (!p) + return -ENOMEM; + + r = unit_require_mounts_for(u, p, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + } + } + + if (!MANAGER_IS_SYSTEM(u->manager)) + return 0; + + if (c->private_tmp) { + const char *p; + + FOREACH_STRING(p, "/tmp", "/var/tmp") { + r = unit_require_mounts_for(u, p, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + } + + r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_TMPFILES_SETUP_SERVICE, true, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + } + + if (!IN_SET(c->std_output, + EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE, + EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE) && + !IN_SET(c->std_error, + EXEC_OUTPUT_JOURNAL, EXEC_OUTPUT_JOURNAL_AND_CONSOLE, + EXEC_OUTPUT_KMSG, EXEC_OUTPUT_KMSG_AND_CONSOLE, + EXEC_OUTPUT_SYSLOG, EXEC_OUTPUT_SYSLOG_AND_CONSOLE)) + return 0; + + /* If syslog or kernel logging is requested, make sure our own + * logging daemon is run first. */ + + r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_JOURNALD_SOCKET, true, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; + + return 0; +} + +const char *unit_description(Unit *u) { + assert(u); + + if (u->description) + return u->description; + + return strna(u->id); +} + +const char *unit_status_string(Unit *u) { + assert(u); + + if (u->manager->status_unit_format == STATUS_UNIT_FORMAT_NAME && u->id) + return u->id; + + return unit_description(u); +} + +static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependencyMask mask, bool *space) { + const struct { + UnitDependencyMask mask; + const char *name; + } table[] = { + { UNIT_DEPENDENCY_FILE, "file" }, + { UNIT_DEPENDENCY_IMPLICIT, "implicit" }, + { UNIT_DEPENDENCY_DEFAULT, "default" }, + { UNIT_DEPENDENCY_UDEV, "udev" }, + { UNIT_DEPENDENCY_PATH, "path" }, + { UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT, "mountinfo-implicit" }, + { UNIT_DEPENDENCY_MOUNTINFO_DEFAULT, "mountinfo-default" }, + { UNIT_DEPENDENCY_PROC_SWAP, "proc-swap" }, + }; + size_t i; + + assert(f); + assert(kind); + assert(space); + + for (i = 0; i < ELEMENTSOF(table); i++) { + + if (mask == 0) + break; + + if (FLAGS_SET(mask, table[i].mask)) { + if (*space) + fputc(' ', f); + else + *space = true; + + fputs(kind, f); + fputs("-", f); + fputs(table[i].name, f); + + mask &= ~table[i].mask; + } + } + + assert(mask == 0); +} + +void unit_dump(Unit *u, FILE *f, const char *prefix) { + char *t, **j; + UnitDependency d; + Iterator i; + const char *prefix2; + char timestamp[5][FORMAT_TIMESTAMP_MAX], timespan[FORMAT_TIMESPAN_MAX]; + Unit *following; + _cleanup_set_free_ Set *following_set = NULL; + const char *n; + CGroupMask m; + int r; + + assert(u); + assert(u->type >= 0); + + prefix = strempty(prefix); + prefix2 = strjoina(prefix, "\t"); + + fprintf(f, + "%s-> Unit %s:\n", + prefix, u->id); + + SET_FOREACH(t, u->names, i) + if (!streq(t, u->id)) + fprintf(f, "%s\tAlias: %s\n", prefix, t); + + fprintf(f, + "%s\tDescription: %s\n" + "%s\tInstance: %s\n" + "%s\tUnit Load State: %s\n" + "%s\tUnit Active State: %s\n" + "%s\tState Change Timestamp: %s\n" + "%s\tInactive Exit Timestamp: %s\n" + "%s\tActive Enter Timestamp: %s\n" + "%s\tActive Exit Timestamp: %s\n" + "%s\tInactive Enter Timestamp: %s\n" + "%s\tMay GC: %s\n" + "%s\tNeed Daemon Reload: %s\n" + "%s\tTransient: %s\n" + "%s\tPerpetual: %s\n" + "%s\tGarbage Collection Mode: %s\n" + "%s\tSlice: %s\n" + "%s\tCGroup: %s\n" + "%s\tCGroup realized: %s\n", + prefix, unit_description(u), + prefix, strna(u->instance), + prefix, unit_load_state_to_string(u->load_state), + prefix, unit_active_state_to_string(unit_active_state(u)), + prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->state_change_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[1], sizeof(timestamp[1]), u->inactive_exit_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[2], sizeof(timestamp[2]), u->active_enter_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[3], sizeof(timestamp[3]), u->active_exit_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[4], sizeof(timestamp[4]), u->inactive_enter_timestamp.realtime)), + prefix, yes_no(unit_may_gc(u)), + prefix, yes_no(unit_need_daemon_reload(u)), + prefix, yes_no(u->transient), + prefix, yes_no(u->perpetual), + prefix, collect_mode_to_string(u->collect_mode), + prefix, strna(unit_slice_name(u)), + prefix, strna(u->cgroup_path), + prefix, yes_no(u->cgroup_realized)); + + if (u->cgroup_realized_mask != 0) { + _cleanup_free_ char *s = NULL; + (void) cg_mask_to_string(u->cgroup_realized_mask, &s); + fprintf(f, "%s\tCGroup realized mask: %s\n", prefix, strnull(s)); + } + + if (u->cgroup_enabled_mask != 0) { + _cleanup_free_ char *s = NULL; + (void) cg_mask_to_string(u->cgroup_enabled_mask, &s); + fprintf(f, "%s\tCGroup enabled mask: %s\n", prefix, strnull(s)); + } + + m = unit_get_own_mask(u); + if (m != 0) { + _cleanup_free_ char *s = NULL; + (void) cg_mask_to_string(m, &s); + fprintf(f, "%s\tCGroup own mask: %s\n", prefix, strnull(s)); + } + + m = unit_get_members_mask(u); + if (m != 0) { + _cleanup_free_ char *s = NULL; + (void) cg_mask_to_string(m, &s); + fprintf(f, "%s\tCGroup members mask: %s\n", prefix, strnull(s)); + } + + m = unit_get_delegate_mask(u); + if (m != 0) { + _cleanup_free_ char *s = NULL; + (void) cg_mask_to_string(m, &s); + fprintf(f, "%s\tCGroup delegate mask: %s\n", prefix, strnull(s)); + } + + if (!sd_id128_is_null(u->invocation_id)) + fprintf(f, "%s\tInvocation ID: " SD_ID128_FORMAT_STR "\n", + prefix, SD_ID128_FORMAT_VAL(u->invocation_id)); + + STRV_FOREACH(j, u->documentation) + fprintf(f, "%s\tDocumentation: %s\n", prefix, *j); + + following = unit_following(u); + if (following) + fprintf(f, "%s\tFollowing: %s\n", prefix, following->id); + + r = unit_following_set(u, &following_set); + if (r >= 0) { + Unit *other; + + SET_FOREACH(other, following_set, i) + fprintf(f, "%s\tFollowing Set Member: %s\n", prefix, other->id); + } + + if (u->fragment_path) + fprintf(f, "%s\tFragment Path: %s\n", prefix, u->fragment_path); + + if (u->source_path) + fprintf(f, "%s\tSource Path: %s\n", prefix, u->source_path); + + STRV_FOREACH(j, u->dropin_paths) + fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j); + + if (u->failure_action != EMERGENCY_ACTION_NONE) + fprintf(f, "%s\tFailure Action: %s\n", prefix, emergency_action_to_string(u->failure_action)); + if (u->failure_action_exit_status >= 0) + fprintf(f, "%s\tFailure Action Exit Status: %i\n", prefix, u->failure_action_exit_status); + if (u->success_action != EMERGENCY_ACTION_NONE) + fprintf(f, "%s\tSuccess Action: %s\n", prefix, emergency_action_to_string(u->success_action)); + if (u->success_action_exit_status >= 0) + fprintf(f, "%s\tSuccess Action Exit Status: %i\n", prefix, u->success_action_exit_status); + + if (u->job_timeout != USEC_INFINITY) + fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0)); + + if (u->job_timeout_action != EMERGENCY_ACTION_NONE) + fprintf(f, "%s\tJob Timeout Action: %s\n", prefix, emergency_action_to_string(u->job_timeout_action)); + + if (u->job_timeout_reboot_arg) + fprintf(f, "%s\tJob Timeout Reboot Argument: %s\n", prefix, u->job_timeout_reboot_arg); + + condition_dump_list(u->conditions, f, prefix, condition_type_to_string); + condition_dump_list(u->asserts, f, prefix, assert_type_to_string); + + if (dual_timestamp_is_set(&u->condition_timestamp)) + fprintf(f, + "%s\tCondition Timestamp: %s\n" + "%s\tCondition Result: %s\n", + prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->condition_timestamp.realtime)), + prefix, yes_no(u->condition_result)); + + if (dual_timestamp_is_set(&u->assert_timestamp)) + fprintf(f, + "%s\tAssert Timestamp: %s\n" + "%s\tAssert Result: %s\n", + prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->assert_timestamp.realtime)), + prefix, yes_no(u->assert_result)); + + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) { + UnitDependencyInfo di; + Unit *other; + + HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d], i) { + bool space = false; + + fprintf(f, "%s\t%s: %s (", prefix, unit_dependency_to_string(d), other->id); + + print_unit_dependency_mask(f, "origin", di.origin_mask, &space); + print_unit_dependency_mask(f, "destination", di.destination_mask, &space); + + fputs(")\n", f); + } + } + + if (!hashmap_isempty(u->requires_mounts_for)) { + UnitDependencyInfo di; + const char *path; + + HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for, i) { + bool space = false; + + fprintf(f, "%s\tRequiresMountsFor: %s (", prefix, path); + + print_unit_dependency_mask(f, "origin", di.origin_mask, &space); + print_unit_dependency_mask(f, "destination", di.destination_mask, &space); + + fputs(")\n", f); + } + } + + if (u->load_state == UNIT_LOADED) { + + fprintf(f, + "%s\tStopWhenUnneeded: %s\n" + "%s\tRefuseManualStart: %s\n" + "%s\tRefuseManualStop: %s\n" + "%s\tDefaultDependencies: %s\n" + "%s\tOnFailureJobMode: %s\n" + "%s\tIgnoreOnIsolate: %s\n", + prefix, yes_no(u->stop_when_unneeded), + prefix, yes_no(u->refuse_manual_start), + prefix, yes_no(u->refuse_manual_stop), + prefix, yes_no(u->default_dependencies), + prefix, job_mode_to_string(u->on_failure_job_mode), + prefix, yes_no(u->ignore_on_isolate)); + + if (UNIT_VTABLE(u)->dump) + UNIT_VTABLE(u)->dump(u, f, prefix2); + + } else if (u->load_state == UNIT_MERGED) + fprintf(f, + "%s\tMerged into: %s\n", + prefix, u->merged_into->id); + else if (u->load_state == UNIT_ERROR) + fprintf(f, "%s\tLoad Error Code: %s\n", prefix, strerror_safe(u->load_error)); + + for (n = sd_bus_track_first(u->bus_track); n; n = sd_bus_track_next(u->bus_track)) + fprintf(f, "%s\tBus Ref: %s\n", prefix, n); + + if (u->job) + job_dump(u->job, f, prefix2); + + if (u->nop_job) + job_dump(u->nop_job, f, prefix2); +} + +/* Common implementation for multiple backends */ +int unit_load_fragment_and_dropin(Unit *u, bool fragment_required) { + int r; + + assert(u); + + /* Load a .{service,socket,...} file */ + r = unit_load_fragment(u); + if (r < 0) + return r; + + if (u->load_state == UNIT_STUB) { + if (fragment_required) + return -ENOENT; + + u->load_state = UNIT_LOADED; + } + + /* Load drop-in directory data. If u is an alias, we might be reloading the + * target unit needlessly. But we cannot be sure which drops-ins have already + * been loaded and which not, at least without doing complicated book-keeping, + * so let's always reread all drop-ins. */ + return unit_load_dropin(unit_follow_merge(u)); +} + +void unit_add_to_target_deps_queue(Unit *u) { + Manager *m = u->manager; + + assert(u); + + if (u->in_target_deps_queue) + return; + + LIST_PREPEND(target_deps_queue, m->target_deps_queue, u); + u->in_target_deps_queue = true; +} + +int unit_add_default_target_dependency(Unit *u, Unit *target) { + assert(u); + assert(target); + + if (target->type != UNIT_TARGET) + return 0; + + /* Only add the dependency if both units are loaded, so that + * that loop check below is reliable */ + if (u->load_state != UNIT_LOADED || + target->load_state != UNIT_LOADED) + return 0; + + /* If either side wants no automatic dependencies, then let's + * skip this */ + if (!u->default_dependencies || + !target->default_dependencies) + return 0; + + /* Don't create loops */ + if (hashmap_get(target->dependencies[UNIT_BEFORE], u)) + return 0; + + return unit_add_dependency(target, UNIT_AFTER, u, true, UNIT_DEPENDENCY_DEFAULT); +} + +static int unit_add_slice_dependencies(Unit *u) { + UnitDependencyMask mask; + assert(u); + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return 0; + + /* Slice units are implicitly ordered against their parent slices (as this relationship is encoded in the + name), while all other units are ordered based on configuration (as in their case Slice= configures the + relationship). */ + mask = u->type == UNIT_SLICE ? UNIT_DEPENDENCY_IMPLICIT : UNIT_DEPENDENCY_FILE; + + if (UNIT_ISSET(u->slice)) + return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT_DEREF(u->slice), true, mask); + + if (unit_has_name(u, SPECIAL_ROOT_SLICE)) + return 0; + + return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_ROOT_SLICE, true, mask); +} + +static int unit_add_mount_dependencies(Unit *u) { + UnitDependencyInfo di; + const char *path; + Iterator i; + int r; + + assert(u); + + HASHMAP_FOREACH_KEY(di.data, path, u->requires_mounts_for, i) { + char prefix[strlen(path) + 1]; + + PATH_FOREACH_PREFIX_MORE(prefix, path) { + _cleanup_free_ char *p = NULL; + Unit *m; + + r = unit_name_from_path(prefix, ".mount", &p); + if (r < 0) + return r; + + m = manager_get_unit(u->manager, p); + if (!m) { + /* Make sure to load the mount unit if + * it exists. If so the dependencies + * on this unit will be added later + * during the loading of the mount + * unit. */ + (void) manager_load_unit_prepare(u->manager, p, NULL, NULL, &m); + continue; + } + if (m == u) + continue; + + if (m->load_state != UNIT_LOADED) + continue; + + r = unit_add_dependency(u, UNIT_AFTER, m, true, di.origin_mask); + if (r < 0) + return r; + + if (m->fragment_path) { + r = unit_add_dependency(u, UNIT_REQUIRES, m, true, di.origin_mask); + if (r < 0) + return r; + } + } + } + + return 0; +} + +static int unit_add_startup_units(Unit *u) { + CGroupContext *c; + int r; + + c = unit_get_cgroup_context(u); + if (!c) + return 0; + + if (c->startup_cpu_shares == CGROUP_CPU_SHARES_INVALID && + c->startup_io_weight == CGROUP_WEIGHT_INVALID && + c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID) + return 0; + + r = set_ensure_allocated(&u->manager->startup_units, NULL); + if (r < 0) + return r; + + return set_put(u->manager->startup_units, u); +} + +int unit_load(Unit *u) { + int r; + + assert(u); + + if (u->in_load_queue) { + LIST_REMOVE(load_queue, u->manager->load_queue, u); + u->in_load_queue = false; + } + + if (u->type == _UNIT_TYPE_INVALID) + return -EINVAL; + + if (u->load_state != UNIT_STUB) + return 0; + + if (u->transient_file) { + /* Finalize transient file: if this is a transient unit file, as soon as we reach unit_load() the setup + * is complete, hence let's synchronize the unit file we just wrote to disk. */ + + r = fflush_and_check(u->transient_file); + if (r < 0) + goto fail; + + u->transient_file = safe_fclose(u->transient_file); + u->fragment_mtime = now(CLOCK_REALTIME); + } + + r = UNIT_VTABLE(u)->load(u); + if (r < 0) + goto fail; + + assert(u->load_state != UNIT_STUB); + + if (u->load_state == UNIT_LOADED) { + unit_add_to_target_deps_queue(u); + + r = unit_add_slice_dependencies(u); + if (r < 0) + goto fail; + + r = unit_add_mount_dependencies(u); + if (r < 0) + goto fail; + + r = unit_add_startup_units(u); + if (r < 0) + goto fail; + + if (u->on_failure_job_mode == JOB_ISOLATE && hashmap_size(u->dependencies[UNIT_ON_FAILURE]) > 1) { + log_unit_error(u, "More than one OnFailure= dependencies specified but OnFailureJobMode=isolate set. Refusing."); + r = -ENOEXEC; + goto fail; + } + + if (u->job_running_timeout != USEC_INFINITY && u->job_running_timeout > u->job_timeout) + log_unit_warning(u, "JobRunningTimeoutSec= is greater than JobTimeoutSec=, it has no effect."); + + /* We finished loading, let's ensure our parents recalculate the members mask */ + unit_invalidate_cgroup_members_masks(u); + } + + assert((u->load_state != UNIT_MERGED) == !u->merged_into); + + unit_add_to_dbus_queue(unit_follow_merge(u)); + unit_add_to_gc_queue(u); + + return 0; + +fail: + /* We convert ENOEXEC errors to the UNIT_BAD_SETTING load state here. Configuration parsing code should hence + * return ENOEXEC to ensure units are placed in this state after loading */ + + u->load_state = u->load_state == UNIT_STUB ? UNIT_NOT_FOUND : + r == -ENOEXEC ? UNIT_BAD_SETTING : + UNIT_ERROR; + u->load_error = r; + + unit_add_to_dbus_queue(u); + unit_add_to_gc_queue(u); + + return log_unit_debug_errno(u, r, "Failed to load configuration: %m"); +} + +_printf_(7, 8) +static int log_unit_internal(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) { + Unit *u = userdata; + va_list ap; + int r; + + va_start(ap, format); + if (u) + r = log_object_internalv(level, error, file, line, func, + u->manager->unit_log_field, + u->id, + u->manager->invocation_log_field, + u->invocation_id_string, + format, ap); + else + r = log_internalv(level, error, file, line, func, format, ap); + va_end(ap); + + return r; +} + +static bool unit_test_condition(Unit *u) { + assert(u); + + dual_timestamp_get(&u->condition_timestamp); + u->condition_result = condition_test_list(u->conditions, condition_type_to_string, log_unit_internal, u); + + unit_add_to_dbus_queue(u); + + return u->condition_result; +} + +static bool unit_test_assert(Unit *u) { + assert(u); + + dual_timestamp_get(&u->assert_timestamp); + u->assert_result = condition_test_list(u->asserts, assert_type_to_string, log_unit_internal, u); + + unit_add_to_dbus_queue(u); + + return u->assert_result; +} + +void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) { + const char *d; + + d = unit_status_string(u); + if (log_get_show_color()) + d = strjoina(ANSI_HIGHLIGHT, d, ANSI_NORMAL); + + DISABLE_WARNING_FORMAT_NONLITERAL; + manager_status_printf(u->manager, STATUS_TYPE_NORMAL, status, unit_status_msg_format, d); + REENABLE_WARNING; +} + +int unit_test_start_limit(Unit *u) { + const char *reason; + + assert(u); + + if (ratelimit_below(&u->start_ratelimit)) { + u->start_limit_hit = false; + return 0; + } + + log_unit_warning(u, "Start request repeated too quickly."); + u->start_limit_hit = true; + + reason = strjoina("unit ", u->id, " failed"); + + emergency_action(u->manager, u->start_limit_action, + EMERGENCY_ACTION_IS_WATCHDOG|EMERGENCY_ACTION_WARN, + u->reboot_arg, -1, reason); + + return -ECANCELED; +} + +bool unit_shall_confirm_spawn(Unit *u) { + assert(u); + + if (manager_is_confirm_spawn_disabled(u->manager)) + return false; + + /* For some reasons units remaining in the same process group + * as PID 1 fail to acquire the console even if it's not used + * by any process. So skip the confirmation question for them. */ + return !unit_get_exec_context(u)->same_pgrp; +} + +static bool unit_verify_deps(Unit *u) { + Unit *other; + Iterator j; + void *v; + + assert(u); + + /* Checks whether all BindsTo= dependencies of this unit are fulfilled — if they are also combined with + * After=. We do not check Requires= or Requisite= here as they only should have an effect on the job + * processing, but do not have any effect afterwards. We don't check BindsTo= dependencies that are not used in + * conjunction with After= as for them any such check would make things entirely racy. */ + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], j) { + + if (!hashmap_contains(u->dependencies[UNIT_AFTER], other)) + continue; + + if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(other))) { + log_unit_notice(u, "Bound to unit %s, but unit isn't active.", other->id); + return false; + } + } + + return true; +} + +/* Errors that aren't really errors: + * -EALREADY: Unit is already started. + * -ECOMM: Condition failed + * -EAGAIN: An operation is already in progress. Retry later. + * + * Errors that are real errors: + * -EBADR: This unit type does not support starting. + * -ECANCELED: Start limit hit, too many requests for now + * -EPROTO: Assert failed + * -EINVAL: Unit not loaded + * -EOPNOTSUPP: Unit type not supported + * -ENOLINK: The necessary dependencies are not fulfilled. + * -ESTALE: This unit has been started before and can't be started a second time + * -ENOENT: This is a triggering unit and unit to trigger is not loaded + */ +int unit_start(Unit *u) { + UnitActiveState state; + Unit *following; + + assert(u); + + /* If this is already started, then this will succeed. Note that this will even succeed if this unit + * is not startable by the user. This is relied on to detect when we need to wait for units and when + * waiting is finished. */ + state = unit_active_state(u); + if (UNIT_IS_ACTIVE_OR_RELOADING(state)) + return -EALREADY; + if (state == UNIT_MAINTENANCE) + return -EAGAIN; + + /* Units that aren't loaded cannot be started */ + if (u->load_state != UNIT_LOADED) + return -EINVAL; + + /* Refuse starting scope units more than once */ + if (UNIT_VTABLE(u)->once_only && dual_timestamp_is_set(&u->inactive_enter_timestamp)) + return -ESTALE; + + /* If the conditions failed, don't do anything at all. If we already are activating this call might + * still be useful to speed up activation in case there is some hold-off time, but we don't want to + * recheck the condition in that case. */ + if (state != UNIT_ACTIVATING && + !unit_test_condition(u)) + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(ECOMM), "Starting requested but condition failed. Not starting unit."); + + /* If the asserts failed, fail the entire job */ + if (state != UNIT_ACTIVATING && + !unit_test_assert(u)) + return log_unit_notice_errno(u, SYNTHETIC_ERRNO(EPROTO), "Starting requested but asserts failed."); + + /* Units of types that aren't supported cannot be started. Note that we do this test only after the + * condition checks, so that we rather return condition check errors (which are usually not + * considered a true failure) than "not supported" errors (which are considered a failure). + */ + if (!unit_type_supported(u->type)) + return -EOPNOTSUPP; + + /* Let's make sure that the deps really are in order before we start this. Normally the job engine + * should have taken care of this already, but let's check this here again. After all, our + * dependencies might not be in effect anymore, due to a reload or due to a failed condition. */ + if (!unit_verify_deps(u)) + return -ENOLINK; + + /* Forward to the main object, if we aren't it. */ + following = unit_following(u); + if (following) { + log_unit_debug(u, "Redirecting start request from %s to %s.", u->id, following->id); + return unit_start(following); + } + + /* If it is stopped, but we cannot start it, then fail */ + if (!UNIT_VTABLE(u)->start) + return -EBADR; + + /* We don't suppress calls to ->start() here when we are already starting, to allow this request to + * be used as a "hurry up" call, for example when the unit is in some "auto restart" state where it + * waits for a holdoff timer to elapse before it will start again. */ + + unit_add_to_dbus_queue(u); + + return UNIT_VTABLE(u)->start(u); +} + +bool unit_can_start(Unit *u) { + assert(u); + + if (u->load_state != UNIT_LOADED) + return false; + + if (!unit_type_supported(u->type)) + return false; + + /* Scope units may be started only once */ + if (UNIT_VTABLE(u)->once_only && dual_timestamp_is_set(&u->inactive_exit_timestamp)) + return false; + + return !!UNIT_VTABLE(u)->start; +} + +bool unit_can_isolate(Unit *u) { + assert(u); + + return unit_can_start(u) && + u->allow_isolate; +} + +/* Errors: + * -EBADR: This unit type does not support stopping. + * -EALREADY: Unit is already stopped. + * -EAGAIN: An operation is already in progress. Retry later. + */ +int unit_stop(Unit *u) { + UnitActiveState state; + Unit *following; + + assert(u); + + state = unit_active_state(u); + if (UNIT_IS_INACTIVE_OR_FAILED(state)) + return -EALREADY; + + following = unit_following(u); + if (following) { + log_unit_debug(u, "Redirecting stop request from %s to %s.", u->id, following->id); + return unit_stop(following); + } + + if (!UNIT_VTABLE(u)->stop) + return -EBADR; + + unit_add_to_dbus_queue(u); + + return UNIT_VTABLE(u)->stop(u); +} + +bool unit_can_stop(Unit *u) { + assert(u); + + if (!unit_type_supported(u->type)) + return false; + + if (u->perpetual) + return false; + + return !!UNIT_VTABLE(u)->stop; +} + +/* Errors: + * -EBADR: This unit type does not support reloading. + * -ENOEXEC: Unit is not started. + * -EAGAIN: An operation is already in progress. Retry later. + */ +int unit_reload(Unit *u) { + UnitActiveState state; + Unit *following; + + assert(u); + + if (u->load_state != UNIT_LOADED) + return -EINVAL; + + if (!unit_can_reload(u)) + return -EBADR; + + state = unit_active_state(u); + if (state == UNIT_RELOADING) + return -EAGAIN; + + if (state != UNIT_ACTIVE) { + log_unit_warning(u, "Unit cannot be reloaded because it is inactive."); + return -ENOEXEC; + } + + following = unit_following(u); + if (following) { + log_unit_debug(u, "Redirecting reload request from %s to %s.", u->id, following->id); + return unit_reload(following); + } + + unit_add_to_dbus_queue(u); + + if (!UNIT_VTABLE(u)->reload) { + /* Unit doesn't have a reload function, but we need to propagate the reload anyway */ + unit_notify(u, unit_active_state(u), unit_active_state(u), 0); + return 0; + } + + return UNIT_VTABLE(u)->reload(u); +} + +bool unit_can_reload(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->can_reload) + return UNIT_VTABLE(u)->can_reload(u); + + if (!hashmap_isempty(u->dependencies[UNIT_PROPAGATES_RELOAD_TO])) + return true; + + return UNIT_VTABLE(u)->reload; +} + +bool unit_is_unneeded(Unit *u) { + static const UnitDependency deps[] = { + UNIT_REQUIRED_BY, + UNIT_REQUISITE_OF, + UNIT_WANTED_BY, + UNIT_BOUND_BY, + }; + size_t j; + + assert(u); + + if (!u->stop_when_unneeded) + return false; + + /* Don't clean up while the unit is transitioning or is even inactive. */ + if (!UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) + return false; + if (u->job) + return false; + + for (j = 0; j < ELEMENTSOF(deps); j++) { + Unit *other; + Iterator i; + void *v; + + /* If a dependent unit has a job queued, is active or transitioning, or is marked for + * restart, then don't clean this one up. */ + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]], i) { + if (other->job) + return false; + + if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) + return false; + + if (unit_will_restart(other)) + return false; + } + } + + return true; +} + +static void check_unneeded_dependencies(Unit *u) { + + static const UnitDependency deps[] = { + UNIT_REQUIRES, + UNIT_REQUISITE, + UNIT_WANTS, + UNIT_BINDS_TO, + }; + size_t j; + + assert(u); + + /* Add all units this unit depends on to the queue that processes StopWhenUnneeded= behaviour. */ + + for (j = 0; j < ELEMENTSOF(deps); j++) { + Unit *other; + Iterator i; + void *v; + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[deps[j]], i) + unit_submit_to_stop_when_unneeded_queue(other); + } +} + +static void unit_check_binds_to(Unit *u) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + bool stop = false; + Unit *other; + Iterator i; + void *v; + int r; + + assert(u); + + if (u->job) + return; + + if (unit_active_state(u) != UNIT_ACTIVE) + return; + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], i) { + if (other->job) + continue; + + if (!other->coldplugged) + /* We might yet create a job for the other unit… */ + continue; + + if (!UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) + continue; + + stop = true; + break; + } + + if (!stop) + return; + + /* If stopping a unit fails continuously we might enter a stop + * loop here, hence stop acting on the service being + * unnecessary after a while. */ + if (!ratelimit_below(&u->auto_stop_ratelimit)) { + log_unit_warning(u, "Unit is bound to inactive unit %s, but not stopping since we tried this too often recently.", other->id); + return; + } + + assert(other); + log_unit_info(u, "Unit is bound to inactive unit %s. Stopping, too.", other->id); + + /* A unit we need to run is gone. Sniff. Let's stop this. */ + r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, NULL, &error, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r)); +} + +static void retroactively_start_dependencies(Unit *u) { + Iterator i; + Unit *other; + void *v; + + assert(u); + assert(UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))); + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_REQUIRES], i) + if (!hashmap_get(u->dependencies[UNIT_AFTER], other) && + !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) + manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL, NULL); + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BINDS_TO], i) + if (!hashmap_get(u->dependencies[UNIT_AFTER], other) && + !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) + manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL, NULL); + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_WANTS], i) + if (!hashmap_get(u->dependencies[UNIT_AFTER], other) && + !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) + manager_add_job(u->manager, JOB_START, other, JOB_FAIL, NULL, NULL, NULL); + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_CONFLICTS], i) + if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) + manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL); + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_CONFLICTED_BY], i) + if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) + manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL); +} + +static void retroactively_stop_dependencies(Unit *u) { + Unit *other; + Iterator i; + void *v; + + assert(u); + assert(UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))); + + /* Pull down units which are bound to us recursively if enabled */ + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BOUND_BY], i) + if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other))) + manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL); +} + +void unit_start_on_failure(Unit *u) { + Unit *other; + Iterator i; + void *v; + int r; + + assert(u); + + if (hashmap_size(u->dependencies[UNIT_ON_FAILURE]) <= 0) + return; + + log_unit_info(u, "Triggering OnFailure= dependencies."); + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_ON_FAILURE], i) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, NULL, &error, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to enqueue OnFailure= job, ignoring: %s", bus_error_message(&error, r)); + } +} + +void unit_trigger_notify(Unit *u) { + Unit *other; + Iterator i; + void *v; + + assert(u); + + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_TRIGGERED_BY], i) + if (UNIT_VTABLE(other)->trigger_notify) + UNIT_VTABLE(other)->trigger_notify(other, u); +} + +static int raise_level(int log_level, bool condition_info, bool condition_notice) { + if (condition_notice && log_level > LOG_NOTICE) + return LOG_NOTICE; + if (condition_info && log_level > LOG_INFO) + return LOG_INFO; + return log_level; +} + +static int unit_log_resources(Unit *u) { + struct iovec iovec[1 + _CGROUP_IP_ACCOUNTING_METRIC_MAX + _CGROUP_IO_ACCOUNTING_METRIC_MAX + 4]; + bool any_traffic = false, have_ip_accounting = false, any_io = false, have_io_accounting = false; + _cleanup_free_ char *igress = NULL, *egress = NULL, *rr = NULL, *wr = NULL; + int log_level = LOG_DEBUG; /* May be raised if resources consumed over a treshold */ + size_t n_message_parts = 0, n_iovec = 0; + char* message_parts[1 + 2 + 2 + 1], *t; + nsec_t nsec = NSEC_INFINITY; + CGroupIPAccountingMetric m; + size_t i; + int r; + const char* const ip_fields[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = { + [CGROUP_IP_INGRESS_BYTES] = "IP_METRIC_INGRESS_BYTES", + [CGROUP_IP_INGRESS_PACKETS] = "IP_METRIC_INGRESS_PACKETS", + [CGROUP_IP_EGRESS_BYTES] = "IP_METRIC_EGRESS_BYTES", + [CGROUP_IP_EGRESS_PACKETS] = "IP_METRIC_EGRESS_PACKETS", + }; + const char* const io_fields[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = { + [CGROUP_IO_READ_BYTES] = "IO_METRIC_READ_BYTES", + [CGROUP_IO_WRITE_BYTES] = "IO_METRIC_WRITE_BYTES", + [CGROUP_IO_READ_OPERATIONS] = "IO_METRIC_READ_OPERATIONS", + [CGROUP_IO_WRITE_OPERATIONS] = "IO_METRIC_WRITE_OPERATIONS", + }; + + assert(u); + + /* Invoked whenever a unit enters failed or dead state. Logs information about consumed resources if resource + * accounting was enabled for a unit. It does this in two ways: a friendly human readable string with reduced + * information and the complete data in structured fields. */ + + (void) unit_get_cpu_usage(u, &nsec); + if (nsec != NSEC_INFINITY) { + char buf[FORMAT_TIMESPAN_MAX] = ""; + + /* Format the CPU time for inclusion in the structured log message */ + if (asprintf(&t, "CPU_USAGE_NSEC=%" PRIu64, nsec) < 0) { + r = log_oom(); + goto finish; + } + iovec[n_iovec++] = IOVEC_MAKE_STRING(t); + + /* Format the CPU time for inclusion in the human language message string */ + format_timespan(buf, sizeof(buf), nsec / NSEC_PER_USEC, USEC_PER_MSEC); + t = strjoin("consumed ", buf, " CPU time"); + if (!t) { + r = log_oom(); + goto finish; + } + + message_parts[n_message_parts++] = t; + + log_level = raise_level(log_level, + nsec > NOTICEWORTHY_CPU_NSEC, + nsec > MENTIONWORTHY_CPU_NSEC); + } + + for (CGroupIOAccountingMetric k = 0; k < _CGROUP_IO_ACCOUNTING_METRIC_MAX; k++) { + char buf[FORMAT_BYTES_MAX] = ""; + uint64_t value = UINT64_MAX; + + assert(io_fields[k]); + + (void) unit_get_io_accounting(u, k, k > 0, &value); + if (value == UINT64_MAX) + continue; + + have_io_accounting = true; + if (value > 0) + any_io = true; + + /* Format IO accounting data for inclusion in the structured log message */ + if (asprintf(&t, "%s=%" PRIu64, io_fields[k], value) < 0) { + r = log_oom(); + goto finish; + } + iovec[n_iovec++] = IOVEC_MAKE_STRING(t); + + /* Format the IO accounting data for inclusion in the human language message string, but only + * for the bytes counters (and not for the operations counters) */ + if (k == CGROUP_IO_READ_BYTES) { + assert(!rr); + rr = strjoin("read ", format_bytes(buf, sizeof(buf), value), " from disk"); + if (!rr) { + r = log_oom(); + goto finish; + } + } else if (k == CGROUP_IO_WRITE_BYTES) { + assert(!wr); + wr = strjoin("written ", format_bytes(buf, sizeof(buf), value), " to disk"); + if (!wr) { + r = log_oom(); + goto finish; + } + } + + if (IN_SET(k, CGROUP_IO_READ_BYTES, CGROUP_IO_WRITE_BYTES)) + log_level = raise_level(log_level, + value > MENTIONWORTHY_IO_BYTES, + value > NOTICEWORTHY_IO_BYTES); + } + + if (have_io_accounting) { + if (any_io) { + if (rr) + message_parts[n_message_parts++] = TAKE_PTR(rr); + if (wr) + message_parts[n_message_parts++] = TAKE_PTR(wr); + + } else { + char *k; + + k = strdup("no IO"); + if (!k) { + r = log_oom(); + goto finish; + } + + message_parts[n_message_parts++] = k; + } + } + + for (m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) { + char buf[FORMAT_BYTES_MAX] = ""; + uint64_t value = UINT64_MAX; + + assert(ip_fields[m]); + + (void) unit_get_ip_accounting(u, m, &value); + if (value == UINT64_MAX) + continue; + + have_ip_accounting = true; + if (value > 0) + any_traffic = true; + + /* Format IP accounting data for inclusion in the structured log message */ + if (asprintf(&t, "%s=%" PRIu64, ip_fields[m], value) < 0) { + r = log_oom(); + goto finish; + } + iovec[n_iovec++] = IOVEC_MAKE_STRING(t); + + /* Format the IP accounting data for inclusion in the human language message string, but only for the + * bytes counters (and not for the packets counters) */ + if (m == CGROUP_IP_INGRESS_BYTES) { + assert(!igress); + igress = strjoin("received ", format_bytes(buf, sizeof(buf), value), " IP traffic"); + if (!igress) { + r = log_oom(); + goto finish; + } + } else if (m == CGROUP_IP_EGRESS_BYTES) { + assert(!egress); + egress = strjoin("sent ", format_bytes(buf, sizeof(buf), value), " IP traffic"); + if (!egress) { + r = log_oom(); + goto finish; + } + } + + if (IN_SET(m, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_EGRESS_BYTES)) + log_level = raise_level(log_level, + value > MENTIONWORTHY_IP_BYTES, + value > NOTICEWORTHY_IP_BYTES); + } + + if (have_ip_accounting) { + if (any_traffic) { + if (igress) + message_parts[n_message_parts++] = TAKE_PTR(igress); + if (egress) + message_parts[n_message_parts++] = TAKE_PTR(egress); + + } else { + char *k; + + k = strdup("no IP traffic"); + if (!k) { + r = log_oom(); + goto finish; + } + + message_parts[n_message_parts++] = k; + } + } + + /* Is there any accounting data available at all? */ + if (n_iovec == 0) { + r = 0; + goto finish; + } + + if (n_message_parts == 0) + t = strjoina("MESSAGE=", u->id, ": Completed."); + else { + _cleanup_free_ char *joined; + + message_parts[n_message_parts] = NULL; + + joined = strv_join(message_parts, ", "); + if (!joined) { + r = log_oom(); + goto finish; + } + + joined[0] = ascii_toupper(joined[0]); + t = strjoina("MESSAGE=", u->id, ": ", joined, "."); + } + + /* The following four fields we allocate on the stack or are static strings, we hence don't want to free them, + * and hence don't increase n_iovec for them */ + iovec[n_iovec] = IOVEC_MAKE_STRING(t); + iovec[n_iovec + 1] = IOVEC_MAKE_STRING("MESSAGE_ID=" SD_MESSAGE_UNIT_RESOURCES_STR); + + t = strjoina(u->manager->unit_log_field, u->id); + iovec[n_iovec + 2] = IOVEC_MAKE_STRING(t); + + t = strjoina(u->manager->invocation_log_field, u->invocation_id_string); + iovec[n_iovec + 3] = IOVEC_MAKE_STRING(t); + + log_struct_iovec(log_level, iovec, n_iovec + 4); + r = 0; + +finish: + for (i = 0; i < n_message_parts; i++) + free(message_parts[i]); + + for (i = 0; i < n_iovec; i++) + free(iovec[i].iov_base); + + return r; + +} + +static void unit_update_on_console(Unit *u) { + bool b; + + assert(u); + + b = unit_needs_console(u); + if (u->on_console == b) + return; + + u->on_console = b; + if (b) + manager_ref_console(u->manager); + else + manager_unref_console(u->manager); +} + +static void unit_emit_audit_start(Unit *u) { + assert(u); + + if (u->type != UNIT_SERVICE) + return; + + /* Write audit record if we have just finished starting up */ + manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_START, true); + u->in_audit = true; +} + +static void unit_emit_audit_stop(Unit *u, UnitActiveState state) { + assert(u); + + if (u->type != UNIT_SERVICE) + return; + + if (u->in_audit) { + /* Write audit record if we have just finished shutting down */ + manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_STOP, state == UNIT_INACTIVE); + u->in_audit = false; + } else { + /* Hmm, if there was no start record written write it now, so that we always have a nice pair */ + manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_START, state == UNIT_INACTIVE); + + if (state == UNIT_INACTIVE) + manager_send_unit_audit(u->manager, u, AUDIT_SERVICE_STOP, true); + } +} + +static bool unit_process_job(Job *j, UnitActiveState ns, UnitNotifyFlags flags) { + bool unexpected = false; + JobResult result; + + assert(j); + + if (j->state == JOB_WAITING) + + /* So we reached a different state for this job. Let's see if we can run it now if it failed previously + * due to EAGAIN. */ + job_add_to_run_queue(j); + + /* Let's check whether the unit's new state constitutes a finished job, or maybe contradicts a running job and + * hence needs to invalidate jobs. */ + + switch (j->type) { + + case JOB_START: + case JOB_VERIFY_ACTIVE: + + if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) + job_finish_and_invalidate(j, JOB_DONE, true, false); + else if (j->state == JOB_RUNNING && ns != UNIT_ACTIVATING) { + unexpected = true; + + if (UNIT_IS_INACTIVE_OR_FAILED(ns)) { + if (ns == UNIT_FAILED) + result = JOB_FAILED; + else if (FLAGS_SET(flags, UNIT_NOTIFY_SKIP_CONDITION)) + result = JOB_SKIPPED; + else + result = JOB_DONE; + + job_finish_and_invalidate(j, result, true, false); + } + } + + break; + + case JOB_RELOAD: + case JOB_RELOAD_OR_START: + case JOB_TRY_RELOAD: + + if (j->state == JOB_RUNNING) { + if (ns == UNIT_ACTIVE) + job_finish_and_invalidate(j, (flags & UNIT_NOTIFY_RELOAD_FAILURE) ? JOB_FAILED : JOB_DONE, true, false); + else if (!IN_SET(ns, UNIT_ACTIVATING, UNIT_RELOADING)) { + unexpected = true; + + if (UNIT_IS_INACTIVE_OR_FAILED(ns)) + job_finish_and_invalidate(j, ns == UNIT_FAILED ? JOB_FAILED : JOB_DONE, true, false); + } + } + + break; + + case JOB_STOP: + case JOB_RESTART: + case JOB_TRY_RESTART: + + if (UNIT_IS_INACTIVE_OR_FAILED(ns)) + job_finish_and_invalidate(j, JOB_DONE, true, false); + else if (j->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) { + unexpected = true; + job_finish_and_invalidate(j, JOB_FAILED, true, false); + } + + break; + + default: + assert_not_reached("Job type unknown"); + } + + return unexpected; +} + +void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags) { + const char *reason; + Manager *m; + + assert(u); + assert(os < _UNIT_ACTIVE_STATE_MAX); + assert(ns < _UNIT_ACTIVE_STATE_MAX); + + /* Note that this is called for all low-level state changes, even if they might map to the same high-level + * UnitActiveState! That means that ns == os is an expected behavior here. For example: if a mount point is + * remounted this function will be called too! */ + + m = u->manager; + + /* Let's enqueue the change signal early. In case this unit has a job associated we want that this unit is in + * the bus queue, so that any job change signal queued will force out the unit change signal first. */ + unit_add_to_dbus_queue(u); + + /* Update timestamps for state changes */ + if (!MANAGER_IS_RELOADING(m)) { + dual_timestamp_get(&u->state_change_timestamp); + + if (UNIT_IS_INACTIVE_OR_FAILED(os) && !UNIT_IS_INACTIVE_OR_FAILED(ns)) + u->inactive_exit_timestamp = u->state_change_timestamp; + else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_INACTIVE_OR_FAILED(ns)) + u->inactive_enter_timestamp = u->state_change_timestamp; + + if (!UNIT_IS_ACTIVE_OR_RELOADING(os) && UNIT_IS_ACTIVE_OR_RELOADING(ns)) + u->active_enter_timestamp = u->state_change_timestamp; + else if (UNIT_IS_ACTIVE_OR_RELOADING(os) && !UNIT_IS_ACTIVE_OR_RELOADING(ns)) + u->active_exit_timestamp = u->state_change_timestamp; + } + + /* Keep track of failed units */ + (void) manager_update_failed_units(m, u, ns == UNIT_FAILED); + + /* Make sure the cgroup and state files are always removed when we become inactive */ + if (UNIT_IS_INACTIVE_OR_FAILED(ns)) { + unit_prune_cgroup(u); + unit_unlink_state_files(u); + } + + unit_update_on_console(u); + + if (!MANAGER_IS_RELOADING(m)) { + bool unexpected; + + /* Let's propagate state changes to the job */ + if (u->job) + unexpected = unit_process_job(u->job, ns, flags); + else + unexpected = true; + + /* If this state change happened without being requested by a job, then let's retroactively start or + * stop dependencies. We skip that step when deserializing, since we don't want to create any + * additional jobs just because something is already activated. */ + + if (unexpected) { + if (UNIT_IS_INACTIVE_OR_FAILED(os) && UNIT_IS_ACTIVE_OR_ACTIVATING(ns)) + retroactively_start_dependencies(u); + else if (UNIT_IS_ACTIVE_OR_ACTIVATING(os) && UNIT_IS_INACTIVE_OR_DEACTIVATING(ns)) + retroactively_stop_dependencies(u); + } + + /* stop unneeded units regardless if going down was expected or not */ + if (UNIT_IS_INACTIVE_OR_FAILED(ns)) + check_unneeded_dependencies(u); + + if (ns != os && ns == UNIT_FAILED) { + log_unit_debug(u, "Unit entered failed state."); + + if (!(flags & UNIT_NOTIFY_WILL_AUTO_RESTART)) + unit_start_on_failure(u); + } + + if (UNIT_IS_ACTIVE_OR_RELOADING(ns) && !UNIT_IS_ACTIVE_OR_RELOADING(os)) { + /* This unit just finished starting up */ + + unit_emit_audit_start(u); + manager_send_unit_plymouth(m, u); + } + + if (UNIT_IS_INACTIVE_OR_FAILED(ns) && !UNIT_IS_INACTIVE_OR_FAILED(os)) { + /* This unit just stopped/failed. */ + + unit_emit_audit_stop(u, ns); + unit_log_resources(u); + } + } + + manager_recheck_journal(m); + manager_recheck_dbus(m); + + unit_trigger_notify(u); + + if (!MANAGER_IS_RELOADING(m)) { + /* Maybe we finished startup and are now ready for being stopped because unneeded? */ + unit_submit_to_stop_when_unneeded_queue(u); + + /* Maybe we finished startup, but something we needed has vanished? Let's die then. (This happens when + * something BindsTo= to a Type=oneshot unit, as these units go directly from starting to inactive, + * without ever entering started.) */ + unit_check_binds_to(u); + + if (os != UNIT_FAILED && ns == UNIT_FAILED) { + reason = strjoina("unit ", u->id, " failed"); + emergency_action(m, u->failure_action, 0, u->reboot_arg, unit_failure_action_exit_status(u), reason); + } else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && ns == UNIT_INACTIVE) { + reason = strjoina("unit ", u->id, " succeeded"); + emergency_action(m, u->success_action, 0, u->reboot_arg, unit_success_action_exit_status(u), reason); + } + } + + unit_add_to_gc_queue(u); +} + +int unit_watch_pid(Unit *u, pid_t pid, bool exclusive) { + int r; + + assert(u); + assert(pid_is_valid(pid)); + + /* Watch a specific PID */ + + /* Caller might be sure that this PID belongs to this unit only. Let's take this + * opportunity to remove any stalled references to this PID as they can be created + * easily (when watching a process which is not our direct child). */ + if (exclusive) + manager_unwatch_pid(u->manager, pid); + + r = set_ensure_allocated(&u->pids, NULL); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&u->manager->watch_pids, NULL); + if (r < 0) + return r; + + /* First try, let's add the unit keyed by "pid". */ + r = hashmap_put(u->manager->watch_pids, PID_TO_PTR(pid), u); + if (r == -EEXIST) { + Unit **array; + bool found = false; + size_t n = 0; + + /* OK, the "pid" key is already assigned to a different unit. Let's see if the "-pid" key (which points + * to an array of Units rather than just a Unit), lists us already. */ + + array = hashmap_get(u->manager->watch_pids, PID_TO_PTR(-pid)); + if (array) + for (; array[n]; n++) + if (array[n] == u) + found = true; + + if (found) /* Found it already? if so, do nothing */ + r = 0; + else { + Unit **new_array; + + /* Allocate a new array */ + new_array = new(Unit*, n + 2); + if (!new_array) + return -ENOMEM; + + memcpy_safe(new_array, array, sizeof(Unit*) * n); + new_array[n] = u; + new_array[n+1] = NULL; + + /* Add or replace the old array */ + r = hashmap_replace(u->manager->watch_pids, PID_TO_PTR(-pid), new_array); + if (r < 0) { + free(new_array); + return r; + } + + free(array); + } + } else if (r < 0) + return r; + + r = set_put(u->pids, PID_TO_PTR(pid)); + if (r < 0) + return r; + + return 0; +} + +void unit_unwatch_pid(Unit *u, pid_t pid) { + Unit **array; + + assert(u); + assert(pid_is_valid(pid)); + + /* First let's drop the unit in case it's keyed as "pid". */ + (void) hashmap_remove_value(u->manager->watch_pids, PID_TO_PTR(pid), u); + + /* Then, let's also drop the unit, in case it's in the array keyed by -pid */ + array = hashmap_get(u->manager->watch_pids, PID_TO_PTR(-pid)); + if (array) { + size_t n, m = 0; + + /* Let's iterate through the array, dropping our own entry */ + for (n = 0; array[n]; n++) + if (array[n] != u) + array[m++] = array[n]; + array[m] = NULL; + + if (m == 0) { + /* The array is now empty, remove the entire entry */ + assert(hashmap_remove(u->manager->watch_pids, PID_TO_PTR(-pid)) == array); + free(array); + } + } + + (void) set_remove(u->pids, PID_TO_PTR(pid)); +} + +void unit_unwatch_all_pids(Unit *u) { + assert(u); + + while (!set_isempty(u->pids)) + unit_unwatch_pid(u, PTR_TO_PID(set_first(u->pids))); + + u->pids = set_free(u->pids); +} + +static void unit_tidy_watch_pids(Unit *u) { + pid_t except1, except2; + Iterator i; + void *e; + + assert(u); + + /* Cleans dead PIDs from our list */ + + except1 = unit_main_pid(u); + except2 = unit_control_pid(u); + + SET_FOREACH(e, u->pids, i) { + pid_t pid = PTR_TO_PID(e); + + if (pid == except1 || pid == except2) + continue; + + if (!pid_is_unwaited(pid)) + unit_unwatch_pid(u, pid); + } +} + +static int on_rewatch_pids_event(sd_event_source *s, void *userdata) { + Unit *u = userdata; + + assert(s); + assert(u); + + unit_tidy_watch_pids(u); + unit_watch_all_pids(u); + + /* If the PID set is empty now, then let's finish this off. */ + unit_synthesize_cgroup_empty_event(u); + + return 0; +} + +int unit_enqueue_rewatch_pids(Unit *u) { + int r; + + assert(u); + + if (!u->cgroup_path) + return -ENOENT; + + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) + return r; + if (r > 0) /* On unified we can use proper notifications */ + return 0; + + /* Enqueues a low-priority job that will clean up dead PIDs from our list of PIDs to watch and subscribe to new + * PIDs that might have appeared. We do this in a delayed job because the work might be quite slow, as it + * involves issuing kill(pid, 0) on all processes we watch. */ + + if (!u->rewatch_pids_event_source) { + _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL; + + r = sd_event_add_defer(u->manager->event, &s, on_rewatch_pids_event, u); + if (r < 0) + return log_error_errno(r, "Failed to allocate event source for tidying watched PIDs: %m"); + + r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE); + if (r < 0) + return log_error_errno(r, "Failed to adjust priority of event source for tidying watched PIDs: %m"); + + (void) sd_event_source_set_description(s, "tidy-watch-pids"); + + u->rewatch_pids_event_source = TAKE_PTR(s); + } + + r = sd_event_source_set_enabled(u->rewatch_pids_event_source, SD_EVENT_ONESHOT); + if (r < 0) + return log_error_errno(r, "Failed to enable event source for tidying watched PIDs: %m"); + + return 0; +} + +void unit_dequeue_rewatch_pids(Unit *u) { + int r; + assert(u); + + if (!u->rewatch_pids_event_source) + return; + + r = sd_event_source_set_enabled(u->rewatch_pids_event_source, SD_EVENT_OFF); + if (r < 0) + log_warning_errno(r, "Failed to disable event source for tidying watched PIDs, ignoring: %m"); + + u->rewatch_pids_event_source = sd_event_source_unref(u->rewatch_pids_event_source); +} + +bool unit_job_is_applicable(Unit *u, JobType j) { + assert(u); + assert(j >= 0 && j < _JOB_TYPE_MAX); + + switch (j) { + + case JOB_VERIFY_ACTIVE: + case JOB_START: + case JOB_NOP: + /* Note that we don't check unit_can_start() here. That's because .device units and suchlike are not + * startable by us but may appear due to external events, and it thus makes sense to permit enqueing + * jobs for it. */ + return true; + + case JOB_STOP: + /* Similar as above. However, perpetual units can never be stopped (neither explicitly nor due to + * external events), hence it makes no sense to permit enqueing such a request either. */ + return !u->perpetual; + + case JOB_RESTART: + case JOB_TRY_RESTART: + return unit_can_stop(u) && unit_can_start(u); + + case JOB_RELOAD: + case JOB_TRY_RELOAD: + return unit_can_reload(u); + + case JOB_RELOAD_OR_START: + return unit_can_reload(u) && unit_can_start(u); + + default: + assert_not_reached("Invalid job type"); + } +} + +static void maybe_warn_about_dependency(Unit *u, const char *other, UnitDependency dependency) { + assert(u); + + /* Only warn about some unit types */ + if (!IN_SET(dependency, UNIT_CONFLICTS, UNIT_CONFLICTED_BY, UNIT_BEFORE, UNIT_AFTER, UNIT_ON_FAILURE, UNIT_TRIGGERS, UNIT_TRIGGERED_BY)) + return; + + if (streq_ptr(u->id, other)) + log_unit_warning(u, "Dependency %s=%s dropped", unit_dependency_to_string(dependency), u->id); + else + log_unit_warning(u, "Dependency %s=%s dropped, merged into %s", unit_dependency_to_string(dependency), strna(other), u->id); +} + +static int unit_add_dependency_hashmap( + Hashmap **h, + Unit *other, + UnitDependencyMask origin_mask, + UnitDependencyMask destination_mask) { + + UnitDependencyInfo info; + int r; + + assert(h); + assert(other); + assert(origin_mask < _UNIT_DEPENDENCY_MASK_FULL); + assert(destination_mask < _UNIT_DEPENDENCY_MASK_FULL); + assert(origin_mask > 0 || destination_mask > 0); + + r = hashmap_ensure_allocated(h, NULL); + if (r < 0) + return r; + + assert_cc(sizeof(void*) == sizeof(info)); + + info.data = hashmap_get(*h, other); + if (info.data) { + /* Entry already exists. Add in our mask. */ + + if (FLAGS_SET(origin_mask, info.origin_mask) && + FLAGS_SET(destination_mask, info.destination_mask)) + return 0; /* NOP */ + + info.origin_mask |= origin_mask; + info.destination_mask |= destination_mask; + + r = hashmap_update(*h, other, info.data); + } else { + info = (UnitDependencyInfo) { + .origin_mask = origin_mask, + .destination_mask = destination_mask, + }; + + r = hashmap_put(*h, other, info.data); + } + if (r < 0) + return r; + + return 1; +} + +int unit_add_dependency( + Unit *u, + UnitDependency d, + Unit *other, + bool add_reference, + UnitDependencyMask mask) { + + static const UnitDependency inverse_table[_UNIT_DEPENDENCY_MAX] = { + [UNIT_REQUIRES] = UNIT_REQUIRED_BY, + [UNIT_WANTS] = UNIT_WANTED_BY, + [UNIT_REQUISITE] = UNIT_REQUISITE_OF, + [UNIT_BINDS_TO] = UNIT_BOUND_BY, + [UNIT_PART_OF] = UNIT_CONSISTS_OF, + [UNIT_REQUIRED_BY] = UNIT_REQUIRES, + [UNIT_REQUISITE_OF] = UNIT_REQUISITE, + [UNIT_WANTED_BY] = UNIT_WANTS, + [UNIT_BOUND_BY] = UNIT_BINDS_TO, + [UNIT_CONSISTS_OF] = UNIT_PART_OF, + [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY, + [UNIT_CONFLICTED_BY] = UNIT_CONFLICTS, + [UNIT_BEFORE] = UNIT_AFTER, + [UNIT_AFTER] = UNIT_BEFORE, + [UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID, + [UNIT_REFERENCES] = UNIT_REFERENCED_BY, + [UNIT_REFERENCED_BY] = UNIT_REFERENCES, + [UNIT_TRIGGERS] = UNIT_TRIGGERED_BY, + [UNIT_TRIGGERED_BY] = UNIT_TRIGGERS, + [UNIT_PROPAGATES_RELOAD_TO] = UNIT_RELOAD_PROPAGATED_FROM, + [UNIT_RELOAD_PROPAGATED_FROM] = UNIT_PROPAGATES_RELOAD_TO, + [UNIT_JOINS_NAMESPACE_OF] = UNIT_JOINS_NAMESPACE_OF, + }; + Unit *original_u = u, *original_other = other; + int r; + + assert(u); + assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX); + assert(other); + + u = unit_follow_merge(u); + other = unit_follow_merge(other); + + /* We won't allow dependencies on ourselves. We will not + * consider them an error however. */ + if (u == other) { + maybe_warn_about_dependency(original_u, original_other->id, d); + return 0; + } + + if ((d == UNIT_BEFORE && other->type == UNIT_DEVICE) || + (d == UNIT_AFTER && u->type == UNIT_DEVICE)) { + log_unit_warning(u, "Dependency Before=%s ignored (.device units cannot be delayed)", other->id); + return 0; + } + + r = unit_add_dependency_hashmap(u->dependencies + d, other, mask, 0); + if (r < 0) + return r; + + if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID && inverse_table[d] != d) { + r = unit_add_dependency_hashmap(other->dependencies + inverse_table[d], u, 0, mask); + if (r < 0) + return r; + } + + if (add_reference) { + r = unit_add_dependency_hashmap(u->dependencies + UNIT_REFERENCES, other, mask, 0); + if (r < 0) + return r; + + r = unit_add_dependency_hashmap(other->dependencies + UNIT_REFERENCED_BY, u, 0, mask); + if (r < 0) + return r; + } + + unit_add_to_dbus_queue(u); + return 0; +} + +int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference, UnitDependencyMask mask) { + int r; + + assert(u); + + r = unit_add_dependency(u, d, other, add_reference, mask); + if (r < 0) + return r; + + return unit_add_dependency(u, e, other, add_reference, mask); +} + +static int resolve_template(Unit *u, const char *name, char **buf, const char **ret) { + int r; + + assert(u); + assert(name); + assert(buf); + assert(ret); + + if (!unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { + *buf = NULL; + *ret = name; + return 0; + } + + if (u->instance) + r = unit_name_replace_instance(name, u->instance, buf); + else { + _cleanup_free_ char *i = NULL; + + r = unit_name_to_prefix(u->id, &i); + if (r < 0) + return r; + + r = unit_name_replace_instance(name, i, buf); + } + if (r < 0) + return r; + + *ret = *buf; + return 0; +} + +int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, bool add_reference, UnitDependencyMask mask) { + _cleanup_free_ char *buf = NULL; + Unit *other; + int r; + + assert(u); + assert(name); + + r = resolve_template(u, name, &buf, &name); + if (r < 0) + return r; + + r = manager_load_unit(u->manager, name, NULL, NULL, &other); + if (r < 0) + return r; + + return unit_add_dependency(u, d, other, add_reference, mask); +} + +int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, bool add_reference, UnitDependencyMask mask) { + _cleanup_free_ char *buf = NULL; + Unit *other; + int r; + + assert(u); + assert(name); + + r = resolve_template(u, name, &buf, &name); + if (r < 0) + return r; + + r = manager_load_unit(u->manager, name, NULL, NULL, &other); + if (r < 0) + return r; + + return unit_add_two_dependencies(u, d, e, other, add_reference, mask); +} + +int set_unit_path(const char *p) { + /* This is mostly for debug purposes */ + if (setenv("SYSTEMD_UNIT_PATH", p, 1) < 0) + return -errno; + + return 0; +} + +char *unit_dbus_path(Unit *u) { + assert(u); + + if (!u->id) + return NULL; + + return unit_dbus_path_from_name(u->id); +} + +char *unit_dbus_path_invocation_id(Unit *u) { + assert(u); + + if (sd_id128_is_null(u->invocation_id)) + return NULL; + + return unit_dbus_path_from_name(u->invocation_id_string); +} + +int unit_set_slice(Unit *u, Unit *slice) { + assert(u); + assert(slice); + + /* Sets the unit slice if it has not been set before. Is extra + * careful, to only allow this for units that actually have a + * cgroup context. Also, we don't allow to set this for slices + * (since the parent slice is derived from the name). Make + * sure the unit we set is actually a slice. */ + + if (!UNIT_HAS_CGROUP_CONTEXT(u)) + return -EOPNOTSUPP; + + if (u->type == UNIT_SLICE) + return -EINVAL; + + if (unit_active_state(u) != UNIT_INACTIVE) + return -EBUSY; + + if (slice->type != UNIT_SLICE) + return -EINVAL; + + if (unit_has_name(u, SPECIAL_INIT_SCOPE) && + !unit_has_name(slice, SPECIAL_ROOT_SLICE)) + return -EPERM; + + if (UNIT_DEREF(u->slice) == slice) + return 0; + + /* Disallow slice changes if @u is already bound to cgroups */ + if (UNIT_ISSET(u->slice) && u->cgroup_realized) + return -EBUSY; + + unit_ref_set(&u->slice, u, slice); + return 1; +} + +int unit_set_default_slice(Unit *u) { + const char *slice_name; + Unit *slice; + int r; + + assert(u); + + if (UNIT_ISSET(u->slice)) + return 0; + + if (u->instance) { + _cleanup_free_ char *prefix = NULL, *escaped = NULL; + + /* Implicitly place all instantiated units in their + * own per-template slice */ + + r = unit_name_to_prefix(u->id, &prefix); + if (r < 0) + return r; + + /* The prefix is already escaped, but it might include + * "-" which has a special meaning for slice units, + * hence escape it here extra. */ + escaped = unit_name_escape(prefix); + if (!escaped) + return -ENOMEM; + + if (MANAGER_IS_SYSTEM(u->manager)) + slice_name = strjoina("system-", escaped, ".slice"); + else + slice_name = strjoina(escaped, ".slice"); + } else + slice_name = + MANAGER_IS_SYSTEM(u->manager) && !unit_has_name(u, SPECIAL_INIT_SCOPE) + ? SPECIAL_SYSTEM_SLICE + : SPECIAL_ROOT_SLICE; + + r = manager_load_unit(u->manager, slice_name, NULL, NULL, &slice); + if (r < 0) + return r; + + return unit_set_slice(u, slice); +} + +const char *unit_slice_name(Unit *u) { + assert(u); + + if (!UNIT_ISSET(u->slice)) + return NULL; + + return UNIT_DEREF(u->slice)->id; +} + +int unit_load_related_unit(Unit *u, const char *type, Unit **_found) { + _cleanup_free_ char *t = NULL; + int r; + + assert(u); + assert(type); + assert(_found); + + r = unit_name_change_suffix(u->id, type, &t); + if (r < 0) + return r; + if (unit_has_name(u, t)) + return -EINVAL; + + r = manager_load_unit(u->manager, t, NULL, NULL, _found); + assert(r < 0 || *_found != u); + return r; +} + +static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *name, *old_owner, *new_owner; + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + old_owner = empty_to_null(old_owner); + new_owner = empty_to_null(new_owner); + + if (UNIT_VTABLE(u)->bus_name_owner_change) + UNIT_VTABLE(u)->bus_name_owner_change(u, old_owner, new_owner); + + return 0; +} + +static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const sd_bus_error *e; + const char *new_owner; + Unit *u = userdata; + int r; + + assert(message); + assert(u); + + u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot); + + if (sd_bus_error_is_set(error)) { + log_error("Failed to get name owner from bus: %s", error->message); + return 0; + } + + e = sd_bus_message_get_error(message); + if (sd_bus_error_has_name(e, "org.freedesktop.DBus.Error.NameHasNoOwner")) + return 0; + + if (e) { + log_error("Unexpected error response from GetNameOwner: %s", e->message); + return 0; + } + + r = sd_bus_message_read(message, "s", &new_owner); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + new_owner = empty_to_null(new_owner); + + if (UNIT_VTABLE(u)->bus_name_owner_change) + UNIT_VTABLE(u)->bus_name_owner_change(u, NULL, new_owner); + + return 0; +} + +int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) { + const char *match; + + assert(u); + assert(bus); + assert(name); + + if (u->match_bus_slot) + return -EBUSY; + + match = strjoina("type='signal'," + "sender='org.freedesktop.DBus'," + "path='/org/freedesktop/DBus'," + "interface='org.freedesktop.DBus'," + "member='NameOwnerChanged'," + "arg0='", name, "'"); + + int r = sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL, u); + if (r < 0) + return r; + + return sd_bus_call_method_async(bus, + &u->get_name_owner_slot, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetNameOwner", + get_name_owner_handler, + u, + "s", name); +} + +int unit_watch_bus_name(Unit *u, const char *name) { + int r; + + assert(u); + assert(name); + + /* Watch a specific name on the bus. We only support one unit + * watching each name for now. */ + + if (u->manager->api_bus) { + /* If the bus is already available, install the match directly. + * Otherwise, just put the name in the list. bus_setup_api() will take care later. */ + r = unit_install_bus_match(u, u->manager->api_bus, name); + if (r < 0) + return log_warning_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name); + } + + r = hashmap_put(u->manager->watch_bus, name, u); + if (r < 0) { + u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); + return log_warning_errno(r, "Failed to put bus name to hashmap: %m"); + } + + return 0; +} + +void unit_unwatch_bus_name(Unit *u, const char *name) { + assert(u); + assert(name); + + (void) hashmap_remove_value(u->manager->watch_bus, name, u); + u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); + u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot); +} + +bool unit_can_serialize(Unit *u) { + assert(u); + + return UNIT_VTABLE(u)->serialize && UNIT_VTABLE(u)->deserialize_item; +} + +static int serialize_cgroup_mask(FILE *f, const char *key, CGroupMask mask) { + _cleanup_free_ char *s = NULL; + int r; + + assert(f); + assert(key); + + if (mask == 0) + return 0; + + r = cg_mask_to_string(mask, &s); + if (r < 0) + return log_error_errno(r, "Failed to format cgroup mask: %m"); + + return serialize_item(f, key, s); +} + +static const char *const ip_accounting_metric_field[_CGROUP_IP_ACCOUNTING_METRIC_MAX] = { + [CGROUP_IP_INGRESS_BYTES] = "ip-accounting-ingress-bytes", + [CGROUP_IP_INGRESS_PACKETS] = "ip-accounting-ingress-packets", + [CGROUP_IP_EGRESS_BYTES] = "ip-accounting-egress-bytes", + [CGROUP_IP_EGRESS_PACKETS] = "ip-accounting-egress-packets", +}; + +static const char *const io_accounting_metric_field_base[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = { + [CGROUP_IO_READ_BYTES] = "io-accounting-read-bytes-base", + [CGROUP_IO_WRITE_BYTES] = "io-accounting-write-bytes-base", + [CGROUP_IO_READ_OPERATIONS] = "io-accounting-read-operations-base", + [CGROUP_IO_WRITE_OPERATIONS] = "io-accounting-write-operations-base", +}; + +static const char *const io_accounting_metric_field_last[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = { + [CGROUP_IO_READ_BYTES] = "io-accounting-read-bytes-last", + [CGROUP_IO_WRITE_BYTES] = "io-accounting-write-bytes-last", + [CGROUP_IO_READ_OPERATIONS] = "io-accounting-read-operations-last", + [CGROUP_IO_WRITE_OPERATIONS] = "io-accounting-write-operations-last", +}; + +int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { + CGroupIPAccountingMetric m; + int r; + + assert(u); + assert(f); + assert(fds); + + if (unit_can_serialize(u)) { + r = UNIT_VTABLE(u)->serialize(u, f, fds); + if (r < 0) + return r; + } + + (void) serialize_dual_timestamp(f, "state-change-timestamp", &u->state_change_timestamp); + + (void) serialize_dual_timestamp(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp); + (void) serialize_dual_timestamp(f, "active-enter-timestamp", &u->active_enter_timestamp); + (void) serialize_dual_timestamp(f, "active-exit-timestamp", &u->active_exit_timestamp); + (void) serialize_dual_timestamp(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp); + + (void) serialize_dual_timestamp(f, "condition-timestamp", &u->condition_timestamp); + (void) serialize_dual_timestamp(f, "assert-timestamp", &u->assert_timestamp); + + if (dual_timestamp_is_set(&u->condition_timestamp)) + (void) serialize_bool(f, "condition-result", u->condition_result); + + if (dual_timestamp_is_set(&u->assert_timestamp)) + (void) serialize_bool(f, "assert-result", u->assert_result); + + (void) serialize_bool(f, "transient", u->transient); + (void) serialize_bool(f, "in-audit", u->in_audit); + + (void) serialize_bool(f, "exported-invocation-id", u->exported_invocation_id); + (void) serialize_bool(f, "exported-log-level-max", u->exported_log_level_max); + (void) serialize_bool(f, "exported-log-extra-fields", u->exported_log_extra_fields); + (void) serialize_bool(f, "exported-log-rate-limit-interval", u->exported_log_ratelimit_interval); + (void) serialize_bool(f, "exported-log-rate-limit-burst", u->exported_log_ratelimit_burst); + + (void) serialize_item_format(f, "cpu-usage-base", "%" PRIu64, u->cpu_usage_base); + if (u->cpu_usage_last != NSEC_INFINITY) + (void) serialize_item_format(f, "cpu-usage-last", "%" PRIu64, u->cpu_usage_last); + + if (u->oom_kill_last > 0) + (void) serialize_item_format(f, "oom-kill-last", "%" PRIu64, u->oom_kill_last); + + for (CGroupIOAccountingMetric im = 0; im < _CGROUP_IO_ACCOUNTING_METRIC_MAX; im++) { + (void) serialize_item_format(f, io_accounting_metric_field_base[im], "%" PRIu64, u->io_accounting_base[im]); + + if (u->io_accounting_last[im] != UINT64_MAX) + (void) serialize_item_format(f, io_accounting_metric_field_last[im], "%" PRIu64, u->io_accounting_last[im]); + } + + if (u->cgroup_path) + (void) serialize_item(f, "cgroup", u->cgroup_path); + + (void) serialize_bool(f, "cgroup-realized", u->cgroup_realized); + (void) serialize_cgroup_mask(f, "cgroup-realized-mask", u->cgroup_realized_mask); + (void) serialize_cgroup_mask(f, "cgroup-enabled-mask", u->cgroup_enabled_mask); + (void) serialize_cgroup_mask(f, "cgroup-invalidated-mask", u->cgroup_invalidated_mask); + + if (uid_is_valid(u->ref_uid)) + (void) serialize_item_format(f, "ref-uid", UID_FMT, u->ref_uid); + if (gid_is_valid(u->ref_gid)) + (void) serialize_item_format(f, "ref-gid", GID_FMT, u->ref_gid); + + if (!sd_id128_is_null(u->invocation_id)) + (void) serialize_item_format(f, "invocation-id", SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(u->invocation_id)); + + bus_track_serialize(u->bus_track, f, "ref"); + + for (m = 0; m < _CGROUP_IP_ACCOUNTING_METRIC_MAX; m++) { + uint64_t v; + + r = unit_get_ip_accounting(u, m, &v); + if (r >= 0) + (void) serialize_item_format(f, ip_accounting_metric_field[m], "%" PRIu64, v); + } + + if (serialize_jobs) { + if (u->job) { + fputs("job\n", f); + job_serialize(u->job, f); + } + + if (u->nop_job) { + fputs("job\n", f); + job_serialize(u->nop_job, f); + } + } + + /* End marker */ + fputc('\n', f); + return 0; +} + +static int unit_deserialize_job(Unit *u, FILE *f) { + _cleanup_(job_freep) Job *j = NULL; + int r; + + assert(u); + assert(f); + + j = job_new_raw(u); + if (!j) + return log_oom(); + + r = job_deserialize(j, f); + if (r < 0) + return r; + + r = job_install_deserialized(j); + if (r < 0) + return r; + + TAKE_PTR(j); + return 0; +} + +int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { + int r; + + assert(u); + assert(f); + assert(fds); + + for (;;) { + _cleanup_free_ char *line = NULL; + char *l, *v; + ssize_t m; + size_t k; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) /* eof */ + break; + + l = strstrip(line); + if (isempty(l)) /* End marker */ + break; + + k = strcspn(l, "="); + + if (l[k] == '=') { + l[k] = 0; + v = l+k+1; + } else + v = l+k; + + if (streq(l, "job")) { + if (v[0] == '\0') { + /* New-style serialized job */ + r = unit_deserialize_job(u, f); + if (r < 0) + return r; + } else /* Legacy for pre-44 */ + log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v); + continue; + } else if (streq(l, "state-change-timestamp")) { + (void) deserialize_dual_timestamp(v, &u->state_change_timestamp); + continue; + } else if (streq(l, "inactive-exit-timestamp")) { + (void) deserialize_dual_timestamp(v, &u->inactive_exit_timestamp); + continue; + } else if (streq(l, "active-enter-timestamp")) { + (void) deserialize_dual_timestamp(v, &u->active_enter_timestamp); + continue; + } else if (streq(l, "active-exit-timestamp")) { + (void) deserialize_dual_timestamp(v, &u->active_exit_timestamp); + continue; + } else if (streq(l, "inactive-enter-timestamp")) { + (void) deserialize_dual_timestamp(v, &u->inactive_enter_timestamp); + continue; + } else if (streq(l, "condition-timestamp")) { + (void) deserialize_dual_timestamp(v, &u->condition_timestamp); + continue; + } else if (streq(l, "assert-timestamp")) { + (void) deserialize_dual_timestamp(v, &u->assert_timestamp); + continue; + } else if (streq(l, "condition-result")) { + + r = parse_boolean(v); + if (r < 0) + log_unit_debug(u, "Failed to parse condition result value %s, ignoring.", v); + else + u->condition_result = r; + + continue; + + } else if (streq(l, "assert-result")) { + + r = parse_boolean(v); + if (r < 0) + log_unit_debug(u, "Failed to parse assert result value %s, ignoring.", v); + else + u->assert_result = r; + + continue; + + } else if (streq(l, "transient")) { + + r = parse_boolean(v); + if (r < 0) + log_unit_debug(u, "Failed to parse transient bool %s, ignoring.", v); + else + u->transient = r; + + continue; + + } else if (streq(l, "in-audit")) { + + r = parse_boolean(v); + if (r < 0) + log_unit_debug(u, "Failed to parse in-audit bool %s, ignoring.", v); + else + u->in_audit = r; + + continue; + + } else if (streq(l, "exported-invocation-id")) { + + r = parse_boolean(v); + if (r < 0) + log_unit_debug(u, "Failed to parse exported invocation ID bool %s, ignoring.", v); + else + u->exported_invocation_id = r; + + continue; + + } else if (streq(l, "exported-log-level-max")) { + + r = parse_boolean(v); + if (r < 0) + log_unit_debug(u, "Failed to parse exported log level max bool %s, ignoring.", v); + else + u->exported_log_level_max = r; + + continue; + + } else if (streq(l, "exported-log-extra-fields")) { + + r = parse_boolean(v); + if (r < 0) + log_unit_debug(u, "Failed to parse exported log extra fields bool %s, ignoring.", v); + else + u->exported_log_extra_fields = r; + + continue; + + } else if (streq(l, "exported-log-rate-limit-interval")) { + + r = parse_boolean(v); + if (r < 0) + log_unit_debug(u, "Failed to parse exported log rate limit interval %s, ignoring.", v); + else + u->exported_log_ratelimit_interval = r; + + continue; + + } else if (streq(l, "exported-log-rate-limit-burst")) { + + r = parse_boolean(v); + if (r < 0) + log_unit_debug(u, "Failed to parse exported log rate limit burst %s, ignoring.", v); + else + u->exported_log_ratelimit_burst = r; + + continue; + + } else if (STR_IN_SET(l, "cpu-usage-base", "cpuacct-usage-base")) { + + r = safe_atou64(v, &u->cpu_usage_base); + if (r < 0) + log_unit_debug(u, "Failed to parse CPU usage base %s, ignoring.", v); + + continue; + + } else if (streq(l, "cpu-usage-last")) { + + r = safe_atou64(v, &u->cpu_usage_last); + if (r < 0) + log_unit_debug(u, "Failed to read CPU usage last %s, ignoring.", v); + + continue; + + } else if (streq(l, "oom-kill-last")) { + + r = safe_atou64(v, &u->oom_kill_last); + if (r < 0) + log_unit_debug(u, "Failed to read OOM kill last %s, ignoring.", v); + + continue; + + } else if (streq(l, "cgroup")) { + + r = unit_set_cgroup_path(u, v); + if (r < 0) + log_unit_debug_errno(u, r, "Failed to set cgroup path %s, ignoring: %m", v); + + (void) unit_watch_cgroup(u); + (void) unit_watch_cgroup_memory(u); + + continue; + } else if (streq(l, "cgroup-realized")) { + int b; + + b = parse_boolean(v); + if (b < 0) + log_unit_debug(u, "Failed to parse cgroup-realized bool %s, ignoring.", v); + else + u->cgroup_realized = b; + + continue; + + } else if (streq(l, "cgroup-realized-mask")) { + + r = cg_mask_from_string(v, &u->cgroup_realized_mask); + if (r < 0) + log_unit_debug(u, "Failed to parse cgroup-realized-mask %s, ignoring.", v); + continue; + + } else if (streq(l, "cgroup-enabled-mask")) { + + r = cg_mask_from_string(v, &u->cgroup_enabled_mask); + if (r < 0) + log_unit_debug(u, "Failed to parse cgroup-enabled-mask %s, ignoring.", v); + continue; + + } else if (streq(l, "cgroup-invalidated-mask")) { + + r = cg_mask_from_string(v, &u->cgroup_invalidated_mask); + if (r < 0) + log_unit_debug(u, "Failed to parse cgroup-invalidated-mask %s, ignoring.", v); + continue; + + } else if (streq(l, "ref-uid")) { + uid_t uid; + + r = parse_uid(v, &uid); + if (r < 0) + log_unit_debug(u, "Failed to parse referenced UID %s, ignoring.", v); + else + unit_ref_uid_gid(u, uid, GID_INVALID); + + continue; + + } else if (streq(l, "ref-gid")) { + gid_t gid; + + r = parse_gid(v, &gid); + if (r < 0) + log_unit_debug(u, "Failed to parse referenced GID %s, ignoring.", v); + else + unit_ref_uid_gid(u, UID_INVALID, gid); + + continue; + + } else if (streq(l, "ref")) { + + r = strv_extend(&u->deserialized_refs, v); + if (r < 0) + return log_oom(); + + continue; + } else if (streq(l, "invocation-id")) { + sd_id128_t id; + + r = sd_id128_from_string(v, &id); + if (r < 0) + log_unit_debug(u, "Failed to parse invocation id %s, ignoring.", v); + else { + r = unit_set_invocation_id(u, id); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to set invocation ID for unit: %m"); + } + + continue; + } + + /* Check if this is an IP accounting metric serialization field */ + m = string_table_lookup(ip_accounting_metric_field, ELEMENTSOF(ip_accounting_metric_field), l); + if (m >= 0) { + uint64_t c; + + r = safe_atou64(v, &c); + if (r < 0) + log_unit_debug(u, "Failed to parse IP accounting value %s, ignoring.", v); + else + u->ip_accounting_extra[m] = c; + continue; + } + + m = string_table_lookup(io_accounting_metric_field_base, ELEMENTSOF(io_accounting_metric_field_base), l); + if (m >= 0) { + uint64_t c; + + r = safe_atou64(v, &c); + if (r < 0) + log_unit_debug(u, "Failed to parse IO accounting base value %s, ignoring.", v); + else + u->io_accounting_base[m] = c; + continue; + } + + m = string_table_lookup(io_accounting_metric_field_last, ELEMENTSOF(io_accounting_metric_field_last), l); + if (m >= 0) { + uint64_t c; + + r = safe_atou64(v, &c); + if (r < 0) + log_unit_debug(u, "Failed to parse IO accounting last value %s, ignoring.", v); + else + u->io_accounting_last[m] = c; + continue; + } + + if (unit_can_serialize(u)) { + r = exec_runtime_deserialize_compat(u, l, v, fds); + if (r < 0) { + log_unit_warning(u, "Failed to deserialize runtime parameter '%s', ignoring.", l); + continue; + } + + /* Returns positive if key was handled by the call */ + if (r > 0) + continue; + + r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds); + if (r < 0) + log_unit_warning(u, "Failed to deserialize unit parameter '%s', ignoring.", l); + } + } + + /* Versions before 228 did not carry a state change timestamp. In this case, take the current time. This is + * useful, so that timeouts based on this timestamp don't trigger too early, and is in-line with the logic from + * before 228 where the base for timeouts was not persistent across reboots. */ + + if (!dual_timestamp_is_set(&u->state_change_timestamp)) + dual_timestamp_get(&u->state_change_timestamp); + + /* Let's make sure that everything that is deserialized also gets any potential new cgroup settings applied + * after we are done. For that we invalidate anything already realized, so that we can realize it again. */ + unit_invalidate_cgroup(u, _CGROUP_MASK_ALL); + unit_invalidate_cgroup_bpf(u); + + return 0; +} + +int unit_deserialize_skip(FILE *f) { + int r; + assert(f); + + /* Skip serialized data for this unit. We don't know what it is. */ + + for (;;) { + _cleanup_free_ char *line = NULL; + char *l; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read serialization line: %m"); + if (r == 0) + return 0; + + l = strstrip(line); + + /* End marker */ + if (isempty(l)) + return 1; + } +} + +int unit_add_node_dependency(Unit *u, const char *what, UnitDependency dep, UnitDependencyMask mask) { + Unit *device; + _cleanup_free_ char *e = NULL; + int r; + + assert(u); + + /* Adds in links to the device node that this unit is based on */ + if (isempty(what)) + return 0; + + if (!is_device_path(what)) + return 0; + + /* When device units aren't supported (such as in a + * container), don't create dependencies on them. */ + if (!unit_type_supported(UNIT_DEVICE)) + return 0; + + r = unit_name_from_path(what, ".device", &e); + if (r < 0) + return r; + + r = manager_load_unit(u->manager, e, NULL, NULL, &device); + if (r < 0) + return r; + + if (dep == UNIT_REQUIRES && device_shall_be_bound_by(device, u)) + dep = UNIT_BINDS_TO; + + return unit_add_two_dependencies(u, UNIT_AFTER, + MANAGER_IS_SYSTEM(u->manager) ? dep : UNIT_WANTS, + device, true, mask); +} + +int unit_coldplug(Unit *u) { + int r = 0, q; + char **i; + Job *uj; + + assert(u); + + /* Make sure we don't enter a loop, when coldplugging recursively. */ + if (u->coldplugged) + return 0; + + u->coldplugged = true; + + STRV_FOREACH(i, u->deserialized_refs) { + q = bus_unit_track_add_name(u, *i); + if (q < 0 && r >= 0) + r = q; + } + u->deserialized_refs = strv_free(u->deserialized_refs); + + if (UNIT_VTABLE(u)->coldplug) { + q = UNIT_VTABLE(u)->coldplug(u); + if (q < 0 && r >= 0) + r = q; + } + + uj = u->job ?: u->nop_job; + if (uj) { + q = job_coldplug(uj); + if (q < 0 && r >= 0) + r = q; + } + + return r; +} + +void unit_catchup(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->catchup) + UNIT_VTABLE(u)->catchup(u); +} + +static bool fragment_mtime_newer(const char *path, usec_t mtime, bool path_masked) { + struct stat st; + + if (!path) + return false; + + /* If the source is some virtual kernel file system, then we assume we watch it anyway, and hence pretend we + * are never out-of-date. */ + if (PATH_STARTSWITH_SET(path, "/proc", "/sys")) + return false; + + if (stat(path, &st) < 0) + /* What, cannot access this anymore? */ + return true; + + if (path_masked) + /* For masked files check if they are still so */ + return !null_or_empty(&st); + else + /* For non-empty files check the mtime */ + return timespec_load(&st.st_mtim) > mtime; + + return false; +} + +bool unit_need_daemon_reload(Unit *u) { + _cleanup_strv_free_ char **t = NULL; + char **path; + + assert(u); + + /* For unit files, we allow masking… */ + if (fragment_mtime_newer(u->fragment_path, u->fragment_mtime, + u->load_state == UNIT_MASKED)) + return true; + + /* Source paths should not be masked… */ + if (fragment_mtime_newer(u->source_path, u->source_mtime, false)) + return true; + + if (u->load_state == UNIT_LOADED) + (void) unit_find_dropin_paths(u, &t); + if (!strv_equal(u->dropin_paths, t)) + return true; + + /* … any drop-ins that are masked are simply omitted from the list. */ + STRV_FOREACH(path, u->dropin_paths) + if (fragment_mtime_newer(*path, u->dropin_mtime, false)) + return true; + + return false; +} + +void unit_reset_failed(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->reset_failed) + UNIT_VTABLE(u)->reset_failed(u); + + ratelimit_reset(&u->start_ratelimit); + u->start_limit_hit = false; +} + +Unit *unit_following(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->following) + return UNIT_VTABLE(u)->following(u); + + return NULL; +} + +bool unit_stop_pending(Unit *u) { + assert(u); + + /* This call does check the current state of the unit. It's + * hence useful to be called from state change calls of the + * unit itself, where the state isn't updated yet. This is + * different from unit_inactive_or_pending() which checks both + * the current state and for a queued job. */ + + return unit_has_job_type(u, JOB_STOP); +} + +bool unit_inactive_or_pending(Unit *u) { + assert(u); + + /* Returns true if the unit is inactive or going down */ + + if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(u))) + return true; + + if (unit_stop_pending(u)) + return true; + + return false; +} + +bool unit_active_or_pending(Unit *u) { + assert(u); + + /* Returns true if the unit is active or going up */ + + if (UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) + return true; + + if (u->job && + IN_SET(u->job->type, JOB_START, JOB_RELOAD_OR_START, JOB_RESTART)) + return true; + + return false; +} + +bool unit_will_restart_default(Unit *u) { + assert(u); + + return unit_has_job_type(u, JOB_START); +} + +bool unit_will_restart(Unit *u) { + assert(u); + + if (!UNIT_VTABLE(u)->will_restart) + return false; + + return UNIT_VTABLE(u)->will_restart(u); +} + +int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) { + assert(u); + assert(w >= 0 && w < _KILL_WHO_MAX); + assert(SIGNAL_VALID(signo)); + + if (!UNIT_VTABLE(u)->kill) + return -EOPNOTSUPP; + + return UNIT_VTABLE(u)->kill(u, w, signo, error); +} + +static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) { + _cleanup_set_free_ Set *pid_set = NULL; + int r; + + pid_set = set_new(NULL); + if (!pid_set) + return NULL; + + /* Exclude the main/control pids from being killed via the cgroup */ + if (main_pid > 0) { + r = set_put(pid_set, PID_TO_PTR(main_pid)); + if (r < 0) + return NULL; + } + + if (control_pid > 0) { + r = set_put(pid_set, PID_TO_PTR(control_pid)); + if (r < 0) + return NULL; + } + + return TAKE_PTR(pid_set); +} + +int unit_kill_common( + Unit *u, + KillWho who, + int signo, + pid_t main_pid, + pid_t control_pid, + sd_bus_error *error) { + + int r = 0; + bool killed = false; + + if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL)) { + if (main_pid < 0) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type)); + else if (main_pid == 0) + return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill"); + } + + if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL)) { + if (control_pid < 0) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type)); + else if (control_pid == 0) + return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill"); + } + + if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL, KILL_ALL, KILL_ALL_FAIL)) + if (control_pid > 0) { + if (kill(control_pid, signo) < 0) + r = -errno; + else + killed = true; + } + + if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL, KILL_ALL, KILL_ALL_FAIL)) + if (main_pid > 0) { + if (kill(main_pid, signo) < 0) + r = -errno; + else + killed = true; + } + + if (IN_SET(who, KILL_ALL, KILL_ALL_FAIL) && u->cgroup_path) { + _cleanup_set_free_ Set *pid_set = NULL; + int q; + + /* Exclude the main/control pids from being killed via the cgroup */ + pid_set = unit_pid_set(main_pid, control_pid); + if (!pid_set) + return -ENOMEM; + + q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, 0, pid_set, NULL, NULL); + if (q < 0 && !IN_SET(q, -EAGAIN, -ESRCH, -ENOENT)) + r = q; + else + killed = true; + } + + if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL)) + return -ESRCH; + + return r; +} + +int unit_following_set(Unit *u, Set **s) { + assert(u); + assert(s); + + if (UNIT_VTABLE(u)->following_set) + return UNIT_VTABLE(u)->following_set(u, s); + + *s = NULL; + return 0; +} + +UnitFileState unit_get_unit_file_state(Unit *u) { + int r; + + assert(u); + + if (u->unit_file_state < 0 && u->fragment_path) { + r = unit_file_get_state( + u->manager->unit_file_scope, + NULL, + u->id, + &u->unit_file_state); + if (r < 0) + u->unit_file_state = UNIT_FILE_BAD; + } + + return u->unit_file_state; +} + +int unit_get_unit_file_preset(Unit *u) { + assert(u); + + if (u->unit_file_preset < 0 && u->fragment_path) + u->unit_file_preset = unit_file_query_preset( + u->manager->unit_file_scope, + NULL, + basename(u->fragment_path)); + + return u->unit_file_preset; +} + +Unit* unit_ref_set(UnitRef *ref, Unit *source, Unit *target) { + assert(ref); + assert(source); + assert(target); + + if (ref->target) + unit_ref_unset(ref); + + ref->source = source; + ref->target = target; + LIST_PREPEND(refs_by_target, target->refs_by_target, ref); + return target; +} + +void unit_ref_unset(UnitRef *ref) { + assert(ref); + + if (!ref->target) + return; + + /* We are about to drop a reference to the unit, make sure the garbage collection has a look at it as it might + * be unreferenced now. */ + unit_add_to_gc_queue(ref->target); + + LIST_REMOVE(refs_by_target, ref->target->refs_by_target, ref); + ref->source = ref->target = NULL; +} + +static int user_from_unit_name(Unit *u, char **ret) { + + static const uint8_t hash_key[] = { + 0x58, 0x1a, 0xaf, 0xe6, 0x28, 0x58, 0x4e, 0x96, + 0xb4, 0x4e, 0xf5, 0x3b, 0x8c, 0x92, 0x07, 0xec + }; + + _cleanup_free_ char *n = NULL; + int r; + + r = unit_name_to_prefix(u->id, &n); + if (r < 0) + return r; + + if (valid_user_group_name(n)) { + *ret = TAKE_PTR(n); + return 0; + } + + /* If we can't use the unit name as a user name, then let's hash it and use that */ + if (asprintf(ret, "_du%016" PRIx64, siphash24(n, strlen(n), hash_key)) < 0) + return -ENOMEM; + + return 0; +} + +int unit_patch_contexts(Unit *u) { + CGroupContext *cc; + ExecContext *ec; + unsigned i; + int r; + + assert(u); + + /* Patch in the manager defaults into the exec and cgroup + * contexts, _after_ the rest of the settings have been + * initialized */ + + ec = unit_get_exec_context(u); + if (ec) { + /* This only copies in the ones that need memory */ + for (i = 0; i < _RLIMIT_MAX; i++) + if (u->manager->rlimit[i] && !ec->rlimit[i]) { + ec->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1); + if (!ec->rlimit[i]) + return -ENOMEM; + } + + if (MANAGER_IS_USER(u->manager) && + !ec->working_directory) { + + r = get_home_dir(&ec->working_directory); + if (r < 0) + return r; + + /* Allow user services to run, even if the + * home directory is missing */ + ec->working_directory_missing_ok = true; + } + + if (ec->private_devices) + ec->capability_bounding_set &= ~((UINT64_C(1) << CAP_MKNOD) | (UINT64_C(1) << CAP_SYS_RAWIO)); + + if (ec->protect_kernel_modules) + ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYS_MODULE); + + if (ec->protect_kernel_logs) + ec->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYSLOG); + + if (ec->dynamic_user) { + if (!ec->user) { + r = user_from_unit_name(u, &ec->user); + if (r < 0) + return r; + } + + if (!ec->group) { + ec->group = strdup(ec->user); + if (!ec->group) + return -ENOMEM; + } + + /* If the dynamic user option is on, let's make sure that the unit can't leave its + * UID/GID around in the file system or on IPC objects. Hence enforce a strict + * sandbox. */ + + ec->private_tmp = true; + ec->remove_ipc = true; + ec->protect_system = PROTECT_SYSTEM_STRICT; + if (ec->protect_home == PROTECT_HOME_NO) + ec->protect_home = PROTECT_HOME_READ_ONLY; + + /* Make sure this service can neither benefit from SUID/SGID binaries nor create + * them. */ + ec->no_new_privileges = true; + ec->restrict_suid_sgid = true; + } + } + + cc = unit_get_cgroup_context(u); + if (cc && ec) { + + if (ec->private_devices && + cc->device_policy == CGROUP_DEVICE_POLICY_AUTO) + cc->device_policy = CGROUP_DEVICE_POLICY_CLOSED; + + if (ec->root_image && + (cc->device_policy != CGROUP_DEVICE_POLICY_AUTO || cc->device_allow)) { + + /* When RootImage= is specified, the following devices are touched. */ + r = cgroup_add_device_allow(cc, "/dev/loop-control", "rw"); + if (r < 0) + return r; + + r = cgroup_add_device_allow(cc, "block-loop", "rwm"); + if (r < 0) + return r; + + r = cgroup_add_device_allow(cc, "block-blkext", "rwm"); + if (r < 0) + return r; + } + } + + return 0; +} + +ExecContext *unit_get_exec_context(Unit *u) { + size_t offset; + assert(u); + + if (u->type < 0) + return NULL; + + offset = UNIT_VTABLE(u)->exec_context_offset; + if (offset <= 0) + return NULL; + + return (ExecContext*) ((uint8_t*) u + offset); +} + +KillContext *unit_get_kill_context(Unit *u) { + size_t offset; + assert(u); + + if (u->type < 0) + return NULL; + + offset = UNIT_VTABLE(u)->kill_context_offset; + if (offset <= 0) + return NULL; + + return (KillContext*) ((uint8_t*) u + offset); +} + +CGroupContext *unit_get_cgroup_context(Unit *u) { + size_t offset; + + if (u->type < 0) + return NULL; + + offset = UNIT_VTABLE(u)->cgroup_context_offset; + if (offset <= 0) + return NULL; + + return (CGroupContext*) ((uint8_t*) u + offset); +} + +ExecRuntime *unit_get_exec_runtime(Unit *u) { + size_t offset; + + if (u->type < 0) + return NULL; + + offset = UNIT_VTABLE(u)->exec_runtime_offset; + if (offset <= 0) + return NULL; + + return *(ExecRuntime**) ((uint8_t*) u + offset); +} + +static const char* unit_drop_in_dir(Unit *u, UnitWriteFlags flags) { + assert(u); + + if (UNIT_WRITE_FLAGS_NOOP(flags)) + return NULL; + + if (u->transient) /* Redirect drop-ins for transient units always into the transient directory. */ + return u->manager->lookup_paths.transient; + + if (flags & UNIT_PERSISTENT) + return u->manager->lookup_paths.persistent_control; + + if (flags & UNIT_RUNTIME) + return u->manager->lookup_paths.runtime_control; + + return NULL; +} + +char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf) { + char *ret = NULL; + + if (!s) + return NULL; + + /* Escapes the input string as requested. Returns the escaped string. If 'buf' is specified then the allocated + * return buffer pointer is also written to *buf, except if no escaping was necessary, in which case *buf is + * set to NULL, and the input pointer is returned as-is. This means the return value always contains a properly + * escaped version, but *buf when passed only contains a pointer if an allocation was necessary. If *buf is + * not specified, then the return value always needs to be freed. Callers can use this to optimize memory + * allocations. */ + + if (flags & UNIT_ESCAPE_SPECIFIERS) { + ret = specifier_escape(s); + if (!ret) + return NULL; + + s = ret; + } + + if (flags & UNIT_ESCAPE_C) { + char *a; + + a = cescape(s); + free(ret); + if (!a) + return NULL; + + ret = a; + } + + if (buf) { + *buf = ret; + return ret ?: (char*) s; + } + + return ret ?: strdup(s); +} + +char* unit_concat_strv(char **l, UnitWriteFlags flags) { + _cleanup_free_ char *result = NULL; + size_t n = 0, allocated = 0; + char **i; + + /* Takes a list of strings, escapes them, and concatenates them. This may be used to format command lines in a + * way suitable for ExecStart= stanzas */ + + STRV_FOREACH(i, l) { + _cleanup_free_ char *buf = NULL; + const char *p; + size_t a; + char *q; + + p = unit_escape_setting(*i, flags, &buf); + if (!p) + return NULL; + + a = (n > 0) + 1 + strlen(p) + 1; /* separating space + " + entry + " */ + if (!GREEDY_REALLOC(result, allocated, n + a + 1)) + return NULL; + + q = result + n; + if (n > 0) + *(q++) = ' '; + + *(q++) = '"'; + q = stpcpy(q, p); + *(q++) = '"'; + + n += a; + } + + if (!GREEDY_REALLOC(result, allocated, n + 1)) + return NULL; + + result[n] = 0; + + return TAKE_PTR(result); +} + +int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data) { + _cleanup_free_ char *p = NULL, *q = NULL, *escaped = NULL; + const char *dir, *wrapped; + int r; + + assert(u); + assert(name); + assert(data); + + if (UNIT_WRITE_FLAGS_NOOP(flags)) + return 0; + + data = unit_escape_setting(data, flags, &escaped); + if (!data) + return -ENOMEM; + + /* Prefix the section header. If we are writing this out as transient file, then let's suppress this if the + * previous section header is the same */ + + if (flags & UNIT_PRIVATE) { + if (!UNIT_VTABLE(u)->private_section) + return -EINVAL; + + if (!u->transient_file || u->last_section_private < 0) + data = strjoina("[", UNIT_VTABLE(u)->private_section, "]\n", data); + else if (u->last_section_private == 0) + data = strjoina("\n[", UNIT_VTABLE(u)->private_section, "]\n", data); + } else { + if (!u->transient_file || u->last_section_private < 0) + data = strjoina("[Unit]\n", data); + else if (u->last_section_private > 0) + data = strjoina("\n[Unit]\n", data); + } + + if (u->transient_file) { + /* When this is a transient unit file in creation, then let's not create a new drop-in but instead + * write to the transient unit file. */ + fputs(data, u->transient_file); + + if (!endswith(data, "\n")) + fputc('\n', u->transient_file); + + /* Remember which section we wrote this entry to */ + u->last_section_private = !!(flags & UNIT_PRIVATE); + return 0; + } + + dir = unit_drop_in_dir(u, flags); + if (!dir) + return -EINVAL; + + wrapped = strjoina("# This is a drop-in unit file extension, created via \"systemctl set-property\"\n" + "# or an equivalent operation. Do not edit.\n", + data, + "\n"); + + r = drop_in_file(dir, u->id, 50, name, &p, &q); + if (r < 0) + return r; + + (void) mkdir_p_label(p, 0755); + + /* Make sure the drop-in dir is registered in our path cache. This way we don't need to stupidly + * recreate the cache after every drop-in we write. */ + if (u->manager->unit_path_cache) { + r = set_put_strdup(u->manager->unit_path_cache, p); + if (r < 0) + return r; + } + + r = write_string_file_atomic_label(q, wrapped); + if (r < 0) + return r; + + r = strv_push(&u->dropin_paths, q); + if (r < 0) + return r; + q = NULL; + + strv_uniq(u->dropin_paths); + + u->dropin_mtime = now(CLOCK_REALTIME); + + return 0; +} + +int unit_write_settingf(Unit *u, UnitWriteFlags flags, const char *name, const char *format, ...) { + _cleanup_free_ char *p = NULL; + va_list ap; + int r; + + assert(u); + assert(name); + assert(format); + + if (UNIT_WRITE_FLAGS_NOOP(flags)) + return 0; + + va_start(ap, format); + r = vasprintf(&p, format, ap); + va_end(ap); + + if (r < 0) + return -ENOMEM; + + return unit_write_setting(u, flags, name, p); +} + +int unit_make_transient(Unit *u) { + _cleanup_free_ char *path = NULL; + FILE *f; + + assert(u); + + if (!UNIT_VTABLE(u)->can_transient) + return -EOPNOTSUPP; + + (void) mkdir_p_label(u->manager->lookup_paths.transient, 0755); + + path = path_join(u->manager->lookup_paths.transient, u->id); + if (!path) + return -ENOMEM; + + /* Let's open the file we'll write the transient settings into. This file is kept open as long as we are + * creating the transient, and is closed in unit_load(), as soon as we start loading the file. */ + + RUN_WITH_UMASK(0022) { + f = fopen(path, "we"); + if (!f) + return -errno; + } + + safe_fclose(u->transient_file); + u->transient_file = f; + + free_and_replace(u->fragment_path, path); + + u->source_path = mfree(u->source_path); + u->dropin_paths = strv_free(u->dropin_paths); + u->fragment_mtime = u->source_mtime = u->dropin_mtime = 0; + + u->load_state = UNIT_STUB; + u->load_error = 0; + u->transient = true; + + unit_add_to_dbus_queue(u); + unit_add_to_gc_queue(u); + + fputs("# This is a transient unit file, created programmatically via the systemd API. Do not edit.\n", + u->transient_file); + + return 0; +} + +static int log_kill(pid_t pid, int sig, void *userdata) { + _cleanup_free_ char *comm = NULL; + + (void) get_process_comm(pid, &comm); + + /* Don't log about processes marked with brackets, under the assumption that these are temporary processes + only, like for example systemd's own PAM stub process. */ + if (comm && comm[0] == '(') + return 0; + + log_unit_notice(userdata, + "Killing process " PID_FMT " (%s) with signal SIG%s.", + pid, + strna(comm), + signal_to_string(sig)); + + return 1; +} + +static int operation_to_signal(const KillContext *c, KillOperation k, bool *noteworthy) { + assert(c); + + switch (k) { + + case KILL_TERMINATE: + case KILL_TERMINATE_AND_LOG: + *noteworthy = false; + return c->kill_signal; + + case KILL_RESTART: + *noteworthy = false; + return restart_kill_signal(c); + + case KILL_KILL: + *noteworthy = true; + return c->final_kill_signal; + + case KILL_WATCHDOG: + *noteworthy = true; + return c->watchdog_signal; + + default: + assert_not_reached("KillOperation unknown"); + } +} + +int unit_kill_context( + Unit *u, + KillContext *c, + KillOperation k, + pid_t main_pid, + pid_t control_pid, + bool main_pid_alien) { + + bool wait_for_exit = false, send_sighup; + cg_kill_log_func_t log_func = NULL; + int sig, r; + + assert(u); + assert(c); + + /* Kill the processes belonging to this unit, in preparation for shutting the unit down. + * Returns > 0 if we killed something worth waiting for, 0 otherwise. */ + + if (c->kill_mode == KILL_NONE) + return 0; + + bool noteworthy; + sig = operation_to_signal(c, k, ¬eworthy); + if (noteworthy) + log_func = log_kill; + + send_sighup = + c->send_sighup && + IN_SET(k, KILL_TERMINATE, KILL_TERMINATE_AND_LOG) && + sig != SIGHUP; + + if (main_pid > 0) { + if (log_func) + log_func(main_pid, sig, u); + + r = kill_and_sigcont(main_pid, sig); + if (r < 0 && r != -ESRCH) { + _cleanup_free_ char *comm = NULL; + (void) get_process_comm(main_pid, &comm); + + log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s), ignoring: %m", main_pid, strna(comm)); + } else { + if (!main_pid_alien) + wait_for_exit = true; + + if (r != -ESRCH && send_sighup) + (void) kill(main_pid, SIGHUP); + } + } + + if (control_pid > 0) { + if (log_func) + log_func(control_pid, sig, u); + + r = kill_and_sigcont(control_pid, sig); + if (r < 0 && r != -ESRCH) { + _cleanup_free_ char *comm = NULL; + (void) get_process_comm(control_pid, &comm); + + log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", control_pid, strna(comm)); + } else { + wait_for_exit = true; + + if (r != -ESRCH && send_sighup) + (void) kill(control_pid, SIGHUP); + } + } + + if (u->cgroup_path && + (c->kill_mode == KILL_CONTROL_GROUP || (c->kill_mode == KILL_MIXED && k == KILL_KILL))) { + _cleanup_set_free_ Set *pid_set = NULL; + + /* Exclude the main/control pids from being killed via the cgroup */ + pid_set = unit_pid_set(main_pid, control_pid); + if (!pid_set) + return -ENOMEM; + + r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, + sig, + CGROUP_SIGCONT|CGROUP_IGNORE_SELF, + pid_set, + log_func, u); + if (r < 0) { + if (!IN_SET(r, -EAGAIN, -ESRCH, -ENOENT)) + log_unit_warning_errno(u, r, "Failed to kill control group %s, ignoring: %m", u->cgroup_path); + + } else if (r > 0) { + + /* FIXME: For now, on the legacy hierarchy, we will not wait for the cgroup members to die if + * we are running in a container or if this is a delegation unit, simply because cgroup + * notification is unreliable in these cases. It doesn't work at all in containers, and outside + * of containers it can be confused easily by left-over directories in the cgroup — which + * however should not exist in non-delegated units. On the unified hierarchy that's different, + * there we get proper events. Hence rely on them. */ + + if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0 || + (detect_container() == 0 && !unit_cgroup_delegate(u))) + wait_for_exit = true; + + if (send_sighup) { + set_free(pid_set); + + pid_set = unit_pid_set(main_pid, control_pid); + if (!pid_set) + return -ENOMEM; + + cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, + SIGHUP, + CGROUP_IGNORE_SELF, + pid_set, + NULL, NULL); + } + } + } + + return wait_for_exit; +} + +int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask) { + _cleanup_free_ char *p = NULL; + UnitDependencyInfo di; + int r; + + assert(u); + assert(path); + + /* Registers a unit for requiring a certain path and all its prefixes. We keep a hashtable of these paths in + * the unit (from the path to the UnitDependencyInfo structure indicating how to the dependency came to + * be). However, we build a prefix table for all possible prefixes so that new appearing mount units can easily + * determine which units to make themselves a dependency of. */ + + if (!path_is_absolute(path)) + return -EINVAL; + + r = hashmap_ensure_allocated(&u->requires_mounts_for, &path_hash_ops); + if (r < 0) + return r; + + p = strdup(path); + if (!p) + return -ENOMEM; + + path = path_simplify(p, true); + + if (!path_is_normalized(path)) + return -EPERM; + + if (hashmap_contains(u->requires_mounts_for, path)) + return 0; + + di = (UnitDependencyInfo) { + .origin_mask = mask + }; + + r = hashmap_put(u->requires_mounts_for, path, di.data); + if (r < 0) + return r; + p = NULL; + + char prefix[strlen(path) + 1]; + PATH_FOREACH_PREFIX_MORE(prefix, path) { + Set *x; + + x = hashmap_get(u->manager->units_requiring_mounts_for, prefix); + if (!x) { + _cleanup_free_ char *q = NULL; + + r = hashmap_ensure_allocated(&u->manager->units_requiring_mounts_for, &path_hash_ops); + if (r < 0) + return r; + + q = strdup(prefix); + if (!q) + return -ENOMEM; + + x = set_new(NULL); + if (!x) + return -ENOMEM; + + r = hashmap_put(u->manager->units_requiring_mounts_for, q, x); + if (r < 0) { + set_free(x); + return r; + } + q = NULL; + } + + r = set_put(x, u); + if (r < 0) + return r; + } + + return 0; +} + +int unit_setup_exec_runtime(Unit *u) { + ExecRuntime **rt; + size_t offset; + Unit *other; + Iterator i; + void *v; + int r; + + offset = UNIT_VTABLE(u)->exec_runtime_offset; + assert(offset > 0); + + /* Check if there already is an ExecRuntime for this unit? */ + rt = (ExecRuntime**) ((uint8_t*) u + offset); + if (*rt) + return 0; + + /* Try to get it from somebody else */ + HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_JOINS_NAMESPACE_OF], i) { + r = exec_runtime_acquire(u->manager, NULL, other->id, false, rt); + if (r == 1) + return 1; + } + + return exec_runtime_acquire(u->manager, unit_get_exec_context(u), u->id, true, rt); +} + +int unit_setup_dynamic_creds(Unit *u) { + ExecContext *ec; + DynamicCreds *dcreds; + size_t offset; + + assert(u); + + offset = UNIT_VTABLE(u)->dynamic_creds_offset; + assert(offset > 0); + dcreds = (DynamicCreds*) ((uint8_t*) u + offset); + + ec = unit_get_exec_context(u); + assert(ec); + + if (!ec->dynamic_user) + return 0; + + return dynamic_creds_acquire(dcreds, u->manager, ec->user, ec->group); +} + +bool unit_type_supported(UnitType t) { + if (_unlikely_(t < 0)) + return false; + if (_unlikely_(t >= _UNIT_TYPE_MAX)) + return false; + + if (!unit_vtable[t]->supported) + return true; + + return unit_vtable[t]->supported(); +} + +void unit_warn_if_dir_nonempty(Unit *u, const char* where) { + int r; + + assert(u); + assert(where); + + r = dir_is_empty(where); + if (r > 0 || r == -ENOTDIR) + return; + if (r < 0) { + log_unit_warning_errno(u, r, "Failed to check directory %s: %m", where); + return; + } + + log_struct(LOG_NOTICE, + "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR, + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u), + LOG_UNIT_MESSAGE(u, "Directory %s to mount over is not empty, mounting anyway.", where), + "WHERE=%s", where); +} + +int unit_fail_if_noncanonical(Unit *u, const char* where) { + _cleanup_free_ char *canonical_where = NULL; + int r; + + assert(u); + assert(where); + + r = chase_symlinks(where, NULL, CHASE_NONEXISTENT, &canonical_where, NULL); + if (r < 0) { + log_unit_debug_errno(u, r, "Failed to check %s for symlinks, ignoring: %m", where); + return 0; + } + + /* We will happily ignore a trailing slash (or any redundant slashes) */ + if (path_equal(where, canonical_where)) + return 0; + + /* No need to mention "." or "..", they would already have been rejected by unit_name_from_path() */ + log_struct(LOG_ERR, + "MESSAGE_ID=" SD_MESSAGE_OVERMOUNTING_STR, + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u), + LOG_UNIT_MESSAGE(u, "Mount path %s is not canonical (contains a symlink).", where), + "WHERE=%s", where); + + return -ELOOP; +} + +bool unit_is_pristine(Unit *u) { + assert(u); + + /* Check if the unit already exists or is already around, + * in a number of different ways. Note that to cater for unit + * types such as slice, we are generally fine with units that + * are marked UNIT_LOADED even though nothing was actually + * loaded, as those unit types don't require a file on disk. */ + + return !(!IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_LOADED) || + u->fragment_path || + u->source_path || + !strv_isempty(u->dropin_paths) || + u->job || + u->merged_into); +} + +pid_t unit_control_pid(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->control_pid) + return UNIT_VTABLE(u)->control_pid(u); + + return 0; +} + +pid_t unit_main_pid(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->main_pid) + return UNIT_VTABLE(u)->main_pid(u); + + return 0; +} + +static void unit_unref_uid_internal( + Unit *u, + uid_t *ref_uid, + bool destroy_now, + void (*_manager_unref_uid)(Manager *m, uid_t uid, bool destroy_now)) { + + assert(u); + assert(ref_uid); + assert(_manager_unref_uid); + + /* Generic implementation of both unit_unref_uid() and unit_unref_gid(), under the assumption that uid_t and + * gid_t are actually the same time, with the same validity rules. + * + * Drops a reference to UID/GID from a unit. */ + + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + assert_cc(UID_INVALID == (uid_t) GID_INVALID); + + if (!uid_is_valid(*ref_uid)) + return; + + _manager_unref_uid(u->manager, *ref_uid, destroy_now); + *ref_uid = UID_INVALID; +} + +void unit_unref_uid(Unit *u, bool destroy_now) { + unit_unref_uid_internal(u, &u->ref_uid, destroy_now, manager_unref_uid); +} + +void unit_unref_gid(Unit *u, bool destroy_now) { + unit_unref_uid_internal(u, (uid_t*) &u->ref_gid, destroy_now, manager_unref_gid); +} + +static int unit_ref_uid_internal( + Unit *u, + uid_t *ref_uid, + uid_t uid, + bool clean_ipc, + int (*_manager_ref_uid)(Manager *m, uid_t uid, bool clean_ipc)) { + + int r; + + assert(u); + assert(ref_uid); + assert(uid_is_valid(uid)); + assert(_manager_ref_uid); + + /* Generic implementation of both unit_ref_uid() and unit_ref_guid(), under the assumption that uid_t and gid_t + * are actually the same type, and have the same validity rules. + * + * Adds a reference on a specific UID/GID to this unit. Each unit referencing the same UID/GID maintains a + * reference so that we can destroy the UID/GID's IPC resources as soon as this is requested and the counter + * drops to zero. */ + + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + assert_cc(UID_INVALID == (uid_t) GID_INVALID); + + if (*ref_uid == uid) + return 0; + + if (uid_is_valid(*ref_uid)) /* Already set? */ + return -EBUSY; + + r = _manager_ref_uid(u->manager, uid, clean_ipc); + if (r < 0) + return r; + + *ref_uid = uid; + return 1; +} + +int unit_ref_uid(Unit *u, uid_t uid, bool clean_ipc) { + return unit_ref_uid_internal(u, &u->ref_uid, uid, clean_ipc, manager_ref_uid); +} + +int unit_ref_gid(Unit *u, gid_t gid, bool clean_ipc) { + return unit_ref_uid_internal(u, (uid_t*) &u->ref_gid, (uid_t) gid, clean_ipc, manager_ref_gid); +} + +static int unit_ref_uid_gid_internal(Unit *u, uid_t uid, gid_t gid, bool clean_ipc) { + int r = 0, q = 0; + + assert(u); + + /* Reference both a UID and a GID in one go. Either references both, or neither. */ + + if (uid_is_valid(uid)) { + r = unit_ref_uid(u, uid, clean_ipc); + if (r < 0) + return r; + } + + if (gid_is_valid(gid)) { + q = unit_ref_gid(u, gid, clean_ipc); + if (q < 0) { + if (r > 0) + unit_unref_uid(u, false); + + return q; + } + } + + return r > 0 || q > 0; +} + +int unit_ref_uid_gid(Unit *u, uid_t uid, gid_t gid) { + ExecContext *c; + int r; + + assert(u); + + c = unit_get_exec_context(u); + + r = unit_ref_uid_gid_internal(u, uid, gid, c ? c->remove_ipc : false); + if (r < 0) + return log_unit_warning_errno(u, r, "Couldn't add UID/GID reference to unit, proceeding without: %m"); + + return r; +} + +void unit_unref_uid_gid(Unit *u, bool destroy_now) { + assert(u); + + unit_unref_uid(u, destroy_now); + unit_unref_gid(u, destroy_now); +} + +void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid) { + int r; + + assert(u); + + /* This is invoked whenever one of the forked off processes let's us know the UID/GID its user name/group names + * resolved to. We keep track of which UID/GID is currently assigned in order to be able to destroy its IPC + * objects when no service references the UID/GID anymore. */ + + r = unit_ref_uid_gid(u, uid, gid); + if (r > 0) + unit_add_to_dbus_queue(u); +} + +int unit_set_invocation_id(Unit *u, sd_id128_t id) { + int r; + + assert(u); + + /* Set the invocation ID for this unit. If we cannot, this will not roll back, but reset the whole thing. */ + + if (sd_id128_equal(u->invocation_id, id)) + return 0; + + if (!sd_id128_is_null(u->invocation_id)) + (void) hashmap_remove_value(u->manager->units_by_invocation_id, &u->invocation_id, u); + + if (sd_id128_is_null(id)) { + r = 0; + goto reset; + } + + r = hashmap_ensure_allocated(&u->manager->units_by_invocation_id, &id128_hash_ops); + if (r < 0) + goto reset; + + u->invocation_id = id; + sd_id128_to_string(id, u->invocation_id_string); + + r = hashmap_put(u->manager->units_by_invocation_id, &u->invocation_id, u); + if (r < 0) + goto reset; + + return 0; + +reset: + u->invocation_id = SD_ID128_NULL; + u->invocation_id_string[0] = 0; + return r; +} + +int unit_acquire_invocation_id(Unit *u) { + sd_id128_t id; + int r; + + assert(u); + + r = sd_id128_randomize(&id); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to generate invocation ID for unit: %m"); + + r = unit_set_invocation_id(u, id); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to set invocation ID for unit: %m"); + + unit_add_to_dbus_queue(u); + return 0; +} + +int unit_set_exec_params(Unit *u, ExecParameters *p) { + int r; + + assert(u); + assert(p); + + /* Copy parameters from manager */ + r = manager_get_effective_environment(u->manager, &p->environment); + if (r < 0) + return r; + + p->confirm_spawn = manager_get_confirm_spawn(u->manager); + p->cgroup_supported = u->manager->cgroup_supported; + p->prefix = u->manager->prefix; + SET_FLAG(p->flags, EXEC_PASS_LOG_UNIT|EXEC_CHOWN_DIRECTORIES, MANAGER_IS_SYSTEM(u->manager)); + + /* Copy parameters from unit */ + p->cgroup_path = u->cgroup_path; + SET_FLAG(p->flags, EXEC_CGROUP_DELEGATE, unit_cgroup_delegate(u)); + + return 0; +} + +int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret) { + int r; + + assert(u); + assert(ret); + + /* Forks off a helper process and makes sure it is a member of the unit's cgroup. Returns == 0 in the child, + * and > 0 in the parent. The pid parameter is always filled in with the child's PID. */ + + (void) unit_realize_cgroup(u); + + r = safe_fork(name, FORK_REOPEN_LOG, ret); + if (r != 0) + return r; + + (void) default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1); + (void) ignore_signals(SIGPIPE, -1); + + (void) prctl(PR_SET_PDEATHSIG, SIGTERM); + + if (u->cgroup_path) { + r = cg_attach_everywhere(u->manager->cgroup_supported, u->cgroup_path, 0, NULL, NULL); + if (r < 0) { + log_unit_error_errno(u, r, "Failed to join unit cgroup %s: %m", u->cgroup_path); + _exit(EXIT_CGROUP); + } + } + + return 0; +} + +int unit_fork_and_watch_rm_rf(Unit *u, char **paths, pid_t *ret_pid) { + pid_t pid; + int r; + + assert(u); + assert(ret_pid); + + r = unit_fork_helper_process(u, "(sd-rmrf)", &pid); + if (r < 0) + return r; + if (r == 0) { + int ret = EXIT_SUCCESS; + char **i; + + STRV_FOREACH(i, paths) { + r = rm_rf(*i, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_MISSING_OK); + if (r < 0) { + log_error_errno(r, "Failed to remove '%s': %m", *i); + ret = EXIT_FAILURE; + } + } + + _exit(ret); + } + + r = unit_watch_pid(u, pid, true); + if (r < 0) + return r; + + *ret_pid = pid; + return 0; +} + +static void unit_update_dependency_mask(Unit *u, UnitDependency d, Unit *other, UnitDependencyInfo di) { + assert(u); + assert(d >= 0); + assert(d < _UNIT_DEPENDENCY_MAX); + assert(other); + + if (di.origin_mask == 0 && di.destination_mask == 0) { + /* No bit set anymore, let's drop the whole entry */ + assert_se(hashmap_remove(u->dependencies[d], other)); + log_unit_debug(u, "%s lost dependency %s=%s", u->id, unit_dependency_to_string(d), other->id); + } else + /* Mask was reduced, let's update the entry */ + assert_se(hashmap_update(u->dependencies[d], other, di.data) == 0); +} + +void unit_remove_dependencies(Unit *u, UnitDependencyMask mask) { + UnitDependency d; + + assert(u); + + /* Removes all dependencies u has on other units marked for ownership by 'mask'. */ + + if (mask == 0) + return; + + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) { + bool done; + + do { + UnitDependencyInfo di; + Unit *other; + Iterator i; + + done = true; + + HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d], i) { + UnitDependency q; + + if ((di.origin_mask & ~mask) == di.origin_mask) + continue; + di.origin_mask &= ~mask; + unit_update_dependency_mask(u, d, other, di); + + /* We updated the dependency from our unit to the other unit now. But most dependencies + * imply a reverse dependency. Hence, let's delete that one too. For that we go through + * all dependency types on the other unit and delete all those which point to us and + * have the right mask set. */ + + for (q = 0; q < _UNIT_DEPENDENCY_MAX; q++) { + UnitDependencyInfo dj; + + dj.data = hashmap_get(other->dependencies[q], u); + if ((dj.destination_mask & ~mask) == dj.destination_mask) + continue; + dj.destination_mask &= ~mask; + + unit_update_dependency_mask(other, q, u, dj); + } + + unit_add_to_gc_queue(other); + + done = false; + break; + } + + } while (!done); + } +} + +static int unit_export_invocation_id(Unit *u) { + const char *p; + int r; + + assert(u); + + if (u->exported_invocation_id) + return 0; + + if (sd_id128_is_null(u->invocation_id)) + return 0; + + p = strjoina("/run/systemd/units/invocation:", u->id); + r = symlink_atomic(u->invocation_id_string, p); + if (r < 0) + return log_unit_debug_errno(u, r, "Failed to create invocation ID symlink %s: %m", p); + + u->exported_invocation_id = true; + return 0; +} + +static int unit_export_log_level_max(Unit *u, const ExecContext *c) { + const char *p; + char buf[2]; + int r; + + assert(u); + assert(c); + + if (u->exported_log_level_max) + return 0; + + if (c->log_level_max < 0) + return 0; + + assert(c->log_level_max <= 7); + + buf[0] = '0' + c->log_level_max; + buf[1] = 0; + + p = strjoina("/run/systemd/units/log-level-max:", u->id); + r = symlink_atomic(buf, p); + if (r < 0) + return log_unit_debug_errno(u, r, "Failed to create maximum log level symlink %s: %m", p); + + u->exported_log_level_max = true; + return 0; +} + +static int unit_export_log_extra_fields(Unit *u, const ExecContext *c) { + _cleanup_close_ int fd = -1; + struct iovec *iovec; + const char *p; + char *pattern; + le64_t *sizes; + ssize_t n; + size_t i; + int r; + + if (u->exported_log_extra_fields) + return 0; + + if (c->n_log_extra_fields <= 0) + return 0; + + sizes = newa(le64_t, c->n_log_extra_fields); + iovec = newa(struct iovec, c->n_log_extra_fields * 2); + + for (i = 0; i < c->n_log_extra_fields; i++) { + sizes[i] = htole64(c->log_extra_fields[i].iov_len); + + iovec[i*2] = IOVEC_MAKE(sizes + i, sizeof(le64_t)); + iovec[i*2+1] = c->log_extra_fields[i]; + } + + p = strjoina("/run/systemd/units/log-extra-fields:", u->id); + pattern = strjoina(p, ".XXXXXX"); + + fd = mkostemp_safe(pattern); + if (fd < 0) + return log_unit_debug_errno(u, fd, "Failed to create extra fields file %s: %m", p); + + n = writev(fd, iovec, c->n_log_extra_fields*2); + if (n < 0) { + r = log_unit_debug_errno(u, errno, "Failed to write extra fields: %m"); + goto fail; + } + + (void) fchmod(fd, 0644); + + if (rename(pattern, p) < 0) { + r = log_unit_debug_errno(u, errno, "Failed to rename extra fields file: %m"); + goto fail; + } + + u->exported_log_extra_fields = true; + return 0; + +fail: + (void) unlink(pattern); + return r; +} + +static int unit_export_log_ratelimit_interval(Unit *u, const ExecContext *c) { + _cleanup_free_ char *buf = NULL; + const char *p; + int r; + + assert(u); + assert(c); + + if (u->exported_log_ratelimit_interval) + return 0; + + if (c->log_ratelimit_interval_usec == 0) + return 0; + + p = strjoina("/run/systemd/units/log-rate-limit-interval:", u->id); + + if (asprintf(&buf, "%" PRIu64, c->log_ratelimit_interval_usec) < 0) + return log_oom(); + + r = symlink_atomic(buf, p); + if (r < 0) + return log_unit_debug_errno(u, r, "Failed to create log rate limit interval symlink %s: %m", p); + + u->exported_log_ratelimit_interval = true; + return 0; +} + +static int unit_export_log_ratelimit_burst(Unit *u, const ExecContext *c) { + _cleanup_free_ char *buf = NULL; + const char *p; + int r; + + assert(u); + assert(c); + + if (u->exported_log_ratelimit_burst) + return 0; + + if (c->log_ratelimit_burst == 0) + return 0; + + p = strjoina("/run/systemd/units/log-rate-limit-burst:", u->id); + + if (asprintf(&buf, "%u", c->log_ratelimit_burst) < 0) + return log_oom(); + + r = symlink_atomic(buf, p); + if (r < 0) + return log_unit_debug_errno(u, r, "Failed to create log rate limit burst symlink %s: %m", p); + + u->exported_log_ratelimit_burst = true; + return 0; +} + +void unit_export_state_files(Unit *u) { + const ExecContext *c; + + assert(u); + + if (!u->id) + return; + + if (!MANAGER_IS_SYSTEM(u->manager)) + return; + + if (MANAGER_IS_TEST_RUN(u->manager)) + return; + + /* Exports a couple of unit properties to /run/systemd/units/, so that journald can quickly query this data + * from there. Ideally, journald would use IPC to query this, like everybody else, but that's hard, as long as + * the IPC system itself and PID 1 also log to the journal. + * + * Note that these files really shouldn't be considered API for anyone else, as use a runtime file system as + * IPC replacement is not compatible with today's world of file system namespaces. However, this doesn't really + * apply to communication between the journal and systemd, as we assume that these two daemons live in the same + * namespace at least. + * + * Note that some of the "files" exported here are actually symlinks and not regular files. Symlinks work + * better for storing small bits of data, in particular as we can write them with two system calls, and read + * them with one. */ + + (void) unit_export_invocation_id(u); + + c = unit_get_exec_context(u); + if (c) { + (void) unit_export_log_level_max(u, c); + (void) unit_export_log_extra_fields(u, c); + (void) unit_export_log_ratelimit_interval(u, c); + (void) unit_export_log_ratelimit_burst(u, c); + } +} + +void unit_unlink_state_files(Unit *u) { + const char *p; + + assert(u); + + if (!u->id) + return; + + if (!MANAGER_IS_SYSTEM(u->manager)) + return; + + /* Undoes the effect of unit_export_state() */ + + if (u->exported_invocation_id) { + p = strjoina("/run/systemd/units/invocation:", u->id); + (void) unlink(p); + + u->exported_invocation_id = false; + } + + if (u->exported_log_level_max) { + p = strjoina("/run/systemd/units/log-level-max:", u->id); + (void) unlink(p); + + u->exported_log_level_max = false; + } + + if (u->exported_log_extra_fields) { + p = strjoina("/run/systemd/units/extra-fields:", u->id); + (void) unlink(p); + + u->exported_log_extra_fields = false; + } + + if (u->exported_log_ratelimit_interval) { + p = strjoina("/run/systemd/units/log-rate-limit-interval:", u->id); + (void) unlink(p); + + u->exported_log_ratelimit_interval = false; + } + + if (u->exported_log_ratelimit_burst) { + p = strjoina("/run/systemd/units/log-rate-limit-burst:", u->id); + (void) unlink(p); + + u->exported_log_ratelimit_burst = false; + } +} + +int unit_prepare_exec(Unit *u) { + int r; + + assert(u); + + /* Load any custom firewall BPF programs here once to test if they are existing and actually loadable. + * Fail here early since later errors in the call chain unit_realize_cgroup to cgroup_context_apply are ignored. */ + r = bpf_firewall_load_custom(u); + if (r < 0) + return r; + + /* Prepares everything so that we can fork of a process for this unit */ + + (void) unit_realize_cgroup(u); + + if (u->reset_accounting) { + (void) unit_reset_accounting(u); + u->reset_accounting = false; + } + + unit_export_state_files(u); + + r = unit_setup_exec_runtime(u); + if (r < 0) + return r; + + r = unit_setup_dynamic_creds(u); + if (r < 0) + return r; + + return 0; +} + +static int log_leftover(pid_t pid, int sig, void *userdata) { + _cleanup_free_ char *comm = NULL; + + (void) get_process_comm(pid, &comm); + + if (comm && comm[0] == '(') /* Most likely our own helper process (PAM?), ignore */ + return 0; + + log_unit_warning(userdata, + "Found left-over process " PID_FMT " (%s) in control group while starting unit. Ignoring.\n" + "This usually indicates unclean termination of a previous run, or service implementation deficiencies.", + pid, strna(comm)); + + return 1; +} + +int unit_warn_leftover_processes(Unit *u) { + assert(u); + + (void) unit_pick_cgroup_path(u); + + if (!u->cgroup_path) + return 0; + + return cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, 0, 0, NULL, log_leftover, u); +} + +bool unit_needs_console(Unit *u) { + ExecContext *ec; + UnitActiveState state; + + assert(u); + + state = unit_active_state(u); + + if (UNIT_IS_INACTIVE_OR_FAILED(state)) + return false; + + if (UNIT_VTABLE(u)->needs_console) + return UNIT_VTABLE(u)->needs_console(u); + + /* If this unit type doesn't implement this call, let's use a generic fallback implementation: */ + ec = unit_get_exec_context(u); + if (!ec) + return false; + + return exec_context_may_touch_console(ec); +} + +const char *unit_label_path(Unit *u) { + const char *p; + + /* Returns the file system path to use for MAC access decisions, i.e. the file to read the SELinux label off + * when validating access checks. */ + + p = u->source_path ?: u->fragment_path; + if (!p) + return NULL; + + /* If a unit is masked, then don't read the SELinux label of /dev/null, as that really makes no sense */ + if (path_equal(p, "/dev/null")) + return NULL; + + return p; +} + +int unit_pid_attachable(Unit *u, pid_t pid, sd_bus_error *error) { + int r; + + assert(u); + + /* Checks whether the specified PID is generally good for attaching, i.e. a valid PID, not our manager itself, + * and not a kernel thread either */ + + /* First, a simple range check */ + if (!pid_is_valid(pid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process identifier " PID_FMT " is not valid.", pid); + + /* Some extra safety check */ + if (pid == 1 || pid == getpid_cached()) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process " PID_FMT " is a manager process, refusing.", pid); + + /* Don't even begin to bother with kernel threads */ + r = is_kernel_thread(pid); + if (r == -ESRCH) + return sd_bus_error_setf(error, SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, "Process with ID " PID_FMT " does not exist.", pid); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to determine whether process " PID_FMT " is a kernel thread: %m", pid); + if (r > 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process " PID_FMT " is a kernel thread, refusing.", pid); + + return 0; +} + +void unit_log_success(Unit *u) { + assert(u); + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_UNIT_SUCCESS_STR, + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u), + LOG_UNIT_MESSAGE(u, "Succeeded.")); +} + +void unit_log_failure(Unit *u, const char *result) { + assert(u); + assert(result); + + log_struct(LOG_WARNING, + "MESSAGE_ID=" SD_MESSAGE_UNIT_FAILURE_RESULT_STR, + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u), + LOG_UNIT_MESSAGE(u, "Failed with result '%s'.", result), + "UNIT_RESULT=%s", result); +} + +void unit_log_skip(Unit *u, const char *result) { + assert(u); + assert(result); + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_UNIT_SKIPPED_STR, + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u), + LOG_UNIT_MESSAGE(u, "Skipped due to '%s'.", result), + "UNIT_RESULT=%s", result); +} + +void unit_log_process_exit( + Unit *u, + const char *kind, + const char *command, + bool success, + int code, + int status) { + + int level; + + assert(u); + assert(kind); + + /* If this is a successful exit, let's log about the exit code on DEBUG level. If this is a failure + * and the process exited on its own via exit(), then let's make this a NOTICE, under the assumption + * that the service already logged the reason at a higher log level on its own. Otherwise, make it a + * WARNING. */ + if (success) + level = LOG_DEBUG; + else if (code == CLD_EXITED) + level = LOG_NOTICE; + else + level = LOG_WARNING; + + log_struct(level, + "MESSAGE_ID=" SD_MESSAGE_UNIT_PROCESS_EXIT_STR, + LOG_UNIT_MESSAGE(u, "%s exited, code=%s, status=%i/%s", + kind, + sigchld_code_to_string(code), status, + strna(code == CLD_EXITED + ? exit_status_to_string(status, EXIT_STATUS_FULL) + : signal_to_string(status))), + "EXIT_CODE=%s", sigchld_code_to_string(code), + "EXIT_STATUS=%i", status, + "COMMAND=%s", strna(command), + LOG_UNIT_ID(u), + LOG_UNIT_INVOCATION_ID(u)); +} + +int unit_exit_status(Unit *u) { + assert(u); + + /* Returns the exit status to propagate for the most recent cycle of this unit. Returns a value in the range + * 0…255 if there's something to propagate. EOPNOTSUPP if the concept does not apply to this unit type, ENODATA + * if no data is currently known (for example because the unit hasn't deactivated yet) and EBADE if the main + * service process has exited abnormally (signal/coredump). */ + + if (!UNIT_VTABLE(u)->exit_status) + return -EOPNOTSUPP; + + return UNIT_VTABLE(u)->exit_status(u); +} + +int unit_failure_action_exit_status(Unit *u) { + int r; + + assert(u); + + /* Returns the exit status to propagate on failure, or an error if there's nothing to propagate */ + + if (u->failure_action_exit_status >= 0) + return u->failure_action_exit_status; + + r = unit_exit_status(u); + if (r == -EBADE) /* Exited, but not cleanly (i.e. by signal or such) */ + return 255; + + return r; +} + +int unit_success_action_exit_status(Unit *u) { + int r; + + assert(u); + + /* Returns the exit status to propagate on success, or an error if there's nothing to propagate */ + + if (u->success_action_exit_status >= 0) + return u->success_action_exit_status; + + r = unit_exit_status(u); + if (r == -EBADE) /* Exited, but not cleanly (i.e. by signal or such) */ + return 255; + + return r; +} + +int unit_test_trigger_loaded(Unit *u) { + Unit *trigger; + + /* Tests whether the unit to trigger is loaded */ + + trigger = UNIT_TRIGGER(u); + if (!trigger) + return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOENT), + "Refusing to start, no unit to trigger."); + if (trigger->load_state != UNIT_LOADED) + return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOENT), + "Refusing to start, unit %s to trigger not loaded.", trigger->id); + + return 0; +} + +void unit_destroy_runtime_directory(Unit *u, const ExecContext *context) { + if (context->runtime_directory_preserve_mode == EXEC_PRESERVE_NO || + (context->runtime_directory_preserve_mode == EXEC_PRESERVE_RESTART && !unit_will_restart(u))) + exec_context_destroy_runtime_directory(context, u->manager->prefix[EXEC_DIRECTORY_RUNTIME]); +} + +int unit_clean(Unit *u, ExecCleanMask mask) { + UnitActiveState state; + + assert(u); + + /* Special return values: + * + * -EOPNOTSUPP → cleaning not supported for this unit type + * -EUNATCH → cleaning not defined for this resource type + * -EBUSY → unit currently can't be cleaned since it's running or not properly loaded, or has + * a job queued or similar + */ + + if (!UNIT_VTABLE(u)->clean) + return -EOPNOTSUPP; + + if (mask == 0) + return -EUNATCH; + + if (u->load_state != UNIT_LOADED) + return -EBUSY; + + if (u->job) + return -EBUSY; + + state = unit_active_state(u); + if (!IN_SET(state, UNIT_INACTIVE)) + return -EBUSY; + + return UNIT_VTABLE(u)->clean(u, mask); +} + +int unit_can_clean(Unit *u, ExecCleanMask *ret) { + assert(u); + + if (!UNIT_VTABLE(u)->clean || + u->load_state != UNIT_LOADED) { + *ret = 0; + return 0; + } + + /* When the clean() method is set, can_clean() really should be set too */ + assert(UNIT_VTABLE(u)->can_clean); + + return UNIT_VTABLE(u)->can_clean(u, ret); +} + +static const char* const collect_mode_table[_COLLECT_MODE_MAX] = { + [COLLECT_INACTIVE] = "inactive", + [COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed", +}; + +DEFINE_STRING_TABLE_LOOKUP(collect_mode, CollectMode); diff --git a/src/core/unit.h b/src/core/unit.h new file mode 100644 index 00000000..c5d8170c --- /dev/null +++ b/src/core/unit.h @@ -0,0 +1,899 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "bpf-program.h" +#include "condition.h" +#include "emergency-action.h" +#include "list.h" +#include "set.h" +#include "unit-file.h" +#include "cgroup.h" + +typedef struct UnitRef UnitRef; + +typedef enum KillOperation { + KILL_TERMINATE, + KILL_TERMINATE_AND_LOG, + KILL_RESTART, + KILL_KILL, + KILL_WATCHDOG, + _KILL_OPERATION_MAX, + _KILL_OPERATION_INVALID = -1 +} KillOperation; + +typedef enum CollectMode { + COLLECT_INACTIVE, + COLLECT_INACTIVE_OR_FAILED, + _COLLECT_MODE_MAX, + _COLLECT_MODE_INVALID = -1, +} CollectMode; + +static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) { + return IN_SET(t, UNIT_ACTIVE, UNIT_RELOADING); +} + +static inline bool UNIT_IS_ACTIVE_OR_ACTIVATING(UnitActiveState t) { + return IN_SET(t, UNIT_ACTIVE, UNIT_ACTIVATING, UNIT_RELOADING); +} + +static inline bool UNIT_IS_INACTIVE_OR_DEACTIVATING(UnitActiveState t) { + return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED, UNIT_DEACTIVATING); +} + +static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) { + return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED); +} + +/* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We + * use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be + * created as a result of multiple "reasons", hence the bitmask. */ +typedef enum UnitDependencyMask { + /* Configured directly by the unit file, .wants/.requires symlink or drop-in, or as an immediate result of a + * non-dependency option configured that way. */ + UNIT_DEPENDENCY_FILE = 1 << 0, + + /* As unconditional implicit dependency (not affected by unit configuration — except by the unit name and + * type) */ + UNIT_DEPENDENCY_IMPLICIT = 1 << 1, + + /* A dependency effected by DefaultDependencies=yes. Note that dependencies marked this way are conceptually + * just a subset of UNIT_DEPENDENCY_FILE, as DefaultDependencies= is itself a unit file setting that can only + * be set in unit files. We make this two separate bits only to help debugging how dependencies came to be. */ + UNIT_DEPENDENCY_DEFAULT = 1 << 2, + + /* A dependency created from udev rules */ + UNIT_DEPENDENCY_UDEV = 1 << 3, + + /* A dependency created because of some unit's RequiresMountsFor= setting */ + UNIT_DEPENDENCY_PATH = 1 << 4, + + /* A dependency created because of data read from /proc/self/mountinfo and no other configuration source */ + UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT = 1 << 5, + + /* A dependency created because of data read from /proc/self/mountinfo, but conditionalized by + * DefaultDependencies= and thus also involving configuration from UNIT_DEPENDENCY_FILE sources */ + UNIT_DEPENDENCY_MOUNTINFO_DEFAULT = 1 << 6, + + /* A dependency created because of data read from /proc/swaps and no other configuration source */ + UNIT_DEPENDENCY_PROC_SWAP = 1 << 7, + + _UNIT_DEPENDENCY_MASK_FULL = (1 << 8) - 1, +} UnitDependencyMask; + +/* The Unit's dependencies[] hashmaps use this structure as value. It has the same size as a void pointer, and thus can + * be stored directly as hashmap value, without any indirection. Note that this stores two masks, as both the origin + * and the destination of a dependency might have created it. */ +typedef union UnitDependencyInfo { + void *data; + struct { + UnitDependencyMask origin_mask:16; + UnitDependencyMask destination_mask:16; + } _packed_; +} UnitDependencyInfo; + +#include "job.h" + +struct UnitRef { + /* Keeps tracks of references to a unit. This is useful so + * that we can merge two units if necessary and correct all + * references to them */ + + Unit *source, *target; + LIST_FIELDS(UnitRef, refs_by_target); +}; + +typedef struct Unit { + Manager *manager; + + UnitType type; + UnitLoadState load_state; + Unit *merged_into; + + char *id; /* One name is special because we use it for identification. Points to an entry in the names set */ + char *instance; + + Set *names; + + /* For each dependency type we maintain a Hashmap whose key is the Unit* object, and the value encodes why the + * dependency exists, using the UnitDependencyInfo type */ + Hashmap *dependencies[_UNIT_DEPENDENCY_MAX]; + + /* Similar, for RequiresMountsFor= path dependencies. The key is the path, the value the UnitDependencyInfo type */ + Hashmap *requires_mounts_for; + + char *description; + char **documentation; + + char *fragment_path; /* if loaded from a config file this is the primary path to it */ + char *source_path; /* if converted, the source file */ + char **dropin_paths; + + usec_t fragment_mtime; + usec_t source_mtime; + usec_t dropin_mtime; + + /* If this is a transient unit we are currently writing, this is where we are writing it to */ + FILE *transient_file; + + /* If there is something to do with this unit, then this is the installed job for it */ + Job *job; + + /* JOB_NOP jobs are special and can be installed without disturbing the real job. */ + Job *nop_job; + + /* The slot used for watching NameOwnerChanged signals */ + sd_bus_slot *match_bus_slot; + sd_bus_slot *get_name_owner_slot; + + /* References to this unit from clients */ + sd_bus_track *bus_track; + char **deserialized_refs; + + /* Job timeout and action to take */ + usec_t job_timeout; + usec_t job_running_timeout; + bool job_running_timeout_set:1; + EmergencyAction job_timeout_action; + char *job_timeout_reboot_arg; + + /* References to this */ + LIST_HEAD(UnitRef, refs_by_target); + + /* Conditions to check */ + LIST_HEAD(Condition, conditions); + LIST_HEAD(Condition, asserts); + + dual_timestamp condition_timestamp; + dual_timestamp assert_timestamp; + + /* Updated whenever the low-level state changes */ + dual_timestamp state_change_timestamp; + + /* Updated whenever the (high-level) active state enters or leaves the active or inactive states */ + dual_timestamp inactive_exit_timestamp; + dual_timestamp active_enter_timestamp; + dual_timestamp active_exit_timestamp; + dual_timestamp inactive_enter_timestamp; + + UnitRef slice; + + /* Per type list */ + LIST_FIELDS(Unit, units_by_type); + + /* Load queue */ + LIST_FIELDS(Unit, load_queue); + + /* D-Bus queue */ + LIST_FIELDS(Unit, dbus_queue); + + /* Cleanup queue */ + LIST_FIELDS(Unit, cleanup_queue); + + /* GC queue */ + LIST_FIELDS(Unit, gc_queue); + + /* CGroup realize members queue */ + LIST_FIELDS(Unit, cgroup_realize_queue); + + /* cgroup empty queue */ + LIST_FIELDS(Unit, cgroup_empty_queue); + + /* cgroup OOM queue */ + LIST_FIELDS(Unit, cgroup_oom_queue); + + /* Target dependencies queue */ + LIST_FIELDS(Unit, target_deps_queue); + + /* Queue of units with StopWhenUnneeded set that shell be checked for clean-up. */ + LIST_FIELDS(Unit, stop_when_unneeded_queue); + + /* PIDs we keep an eye on. Note that a unit might have many + * more, but these are the ones we care enough about to + * process SIGCHLD for */ + Set *pids; + + /* Used in SIGCHLD and sd_notify() message event invocation logic to avoid that we dispatch the same event + * multiple times on the same unit. */ + unsigned sigchldgen; + unsigned notifygen; + + /* Used during GC sweeps */ + unsigned gc_marker; + + /* Error code when we didn't manage to load the unit (negative) */ + int load_error; + + /* Put a ratelimit on unit starting */ + RateLimit start_ratelimit; + EmergencyAction start_limit_action; + + /* What to do on failure or success */ + EmergencyAction success_action, failure_action; + int success_action_exit_status, failure_action_exit_status; + char *reboot_arg; + + /* Make sure we never enter endless loops with the check unneeded logic, or the BindsTo= logic */ + RateLimit auto_stop_ratelimit; + + /* Reference to a specific UID/GID */ + uid_t ref_uid; + gid_t ref_gid; + + /* Cached unit file state and preset */ + UnitFileState unit_file_state; + int unit_file_preset; + + /* Where the cpu.stat or cpuacct.usage was at the time the unit was started */ + nsec_t cpu_usage_base; + nsec_t cpu_usage_last; /* the most recently read value */ + + /* The current counter of the oom_kill field in the memory.events cgroup attribute */ + uint64_t oom_kill_last; + + /* Where the io.stat data was at the time the unit was started */ + uint64_t io_accounting_base[_CGROUP_IO_ACCOUNTING_METRIC_MAX]; + uint64_t io_accounting_last[_CGROUP_IO_ACCOUNTING_METRIC_MAX]; /* the most recently read value */ + + /* Counterparts in the cgroup filesystem */ + char *cgroup_path; + CGroupMask cgroup_realized_mask; /* In which hierarchies does this unit's cgroup exist? (only relevant on cgroup v1) */ + CGroupMask cgroup_enabled_mask; /* Which controllers are enabled (or more correctly: enabled for the children) for this unit's cgroup? (only relevant on cgroup v2) */ + CGroupMask cgroup_invalidated_mask; /* A mask specifying controllers which shall be considered invalidated, and require re-realization */ + CGroupMask cgroup_members_mask; /* A cache for the controllers required by all children of this cgroup (only relevant for slice units) */ + + /* Inotify watch descriptors for watching cgroup.events and memory.events on cgroupv2 */ + int cgroup_control_inotify_wd; + int cgroup_memory_inotify_wd; + + /* Device Controller BPF program */ + BPFProgram *bpf_device_control_installed; + + /* IP BPF Firewalling/accounting */ + int ip_accounting_ingress_map_fd; + int ip_accounting_egress_map_fd; + + int ipv4_allow_map_fd; + int ipv6_allow_map_fd; + int ipv4_deny_map_fd; + int ipv6_deny_map_fd; + + BPFProgram *ip_bpf_ingress, *ip_bpf_ingress_installed; + BPFProgram *ip_bpf_egress, *ip_bpf_egress_installed; + Set *ip_bpf_custom_ingress; + Set *ip_bpf_custom_ingress_installed; + Set *ip_bpf_custom_egress; + Set *ip_bpf_custom_egress_installed; + + uint64_t ip_accounting_extra[_CGROUP_IP_ACCOUNTING_METRIC_MAX]; + + /* Low-priority event source which is used to remove watched PIDs that have gone away, and subscribe to any new + * ones which might have appeared. */ + sd_event_source *rewatch_pids_event_source; + + /* How to start OnFailure units */ + JobMode on_failure_job_mode; + + /* Tweaking the GC logic */ + CollectMode collect_mode; + + /* The current invocation ID */ + sd_id128_t invocation_id; + char invocation_id_string[SD_ID128_STRING_MAX]; /* useful when logging */ + + /* Garbage collect us we nobody wants or requires us anymore */ + bool stop_when_unneeded; + + /* Create default dependencies */ + bool default_dependencies; + + /* Refuse manual starting, allow starting only indirectly via dependency. */ + bool refuse_manual_start; + + /* Don't allow the user to stop this unit manually, allow stopping only indirectly via dependency. */ + bool refuse_manual_stop; + + /* Allow isolation requests */ + bool allow_isolate; + + /* Ignore this unit when isolating */ + bool ignore_on_isolate; + + /* Did the last condition check succeed? */ + bool condition_result; + bool assert_result; + + /* Is this a transient unit? */ + bool transient; + + /* Is this a unit that is always running and cannot be stopped? */ + bool perpetual; + + /* Booleans indicating membership of this unit in the various queues */ + bool in_load_queue:1; + bool in_dbus_queue:1; + bool in_cleanup_queue:1; + bool in_gc_queue:1; + bool in_cgroup_realize_queue:1; + bool in_cgroup_empty_queue:1; + bool in_cgroup_oom_queue:1; + bool in_target_deps_queue:1; + bool in_stop_when_unneeded_queue:1; + + bool sent_dbus_new_signal:1; + + bool in_audit:1; + bool on_console:1; + + bool cgroup_realized:1; + bool cgroup_members_mask_valid:1; + + /* Reset cgroup accounting next time we fork something off */ + bool reset_accounting:1; + + bool start_limit_hit:1; + + /* Did we already invoke unit_coldplug() for this unit? */ + bool coldplugged:1; + + /* For transient units: whether to add a bus track reference after creating the unit */ + bool bus_track_add:1; + + /* Remember which unit state files we created */ + bool exported_invocation_id:1; + bool exported_log_level_max:1; + bool exported_log_extra_fields:1; + bool exported_log_ratelimit_interval:1; + bool exported_log_ratelimit_burst:1; + + /* Whether we warned about clamping the CPU quota period */ + bool warned_clamping_cpu_quota_period:1; + + /* When writing transient unit files, stores which section we stored last. If < 0, we didn't write any yet. If + * == 0 we are in the [Unit] section, if > 0 we are in the unit type-specific section. */ + signed int last_section_private:2; +} Unit; + +typedef struct UnitStatusMessageFormats { + const char *starting_stopping[2]; + const char *finished_start_job[_JOB_RESULT_MAX]; + const char *finished_stop_job[_JOB_RESULT_MAX]; +} UnitStatusMessageFormats; + +/* Flags used when writing drop-in files or transient unit files */ +typedef enum UnitWriteFlags { + /* Write a runtime unit file or drop-in (i.e. one below /run) */ + UNIT_RUNTIME = 1 << 0, + + /* Write a persistent drop-in (i.e. one below /etc) */ + UNIT_PERSISTENT = 1 << 1, + + /* Place this item in the per-unit-type private section, instead of [Unit] */ + UNIT_PRIVATE = 1 << 2, + + /* Apply specifier escaping before writing */ + UNIT_ESCAPE_SPECIFIERS = 1 << 3, + + /* Apply C escaping before writing */ + UNIT_ESCAPE_C = 1 << 4, +} UnitWriteFlags; + +/* Returns true if neither persistent, nor runtime storage is requested, i.e. this is a check invocation only */ +static inline bool UNIT_WRITE_FLAGS_NOOP(UnitWriteFlags flags) { + return (flags & (UNIT_RUNTIME|UNIT_PERSISTENT)) == 0; +} + +#include "kill.h" + +typedef struct UnitVTable { + /* How much memory does an object of this unit type need */ + size_t object_size; + + /* If greater than 0, the offset into the object where + * ExecContext is found, if the unit type has that */ + size_t exec_context_offset; + + /* If greater than 0, the offset into the object where + * CGroupContext is found, if the unit type has that */ + size_t cgroup_context_offset; + + /* If greater than 0, the offset into the object where + * KillContext is found, if the unit type has that */ + size_t kill_context_offset; + + /* If greater than 0, the offset into the object where the + * pointer to ExecRuntime is found, if the unit type has + * that */ + size_t exec_runtime_offset; + + /* If greater than 0, the offset into the object where the pointer to DynamicCreds is found, if the unit type + * has that. */ + size_t dynamic_creds_offset; + + /* The name of the configuration file section with the private settings of this unit */ + const char *private_section; + + /* Config file sections this unit type understands, separated + * by NUL chars */ + const char *sections; + + /* This should reset all type-specific variables. This should + * not allocate memory, and is called with zero-initialized + * data. It should hence only initialize variables that need + * to be set != 0. */ + void (*init)(Unit *u); + + /* This should free all type-specific variables. It should be + * idempotent. */ + void (*done)(Unit *u); + + /* Actually load data from disk. This may fail, and should set + * load_state to UNIT_LOADED, UNIT_MERGED or leave it at + * UNIT_STUB if no configuration could be found. */ + int (*load)(Unit *u); + + /* During deserialization we only record the intended state to return to. With coldplug() we actually put the + * deserialized state in effect. This is where unit_notify() should be called to start things up. Note that + * this callback is invoked *before* we leave the reloading state of the manager, i.e. *before* we consider the + * reloading to be complete. Thus, this callback should just restore the exact same state for any unit that was + * in effect before the reload, i.e. units should not catch up with changes happened during the reload. That's + * what catchup() below is for. */ + int (*coldplug)(Unit *u); + + /* This is called shortly after all units' coldplug() call was invoked, and *after* the manager left the + * reloading state. It's supposed to catch up with state changes due to external events we missed so far (for + * example because they took place while we were reloading/reexecing) */ + void (*catchup)(Unit *u); + + void (*dump)(Unit *u, FILE *f, const char *prefix); + + int (*start)(Unit *u); + int (*stop)(Unit *u); + int (*reload)(Unit *u); + + int (*kill)(Unit *u, KillWho w, int signo, sd_bus_error *error); + + /* Clear out the various runtime/state/cache/logs/configuration data */ + int (*clean)(Unit *u, ExecCleanMask m); + + /* Return which kind of data can be cleaned */ + int (*can_clean)(Unit *u, ExecCleanMask *ret); + + bool (*can_reload)(Unit *u); + + /* Write all data that cannot be restored from other sources + * away using unit_serialize_item() */ + int (*serialize)(Unit *u, FILE *f, FDSet *fds); + + /* Restore one item from the serialization */ + int (*deserialize_item)(Unit *u, const char *key, const char *data, FDSet *fds); + + /* Try to match up fds with what we need for this unit */ + void (*distribute_fds)(Unit *u, FDSet *fds); + + /* Boils down the more complex internal state of this unit to + * a simpler one that the engine can understand */ + UnitActiveState (*active_state)(Unit *u); + + /* Returns the substate specific to this unit type as + * string. This is purely information so that we can give the + * user a more fine grained explanation in which actual state a + * unit is in. */ + const char* (*sub_state_to_string)(Unit *u); + + /* Additionally to UnitActiveState determine whether unit is to be restarted. */ + bool (*will_restart)(Unit *u); + + /* Return false when there is a reason to prevent this unit from being gc'ed + * even though nothing references it and it isn't active in any way. */ + bool (*may_gc)(Unit *u); + + /* When the unit is not running and no job for it queued we shall release its runtime resources */ + void (*release_resources)(Unit *u); + + /* Invoked on every child that died */ + void (*sigchld_event)(Unit *u, pid_t pid, int code, int status); + + /* Reset failed state if we are in failed state */ + void (*reset_failed)(Unit *u); + + /* Called whenever any of the cgroups this unit watches for ran empty */ + void (*notify_cgroup_empty)(Unit *u); + + /* Called whenever an OOM kill event on this unit was seen */ + void (*notify_cgroup_oom)(Unit *u); + + /* Called whenever a process of this unit sends us a message */ + void (*notify_message)(Unit *u, const struct ucred *ucred, char **tags, FDSet *fds); + + /* Called whenever a name this Unit registered for comes or goes away. */ + void (*bus_name_owner_change)(Unit *u, const char *old_owner, const char *new_owner); + + /* Called for each property that is being set */ + int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); + + /* Called after at least one property got changed to apply the necessary change */ + int (*bus_commit_properties)(Unit *u); + + /* Return the unit this unit is following */ + Unit *(*following)(Unit *u); + + /* Return the set of units that are following each other */ + int (*following_set)(Unit *u, Set **s); + + /* Invoked each time a unit this unit is triggering changes + * state or gains/loses a job */ + void (*trigger_notify)(Unit *u, Unit *trigger); + + /* Called whenever CLOCK_REALTIME made a jump */ + void (*time_change)(Unit *u); + + /* Called whenever /etc/localtime was modified */ + void (*timezone_change)(Unit *u); + + /* Returns the next timeout of a unit */ + int (*get_timeout)(Unit *u, usec_t *timeout); + + /* Returns the main PID if there is any defined, or 0. */ + pid_t (*main_pid)(Unit *u); + + /* Returns the main PID if there is any defined, or 0. */ + pid_t (*control_pid)(Unit *u); + + /* Returns true if the unit currently needs access to the console */ + bool (*needs_console)(Unit *u); + + /* Returns the exit status to propagate in case of FailureAction=exit/SuccessAction=exit; usually returns the + * exit code of the "main" process of the service or similar. */ + int (*exit_status)(Unit *u); + + /* Like the enumerate() callback further down, but only enumerates the perpetual units, i.e. all units that + * unconditionally exist and are always active. The main reason to keep both enumeration functions separate is + * philosophical: the state of perpetual units should be put in place by coldplug(), while the state of those + * discovered through regular enumeration should be put in place by catchup(), see below. */ + void (*enumerate_perpetual)(Manager *m); + + /* This is called for each unit type and should be used to enumerate units already existing in the system + * internally and load them. However, everything that is loaded here should still stay in inactive state. It is + * the job of the catchup() call above to put the units into the discovered state. */ + void (*enumerate)(Manager *m); + + /* Type specific cleanups. */ + void (*shutdown)(Manager *m); + + /* If this function is set and return false all jobs for units + * of this type will immediately fail. */ + bool (*supported)(void); + + /* The bus vtable */ + const sd_bus_vtable *bus_vtable; + + /* The strings to print in status messages */ + UnitStatusMessageFormats status_message_formats; + + /* True if transient units of this type are OK */ + bool can_transient:1; + + /* True if cgroup delegation is permissible */ + bool can_delegate:1; + + /* True if units of this type shall be startable only once and then never again */ + bool once_only:1; + + /* True if queued jobs of this type should be GC'ed if no other job needs them anymore */ + bool gc_jobs:1; +} UnitVTable; + +extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX]; + +static inline const UnitVTable* UNIT_VTABLE(Unit *u) { + return unit_vtable[u->type]; +} + +/* For casting a unit into the various unit types */ +#define DEFINE_CAST(UPPERCASE, MixedCase) \ + static inline MixedCase* UPPERCASE(Unit *u) { \ + if (_unlikely_(!u || u->type != UNIT_##UPPERCASE)) \ + return NULL; \ + \ + return (MixedCase*) u; \ + } + +/* For casting the various unit types into a unit */ +#define UNIT(u) \ + ({ \ + typeof(u) _u_ = (u); \ + Unit *_w_ = _u_ ? &(_u_)->meta : NULL; \ + _w_; \ + }) + +#define UNIT_HAS_EXEC_CONTEXT(u) (UNIT_VTABLE(u)->exec_context_offset > 0) +#define UNIT_HAS_CGROUP_CONTEXT(u) (UNIT_VTABLE(u)->cgroup_context_offset > 0) +#define UNIT_HAS_KILL_CONTEXT(u) (UNIT_VTABLE(u)->kill_context_offset > 0) + +static inline Unit* UNIT_TRIGGER(Unit *u) { + return hashmap_first_key(u->dependencies[UNIT_TRIGGERS]); +} + +Unit *unit_new(Manager *m, size_t size); +void unit_free(Unit *u); +DEFINE_TRIVIAL_CLEANUP_FUNC(Unit *, unit_free); + +int unit_new_for_name(Manager *m, size_t size, const char *name, Unit **ret); +int unit_add_name(Unit *u, const char *name); + +int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_reference, UnitDependencyMask mask); +int unit_add_two_dependencies(Unit *u, UnitDependency d, UnitDependency e, Unit *other, bool add_reference, UnitDependencyMask mask); + +int unit_add_dependency_by_name(Unit *u, UnitDependency d, const char *name, bool add_reference, UnitDependencyMask mask); +int unit_add_two_dependencies_by_name(Unit *u, UnitDependency d, UnitDependency e, const char *name, bool add_reference, UnitDependencyMask mask); + +int unit_add_exec_dependencies(Unit *u, ExecContext *c); + +int unit_choose_id(Unit *u, const char *name); +int unit_set_description(Unit *u, const char *description); + +bool unit_may_gc(Unit *u); + +void unit_add_to_load_queue(Unit *u); +void unit_add_to_dbus_queue(Unit *u); +void unit_add_to_cleanup_queue(Unit *u); +void unit_add_to_gc_queue(Unit *u); +void unit_add_to_target_deps_queue(Unit *u); +void unit_submit_to_stop_when_unneeded_queue(Unit *u); + +int unit_merge(Unit *u, Unit *other); +int unit_merge_by_name(Unit *u, const char *other); + +Unit *unit_follow_merge(Unit *u) _pure_; + +int unit_load_fragment_and_dropin(Unit *u, bool fragment_required); +int unit_load(Unit *unit); + +int unit_set_slice(Unit *u, Unit *slice); +int unit_set_default_slice(Unit *u); + +const char *unit_description(Unit *u) _pure_; +const char *unit_status_string(Unit *u) _pure_; + +bool unit_has_name(const Unit *u, const char *name); + +UnitActiveState unit_active_state(Unit *u); + +const char* unit_sub_state_to_string(Unit *u); + +void unit_dump(Unit *u, FILE *f, const char *prefix); + +bool unit_can_reload(Unit *u) _pure_; +bool unit_can_start(Unit *u) _pure_; +bool unit_can_stop(Unit *u) _pure_; +bool unit_can_isolate(Unit *u) _pure_; + +int unit_start(Unit *u); +int unit_stop(Unit *u); +int unit_reload(Unit *u); + +int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error); +int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, sd_bus_error *error); + +typedef enum UnitNotifyFlags { + UNIT_NOTIFY_RELOAD_FAILURE = 1 << 0, + UNIT_NOTIFY_WILL_AUTO_RESTART = 1 << 1, + UNIT_NOTIFY_SKIP_CONDITION = 1 << 2, +} UnitNotifyFlags; + +void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags); + +int unit_watch_pid(Unit *u, pid_t pid, bool exclusive); +void unit_unwatch_pid(Unit *u, pid_t pid); +void unit_unwatch_all_pids(Unit *u); + +int unit_enqueue_rewatch_pids(Unit *u); +void unit_dequeue_rewatch_pids(Unit *u); + +int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name); +int unit_watch_bus_name(Unit *u, const char *name); +void unit_unwatch_bus_name(Unit *u, const char *name); + +bool unit_job_is_applicable(Unit *u, JobType j); + +int set_unit_path(const char *p); + +char *unit_dbus_path(Unit *u); +char *unit_dbus_path_invocation_id(Unit *u); + +int unit_load_related_unit(Unit *u, const char *type, Unit **_found); + +bool unit_can_serialize(Unit *u) _pure_; + +int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs); +int unit_deserialize(Unit *u, FILE *f, FDSet *fds); +int unit_deserialize_skip(FILE *f); + +int unit_add_node_dependency(Unit *u, const char *what, UnitDependency d, UnitDependencyMask mask); + +int unit_coldplug(Unit *u); +void unit_catchup(Unit *u); + +void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) _printf_(3, 0); + +bool unit_need_daemon_reload(Unit *u); + +void unit_reset_failed(Unit *u); + +Unit *unit_following(Unit *u); +int unit_following_set(Unit *u, Set **s); + +const char *unit_slice_name(Unit *u); + +bool unit_stop_pending(Unit *u) _pure_; +bool unit_inactive_or_pending(Unit *u) _pure_; +bool unit_active_or_pending(Unit *u); +bool unit_will_restart_default(Unit *u); +bool unit_will_restart(Unit *u); + +int unit_add_default_target_dependency(Unit *u, Unit *target); + +void unit_start_on_failure(Unit *u); +void unit_trigger_notify(Unit *u); + +UnitFileState unit_get_unit_file_state(Unit *u); +int unit_get_unit_file_preset(Unit *u); + +Unit* unit_ref_set(UnitRef *ref, Unit *source, Unit *target); +void unit_ref_unset(UnitRef *ref); + +#define UNIT_DEREF(ref) ((ref).target) +#define UNIT_ISSET(ref) (!!(ref).target) + +int unit_patch_contexts(Unit *u); + +ExecContext *unit_get_exec_context(Unit *u) _pure_; +KillContext *unit_get_kill_context(Unit *u) _pure_; +CGroupContext *unit_get_cgroup_context(Unit *u) _pure_; + +ExecRuntime *unit_get_exec_runtime(Unit *u) _pure_; + +int unit_setup_exec_runtime(Unit *u); +int unit_setup_dynamic_creds(Unit *u); + +char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf); +char* unit_concat_strv(char **l, UnitWriteFlags flags); + +int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data); +int unit_write_settingf(Unit *u, UnitWriteFlags mode, const char *name, const char *format, ...) _printf_(4,5); + +int unit_kill_context(Unit *u, KillContext *c, KillOperation k, pid_t main_pid, pid_t control_pid, bool main_pid_alien); + +int unit_make_transient(Unit *u); + +int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask); + +bool unit_type_supported(UnitType t); + +bool unit_is_pristine(Unit *u); + +bool unit_is_unneeded(Unit *u); + +pid_t unit_control_pid(Unit *u); +pid_t unit_main_pid(Unit *u); + +void unit_warn_if_dir_nonempty(Unit *u, const char* where); +int unit_fail_if_noncanonical(Unit *u, const char* where); + +int unit_test_start_limit(Unit *u); + +void unit_unref_uid(Unit *u, bool destroy_now); +int unit_ref_uid(Unit *u, uid_t uid, bool clean_ipc); + +void unit_unref_gid(Unit *u, bool destroy_now); +int unit_ref_gid(Unit *u, gid_t gid, bool clean_ipc); + +int unit_ref_uid_gid(Unit *u, uid_t uid, gid_t gid); +void unit_unref_uid_gid(Unit *u, bool destroy_now); + +void unit_notify_user_lookup(Unit *u, uid_t uid, gid_t gid); + +int unit_set_invocation_id(Unit *u, sd_id128_t id); +int unit_acquire_invocation_id(Unit *u); + +bool unit_shall_confirm_spawn(Unit *u); + +int unit_set_exec_params(Unit *s, ExecParameters *p); + +int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret); +int unit_fork_and_watch_rm_rf(Unit *u, char **paths, pid_t *ret_pid); + +void unit_remove_dependencies(Unit *u, UnitDependencyMask mask); + +void unit_export_state_files(Unit *u); +void unit_unlink_state_files(Unit *u); + +int unit_prepare_exec(Unit *u); + +int unit_warn_leftover_processes(Unit *u); + +bool unit_needs_console(Unit *u); + +const char *unit_label_path(Unit *u); + +int unit_pid_attachable(Unit *unit, pid_t pid, sd_bus_error *error); + +static inline bool unit_has_job_type(Unit *u, JobType type) { + return u && u->job && u->job->type == type; +} + +/* unit_log_skip is for cases like ExecCondition= where a unit is considered "done" + * after some execution, rather than succeeded or failed. */ +void unit_log_skip(Unit *u, const char *result); +void unit_log_success(Unit *u); +void unit_log_failure(Unit *u, const char *result); +static inline void unit_log_result(Unit *u, bool success, const char *result) { + if (success) + unit_log_success(u); + else + unit_log_failure(u, result); +} + +void unit_log_process_exit(Unit *u, const char *kind, const char *command, bool success, int code, int status); + +int unit_exit_status(Unit *u); +int unit_success_action_exit_status(Unit *u); +int unit_failure_action_exit_status(Unit *u); + +int unit_test_trigger_loaded(Unit *u); + +void unit_destroy_runtime_directory(Unit *u, const ExecContext *context); +int unit_clean(Unit *u, ExecCleanMask mask); +int unit_can_clean(Unit *u, ExecCleanMask *ret_mask); + +/* Macros which append UNIT= or USER_UNIT= to the message */ + +#define log_unit_full(unit, level, error, ...) \ + ({ \ + const Unit *_u = (unit); \ + _u ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \ + log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ + }) + +#define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__) +#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, 0, ##__VA_ARGS__) +#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, 0, ##__VA_ARGS__) +#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, 0, ##__VA_ARGS__) +#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, 0, ##__VA_ARGS__) + +#define log_unit_debug_errno(unit, error, ...) log_unit_full(unit, LOG_DEBUG, error, ##__VA_ARGS__) +#define log_unit_info_errno(unit, error, ...) log_unit_full(unit, LOG_INFO, error, ##__VA_ARGS__) +#define log_unit_notice_errno(unit, error, ...) log_unit_full(unit, LOG_NOTICE, error, ##__VA_ARGS__) +#define log_unit_warning_errno(unit, error, ...) log_unit_full(unit, LOG_WARNING, error, ##__VA_ARGS__) +#define log_unit_error_errno(unit, error, ...) log_unit_full(unit, LOG_ERR, error, ##__VA_ARGS__) + +#define LOG_UNIT_MESSAGE(unit, fmt, ...) "MESSAGE=%s: " fmt, (unit)->id, ##__VA_ARGS__ +#define LOG_UNIT_ID(unit) (unit)->manager->unit_log_format_string, (unit)->id +#define LOG_UNIT_INVOCATION_ID(unit) (unit)->manager->invocation_log_format_string, (unit)->invocation_id_string + +const char* collect_mode_to_string(CollectMode m) _const_; +CollectMode collect_mode_from_string(const char *s) _pure_; diff --git a/src/core/user.conf.in b/src/core/user.conf.in new file mode 100644 index 00000000..95a162e0 --- /dev/null +++ b/src/core/user.conf.in @@ -0,0 +1,46 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# You can override the directives in this file by creating files in +# /etc/systemd/user.conf.d/*.conf. +# +# See systemd-user.conf(5) for details + +[Manager] +#LogLevel=info +#LogTarget=console +#LogColor=yes +#LogLocation=no +#SystemCallArchitectures= +#TimerSlackNSec= +#StatusUnitFormat=@STATUS_UNIT_FORMAT_DEFAULT@ +#DefaultTimerAccuracySec=1min +#DefaultStandardOutput=inherit +#DefaultStandardError=inherit +#DefaultTimeoutStartSec=90s +#DefaultTimeoutStopSec=90s +#DefaultTimeoutAbortSec= +#DefaultRestartSec=100ms +#DefaultStartLimitIntervalSec=10s +#DefaultStartLimitBurst=5 +#DefaultEnvironment= +#DefaultLimitCPU= +#DefaultLimitFSIZE= +#DefaultLimitDATA= +#DefaultLimitSTACK= +#DefaultLimitCORE= +#DefaultLimitRSS= +#DefaultLimitNOFILE= +#DefaultLimitAS= +#DefaultLimitNPROC= +#DefaultLimitMEMLOCK= +#DefaultLimitLOCKS= +#DefaultLimitSIGPENDING= +#DefaultLimitMSGQUEUE= +#DefaultLimitNICE= +#DefaultLimitRTPRIO= +#DefaultLimitRTTIME= diff --git a/src/coredump/coredump-vacuum.c b/src/coredump/coredump-vacuum.c new file mode 100644 index 00000000..35885dfb --- /dev/null +++ b/src/coredump/coredump-vacuum.c @@ -0,0 +1,248 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "coredump-vacuum.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "macro.h" +#include "memory-util.h" +#include "string-util.h" +#include "time-util.h" +#include "user-util.h" + +#define DEFAULT_MAX_USE_LOWER (uint64_t) (1ULL*1024ULL*1024ULL) /* 1 MiB */ +#define DEFAULT_MAX_USE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ +#define DEFAULT_KEEP_FREE_UPPER (uint64_t) (4ULL*1024ULL*1024ULL*1024ULL) /* 4 GiB */ +#define DEFAULT_KEEP_FREE (uint64_t) (1024ULL*1024ULL) /* 1 MB */ + +struct vacuum_candidate { + unsigned n_files; + char *oldest_file; + usec_t oldest_mtime; +}; + +static void vacuum_candidate_free(struct vacuum_candidate *c) { + if (!c) + return; + + free(c->oldest_file); + free(c); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct vacuum_candidate*, vacuum_candidate_free); + +static void vacuum_candidate_hashmap_free(Hashmap *h) { + hashmap_free_with_destructor(h, vacuum_candidate_free); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, vacuum_candidate_hashmap_free); + +static int uid_from_file_name(const char *filename, uid_t *uid) { + const char *p, *e, *u; + + p = startswith(filename, "core."); + if (!p) + return -EINVAL; + + /* Skip the comm field */ + p = strchr(p, '.'); + if (!p) + return -EINVAL; + p++; + + /* Find end up UID */ + e = strchr(p, '.'); + if (!e) + return -EINVAL; + + u = strndupa(p, e-p); + return parse_uid(u, uid); +} + +static bool vacuum_necessary(int fd, uint64_t sum, uint64_t keep_free, uint64_t max_use) { + uint64_t fs_size = 0, fs_free = (uint64_t) -1; + struct statvfs sv; + + assert(fd >= 0); + + if (fstatvfs(fd, &sv) >= 0) { + fs_size = sv.f_frsize * sv.f_blocks; + fs_free = sv.f_frsize * sv.f_bfree; + } + + if (max_use == (uint64_t) -1) { + + if (fs_size > 0) { + max_use = PAGE_ALIGN(fs_size / 10); /* 10% */ + + if (max_use > DEFAULT_MAX_USE_UPPER) + max_use = DEFAULT_MAX_USE_UPPER; + + if (max_use < DEFAULT_MAX_USE_LOWER) + max_use = DEFAULT_MAX_USE_LOWER; + } else + max_use = DEFAULT_MAX_USE_LOWER; + } else + max_use = PAGE_ALIGN(max_use); + + if (max_use > 0 && sum > max_use) + return true; + + if (keep_free == (uint64_t) -1) { + + if (fs_size > 0) { + keep_free = PAGE_ALIGN((fs_size * 3) / 20); /* 15% */ + + if (keep_free > DEFAULT_KEEP_FREE_UPPER) + keep_free = DEFAULT_KEEP_FREE_UPPER; + } else + keep_free = DEFAULT_KEEP_FREE; + } else + keep_free = PAGE_ALIGN(keep_free); + + if (keep_free > 0 && fs_free < keep_free) + return true; + + return false; +} + +int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use) { + _cleanup_closedir_ DIR *d = NULL; + struct stat exclude_st; + int r; + + if (keep_free == 0 && max_use == 0) + return 0; + + if (exclude_fd >= 0) { + if (fstat(exclude_fd, &exclude_st) < 0) + return log_error_errno(errno, "Failed to fstat(): %m"); + } + + /* This algorithm will keep deleting the oldest file of the + * user with the most coredumps until we are back in the size + * limits. Note that vacuuming for journal files is different, + * because we rely on rate-limiting of the messages there, + * to avoid being flooded. */ + + d = opendir("/var/lib/systemd/coredump"); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Can't open coredump directory: %m"); + } + + for (;;) { + _cleanup_(vacuum_candidate_hashmap_freep) Hashmap *h = NULL; + struct vacuum_candidate *worst = NULL; + struct dirent *de; + uint64_t sum = 0; + + rewinddir(d); + + FOREACH_DIRENT(de, d, goto fail) { + struct vacuum_candidate *c; + struct stat st; + uid_t uid; + usec_t t; + + r = uid_from_file_name(de->d_name, &uid); + if (r < 0) + continue; + + if (fstatat(dirfd(d), de->d_name, &st, AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW) < 0) { + if (errno == ENOENT) + continue; + + log_warning_errno(errno, "Failed to stat /var/lib/systemd/coredump/%s: %m", de->d_name); + continue; + } + + if (!S_ISREG(st.st_mode)) + continue; + + if (exclude_fd >= 0 && + exclude_st.st_dev == st.st_dev && + exclude_st.st_ino == st.st_ino) + continue; + + r = hashmap_ensure_allocated(&h, NULL); + if (r < 0) + return log_oom(); + + t = timespec_load(&st.st_mtim); + + c = hashmap_get(h, UID_TO_PTR(uid)); + if (c) { + + if (t < c->oldest_mtime) { + char *n; + + n = strdup(de->d_name); + if (!n) + return log_oom(); + + free(c->oldest_file); + c->oldest_file = n; + c->oldest_mtime = t; + } + + } else { + _cleanup_(vacuum_candidate_freep) struct vacuum_candidate *n = NULL; + + n = new0(struct vacuum_candidate, 1); + if (!n) + return log_oom(); + + n->oldest_file = strdup(de->d_name); + if (!n->oldest_file) + return log_oom(); + + n->oldest_mtime = t; + + r = hashmap_put(h, UID_TO_PTR(uid), n); + if (r < 0) + return log_oom(); + + c = TAKE_PTR(n); + } + + c->n_files++; + + if (!worst || + worst->n_files < c->n_files || + (worst->n_files == c->n_files && c->oldest_mtime < worst->oldest_mtime)) + worst = c; + + sum += st.st_blocks * 512; + } + + if (!worst) + break; + + r = vacuum_necessary(dirfd(d), sum, keep_free, max_use); + if (r <= 0) + return r; + + r = unlinkat_deallocate(dirfd(d), worst->oldest_file, 0); + if (r == -ENOENT) + continue; + if (r < 0) + return log_error_errno(r, "Failed to remove file %s: %m", worst->oldest_file); + + log_info("Removed old coredump %s.", worst->oldest_file); + } + + return 0; + +fail: + return log_error_errno(errno, "Failed to read directory: %m"); +} diff --git a/src/coredump/coredump-vacuum.h b/src/coredump/coredump-vacuum.h new file mode 100644 index 00000000..0db11673 --- /dev/null +++ b/src/coredump/coredump-vacuum.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +int coredump_vacuum(int exclude_fd, uint64_t keep_free, uint64_t max_use); diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c new file mode 100644 index 00000000..0e9a3c02 --- /dev/null +++ b/src/coredump/coredump.c @@ -0,0 +1,1354 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#if HAVE_ELFUTILS +#include +#include +#endif + +#include "sd-daemon.h" +#include "sd-journal.h" +#include "sd-login.h" +#include "sd-messages.h" + +#include "acl-util.h" +#include "alloc-util.h" +#include "capability-util.h" +#include "cgroup-util.h" +#include "compress.h" +#include "conf-parser.h" +#include "copy.h" +#include "coredump-vacuum.h" +#include "dirent-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "io-util.h" +#include "journal-importer.h" +#include "log.h" +#include "macro.h" +#include "main-func.h" +#include "memory-util.h" +#include "mkdir.h" +#include "parse-util.h" +#include "process-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "special.h" +#include "stacktrace.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "user-util.h" + +/* The maximum size up to which we process coredumps */ +#define PROCESS_SIZE_MAX ((uint64_t) (2LLU*1024LLU*1024LLU*1024LLU)) + +/* The maximum size up to which we leave the coredump around on disk */ +#define EXTERNAL_SIZE_MAX PROCESS_SIZE_MAX + +/* The maximum size up to which we store the coredump in the journal */ +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#define JOURNAL_SIZE_MAX ((size_t) (767LU*1024LU*1024LU)) +#else +/* oss-fuzz limits memory usage. */ +#define JOURNAL_SIZE_MAX ((size_t) (10LU*1024LU*1024LU)) +#endif + +/* Make sure to not make this larger than the maximum journal entry + * size. See DATA_SIZE_MAX in journal-importer.h. */ +assert_cc(JOURNAL_SIZE_MAX <= DATA_SIZE_MAX); + +enum { + /* We use these as array indexes for our process metadata cache. + * + * The first indices of the cache stores the same metadata as the ones passed by + * the kernel via argv[], ie the strings array passed by the kernel according to + * our pattern defined in /proc/sys/kernel/core_pattern (see man:core(5)). */ + + META_ARGV_PID, /* %P: as seen in the initial pid namespace */ + META_ARGV_UID, /* %u: as seen in the initial user namespace */ + META_ARGV_GID, /* %g: as seen in the initial user namespace */ + META_ARGV_SIGNAL, /* %s: number of signal causing dump */ + META_ARGV_TIMESTAMP, /* %t: time of dump, expressed as seconds since the Epoch */ + META_ARGV_RLIMIT, /* %c: core file size soft resource limit */ + META_ARGV_HOSTNAME, /* %h: hostname */ + _META_ARGV_MAX, + + /* The following indexes are cached for a couple of special fields we use (and + * thereby need to be retrieved quickly) for naming coredump files, and attaching + * xattrs. Unlike the previous ones they are retrieved from the runtime + * environment. */ + + META_COMM = _META_ARGV_MAX, + _META_MANDATORY_MAX, + + /* The rest are similar to the previous ones except that we won't fail if one of + * them is missing. */ + + META_EXE = _META_MANDATORY_MAX, + META_UNIT, + _META_MAX +}; + +static const char * const meta_field_names[_META_MAX] = { + [META_ARGV_PID] = "COREDUMP_PID=", + [META_ARGV_UID] = "COREDUMP_UID=", + [META_ARGV_GID] = "COREDUMP_GID=", + [META_ARGV_SIGNAL] = "COREDUMP_SIGNAL=", + [META_ARGV_TIMESTAMP] = "COREDUMP_TIMESTAMP=", + [META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=", + [META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=", + [META_COMM] = "COREDUMP_COMM=", + [META_EXE] = "COREDUMP_EXE=", + [META_UNIT] = "COREDUMP_UNIT=", +}; + +typedef struct Context { + const char *meta[_META_MAX]; + pid_t pid; + bool is_pid1; + bool is_journald; +} Context; + +typedef enum CoredumpStorage { + COREDUMP_STORAGE_NONE, + COREDUMP_STORAGE_EXTERNAL, + COREDUMP_STORAGE_JOURNAL, + _COREDUMP_STORAGE_MAX, + _COREDUMP_STORAGE_INVALID = -1 +} CoredumpStorage; + +static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = { + [COREDUMP_STORAGE_NONE] = "none", + [COREDUMP_STORAGE_EXTERNAL] = "external", + [COREDUMP_STORAGE_JOURNAL] = "journal", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage); +static DEFINE_CONFIG_PARSE_ENUM(config_parse_coredump_storage, coredump_storage, CoredumpStorage, "Failed to parse storage setting"); + +static CoredumpStorage arg_storage = COREDUMP_STORAGE_EXTERNAL; +static bool arg_compress = true; +static uint64_t arg_process_size_max = PROCESS_SIZE_MAX; +static uint64_t arg_external_size_max = EXTERNAL_SIZE_MAX; +static uint64_t arg_journal_size_max = JOURNAL_SIZE_MAX; +static uint64_t arg_keep_free = (uint64_t) -1; +static uint64_t arg_max_use = (uint64_t) -1; + +static int parse_config(void) { + static const ConfigTableItem items[] = { + { "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage }, + { "Coredump", "Compress", config_parse_bool, 0, &arg_compress }, + { "Coredump", "ProcessSizeMax", config_parse_iec_uint64, 0, &arg_process_size_max }, + { "Coredump", "ExternalSizeMax", config_parse_iec_uint64, 0, &arg_external_size_max }, + { "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max }, + { "Coredump", "KeepFree", config_parse_iec_uint64, 0, &arg_keep_free }, + { "Coredump", "MaxUse", config_parse_iec_uint64, 0, &arg_max_use }, + {} + }; + + return config_parse_many_nulstr(PKGSYSCONFDIR "/coredump.conf", + CONF_PATHS_NULSTR("systemd/coredump.conf.d"), + "Coredump\0", + config_item_table_lookup, items, + CONFIG_PARSE_WARN, NULL); +} + +static uint64_t storage_size_max(void) { + if (arg_storage == COREDUMP_STORAGE_EXTERNAL) + return arg_external_size_max; + if (arg_storage == COREDUMP_STORAGE_JOURNAL) + return arg_journal_size_max; + assert(arg_storage == COREDUMP_STORAGE_NONE); + return 0; +} + +static int fix_acl(int fd, uid_t uid) { + +#if HAVE_ACL + _cleanup_(acl_freep) acl_t acl = NULL; + acl_entry_t entry; + acl_permset_t permset; + int r; + + assert(fd >= 0); + + if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY) + return 0; + + /* Make sure normal users can read (but not write or delete) + * their own coredumps */ + + acl = acl_get_fd(fd); + if (!acl) + return log_error_errno(errno, "Failed to get ACL: %m"); + + if (acl_create_entry(&acl, &entry) < 0 || + acl_set_tag_type(entry, ACL_USER) < 0 || + acl_set_qualifier(entry, &uid) < 0) + return log_error_errno(errno, "Failed to patch ACL: %m"); + + if (acl_get_permset(entry, &permset) < 0 || + acl_add_perm(permset, ACL_READ) < 0) + return log_warning_errno(errno, "Failed to patch ACL: %m"); + + r = calc_acl_mask_if_needed(&acl); + if (r < 0) + return log_warning_errno(r, "Failed to patch ACL: %m"); + + if (acl_set_fd(fd, acl) < 0) + return log_error_errno(errno, "Failed to apply ACL: %m"); +#endif + + return 0; +} + +static int fix_xattr(int fd, const Context *context) { + + static const char * const xattrs[_META_MAX] = { + [META_ARGV_PID] = "user.coredump.pid", + [META_ARGV_UID] = "user.coredump.uid", + [META_ARGV_GID] = "user.coredump.gid", + [META_ARGV_SIGNAL] = "user.coredump.signal", + [META_ARGV_TIMESTAMP] = "user.coredump.timestamp", + [META_ARGV_RLIMIT] = "user.coredump.rlimit", + [META_ARGV_HOSTNAME] = "user.coredump.hostname", + [META_COMM] = "user.coredump.comm", + [META_EXE] = "user.coredump.exe", + }; + + int r = 0; + unsigned i; + + assert(fd >= 0); + + /* Attach some metadata to coredumps via extended + * attributes. Just because we can. */ + + for (i = 0; i < _META_MAX; i++) { + int k; + + if (isempty(context->meta[i]) || !xattrs[i]) + continue; + + k = fsetxattr(fd, xattrs[i], context->meta[i], strlen(context->meta[i]), XATTR_CREATE); + if (k < 0 && r == 0) + r = -errno; + } + + return r; +} + +#define filename_escape(s) xescape((s), "./ ") + +static const char *coredump_tmpfile_name(const char *s) { + return s ? s : "(unnamed temporary file)"; +} + +static int fix_permissions( + int fd, + const char *filename, + const char *target, + const Context *context, + uid_t uid) { + + int r; + + assert(fd >= 0); + assert(target); + assert(context); + + /* Ignore errors on these */ + (void) fchmod(fd, 0640); + (void) fix_acl(fd, uid); + (void) fix_xattr(fd, context); + + if (fsync(fd) < 0) + return log_error_errno(errno, "Failed to sync coredump %s: %m", coredump_tmpfile_name(filename)); + + (void) fsync_directory_of_file(fd); + + r = link_tmpfile(fd, filename, target); + if (r < 0) + return log_error_errno(r, "Failed to move coredump %s into place: %m", target); + + return 0; +} + +static int maybe_remove_external_coredump(const char *filename, uint64_t size) { + + /* Returns 1 if might remove, 0 if will not remove, < 0 on error. */ + + if (arg_storage == COREDUMP_STORAGE_EXTERNAL && + size <= arg_external_size_max) + return 0; + + if (!filename) + return 1; + + if (unlink(filename) < 0 && errno != ENOENT) + return log_error_errno(errno, "Failed to unlink %s: %m", filename); + + return 1; +} + +static int make_filename(const Context *context, char **ret) { + _cleanup_free_ char *c = NULL, *u = NULL, *p = NULL, *t = NULL; + sd_id128_t boot = {}; + int r; + + assert(context); + + c = filename_escape(context->meta[META_COMM]); + if (!c) + return -ENOMEM; + + u = filename_escape(context->meta[META_ARGV_UID]); + if (!u) + return -ENOMEM; + + r = sd_id128_get_boot(&boot); + if (r < 0) + return r; + + p = filename_escape(context->meta[META_ARGV_PID]); + if (!p) + return -ENOMEM; + + t = filename_escape(context->meta[META_ARGV_TIMESTAMP]); + if (!t) + return -ENOMEM; + + if (asprintf(ret, + "/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s000000", + c, + u, + SD_ID128_FORMAT_VAL(boot), + p, + t) < 0) + return -ENOMEM; + + return 0; +} + +static int save_external_coredump( + const Context *context, + int input_fd, + char **ret_filename, + int *ret_node_fd, + int *ret_data_fd, + uint64_t *ret_size, + bool *ret_truncated) { + + _cleanup_free_ char *fn = NULL, *tmp = NULL; + _cleanup_close_ int fd = -1; + uint64_t rlimit, process_limit, max_size; + struct stat st; + uid_t uid; + int r; + + assert(context); + assert(ret_filename); + assert(ret_node_fd); + assert(ret_data_fd); + assert(ret_size); + + r = parse_uid(context->meta[META_ARGV_UID], &uid); + if (r < 0) + return log_error_errno(r, "Failed to parse UID: %m"); + + r = safe_atou64(context->meta[META_ARGV_RLIMIT], &rlimit); + if (r < 0) + return log_error_errno(r, "Failed to parse resource limit '%s': %m", + context->meta[META_ARGV_RLIMIT]); + if (rlimit < page_size()) { + /* Is coredumping disabled? Then don't bother saving/processing the + * coredump. Anything below PAGE_SIZE cannot give a readable coredump + * (the kernel uses ELF_EXEC_PAGESIZE which is not easily accessible, but + * is usually the same as PAGE_SIZE. */ + return log_info_errno(SYNTHETIC_ERRNO(EBADSLT), + "Resource limits disable core dumping for process %s (%s).", + context->meta[META_ARGV_PID], context->meta[META_COMM]); + } + + process_limit = MAX(arg_process_size_max, storage_size_max()); + if (process_limit == 0) + return log_debug_errno(SYNTHETIC_ERRNO(EBADSLT), + "Limits for coredump processing and storage are both 0, not dumping core."); + + /* Never store more than the process configured, or than we actually shall keep or process */ + max_size = MIN(rlimit, process_limit); + + r = make_filename(context, &fn); + if (r < 0) + return log_error_errno(r, "Failed to determine coredump file name: %m"); + + (void) mkdir_p_label("/var/lib/systemd/coredump", 0755); + + fd = open_tmpfile_linkable(fn, O_RDWR|O_CLOEXEC, &tmp); + if (fd < 0) + return log_error_errno(fd, "Failed to create temporary file for coredump %s: %m", fn); + + r = copy_bytes(input_fd, fd, max_size, 0); + if (r < 0) { + log_error_errno(r, "Cannot store coredump of %s (%s): %m", + context->meta[META_ARGV_PID], context->meta[META_COMM]); + goto fail; + } + *ret_truncated = r == 1; + if (*ret_truncated) + log_struct(LOG_INFO, + LOG_MESSAGE("Core file was truncated to %zu bytes.", max_size), + "SIZE_LIMIT=%zu", max_size, + "MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR); + + if (fstat(fd, &st) < 0) { + log_error_errno(errno, "Failed to fstat core file %s: %m", coredump_tmpfile_name(tmp)); + goto fail; + } + + if (lseek(fd, 0, SEEK_SET) == (off_t) -1) { + log_error_errno(errno, "Failed to seek on %s: %m", coredump_tmpfile_name(tmp)); + goto fail; + } + +#if HAVE_XZ || HAVE_LZ4 + /* If we will remove the coredump anyway, do not compress. */ + if (arg_compress && !maybe_remove_external_coredump(NULL, st.st_size)) { + + _cleanup_free_ char *fn_compressed = NULL, *tmp_compressed = NULL; + _cleanup_close_ int fd_compressed = -1; + + fn_compressed = strjoin(fn, COMPRESSED_EXT); + if (!fn_compressed) { + log_oom(); + goto uncompressed; + } + + fd_compressed = open_tmpfile_linkable(fn_compressed, O_RDWR|O_CLOEXEC, &tmp_compressed); + if (fd_compressed < 0) { + log_error_errno(fd_compressed, "Failed to create temporary file for coredump %s: %m", fn_compressed); + goto uncompressed; + } + + r = compress_stream(fd, fd_compressed, -1); + if (r < 0) { + log_error_errno(r, "Failed to compress %s: %m", coredump_tmpfile_name(tmp_compressed)); + goto fail_compressed; + } + + r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid); + if (r < 0) + goto fail_compressed; + + /* OK, this worked, we can get rid of the uncompressed version now */ + if (tmp) + unlink_noerrno(tmp); + + *ret_filename = TAKE_PTR(fn_compressed); /* compressed */ + *ret_node_fd = TAKE_FD(fd_compressed); /* compressed */ + *ret_data_fd = TAKE_FD(fd); /* uncompressed */ + *ret_size = (uint64_t) st.st_size; /* uncompressed */ + + return 0; + + fail_compressed: + if (tmp_compressed) + (void) unlink(tmp_compressed); + } + +uncompressed: +#endif + + r = fix_permissions(fd, tmp, fn, context, uid); + if (r < 0) + goto fail; + + *ret_filename = TAKE_PTR(fn); + *ret_data_fd = TAKE_FD(fd); + *ret_node_fd = -1; + *ret_size = (uint64_t) st.st_size; + + return 0; + +fail: + if (tmp) + (void) unlink(tmp); + return r; +} + +static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_size) { + _cleanup_free_ char *field = NULL; + ssize_t n; + + assert(fd >= 0); + assert(ret); + assert(ret_size); + + if (lseek(fd, 0, SEEK_SET) == (off_t) -1) + return log_warning_errno(errno, "Failed to seek: %m"); + + field = malloc(9 + size); + if (!field) { + log_warning("Failed to allocate memory for coredump, coredump will not be stored."); + return -ENOMEM; + } + + memcpy(field, "COREDUMP=", 9); + + n = read(fd, field + 9, size); + if (n < 0) + return log_error_errno((int) n, "Failed to read core data: %m"); + if ((size_t) n < size) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Core data too short."); + + *ret = TAKE_PTR(field); + *ret_size = size + 9; + + return 0; +} + +/* Joins /proc/[pid]/fd/ and /proc/[pid]/fdinfo/ into the following lines: + * 0:/dev/pts/23 + * pos: 0 + * flags: 0100002 + * + * 1:/dev/pts/23 + * pos: 0 + * flags: 0100002 + * + * 2:/dev/pts/23 + * pos: 0 + * flags: 0100002 + * EOF + */ +static int compose_open_fds(pid_t pid, char **open_fds) { + _cleanup_closedir_ DIR *proc_fd_dir = NULL; + _cleanup_close_ int proc_fdinfo_fd = -1; + _cleanup_free_ char *buffer = NULL; + _cleanup_fclose_ FILE *stream = NULL; + const char *fddelim = "", *path; + struct dirent *dent = NULL; + size_t size = 0; + int r; + + assert(pid >= 0); + assert(open_fds != NULL); + + path = procfs_file_alloca(pid, "fd"); + proc_fd_dir = opendir(path); + if (!proc_fd_dir) + return -errno; + + proc_fdinfo_fd = openat(dirfd(proc_fd_dir), "../fdinfo", O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC|O_PATH); + if (proc_fdinfo_fd < 0) + return -errno; + + stream = open_memstream_unlocked(&buffer, &size); + if (!stream) + return -ENOMEM; + + FOREACH_DIRENT(dent, proc_fd_dir, return -errno) { + _cleanup_fclose_ FILE *fdinfo = NULL; + _cleanup_free_ char *fdname = NULL; + int fd; + + r = readlinkat_malloc(dirfd(proc_fd_dir), dent->d_name, &fdname); + if (r < 0) + return r; + + fprintf(stream, "%s%s:%s\n", fddelim, dent->d_name, fdname); + fddelim = "\n"; + + /* Use the directory entry from /proc/[pid]/fd with /proc/[pid]/fdinfo */ + fd = openat(proc_fdinfo_fd, dent->d_name, O_NOFOLLOW|O_CLOEXEC|O_RDONLY); + if (fd < 0) + continue; + + fdinfo = fdopen(fd, "r"); + if (!fdinfo) { + safe_close(fd); + continue; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + + r = read_line(fdinfo, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + fputs(line, stream); + fputc('\n', stream); + } + } + + errno = 0; + stream = safe_fclose(stream); + + if (errno > 0) + return -errno; + + *open_fds = TAKE_PTR(buffer); + + return 0; +} + +static int get_process_ns(pid_t pid, const char *namespace, ino_t *ns) { + const char *p; + struct stat stbuf; + _cleanup_close_ int proc_ns_dir_fd; + + p = procfs_file_alloca(pid, "ns"); + + proc_ns_dir_fd = open(p, O_DIRECTORY | O_CLOEXEC | O_RDONLY); + if (proc_ns_dir_fd < 0) + return -errno; + + if (fstatat(proc_ns_dir_fd, namespace, &stbuf, /* flags */0) < 0) + return -errno; + + *ns = stbuf.st_ino; + return 0; +} + +static int get_mount_namespace_leader(pid_t pid, pid_t *container_pid) { + pid_t cpid = pid, ppid = 0; + ino_t proc_mntns; + int r = 0; + + r = get_process_ns(pid, "mnt", &proc_mntns); + if (r < 0) + return r; + + for (;;) { + ino_t parent_mntns; + + r = get_process_ppid(cpid, &ppid); + if (r < 0) + return r; + + r = get_process_ns(ppid, "mnt", &parent_mntns); + if (r < 0) + return r; + + if (proc_mntns != parent_mntns) + break; + + if (ppid == 1) + return -ENOENT; + + cpid = ppid; + } + + *container_pid = ppid; + return 0; +} + +/* Returns 1 if the parent was found. + * Returns 0 if there is not a process we can call the pid's + * container parent (the pid's process isn't 'containerized'). + * Returns a negative number on errors. + */ +static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) { + int r = 0; + pid_t container_pid; + const char *proc_root_path; + struct stat root_stat, proc_root_stat; + + /* To compare inodes of / and /proc/[pid]/root */ + if (stat("/", &root_stat) < 0) + return -errno; + + proc_root_path = procfs_file_alloca(pid, "root"); + if (stat(proc_root_path, &proc_root_stat) < 0) + return -errno; + + /* The process uses system root. */ + if (proc_root_stat.st_ino == root_stat.st_ino) { + *cmdline = NULL; + return 0; + } + + r = get_mount_namespace_leader(pid, &container_pid); + if (r < 0) + return r; + + r = get_process_cmdline(container_pid, SIZE_MAX, 0, cmdline); + if (r < 0) + return r; + + return 1; +} + +static int change_uid_gid(const Context *context) { + uid_t uid; + gid_t gid; + int r; + + r = parse_uid(context->meta[META_ARGV_UID], &uid); + if (r < 0) + return r; + + if (uid <= SYSTEM_UID_MAX) { + const char *user = "systemd-coredump"; + + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); + if (r < 0) { + log_warning_errno(r, "Cannot resolve %s user. Proceeding to dump core as root: %m", user); + uid = gid = 0; + } + } else { + r = parse_gid(context->meta[META_ARGV_GID], &gid); + if (r < 0) + return r; + } + + return drop_privileges(uid, gid, 0); +} + +static int submit_coredump( + Context *context, + struct iovec_wrapper *iovw, + int input_fd) { + + _cleanup_close_ int coredump_fd = -1, coredump_node_fd = -1; + _cleanup_free_ char *filename = NULL, *coredump_data = NULL; + _cleanup_free_ char *stacktrace = NULL; + char *core_message; + uint64_t coredump_size = UINT64_MAX; + bool truncated = false; + int r; + + assert(context); + assert(iovw); + assert(input_fd >= 0); + + /* Vacuum before we write anything again */ + (void) coredump_vacuum(-1, arg_keep_free, arg_max_use); + + /* Always stream the coredump to disk, if that's possible */ + r = save_external_coredump(context, input_fd, + &filename, &coredump_node_fd, &coredump_fd, &coredump_size, &truncated); + if (r < 0) + /* Skip whole core dumping part */ + goto log; + + /* If we don't want to keep the coredump on disk, remove it now, as later on we + * will lack the privileges for it. However, we keep the fd to it, so that we can + * still process it and log it. */ + r = maybe_remove_external_coredump(filename, coredump_size); + if (r < 0) + return r; + if (r == 0) { + (void) iovw_put_string_field(iovw, "COREDUMP_FILENAME=", filename); + + } else if (arg_storage == COREDUMP_STORAGE_EXTERNAL) + log_info("The core will not be stored: size %"PRIu64" is greater than %"PRIu64" (the configured maximum)", + coredump_size, arg_external_size_max); + + /* Vacuum again, but exclude the coredump we just created */ + (void) coredump_vacuum(coredump_node_fd >= 0 ? coredump_node_fd : coredump_fd, arg_keep_free, arg_max_use); + + /* Now, let's drop privileges to become the user who owns the segfaulted process + * and allocate the coredump memory under the user's uid. This also ensures that + * the credentials journald will see are the ones of the coredumping user, thus + * making sure the user gets access to the core dump. Let's also get rid of all + * capabilities, if we run as root, we won't need them anymore. */ + r = change_uid_gid(context); + if (r < 0) + return log_error_errno(r, "Failed to drop privileges: %m"); + +#if HAVE_ELFUTILS + /* Try to get a stack trace if we can */ + if (coredump_size > arg_process_size_max) { + log_debug("Not generating stack trace: core size %"PRIu64" is greater " + "than %"PRIu64" (the configured maximum)", + coredump_size, arg_process_size_max); + } else + coredump_make_stack_trace(coredump_fd, context->meta[META_EXE], &stacktrace); +#endif + +log: + core_message = strjoina("Process ", context->meta[META_ARGV_PID], + " (", context->meta[META_COMM], ") of user ", + context->meta[META_ARGV_UID], " dumped core.", + context->is_journald && filename ? "\nCoredump diverted to " : NULL, + context->is_journald && filename ? filename : NULL); + + core_message = strjoina(core_message, stacktrace ? "\n\n" : NULL, stacktrace); + + if (context->is_journald) { + /* We cannot log to the journal, so just print the message. + * The target was set previously to something safe. */ + log_dispatch(LOG_ERR, 0, core_message); + return 0; + } + + (void) iovw_put_string_field(iovw, "MESSAGE=", core_message); + + if (truncated) + (void) iovw_put_string_field(iovw, "COREDUMP_TRUNCATED=", "1"); + + /* Optionally store the entire coredump in the journal */ + if (arg_storage == COREDUMP_STORAGE_JOURNAL) { + if (coredump_size <= arg_journal_size_max) { + size_t sz = 0; + + /* Store the coredump itself in the journal */ + + r = allocate_journal_field(coredump_fd, (size_t) coredump_size, &coredump_data, &sz); + if (r >= 0) { + if (iovw_put(iovw, coredump_data, sz) >= 0) + TAKE_PTR(coredump_data); + } else + log_warning_errno(r, "Failed to attach the core to the journal entry: %m"); + } else + log_info("The core will not be stored: size %"PRIu64" is greater than %"PRIu64" (the configured maximum)", + coredump_size, arg_journal_size_max); + } + + r = sd_journal_sendv(iovw->iovec, iovw->count); + if (r < 0) + return log_error_errno(r, "Failed to log coredump: %m"); + + return 0; +} + +static int save_context(Context *context, const struct iovec_wrapper *iovw) { + unsigned n, i, count = 0; + const char *unit; + int r; + + assert(context); + assert(iovw); + assert(iovw->count >= _META_ARGV_MAX); + + /* The context does not allocate any memory on its own */ + + for (n = 0; n < iovw->count; n++) { + struct iovec *iovec = iovw->iovec + n; + + for (i = 0; i < ELEMENTSOF(meta_field_names); i++) { + char *p; + + /* Note that these strings are NUL terminated, because we made sure that a + * trailing NUL byte is in the buffer, though not included in the iov_len + * count (see process_socket() and gather_pid_metadata_*()) */ + assert(((char*) iovec->iov_base)[iovec->iov_len] == 0); + + p = startswith(iovec->iov_base, meta_field_names[i]); + if (p) { + context->meta[i] = p; + count++; + break; + } + } + } + + if (!context->meta[META_ARGV_PID]) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to find the PID of crashing process"); + + r = parse_pid(context->meta[META_ARGV_PID], &context->pid); + if (r < 0) + return log_error_errno(r, "Failed to parse PID \"%s\": %m", context->meta[META_ARGV_PID]); + + unit = context->meta[META_UNIT]; + context->is_pid1 = streq(context->meta[META_ARGV_PID], "1") || streq_ptr(unit, SPECIAL_INIT_SCOPE); + context->is_journald = streq_ptr(unit, SPECIAL_JOURNALD_SERVICE); + + return 0; +} + +static int process_socket(int fd) { + _cleanup_close_ int input_fd = -1; + Context context = {}; + struct iovec_wrapper iovw = {}; + struct iovec iovec; + int i, r; + + assert(fd >= 0); + + log_setup_service(); + + log_debug("Processing coredump received on stdin..."); + + for (;;) { + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int))]; + } control = {}; + struct msghdr mh = { + .msg_control = &control, + .msg_controllen = sizeof(control), + .msg_iovlen = 1, + }; + ssize_t n; + ssize_t l; + + l = next_datagram_size_fd(fd); + if (l < 0) { + r = log_error_errno(l, "Failed to determine datagram size to read: %m"); + goto finish; + } + + iovec.iov_len = l; + iovec.iov_base = malloc(l + 1); + if (!iovec.iov_base) { + r = log_oom(); + goto finish; + } + + mh.msg_iov = &iovec; + + n = recvmsg(fd, &mh, MSG_CMSG_CLOEXEC); + if (n < 0) { + free(iovec.iov_base); + r = log_error_errno(errno, "Failed to receive datagram: %m"); + goto finish; + } + + /* The final zero-length datagram carries the file descriptor and tells us + * that we're done. */ + if (n == 0) { + struct cmsghdr *cmsg, *found = NULL; + + free(iovec.iov_base); + + CMSG_FOREACH(cmsg, &mh) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS && + cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { + assert(!found); + found = cmsg; + } + } + + if (!found) { + log_error("Coredump file descriptor missing."); + r = -EBADMSG; + goto finish; + } + + assert(input_fd < 0); + input_fd = *(int*) CMSG_DATA(found); + break; + } + + /* Add trailing NUL byte, in case these are strings */ + ((char*) iovec.iov_base)[n] = 0; + iovec.iov_len = (size_t) n; + + r = iovw_put(&iovw, iovec.iov_base, iovec.iov_len); + if (r < 0) + goto finish; + + cmsg_close_all(&mh); + } + + /* Make sure we got all data we really need */ + assert(input_fd >= 0); + + r = save_context(&context, &iovw); + if (r < 0) + goto finish; + + /* Make sure we received at least all fields we need. */ + for (i = 0; i < _META_MANDATORY_MAX; i++) + if (!context.meta[i]) { + r = log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "A mandatory argument (%i) has not been sent, aborting.", + i); + goto finish; + } + + r = submit_coredump(&context, &iovw, input_fd); + +finish: + iovw_free_contents(&iovw, true); + return r; +} + +static int send_iovec(const struct iovec_wrapper *iovw, int input_fd) { + + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/coredump", + }; + _cleanup_close_ int fd = -1; + size_t i; + int r; + + assert(iovw); + assert(input_fd >= 0); + + fd = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0); + if (fd < 0) + return log_error_errno(errno, "Failed to create coredump socket: %m"); + + if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) + return log_error_errno(errno, "Failed to connect to coredump service: %m"); + + for (i = 0; i < iovw->count; i++) { + struct msghdr mh = { + .msg_iov = iovw->iovec + i, + .msg_iovlen = 1, + }; + struct iovec copy[2]; + + for (;;) { + if (sendmsg(fd, &mh, MSG_NOSIGNAL) >= 0) + break; + + if (errno == EMSGSIZE && mh.msg_iov[0].iov_len > 0) { + /* This field didn't fit? That's a pity. Given that this is + * just metadata, let's truncate the field at half, and try + * again. We append three dots, in order to show that this is + * truncated. */ + + if (mh.msg_iov != copy) { + /* We don't want to modify the caller's iovec, hence + * let's create our own array, consisting of two new + * iovecs, where the first is a (truncated) copy of + * what we want to send, and the second one contains + * the trailing dots. */ + copy[0] = iovw->iovec[i]; + copy[1] = IOVEC_MAKE(((char[]){'.', '.', '.'}), 3); + + mh.msg_iov = copy; + mh.msg_iovlen = 2; + } + + copy[0].iov_len /= 2; /* halve it, and try again */ + continue; + } + + return log_error_errno(errno, "Failed to send coredump datagram: %m"); + } + } + + r = send_one_fd(fd, input_fd, 0); + if (r < 0) + return log_error_errno(r, "Failed to send coredump fd: %m"); + + return 0; +} + +static int gather_pid_metadata_from_argv(struct iovec_wrapper *iovw, Context *context, + int argc, char **argv) { + _cleanup_free_ char *free_timestamp = NULL; + int i, r, signo; + char *t; + + /* We gather all metadata that were passed via argv[] into an array of iovecs that + * we'll forward to the socket unit */ + + if (argc < _META_ARGV_MAX) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Not enough arguments passed by the kernel (%i, expected %i).", + argc, _META_ARGV_MAX); + + for (i = 0; i < _META_ARGV_MAX; i++) { + + t = argv[i]; + + switch (i) { + case META_ARGV_TIMESTAMP: + /* The journal fields contain the timestamp padded with six + * zeroes, so that the kernel-supplied 1s granularity timestamps + * becomes 1µs granularity, i.e. the granularity systemd usually + * operates in. */ + t = free_timestamp = strjoin(argv[i], "000000"); + if (!t) + return log_oom(); + break; + case META_ARGV_SIGNAL: + /* For signal, record its pretty name too */ + if (safe_atoi(argv[i], &signo) >= 0 && SIGNAL_VALID(signo)) + (void) iovw_put_string_field(iovw, "COREDUMP_SIGNAL_NAME=SIG", + signal_to_string(signo)); + break; + default: + break; + } + + r = iovw_put_string_field(iovw, meta_field_names[i], t); + if (r < 0) + return r; + } + + /* Cache some of the process metadata we collected so far and that we'll need to + * access soon */ + return save_context(context, iovw); +} + +static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) { + uid_t owner_uid; + pid_t pid; + char *t; + const char *p; + int r; + + /* Note that if we fail on oom later on, we do not roll-back changes to the iovec + * structure. (It remains valid, with the first iovec fields initialized.) */ + + pid = context->pid; + + /* The following is mandatory */ + r = get_process_comm(pid, &t); + if (r < 0) + return log_error_errno(r, "Failed to get COMM: %m"); + + r = iovw_put_string_field_free(iovw, "COREDUMP_COMM=", t); + if (r < 0) + return r; + + /* The following are optional but we used them if present */ + r = get_process_exe(pid, &t); + if (r >= 0) + r = iovw_put_string_field_free(iovw, "COREDUMP_EXE=", t); + if (r < 0) + log_warning_errno(r, "Failed to get EXE, ignoring: %m"); + + if (cg_pid_get_unit(pid, &t) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_UNIT=", t); + + /* The next are optional */ + if (cg_pid_get_user_unit(pid, &t) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_USER_UNIT=", t); + + if (sd_pid_get_session(pid, &t) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_SESSION=", t); + + if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) { + r = asprintf(&t, UID_FMT, owner_uid); + if (r > 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_OWNER_UID=", t); + } + + if (sd_pid_get_slice(pid, &t) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_SLICE=", t); + + if (get_process_cmdline(pid, SIZE_MAX, 0, &t) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_CMDLINE=", t); + + if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_CGROUP=", t); + + if (compose_open_fds(pid, &t) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_OPEN_FDS=", t); + + p = procfs_file_alloca(pid, "status"); + if (read_full_file(p, &t, NULL) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_STATUS=", t); + + p = procfs_file_alloca(pid, "maps"); + if (read_full_file(p, &t, NULL) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_MAPS=", t); + + p = procfs_file_alloca(pid, "limits"); + if (read_full_file(p, &t, NULL) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_LIMITS=", t); + + p = procfs_file_alloca(pid, "cgroup"); + if (read_full_file(p, &t, NULL) >=0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_CGROUP=", t); + + p = procfs_file_alloca(pid, "mountinfo"); + if (read_full_file(p, &t, NULL) >=0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_MOUNTINFO=", t); + + if (get_process_cwd(pid, &t) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_CWD=", t); + + if (get_process_root(pid, &t) >= 0) { + bool proc_self_root_is_slash; + + proc_self_root_is_slash = strcmp(t, "/") == 0; + + (void) iovw_put_string_field_free(iovw, "COREDUMP_ROOT=", t); + + /* If the process' root is "/", then there is a chance it has + * mounted own root and hence being containerized. */ + if (proc_self_root_is_slash && get_process_container_parent_cmdline(pid, &t) > 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_CONTAINER_CMDLINE=", t); + } + + if (get_process_environ(pid, &t) >= 0) + (void) iovw_put_string_field_free(iovw, "COREDUMP_ENVIRON=", t); + + /* we successfully acquired all metadata */ + return save_context(context, iovw); +} + +static int process_kernel(int argc, char* argv[]) { + Context context = {}; + struct iovec_wrapper *iovw; + int r; + + log_debug("Processing coredump received from the kernel..."); + + iovw = iovw_new(); + if (!iovw) + return log_oom(); + + (void) iovw_put_string_field(iovw, "MESSAGE_ID=", SD_MESSAGE_COREDUMP_STR); + (void) iovw_put_string_field(iovw, "PRIORITY=", STRINGIFY(LOG_CRIT)); + + /* Collect all process metadata passed by the kernel through argv[] */ + r = gather_pid_metadata_from_argv(iovw, &context, argc - 1, argv + 1); + if (r < 0) + goto finish; + + /* Collect the rest of the process metadata retrieved from the runtime */ + r = gather_pid_metadata(iovw, &context); + if (r < 0) + goto finish; + + if (!context.is_journald) { + /* OK, now we know it's not the journal, hence we can make use of it now. */ + log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); + log_open(); + } + + /* If this is PID 1 disable coredump collection, we'll unlikely be able to process + * it later on. + * + * FIXME: maybe we should disable coredumps generation from the beginning and + * re-enable it only when we know it's either safe (ie we're not running OOM) or + * it's not pid1 ? */ + if (context.is_pid1) { + log_notice("Due to PID 1 having crashed coredump collection will now be turned off."); + disable_coredumps(); + } + + if (context.is_journald || context.is_pid1) + r = submit_coredump(&context, iovw, STDIN_FILENO); + else + r = send_iovec(iovw, STDIN_FILENO); + + finish: + iovw = iovw_free_free(iovw); + return r; +} + +static int process_backtrace(int argc, char *argv[]) { + Context context = {}; + struct iovec_wrapper *iovw; + char *message; + size_t i; + int r; + _cleanup_(journal_importer_cleanup) JournalImporter importer = JOURNAL_IMPORTER_INIT(STDIN_FILENO); + + log_debug("Processing backtrace on stdin..."); + + iovw = iovw_new(); + if (!iovw) + return log_oom(); + + (void) iovw_put_string_field(iovw, "MESSAGE_ID=", SD_MESSAGE_BACKTRACE_STR); + (void) iovw_put_string_field(iovw, "PRIORITY=", STRINGIFY(LOG_CRIT)); + + /* Collect all process metadata from argv[] by making sure to skip the + * '--backtrace' option */ + r = gather_pid_metadata_from_argv(iovw, &context, argc - 2, argv + 2); + if (r < 0) + goto finish; + + /* Collect the rest of the process metadata retrieved from the runtime */ + r = gather_pid_metadata(iovw, &context); + if (r < 0) + goto finish; + + for (;;) { + r = journal_importer_process_data(&importer); + if (r < 0) { + log_error_errno(r, "Failed to parse journal entry on stdin: %m"); + goto finish; + } + if (r == 1 || /* complete entry */ + journal_importer_eof(&importer)) /* end of data */ + break; + } + + if (journal_importer_eof(&importer)) { + log_warning("Did not receive a full journal entry on stdin, ignoring message sent by reporter"); + + message = strjoina("Process ", context.meta[META_ARGV_PID], + " (", context.meta[META_COMM], ")" + " of user ", context.meta[META_ARGV_UID], + " failed with ", context.meta[META_ARGV_SIGNAL]); + + r = iovw_put_string_field(iovw, "MESSAGE=", message); + if (r < 0) + return r; + } else { + /* The imported iovecs are not supposed to be freed by us so let's store + * them at the end of the array so we can skip them while freeing the + * rest. */ + for (i = 0; i < importer.iovw.count; i++) { + struct iovec *iovec = importer.iovw.iovec + i; + + iovw_put(iovw, iovec->iov_base, iovec->iov_len); + } + } + + r = sd_journal_sendv(iovw->iovec, iovw->count); + if (r < 0) + log_error_errno(r, "Failed to log backtrace: %m"); + + finish: + iovw->count -= importer.iovw.count; + iovw = iovw_free_free(iovw); + return r; +} + +static int run(int argc, char *argv[]) { + int r; + + /* First, log to a safe place, since we don't know what crashed and it might + * be journald which we'd rather not log to then. */ + + log_set_target(LOG_TARGET_KMSG); + log_open(); + + /* Make sure we never enter a loop */ + (void) prctl(PR_SET_DUMPABLE, 0); + + /* Ignore all parse errors */ + (void) parse_config(); + + log_debug("Selected storage '%s'.", coredump_storage_to_string(arg_storage)); + log_debug("Selected compression %s.", yes_no(arg_compress)); + + r = sd_listen_fds(false); + if (r < 0) + return log_error_errno(r, "Failed to determine the number of file descriptors: %m"); + + /* If we got an fd passed, we are running in coredumpd mode. Otherwise we + * are invoked from the kernel as coredump handler. */ + if (r == 0) { + if (streq_ptr(argv[1], "--backtrace")) + return process_backtrace(argc, argv); + else + return process_kernel(argc, argv); + } else if (r == 1) + return process_socket(SD_LISTEN_FDS_START); + + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Received unexpected number of file descriptors."); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/coredump/coredump.conf b/src/coredump/coredump.conf new file mode 100644 index 00000000..c2f0643e --- /dev/null +++ b/src/coredump/coredump.conf @@ -0,0 +1,21 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See coredump.conf(5) for details. + +[Coredump] +#Storage=external +#Compress=yes +#ProcessSizeMax=2G +#ExternalSizeMax=2G +#JournalSizeMax=767M +#MaxUse= +#KeepFree= diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c new file mode 100644 index 00000000..ed124649 --- /dev/null +++ b/src/coredump/coredumpctl.c @@ -0,0 +1,1102 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-journal.h" +#include "sd-messages.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "compress.h" +#include "def.h" +#include "fd-util.h" +#include "fs-util.h" +#include "journal-internal.h" +#include "journal-util.h" +#include "log.h" +#include "macro.h" +#include "main-func.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "sigbus.h" +#include "signal-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "user-util.h" +#include "util.h" +#include "verbs.h" + +#define SHORT_BUS_CALL_TIMEOUT_USEC (3 * USEC_PER_SEC) + +static usec_t arg_since = USEC_INFINITY, arg_until = USEC_INFINITY; +static const char* arg_field = NULL; +static const char *arg_debugger = NULL; +static const char *arg_directory = NULL; +static PagerFlags arg_pager_flags = 0; +static int arg_no_legend = false; +static int arg_one = false; +static const char* arg_output = NULL; +static bool arg_reverse = false; +static bool arg_quiet = false; + +static int add_match(sd_journal *j, const char *match) { + _cleanup_free_ char *p = NULL; + const char* prefix, *pattern; + pid_t pid; + int r; + + if (strchr(match, '=')) + prefix = ""; + else if (strchr(match, '/')) { + r = path_make_absolute_cwd(match, &p); + if (r < 0) + return log_error_errno(r, "path_make_absolute_cwd(\"%s\"): %m", match); + + match = p; + prefix = "COREDUMP_EXE="; + } else if (parse_pid(match, &pid) >= 0) + prefix = "COREDUMP_PID="; + else + prefix = "COREDUMP_COMM="; + + pattern = strjoina(prefix, match); + log_debug("Adding match: %s", pattern); + r = sd_journal_add_match(j, pattern, 0); + if (r < 0) + return log_error_errno(r, "Failed to add match \"%s\": %m", match); + + return 0; +} + +static int add_matches(sd_journal *j, char **matches) { + char **match; + int r; + + r = sd_journal_add_match(j, "MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR, 0); + if (r < 0) + return log_error_errno(r, "Failed to add match \"%s\": %m", "MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR); + + r = sd_journal_add_match(j, "MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR, 0); + if (r < 0) + return log_error_errno(r, "Failed to add match \"%s\": %m", "MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR); + + STRV_FOREACH(match, matches) { + r = add_match(j, *match); + if (r < 0) + return r; + } + + return 0; +} + +static int acquire_journal(sd_journal **ret, char **matches) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + int r; + + assert(ret); + + if (arg_directory) { + r = sd_journal_open_directory(&j, arg_directory, 0); + if (r < 0) + return log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory); + } else { + r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); + if (r < 0) + return log_error_errno(r, "Failed to open journal: %m"); + } + + r = journal_access_check_and_warn(j, arg_quiet, true); + if (r < 0) + return r; + + r = add_matches(j, matches); + if (r < 0) + return r; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *filter; + + filter = journal_make_match_string(j); + log_debug("Journal filter: %s", filter); + } + + *ret = TAKE_PTR(j); + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("coredumpctl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n\n" + "%sList or retrieve coredumps from the journal.%s\n" + "\nCommands:\n" + " list [MATCHES...] List available coredumps (default)\n" + " info [MATCHES...] Show detailed information about one or more coredumps\n" + " dump [MATCHES...] Print first matching coredump to stdout\n" + " debug [MATCHES...] Start a debugger for the first matching coredump\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Print version string\n" + " --no-pager Do not pipe output into a pager\n" + " --no-legend Do not print the column headers\n" + " --debugger=DEBUGGER Use the given debugger\n" + " -1 Show information about most recent entry only\n" + " -S --since=DATE Only print coredumps since the date\n" + " -U --until=DATE Only print coredumps until the date\n" + " -r --reverse Show the newest entries first\n" + " -F --field=FIELD List all values a certain field takes\n" + " -o --output=FILE Write output to FILE\n" + " -D --directory=DIR Use journal files from directory\n\n" + " -q --quiet Do not show info messages and privilege warning\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_NO_PAGER, + ARG_NO_LEGEND, + ARG_DEBUGGER, + }; + + int c, r; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version" , no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, + { "debugger", required_argument, NULL, ARG_DEBUGGER }, + { "output", required_argument, NULL, 'o' }, + { "field", required_argument, NULL, 'F' }, + { "directory", required_argument, NULL, 'D' }, + { "reverse", no_argument, NULL, 'r' }, + { "since", required_argument, NULL, 'S' }, + { "until", required_argument, NULL, 'U' }, + { "quiet", no_argument, NULL, 'q' }, + {} + }; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "ho:F:1D:rS:U:q", options, NULL)) >= 0) + switch(c) { + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_NO_LEGEND: + arg_no_legend = true; + break; + + case ARG_DEBUGGER: + arg_debugger = optarg; + break; + + case 'o': + if (arg_output) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot set output more than once."); + + arg_output = optarg; + break; + + case 'S': + r = parse_timestamp(optarg, &arg_since); + if (r < 0) + return log_error_errno(r, "Failed to parse timestamp '%s': %m", optarg); + break; + + case 'U': + r = parse_timestamp(optarg, &arg_until); + if (r < 0) + return log_error_errno(r, "Failed to parse timestamp '%s': %m", optarg); + break; + + case 'F': + if (arg_field) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot use --field/-F more than once."); + arg_field = optarg; + break; + + case '1': + arg_one = true; + break; + + case 'D': + arg_directory = optarg; + break; + + case 'r': + arg_reverse = true; + break; + + case 'q': + arg_quiet = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_since != USEC_INFINITY && arg_until != USEC_INFINITY && + arg_since > arg_until) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--since= must be before --until=."); + + return 1; +} + +static int retrieve(const void *data, + size_t len, + const char *name, + char **var) { + + size_t ident; + char *v; + + ident = strlen(name) + 1; /* name + "=" */ + + if (len < ident) + return 0; + + if (memcmp(data, name, ident - 1) != 0) + return 0; + + if (((const char*) data)[ident - 1] != '=') + return 0; + + v = strndup((const char*)data + ident, len - ident); + if (!v) + return log_oom(); + + free_and_replace(*var, v); + return 1; +} + +static int print_field(FILE* file, sd_journal *j) { + const void *d; + size_t l; + + assert(file); + assert(j); + + assert(arg_field); + + /* A (user-specified) field may appear more than once for a given entry. + * We will print all of the occurrences. + * This is different below for fields that systemd-coredump uses, + * because they cannot meaningfully appear more than once. + */ + SD_JOURNAL_FOREACH_DATA(j, d, l) { + _cleanup_free_ char *value = NULL; + int r; + + r = retrieve(d, l, arg_field, &value); + if (r < 0) + return r; + if (r > 0) + fprintf(file, "%s\n", value); + } + + return 0; +} + +#define RETRIEVE(d, l, name, arg) \ + { \ + int _r = retrieve(d, l, name, &arg); \ + if (_r < 0) \ + return _r; \ + if (_r > 0) \ + continue; \ + } + +static int print_list(FILE* file, sd_journal *j, int had_legend) { + _cleanup_free_ char + *mid = NULL, *pid = NULL, *uid = NULL, *gid = NULL, + *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL, + *filename = NULL, *truncated = NULL, *coredump = NULL; + const void *d; + size_t l; + usec_t t; + char buf[FORMAT_TIMESTAMP_MAX]; + int r; + const char *present; + bool normal_coredump; + + assert(file); + assert(j); + + SD_JOURNAL_FOREACH_DATA(j, d, l) { + RETRIEVE(d, l, "MESSAGE_ID", mid); + RETRIEVE(d, l, "COREDUMP_PID", pid); + RETRIEVE(d, l, "COREDUMP_UID", uid); + RETRIEVE(d, l, "COREDUMP_GID", gid); + RETRIEVE(d, l, "COREDUMP_SIGNAL", sgnl); + RETRIEVE(d, l, "COREDUMP_EXE", exe); + RETRIEVE(d, l, "COREDUMP_COMM", comm); + RETRIEVE(d, l, "COREDUMP_CMDLINE", cmdline); + RETRIEVE(d, l, "COREDUMP_FILENAME", filename); + RETRIEVE(d, l, "COREDUMP_TRUNCATED", truncated); + RETRIEVE(d, l, "COREDUMP", coredump); + } + + if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename) { + log_warning("Empty coredump log entry"); + return -EINVAL; + } + + r = sd_journal_get_realtime_usec(j, &t); + if (r < 0) + return log_error_errno(r, "Failed to get realtime timestamp: %m"); + + format_timestamp(buf, sizeof(buf), t); + + if (!had_legend && !arg_no_legend) + fprintf(file, "%-*s %*s %*s %*s %*s %-*s %s\n", + FORMAT_TIMESTAMP_WIDTH, "TIME", + 6, "PID", + 5, "UID", + 5, "GID", + 3, "SIG", + 9, "COREFILE", + "EXE"); + + normal_coredump = streq_ptr(mid, SD_MESSAGE_COREDUMP_STR); + + if (filename) + if (access(filename, R_OK) == 0) + present = "present"; + else if (errno == ENOENT) + present = "missing"; + else + present = "error"; + else if (coredump) + present = "journal"; + else if (normal_coredump) + present = "none"; + else + present = "-"; + + if (STR_IN_SET(present, "present", "journal") && truncated && parse_boolean(truncated) > 0) + present = "truncated"; + + fprintf(file, "%-*s %*s %*s %*s %*s %-*s %s\n", + FORMAT_TIMESTAMP_WIDTH, buf, + 6, strna(pid), + 5, strna(uid), + 5, strna(gid), + 3, normal_coredump ? strna(sgnl) : "-", + 9, present, + strna(exe ?: (comm ?: cmdline))); + + return 0; +} + +static int print_info(FILE *file, sd_journal *j, bool need_space) { + _cleanup_free_ char + *mid = NULL, *pid = NULL, *uid = NULL, *gid = NULL, + *sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL, + *unit = NULL, *user_unit = NULL, *session = NULL, + *boot_id = NULL, *machine_id = NULL, *hostname = NULL, + *slice = NULL, *cgroup = NULL, *owner_uid = NULL, + *message = NULL, *timestamp = NULL, *filename = NULL, + *truncated = NULL, *coredump = NULL; + const void *d; + size_t l; + bool normal_coredump; + int r; + + assert(file); + assert(j); + + SD_JOURNAL_FOREACH_DATA(j, d, l) { + RETRIEVE(d, l, "MESSAGE_ID", mid); + RETRIEVE(d, l, "COREDUMP_PID", pid); + RETRIEVE(d, l, "COREDUMP_UID", uid); + RETRIEVE(d, l, "COREDUMP_GID", gid); + RETRIEVE(d, l, "COREDUMP_SIGNAL", sgnl); + RETRIEVE(d, l, "COREDUMP_EXE", exe); + RETRIEVE(d, l, "COREDUMP_COMM", comm); + RETRIEVE(d, l, "COREDUMP_CMDLINE", cmdline); + RETRIEVE(d, l, "COREDUMP_UNIT", unit); + RETRIEVE(d, l, "COREDUMP_USER_UNIT", user_unit); + RETRIEVE(d, l, "COREDUMP_SESSION", session); + RETRIEVE(d, l, "COREDUMP_OWNER_UID", owner_uid); + RETRIEVE(d, l, "COREDUMP_SLICE", slice); + RETRIEVE(d, l, "COREDUMP_CGROUP", cgroup); + RETRIEVE(d, l, "COREDUMP_TIMESTAMP", timestamp); + RETRIEVE(d, l, "COREDUMP_FILENAME", filename); + RETRIEVE(d, l, "COREDUMP_TRUNCATED", truncated); + RETRIEVE(d, l, "COREDUMP", coredump); + RETRIEVE(d, l, "_BOOT_ID", boot_id); + RETRIEVE(d, l, "_MACHINE_ID", machine_id); + RETRIEVE(d, l, "_HOSTNAME", hostname); + RETRIEVE(d, l, "MESSAGE", message); + } + + if (need_space) + fputs("\n", file); + + normal_coredump = streq_ptr(mid, SD_MESSAGE_COREDUMP_STR); + + if (comm) + fprintf(file, + " PID: %s%s%s (%s)\n", + ansi_highlight(), strna(pid), ansi_normal(), comm); + else + fprintf(file, + " PID: %s%s%s\n", + ansi_highlight(), strna(pid), ansi_normal()); + + if (uid) { + uid_t n; + + if (parse_uid(uid, &n) >= 0) { + _cleanup_free_ char *u = NULL; + + u = uid_to_name(n); + fprintf(file, + " UID: %s (%s)\n", + uid, u); + } else { + fprintf(file, + " UID: %s\n", + uid); + } + } + + if (gid) { + gid_t n; + + if (parse_gid(gid, &n) >= 0) { + _cleanup_free_ char *g = NULL; + + g = gid_to_name(n); + fprintf(file, + " GID: %s (%s)\n", + gid, g); + } else { + fprintf(file, + " GID: %s\n", + gid); + } + } + + if (sgnl) { + int sig; + const char *name = normal_coredump ? "Signal" : "Reason"; + + if (normal_coredump && safe_atoi(sgnl, &sig) >= 0) + fprintf(file, " %s: %s (%s)\n", name, sgnl, signal_to_string(sig)); + else + fprintf(file, " %s: %s\n", name, sgnl); + } + + if (timestamp) { + usec_t u; + + r = safe_atou64(timestamp, &u); + if (r >= 0) { + char absolute[FORMAT_TIMESTAMP_MAX], relative[FORMAT_TIMESPAN_MAX]; + + fprintf(file, + " Timestamp: %s (%s)\n", + format_timestamp(absolute, sizeof(absolute), u), + format_timestamp_relative(relative, sizeof(relative), u)); + + } else + fprintf(file, " Timestamp: %s\n", timestamp); + } + + if (cmdline) + fprintf(file, " Command Line: %s\n", cmdline); + if (exe) + fprintf(file, " Executable: %s%s%s\n", ansi_highlight(), exe, ansi_normal()); + if (cgroup) + fprintf(file, " Control Group: %s\n", cgroup); + if (unit) + fprintf(file, " Unit: %s\n", unit); + if (user_unit) + fprintf(file, " User Unit: %s\n", user_unit); + if (slice) + fprintf(file, " Slice: %s\n", slice); + if (session) + fprintf(file, " Session: %s\n", session); + if (owner_uid) { + uid_t n; + + if (parse_uid(owner_uid, &n) >= 0) { + _cleanup_free_ char *u = NULL; + + u = uid_to_name(n); + fprintf(file, + " Owner UID: %s (%s)\n", + owner_uid, u); + } else { + fprintf(file, + " Owner UID: %s\n", + owner_uid); + } + } + if (boot_id) + fprintf(file, " Boot ID: %s\n", boot_id); + if (machine_id) + fprintf(file, " Machine ID: %s\n", machine_id); + if (hostname) + fprintf(file, " Hostname: %s\n", hostname); + + if (filename) { + bool inacc, trunc; + + inacc = access(filename, R_OK) < 0; + trunc = truncated && parse_boolean(truncated) > 0; + + if (inacc || trunc) + fprintf(file, " Storage: %s%s (%s%s%s)%s\n", + ansi_highlight_red(), + filename, + inacc ? "inaccessible" : "", + inacc && trunc ? ", " : "", + trunc ? "truncated" : "", + ansi_normal()); + else + fprintf(file, " Storage: %s\n", filename); + } + + else if (coredump) + fprintf(file, " Storage: journal\n"); + else + fprintf(file, " Storage: none\n"); + + if (message) { + _cleanup_free_ char *m = NULL; + + m = strreplace(message, "\n", "\n "); + + fprintf(file, " Message: %s\n", strstrip(m ?: message)); + } + + return 0; +} + +static int focus(sd_journal *j) { + int r; + + r = sd_journal_seek_tail(j); + if (r == 0) + r = sd_journal_previous(j); + if (r < 0) + return log_error_errno(r, "Failed to search journal: %m"); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), + "No match found."); + return r; +} + +static int print_entry(sd_journal *j, unsigned n_found, bool verb_is_info) { + assert(j); + + if (verb_is_info) + return print_info(stdout, j, n_found); + else if (arg_field) + return print_field(stdout, j); + else + return print_list(stdout, j, n_found); +} + +static int dump_list(int argc, char **argv, void *userdata) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + unsigned n_found = 0; + bool verb_is_info; + int r; + + verb_is_info = (argc >= 1 && streq(argv[0], "info")); + + r = acquire_journal(&j, argv + 1); + if (r < 0) + return r; + + (void) pager_open(arg_pager_flags); + + /* The coredumps are likely to compressed, and for just + * listing them we don't need to decompress them, so let's + * pick a fairly low data threshold here */ + sd_journal_set_data_threshold(j, 4096); + + /* "info" without pattern implies "-1" */ + if (arg_one || (verb_is_info && argc == 1)) { + r = focus(j); + if (r < 0) + return r; + + return print_entry(j, 0, verb_is_info); + } else { + if (arg_since != USEC_INFINITY && !arg_reverse) + r = sd_journal_seek_realtime_usec(j, arg_since); + else if (arg_until != USEC_INFINITY && arg_reverse) + r = sd_journal_seek_realtime_usec(j, arg_until); + else if (arg_reverse) + r = sd_journal_seek_tail(j); + else + r = sd_journal_seek_head(j); + if (r < 0) + return log_error_errno(r, "Failed to seek to date: %m"); + + for (;;) { + if (!arg_reverse) + r = sd_journal_next(j); + else + r = sd_journal_previous(j); + + if (r < 0) + return log_error_errno(r, "Failed to iterate through journal: %m"); + + if (r == 0) + break; + + if (arg_until != USEC_INFINITY && !arg_reverse) { + usec_t usec; + + r = sd_journal_get_realtime_usec(j, &usec); + if (r < 0) + return log_error_errno(r, "Failed to determine timestamp: %m"); + if (usec > arg_until) + continue; + } + + if (arg_since != USEC_INFINITY && arg_reverse) { + usec_t usec; + + r = sd_journal_get_realtime_usec(j, &usec); + if (r < 0) + return log_error_errno(r, "Failed to determine timestamp: %m"); + if (usec < arg_since) + continue; + } + + r = print_entry(j, n_found++, verb_is_info); + if (r < 0) + return r; + } + + if (!arg_field && n_found <= 0) { + if (!arg_quiet) + log_notice("No coredumps found."); + return -ESRCH; + } + } + + return 0; +} + +static int save_core(sd_journal *j, FILE *file, char **path, bool *unlink_temp) { + const char *data; + _cleanup_free_ char *filename = NULL; + size_t len; + int r, fd; + _cleanup_close_ int fdt = -1; + char *temp = NULL; + + assert(!(file && path)); /* At most one can be specified */ + assert(!!path == !!unlink_temp); /* Those must be specified together */ + + /* Look for a coredump on disk first. */ + r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len); + if (r == 0) { + r = retrieve(data, len, "COREDUMP_FILENAME", &filename); + if (r < 0) + return r; + assert(r > 0); + + if (access(filename, R_OK) < 0) + return log_error_errno(errno, "File \"%s\" is not readable: %m", filename); + + if (path && !endswith(filename, ".xz") && !endswith(filename, ".lz4")) { + *path = TAKE_PTR(filename); + + return 0; + } + + } else { + if (r != -ENOENT) + return log_error_errno(r, "Failed to retrieve COREDUMP_FILENAME field: %m"); + /* Check that we can have a COREDUMP field. We still haven't set a high + * data threshold, so we'll get a few kilobytes at most. + */ + + r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); + if (r == -ENOENT) + return log_error_errno(r, "Coredump entry has no core attached (neither internally in the journal nor externally on disk)."); + if (r < 0) + return log_error_errno(r, "Failed to retrieve COREDUMP field: %m"); + } + + if (path) { + const char *vt; + + /* Create a temporary file to write the uncompressed core to. */ + + r = var_tmp_dir(&vt); + if (r < 0) + return log_error_errno(r, "Failed to acquire temporary directory path: %m"); + + temp = path_join(vt, "coredump-XXXXXX"); + if (!temp) + return log_oom(); + + fdt = mkostemp_safe(temp); + if (fdt < 0) + return log_error_errno(fdt, "Failed to create temporary file: %m"); + log_debug("Created temporary file %s", temp); + + fd = fdt; + } else { + /* If neither path or file are specified, we will write to stdout. Let's now check + * if stdout is connected to a tty. We checked that the file exists, or that the + * core might be stored in the journal. In this second case, if we found the entry, + * in all likelihood we will be able to access the COREDUMP= field. In either case, + * we stop before doing any "real" work, i.e. before starting decompression or + * reading from the file or creating temporary files. + */ + if (!file) { + if (on_tty()) + return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), + "Refusing to dump core to tty" + " (use shell redirection or specify --output)."); + file = stdout; + } + + fd = fileno(file); + } + + if (filename) { +#if HAVE_XZ || HAVE_LZ4 + _cleanup_close_ int fdf; + + fdf = open(filename, O_RDONLY | O_CLOEXEC); + if (fdf < 0) { + r = log_error_errno(errno, "Failed to open %s: %m", filename); + goto error; + } + + r = decompress_stream(filename, fdf, fd, -1); + if (r < 0) { + log_error_errno(r, "Failed to decompress %s: %m", filename); + goto error; + } +#else + log_error("Cannot decompress file. Compiled without compression support."); + r = -EOPNOTSUPP; + goto error; +#endif + } else { + ssize_t sz; + + /* We want full data, nothing truncated. */ + sd_journal_set_data_threshold(j, 0); + + r = sd_journal_get_data(j, "COREDUMP", (const void**) &data, &len); + if (r < 0) + return log_error_errno(r, "Failed to retrieve COREDUMP field: %m"); + + assert(len >= 9); + data += 9; + len -= 9; + + sz = write(fd, data, len); + if (sz < 0) { + r = log_error_errno(errno, "Failed to write output: %m"); + goto error; + } + if (sz != (ssize_t) len) { + log_error("Short write to output."); + r = -EIO; + goto error; + } + } + + if (temp) { + *path = temp; + *unlink_temp = true; + } + return 0; + +error: + if (temp) { + (void) unlink(temp); + log_debug("Removed temporary file %s", temp); + } + return r; +} + +static int dump_core(int argc, char **argv, void *userdata) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + if (arg_field) { + log_error("Option --field/-F only makes sense with list"); + return -EINVAL; + } + + r = acquire_journal(&j, argv + 1); + if (r < 0) + return r; + + r = focus(j); + if (r < 0) + return r; + + if (arg_output) { + f = fopen(arg_output, "we"); + if (!f) + return log_error_errno(errno, "Failed to open \"%s\" for writing: %m", arg_output); + } + + print_info(f ? stdout : stderr, j, false); + + r = save_core(j, f, NULL, NULL); + if (r < 0) + return r; + + r = sd_journal_previous(j); + if (r > 0 && !arg_quiet) + log_notice("More than one entry matches, ignoring rest."); + + return 0; +} + +static int run_debug(int argc, char **argv, void *userdata) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + _cleanup_free_ char *exe = NULL, *path = NULL, *debugger = NULL; + bool unlink_path = false; + const char *data, *fork_name; + size_t len; + pid_t pid; + int r; + + if (!arg_debugger) { + char *env_debugger; + + env_debugger = getenv("SYSTEMD_DEBUGGER"); + if (env_debugger) + arg_debugger = env_debugger; + else + arg_debugger = "gdb"; + } + + debugger = strdup(arg_debugger); + if (!debugger) + return -ENOMEM; + + if (arg_field) { + log_error("Option --field/-F only makes sense with list"); + return -EINVAL; + } + + r = acquire_journal(&j, argv + 1); + if (r < 0) + return r; + + r = focus(j); + if (r < 0) + return r; + + print_info(stdout, j, false); + fputs("\n", stdout); + + r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len); + if (r < 0) + return log_error_errno(r, "Failed to retrieve COREDUMP_EXE field: %m"); + + assert(len > STRLEN("COREDUMP_EXE=")); + data += STRLEN("COREDUMP_EXE="); + len -= STRLEN("COREDUMP_EXE="); + + exe = strndup(data, len); + if (!exe) + return log_oom(); + + if (endswith(exe, " (deleted)")) { + log_error("Binary already deleted."); + return -ENOENT; + } + + if (!path_is_absolute(exe)) { + log_error("Binary is not an absolute path."); + return -ENOENT; + } + + r = save_core(j, NULL, &path, &unlink_path); + if (r < 0) + return r; + + /* Don't interfere with gdb and its handling of SIGINT. */ + (void) ignore_signals(SIGINT, -1); + + fork_name = strjoina("(", debugger, ")"); + + r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (r < 0) + goto finish; + if (r == 0) { + execlp(debugger, debugger, exe, "-c", path, NULL); + log_open(); + log_error_errno(errno, "Failed to invoke %s: %m", debugger); + _exit(EXIT_FAILURE); + } + + r = wait_for_terminate_and_check(debugger, pid, WAIT_LOG_ABNORMAL); + +finish: + (void) default_signals(SIGINT, -1); + + if (unlink_path) { + log_debug("Removed temporary file %s", path); + (void) unlink(path); + } + + return r; +} + +static int check_units_active(void) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int c = 0, r; + const char *id, *state, *substate; + + if (arg_quiet) + return false; + + r = sd_bus_default_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to acquire bus: %m"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListUnitsByPatterns"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, NULL); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, STRV_MAKE("systemd-coredump@*.service")); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, SHORT_BUS_CALL_TIMEOUT_USEC, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to check if any systemd-coredump@.service units are running: %s", + bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read( + reply, "(ssssssouso)", + &id, NULL, NULL, &state, &substate, + NULL, NULL, NULL, NULL, NULL)) > 0) { + bool found = !STR_IN_SET(state, "inactive", "dead", "failed"); + log_debug("Unit %s is %s/%s, %scounting it.", id, state, substate, found ? "" : "not "); + c += found; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return c; +} + +static int coredumpctl_main(int argc, char *argv[]) { + + static const Verb verbs[] = { + { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, dump_list }, + { "info", VERB_ANY, VERB_ANY, 0, dump_list }, + { "dump", VERB_ANY, VERB_ANY, 0, dump_core }, + { "debug", VERB_ANY, VERB_ANY, 0, run_debug }, + { "gdb", VERB_ANY, VERB_ANY, 0, run_debug }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static int run(int argc, char *argv[]) { + int r, units_active; + + setlocale(LC_ALL, ""); + log_show_color(true); + log_parse_environment(); + log_open(); + + /* The journal merging logic potentially needs a lot of fds. */ + (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + sigbus_install(); + + units_active = check_units_active(); /* error is treated the same as 0 */ + + r = coredumpctl_main(argc, argv); + + if (units_active > 0) + printf("%s-- Notice: %d systemd-coredump@.service %s, output may be incomplete.%s\n", + ansi_highlight_red(), + units_active, units_active == 1 ? "unit is running" : "units are running", + ansi_normal()); + return r; +} + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/coredump/meson.build b/src/coredump/meson.build new file mode 100644 index 00000000..7fa59426 --- /dev/null +++ b/src/coredump/meson.build @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +systemd_coredump_sources = files(''' + coredump.c + coredump-vacuum.c + coredump-vacuum.h +'''.split()) + +if conf.get('HAVE_ELFUTILS') == 1 + systemd_coredump_sources += files(['stacktrace.c', + 'stacktrace.h']) +endif + +coredumpctl_sources = files('coredumpctl.c') + +if conf.get('ENABLE_COREDUMP') == 1 + install_data('coredump.conf', + install_dir : pkgsysconfdir) +endif + +tests += [ + [['src/coredump/test-coredump-vacuum.c', + 'src/coredump/coredump-vacuum.c', + 'src/coredump/coredump-vacuum.h'], + [], + [], + 'ENABLE_COREDUMP', 'manual'], +] diff --git a/src/coredump/stacktrace.c b/src/coredump/stacktrace.c new file mode 100644 index 00000000..4e0d3e76 --- /dev/null +++ b/src/coredump/stacktrace.c @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fileio.h" +#include "fd-util.h" +#include "format-util.h" +#include "macro.h" +#include "stacktrace.h" +#include "string-util.h" +#include "util.h" + +#define FRAMES_MAX 64 +#define THREADS_MAX 64 + +struct stack_context { + FILE *f; + Dwfl *dwfl; + Elf *elf; + unsigned n_thread; + unsigned n_frame; +}; + +static int frame_callback(Dwfl_Frame *frame, void *userdata) { + struct stack_context *c = userdata; + Dwarf_Addr pc, pc_adjusted, bias = 0; + _cleanup_free_ Dwarf_Die *scopes = NULL; + const char *fname = NULL, *symbol = NULL; + Dwfl_Module *module; + bool is_activation; + uint64_t module_offset = 0; + + assert(frame); + assert(c); + + if (c->n_frame >= FRAMES_MAX) + return DWARF_CB_ABORT; + + if (!dwfl_frame_pc(frame, &pc, &is_activation)) + return DWARF_CB_ABORT; + + pc_adjusted = pc - (is_activation ? 0 : 1); + + module = dwfl_addrmodule(c->dwfl, pc_adjusted); + if (module) { + Dwarf_Die *s, *cudie; + int n; + Dwarf_Addr start; + + cudie = dwfl_module_addrdie(module, pc_adjusted, &bias); + if (cudie) { + n = dwarf_getscopes(cudie, pc_adjusted - bias, &scopes); + for (s = scopes; s < scopes + n; s++) { + if (IN_SET(dwarf_tag(s), DW_TAG_subprogram, DW_TAG_inlined_subroutine, DW_TAG_entry_point)) { + Dwarf_Attribute *a, space; + + a = dwarf_attr_integrate(s, DW_AT_MIPS_linkage_name, &space); + if (!a) + a = dwarf_attr_integrate(s, DW_AT_linkage_name, &space); + if (a) + symbol = dwarf_formstring(a); + if (!symbol) + symbol = dwarf_diename(s); + + if (symbol) + break; + } + } + } + + if (!symbol) + symbol = dwfl_module_addrname(module, pc_adjusted); + + fname = dwfl_module_info(module, NULL, &start, NULL, NULL, NULL, NULL, NULL); + module_offset = pc - start; + } + + fprintf(c->f, "#%-2u 0x%016" PRIx64 " %s (%s + 0x%" PRIx64 ")\n", c->n_frame, (uint64_t) pc, strna(symbol), strna(fname), module_offset); + c->n_frame++; + + return DWARF_CB_OK; +} + +static int thread_callback(Dwfl_Thread *thread, void *userdata) { + struct stack_context *c = userdata; + pid_t tid; + + assert(thread); + assert(c); + + if (c->n_thread >= THREADS_MAX) + return DWARF_CB_ABORT; + + if (c->n_thread != 0) + fputc('\n', c->f); + + c->n_frame = 0; + + tid = dwfl_thread_tid(thread); + fprintf(c->f, "Stack trace of thread " PID_FMT ":\n", tid); + + if (dwfl_thread_getframes(thread, frame_callback, c) < 0) + return DWARF_CB_ABORT; + + c->n_thread++; + + return DWARF_CB_OK; +} + +static int make_stack_trace(int fd, const char *executable, char **ret) { + + static const Dwfl_Callbacks callbacks = { + .find_elf = dwfl_build_id_find_elf, + .find_debuginfo = dwfl_standard_find_debuginfo, + }; + + struct stack_context c = {}; + char *buf = NULL; + size_t sz = 0; + int r; + + assert(fd >= 0); + assert(ret); + + if (lseek(fd, 0, SEEK_SET) == (off_t) -1) + return -errno; + + c.f = open_memstream_unlocked(&buf, &sz); + if (!c.f) + return -ENOMEM; + + elf_version(EV_CURRENT); + + c.elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); + if (!c.elf) { + r = -EINVAL; + goto finish; + } + + c.dwfl = dwfl_begin(&callbacks); + if (!c.dwfl) { + r = -EINVAL; + goto finish; + } + + if (dwfl_core_file_report(c.dwfl, c.elf, executable) < 0) { + r = -EINVAL; + goto finish; + } + + if (dwfl_report_end(c.dwfl, NULL, NULL) != 0) { + r = -EINVAL; + goto finish; + } + + if (dwfl_core_file_attach(c.dwfl, c.elf) < 0) { + r = -EINVAL; + goto finish; + } + + if (dwfl_getthreads(c.dwfl, thread_callback, &c) < 0) { + r = -EINVAL; + goto finish; + } + + c.f = safe_fclose(c.f); + + *ret = TAKE_PTR(buf); + + r = 0; + +finish: + if (c.dwfl) + dwfl_end(c.dwfl); + + if (c.elf) + elf_end(c.elf); + + safe_fclose(c.f); + + free(buf); + + return r; +} + +void coredump_make_stack_trace(int fd, const char *executable, char **ret) { + int r; + + r = make_stack_trace(fd, executable, ret); + if (r == -EINVAL) + log_warning("Failed to generate stack trace: %s", dwfl_errmsg(dwfl_errno())); + else if (r < 0) + log_warning_errno(r, "Failed to generate stack trace: %m"); +} diff --git a/src/coredump/stacktrace.h b/src/coredump/stacktrace.h new file mode 100644 index 00000000..2462c763 --- /dev/null +++ b/src/coredump/stacktrace.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +void coredump_make_stack_trace(int fd, const char *executable, char **ret); diff --git a/src/coredump/test-coredump-vacuum.c b/src/coredump/test-coredump-vacuum.c new file mode 100644 index 00000000..75fb4428 --- /dev/null +++ b/src/coredump/test-coredump-vacuum.c @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "coredump-vacuum.h" + +int main(int argc, char *argv[]) { + + if (coredump_vacuum(-1, (uint64_t) -1, 70 * 1024) < 0) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c new file mode 100644 index 00000000..bf7a0fb2 --- /dev/null +++ b/src/cryptsetup/cryptsetup-generator.c @@ -0,0 +1,709 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dropin.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "fstab-util.h" +#include "generator.h" +#include "hashmap.h" +#include "id128-util.h" +#include "log.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "specifier.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "util.h" + +typedef struct crypto_device { + char *uuid; + char *keyfile; + char *keydev; + char *name; + char *options; + bool create; +} crypto_device; + +static const char *arg_dest = NULL; +static bool arg_enabled = true; +static bool arg_read_crypttab = true; +static const char *arg_crypttab = NULL; +static const char *arg_runtime_directory = NULL; +static bool arg_whitelist = false; +static Hashmap *arg_disks = NULL; +static char *arg_default_options = NULL; +static char *arg_default_keyfile = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_disks, hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(arg_default_options, freep); +STATIC_DESTRUCTOR_REGISTER(arg_default_keyfile, freep); + +static int split_keyspec(const char *keyspec, char **ret_keyfile, char **ret_keydev) { + _cleanup_free_ char *keyfile = NULL, *keydev = NULL; + const char *c; + + assert(ret_keyfile); + assert(ret_keydev); + + if (!keyspec) { + *ret_keyfile = *ret_keydev = NULL; + return 0; + } + + c = strrchr(keyspec, ':'); + if (c) { + /* The keydev part has to be either an absolute path to device node (/dev/something, + * /dev/foo/something, or even possibly /dev/foo/something:part), or a fstab device + * specification starting with LABEL= or similar. The keyfile part has the same syntax. + * + * Let's try to guess if the second part looks like a keydev specification, or just part of a + * filename with a colon. fstab_node_to_udev_node() will convert the fstab device syntax to + * an absolute path. If we didn't get an absolute path, assume that it is just part of the + * first keyfile argument. */ + + keydev = fstab_node_to_udev_node(c + 1); + if (!keydev) + return log_oom(); + + if (path_is_absolute(keydev)) + keyfile = strndup(keyspec, c-keyspec); + else { + log_debug("Keyspec argument contains a colon, but \"%s\" doesn't look like a device specification.\n" + "Assuming that \"%s\" is a single device specification.", + c + 1, keyspec); + keydev = mfree(keydev); + c = NULL; + } + } + + if (!c) + /* No keydev specified */ + keyfile = strdup(keyspec); + + if (!keyfile) + return log_oom(); + + *ret_keyfile = TAKE_PTR(keyfile); + *ret_keydev = TAKE_PTR(keydev); + + return 0; +} + +static int generate_keydev_mount(const char *name, const char *keydev, const char *keydev_timeout, bool canfail, char **unit, char **mount) { + _cleanup_free_ char *u = NULL, *where = NULL, *name_escaped = NULL, *device_unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + usec_t timeout_us; + + assert(name); + assert(keydev); + assert(unit); + assert(mount); + + r = mkdir_parents(arg_runtime_directory, 0755); + if (r < 0) + return r; + + r = mkdir(arg_runtime_directory, 0700); + if (r < 0 && errno != EEXIST) + return -errno; + + name_escaped = cescape(name); + if (!name_escaped) + return -ENOMEM; + + where = strjoin(arg_runtime_directory, "/keydev-", name_escaped); + if (!where) + return -ENOMEM; + + r = mkdir(where, 0700); + if (r < 0 && errno != EEXIST) + return -errno; + + r = unit_name_from_path(where, ".mount", &u); + if (r < 0) + return r; + + r = generator_open_unit_file(arg_dest, NULL, u, &f); + if (r < 0) + return r; + + fprintf(f, + "[Unit]\n" + "DefaultDependencies=no\n\n" + "[Mount]\n" + "What=%s\n" + "Where=%s\n" + "Options=ro%s\n", keydev, where, canfail ? ",nofail" : ""); + + if (keydev_timeout) { + r = parse_sec_fix_0(keydev_timeout, &timeout_us); + if (r >= 0) { + r = unit_name_from_path(keydev, ".device", &device_unit); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + r = write_drop_in_format(arg_dest, device_unit, 90, "device-timeout", + "# Automatically generated by systemd-cryptsetup-generator \n\n" + "[Unit]\nJobRunningTimeoutSec=%s", keydev_timeout); + if (r < 0) + return log_error_errno(r, "Failed to write device drop-in: %m"); + + } else + log_warning_errno(r, "Failed to parse %s, ignoring: %m", keydev_timeout); + + } + + r = fflush_and_check(f); + if (r < 0) + return r; + + *unit = TAKE_PTR(u); + *mount = TAKE_PTR(where); + + return 0; +} + +static int print_dependencies(FILE *f, const char* device_path) { + int r; + + if (STR_IN_SET(device_path, "-", "none")) + /* None, nothing to do */ + return 0; + + if (PATH_IN_SET(device_path, "/dev/urandom", "/dev/random", "/dev/hw_random")) { + /* RNG device, add random dep */ + fputs("After=systemd-random-seed.service\n", f); + return 0; + } + + _cleanup_free_ char *udev_node = fstab_node_to_udev_node(device_path); + if (!udev_node) + return log_oom(); + + if (path_equal(udev_node, "/dev/null")) + return 0; + + if (path_startswith(udev_node, "/dev/")) { + /* We are dealing with a block device, add dependency for correspoding unit */ + _cleanup_free_ char *unit = NULL; + + r = unit_name_from_path(udev_node, ".device", &unit); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + fprintf(f, "After=%1$s\nRequires=%1$s\n", unit); + } else { + /* Regular file, add mount dependency */ + _cleanup_free_ char *escaped_path = specifier_escape(device_path); + if (!escaped_path) + return log_oom(); + + fprintf(f, "RequiresMountsFor=%s\n", escaped_path); + } + + return 0; +} + +static int create_disk( + const char *name, + const char *device, + const char *password, + const char *keydev, + const char *options) { + + _cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL, + *keydev_mount = NULL, *keyfile_timeout_value = NULL, *password_escaped = NULL, + *filtered = NULL, *u_escaped = NULL, *filtered_escaped = NULL, *name_escaped = NULL, *header_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *dmname; + bool noauto, nofail, tmp, swap, netdev; + int r, detached_header, keyfile_can_timeout; + + assert(name); + assert(device); + + noauto = fstab_test_yes_no_option(options, "noauto\0" "auto\0"); + nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0"); + tmp = fstab_test_option(options, "tmp\0"); + swap = fstab_test_option(options, "swap\0"); + netdev = fstab_test_option(options, "_netdev\0"); + + keyfile_can_timeout = fstab_filter_options(options, "keyfile-timeout\0", NULL, &keyfile_timeout_value, NULL); + if (keyfile_can_timeout < 0) + return log_error_errno(keyfile_can_timeout, "Failed to parse keyfile-timeout= option value: %m"); + + detached_header = fstab_filter_options(options, "header\0", NULL, &header_path, NULL); + if (detached_header < 0) + return log_error_errno(detached_header, "Failed to parse header= option value: %m"); + + if (tmp && swap) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", + name); + + name_escaped = specifier_escape(name); + if (!name_escaped) + return log_oom(); + + e = unit_name_escape(name); + if (!e) + return log_oom(); + + u = fstab_node_to_udev_node(device); + if (!u) + return log_oom(); + + r = unit_name_build("systemd-cryptsetup", e, ".service", &n); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + u_escaped = specifier_escape(u); + if (!u_escaped) + return log_oom(); + + r = unit_name_from_path(u, ".device", &d); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + if (keydev && !password) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Key device is specified, but path to the password file is missing."); + + r = generator_open_unit_file(arg_dest, NULL, n, &f); + if (r < 0) + return r; + + fprintf(f, + "[Unit]\n" + "Description=Cryptography Setup for %%I\n" + "Documentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n" + "SourcePath=%s\n" + "DefaultDependencies=no\n" + "Conflicts=umount.target\n" + "IgnoreOnIsolate=true\n" + "After=%s\n", + arg_crypttab, + netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target"); + + if (password) { + password_escaped = specifier_escape(password); + if (!password_escaped) + return log_oom(); + } + + if (keydev) { + _cleanup_free_ char *unit = NULL, *p = NULL; + + r = generate_keydev_mount(name, keydev, keyfile_timeout_value, keyfile_can_timeout > 0, &unit, &keydev_mount); + if (r < 0) + return log_error_errno(r, "Failed to generate keydev mount unit: %m"); + + p = path_join(keydev_mount, password_escaped); + if (!p) + return log_oom(); + + free_and_replace(password_escaped, p); + + fprintf(f, "After=%s\n", unit); + if (keyfile_can_timeout > 0) + fprintf(f, "Wants=%s\n", unit); + else + fprintf(f, "Requires=%s\n", unit); + } + + if (!nofail) + fprintf(f, + "Before=%s\n", + netdev ? "remote-cryptsetup.target" : "cryptsetup.target"); + + if (password && !keydev) { + r = print_dependencies(f, password); + if (r < 0) + return r; + } + + /* Check if a header option was specified */ + if (detached_header > 0) { + r = print_dependencies(f, header_path); + if (r < 0) + return r; + } + + if (path_startswith(u, "/dev/")) { + fprintf(f, + "BindsTo=%s\n" + "After=%s\n" + "Before=umount.target\n", + d, d); + + if (swap) + fputs("Before=dev-mapper-%i.swap\n", + f); + } else + /* For loopback devices, add systemd-tmpfiles-setup-dev.service + dependency to ensure that loopback support is available in + the kernel (/dev/loop-control needs to exist) */ + fprintf(f, + "RequiresMountsFor=%s\n" + "Requires=systemd-tmpfiles-setup-dev.service\n" + "After=systemd-tmpfiles-setup-dev.service\n", + u_escaped); + + r = generator_write_timeouts(arg_dest, device, name, options, &filtered); + if (r < 0) + log_warning_errno(r, "Failed to write device timeout drop-in: %m"); + + if (filtered) { + filtered_escaped = specifier_escape(filtered); + if (!filtered_escaped) + return log_oom(); + } + + fprintf(f, + "\n[Service]\n" + "Type=oneshot\n" + "RemainAfterExit=yes\n" + "TimeoutSec=0\n" /* the binary handles timeouts anyway */ + "KeyringMode=shared\n" /* make sure we can share cached keys among instances */ + "OOMScoreAdjust=500\n" /* unlocking can allocate a lot of memory if Argon2 is used */ + "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '%s' '%s'\n" + "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n", + name_escaped, u_escaped, strempty(password_escaped), strempty(filtered_escaped), + name_escaped); + + if (tmp) + fprintf(f, + "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n", + name_escaped); + + if (swap) + fprintf(f, + "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n", + name_escaped); + + if (keydev) + fprintf(f, + "ExecStartPost=-" UMOUNT_PATH " %s\n\n", + keydev_mount); + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", n); + + if (!noauto) { + r = generator_add_symlink(arg_dest, + netdev ? "remote-cryptsetup.target" : "cryptsetup.target", + nofail ? "wants" : "requires", n); + if (r < 0) + return r; + } + + dmname = strjoina("dev-mapper-", e, ".device"); + r = generator_add_symlink(arg_dest, dmname, "requires", n); + if (r < 0) + return r; + + if (!noauto && !nofail) { + r = write_drop_in(arg_dest, dmname, 40, "device-timeout", + "# Automatically generated by systemd-cryptsetup-generator\n\n" + "[Unit]\nJobTimeoutSec=0"); + if (r < 0) + log_warning_errno(r, "Failed to write device timeout drop-in: %m"); + } + + return 0; +} + +static crypto_device* crypt_device_free(crypto_device *d) { + if (!d) + return NULL; + + free(d->uuid); + free(d->keyfile); + free(d->keydev); + free(d->name); + free(d->options); + return mfree(d); +} + +static crypto_device *get_crypto_device(const char *uuid) { + int r; + crypto_device *d; + + assert(uuid); + + d = hashmap_get(arg_disks, uuid); + if (!d) { + d = new0(struct crypto_device, 1); + if (!d) + return NULL; + + d->uuid = strdup(uuid); + if (!d->uuid) + return mfree(d); + + r = hashmap_put(arg_disks, d->uuid, d); + if (r < 0) { + free(d->uuid); + return mfree(d); + } + } + + return d; +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + _cleanup_free_ char *uuid = NULL, *uuid_value = NULL; + crypto_device *d; + int r; + + if (streq(key, "luks")) { + + r = value ? parse_boolean(value) : 1; + if (r < 0) + log_warning("Failed to parse luks= kernel command line switch %s. Ignoring.", value); + else + arg_enabled = r; + + } else if (streq(key, "luks.crypttab")) { + + r = value ? parse_boolean(value) : 1; + if (r < 0) + log_warning("Failed to parse luks.crypttab= kernel command line switch %s. Ignoring.", value); + else + arg_read_crypttab = r; + + } else if (streq(key, "luks.uuid")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + d = get_crypto_device(startswith(value, "luks-") ? value+5 : value); + if (!d) + return log_oom(); + + d->create = arg_whitelist = true; + + } else if (streq(key, "luks.options")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); + if (r == 2) { + d = get_crypto_device(uuid); + if (!d) + return log_oom(); + + free_and_replace(d->options, uuid_value); + } else if (free_and_strdup(&arg_default_options, value) < 0) + return log_oom(); + + } else if (streq(key, "luks.key")) { + size_t n; + _cleanup_free_ char *keyfile = NULL, *keydev = NULL; + const char *keyspec; + + if (proc_cmdline_value_missing(key, value)) + return 0; + + n = strspn(value, LETTERS DIGITS "-"); + if (value[n] != '=') { + if (free_and_strdup(&arg_default_keyfile, value) < 0) + return log_oom(); + return 0; + } + + uuid = strndup(value, n); + if (!uuid) + return log_oom(); + + if (!id128_is_valid(uuid)) { + log_warning("Failed to parse luks.key= kernel command line switch. UUID is invalid, ignoring."); + return 0; + } + + d = get_crypto_device(uuid); + if (!d) + return log_oom(); + + keyspec = value + n + 1; + r = split_keyspec(keyspec, &keyfile, &keydev); + if (r < 0) + return r; + + free_and_replace(d->keyfile, keyfile); + free_and_replace(d->keydev, keydev); + + } else if (streq(key, "luks.name")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); + if (r == 2) { + d = get_crypto_device(uuid); + if (!d) + return log_oom(); + + d->create = arg_whitelist = true; + + free_and_replace(d->name, uuid_value); + } else + log_warning("Failed to parse luks name switch %s. Ignoring.", value); + } + + return 0; +} + +static int add_crypttab_devices(void) { + _cleanup_fclose_ FILE *f = NULL; + unsigned crypttab_line = 0; + struct stat st; + int r; + + if (!arg_read_crypttab) + return 0; + + r = fopen_unlocked(arg_crypttab, "re", &f); + if (r < 0) { + if (errno != ENOENT) + log_error_errno(errno, "Failed to open %s: %m", arg_crypttab); + return 0; + } + + if (fstat(fileno(f), &st) < 0) { + log_error_errno(errno, "Failed to stat %s: %m", arg_crypttab); + return 0; + } + + for (;;) { + _cleanup_free_ char *line = NULL, *name = NULL, *device = NULL, *keyspec = NULL, *options = NULL, *keyfile = NULL, *keydev = NULL; + crypto_device *d = NULL; + char *l, *uuid; + int k; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read %s: %m", arg_crypttab); + if (r == 0) + break; + + crypttab_line++; + + l = strstrip(line); + if (IN_SET(l[0], 0, '#')) + continue; + + k = sscanf(l, "%ms %ms %ms %ms", &name, &device, &keyspec, &options); + if (k < 2 || k > 4) { + log_error("Failed to parse %s:%u, ignoring.", arg_crypttab, crypttab_line); + continue; + } + + uuid = startswith(device, "UUID="); + if (!uuid) + uuid = path_startswith(device, "/dev/disk/by-uuid/"); + if (!uuid) + uuid = startswith(name, "luks-"); + if (uuid) + d = hashmap_get(arg_disks, uuid); + + if (arg_whitelist && !d) { + log_info("Not creating device '%s' because it was not specified on the kernel command line.", name); + continue; + } + + r = split_keyspec(keyspec, &keyfile, &keydev); + if (r < 0) + return r; + + r = create_disk(name, device, keyfile, keydev, (d && d->options) ? d->options : options); + if (r < 0) + return r; + + if (d) + d->create = false; + } + + return 0; +} + +static int add_proc_cmdline_devices(void) { + int r; + Iterator i; + crypto_device *d; + + HASHMAP_FOREACH(d, arg_disks, i) { + _cleanup_free_ char *device = NULL; + + if (!d->create) + continue; + + if (!d->name) { + d->name = strjoin("luks-", d->uuid); + if (!d->name) + return log_oom(); + } + + device = strjoin("UUID=", d->uuid); + if (!device) + return log_oom(); + + r = create_disk(d->name, + device, + d->keyfile ?: arg_default_keyfile, + d->keydev, + d->options ?: arg_default_options); + if (r < 0) + return r; + } + + return 0; +} + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(crypt_device_hash_ops, char, string_hash_func, string_compare_func, + crypto_device, crypt_device_free); + +static int run(const char *dest, const char *dest_early, const char *dest_late) { + int r; + + assert_se(arg_dest = dest); + + arg_crypttab = getenv("SYSTEMD_CRYPTTAB") ?: "/etc/crypttab"; + arg_runtime_directory = getenv("RUNTIME_DIRECTORY") ?: "/run/systemd/cryptsetup"; + + arg_disks = hashmap_new(&crypt_device_hash_ops); + if (!arg_disks) + return log_oom(); + + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); + if (r < 0) + return log_warning_errno(r, "Failed to parse kernel command line: %m"); + + if (!arg_enabled) + return 0; + + r = add_crypttab_devices(); + if (r < 0) + return r; + + r = add_proc_cmdline_devices(); + if (r < 0) + return r; + + return 0; +} + +DEFINE_MAIN_GENERATOR_FUNCTION(run); diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c new file mode 100644 index 00000000..8723eb4c --- /dev/null +++ b/src/cryptsetup/cryptsetup.c @@ -0,0 +1,766 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "sd-device.h" + +#include "alloc-util.h" +#include "ask-password-api.h" +#include "crypt-util.h" +#include "device-util.h" +#include "escape.h" +#include "fileio.h" +#include "fstab-util.h" +#include "log.h" +#include "main-func.h" +#include "mount-util.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "string-util.h" +#include "strv.h" + +/* internal helper */ +#define ANY_LUKS "LUKS" +/* as in src/cryptsetup.h */ +#define CRYPT_SECTOR_SIZE 512 +#define CRYPT_MAX_SECTOR_SIZE 4096 + +static const char *arg_type = NULL; /* ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2, CRYPT_TCRYPT or CRYPT_PLAIN */ +static char *arg_cipher = NULL; +static unsigned arg_key_size = 0; +static unsigned arg_sector_size = CRYPT_SECTOR_SIZE; +static int arg_key_slot = CRYPT_ANY_SLOT; +static unsigned arg_keyfile_size = 0; +static uint64_t arg_keyfile_offset = 0; +static char *arg_hash = NULL; +static char *arg_header = NULL; +static unsigned arg_tries = 3; +static bool arg_readonly = false; +static bool arg_verify = false; +static bool arg_discards = false; +static bool arg_same_cpu_crypt = false; +static bool arg_submit_from_crypt_cpus = false; +static bool arg_tcrypt_hidden = false; +static bool arg_tcrypt_system = false; +static bool arg_tcrypt_veracrypt = false; +static char **arg_tcrypt_keyfiles = NULL; +static uint64_t arg_offset = 0; +static uint64_t arg_skip = 0; +static usec_t arg_timeout = USEC_INFINITY; + +STATIC_DESTRUCTOR_REGISTER(arg_cipher, freep); +STATIC_DESTRUCTOR_REGISTER(arg_hash, freep); +STATIC_DESTRUCTOR_REGISTER(arg_header, freep); +STATIC_DESTRUCTOR_REGISTER(arg_tcrypt_keyfiles, strv_freep); + +/* Options Debian's crypttab knows we don't: + + precheck= + check= + checkargs= + noearly= + loud= + keyscript= +*/ + +static int parse_one_option(const char *option) { + const char *val; + int r; + + assert(option); + + /* Handled outside of this tool */ + if (STR_IN_SET(option, "noauto", "auto", "nofail", "fail", "_netdev", "keyfile-timeout")) + return 0; + + if (startswith(option, "keyfile-timeout=")) + return 0; + + if ((val = startswith(option, "cipher="))) { + r = free_and_strdup(&arg_cipher, val); + if (r < 0) + return log_oom(); + + } else if ((val = startswith(option, "size="))) { + + r = safe_atou(val, &arg_key_size); + if (r < 0) { + log_error_errno(r, "Failed to parse %s, ignoring: %m", option); + return 0; + } + + if (arg_key_size % 8) { + log_error("size= not a multiple of 8, ignoring."); + return 0; + } + + arg_key_size /= 8; + + } else if ((val = startswith(option, "sector-size="))) { + + r = safe_atou(val, &arg_sector_size); + if (r < 0) { + log_error_errno(r, "Failed to parse %s, ignoring: %m", option); + return 0; + } + + if (arg_sector_size % 2) { + log_error("sector-size= not a multiple of 2, ignoring."); + return 0; + } + + if (arg_sector_size < CRYPT_SECTOR_SIZE || arg_sector_size > CRYPT_MAX_SECTOR_SIZE) { + log_error("sector-size= is outside of %u and %u, ignoring.", CRYPT_SECTOR_SIZE, CRYPT_MAX_SECTOR_SIZE); + return 0; + } + + } else if ((val = startswith(option, "key-slot="))) { + + arg_type = ANY_LUKS; + r = safe_atoi(val, &arg_key_slot); + if (r < 0) { + log_error_errno(r, "Failed to parse %s, ignoring: %m", option); + return 0; + } + + } else if ((val = startswith(option, "tcrypt-keyfile="))) { + + arg_type = CRYPT_TCRYPT; + if (path_is_absolute(val)) { + if (strv_extend(&arg_tcrypt_keyfiles, val) < 0) + return log_oom(); + } else + log_error("Key file path \"%s\" is not absolute. Ignoring.", val); + + } else if ((val = startswith(option, "keyfile-size="))) { + + r = safe_atou(val, &arg_keyfile_size); + if (r < 0) { + log_error_errno(r, "Failed to parse %s, ignoring: %m", option); + return 0; + } + + } else if ((val = startswith(option, "keyfile-offset="))) { + + r = safe_atou64(val, &arg_keyfile_offset); + if (r < 0) { + log_error_errno(r, "Failed to parse %s, ignoring: %m", option); + return 0; + } + + } else if ((val = startswith(option, "hash="))) { + r = free_and_strdup(&arg_hash, val); + if (r < 0) + return log_oom(); + + } else if ((val = startswith(option, "header="))) { + arg_type = ANY_LUKS; + + if (!path_is_absolute(val)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Header path \"%s\" is not absolute, refusing.", val); + + if (arg_header) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Duplicate header= option, refusing."); + + arg_header = strdup(val); + if (!arg_header) + return log_oom(); + + } else if ((val = startswith(option, "tries="))) { + + r = safe_atou(val, &arg_tries); + if (r < 0) { + log_error_errno(r, "Failed to parse %s, ignoring: %m", option); + return 0; + } + + } else if (STR_IN_SET(option, "readonly", "read-only")) + arg_readonly = true; + else if (streq(option, "verify")) + arg_verify = true; + else if (STR_IN_SET(option, "allow-discards", "discard")) + arg_discards = true; + else if (streq(option, "same-cpu-crypt")) + arg_same_cpu_crypt = true; + else if (streq(option, "submit-from-crypt-cpus")) + arg_submit_from_crypt_cpus = true; + else if (streq(option, "luks")) + arg_type = ANY_LUKS; + else if (streq(option, "tcrypt")) + arg_type = CRYPT_TCRYPT; + else if (streq(option, "tcrypt-hidden")) { + arg_type = CRYPT_TCRYPT; + arg_tcrypt_hidden = true; + } else if (streq(option, "tcrypt-system")) { + arg_type = CRYPT_TCRYPT; + arg_tcrypt_system = true; + } else if (streq(option, "tcrypt-veracrypt")) { + arg_type = CRYPT_TCRYPT; + arg_tcrypt_veracrypt = true; + } else if (STR_IN_SET(option, "plain", "swap", "tmp")) + arg_type = CRYPT_PLAIN; + else if ((val = startswith(option, "timeout="))) { + + r = parse_sec_fix_0(val, &arg_timeout); + if (r < 0) { + log_error_errno(r, "Failed to parse %s, ignoring: %m", option); + return 0; + } + + } else if ((val = startswith(option, "offset="))) { + + r = safe_atou64(val, &arg_offset); + if (r < 0) + return log_error_errno(r, "Failed to parse %s: %m", option); + + } else if ((val = startswith(option, "skip="))) { + + r = safe_atou64(val, &arg_skip); + if (r < 0) + return log_error_errno(r, "Failed to parse %s: %m", option); + + } else + log_warning("Encountered unknown /etc/crypttab option '%s', ignoring.", option); + + return 0; +} + +static int parse_options(const char *options) { + const char *word, *state; + size_t l; + int r; + + assert(options); + + FOREACH_WORD_SEPARATOR(word, l, options, ",", state) { + _cleanup_free_ char *o; + + o = strndup(word, l); + if (!o) + return -ENOMEM; + r = parse_one_option(o); + if (r < 0) + return r; + } + + /* sanity-check options */ + if (arg_type && !streq(arg_type, CRYPT_PLAIN)) { + if (arg_offset != 0) + log_warning("offset= ignored with type %s", arg_type); + if (arg_skip != 0) + log_warning("skip= ignored with type %s", arg_type); + } + + return 0; +} + +static char* disk_description(const char *path) { + static const char name_fields[] = + "ID_PART_ENTRY_NAME\0" + "DM_NAME\0" + "ID_MODEL_FROM_DATABASE\0" + "ID_MODEL\0"; + + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + const char *i, *name; + struct stat st; + + assert(path); + + if (stat(path, &st) < 0) + return NULL; + + if (!S_ISBLK(st.st_mode)) + return NULL; + + if (sd_device_new_from_devnum(&device, 'b', st.st_rdev) < 0) + return NULL; + + NULSTR_FOREACH(i, name_fields) + if (sd_device_get_property_value(device, i, &name) >= 0 && + !isempty(name)) + return strdup(name); + + return NULL; +} + +static char *disk_mount_point(const char *label) { + _cleanup_free_ char *device = NULL; + _cleanup_endmntent_ FILE *f = NULL; + struct mntent *m; + + /* Yeah, we don't support native systemd unit files here for now */ + + if (asprintf(&device, "/dev/mapper/%s", label) < 0) + return NULL; + + f = setmntent(fstab_path(), "re"); + if (!f) + return NULL; + + while ((m = getmntent(f))) + if (path_equal(m->mnt_fsname, device)) + return strdup(m->mnt_dir); + + return NULL; +} + +static int get_password(const char *vol, const char *src, usec_t until, bool accept_cached, char ***ret) { + _cleanup_free_ char *description = NULL, *name_buffer = NULL, *mount_point = NULL, *text = NULL, *disk_path = NULL; + _cleanup_strv_free_erase_ char **passwords = NULL; + const char *name = NULL; + char **p, *id; + int r = 0; + + assert(vol); + assert(src); + assert(ret); + + description = disk_description(src); + mount_point = disk_mount_point(vol); + + disk_path = cescape(src); + if (!disk_path) + return log_oom(); + + if (description && streq(vol, description)) + /* If the description string is simply the + * volume name, then let's not show this + * twice */ + description = mfree(description); + + if (mount_point && description) + r = asprintf(&name_buffer, "%s (%s) on %s", description, vol, mount_point); + else if (mount_point) + r = asprintf(&name_buffer, "%s on %s", vol, mount_point); + else if (description) + r = asprintf(&name_buffer, "%s (%s)", description, vol); + + if (r < 0) + return log_oom(); + + name = name_buffer ? name_buffer : vol; + + if (asprintf(&text, "Please enter passphrase for disk %s:", name) < 0) + return log_oom(); + + id = strjoina("cryptsetup:", disk_path); + + r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until, + ASK_PASSWORD_PUSH_CACHE | (accept_cached*ASK_PASSWORD_ACCEPT_CACHED), + &passwords); + if (r < 0) + return log_error_errno(r, "Failed to query password: %m"); + + if (arg_verify) { + _cleanup_strv_free_erase_ char **passwords2 = NULL; + + assert(strv_length(passwords) == 1); + + if (asprintf(&text, "Please enter passphrase for disk %s (verification):", name) < 0) + return log_oom(); + + id = strjoina("cryptsetup-verification:", disk_path); + + r = ask_password_auto(text, "drive-harddisk", id, "cryptsetup", until, ASK_PASSWORD_PUSH_CACHE, &passwords2); + if (r < 0) + return log_error_errno(r, "Failed to query verification password: %m"); + + assert(strv_length(passwords2) == 1); + + if (!streq(passwords[0], passwords2[0])) { + log_warning("Passwords did not match, retrying."); + return -EAGAIN; + } + } + + strv_uniq(passwords); + + STRV_FOREACH(p, passwords) { + char *c; + + if (strlen(*p)+1 >= arg_key_size) + continue; + + /* Pad password if necessary */ + c = new(char, arg_key_size); + if (!c) + return log_oom(); + + strncpy(c, *p, arg_key_size); + free_and_replace(*p, c); + } + + *ret = TAKE_PTR(passwords); + + return 0; +} + +static int attach_tcrypt( + struct crypt_device *cd, + const char *name, + const char *key_file, + char **passwords, + uint32_t flags) { + + int r = 0; + _cleanup_free_ char *passphrase = NULL; + struct crypt_params_tcrypt params = { + .flags = CRYPT_TCRYPT_LEGACY_MODES, + .keyfiles = (const char **)arg_tcrypt_keyfiles, + .keyfiles_count = strv_length(arg_tcrypt_keyfiles) + }; + + assert(cd); + assert(name); + assert(key_file || (passwords && passwords[0])); + + if (arg_tcrypt_hidden) + params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER; + + if (arg_tcrypt_system) + params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER; + + if (arg_tcrypt_veracrypt) + params.flags |= CRYPT_TCRYPT_VERA_MODES; + + if (key_file) { + r = read_one_line_file(key_file, &passphrase); + if (r < 0) { + log_error_errno(r, "Failed to read password file '%s': %m", key_file); + return -EAGAIN; /* log with the actual error, but return EAGAIN */ + } + + params.passphrase = passphrase; + } else + params.passphrase = passwords[0]; + params.passphrase_size = strlen(params.passphrase); + + r = crypt_load(cd, CRYPT_TCRYPT, ¶ms); + if (r < 0) { + if (key_file && r == -EPERM) { + log_error_errno(r, "Failed to activate using password file '%s'. (Key data not correct?)", key_file); + return -EAGAIN; /* log the actual error, but return EAGAIN */ + } + + return log_error_errno(r, "Failed to load tcrypt superblock on device %s: %m", crypt_get_device_name(cd)); + } + + r = crypt_activate_by_volume_key(cd, name, NULL, 0, flags); + if (r < 0) + return log_error_errno(r, "Failed to activate tcrypt device %s: %m", crypt_get_device_name(cd)); + + return 0; +} + +static int attach_luks_or_plain( + struct crypt_device *cd, + const char *name, + const char *key_file, + char **passwords, + uint32_t flags) { + + int r = 0; + bool pass_volume_key = false; + + assert(cd); + assert(name); + assert(key_file || passwords); + + if ((!arg_type && !crypt_get_type(cd)) || streq_ptr(arg_type, CRYPT_PLAIN)) { + struct crypt_params_plain params = { + .offset = arg_offset, + .skip = arg_skip, + .sector_size = arg_sector_size, + }; + const char *cipher, *cipher_mode; + _cleanup_free_ char *truncated_cipher = NULL; + + if (arg_hash) { + /* plain isn't a real hash type. it just means "use no hash" */ + if (!streq(arg_hash, "plain")) + params.hash = arg_hash; + } else if (!key_file) + /* for CRYPT_PLAIN, the behaviour of cryptsetup + * package is to not hash when a key file is provided */ + params.hash = "ripemd160"; + + if (arg_cipher) { + size_t l; + + l = strcspn(arg_cipher, "-"); + truncated_cipher = strndup(arg_cipher, l); + if (!truncated_cipher) + return log_oom(); + + cipher = truncated_cipher; + cipher_mode = arg_cipher[l] ? arg_cipher+l+1 : "plain"; + } else { + cipher = "aes"; + cipher_mode = "cbc-essiv:sha256"; + } + + /* for CRYPT_PLAIN limit reads from keyfile to key length, and ignore keyfile-size */ + arg_keyfile_size = arg_key_size; + + /* In contrast to what the name crypt_format() might suggest this doesn't actually format + * anything, it just configures encryption parameters when used for plain mode. */ + r = crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, arg_keyfile_size, ¶ms); + if (r < 0) + return log_error_errno(r, "Loading of cryptographic parameters failed: %m"); + + /* hash == NULL implies the user passed "plain" */ + pass_volume_key = (params.hash == NULL); + } + + log_info("Set cipher %s, mode %s, key size %i bits for device %s.", + crypt_get_cipher(cd), + crypt_get_cipher_mode(cd), + crypt_get_volume_key_size(cd)*8, + crypt_get_device_name(cd)); + + if (key_file) { + r = crypt_activate_by_keyfile_device_offset(cd, name, arg_key_slot, key_file, arg_keyfile_size, arg_keyfile_offset, flags); + if (r == -EPERM) { + log_error_errno(r, "Failed to activate with key file '%s'. (Key data incorrect?)", key_file); + return -EAGAIN; /* Log actual error, but return EAGAIN */ + } + if (r == -EINVAL) { + log_error_errno(r, "Failed to activate with key file '%s'. (Key file missing?)", key_file); + return -EAGAIN; /* Log actual error, but return EAGAIN */ + } + if (r < 0) + return log_error_errno(r, "Failed to activate with key file '%s': %m", key_file); + + } else { + char **p; + + r = -EINVAL; + STRV_FOREACH(p, passwords) { + if (pass_volume_key) + r = crypt_activate_by_volume_key(cd, name, *p, arg_key_size, flags); + else + r = crypt_activate_by_passphrase(cd, name, arg_key_slot, *p, strlen(*p), flags); + if (r >= 0) + break; + } + if (r == -EPERM) { + log_error_errno(r, "Failed to activate with specified passphrase. (Passphrase incorrect?)"); + return -EAGAIN; /* log actual error, but return EAGAIN */ + } + if (r < 0) + return log_error_errno(r, "Failed to activate with specified passphrase: %m"); + } + + return r; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-cryptsetup@.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s attach VOLUME SOURCEDEVICE [PASSWORD] [OPTIONS]\n" + "%s detach VOLUME\n\n" + "Attaches or detaches an encrypted block device.\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , program_invocation_short_name + , link + ); + + return 0; +} + +static uint32_t determine_flags(void) { + uint32_t flags = 0; + + if (arg_readonly) + flags |= CRYPT_ACTIVATE_READONLY; + + if (arg_discards) + flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; + + if (arg_same_cpu_crypt) + flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT; + + if (arg_submit_from_crypt_cpus) + flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS; + +#ifdef CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF + /* Try to decrease the risk of OOM event if memory hard key derivation function is in use */ + /* https://gitlab.com/cryptsetup/cryptsetup/issues/446/ */ + flags |= CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF; +#endif + + return flags; +} + +static int run(int argc, char *argv[]) { + _cleanup_(crypt_freep) struct crypt_device *cd = NULL; + int r; + + if (argc <= 1) + return help(); + + if (argc < 3) { + log_error("This program requires at least two arguments."); + return -EINVAL; + } + + log_setup_service(); + + crypt_set_log_callback(NULL, cryptsetup_log_glue, NULL); + if (DEBUG_LOGGING) + /* libcryptsetup won't even consider debug messages by default */ + crypt_set_debug_level(CRYPT_DEBUG_ALL); + + umask(0022); + + if (streq(argv[1], "attach")) { + uint32_t flags = 0; + unsigned tries; + usec_t until; + crypt_status_info status; + const char *key_file = NULL; + + /* Arguments: systemd-cryptsetup attach VOLUME SOURCE-DEVICE [PASSWORD] [OPTIONS] */ + + if (argc < 4) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least two arguments."); + + if (argc >= 5 && !STR_IN_SET(argv[4], "", "-", "none")) { + if (path_is_absolute(argv[4])) + key_file = argv[4]; + else + log_warning("Password file path '%s' is not absolute. Ignoring.", argv[4]); + } + + if (argc >= 6 && !STR_IN_SET(argv[5], "", "-", "none")) { + r = parse_options(argv[5]); + if (r < 0) + return r; + } + + /* A delicious drop of snake oil */ + (void) mlockall(MCL_FUTURE); + + if (arg_header) { + log_debug("LUKS header: %s", arg_header); + r = crypt_init(&cd, arg_header); + } else + r = crypt_init(&cd, argv[3]); + if (r < 0) + return log_error_errno(r, "crypt_init() failed: %m"); + + crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); + + status = crypt_status(cd, argv[2]); + if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) { + log_info("Volume %s already active.", argv[2]); + return 0; + } + + flags = determine_flags(); + + if (arg_timeout == USEC_INFINITY) + until = 0; + else + until = now(CLOCK_MONOTONIC) + arg_timeout; + + arg_key_size = (arg_key_size > 0 ? arg_key_size : (256 / 8)); + + if (key_file) { + struct stat st; + + /* Ideally we'd do this on the open fd, but since this is just a + * warning it's OK to do this in two steps. */ + if (stat(key_file, &st) >= 0 && S_ISREG(st.st_mode) && (st.st_mode & 0005)) + log_warning("Key file %s is world-readable. This is not a good idea!", key_file); + } + + if (!arg_type || STR_IN_SET(arg_type, ANY_LUKS, CRYPT_LUKS1)) { + r = crypt_load(cd, CRYPT_LUKS, NULL); + if (r < 0) + return log_error_errno(r, "Failed to load LUKS superblock on device %s: %m", crypt_get_device_name(cd)); + + if (arg_header) { + r = crypt_set_data_device(cd, argv[3]); + if (r < 0) + return log_error_errno(r, "Failed to set LUKS data device %s: %m", argv[3]); + } + + /* Tokens are available in LUKS2 only, but it is ok to call (and fail) with LUKS1. */ + if (!key_file) { + r = crypt_activate_by_token(cd, argv[2], CRYPT_ANY_TOKEN, NULL, flags); + if (r >= 0) { + log_debug("Volume %s activated with LUKS token id %i.", argv[2], r); + return 0; + } + + log_debug_errno(r, "Token activation unsuccessful for device %s: %m", crypt_get_device_name(cd)); + } + } + + for (tries = 0; arg_tries == 0 || tries < arg_tries; tries++) { + _cleanup_strv_free_erase_ char **passwords = NULL; + + if (!key_file) { + r = get_password(argv[2], argv[3], until, tries == 0 && !arg_verify, &passwords); + if (r == -EAGAIN) + continue; + if (r < 0) + return r; + } + + if (streq_ptr(arg_type, CRYPT_TCRYPT)) + r = attach_tcrypt(cd, argv[2], key_file, passwords, flags); + else + r = attach_luks_or_plain(cd, argv[2], key_file, passwords, flags); + if (r >= 0) + break; + if (r != -EAGAIN) + return r; + + /* Passphrase not correct? Let's try again! */ + key_file = NULL; + } + + if (arg_tries != 0 && tries >= arg_tries) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Too many attempts to activate; giving up."); + + } else if (streq(argv[1], "detach")) { + + r = crypt_init_by_name(&cd, argv[2]); + if (r == -ENODEV) { + log_info("Volume %s already inactive.", argv[2]); + return 0; + } + if (r < 0) + return log_error_errno(r, "crypt_init_by_name() failed: %m"); + + crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); + + r = crypt_deactivate(cd, argv[2]); + if (r < 0) + return log_error_errno(r, "Failed to deactivate: %m"); + + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb %s.", argv[1]); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c new file mode 100644 index 00000000..bc8714c4 --- /dev/null +++ b/src/debug-generator/debug-generator.c @@ -0,0 +1,190 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "dropin.h" +#include "generator.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "special.h" +#include "string-util.h" +#include "strv.h" +#include "unit-file.h" +#include "unit-name.h" + +static const char *arg_dest = NULL; +static char *arg_default_unit = NULL; +static char **arg_mask = NULL; +static char **arg_wants = NULL; +static char *arg_debug_shell = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_default_unit, freep); +STATIC_DESTRUCTOR_REGISTER(arg_mask, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_wants, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_debug_shell, freep); + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + int r; + + assert(key); + + if (streq(key, "systemd.mask")) { + char *n; + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = unit_name_mangle(value, UNIT_NAME_MANGLE_WARN, &n); + if (r < 0) + return log_error_errno(r, "Failed to glob unit name: %m"); + + r = strv_consume(&arg_mask, n); + if (r < 0) + return log_oom(); + + } else if (streq(key, "systemd.wants")) { + char *n; + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = unit_name_mangle(value, UNIT_NAME_MANGLE_WARN, &n); + if (r < 0) + return log_error_errno(r, "Failed to glob unit name: %m"); + + r = strv_consume(&arg_wants, n); + if (r < 0) + return log_oom(); + + } else if (proc_cmdline_key_streq(key, "systemd.debug_shell")) { + const char *t = NULL; + + r = value ? parse_boolean(value) : 1; + if (r < 0) + t = skip_dev_prefix(value); + else if (r > 0) + t = skip_dev_prefix(DEBUGTTY); + + if (free_and_strdup(&arg_debug_shell, t) < 0) + return log_oom(); + + } else if (streq(key, "systemd.unit")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = free_and_strdup(&arg_default_unit, value); + if (r < 0) + return log_error_errno(r, "Failed to set default unit %s: %m", value); + + } else if (!value) { + const char *target; + + target = runlevel_to_target(key); + if (target) { + r = free_and_strdup(&arg_default_unit, target); + if (r < 0) + return log_error_errno(r, "Failed to set default unit %s: %m", target); + } + } + + return 0; +} + +static int generate_mask_symlinks(void) { + char **u; + int r = 0; + + if (strv_isempty(arg_mask)) + return 0; + + STRV_FOREACH(u, arg_mask) { + _cleanup_free_ char *p = NULL; + + p = path_join(empty_to_root(arg_dest), *u); + if (!p) + return log_oom(); + + if (symlink("/dev/null", p) < 0) + r = log_error_errno(errno, + "Failed to create mask symlink %s: %m", + p); + } + + return r; +} + +static int generate_wants_symlinks(void) { + char **u; + int r = 0; + + if (strv_isempty(arg_wants)) + return 0; + + STRV_FOREACH(u, arg_wants) { + _cleanup_free_ char *p = NULL, *f = NULL; + const char *target = arg_default_unit ?: SPECIAL_DEFAULT_TARGET; + + p = strjoin(arg_dest, "/", target, ".wants/", *u); + if (!p) + return log_oom(); + + f = path_join(SYSTEM_DATA_UNIT_PATH, *u); + if (!f) + return log_oom(); + + mkdir_parents_label(p, 0755); + + if (symlink(f, p) < 0) + r = log_error_errno(errno, + "Failed to create wants symlink %s: %m", + p); + } + + return r; +} + +static void install_debug_shell_dropin(const char *dir) { + int r; + + if (streq(arg_debug_shell, skip_dev_prefix(DEBUGTTY))) + return; + + r = write_drop_in_format(dir, "debug-shell.service", 50, "tty", + "[Unit]\n" + "Description=Early root shell on /dev/%s FOR DEBUGGING ONLY\n" + "ConditionPathExists=\n" + "[Service]\n" + "TTYPath=/dev/%s", + arg_debug_shell, arg_debug_shell); + if (r < 0) + log_warning_errno(r, "Failed to write drop-in for debug-shell.service, ignoring: %m"); +} + +static int run(const char *dest, const char *dest_early, const char *dest_late) { + int r, q; + + assert_se(arg_dest = dest_early); + + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_RD_STRICT | PROC_CMDLINE_STRIP_RD_PREFIX); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + if (arg_debug_shell) { + r = strv_extend(&arg_wants, "debug-shell.service"); + if (r < 0) + return log_oom(); + + install_debug_shell_dropin(arg_dest); + } + + r = generate_mask_symlinks(); + q = generate_wants_symlinks(); + + return r < 0 ? r : q; +} + +DEFINE_MAIN_GENERATOR_FUNCTION(run); diff --git a/src/delta/delta.c b/src/delta/delta.c new file mode 100644 index 00000000..2d80d3a6 --- /dev/null +++ b/src/delta/delta.c @@ -0,0 +1,690 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "locale-util.h" +#include "log.h" +#include "main-func.h" +#include "nulstr-util.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "process-util.h" +#include "signal-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" + +static const char prefixes[] = + "/etc\0" + "/run\0" + "/usr/local/lib\0" + "/usr/local/share\0" + "/usr/lib\0" + "/usr/share\0" +#if HAVE_SPLIT_USR + "/lib\0" +#endif + ; + +static const char suffixes[] = + "sysctl.d\0" + "tmpfiles.d\0" + "modules-load.d\0" + "binfmt.d\0" + "systemd/system\0" + "systemd/user\0" + "systemd/system-preset\0" + "systemd/user-preset\0" + "udev/rules.d\0" + "modprobe.d\0"; + +static const char have_dropins[] = + "systemd/system\0" + "systemd/user\0"; + +static PagerFlags arg_pager_flags = 0; +static int arg_diff = -1; + +static enum { + SHOW_MASKED = 1 << 0, + SHOW_EQUIVALENT = 1 << 1, + SHOW_REDIRECTED = 1 << 2, + SHOW_OVERRIDDEN = 1 << 3, + SHOW_UNCHANGED = 1 << 4, + SHOW_EXTENDED = 1 << 5, + + SHOW_DEFAULTS = + (SHOW_MASKED | SHOW_EQUIVALENT | SHOW_REDIRECTED | SHOW_OVERRIDDEN | SHOW_EXTENDED) +} arg_flags = 0; + +static int equivalent(const char *a, const char *b) { + _cleanup_free_ char *x = NULL, *y = NULL; + int r; + + r = chase_symlinks(a, NULL, CHASE_TRAIL_SLASH, &x, NULL); + if (r < 0) + return r; + + r = chase_symlinks(b, NULL, CHASE_TRAIL_SLASH, &y, NULL); + if (r < 0) + return r; + + return path_equal(x, y); +} + +static int notify_override_masked(const char *top, const char *bottom) { + if (!(arg_flags & SHOW_MASKED)) + return 0; + + printf("%s%s%s %s %s %s\n", + ansi_highlight_red(), "[MASKED]", ansi_normal(), + top, special_glyph(SPECIAL_GLYPH_ARROW), bottom); + return 1; +} + +static int notify_override_equivalent(const char *top, const char *bottom) { + if (!(arg_flags & SHOW_EQUIVALENT)) + return 0; + + printf("%s%s%s %s %s %s\n", + ansi_highlight_green(), "[EQUIVALENT]", ansi_normal(), + top, special_glyph(SPECIAL_GLYPH_ARROW), bottom); + return 1; +} + +static int notify_override_redirected(const char *top, const char *bottom) { + if (!(arg_flags & SHOW_REDIRECTED)) + return 0; + + printf("%s%s%s %s %s %s\n", + ansi_highlight(), "[REDIRECTED]", ansi_normal(), + top, special_glyph(SPECIAL_GLYPH_ARROW), bottom); + return 1; +} + +static int notify_override_overridden(const char *top, const char *bottom) { + if (!(arg_flags & SHOW_OVERRIDDEN)) + return 0; + + printf("%s%s%s %s %s %s\n", + ansi_highlight(), "[OVERRIDDEN]", ansi_normal(), + top, special_glyph(SPECIAL_GLYPH_ARROW), bottom); + return 1; +} + +static int notify_override_extended(const char *top, const char *bottom) { + if (!(arg_flags & SHOW_EXTENDED)) + return 0; + + printf("%s%s%s %s %s %s\n", + ansi_highlight(), "[EXTENDED]", ansi_normal(), + top, special_glyph(SPECIAL_GLYPH_ARROW), bottom); + return 1; +} + +static int notify_override_unchanged(const char *f) { + if (!(arg_flags & SHOW_UNCHANGED)) + return 0; + + printf("[UNCHANGED] %s\n", f); + return 1; +} + +static int found_override(const char *top, const char *bottom) { + _cleanup_free_ char *dest = NULL; + pid_t pid; + int r; + + assert(top); + assert(bottom); + + if (null_or_empty_path(top) > 0) + return notify_override_masked(top, bottom); + + r = readlink_malloc(top, &dest); + if (r >= 0) { + if (equivalent(dest, bottom) > 0) + return notify_override_equivalent(top, bottom); + else + return notify_override_redirected(top, bottom); + } + + r = notify_override_overridden(top, bottom); + if (!arg_diff) + return r; + + putchar('\n'); + + fflush(stdout); + + r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + execlp("diff", "diff", "-us", "--", bottom, top, NULL); + log_open(); + log_error_errno(errno, "Failed to execute diff: %m"); + _exit(EXIT_FAILURE); + } + + (void) wait_for_terminate_and_check("diff", pid, WAIT_LOG_ABNORMAL); + putchar('\n'); + + return r; +} + +static int enumerate_dir_d( + OrderedHashmap *top, + OrderedHashmap *bottom, + OrderedHashmap *drops, + const char *toppath, const char *drop) { + + _cleanup_free_ char *unit = NULL; + _cleanup_free_ char *path = NULL; + _cleanup_strv_free_ char **list = NULL; + char **file; + char *c; + int r; + + assert(!endswith(drop, "/")); + + path = path_join(toppath, drop); + if (!path) + return -ENOMEM; + + log_debug("Looking at %s", path); + + unit = strdup(drop); + if (!unit) + return -ENOMEM; + + c = strrchr(unit, '.'); + if (!c) + return -EINVAL; + *c = 0; + + r = get_files_in_directory(path, &list); + if (r < 0) + return log_error_errno(r, "Failed to enumerate %s: %m", path); + + strv_sort(list); + + STRV_FOREACH(file, list) { + OrderedHashmap *h; + int k; + char *p; + char *d; + + if (!endswith(*file, ".conf")) + continue; + + p = path_join(path, *file); + if (!p) + return -ENOMEM; + d = p + strlen(toppath) + 1; + + log_debug("Adding at top: %s %s %s", d, special_glyph(SPECIAL_GLYPH_ARROW), p); + k = ordered_hashmap_put(top, d, p); + if (k >= 0) { + p = strdup(p); + if (!p) + return -ENOMEM; + d = p + strlen(toppath) + 1; + } else if (k != -EEXIST) { + free(p); + return k; + } + + log_debug("Adding at bottom: %s %s %s", d, special_glyph(SPECIAL_GLYPH_ARROW), p); + free(ordered_hashmap_remove(bottom, d)); + k = ordered_hashmap_put(bottom, d, p); + if (k < 0) { + free(p); + return k; + } + + h = ordered_hashmap_get(drops, unit); + if (!h) { + h = ordered_hashmap_new(&string_hash_ops); + if (!h) + return -ENOMEM; + ordered_hashmap_put(drops, unit, h); + unit = strdup(unit); + if (!unit) + return -ENOMEM; + } + + p = strdup(p); + if (!p) + return -ENOMEM; + + log_debug("Adding to drops: %s %s %s %s %s", + unit, special_glyph(SPECIAL_GLYPH_ARROW), basename(p), special_glyph(SPECIAL_GLYPH_ARROW), p); + k = ordered_hashmap_put(h, basename(p), p); + if (k < 0) { + free(p); + if (k != -EEXIST) + return k; + } + } + return 0; +} + +static int enumerate_dir( + OrderedHashmap *top, + OrderedHashmap *bottom, + OrderedHashmap *drops, + const char *path, bool dropins) { + + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + _cleanup_strv_free_ char **files = NULL, **dirs = NULL; + size_t n_files = 0, allocated_files = 0, n_dirs = 0, allocated_dirs = 0; + char **t; + int r; + + assert(top); + assert(bottom); + assert(drops); + assert(path); + + log_debug("Looking at %s", path); + + d = opendir(path); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open %s: %m", path); + } + + FOREACH_DIRENT_ALL(de, d, return -errno) { + dirent_ensure_type(d, de); + + if (dropins && de->d_type == DT_DIR && endswith(de->d_name, ".d")) { + if (!GREEDY_REALLOC0(dirs, allocated_dirs, n_dirs + 2)) + return -ENOMEM; + + dirs[n_dirs] = strdup(de->d_name); + if (!dirs[n_dirs]) + return -ENOMEM; + n_dirs ++; + } + + if (!dirent_is_file(de)) + continue; + + if (!GREEDY_REALLOC0(files, allocated_files, n_files + 2)) + return -ENOMEM; + + files[n_files] = strdup(de->d_name); + if (!files[n_files]) + return -ENOMEM; + n_files ++; + } + + strv_sort(dirs); + strv_sort(files); + + STRV_FOREACH(t, dirs) { + r = enumerate_dir_d(top, bottom, drops, path, *t); + if (r < 0) + return r; + } + + STRV_FOREACH(t, files) { + _cleanup_free_ char *p = NULL; + + p = path_join(path, *t); + if (!p) + return -ENOMEM; + + log_debug("Adding at top: %s %s %s", basename(p), special_glyph(SPECIAL_GLYPH_ARROW), p); + r = ordered_hashmap_put(top, basename(p), p); + if (r >= 0) { + p = strdup(p); + if (!p) + return -ENOMEM; + } else if (r != -EEXIST) + return r; + + log_debug("Adding at bottom: %s %s %s", basename(p), special_glyph(SPECIAL_GLYPH_ARROW), p); + free(ordered_hashmap_remove(bottom, basename(p))); + r = ordered_hashmap_put(bottom, basename(p), p); + if (r < 0) + return r; + p = NULL; + } + + return 0; +} + +static int should_skip_path(const char *prefix, const char *suffix) { +#if HAVE_SPLIT_USR + _cleanup_free_ char *target = NULL; + const char *dirname, *p; + + dirname = prefix_roota(prefix, suffix); + + if (chase_symlinks(dirname, NULL, 0, &target, NULL) < 0) + return false; + + NULSTR_FOREACH(p, prefixes) { + _cleanup_free_ char *tmp = NULL; + + if (path_startswith(dirname, p)) + continue; + + tmp = path_join(p, suffix); + if (!tmp) + return -ENOMEM; + + if (path_equal(target, tmp)) { + log_debug("%s redirects to %s, skipping.", dirname, target); + return true; + } + } +#endif + return false; +} + +static int process_suffix(const char *suffix, const char *onlyprefix) { + const char *p; + char *f; + OrderedHashmap *top, *bottom, *drops; + OrderedHashmap *h; + char *key; + int r = 0, k; + Iterator i, j; + int n_found = 0; + bool dropins; + + assert(suffix); + assert(!startswith(suffix, "/")); + assert(!strstr(suffix, "//")); + + dropins = nulstr_contains(have_dropins, suffix); + + top = ordered_hashmap_new(&string_hash_ops); + bottom = ordered_hashmap_new(&string_hash_ops); + drops = ordered_hashmap_new(&string_hash_ops); + if (!top || !bottom || !drops) { + r = -ENOMEM; + goto finish; + } + + NULSTR_FOREACH(p, prefixes) { + _cleanup_free_ char *t = NULL; + + if (should_skip_path(p, suffix) > 0) + continue; + + t = path_join(p, suffix); + if (!t) { + r = -ENOMEM; + goto finish; + } + + k = enumerate_dir(top, bottom, drops, t, dropins); + if (r == 0) + r = k; + } + + ORDERED_HASHMAP_FOREACH_KEY(f, key, top, i) { + char *o; + + o = ordered_hashmap_get(bottom, key); + assert(o); + + if (!onlyprefix || startswith(o, onlyprefix)) { + if (path_equal(o, f)) { + notify_override_unchanged(f); + } else { + k = found_override(f, o); + if (k < 0) + r = k; + else + n_found += k; + } + } + + h = ordered_hashmap_get(drops, key); + if (h) + ORDERED_HASHMAP_FOREACH(o, h, j) + if (!onlyprefix || startswith(o, onlyprefix)) + n_found += notify_override_extended(f, o); + } + +finish: + ordered_hashmap_free_free(top); + ordered_hashmap_free_free(bottom); + + ORDERED_HASHMAP_FOREACH_KEY(h, key, drops, i) { + ordered_hashmap_free_free(ordered_hashmap_remove(drops, key)); + ordered_hashmap_remove(drops, key); + free(key); + } + ordered_hashmap_free(drops); + + return r < 0 ? r : n_found; +} + +static int process_suffixes(const char *onlyprefix) { + const char *n; + int n_found = 0, r; + + NULSTR_FOREACH(n, suffixes) { + r = process_suffix(n, onlyprefix); + if (r < 0) + return r; + + n_found += r; + } + + return n_found; +} + +static int process_suffix_chop(const char *arg) { + const char *p; + + assert(arg); + + if (!path_is_absolute(arg)) + return process_suffix(arg, NULL); + + /* Strip prefix from the suffix */ + NULSTR_FOREACH(p, prefixes) { + const char *suffix; + + suffix = startswith(arg, p); + if (suffix) { + suffix += strspn(suffix, "/"); + if (*suffix) + return process_suffix(suffix, p); + else + return process_suffixes(arg); + } + } + + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid suffix specification %s.", arg); +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-delta", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [SUFFIX...]\n\n" + "Find overridden configuration files.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --diff[=1|0] Show a diff when overridden files differ\n" + " -t --type=LIST... Only display a selected set of override types\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_flags(const char *flag_str, int flags) { + const char *word, *state; + size_t l; + + FOREACH_WORD_SEPARATOR(word, l, flag_str, ",", state) { + if (strneq("masked", word, l)) + flags |= SHOW_MASKED; + else if (strneq ("equivalent", word, l)) + flags |= SHOW_EQUIVALENT; + else if (strneq("redirected", word, l)) + flags |= SHOW_REDIRECTED; + else if (strneq("overridden", word, l)) + flags |= SHOW_OVERRIDDEN; + else if (strneq("unchanged", word, l)) + flags |= SHOW_UNCHANGED; + else if (strneq("extended", word, l)) + flags |= SHOW_EXTENDED; + else if (strneq("default", word, l)) + flags |= SHOW_DEFAULTS; + else + return -EINVAL; + } + return flags; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_NO_PAGER = 0x100, + ARG_DIFF, + ARG_VERSION + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "diff", optional_argument, NULL, ARG_DIFF }, + { "type", required_argument, NULL, 't' }, + {} + }; + + int c; + + assert(argc >= 1); + assert(argv); + + while ((c = getopt_long(argc, argv, "ht:", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case 't': { + int f; + f = parse_flags(optarg, arg_flags); + if (f < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse flags field."); + arg_flags = f; + break; + } + + case ARG_DIFF: + if (!optarg) + arg_diff = 1; + else { + int b; + + b = parse_boolean(optarg); + if (b < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse diff boolean."); + + arg_diff = b; + } + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int run(int argc, char *argv[]) { + int r, k, n_found = 0; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (arg_flags == 0) + arg_flags = SHOW_DEFAULTS; + + if (arg_diff < 0) + arg_diff = !!(arg_flags & SHOW_OVERRIDDEN); + else if (arg_diff) + arg_flags |= SHOW_OVERRIDDEN; + + (void) pager_open(arg_pager_flags); + + if (optind < argc) { + int i; + + for (i = optind; i < argc; i++) { + path_simplify(argv[i], false); + + k = process_suffix_chop(argv[i]); + if (k < 0) + r = k; + else + n_found += k; + } + + } else { + k = process_suffixes(NULL); + if (k < 0) + r = k; + else + n_found += k; + } + + if (r >= 0) + printf("%s%i overridden configuration files found.\n", n_found ? "\n" : "", n_found); + return r; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c new file mode 100644 index 00000000..7fb80ca1 --- /dev/null +++ b/src/detect-virt/detect-virt.c @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "main-func.h" +#include "pretty-print.h" +#include "string-table.h" +#include "util.h" +#include "virt.h" + +static bool arg_quiet = false; +static enum { + ANY_VIRTUALIZATION, + ONLY_VM, + ONLY_CONTAINER, + ONLY_CHROOT, + ONLY_PRIVATE_USERS, +} arg_mode = ANY_VIRTUALIZATION; + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-detect-virt", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n\n" + "Detect execution in a virtualized environment.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -c --container Only detect whether we are run in a container\n" + " -v --vm Only detect whether we are run in a VM\n" + " -r --chroot Detect whether we are run in a chroot() environment\n" + " --private-users Only detect whether we are running in a user namespace\n" + " -q --quiet Don't output anything, just set return value\n" + " --list List all known and detectable types of virtualization\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_PRIVATE_USERS, + ARG_LIST, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "container", no_argument, NULL, 'c' }, + { "vm", no_argument, NULL, 'v' }, + { "chroot", no_argument, NULL, 'r' }, + { "private-users", no_argument, NULL, ARG_PRIVATE_USERS }, + { "quiet", no_argument, NULL, 'q' }, + { "list", no_argument, NULL, ARG_LIST }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hqcvr", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case 'q': + arg_quiet = true; + break; + + case 'c': + arg_mode = ONLY_CONTAINER; + break; + + case ARG_PRIVATE_USERS: + arg_mode = ONLY_PRIVATE_USERS; + break; + + case 'v': + arg_mode = ONLY_VM; + break; + + case 'r': + arg_mode = ONLY_CHROOT; + break; + + case ARG_LIST: + DUMP_STRING_TABLE(virtualization, int, _VIRTUALIZATION_MAX); + return 0; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s takes no arguments.", + program_invocation_short_name); + + return 1; +} + +static int run(int argc, char *argv[]) { + int r; + + /* This is mostly intended to be used for scripts which want + * to detect whether we are being run in a virtualized + * environment or not */ + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + switch (arg_mode) { + case ONLY_VM: + r = detect_vm(); + if (r < 0) + return log_error_errno(r, "Failed to check for VM: %m"); + break; + + case ONLY_CONTAINER: + r = detect_container(); + if (r < 0) + return log_error_errno(r, "Failed to check for container: %m"); + break; + + case ONLY_CHROOT: + r = running_in_chroot(); + if (r < 0) + return log_error_errno(r, "Failed to check for chroot() environment: %m"); + return !r; + + case ONLY_PRIVATE_USERS: + r = running_in_userns(); + if (r < 0) + return log_error_errno(r, "Failed to check for user namespace: %m"); + return !r; + + case ANY_VIRTUALIZATION: + default: + r = detect_virtualization(); + if (r < 0) + return log_error_errno(r, "Failed to check for virtualization: %m"); + break; + } + + if (!arg_quiet) + puts(virtualization_to_string(r)); + + return r == VIRTUALIZATION_NONE; +} + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c new file mode 100644 index 00000000..50de0afc --- /dev/null +++ b/src/dissect/dissect.c @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "architecture.h" +#include "dissect-image.h" +#include "hexdecoct.h" +#include "log.h" +#include "loop-util.h" +#include "main-func.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" + +static enum { + ACTION_DISSECT, + ACTION_MOUNT, +} arg_action = ACTION_DISSECT; +static const char *arg_image = NULL; +static const char *arg_path = NULL; +static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP; +static void *arg_root_hash = NULL; +static size_t arg_root_hash_size = 0; + +STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep); + +static void help(void) { + printf("%s [OPTIONS...] IMAGE\n" + "%s [OPTIONS...] --mount IMAGE PATH\n" + "Dissect a file system OS image.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -m --mount Mount the image to the specified directory\n" + " -r --read-only Mount read-only\n" + " --discard=MODE Choose 'discard' mode (disabled, loop, all, crypto)\n" + " --root-hash=HASH Specify root hash for verity\n", + program_invocation_short_name, + program_invocation_short_name); +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_DISCARD, + ARG_ROOT_HASH, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "mount", no_argument, NULL, 'm' }, + { "read-only", no_argument, NULL, 'r' }, + { "discard", required_argument, NULL, ARG_DISCARD }, + { "root-hash", required_argument, NULL, ARG_ROOT_HASH }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hmr", options, NULL)) >= 0) { + + switch (c) { + + case 'h': + help(); + return 0; + + case ARG_VERSION: + return version(); + + case 'm': + arg_action = ACTION_MOUNT; + break; + + case 'r': + arg_flags |= DISSECT_IMAGE_READ_ONLY; + break; + + case ARG_DISCARD: { + DissectImageFlags flags; + + if (streq(optarg, "disabled")) + flags = 0; + else if (streq(optarg, "loop")) + flags = DISSECT_IMAGE_DISCARD_ON_LOOP; + else if (streq(optarg, "all")) + flags = DISSECT_IMAGE_DISCARD_ON_LOOP | DISSECT_IMAGE_DISCARD; + else if (streq(optarg, "crypt")) + flags = DISSECT_IMAGE_DISCARD_ANY; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown --discard= parameter: %s", + optarg); + arg_flags = (arg_flags & ~DISSECT_IMAGE_DISCARD_ANY) | flags; + + break; + } + + case ARG_ROOT_HASH: { + void *p; + size_t l; + + r = unhexmem(optarg, strlen(optarg), &p, &l); + if (r < 0) + return log_error_errno(r, "Failed to parse root hash '%s': %m", optarg); + if (l < sizeof(sd_id128_t)) { + log_error("Root hash must be at least 128bit long: %s", optarg); + free(p); + return -EINVAL; + } + + free(arg_root_hash); + arg_root_hash = p; + arg_root_hash_size = l; + break; + } + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + } + + switch (arg_action) { + + case ACTION_DISSECT: + if (optind + 1 != argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Expected a file path as only argument."); + + arg_image = argv[optind]; + arg_flags |= DISSECT_IMAGE_READ_ONLY; + break; + + case ACTION_MOUNT: + if (optind + 2 != argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Expected a file path and mount point path as only arguments."); + + arg_image = argv[optind]; + arg_path = argv[optind + 1]; + break; + + default: + assert_not_reached("Unknown action."); + } + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; + _cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL; + _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; + int r; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = loop_device_make_by_path(arg_image, (arg_flags & DISSECT_IMAGE_READ_ONLY) ? O_RDONLY : O_RDWR, &d); + if (r < 0) + return log_error_errno(r, "Failed to set up loopback device: %m"); + + if (!arg_root_hash) { + r = root_hash_load(arg_image, &arg_root_hash, &arg_root_hash_size); + if (r < 0) + return log_error_errno(r, "Failed to read root hash file for %s: %m", arg_image); + } + + r = dissect_image_and_warn(d->fd, arg_image, arg_root_hash, arg_root_hash_size, arg_flags, &m); + if (r < 0) + return r; + + switch (arg_action) { + + case ACTION_DISSECT: { + unsigned i; + + for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { + DissectedPartition *p = m->partitions + i; + int k; + + if (!p->found) + continue; + + printf("Found %s '%s' partition", + p->rw ? "writable" : "read-only", + partition_designator_to_string(i)); + + if (!sd_id128_is_null(p->uuid)) + printf(" (UUID " SD_ID128_FORMAT_STR ")", SD_ID128_FORMAT_VAL(p->uuid)); + + if (p->fstype) + printf(" of type %s", p->fstype); + + if (p->architecture != _ARCHITECTURE_INVALID) + printf(" for %s", architecture_to_string(p->architecture)); + + k = PARTITION_VERITY_OF(i); + if (k >= 0) + printf(" %s verity", m->partitions[k].found ? "with" : "without"); + + if (p->partno >= 0) + printf(" on partition #%i", p->partno); + + if (p->node) + printf(" (%s)", p->node); + + putchar('\n'); + } + + r = dissected_image_acquire_metadata(m); + if (r < 0) + return log_error_errno(r, "Failed to acquire image metadata: %m"); + + if (m->hostname) + printf(" Hostname: %s\n", m->hostname); + + if (!sd_id128_is_null(m->machine_id)) + printf("Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(m->machine_id)); + + if (!strv_isempty(m->machine_info)) { + char **p, **q; + + STRV_FOREACH_PAIR(p, q, m->machine_info) + printf("%s %s=%s\n", + p == m->machine_info ? "Mach. Info:" : " ", + *p, *q); + } + + if (!strv_isempty(m->os_release)) { + char **p, **q; + + STRV_FOREACH_PAIR(p, q, m->os_release) + printf("%s %s=%s\n", + p == m->os_release ? "OS Release:" : " ", + *p, *q); + } + + break; + } + + case ACTION_MOUNT: + r = dissected_image_decrypt_interactively(m, NULL, arg_root_hash, arg_root_hash_size, arg_flags, &di); + if (r < 0) + return r; + + r = dissected_image_mount(m, arg_path, UID_INVALID, arg_flags); + if (r < 0) + return log_error_errno(r, "Failed to mount image: %m"); + + if (di) { + r = decrypted_image_relinquish(di); + if (r < 0) + return log_error_errno(r, "Failed to relinquish DM devices: %m"); + } + + loop_device_relinquish(d); + break; + + default: + assert_not_reached("Unknown action."); + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/environment-d-generator/environment-d-generator.c b/src/environment-d-generator/environment-d-generator.c new file mode 100644 index 00000000..5fe51359 --- /dev/null +++ b/src/environment-d-generator/environment-d-generator.c @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-path.h" + +#include "conf-files.h" +#include "def.h" +#include "env-file.h" +#include "escape.h" +#include "log.h" +#include "path-lookup.h" +#include "strv.h" + +static int environment_dirs(char ***ret) { + _cleanup_strv_free_ char **dirs = NULL; + _cleanup_free_ char *c = NULL; + int r; + + dirs = strv_new(CONF_PATHS_USR("environment.d"), NULL); + if (!dirs) + return -ENOMEM; + + /* ~/.config/systemd/environment.d */ + r = sd_path_home(SD_PATH_USER_CONFIGURATION, "environment.d", &c); + if (r < 0) + return r; + + r = strv_extend_front(&dirs, c); + if (r < 0) + return r; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *t; + + t = strv_join(dirs, "\n\t"); + log_debug("Looking for environment.d files in (higher priority first):\n\t%s", strna(t)); + } + + *ret = TAKE_PTR(dirs); + return 0; +} + +static int load_and_print(void) { + _cleanup_strv_free_ char **dirs = NULL, **files = NULL, **env = NULL; + char **i; + int r; + + r = environment_dirs(&dirs); + if (r < 0) + return r; + + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char **) dirs); + if (r < 0) + return r; + + /* This will mutate the existing environment, based on the presumption + * that in case of failure, a partial update is better than none. */ + + STRV_FOREACH(i, files) { + log_debug("Reading %s…", *i); + + r = merge_env_file(&env, NULL, *i); + if (r == -ENOMEM) + return r; + } + + STRV_FOREACH(i, env) { + char *t; + _cleanup_free_ char *q = NULL; + + t = strchr(*i, '='); + assert(t); + + q = shell_maybe_quote(t + 1, ESCAPE_BACKSLASH); + if (!q) + return log_oom(); + + printf("%.*s=%s\n", (int) (t - *i), *i, q); + } + + return 0; +} + +int main(int argc, char *argv[]) { + int r; + + log_parse_environment(); + log_open(); + + if (argc > 1) { + log_error("This program takes no arguments."); + return EXIT_FAILURE; + } + + r = load_and_print(); + if (r < 0) + log_error_errno(r, "Failed to load environment.d: %m"); + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/escape/escape.c b/src/escape/escape.c new file mode 100644 index 00000000..9066c308 --- /dev/null +++ b/src/escape/escape.c @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "log.h" +#include "main-func.h" +#include "pretty-print.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" + +static enum { + ACTION_ESCAPE, + ACTION_UNESCAPE, + ACTION_MANGLE +} arg_action = ACTION_ESCAPE; +static const char *arg_suffix = NULL; +static const char *arg_template = NULL; +static bool arg_path = false; +static bool arg_instance = false; + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-escape", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [NAME...]\n\n" + "Escape strings for usage in systemd unit names.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --suffix=SUFFIX Unit suffix to append to escaped strings\n" + " --template=TEMPLATE Insert strings as instance into template\n" + " --instance With --unescape, show just the instance part\n" + " -u --unescape Unescape strings\n" + " -m --mangle Mangle strings\n" + " -p --path When escaping/unescaping assume the string is a path\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_SUFFIX, + ARG_TEMPLATE + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "suffix", required_argument, NULL, ARG_SUFFIX }, + { "template", required_argument, NULL, ARG_TEMPLATE }, + { "unescape", no_argument, NULL, 'u' }, + { "mangle", no_argument, NULL, 'm' }, + { "path", no_argument, NULL, 'p' }, + { "instance", no_argument, NULL, 'i' }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hump", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_SUFFIX: + + if (unit_type_from_string(optarg) < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid unit suffix type %s.", optarg); + + arg_suffix = optarg; + break; + + case ARG_TEMPLATE: + + if (!unit_name_is_valid(optarg, UNIT_NAME_TEMPLATE)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Template name %s is not valid.", optarg); + + arg_template = optarg; + break; + + case 'u': + arg_action = ACTION_UNESCAPE; + break; + + case 'm': + arg_action = ACTION_MANGLE; + break; + + case 'p': + arg_path = true; + break; + + case 'i': + arg_instance = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind >= argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Not enough arguments."); + + if (arg_template && arg_suffix) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--suffix= and --template= may not be combined."); + + if ((arg_template || arg_suffix) && arg_action == ACTION_MANGLE) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--suffix= and --template= are not compatible with --mangle."); + + if (arg_suffix && arg_action == ACTION_UNESCAPE) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--suffix is not compatible with --unescape."); + + if (arg_path && !IN_SET(arg_action, ACTION_ESCAPE, ACTION_UNESCAPE)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--path may not be combined with --mangle."); + + if (arg_instance && arg_action != ACTION_UNESCAPE) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--instance must be used in conjunction with --unescape."); + + if (arg_instance && arg_template) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--instance may not be combined with --template."); + + return 1; +} + +static int run(int argc, char *argv[]) { + char **i; + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + STRV_FOREACH(i, argv + optind) { + _cleanup_free_ char *e = NULL; + + switch (arg_action) { + + case ACTION_ESCAPE: + if (arg_path) { + r = unit_name_path_escape(*i, &e); + if (r < 0) + return log_error_errno(r, "Failed to escape string: %m"); + } else { + e = unit_name_escape(*i); + if (!e) + return log_oom(); + } + + if (arg_template) { + char *x; + + r = unit_name_replace_instance(arg_template, e, &x); + if (r < 0) + return log_error_errno(r, "Failed to replace instance: %m"); + + free_and_replace(e, x); + } else if (arg_suffix) { + char *x; + + x = strjoin(e, ".", arg_suffix); + if (!x) + return log_oom(); + + free_and_replace(e, x); + } + + break; + + case ACTION_UNESCAPE: { + _cleanup_free_ char *name = NULL; + + if (arg_template || arg_instance) { + _cleanup_free_ char *template = NULL; + + r = unit_name_to_instance(*i, &name); + if (r < 0) + return log_error_errno(r, "Failed to extract instance: %m"); + if (isempty(name)) + return log_error("Unit %s is missing the instance name.", *i); + + r = unit_name_template(*i, &template); + if (r < 0) + return log_error_errno(r, "Failed to extract template: %m"); + if (arg_template && !streq(arg_template, template)) + return log_error("Unit %s template %s does not match specified template %s.", + *i, template, arg_template); + } else { + name = strdup(*i); + if (!name) + return log_oom(); + } + + if (arg_path) + r = unit_name_path_unescape(name, &e); + else + r = unit_name_unescape(name, &e); + if (r < 0) + return log_error_errno(r, "Failed to unescape string: %m"); + + break; + } + + case ACTION_MANGLE: + r = unit_name_mangle(*i, 0, &e); + if (r < 0) + return log_error_errno(r, "Failed to mangle name: %m"); + + break; + } + + if (i != argv + optind) + fputc(' ', stdout); + + fputs(e, stdout); + } + + fputc('\n', stdout); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c new file mode 100644 index 00000000..528e6452 --- /dev/null +++ b/src/firstboot/firstboot.c @@ -0,0 +1,988 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#if HAVE_CRYPT_H +/* libxcrypt is a replacement for glibc's libcrypt, and libcrypt might be + * removed from glibc at some point. As part of the removal, defines for + * crypt(3) are dropped from unistd.h, and we must include crypt.h instead. + * + * Newer versions of glibc (v2.0+) already ship crypt.h with a definition + * of crypt(3) as well, so we simply include it if it is present. MariaDB, + * MySQL, PostgreSQL, Perl and some other wide-spread packages do it the + * same way since ages without any problems. + */ +# include +#endif + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "ask-password-api.h" +#include "copy.h" +#include "env-file.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "kbd-util.h" +#include "locale-util.h" +#include "main-func.h" +#include "memory-util.h" +#include "mkdir.h" +#include "os-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "proc-cmdline.h" +#include "random-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "time-util.h" +#include "umask-util.h" +#include "user-util.h" + +static char *arg_root = NULL; +static char *arg_locale = NULL; /* $LANG */ +static char *arg_keymap = NULL; +static char *arg_locale_messages = NULL; /* $LC_MESSAGES */ +static char *arg_timezone = NULL; +static char *arg_hostname = NULL; +static sd_id128_t arg_machine_id = {}; +static char *arg_root_password = NULL; +static bool arg_prompt_locale = false; +static bool arg_prompt_keymap = false; +static bool arg_prompt_timezone = false; +static bool arg_prompt_hostname = false; +static bool arg_prompt_root_password = false; +static bool arg_copy_locale = false; +static bool arg_copy_keymap = false; +static bool arg_copy_timezone = false; +static bool arg_copy_root_password = false; + +STATIC_DESTRUCTOR_REGISTER(arg_root, freep); +STATIC_DESTRUCTOR_REGISTER(arg_locale, freep); +STATIC_DESTRUCTOR_REGISTER(arg_locale_messages, freep); +STATIC_DESTRUCTOR_REGISTER(arg_keymap, freep); +STATIC_DESTRUCTOR_REGISTER(arg_timezone, freep); +STATIC_DESTRUCTOR_REGISTER(arg_hostname, freep); +STATIC_DESTRUCTOR_REGISTER(arg_root_password, erase_and_freep); + +static bool press_any_key(void) { + char k = 0; + bool need_nl = true; + + printf("-- Press any key to proceed --"); + fflush(stdout); + + (void) read_one_char(stdin, &k, USEC_INFINITY, &need_nl); + + if (need_nl) + putchar('\n'); + + return k != 'q'; +} + +static void print_welcome(void) { + _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL; + static bool done = false; + const char *pn; + int r; + + if (done) + return; + + r = parse_os_release( + arg_root, + "PRETTY_NAME", &pretty_name, + "ANSI_COLOR", &ansi_color, + NULL); + if (r < 0) + log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, + "Failed to read os-release file, ignoring: %m"); + + pn = isempty(pretty_name) ? "Linux" : pretty_name; + + if (colors_enabled()) + printf("\nWelcome to your new installation of \x1B[%sm%s\x1B[0m!\n", ansi_color, pn); + else + printf("\nWelcome to your new installation of %s!\n", pn); + + printf("\nPlease configure your system!\n\n"); + + press_any_key(); + + done = true; +} + +static int show_menu(char **x, unsigned n_columns, unsigned width, unsigned percentage) { + unsigned break_lines, break_modulo; + size_t n, per_column, i, j; + + assert(n_columns > 0); + + n = strv_length(x); + per_column = DIV_ROUND_UP(n, n_columns); + + break_lines = lines(); + if (break_lines > 2) + break_lines--; + + /* The first page gets two extra lines, since we want to show + * a title */ + break_modulo = break_lines; + if (break_modulo > 3) + break_modulo -= 3; + + for (i = 0; i < per_column; i++) { + + for (j = 0; j < n_columns; j ++) { + _cleanup_free_ char *e = NULL; + + if (j * per_column + i >= n) + break; + + e = ellipsize(x[j * per_column + i], width, percentage); + if (!e) + return log_oom(); + + printf("%4zu) %-*s", j * per_column + i + 1, width, e); + } + + putchar('\n'); + + /* on the first screen we reserve 2 extra lines for the title */ + if (i % break_lines == break_modulo) { + if (!press_any_key()) + return 0; + } + } + + return 0; +} + +static int prompt_loop(const char *text, char **l, unsigned percentage, bool (*is_valid)(const char *name), char **ret) { + int r; + + assert(text); + assert(is_valid); + assert(ret); + + for (;;) { + _cleanup_free_ char *p = NULL; + unsigned u; + + r = ask_string(&p, "%s %s (empty to skip, \"list\" to list options): ", + special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), text); + if (r < 0) + return log_error_errno(r, "Failed to query user: %m"); + + if (isempty(p)) { + log_warning("No data entered, skipping."); + return 0; + } + + if (streq(p, "list")) { + r = show_menu(l, 3, 22, percentage); + if (r < 0) + return r; + + putchar('\n'); + continue; + }; + + r = safe_atou(p, &u); + if (r >= 0) { + if (u <= 0 || u > strv_length(l)) { + log_error("Specified entry number out of range."); + continue; + } + + log_info("Selected '%s'.", l[u-1]); + if (free_and_strdup(ret, l[u-1]) < 0) + return log_oom(); + + return 0; + } + + if (!is_valid(p)) { + log_error("Entered data invalid."); + continue; + } + + return free_and_replace(*ret, p); + } +} + +static int prompt_locale(void) { + _cleanup_strv_free_ char **locales = NULL; + int r; + + if (arg_locale || arg_locale_messages) + return 0; + + if (!arg_prompt_locale) + return 0; + + r = get_locales(&locales); + if (r < 0) + return log_error_errno(r, "Cannot query locales list: %m"); + + if (strv_isempty(locales)) + log_debug("No locales found, skipping locale selection."); + else if (strv_length(locales) == 1) { + + if (streq(locales[0], SYSTEMD_DEFAULT_LOCALE)) + log_debug("Only installed locale is default locale anyway, not setting locale explicitly."); + else { + log_debug("Only a single locale available (%s), selecting it as default.", locales[0]); + + arg_locale = strdup(locales[0]); + if (!arg_locale) + return log_oom(); + + /* Not setting arg_locale_message here, since it defaults to LANG anyway */ + } + } else { + print_welcome(); + + r = prompt_loop("Please enter system locale name or number", + locales, 60, locale_is_valid, &arg_locale); + if (r < 0) + return r; + + if (isempty(arg_locale)) + return 0; + + r = prompt_loop("Please enter system message locale name or number", + locales, 60, locale_is_valid, &arg_locale_messages); + if (r < 0) + return r; + + /* Suppress the messages setting if it's the same as the main locale anyway */ + if (streq_ptr(arg_locale, arg_locale_messages)) + arg_locale_messages = mfree(arg_locale_messages); + } + + return 0; +} + +static int process_locale(void) { + const char *etc_localeconf; + char* locales[3]; + unsigned i = 0; + int r; + + etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf"); + if (laccess(etc_localeconf, F_OK) >= 0) + return 0; + + if (arg_copy_locale && arg_root) { + + (void) mkdir_parents(etc_localeconf, 0755); + r = copy_file("/etc/locale.conf", etc_localeconf, 0, 0644, 0, 0, COPY_REFLINK); + if (r != -ENOENT) { + if (r < 0) + return log_error_errno(r, "Failed to copy %s: %m", etc_localeconf); + + log_info("%s copied.", etc_localeconf); + return 0; + } + } + + r = prompt_locale(); + if (r < 0) + return r; + + if (!isempty(arg_locale)) + locales[i++] = strjoina("LANG=", arg_locale); + if (!isempty(arg_locale_messages) && !streq(arg_locale_messages, arg_locale)) + locales[i++] = strjoina("LC_MESSAGES=", arg_locale_messages); + + if (i == 0) + return 0; + + locales[i] = NULL; + + (void) mkdir_parents(etc_localeconf, 0755); + r = write_env_file(etc_localeconf, locales); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", etc_localeconf); + + log_info("%s written.", etc_localeconf); + return 0; +} + +static int prompt_keymap(void) { + _cleanup_strv_free_ char **kmaps = NULL; + int r; + + if (arg_keymap) + return 0; + + if (!arg_prompt_keymap) + return 0; + + r = get_keymaps(&kmaps); + if (r == -ENOENT) /* no keymaps installed */ + return r; + if (r < 0) + return log_error_errno(r, "Failed to read keymaps: %m"); + + print_welcome(); + + return prompt_loop("Please enter system keymap name or number", + kmaps, 60, keymap_is_valid, &arg_keymap); +} + +static int process_keymap(void) { + const char *etc_vconsoleconf; + char **keymap; + int r; + + etc_vconsoleconf = prefix_roota(arg_root, "/etc/vconsole.conf"); + if (laccess(etc_vconsoleconf, F_OK) >= 0) + return 0; + + if (arg_copy_keymap && arg_root) { + + (void) mkdir_parents(etc_vconsoleconf, 0755); + r = copy_file("/etc/vconsole.conf", etc_vconsoleconf, 0, 0644, 0, 0, COPY_REFLINK); + if (r != -ENOENT) { + if (r < 0) + return log_error_errno(r, "Failed to copy %s: %m", etc_vconsoleconf); + + log_info("%s copied.", etc_vconsoleconf); + return 0; + } + } + + r = prompt_keymap(); + if (r == -ENOENT) + return 0; /* don't fail if no keymaps are installed */ + if (r < 0) + return r; + + if (isempty(arg_keymap)) + return 0; + + keymap = STRV_MAKE(strjoina("KEYMAP=", arg_keymap)); + + r = mkdir_parents(etc_vconsoleconf, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create the parent directory of %s: %m", etc_vconsoleconf); + + r = write_env_file(etc_vconsoleconf, keymap); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", etc_vconsoleconf); + + log_info("%s written.", etc_vconsoleconf); + return 0; +} + +static bool timezone_is_valid_log_error(const char *name) { + return timezone_is_valid(name, LOG_ERR); +} + +static int prompt_timezone(void) { + _cleanup_strv_free_ char **zones = NULL; + int r; + + if (arg_timezone) + return 0; + + if (!arg_prompt_timezone) + return 0; + + r = get_timezones(&zones); + if (r < 0) + return log_error_errno(r, "Cannot query timezone list: %m"); + + print_welcome(); + + r = prompt_loop("Please enter timezone name or number", + zones, 30, timezone_is_valid_log_error, &arg_timezone); + if (r < 0) + return r; + + return 0; +} + +static int process_timezone(void) { + const char *etc_localtime, *e; + int r; + + etc_localtime = prefix_roota(arg_root, "/etc/localtime"); + if (laccess(etc_localtime, F_OK) >= 0) + return 0; + + if (arg_copy_timezone && arg_root) { + _cleanup_free_ char *p = NULL; + + r = readlink_malloc("/etc/localtime", &p); + if (r != -ENOENT) { + if (r < 0) + return log_error_errno(r, "Failed to read host timezone: %m"); + + (void) mkdir_parents(etc_localtime, 0755); + if (symlink(p, etc_localtime) < 0) + return log_error_errno(errno, "Failed to create %s symlink: %m", etc_localtime); + + log_info("%s copied.", etc_localtime); + return 0; + } + } + + r = prompt_timezone(); + if (r < 0) + return r; + + if (isempty(arg_timezone)) + return 0; + + e = strjoina("../usr/share/zoneinfo/", arg_timezone); + + (void) mkdir_parents(etc_localtime, 0755); + if (symlink(e, etc_localtime) < 0) + return log_error_errno(errno, "Failed to create %s symlink: %m", etc_localtime); + + log_info("%s written", etc_localtime); + return 0; +} + +static int prompt_hostname(void) { + int r; + + if (arg_hostname) + return 0; + + if (!arg_prompt_hostname) + return 0; + + print_welcome(); + putchar('\n'); + + for (;;) { + _cleanup_free_ char *h = NULL; + + r = ask_string(&h, "%s Please enter hostname for new system (empty to skip): ", special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET)); + if (r < 0) + return log_error_errno(r, "Failed to query hostname: %m"); + + if (isempty(h)) { + log_warning("No hostname entered, skipping."); + break; + } + + if (!hostname_is_valid(h, true)) { + log_error("Specified hostname invalid."); + continue; + } + + /* Get rid of the trailing dot that we allow, but don't want to see */ + arg_hostname = hostname_cleanup(h); + h = NULL; + break; + } + + return 0; +} + +static int process_hostname(void) { + const char *etc_hostname; + int r; + + etc_hostname = prefix_roota(arg_root, "/etc/hostname"); + if (laccess(etc_hostname, F_OK) >= 0) + return 0; + + r = prompt_hostname(); + if (r < 0) + return r; + + if (isempty(arg_hostname)) + return 0; + + r = write_string_file(etc_hostname, arg_hostname, + WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", etc_hostname); + + log_info("%s written.", etc_hostname); + return 0; +} + +static int process_machine_id(void) { + const char *etc_machine_id; + char id[SD_ID128_STRING_MAX]; + int r; + + etc_machine_id = prefix_roota(arg_root, "/etc/machine-id"); + if (laccess(etc_machine_id, F_OK) >= 0) + return 0; + + if (sd_id128_is_null(arg_machine_id)) + return 0; + + r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id), + WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_SYNC | WRITE_STRING_FILE_MKDIR_0755); + if (r < 0) + return log_error_errno(r, "Failed to write machine id: %m"); + + log_info("%s written.", etc_machine_id); + return 0; +} + +static int prompt_root_password(void) { + const char *msg1, *msg2, *etc_shadow; + int r; + + if (arg_root_password) + return 0; + + if (!arg_prompt_root_password) + return 0; + + etc_shadow = prefix_roota(arg_root, "/etc/shadow"); + if (laccess(etc_shadow, F_OK) >= 0) + return 0; + + print_welcome(); + putchar('\n'); + + msg1 = strjoina(special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), " Please enter a new root password (empty to skip):"); + msg2 = strjoina(special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), " Please enter new root password again:"); + + for (;;) { + _cleanup_strv_free_erase_ char **a = NULL, **b = NULL; + + r = ask_password_tty(-1, msg1, NULL, 0, 0, NULL, &a); + if (r < 0) + return log_error_errno(r, "Failed to query root password: %m"); + if (strv_length(a) != 1) { + log_warning("Received multiple passwords, where we expected one."); + return -EINVAL; + } + + if (isempty(*a)) { + log_warning("No password entered, skipping."); + break; + } + + r = ask_password_tty(-1, msg2, NULL, 0, 0, NULL, &b); + if (r < 0) + return log_error_errno(r, "Failed to query root password: %m"); + + if (!streq(*a, *b)) { + log_error("Entered passwords did not match, please try again."); + continue; + } + + arg_root_password = TAKE_PTR(*a); + break; + } + + return 0; +} + +static int write_root_shadow(const char *path, const struct spwd *p) { + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(path); + assert(p); + + RUN_WITH_UMASK(0777) + f = fopen(path, "wex"); + if (!f) + return -errno; + + r = putspent_sane(p, f); + if (r < 0) + return r; + + return fflush_sync_and_check(f); +} + +static int process_root_password(void) { + + struct spwd item = { + .sp_namp = (char*) "root", + .sp_min = -1, + .sp_max = -1, + .sp_warn = -1, + .sp_inact = -1, + .sp_expire = -1, + .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */ + }; + _cleanup_free_ char *salt = NULL; + _cleanup_close_ int lock = -1; + struct crypt_data cd = {}; + + const char *etc_shadow; + int r; + + etc_shadow = prefix_roota(arg_root, "/etc/shadow"); + if (laccess(etc_shadow, F_OK) >= 0) + return 0; + + (void) mkdir_parents(etc_shadow, 0755); + + lock = take_etc_passwd_lock(arg_root); + if (lock < 0) + return log_error_errno(lock, "Failed to take a lock: %m"); + + if (arg_copy_root_password && arg_root) { + struct spwd *p; + + errno = 0; + p = getspnam("root"); + if (p || errno != ENOENT) { + if (!p) { + if (!errno) + errno = EIO; + + return log_error_errno(errno, "Failed to find shadow entry for root: %m"); + } + + r = write_root_shadow(etc_shadow, p); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", etc_shadow); + + log_info("%s copied.", etc_shadow); + return 0; + } + } + + r = prompt_root_password(); + if (r < 0) + return r; + + if (!arg_root_password) + return 0; + + r = make_salt(&salt); + if (r < 0) + return log_error_errno(r, "Failed to get salt: %m"); + + errno = 0; + item.sp_pwdp = crypt_r(arg_root_password, salt, &cd); + if (!item.sp_pwdp) + return log_error_errno(errno == 0 ? SYNTHETIC_ERRNO(EINVAL) : errno, + "Failed to encrypt password: %m"); + + item.sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY); + + r = write_root_shadow(etc_shadow, &item); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", etc_shadow); + + log_info("%s written.", etc_shadow); + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-firstboot", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n\n" + "Configures basic settings of the system.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --root=PATH Operate on an alternate filesystem root\n" + " --locale=LOCALE Set primary locale (LANG=)\n" + " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n" + " --keymap=KEYMAP Set keymap\n" + " --timezone=TIMEZONE Set timezone\n" + " --hostname=NAME Set host name\n" + " --machine-ID=ID Set machine ID\n" + " --root-password=PASSWORD Set root password\n" + " --root-password-file=FILE Set root password from file\n" + " --prompt-locale Prompt the user for locale settings\n" + " --prompt-keymap Prompt the user for keymap settings\n" + " --prompt-timezone Prompt the user for timezone\n" + " --prompt-hostname Prompt the user for hostname\n" + " --prompt-root-password Prompt the user for root password\n" + " --prompt Prompt for all of the above\n" + " --copy-locale Copy locale from host\n" + " --copy-keymap Copy keymap from host\n" + " --copy-timezone Copy timezone from host\n" + " --copy-root-password Copy root password from host\n" + " --copy Copy locale, keymap, timezone, root password\n" + " --setup-machine-id Generate a new random machine ID\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_ROOT, + ARG_LOCALE, + ARG_LOCALE_MESSAGES, + ARG_KEYMAP, + ARG_TIMEZONE, + ARG_HOSTNAME, + ARG_MACHINE_ID, + ARG_ROOT_PASSWORD, + ARG_ROOT_PASSWORD_FILE, + ARG_PROMPT, + ARG_PROMPT_LOCALE, + ARG_PROMPT_KEYMAP, + ARG_PROMPT_TIMEZONE, + ARG_PROMPT_HOSTNAME, + ARG_PROMPT_ROOT_PASSWORD, + ARG_COPY, + ARG_COPY_LOCALE, + ARG_COPY_KEYMAP, + ARG_COPY_TIMEZONE, + ARG_COPY_ROOT_PASSWORD, + ARG_SETUP_MACHINE_ID, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "root", required_argument, NULL, ARG_ROOT }, + { "locale", required_argument, NULL, ARG_LOCALE }, + { "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES }, + { "keymap", required_argument, NULL, ARG_KEYMAP }, + { "timezone", required_argument, NULL, ARG_TIMEZONE }, + { "hostname", required_argument, NULL, ARG_HOSTNAME }, + { "machine-id", required_argument, NULL, ARG_MACHINE_ID }, + { "root-password", required_argument, NULL, ARG_ROOT_PASSWORD }, + { "root-password-file", required_argument, NULL, ARG_ROOT_PASSWORD_FILE }, + { "prompt", no_argument, NULL, ARG_PROMPT }, + { "prompt-locale", no_argument, NULL, ARG_PROMPT_LOCALE }, + { "prompt-keymap", no_argument, NULL, ARG_PROMPT_KEYMAP }, + { "prompt-timezone", no_argument, NULL, ARG_PROMPT_TIMEZONE }, + { "prompt-hostname", no_argument, NULL, ARG_PROMPT_HOSTNAME }, + { "prompt-root-password", no_argument, NULL, ARG_PROMPT_ROOT_PASSWORD }, + { "copy", no_argument, NULL, ARG_COPY }, + { "copy-locale", no_argument, NULL, ARG_COPY_LOCALE }, + { "copy-keymap", no_argument, NULL, ARG_COPY_KEYMAP }, + { "copy-timezone", no_argument, NULL, ARG_COPY_TIMEZONE }, + { "copy-root-password", no_argument, NULL, ARG_COPY_ROOT_PASSWORD }, + { "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID }, + {} + }; + + int r, c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_ROOT: + r = parse_path_argument_and_warn(optarg, true, &arg_root); + if (r < 0) + return r; + break; + + case ARG_LOCALE: + if (!locale_is_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Locale %s is not valid.", optarg); + + r = free_and_strdup(&arg_locale, optarg); + if (r < 0) + return log_oom(); + + break; + + case ARG_LOCALE_MESSAGES: + if (!locale_is_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Locale %s is not valid.", optarg); + + r = free_and_strdup(&arg_locale_messages, optarg); + if (r < 0) + return log_oom(); + + break; + + case ARG_KEYMAP: + if (!keymap_is_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Keymap %s is not valid.", optarg); + + r = free_and_strdup(&arg_keymap, optarg); + if (r < 0) + return log_oom(); + + break; + + case ARG_TIMEZONE: + if (!timezone_is_valid(optarg, LOG_ERR)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Timezone %s is not valid.", optarg); + + r = free_and_strdup(&arg_timezone, optarg); + if (r < 0) + return log_oom(); + + break; + + case ARG_ROOT_PASSWORD: + r = free_and_strdup(&arg_root_password, optarg); + if (r < 0) + return log_oom(); + break; + + case ARG_ROOT_PASSWORD_FILE: + arg_root_password = mfree(arg_root_password); + + r = read_one_line_file(optarg, &arg_root_password); + if (r < 0) + return log_error_errno(r, "Failed to read %s: %m", optarg); + + break; + + case ARG_HOSTNAME: + if (!hostname_is_valid(optarg, true)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Host name %s is not valid.", optarg); + + hostname_cleanup(optarg); + r = free_and_strdup(&arg_hostname, optarg); + if (r < 0) + return log_oom(); + + break; + + case ARG_MACHINE_ID: + if (sd_id128_from_string(optarg, &arg_machine_id) < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse machine id %s.", optarg); + + break; + + case ARG_PROMPT: + arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true; + break; + + case ARG_PROMPT_LOCALE: + arg_prompt_locale = true; + break; + + case ARG_PROMPT_KEYMAP: + arg_prompt_keymap = true; + break; + + case ARG_PROMPT_TIMEZONE: + arg_prompt_timezone = true; + break; + + case ARG_PROMPT_HOSTNAME: + arg_prompt_hostname = true; + break; + + case ARG_PROMPT_ROOT_PASSWORD: + arg_prompt_root_password = true; + break; + + case ARG_COPY: + arg_copy_locale = arg_copy_keymap = arg_copy_timezone = arg_copy_root_password = true; + break; + + case ARG_COPY_LOCALE: + arg_copy_locale = true; + break; + + case ARG_COPY_KEYMAP: + arg_copy_keymap = true; + break; + + case ARG_COPY_TIMEZONE: + arg_copy_timezone = true; + break; + + case ARG_COPY_ROOT_PASSWORD: + arg_copy_root_password = true; + break; + + case ARG_SETUP_MACHINE_ID: + + r = sd_id128_randomize(&arg_machine_id); + if (r < 0) + return log_error_errno(r, "Failed to generate randomized machine ID: %m"); + + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int run(int argc, char *argv[]) { + bool enabled; + int r; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + log_setup_service(); + + umask(0022); + + r = proc_cmdline_get_bool("systemd.firstboot", &enabled); + if (r < 0) + return log_error_errno(r, "Failed to parse systemd.firstboot= kernel command line argument, ignoring: %m"); + if (r > 0 && !enabled) + return 0; /* disabled */ + + r = process_locale(); + if (r < 0) + return r; + + r = process_keymap(); + if (r < 0) + return r; + + r = process_timezone(); + if (r < 0) + return r; + + r = process_hostname(); + if (r < 0) + return r; + + r = process_machine_id(); + if (r < 0) + return r; + + r = process_root_password(); + if (r < 0) + return r; + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c new file mode 100644 index 00000000..80f7107b --- /dev/null +++ b/src/fsck/fsck.c @@ -0,0 +1,430 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Holger Hans Peter Freyther +***/ + +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-device.h" + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-util.h" +#include "device-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "fsck-util.h" +#include "main-func.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "special.h" +#include "stdio-util.h" +#include "util.h" + +static bool arg_skip = false; +static bool arg_force = false; +static bool arg_show_progress = false; +static const char *arg_repair = "-a"; + +static void start_target(const char *target, const char *mode) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + assert(target); + + r = bus_connect_system_systemd(&bus); + if (r < 0) { + log_error_errno(r, "Failed to get D-Bus connection: %m"); + return; + } + + log_info("Running request %s/start/replace", target); + + /* Start these units only if we can replace base.target with it */ + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnitReplace", + &error, + NULL, + "sss", "basic.target", target, mode); + + /* Don't print a warning if we aren't called during startup */ + if (r < 0 && !sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_JOB)) + log_error("Failed to start unit: %s", bus_error_message(&error, r)); +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + int r; + + assert(key); + + if (streq(key, "fsck.mode")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (streq(value, "auto")) + arg_force = arg_skip = false; + else if (streq(value, "force")) + arg_force = true; + else if (streq(value, "skip")) + arg_skip = true; + else + log_warning("Invalid fsck.mode= parameter '%s'. Ignoring.", value); + + } else if (streq(key, "fsck.repair")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (streq(value, "preen")) + arg_repair = "-a"; + else { + r = parse_boolean(value); + if (r > 0) + arg_repair = "-y"; + else if (r == 0) + arg_repair = "-n"; + else + log_warning("Invalid fsck.repair= parameter '%s'. Ignoring.", value); + } + } + +#if HAVE_SYSV_COMPAT + else if (streq(key, "fastboot") && !value) { + log_warning("Please pass 'fsck.mode=skip' rather than 'fastboot' on the kernel command line."); + arg_skip = true; + + } else if (streq(key, "forcefsck") && !value) { + log_warning("Please pass 'fsck.mode=force' rather than 'forcefsck' on the kernel command line."); + arg_force = true; + } +#endif + + return 0; +} + +static void test_files(void) { + +#if HAVE_SYSV_COMPAT + if (access("/fastboot", F_OK) >= 0) { + log_error("Please pass 'fsck.mode=skip' on the kernel command line rather than creating /fastboot on the root file system."); + arg_skip = true; + } + + if (access("/forcefsck", F_OK) >= 0) { + log_error("Please pass 'fsck.mode=force' on the kernel command line rather than creating /forcefsck on the root file system."); + arg_force = true; + } +#endif + + arg_show_progress = access("/run/systemd/show-status", F_OK) >= 0; +} + +static double percent(int pass, unsigned long cur, unsigned long max) { + /* Values stolen from e2fsck */ + + static const int pass_table[] = { + 0, 70, 90, 92, 95, 100 + }; + + if (pass <= 0) + return 0.0; + + if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0) + return 100.0; + + return (double) pass_table[pass-1] + + ((double) pass_table[pass] - (double) pass_table[pass-1]) * + (double) cur / (double) max; +} + +static int process_progress(int fd, FILE* console) { + _cleanup_fclose_ FILE *f = NULL; + usec_t last = 0; + bool locked = false; + int clear = 0, r; + + /* No progress pipe to process? Then we are a NOP. */ + if (fd < 0) + return 0; + + f = fdopen(fd, "r"); + if (!f) { + safe_close(fd); + return log_debug_errno(errno, "Failed to use pipe: %m"); + } + + for (;;) { + int pass, m; + unsigned long cur, max; + _cleanup_free_ char *device = NULL; + double p; + usec_t t; + + if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4) { + + if (ferror(f)) + r = log_warning_errno(errno, "Failed to read from progress pipe: %m"); + else if (feof(f)) + r = 0; + else + r = log_warning_errno(SYNTHETIC_ERRNO(errno), "Failed to parse progress pipe data"); + + break; + } + + /* Only show one progress counter at max */ + if (!locked) { + if (flock(fileno(console), LOCK_EX|LOCK_NB) < 0) + continue; + + locked = true; + } + + /* Only update once every 50ms */ + t = now(CLOCK_MONOTONIC); + if (last + 50 * USEC_PER_MSEC > t) + continue; + + last = t; + + p = percent(pass, cur, max); + fprintf(console, "\r%s: fsck %3.1f%% complete...\r%n", device, p, &m); + fflush(console); + + if (m > clear) + clear = m; + } + + if (clear > 0) { + unsigned j; + + fputc('\r', console); + for (j = 0; j < (unsigned) clear; j++) + fputc(' ', console); + fputc('\r', console); + fflush(console); + } + + return r; +} + +static int fsck_progress_socket(void) { + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/fsck.progress", + }; + + _cleanup_close_ int fd = -1; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + return log_warning_errno(errno, "socket(): %m"); + + if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) + return log_full_errno(IN_SET(errno, ECONNREFUSED, ENOENT) ? LOG_DEBUG : LOG_WARNING, + errno, "Failed to connect to progress socket %s, ignoring: %m", sa.un.sun_path); + + return TAKE_FD(fd); +} + +static int run(int argc, char *argv[]) { + _cleanup_close_pair_ int progress_pipe[2] = { -1, -1 }; + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + _cleanup_free_ char *dpath = NULL; + _cleanup_fclose_ FILE *console = NULL; + const char *device, *type; + bool root_directory; + struct stat st; + int r, exit_status; + pid_t pid; + + log_setup_service(); + + if (argc > 2) { + log_error("This program expects one or no arguments."); + return -EINVAL; + } + + umask(0022); + + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + test_files(); + + if (!arg_force && arg_skip) + return 0; + + if (argc > 1) { + dpath = strdup(argv[1]); + if (!dpath) + return log_oom(); + + device = dpath; + + if (stat(device, &st) < 0) + return log_error_errno(errno, "Failed to stat %s: %m", device); + + if (!S_ISBLK(st.st_mode)) { + log_error("%s is not a block device.", device); + return -EINVAL; + } + + r = sd_device_new_from_devnum(&dev, 'b', st.st_rdev); + if (r < 0) + return log_error_errno(r, "Failed to detect device %s: %m", device); + + root_directory = false; + } else { + struct timespec times[2]; + + /* Find root device */ + + if (stat("/", &st) < 0) + return log_error_errno(errno, "Failed to stat() the root directory: %m"); + + /* Virtual root devices don't need an fsck */ + if (major(st.st_dev) == 0) { + log_debug("Root directory is virtual or btrfs, skipping check."); + return 0; + } + + /* check if we are already writable */ + times[0] = st.st_atim; + times[1] = st.st_mtim; + + if (utimensat(AT_FDCWD, "/", times, 0) == 0) { + log_info("Root directory is writable, skipping check."); + return 0; + } + + r = sd_device_new_from_devnum(&dev, 'b', st.st_dev); + if (r < 0) + return log_error_errno(r, "Failed to detect root device: %m"); + + r = sd_device_get_devname(dev, &device); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to detect device node of root directory: %m"); + + root_directory = true; + } + + if (sd_device_get_property_value(dev, "ID_FS_TYPE", &type) >= 0) { + r = fsck_exists(type); + if (r < 0) + log_device_warning_errno(dev, r, "Couldn't detect if fsck.%s may be used, proceeding: %m", type); + else if (r == 0) { + log_device_info(dev, "fsck.%s doesn't exist, not checking file system.", type); + return 0; + } + } + + console = fopen("/dev/console", "we"); + if (console && + arg_show_progress && + pipe(progress_pipe) < 0) + return log_error_errno(errno, "pipe(): %m"); + + r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + char dash_c[STRLEN("-C") + DECIMAL_STR_MAX(int) + 1]; + int progress_socket = -1; + const char *cmdline[9]; + int i = 0; + + /* Child */ + + /* Close the reading side of the progress pipe */ + progress_pipe[0] = safe_close(progress_pipe[0]); + + /* Try to connect to a progress management daemon, if there is one */ + progress_socket = fsck_progress_socket(); + if (progress_socket >= 0) { + /* If this worked we close the progress pipe early, and just use the socket */ + progress_pipe[1] = safe_close(progress_pipe[1]); + xsprintf(dash_c, "-C%i", progress_socket); + } else if (progress_pipe[1] >= 0) { + /* Otherwise if we have the progress pipe to our own local handle, we use it */ + xsprintf(dash_c, "-C%i", progress_pipe[1]); + } else + dash_c[0] = 0; + + cmdline[i++] = "/sbin/fsck"; + cmdline[i++] = arg_repair; + cmdline[i++] = "-T"; + + /* + * Since util-linux v2.25 fsck uses /run/fsck/.lock files. + * The previous versions use flock for the device and conflict with + * udevd, see https://bugs.freedesktop.org/show_bug.cgi?id=79576#c5 + */ + cmdline[i++] = "-l"; + + if (!root_directory) + cmdline[i++] = "-M"; + + if (arg_force) + cmdline[i++] = "-f"; + + if (!isempty(dash_c)) + cmdline[i++] = dash_c; + + cmdline[i++] = device; + cmdline[i++] = NULL; + + (void) rlimit_nofile_safe(); + + execv(cmdline[0], (char**) cmdline); + _exit(FSCK_OPERATIONAL_ERROR); + } + + if (console) { + progress_pipe[1] = safe_close(progress_pipe[1]); + (void) process_progress(TAKE_FD(progress_pipe[0]), console); + } + + exit_status = wait_for_terminate_and_check("fsck", pid, WAIT_LOG_ABNORMAL); + if (exit_status < 0) + return exit_status; + if ((exit_status & ~FSCK_ERROR_CORRECTED) != FSCK_SUCCESS) { + log_error("fsck failed with exit status %i.", exit_status); + + if ((exit_status & FSCK_SYSTEM_SHOULD_REBOOT) && root_directory) { + /* System should be rebooted. */ + start_target(SPECIAL_REBOOT_TARGET, "replace-irreversibly"); + return -EINVAL; + } else if (exit_status & (FSCK_SYSTEM_SHOULD_REBOOT | FSCK_ERRORS_LEFT_UNCORRECTED)) + /* Some other problem */ + start_target(SPECIAL_EMERGENCY_TARGET, "replace"); + else + log_warning("Ignoring error."); + } + + if (exit_status & FSCK_ERROR_CORRECTED) + (void) touch("/run/systemd/quotacheck"); + + return !!(exit_status & (FSCK_SYSTEM_SHOULD_REBOOT | FSCK_ERRORS_LEFT_UNCORRECTED)); +} + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c new file mode 100644 index 00000000..6fd6fbdf --- /dev/null +++ b/src/fstab-generator/fstab-generator.c @@ -0,0 +1,905 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "fstab-util.h" +#include "generator.h" +#include "log.h" +#include "main-func.h" +#include "mkdir.h" +#include "mount-setup.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "special.h" +#include "specifier.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "util.h" +#include "virt.h" +#include "volatile-util.h" + +typedef enum MountpointFlags { + NOAUTO = 1 << 0, + NOFAIL = 1 << 1, + AUTOMOUNT = 1 << 2, + MAKEFS = 1 << 3, + GROWFS = 1 << 4, +} MountpointFlags; + +static const char *arg_dest = NULL; +static const char *arg_dest_late = NULL; +static bool arg_fstab_enabled = true; +static char *arg_root_what = NULL; +static char *arg_root_fstype = NULL; +static char *arg_root_options = NULL; +static char *arg_root_hash = NULL; +static int arg_root_rw = -1; +static char *arg_usr_what = NULL; +static char *arg_usr_fstype = NULL; +static char *arg_usr_options = NULL; +static VolatileMode arg_volatile_mode = _VOLATILE_MODE_INVALID; + +STATIC_DESTRUCTOR_REGISTER(arg_root_what, freep); +STATIC_DESTRUCTOR_REGISTER(arg_root_fstype, freep); +STATIC_DESTRUCTOR_REGISTER(arg_root_options, freep); +STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep); +STATIC_DESTRUCTOR_REGISTER(arg_usr_what, freep); +STATIC_DESTRUCTOR_REGISTER(arg_usr_fstype, freep); +STATIC_DESTRUCTOR_REGISTER(arg_usr_options, freep); + +static int write_options(FILE *f, const char *options) { + _cleanup_free_ char *o = NULL; + + if (isempty(options)) + return 0; + + if (streq(options, "defaults")) + return 0; + + o = specifier_escape(options); + if (!o) + return log_oom(); + + fprintf(f, "Options=%s\n", o); + return 1; +} + +static int write_what(FILE *f, const char *what) { + _cleanup_free_ char *w = NULL; + + w = specifier_escape(what); + if (!w) + return log_oom(); + + fprintf(f, "What=%s\n", w); + return 1; +} + +static int add_swap( + const char *what, + struct mntent *me, + MountpointFlags flags) { + + _cleanup_free_ char *name = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(what); + assert(me); + + if (access("/proc/swaps", F_OK) < 0) { + log_info("Swap not supported, ignoring fstab swap entry for %s.", what); + return 0; + } + + if (detect_container() > 0) { + log_info("Running in a container, ignoring fstab swap entry for %s.", what); + return 0; + } + + r = unit_name_from_path(what, ".swap", &name); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + r = generator_open_unit_file(arg_dest, fstab_path(), name, &f); + if (r < 0) + return r; + + fprintf(f, + "[Unit]\n" + "SourcePath=%s\n" + "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n" + "[Swap]\n", + fstab_path()); + + r = write_what(f, what); + if (r < 0) + return r; + + r = write_options(f, me->mnt_opts); + if (r < 0) + return r; + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", name); + + /* use what as where, to have a nicer error message */ + r = generator_write_timeouts(arg_dest, what, what, me->mnt_opts, NULL); + if (r < 0) + return r; + + if (flags & MAKEFS) { + r = generator_hook_up_mkswap(arg_dest, what); + if (r < 0) + return r; + } + + if (flags & GROWFS) + /* TODO: swap devices must be wiped and recreated */ + log_warning("%s: growing swap devices is currently unsupported.", what); + + if (!(flags & NOAUTO)) { + r = generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET, + (flags & NOFAIL) ? "wants" : "requires", name); + if (r < 0) + return r; + } + + return 0; +} + +static bool mount_is_network(struct mntent *me) { + assert(me); + + return fstab_test_option(me->mnt_opts, "_netdev\0") || + fstype_is_network(me->mnt_type); +} + +static bool mount_in_initrd(struct mntent *me) { + assert(me); + + return fstab_test_option(me->mnt_opts, "x-initrd.mount\0") || + streq(me->mnt_dir, "/usr"); +} + +static int write_timeout(FILE *f, const char *where, const char *opts, + const char *filter, const char *variable) { + _cleanup_free_ char *timeout = NULL; + char timespan[FORMAT_TIMESPAN_MAX]; + usec_t u; + int r; + + r = fstab_filter_options(opts, filter, NULL, &timeout, NULL); + if (r < 0) + return log_warning_errno(r, "Failed to parse options: %m"); + if (r == 0) + return 0; + + r = parse_sec_fix_0(timeout, &u); + if (r < 0) { + log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout); + return 0; + } + + fprintf(f, "%s=%s\n", variable, format_timespan(timespan, sizeof(timespan), u, 0)); + + return 0; +} + +static int write_idle_timeout(FILE *f, const char *where, const char *opts) { + return write_timeout(f, where, opts, + "x-systemd.idle-timeout\0", "TimeoutIdleSec"); +} + +static int write_mount_timeout(FILE *f, const char *where, const char *opts) { + return write_timeout(f, where, opts, + "x-systemd.mount-timeout\0", "TimeoutSec"); +} + +static int write_dependency(FILE *f, const char *opts, + const char *filter, const char *format) { + _cleanup_strv_free_ char **names = NULL, **units = NULL; + _cleanup_free_ char *res = NULL; + char **s; + int r; + + assert(f); + assert(opts); + + r = fstab_extract_values(opts, filter, &names); + if (r < 0) + return log_warning_errno(r, "Failed to parse options: %m"); + if (r == 0) + return 0; + + STRV_FOREACH(s, names) { + char *x; + + r = unit_name_mangle_with_suffix(*s, "as dependency", 0, ".mount", &x); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + r = strv_consume(&units, x); + if (r < 0) + return log_oom(); + } + + if (units) { + res = strv_join(units, " "); + if (!res) + return log_oom(); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + fprintf(f, format, res); +#pragma GCC diagnostic pop + } + + return 0; +} + +static int write_after(FILE *f, const char *opts) { + return write_dependency(f, opts, "x-systemd.after", "After=%1$s\n"); +} + +static int write_requires_after(FILE *f, const char *opts) { + return write_dependency(f, opts, + "x-systemd.requires", "After=%1$s\nRequires=%1$s\n"); +} + +static int write_before(FILE *f, const char *opts) { + return write_dependency(f, opts, + "x-systemd.before", "Before=%1$s\n"); +} + +static int write_requires_mounts_for(FILE *f, const char *opts) { + _cleanup_strv_free_ char **paths = NULL, **paths_escaped = NULL; + _cleanup_free_ char *res = NULL; + int r; + + assert(f); + assert(opts); + + r = fstab_extract_values(opts, "x-systemd.requires-mounts-for", &paths); + if (r < 0) + return log_warning_errno(r, "Failed to parse options: %m"); + if (r == 0) + return 0; + + r = specifier_escape_strv(paths, &paths_escaped); + if (r < 0) + return log_error_errno(r, "Failed to escape paths: %m"); + + res = strv_join(paths_escaped, " "); + if (!res) + return log_oom(); + + fprintf(f, "RequiresMountsFor=%s\n", res); + + return 0; +} + +static int add_mount( + const char *dest, + const char *what, + const char *where, + const char *original_where, + const char *fstype, + const char *opts, + int passno, + MountpointFlags flags, + const char *post, + const char *source) { + + _cleanup_free_ char + *name = NULL, + *automount_name = NULL, + *filtered = NULL, + *where_escaped = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(what); + assert(where); + assert(opts); + assert(post); + assert(source); + + if (streq_ptr(fstype, "autofs")) + return 0; + + if (!is_path(where)) { + log_warning("Mount point %s is not a valid path, ignoring.", where); + return 0; + } + + if (mount_point_is_api(where) || + mount_point_ignore(where)) + return 0; + + if (path_equal(where, "/")) { + if (flags & NOAUTO) + log_warning("Ignoring \"noauto\" for root device"); + if (flags & NOFAIL) + log_warning("Ignoring \"nofail\" for root device"); + if (flags & AUTOMOUNT) + log_warning("Ignoring automount option for root device"); + + SET_FLAG(flags, NOAUTO | NOFAIL | AUTOMOUNT, false); + } + + r = unit_name_from_path(where, ".mount", &name); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + r = generator_open_unit_file(dest, fstab_path(), name, &f); + if (r < 0) + return r; + + fprintf(f, + "[Unit]\n" + "SourcePath=%s\n" + "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n", + source); + + /* All mounts under /sysroot need to happen later, at initrd-fs.target time. IOW, it's not + * technically part of the basic initrd filesystem itself, and so shouldn't inherit the default + * Before=local-fs.target dependency. */ + if (in_initrd() && path_startswith(where, "/sysroot")) + fprintf(f, "DefaultDependencies=no\n"); + + if (STRPTR_IN_SET(fstype, "nfs", "nfs4") && !(flags & AUTOMOUNT) && + fstab_test_yes_no_option(opts, "bg\0" "fg\0")) { + /* The default retry timeout that mount.nfs uses for 'bg' mounts + * is 10000 minutes, where as it uses 2 minutes for 'fg' mounts. + * As we are making 'bg' mounts look like an 'fg' mount to + * mount.nfs (so systemd can manage the job-control aspects of 'bg'), + * we need to explicitly preserve that default, and also ensure + * the systemd mount-timeout doesn't interfere. + * By placing these options first, they can be over-ridden by + * settings in /etc/fstab. */ + opts = strjoina("x-systemd.mount-timeout=infinity,retry=10000,", opts, ",fg"); + SET_FLAG(flags, NOFAIL, true); + } + + if (!(flags & NOFAIL) && !(flags & AUTOMOUNT)) + fprintf(f, "Before=%s\n", post); + + if (!(flags & AUTOMOUNT) && opts) { + r = write_after(f, opts); + if (r < 0) + return r; + r = write_requires_after(f, opts); + if (r < 0) + return r; + r = write_before(f, opts); + if (r < 0) + return r; + r = write_requires_mounts_for(f, opts); + if (r < 0) + return r; + } + + if (passno != 0) { + r = generator_write_fsck_deps(f, dest, what, where, fstype); + if (r < 0) + return r; + } + + fprintf(f, "\n[Mount]\n"); + if (original_where) + fprintf(f, "# Canonicalized from %s\n", original_where); + + where_escaped = specifier_escape(where); + if (!where_escaped) + return log_oom(); + fprintf(f, "Where=%s\n", where_escaped); + + r = write_what(f, what); + if (r < 0) + return r; + + if (!isempty(fstype) && !streq(fstype, "auto")) { + _cleanup_free_ char *t; + + t = specifier_escape(fstype); + if (!t) + return -ENOMEM; + + fprintf(f, "Type=%s\n", t); + } + + r = generator_write_timeouts(dest, what, where, opts, &filtered); + if (r < 0) + return r; + + r = generator_write_device_deps(dest, what, where, opts); + if (r < 0) + return r; + + r = write_mount_timeout(f, where, opts); + if (r < 0) + return r; + + r = write_options(f, filtered); + if (r < 0) + return r; + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", name); + + if (flags & MAKEFS) { + r = generator_hook_up_mkfs(dest, what, where, fstype); + if (r < 0) + return r; + } + + if (flags & GROWFS) { + r = generator_hook_up_growfs(dest, where, post); + if (r < 0) + return r; + } + + if (!(flags & NOAUTO) && !(flags & AUTOMOUNT)) { + r = generator_add_symlink(dest, post, + (flags & NOFAIL) ? "wants" : "requires", name); + if (r < 0) + return r; + } + + if (flags & AUTOMOUNT) { + r = unit_name_from_path(where, ".automount", &automount_name); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + f = safe_fclose(f); + + r = generator_open_unit_file(dest, fstab_path(), automount_name, &f); + if (r < 0) + return r; + + fprintf(f, + "[Unit]\n" + "SourcePath=%s\n" + "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n", + source); + + fprintf(f, "Before=%s\n", post); + + if (opts) { + r = write_after(f, opts); + if (r < 0) + return r; + r = write_requires_after(f, opts); + if (r < 0) + return r; + r = write_before(f, opts); + if (r < 0) + return r; + r = write_requires_mounts_for(f, opts); + if (r < 0) + return r; + } + + fprintf(f, + "\n" + "[Automount]\n" + "Where=%s\n", + where_escaped); + + r = write_idle_timeout(f, where, opts); + if (r < 0) + return r; + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", automount_name); + + r = generator_add_symlink(dest, post, + (flags & NOFAIL) ? "wants" : "requires", automount_name); + if (r < 0) + return r; + } + + return 0; +} + +static int parse_fstab(bool initrd) { + _cleanup_endmntent_ FILE *f = NULL; + const char *fstab; + struct mntent *me; + int r = 0; + + fstab = initrd ? "/sysroot/etc/fstab" : fstab_path(); + log_debug("Parsing %s...", fstab); + + f = setmntent(fstab, "re"); + if (!f) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open %s: %m", fstab); + } + + while ((me = getmntent(f))) { + _cleanup_free_ char *where = NULL, *what = NULL, *canonical_where = NULL; + bool makefs, growfs, noauto, nofail; + int k; + + if (initrd && !mount_in_initrd(me)) + continue; + + what = fstab_node_to_udev_node(me->mnt_fsname); + if (!what) + return log_oom(); + + if (is_device_path(what) && path_is_read_only_fs("/sys") > 0) { + log_info("Running in a container, ignoring fstab device entry for %s.", what); + continue; + } + + where = strdup(me->mnt_dir); + if (!where) + return log_oom(); + + if (is_path(where)) { + path_simplify(where, false); + + /* Follow symlinks here; see 5261ba901845c084de5a8fd06500ed09bfb0bd80 which makes sense for + * mount units, but causes problems since it historically worked to have symlinks in e.g. + * /etc/fstab. So we canonicalize here. Note that we use CHASE_NONEXISTENT to handle the case + * where a symlink refers to another mount target; this works assuming the sub-mountpoint + * target is the final directory. */ + r = chase_symlinks(where, initrd ? "/sysroot" : NULL, + CHASE_PREFIX_ROOT | CHASE_NONEXISTENT, + &canonical_where, NULL); + if (r < 0) /* If we can't canonicalize we continue on as if it wasn't a symlink */ + log_debug_errno(r, "Failed to read symlink target for %s, ignoring: %m", where); + else if (streq(canonical_where, where)) /* If it was fully canonicalized, suppress the change */ + canonical_where = mfree(canonical_where); + else + log_debug("Canonicalized what=%s where=%s to %s", what, where, canonical_where); + } + + makefs = fstab_test_option(me->mnt_opts, "x-systemd.makefs\0"); + growfs = fstab_test_option(me->mnt_opts, "x-systemd.growfs\0"); + noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0"); + nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0"); + + log_debug("Found entry what=%s where=%s type=%s makefs=%s growfs=%s noauto=%s nofail=%s", + what, where, me->mnt_type, + yes_no(makefs), yes_no(growfs), + yes_no(noauto), yes_no(nofail)); + + if (streq(me->mnt_type, "swap")) + k = add_swap(what, me, + makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL); + else { + bool automount; + const char *post; + + automount = fstab_test_option(me->mnt_opts, + "comment=systemd.automount\0" + "x-systemd.automount\0"); + if (initrd) + post = SPECIAL_INITRD_FS_TARGET; + else if (mount_is_network(me)) + post = SPECIAL_REMOTE_FS_TARGET; + else + post = SPECIAL_LOCAL_FS_TARGET; + + k = add_mount(arg_dest, + what, + canonical_where ?: where, + canonical_where ? where: NULL, + me->mnt_type, + me->mnt_opts, + me->mnt_passno, + makefs*MAKEFS | growfs*GROWFS | noauto*NOAUTO | nofail*NOFAIL | automount*AUTOMOUNT, + post, + fstab); + } + + if (r >= 0 && k < 0) + r = k; + } + + return r; +} + +static int add_sysroot_mount(void) { + _cleanup_free_ char *what = NULL; + const char *opts; + int r; + + if (isempty(arg_root_what)) { + log_debug("Could not find a root= entry on the kernel command line."); + return 0; + } + + if (streq(arg_root_what, "gpt-auto")) { + /* This is handled by the gpt-auto generator */ + log_debug("Skipping root directory handling, as gpt-auto was requested."); + return 0; + } + + if (path_equal(arg_root_what, "/dev/nfs")) { + /* This is handled by the kernel or the initrd */ + log_debug("Skipping root directory handling, as /dev/nfs was requested."); + return 0; + } + + what = fstab_node_to_udev_node(arg_root_what); + if (!what) + return log_oom(); + + if (!arg_root_options) + opts = arg_root_rw > 0 ? "rw" : "ro"; + else if (arg_root_rw >= 0 || + !fstab_test_option(arg_root_options, "ro\0" "rw\0")) + opts = strjoina(arg_root_options, ",", arg_root_rw > 0 ? "rw" : "ro"); + else + opts = arg_root_options; + + log_debug("Found entry what=%s where=/sysroot type=%s", what, strna(arg_root_fstype)); + + if (is_device_path(what)) { + r = generator_write_initrd_root_device_deps(arg_dest, what); + if (r < 0) + return r; + } + + return add_mount(arg_dest, + what, + "/sysroot", + NULL, + arg_root_fstype, + opts, + is_device_path(what) ? 1 : 0, /* passno */ + 0, /* makefs off, growfs off, noauto off, nofail off, automount off */ + SPECIAL_INITRD_ROOT_FS_TARGET, + "/proc/cmdline"); +} + +static int add_sysroot_usr_mount(void) { + _cleanup_free_ char *what = NULL; + const char *opts; + + if (!arg_usr_what && !arg_usr_fstype && !arg_usr_options) + return 0; + + if (arg_root_what && !arg_usr_what) { + /* Copy over the root device, in case the /usr mount just differs in a mount option (consider btrfs subvolumes) */ + arg_usr_what = strdup(arg_root_what); + if (!arg_usr_what) + return log_oom(); + } + + if (arg_root_fstype && !arg_usr_fstype) { + arg_usr_fstype = strdup(arg_root_fstype); + if (!arg_usr_fstype) + return log_oom(); + } + + if (arg_root_options && !arg_usr_options) { + arg_usr_options = strdup(arg_root_options); + if (!arg_usr_options) + return log_oom(); + } + + if (!arg_usr_what) + return 0; + + what = fstab_node_to_udev_node(arg_usr_what); + if (!what) + return log_oom(); + + if (!arg_usr_options) + opts = arg_root_rw > 0 ? "rw" : "ro"; + else if (!fstab_test_option(arg_usr_options, "ro\0" "rw\0")) + opts = strjoina(arg_usr_options, ",", arg_root_rw > 0 ? "rw" : "ro"); + else + opts = arg_usr_options; + + log_debug("Found entry what=%s where=/sysroot/usr type=%s", what, strna(arg_usr_fstype)); + return add_mount(arg_dest, + what, + "/sysroot/usr", + NULL, + arg_usr_fstype, + opts, + is_device_path(what) ? 1 : 0, /* passno */ + 0, + SPECIAL_INITRD_FS_TARGET, + "/proc/cmdline"); +} + +static int add_volatile_root(void) { + + /* Let's add in systemd-remount-volatile.service which will remount the root device to tmpfs if this is + * requested (or as an overlayfs), leaving only /usr from the root mount inside. */ + + if (!IN_SET(arg_volatile_mode, VOLATILE_YES, VOLATILE_OVERLAY)) + return 0; + + return generator_add_symlink(arg_dest, SPECIAL_INITRD_ROOT_FS_TARGET, "requires", + SYSTEM_DATA_UNIT_PATH "/" SPECIAL_VOLATILE_ROOT_SERVICE); +} + +static int add_volatile_var(void) { + + if (arg_volatile_mode != VOLATILE_STATE) + return 0; + + /* If requested, mount /var as tmpfs, but do so only if there's nothing else defined for this. */ + + return add_mount(arg_dest_late, + "tmpfs", + "/var", + NULL, + "tmpfs", + "mode=0755", + 0, + 0, + SPECIAL_LOCAL_FS_TARGET, + "/proc/cmdline"); +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + int r; + + /* root=, usr=, usrfstype= and roofstype= may occur more than once, the last + * instance should take precedence. In the case of multiple rootflags= + * or usrflags= the arguments should be concatenated */ + + if (STR_IN_SET(key, "fstab", "rd.fstab")) { + + r = value ? parse_boolean(value) : 1; + if (r < 0) + log_warning("Failed to parse fstab switch %s. Ignoring.", value); + else + arg_fstab_enabled = r; + + } else if (streq(key, "root")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (free_and_strdup(&arg_root_what, value) < 0) + return log_oom(); + + } else if (streq(key, "rootfstype")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (free_and_strdup(&arg_root_fstype, value) < 0) + return log_oom(); + + } else if (streq(key, "rootflags")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (!strextend_with_separator(&arg_root_options, ",", value, NULL)) + return log_oom(); + + } else if (streq(key, "roothash")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (free_and_strdup(&arg_root_hash, value) < 0) + return log_oom(); + + } else if (streq(key, "mount.usr")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (free_and_strdup(&arg_usr_what, value) < 0) + return log_oom(); + + } else if (streq(key, "mount.usrfstype")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (free_and_strdup(&arg_usr_fstype, value) < 0) + return log_oom(); + + } else if (streq(key, "mount.usrflags")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (!strextend_with_separator(&arg_usr_options, ",", value, NULL)) + return log_oom(); + + } else if (streq(key, "rw") && !value) + arg_root_rw = true; + else if (streq(key, "ro") && !value) + arg_root_rw = false; + else if (streq(key, "systemd.volatile")) { + VolatileMode m; + + if (value) { + m = volatile_mode_from_string(value); + if (m < 0) + log_warning("Failed to parse systemd.volatile= argument: %s", value); + else + arg_volatile_mode = m; + } else + arg_volatile_mode = VOLATILE_YES; + } + + return 0; +} + +static int determine_root(void) { + /* If we have a root hash but no root device then Verity is used, and we use the "root" DM device as root. */ + + if (arg_root_what) + return 0; + + if (!arg_root_hash) + return 0; + + arg_root_what = strdup("/dev/mapper/root"); + if (!arg_root_what) + return log_oom(); + + log_info("Using verity root device %s.", arg_root_what); + + return 1; +} + +static int run(const char *dest, const char *dest_early, const char *dest_late) { + int r, r2 = 0, r3 = 0; + + assert_se(arg_dest = dest); + assert_se(arg_dest_late = dest_late); + + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + (void) determine_root(); + + /* Always honour root= and usr= in the kernel command line if we are in an initrd */ + if (in_initrd()) { + r = add_sysroot_mount(); + + r2 = add_sysroot_usr_mount(); + + r3 = add_volatile_root(); + } else + r = add_volatile_var(); + + /* Honour /etc/fstab only when that's enabled */ + if (arg_fstab_enabled) { + /* Parse the local /etc/fstab, possibly from the initrd */ + r2 = parse_fstab(false); + + /* If running in the initrd also parse the /etc/fstab from the host */ + if (in_initrd()) + r3 = parse_fstab(true); + else + r3 = generator_enable_remount_fs_service(arg_dest); + } + + return r < 0 ? r : r2 < 0 ? r2 : r3; +} + +DEFINE_MAIN_GENERATOR_FUNCTION(run); diff --git a/src/fuzz/fuzz-bus-label.c b/src/fuzz/fuzz-bus-label.c new file mode 100644 index 00000000..46a3d23d --- /dev/null +++ b/src/fuzz/fuzz-bus-label.c @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "bus-label.h" +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_free_ char *unescaped = NULL, *escaped = NULL; + + unescaped = bus_label_unescape_n((const char*)data, size); + assert_se(unescaped != NULL); + escaped = bus_label_escape(unescaped); + assert_se(escaped != NULL); + + return 0; +} diff --git a/src/fuzz/fuzz-bus-message.c b/src/fuzz/fuzz-bus-message.c new file mode 100644 index 00000000..aca82eda --- /dev/null +++ b/src/fuzz/fuzz-bus-message.c @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-dump.h" +#include "bus-message.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_free_ char *out = NULL; /* out should be freed after g */ + size_t out_size; + _cleanup_fclose_ FILE *g = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ void *buffer = NULL; + int r; + + /* We don't want to fill the logs with messages about parse errors. + * Disable most logging if not running standalone */ + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + r = sd_bus_new(&bus); + assert_se(r >= 0); + + assert_se(buffer = memdup(data, size)); + + r = bus_message_from_malloc(bus, buffer, size, NULL, 0, NULL, &m); + if (r == -EBADMSG) + return 0; + assert_se(r >= 0); + TAKE_PTR(buffer); + + if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) + assert_se(g = open_memstream_unlocked(&out, &out_size)); + + bus_message_dump(m, g ?: stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + r = sd_bus_message_rewind(m, true); + assert_se(r >= 0); + + return 0; +} diff --git a/src/fuzz/fuzz-calendarspec.c b/src/fuzz/fuzz-calendarspec.c new file mode 100644 index 00000000..8f031503 --- /dev/null +++ b/src/fuzz/fuzz-calendarspec.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "calendarspec.h" +#include "fd-util.h" +#include "fuzz.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(calendar_spec_freep) CalendarSpec *cspec = NULL; + _cleanup_free_ char *str = NULL, *p = NULL; + + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + str = memdup_suffix0(data, size); + + if (calendar_spec_from_string(str, &cspec) >= 0) { + (void) calendar_spec_valid(cspec); + (void) calendar_spec_normalize(cspec); + (void) calendar_spec_to_string(cspec, &p); + } + + return 0; +} diff --git a/src/fuzz/fuzz-catalog.c b/src/fuzz/fuzz-catalog.c new file mode 100644 index 00000000..ecf25b18 --- /dev/null +++ b/src/fuzz/fuzz-catalog.c @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "catalog.h" +#include "fd-util.h" +#include "fs-util.h" +#include "fuzz.h" +#include "tmpfile-util.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(unlink_tempfilep) char name[] = "/tmp/fuzz-catalog.XXXXXX"; + _cleanup_close_ int fd = -1; + _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL; + + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + assert_se(h = ordered_hashmap_new(&catalog_hash_ops)); + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, data, size) == (ssize_t) size); + + (void) catalog_import_file(h, name); + + return 0; +} diff --git a/src/fuzz/fuzz-compress.c b/src/fuzz/fuzz-compress.c new file mode 100644 index 00000000..9c5dfc92 --- /dev/null +++ b/src/fuzz/fuzz-compress.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "compress.h" +#include "fuzz.h" + +static int compress(int alg, + const void *src, uint64_t src_size, + void *dst, size_t dst_alloc_size, size_t *dst_size) { + + if (alg == OBJECT_COMPRESSED_LZ4) + return compress_blob_lz4(src, src_size, dst, dst_alloc_size, dst_size); + if (alg == OBJECT_COMPRESSED_XZ) + return compress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size); + return -EOPNOTSUPP; +} + +typedef struct header { + uint32_t alg:2; /* We have only two compression algorithms so far, but we might add + * more in the future. Let's make this a bit wider so our fuzzer + * cases remain stable in the future. */ + uint32_t sw_len; + uint32_t sw_alloc; + uint32_t reserved[3]; /* Extra space to keep fuzz cases stable in case we need to + * add stuff in the future. */ + uint8_t data[]; +} header; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_free_ void *buf = NULL, *buf2 = NULL; + int r; + + if (size < offsetof(header, data) + 1) + return 0; + + const header *h = (struct header*) data; + const size_t data_len = size - offsetof(header, data); + + int alg = h->alg; + + /* We don't want to fill the logs with messages about parse errors. + * Disable most logging if not running standalone */ + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + log_info("Using compression %s, data size=%zu", + object_compressed_to_string(alg) ?: "(none)", + data_len); + + buf = malloc(MAX(size, 128u)); /* Make the buffer a bit larger for very small data */ + if (!buf) { + log_oom(); + return 0; + } + + size_t csize; + r = compress(alg, h->data, data_len, buf, size, &csize); + if (r < 0) { + log_error_errno(r, "Compression failed: %m"); + return 0; + } + + log_debug("Compressed %zu bytes to → %zu bytes", data_len, csize); + + size_t sw_alloc = MAX(h->sw_alloc, 1u); + buf2 = malloc(sw_alloc); + if (!buf) { + log_oom(); + return 0; + } + + size_t sw_len = MIN(data_len - 1, h->sw_len); + + r = decompress_startswith(alg, buf, csize, &buf2, &sw_alloc, h->data, sw_len, h->data[sw_len]); + assert_se(r > 0); + + return 0; +} diff --git a/src/fuzz/fuzz-dhcp-server.c b/src/fuzz/fuzz-dhcp-server.c new file mode 100644 index 00000000..71bb99a3 --- /dev/null +++ b/src/fuzz/fuzz-dhcp-server.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "fuzz.h" + +#include "sd-dhcp-server.c" + +/* stub out network so that the server doesn't send */ +ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { + return len; +} + +ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) { + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; + struct in_addr address = {.s_addr = htobe32(UINT32_C(10) << 24 | UINT32_C(1))}; + static const uint8_t chaddr[] = {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}; + uint8_t *client_id; + DHCPLease *lease; + int pool_offset; + + if (size < sizeof(DHCPMessage)) + return 0; + + assert_se(sd_dhcp_server_new(&server, 1) >= 0); + server->fd = open("/dev/null", O_RDWR|O_CLOEXEC|O_NOCTTY); + assert_se(server->fd >= 0); + assert_se(sd_dhcp_server_configure_pool(server, &address, 24, 0, 0) >= 0); + + /* add a lease to the pool to expose additional code paths */ + client_id = malloc(2); + assert_se(client_id); + client_id[0] = 2; + client_id[1] = 2; + lease = new0(DHCPLease, 1); + assert_se(lease); + lease->client_id.length = 2; + lease->client_id.data = client_id; + lease->address = htobe32(UINT32_C(10) << 24 | UINT32_C(2)); + lease->gateway = htobe32(UINT32_C(10) << 24 | UINT32_C(1)); + lease->expiration = UINT64_MAX; + memcpy(lease->chaddr, chaddr, 16); + pool_offset = get_pool_offset(server, lease->address); + server->bound_leases[pool_offset] = lease; + assert_se(hashmap_put(server->leases_by_client_id, &lease->client_id, lease) >= 0); + + (void) dhcp_server_handle_message(server, (DHCPMessage*)data, size); + + return 0; +} diff --git a/src/fuzz/fuzz-dhcp-server.options b/src/fuzz/fuzz-dhcp-server.options new file mode 100644 index 00000000..5c330e5c --- /dev/null +++ b/src/fuzz/fuzz-dhcp-server.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 600 diff --git a/src/fuzz/fuzz-dhcp6-client.c b/src/fuzz/fuzz-dhcp6-client.c new file mode 100644 index 00000000..6d887eaf --- /dev/null +++ b/src/fuzz/fuzz-dhcp6-client.c @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-dhcp6-client.h" +#include "sd-event.h" + +#include "dhcp6-internal.h" +#include "dhcp6-protocol.h" +#include "fd-util.h" +#include "fuzz.h" + +static int test_dhcp_fd[2] = { -1, -1 }; + +int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, + const void *packet, size_t len) { + return len; +} + +int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) { + assert_se(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_dhcp_fd) >= 0); + return test_dhcp_fd[0]; +} + +static void fuzz_client(const uint8_t *data, size_t size, bool is_information_request_enabled) { + _cleanup_(sd_event_unrefp) sd_event *e; + _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; + struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; + + assert_se(sd_event_new(&e) >= 0); + assert_se(sd_dhcp6_client_new(&client) >= 0); + assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0); + assert_se(sd_dhcp6_client_set_ifindex(client, 42) == 0); + assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); + assert_se(sd_dhcp6_client_set_information_request(client, is_information_request_enabled) == 0); + + assert_se(sd_dhcp6_client_start(client) >= 0); + + if (size >= sizeof(DHCP6Message)) + assert_se(sd_dhcp6_client_set_transaction_id(client, htobe32(0x00ffffff) & ((const DHCP6Message *) data)->transaction_id) == 0); + + assert_se(write(test_dhcp_fd[1], data, size) == (ssize_t) size); + + sd_event_run(e, (uint64_t) -1); + + assert_se(sd_dhcp6_client_stop(client) >= 0); + + test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]); +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size > 65536) + return 0; + + /* This triggers client_receive_advertise */ + fuzz_client(data, size, false); + + /* This triggers client_receive_reply */ + fuzz_client(data, size, true); + + return 0; +} diff --git a/src/fuzz/fuzz-dhcp6-client.options b/src/fuzz/fuzz-dhcp6-client.options new file mode 100644 index 00000000..678d526b --- /dev/null +++ b/src/fuzz/fuzz-dhcp6-client.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65536 diff --git a/src/fuzz/fuzz-dns-packet.c b/src/fuzz/fuzz-dns-packet.c new file mode 100644 index 00000000..9bf95b9c --- /dev/null +++ b/src/fuzz/fuzz-dns-packet.c @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fuzz.h" +#include "memory-util.h" +#include "resolved-dns-packet.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + + if (size > DNS_PACKET_SIZE_MAX) + return 0; + + assert_se(dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, DNS_PACKET_SIZE_MAX) >= 0); + p->size = 0; /* by default append starts after the header, undo that */ + assert_se(dns_packet_append_blob(p, data, size, NULL) >= 0); + if (size < DNS_PACKET_HEADER_SIZE) { + /* make sure we pad the packet back up to the minimum header size */ + assert_se(p->allocated >= DNS_PACKET_HEADER_SIZE); + memzero(DNS_PACKET_DATA(p) + size, DNS_PACKET_HEADER_SIZE - size); + p->size = DNS_PACKET_HEADER_SIZE; + } + (void) dns_packet_extract(p); + + return 0; +} diff --git a/src/fuzz/fuzz-dns-packet.options b/src/fuzz/fuzz-dns-packet.options new file mode 100644 index 00000000..0824b19f --- /dev/null +++ b/src/fuzz/fuzz-dns-packet.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/src/fuzz/fuzz-env-file.c b/src/fuzz/fuzz-env-file.c new file mode 100644 index 00000000..d945dfc0 --- /dev/null +++ b/src/fuzz/fuzz-env-file.c @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "env-file.h" +#include "fileio.h" +#include "fd-util.h" +#include "fuzz.h" +#include "strv.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_strv_free_ char **rl = NULL, **rlp = NULL; + + if (size == 0 || size > 65535) + return 0; + + f = fmemopen_unlocked((char*) data, size, "re"); + assert_se(f); + + /* We don't want to fill the logs with messages about parse errors. + * Disable most logging if not running standalone */ + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + (void) load_env_file(f, NULL, &rl); + assert_se(fseek(f, 0, SEEK_SET) == 0); + (void) load_env_file_pairs(f, NULL, &rlp); + + return 0; +} diff --git a/src/fuzz/fuzz-env-file.options b/src/fuzz/fuzz-env-file.options new file mode 100644 index 00000000..0824b19f --- /dev/null +++ b/src/fuzz/fuzz-env-file.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/src/fuzz/fuzz-fido-id-desc.dict b/src/fuzz/fuzz-fido-id-desc.dict new file mode 100644 index 00000000..d2d2679e --- /dev/null +++ b/src/fuzz/fuzz-fido-id-desc.dict @@ -0,0 +1,6 @@ +"\xfe" +"\x00" +"\x01" +"\xf1" +"\xd0" +"\xf1\xd0\x00\x01" diff --git a/src/fuzz/fuzz-hostname-util.c b/src/fuzz/fuzz-hostname-util.c new file mode 100644 index 00000000..2130a4a8 --- /dev/null +++ b/src/fuzz/fuzz-hostname-util.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fuzz.h" +#include "hostname-util.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *ret = NULL; + + if (size == 0) + return 0; + + f = fmemopen_unlocked((char*) data, size, "re"); + assert_se(f); + + /* We don't want to fill the logs with messages about parse errors. + * Disable most logging if not running standalone */ + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + (void) read_etc_hostname_stream(f, &ret); + + return 0; +} diff --git a/src/fuzz/fuzz-journal-remote.c b/src/fuzz/fuzz-journal-remote.c new file mode 100644 index 00000000..3ab4eb07 --- /dev/null +++ b/src/fuzz/fuzz-journal-remote.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fuzz.h" + +#include + +#include "sd-journal.h" + +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "journal-remote.h" +#include "logs-show.h" +#include "memfd-util.h" +#include "strv.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_fclose_ FILE *dev_null = NULL; + RemoteServer s = {}; + char name[] = "/tmp/fuzz-journal-remote.XXXXXX.journal"; + void *mem; + int fdin; /* will be closed by journal_remote handler after EOF */ + _cleanup_close_ int fdout = -1; + sd_journal *j; + OutputMode mode; + int r; + + if (size <= 2) + return 0; + + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + assert_se((fdin = memfd_new_and_map("fuzz-journal-remote", size, &mem)) >= 0); + memcpy(mem, data, size); + assert_se(munmap(mem, size) == 0); + + fdout = mkostemps(name, STRLEN(".journal"), O_CLOEXEC); + assert_se(fdout >= 0); + + /* In */ + + assert_se(journal_remote_server_init(&s, name, JOURNAL_WRITE_SPLIT_NONE, false, false) >= 0); + + assert_se(journal_remote_add_source(&s, fdin, (char*) "fuzz-data", false) > 0); + + while (s.active) { + r = journal_remote_handle_raw_source(NULL, fdin, 0, &s); + assert_se(r >= 0); + } + + journal_remote_server_destroy(&s); + assert_se(close(fdin) < 0 && errno == EBADF); /* Check that the fd is closed already */ + + /* Out */ + + r = sd_journal_open_files(&j, (const char**) STRV_MAKE(name), 0); + assert_se(r >= 0); + + if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) + assert_se(dev_null = fopen("/dev/null", "we")); + + for (mode = 0; mode < _OUTPUT_MODE_MAX; mode++) { + if (!dev_null) + log_info("/* %s */", output_mode_to_string(mode)); + r = show_journal(dev_null ?: stdout, j, mode, 0, 0, -1, 0, NULL); + assert_se(r >= 0); + + r = sd_journal_seek_head(j); + assert_se(r >= 0); + } + + sd_journal_close(j); + unlink(name); + + return 0; +} diff --git a/src/fuzz/fuzz-journal-remote.options b/src/fuzz/fuzz-journal-remote.options new file mode 100644 index 00000000..678d526b --- /dev/null +++ b/src/fuzz/fuzz-journal-remote.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65536 diff --git a/src/fuzz/fuzz-journald-audit.c b/src/fuzz/fuzz-journald-audit.c new file mode 100644 index 00000000..3f3ce7e8 --- /dev/null +++ b/src/fuzz/fuzz-journald-audit.c @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fuzz.h" +#include "fuzz-journald.h" +#include "journald-audit.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + Server s; + + dummy_server_init(&s, data, size); + process_audit_string(&s, 0, s.buffer, size); + server_done(&s); + + return 0; +} diff --git a/src/fuzz/fuzz-journald-kmsg.c b/src/fuzz/fuzz-journald-kmsg.c new file mode 100644 index 00000000..f7426c84 --- /dev/null +++ b/src/fuzz/fuzz-journald-kmsg.c @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fuzz.h" +#include "fuzz-journald.h" +#include "journald-kmsg.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + Server s; + + if (size == 0) + return 0; + + dummy_server_init(&s, data, size); + dev_kmsg_record(&s, s.buffer, size); + server_done(&s); + + return 0; +} diff --git a/src/fuzz/fuzz-journald-native-fd.c b/src/fuzz/fuzz-journald-native-fd.c new file mode 100644 index 00000000..8e3e850f --- /dev/null +++ b/src/fuzz/fuzz-journald-native-fd.c @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fd-util.h" +#include "fs-util.h" +#include "fuzz-journald.h" +#include "fuzz.h" +#include "journald-native.h" +#include "memfd-util.h" +#include "process-util.h" +#include "tmpfile-util.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + Server s; + _cleanup_close_ int sealed_fd = -1, unsealed_fd = -1; + _cleanup_(unlink_tempfilep) char name[] = "/tmp/fuzz-journald-native-fd.XXXXXX"; + char *label = NULL; + size_t label_len = 0; + struct ucred ucred; + struct timeval *tv = NULL; + + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + dummy_server_init(&s, NULL, 0); + + sealed_fd = memfd_new(NULL); + assert_se(sealed_fd >= 0); + assert_se(write(sealed_fd, data, size) == (ssize_t) size); + assert_se(memfd_set_sealed(sealed_fd) >= 0); + assert_se(lseek(sealed_fd, 0, SEEK_SET) == 0); + ucred = (struct ucred) { + .pid = getpid_cached(), + .uid = geteuid(), + .gid = getegid(), + }; + server_process_native_file(&s, sealed_fd, &ucred, tv, label, label_len); + + unsealed_fd = mkostemp_safe(name); + assert_se(unsealed_fd >= 0); + assert_se(write(unsealed_fd, data, size) == (ssize_t) size); + assert_se(lseek(unsealed_fd, 0, SEEK_SET) == 0); + server_process_native_file(&s, unsealed_fd, &ucred, tv, label, label_len); + + server_done(&s); + + return 0; +} diff --git a/src/fuzz/fuzz-journald-native.c b/src/fuzz/fuzz-journald-native.c new file mode 100644 index 00000000..f4de5fd8 --- /dev/null +++ b/src/fuzz/fuzz-journald-native.c @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fuzz.h" +#include "fuzz-journald.h" +#include "journald-native.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + fuzz_journald_processing_function(data, size, server_process_native_message); + return 0; +} diff --git a/src/fuzz/fuzz-journald-stream.c b/src/fuzz/fuzz-journald-stream.c new file mode 100644 index 00000000..0991b287 --- /dev/null +++ b/src/fuzz/fuzz-journald-stream.c @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "fd-util.h" +#include "fuzz.h" +#include "fuzz-journald.h" +#include "journald-stream.h" + +static int stream_fds[2] = { -1, -1 }; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + Server s; + StdoutStream *stream; + int v; + + if (size == 0 || size > 65536) + return 0; + + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0, stream_fds) >= 0); + dummy_server_init(&s, NULL, 0); + assert_se(stdout_stream_install(&s, stream_fds[0], &stream) >= 0); + assert_se(write(stream_fds[1], data, size) == (ssize_t) size); + while (ioctl(stream_fds[0], SIOCINQ, &v) == 0 && v) + sd_event_run(s.event, (uint64_t) -1); + if (s.n_stdout_streams) + stdout_stream_destroy(stream); + server_done(&s); + stream_fds[1] = safe_close(stream_fds[1]); + + return 0; +} diff --git a/src/fuzz/fuzz-journald-stream.options b/src/fuzz/fuzz-journald-stream.options new file mode 100644 index 00000000..678d526b --- /dev/null +++ b/src/fuzz/fuzz-journald-stream.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65536 diff --git a/src/fuzz/fuzz-journald-syslog.c b/src/fuzz/fuzz-journald-syslog.c new file mode 100644 index 00000000..100f0ce6 --- /dev/null +++ b/src/fuzz/fuzz-journald-syslog.c @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fuzz.h" +#include "fuzz-journald.h" +#include "journald-syslog.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + fuzz_journald_processing_function(data, size, server_process_syslog_message); + return 0; +} diff --git a/src/fuzz/fuzz-journald.c b/src/fuzz/fuzz-journald.c new file mode 100644 index 00000000..950e885c --- /dev/null +++ b/src/fuzz/fuzz-journald.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "fuzz-journald.h" +#include "journald-server.h" +#include "sd-event.h" + +void dummy_server_init(Server *s, const uint8_t *buffer, size_t size) { + *s = (Server) { + .syslog_fd = -1, + .native_fd = -1, + .stdout_fd = -1, + .dev_kmsg_fd = -1, + .audit_fd = -1, + .hostname_fd = -1, + .notify_fd = -1, + .storage = STORAGE_NONE, + .line_max = 64, + }; + assert_se(sd_event_default(&s->event) >= 0); + + if (buffer) { + s->buffer = memdup_suffix0(buffer, size); + assert_se(s->buffer); + s->buffer_size = size + 1; + } +} + +void fuzz_journald_processing_function( + const uint8_t *data, + size_t size, + void (*f)(Server *s, const char *buf, size_t raw_len, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len) + ) { + Server s; + char *label = NULL; + size_t label_len = 0; + struct ucred *ucred = NULL; + struct timeval *tv = NULL; + + if (size == 0) + return; + + dummy_server_init(&s, data, size); + (*f)(&s, s.buffer, size, ucred, tv, label, label_len); + server_done(&s); +} diff --git a/src/fuzz/fuzz-journald.h b/src/fuzz/fuzz-journald.h new file mode 100644 index 00000000..77e3b0c0 --- /dev/null +++ b/src/fuzz/fuzz-journald.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "journald-server.h" + +void dummy_server_init(Server *s, const uint8_t *buffer, size_t size); + +void fuzz_journald_processing_function( + const uint8_t *data, + size_t size, + void (*f)(Server *s, const char *buf, size_t raw_len, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len) +); diff --git a/src/fuzz/fuzz-json.c b/src/fuzz/fuzz-json.c new file mode 100644 index 00000000..ce7b69db --- /dev/null +++ b/src/fuzz/fuzz-json.c @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "fileio.h" +#include "fd-util.h" +#include "fuzz.h" +#include "json.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_free_ char *out = NULL; /* out should be freed after g */ + size_t out_size; + _cleanup_fclose_ FILE *f = NULL, *g = NULL; + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + + if (size == 0) + return 0; + + f = fmemopen_unlocked((char*) data, size, "re"); + assert_se(f); + + if (json_parse_file(f, NULL, &v, NULL, NULL) < 0) + return 0; + + g = open_memstream_unlocked(&out, &out_size); + assert_se(g); + + json_variant_dump(v, 0, g, NULL); + json_variant_dump(v, JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR|JSON_FORMAT_SOURCE, g, NULL); + + return 0; +} diff --git a/src/fuzz/fuzz-lldp.c b/src/fuzz/fuzz-lldp.c new file mode 100644 index 00000000..7f252309 --- /dev/null +++ b/src/fuzz/fuzz-lldp.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-event.h" +#include "sd-lldp.h" + +#include "fd-util.h" +#include "fuzz.h" +#include "lldp-network.h" + +static int test_fd[2] = { -1, -1 }; + +int lldp_network_bind_raw_socket(int ifindex) { + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0) + return -errno; + + return test_fd[0]; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL; + + if (size > 2048) + return 0; + + assert_se(sd_event_new(&e) == 0); + assert_se(sd_lldp_new(&lldp) >= 0); + assert_se(sd_lldp_set_ifindex(lldp, 42) >= 0); + assert_se(sd_lldp_attach_event(lldp, e, 0) >= 0); + assert_se(sd_lldp_start(lldp) >= 0); + + assert_se(write(test_fd[1], data, size) == (ssize_t) size); + assert_se(sd_event_run(e, 0) >= 0); + + assert_se(sd_lldp_stop(lldp) >= 0); + assert_se(sd_lldp_detach_event(lldp) >= 0); + test_fd[1] = safe_close(test_fd[1]); + + return 0; +} diff --git a/src/fuzz/fuzz-lldp.options b/src/fuzz/fuzz-lldp.options new file mode 100644 index 00000000..60bd9b0b --- /dev/null +++ b/src/fuzz/fuzz-lldp.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 2048 diff --git a/src/fuzz/fuzz-main.c b/src/fuzz/fuzz-main.c new file mode 100644 index 00000000..d5c99849 --- /dev/null +++ b/src/fuzz/fuzz-main.c @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "log.h" +#include "fileio.h" +#include "fuzz.h" +#include "tests.h" + +/* This is a test driver for the systemd fuzzers that provides main function + * for regression testing outside of oss-fuzz (https://github.com/google/oss-fuzz) + * + * It reads files named on the command line and passes them one by one into the + * fuzzer that it is compiled into. */ + +/* This one was borrowed from + * https://github.com/google/oss-fuzz/blob/646fca1b506b056db3a60d32c4a1a7398f171c94/infra/base-images/base-runner/bad_build_check#L19 + */ +#define MIN_NUMBER_OF_RUNS 4 + +int main(int argc, char **argv) { + int i, r; + size_t size; + char *name; + + test_setup_logging(LOG_DEBUG); + + for (i = 1; i < argc; i++) { + _cleanup_free_ char *buf = NULL; + + name = argv[i]; + r = read_full_file(name, &buf, &size); + if (r < 0) { + log_error_errno(r, "Failed to open '%s': %m", name); + return EXIT_FAILURE; + } + printf("%s... ", name); + fflush(stdout); + for (int j = 0; j < MIN_NUMBER_OF_RUNS; j++) + if (LLVMFuzzerTestOneInput((uint8_t*)buf, size) == EXIT_TEST_SKIP) + return EXIT_TEST_SKIP; + printf("ok\n"); + } + + return EXIT_SUCCESS; +} diff --git a/src/fuzz/fuzz-ndisc-rs.c b/src/fuzz/fuzz-ndisc-rs.c new file mode 100644 index 00000000..d8d256d1 --- /dev/null +++ b/src/fuzz/fuzz-ndisc-rs.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "icmp6-util.h" +#include "fuzz.h" +#include "sd-ndisc.h" +#include "socket-util.h" +#include "ndisc-internal.h" + +static int test_fd[2] = { -1, -1 }; + +int icmp6_bind_router_solicitation(int index) { + assert_se(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0); + return test_fd[0]; +} + +int icmp6_bind_router_advertisement(int index) { + return -ENOSYS; +} + +int icmp6_receive(int fd, void *iov_base, size_t iov_len, + struct in6_addr *dst, triple_timestamp *timestamp) { + assert_se(read(fd, iov_base, iov_len) == (ssize_t) iov_len); + + if (timestamp) + triple_timestamp_get(timestamp); + + return 0; +} + +int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) { + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + struct ether_addr mac_addr = { + .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} + }; + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_(sd_ndisc_unrefp) sd_ndisc *nd = NULL; + + if (size > 2048) + return 0; + + assert_se(sd_event_new(&e) >= 0); + assert_se(sd_ndisc_new(&nd) >= 0); + assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0); + assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0); + assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); + assert_se(sd_ndisc_start(nd) >= 0); + assert_se(write(test_fd[1], data, size) == (ssize_t) size); + (void) sd_event_run(e, (uint64_t) -1); + assert_se(sd_ndisc_stop(nd) >= 0); + close(test_fd[1]); + + return 0; +} diff --git a/src/fuzz/fuzz-ndisc-rs.options b/src/fuzz/fuzz-ndisc-rs.options new file mode 100644 index 00000000..60bd9b0b --- /dev/null +++ b/src/fuzz/fuzz-ndisc-rs.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 2048 diff --git a/src/fuzz/fuzz-nspawn-oci.c b/src/fuzz/fuzz-nspawn-oci.c new file mode 100644 index 00000000..004230ea --- /dev/null +++ b/src/fuzz/fuzz-nspawn-oci.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fuzz.h" +#include "nspawn-oci.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_(settings_freep) Settings *s = NULL; + + if (size == 0) + return 0; + + f = fmemopen_unlocked((char*) data, size, "re"); + assert_se(f); + + /* We don't want to fill the logs with messages about parse errors. + * Disable most logging if not running standalone */ + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + (void) oci_load(f, "/dev/null", &s); + + return 0; +} diff --git a/src/fuzz/fuzz-nspawn-settings.c b/src/fuzz/fuzz-nspawn-settings.c new file mode 100644 index 00000000..aa0a8225 --- /dev/null +++ b/src/fuzz/fuzz-nspawn-settings.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fuzz.h" +#include "nspawn-settings.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_(settings_freep) Settings *s = NULL; + + if (size == 0) + return 0; + + f = fmemopen_unlocked((char*) data, size, "re"); + assert_se(f); + + /* We don't want to fill the logs with messages about parse errors. + * Disable most logging if not running standalone */ + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + (void) settings_load(f, "/dev/null", &s); + + return 0; +} diff --git a/src/fuzz/fuzz-time-util.c b/src/fuzz/fuzz-time-util.c new file mode 100644 index 00000000..22b2496f --- /dev/null +++ b/src/fuzz/fuzz-time-util.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "fd-util.h" +#include "fuzz.h" +#include "time-util.h" +#include "util.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_free_ char *str = NULL; + usec_t usec; + + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + str = memdup_suffix0(data, size); + + (void) parse_timestamp(str, &usec); + (void) parse_sec(str, &usec); + (void) parse_sec_fix_0(str, &usec); + (void) parse_sec_def_infinity(str, &usec); + (void) parse_time(str, &usec, USEC_PER_SEC); + (void) parse_nsec(str, &usec); + + (void) timezone_is_valid(str, LOG_DEBUG); + + return 0; +} diff --git a/src/fuzz/fuzz-udev-database.c b/src/fuzz/fuzz-udev-database.c new file mode 100644 index 00000000..9d7c0fa3 --- /dev/null +++ b/src/fuzz/fuzz-udev-database.c @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "device-internal.h" +#include "device-private.h" +#include "fd-util.h" +#include "fs-util.h" +#include "fuzz.h" +#include "tmpfile-util.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + _cleanup_(unlink_tempfilep) char filename[] = "/tmp/fuzz-udev-database.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + assert_se(fmkostemp_safe(filename, "r+", &f) == 0); + if (size != 0) + assert_se(fwrite(data, size, 1, f) == 1); + + fflush(f); + assert_se(device_new_aux(&dev) >= 0); + (void) device_read_db_internal_filename(dev, filename); + return 0; +} diff --git a/src/fuzz/fuzz-udev-rules.c b/src/fuzz/fuzz-udev-rules.c new file mode 100644 index 00000000..3194f7aa --- /dev/null +++ b/src/fuzz/fuzz-udev-rules.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "fd-util.h" +#include "fs-util.h" +#include "fuzz.h" +#include "log.h" +#include "mkdir.h" +#include "rm-rf.h" +#include "string-util.h" +#include "tests.h" +#include "udev-rules.h" + +static struct fakefs { + const char *target; + bool ignore_mount_error; + bool is_mounted; +} fakefss[] = { + { "/sys", false, false }, + { "/dev", false, false }, + { "/run", false, false }, + { "/etc", false, false }, + { UDEVLIBEXECDIR "/rules.d", true, false }, +}; + +static int setup_mount_namespace(void) { + static thread_local bool is_namespaced = false; + + if (is_namespaced) + return 1; + + if (unshare(CLONE_NEWNS) < 0) + return log_error_errno(errno, "Failed to call unshare(): %m"); + + if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) + return log_error_errno(errno, "Failed to mount / as private: %m"); + + is_namespaced = true; + + return 1; +} + +static int setup_fake_filesystems(const char *runtime_dir) { + for (unsigned i = 0; i < ELEMENTSOF(fakefss); i++) { + if (mount(runtime_dir, fakefss[i].target, NULL, MS_BIND, NULL) < 0) { + log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "Failed to mount %s: %m", fakefss[i].target); + if (!fakefss[i].ignore_mount_error) + return -errno; + } else + fakefss[i].is_mounted = true; + } + + return 0; +} + +static int cleanup_fake_filesystems(const char *runtime_dir) { + for (unsigned i = 0; i < ELEMENTSOF(fakefss); i++) { + if (!fakefss[i].is_mounted) + continue; + + if (umount(fakefss[i].target) < 0) { + log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "Failed to umount %s: %m", fakefss[i].target); + if (!fakefss[i].ignore_mount_error) + return -errno; + } else + fakefss[i].is_mounted = false; + } + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(udev_rules_freep) UdevRules *rules = NULL; + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + FILE *f = NULL; + + (void) setup_mount_namespace(); + + assert_se(runtime_dir = setup_fake_runtime_dir()); + + if (setup_fake_filesystems(runtime_dir) < 0) { +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + return EXIT_TEST_SKIP; +#endif + } + + if (!getenv("SYSTEMD_LOG_LEVEL")) { + log_set_max_level_realm(LOG_REALM_UDEV, LOG_CRIT); + log_set_max_level_realm(LOG_REALM_SYSTEMD, LOG_CRIT); + } + + assert_se(mkdir_p("/etc/udev/rules.d", 0755) >= 0); + f = fopen("/etc/udev/rules.d/fuzz.rules", "we"); + assert_se(f); + if (size != 0) + assert_se(fwrite(data, size, 1, f) == 1); + assert_se(fclose(f) == 0); + + assert_se(udev_rules_new(&rules, RESOLVE_NAME_EARLY) == 0); + + assert_se(cleanup_fake_filesystems(runtime_dir) >= 0); + return 0; +} diff --git a/src/fuzz/fuzz-unit-file.c b/src/fuzz/fuzz-unit-file.c new file mode 100644 index 00000000..d3993cf1 --- /dev/null +++ b/src/fuzz/fuzz-unit-file.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "conf-parser.h" +#include "fd-util.h" +#include "fileio.h" +#include "fuzz.h" +#include "install.h" +#include "load-fragment.h" +#include "string-util.h" +#include "unit.h" +#include "utf8.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_free_ char *out = NULL; /* out should be freed after g */ + size_t out_size; + _cleanup_fclose_ FILE *f = NULL, *g = NULL; + _cleanup_free_ char *p = NULL; + UnitType t; + _cleanup_(manager_freep) Manager *m = NULL; + Unit *u; + const char *name; + long offset; + + if (size == 0) + return 0; + + f = fmemopen_unlocked((char*) data, size, "re"); + assert_se(f); + + if (read_line(f, LINE_MAX, &p) < 0) + return 0; + + t = unit_type_from_string(p); + if (t < 0) + return 0; + + if (!unit_vtable[t]->load) + return 0; + + offset = ftell(f); + assert_se(offset >= 0); + + for (;;) { + _cleanup_free_ char *l = NULL; + const char *ll; + + if (read_line(f, LONG_LINE_MAX, &l) <= 0) + break; + + ll = startswith(l, UTF8_BYTE_ORDER_MARK) ?: l; + ll = ll + strspn(ll, WHITESPACE); + + if (HAS_FEATURE_MEMORY_SANITIZER && startswith(ll, "ListenNetlink")) { + /* ListenNetlink causes a false positive in msan, + * let's skip this for now. */ + log_notice("Skipping test because ListenNetlink= is present"); + return 0; + } + } + + assert_se(fseek(f, offset, SEEK_SET) == 0); + + /* We don't want to fill the logs with messages about parse errors. + * Disable most logging if not running standalone */ + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + assert_se(manager_new(UNIT_FILE_SYSTEM, MANAGER_TEST_RUN_MINIMAL, &m) >= 0); + + name = strjoina("a.", unit_type_to_string(t)); + assert_se(unit_new_for_name(m, unit_vtable[t]->object_size, name, &u) >= 0); + + (void) config_parse(name, name, f, + UNIT_VTABLE(u)->sections, + config_item_perf_lookup, load_fragment_gperf_lookup, + CONFIG_PARSE_ALLOW_INCLUDE, u); + + g = open_memstream_unlocked(&out, &out_size); + assert_se(g); + + unit_dump(u, g, ""); + manager_dump(m, g, ">>>"); + + return 0; +} diff --git a/src/fuzz/fuzz-varlink.c b/src/fuzz/fuzz-varlink.c new file mode 100644 index 00000000..31c13e2b --- /dev/null +++ b/src/fuzz/fuzz-varlink.c @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "errno-util.h" +#include "fd-util.h" +#include "fuzz.h" +#include "hexdecoct.h" +#include "io-util.h" +#include "varlink.h" +#include "log.h" + +static FILE *null = NULL; + +static int method_something(Varlink *v, JsonVariant *p, VarlinkMethodFlags flags, void *userdata) { + json_variant_dump(p, JSON_FORMAT_NEWLINE|JSON_FORMAT_PRETTY, null, NULL); + return 0; +} + +static int reply_callback(Varlink *v, JsonVariant *p, const char *error_id, VarlinkReplyFlags flags, void *userdata) { + json_variant_dump(p, JSON_FORMAT_NEWLINE|JSON_FORMAT_PRETTY, null, NULL); + return 0; +} + +static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + struct iovec *iov = userdata; + bool write_eof = false, read_eof = false; + + assert(s); + assert(fd >= 0); + assert(iov); + + if ((revents & (EPOLLOUT|EPOLLHUP|EPOLLERR)) && iov->iov_len > 0) { + ssize_t n; + + /* never write more than 143 bytes a time, to make broken up recv()s on the other side more + * likely, and thus test some additional code paths. */ + n = send(fd, iov->iov_base, MIN(iov->iov_len, 143U), MSG_NOSIGNAL|MSG_DONTWAIT); + if (n < 0) { + if (ERRNO_IS_DISCONNECT(errno)) + write_eof = true; + else + assert_se(errno == EAGAIN); + } else + IOVEC_INCREMENT(iov, 1, n); + } + + if (revents & EPOLLIN) { + char c[137]; + ssize_t n; + + n = recv(fd, c, sizeof(c), MSG_DONTWAIT); + if (n < 0) { + if (ERRNO_IS_DISCONNECT(errno)) + read_eof = true; + else + assert_se(errno == EAGAIN); + } else if (n == 0) + read_eof = true; + else + hexdump(null, c, (size_t) n); + } + + /* After we wrote everything we could turn off EPOLLOUT. And if we reached read EOF too turn off the + * whole thing. */ + if (write_eof || iov->iov_len == 0) { + + if (read_eof) + assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); + else + assert_se(sd_event_source_set_io_events(s, EPOLLIN) >= 0); + } + + return 0; +} + +static int idle_callback(sd_event_source *s, void *userdata) { + assert(s); + + /* Called as idle callback when there's nothing else to do anymore */ + sd_event_exit(sd_event_source_get_event(s), 0); + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + struct iovec server_iov = IOVEC_MAKE((void*) data, size), client_iov = IOVEC_MAKE((void*) data, size); + /* Important: the declaration order matters here! we want that the fds are closed on return after the + * event sources, hence we declare the fds first, the event sources second */ + _cleanup_close_pair_ int server_pair[2] = { -1, -1 }, client_pair[2] = { -1, -1 }; + _cleanup_(sd_event_source_unrefp) sd_event_source *idle_event_source = NULL, + *server_event_source = NULL, *client_event_source = NULL; + _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL; + _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL; + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + + log_set_max_level(LOG_CRIT); + log_parse_environment(); + + assert_se(null = fopen("/dev/null", "we")); + + assert_se(sd_event_default(&e) >= 0); + + /* Test one: write the data as method call to a server */ + assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, server_pair) >= 0); + assert_se(varlink_server_new(&s, 0) >= 0); + assert_se(varlink_server_set_description(s, "myserver") >= 0); + assert_se(varlink_server_attach_event(s, e, 0) >= 0); + assert_se(varlink_server_add_connection(s, server_pair[0], NULL) >= 0); + TAKE_FD(server_pair[0]); + assert_se(varlink_server_bind_method(s, "io.test.DoSomething", method_something) >= 0); + assert_se(sd_event_add_io(e, &server_event_source, server_pair[1], EPOLLIN|EPOLLOUT, io_callback, &server_iov) >= 0); + + /* Test two: write the data as method response to a client */ + assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, client_pair) >= 0); + assert_se(varlink_connect_fd(&c, client_pair[0]) >= 0); + TAKE_FD(client_pair[0]); + assert_se(varlink_set_description(c, "myclient") >= 0); + assert_se(varlink_attach_event(c, e, 0) >= 0); + assert_se(varlink_bind_reply(c, reply_callback) >= 0); + assert_se(varlink_invoke(c, "io.test.DoSomething", NULL) >= 0); + assert_se(sd_event_add_io(e, &client_event_source, client_pair[1], EPOLLIN|EPOLLOUT, io_callback, &client_iov) >= 0); + + assert_se(sd_event_add_defer(e, &idle_event_source, idle_callback, NULL) >= 0); + assert_se(sd_event_source_set_priority(idle_event_source, SD_EVENT_PRIORITY_IDLE) >= 0); + + assert_se(sd_event_loop(e) >= 0); + + null = safe_fclose(null); + + return 0; +} diff --git a/src/fuzz/fuzz.h b/src/fuzz/fuzz.h new file mode 100644 index 00000000..83b1ac11 --- /dev/null +++ b/src/fuzz/fuzz.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +/* The entry point into the fuzzer */ +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +/* https://docs.fuzzbuzz.io/developer-documentation/porting-targets-to-fuzzbuzz/libfuzzer-targets */ +int FuzzerEntrypoint(const uint8_t *data, size_t size); diff --git a/src/fuzz/fuzzer-entry-point.c b/src/fuzz/fuzzer-entry-point.c new file mode 100644 index 00000000..020c1116 --- /dev/null +++ b/src/fuzz/fuzzer-entry-point.c @@ -0,0 +1,5 @@ +#include "fuzz.h" + +int FuzzerEntrypoint(const uint8_t *data, size_t size) { + return LLVMFuzzerTestOneInput(data, size); +} diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build new file mode 100644 index 00000000..c88812d1 --- /dev/null +++ b/src/fuzz/meson.build @@ -0,0 +1,149 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +fuzzers += [ + [['src/fuzz/fuzz-bus-message.c'], + [libshared], + []], + + [['src/fuzz/fuzz-catalog.c'], + [libjournal_core, + libshared], + []], + + [['src/fuzz/fuzz-dns-packet.c', + dns_type_headers], + [libsystemd_resolve_core, + libshared], + [libgcrypt, + libgpg_error, + libm]], + + [['src/fuzz/fuzz-dhcp6-client.c', + 'src/libsystemd-network/dhcp-identifier.h', + 'src/libsystemd-network/dhcp-identifier.c', + 'src/libsystemd-network/dhcp6-internal.h', + 'src/systemd/sd-dhcp6-client.h'], + [libshared, + libsystemd_network], + []], + + [['src/fuzz/fuzz-dhcp-server.c'], + [libsystemd_network, + libshared], + []], + + [['src/fuzz/fuzz-lldp.c'], + [libshared, + libsystemd_network], + []], + + [['src/fuzz/fuzz-ndisc-rs.c', + 'src/libsystemd-network/dhcp-identifier.h', + 'src/libsystemd-network/dhcp-identifier.c', + 'src/libsystemd-network/icmp6-util.h', + 'src/systemd/sd-dhcp6-client.h', + 'src/systemd/sd-ndisc.h'], + [libshared, + libsystemd_network], + []], + + [['src/fuzz/fuzz-json.c'], + [libshared], + []], + + [['src/fuzz/fuzz-varlink.c'], + [libshared], + []], + + [['src/fuzz/fuzz-unit-file.c'], + [libcore, + libshared], + [libmount]], + + [['src/fuzz/fuzz-journald-audit.c', + 'src/fuzz/fuzz-journald.c'], + [libjournal_core, + libshared], + [libselinux]], + + [['src/fuzz/fuzz-journald-kmsg.c', + 'src/fuzz/fuzz-journald.c'], + [libjournal_core, + libshared], + [libselinux]], + + [['src/fuzz/fuzz-journald-native.c', + 'src/fuzz/fuzz-journald.c'], + [libjournal_core, + libshared], + [libselinux]], + + [['src/fuzz/fuzz-journald-native-fd.c', + 'src/fuzz/fuzz-journald.c'], + [libjournal_core, + libshared], + [libselinux]], + + [['src/fuzz/fuzz-journald-stream.c', + 'src/fuzz/fuzz-journald.c'], + [libjournal_core, + libshared], + [libselinux]], + + [['src/fuzz/fuzz-journald-syslog.c', + 'src/fuzz/fuzz-journald.c'], + [libjournal_core, + libshared], + [libselinux]], + + [['src/fuzz/fuzz-journal-remote.c'], + [libsystemd_journal_remote, + libshared], + []], + + [['src/fuzz/fuzz-udev-database.c'], + [libshared], + []], + + [['src/fuzz/fuzz-udev-rules.c'], + [libudev_core, + libudev_static, + libsystemd_network, + libshared], + [threads, + libacl]], + + [['src/fuzz/fuzz-compress.c'], + [libshared], + []], + + [['src/fuzz/fuzz-bus-label.c'], + [libshared], + []], + + [['src/fuzz/fuzz-env-file.c'], + [libshared], + []], + + [['src/fuzz/fuzz-hostname-util.c'], + [libshared], + []], + + [['src/fuzz/fuzz-nspawn-settings.c'], + [libshared, + libnspawn_core], + [libseccomp]], + + [['src/fuzz/fuzz-nspawn-oci.c'], + [libshared, + libnspawn_core], + [libseccomp]], + + [['src/fuzz/fuzz-calendarspec.c'], + [libshared], + []], + + [['src/fuzz/fuzz-time-util.c'], + [libshared], + []], +] diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c new file mode 100644 index 00000000..be386120 --- /dev/null +++ b/src/getty-generator/getty-generator.c @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "generator.h" +#include "log.h" +#include "mkdir.h" +#include "path-util.h" +#include "process-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "unit-name.h" +#include "util.h" +#include "virt.h" + +static const char *arg_dest = NULL; + +static int add_symlink(const char *fservice, const char *tservice) { + char *from, *to; + int r; + + assert(fservice); + assert(tservice); + + from = strjoina(SYSTEM_DATA_UNIT_PATH "/", fservice); + to = strjoina(arg_dest, "/getty.target.wants/", tservice); + + mkdir_parents_label(to, 0755); + + r = symlink(from, to); + if (r < 0) { + /* In case console=hvc0 is passed this will very likely result in EEXIST */ + if (errno == EEXIST) + return 0; + + return log_error_errno(errno, "Failed to create symlink %s: %m", to); + } + + return 0; +} + +static int add_serial_getty(const char *tty) { + _cleanup_free_ char *n = NULL; + int r; + + assert(tty); + + log_debug("Automatically adding serial getty for /dev/%s.", tty); + + r = unit_name_from_path_instance("serial-getty", tty, ".service", &n); + if (r < 0) + return log_error_errno(r, "Failed to generate service name: %m"); + + return add_symlink("serial-getty@.service", n); +} + +static int add_container_getty(const char *tty) { + _cleanup_free_ char *n = NULL; + int r; + + assert(tty); + + log_debug("Automatically adding container getty for /dev/pts/%s.", tty); + + r = unit_name_from_path_instance("container-getty", tty, ".service", &n); + if (r < 0) + return log_error_errno(r, "Failed to generate service name: %m"); + + return add_symlink("container-getty@.service", n); +} + +static int verify_tty(const char *name) { + _cleanup_close_ int fd = -1; + const char *p; + + /* Some TTYs are weird and have been enumerated but don't work + * when you try to use them, such as classic ttyS0 and + * friends. Let's check that and open the device and run + * isatty() on it. */ + + p = strjoina("/dev/", name); + + /* O_NONBLOCK is essential here, to make sure we don't wait + * for DCD */ + fd = open(p, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC|O_NOFOLLOW); + if (fd < 0) + return -errno; + + errno = 0; + if (isatty(fd) <= 0) + return errno_or_else(EIO); + + return 0; +} + +static int run(const char *dest, const char *dest_early, const char *dest_late) { + _cleanup_free_ char *active = NULL; + const char *j; + int r; + + assert_se(arg_dest = dest); + + if (detect_container() > 0) { + _cleanup_free_ char *container_ttys = NULL; + + log_debug("Automatically adding console shell."); + + r = add_symlink("console-getty.service", "console-getty.service"); + if (r < 0) + return r; + + /* When $container_ttys is set for PID 1, spawn + * gettys on all ptys named therein. Note that despite + * the variable name we only support ptys here. */ + + r = getenv_for_pid(1, "container_ttys", &container_ttys); + if (r > 0) { + const char *word, *state; + size_t l; + + FOREACH_WORD(word, l, container_ttys, state) { + const char *t; + char tty[l + 1]; + + memcpy(tty, word, l); + tty[l] = 0; + + /* First strip off /dev/ if it is specified */ + t = path_startswith(tty, "/dev/"); + if (!t) + t = tty; + + /* Then, make sure it's actually a pty */ + t = path_startswith(t, "pts/"); + if (!t) + continue; + + r = add_container_getty(t); + if (r < 0) + return r; + } + } + + /* Don't add any further magic if we are in a container */ + return 0; + } + + if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) { + const char *word, *state; + size_t l; + + /* Automatically add in a serial getty on all active + * kernel consoles */ + FOREACH_WORD(word, l, active, state) { + _cleanup_free_ char *tty = NULL; + + tty = strndup(word, l); + if (!tty) + return log_oom(); + + /* We assume that gettys on virtual terminals are + * started via manual configuration and do this magic + * only for non-VC terminals. */ + + if (isempty(tty) || tty_is_vc(tty)) + continue; + + if (verify_tty(tty) < 0) + continue; + + r = add_serial_getty(tty); + if (r < 0) + return r; + } + } + + /* Automatically add in a serial getty on the first + * virtualizer console */ + FOREACH_STRING(j, + "hvc0", + "xvc0", + "hvsi0", + "sclp_line0", + "ttysclp0", + "3270!tty1") { + _cleanup_free_ char *p = NULL; + + p = path_join("/sys/class/tty", j); + if (!p) + return -ENOMEM; + if (access(p, F_OK) < 0) + continue; + + r = add_serial_getty(j); + if (r < 0) + return r; + } + + return 0; +} + +DEFINE_MAIN_GENERATOR_FUNCTION(run); diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c new file mode 100644 index 00000000..bd2453db --- /dev/null +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -0,0 +1,832 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-device.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "blkid-util.h" +#include "blockdev-util.h" +#include "btrfs-util.h" +#include "device-util.h" +#include "dirent-util.h" +#include "dissect-image.h" +#include "efi-loader.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "fstab-util.h" +#include "generator.h" +#include "gpt.h" +#include "mkdir.h" +#include "mountpoint-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "special.h" +#include "specifier.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "util.h" +#include "virt.h" + +static const char *arg_dest = NULL; +static bool arg_enabled = true; +static bool arg_root_enabled = true; +static int arg_root_rw = -1; + +static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) { + _cleanup_free_ char *e = NULL, *n = NULL, *d = NULL, *id_escaped = NULL, *what_escaped = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *p; + int r; + + assert(id); + assert(what); + + r = unit_name_from_path(what, ".device", &d); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + e = unit_name_escape(id); + if (!e) + return log_oom(); + + r = unit_name_build("systemd-cryptsetup", e, ".service", &n); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + id_escaped = specifier_escape(id); + if (!id_escaped) + return log_oom(); + + what_escaped = specifier_escape(what); + if (!what_escaped) + return log_oom(); + + p = prefix_roota(arg_dest, n); + f = fopen(p, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", p); + + fprintf(f, + "# Automatically generated by systemd-gpt-auto-generator\n\n" + "[Unit]\n" + "Description=Cryptography Setup for %%I\n" + "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n" + "DefaultDependencies=no\n" + "Conflicts=umount.target\n" + "BindsTo=dev-mapper-%%i.device %s\n" + "Before=umount.target cryptsetup.target\n" + "After=%s\n" + "IgnoreOnIsolate=true\n" + "[Service]\n" + "Type=oneshot\n" + "RemainAfterExit=yes\n" + "TimeoutSec=0\n" /* the binary handles timeouts anyway */ + "KeyringMode=shared\n" /* make sure we can share cached keys among instances */ + "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n" + "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n", + d, d, + id_escaped, what_escaped, rw ? "" : "read-only", + id_escaped); + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write file %s: %m", p); + + r = generator_add_symlink(arg_dest, d, "wants", n); + if (r < 0) + return r; + + if (require) { + const char *dmname; + + r = generator_add_symlink(arg_dest, "cryptsetup.target", "requires", n); + if (r < 0) + return r; + + dmname = strjoina("dev-mapper-", e, ".device"); + r = generator_add_symlink(arg_dest, dmname, "requires", n); + if (r < 0) + return r; + } + + p = strjoina(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf"); + mkdir_parents_label(p, 0755); + r = write_string_file(p, + "# Automatically generated by systemd-gpt-auto-generator\n\n" + "[Unit]\n" + "JobTimeoutSec=0\n", + WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */ + if (r < 0) + return log_error_errno(r, "Failed to write device drop-in: %m"); + + if (device) { + char *ret; + + ret = path_join("/dev/mapper", id); + if (!ret) + return log_oom(); + + *device = ret; + } + + return 0; +} + +static int add_mount( + const char *id, + const char *what, + const char *where, + const char *fstype, + bool rw, + const char *options, + const char *description, + const char *post) { + + _cleanup_free_ char *unit = NULL, *crypto_what = NULL, *p = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + /* Note that we don't apply specifier escaping on the input strings here, since we know they are not configured + * externally, but all originate from our own sources here, and hence we know they contain no % characters that + * could potentially be understood as specifiers. */ + + assert(id); + assert(what); + assert(where); + assert(description); + + log_debug("Adding %s: %s %s", where, what, strna(fstype)); + + if (streq_ptr(fstype, "crypto_LUKS")) { + + r = add_cryptsetup(id, what, rw, true, &crypto_what); + if (r < 0) + return r; + + what = crypto_what; + fstype = NULL; + } + + r = unit_name_from_path(where, ".mount", &unit); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + p = path_join(empty_to_root(arg_dest), unit); + if (!p) + return log_oom(); + + f = fopen(p, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", unit); + + fprintf(f, + "# Automatically generated by systemd-gpt-auto-generator\n\n" + "[Unit]\n" + "Description=%s\n" + "Documentation=man:systemd-gpt-auto-generator(8)\n", + description); + + if (post) + fprintf(f, "Before=%s\n", post); + + r = generator_write_fsck_deps(f, arg_dest, what, where, fstype); + if (r < 0) + return r; + + fprintf(f, + "\n" + "[Mount]\n" + "What=%s\n" + "Where=%s\n", + what, where); + + if (fstype) + fprintf(f, "Type=%s\n", fstype); + + if (options) + fprintf(f, "Options=%s,%s\n", options, rw ? "rw" : "ro"); + else + fprintf(f, "Options=%s\n", rw ? "rw" : "ro"); + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", p); + + if (post) + return generator_add_symlink(arg_dest, post, "requires", unit); + return 0; +} + +static int path_is_busy(const char *where) { + int r; + + /* already a mountpoint; generators run during reload */ + r = path_is_mount_point(where, NULL, AT_SYMLINK_FOLLOW); + if (r > 0) + return false; + + /* the directory might not exist on a stateless system */ + if (r == -ENOENT) + return false; + + if (r < 0) + return log_warning_errno(r, "Cannot check if \"%s\" is a mount point: %m", where); + + /* not a mountpoint but it contains files */ + r = dir_is_empty(where); + if (r < 0) + return log_warning_errno(r, "Cannot check if \"%s\" is empty: %m", where); + if (r > 0) + return false; + + log_debug("\"%s\" already populated, ignoring.", where); + return true; +} + +static int add_partition_mount( + DissectedPartition *p, + const char *id, + const char *where, + const char *description) { + + int r; + assert(p); + + r = path_is_busy(where); + if (r != 0) + return r < 0 ? r : 0; + + return add_mount( + id, + p->node, + where, + p->fstype, + p->rw, + NULL, + description, + SPECIAL_LOCAL_FS_TARGET); +} + +static int add_swap(const char *path) { + _cleanup_free_ char *name = NULL, *unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(path); + + /* Disable the swap auto logic if at least one swap is defined in /etc/fstab, see #6192. */ + r = fstab_has_fstype("swap"); + if (r < 0) + return log_error_errno(r, "Failed to parse fstab: %m"); + if (r > 0) { + log_debug("swap specified in fstab, ignoring."); + return 0; + } + + log_debug("Adding swap: %s", path); + + r = unit_name_from_path(path, ".swap", &name); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + unit = path_join(empty_to_root(arg_dest), name); + if (!unit) + return log_oom(); + + f = fopen(unit, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", unit); + + fprintf(f, + "# Automatically generated by systemd-gpt-auto-generator\n\n" + "[Unit]\n" + "Description=Swap Partition\n" + "Documentation=man:systemd-gpt-auto-generator(8)\n\n" + "[Swap]\n" + "What=%s\n", + path); + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", unit); + + return generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET, "wants", name); +} + +static int add_automount( + const char *id, + const char *what, + const char *where, + const char *fstype, + bool rw, + const char *options, + const char *description, + usec_t timeout) { + + _cleanup_free_ char *unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *opt = "noauto", *p; + int r; + + assert(id); + assert(where); + assert(description); + + if (options) + opt = strjoina(options, ",", opt); + + r = add_mount(id, + what, + where, + fstype, + rw, + opt, + description, + NULL); + if (r < 0) + return r; + + r = unit_name_from_path(where, ".automount", &unit); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + p = prefix_roota(arg_dest, unit); + f = fopen(p, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", unit); + + fprintf(f, + "# Automatically generated by systemd-gpt-auto-generator\n\n" + "[Unit]\n" + "Description=%s\n" + "Documentation=man:systemd-gpt-auto-generator(8)\n" + "[Automount]\n" + "Where=%s\n" + "TimeoutIdleSec="USEC_FMT"\n", + description, + where, + timeout / USEC_PER_SEC); + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", p); + + return generator_add_symlink(arg_dest, SPECIAL_LOCAL_FS_TARGET, "wants", unit); +} + +static const char *esp_or_xbootldr_options(const DissectedPartition *p) { + assert(p); + + /* if we probed vfat or have no idea about the file system then assume these file systems are vfat + * and thus understand "umask=0077". If we detected something else then don't specify any options and + * use kernel defaults. */ + + if (!p->fstype || streq(p->fstype, "vfat")) + return "umask=0077"; + + return NULL; +} + +static int add_xbootldr(DissectedPartition *p) { + int r; + + assert(p); + + if (in_initrd()) { + log_debug("In initrd, ignoring the XBOOTLDR partition."); + return 0; + } + + r = fstab_is_mount_point("/boot"); + if (r < 0) + return log_error_errno(r, "Failed to parse fstab: %m"); + if (r > 0) { + log_debug("/boot specified in fstab, ignoring XBOOTLDR partition."); + return 0; + } + + r = path_is_busy("/boot"); + if (r < 0) + return r; + if (r > 0) + return 0; + + return add_automount("boot", + p->node, + "/boot", + p->fstype, + true, + esp_or_xbootldr_options(p), + "Boot Loader Partition", + 120 * USEC_PER_SEC); +} + +#if ENABLE_EFI +static int add_esp(DissectedPartition *p, bool has_xbootldr) { + const char *esp_path = NULL, *id = NULL; + int r; + + assert(p); + + if (in_initrd()) { + log_debug("In initrd, ignoring the ESP."); + return 0; + } + + /* If /efi exists we'll use that. Otherwise we'll use /boot, as that's usually the better choice, but + * only if there's no explicit XBOOTLDR partition around. */ + if (access("/efi", F_OK) < 0) { + if (errno != ENOENT) + return log_error_errno(errno, "Failed to determine whether /efi exists: %m"); + + /* Use /boot as fallback, but only if there's no XBOOTLDR partition */ + if (!has_xbootldr) { + esp_path = "/boot"; + id = "boot"; + } + } + if (!esp_path) + esp_path = "/efi"; + if (!id) + id = "efi"; + + /* We create an .automount which is not overridden by the .mount from the fstab generator. */ + r = fstab_is_mount_point(esp_path); + if (r < 0) + return log_error_errno(r, "Failed to parse fstab: %m"); + if (r > 0) { + log_debug("%s specified in fstab, ignoring.", esp_path); + return 0; + } + + r = path_is_busy(esp_path); + if (r < 0) + return r; + if (r > 0) + return 0; + + if (is_efi_boot()) { + sd_id128_t loader_uuid; + + /* If this is an EFI boot, be extra careful, and only mount the ESP if it was the ESP used for booting. */ + + r = efi_loader_get_device_part_uuid(&loader_uuid); + if (r == -ENOENT) { + log_debug("EFI loader partition unknown."); + return 0; + } + if (r < 0) + return log_error_errno(r, "Failed to read ESP partition UUID: %m"); + + if (!sd_id128_equal(p->uuid, loader_uuid)) { + log_debug("Partition for %s does not appear to be the partition we are booted from.", p->node); + return 0; + } + } else + log_debug("Not an EFI boot, skipping ESP check."); + + return add_automount(id, + p->node, + esp_path, + p->fstype, + true, + esp_or_xbootldr_options(p), + "EFI System Partition Automount", + 120 * USEC_PER_SEC); +} +#else +static int add_esp(DissectedPartition *p, bool has_xbootldr) { + return 0; +} +#endif + +static int add_root_rw(DissectedPartition *p) { + const char *path; + int r; + + assert(p); + + if (in_initrd()) { + log_debug("In initrd, not generating drop-in for systemd-remount-fs.service."); + return 0; + } + + if (arg_root_rw >= 0) { + log_debug("Parameter ro/rw specified on kernel command line, not generating drop-in for systemd-remount-fs.service."); + return 0; + } + + if (!p->rw) { + log_debug("Root partition marked read-only in GPT partition table, not generating drop-in for systemd-remount-fs.service."); + return 0; + } + + (void) generator_enable_remount_fs_service(arg_dest); + + path = strjoina(arg_dest, "/systemd-remount-fs.service.d/50-remount-rw.conf"); + + r = write_string_file(path, + "# Automatically generated by systemd-gpt-generator\n\n" + "[Service]\n" + "Environment=SYSTEMD_REMOUNT_ROOT_RW=1\n", + WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_NOFOLLOW|WRITE_STRING_FILE_MKDIR_0755); + if (r < 0) + return log_error_errno(r, "Failed to write drop-in file %s: %m", path); + + return 0; +} + +static int open_parent_devno(dev_t devnum, int *ret) { + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + const char *name, *devtype, *node; + sd_device *parent; + dev_t pn; + int fd, r; + + assert(ret); + + r = sd_device_new_from_devnum(&d, 'b', devnum); + if (r < 0) + return log_debug_errno(r, "Failed to open device: %m"); + + if (sd_device_get_devname(d, &name) < 0) { + r = sd_device_get_syspath(d, &name); + if (r < 0) { + log_device_debug_errno(d, r, "Device %u:%u does not have a name, ignoring: %m", major(devnum), minor(devnum)); + return 0; + } + } + + r = sd_device_get_parent(d, &parent); + if (r < 0) { + log_device_debug_errno(d, r, "Not a partitioned device, ignoring: %m"); + return 0; + } + + /* Does it have a devtype? */ + r = sd_device_get_devtype(parent, &devtype); + if (r < 0) { + log_device_debug_errno(parent, r, "Parent doesn't have a device type, ignoring: %m"); + return 0; + } + + /* Is this a disk or a partition? We only care for disks... */ + if (!streq(devtype, "disk")) { + log_device_debug(parent, "Parent isn't a raw disk, ignoring."); + return 0; + } + + /* Does it have a device node? */ + r = sd_device_get_devname(parent, &node); + if (r < 0) { + log_device_debug_errno(parent, r, "Parent device does not have device node, ignoring: %m"); + return 0; + } + + log_device_debug(d, "Root device %s.", node); + + r = sd_device_get_devnum(parent, &pn); + if (r < 0) { + log_device_debug_errno(parent, r, "Parent device is not a proper block device, ignoring: %m"); + return 0; + } + + fd = open(node, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return log_error_errno(errno, "Failed to open %s: %m", node); + + *ret = fd; + return 1; +} + +static int enumerate_partitions(dev_t devnum) { + _cleanup_close_ int fd = -1; + _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; + int r, k; + + r = open_parent_devno(devnum, &fd); + if (r <= 0) + return r; + + r = dissect_image(fd, NULL, 0, DISSECT_IMAGE_GPT_ONLY|DISSECT_IMAGE_NO_UDEV, &m); + if (r == -ENOPKG) { + log_debug_errno(r, "No suitable partition table found, ignoring."); + return 0; + } + if (r < 0) + return log_error_errno(r, "Failed to dissect: %m"); + + if (m->partitions[PARTITION_SWAP].found) { + k = add_swap(m->partitions[PARTITION_SWAP].node); + if (k < 0) + r = k; + } + + if (m->partitions[PARTITION_XBOOTLDR].found) { + k = add_xbootldr(m->partitions + PARTITION_XBOOTLDR); + if (k < 0) + r = k; + } + + if (m->partitions[PARTITION_ESP].found) { + k = add_esp(m->partitions + PARTITION_ESP, m->partitions[PARTITION_XBOOTLDR].found); + if (k < 0) + r = k; + } + + if (m->partitions[PARTITION_HOME].found) { + k = add_partition_mount(m->partitions + PARTITION_HOME, "home", "/home", "Home Partition"); + if (k < 0) + r = k; + } + + if (m->partitions[PARTITION_SRV].found) { + k = add_partition_mount(m->partitions + PARTITION_SRV, "srv", "/srv", "Server Data Partition"); + if (k < 0) + r = k; + } + + if (m->partitions[PARTITION_ROOT].found) { + k = add_root_rw(m->partitions + PARTITION_ROOT); + if (k < 0) + r = k; + } + + return r; +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + int r; + + assert(key); + + if (proc_cmdline_key_streq(key, "systemd.gpt_auto") || + proc_cmdline_key_streq(key, "rd.systemd.gpt_auto")) { + + r = value ? parse_boolean(value) : 1; + if (r < 0) + log_warning_errno(r, "Failed to parse gpt-auto switch \"%s\", ignoring: %m", value); + else + arg_enabled = r; + + } else if (proc_cmdline_key_streq(key, "root")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + /* Disable root disk logic if there's a root= value + * specified (unless it happens to be "gpt-auto") */ + + arg_root_enabled = streq(value, "gpt-auto"); + + } else if (proc_cmdline_key_streq(key, "roothash")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + /* Disable root disk logic if there's roothash= defined (i.e. verity enabled) */ + + arg_root_enabled = false; + + } else if (proc_cmdline_key_streq(key, "rw") && !value) + arg_root_rw = true; + else if (proc_cmdline_key_streq(key, "ro") && !value) + arg_root_rw = false; + + return 0; +} + +#if ENABLE_EFI +static int add_root_cryptsetup(void) { + + /* If a device /dev/gpt-auto-root-luks appears, then make it pull in systemd-cryptsetup-root.service, which + * sets it up, and causes /dev/gpt-auto-root to appear which is all we are looking for. */ + + return add_cryptsetup("root", "/dev/gpt-auto-root-luks", true, false, NULL); +} +#endif + +static int add_root_mount(void) { + +#if ENABLE_EFI + int r; + + if (!is_efi_boot()) { + log_debug("Not a EFI boot, not creating root mount."); + return 0; + } + + r = efi_loader_get_device_part_uuid(NULL); + if (r == -ENOENT) { + log_debug("EFI loader partition unknown, exiting."); + return 0; + } else if (r < 0) + return log_error_errno(r, "Failed to read ESP partition UUID: %m"); + + /* OK, we have an ESP partition, this is fantastic, so let's + * wait for a root device to show up. A udev rule will create + * the link for us under the right name. */ + + if (in_initrd()) { + r = generator_write_initrd_root_device_deps(arg_dest, "/dev/gpt-auto-root"); + if (r < 0) + return 0; + + r = add_root_cryptsetup(); + if (r < 0) + return r; + } + + /* Note that we do not need to enable systemd-remount-fs.service here. If + * /etc/fstab exists, systemd-fstab-generator will pull it in for us. */ + + return add_mount( + "root", + "/dev/gpt-auto-root", + in_initrd() ? "/sysroot" : "/", + NULL, + arg_root_rw > 0, + NULL, + "Root Partition", + in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET); +#else + return 0; +#endif +} + +static int add_mounts(void) { + dev_t devno; + int r; + + r = get_block_device_harder("/", &devno); + if (r < 0) + return log_error_errno(r, "Failed to determine block device of root file system: %m"); + if (r == 0) { + r = get_block_device_harder("/usr", &devno); + if (r < 0) + return log_error_errno(r, "Failed to determine block device of /usr file system: %m"); + if (r == 0) { + _cleanup_free_ char *p = NULL; + mode_t m; + + /* If the root mount has been replaced by some form of volatile file system (overlayfs), the + * original root block device node is symlinked in /run/systemd/volatile-root. Let's read that + * here. */ + r = readlink_malloc("/run/systemd/volatile-root", &p); + if (r == -ENOENT) { + log_debug("Neither root nor /usr file system are on a (single) block device."); + return 0; + } + if (r < 0) + return log_error_errno(r, "Failed to read symlink /run/systemd/volatile-root: %m"); + + r = device_path_parse_major_minor(p, &m, &devno); + if (r < 0) + return log_error_errno(r, "Failed to parse major/minor device node: %m"); + if (!S_ISBLK(m)) + return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Volatile root device is of wrong type."); + } + } + + return enumerate_partitions(devno); +} + +static int run(const char *dest, const char *dest_early, const char *dest_late) { + int r, k; + + assert_se(arg_dest = dest_late); + + if (detect_container() > 0) { + log_debug("In a container, exiting."); + return 0; + } + + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + if (!arg_enabled) { + log_debug("Disabled, exiting."); + return 0; + } + + if (arg_root_enabled) + r = add_root_mount(); + + if (!in_initrd()) { + k = add_mounts(); + if (r >= 0) + r = k; + } + + return r; +} + +DEFINE_MAIN_GENERATOR_FUNCTION(run); diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c new file mode 100644 index 00000000..5e40933f --- /dev/null +++ b/src/hibernate-resume/hibernate-resume-generator.c @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "dropin.h" +#include "fstab-util.h" +#include "generator.h" +#include "log.h" +#include "main-func.h" +#include "mkdir.h" +#include "proc-cmdline.h" +#include "special.h" +#include "string-util.h" +#include "unit-name.h" + +static const char *arg_dest = "/tmp"; +static char *arg_resume_device = NULL; +static char *arg_resume_options = NULL; +static char *arg_root_options = NULL; +static bool arg_noresume = false; + +STATIC_DESTRUCTOR_REGISTER(arg_resume_device, freep); +STATIC_DESTRUCTOR_REGISTER(arg_resume_options, freep); +STATIC_DESTRUCTOR_REGISTER(arg_root_options, freep); + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + + if (streq(key, "resume")) { + char *s; + + if (proc_cmdline_value_missing(key, value)) + return 0; + + s = fstab_node_to_udev_node(value); + if (!s) + return log_oom(); + + free_and_replace(arg_resume_device, s); + + } else if (streq(key, "resumeflags")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (!strextend_with_separator(&arg_resume_options, ",", value, NULL)) + return log_oom(); + + } else if (streq(key, "rootflags")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (!strextend_with_separator(&arg_root_options, ",", value, NULL)) + return log_oom(); + + } else if (streq(key, "noresume")) { + if (value) { + log_warning("\"noresume\" kernel command line switch specified with an argument, ignoring."); + return 0; + } + + arg_noresume = true; + } + + return 0; +} + +static int process_resume(void) { + _cleanup_free_ char *service_unit = NULL, *device_unit = NULL, *lnk = NULL; + int r; + + if (!arg_resume_device) + return 0; + + r = unit_name_from_path_instance("systemd-hibernate-resume", arg_resume_device, ".service", + &service_unit); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + lnk = strjoin(arg_dest, "/" SPECIAL_SYSINIT_TARGET ".wants/", service_unit); + if (!lnk) + return log_oom(); + + mkdir_parents_label(lnk, 0755); + if (symlink(SYSTEM_DATA_UNIT_PATH "/systemd-hibernate-resume@.service", lnk) < 0) + return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); + + r = unit_name_from_path(arg_resume_device, ".device", &device_unit); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + r = write_drop_in(arg_dest, device_unit, 40, "device-timeout", + "# Automatically generated by systemd-cryptsetup-generator\n\n" + "[Unit]\nJobTimeoutSec=0"); + if (r < 0) + log_warning_errno(r, "Failed to write device timeout drop-in: %m"); + + r = generator_write_timeouts(arg_dest, + arg_resume_device, + arg_resume_device, + arg_resume_options ?: arg_root_options, + NULL); + if (r < 0) + return r; + + return 0; +} + +static int run(int argc, char *argv[]) { + int r = 0; + + log_setup_generator(); + + if (argc > 1 && argc != 4) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program takes three or no arguments."); + + if (argc > 1) + arg_dest = argv[1]; + + /* Don't even consider resuming outside of initramfs. */ + if (!in_initrd()) { + log_debug("Not running in an initrd, quitting."); + return 0; + } + + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + if (arg_noresume) { + log_notice("Found \"noresume\" on the kernel command line, quitting."); + return 0; + } + + return process_resume(); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/hibernate-resume/hibernate-resume.c b/src/hibernate-resume/hibernate-resume.c new file mode 100644 index 00000000..17e7cd1a --- /dev/null +++ b/src/hibernate-resume/hibernate-resume.c @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fileio.h" +#include "log.h" +#include "util.h" + +int main(int argc, char *argv[]) { + struct stat st; + const char *device; + _cleanup_free_ char *major_minor = NULL; + int r; + + if (argc != 2) { + log_error("This program expects one argument."); + return EXIT_FAILURE; + } + + log_setup_service(); + + umask(0022); + + /* Refuse to run unless we are in an initrd() */ + if (!in_initrd()) + return EXIT_SUCCESS; + + device = argv[1]; + + if (stat(device, &st) < 0) { + log_error_errno(errno, "Failed to stat '%s': %m", device); + return EXIT_FAILURE; + } + + if (!S_ISBLK(st.st_mode)) { + log_error("Resume device '%s' is not a block device.", device); + return EXIT_FAILURE; + } + + if (asprintf(&major_minor, "%d:%d", major(st.st_rdev), minor(st.st_rdev)) < 0) { + log_oom(); + return EXIT_FAILURE; + } + + r = write_string_file("/sys/power/resume", major_minor, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) { + log_error_errno(r, "Failed to write '%s' to /sys/power/resume: %m", major_minor); + return EXIT_FAILURE; + } + + /* + * The write above shall not return. + * + * However, failed resume is a normal condition (may mean that there is + * no hibernation image). + */ + + log_info("Could not resume from '%s' (%s).", device, major_minor); + return EXIT_SUCCESS; +} diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c new file mode 100644 index 00000000..5596846e --- /dev/null +++ b/src/hostname/hostnamectl.c @@ -0,0 +1,454 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "architecture.h" +#include "bus-error.h" +#include "bus-util.h" +#include "hostname-util.h" +#include "main-func.h" +#include "pretty-print.h" +#include "spawn-polkit-agent.h" +#include "terminal-util.h" +#include "util.h" +#include "verbs.h" + +static bool arg_ask_password = true; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static char *arg_host = NULL; +static bool arg_transient = false; +static bool arg_pretty = false; +static bool arg_static = false; + +typedef struct StatusInfo { + const char *hostname; + const char *static_hostname; + const char *pretty_hostname; + const char *icon_name; + const char *chassis; + const char *deployment; + const char *location; + const char *kernel_name; + const char *kernel_release; + const char *os_pretty_name; + const char *os_cpe_name; + const char *virtualization; + const char *architecture; + const char *home_url; +} StatusInfo; + +static void print_status_info(StatusInfo *i) { + sd_id128_t mid = {}, bid = {}; + int r; + + assert(i); + + printf(" Static hostname: %s\n", strna(i->static_hostname)); + + if (!isempty(i->pretty_hostname) && + !streq_ptr(i->pretty_hostname, i->static_hostname)) + printf(" Pretty hostname: %s\n", i->pretty_hostname); + + if (!isempty(i->hostname) && + !streq_ptr(i->hostname, i->static_hostname)) + printf("Transient hostname: %s\n", i->hostname); + + if (!isempty(i->icon_name)) + printf(" Icon name: %s\n", + strna(i->icon_name)); + + if (!isempty(i->chassis)) + printf(" Chassis: %s\n", + strna(i->chassis)); + + if (!isempty(i->deployment)) + printf(" Deployment: %s\n", i->deployment); + + if (!isempty(i->location)) + printf(" Location: %s\n", i->location); + + r = sd_id128_get_machine(&mid); + if (r >= 0) + printf(" Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(mid)); + + r = sd_id128_get_boot(&bid); + if (r >= 0) + printf(" Boot ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(bid)); + + if (!isempty(i->virtualization)) + printf(" Virtualization: %s\n", i->virtualization); + + if (!isempty(i->os_pretty_name)) { + _cleanup_free_ char *formatted = NULL; + const char *t = i->os_pretty_name; + + if (i->home_url) { + if (terminal_urlify(i->home_url, i->os_pretty_name, &formatted) >= 0) + t = formatted; + } + + printf(" Operating System: %s\n", t); + } + + if (!isempty(i->os_cpe_name)) + printf(" CPE OS Name: %s\n", i->os_cpe_name); + + if (!isempty(i->kernel_name) && !isempty(i->kernel_release)) + printf(" Kernel: %s %s\n", i->kernel_name, i->kernel_release); + + if (!isempty(i->architecture)) + printf(" Architecture: %s\n", i->architecture); + +} + +static int show_one_name(sd_bus *bus, const char* attr) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *s; + int r; + + r = sd_bus_get_property( + bus, + "org.freedesktop.hostname1", + "/org/freedesktop/hostname1", + "org.freedesktop.hostname1", + attr, + &error, &reply, "s"); + if (r < 0) + return log_error_errno(r, "Could not get property: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "s", &s); + if (r < 0) + return bus_log_parse_error(r); + + printf("%s\n", s); + + return 0; +} + +static int show_all_names(sd_bus *bus, sd_bus_error *error) { + StatusInfo info = {}; + + static const struct bus_properties_map hostname_map[] = { + { "Hostname", "s", NULL, offsetof(StatusInfo, hostname) }, + { "StaticHostname", "s", NULL, offsetof(StatusInfo, static_hostname) }, + { "PrettyHostname", "s", NULL, offsetof(StatusInfo, pretty_hostname) }, + { "IconName", "s", NULL, offsetof(StatusInfo, icon_name) }, + { "Chassis", "s", NULL, offsetof(StatusInfo, chassis) }, + { "Deployment", "s", NULL, offsetof(StatusInfo, deployment) }, + { "Location", "s", NULL, offsetof(StatusInfo, location) }, + { "KernelName", "s", NULL, offsetof(StatusInfo, kernel_name) }, + { "KernelRelease", "s", NULL, offsetof(StatusInfo, kernel_release) }, + { "OperatingSystemPrettyName", "s", NULL, offsetof(StatusInfo, os_pretty_name) }, + { "OperatingSystemCPEName", "s", NULL, offsetof(StatusInfo, os_cpe_name) }, + { "HomeURL", "s", NULL, offsetof(StatusInfo, home_url) }, + {} + }; + + static const struct bus_properties_map manager_map[] = { + { "Virtualization", "s", NULL, offsetof(StatusInfo, virtualization) }, + { "Architecture", "s", NULL, offsetof(StatusInfo, architecture) }, + {} + }; + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *host_message = NULL, *manager_message = NULL; + int r; + + r = bus_map_all_properties(bus, + "org.freedesktop.hostname1", + "/org/freedesktop/hostname1", + hostname_map, + 0, + error, + &host_message, + &info); + if (r < 0) + return r; + + r = bus_map_all_properties(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + manager_map, + 0, + error, + &manager_message, + &info); + + print_status_info(&info); + + return r; +} + +static int show_status(int argc, char **argv, void *userdata) { + sd_bus *bus = userdata; + int r; + + if (arg_pretty || arg_static || arg_transient) { + const char *attr; + + if (!!arg_static + !!arg_pretty + !!arg_transient > 1) { + log_error("Cannot query more than one name type at a time"); + return -EINVAL; + } + + attr = arg_pretty ? "PrettyHostname" : + arg_static ? "StaticHostname" : "Hostname"; + + return show_one_name(bus, attr); + } else { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = show_all_names(bus, &error); + if (r < 0) + return log_error_errno(r, "Failed to query system properties: %s", bus_error_message(&error, r)); + + return 0; + } +} + +static int set_simple_string(sd_bus *bus, const char *method, const char *value) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r = 0; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call_method( + bus, + "org.freedesktop.hostname1", + "/org/freedesktop/hostname1", + "org.freedesktop.hostname1", + method, + &error, NULL, + "sb", value, arg_ask_password); + if (r < 0) + return log_error_errno(r, "Could not set property: %s", bus_error_message(&error, -r)); + + return 0; +} + +static int set_hostname(int argc, char **argv, void *userdata) { + _cleanup_free_ char *h = NULL; + const char *hostname = argv[1]; + sd_bus *bus = userdata; + int r; + + if (!arg_pretty && !arg_static && !arg_transient) + arg_pretty = arg_static = arg_transient = true; + + if (arg_pretty) { + const char *p; + + /* If the passed hostname is already valid, then assume the user doesn't know anything about pretty + * hostnames, so let's unset the pretty hostname, and just set the passed hostname as static/dynamic + * hostname. */ + if (arg_static && hostname_is_valid(hostname, true)) + p = ""; /* No pretty hostname (as it is redundant), just a static one */ + else + p = hostname; /* Use the passed name as pretty hostname */ + + r = set_simple_string(bus, "SetPrettyHostname", p); + if (r < 0) + return r; + + /* Now that we set the pretty hostname, let's clean up the parameter and use that as static + * hostname. If the hostname was already valid as static hostname, this will only chop off the trailing + * dot if there is one. If it was not valid, then it will be made fully valid by truncating, dropping + * multiple dots, and dropping weird chars. Note that we clean the name up only if we also are + * supposed to set the pretty name. If the pretty name is not being set we assume the user knows what + * he does and pass the name as-is. */ + h = strdup(hostname); + if (!h) + return log_oom(); + + hostname = hostname_cleanup(h); /* Use the cleaned up name as static hostname */ + } + + if (arg_static) { + r = set_simple_string(bus, "SetStaticHostname", hostname); + if (r < 0) + return r; + } + + if (arg_transient) { + r = set_simple_string(bus, "SetHostname", hostname); + if (r < 0) + return r; + } + + return 0; +} + +static int set_icon_name(int argc, char **argv, void *userdata) { + return set_simple_string(userdata, "SetIconName", argv[1]); +} + +static int set_chassis(int argc, char **argv, void *userdata) { + return set_simple_string(userdata, "SetChassis", argv[1]); +} + +static int set_deployment(int argc, char **argv, void *userdata) { + return set_simple_string(userdata, "SetDeployment", argv[1]); +} + +static int set_location(int argc, char **argv, void *userdata) { + return set_simple_string(userdata, "SetLocation", argv[1]); +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("hostnamectl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n\n" + "%sQuery or change system hostname.%s\n" + "\nCommands:\n" + " status Show current hostname settings\n" + " set-hostname NAME Set system hostname\n" + " set-icon-name NAME Set icon name for host\n" + " set-chassis NAME Set chassis type for host\n" + " set-deployment NAME Set deployment environment for host\n" + " set-location NAME Set location for host\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-ask-password Do not prompt for password\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " --transient Only set transient hostname\n" + " --static Only set static hostname\n" + " --pretty Only set pretty hostname\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int verb_help(int argc, char **argv, void *userdata) { + return help(); +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_ASK_PASSWORD, + ARG_TRANSIENT, + ARG_STATIC, + ARG_PRETTY + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "transient", no_argument, NULL, ARG_TRANSIENT }, + { "static", no_argument, NULL, ARG_STATIC }, + { "pretty", no_argument, NULL, ARG_PRETTY }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case ARG_TRANSIENT: + arg_transient = true; + break; + + case ARG_PRETTY: + arg_pretty = true; + break; + + case ARG_STATIC: + arg_static = true; + break; + + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int hostnamectl_main(sd_bus *bus, int argc, char *argv[]) { + + static const Verb verbs[] = { + { "status", VERB_ANY, 1, VERB_DEFAULT, show_status }, + { "set-hostname", 2, 2, 0, set_hostname }, + { "set-icon-name", 2, 2, 0, set_icon_name }, + { "set-chassis", 2, 2, 0, set_chassis }, + { "set-deployment", 2, 2, 0, set_deployment }, + { "set-location", 2, 2, 0, set_location }, + { "help", VERB_ANY, VERB_ANY, 0, verb_help }, /* Not documented, but supported since it is created. */ + {} + }; + + return dispatch_verb(argc, argv, verbs, bus); +} + +static int run(int argc, char *argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + setlocale(LC_ALL, ""); + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = bus_connect_transport(arg_transport, arg_host, false, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + return hostnamectl_main(bus, argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c new file mode 100644 index 00000000..21f64714 --- /dev/null +++ b/src/hostname/hostnamed.c @@ -0,0 +1,767 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-polkit.h" +#include "def.h" +#include "env-file-label.h" +#include "env-file.h" +#include "env-util.h" +#include "fileio-label.h" +#include "fileio.h" +#include "hostname-util.h" +#include "id128-util.h" +#include "main-func.h" +#include "missing_capability.h" +#include "nscd-flush.h" +#include "nulstr-util.h" +#include "os-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" +#include "virt.h" + +#define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:") + +enum { + PROP_HOSTNAME, + PROP_STATIC_HOSTNAME, + PROP_PRETTY_HOSTNAME, + PROP_ICON_NAME, + PROP_CHASSIS, + PROP_DEPLOYMENT, + PROP_LOCATION, + PROP_KERNEL_NAME, + PROP_KERNEL_RELEASE, + PROP_KERNEL_VERSION, + PROP_OS_PRETTY_NAME, + PROP_OS_CPE_NAME, + PROP_HOME_URL, + _PROP_MAX +}; + +typedef struct Context { + char *data[_PROP_MAX]; + Hashmap *polkit_registry; + sd_id128_t uuid; + bool has_uuid; +} Context; + +static void context_reset(Context *c) { + int p; + + assert(c); + + for (p = 0; p < _PROP_MAX; p++) + c->data[p] = mfree(c->data[p]); +} + +static void context_clear(Context *c) { + assert(c); + + context_reset(c); + bus_verify_polkit_async_registry_free(c->polkit_registry); +} + +static int context_read_data(Context *c) { + int r; + struct utsname u; + + assert(c); + + context_reset(c); + + assert_se(uname(&u) >= 0); + c->data[PROP_KERNEL_NAME] = strdup(u.sysname); + c->data[PROP_KERNEL_RELEASE] = strdup(u.release); + c->data[PROP_KERNEL_VERSION] = strdup(u.version); + if (!c->data[PROP_KERNEL_NAME] || !c->data[PROP_KERNEL_RELEASE] || + !c->data[PROP_KERNEL_VERSION]) + return -ENOMEM; + + c->data[PROP_HOSTNAME] = gethostname_malloc(); + if (!c->data[PROP_HOSTNAME]) + return -ENOMEM; + + r = read_etc_hostname(NULL, &c->data[PROP_STATIC_HOSTNAME]); + if (r < 0 && r != -ENOENT) + return r; + + r = parse_env_file(NULL, "/etc/machine-info", + "PRETTY_HOSTNAME", &c->data[PROP_PRETTY_HOSTNAME], + "ICON_NAME", &c->data[PROP_ICON_NAME], + "CHASSIS", &c->data[PROP_CHASSIS], + "DEPLOYMENT", &c->data[PROP_DEPLOYMENT], + "LOCATION", &c->data[PROP_LOCATION]); + if (r < 0 && r != -ENOENT) + return r; + + r = parse_os_release(NULL, + "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME], + "CPE_NAME", &c->data[PROP_OS_CPE_NAME], + "HOME_URL", &c->data[PROP_HOME_URL], + NULL); + if (r < 0 && r != -ENOENT) + return r; + + r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &c->uuid); + if (r == -ENOENT) + r = id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, &c->uuid); + if (r < 0) + log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, + "Failed to read product UUID, ignoring: %m"); + else if (sd_id128_is_null(c->uuid) || sd_id128_is_allf(c->uuid)) + log_debug("DMI product UUID " SD_ID128_FORMAT_STR " is all 0x00 or all 0xFF, ignoring.", SD_ID128_FORMAT_VAL(c->uuid)); + else + c->has_uuid = true; + + return 0; +} + +static bool valid_chassis(const char *chassis) { + assert(chassis); + + return nulstr_contains( + "vm\0" + "container\0" + "desktop\0" + "laptop\0" + "convertible\0" + "server\0" + "tablet\0" + "handset\0" + "watch\0" + "embedded\0", + chassis); +} + +static bool valid_deployment(const char *deployment) { + assert(deployment); + + return in_charset(deployment, VALID_DEPLOYMENT_CHARS); +} + +static const char* fallback_chassis(void) { + char *type; + unsigned t; + int v, r; + + v = detect_virtualization(); + if (VIRTUALIZATION_IS_VM(v)) + return "vm"; + if (VIRTUALIZATION_IS_CONTAINER(v)) + return "container"; + + r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type); + if (r < 0) + goto try_acpi; + + r = safe_atou(type, &t); + free(type); + if (r < 0) + goto try_acpi; + + /* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any + additional guesswork on top of that. + + See the SMBIOS Specification 3.0 section 7.4.1 for details about the values listed here: + + https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf + */ + + switch (t) { + + case 0x3: /* Desktop */ + case 0x4: /* Low Profile Desktop */ + case 0x6: /* Mini Tower */ + case 0x7: /* Tower */ + return "desktop"; + + case 0x8: /* Portable */ + case 0x9: /* Laptop */ + case 0xA: /* Notebook */ + case 0xE: /* Sub Notebook */ + return "laptop"; + + case 0xB: /* Hand Held */ + return "handset"; + + case 0x11: /* Main Server Chassis */ + case 0x1C: /* Blade */ + case 0x1D: /* Blade Enclosure */ + return "server"; + + case 0x1E: /* Tablet */ + return "tablet"; + + case 0x1F: /* Convertible */ + case 0x20: /* Detachable */ + return "convertible"; + } + +try_acpi: + r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type); + if (r < 0) + return NULL; + + r = safe_atou(type, &t); + free(type); + if (r < 0) + return NULL; + + /* We only list the really obvious cases here as the ACPI data is not really super reliable. + * + * See the ACPI 5.0 Spec Section 5.2.9.1 for details: + * + * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf + */ + + switch(t) { + + case 1: /* Desktop */ + case 3: /* Workstation */ + case 6: /* Appliance PC */ + return "desktop"; + + case 2: /* Mobile */ + return "laptop"; + + case 4: /* Enterprise Server */ + case 5: /* SOHO Server */ + case 7: /* Performance Server */ + return "server"; + + case 8: /* Tablet */ + return "tablet"; + } + + return NULL; +} + +static char* context_fallback_icon_name(Context *c) { + const char *chassis; + + assert(c); + + if (!isempty(c->data[PROP_CHASSIS])) + return strjoin("computer-", c->data[PROP_CHASSIS]); + + chassis = fallback_chassis(); + if (chassis) + return strjoin("computer-", chassis); + + return strdup("computer"); +} + +static bool hostname_is_useful(const char *hn) { + return !isempty(hn) && !is_localhost(hn); +} + +static int context_update_kernel_hostname(Context *c) { + const char *static_hn; + const char *hn; + + assert(c); + + static_hn = c->data[PROP_STATIC_HOSTNAME]; + + /* /etc/hostname with something other than "localhost" + * has the highest preference ... */ + if (hostname_is_useful(static_hn)) + hn = static_hn; + + /* ... the transient host name, (ie: DHCP) comes next ... */ + else if (!isempty(c->data[PROP_HOSTNAME])) + hn = c->data[PROP_HOSTNAME]; + + /* ... fallback to static "localhost.*" ignored above ... */ + else if (!isempty(static_hn)) + hn = static_hn; + + /* ... and the ultimate fallback */ + else + hn = FALLBACK_HOSTNAME; + + if (sethostname_idempotent(hn) < 0) + return -errno; + + (void) nscd_flush_cache(STRV_MAKE("hosts")); + + return 0; +} + +static int context_write_data_static_hostname(Context *c) { + + assert(c); + + if (isempty(c->data[PROP_STATIC_HOSTNAME])) { + + if (unlink("/etc/hostname") < 0) + return errno == ENOENT ? 0 : -errno; + + return 0; + } + return write_string_file_atomic_label("/etc/hostname", c->data[PROP_STATIC_HOSTNAME]); +} + +static int context_write_data_machine_info(Context *c) { + + static const char * const name[_PROP_MAX] = { + [PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME", + [PROP_ICON_NAME] = "ICON_NAME", + [PROP_CHASSIS] = "CHASSIS", + [PROP_DEPLOYMENT] = "DEPLOYMENT", + [PROP_LOCATION] = "LOCATION", + }; + + _cleanup_strv_free_ char **l = NULL; + int r, p; + + assert(c); + + r = load_env_file(NULL, "/etc/machine-info", &l); + if (r < 0 && r != -ENOENT) + return r; + + for (p = PROP_PRETTY_HOSTNAME; p <= PROP_LOCATION; p++) { + _cleanup_free_ char *t = NULL; + char **u; + + assert(name[p]); + + if (isempty(c->data[p])) { + strv_env_unset(l, name[p]); + continue; + } + + t = strjoin(name[p], "=", c->data[p]); + if (!t) + return -ENOMEM; + + u = strv_env_set(l, t); + if (!u) + return -ENOMEM; + + strv_free_and_replace(l, u); + } + + if (strv_isempty(l)) { + if (unlink("/etc/machine-info") < 0) + return errno == ENOENT ? 0 : -errno; + + return 0; + } + + return write_env_file_label("/etc/machine-info", l); +} + +static int property_get_icon_name( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *n = NULL; + Context *c = userdata; + const char *name; + + if (isempty(c->data[PROP_ICON_NAME])) + name = n = context_fallback_icon_name(c); + else + name = c->data[PROP_ICON_NAME]; + + if (!name) + return -ENOMEM; + + return sd_bus_message_append(reply, "s", name); +} + +static int property_get_chassis( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Context *c = userdata; + const char *name; + + if (isempty(c->data[PROP_CHASSIS])) + name = fallback_chassis(); + else + name = c->data[PROP_CHASSIS]; + + return sd_bus_message_append(reply, "s", name); +} + +static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) { + Context *c = userdata; + const char *name; + int interactive; + int r; + + assert(m); + assert(c); + + r = sd_bus_message_read(m, "sb", &name, &interactive); + if (r < 0) + return r; + + if (isempty(name)) + name = c->data[PROP_STATIC_HOSTNAME]; + + if (isempty(name)) + name = FALLBACK_HOSTNAME; + + if (!hostname_is_valid(name, false)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name); + + if (streq_ptr(name, c->data[PROP_HOSTNAME])) + return sd_bus_reply_method_return(m, NULL); + + r = bus_verify_polkit_async( + m, + CAP_SYS_ADMIN, + "org.freedesktop.hostname1.set-hostname", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = free_and_strdup(&c->data[PROP_HOSTNAME], name); + if (r < 0) + return r; + + r = context_update_kernel_hostname(c); + if (r < 0) { + log_error_errno(r, "Failed to set host name: %m"); + return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m"); + } + + log_info("Changed host name to '%s'", strna(c->data[PROP_HOSTNAME])); + + (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "Hostname", NULL); + + return sd_bus_reply_method_return(m, NULL); +} + +static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) { + Context *c = userdata; + const char *name; + int interactive; + int r; + + assert(m); + assert(c); + + r = sd_bus_message_read(m, "sb", &name, &interactive); + if (r < 0) + return r; + + name = empty_to_null(name); + + if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME])) + return sd_bus_reply_method_return(m, NULL); + + if (!isempty(name) && !hostname_is_valid(name, false)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name); + + r = bus_verify_polkit_async( + m, + CAP_SYS_ADMIN, + "org.freedesktop.hostname1.set-static-hostname", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = free_and_strdup(&c->data[PROP_STATIC_HOSTNAME], name); + if (r < 0) + return r; + + r = context_update_kernel_hostname(c); + if (r < 0) { + log_error_errno(r, "Failed to set host name: %m"); + return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m"); + } + + r = context_write_data_static_hostname(c); + if (r < 0) { + log_error_errno(r, "Failed to write static host name: %m"); + return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m"); + } + + log_info("Changed static host name to '%s'", strna(c->data[PROP_STATIC_HOSTNAME])); + + (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "StaticHostname", NULL); + + return sd_bus_reply_method_return(m, NULL); +} + +static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_message_handler_t cb, sd_bus_error *error) { + int interactive; + const char *name; + int r; + + assert(c); + assert(m); + + r = sd_bus_message_read(m, "sb", &name, &interactive); + if (r < 0) + return r; + + name = empty_to_null(name); + + if (streq_ptr(name, c->data[prop])) + return sd_bus_reply_method_return(m, NULL); + + if (!isempty(name)) { + /* The icon name might ultimately be used as file + * name, so better be safe than sorry */ + + if (prop == PROP_ICON_NAME && !filename_is_valid(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name); + if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name); + if (prop == PROP_CHASSIS && !valid_chassis(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name); + if (prop == PROP_DEPLOYMENT && !valid_deployment(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name); + if (prop == PROP_LOCATION && string_has_cc(name, NULL)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name); + } + + /* Since the pretty hostname should always be changed at the + * same time as the static one, use the same policy action for + * both... */ + + r = bus_verify_polkit_async( + m, + CAP_SYS_ADMIN, + prop == PROP_PRETTY_HOSTNAME ? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = free_and_strdup(&c->data[prop], name); + if (r < 0) + return r; + + r = context_write_data_machine_info(c); + if (r < 0) { + log_error_errno(r, "Failed to write machine info: %m"); + return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %m"); + } + + log_info("Changed %s to '%s'", + prop == PROP_PRETTY_HOSTNAME ? "pretty host name" : + prop == PROP_DEPLOYMENT ? "deployment" : + prop == PROP_LOCATION ? "location" : + prop == PROP_CHASSIS ? "chassis" : "icon name", strna(c->data[prop])); + + (void) sd_bus_emit_properties_changed( + sd_bus_message_get_bus(m), + "/org/freedesktop/hostname1", + "org.freedesktop.hostname1", + prop == PROP_PRETTY_HOSTNAME ? "PrettyHostname" : + prop == PROP_DEPLOYMENT ? "Deployment" : + prop == PROP_LOCATION ? "Location" : + prop == PROP_CHASSIS ? "Chassis" : "IconName" , NULL); + + return sd_bus_reply_method_return(m, NULL); +} + +static int method_set_pretty_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) { + return set_machine_info(userdata, m, PROP_PRETTY_HOSTNAME, method_set_pretty_hostname, error); +} + +static int method_set_icon_name(sd_bus_message *m, void *userdata, sd_bus_error *error) { + return set_machine_info(userdata, m, PROP_ICON_NAME, method_set_icon_name, error); +} + +static int method_set_chassis(sd_bus_message *m, void *userdata, sd_bus_error *error) { + return set_machine_info(userdata, m, PROP_CHASSIS, method_set_chassis, error); +} + +static int method_set_deployment(sd_bus_message *m, void *userdata, sd_bus_error *error) { + return set_machine_info(userdata, m, PROP_DEPLOYMENT, method_set_deployment, error); +} + +static int method_set_location(sd_bus_message *m, void *userdata, sd_bus_error *error) { + return set_machine_info(userdata, m, PROP_LOCATION, method_set_location, error); +} + +static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Context *c = userdata; + int interactive, r; + + assert(m); + assert(c); + + if (!c->has_uuid) + return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID, "Failed to read product UUID from /sys/class/dmi/id/product_uuid"); + + r = sd_bus_message_read(m, "b", &interactive); + if (r < 0) + return r; + + r = bus_verify_polkit_async( + m, + CAP_SYS_ADMIN, + "org.freedesktop.hostname1.get-product-uuid", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', &c->uuid, sizeof(c->uuid)); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static const sd_bus_vtable hostname_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Hostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("StaticHostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_STATIC_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("PrettyHostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Deployment", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_DEPLOYMENT, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Location", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_LOCATION, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("KernelName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_KERNEL_NAME, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KernelRelease", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_KERNEL_RELEASE, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KernelVersion", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_KERNEL_VERSION, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_OS_PRETTY_NAME, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("OperatingSystemCPEName", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_OS_CPE_NAME, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HomeURL", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_HOME_URL, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_METHOD("SetHostname", "sb", NULL, method_set_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetStaticHostname", "sb", NULL, method_set_static_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetPrettyHostname", "sb", NULL, method_set_pretty_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetIconName", "sb", NULL, method_set_icon_name, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetChassis", "sb", NULL, method_set_chassis, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDeployment", "sb", NULL, method_set_deployment, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLocation", "sb", NULL, method_set_location, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetProductUUID", "b", "ay", method_get_product_uuid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END, +}; + +static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + assert(c); + assert(event); + assert(_bus); + + r = sd_bus_default_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to get system bus connection: %m"); + + r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c); + if (r < 0) + return log_error_errno(r, "Failed to register object: %m"); + + r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.hostname1", 0, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + r = sd_bus_attach_event(bus, event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + *_bus = TAKE_PTR(bus); + + return 0; +} + +static int run(int argc, char *argv[]) { + _cleanup_(context_clear) Context context = {}; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + log_setup_service(); + + umask(0022); + mac_selinux_init(); + + if (argc != 1) { + log_error("This program takes no arguments."); + return -EINVAL; + } + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + (void) sd_event_set_watchdog(event, true); + + r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to install SIGINT handler: %m"); + + r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to install SIGTERM handler: %m"); + + r = connect_bus(&context, event, &bus); + if (r < 0) + return r; + + r = context_read_data(&context); + if (r < 0) + return log_error_errno(r, "Failed to read hostname and machine information: %m"); + + r = bus_event_loop_with_idle(event, bus, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/hostname/meson.build b/src/hostname/meson.build new file mode 100644 index 00000000..db66ba55 --- /dev/null +++ b/src/hostname/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +if conf.get('ENABLE_HOSTNAMED') == 1 + install_data('org.freedesktop.hostname1.conf', + install_dir : dbuspolicydir) + install_data('org.freedesktop.hostname1.service', + install_dir : dbussystemservicedir) + install_data('org.freedesktop.hostname1.policy', + install_dir : polkitpolicydir) +endif diff --git a/src/hostname/org.freedesktop.hostname1.conf b/src/hostname/org.freedesktop.hostname1.conf new file mode 100644 index 00000000..e2658c6c --- /dev/null +++ b/src/hostname/org.freedesktop.hostname1.conf @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/hostname/org.freedesktop.hostname1.policy b/src/hostname/org.freedesktop.hostname1.policy new file mode 100644 index 00000000..5bedc0b6 --- /dev/null +++ b/src/hostname/org.freedesktop.hostname1.policy @@ -0,0 +1,60 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Set host name + Authentication is required to set the local host name. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Set static host name + Authentication is required to set the statically configured local host name, as well as the pretty host name. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.hostname1.set-hostname org.freedesktop.hostname1.set-machine-info + + + + Set machine information + Authentication is required to set local machine information. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Get product UUID + Authentication is required to get product UUID. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + diff --git a/src/hostname/org.freedesktop.hostname1.service b/src/hostname/org.freedesktop.hostname1.service new file mode 100644 index 00000000..98c7bcbd --- /dev/null +++ b/src/hostname/org.freedesktop.hostname1.service @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.hostname1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.hostname1.service diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c new file mode 100644 index 00000000..651647b3 --- /dev/null +++ b/src/hwdb/hwdb.c @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-hwdb.h" + +#include "alloc-util.h" +#include "hwdb-util.h" +#include "main-func.h" +#include "pretty-print.h" +#include "selinux-util.h" +#include "terminal-util.h" +#include "util.h" +#include "verbs.h" + +static const char *arg_hwdb_bin_dir = NULL; +static const char *arg_root = NULL; +static bool arg_strict = false; + +static int verb_query(int argc, char *argv[], void *userdata) { + return hwdb_query(argv[1]); +} + +static int verb_update(int argc, char *argv[], void *userdata) { + return hwdb_update(arg_root, arg_hwdb_bin_dir, arg_strict, false); +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-hwdb", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n\n" + "%sUpdate or query the hardware database.%s\n" + "\nCommands:\n" + " update Update the hwdb database\n" + " query MODALIAS Query database and print result\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -s --strict When updating, return non-zero exit value on any parsing error\n" + " --usr Generate in " UDEVLIBEXECDIR " instead of /etc/udev\n" + " -r --root=PATH Alternative root path in the filesystem\n\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_USR, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "usr", no_argument, NULL, ARG_USR }, + { "strict", no_argument, NULL, 's' }, + { "root", required_argument, NULL, 'r' }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "ust:r:h", options, NULL)) >= 0) + switch(c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_USR: + arg_hwdb_bin_dir = UDEVLIBEXECDIR; + break; + + case 's': + arg_strict = true; + break; + + case 'r': + arg_root = optarg; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unknown option"); + } + + return 1; +} + +static int hwdb_main(int argc, char *argv[]) { + static const Verb verbs[] = { + { "update", 1, 1, 0, verb_update }, + { "query", 2, 2, 0, verb_query }, + {}, + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static int run(int argc, char *argv[]) { + int r; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + mac_selinux_init(); + + return hwdb_main(argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/id128/id128.c b/src/id128/id128.c new file mode 100644 index 00000000..cd4d5414 --- /dev/null +++ b/src/id128/id128.c @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "id128-print.h" +#include "main-func.h" +#include "pretty-print.h" +#include "terminal-util.h" +#include "util.h" +#include "verbs.h" + +static Id128PrettyPrintMode arg_mode = ID128_PRINT_ID128; +static sd_id128_t arg_app = {}; + +static int verb_new(int argc, char **argv, void *userdata) { + return id128_print_new(arg_mode); +} + +static int verb_machine_id(int argc, char **argv, void *userdata) { + sd_id128_t id; + int r; + + if (sd_id128_is_null(arg_app)) + r = sd_id128_get_machine(&id); + else + r = sd_id128_get_machine_app_specific(arg_app, &id); + if (r < 0) + return log_error_errno(r, "Failed to get %smachine-ID: %m", + sd_id128_is_null(arg_app) ? "" : "app-specific "); + + return id128_pretty_print(id, arg_mode); +} + +static int verb_boot_id(int argc, char **argv, void *userdata) { + sd_id128_t id; + int r; + + if (sd_id128_is_null(arg_app)) + r = sd_id128_get_boot(&id); + else + r = sd_id128_get_boot_app_specific(arg_app, &id); + if (r < 0) + return log_error_errno(r, "Failed to get %sboot-ID: %m", + sd_id128_is_null(arg_app) ? "" : "app-specific "); + + return id128_pretty_print(id, arg_mode); +} + +static int verb_invocation_id(int argc, char **argv, void *userdata) { + sd_id128_t id; + int r; + + if (!sd_id128_is_null(arg_app)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Verb \"invocation-id\" cannot be combined with --app-specific=."); + + r = sd_id128_get_invocation(&id); + if (r < 0) + return log_error_errno(r, "Failed to get invocation-ID: %m"); + + return id128_pretty_print(id, arg_mode); +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-id128", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND\n\n" + "%sGenerate and print 128bit identifiers.%s\n" + "\nCommands:\n" + " new Generate a new id128 string\n" + " machine-id Print the ID of current machine\n" + " boot-id Print the ID of current boot\n" + " invocation-id Print the ID of current invocation\n" + " help Show this help\n" + "\nOptions:\n" + " -h --help Show this help\n" + " -p --pretty Generate samples of program code\n" + " -a --app-specific=ID Generate app-specific IDs\n" + " -u --uuid Output in UUID format\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +static int verb_help(int argc, char **argv, void *userdata) { + return help(); +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "pretty", no_argument, NULL, 'p' }, + { "app-specific", required_argument, NULL, 'a' }, + { "uuid", no_argument, NULL, 'u' }, + {}, + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hpa:u", options, NULL)) >= 0) + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case 'p': + arg_mode = ID128_PRINT_PRETTY; + break; + + case 'a': + r = sd_id128_from_string(optarg, &arg_app); + if (r < 0) + return log_error_errno(r, "Failed to parse \"%s\" as application-ID: %m", optarg); + break; + + case 'u': + arg_mode = ID128_PRINT_UUID; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int id128_main(int argc, char *argv[]) { + static const Verb verbs[] = { + { "new", VERB_ANY, 1, 0, verb_new }, + { "machine-id", VERB_ANY, 1, 0, verb_machine_id }, + { "boot-id", VERB_ANY, 1, 0, verb_boot_id }, + { "invocation-id", VERB_ANY, 1, 0, verb_invocation_id }, + { "help", VERB_ANY, VERB_ANY, 0, verb_help }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static int run(int argc, char *argv[]) { + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + return id128_main(argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/import/curl-util.c b/src/import/curl-util.c new file mode 100644 index 00000000..96cf6966 --- /dev/null +++ b/src/import/curl-util.c @@ -0,0 +1,372 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "build.h" +#include "curl-util.h" +#include "fd-util.h" +#include "locale-util.h" +#include "string-util.h" + +static void curl_glue_check_finished(CurlGlue *g) { + CURLMsg *msg; + int k = 0; + + assert(g); + + msg = curl_multi_info_read(g->curl, &k); + if (!msg) + return; + + if (msg->msg != CURLMSG_DONE) + return; + + if (g->on_finished) + g->on_finished(g, msg->easy_handle, msg->data.result); +} + +static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + CurlGlue *g = userdata; + int action, k = 0; + + assert(s); + assert(g); + + if (FLAGS_SET(revents, EPOLLIN | EPOLLOUT)) + action = CURL_POLL_INOUT; + else if (revents & EPOLLIN) + action = CURL_POLL_IN; + else if (revents & EPOLLOUT) + action = CURL_POLL_OUT; + else + action = 0; + + if (curl_multi_socket_action(g->curl, fd, action, &k) != CURLM_OK) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to propagate IO event."); + + curl_glue_check_finished(g); + return 0; +} + +static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, void *userdata, void *socketp) { + sd_event_source *io = socketp; + CurlGlue *g = userdata; + uint32_t events = 0; + int r; + + assert(curl); + assert(g); + + if (action == CURL_POLL_REMOVE) { + if (io) { + sd_event_source_disable_unref(io); + + hashmap_remove(g->ios, FD_TO_PTR(s)); + } + + return 0; + } + + r = hashmap_ensure_allocated(&g->ios, &trivial_hash_ops); + if (r < 0) { + log_oom(); + return -1; + } + + if (action == CURL_POLL_IN) + events = EPOLLIN; + else if (action == CURL_POLL_OUT) + events = EPOLLOUT; + else if (action == CURL_POLL_INOUT) + events = EPOLLIN|EPOLLOUT; + + if (io) { + if (sd_event_source_set_io_events(io, events) < 0) + return -1; + + if (sd_event_source_set_enabled(io, SD_EVENT_ON) < 0) + return -1; + } else { + if (sd_event_add_io(g->event, &io, s, events, curl_glue_on_io, g) < 0) + return -1; + + if (curl_multi_assign(g->curl, s, io) != CURLM_OK) + return -1; + + (void) sd_event_source_set_description(io, "curl-io"); + + r = hashmap_put(g->ios, FD_TO_PTR(s), io); + if (r < 0) { + log_oom(); + sd_event_source_unref(io); + return -1; + } + } + + return 0; +} + +static int curl_glue_on_timer(sd_event_source *s, uint64_t usec, void *userdata) { + CurlGlue *g = userdata; + int k = 0; + + assert(s); + assert(g); + + if (curl_multi_socket_action(g->curl, CURL_SOCKET_TIMEOUT, 0, &k) != CURLM_OK) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to propagate timeout."); + + curl_glue_check_finished(g); + return 0; +} + +static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata) { + CurlGlue *g = userdata; + usec_t usec; + + assert(curl); + assert(g); + + if (timeout_ms < 0) { + if (g->timer) { + if (sd_event_source_set_enabled(g->timer, SD_EVENT_OFF) < 0) + return -1; + } + + return 0; + } + + usec = now(clock_boottime_or_monotonic()) + (usec_t) timeout_ms * USEC_PER_MSEC + USEC_PER_MSEC - 1; + + if (g->timer) { + if (sd_event_source_set_time(g->timer, usec) < 0) + return -1; + + if (sd_event_source_set_enabled(g->timer, SD_EVENT_ONESHOT) < 0) + return -1; + } else { + if (sd_event_add_time(g->event, &g->timer, clock_boottime_or_monotonic(), usec, 0, curl_glue_on_timer, g) < 0) + return -1; + + (void) sd_event_source_set_description(g->timer, "curl-timer"); + } + + return 0; +} + +CurlGlue *curl_glue_unref(CurlGlue *g) { + sd_event_source *io; + + if (!g) + return NULL; + + if (g->curl) + curl_multi_cleanup(g->curl); + + while ((io = hashmap_steal_first(g->ios))) { + sd_event_source_unref(io); + } + + hashmap_free(g->ios); + + sd_event_source_unref(g->timer); + sd_event_unref(g->event); + return mfree(g); +} + +int curl_glue_new(CurlGlue **glue, sd_event *event) { + _cleanup_(curl_glue_unrefp) CurlGlue *g = NULL; + _cleanup_(curl_multi_cleanupp) CURL *c = NULL; + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + int r; + + if (event) + e = sd_event_ref(event); + else { + r = sd_event_default(&e); + if (r < 0) + return r; + } + + c = curl_multi_init(); + if (!c) + return -ENOMEM; + + g = new(CurlGlue, 1); + if (!g) + return -ENOMEM; + + *g = (CurlGlue) { + .event = TAKE_PTR(e), + .curl = TAKE_PTR(c), + }; + + if (curl_multi_setopt(g->curl, CURLMOPT_SOCKETDATA, g) != CURLM_OK) + return -EINVAL; + + if (curl_multi_setopt(g->curl, CURLMOPT_SOCKETFUNCTION, curl_glue_socket_callback) != CURLM_OK) + return -EINVAL; + + if (curl_multi_setopt(g->curl, CURLMOPT_TIMERDATA, g) != CURLM_OK) + return -EINVAL; + + if (curl_multi_setopt(g->curl, CURLMOPT_TIMERFUNCTION, curl_glue_timer_callback) != CURLM_OK) + return -EINVAL; + + *glue = TAKE_PTR(g); + + return 0; +} + +int curl_glue_make(CURL **ret, const char *url, void *userdata) { + _cleanup_(curl_easy_cleanupp) CURL *c = NULL; + const char *useragent; + + assert(ret); + assert(url); + + c = curl_easy_init(); + if (!c) + return -ENOMEM; + + /* curl_easy_setopt(c, CURLOPT_VERBOSE, 1L); */ + + if (curl_easy_setopt(c, CURLOPT_URL, url) != CURLE_OK) + return -EIO; + + if (curl_easy_setopt(c, CURLOPT_PRIVATE, userdata) != CURLE_OK) + return -EIO; + + useragent = strjoina(program_invocation_short_name, "/" GIT_VERSION); + if (curl_easy_setopt(c, CURLOPT_USERAGENT, useragent) != CURLE_OK) + return -EIO; + + if (curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK) + return -EIO; + + *ret = TAKE_PTR(c); + return 0; +} + +int curl_glue_add(CurlGlue *g, CURL *c) { + assert(g); + assert(c); + + if (curl_multi_add_handle(g->curl, c) != CURLM_OK) + return -EIO; + + return 0; +} + +void curl_glue_remove_and_free(CurlGlue *g, CURL *c) { + assert(g); + + if (!c) + return; + + if (g->curl) + curl_multi_remove_handle(g->curl, c); + + curl_easy_cleanup(c); +} + +struct curl_slist *curl_slist_new(const char *first, ...) { + struct curl_slist *l; + va_list ap; + + if (!first) + return NULL; + + l = curl_slist_append(NULL, first); + if (!l) + return NULL; + + va_start(ap, first); + + for (;;) { + struct curl_slist *n; + const char *i; + + i = va_arg(ap, const char*); + if (!i) + break; + + n = curl_slist_append(l, i); + if (!n) { + va_end(ap); + curl_slist_free_all(l); + return NULL; + } + + l = n; + } + + va_end(ap); + return l; +} + +int curl_header_strdup(const void *contents, size_t sz, const char *field, char **value) { + const char *p; + char *s; + + p = memory_startswith_no_case(contents, sz, field); + if (!p) + return 0; + + sz -= p - (const char*) contents; + + if (memchr(p, 0, sz)) + return 0; + + /* Skip over preceding whitespace */ + while (sz > 0 && strchr(WHITESPACE, p[0])) { + p++; + sz--; + } + + /* Truncate trailing whitespace */ + while (sz > 0 && strchr(WHITESPACE, p[sz-1])) + sz--; + + s = strndup(p, sz); + if (!s) + return -ENOMEM; + + *value = s; + return 1; +} + +int curl_parse_http_time(const char *t, usec_t *ret) { + _cleanup_(freelocalep) locale_t loc = (locale_t) 0; + const char *e; + struct tm tm; + time_t v; + + assert(t); + assert(ret); + + loc = newlocale(LC_TIME_MASK, "C", (locale_t) 0); + if (loc == (locale_t) 0) + return -errno; + + /* RFC822 */ + e = strptime_l(t, "%a, %d %b %Y %H:%M:%S %Z", &tm, loc); + if (!e || *e != 0) + /* RFC 850 */ + e = strptime_l(t, "%A, %d-%b-%y %H:%M:%S %Z", &tm, loc); + if (!e || *e != 0) + /* ANSI C */ + e = strptime_l(t, "%a %b %d %H:%M:%S %Y", &tm, loc); + if (!e || *e != 0) + return -EINVAL; + + v = timegm(&tm); + if (v == (time_t) -1) + return -EINVAL; + + *ret = (usec_t) v * USEC_PER_SEC; + return 0; +} diff --git a/src/import/curl-util.h b/src/import/curl-util.h new file mode 100644 index 00000000..fa80b233 --- /dev/null +++ b/src/import/curl-util.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-event.h" + +#include "hashmap.h" +#include "time-util.h" + +typedef struct CurlGlue CurlGlue; + +struct CurlGlue { + sd_event *event; + CURLM *curl; + sd_event_source *timer; + Hashmap *ios; + + void (*on_finished)(CurlGlue *g, CURL *curl, CURLcode code); + void *userdata; +}; + +int curl_glue_new(CurlGlue **glue, sd_event *event); +CurlGlue* curl_glue_unref(CurlGlue *glue); + +DEFINE_TRIVIAL_CLEANUP_FUNC(CurlGlue*, curl_glue_unref); + +int curl_glue_make(CURL **ret, const char *url, void *userdata); +int curl_glue_add(CurlGlue *g, CURL *c); +void curl_glue_remove_and_free(CurlGlue *g, CURL *c); + +struct curl_slist *curl_slist_new(const char *first, ...) _sentinel_; +int curl_header_strdup(const void *contents, size_t sz, const char *field, char **value); +int curl_parse_http_time(const char *t, usec_t *ret); + +DEFINE_TRIVIAL_CLEANUP_FUNC(CURL*, curl_easy_cleanup); +DEFINE_TRIVIAL_CLEANUP_FUNC(CURL*, curl_multi_cleanup); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct curl_slist*, curl_slist_free_all); diff --git a/src/import/export-raw.c b/src/import/export-raw.c new file mode 100644 index 00000000..a0ac6bc7 --- /dev/null +++ b/src/import/export-raw.c @@ -0,0 +1,331 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +/* When we include libgen.h because we need dirname() we immediately + * undefine basename() since libgen.h defines it as a macro to the POSIX + * version which is really broken. We prefer GNU basename(). */ +#include +#undef basename + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "copy.h" +#include "export-raw.h" +#include "fd-util.h" +#include "fs-util.h" +#include "import-common.h" +#include "missing_fcntl.h" +#include "ratelimit.h" +#include "stat-util.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "util.h" + +#define COPY_BUFFER_SIZE (16*1024) + +struct RawExport { + sd_event *event; + + RawExportFinished on_finished; + void *userdata; + + char *path; + + int input_fd; + int output_fd; + + ImportCompress compress; + + sd_event_source *output_event_source; + + void *buffer; + size_t buffer_size; + size_t buffer_allocated; + + uint64_t written_compressed; + uint64_t written_uncompressed; + + unsigned last_percent; + RateLimit progress_ratelimit; + + struct stat st; + + bool eof; + bool tried_reflink; + bool tried_sendfile; +}; + +RawExport *raw_export_unref(RawExport *e) { + if (!e) + return NULL; + + sd_event_source_unref(e->output_event_source); + + import_compress_free(&e->compress); + + sd_event_unref(e->event); + + safe_close(e->input_fd); + + free(e->buffer); + free(e->path); + return mfree(e); +} + +int raw_export_new( + RawExport **ret, + sd_event *event, + RawExportFinished on_finished, + void *userdata) { + + _cleanup_(raw_export_unrefp) RawExport *e = NULL; + int r; + + assert(ret); + + e = new(RawExport, 1); + if (!e) + return -ENOMEM; + + *e = (RawExport) { + .output_fd = -1, + .input_fd = -1, + .on_finished = on_finished, + .userdata = userdata, + .last_percent = (unsigned) -1, + .progress_ratelimit = { 100 * USEC_PER_MSEC, 1 }, + }; + + if (event) + e->event = sd_event_ref(event); + else { + r = sd_event_default(&e->event); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(e); + + return 0; +} + +static void raw_export_report_progress(RawExport *e) { + unsigned percent; + assert(e); + + if (e->written_uncompressed >= (uint64_t) e->st.st_size) + percent = 100; + else + percent = (unsigned) ((e->written_uncompressed * UINT64_C(100)) / (uint64_t) e->st.st_size); + + if (percent == e->last_percent) + return; + + if (!ratelimit_below(&e->progress_ratelimit)) + return; + + sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); + log_info("Exported %u%%.", percent); + + e->last_percent = percent; +} + +static int raw_export_process(RawExport *e) { + ssize_t l; + int r; + + assert(e); + + if (!e->tried_reflink && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { + + /* If we shall take an uncompressed snapshot we can + * reflink source to destination directly. Let's see + * if this works. */ + + r = btrfs_reflink(e->input_fd, e->output_fd); + if (r >= 0) { + r = 0; + goto finish; + } + + e->tried_reflink = true; + } + + if (!e->tried_sendfile && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { + + l = sendfile(e->output_fd, e->input_fd, NULL, COPY_BUFFER_SIZE); + if (l < 0) { + if (errno == EAGAIN) + return 0; + + e->tried_sendfile = true; + } else if (l == 0) { + r = 0; + goto finish; + } else { + e->written_uncompressed += l; + e->written_compressed += l; + + raw_export_report_progress(e); + + return 0; + } + } + + while (e->buffer_size <= 0) { + uint8_t input[COPY_BUFFER_SIZE]; + + if (e->eof) { + r = 0; + goto finish; + } + + l = read(e->input_fd, input, sizeof(input)); + if (l < 0) { + r = log_error_errno(errno, "Failed to read raw file: %m"); + goto finish; + } + + if (l == 0) { + e->eof = true; + r = import_compress_finish(&e->compress, &e->buffer, &e->buffer_size, &e->buffer_allocated); + } else { + e->written_uncompressed += l; + r = import_compress(&e->compress, input, l, &e->buffer, &e->buffer_size, &e->buffer_allocated); + } + if (r < 0) { + r = log_error_errno(r, "Failed to encode: %m"); + goto finish; + } + } + + l = write(e->output_fd, e->buffer, e->buffer_size); + if (l < 0) { + if (errno == EAGAIN) + return 0; + + r = log_error_errno(errno, "Failed to write output file: %m"); + goto finish; + } + + assert((size_t) l <= e->buffer_size); + memmove(e->buffer, (uint8_t*) e->buffer + l, e->buffer_size - l); + e->buffer_size -= l; + e->written_compressed += l; + + raw_export_report_progress(e); + + return 0; + +finish: + if (r >= 0) { + (void) copy_times(e->input_fd, e->output_fd, COPY_CRTIME); + (void) copy_xattr(e->input_fd, e->output_fd); + } + + if (e->on_finished) + e->on_finished(e, r, e->userdata); + else + sd_event_exit(e->event, r); + + return 0; +} + +static int raw_export_on_output(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + RawExport *i = userdata; + + return raw_export_process(i); +} + +static int raw_export_on_defer(sd_event_source *s, void *userdata) { + RawExport *i = userdata; + + return raw_export_process(i); +} + +static int reflink_snapshot(int fd, const char *path) { + int new_fd, r; + + new_fd = open_parent(path, O_TMPFILE|O_CLOEXEC|O_RDWR, 0600); + if (new_fd < 0) { + _cleanup_free_ char *t = NULL; + + r = tempfn_random(path, NULL, &t); + if (r < 0) + return r; + + new_fd = open(t, O_CLOEXEC|O_CREAT|O_NOCTTY|O_RDWR, 0600); + if (new_fd < 0) + return -errno; + + (void) unlink(t); + } + + r = btrfs_reflink(fd, new_fd); + if (r < 0) { + safe_close(new_fd); + return r; + } + + return new_fd; +} + +int raw_export_start(RawExport *e, const char *path, int fd, ImportCompressType compress) { + _cleanup_close_ int sfd = -1, tfd = -1; + int r; + + assert(e); + assert(path); + assert(fd >= 0); + assert(compress < _IMPORT_COMPRESS_TYPE_MAX); + assert(compress != IMPORT_COMPRESS_UNKNOWN); + + if (e->output_fd >= 0) + return -EBUSY; + + r = fd_nonblock(fd, true); + if (r < 0) + return r; + + r = free_and_strdup(&e->path, path); + if (r < 0) + return r; + + sfd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (sfd < 0) + return -errno; + + if (fstat(sfd, &e->st) < 0) + return -errno; + r = stat_verify_regular(&e->st); + if (r < 0) + return r; + + /* Try to take a reflink snapshot of the file, if we can t make the export atomic */ + tfd = reflink_snapshot(sfd, path); + if (tfd >= 0) + e->input_fd = TAKE_FD(tfd); + else + e->input_fd = TAKE_FD(sfd); + + r = import_compress_init(&e->compress, compress); + if (r < 0) + return r; + + r = sd_event_add_io(e->event, &e->output_event_source, fd, EPOLLOUT, raw_export_on_output, e); + if (r == -EPERM) { + r = sd_event_add_defer(e->event, &e->output_event_source, raw_export_on_defer, e); + if (r < 0) + return r; + + r = sd_event_source_set_enabled(e->output_event_source, SD_EVENT_ON); + } + if (r < 0) + return r; + + e->output_fd = fd; + return r; +} diff --git a/src/import/export-raw.h b/src/import/export-raw.h new file mode 100644 index 00000000..196b8ef2 --- /dev/null +++ b/src/import/export-raw.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" + +#include "import-compress.h" +#include "macro.h" + +typedef struct RawExport RawExport; + +typedef void (*RawExportFinished)(RawExport *export, int error, void *userdata); + +int raw_export_new(RawExport **export, sd_event *event, RawExportFinished on_finished, void *userdata); +RawExport* raw_export_unref(RawExport *export); + +DEFINE_TRIVIAL_CLEANUP_FUNC(RawExport*, raw_export_unref); + +int raw_export_start(RawExport *export, const char *path, int fd, ImportCompressType compress); diff --git a/src/import/export-tar.c b/src/import/export-tar.c new file mode 100644 index 00000000..5f89880e --- /dev/null +++ b/src/import/export-tar.c @@ -0,0 +1,330 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "export-tar.h" +#include "fd-util.h" +#include "import-common.h" +#include "process-util.h" +#include "ratelimit.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "util.h" + +#define COPY_BUFFER_SIZE (16*1024) + +struct TarExport { + sd_event *event; + + TarExportFinished on_finished; + void *userdata; + + char *path; + char *temp_path; + + int output_fd; + int tar_fd; + + ImportCompress compress; + + sd_event_source *output_event_source; + + void *buffer; + size_t buffer_size; + size_t buffer_allocated; + + uint64_t written_compressed; + uint64_t written_uncompressed; + + pid_t tar_pid; + + struct stat st; + uint64_t quota_referenced; + + unsigned last_percent; + RateLimit progress_ratelimit; + + bool eof; + bool tried_splice; +}; + +TarExport *tar_export_unref(TarExport *e) { + if (!e) + return NULL; + + sd_event_source_unref(e->output_event_source); + + if (e->tar_pid > 1) { + (void) kill_and_sigcont(e->tar_pid, SIGKILL); + (void) wait_for_terminate(e->tar_pid, NULL); + } + + if (e->temp_path) { + (void) btrfs_subvol_remove(e->temp_path, BTRFS_REMOVE_QUOTA); + free(e->temp_path); + } + + import_compress_free(&e->compress); + + sd_event_unref(e->event); + + safe_close(e->tar_fd); + + free(e->buffer); + free(e->path); + return mfree(e); +} + +int tar_export_new( + TarExport **ret, + sd_event *event, + TarExportFinished on_finished, + void *userdata) { + + _cleanup_(tar_export_unrefp) TarExport *e = NULL; + int r; + + assert(ret); + + e = new(TarExport, 1); + if (!e) + return -ENOMEM; + + *e = (TarExport) { + .output_fd = -1, + .tar_fd = -1, + .on_finished = on_finished, + .userdata = userdata, + .quota_referenced = (uint64_t) -1, + .last_percent = (unsigned) -1, + .progress_ratelimit = { 100 * USEC_PER_MSEC, 1 }, + }; + + if (event) + e->event = sd_event_ref(event); + else { + r = sd_event_default(&e->event); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(e); + + return 0; +} + +static void tar_export_report_progress(TarExport *e) { + unsigned percent; + assert(e); + + /* Do we have any quota info? If not, we don't know anything about the progress */ + if (e->quota_referenced == (uint64_t) -1) + return; + + if (e->written_uncompressed >= e->quota_referenced) + percent = 100; + else + percent = (unsigned) ((e->written_uncompressed * UINT64_C(100)) / e->quota_referenced); + + if (percent == e->last_percent) + return; + + if (!ratelimit_below(&e->progress_ratelimit)) + return; + + sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); + log_info("Exported %u%%.", percent); + + e->last_percent = percent; +} + +static int tar_export_finish(TarExport *e) { + int r; + + assert(e); + assert(e->tar_fd >= 0); + + if (e->tar_pid > 0) { + r = wait_for_terminate_and_check("tar", e->tar_pid, WAIT_LOG); + e->tar_pid = 0; + if (r < 0) + return r; + if (r != EXIT_SUCCESS) + return -EPROTO; + } + + e->tar_fd = safe_close(e->tar_fd); + + return 0; +} + +static int tar_export_process(TarExport *e) { + ssize_t l; + int r; + + assert(e); + + if (!e->tried_splice && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { + + l = splice(e->tar_fd, NULL, e->output_fd, NULL, COPY_BUFFER_SIZE, 0); + if (l < 0) { + if (errno == EAGAIN) + return 0; + + e->tried_splice = true; + } else if (l == 0) { + r = tar_export_finish(e); + goto finish; + } else { + e->written_uncompressed += l; + e->written_compressed += l; + + tar_export_report_progress(e); + + return 0; + } + } + + while (e->buffer_size <= 0) { + uint8_t input[COPY_BUFFER_SIZE]; + + if (e->eof) { + r = tar_export_finish(e); + goto finish; + } + + l = read(e->tar_fd, input, sizeof(input)); + if (l < 0) { + r = log_error_errno(errno, "Failed to read tar file: %m"); + goto finish; + } + + if (l == 0) { + e->eof = true; + r = import_compress_finish(&e->compress, &e->buffer, &e->buffer_size, &e->buffer_allocated); + } else { + e->written_uncompressed += l; + r = import_compress(&e->compress, input, l, &e->buffer, &e->buffer_size, &e->buffer_allocated); + } + if (r < 0) { + r = log_error_errno(r, "Failed to encode: %m"); + goto finish; + } + } + + l = write(e->output_fd, e->buffer, e->buffer_size); + if (l < 0) { + if (errno == EAGAIN) + return 0; + + r = log_error_errno(errno, "Failed to write output file: %m"); + goto finish; + } + + assert((size_t) l <= e->buffer_size); + memmove(e->buffer, (uint8_t*) e->buffer + l, e->buffer_size - l); + e->buffer_size -= l; + e->written_compressed += l; + + tar_export_report_progress(e); + + return 0; + +finish: + if (e->on_finished) + e->on_finished(e, r, e->userdata); + else + sd_event_exit(e->event, r); + + return 0; +} + +static int tar_export_on_output(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + TarExport *i = userdata; + + return tar_export_process(i); +} + +static int tar_export_on_defer(sd_event_source *s, void *userdata) { + TarExport *i = userdata; + + return tar_export_process(i); +} + +int tar_export_start(TarExport *e, const char *path, int fd, ImportCompressType compress) { + _cleanup_close_ int sfd = -1; + int r; + + assert(e); + assert(path); + assert(fd >= 0); + assert(compress < _IMPORT_COMPRESS_TYPE_MAX); + assert(compress != IMPORT_COMPRESS_UNKNOWN); + + if (e->output_fd >= 0) + return -EBUSY; + + sfd = open(path, O_DIRECTORY|O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (sfd < 0) + return -errno; + + if (fstat(sfd, &e->st) < 0) + return -errno; + + r = fd_nonblock(fd, true); + if (r < 0) + return r; + + r = free_and_strdup(&e->path, path); + if (r < 0) + return r; + + e->quota_referenced = (uint64_t) -1; + + if (e->st.st_ino == 256) { /* might be a btrfs subvolume? */ + BtrfsQuotaInfo q; + + r = btrfs_subvol_get_subtree_quota_fd(sfd, 0, &q); + if (r >= 0) + e->quota_referenced = q.referenced; + + e->temp_path = mfree(e->temp_path); + + r = tempfn_random(path, NULL, &e->temp_path); + if (r < 0) + return r; + + /* Let's try to make a snapshot, if we can, so that the export is atomic */ + r = btrfs_subvol_snapshot_fd(sfd, e->temp_path, BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_RECURSIVE); + if (r < 0) { + log_debug_errno(r, "Couldn't create snapshot %s of %s, not exporting atomically: %m", e->temp_path, path); + e->temp_path = mfree(e->temp_path); + } + } + + r = import_compress_init(&e->compress, compress); + if (r < 0) + return r; + + r = sd_event_add_io(e->event, &e->output_event_source, fd, EPOLLOUT, tar_export_on_output, e); + if (r == -EPERM) { + r = sd_event_add_defer(e->event, &e->output_event_source, tar_export_on_defer, e); + if (r < 0) + return r; + + r = sd_event_source_set_enabled(e->output_event_source, SD_EVENT_ON); + } + if (r < 0) + return r; + + e->tar_fd = import_fork_tar_c(e->temp_path ?: e->path, &e->tar_pid); + if (e->tar_fd < 0) { + e->output_event_source = sd_event_source_unref(e->output_event_source); + return e->tar_fd; + } + + e->output_fd = fd; + return r; +} diff --git a/src/import/export-tar.h b/src/import/export-tar.h new file mode 100644 index 00000000..6abb7d38 --- /dev/null +++ b/src/import/export-tar.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" + +#include "import-compress.h" +#include "macro.h" + +typedef struct TarExport TarExport; + +typedef void (*TarExportFinished)(TarExport *export, int error, void *userdata); + +int tar_export_new(TarExport **export, sd_event *event, TarExportFinished on_finished, void *userdata); +TarExport* tar_export_unref(TarExport *export); + +DEFINE_TRIVIAL_CLEANUP_FUNC(TarExport*, tar_export_unref); + +int tar_export_start(TarExport *export, const char *path, int fd, ImportCompressType compress); diff --git a/src/import/export.c b/src/import/export.c new file mode 100644 index 00000000..77d24b86 --- /dev/null +++ b/src/import/export.c @@ -0,0 +1,297 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-event.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "export-raw.h" +#include "export-tar.h" +#include "fd-util.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "import-util.h" +#include "machine-image.h" +#include "main-func.h" +#include "signal-util.h" +#include "string-util.h" +#include "verbs.h" + +static ImportCompressType arg_compress = IMPORT_COMPRESS_UNKNOWN; + +static void determine_compression_from_filename(const char *p) { + + if (arg_compress != IMPORT_COMPRESS_UNKNOWN) + return; + + if (!p) { + arg_compress = IMPORT_COMPRESS_UNCOMPRESSED; + return; + } + + if (endswith(p, ".xz")) + arg_compress = IMPORT_COMPRESS_XZ; + else if (endswith(p, ".gz")) + arg_compress = IMPORT_COMPRESS_GZIP; + else if (endswith(p, ".bz2")) + arg_compress = IMPORT_COMPRESS_BZIP2; + else + arg_compress = IMPORT_COMPRESS_UNCOMPRESSED; +} + +static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + log_notice("Transfer aborted."); + sd_event_exit(sd_event_source_get_event(s), EINTR); + return 0; +} + +static void on_tar_finished(TarExport *export, int error, void *userdata) { + sd_event *event = userdata; + assert(export); + + if (error == 0) + log_info("Operation completed successfully."); + + sd_event_exit(event, abs(error)); +} + +static int export_tar(int argc, char *argv[], void *userdata) { + _cleanup_(tar_export_unrefp) TarExport *export = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(image_unrefp) Image *image = NULL; + const char *path = NULL, *local = NULL; + _cleanup_close_ int open_fd = -1; + int r, fd; + + if (machine_name_is_valid(argv[1])) { + r = image_find(IMAGE_MACHINE, argv[1], &image); + if (r == -ENOENT) + return log_error_errno(r, "Machine image %s not found.", argv[1]); + if (r < 0) + return log_error_errno(r, "Failed to look for machine %s: %m", argv[1]); + + local = image->path; + } else + local = argv[1]; + + if (argc >= 3) + path = argv[2]; + path = empty_or_dash_to_null(path); + + determine_compression_from_filename(path); + + if (path) { + open_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666); + if (open_fd < 0) + return log_error_errno(errno, "Failed to open tar image for export: %m"); + + fd = open_fd; + + log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, path, import_compress_type_to_string(arg_compress)); + } else { + _cleanup_free_ char *pretty = NULL; + + fd = STDOUT_FILENO; + + (void) fd_get_path(fd, &pretty); + log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, strna(pretty), import_compress_type_to_string(arg_compress)); + } + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); + (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); + + r = tar_export_new(&export, event, on_tar_finished, event); + if (r < 0) + return log_error_errno(r, "Failed to allocate exporter: %m"); + + r = tar_export_start(export, local, fd, arg_compress); + if (r < 0) + return log_error_errno(r, "Failed to export image: %m"); + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + log_info("Exiting."); + return -r; +} + +static void on_raw_finished(RawExport *export, int error, void *userdata) { + sd_event *event = userdata; + assert(export); + + if (error == 0) + log_info("Operation completed successfully."); + + sd_event_exit(event, abs(error)); +} + +static int export_raw(int argc, char *argv[], void *userdata) { + _cleanup_(raw_export_unrefp) RawExport *export = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(image_unrefp) Image *image = NULL; + const char *path = NULL, *local = NULL; + _cleanup_close_ int open_fd = -1; + int r, fd; + + if (machine_name_is_valid(argv[1])) { + r = image_find(IMAGE_MACHINE, argv[1], &image); + if (r == -ENOENT) + return log_error_errno(r, "Machine image %s not found.", argv[1]); + if (r < 0) + return log_error_errno(r, "Failed to look for machine %s: %m", argv[1]); + + local = image->path; + } else + local = argv[1]; + + if (argc >= 3) + path = argv[2]; + path = empty_or_dash_to_null(path); + + determine_compression_from_filename(path); + + if (path) { + open_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666); + if (open_fd < 0) + return log_error_errno(errno, "Failed to open raw image for export: %m"); + + fd = open_fd; + + log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, path, import_compress_type_to_string(arg_compress)); + } else { + _cleanup_free_ char *pretty = NULL; + + fd = STDOUT_FILENO; + + (void) fd_get_path(fd, &pretty); + log_info("Exporting '%s', saving to '%s' with compression '%s'.", local, strna(pretty), import_compress_type_to_string(arg_compress)); + } + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); + (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); + + r = raw_export_new(&export, event, on_raw_finished, event); + if (r < 0) + return log_error_errno(r, "Failed to allocate exporter: %m"); + + r = raw_export_start(export, local, fd, arg_compress); + if (r < 0) + return log_error_errno(r, "Failed to export image: %m"); + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + log_info("Exiting."); + return -r; +} + +static int help(int argc, char *argv[], void *userdata) { + + printf("%s [OPTIONS...] {COMMAND} ...\n\n" + "Export container or virtual machine images.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --format=FORMAT Select format\n\n" + "Commands:\n" + " tar NAME [FILE] Export a TAR image\n" + " raw NAME [FILE] Export a RAW image\n", + program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_FORMAT, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "format", required_argument, NULL, ARG_FORMAT }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(0, NULL, NULL); + + case ARG_VERSION: + return version(); + + case ARG_FORMAT: + if (streq(optarg, "uncompressed")) + arg_compress = IMPORT_COMPRESS_UNCOMPRESSED; + else if (streq(optarg, "xz")) + arg_compress = IMPORT_COMPRESS_XZ; + else if (streq(optarg, "gzip")) + arg_compress = IMPORT_COMPRESS_GZIP; + else if (streq(optarg, "bzip2")) + arg_compress = IMPORT_COMPRESS_BZIP2; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown format: %s", optarg); + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int export_main(int argc, char *argv[]) { + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "tar", 2, 3, 0, export_tar }, + { "raw", 2, 3, 0, export_raw }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static int run(int argc, char *argv[]) { + int r; + + setlocale(LC_ALL, ""); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + (void) ignore_signals(SIGPIPE, -1); + + return export_main(argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/import/import-common.c b/src/import/import-common.c new file mode 100644 index 00000000..2f27dda7 --- /dev/null +++ b/src/import/import-common.c @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "capability-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "import-common.h" +#include "os-util.h" +#include "process-util.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "tmpfile-util.h" +#include "util.h" + +int import_make_read_only_fd(int fd) { + int r; + + assert(fd >= 0); + + /* First, let's make this a read-only subvolume if it refers + * to a subvolume */ + r = btrfs_subvol_set_read_only_fd(fd, true); + if (IN_SET(r, -ENOTTY, -ENOTDIR, -EINVAL)) { + struct stat st; + + /* This doesn't refer to a subvolume, or the file + * system isn't even btrfs. In that, case fall back to + * chmod()ing */ + + r = fstat(fd, &st); + if (r < 0) + return log_error_errno(errno, "Failed to stat temporary image: %m"); + + /* Drop "w" flag */ + if (fchmod(fd, st.st_mode & 07555) < 0) + return log_error_errno(errno, "Failed to chmod() final image: %m"); + + return 0; + + } else if (r < 0) + return log_error_errno(r, "Failed to make subvolume read-only: %m"); + + return 0; +} + +int import_make_read_only(const char *path) { + _cleanup_close_ int fd = 1; + + fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return log_error_errno(errno, "Failed to open %s: %m", path); + + return import_make_read_only_fd(fd); +} + +int import_fork_tar_x(const char *path, pid_t *ret) { + _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; + bool use_selinux; + pid_t pid; + int r; + + assert(path); + assert(ret); + + if (pipe2(pipefd, O_CLOEXEC) < 0) + return log_error_errno(errno, "Failed to create pipe for tar: %m"); + + use_selinux = mac_selinux_use(); + + r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + uint64_t retain = + (1ULL << CAP_CHOWN) | + (1ULL << CAP_FOWNER) | + (1ULL << CAP_FSETID) | + (1ULL << CAP_MKNOD) | + (1ULL << CAP_SETFCAP) | + (1ULL << CAP_DAC_OVERRIDE); + + /* Child */ + + pipefd[1] = safe_close(pipefd[1]); + + r = rearrange_stdio(pipefd[0], -1, STDERR_FILENO); + if (r < 0) { + log_error_errno(r, "Failed to rearrange stdin/stdout: %m"); + _exit(EXIT_FAILURE); + } + + if (unshare(CLONE_NEWNET) < 0) + log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m"); + + r = capability_bounding_set_drop(retain, true); + if (r < 0) + log_error_errno(r, "Failed to drop capabilities, ignoring: %m"); + + execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", "--xattrs", "--xattrs-include=*", + use_selinux ? "--selinux" : "--no-selinux", NULL); + log_error_errno(errno, "Failed to execute tar: %m"); + _exit(EXIT_FAILURE); + } + + *ret = pid; + + return TAKE_FD(pipefd[1]); +} + +int import_fork_tar_c(const char *path, pid_t *ret) { + _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; + bool use_selinux; + pid_t pid; + int r; + + assert(path); + assert(ret); + + if (pipe2(pipefd, O_CLOEXEC) < 0) + return log_error_errno(errno, "Failed to create pipe for tar: %m"); + + use_selinux = mac_selinux_use(); + + r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + uint64_t retain = (1ULL << CAP_DAC_OVERRIDE); + + /* Child */ + + pipefd[0] = safe_close(pipefd[0]); + + r = rearrange_stdio(-1, pipefd[1], STDERR_FILENO); + if (r < 0) { + log_error_errno(r, "Failed to rearrange stdin/stdout: %m"); + _exit(EXIT_FAILURE); + } + + if (unshare(CLONE_NEWNET) < 0) + log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m"); + + r = capability_bounding_set_drop(retain, true); + if (r < 0) + log_error_errno(r, "Failed to drop capabilities, ignoring: %m"); + + execlp("tar", "tar", "-C", path, "-c", "--xattrs", "--xattrs-include=*", + use_selinux ? "--selinux" : "--no-selinux", ".", NULL); + log_error_errno(errno, "Failed to execute tar: %m"); + _exit(EXIT_FAILURE); + } + + *ret = pid; + + return TAKE_FD(pipefd[0]); +} + +int import_mangle_os_tree(const char *path) { + _cleanup_closedir_ DIR *d = NULL, *cd = NULL; + _cleanup_free_ char *child = NULL, *t = NULL; + const char *joined; + struct dirent *de; + int r; + + assert(path); + + /* Some tarballs contain a single top-level directory that contains the actual OS directory tree. Try to + * recognize this, and move the tree one level up. */ + + r = path_is_os_tree(path); + if (r < 0) + return log_error_errno(r, "Failed to determine whether '%s' is an OS tree: %m", path); + if (r > 0) { + log_debug("Directory tree '%s' is a valid OS tree.", path); + return 0; + } + + log_debug("Directory tree '%s' is not recognizable as OS tree, checking whether to rearrange it.", path); + + d = opendir(path); + if (!d) + return log_error_errno(r, "Failed to open directory '%s': %m", path); + + errno = 0; + de = readdir_no_dot(d); + if (!de) { + if (errno != 0) + return log_error_errno(errno, "Failed to iterate through directory '%s': %m", path); + + log_debug("Directory '%s' is empty, leaving it as it is.", path); + return 0; + } + + child = strdup(de->d_name); + if (!child) + return log_oom(); + + errno = 0; + de = readdir_no_dot(d); + if (de) { + if (errno != 0) + return log_error_errno(errno, "Failed to iterate through directory '%s': %m", path); + + log_debug("Directory '%s' does not look like a directory tree, and has multiple children, leaving as it is.", path); + return 0; + } + + joined = prefix_roota(path, child); + r = path_is_os_tree(joined); + if (r == -ENOTDIR) { + log_debug("Directory '%s' does not look like a directory tree, and contains a single regular file only, leaving as it is.", path); + return 0; + } + if (r < 0) + return log_error_errno(r, "Failed to determine whether '%s' is an OS tree: %m", joined); + if (r == 0) { + log_debug("Neither '%s' nor '%s' is a valid OS tree, leaving them as they are.", path, joined); + return 0; + } + + /* Nice, we have checked now: + * + * 1. The top-level directory does not qualify as OS tree + * 1. The top-level directory only contains one item + * 2. That item is a directory + * 3. And that directory qualifies as OS tree + * + * Let's now rearrange things, moving everything in the inner directory one level up */ + + cd = xopendirat(dirfd(d), child, O_NOFOLLOW); + if (!cd) + return log_error_errno(errno, "Can't open directory '%s': %m", joined); + + log_info("Rearranging '%s', moving OS tree one directory up.", joined); + + /* Let's rename the child to an unguessable name so that we can be sure all files contained in it can be + * safely moved up and won't collide with the name. */ + r = tempfn_random(child, NULL, &t); + if (r < 0) + return log_oom(); + r = rename_noreplace(dirfd(d), child, dirfd(d), t); + if (r < 0) + return log_error_errno(r, "Unable to rename '%s' to '%s/%s': %m", joined, path, t); + + FOREACH_DIRENT_ALL(de, cd, return log_error_errno(errno, "Failed to iterate through directory '%s': %m", joined)) { + if (dot_or_dot_dot(de->d_name)) + continue; + + r = rename_noreplace(dirfd(cd), de->d_name, dirfd(d), de->d_name); + if (r < 0) + return log_error_errno(r, "Unable to move '%s/%s/%s' to '%s/%s': %m", path, t, de->d_name, path, de->d_name); + } + + if (unlinkat(dirfd(d), t, AT_REMOVEDIR) < 0) + return log_error_errno(errno, "Failed to remove temporary directory '%s/%s': %m", path, t); + + log_info("Successfully rearranged OS tree."); + + return 0; +} diff --git a/src/import/import-common.h b/src/import/import-common.h new file mode 100644 index 00000000..94d224f4 --- /dev/null +++ b/src/import/import-common.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int import_make_read_only_fd(int fd); +int import_make_read_only(const char *path); + +int import_fork_tar_c(const char *path, pid_t *ret); +int import_fork_tar_x(const char *path, pid_t *ret); + +int import_mangle_os_tree(const char *path); diff --git a/src/import/import-compress.c b/src/import/import-compress.c new file mode 100644 index 00000000..3fbd0677 --- /dev/null +++ b/src/import/import-compress.c @@ -0,0 +1,466 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "import-compress.h" +#include "string-table.h" +#include "util.h" + +void import_compress_free(ImportCompress *c) { + assert(c); + + if (c->type == IMPORT_COMPRESS_XZ) + lzma_end(&c->xz); + else if (c->type == IMPORT_COMPRESS_GZIP) { + if (c->encoding) + deflateEnd(&c->gzip); + else + inflateEnd(&c->gzip); +#if HAVE_BZIP2 + } else if (c->type == IMPORT_COMPRESS_BZIP2) { + if (c->encoding) + BZ2_bzCompressEnd(&c->bzip2); + else + BZ2_bzDecompressEnd(&c->bzip2); +#endif + } + + c->type = IMPORT_COMPRESS_UNKNOWN; +} + +int import_uncompress_detect(ImportCompress *c, const void *data, size_t size) { + static const uint8_t xz_signature[] = { + 0xfd, '7', 'z', 'X', 'Z', 0x00 + }; + static const uint8_t gzip_signature[] = { + 0x1f, 0x8b + }; + static const uint8_t bzip2_signature[] = { + 'B', 'Z', 'h' + }; + + int r; + + assert(c); + + if (c->type != IMPORT_COMPRESS_UNKNOWN) + return 1; + + if (size < MAX3(sizeof(xz_signature), + sizeof(gzip_signature), + sizeof(bzip2_signature))) + return 0; + + assert(data); + + if (memcmp(data, xz_signature, sizeof(xz_signature)) == 0) { + lzma_ret xzr; + + xzr = lzma_stream_decoder(&c->xz, UINT64_MAX, LZMA_TELL_UNSUPPORTED_CHECK | LZMA_CONCATENATED); + if (xzr != LZMA_OK) + return -EIO; + + c->type = IMPORT_COMPRESS_XZ; + + } else if (memcmp(data, gzip_signature, sizeof(gzip_signature)) == 0) { + r = inflateInit2(&c->gzip, 15+16); + if (r != Z_OK) + return -EIO; + + c->type = IMPORT_COMPRESS_GZIP; + +#if HAVE_BZIP2 + } else if (memcmp(data, bzip2_signature, sizeof(bzip2_signature)) == 0) { + r = BZ2_bzDecompressInit(&c->bzip2, 0, 0); + if (r != BZ_OK) + return -EIO; + + c->type = IMPORT_COMPRESS_BZIP2; +#endif + } else + c->type = IMPORT_COMPRESS_UNCOMPRESSED; + + c->encoding = false; + + return 1; +} + +int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata) { + int r; + + assert(c); + assert(callback); + + r = import_uncompress_detect(c, data, size); + if (r <= 0) + return r; + + if (c->encoding) + return -EINVAL; + + if (size <= 0) + return 1; + + assert(data); + + switch (c->type) { + + case IMPORT_COMPRESS_UNCOMPRESSED: + r = callback(data, size, userdata); + if (r < 0) + return r; + + break; + + case IMPORT_COMPRESS_XZ: + c->xz.next_in = data; + c->xz.avail_in = size; + + while (c->xz.avail_in > 0) { + uint8_t buffer[16 * 1024]; + lzma_ret lzr; + + c->xz.next_out = buffer; + c->xz.avail_out = sizeof(buffer); + + lzr = lzma_code(&c->xz, LZMA_RUN); + if (!IN_SET(lzr, LZMA_OK, LZMA_STREAM_END)) + return -EIO; + + r = callback(buffer, sizeof(buffer) - c->xz.avail_out, userdata); + if (r < 0) + return r; + } + + break; + + case IMPORT_COMPRESS_GZIP: + c->gzip.next_in = (void*) data; + c->gzip.avail_in = size; + + while (c->gzip.avail_in > 0) { + uint8_t buffer[16 * 1024]; + + c->gzip.next_out = buffer; + c->gzip.avail_out = sizeof(buffer); + + r = inflate(&c->gzip, Z_NO_FLUSH); + if (!IN_SET(r, Z_OK, Z_STREAM_END)) + return -EIO; + + r = callback(buffer, sizeof(buffer) - c->gzip.avail_out, userdata); + if (r < 0) + return r; + } + + break; + +#if HAVE_BZIP2 + case IMPORT_COMPRESS_BZIP2: + c->bzip2.next_in = (void*) data; + c->bzip2.avail_in = size; + + while (c->bzip2.avail_in > 0) { + uint8_t buffer[16 * 1024]; + + c->bzip2.next_out = (char*) buffer; + c->bzip2.avail_out = sizeof(buffer); + + r = BZ2_bzDecompress(&c->bzip2); + if (!IN_SET(r, BZ_OK, BZ_STREAM_END)) + return -EIO; + + r = callback(buffer, sizeof(buffer) - c->bzip2.avail_out, userdata); + if (r < 0) + return r; + } + + break; +#endif + + default: + assert_not_reached("Unknown compression"); + } + + return 1; +} + +int import_compress_init(ImportCompress *c, ImportCompressType t) { + int r; + + assert(c); + + switch (t) { + + case IMPORT_COMPRESS_XZ: { + lzma_ret xzr; + + xzr = lzma_easy_encoder(&c->xz, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64); + if (xzr != LZMA_OK) + return -EIO; + + c->type = IMPORT_COMPRESS_XZ; + break; + } + + case IMPORT_COMPRESS_GZIP: + r = deflateInit2(&c->gzip, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY); + if (r != Z_OK) + return -EIO; + + c->type = IMPORT_COMPRESS_GZIP; + break; + +#if HAVE_BZIP2 + case IMPORT_COMPRESS_BZIP2: + r = BZ2_bzCompressInit(&c->bzip2, 9, 0, 0); + if (r != BZ_OK) + return -EIO; + + c->type = IMPORT_COMPRESS_BZIP2; + break; +#endif + + case IMPORT_COMPRESS_UNCOMPRESSED: + c->type = IMPORT_COMPRESS_UNCOMPRESSED; + break; + + default: + return -EOPNOTSUPP; + } + + c->encoding = true; + return 0; +} + +static int enlarge_buffer(void **buffer, size_t *buffer_size, size_t *buffer_allocated) { + size_t l; + void *p; + + if (*buffer_allocated > *buffer_size) + return 0; + + l = MAX(16*1024U, (*buffer_size * 2)); + p = realloc(*buffer, l); + if (!p) + return -ENOMEM; + + *buffer = p; + *buffer_allocated = l; + + return 1; +} + +int import_compress(ImportCompress *c, const void *data, size_t size, void **buffer, size_t *buffer_size, size_t *buffer_allocated) { + int r; + + assert(c); + assert(buffer); + assert(buffer_size); + assert(buffer_allocated); + + if (!c->encoding) + return -EINVAL; + + if (size <= 0) + return 0; + + assert(data); + + *buffer_size = 0; + + switch (c->type) { + + case IMPORT_COMPRESS_XZ: + + c->xz.next_in = data; + c->xz.avail_in = size; + + while (c->xz.avail_in > 0) { + lzma_ret lzr; + + r = enlarge_buffer(buffer, buffer_size, buffer_allocated); + if (r < 0) + return r; + + c->xz.next_out = (uint8_t*) *buffer + *buffer_size; + c->xz.avail_out = *buffer_allocated - *buffer_size; + + lzr = lzma_code(&c->xz, LZMA_RUN); + if (lzr != LZMA_OK) + return -EIO; + + *buffer_size += (*buffer_allocated - *buffer_size) - c->xz.avail_out; + } + + break; + + case IMPORT_COMPRESS_GZIP: + + c->gzip.next_in = (void*) data; + c->gzip.avail_in = size; + + while (c->gzip.avail_in > 0) { + r = enlarge_buffer(buffer, buffer_size, buffer_allocated); + if (r < 0) + return r; + + c->gzip.next_out = (uint8_t*) *buffer + *buffer_size; + c->gzip.avail_out = *buffer_allocated - *buffer_size; + + r = deflate(&c->gzip, Z_NO_FLUSH); + if (r != Z_OK) + return -EIO; + + *buffer_size += (*buffer_allocated - *buffer_size) - c->gzip.avail_out; + } + + break; + +#if HAVE_BZIP2 + case IMPORT_COMPRESS_BZIP2: + + c->bzip2.next_in = (void*) data; + c->bzip2.avail_in = size; + + while (c->bzip2.avail_in > 0) { + r = enlarge_buffer(buffer, buffer_size, buffer_allocated); + if (r < 0) + return r; + + c->bzip2.next_out = (void*) ((uint8_t*) *buffer + *buffer_size); + c->bzip2.avail_out = *buffer_allocated - *buffer_size; + + r = BZ2_bzCompress(&c->bzip2, BZ_RUN); + if (r != BZ_RUN_OK) + return -EIO; + + *buffer_size += (*buffer_allocated - *buffer_size) - c->bzip2.avail_out; + } + + break; +#endif + + case IMPORT_COMPRESS_UNCOMPRESSED: + + if (*buffer_allocated < size) { + void *p; + + p = realloc(*buffer, size); + if (!p) + return -ENOMEM; + + *buffer = p; + *buffer_allocated = size; + } + + memcpy(*buffer, data, size); + *buffer_size = size; + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +int import_compress_finish(ImportCompress *c, void **buffer, size_t *buffer_size, size_t *buffer_allocated) { + int r; + + assert(c); + assert(buffer); + assert(buffer_size); + assert(buffer_allocated); + + if (!c->encoding) + return -EINVAL; + + *buffer_size = 0; + + switch (c->type) { + + case IMPORT_COMPRESS_XZ: { + lzma_ret lzr; + + c->xz.avail_in = 0; + + do { + r = enlarge_buffer(buffer, buffer_size, buffer_allocated); + if (r < 0) + return r; + + c->xz.next_out = (uint8_t*) *buffer + *buffer_size; + c->xz.avail_out = *buffer_allocated - *buffer_size; + + lzr = lzma_code(&c->xz, LZMA_FINISH); + if (!IN_SET(lzr, LZMA_OK, LZMA_STREAM_END)) + return -EIO; + + *buffer_size += (*buffer_allocated - *buffer_size) - c->xz.avail_out; + } while (lzr != LZMA_STREAM_END); + + break; + } + + case IMPORT_COMPRESS_GZIP: + c->gzip.avail_in = 0; + + do { + r = enlarge_buffer(buffer, buffer_size, buffer_allocated); + if (r < 0) + return r; + + c->gzip.next_out = (uint8_t*) *buffer + *buffer_size; + c->gzip.avail_out = *buffer_allocated - *buffer_size; + + r = deflate(&c->gzip, Z_FINISH); + if (!IN_SET(r, Z_OK, Z_STREAM_END)) + return -EIO; + + *buffer_size += (*buffer_allocated - *buffer_size) - c->gzip.avail_out; + } while (r != Z_STREAM_END); + + break; + +#if HAVE_BZIP2 + case IMPORT_COMPRESS_BZIP2: + c->bzip2.avail_in = 0; + + do { + r = enlarge_buffer(buffer, buffer_size, buffer_allocated); + if (r < 0) + return r; + + c->bzip2.next_out = (void*) ((uint8_t*) *buffer + *buffer_size); + c->bzip2.avail_out = *buffer_allocated - *buffer_size; + + r = BZ2_bzCompress(&c->bzip2, BZ_FINISH); + if (!IN_SET(r, BZ_FINISH_OK, BZ_STREAM_END)) + return -EIO; + + *buffer_size += (*buffer_allocated - *buffer_size) - c->bzip2.avail_out; + } while (r != BZ_STREAM_END); + + break; +#endif + + case IMPORT_COMPRESS_UNCOMPRESSED: + break; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static const char* const import_compress_type_table[_IMPORT_COMPRESS_TYPE_MAX] = { + [IMPORT_COMPRESS_UNKNOWN] = "unknown", + [IMPORT_COMPRESS_UNCOMPRESSED] = "uncompressed", + [IMPORT_COMPRESS_XZ] = "xz", + [IMPORT_COMPRESS_GZIP] = "gzip", +#if HAVE_BZIP2 + [IMPORT_COMPRESS_BZIP2] = "bzip2", +#endif +}; + +DEFINE_STRING_TABLE_LOOKUP(import_compress_type, ImportCompressType); diff --git a/src/import/import-compress.h b/src/import/import-compress.h new file mode 100644 index 00000000..859bd0e1 --- /dev/null +++ b/src/import/import-compress.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if HAVE_BZIP2 +#include +#endif +#include +#include +#include + +#include "macro.h" + +typedef enum ImportCompressType { + IMPORT_COMPRESS_UNKNOWN, + IMPORT_COMPRESS_UNCOMPRESSED, + IMPORT_COMPRESS_XZ, + IMPORT_COMPRESS_GZIP, + IMPORT_COMPRESS_BZIP2, + _IMPORT_COMPRESS_TYPE_MAX, + _IMPORT_COMPRESS_TYPE_INVALID = -1, +} ImportCompressType; + +typedef struct ImportCompress { + ImportCompressType type; + bool encoding; + union { + lzma_stream xz; + z_stream gzip; +#if HAVE_BZIP2 + bz_stream bzip2; +#endif + }; +} ImportCompress; + +typedef int (*ImportCompressCallback)(const void *data, size_t size, void *userdata); + +void import_compress_free(ImportCompress *c); + +int import_uncompress_detect(ImportCompress *c, const void *data, size_t size); +int import_uncompress(ImportCompress *c, const void *data, size_t size, ImportCompressCallback callback, void *userdata); + +int import_compress_init(ImportCompress *c, ImportCompressType t); +int import_compress(ImportCompress *c, const void *data, size_t size, void **buffer, size_t *buffer_size, size_t *buffer_allocated); +int import_compress_finish(ImportCompress *c, void **buffer, size_t *buffer_size, size_t *buffer_allocated); + +const char* import_compress_type_to_string(ImportCompressType t) _const_; +ImportCompressType import_compress_type_from_string(const char *s) _pure_; diff --git a/src/import/import-fs.c b/src/import/import-fs.c new file mode 100644 index 00000000..468303a6 --- /dev/null +++ b/src/import/import-fs.c @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "import-common.h" +#include "import-util.h" +#include "machine-image.h" +#include "mkdir.h" +#include "ratelimit.h" +#include "rm-rf.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "verbs.h" + +static bool arg_force = false; +static bool arg_read_only = false; +static const char *arg_image_root = "/var/lib/machines"; + +typedef struct ProgressInfo { + RateLimit limit; + char *path; + uint64_t size; + bool started; + bool logged_incomplete; +} ProgressInfo; + +static volatile sig_atomic_t cancelled = false; + +static void sigterm_sigint(int sig) { + cancelled = true; +} + +static void progress_info_free(ProgressInfo *p) { + free(p->path); +} + +static void progress_show(ProgressInfo *p) { + assert(p); + + /* Show progress only every now and then. */ + if (!ratelimit_below(&p->limit)) + return; + + /* Suppress the first message, start with the second one */ + if (!p->started) { + p->started = true; + return; + } + + /* Mention the list is incomplete before showing first output. */ + if (!p->logged_incomplete) { + log_notice("(Note, file list shown below is incomplete, and is intended as sporadic progress report only.)"); + p->logged_incomplete = true; + } + + if (p->size == 0) + log_info("Copying tree, currently at '%s'...", p->path); + else { + char buffer[FORMAT_BYTES_MAX]; + + log_info("Copying tree, currently at '%s' (@%s)...", p->path, format_bytes(buffer, sizeof(buffer), p->size)); + } +} + +static int progress_path(const char *path, const struct stat *st, void *userdata) { + ProgressInfo *p = userdata; + int r; + + assert(p); + + if (cancelled) + return -EOWNERDEAD; + + r = free_and_strdup(&p->path, path); + if (r < 0) + return r; + + p->size = 0; + + progress_show(p); + return 0; +} + +static int progress_bytes(uint64_t nbytes, void *userdata) { + ProgressInfo *p = userdata; + + assert(p); + assert(p->size != UINT64_MAX); + + if (cancelled) + return -EOWNERDEAD; + + p->size += nbytes; + + progress_show(p); + return 0; +} + +static int import_fs(int argc, char *argv[], void *userdata) { + _cleanup_(rm_rf_subvolume_and_freep) char *temp_path = NULL; + _cleanup_(progress_info_free) ProgressInfo progress = {}; + const char *path = NULL, *local = NULL, *final_path; + _cleanup_close_ int open_fd = -1; + struct sigaction old_sigint_sa, old_sigterm_sa; + static const struct sigaction sa = { + .sa_handler = sigterm_sigint, + .sa_flags = SA_RESTART, + }; + int r, fd; + + if (argc >= 2) + path = argv[1]; + path = empty_or_dash_to_null(path); + + if (argc >= 3) + local = argv[2]; + else if (path) + local = basename(path); + local = empty_or_dash_to_null(local); + + if (local) { + if (!machine_name_is_valid(local)) { + log_error("Local image name '%s' is not valid.", local); + return -EINVAL; + } + + if (!arg_force) { + r = image_find(IMAGE_MACHINE, local, NULL); + if (r < 0) { + if (r != -ENOENT) + return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); + } else { + log_error("Image '%s' already exists.", local); + return -EEXIST; + } + } + } else + local = "imported"; + + if (path) { + open_fd = open(path, O_DIRECTORY|O_RDONLY|O_CLOEXEC); + if (open_fd < 0) + return log_error_errno(errno, "Failed to open directory to import: %m"); + + fd = open_fd; + + log_info("Importing '%s', saving as '%s'.", path, local); + } else { + _cleanup_free_ char *pretty = NULL; + + fd = STDIN_FILENO; + + (void) fd_get_path(fd, &pretty); + log_info("Importing '%s', saving as '%s'.", strempty(pretty), local); + } + + final_path = prefix_roota(arg_image_root, local); + + r = tempfn_random(final_path, NULL, &temp_path); + if (r < 0) + return log_oom(); + + (void) mkdir_parents_label(temp_path, 0700); + + progress.limit = (RateLimit) { 200*USEC_PER_MSEC, 1 }; + + /* Hook into SIGINT/SIGTERM, so that we can cancel things then */ + assert(sigaction(SIGINT, &sa, &old_sigint_sa) >= 0); + assert(sigaction(SIGTERM, &sa, &old_sigterm_sa) >= 0); + + r = btrfs_subvol_snapshot_fd_full( + fd, + temp_path, + BTRFS_SNAPSHOT_FALLBACK_COPY|BTRFS_SNAPSHOT_RECURSIVE|BTRFS_SNAPSHOT_FALLBACK_DIRECTORY|BTRFS_SNAPSHOT_QUOTA, + progress_path, + progress_bytes, + &progress); + if (r == -EOWNERDEAD) { /* SIGINT + SIGTERM cause this, see signal handler above */ + log_error("Copy cancelled."); + goto finish; + } + if (r < 0) { + log_error_errno(r, "Failed to copy directory: %m"); + goto finish; + } + + r = import_mangle_os_tree(temp_path); + if (r < 0) + goto finish; + + (void) import_assign_pool_quota_and_warn(temp_path); + + if (arg_read_only) { + r = import_make_read_only(temp_path); + if (r < 0) { + log_error_errno(r, "Failed to make directory read-only: %m"); + goto finish; + } + } + + if (arg_force) + (void) rm_rf(final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + + r = rename_noreplace(AT_FDCWD, temp_path, AT_FDCWD, final_path); + if (r < 0) { + log_error_errno(r, "Failed to move image into place: %m"); + goto finish; + } + + temp_path = mfree(temp_path); + + log_info("Exiting."); + +finish: + /* Put old signal handlers into place */ + assert(sigaction(SIGINT, &old_sigint_sa, NULL) >= 0); + assert(sigaction(SIGTERM, &old_sigterm_sa, NULL) >= 0); + + return 0; +} + +static int help(int argc, char *argv[], void *userdata) { + + printf("%s [OPTIONS...] {COMMAND} ...\n\n" + "Import container images from a file system.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --force Force creation of image\n" + " --image-root=PATH Image root directory\n" + " --read-only Create a read-only image\n\n" + "Commands:\n" + " run DIRECTORY [NAME] Import a directory\n", + program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_FORCE, + ARG_IMAGE_ROOT, + ARG_READ_ONLY, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "force", no_argument, NULL, ARG_FORCE }, + { "image-root", required_argument, NULL, ARG_IMAGE_ROOT }, + { "read-only", no_argument, NULL, ARG_READ_ONLY }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(0, NULL, NULL); + + case ARG_VERSION: + return version(); + + case ARG_FORCE: + arg_force = true; + break; + + case ARG_IMAGE_ROOT: + arg_image_root = optarg; + break; + + case ARG_READ_ONLY: + arg_read_only = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int import_fs_main(int argc, char *argv[]) { + + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "run", 2, 3, 0, import_fs }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +int main(int argc, char *argv[]) { + int r; + + setlocale(LC_ALL, ""); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + + r = import_fs_main(argc, argv); + +finish: + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/import/import-pubring.gpg b/src/import/import-pubring.gpg new file mode 100644 index 0000000000000000000000000000000000000000..be27776896f30f580b03ad79d733483f81c8d117 GIT binary patch literal 9551 zcmb7~Wl$YTyQMc9hX5OQcXxN!;10oIo9skOHiLVy6vh=yK}A1e0|RuSW}%44~W8|R2{x{W~hvPDlp zbCsPxk)GBqx6WR)7Dw|Xm<3texYI1Ud8nSwCW>plN|MgCROOMks$Qr$KhUk7*s3Or z=g6HIT+6E;)Ck^NwtEv!u3*a2PSkY*jEGHeSV*Zf@o{kh;!bh?_A%P-&00z|SIgCM ziTF*Jp5x)mjXYx5n_XG9oKq|9E=X~TCy0TKx=UxB@7e#nQ-6#>2Vh5@thdzbDm>bM)4 z(6B$^dk;+pZUPSPx!0?J^eiU!n^kRonOR5ikC|nf3ibPP{?E%@8bHv|D|u~BfCsynigr=8m6^a#47h1%4@7X z2c2hPU5tP9&HvHCt)vBj3ITwqXOS{Db8t2$Q8PDnus1Vy_9CHSW1}Szu=vlm$Ulpt zvxBv{sVkF%Ggv4R$ODBA0R)gi1OFBh5FZ5w5grZ}5(t9{2ZTpJgu((sLI8;%fY@IF z2=Jh#>F1c-%$iIsLzEB8gv-;)Fv0`0ocy#Yy10RLJik6GN#}Khsv62#P2b7MmqAJi zan-kYR(IB=ePrOB?Mcgmrsnon@0=0~@m-tHlpwhf#_T-*wuo@59sP&lQ>;mLx=qxR z^(rxe{DR_*Hzg-j|M$cC3KTh~d_T$V^yVn)@bo4oW@B<<`r z{@c3veGkLC>;soBw94)*&2@{uxf(}mm=Y4ld)ZYYs^HS}Qiwm{u zephfO0L+j8+?gAx)sQDLlZk;|^j^S08nJ+5f0JZRj1$e#VLb@z;-Bc@W*{BgK@)ez zkfMvR7CsvgB^$Lfk2WNhg=?i?;~?oLwGY4gX-juEhPGzZ(e%>@-%q(P&qCs)mRPAQ zgzB?wIN`M+PUI9tA|L6mE@R0<;$H<@D_957mZ}pb9lh5t2)1x5bn4vWj-XAqI5?UF zj+Bl=0^N~$jGhEKUtwsGkmQrE%PZWdY3n3GlVH6pA8f4aE>-6%+F8B^Q0l-nx~*Ih zp};VlI?|!xYwuNo-F9n8>&!KERH_UHnOgU!z)*bAZ&gMEq~^P`^$7IQ0}wLG167C= zTW)gmSU4=zKmcS5)ISCU0s(Sg)dyHS-S0Yv18f58iqQtpHaoSw@CqXREsxD-!tlIQp%W>t6@Y4sWj3^0RR$d|{!(1g_-5t1v-&f7 ziE;^n8vDTLXnE4GK7D5obrhPadUw>KZ6J&2^8|OJO>?MBv*R&J3>>kIeiz{e1|Zc( zDw@%iGK68WJLup(rf%3FB4PeX#b~$>+Hf6P&O zZG_~o@p)%a=7*JjoNgl-70ImI&%>q|7ZRtp?Q%W)MUL;{Yi{SL zbYH*`hre_vxFkD`uRO@WBx{glP+6GDI-RGCwx1iZyz>Jh>F9ViZRjH2j9OAQhA^|n zU2ABPtPa^{h2})k56%%Qby5PIJtw}-lAm5~dxL@m2eWn~4xnLA4S!j*Y@${>ttmL6 za)8I;f|Xyo8uV8IkkBANklqx;sVAp(z^d84Rj~SM_If7e5mBD`aF3v%izKAwdnsMlt?}WPd()J8+%MYQLI6v{l zxWKIGH%2t89V3B-84SL^^2C&al8wboY};OVZbylWngg{tS|(dT^I)`JJtKJ&4m5Hs z3&zQ1pK72`|B}{~YU7G{m|d{Nv-W|AQ!yc$oL9!Mk3>!1LK+8N`z34-PK-|4aia@p zQ#;T3a92l#vI;JG;hEz;K|C~nsLon31R|ie-ZA!x^2K?=3)|ZoD*&YLtj9gp=mb$0 zpk&FAa~UF^8T)8{@1*SvCMtwmh0CG@>|>k4Y*P%>R$-mO-S~pLQn%nITr+;+7gj{J z73RXvKx|U9Sti^z+!tJs+L#Gb_NI{yP~@)5tB6!&?;VvbU44x0c88%s6z^*)C-*@( zC@uW>sljd{5^JwZ4au>D)E9NU{AI^nQ$#16A)sHe#+xPH!|XlKTSQb95x zZ!Fi`3kA2b?G|BZu2oY!@L>g{~?#FVi z>=1Q!LUL#u2_%NX`72J~|BaJR|1~w*H$Z?Y?Jz^jxMK=6mT~g@gMt@6leH~8k^o5| zBNX@P+x*eE)`zCqaY@S`(JVg{N^O(bEn{;vE6Vy zdPoUV(#woH-8|uD)0F4kmg?4ZNpe-7U9knpGtEWCd6cM6&(rWF>=K&>(zNV}*_9PQ zhR6FneGA!N=w>rwb# z$_8=nSjhkKHoh$1?C{9gBSgG7vloNhrt~-lAbI6>qOmKhz2>)Z(kpFxueq$E)lS>| zVd|ota(bpfC*P3MKd9`6o=DH7G+%`TWo>p#Zb&RpxcX7xVd6K5D76RaI!`}S)-TQ9 z`Qw$Ra4AHrf$b!t)44Na88*Fo9bsSH57X zXN^V|Rr!(jI>^}^FM)%L?V@8%g4{?w-;vD2`D5SaPUB(RHkqwOwyU}Oy|#uR1ZR$= znf8fL)DjsqM32}u%&Ur<(943Vzf&XaKiJwj_!qV=5V3#vK0MV9?(YeB+_+j4?ebC! z5RlF*7%&f~3jI-e#{VY?Dx zkcT0z&+!To?3n37bR%r91)5E#cR`o|NP|ngO2*AX*o_1Tf_YQ&P~Cq%EfWIVBW}sx z04c`G1#WX@FMZgE?ywD4iD}@JlmMO?vl_P8(B0l|;XEAtJmuA%7_$UF;mvWXRF+&q z1S}=>mp1*Z3DgAVGfzv3jcW!IBb63?d!un#y;U)oeW-bxBOr&PAi#jj|J987u-~f zrq&Ob-n6#<$Vao>Llw^ceTrSl3rYP1{WaJSNZjX zAdk6MxJzVjq&y$ZhT#My(q*btLO5%)!+b z!|$h8;vuzfj<_KxZ?`G`&gFIyI7PJ?p~>A6yOwAeXC4grsB0cXD)U0s3QDxym*~9 z;Bm}Jz&kFzNmc^3B9g|g`=dG^eYuE~B!n{3NY=cy1N+C|IVn4ec(o3%n}p9kPln*r zQ-DDmG~8k_zd2_wEq@avi2u8SE8h03 zbjn@UBv8RGN85tasNS@BW*r0L$b;`6M&DcR`8(O{NZ%bd7-m+Vlv?wOv;0F(rZB>3 zEd|({^)aP07@_$xqCIc={@{mA_y74586vCAp)c_zy_Kb%BhS5-@7clYlf&C(Ng^Cq z^~5^OlZ!alo9t#Ds-Q0lvWMG2W=IrhNbQYwZ}jZG@|>N15q~Btkki&&eCQEzg@#JW z8f#vX2HYY5tzGfk9c_614!L@1`)gLW2s?uAr2=(T^<2@KuMz8QYrHp>Mw(>~EHb$z zWl6yI_0a0IxhUDAcaate8=y#NeqY=zZ;TTj?bJG#6dY53ArwNBHY&SE-2TZG7Y>_b zHyLwcB7ul1(x1$IWE#ldRRXO@H2A^O+@$X^(tZ#ICs1Ry;*rqbyqgP(U!4ZsN z>F&McB+#_0|L>{LFRTUG?VI?v52`f$nD(U%-e;6p1@R0#ZN_l0Xf|Vh<8oM`lq(3* zzxbjL#h=3lzAw4eGBb|iLcRYea7q21e51XtU*DJj@^OoO@+s7!2q5Pwmi&LWW!C>; zTmD-}|D6Gu+Wo=JDQaE4K1ccR?ky*N8&oHGfI?0lM~eu}Gz(nqm&Q@Q{$=vRb&ylA zk+3&!PQ&>-)TM5xWFp0$&@CUoaVT@8rh#06^OW&i{8rzzMb2IDSL_yBUpl;H!u-f% zl3dPTVg|pM#>h*G<9&{pv`MkGzT=0e0(<;SaovXze`(c95X!3VDPtJbq((cAKC@R~ z`sHUx3#mx$87uEUI~J65<(z?0GvbSc_}PjcN=S}0Kti1~xoN7mU=uqDcC(Nmesa)NeVJklQ(xcK4OMk#p< zX8%EDjh6;4iVtuR%Wtr*dhnF6-rsb$ToNntz;gC3DO0c7CY@m)#tMT)BQ!YbDMAca zs2+_AA}Xo{0#~~X z4>J{`So;w@B5jWLAD#&Pp~8w($eJs^W(q^$H6xdX;k2c`y`@N^Aj+DYVe8ZnLF*%k zSwKD5;HRw4#l}Gk^9F#CgIC0e*%n_O9Sk-vW?g28={ibd^r8#PVUK<@hn9y3TkhIA zkYtg~MJH0C6id5fEmKtBPCe}XA>AAtW+FJtA+gi0rQyvG)EkmXBURD=`Km^E2;xd5 zJV?C=@hnC|$GP!U{kJXut((8v@-Rw<{z!cA1x9VA?J@<7znKJ8d23UIT@ieS=bxUa zP8PU?gGgzNt>Ve%-~b#B&E{$5mblTrpbC4I-qDq|tP7%_b`GELW|vw%7#r_9t1BDm z^1de~<`}EC$ioTIRg;>*@~rhk6ijLoFlz|FecW6kGyF0%rOdNgm#WtzqY!zPY%hY) zs>4$bSaIR1X-Ss#uO;j+-!a9`9K5XRj@xZGrgL>zZYL(2L&89t`8}u&W9-`pP;^_r z0IY1upNo@^d~|{pa8kF8q)Dck#M?>u#mG6$Tk?=cCA;f70LN|Ye&t@$Z zYY3LVd||!a2t0+ZOIyd()!CiIDht@~S_2S`iVqbCYi&bDYsBM-1IaHXdd&C(RXo*{ z9zA?Ng!&K&a1ZX~$nvDZzbn^k?uhP)s3L+wQj3A-5NJh7;;6%AaM0K4(wgpZ zFEsv8rj49cwn^;Dh1YPmVS4qZj4boaDCAWyY%s3ZzzK7PxU&d643lR&C^ygixnrc`e@4aG(8qdvh;clIL0 zF3P?pyYY_*-QoClMU6qqhvk9{HKkNC3AFlt!JyG8ce+Xb{v$J`w`R%x7s;PZY`a+g z{u%X1dZ*~nQsCRF(Xt#*J2U$S%gTIHXF9KSuEBL+d1`RBpRrxV!*xV`W<~32 z_Kq^4B!L(jF}3<(qqLsh#&f;Tp{uiy?h~Xg_O(o$tfSNArBim|0`JqQ`R{=YA)MPA z8J)W1O12?UR67$xJJH=W3&>w)3A~C=+Z8Zb^^AQxg#2Vd8_@e~J!Pno=x-GlmP4@0 zqA`VU&LN^5@AsG3uN!`__iK^ctm=7sF*8yw-@ENi6Ty+@(by&a%z9JjvPJ1|4d+XK zs}>3RghwJ^5Aj`6LIVB*M@j9=igk`tV%@gzIIs%x! zC}6q@VdJltfBk+k-Ia?L(#q)7ksfbTO`l0x(T0Vv&?m3Q&ZJ6!69znelpl5k3}+OH z^v)N5dy-oQ$fsLmYxy0An8y_;q-tz>y>y*PJklVyujC4AaIeP@7hM@Cnb9P+ zG~%10i-nQB@uL+%-R{<dzy`4At825Tu$Fw3o#>=SpnNoX5N#2Ia`fskH_-NC?f-^F~~xfYdEQtx*m+4>voh zb*?w3oOp@M&2&!1If?#=z=qAF9EDg`FDyX>!dOTbn);Y+!cHG^**)>y3&b!}?^#$~ zv*V{02=7&^7Utw~c($)Di(2He>l#8R{jRg60o~is_USs|{WBU;pZTk0EC#+LRj6Si z!q1BfW_%9&#>AI8(?UX72{7Gc|MjW6ySgR1qeUWfRL@}Xs;P?fY;qSxCyK6FapG!s zC{>8X({5hkKnpXq&&iaCwvYpe&b5`nNDcbE;ZoB!aT;a zg6=D$uzVP+87#FrT^-}v!Bc~?0(#{aycHKDgrr0Rw`J?QIc(uDe;hL$I|jwh&Pxr( zV|Ak8CJyZ{jKiqs*}jomqO>S;_3dto6dBi|-2~`tdh({rWCOiFDc9mrZw?T$8iSNd zQ(*&?=D)xIH$RuC!(&Tre>mN&oc$kc71jL-&wu!ZeR=AalI;290wK^CK?iNRo~))nL=VcjyRQ#qHpQ{>E8h`b*rR%8 z9vM&=hAXItj}j48`)uSD2KE&Tgq`&JM3mKEFUiH5=H-t<+GaJ#l(cu)LQ3uYbpx`LiBfO?+pO&AT@ zl|jix@z=d9@-t8gr8>7x_jB;{Lg6SJ$eCg~IeKQ4ft60R7VAoWijg-mlA}lzRyP|<~>2|pQ7}fon6ZnbZkISHaYgyG=4~f6YaCBnF+&q6H zJ#rz!!MBC5+*Eu+OU^d2337YHHD8GuGw;@0YcujuEuGr%0b{aVa1Z_3Bct+Y5pftl z|1Ui$?Zc=-8ZkqdPXje!84l$KLR|SGVifWdiO*1khZg7^k+gzL_iy2FV_1D&1BBIx zSeQ>PrkTHE9~(`oQw!+`Vl;6Ioq`&K*&e#$5u01R zw(0QA1dyosslzW(3r>74P;2ej`4mcOE+#tb!~434YZ!n7@D|zFHrsC97^2j^a#j*k z=bZ=X@wV=t_Q`F@xqz!flAgxo8gc)3TmGNJs;KUN2dj}4is4E5!s?wBC?8r$u|mAA zs;nfE(d51M(YPt?ukTbX9&(0il@f+AjG3Bq_b0o)yB+s}4Qb+CA++QfA@Kfcc`L@{ z`$N}olKHWCqV)#L$9vn$41r57u9)>ykld8muh=I_48Nei6L!^G=f2Y&KYHf9FNOC= znGTLb;nuiTSzG}n5)MkJtkqACUJ3LdkhUw!X&zZ3Ric;G6?O}0IN0O6{RfSAgKaaM zsVN`09w?h(->4_ zhRpgIKSm5JYDhE~?dNqUBYuAB2vlG2pjlOpP$q-07J2}7UEO{7>kWkE9Z9fmP}}M^ z4xNxX4=;xLY@ay=wIdb~FAZO@ zK4iM)Av3SAd<_R9wMTxm-@Qb!#;I>5_tm?xHX}uA{p2oSuTBjH*p@7w`}gy!r*-h} zX;h7?(4|RYoHJ`OH)$!o?Tl+DX-K9oDK5(K6p)zhs`|m|-^y+NwH>)?TF$?0r(Nr_ zEbc?9hK^&>$gR6A^mRb8&y(IDfc_itmW9g8Yp;ZbBcg~KJrbYzIxVsN&{W{A-PK+b zHN%mM^+S`@QC-xcfIkH}3v*)`JN(WUwz(lA z46V5P%h|fV_h`IpiNus<)pF2);flfR5Ec8LO>g(jabNV$^J8NYBuj{p8rTkq2B<~5 zM!N+BuJc`vrqso87-}_Z3q#&Kc$FmW0rbEFapf`!Pp_y@`a7XbMFXZr*Mo38_u))Y zD_Bv@t)?TMQPR&T+28iy%D!vQH(b)kiy4wk=TJ9O$exxeBs6ZnJ#_Zc3PUOHZ-Y<$ zQM$n#LJWl$?ub-gDi1;9AUguj9iKMccin^R>WKHmT-<7h6N#o5yAwPXk_y40LQM!j zDjuAB;<4-7icL1l+v=t~bo04!>SADv0Iu*<_w{nDH1GaOldD#~g$@?cjRVy82UlYw zzg3Q#F9&K&>xpK@etwv?mJBp4DMSeCPugL0l;G56dNi>dGfVs4yo^rlE;Gt@%B3NA zUKmFZ!e~oKp3OnoI*Jk(eTFr^4|iChABfSM?M!DA@;_Kpvd|A=TJkb4 zMathlspw!+ALuEph`VA@( zD~#|4o37ActnIlOpW2he?F$9s93t(_s5EO^siIkAiGIC$82e-?Zbr)NkJXG}FqS=L zU$$Pq+mQKGw&FXzMn}k{Ta+OWZ8S9Os;O&{FneDW%x&~28>b(Q3>=Ny{mqi59gpd* zG{@Wf?dX;otoo24G8Lfw7tsK*7jFB6#eN+~etPv+^)wjPm0CZ+VY^nA52UH0upA>< zXs{WJF}1JIK-bSdOz3R4vcisUB7!s}9LT-t-IR=}%&GQ*q&ovkwBlgJFfkE~nMhws z01kvvQ%ut{QFbUz^UCt0+f!puC7``1kmfu+!48e7yt6_1)iXCuM|iMtuMB=AF^m#o z^$2TCj7B>oA(!8?bb;LymGla%PyvAtq0aKN|44-UKjRFfKzzu5rWXDd9vvn0e})>M zF%jV55TXAbX#o7K9=tEM3VzMLflSmW@0`27&9$)QtDxuv1h$ff%`Ab!P8Qh&eL!#j^WW(`NlSVW~Ei+xd1!#&z+-)9XM|*9f z^D1g(nIt4>wW|e%!dhfRub9_a2{o{Di1f>qS}AgUU_}3J3&@VT7VzdhjUc6T?{>CC z3{k)JORGR()<+3~==`&cU4+`)s}+Z3Q9FFb;sb4AfC6GXlD^BKKziY89@98_tJ)EH zP;#hB=u*CjTY*mH3Ajga3Qo#Dzp%w9Z+aFrFl8spJlSpwK-N=8@k>-f$S{826*hR@ z7~=b|9Ei9;rEfet72j&$mlIe{4x>(2@2#1>3?$RY`Y0&z#`O|cyW`Do>v!puypon*{T~7JH$0g-T6G&YLsZY9H}|vvj>7^qyCP({{>Bc;DrDH literal 0 HcmV?d00001 diff --git a/src/import/import-raw.c b/src/import/import-raw.c new file mode 100644 index 00000000..a12a6d63 --- /dev/null +++ b/src/import/import-raw.c @@ -0,0 +1,437 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-daemon.h" +#include "sd-event.h" + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "chattr-util.h" +#include "copy.h" +#include "fd-util.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "import-common.h" +#include "import-compress.h" +#include "import-raw.h" +#include "io-util.h" +#include "machine-pool.h" +#include "mkdir.h" +#include "path-util.h" +#include "qcow2-util.h" +#include "ratelimit.h" +#include "rm-rf.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "util.h" + +struct RawImport { + sd_event *event; + + char *image_root; + + RawImportFinished on_finished; + void *userdata; + + char *local; + bool force_local; + bool read_only; + + char *temp_path; + char *final_path; + + int input_fd; + int output_fd; + + ImportCompress compress; + + sd_event_source *input_event_source; + + uint8_t buffer[16*1024]; + size_t buffer_size; + + uint64_t written_compressed; + uint64_t written_uncompressed; + + struct stat st; + + unsigned last_percent; + RateLimit progress_ratelimit; +}; + +RawImport* raw_import_unref(RawImport *i) { + if (!i) + return NULL; + + sd_event_unref(i->event); + + if (i->temp_path) { + (void) unlink(i->temp_path); + free(i->temp_path); + } + + import_compress_free(&i->compress); + + sd_event_source_unref(i->input_event_source); + + safe_close(i->output_fd); + + free(i->final_path); + free(i->image_root); + free(i->local); + return mfree(i); +} + +int raw_import_new( + RawImport **ret, + sd_event *event, + const char *image_root, + RawImportFinished on_finished, + void *userdata) { + + _cleanup_(raw_import_unrefp) RawImport *i = NULL; + _cleanup_free_ char *root = NULL; + int r; + + assert(ret); + + root = strdup(image_root ?: "/var/lib/machines"); + if (!root) + return -ENOMEM; + + i = new(RawImport, 1); + if (!i) + return -ENOMEM; + + *i = (RawImport) { + .input_fd = -1, + .output_fd = -1, + .on_finished = on_finished, + .userdata = userdata, + .last_percent = (unsigned) -1, + .image_root = TAKE_PTR(root), + .progress_ratelimit = { 100 * USEC_PER_MSEC, 1 }, + }; + + if (event) + i->event = sd_event_ref(event); + else { + r = sd_event_default(&i->event); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(i); + + return 0; +} + +static void raw_import_report_progress(RawImport *i) { + unsigned percent; + assert(i); + + /* We have no size information, unless the source is a regular file */ + if (!S_ISREG(i->st.st_mode)) + return; + + if (i->written_compressed >= (uint64_t) i->st.st_size) + percent = 100; + else + percent = (unsigned) ((i->written_compressed * UINT64_C(100)) / (uint64_t) i->st.st_size); + + if (percent == i->last_percent) + return; + + if (!ratelimit_below(&i->progress_ratelimit)) + return; + + sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); + log_info("Imported %u%%.", percent); + + i->last_percent = percent; +} + +static int raw_import_maybe_convert_qcow2(RawImport *i) { + _cleanup_close_ int converted_fd = -1; + _cleanup_free_ char *t = NULL; + int r; + + assert(i); + + r = qcow2_detect(i->output_fd); + if (r < 0) + return log_error_errno(r, "Failed to detect whether this is a QCOW2 image: %m"); + if (r == 0) + return 0; + + /* This is a QCOW2 image, let's convert it */ + r = tempfn_random(i->final_path, NULL, &t); + if (r < 0) + return log_oom(); + + converted_fd = open(t, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); + if (converted_fd < 0) + return log_error_errno(errno, "Failed to create %s: %m", t); + + r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); + if (r < 0) + log_warning_errno(r, "Failed to set file attributes on %s: %m", t); + + log_info("Unpacking QCOW2 file."); + + r = qcow2_convert(i->output_fd, converted_fd); + if (r < 0) { + (void) unlink(t); + return log_error_errno(r, "Failed to convert qcow2 image: %m"); + } + + (void) unlink(i->temp_path); + free_and_replace(i->temp_path, t); + + safe_close(i->output_fd); + i->output_fd = TAKE_FD(converted_fd); + + return 1; +} + +static int raw_import_finish(RawImport *i) { + int r; + + assert(i); + assert(i->output_fd >= 0); + assert(i->temp_path); + assert(i->final_path); + + /* In case this was a sparse file, make sure the file system is right */ + if (i->written_uncompressed > 0) { + if (ftruncate(i->output_fd, i->written_uncompressed) < 0) + return log_error_errno(errno, "Failed to truncate file: %m"); + } + + r = raw_import_maybe_convert_qcow2(i); + if (r < 0) + return r; + + if (S_ISREG(i->st.st_mode)) { + (void) copy_times(i->input_fd, i->output_fd, COPY_CRTIME); + (void) copy_xattr(i->input_fd, i->output_fd); + } + + if (i->read_only) { + r = import_make_read_only_fd(i->output_fd); + if (r < 0) + return r; + } + + if (i->force_local) + (void) rm_rf(i->final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + + r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); + if (r < 0) + return log_error_errno(r, "Failed to move image into place: %m"); + + i->temp_path = mfree(i->temp_path); + + return 0; +} + +static int raw_import_open_disk(RawImport *i) { + int r; + + assert(i); + + assert(!i->final_path); + assert(!i->temp_path); + assert(i->output_fd < 0); + + i->final_path = strjoin(i->image_root, "/", i->local, ".raw"); + if (!i->final_path) + return log_oom(); + + r = tempfn_random(i->final_path, NULL, &i->temp_path); + if (r < 0) + return log_oom(); + + (void) mkdir_parents_label(i->temp_path, 0700); + + i->output_fd = open(i->temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); + if (i->output_fd < 0) + return log_error_errno(errno, "Failed to open destination %s: %m", i->temp_path); + + r = chattr_fd(i->output_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); + if (r < 0) + log_warning_errno(r, "Failed to set file attributes on %s: %m", i->temp_path); + + return 0; +} + +static int raw_import_try_reflink(RawImport *i) { + off_t p; + int r; + + assert(i); + assert(i->input_fd >= 0); + assert(i->output_fd >= 0); + + if (i->compress.type != IMPORT_COMPRESS_UNCOMPRESSED) + return 0; + + if (!S_ISREG(i->st.st_mode)) + return 0; + + p = lseek(i->input_fd, 0, SEEK_CUR); + if (p == (off_t) -1) + return log_error_errno(errno, "Failed to read file offset of input file: %m"); + + /* Let's only try a btrfs reflink, if we are reading from the beginning of the file */ + if ((uint64_t) p != (uint64_t) i->buffer_size) + return 0; + + r = btrfs_reflink(i->input_fd, i->output_fd); + if (r >= 0) + return 1; + + return 0; +} + +static int raw_import_write(const void *p, size_t sz, void *userdata) { + RawImport *i = userdata; + ssize_t n; + + n = sparse_write(i->output_fd, p, sz, 64); + if (n < 0) + return (int) n; + if ((size_t) n < sz) + return -EIO; + + i->written_uncompressed += sz; + + return 0; +} + +static int raw_import_process(RawImport *i) { + ssize_t l; + int r; + + assert(i); + assert(i->buffer_size < sizeof(i->buffer)); + + l = read(i->input_fd, i->buffer + i->buffer_size, sizeof(i->buffer) - i->buffer_size); + if (l < 0) { + if (errno == EAGAIN) + return 0; + + r = log_error_errno(errno, "Failed to read input file: %m"); + goto finish; + } + if (l == 0) { + if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) { + log_error("Premature end of file."); + r = -EIO; + goto finish; + } + + r = raw_import_finish(i); + goto finish; + } + + i->buffer_size += l; + + if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) { + r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size); + if (r < 0) { + log_error_errno(r, "Failed to detect file compression: %m"); + goto finish; + } + if (r == 0) /* Need more data */ + return 0; + + r = raw_import_open_disk(i); + if (r < 0) + goto finish; + + r = raw_import_try_reflink(i); + if (r < 0) + goto finish; + if (r > 0) { + r = raw_import_finish(i); + goto finish; + } + } + + r = import_uncompress(&i->compress, i->buffer, i->buffer_size, raw_import_write, i); + if (r < 0) { + log_error_errno(r, "Failed to decode and write: %m"); + goto finish; + } + + i->written_compressed += i->buffer_size; + i->buffer_size = 0; + + raw_import_report_progress(i); + + return 0; + +finish: + if (i->on_finished) + i->on_finished(i, r, i->userdata); + else + sd_event_exit(i->event, r); + + return 0; +} + +static int raw_import_on_input(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + RawImport *i = userdata; + + return raw_import_process(i); +} + +static int raw_import_on_defer(sd_event_source *s, void *userdata) { + RawImport *i = userdata; + + return raw_import_process(i); +} + +int raw_import_start(RawImport *i, int fd, const char *local, bool force_local, bool read_only) { + int r; + + assert(i); + assert(fd >= 0); + assert(local); + + if (!machine_name_is_valid(local)) + return -EINVAL; + + if (i->input_fd >= 0) + return -EBUSY; + + r = fd_nonblock(fd, true); + if (r < 0) + return r; + + r = free_and_strdup(&i->local, local); + if (r < 0) + return r; + i->force_local = force_local; + i->read_only = read_only; + + if (fstat(fd, &i->st) < 0) + return -errno; + + r = sd_event_add_io(i->event, &i->input_event_source, fd, EPOLLIN, raw_import_on_input, i); + if (r == -EPERM) { + /* This fd does not support epoll, for example because it is a regular file. Busy read in that case */ + r = sd_event_add_defer(i->event, &i->input_event_source, raw_import_on_defer, i); + if (r < 0) + return r; + + r = sd_event_source_set_enabled(i->input_event_source, SD_EVENT_ON); + } + if (r < 0) + return r; + + i->input_fd = fd; + return r; +} diff --git a/src/import/import-raw.h b/src/import/import-raw.h new file mode 100644 index 00000000..de4c3ea3 --- /dev/null +++ b/src/import/import-raw.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" + +#include "import-util.h" +#include "macro.h" + +typedef struct RawImport RawImport; + +typedef void (*RawImportFinished)(RawImport *import, int error, void *userdata); + +int raw_import_new(RawImport **import, sd_event *event, const char *image_root, RawImportFinished on_finished, void *userdata); +RawImport* raw_import_unref(RawImport *import); + +DEFINE_TRIVIAL_CLEANUP_FUNC(RawImport*, raw_import_unref); + +int raw_import_start(RawImport *i, int fd, const char *local, bool force_local, bool read_only); diff --git a/src/import/import-tar.c b/src/import/import-tar.c new file mode 100644 index 00000000..1e50d31b --- /dev/null +++ b/src/import/import-tar.c @@ -0,0 +1,368 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-daemon.h" +#include "sd-event.h" + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "copy.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "import-common.h" +#include "import-compress.h" +#include "import-tar.h" +#include "io-util.h" +#include "machine-pool.h" +#include "mkdir.h" +#include "path-util.h" +#include "process-util.h" +#include "qcow2-util.h" +#include "ratelimit.h" +#include "rm-rf.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "util.h" + +struct TarImport { + sd_event *event; + + char *image_root; + + TarImportFinished on_finished; + void *userdata; + + char *local; + bool force_local; + bool read_only; + + char *temp_path; + char *final_path; + + int input_fd; + int tar_fd; + + ImportCompress compress; + + sd_event_source *input_event_source; + + uint8_t buffer[16*1024]; + size_t buffer_size; + + uint64_t written_compressed; + uint64_t written_uncompressed; + + struct stat st; + + pid_t tar_pid; + + unsigned last_percent; + RateLimit progress_ratelimit; +}; + +TarImport* tar_import_unref(TarImport *i) { + if (!i) + return NULL; + + sd_event_source_unref(i->input_event_source); + + if (i->tar_pid > 1) { + (void) kill_and_sigcont(i->tar_pid, SIGKILL); + (void) wait_for_terminate(i->tar_pid, NULL); + } + + if (i->temp_path) { + (void) rm_rf(i->temp_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + free(i->temp_path); + } + + import_compress_free(&i->compress); + + sd_event_unref(i->event); + + safe_close(i->tar_fd); + + free(i->final_path); + free(i->image_root); + free(i->local); + return mfree(i); +} + +int tar_import_new( + TarImport **ret, + sd_event *event, + const char *image_root, + TarImportFinished on_finished, + void *userdata) { + + _cleanup_(tar_import_unrefp) TarImport *i = NULL; + _cleanup_free_ char *root = NULL; + int r; + + assert(ret); + + root = strdup(image_root ?: "/var/lib/machines"); + if (!root) + return -ENOMEM; + + i = new(TarImport, 1); + if (!i) + return -ENOMEM; + + *i = (TarImport) { + .input_fd = -1, + .tar_fd = -1, + .on_finished = on_finished, + .userdata = userdata, + .last_percent = (unsigned) -1, + .image_root = TAKE_PTR(root), + .progress_ratelimit = { 100 * USEC_PER_MSEC, 1 }, + }; + + if (event) + i->event = sd_event_ref(event); + else { + r = sd_event_default(&i->event); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(i); + + return 0; +} + +static void tar_import_report_progress(TarImport *i) { + unsigned percent; + assert(i); + + /* We have no size information, unless the source is a regular file */ + if (!S_ISREG(i->st.st_mode)) + return; + + if (i->written_compressed >= (uint64_t) i->st.st_size) + percent = 100; + else + percent = (unsigned) ((i->written_compressed * UINT64_C(100)) / (uint64_t) i->st.st_size); + + if (percent == i->last_percent) + return; + + if (!ratelimit_below(&i->progress_ratelimit)) + return; + + sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); + log_info("Imported %u%%.", percent); + + i->last_percent = percent; +} + +static int tar_import_finish(TarImport *i) { + int r; + + assert(i); + assert(i->tar_fd >= 0); + assert(i->temp_path); + assert(i->final_path); + + i->tar_fd = safe_close(i->tar_fd); + + if (i->tar_pid > 0) { + r = wait_for_terminate_and_check("tar", i->tar_pid, WAIT_LOG); + i->tar_pid = 0; + if (r < 0) + return r; + if (r != EXIT_SUCCESS) + return -EPROTO; + } + + r = import_mangle_os_tree(i->temp_path); + if (r < 0) + return r; + + if (i->read_only) { + r = import_make_read_only(i->temp_path); + if (r < 0) + return r; + } + + if (i->force_local) + (void) rm_rf(i->final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + + r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); + if (r < 0) + return log_error_errno(r, "Failed to move image into place: %m"); + + i->temp_path = mfree(i->temp_path); + + return 0; +} + +static int tar_import_fork_tar(TarImport *i) { + int r; + + assert(i); + + assert(!i->final_path); + assert(!i->temp_path); + assert(i->tar_fd < 0); + + i->final_path = path_join(i->image_root, i->local); + if (!i->final_path) + return log_oom(); + + r = tempfn_random(i->final_path, NULL, &i->temp_path); + if (r < 0) + return log_oom(); + + (void) mkdir_parents_label(i->temp_path, 0700); + + r = btrfs_subvol_make(i->temp_path); + if (r == -ENOTTY) { + if (mkdir(i->temp_path, 0755) < 0) + return log_error_errno(errno, "Failed to create directory %s: %m", i->temp_path); + } else if (r < 0) + return log_error_errno(r, "Failed to create subvolume %s: %m", i->temp_path); + else + (void) import_assign_pool_quota_and_warn(i->temp_path); + + i->tar_fd = import_fork_tar_x(i->temp_path, &i->tar_pid); + if (i->tar_fd < 0) + return i->tar_fd; + + return 0; +} + +static int tar_import_write(const void *p, size_t sz, void *userdata) { + TarImport *i = userdata; + int r; + + r = loop_write(i->tar_fd, p, sz, false); + if (r < 0) + return r; + + i->written_uncompressed += sz; + + return 0; +} + +static int tar_import_process(TarImport *i) { + ssize_t l; + int r; + + assert(i); + assert(i->buffer_size < sizeof(i->buffer)); + + l = read(i->input_fd, i->buffer + i->buffer_size, sizeof(i->buffer) - i->buffer_size); + if (l < 0) { + if (errno == EAGAIN) + return 0; + + r = log_error_errno(errno, "Failed to read input file: %m"); + goto finish; + } + if (l == 0) { + if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) { + log_error("Premature end of file."); + r = -EIO; + goto finish; + } + + r = tar_import_finish(i); + goto finish; + } + + i->buffer_size += l; + + if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) { + r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size); + if (r < 0) { + log_error_errno(r, "Failed to detect file compression: %m"); + goto finish; + } + if (r == 0) /* Need more data */ + return 0; + + r = tar_import_fork_tar(i); + if (r < 0) + goto finish; + } + + r = import_uncompress(&i->compress, i->buffer, i->buffer_size, tar_import_write, i); + if (r < 0) { + log_error_errno(r, "Failed to decode and write: %m"); + goto finish; + } + + i->written_compressed += i->buffer_size; + i->buffer_size = 0; + + tar_import_report_progress(i); + + return 0; + +finish: + if (i->on_finished) + i->on_finished(i, r, i->userdata); + else + sd_event_exit(i->event, r); + + return 0; +} + +static int tar_import_on_input(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + TarImport *i = userdata; + + return tar_import_process(i); +} + +static int tar_import_on_defer(sd_event_source *s, void *userdata) { + TarImport *i = userdata; + + return tar_import_process(i); +} + +int tar_import_start(TarImport *i, int fd, const char *local, bool force_local, bool read_only) { + int r; + + assert(i); + assert(fd >= 0); + assert(local); + + if (!machine_name_is_valid(local)) + return -EINVAL; + + if (i->input_fd >= 0) + return -EBUSY; + + r = fd_nonblock(fd, true); + if (r < 0) + return r; + + r = free_and_strdup(&i->local, local); + if (r < 0) + return r; + i->force_local = force_local; + i->read_only = read_only; + + if (fstat(fd, &i->st) < 0) + return -errno; + + r = sd_event_add_io(i->event, &i->input_event_source, fd, EPOLLIN, tar_import_on_input, i); + if (r == -EPERM) { + /* This fd does not support epoll, for example because it is a regular file. Busy read in that case */ + r = sd_event_add_defer(i->event, &i->input_event_source, tar_import_on_defer, i); + if (r < 0) + return r; + + r = sd_event_source_set_enabled(i->input_event_source, SD_EVENT_ON); + } + if (r < 0) + return r; + + i->input_fd = fd; + return r; +} diff --git a/src/import/import-tar.h b/src/import/import-tar.h new file mode 100644 index 00000000..347f5226 --- /dev/null +++ b/src/import/import-tar.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" + +#include "import-util.h" +#include "macro.h" + +typedef struct TarImport TarImport; + +typedef void (*TarImportFinished)(TarImport *import, int error, void *userdata); + +int tar_import_new(TarImport **import, sd_event *event, const char *image_root, TarImportFinished on_finished, void *userdata); +TarImport* tar_import_unref(TarImport *import); + +DEFINE_TRIVIAL_CLEANUP_FUNC(TarImport*, tar_import_unref); + +int tar_import_start(TarImport *import, int fd, const char *local, bool force_local, bool read_only); diff --git a/src/import/import.c b/src/import/import.c new file mode 100644 index 00000000..cc285574 --- /dev/null +++ b/src/import/import.c @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-event.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "import-raw.h" +#include "import-tar.h" +#include "import-util.h" +#include "machine-image.h" +#include "main-func.h" +#include "signal-util.h" +#include "string-util.h" +#include "verbs.h" + +static bool arg_force = false; +static bool arg_read_only = false; +static const char *arg_image_root = "/var/lib/machines"; + +static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + log_notice("Transfer aborted."); + sd_event_exit(sd_event_source_get_event(s), EINTR); + return 0; +} + +static void on_tar_finished(TarImport *import, int error, void *userdata) { + sd_event *event = userdata; + assert(import); + + if (error == 0) + log_info("Operation completed successfully."); + + sd_event_exit(event, abs(error)); +} + +static int import_tar(int argc, char *argv[], void *userdata) { + _cleanup_(tar_import_unrefp) TarImport *import = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + const char *path = NULL, *local = NULL; + _cleanup_free_ char *ll = NULL; + _cleanup_close_ int open_fd = -1; + int r, fd; + + if (argc >= 2) + path = argv[1]; + path = empty_or_dash_to_null(path); + + if (argc >= 3) + local = argv[2]; + else if (path) + local = basename(path); + local = empty_or_dash_to_null(local); + + if (local) { + r = tar_strip_suffixes(local, &ll); + if (r < 0) + return log_oom(); + + local = ll; + + if (!machine_name_is_valid(local)) { + log_error("Local image name '%s' is not valid.", local); + return -EINVAL; + } + + if (!arg_force) { + r = image_find(IMAGE_MACHINE, local, NULL); + if (r < 0) { + if (r != -ENOENT) + return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); + } else { + log_error("Image '%s' already exists.", local); + return -EEXIST; + } + } + } else + local = "imported"; + + if (path) { + open_fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (open_fd < 0) + return log_error_errno(errno, "Failed to open tar image to import: %m"); + + fd = open_fd; + + log_info("Importing '%s', saving as '%s'.", path, local); + } else { + _cleanup_free_ char *pretty = NULL; + + fd = STDIN_FILENO; + + (void) fd_get_path(fd, &pretty); + log_info("Importing '%s', saving as '%s'.", strna(pretty), local); + } + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); + (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); + + r = tar_import_new(&import, event, arg_image_root, on_tar_finished, event); + if (r < 0) + return log_error_errno(r, "Failed to allocate importer: %m"); + + r = tar_import_start(import, fd, local, arg_force, arg_read_only); + if (r < 0) + return log_error_errno(r, "Failed to import image: %m"); + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + log_info("Exiting."); + return -r; +} + +static void on_raw_finished(RawImport *import, int error, void *userdata) { + sd_event *event = userdata; + assert(import); + + if (error == 0) + log_info("Operation completed successfully."); + + sd_event_exit(event, abs(error)); +} + +static int import_raw(int argc, char *argv[], void *userdata) { + _cleanup_(raw_import_unrefp) RawImport *import = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + const char *path = NULL, *local = NULL; + _cleanup_free_ char *ll = NULL; + _cleanup_close_ int open_fd = -1; + int r, fd; + + if (argc >= 2) + path = argv[1]; + path = empty_or_dash_to_null(path); + + if (argc >= 3) + local = argv[2]; + else if (path) + local = basename(path); + local = empty_or_dash_to_null(local); + + if (local) { + r = raw_strip_suffixes(local, &ll); + if (r < 0) + return log_oom(); + + local = ll; + + if (!machine_name_is_valid(local)) { + log_error("Local image name '%s' is not valid.", local); + return -EINVAL; + } + + if (!arg_force) { + r = image_find(IMAGE_MACHINE, local, NULL); + if (r < 0) { + if (r != -ENOENT) + return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); + } else { + log_error("Image '%s' already exists.", local); + return -EEXIST; + } + } + } else + local = "imported"; + + if (path) { + open_fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (open_fd < 0) + return log_error_errno(errno, "Failed to open raw image to import: %m"); + + fd = open_fd; + + log_info("Importing '%s', saving as '%s'.", path, local); + } else { + _cleanup_free_ char *pretty = NULL; + + fd = STDIN_FILENO; + + (void) fd_get_path(fd, &pretty); + log_info("Importing '%s', saving as '%s'.", strempty(pretty), local); + } + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); + (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); + + r = raw_import_new(&import, event, arg_image_root, on_raw_finished, event); + if (r < 0) + return log_error_errno(r, "Failed to allocate importer: %m"); + + r = raw_import_start(import, fd, local, arg_force, arg_read_only); + if (r < 0) + return log_error_errno(r, "Failed to import image: %m"); + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + log_info("Exiting."); + return -r; +} + +static int help(int argc, char *argv[], void *userdata) { + + printf("%s [OPTIONS...] {COMMAND} ...\n\n" + "Import container or virtual machine images.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --force Force creation of image\n" + " --image-root=PATH Image root directory\n" + " --read-only Create a read-only image\n\n" + "Commands:\n" + " tar FILE [NAME] Import a TAR image\n" + " raw FILE [NAME] Import a RAW image\n", + program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_FORCE, + ARG_IMAGE_ROOT, + ARG_READ_ONLY, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "force", no_argument, NULL, ARG_FORCE }, + { "image-root", required_argument, NULL, ARG_IMAGE_ROOT }, + { "read-only", no_argument, NULL, ARG_READ_ONLY }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(0, NULL, NULL); + + case ARG_VERSION: + return version(); + + case ARG_FORCE: + arg_force = true; + break; + + case ARG_IMAGE_ROOT: + arg_image_root = optarg; + break; + + case ARG_READ_ONLY: + arg_read_only = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int import_main(int argc, char *argv[]) { + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "tar", 2, 3, 0, import_tar }, + { "raw", 2, 3, 0, import_raw }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static int run(int argc, char *argv[]) { + int r; + + setlocale(LC_ALL, ""); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return 0; + + (void) ignore_signals(SIGPIPE, -1); + + return import_main(argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/import/importd.c b/src/import/importd.c new file mode 100644 index 00000000..93e704ed --- /dev/null +++ b/src/import/importd.c @@ -0,0 +1,1272 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-polkit.h" +#include "def.h" +#include "fd-util.h" +#include "float.h" +#include "hostname-util.h" +#include "import-util.h" +#include "machine-pool.h" +#include "main-func.h" +#include "missing_capability.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "stat-util.h" +#include "string-table.h" +#include "strv.h" +#include "syslog-util.h" +#include "user-util.h" +#include "util.h" +#include "web-util.h" + +typedef struct Transfer Transfer; +typedef struct Manager Manager; + +typedef enum TransferType { + TRANSFER_IMPORT_TAR, + TRANSFER_IMPORT_RAW, + TRANSFER_IMPORT_FS, + TRANSFER_EXPORT_TAR, + TRANSFER_EXPORT_RAW, + TRANSFER_PULL_TAR, + TRANSFER_PULL_RAW, + _TRANSFER_TYPE_MAX, + _TRANSFER_TYPE_INVALID = -1, +} TransferType; + +struct Transfer { + Manager *manager; + + uint32_t id; + char *object_path; + + TransferType type; + ImportVerify verify; + + char *remote; + char *local; + bool force_local; + bool read_only; + + char *format; + + pid_t pid; + + int log_fd; + + char log_message[LINE_MAX]; + size_t log_message_size; + + sd_event_source *pid_event_source; + sd_event_source *log_event_source; + + unsigned n_canceled; + unsigned progress_percent; + + int stdin_fd; + int stdout_fd; +}; + +struct Manager { + sd_event *event; + sd_bus *bus; + + uint32_t current_transfer_id; + Hashmap *transfers; + + Hashmap *polkit_registry; + + int notify_fd; + + sd_event_source *notify_event_source; +}; + +#define TRANSFERS_MAX 64 + +static const char* const transfer_type_table[_TRANSFER_TYPE_MAX] = { + [TRANSFER_IMPORT_TAR] = "import-tar", + [TRANSFER_IMPORT_RAW] = "import-raw", + [TRANSFER_IMPORT_FS] = "import-fs", + [TRANSFER_EXPORT_TAR] = "export-tar", + [TRANSFER_EXPORT_RAW] = "export-raw", + [TRANSFER_PULL_TAR] = "pull-tar", + [TRANSFER_PULL_RAW] = "pull-raw", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType); + +static Transfer *transfer_unref(Transfer *t) { + if (!t) + return NULL; + + if (t->manager) + hashmap_remove(t->manager->transfers, UINT32_TO_PTR(t->id)); + + sd_event_source_unref(t->pid_event_source); + sd_event_source_unref(t->log_event_source); + + free(t->remote); + free(t->local); + free(t->format); + free(t->object_path); + + if (t->pid > 0) { + (void) kill_and_sigcont(t->pid, SIGKILL); + (void) wait_for_terminate(t->pid, NULL); + } + + safe_close(t->log_fd); + safe_close(t->stdin_fd); + safe_close(t->stdout_fd); + + return mfree(t); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Transfer*, transfer_unref); + +static int transfer_new(Manager *m, Transfer **ret) { + _cleanup_(transfer_unrefp) Transfer *t = NULL; + uint32_t id; + int r; + + assert(m); + assert(ret); + + if (hashmap_size(m->transfers) >= TRANSFERS_MAX) + return -E2BIG; + + r = hashmap_ensure_allocated(&m->transfers, &trivial_hash_ops); + if (r < 0) + return r; + + t = new(Transfer, 1); + if (!t) + return -ENOMEM; + + *t = (Transfer) { + .type = _TRANSFER_TYPE_INVALID, + .log_fd = -1, + .stdin_fd = -1, + .stdout_fd = -1, + .verify = _IMPORT_VERIFY_INVALID, + .progress_percent= (unsigned) -1, + }; + + id = m->current_transfer_id + 1; + + if (asprintf(&t->object_path, "/org/freedesktop/import1/transfer/_%" PRIu32, id) < 0) + return -ENOMEM; + + r = hashmap_put(m->transfers, UINT32_TO_PTR(id), t); + if (r < 0) + return r; + + m->current_transfer_id = id; + + t->manager = m; + t->id = id; + + *ret = TAKE_PTR(t); + + return 0; +} + +static double transfer_percent_as_double(Transfer *t) { + assert(t); + + if (t->progress_percent == (unsigned) -1) + return -DBL_MAX; + + return (double) t->progress_percent / 100.0; +} + +static void transfer_send_log_line(Transfer *t, const char *line) { + int r, priority = LOG_INFO; + + assert(t); + assert(line); + + syslog_parse_priority(&line, &priority, true); + + log_full(priority, "(transfer%" PRIu32 ") %s", t->id, line); + + r = sd_bus_emit_signal( + t->manager->bus, + t->object_path, + "org.freedesktop.import1.Transfer", + "LogMessage", + "us", + priority, + line); + if (r < 0) + log_warning_errno(r, "Cannot emit log message signal, ignoring: %m"); + } + +static void transfer_send_logs(Transfer *t, bool flush) { + assert(t); + + /* Try to send out all log messages, if we can. But if we + * can't we remove the messages from the buffer, but don't + * fail */ + + while (t->log_message_size > 0) { + _cleanup_free_ char *n = NULL; + char *e; + + if (t->log_message_size >= sizeof(t->log_message)) + e = t->log_message + sizeof(t->log_message); + else { + char *a, *b; + + a = memchr(t->log_message, 0, t->log_message_size); + b = memchr(t->log_message, '\n', t->log_message_size); + + if (a && b) + e = a < b ? a : b; + else if (a) + e = a; + else + e = b; + } + + if (!e) { + if (!flush) + return; + + e = t->log_message + t->log_message_size; + } + + n = strndup(t->log_message, e - t->log_message); + + /* Skip over NUL and newlines */ + while (e < t->log_message + t->log_message_size && IN_SET(*e, 0, '\n')) + e++; + + memmove(t->log_message, e, t->log_message + sizeof(t->log_message) - e); + t->log_message_size -= e - t->log_message; + + if (!n) { + log_oom(); + continue; + } + + if (isempty(n)) + continue; + + transfer_send_log_line(t, n); + } +} + +static int transfer_finalize(Transfer *t, bool success) { + int r; + + assert(t); + + transfer_send_logs(t, true); + + r = sd_bus_emit_signal( + t->manager->bus, + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "TransferRemoved", + "uos", + t->id, + t->object_path, + success ? "done" : + t->n_canceled > 0 ? "canceled" : "failed"); + + if (r < 0) + log_error_errno(r, "Cannot emit message: %m"); + + transfer_unref(t); + return 0; +} + +static int transfer_cancel(Transfer *t) { + int r; + + assert(t); + + r = kill_and_sigcont(t->pid, t->n_canceled < 3 ? SIGTERM : SIGKILL); + if (r < 0) + return r; + + t->n_canceled++; + return 0; +} + +static int transfer_on_pid(sd_event_source *s, const siginfo_t *si, void *userdata) { + Transfer *t = userdata; + bool success = false; + + assert(s); + assert(t); + + if (si->si_code == CLD_EXITED) { + if (si->si_status != 0) + log_error("Transfer process failed with exit code %i.", si->si_status); + else { + log_debug("Transfer process succeeded."); + success = true; + } + + } else if (IN_SET(si->si_code, CLD_KILLED, CLD_DUMPED)) + log_error("Transfer process terminated by signal %s.", signal_to_string(si->si_status)); + else + log_error("Transfer process failed due to unknown reason."); + + t->pid = 0; + + return transfer_finalize(t, success); +} + +static int transfer_on_log(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Transfer *t = userdata; + ssize_t l; + + assert(s); + assert(t); + + l = read(fd, t->log_message + t->log_message_size, sizeof(t->log_message) - t->log_message_size); + if (l < 0) + log_error_errno(errno, "Failed to read log message: %m"); + if (l <= 0) { + /* EOF/read error. We just close the pipe here, and + * close the watch, waiting for the SIGCHLD to arrive, + * before we do anything else. */ + t->log_event_source = sd_event_source_unref(t->log_event_source); + return 0; + } + + t->log_message_size += l; + + transfer_send_logs(t, false); + + return 0; +} + +static int transfer_start(Transfer *t) { + _cleanup_close_pair_ int pipefd[2] = { -1, -1 }; + int r; + + assert(t); + assert(t->pid <= 0); + + if (pipe2(pipefd, O_CLOEXEC) < 0) + return -errno; + + r = safe_fork("(sd-transfer)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &t->pid); + if (r < 0) + return r; + if (r == 0) { + const char *cmd[] = { + NULL, /* systemd-import, systemd-import-fs, systemd-export or systemd-pull */ + NULL, /* tar, raw */ + NULL, /* --verify= */ + NULL, /* verify argument */ + NULL, /* maybe --force */ + NULL, /* maybe --read-only */ + NULL, /* if so: the actual URL */ + NULL, /* maybe --format= */ + NULL, /* if so: the actual format */ + NULL, /* remote */ + NULL, /* local */ + NULL + }; + unsigned k = 0; + + /* Child */ + + pipefd[0] = safe_close(pipefd[0]); + + r = rearrange_stdio(t->stdin_fd, + t->stdout_fd < 0 ? pipefd[1] : t->stdout_fd, + pipefd[1]); + if (r < 0) { + log_error_errno(r, "Failed to set stdin/stdout/stderr: %m"); + _exit(EXIT_FAILURE); + } + + if (setenv("SYSTEMD_LOG_TARGET", "console-prefixed", 1) < 0 || + setenv("NOTIFY_SOCKET", "/run/systemd/import/notify", 1) < 0) { + log_error_errno(errno, "setenv() failed: %m"); + _exit(EXIT_FAILURE); + } + + switch (t->type) { + + case TRANSFER_IMPORT_TAR: + case TRANSFER_IMPORT_RAW: + cmd[k++] = SYSTEMD_IMPORT_PATH; + break; + + case TRANSFER_IMPORT_FS: + cmd[k++] = SYSTEMD_IMPORT_FS_PATH; + break; + + case TRANSFER_EXPORT_TAR: + case TRANSFER_EXPORT_RAW: + cmd[k++] = SYSTEMD_EXPORT_PATH; + break; + + case TRANSFER_PULL_TAR: + case TRANSFER_PULL_RAW: + cmd[k++] = SYSTEMD_PULL_PATH; + break; + + default: + assert_not_reached("Unexpected transfer type"); + } + + switch (t->type) { + + case TRANSFER_IMPORT_TAR: + case TRANSFER_EXPORT_TAR: + case TRANSFER_PULL_TAR: + cmd[k++] = "tar"; + break; + + case TRANSFER_IMPORT_RAW: + case TRANSFER_EXPORT_RAW: + case TRANSFER_PULL_RAW: + cmd[k++] = "raw"; + break; + + case TRANSFER_IMPORT_FS: + cmd[k++] = "run"; + break; + + default: + break; + } + + if (t->verify != _IMPORT_VERIFY_INVALID) { + cmd[k++] = "--verify"; + cmd[k++] = import_verify_to_string(t->verify); + } + + if (t->force_local) + cmd[k++] = "--force"; + if (t->read_only) + cmd[k++] = "--read-only"; + + if (t->format) { + cmd[k++] = "--format"; + cmd[k++] = t->format; + } + + if (!IN_SET(t->type, TRANSFER_EXPORT_TAR, TRANSFER_EXPORT_RAW)) { + if (t->remote) + cmd[k++] = t->remote; + else + cmd[k++] = "-"; + } + + if (t->local) + cmd[k++] = t->local; + cmd[k] = NULL; + + execv(cmd[0], (char * const *) cmd); + log_error_errno(errno, "Failed to execute %s tool: %m", cmd[0]); + _exit(EXIT_FAILURE); + } + + pipefd[1] = safe_close(pipefd[1]); + t->log_fd = TAKE_FD(pipefd[0]); + + t->stdin_fd = safe_close(t->stdin_fd); + + r = sd_event_add_child(t->manager->event, &t->pid_event_source, t->pid, WEXITED, transfer_on_pid, t); + if (r < 0) + return r; + + r = sd_event_add_io(t->manager->event, &t->log_event_source, t->log_fd, EPOLLIN, transfer_on_log, t); + if (r < 0) + return r; + + /* Make sure always process logging before SIGCHLD */ + r = sd_event_source_set_priority(t->log_event_source, SD_EVENT_PRIORITY_NORMAL -5); + if (r < 0) + return r; + + r = sd_bus_emit_signal( + t->manager->bus, + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "TransferNew", + "uo", + t->id, + t->object_path); + if (r < 0) + return r; + + return 0; +} + +static Manager *manager_unref(Manager *m) { + Transfer *t; + + if (!m) + return NULL; + + sd_event_source_unref(m->notify_event_source); + safe_close(m->notify_fd); + + while ((t = hashmap_first(m->transfers))) + transfer_unref(t); + + hashmap_free(m->transfers); + + bus_verify_polkit_async_registry_free(m->polkit_registry); + + m->bus = sd_bus_flush_close_unref(m->bus); + sd_event_unref(m->event); + + return mfree(m); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref); + +static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + + char buf[NOTIFY_BUFFER_MAX+1]; + struct iovec iovec = { + .iov_base = buf, + .iov_len = sizeof(buf)-1, + }; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + + CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)]; + } control = {}; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + struct ucred *ucred = NULL; + Manager *m = userdata; + struct cmsghdr *cmsg; + char *p, *e; + Transfer *t; + Iterator i; + ssize_t n; + int r; + + n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + return -errno; + } + + cmsg_close_all(&msghdr); + + CMSG_FOREACH(cmsg, &msghdr) + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) + ucred = (struct ucred*) CMSG_DATA(cmsg); + + if (msghdr.msg_flags & MSG_TRUNC) { + log_warning("Got overly long notification datagram, ignoring."); + return 0; + } + + if (!ucred || ucred->pid <= 0) { + log_warning("Got notification datagram lacking credential information, ignoring."); + return 0; + } + + HASHMAP_FOREACH(t, m->transfers, i) + if (ucred->pid == t->pid) + break; + + if (!t) { + log_warning("Got notification datagram from unexpected peer, ignoring."); + return 0; + } + + buf[n] = 0; + + p = startswith(buf, "X_IMPORT_PROGRESS="); + if (!p) { + p = strstr(buf, "\nX_IMPORT_PROGRESS="); + if (!p) + return 0; + + p += 19; + } + + e = strchrnul(p, '\n'); + *e = 0; + + r = parse_percent(p); + if (r < 0) { + log_warning("Got invalid percent value, ignoring."); + return 0; + } + + t->progress_percent = (unsigned) r; + + log_debug("Got percentage from client: %u%%", t->progress_percent); + return 0; +} + +static int manager_new(Manager **ret) { + _cleanup_(manager_unrefp) Manager *m = NULL; + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/import/notify", + }; + int r; + + assert(ret); + + m = new0(Manager, 1); + if (!m) + return -ENOMEM; + + r = sd_event_default(&m->event); + if (r < 0) + return r; + + sd_event_set_watchdog(m->event, true); + + r = sd_bus_default_system(&m->bus); + if (r < 0) + return r; + + m->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (m->notify_fd < 0) + return -errno; + + (void) mkdir_parents_label(sa.un.sun_path, 0755); + (void) sockaddr_un_unlink(&sa.un); + + if (bind(m->notify_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) + return -errno; + + r = setsockopt_int(m->notify_fd, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return r; + + r = sd_event_add_io(m->event, &m->notify_event_source, m->notify_fd, EPOLLIN, manager_on_notify, m); + if (r < 0) + return r; + + *ret = TAKE_PTR(m); + + return 0; +} + +static Transfer *manager_find(Manager *m, TransferType type, const char *remote) { + Transfer *t; + Iterator i; + + assert(m); + assert(type >= 0); + assert(type < _TRANSFER_TYPE_MAX); + + HASHMAP_FOREACH(t, m->transfers, i) + if (t->type == type && streq_ptr(t->remote, remote)) + return t; + + return NULL; +} + +static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) { + _cleanup_(transfer_unrefp) Transfer *t = NULL; + int fd, force, read_only, r; + const char *local, *object; + Manager *m = userdata; + TransferType type; + struct stat st; + uint32_t id; + + assert(msg); + assert(m); + + r = bus_verify_polkit_async( + msg, + CAP_SYS_ADMIN, + "org.freedesktop.import1.import", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = sd_bus_message_read(msg, "hsbb", &fd, &local, &force, &read_only); + if (r < 0) + return r; + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode)) + return -EINVAL; + + if (!machine_name_is_valid(local)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); + + r = setup_machine_directory(error); + if (r < 0) + return r; + + type = streq_ptr(sd_bus_message_get_member(msg), "ImportTar") ? TRANSFER_IMPORT_TAR : TRANSFER_IMPORT_RAW; + + r = transfer_new(m, &t); + if (r < 0) + return r; + + t->type = type; + t->force_local = force; + t->read_only = read_only; + + t->local = strdup(local); + if (!t->local) + return -ENOMEM; + + t->stdin_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (t->stdin_fd < 0) + return -errno; + + r = transfer_start(t); + if (r < 0) + return r; + + object = t->object_path; + id = t->id; + t = NULL; + + return sd_bus_reply_method_return(msg, "uo", id, object); +} + +static int method_import_fs(sd_bus_message *msg, void *userdata, sd_bus_error *error) { + _cleanup_(transfer_unrefp) Transfer *t = NULL; + int fd, force, read_only, r; + const char *local, *object; + Manager *m = userdata; + uint32_t id; + + assert(msg); + assert(m); + + r = bus_verify_polkit_async( + msg, + CAP_SYS_ADMIN, + "org.freedesktop.import1.import", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = sd_bus_message_read(msg, "hsbb", &fd, &local, &force, &read_only); + if (r < 0) + return r; + + r = fd_verify_directory(fd); + if (r < 0) + return r; + + if (!machine_name_is_valid(local)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); + + r = setup_machine_directory(error); + if (r < 0) + return r; + + r = transfer_new(m, &t); + if (r < 0) + return r; + + t->type = TRANSFER_IMPORT_FS; + t->force_local = force; + t->read_only = read_only; + + t->local = strdup(local); + if (!t->local) + return -ENOMEM; + + t->stdin_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (t->stdin_fd < 0) + return -errno; + + r = transfer_start(t); + if (r < 0) + return r; + + object = t->object_path; + id = t->id; + t = NULL; + + return sd_bus_reply_method_return(msg, "uo", id, object); +} + +static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) { + _cleanup_(transfer_unrefp) Transfer *t = NULL; + int fd, r; + const char *local, *object, *format; + Manager *m = userdata; + TransferType type; + struct stat st; + uint32_t id; + + assert(msg); + assert(m); + + r = bus_verify_polkit_async( + msg, + CAP_SYS_ADMIN, + "org.freedesktop.import1.export", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = sd_bus_message_read(msg, "shs", &local, &fd, &format); + if (r < 0) + return r; + + if (!machine_name_is_valid(local)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode)) + return -EINVAL; + + type = streq_ptr(sd_bus_message_get_member(msg), "ExportTar") ? TRANSFER_EXPORT_TAR : TRANSFER_EXPORT_RAW; + + r = transfer_new(m, &t); + if (r < 0) + return r; + + t->type = type; + + if (!isempty(format)) { + t->format = strdup(format); + if (!t->format) + return -ENOMEM; + } + + t->local = strdup(local); + if (!t->local) + return -ENOMEM; + + t->stdout_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (t->stdout_fd < 0) + return -errno; + + r = transfer_start(t); + if (r < 0) + return r; + + object = t->object_path; + id = t->id; + t = NULL; + + return sd_bus_reply_method_return(msg, "uo", id, object); +} + +static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) { + _cleanup_(transfer_unrefp) Transfer *t = NULL; + const char *remote, *local, *verify, *object; + Manager *m = userdata; + ImportVerify v; + TransferType type; + int force, r; + uint32_t id; + + assert(msg); + assert(m); + + r = bus_verify_polkit_async( + msg, + CAP_SYS_ADMIN, + "org.freedesktop.import1.pull", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = sd_bus_message_read(msg, "sssb", &remote, &local, &verify, &force); + if (r < 0) + return r; + + if (!http_url_is_valid(remote)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "URL %s is invalid", remote); + + if (isempty(local)) + local = NULL; + else if (!machine_name_is_valid(local)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local); + + if (isempty(verify)) + v = IMPORT_VERIFY_SIGNATURE; + else + v = import_verify_from_string(verify); + if (v < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown verification mode %s", verify); + + r = setup_machine_directory(error); + if (r < 0) + return r; + + type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ? TRANSFER_PULL_TAR : TRANSFER_PULL_RAW; + + if (manager_find(m, type, remote)) + return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote); + + r = transfer_new(m, &t); + if (r < 0) + return r; + + t->type = type; + t->verify = v; + t->force_local = force; + + t->remote = strdup(remote); + if (!t->remote) + return -ENOMEM; + + if (local) { + t->local = strdup(local); + if (!t->local) + return -ENOMEM; + } + + r = transfer_start(t); + if (r < 0) + return r; + + object = t->object_path; + id = t->id; + t = NULL; + + return sd_bus_reply_method_return(msg, "uo", id, object); +} + +static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + Transfer *t; + Iterator i; + int r; + + assert(msg); + assert(m); + + r = sd_bus_message_new_method_return(msg, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(usssdo)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(t, m->transfers, i) { + + r = sd_bus_message_append( + reply, + "(usssdo)", + t->id, + transfer_type_to_string(t->type), + t->remote, + t->local, + transfer_percent_as_double(t), + t->object_path); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_cancel(sd_bus_message *msg, void *userdata, sd_bus_error *error) { + Transfer *t = userdata; + int r; + + assert(msg); + assert(t); + + r = bus_verify_polkit_async( + msg, + CAP_SYS_ADMIN, + "org.freedesktop.import1.pull", + NULL, + false, + UID_INVALID, + &t->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = transfer_cancel(t); + if (r < 0) + return r; + + return sd_bus_reply_method_return(msg, NULL); +} + +static int method_cancel_transfer(sd_bus_message *msg, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + Transfer *t; + uint32_t id; + int r; + + assert(msg); + assert(m); + + r = bus_verify_polkit_async( + msg, + CAP_SYS_ADMIN, + "org.freedesktop.import1.pull", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = sd_bus_message_read(msg, "u", &id); + if (r < 0) + return r; + if (id <= 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid transfer id"); + + t = hashmap_get(m->transfers, UINT32_TO_PTR(id)); + if (!t) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_TRANSFER, "No transfer by id %" PRIu32, id); + + r = transfer_cancel(t); + if (r < 0) + return r; + + return sd_bus_reply_method_return(msg, NULL); +} + +static int property_get_progress( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Transfer *t = userdata; + + assert(bus); + assert(reply); + assert(t); + + return sd_bus_message_append(reply, "d", transfer_percent_as_double(t)); +} + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, transfer_type, TransferType); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_verify, import_verify, ImportVerify); + +static const sd_bus_vtable transfer_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Id", "u", NULL, offsetof(Transfer, id), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Local", "s", NULL, offsetof(Transfer, local), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Remote", "s", NULL, offsetof(Transfer, remote), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Transfer, type), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Verify", "s", property_get_verify, offsetof(Transfer, verify), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0), + SD_BUS_METHOD("Cancel", NULL, NULL, method_cancel, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_SIGNAL("LogMessage", "us", 0), + SD_BUS_VTABLE_END, +}; + +static const sd_bus_vtable manager_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD("ImportTar", "hsbb", "uo", method_import_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ImportRaw", "hsbb", "uo", method_import_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ImportFileSystem", "hsbb", "uo", method_import_fs, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ExportTar", "shs", "uo", method_export_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ExportRaw", "shs", "uo", method_export_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("PullTar", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("PullRaw", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListTransfers", NULL, "a(usssdo)", method_list_transfers, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CancelTransfer", "u", NULL, method_cancel_transfer, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_SIGNAL("TransferNew", "uo", 0), + SD_BUS_SIGNAL("TransferRemoved", "uos", 0), + SD_BUS_VTABLE_END, +}; + +static int transfer_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + Transfer *t; + const char *p; + uint32_t id; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + p = startswith(path, "/org/freedesktop/import1/transfer/_"); + if (!p) + return 0; + + r = safe_atou32(p, &id); + if (r < 0 || id == 0) + return 0; + + t = hashmap_get(m->transfers, UINT32_TO_PTR(id)); + if (!t) + return 0; + + *found = t; + return 1; +} + +static int transfer_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + Transfer *t; + unsigned k = 0; + Iterator i; + + l = new0(char*, hashmap_size(m->transfers) + 1); + if (!l) + return -ENOMEM; + + HASHMAP_FOREACH(t, m->transfers, i) { + + l[k] = strdup(t->object_path); + if (!l[k]) + return -ENOMEM; + + k++; + } + + *nodes = TAKE_PTR(l); + + return 1; +} + +static int manager_add_bus_objects(Manager *m) { + int r; + + assert(m); + + r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/import1", "org.freedesktop.import1.Manager", manager_vtable, m); + if (r < 0) + return log_error_errno(r, "Failed to register object: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/import1/transfer", "org.freedesktop.import1.Transfer", transfer_vtable, transfer_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to register object: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/import1/transfer", transfer_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add transfer enumerator: %m"); + + r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.import1", 0, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + r = sd_bus_attach_event(m->bus, m->event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + return 0; +} + +static bool manager_check_idle(void *userdata) { + Manager *m = userdata; + + return hashmap_isempty(m->transfers); +} + +static int manager_run(Manager *m) { + assert(m); + + return bus_event_loop_with_idle( + m->event, + m->bus, + "org.freedesktop.import1", + DEFAULT_EXIT_USEC, + manager_check_idle, + m); +} + +static int run(int argc, char *argv[]) { + _cleanup_(manager_unrefp) Manager *m = NULL; + int r; + + log_setup_service(); + + umask(0022); + + if (argc != 1) { + log_error("This program takes no arguments."); + return -EINVAL; + } + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); + + r = manager_new(&m); + if (r < 0) + return log_error_errno(r, "Failed to allocate manager object: %m"); + + r = manager_add_bus_objects(m); + if (r < 0) + return r; + + r = manager_run(m); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/import/meson.build b/src/import/meson.build new file mode 100644 index 00000000..1c15fd88 --- /dev/null +++ b/src/import/meson.build @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +systemd_importd_sources = files(''' + importd.c +'''.split()) + +systemd_pull_sources = files(''' + pull.c + pull-raw.c + pull-raw.h + pull-tar.c + pull-tar.h + pull-job.c + pull-job.h + pull-common.c + pull-common.h + import-common.c + import-common.h + import-compress.c + import-compress.h + curl-util.c + curl-util.h + qcow2-util.c + qcow2-util.h +'''.split()) + +systemd_import_sources = files(''' + import.c + import-raw.c + import-raw.h + import-tar.c + import-tar.h + import-common.c + import-common.h + import-compress.c + import-compress.h + qcow2-util.c + qcow2-util.h +'''.split()) + +systemd_import_fs_sources = files(''' + import-fs.c + import-common.c + import-common.h +'''.split()) + +systemd_export_sources = files(''' + export.c + export-tar.c + export-tar.h + export-raw.c + export-raw.h + import-common.c + import-common.h + import-compress.c + import-compress.h +'''.split()) + +if conf.get('ENABLE_IMPORTD') == 1 + install_data('org.freedesktop.import1.conf', + install_dir : dbuspolicydir) + install_data('org.freedesktop.import1.service', + install_dir : dbussystemservicedir) + install_data('org.freedesktop.import1.policy', + install_dir : polkitpolicydir) + + install_data('import-pubring.gpg', + install_dir : rootlibexecdir) + # TODO: shouldn't this be in pkgdatadir? +endif + +tests += [ + [['src/import/test-qcow2.c', + 'src/import/qcow2-util.c', + 'src/import/qcow2-util.h'], + [libshared], + [libz], + 'HAVE_ZLIB', 'manual'], +] diff --git a/src/import/org.freedesktop.import1.conf b/src/import/org.freedesktop.import1.conf new file mode 100644 index 00000000..2fdb2ba7 --- /dev/null +++ b/src/import/org.freedesktop.import1.conf @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/import/org.freedesktop.import1.policy b/src/import/org.freedesktop.import1.policy new file mode 100644 index 00000000..beea5fea --- /dev/null +++ b/src/import/org.freedesktop.import1.policy @@ -0,0 +1,51 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Import a VM or container image + Authentication is required to import a VM or container image + + auth_admin + auth_admin + auth_admin_keep + + + + + Export a VM or container image + Authentication is required to export a VM or container image + + auth_admin + auth_admin + auth_admin_keep + + + + + Download a VM or container image + Authentication is required to download a VM or container image + + auth_admin + auth_admin + auth_admin_keep + + + + diff --git a/src/import/org.freedesktop.import1.service b/src/import/org.freedesktop.import1.service new file mode 100644 index 00000000..34d26d07 --- /dev/null +++ b/src/import/org.freedesktop.import1.service @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.import1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.import1.service diff --git a/src/import/pull-common.c b/src/import/pull-common.c new file mode 100644 index 00000000..249ea533 --- /dev/null +++ b/src/import/pull-common.c @@ -0,0 +1,528 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "capability-util.h" +#include "copy.h" +#include "dirent-util.h" +#include "escape.h" +#include "fd-util.h" +#include "io-util.h" +#include "path-util.h" +#include "process-util.h" +#include "pull-common.h" +#include "pull-job.h" +#include "rlimit-util.h" +#include "rm-rf.h" +#include "signal-util.h" +#include "siphash24.h" +#include "string-util.h" +#include "strv.h" +#include "util.h" +#include "web-util.h" + +#define FILENAME_ESCAPE "/.#\"\'" +#define HASH_URL_THRESHOLD_LENGTH (_POSIX_PATH_MAX - 16) + +int pull_find_old_etags( + const char *url, + const char *image_root, + int dt, + const char *prefix, + const char *suffix, + char ***etags) { + + _cleanup_free_ char *escaped_url = NULL; + _cleanup_closedir_ DIR *d = NULL; + _cleanup_strv_free_ char **l = NULL; + struct dirent *de; + int r; + + assert(url); + assert(etags); + + if (!image_root) + image_root = "/var/lib/machines"; + + escaped_url = xescape(url, FILENAME_ESCAPE); + if (!escaped_url) + return -ENOMEM; + + d = opendir(image_root); + if (!d) { + if (errno == ENOENT) { + *etags = NULL; + return 0; + } + + return -errno; + } + + FOREACH_DIRENT_ALL(de, d, return -errno) { + _cleanup_free_ char *u = NULL; + const char *a, *b; + + if (de->d_type != DT_UNKNOWN && + de->d_type != dt) + continue; + + if (prefix) { + a = startswith(de->d_name, prefix); + if (!a) + continue; + } else + a = de->d_name; + + a = startswith(a, escaped_url); + if (!a) + continue; + + a = startswith(a, "."); + if (!a) + continue; + + if (suffix) { + b = endswith(de->d_name, suffix); + if (!b) + continue; + } else + b = strchr(de->d_name, 0); + + if (a >= b) + continue; + + r = cunescape_length(a, b - a, 0, &u); + if (r < 0) + return r; + + if (!http_etag_is_valid(u)) + continue; + + r = strv_consume(&l, TAKE_PTR(u)); + if (r < 0) + return r; + } + + *etags = TAKE_PTR(l); + + return 0; +} + +int pull_make_local_copy(const char *final, const char *image_root, const char *local, bool force_local) { + const char *p; + int r; + + assert(final); + assert(local); + + if (!image_root) + image_root = "/var/lib/machines"; + + p = prefix_roota(image_root, local); + + if (force_local) + (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + + r = btrfs_subvol_snapshot(final, p, + BTRFS_SNAPSHOT_QUOTA| + BTRFS_SNAPSHOT_FALLBACK_COPY| + BTRFS_SNAPSHOT_FALLBACK_DIRECTORY| + BTRFS_SNAPSHOT_RECURSIVE); + if (r < 0) + return log_error_errno(r, "Failed to create local image: %m"); + + log_info("Created new local image '%s'.", local); + + return 0; +} + +static int hash_url(const char *url, char **ret) { + uint64_t h; + static const sd_id128_t k = SD_ID128_ARRAY(df,89,16,87,01,cc,42,30,98,ab,4a,19,a6,a5,63,4f); + + assert(url); + + h = siphash24(url, strlen(url), k.bytes); + if (asprintf(ret, "%"PRIx64, h) < 0) + return -ENOMEM; + + return 0; +} + +int pull_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret) { + _cleanup_free_ char *escaped_url = NULL, *escaped_etag = NULL; + char *path; + + assert(url); + assert(ret); + + if (!image_root) + image_root = "/var/lib/machines"; + + escaped_url = xescape(url, FILENAME_ESCAPE); + if (!escaped_url) + return -ENOMEM; + + if (etag) { + escaped_etag = xescape(etag, FILENAME_ESCAPE); + if (!escaped_etag) + return -ENOMEM; + } + + path = strjoin(image_root, "/", strempty(prefix), escaped_url, escaped_etag ? "." : "", + strempty(escaped_etag), strempty(suffix)); + if (!path) + return -ENOMEM; + + /* URLs might make the path longer than the maximum allowed length for a file name. + * When that happens, a URL hash is used instead. Paths returned by this function + * can be later used with tempfn_random() which adds 16 bytes to the resulting name. */ + if (strlen(path) >= HASH_URL_THRESHOLD_LENGTH) { + _cleanup_free_ char *hash = NULL; + int r; + + free(path); + + r = hash_url(url, &hash); + if (r < 0) + return r; + + path = strjoin(image_root, "/", strempty(prefix), hash, escaped_etag ? "." : "", + strempty(escaped_etag), strempty(suffix)); + if (!path) + return -ENOMEM; + } + + *ret = path; + return 0; +} + +int pull_make_auxiliary_job( + PullJob **ret, + const char *url, + int (*strip_suffixes)(const char *name, char **ret), + const char *suffix, + CurlGlue *glue, + PullJobFinished on_finished, + void *userdata) { + + _cleanup_free_ char *last_component = NULL, *ll = NULL, *auxiliary_url = NULL; + _cleanup_(pull_job_unrefp) PullJob *job = NULL; + const char *q; + int r; + + assert(ret); + assert(url); + assert(strip_suffixes); + assert(glue); + + r = import_url_last_component(url, &last_component); + if (r < 0) + return r; + + r = strip_suffixes(last_component, &ll); + if (r < 0) + return r; + + q = strjoina(ll, suffix); + + r = import_url_change_last_component(url, q, &auxiliary_url); + if (r < 0) + return r; + + r = pull_job_new(&job, auxiliary_url, glue, userdata); + if (r < 0) + return r; + + job->on_finished = on_finished; + job->compressed_max = job->uncompressed_max = 1ULL * 1024ULL * 1024ULL; + + *ret = TAKE_PTR(job); + + return 0; +} + +int pull_make_verification_jobs( + PullJob **ret_checksum_job, + PullJob **ret_signature_job, + ImportVerify verify, + const char *url, + CurlGlue *glue, + PullJobFinished on_finished, + void *userdata) { + + _cleanup_(pull_job_unrefp) PullJob *checksum_job = NULL, *signature_job = NULL; + int r; + const char *chksums = NULL; + + assert(ret_checksum_job); + assert(ret_signature_job); + assert(verify >= 0); + assert(verify < _IMPORT_VERIFY_MAX); + assert(url); + assert(glue); + + if (verify != IMPORT_VERIFY_NO) { + _cleanup_free_ char *checksum_url = NULL, *fn = NULL; + + /* Queue jobs for the checksum file for the image. */ + r = import_url_last_component(url, &fn); + if (r < 0) + return r; + + chksums = strjoina(fn, ".sha256"); + + r = import_url_change_last_component(url, chksums, &checksum_url); + if (r < 0) + return r; + + r = pull_job_new(&checksum_job, checksum_url, glue, userdata); + if (r < 0) + return r; + + checksum_job->on_finished = on_finished; + checksum_job->uncompressed_max = checksum_job->compressed_max = 1ULL * 1024ULL * 1024ULL; + } + + if (verify == IMPORT_VERIFY_SIGNATURE) { + _cleanup_free_ char *signature_url = NULL; + + /* Queue job for the SHA256SUMS.gpg file for the image. */ + r = import_url_change_last_component(url, "SHA256SUMS.gpg", &signature_url); + if (r < 0) + return r; + + r = pull_job_new(&signature_job, signature_url, glue, userdata); + if (r < 0) + return r; + + signature_job->on_finished = on_finished; + signature_job->uncompressed_max = signature_job->compressed_max = 1ULL * 1024ULL * 1024ULL; + } + + *ret_checksum_job = checksum_job; + *ret_signature_job = signature_job; + + checksum_job = signature_job = NULL; + + return 0; +} + +static int verify_one(PullJob *checksum_job, PullJob *job) { + _cleanup_free_ char *fn = NULL; + const char *line, *p; + int r; + + assert(checksum_job); + + if (!job) + return 0; + + assert(IN_SET(job->state, PULL_JOB_DONE, PULL_JOB_FAILED)); + + /* Don't verify the checksum if we didn't actually successfully download something new */ + if (job->state != PULL_JOB_DONE) + return 0; + if (job->error != 0) + return 0; + if (job->etag_exists) + return 0; + + assert(job->calc_checksum); + assert(job->checksum); + + r = import_url_last_component(job->url, &fn); + if (r < 0) + return log_oom(); + + if (!filename_is_valid(fn)) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Cannot verify checksum, could not determine server-side file name."); + + line = strjoina(job->checksum, " *", fn, "\n"); + + p = memmem(checksum_job->payload, + checksum_job->payload_size, + line, + strlen(line)); + + if (!p) { + line = strjoina(job->checksum, " ", fn, "\n"); + + p = memmem(checksum_job->payload, + checksum_job->payload_size, + line, + strlen(line)); + } + + if (!p || (p != (char*) checksum_job->payload && p[-1] != '\n')) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "DOWNLOAD INVALID: Checksum of %s file did not checkout, file has been tampered with.", fn); + + log_info("SHA256 checksum of %s is valid.", job->url); + return 1; +} + +int pull_verify(PullJob *main_job, + PullJob *roothash_job, + PullJob *settings_job, + PullJob *checksum_job, + PullJob *signature_job) { + + _cleanup_close_pair_ int gpg_pipe[2] = { -1, -1 }; + _cleanup_close_ int sig_file = -1; + char sig_file_path[] = "/tmp/sigXXXXXX", gpg_home[] = "/tmp/gpghomeXXXXXX"; + _cleanup_(sigkill_waitp) pid_t pid = 0; + bool gpg_home_created = false; + int r; + + assert(main_job); + assert(main_job->state == PULL_JOB_DONE); + + if (!checksum_job) + return 0; + + assert(main_job->calc_checksum); + assert(main_job->checksum); + + assert(checksum_job->state == PULL_JOB_DONE); + + if (!checksum_job->payload || checksum_job->payload_size <= 0) { + log_error("Checksum is empty, cannot verify."); + return -EBADMSG; + } + + r = verify_one(checksum_job, main_job); + if (r < 0) + return r; + + r = verify_one(checksum_job, roothash_job); + if (r < 0) + return r; + + r = verify_one(checksum_job, settings_job); + if (r < 0) + return r; + + if (!signature_job) + return 0; + + if (checksum_job->style == VERIFICATION_PER_FILE) + signature_job = checksum_job; + + assert(signature_job->state == PULL_JOB_DONE); + + if (!signature_job->payload || signature_job->payload_size <= 0) { + log_error("Signature is empty, cannot verify."); + return -EBADMSG; + } + + r = pipe2(gpg_pipe, O_CLOEXEC); + if (r < 0) + return log_error_errno(errno, "Failed to create pipe for gpg: %m"); + + sig_file = mkostemp(sig_file_path, O_RDWR); + if (sig_file < 0) + return log_error_errno(errno, "Failed to create temporary file: %m"); + + r = loop_write(sig_file, signature_job->payload, signature_job->payload_size, false); + if (r < 0) { + log_error_errno(r, "Failed to write to temporary file: %m"); + goto finish; + } + + if (!mkdtemp(gpg_home)) { + r = log_error_errno(errno, "Failed to create temporary home for gpg: %m"); + goto finish; + } + + gpg_home_created = true; + + r = safe_fork("(gpg)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + const char *cmd[] = { + "gpg", + "--no-options", + "--no-default-keyring", + "--no-auto-key-locate", + "--no-auto-check-trustdb", + "--batch", + "--trust-model=always", + NULL, /* --homedir= */ + NULL, /* --keyring= */ + NULL, /* --verify */ + NULL, /* signature file */ + NULL, /* dash */ + NULL /* trailing NULL */ + }; + unsigned k = ELEMENTSOF(cmd) - 6; + + /* Child */ + + gpg_pipe[1] = safe_close(gpg_pipe[1]); + + r = rearrange_stdio(gpg_pipe[0], -1, STDERR_FILENO); + if (r < 0) { + log_error_errno(r, "Failed to rearrange stdin/stdout: %m"); + _exit(EXIT_FAILURE); + } + + (void) rlimit_nofile_safe(); + + cmd[k++] = strjoina("--homedir=", gpg_home); + + /* We add the user keyring only to the command line + * arguments, if it's around since gpg fails + * otherwise. */ + if (access(USER_KEYRING_PATH, F_OK) >= 0) + cmd[k++] = "--keyring=" USER_KEYRING_PATH; + else + cmd[k++] = "--keyring=" VENDOR_KEYRING_PATH; + + cmd[k++] = "--verify"; + if (checksum_job->style == VERIFICATION_PER_DIRECTORY) { + cmd[k++] = sig_file_path; + cmd[k++] = "-"; + cmd[k++] = NULL; + } + + execvp("gpg2", (char * const *) cmd); + execvp("gpg", (char * const *) cmd); + log_error_errno(errno, "Failed to execute gpg: %m"); + _exit(EXIT_FAILURE); + } + + gpg_pipe[0] = safe_close(gpg_pipe[0]); + + r = loop_write(gpg_pipe[1], checksum_job->payload, checksum_job->payload_size, false); + if (r < 0) { + log_error_errno(r, "Failed to write to pipe: %m"); + goto finish; + } + + gpg_pipe[1] = safe_close(gpg_pipe[1]); + + r = wait_for_terminate_and_check("gpg", pid, WAIT_LOG_ABNORMAL); + pid = 0; + if (r < 0) + goto finish; + if (r != EXIT_SUCCESS) { + log_error("DOWNLOAD INVALID: Signature verification failed."); + r = -EBADMSG; + } else { + log_info("Signature verification succeeded."); + r = 0; + } + +finish: + (void) unlink(sig_file_path); + + if (gpg_home_created) + (void) rm_rf(gpg_home, REMOVE_ROOT|REMOVE_PHYSICAL); + + return r; +} diff --git a/src/import/pull-common.h b/src/import/pull-common.h new file mode 100644 index 00000000..65f239da --- /dev/null +++ b/src/import/pull-common.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "import-util.h" +#include "pull-job.h" + +int pull_make_local_copy(const char *final, const char *root, const char *local, bool force_local); + +int pull_find_old_etags(const char *url, const char *root, int dt, const char *prefix, const char *suffix, char ***etags); + +int pull_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret); + +int pull_make_auxiliary_job(PullJob **ret, const char *url, int (*strip_suffixes)(const char *name, char **ret), const char *suffix, CurlGlue *glue, PullJobFinished on_finished, void *userdata); +int pull_make_verification_jobs(PullJob **ret_checksum_job, PullJob **ret_signature_job, ImportVerify verify, const char *url, CurlGlue *glue, PullJobFinished on_finished, void *userdata); + +int pull_verify(PullJob *main_job, PullJob *roothash_job, PullJob *settings_job, PullJob *checksum_job, PullJob *signature_job); diff --git a/src/import/pull-job.c b/src/import/pull-job.c new file mode 100644 index 00000000..45617945 --- /dev/null +++ b/src/import/pull-job.c @@ -0,0 +1,639 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "gcrypt-util.h" +#include "hexdecoct.h" +#include "import-util.h" +#include "io-util.h" +#include "machine-pool.h" +#include "parse-util.h" +#include "pull-common.h" +#include "pull-job.h" +#include "string-util.h" +#include "strv.h" +#include "xattr-util.h" + +PullJob* pull_job_unref(PullJob *j) { + if (!j) + return NULL; + + curl_glue_remove_and_free(j->glue, j->curl); + curl_slist_free_all(j->request_header); + + safe_close(j->disk_fd); + + import_compress_free(&j->compress); + + if (j->checksum_context) + gcry_md_close(j->checksum_context); + + free(j->url); + free(j->etag); + strv_free(j->old_etags); + free(j->payload); + free(j->checksum); + + return mfree(j); +} + +static void pull_job_finish(PullJob *j, int ret) { + assert(j); + + if (IN_SET(j->state, PULL_JOB_DONE, PULL_JOB_FAILED)) + return; + + if (ret == 0) { + j->state = PULL_JOB_DONE; + j->progress_percent = 100; + log_info("Download of %s complete.", j->url); + } else { + j->state = PULL_JOB_FAILED; + j->error = ret; + } + + if (j->on_finished) + j->on_finished(j); +} + +static int pull_job_restart(PullJob *j) { + int r; + char *chksum_url = NULL; + + r = import_url_change_last_component(j->url, "SHA256SUMS", &chksum_url); + if (r < 0) + return r; + + free(j->url); + j->url = chksum_url; + j->state = PULL_JOB_INIT; + j->payload = mfree(j->payload); + j->payload_size = 0; + j->payload_allocated = 0; + j->written_compressed = 0; + j->written_uncompressed = 0; + + r = pull_job_begin(j); + if (r < 0) + return r; + + return 0; +} + +void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) { + PullJob *j = NULL; + CURLcode code; + long status; + int r; + + if (curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&j) != CURLE_OK) + return; + + if (!j || IN_SET(j->state, PULL_JOB_DONE, PULL_JOB_FAILED)) + return; + + if (result != CURLE_OK) { + log_error("Transfer failed: %s", curl_easy_strerror(result)); + r = -EIO; + goto finish; + } + + code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status); + if (code != CURLE_OK) { + log_error("Failed to retrieve response code: %s", curl_easy_strerror(code)); + r = -EIO; + goto finish; + } else if (status == 304) { + log_info("Image already downloaded. Skipping download."); + j->etag_exists = true; + r = 0; + goto finish; + } else if (status >= 300) { + if (status == 404 && j->style == VERIFICATION_PER_FILE) { + + /* retry pull job with SHA256SUMS file */ + r = pull_job_restart(j); + if (r < 0) + goto finish; + + code = curl_easy_getinfo(j->curl, CURLINFO_RESPONSE_CODE, &status); + if (code != CURLE_OK) { + log_error("Failed to retrieve response code: %s", curl_easy_strerror(code)); + r = -EIO; + goto finish; + } + + if (status == 0) { + j->style = VERIFICATION_PER_DIRECTORY; + return; + } + } + + log_error("HTTP request to %s failed with code %li.", j->url, status); + r = -EIO; + goto finish; + } else if (status < 200) { + log_error("HTTP request to %s finished with unexpected code %li.", j->url, status); + r = -EIO; + goto finish; + } + + if (j->state != PULL_JOB_RUNNING) { + log_error("Premature connection termination."); + r = -EIO; + goto finish; + } + + if (j->content_length != (uint64_t) -1 && + j->content_length != j->written_compressed) { + log_error("Download truncated."); + r = -EIO; + goto finish; + } + + if (j->checksum_context) { + uint8_t *k; + + k = gcry_md_read(j->checksum_context, GCRY_MD_SHA256); + if (!k) { + log_error("Failed to get checksum."); + r = -EIO; + goto finish; + } + + j->checksum = hexmem(k, gcry_md_get_algo_dlen(GCRY_MD_SHA256)); + if (!j->checksum) { + r = log_oom(); + goto finish; + } + + log_debug("SHA256 of %s is %s.", j->url, j->checksum); + } + + if (j->disk_fd >= 0 && j->allow_sparse) { + /* Make sure the file size is right, in case the file was + * sparse and we just seeked for the last part */ + + if (ftruncate(j->disk_fd, j->written_uncompressed) < 0) { + r = log_error_errno(errno, "Failed to truncate file: %m"); + goto finish; + } + + if (j->etag) + (void) fsetxattr(j->disk_fd, "user.source_etag", j->etag, strlen(j->etag), 0); + if (j->url) + (void) fsetxattr(j->disk_fd, "user.source_url", j->url, strlen(j->url), 0); + + if (j->mtime != 0) { + struct timespec ut[2]; + + timespec_store(&ut[0], j->mtime); + ut[1] = ut[0]; + (void) futimens(j->disk_fd, ut); + + (void) fd_setcrtime(j->disk_fd, j->mtime); + } + } + + r = 0; + +finish: + pull_job_finish(j, r); +} + +static int pull_job_write_uncompressed(const void *p, size_t sz, void *userdata) { + PullJob *j = userdata; + ssize_t n; + + assert(j); + assert(p); + + if (sz <= 0) + return 0; + + if (j->written_uncompressed + sz < j->written_uncompressed) + return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), + "File too large, overflow"); + + if (j->written_uncompressed + sz > j->uncompressed_max) + return log_error_errno(SYNTHETIC_ERRNO(EFBIG), + "File overly large, refusing"); + + if (j->disk_fd >= 0) { + + if (j->allow_sparse) + n = sparse_write(j->disk_fd, p, sz, 64); + else { + n = write(j->disk_fd, p, sz); + if (n < 0) + n = -errno; + } + if (n < 0) + return log_error_errno((int) n, "Failed to write file: %m"); + if ((size_t) n < sz) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write"); + } else { + + if (!GREEDY_REALLOC(j->payload, j->payload_allocated, j->payload_size + sz)) + return log_oom(); + + memcpy(j->payload + j->payload_size, p, sz); + j->payload_size += sz; + } + + j->written_uncompressed += sz; + + return 0; +} + +static int pull_job_write_compressed(PullJob *j, void *p, size_t sz) { + int r; + + assert(j); + assert(p); + + if (sz <= 0) + return 0; + + if (j->written_compressed + sz < j->written_compressed) + return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "File too large, overflow"); + + if (j->written_compressed + sz > j->compressed_max) + return log_error_errno(SYNTHETIC_ERRNO(EFBIG), "File overly large, refusing."); + + if (j->content_length != (uint64_t) -1 && + j->written_compressed + sz > j->content_length) + return log_error_errno(SYNTHETIC_ERRNO(EFBIG), + "Content length incorrect."); + + if (j->checksum_context) + gcry_md_write(j->checksum_context, p, sz); + + r = import_uncompress(&j->compress, p, sz, pull_job_write_uncompressed, j); + if (r < 0) + return r; + + j->written_compressed += sz; + + return 0; +} + +static int pull_job_open_disk(PullJob *j) { + int r; + + assert(j); + + if (j->on_open_disk) { + r = j->on_open_disk(j); + if (r < 0) + return r; + } + + if (j->disk_fd >= 0) { + /* Check if we can do sparse files */ + + if (lseek(j->disk_fd, SEEK_SET, 0) == 0) + j->allow_sparse = true; + else { + if (errno != ESPIPE) + return log_error_errno(errno, "Failed to seek on file descriptor: %m"); + + j->allow_sparse = false; + } + } + + if (j->calc_checksum) { + initialize_libgcrypt(false); + + if (gcry_md_open(&j->checksum_context, GCRY_MD_SHA256, 0) != 0) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Failed to initialize hash context."); + } + + return 0; +} + +static int pull_job_detect_compression(PullJob *j) { + _cleanup_free_ uint8_t *stub = NULL; + size_t stub_size; + + int r; + + assert(j); + + r = import_uncompress_detect(&j->compress, j->payload, j->payload_size); + if (r < 0) + return log_error_errno(r, "Failed to initialize compressor: %m"); + if (r == 0) + return 0; + + log_debug("Stream is compressed: %s", import_compress_type_to_string(j->compress.type)); + + r = pull_job_open_disk(j); + if (r < 0) + return r; + + /* Now, take the payload we read so far, and decompress it */ + stub = j->payload; + stub_size = j->payload_size; + + j->payload = NULL; + j->payload_size = 0; + j->payload_allocated = 0; + + j->state = PULL_JOB_RUNNING; + + r = pull_job_write_compressed(j, stub, stub_size); + if (r < 0) + return r; + + return 0; +} + +static size_t pull_job_write_callback(void *contents, size_t size, size_t nmemb, void *userdata) { + PullJob *j = userdata; + size_t sz = size * nmemb; + int r; + + assert(contents); + assert(j); + + switch (j->state) { + + case PULL_JOB_ANALYZING: + /* Let's first check what it actually is */ + + if (!GREEDY_REALLOC(j->payload, j->payload_allocated, j->payload_size + sz)) { + r = log_oom(); + goto fail; + } + + memcpy(j->payload + j->payload_size, contents, sz); + j->payload_size += sz; + + r = pull_job_detect_compression(j); + if (r < 0) + goto fail; + + break; + + case PULL_JOB_RUNNING: + + r = pull_job_write_compressed(j, contents, sz); + if (r < 0) + goto fail; + + break; + + case PULL_JOB_DONE: + case PULL_JOB_FAILED: + r = -ESTALE; + goto fail; + + default: + assert_not_reached("Impossible state."); + } + + return sz; + +fail: + pull_job_finish(j, r); + return 0; +} + +static size_t pull_job_header_callback(void *contents, size_t size, size_t nmemb, void *userdata) { + PullJob *j = userdata; + size_t sz = size * nmemb; + _cleanup_free_ char *length = NULL, *last_modified = NULL; + char *etag; + int r; + + assert(contents); + assert(j); + + if (IN_SET(j->state, PULL_JOB_DONE, PULL_JOB_FAILED)) { + r = -ESTALE; + goto fail; + } + + assert(j->state == PULL_JOB_ANALYZING); + + r = curl_header_strdup(contents, sz, "ETag:", &etag); + if (r < 0) { + log_oom(); + goto fail; + } + if (r > 0) { + free(j->etag); + j->etag = etag; + + if (strv_contains(j->old_etags, j->etag)) { + log_info("Image already downloaded. Skipping download."); + j->etag_exists = true; + pull_job_finish(j, 0); + return sz; + } + + return sz; + } + + r = curl_header_strdup(contents, sz, "Content-Length:", &length); + if (r < 0) { + log_oom(); + goto fail; + } + if (r > 0) { + (void) safe_atou64(length, &j->content_length); + + if (j->content_length != (uint64_t) -1) { + char bytes[FORMAT_BYTES_MAX]; + + if (j->content_length > j->compressed_max) { + log_error("Content too large."); + r = -EFBIG; + goto fail; + } + + log_info("Downloading %s for %s.", format_bytes(bytes, sizeof(bytes), j->content_length), j->url); + } + + return sz; + } + + r = curl_header_strdup(contents, sz, "Last-Modified:", &last_modified); + if (r < 0) { + log_oom(); + goto fail; + } + if (r > 0) { + (void) curl_parse_http_time(last_modified, &j->mtime); + return sz; + } + + if (j->on_header) { + r = j->on_header(j, contents, sz); + if (r < 0) + goto fail; + } + + return sz; + +fail: + pull_job_finish(j, r); + return 0; +} + +static int pull_job_progress_callback(void *userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { + PullJob *j = userdata; + unsigned percent; + usec_t n; + + assert(j); + + if (dltotal <= 0) + return 0; + + percent = ((100 * dlnow) / dltotal); + n = now(CLOCK_MONOTONIC); + + if (n > j->last_status_usec + USEC_PER_SEC && + percent != j->progress_percent && + dlnow < dltotal) { + char buf[FORMAT_TIMESPAN_MAX]; + + if (n - j->start_usec > USEC_PER_SEC && dlnow > 0) { + char y[FORMAT_BYTES_MAX]; + usec_t left, done; + + done = n - j->start_usec; + left = (usec_t) (((double) done * (double) dltotal) / dlnow) - done; + + log_info("Got %u%% of %s. %s left at %s/s.", + percent, + j->url, + format_timespan(buf, sizeof(buf), left, USEC_PER_SEC), + format_bytes(y, sizeof(y), (uint64_t) ((double) dlnow / ((double) done / (double) USEC_PER_SEC)))); + } else + log_info("Got %u%% of %s.", percent, j->url); + + j->progress_percent = percent; + j->last_status_usec = n; + + if (j->on_progress) + j->on_progress(j); + } + + return 0; +} + +int pull_job_new(PullJob **ret, const char *url, CurlGlue *glue, void *userdata) { + _cleanup_(pull_job_unrefp) PullJob *j = NULL; + _cleanup_free_ char *u = NULL; + + assert(url); + assert(glue); + assert(ret); + + u = strdup(url); + if (!u) + return -ENOMEM; + + j = new(PullJob, 1); + if (!j) + return -ENOMEM; + + *j = (PullJob) { + .state = PULL_JOB_INIT, + .disk_fd = -1, + .userdata = userdata, + .glue = glue, + .content_length = (uint64_t) -1, + .start_usec = now(CLOCK_MONOTONIC), + .compressed_max = 64LLU * 1024LLU * 1024LLU * 1024LLU, /* 64GB safety limit */ + .uncompressed_max = 64LLU * 1024LLU * 1024LLU * 1024LLU, /* 64GB safety limit */ + .style = VERIFICATION_STYLE_UNSET, + .url = TAKE_PTR(u), + }; + + *ret = TAKE_PTR(j); + + return 0; +} + +int pull_job_begin(PullJob *j) { + int r; + + assert(j); + + if (j->state != PULL_JOB_INIT) + return -EBUSY; + + r = curl_glue_make(&j->curl, j->url, j); + if (r < 0) + return r; + + if (!strv_isempty(j->old_etags)) { + _cleanup_free_ char *cc = NULL, *hdr = NULL; + + cc = strv_join(j->old_etags, ", "); + if (!cc) + return -ENOMEM; + + hdr = strjoin("If-None-Match: ", cc); + if (!hdr) + return -ENOMEM; + + if (!j->request_header) { + j->request_header = curl_slist_new(hdr, NULL); + if (!j->request_header) + return -ENOMEM; + } else { + struct curl_slist *l; + + l = curl_slist_append(j->request_header, hdr); + if (!l) + return -ENOMEM; + + j->request_header = l; + } + } + + if (j->request_header) { + if (curl_easy_setopt(j->curl, CURLOPT_HTTPHEADER, j->request_header) != CURLE_OK) + return -EIO; + } + + if (curl_easy_setopt(j->curl, CURLOPT_WRITEFUNCTION, pull_job_write_callback) != CURLE_OK) + return -EIO; + + if (curl_easy_setopt(j->curl, CURLOPT_WRITEDATA, j) != CURLE_OK) + return -EIO; + + if (curl_easy_setopt(j->curl, CURLOPT_HEADERFUNCTION, pull_job_header_callback) != CURLE_OK) + return -EIO; + + if (curl_easy_setopt(j->curl, CURLOPT_HEADERDATA, j) != CURLE_OK) + return -EIO; + + if (curl_easy_setopt(j->curl, CURLOPT_XFERINFOFUNCTION, pull_job_progress_callback) != CURLE_OK) + return -EIO; + + if (curl_easy_setopt(j->curl, CURLOPT_XFERINFODATA, j) != CURLE_OK) + return -EIO; + + if (curl_easy_setopt(j->curl, CURLOPT_NOPROGRESS, 0) != CURLE_OK) + return -EIO; + + r = curl_glue_add(j->glue, j->curl); + if (r < 0) + return r; + + j->state = PULL_JOB_ANALYZING; + + return 0; +} diff --git a/src/import/pull-job.h b/src/import/pull-job.h new file mode 100644 index 00000000..c907e740 --- /dev/null +++ b/src/import/pull-job.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "curl-util.h" +#include "import-compress.h" +#include "macro.h" + +typedef struct PullJob PullJob; + +typedef void (*PullJobFinished)(PullJob *job); +typedef int (*PullJobOpenDisk)(PullJob *job); +typedef int (*PullJobHeader)(PullJob *job, const char *header, size_t sz); +typedef void (*PullJobProgress)(PullJob *job); + +typedef enum PullJobState { + PULL_JOB_INIT, + PULL_JOB_ANALYZING, /* Still reading into ->payload, to figure out what we have */ + PULL_JOB_RUNNING, /* Writing to destination */ + PULL_JOB_DONE, + PULL_JOB_FAILED, + _PULL_JOB_STATE_MAX, + _PULL_JOB_STATE_INVALID = -1, +} PullJobState; + +typedef enum VerificationStyle { + VERIFICATION_STYLE_UNSET, + VERIFICATION_PER_FILE, /* SuSE-style ".sha256" files with inline signature */ + VERIFICATION_PER_DIRECTORY, /* Ubuntu-style SHA256SUM files with detach SHA256SUM.gpg signatures */ +} VerificationStyle; + +#define PULL_JOB_IS_COMPLETE(j) (IN_SET((j)->state, PULL_JOB_DONE, PULL_JOB_FAILED)) + +struct PullJob { + PullJobState state; + int error; + + char *url; + + void *userdata; + PullJobFinished on_finished; + PullJobOpenDisk on_open_disk; + PullJobHeader on_header; + PullJobProgress on_progress; + + CurlGlue *glue; + CURL *curl; + struct curl_slist *request_header; + + char *etag; + char **old_etags; + bool etag_exists; + + uint64_t content_length; + uint64_t written_compressed; + uint64_t written_uncompressed; + + uint64_t uncompressed_max; + uint64_t compressed_max; + + uint8_t *payload; + size_t payload_size; + size_t payload_allocated; + + int disk_fd; + + usec_t mtime; + + ImportCompress compress; + + unsigned progress_percent; + usec_t start_usec; + usec_t last_status_usec; + + bool allow_sparse; + + bool calc_checksum; + gcry_md_hd_t checksum_context; + + char *checksum; + + VerificationStyle style; +}; + +int pull_job_new(PullJob **job, const char *url, CurlGlue *glue, void *userdata); +PullJob* pull_job_unref(PullJob *job); + +int pull_job_begin(PullJob *j); + +void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result); + +DEFINE_TRIVIAL_CLEANUP_FUNC(PullJob*, pull_job_unref); diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c new file mode 100644 index 00000000..4f76421b --- /dev/null +++ b/src/import/pull-raw.c @@ -0,0 +1,750 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "chattr-util.h" +#include "copy.h" +#include "curl-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "import-common.h" +#include "import-util.h" +#include "macro.h" +#include "mkdir.h" +#include "path-util.h" +#include "pull-common.h" +#include "pull-job.h" +#include "pull-raw.h" +#include "qcow2-util.h" +#include "rm-rf.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "utf8.h" +#include "util.h" +#include "web-util.h" + +typedef enum RawProgress { + RAW_DOWNLOADING, + RAW_VERIFYING, + RAW_UNPACKING, + RAW_FINALIZING, + RAW_COPYING, +} RawProgress; + +struct RawPull { + sd_event *event; + CurlGlue *glue; + + char *image_root; + + PullJob *raw_job; + PullJob *roothash_job; + PullJob *settings_job; + PullJob *checksum_job; + PullJob *signature_job; + + RawPullFinished on_finished; + void *userdata; + + char *local; + bool force_local; + bool settings; + bool roothash; + + char *final_path; + char *temp_path; + + char *settings_path; + char *settings_temp_path; + + char *roothash_path; + char *roothash_temp_path; + + ImportVerify verify; +}; + +RawPull* raw_pull_unref(RawPull *i) { + if (!i) + return NULL; + + pull_job_unref(i->raw_job); + pull_job_unref(i->settings_job); + pull_job_unref(i->roothash_job); + pull_job_unref(i->checksum_job); + pull_job_unref(i->signature_job); + + curl_glue_unref(i->glue); + sd_event_unref(i->event); + + if (i->temp_path) { + (void) unlink(i->temp_path); + free(i->temp_path); + } + + if (i->roothash_temp_path) { + (void) unlink(i->roothash_temp_path); + free(i->roothash_temp_path); + } + + if (i->settings_temp_path) { + (void) unlink(i->settings_temp_path); + free(i->settings_temp_path); + } + + free(i->final_path); + free(i->roothash_path); + free(i->settings_path); + free(i->image_root); + free(i->local); + return mfree(i); +} + +int raw_pull_new( + RawPull **ret, + sd_event *event, + const char *image_root, + RawPullFinished on_finished, + void *userdata) { + + _cleanup_(curl_glue_unrefp) CurlGlue *g = NULL; + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_(raw_pull_unrefp) RawPull *i = NULL; + _cleanup_free_ char *root = NULL; + int r; + + assert(ret); + + root = strdup(image_root ?: "/var/lib/machines"); + if (!root) + return -ENOMEM; + + if (event) + e = sd_event_ref(event); + else { + r = sd_event_default(&e); + if (r < 0) + return r; + } + + r = curl_glue_new(&g, e); + if (r < 0) + return r; + + i = new(RawPull, 1); + if (!i) + return -ENOMEM; + + *i = (RawPull) { + .on_finished = on_finished, + .userdata = userdata, + .image_root = TAKE_PTR(root), + .event = TAKE_PTR(e), + .glue = TAKE_PTR(g), + }; + + i->glue->on_finished = pull_job_curl_on_finished; + i->glue->userdata = i; + + *ret = TAKE_PTR(i); + + return 0; +} + +static void raw_pull_report_progress(RawPull *i, RawProgress p) { + unsigned percent; + + assert(i); + + switch (p) { + + case RAW_DOWNLOADING: { + unsigned remain = 80; + + percent = 0; + + if (i->settings_job) { + percent += i->settings_job->progress_percent * 5 / 100; + remain -= 5; + } + + if (i->roothash_job) { + percent += i->roothash_job->progress_percent * 5 / 100; + remain -= 5; + } + + if (i->checksum_job) { + percent += i->checksum_job->progress_percent * 5 / 100; + remain -= 5; + } + + if (i->signature_job) { + percent += i->signature_job->progress_percent * 5 / 100; + remain -= 5; + } + + if (i->raw_job) + percent += i->raw_job->progress_percent * remain / 100; + break; + } + + case RAW_VERIFYING: + percent = 80; + break; + + case RAW_UNPACKING: + percent = 85; + break; + + case RAW_FINALIZING: + percent = 90; + break; + + case RAW_COPYING: + percent = 95; + break; + + default: + assert_not_reached("Unknown progress state"); + } + + sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); + log_debug("Combined progress %u%%", percent); +} + +static int raw_pull_maybe_convert_qcow2(RawPull *i) { + _cleanup_close_ int converted_fd = -1; + _cleanup_free_ char *t = NULL; + int r; + + assert(i); + assert(i->raw_job); + + r = qcow2_detect(i->raw_job->disk_fd); + if (r < 0) + return log_error_errno(r, "Failed to detect whether this is a QCOW2 image: %m"); + if (r == 0) + return 0; + + /* This is a QCOW2 image, let's convert it */ + r = tempfn_random(i->final_path, NULL, &t); + if (r < 0) + return log_oom(); + + converted_fd = open(t, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); + if (converted_fd < 0) + return log_error_errno(errno, "Failed to create %s: %m", t); + + r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); + if (r < 0) + log_warning_errno(r, "Failed to set file attributes on %s: %m", t); + + log_info("Unpacking QCOW2 file."); + + r = qcow2_convert(i->raw_job->disk_fd, converted_fd); + if (r < 0) { + (void) unlink(t); + return log_error_errno(r, "Failed to convert qcow2 image: %m"); + } + + (void) unlink(i->temp_path); + free_and_replace(i->temp_path, t); + + safe_close(i->raw_job->disk_fd); + i->raw_job->disk_fd = TAKE_FD(converted_fd); + + return 1; +} + +static int raw_pull_determine_path(RawPull *i, const char *suffix, char **field) { + int r; + + assert(i); + assert(field); + + if (*field) + return 0; + + assert(i->raw_job); + + r = pull_make_path(i->raw_job->url, i->raw_job->etag, i->image_root, ".raw-", suffix, field); + if (r < 0) + return log_oom(); + + return 1; +} + +static int raw_pull_copy_auxiliary_file( + RawPull *i, + const char *suffix, + char **path) { + + const char *local; + int r; + + assert(i); + assert(suffix); + assert(path); + + r = raw_pull_determine_path(i, suffix, path); + if (r < 0) + return r; + + local = strjoina(i->image_root, "/", i->local, suffix); + + r = copy_file_atomic(*path, local, 0644, 0, 0, COPY_REFLINK | (i->force_local ? COPY_REPLACE : 0)); + if (r == -EEXIST) + log_warning_errno(r, "File %s already exists, not replacing.", local); + else if (r == -ENOENT) + log_debug_errno(r, "Skipping creation of auxiliary file, since none was found."); + else if (r < 0) + log_warning_errno(r, "Failed to copy file %s, ignoring: %m", local); + else + log_info("Created new file %s.", local); + + return 0; +} + +static int raw_pull_make_local_copy(RawPull *i) { + _cleanup_free_ char *tp = NULL; + _cleanup_close_ int dfd = -1; + const char *p; + int r; + + assert(i); + assert(i->raw_job); + + if (!i->local) + return 0; + + if (i->raw_job->etag_exists) { + /* We have downloaded this one previously, reopen it */ + + assert(i->raw_job->disk_fd < 0); + + i->raw_job->disk_fd = open(i->final_path, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (i->raw_job->disk_fd < 0) + return log_error_errno(errno, "Failed to open vendor image: %m"); + } else { + /* We freshly downloaded the image, use it */ + + assert(i->raw_job->disk_fd >= 0); + + if (lseek(i->raw_job->disk_fd, SEEK_SET, 0) == (off_t) -1) + return log_error_errno(errno, "Failed to seek to beginning of vendor image: %m"); + } + + p = strjoina(i->image_root, "/", i->local, ".raw"); + + if (i->force_local) + (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + + r = tempfn_random(p, NULL, &tp); + if (r < 0) + return log_oom(); + + dfd = open(tp, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); + if (dfd < 0) + return log_error_errno(errno, "Failed to create writable copy of image: %m"); + + /* Turn off COW writing. This should greatly improve + * performance on COW file systems like btrfs, since it + * reduces fragmentation caused by not allowing in-place + * writes. */ + r = chattr_fd(dfd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); + if (r < 0) + log_warning_errno(r, "Failed to set file attributes on %s: %m", tp); + + r = copy_bytes(i->raw_job->disk_fd, dfd, (uint64_t) -1, COPY_REFLINK); + if (r < 0) { + (void) unlink(tp); + return log_error_errno(r, "Failed to make writable copy of image: %m"); + } + + (void) copy_times(i->raw_job->disk_fd, dfd, COPY_CRTIME); + (void) copy_xattr(i->raw_job->disk_fd, dfd); + + dfd = safe_close(dfd); + + r = rename(tp, p); + if (r < 0) { + r = log_error_errno(errno, "Failed to move writable image into place: %m"); + (void) unlink(tp); + return r; + } + + log_info("Created new local image '%s'.", i->local); + + if (i->roothash) { + r = raw_pull_copy_auxiliary_file(i, ".roothash", &i->roothash_path); + if (r < 0) + return r; + } + + if (i->settings) { + r = raw_pull_copy_auxiliary_file(i, ".nspawn", &i->settings_path); + if (r < 0) + return r; + } + + return 0; +} + +static bool raw_pull_is_done(RawPull *i) { + assert(i); + assert(i->raw_job); + + if (!PULL_JOB_IS_COMPLETE(i->raw_job)) + return false; + if (i->roothash_job && !PULL_JOB_IS_COMPLETE(i->roothash_job)) + return false; + if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job)) + return false; + if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job)) + return false; + if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job)) + return false; + + return true; +} + +static int raw_pull_rename_auxiliary_file( + RawPull *i, + const char *suffix, + char **temp_path, + char **path) { + + int r; + + assert(i); + assert(temp_path); + assert(suffix); + assert(path); + + /* Regenerate final name for this auxiliary file, we might know the etag of the file now, and we should + * incorporate it in the file name if we can */ + *path = mfree(*path); + r = raw_pull_determine_path(i, suffix, path); + if (r < 0) + return r; + + r = import_make_read_only(*temp_path); + if (r < 0) + return r; + + r = rename_noreplace(AT_FDCWD, *temp_path, AT_FDCWD, *path); + if (r < 0) + return log_error_errno(r, "Failed to rename file %s to %s: %m", *temp_path, *path); + + *temp_path = mfree(*temp_path); + + return 1; +} + +static void raw_pull_job_on_finished(PullJob *j) { + RawPull *i; + int r; + + assert(j); + assert(j->userdata); + + i = j->userdata; + if (j == i->roothash_job) { + if (j->error != 0) + log_info_errno(j->error, "Root hash file could not be retrieved, proceeding without."); + } else if (j == i->settings_job) { + if (j->error != 0) + log_info_errno(j->error, "Settings file could not be retrieved, proceeding without."); + } else if (j->error != 0 && j != i->signature_job) { + if (j == i->checksum_job) + log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)"); + else + log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)"); + + r = j->error; + goto finish; + } + + /* This is invoked if either the download completed + * successfully, or the download was skipped because we + * already have the etag. In this case ->etag_exists is + * true. + * + * We only do something when we got all three files */ + + if (!raw_pull_is_done(i)) + return; + + if (i->signature_job && i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) { + log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)"); + + r = i->signature_job->error; + goto finish; + } + + if (i->roothash_job) + i->roothash_job->disk_fd = safe_close(i->roothash_job->disk_fd); + if (i->settings_job) + i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd); + + r = raw_pull_determine_path(i, ".raw", &i->final_path); + if (r < 0) + goto finish; + + if (!i->raw_job->etag_exists) { + /* This is a new download, verify it, and move it into place */ + assert(i->raw_job->disk_fd >= 0); + + raw_pull_report_progress(i, RAW_VERIFYING); + + r = pull_verify(i->raw_job, i->roothash_job, i->settings_job, i->checksum_job, i->signature_job); + if (r < 0) + goto finish; + + raw_pull_report_progress(i, RAW_UNPACKING); + + r = raw_pull_maybe_convert_qcow2(i); + if (r < 0) + goto finish; + + raw_pull_report_progress(i, RAW_FINALIZING); + + r = import_make_read_only_fd(i->raw_job->disk_fd); + if (r < 0) + goto finish; + + r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); + if (r < 0) { + log_error_errno(r, "Failed to rename raw file to %s: %m", i->final_path); + goto finish; + } + + i->temp_path = mfree(i->temp_path); + + if (i->roothash_job && + i->roothash_job->error == 0) { + r = raw_pull_rename_auxiliary_file(i, ".roothash", &i->roothash_temp_path, &i->roothash_path); + if (r < 0) + goto finish; + } + + if (i->settings_job && + i->settings_job->error == 0) { + r = raw_pull_rename_auxiliary_file(i, ".nspawn", &i->settings_temp_path, &i->settings_path); + if (r < 0) + goto finish; + } + } + + raw_pull_report_progress(i, RAW_COPYING); + + r = raw_pull_make_local_copy(i); + if (r < 0) + goto finish; + + r = 0; + +finish: + if (i->on_finished) + i->on_finished(i, r, i->userdata); + else + sd_event_exit(i->event, r); +} + +static int raw_pull_job_on_open_disk_generic( + RawPull *i, + PullJob *j, + const char *extra, + char **temp_path) { + + int r; + + assert(i); + assert(j); + assert(extra); + assert(temp_path); + + if (!*temp_path) { + r = tempfn_random_child(i->image_root, extra, temp_path); + if (r < 0) + return log_oom(); + } + + (void) mkdir_parents_label(*temp_path, 0700); + + j->disk_fd = open(*temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); + if (j->disk_fd < 0) + return log_error_errno(errno, "Failed to create %s: %m", *temp_path); + + return 0; +} + +static int raw_pull_job_on_open_disk_raw(PullJob *j) { + RawPull *i; + int r; + + assert(j); + assert(j->userdata); + + i = j->userdata; + assert(i->raw_job == j); + + r = raw_pull_job_on_open_disk_generic(i, j, "raw", &i->temp_path); + if (r < 0) + return r; + + r = chattr_fd(j->disk_fd, FS_NOCOW_FL, FS_NOCOW_FL, NULL); + if (r < 0) + log_warning_errno(r, "Failed to set file attributes on %s, ignoring: %m", i->temp_path); + + return 0; +} + +static int raw_pull_job_on_open_disk_roothash(PullJob *j) { + RawPull *i; + + assert(j); + assert(j->userdata); + + i = j->userdata; + assert(i->roothash_job == j); + + return raw_pull_job_on_open_disk_generic(i, j, "roothash", &i->roothash_temp_path); +} + +static int raw_pull_job_on_open_disk_settings(PullJob *j) { + RawPull *i; + + assert(j); + assert(j->userdata); + + i = j->userdata; + assert(i->settings_job == j); + + return raw_pull_job_on_open_disk_generic(i, j, "settings", &i->settings_temp_path); +} + +static void raw_pull_job_on_progress(PullJob *j) { + RawPull *i; + + assert(j); + assert(j->userdata); + + i = j->userdata; + + raw_pull_report_progress(i, RAW_DOWNLOADING); +} + +int raw_pull_start( + RawPull *i, + const char *url, + const char *local, + bool force_local, + ImportVerify verify, + bool settings, + bool roothash) { + + int r; + + assert(i); + assert(verify < _IMPORT_VERIFY_MAX); + assert(verify >= 0); + + if (!http_url_is_valid(url)) + return -EINVAL; + + if (local && !machine_name_is_valid(local)) + return -EINVAL; + + if (i->raw_job) + return -EBUSY; + + r = free_and_strdup(&i->local, local); + if (r < 0) + return r; + + i->force_local = force_local; + i->verify = verify; + i->settings = settings; + i->roothash = roothash; + + /* Queue job for the image itself */ + r = pull_job_new(&i->raw_job, url, i->glue, i); + if (r < 0) + return r; + + i->raw_job->on_finished = raw_pull_job_on_finished; + i->raw_job->on_open_disk = raw_pull_job_on_open_disk_raw; + i->raw_job->on_progress = raw_pull_job_on_progress; + i->raw_job->calc_checksum = verify != IMPORT_VERIFY_NO; + + r = pull_find_old_etags(url, i->image_root, DT_REG, ".raw-", ".raw", &i->raw_job->old_etags); + if (r < 0) + return r; + + if (roothash) { + r = pull_make_auxiliary_job(&i->roothash_job, url, raw_strip_suffixes, ".roothash", i->glue, raw_pull_job_on_finished, i); + if (r < 0) + return r; + + i->roothash_job->on_open_disk = raw_pull_job_on_open_disk_roothash; + i->roothash_job->on_progress = raw_pull_job_on_progress; + i->roothash_job->calc_checksum = verify != IMPORT_VERIFY_NO; + } + + if (settings) { + r = pull_make_auxiliary_job(&i->settings_job, url, raw_strip_suffixes, ".nspawn", i->glue, raw_pull_job_on_finished, i); + if (r < 0) + return r; + + i->settings_job->on_open_disk = raw_pull_job_on_open_disk_settings; + i->settings_job->on_progress = raw_pull_job_on_progress; + i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO; + } + + r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, raw_pull_job_on_finished, i); + if (r < 0) + return r; + + r = pull_job_begin(i->raw_job); + if (r < 0) + return r; + + if (i->roothash_job) { + r = pull_job_begin(i->roothash_job); + if (r < 0) + return r; + } + + if (i->settings_job) { + r = pull_job_begin(i->settings_job); + if (r < 0) + return r; + } + + if (i->checksum_job) { + i->checksum_job->on_progress = raw_pull_job_on_progress; + i->checksum_job->style = VERIFICATION_PER_FILE; + + r = pull_job_begin(i->checksum_job); + if (r < 0) + return r; + } + + if (i->signature_job) { + i->signature_job->on_progress = raw_pull_job_on_progress; + + r = pull_job_begin(i->signature_job); + if (r < 0) + return r; + } + + return 0; +} diff --git a/src/import/pull-raw.h b/src/import/pull-raw.h new file mode 100644 index 00000000..4ccd65b7 --- /dev/null +++ b/src/import/pull-raw.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" + +#include "import-util.h" +#include "macro.h" + +typedef struct RawPull RawPull; + +typedef void (*RawPullFinished)(RawPull *pull, int error, void *userdata); + +int raw_pull_new(RawPull **pull, sd_event *event, const char *image_root, RawPullFinished on_finished, void *userdata); +RawPull* raw_pull_unref(RawPull *pull); + +DEFINE_TRIVIAL_CLEANUP_FUNC(RawPull*, raw_pull_unref); + +int raw_pull_start(RawPull *pull, const char *url, const char *local, bool force_local, ImportVerify verify, bool settings, bool roothash); diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c new file mode 100644 index 00000000..3930578a --- /dev/null +++ b/src/import/pull-tar.c @@ -0,0 +1,559 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "copy.h" +#include "curl-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "import-common.h" +#include "import-util.h" +#include "macro.h" +#include "mkdir.h" +#include "path-util.h" +#include "process-util.h" +#include "pull-common.h" +#include "pull-job.h" +#include "pull-tar.h" +#include "rm-rf.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "utf8.h" +#include "util.h" +#include "web-util.h" + +typedef enum TarProgress { + TAR_DOWNLOADING, + TAR_VERIFYING, + TAR_FINALIZING, + TAR_COPYING, +} TarProgress; + +struct TarPull { + sd_event *event; + CurlGlue *glue; + + char *image_root; + + PullJob *tar_job; + PullJob *settings_job; + PullJob *checksum_job; + PullJob *signature_job; + + TarPullFinished on_finished; + void *userdata; + + char *local; + bool force_local; + bool settings; + + pid_t tar_pid; + + char *final_path; + char *temp_path; + + char *settings_path; + char *settings_temp_path; + + ImportVerify verify; +}; + +TarPull* tar_pull_unref(TarPull *i) { + if (!i) + return NULL; + + if (i->tar_pid > 1) { + (void) kill_and_sigcont(i->tar_pid, SIGKILL); + (void) wait_for_terminate(i->tar_pid, NULL); + } + + pull_job_unref(i->tar_job); + pull_job_unref(i->settings_job); + pull_job_unref(i->checksum_job); + pull_job_unref(i->signature_job); + + curl_glue_unref(i->glue); + sd_event_unref(i->event); + + if (i->temp_path) { + (void) rm_rf(i->temp_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + free(i->temp_path); + } + + if (i->settings_temp_path) { + (void) unlink(i->settings_temp_path); + free(i->settings_temp_path); + } + + free(i->final_path); + free(i->settings_path); + free(i->image_root); + free(i->local); + + return mfree(i); +} + +int tar_pull_new( + TarPull **ret, + sd_event *event, + const char *image_root, + TarPullFinished on_finished, + void *userdata) { + + _cleanup_(curl_glue_unrefp) CurlGlue *g = NULL; + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_(tar_pull_unrefp) TarPull *i = NULL; + _cleanup_free_ char *root = NULL; + int r; + + assert(ret); + + root = strdup(image_root ?: "/var/lib/machines"); + if (!root) + return -ENOMEM; + + if (event) + e = sd_event_ref(event); + else { + r = sd_event_default(&e); + if (r < 0) + return r; + } + + r = curl_glue_new(&g, e); + if (r < 0) + return r; + + i = new(TarPull, 1); + if (!i) + return -ENOMEM; + + *i = (TarPull) { + .on_finished = on_finished, + .userdata = userdata, + .image_root = TAKE_PTR(root), + .event = TAKE_PTR(e), + .glue = TAKE_PTR(g), + }; + + i->glue->on_finished = pull_job_curl_on_finished; + i->glue->userdata = i; + + *ret = TAKE_PTR(i); + + return 0; +} + +static void tar_pull_report_progress(TarPull *i, TarProgress p) { + unsigned percent; + + assert(i); + + switch (p) { + + case TAR_DOWNLOADING: { + unsigned remain = 85; + + percent = 0; + + if (i->settings_job) { + percent += i->settings_job->progress_percent * 5 / 100; + remain -= 5; + } + + if (i->checksum_job) { + percent += i->checksum_job->progress_percent * 5 / 100; + remain -= 5; + } + + if (i->signature_job) { + percent += i->signature_job->progress_percent * 5 / 100; + remain -= 5; + } + + if (i->tar_job) + percent += i->tar_job->progress_percent * remain / 100; + break; + } + + case TAR_VERIFYING: + percent = 85; + break; + + case TAR_FINALIZING: + percent = 90; + break; + + case TAR_COPYING: + percent = 95; + break; + + default: + assert_not_reached("Unknown progress state"); + } + + sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent); + log_debug("Combined progress %u%%", percent); +} + +static int tar_pull_determine_path(TarPull *i, const char *suffix, char **field) { + int r; + + assert(i); + assert(field); + + if (*field) + return 0; + + assert(i->tar_job); + + r = pull_make_path(i->tar_job->url, i->tar_job->etag, i->image_root, ".tar-", suffix, field); + if (r < 0) + return log_oom(); + + return 1; +} + +static int tar_pull_make_local_copy(TarPull *i) { + int r; + + assert(i); + assert(i->tar_job); + + if (!i->local) + return 0; + + r = pull_make_local_copy(i->final_path, i->image_root, i->local, i->force_local); + if (r < 0) + return r; + + if (i->settings) { + const char *local_settings; + assert(i->settings_job); + + r = tar_pull_determine_path(i, ".nspawn", &i->settings_path); + if (r < 0) + return r; + + local_settings = strjoina(i->image_root, "/", i->local, ".nspawn"); + + r = copy_file_atomic(i->settings_path, local_settings, 0664, 0, 0, COPY_REFLINK | (i->force_local ? COPY_REPLACE : 0)); + if (r == -EEXIST) + log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings); + else if (r == -ENOENT) + log_debug_errno(r, "Skipping creation of settings file, since none was found."); + else if (r < 0) + log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings); + else + log_info("Created new settings file %s.", local_settings); + } + + return 0; +} + +static bool tar_pull_is_done(TarPull *i) { + assert(i); + assert(i->tar_job); + + if (!PULL_JOB_IS_COMPLETE(i->tar_job)) + return false; + if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job)) + return false; + if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job)) + return false; + if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job)) + return false; + + return true; +} + +static void tar_pull_job_on_finished(PullJob *j) { + TarPull *i; + int r; + + assert(j); + assert(j->userdata); + + i = j->userdata; + + if (j == i->settings_job) { + if (j->error != 0) + log_info_errno(j->error, "Settings file could not be retrieved, proceeding without."); + } else if (j->error != 0 && j != i->signature_job) { + if (j == i->checksum_job) + log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)"); + else + log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)"); + + r = j->error; + goto finish; + } + + /* This is invoked if either the download completed + * successfully, or the download was skipped because we + * already have the etag. */ + + if (!tar_pull_is_done(i)) + return; + + if (i->signature_job && i->checksum_job->style == VERIFICATION_PER_DIRECTORY && i->signature_job->error != 0) { + log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)"); + + r = i->signature_job->error; + goto finish; + } + + i->tar_job->disk_fd = safe_close(i->tar_job->disk_fd); + if (i->settings_job) + i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd); + + r = tar_pull_determine_path(i, NULL, &i->final_path); + if (r < 0) + goto finish; + + if (i->tar_pid > 0) { + r = wait_for_terminate_and_check("tar", i->tar_pid, WAIT_LOG); + i->tar_pid = 0; + if (r < 0) + goto finish; + if (r != EXIT_SUCCESS) { + r = -EIO; + goto finish; + } + } + + if (!i->tar_job->etag_exists) { + /* This is a new download, verify it, and move it into place */ + + tar_pull_report_progress(i, TAR_VERIFYING); + + r = pull_verify(i->tar_job, NULL, i->settings_job, i->checksum_job, i->signature_job); + if (r < 0) + goto finish; + + tar_pull_report_progress(i, TAR_FINALIZING); + + r = import_make_read_only(i->temp_path); + if (r < 0) + goto finish; + + r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); + if (r < 0) { + log_error_errno(r, "Failed to rename to final image name to %s: %m", i->final_path); + goto finish; + } + + i->temp_path = mfree(i->temp_path); + + if (i->settings_job && + i->settings_job->error == 0) { + + /* Also move the settings file into place, if it exists. Note that we do so only if we also + * moved the tar file in place, to keep things strictly in sync. */ + assert(i->settings_temp_path); + + /* Regenerate final name for this auxiliary file, we might know the etag of the file now, and + * we should incorporate it in the file name if we can */ + i->settings_path = mfree(i->settings_path); + + r = tar_pull_determine_path(i, ".nspawn", &i->settings_path); + if (r < 0) + goto finish; + + r = import_make_read_only(i->settings_temp_path); + if (r < 0) + goto finish; + + r = rename_noreplace(AT_FDCWD, i->settings_temp_path, AT_FDCWD, i->settings_path); + if (r < 0) { + log_error_errno(r, "Failed to rename settings file to %s: %m", i->settings_path); + goto finish; + } + + i->settings_temp_path = mfree(i->settings_temp_path); + } + } + + tar_pull_report_progress(i, TAR_COPYING); + + r = tar_pull_make_local_copy(i); + if (r < 0) + goto finish; + + r = 0; + +finish: + if (i->on_finished) + i->on_finished(i, r, i->userdata); + else + sd_event_exit(i->event, r); +} + +static int tar_pull_job_on_open_disk_tar(PullJob *j) { + TarPull *i; + int r; + + assert(j); + assert(j->userdata); + + i = j->userdata; + assert(i->tar_job == j); + assert(i->tar_pid <= 0); + + if (!i->temp_path) { + r = tempfn_random_child(i->image_root, "tar", &i->temp_path); + if (r < 0) + return log_oom(); + } + + mkdir_parents_label(i->temp_path, 0700); + + r = btrfs_subvol_make(i->temp_path); + if (r == -ENOTTY) { + if (mkdir(i->temp_path, 0755) < 0) + return log_error_errno(errno, "Failed to create directory %s: %m", i->temp_path); + } else if (r < 0) + return log_error_errno(r, "Failed to create subvolume %s: %m", i->temp_path); + else + (void) import_assign_pool_quota_and_warn(i->temp_path); + + j->disk_fd = import_fork_tar_x(i->temp_path, &i->tar_pid); + if (j->disk_fd < 0) + return j->disk_fd; + + return 0; +} + +static int tar_pull_job_on_open_disk_settings(PullJob *j) { + TarPull *i; + int r; + + assert(j); + assert(j->userdata); + + i = j->userdata; + assert(i->settings_job == j); + + if (!i->settings_temp_path) { + r = tempfn_random_child(i->image_root, "settings", &i->settings_temp_path); + if (r < 0) + return log_oom(); + } + + mkdir_parents_label(i->settings_temp_path, 0700); + + j->disk_fd = open(i->settings_temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); + if (j->disk_fd < 0) + return log_error_errno(errno, "Failed to create %s: %m", i->settings_temp_path); + + return 0; +} + +static void tar_pull_job_on_progress(PullJob *j) { + TarPull *i; + + assert(j); + assert(j->userdata); + + i = j->userdata; + + tar_pull_report_progress(i, TAR_DOWNLOADING); +} + +int tar_pull_start( + TarPull *i, + const char *url, + const char *local, + bool force_local, + ImportVerify verify, + bool settings) { + + int r; + + assert(i); + assert(verify < _IMPORT_VERIFY_MAX); + assert(verify >= 0); + + if (!http_url_is_valid(url)) + return -EINVAL; + + if (local && !machine_name_is_valid(local)) + return -EINVAL; + + if (i->tar_job) + return -EBUSY; + + r = free_and_strdup(&i->local, local); + if (r < 0) + return r; + + i->force_local = force_local; + i->verify = verify; + i->settings = settings; + + /* Set up download job for TAR file */ + r = pull_job_new(&i->tar_job, url, i->glue, i); + if (r < 0) + return r; + + i->tar_job->on_finished = tar_pull_job_on_finished; + i->tar_job->on_open_disk = tar_pull_job_on_open_disk_tar; + i->tar_job->on_progress = tar_pull_job_on_progress; + i->tar_job->calc_checksum = verify != IMPORT_VERIFY_NO; + + r = pull_find_old_etags(url, i->image_root, DT_DIR, ".tar-", NULL, &i->tar_job->old_etags); + if (r < 0) + return r; + + /* Set up download job for the settings file (.nspawn) */ + if (settings) { + r = pull_make_auxiliary_job(&i->settings_job, url, tar_strip_suffixes, ".nspawn", i->glue, tar_pull_job_on_finished, i); + if (r < 0) + return r; + + i->settings_job->on_open_disk = tar_pull_job_on_open_disk_settings; + i->settings_job->on_progress = tar_pull_job_on_progress; + i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO; + } + + /* Set up download of checksum/signature files */ + r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, tar_pull_job_on_finished, i); + if (r < 0) + return r; + + r = pull_job_begin(i->tar_job); + if (r < 0) + return r; + + if (i->settings_job) { + r = pull_job_begin(i->settings_job); + if (r < 0) + return r; + } + + if (i->checksum_job) { + i->checksum_job->on_progress = tar_pull_job_on_progress; + i->checksum_job->style = VERIFICATION_PER_FILE; + + r = pull_job_begin(i->checksum_job); + if (r < 0) + return r; + } + + if (i->signature_job) { + i->signature_job->on_progress = tar_pull_job_on_progress; + + r = pull_job_begin(i->signature_job); + if (r < 0) + return r; + } + + return 0; +} diff --git a/src/import/pull-tar.h b/src/import/pull-tar.h new file mode 100644 index 00000000..76f920ee --- /dev/null +++ b/src/import/pull-tar.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" + +#include "import-util.h" +#include "macro.h" + +typedef struct TarPull TarPull; + +typedef void (*TarPullFinished)(TarPull *pull, int error, void *userdata); + +int tar_pull_new(TarPull **pull, sd_event *event, const char *image_root, TarPullFinished on_finished, void *userdata); +TarPull* tar_pull_unref(TarPull *pull); + +DEFINE_TRIVIAL_CLEANUP_FUNC(TarPull*, tar_pull_unref); + +int tar_pull_start(TarPull *pull, const char *url, const char *local, bool force_local, ImportVerify verify, bool settings); diff --git a/src/import/pull.c b/src/import/pull.c new file mode 100644 index 00000000..7e871249 --- /dev/null +++ b/src/import/pull.c @@ -0,0 +1,332 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-event.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "hostname-util.h" +#include "import-util.h" +#include "machine-image.h" +#include "main-func.h" +#include "parse-util.h" +#include "pull-raw.h" +#include "pull-tar.h" +#include "signal-util.h" +#include "string-util.h" +#include "verbs.h" +#include "web-util.h" + +static bool arg_force = false; +static const char *arg_image_root = "/var/lib/machines"; +static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE; +static bool arg_settings = true; +static bool arg_roothash = true; + +static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + log_notice("Transfer aborted."); + sd_event_exit(sd_event_source_get_event(s), EINTR); + return 0; +} + +static void on_tar_finished(TarPull *pull, int error, void *userdata) { + sd_event *event = userdata; + assert(pull); + + if (error == 0) + log_info("Operation completed successfully."); + + sd_event_exit(event, abs(error)); +} + +static int pull_tar(int argc, char *argv[], void *userdata) { + _cleanup_(tar_pull_unrefp) TarPull *pull = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + const char *url, *local; + _cleanup_free_ char *l = NULL, *ll = NULL; + int r; + + url = argv[1]; + if (!http_url_is_valid(url)) { + log_error("URL '%s' is not valid.", url); + return -EINVAL; + } + + if (argc >= 3) + local = argv[2]; + else { + r = import_url_last_component(url, &l); + if (r < 0) + return log_error_errno(r, "Failed get final component of URL: %m"); + + local = l; + } + + local = empty_or_dash_to_null(local); + + if (local) { + r = tar_strip_suffixes(local, &ll); + if (r < 0) + return log_oom(); + + local = ll; + + if (!machine_name_is_valid(local)) { + log_error("Local image name '%s' is not valid.", local); + return -EINVAL; + } + + if (!arg_force) { + r = image_find(IMAGE_MACHINE, local, NULL); + if (r < 0) { + if (r != -ENOENT) + return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); + } else { + log_error("Image '%s' already exists.", local); + return -EEXIST; + } + } + + log_info("Pulling '%s', saving as '%s'.", url, local); + } else + log_info("Pulling '%s'.", url); + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); + (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); + + r = tar_pull_new(&pull, event, arg_image_root, on_tar_finished, event); + if (r < 0) + return log_error_errno(r, "Failed to allocate puller: %m"); + + r = tar_pull_start(pull, url, local, arg_force, arg_verify, arg_settings); + if (r < 0) + return log_error_errno(r, "Failed to pull image: %m"); + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + log_info("Exiting."); + return -r; +} + +static void on_raw_finished(RawPull *pull, int error, void *userdata) { + sd_event *event = userdata; + assert(pull); + + if (error == 0) + log_info("Operation completed successfully."); + + sd_event_exit(event, abs(error)); +} + +static int pull_raw(int argc, char *argv[], void *userdata) { + _cleanup_(raw_pull_unrefp) RawPull *pull = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + const char *url, *local; + _cleanup_free_ char *l = NULL, *ll = NULL; + int r; + + url = argv[1]; + if (!http_url_is_valid(url)) { + log_error("URL '%s' is not valid.", url); + return -EINVAL; + } + + if (argc >= 3) + local = argv[2]; + else { + r = import_url_last_component(url, &l); + if (r < 0) + return log_error_errno(r, "Failed get final component of URL: %m"); + + local = l; + } + + local = empty_or_dash_to_null(local); + + if (local) { + r = raw_strip_suffixes(local, &ll); + if (r < 0) + return log_oom(); + + local = ll; + + if (!machine_name_is_valid(local)) { + log_error("Local image name '%s' is not valid.", local); + return -EINVAL; + } + + if (!arg_force) { + r = image_find(IMAGE_MACHINE, local, NULL); + if (r < 0) { + if (r != -ENOENT) + return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local); + } else { + log_error("Image '%s' already exists.", local); + return -EEXIST; + } + } + + log_info("Pulling '%s', saving as '%s'.", url, local); + } else + log_info("Pulling '%s'.", url); + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL); + (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL); + + r = raw_pull_new(&pull, event, arg_image_root, on_raw_finished, event); + if (r < 0) + return log_error_errno(r, "Failed to allocate puller: %m"); + + r = raw_pull_start(pull, url, local, arg_force, arg_verify, arg_settings, arg_roothash); + if (r < 0) + return log_error_errno(r, "Failed to pull image: %m"); + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + log_info("Exiting."); + return -r; +} + +static int help(int argc, char *argv[], void *userdata) { + + printf("%s [OPTIONS...] {COMMAND} ...\n\n" + "Download container or virtual machine images.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --force Force creation of image\n" + " --verify=MODE Verify downloaded image, one of: 'no',\n" + " 'checksum', 'signature'\n" + " --settings=BOOL Download settings file with image\n" + " --roothash=BOOL Download root hash file with image\n" + " --image-root=PATH Image root directory\n\n" + "Commands:\n" + " tar URL [NAME] Download a TAR image\n" + " raw URL [NAME] Download a RAW image\n", + program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_FORCE, + ARG_IMAGE_ROOT, + ARG_VERIFY, + ARG_SETTINGS, + ARG_ROOTHASH, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "force", no_argument, NULL, ARG_FORCE }, + { "image-root", required_argument, NULL, ARG_IMAGE_ROOT }, + { "verify", required_argument, NULL, ARG_VERIFY }, + { "settings", required_argument, NULL, ARG_SETTINGS }, + { "roothash", required_argument, NULL, ARG_ROOTHASH }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(0, NULL, NULL); + + case ARG_VERSION: + return version(); + + case ARG_FORCE: + arg_force = true; + break; + + case ARG_IMAGE_ROOT: + arg_image_root = optarg; + break; + + case ARG_VERIFY: + arg_verify = import_verify_from_string(optarg); + if (arg_verify < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid verification setting '%s'", optarg); + + break; + + case ARG_SETTINGS: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --settings= parameter '%s': %m", optarg); + + arg_settings = r; + break; + + case ARG_ROOTHASH: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --roothash= parameter '%s': %m", optarg); + + arg_roothash = r; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int pull_main(int argc, char *argv[]) { + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "tar", 2, 3, 0, pull_tar }, + { "raw", 2, 3, 0, pull_raw }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static int run(int argc, char *argv[]) { + int r; + + setlocale(LC_ALL, ""); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + (void) ignore_signals(SIGPIPE, -1); + + return pull_main(argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/import/qcow2-util.c b/src/import/qcow2-util.c new file mode 100644 index 00000000..e927b60f --- /dev/null +++ b/src/import/qcow2-util.c @@ -0,0 +1,334 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "qcow2-util.h" +#include "sparse-endian.h" +#include "util.h" + +#define QCOW2_MAGIC 0x514649fb + +#define QCOW2_COPIED (1ULL << 63) +#define QCOW2_COMPRESSED (1ULL << 62) +#define QCOW2_ZERO (1ULL << 0) + +typedef struct _packed_ Header { + be32_t magic; + be32_t version; + + be64_t backing_file_offset; + be32_t backing_file_size; + + be32_t cluster_bits; + be64_t size; + be32_t crypt_method; + + be32_t l1_size; + be64_t l1_table_offset; + + be64_t refcount_table_offset; + be32_t refcount_table_clusters; + + be32_t nb_snapshots; + be64_t snapshots_offset; + + /* The remainder is only present on QCOW3 */ + be64_t incompatible_features; + be64_t compatible_features; + be64_t autoclear_features; + + be32_t refcount_order; + be32_t header_length; +} Header; + +#define HEADER_MAGIC(header) be32toh((header)->magic) +#define HEADER_VERSION(header) be32toh((header)->version) +#define HEADER_CLUSTER_BITS(header) be32toh((header)->cluster_bits) +#define HEADER_CLUSTER_SIZE(header) (1ULL << HEADER_CLUSTER_BITS(header)) +#define HEADER_L2_BITS(header) (HEADER_CLUSTER_BITS(header) - 3) +#define HEADER_SIZE(header) be64toh((header)->size) +#define HEADER_CRYPT_METHOD(header) be32toh((header)->crypt_method) +#define HEADER_L1_SIZE(header) be32toh((header)->l1_size) +#define HEADER_L2_SIZE(header) (HEADER_CLUSTER_SIZE(header)/sizeof(uint64_t)) +#define HEADER_L1_TABLE_OFFSET(header) be64toh((header)->l1_table_offset) + +static uint32_t HEADER_HEADER_LENGTH(const Header *h) { + if (HEADER_VERSION(h) < 3) + return offsetof(Header, incompatible_features); + + return be32toh(h->header_length); +} + +static int copy_cluster( + int sfd, uint64_t soffset, + int dfd, uint64_t doffset, + uint64_t cluster_size, + void *buffer) { + + ssize_t l; + int r; + + r = btrfs_clone_range(sfd, soffset, dfd, doffset, cluster_size); + if (r >= 0) + return r; + + l = pread(sfd, buffer, cluster_size, soffset); + if (l < 0) + return -errno; + if ((uint64_t) l != cluster_size) + return -EIO; + + l = pwrite(dfd, buffer, cluster_size, doffset); + if (l < 0) + return -errno; + if ((uint64_t) l != cluster_size) + return -EIO; + + return 0; +} + +static int decompress_cluster( + int sfd, uint64_t soffset, + int dfd, uint64_t doffset, + uint64_t compressed_size, + uint64_t cluster_size, + void *buffer1, + void *buffer2) { + + _cleanup_free_ void *large_buffer = NULL; + z_stream s = {}; + uint64_t sz; + ssize_t l; + int r; + + if (compressed_size > cluster_size) { + /* The usual cluster buffer doesn't suffice, let's + * allocate a larger one, temporarily */ + + large_buffer = malloc(compressed_size); + if (!large_buffer) + return -ENOMEM; + + buffer1 = large_buffer; + } + + l = pread(sfd, buffer1, compressed_size, soffset); + if (l < 0) + return -errno; + if ((uint64_t) l != compressed_size) + return -EIO; + + s.next_in = buffer1; + s.avail_in = compressed_size; + s.next_out = buffer2; + s.avail_out = cluster_size; + + r = inflateInit2(&s, -12); + if (r != Z_OK) + return -EIO; + + r = inflate(&s, Z_FINISH); + sz = (uint8_t*) s.next_out - (uint8_t*) buffer2; + inflateEnd(&s); + if (r != Z_STREAM_END || sz != cluster_size) + return -EIO; + + l = pwrite(dfd, buffer2, cluster_size, doffset); + if (l < 0) + return -errno; + if ((uint64_t) l != cluster_size) + return -EIO; + + return 0; +} + +static int normalize_offset( + const Header *header, + uint64_t p, + uint64_t *ret, + bool *compressed, + uint64_t *compressed_size) { + + uint64_t q; + + q = be64toh(p); + + if (q & QCOW2_COMPRESSED) { + uint64_t sz, csize_shift, csize_mask; + + if (!compressed) + return -EOPNOTSUPP; + + csize_shift = 64 - 2 - (HEADER_CLUSTER_BITS(header) - 8); + csize_mask = (1ULL << (HEADER_CLUSTER_BITS(header) - 8)) - 1; + sz = (((q >> csize_shift) & csize_mask) + 1) * 512 - (q & 511); + q &= ((1ULL << csize_shift) - 1); + + if (compressed_size) + *compressed_size = sz; + + *compressed = true; + + } else { + if (compressed) { + *compressed = false; + *compressed_size = 0; + } + + if (q & QCOW2_ZERO) { + /* We make no distinction between zero blocks and holes */ + *ret = 0; + return 0; + } + + q &= ~QCOW2_COPIED; + } + + *ret = q; + return q > 0; /* returns positive if not a hole */ +} + +static int verify_header(const Header *header) { + assert(header); + + if (HEADER_MAGIC(header) != QCOW2_MAGIC) + return -EBADMSG; + + if (!IN_SET(HEADER_VERSION(header), 2, 3)) + return -EOPNOTSUPP; + + if (HEADER_CRYPT_METHOD(header) != 0) + return -EOPNOTSUPP; + + if (HEADER_CLUSTER_BITS(header) < 9) /* 512K */ + return -EBADMSG; + + if (HEADER_CLUSTER_BITS(header) > 21) /* 2MB */ + return -EBADMSG; + + if (HEADER_SIZE(header) % HEADER_CLUSTER_SIZE(header) != 0) + return -EBADMSG; + + if (HEADER_L1_SIZE(header) > 32*1024*1024) /* 32MB */ + return -EBADMSG; + + if (HEADER_VERSION(header) == 3) { + + if (header->incompatible_features != 0) + return -EOPNOTSUPP; + + if (HEADER_HEADER_LENGTH(header) < sizeof(Header)) + return -EBADMSG; + } + + return 0; +} + +int qcow2_convert(int qcow2_fd, int raw_fd) { + _cleanup_free_ void *buffer1 = NULL, *buffer2 = NULL; + _cleanup_free_ be64_t *l1_table = NULL, *l2_table = NULL; + uint64_t sz, i; + Header header; + ssize_t l; + int r; + + l = pread(qcow2_fd, &header, sizeof(header), 0); + if (l < 0) + return -errno; + if (l != sizeof(header)) + return -EIO; + + r = verify_header(&header); + if (r < 0) + return r; + + l1_table = new(be64_t, HEADER_L1_SIZE(&header)); + if (!l1_table) + return -ENOMEM; + + l2_table = malloc(HEADER_CLUSTER_SIZE(&header)); + if (!l2_table) + return -ENOMEM; + + buffer1 = malloc(HEADER_CLUSTER_SIZE(&header)); + if (!buffer1) + return -ENOMEM; + + buffer2 = malloc(HEADER_CLUSTER_SIZE(&header)); + if (!buffer2) + return -ENOMEM; + + /* Empty the file if it exists, we rely on zero bits */ + if (ftruncate(raw_fd, 0) < 0) + return -errno; + + if (ftruncate(raw_fd, HEADER_SIZE(&header)) < 0) + return -errno; + + sz = sizeof(uint64_t) * HEADER_L1_SIZE(&header); + l = pread(qcow2_fd, l1_table, sz, HEADER_L1_TABLE_OFFSET(&header)); + if (l < 0) + return -errno; + if ((uint64_t) l != sz) + return -EIO; + + for (i = 0; i < HEADER_L1_SIZE(&header); i ++) { + uint64_t l2_begin, j; + + r = normalize_offset(&header, l1_table[i], &l2_begin, NULL, NULL); + if (r < 0) + return r; + if (r == 0) + continue; + + l = pread(qcow2_fd, l2_table, HEADER_CLUSTER_SIZE(&header), l2_begin); + if (l < 0) + return -errno; + if ((uint64_t) l != HEADER_CLUSTER_SIZE(&header)) + return -EIO; + + for (j = 0; j < HEADER_L2_SIZE(&header); j++) { + uint64_t data_begin, p, compressed_size; + bool compressed; + + p = ((i << HEADER_L2_BITS(&header)) + j) << HEADER_CLUSTER_BITS(&header); + + r = normalize_offset(&header, l2_table[j], &data_begin, &compressed, &compressed_size); + if (r < 0) + return r; + if (r == 0) + continue; + + if (compressed) + r = decompress_cluster( + qcow2_fd, data_begin, + raw_fd, p, + compressed_size, HEADER_CLUSTER_SIZE(&header), + buffer1, buffer2); + else + r = copy_cluster( + qcow2_fd, data_begin, + raw_fd, p, + HEADER_CLUSTER_SIZE(&header), buffer1); + if (r < 0) + return r; + } + } + + return 0; +} + +int qcow2_detect(int fd) { + be32_t id; + ssize_t l; + + l = pread(fd, &id, sizeof(id), 0); + if (l < 0) + return -errno; + if (l != sizeof(id)) + return -EIO; + + return htobe32(QCOW2_MAGIC) == id; +} diff --git a/src/import/qcow2-util.h b/src/import/qcow2-util.h new file mode 100644 index 00000000..7393d983 --- /dev/null +++ b/src/import/qcow2-util.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int qcow2_detect(int fd); +int qcow2_convert(int qcow2_fd, int raw_fd); diff --git a/src/import/test-qcow2.c b/src/import/test-qcow2.c new file mode 100644 index 00000000..1703cfd1 --- /dev/null +++ b/src/import/test-qcow2.c @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "fd-util.h" +#include "log.h" +#include "qcow2-util.h" + +int main(int argc, char *argv[]) { + _cleanup_close_ int sfd = -1, dfd = -1; + int r; + + if (argc != 3) { + log_error("Needs two arguments."); + return EXIT_FAILURE; + } + + sfd = open(argv[1], O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (sfd < 0) { + log_error_errno(errno, "Can't open source file: %m"); + return EXIT_FAILURE; + } + + dfd = open(argv[2], O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0666); + if (dfd < 0) { + log_error_errno(errno, "Can't open destination file: %m"); + return EXIT_FAILURE; + } + + r = qcow2_convert(sfd, dfd); + if (r < 0) { + log_error_errno(r, "Failed to unpack: %m"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c new file mode 100644 index 00000000..96ea942b --- /dev/null +++ b/src/initctl/initctl.c @@ -0,0 +1,407 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "def.h" +#include "fd-util.h" +#include "format-util.h" +#include "initreq.h" +#include "list.h" +#include "log.h" +#include "memory-util.h" +#include "process-util.h" +#include "special.h" + +#define SERVER_FD_MAX 16 +#define TIMEOUT_MSEC ((int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)) + +typedef struct Fifo Fifo; + +typedef struct Server { + int epoll_fd; + + LIST_HEAD(Fifo, fifos); + unsigned n_fifos; + + sd_bus *bus; + + bool quit; +} Server; + +struct Fifo { + Server *server; + + int fd; + + struct init_request buffer; + size_t bytes_read; + + LIST_FIELDS(Fifo, fifo); +}; + +static const char *translate_runlevel(int runlevel, bool *isolate) { + static const struct { + const int runlevel; + const char *special; + bool isolate; + } table[] = { + { '0', SPECIAL_POWEROFF_TARGET, false }, + { '1', SPECIAL_RESCUE_TARGET, true }, + { 's', SPECIAL_RESCUE_TARGET, true }, + { 'S', SPECIAL_RESCUE_TARGET, true }, + { '2', SPECIAL_MULTI_USER_TARGET, true }, + { '3', SPECIAL_MULTI_USER_TARGET, true }, + { '4', SPECIAL_MULTI_USER_TARGET, true }, + { '5', SPECIAL_GRAPHICAL_TARGET, true }, + { '6', SPECIAL_REBOOT_TARGET, false }, + }; + + unsigned i; + + assert(isolate); + + for (i = 0; i < ELEMENTSOF(table); i++) + if (table[i].runlevel == runlevel) { + *isolate = table[i].isolate; + if (runlevel == '6' && kexec_loaded()) + return SPECIAL_KEXEC_TARGET; + return table[i].special; + } + + return NULL; +} + +static int change_runlevel(Server *s, int runlevel) { + const char *target; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *mode; + bool isolate = false; + int r; + + assert(s); + + target = translate_runlevel(runlevel, &isolate); + if (!target) { + log_warning("Got request for unknown runlevel %c, ignoring.", runlevel); + return 0; + } + + if (isolate) + mode = "isolate"; + else + mode = "replace-irreversibly"; + + log_debug("Running request %s/start/%s", target, mode); + + r = sd_bus_call_method( + s->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + &error, + NULL, + "ss", target, mode); + if (r < 0) + return log_error_errno(r, "Failed to change runlevel: %s", bus_error_message(&error, -r)); + + return 0; +} + +static void request_process(Server *s, const struct init_request *req) { + assert(s); + assert(req); + + if (req->magic != INIT_MAGIC) { + log_error("Got initctl request with invalid magic. Ignoring."); + return; + } + + switch (req->cmd) { + + case INIT_CMD_RUNLVL: + if (!isprint(req->runlevel)) + log_error("Got invalid runlevel. Ignoring."); + else + switch (req->runlevel) { + + /* we are async anyway, so just use kill for reexec/reload */ + case 'u': + case 'U': + if (kill(1, SIGTERM) < 0) + log_error_errno(errno, "kill() failed: %m"); + + /* The bus connection will be + * terminated if PID 1 is reexecuted, + * hence let's just exit here, and + * rely on that we'll be restarted on + * the next request */ + s->quit = true; + break; + + case 'q': + case 'Q': + if (kill(1, SIGHUP) < 0) + log_error_errno(errno, "kill() failed: %m"); + break; + + default: + (void) change_runlevel(s, req->runlevel); + } + return; + + case INIT_CMD_POWERFAIL: + case INIT_CMD_POWERFAILNOW: + case INIT_CMD_POWEROK: + log_warning("Received UPS/power initctl request. This is not implemented in systemd. Upgrade your UPS daemon!"); + return; + + case INIT_CMD_CHANGECONS: + log_warning("Received console change initctl request. This is not implemented in systemd."); + return; + + case INIT_CMD_SETENV: + case INIT_CMD_UNSETENV: + log_warning("Received environment initctl request. This is not implemented in systemd."); + return; + + default: + log_warning("Received unknown initctl request. Ignoring."); + return; + } +} + +static int fifo_process(Fifo *f) { + ssize_t l; + + assert(f); + + errno = EIO; + l = read(f->fd, + ((uint8_t*) &f->buffer) + f->bytes_read, + sizeof(f->buffer) - f->bytes_read); + if (l <= 0) { + if (errno == EAGAIN) + return 0; + + return log_warning_errno(errno, "Failed to read from fifo: %m"); + } + + f->bytes_read += l; + assert(f->bytes_read <= sizeof(f->buffer)); + + if (f->bytes_read == sizeof(f->buffer)) { + request_process(f->server, &f->buffer); + f->bytes_read = 0; + } + + return 0; +} + +static void fifo_free(Fifo *f) { + assert(f); + + if (f->server) { + assert(f->server->n_fifos > 0); + f->server->n_fifos--; + LIST_REMOVE(fifo, f->server->fifos, f); + } + + if (f->fd >= 0) { + if (f->server) + epoll_ctl(f->server->epoll_fd, EPOLL_CTL_DEL, f->fd, NULL); + + safe_close(f->fd); + } + + free(f); +} + +static void server_done(Server *s) { + assert(s); + + while (s->fifos) + fifo_free(s->fifos); + + s->epoll_fd = safe_close(s->epoll_fd); + s->bus = sd_bus_flush_close_unref(s->bus); +} + +static int server_init(Server *s, unsigned n_sockets) { + int r; + unsigned i; + + assert(s); + assert(n_sockets > 0); + + zero(*s); + + s->epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (s->epoll_fd < 0) { + r = log_error_errno(errno, + "Failed to create epoll object: %m"); + goto fail; + } + + for (i = 0; i < n_sockets; i++) { + struct epoll_event ev; + Fifo *f; + int fd; + + fd = SD_LISTEN_FDS_START+i; + + r = sd_is_fifo(fd, NULL); + if (r < 0) { + log_error_errno(r, "Failed to determine file descriptor type: %m"); + goto fail; + } + + if (!r) { + log_error("Wrong file descriptor type."); + r = -EINVAL; + goto fail; + } + + f = new0(Fifo, 1); + if (!f) { + r = -ENOMEM; + log_error_errno(errno, "Failed to create fifo object: %m"); + goto fail; + } + + f->fd = -1; + + zero(ev); + ev.events = EPOLLIN; + ev.data.ptr = f; + if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { + r = -errno; + fifo_free(f); + log_error_errno(errno, "Failed to add fifo fd to epoll object: %m"); + goto fail; + } + + f->fd = fd; + LIST_PREPEND(fifo, s->fifos, f); + f->server = s; + s->n_fifos++; + } + + r = bus_connect_system_systemd(&s->bus); + if (r < 0) { + log_error_errno(r, "Failed to get D-Bus connection: %m"); + r = -EIO; + goto fail; + } + + return 0; + +fail: + server_done(s); + + return r; +} + +static int process_event(Server *s, struct epoll_event *ev) { + int r; + Fifo *f; + + assert(s); + + if (!(ev->events & EPOLLIN)) + return log_info_errno(SYNTHETIC_ERRNO(EIO), + "Got invalid event from epoll. (3)"); + + f = (Fifo*) ev->data.ptr; + r = fifo_process(f); + if (r < 0) { + log_info_errno(r, "Got error on fifo: %m"); + fifo_free(f); + return r; + } + + return 0; +} + +int main(int argc, char *argv[]) { + Server server; + int r = EXIT_FAILURE, n; + + if (getppid() != 1) { + log_error("This program should be invoked by init only."); + return EXIT_FAILURE; + } + + if (argc > 1) { + log_error("This program does not take arguments."); + return EXIT_FAILURE; + } + + log_setup_service(); + + umask(0022); + + n = sd_listen_fds(true); + if (n < 0) { + log_error_errno(r, "Failed to read listening file descriptors from environment: %m"); + return EXIT_FAILURE; + } + + if (n <= 0 || n > SERVER_FD_MAX) { + log_error("No or too many file descriptors passed."); + return EXIT_FAILURE; + } + + if (server_init(&server, (unsigned) n) < 0) + return EXIT_FAILURE; + + log_debug("systemd-initctl running as pid "PID_FMT, getpid_cached()); + + sd_notify(false, + "READY=1\n" + "STATUS=Processing requests..."); + + while (!server.quit) { + struct epoll_event event; + int k; + + k = epoll_wait(server.epoll_fd, &event, 1, TIMEOUT_MSEC); + if (k < 0) { + if (errno == EINTR) + continue; + log_error_errno(errno, "epoll_wait() failed: %m"); + goto fail; + } + + if (k <= 0) + break; + + if (process_event(&server, &event) < 0) + goto fail; + } + + r = EXIT_SUCCESS; + + log_debug("systemd-initctl stopped as pid "PID_FMT, getpid_cached()); + +fail: + sd_notify(false, + "STOPPING=1\n" + "STATUS=Shutting down..."); + + server_done(&server); + + return r; +} diff --git a/src/journal-remote/browse.html b/src/journal-remote/browse.html new file mode 100644 index 00000000..9a5ae803 --- /dev/null +++ b/src/journal-remote/browse.html @@ -0,0 +1,547 @@ + + + + Journal + + + + + + + +

+ +
+
+
+
+
+
+ +
+ +      + Only current boot +
+ +
+ +
+ +
+ + + + +      + + +
+ +
+ g: First Page      + ←, k, BACKSPACE: Previous Page      + →, j, SPACE: Next Page      + G: Last Page      + +: More entries      + -: Fewer entries +
+ + + + diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c new file mode 100644 index 00000000..459d8e86 --- /dev/null +++ b/src/journal-remote/journal-gatewayd.c @@ -0,0 +1,1048 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-daemon.h" +#include "sd-journal.h" + +#include "alloc-util.h" +#include "bus-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "hostname-util.h" +#include "log.h" +#include "logs-show.h" +#include "main-func.h" +#include "microhttpd-util.h" +#include "os-util.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "sigbus.h" +#include "tmpfile-util.h" +#include "util.h" + +#define JOURNAL_WAIT_TIMEOUT (10*USEC_PER_SEC) + +static char *arg_key_pem = NULL; +static char *arg_cert_pem = NULL; +static char *arg_trust_pem = NULL; +static const char *arg_directory = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_key_pem, freep); +STATIC_DESTRUCTOR_REGISTER(arg_cert_pem, freep); +STATIC_DESTRUCTOR_REGISTER(arg_trust_pem, freep); + +typedef struct RequestMeta { + sd_journal *journal; + + OutputMode mode; + + char *cursor; + int64_t n_skip; + uint64_t n_entries; + bool n_entries_set; + + FILE *tmp; + uint64_t delta, size; + + int argument_parse_error; + + bool follow; + bool discrete; + + uint64_t n_fields; + bool n_fields_set; +} RequestMeta; + +static const char* const mime_types[_OUTPUT_MODE_MAX] = { + [OUTPUT_SHORT] = "text/plain", + [OUTPUT_JSON] = "application/json", + [OUTPUT_JSON_SSE] = "text/event-stream", + [OUTPUT_JSON_SEQ] = "application/json-seq", + [OUTPUT_EXPORT] = "application/vnd.fdo.journal", +}; + +static RequestMeta *request_meta(void **connection_cls) { + RequestMeta *m; + + assert(connection_cls); + if (*connection_cls) + return *connection_cls; + + m = new0(RequestMeta, 1); + if (!m) + return NULL; + + *connection_cls = m; + return m; +} + +static void request_meta_free( + void *cls, + struct MHD_Connection *connection, + void **connection_cls, + enum MHD_RequestTerminationCode toe) { + + RequestMeta *m = *connection_cls; + + if (!m) + return; + + sd_journal_close(m->journal); + + safe_fclose(m->tmp); + + free(m->cursor); + free(m); +} + +static int open_journal(RequestMeta *m) { + assert(m); + + if (m->journal) + return 0; + + if (arg_directory) + return sd_journal_open_directory(&m->journal, arg_directory, 0); + else + return sd_journal_open(&m->journal, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM); +} + +static int request_meta_ensure_tmp(RequestMeta *m) { + assert(m); + + if (m->tmp) + rewind(m->tmp); + else { + int fd; + + fd = open_tmpfile_unlinkable("/tmp", O_RDWR|O_CLOEXEC); + if (fd < 0) + return fd; + + m->tmp = fdopen(fd, "w+"); + if (!m->tmp) { + safe_close(fd); + return -errno; + } + } + + return 0; +} + +static ssize_t request_reader_entries( + void *cls, + uint64_t pos, + char *buf, + size_t max) { + + RequestMeta *m = cls; + int r; + size_t n, k; + + assert(m); + assert(buf); + assert(max > 0); + assert(pos >= m->delta); + + pos -= m->delta; + + while (pos >= m->size) { + off_t sz; + + /* End of this entry, so let's serialize the next + * one */ + + if (m->n_entries_set && + m->n_entries <= 0) + return MHD_CONTENT_READER_END_OF_STREAM; + + if (m->n_skip < 0) + r = sd_journal_previous_skip(m->journal, (uint64_t) -m->n_skip + 1); + else if (m->n_skip > 0) + r = sd_journal_next_skip(m->journal, (uint64_t) m->n_skip + 1); + else + r = sd_journal_next(m->journal); + + if (r < 0) { + log_error_errno(r, "Failed to advance journal pointer: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } else if (r == 0) { + + if (m->follow) { + r = sd_journal_wait(m->journal, (uint64_t) JOURNAL_WAIT_TIMEOUT); + if (r < 0) { + log_error_errno(r, "Couldn't wait for journal event: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + if (r == SD_JOURNAL_NOP) + break; + + continue; + } + + return MHD_CONTENT_READER_END_OF_STREAM; + } + + if (m->discrete) { + assert(m->cursor); + + r = sd_journal_test_cursor(m->journal, m->cursor); + if (r < 0) { + log_error_errno(r, "Failed to test cursor: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + if (r == 0) + return MHD_CONTENT_READER_END_OF_STREAM; + } + + pos -= m->size; + m->delta += m->size; + + if (m->n_entries_set) + m->n_entries -= 1; + + m->n_skip = 0; + + r = request_meta_ensure_tmp(m); + if (r < 0) { + log_error_errno(r, "Failed to create temporary file: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + r = show_journal_entry(m->tmp, m->journal, m->mode, 0, OUTPUT_FULL_WIDTH, + NULL, NULL, NULL); + if (r < 0) { + log_error_errno(r, "Failed to serialize item: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + sz = ftello(m->tmp); + if (sz == (off_t) -1) { + log_error_errno(errno, "Failed to retrieve file position: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + m->size = (uint64_t) sz; + } + + if (m->tmp == NULL && m->follow) + return 0; + + if (fseeko(m->tmp, pos, SEEK_SET) < 0) { + log_error_errno(errno, "Failed to seek to position: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + n = m->size - pos; + if (n < 1) + return 0; + if (n > max) + n = max; + + errno = 0; + k = fread(buf, 1, n, m->tmp); + if (k != n) { + log_error("Failed to read from file: %s", errno != 0 ? strerror_safe(errno) : "Premature EOF"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + return (ssize_t) k; +} + +static int request_parse_accept( + RequestMeta *m, + struct MHD_Connection *connection) { + + const char *header; + + assert(m); + assert(connection); + + header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Accept"); + if (!header) + return 0; + + if (streq(header, mime_types[OUTPUT_JSON])) + m->mode = OUTPUT_JSON; + else if (streq(header, mime_types[OUTPUT_JSON_SSE])) + m->mode = OUTPUT_JSON_SSE; + else if (streq(header, mime_types[OUTPUT_JSON_SEQ])) + m->mode = OUTPUT_JSON_SEQ; + else if (streq(header, mime_types[OUTPUT_EXPORT])) + m->mode = OUTPUT_EXPORT; + else + m->mode = OUTPUT_SHORT; + + return 0; +} + +static int request_parse_range( + RequestMeta *m, + struct MHD_Connection *connection) { + + const char *range, *colon, *colon2; + int r; + + assert(m); + assert(connection); + + range = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Range"); + if (!range) + return 0; + + if (!startswith(range, "entries=")) + return 0; + + range += 8; + range += strspn(range, WHITESPACE); + + colon = strchr(range, ':'); + if (!colon) + m->cursor = strdup(range); + else { + const char *p; + + colon2 = strchr(colon + 1, ':'); + if (colon2) { + _cleanup_free_ char *t; + + t = strndup(colon + 1, colon2 - colon - 1); + if (!t) + return -ENOMEM; + + r = safe_atoi64(t, &m->n_skip); + if (r < 0) + return r; + } + + p = (colon2 ? colon2 : colon) + 1; + if (*p) { + r = safe_atou64(p, &m->n_entries); + if (r < 0) + return r; + + if (m->n_entries <= 0) + return -EINVAL; + + m->n_entries_set = true; + } + + m->cursor = strndup(range, colon - range); + } + + if (!m->cursor) + return -ENOMEM; + + m->cursor[strcspn(m->cursor, WHITESPACE)] = 0; + if (isempty(m->cursor)) + m->cursor = mfree(m->cursor); + + return 0; +} + +static int request_parse_arguments_iterator( + void *cls, + enum MHD_ValueKind kind, + const char *key, + const char *value) { + + RequestMeta *m = cls; + _cleanup_free_ char *p = NULL; + int r; + + assert(m); + + if (isempty(key)) { + m->argument_parse_error = -EINVAL; + return MHD_NO; + } + + if (streq(key, "follow")) { + if (isempty(value)) { + m->follow = true; + return MHD_YES; + } + + r = parse_boolean(value); + if (r < 0) { + m->argument_parse_error = r; + return MHD_NO; + } + + m->follow = r; + return MHD_YES; + } + + if (streq(key, "discrete")) { + if (isempty(value)) { + m->discrete = true; + return MHD_YES; + } + + r = parse_boolean(value); + if (r < 0) { + m->argument_parse_error = r; + return MHD_NO; + } + + m->discrete = r; + return MHD_YES; + } + + if (streq(key, "boot")) { + if (isempty(value)) + r = true; + else { + r = parse_boolean(value); + if (r < 0) { + m->argument_parse_error = r; + return MHD_NO; + } + } + + if (r) { + char match[9 + 32 + 1] = "_BOOT_ID="; + sd_id128_t bid; + + r = sd_id128_get_boot(&bid); + if (r < 0) { + log_error_errno(r, "Failed to get boot ID: %m"); + return MHD_NO; + } + + sd_id128_to_string(bid, match + 9); + r = sd_journal_add_match(m->journal, match, sizeof(match)-1); + if (r < 0) { + m->argument_parse_error = r; + return MHD_NO; + } + } + + return MHD_YES; + } + + p = strjoin(key, "=", strempty(value)); + if (!p) { + m->argument_parse_error = log_oom(); + return MHD_NO; + } + + r = sd_journal_add_match(m->journal, p, 0); + if (r < 0) { + m->argument_parse_error = r; + return MHD_NO; + } + + return MHD_YES; +} + +static int request_parse_arguments( + RequestMeta *m, + struct MHD_Connection *connection) { + + assert(m); + assert(connection); + + m->argument_parse_error = 0; + MHD_get_connection_values(connection, MHD_GET_ARGUMENT_KIND, request_parse_arguments_iterator, m); + + return m->argument_parse_error; +} + +static int request_handler_entries( + struct MHD_Connection *connection, + void *connection_cls) { + + _cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL; + RequestMeta *m = connection_cls; + int r; + + assert(connection); + assert(m); + + r = open_journal(m); + if (r < 0) + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m"); + + if (request_parse_accept(m, connection) < 0) + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header."); + + if (request_parse_range(m, connection) < 0) + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Range header."); + + if (request_parse_arguments(m, connection) < 0) + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments."); + + if (m->discrete) { + if (!m->cursor) + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification."); + + m->n_entries = 1; + m->n_entries_set = true; + } + + if (m->cursor) + r = sd_journal_seek_cursor(m->journal, m->cursor); + else if (m->n_skip >= 0) + r = sd_journal_seek_head(m->journal); + else if (m->n_skip < 0) + r = sd_journal_seek_tail(m->journal); + if (r < 0) + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal."); + + response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_entries, m, NULL); + if (!response) + return respond_oom(connection); + + MHD_add_response_header(response, "Content-Type", mime_types[m->mode]); + return MHD_queue_response(connection, MHD_HTTP_OK, response); +} + +static int output_field(FILE *f, OutputMode m, const char *d, size_t l) { + const char *eq; + size_t j; + + eq = memchr(d, '=', l); + if (!eq) + return -EINVAL; + + j = l - (eq - d + 1); + + if (m == OUTPUT_JSON) { + fprintf(f, "{ \"%.*s\" : ", (int) (eq - d), d); + json_escape(f, eq+1, j, OUTPUT_FULL_WIDTH); + fputs(" }\n", f); + } else { + fwrite(eq+1, 1, j, f); + fputc('\n', f); + } + + return 0; +} + +static ssize_t request_reader_fields( + void *cls, + uint64_t pos, + char *buf, + size_t max) { + + RequestMeta *m = cls; + int r; + size_t n, k; + + assert(m); + assert(buf); + assert(max > 0); + assert(pos >= m->delta); + + pos -= m->delta; + + while (pos >= m->size) { + off_t sz; + const void *d; + size_t l; + + /* End of this field, so let's serialize the next + * one */ + + if (m->n_fields_set && + m->n_fields <= 0) + return MHD_CONTENT_READER_END_OF_STREAM; + + r = sd_journal_enumerate_unique(m->journal, &d, &l); + if (r < 0) { + log_error_errno(r, "Failed to advance field index: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } else if (r == 0) + return MHD_CONTENT_READER_END_OF_STREAM; + + pos -= m->size; + m->delta += m->size; + + if (m->n_fields_set) + m->n_fields -= 1; + + r = request_meta_ensure_tmp(m); + if (r < 0) { + log_error_errno(r, "Failed to create temporary file: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + r = output_field(m->tmp, m->mode, d, l); + if (r < 0) { + log_error_errno(r, "Failed to serialize item: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + sz = ftello(m->tmp); + if (sz == (off_t) -1) { + log_error_errno(errno, "Failed to retrieve file position: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + m->size = (uint64_t) sz; + } + + if (fseeko(m->tmp, pos, SEEK_SET) < 0) { + log_error_errno(errno, "Failed to seek to position: %m"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + n = m->size - pos; + if (n > max) + n = max; + + errno = 0; + k = fread(buf, 1, n, m->tmp); + if (k != n) { + log_error("Failed to read from file: %s", errno != 0 ? strerror_safe(errno) : "Premature EOF"); + return MHD_CONTENT_READER_END_WITH_ERROR; + } + + return (ssize_t) k; +} + +static int request_handler_fields( + struct MHD_Connection *connection, + const char *field, + void *connection_cls) { + + _cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL; + RequestMeta *m = connection_cls; + int r; + + assert(connection); + assert(m); + + r = open_journal(m); + if (r < 0) + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m"); + + if (request_parse_accept(m, connection) < 0) + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header."); + + r = sd_journal_query_unique(m->journal, field); + if (r < 0) + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to query unique fields."); + + response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_fields, m, NULL); + if (!response) + return respond_oom(connection); + + MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]); + return MHD_queue_response(connection, MHD_HTTP_OK, response); +} + +static int request_handler_redirect( + struct MHD_Connection *connection, + const char *target) { + + char *page; + _cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL; + + assert(connection); + assert(target); + + if (asprintf(&page, "Please continue to the journal browser.", target) < 0) + return respond_oom(connection); + + response = MHD_create_response_from_buffer(strlen(page), page, MHD_RESPMEM_MUST_FREE); + if (!response) { + free(page); + return respond_oom(connection); + } + + MHD_add_response_header(response, "Content-Type", "text/html"); + MHD_add_response_header(response, "Location", target); + return MHD_queue_response(connection, MHD_HTTP_MOVED_PERMANENTLY, response); +} + +static int request_handler_file( + struct MHD_Connection *connection, + const char *path, + const char *mime_type) { + + _cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL; + _cleanup_close_ int fd = -1; + struct stat st; + + assert(connection); + assert(path); + assert(mime_type); + + fd = open(path, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return mhd_respondf(connection, errno, MHD_HTTP_NOT_FOUND, "Failed to open file %s: %m", path); + + if (fstat(fd, &st) < 0) + return mhd_respondf(connection, errno, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m"); + + response = MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0); + if (!response) + return respond_oom(connection); + TAKE_FD(fd); + + MHD_add_response_header(response, "Content-Type", mime_type); + return MHD_queue_response(connection, MHD_HTTP_OK, response); +} + +static int get_virtualization(char **v) { + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + char *b = NULL; + int r; + + r = sd_bus_default_system(&bus); + if (r < 0) + return r; + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Virtualization", + NULL, + &b); + if (r < 0) + return r; + + if (isempty(b)) { + free(b); + *v = NULL; + return 0; + } + + *v = b; + return 1; +} + +static int request_handler_machine( + struct MHD_Connection *connection, + void *connection_cls) { + + _cleanup_(MHD_destroy_responsep) struct MHD_Response *response = NULL; + RequestMeta *m = connection_cls; + int r; + _cleanup_free_ char* hostname = NULL, *os_name = NULL; + uint64_t cutoff_from = 0, cutoff_to = 0, usage = 0; + sd_id128_t mid, bid; + _cleanup_free_ char *v = NULL, *json = NULL; + + assert(connection); + assert(m); + + r = open_journal(m); + if (r < 0) + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m"); + + r = sd_id128_get_machine(&mid); + if (r < 0) + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %m"); + + r = sd_id128_get_boot(&bid); + if (r < 0) + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %m"); + + hostname = gethostname_malloc(); + if (!hostname) + return respond_oom(connection); + + r = sd_journal_get_usage(m->journal, &usage); + if (r < 0) + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %m"); + + r = sd_journal_get_cutoff_realtime_usec(m->journal, &cutoff_from, &cutoff_to); + if (r < 0) + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %m"); + + (void) parse_os_release(NULL, "PRETTY_NAME", &os_name, NULL); + (void) get_virtualization(&v); + + r = asprintf(&json, + "{ \"machine_id\" : \"" SD_ID128_FORMAT_STR "\"," + "\"boot_id\" : \"" SD_ID128_FORMAT_STR "\"," + "\"hostname\" : \"%s\"," + "\"os_pretty_name\" : \"%s\"," + "\"virtualization\" : \"%s\"," + "\"usage\" : \"%"PRIu64"\"," + "\"cutoff_from_realtime\" : \"%"PRIu64"\"," + "\"cutoff_to_realtime\" : \"%"PRIu64"\" }\n", + SD_ID128_FORMAT_VAL(mid), + SD_ID128_FORMAT_VAL(bid), + hostname_cleanup(hostname), + os_name ? os_name : "Linux", + v ? v : "bare", + usage, + cutoff_from, + cutoff_to); + if (r < 0) + return respond_oom(connection); + + response = MHD_create_response_from_buffer(strlen(json), json, MHD_RESPMEM_MUST_FREE); + if (!response) + return respond_oom(connection); + TAKE_PTR(json); + + MHD_add_response_header(response, "Content-Type", "application/json"); + return MHD_queue_response(connection, MHD_HTTP_OK, response); +} + +static int request_handler( + void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, + size_t *upload_data_size, + void **connection_cls) { + int r, code; + + assert(connection); + assert(connection_cls); + assert(url); + assert(method); + + if (!streq(method, "GET")) + return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method."); + + if (!*connection_cls) { + if (!request_meta(connection_cls)) + return respond_oom(connection); + return MHD_YES; + } + + if (arg_trust_pem) { + r = check_permissions(connection, &code, NULL); + if (r < 0) + return code; + } + + if (streq(url, "/")) + return request_handler_redirect(connection, "/browse"); + + if (streq(url, "/entries")) + return request_handler_entries(connection, *connection_cls); + + if (startswith(url, "/fields/")) + return request_handler_fields(connection, url + 8, *connection_cls); + + if (streq(url, "/browse")) + return request_handler_file(connection, DOCUMENT_ROOT "/browse.html", "text/html"); + + if (streq(url, "/machine")) + return request_handler_machine(connection, *connection_cls); + + return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found."); +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-journal-gatewayd.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] ...\n\n" + "HTTP server for journal events.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --cert=CERT.PEM Server certificate in PEM format\n" + " --key=KEY.PEM Server key in PEM format\n" + " --trust=CERT.PEM Certificate authority certificate in PEM format\n" + " -D --directory=PATH Serve journal files in directory\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_KEY, + ARG_CERT, + ARG_TRUST, + }; + + int r, c; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "key", required_argument, NULL, ARG_KEY }, + { "cert", required_argument, NULL, ARG_CERT }, + { "trust", required_argument, NULL, ARG_TRUST }, + { "directory", required_argument, NULL, 'D' }, + {} + }; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hD:", options, NULL)) >= 0) + + switch(c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_KEY: + if (arg_key_pem) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Key file specified twice"); + r = read_full_file(optarg, &arg_key_pem, NULL); + if (r < 0) + return log_error_errno(r, "Failed to read key file: %m"); + assert(arg_key_pem); + break; + + case ARG_CERT: + if (arg_cert_pem) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Certificate file specified twice"); + r = read_full_file(optarg, &arg_cert_pem, NULL); + if (r < 0) + return log_error_errno(r, "Failed to read certificate file: %m"); + assert(arg_cert_pem); + break; + + case ARG_TRUST: +#if HAVE_GNUTLS + if (arg_trust_pem) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "CA certificate file specified twice"); + r = read_full_file(optarg, &arg_trust_pem, NULL); + if (r < 0) + return log_error_errno(r, "Failed to read CA certificate file: %m"); + assert(arg_trust_pem); + break; +#else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --trust is not available."); +#endif + case 'D': + arg_directory = optarg; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program does not take arguments."); + + if (!!arg_key_pem != !!arg_cert_pem) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Certificate and key files must be specified together"); + + if (arg_trust_pem && !arg_key_pem) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "CA certificate can only be used with certificate file"); + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(MHD_stop_daemonp) struct MHD_Daemon *d = NULL; + struct MHD_OptionItem opts[] = { + { MHD_OPTION_NOTIFY_COMPLETED, + (intptr_t) request_meta_free, NULL }, + { MHD_OPTION_EXTERNAL_LOGGER, + (intptr_t) microhttpd_logger, NULL }, + { MHD_OPTION_END, 0, NULL }, + { MHD_OPTION_END, 0, NULL }, + { MHD_OPTION_END, 0, NULL }, + { MHD_OPTION_END, 0, NULL }, + { MHD_OPTION_END, 0, NULL }, + }; + int opts_pos = 2; + + /* We force MHD_USE_ITC here, in order to make sure + * libmicrohttpd doesn't use shutdown() on our listening + * socket, which would break socket re-activation. See + * + * https://lists.gnu.org/archive/html/libmicrohttpd/2015-09/msg00014.html + * https://github.com/systemd/systemd/pull/1286 + */ + + int flags = + MHD_USE_DEBUG | + MHD_USE_DUAL_STACK | + MHD_USE_ITC | + MHD_USE_POLL_INTERNAL_THREAD | + MHD_USE_THREAD_PER_CONNECTION; + int r, n; + + log_setup_service(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + sigbus_install(); + + r = setup_gnutls_logger(NULL); + if (r < 0) + return r; + + n = sd_listen_fds(1); + if (n < 0) + return log_error_errno(n, "Failed to determine passed sockets: %m"); + if (n > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Can't listen on more than one socket."); + + if (n == 1) + opts[opts_pos++] = (struct MHD_OptionItem) + { MHD_OPTION_LISTEN_SOCKET, SD_LISTEN_FDS_START }; + + if (arg_key_pem) { + assert(arg_cert_pem); + opts[opts_pos++] = (struct MHD_OptionItem) + { MHD_OPTION_HTTPS_MEM_KEY, 0, arg_key_pem }; + opts[opts_pos++] = (struct MHD_OptionItem) + { MHD_OPTION_HTTPS_MEM_CERT, 0, arg_cert_pem }; + flags |= MHD_USE_TLS; + } + + if (arg_trust_pem) { + assert(flags & MHD_USE_TLS); + opts[opts_pos++] = (struct MHD_OptionItem) + { MHD_OPTION_HTTPS_MEM_TRUST, 0, arg_trust_pem }; + } + + d = MHD_start_daemon(flags, 19531, + NULL, NULL, + request_handler, NULL, + MHD_OPTION_ARRAY, opts, + MHD_OPTION_END); + if (!d) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to start daemon!"); + + pause(); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c new file mode 100644 index 00000000..ac2bf648 --- /dev/null +++ b/src/journal-remote/journal-remote-main.c @@ -0,0 +1,1172 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-daemon.h" + +#include "conf-parser.h" +#include "daemon-util.h" +#include "def.h" +#include "fd-util.h" +#include "fileio.h" +#include "journal-remote-write.h" +#include "journal-remote.h" +#include "main-func.h" +#include "pretty-print.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "stat-util.h" +#include "string-table.h" +#include "strv.h" + +#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-remote.pem" +#define CERT_FILE CERTIFICATE_ROOT "/certs/journal-remote.pem" +#define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem" + +static const char* arg_url = NULL; +static const char* arg_getter = NULL; +static const char* arg_listen_raw = NULL; +static const char* arg_listen_http = NULL; +static const char* arg_listen_https = NULL; +static char** arg_files = NULL; /* Do not free this. */ +static int arg_compress = true; +static int arg_seal = false; +static int http_socket = -1, https_socket = -1; +static char** arg_gnutls_log = NULL; + +static JournalWriteSplitMode arg_split_mode = _JOURNAL_WRITE_SPLIT_INVALID; +static const char* arg_output = NULL; + +static char *arg_key = NULL; +static char *arg_cert = NULL; +static char *arg_trust = NULL; +static bool arg_trust_all = false; + +STATIC_DESTRUCTOR_REGISTER(arg_gnutls_log, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_key, freep); +STATIC_DESTRUCTOR_REGISTER(arg_cert, freep); +STATIC_DESTRUCTOR_REGISTER(arg_trust, freep); + +static const char* const journal_write_split_mode_table[_JOURNAL_WRITE_SPLIT_MAX] = { + [JOURNAL_WRITE_SPLIT_NONE] = "none", + [JOURNAL_WRITE_SPLIT_HOST] = "host", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(journal_write_split_mode, JournalWriteSplitMode); +static DEFINE_CONFIG_PARSE_ENUM(config_parse_write_split_mode, + journal_write_split_mode, + JournalWriteSplitMode, + "Failed to parse split mode setting"); + +/********************************************************************** + ********************************************************************** + **********************************************************************/ + +static int spawn_child(const char* child, char** argv) { + pid_t child_pid; + int fd[2], r; + + if (pipe(fd) < 0) + return log_error_errno(errno, "Failed to create pager pipe: %m"); + + r = safe_fork("(remote)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &child_pid); + if (r < 0) { + safe_close_pair(fd); + return r; + } + + /* In the child */ + if (r == 0) { + safe_close(fd[0]); + + r = rearrange_stdio(STDIN_FILENO, fd[1], STDERR_FILENO); + if (r < 0) { + log_error_errno(r, "Failed to dup pipe to stdout: %m"); + _exit(EXIT_FAILURE); + } + + (void) rlimit_nofile_safe(); + + execvp(child, argv); + log_error_errno(errno, "Failed to exec child %s: %m", child); + _exit(EXIT_FAILURE); + } + + safe_close(fd[1]); + + r = fd_nonblock(fd[0], true); + if (r < 0) + log_warning_errno(errno, "Failed to set child pipe to non-blocking: %m"); + + return fd[0]; +} + +static int spawn_curl(const char* url) { + char **argv = STRV_MAKE("curl", + "-HAccept: application/vnd.fdo.journal", + "--silent", + "--show-error", + url); + int r; + + r = spawn_child("curl", argv); + if (r < 0) + log_error_errno(r, "Failed to spawn curl: %m"); + return r; +} + +static int spawn_getter(const char *getter) { + int r; + _cleanup_strv_free_ char **words = NULL; + + assert(getter); + r = strv_split_extract(&words, getter, WHITESPACE, EXTRACT_UNQUOTE); + if (r < 0) + return log_error_errno(r, "Failed to split getter option: %m"); + + r = spawn_child(words[0], words); + if (r < 0) + log_error_errno(r, "Failed to spawn getter %s: %m", getter); + + return r; +} + +/********************************************************************** + ********************************************************************** + **********************************************************************/ + +static int null_timer_event_handler(sd_event_source *s, + uint64_t usec, + void *userdata); +static int dispatch_http_event(sd_event_source *event, + int fd, + uint32_t revents, + void *userdata); + +static int request_meta(void **connection_cls, int fd, char *hostname) { + RemoteSource *source; + Writer *writer; + int r; + + assert(connection_cls); + if (*connection_cls) + return 0; + + r = journal_remote_get_writer(journal_remote_server_global, hostname, &writer); + if (r < 0) + return log_warning_errno(r, "Failed to get writer for source %s: %m", + hostname); + + source = source_new(fd, true, hostname, writer); + if (!source) { + writer_unref(writer); + return log_oom(); + } + + log_debug("Added RemoteSource as connection metadata %p", source); + + *connection_cls = source; + return 0; +} + +static void request_meta_free(void *cls, + struct MHD_Connection *connection, + void **connection_cls, + enum MHD_RequestTerminationCode toe) { + RemoteSource *s; + + assert(connection_cls); + s = *connection_cls; + + if (s) { + log_debug("Cleaning up connection metadata %p", s); + source_free(s); + *connection_cls = NULL; + } +} + +static int process_http_upload( + struct MHD_Connection *connection, + const char *upload_data, + size_t *upload_data_size, + RemoteSource *source) { + + bool finished = false; + size_t remaining; + int r; + + assert(source); + + log_trace("%s: connection %p, %zu bytes", + __func__, connection, *upload_data_size); + + if (*upload_data_size) { + log_trace("Received %zu bytes", *upload_data_size); + + r = journal_importer_push_data(&source->importer, + upload_data, *upload_data_size); + if (r < 0) + return mhd_respond_oom(connection); + + *upload_data_size = 0; + } else + finished = true; + + for (;;) { + r = process_source(source, + journal_remote_server_global->compress, + journal_remote_server_global->seal); + if (r == -EAGAIN) + break; + if (r < 0) { + if (r == -ENOBUFS) + log_warning_errno(r, "Entry is above the maximum of %u, aborting connection %p.", + DATA_SIZE_MAX, connection); + else if (r == -E2BIG) + log_warning_errno(r, "Entry with more fields than the maximum of %u, aborting connection %p.", + ENTRY_FIELD_COUNT_MAX, connection); + else + log_warning_errno(r, "Failed to process data, aborting connection %p: %m", + connection); + return MHD_NO; + } + } + + if (!finished) + return MHD_YES; + + /* The upload is finished */ + + remaining = journal_importer_bytes_remaining(&source->importer); + if (remaining > 0) { + log_warning("Premature EOF byte. %zu bytes lost.", remaining); + return mhd_respondf(connection, + 0, MHD_HTTP_EXPECTATION_FAILED, + "Premature EOF. %zu bytes of trailing data not processed.", + remaining); + } + + return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK."); +}; + +static int request_handler( + void *cls, + struct MHD_Connection *connection, + const char *url, + const char *method, + const char *version, + const char *upload_data, + size_t *upload_data_size, + void **connection_cls) { + + const char *header; + int r, code, fd; + _cleanup_free_ char *hostname = NULL; + bool chunked = false; + + assert(connection); + assert(connection_cls); + assert(url); + assert(method); + + log_trace("Handling a connection %s %s %s", method, url, version); + + if (*connection_cls) + return process_http_upload(connection, + upload_data, upload_data_size, + *connection_cls); + + if (!streq(method, "POST")) + return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method."); + + if (!streq(url, "/upload")) + return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found."); + + header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Type"); + if (!header || !streq(header, "application/vnd.fdo.journal")) + return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE, + "Content-Type: application/vnd.fdo.journal is required."); + + header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Transfer-Encoding"); + if (header) { + if (!strcaseeq(header, "chunked")) + return mhd_respondf(connection, 0, MHD_HTTP_BAD_REQUEST, + "Unsupported Transfer-Encoding type: %s", header); + + chunked = true; + } + + header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Length"); + if (header) { + size_t len; + + if (chunked) + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, + "Content-Length must not specified when Transfer-Encoding type is 'chuncked'"); + + r = safe_atozu(header, &len); + if (r < 0) + return mhd_respondf(connection, r, MHD_HTTP_LENGTH_REQUIRED, + "Content-Length: %s cannot be parsed: %m", header); + + if (len > ENTRY_SIZE_MAX) + /* When serialized, an entry of maximum size might be slightly larger, + * so this does not correspond exactly to the limit in journald. Oh well. + */ + return mhd_respondf(connection, 0, MHD_HTTP_PAYLOAD_TOO_LARGE, + "Payload larger than maximum size of %u bytes", ENTRY_SIZE_MAX); + } + + { + const union MHD_ConnectionInfo *ci; + + ci = MHD_get_connection_info(connection, + MHD_CONNECTION_INFO_CONNECTION_FD); + if (!ci) { + log_error("MHD_get_connection_info failed: cannot get remote fd"); + return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, + "Cannot check remote address."); + } + + fd = ci->connect_fd; + assert(fd >= 0); + } + + if (journal_remote_server_global->check_trust) { + r = check_permissions(connection, &code, &hostname); + if (r < 0) + return code; + } else { + r = getpeername_pretty(fd, false, &hostname); + if (r < 0) + return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, + "Cannot check remote hostname."); + } + + assert(hostname); + + r = request_meta(connection_cls, fd, hostname); + if (r == -ENOMEM) + return respond_oom(connection); + else if (r < 0) + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "%m"); + + hostname = NULL; + return MHD_YES; +} + +static int setup_microhttpd_server(RemoteServer *s, + int fd, + const char *key, + const char *cert, + const char *trust) { + struct MHD_OptionItem opts[] = { + { MHD_OPTION_NOTIFY_COMPLETED, (intptr_t) request_meta_free}, + { MHD_OPTION_EXTERNAL_LOGGER, (intptr_t) microhttpd_logger}, + { MHD_OPTION_LISTEN_SOCKET, fd}, + { MHD_OPTION_CONNECTION_MEMORY_LIMIT, 128*1024}, + { MHD_OPTION_END}, + { MHD_OPTION_END}, + { MHD_OPTION_END}, + { MHD_OPTION_END}, + { MHD_OPTION_END}}; + int opts_pos = 4; + int flags = + MHD_USE_DEBUG | + MHD_USE_DUAL_STACK | + MHD_USE_EPOLL | + MHD_USE_ITC; + + const union MHD_DaemonInfo *info; + int r, epoll_fd; + MHDDaemonWrapper *d; + + assert(fd >= 0); + + r = fd_nonblock(fd, true); + if (r < 0) + return log_error_errno(r, "Failed to make fd:%d nonblocking: %m", fd); + +/* MHD_OPTION_STRICT_FOR_CLIENT is introduced in microhttpd 0.9.54, + * and MHD_USE_PEDANTIC_CHECKS will be deprecated in future. + * If MHD_USE_PEDANTIC_CHECKS is '#define'd, then it is deprecated + * and we should use MHD_OPTION_STRICT_FOR_CLIENT. On the other hand, + * if MHD_USE_PEDANTIC_CHECKS is not '#define'd, then it is not + * deprecated yet and there exists an enum element with the same name. + * So we can safely use it. */ +#ifdef MHD_USE_PEDANTIC_CHECKS + opts[opts_pos++] = (struct MHD_OptionItem) + {MHD_OPTION_STRICT_FOR_CLIENT, 1}; +#else + flags |= MHD_USE_PEDANTIC_CHECKS; +#endif + + if (key) { + assert(cert); + + opts[opts_pos++] = (struct MHD_OptionItem) + {MHD_OPTION_HTTPS_MEM_KEY, 0, (char*) key}; + opts[opts_pos++] = (struct MHD_OptionItem) + {MHD_OPTION_HTTPS_MEM_CERT, 0, (char*) cert}; + + flags |= MHD_USE_TLS; + + if (trust) + opts[opts_pos++] = (struct MHD_OptionItem) + {MHD_OPTION_HTTPS_MEM_TRUST, 0, (char*) trust}; + } + + d = new(MHDDaemonWrapper, 1); + if (!d) + return log_oom(); + + d->fd = (uint64_t) fd; + + d->daemon = MHD_start_daemon(flags, 0, + NULL, NULL, + request_handler, NULL, + MHD_OPTION_ARRAY, opts, + MHD_OPTION_END); + if (!d->daemon) { + log_error("Failed to start µhttp daemon"); + r = -EINVAL; + goto error; + } + + log_debug("Started MHD %s daemon on fd:%d (wrapper @ %p)", + key ? "HTTPS" : "HTTP", fd, d); + + info = MHD_get_daemon_info(d->daemon, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY); + if (!info) { + log_error("µhttp returned NULL daemon info"); + r = -EOPNOTSUPP; + goto error; + } + + epoll_fd = info->listen_fd; + if (epoll_fd < 0) { + log_error("µhttp epoll fd is invalid"); + r = -EUCLEAN; + goto error; + } + + r = sd_event_add_io(s->events, &d->io_event, + epoll_fd, EPOLLIN, + dispatch_http_event, d); + if (r < 0) { + log_error_errno(r, "Failed to add event callback: %m"); + goto error; + } + + r = sd_event_source_set_description(d->io_event, "io_event"); + if (r < 0) { + log_error_errno(r, "Failed to set source name: %m"); + goto error; + } + + r = sd_event_add_time(s->events, &d->timer_event, + CLOCK_MONOTONIC, (uint64_t) -1, 0, + null_timer_event_handler, d); + if (r < 0) { + log_error_errno(r, "Failed to add timer_event: %m"); + goto error; + } + + r = sd_event_source_set_description(d->timer_event, "timer_event"); + if (r < 0) { + log_error_errno(r, "Failed to set source name: %m"); + goto error; + } + + r = hashmap_ensure_allocated(&s->daemons, &uint64_hash_ops); + if (r < 0) { + log_oom(); + goto error; + } + + r = hashmap_put(s->daemons, &d->fd, d); + if (r < 0) { + log_error_errno(r, "Failed to add daemon to hashmap: %m"); + goto error; + } + + s->active++; + return 0; + +error: + MHD_stop_daemon(d->daemon); + free(d->daemon); + free(d); + return r; +} + +static int setup_microhttpd_socket(RemoteServer *s, + const char *address, + const char *key, + const char *cert, + const char *trust) { + int fd; + + fd = make_socket_fd(LOG_DEBUG, address, SOCK_STREAM, SOCK_CLOEXEC); + if (fd < 0) + return fd; + + return setup_microhttpd_server(s, fd, key, cert, trust); +} + +static int null_timer_event_handler(sd_event_source *timer_event, + uint64_t usec, + void *userdata) { + return dispatch_http_event(timer_event, 0, 0, userdata); +} + +static int dispatch_http_event(sd_event_source *event, + int fd, + uint32_t revents, + void *userdata) { + MHDDaemonWrapper *d = userdata; + int r; + MHD_UNSIGNED_LONG_LONG timeout = ULLONG_MAX; + + assert(d); + + r = MHD_run(d->daemon); + if (r == MHD_NO) + // FIXME: unregister daemon + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "MHD_run failed!"); + if (MHD_get_timeout(d->daemon, &timeout) == MHD_NO) + timeout = ULLONG_MAX; + + r = sd_event_source_set_time(d->timer_event, timeout); + if (r < 0) { + log_warning_errno(r, "Unable to set event loop timeout: %m, this may result in indefinite blocking!"); + return 1; + } + + r = sd_event_source_set_enabled(d->timer_event, SD_EVENT_ON); + if (r < 0) + log_warning_errno(r, "Unable to enable timer_event: %m, this may result in indefinite blocking!"); + + return 1; /* work to do */ +} + +/********************************************************************** + ********************************************************************** + **********************************************************************/ + +static int setup_signals(RemoteServer *s) { + int r; + + assert(s); + + assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0); + + r = sd_event_add_signal(s->events, &s->sigterm_event, SIGTERM, NULL, s); + if (r < 0) + return r; + + r = sd_event_add_signal(s->events, &s->sigint_event, SIGINT, NULL, s); + if (r < 0) + return r; + + return 0; +} + +static int setup_raw_socket(RemoteServer *s, const char *address) { + int fd; + + fd = make_socket_fd(LOG_INFO, address, SOCK_STREAM, SOCK_CLOEXEC); + if (fd < 0) + return fd; + + return journal_remote_add_raw_socket(s, fd); +} + +static int create_remoteserver( + RemoteServer *s, + const char* key, + const char* cert, + const char* trust) { + + int r, n, fd; + char **file; + + r = journal_remote_server_init(s, arg_output, arg_split_mode, arg_compress, arg_seal); + if (r < 0) + return r; + + r = setup_signals(s); + if (r < 0) + return log_error_errno(r, "Failed to set up signals: %m"); + + n = sd_listen_fds(true); + if (n < 0) + return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); + else + log_debug("Received %d descriptors", n); + + if (MAX(http_socket, https_socket) >= SD_LISTEN_FDS_START + n) + return log_error_errno(SYNTHETIC_ERRNO(EBADFD), + "Received fewer sockets than expected"); + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { + if (sd_is_socket(fd, AF_UNSPEC, 0, true)) { + log_debug("Received a listening socket (fd:%d)", fd); + + if (fd == http_socket) + r = setup_microhttpd_server(s, fd, NULL, NULL, NULL); + else if (fd == https_socket) + r = setup_microhttpd_server(s, fd, key, cert, trust); + else + r = journal_remote_add_raw_socket(s, fd); + } else if (sd_is_socket(fd, AF_UNSPEC, 0, false)) { + char *hostname; + + r = getpeername_pretty(fd, false, &hostname); + if (r < 0) + return log_error_errno(r, "Failed to retrieve remote name: %m"); + + log_debug("Received a connection socket (fd:%d) from %s", fd, hostname); + + r = journal_remote_add_source(s, fd, hostname, true); + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown socket passed on fd:%d", fd); + + if (r < 0) + return log_error_errno(r, "Failed to register socket (fd:%d): %m", fd); + } + + if (arg_getter) { + log_info("Spawning getter %s...", arg_getter); + fd = spawn_getter(arg_getter); + if (fd < 0) + return fd; + + r = journal_remote_add_source(s, fd, (char*) arg_output, false); + if (r < 0) + return r; + } + + if (arg_url) { + const char *url, *hostname; + + if (!strstr(arg_url, "/entries")) { + if (endswith(arg_url, "/")) + url = strjoina(arg_url, "entries"); + else + url = strjoina(arg_url, "/entries"); + } else + url = strdupa(arg_url); + + log_info("Spawning curl %s...", url); + fd = spawn_curl(url); + if (fd < 0) + return fd; + + hostname = STARTSWITH_SET(arg_url, "https://", "http://"); + if (!hostname) + hostname = arg_url; + + hostname = strndupa(hostname, strcspn(hostname, "/:")); + + r = journal_remote_add_source(s, fd, (char *) hostname, false); + if (r < 0) + return r; + } + + if (arg_listen_raw) { + log_debug("Listening on a socket..."); + r = setup_raw_socket(s, arg_listen_raw); + if (r < 0) + return r; + } + + if (arg_listen_http) { + r = setup_microhttpd_socket(s, arg_listen_http, NULL, NULL, NULL); + if (r < 0) + return r; + } + + if (arg_listen_https) { + r = setup_microhttpd_socket(s, arg_listen_https, key, cert, trust); + if (r < 0) + return r; + } + + STRV_FOREACH(file, arg_files) { + const char *output_name; + + if (streq(*file, "-")) { + log_debug("Using standard input as source."); + + fd = STDIN_FILENO; + output_name = "stdin"; + } else { + log_debug("Reading file %s...", *file); + + fd = open(*file, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); + if (fd < 0) + return log_error_errno(errno, "Failed to open %s: %m", *file); + output_name = *file; + } + + r = journal_remote_add_source(s, fd, (char*) output_name, false); + if (r < 0) + return r; + } + + if (s->active == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Zero sources specified"); + + if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE) { + /* In this case we know what the writer will be + called, so we can create it and verify that we can + create output as expected. */ + r = journal_remote_get_writer(s, NULL, &s->_single_writer); + if (r < 0) + return r; + } + + return 0; +} + +static int negative_fd(const char *spec) { + /* Return a non-positive number as its inverse, -EINVAL otherwise. */ + + int fd, r; + + r = safe_atoi(spec, &fd); + if (r < 0) + return r; + + if (fd > 0) + return -EINVAL; + else + return -fd; +} + +static int parse_config(void) { + const ConfigTableItem items[] = { + { "Remote", "Seal", config_parse_bool, 0, &arg_seal }, + { "Remote", "SplitMode", config_parse_write_split_mode, 0, &arg_split_mode }, + { "Remote", "ServerKeyFile", config_parse_path, 0, &arg_key }, + { "Remote", "ServerCertificateFile", config_parse_path, 0, &arg_cert }, + { "Remote", "TrustedCertificateFile", config_parse_path, 0, &arg_trust }, + {} + }; + + return config_parse_many_nulstr(PKGSYSCONFDIR "/journal-remote.conf", + CONF_PATHS_NULSTR("systemd/journal-remote.conf.d"), + "Remote\0", config_item_table_lookup, items, + CONFIG_PARSE_WARN, NULL); +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-journal-remote.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] {FILE|-}...\n\n" + "Write external journal events to journal file(s).\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --url=URL Read events from systemd-journal-gatewayd at URL\n" + " --getter=COMMAND Read events from the output of COMMAND\n" + " --listen-raw=ADDR Listen for connections at ADDR\n" + " --listen-http=ADDR Listen for HTTP connections at ADDR\n" + " --listen-https=ADDR Listen for HTTPS connections at ADDR\n" + " -o --output=FILE|DIR Write output to FILE or DIR/external-*.journal\n" + " --compress[=BOOL] XZ-compress the output journal (default: yes)\n" + " --seal[=BOOL] Use event sealing (default: no)\n" + " --key=FILENAME SSL key in PEM format (default:\n" + " \"" PRIV_KEY_FILE "\")\n" + " --cert=FILENAME SSL certificate in PEM format (default:\n" + " \"" CERT_FILE "\")\n" + " --trust=FILENAME|all SSL CA certificate or disable checking (default:\n" + " \"" TRUST_FILE "\")\n" + " --gnutls-log=CATEGORY...\n" + " Specify a list of gnutls logging categories\n" + " --split-mode=none|host How many output files to create\n" + "\nNote: file descriptors from sd_listen_fds() will be consumed, too.\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_URL, + ARG_LISTEN_RAW, + ARG_LISTEN_HTTP, + ARG_LISTEN_HTTPS, + ARG_GETTER, + ARG_SPLIT_MODE, + ARG_COMPRESS, + ARG_SEAL, + ARG_KEY, + ARG_CERT, + ARG_TRUST, + ARG_GNUTLS_LOG, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "url", required_argument, NULL, ARG_URL }, + { "getter", required_argument, NULL, ARG_GETTER }, + { "listen-raw", required_argument, NULL, ARG_LISTEN_RAW }, + { "listen-http", required_argument, NULL, ARG_LISTEN_HTTP }, + { "listen-https", required_argument, NULL, ARG_LISTEN_HTTPS }, + { "output", required_argument, NULL, 'o' }, + { "split-mode", required_argument, NULL, ARG_SPLIT_MODE }, + { "compress", optional_argument, NULL, ARG_COMPRESS }, + { "seal", optional_argument, NULL, ARG_SEAL }, + { "key", required_argument, NULL, ARG_KEY }, + { "cert", required_argument, NULL, ARG_CERT }, + { "trust", required_argument, NULL, ARG_TRUST }, + { "gnutls-log", required_argument, NULL, ARG_GNUTLS_LOG }, + {} + }; + + int c, r; + bool type_a, type_b; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "ho:", options, NULL)) >= 0) + switch(c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_URL: + if (arg_url) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot currently set more than one --url"); + + arg_url = optarg; + break; + + case ARG_GETTER: + if (arg_getter) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot currently use --getter more than once"); + + arg_getter = optarg; + break; + + case ARG_LISTEN_RAW: + if (arg_listen_raw) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot currently use --listen-raw more than once"); + + arg_listen_raw = optarg; + break; + + case ARG_LISTEN_HTTP: + if (arg_listen_http || http_socket >= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot currently use --listen-http more than once"); + + r = negative_fd(optarg); + if (r >= 0) + http_socket = r; + else + arg_listen_http = optarg; + break; + + case ARG_LISTEN_HTTPS: + if (arg_listen_https || https_socket >= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot currently use --listen-https more than once"); + + r = negative_fd(optarg); + if (r >= 0) + https_socket = r; + else + arg_listen_https = optarg; + + break; + + case ARG_KEY: + if (arg_key) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Key file specified twice"); + + arg_key = strdup(optarg); + if (!arg_key) + return log_oom(); + + break; + + case ARG_CERT: + if (arg_cert) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Certificate file specified twice"); + + arg_cert = strdup(optarg); + if (!arg_cert) + return log_oom(); + + break; + + case ARG_TRUST: + if (arg_trust || arg_trust_all) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Confusing trusted CA configuration"); + + if (streq(optarg, "all")) + arg_trust_all = true; + else { +#if HAVE_GNUTLS + arg_trust = strdup(optarg); + if (!arg_trust) + return log_oom(); +#else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --trust is not available."); +#endif + } + + break; + + case 'o': + if (arg_output) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use --output/-o more than once"); + + arg_output = optarg; + break; + + case ARG_SPLIT_MODE: + arg_split_mode = journal_write_split_mode_from_string(optarg); + if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid split mode: %s", optarg); + break; + + case ARG_COMPRESS: + if (optarg) { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse --compress= parameter."); + + arg_compress = !!r; + } else + arg_compress = true; + + break; + + case ARG_SEAL: + if (optarg) { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse --seal= parameter."); + + arg_seal = !!r; + } else + arg_seal = true; + + break; + + case ARG_GNUTLS_LOG: { +#if HAVE_GNUTLS + const char* p = optarg; + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse --gnutls-log= argument: %m"); + if (r == 0) + break; + + if (strv_push(&arg_gnutls_log, word) < 0) + return log_oom(); + + word = NULL; + } + break; +#else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --gnutls-log is not available."); +#endif + } + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unknown option code."); + } + + if (optind < argc) + arg_files = argv + optind; + + type_a = arg_getter || !strv_isempty(arg_files); + type_b = arg_url + || arg_listen_raw + || arg_listen_http || arg_listen_https + || sd_listen_fds(false) > 0; + if (type_a && type_b) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot use file input or --getter with " + "--arg-listen-... or socket activation."); + if (type_a) { + if (!arg_output) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --output must be specified with file input or --getter."); + + if (!IN_SET(arg_split_mode, JOURNAL_WRITE_SPLIT_NONE, _JOURNAL_WRITE_SPLIT_INVALID)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "For active sources, only --split-mode=none is allowed."); + + arg_split_mode = JOURNAL_WRITE_SPLIT_NONE; + } + + if (arg_split_mode == _JOURNAL_WRITE_SPLIT_INVALID) + arg_split_mode = JOURNAL_WRITE_SPLIT_HOST; + + if (arg_split_mode == JOURNAL_WRITE_SPLIT_NONE && arg_output) { + if (is_dir(arg_output, true) > 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "For SplitMode=none, output must be a file."); + if (!endswith(arg_output, ".journal")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "For SplitMode=none, output file name must end with .journal."); + } + + if (arg_split_mode == JOURNAL_WRITE_SPLIT_HOST + && arg_output && is_dir(arg_output, true) <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "For SplitMode=host, output must be a directory."); + + log_debug("Full config: SplitMode=%s Key=%s Cert=%s Trust=%s", + journal_write_split_mode_to_string(arg_split_mode), + strna(arg_key), + strna(arg_cert), + strna(arg_trust)); + + return 1 /* work to do */; +} + +static int load_certificates(char **key, char **cert, char **trust) { + int r; + + r = read_full_file(arg_key ?: PRIV_KEY_FILE, key, NULL); + if (r < 0) + return log_error_errno(r, "Failed to read key from file '%s': %m", + arg_key ?: PRIV_KEY_FILE); + + r = read_full_file(arg_cert ?: CERT_FILE, cert, NULL); + if (r < 0) + return log_error_errno(r, "Failed to read certificate from file '%s': %m", + arg_cert ?: CERT_FILE); + + if (arg_trust_all) + log_info("Certificate checking disabled."); + else { + r = read_full_file(arg_trust ?: TRUST_FILE, trust, NULL); + if (r < 0) + return log_error_errno(r, "Failed to read CA certificate file '%s': %m", + arg_trust ?: TRUST_FILE); + } + + if ((arg_listen_raw || arg_listen_http) && *trust) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --trust makes all non-HTTPS connections untrusted."); + + return 0; +} + +static int run(int argc, char **argv) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; + _cleanup_(journal_remote_server_destroy) RemoteServer s = {}; + _cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL; + int r; + + log_show_color(true); + log_parse_environment(); + + /* The journal merging logic potentially needs a lot of fds. */ + (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); + + r = parse_config(); + if (r < 0) + return r; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (arg_listen_http || arg_listen_https) { + r = setup_gnutls_logger(arg_gnutls_log); + if (r < 0) + return r; + } + + if (arg_listen_https || https_socket >= 0) { + r = load_certificates(&key, &cert, &trust); + if (r < 0) + return r; + + s.check_trust = !arg_trust_all; + } + + r = create_remoteserver(&s, key, cert, trust); + if (r < 0) + return r; + + r = sd_event_set_watchdog(s.events, true); + if (r < 0) + return log_error_errno(r, "Failed to enable watchdog: %m"); + + log_debug("Watchdog is %sd.", enable_disable(r > 0)); + + log_debug("%s running as pid "PID_FMT, + program_invocation_short_name, getpid_cached()); + + notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING); + + while (s.active) { + r = sd_event_get_state(s.events); + if (r < 0) + return r; + if (r == SD_EVENT_FINISHED) + break; + + r = sd_event_run(s.events, -1); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + } + + notify_message = NULL; + (void) sd_notifyf(false, + "STOPPING=1\n" + "STATUS=Shutting down after writing %" PRIu64 " entries...", s.event_count); + + log_info("Finishing after writing %" PRIu64 " entries", s.event_count); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c new file mode 100644 index 00000000..dc047b2d --- /dev/null +++ b/src/journal-remote/journal-remote-parse.c @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "fd-util.h" +#include "journal-remote-parse.h" +#include "journald-native.h" +#include "parse-util.h" +#include "string-util.h" + +void source_free(RemoteSource *source) { + if (!source) + return; + + journal_importer_cleanup(&source->importer); + + log_debug("Writer ref count %i", source->writer->n_ref); + writer_unref(source->writer); + + sd_event_source_unref(source->event); + sd_event_source_unref(source->buffer_event); + + free(source); +} + +/** + * Initialize zero-filled source with given values. On success, takes + * ownership of fd, name, and writer, otherwise does not touch them. + */ +RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer) { + RemoteSource *source; + + log_debug("Creating source for %sfd:%d (%s)", + passive_fd ? "passive " : "", fd, name); + + assert(fd >= 0); + + source = new0(RemoteSource, 1); + if (!source) + return NULL; + + source->importer = JOURNAL_IMPORTER_MAKE(fd); + source->importer.passive_fd = passive_fd; + source->importer.name = name; + + source->writer = writer; + + return source; +} + +int process_source(RemoteSource *source, bool compress, bool seal) { + int r; + + assert(source); + assert(source->writer); + + r = journal_importer_process_data(&source->importer); + if (r <= 0) + return r; + + /* We have a full event */ + log_trace("Received full event from source@%p fd:%d (%s)", + source, source->importer.fd, source->importer.name); + + if (source->importer.iovw.count == 0) { + log_warning("Entry with no payload, skipping"); + goto freeing; + } + + assert(source->importer.iovw.iovec); + + r = writer_write(source->writer, + &source->importer.iovw, + &source->importer.ts, + &source->importer.boot_id, + compress, seal); + if (r == -EBADMSG) { + log_error_errno(r, "Entry is invalid, ignoring."); + r = 0; + } else if (r < 0) + log_error_errno(r, "Failed to write entry of %zu bytes: %m", + iovw_size(&source->importer.iovw)); + else + r = 1; + + freeing: + journal_importer_drop_iovw(&source->importer); + return r; +} diff --git a/src/journal-remote/journal-remote-parse.h b/src/journal-remote/journal-remote-parse.h new file mode 100644 index 00000000..d6c77360 --- /dev/null +++ b/src/journal-remote/journal-remote-parse.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" + +#include "journal-importer.h" +#include "journal-remote-write.h" + +typedef struct RemoteSource { + JournalImporter importer; + + Writer *writer; + + sd_event_source *event; + sd_event_source *buffer_event; +} RemoteSource; + +RemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer); +void source_free(RemoteSource *source); +int process_source(RemoteSource *source, bool compress, bool seal); diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c new file mode 100644 index 00000000..ab5e03ab --- /dev/null +++ b/src/journal-remote/journal-remote-write.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "journal-remote.h" + +static int do_rotate(JournalFile **f, bool compress, bool seal) { + int r = journal_file_rotate(f, compress, (uint64_t) -1, seal, NULL); + if (r < 0) { + if (*f) + log_error_errno(r, "Failed to rotate %s: %m", (*f)->path); + else + log_error_errno(r, "Failed to create rotated journal: %m"); + } + + return r; +} + +Writer* writer_new(RemoteServer *server) { + Writer *w; + + w = new0(Writer, 1); + if (!w) + return NULL; + + memset(&w->metrics, 0xFF, sizeof(w->metrics)); + + w->mmap = mmap_cache_new(); + if (!w->mmap) + return mfree(w); + + w->n_ref = 1; + w->server = server; + + return w; +} + +static Writer* writer_free(Writer *w) { + if (!w) + return NULL; + + if (w->journal) { + log_debug("Closing journal file %s.", w->journal->path); + journal_file_close(w->journal); + } + + if (w->server && w->hashmap_key) + hashmap_remove(w->server->writers, w->hashmap_key); + + free(w->hashmap_key); + + if (w->mmap) + mmap_cache_unref(w->mmap); + + return mfree(w); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(Writer, writer, writer_free); + +int writer_write(Writer *w, + struct iovec_wrapper *iovw, + dual_timestamp *ts, + sd_id128_t *boot_id, + bool compress, + bool seal) { + int r; + + assert(w); + assert(iovw); + assert(iovw->count > 0); + + if (journal_file_rotate_suggested(w->journal, 0)) { + log_info("%s: Journal header limits reached or header out-of-date, rotating", + w->journal->path); + r = do_rotate(&w->journal, compress, seal); + if (r < 0) + return r; + } + + r = journal_file_append_entry(w->journal, ts, boot_id, + iovw->iovec, iovw->count, + &w->seqnum, NULL, NULL); + if (r >= 0) { + if (w->server) + w->server->event_count += 1; + return 0; + } else if (r == -EBADMSG) + return r; + + log_debug_errno(r, "%s: Write failed, rotating: %m", w->journal->path); + r = do_rotate(&w->journal, compress, seal); + if (r < 0) + return r; + else + log_debug("%s: Successfully rotated journal", w->journal->path); + + log_debug("Retrying write."); + r = journal_file_append_entry(w->journal, ts, boot_id, + iovw->iovec, iovw->count, + &w->seqnum, NULL, NULL); + if (r < 0) + return r; + + if (w->server) + w->server->event_count += 1; + return 0; +} diff --git a/src/journal-remote/journal-remote-write.h b/src/journal-remote/journal-remote-write.h new file mode 100644 index 00000000..d42256e6 --- /dev/null +++ b/src/journal-remote/journal-remote-write.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "journal-file.h" +#include "journal-importer.h" + +typedef struct RemoteServer RemoteServer; + +typedef struct Writer { + JournalFile *journal; + JournalMetrics metrics; + + MMapCache *mmap; + RemoteServer *server; + char *hashmap_key; + + uint64_t seqnum; + + unsigned n_ref; +} Writer; + +Writer* writer_new(RemoteServer* server); +Writer* writer_ref(Writer *w); +Writer* writer_unref(Writer *w); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Writer*, writer_unref); + +int writer_write(Writer *s, + struct iovec_wrapper *iovw, + dual_timestamp *ts, + sd_id128_t *boot_id, + bool compress, + bool seal); + +typedef enum JournalWriteSplitMode { + JOURNAL_WRITE_SPLIT_NONE, + JOURNAL_WRITE_SPLIT_HOST, + _JOURNAL_WRITE_SPLIT_MAX, + _JOURNAL_WRITE_SPLIT_INVALID = -1 +} JournalWriteSplitMode; diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c new file mode 100644 index 00000000..b241d335 --- /dev/null +++ b/src/journal-remote/journal-remote.c @@ -0,0 +1,536 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "def.h" +#include "errno-util.h" +#include "escape.h" +#include "fd-util.h" +#include "journal-file.h" +#include "journal-remote-write.h" +#include "journal-remote.h" +#include "journald-native.h" +#include "macro.h" +#include "parse-util.h" +#include "process-util.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" + +#define REMOTE_JOURNAL_PATH "/var/log/journal/remote" + +#define filename_escape(s) xescape((s), "/ ") + +static int open_output(RemoteServer *s, Writer *w, const char* host) { + _cleanup_free_ char *_filename = NULL; + const char *filename; + int r; + + switch (s->split_mode) { + case JOURNAL_WRITE_SPLIT_NONE: + filename = s->output; + break; + + case JOURNAL_WRITE_SPLIT_HOST: { + _cleanup_free_ char *name; + + assert(host); + + name = filename_escape(host); + if (!name) + return log_oom(); + + r = asprintf(&_filename, "%s/remote-%s.journal", s->output, name); + if (r < 0) + return log_oom(); + + filename = _filename; + break; + } + + default: + assert_not_reached("what?"); + } + + r = journal_file_open_reliably(filename, + O_RDWR|O_CREAT, 0640, + s->compress, (uint64_t) -1, s->seal, + &w->metrics, + w->mmap, NULL, + NULL, &w->journal); + if (r < 0) + return log_error_errno(r, "Failed to open output journal %s: %m", filename); + + log_debug("Opened output file %s", w->journal->path); + return 0; +} + +/********************************************************************** + ********************************************************************** + **********************************************************************/ + +static int init_writer_hashmap(RemoteServer *s) { + static const struct hash_ops* const hash_ops[] = { + [JOURNAL_WRITE_SPLIT_NONE] = NULL, + [JOURNAL_WRITE_SPLIT_HOST] = &string_hash_ops, + }; + + assert(s); + assert(s->split_mode >= 0 && s->split_mode < (int) ELEMENTSOF(hash_ops)); + + s->writers = hashmap_new(hash_ops[s->split_mode]); + if (!s->writers) + return log_oom(); + + return 0; +} + +int journal_remote_get_writer(RemoteServer *s, const char *host, Writer **writer) { + _cleanup_(writer_unrefp) Writer *w = NULL; + const void *key; + int r; + + switch(s->split_mode) { + case JOURNAL_WRITE_SPLIT_NONE: + key = "one and only"; + break; + + case JOURNAL_WRITE_SPLIT_HOST: + assert(host); + key = host; + break; + + default: + assert_not_reached("what split mode?"); + } + + w = hashmap_get(s->writers, key); + if (w) + writer_ref(w); + else { + w = writer_new(s); + if (!w) + return log_oom(); + + if (s->split_mode == JOURNAL_WRITE_SPLIT_HOST) { + w->hashmap_key = strdup(key); + if (!w->hashmap_key) + return log_oom(); + } + + r = open_output(s, w, host); + if (r < 0) + return r; + + r = hashmap_put(s->writers, w->hashmap_key ?: key, w); + if (r < 0) + return r; + } + + *writer = TAKE_PTR(w); + + return 0; +} + +/********************************************************************** + ********************************************************************** + **********************************************************************/ + +/* This should go away as soon as µhttpd allows state to be passed around. */ +RemoteServer *journal_remote_server_global; + +static int dispatch_raw_source_event(sd_event_source *event, + int fd, + uint32_t revents, + void *userdata); +static int dispatch_raw_source_until_block(sd_event_source *event, + void *userdata); +static int dispatch_blocking_source_event(sd_event_source *event, + void *userdata); +static int dispatch_raw_connection_event(sd_event_source *event, + int fd, + uint32_t revents, + void *userdata); + +static int get_source_for_fd(RemoteServer *s, + int fd, char *name, RemoteSource **source) { + Writer *writer; + int r; + + /* This takes ownership of name, but only on success. */ + + assert(fd >= 0); + assert(source); + + if (!GREEDY_REALLOC0(s->sources, s->sources_size, fd + 1)) + return log_oom(); + + r = journal_remote_get_writer(s, name, &writer); + if (r < 0) + return log_warning_errno(r, "Failed to get writer for source %s: %m", + name); + + if (!s->sources[fd]) { + s->sources[fd] = source_new(fd, false, name, writer); + if (!s->sources[fd]) { + writer_unref(writer); + return log_oom(); + } + + s->active++; + } + + *source = s->sources[fd]; + return 0; +} + +static int remove_source(RemoteServer *s, int fd) { + RemoteSource *source; + + assert(s); + assert(fd >= 0 && fd < (ssize_t) s->sources_size); + + source = s->sources[fd]; + if (source) { + /* this closes fd too */ + source_free(source); + s->sources[fd] = NULL; + s->active--; + } + + return 0; +} + +int journal_remote_add_source(RemoteServer *s, int fd, char* name, bool own_name) { + RemoteSource *source = NULL; + int r; + + /* This takes ownership of name, even on failure, if own_name is true. */ + + assert(s); + assert(fd >= 0); + assert(name); + + if (!own_name) { + name = strdup(name); + if (!name) + return log_oom(); + } + + r = get_source_for_fd(s, fd, name, &source); + if (r < 0) { + log_error_errno(r, "Failed to create source for fd:%d (%s): %m", + fd, name); + free(name); + return r; + } + + r = sd_event_add_io(s->events, &source->event, + fd, EPOLLIN|EPOLLRDHUP|EPOLLPRI, + dispatch_raw_source_event, source); + if (r == 0) { + /* Add additional source for buffer processing. It will be + * enabled later. */ + r = sd_event_add_defer(s->events, &source->buffer_event, + dispatch_raw_source_until_block, source); + if (r == 0) + sd_event_source_set_enabled(source->buffer_event, SD_EVENT_OFF); + } else if (r == -EPERM) { + log_debug("Falling back to sd_event_add_defer for fd:%d (%s)", fd, name); + r = sd_event_add_defer(s->events, &source->event, + dispatch_blocking_source_event, source); + if (r == 0) + sd_event_source_set_enabled(source->event, SD_EVENT_ON); + } + if (r < 0) { + log_error_errno(r, "Failed to register event source for fd:%d: %m", + fd); + goto error; + } + + r = sd_event_source_set_description(source->event, name); + if (r < 0) { + log_error_errno(r, "Failed to set source name for fd:%d: %m", fd); + goto error; + } + + return 1; /* work to do */ + + error: + remove_source(s, fd); + return r; +} + +int journal_remote_add_raw_socket(RemoteServer *s, int fd) { + int r; + _cleanup_close_ int fd_ = fd; + char name[STRLEN("raw-socket-") + DECIMAL_STR_MAX(int) + 1]; + + assert(fd >= 0); + + r = sd_event_add_io(s->events, &s->listen_event, + fd, EPOLLIN, + dispatch_raw_connection_event, s); + if (r < 0) + return r; + + xsprintf(name, "raw-socket-%d", fd); + + r = sd_event_source_set_description(s->listen_event, name); + if (r < 0) + return r; + + fd_ = -1; + s->active++; + return 0; +} + +/********************************************************************** + ********************************************************************** + **********************************************************************/ + +int journal_remote_server_init( + RemoteServer *s, + const char *output, + JournalWriteSplitMode split_mode, + bool compress, + bool seal) { + + int r; + + assert(s); + + assert(journal_remote_server_global == NULL); + journal_remote_server_global = s; + + s->split_mode = split_mode; + s->compress = compress; + s->seal = seal; + + if (output) + s->output = output; + else if (split_mode == JOURNAL_WRITE_SPLIT_NONE) + s->output = REMOTE_JOURNAL_PATH "/remote.journal"; + else if (split_mode == JOURNAL_WRITE_SPLIT_HOST) + s->output = REMOTE_JOURNAL_PATH; + else + assert_not_reached("bad split mode"); + + r = sd_event_default(&s->events); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + r = init_writer_hashmap(s); + if (r < 0) + return r; + + return 0; +} + +#if HAVE_MICROHTTPD +static void MHDDaemonWrapper_free(MHDDaemonWrapper *d) { + MHD_stop_daemon(d->daemon); + sd_event_source_unref(d->io_event); + sd_event_source_unref(d->timer_event); + free(d); +} +#endif + +void journal_remote_server_destroy(RemoteServer *s) { + size_t i; + +#if HAVE_MICROHTTPD + hashmap_free_with_destructor(s->daemons, MHDDaemonWrapper_free); +#endif + + assert(s->sources_size == 0 || s->sources); + for (i = 0; i < s->sources_size; i++) + remove_source(s, i); + free(s->sources); + + writer_unref(s->_single_writer); + hashmap_free(s->writers); + + sd_event_source_unref(s->sigterm_event); + sd_event_source_unref(s->sigint_event); + sd_event_source_unref(s->listen_event); + sd_event_unref(s->events); + + if (s == journal_remote_server_global) + journal_remote_server_global = NULL; + + /* fds that we're listening on remain open... */ +} + +/********************************************************************** + ********************************************************************** + **********************************************************************/ + +int journal_remote_handle_raw_source( + sd_event_source *event, + int fd, + uint32_t revents, + RemoteServer *s) { + + RemoteSource *source; + int r; + + /* Returns 1 if there might be more data pending, + * 0 if data is currently exhausted, negative on error. + */ + + assert(fd >= 0 && fd < (ssize_t) s->sources_size); + source = s->sources[fd]; + assert(source->importer.fd == fd); + + r = process_source(source, s->compress, s->seal); + if (journal_importer_eof(&source->importer)) { + size_t remaining; + + log_debug("EOF reached with source %s (fd=%d)", + source->importer.name, source->importer.fd); + + remaining = journal_importer_bytes_remaining(&source->importer); + if (remaining > 0) + log_notice("Premature EOF. %zu bytes lost.", remaining); + remove_source(s, source->importer.fd); + log_debug("%zu active sources remaining", s->active); + return 0; + } else if (r == -E2BIG) { + log_notice("Entry with too many fields, skipped"); + return 1; + } else if (r == -ENOBUFS) { + log_notice("Entry too big, skipped"); + return 1; + } else if (r == -EAGAIN) { + return 0; + } else if (r < 0) { + log_debug_errno(r, "Closing connection: %m"); + remove_source(s, fd); + return 0; + } else + return 1; +} + +static int dispatch_raw_source_until_block(sd_event_source *event, + void *userdata) { + RemoteSource *source = userdata; + int r; + + /* Make sure event stays around even if source is destroyed */ + sd_event_source_ref(event); + + r = journal_remote_handle_raw_source(event, source->importer.fd, EPOLLIN, journal_remote_server_global); + if (r != 1) + /* No more data for now */ + sd_event_source_set_enabled(event, SD_EVENT_OFF); + + sd_event_source_unref(event); + + return r; +} + +static int dispatch_raw_source_event(sd_event_source *event, + int fd, + uint32_t revents, + void *userdata) { + RemoteSource *source = userdata; + int r; + + assert(source->event); + assert(source->buffer_event); + + r = journal_remote_handle_raw_source(event, fd, EPOLLIN, journal_remote_server_global); + if (r == 1) + /* Might have more data. We need to rerun the handler + * until we are sure the buffer is exhausted. */ + sd_event_source_set_enabled(source->buffer_event, SD_EVENT_ON); + + return r; +} + +static int dispatch_blocking_source_event(sd_event_source *event, + void *userdata) { + RemoteSource *source = userdata; + + return journal_remote_handle_raw_source(event, source->importer.fd, EPOLLIN, journal_remote_server_global); +} + +static int accept_connection( + const char* type, + int fd, + SocketAddress *addr, + char **hostname) { + + _cleanup_close_ int fd2 = -1; + int r; + + log_debug("Accepting new %s connection on fd:%d", type, fd); + fd2 = accept4(fd, &addr->sockaddr.sa, &addr->size, SOCK_NONBLOCK|SOCK_CLOEXEC); + if (fd2 < 0) { + if (ERRNO_IS_ACCEPT_AGAIN(errno)) + return -EAGAIN; + + return log_error_errno(errno, "accept() on fd:%d failed: %m", fd); + } + + switch(socket_address_family(addr)) { + case AF_INET: + case AF_INET6: { + _cleanup_free_ char *a = NULL; + char *b; + + r = socket_address_print(addr, &a); + if (r < 0) + return log_error_errno(r, "socket_address_print(): %m"); + + r = socknameinfo_pretty(&addr->sockaddr, addr->size, &b); + if (r < 0) + return log_error_errno(r, "Resolving hostname failed: %m"); + + log_debug("Accepted %s %s connection from %s", + type, + socket_address_family(addr) == AF_INET ? "IP" : "IPv6", + a); + + *hostname = b; + return TAKE_FD(fd2); + } + + default: + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Rejected %s connection with unsupported family %d", + type, socket_address_family(addr)); + } +} + +static int dispatch_raw_connection_event( + sd_event_source *event, + int fd, + uint32_t revents, + void *userdata) { + + RemoteServer *s = userdata; + int fd2; + SocketAddress addr = { + .size = sizeof(union sockaddr_union), + .type = SOCK_STREAM, + }; + char *hostname = NULL; + + fd2 = accept_connection("raw", fd, &addr, &hostname); + if (fd2 == -EAGAIN) + return 0; + if (fd2 < 0) + return fd2; + + return journal_remote_add_source(s, fd2, hostname, true); +} diff --git a/src/journal-remote/journal-remote.conf.in b/src/journal-remote/journal-remote.conf.in new file mode 100644 index 00000000..edc3abab --- /dev/null +++ b/src/journal-remote/journal-remote.conf.in @@ -0,0 +1,19 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See journal-remote.conf(5) for details + +[Remote] +# Seal=false +# SplitMode=host +# ServerKeyFile=@CERTIFICATEROOT@/private/journal-remote.pem +# ServerCertificateFile=@CERTIFICATEROOT@/certs/journal-remote.pem +# TrustedCertificateFile=@CERTIFICATEROOT@/ca/trusted.pem diff --git a/src/journal-remote/journal-remote.h b/src/journal-remote/journal-remote.h new file mode 100644 index 00000000..4c25d43a --- /dev/null +++ b/src/journal-remote/journal-remote.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" + +#include "hashmap.h" +#include "journal-remote-parse.h" +#include "journal-remote-write.h" + +#if HAVE_MICROHTTPD +#include "microhttpd-util.h" + +typedef struct MHDDaemonWrapper MHDDaemonWrapper; + +struct MHDDaemonWrapper { + uint64_t fd; + struct MHD_Daemon *daemon; + + sd_event_source *io_event; + sd_event_source *timer_event; +}; +#endif + +struct RemoteServer { + RemoteSource **sources; + size_t sources_size; + size_t active; + + sd_event *events; + sd_event_source *sigterm_event, *sigint_event, *listen_event; + + Hashmap *writers; + Writer *_single_writer; + uint64_t event_count; + +#if HAVE_MICROHTTPD + Hashmap *daemons; +#endif + const char *output; /* either the output file or directory */ + + JournalWriteSplitMode split_mode; + bool compress; + bool seal; + bool check_trust; +}; +extern RemoteServer *journal_remote_server_global; + +int journal_remote_server_init( + RemoteServer *s, + const char *output, + JournalWriteSplitMode split_mode, + bool compress, + bool seal); + +int journal_remote_get_writer(RemoteServer *s, const char *host, Writer **writer); + +int journal_remote_add_source(RemoteServer *s, int fd, char* name, bool own_name); +int journal_remote_add_raw_socket(RemoteServer *s, int fd); +int journal_remote_handle_raw_source( + sd_event_source *event, + int fd, + uint32_t revents, + RemoteServer *s); + +void journal_remote_server_destroy(RemoteServer *s); diff --git a/src/journal-remote/journal-upload-journal.c b/src/journal-remote/journal-upload-journal.c new file mode 100644 index 00000000..7d7e7384 --- /dev/null +++ b/src/journal-remote/journal-upload-journal.c @@ -0,0 +1,414 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "journal-upload.h" +#include "log.h" +#include "string-util.h" +#include "utf8.h" +#include "util.h" + +/** + * Write up to size bytes to buf. Return negative on error, and number of + * bytes written otherwise. The last case is a kind of an error too. + */ +static ssize_t write_entry(char *buf, size_t size, Uploader *u) { + int r; + size_t pos = 0; + + assert(size <= SSIZE_MAX); + + for (;;) { + + switch(u->entry_state) { + case ENTRY_CURSOR: { + u->current_cursor = mfree(u->current_cursor); + + r = sd_journal_get_cursor(u->journal, &u->current_cursor); + if (r < 0) + return log_error_errno(r, "Failed to get cursor: %m"); + + r = snprintf(buf + pos, size - pos, + "__CURSOR=%s\n", u->current_cursor); + assert(r >= 0); + if ((size_t) r > size - pos) + /* not enough space */ + return pos; + + u->entry_state++; + + if (pos + r == size) { + /* exactly one character short, but we don't need it */ + buf[size - 1] = '\n'; + return size; + } + + pos += r; + } + _fallthrough_; + case ENTRY_REALTIME: { + usec_t realtime; + + r = sd_journal_get_realtime_usec(u->journal, &realtime); + if (r < 0) + return log_error_errno(r, "Failed to get realtime timestamp: %m"); + + r = snprintf(buf + pos, size - pos, + "__REALTIME_TIMESTAMP="USEC_FMT"\n", realtime); + assert(r >= 0); + if ((size_t) r > size - pos) + /* not enough space */ + return pos; + + u->entry_state++; + + if (r + pos == size) { + /* exactly one character short, but we don't need it */ + buf[size - 1] = '\n'; + return size; + } + + pos += r; + } + _fallthrough_; + case ENTRY_MONOTONIC: { + usec_t monotonic; + sd_id128_t boot_id; + + r = sd_journal_get_monotonic_usec(u->journal, &monotonic, &boot_id); + if (r < 0) + return log_error_errno(r, "Failed to get monotonic timestamp: %m"); + + r = snprintf(buf + pos, size - pos, + "__MONOTONIC_TIMESTAMP="USEC_FMT"\n", monotonic); + assert(r >= 0); + if ((size_t) r > size - pos) + /* not enough space */ + return pos; + + u->entry_state++; + + if (r + pos == size) { + /* exactly one character short, but we don't need it */ + buf[size - 1] = '\n'; + return size; + } + + pos += r; + } + _fallthrough_; + case ENTRY_BOOT_ID: { + sd_id128_t boot_id; + char sid[33]; + + r = sd_journal_get_monotonic_usec(u->journal, NULL, &boot_id); + if (r < 0) + return log_error_errno(r, "Failed to get monotonic timestamp: %m"); + + r = snprintf(buf + pos, size - pos, + "_BOOT_ID=%s\n", sd_id128_to_string(boot_id, sid)); + assert(r >= 0); + if ((size_t) r > size - pos) + /* not enough space */ + return pos; + + u->entry_state++; + + if (r + pos == size) { + /* exactly one character short, but we don't need it */ + buf[size - 1] = '\n'; + return size; + } + + pos += r; + } + _fallthrough_; + case ENTRY_NEW_FIELD: { + u->field_pos = 0; + + r = sd_journal_enumerate_data(u->journal, + &u->field_data, + &u->field_length); + if (r < 0) + return log_error_errno(r, "Failed to move to next field in entry: %m"); + else if (r == 0) { + u->entry_state = ENTRY_OUTRO; + continue; + } + + /* We already printed the boot id from the data in + * the header, hence let's suppress it here */ + if (memory_startswith(u->field_data, u->field_length, "_BOOT_ID=")) + continue; + + if (!utf8_is_printable_newline(u->field_data, u->field_length, false)) { + u->entry_state = ENTRY_BINARY_FIELD_START; + continue; + } + + u->entry_state++; + } + _fallthrough_; + case ENTRY_TEXT_FIELD: + case ENTRY_BINARY_FIELD: { + bool done; + size_t tocopy; + + done = size - pos > u->field_length - u->field_pos; + if (done) + tocopy = u->field_length - u->field_pos; + else + tocopy = size - pos; + + memcpy(buf + pos, + (char*) u->field_data + u->field_pos, + tocopy); + + if (done) { + buf[pos + tocopy] = '\n'; + pos += tocopy + 1; + u->entry_state = ENTRY_NEW_FIELD; + continue; + } else { + u->field_pos += tocopy; + return size; + } + } + + case ENTRY_BINARY_FIELD_START: { + const char *c; + size_t len; + + c = memchr(u->field_data, '=', u->field_length); + if (!c || c == u->field_data) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid field."); + + len = c - (const char*)u->field_data; + + /* need space for label + '\n' */ + if (size - pos < len + 1) + return pos; + + memcpy(buf + pos, u->field_data, len); + buf[pos + len] = '\n'; + pos += len + 1; + + u->field_pos = len + 1; + u->entry_state++; + } + _fallthrough_; + case ENTRY_BINARY_FIELD_SIZE: { + uint64_t le64; + + /* need space for uint64_t */ + if (size - pos < 8) + return pos; + + le64 = htole64(u->field_length - u->field_pos); + memcpy(buf + pos, &le64, 8); + pos += 8; + + u->entry_state++; + continue; + } + + case ENTRY_OUTRO: + /* need space for '\n' */ + if (size - pos < 1) + return pos; + + buf[pos++] = '\n'; + u->entry_state++; + u->entries_sent++; + + return pos; + + default: + assert_not_reached("WTF?"); + } + } + assert_not_reached("WTF?"); +} + +static void check_update_watchdog(Uploader *u) { + usec_t after; + usec_t elapsed_time; + + if (u->watchdog_usec <= 0) + return; + + after = now(CLOCK_MONOTONIC); + elapsed_time = usec_sub_unsigned(after, u->watchdog_timestamp); + if (elapsed_time > u->watchdog_usec / 2) { + log_debug("Update watchdog timer"); + sd_notify(false, "WATCHDOG=1"); + u->watchdog_timestamp = after; + } +} + +static size_t journal_input_callback(void *buf, size_t size, size_t nmemb, void *userp) { + Uploader *u = userp; + int r; + sd_journal *j; + size_t filled = 0; + ssize_t w; + + assert(u); + assert(nmemb <= SSIZE_MAX / size); + + check_update_watchdog(u); + + j = u->journal; + + while (j && filled < size * nmemb) { + if (u->entry_state == ENTRY_DONE) { + r = sd_journal_next(j); + if (r < 0) { + log_error_errno(r, "Failed to move to next entry in journal: %m"); + return CURL_READFUNC_ABORT; + } else if (r == 0) { + if (u->input_event) + log_debug("No more entries, waiting for journal."); + else { + log_info("No more entries, closing journal."); + close_journal_input(u); + } + + u->uploading = false; + + break; + } + + u->entry_state = ENTRY_CURSOR; + } + + w = write_entry((char*)buf + filled, size * nmemb - filled, u); + if (w < 0) + return CURL_READFUNC_ABORT; + filled += w; + + if (filled == 0) { + log_error("Buffer space is too small to write entry."); + return CURL_READFUNC_ABORT; + } else if (u->entry_state != ENTRY_DONE) + /* This means that all available space was used up */ + break; + + log_debug("Entry %zu (%s) has been uploaded.", + u->entries_sent, u->current_cursor); + } + + return filled; +} + +void close_journal_input(Uploader *u) { + assert(u); + + if (u->journal) { + log_debug("Closing journal input."); + + sd_journal_close(u->journal); + u->journal = NULL; + } + u->timeout = 0; +} + +static int process_journal_input(Uploader *u, int skip) { + int r; + + if (u->uploading) + return 0; + + r = sd_journal_next_skip(u->journal, skip); + if (r < 0) + return log_error_errno(r, "Failed to skip to next entry: %m"); + else if (r < skip) + return 0; + + /* have data */ + u->entry_state = ENTRY_CURSOR; + return start_upload(u, journal_input_callback, u); +} + +int check_journal_input(Uploader *u) { + if (u->input_event) { + int r; + + r = sd_journal_process(u->journal); + if (r < 0) { + log_error_errno(r, "Failed to process journal: %m"); + close_journal_input(u); + return r; + } + + if (r == SD_JOURNAL_NOP) + return 0; + } + + return process_journal_input(u, 1); +} + +static int dispatch_journal_input(sd_event_source *event, + int fd, + uint32_t revents, + void *userp) { + Uploader *u = userp; + + assert(u); + + if (u->uploading) + return 0; + + log_debug("Detected journal input, checking for new data."); + return check_journal_input(u); +} + +int open_journal_for_upload(Uploader *u, + sd_journal *j, + const char *cursor, + bool after_cursor, + bool follow) { + int fd, r, events; + + u->journal = j; + + sd_journal_set_data_threshold(j, 0); + + if (follow) { + fd = sd_journal_get_fd(j); + if (fd < 0) + return log_error_errno(fd, "sd_journal_get_fd failed: %m"); + + events = sd_journal_get_events(j); + + r = sd_journal_reliable_fd(j); + assert(r >= 0); + if (r > 0) + u->timeout = -1; + else + u->timeout = JOURNAL_UPLOAD_POLL_TIMEOUT; + + r = sd_event_add_io(u->events, &u->input_event, + fd, events, dispatch_journal_input, u); + if (r < 0) + return log_error_errno(r, "Failed to register input event: %m"); + + log_debug("Listening for journal events on fd:%d, timeout %d", + fd, u->timeout == (uint64_t) -1 ? -1 : (int) u->timeout); + } else + log_debug("Not listening for journal events."); + + if (cursor) { + r = sd_journal_seek_cursor(j, cursor); + if (r < 0) + return log_error_errno(r, "Failed to seek to cursor %s: %m", + cursor); + } + + return process_journal_input(u, 1 + !!after_cursor); +} diff --git a/src/journal-remote/journal-upload.c b/src/journal-remote/journal-upload.c new file mode 100644 index 00000000..cc968252 --- /dev/null +++ b/src/journal-remote/journal-upload.c @@ -0,0 +1,854 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "build.h" +#include "conf-parser.h" +#include "daemon-util.h" +#include "def.h" +#include "env-file.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "glob-util.h" +#include "journal-upload.h" +#include "log.h" +#include "main-func.h" +#include "mkdir.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "sigbus.h" +#include "signal-util.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "util.h" + +#define PRIV_KEY_FILE CERTIFICATE_ROOT "/private/journal-upload.pem" +#define CERT_FILE CERTIFICATE_ROOT "/certs/journal-upload.pem" +#define TRUST_FILE CERTIFICATE_ROOT "/ca/trusted.pem" +#define DEFAULT_PORT 19532 + +static const char* arg_url = NULL; +static const char *arg_key = NULL; +static const char *arg_cert = NULL; +static const char *arg_trust = NULL; +static const char *arg_directory = NULL; +static char **arg_file = NULL; +static const char *arg_cursor = NULL; +static bool arg_after_cursor = false; +static int arg_journal_type = 0; +static const char *arg_machine = NULL; +static bool arg_merge = false; +static int arg_follow = -1; +static const char *arg_save_state = NULL; + +static void close_fd_input(Uploader *u); + +#define SERVER_ANSWER_KEEP 2048 + +#define STATE_FILE "/var/lib/systemd/journal-upload/state" + +#define easy_setopt(curl, opt, value, level, cmd) \ + do { \ + code = curl_easy_setopt(curl, opt, value); \ + if (code) { \ + log_full(level, \ + "curl_easy_setopt " #opt " failed: %s", \ + curl_easy_strerror(code)); \ + cmd; \ + } \ + } while (0) + +static size_t output_callback(char *buf, + size_t size, + size_t nmemb, + void *userp) { + Uploader *u = userp; + + assert(u); + + log_debug("The server answers (%zu bytes): %.*s", + size*nmemb, (int)(size*nmemb), buf); + + if (nmemb && !u->answer) { + u->answer = strndup(buf, size*nmemb); + if (!u->answer) + log_warning("Failed to store server answer (%zu bytes): out of memory", size*nmemb); + } + + return size * nmemb; +} + +static int check_cursor_updating(Uploader *u) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + if (!u->state_file) + return 0; + + r = mkdir_parents(u->state_file, 0755); + if (r < 0) + return log_error_errno(r, "Cannot create parent directory of state file %s: %m", + u->state_file); + + r = fopen_temporary(u->state_file, &f, &temp_path); + if (r < 0) + return log_error_errno(r, "Cannot save state to %s: %m", + u->state_file); + (void) unlink(temp_path); + + return 0; +} + +static int update_cursor_state(Uploader *u) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + if (!u->state_file || !u->last_cursor) + return 0; + + r = fopen_temporary(u->state_file, &f, &temp_path); + if (r < 0) + goto fail; + + fprintf(f, + "# This is private data. Do not parse.\n" + "LAST_CURSOR=%s\n", + u->last_cursor); + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, u->state_file) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + if (temp_path) + (void) unlink(temp_path); + + (void) unlink(u->state_file); + + return log_error_errno(r, "Failed to save state %s: %m", u->state_file); +} + +static int load_cursor_state(Uploader *u) { + int r; + + if (!u->state_file) + return 0; + + r = parse_env_file(NULL, u->state_file, "LAST_CURSOR", &u->last_cursor); + if (r == -ENOENT) + log_debug("State file %s is not present.", u->state_file); + else if (r < 0) + return log_error_errno(r, "Failed to read state file %s: %m", + u->state_file); + else + log_debug("Last cursor was %s", u->last_cursor); + + return 0; +} + +int start_upload(Uploader *u, + size_t (*input_callback)(void *ptr, + size_t size, + size_t nmemb, + void *userdata), + void *data) { + CURLcode code; + + assert(u); + assert(input_callback); + + if (!u->header) { + struct curl_slist *h; + + h = curl_slist_append(NULL, "Content-Type: application/vnd.fdo.journal"); + if (!h) + return log_oom(); + + h = curl_slist_append(h, "Transfer-Encoding: chunked"); + if (!h) { + curl_slist_free_all(h); + return log_oom(); + } + + h = curl_slist_append(h, "Accept: text/plain"); + if (!h) { + curl_slist_free_all(h); + return log_oom(); + } + + u->header = h; + } + + if (!u->easy) { + CURL *curl; + + curl = curl_easy_init(); + if (!curl) + return log_error_errno(SYNTHETIC_ERRNO(ENOSR), + "Call to curl_easy_init failed."); + + /* tell it to POST to the URL */ + easy_setopt(curl, CURLOPT_POST, 1L, + LOG_ERR, return -EXFULL); + + easy_setopt(curl, CURLOPT_ERRORBUFFER, u->error, + LOG_ERR, return -EXFULL); + + /* set where to write to */ + easy_setopt(curl, CURLOPT_WRITEFUNCTION, output_callback, + LOG_ERR, return -EXFULL); + + easy_setopt(curl, CURLOPT_WRITEDATA, data, + LOG_ERR, return -EXFULL); + + /* set where to read from */ + easy_setopt(curl, CURLOPT_READFUNCTION, input_callback, + LOG_ERR, return -EXFULL); + + easy_setopt(curl, CURLOPT_READDATA, data, + LOG_ERR, return -EXFULL); + + /* use our special own mime type and chunked transfer */ + easy_setopt(curl, CURLOPT_HTTPHEADER, u->header, + LOG_ERR, return -EXFULL); + + if (DEBUG_LOGGING) + /* enable verbose for easier tracing */ + easy_setopt(curl, CURLOPT_VERBOSE, 1L, LOG_WARNING, ); + + easy_setopt(curl, CURLOPT_USERAGENT, + "systemd-journal-upload " GIT_VERSION, + LOG_WARNING, ); + + if (arg_key || startswith(u->url, "https://")) { + easy_setopt(curl, CURLOPT_SSLKEY, arg_key ?: PRIV_KEY_FILE, + LOG_ERR, return -EXFULL); + easy_setopt(curl, CURLOPT_SSLCERT, arg_cert ?: CERT_FILE, + LOG_ERR, return -EXFULL); + } + + if (streq_ptr(arg_trust, "all")) + easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0, + LOG_ERR, return -EUCLEAN); + else if (arg_trust || startswith(u->url, "https://")) + easy_setopt(curl, CURLOPT_CAINFO, arg_trust ?: TRUST_FILE, + LOG_ERR, return -EXFULL); + + if (arg_key || arg_trust) + easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1, + LOG_WARNING, ); + + u->easy = curl; + } else { + /* truncate the potential old error message */ + u->error[0] = '\0'; + + free(u->answer); + u->answer = 0; + } + + /* upload to this place */ + code = curl_easy_setopt(u->easy, CURLOPT_URL, u->url); + if (code) + return log_error_errno(SYNTHETIC_ERRNO(EXFULL), + "curl_easy_setopt CURLOPT_URL failed: %s", + curl_easy_strerror(code)); + + u->uploading = true; + + return 0; +} + +static size_t fd_input_callback(void *buf, size_t size, size_t nmemb, void *userp) { + Uploader *u = userp; + ssize_t n; + + assert(u); + assert(nmemb < SSIZE_MAX / size); + + if (u->input < 0) + return 0; + + assert(!size_multiply_overflow(size, nmemb)); + + n = read(u->input, buf, size * nmemb); + log_debug("%s: allowed %zu, read %zd", __func__, size*nmemb, n); + if (n > 0) + return n; + + u->uploading = false; + if (n < 0) { + log_error_errno(errno, "Aborting transfer after read error on input: %m."); + return CURL_READFUNC_ABORT; + } + + log_debug("Reached EOF"); + close_fd_input(u); + return 0; +} + +static void close_fd_input(Uploader *u) { + assert(u); + + u->input = safe_close(u->input); + u->timeout = 0; +} + +static int dispatch_fd_input(sd_event_source *event, + int fd, + uint32_t revents, + void *userp) { + Uploader *u = userp; + + assert(u); + assert(fd >= 0); + + if (revents & EPOLLHUP) { + log_debug("Received HUP"); + close_fd_input(u); + return 0; + } + + if (!(revents & EPOLLIN)) { + log_warning("Unexpected poll event %"PRIu32".", revents); + return -EINVAL; + } + + if (u->uploading) { + log_warning("dispatch_fd_input called when uploading, ignoring."); + return 0; + } + + return start_upload(u, fd_input_callback, u); +} + +static int open_file_for_upload(Uploader *u, const char *filename) { + int fd, r = 0; + + if (streq(filename, "-")) + fd = STDIN_FILENO; + else { + fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return log_error_errno(errno, "Failed to open %s: %m", filename); + } + + u->input = fd; + + if (arg_follow) { + r = sd_event_add_io(u->events, &u->input_event, + fd, EPOLLIN, dispatch_fd_input, u); + if (r < 0) { + if (r != -EPERM || arg_follow > 0) + return log_error_errno(r, "Failed to register input event: %m"); + + /* Normal files should just be consumed without polling. */ + r = start_upload(u, fd_input_callback, u); + } + } + + return r; +} + +static int dispatch_sigterm(sd_event_source *event, + const struct signalfd_siginfo *si, + void *userdata) { + Uploader *u = userdata; + + assert(u); + + log_received_signal(LOG_INFO, si); + + close_fd_input(u); + close_journal_input(u); + + sd_event_exit(u->events, 0); + return 0; +} + +static int setup_signals(Uploader *u) { + int r; + + assert(u); + + assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, -1) >= 0); + + r = sd_event_add_signal(u->events, &u->sigterm_event, SIGTERM, dispatch_sigterm, u); + if (r < 0) + return r; + + r = sd_event_add_signal(u->events, &u->sigint_event, SIGINT, dispatch_sigterm, u); + if (r < 0) + return r; + + return 0; +} + +static int setup_uploader(Uploader *u, const char *url, const char *state_file) { + int r; + const char *host, *proto = ""; + + assert(u); + assert(url); + + *u = (Uploader) { + .input = -1 + }; + + host = STARTSWITH_SET(url, "http://", "https://"); + if (!host) { + host = url; + proto = "https://"; + } + + if (strchr(host, ':')) + u->url = strjoin(proto, url, "/upload"); + else { + char *t; + size_t x; + + t = strdupa(url); + x = strlen(t); + while (x > 0 && t[x - 1] == '/') + t[x - 1] = '\0'; + + u->url = strjoin(proto, t, ":" STRINGIFY(DEFAULT_PORT), "/upload"); + } + if (!u->url) + return log_oom(); + + u->state_file = state_file; + + r = sd_event_default(&u->events); + if (r < 0) + return log_error_errno(r, "sd_event_default failed: %m"); + + r = setup_signals(u); + if (r < 0) + return log_error_errno(r, "Failed to set up signals: %m"); + + (void) sd_watchdog_enabled(false, &u->watchdog_usec); + + return load_cursor_state(u); +} + +static void destroy_uploader(Uploader *u) { + assert(u); + + curl_easy_cleanup(u->easy); + curl_slist_free_all(u->header); + free(u->answer); + + free(u->last_cursor); + free(u->current_cursor); + + free(u->url); + + u->input_event = sd_event_source_unref(u->input_event); + + close_fd_input(u); + close_journal_input(u); + + sd_event_source_unref(u->sigterm_event); + sd_event_source_unref(u->sigint_event); + sd_event_unref(u->events); +} + +static int perform_upload(Uploader *u) { + CURLcode code; + long status; + + assert(u); + + u->watchdog_timestamp = now(CLOCK_MONOTONIC); + code = curl_easy_perform(u->easy); + if (code) { + if (u->error[0]) + log_error("Upload to %s failed: %.*s", + u->url, (int) sizeof(u->error), u->error); + else + log_error("Upload to %s failed: %s", + u->url, curl_easy_strerror(code)); + return -EIO; + } + + code = curl_easy_getinfo(u->easy, CURLINFO_RESPONSE_CODE, &status); + if (code) + return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), + "Failed to retrieve response code: %s", + curl_easy_strerror(code)); + + if (status >= 300) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Upload to %s failed with code %ld: %s", + u->url, status, strna(u->answer)); + else if (status < 200) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Upload to %s finished with unexpected code %ld: %s", + u->url, status, strna(u->answer)); + else + log_debug("Upload finished successfully with code %ld: %s", + status, strna(u->answer)); + + free_and_replace(u->last_cursor, u->current_cursor); + + return update_cursor_state(u); +} + +static int parse_config(void) { + const ConfigTableItem items[] = { + { "Upload", "URL", config_parse_string, 0, &arg_url }, + { "Upload", "ServerKeyFile", config_parse_path, 0, &arg_key }, + { "Upload", "ServerCertificateFile", config_parse_path, 0, &arg_cert }, + { "Upload", "TrustedCertificateFile", config_parse_path, 0, &arg_trust }, + {}}; + + return config_parse_many_nulstr(PKGSYSCONFDIR "/journal-upload.conf", + CONF_PATHS_NULSTR("systemd/journal-upload.conf.d"), + "Upload\0", config_item_table_lookup, items, + CONFIG_PARSE_WARN, NULL); +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-journal-upload.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s -u URL {FILE|-}...\n\n" + "Upload journal events to a remote server.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -u --url=URL Upload to this address (default port " + STRINGIFY(DEFAULT_PORT) ")\n" + " --key=FILENAME Specify key in PEM format (default:\n" + " \"" PRIV_KEY_FILE "\")\n" + " --cert=FILENAME Specify certificate in PEM format (default:\n" + " \"" CERT_FILE "\")\n" + " --trust=FILENAME|all Specify CA certificate or disable checking (default:\n" + " \"" TRUST_FILE "\")\n" + " --system Use the system journal\n" + " --user Use the user journal for the current user\n" + " -m --merge Use all available journals\n" + " -M --machine=CONTAINER Operate on local container\n" + " -D --directory=PATH Use journal files from directory\n" + " --file=PATH Use this journal file\n" + " --cursor=CURSOR Start at the specified cursor\n" + " --after-cursor=CURSOR Start after the specified cursor\n" + " --follow[=BOOL] Do [not] wait for input\n" + " --save-state[=FILE] Save uploaded cursors (default \n" + " " STATE_FILE ")\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_KEY, + ARG_CERT, + ARG_TRUST, + ARG_USER, + ARG_SYSTEM, + ARG_FILE, + ARG_CURSOR, + ARG_AFTER_CURSOR, + ARG_FOLLOW, + ARG_SAVE_STATE, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "url", required_argument, NULL, 'u' }, + { "key", required_argument, NULL, ARG_KEY }, + { "cert", required_argument, NULL, ARG_CERT }, + { "trust", required_argument, NULL, ARG_TRUST }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "user", no_argument, NULL, ARG_USER }, + { "merge", no_argument, NULL, 'm' }, + { "machine", required_argument, NULL, 'M' }, + { "directory", required_argument, NULL, 'D' }, + { "file", required_argument, NULL, ARG_FILE }, + { "cursor", required_argument, NULL, ARG_CURSOR }, + { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR }, + { "follow", optional_argument, NULL, ARG_FOLLOW }, + { "save-state", optional_argument, NULL, ARG_SAVE_STATE }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + opterr = 0; + + while ((c = getopt_long(argc, argv, "hu:mM:D:", options, NULL)) >= 0) + switch(c) { + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case 'u': + if (arg_url) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --url"); + + arg_url = optarg; + break; + + case ARG_KEY: + if (arg_key) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --key"); + + arg_key = optarg; + break; + + case ARG_CERT: + if (arg_cert) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --cert"); + + arg_cert = optarg; + break; + + case ARG_TRUST: + if (arg_trust) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --trust"); + + arg_trust = optarg; + break; + + case ARG_SYSTEM: + arg_journal_type |= SD_JOURNAL_SYSTEM; + break; + + case ARG_USER: + arg_journal_type |= SD_JOURNAL_CURRENT_USER; + break; + + case 'm': + arg_merge = true; + break; + + case 'M': + if (arg_machine) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --machine/-M"); + + arg_machine = optarg; + break; + + case 'D': + if (arg_directory) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --directory/-D"); + + arg_directory = optarg; + break; + + case ARG_FILE: + r = glob_extend(&arg_file, optarg); + if (r < 0) + return log_error_errno(r, "Failed to add paths: %m"); + break; + + case ARG_CURSOR: + if (arg_cursor) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --cursor/--after-cursor"); + + arg_cursor = optarg; + break; + + case ARG_AFTER_CURSOR: + if (arg_cursor) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "cannot use more than one --cursor/--after-cursor"); + + arg_cursor = optarg; + arg_after_cursor = true; + break; + + case ARG_FOLLOW: + if (optarg) { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse --follow= parameter."); + + arg_follow = !!r; + } else + arg_follow = true; + + break; + + case ARG_SAVE_STATE: + arg_save_state = optarg ?: STATE_FILE; + break; + + case '?': + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown option %s.", + argv[optind - 1]); + + case ':': + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Missing argument to %s.", + argv[optind - 1]); + + default: + assert_not_reached("Unhandled option code."); + } + + if (!arg_url) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Required --url/-u option missing."); + + if (!!arg_key != !!arg_cert) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Options --key and --cert must be used together."); + + if (optind < argc && (arg_directory || arg_file || arg_machine || arg_journal_type)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Input arguments make no sense with journal input."); + + return 1; +} + +static int open_journal(sd_journal **j) { + int r; + + if (arg_directory) + r = sd_journal_open_directory(j, arg_directory, arg_journal_type); + else if (arg_file) + r = sd_journal_open_files(j, (const char**) arg_file, 0); + else if (arg_machine) + r = sd_journal_open_container(j, arg_machine, 0); + else + r = sd_journal_open(j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type); + if (r < 0) + log_error_errno(r, "Failed to open %s: %m", + arg_directory ? arg_directory : arg_file ? "files" : "journal"); + return r; +} + +static int run(int argc, char **argv) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; + _cleanup_(destroy_uploader) Uploader u = {}; + bool use_journal; + int r; + + log_show_color(true); + log_parse_environment(); + + /* The journal merging logic potentially needs a lot of fds. */ + (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); + + r = parse_config(); + if (r < 0) + return r; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + sigbus_install(); + + r = setup_uploader(&u, arg_url, arg_save_state); + if (r < 0) + return r; + + sd_event_set_watchdog(u.events, true); + + r = check_cursor_updating(&u); + if (r < 0) + return r; + + log_debug("%s running as pid "PID_FMT, + program_invocation_short_name, getpid_cached()); + + use_journal = optind >= argc; + if (use_journal) { + sd_journal *j; + r = open_journal(&j); + if (r < 0) + return r; + r = open_journal_for_upload(&u, j, + arg_cursor ?: u.last_cursor, + arg_cursor ? arg_after_cursor : true, + !!arg_follow); + if (r < 0) + return r; + } + + notify_message = notify_start("READY=1\n" + "STATUS=Processing input...", + NOTIFY_STOPPING); + + for (;;) { + r = sd_event_get_state(u.events); + if (r < 0) + return r; + if (r == SD_EVENT_FINISHED) + return 0; + + if (use_journal) { + if (!u.journal) + return 0; + + r = check_journal_input(&u); + } else if (u.input < 0 && !use_journal) { + if (optind >= argc) + return 0; + + log_debug("Using %s as input.", argv[optind]); + r = open_file_for_upload(&u, argv[optind++]); + } + if (r < 0) + return r; + + if (u.uploading) { + r = perform_upload(&u); + if (r < 0) + return r; + } + + r = sd_event_run(u.events, u.timeout); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + } +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/journal-remote/journal-upload.conf.in b/src/journal-remote/journal-upload.conf.in new file mode 100644 index 00000000..5f59a6fe --- /dev/null +++ b/src/journal-remote/journal-upload.conf.in @@ -0,0 +1,18 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See journal-upload.conf(5) for details + +[Upload] +# URL= +# ServerKeyFile=@CERTIFICATEROOT@/private/journal-upload.pem +# ServerCertificateFile=@CERTIFICATEROOT@/certs/journal-upload.pem +# TrustedCertificateFile=@CERTIFICATEROOT@/ca/trusted.pem diff --git a/src/journal-remote/journal-upload.h b/src/journal-remote/journal-upload.h new file mode 100644 index 00000000..5711905f --- /dev/null +++ b/src/journal-remote/journal-upload.h @@ -0,0 +1,71 @@ +#pragma once + +#include + +#include "sd-event.h" +#include "sd-journal.h" +#include "time-util.h" + +typedef enum { + ENTRY_CURSOR = 0, /* Nothing actually written yet. */ + ENTRY_REALTIME, + ENTRY_MONOTONIC, + ENTRY_BOOT_ID, + ENTRY_NEW_FIELD, /* In between fields. */ + ENTRY_TEXT_FIELD, /* In the middle of a text field. */ + ENTRY_BINARY_FIELD_START, /* Writing the name of a binary field. */ + ENTRY_BINARY_FIELD_SIZE, /* Writing the size of a binary field. */ + ENTRY_BINARY_FIELD, /* In the middle of a binary field. */ + ENTRY_OUTRO, /* Writing '\n' */ + ENTRY_DONE, /* Need to move to a new field. */ +} entry_state; + +typedef struct Uploader { + sd_event *events; + sd_event_source *sigint_event, *sigterm_event; + + char *url; + CURL *easy; + bool uploading; + char error[CURL_ERROR_SIZE]; + struct curl_slist *header; + char *answer; + + sd_event_source *input_event; + uint64_t timeout; + + /* fd stuff */ + int input; + + /* journal stuff */ + sd_journal* journal; + + entry_state entry_state; + const void *field_data; + size_t field_pos, field_length; + + /* general metrics */ + const char *state_file; + + size_t entries_sent; + char *last_cursor, *current_cursor; + usec_t watchdog_timestamp; + usec_t watchdog_usec; +} Uploader; + +#define JOURNAL_UPLOAD_POLL_TIMEOUT (10 * USEC_PER_SEC) + +int start_upload(Uploader *u, + size_t (*input_callback)(void *ptr, + size_t size, + size_t nmemb, + void *userdata), + void *data); + +int open_journal_for_upload(Uploader *u, + sd_journal *j, + const char *cursor, + bool after_cursor, + bool follow); +void close_journal_input(Uploader *u); +int check_journal_input(Uploader *u); diff --git a/src/journal-remote/log-generator.py b/src/journal-remote/log-generator.py new file mode 100755 index 00000000..e1725b1a --- /dev/null +++ b/src/journal-remote/log-generator.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +import sys +import argparse + +PARSER = argparse.ArgumentParser() +PARSER.add_argument('n', type=int) +PARSER.add_argument('--dots', action='store_true') +PARSER.add_argument('-m', '--message-size', type=int, default=200) +PARSER.add_argument('-d', '--data-size', type=int, default=4000) +PARSER.add_argument('--data-type', choices={'random', 'simple'}) +OPTIONS = PARSER.parse_args() + +template = """\ +__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m={m:x};t=4fd05c +__REALTIME_TIMESTAMP={realtime_ts} +__MONOTONIC_TIMESTAMP={monotonic_ts} +_BOOT_ID=f446871715504074bf7049ef0718fa93 +_TRANSPORT=syslog +PRIORITY={priority} +SYSLOG_FACILITY={facility} +SYSLOG_IDENTIFIER=/USR/SBIN/CRON +MESSAGE={message} +_UID=0 +_GID=0 +_MACHINE_ID=69121ca41d12c1b69a7960174c27b618 +_HOSTNAME=hostname +SYSLOG_PID=25721 +_PID=25721 +_SOURCE_REALTIME_TIMESTAMP={source_realtime_ts} +DATA={data} +""" + +m = 0x198603b12d7 +realtime_ts = 1404101101501873 +monotonic_ts = 1753961140951 +source_realtime_ts = 1404101101483516 +priority = 3 +facility = 6 + +src = open('/dev/urandom', 'rb') + +bytes = 0 +counter = 0 + +for i in range(OPTIONS.n): + message = src.read(OPTIONS.message_size) + message = repr(message)[2:-1] + + if OPTIONS.data_type == 'random': + data = repr(src.read(OPTIONS.data_size)) + else: + # keep the pattern non-repeating so we get a different blob every time + data = '{:0{}}'.format(counter, OPTIONS.data_size) + counter += 1 + + entry = template.format(m=m, + realtime_ts=realtime_ts, + monotonic_ts=monotonic_ts, + source_realtime_ts=source_realtime_ts, + priority=priority, + facility=facility, + message=message, + data=data) + m += 1 + realtime_ts += 1 + monotonic_ts += 1 + source_realtime_ts += 1 + + bytes += len(entry) + + print(entry) + + if OPTIONS.dots: + print('.', file=sys.stderr, end='', flush=True) + +if OPTIONS.dots: + print(file=sys.stderr) +print('Wrote {} bytes'.format(bytes), file=sys.stderr) diff --git a/src/journal-remote/meson.build b/src/journal-remote/meson.build new file mode 100644 index 00000000..87b8ba64 --- /dev/null +++ b/src/journal-remote/meson.build @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +systemd_journal_upload_sources = files(''' + journal-upload.h + journal-upload.c + journal-upload-journal.c +'''.split()) + +libsystemd_journal_remote_sources = files(''' + journal-remote-parse.h + journal-remote-parse.c + journal-remote-write.h + journal-remote-write.c + journal-remote.h + journal-remote.c +'''.split()) + +if conf.get('HAVE_MICROHTTPD') == 1 + libsystemd_journal_remote_sources += files(''' + microhttpd-util.h + microhttpd-util.c +'''.split()) +endif + +libsystemd_journal_remote = static_library( + 'systemd-journal-remote', + libsystemd_journal_remote_sources, + include_directories : includes, + dependencies : [threads, + libmicrohttpd, + libgnutls, + libxz, + liblz4], + install : false) + +systemd_journal_remote_sources = files(''' + journal-remote-main.c +'''.split()) + +systemd_journal_gatewayd_sources = files(''' + journal-gatewayd.c + microhttpd-util.h + microhttpd-util.c +'''.split()) + +if conf.get('ENABLE_REMOTE') ==1 and conf.get('HAVE_LIBCURL') == 1 + journal_upload_conf = configure_file( + input : 'journal-upload.conf.in', + output : 'journal-upload.conf', + configuration : substs) + install_data(journal_upload_conf, + install_dir : pkgsysconfdir) +endif + +if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1 + journal_remote_conf = configure_file( + input : 'journal-remote.conf.in', + output : 'journal-remote.conf', + configuration : substs) + install_data(journal_remote_conf, + install_dir : pkgsysconfdir) + + install_data('browse.html', + install_dir : join_paths(pkgdatadir, 'gatewayd')) + + if get_option('create-log-dirs') + meson.add_install_script('sh', '-c', + mkdir_p.format('/var/log/journal/remote')) + meson.add_install_script('sh', '-c', + '''chown 0:0 $DESTDIR/var/log/journal/remote && + chmod 755 $DESTDIR/var/log/journal/remote || :''') + endif +endif diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c new file mode 100644 index 00000000..939af125 --- /dev/null +++ b/src/journal-remote/microhttpd-util.c @@ -0,0 +1,311 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#if HAVE_GNUTLS +#include +#include +#endif + +#include "alloc-util.h" +#include "log.h" +#include "macro.h" +#include "microhttpd-util.h" +#include "string-util.h" +#include "strv.h" +#include "util.h" + +void microhttpd_logger(void *arg, const char *fmt, va_list ap) { + char *f; + + f = strjoina("microhttpd: ", fmt); + + DISABLE_WARNING_FORMAT_NONLITERAL; + log_internalv(LOG_INFO, 0, NULL, 0, NULL, f, ap); + REENABLE_WARNING; +} + +static int mhd_respond_internal(struct MHD_Connection *connection, + enum MHD_RequestTerminationCode code, + const char *buffer, + size_t size, + enum MHD_ResponseMemoryMode mode) { + assert(connection); + + _cleanup_(MHD_destroy_responsep) struct MHD_Response *response + = MHD_create_response_from_buffer(size, (char*) buffer, mode); + if (!response) + return MHD_NO; + + log_debug("Queueing response %u: %s", code, buffer); + MHD_add_response_header(response, "Content-Type", "text/plain"); + return MHD_queue_response(connection, code, response); +} + +int mhd_respond(struct MHD_Connection *connection, + enum MHD_RequestTerminationCode code, + const char *message) { + + const char *fmt; + + fmt = strjoina(message, "\n"); + + return mhd_respond_internal(connection, code, + fmt, strlen(message) + 1, + MHD_RESPMEM_PERSISTENT); +} + +int mhd_respond_oom(struct MHD_Connection *connection) { + return mhd_respond(connection, MHD_HTTP_SERVICE_UNAVAILABLE, "Out of memory."); +} + +int mhd_respondf(struct MHD_Connection *connection, + int error, + enum MHD_RequestTerminationCode code, + const char *format, ...) { + + const char *fmt; + char *m; + int r; + va_list ap; + + assert(connection); + assert(format); + + if (error < 0) + error = -error; + errno = -error; + fmt = strjoina(format, "\n"); + va_start(ap, format); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + r = vasprintf(&m, fmt, ap); +#pragma GCC diagnostic pop + va_end(ap); + + if (r < 0) + return respond_oom(connection); + + return mhd_respond_internal(connection, code, m, r, MHD_RESPMEM_MUST_FREE); +} + +#if HAVE_GNUTLS + +static struct { + const char *const names[4]; + int level; + bool enabled; +} gnutls_log_map[] = { + { {"0"}, LOG_DEBUG }, + { {"1", "audit"}, LOG_WARNING, true}, /* gnutls session audit */ + { {"2", "assert"}, LOG_DEBUG }, /* gnutls assert log */ + { {"3", "hsk", "ext"}, LOG_DEBUG }, /* gnutls handshake log */ + { {"4", "rec"}, LOG_DEBUG }, /* gnutls record log */ + { {"5", "dtls"}, LOG_DEBUG }, /* gnutls DTLS log */ + { {"6", "buf"}, LOG_DEBUG }, + { {"7", "write", "read"}, LOG_DEBUG }, + { {"8"}, LOG_DEBUG }, + { {"9", "enc", "int"}, LOG_DEBUG }, +}; + +static void log_func_gnutls(int level, const char *message) { + assert_se(message); + + if (0 <= level && level < (int) ELEMENTSOF(gnutls_log_map)) { + if (gnutls_log_map[level].enabled) + log_internal(gnutls_log_map[level].level, 0, NULL, 0, NULL, "gnutls %d/%s: %s", level, gnutls_log_map[level].names[1], message); + } else { + log_debug("Received GNUTLS message with unknown level %d.", level); + log_internal(LOG_DEBUG, 0, NULL, 0, NULL, "gnutls: %s", message); + } +} + +static void log_reset_gnutls_level(void) { + int i; + + for (i = ELEMENTSOF(gnutls_log_map) - 1; i >= 0; i--) + if (gnutls_log_map[i].enabled) { + log_debug("Setting gnutls log level to %d", i); + gnutls_global_set_log_level(i); + break; + } +} + +static int log_enable_gnutls_category(const char *cat) { + unsigned i; + + if (streq(cat, "all")) { + for (i = 0; i < ELEMENTSOF(gnutls_log_map); i++) + gnutls_log_map[i].enabled = true; + log_reset_gnutls_level(); + return 0; + } else + for (i = 0; i < ELEMENTSOF(gnutls_log_map); i++) + if (strv_contains((char**)gnutls_log_map[i].names, cat)) { + gnutls_log_map[i].enabled = true; + log_reset_gnutls_level(); + return 0; + } + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No such log category: %s", cat); +} + +int setup_gnutls_logger(char **categories) { + char **cat; + int r; + + gnutls_global_set_log_function(log_func_gnutls); + + if (categories) { + STRV_FOREACH(cat, categories) { + r = log_enable_gnutls_category(*cat); + if (r < 0) + return r; + } + } else + log_reset_gnutls_level(); + + return 0; +} + +static int verify_cert_authorized(gnutls_session_t session) { + unsigned status; + gnutls_certificate_type_t type; + gnutls_datum_t out; + int r; + + r = gnutls_certificate_verify_peers2(session, &status); + if (r < 0) + return log_error_errno(r, "gnutls_certificate_verify_peers2 failed: %m"); + + type = gnutls_certificate_type_get(session); + r = gnutls_certificate_verification_status_print(status, type, &out, 0); + if (r < 0) + return log_error_errno(r, "gnutls_certificate_verification_status_print failed: %m"); + + log_debug("Certificate status: %s", out.data); + gnutls_free(out.data); + + return status == 0 ? 0 : -EPERM; +} + +static int get_client_cert(gnutls_session_t session, gnutls_x509_crt_t *client_cert) { + const gnutls_datum_t *pcert; + unsigned listsize; + gnutls_x509_crt_t cert; + int r; + + assert(session); + assert(client_cert); + + pcert = gnutls_certificate_get_peers(session, &listsize); + if (!pcert || !listsize) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to retrieve certificate chain"); + + r = gnutls_x509_crt_init(&cert); + if (r < 0) { + log_error("Failed to initialize client certificate"); + return r; + } + + /* Note that by passing values between 0 and listsize here, you + can get access to the CA's certs */ + r = gnutls_x509_crt_import(cert, &pcert[0], GNUTLS_X509_FMT_DER); + if (r < 0) { + log_error("Failed to import client certificate"); + gnutls_x509_crt_deinit(cert); + return r; + } + + *client_cert = cert; + return 0; +} + +static int get_auth_dn(gnutls_x509_crt_t client_cert, char **buf) { + size_t len = 0; + int r; + + assert(buf); + assert(*buf == NULL); + + r = gnutls_x509_crt_get_dn(client_cert, NULL, &len); + if (r != GNUTLS_E_SHORT_MEMORY_BUFFER) { + log_error("gnutls_x509_crt_get_dn failed"); + return r; + } + + *buf = malloc(len); + if (!*buf) + return log_oom(); + + gnutls_x509_crt_get_dn(client_cert, *buf, &len); + return 0; +} + +static void gnutls_x509_crt_deinitp(gnutls_x509_crt_t *p) { + gnutls_x509_crt_deinit(*p); +} + +int check_permissions(struct MHD_Connection *connection, int *code, char **hostname) { + const union MHD_ConnectionInfo *ci; + gnutls_session_t session; + _cleanup_(gnutls_x509_crt_deinitp) gnutls_x509_crt_t client_cert = NULL; + _cleanup_free_ char *buf = NULL; + int r; + + assert(connection); + assert(code); + + *code = 0; + + ci = MHD_get_connection_info(connection, + MHD_CONNECTION_INFO_GNUTLS_SESSION); + if (!ci) { + log_error("MHD_get_connection_info failed: session is unencrypted"); + *code = mhd_respond(connection, MHD_HTTP_FORBIDDEN, + "Encrypted connection is required"); + return -EPERM; + } + session = ci->tls_session; + assert(session); + + r = get_client_cert(session, &client_cert); + if (r < 0) { + *code = mhd_respond(connection, MHD_HTTP_UNAUTHORIZED, + "Authorization through certificate is required"); + return -EPERM; + } + + r = get_auth_dn(client_cert, &buf); + if (r < 0) { + *code = mhd_respond(connection, MHD_HTTP_UNAUTHORIZED, + "Failed to determine distinguished name from certificate"); + return -EPERM; + } + + log_debug("Connection from %s", buf); + + if (hostname) + *hostname = TAKE_PTR(buf); + + r = verify_cert_authorized(session); + if (r < 0) { + log_warning("Client is not authorized"); + *code = mhd_respond(connection, MHD_HTTP_UNAUTHORIZED, + "Client certificate not signed by recognized authority"); + } + return r; +} + +#else +int check_permissions(struct MHD_Connection *connection, int *code, char **hostname) { + return -EPERM; +} + +int setup_gnutls_logger(char **categories) { + if (categories) + log_notice("Ignoring specified gnutls logging categories — gnutls not available."); + return 0; +} +#endif diff --git a/src/journal-remote/microhttpd-util.h b/src/journal-remote/microhttpd-util.h new file mode 100644 index 00000000..d90c6bbd --- /dev/null +++ b/src/journal-remote/microhttpd-util.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "macro.h" + +/* Those defines are added when options are renamed. If the old names + * are not '#define'd, then they are not deprecated yet and there are + * enum elements with the same name. Hence let's check for the *old* name, + * and define the new name by the value of the old name. */ + +/* Renamed in µhttpd 0.9.51 */ +#ifndef MHD_USE_PIPE_FOR_SHUTDOWN +# define MHD_USE_ITC MHD_USE_PIPE_FOR_SHUTDOWN +#endif + +/* Renamed in µhttpd 0.9.52 */ +#ifndef MHD_USE_EPOLL_LINUX_ONLY +# define MHD_USE_EPOLL MHD_USE_EPOLL_LINUX_ONLY +#endif + +/* Renamed in µhttpd 0.9.52 */ +#ifndef MHD_USE_SSL +# define MHD_USE_TLS MHD_USE_SSL +#endif + +/* Renamed in µhttpd 0.9.53 */ +#ifndef MHD_USE_POLL_INTERNALLY +# define MHD_USE_POLL_INTERNAL_THREAD MHD_USE_POLL_INTERNALLY +#endif + +/* Both the old and new names are defines, check for the new one. */ + +/* Compatibility with libmicrohttpd < 0.9.38 */ +#ifndef MHD_HTTP_NOT_ACCEPTABLE +# define MHD_HTTP_NOT_ACCEPTABLE MHD_HTTP_METHOD_NOT_ACCEPTABLE +#endif + +/* Renamed in µhttpd 0.9.53 */ +#ifndef MHD_HTTP_PAYLOAD_TOO_LARGE +# define MHD_HTTP_PAYLOAD_TOO_LARGE MHD_HTTP_REQUEST_ENTITY_TOO_LARGE +#endif + +#if MHD_VERSION < 0x00094203 +# define MHD_create_response_from_fd_at_offset64 MHD_create_response_from_fd_at_offset +#endif + +void microhttpd_logger(void *arg, const char *fmt, va_list ap) _printf_(2, 0); + +/* respond_oom() must be usable with return, hence this form. */ +#define respond_oom(connection) log_oom(), mhd_respond_oom(connection) + +int mhd_respondf(struct MHD_Connection *connection, + int error, + unsigned code, + const char *format, ...) _printf_(4,5); + +int mhd_respond(struct MHD_Connection *connection, + unsigned code, + const char *message); + +int mhd_respond_oom(struct MHD_Connection *connection); + +int check_permissions(struct MHD_Connection *connection, int *code, char **hostname); + +/* Set gnutls internal logging function to a callback which uses our + * own logging framework. + * + * gnutls categories are additionally filtered by our internal log + * level, so it should be set fairly high to capture all potentially + * interesting events without overwhelming detail. + */ +int setup_gnutls_logger(char **categories); + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Daemon*, MHD_stop_daemon); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct MHD_Response*, MHD_destroy_response); diff --git a/src/journal/audit-type.c b/src/journal/audit-type.c new file mode 100644 index 00000000..7b3dc1e9 --- /dev/null +++ b/src/journal/audit-type.c @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "audit-type.h" +#include "missing_audit.h" + +#include "audit_type-to-name.h" diff --git a/src/journal/audit-type.h b/src/journal/audit-type.h new file mode 100644 index 00000000..39d91789 --- /dev/null +++ b/src/journal/audit-type.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "alloc-util.h" +#include "macro.h" + +const char *audit_type_to_string(int type); +int audit_type_from_string(const char *s); + +/* This is inspired by DNS TYPEnnn formatting */ +#define audit_type_name_alloca(type) \ + ({ \ + const char *_s_; \ + _s_ = audit_type_to_string(type); \ + if (!_s_) { \ + _s_ = newa(char, STRLEN("AUDIT") + DECIMAL_STR_MAX(int)); \ + sprintf((char*) _s_, "AUDIT%04i", type); \ + } \ + _s_; \ + }) diff --git a/src/journal/audit_type-to-name.awk b/src/journal/audit_type-to-name.awk new file mode 100644 index 00000000..44fc702e --- /dev/null +++ b/src/journal/audit_type-to-name.awk @@ -0,0 +1,9 @@ +BEGIN{ + print "const char *audit_type_to_string(int type) {\n\tswitch(type) {" +} +{ + printf " case AUDIT_%s: return \"%s\";\n", $1, $1 +} +END{ + print " default: return NULL;\n\t}\n}\n" +} diff --git a/src/journal/cat.c b/src/journal/cat.c new file mode 100644 index 00000000..500b6745 --- /dev/null +++ b/src/journal/cat.c @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "sd-journal.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "main-func.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "string-util.h" +#include "syslog-util.h" +#include "terminal-util.h" +#include "util.h" + +static const char *arg_identifier = NULL; +static int arg_priority = LOG_INFO; +static int arg_stderr_priority = -1; +static bool arg_level_prefix = true; + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-cat", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n" + "\n%sExecute process with stdout/stderr connected to the journal.%s\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -t --identifier=STRING Set syslog identifier\n" + " -p --priority=PRIORITY Set priority value (0..7)\n" + " --stderr-priority=PRIORITY Set priority value (0..7) used for stderr\n" + " --level-prefix=BOOL Control whether level prefix shall be parsed\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_STDERR_PRIORITY, + ARG_LEVEL_PREFIX + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "identifier", required_argument, NULL, 't' }, + { "priority", required_argument, NULL, 'p' }, + { "stderr-priority", required_argument, NULL, ARG_STDERR_PRIORITY }, + { "level-prefix", required_argument, NULL, ARG_LEVEL_PREFIX }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "+ht:p:", options, NULL)) >= 0) + + switch (c) { + + case 'h': + help(); + return 0; + + case ARG_VERSION: + return version(); + + case 't': + if (isempty(optarg)) + arg_identifier = NULL; + else + arg_identifier = optarg; + break; + + case 'p': + arg_priority = log_level_from_string(optarg); + if (arg_priority < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse priority value."); + break; + + case ARG_STDERR_PRIORITY: + arg_stderr_priority = log_level_from_string(optarg); + if (arg_stderr_priority < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse stderr priority value."); + break; + + case ARG_LEVEL_PREFIX: { + int k; + + k = parse_boolean(optarg); + if (k < 0) + return log_error_errno(k, "Failed to parse level prefix value."); + + arg_level_prefix = k; + break; + } + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_close_ int outfd = -1, errfd = -1, saved_stderr = -1; + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + outfd = sd_journal_stream_fd(arg_identifier, arg_priority, arg_level_prefix); + if (outfd < 0) + return log_error_errno(outfd, "Failed to create stream fd: %m"); + + if (arg_stderr_priority >= 0 && arg_stderr_priority != arg_priority) { + errfd = sd_journal_stream_fd(arg_identifier, arg_stderr_priority, arg_level_prefix); + if (errfd < 0) + return log_error_errno(errfd, "Failed to create stream fd: %m"); + } + + saved_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3); + + r = rearrange_stdio(STDIN_FILENO, outfd, errfd < 0 ? outfd : errfd); /* Invalidates fd on success + error! */ + TAKE_FD(outfd); + TAKE_FD(errfd); + if (r < 0) + return log_error_errno(r, "Failed to rearrange stdout/stderr: %m"); + + if (argc <= optind) + (void) execl("/bin/cat", "/bin/cat", NULL); + else + (void) execvp(argv[optind], argv + optind); + r = -errno; + + /* Let's try to restore a working stderr, so we can print the error message */ + if (saved_stderr >= 0) + (void) dup3(saved_stderr, STDERR_FILENO, 0); + + return log_error_errno(r, "Failed to execute process: %m"); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/journal/catalog.c b/src/journal/catalog.c new file mode 100644 index 00000000..70b2c8b4 --- /dev/null +++ b/src/journal/catalog.c @@ -0,0 +1,743 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "catalog.h" +#include "conf-files.h" +#include "fd-util.h" +#include "fileio.h" +#include "hashmap.h" +#include "log.h" +#include "memory-util.h" +#include "mkdir.h" +#include "path-util.h" +#include "siphash24.h" +#include "sort-util.h" +#include "sparse-endian.h" +#include "strbuf.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" + +const char * const catalog_file_dirs[] = { + "/usr/local/lib/systemd/catalog/", + "/usr/lib/systemd/catalog/", + NULL +}; + +#define CATALOG_SIGNATURE { 'R', 'H', 'H', 'H', 'K', 'S', 'L', 'P' } + +typedef struct CatalogHeader { + uint8_t signature[8]; /* "RHHHKSLP" */ + le32_t compatible_flags; + le32_t incompatible_flags; + le64_t header_size; + le64_t n_items; + le64_t catalog_item_size; +} CatalogHeader; + +typedef struct CatalogItem { + sd_id128_t id; + char language[32]; /* One byte is used for termination, so the maximum allowed + * length of the string is actually 31 bytes. */ + le64_t offset; +} CatalogItem; + +static void catalog_hash_func(const CatalogItem *i, struct siphash *state) { + siphash24_compress(&i->id, sizeof(i->id), state); + siphash24_compress(i->language, strlen(i->language), state); +} + +static int catalog_compare_func(const CatalogItem *a, const CatalogItem *b) { + unsigned k; + int r; + + for (k = 0; k < ELEMENTSOF(b->id.bytes); k++) { + r = CMP(a->id.bytes[k], b->id.bytes[k]); + if (r != 0) + return r; + } + + return strcmp(a->language, b->language); +} + +DEFINE_HASH_OPS(catalog_hash_ops, CatalogItem, catalog_hash_func, catalog_compare_func); + +static bool next_header(const char **s) { + const char *e; + + e = strchr(*s, '\n'); + + /* Unexpected end */ + if (!e) + return false; + + /* End of headers */ + if (e == *s) + return false; + + *s = e + 1; + return true; +} + +static const char *skip_header(const char *s) { + while (next_header(&s)) + ; + return s; +} + +static char *combine_entries(const char *one, const char *two) { + const char *b1, *b2; + size_t l1, l2, n; + char *dest, *p; + + /* Find split point of headers to body */ + b1 = skip_header(one); + b2 = skip_header(two); + + l1 = strlen(one); + l2 = strlen(two); + dest = new(char, l1 + l2 + 1); + if (!dest) { + log_oom(); + return NULL; + } + + p = dest; + + /* Headers from @one */ + n = b1 - one; + p = mempcpy(p, one, n); + + /* Headers from @two, these will only be found if not present above */ + n = b2 - two; + p = mempcpy(p, two, n); + + /* Body from @one */ + n = l1 - (b1 - one); + if (n > 0) { + memcpy(p, b1, n); + p += n; + + /* Body from @two */ + } else { + n = l2 - (b2 - two); + memcpy(p, b2, n); + p += n; + } + + assert(p - dest <= (ptrdiff_t)(l1 + l2)); + p[0] = '\0'; + return dest; +} + +static int finish_item( + OrderedHashmap *h, + sd_id128_t id, + const char *language, + char *payload, size_t payload_size) { + + _cleanup_free_ CatalogItem *i = NULL; + _cleanup_free_ char *prev = NULL, *combined = NULL; + + assert(h); + assert(payload); + assert(payload_size > 0); + + i = new0(CatalogItem, 1); + if (!i) + return log_oom(); + + i->id = id; + if (language) { + assert(strlen(language) > 1 && strlen(language) < 32); + strcpy(i->language, language); + } + + prev = ordered_hashmap_get(h, i); + if (prev) { + /* Already have such an item, combine them */ + combined = combine_entries(payload, prev); + if (!combined) + return log_oom(); + + if (ordered_hashmap_update(h, i, combined) < 0) + return log_oom(); + combined = NULL; + } else { + /* A new item */ + combined = memdup(payload, payload_size + 1); + if (!combined) + return log_oom(); + + if (ordered_hashmap_put(h, i, combined) < 0) + return log_oom(); + i = NULL; + combined = NULL; + } + + return 0; +} + +int catalog_file_lang(const char* filename, char **lang) { + char *beg, *end, *_lang; + + end = endswith(filename, ".catalog"); + if (!end) + return 0; + + beg = end - 1; + while (beg > filename && !IN_SET(*beg, '.', '/') && end - beg < 32) + beg--; + + if (*beg != '.' || end <= beg + 1) + return 0; + + _lang = strndup(beg + 1, end - beg - 1); + if (!_lang) + return -ENOMEM; + + *lang = _lang; + return 1; +} + +static int catalog_entry_lang( + const char* filename, + unsigned line, + const char* t, + const char* deflang, + char **ret) { + + size_t c; + char *z; + + c = strlen(t); + if (c < 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Language too short.", filename, line); + if (c > 31) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] language too long.", filename, line); + + if (deflang) { + if (streq(t, deflang)) { + log_warning("[%s:%u] language specified unnecessarily", filename, line); + return 0; + } + + log_warning("[%s:%u] language differs from default for file", filename, line); + } + + z = strdup(t); + if (!z) + return -ENOMEM; + + *ret = z; + return 0; +} + +int catalog_import_file(OrderedHashmap *h, const char *path) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *payload = NULL; + size_t payload_size = 0, payload_allocated = 0; + unsigned n = 0; + sd_id128_t id; + _cleanup_free_ char *deflang = NULL, *lang = NULL; + bool got_id = false, empty_line = true; + int r; + + assert(h); + assert(path); + + f = fopen(path, "re"); + if (!f) + return log_error_errno(errno, "Failed to open file %s: %m", path); + + r = catalog_file_lang(path, &deflang); + if (r < 0) + log_error_errno(r, "Failed to determine language for file %s: %m", path); + if (r == 1) + log_debug("File %s has language %s.", path, deflang); + + for (;;) { + _cleanup_free_ char *line = NULL; + size_t line_len; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read file %s: %m", path); + if (r == 0) + break; + + n++; + + if (isempty(line)) { + empty_line = true; + continue; + } + + if (strchr(COMMENTS, line[0])) + continue; + + if (empty_line && + strlen(line) >= 2+1+32 && + line[0] == '-' && + line[1] == '-' && + line[2] == ' ' && + IN_SET(line[2+1+32], ' ', '\0')) { + + bool with_language; + sd_id128_t jd; + + /* New entry */ + + with_language = line[2+1+32] != '\0'; + line[2+1+32] = '\0'; + + if (sd_id128_from_string(line + 2 + 1, &jd) >= 0) { + + if (got_id) { + if (payload_size == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] No payload text.", + path, + n); + + r = finish_item(h, id, lang ?: deflang, payload, payload_size); + if (r < 0) + return r; + + lang = mfree(lang); + payload_size = 0; + } + + if (with_language) { + char *t; + + t = strstrip(line + 2 + 1 + 32 + 1); + r = catalog_entry_lang(path, n, t, deflang, &lang); + if (r < 0) + return r; + } + + got_id = true; + empty_line = false; + id = jd; + + continue; + } + } + + /* Payload */ + if (!got_id) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Got payload before ID.", + path, n); + + line_len = strlen(line); + if (!GREEDY_REALLOC(payload, payload_allocated, + payload_size + (empty_line ? 1 : 0) + line_len + 1 + 1)) + return log_oom(); + + if (empty_line) + payload[payload_size++] = '\n'; + memcpy(payload + payload_size, line, line_len); + payload_size += line_len; + payload[payload_size++] = '\n'; + payload[payload_size] = '\0'; + + empty_line = false; + } + + if (got_id) { + if (payload_size == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] No payload text.", + path, n); + + r = finish_item(h, id, lang ?: deflang, payload, payload_size); + if (r < 0) + return r; + } + + return 0; +} + +static int64_t write_catalog( + const char *database, + struct strbuf *sb, + CatalogItem *items, + size_t n) { + + _cleanup_fclose_ FILE *w = NULL; + _cleanup_free_ char *p = NULL; + CatalogHeader header; + size_t k; + int r; + + r = mkdir_parents(database, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create parent directories of %s: %m", database); + + r = fopen_temporary(database, &w, &p); + if (r < 0) + return log_error_errno(r, "Failed to open database for writing: %s: %m", + database); + + header = (CatalogHeader) { + .signature = CATALOG_SIGNATURE, + .header_size = htole64(ALIGN_TO(sizeof(CatalogHeader), 8)), + .catalog_item_size = htole64(sizeof(CatalogItem)), + .n_items = htole64(n), + }; + + r = -EIO; + + k = fwrite(&header, 1, sizeof(header), w); + if (k != sizeof(header)) { + log_error("%s: failed to write header.", p); + goto error; + } + + k = fwrite(items, 1, n * sizeof(CatalogItem), w); + if (k != n * sizeof(CatalogItem)) { + log_error("%s: failed to write database.", p); + goto error; + } + + k = fwrite(sb->buf, 1, sb->len, w); + if (k != sb->len) { + log_error("%s: failed to write strings.", p); + goto error; + } + + r = fflush_and_check(w); + if (r < 0) { + log_error_errno(r, "%s: failed to write database: %m", p); + goto error; + } + + (void) fchmod(fileno(w), 0644); + + if (rename(p, database) < 0) { + r = log_error_errno(errno, "rename (%s -> %s) failed: %m", p, database); + goto error; + } + + return ftello(w); + +error: + (void) unlink(p); + return r; +} + +int catalog_update(const char* database, const char* root, const char* const* dirs) { + _cleanup_strv_free_ char **files = NULL; + char **f; + _cleanup_(strbuf_cleanupp) struct strbuf *sb = NULL; + _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL; + _cleanup_free_ CatalogItem *items = NULL; + ssize_t offset; + char *payload; + CatalogItem *i; + Iterator j; + unsigned n; + int r; + int64_t sz; + + h = ordered_hashmap_new(&catalog_hash_ops); + sb = strbuf_new(); + if (!h || !sb) + return log_oom(); + + r = conf_files_list_strv(&files, ".catalog", root, 0, dirs); + if (r < 0) + return log_error_errno(r, "Failed to get catalog files: %m"); + + STRV_FOREACH(f, files) { + log_debug("Reading file '%s'", *f); + r = catalog_import_file(h, *f); + if (r < 0) + return log_error_errno(r, "Failed to import file '%s': %m", *f); + } + + if (ordered_hashmap_size(h) <= 0) { + log_info("No items in catalog."); + return 0; + } else + log_debug("Found %u items in catalog.", ordered_hashmap_size(h)); + + items = new(CatalogItem, ordered_hashmap_size(h)); + if (!items) + return log_oom(); + + n = 0; + ORDERED_HASHMAP_FOREACH_KEY(payload, i, h, j) { + log_debug("Found " SD_ID128_FORMAT_STR ", language %s", + SD_ID128_FORMAT_VAL(i->id), + isempty(i->language) ? "C" : i->language); + + offset = strbuf_add_string(sb, payload, strlen(payload)); + if (offset < 0) + return log_oom(); + + i->offset = htole64((uint64_t) offset); + items[n++] = *i; + } + + assert(n == ordered_hashmap_size(h)); + typesafe_qsort(items, n, catalog_compare_func); + + strbuf_complete(sb); + + sz = write_catalog(database, sb, items, n); + if (sz < 0) + return log_error_errno(sz, "Failed to write %s: %m", database); + + log_debug("%s: wrote %u items, with %zu bytes of strings, %"PRIi64" total size.", + database, n, sb->len, sz); + return 0; +} + +static int open_mmap(const char *database, int *_fd, struct stat *_st, void **_p) { + _cleanup_close_ int fd = -1; + const CatalogHeader *h; + struct stat st; + void *p; + + assert(_fd); + assert(_st); + assert(_p); + + fd = open(database, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return -errno; + + if (fstat(fd, &st) < 0) + return -errno; + + if (st.st_size < (off_t) sizeof(CatalogHeader)) + return -EINVAL; + + p = mmap(NULL, PAGE_ALIGN(st.st_size), PROT_READ, MAP_SHARED, fd, 0); + if (p == MAP_FAILED) + return -errno; + + h = p; + if (memcmp(h->signature, (const uint8_t[]) CATALOG_SIGNATURE, sizeof(h->signature)) != 0 || + le64toh(h->header_size) < sizeof(CatalogHeader) || + le64toh(h->catalog_item_size) < sizeof(CatalogItem) || + h->incompatible_flags != 0 || + le64toh(h->n_items) <= 0 || + st.st_size < (off_t) (le64toh(h->header_size) + le64toh(h->catalog_item_size) * le64toh(h->n_items))) { + munmap(p, st.st_size); + return -EBADMSG; + } + + *_fd = TAKE_FD(fd); + *_st = st; + *_p = p; + + return 0; +} + +static const char *find_id(void *p, sd_id128_t id) { + CatalogItem *f = NULL, key = { .id = id }; + const CatalogHeader *h = p; + const char *loc; + + loc = setlocale(LC_MESSAGES, NULL); + if (!isempty(loc) && !STR_IN_SET(loc, "C", "POSIX")) { + size_t len; + + len = strcspn(loc, ".@"); + if (len > sizeof(key.language) - 1) + log_debug("LC_MESSAGES value too long, ignoring: \"%.*s\"", (int) len, loc); + else { + strncpy(key.language, loc, len); + key.language[len] = '\0'; + + f = bsearch(&key, + (const uint8_t*) p + le64toh(h->header_size), + le64toh(h->n_items), + le64toh(h->catalog_item_size), + (comparison_fn_t) catalog_compare_func); + if (!f) { + char *e; + + e = strchr(key.language, '_'); + if (e) { + *e = 0; + f = bsearch(&key, + (const uint8_t*) p + le64toh(h->header_size), + le64toh(h->n_items), + le64toh(h->catalog_item_size), + (comparison_fn_t) catalog_compare_func); + } + } + } + } + + if (!f) { + zero(key.language); + f = bsearch(&key, + (const uint8_t*) p + le64toh(h->header_size), + le64toh(h->n_items), + le64toh(h->catalog_item_size), + (comparison_fn_t) catalog_compare_func); + } + + if (!f) + return NULL; + + return (const char*) p + + le64toh(h->header_size) + + le64toh(h->n_items) * le64toh(h->catalog_item_size) + + le64toh(f->offset); +} + +int catalog_get(const char* database, sd_id128_t id, char **_text) { + _cleanup_close_ int fd = -1; + void *p = NULL; + struct stat st = {}; + char *text = NULL; + int r; + const char *s; + + assert(_text); + + r = open_mmap(database, &fd, &st, &p); + if (r < 0) + return r; + + s = find_id(p, id); + if (!s) { + r = -ENOENT; + goto finish; + } + + text = strdup(s); + if (!text) { + r = -ENOMEM; + goto finish; + } + + *_text = text; + r = 0; + +finish: + if (p) + munmap(p, st.st_size); + + return r; +} + +static char *find_header(const char *s, const char *header) { + + for (;;) { + const char *v; + + v = startswith(s, header); + if (v) { + v += strspn(v, WHITESPACE); + return strndup(v, strcspn(v, NEWLINE)); + } + + if (!next_header(&s)) + return NULL; + } +} + +static void dump_catalog_entry(FILE *f, sd_id128_t id, const char *s, bool oneline) { + if (oneline) { + _cleanup_free_ char *subject = NULL, *defined_by = NULL; + + subject = find_header(s, "Subject:"); + defined_by = find_header(s, "Defined-By:"); + + fprintf(f, SD_ID128_FORMAT_STR " %s: %s\n", + SD_ID128_FORMAT_VAL(id), + strna(defined_by), strna(subject)); + } else + fprintf(f, "-- " SD_ID128_FORMAT_STR "\n%s\n", + SD_ID128_FORMAT_VAL(id), s); +} + +int catalog_list(FILE *f, const char *database, bool oneline) { + _cleanup_close_ int fd = -1; + void *p = NULL; + struct stat st; + const CatalogHeader *h; + const CatalogItem *items; + int r; + unsigned n; + sd_id128_t last_id; + bool last_id_set = false; + + r = open_mmap(database, &fd, &st, &p); + if (r < 0) + return r; + + h = p; + items = (const CatalogItem*) ((const uint8_t*) p + le64toh(h->header_size)); + + for (n = 0; n < le64toh(h->n_items); n++) { + const char *s; + + if (last_id_set && sd_id128_equal(last_id, items[n].id)) + continue; + + assert_se(s = find_id(p, items[n].id)); + + dump_catalog_entry(f, items[n].id, s, oneline); + + last_id_set = true; + last_id = items[n].id; + } + + munmap(p, st.st_size); + + return 0; +} + +int catalog_list_items(FILE *f, const char *database, bool oneline, char **items) { + char **item; + int r = 0; + + STRV_FOREACH(item, items) { + sd_id128_t id; + int k; + _cleanup_free_ char *msg = NULL; + + k = sd_id128_from_string(*item, &id); + if (k < 0) { + log_error_errno(k, "Failed to parse id128 '%s': %m", *item); + if (r == 0) + r = k; + continue; + } + + k = catalog_get(database, id, &msg); + if (k < 0) { + log_full_errno(k == -ENOENT ? LOG_NOTICE : LOG_ERR, k, + "Failed to retrieve catalog entry for '%s': %m", *item); + if (r == 0) + r = k; + continue; + } + + dump_catalog_entry(f, id, msg, oneline); + } + + return r; +} diff --git a/src/journal/catalog.h b/src/journal/catalog.h new file mode 100644 index 00000000..092a0146 --- /dev/null +++ b/src/journal/catalog.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-id128.h" + +#include "hashmap.h" +#include "strbuf.h" + +int catalog_import_file(OrderedHashmap *h, const char *path); +int catalog_update(const char* database, const char* root, const char* const* dirs); +int catalog_get(const char* database, sd_id128_t id, char **data); +int catalog_list(FILE *f, const char* database, bool oneline); +int catalog_list_items(FILE *f, const char* database, bool oneline, char **items); +int catalog_file_lang(const char *filename, char **lang); +extern const char * const catalog_file_dirs[]; +extern const struct hash_ops catalog_hash_ops; diff --git a/src/journal/compress.c b/src/journal/compress.c new file mode 100644 index 00000000..4e00e4fc --- /dev/null +++ b/src/journal/compress.c @@ -0,0 +1,679 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#if HAVE_XZ +#include +#endif + +#if HAVE_LZ4 +#include +#include +#endif + +#include "alloc-util.h" +#include "compress.h" +#include "fd-util.h" +#include "io-util.h" +#include "journal-def.h" +#include "macro.h" +#include "sparse-endian.h" +#include "string-table.h" +#include "string-util.h" +#include "unaligned.h" +#include "util.h" + +#if HAVE_LZ4 +DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_compressionContext_t, LZ4F_freeCompressionContext); +DEFINE_TRIVIAL_CLEANUP_FUNC(LZ4F_decompressionContext_t, LZ4F_freeDecompressionContext); +#endif + +#define ALIGN_8(l) ALIGN_TO(l, sizeof(size_t)) + +static const char* const object_compressed_table[_OBJECT_COMPRESSED_MAX] = { + [OBJECT_COMPRESSED_XZ] = "XZ", + [OBJECT_COMPRESSED_LZ4] = "LZ4", +}; + +DEFINE_STRING_TABLE_LOOKUP(object_compressed, int); + +int compress_blob_xz(const void *src, uint64_t src_size, + void *dst, size_t dst_alloc_size, size_t *dst_size) { +#if HAVE_XZ + static const lzma_options_lzma opt = { + 1u << 20u, NULL, 0, LZMA_LC_DEFAULT, LZMA_LP_DEFAULT, + LZMA_PB_DEFAULT, LZMA_MODE_FAST, 128, LZMA_MF_HC3, 4 + }; + static const lzma_filter filters[] = { + { LZMA_FILTER_LZMA2, (lzma_options_lzma*) &opt }, + { LZMA_VLI_UNKNOWN, NULL } + }; + lzma_ret ret; + size_t out_pos = 0; + + assert(src); + assert(src_size > 0); + assert(dst); + assert(dst_alloc_size > 0); + assert(dst_size); + + /* Returns < 0 if we couldn't compress the data or the + * compressed result is longer than the original */ + + if (src_size < 80) + return -ENOBUFS; + + ret = lzma_stream_buffer_encode((lzma_filter*) filters, LZMA_CHECK_NONE, NULL, + src, src_size, dst, &out_pos, dst_alloc_size); + if (ret != LZMA_OK) + return -ENOBUFS; + + *dst_size = out_pos; + return 0; +#else + return -EPROTONOSUPPORT; +#endif +} + +int compress_blob_lz4(const void *src, uint64_t src_size, + void *dst, size_t dst_alloc_size, size_t *dst_size) { +#if HAVE_LZ4 + int r; + + assert(src); + assert(src_size > 0); + assert(dst); + assert(dst_alloc_size > 0); + assert(dst_size); + + /* Returns < 0 if we couldn't compress the data or the + * compressed result is longer than the original */ + + if (src_size < 9) + return -ENOBUFS; + + r = LZ4_compress_default(src, (char*)dst + 8, src_size, (int) dst_alloc_size - 8); + if (r <= 0) + return -ENOBUFS; + + unaligned_write_le64(dst, src_size); + *dst_size = r + 8; + + return 0; +#else + return -EPROTONOSUPPORT; +#endif +} + +int decompress_blob_xz(const void *src, uint64_t src_size, + void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) { + +#if HAVE_XZ + _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; + lzma_ret ret; + size_t space; + + assert(src); + assert(src_size > 0); + assert(dst); + assert(dst_alloc_size); + assert(dst_size); + assert(*dst_alloc_size == 0 || *dst); + + ret = lzma_stream_decoder(&s, UINT64_MAX, 0); + if (ret != LZMA_OK) + return -ENOMEM; + + space = MIN(src_size * 2, dst_max ?: (size_t) -1); + if (!greedy_realloc(dst, dst_alloc_size, space, 1)) + return -ENOMEM; + + s.next_in = src; + s.avail_in = src_size; + + s.next_out = *dst; + s.avail_out = space; + + for (;;) { + size_t used; + + ret = lzma_code(&s, LZMA_FINISH); + + if (ret == LZMA_STREAM_END) + break; + else if (ret != LZMA_OK) + return -ENOMEM; + + if (dst_max > 0 && (space - s.avail_out) >= dst_max) + break; + else if (dst_max > 0 && space == dst_max) + return -ENOBUFS; + + used = space - s.avail_out; + space = MIN(2 * space, dst_max ?: (size_t) -1); + if (!greedy_realloc(dst, dst_alloc_size, space, 1)) + return -ENOMEM; + + s.avail_out = space - used; + s.next_out = *(uint8_t**)dst + used; + } + + *dst_size = space - s.avail_out; + return 0; +#else + return -EPROTONOSUPPORT; +#endif +} + +int decompress_blob_lz4(const void *src, uint64_t src_size, + void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) { + +#if HAVE_LZ4 + char* out; + int r, size; /* LZ4 uses int for size */ + + assert(src); + assert(src_size > 0); + assert(dst); + assert(dst_alloc_size); + assert(dst_size); + assert(*dst_alloc_size == 0 || *dst); + + if (src_size <= 8) + return -EBADMSG; + + size = unaligned_read_le64(src); + if (size < 0 || (unsigned) size != unaligned_read_le64(src)) + return -EFBIG; + if ((size_t) size > *dst_alloc_size) { + out = realloc(*dst, size); + if (!out) + return -ENOMEM; + *dst = out; + *dst_alloc_size = size; + } else + out = *dst; + + r = LZ4_decompress_safe((char*)src + 8, out, src_size - 8, size); + if (r < 0 || r != size) + return -EBADMSG; + + *dst_size = size; + return 0; +#else + return -EPROTONOSUPPORT; +#endif +} + +int decompress_blob(int compression, + const void *src, uint64_t src_size, + void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max) { + if (compression == OBJECT_COMPRESSED_XZ) + return decompress_blob_xz(src, src_size, + dst, dst_alloc_size, dst_size, dst_max); + else if (compression == OBJECT_COMPRESSED_LZ4) + return decompress_blob_lz4(src, src_size, + dst, dst_alloc_size, dst_size, dst_max); + else + return -EBADMSG; +} + +int decompress_startswith_xz(const void *src, uint64_t src_size, + void **buffer, size_t *buffer_size, + const void *prefix, size_t prefix_len, + uint8_t extra) { + +#if HAVE_XZ + _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; + lzma_ret ret; + + /* Checks whether the decompressed blob starts with the + * mentioned prefix. The byte extra needs to follow the + * prefix */ + + assert(src); + assert(src_size > 0); + assert(buffer); + assert(buffer_size); + assert(prefix); + assert(*buffer_size == 0 || *buffer); + + ret = lzma_stream_decoder(&s, UINT64_MAX, 0); + if (ret != LZMA_OK) + return -EBADMSG; + + if (!(greedy_realloc(buffer, buffer_size, ALIGN_8(prefix_len + 1), 1))) + return -ENOMEM; + + s.next_in = src; + s.avail_in = src_size; + + s.next_out = *buffer; + s.avail_out = *buffer_size; + + for (;;) { + ret = lzma_code(&s, LZMA_FINISH); + + if (!IN_SET(ret, LZMA_OK, LZMA_STREAM_END)) + return -EBADMSG; + + if (*buffer_size - s.avail_out >= prefix_len + 1) + return memcmp(*buffer, prefix, prefix_len) == 0 && + ((const uint8_t*) *buffer)[prefix_len] == extra; + + if (ret == LZMA_STREAM_END) + return 0; + + s.avail_out += *buffer_size; + + if (!(greedy_realloc(buffer, buffer_size, *buffer_size * 2, 1))) + return -ENOMEM; + + s.next_out = *(uint8_t**)buffer + *buffer_size - s.avail_out; + } + +#else + return -EPROTONOSUPPORT; +#endif +} + +int decompress_startswith_lz4(const void *src, uint64_t src_size, + void **buffer, size_t *buffer_size, + const void *prefix, size_t prefix_len, + uint8_t extra) { +#if HAVE_LZ4 + /* Checks whether the decompressed blob starts with the + * mentioned prefix. The byte extra needs to follow the + * prefix */ + + int r; + + assert(src); + assert(src_size > 0); + assert(buffer); + assert(buffer_size); + assert(prefix); + assert(*buffer_size == 0 || *buffer); + + if (src_size <= 8) + return -EBADMSG; + + if (!(greedy_realloc(buffer, buffer_size, ALIGN_8(prefix_len + 1), 1))) + return -ENOMEM; + + r = LZ4_decompress_safe_partial((char*)src + 8, *buffer, src_size - 8, + prefix_len + 1, *buffer_size); + /* One lz4 < 1.8.3, we might get "failure" (r < 0), or "success" where + * just a part of the buffer is decompressed. But if we get a smaller + * amount of bytes than requested, we don't know whether there isn't enough + * data to fill the requested size or whether we just got a partial answer. + */ + if (r < 0 || (size_t) r < prefix_len + 1) { + size_t size; + + if (LZ4_versionNumber() >= 10803) + /* We trust that the newer lz4 decompresses the number of bytes we + * requested if available in the compressed string. */ + return 0; + + if (r > 0) + /* Compare what we have first, in case of mismatch we can + * shortcut the full comparison. */ + if (memcmp(*buffer, prefix, r) != 0) + return 0; + + /* Before version 1.8.3, lz4 always tries to decode full a "sequence", + * so in pathological cases might need to decompress the full field. */ + r = decompress_blob_lz4(src, src_size, buffer, buffer_size, &size, 0); + if (r < 0) + return r; + + if (size < prefix_len + 1) + return 0; + } + + return memcmp(*buffer, prefix, prefix_len) == 0 && + ((const uint8_t*) *buffer)[prefix_len] == extra; +#else + return -EPROTONOSUPPORT; +#endif +} + +int decompress_startswith(int compression, + const void *src, uint64_t src_size, + void **buffer, size_t *buffer_size, + const void *prefix, size_t prefix_len, + uint8_t extra) { + if (compression == OBJECT_COMPRESSED_XZ) + return decompress_startswith_xz(src, src_size, + buffer, buffer_size, + prefix, prefix_len, + extra); + else if (compression == OBJECT_COMPRESSED_LZ4) + return decompress_startswith_lz4(src, src_size, + buffer, buffer_size, + prefix, prefix_len, + extra); + else + return -EBADMSG; +} + +int compress_stream_xz(int fdf, int fdt, uint64_t max_bytes) { +#if HAVE_XZ + _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; + lzma_ret ret; + uint8_t buf[BUFSIZ], out[BUFSIZ]; + lzma_action action = LZMA_RUN; + + assert(fdf >= 0); + assert(fdt >= 0); + + ret = lzma_easy_encoder(&s, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64); + if (ret != LZMA_OK) { + log_error("Failed to initialize XZ encoder: code %u", ret); + return -EINVAL; + } + + for (;;) { + if (s.avail_in == 0 && action == LZMA_RUN) { + size_t m = sizeof(buf); + ssize_t n; + + if (max_bytes != (uint64_t) -1 && (uint64_t) m > max_bytes) + m = (size_t) max_bytes; + + n = read(fdf, buf, m); + if (n < 0) + return -errno; + if (n == 0) + action = LZMA_FINISH; + else { + s.next_in = buf; + s.avail_in = n; + + if (max_bytes != (uint64_t) -1) { + assert(max_bytes >= (uint64_t) n); + max_bytes -= n; + } + } + } + + if (s.avail_out == 0) { + s.next_out = out; + s.avail_out = sizeof(out); + } + + ret = lzma_code(&s, action); + if (!IN_SET(ret, LZMA_OK, LZMA_STREAM_END)) { + log_error("Compression failed: code %u", ret); + return -EBADMSG; + } + + if (s.avail_out == 0 || ret == LZMA_STREAM_END) { + ssize_t n, k; + + n = sizeof(out) - s.avail_out; + + k = loop_write(fdt, out, n, false); + if (k < 0) + return k; + + if (ret == LZMA_STREAM_END) { + log_debug("XZ compression finished (%"PRIu64" -> %"PRIu64" bytes, %.1f%%)", + s.total_in, s.total_out, + (double) s.total_out / s.total_in * 100); + + return 0; + } + } + } +#else + return -EPROTONOSUPPORT; +#endif +} + +#define LZ4_BUFSIZE (512*1024u) + +int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes) { + +#if HAVE_LZ4 + LZ4F_errorCode_t c; + _cleanup_(LZ4F_freeCompressionContextp) LZ4F_compressionContext_t ctx = NULL; + _cleanup_free_ char *buf = NULL; + char *src = NULL; + size_t size, n, total_in = 0, total_out, offset = 0, frame_size; + struct stat st; + int r; + static const LZ4F_compressOptions_t options = { + .stableSrc = 1, + }; + static const LZ4F_preferences_t preferences = { + .frameInfo.blockSizeID = 5, + }; + + c = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION); + if (LZ4F_isError(c)) + return -ENOMEM; + + if (fstat(fdf, &st) < 0) + return log_debug_errno(errno, "fstat() failed: %m"); + + frame_size = LZ4F_compressBound(LZ4_BUFSIZE, &preferences); + size = frame_size + 64*1024; /* add some space for header and trailer */ + buf = malloc(size); + if (!buf) + return -ENOMEM; + + n = offset = total_out = LZ4F_compressBegin(ctx, buf, size, &preferences); + if (LZ4F_isError(n)) + return -EINVAL; + + src = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fdf, 0); + if (src == MAP_FAILED) + return -errno; + + log_debug("Buffer size is %zu bytes, header size %zu bytes.", size, n); + + while (total_in < (size_t) st.st_size) { + ssize_t k; + + k = MIN(LZ4_BUFSIZE, st.st_size - total_in); + n = LZ4F_compressUpdate(ctx, buf + offset, size - offset, + src + total_in, k, &options); + if (LZ4F_isError(n)) { + r = -ENOTRECOVERABLE; + goto cleanup; + } + + total_in += k; + offset += n; + total_out += n; + + if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) { + log_debug("Compressed stream longer than %"PRIu64" bytes", max_bytes); + return -EFBIG; + } + + if (size - offset < frame_size + 4) { + k = loop_write(fdt, buf, offset, false); + if (k < 0) { + r = k; + goto cleanup; + } + offset = 0; + } + } + + n = LZ4F_compressEnd(ctx, buf + offset, size - offset, &options); + if (LZ4F_isError(n)) { + r = -ENOTRECOVERABLE; + goto cleanup; + } + + offset += n; + total_out += n; + r = loop_write(fdt, buf, offset, false); + if (r < 0) + goto cleanup; + + log_debug("LZ4 compression finished (%zu -> %zu bytes, %.1f%%)", + total_in, total_out, + (double) total_out / total_in * 100); + cleanup: + munmap(src, st.st_size); + return r; +#else + return -EPROTONOSUPPORT; +#endif +} + +int decompress_stream_xz(int fdf, int fdt, uint64_t max_bytes) { + +#if HAVE_XZ + _cleanup_(lzma_end) lzma_stream s = LZMA_STREAM_INIT; + lzma_ret ret; + + uint8_t buf[BUFSIZ], out[BUFSIZ]; + lzma_action action = LZMA_RUN; + + assert(fdf >= 0); + assert(fdt >= 0); + + ret = lzma_stream_decoder(&s, UINT64_MAX, 0); + if (ret != LZMA_OK) { + log_debug("Failed to initialize XZ decoder: code %u", ret); + return -ENOMEM; + } + + for (;;) { + if (s.avail_in == 0 && action == LZMA_RUN) { + ssize_t n; + + n = read(fdf, buf, sizeof(buf)); + if (n < 0) + return -errno; + if (n == 0) + action = LZMA_FINISH; + else { + s.next_in = buf; + s.avail_in = n; + } + } + + if (s.avail_out == 0) { + s.next_out = out; + s.avail_out = sizeof(out); + } + + ret = lzma_code(&s, action); + if (!IN_SET(ret, LZMA_OK, LZMA_STREAM_END)) { + log_debug("Decompression failed: code %u", ret); + return -EBADMSG; + } + + if (s.avail_out == 0 || ret == LZMA_STREAM_END) { + ssize_t n, k; + + n = sizeof(out) - s.avail_out; + + if (max_bytes != (uint64_t) -1) { + if (max_bytes < (uint64_t) n) + return -EFBIG; + + max_bytes -= n; + } + + k = loop_write(fdt, out, n, false); + if (k < 0) + return k; + + if (ret == LZMA_STREAM_END) { + log_debug("XZ decompression finished (%"PRIu64" -> %"PRIu64" bytes, %.1f%%)", + s.total_in, s.total_out, + (double) s.total_out / s.total_in * 100); + + return 0; + } + } + } +#else + log_debug("Cannot decompress file. Compiled without XZ support."); + return -EPROTONOSUPPORT; +#endif +} + +int decompress_stream_lz4(int in, int out, uint64_t max_bytes) { +#if HAVE_LZ4 + size_t c; + _cleanup_(LZ4F_freeDecompressionContextp) LZ4F_decompressionContext_t ctx = NULL; + _cleanup_free_ char *buf = NULL; + char *src; + struct stat st; + int r = 0; + size_t total_in = 0, total_out = 0; + + c = LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION); + if (LZ4F_isError(c)) + return -ENOMEM; + + if (fstat(in, &st) < 0) + return log_debug_errno(errno, "fstat() failed: %m"); + + buf = malloc(LZ4_BUFSIZE); + if (!buf) + return -ENOMEM; + + src = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, in, 0); + if (src == MAP_FAILED) + return -errno; + + while (total_in < (size_t) st.st_size) { + size_t produced = LZ4_BUFSIZE; + size_t used = st.st_size - total_in; + + c = LZ4F_decompress(ctx, buf, &produced, src + total_in, &used, NULL); + if (LZ4F_isError(c)) { + r = -EBADMSG; + goto cleanup; + } + + total_in += used; + total_out += produced; + + if (max_bytes != (uint64_t) -1 && total_out > (size_t) max_bytes) { + log_debug("Decompressed stream longer than %"PRIu64" bytes", max_bytes); + r = -EFBIG; + goto cleanup; + } + + r = loop_write(out, buf, produced, false); + if (r < 0) + goto cleanup; + } + + log_debug("LZ4 decompression finished (%zu -> %zu bytes, %.1f%%)", + total_in, total_out, + total_in > 0 ? (double) total_out / total_in * 100 : 0.0); + cleanup: + munmap(src, st.st_size); + return r; +#else + log_debug("Cannot decompress file. Compiled without LZ4 support."); + return -EPROTONOSUPPORT; +#endif +} + +int decompress_stream(const char *filename, int fdf, int fdt, uint64_t max_bytes) { + + if (endswith(filename, ".lz4")) + return decompress_stream_lz4(fdf, fdt, max_bytes); + else if (endswith(filename, ".xz")) + return decompress_stream_xz(fdf, fdt, max_bytes); + else + return -EPROTONOSUPPORT; +} diff --git a/src/journal/compress.h b/src/journal/compress.h new file mode 100644 index 00000000..56411484 --- /dev/null +++ b/src/journal/compress.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "journal-def.h" + +const char* object_compressed_to_string(int compression); +int object_compressed_from_string(const char *compression); + +int compress_blob_xz(const void *src, uint64_t src_size, + void *dst, size_t dst_alloc_size, size_t *dst_size); +int compress_blob_lz4(const void *src, uint64_t src_size, + void *dst, size_t dst_alloc_size, size_t *dst_size); + +static inline int compress_blob(const void *src, uint64_t src_size, + void *dst, size_t dst_alloc_size, size_t *dst_size) { + int r; +#if HAVE_LZ4 + r = compress_blob_lz4(src, src_size, dst, dst_alloc_size, dst_size); + if (r == 0) + return OBJECT_COMPRESSED_LZ4; +#else + r = compress_blob_xz(src, src_size, dst, dst_alloc_size, dst_size); + if (r == 0) + return OBJECT_COMPRESSED_XZ; +#endif + return r; +} + +int decompress_blob_xz(const void *src, uint64_t src_size, + void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); +int decompress_blob_lz4(const void *src, uint64_t src_size, + void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); +int decompress_blob(int compression, + const void *src, uint64_t src_size, + void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); + +int decompress_startswith_xz(const void *src, uint64_t src_size, + void **buffer, size_t *buffer_size, + const void *prefix, size_t prefix_len, + uint8_t extra); +int decompress_startswith_lz4(const void *src, uint64_t src_size, + void **buffer, size_t *buffer_size, + const void *prefix, size_t prefix_len, + uint8_t extra); +int decompress_startswith(int compression, + const void *src, uint64_t src_size, + void **buffer, size_t *buffer_size, + const void *prefix, size_t prefix_len, + uint8_t extra); + +int compress_stream_xz(int fdf, int fdt, uint64_t max_bytes); +int compress_stream_lz4(int fdf, int fdt, uint64_t max_bytes); + +int decompress_stream_xz(int fdf, int fdt, uint64_t max_size); +int decompress_stream_lz4(int fdf, int fdt, uint64_t max_size); + +#if HAVE_LZ4 +# define compress_stream compress_stream_lz4 +# define COMPRESSED_EXT ".lz4" +#else +# define compress_stream compress_stream_xz +# define COMPRESSED_EXT ".xz" +#endif + +int decompress_stream(const char *filename, int fdf, int fdt, uint64_t max_bytes); diff --git a/src/journal/fsprg.c b/src/journal/fsprg.c new file mode 100644 index 00000000..1dda2149 --- /dev/null +++ b/src/journal/fsprg.c @@ -0,0 +1,378 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * + * fsprg v0.1 - (seekable) forward-secure pseudorandom generator + * Copyright © 2012 B. Poettering + * Contact: fsprg@point-at-infinity.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +/* + * See "Practical Secure Logging: Seekable Sequential Key Generators" + * by G. A. Marson, B. Poettering for details: + * + * http://eprint.iacr.org/2013/397 + */ + +#include + +#include "fsprg.h" +#include "gcrypt-util.h" +#include "memory-util.h" + +#define ISVALID_SECPAR(secpar) (((secpar) % 16 == 0) && ((secpar) >= 16) && ((secpar) <= 16384)) +#define VALIDATE_SECPAR(secpar) assert(ISVALID_SECPAR(secpar)); + +#define RND_HASH GCRY_MD_SHA256 +#define RND_GEN_P 0x01 +#define RND_GEN_Q 0x02 +#define RND_GEN_X 0x03 + +#pragma GCC diagnostic ignored "-Wpointer-arith" +/* TODO: remove void* arithmetic and this work-around */ + +/******************************************************************************/ + +static void mpi_export(void *buf, size_t buflen, const gcry_mpi_t x) { + unsigned len; + size_t nwritten; + + assert(gcry_mpi_cmp_ui(x, 0) >= 0); + len = (gcry_mpi_get_nbits(x) + 7) / 8; + assert(len <= buflen); + memzero(buf, buflen); + gcry_mpi_print(GCRYMPI_FMT_USG, buf + (buflen - len), len, &nwritten, x); + assert(nwritten == len); +} + +static gcry_mpi_t mpi_import(const void *buf, size_t buflen) { + gcry_mpi_t h; + unsigned len; + + assert_se(gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL) == 0); + len = (gcry_mpi_get_nbits(h) + 7) / 8; + assert(len <= buflen); + assert(gcry_mpi_cmp_ui(h, 0) >= 0); + + return h; +} + +static void uint64_export(void *buf, size_t buflen, uint64_t x) { + assert(buflen == 8); + ((uint8_t*) buf)[0] = (x >> 56) & 0xff; + ((uint8_t*) buf)[1] = (x >> 48) & 0xff; + ((uint8_t*) buf)[2] = (x >> 40) & 0xff; + ((uint8_t*) buf)[3] = (x >> 32) & 0xff; + ((uint8_t*) buf)[4] = (x >> 24) & 0xff; + ((uint8_t*) buf)[5] = (x >> 16) & 0xff; + ((uint8_t*) buf)[6] = (x >> 8) & 0xff; + ((uint8_t*) buf)[7] = (x >> 0) & 0xff; +} + +_pure_ static uint64_t uint64_import(const void *buf, size_t buflen) { + assert(buflen == 8); + return + (uint64_t)(((uint8_t*) buf)[0]) << 56 | + (uint64_t)(((uint8_t*) buf)[1]) << 48 | + (uint64_t)(((uint8_t*) buf)[2]) << 40 | + (uint64_t)(((uint8_t*) buf)[3]) << 32 | + (uint64_t)(((uint8_t*) buf)[4]) << 24 | + (uint64_t)(((uint8_t*) buf)[5]) << 16 | + (uint64_t)(((uint8_t*) buf)[6]) << 8 | + (uint64_t)(((uint8_t*) buf)[7]) << 0; +} + +/* deterministically generate from seed/idx a string of buflen pseudorandom bytes */ +static void det_randomize(void *buf, size_t buflen, const void *seed, size_t seedlen, uint32_t idx) { + gcry_md_hd_t hd, hd2; + size_t olen, cpylen; + uint32_t ctr; + + olen = gcry_md_get_algo_dlen(RND_HASH); + gcry_md_open(&hd, RND_HASH, 0); + gcry_md_write(hd, seed, seedlen); + gcry_md_putc(hd, (idx >> 24) & 0xff); + gcry_md_putc(hd, (idx >> 16) & 0xff); + gcry_md_putc(hd, (idx >> 8) & 0xff); + gcry_md_putc(hd, (idx >> 0) & 0xff); + + for (ctr = 0; buflen; ctr++) { + gcry_md_copy(&hd2, hd); + gcry_md_putc(hd2, (ctr >> 24) & 0xff); + gcry_md_putc(hd2, (ctr >> 16) & 0xff); + gcry_md_putc(hd2, (ctr >> 8) & 0xff); + gcry_md_putc(hd2, (ctr >> 0) & 0xff); + gcry_md_final(hd2); + cpylen = (buflen < olen) ? buflen : olen; + memcpy(buf, gcry_md_read(hd2, RND_HASH), cpylen); + gcry_md_close(hd2); + buf += cpylen; + buflen -= cpylen; + } + gcry_md_close(hd); +} + +/* deterministically generate from seed/idx a prime of length `bits' that is 3 (mod 4) */ +static gcry_mpi_t genprime3mod4(int bits, const void *seed, size_t seedlen, uint32_t idx) { + size_t buflen = bits / 8; + uint8_t buf[buflen]; + gcry_mpi_t p; + + assert(bits % 8 == 0); + assert(buflen > 0); + + det_randomize(buf, buflen, seed, seedlen, idx); + buf[0] |= 0xc0; /* set upper two bits, so that n=pq has maximum size */ + buf[buflen - 1] |= 0x03; /* set lower two bits, to have result 3 (mod 4) */ + + p = mpi_import(buf, buflen); + while (gcry_prime_check(p, 0)) + gcry_mpi_add_ui(p, p, 4); + + return p; +} + +/* deterministically generate from seed/idx a quadratic residue (mod n) */ +static gcry_mpi_t gensquare(const gcry_mpi_t n, const void *seed, size_t seedlen, uint32_t idx, unsigned secpar) { + size_t buflen = secpar / 8; + uint8_t buf[buflen]; + gcry_mpi_t x; + + det_randomize(buf, buflen, seed, seedlen, idx); + buf[0] &= 0x7f; /* clear upper bit, so that we have x < n */ + x = mpi_import(buf, buflen); + assert(gcry_mpi_cmp(x, n) < 0); + gcry_mpi_mulm(x, x, x, n); + return x; +} + +/* compute 2^m (mod phi(p)), for a prime p */ +static gcry_mpi_t twopowmodphi(uint64_t m, const gcry_mpi_t p) { + gcry_mpi_t phi, r; + int n; + + phi = gcry_mpi_new(0); + gcry_mpi_sub_ui(phi, p, 1); + + /* count number of used bits in m */ + for (n = 0; (1ULL << n) <= m; n++) + ; + + r = gcry_mpi_new(0); + gcry_mpi_set_ui(r, 1); + while (n) { /* square and multiply algorithm for fast exponentiation */ + n--; + gcry_mpi_mulm(r, r, r, phi); + if (m & ((uint64_t)1 << n)) { + gcry_mpi_add(r, r, r); + if (gcry_mpi_cmp(r, phi) >= 0) + gcry_mpi_sub(r, r, phi); + } + } + + gcry_mpi_release(phi); + return r; +} + +/* Decompose $x \in Z_n$ into $(xp,xq) \in Z_p \times Z_q$ using Chinese Remainder Theorem */ +static void CRT_decompose(gcry_mpi_t *xp, gcry_mpi_t *xq, const gcry_mpi_t x, const gcry_mpi_t p, const gcry_mpi_t q) { + *xp = gcry_mpi_new(0); + *xq = gcry_mpi_new(0); + gcry_mpi_mod(*xp, x, p); + gcry_mpi_mod(*xq, x, q); +} + +/* Compose $(xp,xq) \in Z_p \times Z_q$ into $x \in Z_n$ using Chinese Remainder Theorem */ +static void CRT_compose(gcry_mpi_t *x, const gcry_mpi_t xp, const gcry_mpi_t xq, const gcry_mpi_t p, const gcry_mpi_t q) { + gcry_mpi_t a, u; + + a = gcry_mpi_new(0); + u = gcry_mpi_new(0); + *x = gcry_mpi_new(0); + gcry_mpi_subm(a, xq, xp, q); + gcry_mpi_invm(u, p, q); + gcry_mpi_mulm(a, a, u, q); /* a = (xq - xp) / p (mod q) */ + gcry_mpi_mul(*x, p, a); + gcry_mpi_add(*x, *x, xp); /* x = p * ((xq - xp) / p mod q) + xp */ + gcry_mpi_release(a); + gcry_mpi_release(u); +} + +/******************************************************************************/ + +size_t FSPRG_mskinbytes(unsigned _secpar) { + VALIDATE_SECPAR(_secpar); + return 2 + 2 * (_secpar / 2) / 8; /* to store header,p,q */ +} + +size_t FSPRG_mpkinbytes(unsigned _secpar) { + VALIDATE_SECPAR(_secpar); + return 2 + _secpar / 8; /* to store header,n */ +} + +size_t FSPRG_stateinbytes(unsigned _secpar) { + VALIDATE_SECPAR(_secpar); + return 2 + 2 * _secpar / 8 + 8; /* to store header,n,x,epoch */ +} + +static void store_secpar(void *buf, uint16_t secpar) { + secpar = secpar / 16 - 1; + ((uint8_t*) buf)[0] = (secpar >> 8) & 0xff; + ((uint8_t*) buf)[1] = (secpar >> 0) & 0xff; +} + +static uint16_t read_secpar(const void *buf) { + uint16_t secpar; + secpar = + (uint16_t)(((uint8_t*) buf)[0]) << 8 | + (uint16_t)(((uint8_t*) buf)[1]) << 0; + return 16 * (secpar + 1); +} + +void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned _secpar) { + uint8_t iseed[FSPRG_RECOMMENDED_SEEDLEN]; + gcry_mpi_t n, p, q; + uint16_t secpar; + + VALIDATE_SECPAR(_secpar); + secpar = _secpar; + + initialize_libgcrypt(false); + + if (!seed) { + gcry_randomize(iseed, FSPRG_RECOMMENDED_SEEDLEN, GCRY_STRONG_RANDOM); + seed = iseed; + seedlen = FSPRG_RECOMMENDED_SEEDLEN; + } + + p = genprime3mod4(secpar / 2, seed, seedlen, RND_GEN_P); + q = genprime3mod4(secpar / 2, seed, seedlen, RND_GEN_Q); + + if (msk) { + store_secpar(msk + 0, secpar); + mpi_export(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8, p); + mpi_export(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8, q); + } + + if (mpk) { + n = gcry_mpi_new(0); + gcry_mpi_mul(n, p, q); + assert(gcry_mpi_get_nbits(n) == secpar); + + store_secpar(mpk + 0, secpar); + mpi_export(mpk + 2, secpar / 8, n); + + gcry_mpi_release(n); + } + + gcry_mpi_release(p); + gcry_mpi_release(q); +} + +void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen) { + gcry_mpi_t n, x; + uint16_t secpar; + + initialize_libgcrypt(false); + + secpar = read_secpar(mpk + 0); + n = mpi_import(mpk + 2, secpar / 8); + x = gensquare(n, seed, seedlen, RND_GEN_X, secpar); + + memcpy(state, mpk, 2 + secpar / 8); + mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x); + memzero(state + 2 + 2 * secpar / 8, 8); + + gcry_mpi_release(n); + gcry_mpi_release(x); +} + +void FSPRG_Evolve(void *state) { + gcry_mpi_t n, x; + uint16_t secpar; + uint64_t epoch; + + initialize_libgcrypt(false); + + secpar = read_secpar(state + 0); + n = mpi_import(state + 2 + 0 * secpar / 8, secpar / 8); + x = mpi_import(state + 2 + 1 * secpar / 8, secpar / 8); + epoch = uint64_import(state + 2 + 2 * secpar / 8, 8); + + gcry_mpi_mulm(x, x, x, n); + epoch++; + + mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, x); + uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); + + gcry_mpi_release(n); + gcry_mpi_release(x); +} + +uint64_t FSPRG_GetEpoch(const void *state) { + uint16_t secpar; + secpar = read_secpar(state + 0); + return uint64_import(state + 2 + 2 * secpar / 8, 8); +} + +void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen) { + gcry_mpi_t p, q, n, x, xp, xq, kp, kq, xm; + uint16_t secpar; + + initialize_libgcrypt(false); + + secpar = read_secpar(msk + 0); + p = mpi_import(msk + 2 + 0 * (secpar / 2) / 8, (secpar / 2) / 8); + q = mpi_import(msk + 2 + 1 * (secpar / 2) / 8, (secpar / 2) / 8); + + n = gcry_mpi_new(0); + gcry_mpi_mul(n, p, q); + + x = gensquare(n, seed, seedlen, RND_GEN_X, secpar); + CRT_decompose(&xp, &xq, x, p, q); /* split (mod n) into (mod p) and (mod q) using CRT */ + + kp = twopowmodphi(epoch, p); /* compute 2^epoch (mod phi(p)) */ + kq = twopowmodphi(epoch, q); /* compute 2^epoch (mod phi(q)) */ + + gcry_mpi_powm(xp, xp, kp, p); /* compute x^(2^epoch) (mod p) */ + gcry_mpi_powm(xq, xq, kq, q); /* compute x^(2^epoch) (mod q) */ + + CRT_compose(&xm, xp, xq, p, q); /* combine (mod p) and (mod q) to (mod n) using CRT */ + + store_secpar(state + 0, secpar); + mpi_export(state + 2 + 0 * secpar / 8, secpar / 8, n); + mpi_export(state + 2 + 1 * secpar / 8, secpar / 8, xm); + uint64_export(state + 2 + 2 * secpar / 8, 8, epoch); + + gcry_mpi_release(p); + gcry_mpi_release(q); + gcry_mpi_release(n); + gcry_mpi_release(x); + gcry_mpi_release(xp); + gcry_mpi_release(xq); + gcry_mpi_release(kp); + gcry_mpi_release(kq); + gcry_mpi_release(xm); +} + +void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx) { + uint16_t secpar; + + initialize_libgcrypt(false); + + secpar = read_secpar(state + 0); + det_randomize(key, keylen, state + 2, 2 * secpar / 8 + 8, idx); +} diff --git a/src/journal/fsprg.h b/src/journal/fsprg.h new file mode 100644 index 00000000..33412675 --- /dev/null +++ b/src/journal/fsprg.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/* + * fsprg v0.1 - (seekable) forward-secure pseudorandom generator + * Copyright © 2012 B. Poettering + * Contact: fsprg@point-at-infinity.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include + +#include "macro.h" +#include "util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FSPRG_RECOMMENDED_SECPAR 1536 +#define FSPRG_RECOMMENDED_SEEDLEN (96/8) + +size_t FSPRG_mskinbytes(unsigned secpar) _const_; +size_t FSPRG_mpkinbytes(unsigned secpar) _const_; +size_t FSPRG_stateinbytes(unsigned secpar) _const_; + +/* Setup msk and mpk. Providing seed != NULL makes this algorithm deterministic. */ +void FSPRG_GenMK(void *msk, void *mpk, const void *seed, size_t seedlen, unsigned secpar); + +/* Initialize state deterministically in dependence on seed. */ +/* Note: in case one wants to run only one GenState0 per GenMK it is safe to use + the same seed for both GenMK and GenState0. +*/ +void FSPRG_GenState0(void *state, const void *mpk, const void *seed, size_t seedlen); + +void FSPRG_Evolve(void *state); + +uint64_t FSPRG_GetEpoch(const void *state) _pure_; + +/* Seek to any arbitrary state (by providing msk together with seed from GenState0). */ +void FSPRG_Seek(void *state, uint64_t epoch, const void *msk, const void *seed, size_t seedlen); + +void FSPRG_GetKey(const void *state, void *key, size_t keylen, uint32_t idx); + +#ifdef __cplusplus +} +#endif diff --git a/src/journal/generate-audit_type-list.sh b/src/journal/generate-audit_type-list.sh new file mode 100755 index 00000000..912d0c99 --- /dev/null +++ b/src/journal/generate-audit_type-list.sh @@ -0,0 +1,15 @@ +#!/bin/sh +set -eu + +cpp="$1" +shift + +includes="" +for i in "$@"; do + includes="$includes -include $i" +done + +$cpp -dM $includes -
+#include + +#include "fd-util.h" +#include "fsprg.h" +#include "gcrypt-util.h" +#include "hexdecoct.h" +#include "journal-authenticate.h" +#include "journal-def.h" +#include "journal-file.h" +#include "memory-util.h" +#include "time-util.h" + +static uint64_t journal_file_tag_seqnum(JournalFile *f) { + uint64_t r; + + assert(f); + + r = le64toh(f->header->n_tags) + 1; + f->header->n_tags = htole64(r); + + return r; +} + +int journal_file_append_tag(JournalFile *f) { + Object *o; + uint64_t p; + int r; + + assert(f); + + if (!f->seal) + return 0; + + if (!f->hmac_running) + return 0; + + assert(f->hmac); + + r = journal_file_append_object(f, OBJECT_TAG, sizeof(struct TagObject), &o, &p); + if (r < 0) + return r; + + o->tag.seqnum = htole64(journal_file_tag_seqnum(f)); + o->tag.epoch = htole64(FSPRG_GetEpoch(f->fsprg_state)); + + log_debug("Writing tag %"PRIu64" for epoch %"PRIu64"", + le64toh(o->tag.seqnum), + FSPRG_GetEpoch(f->fsprg_state)); + + /* Add the tag object itself, so that we can protect its + * header. This will exclude the actual hash value in it */ + r = journal_file_hmac_put_object(f, OBJECT_TAG, o, p); + if (r < 0) + return r; + + /* Get the HMAC tag and store it in the object */ + memcpy(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH); + f->hmac_running = false; + + return 0; +} + +int journal_file_hmac_start(JournalFile *f) { + uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */ + assert(f); + + if (!f->seal) + return 0; + + if (f->hmac_running) + return 0; + + /* Prepare HMAC for next cycle */ + gcry_md_reset(f->hmac); + FSPRG_GetKey(f->fsprg_state, key, sizeof(key), 0); + gcry_md_setkey(f->hmac, key, sizeof(key)); + + f->hmac_running = true; + + return 0; +} + +static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *epoch) { + uint64_t t; + + assert(f); + assert(epoch); + assert(f->seal); + + if (f->fss_start_usec == 0 || + f->fss_interval_usec == 0) + return -EOPNOTSUPP; + + if (realtime < f->fss_start_usec) + return -ESTALE; + + t = realtime - f->fss_start_usec; + t = t / f->fss_interval_usec; + + *epoch = t; + return 0; +} + +static int journal_file_fsprg_need_evolve(JournalFile *f, uint64_t realtime) { + uint64_t goal, epoch; + int r; + assert(f); + + if (!f->seal) + return 0; + + r = journal_file_get_epoch(f, realtime, &goal); + if (r < 0) + return r; + + epoch = FSPRG_GetEpoch(f->fsprg_state); + if (epoch > goal) + return -ESTALE; + + return epoch != goal; +} + +int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) { + uint64_t goal, epoch; + int r; + + assert(f); + + if (!f->seal) + return 0; + + r = journal_file_get_epoch(f, realtime, &goal); + if (r < 0) + return r; + + epoch = FSPRG_GetEpoch(f->fsprg_state); + if (epoch < goal) + log_debug("Evolving FSPRG key from epoch %"PRIu64" to %"PRIu64".", epoch, goal); + + for (;;) { + if (epoch > goal) + return -ESTALE; + if (epoch == goal) + return 0; + + FSPRG_Evolve(f->fsprg_state); + epoch = FSPRG_GetEpoch(f->fsprg_state); + } +} + +int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) { + void *msk; + uint64_t epoch; + + assert(f); + + if (!f->seal) + return 0; + + assert(f->fsprg_seed); + + if (f->fsprg_state) { + /* Cheaper... */ + + epoch = FSPRG_GetEpoch(f->fsprg_state); + if (goal == epoch) + return 0; + + if (goal == epoch+1) { + FSPRG_Evolve(f->fsprg_state); + return 0; + } + } else { + f->fsprg_state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR); + f->fsprg_state = malloc(f->fsprg_state_size); + + if (!f->fsprg_state) + return -ENOMEM; + } + + log_debug("Seeking FSPRG key to %"PRIu64".", goal); + + msk = alloca(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR)); + FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR); + FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size); + return 0; +} + +int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) { + int r; + + assert(f); + + if (!f->seal) + return 0; + + if (realtime <= 0) + realtime = now(CLOCK_REALTIME); + + r = journal_file_fsprg_need_evolve(f, realtime); + if (r <= 0) + return 0; + + r = journal_file_append_tag(f); + if (r < 0) + return r; + + r = journal_file_fsprg_evolve(f, realtime); + if (r < 0) + return r; + + return 0; +} + +int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p) { + int r; + + assert(f); + + if (!f->seal) + return 0; + + r = journal_file_hmac_start(f); + if (r < 0) + return r; + + if (!o) { + r = journal_file_move_to_object(f, type, p, &o); + if (r < 0) + return r; + } else { + if (type > OBJECT_UNUSED && o->object.type != type) + return -EBADMSG; + } + + gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload)); + + switch (o->object.type) { + + case OBJECT_DATA: + /* All but hash and payload are mutable */ + gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash)); + gcry_md_write(f->hmac, o->data.payload, le64toh(o->object.size) - offsetof(DataObject, payload)); + break; + + case OBJECT_FIELD: + /* Same here */ + gcry_md_write(f->hmac, &o->field.hash, sizeof(o->field.hash)); + gcry_md_write(f->hmac, o->field.payload, le64toh(o->object.size) - offsetof(FieldObject, payload)); + break; + + case OBJECT_ENTRY: + /* All */ + gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(EntryObject, seqnum)); + break; + + case OBJECT_FIELD_HASH_TABLE: + case OBJECT_DATA_HASH_TABLE: + case OBJECT_ENTRY_ARRAY: + /* Nothing: everything is mutable */ + break; + + case OBJECT_TAG: + /* All but the tag itself */ + gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum)); + gcry_md_write(f->hmac, &o->tag.epoch, sizeof(o->tag.epoch)); + break; + default: + return -EINVAL; + } + + return 0; +} + +int journal_file_hmac_put_header(JournalFile *f) { + int r; + + assert(f); + + if (!f->seal) + return 0; + + r = journal_file_hmac_start(f); + if (r < 0) + return r; + + /* All but state+reserved, boot_id, arena_size, + * tail_object_offset, n_objects, n_entries, + * tail_entry_seqnum, head_entry_seqnum, entry_array_offset, + * head_entry_realtime, tail_entry_realtime, + * tail_entry_monotonic, n_data, n_fields, n_tags, + * n_entry_arrays. */ + + gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature)); + gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id)); + gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id)); + gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset)); + + return 0; +} + +int journal_file_fss_load(JournalFile *f) { + int r, fd = -1; + char *p = NULL; + struct stat st; + FSSHeader *m = NULL; + sd_id128_t machine; + + assert(f); + + if (!f->seal) + return 0; + + r = sd_id128_get_machine(&machine); + if (r < 0) + return r; + + if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss", + SD_ID128_FORMAT_VAL(machine)) < 0) + return -ENOMEM; + + fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600); + if (fd < 0) { + if (errno != ENOENT) + log_error_errno(errno, "Failed to open %s: %m", p); + + r = -errno; + goto finish; + } + + if (fstat(fd, &st) < 0) { + r = -errno; + goto finish; + } + + if (st.st_size < (off_t) sizeof(FSSHeader)) { + r = -ENODATA; + goto finish; + } + + m = mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0); + if (m == MAP_FAILED) { + m = NULL; + r = -errno; + goto finish; + } + + if (memcmp(m->signature, FSS_HEADER_SIGNATURE, 8) != 0) { + r = -EBADMSG; + goto finish; + } + + if (m->incompatible_flags != 0) { + r = -EPROTONOSUPPORT; + goto finish; + } + + if (le64toh(m->header_size) < sizeof(FSSHeader)) { + r = -EBADMSG; + goto finish; + } + + if (le64toh(m->fsprg_state_size) != FSPRG_stateinbytes(le16toh(m->fsprg_secpar))) { + r = -EBADMSG; + goto finish; + } + + f->fss_file_size = le64toh(m->header_size) + le64toh(m->fsprg_state_size); + if ((uint64_t) st.st_size < f->fss_file_size) { + r = -ENODATA; + goto finish; + } + + if (!sd_id128_equal(machine, m->machine_id)) { + r = -EHOSTDOWN; + goto finish; + } + + if (le64toh(m->start_usec) <= 0 || + le64toh(m->interval_usec) <= 0) { + r = -EBADMSG; + goto finish; + } + + f->fss_file = mmap(NULL, PAGE_ALIGN(f->fss_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (f->fss_file == MAP_FAILED) { + f->fss_file = NULL; + r = -errno; + goto finish; + } + + f->fss_start_usec = le64toh(f->fss_file->start_usec); + f->fss_interval_usec = le64toh(f->fss_file->interval_usec); + + f->fsprg_state = (uint8_t*) f->fss_file + le64toh(f->fss_file->header_size); + f->fsprg_state_size = le64toh(f->fss_file->fsprg_state_size); + + r = 0; + +finish: + if (m) + munmap(m, PAGE_ALIGN(sizeof(FSSHeader))); + + safe_close(fd); + free(p); + + return r; +} + +int journal_file_hmac_setup(JournalFile *f) { + gcry_error_t e; + + if (!f->seal) + return 0; + + initialize_libgcrypt(true); + + e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); + if (e != 0) + return -EOPNOTSUPP; + + return 0; +} + +int journal_file_append_first_tag(JournalFile *f) { + int r; + uint64_t p; + + if (!f->seal) + return 0; + + log_debug("Calculating first tag..."); + + r = journal_file_hmac_put_header(f); + if (r < 0) + return r; + + p = le64toh(f->header->field_hash_table_offset); + if (p < offsetof(Object, hash_table.items)) + return -EINVAL; + p -= offsetof(Object, hash_table.items); + + r = journal_file_hmac_put_object(f, OBJECT_FIELD_HASH_TABLE, NULL, p); + if (r < 0) + return r; + + p = le64toh(f->header->data_hash_table_offset); + if (p < offsetof(Object, hash_table.items)) + return -EINVAL; + p -= offsetof(Object, hash_table.items); + + r = journal_file_hmac_put_object(f, OBJECT_DATA_HASH_TABLE, NULL, p); + if (r < 0) + return r; + + r = journal_file_append_tag(f); + if (r < 0) + return r; + + return 0; +} + +int journal_file_parse_verification_key(JournalFile *f, const char *key) { + uint8_t *seed; + size_t seed_size, c; + const char *k; + int r; + unsigned long long start, interval; + + seed_size = FSPRG_RECOMMENDED_SEEDLEN; + seed = malloc(seed_size); + if (!seed) + return -ENOMEM; + + k = key; + for (c = 0; c < seed_size; c++) { + int x, y; + + while (*k == '-') + k++; + + x = unhexchar(*k); + if (x < 0) { + free(seed); + return -EINVAL; + } + k++; + y = unhexchar(*k); + if (y < 0) { + free(seed); + return -EINVAL; + } + k++; + + seed[c] = (uint8_t) (x * 16 + y); + } + + if (*k != '/') { + free(seed); + return -EINVAL; + } + k++; + + r = sscanf(k, "%llx-%llx", &start, &interval); + if (r != 2) { + free(seed); + return -EINVAL; + } + + f->fsprg_seed = seed; + f->fsprg_seed_size = seed_size; + + f->fss_start_usec = start * interval; + f->fss_interval_usec = interval; + + return 0; +} + +bool journal_file_next_evolve_usec(JournalFile *f, usec_t *u) { + uint64_t epoch; + + assert(f); + assert(u); + + if (!f->seal) + return false; + + epoch = FSPRG_GetEpoch(f->fsprg_state); + + *u = (usec_t) (f->fss_start_usec + f->fss_interval_usec * epoch + f->fss_interval_usec); + + return true; +} diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h new file mode 100644 index 00000000..2ef01330 --- /dev/null +++ b/src/journal/journal-authenticate.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "journal-file.h" + +int journal_file_append_tag(JournalFile *f); +int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime); +int journal_file_append_first_tag(JournalFile *f); + +int journal_file_hmac_setup(JournalFile *f); +int journal_file_hmac_start(JournalFile *f); +int journal_file_hmac_put_header(JournalFile *f); +int journal_file_hmac_put_object(JournalFile *f, ObjectType type, Object *o, uint64_t p); + +int journal_file_fss_load(JournalFile *f); +int journal_file_parse_verification_key(JournalFile *f, const char *key); + +int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime); +int journal_file_fsprg_seek(JournalFile *f, uint64_t epoch); + +bool journal_file_next_evolve_usec(JournalFile *f, usec_t *u); diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h new file mode 100644 index 00000000..ff4e71a3 --- /dev/null +++ b/src/journal/journal-def.h @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-id128.h" + +#include "macro.h" +#include "sparse-endian.h" + +/* + * If you change this file you probably should also change its documentation: + * + * http://www.freedesktop.org/wiki/Software/systemd/journal-files + */ + +typedef struct Header Header; + +typedef struct ObjectHeader ObjectHeader; +typedef union Object Object; + +typedef struct DataObject DataObject; +typedef struct FieldObject FieldObject; +typedef struct EntryObject EntryObject; +typedef struct HashTableObject HashTableObject; +typedef struct EntryArrayObject EntryArrayObject; +typedef struct TagObject TagObject; + +typedef struct EntryItem EntryItem; +typedef struct HashItem HashItem; + +typedef struct FSSHeader FSSHeader; + +/* Object types */ +typedef enum ObjectType { + OBJECT_UNUSED, /* also serves as "any type" or "additional context" */ + OBJECT_DATA, + OBJECT_FIELD, + OBJECT_ENTRY, + OBJECT_DATA_HASH_TABLE, + OBJECT_FIELD_HASH_TABLE, + OBJECT_ENTRY_ARRAY, + OBJECT_TAG, + _OBJECT_TYPE_MAX +} ObjectType; + +/* Object flags */ +enum { + OBJECT_COMPRESSED_XZ = 1 << 0, + OBJECT_COMPRESSED_LZ4 = 1 << 1, + _OBJECT_COMPRESSED_MAX +}; + +#define OBJECT_COMPRESSION_MASK (OBJECT_COMPRESSED_XZ | OBJECT_COMPRESSED_LZ4) + +struct ObjectHeader { + uint8_t type; + uint8_t flags; + uint8_t reserved[6]; + le64_t size; + uint8_t payload[]; +} _packed_; + +#define DataObject__contents { \ + ObjectHeader object; \ + le64_t hash; \ + le64_t next_hash_offset; \ + le64_t next_field_offset; \ + le64_t entry_offset; /* the first array entry we store inline */ \ + le64_t entry_array_offset; \ + le64_t n_entries; \ + uint8_t payload[]; \ + } + +struct DataObject DataObject__contents; +struct DataObject__packed DataObject__contents _packed_; +assert_cc(sizeof(struct DataObject) == sizeof(struct DataObject__packed)); + +struct FieldObject { + ObjectHeader object; + le64_t hash; + le64_t next_hash_offset; + le64_t head_data_offset; + uint8_t payload[]; +} _packed_; + +struct EntryItem { + le64_t object_offset; + le64_t hash; +} _packed_; + +#define EntryObject__contents { \ + ObjectHeader object; \ + le64_t seqnum; \ + le64_t realtime; \ + le64_t monotonic; \ + sd_id128_t boot_id; \ + le64_t xor_hash; \ + EntryItem items[]; \ + } + +struct EntryObject EntryObject__contents; +struct EntryObject__packed EntryObject__contents _packed_; +assert_cc(sizeof(struct EntryObject) == sizeof(struct EntryObject__packed)); + +struct HashItem { + le64_t head_hash_offset; + le64_t tail_hash_offset; +} _packed_; + +struct HashTableObject { + ObjectHeader object; + HashItem items[]; +} _packed_; + +struct EntryArrayObject { + ObjectHeader object; + le64_t next_entry_array_offset; + le64_t items[]; +} _packed_; + +#define TAG_LENGTH (256/8) + +struct TagObject { + ObjectHeader object; + le64_t seqnum; + le64_t epoch; + uint8_t tag[TAG_LENGTH]; /* SHA-256 HMAC */ +} _packed_; + +union Object { + ObjectHeader object; + DataObject data; + FieldObject field; + EntryObject entry; + HashTableObject hash_table; + EntryArrayObject entry_array; + TagObject tag; +}; + +enum { + STATE_OFFLINE = 0, + STATE_ONLINE = 1, + STATE_ARCHIVED = 2, + _STATE_MAX +}; + +/* Header flags */ +enum { + HEADER_INCOMPATIBLE_COMPRESSED_XZ = 1 << 0, + HEADER_INCOMPATIBLE_COMPRESSED_LZ4 = 1 << 1, +}; + +#define HEADER_INCOMPATIBLE_ANY (HEADER_INCOMPATIBLE_COMPRESSED_XZ|HEADER_INCOMPATIBLE_COMPRESSED_LZ4) + +#if HAVE_XZ && HAVE_LZ4 +# define HEADER_INCOMPATIBLE_SUPPORTED HEADER_INCOMPATIBLE_ANY +#elif HAVE_XZ +# define HEADER_INCOMPATIBLE_SUPPORTED HEADER_INCOMPATIBLE_COMPRESSED_XZ +#elif HAVE_LZ4 +# define HEADER_INCOMPATIBLE_SUPPORTED HEADER_INCOMPATIBLE_COMPRESSED_LZ4 +#else +# define HEADER_INCOMPATIBLE_SUPPORTED 0 +#endif + +enum { + HEADER_COMPATIBLE_SEALED = 1 +}; + +#define HEADER_COMPATIBLE_ANY HEADER_COMPATIBLE_SEALED +#if HAVE_GCRYPT +# define HEADER_COMPATIBLE_SUPPORTED HEADER_COMPATIBLE_SEALED +#else +# define HEADER_COMPATIBLE_SUPPORTED 0 +#endif + +#define HEADER_SIGNATURE ((char[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' }) + +#define struct_Header__contents { \ + uint8_t signature[8]; /* "LPKSHHRH" */ \ + le32_t compatible_flags; \ + le32_t incompatible_flags; \ + uint8_t state; \ + uint8_t reserved[7]; \ + sd_id128_t file_id; \ + sd_id128_t machine_id; \ + sd_id128_t boot_id; /* last writer */ \ + sd_id128_t seqnum_id; \ + le64_t header_size; \ + le64_t arena_size; \ + le64_t data_hash_table_offset; \ + le64_t data_hash_table_size; \ + le64_t field_hash_table_offset; \ + le64_t field_hash_table_size; \ + le64_t tail_object_offset; \ + le64_t n_objects; \ + le64_t n_entries; \ + le64_t tail_entry_seqnum; \ + le64_t head_entry_seqnum; \ + le64_t entry_array_offset; \ + le64_t head_entry_realtime; \ + le64_t tail_entry_realtime; \ + le64_t tail_entry_monotonic; \ + /* Added in 187 */ \ + le64_t n_data; \ + le64_t n_fields; \ + /* Added in 189 */ \ + le64_t n_tags; \ + le64_t n_entry_arrays; \ + } + +struct Header struct_Header__contents; +struct Header__packed struct_Header__contents _packed_; +assert_cc(sizeof(struct Header) == sizeof(struct Header__packed)); +assert_cc(sizeof(struct Header) == 240); + +#define FSS_HEADER_SIGNATURE ((char[]) { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' }) + +struct FSSHeader { + uint8_t signature[8]; /* "KSHHRHLP" */ + le32_t compatible_flags; + le32_t incompatible_flags; + sd_id128_t machine_id; + sd_id128_t boot_id; /* last writer */ + le64_t header_size; + le64_t start_usec; + le64_t interval_usec; + le16_t fsprg_secpar; + le16_t reserved[3]; + le64_t fsprg_state_size; +} _packed_; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c new file mode 100644 index 00000000..e1cd080c --- /dev/null +++ b/src/journal/journal-file.c @@ -0,0 +1,3923 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-event.h" + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "chattr-util.h" +#include "compress.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "journal-authenticate.h" +#include "journal-def.h" +#include "journal-file.h" +#include "lookup3.h" +#include "memory-util.h" +#include "path-util.h" +#include "random-util.h" +#include "set.h" +#include "sort-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "xattr-util.h" + +#define DEFAULT_DATA_HASH_TABLE_SIZE (2047ULL*sizeof(HashItem)) +#define DEFAULT_FIELD_HASH_TABLE_SIZE (333ULL*sizeof(HashItem)) + +#define DEFAULT_COMPRESS_THRESHOLD (512ULL) +#define MIN_COMPRESS_THRESHOLD (8ULL) + +/* This is the minimum journal file size */ +#define JOURNAL_FILE_SIZE_MIN (512 * 1024ULL) /* 512 KiB */ + +/* These are the lower and upper bounds if we deduce the max_use value + * from the file system size */ +#define MAX_USE_LOWER (1 * 1024 * 1024ULL) /* 1 MiB */ +#define MAX_USE_UPPER (4 * 1024 * 1024 * 1024ULL) /* 4 GiB */ + +/* Those are the lower and upper bounds for the minimal use limit, + * i.e. how much we'll use even if keep_free suggests otherwise. */ +#define MIN_USE_LOW (1 * 1024 * 1024ULL) /* 1 MiB */ +#define MIN_USE_HIGH (16 * 1024 * 1024ULL) /* 16 MiB */ + +/* This is the upper bound if we deduce max_size from max_use */ +#define MAX_SIZE_UPPER (128 * 1024 * 1024ULL) /* 128 MiB */ + +/* This is the upper bound if we deduce the keep_free value from the + * file system size */ +#define KEEP_FREE_UPPER (4 * 1024 * 1024 * 1024ULL) /* 4 GiB */ + +/* This is the keep_free value when we can't determine the system + * size */ +#define DEFAULT_KEEP_FREE (1024 * 1024ULL) /* 1 MB */ + +/* This is the default maximum number of journal files to keep around. */ +#define DEFAULT_N_MAX_FILES 100 + +/* n_data was the first entry we added after the initial file format design */ +#define HEADER_SIZE_MIN ALIGN64(offsetof(Header, n_data)) + +/* How many entries to keep in the entry array chain cache at max */ +#define CHAIN_CACHE_MAX 20 + +/* How much to increase the journal file size at once each time we allocate something new. */ +#define FILE_SIZE_INCREASE (8 * 1024 * 1024ULL) /* 8MB */ + +/* Reread fstat() of the file for detecting deletions at least this often */ +#define LAST_STAT_REFRESH_USEC (5*USEC_PER_SEC) + +/* The mmap context to use for the header we pick as one above the last defined typed */ +#define CONTEXT_HEADER _OBJECT_TYPE_MAX + +#ifdef __clang__ +# pragma GCC diagnostic ignored "-Waddress-of-packed-member" +#endif + +/* This may be called from a separate thread to prevent blocking the caller for the duration of fsync(). + * As a result we use atomic operations on f->offline_state for inter-thread communications with + * journal_file_set_offline() and journal_file_set_online(). */ +static void journal_file_set_offline_internal(JournalFile *f) { + assert(f); + assert(f->fd >= 0); + assert(f->header); + + for (;;) { + switch (f->offline_state) { + case OFFLINE_CANCEL: + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_CANCEL, OFFLINE_DONE)) + continue; + return; + + case OFFLINE_AGAIN_FROM_SYNCING: + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_SYNCING, OFFLINE_SYNCING)) + continue; + break; + + case OFFLINE_AGAIN_FROM_OFFLINING: + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_OFFLINING, OFFLINE_SYNCING)) + continue; + break; + + case OFFLINE_SYNCING: + (void) fsync(f->fd); + + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_OFFLINING)) + continue; + + f->header->state = f->archive ? STATE_ARCHIVED : STATE_OFFLINE; + (void) fsync(f->fd); + break; + + case OFFLINE_OFFLINING: + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_OFFLINING, OFFLINE_DONE)) + continue; + _fallthrough_; + case OFFLINE_DONE: + return; + + case OFFLINE_JOINED: + log_debug("OFFLINE_JOINED unexpected offline state for journal_file_set_offline_internal()"); + return; + } + } +} + +static void * journal_file_set_offline_thread(void *arg) { + JournalFile *f = arg; + + (void) pthread_setname_np(pthread_self(), "journal-offline"); + + journal_file_set_offline_internal(f); + + return NULL; +} + +static int journal_file_set_offline_thread_join(JournalFile *f) { + int r; + + assert(f); + + if (f->offline_state == OFFLINE_JOINED) + return 0; + + r = pthread_join(f->offline_thread, NULL); + if (r) + return -r; + + f->offline_state = OFFLINE_JOINED; + + if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) + return -EIO; + + return 0; +} + +/* Trigger a restart if the offline thread is mid-flight in a restartable state. */ +static bool journal_file_set_offline_try_restart(JournalFile *f) { + for (;;) { + switch (f->offline_state) { + case OFFLINE_AGAIN_FROM_SYNCING: + case OFFLINE_AGAIN_FROM_OFFLINING: + return true; + + case OFFLINE_CANCEL: + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_CANCEL, OFFLINE_AGAIN_FROM_SYNCING)) + continue; + return true; + + case OFFLINE_SYNCING: + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_AGAIN_FROM_SYNCING)) + continue; + return true; + + case OFFLINE_OFFLINING: + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_OFFLINING, OFFLINE_AGAIN_FROM_OFFLINING)) + continue; + return true; + + default: + return false; + } + } +} + +/* Sets a journal offline. + * + * If wait is false then an offline is dispatched in a separate thread for a + * subsequent journal_file_set_offline() or journal_file_set_online() of the + * same journal to synchronize with. + * + * If wait is true, then either an existing offline thread will be restarted + * and joined, or if none exists the offline is simply performed in this + * context without involving another thread. + */ +int journal_file_set_offline(JournalFile *f, bool wait) { + bool restarted; + int r; + + assert(f); + + if (!f->writable) + return -EPERM; + + if (f->fd < 0 || !f->header) + return -EINVAL; + + /* An offlining journal is implicitly online and may modify f->header->state, + * we must also join any potentially lingering offline thread when not online. */ + if (!journal_file_is_offlining(f) && f->header->state != STATE_ONLINE) + return journal_file_set_offline_thread_join(f); + + /* Restart an in-flight offline thread and wait if needed, or join a lingering done one. */ + restarted = journal_file_set_offline_try_restart(f); + if ((restarted && wait) || !restarted) { + r = journal_file_set_offline_thread_join(f); + if (r < 0) + return r; + } + + if (restarted) + return 0; + + /* Initiate a new offline. */ + f->offline_state = OFFLINE_SYNCING; + + if (wait) /* Without using a thread if waiting. */ + journal_file_set_offline_internal(f); + else { + sigset_t ss, saved_ss; + int k; + + assert_se(sigfillset(&ss) >= 0); + /* Don't block SIGBUS since the offlining thread accesses a memory mapped file. + * Asynchronous SIGBUS signals can safely be handled by either thread. */ + assert_se(sigdelset(&ss, SIGBUS) >= 0); + + r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss); + if (r > 0) + return -r; + + r = pthread_create(&f->offline_thread, NULL, journal_file_set_offline_thread, f); + + k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL); + if (r > 0) { + f->offline_state = OFFLINE_JOINED; + return -r; + } + if (k > 0) + return -k; + } + + return 0; +} + +static int journal_file_set_online(JournalFile *f) { + bool wait = true; + + assert(f); + + if (!f->writable) + return -EPERM; + + if (f->fd < 0 || !f->header) + return -EINVAL; + + while (wait) { + switch (f->offline_state) { + case OFFLINE_JOINED: + /* No offline thread, no need to wait. */ + wait = false; + break; + + case OFFLINE_SYNCING: + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_SYNCING, OFFLINE_CANCEL)) + continue; + /* Canceled syncing prior to offlining, no need to wait. */ + wait = false; + break; + + case OFFLINE_AGAIN_FROM_SYNCING: + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_SYNCING, OFFLINE_CANCEL)) + continue; + /* Canceled restart from syncing, no need to wait. */ + wait = false; + break; + + case OFFLINE_AGAIN_FROM_OFFLINING: + if (!__sync_bool_compare_and_swap(&f->offline_state, OFFLINE_AGAIN_FROM_OFFLINING, OFFLINE_CANCEL)) + continue; + /* Canceled restart from offlining, must wait for offlining to complete however. */ + _fallthrough_; + default: { + int r; + + r = journal_file_set_offline_thread_join(f); + if (r < 0) + return r; + + wait = false; + break; + } + } + } + + if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) + return -EIO; + + switch (f->header->state) { + case STATE_ONLINE: + return 0; + + case STATE_OFFLINE: + f->header->state = STATE_ONLINE; + (void) fsync(f->fd); + return 0; + + default: + return -EINVAL; + } +} + +bool journal_file_is_offlining(JournalFile *f) { + assert(f); + + __sync_synchronize(); + + if (IN_SET(f->offline_state, OFFLINE_DONE, OFFLINE_JOINED)) + return false; + + return true; +} + +JournalFile* journal_file_close(JournalFile *f) { + if (!f) + return NULL; + +#if HAVE_GCRYPT + /* Write the final tag */ + if (f->seal && f->writable) { + int r; + + r = journal_file_append_tag(f); + if (r < 0) + log_error_errno(r, "Failed to append tag when closing journal: %m"); + } +#endif + + if (f->post_change_timer) { + if (sd_event_source_get_enabled(f->post_change_timer, NULL) > 0) + journal_file_post_change(f); + + sd_event_source_disable_unref(f->post_change_timer); + } + + journal_file_set_offline(f, true); + + if (f->mmap && f->cache_fd) + mmap_cache_free_fd(f->mmap, f->cache_fd); + + if (f->fd >= 0 && f->defrag_on_close) { + + /* Be friendly to btrfs: turn COW back on again now, + * and defragment the file. We won't write to the file + * ever again, hence remove all fragmentation, and + * reenable all the good bits COW usually provides + * (such as data checksumming). */ + + (void) chattr_fd(f->fd, 0, FS_NOCOW_FL, NULL); + (void) btrfs_defrag_fd(f->fd); + } + + if (f->close_fd) + safe_close(f->fd); + free(f->path); + + mmap_cache_unref(f->mmap); + + ordered_hashmap_free_free(f->chain_cache); + +#if HAVE_XZ || HAVE_LZ4 + free(f->compress_buffer); +#endif + +#if HAVE_GCRYPT + if (f->fss_file) + munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size)); + else + free(f->fsprg_state); + + free(f->fsprg_seed); + + if (f->hmac) + gcry_md_close(f->hmac); +#endif + + return mfree(f); +} + +static int journal_file_init_header(JournalFile *f, JournalFile *template) { + Header h = {}; + ssize_t k; + int r; + + assert(f); + + memcpy(h.signature, HEADER_SIGNATURE, 8); + h.header_size = htole64(ALIGN64(sizeof(h))); + + h.incompatible_flags |= htole32( + f->compress_xz * HEADER_INCOMPATIBLE_COMPRESSED_XZ | + f->compress_lz4 * HEADER_INCOMPATIBLE_COMPRESSED_LZ4); + + h.compatible_flags = htole32( + f->seal * HEADER_COMPATIBLE_SEALED); + + r = sd_id128_randomize(&h.file_id); + if (r < 0) + return r; + + if (template) { + h.seqnum_id = template->header->seqnum_id; + h.tail_entry_seqnum = template->header->tail_entry_seqnum; + } else + h.seqnum_id = h.file_id; + + k = pwrite(f->fd, &h, sizeof(h), 0); + if (k < 0) + return -errno; + + if (k != sizeof(h)) + return -EIO; + + return 0; +} + +static int journal_file_refresh_header(JournalFile *f) { + sd_id128_t boot_id; + int r; + + assert(f); + assert(f->header); + + r = sd_id128_get_machine(&f->header->machine_id); + if (IN_SET(r, -ENOENT, -ENOMEDIUM)) + /* We don't have a machine-id, let's continue without */ + zero(f->header->machine_id); + else if (r < 0) + return r; + + r = sd_id128_get_boot(&boot_id); + if (r < 0) + return r; + + f->header->boot_id = boot_id; + + r = journal_file_set_online(f); + + /* Sync the online state to disk */ + (void) fsync(f->fd); + + /* We likely just created a new file, also sync the directory this file is located in. */ + (void) fsync_directory_of_file(f->fd); + + return r; +} + +static bool warn_wrong_flags(const JournalFile *f, bool compatible) { + const uint32_t any = compatible ? HEADER_COMPATIBLE_ANY : HEADER_INCOMPATIBLE_ANY, + supported = compatible ? HEADER_COMPATIBLE_SUPPORTED : HEADER_INCOMPATIBLE_SUPPORTED; + const char *type = compatible ? "compatible" : "incompatible"; + uint32_t flags; + + flags = le32toh(compatible ? f->header->compatible_flags : f->header->incompatible_flags); + + if (flags & ~supported) { + if (flags & ~any) + log_debug("Journal file %s has unknown %s flags 0x%"PRIx32, + f->path, type, flags & ~any); + flags = (flags & any) & ~supported; + if (flags) { + const char* strv[3]; + unsigned n = 0; + _cleanup_free_ char *t = NULL; + + if (compatible && (flags & HEADER_COMPATIBLE_SEALED)) + strv[n++] = "sealed"; + if (!compatible && (flags & HEADER_INCOMPATIBLE_COMPRESSED_XZ)) + strv[n++] = "xz-compressed"; + if (!compatible && (flags & HEADER_INCOMPATIBLE_COMPRESSED_LZ4)) + strv[n++] = "lz4-compressed"; + strv[n] = NULL; + assert(n < ELEMENTSOF(strv)); + + t = strv_join((char**) strv, ", "); + log_debug("Journal file %s uses %s %s %s disabled at compilation time.", + f->path, type, n > 1 ? "flags" : "flag", strnull(t)); + } + return true; + } + + return false; +} + +static int journal_file_verify_header(JournalFile *f) { + uint64_t arena_size, header_size; + + assert(f); + assert(f->header); + + if (memcmp(f->header->signature, HEADER_SIGNATURE, 8)) + return -EBADMSG; + + /* In both read and write mode we refuse to open files with incompatible + * flags we don't know. */ + if (warn_wrong_flags(f, false)) + return -EPROTONOSUPPORT; + + /* When open for writing we refuse to open files with compatible flags, too. */ + if (f->writable && warn_wrong_flags(f, true)) + return -EPROTONOSUPPORT; + + if (f->header->state >= _STATE_MAX) + return -EBADMSG; + + header_size = le64toh(f->header->header_size); + + /* The first addition was n_data, so check that we are at least this large */ + if (header_size < HEADER_SIZE_MIN) + return -EBADMSG; + + if (JOURNAL_HEADER_SEALED(f->header) && !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)) + return -EBADMSG; + + arena_size = le64toh(f->header->arena_size); + + if (UINT64_MAX - header_size < arena_size || header_size + arena_size > (uint64_t) f->last_stat.st_size) + return -ENODATA; + + if (le64toh(f->header->tail_object_offset) > header_size + arena_size) + return -ENODATA; + + if (!VALID64(le64toh(f->header->data_hash_table_offset)) || + !VALID64(le64toh(f->header->field_hash_table_offset)) || + !VALID64(le64toh(f->header->tail_object_offset)) || + !VALID64(le64toh(f->header->entry_array_offset))) + return -ENODATA; + + if (f->writable) { + sd_id128_t machine_id; + uint8_t state; + int r; + + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return r; + + if (!sd_id128_equal(machine_id, f->header->machine_id)) + return -EHOSTDOWN; + + state = f->header->state; + + if (state == STATE_ARCHIVED) + return -ESHUTDOWN; /* Already archived */ + else if (state == STATE_ONLINE) + return log_debug_errno(SYNTHETIC_ERRNO(EBUSY), + "Journal file %s is already online. Assuming unclean closing.", + f->path); + else if (state != STATE_OFFLINE) + return log_debug_errno(SYNTHETIC_ERRNO(EBUSY), + "Journal file %s has unknown state %i.", + f->path, state); + + if (f->header->field_hash_table_size == 0 || f->header->data_hash_table_size == 0) + return -EBADMSG; + + /* Don't permit appending to files from the future. Because otherwise the realtime timestamps wouldn't + * be strictly ordered in the entries in the file anymore, and we can't have that since it breaks + * bisection. */ + if (le64toh(f->header->tail_entry_realtime) > now(CLOCK_REALTIME)) + return log_debug_errno(SYNTHETIC_ERRNO(ETXTBSY), + "Journal file %s is from the future, refusing to append new data to it that'd be older.", + f->path); + } + + f->compress_xz = JOURNAL_HEADER_COMPRESSED_XZ(f->header); + f->compress_lz4 = JOURNAL_HEADER_COMPRESSED_LZ4(f->header); + + f->seal = JOURNAL_HEADER_SEALED(f->header); + + return 0; +} + +static int journal_file_fstat(JournalFile *f) { + int r; + + assert(f); + assert(f->fd >= 0); + + if (fstat(f->fd, &f->last_stat) < 0) + return -errno; + + f->last_stat_usec = now(CLOCK_MONOTONIC); + + /* Refuse dealing with with files that aren't regular */ + r = stat_verify_regular(&f->last_stat); + if (r < 0) + return r; + + /* Refuse appending to files that are already deleted */ + if (f->last_stat.st_nlink <= 0) + return -EIDRM; + + return 0; +} + +static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) { + uint64_t old_size, new_size; + int r; + + assert(f); + assert(f->header); + + /* We assume that this file is not sparse, and we know that + * for sure, since we always call posix_fallocate() + * ourselves */ + + if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) + return -EIO; + + old_size = + le64toh(f->header->header_size) + + le64toh(f->header->arena_size); + + new_size = PAGE_ALIGN(offset + size); + if (new_size < le64toh(f->header->header_size)) + new_size = le64toh(f->header->header_size); + + if (new_size <= old_size) { + + /* We already pre-allocated enough space, but before + * we write to it, let's check with fstat() if the + * file got deleted, in order make sure we don't throw + * away the data immediately. Don't check fstat() for + * all writes though, but only once ever 10s. */ + + if (f->last_stat_usec + LAST_STAT_REFRESH_USEC > now(CLOCK_MONOTONIC)) + return 0; + + return journal_file_fstat(f); + } + + /* Allocate more space. */ + + if (f->metrics.max_size > 0 && new_size > f->metrics.max_size) + return -E2BIG; + + if (new_size > f->metrics.min_size && f->metrics.keep_free > 0) { + struct statvfs svfs; + + if (fstatvfs(f->fd, &svfs) >= 0) { + uint64_t available; + + available = LESS_BY((uint64_t) svfs.f_bfree * (uint64_t) svfs.f_bsize, f->metrics.keep_free); + + if (new_size - old_size > available) + return -E2BIG; + } + } + + /* Increase by larger blocks at once */ + new_size = DIV_ROUND_UP(new_size, FILE_SIZE_INCREASE) * FILE_SIZE_INCREASE; + if (f->metrics.max_size > 0 && new_size > f->metrics.max_size) + new_size = f->metrics.max_size; + + /* Note that the glibc fallocate() fallback is very + inefficient, hence we try to minimize the allocation area + as we can. */ + r = posix_fallocate(f->fd, old_size, new_size - old_size); + if (r != 0) + return -r; + + f->header->arena_size = htole64(new_size - le64toh(f->header->header_size)); + + return journal_file_fstat(f); +} + +static unsigned type_to_context(ObjectType type) { + /* One context for each type, plus one catch-all for the rest */ + assert_cc(_OBJECT_TYPE_MAX <= MMAP_CACHE_MAX_CONTEXTS); + assert_cc(CONTEXT_HEADER < MMAP_CACHE_MAX_CONTEXTS); + return type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX ? type : 0; +} + +static int journal_file_move_to(JournalFile *f, ObjectType type, bool keep_always, uint64_t offset, uint64_t size, void **ret, size_t *ret_size) { + int r; + + assert(f); + assert(ret); + + if (size <= 0) + return -EINVAL; + + /* Avoid SIGBUS on invalid accesses */ + if (offset + size > (uint64_t) f->last_stat.st_size) { + /* Hmm, out of range? Let's refresh the fstat() data + * first, before we trust that check. */ + + r = journal_file_fstat(f); + if (r < 0) + return r; + + if (offset + size > (uint64_t) f->last_stat.st_size) + return -EADDRNOTAVAIL; + } + + return mmap_cache_get(f->mmap, f->cache_fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret, ret_size); +} + +static uint64_t minimum_header_size(Object *o) { + + static const uint64_t table[] = { + [OBJECT_DATA] = sizeof(DataObject), + [OBJECT_FIELD] = sizeof(FieldObject), + [OBJECT_ENTRY] = sizeof(EntryObject), + [OBJECT_DATA_HASH_TABLE] = sizeof(HashTableObject), + [OBJECT_FIELD_HASH_TABLE] = sizeof(HashTableObject), + [OBJECT_ENTRY_ARRAY] = sizeof(EntryArrayObject), + [OBJECT_TAG] = sizeof(TagObject), + }; + + if (o->object.type >= ELEMENTSOF(table) || table[o->object.type] <= 0) + return sizeof(ObjectHeader); + + return table[o->object.type]; +} + +/* Lightweight object checks. We want this to be fast, so that we won't + * slowdown every journal_file_move_to_object() call too much. */ +static int journal_file_check_object(JournalFile *f, uint64_t offset, Object *o) { + assert(f); + assert(o); + + switch (o->object.type) { + + case OBJECT_DATA: + if ((le64toh(o->data.entry_offset) == 0) ^ (le64toh(o->data.n_entries) == 0)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Bad n_entries: %" PRIu64 ": %" PRIu64, + le64toh(o->data.n_entries), + offset); + + if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Bad object size (<= %zu): %" PRIu64 ": %" PRIu64, + offsetof(DataObject, payload), + le64toh(o->object.size), + offset); + + if (!VALID64(le64toh(o->data.next_hash_offset)) || + !VALID64(le64toh(o->data.next_field_offset)) || + !VALID64(le64toh(o->data.entry_offset)) || + !VALID64(le64toh(o->data.entry_array_offset))) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid offset, next_hash_offset=" OFSfmt ", next_field_offset=" OFSfmt ", entry_offset=" OFSfmt ", entry_array_offset=" OFSfmt ": %" PRIu64, + le64toh(o->data.next_hash_offset), + le64toh(o->data.next_field_offset), + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + offset); + + break; + + case OBJECT_FIELD: + if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Bad field size (<= %zu): %" PRIu64 ": %" PRIu64, + offsetof(FieldObject, payload), + le64toh(o->object.size), + offset); + + if (!VALID64(le64toh(o->field.next_hash_offset)) || + !VALID64(le64toh(o->field.head_data_offset))) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid offset, next_hash_offset=" OFSfmt ", head_data_offset=" OFSfmt ": %" PRIu64, + le64toh(o->field.next_hash_offset), + le64toh(o->field.head_data_offset), + offset); + break; + + case OBJECT_ENTRY: + if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Bad entry size (<= %zu): %" PRIu64 ": %" PRIu64, + offsetof(EntryObject, items), + le64toh(o->object.size), + offset); + + if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid number items in entry: %" PRIu64 ": %" PRIu64, + (le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem), + offset); + + if (le64toh(o->entry.seqnum) <= 0) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid entry seqnum: %" PRIx64 ": %" PRIu64, + le64toh(o->entry.seqnum), + offset); + + if (!VALID_REALTIME(le64toh(o->entry.realtime))) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid entry realtime timestamp: %" PRIu64 ": %" PRIu64, + le64toh(o->entry.realtime), + offset); + + if (!VALID_MONOTONIC(le64toh(o->entry.monotonic))) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid entry monotonic timestamp: %" PRIu64 ": %" PRIu64, + le64toh(o->entry.monotonic), + offset); + + break; + + case OBJECT_DATA_HASH_TABLE: + case OBJECT_FIELD_HASH_TABLE: + if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0 || + (le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid %s hash table size: %" PRIu64 ": %" PRIu64, + o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field", + le64toh(o->object.size), + offset); + + break; + + case OBJECT_ENTRY_ARRAY: + if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0 || + (le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid object entry array size: %" PRIu64 ": %" PRIu64, + le64toh(o->object.size), + offset); + + if (!VALID64(le64toh(o->entry_array.next_entry_array_offset))) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid object entry array next_entry_array_offset: " OFSfmt ": %" PRIu64, + le64toh(o->entry_array.next_entry_array_offset), + offset); + + break; + + case OBJECT_TAG: + if (le64toh(o->object.size) != sizeof(TagObject)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid object tag size: %" PRIu64 ": %" PRIu64, + le64toh(o->object.size), + offset); + + if (!VALID_EPOCH(le64toh(o->tag.epoch))) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid object tag epoch: %" PRIu64 ": %" PRIu64, + le64toh(o->tag.epoch), offset); + + break; + } + + return 0; +} + +int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret) { + int r; + void *t; + size_t tsize; + Object *o; + uint64_t s; + + assert(f); + assert(ret); + + /* Objects may only be located at multiple of 64 bit */ + if (!VALID64(offset)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Attempt to move to object at non-64bit boundary: %" PRIu64, + offset); + + /* Object may not be located in the file header */ + if (offset < le64toh(f->header->header_size)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Attempt to move to object located in file header: %" PRIu64, + offset); + + r = journal_file_move_to(f, type, false, offset, sizeof(ObjectHeader), &t, &tsize); + if (r < 0) + return r; + + o = (Object*) t; + s = le64toh(o->object.size); + + if (s == 0) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Attempt to move to uninitialized object: %" PRIu64, + offset); + if (s < sizeof(ObjectHeader)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Attempt to move to overly short object: %" PRIu64, + offset); + + if (o->object.type <= OBJECT_UNUSED) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Attempt to move to object with invalid type: %" PRIu64, + offset); + + if (s < minimum_header_size(o)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Attempt to move to truncated object: %" PRIu64, + offset); + + if (type > OBJECT_UNUSED && o->object.type != type) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Attempt to move to object of unexpected type: %" PRIu64, + offset); + + if (s > tsize) { + r = journal_file_move_to(f, type, false, offset, s, &t, NULL); + if (r < 0) + return r; + + o = (Object*) t; + } + + r = journal_file_check_object(f, offset, o); + if (r < 0) + return r; + + *ret = o; + return 0; +} + +static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) { + uint64_t r; + + assert(f); + assert(f->header); + + r = le64toh(f->header->tail_entry_seqnum) + 1; + + if (seqnum) { + /* If an external seqnum counter was passed, we update + * both the local and the external one, and set it to + * the maximum of both */ + + if (*seqnum + 1 > r) + r = *seqnum + 1; + + *seqnum = r; + } + + f->header->tail_entry_seqnum = htole64(r); + + if (f->header->head_entry_seqnum == 0) + f->header->head_entry_seqnum = htole64(r); + + return r; +} + +int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset) { + int r; + uint64_t p; + Object *tail, *o; + void *t; + + assert(f); + assert(f->header); + assert(type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX); + assert(size >= sizeof(ObjectHeader)); + assert(offset); + assert(ret); + + r = journal_file_set_online(f); + if (r < 0) + return r; + + p = le64toh(f->header->tail_object_offset); + if (p == 0) + p = le64toh(f->header->header_size); + else { + r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail); + if (r < 0) + return r; + + p += ALIGN64(le64toh(tail->object.size)); + } + + r = journal_file_allocate(f, p, size); + if (r < 0) + return r; + + r = journal_file_move_to(f, type, false, p, size, &t, NULL); + if (r < 0) + return r; + + o = (Object*) t; + + zero(o->object); + o->object.type = type; + o->object.size = htole64(size); + + f->header->tail_object_offset = htole64(p); + f->header->n_objects = htole64(le64toh(f->header->n_objects) + 1); + + *ret = o; + *offset = p; + + return 0; +} + +static int journal_file_setup_data_hash_table(JournalFile *f) { + uint64_t s, p; + Object *o; + int r; + + assert(f); + assert(f->header); + + /* We estimate that we need 1 hash table entry per 768 bytes + of journal file and we want to make sure we never get + beyond 75% fill level. Calculate the hash table size for + the maximum file size based on these metrics. */ + + s = (f->metrics.max_size * 4 / 768 / 3) * sizeof(HashItem); + if (s < DEFAULT_DATA_HASH_TABLE_SIZE) + s = DEFAULT_DATA_HASH_TABLE_SIZE; + + log_debug("Reserving %"PRIu64" entries in hash table.", s / sizeof(HashItem)); + + r = journal_file_append_object(f, + OBJECT_DATA_HASH_TABLE, + offsetof(Object, hash_table.items) + s, + &o, &p); + if (r < 0) + return r; + + memzero(o->hash_table.items, s); + + f->header->data_hash_table_offset = htole64(p + offsetof(Object, hash_table.items)); + f->header->data_hash_table_size = htole64(s); + + return 0; +} + +static int journal_file_setup_field_hash_table(JournalFile *f) { + uint64_t s, p; + Object *o; + int r; + + assert(f); + assert(f->header); + + /* We use a fixed size hash table for the fields as this + * number should grow very slowly only */ + + s = DEFAULT_FIELD_HASH_TABLE_SIZE; + r = journal_file_append_object(f, + OBJECT_FIELD_HASH_TABLE, + offsetof(Object, hash_table.items) + s, + &o, &p); + if (r < 0) + return r; + + memzero(o->hash_table.items, s); + + f->header->field_hash_table_offset = htole64(p + offsetof(Object, hash_table.items)); + f->header->field_hash_table_size = htole64(s); + + return 0; +} + +int journal_file_map_data_hash_table(JournalFile *f) { + uint64_t s, p; + void *t; + int r; + + assert(f); + assert(f->header); + + if (f->data_hash_table) + return 0; + + p = le64toh(f->header->data_hash_table_offset); + s = le64toh(f->header->data_hash_table_size); + + r = journal_file_move_to(f, + OBJECT_DATA_HASH_TABLE, + true, + p, s, + &t, NULL); + if (r < 0) + return r; + + f->data_hash_table = t; + return 0; +} + +int journal_file_map_field_hash_table(JournalFile *f) { + uint64_t s, p; + void *t; + int r; + + assert(f); + assert(f->header); + + if (f->field_hash_table) + return 0; + + p = le64toh(f->header->field_hash_table_offset); + s = le64toh(f->header->field_hash_table_size); + + r = journal_file_move_to(f, + OBJECT_FIELD_HASH_TABLE, + true, + p, s, + &t, NULL); + if (r < 0) + return r; + + f->field_hash_table = t; + return 0; +} + +static int journal_file_link_field( + JournalFile *f, + Object *o, + uint64_t offset, + uint64_t hash) { + + uint64_t p, h, m; + int r; + + assert(f); + assert(f->header); + assert(f->field_hash_table); + assert(o); + assert(offset > 0); + + if (o->object.type != OBJECT_FIELD) + return -EINVAL; + + m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem); + if (m <= 0) + return -EBADMSG; + + /* This might alter the window we are looking at */ + o->field.next_hash_offset = o->field.head_data_offset = 0; + + h = hash % m; + p = le64toh(f->field_hash_table[h].tail_hash_offset); + if (p == 0) + f->field_hash_table[h].head_hash_offset = htole64(offset); + else { + r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o); + if (r < 0) + return r; + + o->field.next_hash_offset = htole64(offset); + } + + f->field_hash_table[h].tail_hash_offset = htole64(offset); + + if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) + f->header->n_fields = htole64(le64toh(f->header->n_fields) + 1); + + return 0; +} + +static int journal_file_link_data( + JournalFile *f, + Object *o, + uint64_t offset, + uint64_t hash) { + + uint64_t p, h, m; + int r; + + assert(f); + assert(f->header); + assert(f->data_hash_table); + assert(o); + assert(offset > 0); + + if (o->object.type != OBJECT_DATA) + return -EINVAL; + + m = le64toh(f->header->data_hash_table_size) / sizeof(HashItem); + if (m <= 0) + return -EBADMSG; + + /* This might alter the window we are looking at */ + o->data.next_hash_offset = o->data.next_field_offset = 0; + o->data.entry_offset = o->data.entry_array_offset = 0; + o->data.n_entries = 0; + + h = hash % m; + p = le64toh(f->data_hash_table[h].tail_hash_offset); + if (p == 0) + /* Only entry in the hash table is easy */ + f->data_hash_table[h].head_hash_offset = htole64(offset); + else { + /* Move back to the previous data object, to patch in + * pointer */ + + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + o->data.next_hash_offset = htole64(offset); + } + + f->data_hash_table[h].tail_hash_offset = htole64(offset); + + if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) + f->header->n_data = htole64(le64toh(f->header->n_data) + 1); + + return 0; +} + +int journal_file_find_field_object_with_hash( + JournalFile *f, + const void *field, uint64_t size, uint64_t hash, + Object **ret, uint64_t *offset) { + + uint64_t p, osize, h, m; + int r; + + assert(f); + assert(f->header); + assert(field && size > 0); + + /* If the field hash table is empty, we can't find anything */ + if (le64toh(f->header->field_hash_table_size) <= 0) + return 0; + + /* Map the field hash table, if it isn't mapped yet. */ + r = journal_file_map_field_hash_table(f); + if (r < 0) + return r; + + osize = offsetof(Object, field.payload) + size; + + m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem); + if (m <= 0) + return -EBADMSG; + + h = hash % m; + p = le64toh(f->field_hash_table[h].head_hash_offset); + + while (p > 0) { + Object *o; + + r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o); + if (r < 0) + return r; + + if (le64toh(o->field.hash) == hash && + le64toh(o->object.size) == osize && + memcmp(o->field.payload, field, size) == 0) { + + if (ret) + *ret = o; + if (offset) + *offset = p; + + return 1; + } + + p = le64toh(o->field.next_hash_offset); + } + + return 0; +} + +int journal_file_find_field_object( + JournalFile *f, + const void *field, uint64_t size, + Object **ret, uint64_t *offset) { + + uint64_t hash; + + assert(f); + assert(field && size > 0); + + hash = hash64(field, size); + + return journal_file_find_field_object_with_hash(f, + field, size, hash, + ret, offset); +} + +int journal_file_find_data_object_with_hash( + JournalFile *f, + const void *data, uint64_t size, uint64_t hash, + Object **ret, uint64_t *offset) { + + uint64_t p, osize, h, m; + int r; + + assert(f); + assert(f->header); + assert(data || size == 0); + + /* If there's no data hash table, then there's no entry. */ + if (le64toh(f->header->data_hash_table_size) <= 0) + return 0; + + /* Map the data hash table, if it isn't mapped yet. */ + r = journal_file_map_data_hash_table(f); + if (r < 0) + return r; + + osize = offsetof(Object, data.payload) + size; + + m = le64toh(f->header->data_hash_table_size) / sizeof(HashItem); + if (m <= 0) + return -EBADMSG; + + h = hash % m; + p = le64toh(f->data_hash_table[h].head_hash_offset); + + while (p > 0) { + Object *o; + + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + if (le64toh(o->data.hash) != hash) + goto next; + + if (o->object.flags & OBJECT_COMPRESSION_MASK) { +#if HAVE_XZ || HAVE_LZ4 + uint64_t l; + size_t rsize = 0; + + l = le64toh(o->object.size); + if (l <= offsetof(Object, data.payload)) + return -EBADMSG; + + l -= offsetof(Object, data.payload); + + r = decompress_blob(o->object.flags & OBJECT_COMPRESSION_MASK, + o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize, 0); + if (r < 0) + return r; + + if (rsize == size && + memcmp(f->compress_buffer, data, size) == 0) { + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 1; + } +#else + return -EPROTONOSUPPORT; +#endif + } else if (le64toh(o->object.size) == osize && + memcmp(o->data.payload, data, size) == 0) { + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 1; + } + + next: + p = le64toh(o->data.next_hash_offset); + } + + return 0; +} + +int journal_file_find_data_object( + JournalFile *f, + const void *data, uint64_t size, + Object **ret, uint64_t *offset) { + + uint64_t hash; + + assert(f); + assert(data || size == 0); + + hash = hash64(data, size); + + return journal_file_find_data_object_with_hash(f, + data, size, hash, + ret, offset); +} + +static int journal_file_append_field( + JournalFile *f, + const void *field, uint64_t size, + Object **ret, uint64_t *offset) { + + uint64_t hash, p; + uint64_t osize; + Object *o; + int r; + + assert(f); + assert(field && size > 0); + + hash = hash64(field, size); + + r = journal_file_find_field_object_with_hash(f, field, size, hash, &o, &p); + if (r < 0) + return r; + else if (r > 0) { + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 0; + } + + osize = offsetof(Object, field.payload) + size; + r = journal_file_append_object(f, OBJECT_FIELD, osize, &o, &p); + if (r < 0) + return r; + + o->field.hash = htole64(hash); + memcpy(o->field.payload, field, size); + + r = journal_file_link_field(f, o, p, hash); + if (r < 0) + return r; + + /* The linking might have altered the window, so let's + * refresh our pointer */ + r = journal_file_move_to_object(f, OBJECT_FIELD, p, &o); + if (r < 0) + return r; + +#if HAVE_GCRYPT + r = journal_file_hmac_put_object(f, OBJECT_FIELD, o, p); + if (r < 0) + return r; +#endif + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 0; +} + +static int journal_file_append_data( + JournalFile *f, + const void *data, uint64_t size, + Object **ret, uint64_t *offset) { + + uint64_t hash, p; + uint64_t osize; + Object *o; + int r, compression = 0; + const void *eq; + + assert(f); + assert(data || size == 0); + + hash = hash64(data, size); + + r = journal_file_find_data_object_with_hash(f, data, size, hash, &o, &p); + if (r < 0) + return r; + if (r > 0) { + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 0; + } + + osize = offsetof(Object, data.payload) + size; + r = journal_file_append_object(f, OBJECT_DATA, osize, &o, &p); + if (r < 0) + return r; + + o->data.hash = htole64(hash); + +#if HAVE_XZ || HAVE_LZ4 + if (JOURNAL_FILE_COMPRESS(f) && size >= f->compress_threshold_bytes) { + size_t rsize = 0; + + compression = compress_blob(data, size, o->data.payload, size - 1, &rsize); + + if (compression >= 0) { + o->object.size = htole64(offsetof(Object, data.payload) + rsize); + o->object.flags |= compression; + + log_debug("Compressed data object %"PRIu64" -> %zu using %s", + size, rsize, object_compressed_to_string(compression)); + } else + /* Compression didn't work, we don't really care why, let's continue without compression */ + compression = 0; + } +#endif + + if (compression == 0) + memcpy_safe(o->data.payload, data, size); + + r = journal_file_link_data(f, o, p, hash); + if (r < 0) + return r; + +#if HAVE_GCRYPT + r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p); + if (r < 0) + return r; +#endif + + /* The linking might have altered the window, so let's + * refresh our pointer */ + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + if (!data) + eq = NULL; + else + eq = memchr(data, '=', size); + if (eq && eq > data) { + Object *fo = NULL; + uint64_t fp; + + /* Create field object ... */ + r = journal_file_append_field(f, data, (uint8_t*) eq - (uint8_t*) data, &fo, &fp); + if (r < 0) + return r; + + /* ... and link it in. */ + o->data.next_field_offset = fo->field.head_data_offset; + fo->field.head_data_offset = le64toh(p); + } + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 0; +} + +uint64_t journal_file_entry_n_items(Object *o) { + assert(o); + + if (o->object.type != OBJECT_ENTRY) + return 0; + + return (le64toh(o->object.size) - offsetof(Object, entry.items)) / sizeof(EntryItem); +} + +uint64_t journal_file_entry_array_n_items(Object *o) { + assert(o); + + if (o->object.type != OBJECT_ENTRY_ARRAY) + return 0; + + return (le64toh(o->object.size) - offsetof(Object, entry_array.items)) / sizeof(uint64_t); +} + +uint64_t journal_file_hash_table_n_items(Object *o) { + assert(o); + + if (!IN_SET(o->object.type, OBJECT_DATA_HASH_TABLE, OBJECT_FIELD_HASH_TABLE)) + return 0; + + return (le64toh(o->object.size) - offsetof(Object, hash_table.items)) / sizeof(HashItem); +} + +static int link_entry_into_array(JournalFile *f, + le64_t *first, + le64_t *idx, + uint64_t p) { + int r; + uint64_t n = 0, ap = 0, q, i, a, hidx; + Object *o; + + assert(f); + assert(f->header); + assert(first); + assert(idx); + assert(p > 0); + + a = le64toh(*first); + i = hidx = le64toh(*idx); + while (a > 0) { + + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); + if (r < 0) + return r; + + n = journal_file_entry_array_n_items(o); + if (i < n) { + o->entry_array.items[i] = htole64(p); + *idx = htole64(hidx + 1); + return 0; + } + + i -= n; + ap = a; + a = le64toh(o->entry_array.next_entry_array_offset); + } + + if (hidx > n) + n = (hidx+1) * 2; + else + n = n * 2; + + if (n < 4) + n = 4; + + r = journal_file_append_object(f, OBJECT_ENTRY_ARRAY, + offsetof(Object, entry_array.items) + n * sizeof(uint64_t), + &o, &q); + if (r < 0) + return r; + +#if HAVE_GCRYPT + r = journal_file_hmac_put_object(f, OBJECT_ENTRY_ARRAY, o, q); + if (r < 0) + return r; +#endif + + o->entry_array.items[i] = htole64(p); + + if (ap == 0) + *first = htole64(q); + else { + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, ap, &o); + if (r < 0) + return r; + + o->entry_array.next_entry_array_offset = htole64(q); + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)) + f->header->n_entry_arrays = htole64(le64toh(f->header->n_entry_arrays) + 1); + + *idx = htole64(hidx + 1); + + return 0; +} + +static int link_entry_into_array_plus_one(JournalFile *f, + le64_t *extra, + le64_t *first, + le64_t *idx, + uint64_t p) { + + int r; + + assert(f); + assert(extra); + assert(first); + assert(idx); + assert(p > 0); + + if (*idx == 0) + *extra = htole64(p); + else { + le64_t i; + + i = htole64(le64toh(*idx) - 1); + r = link_entry_into_array(f, first, &i, p); + if (r < 0) + return r; + } + + *idx = htole64(le64toh(*idx) + 1); + return 0; +} + +static int journal_file_link_entry_item(JournalFile *f, Object *o, uint64_t offset, uint64_t i) { + uint64_t p; + int r; + assert(f); + assert(o); + assert(offset > 0); + + p = le64toh(o->entry.items[i].object_offset); + if (p == 0) + return -EINVAL; + + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + return link_entry_into_array_plus_one(f, + &o->data.entry_offset, + &o->data.entry_array_offset, + &o->data.n_entries, + offset); +} + +static int journal_file_link_entry(JournalFile *f, Object *o, uint64_t offset) { + uint64_t n, i; + int r; + + assert(f); + assert(f->header); + assert(o); + assert(offset > 0); + + if (o->object.type != OBJECT_ENTRY) + return -EINVAL; + + __sync_synchronize(); + + /* Link up the entry itself */ + r = link_entry_into_array(f, + &f->header->entry_array_offset, + &f->header->n_entries, + offset); + if (r < 0) + return r; + + /* log_debug("=> %s seqnr=%"PRIu64" n_entries=%"PRIu64, f->path, o->entry.seqnum, f->header->n_entries); */ + + if (f->header->head_entry_realtime == 0) + f->header->head_entry_realtime = o->entry.realtime; + + f->header->tail_entry_realtime = o->entry.realtime; + f->header->tail_entry_monotonic = o->entry.monotonic; + + /* Link up the items */ + n = journal_file_entry_n_items(o); + for (i = 0; i < n; i++) { + r = journal_file_link_entry_item(f, o, offset, i); + if (r < 0) + return r; + } + + return 0; +} + +static int journal_file_append_entry_internal( + JournalFile *f, + const dual_timestamp *ts, + const sd_id128_t *boot_id, + uint64_t xor_hash, + const EntryItem items[], unsigned n_items, + uint64_t *seqnum, + Object **ret, uint64_t *offset) { + uint64_t np; + uint64_t osize; + Object *o; + int r; + + assert(f); + assert(f->header); + assert(items || n_items == 0); + assert(ts); + + osize = offsetof(Object, entry.items) + (n_items * sizeof(EntryItem)); + + r = journal_file_append_object(f, OBJECT_ENTRY, osize, &o, &np); + if (r < 0) + return r; + + o->entry.seqnum = htole64(journal_file_entry_seqnum(f, seqnum)); + memcpy_safe(o->entry.items, items, n_items * sizeof(EntryItem)); + o->entry.realtime = htole64(ts->realtime); + o->entry.monotonic = htole64(ts->monotonic); + o->entry.xor_hash = htole64(xor_hash); + if (boot_id) + f->header->boot_id = *boot_id; + o->entry.boot_id = f->header->boot_id; + +#if HAVE_GCRYPT + r = journal_file_hmac_put_object(f, OBJECT_ENTRY, o, np); + if (r < 0) + return r; +#endif + + r = journal_file_link_entry(f, o, np); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = np; + + return 0; +} + +void journal_file_post_change(JournalFile *f) { + assert(f); + + if (f->fd < 0) + return; + + /* inotify() does not receive IN_MODIFY events from file + * accesses done via mmap(). After each access we hence + * trigger IN_MODIFY by truncating the journal file to its + * current size which triggers IN_MODIFY. */ + + __sync_synchronize(); + + if (ftruncate(f->fd, f->last_stat.st_size) < 0) + log_debug_errno(errno, "Failed to truncate file to its own size: %m"); +} + +static int post_change_thunk(sd_event_source *timer, uint64_t usec, void *userdata) { + assert(userdata); + + journal_file_post_change(userdata); + + return 1; +} + +static void schedule_post_change(JournalFile *f) { + uint64_t now; + int r; + + assert(f); + assert(f->post_change_timer); + + r = sd_event_source_get_enabled(f->post_change_timer, NULL); + if (r < 0) { + log_debug_errno(r, "Failed to get ftruncate timer state: %m"); + goto fail; + } + if (r > 0) + return; + + r = sd_event_now(sd_event_source_get_event(f->post_change_timer), CLOCK_MONOTONIC, &now); + if (r < 0) { + log_debug_errno(r, "Failed to get clock's now for scheduling ftruncate: %m"); + goto fail; + } + + r = sd_event_source_set_time(f->post_change_timer, now + f->post_change_timer_period); + if (r < 0) { + log_debug_errno(r, "Failed to set time for scheduling ftruncate: %m"); + goto fail; + } + + r = sd_event_source_set_enabled(f->post_change_timer, SD_EVENT_ONESHOT); + if (r < 0) { + log_debug_errno(r, "Failed to enable scheduled ftruncate: %m"); + goto fail; + } + + return; + +fail: + /* On failure, let's simply post the change immediately. */ + journal_file_post_change(f); +} + +/* Enable coalesced change posting in a timer on the provided sd_event instance */ +int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t) { + _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL; + int r; + + assert(f); + assert_return(!f->post_change_timer, -EINVAL); + assert(e); + assert(t); + + r = sd_event_add_time(e, &timer, CLOCK_MONOTONIC, 0, 0, post_change_thunk, f); + if (r < 0) + return r; + + r = sd_event_source_set_enabled(timer, SD_EVENT_OFF); + if (r < 0) + return r; + + f->post_change_timer = TAKE_PTR(timer); + f->post_change_timer_period = t; + + return r; +} + +static int entry_item_cmp(const EntryItem *a, const EntryItem *b) { + return CMP(le64toh(a->object_offset), le64toh(b->object_offset)); +} + +int journal_file_append_entry( + JournalFile *f, + const dual_timestamp *ts, + const sd_id128_t *boot_id, + const struct iovec iovec[], unsigned n_iovec, + uint64_t *seqnum, + Object **ret, uint64_t *offset) { + + unsigned i; + EntryItem *items; + int r; + uint64_t xor_hash = 0; + struct dual_timestamp _ts; + + assert(f); + assert(f->header); + assert(iovec || n_iovec == 0); + + if (ts) { + if (!VALID_REALTIME(ts->realtime)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid realtime timestamp %" PRIu64 ", refusing entry.", + ts->realtime); + if (!VALID_MONOTONIC(ts->monotonic)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid monotomic timestamp %" PRIu64 ", refusing entry.", + ts->monotonic); + } else { + dual_timestamp_get(&_ts); + ts = &_ts; + } + +#if HAVE_GCRYPT + r = journal_file_maybe_append_tag(f, ts->realtime); + if (r < 0) + return r; +#endif + + /* alloca() can't take 0, hence let's allocate at least one */ + items = newa(EntryItem, MAX(1u, n_iovec)); + + for (i = 0; i < n_iovec; i++) { + uint64_t p; + Object *o; + + r = journal_file_append_data(f, iovec[i].iov_base, iovec[i].iov_len, &o, &p); + if (r < 0) + return r; + + xor_hash ^= le64toh(o->data.hash); + items[i].object_offset = htole64(p); + items[i].hash = o->data.hash; + } + + /* Order by the position on disk, in order to improve seek + * times for rotating media. */ + typesafe_qsort(items, n_iovec, entry_item_cmp); + + r = journal_file_append_entry_internal(f, ts, boot_id, xor_hash, items, n_iovec, seqnum, ret, offset); + + /* If the memory mapping triggered a SIGBUS then we return an + * IO error and ignore the error code passed down to us, since + * it is very likely just an effect of a nullified replacement + * mapping page */ + + if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) + r = -EIO; + + if (f->post_change_timer) + schedule_post_change(f); + else + journal_file_post_change(f); + + return r; +} + +typedef struct ChainCacheItem { + uint64_t first; /* the array at the beginning of the chain */ + uint64_t array; /* the cached array */ + uint64_t begin; /* the first item in the cached array */ + uint64_t total; /* the total number of items in all arrays before this one in the chain */ + uint64_t last_index; /* the last index we looked at, to optimize locality when bisecting */ +} ChainCacheItem; + +static void chain_cache_put( + OrderedHashmap *h, + ChainCacheItem *ci, + uint64_t first, + uint64_t array, + uint64_t begin, + uint64_t total, + uint64_t last_index) { + + if (!ci) { + /* If the chain item to cache for this chain is the + * first one it's not worth caching anything */ + if (array == first) + return; + + if (ordered_hashmap_size(h) >= CHAIN_CACHE_MAX) { + ci = ordered_hashmap_steal_first(h); + assert(ci); + } else { + ci = new(ChainCacheItem, 1); + if (!ci) + return; + } + + ci->first = first; + + if (ordered_hashmap_put(h, &ci->first, ci) < 0) { + free(ci); + return; + } + } else + assert(ci->first == first); + + ci->array = array; + ci->begin = begin; + ci->total = total; + ci->last_index = last_index; +} + +static int generic_array_get( + JournalFile *f, + uint64_t first, + uint64_t i, + Object **ret, uint64_t *offset) { + + Object *o; + uint64_t p = 0, a, t = 0; + int r; + ChainCacheItem *ci; + + assert(f); + + a = first; + + /* Try the chain cache first */ + ci = ordered_hashmap_get(f->chain_cache, &first); + if (ci && i > ci->total) { + a = ci->array; + i -= ci->total; + t = ci->total; + } + + while (a > 0) { + uint64_t k; + + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); + if (r < 0) + return r; + + k = journal_file_entry_array_n_items(o); + if (i < k) { + p = le64toh(o->entry_array.items[i]); + goto found; + } + + i -= k; + t += k; + a = le64toh(o->entry_array.next_entry_array_offset); + } + + return 0; + +found: + /* Let's cache this item for the next invocation */ + chain_cache_put(f->chain_cache, ci, first, a, le64toh(o->entry_array.items[0]), t, i); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + return 1; +} + +static int generic_array_get_plus_one( + JournalFile *f, + uint64_t extra, + uint64_t first, + uint64_t i, + Object **ret, uint64_t *offset) { + + Object *o; + + assert(f); + + if (i == 0) { + int r; + + r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = extra; + + return 1; + } + + return generic_array_get(f, first, i-1, ret, offset); +} + +enum { + TEST_FOUND, + TEST_LEFT, + TEST_RIGHT +}; + +static int generic_array_bisect( + JournalFile *f, + uint64_t first, + uint64_t n, + uint64_t needle, + int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle), + direction_t direction, + Object **ret, + uint64_t *offset, + uint64_t *idx) { + + uint64_t a, p, t = 0, i = 0, last_p = 0, last_index = (uint64_t) -1; + bool subtract_one = false; + Object *o, *array = NULL; + int r; + ChainCacheItem *ci; + + assert(f); + assert(test_object); + + /* Start with the first array in the chain */ + a = first; + + ci = ordered_hashmap_get(f->chain_cache, &first); + if (ci && n > ci->total && ci->begin != 0) { + /* Ah, we have iterated this bisection array chain + * previously! Let's see if we can skip ahead in the + * chain, as far as the last time. But we can't jump + * backwards in the chain, so let's check that + * first. */ + + r = test_object(f, ci->begin, needle); + if (r < 0) + return r; + + if (r == TEST_LEFT) { + /* OK, what we are looking for is right of the + * begin of this EntryArray, so let's jump + * straight to previously cached array in the + * chain */ + + a = ci->array; + n -= ci->total; + t = ci->total; + last_index = ci->last_index; + } + } + + while (a > 0) { + uint64_t left, right, k, lp; + + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array); + if (r < 0) + return r; + + k = journal_file_entry_array_n_items(array); + right = MIN(k, n); + if (right <= 0) + return 0; + + i = right - 1; + lp = p = le64toh(array->entry_array.items[i]); + if (p <= 0) + r = -EBADMSG; + else + r = test_object(f, p, needle); + if (r == -EBADMSG) { + log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short. (1)"); + n = i; + continue; + } + if (r < 0) + return r; + + if (r == TEST_FOUND) + r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + + if (r == TEST_RIGHT) { + left = 0; + right -= 1; + + if (last_index != (uint64_t) -1) { + assert(last_index <= right); + + /* If we cached the last index we + * looked at, let's try to not to jump + * too wildly around and see if we can + * limit the range to look at early to + * the immediate neighbors of the last + * index we looked at. */ + + if (last_index > 0) { + uint64_t x = last_index - 1; + + p = le64toh(array->entry_array.items[x]); + if (p <= 0) + return -EBADMSG; + + r = test_object(f, p, needle); + if (r < 0) + return r; + + if (r == TEST_FOUND) + r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + + if (r == TEST_RIGHT) + right = x; + else + left = x + 1; + } + + if (last_index < right) { + uint64_t y = last_index + 1; + + p = le64toh(array->entry_array.items[y]); + if (p <= 0) + return -EBADMSG; + + r = test_object(f, p, needle); + if (r < 0) + return r; + + if (r == TEST_FOUND) + r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + + if (r == TEST_RIGHT) + right = y; + else + left = y + 1; + } + } + + for (;;) { + if (left == right) { + if (direction == DIRECTION_UP) + subtract_one = true; + + i = left; + goto found; + } + + assert(left < right); + i = (left + right) / 2; + + p = le64toh(array->entry_array.items[i]); + if (p <= 0) + r = -EBADMSG; + else + r = test_object(f, p, needle); + if (r == -EBADMSG) { + log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short. (2)"); + right = n = i; + continue; + } + if (r < 0) + return r; + + if (r == TEST_FOUND) + r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + + if (r == TEST_RIGHT) + right = i; + else + left = i + 1; + } + } + + if (k >= n) { + if (direction == DIRECTION_UP) { + i = n; + subtract_one = true; + goto found; + } + + return 0; + } + + last_p = lp; + + n -= k; + t += k; + last_index = (uint64_t) -1; + a = le64toh(array->entry_array.next_entry_array_offset); + } + + return 0; + +found: + if (subtract_one && t == 0 && i == 0) + return 0; + + /* Let's cache this item for the next invocation */ + chain_cache_put(f->chain_cache, ci, first, a, le64toh(array->entry_array.items[0]), t, subtract_one ? (i > 0 ? i-1 : (uint64_t) -1) : i); + + if (subtract_one && i == 0) + p = last_p; + else if (subtract_one) + p = le64toh(array->entry_array.items[i-1]); + else + p = le64toh(array->entry_array.items[i]); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = p; + + if (idx) + *idx = t + i + (subtract_one ? -1 : 0); + + return 1; +} + +static int generic_array_bisect_plus_one( + JournalFile *f, + uint64_t extra, + uint64_t first, + uint64_t n, + uint64_t needle, + int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle), + direction_t direction, + Object **ret, + uint64_t *offset, + uint64_t *idx) { + + int r; + bool step_back = false; + Object *o; + + assert(f); + assert(test_object); + + if (n <= 0) + return 0; + + /* This bisects the array in object 'first', but first checks + * an extra */ + r = test_object(f, extra, needle); + if (r < 0) + return r; + + if (r == TEST_FOUND) + r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT; + + /* if we are looking with DIRECTION_UP then we need to first + see if in the actual array there is a matching entry, and + return the last one of that. But if there isn't any we need + to return this one. Hence remember this, and return it + below. */ + if (r == TEST_LEFT) + step_back = direction == DIRECTION_UP; + + if (r == TEST_RIGHT) { + if (direction == DIRECTION_DOWN) + goto found; + else + return 0; + } + + r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, offset, idx); + + if (r == 0 && step_back) + goto found; + + if (r > 0 && idx) + (*idx)++; + + return r; + +found: + r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o); + if (r < 0) + return r; + + if (ret) + *ret = o; + + if (offset) + *offset = extra; + + if (idx) + *idx = 0; + + return 1; +} + +_pure_ static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle) { + assert(f); + assert(p > 0); + + if (p == needle) + return TEST_FOUND; + else if (p < needle) + return TEST_LEFT; + else + return TEST_RIGHT; +} + +static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) { + Object *o; + int r; + + assert(f); + assert(p > 0); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + + if (le64toh(o->entry.seqnum) == needle) + return TEST_FOUND; + else if (le64toh(o->entry.seqnum) < needle) + return TEST_LEFT; + else + return TEST_RIGHT; +} + +int journal_file_move_to_entry_by_seqnum( + JournalFile *f, + uint64_t seqnum, + direction_t direction, + Object **ret, + uint64_t *offset) { + assert(f); + assert(f->header); + + return generic_array_bisect(f, + le64toh(f->header->entry_array_offset), + le64toh(f->header->n_entries), + seqnum, + test_object_seqnum, + direction, + ret, offset, NULL); +} + +static int test_object_realtime(JournalFile *f, uint64_t p, uint64_t needle) { + Object *o; + int r; + + assert(f); + assert(p > 0); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + + if (le64toh(o->entry.realtime) == needle) + return TEST_FOUND; + else if (le64toh(o->entry.realtime) < needle) + return TEST_LEFT; + else + return TEST_RIGHT; +} + +int journal_file_move_to_entry_by_realtime( + JournalFile *f, + uint64_t realtime, + direction_t direction, + Object **ret, + uint64_t *offset) { + assert(f); + assert(f->header); + + return generic_array_bisect(f, + le64toh(f->header->entry_array_offset), + le64toh(f->header->n_entries), + realtime, + test_object_realtime, + direction, + ret, offset, NULL); +} + +static int test_object_monotonic(JournalFile *f, uint64_t p, uint64_t needle) { + Object *o; + int r; + + assert(f); + assert(p > 0); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + + if (le64toh(o->entry.monotonic) == needle) + return TEST_FOUND; + else if (le64toh(o->entry.monotonic) < needle) + return TEST_LEFT; + else + return TEST_RIGHT; +} + +static int find_data_object_by_boot_id( + JournalFile *f, + sd_id128_t boot_id, + Object **o, + uint64_t *b) { + + char t[STRLEN("_BOOT_ID=") + 32 + 1] = "_BOOT_ID="; + + sd_id128_to_string(boot_id, t + 9); + return journal_file_find_data_object(f, t, sizeof(t) - 1, o, b); +} + +int journal_file_move_to_entry_by_monotonic( + JournalFile *f, + sd_id128_t boot_id, + uint64_t monotonic, + direction_t direction, + Object **ret, + uint64_t *offset) { + + Object *o; + int r; + + assert(f); + + r = find_data_object_by_boot_id(f, boot_id, &o, NULL); + if (r < 0) + return r; + if (r == 0) + return -ENOENT; + + return generic_array_bisect_plus_one(f, + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + le64toh(o->data.n_entries), + monotonic, + test_object_monotonic, + direction, + ret, offset, NULL); +} + +void journal_file_reset_location(JournalFile *f) { + f->location_type = LOCATION_HEAD; + f->current_offset = 0; + f->current_seqnum = 0; + f->current_realtime = 0; + f->current_monotonic = 0; + zero(f->current_boot_id); + f->current_xor_hash = 0; +} + +void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) { + f->location_type = LOCATION_SEEK; + f->current_offset = offset; + f->current_seqnum = le64toh(o->entry.seqnum); + f->current_realtime = le64toh(o->entry.realtime); + f->current_monotonic = le64toh(o->entry.monotonic); + f->current_boot_id = o->entry.boot_id; + f->current_xor_hash = le64toh(o->entry.xor_hash); +} + +int journal_file_compare_locations(JournalFile *af, JournalFile *bf) { + int r; + + assert(af); + assert(af->header); + assert(bf); + assert(bf->header); + assert(af->location_type == LOCATION_SEEK); + assert(bf->location_type == LOCATION_SEEK); + + /* If contents and timestamps match, these entries are + * identical, even if the seqnum does not match */ + if (sd_id128_equal(af->current_boot_id, bf->current_boot_id) && + af->current_monotonic == bf->current_monotonic && + af->current_realtime == bf->current_realtime && + af->current_xor_hash == bf->current_xor_hash) + return 0; + + if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) { + + /* If this is from the same seqnum source, compare + * seqnums */ + r = CMP(af->current_seqnum, bf->current_seqnum); + if (r != 0) + return r; + + /* Wow! This is weird, different data but the same + * seqnums? Something is borked, but let's make the + * best of it and compare by time. */ + } + + if (sd_id128_equal(af->current_boot_id, bf->current_boot_id)) { + + /* If the boot id matches, compare monotonic time */ + r = CMP(af->current_monotonic, bf->current_monotonic); + if (r != 0) + return r; + } + + /* Otherwise, compare UTC time */ + r = CMP(af->current_realtime, bf->current_realtime); + if (r != 0) + return r; + + /* Finally, compare by contents */ + return CMP(af->current_xor_hash, bf->current_xor_hash); +} + +static int bump_array_index(uint64_t *i, direction_t direction, uint64_t n) { + + /* Increase or decrease the specified index, in the right direction. */ + + if (direction == DIRECTION_DOWN) { + if (*i >= n - 1) + return 0; + + (*i) ++; + } else { + if (*i <= 0) + return 0; + + (*i) --; + } + + return 1; +} + +static bool check_properly_ordered(uint64_t new_offset, uint64_t old_offset, direction_t direction) { + + /* Consider it an error if any of the two offsets is uninitialized */ + if (old_offset == 0 || new_offset == 0) + return false; + + /* If we go down, the new offset must be larger than the old one. */ + return direction == DIRECTION_DOWN ? + new_offset > old_offset : + new_offset < old_offset; +} + +int journal_file_next_entry( + JournalFile *f, + uint64_t p, + direction_t direction, + Object **ret, uint64_t *offset) { + + uint64_t i, n, ofs; + int r; + + assert(f); + assert(f->header); + + n = le64toh(f->header->n_entries); + if (n <= 0) + return 0; + + if (p == 0) + i = direction == DIRECTION_DOWN ? 0 : n - 1; + else { + r = generic_array_bisect(f, + le64toh(f->header->entry_array_offset), + le64toh(f->header->n_entries), + p, + test_object_offset, + DIRECTION_DOWN, + NULL, NULL, + &i); + if (r <= 0) + return r; + + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; + } + + /* And jump to it */ + for (;;) { + r = generic_array_get(f, + le64toh(f->header->entry_array_offset), + i, + ret, &ofs); + if (r > 0) + break; + if (r != -EBADMSG) + return r; + + /* OK, so this entry is borked. Most likely some entry didn't get synced to disk properly, let's see if + * the next one might work for us instead. */ + log_debug_errno(r, "Entry item %" PRIu64 " is bad, skipping over it.", i); + + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; + } + + /* Ensure our array is properly ordered. */ + if (p > 0 && !check_properly_ordered(ofs, p, direction)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "%s: entry array not properly ordered at entry %" PRIu64, + f->path, i); + + if (offset) + *offset = ofs; + + return 1; +} + +int journal_file_next_entry_for_data( + JournalFile *f, + Object *o, uint64_t p, + uint64_t data_offset, + direction_t direction, + Object **ret, uint64_t *offset) { + + uint64_t i, n, ofs; + Object *d; + int r; + + assert(f); + assert(p > 0 || !o); + + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); + if (r < 0) + return r; + + n = le64toh(d->data.n_entries); + if (n <= 0) + return n; + + if (!o) + i = direction == DIRECTION_DOWN ? 0 : n - 1; + else { + if (o->object.type != OBJECT_ENTRY) + return -EINVAL; + + r = generic_array_bisect_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + le64toh(d->data.n_entries), + p, + test_object_offset, + DIRECTION_DOWN, + NULL, NULL, + &i); + + if (r <= 0) + return r; + + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; + } + + for (;;) { + r = generic_array_get_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + i, + ret, &ofs); + if (r > 0) + break; + if (r != -EBADMSG) + return r; + + log_debug_errno(r, "Data entry item %" PRIu64 " is bad, skipping over it.", i); + + r = bump_array_index(&i, direction, n); + if (r <= 0) + return r; + } + + /* Ensure our array is properly ordered. */ + if (p > 0 && check_properly_ordered(ofs, p, direction)) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "%s data entry array not properly ordered at entry %" PRIu64, + f->path, i); + + if (offset) + *offset = ofs; + + return 1; +} + +int journal_file_move_to_entry_by_offset_for_data( + JournalFile *f, + uint64_t data_offset, + uint64_t p, + direction_t direction, + Object **ret, uint64_t *offset) { + + int r; + Object *d; + + assert(f); + + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); + if (r < 0) + return r; + + return generic_array_bisect_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + le64toh(d->data.n_entries), + p, + test_object_offset, + direction, + ret, offset, NULL); +} + +int journal_file_move_to_entry_by_monotonic_for_data( + JournalFile *f, + uint64_t data_offset, + sd_id128_t boot_id, + uint64_t monotonic, + direction_t direction, + Object **ret, uint64_t *offset) { + + Object *o, *d; + int r; + uint64_t b, z; + + assert(f); + + /* First, seek by time */ + r = find_data_object_by_boot_id(f, boot_id, &o, &b); + if (r < 0) + return r; + if (r == 0) + return -ENOENT; + + r = generic_array_bisect_plus_one(f, + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + le64toh(o->data.n_entries), + monotonic, + test_object_monotonic, + direction, + NULL, &z, NULL); + if (r <= 0) + return r; + + /* And now, continue seeking until we find an entry that + * exists in both bisection arrays */ + + for (;;) { + Object *qo; + uint64_t p, q; + + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); + if (r < 0) + return r; + + r = generic_array_bisect_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + le64toh(d->data.n_entries), + z, + test_object_offset, + direction, + NULL, &p, NULL); + if (r <= 0) + return r; + + r = journal_file_move_to_object(f, OBJECT_DATA, b, &o); + if (r < 0) + return r; + + r = generic_array_bisect_plus_one(f, + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + le64toh(o->data.n_entries), + p, + test_object_offset, + direction, + &qo, &q, NULL); + + if (r <= 0) + return r; + + if (p == q) { + if (ret) + *ret = qo; + if (offset) + *offset = q; + + return 1; + } + + z = q; + } +} + +int journal_file_move_to_entry_by_seqnum_for_data( + JournalFile *f, + uint64_t data_offset, + uint64_t seqnum, + direction_t direction, + Object **ret, uint64_t *offset) { + + Object *d; + int r; + + assert(f); + + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); + if (r < 0) + return r; + + return generic_array_bisect_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + le64toh(d->data.n_entries), + seqnum, + test_object_seqnum, + direction, + ret, offset, NULL); +} + +int journal_file_move_to_entry_by_realtime_for_data( + JournalFile *f, + uint64_t data_offset, + uint64_t realtime, + direction_t direction, + Object **ret, uint64_t *offset) { + + Object *d; + int r; + + assert(f); + + r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d); + if (r < 0) + return r; + + return generic_array_bisect_plus_one(f, + le64toh(d->data.entry_offset), + le64toh(d->data.entry_array_offset), + le64toh(d->data.n_entries), + realtime, + test_object_realtime, + direction, + ret, offset, NULL); +} + +void journal_file_dump(JournalFile *f) { + Object *o; + int r; + uint64_t p; + + assert(f); + assert(f->header); + + journal_file_print_header(f); + + p = le64toh(f->header->header_size); + while (p != 0) { + r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); + if (r < 0) + goto fail; + + switch (o->object.type) { + + case OBJECT_UNUSED: + printf("Type: OBJECT_UNUSED\n"); + break; + + case OBJECT_DATA: + printf("Type: OBJECT_DATA\n"); + break; + + case OBJECT_FIELD: + printf("Type: OBJECT_FIELD\n"); + break; + + case OBJECT_ENTRY: + printf("Type: OBJECT_ENTRY seqnum=%"PRIu64" monotonic=%"PRIu64" realtime=%"PRIu64"\n", + le64toh(o->entry.seqnum), + le64toh(o->entry.monotonic), + le64toh(o->entry.realtime)); + break; + + case OBJECT_FIELD_HASH_TABLE: + printf("Type: OBJECT_FIELD_HASH_TABLE\n"); + break; + + case OBJECT_DATA_HASH_TABLE: + printf("Type: OBJECT_DATA_HASH_TABLE\n"); + break; + + case OBJECT_ENTRY_ARRAY: + printf("Type: OBJECT_ENTRY_ARRAY\n"); + break; + + case OBJECT_TAG: + printf("Type: OBJECT_TAG seqnum=%"PRIu64" epoch=%"PRIu64"\n", + le64toh(o->tag.seqnum), + le64toh(o->tag.epoch)); + break; + + default: + printf("Type: unknown (%i)\n", o->object.type); + break; + } + + if (o->object.flags & OBJECT_COMPRESSION_MASK) + printf("Flags: %s\n", + object_compressed_to_string(o->object.flags & OBJECT_COMPRESSION_MASK)); + + if (p == le64toh(f->header->tail_object_offset)) + p = 0; + else + p = p + ALIGN64(le64toh(o->object.size)); + } + + return; +fail: + log_error("File corrupt"); +} + +static const char* format_timestamp_safe(char *buf, size_t l, usec_t t) { + const char *x; + + x = format_timestamp(buf, l, t); + if (x) + return x; + return " --- "; +} + +void journal_file_print_header(JournalFile *f) { + char a[33], b[33], c[33], d[33]; + char x[FORMAT_TIMESTAMP_MAX], y[FORMAT_TIMESTAMP_MAX], z[FORMAT_TIMESTAMP_MAX]; + struct stat st; + char bytes[FORMAT_BYTES_MAX]; + + assert(f); + assert(f->header); + + printf("File path: %s\n" + "File ID: %s\n" + "Machine ID: %s\n" + "Boot ID: %s\n" + "Sequential number ID: %s\n" + "State: %s\n" + "Compatible flags:%s%s\n" + "Incompatible flags:%s%s%s\n" + "Header size: %"PRIu64"\n" + "Arena size: %"PRIu64"\n" + "Data hash table size: %"PRIu64"\n" + "Field hash table size: %"PRIu64"\n" + "Rotate suggested: %s\n" + "Head sequential number: %"PRIu64" (%"PRIx64")\n" + "Tail sequential number: %"PRIu64" (%"PRIx64")\n" + "Head realtime timestamp: %s (%"PRIx64")\n" + "Tail realtime timestamp: %s (%"PRIx64")\n" + "Tail monotonic timestamp: %s (%"PRIx64")\n" + "Objects: %"PRIu64"\n" + "Entry objects: %"PRIu64"\n", + f->path, + sd_id128_to_string(f->header->file_id, a), + sd_id128_to_string(f->header->machine_id, b), + sd_id128_to_string(f->header->boot_id, c), + sd_id128_to_string(f->header->seqnum_id, d), + f->header->state == STATE_OFFLINE ? "OFFLINE" : + f->header->state == STATE_ONLINE ? "ONLINE" : + f->header->state == STATE_ARCHIVED ? "ARCHIVED" : "UNKNOWN", + JOURNAL_HEADER_SEALED(f->header) ? " SEALED" : "", + (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_ANY) ? " ???" : "", + JOURNAL_HEADER_COMPRESSED_XZ(f->header) ? " COMPRESSED-XZ" : "", + JOURNAL_HEADER_COMPRESSED_LZ4(f->header) ? " COMPRESSED-LZ4" : "", + (le32toh(f->header->incompatible_flags) & ~HEADER_INCOMPATIBLE_ANY) ? " ???" : "", + le64toh(f->header->header_size), + le64toh(f->header->arena_size), + le64toh(f->header->data_hash_table_size) / sizeof(HashItem), + le64toh(f->header->field_hash_table_size) / sizeof(HashItem), + yes_no(journal_file_rotate_suggested(f, 0)), + le64toh(f->header->head_entry_seqnum), le64toh(f->header->head_entry_seqnum), + le64toh(f->header->tail_entry_seqnum), le64toh(f->header->tail_entry_seqnum), + format_timestamp_safe(x, sizeof(x), le64toh(f->header->head_entry_realtime)), le64toh(f->header->head_entry_realtime), + format_timestamp_safe(y, sizeof(y), le64toh(f->header->tail_entry_realtime)), le64toh(f->header->tail_entry_realtime), + format_timespan(z, sizeof(z), le64toh(f->header->tail_entry_monotonic), USEC_PER_MSEC), le64toh(f->header->tail_entry_monotonic), + le64toh(f->header->n_objects), + le64toh(f->header->n_entries)); + + if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) + printf("Data objects: %"PRIu64"\n" + "Data hash table fill: %.1f%%\n", + le64toh(f->header->n_data), + 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)))); + + if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) + printf("Field objects: %"PRIu64"\n" + "Field hash table fill: %.1f%%\n", + le64toh(f->header->n_fields), + 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)))); + + if (JOURNAL_HEADER_CONTAINS(f->header, n_tags)) + printf("Tag objects: %"PRIu64"\n", + le64toh(f->header->n_tags)); + if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays)) + printf("Entry array objects: %"PRIu64"\n", + le64toh(f->header->n_entry_arrays)); + + if (fstat(f->fd, &st) >= 0) + printf("Disk usage: %s\n", format_bytes(bytes, sizeof(bytes), (uint64_t) st.st_blocks * 512ULL)); +} + +static int journal_file_warn_btrfs(JournalFile *f) { + unsigned attrs; + int r; + + assert(f); + + /* Before we write anything, check if the COW logic is turned + * off on btrfs. Given our write pattern that is quite + * unfriendly to COW file systems this should greatly improve + * performance on COW file systems, such as btrfs, at the + * expense of data integrity features (which shouldn't be too + * bad, given that we do our own checksumming). */ + + r = btrfs_is_filesystem(f->fd); + if (r < 0) + return log_warning_errno(r, "Failed to determine if journal is on btrfs: %m"); + if (!r) + return 0; + + r = read_attr_fd(f->fd, &attrs); + if (r < 0) + return log_warning_errno(r, "Failed to read file attributes: %m"); + + if (attrs & FS_NOCOW_FL) { + log_debug("Detected btrfs file system with copy-on-write disabled, all is good."); + return 0; + } + + log_notice("Creating journal file %s on a btrfs file system, and copy-on-write is enabled. " + "This is likely to slow down journal access substantially, please consider turning " + "off the copy-on-write file attribute on the journal directory, using chattr +C.", f->path); + + return 1; +} + +int journal_file_open( + int fd, + const char *fname, + int flags, + mode_t mode, + bool compress, + uint64_t compress_threshold_bytes, + bool seal, + JournalMetrics *metrics, + MMapCache *mmap_cache, + Set *deferred_closes, + JournalFile *template, + JournalFile **ret) { + + bool newly_created = false; + JournalFile *f; + void *h; + int r; + + assert(ret); + assert(fd >= 0 || fname); + + if (!IN_SET((flags & O_ACCMODE), O_RDONLY, O_RDWR)) + return -EINVAL; + + if (fname && (flags & O_CREAT) && !endswith(fname, ".journal")) + return -EINVAL; + + f = new(JournalFile, 1); + if (!f) + return -ENOMEM; + + *f = (JournalFile) { + .fd = fd, + .mode = mode, + + .flags = flags, + .prot = prot_from_flags(flags), + .writable = (flags & O_ACCMODE) != O_RDONLY, + +#if HAVE_LZ4 + .compress_lz4 = compress, +#elif HAVE_XZ + .compress_xz = compress, +#endif + .compress_threshold_bytes = compress_threshold_bytes == (uint64_t) -1 ? + DEFAULT_COMPRESS_THRESHOLD : + MAX(MIN_COMPRESS_THRESHOLD, compress_threshold_bytes), +#if HAVE_GCRYPT + .seal = seal, +#endif + }; + + if (DEBUG_LOGGING) { + static int last_seal = -1, last_compress = -1; + static uint64_t last_bytes = UINT64_MAX; + char bytes[FORMAT_BYTES_MAX]; + + if (last_seal != f->seal || + last_compress != JOURNAL_FILE_COMPRESS(f) || + last_bytes != f->compress_threshold_bytes) { + + log_debug("Journal effective settings seal=%s compress=%s compress_threshold_bytes=%s", + yes_no(f->seal), yes_no(JOURNAL_FILE_COMPRESS(f)), + format_bytes(bytes, sizeof bytes, f->compress_threshold_bytes)); + last_seal = f->seal; + last_compress = JOURNAL_FILE_COMPRESS(f); + last_bytes = f->compress_threshold_bytes; + } + } + + if (mmap_cache) + f->mmap = mmap_cache_ref(mmap_cache); + else { + f->mmap = mmap_cache_new(); + if (!f->mmap) { + r = -ENOMEM; + goto fail; + } + } + + if (fname) { + f->path = strdup(fname); + if (!f->path) { + r = -ENOMEM; + goto fail; + } + } else { + assert(fd >= 0); + + /* If we don't know the path, fill in something explanatory and vaguely useful */ + if (asprintf(&f->path, "/proc/self/%i", fd) < 0) { + r = -ENOMEM; + goto fail; + } + } + + f->chain_cache = ordered_hashmap_new(&uint64_hash_ops); + if (!f->chain_cache) { + r = -ENOMEM; + goto fail; + } + + if (f->fd < 0) { + /* We pass O_NONBLOCK here, so that in case somebody pointed us to some character device node or FIFO + * or so, we likely fail quickly than block for long. For regular files O_NONBLOCK has no effect, hence + * it doesn't hurt in that case. */ + + f->fd = open(f->path, f->flags|O_CLOEXEC|O_NONBLOCK, f->mode); + if (f->fd < 0) { + r = -errno; + goto fail; + } + + /* fds we opened here by us should also be closed by us. */ + f->close_fd = true; + + r = fd_nonblock(f->fd, false); + if (r < 0) + goto fail; + } + + f->cache_fd = mmap_cache_add_fd(f->mmap, f->fd); + if (!f->cache_fd) { + r = -ENOMEM; + goto fail; + } + + r = journal_file_fstat(f); + if (r < 0) + goto fail; + + if (f->last_stat.st_size == 0 && f->writable) { + + (void) journal_file_warn_btrfs(f); + + /* Let's attach the creation time to the journal file, so that the vacuuming code knows the age of this + * file even if the file might end up corrupted one day... Ideally we'd just use the creation time many + * file systems maintain for each file, but the API to query this is very new, hence let's emulate this + * via extended attributes. If extended attributes are not supported we'll just skip this, and rely + * solely on mtime/atime/ctime of the file. */ + (void) fd_setcrtime(f->fd, 0); + +#if HAVE_GCRYPT + /* Try to load the FSPRG state, and if we can't, then + * just don't do sealing */ + if (f->seal) { + r = journal_file_fss_load(f); + if (r < 0) + f->seal = false; + } +#endif + + r = journal_file_init_header(f, template); + if (r < 0) + goto fail; + + r = journal_file_fstat(f); + if (r < 0) + goto fail; + + newly_created = true; + } + + if (f->last_stat.st_size < (off_t) HEADER_SIZE_MIN) { + r = -ENODATA; + goto fail; + } + + r = mmap_cache_get(f->mmap, f->cache_fd, f->prot, CONTEXT_HEADER, true, 0, PAGE_ALIGN(sizeof(Header)), &f->last_stat, &h, NULL); + if (r == -EINVAL) { + /* Some file systems (jffs2 or p9fs) don't support mmap() properly (or only read-only + * mmap()), and return EINVAL in that case. Let's propagate that as a more recognizable error + * code. */ + r = -EAFNOSUPPORT; + goto fail; + } + if (r < 0) + goto fail; + + f->header = h; + + if (!newly_created) { + set_clear_with_destructor(deferred_closes, journal_file_close); + + r = journal_file_verify_header(f); + if (r < 0) + goto fail; + } + +#if HAVE_GCRYPT + if (!newly_created && f->writable) { + r = journal_file_fss_load(f); + if (r < 0) + goto fail; + } +#endif + + if (f->writable) { + if (metrics) { + journal_default_metrics(metrics, f->fd); + f->metrics = *metrics; + } else if (template) + f->metrics = template->metrics; + + r = journal_file_refresh_header(f); + if (r < 0) + goto fail; + } + +#if HAVE_GCRYPT + r = journal_file_hmac_setup(f); + if (r < 0) + goto fail; +#endif + + if (newly_created) { + r = journal_file_setup_field_hash_table(f); + if (r < 0) + goto fail; + + r = journal_file_setup_data_hash_table(f); + if (r < 0) + goto fail; + +#if HAVE_GCRYPT + r = journal_file_append_first_tag(f); + if (r < 0) + goto fail; +#endif + } + + if (mmap_cache_got_sigbus(f->mmap, f->cache_fd)) { + r = -EIO; + goto fail; + } + + if (template && template->post_change_timer) { + r = journal_file_enable_post_change_timer( + f, + sd_event_source_get_event(template->post_change_timer), + template->post_change_timer_period); + + if (r < 0) + goto fail; + } + + /* The file is opened now successfully, thus we take possession of any passed in fd. */ + f->close_fd = true; + + *ret = f; + return 0; + +fail: + if (f->cache_fd && mmap_cache_got_sigbus(f->mmap, f->cache_fd)) + r = -EIO; + + (void) journal_file_close(f); + + return r; +} + +int journal_file_archive(JournalFile *f) { + _cleanup_free_ char *p = NULL; + + assert(f); + + if (!f->writable) + return -EINVAL; + + /* Is this a journal file that was passed to us as fd? If so, we synthesized a path name for it, and we refuse + * rotation, since we don't know the actual path, and couldn't rename the file hence. */ + if (path_startswith(f->path, "/proc/self/fd")) + return -EINVAL; + + if (!endswith(f->path, ".journal")) + return -EINVAL; + + if (asprintf(&p, "%.*s@" SD_ID128_FORMAT_STR "-%016"PRIx64"-%016"PRIx64".journal", + (int) strlen(f->path) - 8, f->path, + SD_ID128_FORMAT_VAL(f->header->seqnum_id), + le64toh(f->header->head_entry_seqnum), + le64toh(f->header->head_entry_realtime)) < 0) + return -ENOMEM; + + /* Try to rename the file to the archived version. If the file already was deleted, we'll get ENOENT, let's + * ignore that case. */ + if (rename(f->path, p) < 0 && errno != ENOENT) + return -errno; + + /* Sync the rename to disk */ + (void) fsync_directory_of_file(f->fd); + + /* Set as archive so offlining commits w/state=STATE_ARCHIVED. Previously we would set old_file->header->state + * to STATE_ARCHIVED directly here, but journal_file_set_offline() short-circuits when state != STATE_ONLINE, + * which would result in the rotated journal never getting fsync() called before closing. Now we simply queue + * the archive state by setting an archive bit, leaving the state as STATE_ONLINE so proper offlining + * occurs. */ + f->archive = true; + + /* Currently, btrfs is not very good with out write patterns and fragments heavily. Let's defrag our journal + * files when we archive them */ + f->defrag_on_close = true; + + return 0; +} + +JournalFile* journal_initiate_close( + JournalFile *f, + Set *deferred_closes) { + + int r; + + assert(f); + + if (deferred_closes) { + + r = set_put(deferred_closes, f); + if (r < 0) + log_debug_errno(r, "Failed to add file to deferred close set, closing immediately."); + else { + (void) journal_file_set_offline(f, false); + return NULL; + } + } + + return journal_file_close(f); +} + +int journal_file_rotate( + JournalFile **f, + bool compress, + uint64_t compress_threshold_bytes, + bool seal, + Set *deferred_closes) { + + JournalFile *new_file = NULL; + int r; + + assert(f); + assert(*f); + + r = journal_file_archive(*f); + if (r < 0) + return r; + + r = journal_file_open( + -1, + (*f)->path, + (*f)->flags, + (*f)->mode, + compress, + compress_threshold_bytes, + seal, + NULL, /* metrics */ + (*f)->mmap, + deferred_closes, + *f, /* template */ + &new_file); + + journal_initiate_close(*f, deferred_closes); + *f = new_file; + + return r; +} + +int journal_file_dispose(int dir_fd, const char *fname) { + _cleanup_free_ char *p = NULL; + _cleanup_close_ int fd = -1; + + assert(fname); + + /* Renames a journal file to *.journal~, i.e. to mark it as corruped or otherwise uncleanly shutdown. Note that + * this is done without looking into the file or changing any of its contents. The idea is that this is called + * whenever something is suspicious and we want to move the file away and make clear that it is not accessed + * for writing anymore. */ + + if (!endswith(fname, ".journal")) + return -EINVAL; + + if (asprintf(&p, "%.*s@%016" PRIx64 "-%016" PRIx64 ".journal~", + (int) strlen(fname) - 8, fname, + now(CLOCK_REALTIME), + random_u64()) < 0) + return -ENOMEM; + + if (renameat(dir_fd, fname, dir_fd, p) < 0) + return -errno; + + /* btrfs doesn't cope well with our write pattern and fragments heavily. Let's defrag all files we rotate */ + fd = openat(dir_fd, p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + log_debug_errno(errno, "Failed to open file for defragmentation/FS_NOCOW_FL, ignoring: %m"); + else { + (void) chattr_fd(fd, 0, FS_NOCOW_FL, NULL); + (void) btrfs_defrag_fd(fd); + } + + return 0; +} + +int journal_file_open_reliably( + const char *fname, + int flags, + mode_t mode, + bool compress, + uint64_t compress_threshold_bytes, + bool seal, + JournalMetrics *metrics, + MMapCache *mmap_cache, + Set *deferred_closes, + JournalFile *template, + JournalFile **ret) { + + int r; + + r = journal_file_open(-1, fname, flags, mode, compress, compress_threshold_bytes, seal, metrics, mmap_cache, + deferred_closes, template, ret); + if (!IN_SET(r, + -EBADMSG, /* Corrupted */ + -ENODATA, /* Truncated */ + -EHOSTDOWN, /* Other machine */ + -EPROTONOSUPPORT, /* Incompatible feature */ + -EBUSY, /* Unclean shutdown */ + -ESHUTDOWN, /* Already archived */ + -EIO, /* IO error, including SIGBUS on mmap */ + -EIDRM, /* File has been deleted */ + -ETXTBSY)) /* File is from the future */ + return r; + + if ((flags & O_ACCMODE) == O_RDONLY) + return r; + + if (!(flags & O_CREAT)) + return r; + + if (!endswith(fname, ".journal")) + return r; + + /* The file is corrupted. Rotate it away and try it again (but only once) */ + log_warning_errno(r, "File %s corrupted or uncleanly shut down, renaming and replacing.", fname); + + r = journal_file_dispose(AT_FDCWD, fname); + if (r < 0) + return r; + + return journal_file_open(-1, fname, flags, mode, compress, compress_threshold_bytes, seal, metrics, mmap_cache, + deferred_closes, template, ret); +} + +int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p) { + uint64_t i, n; + uint64_t q, xor_hash = 0; + int r; + EntryItem *items; + dual_timestamp ts; + const sd_id128_t *boot_id; + + assert(from); + assert(to); + assert(o); + assert(p); + + if (!to->writable) + return -EPERM; + + ts.monotonic = le64toh(o->entry.monotonic); + ts.realtime = le64toh(o->entry.realtime); + boot_id = &o->entry.boot_id; + + n = journal_file_entry_n_items(o); + /* alloca() can't take 0, hence let's allocate at least one */ + items = newa(EntryItem, MAX(1u, n)); + + for (i = 0; i < n; i++) { + uint64_t l, h; + le64_t le_hash; + size_t t; + void *data; + Object *u; + + q = le64toh(o->entry.items[i].object_offset); + le_hash = o->entry.items[i].hash; + + r = journal_file_move_to_object(from, OBJECT_DATA, q, &o); + if (r < 0) + return r; + + if (le_hash != o->data.hash) + return -EBADMSG; + + l = le64toh(o->object.size) - offsetof(Object, data.payload); + t = (size_t) l; + + /* We hit the limit on 32bit machines */ + if ((uint64_t) t != l) + return -E2BIG; + + if (o->object.flags & OBJECT_COMPRESSION_MASK) { +#if HAVE_XZ || HAVE_LZ4 + size_t rsize = 0; + + r = decompress_blob(o->object.flags & OBJECT_COMPRESSION_MASK, + o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize, 0); + if (r < 0) + return r; + + data = from->compress_buffer; + l = rsize; +#else + return -EPROTONOSUPPORT; +#endif + } else + data = o->data.payload; + + r = journal_file_append_data(to, data, l, &u, &h); + if (r < 0) + return r; + + xor_hash ^= le64toh(u->data.hash); + items[i].object_offset = htole64(h); + items[i].hash = u->data.hash; + + r = journal_file_move_to_object(from, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + } + + r = journal_file_append_entry_internal(to, &ts, boot_id, xor_hash, items, n, + NULL, NULL, NULL); + + if (mmap_cache_got_sigbus(to->mmap, to->cache_fd)) + return -EIO; + + return r; +} + +void journal_reset_metrics(JournalMetrics *m) { + assert(m); + + /* Set everything to "pick automatic values". */ + + *m = (JournalMetrics) { + .min_use = (uint64_t) -1, + .max_use = (uint64_t) -1, + .min_size = (uint64_t) -1, + .max_size = (uint64_t) -1, + .keep_free = (uint64_t) -1, + .n_max_files = (uint64_t) -1, + }; +} + +void journal_default_metrics(JournalMetrics *m, int fd) { + char a[FORMAT_BYTES_MAX], b[FORMAT_BYTES_MAX], c[FORMAT_BYTES_MAX], d[FORMAT_BYTES_MAX], e[FORMAT_BYTES_MAX]; + struct statvfs ss; + uint64_t fs_size = 0; + + assert(m); + assert(fd >= 0); + + if (fstatvfs(fd, &ss) >= 0) + fs_size = ss.f_frsize * ss.f_blocks; + else + log_debug_errno(errno, "Failed to determine disk size: %m"); + + if (m->max_use == (uint64_t) -1) { + + if (fs_size > 0) + m->max_use = CLAMP(PAGE_ALIGN(fs_size / 10), /* 10% of file system size */ + MAX_USE_LOWER, MAX_USE_UPPER); + else + m->max_use = MAX_USE_LOWER; + } else { + m->max_use = PAGE_ALIGN(m->max_use); + + if (m->max_use != 0 && m->max_use < JOURNAL_FILE_SIZE_MIN*2) + m->max_use = JOURNAL_FILE_SIZE_MIN*2; + } + + if (m->min_use == (uint64_t) -1) { + if (fs_size > 0) + m->min_use = CLAMP(PAGE_ALIGN(fs_size / 50), /* 2% of file system size */ + MIN_USE_LOW, MIN_USE_HIGH); + else + m->min_use = MIN_USE_LOW; + } + + if (m->min_use > m->max_use) + m->min_use = m->max_use; + + if (m->max_size == (uint64_t) -1) + m->max_size = MIN(PAGE_ALIGN(m->max_use / 8), /* 8 chunks */ + MAX_SIZE_UPPER); + else + m->max_size = PAGE_ALIGN(m->max_size); + + if (m->max_size != 0) { + if (m->max_size < JOURNAL_FILE_SIZE_MIN) + m->max_size = JOURNAL_FILE_SIZE_MIN; + + if (m->max_use != 0 && m->max_size*2 > m->max_use) + m->max_use = m->max_size*2; + } + + if (m->min_size == (uint64_t) -1) + m->min_size = JOURNAL_FILE_SIZE_MIN; + else + m->min_size = CLAMP(PAGE_ALIGN(m->min_size), + JOURNAL_FILE_SIZE_MIN, + m->max_size ?: UINT64_MAX); + + if (m->keep_free == (uint64_t) -1) { + if (fs_size > 0) + m->keep_free = MIN(PAGE_ALIGN(fs_size / 20), /* 5% of file system size */ + KEEP_FREE_UPPER); + else + m->keep_free = DEFAULT_KEEP_FREE; + } + + if (m->n_max_files == (uint64_t) -1) + m->n_max_files = DEFAULT_N_MAX_FILES; + + log_debug("Fixed min_use=%s max_use=%s max_size=%s min_size=%s keep_free=%s n_max_files=%" PRIu64, + format_bytes(a, sizeof(a), m->min_use), + format_bytes(b, sizeof(b), m->max_use), + format_bytes(c, sizeof(c), m->max_size), + format_bytes(d, sizeof(d), m->min_size), + format_bytes(e, sizeof(e), m->keep_free), + m->n_max_files); +} + +int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) { + assert(f); + assert(f->header); + assert(from || to); + + if (from) { + if (f->header->head_entry_realtime == 0) + return -ENOENT; + + *from = le64toh(f->header->head_entry_realtime); + } + + if (to) { + if (f->header->tail_entry_realtime == 0) + return -ENOENT; + + *to = le64toh(f->header->tail_entry_realtime); + } + + return 1; +} + +int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *from, usec_t *to) { + Object *o; + uint64_t p; + int r; + + assert(f); + assert(from || to); + + r = find_data_object_by_boot_id(f, boot_id, &o, &p); + if (r <= 0) + return r; + + if (le64toh(o->data.n_entries) <= 0) + return 0; + + if (from) { + r = journal_file_move_to_object(f, OBJECT_ENTRY, le64toh(o->data.entry_offset), &o); + if (r < 0) + return r; + + *from = le64toh(o->entry.monotonic); + } + + if (to) { + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + r = generic_array_get_plus_one(f, + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + le64toh(o->data.n_entries)-1, + &o, NULL); + if (r <= 0) + return r; + + *to = le64toh(o->entry.monotonic); + } + + return 1; +} + +bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec) { + assert(f); + assert(f->header); + + /* If we gained new header fields we gained new features, + * hence suggest a rotation */ + if (le64toh(f->header->header_size) < sizeof(Header)) { + log_debug("%s uses an outdated header, suggesting rotation.", f->path); + return true; + } + + /* Let's check if the hash tables grew over a certain fill + * level (75%, borrowing this value from Java's hash table + * implementation), and if so suggest a rotation. To calculate + * the fill level we need the n_data field, which only exists + * in newer versions. */ + + if (JOURNAL_HEADER_CONTAINS(f->header, n_data)) + if (le64toh(f->header->n_data) * 4ULL > (le64toh(f->header->data_hash_table_size) / sizeof(HashItem)) * 3ULL) { + log_debug("Data hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items, %llu file size, %"PRIu64" bytes per hash table item), suggesting rotation.", + f->path, + 100.0 * (double) le64toh(f->header->n_data) / ((double) (le64toh(f->header->data_hash_table_size) / sizeof(HashItem))), + le64toh(f->header->n_data), + le64toh(f->header->data_hash_table_size) / sizeof(HashItem), + (unsigned long long) f->last_stat.st_size, + f->last_stat.st_size / le64toh(f->header->n_data)); + return true; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_fields)) + if (le64toh(f->header->n_fields) * 4ULL > (le64toh(f->header->field_hash_table_size) / sizeof(HashItem)) * 3ULL) { + log_debug("Field hash table of %s has a fill level at %.1f (%"PRIu64" of %"PRIu64" items), suggesting rotation.", + f->path, + 100.0 * (double) le64toh(f->header->n_fields) / ((double) (le64toh(f->header->field_hash_table_size) / sizeof(HashItem))), + le64toh(f->header->n_fields), + le64toh(f->header->field_hash_table_size) / sizeof(HashItem)); + return true; + } + + /* Are the data objects properly indexed by field objects? */ + if (JOURNAL_HEADER_CONTAINS(f->header, n_data) && + JOURNAL_HEADER_CONTAINS(f->header, n_fields) && + le64toh(f->header->n_data) > 0 && + le64toh(f->header->n_fields) == 0) + return true; + + if (max_file_usec > 0) { + usec_t t, h; + + h = le64toh(f->header->head_entry_realtime); + t = now(CLOCK_REALTIME); + + if (h > 0 && t > h + max_file_usec) + return true; + } + + return false; +} diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h new file mode 100644 index 00000000..502f1f56 --- /dev/null +++ b/src/journal/journal-file.h @@ -0,0 +1,263 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#if HAVE_GCRYPT +# include +#endif + +#include "sd-event.h" +#include "sd-id128.h" + +#include "hashmap.h" +#include "journal-def.h" +#include "mmap-cache.h" +#include "sparse-endian.h" +#include "time-util.h" + +typedef struct JournalMetrics { + /* For all these: -1 means "pick automatically", and 0 means "no limit enforced" */ + uint64_t max_size; /* how large journal files grow at max */ + uint64_t min_size; /* how large journal files grow at least */ + uint64_t max_use; /* how much disk space to use in total at max, keep_free permitting */ + uint64_t min_use; /* how much disk space to use in total at least, even if keep_free says not to */ + uint64_t keep_free; /* how much to keep free on disk */ + uint64_t n_max_files; /* how many files to keep around at max */ +} JournalMetrics; + +typedef enum direction { + DIRECTION_UP, + DIRECTION_DOWN +} direction_t; + +typedef enum LocationType { + /* The first and last entries, resp. */ + LOCATION_HEAD, + LOCATION_TAIL, + + /* We already read the entry we currently point to, and the + * next one to read should probably not be this one again. */ + LOCATION_DISCRETE, + + /* We should seek to the precise location specified, and + * return it, as we haven't read it yet. */ + LOCATION_SEEK +} LocationType; + +typedef enum OfflineState { + OFFLINE_JOINED, + OFFLINE_SYNCING, + OFFLINE_OFFLINING, + OFFLINE_CANCEL, + OFFLINE_AGAIN_FROM_SYNCING, + OFFLINE_AGAIN_FROM_OFFLINING, + OFFLINE_DONE +} OfflineState; + +typedef struct JournalFile { + int fd; + MMapFileDescriptor *cache_fd; + + mode_t mode; + + int flags; + int prot; + bool writable:1; + bool compress_xz:1; + bool compress_lz4:1; + bool seal:1; + bool defrag_on_close:1; + bool close_fd:1; + bool archive:1; + + direction_t last_direction; + LocationType location_type; + uint64_t last_n_entries; + + char *path; + struct stat last_stat; + usec_t last_stat_usec; + + Header *header; + HashItem *data_hash_table; + HashItem *field_hash_table; + + uint64_t current_offset; + uint64_t current_seqnum; + uint64_t current_realtime; + uint64_t current_monotonic; + sd_id128_t current_boot_id; + uint64_t current_xor_hash; + + JournalMetrics metrics; + MMapCache *mmap; + + sd_event_source *post_change_timer; + usec_t post_change_timer_period; + + OrderedHashmap *chain_cache; + + pthread_t offline_thread; + volatile OfflineState offline_state; + + unsigned last_seen_generation; + + uint64_t compress_threshold_bytes; +#if HAVE_XZ || HAVE_LZ4 + void *compress_buffer; + size_t compress_buffer_size; +#endif + +#if HAVE_GCRYPT + gcry_md_hd_t hmac; + bool hmac_running; + + FSSHeader *fss_file; + size_t fss_file_size; + + uint64_t fss_start_usec; + uint64_t fss_interval_usec; + + void *fsprg_state; + size_t fsprg_state_size; + + void *fsprg_seed; + size_t fsprg_seed_size; +#endif +} JournalFile; + +int journal_file_open( + int fd, + const char *fname, + int flags, + mode_t mode, + bool compress, + uint64_t compress_threshold_bytes, + bool seal, + JournalMetrics *metrics, + MMapCache *mmap_cache, + Set *deferred_closes, + JournalFile *template, + JournalFile **ret); + +int journal_file_set_offline(JournalFile *f, bool wait); +bool journal_file_is_offlining(JournalFile *f); +JournalFile* journal_file_close(JournalFile *j); +DEFINE_TRIVIAL_CLEANUP_FUNC(JournalFile*, journal_file_close); + +int journal_file_open_reliably( + const char *fname, + int flags, + mode_t mode, + bool compress, + uint64_t compress_threshold_bytes, + bool seal, + JournalMetrics *metrics, + MMapCache *mmap_cache, + Set *deferred_closes, + JournalFile *template, + JournalFile **ret); + +#define ALIGN64(x) (((x) + 7ULL) & ~7ULL) +#define VALID64(x) (((x) & 7ULL) == 0ULL) + +/* Use six characters to cover the offsets common in smallish journal + * files without adding too many zeros. */ +#define OFSfmt "%06"PRIx64 + +static inline bool VALID_REALTIME(uint64_t u) { + /* This considers timestamps until the year 3112 valid. That should be plenty room... */ + return u > 0 && u < (1ULL << 55); +} + +static inline bool VALID_MONOTONIC(uint64_t u) { + /* This considers timestamps until 1142 years of runtime valid. */ + return u < (1ULL << 55); +} + +static inline bool VALID_EPOCH(uint64_t u) { + /* This allows changing the key for 1142 years, every usec. */ + return u < (1ULL << 55); +} + +#define JOURNAL_HEADER_CONTAINS(h, field) \ + (le64toh((h)->header_size) >= offsetof(Header, field) + sizeof((h)->field)) + +#define JOURNAL_HEADER_SEALED(h) \ + (!!(le32toh((h)->compatible_flags) & HEADER_COMPATIBLE_SEALED)) + +#define JOURNAL_HEADER_COMPRESSED_XZ(h) \ + (!!(le32toh((h)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_XZ)) + +#define JOURNAL_HEADER_COMPRESSED_LZ4(h) \ + (!!(le32toh((h)->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED_LZ4)) + +int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret); + +uint64_t journal_file_entry_n_items(Object *o) _pure_; +uint64_t journal_file_entry_array_n_items(Object *o) _pure_; +uint64_t journal_file_hash_table_n_items(Object *o) _pure_; + +int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset); +int journal_file_append_entry( + JournalFile *f, + const dual_timestamp *ts, + const sd_id128_t *boot_id, + const struct iovec iovec[], unsigned n_iovec, + uint64_t *seqno, + Object **ret, + uint64_t *offset); + +int journal_file_find_data_object(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset); +int journal_file_find_data_object_with_hash(JournalFile *f, const void *data, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset); + +int journal_file_find_field_object(JournalFile *f, const void *field, uint64_t size, Object **ret, uint64_t *offset); +int journal_file_find_field_object_with_hash(JournalFile *f, const void *field, uint64_t size, uint64_t hash, Object **ret, uint64_t *offset); + +void journal_file_reset_location(JournalFile *f); +void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset); +int journal_file_compare_locations(JournalFile *af, JournalFile *bf); +int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret, uint64_t *offset); + +int journal_file_next_entry_for_data(JournalFile *f, Object *o, uint64_t p, uint64_t data_offset, direction_t direction, Object **ret, uint64_t *offset); + +int journal_file_move_to_entry_by_seqnum(JournalFile *f, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_realtime(JournalFile *f, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_monotonic(JournalFile *f, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset); + +int journal_file_move_to_entry_by_offset_for_data(JournalFile *f, uint64_t data_offset, uint64_t p, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_seqnum_for_data(JournalFile *f, uint64_t data_offset, uint64_t seqnum, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_realtime_for_data(JournalFile *f, uint64_t data_offset, uint64_t realtime, direction_t direction, Object **ret, uint64_t *offset); +int journal_file_move_to_entry_by_monotonic_for_data(JournalFile *f, uint64_t data_offset, sd_id128_t boot_id, uint64_t monotonic, direction_t direction, Object **ret, uint64_t *offset); + +int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p); + +void journal_file_dump(JournalFile *f); +void journal_file_print_header(JournalFile *f); + +int journal_file_archive(JournalFile *f); +JournalFile* journal_initiate_close(JournalFile *f, Set *deferred_closes); +int journal_file_rotate(JournalFile **f, bool compress, uint64_t compress_threshold_bytes, bool seal, Set *deferred_closes); + +int journal_file_dispose(int dir_fd, const char *fname); + +void journal_file_post_change(JournalFile *f); +int journal_file_enable_post_change_timer(JournalFile *f, sd_event *e, usec_t t); + +void journal_reset_metrics(JournalMetrics *m); +void journal_default_metrics(JournalMetrics *m, int fd); + +int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to); +int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to); + +bool journal_file_rotate_suggested(JournalFile *f, usec_t max_file_usec); + +int journal_file_map_data_hash_table(JournalFile *f); +int journal_file_map_field_hash_table(JournalFile *f); + +static inline bool JOURNAL_FILE_COMPRESS(JournalFile *f) { + assert(f); + return f->compress_xz || f->compress_lz4; +} diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h new file mode 100644 index 00000000..80a69da4 --- /dev/null +++ b/src/journal/journal-internal.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "sd-id128.h" +#include "sd-journal.h" + +#include "hashmap.h" +#include "journal-def.h" +#include "journal-file.h" +#include "list.h" +#include "set.h" + +typedef struct Match Match; +typedef struct Location Location; +typedef struct Directory Directory; + +typedef enum MatchType { + MATCH_DISCRETE, + MATCH_OR_TERM, + MATCH_AND_TERM +} MatchType; + +struct Match { + MatchType type; + Match *parent; + LIST_FIELDS(Match, matches); + + /* For concrete matches */ + char *data; + size_t size; + le64_t le_hash; + + /* For terms */ + LIST_HEAD(Match, matches); +}; + +struct Location { + LocationType type; + + bool seqnum_set; + bool realtime_set; + bool monotonic_set; + bool xor_hash_set; + + uint64_t seqnum; + sd_id128_t seqnum_id; + + uint64_t realtime; + + uint64_t monotonic; + sd_id128_t boot_id; + + uint64_t xor_hash; +}; + +struct Directory { + char *path; + int wd; + bool is_root; + unsigned last_seen_generation; +}; + +struct sd_journal { + int toplevel_fd; + + char *path; + char *prefix; + + OrderedHashmap *files; + IteratedCache *files_cache; + MMapCache *mmap; + + Location current_location; + + JournalFile *current_file; + uint64_t current_field; + + Match *level0, *level1, *level2; + + pid_t original_pid; + + int inotify_fd; + unsigned current_invalidate_counter, last_invalidate_counter; + usec_t last_process_usec; + unsigned generation; + + /* Iterating through unique fields and their data values */ + char *unique_field; + JournalFile *unique_file; + uint64_t unique_offset; + + /* Iterating through known fields */ + JournalFile *fields_file; + uint64_t fields_offset; + uint64_t fields_hash_table_index; + char *fields_buffer; + size_t fields_buffer_allocated; + + int flags; + + bool on_network:1; + bool no_new_files:1; + bool no_inotify:1; + bool unique_file_lost:1; /* File we were iterating over got + removed, and there were no more + files, so sd_j_enumerate_unique + will return a value equal to 0. */ + bool fields_file_lost:1; + bool has_runtime_files:1; + bool has_persistent_files:1; + + size_t data_threshold; + + Hashmap *directories_by_path; + Hashmap *directories_by_wd; + + Hashmap *errors; +}; + +char *journal_make_match_string(sd_journal *j); +void journal_print_header(sd_journal *j); + +#define JOURNAL_FOREACH_DATA_RETVAL(j, data, l, retval) \ + for (sd_journal_restart_data(j); ((retval) = sd_journal_enumerate_data((j), &(data), &(l))) > 0; ) diff --git a/src/journal/journal-qrcode.c b/src/journal/journal-qrcode.c new file mode 100644 index 00000000..678654f7 --- /dev/null +++ b/src/journal/journal-qrcode.c @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "fileio.h" +#include "journal-qrcode.h" +#include "macro.h" + +#define WHITE_ON_BLACK "\033[40;37;1m" +#define NORMAL "\033[0m" + +static void print_border(FILE *output, unsigned width) { + unsigned x, y; + + /* Four rows of border */ + for (y = 0; y < 4; y += 2) { + fputs(WHITE_ON_BLACK, output); + + for (x = 0; x < 4 + width + 4; x++) + fputs("\342\226\210", output); + + fputs(NORMAL "\n", output); + } +} + +int print_qr_code( + FILE *output, + const void *seed, + size_t seed_size, + uint64_t start, + uint64_t interval, + const char *hn, + sd_id128_t machine) { + + FILE *f; + char *url = NULL; + size_t url_size = 0, i; + QRcode* qr; + unsigned x, y; + + assert(seed); + assert(seed_size > 0); + + f = open_memstream_unlocked(&url, &url_size); + if (!f) + return -ENOMEM; + + fputs("fss://", f); + + for (i = 0; i < seed_size; i++) { + if (i > 0 && i % 3 == 0) + fputc('-', f); + fprintf(f, "%02x", ((uint8_t*) seed)[i]); + } + + fprintf(f, "/%"PRIx64"-%"PRIx64"?machine=" SD_ID128_FORMAT_STR, + start, + interval, + SD_ID128_FORMAT_VAL(machine)); + + if (hn) + fprintf(f, ";hostname=%s", hn); + + if (ferror(f)) { + fclose(f); + free(url); + return -ENOMEM; + } + + fclose(f); + + qr = QRcode_encodeString(url, 0, QR_ECLEVEL_L, QR_MODE_8, 1); + free(url); + + if (!qr) + return -ENOMEM; + + print_border(output, qr->width); + + for (y = 0; y < (unsigned) qr->width; y += 2) { + const uint8_t *row1, *row2; + + row1 = qr->data + qr->width * y; + row2 = row1 + qr->width; + + fputs(WHITE_ON_BLACK, output); + for (x = 0; x < 4; x++) + fputs("\342\226\210", output); + + for (x = 0; x < (unsigned) qr->width; x ++) { + bool a, b; + + a = row1[x] & 1; + b = (y+1) < (unsigned) qr->width ? (row2[x] & 1) : false; + + if (a && b) + fputc(' ', output); + else if (a) + fputs("\342\226\204", output); + else if (b) + fputs("\342\226\200", output); + else + fputs("\342\226\210", output); + } + + for (x = 0; x < 4; x++) + fputs("\342\226\210", output); + fputs(NORMAL "\n", output); + } + + print_border(output, qr->width); + + QRcode_free(qr); + return 0; +} diff --git a/src/journal/journal-qrcode.h b/src/journal/journal-qrcode.h new file mode 100644 index 00000000..0774608e --- /dev/null +++ b/src/journal/journal-qrcode.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-id128.h" + +int print_qr_code(FILE *f, const void *seed, size_t seed_size, uint64_t start, uint64_t interval, const char *hn, sd_id128_t machine); diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c new file mode 100644 index 00000000..912ecef7 --- /dev/null +++ b/src/journal/journal-send.c @@ -0,0 +1,542 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#define SD_JOURNAL_SUPPRESS_LOCATION + +#include "sd-journal.h" + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "io-util.h" +#include "memfd-util.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "tmpfile-util.h" + +#define SNDBUF_SIZE (8*1024*1024) + +#define ALLOCA_CODE_FUNC(f, func) \ + do { \ + size_t _fl; \ + const char *_func = (func); \ + char **_f = &(f); \ + _fl = strlen(_func) + 1; \ + *_f = newa(char, _fl + 10); \ + memcpy(*_f, "CODE_FUNC=", 10); \ + memcpy(*_f + 10, _func, _fl); \ + } while (false) + +/* We open a single fd, and we'll share it with the current process, + * all its threads, and all its subprocesses. This means we need to + * initialize it atomically, and need to operate on it atomically + * never assuming we are the only user */ + +static int journal_fd(void) { + int fd; + static int fd_plus_one = 0; + +retry: + if (fd_plus_one > 0) + return fd_plus_one - 1; + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) + return -errno; + + fd_inc_sndbuf(fd, SNDBUF_SIZE); + + if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) { + safe_close(fd); + goto retry; + } + + return fd; +} + +_public_ int sd_journal_print(int priority, const char *format, ...) { + int r; + va_list ap; + + va_start(ap, format); + r = sd_journal_printv(priority, format, ap); + va_end(ap); + + return r; +} + +_public_ int sd_journal_printv(int priority, const char *format, va_list ap) { + + /* FIXME: Instead of limiting things to LINE_MAX we could do a + C99 variable-length array on the stack here in a loop. */ + + char buffer[8 + LINE_MAX], p[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int) + 1]; + struct iovec iov[2]; + + assert_return(priority >= 0, -EINVAL); + assert_return(priority <= 7, -EINVAL); + assert_return(format, -EINVAL); + + xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK); + + memcpy(buffer, "MESSAGE=", 8); + vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap); + + /* Strip trailing whitespace, keep prefix whitespace. */ + (void) strstrip(buffer); + + /* Suppress empty lines */ + if (isempty(buffer+8)) + return 0; + + iov[0] = IOVEC_MAKE_STRING(buffer); + iov[1] = IOVEC_MAKE_STRING(p); + + return sd_journal_sendv(iov, 2); +} + +_printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) { + PROTECT_ERRNO; + int r, n = 0, i = 0, j; + struct iovec *iov = NULL; + + assert(_iov); + + if (extra > 0) { + n = MAX(extra * 2, extra + 4); + iov = malloc0(n * sizeof(struct iovec)); + if (!iov) { + r = -ENOMEM; + goto fail; + } + + i = extra; + } + + while (format) { + struct iovec *c; + char *buffer; + va_list aq; + + if (i >= n) { + n = MAX(i*2, 4); + c = realloc(iov, n * sizeof(struct iovec)); + if (!c) { + r = -ENOMEM; + goto fail; + } + + iov = c; + } + + va_copy(aq, ap); + if (vasprintf(&buffer, format, aq) < 0) { + va_end(aq); + r = -ENOMEM; + goto fail; + } + va_end(aq); + + VA_FORMAT_ADVANCE(format, ap); + + (void) strstrip(buffer); /* strip trailing whitespace, keep prefixing whitespace */ + + iov[i++] = IOVEC_MAKE_STRING(buffer); + + format = va_arg(ap, char *); + } + + *_iov = iov; + + return i; + +fail: + for (j = 0; j < i; j++) + free(iov[j].iov_base); + + free(iov); + + return r; +} + +_public_ int sd_journal_send(const char *format, ...) { + int r, i, j; + va_list ap; + struct iovec *iov = NULL; + + va_start(ap, format); + i = fill_iovec_sprintf(format, ap, 0, &iov); + va_end(ap); + + if (_unlikely_(i < 0)) { + r = i; + goto finish; + } + + r = sd_journal_sendv(iov, i); + +finish: + for (j = 0; j < i; j++) + free(iov[j].iov_base); + + free(iov); + + return r; +} + +_public_ int sd_journal_sendv(const struct iovec *iov, int n) { + PROTECT_ERRNO; + int fd, r; + _cleanup_close_ int buffer_fd = -1; + struct iovec *w; + uint64_t *l; + int i, j = 0; + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/socket", + }; + struct msghdr mh = { + .msg_name = (struct sockaddr*) &sa.sa, + .msg_namelen = SOCKADDR_UN_LEN(sa.un), + }; + ssize_t k; + bool have_syslog_identifier = false; + bool seal = true; + + assert_return(iov, -EINVAL); + assert_return(n > 0, -EINVAL); + + w = newa(struct iovec, n * 5 + 3); + l = newa(uint64_t, n); + + for (i = 0; i < n; i++) { + char *c, *nl; + + if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1)) + return -EINVAL; + + c = memchr(iov[i].iov_base, '=', iov[i].iov_len); + if (_unlikely_(!c || c == iov[i].iov_base)) + return -EINVAL; + + have_syslog_identifier = have_syslog_identifier || + (c == (char *) iov[i].iov_base + 17 && + startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER")); + + nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len); + if (nl) { + if (_unlikely_(nl < c)) + return -EINVAL; + + /* Already includes a newline? Bummer, then + * let's write the variable name, then a + * newline, then the size (64bit LE), followed + * by the data and a final newline */ + + w[j++] = IOVEC_MAKE(iov[i].iov_base, c - (char*) iov[i].iov_base); + w[j++] = IOVEC_MAKE_STRING("\n"); + + l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1); + w[j++] = IOVEC_MAKE(&l[i], sizeof(uint64_t)); + + w[j++] = IOVEC_MAKE(c + 1, iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1); + } else + /* Nothing special? Then just add the line and + * append a newline */ + w[j++] = iov[i]; + + w[j++] = IOVEC_MAKE_STRING("\n"); + } + + if (!have_syslog_identifier && + string_is_safe(program_invocation_short_name)) { + + /* Implicitly add program_invocation_short_name, if it + * is not set explicitly. We only do this for + * program_invocation_short_name, and nothing else + * since everything else is much nicer to retrieve + * from the outside. */ + + w[j++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER="); + w[j++] = IOVEC_MAKE_STRING(program_invocation_short_name); + w[j++] = IOVEC_MAKE_STRING("\n"); + } + + fd = journal_fd(); + if (_unlikely_(fd < 0)) + return fd; + + mh.msg_iov = w; + mh.msg_iovlen = j; + + k = sendmsg(fd, &mh, MSG_NOSIGNAL); + if (k >= 0) + return 0; + + /* Fail silently if the journal is not available */ + if (errno == ENOENT) + return 0; + + if (!IN_SET(errno, EMSGSIZE, ENOBUFS)) + return -errno; + + /* Message doesn't fit... Let's dump the data in a memfd or + * temporary file and just pass a file descriptor of it to the + * other side. + * + * For the temporary files we use /dev/shm instead of /tmp + * here, since we want this to be a tmpfs, and one that is + * available from early boot on and where unprivileged users + * can create files. */ + buffer_fd = memfd_new(NULL); + if (buffer_fd < 0) { + if (buffer_fd == -ENOSYS) { + buffer_fd = open_tmpfile_unlinkable("/dev/shm", O_RDWR | O_CLOEXEC); + if (buffer_fd < 0) + return buffer_fd; + + seal = false; + } else + return buffer_fd; + } + + n = writev(buffer_fd, w, j); + if (n < 0) + return -errno; + + if (seal) { + r = memfd_set_sealed(buffer_fd); + if (r < 0) + return r; + } + + r = send_one_fd_sa(fd, buffer_fd, mh.msg_name, mh.msg_namelen, 0); + if (r == -ENOENT) + /* Fail silently if the journal is not available */ + return 0; + return r; +} + +static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) { + PROTECT_ERRNO; + size_t n, k; + + k = isempty(message) ? 0 : strlen(message) + 2; + n = 8 + k + 256 + 1; + + for (;;) { + char buffer[n]; + char* j; + + errno = 0; + j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k); + if (errno == 0) { + char error[STRLEN("ERRNO=") + DECIMAL_STR_MAX(int) + 1]; + + if (j != buffer + 8 + k) + memmove(buffer + 8 + k, j, strlen(j)+1); + + memcpy(buffer, "MESSAGE=", 8); + + if (k > 0) { + memcpy(buffer + 8, message, k - 2); + memcpy(buffer + 8 + k - 2, ": ", 2); + } + + xsprintf(error, "ERRNO=%i", _saved_errno_); + + assert_cc(3 == LOG_ERR); + iov[skip+0] = IOVEC_MAKE_STRING("PRIORITY=3"); + iov[skip+1] = IOVEC_MAKE_STRING(buffer); + iov[skip+2] = IOVEC_MAKE_STRING(error); + + return sd_journal_sendv(iov, skip + 3); + } + + if (errno != ERANGE) + return -errno; + + n *= 2; + } +} + +_public_ int sd_journal_perror(const char *message) { + struct iovec iovec[3]; + + return fill_iovec_perror_and_send(message, 0, iovec); +} + +_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) { + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/stdout", + }; + _cleanup_close_ int fd = -1; + char *header; + size_t l; + int r; + + assert_return(priority >= 0, -EINVAL); + assert_return(priority <= 7, -EINVAL); + + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + if (fd < 0) + return -errno; + + r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return -errno; + + if (shutdown(fd, SHUT_RD) < 0) + return -errno; + + (void) fd_inc_sndbuf(fd, SNDBUF_SIZE); + + identifier = strempty(identifier); + + l = strlen(identifier); + header = newa(char, l + 1 + 1 + 2 + 2 + 2 + 2 + 2); + + memcpy(header, identifier, l); + header[l++] = '\n'; + header[l++] = '\n'; /* unit id */ + header[l++] = '0' + priority; + header[l++] = '\n'; + header[l++] = '0' + !!level_prefix; + header[l++] = '\n'; + header[l++] = '0'; + header[l++] = '\n'; + header[l++] = '0'; + header[l++] = '\n'; + header[l++] = '0'; + header[l++] = '\n'; + + r = loop_write(fd, header, l, false); + if (r < 0) + return r; + + return TAKE_FD(fd); +} + +_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) { + int r; + va_list ap; + + va_start(ap, format); + r = sd_journal_printv_with_location(priority, file, line, func, format, ap); + va_end(ap); + + return r; +} + +_public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) { + char buffer[8 + LINE_MAX], p[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int) + 1]; + struct iovec iov[5]; + char *f; + + assert_return(priority >= 0, -EINVAL); + assert_return(priority <= 7, -EINVAL); + assert_return(format, -EINVAL); + + xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK); + + memcpy(buffer, "MESSAGE=", 8); + vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap); + + /* Strip trailing whitespace, keep prefixing whitespace */ + (void) strstrip(buffer); + + /* Suppress empty lines */ + if (isempty(buffer+8)) + return 0; + + /* func is initialized from __func__ which is not a macro, but + * a static const char[], hence cannot easily be prefixed with + * CODE_FUNC=, hence let's do it manually here. */ + ALLOCA_CODE_FUNC(f, func); + + iov[0] = IOVEC_MAKE_STRING(buffer); + iov[1] = IOVEC_MAKE_STRING(p); + iov[2] = IOVEC_MAKE_STRING(file); + iov[3] = IOVEC_MAKE_STRING(line); + iov[4] = IOVEC_MAKE_STRING(f); + + return sd_journal_sendv(iov, ELEMENTSOF(iov)); +} + +_public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) { + _cleanup_free_ struct iovec *iov = NULL; + int r, i, j; + va_list ap; + char *f; + + va_start(ap, format); + i = fill_iovec_sprintf(format, ap, 3, &iov); + va_end(ap); + + if (_unlikely_(i < 0)) { + r = i; + goto finish; + } + + ALLOCA_CODE_FUNC(f, func); + + iov[0] = IOVEC_MAKE_STRING(file); + iov[1] = IOVEC_MAKE_STRING(line); + iov[2] = IOVEC_MAKE_STRING(f); + + r = sd_journal_sendv(iov, i); + +finish: + for (j = 3; j < i; j++) + free(iov[j].iov_base); + + return r; +} + +_public_ int sd_journal_sendv_with_location( + const char *file, const char *line, + const char *func, + const struct iovec *iov, int n) { + + struct iovec *niov; + char *f; + + assert_return(iov, -EINVAL); + assert_return(n > 0, -EINVAL); + + niov = newa(struct iovec, n + 3); + memcpy(niov, iov, sizeof(struct iovec) * n); + + ALLOCA_CODE_FUNC(f, func); + + niov[n++] = IOVEC_MAKE_STRING(file); + niov[n++] = IOVEC_MAKE_STRING(line); + niov[n++] = IOVEC_MAKE_STRING(f); + + return sd_journal_sendv(niov, n); +} + +_public_ int sd_journal_perror_with_location( + const char *file, const char *line, + const char *func, + const char *message) { + + struct iovec iov[6]; + char *f; + + ALLOCA_CODE_FUNC(f, func); + + iov[0] = IOVEC_MAKE_STRING(file); + iov[1] = IOVEC_MAKE_STRING(line); + iov[2] = IOVEC_MAKE_STRING(f); + + return fill_iovec_perror_and_send(message, 3, iov); +} diff --git a/src/journal/journal-vacuum.c b/src/journal/journal-vacuum.c new file mode 100644 index 00000000..87d65896 --- /dev/null +++ b/src/journal/journal-vacuum.c @@ -0,0 +1,321 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "journal-def.h" +#include "journal-file.h" +#include "journal-vacuum.h" +#include "sort-util.h" +#include "string-util.h" +#include "time-util.h" +#include "xattr-util.h" + +struct vacuum_info { + uint64_t usage; + char *filename; + + uint64_t realtime; + + sd_id128_t seqnum_id; + uint64_t seqnum; + bool have_seqnum; +}; + +static int vacuum_compare(const struct vacuum_info *a, const struct vacuum_info *b) { + int r; + + if (a->have_seqnum && b->have_seqnum && + sd_id128_equal(a->seqnum_id, b->seqnum_id)) + return CMP(a->seqnum, b->seqnum); + + r = CMP(a->realtime, b->realtime); + if (r != 0) + return r; + + if (a->have_seqnum && b->have_seqnum) + return memcmp(&a->seqnum_id, &b->seqnum_id, 16); + + return strcmp(a->filename, b->filename); +} + +static void patch_realtime( + int fd, + const char *fn, + const struct stat *st, + unsigned long long *realtime) { + + usec_t x, crtime = 0; + + /* The timestamp was determined by the file name, but let's + * see if the file might actually be older than the file name + * suggested... */ + + assert(fd >= 0); + assert(fn); + assert(st); + assert(realtime); + + x = timespec_load(&st->st_ctim); + if (x > 0 && x != USEC_INFINITY && x < *realtime) + *realtime = x; + + x = timespec_load(&st->st_atim); + if (x > 0 && x != USEC_INFINITY && x < *realtime) + *realtime = x; + + x = timespec_load(&st->st_mtim); + if (x > 0 && x != USEC_INFINITY && x < *realtime) + *realtime = x; + + /* Let's read the original creation time, if possible. Ideally + * we'd just query the creation time the FS might provide, but + * unfortunately there's currently no sane API to query + * it. Hence let's implement this manually... */ + + if (fd_getcrtime_at(fd, fn, &crtime, 0) >= 0) { + if (crtime < *realtime) + *realtime = crtime; + } +} + +static int journal_file_empty(int dir_fd, const char *name) { + _cleanup_close_ int fd; + struct stat st; + le64_t n_entries; + ssize_t n; + + fd = openat(dir_fd, name, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK|O_NOATIME); + if (fd < 0) { + /* Maybe failed due to O_NOATIME and lack of privileges? */ + fd = openat(dir_fd, name, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK); + if (fd < 0) + return -errno; + } + + if (fstat(fd, &st) < 0) + return -errno; + + /* If an offline file doesn't even have a header we consider it empty */ + if (st.st_size < (off_t) sizeof(Header)) + return 1; + + /* If the number of entries is empty, we consider it empty, too */ + n = pread(fd, &n_entries, sizeof(n_entries), offsetof(Header, n_entries)); + if (n < 0) + return -errno; + if (n != sizeof(n_entries)) + return -EIO; + + return le64toh(n_entries) <= 0; +} + +int journal_directory_vacuum( + const char *directory, + uint64_t max_use, + uint64_t n_max_files, + usec_t max_retention_usec, + usec_t *oldest_usec, + bool verbose) { + + uint64_t sum = 0, freed = 0, n_active_files = 0; + size_t n_list = 0, n_allocated = 0, i; + _cleanup_closedir_ DIR *d = NULL; + struct vacuum_info *list = NULL; + usec_t retention_limit = 0; + char sbytes[FORMAT_BYTES_MAX]; + struct dirent *de; + int r; + + assert(directory); + + if (max_use <= 0 && max_retention_usec <= 0 && n_max_files <= 0) + return 0; + + if (max_retention_usec > 0) + retention_limit = usec_sub_unsigned(now(CLOCK_REALTIME), max_retention_usec); + + d = opendir(directory); + if (!d) + return -errno; + + FOREACH_DIRENT_ALL(de, d, r = -errno; goto finish) { + + unsigned long long seqnum = 0, realtime; + _cleanup_free_ char *p = NULL; + sd_id128_t seqnum_id; + bool have_seqnum; + uint64_t size; + struct stat st; + size_t q; + + if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { + log_debug_errno(errno, "Failed to stat file %s while vacuuming, ignoring: %m", de->d_name); + continue; + } + + if (!S_ISREG(st.st_mode)) + continue; + + q = strlen(de->d_name); + + if (endswith(de->d_name, ".journal")) { + + /* Vacuum archived files. Active files are + * left around */ + + if (q < 1 + 32 + 1 + 16 + 1 + 16 + 8) { + n_active_files++; + continue; + } + + if (de->d_name[q-8-16-1] != '-' || + de->d_name[q-8-16-1-16-1] != '-' || + de->d_name[q-8-16-1-16-1-32-1] != '@') { + n_active_files++; + continue; + } + + p = strdup(de->d_name); + if (!p) { + r = -ENOMEM; + goto finish; + } + + de->d_name[q-8-16-1-16-1] = 0; + if (sd_id128_from_string(de->d_name + q-8-16-1-16-1-32, &seqnum_id) < 0) { + n_active_files++; + continue; + } + + if (sscanf(de->d_name + q-8-16-1-16, "%16llx-%16llx.journal", &seqnum, &realtime) != 2) { + n_active_files++; + continue; + } + + have_seqnum = true; + + } else if (endswith(de->d_name, ".journal~")) { + unsigned long long tmp; + + /* Vacuum corrupted files */ + + if (q < 1 + 16 + 1 + 16 + 8 + 1) { + n_active_files++; + continue; + } + + if (de->d_name[q-1-8-16-1] != '-' || + de->d_name[q-1-8-16-1-16-1] != '@') { + n_active_files++; + continue; + } + + p = strdup(de->d_name); + if (!p) { + r = -ENOMEM; + goto finish; + } + + if (sscanf(de->d_name + q-1-8-16-1-16, "%16llx-%16llx.journal~", &realtime, &tmp) != 2) { + n_active_files++; + continue; + } + + have_seqnum = false; + } else { + /* We do not vacuum unknown files! */ + log_debug("Not vacuuming unknown file %s.", de->d_name); + continue; + } + + size = 512UL * (uint64_t) st.st_blocks; + + r = journal_file_empty(dirfd(d), p); + if (r < 0) { + log_debug_errno(r, "Failed check if %s is empty, ignoring: %m", p); + continue; + } + if (r > 0) { + /* Always vacuum empty non-online files. */ + + r = unlinkat_deallocate(dirfd(d), p, 0); + if (r >= 0) { + + log_full(verbose ? LOG_INFO : LOG_DEBUG, + "Deleted empty archived journal %s/%s (%s).", directory, p, format_bytes(sbytes, sizeof(sbytes), size)); + + freed += size; + } else if (r != -ENOENT) + log_warning_errno(r, "Failed to delete empty archived journal %s/%s: %m", directory, p); + + continue; + } + + patch_realtime(dirfd(d), p, &st, &realtime); + + if (!GREEDY_REALLOC(list, n_allocated, n_list + 1)) { + r = -ENOMEM; + goto finish; + } + + list[n_list++] = (struct vacuum_info) { + .filename = TAKE_PTR(p), + .usage = size, + .seqnum = seqnum, + .realtime = realtime, + .seqnum_id = seqnum_id, + .have_seqnum = have_seqnum, + }; + + sum += size; + } + + typesafe_qsort(list, n_list, vacuum_compare); + + for (i = 0; i < n_list; i++) { + uint64_t left; + + left = n_active_files + n_list - i; + + if ((max_retention_usec <= 0 || list[i].realtime >= retention_limit) && + (max_use <= 0 || sum <= max_use) && + (n_max_files <= 0 || left <= n_max_files)) + break; + + r = unlinkat_deallocate(dirfd(d), list[i].filename, 0); + if (r >= 0) { + log_full(verbose ? LOG_INFO : LOG_DEBUG, "Deleted archived journal %s/%s (%s).", directory, list[i].filename, format_bytes(sbytes, sizeof(sbytes), list[i].usage)); + freed += list[i].usage; + + if (list[i].usage < sum) + sum -= list[i].usage; + else + sum = 0; + + } else if (r != -ENOENT) + log_warning_errno(r, "Failed to delete archived journal %s/%s: %m", directory, list[i].filename); + } + + if (oldest_usec && i < n_list && (*oldest_usec == 0 || list[i].realtime < *oldest_usec)) + *oldest_usec = list[i].realtime; + + r = 0; + +finish: + for (i = 0; i < n_list; i++) + free(list[i].filename); + free(list); + + log_full(verbose ? LOG_INFO : LOG_DEBUG, "Vacuuming done, freed %s of archived journals from %s.", format_bytes(sbytes, sizeof(sbytes), freed), directory); + + return r; +} diff --git a/src/journal/journal-vacuum.h b/src/journal/journal-vacuum.h new file mode 100644 index 00000000..0b336ac0 --- /dev/null +++ b/src/journal/journal-vacuum.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "time-util.h" + +int journal_directory_vacuum(const char *directory, uint64_t max_use, uint64_t n_max_files, usec_t max_retention_usec, usec_t *oldest_usec, bool verbose); diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c new file mode 100644 index 00000000..344b7b01 --- /dev/null +++ b/src/journal/journal-verify.c @@ -0,0 +1,1320 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "compress.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "journal-authenticate.h" +#include "journal-def.h" +#include "journal-file.h" +#include "journal-verify.h" +#include "lookup3.h" +#include "macro.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "util.h" + +static void draw_progress(uint64_t p, usec_t *last_usec) { + unsigned n, i, j, k; + usec_t z, x; + + if (!on_tty()) + return; + + z = now(CLOCK_MONOTONIC); + x = *last_usec; + + if (x != 0 && x + 40 * USEC_PER_MSEC > z) + return; + + *last_usec = z; + + n = (3 * columns()) / 4; + j = (n * (unsigned) p) / 65535ULL; + k = n - j; + + fputs("\r", stdout); + if (colors_enabled()) + fputs("\x1B[?25l" ANSI_HIGHLIGHT_GREEN, stdout); + + for (i = 0; i < j; i++) + fputs("\xe2\x96\x88", stdout); + + fputs(ansi_normal(), stdout); + + for (i = 0; i < k; i++) + fputs("\xe2\x96\x91", stdout); + + printf(" %3"PRIu64"%%", 100U * p / 65535U); + + fputs("\r", stdout); + if (colors_enabled()) + fputs("\x1B[?25h", stdout); + + fflush(stdout); +} + +static uint64_t scale_progress(uint64_t scale, uint64_t p, uint64_t m) { + /* Calculates scale * p / m, but handles m == 0 safely, and saturates. + * Currently all callers use m >= 1, but we keep the check to be defensive. + */ + + if (p >= m || m == 0) // lgtm[cpp/constant-comparison] + return scale; + + return scale * p / m; +} + +static void flush_progress(void) { + unsigned n, i; + + if (!on_tty()) + return; + + n = (3 * columns()) / 4; + + putchar('\r'); + + for (i = 0; i < n + 5; i++) + putchar(' '); + + putchar('\r'); + fflush(stdout); +} + +#define debug(_offset, _fmt, ...) do { \ + flush_progress(); \ + log_debug(OFSfmt": " _fmt, _offset, ##__VA_ARGS__); \ + } while (0) + +#define warning(_offset, _fmt, ...) do { \ + flush_progress(); \ + log_warning(OFSfmt": " _fmt, _offset, ##__VA_ARGS__); \ + } while (0) + +#define error(_offset, _fmt, ...) do { \ + flush_progress(); \ + log_error(OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \ + } while (0) + +#define error_errno(_offset, error, _fmt, ...) do { \ + flush_progress(); \ + log_error_errno(error, OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \ + } while (0) + +static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) { + uint64_t i; + + assert(f); + assert(offset); + assert(o); + + /* This does various superficial tests about the length an + * possible field values. It does not follow any references to + * other objects. */ + + if ((o->object.flags & OBJECT_COMPRESSED_XZ) && + o->object.type != OBJECT_DATA) { + error(offset, "Found compressed object that isn't of type DATA, which is not allowed."); + return -EBADMSG; + } + + switch (o->object.type) { + + case OBJECT_DATA: { + uint64_t h1, h2; + int compression, r; + + if (le64toh(o->data.entry_offset) == 0) + warning(offset, "Unused data (entry_offset==0)"); + + if ((le64toh(o->data.entry_offset) == 0) ^ (le64toh(o->data.n_entries) == 0)) { + error(offset, "Bad n_entries: %"PRIu64, le64toh(o->data.n_entries)); + return -EBADMSG; + } + + if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0) { + error(offset, "Bad object size (<= %zu): %"PRIu64, + offsetof(DataObject, payload), + le64toh(o->object.size)); + return -EBADMSG; + } + + h1 = le64toh(o->data.hash); + + compression = o->object.flags & OBJECT_COMPRESSION_MASK; + if (compression) { + _cleanup_free_ void *b = NULL; + size_t alloc = 0, b_size; + + r = decompress_blob(compression, + o->data.payload, + le64toh(o->object.size) - offsetof(Object, data.payload), + &b, &alloc, &b_size, 0); + if (r < 0) { + error_errno(offset, r, "%s decompression failed: %m", + object_compressed_to_string(compression)); + return r; + } + + h2 = hash64(b, b_size); + } else + h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload)); + + if (h1 != h2) { + error(offset, "Invalid hash (%08"PRIx64" vs. %08"PRIx64, h1, h2); + return -EBADMSG; + } + + if (!VALID64(le64toh(o->data.next_hash_offset)) || + !VALID64(le64toh(o->data.next_field_offset)) || + !VALID64(le64toh(o->data.entry_offset)) || + !VALID64(le64toh(o->data.entry_array_offset))) { + error(offset, "Invalid offset (next_hash_offset="OFSfmt", next_field_offset="OFSfmt", entry_offset="OFSfmt", entry_array_offset="OFSfmt, + le64toh(o->data.next_hash_offset), + le64toh(o->data.next_field_offset), + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset)); + return -EBADMSG; + } + + break; + } + + case OBJECT_FIELD: + if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0) { + error(offset, + "Bad field size (<= %zu): %"PRIu64, + offsetof(FieldObject, payload), + le64toh(o->object.size)); + return -EBADMSG; + } + + if (!VALID64(le64toh(o->field.next_hash_offset)) || + !VALID64(le64toh(o->field.head_data_offset))) { + error(offset, + "Invalid offset (next_hash_offset="OFSfmt", head_data_offset="OFSfmt, + le64toh(o->field.next_hash_offset), + le64toh(o->field.head_data_offset)); + return -EBADMSG; + } + break; + + case OBJECT_ENTRY: + if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0) { + error(offset, + "Bad entry size (<= %zu): %"PRIu64, + offsetof(EntryObject, items), + le64toh(o->object.size)); + return -EBADMSG; + } + + if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0) { + error(offset, + "Invalid number items in entry: %"PRIu64, + (le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem)); + return -EBADMSG; + } + + if (le64toh(o->entry.seqnum) <= 0) { + error(offset, + "Invalid entry seqnum: %"PRIx64, + le64toh(o->entry.seqnum)); + return -EBADMSG; + } + + if (!VALID_REALTIME(le64toh(o->entry.realtime))) { + error(offset, + "Invalid entry realtime timestamp: %"PRIu64, + le64toh(o->entry.realtime)); + return -EBADMSG; + } + + if (!VALID_MONOTONIC(le64toh(o->entry.monotonic))) { + error(offset, + "Invalid entry monotonic timestamp: %"PRIu64, + le64toh(o->entry.monotonic)); + return -EBADMSG; + } + + for (i = 0; i < journal_file_entry_n_items(o); i++) { + if (le64toh(o->entry.items[i].object_offset) == 0 || + !VALID64(le64toh(o->entry.items[i].object_offset))) { + error(offset, + "Invalid entry item (%"PRIu64"/%"PRIu64" offset: "OFSfmt, + i, journal_file_entry_n_items(o), + le64toh(o->entry.items[i].object_offset)); + return -EBADMSG; + } + } + + break; + + case OBJECT_DATA_HASH_TABLE: + case OBJECT_FIELD_HASH_TABLE: + if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0 || + (le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0) { + error(offset, + "Invalid %s hash table size: %"PRIu64, + o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field", + le64toh(o->object.size)); + return -EBADMSG; + } + + for (i = 0; i < journal_file_hash_table_n_items(o); i++) { + if (o->hash_table.items[i].head_hash_offset != 0 && + !VALID64(le64toh(o->hash_table.items[i].head_hash_offset))) { + error(offset, + "Invalid %s hash table item (%"PRIu64"/%"PRIu64") head_hash_offset: "OFSfmt, + o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field", + i, journal_file_hash_table_n_items(o), + le64toh(o->hash_table.items[i].head_hash_offset)); + return -EBADMSG; + } + if (o->hash_table.items[i].tail_hash_offset != 0 && + !VALID64(le64toh(o->hash_table.items[i].tail_hash_offset))) { + error(offset, + "Invalid %s hash table item (%"PRIu64"/%"PRIu64") tail_hash_offset: "OFSfmt, + o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field", + i, journal_file_hash_table_n_items(o), + le64toh(o->hash_table.items[i].tail_hash_offset)); + return -EBADMSG; + } + + if ((o->hash_table.items[i].head_hash_offset != 0) != + (o->hash_table.items[i].tail_hash_offset != 0)) { + error(offset, + "Invalid %s hash table item (%"PRIu64"/%"PRIu64"): head_hash_offset="OFSfmt" tail_hash_offset="OFSfmt, + o->object.type == OBJECT_DATA_HASH_TABLE ? "data" : "field", + i, journal_file_hash_table_n_items(o), + le64toh(o->hash_table.items[i].head_hash_offset), + le64toh(o->hash_table.items[i].tail_hash_offset)); + return -EBADMSG; + } + } + + break; + + case OBJECT_ENTRY_ARRAY: + if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0 || + (le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0) { + error(offset, + "Invalid object entry array size: %"PRIu64, + le64toh(o->object.size)); + return -EBADMSG; + } + + if (!VALID64(le64toh(o->entry_array.next_entry_array_offset))) { + error(offset, + "Invalid object entry array next_entry_array_offset: "OFSfmt, + le64toh(o->entry_array.next_entry_array_offset)); + return -EBADMSG; + } + + for (i = 0; i < journal_file_entry_array_n_items(o); i++) + if (le64toh(o->entry_array.items[i]) != 0 && + !VALID64(le64toh(o->entry_array.items[i]))) { + error(offset, + "Invalid object entry array item (%"PRIu64"/%"PRIu64"): "OFSfmt, + i, journal_file_entry_array_n_items(o), + le64toh(o->entry_array.items[i])); + return -EBADMSG; + } + + break; + + case OBJECT_TAG: + if (le64toh(o->object.size) != sizeof(TagObject)) { + error(offset, + "Invalid object tag size: %"PRIu64, + le64toh(o->object.size)); + return -EBADMSG; + } + + if (!VALID_EPOCH(le64toh(o->tag.epoch))) { + error(offset, + "Invalid object tag epoch: %"PRIu64, + le64toh(o->tag.epoch)); + return -EBADMSG; + } + + break; + } + + return 0; +} + +static int write_uint64(int fd, uint64_t p) { + ssize_t k; + + k = write(fd, &p, sizeof(p)); + if (k < 0) + return -errno; + if (k != sizeof(p)) + return -EIO; + + return 0; +} + +static int contains_uint64(MMapCache *m, MMapFileDescriptor *f, uint64_t n, uint64_t p) { + uint64_t a, b; + int r; + + assert(m); + assert(f); + + /* Bisection ... */ + + a = 0; b = n; + while (a < b) { + uint64_t c, *z; + + c = (a + b) / 2; + + r = mmap_cache_get(m, f, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z, NULL); + if (r < 0) + return r; + + if (*z == p) + return 1; + + if (a + 1 >= b) + return 0; + + if (p < *z) + b = c; + else + a = c; + } + + return 0; +} + +static int entry_points_to_data( + JournalFile *f, + MMapFileDescriptor *cache_entry_fd, + uint64_t n_entries, + uint64_t entry_p, + uint64_t data_p) { + + int r; + uint64_t i, n, a; + Object *o; + bool found = false; + + assert(f); + assert(cache_entry_fd); + + if (!contains_uint64(f->mmap, cache_entry_fd, n_entries, entry_p)) { + error(data_p, "Data object references invalid entry at "OFSfmt, entry_p); + return -EBADMSG; + } + + r = journal_file_move_to_object(f, OBJECT_ENTRY, entry_p, &o); + if (r < 0) + return r; + + n = journal_file_entry_n_items(o); + for (i = 0; i < n; i++) + if (le64toh(o->entry.items[i].object_offset) == data_p) { + found = true; + break; + } + + if (!found) { + error(entry_p, "Data object at "OFSfmt" not referenced by linked entry", data_p); + return -EBADMSG; + } + + /* Check if this entry is also in main entry array. Since the + * main entry array has already been verified we can rely on + * its consistency. */ + + i = 0; + n = le64toh(f->header->n_entries); + a = le64toh(f->header->entry_array_offset); + + while (i < n) { + uint64_t m, u; + + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); + if (r < 0) + return r; + + m = journal_file_entry_array_n_items(o); + u = MIN(n - i, m); + + if (entry_p <= le64toh(o->entry_array.items[u-1])) { + uint64_t x, y, z; + + x = 0; + y = u; + + while (x < y) { + z = (x + y) / 2; + + if (le64toh(o->entry_array.items[z]) == entry_p) + return 0; + + if (x + 1 >= y) + break; + + if (entry_p < le64toh(o->entry_array.items[z])) + y = z; + else + x = z; + } + + error(entry_p, "Entry object doesn't exist in main entry array"); + return -EBADMSG; + } + + i += u; + a = le64toh(o->entry_array.next_entry_array_offset); + } + + return 0; +} + +static int verify_data( + JournalFile *f, + Object *o, uint64_t p, + MMapFileDescriptor *cache_entry_fd, uint64_t n_entries, + MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays) { + + uint64_t i, n, a, last, q; + int r; + + assert(f); + assert(o); + assert(cache_entry_fd); + assert(cache_entry_array_fd); + + n = le64toh(o->data.n_entries); + a = le64toh(o->data.entry_array_offset); + + /* Entry array means at least two objects */ + if (a && n < 2) { + error(p, "Entry array present (entry_array_offset="OFSfmt", but n_entries=%"PRIu64")", a, n); + return -EBADMSG; + } + + if (n == 0) + return 0; + + /* We already checked that earlier */ + assert(o->data.entry_offset); + + last = q = le64toh(o->data.entry_offset); + r = entry_points_to_data(f, cache_entry_fd, n_entries, q, p); + if (r < 0) + return r; + + i = 1; + while (i < n) { + uint64_t next, m, j; + + if (a == 0) { + error(p, "Array chain too short"); + return -EBADMSG; + } + + if (!contains_uint64(f->mmap, cache_entry_array_fd, n_entry_arrays, a)) { + error(p, "Invalid array offset "OFSfmt, a); + return -EBADMSG; + } + + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); + if (r < 0) + return r; + + next = le64toh(o->entry_array.next_entry_array_offset); + if (next != 0 && next <= a) { + error(p, "Array chain has cycle (jumps back from "OFSfmt" to "OFSfmt")", a, next); + return -EBADMSG; + } + + m = journal_file_entry_array_n_items(o); + for (j = 0; i < n && j < m; i++, j++) { + + q = le64toh(o->entry_array.items[j]); + if (q <= last) { + error(p, "Data object's entry array not sorted"); + return -EBADMSG; + } + last = q; + + r = entry_points_to_data(f, cache_entry_fd, n_entries, q, p); + if (r < 0) + return r; + + /* Pointer might have moved, reposition */ + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); + if (r < 0) + return r; + } + + a = next; + } + + return 0; +} + +static int verify_hash_table( + JournalFile *f, + MMapFileDescriptor *cache_data_fd, uint64_t n_data, + MMapFileDescriptor *cache_entry_fd, uint64_t n_entries, + MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays, + usec_t *last_usec, + bool show_progress) { + + uint64_t i, n; + int r; + + assert(f); + assert(cache_data_fd); + assert(cache_entry_fd); + assert(cache_entry_array_fd); + assert(last_usec); + + n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem); + if (n <= 0) + return 0; + + r = journal_file_map_data_hash_table(f); + if (r < 0) + return log_error_errno(r, "Failed to map data hash table: %m"); + + for (i = 0; i < n; i++) { + uint64_t last = 0, p; + + if (show_progress) + draw_progress(0xC000 + scale_progress(0x3FFF, i, n), last_usec); + + p = le64toh(f->data_hash_table[i].head_hash_offset); + while (p != 0) { + Object *o; + uint64_t next; + + if (!contains_uint64(f->mmap, cache_data_fd, n_data, p)) { + error(p, "Invalid data object at hash entry %"PRIu64" of %"PRIu64, i, n); + return -EBADMSG; + } + + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + next = le64toh(o->data.next_hash_offset); + if (next != 0 && next <= p) { + error(p, "Hash chain has a cycle in hash entry %"PRIu64" of %"PRIu64, i, n); + return -EBADMSG; + } + + if (le64toh(o->data.hash) % n != i) { + error(p, "Hash value mismatch in hash entry %"PRIu64" of %"PRIu64, i, n); + return -EBADMSG; + } + + r = verify_data(f, o, p, cache_entry_fd, n_entries, cache_entry_array_fd, n_entry_arrays); + if (r < 0) + return r; + + last = p; + p = next; + } + + if (last != le64toh(f->data_hash_table[i].tail_hash_offset)) { + error(p, "Tail hash pointer mismatch in hash table"); + return -EBADMSG; + } + } + + return 0; +} + +static int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p) { + uint64_t n, h, q; + int r; + assert(f); + + n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem); + if (n <= 0) + return 0; + + r = journal_file_map_data_hash_table(f); + if (r < 0) + return log_error_errno(r, "Failed to map data hash table: %m"); + + h = hash % n; + + q = le64toh(f->data_hash_table[h].head_hash_offset); + while (q != 0) { + Object *o; + + if (p == q) + return 1; + + r = journal_file_move_to_object(f, OBJECT_DATA, q, &o); + if (r < 0) + return r; + + q = le64toh(o->data.next_hash_offset); + } + + return 0; +} + +static int verify_entry( + JournalFile *f, + Object *o, uint64_t p, + MMapFileDescriptor *cache_data_fd, uint64_t n_data) { + + uint64_t i, n; + int r; + + assert(f); + assert(o); + assert(cache_data_fd); + + n = journal_file_entry_n_items(o); + for (i = 0; i < n; i++) { + uint64_t q, h; + Object *u; + + q = le64toh(o->entry.items[i].object_offset); + h = le64toh(o->entry.items[i].hash); + + if (!contains_uint64(f->mmap, cache_data_fd, n_data, q)) { + error(p, "Invalid data object of entry"); + return -EBADMSG; + } + + r = journal_file_move_to_object(f, OBJECT_DATA, q, &u); + if (r < 0) + return r; + + if (le64toh(u->data.hash) != h) { + error(p, "Hash mismatch for data object of entry"); + return -EBADMSG; + } + + r = data_object_in_hash_table(f, h, q); + if (r < 0) + return r; + if (r == 0) { + error(p, "Data object missing from hash table"); + return -EBADMSG; + } + } + + return 0; +} + +static int verify_entry_array( + JournalFile *f, + MMapFileDescriptor *cache_data_fd, uint64_t n_data, + MMapFileDescriptor *cache_entry_fd, uint64_t n_entries, + MMapFileDescriptor *cache_entry_array_fd, uint64_t n_entry_arrays, + usec_t *last_usec, + bool show_progress) { + + uint64_t i = 0, a, n, last = 0; + int r; + + assert(f); + assert(cache_data_fd); + assert(cache_entry_fd); + assert(cache_entry_array_fd); + assert(last_usec); + + n = le64toh(f->header->n_entries); + a = le64toh(f->header->entry_array_offset); + while (i < n) { + uint64_t next, m, j; + Object *o; + + if (show_progress) + draw_progress(0x8000 + scale_progress(0x3FFF, i, n), last_usec); + + if (a == 0) { + error(a, "Array chain too short at %"PRIu64" of %"PRIu64, i, n); + return -EBADMSG; + } + + if (!contains_uint64(f->mmap, cache_entry_array_fd, n_entry_arrays, a)) { + error(a, "Invalid array %"PRIu64" of %"PRIu64, i, n); + return -EBADMSG; + } + + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); + if (r < 0) + return r; + + next = le64toh(o->entry_array.next_entry_array_offset); + if (next != 0 && next <= a) { + error(a, "Array chain has cycle at %"PRIu64" of %"PRIu64" (jumps back from to "OFSfmt")", i, n, next); + return -EBADMSG; + } + + m = journal_file_entry_array_n_items(o); + for (j = 0; i < n && j < m; i++, j++) { + uint64_t p; + + p = le64toh(o->entry_array.items[j]); + if (p <= last) { + error(a, "Entry array not sorted at %"PRIu64" of %"PRIu64, i, n); + return -EBADMSG; + } + last = p; + + if (!contains_uint64(f->mmap, cache_entry_fd, n_entries, p)) { + error(a, "Invalid array entry at %"PRIu64" of %"PRIu64, i, n); + return -EBADMSG; + } + + r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); + if (r < 0) + return r; + + r = verify_entry(f, o, p, cache_data_fd, n_data); + if (r < 0) + return r; + + /* Pointer might have moved, reposition */ + r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); + if (r < 0) + return r; + } + + a = next; + } + + return 0; +} + +int journal_file_verify( + JournalFile *f, + const char *key, + usec_t *first_contained, usec_t *last_validated, usec_t *last_contained, + bool show_progress) { + int r; + Object *o; + uint64_t p = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0; + + uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0; + sd_id128_t entry_boot_id; + bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false; + uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0; + usec_t last_usec = 0; + int data_fd = -1, entry_fd = -1, entry_array_fd = -1; + MMapFileDescriptor *cache_data_fd = NULL, *cache_entry_fd = NULL, *cache_entry_array_fd = NULL; + unsigned i; + bool found_last = false; + const char *tmp_dir = NULL; + +#if HAVE_GCRYPT + uint64_t last_tag = 0; +#endif + assert(f); + + if (key) { +#if HAVE_GCRYPT + r = journal_file_parse_verification_key(f, key); + if (r < 0) { + log_error("Failed to parse seed."); + return r; + } +#else + return -EOPNOTSUPP; +#endif + } else if (f->seal) + return -ENOKEY; + + r = var_tmp_dir(&tmp_dir); + if (r < 0) { + log_error_errno(r, "Failed to determine temporary directory: %m"); + goto fail; + } + + data_fd = open_tmpfile_unlinkable(tmp_dir, O_RDWR | O_CLOEXEC); + if (data_fd < 0) { + r = log_error_errno(data_fd, "Failed to create data file: %m"); + goto fail; + } + + entry_fd = open_tmpfile_unlinkable(tmp_dir, O_RDWR | O_CLOEXEC); + if (entry_fd < 0) { + r = log_error_errno(entry_fd, "Failed to create entry file: %m"); + goto fail; + } + + entry_array_fd = open_tmpfile_unlinkable(tmp_dir, O_RDWR | O_CLOEXEC); + if (entry_array_fd < 0) { + r = log_error_errno(entry_array_fd, + "Failed to create entry array file: %m"); + goto fail; + } + + cache_data_fd = mmap_cache_add_fd(f->mmap, data_fd); + if (!cache_data_fd) { + r = log_oom(); + goto fail; + } + + cache_entry_fd = mmap_cache_add_fd(f->mmap, entry_fd); + if (!cache_entry_fd) { + r = log_oom(); + goto fail; + } + + cache_entry_array_fd = mmap_cache_add_fd(f->mmap, entry_array_fd); + if (!cache_entry_array_fd) { + r = log_oom(); + goto fail; + } + + if (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SUPPORTED) { + log_error("Cannot verify file with unknown extensions."); + r = -EOPNOTSUPP; + goto fail; + } + + for (i = 0; i < sizeof(f->header->reserved); i++) + if (f->header->reserved[i] != 0) { + error(offsetof(Header, reserved[i]), "Reserved field is non-zero"); + r = -EBADMSG; + goto fail; + } + + /* First iteration: we go through all objects, verify the + * superficial structure, headers, hashes. */ + + p = le64toh(f->header->header_size); + for (;;) { + /* Early exit if there are no objects in the file, at all */ + if (le64toh(f->header->tail_object_offset) == 0) + break; + + if (show_progress) + draw_progress(scale_progress(0x7FFF, p, le64toh(f->header->tail_object_offset)), &last_usec); + + r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); + if (r < 0) { + error(p, "Invalid object"); + goto fail; + } + + if (p > le64toh(f->header->tail_object_offset)) { + error(offsetof(Header, tail_object_offset), "Invalid tail object pointer"); + r = -EBADMSG; + goto fail; + } + + n_objects++; + + r = journal_file_object_verify(f, p, o); + if (r < 0) { + error_errno(p, r, "Invalid object contents: %m"); + goto fail; + } + + if ((o->object.flags & OBJECT_COMPRESSED_XZ) && + (o->object.flags & OBJECT_COMPRESSED_LZ4)) { + error(p, "Objected with double compression"); + r = -EINVAL; + goto fail; + } + + if ((o->object.flags & OBJECT_COMPRESSED_XZ) && !JOURNAL_HEADER_COMPRESSED_XZ(f->header)) { + error(p, "XZ compressed object in file without XZ compression"); + r = -EBADMSG; + goto fail; + } + + if ((o->object.flags & OBJECT_COMPRESSED_LZ4) && !JOURNAL_HEADER_COMPRESSED_LZ4(f->header)) { + error(p, "LZ4 compressed object in file without LZ4 compression"); + r = -EBADMSG; + goto fail; + } + + switch (o->object.type) { + + case OBJECT_DATA: + r = write_uint64(data_fd, p); + if (r < 0) + goto fail; + + n_data++; + break; + + case OBJECT_FIELD: + n_fields++; + break; + + case OBJECT_ENTRY: + if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) { + error(p, "First entry before first tag"); + r = -EBADMSG; + goto fail; + } + + r = write_uint64(entry_fd, p); + if (r < 0) + goto fail; + + if (le64toh(o->entry.realtime) < last_tag_realtime) { + error(p, "Older entry after newer tag"); + r = -EBADMSG; + goto fail; + } + + if (!entry_seqnum_set && + le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) { + error(p, "Head entry sequence number incorrect"); + r = -EBADMSG; + goto fail; + } + + if (entry_seqnum_set && + entry_seqnum >= le64toh(o->entry.seqnum)) { + error(p, "Entry sequence number out of synchronization"); + r = -EBADMSG; + goto fail; + } + + entry_seqnum = le64toh(o->entry.seqnum); + entry_seqnum_set = true; + + if (entry_monotonic_set && + sd_id128_equal(entry_boot_id, o->entry.boot_id) && + entry_monotonic > le64toh(o->entry.monotonic)) { + error(p, "Entry timestamp out of synchronization"); + r = -EBADMSG; + goto fail; + } + + entry_monotonic = le64toh(o->entry.monotonic); + entry_boot_id = o->entry.boot_id; + entry_monotonic_set = true; + + if (!entry_realtime_set && + le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) { + error(p, "Head entry realtime timestamp incorrect"); + r = -EBADMSG; + goto fail; + } + + entry_realtime = le64toh(o->entry.realtime); + entry_realtime_set = true; + + n_entries++; + break; + + case OBJECT_DATA_HASH_TABLE: + if (n_data_hash_tables > 1) { + error(p, "More than one data hash table"); + r = -EBADMSG; + goto fail; + } + + if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) || + le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { + error(p, "header fields for data hash table invalid"); + r = -EBADMSG; + goto fail; + } + + n_data_hash_tables++; + break; + + case OBJECT_FIELD_HASH_TABLE: + if (n_field_hash_tables > 1) { + error(p, "More than one field hash table"); + r = -EBADMSG; + goto fail; + } + + if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) || + le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { + error(p, "Header fields for field hash table invalid"); + r = -EBADMSG; + goto fail; + } + + n_field_hash_tables++; + break; + + case OBJECT_ENTRY_ARRAY: + r = write_uint64(entry_array_fd, p); + if (r < 0) + goto fail; + + if (p == le64toh(f->header->entry_array_offset)) { + if (found_main_entry_array) { + error(p, "More than one main entry array"); + r = -EBADMSG; + goto fail; + } + + found_main_entry_array = true; + } + + n_entry_arrays++; + break; + + case OBJECT_TAG: + if (!JOURNAL_HEADER_SEALED(f->header)) { + error(p, "Tag object in file without sealing"); + r = -EBADMSG; + goto fail; + } + + if (le64toh(o->tag.seqnum) != n_tags + 1) { + error(p, "Tag sequence number out of synchronization"); + r = -EBADMSG; + goto fail; + } + + if (le64toh(o->tag.epoch) < last_epoch) { + error(p, "Epoch sequence out of synchronization"); + r = -EBADMSG; + goto fail; + } + +#if HAVE_GCRYPT + if (f->seal) { + uint64_t q, rt; + + debug(p, "Checking tag %"PRIu64"...", le64toh(o->tag.seqnum)); + + rt = f->fss_start_usec + le64toh(o->tag.epoch) * f->fss_interval_usec; + if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) { + error(p, "tag/entry realtime timestamp out of synchronization"); + r = -EBADMSG; + goto fail; + } + + /* OK, now we know the epoch. So let's now set + * it, and calculate the HMAC for everything + * since the last tag. */ + r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch)); + if (r < 0) + goto fail; + + r = journal_file_hmac_start(f); + if (r < 0) + goto fail; + + if (last_tag == 0) { + r = journal_file_hmac_put_header(f); + if (r < 0) + goto fail; + + q = le64toh(f->header->header_size); + } else + q = last_tag; + + while (q <= p) { + r = journal_file_move_to_object(f, OBJECT_UNUSED, q, &o); + if (r < 0) + goto fail; + + r = journal_file_hmac_put_object(f, OBJECT_UNUSED, o, q); + if (r < 0) + goto fail; + + q = q + ALIGN64(le64toh(o->object.size)); + } + + /* Position might have changed, let's reposition things */ + r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); + if (r < 0) + goto fail; + + if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) { + error(p, "Tag failed verification"); + r = -EBADMSG; + goto fail; + } + + f->hmac_running = false; + last_tag_realtime = rt; + last_sealed_realtime = entry_realtime; + } + + last_tag = p + ALIGN64(le64toh(o->object.size)); +#endif + + last_epoch = le64toh(o->tag.epoch); + + n_tags++; + break; + + default: + n_weird++; + } + + if (p == le64toh(f->header->tail_object_offset)) { + found_last = true; + break; + } + + p = p + ALIGN64(le64toh(o->object.size)); + }; + + if (!found_last && le64toh(f->header->tail_object_offset) != 0) { + error(le64toh(f->header->tail_object_offset), "Tail object pointer dead"); + r = -EBADMSG; + goto fail; + } + + if (n_objects != le64toh(f->header->n_objects)) { + error(offsetof(Header, n_objects), "Object number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (n_entries != le64toh(f->header->n_entries)) { + error(offsetof(Header, n_entries), "Entry number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_data) && + n_data != le64toh(f->header->n_data)) { + error(offsetof(Header, n_data), "Data number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) && + n_fields != le64toh(f->header->n_fields)) { + error(offsetof(Header, n_fields), "Field number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) && + n_tags != le64toh(f->header->n_tags)) { + error(offsetof(Header, n_tags), "Tag number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) && + n_entry_arrays != le64toh(f->header->n_entry_arrays)) { + error(offsetof(Header, n_entry_arrays), "Entry array number mismatch"); + r = -EBADMSG; + goto fail; + } + + if (!found_main_entry_array && le64toh(f->header->entry_array_offset) != 0) { + error(0, "Missing entry array"); + r = -EBADMSG; + goto fail; + } + + if (entry_seqnum_set && + entry_seqnum != le64toh(f->header->tail_entry_seqnum)) { + error(offsetof(Header, tail_entry_seqnum), "Invalid tail seqnum"); + r = -EBADMSG; + goto fail; + } + + if (entry_monotonic_set && + (sd_id128_equal(entry_boot_id, f->header->boot_id) && + entry_monotonic != le64toh(f->header->tail_entry_monotonic))) { + error(0, "Invalid tail monotonic timestamp"); + r = -EBADMSG; + goto fail; + } + + if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) { + error(0, "Invalid tail realtime timestamp"); + r = -EBADMSG; + goto fail; + } + + /* Second iteration: we follow all objects referenced from the + * two entry points: the object hash table and the entry + * array. We also check that everything referenced (directly + * or indirectly) in the data hash table also exists in the + * entry array, and vice versa. Note that we do not care for + * unreferenced objects. We only care that everything that is + * referenced is consistent. */ + + r = verify_entry_array(f, + cache_data_fd, n_data, + cache_entry_fd, n_entries, + cache_entry_array_fd, n_entry_arrays, + &last_usec, + show_progress); + if (r < 0) + goto fail; + + r = verify_hash_table(f, + cache_data_fd, n_data, + cache_entry_fd, n_entries, + cache_entry_array_fd, n_entry_arrays, + &last_usec, + show_progress); + if (r < 0) + goto fail; + + if (show_progress) + flush_progress(); + + mmap_cache_free_fd(f->mmap, cache_data_fd); + mmap_cache_free_fd(f->mmap, cache_entry_fd); + mmap_cache_free_fd(f->mmap, cache_entry_array_fd); + + safe_close(data_fd); + safe_close(entry_fd); + safe_close(entry_array_fd); + + if (first_contained) + *first_contained = le64toh(f->header->head_entry_realtime); + if (last_validated) + *last_validated = last_sealed_realtime; + if (last_contained) + *last_contained = le64toh(f->header->tail_entry_realtime); + + return 0; + +fail: + if (show_progress) + flush_progress(); + + log_error("File corruption detected at %s:"OFSfmt" (of %llu bytes, %"PRIu64"%%).", + f->path, + p, + (unsigned long long) f->last_stat.st_size, + 100 * p / f->last_stat.st_size); + + if (data_fd >= 0) + safe_close(data_fd); + + if (entry_fd >= 0) + safe_close(entry_fd); + + if (entry_array_fd >= 0) + safe_close(entry_array_fd); + + if (cache_data_fd) + mmap_cache_free_fd(f->mmap, cache_data_fd); + + if (cache_entry_fd) + mmap_cache_free_fd(f->mmap, cache_entry_fd); + + if (cache_entry_array_fd) + mmap_cache_free_fd(f->mmap, cache_entry_array_fd); + + return r; +} diff --git a/src/journal/journal-verify.h b/src/journal/journal-verify.h new file mode 100644 index 00000000..f0ea31ab --- /dev/null +++ b/src/journal/journal-verify.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "journal-file.h" + +int journal_file_verify(JournalFile *f, const char *key, usec_t *first_contained, usec_t *last_validated, usec_t *last_contained, bool show_progress); diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c new file mode 100644 index 00000000..17565abe --- /dev/null +++ b/src/journal/journalctl.c @@ -0,0 +1,2696 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_PCRE2 +# define PCRE2_CODE_UNIT_WIDTH 8 +# include +#endif + +#include "sd-bus.h" +#include "sd-device.h" +#include "sd-journal.h" + +#include "acl-util.h" +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "catalog.h" +#include "chattr-util.h" +#include "def.h" +#include "device-private.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "fsprg.h" +#include "glob-util.h" +#include "hostname-util.h" +#include "id128-print.h" +#include "io-util.h" +#include "journal-def.h" +#include "journal-internal.h" +#include "journal-qrcode.h" +#include "journal-util.h" +#include "journal-vacuum.h" +#include "journal-verify.h" +#include "locale-util.h" +#include "log.h" +#include "logs-show.h" +#include "memory-util.h" +#include "mkdir.h" +#include "mountpoint-util.h" +#include "nulstr-util.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "rlimit-util.h" +#include "set.h" +#include "sigbus.h" +#include "string-table.h" +#include "strv.h" +#include "syslog-util.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "unit-name.h" +#include "user-util.h" +#include "varlink.h" + +#define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE) + +#define PROCESS_INOTIFY_INTERVAL 1024 /* Every 1,024 messages processed */ + +#if HAVE_PCRE2 +DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_match_data*, pcre2_match_data_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(pcre2_code*, pcre2_code_free); + +static int pattern_compile(const char *pattern, unsigned flags, pcre2_code **out) { + int errorcode, r; + PCRE2_SIZE erroroffset; + pcre2_code *p; + + p = pcre2_compile((PCRE2_SPTR8) pattern, + PCRE2_ZERO_TERMINATED, flags, &errorcode, &erroroffset, NULL); + if (!p) { + unsigned char buf[LINE_MAX]; + + r = pcre2_get_error_message(errorcode, buf, sizeof buf); + + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Bad pattern \"%s\": %s", pattern, + r < 0 ? "unknown error" : (char *)buf); + } + + *out = p; + return 0; +} + +#endif + +enum { + /* Special values for arg_lines */ + ARG_LINES_DEFAULT = -2, + ARG_LINES_ALL = -1, +}; + +static OutputMode arg_output = OUTPUT_SHORT; +static bool arg_utc = false; +static bool arg_follow = false; +static bool arg_full = true; +static bool arg_all = false; +static PagerFlags arg_pager_flags = 0; +static int arg_lines = ARG_LINES_DEFAULT; +static bool arg_no_tail = false; +static bool arg_quiet = false; +static bool arg_merge = false; +static bool arg_boot = false; +static sd_id128_t arg_boot_id = {}; +static int arg_boot_offset = 0; +static bool arg_dmesg = false; +static bool arg_no_hostname = false; +static const char *arg_cursor = NULL; +static const char *arg_cursor_file = NULL; +static const char *arg_after_cursor = NULL; +static bool arg_show_cursor = false; +static const char *arg_directory = NULL; +static char **arg_file = NULL; +static bool arg_file_stdin = false; +static int arg_priorities = 0xFF; +static char *arg_verify_key = NULL; +#if HAVE_GCRYPT +static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC; +static bool arg_force = false; +#endif +static usec_t arg_since, arg_until; +static bool arg_since_set = false, arg_until_set = false; +static char **arg_syslog_identifier = NULL; +static char **arg_system_units = NULL; +static char **arg_user_units = NULL; +static const char *arg_field = NULL; +static bool arg_catalog = false; +static bool arg_reverse = false; +static int arg_journal_type = 0; +static char *arg_root = NULL; +static const char *arg_machine = NULL; +static uint64_t arg_vacuum_size = 0; +static uint64_t arg_vacuum_n_files = 0; +static usec_t arg_vacuum_time = 0; +static char **arg_output_fields = NULL; + +#if HAVE_PCRE2 +static const char *arg_pattern = NULL; +static pcre2_code *arg_compiled_pattern = NULL; +static int arg_case_sensitive = -1; /* -1 means be smart */ +#endif + +static enum { + ACTION_SHOW, + ACTION_NEW_ID128, + ACTION_PRINT_HEADER, + ACTION_SETUP_KEYS, + ACTION_VERIFY, + ACTION_DISK_USAGE, + ACTION_LIST_CATALOG, + ACTION_DUMP_CATALOG, + ACTION_UPDATE_CATALOG, + ACTION_LIST_BOOTS, + ACTION_FLUSH, + ACTION_RELINQUISH_VAR, + ACTION_SYNC, + ACTION_ROTATE, + ACTION_VACUUM, + ACTION_ROTATE_AND_VACUUM, + ACTION_LIST_FIELDS, + ACTION_LIST_FIELD_NAMES, +} arg_action = ACTION_SHOW; + +typedef struct BootId { + sd_id128_t id; + uint64_t first; + uint64_t last; + LIST_FIELDS(struct BootId, boot_list); +} BootId; + +static int add_matches_for_device(sd_journal *j, const char *devpath) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + sd_device *d = NULL; + struct stat st; + int r; + + assert(j); + assert(devpath); + + if (!path_startswith(devpath, "/dev/")) { + log_error("Devpath does not start with /dev/"); + return -EINVAL; + } + + if (stat(devpath, &st) < 0) + return log_error_errno(errno, "Couldn't stat file: %m"); + + r = device_new_from_stat_rdev(&device, &st); + if (r < 0) + return log_error_errno(r, "Failed to get device from devnum %u:%u: %m", major(st.st_rdev), minor(st.st_rdev)); + + for (d = device; d; ) { + _cleanup_free_ char *match = NULL; + const char *subsys, *sysname, *devnode; + sd_device *parent; + + r = sd_device_get_subsystem(d, &subsys); + if (r < 0) + goto get_parent; + + r = sd_device_get_sysname(d, &sysname); + if (r < 0) + goto get_parent; + + match = strjoin("_KERNEL_DEVICE=+", subsys, ":", sysname); + if (!match) + return log_oom(); + + r = sd_journal_add_match(j, match, 0); + if (r < 0) + return log_error_errno(r, "Failed to add match: %m"); + + if (sd_device_get_devname(d, &devnode) >= 0) { + _cleanup_free_ char *match1 = NULL; + + r = stat(devnode, &st); + if (r < 0) + return log_error_errno(r, "Failed to stat() device node \"%s\": %m", devnode); + + r = asprintf(&match1, "_KERNEL_DEVICE=%c%u:%u", S_ISBLK(st.st_mode) ? 'b' : 'c', major(st.st_rdev), minor(st.st_rdev)); + if (r < 0) + return log_oom(); + + r = sd_journal_add_match(j, match1, 0); + if (r < 0) + return log_error_errno(r, "Failed to add match: %m"); + } + +get_parent: + if (sd_device_get_parent(d, &parent) < 0) + break; + + d = parent; + } + + r = add_match_this_boot(j, arg_machine); + if (r < 0) + return log_error_errno(r, "Failed to add match for the current boot: %m"); + + return 0; +} + +static char *format_timestamp_maybe_utc(char *buf, size_t l, usec_t t) { + + if (arg_utc) + return format_timestamp_utc(buf, l, t); + + return format_timestamp(buf, l, t); +} + +static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset) { + sd_id128_t id = SD_ID128_NULL; + int off = 0, r; + + if (streq(x, "all")) { + *boot_id = SD_ID128_NULL; + *offset = 0; + return 0; + } else if (strlen(x) >= 32) { + char *t; + + t = strndupa(x, 32); + r = sd_id128_from_string(t, &id); + if (r >= 0) + x += 32; + + if (!IN_SET(*x, 0, '-', '+')) + return -EINVAL; + + if (*x != 0) { + r = safe_atoi(x, &off); + if (r < 0) + return r; + } + } else { + r = safe_atoi(x, &off); + if (r < 0) + return r; + } + + if (boot_id) + *boot_id = id; + + if (offset) + *offset = off; + + return 1; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + (void) pager_open(arg_pager_flags); + + r = terminal_urlify_man("journalctl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [MATCHES...]\n\n" + "%sQuery the journal.%s\n\n" + "Options:\n" + " --system Show the system journal\n" + " --user Show the user journal for the current user\n" + " -M --machine=CONTAINER Operate on local container\n" + " -S --since=DATE Show entries not older than the specified date\n" + " -U --until=DATE Show entries not newer than the specified date\n" + " -c --cursor=CURSOR Show entries starting at the specified cursor\n" + " --after-cursor=CURSOR Show entries after the specified cursor\n" + " --show-cursor Print the cursor after all the entries\n" + " --cursor-file=FILE Show entries after cursor in FILE and update FILE\n" + " -b --boot[=ID] Show current boot or the specified boot\n" + " --list-boots Show terse information about recorded boots\n" + " -k --dmesg Show kernel message log from the current boot\n" + " -u --unit=UNIT Show logs from the specified unit\n" + " --user-unit=UNIT Show logs from the specified user unit\n" + " -t --identifier=STRING Show entries with the specified syslog identifier\n" + " -p --priority=RANGE Show entries with the specified priority\n" + " -g --grep=PATTERN Show entries with MESSAGE matching PATTERN\n" + " --case-sensitive[=BOOL] Force case sensitive or insenstive matching\n" + " -e --pager-end Immediately jump to the end in the pager\n" + " -f --follow Follow the journal\n" + " -n --lines[=INTEGER] Number of journal entries to show\n" + " --no-tail Show all lines, even in follow mode\n" + " -r --reverse Show the newest entries first\n" + " -o --output=STRING Change journal output mode (short, short-precise,\n" + " short-iso, short-iso-precise, short-full,\n" + " short-monotonic, short-unix, verbose, export,\n" + " json, json-pretty, json-sse, json-seq, cat,\n" + " with-unit)\n" + " --output-fields=LIST Select fields to print in verbose/export/json modes\n" + " --utc Express time in Coordinated Universal Time (UTC)\n" + " -x --catalog Add message explanations where available\n" + " --no-full Ellipsize fields\n" + " -a --all Show all fields, including long and unprintable\n" + " -q --quiet Do not show info messages and privilege warning\n" + " --no-pager Do not pipe output into a pager\n" + " --no-hostname Suppress output of hostname field\n" + " -m --merge Show entries from all available journals\n" + " -D --directory=PATH Show journal files from directory\n" + " --file=PATH Show journal file\n" + " --root=ROOT Operate on files below a root directory\n" + " --interval=TIME Time interval for changing the FSS sealing key\n" + " --verify-key=KEY Specify FSS verification key\n" + " --force Override of the FSS key pair with --setup-keys\n" + "\nCommands:\n" + " -h --help Show this help text\n" + " --version Show package version\n" + " -N --fields List all field names currently used\n" + " -F --field=FIELD List all values that a specified field takes\n" + " --disk-usage Show total disk usage of all journal files\n" + " --vacuum-size=BYTES Reduce disk usage below specified size\n" + " --vacuum-files=INT Leave only the specified number of journal files\n" + " --vacuum-time=TIME Remove journal files older than specified time\n" + " --verify Verify journal file consistency\n" + " --sync Synchronize unwritten journal messages to disk\n" + " --relinquish-var Stop logging to disk, log to temporary file system\n" + " --smart-relinquish-var Similar, but NOP if log directory is on root mount\n" + " --flush Flush all journal data from /run into /var\n" + " --rotate Request immediate rotation of the journal files\n" + " --header Show journal header information\n" + " --list-catalog Show all message IDs in the catalog\n" + " --dump-catalog Show entries in the message catalog\n" + " --update-catalog Update the message catalog database\n" + " --setup-keys Generate a new FSS key pair\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_PAGER, + ARG_NO_FULL, + ARG_NO_TAIL, + ARG_NEW_ID128, + ARG_THIS_BOOT, + ARG_LIST_BOOTS, + ARG_USER, + ARG_SYSTEM, + ARG_ROOT, + ARG_HEADER, + ARG_SETUP_KEYS, + ARG_FILE, + ARG_INTERVAL, + ARG_VERIFY, + ARG_VERIFY_KEY, + ARG_DISK_USAGE, + ARG_AFTER_CURSOR, + ARG_CURSOR_FILE, + ARG_SHOW_CURSOR, + ARG_USER_UNIT, + ARG_LIST_CATALOG, + ARG_DUMP_CATALOG, + ARG_UPDATE_CATALOG, + ARG_FORCE, + ARG_CASE_SENSITIVE, + ARG_UTC, + ARG_SYNC, + ARG_FLUSH, + ARG_RELINQUISH_VAR, + ARG_SMART_RELINQUISH_VAR, + ARG_ROTATE, + ARG_VACUUM_SIZE, + ARG_VACUUM_FILES, + ARG_VACUUM_TIME, + ARG_NO_HOSTNAME, + ARG_OUTPUT_FIELDS, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version" , no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "pager-end", no_argument, NULL, 'e' }, + { "follow", no_argument, NULL, 'f' }, + { "force", no_argument, NULL, ARG_FORCE }, + { "output", required_argument, NULL, 'o' }, + { "all", no_argument, NULL, 'a' }, + { "full", no_argument, NULL, 'l' }, + { "no-full", no_argument, NULL, ARG_NO_FULL }, + { "lines", optional_argument, NULL, 'n' }, + { "no-tail", no_argument, NULL, ARG_NO_TAIL }, + { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, /* deprecated */ + { "quiet", no_argument, NULL, 'q' }, + { "merge", no_argument, NULL, 'm' }, + { "this-boot", no_argument, NULL, ARG_THIS_BOOT }, /* deprecated */ + { "boot", optional_argument, NULL, 'b' }, + { "list-boots", no_argument, NULL, ARG_LIST_BOOTS }, + { "dmesg", no_argument, NULL, 'k' }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "user", no_argument, NULL, ARG_USER }, + { "directory", required_argument, NULL, 'D' }, + { "file", required_argument, NULL, ARG_FILE }, + { "root", required_argument, NULL, ARG_ROOT }, + { "header", no_argument, NULL, ARG_HEADER }, + { "identifier", required_argument, NULL, 't' }, + { "priority", required_argument, NULL, 'p' }, + { "grep", required_argument, NULL, 'g' }, + { "case-sensitive", optional_argument, NULL, ARG_CASE_SENSITIVE }, + { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS }, + { "interval", required_argument, NULL, ARG_INTERVAL }, + { "verify", no_argument, NULL, ARG_VERIFY }, + { "verify-key", required_argument, NULL, ARG_VERIFY_KEY }, + { "disk-usage", no_argument, NULL, ARG_DISK_USAGE }, + { "cursor", required_argument, NULL, 'c' }, + { "cursor-file", required_argument, NULL, ARG_CURSOR_FILE }, + { "after-cursor", required_argument, NULL, ARG_AFTER_CURSOR }, + { "show-cursor", no_argument, NULL, ARG_SHOW_CURSOR }, + { "since", required_argument, NULL, 'S' }, + { "until", required_argument, NULL, 'U' }, + { "unit", required_argument, NULL, 'u' }, + { "user-unit", required_argument, NULL, ARG_USER_UNIT }, + { "field", required_argument, NULL, 'F' }, + { "fields", no_argument, NULL, 'N' }, + { "catalog", no_argument, NULL, 'x' }, + { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG }, + { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG }, + { "update-catalog", no_argument, NULL, ARG_UPDATE_CATALOG }, + { "reverse", no_argument, NULL, 'r' }, + { "machine", required_argument, NULL, 'M' }, + { "utc", no_argument, NULL, ARG_UTC }, + { "flush", no_argument, NULL, ARG_FLUSH }, + { "relinquish-var", no_argument, NULL, ARG_RELINQUISH_VAR }, + { "smart-relinquish-var", no_argument, NULL, ARG_SMART_RELINQUISH_VAR }, + { "sync", no_argument, NULL, ARG_SYNC }, + { "rotate", no_argument, NULL, ARG_ROTATE }, + { "vacuum-size", required_argument, NULL, ARG_VACUUM_SIZE }, + { "vacuum-files", required_argument, NULL, ARG_VACUUM_FILES }, + { "vacuum-time", required_argument, NULL, ARG_VACUUM_TIME }, + { "no-hostname", no_argument, NULL, ARG_NO_HOSTNAME }, + { "output-fields", required_argument, NULL, ARG_OUTPUT_FIELDS }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:g:c:S:U:t:u:NF:xrM:", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case 'e': + arg_pager_flags |= PAGER_JUMP_TO_END; + + if (arg_lines == ARG_LINES_DEFAULT) + arg_lines = 1000; + + break; + + case 'f': + arg_follow = true; + break; + + case 'o': + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX); + return 0; + } + + arg_output = output_mode_from_string(optarg); + if (arg_output < 0) { + log_error("Unknown output format '%s'.", optarg); + return -EINVAL; + } + + if (IN_SET(arg_output, OUTPUT_EXPORT, OUTPUT_JSON, OUTPUT_JSON_PRETTY, OUTPUT_JSON_SSE, OUTPUT_JSON_SEQ, OUTPUT_CAT)) + arg_quiet = true; + + break; + + case 'l': + arg_full = true; + break; + + case ARG_NO_FULL: + arg_full = false; + break; + + case 'a': + arg_all = true; + break; + + case 'n': + if (optarg) { + if (streq(optarg, "all")) + arg_lines = ARG_LINES_ALL; + else { + r = safe_atoi(optarg, &arg_lines); + if (r < 0 || arg_lines < 0) { + log_error("Failed to parse lines '%s'", optarg); + return -EINVAL; + } + } + } else { + arg_lines = 10; + + /* Hmm, no argument? Maybe the next + * word on the command line is + * supposed to be the argument? Let's + * see if there is one, and is + * parsable. */ + if (optind < argc) { + int n; + if (streq(argv[optind], "all")) { + arg_lines = ARG_LINES_ALL; + optind++; + } else if (safe_atoi(argv[optind], &n) >= 0 && n >= 0) { + arg_lines = n; + optind++; + } + } + } + + break; + + case ARG_NO_TAIL: + arg_no_tail = true; + break; + + case ARG_NEW_ID128: + arg_action = ACTION_NEW_ID128; + break; + + case 'q': + arg_quiet = true; + break; + + case 'm': + arg_merge = true; + break; + + case ARG_THIS_BOOT: + arg_boot = true; + arg_boot_id = SD_ID128_NULL; + arg_boot_offset = 0; + break; + + case 'b': + arg_boot = true; + arg_boot_id = SD_ID128_NULL; + arg_boot_offset = 0; + + if (optarg) { + r = parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset); + if (r < 0) + return log_error_errno(r, "Failed to parse boot descriptor '%s'", optarg); + + arg_boot = r; + + /* Hmm, no argument? Maybe the next + * word on the command line is + * supposed to be the argument? Let's + * see if there is one and is parsable + * as a boot descriptor... */ + } else if (optind < argc) { + r = parse_boot_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset); + if (r >= 0) { + arg_boot = r; + optind++; + } + } + break; + + case ARG_LIST_BOOTS: + arg_action = ACTION_LIST_BOOTS; + break; + + case 'k': + arg_boot = arg_dmesg = true; + break; + + case ARG_SYSTEM: + arg_journal_type |= SD_JOURNAL_SYSTEM; + break; + + case ARG_USER: + arg_journal_type |= SD_JOURNAL_CURRENT_USER; + break; + + case 'M': + arg_machine = optarg; + break; + + case 'D': + arg_directory = optarg; + break; + + case ARG_FILE: + if (streq(optarg, "-")) + /* An undocumented feature: we can read journal files from STDIN. We don't document + * this though, since after all we only support this for mmap-able, seekable files, and + * not for example pipes which are probably the primary usecase for reading things from + * STDIN. To avoid confusion we hence don't document this feature. */ + arg_file_stdin = true; + else { + r = glob_extend(&arg_file, optarg); + if (r < 0) + return log_error_errno(r, "Failed to add paths: %m"); + } + break; + + case ARG_ROOT: + r = parse_path_argument_and_warn(optarg, true, &arg_root); + if (r < 0) + return r; + break; + + case 'c': + arg_cursor = optarg; + break; + + case ARG_CURSOR_FILE: + arg_cursor_file = optarg; + break; + + case ARG_AFTER_CURSOR: + arg_after_cursor = optarg; + break; + + case ARG_SHOW_CURSOR: + arg_show_cursor = true; + break; + + case ARG_HEADER: + arg_action = ACTION_PRINT_HEADER; + break; + + case ARG_VERIFY: + arg_action = ACTION_VERIFY; + break; + + case ARG_DISK_USAGE: + arg_action = ACTION_DISK_USAGE; + break; + + case ARG_VACUUM_SIZE: + r = parse_size(optarg, 1024, &arg_vacuum_size); + if (r < 0) { + log_error("Failed to parse vacuum size: %s", optarg); + return r; + } + + arg_action = arg_action == ACTION_ROTATE ? ACTION_ROTATE_AND_VACUUM : ACTION_VACUUM; + break; + + case ARG_VACUUM_FILES: + r = safe_atou64(optarg, &arg_vacuum_n_files); + if (r < 0) { + log_error("Failed to parse vacuum files: %s", optarg); + return r; + } + + arg_action = arg_action == ACTION_ROTATE ? ACTION_ROTATE_AND_VACUUM : ACTION_VACUUM; + break; + + case ARG_VACUUM_TIME: + r = parse_sec(optarg, &arg_vacuum_time); + if (r < 0) { + log_error("Failed to parse vacuum time: %s", optarg); + return r; + } + + arg_action = arg_action == ACTION_ROTATE ? ACTION_ROTATE_AND_VACUUM : ACTION_VACUUM; + break; + +#if HAVE_GCRYPT + case ARG_FORCE: + arg_force = true; + break; + + case ARG_SETUP_KEYS: + arg_action = ACTION_SETUP_KEYS; + break; + + case ARG_VERIFY_KEY: + arg_action = ACTION_VERIFY; + r = free_and_strdup(&arg_verify_key, optarg); + if (r < 0) + return r; + /* Use memset not explicit_bzero() or similar so this doesn't look confusing + * in ps or htop output. */ + memset(optarg, 'x', strlen(optarg)); + + arg_merge = false; + break; + + case ARG_INTERVAL: + r = parse_sec(optarg, &arg_interval); + if (r < 0 || arg_interval <= 0) { + log_error("Failed to parse sealing key change interval: %s", optarg); + return -EINVAL; + } + break; +#else + case ARG_SETUP_KEYS: + case ARG_VERIFY_KEY: + case ARG_INTERVAL: + case ARG_FORCE: + log_error("Compiled without forward-secure sealing support."); + return -EOPNOTSUPP; +#endif + + case 'p': { + const char *dots; + + dots = strstr(optarg, ".."); + if (dots) { + char *a; + int from, to, i; + + /* a range */ + a = strndup(optarg, dots - optarg); + if (!a) + return log_oom(); + + from = log_level_from_string(a); + to = log_level_from_string(dots + 2); + free(a); + + if (from < 0 || to < 0) { + log_error("Failed to parse log level range %s", optarg); + return -EINVAL; + } + + arg_priorities = 0; + + if (from < to) { + for (i = from; i <= to; i++) + arg_priorities |= 1 << i; + } else { + for (i = to; i <= from; i++) + arg_priorities |= 1 << i; + } + + } else { + int p, i; + + p = log_level_from_string(optarg); + if (p < 0) { + log_error("Unknown log level %s", optarg); + return -EINVAL; + } + + arg_priorities = 0; + + for (i = 0; i <= p; i++) + arg_priorities |= 1 << i; + } + + break; + } + +#if HAVE_PCRE2 + case 'g': + arg_pattern = optarg; + break; + + case ARG_CASE_SENSITIVE: + if (optarg) { + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Bad --case-sensitive= argument \"%s\": %m", optarg); + arg_case_sensitive = r; + } else + arg_case_sensitive = true; + + break; +#else + case 'g': + case ARG_CASE_SENSITIVE: + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Compiled without pattern matching support"); +#endif + + case 'S': + r = parse_timestamp(optarg, &arg_since); + if (r < 0) { + log_error("Failed to parse timestamp: %s", optarg); + return -EINVAL; + } + arg_since_set = true; + break; + + case 'U': + r = parse_timestamp(optarg, &arg_until); + if (r < 0) { + log_error("Failed to parse timestamp: %s", optarg); + return -EINVAL; + } + arg_until_set = true; + break; + + case 't': + r = strv_extend(&arg_syslog_identifier, optarg); + if (r < 0) + return log_oom(); + break; + + case 'u': + r = strv_extend(&arg_system_units, optarg); + if (r < 0) + return log_oom(); + break; + + case ARG_USER_UNIT: + r = strv_extend(&arg_user_units, optarg); + if (r < 0) + return log_oom(); + break; + + case 'F': + arg_action = ACTION_LIST_FIELDS; + arg_field = optarg; + break; + + case 'N': + arg_action = ACTION_LIST_FIELD_NAMES; + break; + + case ARG_NO_HOSTNAME: + arg_no_hostname = true; + break; + + case 'x': + arg_catalog = true; + break; + + case ARG_LIST_CATALOG: + arg_action = ACTION_LIST_CATALOG; + break; + + case ARG_DUMP_CATALOG: + arg_action = ACTION_DUMP_CATALOG; + break; + + case ARG_UPDATE_CATALOG: + arg_action = ACTION_UPDATE_CATALOG; + break; + + case 'r': + arg_reverse = true; + break; + + case ARG_UTC: + arg_utc = true; + break; + + case ARG_FLUSH: + arg_action = ACTION_FLUSH; + break; + + case ARG_SMART_RELINQUISH_VAR: { + int root_mnt_id, log_mnt_id; + + /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown: + * if it's on the same mount as the root file system there's no point in + * relinquishing access and we can leave journald write to it until the very last + * moment. */ + + r = path_get_mnt_id("/", &root_mnt_id); + if (r < 0) + log_debug_errno(r, "Failed to get root mount ID, ignoring: %m"); + else { + r = path_get_mnt_id("/var/log/journal/", &log_mnt_id); + if (r < 0) + log_debug_errno(r, "Failed to get journal directory mount ID, ignoring: %m"); + else if (root_mnt_id == log_mnt_id) { + log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var."); + return 0; + } else + log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it."); + } + + _fallthrough_; + } + + case ARG_RELINQUISH_VAR: + arg_action = ACTION_RELINQUISH_VAR; + break; + + case ARG_ROTATE: + arg_action = arg_action == ACTION_VACUUM ? ACTION_ROTATE_AND_VACUUM : ACTION_ROTATE; + break; + + case ARG_SYNC: + arg_action = ACTION_SYNC; + break; + + case ARG_OUTPUT_FIELDS: { + _cleanup_strv_free_ char **v = NULL; + + v = strv_split(optarg, ","); + if (!v) + return log_oom(); + + if (!arg_output_fields) + arg_output_fields = TAKE_PTR(v); + else { + r = strv_extend_strv(&arg_output_fields, v, true); + if (r < 0) + return log_oom(); + } + break; + } + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_follow && !arg_no_tail && !arg_since && arg_lines == ARG_LINES_DEFAULT) + arg_lines = 10; + + if (!!arg_directory + !!arg_file + !!arg_machine + !!arg_root > 1) { + log_error("Please specify at most one of -D/--directory=, --file=, -M/--machine=, --root."); + return -EINVAL; + } + + if (arg_since_set && arg_until_set && arg_since > arg_until) { + log_error("--since= must be before --until=."); + return -EINVAL; + } + + if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) { + log_error("Please specify only one of --since=, --cursor=, and --after-cursor."); + return -EINVAL; + } + + if (arg_follow && arg_reverse) { + log_error("Please specify either --reverse= or --follow=, not both."); + return -EINVAL; + } + + if (!IN_SET(arg_action, ACTION_SHOW, ACTION_DUMP_CATALOG, ACTION_LIST_CATALOG) && optind < argc) { + log_error("Extraneous arguments starting with '%s'", argv[optind]); + return -EINVAL; + } + + if ((arg_boot || arg_action == ACTION_LIST_BOOTS) && arg_merge) { + log_error("Using --boot or --list-boots with --merge is not supported."); + return -EINVAL; + } + + if (!strv_isempty(arg_system_units) && arg_journal_type == SD_JOURNAL_CURRENT_USER) { + /* Specifying --user and --unit= at the same time makes no sense (as the former excludes the user + * journal, but the latter excludes the system journal, thus resulting in empty output). Let's be nice + * to users, and automatically turn --unit= into --user-unit= if combined with --user. */ + r = strv_extend_strv(&arg_user_units, arg_system_units, true); + if (r < 0) + return r; + + arg_system_units = strv_free(arg_system_units); + } + +#if HAVE_PCRE2 + if (arg_pattern) { + unsigned flags; + + if (arg_case_sensitive >= 0) + flags = !arg_case_sensitive * PCRE2_CASELESS; + else { + _cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL; + bool has_case; + _cleanup_(pcre2_code_freep) pcre2_code *cs = NULL; + + md = pcre2_match_data_create(1, NULL); + if (!md) + return log_oom(); + + r = pattern_compile("[[:upper:]]", 0, &cs); + if (r < 0) + return r; + + r = pcre2_match(cs, (PCRE2_SPTR8) arg_pattern, PCRE2_ZERO_TERMINATED, 0, 0, md, NULL); + has_case = r >= 0; + + flags = !has_case * PCRE2_CASELESS; + } + + log_debug("Doing case %s matching based on %s", + flags & PCRE2_CASELESS ? "insensitive" : "sensitive", + arg_case_sensitive >= 0 ? "request" : "pattern casing"); + + r = pattern_compile(arg_pattern, flags, &arg_compiled_pattern); + if (r < 0) + return r; + } +#endif + + return 1; +} + +static int add_matches(sd_journal *j, char **args) { + char **i; + bool have_term = false; + + assert(j); + + STRV_FOREACH(i, args) { + int r; + + if (streq(*i, "+")) { + if (!have_term) + break; + r = sd_journal_add_disjunction(j); + have_term = false; + + } else if (path_is_absolute(*i)) { + _cleanup_free_ char *p = NULL, *t = NULL, *t2 = NULL, *interpreter = NULL; + struct stat st; + + r = chase_symlinks(*i, NULL, CHASE_TRAIL_SLASH, &p, NULL); + if (r < 0) + return log_error_errno(r, "Couldn't canonicalize path: %m"); + + if (lstat(p, &st) < 0) + return log_error_errno(errno, "Couldn't stat file: %m"); + + if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) { + if (executable_is_script(p, &interpreter) > 0) { + _cleanup_free_ char *comm; + + comm = strndup(basename(p), 15); + if (!comm) + return log_oom(); + + t = strjoin("_COMM=", comm); + if (!t) + return log_oom(); + + /* Append _EXE only if the interpreter is not a link. + Otherwise, it might be outdated often. */ + if (lstat(interpreter, &st) == 0 && !S_ISLNK(st.st_mode)) { + t2 = strjoin("_EXE=", interpreter); + if (!t2) + return log_oom(); + } + } else { + t = strjoin("_EXE=", p); + if (!t) + return log_oom(); + } + + r = sd_journal_add_match(j, t, 0); + + if (r >=0 && t2) + r = sd_journal_add_match(j, t2, 0); + + } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { + r = add_matches_for_device(j, p); + if (r < 0) + return r; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "File is neither a device node, nor regular file, nor executable: %s", + *i); + + have_term = true; + } else { + r = sd_journal_add_match(j, *i, 0); + have_term = true; + } + + if (r < 0) + return log_error_errno(r, "Failed to add match '%s': %m", *i); + } + + if (!strv_isempty(args) && !have_term) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "\"+\" can only be used between terms"); + + return 0; +} + +static void boot_id_free_all(BootId *l) { + + while (l) { + BootId *i = l; + LIST_REMOVE(boot_list, l, i); + free(i); + } +} + +static int discover_next_boot(sd_journal *j, + sd_id128_t previous_boot_id, + bool advance_older, + BootId **ret) { + + _cleanup_free_ BootId *next_boot = NULL; + char match[9+32+1] = "_BOOT_ID="; + sd_id128_t boot_id; + int r; + + assert(j); + assert(ret); + + /* We expect the journal to be on the last position of a boot + * (in relation to the direction we are going), so that the next + * invocation of sd_journal_next/previous will be from a different + * boot. We then collect any information we desire and then jump + * to the last location of the new boot by using a _BOOT_ID match + * coming from the other journal direction. */ + + /* Make sure we aren't restricted by any _BOOT_ID matches, so that + * we can actually advance to a *different* boot. */ + sd_journal_flush_matches(j); + + do { + if (advance_older) + r = sd_journal_previous(j); + else + r = sd_journal_next(j); + if (r < 0) + return r; + else if (r == 0) + return 0; /* End of journal, yay. */ + + r = sd_journal_get_monotonic_usec(j, NULL, &boot_id); + if (r < 0) + return r; + + /* We iterate through this in a loop, until the boot ID differs from the previous one. Note that + * normally, this will only require a single iteration, as we seeked to the last entry of the previous + * boot entry already. However, it might happen that the per-journal-field entry arrays are less + * complete than the main entry array, and hence might reference an entry that's not actually the last + * one of the boot ID as last one. Let's hence use the per-field array is initial seek position to + * speed things up, but let's not trust that it is complete, and hence, manually advance as + * necessary. */ + + } while (sd_id128_equal(boot_id, previous_boot_id)); + + next_boot = new0(BootId, 1); + if (!next_boot) + return -ENOMEM; + + next_boot->id = boot_id; + + r = sd_journal_get_realtime_usec(j, &next_boot->first); + if (r < 0) + return r; + + /* Now seek to the last occurrence of this boot ID. */ + sd_id128_to_string(next_boot->id, match + 9); + r = sd_journal_add_match(j, match, sizeof(match) - 1); + if (r < 0) + return r; + + if (advance_older) + r = sd_journal_seek_head(j); + else + r = sd_journal_seek_tail(j); + if (r < 0) + return r; + + if (advance_older) + r = sd_journal_next(j); + else + r = sd_journal_previous(j); + if (r < 0) + return r; + else if (r == 0) + return log_debug_errno(SYNTHETIC_ERRNO(ENODATA), + "Whoopsie! We found a boot ID but can't read its last entry."); /* This shouldn't happen. We just came from this very boot ID. */ + + r = sd_journal_get_realtime_usec(j, &next_boot->last); + if (r < 0) + return r; + + *ret = TAKE_PTR(next_boot); + + return 0; +} + +static int get_boots( + sd_journal *j, + BootId **boots, + sd_id128_t *boot_id, + int offset) { + + bool skip_once; + int r, count = 0; + BootId *head = NULL, *tail = NULL, *id; + const bool advance_older = boot_id && offset <= 0; + sd_id128_t previous_boot_id; + + assert(j); + + /* Adjust for the asymmetry that offset 0 is + * the last (and current) boot, while 1 is considered the + * (chronological) first boot in the journal. */ + skip_once = boot_id && sd_id128_is_null(*boot_id) && offset <= 0; + + /* Advance to the earliest/latest occurrence of our reference + * boot ID (taking our lookup direction into account), so that + * discover_next_boot() can do its job. + * If no reference is given, the journal head/tail will do, + * they're "virtual" boots after all. */ + if (boot_id && !sd_id128_is_null(*boot_id)) { + char match[9+32+1] = "_BOOT_ID="; + + sd_journal_flush_matches(j); + + sd_id128_to_string(*boot_id, match + 9); + r = sd_journal_add_match(j, match, sizeof(match) - 1); + if (r < 0) + return r; + + if (advance_older) + r = sd_journal_seek_head(j); /* seek to oldest */ + else + r = sd_journal_seek_tail(j); /* seek to newest */ + if (r < 0) + return r; + + if (advance_older) + r = sd_journal_next(j); /* read the oldest entry */ + else + r = sd_journal_previous(j); /* read the most recently added entry */ + if (r < 0) + return r; + else if (r == 0) + goto finish; + else if (offset == 0) { + count = 1; + goto finish; + } + + /* At this point the read pointer is positioned at the oldest/newest occurrence of the reference boot + * ID. After flushing the matches, one more invocation of _previous()/_next() will hence place us at + * the following entry, which must then have an older/newer boot ID */ + } else { + + if (advance_older) + r = sd_journal_seek_tail(j); /* seek to newest */ + else + r = sd_journal_seek_head(j); /* seek to oldest */ + if (r < 0) + return r; + + /* No sd_journal_next()/_previous() here. + * + * At this point the read pointer is positioned after the newest/before the oldest entry in the whole + * journal. The next invocation of _previous()/_next() will hence position us at the newest/oldest + * entry we have. */ + } + + previous_boot_id = SD_ID128_NULL; + for (;;) { + _cleanup_free_ BootId *current = NULL; + + r = discover_next_boot(j, previous_boot_id, advance_older, ¤t); + if (r < 0) { + boot_id_free_all(head); + return r; + } + + if (!current) + break; + + previous_boot_id = current->id; + + if (boot_id) { + if (!skip_once) + offset += advance_older ? 1 : -1; + skip_once = false; + + if (offset == 0) { + count = 1; + *boot_id = current->id; + break; + } + } else { + LIST_FOREACH(boot_list, id, head) { + if (sd_id128_equal(id->id, current->id)) { + /* boot id already stored, something wrong with the journal files */ + /* exiting as otherwise this problem would cause forever loop */ + goto finish; + } + } + LIST_INSERT_AFTER(boot_list, head, tail, current); + tail = TAKE_PTR(current); + count++; + } + } + +finish: + if (boots) + *boots = head; + + sd_journal_flush_matches(j); + + return count; +} + +static int list_boots(sd_journal *j) { + int w, i, count; + BootId *id, *all_ids; + + assert(j); + + count = get_boots(j, &all_ids, NULL, 0); + if (count < 0) + return log_error_errno(count, "Failed to determine boots: %m"); + if (count == 0) + return count; + + (void) pager_open(arg_pager_flags); + + /* numbers are one less, but we need an extra char for the sign */ + w = DECIMAL_STR_WIDTH(count - 1) + 1; + + i = 0; + LIST_FOREACH(boot_list, id, all_ids) { + char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX]; + + printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n", + w, i - count + 1, + SD_ID128_FORMAT_VAL(id->id), + format_timestamp_maybe_utc(a, sizeof(a), id->first), + format_timestamp_maybe_utc(b, sizeof(b), id->last)); + i++; + } + + boot_id_free_all(all_ids); + + return 0; +} + +static int add_boot(sd_journal *j) { + char match[9+32+1] = "_BOOT_ID="; + sd_id128_t boot_id; + int r; + + assert(j); + + if (!arg_boot) + return 0; + + /* Take a shortcut and use the current boot_id, which we can do very quickly. + * We can do this only when we logs are coming from the current machine, + * so take the slow path if log location is specified. */ + if (arg_boot_offset == 0 && sd_id128_is_null(arg_boot_id) && + !arg_directory && !arg_file && !arg_root) + + return add_match_this_boot(j, arg_machine); + + boot_id = arg_boot_id; + r = get_boots(j, NULL, &boot_id, arg_boot_offset); + assert(r <= 1); + if (r <= 0) { + const char *reason = (r == 0) ? "No such boot ID in journal" : strerror_safe(r); + + if (sd_id128_is_null(arg_boot_id)) + log_error("Data from the specified boot (%+i) is not available: %s", + arg_boot_offset, reason); + else + log_error("Data from the specified boot ("SD_ID128_FORMAT_STR") is not available: %s", + SD_ID128_FORMAT_VAL(arg_boot_id), reason); + + return r == 0 ? -ENODATA : r; + } + + sd_id128_to_string(boot_id, match + 9); + + r = sd_journal_add_match(j, match, sizeof(match) - 1); + if (r < 0) + return log_error_errno(r, "Failed to add match: %m"); + + r = sd_journal_add_conjunction(j); + if (r < 0) + return log_error_errno(r, "Failed to add conjunction: %m"); + + return 0; +} + +static int add_dmesg(sd_journal *j) { + int r; + assert(j); + + if (!arg_dmesg) + return 0; + + r = sd_journal_add_match(j, "_TRANSPORT=kernel", + STRLEN("_TRANSPORT=kernel")); + if (r < 0) + return log_error_errno(r, "Failed to add match: %m"); + + r = sd_journal_add_conjunction(j); + if (r < 0) + return log_error_errno(r, "Failed to add conjunction: %m"); + + return 0; +} + +static int get_possible_units( + sd_journal *j, + const char *fields, + char **patterns, + Set **units) { + + _cleanup_set_free_free_ Set *found; + const char *field; + int r; + + found = set_new(&string_hash_ops); + if (!found) + return -ENOMEM; + + NULSTR_FOREACH(field, fields) { + const void *data; + size_t size; + + r = sd_journal_query_unique(j, field); + if (r < 0) + return r; + + SD_JOURNAL_FOREACH_UNIQUE(j, data, size) { + char **pattern, *eq; + size_t prefix; + _cleanup_free_ char *u = NULL; + + eq = memchr(data, '=', size); + if (eq) + prefix = eq - (char*) data + 1; + else + prefix = 0; + + u = strndup((char*) data + prefix, size - prefix); + if (!u) + return -ENOMEM; + + STRV_FOREACH(pattern, patterns) + if (fnmatch(*pattern, u, FNM_NOESCAPE) == 0) { + log_debug("Matched %s with pattern %s=%s", u, field, *pattern); + + r = set_consume(found, u); + u = NULL; + if (r < 0 && r != -EEXIST) + return r; + + break; + } + } + } + + *units = TAKE_PTR(found); + + return 0; +} + +/* This list is supposed to return the superset of unit names + * possibly matched by rules added with add_matches_for_unit... */ +#define SYSTEM_UNITS \ + "_SYSTEMD_UNIT\0" \ + "COREDUMP_UNIT\0" \ + "UNIT\0" \ + "OBJECT_SYSTEMD_UNIT\0" \ + "_SYSTEMD_SLICE\0" + +/* ... and add_matches_for_user_unit */ +#define USER_UNITS \ + "_SYSTEMD_USER_UNIT\0" \ + "USER_UNIT\0" \ + "COREDUMP_USER_UNIT\0" \ + "OBJECT_SYSTEMD_USER_UNIT\0" \ + "_SYSTEMD_USER_SLICE\0" + +static int add_units(sd_journal *j) { + _cleanup_strv_free_ char **patterns = NULL; + int r, count = 0; + char **i; + + assert(j); + + STRV_FOREACH(i, arg_system_units) { + _cleanup_free_ char *u = NULL; + + r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN), &u); + if (r < 0) + return r; + + if (string_is_glob(u)) { + r = strv_push(&patterns, u); + if (r < 0) + return r; + u = NULL; + } else { + r = add_matches_for_unit(j, u); + if (r < 0) + return r; + r = sd_journal_add_disjunction(j); + if (r < 0) + return r; + count++; + } + } + + if (!strv_isempty(patterns)) { + _cleanup_set_free_free_ Set *units = NULL; + Iterator it; + char *u; + + r = get_possible_units(j, SYSTEM_UNITS, patterns, &units); + if (r < 0) + return r; + + SET_FOREACH(u, units, it) { + r = add_matches_for_unit(j, u); + if (r < 0) + return r; + r = sd_journal_add_disjunction(j); + if (r < 0) + return r; + count++; + } + } + + patterns = strv_free(patterns); + + STRV_FOREACH(i, arg_user_units) { + _cleanup_free_ char *u = NULL; + + r = unit_name_mangle(*i, UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN), &u); + if (r < 0) + return r; + + if (string_is_glob(u)) { + r = strv_push(&patterns, u); + if (r < 0) + return r; + u = NULL; + } else { + r = add_matches_for_user_unit(j, u, getuid()); + if (r < 0) + return r; + r = sd_journal_add_disjunction(j); + if (r < 0) + return r; + count++; + } + } + + if (!strv_isempty(patterns)) { + _cleanup_set_free_free_ Set *units = NULL; + Iterator it; + char *u; + + r = get_possible_units(j, USER_UNITS, patterns, &units); + if (r < 0) + return r; + + SET_FOREACH(u, units, it) { + r = add_matches_for_user_unit(j, u, getuid()); + if (r < 0) + return r; + r = sd_journal_add_disjunction(j); + if (r < 0) + return r; + count++; + } + } + + /* Complain if the user request matches but nothing whatsoever was + * found, since otherwise everything would be matched. */ + if (!(strv_isempty(arg_system_units) && strv_isempty(arg_user_units)) && count == 0) + return -ENODATA; + + r = sd_journal_add_conjunction(j); + if (r < 0) + return r; + + return 0; +} + +static int add_priorities(sd_journal *j) { + char match[] = "PRIORITY=0"; + int i, r; + assert(j); + + if (arg_priorities == 0xFF) + return 0; + + for (i = LOG_EMERG; i <= LOG_DEBUG; i++) + if (arg_priorities & (1 << i)) { + match[sizeof(match)-2] = '0' + i; + + r = sd_journal_add_match(j, match, strlen(match)); + if (r < 0) + return log_error_errno(r, "Failed to add match: %m"); + } + + r = sd_journal_add_conjunction(j); + if (r < 0) + return log_error_errno(r, "Failed to add conjunction: %m"); + + return 0; +} + +static int add_syslog_identifier(sd_journal *j) { + int r; + char **i; + + assert(j); + + STRV_FOREACH(i, arg_syslog_identifier) { + _cleanup_free_ char *u = NULL; + + u = strjoin("SYSLOG_IDENTIFIER=", *i); + if (!u) + return -ENOMEM; + r = sd_journal_add_match(j, u, 0); + if (r < 0) + return r; + r = sd_journal_add_disjunction(j); + if (r < 0) + return r; + } + + r = sd_journal_add_conjunction(j); + if (r < 0) + return r; + + return 0; +} + +static int setup_keys(void) { +#if HAVE_GCRYPT + size_t mpk_size, seed_size, state_size, i; + uint8_t *mpk, *seed, *state; + int fd = -1, r; + sd_id128_t machine, boot; + char *p = NULL, *k = NULL; + struct FSSHeader h; + uint64_t n; + struct stat st; + + r = stat("/var/log/journal", &st); + if (r < 0 && !IN_SET(errno, ENOENT, ENOTDIR)) + return log_error_errno(errno, "stat(\"%s\") failed: %m", "/var/log/journal"); + + if (r < 0 || !S_ISDIR(st.st_mode)) { + log_error("%s is not a directory, must be using persistent logging for FSS.", + "/var/log/journal"); + return r < 0 ? -errno : -ENOTDIR; + } + + r = sd_id128_get_machine(&machine); + if (r < 0) + return log_error_errno(r, "Failed to get machine ID: %m"); + + r = sd_id128_get_boot(&boot); + if (r < 0) + return log_error_errno(r, "Failed to get boot ID: %m"); + + if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss", + SD_ID128_FORMAT_VAL(machine)) < 0) + return log_oom(); + + if (arg_force) { + r = unlink(p); + if (r < 0 && errno != ENOENT) { + r = log_error_errno(errno, "unlink(\"%s\") failed: %m", p); + goto finish; + } + } else if (access(p, F_OK) >= 0) { + log_error("Sealing key file %s exists already. Use --force to recreate.", p); + r = -EEXIST; + goto finish; + } + + if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX", + SD_ID128_FORMAT_VAL(machine)) < 0) { + r = log_oom(); + goto finish; + } + + mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR); + mpk = alloca(mpk_size); + + seed_size = FSPRG_RECOMMENDED_SEEDLEN; + seed = alloca(seed_size); + + state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR); + state = alloca(state_size); + + fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + r = log_error_errno(errno, "Failed to open /dev/random: %m"); + goto finish; + } + + log_info("Generating seed..."); + r = loop_read_exact(fd, seed, seed_size, true); + if (r < 0) { + log_error_errno(r, "Failed to read random seed: %m"); + goto finish; + } + + log_info("Generating key pair..."); + FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR); + + log_info("Generating sealing key..."); + FSPRG_GenState0(state, mpk, seed, seed_size); + + assert(arg_interval > 0); + + n = now(CLOCK_REALTIME); + n /= arg_interval; + + safe_close(fd); + fd = mkostemp_safe(k); + if (fd < 0) { + r = log_error_errno(fd, "Failed to open %s: %m", k); + goto finish; + } + + /* Enable secure remove, exclusion from dump, synchronous + * writing and in-place updating */ + r = chattr_fd(fd, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL, NULL); + if (r < 0) + log_warning_errno(r, "Failed to set file attributes: %m"); + + zero(h); + memcpy(h.signature, "KSHHRHLP", 8); + h.machine_id = machine; + h.boot_id = boot; + h.header_size = htole64(sizeof(h)); + h.start_usec = htole64(n * arg_interval); + h.interval_usec = htole64(arg_interval); + h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR); + h.fsprg_state_size = htole64(state_size); + + r = loop_write(fd, &h, sizeof(h), false); + if (r < 0) { + log_error_errno(r, "Failed to write header: %m"); + goto finish; + } + + r = loop_write(fd, state, state_size, false); + if (r < 0) { + log_error_errno(r, "Failed to write state: %m"); + goto finish; + } + + if (link(k, p) < 0) { + r = log_error_errno(errno, "Failed to link file: %m"); + goto finish; + } + + if (on_tty()) { + fprintf(stderr, + "\n" + "The new key pair has been generated. The %ssecret sealing key%s has been written to\n" + "the following local file. This key file is automatically updated when the\n" + "sealing key is advanced. It should not be used on multiple hosts.\n" + "\n" + "\t%s\n" + "\n" + "Please write down the following %ssecret verification key%s. It should be stored\n" + "at a safe location and should not be saved locally on disk.\n" + "\n\t%s", + ansi_highlight(), ansi_normal(), + p, + ansi_highlight(), ansi_normal(), + ansi_highlight_red()); + fflush(stderr); + } + for (i = 0; i < seed_size; i++) { + if (i > 0 && i % 3 == 0) + putchar('-'); + printf("%02x", ((uint8_t*) seed)[i]); + } + + printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval); + + if (on_tty()) { + char tsb[FORMAT_TIMESPAN_MAX], *hn; + + fprintf(stderr, + "%s\n" + "The sealing key is automatically changed every %s.\n", + ansi_normal(), + format_timespan(tsb, sizeof(tsb), arg_interval, 0)); + + hn = gethostname_malloc(); + + if (hn) { + hostname_cleanup(hn); + fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine)); + } else + fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine)); + +#if HAVE_QRENCODE + /* If this is not an UTF-8 system don't print any QR codes */ + if (is_locale_utf8()) { + fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr); + print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine); + } +#endif + free(hn); + } + + r = 0; + +finish: + safe_close(fd); + + if (k) { + (void) unlink(k); + free(k); + } + + free(p); + + return r; +#else + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Forward-secure sealing not available."); +#endif +} + +static int verify(sd_journal *j) { + int r = 0; + Iterator i; + JournalFile *f; + + assert(j); + + log_show_color(true); + + ORDERED_HASHMAP_FOREACH(f, j->files, i) { + int k; + usec_t first = 0, validated = 0, last = 0; + +#if HAVE_GCRYPT + if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) + log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path); +#endif + + k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true); + if (k == -EINVAL) { + /* If the key was invalid give up right-away. */ + return k; + } else if (k < 0) { + log_warning_errno(k, "FAIL: %s (%m)", f->path); + r = k; + } else { + char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX]; + log_info("PASS: %s", f->path); + + if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) { + if (validated > 0) { + log_info("=> Validated from %s to %s, final %s entries not sealed.", + format_timestamp_maybe_utc(a, sizeof(a), first), + format_timestamp_maybe_utc(b, sizeof(b), validated), + format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0)); + } else if (last > 0) + log_info("=> No sealing yet, %s of entries not sealed.", + format_timespan(c, sizeof(c), last - first, 0)); + else + log_info("=> No sealing yet, no entries in file."); + } + } + } + + return r; +} + +static int simple_varlink_call(const char *option, const char *method) { + _cleanup_(varlink_flush_close_unrefp) Varlink *link = NULL; + const char *error; + int r; + + if (arg_machine) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "%s is not supported in conjunction with --machine=.", option); + + r = varlink_connect_address(&link, "/run/systemd/journal/io.systemd.journal"); + if (r < 0) + return log_error_errno(r, "Failed to connect to /run/systemd/journal/io.systemd.journal: %m"); + + (void) varlink_set_description(link, "journal"); + (void) varlink_set_relative_timeout(link, USEC_INFINITY); + + r = varlink_call(link, method, NULL, NULL, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to execute varlink call: %m"); + if (error) + return log_error_errno(SYNTHETIC_ERRNO(ENOANO), + "Failed to execute varlink call: %s", error); + + return 0; +} + +static int flush_to_var(void) { + return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar"); +} + +static int relinquish_var(void) { + return simple_varlink_call("--relinquish-var/--smart-relinquish-var", "io.systemd.Journal.RelinquishVar"); +} + +static int rotate(void) { + return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate"); +} + +static int sync_journal(void) { + return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize"); +} + +static int wait_for_change(sd_journal *j, int poll_fd) { + struct pollfd pollfds[] = { + { .fd = poll_fd, .events = POLLIN }, + { .fd = STDOUT_FILENO }, + }; + + struct timespec ts; + usec_t timeout; + int r; + + assert(j); + assert(poll_fd >= 0); + + /* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, + * i.e. when it is closed. */ + + r = sd_journal_get_timeout(j, &timeout); + if (r < 0) + return log_error_errno(r, "Failed to determine journal waiting time: %m"); + + if (ppoll(pollfds, ELEMENTSOF(pollfds), + timeout == USEC_INFINITY ? NULL : timespec_store(&ts, timeout), NULL) < 0) { + if (errno == EINTR) + return 0; + + return log_error_errno(errno, "Couldn't wait for journal event: %m"); + } + + if (pollfds[1].revents & (POLLHUP|POLLERR)) /* STDOUT has been closed? */ + return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED), + "Standard output has been closed."); + + r = sd_journal_process(j); + if (r < 0) + return log_error_errno(r, "Failed to process journal events: %m"); + + return 0; +} + +int main(int argc, char *argv[]) { + bool previous_boot_id_valid = false, first_line = true, ellipsized = false, need_seek = false; + bool use_cursor = false, after_cursor = false; + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + sd_id128_t previous_boot_id; + int n_shown = 0, r, poll_fd = -1; + + setlocale(LC_ALL, ""); + log_show_color(true); + log_parse_environment(); + log_open(); + + /* Increase max number of open files if we can, we might needs this when browsing journal files, which might be + * split up into many files. */ + (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); + + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + + signal(SIGWINCH, columns_lines_cache_reset); + sigbus_install(); + + switch (arg_action) { + + case ACTION_NEW_ID128: + r = id128_print_new(ID128_PRINT_PRETTY); + goto finish; + + case ACTION_SETUP_KEYS: + r = setup_keys(); + goto finish; + + case ACTION_LIST_CATALOG: + case ACTION_DUMP_CATALOG: + case ACTION_UPDATE_CATALOG: { + _cleanup_free_ char *database; + + database = path_join(arg_root, CATALOG_DATABASE); + if (!database) { + r = log_oom(); + goto finish; + } + + if (arg_action == ACTION_UPDATE_CATALOG) { + r = catalog_update(database, arg_root, catalog_file_dirs); + if (r < 0) + log_error_errno(r, "Failed to list catalog: %m"); + } else { + bool oneline = arg_action == ACTION_LIST_CATALOG; + + (void) pager_open(arg_pager_flags); + + if (optind < argc) + r = catalog_list_items(stdout, database, oneline, argv + optind); + else + r = catalog_list(stdout, database, oneline); + if (r < 0) + log_error_errno(r, "Failed to list catalog: %m"); + } + + goto finish; + } + + case ACTION_FLUSH: + r = flush_to_var(); + goto finish; + + case ACTION_RELINQUISH_VAR: + r = relinquish_var(); + goto finish; + + case ACTION_SYNC: + r = sync_journal(); + goto finish; + + case ACTION_ROTATE: + r = rotate(); + goto finish; + + case ACTION_SHOW: + case ACTION_PRINT_HEADER: + case ACTION_VERIFY: + case ACTION_DISK_USAGE: + case ACTION_LIST_BOOTS: + case ACTION_VACUUM: + case ACTION_ROTATE_AND_VACUUM: + case ACTION_LIST_FIELDS: + case ACTION_LIST_FIELD_NAMES: + /* These ones require access to the journal files, continue below. */ + break; + + default: + assert_not_reached("Unknown action"); + } + + if (arg_directory) + r = sd_journal_open_directory(&j, arg_directory, arg_journal_type); + else if (arg_root) + r = sd_journal_open_directory(&j, arg_root, arg_journal_type | SD_JOURNAL_OS_ROOT); + else if (arg_file_stdin) { + int ifd = STDIN_FILENO; + r = sd_journal_open_files_fd(&j, &ifd, 1, 0); + } else if (arg_file) + r = sd_journal_open_files(&j, (const char**) arg_file, 0); + else if (arg_machine) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int fd; + + if (geteuid() != 0) { + /* The file descriptor returned by OpenMachineRootDirectory() will be owned by users/groups of + * the container, thus we need root privileges to override them. */ + log_error("Using the --machine= switch requires root privileges."); + r = -EPERM; + goto finish; + } + + r = sd_bus_open_system(&bus); + if (r < 0) { + log_error_errno(r, "Failed to open system bus: %m"); + goto finish; + } + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "OpenMachineRootDirectory", + &error, + &reply, + "s", arg_machine); + if (r < 0) { + log_error_errno(r, "Failed to open root directory: %s", bus_error_message(&error, r)); + goto finish; + } + + r = sd_bus_message_read(reply, "h", &fd); + if (r < 0) { + bus_log_parse_error(r); + goto finish; + } + + fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (fd < 0) { + r = log_error_errno(errno, "Failed to duplicate file descriptor: %m"); + goto finish; + } + + r = sd_journal_open_directory_fd(&j, fd, SD_JOURNAL_OS_ROOT); + if (r < 0) + safe_close(fd); + } else + r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type); + if (r < 0) { + log_error_errno(r, "Failed to open %s: %m", arg_directory ?: arg_file ? "files" : "journal"); + goto finish; + } + + r = journal_access_check_and_warn(j, arg_quiet, + !(arg_journal_type == SD_JOURNAL_CURRENT_USER || arg_user_units)); + if (r < 0) + goto finish; + + switch (arg_action) { + + case ACTION_NEW_ID128: + case ACTION_SETUP_KEYS: + case ACTION_LIST_CATALOG: + case ACTION_DUMP_CATALOG: + case ACTION_UPDATE_CATALOG: + case ACTION_FLUSH: + case ACTION_SYNC: + case ACTION_ROTATE: + assert_not_reached("Unexpected action."); + + case ACTION_PRINT_HEADER: + journal_print_header(j); + r = 0; + goto finish; + + case ACTION_VERIFY: + r = verify(j); + goto finish; + + case ACTION_DISK_USAGE: { + uint64_t bytes = 0; + char sbytes[FORMAT_BYTES_MAX]; + + r = sd_journal_get_usage(j, &bytes); + if (r < 0) + goto finish; + + printf("Archived and active journals take up %s in the file system.\n", + format_bytes(sbytes, sizeof(sbytes), bytes)); + goto finish; + } + + case ACTION_LIST_BOOTS: + r = list_boots(j); + goto finish; + + case ACTION_ROTATE_AND_VACUUM: + + r = rotate(); + if (r < 0) + goto finish; + + _fallthrough_; + + case ACTION_VACUUM: { + Directory *d; + Iterator i; + + HASHMAP_FOREACH(d, j->directories_by_path, i) { + int q; + + q = journal_directory_vacuum(d->path, arg_vacuum_size, arg_vacuum_n_files, arg_vacuum_time, NULL, !arg_quiet); + if (q < 0) { + log_error_errno(q, "Failed to vacuum %s: %m", d->path); + r = q; + } + } + + goto finish; + } + + case ACTION_LIST_FIELD_NAMES: { + const char *field; + + SD_JOURNAL_FOREACH_FIELD(j, field) { + printf("%s\n", field); + n_shown++; + } + + r = 0; + goto finish; + } + + case ACTION_SHOW: + case ACTION_LIST_FIELDS: + break; + + default: + assert_not_reached("Unknown action"); + } + + if (arg_boot_offset != 0 && + sd_journal_has_runtime_files(j) > 0 && + sd_journal_has_persistent_files(j) == 0) { + log_info("Specifying boot ID or boot offset has no effect, no persistent journal was found."); + r = 0; + goto finish; + } + /* add_boot() must be called first! + * It may need to seek the journal to find parent boot IDs. */ + r = add_boot(j); + if (r < 0) + goto finish; + + r = add_dmesg(j); + if (r < 0) + goto finish; + + r = add_units(j); + if (r < 0) { + log_error_errno(r, "Failed to add filter for units: %m"); + goto finish; + } + + r = add_syslog_identifier(j); + if (r < 0) { + log_error_errno(r, "Failed to add filter for syslog identifiers: %m"); + goto finish; + } + + r = add_priorities(j); + if (r < 0) + goto finish; + + r = add_matches(j, argv + optind); + if (r < 0) + goto finish; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *filter; + + filter = journal_make_match_string(j); + if (!filter) + return log_oom(); + + log_debug("Journal filter: %s", filter); + } + + if (arg_action == ACTION_LIST_FIELDS) { + const void *data; + size_t size; + + assert(arg_field); + + r = sd_journal_set_data_threshold(j, 0); + if (r < 0) { + log_error_errno(r, "Failed to unset data size threshold: %m"); + goto finish; + } + + r = sd_journal_query_unique(j, arg_field); + if (r < 0) { + log_error_errno(r, "Failed to query unique data objects: %m"); + goto finish; + } + + SD_JOURNAL_FOREACH_UNIQUE(j, data, size) { + const void *eq; + + if (arg_lines >= 0 && n_shown >= arg_lines) + break; + + eq = memchr(data, '=', size); + if (eq) + printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1); + else + printf("%.*s\n", (int) size, (const char*) data); + + n_shown++; + } + + r = 0; + goto finish; + } + + /* Opening the fd now means the first sd_journal_wait() will actually wait */ + if (arg_follow) { + poll_fd = sd_journal_get_fd(j); + if (poll_fd == -EMFILE) { + log_warning_errno(poll_fd, "Insufficient watch descriptors available. Reverting to -n."); + arg_follow = false; + } else if (poll_fd == -EMEDIUMTYPE) { + log_error_errno(poll_fd, "The --follow switch is not supported in conjunction with reading from STDIN."); + goto finish; + } else if (poll_fd < 0) { + log_error_errno(poll_fd, "Failed to get journal fd: %m"); + goto finish; + } + } + + if (arg_cursor || arg_after_cursor || arg_cursor_file) { + _cleanup_free_ char *cursor_from_file = NULL; + const char *cursor = arg_cursor ?: arg_after_cursor; + + if (arg_cursor_file) { + r = read_one_line_file(arg_cursor_file, &cursor_from_file); + if (r < 0 && r != -ENOENT) { + log_error_errno(r, "Failed to read cursor file %s: %m", arg_cursor_file); + goto finish; + } + + if (r > 0) { + cursor = cursor_from_file; + after_cursor = true; + } + } else + after_cursor = !!arg_after_cursor; + + if (cursor) { + r = sd_journal_seek_cursor(j, cursor); + if (r < 0) { + log_error_errno(r, "Failed to seek to cursor: %m"); + goto finish; + } + use_cursor = true; + } + } + + if (use_cursor) { + if (!arg_reverse) + r = sd_journal_next_skip(j, 1 + after_cursor); + else + r = sd_journal_previous_skip(j, 1 + after_cursor); + + if (after_cursor && r < 2) { + /* We couldn't find the next entry after the cursor. */ + if (arg_follow) + need_seek = true; + else + arg_lines = 0; + } + + } else if (arg_since_set && !arg_reverse) { + r = sd_journal_seek_realtime_usec(j, arg_since); + if (r < 0) { + log_error_errno(r, "Failed to seek to date: %m"); + goto finish; + } + r = sd_journal_next(j); + + } else if (arg_until_set && arg_reverse) { + r = sd_journal_seek_realtime_usec(j, arg_until); + if (r < 0) { + log_error_errno(r, "Failed to seek to date: %m"); + goto finish; + } + r = sd_journal_previous(j); + + } else if (arg_reverse) { + r = sd_journal_seek_tail(j); + if (r < 0) { + log_error_errno(r, "Failed to seek to tail: %m"); + goto finish; + } + + r = sd_journal_previous(j); + + } else if (arg_lines >= 0) { + r = sd_journal_seek_tail(j); + if (r < 0) { + log_error_errno(r, "Failed to seek to tail: %m"); + goto finish; + } + + r = sd_journal_previous_skip(j, arg_lines); + + } else { + r = sd_journal_seek_head(j); + if (r < 0) { + log_error_errno(r, "Failed to seek to head: %m"); + goto finish; + } + + r = sd_journal_next(j); + } + + if (r < 0) { + log_error_errno(r, "Failed to iterate through journal: %m"); + goto finish; + } + if (r == 0) + need_seek = true; + + if (!arg_follow) + (void) pager_open(arg_pager_flags); + + if (!arg_quiet && (arg_lines != 0 || arg_follow)) { + usec_t start, end; + char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX]; + + r = sd_journal_get_cutoff_realtime_usec(j, &start, &end); + if (r < 0) { + log_error_errno(r, "Failed to get cutoff: %m"); + goto finish; + } + + if (r > 0) { + if (arg_follow) + printf("-- Logs begin at %s. --\n", + format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start)); + else + printf("-- Logs begin at %s, end at %s. --\n", + format_timestamp_maybe_utc(start_buf, sizeof(start_buf), start), + format_timestamp_maybe_utc(end_buf, sizeof(end_buf), end)); + } + } + + for (;;) { + while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) { + int flags; + size_t highlight[2] = {}; + + if (need_seek) { + if (!arg_reverse) + r = sd_journal_next(j); + else + r = sd_journal_previous(j); + if (r < 0) { + log_error_errno(r, "Failed to iterate through journal: %m"); + goto finish; + } + if (r == 0) + break; + } + + if (arg_until_set && !arg_reverse) { + usec_t usec; + + r = sd_journal_get_realtime_usec(j, &usec); + if (r < 0) { + log_error_errno(r, "Failed to determine timestamp: %m"); + goto finish; + } + if (usec > arg_until) + break; + } + + if (arg_since_set && arg_reverse) { + usec_t usec; + + r = sd_journal_get_realtime_usec(j, &usec); + if (r < 0) { + log_error_errno(r, "Failed to determine timestamp: %m"); + goto finish; + } + if (usec < arg_since) + break; + } + + if (!arg_merge && !arg_quiet) { + sd_id128_t boot_id; + + r = sd_journal_get_monotonic_usec(j, NULL, &boot_id); + if (r >= 0) { + if (previous_boot_id_valid && + !sd_id128_equal(boot_id, previous_boot_id)) + printf("%s-- Reboot --%s\n", + ansi_highlight(), ansi_normal()); + + previous_boot_id = boot_id; + previous_boot_id_valid = true; + } + } + +#if HAVE_PCRE2 + if (arg_compiled_pattern) { + _cleanup_(pcre2_match_data_freep) pcre2_match_data *md = NULL; + const void *message; + size_t len; + PCRE2_SIZE *ovec; + + md = pcre2_match_data_create(1, NULL); + if (!md) + return log_oom(); + + r = sd_journal_get_data(j, "MESSAGE", &message, &len); + if (r < 0) { + if (r == -ENOENT) { + need_seek = true; + continue; + } + + log_error_errno(r, "Failed to get MESSAGE field: %m"); + goto finish; + } + + assert_se(message = startswith(message, "MESSAGE=")); + + r = pcre2_match(arg_compiled_pattern, + message, + len - strlen("MESSAGE="), + 0, /* start at offset 0 in the subject */ + 0, /* default options */ + md, + NULL); + if (r == PCRE2_ERROR_NOMATCH) { + need_seek = true; + continue; + } + if (r < 0) { + unsigned char buf[LINE_MAX]; + int r2; + + r2 = pcre2_get_error_message(r, buf, sizeof buf); + log_error("Pattern matching failed: %s", + r2 < 0 ? "unknown error" : (char*) buf); + r = -EINVAL; + goto finish; + } + + ovec = pcre2_get_ovector_pointer(md); + highlight[0] = ovec[0]; + highlight[1] = ovec[1]; + } +#endif + + flags = + arg_all * OUTPUT_SHOW_ALL | + arg_full * OUTPUT_FULL_WIDTH | + colors_enabled() * OUTPUT_COLOR | + arg_catalog * OUTPUT_CATALOG | + arg_utc * OUTPUT_UTC | + arg_no_hostname * OUTPUT_NO_HOSTNAME; + + r = show_journal_entry(stdout, j, arg_output, 0, flags, + arg_output_fields, highlight, &ellipsized); + need_seek = true; + if (r == -EADDRNOTAVAIL) + break; + else if (r < 0) + goto finish; + + n_shown++; + + /* If journalctl take a long time to process messages, and during that time journal file + * rotation occurs, a journalctl client will keep those rotated files open until it calls + * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below + * in the "following" case. By periodically calling sd_journal_process() during the processing + * loop we shrink the window of time a client instance has open file descriptors for rotated + * (deleted) journal files. */ + if ((n_shown % PROCESS_INOTIFY_INTERVAL) == 0) { + r = sd_journal_process(j); + if (r < 0) { + log_error_errno(r, "Failed to process inotify events: %m"); + goto finish; + } + } + } + + if (!arg_follow) { + if (n_shown == 0 && !arg_quiet) + printf("-- No entries --\n"); + break; + } + + fflush(stdout); + + r = wait_for_change(j, poll_fd); + if (r < 0) + goto finish; + + first_line = false; + } + + if (arg_show_cursor || arg_cursor_file) { + _cleanup_free_ char *cursor = NULL; + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0 && r != -EADDRNOTAVAIL) + log_error_errno(r, "Failed to get cursor: %m"); + else if (r >= 0) { + if (arg_show_cursor) + printf("-- cursor: %s\n", cursor); + + if (arg_cursor_file) { + r = write_string_file(arg_cursor_file, cursor, + WRITE_STRING_FILE_CREATE | + WRITE_STRING_FILE_ATOMIC); + if (r < 0) + log_error_errno(r, + "Failed to write new cursor to %s: %m", + arg_cursor_file); + } + } + } + +finish: + pager_close(); + + strv_free(arg_file); + + strv_free(arg_syslog_identifier); + strv_free(arg_system_units); + strv_free(arg_user_units); + strv_free(arg_output_fields); + + free(arg_root); + free(arg_verify_key); + +#if HAVE_PCRE2 + if (arg_compiled_pattern) { + pcre2_code_free(arg_compiled_pattern); + + /* --grep was used, no error was thrown, but the pattern didn't + * match anything. Let's mimic grep's behavior here and return + * a non-zero exit code, so journalctl --grep can be used + * in scripts and such */ + if (r == 0 && n_shown == 0) + r = -ENOENT; + } +#endif + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/journal/journald-audit.c b/src/journal/journald-audit.c new file mode 100644 index 00000000..339e091d --- /dev/null +++ b/src/journal/journald-audit.c @@ -0,0 +1,548 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "audit-type.h" +#include "fd-util.h" +#include "hexdecoct.h" +#include "io-util.h" +#include "journald-audit.h" +#include "missing_audit.h" +#include "string-util.h" + +typedef struct MapField { + const char *audit_field; + const char *journal_field; + int (*map)(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov); +} MapField; + +static int map_simple_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov) { + _cleanup_free_ char *c = NULL; + size_t l = 0, allocated = 0; + const char *e; + + assert(field); + assert(p); + assert(iov); + assert(n_iov); + + l = strlen(field); + allocated = l + 1; + c = malloc(allocated); + if (!c) + return -ENOMEM; + + memcpy(c, field, l); + for (e = *p; !IN_SET(*e, 0, ' '); e++) { + if (!GREEDY_REALLOC(c, allocated, l+2)) + return -ENOMEM; + + c[l++] = *e; + } + + c[l] = 0; + + if (!GREEDY_REALLOC(*iov, *n_iov_allocated, *n_iov + 1)) + return -ENOMEM; + + (*iov)[(*n_iov)++] = IOVEC_MAKE(c, l); + + *p = e; + c = NULL; + + return 1; +} + +static int map_string_field_internal(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov, bool filter_printable) { + _cleanup_free_ char *c = NULL; + const char *s, *e; + size_t l; + + assert(field); + assert(p); + assert(iov); + assert(n_iov); + + /* The kernel formats string fields in one of two formats. */ + + if (**p == '"') { + /* Normal quoted syntax */ + s = *p + 1; + e = strchr(s, '"'); + if (!e) + return 0; + + l = strlen(field) + (e - s); + c = malloc(l+1); + if (!c) + return -ENOMEM; + + *((char*) mempcpy(stpcpy(c, field), s, e - s)) = 0; + + e += 1; + + } else if (unhexchar(**p) >= 0) { + /* Hexadecimal escaping */ + size_t allocated = 0; + + l = strlen(field); + allocated = l + 2; + c = malloc(allocated); + if (!c) + return -ENOMEM; + + memcpy(c, field, l); + for (e = *p; !IN_SET(*e, 0, ' '); e += 2) { + int a, b; + uint8_t x; + + a = unhexchar(e[0]); + if (a < 0) + return 0; + + b = unhexchar(e[1]); + if (b < 0) + return 0; + + x = ((uint8_t) a << 4 | (uint8_t) b); + + if (filter_printable && x < (uint8_t) ' ') + x = (uint8_t) ' '; + + if (!GREEDY_REALLOC(c, allocated, l+2)) + return -ENOMEM; + + c[l++] = (char) x; + } + + c[l] = 0; + } else + return 0; + + if (!GREEDY_REALLOC(*iov, *n_iov_allocated, *n_iov + 1)) + return -ENOMEM; + + (*iov)[(*n_iov)++] = IOVEC_MAKE(c, l); + + *p = e; + c = NULL; + + return 1; +} + +static int map_string_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov) { + return map_string_field_internal(field, p, iov, n_iov_allocated, n_iov, false); +} + +static int map_string_field_printable(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov) { + return map_string_field_internal(field, p, iov, n_iov_allocated, n_iov, true); +} + +static int map_generic_field(const char *prefix, const char **p, struct iovec **iov, size_t *n_iov_allocated, size_t *n_iov) { + const char *e, *f; + char *c, *t; + int r; + + /* Implements fallback mappings for all fields we don't know */ + + for (e = *p; e < *p + 16; e++) { + + if (IN_SET(*e, 0, ' ')) + return 0; + + if (*e == '=') + break; + + if (!((*e >= 'a' && *e <= 'z') || + (*e >= 'A' && *e <= 'Z') || + (*e >= '0' && *e <= '9') || + IN_SET(*e, '_', '-'))) + return 0; + } + + if (e <= *p || e >= *p + 16) + return 0; + + c = newa(char, strlen(prefix) + (e - *p) + 2); + + t = stpcpy(c, prefix); + for (f = *p; f < e; f++) { + char x; + + if (*f >= 'a' && *f <= 'z') + x = (*f - 'a') + 'A'; /* uppercase */ + else if (*f == '-') + x = '_'; /* dashes → underscores */ + else + x = *f; + + *(t++) = x; + } + strcpy(t, "="); + + e++; + + r = map_simple_field(c, &e, iov, n_iov_allocated, n_iov); + if (r < 0) + return r; + + *p = e; + return r; +} + +/* Kernel fields are those occurring in the audit string before + * msg='. All of these fields are trusted, hence carry the "_" prefix. + * We try to translate the fields we know into our native names. The + * other's are generically mapped to _AUDIT_FIELD_XYZ= */ +static const MapField map_fields_kernel[] = { + + /* First, we map certain well-known audit fields into native + * well-known fields */ + { "pid=", "_PID=", map_simple_field }, + { "ppid=", "_PPID=", map_simple_field }, + { "uid=", "_UID=", map_simple_field }, + { "euid=", "_EUID=", map_simple_field }, + { "fsuid=", "_FSUID=", map_simple_field }, + { "gid=", "_GID=", map_simple_field }, + { "egid=", "_EGID=", map_simple_field }, + { "fsgid=", "_FSGID=", map_simple_field }, + { "tty=", "_TTY=", map_simple_field }, + { "ses=", "_AUDIT_SESSION=", map_simple_field }, + { "auid=", "_AUDIT_LOGINUID=", map_simple_field }, + { "subj=", "_SELINUX_CONTEXT=", map_simple_field }, + { "comm=", "_COMM=", map_string_field }, + { "exe=", "_EXE=", map_string_field }, + { "proctitle=", "_CMDLINE=", map_string_field_printable }, + + /* Some fields don't map to native well-known fields. However, + * we know that they are string fields, hence let's undo + * string field escaping for them, though we stick to the + * generic field names. */ + { "path=", "_AUDIT_FIELD_PATH=", map_string_field }, + { "dev=", "_AUDIT_FIELD_DEV=", map_string_field }, + { "name=", "_AUDIT_FIELD_NAME=", map_string_field }, + {} +}; + +/* Userspace fields are those occurring in the audit string after + * msg='. All of these fields are untrusted, hence carry no "_" + * prefix. We map the fields we don't know to AUDIT_FIELD_XYZ= */ +static const MapField map_fields_userspace[] = { + { "cwd=", "AUDIT_FIELD_CWD=", map_string_field }, + { "cmd=", "AUDIT_FIELD_CMD=", map_string_field }, + { "acct=", "AUDIT_FIELD_ACCT=", map_string_field }, + { "exe=", "AUDIT_FIELD_EXE=", map_string_field }, + { "comm=", "AUDIT_FIELD_COMM=", map_string_field }, + {} +}; + +static int map_all_fields( + const char *p, + const MapField map_fields[], + const char *prefix, + bool handle_msg, + struct iovec **iov, + size_t *n_iov_allocated, + size_t *n_iov) { + + int r; + + assert(p); + assert(iov); + assert(n_iov_allocated); + assert(n_iov); + + for (;;) { + bool mapped = false; + const MapField *m; + const char *v; + + p += strspn(p, WHITESPACE); + + if (*p == 0) + return 0; + + if (handle_msg) { + v = startswith(p, "msg='"); + if (v) { + _cleanup_free_ char *c = NULL; + const char *e; + + /* Userspace message. It's enclosed in + simple quotation marks, is not + escaped, but the last field in the + line, hence let's remove the + quotation mark, and apply the + userspace mapping instead of the + kernel mapping. */ + + e = endswith(v, "'"); + if (!e) + return 0; /* don't continue splitting up if the final quotation mark is missing */ + + c = strndup(v, e - v); + if (!c) + return -ENOMEM; + + return map_all_fields(c, map_fields_userspace, "AUDIT_FIELD_", false, iov, n_iov_allocated, n_iov); + } + } + + /* Try to map the kernel fields to our own names */ + for (m = map_fields; m->audit_field; m++) { + v = startswith(p, m->audit_field); + if (!v) + continue; + + r = m->map(m->journal_field, &v, iov, n_iov_allocated, n_iov); + if (r < 0) + return log_debug_errno(r, "Failed to parse audit array: %m"); + + if (r > 0) { + mapped = true; + p = v; + break; + } + } + + if (!mapped) { + r = map_generic_field(prefix, &p, iov, n_iov_allocated, n_iov); + if (r < 0) + return log_debug_errno(r, "Failed to parse audit array: %m"); + + if (r == 0) + /* Couldn't process as generic field, let's just skip over it */ + p += strcspn(p, WHITESPACE); + } + } +} + +void process_audit_string(Server *s, int type, const char *data, size_t size) { + size_t n_iov_allocated = 0, n_iov = 0, z; + _cleanup_free_ struct iovec *iov = NULL; + uint64_t seconds, msec, id; + const char *p, *type_name; + char id_field[sizeof("_AUDIT_ID=") + DECIMAL_STR_MAX(uint64_t)], + type_field[sizeof("_AUDIT_TYPE=") + DECIMAL_STR_MAX(int)], + source_time_field[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)]; + char *m, *type_field_name; + int k; + + assert(s); + + if (size <= 0) + return; + + if (!data) + return; + + /* Note that the input buffer is NUL terminated, but let's + * check whether there is a spurious NUL byte */ + if (memchr(data, 0, size)) + return; + + p = startswith(data, "audit"); + if (!p) + return; + + k = 0; + if (sscanf(p, "(%" PRIu64 ".%" PRIu64 ":%" PRIu64 "):%n", + &seconds, + &msec, + &id, + &k) != 3 || k == 0) + return; + + p += k; + p += strspn(p, WHITESPACE); + + if (isempty(p)) + return; + + n_iov_allocated = N_IOVEC_META_FIELDS + 8; + iov = new(struct iovec, n_iov_allocated); + if (!iov) { + log_oom(); + return; + } + + iov[n_iov++] = IOVEC_MAKE_STRING("_TRANSPORT=audit"); + + sprintf(source_time_field, "_SOURCE_REALTIME_TIMESTAMP=%" PRIu64, + (usec_t) seconds * USEC_PER_SEC + (usec_t) msec * USEC_PER_MSEC); + iov[n_iov++] = IOVEC_MAKE_STRING(source_time_field); + + sprintf(type_field, "_AUDIT_TYPE=%i", type); + iov[n_iov++] = IOVEC_MAKE_STRING(type_field); + + sprintf(id_field, "_AUDIT_ID=%" PRIu64, id); + iov[n_iov++] = IOVEC_MAKE_STRING(id_field); + + assert_cc(4 == LOG_FAC(LOG_AUTH)); + iov[n_iov++] = IOVEC_MAKE_STRING("SYSLOG_FACILITY=4"); + iov[n_iov++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=audit"); + + type_name = audit_type_name_alloca(type); + + type_field_name = strjoina("_AUDIT_TYPE_NAME=", type_name); + iov[n_iov++] = IOVEC_MAKE_STRING(type_field_name); + + m = strjoina("MESSAGE=", type_name, " ", p); + iov[n_iov++] = IOVEC_MAKE_STRING(m); + + z = n_iov; + + map_all_fields(p, map_fields_kernel, "_AUDIT_FIELD_", true, &iov, &n_iov_allocated, &n_iov); + + if (!GREEDY_REALLOC(iov, n_iov_allocated, n_iov + N_IOVEC_META_FIELDS)) { + log_oom(); + goto finish; + } + + server_dispatch_message(s, iov, n_iov, n_iov_allocated, NULL, NULL, LOG_NOTICE, 0); + +finish: + /* free() all entries that map_all_fields() added. All others + * are allocated on the stack or are constant. */ + + for (; z < n_iov; z++) + free(iov[z].iov_base); +} + +void server_process_audit_message( + Server *s, + const void *buffer, + size_t buffer_size, + const struct ucred *ucred, + const union sockaddr_union *sa, + socklen_t salen) { + + const struct nlmsghdr *nl = buffer; + + assert(s); + + if (buffer_size < ALIGN(sizeof(struct nlmsghdr))) + return; + + assert(buffer); + + /* Filter out fake data */ + if (!sa || + salen != sizeof(struct sockaddr_nl) || + sa->nl.nl_family != AF_NETLINK || + sa->nl.nl_pid != 0) { + log_debug("Audit netlink message from invalid sender."); + return; + } + + if (!ucred || ucred->pid != 0) { + log_debug("Audit netlink message with invalid credentials."); + return; + } + + if (!NLMSG_OK(nl, buffer_size)) { + log_error("Audit netlink message truncated."); + return; + } + + /* Ignore special Netlink messages */ + if (IN_SET(nl->nlmsg_type, NLMSG_NOOP, NLMSG_ERROR)) + return; + + /* Except AUDIT_USER, all messages below AUDIT_FIRST_USER_MSG are control messages, let's ignore those */ + if (nl->nlmsg_type < AUDIT_FIRST_USER_MSG && nl->nlmsg_type != AUDIT_USER) + return; + + process_audit_string(s, nl->nlmsg_type, NLMSG_DATA(nl), nl->nlmsg_len - ALIGN(sizeof(struct nlmsghdr))); +} + +static int enable_audit(int fd, bool b) { + struct { + union { + struct nlmsghdr header; + uint8_t header_space[NLMSG_HDRLEN]; + }; + struct audit_status body; + } _packed_ request = { + .header.nlmsg_len = NLMSG_LENGTH(sizeof(struct audit_status)), + .header.nlmsg_type = AUDIT_SET, + .header.nlmsg_flags = NLM_F_REQUEST, + .header.nlmsg_seq = 1, + .header.nlmsg_pid = 0, + .body.mask = AUDIT_STATUS_ENABLED, + .body.enabled = b, + }; + union sockaddr_union sa = { + .nl.nl_family = AF_NETLINK, + .nl.nl_pid = 0, + }; + struct iovec iovec = { + .iov_base = &request, + .iov_len = NLMSG_LENGTH(sizeof(struct audit_status)), + }; + struct msghdr mh = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_name = &sa.sa, + .msg_namelen = sizeof(sa.nl), + }; + + ssize_t n; + + n = sendmsg(fd, &mh, MSG_NOSIGNAL); + if (n < 0) + return -errno; + if (n != NLMSG_LENGTH(sizeof(struct audit_status))) + return -EIO; + + /* We don't wait for the result here, we can't do anything + * about it anyway */ + + return 0; +} + +int server_open_audit(Server *s) { + int r; + + if (s->audit_fd < 0) { + static const union sockaddr_union sa = { + .nl.nl_family = AF_NETLINK, + .nl.nl_pid = 0, + .nl.nl_groups = AUDIT_NLGRP_READLOG, + }; + + s->audit_fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT); + if (s->audit_fd < 0) { + if (IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT)) + log_debug("Audit not supported in the kernel."); + else + log_warning_errno(errno, "Failed to create audit socket, ignoring: %m"); + + return 0; + } + + if (bind(s->audit_fd, &sa.sa, sizeof(sa.nl)) < 0) { + log_warning_errno(errno, + "Failed to join audit multicast group. " + "The kernel is probably too old or multicast reading is not supported. " + "Ignoring: %m"); + s->audit_fd = safe_close(s->audit_fd); + return 0; + } + } else + (void) fd_nonblock(s->audit_fd, true); + + r = setsockopt_int(s->audit_fd, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return log_error_errno(r, "Failed to set SO_PASSCRED on audit socket: %m"); + + r = sd_event_add_io(s->event, &s->audit_event_source, s->audit_fd, EPOLLIN, server_process_datagram, s); + if (r < 0) + return log_error_errno(r, "Failed to add audit fd to event loop: %m"); + + /* We are listening now, try to enable audit */ + r = enable_audit(s->audit_fd, true); + if (r < 0) + log_warning_errno(r, "Failed to issue audit enable call: %m"); + + return 0; +} diff --git a/src/journal/journald-audit.h b/src/journal/journald-audit.h new file mode 100644 index 00000000..df41f814 --- /dev/null +++ b/src/journal/journald-audit.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "journald-server.h" +#include "socket-util.h" + +void server_process_audit_message(Server *s, const void *buffer, size_t buffer_size, const struct ucred *ucred, const union sockaddr_union *sa, socklen_t salen); + +void process_audit_string(Server *s, int type, const char *data, size_t size); + +int server_open_audit(Server *s); diff --git a/src/journal/journald-console.c b/src/journal/journald-console.c new file mode 100644 index 00000000..80e29585 --- /dev/null +++ b/src/journal/journald-console.c @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "io-util.h" +#include "journald-console.h" +#include "journald-server.h" +#include "parse-util.h" +#include "process-util.h" +#include "stdio-util.h" +#include "terminal-util.h" + +static bool prefix_timestamp(void) { + + static int cached_printk_time = -1; + + if (_unlikely_(cached_printk_time < 0)) { + _cleanup_free_ char *p = NULL; + + cached_printk_time = + read_one_line_file("/sys/module/printk/parameters/time", &p) >= 0 + && parse_boolean(p) > 0; + } + + return cached_printk_time; +} + +void server_forward_console( + Server *s, + int priority, + const char *identifier, + const char *message, + const struct ucred *ucred) { + + struct iovec iovec[5]; + struct timespec ts; + char tbuf[STRLEN("[] ") + DECIMAL_STR_MAX(ts.tv_sec) + DECIMAL_STR_MAX(ts.tv_nsec)-3 + 1]; + char header_pid[STRLEN("[]: ") + DECIMAL_STR_MAX(pid_t)]; + _cleanup_free_ char *ident_buf = NULL; + _cleanup_close_ int fd = -1; + const char *tty; + int n = 0; + + assert(s); + assert(message); + + if (LOG_PRI(priority) > s->max_level_console) + return; + + /* First: timestamp */ + if (prefix_timestamp()) { + assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); + xsprintf(tbuf, "[%5"PRI_TIME".%06"PRI_NSEC"] ", + ts.tv_sec, + (nsec_t)ts.tv_nsec / 1000); + + iovec[n++] = IOVEC_MAKE_STRING(tbuf); + } + + /* Second: identifier and PID */ + if (ucred) { + if (!identifier) { + get_process_comm(ucred->pid, &ident_buf); + identifier = ident_buf; + } + + xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid); + + if (identifier) + iovec[n++] = IOVEC_MAKE_STRING(identifier); + + iovec[n++] = IOVEC_MAKE_STRING(header_pid); + } else if (identifier) { + iovec[n++] = IOVEC_MAKE_STRING(identifier); + iovec[n++] = IOVEC_MAKE_STRING(": "); + } + + /* Fourth: message */ + iovec[n++] = IOVEC_MAKE_STRING(message); + iovec[n++] = IOVEC_MAKE_STRING("\n"); + + tty = s->tty_path ?: "/dev/console"; + + /* Before you ask: yes, on purpose we open/close the console for each log line we write individually. This is a + * good strategy to avoid journald getting killed by the kernel's SAK concept (it doesn't fix this entirely, + * but minimizes the time window the kernel might end up killing journald due to SAK). It also makes things + * easier for us so that we don't have to recover from hangups and suchlike triggered on the console. */ + + fd = open_terminal(tty, O_WRONLY|O_NOCTTY|O_CLOEXEC); + if (fd < 0) { + log_debug_errno(fd, "Failed to open %s for logging: %m", tty); + return; + } + + if (writev(fd, iovec, n) < 0) + log_debug_errno(errno, "Failed to write to %s for logging: %m", tty); +} diff --git a/src/journal/journald-console.h b/src/journal/journald-console.h new file mode 100644 index 00000000..3def00ad --- /dev/null +++ b/src/journal/journald-console.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "journald-server.h" + +void server_forward_console(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred); diff --git a/src/journal/journald-context.c b/src/journal/journald-context.c new file mode 100644 index 00000000..342ed062 --- /dev/null +++ b/src/journal/journald-context.c @@ -0,0 +1,779 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if HAVE_SELINUX +#include +#endif + +#include "alloc-util.h" +#include "audit-util.h" +#include "cgroup-util.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "io-util.h" +#include "journal-util.h" +#include "journald-context.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "procfs-util.h" +#include "string-util.h" +#include "syslog-util.h" +#include "unaligned.h" +#include "user-util.h" + +/* This implements a metadata cache for clients, which are identified by their PID. Requesting metadata through /proc + * is expensive, hence let's cache the data if we can. Note that this means the metadata might be out-of-date when we + * store it, but it might already be anyway, as we request the data asynchronously from /proc at a different time the + * log entry was originally created. We hence just increase the "window of inaccuracy" a bit. + * + * The cache is indexed by the PID. Entries may be "pinned" in the cache, in which case the entries are not removed + * until they are unpinned. Unpinned entries are kept around until cache pressure is seen. Cache entries older than 5s + * are never used (a sad attempt to deal with the UNIX weakness of PIDs reuse), cache entries older than 1s are + * refreshed in an incremental way (meaning: data is reread from /proc, but any old data we can't refresh is not + * flushed out). Data newer than 1s is used immediately without refresh. + * + * Log stream clients (i.e. all clients using the AF_UNIX/SOCK_STREAM stdout/stderr transport) will pin a cache entry + * as long as their socket is connected. Note that cache entries are shared between different transports. That means a + * cache entry pinned for the stream connection logic may be reused for the syslog or native protocols. + * + * Caching metadata like this has two major benefits: + * + * 1. Reading metadata is expensive, and we can thus substantially speed up log processing under flood. + * + * 2. Because metadata caching is shared between stream and datagram transports and stream connections pin a cache + * entry there's a good chance we can properly map a substantial set of datagram log messages to their originating + * service, as all services (unless explicitly configured otherwise) will have their stdout/stderr connected to a + * stream connection. This should improve cases where a service process logs immediately before exiting and we + * previously had trouble associating the log message with the service. + * + * NB: With and without the metadata cache: the implicitly added entry metadata in the journal (with the exception of + * UID/PID/GID and SELinux label) must be understood as possibly slightly out of sync (i.e. sometimes slightly older + * and sometimes slightly newer than what was current at the log event). + */ + +/* We refresh every 1s */ +#define REFRESH_USEC (1*USEC_PER_SEC) + +/* Data older than 5s we flush out */ +#define MAX_USEC (5*USEC_PER_SEC) + +/* Keep at most 16K entries in the cache. (Note though that this limit may be violated if enough streams pin entries in + * the cache, in which case we *do* permit this limit to be breached. That's safe however, as the number of stream + * clients itself is limited.) */ +#define CACHE_MAX_FALLBACK 128U +#define CACHE_MAX_MAX (16*1024U) +#define CACHE_MAX_MIN 64U + +static size_t cache_max(void) { + static size_t cached = -1; + + if (cached == (size_t) -1) { + uint64_t mem_total; + int r; + + r = procfs_memory_get(&mem_total, NULL); + if (r < 0) { + log_warning_errno(r, "Cannot query /proc/meminfo for MemTotal: %m"); + cached = CACHE_MAX_FALLBACK; + } else + /* Cache entries are usually a few kB, but the process cmdline is controlled by the + * user and can be up to _SC_ARG_MAX, usually 2MB. Let's say that approximately up to + * 1/8th of memory may be used by the cache. + * + * In the common case, this formula gives 64 cache entries for each GB of RAM. + */ + cached = CLAMP(mem_total / 8 / sc_arg_max(), CACHE_MAX_MIN, CACHE_MAX_MAX); + } + + return cached; +} + +static int client_context_compare(const void *a, const void *b) { + const ClientContext *x = a, *y = b; + int r; + + r = CMP(x->timestamp, y->timestamp); + if (r != 0) + return r; + + return CMP(x->pid, y->pid); +} + +static int client_context_new(Server *s, pid_t pid, ClientContext **ret) { + ClientContext *c; + int r; + + assert(s); + assert(pid_is_valid(pid)); + assert(ret); + + r = hashmap_ensure_allocated(&s->client_contexts, NULL); + if (r < 0) + return r; + + r = prioq_ensure_allocated(&s->client_contexts_lru, client_context_compare); + if (r < 0) + return r; + + c = new0(ClientContext, 1); + if (!c) + return -ENOMEM; + + c->pid = pid; + + c->uid = UID_INVALID; + c->gid = GID_INVALID; + c->auditid = AUDIT_SESSION_INVALID; + c->loginuid = UID_INVALID; + c->owner_uid = UID_INVALID; + c->lru_index = PRIOQ_IDX_NULL; + c->timestamp = USEC_INFINITY; + c->extra_fields_mtime = NSEC_INFINITY; + c->log_level_max = -1; + c->log_ratelimit_interval = s->ratelimit_interval; + c->log_ratelimit_burst = s->ratelimit_burst; + + r = hashmap_put(s->client_contexts, PID_TO_PTR(pid), c); + if (r < 0) { + free(c); + return r; + } + + *ret = c; + return 0; +} + +static void client_context_reset(Server *s, ClientContext *c) { + assert(s); + assert(c); + + c->timestamp = USEC_INFINITY; + + c->uid = UID_INVALID; + c->gid = GID_INVALID; + + c->comm = mfree(c->comm); + c->exe = mfree(c->exe); + c->cmdline = mfree(c->cmdline); + c->capeff = mfree(c->capeff); + + c->auditid = AUDIT_SESSION_INVALID; + c->loginuid = UID_INVALID; + + c->cgroup = mfree(c->cgroup); + c->session = mfree(c->session); + c->owner_uid = UID_INVALID; + c->unit = mfree(c->unit); + c->user_unit = mfree(c->user_unit); + c->slice = mfree(c->slice); + c->user_slice = mfree(c->user_slice); + + c->invocation_id = SD_ID128_NULL; + + c->label = mfree(c->label); + c->label_size = 0; + + c->extra_fields_iovec = mfree(c->extra_fields_iovec); + c->extra_fields_n_iovec = 0; + c->extra_fields_data = mfree(c->extra_fields_data); + c->extra_fields_mtime = NSEC_INFINITY; + + c->log_level_max = -1; + + c->log_ratelimit_interval = s->ratelimit_interval; + c->log_ratelimit_burst = s->ratelimit_burst; +} + +static ClientContext* client_context_free(Server *s, ClientContext *c) { + assert(s); + + if (!c) + return NULL; + + assert_se(hashmap_remove(s->client_contexts, PID_TO_PTR(c->pid)) == c); + + if (c->in_lru) + assert_se(prioq_remove(s->client_contexts_lru, c, &c->lru_index) >= 0); + + client_context_reset(s, c); + + return mfree(c); +} + +static void client_context_read_uid_gid(ClientContext *c, const struct ucred *ucred) { + assert(c); + assert(pid_is_valid(c->pid)); + + /* The ucred data passed in is always the most current and accurate, if we have any. Use it. */ + if (ucred && uid_is_valid(ucred->uid)) + c->uid = ucred->uid; + else + (void) get_process_uid(c->pid, &c->uid); + + if (ucred && gid_is_valid(ucred->gid)) + c->gid = ucred->gid; + else + (void) get_process_gid(c->pid, &c->gid); +} + +static void client_context_read_basic(ClientContext *c) { + char *t; + + assert(c); + assert(pid_is_valid(c->pid)); + + if (get_process_comm(c->pid, &t) >= 0) + free_and_replace(c->comm, t); + + if (get_process_exe(c->pid, &t) >= 0) + free_and_replace(c->exe, t); + + if (get_process_cmdline(c->pid, SIZE_MAX, 0, &t) >= 0) + free_and_replace(c->cmdline, t); + + if (get_process_capeff(c->pid, &t) >= 0) + free_and_replace(c->capeff, t); +} + +static int client_context_read_label( + ClientContext *c, + const char *label, size_t label_size) { + + assert(c); + assert(pid_is_valid(c->pid)); + assert(label_size == 0 || label); + + if (label_size > 0) { + char *l; + + /* If we got an SELinux label passed in it counts. */ + + l = newdup_suffix0(char, label, label_size); + if (!l) + return -ENOMEM; + + free_and_replace(c->label, l); + c->label_size = label_size; + } +#if HAVE_SELINUX + else { + char *con; + + /* If we got no SELinux label passed in, let's try to acquire one */ + + if (getpidcon(c->pid, &con) >= 0) { + free_and_replace(c->label, con); + c->label_size = strlen(c->label); + } + } +#endif + + return 0; +} + +static int client_context_read_cgroup(Server *s, ClientContext *c, const char *unit_id) { + _cleanup_free_ char *t = NULL; + int r; + + assert(c); + + /* Try to acquire the current cgroup path */ + r = cg_pid_get_path_shifted(c->pid, s->cgroup_root, &t); + if (r < 0 || empty_or_root(t)) { + /* We use the unit ID passed in as fallback if we have nothing cached yet and cg_pid_get_path_shifted() + * failed or process is running in a root cgroup. Zombie processes are automatically migrated to root cgroup + * on cgroup v1 and we want to be able to map log messages from them too. */ + if (unit_id && !c->unit) { + c->unit = strdup(unit_id); + if (c->unit) + return 0; + } + + return r; + } + + /* Let's shortcut this if the cgroup path didn't change */ + if (streq_ptr(c->cgroup, t)) + return 0; + + free_and_replace(c->cgroup, t); + + (void) cg_path_get_session(c->cgroup, &t); + free_and_replace(c->session, t); + + if (cg_path_get_owner_uid(c->cgroup, &c->owner_uid) < 0) + c->owner_uid = UID_INVALID; + + (void) cg_path_get_unit(c->cgroup, &t); + free_and_replace(c->unit, t); + + (void) cg_path_get_user_unit(c->cgroup, &t); + free_and_replace(c->user_unit, t); + + (void) cg_path_get_slice(c->cgroup, &t); + free_and_replace(c->slice, t); + + (void) cg_path_get_user_slice(c->cgroup, &t); + free_and_replace(c->user_slice, t); + + return 0; +} + +static int client_context_read_invocation_id( + Server *s, + ClientContext *c) { + + _cleanup_free_ char *value = NULL; + const char *p; + int r; + + assert(s); + assert(c); + + /* Read the invocation ID of a unit off a unit. PID 1 stores it in a per-unit symlink in /run/systemd/units/ */ + + if (!c->unit) + return 0; + + p = strjoina("/run/systemd/units/invocation:", c->unit); + r = readlink_malloc(p, &value); + if (r < 0) + return r; + + return sd_id128_from_string(value, &c->invocation_id); +} + +static int client_context_read_log_level_max( + Server *s, + ClientContext *c) { + + _cleanup_free_ char *value = NULL; + const char *p; + int r, ll; + + if (!c->unit) + return 0; + + p = strjoina("/run/systemd/units/log-level-max:", c->unit); + r = readlink_malloc(p, &value); + if (r < 0) + return r; + + ll = log_level_from_string(value); + if (ll < 0) + return -EINVAL; + + c->log_level_max = ll; + return 0; +} + +static int client_context_read_extra_fields( + Server *s, + ClientContext *c) { + + size_t size = 0, n_iovec = 0, n_allocated = 0, left; + _cleanup_free_ struct iovec *iovec = NULL; + _cleanup_free_ void *data = NULL; + _cleanup_fclose_ FILE *f = NULL; + struct stat st; + const char *p; + uint8_t *q; + int r; + + if (!c->unit) + return 0; + + p = strjoina("/run/systemd/units/log-extra-fields:", c->unit); + + if (c->extra_fields_mtime != NSEC_INFINITY) { + if (stat(p, &st) < 0) { + if (errno == ENOENT) + return 0; + + return -errno; + } + + if (timespec_load_nsec(&st.st_mtim) == c->extra_fields_mtime) + return 0; + } + + f = fopen(p, "re"); + if (!f) { + if (errno == ENOENT) + return 0; + + return -errno; + } + + if (fstat(fileno(f), &st) < 0) /* The file might have been replaced since the stat() above, let's get a new + * one, that matches the stuff we are reading */ + return -errno; + + r = read_full_stream(f, (char**) &data, &size); + if (r < 0) + return r; + + q = data, left = size; + while (left > 0) { + uint8_t *field, *eq; + uint64_t v, n; + + if (left < sizeof(uint64_t)) + return -EBADMSG; + + v = unaligned_read_le64(q); + if (v < 2) + return -EBADMSG; + + n = sizeof(uint64_t) + v; + if (left < n) + return -EBADMSG; + + field = q + sizeof(uint64_t); + + eq = memchr(field, '=', v); + if (!eq) + return -EBADMSG; + + if (!journal_field_valid((const char *) field, eq - field, false)) + return -EBADMSG; + + if (!GREEDY_REALLOC(iovec, n_allocated, n_iovec+1)) + return -ENOMEM; + + iovec[n_iovec++] = IOVEC_MAKE(field, v); + + left -= n, q += n; + } + + free(c->extra_fields_iovec); + free(c->extra_fields_data); + + c->extra_fields_iovec = TAKE_PTR(iovec); + c->extra_fields_n_iovec = n_iovec; + c->extra_fields_data = TAKE_PTR(data); + c->extra_fields_mtime = timespec_load_nsec(&st.st_mtim); + + return 0; +} + +static int client_context_read_log_ratelimit_interval(ClientContext *c) { + _cleanup_free_ char *value = NULL; + const char *p; + int r; + + assert(c); + + if (!c->unit) + return 0; + + p = strjoina("/run/systemd/units/log-rate-limit-interval:", c->unit); + r = readlink_malloc(p, &value); + if (r < 0) + return r; + + return safe_atou64(value, &c->log_ratelimit_interval); +} + +static int client_context_read_log_ratelimit_burst(ClientContext *c) { + _cleanup_free_ char *value = NULL; + const char *p; + int r; + + assert(c); + + if (!c->unit) + return 0; + + p = strjoina("/run/systemd/units/log-rate-limit-burst:", c->unit); + r = readlink_malloc(p, &value); + if (r < 0) + return r; + + return safe_atou(value, &c->log_ratelimit_burst); +} + +static void client_context_really_refresh( + Server *s, + ClientContext *c, + const struct ucred *ucred, + const char *label, size_t label_size, + const char *unit_id, + usec_t timestamp) { + + assert(s); + assert(c); + assert(pid_is_valid(c->pid)); + + if (timestamp == USEC_INFINITY) + timestamp = now(CLOCK_MONOTONIC); + + client_context_read_uid_gid(c, ucred); + client_context_read_basic(c); + (void) client_context_read_label(c, label, label_size); + + (void) audit_session_from_pid(c->pid, &c->auditid); + (void) audit_loginuid_from_pid(c->pid, &c->loginuid); + + (void) client_context_read_cgroup(s, c, unit_id); + (void) client_context_read_invocation_id(s, c); + (void) client_context_read_log_level_max(s, c); + (void) client_context_read_extra_fields(s, c); + (void) client_context_read_log_ratelimit_interval(c); + (void) client_context_read_log_ratelimit_burst(c); + + c->timestamp = timestamp; + + if (c->in_lru) { + assert(c->n_ref == 0); + assert_se(prioq_reshuffle(s->client_contexts_lru, c, &c->lru_index) >= 0); + } +} + +void client_context_maybe_refresh( + Server *s, + ClientContext *c, + const struct ucred *ucred, + const char *label, size_t label_size, + const char *unit_id, + usec_t timestamp) { + + assert(s); + assert(c); + + if (timestamp == USEC_INFINITY) + timestamp = now(CLOCK_MONOTONIC); + + /* No cached data so far? Let's fill it up */ + if (c->timestamp == USEC_INFINITY) + goto refresh; + + /* If the data isn't pinned and if the cashed data is older than the upper limit, we flush it out + * entirely. This follows the logic that as long as an entry is pinned the PID reuse is unlikely. */ + if (c->n_ref == 0 && c->timestamp + MAX_USEC < timestamp) { + client_context_reset(s, c); + goto refresh; + } + + /* If the data is older than the lower limit, we refresh, but keep the old data for all we can't update */ + if (c->timestamp + REFRESH_USEC < timestamp) + goto refresh; + + /* If the data passed along doesn't match the cached data we also do a refresh */ + if (ucred && uid_is_valid(ucred->uid) && c->uid != ucred->uid) + goto refresh; + + if (ucred && gid_is_valid(ucred->gid) && c->gid != ucred->gid) + goto refresh; + + if (label_size > 0 && (label_size != c->label_size || memcmp(label, c->label, label_size) != 0)) + goto refresh; + + return; + +refresh: + client_context_really_refresh(s, c, ucred, label, label_size, unit_id, timestamp); +} + +static void client_context_try_shrink_to(Server *s, size_t limit) { + ClientContext *c; + usec_t t; + + assert(s); + + /* Flush any cache entries for PIDs that have already moved on. Don't do this + * too often, since it's a slow process. */ + t = now(CLOCK_MONOTONIC); + if (s->last_cache_pid_flush + MAX_USEC < t) { + unsigned n = prioq_size(s->client_contexts_lru), idx = 0; + + /* We do a number of iterations based on the initial size of the prioq. When we remove an + * item, a new item is moved into its places, and items to the right might be reshuffled. + */ + for (unsigned i = 0; i < n; i++) { + c = prioq_peek_by_index(s->client_contexts_lru, idx); + + assert(c->n_ref == 0); + + if (!pid_is_unwaited(c->pid)) + client_context_free(s, c); + else + idx ++; + } + + s->last_cache_pid_flush = t; + } + + /* Bring the number of cache entries below the indicated limit, so that we can create a new entry without + * breaching the limit. Note that we only flush out entries that aren't pinned here. This means the number of + * cache entries may very well grow beyond the limit, if all entries stored remain pinned. */ + + while (hashmap_size(s->client_contexts) > limit) { + c = prioq_pop(s->client_contexts_lru); + if (!c) + break; /* All remaining entries are pinned, give up */ + + assert(c->in_lru); + assert(c->n_ref == 0); + + c->in_lru = false; + + client_context_free(s, c); + } +} + +void client_context_flush_all(Server *s) { + assert(s); + + /* Flush out all remaining entries. This assumes all references are already dropped. */ + + s->my_context = client_context_release(s, s->my_context); + s->pid1_context = client_context_release(s, s->pid1_context); + + client_context_try_shrink_to(s, 0); + + assert(prioq_size(s->client_contexts_lru) == 0); + assert(hashmap_size(s->client_contexts) == 0); + + s->client_contexts_lru = prioq_free(s->client_contexts_lru); + s->client_contexts = hashmap_free(s->client_contexts); +} + +static int client_context_get_internal( + Server *s, + pid_t pid, + const struct ucred *ucred, + const char *label, size_t label_len, + const char *unit_id, + bool add_ref, + ClientContext **ret) { + + ClientContext *c; + int r; + + assert(s); + assert(ret); + + if (!pid_is_valid(pid)) + return -EINVAL; + + c = hashmap_get(s->client_contexts, PID_TO_PTR(pid)); + if (c) { + + if (add_ref) { + if (c->in_lru) { + /* The entry wasn't pinned so far, let's remove it from the LRU list then */ + assert(c->n_ref == 0); + assert_se(prioq_remove(s->client_contexts_lru, c, &c->lru_index) >= 0); + c->in_lru = false; + } + + c->n_ref++; + } + + client_context_maybe_refresh(s, c, ucred, label, label_len, unit_id, USEC_INFINITY); + + *ret = c; + return 0; + } + + client_context_try_shrink_to(s, cache_max()-1); + + r = client_context_new(s, pid, &c); + if (r < 0) + return r; + + if (add_ref) + c->n_ref++; + else { + r = prioq_put(s->client_contexts_lru, c, &c->lru_index); + if (r < 0) { + client_context_free(s, c); + return r; + } + + c->in_lru = true; + } + + client_context_really_refresh(s, c, ucred, label, label_len, unit_id, USEC_INFINITY); + + *ret = c; + return 0; +} + +int client_context_get( + Server *s, + pid_t pid, + const struct ucred *ucred, + const char *label, size_t label_len, + const char *unit_id, + ClientContext **ret) { + + return client_context_get_internal(s, pid, ucred, label, label_len, unit_id, false, ret); +} + +int client_context_acquire( + Server *s, + pid_t pid, + const struct ucred *ucred, + const char *label, size_t label_len, + const char *unit_id, + ClientContext **ret) { + + return client_context_get_internal(s, pid, ucred, label, label_len, unit_id, true, ret); +}; + +ClientContext *client_context_release(Server *s, ClientContext *c) { + assert(s); + + if (!c) + return NULL; + + assert(c->n_ref > 0); + assert(!c->in_lru); + + c->n_ref--; + if (c->n_ref > 0) + return NULL; + + /* The entry is not pinned anymore, let's add it to the LRU prioq if we can. If we can't we'll drop it + * right-away */ + + if (prioq_put(s->client_contexts_lru, c, &c->lru_index) < 0) + client_context_free(s, c); + else + c->in_lru = true; + + return NULL; +} + +void client_context_acquire_default(Server *s) { + int r; + + assert(s); + + /* Ensure that our own and PID1's contexts are always pinned. Our own context is particularly useful to + * generate driver messages. */ + + if (!s->my_context) { + struct ucred ucred = { + .pid = getpid_cached(), + .uid = getuid(), + .gid = getgid(), + }; + + r = client_context_acquire(s, ucred.pid, &ucred, NULL, 0, NULL, &s->my_context); + if (r < 0) + log_warning_errno(r, "Failed to acquire our own context, ignoring: %m"); + } + + if (!s->pid1_context) { + + r = client_context_acquire(s, 1, NULL, NULL, 0, NULL, &s->pid1_context); + if (r < 0) + log_warning_errno(r, "Failed to acquire PID1's context, ignoring: %m"); + + } +} diff --git a/src/journal/journald-context.h b/src/journal/journald-context.h new file mode 100644 index 00000000..91f0302b --- /dev/null +++ b/src/journal/journald-context.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "sd-id128.h" + +#include "time-util.h" + +typedef struct ClientContext ClientContext; + +#include "journald-server.h" + +struct ClientContext { + unsigned n_ref; + unsigned lru_index; + usec_t timestamp; + bool in_lru; + + pid_t pid; + uid_t uid; + gid_t gid; + + char *comm; + char *exe; + char *cmdline; + char *capeff; + + uint32_t auditid; + uid_t loginuid; + + char *cgroup; + char *session; + uid_t owner_uid; + + char *unit; + char *user_unit; + + char *slice; + char *user_slice; + + sd_id128_t invocation_id; + + char *label; + size_t label_size; + + int log_level_max; + + struct iovec *extra_fields_iovec; + size_t extra_fields_n_iovec; + void *extra_fields_data; + nsec_t extra_fields_mtime; + + usec_t log_ratelimit_interval; + unsigned log_ratelimit_burst; +}; + +int client_context_get( + Server *s, + pid_t pid, + const struct ucred *ucred, + const char *label, size_t label_len, + const char *unit_id, + ClientContext **ret); + +int client_context_acquire( + Server *s, + pid_t pid, + const struct ucred *ucred, + const char *label, size_t label_len, + const char *unit_id, + ClientContext **ret); + +ClientContext* client_context_release(Server *s, ClientContext *c); + +void client_context_maybe_refresh( + Server *s, + ClientContext *c, + const struct ucred *ucred, + const char *label, size_t label_size, + const char *unit_id, + usec_t tstamp); + +void client_context_acquire_default(Server *s); +void client_context_flush_all(Server *s); + +static inline size_t client_context_extra_fields_n_iovec(const ClientContext *c) { + return c ? c->extra_fields_n_iovec : 0; +} + +static inline bool client_context_test_priority(const ClientContext *c, int priority) { + if (!c) + return true; + + if (c->log_level_max < 0) + return true; + + return LOG_PRI(priority) <= c->log_level_max; +} diff --git a/src/journal/journald-gperf.gperf b/src/journal/journald-gperf.gperf new file mode 100644 index 00000000..0774444e --- /dev/null +++ b/src/journal/journald-gperf.gperf @@ -0,0 +1,51 @@ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif +#include +#include +#include "conf-parser.h" +#include "journald-server.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name journald_gperf_hash +%define lookup-function-name journald_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +Journal.Storage, config_parse_storage, 0, offsetof(Server, storage) +Journal.Compress, config_parse_compress, 0, offsetof(Server, compress) +Journal.Seal, config_parse_bool, 0, offsetof(Server, seal) +Journal.ReadKMsg, config_parse_bool, 0, offsetof(Server, read_kmsg) +Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec) +# The following is a legacy name for compatibility +Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, ratelimit_interval) +Journal.RateLimitIntervalSec,config_parse_sec, 0, offsetof(Server, ratelimit_interval) +Journal.RateLimitBurst, config_parse_unsigned, 0, offsetof(Server, ratelimit_burst) +Journal.SystemMaxUse, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.max_use) +Journal.SystemMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.max_size) +Journal.SystemKeepFree, config_parse_iec_uint64, 0, offsetof(Server, system_storage.metrics.keep_free) +Journal.SystemMaxFiles, config_parse_uint64, 0, offsetof(Server, system_storage.metrics.n_max_files) +Journal.RuntimeMaxUse, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.max_use) +Journal.RuntimeMaxFileSize, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.max_size) +Journal.RuntimeKeepFree, config_parse_iec_uint64, 0, offsetof(Server, runtime_storage.metrics.keep_free) +Journal.RuntimeMaxFiles, config_parse_uint64, 0, offsetof(Server, runtime_storage.metrics.n_max_files) +Journal.MaxRetentionSec, config_parse_sec, 0, offsetof(Server, max_retention_usec) +Journal.MaxFileSec, config_parse_sec, 0, offsetof(Server, max_file_usec) +Journal.ForwardToSyslog, config_parse_bool, 0, offsetof(Server, forward_to_syslog) +Journal.ForwardToKMsg, config_parse_bool, 0, offsetof(Server, forward_to_kmsg) +Journal.ForwardToConsole, config_parse_bool, 0, offsetof(Server, forward_to_console) +Journal.ForwardToWall, config_parse_bool, 0, offsetof(Server, forward_to_wall) +Journal.TTYPath, config_parse_path, 0, offsetof(Server, tty_path) +Journal.MaxLevelStore, config_parse_log_level, 0, offsetof(Server, max_level_store) +Journal.MaxLevelSyslog, config_parse_log_level, 0, offsetof(Server, max_level_syslog) +Journal.MaxLevelKMsg, config_parse_log_level, 0, offsetof(Server, max_level_kmsg) +Journal.MaxLevelConsole, config_parse_log_level, 0, offsetof(Server, max_level_console) +Journal.MaxLevelWall, config_parse_log_level, 0, offsetof(Server, max_level_wall) +Journal.SplitMode, config_parse_split_mode, 0, offsetof(Server, split_mode) +Journal.LineMax, config_parse_line_max, 0, offsetof(Server, line_max) diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c new file mode 100644 index 00000000..36629875 --- /dev/null +++ b/src/journal/journald-kmsg.c @@ -0,0 +1,450 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-device.h" +#include "sd-messages.h" + +#include "alloc-util.h" +#include "device-util.h" +#include "escape.h" +#include "fd-util.h" +#include "format-util.h" +#include "io-util.h" +#include "journald-kmsg.h" +#include "journald-server.h" +#include "journald-syslog.h" +#include "parse-util.h" +#include "process-util.h" +#include "stdio-util.h" +#include "string-util.h" + +void server_forward_kmsg( + Server *s, + int priority, + const char *identifier, + const char *message, + const struct ucred *ucred) { + + _cleanup_free_ char *ident_buf = NULL; + struct iovec iovec[5]; + char header_priority[DECIMAL_STR_MAX(priority) + 3], + header_pid[STRLEN("[]: ") + DECIMAL_STR_MAX(pid_t) + 1]; + int n = 0; + + assert(s); + assert(priority >= 0); + assert(priority <= 999); + assert(message); + + if (_unlikely_(LOG_PRI(priority) > s->max_level_kmsg)) + return; + + if (_unlikely_(s->dev_kmsg_fd < 0)) + return; + + /* Never allow messages with kernel facility to be written to + * kmsg, regardless where the data comes from. */ + priority = syslog_fixup_facility(priority); + + /* First: priority field */ + xsprintf(header_priority, "<%i>", priority); + iovec[n++] = IOVEC_MAKE_STRING(header_priority); + + /* Second: identifier and PID */ + if (ucred) { + if (!identifier) { + get_process_comm(ucred->pid, &ident_buf); + identifier = ident_buf; + } + + xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid); + + if (identifier) + iovec[n++] = IOVEC_MAKE_STRING(identifier); + + iovec[n++] = IOVEC_MAKE_STRING(header_pid); + } else if (identifier) { + iovec[n++] = IOVEC_MAKE_STRING(identifier); + iovec[n++] = IOVEC_MAKE_STRING(": "); + } + + /* Fourth: message */ + iovec[n++] = IOVEC_MAKE_STRING(message); + iovec[n++] = IOVEC_MAKE_STRING("\n"); + + if (writev(s->dev_kmsg_fd, iovec, n) < 0) + log_debug_errno(errno, "Failed to write to /dev/kmsg for logging: %m"); +} + +static bool is_us(const char *identifier, const char *pid) { + pid_t pid_num; + + if (!identifier || !pid) + return false; + + if (parse_pid(pid, &pid_num) < 0) + return false; + + return pid_num == getpid_cached() && + streq(identifier, program_invocation_short_name); +} + +void dev_kmsg_record(Server *s, char *p, size_t l) { + + _cleanup_free_ char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL, *identifier = NULL, *pid = NULL; + struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS]; + char *kernel_device = NULL; + unsigned long long usec; + size_t n = 0, z = 0, j; + int priority, r; + char *e, *f, *k; + uint64_t serial; + size_t pl; + + assert(s); + assert(p); + + if (l <= 0) + return; + + e = memchr(p, ',', l); + if (!e) + return; + *e = 0; + + r = safe_atoi(p, &priority); + if (r < 0 || priority < 0 || priority > 999) + return; + + if (s->forward_to_kmsg && LOG_FAC(priority) != LOG_KERN) + return; + + l -= (e - p) + 1; + p = e + 1; + e = memchr(p, ',', l); + if (!e) + return; + *e = 0; + + r = safe_atou64(p, &serial); + if (r < 0) + return; + + if (s->kernel_seqnum) { + /* We already read this one? */ + if (serial < *s->kernel_seqnum) + return; + + /* Did we lose any? */ + if (serial > *s->kernel_seqnum) + server_driver_message(s, 0, + "MESSAGE_ID=" SD_MESSAGE_JOURNAL_MISSED_STR, + LOG_MESSAGE("Missed %"PRIu64" kernel messages", + serial - *s->kernel_seqnum), + NULL); + + /* Make sure we never read this one again. Note that + * we always store the next message serial we expect + * here, simply because this makes handling the first + * message with serial 0 easy. */ + *s->kernel_seqnum = serial + 1; + } + + l -= (e - p) + 1; + p = e + 1; + f = memchr(p, ';', l); + if (!f) + return; + /* Kernel 3.6 has the flags field, kernel 3.5 lacks that */ + e = memchr(p, ',', l); + if (!e || f < e) + e = f; + *e = 0; + + r = safe_atollu(p, &usec); + if (r < 0) + return; + + l -= (f - p) + 1; + p = f + 1; + e = memchr(p, '\n', l); + if (!e) + return; + *e = 0; + + pl = e - p; + l -= (e - p) + 1; + k = e + 1; + + for (j = 0; l > 0 && j < N_IOVEC_KERNEL_FIELDS; j++) { + char *m; + /* Metadata fields attached */ + + if (*k != ' ') + break; + + k++, l--; + + e = memchr(k, '\n', l); + if (!e) + goto finish; + + *e = 0; + + if (cunescape_length_with_prefix(k, e - k, "_KERNEL_", UNESCAPE_RELAX, &m) < 0) + break; + + if (startswith(m, "_KERNEL_DEVICE=")) + kernel_device = m + 15; + + iovec[n++] = IOVEC_MAKE_STRING(m); + z++; + + l -= (e - k) + 1; + k = e + 1; + } + + if (kernel_device) { + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + + if (sd_device_new_from_device_id(&d, kernel_device) >= 0) { + const char *g; + char *b; + + if (sd_device_get_devname(d, &g) >= 0) { + b = strjoin("_UDEV_DEVNODE=", g); + if (b) { + iovec[n++] = IOVEC_MAKE_STRING(b); + z++; + } + } + + if (sd_device_get_sysname(d, &g) >= 0) { + b = strjoin("_UDEV_SYSNAME=", g); + if (b) { + iovec[n++] = IOVEC_MAKE_STRING(b); + z++; + } + } + + j = 0; + FOREACH_DEVICE_DEVLINK(d, g) { + + if (j >= N_IOVEC_UDEV_FIELDS) + break; + + b = strjoin("_UDEV_DEVLINK=", g); + if (b) { + iovec[n++] = IOVEC_MAKE_STRING(b); + z++; + } + + j++; + } + } + } + + if (asprintf(&source_time, "_SOURCE_MONOTONIC_TIMESTAMP=%llu", usec) >= 0) + iovec[n++] = IOVEC_MAKE_STRING(source_time); + + iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=kernel"); + + if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0) + iovec[n++] = IOVEC_MAKE_STRING(syslog_priority); + + if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0) + iovec[n++] = IOVEC_MAKE_STRING(syslog_facility); + + if (LOG_FAC(priority) == LOG_KERN) + iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=kernel"); + else { + pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid); + + /* Avoid any messages we generated ourselves via + * log_info() and friends. */ + if (is_us(identifier, pid)) + goto finish; + + if (identifier) { + syslog_identifier = strjoin("SYSLOG_IDENTIFIER=", identifier); + if (syslog_identifier) + iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier); + } + + if (pid) { + syslog_pid = strjoin("SYSLOG_PID=", pid); + if (syslog_pid) + iovec[n++] = IOVEC_MAKE_STRING(syslog_pid); + } + } + + if (cunescape_length_with_prefix(p, pl, "MESSAGE=", UNESCAPE_RELAX, &message) >= 0) + iovec[n++] = IOVEC_MAKE_STRING(message); + + server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, priority, 0); + +finish: + for (j = 0; j < z; j++) + free(iovec[j].iov_base); +} + +static int server_read_dev_kmsg(Server *s) { + char buffer[8192+1]; /* the kernel-side limit per record is 8K currently */ + ssize_t l; + + assert(s); + assert(s->dev_kmsg_fd >= 0); + + l = read(s->dev_kmsg_fd, buffer, sizeof(buffer) - 1); + if (l == 0) + return 0; + if (l < 0) { + /* Old kernels who don't allow reading from /dev/kmsg + * return EINVAL when we try. So handle this cleanly, + * but don' try to ever read from it again. */ + if (errno == EINVAL) { + s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source); + return 0; + } + + if (IN_SET(errno, EAGAIN, EINTR, EPIPE)) + return 0; + + return log_error_errno(errno, "Failed to read from kernel: %m"); + } + + dev_kmsg_record(s, buffer, l); + return 1; +} + +int server_flush_dev_kmsg(Server *s) { + int r; + + assert(s); + + if (s->dev_kmsg_fd < 0) + return 0; + + if (!s->dev_kmsg_readable) + return 0; + + log_debug("Flushing /dev/kmsg..."); + + for (;;) { + r = server_read_dev_kmsg(s); + if (r < 0) + return r; + + if (r == 0) + break; + } + + return 0; +} + +static int dispatch_dev_kmsg(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + Server *s = userdata; + + assert(es); + assert(fd == s->dev_kmsg_fd); + assert(s); + + if (revents & EPOLLERR) + log_warning("/dev/kmsg buffer overrun, some messages lost."); + + if (!(revents & EPOLLIN)) + log_error("Got invalid event from epoll for /dev/kmsg: %"PRIx32, revents); + + return server_read_dev_kmsg(s); +} + +int server_open_dev_kmsg(Server *s) { + mode_t mode; + int r; + + assert(s); + + if (s->read_kmsg) + mode = O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY; + else + mode = O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY; + + s->dev_kmsg_fd = open("/dev/kmsg", mode); + if (s->dev_kmsg_fd < 0) { + log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, + "Failed to open /dev/kmsg, ignoring: %m"); + return 0; + } + + if (!s->read_kmsg) + return 0; + + r = sd_event_add_io(s->event, &s->dev_kmsg_event_source, s->dev_kmsg_fd, EPOLLIN, dispatch_dev_kmsg, s); + if (r < 0) { + + /* This will fail with EPERM on older kernels where + * /dev/kmsg is not readable. */ + if (r == -EPERM) { + r = 0; + goto fail; + } + + log_error_errno(r, "Failed to add /dev/kmsg fd to event loop: %m"); + goto fail; + } + + r = sd_event_source_set_priority(s->dev_kmsg_event_source, SD_EVENT_PRIORITY_IMPORTANT+10); + if (r < 0) { + log_error_errno(r, "Failed to adjust priority of kmsg event source: %m"); + goto fail; + } + + s->dev_kmsg_readable = true; + + return 0; + +fail: + s->dev_kmsg_event_source = sd_event_source_unref(s->dev_kmsg_event_source); + s->dev_kmsg_fd = safe_close(s->dev_kmsg_fd); + + return r; +} + +int server_open_kernel_seqnum(Server *s) { + _cleanup_close_ int fd; + uint64_t *p; + int r; + + assert(s); + + /* We store the seqnum we last read in an mmaped file. That + * way we can just use it like a variable, but it is + * persistent and automatically flushed at reboot. */ + + fd = open("/run/systemd/journal/kernel-seqnum", O_RDWR|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); + if (fd < 0) { + log_error_errno(errno, "Failed to open /run/systemd/journal/kernel-seqnum, ignoring: %m"); + return 0; + } + + r = posix_fallocate(fd, 0, sizeof(uint64_t)); + if (r != 0) { + log_error_errno(r, "Failed to allocate sequential number file, ignoring: %m"); + return 0; + } + + p = mmap(NULL, sizeof(uint64_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (p == MAP_FAILED) { + log_error_errno(errno, "Failed to map sequential number file, ignoring: %m"); + return 0; + } + + s->kernel_seqnum = p; + + return 0; +} diff --git a/src/journal/journald-kmsg.h b/src/journal/journald-kmsg.h new file mode 100644 index 00000000..2326bc8c --- /dev/null +++ b/src/journal/journald-kmsg.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "journald-server.h" + +int server_open_dev_kmsg(Server *s); +int server_flush_dev_kmsg(Server *s); + +void server_forward_kmsg(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred); + +int server_open_kernel_seqnum(Server *s); + +void dev_kmsg_record(Server *s, char *p, size_t l); diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c new file mode 100644 index 00000000..73a96da9 --- /dev/null +++ b/src/journal/journald-native.c @@ -0,0 +1,503 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "io-util.h" +#include "journal-importer.h" +#include "journal-util.h" +#include "journald-console.h" +#include "journald-kmsg.h" +#include "journald-native.h" +#include "journald-server.h" +#include "journald-syslog.h" +#include "journald-wall.h" +#include "memfd-util.h" +#include "memory-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "selinux-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" +#include "unaligned.h" + +static bool allow_object_pid(const struct ucred *ucred) { + return ucred && ucred->uid == 0; +} + +static void server_process_entry_meta( + const char *p, size_t l, + const struct ucred *ucred, + int *priority, + char **identifier, + char **message, + pid_t *object_pid) { + + /* We need to determine the priority of this entry for the rate limiting logic */ + + if (l == 10 && + startswith(p, "PRIORITY=") && + p[9] >= '0' && p[9] <= '9') + *priority = (*priority & LOG_FACMASK) | (p[9] - '0'); + + else if (l == 17 && + startswith(p, "SYSLOG_FACILITY=") && + p[16] >= '0' && p[16] <= '9') + *priority = (*priority & LOG_PRIMASK) | ((p[16] - '0') << 3); + + else if (l == 18 && + startswith(p, "SYSLOG_FACILITY=") && + p[16] >= '0' && p[16] <= '9' && + p[17] >= '0' && p[17] <= '9') + *priority = (*priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3); + + else if (l >= 19 && + startswith(p, "SYSLOG_IDENTIFIER=")) { + char *t; + + t = memdup_suffix0(p + 18, l - 18); + if (t) { + free(*identifier); + *identifier = t; + } + + } else if (l >= 8 && + startswith(p, "MESSAGE=")) { + char *t; + + t = memdup_suffix0(p + 8, l - 8); + if (t) { + free(*message); + *message = t; + } + + } else if (l > STRLEN("OBJECT_PID=") && + l < STRLEN("OBJECT_PID=") + DECIMAL_STR_MAX(pid_t) && + startswith(p, "OBJECT_PID=") && + allow_object_pid(ucred)) { + char buf[DECIMAL_STR_MAX(pid_t)]; + memcpy(buf, p + STRLEN("OBJECT_PID="), + l - STRLEN("OBJECT_PID=")); + buf[l-STRLEN("OBJECT_PID=")] = '\0'; + + (void) parse_pid(buf, object_pid); + } +} + +static int server_process_entry( + Server *s, + const void *buffer, size_t *remaining, + ClientContext *context, + const struct ucred *ucred, + const struct timeval *tv, + const char *label, size_t label_len) { + + /* Process a single entry from a native message. Returns 0 if nothing special happened and the message + * processing should continue, and a negative or positive value otherwise. + * + * Note that *remaining is altered on both success and failure. */ + + size_t n = 0, j, tn = (size_t) -1, m = 0, entry_size = 0; + char *identifier = NULL, *message = NULL; + struct iovec *iovec = NULL; + int priority = LOG_INFO; + pid_t object_pid = 0; + const char *p; + int r = 1; + + p = buffer; + + while (*remaining > 0) { + const char *e, *q; + + e = memchr(p, '\n', *remaining); + + if (!e) { + /* Trailing noise, let's ignore it, and flush what we collected */ + log_debug("Received message with trailing noise, ignoring."); + break; /* finish processing of the message */ + } + + if (e == p) { + /* Entry separator */ + *remaining -= 1; + break; + } + + if (IN_SET(*p, '.', '#')) { + /* Ignore control commands for now, and comments too. */ + *remaining -= (e - p) + 1; + p = e + 1; + continue; + } + + /* A property follows */ + if (n > ENTRY_FIELD_COUNT_MAX) { + log_debug("Received an entry that has more than " STRINGIFY(ENTRY_FIELD_COUNT_MAX) " fields, ignoring entry."); + goto finish; + } + + /* n existing properties, 1 new, +1 for _TRANSPORT */ + if (!GREEDY_REALLOC(iovec, m, + n + 2 + + N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS + + client_context_extra_fields_n_iovec(context))) { + r = log_oom(); + goto finish; + } + + q = memchr(p, '=', e - p); + if (q) { + if (journal_field_valid(p, q - p, false)) { + size_t l; + + l = e - p; + if (l > DATA_SIZE_MAX) { + log_debug("Received text block of %zu bytes is too large, ignoring entry.", l); + goto finish; + } + + if (entry_size + l + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ + log_debug("Entry is too big (%zu bytes after processing %zu entries), ignoring entry.", + entry_size + l, n + 1); + goto finish; + } + + /* If the field name starts with an underscore, skip the variable, since that indicates + * a trusted field */ + iovec[n++] = IOVEC_MAKE((char*) p, l); + entry_size += l; + + server_process_entry_meta(p, l, ucred, + &priority, + &identifier, + &message, + &object_pid); + } + + *remaining -= (e - p) + 1; + p = e + 1; + continue; + } else { + uint64_t l, total; + char *k; + + if (*remaining < e - p + 1 + sizeof(uint64_t) + 1) { + log_debug("Failed to parse message, ignoring."); + break; + } + + l = unaligned_read_le64(e + 1); + if (l > DATA_SIZE_MAX) { + log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring entry.", l); + goto finish; + } + + total = (e - p) + 1 + l; + if (entry_size + total + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ + log_debug("Entry is too big (%"PRIu64"bytes after processing %zu fields), ignoring.", + entry_size + total, n + 1); + goto finish; + } + + if ((uint64_t) *remaining < e - p + 1 + sizeof(uint64_t) + l + 1 || + e[1+sizeof(uint64_t)+l] != '\n') { + log_debug("Failed to parse message, ignoring."); + break; + } + + k = malloc(total); + if (!k) { + log_oom(); + break; + } + + memcpy(k, p, e - p); + k[e - p] = '='; + memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l); + + if (journal_field_valid(p, e - p, false)) { + iovec[n] = IOVEC_MAKE(k, (e - p) + 1 + l); + entry_size += iovec[n].iov_len; + n++; + + server_process_entry_meta(k, (e - p) + 1 + l, ucred, + &priority, + &identifier, + &message, + &object_pid); + } else + free(k); + + *remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1; + p = e + 1 + sizeof(uint64_t) + l + 1; + } + } + + if (n <= 0) + goto finish; + + tn = n++; + iovec[tn] = IOVEC_MAKE_STRING("_TRANSPORT=journal"); + entry_size += STRLEN("_TRANSPORT=journal"); + + if (entry_size + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ + log_debug("Entry is too big with %zu properties and %zu bytes, ignoring.", n, entry_size); + goto finish; + } + + r = 0; /* Success, we read the message. */ + + if (!client_context_test_priority(context, priority)) + goto finish; + + if (message) { + if (s->forward_to_syslog) + server_forward_syslog(s, syslog_fixup_facility(priority), identifier, message, ucred, tv); + + if (s->forward_to_kmsg) + server_forward_kmsg(s, priority, identifier, message, ucred); + + if (s->forward_to_console) + server_forward_console(s, priority, identifier, message, ucred); + + if (s->forward_to_wall) + server_forward_wall(s, priority, identifier, message, ucred); + } + + server_dispatch_message(s, iovec, n, m, context, tv, priority, object_pid); + +finish: + for (j = 0; j < n; j++) { + if (j == tn) + continue; + + if (iovec[j].iov_base < buffer || + (const char*) iovec[j].iov_base >= p + *remaining) + free(iovec[j].iov_base); + } + + free(iovec); + free(identifier); + free(message); + + return r; +} + +void server_process_native_message( + Server *s, + const char *buffer, size_t buffer_size, + const struct ucred *ucred, + const struct timeval *tv, + const char *label, size_t label_len) { + + size_t remaining = buffer_size; + ClientContext *context = NULL; + int r; + + assert(s); + assert(buffer || buffer_size == 0); + + if (ucred && pid_is_valid(ucred->pid)) { + r = client_context_get(s, ucred->pid, ucred, label, label_len, NULL, &context); + if (r < 0) + log_warning_errno(r, "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", ucred->pid); + } + + do { + r = server_process_entry(s, + (const uint8_t*) buffer + (buffer_size - remaining), &remaining, + context, ucred, tv, label, label_len); + } while (r == 0); +} + +void server_process_native_file( + Server *s, + int fd, + const struct ucred *ucred, + const struct timeval *tv, + const char *label, size_t label_len) { + + struct stat st; + bool sealed; + int r; + + /* Data is in the passed fd, probably it didn't fit in a datagram. */ + + assert(s); + assert(fd >= 0); + + /* If it's a memfd, check if it is sealed. If so, we can just + * mmap it and use it, and do not need to copy the data out. */ + sealed = memfd_get_sealed(fd) > 0; + + if (!sealed && (!ucred || ucred->uid != 0)) { + _cleanup_free_ char *k = NULL; + const char *e; + + /* If this is not a sealed memfd, and the peer is unknown or + * unprivileged, then verify the path. */ + + r = fd_get_path(fd, &k); + if (r < 0) { + log_error_errno(r, "readlink(/proc/self/fd/%i) failed: %m", fd); + return; + } + + e = PATH_STARTSWITH_SET(k, "/dev/shm/", "/tmp/", "/var/tmp/"); + if (!e) { + log_error("Received file outside of allowed directories. Refusing."); + return; + } + + if (!filename_is_valid(e)) { + log_error("Received file in subdirectory of allowed directories. Refusing."); + return; + } + } + + if (fstat(fd, &st) < 0) { + log_error_errno(errno, "Failed to stat passed file, ignoring: %m"); + return; + } + + if (!S_ISREG(st.st_mode)) { + log_error("File passed is not regular. Ignoring."); + return; + } + + if (st.st_size <= 0) + return; + + /* When !sealed, set a lower memory limit. We have to read the file, + * effectively doubling memory use. */ + if (st.st_size > ENTRY_SIZE_MAX / (sealed ? 1 : 2)) { + log_error("File passed too large (%"PRIu64" bytes). Ignoring.", (uint64_t) st.st_size); + return; + } + + if (sealed) { + void *p; + size_t ps; + + /* The file is sealed, we can just map it and use it. */ + + ps = PAGE_ALIGN(st.st_size); + p = mmap(NULL, ps, PROT_READ, MAP_PRIVATE, fd, 0); + if (p == MAP_FAILED) { + log_error_errno(errno, "Failed to map memfd, ignoring: %m"); + return; + } + + server_process_native_message(s, p, st.st_size, ucred, tv, label, label_len); + assert_se(munmap(p, ps) >= 0); + } else { + _cleanup_free_ void *p = NULL; + struct statvfs vfs; + ssize_t n; + + if (fstatvfs(fd, &vfs) < 0) { + log_error_errno(errno, "Failed to stat file system of passed file, not processing it: %m"); + return; + } + + /* Refuse operating on file systems that have + * mandatory locking enabled, see: + * + * https://github.com/systemd/systemd/issues/1822 + */ + if (vfs.f_flag & ST_MANDLOCK) { + log_error("Received file descriptor from file system with mandatory locking enabled, not processing it."); + return; + } + + /* Make the fd non-blocking. On regular files this has + * the effect of bypassing mandatory locking. Of + * course, this should normally not be necessary given + * the check above, but let's better be safe than + * sorry, after all NFS is pretty confusing regarding + * file system flags, and we better don't trust it, + * and so is SMB. */ + r = fd_nonblock(fd, true); + if (r < 0) { + log_error_errno(r, "Failed to make fd non-blocking, not processing it: %m"); + return; + } + + /* The file is not sealed, we can't map the file here, since + * clients might then truncate it and trigger a SIGBUS for + * us. So let's stupidly read it. */ + + p = malloc(st.st_size); + if (!p) { + log_oom(); + return; + } + + n = pread(fd, p, st.st_size, 0); + if (n < 0) + log_error_errno(errno, "Failed to read file, ignoring: %m"); + else if (n > 0) + server_process_native_message(s, p, n, ucred, tv, label, label_len); + } +} + +int server_open_native_socket(Server *s) { + + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/socket", + }; + int r; + + assert(s); + + if (s->native_fd < 0) { + s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s->native_fd < 0) + return log_error_errno(errno, "socket() failed: %m"); + + (void) sockaddr_un_unlink(&sa.un); + + r = bind(s->native_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); + + (void) chmod(sa.un.sun_path, 0666); + } else + (void) fd_nonblock(s->native_fd, true); + + r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return log_error_errno(r, "SO_PASSCRED failed: %m"); + +#if HAVE_SELINUX + if (mac_selinux_use()) { + r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_PASSSEC, true); + if (r < 0) + log_warning_errno(r, "SO_PASSSEC failed: %m"); + } +#endif + + r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, true); + if (r < 0) + return log_error_errno(r, "SO_TIMESTAMP failed: %m"); + + r = sd_event_add_io(s->event, &s->native_event_source, s->native_fd, EPOLLIN, server_process_datagram, s); + if (r < 0) + return log_error_errno(r, "Failed to add native server fd to event loop: %m"); + + r = sd_event_source_set_priority(s->native_event_source, SD_EVENT_PRIORITY_NORMAL+5); + if (r < 0) + return log_error_errno(r, "Failed to adjust native event source priority: %m"); + + return 0; +} diff --git a/src/journal/journald-native.h b/src/journal/journald-native.h new file mode 100644 index 00000000..2a33ef74 --- /dev/null +++ b/src/journal/journald-native.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "journald-server.h" + +void server_process_native_message( + Server *s, + const char *buffer, + size_t buffer_size, + const struct ucred *ucred, + const struct timeval *tv, + const char *label, + size_t label_len); + +void server_process_native_file( + Server *s, + int fd, + const struct ucred *ucred, + const struct timeval *tv, + const char *label, + size_t label_len); + +int server_open_native_socket(Server *s); diff --git a/src/journal/journald-rate-limit.c b/src/journal/journald-rate-limit.c new file mode 100644 index 00000000..af7196c6 --- /dev/null +++ b/src/journal/journald-rate-limit.c @@ -0,0 +1,254 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "hashmap.h" +#include "journald-rate-limit.h" +#include "list.h" +#include "random-util.h" +#include "string-util.h" +#include "time-util.h" + +#define POOLS_MAX 5 +#define BUCKETS_MAX 127 +#define GROUPS_MAX 2047 + +static const int priority_map[] = { + [LOG_EMERG] = 0, + [LOG_ALERT] = 0, + [LOG_CRIT] = 0, + [LOG_ERR] = 1, + [LOG_WARNING] = 2, + [LOG_NOTICE] = 3, + [LOG_INFO] = 3, + [LOG_DEBUG] = 4 +}; + +typedef struct JournalRateLimitPool JournalRateLimitPool; +typedef struct JournalRateLimitGroup JournalRateLimitGroup; + +struct JournalRateLimitPool { + usec_t begin; + unsigned num; + unsigned suppressed; +}; + +struct JournalRateLimitGroup { + JournalRateLimit *parent; + + char *id; + + /* Interval is stored to keep track of when the group expires */ + usec_t interval; + + JournalRateLimitPool pools[POOLS_MAX]; + uint64_t hash; + + LIST_FIELDS(JournalRateLimitGroup, bucket); + LIST_FIELDS(JournalRateLimitGroup, lru); +}; + +struct JournalRateLimit { + + JournalRateLimitGroup* buckets[BUCKETS_MAX]; + JournalRateLimitGroup *lru, *lru_tail; + + unsigned n_groups; + + uint8_t hash_key[16]; +}; + +JournalRateLimit *journal_ratelimit_new(void) { + JournalRateLimit *r; + + r = new0(JournalRateLimit, 1); + if (!r) + return NULL; + + random_bytes(r->hash_key, sizeof(r->hash_key)); + + return r; +} + +static void journal_ratelimit_group_free(JournalRateLimitGroup *g) { + assert(g); + + if (g->parent) { + assert(g->parent->n_groups > 0); + + if (g->parent->lru_tail == g) + g->parent->lru_tail = g->lru_prev; + + LIST_REMOVE(lru, g->parent->lru, g); + LIST_REMOVE(bucket, g->parent->buckets[g->hash % BUCKETS_MAX], g); + + g->parent->n_groups--; + } + + free(g->id); + free(g); +} + +void journal_ratelimit_free(JournalRateLimit *r) { + assert(r); + + while (r->lru) + journal_ratelimit_group_free(r->lru); + + free(r); +} + +_pure_ static bool journal_ratelimit_group_expired(JournalRateLimitGroup *g, usec_t ts) { + unsigned i; + + assert(g); + + for (i = 0; i < POOLS_MAX; i++) + if (g->pools[i].begin + g->interval >= ts) + return false; + + return true; +} + +static void journal_ratelimit_vacuum(JournalRateLimit *r, usec_t ts) { + assert(r); + + /* Makes room for at least one new item, but drop all + * expored items too. */ + + while (r->n_groups >= GROUPS_MAX || + (r->lru_tail && journal_ratelimit_group_expired(r->lru_tail, ts))) + journal_ratelimit_group_free(r->lru_tail); +} + +static JournalRateLimitGroup* journal_ratelimit_group_new(JournalRateLimit *r, const char *id, usec_t interval, usec_t ts) { + JournalRateLimitGroup *g; + + assert(r); + assert(id); + + g = new0(JournalRateLimitGroup, 1); + if (!g) + return NULL; + + g->id = strdup(id); + if (!g->id) + goto fail; + + g->hash = siphash24_string(g->id, r->hash_key); + + g->interval = interval; + + journal_ratelimit_vacuum(r, ts); + + LIST_PREPEND(bucket, r->buckets[g->hash % BUCKETS_MAX], g); + LIST_PREPEND(lru, r->lru, g); + if (!g->lru_next) + r->lru_tail = g; + r->n_groups++; + + g->parent = r; + return g; + +fail: + journal_ratelimit_group_free(g); + return NULL; +} + +static unsigned burst_modulate(unsigned burst, uint64_t available) { + unsigned k; + + /* Modulates the burst rate a bit with the amount of available + * disk space */ + + k = u64log2(available); + + /* 1MB */ + if (k <= 20) + return burst; + + burst = (burst * (k-16)) / 4; + + /* + * Example: + * + * <= 1MB = rate * 1 + * 16MB = rate * 2 + * 256MB = rate * 3 + * 4GB = rate * 4 + * 64GB = rate * 5 + * 1TB = rate * 6 + */ + + return burst; +} + +int journal_ratelimit_test(JournalRateLimit *r, const char *id, usec_t rl_interval, unsigned rl_burst, int priority, uint64_t available) { + uint64_t h; + JournalRateLimitGroup *g; + JournalRateLimitPool *p; + unsigned burst; + usec_t ts; + + assert(id); + + /* Returns: + * + * 0 → the log message shall be suppressed, + * 1 + n → the log message shall be permitted, and n messages were dropped from the peer before + * < 0 → error + */ + + if (!r) + return 1; + + ts = now(CLOCK_MONOTONIC); + + h = siphash24_string(id, r->hash_key); + g = r->buckets[h % BUCKETS_MAX]; + + LIST_FOREACH(bucket, g, g) + if (streq(g->id, id)) + break; + + if (!g) { + g = journal_ratelimit_group_new(r, id, rl_interval, ts); + if (!g) + return -ENOMEM; + } else + g->interval = rl_interval; + + if (rl_interval == 0 || rl_burst == 0) + return 1; + + burst = burst_modulate(rl_burst, available); + + p = &g->pools[priority_map[priority]]; + + if (p->begin <= 0) { + p->suppressed = 0; + p->num = 1; + p->begin = ts; + return 1; + } + + if (p->begin + rl_interval < ts) { + unsigned s; + + s = p->suppressed; + p->suppressed = 0; + p->num = 1; + p->begin = ts; + + return 1 + s; + } + + if (p->num < burst) { + p->num++; + return 1; + } + + p->suppressed++; + return 0; +} diff --git a/src/journal/journald-rate-limit.h b/src/journal/journald-rate-limit.h new file mode 100644 index 00000000..0fff8767 --- /dev/null +++ b/src/journal/journald-rate-limit.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "time-util.h" + +typedef struct JournalRateLimit JournalRateLimit; + +JournalRateLimit *journal_ratelimit_new(void); +void journal_ratelimit_free(JournalRateLimit *r); +int journal_ratelimit_test(JournalRateLimit *r, const char *id, usec_t rl_interval, unsigned rl_burst, int priority, uint64_t available); diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c new file mode 100644 index 00000000..f6caf0e2 --- /dev/null +++ b/src/journal/journald-server.c @@ -0,0 +1,2386 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if HAVE_SELINUX +#include +#endif +#include +#include +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-journal.h" +#include "sd-messages.h" + +#include "acl-util.h" +#include "alloc-util.h" +#include "audit-util.h" +#include "cgroup-util.h" +#include "conf-parser.h" +#include "dirent-util.h" +#include "extract-word.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "hostname-util.h" +#include "id128-util.h" +#include "io-util.h" +#include "journal-authenticate.h" +#include "journal-file.h" +#include "journal-internal.h" +#include "journal-vacuum.h" +#include "journald-audit.h" +#include "journald-context.h" +#include "journald-kmsg.h" +#include "journald-native.h" +#include "journald-rate-limit.h" +#include "journald-server.h" +#include "journald-stream.h" +#include "journald-syslog.h" +#include "log.h" +#include "missing_audit.h" +#include "mkdir.h" +#include "parse-util.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "rm-rf.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "syslog-util.h" +#include "user-util.h" + +#define USER_JOURNALS_MAX 1024 + +#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE) +#define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC) +#define DEFAULT_RATE_LIMIT_BURST 10000 +#define DEFAULT_MAX_FILE_USEC USEC_PER_MONTH + +#define RECHECK_SPACE_USEC (30*USEC_PER_SEC) + +#define NOTIFY_SNDBUF_SIZE (8*1024*1024) + +/* The period to insert between posting changes for coalescing */ +#define POST_CHANGE_TIMER_INTERVAL_USEC (250*USEC_PER_MSEC) + +/* Pick a good default that is likely to fit into AF_UNIX and AF_INET SOCK_DGRAM datagrams, and even leaves some room + * for a bit of additional metadata. */ +#define DEFAULT_LINE_MAX (48*1024) + +#define DEFERRED_CLOSES_MAX (4096) + +static int determine_path_usage(Server *s, const char *path, uint64_t *ret_used, uint64_t *ret_free) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + struct statvfs ss; + + assert(ret_used); + assert(ret_free); + + d = opendir(path); + if (!d) + return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, + errno, "Failed to open %s: %m", path); + + if (fstatvfs(dirfd(d), &ss) < 0) + return log_error_errno(errno, "Failed to fstatvfs(%s): %m", path); + + *ret_free = ss.f_bsize * ss.f_bavail; + *ret_used = 0; + FOREACH_DIRENT_ALL(de, d, break) { + struct stat st; + + if (!endswith(de->d_name, ".journal") && + !endswith(de->d_name, ".journal~")) + continue; + + if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { + log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", path, de->d_name); + continue; + } + + if (!S_ISREG(st.st_mode)) + continue; + + *ret_used += (uint64_t) st.st_blocks * 512UL; + } + + return 0; +} + +static void cache_space_invalidate(JournalStorageSpace *space) { + zero(*space); +} + +static int cache_space_refresh(Server *s, JournalStorage *storage) { + JournalStorageSpace *space; + JournalMetrics *metrics; + uint64_t vfs_used, vfs_avail, avail; + usec_t ts; + int r; + + assert(s); + + metrics = &storage->metrics; + space = &storage->space; + + ts = now(CLOCK_MONOTONIC); + + if (space->timestamp != 0 && space->timestamp + RECHECK_SPACE_USEC > ts) + return 0; + + r = determine_path_usage(s, storage->path, &vfs_used, &vfs_avail); + if (r < 0) + return r; + + space->vfs_used = vfs_used; + space->vfs_available = vfs_avail; + + avail = LESS_BY(vfs_avail, metrics->keep_free); + + space->limit = MIN(MAX(vfs_used + avail, metrics->min_use), metrics->max_use); + space->available = LESS_BY(space->limit, vfs_used); + space->timestamp = ts; + return 1; +} + +static void patch_min_use(JournalStorage *storage) { + assert(storage); + + /* Let's bump the min_use limit to the current usage on disk. We do + * this when starting up and first opening the journal files. This way + * sudden spikes in disk usage will not cause journald to vacuum files + * without bounds. Note that this means that only a restart of journald + * will make it reset this value. */ + + storage->metrics.min_use = MAX(storage->metrics.min_use, storage->space.vfs_used); +} + +static int determine_space(Server *s, uint64_t *available, uint64_t *limit) { + JournalStorage *js; + int r; + + assert(s); + + js = s->system_journal ? &s->system_storage : &s->runtime_storage; + + r = cache_space_refresh(s, js); + if (r >= 0) { + if (available) + *available = js->space.available; + if (limit) + *limit = js->space.limit; + } + return r; +} + +void server_space_usage_message(Server *s, JournalStorage *storage) { + char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX], + fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX]; + JournalMetrics *metrics; + + assert(s); + + if (!storage) + storage = s->system_journal ? &s->system_storage : &s->runtime_storage; + + if (cache_space_refresh(s, storage) < 0) + return; + + metrics = &storage->metrics; + format_bytes(fb1, sizeof(fb1), storage->space.vfs_used); + format_bytes(fb2, sizeof(fb2), metrics->max_use); + format_bytes(fb3, sizeof(fb3), metrics->keep_free); + format_bytes(fb4, sizeof(fb4), storage->space.vfs_available); + format_bytes(fb5, sizeof(fb5), storage->space.limit); + format_bytes(fb6, sizeof(fb6), storage->space.available); + + server_driver_message(s, 0, + "MESSAGE_ID=" SD_MESSAGE_JOURNAL_USAGE_STR, + LOG_MESSAGE("%s (%s) is %s, max %s, %s free.", + storage->name, storage->path, fb1, fb5, fb6), + "JOURNAL_NAME=%s", storage->name, + "JOURNAL_PATH=%s", storage->path, + "CURRENT_USE=%"PRIu64, storage->space.vfs_used, + "CURRENT_USE_PRETTY=%s", fb1, + "MAX_USE=%"PRIu64, metrics->max_use, + "MAX_USE_PRETTY=%s", fb2, + "DISK_KEEP_FREE=%"PRIu64, metrics->keep_free, + "DISK_KEEP_FREE_PRETTY=%s", fb3, + "DISK_AVAILABLE=%"PRIu64, storage->space.vfs_available, + "DISK_AVAILABLE_PRETTY=%s", fb4, + "LIMIT=%"PRIu64, storage->space.limit, + "LIMIT_PRETTY=%s", fb5, + "AVAILABLE=%"PRIu64, storage->space.available, + "AVAILABLE_PRETTY=%s", fb6, + NULL); +} + +static bool uid_for_system_journal(uid_t uid) { + + /* Returns true if the specified UID shall get its data stored in the system journal*/ + + return uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY; +} + +static void server_add_acls(JournalFile *f, uid_t uid) { +#if HAVE_ACL + int r; +#endif + assert(f); + +#if HAVE_ACL + if (uid_for_system_journal(uid)) + return; + + r = add_acls_for_user(f->fd, uid); + if (r < 0) + log_warning_errno(r, "Failed to set ACL on %s, ignoring: %m", f->path); +#endif +} + +static int open_journal( + Server *s, + bool reliably, + const char *fname, + int flags, + bool seal, + JournalMetrics *metrics, + JournalFile **ret) { + + _cleanup_(journal_file_closep) JournalFile *f = NULL; + int r; + + assert(s); + assert(fname); + assert(ret); + + if (reliably) + r = journal_file_open_reliably(fname, flags, 0640, s->compress.enabled, s->compress.threshold_bytes, + seal, metrics, s->mmap, s->deferred_closes, NULL, &f); + else + r = journal_file_open(-1, fname, flags, 0640, s->compress.enabled, s->compress.threshold_bytes, seal, + metrics, s->mmap, s->deferred_closes, NULL, &f); + + if (r < 0) + return r; + + r = journal_file_enable_post_change_timer(f, s->event, POST_CHANGE_TIMER_INTERVAL_USEC); + if (r < 0) + return r; + + *ret = TAKE_PTR(f); + return r; +} + +static bool flushed_flag_is_set(void) { + return access("/run/systemd/journal/flushed", F_OK) >= 0; +} + +static int system_journal_open(Server *s, bool flush_requested, bool relinquish_requested) { + const char *fn; + int r = 0; + + if (!s->system_journal && + IN_SET(s->storage, STORAGE_PERSISTENT, STORAGE_AUTO) && + (flush_requested || flushed_flag_is_set()) && + !relinquish_requested) { + + /* If in auto mode: first try to create the machine + * path, but not the prefix. + * + * If in persistent mode: create /var/log/journal and + * the machine path */ + + if (s->storage == STORAGE_PERSISTENT) + (void) mkdir_p("/var/log/journal/", 0755); + + (void) mkdir(s->system_storage.path, 0755); + + fn = strjoina(s->system_storage.path, "/system.journal"); + r = open_journal(s, true, fn, O_RDWR|O_CREAT, s->seal, &s->system_storage.metrics, &s->system_journal); + if (r >= 0) { + server_add_acls(s->system_journal, 0); + (void) cache_space_refresh(s, &s->system_storage); + patch_min_use(&s->system_storage); + } else { + if (!IN_SET(r, -ENOENT, -EROFS)) + log_warning_errno(r, "Failed to open system journal: %m"); + + r = 0; + } + + /* If the runtime journal is open, and we're post-flush, we're + * recovering from a failed system journal rotate (ENOSPC) + * for which the runtime journal was reopened. + * + * Perform an implicit flush to var, leaving the runtime + * journal closed, now that the system journal is back. + */ + if (!flush_requested) + (void) server_flush_to_var(s, true); + } + + if (!s->runtime_journal && + (s->storage != STORAGE_NONE)) { + + fn = strjoina(s->runtime_storage.path, "/system.journal"); + + if (s->system_journal && !relinquish_requested) { + + /* Try to open the runtime journal, but only + * if it already exists, so that we can flush + * it into the system journal */ + + r = open_journal(s, false, fn, O_RDWR, false, &s->runtime_storage.metrics, &s->runtime_journal); + if (r < 0) { + if (r != -ENOENT) + log_warning_errno(r, "Failed to open runtime journal: %m"); + + r = 0; + } + + } else { + + /* OK, we really need the runtime journal, so create + * it if necessary. */ + + (void) mkdir("/run/log", 0755); + (void) mkdir("/run/log/journal", 0755); + (void) mkdir_parents(fn, 0750); + + r = open_journal(s, true, fn, O_RDWR|O_CREAT, false, &s->runtime_storage.metrics, &s->runtime_journal); + if (r < 0) + return log_error_errno(r, "Failed to open runtime journal: %m"); + } + + if (s->runtime_journal) { + server_add_acls(s->runtime_journal, 0); + (void) cache_space_refresh(s, &s->runtime_storage); + patch_min_use(&s->runtime_storage); + } + } + + return r; +} + +static JournalFile* find_journal(Server *s, uid_t uid) { + _cleanup_free_ char *p = NULL; + int r; + JournalFile *f; + sd_id128_t machine; + + assert(s); + + /* A rotate that fails to create the new journal (ENOSPC) leaves the + * rotated journal as NULL. Unless we revisit opening, even after + * space is made available we'll continue to return NULL indefinitely. + * + * system_journal_open() is a noop if the journals are already open, so + * we can just call it here to recover from failed rotates (or anything + * else that's left the journals as NULL). + * + * Fixes https://github.com/systemd/systemd/issues/3968 */ + (void) system_journal_open(s, false, false); + + /* We split up user logs only on /var, not on /run. If the + * runtime file is open, we write to it exclusively, in order + * to guarantee proper order as soon as we flush /run to + * /var and close the runtime file. */ + + if (s->runtime_journal) + return s->runtime_journal; + + if (uid_for_system_journal(uid)) + return s->system_journal; + + f = ordered_hashmap_get(s->user_journals, UID_TO_PTR(uid)); + if (f) + return f; + + r = sd_id128_get_machine(&machine); + if (r < 0) { + log_debug_errno(r, "Failed to determine machine ID, using system log: %m"); + return s->system_journal; + } + + if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/user-"UID_FMT".journal", + SD_ID128_FORMAT_VAL(machine), uid) < 0) { + log_oom(); + return s->system_journal; + } + + while (ordered_hashmap_size(s->user_journals) >= USER_JOURNALS_MAX) { + /* Too many open? Then let's close one */ + f = ordered_hashmap_steal_first(s->user_journals); + assert(f); + (void) journal_file_close(f); + } + + r = open_journal(s, true, p, O_RDWR|O_CREAT, s->seal, &s->system_storage.metrics, &f); + if (r < 0) + return s->system_journal; + + server_add_acls(f, uid); + + r = ordered_hashmap_put(s->user_journals, UID_TO_PTR(uid), f); + if (r < 0) { + (void) journal_file_close(f); + return s->system_journal; + } + + return f; +} + +static int do_rotate( + Server *s, + JournalFile **f, + const char* name, + bool seal, + uint32_t uid) { + + int r; + assert(s); + + if (!*f) + return -EINVAL; + + r = journal_file_rotate(f, s->compress.enabled, s->compress.threshold_bytes, seal, s->deferred_closes); + if (r < 0) { + if (*f) + return log_error_errno(r, "Failed to rotate %s: %m", (*f)->path); + else + return log_error_errno(r, "Failed to create new %s journal: %m", name); + } + + server_add_acls(*f, uid); + + return r; +} + +static void server_process_deferred_closes(Server *s) { + JournalFile *f; + Iterator i; + + /* Perform any deferred closes which aren't still offlining. */ + SET_FOREACH(f, s->deferred_closes, i) { + if (journal_file_is_offlining(f)) + continue; + + (void) set_remove(s->deferred_closes, f); + (void) journal_file_close(f); + } +} + +static void server_vacuum_deferred_closes(Server *s) { + assert(s); + + /* Make some room in the deferred closes list, so that it doesn't grow without bounds */ + if (set_size(s->deferred_closes) < DEFERRED_CLOSES_MAX) + return; + + /* Let's first remove all journal files that might already have completed closing */ + server_process_deferred_closes(s); + + /* And now, let's close some more until we reach the limit again. */ + while (set_size(s->deferred_closes) >= DEFERRED_CLOSES_MAX) { + JournalFile *f; + + assert_se(f = set_steal_first(s->deferred_closes)); + journal_file_close(f); + } +} + +static int open_user_journal_directory(Server *s, DIR **ret_dir, char **ret_path) { + _cleanup_closedir_ DIR *dir = NULL; + _cleanup_free_ char *path = NULL; + sd_id128_t machine; + int r; + + assert(s); + + r = sd_id128_get_machine(&machine); + if (r < 0) + return log_error_errno(r, "Failed to determine machine ID, ignoring: %m"); + + if (asprintf(&path, "/var/log/journal/" SD_ID128_FORMAT_STR "/", SD_ID128_FORMAT_VAL(machine)) < 0) + return log_oom(); + + dir = opendir(path); + if (!dir) + return log_error_errno(errno, "Failed to open user journal directory '%s': %m", path); + + if (ret_dir) + *ret_dir = TAKE_PTR(dir); + if (ret_path) + *ret_path = TAKE_PTR(path); + + return 0; +} + +void server_rotate(Server *s) { + _cleanup_free_ char *path = NULL; + _cleanup_closedir_ DIR *d = NULL; + JournalFile *f; + Iterator i; + void *k; + int r; + + log_debug("Rotating..."); + + /* First, rotate the system journal (either in its runtime flavour or in its runtime flavour) */ + (void) do_rotate(s, &s->runtime_journal, "runtime", false, 0); + (void) do_rotate(s, &s->system_journal, "system", s->seal, 0); + + /* Then, rotate all user journals we have open (keeping them open) */ + ORDERED_HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) { + r = do_rotate(s, &f, "user", s->seal, PTR_TO_UID(k)); + if (r >= 0) + ordered_hashmap_replace(s->user_journals, k, f); + else if (!f) + /* Old file has been closed and deallocated */ + ordered_hashmap_remove(s->user_journals, k); + } + + /* Finally, also rotate all user journals we currently do not have open. (But do so only if we actually have + * access to /var, i.e. are not in the log-to-runtime-journal mode). */ + if (!s->runtime_journal && + open_user_journal_directory(s, &d, &path) >= 0) { + + struct dirent *de; + + FOREACH_DIRENT(de, d, log_warning_errno(errno, "Failed to enumerate %s, ignoring: %m", path)) { + _cleanup_free_ char *u = NULL, *full = NULL; + _cleanup_close_ int fd = -1; + const char *a, *b; + uid_t uid; + + a = startswith(de->d_name, "user-"); + if (!a) + continue; + b = endswith(de->d_name, ".journal"); + if (!b) + continue; + + u = strndup(a, b-a); + if (!u) { + log_oom(); + break; + } + + r = parse_uid(u, &uid); + if (r < 0) { + log_debug_errno(r, "Failed to parse UID from file name '%s', ignoring: %m", de->d_name); + continue; + } + + /* Already rotated in the above loop? i.e. is it an open user journal? */ + if (ordered_hashmap_contains(s->user_journals, UID_TO_PTR(uid))) + continue; + + full = strjoin(path, de->d_name); + if (!full) { + log_oom(); + break; + } + + fd = openat(dirfd(d), de->d_name, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK); + if (fd < 0) { + log_full_errno(IN_SET(errno, ELOOP, ENOENT) ? LOG_DEBUG : LOG_WARNING, errno, + "Failed to open journal file '%s' for rotation: %m", full); + continue; + } + + /* Make some room in the set of deferred close()s */ + server_vacuum_deferred_closes(s); + + /* Open the file briefly, so that we can archive it */ + r = journal_file_open(fd, + full, + O_RDWR, + 0640, + s->compress.enabled, + s->compress.threshold_bytes, + s->seal, + &s->system_storage.metrics, + s->mmap, + s->deferred_closes, + NULL, + &f); + if (r < 0) { + log_warning_errno(r, "Failed to read journal file %s for rotation, trying to move it out of the way: %m", full); + + r = journal_file_dispose(dirfd(d), de->d_name); + if (r < 0) + log_warning_errno(r, "Failed to move %s out of the way, ignoring: %m", full); + else + log_debug("Successfully moved %s out of the way.", full); + + continue; + } + + TAKE_FD(fd); /* Donated to journal_file_open() */ + + r = journal_file_archive(f); + if (r < 0) + log_debug_errno(r, "Failed to archive journal file '%s', ignoring: %m", full); + + f = journal_initiate_close(f, s->deferred_closes); + } + } + + server_process_deferred_closes(s); +} + +void server_sync(Server *s) { + JournalFile *f; + Iterator i; + int r; + + if (s->system_journal) { + r = journal_file_set_offline(s->system_journal, false); + if (r < 0) + log_warning_errno(r, "Failed to sync system journal, ignoring: %m"); + } + + ORDERED_HASHMAP_FOREACH(f, s->user_journals, i) { + r = journal_file_set_offline(f, false); + if (r < 0) + log_warning_errno(r, "Failed to sync user journal, ignoring: %m"); + } + + if (s->sync_event_source) { + r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_OFF); + if (r < 0) + log_error_errno(r, "Failed to disable sync timer source: %m"); + } + + s->sync_scheduled = false; +} + +static void do_vacuum(Server *s, JournalStorage *storage, bool verbose) { + + int r; + + assert(s); + assert(storage); + + (void) cache_space_refresh(s, storage); + + if (verbose) + server_space_usage_message(s, storage); + + r = journal_directory_vacuum(storage->path, storage->space.limit, + storage->metrics.n_max_files, s->max_retention_usec, + &s->oldest_file_usec, verbose); + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to vacuum %s, ignoring: %m", storage->path); + + cache_space_invalidate(&storage->space); +} + +int server_vacuum(Server *s, bool verbose) { + assert(s); + + log_debug("Vacuuming..."); + + s->oldest_file_usec = 0; + + if (s->system_journal) + do_vacuum(s, &s->system_storage, verbose); + if (s->runtime_journal) + do_vacuum(s, &s->runtime_storage, verbose); + + return 0; +} + +static void server_cache_machine_id(Server *s) { + sd_id128_t id; + int r; + + assert(s); + + r = sd_id128_get_machine(&id); + if (r < 0) + return; + + sd_id128_to_string(id, stpcpy(s->machine_id_field, "_MACHINE_ID=")); +} + +static void server_cache_boot_id(Server *s) { + sd_id128_t id; + int r; + + assert(s); + + r = sd_id128_get_boot(&id); + if (r < 0) + return; + + sd_id128_to_string(id, stpcpy(s->boot_id_field, "_BOOT_ID=")); +} + +static void server_cache_hostname(Server *s) { + _cleanup_free_ char *t = NULL; + char *x; + + assert(s); + + t = gethostname_malloc(); + if (!t) + return; + + x = strjoin("_HOSTNAME=", t); + if (!x) + return; + + free(s->hostname_field); + s->hostname_field = x; +} + +static bool shall_try_append_again(JournalFile *f, int r) { + switch(r) { + + case -E2BIG: /* Hit configured limit */ + case -EFBIG: /* Hit fs limit */ + case -EDQUOT: /* Quota limit hit */ + case -ENOSPC: /* Disk full */ + log_debug("%s: Allocation limit reached, rotating.", f->path); + return true; + + case -EIO: /* I/O error of some kind (mmap) */ + log_warning("%s: IO error, rotating.", f->path); + return true; + + case -EHOSTDOWN: /* Other machine */ + log_info("%s: Journal file from other machine, rotating.", f->path); + return true; + + case -EBUSY: /* Unclean shutdown */ + log_info("%s: Unclean shutdown, rotating.", f->path); + return true; + + case -EPROTONOSUPPORT: /* Unsupported feature */ + log_info("%s: Unsupported feature, rotating.", f->path); + return true; + + case -EBADMSG: /* Corrupted */ + case -ENODATA: /* Truncated */ + case -ESHUTDOWN: /* Already archived */ + log_warning("%s: Journal file corrupted, rotating.", f->path); + return true; + + case -EIDRM: /* Journal file has been deleted */ + log_warning("%s: Journal file has been deleted, rotating.", f->path); + return true; + + case -ETXTBSY: /* Journal file is from the future */ + log_warning("%s: Journal file is from the future, rotating.", f->path); + return true; + + case -EAFNOSUPPORT: + log_warning("%s: underlying file system does not support memory mapping or another required file system feature.", f->path); + return false; + + default: + return false; + } +} + +static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n, int priority) { + bool vacuumed = false, rotate = false; + struct dual_timestamp ts; + JournalFile *f; + int r; + + assert(s); + assert(iovec); + assert(n > 0); + + /* Get the closest, linearized time we have for this log event from the event loop. (Note that we do not use + * the source time, and not even the time the event was originally seen, but instead simply the time we started + * processing it, as we want strictly linear ordering in what we write out.) */ + assert_se(sd_event_now(s->event, CLOCK_REALTIME, &ts.realtime) >= 0); + assert_se(sd_event_now(s->event, CLOCK_MONOTONIC, &ts.monotonic) >= 0); + + if (ts.realtime < s->last_realtime_clock) { + /* When the time jumps backwards, let's immediately rotate. Of course, this should not happen during + * regular operation. However, when it does happen, then we should make sure that we start fresh files + * to ensure that the entries in the journal files are strictly ordered by time, in order to ensure + * bisection works correctly. */ + + log_debug("Time jumped backwards, rotating."); + rotate = true; + } else { + + f = find_journal(s, uid); + if (!f) + return; + + if (journal_file_rotate_suggested(f, s->max_file_usec)) { + log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->path); + rotate = true; + } + } + + if (rotate) { + server_rotate(s); + server_vacuum(s, false); + vacuumed = true; + + f = find_journal(s, uid); + if (!f) + return; + } + + s->last_realtime_clock = ts.realtime; + + r = journal_file_append_entry(f, &ts, NULL, iovec, n, &s->seqnum, NULL, NULL); + if (r >= 0) { + server_schedule_sync(s, priority); + return; + } + + if (vacuumed || !shall_try_append_again(f, r)) { + log_error_errno(r, "Failed to write entry (%zu items, %zu bytes), ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n)); + return; + } + + server_rotate(s); + server_vacuum(s, false); + + f = find_journal(s, uid); + if (!f) + return; + + log_debug("Retrying write."); + r = journal_file_append_entry(f, &ts, NULL, iovec, n, &s->seqnum, NULL, NULL); + if (r < 0) + log_error_errno(r, "Failed to write entry (%zu items, %zu bytes) despite vacuuming, ignoring: %m", n, IOVEC_TOTAL_SIZE(iovec, n)); + else + server_schedule_sync(s, priority); +} + +#define IOVEC_ADD_NUMERIC_FIELD(iovec, n, value, type, isset, format, field) \ + if (isset(value)) { \ + char *k; \ + k = newa(char, STRLEN(field "=") + DECIMAL_STR_MAX(type) + 1); \ + sprintf(k, field "=" format, value); \ + iovec[n++] = IOVEC_MAKE_STRING(k); \ + } + +#define IOVEC_ADD_STRING_FIELD(iovec, n, value, field) \ + if (!isempty(value)) { \ + char *k; \ + k = strjoina(field "=", value); \ + iovec[n++] = IOVEC_MAKE_STRING(k); \ + } + +#define IOVEC_ADD_ID128_FIELD(iovec, n, value, field) \ + if (!sd_id128_is_null(value)) { \ + char *k; \ + k = newa(char, STRLEN(field "=") + SD_ID128_STRING_MAX); \ + sd_id128_to_string(value, stpcpy(k, field "=")); \ + iovec[n++] = IOVEC_MAKE_STRING(k); \ + } + +#define IOVEC_ADD_SIZED_FIELD(iovec, n, value, value_size, field) \ + if (value_size > 0) { \ + char *k; \ + k = newa(char, STRLEN(field "=") + value_size + 1); \ + *((char*) mempcpy(stpcpy(k, field "="), value, value_size)) = 0; \ + iovec[n++] = IOVEC_MAKE_STRING(k); \ + } \ + +static void dispatch_message_real( + Server *s, + struct iovec *iovec, size_t n, size_t m, + const ClientContext *c, + const struct timeval *tv, + int priority, + pid_t object_pid) { + + char source_time[sizeof("_SOURCE_REALTIME_TIMESTAMP=") + DECIMAL_STR_MAX(usec_t)]; + _cleanup_free_ char *cmdline1 = NULL, *cmdline2 = NULL; + uid_t journal_uid; + ClientContext *o; + + assert(s); + assert(iovec); + assert(n > 0); + assert(n + + N_IOVEC_META_FIELDS + + (pid_is_valid(object_pid) ? N_IOVEC_OBJECT_FIELDS : 0) + + client_context_extra_fields_n_iovec(c) <= m); + + if (c) { + IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->pid, pid_t, pid_is_valid, PID_FMT, "_PID"); + IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->uid, uid_t, uid_is_valid, UID_FMT, "_UID"); + IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->gid, gid_t, gid_is_valid, GID_FMT, "_GID"); + + IOVEC_ADD_STRING_FIELD(iovec, n, c->comm, "_COMM"); /* At most TASK_COMM_LENGTH (16 bytes) */ + IOVEC_ADD_STRING_FIELD(iovec, n, c->exe, "_EXE"); /* A path, so at most PATH_MAX (4096 bytes) */ + + if (c->cmdline) + /* At most _SC_ARG_MAX (2MB usually), which is too much to put on stack. + * Let's use a heap allocation for this one. */ + cmdline1 = set_iovec_string_field(iovec, &n, "_CMDLINE=", c->cmdline); + + IOVEC_ADD_STRING_FIELD(iovec, n, c->capeff, "_CAP_EFFECTIVE"); /* Read from /proc/.../status */ + IOVEC_ADD_SIZED_FIELD(iovec, n, c->label, c->label_size, "_SELINUX_CONTEXT"); + IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "_AUDIT_SESSION"); + IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->loginuid, uid_t, uid_is_valid, UID_FMT, "_AUDIT_LOGINUID"); + + IOVEC_ADD_STRING_FIELD(iovec, n, c->cgroup, "_SYSTEMD_CGROUP"); /* A path */ + IOVEC_ADD_STRING_FIELD(iovec, n, c->session, "_SYSTEMD_SESSION"); + IOVEC_ADD_NUMERIC_FIELD(iovec, n, c->owner_uid, uid_t, uid_is_valid, UID_FMT, "_SYSTEMD_OWNER_UID"); + IOVEC_ADD_STRING_FIELD(iovec, n, c->unit, "_SYSTEMD_UNIT"); /* Unit names are bounded by UNIT_NAME_MAX */ + IOVEC_ADD_STRING_FIELD(iovec, n, c->user_unit, "_SYSTEMD_USER_UNIT"); + IOVEC_ADD_STRING_FIELD(iovec, n, c->slice, "_SYSTEMD_SLICE"); + IOVEC_ADD_STRING_FIELD(iovec, n, c->user_slice, "_SYSTEMD_USER_SLICE"); + + IOVEC_ADD_ID128_FIELD(iovec, n, c->invocation_id, "_SYSTEMD_INVOCATION_ID"); + + if (c->extra_fields_n_iovec > 0) { + memcpy(iovec + n, c->extra_fields_iovec, c->extra_fields_n_iovec * sizeof(struct iovec)); + n += c->extra_fields_n_iovec; + } + } + + assert(n <= m); + + if (pid_is_valid(object_pid) && client_context_get(s, object_pid, NULL, NULL, 0, NULL, &o) >= 0) { + + IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->pid, pid_t, pid_is_valid, PID_FMT, "OBJECT_PID"); + IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->uid, uid_t, uid_is_valid, UID_FMT, "OBJECT_UID"); + IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->gid, gid_t, gid_is_valid, GID_FMT, "OBJECT_GID"); + + /* See above for size limits, only ->cmdline may be large, so use a heap allocation for it. */ + IOVEC_ADD_STRING_FIELD(iovec, n, o->comm, "OBJECT_COMM"); + IOVEC_ADD_STRING_FIELD(iovec, n, o->exe, "OBJECT_EXE"); + if (o->cmdline) + cmdline2 = set_iovec_string_field(iovec, &n, "OBJECT_CMDLINE=", o->cmdline); + + IOVEC_ADD_STRING_FIELD(iovec, n, o->capeff, "OBJECT_CAP_EFFECTIVE"); + IOVEC_ADD_SIZED_FIELD(iovec, n, o->label, o->label_size, "OBJECT_SELINUX_CONTEXT"); + IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->auditid, uint32_t, audit_session_is_valid, "%" PRIu32, "OBJECT_AUDIT_SESSION"); + IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->loginuid, uid_t, uid_is_valid, UID_FMT, "OBJECT_AUDIT_LOGINUID"); + + IOVEC_ADD_STRING_FIELD(iovec, n, o->cgroup, "OBJECT_SYSTEMD_CGROUP"); + IOVEC_ADD_STRING_FIELD(iovec, n, o->session, "OBJECT_SYSTEMD_SESSION"); + IOVEC_ADD_NUMERIC_FIELD(iovec, n, o->owner_uid, uid_t, uid_is_valid, UID_FMT, "OBJECT_SYSTEMD_OWNER_UID"); + IOVEC_ADD_STRING_FIELD(iovec, n, o->unit, "OBJECT_SYSTEMD_UNIT"); + IOVEC_ADD_STRING_FIELD(iovec, n, o->user_unit, "OBJECT_SYSTEMD_USER_UNIT"); + IOVEC_ADD_STRING_FIELD(iovec, n, o->slice, "OBJECT_SYSTEMD_SLICE"); + IOVEC_ADD_STRING_FIELD(iovec, n, o->user_slice, "OBJECT_SYSTEMD_USER_SLICE"); + + IOVEC_ADD_ID128_FIELD(iovec, n, o->invocation_id, "OBJECT_SYSTEMD_INVOCATION_ID="); + } + + assert(n <= m); + + if (tv) { + sprintf(source_time, "_SOURCE_REALTIME_TIMESTAMP=" USEC_FMT, timeval_load(tv)); + iovec[n++] = IOVEC_MAKE_STRING(source_time); + } + + /* Note that strictly speaking storing the boot id here is + * redundant since the entry includes this in-line + * anyway. However, we need this indexed, too. */ + if (!isempty(s->boot_id_field)) + iovec[n++] = IOVEC_MAKE_STRING(s->boot_id_field); + + if (!isempty(s->machine_id_field)) + iovec[n++] = IOVEC_MAKE_STRING(s->machine_id_field); + + if (!isempty(s->hostname_field)) + iovec[n++] = IOVEC_MAKE_STRING(s->hostname_field); + + assert(n <= m); + + if (s->split_mode == SPLIT_UID && c && uid_is_valid(c->uid)) + /* Split up strictly by (non-root) UID */ + journal_uid = c->uid; + else if (s->split_mode == SPLIT_LOGIN && c && c->uid > 0 && uid_is_valid(c->owner_uid)) + /* Split up by login UIDs. We do this only if the + * realuid is not root, in order not to accidentally + * leak privileged information to the user that is + * logged by a privileged process that is part of an + * unprivileged session. */ + journal_uid = c->owner_uid; + else + journal_uid = 0; + + write_to_journal(s, journal_uid, iovec, n, priority); +} + +void server_driver_message(Server *s, pid_t object_pid, const char *message_id, const char *format, ...) { + + struct iovec *iovec; + size_t n = 0, k, m; + va_list ap; + int r; + + assert(s); + assert(format); + + m = N_IOVEC_META_FIELDS + 5 + N_IOVEC_PAYLOAD_FIELDS + client_context_extra_fields_n_iovec(s->my_context) + N_IOVEC_OBJECT_FIELDS; + iovec = newa(struct iovec, m); + + assert_cc(3 == LOG_FAC(LOG_DAEMON)); + iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_FACILITY=3"); + iovec[n++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=systemd-journald"); + + iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=driver"); + assert_cc(6 == LOG_INFO); + iovec[n++] = IOVEC_MAKE_STRING("PRIORITY=6"); + + if (message_id) + iovec[n++] = IOVEC_MAKE_STRING(message_id); + k = n; + + va_start(ap, format); + r = log_format_iovec(iovec, m, &n, false, 0, format, ap); + /* Error handling below */ + va_end(ap); + + if (r >= 0) + dispatch_message_real(s, iovec, n, m, s->my_context, NULL, LOG_INFO, object_pid); + + while (k < n) + free(iovec[k++].iov_base); + + if (r < 0) { + /* We failed to format the message. Emit a warning instead. */ + char buf[LINE_MAX]; + + xsprintf(buf, "MESSAGE=Entry printing failed: %s", strerror_safe(r)); + + n = 3; + iovec[n++] = IOVEC_MAKE_STRING("PRIORITY=4"); + iovec[n++] = IOVEC_MAKE_STRING(buf); + dispatch_message_real(s, iovec, n, m, s->my_context, NULL, LOG_INFO, object_pid); + } +} + +void server_dispatch_message( + Server *s, + struct iovec *iovec, size_t n, size_t m, + ClientContext *c, + const struct timeval *tv, + int priority, + pid_t object_pid) { + + uint64_t available = 0; + int rl; + + assert(s); + assert(iovec || n == 0); + + if (n == 0) + return; + + if (LOG_PRI(priority) > s->max_level_store) + return; + + /* Stop early in case the information will not be stored + * in a journal. */ + if (s->storage == STORAGE_NONE) + return; + + if (c && c->unit) { + (void) determine_space(s, &available, NULL); + + rl = journal_ratelimit_test(s->ratelimit, c->unit, c->log_ratelimit_interval, c->log_ratelimit_burst, priority & LOG_PRIMASK, available); + if (rl == 0) + return; + + /* Write a suppression message if we suppressed something */ + if (rl > 1) + server_driver_message(s, c->pid, + "MESSAGE_ID=" SD_MESSAGE_JOURNAL_DROPPED_STR, + LOG_MESSAGE("Suppressed %i messages from %s", rl - 1, c->unit), + "N_DROPPED=%i", rl - 1, + NULL); + } + + dispatch_message_real(s, iovec, n, m, c, tv, priority, object_pid); +} + +int server_flush_to_var(Server *s, bool require_flag_file) { + sd_journal *j = NULL; + char ts[FORMAT_TIMESPAN_MAX]; + usec_t start; + unsigned n = 0; + int r, k; + + assert(s); + + if (!IN_SET(s->storage, STORAGE_AUTO, STORAGE_PERSISTENT)) + return 0; + + if (!s->runtime_journal) + return 0; + + if (require_flag_file && !flushed_flag_is_set()) + return 0; + + (void) system_journal_open(s, true, false); + + if (!s->system_journal) + return 0; + + log_debug("Flushing to /var..."); + + start = now(CLOCK_MONOTONIC); + + r = sd_journal_open(&j, SD_JOURNAL_RUNTIME_ONLY); + if (r < 0) + return log_error_errno(r, "Failed to read runtime journal: %m"); + + sd_journal_set_data_threshold(j, 0); + + SD_JOURNAL_FOREACH(j) { + Object *o = NULL; + JournalFile *f; + + f = j->current_file; + assert(f && f->current_offset > 0); + + n++; + + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); + if (r < 0) { + log_error_errno(r, "Can't read entry: %m"); + goto finish; + } + + r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset); + if (r >= 0) + continue; + + if (!shall_try_append_again(s->system_journal, r)) { + log_error_errno(r, "Can't write entry: %m"); + goto finish; + } + + server_rotate(s); + server_vacuum(s, false); + + if (!s->system_journal) { + log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful."); + r = -EIO; + goto finish; + } + + log_debug("Retrying write."); + r = journal_file_copy_entry(f, s->system_journal, o, f->current_offset); + if (r < 0) { + log_error_errno(r, "Can't write entry: %m"); + goto finish; + } + } + + r = 0; + +finish: + if (s->system_journal) + journal_file_post_change(s->system_journal); + + s->runtime_journal = journal_file_close(s->runtime_journal); + + if (r >= 0) + (void) rm_rf("/run/log/journal", REMOVE_ROOT); + + sd_journal_close(j); + + server_driver_message(s, 0, NULL, + LOG_MESSAGE("Time spent on flushing to /var is %s for %u entries.", + format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0), + n), + NULL); + + k = touch("/run/systemd/journal/flushed"); + if (k < 0) + log_warning_errno(k, "Failed to touch /run/systemd/journal/flushed, ignoring: %m"); + + return r; +} + +static int server_relinquish_var(Server *s) { + assert(s); + + if (s->storage == STORAGE_NONE) + return 0; + + if (s->runtime_journal && !s->system_journal) + return 0; + + log_debug("Relinquishing /var..."); + + (void) system_journal_open(s, false, true); + + s->system_journal = journal_file_close(s->system_journal); + ordered_hashmap_clear_with_destructor(s->user_journals, journal_file_close); + set_clear_with_destructor(s->deferred_closes, journal_file_close); + + if (unlink("/run/systemd/journal/flushed") < 0 && errno != ENOENT) + log_warning_errno(errno, "Failed to unlink /run/systemd/journal/flushed, ignoring: %m"); + + return 0; +} + +int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + Server *s = userdata; + struct ucred *ucred = NULL; + struct timeval *tv = NULL; + struct cmsghdr *cmsg; + char *label = NULL; + size_t label_len = 0, m; + struct iovec iovec; + ssize_t n; + int *fds = NULL, v = 0; + size_t n_fds = 0; + + union { + struct cmsghdr cmsghdr; + + /* We use NAME_MAX space for the SELinux label + * here. The kernel currently enforces no + * limit, but according to suggestions from + * the SELinux people this will change and it + * will probably be identical to NAME_MAX. For + * now we use that, but this should be updated + * one day when the final limit is known. */ + uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + + CMSG_SPACE(sizeof(struct timeval)) + + CMSG_SPACE(sizeof(int)) + /* fd */ + CMSG_SPACE(NAME_MAX)]; /* selinux label */ + } control = {}; + + union sockaddr_union sa = {}; + + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + .msg_name = &sa, + .msg_namelen = sizeof(sa), + }; + + assert(s); + assert(fd == s->native_fd || fd == s->syslog_fd || fd == s->audit_fd); + + if (revents != EPOLLIN) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Got invalid event from epoll for datagram fd: %" PRIx32, + revents); + + /* Try to get the right size, if we can. (Not all sockets support SIOCINQ, hence we just try, but don't rely on + * it.) */ + (void) ioctl(fd, SIOCINQ, &v); + + /* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful! */ + m = PAGE_ALIGN(MAX3((size_t) v + 1, + (size_t) LINE_MAX, + ALIGN(sizeof(struct nlmsghdr)) + ALIGN((size_t) MAX_AUDIT_MESSAGE_LENGTH)) + 1); + + if (!GREEDY_REALLOC(s->buffer, s->buffer_size, m)) + return log_oom(); + + iovec = IOVEC_MAKE(s->buffer, s->buffer_size - 1); /* Leave room for trailing NUL we add later */ + + n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (n < 0) { + if (IN_SET(errno, EINTR, EAGAIN)) + return 0; + + return log_error_errno(errno, "recvmsg() failed: %m"); + } + + CMSG_FOREACH(cmsg, &msghdr) + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) + ucred = (struct ucred*) CMSG_DATA(cmsg); + else if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_SECURITY) { + label = (char*) CMSG_DATA(cmsg); + label_len = cmsg->cmsg_len - CMSG_LEN(0); + } else if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SO_TIMESTAMP && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) + tv = (struct timeval*) CMSG_DATA(cmsg); + else if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) { + fds = (int*) CMSG_DATA(cmsg); + n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); + } + + /* And a trailing NUL, just in case */ + s->buffer[n] = 0; + + if (fd == s->syslog_fd) { + if (n > 0 && n_fds == 0) + server_process_syslog_message(s, s->buffer, n, ucred, tv, label, label_len); + else if (n_fds > 0) + log_warning("Got file descriptors via syslog socket. Ignoring."); + + } else if (fd == s->native_fd) { + if (n > 0 && n_fds == 0) + server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len); + else if (n == 0 && n_fds == 1) + server_process_native_file(s, fds[0], ucred, tv, label, label_len); + else if (n_fds > 0) + log_warning("Got too many file descriptors via native socket. Ignoring."); + + } else { + assert(fd == s->audit_fd); + + if (n > 0 && n_fds == 0) + server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen); + else if (n_fds > 0) + log_warning("Got file descriptors via audit socket. Ignoring."); + } + + close_many(fds, n_fds); + return 0; +} + +static void server_full_flush(Server *s) { + assert(s); + + (void) server_flush_to_var(s, false); + server_sync(s); + server_vacuum(s, false); + + server_space_usage_message(s, NULL); +} + +static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { + Server *s = userdata; + + assert(s); + + log_info("Received SIGUSR1 signal from PID " PID_FMT ", as request to flush runtime journal.", si->ssi_pid); + server_full_flush(s); + + return 0; +} + +static void server_full_rotate(Server *s) { + int r; + + assert(s); + + server_rotate(s); + server_vacuum(s, true); + + if (s->system_journal) + patch_min_use(&s->system_storage); + if (s->runtime_journal) + patch_min_use(&s->runtime_storage); + + /* Let clients know when the most recent rotation happened. */ + r = write_timestamp_file_atomic("/run/systemd/journal/rotated", now(CLOCK_MONOTONIC)); + if (r < 0) + log_warning_errno(r, "Failed to write /run/systemd/journal/rotated, ignoring: %m"); +} + +static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { + Server *s = userdata; + + assert(s); + + log_info("Received SIGUSR2 signal from PID " PID_FMT ", as request to rotate journal.", si->ssi_pid); + server_full_rotate(s); + + return 0; +} + +static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { + Server *s = userdata; + + assert(s); + + log_received_signal(LOG_INFO, si); + + sd_event_exit(s->event, 0); + return 0; +} + +static void server_full_sync(Server *s) { + int r; + + assert(s); + + server_sync(s); + + /* Let clients know when the most recent sync happened. */ + r = write_timestamp_file_atomic("/run/systemd/journal/synced", now(CLOCK_MONOTONIC)); + if (r < 0) + log_warning_errno(r, "Failed to write /run/systemd/journal/synced, ignoring: %m"); + + return; +} + +static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) { + Server *s = userdata; + + assert(s); + + log_debug("Received SIGRTMIN1 signal from PID " PID_FMT ", as request to sync.", si->ssi_pid ); + server_full_sync(s); + + return 0; +} + +static int setup_signals(Server *s) { + int r; + + assert(s); + + assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0); + + r = sd_event_add_signal(s->event, &s->sigusr1_event_source, SIGUSR1, dispatch_sigusr1, s); + if (r < 0) + return r; + + r = sd_event_add_signal(s->event, &s->sigusr2_event_source, SIGUSR2, dispatch_sigusr2, s); + if (r < 0) + return r; + + r = sd_event_add_signal(s->event, &s->sigterm_event_source, SIGTERM, dispatch_sigterm, s); + if (r < 0) + return r; + + /* Let's process SIGTERM late, so that we flush all queued messages to disk before we exit */ + r = sd_event_source_set_priority(s->sigterm_event_source, SD_EVENT_PRIORITY_NORMAL+20); + if (r < 0) + return r; + + /* When journald is invoked on the terminal (when debugging), it's useful if C-c is handled + * equivalent to SIGTERM. */ + r = sd_event_add_signal(s->event, &s->sigint_event_source, SIGINT, dispatch_sigterm, s); + if (r < 0) + return r; + + r = sd_event_source_set_priority(s->sigint_event_source, SD_EVENT_PRIORITY_NORMAL+20); + if (r < 0) + return r; + + /* SIGRTMIN+1 causes an immediate sync. We process this very late, so that everything else queued at + * this point is really written to disk. Clients can watch /run/systemd/journal/synced with inotify + * until its mtime changes to see when a sync happened. */ + r = sd_event_add_signal(s->event, &s->sigrtmin1_event_source, SIGRTMIN+1, dispatch_sigrtmin1, s); + if (r < 0) + return r; + + r = sd_event_source_set_priority(s->sigrtmin1_event_source, SD_EVENT_PRIORITY_NORMAL+15); + if (r < 0) + return r; + + return 0; +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + Server *s = data; + int r; + + assert(s); + + if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_syslog")) { + + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning("Failed to parse forward to syslog switch \"%s\". Ignoring.", value); + else + s->forward_to_syslog = r; + + } else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_kmsg")) { + + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning("Failed to parse forward to kmsg switch \"%s\". Ignoring.", value); + else + s->forward_to_kmsg = r; + + } else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_console")) { + + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning("Failed to parse forward to console switch \"%s\". Ignoring.", value); + else + s->forward_to_console = r; + + } else if (proc_cmdline_key_streq(key, "systemd.journald.forward_to_wall")) { + + r = value ? parse_boolean(value) : true; + if (r < 0) + log_warning("Failed to parse forward to wall switch \"%s\". Ignoring.", value); + else + s->forward_to_wall = r; + + } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_console")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = log_level_from_string(value); + if (r < 0) + log_warning("Failed to parse max level console value \"%s\". Ignoring.", value); + else + s->max_level_console = r; + + } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_store")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = log_level_from_string(value); + if (r < 0) + log_warning("Failed to parse max level store value \"%s\". Ignoring.", value); + else + s->max_level_store = r; + + } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_syslog")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = log_level_from_string(value); + if (r < 0) + log_warning("Failed to parse max level syslog value \"%s\". Ignoring.", value); + else + s->max_level_syslog = r; + + } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_kmsg")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = log_level_from_string(value); + if (r < 0) + log_warning("Failed to parse max level kmsg value \"%s\". Ignoring.", value); + else + s->max_level_kmsg = r; + + } else if (proc_cmdline_key_streq(key, "systemd.journald.max_level_wall")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = log_level_from_string(value); + if (r < 0) + log_warning("Failed to parse max level wall value \"%s\". Ignoring.", value); + else + s->max_level_wall = r; + + } else if (startswith(key, "systemd.journald")) + log_warning("Unknown journald kernel command line option \"%s\". Ignoring.", key); + + /* do not warn about state here, since probably systemd already did */ + return 0; +} + +static int server_parse_config_file(Server *s) { + assert(s); + + return config_parse_many_nulstr(PKGSYSCONFDIR "/journald.conf", + CONF_PATHS_NULSTR("systemd/journald.conf.d"), + "Journal\0", + config_item_perf_lookup, journald_gperf_lookup, + CONFIG_PARSE_WARN, s); +} + +static int server_dispatch_sync(sd_event_source *es, usec_t t, void *userdata) { + Server *s = userdata; + + assert(s); + + server_sync(s); + return 0; +} + +int server_schedule_sync(Server *s, int priority) { + int r; + + assert(s); + + if (priority <= LOG_CRIT) { + /* Immediately sync to disk when this is of priority CRIT, ALERT, EMERG */ + server_sync(s); + return 0; + } + + if (s->sync_scheduled) + return 0; + + if (s->sync_interval_usec > 0) { + usec_t when; + + r = sd_event_now(s->event, CLOCK_MONOTONIC, &when); + if (r < 0) + return r; + + when += s->sync_interval_usec; + + if (!s->sync_event_source) { + r = sd_event_add_time( + s->event, + &s->sync_event_source, + CLOCK_MONOTONIC, + when, 0, + server_dispatch_sync, s); + if (r < 0) + return r; + + r = sd_event_source_set_priority(s->sync_event_source, SD_EVENT_PRIORITY_IMPORTANT); + } else { + r = sd_event_source_set_time(s->sync_event_source, when); + if (r < 0) + return r; + + r = sd_event_source_set_enabled(s->sync_event_source, SD_EVENT_ONESHOT); + } + if (r < 0) + return r; + + s->sync_scheduled = true; + } + + return 0; +} + +static int dispatch_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + Server *s = userdata; + + assert(s); + + server_cache_hostname(s); + return 0; +} + +static int server_open_hostname(Server *s) { + int r; + + assert(s); + + s->hostname_fd = open("/proc/sys/kernel/hostname", + O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (s->hostname_fd < 0) + return log_error_errno(errno, "Failed to open /proc/sys/kernel/hostname: %m"); + + r = sd_event_add_io(s->event, &s->hostname_event_source, s->hostname_fd, 0, dispatch_hostname_change, s); + if (r < 0) { + /* kernels prior to 3.2 don't support polling this file. Ignore + * the failure. */ + if (r == -EPERM) { + log_warning_errno(r, "Failed to register hostname fd in event loop, ignoring: %m"); + s->hostname_fd = safe_close(s->hostname_fd); + return 0; + } + + return log_error_errno(r, "Failed to register hostname fd in event loop: %m"); + } + + r = sd_event_source_set_priority(s->hostname_event_source, SD_EVENT_PRIORITY_IMPORTANT-10); + if (r < 0) + return log_error_errno(r, "Failed to adjust priority of host name event source: %m"); + + return 0; +} + +static int dispatch_notify_event(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + Server *s = userdata; + int r; + + assert(s); + assert(s->notify_event_source == es); + assert(s->notify_fd == fd); + + /* The $NOTIFY_SOCKET is writable again, now send exactly one + * message on it. Either it's the watchdog event, the initial + * READY=1 event or an stdout stream event. If there's nothing + * to write anymore, turn our event source off. The next time + * there's something to send it will be turned on again. */ + + if (!s->sent_notify_ready) { + static const char p[] = + "READY=1\n" + "STATUS=Processing requests..."; + ssize_t l; + + l = send(s->notify_fd, p, strlen(p), MSG_DONTWAIT); + if (l < 0) { + if (errno == EAGAIN) + return 0; + + return log_error_errno(errno, "Failed to send READY=1 notification message: %m"); + } + + s->sent_notify_ready = true; + log_debug("Sent READY=1 notification."); + + } else if (s->send_watchdog) { + + static const char p[] = + "WATCHDOG=1"; + + ssize_t l; + + l = send(s->notify_fd, p, strlen(p), MSG_DONTWAIT); + if (l < 0) { + if (errno == EAGAIN) + return 0; + + return log_error_errno(errno, "Failed to send WATCHDOG=1 notification message: %m"); + } + + s->send_watchdog = false; + log_debug("Sent WATCHDOG=1 notification."); + + } else if (s->stdout_streams_notify_queue) + /* Dispatch one stream notification event */ + stdout_stream_send_notify(s->stdout_streams_notify_queue); + + /* Leave us enabled if there's still more to do. */ + if (s->send_watchdog || s->stdout_streams_notify_queue) + return 0; + + /* There was nothing to do anymore, let's turn ourselves off. */ + r = sd_event_source_set_enabled(es, SD_EVENT_OFF); + if (r < 0) + return log_error_errno(r, "Failed to turn off notify event source: %m"); + + return 0; +} + +static int dispatch_watchdog(sd_event_source *es, uint64_t usec, void *userdata) { + Server *s = userdata; + int r; + + assert(s); + + s->send_watchdog = true; + + r = sd_event_source_set_enabled(s->notify_event_source, SD_EVENT_ON); + if (r < 0) + log_warning_errno(r, "Failed to turn on notify event source: %m"); + + r = sd_event_source_set_time(s->watchdog_event_source, usec + s->watchdog_usec / 2); + if (r < 0) + return log_error_errno(r, "Failed to restart watchdog event source: %m"); + + r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ON); + if (r < 0) + return log_error_errno(r, "Failed to enable watchdog event source: %m"); + + return 0; +} + +static int server_connect_notify(Server *s) { + union sockaddr_union sa = {}; + const char *e; + int r, salen; + + assert(s); + assert(s->notify_fd < 0); + assert(!s->notify_event_source); + + /* + * So here's the problem: we'd like to send notification messages to PID 1, but we cannot do that via + * sd_notify(), since that's synchronous, and we might end up blocking on it. Specifically: given + * that PID 1 might block on dbus-daemon during IPC, and dbus-daemon is logging to us, and might + * hence block on us, we might end up in a deadlock if we block on sending PID 1 notification + * messages — by generating a full blocking circle. To avoid this, let's create a non-blocking + * socket, and connect it to the notification socket, and then wait for POLLOUT before we send + * anything. This should efficiently avoid any deadlocks, as we'll never block on PID 1, hence PID 1 + * can safely block on dbus-daemon which can safely block on us again. + * + * Don't think that this issue is real? It is, see: https://github.com/systemd/systemd/issues/1505 + */ + + e = getenv("NOTIFY_SOCKET"); + if (!e) + return 0; + + salen = sockaddr_un_set_path(&sa.un, e); + if (salen < 0) + return log_error_errno(salen, "NOTIFY_SOCKET set to invalid value '%s': %m", e); + + s->notify_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s->notify_fd < 0) + return log_error_errno(errno, "Failed to create notify socket: %m"); + + (void) fd_inc_sndbuf(s->notify_fd, NOTIFY_SNDBUF_SIZE); + + r = connect(s->notify_fd, &sa.sa, salen); + if (r < 0) + return log_error_errno(errno, "Failed to connect to notify socket: %m"); + + r = sd_event_add_io(s->event, &s->notify_event_source, s->notify_fd, EPOLLOUT, dispatch_notify_event, s); + if (r < 0) + return log_error_errno(r, "Failed to watch notification socket: %m"); + + if (sd_watchdog_enabled(false, &s->watchdog_usec) > 0) { + s->send_watchdog = true; + + r = sd_event_add_time(s->event, &s->watchdog_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + s->watchdog_usec/2, s->watchdog_usec/4, dispatch_watchdog, s); + if (r < 0) + return log_error_errno(r, "Failed to add watchdog time event: %m"); + } + + /* This should fire pretty soon, which we'll use to send the READY=1 event. */ + + return 0; +} + +static int synchronize_second_half(sd_event_source *event_source, void *userdata) { + Varlink *link = userdata; + Server *s; + int r; + + assert(link); + assert_se(s = varlink_get_userdata(link)); + + /* This is the "second half" of the Synchronize() varlink method. This function is called as deferred + * event source at a low priority to ensure the synchronization completes after all queued log + * messages are processed. */ + server_full_sync(s); + + /* Let's get rid of the event source now, by marking it as non-floating again. It then has no ref + * anymore and is immediately destroyed after we return from this function, i.e. from this event + * source handler at the end. */ + r = sd_event_source_set_floating(event_source, false); + if (r < 0) + return log_error_errno(r, "Failed to mark event source as non-floating: %m"); + + return varlink_reply(link, NULL); +} + +static void synchronize_destroy(void *userdata) { + varlink_unref(userdata); +} + +static int vl_method_synchronize(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { + _cleanup_(sd_event_source_unrefp) sd_event_source *event_source = NULL; + Server *s = userdata; + int r; + + assert(link); + assert(s); + + if (json_variant_elements(parameters) > 0) + return varlink_error_invalid_parameter(link, parameters); + + log_info("Received client request to rotate journal."); + + /* We don't do the main work now, but instead enqueue a deferred event loop job which will do + * it. That job is scheduled at low priority, so that we return from this method call only after all + * queued but not processed log messages are written to disk, so that this method call returning can + * be used as nice synchronization point. */ + r = sd_event_add_defer(s->event, &event_source, synchronize_second_half, link); + if (r < 0) + return log_error_errno(r, "Failed to allocate defer event source: %m"); + + r = sd_event_source_set_destroy_callback(event_source, synchronize_destroy); + if (r < 0) + return log_error_errno(r, "Failed to set event source destroy callback: %m"); + + varlink_ref(link); /* The varlink object is now left to the destroy callack to unref */ + + r = sd_event_source_set_priority(event_source, SD_EVENT_PRIORITY_NORMAL+15); + if (r < 0) + return log_error_errno(r, "Failed to set defer event source priority: %m"); + + /* Give up ownership of this event source. It will now be destroyed along with event loop itself, + * unless it destroys itself earlier. */ + r = sd_event_source_set_floating(event_source, true); + if (r < 0) + return log_error_errno(r, "Failed to mark event source as floating: %m"); + + (void) sd_event_source_set_description(event_source, "deferred-sync"); + + return 0; +} + +static int vl_method_rotate(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { + Server *s = userdata; + + assert(link); + assert(s); + + if (json_variant_elements(parameters) > 0) + return varlink_error_invalid_parameter(link, parameters); + + log_info("Received client request to rotate journal."); + server_full_rotate(s); + + return varlink_reply(link, NULL); +} + +static int vl_method_flush_to_var(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { + Server *s = userdata; + + assert(link); + assert(s); + + if (json_variant_elements(parameters) > 0) + return varlink_error_invalid_parameter(link, parameters); + + log_info("Received client request to flush runtime journal."); + server_full_flush(s); + + return varlink_reply(link, NULL); +} + +static int vl_method_relinquish_var(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { + Server *s = userdata; + + assert(link); + assert(s); + + if (json_variant_elements(parameters) > 0) + return varlink_error_invalid_parameter(link, parameters); + + log_info("Received client request to relinquish /var access."); + server_relinquish_var(s); + + return varlink_reply(link, NULL); +} + +static int server_open_varlink(Server *s) { + int r; + + assert(s); + + r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY); + if (r < 0) + return r; + + varlink_server_set_userdata(s->varlink_server, s); + + r = varlink_server_bind_method_many( + s->varlink_server, + "io.systemd.Journal.Synchronize", vl_method_synchronize, + "io.systemd.Journal.Rotate", vl_method_rotate, + "io.systemd.Journal.FlushToVar", vl_method_flush_to_var, + "io.systemd.Journal.RelinquishVar", vl_method_relinquish_var); + if (r < 0) + return r; + + r = varlink_server_listen_address(s->varlink_server, "/run/systemd/journal/io.systemd.journal", 0600); + if (r < 0) + return r; + + r = varlink_server_attach_event(s->varlink_server, s->event, SD_EVENT_PRIORITY_NORMAL); + if (r < 0) + return r; + + return 0; +} + +int server_init(Server *s) { + _cleanup_fdset_free_ FDSet *fds = NULL; + int n, r, fd; + bool no_sockets; + + assert(s); + + *s = (Server) { + .syslog_fd = -1, + .native_fd = -1, + .stdout_fd = -1, + .dev_kmsg_fd = -1, + .audit_fd = -1, + .hostname_fd = -1, + .notify_fd = -1, + + .compress.enabled = true, + .compress.threshold_bytes = (uint64_t) -1, + .seal = true, + .read_kmsg = true, + + .watchdog_usec = USEC_INFINITY, + + .sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC, + .sync_scheduled = false, + + .ratelimit_interval = DEFAULT_RATE_LIMIT_INTERVAL, + .ratelimit_burst = DEFAULT_RATE_LIMIT_BURST, + + .forward_to_wall = true, + + .max_file_usec = DEFAULT_MAX_FILE_USEC, + + .max_level_store = LOG_DEBUG, + .max_level_syslog = LOG_DEBUG, + .max_level_kmsg = LOG_NOTICE, + .max_level_console = LOG_INFO, + .max_level_wall = LOG_EMERG, + + .line_max = DEFAULT_LINE_MAX, + + .runtime_storage.name = "Runtime Journal", + .system_storage.name = "System Journal", + }; + + journal_reset_metrics(&s->system_storage.metrics); + journal_reset_metrics(&s->runtime_storage.metrics); + + server_parse_config_file(s); + + r = proc_cmdline_parse(parse_proc_cmdline_item, s, PROC_CMDLINE_STRIP_RD_PREFIX); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + if (!!s->ratelimit_interval ^ !!s->ratelimit_burst) { + log_debug("Setting both rate limit interval and burst from "USEC_FMT",%u to 0,0", + s->ratelimit_interval, s->ratelimit_burst); + s->ratelimit_interval = s->ratelimit_burst = 0; + } + + (void) mkdir_p("/run/systemd/journal", 0755); + + s->user_journals = ordered_hashmap_new(NULL); + if (!s->user_journals) + return log_oom(); + + s->mmap = mmap_cache_new(); + if (!s->mmap) + return log_oom(); + + s->deferred_closes = set_new(NULL); + if (!s->deferred_closes) + return log_oom(); + + r = sd_event_default(&s->event); + if (r < 0) + return log_error_errno(r, "Failed to create event loop: %m"); + + n = sd_listen_fds(true); + if (n < 0) + return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { + + if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/socket", 0) > 0) { + + if (s->native_fd >= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many native sockets passed."); + + s->native_fd = fd; + + } else if (sd_is_socket_unix(fd, SOCK_STREAM, 1, "/run/systemd/journal/stdout", 0) > 0) { + + if (s->stdout_fd >= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many stdout sockets passed."); + + s->stdout_fd = fd; + + } else if (sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/dev/log", 0) > 0 || + sd_is_socket_unix(fd, SOCK_DGRAM, -1, "/run/systemd/journal/dev-log", 0) > 0) { + + if (s->syslog_fd >= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many /dev/log sockets passed."); + + s->syslog_fd = fd; + + } else if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) { + + if (s->audit_fd >= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many audit sockets passed."); + + s->audit_fd = fd; + + } else { + + if (!fds) { + fds = fdset_new(); + if (!fds) + return log_oom(); + } + + r = fdset_put(fds, fd); + if (r < 0) + return log_oom(); + } + } + + /* Try to restore streams, but don't bother if this fails */ + (void) server_restore_streams(s, fds); + + if (fdset_size(fds) > 0) { + log_warning("%u unknown file descriptors passed, closing.", fdset_size(fds)); + fds = fdset_free(fds); + } + + no_sockets = s->native_fd < 0 && s->stdout_fd < 0 && s->syslog_fd < 0 && s->audit_fd < 0; + + /* always open stdout, syslog, native, and kmsg sockets */ + + /* systemd-journald.socket: /run/systemd/journal/stdout */ + r = server_open_stdout_socket(s); + if (r < 0) + return r; + + /* systemd-journald-dev-log.socket: /run/systemd/journal/dev-log */ + r = server_open_syslog_socket(s); + if (r < 0) + return r; + + /* systemd-journald.socket: /run/systemd/journal/socket */ + r = server_open_native_socket(s); + if (r < 0) + return r; + + /* /dev/kmsg */ + r = server_open_dev_kmsg(s); + if (r < 0) + return r; + + /* Unless we got *some* sockets and not audit, open audit socket */ + if (s->audit_fd >= 0 || no_sockets) { + r = server_open_audit(s); + if (r < 0) + return r; + } + + r = server_open_varlink(s); + if (r < 0) + return r; + + r = server_open_kernel_seqnum(s); + if (r < 0) + return r; + + r = server_open_hostname(s); + if (r < 0) + return r; + + r = setup_signals(s); + if (r < 0) + return r; + + s->ratelimit = journal_ratelimit_new(); + if (!s->ratelimit) + return -ENOMEM; + + r = cg_get_root_path(&s->cgroup_root); + if (r < 0) + return r; + + server_cache_hostname(s); + server_cache_boot_id(s); + server_cache_machine_id(s); + + s->runtime_storage.path = path_join("/run/log/journal", SERVER_MACHINE_ID(s)); + s->system_storage.path = path_join("/var/log/journal", SERVER_MACHINE_ID(s)); + if (!s->runtime_storage.path || !s->system_storage.path) + return -ENOMEM; + + (void) server_connect_notify(s); + + (void) client_context_acquire_default(s); + + return system_journal_open(s, false, false); +} + +void server_maybe_append_tags(Server *s) { +#if HAVE_GCRYPT + JournalFile *f; + Iterator i; + usec_t n; + + n = now(CLOCK_REALTIME); + + if (s->system_journal) + journal_file_maybe_append_tag(s->system_journal, n); + + ORDERED_HASHMAP_FOREACH(f, s->user_journals, i) + journal_file_maybe_append_tag(f, n); +#endif +} + +void server_done(Server *s) { + assert(s); + + set_free_with_destructor(s->deferred_closes, journal_file_close); + + while (s->stdout_streams) + stdout_stream_free(s->stdout_streams); + + client_context_flush_all(s); + + (void) journal_file_close(s->system_journal); + (void) journal_file_close(s->runtime_journal); + + ordered_hashmap_free_with_destructor(s->user_journals, journal_file_close); + + varlink_server_unref(s->varlink_server); + + sd_event_source_unref(s->syslog_event_source); + sd_event_source_unref(s->native_event_source); + sd_event_source_unref(s->stdout_event_source); + sd_event_source_unref(s->dev_kmsg_event_source); + sd_event_source_unref(s->audit_event_source); + sd_event_source_unref(s->sync_event_source); + sd_event_source_unref(s->sigusr1_event_source); + sd_event_source_unref(s->sigusr2_event_source); + sd_event_source_unref(s->sigterm_event_source); + sd_event_source_unref(s->sigint_event_source); + sd_event_source_unref(s->sigrtmin1_event_source); + sd_event_source_unref(s->hostname_event_source); + sd_event_source_unref(s->notify_event_source); + sd_event_source_unref(s->watchdog_event_source); + sd_event_unref(s->event); + + safe_close(s->syslog_fd); + safe_close(s->native_fd); + safe_close(s->stdout_fd); + safe_close(s->dev_kmsg_fd); + safe_close(s->audit_fd); + safe_close(s->hostname_fd); + safe_close(s->notify_fd); + + if (s->ratelimit) + journal_ratelimit_free(s->ratelimit); + + if (s->kernel_seqnum) + munmap(s->kernel_seqnum, sizeof(uint64_t)); + + free(s->buffer); + free(s->tty_path); + free(s->cgroup_root); + free(s->hostname_field); + free(s->runtime_storage.path); + free(s->system_storage.path); + + mmap_cache_unref(s->mmap); +} + +static const char* const storage_table[_STORAGE_MAX] = { + [STORAGE_AUTO] = "auto", + [STORAGE_VOLATILE] = "volatile", + [STORAGE_PERSISTENT] = "persistent", + [STORAGE_NONE] = "none" +}; + +DEFINE_STRING_TABLE_LOOKUP(storage, Storage); +DEFINE_CONFIG_PARSE_ENUM(config_parse_storage, storage, Storage, "Failed to parse storage setting"); + +static const char* const split_mode_table[_SPLIT_MAX] = { + [SPLIT_LOGIN] = "login", + [SPLIT_UID] = "uid", + [SPLIT_NONE] = "none", +}; + +DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode); +DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting"); + +int config_parse_line_max( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + size_t *sz = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) + /* Empty assignment means default */ + *sz = DEFAULT_LINE_MAX; + else { + uint64_t v; + + r = parse_size(rvalue, 1024, &v); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse LineMax= value, ignoring: %s", rvalue); + return 0; + } + + if (v < 79) { + /* Why specify 79 here as minimum line length? Simply, because the most common traditional + * terminal size is 80ch, and it might make sense to break one character before the natural + * line break would occur on that. */ + log_syntax(unit, LOG_WARNING, filename, line, 0, "LineMax= too small, clamping to 79: %s", rvalue); + *sz = 79; + } else if (v > (uint64_t) (SSIZE_MAX-1)) { + /* So, why specify SSIZE_MAX-1 here? Because that's one below the largest size value read() + * can return, and we need one extra byte for the trailing NUL byte. Of course IRL such large + * memory allocations will fail anyway, hence this limit is mostly theoretical anyway, as we'll + * fail much earlier anyway. */ + log_syntax(unit, LOG_WARNING, filename, line, 0, "LineMax= too large, clamping to %" PRIu64 ": %s", (uint64_t) (SSIZE_MAX-1), rvalue); + *sz = SSIZE_MAX-1; + } else + *sz = (size_t) v; + } + + return 0; +} + +int config_parse_compress( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + JournalCompressOptions* compress = data; + int r; + + if (isempty(rvalue)) { + compress->enabled = true; + compress->threshold_bytes = (uint64_t) -1; + } else if (streq(rvalue, "1")) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Compress= ambiguously specified as 1, enabling compression with default threshold"); + compress->enabled = true; + } else if (streq(rvalue, "0")) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Compress= ambiguously specified as 0, disabling compression"); + compress->enabled = false; + } else { + r = parse_boolean(rvalue); + if (r < 0) { + r = parse_size(rvalue, 1024, &compress->threshold_bytes); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse Compress= value, ignoring: %s", rvalue); + else + compress->enabled = true; + } else + compress->enabled = r; + } + + return 0; +} diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h new file mode 100644 index 00000000..a609e9db --- /dev/null +++ b/src/journal/journald-server.h @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-event.h" + +typedef struct Server Server; + +#include "conf-parser.h" +#include "hashmap.h" +#include "journal-file.h" +#include "journald-context.h" +#include "journald-rate-limit.h" +#include "journald-stream.h" +#include "list.h" +#include "prioq.h" +#include "time-util.h" +#include "varlink.h" + +typedef enum Storage { + STORAGE_AUTO, + STORAGE_VOLATILE, + STORAGE_PERSISTENT, + STORAGE_NONE, + _STORAGE_MAX, + _STORAGE_INVALID = -1 +} Storage; + +typedef enum SplitMode { + SPLIT_UID, + SPLIT_LOGIN, /* deprecated */ + SPLIT_NONE, + _SPLIT_MAX, + _SPLIT_INVALID = -1 +} SplitMode; + +typedef struct JournalCompressOptions { + bool enabled; + uint64_t threshold_bytes; +} JournalCompressOptions; + +typedef struct JournalStorageSpace { + usec_t timestamp; + + uint64_t available; + uint64_t limit; + + uint64_t vfs_used; /* space used by journal files */ + uint64_t vfs_available; +} JournalStorageSpace; + +typedef struct JournalStorage { + const char *name; + char *path; + + JournalMetrics metrics; + JournalStorageSpace space; +} JournalStorage; + +struct Server { + int syslog_fd; + int native_fd; + int stdout_fd; + int dev_kmsg_fd; + int audit_fd; + int hostname_fd; + int notify_fd; + + sd_event *event; + + sd_event_source *syslog_event_source; + sd_event_source *native_event_source; + sd_event_source *stdout_event_source; + sd_event_source *dev_kmsg_event_source; + sd_event_source *audit_event_source; + sd_event_source *sync_event_source; + sd_event_source *sigusr1_event_source; + sd_event_source *sigusr2_event_source; + sd_event_source *sigterm_event_source; + sd_event_source *sigint_event_source; + sd_event_source *sigrtmin1_event_source; + sd_event_source *hostname_event_source; + sd_event_source *notify_event_source; + sd_event_source *watchdog_event_source; + + JournalFile *runtime_journal; + JournalFile *system_journal; + OrderedHashmap *user_journals; + + uint64_t seqnum; + + char *buffer; + size_t buffer_size; + + JournalRateLimit *ratelimit; + usec_t sync_interval_usec; + usec_t ratelimit_interval; + unsigned ratelimit_burst; + + JournalStorage runtime_storage; + JournalStorage system_storage; + + JournalCompressOptions compress; + bool seal; + bool read_kmsg; + + bool forward_to_kmsg; + bool forward_to_syslog; + bool forward_to_console; + bool forward_to_wall; + + unsigned n_forward_syslog_missed; + usec_t last_warn_forward_syslog_missed; + + usec_t max_retention_usec; + usec_t max_file_usec; + usec_t oldest_file_usec; + + LIST_HEAD(StdoutStream, stdout_streams); + LIST_HEAD(StdoutStream, stdout_streams_notify_queue); + unsigned n_stdout_streams; + + char *tty_path; + + int max_level_store; + int max_level_syslog; + int max_level_kmsg; + int max_level_console; + int max_level_wall; + + Storage storage; + SplitMode split_mode; + + MMapCache *mmap; + + Set *deferred_closes; + + uint64_t *kernel_seqnum; + bool dev_kmsg_readable:1; + + bool send_watchdog:1; + bool sent_notify_ready:1; + bool sync_scheduled:1; + + char machine_id_field[sizeof("_MACHINE_ID=") + 32]; + char boot_id_field[sizeof("_BOOT_ID=") + 32]; + char *hostname_field; + + /* Cached cgroup root, so that we don't have to query that all the time */ + char *cgroup_root; + + usec_t watchdog_usec; + + usec_t last_realtime_clock; + + size_t line_max; + + /* Caching of client metadata */ + Hashmap *client_contexts; + Prioq *client_contexts_lru; + + usec_t last_cache_pid_flush; + + ClientContext *my_context; /* the context of journald itself */ + ClientContext *pid1_context; /* the context of PID 1 */ + + VarlinkServer *varlink_server; +}; + +#define SERVER_MACHINE_ID(s) ((s)->machine_id_field + STRLEN("_MACHINE_ID=")) + +/* Extra fields for any log messages */ +#define N_IOVEC_META_FIELDS 22 + +/* Extra fields for log messages that contain OBJECT_PID= (i.e. log about another process) */ +#define N_IOVEC_OBJECT_FIELDS 18 + +/* Maximum number of fields we'll add in for driver (i.e. internal) messages */ +#define N_IOVEC_PAYLOAD_FIELDS 16 + +/* kmsg: Maximum number of extra fields we'll import from the kernel's /dev/kmsg */ +#define N_IOVEC_KERNEL_FIELDS 64 + +/* kmsg: Maximum number of extra fields we'll import from udev's devices */ +#define N_IOVEC_UDEV_FIELDS 32 + +void server_dispatch_message(Server *s, struct iovec *iovec, size_t n, size_t m, ClientContext *c, const struct timeval *tv, int priority, pid_t object_pid); +void server_driver_message(Server *s, pid_t object_pid, const char *message_id, const char *format, ...) _sentinel_ _printf_(4,0); + +/* gperf lookup function */ +const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TYPE length); + +CONFIG_PARSER_PROTOTYPE(config_parse_storage); +CONFIG_PARSER_PROTOTYPE(config_parse_line_max); +CONFIG_PARSER_PROTOTYPE(config_parse_compress); + +const char *storage_to_string(Storage s) _const_; +Storage storage_from_string(const char *s) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_split_mode); + +const char *split_mode_to_string(SplitMode s) _const_; +SplitMode split_mode_from_string(const char *s) _pure_; + +int server_init(Server *s); +void server_done(Server *s); +void server_sync(Server *s); +int server_vacuum(Server *s, bool verbose); +void server_rotate(Server *s); +int server_schedule_sync(Server *s, int priority); +int server_flush_to_var(Server *s, bool require_flag_file); +void server_maybe_append_tags(Server *s); +int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata); +void server_space_usage_message(Server *s, JournalStorage *storage); diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c new file mode 100644 index 00000000..22a70ce5 --- /dev/null +++ b/src/journal/journald-stream.c @@ -0,0 +1,922 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#if HAVE_SELINUX +#include +#endif + +#include "sd-daemon.h" +#include "sd-event.h" + +#include "alloc-util.h" +#include "dirent-util.h" +#include "env-file.h" +#include "errno-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "io-util.h" +#include "journald-console.h" +#include "journald-context.h" +#include "journald-kmsg.h" +#include "journald-server.h" +#include "journald-stream.h" +#include "journald-syslog.h" +#include "journald-wall.h" +#include "mkdir.h" +#include "parse-util.h" +#include "process-util.h" +#include "selinux-util.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "syslog-util.h" +#include "tmpfile-util.h" +#include "unit-name.h" + +#define STDOUT_STREAMS_MAX 4096 + +typedef enum StdoutStreamState { + STDOUT_STREAM_IDENTIFIER, + STDOUT_STREAM_UNIT_ID, + STDOUT_STREAM_PRIORITY, + STDOUT_STREAM_LEVEL_PREFIX, + STDOUT_STREAM_FORWARD_TO_SYSLOG, + STDOUT_STREAM_FORWARD_TO_KMSG, + STDOUT_STREAM_FORWARD_TO_CONSOLE, + STDOUT_STREAM_RUNNING +} StdoutStreamState; + +/* The different types of log record terminators: a real \n was read, a NUL character was read, the maximum line length + * was reached, or the end of the stream was reached */ + +typedef enum LineBreak { + LINE_BREAK_NEWLINE, + LINE_BREAK_NUL, + LINE_BREAK_LINE_MAX, + LINE_BREAK_EOF, +} LineBreak; + +struct StdoutStream { + Server *server; + StdoutStreamState state; + + int fd; + + struct ucred ucred; + char *label; + char *identifier; + char *unit_id; + int priority; + bool level_prefix:1; + bool forward_to_syslog:1; + bool forward_to_kmsg:1; + bool forward_to_console:1; + + bool fdstore:1; + bool in_notify_queue:1; + + char *buffer; + size_t length; + size_t allocated; + + sd_event_source *event_source; + + char *state_file; + + ClientContext *context; + + LIST_FIELDS(StdoutStream, stdout_stream); + LIST_FIELDS(StdoutStream, stdout_stream_notify_queue); + + char id_field[STRLEN("_STREAM_ID=") + SD_ID128_STRING_MAX]; +}; + +void stdout_stream_free(StdoutStream *s) { + if (!s) + return; + + if (s->server) { + + if (s->context) + client_context_release(s->server, s->context); + + assert(s->server->n_stdout_streams > 0); + s->server->n_stdout_streams--; + LIST_REMOVE(stdout_stream, s->server->stdout_streams, s); + + if (s->in_notify_queue) + LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s); + } + + if (s->event_source) { + sd_event_source_set_enabled(s->event_source, SD_EVENT_OFF); + s->event_source = sd_event_source_unref(s->event_source); + } + + safe_close(s->fd); + free(s->label); + free(s->identifier); + free(s->unit_id); + free(s->state_file); + free(s->buffer); + + free(s); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free); + +void stdout_stream_destroy(StdoutStream *s) { + if (!s) + return; + + if (s->state_file) + (void) unlink(s->state_file); + + stdout_stream_free(s); +} + +static int stdout_stream_save(StdoutStream *s) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(s); + + if (s->state != STDOUT_STREAM_RUNNING) + return 0; + + if (!s->state_file) { + struct stat st; + + r = fstat(s->fd, &st); + if (r < 0) + return log_warning_errno(errno, "Failed to stat connected stream: %m"); + + /* We use device and inode numbers as identifier for the stream */ + if (asprintf(&s->state_file, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino) < 0) + return log_oom(); + } + + (void) mkdir_p("/run/systemd/journal/streams", 0755); + + r = fopen_temporary(s->state_file, &f, &temp_path); + if (r < 0) + goto fail; + + fprintf(f, + "# This is private data. Do not parse\n" + "PRIORITY=%i\n" + "LEVEL_PREFIX=%i\n" + "FORWARD_TO_SYSLOG=%i\n" + "FORWARD_TO_KMSG=%i\n" + "FORWARD_TO_CONSOLE=%i\n" + "STREAM_ID=%s\n", + s->priority, + s->level_prefix, + s->forward_to_syslog, + s->forward_to_kmsg, + s->forward_to_console, + s->id_field + STRLEN("_STREAM_ID=")); + + if (!isempty(s->identifier)) { + _cleanup_free_ char *escaped; + + escaped = cescape(s->identifier); + if (!escaped) { + r = -ENOMEM; + goto fail; + } + + fprintf(f, "IDENTIFIER=%s\n", escaped); + } + + if (!isempty(s->unit_id)) { + _cleanup_free_ char *escaped; + + escaped = cescape(s->unit_id); + if (!escaped) { + r = -ENOMEM; + goto fail; + } + + fprintf(f, "UNIT=%s\n", escaped); + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, s->state_file) < 0) { + r = -errno; + goto fail; + } + + if (!s->fdstore && !s->in_notify_queue) { + LIST_PREPEND(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s); + s->in_notify_queue = true; + + if (s->server->notify_event_source) { + r = sd_event_source_set_enabled(s->server->notify_event_source, SD_EVENT_ON); + if (r < 0) + log_warning_errno(r, "Failed to enable notify event source: %m"); + } + } + + return 0; + +fail: + (void) unlink(s->state_file); + + if (temp_path) + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file); +} + +static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_break) { + struct iovec *iovec; + int priority; + char syslog_priority[] = "PRIORITY=\0"; + char syslog_facility[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int) + 1]; + _cleanup_free_ char *message = NULL, *syslog_identifier = NULL; + size_t n = 0, m; + int r; + + assert(s); + assert(p); + + if (s->context) + (void) client_context_maybe_refresh(s->server, s->context, NULL, NULL, 0, NULL, USEC_INFINITY); + else if (pid_is_valid(s->ucred.pid)) { + r = client_context_acquire(s->server, s->ucred.pid, &s->ucred, s->label, strlen_ptr(s->label), s->unit_id, &s->context); + if (r < 0) + log_warning_errno(r, "Failed to acquire client context, ignoring: %m"); + } + + priority = s->priority; + + if (s->level_prefix) + syslog_parse_priority(&p, &priority, false); + + if (!client_context_test_priority(s->context, priority)) + return 0; + + if (isempty(p)) + return 0; + + if (s->forward_to_syslog || s->server->forward_to_syslog) + server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL); + + if (s->forward_to_kmsg || s->server->forward_to_kmsg) + server_forward_kmsg(s->server, priority, s->identifier, p, &s->ucred); + + if (s->forward_to_console || s->server->forward_to_console) + server_forward_console(s->server, priority, s->identifier, p, &s->ucred); + + if (s->server->forward_to_wall) + server_forward_wall(s->server, priority, s->identifier, p, &s->ucred); + + m = N_IOVEC_META_FIELDS + 7 + client_context_extra_fields_n_iovec(s->context); + iovec = newa(struct iovec, m); + + iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=stdout"); + iovec[n++] = IOVEC_MAKE_STRING(s->id_field); + + syslog_priority[STRLEN("PRIORITY=")] = '0' + LOG_PRI(priority); + iovec[n++] = IOVEC_MAKE_STRING(syslog_priority); + + if (priority & LOG_FACMASK) { + xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)); + iovec[n++] = IOVEC_MAKE_STRING(syslog_facility); + } + + if (s->identifier) { + syslog_identifier = strjoin("SYSLOG_IDENTIFIER=", s->identifier); + if (syslog_identifier) + iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier); + } + + if (line_break != LINE_BREAK_NEWLINE) { + const char *c; + + /* If this log message was generated due to an uncommon line break then mention this in the log + * entry */ + + c = line_break == LINE_BREAK_NUL ? "_LINE_BREAK=nul" : + line_break == LINE_BREAK_LINE_MAX ? "_LINE_BREAK=line-max" : + "_LINE_BREAK=eof"; + iovec[n++] = IOVEC_MAKE_STRING(c); + } + + message = strjoin("MESSAGE=", p); + if (message) + iovec[n++] = IOVEC_MAKE_STRING(message); + + server_dispatch_message(s->server, iovec, n, m, s->context, NULL, priority, 0); + return 0; +} + +static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { + int r; + char *orig; + + assert(s); + assert(p); + + orig = p; + p = strstrip(p); + + /* line breaks by NUL, line max length or EOF are not permissible during the negotiation part of the protocol */ + if (line_break != LINE_BREAK_NEWLINE && s->state != STDOUT_STREAM_RUNNING) { + log_warning("Control protocol line not properly terminated."); + return -EINVAL; + } + + switch (s->state) { + + case STDOUT_STREAM_IDENTIFIER: + if (!isempty(p)) { + s->identifier = strdup(p); + if (!s->identifier) + return log_oom(); + } + + s->state = STDOUT_STREAM_UNIT_ID; + return 0; + + case STDOUT_STREAM_UNIT_ID: + if (s->ucred.uid == 0 && + unit_name_is_valid(p, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) { + + s->unit_id = strdup(p); + if (!s->unit_id) + return log_oom(); + } + + s->state = STDOUT_STREAM_PRIORITY; + return 0; + + case STDOUT_STREAM_PRIORITY: + r = safe_atoi(p, &s->priority); + if (r < 0 || s->priority < 0 || s->priority > 999) { + log_warning("Failed to parse log priority line."); + return -EINVAL; + } + + s->state = STDOUT_STREAM_LEVEL_PREFIX; + return 0; + + case STDOUT_STREAM_LEVEL_PREFIX: + r = parse_boolean(p); + if (r < 0) { + log_warning("Failed to parse level prefix line."); + return -EINVAL; + } + + s->level_prefix = r; + s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG; + return 0; + + case STDOUT_STREAM_FORWARD_TO_SYSLOG: + r = parse_boolean(p); + if (r < 0) { + log_warning("Failed to parse forward to syslog line."); + return -EINVAL; + } + + s->forward_to_syslog = r; + s->state = STDOUT_STREAM_FORWARD_TO_KMSG; + return 0; + + case STDOUT_STREAM_FORWARD_TO_KMSG: + r = parse_boolean(p); + if (r < 0) { + log_warning("Failed to parse copy to kmsg line."); + return -EINVAL; + } + + s->forward_to_kmsg = r; + s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE; + return 0; + + case STDOUT_STREAM_FORWARD_TO_CONSOLE: + r = parse_boolean(p); + if (r < 0) { + log_warning("Failed to parse copy to console line."); + return -EINVAL; + } + + s->forward_to_console = r; + s->state = STDOUT_STREAM_RUNNING; + + /* Try to save the stream, so that journald can be restarted and we can recover */ + (void) stdout_stream_save(s); + return 0; + + case STDOUT_STREAM_RUNNING: + return stdout_stream_log(s, orig, line_break); + } + + assert_not_reached("Unknown stream state"); +} + +static int stdout_stream_scan(StdoutStream *s, bool force_flush) { + char *p; + size_t remaining; + int r; + + assert(s); + + p = s->buffer; + remaining = s->length; + + /* XXX: This function does nothing if (s->length == 0) */ + + for (;;) { + LineBreak line_break; + size_t skip; + char *end1, *end2; + + end1 = memchr(p, '\n', remaining); + end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : remaining); + + if (end2) { + /* We found a NUL terminator */ + skip = end2 - p + 1; + line_break = LINE_BREAK_NUL; + } else if (end1) { + /* We found a \n terminator */ + *end1 = 0; + skip = end1 - p + 1; + line_break = LINE_BREAK_NEWLINE; + } else if (remaining >= s->server->line_max) { + /* Force a line break after the maximum line length */ + *(p + s->server->line_max) = 0; + skip = remaining; + line_break = LINE_BREAK_LINE_MAX; + } else + break; + + r = stdout_stream_line(s, p, line_break); + if (r < 0) + return r; + + remaining -= skip; + p += skip; + } + + if (force_flush && remaining > 0) { + p[remaining] = 0; + r = stdout_stream_line(s, p, LINE_BREAK_EOF); + if (r < 0) + return r; + + p += remaining; + remaining = 0; + } + + if (p > s->buffer) { + memmove(s->buffer, p, remaining); + s->length = remaining; + } + + return 0; +} + +static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; + StdoutStream *s = userdata; + struct ucred *ucred = NULL; + struct cmsghdr *cmsg; + struct iovec iovec; + size_t limit; + ssize_t l; + int r; + + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_control = buf, + .msg_controllen = sizeof(buf), + }; + + assert(s); + + if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) { + log_error("Got invalid event from epoll for stdout stream: %"PRIx32, revents); + goto terminate; + } + + /* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */ + if (s->length + 1 >= s->allocated) { + if (!GREEDY_REALLOC(s->buffer, s->allocated, s->length + 1 + 1024)) { + log_oom(); + goto terminate; + } + } + + /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also, + * always leave room for a terminating NUL we might need to add. */ + limit = MIN(s->allocated - 1, s->server->line_max); + + iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length); + + l = recvmsg(s->fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (l < 0) { + if (IN_SET(errno, EINTR, EAGAIN)) + return 0; + + log_warning_errno(errno, "Failed to read from stream: %m"); + goto terminate; + } + cmsg_close_all(&msghdr); + + if (l == 0) { + stdout_stream_scan(s, true); + goto terminate; + } + + CMSG_FOREACH(cmsg, &msghdr) + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + ucred = (struct ucred *)CMSG_DATA(cmsg); + break; + } + + /* Invalidate the context if the pid of the sender changed. + * This happens when a forked process inherits stdout / stderr + * from a parent. In this case getpeercred returns the ucred + * of the parent, which can be invalid if the parent has exited + * in the meantime. + */ + if (ucred && ucred->pid != s->ucred.pid) { + /* force out any previously half-written lines from a + * different process, before we switch to the new ucred + * structure for everything we just added */ + r = stdout_stream_scan(s, true); + if (r < 0) + goto terminate; + + s->ucred = *ucred; + client_context_release(s->server, s->context); + s->context = NULL; + } + + s->length += l; + r = stdout_stream_scan(s, false); + if (r < 0) + goto terminate; + + return 1; + +terminate: + stdout_stream_destroy(s); + return 0; +} + +int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { + _cleanup_(stdout_stream_freep) StdoutStream *stream = NULL; + sd_id128_t id; + int r; + + assert(s); + assert(fd >= 0); + + r = sd_id128_randomize(&id); + if (r < 0) + return log_error_errno(r, "Failed to generate stream ID: %m"); + + stream = new0(StdoutStream, 1); + if (!stream) + return log_oom(); + + stream->fd = -1; + stream->priority = LOG_INFO; + + xsprintf(stream->id_field, "_STREAM_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)); + + r = getpeercred(fd, &stream->ucred); + if (r < 0) + return log_error_errno(r, "Failed to determine peer credentials: %m"); + + r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return log_error_errno(r, "SO_PASSCRED failed: %m"); + + if (mac_selinux_use()) { + r = getpeersec(fd, &stream->label); + if (r < 0 && r != -EOPNOTSUPP) + (void) log_warning_errno(r, "Failed to determine peer security context: %m"); + } + + (void) shutdown(fd, SHUT_WR); + + r = sd_event_add_io(s->event, &stream->event_source, fd, EPOLLIN, stdout_stream_process, stream); + if (r < 0) + return log_error_errno(r, "Failed to add stream to event loop: %m"); + + r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5); + if (r < 0) + return log_error_errno(r, "Failed to adjust stdout event source priority: %m"); + + stream->fd = fd; + + stream->server = s; + LIST_PREPEND(stdout_stream, s->stdout_streams, stream); + s->n_stdout_streams++; + + if (ret) + *ret = stream; + + stream = NULL; + + return 0; +} + +static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revents, void *userdata) { + _cleanup_close_ int fd = -1; + Server *s = userdata; + int r; + + assert(s); + + if (revents != EPOLLIN) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Got invalid event from epoll for stdout server fd: %" PRIx32, + revents); + + fd = accept4(s->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); + if (fd < 0) { + if (ERRNO_IS_ACCEPT_AGAIN(errno)) + return 0; + + return log_error_errno(errno, "Failed to accept stdout connection: %m"); + } + + if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) { + struct ucred u; + + r = getpeercred(fd, &u); + + /* By closing fd here we make sure that the client won't wait too long for journald to + * gather all the data it adds to the error message to find out that the connection has + * just been refused. + */ + fd = safe_close(fd); + + server_driver_message(s, r < 0 ? 0 : u.pid, NULL, LOG_MESSAGE("Too many stdout streams, refusing connection."), NULL); + return 0; + } + + r = stdout_stream_install(s, fd, NULL); + if (r < 0) + return r; + + fd = -1; + return 0; +} + +static int stdout_stream_load(StdoutStream *stream, const char *fname) { + _cleanup_free_ char + *priority = NULL, + *level_prefix = NULL, + *forward_to_syslog = NULL, + *forward_to_kmsg = NULL, + *forward_to_console = NULL, + *stream_id = NULL; + int r; + + assert(stream); + assert(fname); + + if (!stream->state_file) { + stream->state_file = path_join("/run/systemd/journal/streams", fname); + if (!stream->state_file) + return log_oom(); + } + + r = parse_env_file(NULL, stream->state_file, + "PRIORITY", &priority, + "LEVEL_PREFIX", &level_prefix, + "FORWARD_TO_SYSLOG", &forward_to_syslog, + "FORWARD_TO_KMSG", &forward_to_kmsg, + "FORWARD_TO_CONSOLE", &forward_to_console, + "IDENTIFIER", &stream->identifier, + "UNIT", &stream->unit_id, + "STREAM_ID", &stream_id); + if (r < 0) + return log_error_errno(r, "Failed to read: %s", stream->state_file); + + if (priority) { + int p; + + p = log_level_from_string(priority); + if (p >= 0) + stream->priority = p; + } + + if (level_prefix) { + r = parse_boolean(level_prefix); + if (r >= 0) + stream->level_prefix = r; + } + + if (forward_to_syslog) { + r = parse_boolean(forward_to_syslog); + if (r >= 0) + stream->forward_to_syslog = r; + } + + if (forward_to_kmsg) { + r = parse_boolean(forward_to_kmsg); + if (r >= 0) + stream->forward_to_kmsg = r; + } + + if (forward_to_console) { + r = parse_boolean(forward_to_console); + if (r >= 0) + stream->forward_to_console = r; + } + + if (stream_id) { + sd_id128_t id; + + r = sd_id128_from_string(stream_id, &id); + if (r >= 0) + xsprintf(stream->id_field, "_STREAM_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)); + } + + return 0; +} + +static int stdout_stream_restore(Server *s, const char *fname, int fd) { + StdoutStream *stream; + int r; + + assert(s); + assert(fname); + assert(fd >= 0); + + if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) { + log_warning("Too many stdout streams, refusing restoring of stream."); + return -ENOBUFS; + } + + r = stdout_stream_install(s, fd, &stream); + if (r < 0) + return r; + + stream->state = STDOUT_STREAM_RUNNING; + stream->fdstore = true; + + /* Ignore all parsing errors */ + (void) stdout_stream_load(stream, fname); + + return 0; +} + +int server_restore_streams(Server *s, FDSet *fds) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r; + + d = opendir("/run/systemd/journal/streams"); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to enumerate /run/systemd/journal/streams: %m"); + } + + FOREACH_DIRENT(de, d, goto fail) { + unsigned long st_dev, st_ino; + bool found = false; + Iterator i; + int fd; + + if (sscanf(de->d_name, "%lu:%lu", &st_dev, &st_ino) != 2) + continue; + + FDSET_FOREACH(fd, fds, i) { + struct stat st; + + if (fstat(fd, &st) < 0) + return log_error_errno(errno, "Failed to stat %s: %m", de->d_name); + + if (S_ISSOCK(st.st_mode) && st.st_dev == st_dev && st.st_ino == st_ino) { + found = true; + break; + } + } + + if (!found) { + /* No file descriptor? Then let's delete the state file */ + log_debug("Cannot restore stream file %s", de->d_name); + if (unlinkat(dirfd(d), de->d_name, 0) < 0) + log_warning_errno(errno, "Failed to remove /run/systemd/journal/streams/%s: %m", + de->d_name); + continue; + } + + fdset_remove(fds, fd); + + r = stdout_stream_restore(s, de->d_name, fd); + if (r < 0) + safe_close(fd); + } + + return 0; + +fail: + return log_error_errno(errno, "Failed to read streams directory: %m"); +} + +int server_open_stdout_socket(Server *s) { + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/stdout", + }; + int r; + + assert(s); + + if (s->stdout_fd < 0) { + s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s->stdout_fd < 0) + return log_error_errno(errno, "socket() failed: %m"); + + (void) sockaddr_un_unlink(&sa.un); + + r = bind(s->stdout_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); + + (void) chmod(sa.un.sun_path, 0666); + + if (listen(s->stdout_fd, SOMAXCONN) < 0) + return log_error_errno(errno, "listen(%s) failed: %m", sa.un.sun_path); + } else + (void) fd_nonblock(s->stdout_fd, true); + + r = sd_event_add_io(s->event, &s->stdout_event_source, s->stdout_fd, EPOLLIN, stdout_stream_new, s); + if (r < 0) + return log_error_errno(r, "Failed to add stdout server fd to event source: %m"); + + r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+5); + if (r < 0) + return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m"); + + return 0; +} + +void stdout_stream_send_notify(StdoutStream *s) { + struct iovec iovec = { + .iov_base = (char*) "FDSTORE=1", + .iov_len = STRLEN("FDSTORE=1"), + }; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + }; + struct cmsghdr *cmsg; + ssize_t l; + + assert(s); + assert(!s->fdstore); + assert(s->in_notify_queue); + assert(s->server); + assert(s->server->notify_fd >= 0); + + /* Store the connection fd in PID 1, so that we get it passed + * in again on next start */ + + msghdr.msg_controllen = CMSG_SPACE(sizeof(int)); + msghdr.msg_control = alloca0(msghdr.msg_controllen); + + cmsg = CMSG_FIRSTHDR(&msghdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + + memcpy(CMSG_DATA(cmsg), &s->fd, sizeof(int)); + + l = sendmsg(s->server->notify_fd, &msghdr, MSG_DONTWAIT|MSG_NOSIGNAL); + if (l < 0) { + if (errno == EAGAIN) + return; + + log_error_errno(errno, "Failed to send stream file descriptor to service manager: %m"); + } else { + log_debug("Successfully sent stream file descriptor to service manager."); + s->fdstore = 1; + } + + LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s); + s->in_notify_queue = false; + +} diff --git a/src/journal/journald-stream.h b/src/journal/journald-stream.h new file mode 100644 index 00000000..487376e7 --- /dev/null +++ b/src/journal/journald-stream.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct StdoutStream StdoutStream; + +#include "fdset.h" +#include "journald-server.h" + +int server_open_stdout_socket(Server *s); +int server_restore_streams(Server *s, FDSet *fds); + +void stdout_stream_free(StdoutStream *s); +int stdout_stream_install(Server *s, int fd, StdoutStream **ret); +void stdout_stream_destroy(StdoutStream *s); +void stdout_stream_send_notify(StdoutStream *s); diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c new file mode 100644 index 00000000..a60a259b --- /dev/null +++ b/src/journal/journald-syslog.c @@ -0,0 +1,516 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "io-util.h" +#include "journald-console.h" +#include "journald-kmsg.h" +#include "journald-server.h" +#include "journald-syslog.h" +#include "journald-wall.h" +#include "process-util.h" +#include "selinux-util.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "syslog-util.h" + +/* Warn once every 30s if we missed syslog message */ +#define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC) + +static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, const struct ucred *ucred, const struct timeval *tv) { + + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/syslog", + }; + struct msghdr msghdr = { + .msg_iov = (struct iovec *) iovec, + .msg_iovlen = n_iovec, + .msg_name = (struct sockaddr*) &sa.sa, + .msg_namelen = SOCKADDR_UN_LEN(sa.un), + }; + struct cmsghdr *cmsg; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; + } control; + + assert(s); + assert(iovec); + assert(n_iovec > 0); + + if (ucred) { + zero(control); + msghdr.msg_control = &control; + msghdr.msg_controllen = sizeof(control); + + cmsg = CMSG_FIRSTHDR(&msghdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); + memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred)); + msghdr.msg_controllen = cmsg->cmsg_len; + } + + /* Forward the syslog message we received via /dev/log to + * /run/systemd/syslog. Unfortunately we currently can't set + * the SO_TIMESTAMP auxiliary data, and hence we don't. */ + + if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0) + return; + + /* The socket is full? I guess the syslog implementation is + * too slow, and we shouldn't wait for that... */ + if (errno == EAGAIN) { + s->n_forward_syslog_missed++; + return; + } + + if (ucred && IN_SET(errno, ESRCH, EPERM)) { + struct ucred u; + + /* Hmm, presumably the sender process vanished + * by now, or we don't have CAP_SYS_AMDIN, so + * let's fix it as good as we can, and retry */ + + u = *ucred; + u.pid = getpid_cached(); + memcpy(CMSG_DATA(cmsg), &u, sizeof(struct ucred)); + + if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0) + return; + + if (errno == EAGAIN) { + s->n_forward_syslog_missed++; + return; + } + } + + if (errno != ENOENT) + log_debug_errno(errno, "Failed to forward syslog message: %m"); +} + +static void forward_syslog_raw(Server *s, int priority, const char *buffer, size_t buffer_len, const struct ucred *ucred, const struct timeval *tv) { + struct iovec iovec; + + assert(s); + assert(buffer); + + if (LOG_PRI(priority) > s->max_level_syslog) + return; + + iovec = IOVEC_MAKE((char *) buffer, buffer_len); + forward_syslog_iovec(s, &iovec, 1, ucred, tv); +} + +void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred, const struct timeval *tv) { + struct iovec iovec[5]; + char header_priority[DECIMAL_STR_MAX(priority) + 3], header_time[64], + header_pid[STRLEN("[]: ") + DECIMAL_STR_MAX(pid_t) + 1]; + int n = 0; + time_t t; + struct tm tm; + _cleanup_free_ char *ident_buf = NULL; + + assert(s); + assert(priority >= 0); + assert(priority <= 999); + assert(message); + + if (LOG_PRI(priority) > s->max_level_syslog) + return; + + /* First: priority field */ + xsprintf(header_priority, "<%i>", priority); + iovec[n++] = IOVEC_MAKE_STRING(header_priority); + + /* Second: timestamp */ + t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC)); + if (!localtime_r(&t, &tm)) + return; + if (strftime(header_time, sizeof(header_time), "%h %e %T ", &tm) <= 0) + return; + iovec[n++] = IOVEC_MAKE_STRING(header_time); + + /* Third: identifier and PID */ + if (ucred) { + if (!identifier) { + get_process_comm(ucred->pid, &ident_buf); + identifier = ident_buf; + } + + xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid); + + if (identifier) + iovec[n++] = IOVEC_MAKE_STRING(identifier); + + iovec[n++] = IOVEC_MAKE_STRING(header_pid); + } else if (identifier) { + iovec[n++] = IOVEC_MAKE_STRING(identifier); + iovec[n++] = IOVEC_MAKE_STRING(": "); + } + + /* Fourth: message */ + iovec[n++] = IOVEC_MAKE_STRING(message); + + forward_syslog_iovec(s, iovec, n, ucred, tv); +} + +int syslog_fixup_facility(int priority) { + + if ((priority & LOG_FACMASK) == 0) + return (priority & LOG_PRIMASK) | LOG_USER; + + return priority; +} + +size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid) { + const char *p; + char *t; + size_t l, e; + + assert(buf); + assert(identifier); + assert(pid); + + p = *buf; + + p += strspn(p, WHITESPACE); + l = strcspn(p, WHITESPACE); + + if (l <= 0 || + p[l-1] != ':') + return 0; + + e = l; + l--; + + if (l > 0 && p[l-1] == ']') { + size_t k = l-1; + + for (;;) { + + if (p[k] == '[') { + t = strndup(p+k+1, l-k-2); + if (t) + *pid = t; + + l = k; + break; + } + + if (k == 0) + break; + + k--; + } + } + + t = strndup(p, l); + if (t) + *identifier = t; + + /* Single space is used as separator */ + if (p[e] != '\0' && strchr(WHITESPACE, p[e])) + e++; + + l = (p - *buf) + e; + *buf = p + e; + return l; +} + +static int syslog_skip_timestamp(const char **buf) { + enum { + LETTER, + SPACE, + NUMBER, + SPACE_OR_NUMBER, + COLON + } sequence[] = { + LETTER, LETTER, LETTER, + SPACE, + SPACE_OR_NUMBER, NUMBER, + SPACE, + SPACE_OR_NUMBER, NUMBER, + COLON, + SPACE_OR_NUMBER, NUMBER, + COLON, + SPACE_OR_NUMBER, NUMBER, + SPACE + }; + + const char *p, *t; + unsigned i; + + assert(buf); + assert(*buf); + + for (i = 0, p = *buf; i < ELEMENTSOF(sequence); i++, p++) { + if (!*p) + return 0; + + switch (sequence[i]) { + + case SPACE: + if (*p != ' ') + return 0; + break; + + case SPACE_OR_NUMBER: + if (*p == ' ') + break; + + _fallthrough_; + case NUMBER: + if (*p < '0' || *p > '9') + return 0; + + break; + + case LETTER: + if (!(*p >= 'A' && *p <= 'Z') && + !(*p >= 'a' && *p <= 'z')) + return 0; + + break; + + case COLON: + if (*p != ':') + return 0; + break; + + } + } + + t = *buf; + *buf = p; + return p - t; +} + +void server_process_syslog_message( + Server *s, + const char *buf, + size_t raw_len, + const struct ucred *ucred, + const struct timeval *tv, + const char *label, + size_t label_len) { + + char *t, syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)], + syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)]; + const char *msg, *syslog_ts, *a; + _cleanup_free_ char *identifier = NULL, *pid = NULL, + *dummy = NULL, *msg_msg = NULL, *msg_raw = NULL; + int priority = LOG_USER | LOG_INFO, r; + ClientContext *context = NULL; + struct iovec *iovec; + size_t n = 0, m, i, leading_ws, syslog_ts_len; + bool store_raw; + + assert(s); + assert(buf); + /* The message cannot be empty. */ + assert(raw_len > 0); + /* The buffer NUL-terminated and can be used a string. raw_len is the length + * without the terminating NUL byte, the buffer is actually one bigger. */ + assert(buf[raw_len] == '\0'); + + if (ucred && pid_is_valid(ucred->pid)) { + r = client_context_get(s, ucred->pid, ucred, label, label_len, NULL, &context); + if (r < 0) + log_warning_errno(r, "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", ucred->pid); + } + + /* We are creating a copy of the message because we want to forward the original message + verbatim to the legacy syslog implementation */ + for (i = raw_len; i > 0; i--) + if (!strchr(WHITESPACE, buf[i-1])) + break; + + leading_ws = strspn(buf, WHITESPACE); + + if (i == 0) + /* The message contains only whitespaces */ + msg = buf + raw_len; + else if (i == raw_len) + /* Nice! No need to strip anything on the end, let's optimize this a bit */ + msg = buf + leading_ws; + else { + msg = dummy = new(char, i - leading_ws + 1); + if (!dummy) { + log_oom(); + return; + } + + memcpy(dummy, buf + leading_ws, i - leading_ws); + dummy[i - leading_ws] = 0; + } + + /* We will add the SYSLOG_RAW= field when we stripped anything + * _or_ if the input message contained NUL bytes. */ + store_raw = msg != buf || strlen(msg) != raw_len; + + syslog_parse_priority(&msg, &priority, true); + + if (!client_context_test_priority(context, priority)) + return; + + syslog_ts = msg; + syslog_ts_len = syslog_skip_timestamp(&msg); + if (syslog_ts_len == 0) + /* We failed to parse the full timestamp, store the raw message too */ + store_raw = true; + + syslog_parse_identifier(&msg, &identifier, &pid); + + if (s->forward_to_syslog) + forward_syslog_raw(s, priority, buf, raw_len, ucred, tv); + + if (s->forward_to_kmsg) + server_forward_kmsg(s, priority, identifier, msg, ucred); + + if (s->forward_to_console) + server_forward_console(s, priority, identifier, msg, ucred); + + if (s->forward_to_wall) + server_forward_wall(s, priority, identifier, msg, ucred); + + m = N_IOVEC_META_FIELDS + 8 + client_context_extra_fields_n_iovec(context); + iovec = newa(struct iovec, m); + + iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=syslog"); + + xsprintf(syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK); + iovec[n++] = IOVEC_MAKE_STRING(syslog_priority); + + if (priority & LOG_FACMASK) { + xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)); + iovec[n++] = IOVEC_MAKE_STRING(syslog_facility); + } + + if (identifier) { + a = strjoina("SYSLOG_IDENTIFIER=", identifier); + iovec[n++] = IOVEC_MAKE_STRING(a); + } + + if (pid) { + a = strjoina("SYSLOG_PID=", pid); + iovec[n++] = IOVEC_MAKE_STRING(a); + } + + if (syslog_ts_len > 0) { + const size_t hlen = STRLEN("SYSLOG_TIMESTAMP="); + + t = newa(char, hlen + syslog_ts_len); + memcpy(t, "SYSLOG_TIMESTAMP=", hlen); + memcpy(t + hlen, syslog_ts, syslog_ts_len); + + iovec[n++] = IOVEC_MAKE(t, hlen + syslog_ts_len); + } + + msg_msg = strjoin("MESSAGE=", msg); + if (!msg_msg) { + log_oom(); + return; + } + iovec[n++] = IOVEC_MAKE_STRING(msg_msg); + + if (store_raw) { + const size_t hlen = STRLEN("SYSLOG_RAW="); + + msg_raw = new(char, hlen + raw_len); + if (!msg_raw) { + log_oom(); + return; + } + + memcpy(msg_raw, "SYSLOG_RAW=", hlen); + memcpy(msg_raw + hlen, buf, raw_len); + + iovec[n++] = IOVEC_MAKE(msg_raw, hlen + raw_len); + } + + server_dispatch_message(s, iovec, n, m, context, tv, priority, 0); +} + +int server_open_syslog_socket(Server *s) { + + static const union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/systemd/journal/dev-log", + }; + int r; + + assert(s); + + if (s->syslog_fd < 0) { + s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s->syslog_fd < 0) + return log_error_errno(errno, "socket() failed: %m"); + + (void) sockaddr_un_unlink(&sa.un); + + r = bind(s->syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); + + (void) chmod(sa.un.sun_path, 0666); + } else + (void) fd_nonblock(s->syslog_fd, true); + + r = setsockopt_int(s->syslog_fd, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return log_error_errno(r, "SO_PASSCRED failed: %m"); + +#if HAVE_SELINUX + if (mac_selinux_use()) { + r = setsockopt_int(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, true); + if (r < 0) + log_warning_errno(r, "SO_PASSSEC failed: %m"); + } +#endif + + r = setsockopt_int(s->syslog_fd, SOL_SOCKET, SO_TIMESTAMP, true); + if (r < 0) + return log_error_errno(r, "SO_TIMESTAMP failed: %m"); + + r = sd_event_add_io(s->event, &s->syslog_event_source, s->syslog_fd, EPOLLIN, server_process_datagram, s); + if (r < 0) + return log_error_errno(r, "Failed to add syslog server fd to event loop: %m"); + + r = sd_event_source_set_priority(s->syslog_event_source, SD_EVENT_PRIORITY_NORMAL+5); + if (r < 0) + return log_error_errno(r, "Failed to adjust syslog event source priority: %m"); + + return 0; +} + +void server_maybe_warn_forward_syslog_missed(Server *s) { + usec_t n; + + assert(s); + + if (s->n_forward_syslog_missed <= 0) + return; + + n = now(CLOCK_MONOTONIC); + if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC > n) + return; + + server_driver_message(s, 0, + "MESSAGE_ID=" SD_MESSAGE_FORWARD_SYSLOG_MISSED_STR, + LOG_MESSAGE("Forwarding to syslog missed %u messages.", + s->n_forward_syslog_missed), + NULL); + + s->n_forward_syslog_missed = 0; + s->last_warn_forward_syslog_missed = n; +} diff --git a/src/journal/journald-syslog.h b/src/journal/journald-syslog.h new file mode 100644 index 00000000..7ca58972 --- /dev/null +++ b/src/journal/journald-syslog.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "journald-server.h" + +int syslog_fixup_facility(int priority) _const_; + +size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid); + +void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred, const struct timeval *tv); + +void server_process_syslog_message(Server *s, const char *buf, size_t buf_len, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len); +int server_open_syslog_socket(Server *s); + +void server_maybe_warn_forward_syslog_missed(Server *s); diff --git a/src/journal/journald-wall.c b/src/journal/journald-wall.c new file mode 100644 index 00000000..370c9b32 --- /dev/null +++ b/src/journal/journald-wall.c @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "format-util.h" +#include "journald-server.h" +#include "journald-wall.h" +#include "process-util.h" +#include "string-util.h" +#include "utmp-wtmp.h" + +void server_forward_wall( + Server *s, + int priority, + const char *identifier, + const char *message, + const struct ucred *ucred) { + + _cleanup_free_ char *ident_buf = NULL, *l_buf = NULL; + const char *l; + int r; + + assert(s); + assert(message); + + if (LOG_PRI(priority) > s->max_level_wall) + return; + + if (ucred) { + if (!identifier) { + get_process_comm(ucred->pid, &ident_buf); + identifier = ident_buf; + } + + if (asprintf(&l_buf, "%s["PID_FMT"]: %s", strempty(identifier), ucred->pid, message) < 0) { + log_oom(); + return; + } + + l = l_buf; + + } else if (identifier) { + + l = l_buf = strjoin(identifier, ": ", message); + if (!l_buf) { + log_oom(); + return; + } + } else + l = message; + + r = utmp_wall(l, "systemd-journald", NULL, NULL, NULL); + if (r < 0) + log_debug_errno(r, "Failed to send wall message: %m"); +} diff --git a/src/journal/journald-wall.h b/src/journal/journald-wall.h new file mode 100644 index 00000000..026649eb --- /dev/null +++ b/src/journal/journald-wall.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "journald-server.h" + +void server_forward_wall(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred); diff --git a/src/journal/journald.c b/src/journal/journald.c new file mode 100644 index 00000000..5e7b1dcb --- /dev/null +++ b/src/journal/journald.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-daemon.h" +#include "sd-messages.h" + +#include "format-util.h" +#include "journal-authenticate.h" +#include "journald-kmsg.h" +#include "journald-server.h" +#include "journald-syslog.h" +#include "process-util.h" +#include "sigbus.h" + +int main(int argc, char *argv[]) { + Server server; + int r; + + if (argc > 1) { + log_error("This program does not take arguments."); + return EXIT_FAILURE; + } + + log_set_prohibit_ipc(true); + log_set_target(LOG_TARGET_AUTO); + log_set_facility(LOG_SYSLOG); + log_parse_environment(); + log_open(); + + umask(0022); + + sigbus_install(); + + r = server_init(&server); + if (r < 0) + goto finish; + + server_vacuum(&server, false); + server_flush_to_var(&server, true); + server_flush_dev_kmsg(&server); + + log_debug("systemd-journald running as pid "PID_FMT, getpid_cached()); + server_driver_message(&server, 0, + "MESSAGE_ID=" SD_MESSAGE_JOURNAL_START_STR, + LOG_MESSAGE("Journal started"), + NULL); + + /* Make sure to send the usage message *after* flushing the + * journal so entries from the runtime journals are ordered + * before this message. See #4190 for some details. */ + server_space_usage_message(&server, NULL); + + for (;;) { + usec_t t = USEC_INFINITY, n; + + r = sd_event_get_state(server.event); + if (r < 0) + goto finish; + if (r == SD_EVENT_FINISHED) + break; + + n = now(CLOCK_REALTIME); + + if (server.max_retention_usec > 0 && server.oldest_file_usec > 0) { + + /* The retention time is reached, so let's vacuum! */ + if (server.oldest_file_usec + server.max_retention_usec < n) { + log_info("Retention time reached."); + server_rotate(&server); + server_vacuum(&server, false); + continue; + } + + /* Calculate when to rotate the next time */ + t = server.oldest_file_usec + server.max_retention_usec - n; + } + +#if HAVE_GCRYPT + if (server.system_journal) { + usec_t u; + + if (journal_file_next_evolve_usec(server.system_journal, &u)) { + if (n >= u) + t = 0; + else + t = MIN(t, u - n); + } + } +#endif + + r = sd_event_run(server.event, t); + if (r < 0) { + log_error_errno(r, "Failed to run event loop: %m"); + goto finish; + } + + server_maybe_append_tags(&server); + server_maybe_warn_forward_syslog_missed(&server); + } + + log_debug("systemd-journald stopped as pid "PID_FMT, getpid_cached()); + server_driver_message(&server, 0, + "MESSAGE_ID=" SD_MESSAGE_JOURNAL_STOP_STR, + LOG_MESSAGE("Journal stopped"), + NULL); + +finish: + server_done(&server); + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/journal/journald.conf b/src/journal/journald.conf new file mode 100644 index 00000000..2f1c6611 --- /dev/null +++ b/src/journal/journald.conf @@ -0,0 +1,43 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See journald.conf(5) for details. + +[Journal] +#Storage=auto +#Compress=yes +#Seal=yes +#SplitMode=uid +#SyncIntervalSec=5m +#RateLimitIntervalSec=30s +#RateLimitBurst=10000 +#SystemMaxUse= +#SystemKeepFree= +#SystemMaxFileSize= +#SystemMaxFiles=100 +#RuntimeMaxUse= +#RuntimeKeepFree= +#RuntimeMaxFileSize= +#RuntimeMaxFiles=100 +#MaxRetentionSec= +#MaxFileSec=1month +#ForwardToSyslog=no +#ForwardToKMsg=no +#ForwardToConsole=no +#ForwardToWall=yes +#TTYPath=/dev/console +#MaxLevelStore=debug +#MaxLevelSyslog=debug +#MaxLevelKMsg=notice +#MaxLevelConsole=info +#MaxLevelWall=emerg +#LineMax=48K +#ReadKMsg=yes diff --git a/src/journal/lookup3.c b/src/journal/lookup3.c new file mode 100644 index 00000000..74c80b72 --- /dev/null +++ b/src/journal/lookup3.c @@ -0,0 +1,1005 @@ +/* Slightly modified by Lennart Poettering, to avoid name clashes, and + * unexport a few functions. */ + +#include "lookup3.h" + +/* +------------------------------------------------------------------------------- +lookup3.c, by Bob Jenkins, May 2006, Public Domain. + +These are functions for producing 32-bit hashes for hash table lookup. +hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included +if SELF_TEST is defined. You can use this free for any purpose. It's in +the public domain. It has no warranty. + +You probably want to use hashlittle(). hashlittle() and hashbig() +hash byte arrays. hashlittle() is faster than hashbig() on +little-endian machines. Intel and AMD are little-endian machines. +On second thought, you probably want hashlittle2(), which is identical to +hashlittle() except it returns two 32-bit hashes for the price of one. +You could implement hashbig2() if you wanted but I haven't bothered here. + +If you want to find a hash of, say, exactly 7 integers, do + a = i1; b = i2; c = i3; + mix(a,b,c); + a += i4; b += i5; c += i6; + mix(a,b,c); + a += i7; + final(a,b,c); +then use c as the hash value. If you have a variable length array of +4-byte integers to hash, use hashword(). If you have a byte array (like +a character string), use hashlittle(). If you have several byte arrays, or +a mix of things, see the comments above hashlittle(). + +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +then mix those integers. This is fast (you can do a lot more thorough +mixing with 12*3 instructions on 3 integers than you can with 3 instructions +on 1 byte), but shoehorning those bytes into integers efficiently is messy. +------------------------------------------------------------------------------- +*/ +/* #define SELF_TEST 1 */ + +#include /* defines uint32_t etc */ +#include /* defines printf for tests */ +#include /* attempt to define endianness */ +#include /* defines time_t for timings in the test */ +#ifdef linux +# include /* attempt to define endianness */ +#endif + +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif + +/* + * My best guess at if you are big-endian or little-endian. This may + * need adjustment. + */ +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ + __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) +# define HASH_LITTLE_ENDIAN 1 +# define HASH_BIG_ENDIAN 0 +#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ + __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 1 +#else +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 0 +#endif + +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* +------------------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. + +This is reversible, so any information in (a,b,c) before mix() is +still in (a,b,c) after mix(). + +If four pairs of (a,b,c) inputs are run through mix(), or through +mix() in reverse, there are at least 32 bits of the output that +are sometimes the same for one pair and different for another pair. +This was tested for: +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that +satisfy this are + 4 6 8 16 19 4 + 9 15 3 18 27 15 + 14 9 3 7 17 3 +Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing +for "differ" defined as + with a one-bit base and a two-bit delta. I +used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables. + +This does not achieve avalanche. There are input bits of (a,b,c) +that fail to affect some output bits of (a,b,c), especially of a. The +most thoroughly mixed value is c, but it doesn't really even achieve +avalanche in c. + +This allows some parallelism. Read-after-writes are good at doubling +the number of bits affected, so the goal of mixing pulls in the opposite +direction as the goal of parallelism. I did what I could. Rotates +seem to cost as much as shifts on every machine I could lay my hands +on, and rotates are much kinder to the top and bottom bits, so I used +rotates. +------------------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* +------------------------------------------------------------------------------- +final -- final mixing of 3 32-bit values (a,b,c) into c + +Pairs of (a,b,c) values differing in only a few bits will usually +produce values of c that look totally different. This was tested for +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +These constants passed: + 14 11 25 16 4 14 24 + 12 14 25 16 4 14 24 +and these came close: + 4 8 15 26 3 22 24 + 10 8 15 26 3 22 24 + 11 8 15 26 3 22 24 +------------------------------------------------------------------------------- +*/ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + +/* +-------------------------------------------------------------------- + This works on all machines. To be useful, it requires + -- that the key be an array of uint32_t's, and + -- that the length be the number of uint32_t's in the key + + The function hashword() is identical to hashlittle() on little-endian + machines, and identical to hashbig() on big-endian machines, + except that the length has to be measured in uint32_ts rather than in + bytes. hashlittle() is more complicated than hashword() only because + hashlittle() has to dance around fitting the key bytes into registers. +-------------------------------------------------------------------- +*/ +uint32_t jenkins_hashword( +const uint32_t *k, /* the key, an array of uint32_t values */ +size_t length, /* the length of the key, in uint32_ts */ +uint32_t initval) /* the previous hash, or an arbitrary value */ +{ + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval; + + /*------------------------------------------------- handle most of the key */ + while (length > 3) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 uint32_t's */ + switch(length) /* all the case statements fall through */ + { + case 3 : c+=k[2]; + case 2 : b+=k[1]; + case 1 : a+=k[0]; + final(a,b,c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + return c; +} + +/* +-------------------------------------------------------------------- +hashword2() -- same as hashword(), but take two seeds and return two +32-bit values. pc and pb must both be nonnull, and *pc and *pb must +both be initialized with seeds. If you pass in (*pb)==0, the output +(*pc) will be the same as the return value from hashword(). +-------------------------------------------------------------------- +*/ +void jenkins_hashword2 ( +const uint32_t *k, /* the key, an array of uint32_t values */ +size_t length, /* the length of the key, in uint32_ts */ +uint32_t *pc, /* IN: seed OUT: primary hash value */ +uint32_t *pb) /* IN: more seed OUT: secondary hash value */ +{ + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)(length<<2)) + *pc; + c += *pb; + + /*------------------------------------------------- handle most of the key */ + while (length > 3) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 uint32_t's */ + switch(length) /* all the case statements fall through */ + { + case 3 : c+=k[2]; + case 2 : b+=k[1]; + case 1 : a+=k[0]; + final(a,b,c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + *pc=c; *pb=b; +} + +/* +------------------------------------------------------------------------------- +hashlittle() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + length : the length of the key, counting by bytes + initval : can be any 4-byte value +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Two keys differing by one or two bits will have +totally different hash values. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (uint8_t **)k, do it like this: + for (i=0, h=0; i 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But valgrind will + * still catch it and complain. The masking trick does make the hash + * noticeably faster for short strings (like English words). + */ +#if !VALGRIND && !HAS_FEATURE_ADDRESS_SANITIZER && !HAS_FEATURE_MEMORY_SANITIZER + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + { + const uint8_t *k8 = (const uint8_t *) k; + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : return c; + } + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; + case 9 : c+=k[8]; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} + +/* + * hashlittle2: return 2 32-bit hash values + * + * This is identical to hashlittle(), except it returns two 32-bit hash + * values instead of just one. This is good enough for hash table + * lookup with 2^^64 buckets, or if you want a second hash if you're not + * happy with the first, or if you want a probably-unique 64-bit ID for + * the key. *pc is better mixed than *pb, so use *pc first. If you want + * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)". + */ +void jenkins_hashlittle2( + const void *key, /* the key to hash */ + size_t length, /* length of the key */ + uint32_t *pc, /* IN: primary initval, OUT: primary hash */ + uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */ +{ + uint32_t a,b,c; /* internal state */ + union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)length) + *pc; + c += *pb; + + u.ptr = key; + if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But valgrind will + * still catch it and complain. The masking trick does make the hash + * noticeably faster for short strings (like English words). + */ +#if !VALGRIND && !HAS_FEATURE_ADDRESS_SANITIZER && !HAS_FEATURE_MEMORY_SANITIZER + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + { + const uint8_t *k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; + case 9 : c+=k[8]; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; + case 1 : a+=k[0]; + break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + } + + final(a,b,c); + *pc=c; *pb=b; +} + +/* + * hashbig(): + * This is the same as hashword() on big-endian machines. It is different + * from hashlittle() on all machines. hashbig() takes advantage of + * big-endian byte ordering. + */ +uint32_t jenkins_hashbig( const void *key, size_t length, uint32_t initval) +{ + uint32_t a,b,c; + union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; + + u.ptr = key; + if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]<<8" actually reads beyond the end of the string, but + * then shifts out the part it's not allowed to read. Because the + * string is aligned, the illegal read is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But valgrind will + * still catch it and complain. The masking trick does make the hash + * noticeably faster for short strings (like English words). + */ +#if !VALGRIND && !HAS_FEATURE_ADDRESS_SANITIZER && !HAS_FEATURE_MEMORY_SANITIZER + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff00; a+=k[0]; break; + case 6 : b+=k[1]&0xffff0000; a+=k[0]; break; + case 5 : b+=k[1]&0xff000000; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff00; break; + case 2 : a+=k[0]&0xffff0000; break; + case 1 : a+=k[0]&0xff000000; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + { + const uint8_t *k8 = (const uint8_t *)k; + switch(length) /* all the case statements fall through */ + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<8; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<16; /* fall through */ + case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */ + case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */ + case 1 : a+=((uint32_t)k8[0])<<24; break; + case 0 : return c; + } + } + +#endif /* !VALGRIND */ + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += ((uint32_t)k[0])<<24; + a += ((uint32_t)k[1])<<16; + a += ((uint32_t)k[2])<<8; + a += ((uint32_t)k[3]); + b += ((uint32_t)k[4])<<24; + b += ((uint32_t)k[5])<<16; + b += ((uint32_t)k[6])<<8; + b += ((uint32_t)k[7]); + c += ((uint32_t)k[8])<<24; + c += ((uint32_t)k[9])<<16; + c += ((uint32_t)k[10])<<8; + c += ((uint32_t)k[11]); + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=k[11]; + case 11: c+=((uint32_t)k[10])<<8; + case 10: c+=((uint32_t)k[9])<<16; + case 9 : c+=((uint32_t)k[8])<<24; + case 8 : b+=k[7]; + case 7 : b+=((uint32_t)k[6])<<8; + case 6 : b+=((uint32_t)k[5])<<16; + case 5 : b+=((uint32_t)k[4])<<24; + case 4 : a+=k[3]; + case 3 : a+=((uint32_t)k[2])<<8; + case 2 : a+=((uint32_t)k[1])<<16; + case 1 : a+=((uint32_t)k[0])<<24; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} + +#ifdef SELF_TEST + +/* used for timings */ +void driver1() +{ + uint8_t buf[256]; + uint32_t i; + uint32_t h=0; + time_t a,z; + + time(&a); + for (i=0; i<256; ++i) buf[i] = 'x'; + for (i=0; i<1; ++i) + { + h = hashlittle(&buf[0],1,h); + } + time(&z); + if (z-a > 0) printf("time %d %.8x\n", z-a, h); +} + +/* check that every input bit changes every output bit half the time */ +#define HASHSTATE 1 +#define HASHLEN 1 +#define MAXPAIR 60 +#define MAXLEN 70 +void driver2() +{ + uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1]; + uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z; + uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; + uint32_t x[HASHSTATE],y[HASHSTATE]; + uint32_t hlen; + + printf("No more than %d trials should ever be needed \n",MAXPAIR/2); + for (hlen=0; hlen < MAXLEN; ++hlen) + { + z=0; + for (i=0; i>(8-j)); + c[0] = hashlittle(a, hlen, m); + b[i] ^= ((k+1)<>(8-j)); + d[0] = hashlittle(b, hlen, m); + /* check every bit is 1, 0, set, and not set at least once */ + for (l=0; lz) z=k; + if (k==MAXPAIR) + { + printf("Some bit didn't change: "); + printf("%.8x %.8x %.8x %.8x %.8x %.8x ", + e[0],f[0],g[0],h[0],x[0],y[0]); + printf("i %d j %d m %d len %d\n", i, j, m, hlen); + } + if (z==MAXPAIR) goto done; + } + } + } + done: + if (z < MAXPAIR) + { + printf("Mix success %2d bytes %2d initvals ",i,m); + printf("required %d trials\n", z/2); + } + } + printf("\n"); +} + +/* Check for reading beyond the end of the buffer and alignment problems */ +void driver3() +{ + uint8_t buf[MAXLEN+20], *b; + uint32_t len; + uint8_t q[] = "This is the time for all good men to come to the aid of their country..."; + uint32_t h; + uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country..."; + uint32_t i; + uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country..."; + uint32_t j; + uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country..."; + uint32_t ref,x,y; + uint8_t *p; + + printf("Endianness. These lines should all be the same (for values filled in):\n"); + printf("%.8x %.8x %.8x\n", + hashword((const uint32_t *)q, (sizeof(q)-1)/4, 13), + hashword((const uint32_t *)q, (sizeof(q)-5)/4, 13), + hashword((const uint32_t *)q, (sizeof(q)-9)/4, 13)); + p = q; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + p = &qq[1]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + p = &qqq[2]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + p = &qqqq[3]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + printf("\n"); + + /* check that hashlittle2 and hashlittle produce the same results */ + i=47; j=0; + hashlittle2(q, sizeof(q), &i, &j); + if (hashlittle(q, sizeof(q), 47) != i) + printf("hashlittle2 and hashlittle mismatch\n"); + + /* check that hashword2 and hashword produce the same results */ + len = 0xdeadbeef; + i=47, j=0; + hashword2(&len, 1, &i, &j); + if (hashword(&len, 1, 47) != i) + printf("hashword2 and hashword mismatch %x %x\n", + i, hashword(&len, 1, 47)); + + /* check hashlittle doesn't read before or after the ends of the string */ + for (h=0, b=buf+1; h<8; ++h, ++b) + { + for (i=0; i +#include + +#include "macro.h" + +uint32_t jenkins_hashword(const uint32_t *k, size_t length, uint32_t initval) _pure_; +void jenkins_hashword2(const uint32_t *k, size_t length, uint32_t *pc, uint32_t *pb); + +uint32_t jenkins_hashlittle(const void *key, size_t length, uint32_t initval) _pure_; +void jenkins_hashlittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb); + +uint32_t jenkins_hashbig(const void *key, size_t length, uint32_t initval) _pure_; + +static inline uint64_t hash64(const void *data, size_t length) { + uint32_t a = 0, b = 0; + + jenkins_hashlittle2(data, length, &a, &b); + + return ((uint64_t) a << 32ULL) | (uint64_t) b; +} diff --git a/src/journal/meson.build b/src/journal/meson.build new file mode 100644 index 00000000..5796f77c --- /dev/null +++ b/src/journal/meson.build @@ -0,0 +1,132 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +journal_client_sources = files(''' + audit-type.c + audit-type.h + catalog.c + catalog.h + compress.c + compress.h + journal-def.h + journal-file.c + journal-file.h + journal-send.c + journal-vacuum.c + journal-vacuum.h + journal-verify.c + journal-verify.h + lookup3.c + lookup3.h + mmap-cache.c + mmap-cache.h + sd-journal.c +'''.split()) + +if conf.get('HAVE_GCRYPT') == 1 + journal_client_sources += files(''' + journal-authenticate.c + journal-authenticate.h + fsprg.c + fsprg.h + '''.split()) +endif + +############################################################ + +audit_type_includes = [config_h, + missing_audit_h, + 'linux/audit.h'] +if conf.get('HAVE_AUDIT') == 1 + audit_type_includes += 'libaudit.h' +endif + +generate_audit_type_list = find_program('generate-audit_type-list.sh') +audit_type_list_txt = custom_target( + 'audit_type-list.txt', + output : 'audit_type-list.txt', + command : [generate_audit_type_list, cpp] + audit_type_includes, + capture : true) + +audit_type_to_name = custom_target( + 'audit_type-to-name.h', + input : ['audit_type-to-name.awk', audit_type_list_txt], + output : 'audit_type-to-name.h', + command : [awk, '-f', '@INPUT0@', '@INPUT1@'], + capture : true) + +journal_client_sources += [audit_type_to_name] + +libjournal_client = static_library( + 'journal-client', + journal_client_sources, + include_directories : includes, + c_args : ['-fvisibility=default']) + +############################################################ + +libjournal_core_sources = files(''' + journald-audit.c + journald-audit.h + journald-console.c + journald-console.h + journald-context.c + journald-context.h + journald-kmsg.c + journald-kmsg.h + journald-native.c + journald-native.h + journald-rate-limit.c + journald-rate-limit.h + journald-server.c + journald-server.h + journald-stream.c + journald-stream.h + journald-syslog.c + journald-syslog.h + journald-wall.c + journald-wall.h + journal-internal.h +'''.split()) + +systemd_journald_sources = files(''' + journald.c + journald-server.h +'''.split()) + +journald_gperf_c = custom_target( + 'journald-gperf.c', + input : 'journald-gperf.gperf', + output : 'journald-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + +systemd_cat_sources = files('cat.c') + +journalctl_sources = files('journalctl.c') + +if conf.get('HAVE_QRENCODE') == 1 + journalctl_sources += files('journal-qrcode.c', + 'journal-qrcode.h') +endif + +install_data('journald.conf', + install_dir : pkgsysconfdir) + +if get_option('create-log-dirs') + meson.add_install_script( + 'sh', '-c', + mkdir_p.format('/var/log/journal')) + meson.add_install_script( + 'sh', '-c', + '''chown 0:0 $DESTDIR/var/log/journal && + chmod 755 $DESTDIR/var/log/journal || :''') + if get_option('adm-group') + meson.add_install_script( + 'sh', '-c', + 'setfacl -nm g:adm:rx,d:g:adm:rx $DESTDIR/var/log/journal || :') + endif + if get_option('wheel-group') + meson.add_install_script( + 'sh', '-c', + 'setfacl -nm g:wheel:rx,d:g:wheel:rx $DESTDIR/var/log/journal || :') + endif +endif diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c new file mode 100644 index 00000000..e2f7bd7e --- /dev/null +++ b/src/journal/mmap-cache.c @@ -0,0 +1,669 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "hashmap.h" +#include "list.h" +#include "log.h" +#include "macro.h" +#include "memory-util.h" +#include "mmap-cache.h" +#include "sigbus.h" + +typedef struct Window Window; +typedef struct Context Context; + +struct Window { + MMapCache *cache; + + bool invalidated:1; + bool keep_always:1; + bool in_unused:1; + + int prot; + void *ptr; + uint64_t offset; + size_t size; + + MMapFileDescriptor *fd; + + LIST_FIELDS(Window, by_fd); + LIST_FIELDS(Window, unused); + + LIST_HEAD(Context, contexts); +}; + +struct Context { + MMapCache *cache; + unsigned id; + Window *window; + + LIST_FIELDS(Context, by_window); +}; + +struct MMapFileDescriptor { + MMapCache *cache; + int fd; + bool sigbus; + LIST_HEAD(Window, windows); +}; + +struct MMapCache { + unsigned n_ref; + unsigned n_windows; + + unsigned n_hit, n_missed; + + Hashmap *fds; + Context *contexts[MMAP_CACHE_MAX_CONTEXTS]; + + LIST_HEAD(Window, unused); + Window *last_unused; +}; + +#define WINDOWS_MIN 64 + +#if ENABLE_DEBUG_MMAP_CACHE +/* Tiny windows increase mmap activity and the chance of exposing unsafe use. */ +# define WINDOW_SIZE (page_size()) +#else +# define WINDOW_SIZE (8ULL*1024ULL*1024ULL) +#endif + +MMapCache* mmap_cache_new(void) { + MMapCache *m; + + m = new0(MMapCache, 1); + if (!m) + return NULL; + + m->n_ref = 1; + return m; +} + +static void window_unlink(Window *w) { + Context *c; + + assert(w); + + if (w->ptr) + munmap(w->ptr, w->size); + + if (w->fd) + LIST_REMOVE(by_fd, w->fd->windows, w); + + if (w->in_unused) { + if (w->cache->last_unused == w) + w->cache->last_unused = w->unused_prev; + + LIST_REMOVE(unused, w->cache->unused, w); + } + + LIST_FOREACH(by_window, c, w->contexts) { + assert(c->window == w); + c->window = NULL; + } +} + +static void window_invalidate(Window *w) { + assert(w); + + if (w->invalidated) + return; + + /* Replace the window with anonymous pages. This is useful + * when we hit a SIGBUS and want to make sure the file cannot + * trigger any further SIGBUS, possibly overrunning the sigbus + * queue. */ + + assert_se(mmap(w->ptr, w->size, w->prot, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0) == w->ptr); + w->invalidated = true; +} + +static void window_free(Window *w) { + assert(w); + + window_unlink(w); + w->cache->n_windows--; + free(w); +} + +_pure_ static bool window_matches(Window *w, int prot, uint64_t offset, size_t size) { + assert(w); + assert(size > 0); + + return + prot == w->prot && + offset >= w->offset && + offset + size <= w->offset + w->size; +} + +_pure_ static bool window_matches_fd(Window *w, MMapFileDescriptor *f, int prot, uint64_t offset, size_t size) { + assert(w); + assert(f); + + return + w->fd && + f->fd == w->fd->fd && + window_matches(w, prot, offset, size); +} + +static Window *window_add(MMapCache *m, MMapFileDescriptor *f, int prot, bool keep_always, uint64_t offset, size_t size, void *ptr) { + Window *w; + + assert(m); + assert(f); + + if (!m->last_unused || m->n_windows <= WINDOWS_MIN) { + + /* Allocate a new window */ + w = new0(Window, 1); + if (!w) + return NULL; + m->n_windows++; + } else { + + /* Reuse an existing one */ + w = m->last_unused; + window_unlink(w); + zero(*w); + } + + w->cache = m; + w->fd = f; + w->prot = prot; + w->keep_always = keep_always; + w->offset = offset; + w->size = size; + w->ptr = ptr; + + LIST_PREPEND(by_fd, f->windows, w); + + return w; +} + +static void context_detach_window(Context *c) { + Window *w; + + assert(c); + + if (!c->window) + return; + + w = TAKE_PTR(c->window); + LIST_REMOVE(by_window, w->contexts, c); + + if (!w->contexts && !w->keep_always) { + /* Not used anymore? */ +#if ENABLE_DEBUG_MMAP_CACHE + /* Unmap unused windows immediately to expose use-after-unmap + * by SIGSEGV. */ + window_free(w); +#else + LIST_PREPEND(unused, c->cache->unused, w); + if (!c->cache->last_unused) + c->cache->last_unused = w; + + w->in_unused = true; +#endif + } +} + +static void context_attach_window(Context *c, Window *w) { + assert(c); + assert(w); + + if (c->window == w) + return; + + context_detach_window(c); + + if (w->in_unused) { + /* Used again? */ + LIST_REMOVE(unused, c->cache->unused, w); + if (c->cache->last_unused == w) + c->cache->last_unused = w->unused_prev; + + w->in_unused = false; + } + + c->window = w; + LIST_PREPEND(by_window, w->contexts, c); +} + +static Context *context_add(MMapCache *m, unsigned id) { + Context *c; + + assert(m); + + c = m->contexts[id]; + if (c) + return c; + + c = new0(Context, 1); + if (!c) + return NULL; + + c->cache = m; + c->id = id; + + assert(!m->contexts[id]); + m->contexts[id] = c; + + return c; +} + +static void context_free(Context *c) { + assert(c); + + context_detach_window(c); + + if (c->cache) { + assert(c->cache->contexts[c->id] == c); + c->cache->contexts[c->id] = NULL; + } + + free(c); +} + +static MMapCache *mmap_cache_free(MMapCache *m) { + int i; + + assert(m); + + for (i = 0; i < MMAP_CACHE_MAX_CONTEXTS; i++) + if (m->contexts[i]) + context_free(m->contexts[i]); + + hashmap_free(m->fds); + + while (m->unused) + window_free(m->unused); + + return mfree(m); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(MMapCache, mmap_cache, mmap_cache_free); + +static int make_room(MMapCache *m) { + assert(m); + + if (!m->last_unused) + return 0; + + window_free(m->last_unused); + return 1; +} + +static int try_context( + MMapCache *m, + MMapFileDescriptor *f, + int prot, + unsigned context, + bool keep_always, + uint64_t offset, + size_t size, + void **ret, + size_t *ret_size) { + + Context *c; + + assert(m); + assert(m->n_ref > 0); + assert(f); + assert(size > 0); + assert(ret); + + c = m->contexts[context]; + if (!c) + return 0; + + assert(c->id == context); + + if (!c->window) + return 0; + + if (!window_matches_fd(c->window, f, prot, offset, size)) { + + /* Drop the reference to the window, since it's unnecessary now */ + context_detach_window(c); + return 0; + } + + if (c->window->fd->sigbus) + return -EIO; + + c->window->keep_always = c->window->keep_always || keep_always; + + *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset); + if (ret_size) + *ret_size = c->window->size - (offset - c->window->offset); + + return 1; +} + +static int find_mmap( + MMapCache *m, + MMapFileDescriptor *f, + int prot, + unsigned context, + bool keep_always, + uint64_t offset, + size_t size, + void **ret, + size_t *ret_size) { + + Window *w; + Context *c; + + assert(m); + assert(m->n_ref > 0); + assert(f); + assert(size > 0); + + if (f->sigbus) + return -EIO; + + LIST_FOREACH(by_fd, w, f->windows) + if (window_matches(w, prot, offset, size)) + break; + + if (!w) + return 0; + + c = context_add(m, context); + if (!c) + return -ENOMEM; + + context_attach_window(c, w); + w->keep_always = w->keep_always || keep_always; + + *ret = (uint8_t*) w->ptr + (offset - w->offset); + if (ret_size) + *ret_size = w->size - (offset - w->offset); + + return 1; +} + +static int mmap_try_harder(MMapCache *m, void *addr, MMapFileDescriptor *f, int prot, int flags, uint64_t offset, size_t size, void **res) { + void *ptr; + + assert(m); + assert(f); + assert(res); + + for (;;) { + int r; + + ptr = mmap(addr, size, prot, flags, f->fd, offset); + if (ptr != MAP_FAILED) + break; + if (errno != ENOMEM) + return negative_errno(); + + r = make_room(m); + if (r < 0) + return r; + if (r == 0) + return -ENOMEM; + } + + *res = ptr; + return 0; +} + +static int add_mmap( + MMapCache *m, + MMapFileDescriptor *f, + int prot, + unsigned context, + bool keep_always, + uint64_t offset, + size_t size, + struct stat *st, + void **ret, + size_t *ret_size) { + + uint64_t woffset, wsize; + Context *c; + Window *w; + void *d; + int r; + + assert(m); + assert(m->n_ref > 0); + assert(f); + assert(size > 0); + assert(ret); + + woffset = offset & ~((uint64_t) page_size() - 1ULL); + wsize = size + (offset - woffset); + wsize = PAGE_ALIGN(wsize); + + if (wsize < WINDOW_SIZE) { + uint64_t delta; + + delta = PAGE_ALIGN((WINDOW_SIZE - wsize) / 2); + + if (delta > offset) + woffset = 0; + else + woffset -= delta; + + wsize = WINDOW_SIZE; + } + + if (st) { + /* Memory maps that are larger then the files + underneath have undefined behavior. Hence, clamp + things to the file size if we know it */ + + if (woffset >= (uint64_t) st->st_size) + return -EADDRNOTAVAIL; + + if (woffset + wsize > (uint64_t) st->st_size) + wsize = PAGE_ALIGN(st->st_size - woffset); + } + + r = mmap_try_harder(m, NULL, f, prot, MAP_SHARED, woffset, wsize, &d); + if (r < 0) + return r; + + c = context_add(m, context); + if (!c) + goto outofmem; + + w = window_add(m, f, prot, keep_always, woffset, wsize, d); + if (!w) + goto outofmem; + + context_attach_window(c, w); + + *ret = (uint8_t*) w->ptr + (offset - w->offset); + if (ret_size) + *ret_size = w->size - (offset - w->offset); + + return 1; + +outofmem: + (void) munmap(d, wsize); + return -ENOMEM; +} + +int mmap_cache_get( + MMapCache *m, + MMapFileDescriptor *f, + int prot, + unsigned context, + bool keep_always, + uint64_t offset, + size_t size, + struct stat *st, + void **ret, + size_t *ret_size) { + + int r; + + assert(m); + assert(m->n_ref > 0); + assert(f); + assert(size > 0); + assert(ret); + assert(context < MMAP_CACHE_MAX_CONTEXTS); + + /* Check whether the current context is the right one already */ + r = try_context(m, f, prot, context, keep_always, offset, size, ret, ret_size); + if (r != 0) { + m->n_hit++; + return r; + } + + /* Search for a matching mmap */ + r = find_mmap(m, f, prot, context, keep_always, offset, size, ret, ret_size); + if (r != 0) { + m->n_hit++; + return r; + } + + m->n_missed++; + + /* Create a new mmap */ + return add_mmap(m, f, prot, context, keep_always, offset, size, st, ret, ret_size); +} + +unsigned mmap_cache_get_hit(MMapCache *m) { + assert(m); + + return m->n_hit; +} + +unsigned mmap_cache_get_missed(MMapCache *m) { + assert(m); + + return m->n_missed; +} + +static void mmap_cache_process_sigbus(MMapCache *m) { + bool found = false; + MMapFileDescriptor *f; + Iterator i; + int r; + + assert(m); + + /* Iterate through all triggered pages and mark their files as + * invalidated */ + for (;;) { + bool ours; + void *addr; + + r = sigbus_pop(&addr); + if (_likely_(r == 0)) + break; + if (r < 0) { + log_error_errno(r, "SIGBUS handling failed: %m"); + abort(); + } + + ours = false; + HASHMAP_FOREACH(f, m->fds, i) { + Window *w; + + LIST_FOREACH(by_fd, w, f->windows) { + if ((uint8_t*) addr >= (uint8_t*) w->ptr && + (uint8_t*) addr < (uint8_t*) w->ptr + w->size) { + found = ours = f->sigbus = true; + break; + } + } + + if (ours) + break; + } + + /* Didn't find a matching window, give up */ + if (!ours) { + log_error("Unknown SIGBUS page, aborting."); + abort(); + } + } + + /* The list of triggered pages is now empty. Now, let's remap + * all windows of the triggered file to anonymous maps, so + * that no page of the file in question is triggered again, so + * that we can be sure not to hit the queue size limit. */ + if (_likely_(!found)) + return; + + HASHMAP_FOREACH(f, m->fds, i) { + Window *w; + + if (!f->sigbus) + continue; + + LIST_FOREACH(by_fd, w, f->windows) + window_invalidate(w); + } +} + +bool mmap_cache_got_sigbus(MMapCache *m, MMapFileDescriptor *f) { + assert(m); + assert(f); + + mmap_cache_process_sigbus(m); + + return f->sigbus; +} + +MMapFileDescriptor* mmap_cache_add_fd(MMapCache *m, int fd) { + MMapFileDescriptor *f; + int r; + + assert(m); + assert(fd >= 0); + + f = hashmap_get(m->fds, FD_TO_PTR(fd)); + if (f) + return f; + + r = hashmap_ensure_allocated(&m->fds, NULL); + if (r < 0) + return NULL; + + f = new0(MMapFileDescriptor, 1); + if (!f) + return NULL; + + f->cache = m; + f->fd = fd; + + r = hashmap_put(m->fds, FD_TO_PTR(fd), f); + if (r < 0) + return mfree(f); + + return f; +} + +void mmap_cache_free_fd(MMapCache *m, MMapFileDescriptor *f) { + assert(m); + assert(f); + + /* Make sure that any queued SIGBUS are first dispatched, so + * that we don't end up with a SIGBUS entry we cannot relate + * to any existing memory map */ + + mmap_cache_process_sigbus(m); + + while (f->windows) + window_free(f->windows); + + if (f->cache) + assert_se(hashmap_remove(f->cache->fds, FD_TO_PTR(f->fd))); + + free(f); +} diff --git a/src/journal/mmap-cache.h b/src/journal/mmap-cache.h new file mode 100644 index 00000000..bf70d320 --- /dev/null +++ b/src/journal/mmap-cache.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +/* One context per object type, plus one of the header, plus one "additional" one */ +#define MMAP_CACHE_MAX_CONTEXTS 9 + +typedef struct MMapCache MMapCache; +typedef struct MMapFileDescriptor MMapFileDescriptor; + +MMapCache* mmap_cache_new(void); +MMapCache* mmap_cache_ref(MMapCache *m); +MMapCache* mmap_cache_unref(MMapCache *m); + +int mmap_cache_get( + MMapCache *m, + MMapFileDescriptor *f, + int prot, + unsigned context, + bool keep_always, + uint64_t offset, + size_t size, + struct stat *st, + void **ret, + size_t *ret_size); +MMapFileDescriptor * mmap_cache_add_fd(MMapCache *m, int fd); +void mmap_cache_free_fd(MMapCache *m, MMapFileDescriptor *f); + +unsigned mmap_cache_get_hit(MMapCache *m); +unsigned mmap_cache_get_missed(MMapCache *m); + +bool mmap_cache_got_sigbus(MMapCache *m, MMapFileDescriptor *f); diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c new file mode 100644 index 00000000..055a975b --- /dev/null +++ b/src/journal/sd-journal.c @@ -0,0 +1,3134 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-journal.h" + +#include "alloc-util.h" +#include "catalog.h" +#include "compress.h" +#include "dirent-util.h" +#include "env-file.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "hostname-util.h" +#include "id128-util.h" +#include "io-util.h" +#include "journal-def.h" +#include "journal-file.h" +#include "journal-internal.h" +#include "list.h" +#include "lookup3.h" +#include "nulstr-util.h" +#include "path-util.h" +#include "process-util.h" +#include "replace-var.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" + +#define JOURNAL_FILES_MAX 7168 + +#define JOURNAL_FILES_RECHECK_USEC (2 * USEC_PER_SEC) + +#define REPLACE_VAR_MAX 256 + +#define DEFAULT_DATA_THRESHOLD (64*1024) + +static void remove_file_real(sd_journal *j, JournalFile *f); + +static bool journal_pid_changed(sd_journal *j) { + assert(j); + + /* We don't support people creating a journal object and + * keeping it around over a fork(). Let's complain. */ + + return j->original_pid != getpid_cached(); +} + +static int journal_put_error(sd_journal *j, int r, const char *path) { + char *copy; + int k; + + /* Memorize an error we encountered, and store which + * file/directory it was generated from. Note that we store + * only *one* path per error code, as the error code is the + * key into the hashmap, and the path is the value. This means + * we keep track only of all error kinds, but not of all error + * locations. This has the benefit that the hashmap cannot + * grow beyond bounds. + * + * We return an error here only if we didn't manage to + * memorize the real error. */ + + if (r >= 0) + return r; + + k = hashmap_ensure_allocated(&j->errors, NULL); + if (k < 0) + return k; + + if (path) { + copy = strdup(path); + if (!copy) + return -ENOMEM; + } else + copy = NULL; + + k = hashmap_put(j->errors, INT_TO_PTR(r), copy); + if (k < 0) { + free(copy); + + if (k == -EEXIST) + return 0; + + return k; + } + + return 0; +} + +static void detach_location(sd_journal *j) { + Iterator i; + JournalFile *f; + + assert(j); + + j->current_file = NULL; + j->current_field = 0; + + ORDERED_HASHMAP_FOREACH(f, j->files, i) + journal_file_reset_location(f); +} + +static void reset_location(sd_journal *j) { + assert(j); + + detach_location(j); + zero(j->current_location); +} + +static void init_location(Location *l, LocationType type, JournalFile *f, Object *o) { + assert(l); + assert(IN_SET(type, LOCATION_DISCRETE, LOCATION_SEEK)); + assert(f); + assert(o->object.type == OBJECT_ENTRY); + + l->type = type; + l->seqnum = le64toh(o->entry.seqnum); + l->seqnum_id = f->header->seqnum_id; + l->realtime = le64toh(o->entry.realtime); + l->monotonic = le64toh(o->entry.monotonic); + l->boot_id = o->entry.boot_id; + l->xor_hash = le64toh(o->entry.xor_hash); + + l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true; +} + +static void set_location(sd_journal *j, JournalFile *f, Object *o) { + assert(j); + assert(f); + assert(o); + + init_location(&j->current_location, LOCATION_DISCRETE, f, o); + + j->current_file = f; + j->current_field = 0; + + /* Let f know its candidate entry was picked. */ + assert(f->location_type == LOCATION_SEEK); + f->location_type = LOCATION_DISCRETE; +} + +static int match_is_valid(const void *data, size_t size) { + const char *b, *p; + + assert(data); + + if (size < 2) + return false; + + if (((char*) data)[0] == '_' && ((char*) data)[1] == '_') + return false; + + b = data; + for (p = b; p < b + size; p++) { + + if (*p == '=') + return p > b; + + if (*p == '_') + continue; + + if (*p >= 'A' && *p <= 'Z') + continue; + + if (*p >= '0' && *p <= '9') + continue; + + return false; + } + + return false; +} + +static bool same_field(const void *_a, size_t s, const void *_b, size_t t) { + const uint8_t *a = _a, *b = _b; + size_t j; + + for (j = 0; j < s && j < t; j++) { + + if (a[j] != b[j]) + return false; + + if (a[j] == '=') + return true; + } + + assert_not_reached("\"=\" not found"); +} + +static Match *match_new(Match *p, MatchType t) { + Match *m; + + m = new0(Match, 1); + if (!m) + return NULL; + + m->type = t; + + if (p) { + m->parent = p; + LIST_PREPEND(matches, p->matches, m); + } + + return m; +} + +static void match_free(Match *m) { + assert(m); + + while (m->matches) + match_free(m->matches); + + if (m->parent) + LIST_REMOVE(matches, m->parent->matches, m); + + free(m->data); + free(m); +} + +static void match_free_if_empty(Match *m) { + if (!m || m->matches) + return; + + match_free(m); +} + +_public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) { + Match *l3, *l4, *add_here = NULL, *m; + le64_t le_hash; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(data, -EINVAL); + + if (size == 0) + size = strlen(data); + + assert_return(match_is_valid(data, size), -EINVAL); + + /* level 0: AND term + * level 1: OR terms + * level 2: AND terms + * level 3: OR terms + * level 4: concrete matches */ + + if (!j->level0) { + j->level0 = match_new(NULL, MATCH_AND_TERM); + if (!j->level0) + return -ENOMEM; + } + + if (!j->level1) { + j->level1 = match_new(j->level0, MATCH_OR_TERM); + if (!j->level1) + return -ENOMEM; + } + + if (!j->level2) { + j->level2 = match_new(j->level1, MATCH_AND_TERM); + if (!j->level2) + return -ENOMEM; + } + + assert(j->level0->type == MATCH_AND_TERM); + assert(j->level1->type == MATCH_OR_TERM); + assert(j->level2->type == MATCH_AND_TERM); + + le_hash = htole64(hash64(data, size)); + + LIST_FOREACH(matches, l3, j->level2->matches) { + assert(l3->type == MATCH_OR_TERM); + + LIST_FOREACH(matches, l4, l3->matches) { + assert(l4->type == MATCH_DISCRETE); + + /* Exactly the same match already? Then ignore + * this addition */ + if (l4->le_hash == le_hash && + l4->size == size && + memcmp(l4->data, data, size) == 0) + return 0; + + /* Same field? Then let's add this to this OR term */ + if (same_field(data, size, l4->data, l4->size)) { + add_here = l3; + break; + } + } + + if (add_here) + break; + } + + if (!add_here) { + add_here = match_new(j->level2, MATCH_OR_TERM); + if (!add_here) + goto fail; + } + + m = match_new(add_here, MATCH_DISCRETE); + if (!m) + goto fail; + + m->le_hash = le_hash; + m->size = size; + m->data = memdup(data, size); + if (!m->data) + goto fail; + + detach_location(j); + + return 0; + +fail: + match_free_if_empty(add_here); + match_free_if_empty(j->level2); + match_free_if_empty(j->level1); + match_free_if_empty(j->level0); + + return -ENOMEM; +} + +_public_ int sd_journal_add_conjunction(sd_journal *j) { + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + if (!j->level0) + return 0; + + if (!j->level1) + return 0; + + if (!j->level1->matches) + return 0; + + j->level1 = NULL; + j->level2 = NULL; + + return 0; +} + +_public_ int sd_journal_add_disjunction(sd_journal *j) { + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + if (!j->level0) + return 0; + + if (!j->level1) + return 0; + + if (!j->level2) + return 0; + + if (!j->level2->matches) + return 0; + + j->level2 = NULL; + return 0; +} + +static char *match_make_string(Match *m) { + char *p = NULL, *r; + Match *i; + bool enclose = false; + + if (!m) + return strdup("none"); + + if (m->type == MATCH_DISCRETE) + return cescape_length(m->data, m->size); + + LIST_FOREACH(matches, i, m->matches) { + char *t, *k; + + t = match_make_string(i); + if (!t) + return mfree(p); + + if (p) { + k = strjoin(p, m->type == MATCH_OR_TERM ? " OR " : " AND ", t); + free(p); + free(t); + + if (!k) + return NULL; + + p = k; + + enclose = true; + } else + p = t; + } + + if (enclose) { + r = strjoin("(", p, ")"); + free(p); + return r; + } + + return p; +} + +char *journal_make_match_string(sd_journal *j) { + assert(j); + + return match_make_string(j->level0); +} + +_public_ void sd_journal_flush_matches(sd_journal *j) { + if (!j) + return; + + if (j->level0) + match_free(j->level0); + + j->level0 = j->level1 = j->level2 = NULL; + + detach_location(j); +} + +_pure_ static int compare_with_location(JournalFile *f, Location *l) { + int r; + + assert(f); + assert(l); + assert(f->location_type == LOCATION_SEEK); + assert(IN_SET(l->type, LOCATION_DISCRETE, LOCATION_SEEK)); + + if (l->monotonic_set && + sd_id128_equal(f->current_boot_id, l->boot_id) && + l->realtime_set && + f->current_realtime == l->realtime && + l->xor_hash_set && + f->current_xor_hash == l->xor_hash) + return 0; + + if (l->seqnum_set && + sd_id128_equal(f->header->seqnum_id, l->seqnum_id)) { + + r = CMP(f->current_seqnum, l->seqnum); + if (r != 0) + return r; + } + + if (l->monotonic_set && + sd_id128_equal(f->current_boot_id, l->boot_id)) { + + r = CMP(f->current_monotonic, l->monotonic); + if (r != 0) + return r; + } + + if (l->realtime_set) { + + r = CMP(f->current_realtime, l->realtime); + if (r != 0) + return r; + } + + if (l->xor_hash_set) { + + r = CMP(f->current_xor_hash, l->xor_hash); + if (r != 0) + return r; + } + + return 0; +} + +static int next_for_match( + sd_journal *j, + Match *m, + JournalFile *f, + uint64_t after_offset, + direction_t direction, + Object **ret, + uint64_t *offset) { + + int r; + uint64_t np = 0; + Object *n; + + assert(j); + assert(m); + assert(f); + + if (m->type == MATCH_DISCRETE) { + uint64_t dp; + + r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp); + if (r <= 0) + return r; + + return journal_file_move_to_entry_by_offset_for_data(f, dp, after_offset, direction, ret, offset); + + } else if (m->type == MATCH_OR_TERM) { + Match *i; + + /* Find the earliest match beyond after_offset */ + + LIST_FOREACH(matches, i, m->matches) { + uint64_t cp; + + r = next_for_match(j, i, f, after_offset, direction, NULL, &cp); + if (r < 0) + return r; + else if (r > 0) { + if (np == 0 || (direction == DIRECTION_DOWN ? cp < np : cp > np)) + np = cp; + } + } + + if (np == 0) + return 0; + + } else if (m->type == MATCH_AND_TERM) { + Match *i, *last_moved; + + /* Always jump to the next matching entry and repeat + * this until we find an offset that matches for all + * matches. */ + + if (!m->matches) + return 0; + + r = next_for_match(j, m->matches, f, after_offset, direction, NULL, &np); + if (r <= 0) + return r; + + assert(direction == DIRECTION_DOWN ? np >= after_offset : np <= after_offset); + last_moved = m->matches; + + LIST_LOOP_BUT_ONE(matches, i, m->matches, last_moved) { + uint64_t cp; + + r = next_for_match(j, i, f, np, direction, NULL, &cp); + if (r <= 0) + return r; + + assert(direction == DIRECTION_DOWN ? cp >= np : cp <= np); + if (direction == DIRECTION_DOWN ? cp > np : cp < np) { + np = cp; + last_moved = i; + } + } + } + + assert(np > 0); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n); + if (r < 0) + return r; + + if (ret) + *ret = n; + if (offset) + *offset = np; + + return 1; +} + +static int find_location_for_match( + sd_journal *j, + Match *m, + JournalFile *f, + direction_t direction, + Object **ret, + uint64_t *offset) { + + int r; + + assert(j); + assert(m); + assert(f); + + if (m->type == MATCH_DISCRETE) { + uint64_t dp; + + r = journal_file_find_data_object_with_hash(f, m->data, m->size, le64toh(m->le_hash), NULL, &dp); + if (r <= 0) + return r; + + /* FIXME: missing: find by monotonic */ + + if (j->current_location.type == LOCATION_HEAD) + return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_DOWN, ret, offset); + if (j->current_location.type == LOCATION_TAIL) + return journal_file_next_entry_for_data(f, NULL, 0, dp, DIRECTION_UP, ret, offset); + if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) + return journal_file_move_to_entry_by_seqnum_for_data(f, dp, j->current_location.seqnum, direction, ret, offset); + if (j->current_location.monotonic_set) { + r = journal_file_move_to_entry_by_monotonic_for_data(f, dp, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset); + if (r != -ENOENT) + return r; + } + if (j->current_location.realtime_set) + return journal_file_move_to_entry_by_realtime_for_data(f, dp, j->current_location.realtime, direction, ret, offset); + + return journal_file_next_entry_for_data(f, NULL, 0, dp, direction, ret, offset); + + } else if (m->type == MATCH_OR_TERM) { + uint64_t np = 0; + Object *n; + Match *i; + + /* Find the earliest match */ + + LIST_FOREACH(matches, i, m->matches) { + uint64_t cp; + + r = find_location_for_match(j, i, f, direction, NULL, &cp); + if (r < 0) + return r; + else if (r > 0) { + if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp)) + np = cp; + } + } + + if (np == 0) + return 0; + + r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n); + if (r < 0) + return r; + + if (ret) + *ret = n; + if (offset) + *offset = np; + + return 1; + + } else { + Match *i; + uint64_t np = 0; + + assert(m->type == MATCH_AND_TERM); + + /* First jump to the last match, and then find the + * next one where all matches match */ + + if (!m->matches) + return 0; + + LIST_FOREACH(matches, i, m->matches) { + uint64_t cp; + + r = find_location_for_match(j, i, f, direction, NULL, &cp); + if (r <= 0) + return r; + + if (np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np)) + np = cp; + } + + return next_for_match(j, m, f, np, direction, ret, offset); + } +} + +static int find_location_with_matches( + sd_journal *j, + JournalFile *f, + direction_t direction, + Object **ret, + uint64_t *offset) { + + int r; + + assert(j); + assert(f); + assert(ret); + assert(offset); + + if (!j->level0) { + /* No matches is simple */ + + if (j->current_location.type == LOCATION_HEAD) + return journal_file_next_entry(f, 0, DIRECTION_DOWN, ret, offset); + if (j->current_location.type == LOCATION_TAIL) + return journal_file_next_entry(f, 0, DIRECTION_UP, ret, offset); + if (j->current_location.seqnum_set && sd_id128_equal(j->current_location.seqnum_id, f->header->seqnum_id)) + return journal_file_move_to_entry_by_seqnum(f, j->current_location.seqnum, direction, ret, offset); + if (j->current_location.monotonic_set) { + r = journal_file_move_to_entry_by_monotonic(f, j->current_location.boot_id, j->current_location.monotonic, direction, ret, offset); + if (r != -ENOENT) + return r; + } + if (j->current_location.realtime_set) + return journal_file_move_to_entry_by_realtime(f, j->current_location.realtime, direction, ret, offset); + + return journal_file_next_entry(f, 0, direction, ret, offset); + } else + return find_location_for_match(j, j->level0, f, direction, ret, offset); +} + +static int next_with_matches( + sd_journal *j, + JournalFile *f, + direction_t direction, + Object **ret, + uint64_t *offset) { + + assert(j); + assert(f); + assert(ret); + assert(offset); + + /* No matches is easy. We simple advance the file + * pointer by one. */ + if (!j->level0) + return journal_file_next_entry(f, f->current_offset, direction, ret, offset); + + /* If we have a match then we look for the next matching entry + * with an offset at least one step larger */ + return next_for_match(j, j->level0, f, + direction == DIRECTION_DOWN ? f->current_offset + 1 + : f->current_offset - 1, + direction, ret, offset); +} + +static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direction) { + Object *c; + uint64_t cp, n_entries; + int r; + + assert(j); + assert(f); + + n_entries = le64toh(f->header->n_entries); + + /* If we hit EOF before, we don't need to look into this file again + * unless direction changed or new entries appeared. */ + if (f->last_direction == direction && f->location_type == LOCATION_TAIL && + n_entries == f->last_n_entries) + return 0; + + f->last_n_entries = n_entries; + + if (f->last_direction == direction && f->current_offset > 0) { + /* LOCATION_SEEK here means we did the work in a previous + * iteration and the current location already points to a + * candidate entry. */ + if (f->location_type != LOCATION_SEEK) { + r = next_with_matches(j, f, direction, &c, &cp); + if (r <= 0) + return r; + + journal_file_save_location(f, c, cp); + } + } else { + f->last_direction = direction; + + r = find_location_with_matches(j, f, direction, &c, &cp); + if (r <= 0) + return r; + + journal_file_save_location(f, c, cp); + } + + /* OK, we found the spot, now let's advance until an entry + * that is actually different from what we were previously + * looking at. This is necessary to handle entries which exist + * in two (or more) journal files, and which shall all be + * suppressed but one. */ + + for (;;) { + bool found; + + if (j->current_location.type == LOCATION_DISCRETE) { + int k; + + k = compare_with_location(f, &j->current_location); + + found = direction == DIRECTION_DOWN ? k > 0 : k < 0; + } else + found = true; + + if (found) + return 1; + + r = next_with_matches(j, f, direction, &c, &cp); + if (r <= 0) + return r; + + journal_file_save_location(f, c, cp); + } +} + +static int real_journal_next(sd_journal *j, direction_t direction) { + JournalFile *new_file = NULL; + unsigned i, n_files; + const void **files; + Object *o; + int r; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + r = iterated_cache_get(j->files_cache, NULL, &files, &n_files); + if (r < 0) + return r; + + for (i = 0; i < n_files; i++) { + JournalFile *f = (JournalFile *)files[i]; + bool found; + + r = next_beyond_location(j, f, direction); + if (r < 0) { + log_debug_errno(r, "Can't iterate through %s, ignoring: %m", f->path); + remove_file_real(j, f); + continue; + } else if (r == 0) { + f->location_type = LOCATION_TAIL; + continue; + } + + if (!new_file) + found = true; + else { + int k; + + k = journal_file_compare_locations(f, new_file); + + found = direction == DIRECTION_DOWN ? k < 0 : k > 0; + } + + if (found) + new_file = f; + } + + if (!new_file) + return 0; + + r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_file->current_offset, &o); + if (r < 0) + return r; + + set_location(j, new_file, o); + + return 1; +} + +_public_ int sd_journal_next(sd_journal *j) { + return real_journal_next(j, DIRECTION_DOWN); +} + +_public_ int sd_journal_previous(sd_journal *j) { + return real_journal_next(j, DIRECTION_UP); +} + +static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t skip) { + int c = 0, r; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + if (skip == 0) { + /* If this is not a discrete skip, then at least + * resolve the current location */ + if (j->current_location.type != LOCATION_DISCRETE) { + r = real_journal_next(j, direction); + if (r < 0) + return r; + } + + return 0; + } + + do { + r = real_journal_next(j, direction); + if (r < 0) + return r; + + if (r == 0) + return c; + + skip--; + c++; + } while (skip > 0); + + return c; +} + +_public_ int sd_journal_next_skip(sd_journal *j, uint64_t skip) { + return real_journal_next_skip(j, DIRECTION_DOWN, skip); +} + +_public_ int sd_journal_previous_skip(sd_journal *j, uint64_t skip) { + return real_journal_next_skip(j, DIRECTION_UP, skip); +} + +_public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) { + Object *o; + int r; + char bid[33], sid[33]; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(cursor, -EINVAL); + + if (!j->current_file || j->current_file->current_offset <= 0) + return -EADDRNOTAVAIL; + + r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o); + if (r < 0) + return r; + + sd_id128_to_string(j->current_file->header->seqnum_id, sid); + sd_id128_to_string(o->entry.boot_id, bid); + + if (asprintf(cursor, + "s=%s;i=%"PRIx64";b=%s;m=%"PRIx64";t=%"PRIx64";x=%"PRIx64, + sid, le64toh(o->entry.seqnum), + bid, le64toh(o->entry.monotonic), + le64toh(o->entry.realtime), + le64toh(o->entry.xor_hash)) < 0) + return -ENOMEM; + + return 0; +} + +_public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) { + const char *word, *state; + size_t l; + unsigned long long seqnum, monotonic, realtime, xor_hash; + bool + seqnum_id_set = false, + seqnum_set = false, + boot_id_set = false, + monotonic_set = false, + realtime_set = false, + xor_hash_set = false; + sd_id128_t seqnum_id, boot_id; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!isempty(cursor), -EINVAL); + + FOREACH_WORD_SEPARATOR(word, l, cursor, ";", state) { + char *item; + int k = 0; + + if (l < 2 || word[1] != '=') + return -EINVAL; + + item = strndup(word, l); + if (!item) + return -ENOMEM; + + switch (word[0]) { + + case 's': + seqnum_id_set = true; + k = sd_id128_from_string(item+2, &seqnum_id); + break; + + case 'i': + seqnum_set = true; + if (sscanf(item+2, "%llx", &seqnum) != 1) + k = -EINVAL; + break; + + case 'b': + boot_id_set = true; + k = sd_id128_from_string(item+2, &boot_id); + break; + + case 'm': + monotonic_set = true; + if (sscanf(item+2, "%llx", &monotonic) != 1) + k = -EINVAL; + break; + + case 't': + realtime_set = true; + if (sscanf(item+2, "%llx", &realtime) != 1) + k = -EINVAL; + break; + + case 'x': + xor_hash_set = true; + if (sscanf(item+2, "%llx", &xor_hash) != 1) + k = -EINVAL; + break; + } + + free(item); + + if (k < 0) + return k; + } + + if ((!seqnum_set || !seqnum_id_set) && + (!monotonic_set || !boot_id_set) && + !realtime_set) + return -EINVAL; + + reset_location(j); + + j->current_location.type = LOCATION_SEEK; + + if (realtime_set) { + j->current_location.realtime = (uint64_t) realtime; + j->current_location.realtime_set = true; + } + + if (seqnum_set && seqnum_id_set) { + j->current_location.seqnum = (uint64_t) seqnum; + j->current_location.seqnum_id = seqnum_id; + j->current_location.seqnum_set = true; + } + + if (monotonic_set && boot_id_set) { + j->current_location.monotonic = (uint64_t) monotonic; + j->current_location.boot_id = boot_id; + j->current_location.monotonic_set = true; + } + + if (xor_hash_set) { + j->current_location.xor_hash = (uint64_t) xor_hash; + j->current_location.xor_hash_set = true; + } + + return 0; +} + +_public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) { + int r; + Object *o; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!isempty(cursor), -EINVAL); + + if (!j->current_file || j->current_file->current_offset <= 0) + return -EADDRNOTAVAIL; + + r = journal_file_move_to_object(j->current_file, OBJECT_ENTRY, j->current_file->current_offset, &o); + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *item = NULL; + unsigned long long ll; + sd_id128_t id; + int k = 0; + + r = extract_first_word(&cursor, &item, ";", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + + if (r == 0) + break; + + if (strlen(item) < 2 || item[1] != '=') + return -EINVAL; + + switch (item[0]) { + + case 's': + k = sd_id128_from_string(item+2, &id); + if (k < 0) + return k; + if (!sd_id128_equal(id, j->current_file->header->seqnum_id)) + return 0; + break; + + case 'i': + if (sscanf(item+2, "%llx", &ll) != 1) + return -EINVAL; + if (ll != le64toh(o->entry.seqnum)) + return 0; + break; + + case 'b': + k = sd_id128_from_string(item+2, &id); + if (k < 0) + return k; + if (!sd_id128_equal(id, o->entry.boot_id)) + return 0; + break; + + case 'm': + if (sscanf(item+2, "%llx", &ll) != 1) + return -EINVAL; + if (ll != le64toh(o->entry.monotonic)) + return 0; + break; + + case 't': + if (sscanf(item+2, "%llx", &ll) != 1) + return -EINVAL; + if (ll != le64toh(o->entry.realtime)) + return 0; + break; + + case 'x': + if (sscanf(item+2, "%llx", &ll) != 1) + return -EINVAL; + if (ll != le64toh(o->entry.xor_hash)) + return 0; + break; + } + } + + return 1; +} + +_public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) { + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + reset_location(j); + j->current_location.type = LOCATION_SEEK; + j->current_location.boot_id = boot_id; + j->current_location.monotonic = usec; + j->current_location.monotonic_set = true; + + return 0; +} + +_public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) { + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + reset_location(j); + j->current_location.type = LOCATION_SEEK; + j->current_location.realtime = usec; + j->current_location.realtime_set = true; + + return 0; +} + +_public_ int sd_journal_seek_head(sd_journal *j) { + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + reset_location(j); + j->current_location.type = LOCATION_HEAD; + + return 0; +} + +_public_ int sd_journal_seek_tail(sd_journal *j) { + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + reset_location(j); + j->current_location.type = LOCATION_TAIL; + + return 0; +} + +static void check_network(sd_journal *j, int fd) { + assert(j); + + if (j->on_network) + return; + + j->on_network = fd_is_network_fs(fd); +} + +static bool file_has_type_prefix(const char *prefix, const char *filename) { + const char *full, *tilded, *atted; + + full = strjoina(prefix, ".journal"); + tilded = strjoina(full, "~"); + atted = strjoina(prefix, "@"); + + return STR_IN_SET(filename, full, tilded) || + startswith(filename, atted); +} + +static bool file_type_wanted(int flags, const char *filename) { + assert(filename); + + if (!endswith(filename, ".journal") && !endswith(filename, ".journal~")) + return false; + + /* no flags set → every type is OK */ + if (!(flags & (SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER))) + return true; + + if (flags & SD_JOURNAL_SYSTEM && file_has_type_prefix("system", filename)) + return true; + + if (flags & SD_JOURNAL_CURRENT_USER) { + char prefix[5 + DECIMAL_STR_MAX(uid_t) + 1]; + + xsprintf(prefix, "user-"UID_FMT, getuid()); + + if (file_has_type_prefix(prefix, filename)) + return true; + } + + return false; +} + +static bool path_has_prefix(sd_journal *j, const char *path, const char *prefix) { + assert(j); + assert(path); + assert(prefix); + + if (j->toplevel_fd >= 0) + return false; + + return path_startswith(path, prefix); +} + +static void track_file_disposition(sd_journal *j, JournalFile *f) { + assert(j); + assert(f); + + if (!j->has_runtime_files && path_has_prefix(j, f->path, "/run")) + j->has_runtime_files = true; + else if (!j->has_persistent_files && path_has_prefix(j, f->path, "/var")) + j->has_persistent_files = true; +} + +static const char *skip_slash(const char *p) { + + if (!p) + return NULL; + + while (*p == '/') + p++; + + return p; +} + +static int add_any_file( + sd_journal *j, + int fd, + const char *path) { + + bool close_fd = false; + JournalFile *f; + struct stat st; + int r, k; + + assert(j); + assert(fd >= 0 || path); + + if (fd < 0) { + if (j->toplevel_fd >= 0) + /* If there's a top-level fd defined make the path relative, explicitly, since otherwise + * openat() ignores the first argument. */ + + fd = openat(j->toplevel_fd, skip_slash(path), O_RDONLY|O_CLOEXEC|O_NONBLOCK); + else + fd = open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) { + r = log_debug_errno(errno, "Failed to open journal file %s: %m", path); + goto finish; + } + + close_fd = true; + + r = fd_nonblock(fd, false); + if (r < 0) { + r = log_debug_errno(errno, "Failed to turn off O_NONBLOCK for %s: %m", path); + goto finish; + } + } + + if (fstat(fd, &st) < 0) { + r = log_debug_errno(errno, "Failed to fstat file '%s': %m", path); + goto finish; + } + + r = stat_verify_regular(&st); + if (r < 0) { + log_debug_errno(r, "Refusing to open '%s', as it is not a regular file.", path); + goto finish; + } + + f = ordered_hashmap_get(j->files, path); + if (f) { + if (f->last_stat.st_dev == st.st_dev && + f->last_stat.st_ino == st.st_ino) { + + /* We already track this file, under the same path and with the same device/inode numbers, it's + * hence really the same. Mark this file as seen in this generation. This is used to GC old + * files in process_q_overflow() to detect journal files that are still there and discern them + * from those which are gone. */ + + f->last_seen_generation = j->generation; + r = 0; + goto finish; + } + + /* So we tracked a file under this name, but it has a different inode/device. In that case, it got + * replaced (probably due to rotation?), let's drop it hence from our list. */ + remove_file_real(j, f); + f = NULL; + } + + if (ordered_hashmap_size(j->files) >= JOURNAL_FILES_MAX) { + log_debug("Too many open journal files, not adding %s.", path); + r = -ETOOMANYREFS; + goto finish; + } + + r = journal_file_open(fd, path, O_RDONLY, 0, false, 0, false, NULL, j->mmap, NULL, NULL, &f); + if (r < 0) { + log_debug_errno(r, "Failed to open journal file %s: %m", path); + goto finish; + } + + /* journal_file_dump(f); */ + + r = ordered_hashmap_put(j->files, f->path, f); + if (r < 0) { + f->close_fd = false; /* make sure journal_file_close() doesn't close the caller's fd (or our own). We'll let the caller do that, or ourselves */ + (void) journal_file_close(f); + goto finish; + } + + close_fd = false; /* the fd is now owned by the JournalFile object */ + + f->last_seen_generation = j->generation; + + track_file_disposition(j, f); + check_network(j, f->fd); + + j->current_invalidate_counter++; + + log_debug("File %s added.", f->path); + + r = 0; + +finish: + if (close_fd) + safe_close(fd); + + if (r < 0) { + k = journal_put_error(j, r, path); + if (k < 0) + return k; + } + + return r; +} + +static int add_file_by_name( + sd_journal *j, + const char *prefix, + const char *filename) { + + const char *path; + + assert(j); + assert(prefix); + assert(filename); + + if (j->no_new_files) + return 0; + + if (!file_type_wanted(j->flags, filename)) + return 0; + + path = prefix_roota(prefix, filename); + return add_any_file(j, -1, path); +} + +static void remove_file_by_name( + sd_journal *j, + const char *prefix, + const char *filename) { + + const char *path; + JournalFile *f; + + assert(j); + assert(prefix); + assert(filename); + + path = prefix_roota(prefix, filename); + f = ordered_hashmap_get(j->files, path); + if (!f) + return; + + remove_file_real(j, f); +} + +static void remove_file_real(sd_journal *j, JournalFile *f) { + assert(j); + assert(f); + + (void) ordered_hashmap_remove(j->files, f->path); + + log_debug("File %s removed.", f->path); + + if (j->current_file == f) { + j->current_file = NULL; + j->current_field = 0; + } + + if (j->unique_file == f) { + /* Jump to the next unique_file or NULL if that one was last */ + j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path); + j->unique_offset = 0; + if (!j->unique_file) + j->unique_file_lost = true; + } + + if (j->fields_file == f) { + j->fields_file = ordered_hashmap_next(j->files, j->fields_file->path); + j->fields_offset = 0; + if (!j->fields_file) + j->fields_file_lost = true; + } + + (void) journal_file_close(f); + + j->current_invalidate_counter++; +} + +static int dirname_is_machine_id(const char *fn) { + sd_id128_t id, machine; + int r; + + r = sd_id128_get_machine(&machine); + if (r < 0) + return r; + + r = sd_id128_from_string(fn, &id); + if (r < 0) + return r; + + return sd_id128_equal(id, machine); +} + +static bool dirent_is_journal_file(const struct dirent *de) { + assert(de); + + if (!IN_SET(de->d_type, DT_REG, DT_LNK, DT_UNKNOWN)) + return false; + + return endswith(de->d_name, ".journal") || + endswith(de->d_name, ".journal~"); +} + +static bool dirent_is_id128_subdir(const struct dirent *de) { + assert(de); + + if (!IN_SET(de->d_type, DT_DIR, DT_LNK, DT_UNKNOWN)) + return false; + + return id128_is_valid(de->d_name); +} + +static int directory_open(sd_journal *j, const char *path, DIR **ret) { + DIR *d; + + assert(j); + assert(path); + assert(ret); + + if (j->toplevel_fd < 0) + d = opendir(path); + else + /* Open the specified directory relative to the toplevel fd. Enforce that the path specified is + * relative, by dropping the initial slash */ + d = xopendirat(j->toplevel_fd, skip_slash(path), 0); + if (!d) + return -errno; + + *ret = d; + return 0; +} + +static int add_directory(sd_journal *j, const char *prefix, const char *dirname); + +static void directory_enumerate(sd_journal *j, Directory *m, DIR *d) { + struct dirent *de; + + assert(j); + assert(m); + assert(d); + + FOREACH_DIRENT_ALL(de, d, goto fail) { + + if (dirent_is_journal_file(de)) + (void) add_file_by_name(j, m->path, de->d_name); + + if (m->is_root && dirent_is_id128_subdir(de)) + (void) add_directory(j, m->path, de->d_name); + } + + return; + +fail: + log_debug_errno(errno, "Failed to enumerate directory %s, ignoring: %m", m->path); +} + +static void directory_watch(sd_journal *j, Directory *m, int fd, uint32_t mask) { + int r; + + assert(j); + assert(m); + assert(fd >= 0); + + /* Watch this directory if that's enabled and if it not being watched yet. */ + + if (m->wd > 0) /* Already have a watch? */ + return; + if (j->inotify_fd < 0) /* Not watching at all? */ + return; + + m->wd = inotify_add_watch_fd(j->inotify_fd, fd, mask); + if (m->wd < 0) { + log_debug_errno(errno, "Failed to watch journal directory '%s', ignoring: %m", m->path); + return; + } + + r = hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m); + if (r == -EEXIST) + log_debug_errno(r, "Directory '%s' already being watched under a different path, ignoring: %m", m->path); + if (r < 0) { + log_debug_errno(r, "Failed to add watch for journal directory '%s' to hashmap, ignoring: %m", m->path); + (void) inotify_rm_watch(j->inotify_fd, m->wd); + m->wd = -1; + } +} + +static int add_directory(sd_journal *j, const char *prefix, const char *dirname) { + _cleanup_free_ char *path = NULL; + _cleanup_closedir_ DIR *d = NULL; + Directory *m; + int r, k; + + assert(j); + assert(prefix); + + /* Adds a journal file directory to watch. If the directory is already tracked this updates the inotify watch + * and reenumerates directory contents */ + + path = path_join(prefix, dirname); + if (!path) { + r = -ENOMEM; + goto fail; + } + + log_debug("Considering directory '%s'.", path); + + /* We consider everything local that is in a directory for the local machine ID, or that is stored in /run */ + if ((j->flags & SD_JOURNAL_LOCAL_ONLY) && + !((dirname && dirname_is_machine_id(dirname) > 0) || path_has_prefix(j, path, "/run"))) + return 0; + + r = directory_open(j, path, &d); + if (r < 0) { + log_debug_errno(r, "Failed to open directory '%s': %m", path); + goto fail; + } + + m = hashmap_get(j->directories_by_path, path); + if (!m) { + m = new0(Directory, 1); + if (!m) { + r = -ENOMEM; + goto fail; + } + + m->is_root = false; + m->path = path; + + if (hashmap_put(j->directories_by_path, m->path, m) < 0) { + free(m); + r = -ENOMEM; + goto fail; + } + + path = NULL; /* avoid freeing in cleanup */ + j->current_invalidate_counter++; + + log_debug("Directory %s added.", m->path); + + } else if (m->is_root) + return 0; /* Don't 'downgrade' from root directory */ + + m->last_seen_generation = j->generation; + + directory_watch(j, m, dirfd(d), + IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| + IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_MOVED_FROM| + IN_ONLYDIR); + + if (!j->no_new_files) + directory_enumerate(j, m, d); + + check_network(j, dirfd(d)); + + return 0; + +fail: + k = journal_put_error(j, r, path ?: prefix); + if (k < 0) + return k; + + return r; +} + +static int add_root_directory(sd_journal *j, const char *p, bool missing_ok) { + + _cleanup_closedir_ DIR *d = NULL; + Directory *m; + int r, k; + + assert(j); + + /* Adds a root directory to our set of directories to use. If the root directory is already in the set, we + * update the inotify logic, and renumerate the directory entries. This call may hence be called to initially + * populate the set, as well as to update it later. */ + + if (p) { + /* If there's a path specified, use it. */ + + log_debug("Considering root directory '%s'.", p); + + if ((j->flags & SD_JOURNAL_RUNTIME_ONLY) && + !path_has_prefix(j, p, "/run")) + return -EINVAL; + + if (j->prefix) + p = strjoina(j->prefix, p); + + r = directory_open(j, p, &d); + if (r == -ENOENT && missing_ok) + return 0; + if (r < 0) { + log_debug_errno(r, "Failed to open root directory %s: %m", p); + goto fail; + } + } else { + int dfd; + + /* If there's no path specified, then we use the top-level fd itself. We duplicate the fd here, since + * opendir() will take possession of the fd, and close it, which we don't want. */ + + p = "."; /* store this as "." in the directories hashmap */ + + dfd = fcntl(j->toplevel_fd, F_DUPFD_CLOEXEC, 3); + if (dfd < 0) { + r = -errno; + goto fail; + } + + d = fdopendir(dfd); + if (!d) { + r = -errno; + safe_close(dfd); + goto fail; + } + + rewinddir(d); + } + + m = hashmap_get(j->directories_by_path, p); + if (!m) { + m = new0(Directory, 1); + if (!m) { + r = -ENOMEM; + goto fail; + } + + m->is_root = true; + + m->path = strdup(p); + if (!m->path) { + free(m); + r = -ENOMEM; + goto fail; + } + + if (hashmap_put(j->directories_by_path, m->path, m) < 0) { + free(m->path); + free(m); + r = -ENOMEM; + goto fail; + } + + j->current_invalidate_counter++; + + log_debug("Root directory %s added.", m->path); + + } else if (!m->is_root) + return 0; + + directory_watch(j, m, dirfd(d), + IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE| + IN_ONLYDIR); + + if (!j->no_new_files) + directory_enumerate(j, m, d); + + check_network(j, dirfd(d)); + + return 0; + +fail: + k = journal_put_error(j, r, p); + if (k < 0) + return k; + + return r; +} + +static void remove_directory(sd_journal *j, Directory *d) { + assert(j); + + if (d->wd > 0) { + hashmap_remove(j->directories_by_wd, INT_TO_PTR(d->wd)); + + if (j->inotify_fd >= 0) + (void) inotify_rm_watch(j->inotify_fd, d->wd); + } + + hashmap_remove(j->directories_by_path, d->path); + + if (d->is_root) + log_debug("Root directory %s removed.", d->path); + else + log_debug("Directory %s removed.", d->path); + + free(d->path); + free(d); +} + +static int add_search_paths(sd_journal *j) { + + static const char search_paths[] = + "/run/log/journal\0" + "/var/log/journal\0"; + const char *p; + + assert(j); + + /* We ignore most errors here, since the idea is to only open + * what's actually accessible, and ignore the rest. */ + + NULSTR_FOREACH(p, search_paths) + (void) add_root_directory(j, p, true); + + if (!(j->flags & SD_JOURNAL_LOCAL_ONLY)) + (void) add_root_directory(j, "/var/log/journal/remote", true); + + return 0; +} + +static int add_current_paths(sd_journal *j) { + Iterator i; + JournalFile *f; + + assert(j); + assert(j->no_new_files); + + /* Simply adds all directories for files we have open as directories. We don't expect errors here, so we + * treat them as fatal. */ + + ORDERED_HASHMAP_FOREACH(f, j->files, i) { + _cleanup_free_ char *dir; + int r; + + dir = dirname_malloc(f->path); + if (!dir) + return -ENOMEM; + + r = add_directory(j, dir, NULL); + if (r < 0) + return r; + } + + return 0; +} + +static int allocate_inotify(sd_journal *j) { + assert(j); + + if (j->inotify_fd < 0) { + j->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (j->inotify_fd < 0) + return -errno; + } + + return hashmap_ensure_allocated(&j->directories_by_wd, NULL); +} + +static sd_journal *journal_new(int flags, const char *path) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + + j = new0(sd_journal, 1); + if (!j) + return NULL; + + j->original_pid = getpid_cached(); + j->toplevel_fd = -1; + j->inotify_fd = -1; + j->flags = flags; + j->data_threshold = DEFAULT_DATA_THRESHOLD; + + if (path) { + char *t; + + t = strdup(path); + if (!t) + return NULL; + + if (flags & SD_JOURNAL_OS_ROOT) + j->prefix = t; + else + j->path = t; + } + + j->files = ordered_hashmap_new(&path_hash_ops); + if (!j->files) + return NULL; + + j->files_cache = ordered_hashmap_iterated_cache_new(j->files); + j->directories_by_path = hashmap_new(&path_hash_ops); + j->mmap = mmap_cache_new(); + if (!j->files_cache || !j->directories_by_path || !j->mmap) + return NULL; + + return TAKE_PTR(j); +} + +#define OPEN_ALLOWED_FLAGS \ + (SD_JOURNAL_LOCAL_ONLY | \ + SD_JOURNAL_RUNTIME_ONLY | \ + SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER) + +_public_ int sd_journal_open(sd_journal **ret, int flags) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + int r; + + assert_return(ret, -EINVAL); + assert_return((flags & ~OPEN_ALLOWED_FLAGS) == 0, -EINVAL); + + j = journal_new(flags, NULL); + if (!j) + return -ENOMEM; + + r = add_search_paths(j); + if (r < 0) + return r; + + *ret = TAKE_PTR(j); + return 0; +} + +#define OPEN_CONTAINER_ALLOWED_FLAGS \ + (SD_JOURNAL_LOCAL_ONLY | SD_JOURNAL_SYSTEM) + +_public_ int sd_journal_open_container(sd_journal **ret, const char *machine, int flags) { + _cleanup_free_ char *root = NULL, *class = NULL; + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + char *p; + int r; + + /* This is pretty much deprecated, people should use machined's OpenMachineRootDirectory() call instead in + * combination with sd_journal_open_directory_fd(). */ + + assert_return(machine, -EINVAL); + assert_return(ret, -EINVAL); + assert_return((flags & ~OPEN_CONTAINER_ALLOWED_FLAGS) == 0, -EINVAL); + assert_return(machine_name_is_valid(machine), -EINVAL); + + p = strjoina("/run/systemd/machines/", machine); + r = parse_env_file(NULL, p, + "ROOT", &root, + "CLASS", &class); + if (r == -ENOENT) + return -EHOSTDOWN; + if (r < 0) + return r; + if (!root) + return -ENODATA; + + if (!streq_ptr(class, "container")) + return -EIO; + + j = journal_new(flags, root); + if (!j) + return -ENOMEM; + + r = add_search_paths(j); + if (r < 0) + return r; + + *ret = TAKE_PTR(j); + return 0; +} + +#define OPEN_DIRECTORY_ALLOWED_FLAGS \ + (SD_JOURNAL_OS_ROOT | \ + SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER ) + +_public_ int sd_journal_open_directory(sd_journal **ret, const char *path, int flags) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + int r; + + assert_return(ret, -EINVAL); + assert_return(path, -EINVAL); + assert_return((flags & ~OPEN_DIRECTORY_ALLOWED_FLAGS) == 0, -EINVAL); + + j = journal_new(flags, path); + if (!j) + return -ENOMEM; + + if (flags & SD_JOURNAL_OS_ROOT) + r = add_search_paths(j); + else + r = add_root_directory(j, path, false); + if (r < 0) + return r; + + *ret = TAKE_PTR(j); + return 0; +} + +_public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + const char **path; + int r; + + assert_return(ret, -EINVAL); + assert_return(flags == 0, -EINVAL); + + j = journal_new(flags, NULL); + if (!j) + return -ENOMEM; + + STRV_FOREACH(path, paths) { + r = add_any_file(j, -1, *path); + if (r < 0) + return r; + } + + j->no_new_files = true; + + *ret = TAKE_PTR(j); + return 0; +} + +#define OPEN_DIRECTORY_FD_ALLOWED_FLAGS \ + (SD_JOURNAL_OS_ROOT | \ + SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER ) + +_public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + struct stat st; + int r; + + assert_return(ret, -EINVAL); + assert_return(fd >= 0, -EBADF); + assert_return((flags & ~OPEN_DIRECTORY_FD_ALLOWED_FLAGS) == 0, -EINVAL); + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISDIR(st.st_mode)) + return -EBADFD; + + j = journal_new(flags, NULL); + if (!j) + return -ENOMEM; + + j->toplevel_fd = fd; + + if (flags & SD_JOURNAL_OS_ROOT) + r = add_search_paths(j); + else + r = add_root_directory(j, NULL, false); + if (r < 0) + return r; + + *ret = TAKE_PTR(j); + return 0; +} + +_public_ int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags) { + Iterator iterator; + JournalFile *f; + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + unsigned i; + int r; + + assert_return(ret, -EINVAL); + assert_return(n_fds > 0, -EBADF); + assert_return(flags == 0, -EINVAL); + + j = journal_new(flags, NULL); + if (!j) + return -ENOMEM; + + for (i = 0; i < n_fds; i++) { + struct stat st; + + if (fds[i] < 0) { + r = -EBADF; + goto fail; + } + + if (fstat(fds[i], &st) < 0) { + r = -errno; + goto fail; + } + + r = stat_verify_regular(&st); + if (r < 0) + goto fail; + + r = add_any_file(j, fds[i], NULL); + if (r < 0) + goto fail; + } + + j->no_new_files = true; + j->no_inotify = true; + + *ret = TAKE_PTR(j); + return 0; + +fail: + /* If we fail, make sure we don't take possession of the files we managed to make use of successfully, and they + * remain open */ + ORDERED_HASHMAP_FOREACH(f, j->files, iterator) + f->close_fd = false; + + return r; +} + +_public_ void sd_journal_close(sd_journal *j) { + Directory *d; + + if (!j) + return; + + sd_journal_flush_matches(j); + + ordered_hashmap_free_with_destructor(j->files, journal_file_close); + iterated_cache_free(j->files_cache); + + while ((d = hashmap_first(j->directories_by_path))) + remove_directory(j, d); + + while ((d = hashmap_first(j->directories_by_wd))) + remove_directory(j, d); + + hashmap_free(j->directories_by_path); + hashmap_free(j->directories_by_wd); + + safe_close(j->inotify_fd); + + if (j->mmap) { + log_debug("mmap cache statistics: %u hit, %u miss", mmap_cache_get_hit(j->mmap), mmap_cache_get_missed(j->mmap)); + mmap_cache_unref(j->mmap); + } + + hashmap_free_free(j->errors); + + free(j->path); + free(j->prefix); + free(j->unique_field); + free(j->fields_buffer); + free(j); +} + +_public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) { + Object *o; + JournalFile *f; + int r; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(ret, -EINVAL); + + f = j->current_file; + if (!f) + return -EADDRNOTAVAIL; + + if (f->current_offset <= 0) + return -EADDRNOTAVAIL; + + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); + if (r < 0) + return r; + + *ret = le64toh(o->entry.realtime); + return 0; +} + +_public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id) { + Object *o; + JournalFile *f; + int r; + sd_id128_t id; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + f = j->current_file; + if (!f) + return -EADDRNOTAVAIL; + + if (f->current_offset <= 0) + return -EADDRNOTAVAIL; + + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); + if (r < 0) + return r; + + if (ret_boot_id) + *ret_boot_id = o->entry.boot_id; + else { + r = sd_id128_get_boot(&id); + if (r < 0) + return r; + + if (!sd_id128_equal(id, o->entry.boot_id)) + return -ESTALE; + } + + if (ret) + *ret = le64toh(o->entry.monotonic); + + return 0; +} + +static bool field_is_valid(const char *field) { + const char *p; + + assert(field); + + if (isempty(field)) + return false; + + if (startswith(field, "__")) + return false; + + for (p = field; *p; p++) { + + if (*p == '_') + continue; + + if (*p >= 'A' && *p <= 'Z') + continue; + + if (*p >= '0' && *p <= '9') + continue; + + return false; + } + + return true; +} + +_public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *size) { + JournalFile *f; + uint64_t i, n; + size_t field_length; + int r; + Object *o; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(field, -EINVAL); + assert_return(data, -EINVAL); + assert_return(size, -EINVAL); + assert_return(field_is_valid(field), -EINVAL); + + f = j->current_file; + if (!f) + return -EADDRNOTAVAIL; + + if (f->current_offset <= 0) + return -EADDRNOTAVAIL; + + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); + if (r < 0) + return r; + + field_length = strlen(field); + + n = journal_file_entry_n_items(o); + for (i = 0; i < n; i++) { + uint64_t p, l; + le64_t le_hash; + size_t t; + int compression; + + p = le64toh(o->entry.items[i].object_offset); + le_hash = o->entry.items[i].hash; + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + if (le_hash != o->data.hash) + return -EBADMSG; + + l = le64toh(o->object.size) - offsetof(Object, data.payload); + + compression = o->object.flags & OBJECT_COMPRESSION_MASK; + if (compression) { +#if HAVE_XZ || HAVE_LZ4 + r = decompress_startswith(compression, + o->data.payload, l, + &f->compress_buffer, &f->compress_buffer_size, + field, field_length, '='); + if (r < 0) + log_debug_errno(r, "Cannot decompress %s object of length %"PRIu64" at offset "OFSfmt": %m", + object_compressed_to_string(compression), l, p); + else if (r > 0) { + + size_t rsize; + + r = decompress_blob(compression, + o->data.payload, l, + &f->compress_buffer, &f->compress_buffer_size, &rsize, + j->data_threshold); + if (r < 0) + return r; + + *data = f->compress_buffer; + *size = (size_t) rsize; + + return 0; + } +#else + return -EPROTONOSUPPORT; +#endif + } else if (l >= field_length+1 && + memcmp(o->data.payload, field, field_length) == 0 && + o->data.payload[field_length] == '=') { + + t = (size_t) l; + + if ((uint64_t) t != l) + return -E2BIG; + + *data = o->data.payload; + *size = t; + + return 0; + } + + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); + if (r < 0) + return r; + } + + return -ENOENT; +} + +static int return_data(sd_journal *j, JournalFile *f, Object *o, const void **data, size_t *size) { + size_t t; + uint64_t l; + int compression; + + l = le64toh(o->object.size) - offsetof(Object, data.payload); + t = (size_t) l; + + /* We can't read objects larger than 4G on a 32bit machine */ + if ((uint64_t) t != l) + return -E2BIG; + + compression = o->object.flags & OBJECT_COMPRESSION_MASK; + if (compression) { +#if HAVE_XZ || HAVE_LZ4 + size_t rsize; + int r; + + r = decompress_blob(compression, + o->data.payload, l, &f->compress_buffer, + &f->compress_buffer_size, &rsize, j->data_threshold); + if (r < 0) + return r; + + *data = f->compress_buffer; + *size = (size_t) rsize; +#else + return -EPROTONOSUPPORT; +#endif + } else { + *data = o->data.payload; + *size = t; + } + + return 0; +} + +_public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *size) { + JournalFile *f; + uint64_t p, n; + le64_t le_hash; + int r; + Object *o; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(data, -EINVAL); + assert_return(size, -EINVAL); + + f = j->current_file; + if (!f) + return -EADDRNOTAVAIL; + + if (f->current_offset <= 0) + return -EADDRNOTAVAIL; + + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); + if (r < 0) + return r; + + n = journal_file_entry_n_items(o); + if (j->current_field >= n) + return 0; + + p = le64toh(o->entry.items[j->current_field].object_offset); + le_hash = o->entry.items[j->current_field].hash; + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + if (le_hash != o->data.hash) + return -EBADMSG; + + r = return_data(j, f, o, data, size); + if (r < 0) + return r; + + j->current_field++; + + return 1; +} + +_public_ void sd_journal_restart_data(sd_journal *j) { + if (!j) + return; + + j->current_field = 0; +} + +static int reiterate_all_paths(sd_journal *j) { + assert(j); + + if (j->no_new_files) + return add_current_paths(j); + + if (j->flags & SD_JOURNAL_OS_ROOT) + return add_search_paths(j); + + if (j->toplevel_fd >= 0) + return add_root_directory(j, NULL, false); + + if (j->path) + return add_root_directory(j, j->path, true); + + return add_search_paths(j); +} + +_public_ int sd_journal_get_fd(sd_journal *j) { + int r; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + if (j->no_inotify) + return -EMEDIUMTYPE; + + if (j->inotify_fd >= 0) + return j->inotify_fd; + + r = allocate_inotify(j); + if (r < 0) + return r; + + log_debug("Reiterating files to get inotify watches established."); + + /* Iterate through all dirs again, to add them to the inotify */ + r = reiterate_all_paths(j); + if (r < 0) + return r; + + return j->inotify_fd; +} + +_public_ int sd_journal_get_events(sd_journal *j) { + int fd; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + fd = sd_journal_get_fd(j); + if (fd < 0) + return fd; + + return POLLIN; +} + +_public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) { + int fd; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(timeout_usec, -EINVAL); + + fd = sd_journal_get_fd(j); + if (fd < 0) + return fd; + + if (!j->on_network) { + *timeout_usec = (uint64_t) -1; + return 0; + } + + /* If we are on the network we need to regularly check for + * changes manually */ + + *timeout_usec = j->last_process_usec + JOURNAL_FILES_RECHECK_USEC; + return 1; +} + +static void process_q_overflow(sd_journal *j) { + JournalFile *f; + Directory *m; + Iterator i; + + assert(j); + + /* When the inotify queue overruns we need to enumerate and re-validate all journal files to bring our list + * back in sync with what's on disk. For this we pick a new generation counter value. It'll be assigned to all + * journal files we encounter. All journal files and all directories that don't carry it after reenumeration + * are subject for unloading. */ + + log_debug("Inotify queue overrun, reiterating everything."); + + j->generation++; + (void) reiterate_all_paths(j); + + ORDERED_HASHMAP_FOREACH(f, j->files, i) { + + if (f->last_seen_generation == j->generation) + continue; + + log_debug("File '%s' hasn't been seen in this enumeration, removing.", f->path); + remove_file_real(j, f); + } + + HASHMAP_FOREACH(m, j->directories_by_path, i) { + + if (m->last_seen_generation == j->generation) + continue; + + if (m->is_root) /* Never GC root directories */ + continue; + + log_debug("Directory '%s' hasn't been seen in this enumeration, removing.", f->path); + remove_directory(j, m); + } + + log_debug("Reiteration complete."); +} + +static void process_inotify_event(sd_journal *j, struct inotify_event *e) { + Directory *d; + + assert(j); + assert(e); + + if (e->mask & IN_Q_OVERFLOW) { + process_q_overflow(j); + return; + } + + /* Is this a subdirectory we watch? */ + d = hashmap_get(j->directories_by_wd, INT_TO_PTR(e->wd)); + if (d) { + if (!(e->mask & IN_ISDIR) && e->len > 0 && + (endswith(e->name, ".journal") || + endswith(e->name, ".journal~"))) { + + /* Event for a journal file */ + + if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) + (void) add_file_by_name(j, d->path, e->name); + else if (e->mask & (IN_DELETE|IN_MOVED_FROM|IN_UNMOUNT)) + remove_file_by_name(j, d->path, e->name); + + } else if (!d->is_root && e->len == 0) { + + /* Event for a subdirectory */ + + if (e->mask & (IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)) + remove_directory(j, d); + + } else if (d->is_root && (e->mask & IN_ISDIR) && e->len > 0 && id128_is_valid(e->name)) { + + /* Event for root directory */ + + if (e->mask & (IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB)) + (void) add_directory(j, d->path, e->name); + } + + return; + } + + if (e->mask & IN_IGNORED) + return; + + log_debug("Unexpected inotify event."); +} + +static int determine_change(sd_journal *j) { + bool b; + + assert(j); + + b = j->current_invalidate_counter != j->last_invalidate_counter; + j->last_invalidate_counter = j->current_invalidate_counter; + + return b ? SD_JOURNAL_INVALIDATE : SD_JOURNAL_APPEND; +} + +_public_ int sd_journal_process(sd_journal *j) { + bool got_something = false; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + if (j->inotify_fd < 0) /* We have no inotify fd yet? Then there's noting to process. */ + return 0; + + j->last_process_usec = now(CLOCK_MONOTONIC); + j->last_invalidate_counter = j->current_invalidate_counter; + + for (;;) { + union inotify_event_buffer buffer; + struct inotify_event *e; + ssize_t l; + + l = read(j->inotify_fd, &buffer, sizeof(buffer)); + if (l < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return got_something ? determine_change(j) : SD_JOURNAL_NOP; + + return -errno; + } + + got_something = true; + + FOREACH_INOTIFY_EVENT(e, buffer, l) + process_inotify_event(j, e); + } +} + +_public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { + int r; + uint64_t t; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + if (j->inotify_fd < 0) { + + /* This is the first invocation, hence create the + * inotify watch */ + r = sd_journal_get_fd(j); + if (r < 0) + return r; + + /* The journal might have changed since the context + * object was created and we weren't watching before, + * hence don't wait for anything, and return + * immediately. */ + return determine_change(j); + } + + r = sd_journal_get_timeout(j, &t); + if (r < 0) + return r; + + if (t != (uint64_t) -1) { + usec_t n; + + n = now(CLOCK_MONOTONIC); + t = t > n ? t - n : 0; + + if (timeout_usec == (uint64_t) -1 || timeout_usec > t) + timeout_usec = t; + } + + do { + r = fd_wait_for_event(j->inotify_fd, POLLIN, timeout_usec); + } while (r == -EINTR); + + if (r < 0) + return r; + + return sd_journal_process(j); +} + +_public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) { + Iterator i; + JournalFile *f; + bool first = true; + uint64_t fmin = 0, tmax = 0; + int r; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(from || to, -EINVAL); + assert_return(from != to, -EINVAL); + + ORDERED_HASHMAP_FOREACH(f, j->files, i) { + usec_t fr, t; + + r = journal_file_get_cutoff_realtime_usec(f, &fr, &t); + if (r == -ENOENT) + continue; + if (r < 0) + return r; + if (r == 0) + continue; + + if (first) { + fmin = fr; + tmax = t; + first = false; + } else { + fmin = MIN(fr, fmin); + tmax = MAX(t, tmax); + } + } + + if (from) + *from = fmin; + if (to) + *to = tmax; + + return first ? 0 : 1; +} + +_public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) { + Iterator i; + JournalFile *f; + bool found = false; + int r; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(from || to, -EINVAL); + assert_return(from != to, -EINVAL); + + ORDERED_HASHMAP_FOREACH(f, j->files, i) { + usec_t fr, t; + + r = journal_file_get_cutoff_monotonic_usec(f, boot_id, &fr, &t); + if (r == -ENOENT) + continue; + if (r < 0) + return r; + if (r == 0) + continue; + + if (found) { + if (from) + *from = MIN(fr, *from); + if (to) + *to = MAX(t, *to); + } else { + if (from) + *from = fr; + if (to) + *to = t; + found = true; + } + } + + return found; +} + +void journal_print_header(sd_journal *j) { + Iterator i; + JournalFile *f; + bool newline = false; + + assert(j); + + ORDERED_HASHMAP_FOREACH(f, j->files, i) { + if (newline) + putchar('\n'); + else + newline = true; + + journal_file_print_header(f); + } +} + +_public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) { + Iterator i; + JournalFile *f; + uint64_t sum = 0; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(bytes, -EINVAL); + + ORDERED_HASHMAP_FOREACH(f, j->files, i) { + struct stat st; + + if (fstat(f->fd, &st) < 0) + return -errno; + + sum += (uint64_t) st.st_blocks * 512ULL; + } + + *bytes = sum; + return 0; +} + +_public_ int sd_journal_query_unique(sd_journal *j, const char *field) { + char *f; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(!isempty(field), -EINVAL); + assert_return(field_is_valid(field), -EINVAL); + + f = strdup(field); + if (!f) + return -ENOMEM; + + free(j->unique_field); + j->unique_field = f; + j->unique_file = NULL; + j->unique_offset = 0; + j->unique_file_lost = false; + + return 0; +} + +_public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l) { + size_t k; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(data, -EINVAL); + assert_return(l, -EINVAL); + assert_return(j->unique_field, -EINVAL); + + k = strlen(j->unique_field); + + if (!j->unique_file) { + if (j->unique_file_lost) + return 0; + + j->unique_file = ordered_hashmap_first(j->files); + if (!j->unique_file) + return 0; + + j->unique_offset = 0; + } + + for (;;) { + JournalFile *of; + Iterator i; + Object *o; + const void *odata; + size_t ol; + bool found; + int r; + + /* Proceed to next data object in the field's linked list */ + if (j->unique_offset == 0) { + r = journal_file_find_field_object(j->unique_file, j->unique_field, k, &o, NULL); + if (r < 0) + return r; + + j->unique_offset = r > 0 ? le64toh(o->field.head_data_offset) : 0; + } else { + r = journal_file_move_to_object(j->unique_file, OBJECT_DATA, j->unique_offset, &o); + if (r < 0) + return r; + + j->unique_offset = le64toh(o->data.next_field_offset); + } + + /* We reached the end of the list? Then start again, with the next file */ + if (j->unique_offset == 0) { + j->unique_file = ordered_hashmap_next(j->files, j->unique_file->path); + if (!j->unique_file) + return 0; + + continue; + } + + /* We do not use OBJECT_DATA context here, but OBJECT_UNUSED + * instead, so that we can look at this data object at the same + * time as one on another file */ + r = journal_file_move_to_object(j->unique_file, OBJECT_UNUSED, j->unique_offset, &o); + if (r < 0) + return r; + + /* Let's do the type check by hand, since we used 0 context above. */ + if (o->object.type != OBJECT_DATA) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "%s:offset " OFSfmt ": object has type %d, expected %d", + j->unique_file->path, + j->unique_offset, + o->object.type, OBJECT_DATA); + + r = return_data(j, j->unique_file, o, &odata, &ol); + if (r < 0) + return r; + + /* Check if we have at least the field name and "=". */ + if (ol <= k) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "%s:offset " OFSfmt ": object has size %zu, expected at least %zu", + j->unique_file->path, + j->unique_offset, ol, k + 1); + + if (memcmp(odata, j->unique_field, k) || ((const char*) odata)[k] != '=') + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "%s:offset " OFSfmt ": object does not start with \"%s=\"", + j->unique_file->path, + j->unique_offset, + j->unique_field); + + /* OK, now let's see if we already returned this data + * object by checking if it exists in the earlier + * traversed files. */ + found = false; + ORDERED_HASHMAP_FOREACH(of, j->files, i) { + if (of == j->unique_file) + break; + + /* Skip this file it didn't have any fields indexed */ + if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0) + continue; + + r = journal_file_find_data_object_with_hash(of, odata, ol, le64toh(o->data.hash), NULL, NULL); + if (r < 0) + return r; + if (r > 0) { + found = true; + break; + } + } + + if (found) + continue; + + r = return_data(j, j->unique_file, o, data, l); + if (r < 0) + return r; + + return 1; + } +} + +_public_ void sd_journal_restart_unique(sd_journal *j) { + if (!j) + return; + + j->unique_file = NULL; + j->unique_offset = 0; + j->unique_file_lost = false; +} + +_public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) { + int r; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(field, -EINVAL); + + if (!j->fields_file) { + if (j->fields_file_lost) + return 0; + + j->fields_file = ordered_hashmap_first(j->files); + if (!j->fields_file) + return 0; + + j->fields_hash_table_index = 0; + j->fields_offset = 0; + } + + for (;;) { + JournalFile *f, *of; + Iterator i; + uint64_t m; + Object *o; + size_t sz; + bool found; + + f = j->fields_file; + + if (j->fields_offset == 0) { + bool eof = false; + + /* We are not yet positioned at any field. Let's pick the first one */ + r = journal_file_map_field_hash_table(f); + if (r < 0) + return r; + + m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem); + for (;;) { + if (j->fields_hash_table_index >= m) { + /* Reached the end of the hash table, go to the next file. */ + eof = true; + break; + } + + j->fields_offset = le64toh(f->field_hash_table[j->fields_hash_table_index].head_hash_offset); + + if (j->fields_offset != 0) + break; + + /* Empty hash table bucket, go to next one */ + j->fields_hash_table_index++; + } + + if (eof) { + /* Proceed with next file */ + j->fields_file = ordered_hashmap_next(j->files, f->path); + if (!j->fields_file) { + *field = NULL; + return 0; + } + + j->fields_offset = 0; + j->fields_hash_table_index = 0; + continue; + } + + } else { + /* We are already positioned at a field. If so, let's figure out the next field from it */ + + r = journal_file_move_to_object(f, OBJECT_FIELD, j->fields_offset, &o); + if (r < 0) + return r; + + j->fields_offset = le64toh(o->field.next_hash_offset); + if (j->fields_offset == 0) { + /* Reached the end of the hash table chain */ + j->fields_hash_table_index++; + continue; + } + } + + /* We use OBJECT_UNUSED here, so that the iterator below doesn't remove our mmap window */ + r = journal_file_move_to_object(f, OBJECT_UNUSED, j->fields_offset, &o); + if (r < 0) + return r; + + /* Because we used OBJECT_UNUSED above, we need to do our type check manually */ + if (o->object.type != OBJECT_FIELD) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "%s:offset " OFSfmt ": object has type %i, expected %i", + f->path, j->fields_offset, + o->object.type, OBJECT_FIELD); + + sz = le64toh(o->object.size) - offsetof(Object, field.payload); + + /* Let's see if we already returned this field name before. */ + found = false; + ORDERED_HASHMAP_FOREACH(of, j->files, i) { + if (of == f) + break; + + /* Skip this file it didn't have any fields indexed */ + if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0) + continue; + + r = journal_file_find_field_object_with_hash(of, o->field.payload, sz, le64toh(o->field.hash), NULL, NULL); + if (r < 0) + return r; + if (r > 0) { + found = true; + break; + } + } + + if (found) + continue; + + /* Check if this is really a valid string containing no NUL byte */ + if (memchr(o->field.payload, 0, sz)) + return -EBADMSG; + + if (sz > j->data_threshold) + sz = j->data_threshold; + + if (!GREEDY_REALLOC(j->fields_buffer, j->fields_buffer_allocated, sz + 1)) + return -ENOMEM; + + memcpy(j->fields_buffer, o->field.payload, sz); + j->fields_buffer[sz] = 0; + + if (!field_is_valid(j->fields_buffer)) + return -EBADMSG; + + *field = j->fields_buffer; + return 1; + } +} + +_public_ void sd_journal_restart_fields(sd_journal *j) { + if (!j) + return; + + j->fields_file = NULL; + j->fields_hash_table_index = 0; + j->fields_offset = 0; + j->fields_file_lost = false; +} + +_public_ int sd_journal_reliable_fd(sd_journal *j) { + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + return !j->on_network; +} + +static char *lookup_field(const char *field, void *userdata) { + sd_journal *j = userdata; + const void *data; + size_t size, d; + int r; + + assert(field); + assert(j); + + r = sd_journal_get_data(j, field, &data, &size); + if (r < 0 || + size > REPLACE_VAR_MAX) + return strdup(field); + + d = strlen(field) + 1; + + return strndup((const char*) data + d, size - d); +} + +_public_ int sd_journal_get_catalog(sd_journal *j, char **ret) { + const void *data; + size_t size; + sd_id128_t id; + _cleanup_free_ char *text = NULL, *cid = NULL; + char *t; + int r; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(ret, -EINVAL); + + r = sd_journal_get_data(j, "MESSAGE_ID", &data, &size); + if (r < 0) + return r; + + cid = strndup((const char*) data + 11, size - 11); + if (!cid) + return -ENOMEM; + + r = sd_id128_from_string(cid, &id); + if (r < 0) + return r; + + r = catalog_get(CATALOG_DATABASE, id, &text); + if (r < 0) + return r; + + t = replace_var(text, lookup_field, j); + if (!t) + return -ENOMEM; + + *ret = t; + return 0; +} + +_public_ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret) { + assert_return(ret, -EINVAL); + + return catalog_get(CATALOG_DATABASE, id, ret); +} + +_public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) { + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + + j->data_threshold = sz; + return 0; +} + +_public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) { + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); + assert_return(sz, -EINVAL); + + *sz = j->data_threshold; + return 0; +} + +_public_ int sd_journal_has_runtime_files(sd_journal *j) { + assert_return(j, -EINVAL); + + return j->has_runtime_files; +} + +_public_ int sd_journal_has_persistent_files(sd_journal *j) { + assert_return(j, -EINVAL); + + return j->has_persistent_files; +} diff --git a/src/journal/test-audit-type.c b/src/journal/test-audit-type.c new file mode 100644 index 00000000..20e654b5 --- /dev/null +++ b/src/journal/test-audit-type.c @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "audit-type.h" + +static void print_audit_label(int i) { + const char *name; + + name = audit_type_name_alloca(i); + /* This is a separate function only because of alloca */ + printf("%i → %s → %s\n", i, audit_type_to_string(i), name); +} + +static void test_audit_type(void) { + int i; + + for (i = 0; i <= AUDIT_KERNEL; i++) + print_audit_label(i); +} + +int main(int argc, char **argv) { + test_audit_type(); +} diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c new file mode 100644 index 00000000..ba14d922 --- /dev/null +++ b/src/journal/test-catalog.c @@ -0,0 +1,240 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "catalog.h" +#include "fd-util.h" +#include "fs-util.h" +#include "log.h" +#include "macro.h" +#include "path-util.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "tmpfile-util.h" +#include "util.h" + +static char** catalog_dirs = NULL; +static const char *no_catalog_dirs[] = { + "/bin/hopefully/with/no/catalog", + NULL +}; + +static OrderedHashmap* test_import(const char* contents, ssize_t size, int code) { + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-catalog.XXXXXX"; + _cleanup_close_ int fd; + OrderedHashmap *h; + + if (size < 0) + size = strlen(contents); + + assert_se(h = ordered_hashmap_new(&catalog_hash_ops)); + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, contents, size) == size); + + assert_se(catalog_import_file(h, name) == code); + + return h; +} + +static void test_catalog_import_invalid(void) { + _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL; + + h = test_import("xxx", -1, -EINVAL); + assert_se(ordered_hashmap_isempty(h)); +} + +static void test_catalog_import_badid(void) { + _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL; + const char *input = +"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededede\n" \ +"Subject: message\n" \ +"\n" \ +"payload\n"; + h = test_import(input, -1, -EINVAL); +} + +static void test_catalog_import_one(void) { + _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL; + char *payload; + Iterator j; + + const char *input = +"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ +"Subject: message\n" \ +"\n" \ +"payload\n"; + const char *expect = +"Subject: message\n" \ +"\n" \ +"payload\n"; + + h = test_import(input, -1, 0); + assert_se(ordered_hashmap_size(h) == 1); + + ORDERED_HASHMAP_FOREACH(payload, h, j) { + printf("expect: %s\n", expect); + printf("actual: %s\n", payload); + assert_se(streq(expect, payload)); + } +} + +static void test_catalog_import_merge(void) { + _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL; + char *payload; + Iterator j; + + const char *input = +"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ +"Subject: message\n" \ +"Defined-By: me\n" \ +"\n" \ +"payload\n" \ +"\n" \ +"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ +"Subject: override subject\n" \ +"X-Header: hello\n" \ +"\n" \ +"override payload\n"; + + const char *combined = +"Subject: override subject\n" \ +"X-Header: hello\n" \ +"Subject: message\n" \ +"Defined-By: me\n" \ +"\n" \ +"override payload\n"; + + h = test_import(input, -1, 0); + assert_se(ordered_hashmap_size(h) == 1); + + ORDERED_HASHMAP_FOREACH(payload, h, j) { + assert_se(streq(combined, payload)); + } +} + +static void test_catalog_import_merge_no_body(void) { + _cleanup_ordered_hashmap_free_free_free_ OrderedHashmap *h = NULL; + char *payload; + Iterator j; + + const char *input = +"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ +"Subject: message\n" \ +"Defined-By: me\n" \ +"\n" \ +"payload\n" \ +"\n" \ +"-- 0027229ca0644181a76c4e92458afaff dededededededededededededededed\n" \ +"Subject: override subject\n" \ +"X-Header: hello\n" \ +"\n"; + + const char *combined = +"Subject: override subject\n" \ +"X-Header: hello\n" \ +"Subject: message\n" \ +"Defined-By: me\n" \ +"\n" \ +"payload\n"; + + h = test_import(input, -1, 0); + assert_se(ordered_hashmap_size(h) == 1); + + ORDERED_HASHMAP_FOREACH(payload, h, j) { + assert_se(streq(combined, payload)); + } +} + +static void test_catalog_update(const char *database) { + int r; + + /* Test what happens if there are no files. */ + r = catalog_update(database, NULL, NULL); + assert_se(r == 0); + + /* Test what happens if there are no files in the directory. */ + r = catalog_update(database, NULL, no_catalog_dirs); + assert_se(r == 0); + + /* Make sure that we at least have some files loaded or the + * catalog_list below will fail. */ + r = catalog_update(database, NULL, (const char * const *) catalog_dirs); + assert_se(r == 0); +} + +static void test_catalog_file_lang(void) { + _cleanup_free_ char *lang = NULL, *lang2 = NULL, *lang3 = NULL, *lang4 = NULL; + + assert_se(catalog_file_lang("systemd.de_DE.catalog", &lang) == 1); + assert_se(streq(lang, "de_DE")); + + assert_se(catalog_file_lang("systemd..catalog", &lang2) == 0); + assert_se(lang2 == NULL); + + assert_se(catalog_file_lang("systemd.fr.catalog", &lang2) == 1); + assert_se(streq(lang2, "fr")); + + assert_se(catalog_file_lang("systemd.fr.catalog.gz", &lang3) == 0); + assert_se(lang3 == NULL); + + assert_se(catalog_file_lang("systemd.01234567890123456789012345678901.catalog", &lang3) == 0); + assert_se(lang3 == NULL); + + assert_se(catalog_file_lang("systemd.0123456789012345678901234567890.catalog", &lang3) == 1); + assert_se(streq(lang3, "0123456789012345678901234567890")); + + assert_se(catalog_file_lang("/x/y/systemd.catalog", &lang4) == 0); + assert_se(lang4 == NULL); + + assert_se(catalog_file_lang("/x/y/systemd.ru_RU.catalog", &lang4) == 1); + assert_se(streq(lang4, "ru_RU")); +} + +int main(int argc, char *argv[]) { + _cleanup_(unlink_tempfilep) char database[] = "/tmp/test-catalog.XXXXXX"; + _cleanup_free_ char *text = NULL; + int r; + + setlocale(LC_ALL, "de_DE.UTF-8"); + + test_setup_logging(LOG_DEBUG); + + /* If test-catalog is located at the build directory, then use catalogs in that. + * If it is not, e.g. installed by systemd-tests package, then use installed catalogs. */ + catalog_dirs = STRV_MAKE(get_catalog_dir()); + + assert_se(access(catalog_dirs[0], F_OK) >= 0); + log_notice("Using catalog directory '%s'", catalog_dirs[0]); + + test_catalog_file_lang(); + + test_catalog_import_invalid(); + test_catalog_import_badid(); + test_catalog_import_one(); + test_catalog_import_merge(); + test_catalog_import_merge_no_body(); + + assert_se(mkostemp_safe(database) >= 0); + + test_catalog_update(database); + + r = catalog_list(stdout, database, true); + assert_se(r >= 0); + + r = catalog_list(stdout, database, false); + assert_se(r >= 0); + + assert_se(catalog_get(database, SD_MESSAGE_COREDUMP, &text) >= 0); + printf(">>>%s<<<\n", text); + + return 0; +} diff --git a/src/journal/test-compress-benchmark.c b/src/journal/test-compress-benchmark.c new file mode 100644 index 00000000..10059970 --- /dev/null +++ b/src/journal/test-compress-benchmark.c @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "compress.h" +#include "env-util.h" +#include "macro.h" +#include "memory-util.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "process-util.h" +#include "random-util.h" +#include "string-util.h" +#include "tests.h" + +typedef int (compress_t)(const void *src, uint64_t src_size, void *dst, + size_t dst_alloc_size, size_t *dst_size); +typedef int (decompress_t)(const void *src, uint64_t src_size, + void **dst, size_t *dst_alloc_size, size_t* dst_size, size_t dst_max); + +#if HAVE_XZ || HAVE_LZ4 + +static usec_t arg_duration; +static size_t arg_start; + +#define MAX_SIZE (1024*1024LU) +#define PRIME 1048571 /* A prime close enough to one megabyte that mod 4 == 3 */ + +static size_t _permute(size_t x) { + size_t residue; + + if (x >= PRIME) + return x; + + residue = x*x % PRIME; + if (x <= PRIME / 2) + return residue; + else + return PRIME - residue; +} + +static size_t permute(size_t x) { + return _permute((_permute(x) + arg_start) % MAX_SIZE ^ 0xFF345); +} + +static char* make_buf(size_t count, const char *type) { + char *buf; + size_t i; + + buf = malloc(count); + assert_se(buf); + + if (streq(type, "zeros")) + memzero(buf, count); + else if (streq(type, "simple")) + for (i = 0; i < count; i++) + buf[i] = 'a' + i % ('z' - 'a' + 1); + else if (streq(type, "random")) { + size_t step = count / 10; + + random_bytes(buf, step); + memzero(buf + 1*step, step); + random_bytes(buf + 2*step, step); + memzero(buf + 3*step, step); + random_bytes(buf + 4*step, step); + memzero(buf + 5*step, step); + random_bytes(buf + 6*step, step); + memzero(buf + 7*step, step); + random_bytes(buf + 8*step, step); + memzero(buf + 9*step, step); + } else + assert_not_reached("here"); + + return buf; +} + +static void test_compress_decompress(const char* label, const char* type, + compress_t compress, decompress_t decompress) { + usec_t n, n2 = 0; + float dt; + + _cleanup_free_ char *text, *buf; + _cleanup_free_ void *buf2 = NULL; + size_t buf2_allocated = 0; + size_t skipped = 0, compressed = 0, total = 0; + + text = make_buf(MAX_SIZE, type); + buf = calloc(MAX_SIZE + 1, 1); + assert_se(text && buf); + + n = now(CLOCK_MONOTONIC); + + for (size_t i = 0; i <= MAX_SIZE; i++) { + size_t j = 0, k = 0, size; + int r; + + size = permute(i); + if (size == 0) + continue; + + log_debug("%s %zu %zu", type, i, size); + + memzero(buf, MIN(size + 1000, MAX_SIZE)); + + r = compress(text, size, buf, size, &j); + /* assume compression must be successful except for small or random inputs */ + assert_se(r == 0 || (size < 2048 && r == -ENOBUFS) || streq(type, "random")); + + /* check for overwrites */ + assert_se(buf[size] == 0); + if (r != 0) { + skipped += size; + continue; + } + + assert_se(j > 0); + if (j >= size) + log_error("%s \"compressed\" %zu -> %zu", label, size, j); + + r = decompress(buf, j, &buf2, &buf2_allocated, &k, 0); + assert_se(r == 0); + assert_se(buf2_allocated >= k); + assert_se(k == size); + + assert_se(memcmp(text, buf2, size) == 0); + + total += size; + compressed += j; + + n2 = now(CLOCK_MONOTONIC); + if (n2 - n > arg_duration) + break; + } + + dt = (n2-n) / 1e6; + + log_info("%s/%s: compressed & decompressed %zu bytes in %.2fs (%.2fMiB/s), " + "mean compression %.2f%%, skipped %zu bytes", + label, type, total, dt, + total / 1024. / 1024 / dt, + 100 - compressed * 100. / total, + skipped); +} +#endif + +int main(int argc, char *argv[]) { +#if HAVE_XZ || HAVE_LZ4 + test_setup_logging(LOG_INFO); + + if (argc >= 2) { + unsigned x; + + assert_se(safe_atou(argv[1], &x) >= 0); + arg_duration = x * USEC_PER_SEC; + } else + arg_duration = slow_tests_enabled() ? + 2 * USEC_PER_SEC : USEC_PER_SEC / 50; + + if (argc == 3) + (void) safe_atozu(argv[2], &arg_start); + else + arg_start = getpid_cached(); + + const char *i; + NULSTR_FOREACH(i, "zeros\0simple\0random\0") { +#if HAVE_XZ + test_compress_decompress("XZ", i, compress_blob_xz, decompress_blob_xz); +#endif +#if HAVE_LZ4 + test_compress_decompress("LZ4", i, compress_blob_lz4, decompress_blob_lz4); +#endif + } + return 0; +#else + return log_tests_skipped("No compression feature is enabled"); +#endif +} diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c new file mode 100644 index 00000000..fac2b43c --- /dev/null +++ b/src/journal/test-compress.c @@ -0,0 +1,343 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#if HAVE_LZ4 +#include +#endif + +#include "alloc-util.h" +#include "compress.h" +#include "fd-util.h" +#include "fs-util.h" +#include "macro.h" +#include "memory-util.h" +#include "path-util.h" +#include "random-util.h" +#include "tests.h" +#include "tmpfile-util.h" + +#if HAVE_XZ +# define XZ_OK 0 +#else +# define XZ_OK -EPROTONOSUPPORT +#endif + +#if HAVE_LZ4 +# define LZ4_OK 0 +#else +# define LZ4_OK -EPROTONOSUPPORT +#endif + +typedef int (compress_blob_t)(const void *src, uint64_t src_size, + void *dst, size_t dst_alloc_size, size_t *dst_size); +typedef int (decompress_blob_t)(const void *src, uint64_t src_size, + void **dst, size_t *dst_alloc_size, + size_t* dst_size, size_t dst_max); +typedef int (decompress_sw_t)(const void *src, uint64_t src_size, + void **buffer, size_t *buffer_size, + const void *prefix, size_t prefix_len, + uint8_t extra); + +typedef int (compress_stream_t)(int fdf, int fdt, uint64_t max_bytes); +typedef int (decompress_stream_t)(int fdf, int fdt, uint64_t max_size); + +#if HAVE_XZ || HAVE_LZ4 +static void test_compress_decompress(int compression, + compress_blob_t compress, + decompress_blob_t decompress, + const char *data, + size_t data_len, + bool may_fail) { + char compressed[512]; + size_t csize, usize = 0; + _cleanup_free_ char *decompressed = NULL; + int r; + + log_info("/* testing %s %s blob compression/decompression */", + object_compressed_to_string(compression), data); + + r = compress(data, data_len, compressed, sizeof(compressed), &csize); + if (r == -ENOBUFS) { + log_info_errno(r, "compression failed: %m"); + assert_se(may_fail); + } else { + assert_se(r == 0); + r = decompress(compressed, csize, + (void **) &decompressed, &usize, &csize, 0); + assert_se(r == 0); + assert_se(decompressed); + assert_se(memcmp(decompressed, data, data_len) == 0); + } + + r = decompress("garbage", 7, + (void **) &decompressed, &usize, &csize, 0); + assert_se(r < 0); + + /* make sure to have the minimal lz4 compressed size */ + r = decompress("00000000\1g", 9, + (void **) &decompressed, &usize, &csize, 0); + assert_se(r < 0); + + r = decompress("\100000000g", 9, + (void **) &decompressed, &usize, &csize, 0); + assert_se(r < 0); + + memzero(decompressed, usize); +} + +static void test_decompress_startswith(int compression, + compress_blob_t compress, + decompress_sw_t decompress_sw, + const char *data, + size_t data_len, + bool may_fail) { + + char *compressed; + _cleanup_free_ char *compressed1 = NULL, *compressed2 = NULL, *decompressed = NULL; + size_t csize, usize = 0, len; + int r; + + log_info("/* testing decompress_startswith with %s on %.20s text */", + object_compressed_to_string(compression), data); + +#define BUFSIZE_1 512 +#define BUFSIZE_2 20000 + + compressed = compressed1 = malloc(BUFSIZE_1); + assert_se(compressed1); + r = compress(data, data_len, compressed, BUFSIZE_1, &csize); + if (r == -ENOBUFS) { + log_info_errno(r, "compression failed: %m"); + assert_se(may_fail); + + compressed = compressed2 = malloc(BUFSIZE_2); + assert_se(compressed2); + r = compress(data, data_len, compressed, BUFSIZE_2, &csize); + assert(r == 0); + } + assert_se(r == 0); + + len = strlen(data); + + r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, '\0'); + assert_se(r > 0); + r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, 'w'); + assert_se(r == 0); + r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, "barbarbar", 9, ' '); + assert_se(r == 0); + r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len - 1, data[len-1]); + assert_se(r > 0); + r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len - 1, 'w'); + assert_se(r == 0); + r = decompress_sw(compressed, csize, (void **) &decompressed, &usize, data, len, '\0'); + assert_se(r > 0); +} + +static void test_decompress_startswith_short(int compression, + compress_blob_t compress, + decompress_sw_t decompress_sw) { + +#define TEXT "HUGE=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + + char buf[1024]; + size_t i, csize; + int r; + + log_info("/* %s with %s */", __func__, object_compressed_to_string(compression)); + + r = compress(TEXT, sizeof TEXT, buf, sizeof buf, &csize); + assert_se(r == 0); + + for (i = 1; i < strlen(TEXT); i++) { + size_t alloc_size = i; + _cleanup_free_ void *buf2 = NULL; + + assert_se(buf2 = malloc(i)); + + assert_se(decompress_sw(buf, csize, &buf2, &alloc_size, TEXT, i, TEXT[i]) == 1); + assert_se(decompress_sw(buf, csize, &buf2, &alloc_size, TEXT, i, 'y') == 0); + } +} + +static void test_compress_stream(int compression, + const char* cat, + compress_stream_t compress, + decompress_stream_t decompress, + const char *srcfile) { + + _cleanup_close_ int src = -1, dst = -1, dst2 = -1; + _cleanup_(unlink_tempfilep) char + pattern[] = "/tmp/systemd-test.compressed.XXXXXX", + pattern2[] = "/tmp/systemd-test.compressed.XXXXXX"; + int r; + _cleanup_free_ char *cmd = NULL, *cmd2 = NULL; + struct stat st = {}; + + r = find_binary(cat, NULL); + if (r < 0) { + log_error_errno(r, "Skipping %s, could not find %s binary: %m", __func__, cat); + return; + } + + log_debug("/* testing %s compression */", + object_compressed_to_string(compression)); + + log_debug("/* create source from %s */", srcfile); + + assert_se((src = open(srcfile, O_RDONLY|O_CLOEXEC)) >= 0); + + log_debug("/* test compression */"); + + assert_se((dst = mkostemp_safe(pattern)) >= 0); + + assert_se(compress(src, dst, -1) == 0); + + if (cat) { + assert_se(asprintf(&cmd, "%s %s | diff %s -", cat, pattern, srcfile) > 0); + assert_se(system(cmd) == 0); + } + + log_debug("/* test decompression */"); + + assert_se((dst2 = mkostemp_safe(pattern2)) >= 0); + + assert_se(stat(srcfile, &st) == 0); + + assert_se(lseek(dst, 0, SEEK_SET) == 0); + r = decompress(dst, dst2, st.st_size); + assert_se(r == 0); + + assert_se(asprintf(&cmd2, "diff %s %s", srcfile, pattern2) > 0); + assert_se(system(cmd2) == 0); + + log_debug("/* test faulty decompression */"); + + assert_se(lseek(dst, 1, SEEK_SET) == 1); + r = decompress(dst, dst2, st.st_size); + assert_se(IN_SET(r, 0, -EBADMSG)); + + assert_se(lseek(dst, 0, SEEK_SET) == 0); + assert_se(lseek(dst2, 0, SEEK_SET) == 0); + r = decompress(dst, dst2, st.st_size - 1); + assert_se(r == -EFBIG); +} +#endif + +#if HAVE_LZ4 +static void test_lz4_decompress_partial(void) { + char buf[20000], buf2[100]; + size_t buf_size = sizeof(buf), compressed; + int r; + _cleanup_free_ char *huge = NULL; + +#define HUGE_SIZE (4096*1024) + assert_se(huge = malloc(HUGE_SIZE)); + memset(huge, 'x', HUGE_SIZE); + memcpy(huge, "HUGE=", 5); + + r = LZ4_compress_default(huge, buf, HUGE_SIZE, buf_size); + assert_se(r >= 0); + compressed = r; + log_info("Compressed %i → %zu", HUGE_SIZE, compressed); + + r = LZ4_decompress_safe(buf, huge, r, HUGE_SIZE); + assert_se(r >= 0); + log_info("Decompressed → %i", r); + + r = LZ4_decompress_safe_partial(buf, huge, + compressed, + 12, HUGE_SIZE); + assert_se(r >= 0); + log_info("Decompressed partial %i/%i → %i", 12, HUGE_SIZE, r); + + for (size_t size = 1; size < sizeof(buf2); size++) { + /* This failed in older lz4s but works in newer ones. */ + r = LZ4_decompress_safe_partial(buf, buf2, compressed, size, size); + log_info("Decompressed partial %zu/%zu → %i (%s)", size, size, r, + r < 0 ? "bad" : "good"); + if (r >= 0 && LZ4_versionNumber() >= 10803) + /* lz4 <= 1.8.2 should fail that test, let's only check for newer ones */ + assert_se(memcmp(buf2, huge, r) == 0); + } +} +#endif + +int main(int argc, char *argv[]) { +#if HAVE_XZ || HAVE_LZ4 + const char text[] = + "text\0foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF" + "foofoofoofoo AAAA aaaaaaaaa ghost busters barbarbar FFF"; + + /* The file to test compression on can be specified as the first argument */ + const char *srcfile = argc > 1 ? argv[1] : argv[0]; + + char data[512] = "random\0"; + + char huge[4096*1024]; + memset(huge, 'x', sizeof(huge)); + memcpy(huge, "HUGE=", 5); + char_array_0(huge); + + test_setup_logging(LOG_DEBUG); + + random_bytes(data + 7, sizeof(data) - 7); + +#if HAVE_XZ + test_compress_decompress(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_blob_xz, + text, sizeof(text), false); + test_compress_decompress(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_blob_xz, + data, sizeof(data), true); + + test_decompress_startswith(OBJECT_COMPRESSED_XZ, + compress_blob_xz, decompress_startswith_xz, + text, sizeof(text), false); + test_decompress_startswith(OBJECT_COMPRESSED_XZ, + compress_blob_xz, decompress_startswith_xz, + data, sizeof(data), true); + test_decompress_startswith(OBJECT_COMPRESSED_XZ, + compress_blob_xz, decompress_startswith_xz, + huge, sizeof(huge), true); + + test_compress_stream(OBJECT_COMPRESSED_XZ, "xzcat", + compress_stream_xz, decompress_stream_xz, srcfile); + + test_decompress_startswith_short(OBJECT_COMPRESSED_XZ, compress_blob_xz, decompress_startswith_xz); + +#else + log_info("/* XZ test skipped */"); +#endif + +#if HAVE_LZ4 + test_compress_decompress(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_blob_lz4, + text, sizeof(text), false); + test_compress_decompress(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_blob_lz4, + data, sizeof(data), true); + + test_decompress_startswith(OBJECT_COMPRESSED_LZ4, + compress_blob_lz4, decompress_startswith_lz4, + text, sizeof(text), false); + test_decompress_startswith(OBJECT_COMPRESSED_LZ4, + compress_blob_lz4, decompress_startswith_lz4, + data, sizeof(data), true); + test_decompress_startswith(OBJECT_COMPRESSED_LZ4, + compress_blob_lz4, decompress_startswith_lz4, + huge, sizeof(huge), true); + + test_compress_stream(OBJECT_COMPRESSED_LZ4, "lz4cat", + compress_stream_lz4, decompress_stream_lz4, srcfile); + + test_lz4_decompress_partial(); + + test_decompress_startswith_short(OBJECT_COMPRESSED_LZ4, compress_blob_lz4, decompress_startswith_lz4); + +#else + log_info("/* LZ4 test skipped */"); +#endif + + return 0; +#else + log_info("/* XZ and LZ4 tests skipped */"); + return EXIT_TEST_SKIP; +#endif +} diff --git a/src/journal/test-journal-config.c b/src/journal/test-journal-config.c new file mode 100644 index 00000000..14824904 --- /dev/null +++ b/src/journal/test-journal-config.c @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "journald-server.h" + +#define _COMPRESS_PARSE_CHECK(str, enab, thresh, varname) \ + do { \ + JournalCompressOptions varname = {true, 111}; \ + config_parse_compress("", "", 0, "", 0, "", 0, str, \ + &varname, NULL); \ + assert_se((enab) == varname.enabled); \ + if (varname.enabled) \ + assert_se((thresh) == varname.threshold_bytes); \ + } while (0) + +#define COMPRESS_PARSE_CHECK(str, enabled, threshold) \ + _COMPRESS_PARSE_CHECK(str, enabled, threshold, conf##__COUNTER__) + +static void test_config_compress(void) { + COMPRESS_PARSE_CHECK("yes", true, 111); + COMPRESS_PARSE_CHECK("no", false, 111); + COMPRESS_PARSE_CHECK("y", true, 111); + COMPRESS_PARSE_CHECK("n", false, 111); + COMPRESS_PARSE_CHECK("true", true, 111); + COMPRESS_PARSE_CHECK("false", false, 111); + COMPRESS_PARSE_CHECK("t", true, 111); + COMPRESS_PARSE_CHECK("f", false, 111); + COMPRESS_PARSE_CHECK("on", true, 111); + COMPRESS_PARSE_CHECK("off", false, 111); + + /* Weird size/bool overlapping case. We preserve backward compatibility instead of assuming these are byte + * counts. */ + COMPRESS_PARSE_CHECK("1", true, 111); + COMPRESS_PARSE_CHECK("0", false, 111); + + /* IEC sizing */ + COMPRESS_PARSE_CHECK("1B", true, 1); + COMPRESS_PARSE_CHECK("1K", true, 1024); + COMPRESS_PARSE_CHECK("1M", true, 1024 * 1024); + COMPRESS_PARSE_CHECK("1G", true, 1024 * 1024 * 1024); + + /* Invalid Case */ + COMPRESS_PARSE_CHECK("-1", true, 111); + COMPRESS_PARSE_CHECK("blah blah", true, 111); + COMPRESS_PARSE_CHECK("", true, (uint64_t)-1); +} + +int main(int argc, char *argv[]) { + test_config_compress(); + + return 0; +} diff --git a/src/journal/test-journal-enum.c b/src/journal/test-journal-enum.c new file mode 100644 index 00000000..8e839920 --- /dev/null +++ b/src/journal/test-journal-enum.c @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-journal.h" + +#include "journal-internal.h" +#include "log.h" +#include "macro.h" +#include "tests.h" + +int main(int argc, char *argv[]) { + unsigned n = 0; + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + + test_setup_logging(LOG_DEBUG); + + assert_se(sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY) >= 0); + + assert_se(sd_journal_add_match(j, "_TRANSPORT=syslog", 0) >= 0); + assert_se(sd_journal_add_match(j, "_UID=0", 0) >= 0); + + SD_JOURNAL_FOREACH_BACKWARDS(j) { + const void *d; + size_t l; + + assert_se(sd_journal_get_data(j, "MESSAGE", &d, &l) >= 0); + + printf("%.*s\n", (int) l, (char*) d); + + n++; + if (n >= 10) + break; + } + + return 0; +} diff --git a/src/journal/test-journal-flush.c b/src/journal/test-journal-flush.c new file mode 100644 index 00000000..5fedd3ed --- /dev/null +++ b/src/journal/test-journal-flush.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-journal.h" + +#include "alloc-util.h" +#include "chattr-util.h" +#include "journal-file.h" +#include "journal-internal.h" +#include "macro.h" +#include "path-util.h" +#include "string-util.h" + +int main(int argc, char *argv[]) { + _cleanup_free_ char *fn = NULL; + char dn[] = "/var/tmp/test-journal-flush.XXXXXX"; + JournalFile *new_journal = NULL; + sd_journal *j = NULL; + unsigned n = 0; + int r; + + assert_se(mkdtemp(dn)); + (void) chattr_path(dn, FS_NOCOW_FL, FS_NOCOW_FL, NULL); + + fn = path_join(dn, "test.journal"); + + r = journal_file_open(-1, fn, O_CREAT|O_RDWR, 0644, false, 0, false, NULL, NULL, NULL, NULL, &new_journal); + assert_se(r >= 0); + + r = sd_journal_open(&j, 0); + assert_se(r >= 0); + + sd_journal_set_data_threshold(j, 0); + + SD_JOURNAL_FOREACH(j) { + Object *o; + JournalFile *f; + + f = j->current_file; + assert_se(f && f->current_offset > 0); + + r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); + if (r < 0) + log_error_errno(r, "journal_file_move_to_object failed: %m"); + assert_se(r >= 0); + + r = journal_file_copy_entry(f, new_journal, o, f->current_offset); + if (r < 0) + log_error_errno(r, "journal_file_copy_entry failed: %m"); + assert_se(r >= 0); + + if (++n >= 10000) + break; + } + + sd_journal_close(j); + + (void) journal_file_close(new_journal); + + unlink(fn); + assert_se(rmdir(dn) == 0); + + return 0; +} diff --git a/src/journal/test-journal-init.c b/src/journal/test-journal-init.c new file mode 100644 index 00000000..d10e6108 --- /dev/null +++ b/src/journal/test-journal-init.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-journal.h" + +#include "chattr-util.h" +#include "log.h" +#include "parse-util.h" +#include "rm-rf.h" +#include "tests.h" +#include "util.h" + +int main(int argc, char *argv[]) { + sd_journal *j; + int r, i, I = 100; + char t[] = "/var/tmp/journal-stream-XXXXXX"; + + test_setup_logging(LOG_DEBUG); + + if (argc >= 2) { + r = safe_atoi(argv[1], &I); + if (r < 0) + log_info("Could not parse loop count argument. Using default."); + } + + log_info("Running %d loops", I); + + assert_se(mkdtemp(t)); + (void) chattr_path(t, FS_NOCOW_FL, FS_NOCOW_FL, NULL); + + for (i = 0; i < I; i++) { + r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); + assert_se(r == 0); + + sd_journal_close(j); + + r = sd_journal_open_directory(&j, t, 0); + assert_se(r == 0); + + sd_journal_close(j); + + j = NULL; + r = sd_journal_open_directory(&j, t, SD_JOURNAL_LOCAL_ONLY); + assert_se(r == -EINVAL); + assert_se(j == NULL); + } + + assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); + + return 0; +} diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c new file mode 100644 index 00000000..c0bda688 --- /dev/null +++ b/src/journal/test-journal-interleaving.c @@ -0,0 +1,296 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-journal.h" + +#include "alloc-util.h" +#include "chattr-util.h" +#include "io-util.h" +#include "journal-file.h" +#include "journal-vacuum.h" +#include "log.h" +#include "parse-util.h" +#include "rm-rf.h" +#include "tests.h" +#include "util.h" + +/* This program tests skipping around in a multi-file journal. */ + +static bool arg_keep = false; + +_noreturn_ static void log_assert_errno(const char *text, int error, const char *file, int line, const char *func) { + log_internal(LOG_CRIT, error, file, line, func, + "'%s' failed at %s:%u (%s): %m", text, file, line, func); + abort(); +} + +#define assert_ret(expr) \ + do { \ + int _r_ = (expr); \ + if (_unlikely_(_r_ < 0)) \ + log_assert_errno(#expr, -_r_, PROJECT_FILE, __LINE__, __PRETTY_FUNCTION__); \ + } while (false) + +static JournalFile *test_open(const char *name) { + JournalFile *f; + assert_ret(journal_file_open(-1, name, O_RDWR|O_CREAT, 0644, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &f)); + return f; +} + +static void test_close(JournalFile *f) { + (void) journal_file_close (f); +} + +static void append_number(JournalFile *f, int n, uint64_t *seqnum) { + char *p; + dual_timestamp ts; + static dual_timestamp previous_ts = {}; + struct iovec iovec[1]; + + dual_timestamp_get(&ts); + + if (ts.monotonic <= previous_ts.monotonic) + ts.monotonic = previous_ts.monotonic + 1; + + if (ts.realtime <= previous_ts.realtime) + ts.realtime = previous_ts.realtime + 1; + + previous_ts = ts; + + assert_se(asprintf(&p, "NUMBER=%d", n) >= 0); + iovec[0] = IOVEC_MAKE_STRING(p); + assert_ret(journal_file_append_entry(f, &ts, NULL, iovec, 1, seqnum, NULL, NULL)); + free(p); +} + +static void test_check_number (sd_journal *j, int n) { + const void *d; + _cleanup_free_ char *k; + size_t l; + int x; + + assert_ret(sd_journal_get_data(j, "NUMBER", &d, &l)); + assert_se(k = strndup(d, l)); + printf("%s\n", k); + + assert_se(safe_atoi(k + 7, &x) >= 0); + assert_se(n == x); +} + +static void test_check_numbers_down (sd_journal *j, int count) { + int i; + + for (i = 1; i <= count; i++) { + int r; + test_check_number(j, i); + assert_ret(r = sd_journal_next(j)); + if (i == count) + assert_se(r == 0); + else + assert_se(r == 1); + } + +} + +static void test_check_numbers_up (sd_journal *j, int count) { + for (int i = count; i >= 1; i--) { + int r; + test_check_number(j, i); + assert_ret(r = sd_journal_previous(j)); + if (i == 1) + assert_se(r == 0); + else + assert_se(r == 1); + } + +} + +static void setup_sequential(void) { + JournalFile *one, *two; + one = test_open("one.journal"); + two = test_open("two.journal"); + append_number(one, 1, NULL); + append_number(one, 2, NULL); + append_number(two, 3, NULL); + append_number(two, 4, NULL); + test_close(one); + test_close(two); +} + +static void setup_interleaved(void) { + JournalFile *one, *two; + one = test_open("one.journal"); + two = test_open("two.journal"); + append_number(one, 1, NULL); + append_number(two, 2, NULL); + append_number(one, 3, NULL); + append_number(two, 4, NULL); + test_close(one); + test_close(two); +} + +static void mkdtemp_chdir_chattr(char *path) { + assert_se(mkdtemp(path)); + assert_se(chdir(path) >= 0); + + /* Speed up things a bit on btrfs, ensuring that CoW is turned off for all files created in our + * directory during the test run */ + (void) chattr_path(path, FS_NOCOW_FL, FS_NOCOW_FL, NULL); +} + +static void test_skip(void (*setup)(void)) { + char t[] = "/var/tmp/journal-skip-XXXXXX"; + sd_journal *j; + int r; + + mkdtemp_chdir_chattr(t); + + setup(); + + /* Seek to head, iterate down. + */ + assert_ret(sd_journal_open_directory(&j, t, 0)); + assert_ret(sd_journal_seek_head(j)); + assert_ret(sd_journal_next(j)); + test_check_numbers_down(j, 4); + sd_journal_close(j); + + /* Seek to tail, iterate up. + */ + assert_ret(sd_journal_open_directory(&j, t, 0)); + assert_ret(sd_journal_seek_tail(j)); + assert_ret(sd_journal_previous(j)); + test_check_numbers_up(j, 4); + sd_journal_close(j); + + /* Seek to tail, skip to head, iterate down. + */ + assert_ret(sd_journal_open_directory(&j, t, 0)); + assert_ret(sd_journal_seek_tail(j)); + assert_ret(r = sd_journal_previous_skip(j, 4)); + assert_se(r == 4); + test_check_numbers_down(j, 4); + sd_journal_close(j); + + /* Seek to head, skip to tail, iterate up. + */ + assert_ret(sd_journal_open_directory(&j, t, 0)); + assert_ret(sd_journal_seek_head(j)); + assert_ret(r = sd_journal_next_skip(j, 4)); + assert_se(r == 4); + test_check_numbers_up(j, 4); + sd_journal_close(j); + + log_info("Done..."); + + if (arg_keep) + log_info("Not removing %s", t); + else { + journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); + + assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); + } + + puts("------------------------------------------------------------"); +} + +static void test_sequence_numbers(void) { + + char t[] = "/var/tmp/journal-seq-XXXXXX"; + JournalFile *one, *two; + uint64_t seqnum = 0; + sd_id128_t seqnum_id; + + mkdtemp_chdir_chattr(t); + + assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, 0644, + true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &one) == 0); + + append_number(one, 1, &seqnum); + printf("seqnum=%"PRIu64"\n", seqnum); + assert_se(seqnum == 1); + append_number(one, 2, &seqnum); + printf("seqnum=%"PRIu64"\n", seqnum); + assert_se(seqnum == 2); + + assert_se(one->header->state == STATE_ONLINE); + assert_se(!sd_id128_equal(one->header->file_id, one->header->machine_id)); + assert_se(!sd_id128_equal(one->header->file_id, one->header->boot_id)); + assert_se(sd_id128_equal(one->header->file_id, one->header->seqnum_id)); + + memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t)); + + assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, 0644, + true, (uint64_t) -1, false, NULL, NULL, NULL, one, &two) == 0); + + assert_se(two->header->state == STATE_ONLINE); + assert_se(!sd_id128_equal(two->header->file_id, one->header->file_id)); + assert_se(sd_id128_equal(one->header->machine_id, one->header->machine_id)); + assert_se(sd_id128_equal(one->header->boot_id, one->header->boot_id)); + assert_se(sd_id128_equal(one->header->seqnum_id, one->header->seqnum_id)); + + append_number(two, 3, &seqnum); + printf("seqnum=%"PRIu64"\n", seqnum); + assert_se(seqnum == 3); + append_number(two, 4, &seqnum); + printf("seqnum=%"PRIu64"\n", seqnum); + assert_se(seqnum == 4); + + test_close(two); + + append_number(one, 5, &seqnum); + printf("seqnum=%"PRIu64"\n", seqnum); + assert_se(seqnum == 5); + + append_number(one, 6, &seqnum); + printf("seqnum=%"PRIu64"\n", seqnum); + assert_se(seqnum == 6); + + test_close(one); + + /* restart server */ + seqnum = 0; + + assert_se(journal_file_open(-1, "two.journal", O_RDWR, 0, + true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &two) == 0); + + assert_se(sd_id128_equal(two->header->seqnum_id, seqnum_id)); + + append_number(two, 7, &seqnum); + printf("seqnum=%"PRIu64"\n", seqnum); + assert_se(seqnum == 5); + + /* So..., here we have the same seqnum in two files with the + * same seqnum_id. */ + + test_close(two); + + log_info("Done..."); + + if (arg_keep) + log_info("Not removing %s", t); + else { + journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); + + assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); + } +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + /* journal_file_open requires a valid machine id */ + if (access("/etc/machine-id", F_OK) != 0) + return log_tests_skipped("/etc/machine-id not found"); + + arg_keep = argc > 1; + + test_skip(setup_sequential); + test_skip(setup_interleaved); + + test_sequence_numbers(); + + return 0; +} diff --git a/src/journal/test-journal-match.c b/src/journal/test-journal-match.c new file mode 100644 index 00000000..b1752791 --- /dev/null +++ b/src/journal/test-journal-match.c @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-journal.h" + +#include "alloc-util.h" +#include "journal-internal.h" +#include "log.h" +#include "string-util.h" +#include "tests.h" +#include "util.h" + +int main(int argc, char *argv[]) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + _cleanup_free_ char *t; + + test_setup_logging(LOG_DEBUG); + + assert_se(sd_journal_open(&j, 0) >= 0); + + assert_se(sd_journal_add_match(j, "foobar", 0) < 0); + assert_se(sd_journal_add_match(j, "foobar=waldo", 0) < 0); + assert_se(sd_journal_add_match(j, "", 0) < 0); + assert_se(sd_journal_add_match(j, "=", 0) < 0); + assert_se(sd_journal_add_match(j, "=xxxxx", 0) < 0); + assert_se(sd_journal_add_match(j, (uint8_t[4]){'A', '=', '\1', '\2'}, 4) >= 0); + assert_se(sd_journal_add_match(j, (uint8_t[5]){'B', '=', 'C', '\0', 'D'}, 5) >= 0); + assert_se(sd_journal_add_match(j, "HALLO=WALDO", 0) >= 0); + assert_se(sd_journal_add_match(j, "QUUX=mmmm", 0) >= 0); + assert_se(sd_journal_add_match(j, "QUUX=xxxxx", 0) >= 0); + assert_se(sd_journal_add_match(j, "HALLO=", 0) >= 0); + assert_se(sd_journal_add_match(j, "QUUX=xxxxx", 0) >= 0); + assert_se(sd_journal_add_match(j, "QUUX=yyyyy", 0) >= 0); + assert_se(sd_journal_add_match(j, "PIFF=paff", 0) >= 0); + + assert_se(sd_journal_add_disjunction(j) >= 0); + + assert_se(sd_journal_add_match(j, "ONE=one", 0) >= 0); + assert_se(sd_journal_add_match(j, "ONE=two", 0) >= 0); + assert_se(sd_journal_add_match(j, "TWO=two", 0) >= 0); + + assert_se(sd_journal_add_conjunction(j) >= 0); + + assert_se(sd_journal_add_match(j, "L4_1=yes", 0) >= 0); + assert_se(sd_journal_add_match(j, "L4_1=ok", 0) >= 0); + assert_se(sd_journal_add_match(j, "L4_2=yes", 0) >= 0); + assert_se(sd_journal_add_match(j, "L4_2=ok", 0) >= 0); + + assert_se(sd_journal_add_disjunction(j) >= 0); + + assert_se(sd_journal_add_match(j, "L3=yes", 0) >= 0); + assert_se(sd_journal_add_match(j, "L3=ok", 0) >= 0); + + assert_se(t = journal_make_match_string(j)); + + printf("resulting match expression is: %s\n", t); + + assert_se(streq(t, "(((L3=ok OR L3=yes) OR ((L4_2=ok OR L4_2=yes) AND (L4_1=ok OR L4_1=yes))) AND ((TWO=two AND (ONE=two OR ONE=one)) OR (PIFF=paff AND (QUUX=yyyyy OR QUUX=xxxxx OR QUUX=mmmm) AND (HALLO= OR HALLO=WALDO) AND B=C\\000D AND A=\\001\\002)))")); + + return 0; +} diff --git a/src/journal/test-journal-send.c b/src/journal/test-journal-send.c new file mode 100644 index 00000000..484308e5 --- /dev/null +++ b/src/journal/test-journal-send.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-journal.h" + +#include "macro.h" + +int main(int argc, char *argv[]) { + char huge[4096*1024]; + + /* utf-8 and non-utf-8, message-less and message-ful iovecs */ + struct iovec graph1[] = { + {(char*) "GRAPH=graph", STRLEN("GRAPH=graph")} + }; + struct iovec graph2[] = { + {(char*) "GRAPH=graph\n", STRLEN("GRAPH=graph\n")} + }; + struct iovec message1[] = { + {(char*) "MESSAGE=graph", STRLEN("MESSAGE=graph")} + }; + struct iovec message2[] = { + {(char*) "MESSAGE=graph\n", STRLEN("MESSAGE=graph\n")} + }; + + assert_se(sd_journal_print(LOG_INFO, "piepapo") == 0); + + assert_se(sd_journal_send("MESSAGE=foobar", + "VALUE=%i", 7, + NULL) == 0); + + errno = ENOENT; + assert_se(sd_journal_perror("Foobar") == 0); + + assert_se(sd_journal_perror("") == 0); + + memset(huge, 'x', sizeof(huge)); + memcpy(huge, "HUGE=", 5); + char_array_0(huge); + + assert_se(sd_journal_send("MESSAGE=Huge field attached", + huge, + NULL) == 0); + + assert_se(sd_journal_send("MESSAGE=uiui", + "VALUE=A", + "VALUE=B", + "VALUE=C", + "SINGLETON=1", + "OTHERVALUE=X", + "OTHERVALUE=Y", + "WITH_BINARY=this is a binary value \a", + NULL) == 0); + + syslog(LOG_NOTICE, "Hello World!"); + + assert_se(sd_journal_print(LOG_NOTICE, "Hello World") == 0); + + assert_se(sd_journal_send("MESSAGE=Hello World!", + "MESSAGE_ID=52fb62f99e2c49d89cfbf9d6de5e3555", + "PRIORITY=5", + "HOME=%s", getenv("HOME"), + "TERM=%s", getenv("TERM"), + "PAGE_SIZE=%li", sysconf(_SC_PAGESIZE), + "N_CPUS=%li", sysconf(_SC_NPROCESSORS_ONLN), + NULL) == 0); + + assert_se(sd_journal_sendv(graph1, 1) == 0); + assert_se(sd_journal_sendv(graph2, 1) == 0); + assert_se(sd_journal_sendv(message1, 1) == 0); + assert_se(sd_journal_sendv(message2, 1) == 0); + + /* test without location fields */ +#undef sd_journal_sendv + assert_se(sd_journal_sendv(graph1, 1) == 0); + assert_se(sd_journal_sendv(graph2, 1) == 0); + assert_se(sd_journal_sendv(message1, 1) == 0); + assert_se(sd_journal_sendv(message2, 1) == 0); + + sleep(1); + + return 0; +} diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c new file mode 100644 index 00000000..6d97bc5c --- /dev/null +++ b/src/journal/test-journal-stream.c @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-journal.h" + +#include "alloc-util.h" +#include "chattr-util.h" +#include "journal-file.h" +#include "journal-internal.h" +#include "log.h" +#include "macro.h" +#include "parse-util.h" +#include "rm-rf.h" +#include "tests.h" +#include "util.h" + +#define N_ENTRIES 200 + +static void verify_contents(sd_journal *j, unsigned skip) { + unsigned i; + + assert_se(j); + + i = 0; + SD_JOURNAL_FOREACH(j) { + const void *d; + char *k, *c; + size_t l; + unsigned u = 0; + + assert_se(sd_journal_get_cursor(j, &k) >= 0); + printf("cursor: %s\n", k); + free(k); + + assert_se(sd_journal_get_data(j, "MAGIC", &d, &l) >= 0); + printf("\t%.*s\n", (int) l, (const char*) d); + + assert_se(sd_journal_get_data(j, "NUMBER", &d, &l) >= 0); + assert_se(k = strndup(d, l)); + printf("\t%s\n", k); + + if (skip > 0) { + assert_se(safe_atou(k + 7, &u) >= 0); + assert_se(i == u); + i += skip; + } + + free(k); + + assert_se(sd_journal_get_cursor(j, &c) >= 0); + assert_se(sd_journal_test_cursor(j, c) > 0); + free(c); + } + + if (skip > 0) + assert_se(i == N_ENTRIES); +} + +int main(int argc, char *argv[]) { + JournalFile *one, *two, *three; + char t[] = "/var/tmp/journal-stream-XXXXXX"; + unsigned i; + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + char *z; + const void *data; + size_t l; + dual_timestamp previous_ts = DUAL_TIMESTAMP_NULL; + + /* journal_file_open requires a valid machine id */ + if (access("/etc/machine-id", F_OK) != 0) + return log_tests_skipped("/etc/machine-id not found"); + + test_setup_logging(LOG_DEBUG); + + assert_se(mkdtemp(t)); + assert_se(chdir(t) >= 0); + (void) chattr_path(t, FS_NOCOW_FL, FS_NOCOW_FL, NULL); + + assert_se(journal_file_open(-1, "one.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &one) == 0); + assert_se(journal_file_open(-1, "two.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &two) == 0); + assert_se(journal_file_open(-1, "three.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &three) == 0); + + for (i = 0; i < N_ENTRIES; i++) { + char *p, *q; + dual_timestamp ts; + struct iovec iovec[2]; + + dual_timestamp_get(&ts); + + if (ts.monotonic <= previous_ts.monotonic) + ts.monotonic = previous_ts.monotonic + 1; + + if (ts.realtime <= previous_ts.realtime) + ts.realtime = previous_ts.realtime + 1; + + previous_ts = ts; + + assert_se(asprintf(&p, "NUMBER=%u", i) >= 0); + iovec[0].iov_base = p; + iovec[0].iov_len = strlen(p); + + assert_se(asprintf(&q, "MAGIC=%s", i % 5 == 0 ? "quux" : "waldo") >= 0); + + iovec[1].iov_base = q; + iovec[1].iov_len = strlen(q); + + if (i % 10 == 0) + assert_se(journal_file_append_entry(three, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0); + else { + if (i % 3 == 0) + assert_se(journal_file_append_entry(two, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0); + + assert_se(journal_file_append_entry(one, &ts, NULL, iovec, 2, NULL, NULL, NULL) == 0); + } + + free(p); + free(q); + } + + (void) journal_file_close(one); + (void) journal_file_close(two); + (void) journal_file_close(three); + + assert_se(sd_journal_open_directory(&j, t, 0) >= 0); + + assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0); + SD_JOURNAL_FOREACH_BACKWARDS(j) { + _cleanup_free_ char *c; + + assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0); + printf("\t%.*s\n", (int) l, (const char*) data); + + assert_se(sd_journal_get_cursor(j, &c) >= 0); + assert_se(sd_journal_test_cursor(j, c) > 0); + } + + SD_JOURNAL_FOREACH(j) { + _cleanup_free_ char *c; + + assert_se(sd_journal_get_data(j, "NUMBER", &data, &l) >= 0); + printf("\t%.*s\n", (int) l, (const char*) data); + + assert_se(sd_journal_get_cursor(j, &c) >= 0); + assert_se(sd_journal_test_cursor(j, c) > 0); + } + + sd_journal_flush_matches(j); + + verify_contents(j, 1); + + printf("NEXT TEST\n"); + assert_se(sd_journal_add_match(j, "MAGIC=quux", 0) >= 0); + + assert_se(z = journal_make_match_string(j)); + printf("resulting match expression is: %s\n", z); + free(z); + + verify_contents(j, 5); + + printf("NEXT TEST\n"); + sd_journal_flush_matches(j); + assert_se(sd_journal_add_match(j, "MAGIC=waldo", 0) >= 0); + assert_se(sd_journal_add_match(j, "NUMBER=10", 0) >= 0); + assert_se(sd_journal_add_match(j, "NUMBER=11", 0) >= 0); + assert_se(sd_journal_add_match(j, "NUMBER=12", 0) >= 0); + + assert_se(z = journal_make_match_string(j)); + printf("resulting match expression is: %s\n", z); + free(z); + + verify_contents(j, 0); + + assert_se(sd_journal_query_unique(j, "NUMBER") >= 0); + SD_JOURNAL_FOREACH_UNIQUE(j, data, l) + printf("%.*s\n", (int) l, (const char*) data); + + assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); + + return 0; +} diff --git a/src/journal/test-journal-syslog.c b/src/journal/test-journal-syslog.c new file mode 100644 index 00000000..45be7e5b --- /dev/null +++ b/src/journal/test-journal-syslog.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "journald-syslog.h" +#include "macro.h" +#include "string-util.h" +#include "syslog-util.h" + +static void test_syslog_parse_identifier(const char *str, + const char *ident, const char *pid, const char *rest, int ret) { + const char *buf = str; + _cleanup_free_ char *ident2 = NULL, *pid2 = NULL; + int ret2; + + ret2 = syslog_parse_identifier(&buf, &ident2, &pid2); + + assert_se(ret == ret2); + assert_se(ident == ident2 || streq_ptr(ident, ident2)); + assert_se(pid == pid2 || streq_ptr(pid, pid2)); + assert_se(streq(buf, rest)); +} + +static void test_syslog_parse_priority(const char *str, int priority, int ret) { + const char *buf = str; + int priority2 = 0, ret2; + + ret2 = syslog_parse_priority(&buf, &priority2, false); + + assert_se(ret == ret2); + if (ret2 == 1) + assert_se(priority == priority2); +} + +int main(void) { + test_syslog_parse_identifier("pidu[111]: xxx", "pidu", "111", "xxx", 11); + test_syslog_parse_identifier("pidu: xxx", "pidu", NULL, "xxx", 6); + test_syslog_parse_identifier("pidu: xxx", "pidu", NULL, " xxx", 6); + test_syslog_parse_identifier("pidu xxx", NULL, NULL, "pidu xxx", 0); + test_syslog_parse_identifier(" pidu xxx", NULL, NULL, " pidu xxx", 0); + test_syslog_parse_identifier("", NULL, NULL, "", 0); + test_syslog_parse_identifier(" ", NULL, NULL, " ", 0); + test_syslog_parse_identifier(":", "", NULL, "", 1); + test_syslog_parse_identifier(": ", "", NULL, " ", 2); + test_syslog_parse_identifier(" :", "", NULL, "", 2); + test_syslog_parse_identifier(" pidu:", "pidu", NULL, "", 8); + test_syslog_parse_identifier("pidu:", "pidu", NULL, "", 5); + test_syslog_parse_identifier("pidu: ", "pidu", NULL, "", 6); + test_syslog_parse_identifier("pidu : ", NULL, NULL, "pidu : ", 0); + + test_syslog_parse_priority("<>", 0, 0); + test_syslog_parse_priority("<>aaa", 0, 0); + test_syslog_parse_priority("", 0, 0); + test_syslog_parse_priority("aaa", 0, 0); + test_syslog_parse_priority(" ", 0, 0); + test_syslog_parse_priority(" aaa", 0, 0); + /* TODO: add test cases of valid priorities */ + + return 0; +} diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c new file mode 100644 index 00000000..2893a7c0 --- /dev/null +++ b/src/journal/test-journal-verify.c @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "chattr-util.h" +#include "fd-util.h" +#include "io-util.h" +#include "journal-file.h" +#include "journal-verify.h" +#include "log.h" +#include "rm-rf.h" +#include "terminal-util.h" +#include "tests.h" +#include "util.h" + +#define N_ENTRIES 6000 +#define RANDOM_RANGE 77 + +static void bit_toggle(const char *fn, uint64_t p) { + uint8_t b; + ssize_t r; + int fd; + + fd = open(fn, O_RDWR|O_CLOEXEC); + assert_se(fd >= 0); + + r = pread(fd, &b, 1, p/8); + assert_se(r == 1); + + b ^= 1 << (p % 8); + + r = pwrite(fd, &b, 1, p/8); + assert_se(r == 1); + + safe_close(fd); +} + +static int raw_verify(const char *fn, const char *verification_key) { + JournalFile *f; + int r; + + r = journal_file_open(-1, fn, O_RDONLY, 0666, true, (uint64_t) -1, !!verification_key, NULL, NULL, NULL, NULL, &f); + if (r < 0) + return r; + + r = journal_file_verify(f, verification_key, NULL, NULL, NULL, false); + (void) journal_file_close(f); + + return r; +} + +int main(int argc, char *argv[]) { + char t[] = "/var/tmp/journal-XXXXXX"; + unsigned n; + JournalFile *f; + const char *verification_key = argv[1]; + usec_t from = 0, to = 0, total = 0; + char a[FORMAT_TIMESTAMP_MAX]; + char b[FORMAT_TIMESTAMP_MAX]; + char c[FORMAT_TIMESPAN_MAX]; + struct stat st; + uint64_t p; + + /* journal_file_open requires a valid machine id */ + if (access("/etc/machine-id", F_OK) != 0) + return log_tests_skipped("/etc/machine-id not found"); + + test_setup_logging(LOG_DEBUG); + + assert_se(mkdtemp(t)); + assert_se(chdir(t) >= 0); + (void) chattr_path(t, FS_NOCOW_FL, FS_NOCOW_FL, NULL); + + log_info("Generating..."); + + assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0); + + for (n = 0; n < N_ENTRIES; n++) { + struct iovec iovec; + struct dual_timestamp ts; + char *test; + + dual_timestamp_get(&ts); + + assert_se(asprintf(&test, "RANDOM=%lu", random() % RANDOM_RANGE)); + + iovec = IOVEC_MAKE_STRING(test); + + assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0); + + free(test); + } + + (void) journal_file_close(f); + + log_info("Verifying..."); + + assert_se(journal_file_open(-1, "test.journal", O_RDONLY, 0666, true, (uint64_t) -1, !!verification_key, NULL, NULL, NULL, NULL, &f) == 0); + /* journal_file_print_header(f); */ + journal_file_dump(f); + + assert_se(journal_file_verify(f, verification_key, &from, &to, &total, true) >= 0); + + if (verification_key && JOURNAL_HEADER_SEALED(f->header)) + log_info("=> Validated from %s to %s, %s missing", + format_timestamp(a, sizeof(a), from), + format_timestamp(b, sizeof(b), to), + format_timespan(c, sizeof(c), total > to ? total - to : 0, 0)); + + (void) journal_file_close(f); + + if (verification_key) { + log_info("Toggling bits..."); + + assert_se(stat("test.journal", &st) >= 0); + + for (p = 38448*8+0; p < ((uint64_t) st.st_size * 8); p ++) { + bit_toggle("test.journal", p); + + log_info("[ %"PRIu64"+%"PRIu64"]", p / 8, p % 8); + + if (raw_verify("test.journal", verification_key) >= 0) + log_notice(ANSI_HIGHLIGHT_RED ">>>> %"PRIu64" (bit %"PRIu64") can be toggled without detection." ANSI_NORMAL, p / 8, p % 8); + + bit_toggle("test.journal", p); + } + } + + log_info("Exiting..."); + + assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); + + return 0; +} diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c new file mode 100644 index 00000000..7f56668a --- /dev/null +++ b/src/journal/test-journal.c @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "chattr-util.h" +#include "io-util.h" +#include "journal-authenticate.h" +#include "journal-file.h" +#include "journal-vacuum.h" +#include "log.h" +#include "rm-rf.h" +#include "tests.h" + +static bool arg_keep = false; + +static void mkdtemp_chdir_chattr(char *path) { + assert_se(mkdtemp(path)); + assert_se(chdir(path) >= 0); + + /* Speed up things a bit on btrfs, ensuring that CoW is turned off for all files created in our + * directory during the test run */ + (void) chattr_path(path, FS_NOCOW_FL, FS_NOCOW_FL, NULL); +} + +static void test_non_empty(void) { + dual_timestamp ts; + JournalFile *f; + struct iovec iovec; + static const char test[] = "TEST1=1", test2[] = "TEST2=2"; + Object *o; + uint64_t p; + sd_id128_t fake_boot_id; + char t[] = "/var/tmp/journal-XXXXXX"; + + test_setup_logging(LOG_DEBUG); + + mkdtemp_chdir_chattr(t); + + assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, true, NULL, NULL, NULL, NULL, &f) == 0); + + assert_se(dual_timestamp_get(&ts)); + assert_se(sd_id128_randomize(&fake_boot_id) == 0); + + iovec = IOVEC_MAKE_STRING(test); + assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0); + + iovec = IOVEC_MAKE_STRING(test2); + assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0); + + iovec = IOVEC_MAKE_STRING(test); + assert_se(journal_file_append_entry(f, &ts, &fake_boot_id, &iovec, 1, NULL, NULL, NULL) == 0); + +#if HAVE_GCRYPT + journal_file_append_tag(f); +#endif + journal_file_dump(f); + + assert_se(journal_file_next_entry(f, 0, DIRECTION_DOWN, &o, &p) == 1); + assert_se(le64toh(o->entry.seqnum) == 1); + + assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 1); + assert_se(le64toh(o->entry.seqnum) == 2); + + assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 1); + assert_se(le64toh(o->entry.seqnum) == 3); + assert_se(sd_id128_equal(o->entry.boot_id, fake_boot_id)); + + assert_se(journal_file_next_entry(f, p, DIRECTION_DOWN, &o, &p) == 0); + + assert_se(journal_file_next_entry(f, 0, DIRECTION_DOWN, &o, &p) == 1); + assert_se(le64toh(o->entry.seqnum) == 1); + + assert_se(journal_file_find_data_object(f, test, strlen(test), NULL, &p) == 1); + assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1); + assert_se(le64toh(o->entry.seqnum) == 1); + + assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1); + assert_se(le64toh(o->entry.seqnum) == 3); + + assert_se(journal_file_find_data_object(f, test2, strlen(test2), NULL, &p) == 1); + assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_UP, &o, NULL) == 1); + assert_se(le64toh(o->entry.seqnum) == 2); + + assert_se(journal_file_next_entry_for_data(f, NULL, 0, p, DIRECTION_DOWN, &o, NULL) == 1); + assert_se(le64toh(o->entry.seqnum) == 2); + + assert_se(journal_file_find_data_object(f, "quux", 4, NULL, &p) == 0); + + assert_se(journal_file_move_to_entry_by_seqnum(f, 1, DIRECTION_DOWN, &o, NULL) == 1); + assert_se(le64toh(o->entry.seqnum) == 1); + + assert_se(journal_file_move_to_entry_by_seqnum(f, 3, DIRECTION_DOWN, &o, NULL) == 1); + assert_se(le64toh(o->entry.seqnum) == 3); + + assert_se(journal_file_move_to_entry_by_seqnum(f, 2, DIRECTION_DOWN, &o, NULL) == 1); + assert_se(le64toh(o->entry.seqnum) == 2); + + assert_se(journal_file_move_to_entry_by_seqnum(f, 10, DIRECTION_DOWN, &o, NULL) == 0); + + journal_file_rotate(&f, true, (uint64_t) -1, true, NULL); + journal_file_rotate(&f, true, (uint64_t) -1, true, NULL); + + (void) journal_file_close(f); + + log_info("Done..."); + + if (arg_keep) + log_info("Not removing %s", t); + else { + journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); + + assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); + } + + puts("------------------------------------------------------------"); +} + +static void test_empty(void) { + JournalFile *f1, *f2, *f3, *f4; + char t[] = "/var/tmp/journal-XXXXXX"; + + test_setup_logging(LOG_DEBUG); + + mkdtemp_chdir_chattr(t); + + assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, false, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &f1) == 0); + + assert_se(journal_file_open(-1, "test-compress.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, false, NULL, NULL, NULL, NULL, &f2) == 0); + + assert_se(journal_file_open(-1, "test-seal.journal", O_RDWR|O_CREAT, 0666, false, (uint64_t) -1, true, NULL, NULL, NULL, NULL, &f3) == 0); + + assert_se(journal_file_open(-1, "test-seal-compress.journal", O_RDWR|O_CREAT, 0666, true, (uint64_t) -1, true, NULL, NULL, NULL, NULL, &f4) == 0); + + journal_file_print_header(f1); + puts(""); + journal_file_print_header(f2); + puts(""); + journal_file_print_header(f3); + puts(""); + journal_file_print_header(f4); + puts(""); + + log_info("Done..."); + + if (arg_keep) + log_info("Not removing %s", t); + else { + journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); + + assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); + } + + (void) journal_file_close(f1); + (void) journal_file_close(f2); + (void) journal_file_close(f3); + (void) journal_file_close(f4); +} + +#if HAVE_XZ || HAVE_LZ4 +static bool check_compressed(uint64_t compress_threshold, uint64_t data_size) { + dual_timestamp ts; + JournalFile *f; + struct iovec iovec; + Object *o; + uint64_t p; + char t[] = "/var/tmp/journal-XXXXXX"; + char data[2048] = {0}; + bool is_compressed; + int r; + + assert_se(data_size <= sizeof(data)); + + test_setup_logging(LOG_DEBUG); + + mkdtemp_chdir_chattr(t); + + assert_se(journal_file_open(-1, "test.journal", O_RDWR|O_CREAT, 0666, true, compress_threshold, true, NULL, NULL, NULL, NULL, &f) == 0); + + dual_timestamp_get(&ts); + + iovec = IOVEC_MAKE(data, data_size); + assert_se(journal_file_append_entry(f, &ts, NULL, &iovec, 1, NULL, NULL, NULL) == 0); + +#if HAVE_GCRYPT + journal_file_append_tag(f); +#endif + journal_file_dump(f); + + /* We have to partially reimplement some of the dump logic, because the normal next_entry does the + * decompression for us. */ + p = le64toh(f->header->header_size); + for (;;) { + r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); + assert_se(r == 0); + if (o->object.type == OBJECT_DATA) + break; + + assert_se(p < le64toh(f->header->tail_object_offset)); + p = p + ALIGN64(le64toh(o->object.size)); + } + + is_compressed = (o->object.flags & OBJECT_COMPRESSION_MASK) != 0; + + (void) journal_file_close(f); + + log_info("Done..."); + + if (arg_keep) + log_info("Not removing %s", t); + else { + journal_directory_vacuum(".", 3000000, 0, 0, NULL, true); + + assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); + } + + puts("------------------------------------------------------------"); + + return is_compressed; +} + +static void test_min_compress_size(void) { + /* Note that XZ will actually fail to compress anything under 80 bytes, so you have to choose the limits + * carefully */ + + /* DEFAULT_MIN_COMPRESS_SIZE is 512 */ + assert_se(!check_compressed((uint64_t) -1, 255)); + assert_se(check_compressed((uint64_t) -1, 513)); + + /* compress everything */ + assert_se(check_compressed(0, 96)); + assert_se(check_compressed(8, 96)); + + /* Ensure we don't try to compress less than 8 bytes */ + assert_se(!check_compressed(0, 7)); + + /* check boundary conditions */ + assert_se(check_compressed(256, 256)); + assert_se(!check_compressed(256, 255)); +} +#endif + +int main(int argc, char *argv[]) { + arg_keep = argc > 1; + + test_setup_logging(LOG_INFO); + + /* journal_file_open requires a valid machine id */ + if (access("/etc/machine-id", F_OK) != 0) + return log_tests_skipped("/etc/machine-id not found"); + + test_non_empty(); + test_empty(); +#if HAVE_XZ || HAVE_LZ4 + test_min_compress_size(); +#endif + + return 0; +} diff --git a/src/journal/test-mmap-cache.c b/src/journal/test-mmap-cache.c new file mode 100644 index 00000000..8f755efd --- /dev/null +++ b/src/journal/test-mmap-cache.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "fd-util.h" +#include "macro.h" +#include "mmap-cache.h" +#include "tmpfile-util.h" +#include "util.h" + +int main(int argc, char *argv[]) { + MMapFileDescriptor *fx; + int x, y, z, r; + char px[] = "/tmp/testmmapXXXXXXX", py[] = "/tmp/testmmapYXXXXXX", pz[] = "/tmp/testmmapZXXXXXX"; + MMapCache *m; + void *p, *q; + + assert_se(m = mmap_cache_new()); + + x = mkostemp_safe(px); + assert_se(x >= 0); + unlink(px); + + assert_se(fx = mmap_cache_add_fd(m, x)); + + y = mkostemp_safe(py); + assert_se(y >= 0); + unlink(py); + + z = mkostemp_safe(pz); + assert_se(z >= 0); + unlink(pz); + + r = mmap_cache_get(m, fx, PROT_READ, 0, false, 1, 2, NULL, &p, NULL); + assert_se(r >= 0); + + r = mmap_cache_get(m, fx, PROT_READ, 0, false, 2, 2, NULL, &q, NULL); + assert_se(r >= 0); + + assert_se((uint8_t*) p + 1 == (uint8_t*) q); + + r = mmap_cache_get(m, fx, PROT_READ, 1, false, 3, 2, NULL, &q, NULL); + assert_se(r >= 0); + + assert_se((uint8_t*) p + 2 == (uint8_t*) q); + + r = mmap_cache_get(m, fx, PROT_READ, 0, false, 16ULL*1024ULL*1024ULL, 2, NULL, &p, NULL); + assert_se(r >= 0); + + r = mmap_cache_get(m, fx, PROT_READ, 1, false, 16ULL*1024ULL*1024ULL+1, 2, NULL, &q, NULL); + assert_se(r >= 0); + + assert_se((uint8_t*) p + 1 == (uint8_t*) q); + + mmap_cache_free_fd(m, fx); + mmap_cache_unref(m); + + safe_close(x); + safe_close(y); + safe_close(z); + + return 0; +} diff --git a/src/kernel-install/00-entry-directory.install b/src/kernel-install/00-entry-directory.install new file mode 100644 index 00000000..2aa8c583 --- /dev/null +++ b/src/kernel-install/00-entry-directory.install @@ -0,0 +1,32 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +COMMAND="$1" +KERNEL_VERSION="$2" +ENTRY_DIR_ABS="$3" +KERNEL_IMAGE="$4" +INITRD_OPTIONS_START="5" + +if ! [[ $KERNEL_INSTALL_MACHINE_ID ]]; then + exit 0 +fi + +if [[ $COMMAND != add ]]; then + exit 0 +fi + +# If the boot dir exists (e.g. $ESP/), +# create the entry directory ($ESP//). +# This is the only function of this plugin. +MACHINE_ID_DIR="${ENTRY_DIR_ABS%/*}" +if ! [ -d "$MACHINE_ID_DIR" ]; then + exit 0 +fi + +if [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ]; then + echo "+mkdir -v -p $ENTRY_DIR_ABS" + exec mkdir -v -p "$ENTRY_DIR_ABS" +else + exec mkdir -p "$ENTRY_DIR_ABS" +fi diff --git a/src/kernel-install/50-depmod.install b/src/kernel-install/50-depmod.install new file mode 100644 index 00000000..268b6ce0 --- /dev/null +++ b/src/kernel-install/50-depmod.install @@ -0,0 +1,27 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +COMMAND="$1" +KERNEL_VERSION="$2" +ENTRY_DIR_ABS="$3" +KERNEL_IMAGE="$4" +INITRD_OPTIONS_START="5" + +[[ $KERNEL_VERSION ]] || exit 1 + +case "$COMMAND" in + add) + [[ -d "/lib/modules/${KERNEL_VERSION}/kernel" ]] || exit 0 + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "Running depmod -a ${KERNEL_VERSION}" + exec depmod -a "${KERNEL_VERSION}" + ;; + remove) + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "Removing /lib/modules/${KERNEL_VERSION}/modules.dep and associated files" + exec rm -f /lib/modules/"${KERNEL_VERSION}"/modules.{alias{,.bin},builtin.bin,dep{,.bin},devname,softdep,symbols{,.bin}} + ;; + *) + exit 0 +esac diff --git a/src/kernel-install/90-loaderentry.install b/src/kernel-install/90-loaderentry.install new file mode 100644 index 00000000..47a0cd22 --- /dev/null +++ b/src/kernel-install/90-loaderentry.install @@ -0,0 +1,122 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh + +COMMAND="$1" +KERNEL_VERSION="$2" +ENTRY_DIR_ABS="$3" +KERNEL_IMAGE="$4" +INITRD_OPTIONS_START="5" + +if ! [[ $KERNEL_INSTALL_MACHINE_ID ]]; then + exit 0 +fi + +if ! [[ -d "$ENTRY_DIR_ABS" ]]; then + exit 0 +fi + +MACHINE_ID=$KERNEL_INSTALL_MACHINE_ID + +ENTRY_DIR="/$MACHINE_ID/$KERNEL_VERSION" +BOOT_ROOT=${ENTRY_DIR_ABS%$ENTRY_DIR} + +if [[ $COMMAND == remove ]]; then + rm -f "$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf" + rm -f "$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION+"*".conf" + exit 0 +fi + +if ! [[ $COMMAND == add ]]; then + exit 1 +fi + +if ! [[ $KERNEL_IMAGE ]]; then + exit 1 +fi + +if [[ -f /etc/os-release ]]; then + . /etc/os-release +elif [[ -f /usr/lib/os-release ]]; then + . /usr/lib/os-release +fi + +if ! [[ $PRETTY_NAME ]]; then + PRETTY_NAME="Linux $KERNEL_VERSION" +fi + +if [[ -f /etc/kernel/cmdline ]]; then + read -r -d '' -a BOOT_OPTIONS < /etc/kernel/cmdline +elif [[ -f /usr/lib/kernel/cmdline ]]; then + read -r -d '' -a BOOT_OPTIONS < /usr/lib/kernel/cmdline +else + declare -a BOOT_OPTIONS + + read -r -d '' -a line < /proc/cmdline + for i in "${line[@]}"; do + [[ "${i#initrd=*}" != "$i" ]] && continue + BOOT_OPTIONS+=("$i") + done +fi + +if [[ -f /etc/kernel/tries ]]; then + read -r TRIES &2 + exit 1 + fi + LOADER_ENTRY="$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION+$TRIES.conf" +else + LOADER_ENTRY="$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf" +fi + +cp "$KERNEL_IMAGE" "$ENTRY_DIR_ABS/linux" && + chown root:root "$ENTRY_DIR_ABS/linux" && + chmod 0644 "$ENTRY_DIR_ABS/linux" || { + echo "Could not copy '$KERNEL_IMAGE to '$ENTRY_DIR_ABS/linux'." >&2 + exit 1 +} + +INITRD_OPTIONS=( "${@:${INITRD_OPTIONS_START}}" ) + +for initrd in "${INITRD_OPTIONS[@]}"; do + if [[ -f "${initrd}" ]]; then + initrd_basename="$(basename ${initrd})" + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "Installing $ENTRY_DIR_ABS/${initrd_basename}" + cp "${initrd}" "$ENTRY_DIR_ABS/${initrd_basename}" && + chown root:root "$ENTRY_DIR_ABS/${initrd_basename}" && + chmod 0644 "$ENTRY_DIR_ABS/${initrd_basename}" || { + echo "Could not copy '${initrd}' to '$ENTRY_DIR_ABS/${initrd_basename}'." >&2 + exit 1 + } + fi +done + +# If no initrd option is supplied, fallback to "initrd" which is +# the name used by dracut when generating it in its kernel-install hook +[[ ${#INITRD_OPTIONS[@]} == 0 ]] && INITRD_OPTIONS=( initrd ) + +mkdir -p "${LOADER_ENTRY%/*}" || { + echo "Could not create loader entry directory '${LOADER_ENTRY%/*}'." >&2 + exit 1 +} + +[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "Creating $LOADER_ENTRY" +{ + echo "title $PRETTY_NAME" + echo "version $KERNEL_VERSION" + echo "machine-id $MACHINE_ID" + echo "options ${BOOT_OPTIONS[*]}" + echo "linux $ENTRY_DIR/linux" + for initrd in "${INITRD_OPTIONS[@]}"; do + [[ -f $ENTRY_DIR_ABS/$(basename ${initrd}) ]] && \ + echo "initrd $ENTRY_DIR/$(basename ${initrd})" + done + : +} > "$LOADER_ENTRY" || { + echo "Could not create loader entry '$LOADER_ENTRY'." >&2 + exit 1 +} +exit 0 diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install new file mode 100644 index 00000000..e7f2beb5 --- /dev/null +++ b/src/kernel-install/kernel-install @@ -0,0 +1,184 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# systemd is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with systemd; If not, see . + +SKIP_REMAINING=77 + +usage() +{ + echo "Usage:" + echo " $0 add KERNEL-VERSION KERNEL-IMAGE [INITRD-FILE ...]" + echo " $0 remove KERNEL-VERSION" +} + +dropindirs_sort() +{ + local suffix=$1; shift + local -a files + local f d i + + readarray -t files <<<"$( + for d in "$@"; do + for i in "$d/"*"$suffix"; do + if [[ -e "$i" ]]; then + echo "${i##*/}" + fi + done + done | sort -Vu + )" + + for f in "${files[@]}"; do + for d in "$@"; do + if [[ -e "$d/$f" ]]; then + echo "$d/$f" + continue 2 + fi + done + done +} + +export LC_COLLATE=C + +for i in "$@"; do + if [ "$i" == "--help" -o "$i" == "-h" ]; then + usage + exit 0 + fi +done + +KERNEL_INSTALL_VERBOSE=0 +if [ "$1" == "--verbose" -o "$1" == "-v" ]; then + shift + KERNEL_INSTALL_VERBOSE=1 +fi +export KERNEL_INSTALL_VERBOSE + +if [[ "${0##*/}" == 'installkernel' ]]; then + COMMAND='add' + # make install doesn't pass any parameter wrt initrd handling + INITRD_OPTIONS=() +else + COMMAND="$1" + shift + INITRD_OPTIONS=( "${@:3}" ) +fi + +KERNEL_VERSION="$1" +KERNEL_IMAGE="$2" + +if [[ -f /etc/machine-id ]]; then + read MACHINE_ID < /etc/machine-id +fi + +if [[ ! $COMMAND ]] || [[ ! $KERNEL_VERSION ]]; then + echo "Not enough arguments" >&2 + exit 1 +fi + +if ! [[ $MACHINE_ID ]]; then + ENTRY_DIR_ABS=$(mktemp -d /tmp/kernel-install.XXXXX) || exit 1 + trap "rm -rf '$ENTRY_DIR_ABS'" EXIT INT QUIT PIPE +elif [[ -d /efi/loader/entries ]] || [[ -d /efi/$MACHINE_ID ]]; then + ENTRY_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION" +elif [[ -d /boot/loader/entries ]] || [[ -d /boot/$MACHINE_ID ]]; then + ENTRY_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION" +elif [[ -d /boot/efi/loader/entries ]] || [[ -d /boot/efi/$MACHINE_ID ]]; then + ENTRY_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION" +elif mountpoint -q /efi; then + ENTRY_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION" +elif mountpoint -q /boot/efi; then + ENTRY_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION" +else + ENTRY_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION" +fi + +export KERNEL_INSTALL_MACHINE_ID=$MACHINE_ID + +ret=0 + +readarray -t PLUGINS <<<"$( + dropindirs_sort ".install" \ + "/etc/kernel/install.d" \ + "/usr/lib/kernel/install.d" +)" + +case $COMMAND in + add) + if [[ ! "$KERNEL_IMAGE" ]]; then + echo "Command 'add' requires an argument" >&2 + exit 1 + fi + + if [[ ! -f "$KERNEL_IMAGE" ]]; then + echo "Kernel image argument ${KERNEL_IMAGE} not a file" >&2 + exit 1 + fi + + for f in "${PLUGINS[@]}"; do + if [[ -x $f ]]; then + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "+$f add $KERNEL_VERSION $ENTRY_DIR_ABS $KERNEL_IMAGE ${INITRD_OPTIONS[@]}" + "$f" add "$KERNEL_VERSION" "$ENTRY_DIR_ABS" "$KERNEL_IMAGE" "${INITRD_OPTIONS[@]}" + x=$? + if [[ $x == $SKIP_REMAINING ]]; then + ret=0 + break + fi + ((ret+=$x)) + fi + done + + if ! [[ $MACHINE_ID ]] && ! rmdir "$ENTRY_DIR_ABS"; then + echo "Warning: In kernel-install plugins, requiring ENTRY_DIR_ABS to be preset is deprecated." >&2 + echo " All plugins should not put anything in ENTRY_DIR_ABS if the environment" >&2 + echo " variable KERNEL_INSTALL_MACHINE_ID is empty." >&2 + rm -rf "$ENTRY_DIR_ABS" + ((ret+=$?)) + fi + ;; + + remove) + for f in "${PLUGINS[@]}"; do + if [[ -x $f ]]; then + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "+$f remove $KERNEL_VERSION $ENTRY_DIR_ABS" + "$f" remove "$KERNEL_VERSION" "$ENTRY_DIR_ABS" + x=$? + if [[ $x == $SKIP_REMAINING ]]; then + ret=0 + break + fi + ((ret+=$x)) + fi + done + + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "Removing $ENTRY_DIR_ABS" + + rm -rf "$ENTRY_DIR_ABS" + ((ret+=$?)) + ;; + + *) + echo "Unknown command '$COMMAND'" >&2 + exit 1 + ;; +esac + +exit $ret diff --git a/src/kernel-install/meson.build b/src/kernel-install/meson.build new file mode 100644 index 00000000..261c3aaa --- /dev/null +++ b/src/kernel-install/meson.build @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +install_data('kernel-install', + install_mode : 'rwxr-xr-x', + install_dir : bindir) + +install_data('00-entry-directory.install', + '50-depmod.install', + '90-loaderentry.install', + install_mode : 'rwxr-xr-x', + install_dir : kernelinstalldir) + +meson.add_install_script('sh', '-c', + mkdir_p.format(join_paths(sysconfdir, 'kernel/install.d'))) diff --git a/src/libsystemd-network/arp-util.c b/src/libsystemd-network/arp-util.c new file mode 100644 index 00000000..ac601a4e --- /dev/null +++ b/src/libsystemd-network/arp-util.c @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Axis Communications AB. All rights reserved. +***/ + +#include +#include +#include + +#include "arp-util.h" +#include "fd-util.h" +#include "unaligned.h" +#include "util.h" + +int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_addr *eth_mac) { + struct sock_filter filter[] = { + BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */ + BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ether_arp), 1, 0), /* packet >= arp packet ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hrd)), /* A <- header */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPHRD_ETHER, 1, 0), /* header == ethernet ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pro)), /* A <- protocol */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 1, 0), /* protocol == IP ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hln)), /* A <- hardware address length */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(struct ether_addr), 1, 0), /* length == sizeof(ether_addr)? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pln)), /* A <- protocol address length */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(struct in_addr), 1, 0), /* length == sizeof(in_addr) ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_op)), /* A <- operation */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REQUEST, 2, 0), /* protocol == request ? */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 0), /* protocol == reply ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + /* Sender Hardware Address must be different from our own */ + BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])),/* A <- 4 bytes of client's MAC */ + BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_sha)), /* A <- 4 bytes of SHA */ + BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 6), /* A == 0 ? */ + BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])),/* A <- remainder of client's MAC */ + BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, arp_sha) + 4), /* A <- remainder of SHA */ + BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + /* Sender Protocol Address or Target Protocol Address must be equal to the one we care about */ + BPF_STMT(BPF_LD + BPF_IMM, htobe32(address)), /* A <- clients IP */ + BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_spa)), /* A <- SPA */ + BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* X xor A */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ + BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ + BPF_STMT(BPF_LD + BPF_IMM, htobe32(address)), /* A <- clients IP */ + BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_tpa)), /* A <- TPA */ + BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* X xor A */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ + BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + }; + struct sock_fprog fprog = { + .len = ELEMENTSOF(filter), + .filter = (struct sock_filter*) filter + }; + union sockaddr_union link = { + .ll.sll_family = AF_PACKET, + .ll.sll_protocol = htobe16(ETH_P_ARP), + .ll.sll_ifindex = ifindex, + .ll.sll_halen = ETH_ALEN, + .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + }; + _cleanup_close_ int s = -1; + int r; + + assert(ifindex > 0); + + s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (s < 0) + return -errno; + + r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); + if (r < 0) + return -errno; + + r = bind(s, &link.sa, sizeof(link.ll)); + if (r < 0) + return -errno; + + return TAKE_FD(s); +} + +static int arp_send_packet(int fd, int ifindex, + be32_t pa, const struct ether_addr *ha, + bool announce) { + union sockaddr_union link = { + .ll.sll_family = AF_PACKET, + .ll.sll_protocol = htobe16(ETH_P_ARP), + .ll.sll_ifindex = ifindex, + .ll.sll_halen = ETH_ALEN, + .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + }; + struct ether_arp arp = { + .ea_hdr.ar_hrd = htobe16(ARPHRD_ETHER), /* HTYPE */ + .ea_hdr.ar_pro = htobe16(ETHERTYPE_IP), /* PTYPE */ + .ea_hdr.ar_hln = ETH_ALEN, /* HLEN */ + .ea_hdr.ar_pln = sizeof(be32_t), /* PLEN */ + .ea_hdr.ar_op = htobe16(ARPOP_REQUEST), /* REQUEST */ + }; + int r; + + assert(fd >= 0); + assert(pa != 0); + assert(ha); + + memcpy(&arp.arp_sha, ha, ETH_ALEN); + memcpy(&arp.arp_tpa, &pa, sizeof(pa)); + + if (announce) + memcpy(&arp.arp_spa, &pa, sizeof(pa)); + + r = sendto(fd, &arp, sizeof(struct ether_arp), 0, &link.sa, sizeof(link.ll)); + if (r < 0) + return -errno; + + return 0; +} + +int arp_send_probe(int fd, int ifindex, + be32_t pa, const struct ether_addr *ha) { + return arp_send_packet(fd, ifindex, pa, ha, false); +} + +int arp_send_announcement(int fd, int ifindex, + be32_t pa, const struct ether_addr *ha) { + return arp_send_packet(fd, ifindex, pa, ha, true); +} diff --git a/src/libsystemd-network/arp-util.h b/src/libsystemd-network/arp-util.h new file mode 100644 index 00000000..9a4427e8 --- /dev/null +++ b/src/libsystemd-network/arp-util.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2014 Axis Communications AB. All rights reserved. +***/ + +#include + +#include "socket-util.h" +#include "sparse-endian.h" + +int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_addr *eth_mac); + +int arp_send_probe(int fd, int ifindex, + be32_t pa, const struct ether_addr *ha); +int arp_send_announcement(int fd, int ifindex, + be32_t pa, const struct ether_addr *ha); diff --git a/src/libsystemd-network/dhcp-client-internal.h b/src/libsystemd-network/dhcp-client-internal.h new file mode 100644 index 00000000..2c48d095 --- /dev/null +++ b/src/libsystemd-network/dhcp-client-internal.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +extern const struct hash_ops dhcp_option_hash_ops; diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c new file mode 100644 index 00000000..c01c1cf6 --- /dev/null +++ b/src/libsystemd-network/dhcp-identifier.c @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-device.h" +#include "sd-id128.h" + +#include "dhcp-identifier.h" +#include "dhcp6-protocol.h" +#include "network-internal.h" +#include "siphash24.h" +#include "sparse-endian.h" +#include "stdio-util.h" +#include "udev-util.h" +#include "virt.h" + +#define SYSTEMD_PEN 43793 +#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09) +#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03) +#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */ + +int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict) { + struct duid d; + + assert_cc(sizeof(d.raw) >= MAX_DUID_LEN); + if (duid_len > MAX_DUID_LEN) + return -EINVAL; + + if (!strict) { + /* Strict validation is not requested. We only ensure that the + * DUID is not too long. */ + return 0; + } + + switch (duid_type) { + case DUID_TYPE_LLT: + if (duid_len <= sizeof(d.llt)) + return -EINVAL; + break; + case DUID_TYPE_EN: + if (duid_len != sizeof(d.en)) + return -EINVAL; + break; + case DUID_TYPE_LL: + if (duid_len <= sizeof(d.ll)) + return -EINVAL; + break; + case DUID_TYPE_UUID: + if (duid_len != sizeof(d.uuid)) + return -EINVAL; + break; + default: + /* accept unknown type in order to be forward compatible */ + break; + } + return 0; +} + +int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) { + uint16_t time_from_2000y; + + assert(duid); + assert(len); + assert(addr); + + if (arp_type == ARPHRD_ETHER) + assert_return(addr_len == ETH_ALEN, -EINVAL); + else if (arp_type == ARPHRD_INFINIBAND) + assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); + else + return -EINVAL; + + if (t < USEC_2000) + time_from_2000y = 0; + else + time_from_2000y = (uint16_t) (((t - USEC_2000) / USEC_PER_SEC) & 0xffffffff); + + unaligned_write_be16(&duid->type, DUID_TYPE_LLT); + unaligned_write_be16(&duid->llt.htype, arp_type); + unaligned_write_be32(&duid->llt.time, time_from_2000y); + memcpy(duid->llt.haddr, addr, addr_len); + + *len = sizeof(duid->type) + sizeof(duid->llt.htype) + sizeof(duid->llt.time) + addr_len; + + return 0; +} + +int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) { + assert(duid); + assert(len); + assert(addr); + + if (arp_type == ARPHRD_ETHER) + assert_return(addr_len == ETH_ALEN, -EINVAL); + else if (arp_type == ARPHRD_INFINIBAND) + assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); + else + return -EINVAL; + + unaligned_write_be16(&duid->type, DUID_TYPE_LL); + unaligned_write_be16(&duid->ll.htype, arp_type); + memcpy(duid->ll.haddr, addr, addr_len); + + *len = sizeof(duid->type) + sizeof(duid->ll.htype) + addr_len; + + return 0; +} + +int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { + sd_id128_t machine_id; + uint64_t hash; + int r; + + assert(duid); + assert(len); + + r = sd_id128_get_machine(&machine_id); + if (r < 0) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + machine_id = SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10); +#else + return r; +#endif + } + + unaligned_write_be16(&duid->type, DUID_TYPE_EN); + unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN); + + *len = sizeof(duid->type) + sizeof(duid->en); + + /* a bit of snake-oil perhaps, but no need to expose the machine-id + * directly; duid->en.id might not be aligned, so we need to copy */ + hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes)); + memcpy(duid->en.id, &hash, sizeof(duid->en.id)); + + return 0; +} + +int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len) { + sd_id128_t machine_id; + int r; + + assert(duid); + assert(len); + + r = sd_id128_get_machine_app_specific(APPLICATION_ID, &machine_id); + if (r < 0) + return r; + + unaligned_write_be16(&duid->type, DUID_TYPE_UUID); + memcpy(&duid->raw.data, &machine_id, sizeof(machine_id)); + + *len = sizeof(duid->type) + sizeof(machine_id); + + return 0; +} + +int dhcp_identifier_set_iaid( + int ifindex, + const uint8_t *mac, + size_t mac_len, + bool legacy_unstable_byteorder, + void *_id) { + /* name is a pointer to memory in the sd_device struct, so must + * have the same scope */ + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + const char *name = NULL; + uint64_t id; + uint32_t id32; + + if (detect_container() <= 0) { + /* not in a container, udev will be around */ + char ifindex_str[1 + DECIMAL_STR_MAX(int)]; + int r; + + xsprintf(ifindex_str, "n%d", ifindex); + if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) { + r = sd_device_get_is_initialized(device); + if (r < 0) + return r; + if (r == 0) + /* not yet ready */ + return -EBUSY; + + r = device_is_renaming(device); + if (r < 0) + return r; + if (r > 0) + /* device is under renaming */ + return -EBUSY; + + name = net_get_name_persistent(device); + } + } + + if (name) + id = siphash24(name, strlen(name), HASH_KEY.bytes); + else + /* fall back to MAC address if no predictable name available */ + id = siphash24(mac, mac_len, HASH_KEY.bytes); + + id32 = (id & 0xffffffff) ^ (id >> 32); + + if (legacy_unstable_byteorder) + /* for historical reasons (a bug), the bits were swapped and thus + * the result was endianness dependent. Preserve that behavior. */ + id32 = __bswap_32(id32); + else + /* the fixed behavior returns a stable byte order. Since LE is expected + * to be more common, swap the bytes on LE to give the same as legacy + * behavior. */ + id32 = be32toh(id32); + + unaligned_write_ne32(_id, id32); + return 0; +} diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h new file mode 100644 index 00000000..b3115125 --- /dev/null +++ b/src/libsystemd-network/dhcp-identifier.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-id128.h" + +#include "macro.h" +#include "sparse-endian.h" +#include "time-util.h" +#include "unaligned.h" + +typedef enum DUIDType { + DUID_TYPE_LLT = 1, + DUID_TYPE_EN = 2, + DUID_TYPE_LL = 3, + DUID_TYPE_UUID = 4, + _DUID_TYPE_MAX, + _DUID_TYPE_INVALID = -1, +} DUIDType; + +/* RFC 3315 section 9.1: + * A DUID can be no more than 128 octets long (not including the type code). + */ +#define MAX_DUID_LEN 128 + +/* https://tools.ietf.org/html/rfc3315#section-9.1 */ +struct duid { + be16_t type; + union { + struct { + /* DUID_TYPE_LLT */ + be16_t htype; + be32_t time; + uint8_t haddr[0]; + } _packed_ llt; + struct { + /* DUID_TYPE_EN */ + be32_t pen; + uint8_t id[8]; + } _packed_ en; + struct { + /* DUID_TYPE_LL */ + be16_t htype; + uint8_t haddr[0]; + } _packed_ ll; + struct { + /* DUID_TYPE_UUID */ + sd_id128_t uuid; + } _packed_ uuid; + struct { + uint8_t data[MAX_DUID_LEN]; + } _packed_ raw; + }; +} _packed_; + +int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict); +int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); +int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); +int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len); +int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len); +int dhcp_identifier_set_iaid(int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, void *_id); diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h new file mode 100644 index 00000000..6a803d7b --- /dev/null +++ b/src/libsystemd-network/dhcp-internal.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include + +#include "sd-dhcp-client.h" + +#include "dhcp-protocol.h" +#include "socket-util.h" + +typedef struct sd_dhcp_option { + unsigned n_ref; + + uint8_t option; + void *data; + size_t length; +} sd_dhcp_option; + +extern const struct hash_ops dhcp_option_hash_ops; + +int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, + uint32_t xid, const uint8_t *mac_addr, + size_t mac_addr_len, uint16_t arp_type, + uint16_t port); +int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type); +int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, + const void *packet, size_t len); +int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, + const void *packet, size_t len); + +int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload, + uint8_t code, size_t optlen, const void *optval); + +typedef int (*dhcp_option_callback_t)(uint8_t code, uint8_t len, + const void *option, void *userdata); + +int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **error_message); + +int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, + uint8_t type, uint16_t arp_type, size_t optlen, + size_t *optoffset); + +uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len); + +void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr, + uint16_t source, be32_t destination_addr, + uint16_t destination, uint16_t len, int ip_service_type); + +int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port); + +/* If we are invoking callbacks of a dhcp-client, ensure unreffing the + * client from the callback doesn't destroy the object we are working + * on */ +#define DHCP_CLIENT_DONT_DESTROY(client) \ + _cleanup_(sd_dhcp_client_unrefp) _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(client) + +#define log_dhcp_client_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__) +#define log_dhcp_client(client, fmt, ...) log_dhcp_client_errno(client, 0, fmt, ##__VA_ARGS__) diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h new file mode 100644 index 00000000..a2d0f8bd --- /dev/null +++ b/src/libsystemd-network/dhcp-lease-internal.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include +#include + +#include "sd-dhcp-client.h" + +#include "dhcp-protocol.h" +#include "list.h" +#include "util.h" + +struct sd_dhcp_route { + struct in_addr dst_addr; + struct in_addr gw_addr; + unsigned char dst_prefixlen; + + uint8_t option; +}; + +struct sd_dhcp_raw_option { + LIST_FIELDS(struct sd_dhcp_raw_option, options); + + uint8_t tag; + uint8_t length; + void *data; +}; + +struct sd_dhcp_lease { + unsigned n_ref; + + /* each 0 if unset */ + uint32_t t1; + uint32_t t2; + uint32_t lifetime; + + /* each 0 if unset */ + be32_t address; + be32_t server_address; + be32_t next_server; + + bool have_subnet_mask; + be32_t subnet_mask; + + bool have_broadcast; + be32_t broadcast; + + struct in_addr *router; + size_t router_size; + + struct in_addr *dns; + size_t dns_size; + + struct in_addr *ntp; + size_t ntp_size; + + struct in_addr *sip; + size_t sip_size; + + struct sd_dhcp_route *static_route; + size_t static_route_size, static_route_allocated; + + uint16_t mtu; /* 0 if unset */ + + char *domainname; + char **search_domains; + char *hostname; + char *root_path; + + void *client_id; + size_t client_id_len; + + void *vendor_specific; + size_t vendor_specific_len; + + char *timezone; + + LIST_HEAD(struct sd_dhcp_raw_option, private_options); +}; + +int dhcp_lease_new(sd_dhcp_lease **ret); + +int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata); +int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains); +int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len); + +int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease); + +int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len); + +int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file); +int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file); diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c new file mode 100644 index 00000000..f48e7c34 --- /dev/null +++ b/src/libsystemd-network/dhcp-network.c @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dhcp-internal.h" +#include "fd-util.h" +#include "socket-util.h" +#include "unaligned.h" + +static int _bind_raw_socket(int ifindex, union sockaddr_union *link, + uint32_t xid, const uint8_t *mac_addr, + size_t mac_addr_len, + const uint8_t *bcast_addr, + const struct ether_addr *eth_mac, + uint16_t arp_type, uint8_t dhcp_hlen, + uint16_t port) { + struct sock_filter filter[] = { + BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */ + BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0), /* packet >= DHCPPacket ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.protocol)), /* A <- IP protocol */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 1, 0), /* IP protocol == UDP ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.frag_off)), /* A <- Flags */ + BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x20), /* A <- A & 0x20 (More Fragments bit) */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, ip.frag_off)), /* A <- Flags + Fragment offset */ + BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x1fff), /* A <- A & 0x1fff (Fragment offset) */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, udp.dest)), /* A <- UDP destination port */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, port, 1, 0), /* UDP destination port == DHCP client port ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.op)), /* A <- DHCP op */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTREPLY, 1, 0), /* op == BOOTREPLY ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.htype)), /* A <- DHCP header type */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arp_type, 1, 0), /* header type == arp_type ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.xid)), /* A <- client identifier */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0), /* client identifier == xid ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.hlen)), /* A <- MAC address length */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, dhcp_hlen, 1, 0), /* address length == dhcp_hlen ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + + /* We only support MAC address length to be either 0 or 6 (ETH_ALEN). Optionally + * compare chaddr for ETH_ALEN bytes. */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_ALEN, 0, 12), /* A (the MAC address length) == ETH_ALEN ? */ + BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])), /* A <- 4 bytes of client's MAC */ + BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)), /* A <- 4 bytes of MAC from dhcp.chaddr */ + BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])), /* A <- remainder of client's MAC */ + BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4), /* A <- remainder of MAC from dhcp.chaddr */ + BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + + BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.magic)), /* A <- DHCP magic cookie */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0), /* cookie == DHCP magic cookie ? */ + BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ + BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ + }; + struct sock_fprog fprog = { + .len = ELEMENTSOF(filter), + .filter = filter + }; + _cleanup_close_ int s = -1; + int r; + + assert(ifindex > 0); + assert(link); + + s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (s < 0) + return -errno; + + r = setsockopt_int(s, SOL_PACKET, PACKET_AUXDATA, true); + if (r < 0) + return r; + + r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); + if (r < 0) + return -errno; + + link->ll = (struct sockaddr_ll) { + .sll_family = AF_PACKET, + .sll_protocol = htobe16(ETH_P_IP), + .sll_ifindex = ifindex, + .sll_hatype = htobe16(arp_type), + .sll_halen = mac_addr_len, + }; + memcpy(link->ll.sll_addr, bcast_addr, mac_addr_len); + + r = bind(s, &link->sa, SOCKADDR_LL_LEN(link->ll)); + if (r < 0) + return -errno; + + return TAKE_FD(s); +} + +int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, + uint32_t xid, const uint8_t *mac_addr, + size_t mac_addr_len, uint16_t arp_type, + uint16_t port) { + static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + /* Default broadcast address for IPoIB */ + static const uint8_t ib_bcast[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x40, 0x1b, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff + }; + struct ether_addr eth_mac = { { 0, 0, 0, 0, 0, 0 } }; + const uint8_t *bcast_addr = NULL; + uint8_t dhcp_hlen = 0; + + if (arp_type == ARPHRD_ETHER) { + assert_return(mac_addr_len == ETH_ALEN, -EINVAL); + memcpy(ð_mac, mac_addr, ETH_ALEN); + bcast_addr = eth_bcast; + dhcp_hlen = ETH_ALEN; + } else if (arp_type == ARPHRD_INFINIBAND) { + assert_return(mac_addr_len == INFINIBAND_ALEN, -EINVAL); + bcast_addr = ib_bcast; + } else + return -EINVAL; + + return _bind_raw_socket(ifindex, link, xid, mac_addr, mac_addr_len, + bcast_addr, ð_mac, arp_type, dhcp_hlen, port); +} + +int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) { + union sockaddr_union src = { + .in.sin_family = AF_INET, + .in.sin_port = htobe16(port), + .in.sin_addr.s_addr = address, + }; + _cleanup_close_ int s = -1; + int r; + + s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (s < 0) + return -errno; + + if (ip_service_type >= 0) + r = setsockopt_int(s, IPPROTO_IP, IP_TOS, ip_service_type); + else + r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6); + + if (r < 0) + return r; + + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return r; + + if (ifindex > 0) { + r = socket_bind_to_ifindex(s, ifindex); + if (r < 0) + return r; + } + + if (address == INADDR_ANY) { + r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true); + if (r < 0) + return r; + + r = setsockopt_int(s, SOL_SOCKET, SO_BROADCAST, true); + if (r < 0) + return r; + + } else { + r = setsockopt_int(s, IPPROTO_IP, IP_FREEBIND, true); + if (r < 0) + return r; + } + + r = bind(s, &src.sa, sizeof(src.in)); + if (r < 0) + return -errno; + + return TAKE_FD(s); +} + +int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, + const void *packet, size_t len) { + int r; + + assert(link); + assert(packet); + assert(len); + + r = sendto(s, packet, len, 0, &link->sa, SOCKADDR_LL_LEN(link->ll)); + if (r < 0) + return -errno; + + return 0; +} + +int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, + const void *packet, size_t len) { + union sockaddr_union dest = { + .in.sin_family = AF_INET, + .in.sin_port = htobe16(port), + .in.sin_addr.s_addr = address, + }; + int r; + + assert(s >= 0); + assert(packet); + assert(len); + + r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in)); + if (r < 0) + return -errno; + + return 0; +} diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c new file mode 100644 index 00000000..e03c1a89 --- /dev/null +++ b/src/libsystemd-network/dhcp-option.c @@ -0,0 +1,357 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include + +#include "alloc-util.h" +#include "dhcp-internal.h" +#include "dhcp-server-internal.h" +#include "memory-util.h" +#include "strv.h" +#include "utf8.h" + +static int option_append(uint8_t options[], size_t size, size_t *offset, + uint8_t code, size_t optlen, const void *optval) { + assert(options); + assert(offset); + + if (code != SD_DHCP_OPTION_END) + /* always make sure there is space for an END option */ + size--; + + switch (code) { + + case SD_DHCP_OPTION_PAD: + case SD_DHCP_OPTION_END: + if (*offset + 1 > size) + return -ENOBUFS; + + options[*offset] = code; + *offset += 1; + break; + + case SD_DHCP_OPTION_USER_CLASS: { + size_t total = 0; + char **s; + + STRV_FOREACH(s, (char **) optval) { + size_t len = strlen(*s); + + if (len > 255) + return -ENAMETOOLONG; + + total += 1 + len; + } + + if (*offset + 2 + total > size) + return -ENOBUFS; + + options[*offset] = code; + options[*offset + 1] = total; + *offset += 2; + + STRV_FOREACH(s, (char **) optval) { + size_t len = strlen(*s); + + options[*offset] = len; + + memcpy(&options[*offset + 1], *s, len); + *offset += 1 + len; + } + + break; + } + case SD_DHCP_OPTION_SIP_SERVER: + if (*offset + 3 + optlen > size) + return -ENOBUFS; + + options[*offset] = code; + options[*offset + 1] = optlen + 1; + options[*offset + 2] = 1; + + memcpy_safe(&options[*offset + 3], optval, optlen); + *offset += 3 + optlen; + + break; + case SD_DHCP_OPTION_VENDOR_SPECIFIC: { + OrderedHashmap *s = (OrderedHashmap *) optval; + struct sd_dhcp_option *p; + size_t l = 0; + Iterator i; + + ORDERED_HASHMAP_FOREACH(p, s, i) + l += p->length + 2; + + if (*offset + l + 2 > size) + return -ENOBUFS; + + options[*offset] = code; + options[*offset + 1] = l; + + *offset += 2; + + ORDERED_HASHMAP_FOREACH(p, s, i) { + options[*offset] = p->option; + options[*offset + 1] = p->length; + memcpy(&options[*offset + 2], p->data, p->length); + *offset += 2 + p->length; + } + + break; + } + default: + if (*offset + 2 + optlen > size) + return -ENOBUFS; + + options[*offset] = code; + options[*offset + 1] = optlen; + + memcpy_safe(&options[*offset + 2], optval, optlen); + *offset += 2 + optlen; + + break; + } + + return 0; +} + +int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, + uint8_t overload, + uint8_t code, size_t optlen, const void *optval) { + const bool use_file = overload & DHCP_OVERLOAD_FILE; + const bool use_sname = overload & DHCP_OVERLOAD_SNAME; + int r; + + assert(message); + assert(offset); + + /* If *offset is in range [0, size), we are writing to ->options, + * if *offset is in range [size, size + sizeof(message->file)) and use_file, we are writing to ->file, + * if *offset is in range [size + use_file*sizeof(message->file), size + use_file*sizeof(message->file) + sizeof(message->sname)) + * and use_sname, we are writing to ->sname. + */ + + if (*offset < size) { + /* still space in the options array */ + r = option_append(message->options, size, offset, code, optlen, optval); + if (r >= 0) + return 0; + else if (r == -ENOBUFS && (use_file || use_sname)) { + /* did not fit, but we have more buffers to try + close the options array and move the offset to its end */ + r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; + + *offset = size; + } else + return r; + } + + if (use_file) { + size_t file_offset = *offset - size; + + if (file_offset < sizeof(message->file)) { + /* still space in the 'file' array */ + r = option_append(message->file, sizeof(message->file), &file_offset, code, optlen, optval); + if (r >= 0) { + *offset = size + file_offset; + return 0; + } else if (r == -ENOBUFS && use_sname) { + /* did not fit, but we have more buffers to try + close the file array and move the offset to its end */ + r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; + + *offset = size + sizeof(message->file); + } else + return r; + } + } + + if (use_sname) { + size_t sname_offset = *offset - size - use_file*sizeof(message->file); + + if (sname_offset < sizeof(message->sname)) { + /* still space in the 'sname' array */ + r = option_append(message->sname, sizeof(message->sname), &sname_offset, code, optlen, optval); + if (r >= 0) { + *offset = size + use_file*sizeof(message->file) + sname_offset; + return 0; + } else + /* no space, or other error, give up */ + return r; + } + } + + return -ENOBUFS; +} + +static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload, + uint8_t *message_type, char **error_message, dhcp_option_callback_t cb, + void *userdata) { + uint8_t code, len; + const uint8_t *option; + size_t offset = 0; + + while (offset < buflen) { + code = options[offset ++]; + + switch (code) { + case SD_DHCP_OPTION_PAD: + continue; + + case SD_DHCP_OPTION_END: + return 0; + } + + if (buflen < offset + 1) + return -ENOBUFS; + + len = options[offset ++]; + + if (buflen < offset + len) + return -EINVAL; + + option = &options[offset]; + + switch (code) { + case SD_DHCP_OPTION_MESSAGE_TYPE: + if (len != 1) + return -EINVAL; + + if (message_type) + *message_type = *option; + + break; + + case SD_DHCP_OPTION_ERROR_MESSAGE: + if (len == 0) + return -EINVAL; + + if (error_message) { + _cleanup_free_ char *string = NULL; + + /* Accept a trailing NUL byte */ + if (memchr(option, 0, len - 1)) + return -EINVAL; + + string = memdup_suffix0((const char *) option, len); + if (!string) + return -ENOMEM; + + if (!ascii_is_valid(string)) + return -EINVAL; + + free_and_replace(*error_message, string); + } + + break; + case SD_DHCP_OPTION_OVERLOAD: + if (len != 1) + return -EINVAL; + + if (overload) + *overload = *option; + + break; + + default: + if (cb) + cb(code, len, option, userdata); + + break; + } + + offset += len; + } + + if (offset < buflen) + return -EINVAL; + + return 0; +} + +int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **_error_message) { + _cleanup_free_ char *error_message = NULL; + uint8_t overload = 0; + uint8_t message_type = 0; + int r; + + if (!message) + return -EINVAL; + + if (len < sizeof(DHCPMessage)) + return -EINVAL; + + len -= sizeof(DHCPMessage); + + r = parse_options(message->options, len, &overload, &message_type, &error_message, cb, userdata); + if (r < 0) + return r; + + if (overload & DHCP_OVERLOAD_FILE) { + r = parse_options(message->file, sizeof(message->file), NULL, &message_type, &error_message, cb, userdata); + if (r < 0) + return r; + } + + if (overload & DHCP_OVERLOAD_SNAME) { + r = parse_options(message->sname, sizeof(message->sname), NULL, &message_type, &error_message, cb, userdata); + if (r < 0) + return r; + } + + if (message_type == 0) + return -ENOMSG; + + if (_error_message && IN_SET(message_type, DHCP_NAK, DHCP_DECLINE)) + *_error_message = TAKE_PTR(error_message); + + return message_type; +} + +static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) { + if (!i) + return NULL; + + free(i->data); + return mfree(i); +} + +int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret) { + assert_return(ret, -EINVAL); + assert_return(length == 0 || data, -EINVAL); + + _cleanup_free_ void *q = memdup(data, length); + if (!q) + return -ENOMEM; + + sd_dhcp_option *p = new(sd_dhcp_option, 1); + if (!p) + return -ENOMEM; + + *p = (sd_dhcp_option) { + .n_ref = 1, + .option = option, + .length = length, + .data = TAKE_PTR(q), + }; + + *ret = TAKE_PTR(p); + return 0; +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option, sd_dhcp_option, dhcp_option_free); +DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + dhcp_option_hash_ops, + void, + trivial_hash_func, + trivial_compare_func, + sd_dhcp_option, + sd_dhcp_option_unref); diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c new file mode 100644 index 00000000..fe7d5170 --- /dev/null +++ b/src/libsystemd-network/dhcp-packet.c @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include + +#include "dhcp-internal.h" +#include "dhcp-protocol.h" + +#define DHCP_CLIENT_MIN_OPTIONS_SIZE 312 + +int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, + uint8_t type, uint16_t arp_type, size_t optlen, + size_t *optoffset) { + size_t offset = 0; + int r; + + assert(IN_SET(op, BOOTREQUEST, BOOTREPLY)); + assert(IN_SET(arp_type, ARPHRD_ETHER, ARPHRD_INFINIBAND)); + + message->op = op; + message->htype = arp_type; + message->hlen = (arp_type == ARPHRD_ETHER) ? ETHER_ADDR_LEN : 0; + message->xid = htobe32(xid); + message->magic = htobe32(DHCP_MAGIC_COOKIE); + + r = dhcp_option_append(message, optlen, &offset, 0, + SD_DHCP_OPTION_MESSAGE_TYPE, 1, &type); + if (r < 0) + return r; + + *optoffset = offset; + + return 0; +} + +uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len) { + uint64_t *buf_64 = (uint64_t*)buf; + uint64_t *end_64 = buf_64 + (len / sizeof(uint64_t)); + uint64_t sum = 0; + + /* See RFC1071 */ + + while (buf_64 < end_64) { + sum += *buf_64; + if (sum < *buf_64) + /* wrap around in one's complement */ + sum++; + + buf_64++; + } + + if (len % sizeof(uint64_t)) { + /* If the buffer is not aligned to 64-bit, we need + to zero-pad the last few bytes and add them in */ + uint64_t buf_tail = 0; + + memcpy(&buf_tail, buf_64, len % sizeof(uint64_t)); + + sum += buf_tail; + if (sum < buf_tail) + /* wrap around */ + sum++; + } + + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + + return ~sum; +} + +void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr, + uint16_t source_port, be32_t destination_addr, + uint16_t destination_port, uint16_t len, int ip_service_type) { + packet->ip.version = IPVERSION; + packet->ip.ihl = DHCP_IP_SIZE / 4; + packet->ip.tot_len = htobe16(len); + + if (ip_service_type >= 0) + packet->ip.tos = ip_service_type; + else + packet->ip.tos = IPTOS_CLASS_CS6; + + packet->ip.protocol = IPPROTO_UDP; + packet->ip.saddr = source_addr; + packet->ip.daddr = destination_addr; + + packet->udp.source = htobe16(source_port); + packet->udp.dest = htobe16(destination_port); + + packet->udp.len = htobe16(len - DHCP_IP_SIZE); + + packet->ip.check = packet->udp.len; + packet->udp.check = dhcp_packet_checksum((uint8_t*)&packet->ip.ttl, len - 8); + + packet->ip.ttl = IPDEFTTL; + packet->ip.check = 0; + packet->ip.check = dhcp_packet_checksum((uint8_t*)&packet->ip, DHCP_IP_SIZE); +} + +int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port) { + size_t hdrlen; + + assert(packet); + + /* IP */ + + if (packet->ip.version != IPVERSION) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: not IPv4"); + + if (packet->ip.ihl < 5) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: IPv4 IHL (%u words) invalid", + packet->ip.ihl); + + hdrlen = packet->ip.ihl * 4; + if (hdrlen < 20) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: IPv4 IHL (%zu bytes) " + "smaller than minimum (20 bytes)", + hdrlen); + + if (len < hdrlen) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: packet (%zu bytes) " + "smaller than expected (%zu) by IP header", + len, hdrlen); + + /* UDP */ + + if (packet->ip.protocol != IPPROTO_UDP) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: not UDP"); + + if (len < hdrlen + be16toh(packet->udp.len)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: packet (%zu bytes) " + "smaller than expected (%zu) by UDP header", + len, hdrlen + be16toh(packet->udp.len)); + + if (be16toh(packet->udp.dest) != port) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: to port %u, which " + "is not the DHCP client port (%u)", + be16toh(packet->udp.dest), port); + + /* checksums - computing these is relatively expensive, so only do it + if all the other checks have passed + */ + + if (dhcp_packet_checksum((uint8_t*)&packet->ip, hdrlen)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: invalid IP checksum"); + + if (checksum && packet->udp.check) { + packet->ip.check = packet->udp.len; + packet->ip.ttl = 0; + + if (dhcp_packet_checksum((uint8_t*)&packet->ip.ttl, + be16toh(packet->udp.len) + 12)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "ignoring packet: invalid UDP checksum"); + } + + return 0; +} diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h new file mode 100644 index 00000000..f0366324 --- /dev/null +++ b/src/libsystemd-network/dhcp-protocol.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include + +#include "macro.h" +#include "sparse-endian.h" + +struct DHCPMessage { + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + be32_t xid; + be16_t secs; + be16_t flags; + be32_t ciaddr; + be32_t yiaddr; + be32_t siaddr; + be32_t giaddr; + uint8_t chaddr[16]; + uint8_t sname[64]; + uint8_t file[128]; + be32_t magic; + uint8_t options[0]; +} _packed_; + +typedef struct DHCPMessage DHCPMessage; + +struct DHCPPacket { + struct iphdr ip; + struct udphdr udp; + DHCPMessage dhcp; +} _packed_; + +typedef struct DHCPPacket DHCPPacket; + +#define DHCP_IP_SIZE (int32_t)(sizeof(struct iphdr)) +#define DHCP_IP_UDP_SIZE (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE) +#define DHCP_MESSAGE_SIZE (int32_t)(sizeof(DHCPMessage)) +#define DHCP_DEFAULT_MIN_SIZE 576 /* the minimum internet hosts must be able to receive */ +#define DHCP_MIN_OPTIONS_SIZE (DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE) +#define DHCP_MAGIC_COOKIE (uint32_t)(0x63825363) + +enum { + DHCP_PORT_SERVER = 67, + DHCP_PORT_CLIENT = 68, +}; + +enum DHCPState { + DHCP_STATE_INIT = 0, + DHCP_STATE_SELECTING = 1, + DHCP_STATE_INIT_REBOOT = 2, + DHCP_STATE_REBOOTING = 3, + DHCP_STATE_REQUESTING = 4, + DHCP_STATE_BOUND = 5, + DHCP_STATE_RENEWING = 6, + DHCP_STATE_REBINDING = 7, + DHCP_STATE_STOPPED = 8, +}; + +typedef enum DHCPState DHCPState; + +enum { + BOOTREQUEST = 1, + BOOTREPLY = 2, +}; + +enum { + DHCP_DISCOVER = 1, + DHCP_OFFER = 2, + DHCP_REQUEST = 3, + DHCP_DECLINE = 4, + DHCP_ACK = 5, + DHCP_NAK = 6, + DHCP_RELEASE = 7, + DHCP_INFORM = 8, + DHCP_FORCERENEW = 9, +}; + +enum { + DHCP_OVERLOAD_FILE = 1, + DHCP_OVERLOAD_SNAME = 2, +}; + +#define DHCP_MAX_FQDN_LENGTH 255 + +enum { + DHCP_FQDN_FLAG_S = (1 << 0), + DHCP_FQDN_FLAG_O = (1 << 1), + DHCP_FQDN_FLAG_E = (1 << 2), + DHCP_FQDN_FLAG_N = (1 << 3), +}; diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h new file mode 100644 index 00000000..42c3ceb8 --- /dev/null +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include "sd-dhcp-server.h" +#include "sd-event.h" + +#include "dhcp-internal.h" +#include "hashmap.h" +#include "log.h" +#include "time-util.h" + +typedef enum DHCPRawOption { + DHCP_RAW_OPTION_DATA_UINT8, + DHCP_RAW_OPTION_DATA_UINT16, + DHCP_RAW_OPTION_DATA_UINT32, + DHCP_RAW_OPTION_DATA_STRING, + DHCP_RAW_OPTION_DATA_IPV4ADDRESS, + _DHCP_RAW_OPTION_DATA_MAX, + _DHCP_RAW_OPTION_DATA_INVALID, +} DHCPRawOption; + +typedef struct DHCPClientId { + size_t length; + void *data; +} DHCPClientId; + +typedef struct DHCPLease { + DHCPClientId client_id; + + be32_t address; + be32_t gateway; + uint8_t chaddr[16]; + usec_t expiration; +} DHCPLease; + +struct sd_dhcp_server { + unsigned n_ref; + + sd_event *event; + int event_priority; + sd_event_source *receive_message; + int fd; + int fd_raw; + + int ifindex; + be32_t address; + be32_t netmask; + be32_t subnet; + uint32_t pool_offset; + uint32_t pool_size; + + char *timezone; + + struct in_addr *ntp, *dns, *sip; + unsigned n_ntp, n_dns, n_sip; + + OrderedHashmap *raw_option; + + bool emit_router; + + Hashmap *leases_by_client_id; + DHCPLease **bound_leases; + DHCPLease invalid_lease; + + uint32_t max_lease_time, default_lease_time; +}; + +typedef struct DHCPRequest { + /* received message */ + DHCPMessage *message; + + /* options */ + DHCPClientId client_id; + size_t max_optlen; + be32_t server_id; + be32_t requested_ip; + uint32_t lifetime; +} DHCPRequest; + +#define log_dhcp_server(client, fmt, ...) log_internal(LOG_DEBUG, 0, PROJECT_FILE, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__) +#define log_dhcp_server_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCP SERVER: " fmt, ##__VA_ARGS__) + +int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, + size_t length); +int dhcp_server_send_packet(sd_dhcp_server *server, + DHCPRequest *req, DHCPPacket *packet, + int type, size_t optoffset); + +void client_id_hash_func(const DHCPClientId *p, struct siphash *state); +int client_id_compare_func(const DHCPClientId *a, const DHCPClientId *b); diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h new file mode 100644 index 00000000..517e357d --- /dev/null +++ b/src/libsystemd-network/dhcp6-internal.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2014-2015 Intel Corporation. All rights reserved. +***/ + +#include +#include + +#include "sd-event.h" + +#include "list.h" +#include "macro.h" +#include "sparse-endian.h" + +/* Common option header */ +typedef struct DHCP6Option { + be16_t code; + be16_t len; + uint8_t data[]; +} _packed_ DHCP6Option; + +/* Address option */ +struct iaaddr { + struct in6_addr address; + be32_t lifetime_preferred; + be32_t lifetime_valid; +} _packed_; + +/* Prefix Delegation Prefix option */ +struct iapdprefix { + be32_t lifetime_preferred; + be32_t lifetime_valid; + uint8_t prefixlen; + struct in6_addr address; +} _packed_; + +typedef struct DHCP6Address DHCP6Address; + +struct DHCP6Address { + LIST_FIELDS(DHCP6Address, addresses); + + union { + struct iaaddr iaaddr; + struct iapdprefix iapdprefix; + }; +}; + +/* Non-temporary Address option */ +struct ia_na { + be32_t id; + be32_t lifetime_t1; + be32_t lifetime_t2; +} _packed_; + +/* Prefix Delegation option */ +struct ia_pd { + be32_t id; + be32_t lifetime_t1; + be32_t lifetime_t2; +} _packed_; + +/* Temporary Address option */ +struct ia_ta { + be32_t id; +} _packed_; + +struct DHCP6IA { + uint16_t type; + union { + struct ia_na ia_na; + struct ia_pd ia_pd; + struct ia_ta ia_ta; + }; + + LIST_HEAD(DHCP6Address, addresses); +}; + +typedef struct DHCP6IA DHCP6IA; + +#define log_dhcp6_client_errno(p, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__) +#define log_dhcp6_client(p, fmt, ...) log_dhcp6_client_errno(p, 0, fmt, ##__VA_ARGS__) + +int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, + size_t optlen, const void *optval); +int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia); +int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix); +int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn); +int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, + size_t *optlen, uint8_t **optvalue); +int dhcp6_option_parse_status(DHCP6Option *option, size_t len); +int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia); +int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, + struct in6_addr **addrs, size_t count, + size_t *allocated); +int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, + char ***str_arr); + +int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address); +int dhcp6_network_send_udp_socket(int s, struct in6_addr *address, + const void *packet, size_t len); + +const char *dhcp6_message_type_to_string(int s) _const_; +int dhcp6_message_type_from_string(const char *s) _pure_; +const char *dhcp6_message_status_to_string(int s) _const_; +int dhcp6_message_status_from_string(const char *s) _pure_; diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h new file mode 100644 index 00000000..e004f48b --- /dev/null +++ b/src/libsystemd-network/dhcp6-lease-internal.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2014-2015 Intel Corporation. All rights reserved. +***/ + +#include + +#include "sd-dhcp6-lease.h" + +#include "dhcp6-internal.h" + +struct sd_dhcp6_lease { + unsigned n_ref; + + uint8_t *serverid; + size_t serverid_len; + uint8_t preference; + bool rapid_commit; + + DHCP6IA ia; + DHCP6IA pd; + + DHCP6Address *addr_iter; + DHCP6Address *prefix_iter; + + struct in6_addr *dns; + size_t dns_count; + size_t dns_allocated; + char **domains; + size_t domains_count; + struct in6_addr *ntp; + size_t ntp_count; + size_t ntp_allocated; + char **ntp_fqdn; + size_t ntp_fqdn_count; +}; + +int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire); +DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia); + +int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, + size_t len); +int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len); +int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference); +int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference); +int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease); +int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit); + +int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid); +int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid); + +int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); +int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval, + size_t optlen); +int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); +int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, + size_t optlen) ; + +int dhcp6_lease_new(sd_dhcp6_lease **ret); diff --git a/src/libsystemd-network/dhcp6-network.c b/src/libsystemd-network/dhcp6-network.c new file mode 100644 index 00000000..f82afe6a --- /dev/null +++ b/src/libsystemd-network/dhcp6-network.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dhcp6-internal.h" +#include "dhcp6-protocol.h" +#include "fd-util.h" +#include "socket-util.h" + +int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) { + union sockaddr_union src = { + .in6.sin6_family = AF_INET6, + .in6.sin6_port = htobe16(DHCP6_PORT_CLIENT), + .in6.sin6_scope_id = index, + }; + _cleanup_close_ int s = -1; + int r; + + assert(index > 0); + assert(local_address); + + src.in6.sin6_addr = *local_address; + + s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_UDP); + if (s < 0) + return -errno; + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true); + if (r < 0) + return r; + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, false); + if (r < 0) + return r; + + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return r; + + r = bind(s, &src.sa, sizeof(src.in6)); + if (r < 0) + return -errno; + + return TAKE_FD(s); +} + +int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, + const void *packet, size_t len) { + union sockaddr_union dest = { + .in6.sin6_family = AF_INET6, + .in6.sin6_port = htobe16(DHCP6_PORT_SERVER), + }; + int r; + + assert(server_address); + + memcpy(&dest.in6.sin6_addr, server_address, sizeof(dest.in6.sin6_addr)); + + r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in6)); + if (r < 0) + return -errno; + + return 0; +} diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c new file mode 100644 index 00000000..9f5352a6 --- /dev/null +++ b/src/libsystemd-network/dhcp6-option.c @@ -0,0 +1,599 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014-2015 Intel Corporation. All rights reserved. +***/ + +#include +#include + +#include "sd-dhcp6-client.h" + +#include "alloc-util.h" +#include "dhcp6-internal.h" +#include "dhcp6-lease-internal.h" +#include "dhcp6-protocol.h" +#include "dns-domain.h" +#include "memory-util.h" +#include "sparse-endian.h" +#include "strv.h" +#include "unaligned.h" + +typedef struct DHCP6StatusOption { + struct DHCP6Option option; + be16_t status; + char msg[]; +} _packed_ DHCP6StatusOption; + +typedef struct DHCP6AddressOption { + struct DHCP6Option option; + struct iaaddr iaaddr; + uint8_t options[]; +} _packed_ DHCP6AddressOption; + +typedef struct DHCP6PDPrefixOption { + struct DHCP6Option option; + struct iapdprefix iapdprefix; + uint8_t options[]; +} _packed_ DHCP6PDPrefixOption; + +#define DHCP6_OPTION_IA_NA_LEN (sizeof(struct ia_na)) +#define DHCP6_OPTION_IA_PD_LEN (sizeof(struct ia_pd)) +#define DHCP6_OPTION_IA_TA_LEN (sizeof(struct ia_ta)) + +static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode, + size_t optlen) { + DHCP6Option *option = (DHCP6Option*) *buf; + + assert_return(buf, -EINVAL); + assert_return(*buf, -EINVAL); + assert_return(buflen, -EINVAL); + + if (optlen > 0xffff || *buflen < optlen + offsetof(DHCP6Option, data)) + return -ENOBUFS; + + option->code = htobe16(optcode); + option->len = htobe16(optlen); + + *buf += offsetof(DHCP6Option, data); + *buflen -= offsetof(DHCP6Option, data); + + return 0; +} + +int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, + size_t optlen, const void *optval) { + int r; + + assert_return(optval || optlen == 0, -EINVAL); + + r = option_append_hdr(buf, buflen, code, optlen); + if (r < 0) + return r; + + memcpy_safe(*buf, optval, optlen); + + *buf += optlen; + *buflen -= optlen; + + return 0; +} + +int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) { + uint16_t len; + uint8_t *ia_hdr; + size_t iaid_offset, ia_buflen, ia_addrlen = 0; + DHCP6Address *addr; + int r; + + assert_return(buf, -EINVAL); + assert_return(*buf, -EINVAL); + assert_return(buflen, -EINVAL); + assert_return(ia, -EINVAL); + + switch (ia->type) { + case SD_DHCP6_OPTION_IA_NA: + len = DHCP6_OPTION_IA_NA_LEN; + iaid_offset = offsetof(DHCP6IA, ia_na); + break; + + case SD_DHCP6_OPTION_IA_TA: + len = DHCP6_OPTION_IA_TA_LEN; + iaid_offset = offsetof(DHCP6IA, ia_ta); + break; + + default: + return -EINVAL; + } + + if (*buflen < offsetof(DHCP6Option, data) + len) + return -ENOBUFS; + + ia_hdr = *buf; + ia_buflen = *buflen; + + *buf += offsetof(DHCP6Option, data); + *buflen -= offsetof(DHCP6Option, data); + + memcpy(*buf, (char*) ia + iaid_offset, len); + + *buf += len; + *buflen -= len; + + LIST_FOREACH(addresses, addr, ia->addresses) { + r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR, + sizeof(addr->iaaddr)); + if (r < 0) + return r; + + memcpy(*buf, &addr->iaaddr, sizeof(addr->iaaddr)); + + *buf += sizeof(addr->iaaddr); + *buflen -= sizeof(addr->iaaddr); + + ia_addrlen += offsetof(DHCP6Option, data) + sizeof(addr->iaaddr); + } + + r = option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen); + if (r < 0) + return r; + + return 0; +} + +int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) { + uint8_t buffer[1 + DNS_WIRE_FORMAT_HOSTNAME_MAX]; + int r; + + assert_return(buf && *buf && buflen && fqdn, -EINVAL); + + buffer[0] = DHCP6_FQDN_FLAG_S; /* Request server to perform AAAA RR DNS updates */ + + /* Store domain name after flags field */ + r = dns_name_to_wire_format(fqdn, buffer + 1, sizeof(buffer) - 1, false); + if (r <= 0) + return r; + + /* + * According to RFC 4704, chapter 4.2 only add terminating zero-length + * label in case a FQDN is provided. Since dns_name_to_wire_format + * always adds terminating zero-length label remove if only a hostname + * is provided. + */ + if (dns_name_is_single_label(fqdn)) + r--; + + r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_FQDN, 1 + r, buffer); + + return r; +} + +int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) { + DHCP6Option *option = (DHCP6Option *)buf; + size_t i = sizeof(*option) + sizeof(pd->ia_pd); + DHCP6PDPrefixOption *prefix_opt; + DHCP6Address *prefix; + + assert_return(buf, -EINVAL); + assert_return(pd, -EINVAL); + assert_return(pd->type == SD_DHCP6_OPTION_IA_PD, -EINVAL); + + if (len < i) + return -ENOBUFS; + + option->code = htobe16(SD_DHCP6_OPTION_IA_PD); + + memcpy(&option->data, &pd->ia_pd, sizeof(pd->ia_pd)); + LIST_FOREACH(addresses, prefix, pd->addresses) { + if (len < i + sizeof(*prefix_opt)) + return -ENOBUFS; + + prefix_opt = (DHCP6PDPrefixOption *)&buf[i]; + prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX); + prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix)); + + memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix, sizeof(struct iapdprefix)); + i += sizeof(*prefix_opt); + } + + if (hint_pd_prefix && hint_pd_prefix->iapdprefix.prefixlen > 0) { + if (len < i + sizeof(*prefix_opt)) + return -ENOBUFS; + + prefix_opt = (DHCP6PDPrefixOption *)&buf[i]; + prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX); + prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix)); + + memcpy(&prefix_opt->iapdprefix, &hint_pd_prefix->iapdprefix, sizeof(struct iapdprefix)); + i += sizeof(*prefix_opt); + } + + option->len = htobe16(i - sizeof(*option)); + + return i; +} + +static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen) { + DHCP6Option *option = (DHCP6Option*) *buf; + uint16_t len; + + assert_return(buf, -EINVAL); + assert_return(optcode, -EINVAL); + assert_return(optlen, -EINVAL); + + if (*buflen < offsetof(DHCP6Option, data)) + return -ENOMSG; + + len = be16toh(option->len); + + if (len > *buflen) + return -ENOMSG; + + *optcode = be16toh(option->code); + *optlen = len; + + *buf += 4; + *buflen -= 4; + + return 0; +} + +int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, + size_t *optlen, uint8_t **optvalue) { + int r; + + assert_return(buf && buflen && optcode && optlen && optvalue, -EINVAL); + + r = option_parse_hdr(buf, buflen, optcode, optlen); + if (r < 0) + return r; + + if (*optlen > *buflen) + return -ENOBUFS; + + *optvalue = *buf; + *buflen -= *optlen; + *buf += *optlen; + + return 0; +} + +int dhcp6_option_parse_status(DHCP6Option *option, size_t len) { + DHCP6StatusOption *statusopt = (DHCP6StatusOption *)option; + + if (len < sizeof(DHCP6StatusOption) || + be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(DHCP6StatusOption)) + return -ENOBUFS; + + return be16toh(statusopt->status); +} + +static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia, + uint32_t *lifetime_valid) { + DHCP6AddressOption *addr_option = (DHCP6AddressOption *)option; + DHCP6Address *addr; + uint32_t lt_valid, lt_pref; + int r; + + if (be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(*addr_option)) + return -ENOBUFS; + + lt_valid = be32toh(addr_option->iaaddr.lifetime_valid); + lt_pref = be32toh(addr_option->iaaddr.lifetime_preferred); + + if (lt_valid == 0 || lt_pref > lt_valid) { + log_dhcp6_client(client, "Valid lifetime of an IA address is zero or preferred lifetime %d > valid lifetime %d", + lt_pref, lt_valid); + + return 0; + } + + if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*addr_option)) { + r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*addr_option)); + if (r != 0) + return r < 0 ? r: 0; + } + + addr = new0(DHCP6Address, 1); + if (!addr) + return -ENOMEM; + + LIST_INIT(addresses, addr); + memcpy(&addr->iaaddr, option->data, sizeof(addr->iaaddr)); + + LIST_PREPEND(addresses, ia->addresses, addr); + + *lifetime_valid = be32toh(addr->iaaddr.lifetime_valid); + + return 0; +} + +static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia, + uint32_t *lifetime_valid) { + DHCP6PDPrefixOption *pdprefix_option = (DHCP6PDPrefixOption *)option; + DHCP6Address *prefix; + uint32_t lt_valid, lt_pref; + int r; + + if (be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(*pdprefix_option)) + return -ENOBUFS; + + lt_valid = be32toh(pdprefix_option->iapdprefix.lifetime_valid); + lt_pref = be32toh(pdprefix_option->iapdprefix.lifetime_preferred); + + if (lt_valid == 0 || lt_pref > lt_valid) { + log_dhcp6_client(client, "Valid lifetieme of a PD prefix is zero or preferred lifetime %d > valid lifetime %d", + lt_pref, lt_valid); + + return 0; + } + + if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*pdprefix_option)) { + r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*pdprefix_option)); + if (r != 0) + return r < 0 ? r: 0; + } + + prefix = new0(DHCP6Address, 1); + if (!prefix) + return -ENOMEM; + + LIST_INIT(addresses, prefix); + memcpy(&prefix->iapdprefix, option->data, sizeof(prefix->iapdprefix)); + + LIST_PREPEND(addresses, ia->addresses, prefix); + + *lifetime_valid = be32toh(prefix->iapdprefix.lifetime_valid); + + return 0; +} + +int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) { + uint16_t iatype, optlen; + size_t i, len; + int r = 0, status; + uint16_t opt; + size_t iaaddr_offset; + uint32_t lt_t1, lt_t2, lt_valid = 0, lt_min = UINT32_MAX; + + assert_return(ia, -EINVAL); + assert_return(!ia->addresses, -EINVAL); + + iatype = be16toh(iaoption->code); + len = be16toh(iaoption->len); + + switch (iatype) { + case SD_DHCP6_OPTION_IA_NA: + + if (len < DHCP6_OPTION_IA_NA_LEN) + return -ENOBUFS; + + iaaddr_offset = DHCP6_OPTION_IA_NA_LEN; + memcpy(&ia->ia_na, iaoption->data, sizeof(ia->ia_na)); + + lt_t1 = be32toh(ia->ia_na.lifetime_t1); + lt_t2 = be32toh(ia->ia_na.lifetime_t2); + + if (lt_t1 && lt_t2 && lt_t1 > lt_t2) { + log_dhcp6_client(client, "IA NA T1 %ds > T2 %ds", + lt_t1, lt_t2); + return -EINVAL; + } + + break; + + case SD_DHCP6_OPTION_IA_PD: + + if (len < sizeof(ia->ia_pd)) + return -ENOBUFS; + + iaaddr_offset = sizeof(ia->ia_pd); + memcpy(&ia->ia_pd, iaoption->data, sizeof(ia->ia_pd)); + + lt_t1 = be32toh(ia->ia_pd.lifetime_t1); + lt_t2 = be32toh(ia->ia_pd.lifetime_t2); + + if (lt_t1 && lt_t2 && lt_t1 > lt_t2) { + log_dhcp6_client(client, "IA PD T1 %ds > T2 %ds", + lt_t1, lt_t2); + return -EINVAL; + } + + break; + + case SD_DHCP6_OPTION_IA_TA: + if (len < DHCP6_OPTION_IA_TA_LEN) + return -ENOBUFS; + + iaaddr_offset = DHCP6_OPTION_IA_TA_LEN; + memcpy(&ia->ia_ta.id, iaoption->data, sizeof(ia->ia_ta)); + + break; + + default: + return -ENOMSG; + } + + ia->type = iatype; + i = iaaddr_offset; + + while (i < len) { + DHCP6Option *option = (DHCP6Option *)&iaoption->data[i]; + + if (len < i + sizeof(*option) || len < i + sizeof(*option) + be16toh(option->len)) + return -ENOBUFS; + + opt = be16toh(option->code); + optlen = be16toh(option->len); + + switch (opt) { + case SD_DHCP6_OPTION_IAADDR: + + if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_TA)) { + log_dhcp6_client(client, "IA Address option not in IA NA or TA option"); + return -EINVAL; + } + + r = dhcp6_option_parse_address(option, ia, <_valid); + if (r < 0) + return r; + + if (lt_valid < lt_min) + lt_min = lt_valid; + + break; + + case SD_DHCP6_OPTION_IA_PD_PREFIX: + + if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_PD)) { + log_dhcp6_client(client, "IA PD Prefix option not in IA PD option"); + return -EINVAL; + } + + r = dhcp6_option_parse_pdprefix(option, ia, <_valid); + if (r < 0) + return r; + + if (lt_valid < lt_min) + lt_min = lt_valid; + + break; + + case SD_DHCP6_OPTION_STATUS_CODE: + + status = dhcp6_option_parse_status(option, optlen + offsetof(DHCP6Option, data)); + if (status < 0) + return status; + if (status > 0) { + log_dhcp6_client(client, "IA status %d", + status); + + return -EINVAL; + } + + break; + + default: + log_dhcp6_client(client, "Unknown IA option %d", opt); + break; + } + + i += sizeof(*option) + optlen; + } + + switch(iatype) { + case SD_DHCP6_OPTION_IA_NA: + if (!ia->ia_na.lifetime_t1 && !ia->ia_na.lifetime_t2) { + lt_t1 = lt_min / 2; + lt_t2 = lt_min / 10 * 8; + ia->ia_na.lifetime_t1 = htobe32(lt_t1); + ia->ia_na.lifetime_t2 = htobe32(lt_t2); + + log_dhcp6_client(client, "Computed IA NA T1 %ds and T2 %ds as both were zero", + lt_t1, lt_t2); + } + + break; + + case SD_DHCP6_OPTION_IA_PD: + if (!ia->ia_pd.lifetime_t1 && !ia->ia_pd.lifetime_t2) { + lt_t1 = lt_min / 2; + lt_t2 = lt_min / 10 * 8; + ia->ia_pd.lifetime_t1 = htobe32(lt_t1); + ia->ia_pd.lifetime_t2 = htobe32(lt_t2); + + log_dhcp6_client(client, "Computed IA PD T1 %ds and T2 %ds as both were zero", + lt_t1, lt_t2); + } + + break; + + default: + break; + } + + return 0; +} + +int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, + struct in6_addr **addrs, size_t count, + size_t *allocated) { + + if (optlen == 0 || optlen % sizeof(struct in6_addr) != 0) + return -EINVAL; + + if (!GREEDY_REALLOC(*addrs, *allocated, + count * sizeof(struct in6_addr) + optlen)) + return -ENOMEM; + + memcpy(*addrs + count, optval, optlen); + + count += optlen / sizeof(struct in6_addr); + + return count; +} + +int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char ***str_arr) { + size_t pos = 0, idx = 0; + _cleanup_strv_free_ char **names = NULL; + int r; + + assert_return(optlen > 1, -ENODATA); + assert_return(optval[optlen - 1] == '\0', -EINVAL); + + while (pos < optlen) { + _cleanup_free_ char *ret = NULL; + size_t n = 0, allocated = 0; + bool first = true; + + for (;;) { + const char *label; + uint8_t c; + + c = optval[pos++]; + + if (c == 0) + /* End of name */ + break; + if (c > 63) + return -EBADMSG; + + /* Literal label */ + label = (const char *)&optval[pos]; + pos += c; + if (pos >= optlen) + return -EMSGSIZE; + + if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) + return -ENOMEM; + + if (first) + first = false; + else + ret[n++] = '.'; + + r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX); + if (r < 0) + return r; + + n += r; + } + + if (n == 0) + continue; + + if (!GREEDY_REALLOC(ret, allocated, n + 1)) + return -ENOMEM; + + ret[n] = 0; + + r = strv_extend(&names, ret); + if (r < 0) + return r; + + idx++; + } + + *str_arr = TAKE_PTR(names); + + return idx; +} diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h new file mode 100644 index 00000000..ffae4453 --- /dev/null +++ b/src/libsystemd-network/dhcp6-protocol.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include +#include + +#include "macro.h" +#include "sparse-endian.h" + +struct DHCP6Message { + union { + struct { + uint8_t type; + uint8_t _pad[3]; + } _packed_; + be32_t transaction_id; + }; + uint8_t options[]; +} _packed_; + +typedef struct DHCP6Message DHCP6Message; + +#define DHCP6_MIN_OPTIONS_SIZE \ + 1280 - sizeof(struct ip6_hdr) - sizeof(struct udphdr) + +#define IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT \ + { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02 } } } + +enum { + DHCP6_PORT_SERVER = 547, + DHCP6_PORT_CLIENT = 546, +}; + +#define DHCP6_INF_TIMEOUT 1 * USEC_PER_SEC +#define DHCP6_INF_MAX_RT 120 * USEC_PER_SEC +#define DHCP6_SOL_MAX_DELAY 1 * USEC_PER_SEC +#define DHCP6_SOL_TIMEOUT 1 * USEC_PER_SEC +#define DHCP6_SOL_MAX_RT 120 * USEC_PER_SEC +#define DHCP6_REQ_TIMEOUT 1 * USEC_PER_SEC +#define DHCP6_REQ_MAX_RT 120 * USEC_PER_SEC +#define DHCP6_REQ_MAX_RC 10 +#define DHCP6_REN_TIMEOUT 10 * USEC_PER_SEC +#define DHCP6_REN_MAX_RT 600 * USEC_PER_SEC +#define DHCP6_REB_TIMEOUT 10 * USEC_PER_SEC +#define DHCP6_REB_MAX_RT 600 * USEC_PER_SEC + +enum DHCP6State { + DHCP6_STATE_STOPPED = 0, + DHCP6_STATE_INFORMATION_REQUEST = 1, + DHCP6_STATE_SOLICITATION = 2, + DHCP6_STATE_REQUEST = 3, + DHCP6_STATE_BOUND = 4, + DHCP6_STATE_RENEW = 5, + DHCP6_STATE_REBIND = 6, +}; + +enum { + DHCP6_SOLICIT = 1, + DHCP6_ADVERTISE = 2, + DHCP6_REQUEST = 3, + DHCP6_CONFIRM = 4, + DHCP6_RENEW = 5, + DHCP6_REBIND = 6, + DHCP6_REPLY = 7, + DHCP6_RELEASE = 8, + DHCP6_DECLINE = 9, + DHCP6_RECONFIGURE = 10, + DHCP6_INFORMATION_REQUEST = 11, + DHCP6_RELAY_FORW = 12, + DHCP6_RELAY_REPL = 13, + _DHCP6_MESSAGE_MAX = 14, +}; + +enum { + DHCP6_NTP_SUBOPTION_SRV_ADDR = 1, + DHCP6_NTP_SUBOPTION_MC_ADDR = 2, + DHCP6_NTP_SUBOPTION_SRV_FQDN = 3, +}; + +enum { + DHCP6_STATUS_SUCCESS = 0, + DHCP6_STATUS_UNSPEC_FAIL = 1, + DHCP6_STATUS_NO_ADDRS_AVAIL = 2, + DHCP6_STATUS_NO_BINDING = 3, + DHCP6_STATUS_NOT_ON_LINK = 4, + DHCP6_STATUS_USE_MULTICAST = 5, + _DHCP6_STATUS_MAX = 6, +}; + +enum { + DHCP6_FQDN_FLAG_S = (1 << 0), + DHCP6_FQDN_FLAG_O = (1 << 1), + DHCP6_FQDN_FLAG_N = (1 << 2), +}; diff --git a/src/libsystemd-network/icmp6-util.c b/src/libsystemd-network/icmp6-util.c new file mode 100644 index 00000000..dbb1e51a --- /dev/null +++ b/src/libsystemd-network/icmp6-util.c @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fd-util.h" +#include "icmp6-util.h" +#include "in-addr-util.h" +#include "io-util.h" +#include "socket-util.h" + +#define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \ + { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } } } + +#define IN6ADDR_ALL_NODES_MULTICAST_INIT \ + { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } } + +static int icmp6_bind_router_message(const struct icmp6_filter *filter, + const struct ipv6_mreq *mreq) { + int ifindex = mreq->ipv6mr_interface; + _cleanup_close_ int s = -1; + int r; + + s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6); + if (s < 0) + return -errno; + + r = setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, filter, sizeof(*filter)); + if (r < 0) + return -errno; + + r = setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq, sizeof(*mreq)); + if (r < 0) + return -errno; + + /* RFC 3315, section 6.7, bullet point 2 may indicate that an + IPV6_PKTINFO socket option also applies for ICMPv6 multicast. + Empirical experiments indicates otherwise and therefore an + IPV6_MULTICAST_IF socket option is used here instead */ + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, ifindex); + if (r < 0) + return r; + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, false); + if (r < 0) + return r; + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255); + if (r < 0) + return r; + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255); + if (r < 0) + return r; + + r = setsockopt_int(s, SOL_IPV6, IPV6_RECVHOPLIMIT, true); + if (r < 0) + return r; + + r = setsockopt_int(s, SOL_SOCKET, SO_TIMESTAMP, true); + if (r < 0) + return r; + + r = socket_bind_to_ifindex(s, ifindex); + if (r < 0) + return r; + + return TAKE_FD(s); +} + +int icmp6_bind_router_solicitation(int index) { + struct icmp6_filter filter = {}; + struct ipv6_mreq mreq = { + .ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT, + .ipv6mr_interface = index, + }; + + ICMP6_FILTER_SETBLOCKALL(&filter); + ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter); + + return icmp6_bind_router_message(&filter, &mreq); +} + +int icmp6_bind_router_advertisement(int index) { + struct icmp6_filter filter = {}; + struct ipv6_mreq mreq = { + .ipv6mr_multiaddr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT, + .ipv6mr_interface = index, + }; + + ICMP6_FILTER_SETBLOCKALL(&filter); + ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter); + + return icmp6_bind_router_message(&filter, &mreq); +} + +int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) { + struct sockaddr_in6 dst = { + .sin6_family = AF_INET6, + .sin6_addr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT, + }; + struct { + struct nd_router_solicit rs; + struct nd_opt_hdr rs_opt; + struct ether_addr rs_opt_mac; + } _packed_ rs = { + .rs.nd_rs_type = ND_ROUTER_SOLICIT, + .rs_opt.nd_opt_type = ND_OPT_SOURCE_LINKADDR, + .rs_opt.nd_opt_len = 1, + }; + struct iovec iov = { + .iov_base = &rs, + .iov_len = sizeof(rs), + }; + struct msghdr msg = { + .msg_name = &dst, + .msg_namelen = sizeof(dst), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + int r; + + assert(s >= 0); + assert(ether_addr); + + rs.rs_opt_mac = *ether_addr; + + r = sendmsg(s, &msg, 0); + if (r < 0) + return -errno; + + return 0; +} + +int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *dst, + triple_timestamp *timestamp) { + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int)) + /* ttl */ + CMSG_SPACE(sizeof(struct timeval))]; + } control = {}; + struct iovec iov = {}; + union sockaddr_union sa = {}; + struct msghdr msg = { + .msg_name = &sa.sa, + .msg_namelen = sizeof(sa), + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + struct cmsghdr *cmsg; + ssize_t len; + + iov = IOVEC_MAKE(buffer, size); + + len = recvmsg(fd, &msg, MSG_DONTWAIT); + if (len < 0) + return -errno; + + if ((size_t) len != size) + return -EINVAL; + + if (msg.msg_namelen == sizeof(struct sockaddr_in6) && + sa.in6.sin6_family == AF_INET6) { + + *dst = sa.in6.sin6_addr; + if (in_addr_is_link_local(AF_INET6, (union in_addr_union*) dst) <= 0) + return -EADDRNOTAVAIL; + + } else if (msg.msg_namelen > 0) + return -EPFNOSUPPORT; + + /* namelen == 0 only happens when running the test-suite over a socketpair */ + + assert(!(msg.msg_flags & MSG_CTRUNC)); + assert(!(msg.msg_flags & MSG_TRUNC)); + + CMSG_FOREACH(cmsg, &msg) { + if (cmsg->cmsg_level == SOL_IPV6 && + cmsg->cmsg_type == IPV6_HOPLIMIT && + cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { + int hops = *(int*) CMSG_DATA(cmsg); + + if (hops != 255) + return -EMULTIHOP; + } + + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SO_TIMESTAMP && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) + triple_timestamp_from_realtime(timestamp, timeval_load((struct timeval*) CMSG_DATA(cmsg))); + } + + if (!triple_timestamp_is_set(timestamp)) + triple_timestamp_get(timestamp); + + return 0; +} diff --git a/src/libsystemd-network/icmp6-util.h b/src/libsystemd-network/icmp6-util.h new file mode 100644 index 00000000..725a6808 --- /dev/null +++ b/src/libsystemd-network/icmp6-util.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2014-2015 Intel Corporation. All rights reserved. +***/ + +#include + +#include "time-util.h" + +#define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \ + { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } } } + +#define IN6ADDR_ALL_NODES_MULTICAST_INIT \ + { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } } + +int icmp6_bind_router_solicitation(int index); +int icmp6_bind_router_advertisement(int index); +int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr); +int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *dst, + triple_timestamp *timestamp); diff --git a/src/libsystemd-network/lldp-internal.h b/src/libsystemd-network/lldp-internal.h new file mode 100644 index 00000000..9598438d --- /dev/null +++ b/src/libsystemd-network/lldp-internal.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" +#include "sd-lldp.h" + +#include "hashmap.h" +#include "log.h" +#include "prioq.h" + +struct sd_lldp { + unsigned n_ref; + + int ifindex; + int fd; + + sd_event *event; + int64_t event_priority; + sd_event_source *io_event_source; + sd_event_source *timer_event_source; + + Prioq *neighbor_by_expiry; + Hashmap *neighbor_by_id; + + uint64_t neighbors_max; + + sd_lldp_callback_t callback; + void *userdata; + + uint16_t capability_mask; + + struct ether_addr filter_address; +}; + +#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__) +#define log_lldp(fmt, ...) log_lldp_errno(0, fmt, ##__VA_ARGS__) + +const char* lldp_event_to_string(sd_lldp_event e) _const_; +sd_lldp_event lldp_event_from_string(const char *s) _pure_; diff --git a/src/libsystemd-network/lldp-neighbor.c b/src/libsystemd-network/lldp-neighbor.c new file mode 100644 index 00000000..1e9fe730 --- /dev/null +++ b/src/libsystemd-network/lldp-neighbor.c @@ -0,0 +1,769 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "escape.h" +#include "ether-addr-util.h" +#include "hexdecoct.h" +#include "in-addr-util.h" +#include "lldp-internal.h" +#include "lldp-neighbor.h" +#include "memory-util.h" +#include "missing_network.h" +#include "unaligned.h" + +static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash *state) { + siphash24_compress(id->chassis_id, id->chassis_id_size, state); + siphash24_compress(&id->chassis_id_size, sizeof(id->chassis_id_size), state); + siphash24_compress(id->port_id, id->port_id_size, state); + siphash24_compress(&id->port_id_size, sizeof(id->port_id_size), state); +} + +int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y) { + return memcmp_nn(x->chassis_id, x->chassis_id_size, y->chassis_id, y->chassis_id_size) + ?: memcmp_nn(x->port_id, x->port_id_size, y->port_id, y->port_id_size); +} + +DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(lldp_neighbor_hash_ops, LLDPNeighborID, lldp_neighbor_id_hash_func, lldp_neighbor_id_compare_func, + sd_lldp_neighbor, lldp_neighbor_unlink); + +int lldp_neighbor_prioq_compare_func(const void *a, const void *b) { + const sd_lldp_neighbor *x = a, *y = b; + + return CMP(x->until, y->until); +} + +_public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) { + if (!n) + return NULL; + + assert(n->n_ref > 0 || n->lldp); + n->n_ref++; + + return n; +} + +static void lldp_neighbor_free(sd_lldp_neighbor *n) { + assert(n); + + free(n->id.port_id); + free(n->id.chassis_id); + free(n->port_description); + free(n->system_name); + free(n->system_description); + free(n->chassis_id_as_string); + free(n->port_id_as_string); + free(n); +} + +_public_ sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n) { + + /* Drops one reference from the neighbor. Note that the object is not freed unless it is already unlinked from + * the sd_lldp object. */ + + if (!n) + return NULL; + + assert(n->n_ref > 0); + n->n_ref--; + + if (n->n_ref <= 0 && !n->lldp) + lldp_neighbor_free(n); + + return NULL; +} + +sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n) { + + /* Removes the neighbor object from the LLDP object, and frees it if it also has no other reference. */ + + if (!n) + return NULL; + + if (!n->lldp) + return NULL; + + /* Only remove the neighbor object from the hash table if it's in there, don't complain if it isn't. This is + * because we are used as destructor call for hashmap_clear() and thus sometimes are called to de-register + * ourselves from the hashtable and sometimes are called after we already are de-registered. */ + + (void) hashmap_remove_value(n->lldp->neighbor_by_id, &n->id, n); + + assert_se(prioq_remove(n->lldp->neighbor_by_expiry, n, &n->prioq_idx) >= 0); + + n->lldp = NULL; + + if (n->n_ref <= 0) + lldp_neighbor_free(n); + + return NULL; +} + +sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size) { + sd_lldp_neighbor *n; + + n = malloc0(ALIGN(sizeof(sd_lldp_neighbor)) + raw_size); + if (!n) + return NULL; + + n->raw_size = raw_size; + n->n_ref = 1; + + return n; +} + +static int parse_string(char **s, const void *q, size_t n) { + const char *p = q; + char *k; + + assert(s); + assert(p || n == 0); + + if (*s) { + log_lldp("Found duplicate string, ignoring field."); + return 0; + } + + /* Strip trailing NULs, just to be nice */ + while (n > 0 && p[n-1] == 0) + n--; + + if (n <= 0) /* Ignore empty strings */ + return 0; + + /* Look for inner NULs */ + if (memchr(p, 0, n)) { + log_lldp("Found inner NUL in string, ignoring field."); + return 0; + } + + /* Let's escape weird chars, for security reasons */ + k = cescape_length(p, n); + if (!k) + return -ENOMEM; + + free(*s); + *s = k; + + return 1; +} + +int lldp_neighbor_parse(sd_lldp_neighbor *n) { + struct ether_header h; + const uint8_t *p; + size_t left; + int r; + + assert(n); + + if (n->raw_size < sizeof(struct ether_header)) { + log_lldp("Received truncated packet, ignoring."); + return -EBADMSG; + } + + memcpy(&h, LLDP_NEIGHBOR_RAW(n), sizeof(h)); + + if (h.ether_type != htobe16(ETHERTYPE_LLDP)) { + log_lldp("Received packet with wrong type, ignoring."); + return -EBADMSG; + } + + if (h.ether_dhost[0] != 0x01 || + h.ether_dhost[1] != 0x80 || + h.ether_dhost[2] != 0xc2 || + h.ether_dhost[3] != 0x00 || + h.ether_dhost[4] != 0x00 || + !IN_SET(h.ether_dhost[5], 0x00, 0x03, 0x0e)) { + log_lldp("Received packet with wrong destination address, ignoring."); + return -EBADMSG; + } + + memcpy(&n->source_address, h.ether_shost, sizeof(struct ether_addr)); + memcpy(&n->destination_address, h.ether_dhost, sizeof(struct ether_addr)); + + p = (const uint8_t*) LLDP_NEIGHBOR_RAW(n) + sizeof(struct ether_header); + left = n->raw_size - sizeof(struct ether_header); + + for (;;) { + uint8_t type; + uint16_t length; + + if (left < 2) { + log_lldp("TLV lacks header, ignoring."); + return -EBADMSG; + } + + type = p[0] >> 1; + length = p[1] + (((uint16_t) (p[0] & 1)) << 8); + p += 2, left -= 2; + + if (left < length) { + log_lldp("TLV truncated, ignoring datagram."); + return -EBADMSG; + } + + switch (type) { + + case SD_LLDP_TYPE_END: + if (length != 0) { + log_lldp("End marker TLV not zero-sized, ignoring datagram."); + return -EBADMSG; + } + + /* Note that after processing the SD_LLDP_TYPE_END left could still be > 0 + * as the message may contain padding (see IEEE 802.1AB-2016, sec. 8.5.12) */ + + goto end_marker; + + case SD_LLDP_TYPE_CHASSIS_ID: + if (length < 2 || length > 256) { /* includes the chassis subtype, hence one extra byte */ + log_lldp("Chassis ID field size out of range, ignoring datagram."); + return -EBADMSG; + } + if (n->id.chassis_id) { + log_lldp("Duplicate chassis ID field, ignoring datagram."); + return -EBADMSG; + } + + n->id.chassis_id = memdup(p, length); + if (!n->id.chassis_id) + return -ENOMEM; + + n->id.chassis_id_size = length; + break; + + case SD_LLDP_TYPE_PORT_ID: + if (length < 2 || length > 256) { /* includes the port subtype, hence one extra byte */ + log_lldp("Port ID field size out of range, ignoring datagram."); + return -EBADMSG; + } + if (n->id.port_id) { + log_lldp("Duplicate port ID field, ignoring datagram."); + return -EBADMSG; + } + + n->id.port_id = memdup(p, length); + if (!n->id.port_id) + return -ENOMEM; + + n->id.port_id_size = length; + break; + + case SD_LLDP_TYPE_TTL: + if (length != 2) { + log_lldp("TTL field has wrong size, ignoring datagram."); + return -EBADMSG; + } + + if (n->has_ttl) { + log_lldp("Duplicate TTL field, ignoring datagram."); + return -EBADMSG; + } + + n->ttl = unaligned_read_be16(p); + n->has_ttl = true; + break; + + case SD_LLDP_TYPE_PORT_DESCRIPTION: + r = parse_string(&n->port_description, p, length); + if (r < 0) + return r; + break; + + case SD_LLDP_TYPE_SYSTEM_NAME: + r = parse_string(&n->system_name, p, length); + if (r < 0) + return r; + break; + + case SD_LLDP_TYPE_SYSTEM_DESCRIPTION: + r = parse_string(&n->system_description, p, length); + if (r < 0) + return r; + break; + + case SD_LLDP_TYPE_SYSTEM_CAPABILITIES: + if (length != 4) + log_lldp("System capabilities field has wrong size, ignoring."); + else { + n->system_capabilities = unaligned_read_be16(p); + n->enabled_capabilities = unaligned_read_be16(p + 2); + n->has_capabilities = true; + } + + break; + + case SD_LLDP_TYPE_PRIVATE: + if (length < 4) + log_lldp("Found private TLV that is too short, ignoring."); + + break; + } + + p += length, left -= length; + } + +end_marker: + if (!n->id.chassis_id || !n->id.port_id || !n->has_ttl) { + log_lldp("One or more mandatory TLV missing in datagram. Ignoring."); + return -EBADMSG; + + } + + n->rindex = sizeof(struct ether_header); + + return 0; +} + +void lldp_neighbor_start_ttl(sd_lldp_neighbor *n) { + assert(n); + + if (n->ttl > 0) { + usec_t base; + + /* Use the packet's timestamp if there is one known */ + base = triple_timestamp_by_clock(&n->timestamp, clock_boottime_or_monotonic()); + if (base <= 0 || base == USEC_INFINITY) + base = now(clock_boottime_or_monotonic()); /* Otherwise, take the current time */ + + n->until = usec_add(base, n->ttl * USEC_PER_SEC); + } else + n->until = 0; + + if (n->lldp) + prioq_reshuffle(n->lldp->neighbor_by_expiry, n, &n->prioq_idx); +} + +bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b) { + if (a == b) + return true; + + if (!a || !b) + return false; + + if (a->raw_size != b->raw_size) + return false; + + return memcmp(LLDP_NEIGHBOR_RAW(a), LLDP_NEIGHBOR_RAW(b), a->raw_size) == 0; +} + +_public_ int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address) { + assert_return(n, -EINVAL); + assert_return(address, -EINVAL); + + *address = n->source_address; + return 0; +} + +_public_ int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address) { + assert_return(n, -EINVAL); + assert_return(address, -EINVAL); + + *address = n->destination_address; + return 0; +} + +_public_ int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(size, -EINVAL); + + *ret = LLDP_NEIGHBOR_RAW(n); + *size = n->raw_size; + + return 0; +} + +_public_ int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { + assert_return(n, -EINVAL); + assert_return(type, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(size, -EINVAL); + + assert(n->id.chassis_id_size > 0); + + *type = *(uint8_t*) n->id.chassis_id; + *ret = (uint8_t*) n->id.chassis_id + 1; + *size = n->id.chassis_id_size - 1; + + return 0; +} + +static int format_mac_address(const void *data, size_t sz, char **ret) { + struct ether_addr a; + char *k; + + assert(data || sz <= 0); + + if (sz != 7) + return 0; + + memcpy(&a, (uint8_t*) data + 1, sizeof(a)); + + k = new(char, ETHER_ADDR_TO_STRING_MAX); + if (!k) + return -ENOMEM; + + *ret = ether_addr_to_string(&a, k); + return 1; +} + +static int format_network_address(const void *data, size_t sz, char **ret) { + union in_addr_union a; + int family, r; + + if (sz == 6 && ((uint8_t*) data)[1] == 1) { + memcpy(&a.in, (uint8_t*) data + 2, sizeof(a.in)); + family = AF_INET; + } else if (sz == 18 && ((uint8_t*) data)[1] == 2) { + memcpy(&a.in6, (uint8_t*) data + 2, sizeof(a.in6)); + family = AF_INET6; + } else + return 0; + + r = in_addr_to_string(family, &a, ret); + if (r < 0) + return r; + return 1; +} + +_public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret) { + char *k; + int r; + + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (n->chassis_id_as_string) { + *ret = n->chassis_id_as_string; + return 0; + } + + assert(n->id.chassis_id_size > 0); + + switch (*(uint8_t*) n->id.chassis_id) { + + case SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: + case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: + case SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT: + case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: + case SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: + k = cescape_length((char*) n->id.chassis_id + 1, n->id.chassis_id_size - 1); + if (!k) + return -ENOMEM; + + goto done; + + case SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: + r = format_mac_address(n->id.chassis_id, n->id.chassis_id_size, &k); + if (r < 0) + return r; + if (r > 0) + goto done; + + break; + + case SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS: + r = format_network_address(n->id.chassis_id, n->id.chassis_id_size, &k); + if (r < 0) + return r; + if (r > 0) + goto done; + + break; + } + + /* Generic fallback */ + k = hexmem(n->id.chassis_id, n->id.chassis_id_size); + if (!k) + return -ENOMEM; + +done: + *ret = n->chassis_id_as_string = k; + return 0; +} + +_public_ int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { + assert_return(n, -EINVAL); + assert_return(type, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(size, -EINVAL); + + assert(n->id.port_id_size > 0); + + *type = *(uint8_t*) n->id.port_id; + *ret = (uint8_t*) n->id.port_id + 1; + *size = n->id.port_id_size - 1; + + return 0; +} + +_public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret) { + char *k; + int r; + + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (n->port_id_as_string) { + *ret = n->port_id_as_string; + return 0; + } + + assert(n->id.port_id_size > 0); + + switch (*(uint8_t*) n->id.port_id) { + + case SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: + case SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT: + case SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME: + case SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: + k = cescape_length((char*) n->id.port_id + 1, n->id.port_id_size - 1); + if (!k) + return -ENOMEM; + + goto done; + + case SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS: + r = format_mac_address(n->id.port_id, n->id.port_id_size, &k); + if (r < 0) + return r; + if (r > 0) + goto done; + + break; + + case SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS: + r = format_network_address(n->id.port_id, n->id.port_id_size, &k); + if (r < 0) + return r; + if (r > 0) + goto done; + + break; + } + + /* Generic fallback */ + k = hexmem(n->id.port_id, n->id.port_id_size); + if (!k) + return -ENOMEM; + +done: + *ret = n->port_id_as_string = k; + return 0; +} + +_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec) { + assert_return(n, -EINVAL); + assert_return(ret_sec, -EINVAL); + + *ret_sec = n->ttl; + return 0; +} + +_public_ int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->system_name) + return -ENODATA; + + *ret = n->system_name; + return 0; +} + +_public_ int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->system_description) + return -ENODATA; + + *ret = n->system_description; + return 0; +} + +_public_ int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->port_description) + return -ENODATA; + + *ret = n->port_description; + return 0; +} + +_public_ int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->has_capabilities) + return -ENODATA; + + *ret = n->system_capabilities; + return 0; +} + +_public_ int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + + if (!n->has_capabilities) + return -ENODATA; + + *ret = n->enabled_capabilities; + return 0; +} + +_public_ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) { + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; + int r; + + assert_return(ret, -EINVAL); + assert_return(raw || raw_size <= 0, -EINVAL); + + n = lldp_neighbor_new(raw_size); + if (!n) + return -ENOMEM; + + memcpy(LLDP_NEIGHBOR_RAW(n), raw, raw_size); + r = lldp_neighbor_parse(n); + if (r < 0) + return r; + + *ret = TAKE_PTR(n); + + return r; +} + +_public_ int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) { + assert_return(n, -EINVAL); + + assert(n->raw_size >= sizeof(struct ether_header)); + n->rindex = sizeof(struct ether_header); + + return n->rindex < n->raw_size; +} + +_public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) { + size_t length; + + assert_return(n, -EINVAL); + + if (n->rindex == n->raw_size) /* EOF */ + return -ESPIPE; + + if (n->rindex + 2 > n->raw_size) /* Truncated message */ + return -EBADMSG; + + length = LLDP_NEIGHBOR_TLV_LENGTH(n); + if (n->rindex + 2 + length > n->raw_size) + return -EBADMSG; + + n->rindex += 2 + length; + return n->rindex < n->raw_size; +} + +_public_ int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) { + assert_return(n, -EINVAL); + assert_return(type, -EINVAL); + + if (n->rindex == n->raw_size) /* EOF */ + return -ESPIPE; + + if (n->rindex + 2 > n->raw_size) + return -EBADMSG; + + *type = LLDP_NEIGHBOR_TLV_TYPE(n); + return 0; +} + +_public_ int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type) { + uint8_t k; + int r; + + assert_return(n, -EINVAL); + + r = sd_lldp_neighbor_tlv_get_type(n, &k); + if (r < 0) + return r; + + return type == k; +} + +_public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype) { + const uint8_t *d; + size_t length; + int r; + + assert_return(n, -EINVAL); + assert_return(oui, -EINVAL); + assert_return(subtype, -EINVAL); + + r = sd_lldp_neighbor_tlv_is_type(n, SD_LLDP_TYPE_PRIVATE); + if (r < 0) + return r; + if (r == 0) + return -ENXIO; + + length = LLDP_NEIGHBOR_TLV_LENGTH(n); + if (length < 4) + return -EBADMSG; + + if (n->rindex + 2 + length > n->raw_size) + return -EBADMSG; + + d = LLDP_NEIGHBOR_TLV_DATA(n); + memcpy(oui, d, 3); + *subtype = d[3]; + + return 0; +} + +_public_ int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype) { + uint8_t k[3], st; + int r; + + r = sd_lldp_neighbor_tlv_get_oui(n, k, &st); + if (r == -ENXIO) + return 0; + if (r < 0) + return r; + + return memcmp(k, oui, 3) == 0 && st == subtype; +} + +_public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { + size_t length; + + assert_return(n, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(size, -EINVAL); + + /* Note that this returns the full TLV, including the TLV header */ + + if (n->rindex + 2 > n->raw_size) + return -EBADMSG; + + length = LLDP_NEIGHBOR_TLV_LENGTH(n); + if (n->rindex + 2 + length > n->raw_size) + return -EBADMSG; + + *ret = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex; + *size = length + 2; + + return 0; +} + +_public_ int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret) { + assert_return(n, -EINVAL); + assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP); + assert_return(clock_supported(clock), -EOPNOTSUPP); + assert_return(ret, -EINVAL); + + if (!triple_timestamp_is_set(&n->timestamp)) + return -ENODATA; + + *ret = triple_timestamp_by_clock(&n->timestamp, clock); + return 0; +} diff --git a/src/libsystemd-network/lldp-neighbor.h b/src/libsystemd-network/lldp-neighbor.h new file mode 100644 index 00000000..62dbff42 --- /dev/null +++ b/src/libsystemd-network/lldp-neighbor.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "sd-lldp.h" + +#include "hash-funcs.h" +#include "lldp-internal.h" +#include "time-util.h" + +typedef struct LLDPNeighborID { + /* The spec calls this an "MSAP identifier" */ + void *chassis_id; + size_t chassis_id_size; + + void *port_id; + size_t port_id_size; +} LLDPNeighborID; + +struct sd_lldp_neighbor { + /* Neighbor objects stay around as long as they are linked into an "sd_lldp" object or n_ref > 0. */ + sd_lldp *lldp; + unsigned n_ref; + + triple_timestamp timestamp; + + usec_t until; + unsigned prioq_idx; + + struct ether_addr source_address; + struct ether_addr destination_address; + + LLDPNeighborID id; + + /* The raw packet size. The data is appended to the object, accessible via LLDP_NEIGHBOR_RAW() */ + size_t raw_size; + + /* The current read index for the iterative TLV interface */ + size_t rindex; + + /* And a couple of fields parsed out. */ + bool has_ttl:1; + bool has_capabilities:1; + bool has_port_vlan_id:1; + + uint16_t ttl; + + uint16_t system_capabilities; + uint16_t enabled_capabilities; + + char *port_description; + char *system_name; + char *system_description; + + uint16_t port_vlan_id; + + char *chassis_id_as_string; + char *port_id_as_string; +}; + +static inline void *LLDP_NEIGHBOR_RAW(const sd_lldp_neighbor *n) { + return (uint8_t*) n + ALIGN(sizeof(sd_lldp_neighbor)); +} + +static inline uint8_t LLDP_NEIGHBOR_TLV_TYPE(const sd_lldp_neighbor *n) { + return ((uint8_t*) LLDP_NEIGHBOR_RAW(n))[n->rindex] >> 1; +} + +static inline size_t LLDP_NEIGHBOR_TLV_LENGTH(const sd_lldp_neighbor *n) { + uint8_t *p; + + p = (uint8_t*) LLDP_NEIGHBOR_RAW(n) + n->rindex; + return p[1] + (((size_t) (p[0] & 1)) << 8); +} + +static inline void* LLDP_NEIGHBOR_TLV_DATA(const sd_lldp_neighbor *n) { + return ((uint8_t*) LLDP_NEIGHBOR_RAW(n)) + n->rindex + 2; +} + +extern const struct hash_ops lldp_neighbor_hash_ops; +int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y); +int lldp_neighbor_prioq_compare_func(const void *a, const void *b); + +sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n); +sd_lldp_neighbor *lldp_neighbor_new(size_t raw_size); +int lldp_neighbor_parse(sd_lldp_neighbor *n); +void lldp_neighbor_start_ttl(sd_lldp_neighbor *n); +bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b); diff --git a/src/libsystemd-network/lldp-network.c b/src/libsystemd-network/lldp-network.c new file mode 100644 index 00000000..53e32973 --- /dev/null +++ b/src/libsystemd-network/lldp-network.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "fd-util.h" +#include "lldp-network.h" +#include "missing_network.h" +#include "socket-util.h" + +int lldp_network_bind_raw_socket(int ifindex) { + + static const struct sock_filter filter[] = { + BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ethhdr, h_dest)), /* A <- 4 bytes of destination MAC */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0180c200, 1, 0), /* A != 01:80:c2:00 */ + BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_dest) + 4), /* A <- remaining 2 bytes of destination MAC */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0000, 3, 0), /* A != 00:00 */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0003, 2, 0), /* A != 00:03 */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x000e, 1, 0), /* A != 00:0e */ + BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ + BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_proto)), /* A <- protocol */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_LLDP, 1, 0), /* A != ETHERTYPE_LLDP */ + BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ + BPF_STMT(BPF_RET + BPF_K, (uint32_t) -1), /* accept packet */ + }; + + static const struct sock_fprog fprog = { + .len = ELEMENTSOF(filter), + .filter = (struct sock_filter*) filter, + }; + + struct packet_mreq mreq = { + .mr_ifindex = ifindex, + .mr_type = PACKET_MR_MULTICAST, + .mr_alen = ETH_ALEN, + .mr_address = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 } + }; + + union sockaddr_union saddrll = { + .ll.sll_family = AF_PACKET, + .ll.sll_ifindex = ifindex, + }; + + _cleanup_close_ int fd = -1; + int r; + + assert(ifindex > 0); + + fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, + htobe16(ETHERTYPE_LLDP)); + if (fd < 0) + return -errno; + + r = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); + if (r < 0) + return -errno; + + r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (r < 0) + return -errno; + + mreq.mr_address[ETH_ALEN - 1] = 0x03; + r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (r < 0) + return -errno; + + mreq.mr_address[ETH_ALEN - 1] = 0x0E; + r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (r < 0) + return -errno; + + r = bind(fd, &saddrll.sa, sizeof(saddrll.ll)); + if (r < 0) + return -errno; + + return TAKE_FD(fd); +} diff --git a/src/libsystemd-network/lldp-network.h b/src/libsystemd-network/lldp-network.h new file mode 100644 index 00000000..e4ed2898 --- /dev/null +++ b/src/libsystemd-network/lldp-network.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" + +int lldp_network_bind_raw_socket(int ifindex); diff --git a/src/libsystemd-network/meson.build b/src/libsystemd-network/meson.build new file mode 100644 index 00000000..7fa0c679 --- /dev/null +++ b/src/libsystemd-network/meson.build @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +sources = files(''' + sd-dhcp-client.c + sd-dhcp-server.c + dhcp-client-internal.h + dhcp-network.c + dhcp-option.c + dhcp-packet.c + dhcp-internal.h + dhcp-server-internal.h + dhcp-protocol.h + dhcp-lease-internal.h + sd-dhcp-lease.c + sd-ipv4ll.c + sd-ipv4acd.c + arp-util.h + arp-util.c + network-internal.c + sd-ndisc.c + ndisc-internal.h + ndisc-router.h + ndisc-router.c + sd-radv.c + radv-internal.h + icmp6-util.h + icmp6-util.c + sd-dhcp6-client.c + dhcp6-internal.h + dhcp6-protocol.h + dhcp6-network.c + dhcp6-option.c + dhcp6-lease-internal.h + sd-dhcp6-lease.c + dhcp-identifier.h + dhcp-identifier.c + lldp-internal.h + lldp-network.h + lldp-network.c + lldp-neighbor.h + lldp-neighbor.c + sd-lldp.c +'''.split()) + +network_internal_h = files('network-internal.h') + +libsystemd_network = static_library( + 'systemd-network', + sources, + network_internal_h, + include_directories : includes) diff --git a/src/libsystemd-network/ndisc-internal.h b/src/libsystemd-network/ndisc-internal.h new file mode 100644 index 00000000..c66dc3d4 --- /dev/null +++ b/src/libsystemd-network/ndisc-internal.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include "log.h" +#include "time-util.h" + +#include "sd-ndisc.h" + +#define NDISC_ROUTER_SOLICITATION_INTERVAL (4U * USEC_PER_SEC) +#define NDISC_MAX_ROUTER_SOLICITATION_INTERVAL (3600U * USEC_PER_SEC) +#define NDISC_MAX_ROUTER_SOLICITATIONS 3U + +struct sd_ndisc { + unsigned n_ref; + + int ifindex; + int fd; + + sd_event *event; + int event_priority; + + struct ether_addr mac_addr; + uint8_t hop_limit; + uint32_t mtu; + + sd_event_source *recv_event_source; + sd_event_source *timeout_event_source; + sd_event_source *timeout_no_ra; + + usec_t retransmit_time; + + sd_ndisc_callback_t callback; + void *userdata; +}; + +#define log_ndisc_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "NDISC: " fmt, ##__VA_ARGS__) +#define log_ndisc(fmt, ...) log_ndisc_errno(0, fmt, ##__VA_ARGS__) + +const char* ndisc_event_to_string(sd_ndisc_event e) _const_; +sd_ndisc_event ndisc_event_from_string(const char *s) _pure_; diff --git a/src/libsystemd-network/ndisc-router.c b/src/libsystemd-network/ndisc-router.c new file mode 100644 index 00000000..a2a93663 --- /dev/null +++ b/src/libsystemd-network/ndisc-router.c @@ -0,0 +1,750 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include + +#include "sd-ndisc.h" + +#include "alloc-util.h" +#include "dns-domain.h" +#include "hostname-util.h" +#include "memory-util.h" +#include "missing_network.h" +#include "ndisc-internal.h" +#include "ndisc-router.h" +#include "strv.h" + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_ndisc_router, sd_ndisc_router, mfree); + +sd_ndisc_router *ndisc_router_new(size_t raw_size) { + sd_ndisc_router *rt; + + rt = malloc0(ALIGN(sizeof(sd_ndisc_router)) + raw_size); + if (!rt) + return NULL; + + rt->raw_size = raw_size; + rt->n_ref = 1; + + return rt; +} + +_public_ int sd_ndisc_router_from_raw(sd_ndisc_router **ret, const void *raw, size_t raw_size) { + _cleanup_(sd_ndisc_router_unrefp) sd_ndisc_router *rt = NULL; + int r; + + assert_return(ret, -EINVAL); + assert_return(raw || raw_size <= 0, -EINVAL); + + rt = ndisc_router_new(raw_size); + if (!rt) + return -ENOMEM; + + memcpy(NDISC_ROUTER_RAW(rt), raw, raw_size); + r = ndisc_router_parse(rt); + if (r < 0) + return r; + + *ret = TAKE_PTR(rt); + + return r; +} + +_public_ int sd_ndisc_router_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr) { + assert_return(rt, -EINVAL); + assert_return(ret_addr, -EINVAL); + + if (IN6_IS_ADDR_UNSPECIFIED(&rt->address)) + return -ENODATA; + + *ret_addr = rt->address; + return 0; +} + +_public_ int sd_ndisc_router_get_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret) { + assert_return(rt, -EINVAL); + assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP); + assert_return(clock_supported(clock), -EOPNOTSUPP); + assert_return(ret, -EINVAL); + + if (!triple_timestamp_is_set(&rt->timestamp)) + return -ENODATA; + + *ret = triple_timestamp_by_clock(&rt->timestamp, clock); + return 0; +} + +_public_ int sd_ndisc_router_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size) { + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(size, -EINVAL); + + *ret = NDISC_ROUTER_RAW(rt); + *size = rt->raw_size; + + return 0; +} + +int ndisc_router_parse(sd_ndisc_router *rt) { + struct nd_router_advert *a; + const uint8_t *p; + bool has_mtu = false, has_flag_extension = false; + size_t left; + + assert(rt); + + if (rt->raw_size < sizeof(struct nd_router_advert)) { + log_ndisc("Too small to be a router advertisement, ignoring."); + return -EBADMSG; + } + + /* Router advertisement packets are neatly aligned to 64bit boundaries, hence we can access them directly */ + a = NDISC_ROUTER_RAW(rt); + + if (a->nd_ra_type != ND_ROUTER_ADVERT) { + log_ndisc("Received ND packet that is not a router advertisement, ignoring."); + return -EBADMSG; + } + + if (a->nd_ra_code != 0) { + log_ndisc("Received ND packet with wrong RA code, ignoring."); + return -EBADMSG; + } + + rt->hop_limit = a->nd_ra_curhoplimit; + rt->flags = a->nd_ra_flags_reserved; /* the first 8bit */ + rt->lifetime = be16toh(a->nd_ra_router_lifetime); + + rt->preference = (rt->flags >> 3) & 3; + if (!IN_SET(rt->preference, SD_NDISC_PREFERENCE_LOW, SD_NDISC_PREFERENCE_HIGH)) + rt->preference = SD_NDISC_PREFERENCE_MEDIUM; + + p = (const uint8_t*) NDISC_ROUTER_RAW(rt) + sizeof(struct nd_router_advert); + left = rt->raw_size - sizeof(struct nd_router_advert); + + for (;;) { + uint8_t type; + size_t length; + + if (left == 0) + break; + + if (left < 2) { + log_ndisc("Option lacks header, ignoring datagram."); + return -EBADMSG; + } + + type = p[0]; + length = p[1] * 8; + + if (length == 0) { + log_ndisc("Zero-length option, ignoring datagram."); + return -EBADMSG; + } + if (left < length) { + log_ndisc("Option truncated, ignoring datagram."); + return -EBADMSG; + } + + switch (type) { + + case SD_NDISC_OPTION_PREFIX_INFORMATION: + + if (length != 4*8) { + log_ndisc("Prefix option of invalid size, ignoring datagram."); + return -EBADMSG; + } + + if (p[2] > 128) { + log_ndisc("Bad prefix length, ignoring datagram."); + return -EBADMSG; + } + + break; + + case SD_NDISC_OPTION_MTU: { + uint32_t m; + + if (has_mtu) { + log_ndisc("MTU option specified twice, ignoring."); + break; + } + + if (length != 8) { + log_ndisc("MTU option of invalid size, ignoring datagram."); + return -EBADMSG; + } + + m = be32toh(*(uint32_t*) (p + 4)); + if (m >= IPV6_MIN_MTU) /* ignore invalidly small MTUs */ + rt->mtu = m; + + has_mtu = true; + break; + } + + case SD_NDISC_OPTION_ROUTE_INFORMATION: + if (length < 1*8 || length > 3*8) { + log_ndisc("Route information option of invalid size, ignoring datagram."); + return -EBADMSG; + } + + if (p[2] > 128) { + log_ndisc("Bad route prefix length, ignoring datagram."); + return -EBADMSG; + } + + break; + + case SD_NDISC_OPTION_RDNSS: + if (length < 3*8 || (length % (2*8)) != 1*8) { + log_ndisc("RDNSS option has invalid size."); + return -EBADMSG; + } + + break; + + case SD_NDISC_OPTION_FLAGS_EXTENSION: + + if (has_flag_extension) { + log_ndisc("Flags extension option specified twice, ignoring."); + break; + } + + if (length < 1*8) { + log_ndisc("Flags extension option has invalid size."); + return -EBADMSG; + } + + /* Add in the additional flags bits */ + rt->flags |= + ((uint64_t) p[2] << 8) | + ((uint64_t) p[3] << 16) | + ((uint64_t) p[4] << 24) | + ((uint64_t) p[5] << 32) | + ((uint64_t) p[6] << 40) | + ((uint64_t) p[7] << 48); + + has_flag_extension = true; + break; + + case SD_NDISC_OPTION_DNSSL: + if (length < 2*8) { + log_ndisc("DNSSL option has invalid size."); + return -EBADMSG; + } + + break; + } + + p += length, left -= length; + } + + rt->rindex = sizeof(struct nd_router_advert); + return 0; +} + +_public_ int sd_ndisc_router_get_hop_limit(sd_ndisc_router *rt, uint8_t *ret) { + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + *ret = rt->hop_limit; + return 0; +} + +_public_ int sd_ndisc_router_get_flags(sd_ndisc_router *rt, uint64_t *ret_flags) { + assert_return(rt, -EINVAL); + assert_return(ret_flags, -EINVAL); + + *ret_flags = rt->flags; + return 0; +} + +_public_ int sd_ndisc_router_get_lifetime(sd_ndisc_router *rt, uint16_t *ret_lifetime) { + assert_return(rt, -EINVAL); + assert_return(ret_lifetime, -EINVAL); + + *ret_lifetime = rt->lifetime; + return 0; +} + +_public_ int sd_ndisc_router_get_preference(sd_ndisc_router *rt, unsigned *ret) { + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + *ret = rt->preference; + return 0; +} + +_public_ int sd_ndisc_router_get_mtu(sd_ndisc_router *rt, uint32_t *ret) { + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + if (rt->mtu <= 0) + return -ENODATA; + + *ret = rt->mtu; + return 0; +} + +_public_ int sd_ndisc_router_option_rewind(sd_ndisc_router *rt) { + assert_return(rt, -EINVAL); + + assert(rt->raw_size >= sizeof(struct nd_router_advert)); + rt->rindex = sizeof(struct nd_router_advert); + + return rt->rindex < rt->raw_size; +} + +_public_ int sd_ndisc_router_option_next(sd_ndisc_router *rt) { + size_t length; + + assert_return(rt, -EINVAL); + + if (rt->rindex == rt->raw_size) /* EOF */ + return -ESPIPE; + + if (rt->rindex + 2 > rt->raw_size) /* Truncated message */ + return -EBADMSG; + + length = NDISC_ROUTER_OPTION_LENGTH(rt); + if (rt->rindex + length > rt->raw_size) + return -EBADMSG; + + rt->rindex += length; + return rt->rindex < rt->raw_size; +} + +_public_ int sd_ndisc_router_option_get_type(sd_ndisc_router *rt, uint8_t *ret) { + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + if (rt->rindex == rt->raw_size) /* EOF */ + return -ESPIPE; + + if (rt->rindex + 2 > rt->raw_size) /* Truncated message */ + return -EBADMSG; + + *ret = NDISC_ROUTER_OPTION_TYPE(rt); + return 0; +} + +_public_ int sd_ndisc_router_option_is_type(sd_ndisc_router *rt, uint8_t type) { + uint8_t k; + int r; + + assert_return(rt, -EINVAL); + + r = sd_ndisc_router_option_get_type(rt, &k); + if (r < 0) + return r; + + return type == k; +} + +_public_ int sd_ndisc_router_option_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size) { + size_t length; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(size, -EINVAL); + + /* Note that this returns the full option, including the option header */ + + if (rt->rindex + 2 > rt->raw_size) + return -EBADMSG; + + length = NDISC_ROUTER_OPTION_LENGTH(rt); + if (rt->rindex + length > rt->raw_size) + return -EBADMSG; + + *ret = (uint8_t*) NDISC_ROUTER_RAW(rt) + rt->rindex; + *size = length; + + return 0; +} + +static int get_prefix_info(sd_ndisc_router *rt, struct nd_opt_prefix_info **ret) { + struct nd_opt_prefix_info *ri; + size_t length; + int r; + + assert(rt); + assert(ret); + + r = sd_ndisc_router_option_is_type(rt, SD_NDISC_OPTION_PREFIX_INFORMATION); + if (r < 0) + return r; + if (r == 0) + return -EMEDIUMTYPE; + + length = NDISC_ROUTER_OPTION_LENGTH(rt); + if (length != sizeof(struct nd_opt_prefix_info)) + return -EBADMSG; + + ri = (struct nd_opt_prefix_info*) ((uint8_t*) NDISC_ROUTER_RAW(rt) + rt->rindex); + if (ri->nd_opt_pi_prefix_len > 128) + return -EBADMSG; + + *ret = ri; + return 0; +} + +_public_ int sd_ndisc_router_prefix_get_valid_lifetime(sd_ndisc_router *rt, uint32_t *ret) { + struct nd_opt_prefix_info *ri; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + r = get_prefix_info(rt, &ri); + if (r < 0) + return r; + + *ret = be32toh(ri->nd_opt_pi_valid_time); + return 0; +} + +_public_ int sd_ndisc_router_prefix_get_preferred_lifetime(sd_ndisc_router *rt, uint32_t *ret) { + struct nd_opt_prefix_info *pi; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + r = get_prefix_info(rt, &pi); + if (r < 0) + return r; + + *ret = be32toh(pi->nd_opt_pi_preferred_time); + return 0; +} + +_public_ int sd_ndisc_router_prefix_get_flags(sd_ndisc_router *rt, uint8_t *ret) { + struct nd_opt_prefix_info *pi; + uint8_t flags; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + r = get_prefix_info(rt, &pi); + if (r < 0) + return r; + + flags = pi->nd_opt_pi_flags_reserved; + + if ((flags & ND_OPT_PI_FLAG_AUTO) && (pi->nd_opt_pi_prefix_len != 64)) { + log_ndisc("Invalid prefix length, ignoring prefix for stateless autoconfiguration."); + flags &= ~ND_OPT_PI_FLAG_AUTO; + } + + *ret = flags; + return 0; +} + +_public_ int sd_ndisc_router_prefix_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr) { + struct nd_opt_prefix_info *pi; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret_addr, -EINVAL); + + r = get_prefix_info(rt, &pi); + if (r < 0) + return r; + + *ret_addr = pi->nd_opt_pi_prefix; + return 0; +} + +_public_ int sd_ndisc_router_prefix_get_prefixlen(sd_ndisc_router *rt, unsigned *ret) { + struct nd_opt_prefix_info *pi; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + r = get_prefix_info(rt, &pi); + if (r < 0) + return r; + + if (pi->nd_opt_pi_prefix_len > 128) + return -EBADMSG; + + *ret = pi->nd_opt_pi_prefix_len; + return 0; +} + +static int get_route_info(sd_ndisc_router *rt, uint8_t **ret) { + uint8_t *ri; + size_t length; + int r; + + assert(rt); + assert(ret); + + r = sd_ndisc_router_option_is_type(rt, SD_NDISC_OPTION_ROUTE_INFORMATION); + if (r < 0) + return r; + if (r == 0) + return -EMEDIUMTYPE; + + length = NDISC_ROUTER_OPTION_LENGTH(rt); + if (length < 1*8 || length > 3*8) + return -EBADMSG; + + ri = (uint8_t*) NDISC_ROUTER_RAW(rt) + rt->rindex; + + if (ri[2] > 128) + return -EBADMSG; + + *ret = ri; + return 0; +} + +_public_ int sd_ndisc_router_route_get_lifetime(sd_ndisc_router *rt, uint32_t *ret) { + uint8_t *ri; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + r = get_route_info(rt, &ri); + if (r < 0) + return r; + + *ret = be32toh(*(uint32_t*) (ri + 4)); + return 0; +} + +_public_ int sd_ndisc_router_route_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr) { + uint8_t *ri; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret_addr, -EINVAL); + + r = get_route_info(rt, &ri); + if (r < 0) + return r; + + zero(*ret_addr); + memcpy(ret_addr, ri + 8, NDISC_ROUTER_OPTION_LENGTH(rt) - 8); + + return 0; +} + +_public_ int sd_ndisc_router_route_get_prefixlen(sd_ndisc_router *rt, unsigned *ret) { + uint8_t *ri; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + r = get_route_info(rt, &ri); + if (r < 0) + return r; + + *ret = ri[2]; + return 0; +} + +_public_ int sd_ndisc_router_route_get_preference(sd_ndisc_router *rt, unsigned *ret) { + uint8_t *ri; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + r = get_route_info(rt, &ri); + if (r < 0) + return r; + + *ret = (ri[3] >> 3) & 3; + if (!IN_SET(*ret, SD_NDISC_PREFERENCE_LOW, SD_NDISC_PREFERENCE_HIGH)) + *ret = SD_NDISC_PREFERENCE_MEDIUM; + + return 0; +} + +static int get_rdnss_info(sd_ndisc_router *rt, uint8_t **ret) { + size_t length; + int r; + + assert(rt); + assert(ret); + + r = sd_ndisc_router_option_is_type(rt, SD_NDISC_OPTION_RDNSS); + if (r < 0) + return r; + if (r == 0) + return -EMEDIUMTYPE; + + length = NDISC_ROUTER_OPTION_LENGTH(rt); + if (length < 3*8 || (length % (2*8)) != 1*8) + return -EBADMSG; + + *ret = (uint8_t*) NDISC_ROUTER_RAW(rt) + rt->rindex; + return 0; +} + +_public_ int sd_ndisc_router_rdnss_get_addresses(sd_ndisc_router *rt, const struct in6_addr **ret) { + uint8_t *ri; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + r = get_rdnss_info(rt, &ri); + if (r < 0) + return r; + + *ret = (const struct in6_addr*) (ri + 8); + return (NDISC_ROUTER_OPTION_LENGTH(rt) - 8) / 16; +} + +_public_ int sd_ndisc_router_rdnss_get_lifetime(sd_ndisc_router *rt, uint32_t *ret) { + uint8_t *ri; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + r = get_rdnss_info(rt, &ri); + if (r < 0) + return r; + + *ret = be32toh(*(uint32_t*) (ri + 4)); + return 0; +} + +static int get_dnssl_info(sd_ndisc_router *rt, uint8_t **ret) { + size_t length; + int r; + + assert(rt); + assert(ret); + + r = sd_ndisc_router_option_is_type(rt, SD_NDISC_OPTION_DNSSL); + if (r < 0) + return r; + if (r == 0) + return -EMEDIUMTYPE; + + length = NDISC_ROUTER_OPTION_LENGTH(rt); + if (length < 2*8) + return -EBADMSG; + + *ret = (uint8_t*) NDISC_ROUTER_RAW(rt) + rt->rindex; + return 0; +} + +_public_ int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret) { + _cleanup_strv_free_ char **l = NULL; + _cleanup_free_ char *e = NULL; + size_t allocated = 0, n = 0, left; + uint8_t *ri, *p; + bool first = true; + int r; + unsigned k = 0; + + assert_return(rt, -EINVAL); + assert_return(ret, -EINVAL); + + r = get_dnssl_info(rt, &ri); + if (r < 0) + return r; + + p = ri + 8; + left = NDISC_ROUTER_OPTION_LENGTH(rt) - 8; + + for (;;) { + if (left == 0) { + + if (n > 0) /* Not properly NUL terminated */ + return -EBADMSG; + + break; + } + + if (*p == 0) { + /* Found NUL termination */ + + if (n > 0) { + _cleanup_free_ char *normalized = NULL; + + e[n] = 0; + r = dns_name_normalize(e, 0, &normalized); + if (r < 0) + return r; + + /* Ignore the root domain name or "localhost" and friends */ + if (!is_localhost(normalized) && + !dns_name_is_root(normalized)) { + + if (strv_push(&l, normalized) < 0) + return -ENOMEM; + + normalized = NULL; + k++; + } + } + + n = 0; + first = true; + p++, left--; + continue; + } + + /* Check for compression (which is not allowed) */ + if (*p > 63) + return -EBADMSG; + + if (1U + *p + 1U > left) + return -EBADMSG; + + if (!GREEDY_REALLOC(e, allocated, n + !first + DNS_LABEL_ESCAPED_MAX + 1U)) + return -ENOMEM; + + if (first) + first = false; + else + e[n++] = '.'; + + r = dns_label_escape((char*) p+1, *p, e + n, DNS_LABEL_ESCAPED_MAX); + if (r < 0) + return r; + + n += r; + + left -= 1 + *p; + p += 1 + *p; + } + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + *ret = TAKE_PTR(l); + + return k; +} + +_public_ int sd_ndisc_router_dnssl_get_lifetime(sd_ndisc_router *rt, uint32_t *ret_sec) { + uint8_t *ri; + int r; + + assert_return(rt, -EINVAL); + assert_return(ret_sec, -EINVAL); + + r = get_dnssl_info(rt, &ri); + if (r < 0) + return r; + + *ret_sec = be32toh(*(uint32_t*) (ri + 4)); + return 0; +} diff --git a/src/libsystemd-network/ndisc-router.h b/src/libsystemd-network/ndisc-router.h new file mode 100644 index 00000000..2e2c1afd --- /dev/null +++ b/src/libsystemd-network/ndisc-router.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include "sd-ndisc.h" + +#include "time-util.h" + +struct sd_ndisc_router { + unsigned n_ref; + + triple_timestamp timestamp; + struct in6_addr address; + + /* The raw packet size. The data is appended to the object, accessible via NDIS_ROUTER_RAW() */ + size_t raw_size; + + /* The current read index for the iterative option interface */ + size_t rindex; + + uint64_t flags; + unsigned preference; + uint16_t lifetime; + + uint8_t hop_limit; + uint32_t mtu; +}; + +static inline void* NDISC_ROUTER_RAW(const sd_ndisc_router *rt) { + return (uint8_t*) rt + ALIGN(sizeof(sd_ndisc_router)); +} + +static inline void *NDISC_ROUTER_OPTION_DATA(const sd_ndisc_router *rt) { + return ((uint8_t*) NDISC_ROUTER_RAW(rt)) + rt->rindex; +} + +static inline uint8_t NDISC_ROUTER_OPTION_TYPE(const sd_ndisc_router *rt) { + return ((uint8_t*) NDISC_ROUTER_OPTION_DATA(rt))[0]; +} +static inline size_t NDISC_ROUTER_OPTION_LENGTH(const sd_ndisc_router *rt) { + return ((uint8_t*) NDISC_ROUTER_OPTION_DATA(rt))[1] * 8; +} + +sd_ndisc_router *ndisc_router_new(size_t raw_size); +int ndisc_router_parse(sd_ndisc_router *rt); diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c new file mode 100644 index 00000000..e3704992 --- /dev/null +++ b/src/libsystemd-network/network-internal.c @@ -0,0 +1,837 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-id128.h" +#include "sd-ndisc.h" + +#include "alloc-util.h" +#include "condition.h" +#include "conf-parser.h" +#include "device-util.h" +#include "dhcp-lease-internal.h" +#include "env-util.h" +#include "ether-addr-util.h" +#include "hexdecoct.h" +#include "log.h" +#include "network-internal.h" +#include "parse-util.h" +#include "siphash24.h" +#include "socket-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "utf8.h" +#include "util.h" + +const char *net_get_name_persistent(sd_device *device) { + const char *name, *field; + + assert(device); + + /* fetch some persistent data unique (on this machine) to this device */ + FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") + if (sd_device_get_property_value(device, field, &name) >= 0) + return name; + + return NULL; +} + +#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a) + +int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result) { + size_t l, sz = 0; + const char *name; + int r; + uint8_t *v; + + assert(device); + + /* net_get_name_persistent() will return one of the device names based on stable information about + * the device. If this is not available, we fall back to using the actual device name. */ + name = net_get_name_persistent(device); + if (!name && use_sysname) + (void) sd_device_get_sysname(device, &name); + if (!name) + return log_device_debug_errno(device, SYNTHETIC_ERRNO(ENODATA), + "No stable identifying information found"); + + log_device_debug(device, "Using \"%s\" as stable identifying information", name); + l = strlen(name); + sz = sizeof(sd_id128_t) + l; + v = newa(uint8_t, sz); + + /* Fetch some persistent data unique to this machine */ + r = sd_id128_get_machine((sd_id128_t*) v); + if (r < 0) + return r; + memcpy(v + sizeof(sd_id128_t), name, l); + + /* Let's hash the machine ID plus the device name. We use + * a fixed, but originally randomly created hash key here. */ + *result = htole64(siphash24(v, sz, HASH_KEY.bytes)); + return 0; +} + +static bool net_condition_test_strv(char * const *patterns, const char *string) { + char * const *p; + bool match = false, has_positive_rule = false; + + if (strv_isempty(patterns)) + return true; + + STRV_FOREACH(p, patterns) { + const char *q = *p; + bool invert; + + invert = *q == '!'; + q += invert; + + if (!invert) + has_positive_rule = true; + + if (string && fnmatch(q, string, 0) == 0) { + if (invert) + return false; + else + match = true; + } + } + + return has_positive_rule ? match : true; +} + +static int net_condition_test_property(char * const *match_property, sd_device *device) { + char * const *p; + + if (strv_isempty(match_property)) + return true; + + STRV_FOREACH(p, match_property) { + _cleanup_free_ char *key = NULL; + const char *val, *dev_val; + bool invert, v; + + invert = **p == '!'; + + val = strchr(*p + invert, '='); + if (!val) + return -EINVAL; + + key = strndup(*p + invert, val - *p - invert); + if (!key) + return -ENOMEM; + + val++; + + v = device && + sd_device_get_property_value(device, key, &dev_val) >= 0 && + fnmatch(val, dev_val, 0) == 0; + + if (invert ? v : !v) + return false; + } + + return true; +} + +static const char *const wifi_iftype_table[NL80211_IFTYPE_MAX+1] = { + [NL80211_IFTYPE_ADHOC] = "ad-hoc", + [NL80211_IFTYPE_STATION] = "station", + [NL80211_IFTYPE_AP] = "ap", + [NL80211_IFTYPE_AP_VLAN] = "ap-vlan", + [NL80211_IFTYPE_WDS] = "wds", + [NL80211_IFTYPE_MONITOR] = "monitor", + [NL80211_IFTYPE_MESH_POINT] = "mesh-point", + [NL80211_IFTYPE_P2P_CLIENT] = "p2p-client", + [NL80211_IFTYPE_P2P_GO] = "p2p-go", + [NL80211_IFTYPE_P2P_DEVICE] = "p2p-device", + [NL80211_IFTYPE_OCB] = "ocb", + [NL80211_IFTYPE_NAN] = "nan", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wifi_iftype, enum nl80211_iftype); + +bool net_match_config(Set *match_mac, + char * const *match_paths, + char * const *match_drivers, + char * const *match_types, + char * const *match_names, + char * const *match_property, + char * const *match_wifi_iftype, + char * const *match_ssid, + Set *match_bssid, + sd_device *device, + const struct ether_addr *dev_mac, + const char *dev_name, + enum nl80211_iftype wifi_iftype, + const char *ssid, + const struct ether_addr *bssid) { + + const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str; + + if (device) { + (void) sd_device_get_property_value(device, "ID_PATH", &dev_path); + (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver); + (void) sd_device_get_devtype(device, &dev_type); + + if (!dev_name) + (void) sd_device_get_sysname(device, &dev_name); + if (!dev_mac && + sd_device_get_sysattr_value(device, "address", &mac_str) >= 0) + dev_mac = ether_aton(mac_str); + } + + if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac))) + return false; + + if (!net_condition_test_strv(match_paths, dev_path)) + return false; + + if (!net_condition_test_strv(match_drivers, dev_driver)) + return false; + + if (!net_condition_test_strv(match_types, dev_type)) + return false; + + if (!net_condition_test_strv(match_names, dev_name)) + return false; + + if (!net_condition_test_property(match_property, device)) + return false; + + if (!net_condition_test_strv(match_wifi_iftype, wifi_iftype_to_string(wifi_iftype))) + return false; + + if (!net_condition_test_strv(match_ssid, ssid)) + return false; + + if (match_bssid && (!bssid || !set_contains(match_bssid, bssid))) + return false; + + return true; +} + +int config_parse_net_condition(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ConditionType cond = ltype; + Condition **list = data, *c; + bool negate; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + *list = condition_free_list_type(*list, cond); + return 0; + } + + negate = rvalue[0] == '!'; + if (negate) + rvalue++; + + c = condition_new(cond, rvalue, false, negate); + if (!c) + return log_oom(); + + /* Drop previous assignment. */ + *list = condition_free_list_type(*list, cond); + + LIST_PREPEND(conditions, *list, c); + return 0; +} + +int config_parse_match_strv( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const char *p = rvalue; + char ***sv = data; + bool invert; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + *sv = strv_free(*sv); + return 0; + } + + invert = *p == '!'; + p += invert; + + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + if (invert) { + k = strjoin("!", word); + if (!k) + return log_oom(); + } else + k = TAKE_PTR(word); + + r = strv_consume(sv, TAKE_PTR(k)); + if (r < 0) + return log_oom(); + } +} + +int config_parse_match_ifnames( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const char *p = rvalue; + char ***sv = data; + bool invert; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + invert = *p == '!'; + p += invert; + + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, NULL, 0); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse interface name list: %s", rvalue); + return 0; + } + + if (!ifname_valid(word)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Interface name is not valid or too long, ignoring assignment: %s", word); + continue; + } + + if (invert) { + k = strjoin("!", word); + if (!k) + return log_oom(); + } else + k = TAKE_PTR(word); + + r = strv_consume(sv, TAKE_PTR(k)); + if (r < 0) + return log_oom(); + } +} + +int config_parse_match_property( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const char *p = rvalue; + char ***sv = data; + bool invert; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + invert = *p == '!'; + p += invert; + + for (;;) { + _cleanup_free_ char *word = NULL, *k = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE); + if (r == 0) + return 0; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + if (!env_assignment_is_valid(word)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid property or value, ignoring assignment: %s", word); + continue; + } + + if (invert) { + k = strjoin("!", word); + if (!k) + return log_oom(); + } else + k = TAKE_PTR(word); + + r = strv_consume(sv, TAKE_PTR(k)); + if (r < 0) + return log_oom(); + } +} + +int config_parse_ifalias(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char **s = data; + _cleanup_free_ char *n = NULL; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + n = strdup(rvalue); + if (!n) + return log_oom(); + + if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue); + return 0; + } + + if (isempty(n)) + *s = mfree(*s); + else + free_and_replace(*s, n); + + return 0; +} + +int config_parse_hwaddr(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ struct ether_addr *n = NULL; + struct ether_addr **hwaddr = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + n = new0(struct ether_addr, 1); + if (!n) + return log_oom(); + + r = ether_addr_from_string(rvalue, n); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue); + return 0; + } + + free_and_replace(*hwaddr, n); + + return 0; +} + +int config_parse_hwaddrs(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_set_free_free_ Set *s = NULL; + const char *p = rvalue; + Set **hwaddrs = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty assignment resets the list */ + *hwaddrs = set_free_free(*hwaddrs); + return 0; + } + + s = set_new(ðer_addr_hash_ops); + if (!s) + return log_oom(); + + for (;;) { + _cleanup_free_ char *word = NULL; + _cleanup_free_ struct ether_addr *n = NULL; + + r = extract_first_word(&p, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + n = new(struct ether_addr, 1); + if (!n) + return log_oom(); + + r = ether_addr_from_string(word, n); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring: %s", word); + continue; + } + + r = set_put(s, n); + if (r < 0) + return log_oom(); + if (r > 0) + n = NULL; /* avoid cleanup */ + } + + r = set_ensure_allocated(hwaddrs, ðer_addr_hash_ops); + if (r < 0) + return log_oom(); + + r = set_move(*hwaddrs, s); + if (r < 0) + return log_oom(); + + return 0; +} + +int config_parse_bridge_port_priority( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint16_t i; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou16(rvalue, &i); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse bridge port priority, ignoring: %s", rvalue); + return 0; + } + + if (i > LINK_BRIDGE_PORT_PRIORITY_MAX) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Bridge port priority is larger than maximum %u, ignoring: %s", LINK_BRIDGE_PORT_PRIORITY_MAX, rvalue); + return 0; + } + + *((uint16_t *)data) = i; + + return 0; +} + +size_t serialize_in_addrs(FILE *f, + const struct in_addr *addresses, + size_t size, + bool with_leading_space, + bool (*predicate)(const struct in_addr *addr)) { + size_t count; + size_t i; + + assert(f); + assert(addresses); + + count = 0; + + for (i = 0; i < size; i++) { + char sbuf[INET_ADDRSTRLEN]; + + if (predicate && !predicate(&addresses[i])) + continue; + if (with_leading_space) + fputc(' ', f); + else + with_leading_space = true; + fputs(inet_ntop(AF_INET, &addresses[i], sbuf, sizeof(sbuf)), f); + count++; + } + + return count; +} + +int deserialize_in_addrs(struct in_addr **ret, const char *string) { + _cleanup_free_ struct in_addr *addresses = NULL; + int size = 0; + + assert(ret); + assert(string); + + for (;;) { + _cleanup_free_ char *word = NULL; + struct in_addr *new_addresses; + int r; + + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + new_addresses = reallocarray(addresses, size + 1, sizeof(struct in_addr)); + if (!new_addresses) + return -ENOMEM; + else + addresses = new_addresses; + + r = inet_pton(AF_INET, word, &(addresses[size])); + if (r <= 0) + continue; + + size++; + } + + *ret = size > 0 ? TAKE_PTR(addresses) : NULL; + + return size; +} + +void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size) { + unsigned i; + + assert(f); + assert(addresses); + assert(size); + + for (i = 0; i < size; i++) { + char buffer[INET6_ADDRSTRLEN]; + + fputs(inet_ntop(AF_INET6, addresses+i, buffer, sizeof(buffer)), f); + + if (i < size - 1) + fputc(' ', f); + } +} + +int deserialize_in6_addrs(struct in6_addr **ret, const char *string) { + _cleanup_free_ struct in6_addr *addresses = NULL; + int size = 0; + + assert(ret); + assert(string); + + for (;;) { + _cleanup_free_ char *word = NULL; + struct in6_addr *new_addresses; + int r; + + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + new_addresses = reallocarray(addresses, size + 1, sizeof(struct in6_addr)); + if (!new_addresses) + return -ENOMEM; + else + addresses = new_addresses; + + r = inet_pton(AF_INET6, word, &(addresses[size])); + if (r <= 0) + continue; + + size++; + } + + *ret = TAKE_PTR(addresses); + + return size; +} + +void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) { + unsigned i; + + assert(f); + assert(key); + assert(routes); + assert(size); + + fprintf(f, "%s=", key); + + for (i = 0; i < size; i++) { + char sbuf[INET_ADDRSTRLEN]; + struct in_addr dest, gw; + uint8_t length; + + assert_se(sd_dhcp_route_get_destination(routes[i], &dest) >= 0); + assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0); + assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0); + + fprintf(f, "%s/%" PRIu8, inet_ntop(AF_INET, &dest, sbuf, sizeof(sbuf)), length); + fprintf(f, ",%s%s", inet_ntop(AF_INET, &gw, sbuf, sizeof(sbuf)), (i < (size - 1)) ? " ": ""); + } + + fputs("\n", f); +} + +int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) { + _cleanup_free_ struct sd_dhcp_route *routes = NULL; + size_t size = 0, allocated = 0; + + assert(ret); + assert(ret_size); + assert(ret_allocated); + assert(string); + + /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */ + for (;;) { + _cleanup_free_ char *word = NULL; + char *tok, *tok_end; + unsigned n; + int r; + + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + if (!GREEDY_REALLOC(routes, allocated, size + 1)) + return -ENOMEM; + + tok = word; + + /* get the subnet */ + tok_end = strchr(tok, '/'); + if (!tok_end) + continue; + *tok_end = '\0'; + + r = inet_aton(tok, &routes[size].dst_addr); + if (r == 0) + continue; + + tok = tok_end + 1; + + /* get the prefixlen */ + tok_end = strchr(tok, ','); + if (!tok_end) + continue; + + *tok_end = '\0'; + + r = safe_atou(tok, &n); + if (r < 0 || n > 32) + continue; + + routes[size].dst_prefixlen = (uint8_t) n; + tok = tok_end + 1; + + /* get the gateway */ + r = inet_aton(tok, &routes[size].gw_addr); + if (r == 0) + continue; + + size++; + } + + *ret_size = size; + *ret_allocated = allocated; + *ret = TAKE_PTR(routes); + + return 0; +} + +int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) { + _cleanup_free_ char *hex_buf = NULL; + + assert(f); + assert(key); + assert(data); + + hex_buf = hexmem(data, size); + if (!hex_buf) + return -ENOMEM; + + fprintf(f, "%s=%s\n", key, hex_buf); + + return 0; +} diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h new file mode 100644 index 00000000..7875f690 --- /dev/null +++ b/src/libsystemd-network/network-internal.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-device.h" +#include "sd-dhcp-lease.h" + +#include "conf-parser.h" +#include "def.h" +#include "set.h" +#include "strv.h" + +#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128 +#define LINK_BRIDGE_PORT_PRIORITY_MAX 63 + +bool net_match_config(Set *match_mac, + char * const *match_path, + char * const *match_driver, + char * const *match_type, + char * const *match_name, + char * const *match_property, + char * const *match_wifi_iftype, + char * const *match_ssid, + Set *match_bssid, + sd_device *device, + const struct ether_addr *dev_mac, + const char *dev_name, + enum nl80211_iftype wifi_iftype, + const char *ssid, + const struct ether_addr *bssid); + +CONFIG_PARSER_PROTOTYPE(config_parse_net_condition); +CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr); +CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs); +CONFIG_PARSER_PROTOTYPE(config_parse_match_strv); +CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames); +CONFIG_PARSER_PROTOTYPE(config_parse_match_property); +CONFIG_PARSER_PROTOTYPE(config_parse_ifalias); +CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority); + +int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result); +const char *net_get_name_persistent(sd_device *device); + +size_t serialize_in_addrs(FILE *f, + const struct in_addr *addresses, + size_t size, + bool with_leading_space, + bool (*predicate)(const struct in_addr *addr)); +int deserialize_in_addrs(struct in_addr **addresses, const char *string); +void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, + size_t size); +int deserialize_in6_addrs(struct in6_addr **addresses, const char *string); + +/* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */ +struct sd_dhcp_route; + +void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size); +int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string); + +/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */ +int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size); + +#define NETWORK_DIRS ((const char* const*) CONF_PATHS_STRV("systemd/network")) diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h new file mode 100644 index 00000000..fb6617be --- /dev/null +++ b/src/libsystemd-network/radv-internal.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2017 Intel Corporation. All rights reserved. +***/ + +#include "sd-radv.h" + +#include "log.h" +#include "list.h" +#include "sparse-endian.h" + +assert_cc(SD_RADV_DEFAULT_MIN_TIMEOUT_USEC <= SD_RADV_DEFAULT_MAX_TIMEOUT_USEC); + +#define SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC (16*USEC_PER_SEC) +#define SD_RADV_MAX_INITIAL_RTR_ADVERTISEMENTS 3 +#define SD_RADV_MAX_FINAL_RTR_ADVERTISEMENTS 3 +#define SD_RADV_MIN_DELAY_BETWEEN_RAS 3 +#define SD_RADV_MAX_RA_DELAY_TIME_USEC (500*USEC_PER_MSEC) + +#define SD_RADV_OPT_ROUTE_INFORMATION 24 +#define SD_RADV_OPT_RDNSS 25 +#define SD_RADV_OPT_DNSSL 31 + +enum RAdvState { + SD_RADV_STATE_IDLE = 0, + SD_RADV_STATE_ADVERTISING = 1, +}; +typedef enum RAdvState RAdvState; + +struct sd_radv_opt_dns { + uint8_t type; + uint8_t length; + uint16_t reserved; + be32_t lifetime; +} _packed_; + +struct sd_radv { + unsigned n_ref; + RAdvState state; + + int ifindex; + + sd_event *event; + int event_priority; + + struct ether_addr mac_addr; + uint8_t hop_limit; + uint8_t flags; + uint32_t mtu; + uint16_t lifetime; + + int fd; + unsigned ra_sent; + sd_event_source *recv_event_source; + sd_event_source *timeout_event_source; + + unsigned n_prefixes; + LIST_HEAD(sd_radv_prefix, prefixes); + + unsigned n_route_prefixes; + LIST_HEAD(sd_radv_route_prefix, route_prefixes); + + size_t n_rdnss; + struct sd_radv_opt_dns *rdnss; + struct sd_radv_opt_dns *dnssl; +}; + +#define radv_prefix_opt__contents { \ + uint8_t type; \ + uint8_t length; \ + uint8_t prefixlen; \ + uint8_t flags; \ + be32_t valid_lifetime; \ + be32_t preferred_lifetime; \ + uint32_t reserved; \ + struct in6_addr in6_addr; \ +} + +struct radv_prefix_opt radv_prefix_opt__contents; + +/* We need the opt substructure to be packed, because we use it in send(). But + * if we use _packed_, this means that the structure cannot be used directly in + * normal code in general, because the fields might not be properly aligned. + * But in this particular case, the structure is defined in a way that gives + * proper alignment, even without the explicit _packed_ attribute. To appease + * the compiler we use the "unpacked" structure, but we also verify that + * structure contains no holes, so offsets are the same when _packed_ is used. + */ +struct radv_prefix_opt__packed radv_prefix_opt__contents _packed_; +assert_cc(sizeof(struct radv_prefix_opt) == sizeof(struct radv_prefix_opt__packed)); + +struct sd_radv_prefix { + unsigned n_ref; + + struct radv_prefix_opt opt; + + LIST_FIELDS(struct sd_radv_prefix, prefix); + + usec_t valid_until; + usec_t preferred_until; +}; + +#define radv_route_prefix_opt__contents { \ + uint8_t type; \ + uint8_t length; \ + uint8_t prefixlen; \ + uint8_t flags_reserved; \ + be32_t lifetime; \ + struct in6_addr in6_addr; \ +} + +struct radv_route_prefix_opt radv_route_prefix_opt__contents; + +struct radv_route_prefix_opt__packed radv_route_prefix_opt__contents _packed_; +assert_cc(sizeof(struct radv_route_prefix_opt) == sizeof(struct radv_route_prefix_opt__packed)); + +struct sd_radv_route_prefix { + unsigned n_ref; + + struct radv_route_prefix_opt opt; + + LIST_FIELDS(struct sd_radv_route_prefix, prefix); +}; + +#define log_radv_full(level, error, fmt, ...) log_internal(level, error, PROJECT_FILE, __LINE__, __func__, "RADV: " fmt, ##__VA_ARGS__) +#define log_radv_errno(error, fmt, ...) log_radv_full(LOG_DEBUG, error, fmt, ##__VA_ARGS__) +#define log_radv(fmt, ...) log_radv_errno(0, fmt, ##__VA_ARGS__) diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c new file mode 100644 index 00000000..901985fc --- /dev/null +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -0,0 +1,2072 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include +#include +#include +#include + +#include "sd-dhcp-client.h" + +#include "alloc-util.h" +#include "async.h" +#include "dhcp-identifier.h" +#include "dhcp-internal.h" +#include "dhcp-lease-internal.h" +#include "dhcp-protocol.h" +#include "dns-domain.h" +#include "event-util.h" +#include "hostname-util.h" +#include "io-util.h" +#include "memory-util.h" +#include "random-util.h" +#include "string-util.h" +#include "strv.h" + +#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */ +#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN) + +#define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC) +#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE) + +struct sd_dhcp_client { + unsigned n_ref; + + DHCPState state; + sd_event *event; + int event_priority; + sd_event_source *timeout_resend; + int ifindex; + int fd; + uint16_t port; + union sockaddr_union link; + sd_event_source *receive_message; + bool request_broadcast; + uint8_t *req_opts; + size_t req_opts_allocated; + size_t req_opts_size; + bool anonymize; + be32_t last_addr; + uint8_t mac_addr[MAX_MAC_ADDR_LEN]; + size_t mac_addr_len; + uint16_t arp_type; + struct { + uint8_t type; + union { + struct { + /* 0: Generic (non-LL) (RFC 2132) */ + uint8_t data[MAX_CLIENT_ID_LEN]; + } _packed_ gen; + struct { + /* 1: Ethernet Link-Layer (RFC 2132) */ + uint8_t haddr[ETH_ALEN]; + } _packed_ eth; + struct { + /* 2 - 254: ARP/Link-Layer (RFC 2132) */ + uint8_t haddr[0]; + } _packed_ ll; + struct { + /* 255: Node-specific (RFC 4361) */ + be32_t iaid; + struct duid duid; + } _packed_ ns; + struct { + uint8_t data[MAX_CLIENT_ID_LEN]; + } _packed_ raw; + }; + } _packed_ client_id; + size_t client_id_len; + char *hostname; + char *vendor_class_identifier; + char **user_class; + uint32_t mtu; + uint32_t xid; + usec_t start_time; + uint64_t attempt; + uint64_t max_attempts; + OrderedHashmap *options; + usec_t request_sent; + sd_event_source *timeout_t1; + sd_event_source *timeout_t2; + sd_event_source *timeout_expire; + sd_dhcp_client_callback_t callback; + void *userdata; + sd_dhcp_lease *lease; + usec_t start_delay; + int ip_service_type; +}; + +static const uint8_t default_req_opts[] = { + SD_DHCP_OPTION_SUBNET_MASK, + SD_DHCP_OPTION_ROUTER, + SD_DHCP_OPTION_HOST_NAME, + SD_DHCP_OPTION_DOMAIN_NAME, + SD_DHCP_OPTION_DOMAIN_NAME_SERVER, +}; + +/* RFC7844 section 3: + MAY contain the Parameter Request List option. + RFC7844 section 3.6: + The client intending to protect its privacy SHOULD only request a + minimal number of options in the PRL and SHOULD also randomly shuffle + the ordering of option codes in the PRL. If this random ordering + cannot be implemented, the client MAY order the option codes in the + PRL by option code number (lowest to highest). +*/ +/* NOTE: using PRL options that Windows 10 RFC7844 implementation uses */ +static const uint8_t default_req_opts_anonymize[] = { + SD_DHCP_OPTION_SUBNET_MASK, /* 1 */ + SD_DHCP_OPTION_ROUTER, /* 3 */ + SD_DHCP_OPTION_DOMAIN_NAME_SERVER, /* 6 */ + SD_DHCP_OPTION_DOMAIN_NAME, /* 15 */ + SD_DHCP_OPTION_ROUTER_DISCOVER, /* 31 */ + SD_DHCP_OPTION_STATIC_ROUTE, /* 33 */ + SD_DHCP_OPTION_VENDOR_SPECIFIC, /* 43 */ + SD_DHCP_OPTION_NETBIOS_NAMESERVER, /* 44 */ + SD_DHCP_OPTION_NETBIOS_NODETYPE, /* 46 */ + SD_DHCP_OPTION_NETBIOS_SCOPE, /* 47 */ + SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, /* 121 */ + SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE, /* 249 */ + SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY, /* 252 */ +}; + +static int client_receive_message_raw( + sd_event_source *s, + int fd, + uint32_t revents, + void *userdata); +static int client_receive_message_udp( + sd_event_source *s, + int fd, + uint32_t revents, + void *userdata); +static void client_stop(sd_dhcp_client *client, int error); + +int sd_dhcp_client_set_callback( + sd_dhcp_client *client, + sd_dhcp_client_callback_t cb, + void *userdata) { + + assert_return(client, -EINVAL); + + client->callback = cb; + client->userdata = userdata; + + return 0; +} + +int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) { + assert_return(client, -EINVAL); + + client->request_broadcast = !!broadcast; + + return 0; +} + +int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) { + size_t i; + + assert_return(client, -EINVAL); + assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); + + switch(option) { + + case SD_DHCP_OPTION_PAD: + case SD_DHCP_OPTION_OVERLOAD: + case SD_DHCP_OPTION_MESSAGE_TYPE: + case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST: + case SD_DHCP_OPTION_END: + return -EINVAL; + + default: + break; + } + + for (i = 0; i < client->req_opts_size; i++) + if (client->req_opts[i] == option) + return -EEXIST; + + if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated, + client->req_opts_size + 1)) + return -ENOMEM; + + client->req_opts[client->req_opts_size++] = option; + + return 0; +} + +int sd_dhcp_client_set_request_address( + sd_dhcp_client *client, + const struct in_addr *last_addr) { + + assert_return(client, -EINVAL); + assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); + + if (last_addr) + client->last_addr = last_addr->s_addr; + else + client->last_addr = INADDR_ANY; + + return 0; +} + +int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) { + + assert_return(client, -EINVAL); + assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); + assert_return(ifindex > 0, -EINVAL); + + client->ifindex = ifindex; + return 0; +} + +int sd_dhcp_client_set_mac( + sd_dhcp_client *client, + const uint8_t *addr, + size_t addr_len, + uint16_t arp_type) { + + DHCP_CLIENT_DONT_DESTROY(client); + bool need_restart = false; + int r; + + assert_return(client, -EINVAL); + assert_return(addr, -EINVAL); + assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); + assert_return(arp_type > 0, -EINVAL); + + if (arp_type == ARPHRD_ETHER) + assert_return(addr_len == ETH_ALEN, -EINVAL); + else if (arp_type == ARPHRD_INFINIBAND) + assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); + else + return -EINVAL; + + if (client->mac_addr_len == addr_len && + memcmp(&client->mac_addr, addr, addr_len) == 0) + return 0; + + if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { + log_dhcp_client(client, "Changing MAC address on running DHCP client, restarting"); + need_restart = true; + client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); + } + + memcpy(&client->mac_addr, addr, addr_len); + client->mac_addr_len = addr_len; + client->arp_type = arp_type; + + if (need_restart && client->state != DHCP_STATE_STOPPED) { + r = sd_dhcp_client_start(client); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); + } + + return 0; +} + +int sd_dhcp_client_get_client_id( + sd_dhcp_client *client, + uint8_t *type, + const uint8_t **data, + size_t *data_len) { + + assert_return(client, -EINVAL); + assert_return(type, -EINVAL); + assert_return(data, -EINVAL); + assert_return(data_len, -EINVAL); + + *type = 0; + *data = NULL; + *data_len = 0; + if (client->client_id_len) { + *type = client->client_id.type; + *data = client->client_id.raw.data; + *data_len = client->client_id_len - sizeof(client->client_id.type); + } + + return 0; +} + +int sd_dhcp_client_set_client_id( + sd_dhcp_client *client, + uint8_t type, + const uint8_t *data, + size_t data_len) { + + DHCP_CLIENT_DONT_DESTROY(client); + bool need_restart = false; + int r; + + assert_return(client, -EINVAL); + assert_return(data, -EINVAL); + assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL); + + if (client->client_id_len == data_len + sizeof(client->client_id.type) && + client->client_id.type == type && + memcmp(&client->client_id.raw.data, data, data_len) == 0) + return 0; + + /* For hardware types, log debug message about unexpected data length. + * + * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only + * last last 8 bytes of the address are stable and suitable to put into + * the client-id. The caller is advised to account for that. */ + if ((type == ARPHRD_ETHER && data_len != ETH_ALEN) || + (type == ARPHRD_INFINIBAND && data_len != 8)) + log_dhcp_client(client, "Changing client ID to hardware type %u with " + "unexpected address length %zu", + type, data_len); + + if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { + log_dhcp_client(client, "Changing client ID on running DHCP " + "client, restarting"); + need_restart = true; + client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); + } + + client->client_id.type = type; + memcpy(&client->client_id.raw.data, data, data_len); + client->client_id_len = data_len + sizeof (client->client_id.type); + + if (need_restart && client->state != DHCP_STATE_STOPPED) { + r = sd_dhcp_client_start(client); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); + } + + return 0; +} + +/** + * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid + * without further modification. Otherwise, if duid_type is supported, DUID + * is set based on that type. Otherwise, an error is returned. + */ +static int dhcp_client_set_iaid_duid_internal( + sd_dhcp_client *client, + bool iaid_append, + bool iaid_set, + uint32_t iaid, + uint16_t duid_type, + const void *duid, + size_t duid_len, + usec_t llt_time) { + + DHCP_CLIENT_DONT_DESTROY(client); + int r; + size_t len; + + assert_return(client, -EINVAL); + assert_return(duid_len == 0 || duid, -EINVAL); + + if (duid) { + r = dhcp_validate_duid_len(duid_type, duid_len, true); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to validate length of DUID: %m"); + } + + zero(client->client_id); + client->client_id.type = 255; + + if (iaid_append) { + if (iaid_set) + client->client_id.ns.iaid = htobe32(iaid); + else { + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, + client->mac_addr_len, + true, + &client->client_id.ns.iaid); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to set IAID: %m"); + } + } + + if (duid) { + client->client_id.ns.duid.type = htobe16(duid_type); + memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len); + len = sizeof(client->client_id.ns.duid.type) + duid_len; + } else + switch (duid_type) { + case DUID_TYPE_LLT: + if (client->mac_addr_len == 0) + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set."); + + r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &len); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to set DUID-LLT: %m"); + break; + case DUID_TYPE_EN: + r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to set DUID-EN: %m"); + break; + case DUID_TYPE_LL: + if (client->mac_addr_len == 0) + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set."); + + r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to set DUID-LL: %m"); + break; + case DUID_TYPE_UUID: + r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to set DUID-UUID: %m"); + break; + default: + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type"); + } + + client->client_id_len = sizeof(client->client_id.type) + len + + (iaid_append ? sizeof(client->client_id.ns.iaid) : 0); + + if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { + log_dhcp_client(client, "Configured %sDUID, restarting.", iaid_append ? "IAID+" : ""); + client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); + r = sd_dhcp_client_start(client); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); + } + + return 0; +} + +int sd_dhcp_client_set_iaid_duid( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid, + uint16_t duid_type, + const void *duid, + size_t duid_len) { + return dhcp_client_set_iaid_duid_internal(client, true, iaid_set, iaid, duid_type, duid, duid_len, 0); +} + +int sd_dhcp_client_set_iaid_duid_llt( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid, + usec_t llt_time) { + return dhcp_client_set_iaid_duid_internal(client, true, iaid_set, iaid, DUID_TYPE_LLT, NULL, 0, llt_time); +} + +int sd_dhcp_client_set_duid( + sd_dhcp_client *client, + uint16_t duid_type, + const void *duid, + size_t duid_len) { + return dhcp_client_set_iaid_duid_internal(client, false, false, 0, duid_type, duid, duid_len, 0); +} + +int sd_dhcp_client_set_duid_llt( + sd_dhcp_client *client, + usec_t llt_time) { + return dhcp_client_set_iaid_duid_internal(client, false, false, 0, DUID_TYPE_LLT, NULL, 0, llt_time); +} + +int sd_dhcp_client_set_hostname( + sd_dhcp_client *client, + const char *hostname) { + + assert_return(client, -EINVAL); + + /* Make sure hostnames qualify as DNS and as Linux hostnames */ + if (hostname && + !(hostname_is_valid(hostname, false) && dns_name_is_valid(hostname) > 0)) + return -EINVAL; + + return free_and_strdup(&client->hostname, hostname); +} + +int sd_dhcp_client_set_vendor_class_identifier( + sd_dhcp_client *client, + const char *vci) { + + assert_return(client, -EINVAL); + + return free_and_strdup(&client->vendor_class_identifier, vci); +} + +int sd_dhcp_client_set_user_class( + sd_dhcp_client *client, + const char* const* user_class) { + + _cleanup_strv_free_ char **s = NULL; + char **p; + + STRV_FOREACH(p, (char **) user_class) + if (strlen(*p) > 255) + return -ENAMETOOLONG; + + s = strv_copy((char **) user_class); + if (!s) + return -ENOMEM; + + client->user_class = TAKE_PTR(s); + + return 0; +} + +int sd_dhcp_client_set_client_port( + sd_dhcp_client *client, + uint16_t port) { + + assert_return(client, -EINVAL); + + client->port = port; + + return 0; +} + +int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) { + assert_return(client, -EINVAL); + assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE); + + client->mtu = mtu; + + return 0; +} + +int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) { + assert_return(client, -EINVAL); + + client->max_attempts = max_attempts; + + return 0; +} + +int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v) { + int r; + + assert_return(client, -EINVAL); + assert_return(v, -EINVAL); + + r = ordered_hashmap_ensure_allocated(&client->options, &dhcp_option_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(client->options, UINT_TO_PTR(v->option), v); + if (r < 0) + return r; + + sd_dhcp_option_ref(v); + return 0; +} + +int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { + assert_return(client, -EINVAL); + + if (!IN_SET(client->state, DHCP_STATE_SELECTING, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING)) + return -EADDRNOTAVAIL; + + if (ret) + *ret = client->lease; + + return 0; +} + +int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) { + assert_return(client, -EINVAL); + + client->ip_service_type = type; + + return 0; +} + +static int client_notify(sd_dhcp_client *client, int event) { + assert(client); + + if (client->callback) + return client->callback(client, event, client->userdata); + + return 0; +} + +static int client_initialize(sd_dhcp_client *client) { + assert_return(client, -EINVAL); + + client->receive_message = sd_event_source_unref(client->receive_message); + + client->fd = asynchronous_close(client->fd); + + (void) event_source_disable(client->timeout_resend); + (void) event_source_disable(client->timeout_t1); + (void) event_source_disable(client->timeout_t2); + (void) event_source_disable(client->timeout_expire); + + client->attempt = 0; + + client->state = DHCP_STATE_INIT; + client->xid = 0; + + client->lease = sd_dhcp_lease_unref(client->lease); + + return 0; +} + +static void client_stop(sd_dhcp_client *client, int error) { + assert(client); + + if (error < 0) + log_dhcp_client_errno(client, error, "STOPPED: %m"); + else if (error == SD_DHCP_CLIENT_EVENT_STOP) + log_dhcp_client(client, "STOPPED"); + else + log_dhcp_client(client, "STOPPED: Unknown event"); + + client_notify(client, error); + + client_initialize(client); +} + +static int client_message_init( + sd_dhcp_client *client, + DHCPPacket **ret, + uint8_t type, + size_t *_optlen, + size_t *_optoffset) { + + _cleanup_free_ DHCPPacket *packet = NULL; + size_t optlen, optoffset, size; + be16_t max_size; + usec_t time_now; + uint16_t secs; + int r; + + assert(client); + assert(client->start_time); + assert(ret); + assert(_optlen); + assert(_optoffset); + assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE)); + + optlen = DHCP_MIN_OPTIONS_SIZE; + size = sizeof(DHCPPacket) + optlen; + + packet = malloc0(size); + if (!packet) + return -ENOMEM; + + r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type, + client->arp_type, optlen, &optoffset); + if (r < 0) + return r; + + /* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers + refuse to issue an DHCP lease if 'secs' is set to zero */ + r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return r; + assert(time_now >= client->start_time); + + /* seconds between sending first and last DISCOVER + * must always be strictly positive to deal with broken servers */ + secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1; + packet->dhcp.secs = htobe16(secs); + + /* RFC2132 section 4.1 + A client that cannot receive unicast IP datagrams until its protocol + software has been configured with an IP address SHOULD set the + BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or + DHCPREQUEST messages that client sends. The BROADCAST bit will + provide a hint to the DHCP server and BOOTP relay agent to broadcast + any messages to the client on the client's subnet. + + Note: some interfaces needs this to be enabled, but some networks + needs this to be disabled as broadcasts are filteretd, so this + needs to be configurable */ + if (client->request_broadcast || client->arp_type != ARPHRD_ETHER) + packet->dhcp.flags = htobe16(0x8000); + + /* RFC2132 section 4.1.1: + The client MUST include its hardware address in the ’chaddr’ field, if + necessary for delivery of DHCP reply messages. Non-Ethernet + interfaces will leave 'chaddr' empty and use the client identifier + instead (eg, RFC 4390 section 2.1). + */ + if (client->arp_type == ARPHRD_ETHER) + memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN); + + /* If no client identifier exists, construct an RFC 4361-compliant one */ + if (client->client_id_len == 0) { + size_t duid_len; + + client->client_id.type = 255; + + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, + true, &client->client_id.ns.iaid); + if (r < 0) + return r; + + r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &duid_len); + if (r < 0) + return r; + + client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len; + } + + /* Some DHCP servers will refuse to issue an DHCP lease if the Client + Identifier option is not set */ + if (client->client_id_len) { + r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_CLIENT_IDENTIFIER, + client->client_id_len, + &client->client_id); + if (r < 0) + return r; + } + + /* RFC2131 section 3.5: + in its initial DHCPDISCOVER or DHCPREQUEST message, a + client may provide the server with a list of specific + parameters the client is interested in. If the client + includes a list of parameters in a DHCPDISCOVER message, + it MUST include that list in any subsequent DHCPREQUEST + messages. + */ + + /* RFC7844 section 3: + MAY contain the Parameter Request List option. */ + /* NOTE: in case that there would be an option to do not send + * any PRL at all, the size should be checked before sending */ + if (client->req_opts_size > 0 && type != DHCP_RELEASE) { + r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_PARAMETER_REQUEST_LIST, + client->req_opts_size, client->req_opts); + if (r < 0) + return r; + } + + /* RFC2131 section 3.5: + The client SHOULD include the ’maximum DHCP message size’ option to + let the server know how large the server may make its DHCP messages. + + Note (from ConnMan): Some DHCP servers will send bigger DHCP packets + than the defined default size unless the Maximum Message Size option + is explicitly set + + RFC3442 "Requirements to Avoid Sizing Constraints": + Because a full routing table can be quite large, the standard 576 + octet maximum size for a DHCP message may be too short to contain + some legitimate Classless Static Route options. Because of this, + clients implementing the Classless Static Route option SHOULD send a + Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP + stack is capable of receiving larger IP datagrams. In this case, the + client SHOULD set the value of this option to at least the MTU of the + interface that the client is configuring. The client MAY set the + value of this option higher, up to the size of the largest UDP packet + it is prepared to accept. (Note that the value specified in the + Maximum DHCP Message Size option is the total maximum packet size, + including IP and UDP headers.) + */ + /* RFC7844 section 3: + SHOULD NOT contain any other option. */ + if (!client->anonymize && type != DHCP_RELEASE) { + max_size = htobe16(size); + r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0, + SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE, + 2, &max_size); + if (r < 0) + return r; + } + + *_optlen = optlen; + *_optoffset = optoffset; + *ret = TAKE_PTR(packet); + + return 0; +} + +static int client_append_fqdn_option( + DHCPMessage *message, + size_t optlen, + size_t *optoffset, + const char *fqdn) { + + uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH]; + int r; + + buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */ + DHCP_FQDN_FLAG_E; /* Canonical wire format */ + buffer[1] = 0; /* RCODE1 (deprecated) */ + buffer[2] = 0; /* RCODE2 (deprecated) */ + + r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false); + if (r > 0) + r = dhcp_option_append(message, optlen, optoffset, 0, + SD_DHCP_OPTION_FQDN, 3 + r, buffer); + + return r; +} + +static int dhcp_client_send_raw( + sd_dhcp_client *client, + DHCPPacket *packet, + size_t len) { + + dhcp_packet_append_ip_headers(packet, INADDR_ANY, client->port, + INADDR_BROADCAST, DHCP_PORT_SERVER, len, client->ip_service_type); + + return dhcp_network_send_raw_socket(client->fd, &client->link, + packet, len); +} + +static int client_send_discover(sd_dhcp_client *client) { + _cleanup_free_ DHCPPacket *discover = NULL; + size_t optoffset, optlen; + sd_dhcp_option *j; + Iterator i; + int r; + + assert(client); + assert(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_SELECTING)); + + r = client_message_init(client, &discover, DHCP_DISCOVER, + &optlen, &optoffset); + if (r < 0) + return r; + + /* the client may suggest values for the network address + and lease time in the DHCPDISCOVER message. The client may include + the ’requested IP address’ option to suggest that a particular IP + address be assigned, and may include the ’IP address lease time’ + option to suggest the lease time it would like. + */ + /* RFC7844 section 3: + SHOULD NOT contain any other option. */ + if (!client->anonymize && client->last_addr != INADDR_ANY) { + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, + 4, &client->last_addr); + if (r < 0) + return r; + } + + if (client->hostname) { + /* According to RFC 4702 "clients that send the Client FQDN option in + their messages MUST NOT also send the Host Name option". Just send + one of the two depending on the hostname type. + */ + if (dns_name_is_single_label(client->hostname)) { + /* it is unclear from RFC 2131 if client should send hostname in + DHCPDISCOVER but dhclient does and so we do as well + */ + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_HOST_NAME, + strlen(client->hostname), client->hostname); + } else + r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset, + client->hostname); + if (r < 0) + return r; + } + + if (client->vendor_class_identifier) { + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER, + strlen(client->vendor_class_identifier), + client->vendor_class_identifier); + if (r < 0) + return r; + } + + if (client->user_class) { + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_USER_CLASS, + strv_length(client->user_class), + client->user_class); + if (r < 0) + return r; + } + + ORDERED_HASHMAP_FOREACH(j, client->options, i) { + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + j->option, j->length, j->data); + if (r < 0) + return r; + } + + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; + + /* We currently ignore: + The client SHOULD wait a random time between one and ten seconds to + desynchronize the use of DHCP at startup. + */ + r = dhcp_client_send_raw(client, discover, sizeof(DHCPPacket) + optoffset); + if (r < 0) + return r; + + log_dhcp_client(client, "DISCOVER"); + + return 0; +} + +static int client_send_request(sd_dhcp_client *client) { + _cleanup_free_ DHCPPacket *request = NULL; + size_t optoffset, optlen; + int r; + + assert(client); + + r = client_message_init(client, &request, DHCP_REQUEST, &optlen, &optoffset); + if (r < 0) + return r; + + switch (client->state) { + /* See RFC2131 section 4.3.2 (note that there is a typo in the RFC, + SELECTING should be REQUESTING) + */ + + case DHCP_STATE_REQUESTING: + /* Client inserts the address of the selected server in ’server + identifier’, ’ciaddr’ MUST be zero, ’requested IP address’ MUST be + filled in with the yiaddr value from the chosen DHCPOFFER. + */ + + r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_SERVER_IDENTIFIER, + 4, &client->lease->server_address); + if (r < 0) + return r; + + r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, + 4, &client->lease->address); + if (r < 0) + return r; + + break; + + case DHCP_STATE_INIT_REBOOT: + /* ’server identifier’ MUST NOT be filled in, ’requested IP address’ + option MUST be filled in with client’s notion of its previously + assigned address. ’ciaddr’ MUST be zero. + */ + r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, + 4, &client->last_addr); + if (r < 0) + return r; + break; + + case DHCP_STATE_RENEWING: + /* ’server identifier’ MUST NOT be filled in, ’requested IP address’ + option MUST NOT be filled in, ’ciaddr’ MUST be filled in with + client’s IP address. + */ + + case DHCP_STATE_REBINDING: + /* ’server identifier’ MUST NOT be filled in, ’requested IP address’ + option MUST NOT be filled in, ’ciaddr’ MUST be filled in with + client’s IP address. + + This message MUST be broadcast to the 0xffffffff IP broadcast address. + */ + request->dhcp.ciaddr = client->lease->address; + + break; + + case DHCP_STATE_INIT: + case DHCP_STATE_SELECTING: + case DHCP_STATE_REBOOTING: + case DHCP_STATE_BOUND: + case DHCP_STATE_STOPPED: + return -EINVAL; + } + + if (client->hostname) { + if (dns_name_is_single_label(client->hostname)) + r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_HOST_NAME, + strlen(client->hostname), client->hostname); + else + r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset, + client->hostname); + if (r < 0) + return r; + } + + if (client->vendor_class_identifier) { + r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER, + strlen(client->vendor_class_identifier), + client->vendor_class_identifier); + if (r < 0) + return r; + } + + r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; + + if (client->state == DHCP_STATE_RENEWING) + r = dhcp_network_send_udp_socket(client->fd, + client->lease->server_address, + DHCP_PORT_SERVER, + &request->dhcp, + sizeof(DHCPMessage) + optoffset); + else + r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset); + if (r < 0) + return r; + + switch (client->state) { + + case DHCP_STATE_REQUESTING: + log_dhcp_client(client, "REQUEST (requesting)"); + break; + + case DHCP_STATE_INIT_REBOOT: + log_dhcp_client(client, "REQUEST (init-reboot)"); + break; + + case DHCP_STATE_RENEWING: + log_dhcp_client(client, "REQUEST (renewing)"); + break; + + case DHCP_STATE_REBINDING: + log_dhcp_client(client, "REQUEST (rebinding)"); + break; + + default: + log_dhcp_client(client, "REQUEST (invalid)"); + break; + } + + return 0; +} + +static int client_start(sd_dhcp_client *client); + +static int client_timeout_resend( + sd_event_source *s, + uint64_t usec, + void *userdata) { + + sd_dhcp_client *client = userdata; + DHCP_CLIENT_DONT_DESTROY(client); + usec_t next_timeout = 0; + uint64_t time_now; + uint32_t time_left; + int r; + + assert(s); + assert(client); + assert(client->event); + + r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + goto error; + + switch (client->state) { + + case DHCP_STATE_RENEWING: + + time_left = (client->lease->t2 - client->lease->t1) / 2; + if (time_left < 60) + time_left = 60; + + next_timeout = time_now + time_left * USEC_PER_SEC; + + break; + + case DHCP_STATE_REBINDING: + + time_left = (client->lease->lifetime - client->lease->t2) / 2; + if (time_left < 60) + time_left = 60; + + next_timeout = time_now + time_left * USEC_PER_SEC; + break; + + case DHCP_STATE_REBOOTING: + /* start over as we did not receive a timely ack or nak */ + r = client_initialize(client); + if (r < 0) + goto error; + + r = client_start(client); + if (r < 0) + goto error; + else { + log_dhcp_client(client, "REBOOTED"); + return 0; + } + + case DHCP_STATE_INIT: + case DHCP_STATE_INIT_REBOOT: + case DHCP_STATE_SELECTING: + case DHCP_STATE_REQUESTING: + case DHCP_STATE_BOUND: + + if (client->attempt < client->max_attempts) + client->attempt++; + else + goto error; + + next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC; + + break; + + case DHCP_STATE_STOPPED: + r = -EINVAL; + goto error; + } + + next_timeout += (random_u32() & 0x1fffff); + + r = event_reset_time(client->event, &client->timeout_resend, + clock_boottime_or_monotonic(), + next_timeout, 10 * USEC_PER_MSEC, + client_timeout_resend, client, + client->event_priority, "dhcp4-resend-timer", true); + if (r < 0) + goto error; + + switch (client->state) { + case DHCP_STATE_INIT: + r = client_send_discover(client); + if (r >= 0) { + client->state = DHCP_STATE_SELECTING; + client->attempt = 0; + } else if (client->attempt >= client->max_attempts) + goto error; + + break; + + case DHCP_STATE_SELECTING: + r = client_send_discover(client); + if (r < 0 && client->attempt >= client->max_attempts) + goto error; + + break; + + case DHCP_STATE_INIT_REBOOT: + case DHCP_STATE_REQUESTING: + case DHCP_STATE_RENEWING: + case DHCP_STATE_REBINDING: + r = client_send_request(client); + if (r < 0 && client->attempt >= client->max_attempts) + goto error; + + if (client->state == DHCP_STATE_INIT_REBOOT) + client->state = DHCP_STATE_REBOOTING; + + client->request_sent = time_now; + + break; + + case DHCP_STATE_REBOOTING: + case DHCP_STATE_BOUND: + + break; + + case DHCP_STATE_STOPPED: + r = -EINVAL; + goto error; + } + + return 0; + +error: + client_stop(client, r); + + /* Errors were dealt with when stopping the client, don't spill + errors into the event loop handler */ + return 0; +} + +static int client_initialize_io_events( + sd_dhcp_client *client, + sd_event_io_handler_t io_callback) { + + int r; + + assert(client); + assert(client->event); + + r = sd_event_add_io(client->event, &client->receive_message, + client->fd, EPOLLIN, io_callback, + client); + if (r < 0) + goto error; + + r = sd_event_source_set_priority(client->receive_message, + client->event_priority); + if (r < 0) + goto error; + + r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message"); + if (r < 0) + goto error; + +error: + if (r < 0) + client_stop(client, r); + + return 0; +} + +static int client_initialize_time_events(sd_dhcp_client *client) { + uint64_t usec = 0; + int r; + + assert(client); + assert(client->event); + + if (client->start_delay > 0) { + assert_se(sd_event_now(client->event, clock_boottime_or_monotonic(), &usec) >= 0); + usec += client->start_delay; + } + + r = event_reset_time(client->event, &client->timeout_resend, + clock_boottime_or_monotonic(), + usec, 0, + client_timeout_resend, client, + client->event_priority, "dhcp4-resend-timer", true); + if (r < 0) + client_stop(client, r); + + return 0; + +} + +static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) { + client_initialize_io_events(client, io_callback); + client_initialize_time_events(client); + + return 0; +} + +static int client_start_delayed(sd_dhcp_client *client) { + int r; + + assert_return(client, -EINVAL); + assert_return(client->event, -EINVAL); + assert_return(client->ifindex > 0, -EINVAL); + assert_return(client->fd < 0, -EBUSY); + assert_return(client->xid == 0, -EINVAL); + assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT), -EBUSY); + + client->xid = random_u32(); + + r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, + client->xid, client->mac_addr, + client->mac_addr_len, client->arp_type, client->port); + if (r < 0) { + client_stop(client, r); + return r; + } + client->fd = r; + + if (IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT)) + client->start_time = now(clock_boottime_or_monotonic()); + + return client_initialize_events(client, client_receive_message_raw); +} + +static int client_start(sd_dhcp_client *client) { + client->start_delay = 0; + return client_start_delayed(client); +} + +static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) { + sd_dhcp_client *client = userdata; + DHCP_CLIENT_DONT_DESTROY(client); + + log_dhcp_client(client, "EXPIRED"); + + client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED); + + /* lease was lost, start over if not freed or stopped in callback */ + if (client->state != DHCP_STATE_STOPPED) { + client_initialize(client); + client_start(client); + } + + return 0; +} + +static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) { + sd_dhcp_client *client = userdata; + DHCP_CLIENT_DONT_DESTROY(client); + int r; + + assert(client); + + client->receive_message = sd_event_source_unref(client->receive_message); + client->fd = asynchronous_close(client->fd); + + client->state = DHCP_STATE_REBINDING; + client->attempt = 0; + + r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, + client->xid, client->mac_addr, + client->mac_addr_len, client->arp_type, + client->port); + if (r < 0) { + client_stop(client, r); + return 0; + } + client->fd = r; + + return client_initialize_events(client, client_receive_message_raw); +} + +static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) { + sd_dhcp_client *client = userdata; + DHCP_CLIENT_DONT_DESTROY(client); + + client->state = DHCP_STATE_RENEWING; + client->attempt = 0; + + return client_initialize_time_events(client); +} + +static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) { + _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; + int r; + + r = dhcp_lease_new(&lease); + if (r < 0) + return r; + + if (client->client_id_len) { + r = dhcp_lease_set_client_id(lease, + (uint8_t *) &client->client_id, + client->client_id_len); + if (r < 0) + return r; + } + + r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease, NULL); + if (r != DHCP_OFFER) { + log_dhcp_client(client, "received message was not an OFFER, ignoring"); + return -ENOMSG; + } + + lease->next_server = offer->siaddr; + lease->address = offer->yiaddr; + + if (lease->address == 0 || + lease->server_address == 0 || + lease->lifetime == 0) { + log_dhcp_client(client, "received lease lacks address, server address or lease lifetime, ignoring"); + return -ENOMSG; + } + + if (!lease->have_subnet_mask) { + r = dhcp_lease_set_default_subnet_mask(lease); + if (r < 0) { + log_dhcp_client(client, + "received lease lacks subnet mask, " + "and a fallback one cannot be generated, ignoring"); + return -ENOMSG; + } + } + + sd_dhcp_lease_unref(client->lease); + client->lease = TAKE_PTR(lease); + + if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0) + return -ENOMSG; + + log_dhcp_client(client, "OFFER"); + + return 0; +} + +static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) { + int r; + + r = dhcp_option_parse(force, len, NULL, NULL, NULL); + if (r != DHCP_FORCERENEW) + return -ENOMSG; + + log_dhcp_client(client, "FORCERENEW"); + + return 0; +} + +static bool lease_equal(const sd_dhcp_lease *a, const sd_dhcp_lease *b) { + if (a->address != b->address) + return false; + + if (a->subnet_mask != b->subnet_mask) + return false; + + if (a->router_size != b->router_size) + return false; + + for (size_t i = 0; i < a->router_size; i++) + if (a->router[i].s_addr != b->router[i].s_addr) + return false; + + return true; +} + +static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t len) { + _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; + _cleanup_free_ char *error_message = NULL; + int r; + + r = dhcp_lease_new(&lease); + if (r < 0) + return r; + + if (client->client_id_len) { + r = dhcp_lease_set_client_id(lease, + (uint8_t *) &client->client_id, + client->client_id_len); + if (r < 0) + return r; + } + + r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease, &error_message); + if (r == DHCP_NAK) { + log_dhcp_client(client, "NAK: %s", strna(error_message)); + return -EADDRNOTAVAIL; + } + + if (r != DHCP_ACK) { + log_dhcp_client(client, "received message was not an ACK, ignoring"); + return -ENOMSG; + } + + lease->next_server = ack->siaddr; + + lease->address = ack->yiaddr; + + if (lease->address == INADDR_ANY || + lease->server_address == INADDR_ANY || + lease->lifetime == 0) { + log_dhcp_client(client, "received lease lacks address, server " + "address or lease lifetime, ignoring"); + return -ENOMSG; + } + + if (lease->subnet_mask == INADDR_ANY) { + r = dhcp_lease_set_default_subnet_mask(lease); + if (r < 0) { + log_dhcp_client(client, + "received lease lacks subnet mask, " + "and a fallback one cannot be generated, ignoring"); + return -ENOMSG; + } + } + + r = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE; + if (client->lease) { + if (lease_equal(client->lease, lease)) + r = SD_DHCP_CLIENT_EVENT_RENEW; + else + r = SD_DHCP_CLIENT_EVENT_IP_CHANGE; + + client->lease = sd_dhcp_lease_unref(client->lease); + } + + client->lease = TAKE_PTR(lease); + + log_dhcp_client(client, "ACK"); + + return r; +} + +static uint64_t client_compute_timeout(sd_dhcp_client *client, uint32_t lifetime, double factor) { + assert(client); + assert(client->request_sent); + assert(lifetime > 0); + + if (lifetime > 3) + lifetime -= 3; + else + lifetime = 0; + + return client->request_sent + (lifetime * USEC_PER_SEC * factor) + + + (random_u32() & 0x1fffff); +} + +static int client_set_lease_timeouts(sd_dhcp_client *client) { + usec_t time_now; + uint64_t lifetime_timeout; + uint64_t t2_timeout; + uint64_t t1_timeout; + char time_string[FORMAT_TIMESPAN_MAX]; + int r; + + assert(client); + assert(client->event); + assert(client->lease); + assert(client->lease->lifetime); + + /* don't set timers for infinite leases */ + if (client->lease->lifetime == 0xffffffff) { + (void) event_source_disable(client->timeout_t1); + (void) event_source_disable(client->timeout_t2); + (void) event_source_disable(client->timeout_expire); + + return 0; + } + + r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return r; + assert(client->request_sent <= time_now); + + /* convert the various timeouts from relative (secs) to absolute (usecs) */ + lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1); + if (client->lease->t1 > 0 && client->lease->t2 > 0) { + /* both T1 and T2 are given */ + if (client->lease->t1 < client->lease->t2 && + client->lease->t2 < client->lease->lifetime) { + /* they are both valid */ + t2_timeout = client_compute_timeout(client, client->lease->t2, 1); + t1_timeout = client_compute_timeout(client, client->lease->t1, 1); + } else { + /* discard both */ + t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); + client->lease->t2 = (client->lease->lifetime * 7) / 8; + t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); + client->lease->t1 = client->lease->lifetime / 2; + } + } else if (client->lease->t2 > 0 && client->lease->t2 < client->lease->lifetime) { + /* only T2 is given, and it is valid */ + t2_timeout = client_compute_timeout(client, client->lease->t2, 1); + t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); + client->lease->t1 = client->lease->lifetime / 2; + if (t2_timeout <= t1_timeout) { + /* the computed T1 would be invalid, so discard T2 */ + t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); + client->lease->t2 = (client->lease->lifetime * 7) / 8; + } + } else if (client->lease->t1 > 0 && client->lease->t1 < client->lease->lifetime) { + /* only T1 is given, and it is valid */ + t1_timeout = client_compute_timeout(client, client->lease->t1, 1); + t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); + client->lease->t2 = (client->lease->lifetime * 7) / 8; + if (t2_timeout <= t1_timeout) { + /* the computed T2 would be invalid, so discard T1 */ + t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); + client->lease->t2 = client->lease->lifetime / 2; + } + } else { + /* fall back to the default timeouts */ + t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); + client->lease->t1 = client->lease->lifetime / 2; + t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); + client->lease->t2 = (client->lease->lifetime * 7) / 8; + } + + /* arm lifetime timeout */ + r = event_reset_time(client->event, &client->timeout_expire, + clock_boottime_or_monotonic(), + lifetime_timeout, 10 * USEC_PER_MSEC, + client_timeout_expire, client, + client->event_priority, "dhcp4-lifetime", true); + if (r < 0) + return r; + + log_dhcp_client(client, "lease expires in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_timeout - time_now, USEC_PER_SEC)); + + /* don't arm earlier timeouts if this has already expired */ + if (lifetime_timeout <= time_now) + return 0; + + /* arm T2 timeout */ + r = event_reset_time(client->event, &client->timeout_t2, + clock_boottime_or_monotonic(), + t2_timeout, 10 * USEC_PER_MSEC, + client_timeout_t2, client, + client->event_priority, "dhcp4-t2-timeout", true); + if (r < 0) + return r; + + log_dhcp_client(client, "T2 expires in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, t2_timeout - time_now, USEC_PER_SEC)); + + /* don't arm earlier timeout if this has already expired */ + if (t2_timeout <= time_now) + return 0; + + /* arm T1 timeout */ + r = event_reset_time(client->event, &client->timeout_t1, + clock_boottime_or_monotonic(), + t1_timeout, 10 * USEC_PER_MSEC, + client_timeout_t1, client, + client->event_priority, "dhcp4-t1-timer", true); + if (r < 0) + return r; + + log_dhcp_client(client, "T1 expires in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, t1_timeout - time_now, USEC_PER_SEC)); + + return 0; +} + +static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) { + DHCP_CLIENT_DONT_DESTROY(client); + char time_string[FORMAT_TIMESPAN_MAX]; + int r = 0, notify_event = 0; + + assert(client); + assert(client->event); + assert(message); + + switch (client->state) { + case DHCP_STATE_SELECTING: + + r = client_handle_offer(client, message, len); + if (r >= 0) { + + client->state = DHCP_STATE_REQUESTING; + client->attempt = 0; + + r = event_reset_time(client->event, &client->timeout_resend, + clock_boottime_or_monotonic(), + 0, 0, + client_timeout_resend, client, + client->event_priority, "dhcp4-resend-timer", true); + if (r < 0) + goto error; + } else if (r == -ENOMSG) + /* invalid message, let's ignore it */ + return 0; + + break; + + case DHCP_STATE_REBOOTING: + case DHCP_STATE_REQUESTING: + case DHCP_STATE_RENEWING: + case DHCP_STATE_REBINDING: + + r = client_handle_ack(client, message, len); + if (r >= 0) { + client->start_delay = 0; + (void) event_source_disable(client->timeout_resend); + client->receive_message = + sd_event_source_unref(client->receive_message); + client->fd = asynchronous_close(client->fd); + + if (IN_SET(client->state, DHCP_STATE_REQUESTING, + DHCP_STATE_REBOOTING)) + notify_event = SD_DHCP_CLIENT_EVENT_IP_ACQUIRE; + else if (r != SD_DHCP_CLIENT_EVENT_IP_ACQUIRE) + notify_event = r; + + client->state = DHCP_STATE_BOUND; + client->attempt = 0; + + client->last_addr = client->lease->address; + + r = client_set_lease_timeouts(client); + if (r < 0) { + log_dhcp_client(client, "could not set lease timeouts"); + goto error; + } + + r = dhcp_network_bind_udp_socket(client->ifindex, client->lease->address, client->port, client->ip_service_type); + if (r < 0) { + log_dhcp_client(client, "could not bind UDP socket"); + goto error; + } + + client->fd = r; + + client_initialize_io_events(client, client_receive_message_udp); + + if (notify_event) { + client_notify(client, notify_event); + if (client->state == DHCP_STATE_STOPPED) + return 0; + } + + } else if (r == -EADDRNOTAVAIL) { + /* got a NAK, let's restart the client */ + client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED); + + r = client_initialize(client); + if (r < 0) + goto error; + + r = client_start_delayed(client); + if (r < 0) + goto error; + + log_dhcp_client(client, "REBOOT in %s", format_timespan(time_string, FORMAT_TIMESPAN_MAX, + client->start_delay, USEC_PER_SEC)); + + client->start_delay = CLAMP(client->start_delay * 2, + RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC); + + return 0; + } else if (r == -ENOMSG) + /* invalid message, let's ignore it */ + return 0; + + break; + + case DHCP_STATE_BOUND: + r = client_handle_forcerenew(client, message, len); + if (r >= 0) { + r = client_timeout_t1(NULL, 0, client); + if (r < 0) + goto error; + } else if (r == -ENOMSG) + /* invalid message, let's ignore it */ + return 0; + + break; + + case DHCP_STATE_INIT: + case DHCP_STATE_INIT_REBOOT: + + break; + + case DHCP_STATE_STOPPED: + r = -EINVAL; + goto error; + } + +error: + if (r < 0) + client_stop(client, r); + + return r; +} + +static int client_receive_message_udp( + sd_event_source *s, + int fd, + uint32_t revents, + void *userdata) { + + sd_dhcp_client *client = userdata; + _cleanup_free_ DHCPMessage *message = NULL; + const uint8_t *expected_chaddr = NULL; + uint8_t expected_hlen = 0; + ssize_t len, buflen; + + assert(s); + assert(client); + + buflen = next_datagram_size_fd(fd); + if (buflen == -ENETDOWN) { + /* the link is down. Don't return an error or the I/O event + source will be disconnected and we won't be able to receive + packets again when the link comes back. */ + return 0; + } + if (buflen < 0) + return buflen; + + message = malloc0(buflen); + if (!message) + return -ENOMEM; + + len = recv(fd, message, buflen, 0); + if (len < 0) { + /* see comment above for why we shouldn't error out on ENETDOWN. */ + if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN)) + return 0; + + return log_dhcp_client_errno(client, errno, + "Could not receive message from UDP socket: %m"); + } + if ((size_t) len < sizeof(DHCPMessage)) { + log_dhcp_client(client, "Too small to be a DHCP message: ignoring"); + return 0; + } + + if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) { + log_dhcp_client(client, "Not a DHCP message: ignoring"); + return 0; + } + + if (message->op != BOOTREPLY) { + log_dhcp_client(client, "Not a BOOTREPLY message: ignoring"); + return 0; + } + + if (message->htype != client->arp_type) { + log_dhcp_client(client, "Packet type does not match client type"); + return 0; + } + + if (client->arp_type == ARPHRD_ETHER) { + expected_hlen = ETH_ALEN; + expected_chaddr = &client->mac_addr[0]; + } + + if (message->hlen != expected_hlen) { + log_dhcp_client(client, "Unexpected packet hlen %d", message->hlen); + return 0; + } + + if (expected_hlen > 0 && memcmp(&message->chaddr[0], expected_chaddr, expected_hlen)) { + log_dhcp_client(client, "Received chaddr does not match expected: ignoring"); + return 0; + } + + if (client->state != DHCP_STATE_BOUND && + be32toh(message->xid) != client->xid) { + /* in BOUND state, we may receive FORCERENEW with xid set by server, + so ignore the xid in this case */ + log_dhcp_client(client, "Received xid (%u) does not match expected (%u): ignoring", + be32toh(message->xid), client->xid); + return 0; + } + + return client_handle_message(client, message, len); +} + +static int client_receive_message_raw( + sd_event_source *s, + int fd, + uint32_t revents, + void *userdata) { + + sd_dhcp_client *client = userdata; + _cleanup_free_ DHCPPacket *packet = NULL; + uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; + struct iovec iov = {}; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cmsgbuf, + .msg_controllen = sizeof(cmsgbuf), + }; + struct cmsghdr *cmsg; + bool checksum = true; + ssize_t buflen, len; + int r; + + assert(s); + assert(client); + + buflen = next_datagram_size_fd(fd); + if (buflen == -ENETDOWN) + return 0; + if (buflen < 0) + return buflen; + + packet = malloc0(buflen); + if (!packet) + return -ENOMEM; + + iov = IOVEC_MAKE(packet, buflen); + + len = recvmsg(fd, &msg, 0); + if (len < 0) { + if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN)) + return 0; + + return log_dhcp_client_errno(client, errno, + "Could not receive message from raw socket: %m"); + } else if ((size_t)len < sizeof(DHCPPacket)) + return 0; + + CMSG_FOREACH(cmsg, &msg) + if (cmsg->cmsg_level == SOL_PACKET && + cmsg->cmsg_type == PACKET_AUXDATA && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct tpacket_auxdata))) { + struct tpacket_auxdata *aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg); + + checksum = !(aux->tp_status & TP_STATUS_CSUMNOTREADY); + break; + } + + r = dhcp_packet_verify_headers(packet, len, checksum, client->port); + if (r < 0) + return 0; + + len -= DHCP_IP_UDP_SIZE; + + return client_handle_message(client, &packet->dhcp, len); +} + +int sd_dhcp_client_send_renew(sd_dhcp_client *client) { + assert_return(client, -EINVAL); + assert_return(client->fd >= 0, -EINVAL); + + client->start_delay = 0; + client->attempt = 1; + client->state = DHCP_STATE_RENEWING; + + return client_initialize_time_events(client); +} + +int sd_dhcp_client_start(sd_dhcp_client *client) { + int r; + + assert_return(client, -EINVAL); + + r = client_initialize(client); + if (r < 0) + return r; + + /* RFC7844 section 3.3: + SHOULD perform a complete four-way handshake, starting with a + DHCPDISCOVER, to obtain a new address lease. If the client can + ascertain that this is exactly the same network to which it was + previously connected, and if the link-layer address did not change, + the client MAY issue a DHCPREQUEST to try to reclaim the current + address. */ + if (client->last_addr && !client->anonymize) + client->state = DHCP_STATE_INIT_REBOOT; + + r = client_start(client); + if (r >= 0) + log_dhcp_client(client, "STARTED on ifindex %i", client->ifindex); + + return r; +} + +int sd_dhcp_client_send_release(sd_dhcp_client *client) { + assert_return(client, -EINVAL); + assert_return(client->state != DHCP_STATE_STOPPED, -ESTALE); + assert_return(client->lease, -EUNATCH); + + _cleanup_free_ DHCPPacket *release = NULL; + size_t optoffset, optlen; + int r; + + r = client_message_init(client, &release, DHCP_RELEASE, &optlen, &optoffset); + if (r < 0) + return r; + + /* Fill up release IP and MAC */ + release->dhcp.ciaddr = client->lease->address; + memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len); + + r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; + + r = dhcp_network_send_udp_socket(client->fd, + client->lease->server_address, + DHCP_PORT_SERVER, + &release->dhcp, + sizeof(DHCPMessage) + optoffset); + if (r < 0) + return r; + + log_dhcp_client(client, "RELEASE"); + + return 0; +} + +int sd_dhcp_client_stop(sd_dhcp_client *client) { + DHCP_CLIENT_DONT_DESTROY(client); + + assert_return(client, -EINVAL); + + client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); + client->state = DHCP_STATE_STOPPED; + + return 0; +} + +int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority) { + int r; + + assert_return(client, -EINVAL); + assert_return(!client->event, -EBUSY); + + if (event) + client->event = sd_event_ref(event); + else { + r = sd_event_default(&client->event); + if (r < 0) + return 0; + } + + client->event_priority = priority; + + return 0; +} + +int sd_dhcp_client_detach_event(sd_dhcp_client *client) { + assert_return(client, -EINVAL); + + client->event = sd_event_unref(client->event); + + return 0; +} + +sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) { + assert_return(client, NULL); + + return client->event; +} + +static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) { + if (!client) + return NULL; + + log_dhcp_client(client, "FREE"); + + client->timeout_resend = sd_event_source_unref(client->timeout_resend); + client->timeout_t1 = sd_event_source_unref(client->timeout_t1); + client->timeout_t2 = sd_event_source_unref(client->timeout_t2); + client->timeout_expire = sd_event_source_unref(client->timeout_expire); + + client_initialize(client); + + sd_dhcp_client_detach_event(client); + + sd_dhcp_lease_unref(client->lease); + + free(client->req_opts); + free(client->hostname); + free(client->vendor_class_identifier); + client->user_class = strv_free(client->user_class); + ordered_hashmap_free(client->options); + return mfree(client); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free); + +int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { + assert_return(ret, -EINVAL); + + _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = new(sd_dhcp_client, 1); + if (!client) + return -ENOMEM; + + *client = (sd_dhcp_client) { + .n_ref = 1, + .state = DHCP_STATE_INIT, + .ifindex = -1, + .fd = -1, + .mtu = DHCP_DEFAULT_MIN_SIZE, + .port = DHCP_PORT_CLIENT, + .anonymize = !!anonymize, + .max_attempts = (uint64_t) -1, + .ip_service_type = -1, + }; + /* NOTE: this could be moved to a function. */ + if (anonymize) { + client->req_opts_size = ELEMENTSOF(default_req_opts_anonymize); + client->req_opts = memdup(default_req_opts_anonymize, client->req_opts_size); + } else { + client->req_opts_size = ELEMENTSOF(default_req_opts); + client->req_opts = memdup(default_req_opts, client->req_opts_size); + } + if (!client->req_opts) + return -ENOMEM; + + *ret = TAKE_PTR(client); + + return 0; +} diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c new file mode 100644 index 00000000..48e8aad8 --- /dev/null +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -0,0 +1,1358 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include +#include +#include + +#include "sd-dhcp-lease.h" + +#include "alloc-util.h" +#include "dhcp-lease-internal.h" +#include "dhcp-protocol.h" +#include "dns-domain.h" +#include "env-file.h" +#include "fd-util.h" +#include "fileio.h" +#include "hexdecoct.h" +#include "hostname-util.h" +#include "in-addr-util.h" +#include "network-internal.h" +#include "parse-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "unaligned.h" + +int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (lease->address == 0) + return -ENODATA; + + addr->s_addr = lease->address; + return 0; +} + +int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (!lease->have_broadcast) + return -ENODATA; + + addr->s_addr = lease->broadcast; + return 0; +} + +int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) { + assert_return(lease, -EINVAL); + assert_return(lifetime, -EINVAL); + + if (lease->lifetime <= 0) + return -ENODATA; + + *lifetime = lease->lifetime; + return 0; +} + +int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) { + assert_return(lease, -EINVAL); + assert_return(t1, -EINVAL); + + if (lease->t1 <= 0) + return -ENODATA; + + *t1 = lease->t1; + return 0; +} + +int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) { + assert_return(lease, -EINVAL); + assert_return(t2, -EINVAL); + + if (lease->t2 <= 0) + return -ENODATA; + + *t2 = lease->t2; + return 0; +} + +int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) { + assert_return(lease, -EINVAL); + assert_return(mtu, -EINVAL); + + if (lease->mtu <= 0) + return -ENODATA; + + *mtu = lease->mtu; + return 0; +} + +int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (lease->dns_size <= 0) + return -ENODATA; + + *addr = lease->dns; + return (int) lease->dns_size; +} + +int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (lease->ntp_size <= 0) + return -ENODATA; + + *addr = lease->ntp; + return (int) lease->ntp_size; +} + +int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (lease->sip_size <= 0) + return -ENODATA; + + *addr = lease->sip; + return (int) lease->sip_size; +} + +int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { + assert_return(lease, -EINVAL); + assert_return(domainname, -EINVAL); + + if (!lease->domainname) + return -ENODATA; + + *domainname = lease->domainname; + return 0; +} + +int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) { + assert_return(lease, -EINVAL); + assert_return(hostname, -EINVAL); + + if (!lease->hostname) + return -ENODATA; + + *hostname = lease->hostname; + return 0; +} + +int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) { + assert_return(lease, -EINVAL); + assert_return(root_path, -EINVAL); + + if (!lease->root_path) + return -ENODATA; + + *root_path = lease->root_path; + return 0; +} + +int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (lease->router_size <= 0) + return -ENODATA; + + *addr = lease->router; + return (int) lease->router_size; +} + +int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (!lease->have_subnet_mask) + return -ENODATA; + + addr->s_addr = lease->subnet_mask; + return 0; +} + +int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (lease->server_address == 0) + return -ENODATA; + + addr->s_addr = lease->server_address; + return 0; +} + +int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (lease->next_server == 0) + return -ENODATA; + + addr->s_addr = lease->next_server; + return 0; +} + +/* + * The returned routes array must be freed by the caller. + * Route objects have the same lifetime of the lease and must not be freed. + */ +int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) { + sd_dhcp_route **ret; + unsigned i; + + assert_return(lease, -EINVAL); + assert_return(routes, -EINVAL); + + if (lease->static_route_size <= 0) + return -ENODATA; + + ret = new(sd_dhcp_route *, lease->static_route_size); + if (!ret) + return -ENOMEM; + + for (i = 0; i < lease->static_route_size; i++) + ret[i] = &lease->static_route[i]; + + *routes = ret; + return (int) lease->static_route_size; +} + +int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) { + size_t r; + + assert_return(lease, -EINVAL); + assert_return(domains, -EINVAL); + + r = strv_length(lease->search_domains); + if (r > 0) { + *domains = lease->search_domains; + return (int) r; + } + + return -ENODATA; +} + +int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) { + assert_return(lease, -EINVAL); + assert_return(data, -EINVAL); + assert_return(data_len, -EINVAL); + + if (lease->vendor_specific_len <= 0) + return -ENODATA; + + *data = lease->vendor_specific; + *data_len = lease->vendor_specific_len; + return 0; +} + +static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) { + assert(lease); + + while (lease->private_options) { + struct sd_dhcp_raw_option *option = lease->private_options; + + LIST_REMOVE(options, lease->private_options, option); + + free(option->data); + free(option); + } + + free(lease->root_path); + free(lease->router); + free(lease->timezone); + free(lease->hostname); + free(lease->domainname); + free(lease->dns); + free(lease->ntp); + free(lease->sip); + free(lease->static_route); + free(lease->client_id); + free(lease->vendor_specific); + strv_free(lease->search_domains); + return mfree(lease); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_lease, sd_dhcp_lease, dhcp_lease_free); + +static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) { + assert(option); + assert(ret); + + if (len != 4) + return -EINVAL; + + *ret = unaligned_read_be32((be32_t*) option); + if (*ret < min) + *ret = min; + + return 0; +} + +static int lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) { + assert(option); + assert(ret); + + if (len != 2) + return -EINVAL; + + *ret = unaligned_read_be16((be16_t*) option); + if (*ret < min) + *ret = min; + + return 0; +} + +static int lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) { + assert(option); + assert(ret); + + if (len != 4) + return -EINVAL; + + memcpy(ret, option, 4); + return 0; +} + +static int lease_parse_string(const uint8_t *option, size_t len, char **ret) { + assert(option); + assert(ret); + + if (len <= 0) + *ret = mfree(*ret); + else { + char *string; + + /* + * One trailing NUL byte is OK, we don't mind. See: + * https://github.com/systemd/systemd/issues/1337 + */ + if (memchr(option, 0, len - 1)) + return -EINVAL; + + string = memdup_suffix0((const char *) option, len); + if (!string) + return -ENOMEM; + + free_and_replace(*ret, string); + } + + return 0; +} + +static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) { + _cleanup_free_ char *name = NULL, *normalized = NULL; + int r; + + assert(option); + assert(ret); + + r = lease_parse_string(option, len, &name); + if (r < 0) + return r; + if (!name) { + *ret = mfree(*ret); + return 0; + } + + r = dns_name_normalize(name, 0, &normalized); + if (r < 0) + return r; + + if (is_localhost(normalized)) + return -EINVAL; + + if (dns_name_is_root(normalized)) + return -EINVAL; + + free_and_replace(*ret, normalized); + + return 0; +} + +static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) { + assert(option); + assert(ret); + assert(n_ret); + + if (len <= 0) { + *ret = mfree(*ret); + *n_ret = 0; + } else { + size_t n_addresses; + struct in_addr *addresses; + + if (len % 4 != 0) + return -EINVAL; + + n_addresses = len / 4; + + addresses = newdup(struct in_addr, option, n_addresses); + if (!addresses) + return -ENOMEM; + + free(*ret); + *ret = addresses; + *n_ret = n_addresses; + } + + return 0; +} + +static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) { + assert(option); + assert(ret); + assert(n_ret); + + if (len <= 0) { + *ret = mfree(*ret); + *n_ret = 0; + } else { + size_t n_addresses; + struct in_addr *addresses; + int l = len - 1; + + if (l % 4 != 0) + return -EINVAL; + + n_addresses = l / 4; + + addresses = newdup(struct in_addr, option + 1, n_addresses); + if (!addresses) + return -ENOMEM; + + free(*ret); + *ret = addresses; + *n_ret = n_addresses; + } + + return 0; +} + +static int lease_parse_routes( + const uint8_t *option, size_t len, + struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) { + + struct in_addr addr; + + assert(option || len <= 0); + assert(routes); + assert(routes_size); + assert(routes_allocated); + + if (len <= 0) + return 0; + + if (len % 8 != 0) + return -EINVAL; + + if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + (len / 8))) + return -ENOMEM; + + while (len >= 8) { + struct sd_dhcp_route *route = *routes + *routes_size; + int r; + + route->option = SD_DHCP_OPTION_STATIC_ROUTE; + r = in4_addr_default_prefixlen((struct in_addr*) option, &route->dst_prefixlen); + if (r < 0) { + log_debug("Failed to determine destination prefix length from class based IP, ignoring"); + continue; + } + + assert_se(lease_parse_be32(option, 4, &addr.s_addr) >= 0); + route->dst_addr = inet_makeaddr(inet_netof(addr), 0); + option += 4; + + assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0); + option += 4; + + len -= 8; + (*routes_size)++; + } + + return 0; +} + +/* parses RFC3442 Classless Static Route Option */ +static int lease_parse_classless_routes( + const uint8_t *option, size_t len, + struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) { + + assert(option || len <= 0); + assert(routes); + assert(routes_size); + assert(routes_allocated); + + if (len <= 0) + return 0; + + /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */ + + while (len > 0) { + uint8_t dst_octets; + struct sd_dhcp_route *route; + + if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + 1)) + return -ENOMEM; + + route = *routes + *routes_size; + route->option = SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE; + + dst_octets = (*option == 0 ? 0 : ((*option - 1) / 8) + 1); + route->dst_prefixlen = *option; + option++; + len--; + + /* can't have more than 4 octets in IPv4 */ + if (dst_octets > 4 || len < dst_octets) + return -EINVAL; + + route->dst_addr.s_addr = 0; + memcpy(&route->dst_addr.s_addr, option, dst_octets); + option += dst_octets; + len -= dst_octets; + + if (len < 4) + return -EINVAL; + + assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0); + option += 4; + len -= 4; + + (*routes_size)++; + } + + return 0; +} + +int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata) { + sd_dhcp_lease *lease = userdata; + int r; + + assert(lease); + + switch(code) { + + case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME: + r = lease_parse_u32(option, len, &lease->lifetime, 1); + if (r < 0) + log_debug_errno(r, "Failed to parse lease time, ignoring: %m"); + + break; + + case SD_DHCP_OPTION_SERVER_IDENTIFIER: + r = lease_parse_be32(option, len, &lease->server_address); + if (r < 0) + log_debug_errno(r, "Failed to parse server identifier, ignoring: %m"); + + break; + + case SD_DHCP_OPTION_SUBNET_MASK: + r = lease_parse_be32(option, len, &lease->subnet_mask); + if (r < 0) + log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m"); + else + lease->have_subnet_mask = true; + break; + + case SD_DHCP_OPTION_BROADCAST: + r = lease_parse_be32(option, len, &lease->broadcast); + if (r < 0) + log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m"); + else + lease->have_broadcast = true; + break; + + case SD_DHCP_OPTION_ROUTER: + r = lease_parse_in_addrs(option, len, &lease->router, &lease->router_size); + if (r < 0) + log_debug_errno(r, "Failed to parse router addresses, ignoring: %m"); + break; + + case SD_DHCP_OPTION_DOMAIN_NAME_SERVER: + r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size); + if (r < 0) + log_debug_errno(r, "Failed to parse DNS server, ignoring: %m"); + break; + + case SD_DHCP_OPTION_NTP_SERVER: + r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size); + if (r < 0) + log_debug_errno(r, "Failed to parse NTP server, ignoring: %m"); + break; + + case SD_DHCP_OPTION_SIP_SERVER: + r = lease_parse_sip_server(option, len, &lease->sip, &lease->sip_size); + if (r < 0) + log_debug_errno(r, "Failed to parse SIP server, ignoring: %m"); + break; + + case SD_DHCP_OPTION_STATIC_ROUTE: + r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated); + if (r < 0) + log_debug_errno(r, "Failed to parse static routes, ignoring: %m"); + break; + + case SD_DHCP_OPTION_INTERFACE_MTU: + r = lease_parse_u16(option, len, &lease->mtu, 68); + if (r < 0) + log_debug_errno(r, "Failed to parse MTU, ignoring: %m"); + if (lease->mtu < DHCP_DEFAULT_MIN_SIZE) { + log_debug("MTU value of %" PRIu16 " too small. Using default MTU value of %d instead.", lease->mtu, DHCP_DEFAULT_MIN_SIZE); + lease->mtu = DHCP_DEFAULT_MIN_SIZE; + } + + break; + + case SD_DHCP_OPTION_DOMAIN_NAME: + r = lease_parse_domain(option, len, &lease->domainname); + if (r < 0) { + log_debug_errno(r, "Failed to parse domain name, ignoring: %m"); + return 0; + } + + break; + + case SD_DHCP_OPTION_DOMAIN_SEARCH_LIST: + r = dhcp_lease_parse_search_domains(option, len, &lease->search_domains); + if (r < 0) + log_debug_errno(r, "Failed to parse Domain Search List, ignoring: %m"); + break; + + case SD_DHCP_OPTION_HOST_NAME: + r = lease_parse_domain(option, len, &lease->hostname); + if (r < 0) { + log_debug_errno(r, "Failed to parse host name, ignoring: %m"); + return 0; + } + + break; + + case SD_DHCP_OPTION_ROOT_PATH: + r = lease_parse_string(option, len, &lease->root_path); + if (r < 0) + log_debug_errno(r, "Failed to parse root path, ignoring: %m"); + break; + + case SD_DHCP_OPTION_RENEWAL_T1_TIME: + r = lease_parse_u32(option, len, &lease->t1, 1); + if (r < 0) + log_debug_errno(r, "Failed to parse T1 time, ignoring: %m"); + break; + + case SD_DHCP_OPTION_REBINDING_T2_TIME: + r = lease_parse_u32(option, len, &lease->t2, 1); + if (r < 0) + log_debug_errno(r, "Failed to parse T2 time, ignoring: %m"); + break; + + case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE: + r = lease_parse_classless_routes( + option, len, + &lease->static_route, + &lease->static_route_size, + &lease->static_route_allocated); + if (r < 0) + log_debug_errno(r, "Failed to parse classless routes, ignoring: %m"); + break; + + case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE: { + _cleanup_free_ char *tz = NULL; + + r = lease_parse_string(option, len, &tz); + if (r < 0) { + log_debug_errno(r, "Failed to parse timezone option, ignoring: %m"); + return 0; + } + + if (!timezone_is_valid(tz, LOG_DEBUG)) { + log_debug_errno(r, "Timezone is not valid, ignoring: %m"); + return 0; + } + + free_and_replace(lease->timezone, tz); + + break; + } + + case SD_DHCP_OPTION_VENDOR_SPECIFIC: + + if (len <= 0) + lease->vendor_specific = mfree(lease->vendor_specific); + else { + void *p; + + p = memdup(option, len); + if (!p) + return -ENOMEM; + + free(lease->vendor_specific); + lease->vendor_specific = p; + } + + lease->vendor_specific_len = len; + break; + + case SD_DHCP_OPTION_PRIVATE_BASE ... SD_DHCP_OPTION_PRIVATE_LAST: + r = dhcp_lease_insert_private_option(lease, code, option, len); + if (r < 0) + return r; + + break; + + default: + log_debug("Ignoring option DHCP option %"PRIu8" while parsing.", code); + break; + } + + return 0; +} + +/* Parses compressed domain names. */ +int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains) { + _cleanup_strv_free_ char **names = NULL; + size_t pos = 0, cnt = 0; + int r; + + assert(domains); + assert_return(option && len > 0, -ENODATA); + + while (pos < len) { + _cleanup_free_ char *name = NULL; + size_t n = 0, allocated = 0; + size_t jump_barrier = pos, next_chunk = 0; + bool first = true; + + for (;;) { + uint8_t c; + c = option[pos++]; + + if (c == 0) { + /* End of name */ + break; + } else if (c <= 63) { + const char *label; + + /* Literal label */ + label = (const char*) (option + pos); + pos += c; + if (pos >= len) + return -EBADMSG; + + if (!GREEDY_REALLOC(name, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) + return -ENOMEM; + + if (first) + first = false; + else + name[n++] = '.'; + + r = dns_label_escape(label, c, name + n, DNS_LABEL_ESCAPED_MAX); + if (r < 0) + return r; + + n += r; + } else if ((c & 0xc0) == 0xc0) { + /* Pointer */ + + uint8_t d; + uint16_t ptr; + + if (pos >= len) + return -EBADMSG; + + d = option[pos++]; + ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d; + + /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */ + if (ptr >= jump_barrier) + return -EBADMSG; + jump_barrier = ptr; + + /* Save current location so we don't end up re-parsing what's parsed so far. */ + if (next_chunk == 0) + next_chunk = pos; + + pos = ptr; + } else + return -EBADMSG; + } + + if (!GREEDY_REALLOC(name, allocated, n + 1)) + return -ENOMEM; + name[n] = 0; + + r = strv_extend(&names, name); + if (r < 0) + return r; + + cnt++; + + if (next_chunk != 0) + pos = next_chunk; + } + + *domains = TAKE_PTR(names); + + return cnt; +} + +int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len) { + struct sd_dhcp_raw_option *cur, *option; + + assert(lease); + + LIST_FOREACH(options, cur, lease->private_options) { + if (tag < cur->tag) + break; + if (tag == cur->tag) { + log_debug("Ignoring duplicate option, tagged %i.", tag); + return 0; + } + } + + option = new(struct sd_dhcp_raw_option, 1); + if (!option) + return -ENOMEM; + + option->tag = tag; + option->length = len; + option->data = memdup(data, len); + if (!option->data) { + free(option); + return -ENOMEM; + } + + LIST_INSERT_BEFORE(options, lease->private_options, cur, option); + return 0; +} + +int dhcp_lease_new(sd_dhcp_lease **ret) { + sd_dhcp_lease *lease; + + lease = new0(sd_dhcp_lease, 1); + if (!lease) + return -ENOMEM; + + lease->n_ref = 1; + + *ret = lease; + return 0; +} + +int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + struct sd_dhcp_raw_option *option; + struct in_addr address; + const struct in_addr *addresses; + const void *client_id, *data; + size_t client_id_len, data_len; + char sbuf[INET_ADDRSTRLEN]; + const char *string; + uint16_t mtu; + _cleanup_free_ sd_dhcp_route **routes = NULL; + char **search_domains = NULL; + uint32_t t1, t2, lifetime; + int r; + + assert(lease); + assert(lease_file); + + r = fopen_temporary(lease_file, &f, &temp_path); + if (r < 0) + goto fail; + + (void) fchmod(fileno(f), 0644); + + fprintf(f, + "# This is private data. Do not parse.\n"); + + r = sd_dhcp_lease_get_address(lease, &address); + if (r >= 0) + fprintf(f, "ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf))); + + r = sd_dhcp_lease_get_netmask(lease, &address); + if (r >= 0) + fprintf(f, "NETMASK=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf))); + + r = sd_dhcp_lease_get_router(lease, &addresses); + if (r > 0) { + fputs("ROUTER=", f); + serialize_in_addrs(f, addresses, r, false, NULL); + fputc('\n', f); + } + + r = sd_dhcp_lease_get_server_identifier(lease, &address); + if (r >= 0) + fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf))); + + r = sd_dhcp_lease_get_next_server(lease, &address); + if (r >= 0) + fprintf(f, "NEXT_SERVER=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf))); + + r = sd_dhcp_lease_get_broadcast(lease, &address); + if (r >= 0) + fprintf(f, "BROADCAST=%s\n", inet_ntop(AF_INET, &address, sbuf, sizeof(sbuf))); + + r = sd_dhcp_lease_get_mtu(lease, &mtu); + if (r >= 0) + fprintf(f, "MTU=%" PRIu16 "\n", mtu); + + r = sd_dhcp_lease_get_t1(lease, &t1); + if (r >= 0) + fprintf(f, "T1=%" PRIu32 "\n", t1); + + r = sd_dhcp_lease_get_t2(lease, &t2); + if (r >= 0) + fprintf(f, "T2=%" PRIu32 "\n", t2); + + r = sd_dhcp_lease_get_lifetime(lease, &lifetime); + if (r >= 0) + fprintf(f, "LIFETIME=%" PRIu32 "\n", lifetime); + + r = sd_dhcp_lease_get_dns(lease, &addresses); + if (r > 0) { + fputs("DNS=", f); + serialize_in_addrs(f, addresses, r, false, NULL); + fputc('\n', f); + } + + r = sd_dhcp_lease_get_ntp(lease, &addresses); + if (r > 0) { + fputs("NTP=", f); + serialize_in_addrs(f, addresses, r, false, NULL); + fputc('\n', f); + } + + r = sd_dhcp_lease_get_sip(lease, &addresses); + if (r > 0) { + fputs("SIP=", f); + serialize_in_addrs(f, addresses, r, false, NULL); + fputc('\n', f); + } + + r = sd_dhcp_lease_get_domainname(lease, &string); + if (r >= 0) + fprintf(f, "DOMAINNAME=%s\n", string); + + r = sd_dhcp_lease_get_search_domains(lease, &search_domains); + if (r > 0) { + fputs("DOMAIN_SEARCH_LIST=", f); + fputstrv(f, search_domains, NULL, NULL); + fputc('\n', f); + } + + r = sd_dhcp_lease_get_hostname(lease, &string); + if (r >= 0) + fprintf(f, "HOSTNAME=%s\n", string); + + r = sd_dhcp_lease_get_root_path(lease, &string); + if (r >= 0) + fprintf(f, "ROOT_PATH=%s\n", string); + + r = sd_dhcp_lease_get_routes(lease, &routes); + if (r > 0) + serialize_dhcp_routes(f, "ROUTES", routes, r); + + r = sd_dhcp_lease_get_timezone(lease, &string); + if (r >= 0) + fprintf(f, "TIMEZONE=%s\n", string); + + r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len); + if (r >= 0) { + _cleanup_free_ char *client_id_hex = NULL; + + client_id_hex = hexmem(client_id, client_id_len); + if (!client_id_hex) { + r = -ENOMEM; + goto fail; + } + fprintf(f, "CLIENTID=%s\n", client_id_hex); + } + + r = sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len); + if (r >= 0) { + _cleanup_free_ char *option_hex = NULL; + + option_hex = hexmem(data, data_len); + if (!option_hex) { + r = -ENOMEM; + goto fail; + } + fprintf(f, "VENDOR_SPECIFIC=%s\n", option_hex); + } + + LIST_FOREACH(options, option, lease->private_options) { + char key[STRLEN("OPTION_000")+1]; + + xsprintf(key, "OPTION_%" PRIu8, option->tag); + r = serialize_dhcp_option(f, key, option->data, option->length); + if (r < 0) + goto fail; + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, lease_file) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + if (temp_path) + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save lease data %s: %m", lease_file); +} + +int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { + + _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; + _cleanup_free_ char + *address = NULL, + *router = NULL, + *netmask = NULL, + *server_address = NULL, + *next_server = NULL, + *broadcast = NULL, + *dns = NULL, + *ntp = NULL, + *sip = NULL, + *mtu = NULL, + *routes = NULL, + *domains = NULL, + *client_id_hex = NULL, + *vendor_specific_hex = NULL, + *lifetime = NULL, + *t1 = NULL, + *t2 = NULL, + *options[SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1] = {}; + + int r, i; + + assert(lease_file); + assert(ret); + + r = dhcp_lease_new(&lease); + if (r < 0) + return r; + + r = parse_env_file(NULL, lease_file, + "ADDRESS", &address, + "ROUTER", &router, + "NETMASK", &netmask, + "SERVER_IDENTIFIER", &server_address, + "NEXT_SERVER", &next_server, + "BROADCAST", &broadcast, + "DNS", &dns, + "NTP", &ntp, + "SIP", &sip, + "MTU", &mtu, + "DOMAINNAME", &lease->domainname, + "HOSTNAME", &lease->hostname, + "DOMAIN_SEARCH_LIST", &domains, + "ROOT_PATH", &lease->root_path, + "ROUTES", &routes, + "CLIENTID", &client_id_hex, + "TIMEZONE", &lease->timezone, + "VENDOR_SPECIFIC", &vendor_specific_hex, + "LIFETIME", &lifetime, + "T1", &t1, + "T2", &t2, + "OPTION_224", &options[0], + "OPTION_225", &options[1], + "OPTION_226", &options[2], + "OPTION_227", &options[3], + "OPTION_228", &options[4], + "OPTION_229", &options[5], + "OPTION_230", &options[6], + "OPTION_231", &options[7], + "OPTION_232", &options[8], + "OPTION_233", &options[9], + "OPTION_234", &options[10], + "OPTION_235", &options[11], + "OPTION_236", &options[12], + "OPTION_237", &options[13], + "OPTION_238", &options[14], + "OPTION_239", &options[15], + "OPTION_240", &options[16], + "OPTION_241", &options[17], + "OPTION_242", &options[18], + "OPTION_243", &options[19], + "OPTION_244", &options[20], + "OPTION_245", &options[21], + "OPTION_246", &options[22], + "OPTION_247", &options[23], + "OPTION_248", &options[24], + "OPTION_249", &options[25], + "OPTION_250", &options[26], + "OPTION_251", &options[27], + "OPTION_252", &options[28], + "OPTION_253", &options[29], + "OPTION_254", &options[30]); + if (r < 0) + return r; + + if (address) { + r = inet_pton(AF_INET, address, &lease->address); + if (r <= 0) + log_debug("Failed to parse address %s, ignoring.", address); + } + + if (router) { + r = deserialize_in_addrs(&lease->router, router); + if (r < 0) + log_debug_errno(r, "Failed to deserialize router addresses %s, ignoring: %m", router); + else + lease->router_size = r; + } + + if (netmask) { + r = inet_pton(AF_INET, netmask, &lease->subnet_mask); + if (r <= 0) + log_debug("Failed to parse netmask %s, ignoring.", netmask); + else + lease->have_subnet_mask = true; + } + + if (server_address) { + r = inet_pton(AF_INET, server_address, &lease->server_address); + if (r <= 0) + log_debug("Failed to parse server address %s, ignoring.", server_address); + } + + if (next_server) { + r = inet_pton(AF_INET, next_server, &lease->next_server); + if (r <= 0) + log_debug("Failed to parse next server %s, ignoring.", next_server); + } + + if (broadcast) { + r = inet_pton(AF_INET, broadcast, &lease->broadcast); + if (r <= 0) + log_debug("Failed to parse broadcast address %s, ignoring.", broadcast); + else + lease->have_broadcast = true; + } + + if (dns) { + r = deserialize_in_addrs(&lease->dns, dns); + if (r < 0) + log_debug_errno(r, "Failed to deserialize DNS servers %s, ignoring: %m", dns); + else + lease->dns_size = r; + } + + if (ntp) { + r = deserialize_in_addrs(&lease->ntp, ntp); + if (r < 0) + log_debug_errno(r, "Failed to deserialize NTP servers %s, ignoring: %m", ntp); + else + lease->ntp_size = r; + } + + if (sip) { + r = deserialize_in_addrs(&lease->sip, sip); + if (r < 0) + log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip); + else + lease->ntp_size = r; + } + + if (mtu) { + r = safe_atou16(mtu, &lease->mtu); + if (r < 0) + log_debug_errno(r, "Failed to parse MTU %s, ignoring: %m", mtu); + } + + if (domains) { + _cleanup_strv_free_ char **a = NULL; + a = strv_split(domains, " "); + if (!a) + return -ENOMEM; + + if (!strv_isempty(a)) { + lease->search_domains = a; + a = NULL; + } + } + + if (routes) { + r = deserialize_dhcp_routes( + &lease->static_route, + &lease->static_route_size, + &lease->static_route_allocated, + routes); + if (r < 0) + log_debug_errno(r, "Failed to parse DHCP routes %s, ignoring: %m", routes); + } + + if (lifetime) { + r = safe_atou32(lifetime, &lease->lifetime); + if (r < 0) + log_debug_errno(r, "Failed to parse lifetime %s, ignoring: %m", lifetime); + } + + if (t1) { + r = safe_atou32(t1, &lease->t1); + if (r < 0) + log_debug_errno(r, "Failed to parse T1 %s, ignoring: %m", t1); + } + + if (t2) { + r = safe_atou32(t2, &lease->t2); + if (r < 0) + log_debug_errno(r, "Failed to parse T2 %s, ignoring: %m", t2); + } + + if (client_id_hex) { + r = unhexmem(client_id_hex, (size_t) -1, &lease->client_id, &lease->client_id_len); + if (r < 0) + log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex); + } + + if (vendor_specific_hex) { + r = unhexmem(vendor_specific_hex, (size_t) -1, &lease->vendor_specific, &lease->vendor_specific_len); + if (r < 0) + log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex); + } + + for (i = 0; i <= SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE; i++) { + _cleanup_free_ void *data = NULL; + size_t len; + + if (!options[i]) + continue; + + r = unhexmem(options[i], (size_t) -1, &data, &len); + if (r < 0) { + log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]); + continue; + } + + r = dhcp_lease_insert_private_option(lease, SD_DHCP_OPTION_PRIVATE_BASE + i, data, len); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(lease); + + return 0; +} + +int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) { + struct in_addr address, mask; + int r; + + assert(lease); + + if (lease->address == 0) + return -ENODATA; + + address.s_addr = lease->address; + + /* fall back to the default subnet masks based on address class */ + r = in4_addr_default_subnet_mask(&address, &mask); + if (r < 0) + return r; + + lease->subnet_mask = mask.s_addr; + lease->have_subnet_mask = true; + + return 0; +} + +int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) { + assert_return(lease, -EINVAL); + assert_return(client_id, -EINVAL); + assert_return(client_id_len, -EINVAL); + + if (!lease->client_id) + return -ENODATA; + + *client_id = lease->client_id; + *client_id_len = lease->client_id_len; + + return 0; +} + +int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len) { + assert_return(lease, -EINVAL); + assert_return(client_id || client_id_len <= 0, -EINVAL); + + if (client_id_len <= 0) + lease->client_id = mfree(lease->client_id); + else { + void *p; + + p = memdup(client_id, client_id_len); + if (!p) + return -ENOMEM; + + free(lease->client_id); + lease->client_id = p; + lease->client_id_len = client_id_len; + } + + return 0; +} + +int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) { + assert_return(lease, -EINVAL); + assert_return(tz, -EINVAL); + + if (!lease->timezone) + return -ENODATA; + + *tz = lease->timezone; + return 0; +} + +int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination) { + assert_return(route, -EINVAL); + assert_return(destination, -EINVAL); + + *destination = route->dst_addr; + return 0; +} + +int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length) { + assert_return(route, -EINVAL); + assert_return(length, -EINVAL); + + *length = route->dst_prefixlen; + return 0; +} + +int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) { + assert_return(route, -EINVAL); + assert_return(gateway, -EINVAL); + + *gateway = route->gw_addr; + return 0; +} + +int sd_dhcp_route_get_option(sd_dhcp_route *route) { + assert_return(route, -EINVAL); + + return route->option; +} diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c new file mode 100644 index 00000000..9e51bf74 --- /dev/null +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -0,0 +1,1202 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include + +#include "sd-dhcp-server.h" + +#include "alloc-util.h" +#include "dhcp-internal.h" +#include "dhcp-server-internal.h" +#include "fd-util.h" +#include "in-addr-util.h" +#include "io-util.h" +#include "sd-id128.h" +#include "siphash24.h" +#include "string-util.h" +#include "unaligned.h" + +#define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR +#define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12) + +static DHCPLease *dhcp_lease_free(DHCPLease *lease) { + if (!lease) + return NULL; + + free(lease->client_id.data); + return mfree(lease); +} + +/* configures the server's address and subnet, and optionally the pool's size and offset into the subnet + * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address + * moreover, the server's own address may be in the pool, and is in that case reserved in order not to + * accidentally hand it out */ +int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *address, unsigned char prefixlen, uint32_t offset, uint32_t size) { + struct in_addr netmask_addr; + be32_t netmask; + uint32_t server_off, broadcast_off, size_max; + + assert_return(server, -EINVAL); + assert_return(address, -EINVAL); + assert_return(address->s_addr != INADDR_ANY, -EINVAL); + assert_return(prefixlen <= 32, -ERANGE); + + assert_se(in4_addr_prefixlen_to_netmask(&netmask_addr, prefixlen)); + netmask = netmask_addr.s_addr; + + server_off = be32toh(address->s_addr & ~netmask); + broadcast_off = be32toh(~netmask); + + /* the server address cannot be the subnet address */ + assert_return(server_off != 0, -ERANGE); + + /* nor the broadcast address */ + assert_return(server_off != broadcast_off, -ERANGE); + + /* 0 offset means we should set a default, we skip the first (subnet) address + and take the next one */ + if (offset == 0) + offset = 1; + + size_max = (broadcast_off + 1) /* the number of addresses in the subnet */ + - offset /* exclude the addresses before the offset */ + - 1; /* exclude the last (broadcast) address */ + + /* The pool must contain at least one address */ + assert_return(size_max >= 1, -ERANGE); + + if (size != 0) + assert_return(size <= size_max, -ERANGE); + else + size = size_max; + + if (server->address != address->s_addr || server->netmask != netmask || server->pool_size != size || server->pool_offset != offset) { + + free(server->bound_leases); + server->bound_leases = new0(DHCPLease*, size); + if (!server->bound_leases) + return -ENOMEM; + + server->pool_offset = offset; + server->pool_size = size; + + server->address = address->s_addr; + server->netmask = netmask; + server->subnet = address->s_addr & netmask; + + if (server_off >= offset && server_off - offset < size) + server->bound_leases[server_off - offset] = &server->invalid_lease; + + /* Drop any leases associated with the old address range */ + hashmap_clear(server->leases_by_client_id); + } + + return 0; +} + +int sd_dhcp_server_is_running(sd_dhcp_server *server) { + assert_return(server, false); + + return !!server->receive_message; +} + +void client_id_hash_func(const DHCPClientId *id, struct siphash *state) { + assert(id); + assert(id->length); + assert(id->data); + + siphash24_compress(&id->length, sizeof(id->length), state); + siphash24_compress(id->data, id->length, state); +} + +int client_id_compare_func(const DHCPClientId *a, const DHCPClientId *b) { + int r; + + assert(!a->length || a->data); + assert(!b->length || b->data); + + r = CMP(a->length, b->length); + if (r != 0) + return r; + + return memcmp(a->data, b->data, a->length); +} + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(dhcp_lease_hash_ops, DHCPClientId, client_id_hash_func, client_id_compare_func, + DHCPLease, dhcp_lease_free); + +static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) { + assert(server); + + log_dhcp_server(server, "UNREF"); + + sd_dhcp_server_stop(server); + + sd_event_unref(server->event); + + free(server->timezone); + free(server->dns); + free(server->ntp); + free(server->sip); + + hashmap_free(server->leases_by_client_id); + + ordered_hashmap_free(server->raw_option); + + free(server->bound_leases); + return mfree(server); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_server, sd_dhcp_server, dhcp_server_free); + +int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) { + _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; + + assert_return(ret, -EINVAL); + assert_return(ifindex > 0, -EINVAL); + + server = new0(sd_dhcp_server, 1); + if (!server) + return -ENOMEM; + + server->n_ref = 1; + server->fd_raw = -1; + server->fd = -1; + server->address = htobe32(INADDR_ANY); + server->netmask = htobe32(INADDR_ANY); + server->ifindex = ifindex; + + server->leases_by_client_id = hashmap_new(&dhcp_lease_hash_ops); + if (!server->leases_by_client_id) + return -ENOMEM; + + server->default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC); + server->max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC); + + *ret = TAKE_PTR(server); + + return 0; +} + +int sd_dhcp_server_attach_event(sd_dhcp_server *server, sd_event *event, int64_t priority) { + int r; + + assert_return(server, -EINVAL); + assert_return(!server->event, -EBUSY); + + if (event) + server->event = sd_event_ref(event); + else { + r = sd_event_default(&server->event); + if (r < 0) + return r; + } + + server->event_priority = priority; + + return 0; +} + +int sd_dhcp_server_detach_event(sd_dhcp_server *server) { + assert_return(server, -EINVAL); + + server->event = sd_event_unref(server->event); + + return 0; +} + +sd_event *sd_dhcp_server_get_event(sd_dhcp_server *server) { + assert_return(server, NULL); + + return server->event; +} + +int sd_dhcp_server_stop(sd_dhcp_server *server) { + assert_return(server, -EINVAL); + + server->receive_message = + sd_event_source_unref(server->receive_message); + + server->fd_raw = safe_close(server->fd_raw); + server->fd = safe_close(server->fd); + + log_dhcp_server(server, "STOPPED"); + + return 0; +} + +static int dhcp_server_send_unicast_raw(sd_dhcp_server *server, + DHCPPacket *packet, size_t len) { + union sockaddr_union link = { + .ll.sll_family = AF_PACKET, + .ll.sll_protocol = htobe16(ETH_P_IP), + .ll.sll_ifindex = server->ifindex, + .ll.sll_halen = ETH_ALEN, + }; + + assert(server); + assert(server->ifindex > 0); + assert(server->address); + assert(packet); + assert(len > sizeof(DHCPPacket)); + + memcpy(&link.ll.sll_addr, &packet->dhcp.chaddr, ETH_ALEN); + + dhcp_packet_append_ip_headers(packet, server->address, DHCP_PORT_SERVER, + packet->dhcp.yiaddr, + DHCP_PORT_CLIENT, len, -1); + + return dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len); +} + +static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination, + uint16_t destination_port, + DHCPMessage *message, size_t len) { + union sockaddr_union dest = { + .in.sin_family = AF_INET, + .in.sin_port = htobe16(destination_port), + .in.sin_addr.s_addr = destination, + }; + struct iovec iov = { + .iov_base = message, + .iov_len = len, + }; + uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))] = {}; + struct msghdr msg = { + .msg_name = &dest, + .msg_namelen = sizeof(dest.in), + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cmsgbuf, + .msg_controllen = sizeof(cmsgbuf), + }; + struct cmsghdr *cmsg; + struct in_pktinfo *pktinfo; + + assert(server); + assert(server->fd >= 0); + assert(message); + assert(len > sizeof(DHCPMessage)); + + cmsg = CMSG_FIRSTHDR(&msg); + assert(cmsg); + + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + + /* we attach source interface and address info to the message + rather than binding the socket. This will be mostly useful + when we gain support for arbitrary number of server addresses + */ + pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg); + assert(pktinfo); + + pktinfo->ipi_ifindex = server->ifindex; + pktinfo->ipi_spec_dst.s_addr = server->address; + + if (sendmsg(server->fd, &msg, 0) < 0) + return -errno; + + return 0; +} + +static bool requested_broadcast(DHCPRequest *req) { + assert(req); + + return req->message->flags & htobe16(0x8000); +} + +int dhcp_server_send_packet(sd_dhcp_server *server, + DHCPRequest *req, DHCPPacket *packet, + int type, size_t optoffset) { + be32_t destination = INADDR_ANY; + uint16_t destination_port = DHCP_PORT_CLIENT; + int r; + + assert(server); + assert(req); + assert(req->max_optlen); + assert(optoffset <= req->max_optlen); + assert(packet); + + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0, + SD_DHCP_OPTION_SERVER_IDENTIFIER, + 4, &server->address); + if (r < 0) + return r; + + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &optoffset, 0, + SD_DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; + + /* RFC 2131 Section 4.1 + + If the ’giaddr’ field in a DHCP message from a client is non-zero, + the server sends any return messages to the ’DHCP server’ port on the + BOOTP relay agent whose address appears in ’giaddr’. If the ’giaddr’ + field is zero and the ’ciaddr’ field is nonzero, then the server + unicasts DHCPOFFER and DHCPACK messages to the address in ’ciaddr’. + If ’giaddr’ is zero and ’ciaddr’ is zero, and the broadcast bit is + set, then the server broadcasts DHCPOFFER and DHCPACK messages to + 0xffffffff. If the broadcast bit is not set and ’giaddr’ is zero and + ’ciaddr’ is zero, then the server unicasts DHCPOFFER and DHCPACK + messages to the client’s hardware address and ’yiaddr’ address. In + all cases, when ’giaddr’ is zero, the server broadcasts any DHCPNAK + messages to 0xffffffff. + + Section 4.3.2 + + If ’giaddr’ is set in the DHCPREQUEST message, the client is on a + different subnet. The server MUST set the broadcast bit in the + DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the + client, because the client may not have a correct network address + or subnet mask, and the client may not be answering ARP requests. + */ + if (req->message->giaddr) { + destination = req->message->giaddr; + destination_port = DHCP_PORT_SERVER; + if (type == DHCP_NAK) + packet->dhcp.flags = htobe16(0x8000); + } else if (req->message->ciaddr && type != DHCP_NAK) + destination = req->message->ciaddr; + + if (destination != INADDR_ANY) + return dhcp_server_send_udp(server, destination, + destination_port, &packet->dhcp, + sizeof(DHCPMessage) + optoffset); + else if (requested_broadcast(req) || type == DHCP_NAK) + return dhcp_server_send_udp(server, INADDR_BROADCAST, + destination_port, &packet->dhcp, + sizeof(DHCPMessage) + optoffset); + else + /* we cannot send UDP packet to specific MAC address when the + address is not yet configured, so must fall back to raw + packets */ + return dhcp_server_send_unicast_raw(server, packet, + sizeof(DHCPPacket) + optoffset); +} + +static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret, + uint8_t type, size_t *_optoffset, + DHCPRequest *req) { + _cleanup_free_ DHCPPacket *packet = NULL; + size_t optoffset = 0; + int r; + + assert(server); + assert(ret); + assert(_optoffset); + assert(IN_SET(type, DHCP_OFFER, DHCP_ACK, DHCP_NAK)); + + packet = malloc0(sizeof(DHCPPacket) + req->max_optlen); + if (!packet) + return -ENOMEM; + + r = dhcp_message_init(&packet->dhcp, BOOTREPLY, + be32toh(req->message->xid), type, ARPHRD_ETHER, + req->max_optlen, &optoffset); + if (r < 0) + return r; + + packet->dhcp.flags = req->message->flags; + packet->dhcp.giaddr = req->message->giaddr; + memcpy(&packet->dhcp.chaddr, &req->message->chaddr, ETH_ALEN); + + *_optoffset = optoffset; + *ret = TAKE_PTR(packet); + + return 0; +} + +static int server_send_offer(sd_dhcp_server *server, DHCPRequest *req, + be32_t address) { + _cleanup_free_ DHCPPacket *packet = NULL; + size_t offset; + be32_t lease_time; + int r; + + r = server_message_init(server, &packet, DHCP_OFFER, &offset, req); + if (r < 0) + return r; + + packet->dhcp.yiaddr = address; + + lease_time = htobe32(req->lifetime); + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4, + &lease_time); + if (r < 0) + return r; + + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask); + if (r < 0) + return r; + + if (server->emit_router) { + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_ROUTER, 4, &server->address); + if (r < 0) + return r; + } + + r = dhcp_server_send_packet(server, req, packet, DHCP_OFFER, offset); + if (r < 0) + return r; + + return 0; +} + +static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req, + be32_t address) { + _cleanup_free_ DHCPPacket *packet = NULL; + be32_t lease_time; + size_t offset; + int r; + + r = server_message_init(server, &packet, DHCP_ACK, &offset, req); + if (r < 0) + return r; + + packet->dhcp.yiaddr = address; + + lease_time = htobe32(req->lifetime); + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4, + &lease_time); + if (r < 0) + return r; + + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask); + if (r < 0) + return r; + + if (server->emit_router) { + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_ROUTER, 4, &server->address); + if (r < 0) + return r; + } + + if (server->n_dns > 0) { + r = dhcp_option_append( + &packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_DOMAIN_NAME_SERVER, + sizeof(struct in_addr) * server->n_dns, server->dns); + if (r < 0) + return r; + } + + if (server->n_ntp > 0) { + r = dhcp_option_append( + &packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_NTP_SERVER, + sizeof(struct in_addr) * server->n_ntp, server->ntp); + if (r < 0) + return r; + } + + if (server->n_sip > 0) { + r = dhcp_option_append( + &packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_SIP_SERVER, + sizeof(struct in_addr) * server->n_sip, server->sip); + if (r < 0) + return r; + } + + if (server->timezone) { + r = dhcp_option_append( + &packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_NEW_TZDB_TIMEZONE, + strlen(server->timezone), server->timezone); + if (r < 0) + return r; + } + + if (!ordered_hashmap_isempty(server->raw_option)) { + r = dhcp_option_append( + &packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_VENDOR_SPECIFIC, + ordered_hashmap_size(server->raw_option), server->raw_option); + if (r < 0) + return r; + } + + r = dhcp_server_send_packet(server, req, packet, DHCP_ACK, offset); + if (r < 0) + return r; + + return 0; +} + +static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) { + _cleanup_free_ DHCPPacket *packet = NULL; + size_t offset; + int r; + + r = server_message_init(server, &packet, DHCP_NAK, &offset, req); + if (r < 0) + return r; + + return dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset); +} + +static int server_send_forcerenew(sd_dhcp_server *server, be32_t address, + be32_t gateway, uint8_t chaddr[]) { + _cleanup_free_ DHCPPacket *packet = NULL; + size_t optoffset = 0; + int r; + + assert(server); + assert(address != INADDR_ANY); + assert(chaddr); + + packet = malloc0(sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE); + if (!packet) + return -ENOMEM; + + r = dhcp_message_init(&packet->dhcp, BOOTREPLY, 0, + DHCP_FORCERENEW, ARPHRD_ETHER, + DHCP_MIN_OPTIONS_SIZE, &optoffset); + if (r < 0) + return r; + + r = dhcp_option_append(&packet->dhcp, DHCP_MIN_OPTIONS_SIZE, + &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; + + memcpy(&packet->dhcp.chaddr, chaddr, ETH_ALEN); + + r = dhcp_server_send_udp(server, address, DHCP_PORT_CLIENT, + &packet->dhcp, + sizeof(DHCPMessage) + optoffset); + if (r < 0) + return r; + + return 0; +} + +static int parse_request(uint8_t code, uint8_t len, const void *option, void *userdata) { + DHCPRequest *req = userdata; + + assert(req); + + switch(code) { + case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME: + if (len == 4) + req->lifetime = unaligned_read_be32(option); + + break; + case SD_DHCP_OPTION_REQUESTED_IP_ADDRESS: + if (len == 4) + memcpy(&req->requested_ip, option, sizeof(be32_t)); + + break; + case SD_DHCP_OPTION_SERVER_IDENTIFIER: + if (len == 4) + memcpy(&req->server_id, option, sizeof(be32_t)); + + break; + case SD_DHCP_OPTION_CLIENT_IDENTIFIER: + if (len >= 2) { + uint8_t *data; + + data = memdup(option, len); + if (!data) + return -ENOMEM; + + free(req->client_id.data); + req->client_id.data = data; + req->client_id.length = len; + } + + break; + case SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE: + + if (len == 2 && unaligned_read_be16(option) >= sizeof(DHCPPacket)) + req->max_optlen = unaligned_read_be16(option) - sizeof(DHCPPacket); + + break; + } + + return 0; +} + +static void dhcp_request_free(DHCPRequest *req) { + if (!req) + return; + + free(req->client_id.data); + free(req); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free); + +static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMessage *message) { + assert(req); + assert(message); + + req->message = message; + + /* set client id based on MAC address if client did not send an explicit + one */ + if (!req->client_id.data) { + void *data; + + data = malloc0(ETH_ALEN + 1); + if (!data) + return -ENOMEM; + + ((uint8_t*) data)[0] = 0x01; + memcpy((uint8_t*) data + 1, &message->chaddr, ETH_ALEN); + + req->client_id.length = ETH_ALEN + 1; + req->client_id.data = data; + } + + if (req->max_optlen < DHCP_MIN_OPTIONS_SIZE) + req->max_optlen = DHCP_MIN_OPTIONS_SIZE; + + if (req->lifetime <= 0) + req->lifetime = MAX(1ULL, server->default_lease_time); + + if (server->max_lease_time > 0 && req->lifetime > server->max_lease_time) + req->lifetime = server->max_lease_time; + + return 0; +} + +static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) { + assert(server); + + if (!server->pool_size) + return -EINVAL; + + if (be32toh(requested_ip) < (be32toh(server->subnet) | server->pool_offset) || + be32toh(requested_ip) >= (be32toh(server->subnet) | (server->pool_offset + server->pool_size))) + return -ERANGE; + + return be32toh(requested_ip & ~server->netmask) - server->pool_offset; +} + +#define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30) + +int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, + size_t length) { + _cleanup_(dhcp_request_freep) DHCPRequest *req = NULL; + _cleanup_free_ char *error_message = NULL; + DHCPLease *existing_lease; + int type, r; + + assert(server); + assert(message); + + if (message->op != BOOTREQUEST || + message->htype != ARPHRD_ETHER || + message->hlen != ETHER_ADDR_LEN) + return 0; + + req = new0(DHCPRequest, 1); + if (!req) + return -ENOMEM; + + type = dhcp_option_parse(message, length, parse_request, req, &error_message); + if (type < 0) + return 0; + + r = ensure_sane_request(server, req, message); + if (r < 0) + /* this only fails on critical errors */ + return r; + + existing_lease = hashmap_get(server->leases_by_client_id, + &req->client_id); + + switch(type) { + + case DHCP_DISCOVER: { + be32_t address = INADDR_ANY; + unsigned i; + + log_dhcp_server(server, "DISCOVER (0x%x)", + be32toh(req->message->xid)); + + if (!server->pool_size) + /* no pool allocated */ + return 0; + + /* for now pick a random free address from the pool */ + if (existing_lease) + address = existing_lease->address; + else { + struct siphash state; + uint64_t hash; + uint32_t next_offer; + + /* even with no persistence of leases, we try to offer the same client + the same IP address. we do this by using the hash of the client id + as the offset into the pool of leases when finding the next free one */ + + siphash24_init(&state, HASH_KEY.bytes); + client_id_hash_func(&req->client_id, &state); + hash = htole64(siphash24_finalize(&state)); + next_offer = hash % server->pool_size; + + for (i = 0; i < server->pool_size; i++) { + if (!server->bound_leases[next_offer]) { + address = server->subnet | htobe32(server->pool_offset + next_offer); + break; + } + + next_offer = (next_offer + 1) % server->pool_size; + } + } + + if (address == INADDR_ANY) + /* no free addresses left */ + return 0; + + r = server_send_offer(server, req, address); + if (r < 0) + /* this only fails on critical errors */ + return log_dhcp_server_errno(server, r, "Could not send offer: %m"); + + log_dhcp_server(server, "OFFER (0x%x)", be32toh(req->message->xid)); + return DHCP_OFFER; + } + case DHCP_DECLINE: + log_dhcp_server(server, "DECLINE (0x%x): %s", be32toh(req->message->xid), strna(error_message)); + + /* TODO: make sure we don't offer this address again */ + + return 1; + + case DHCP_REQUEST: { + be32_t address; + bool init_reboot = false; + int pool_offset; + + /* see RFC 2131, section 4.3.2 */ + + if (req->server_id) { + log_dhcp_server(server, "REQUEST (selecting) (0x%x)", + be32toh(req->message->xid)); + + /* SELECTING */ + if (req->server_id != server->address) + /* client did not pick us */ + return 0; + + if (req->message->ciaddr) + /* this MUST be zero */ + return 0; + + if (!req->requested_ip) + /* this must be filled in with the yiaddr + from the chosen OFFER */ + return 0; + + address = req->requested_ip; + } else if (req->requested_ip) { + log_dhcp_server(server, "REQUEST (init-reboot) (0x%x)", + be32toh(req->message->xid)); + + /* INIT-REBOOT */ + if (req->message->ciaddr) + /* this MUST be zero */ + return 0; + + /* TODO: check more carefully if IP is correct */ + address = req->requested_ip; + init_reboot = true; + } else { + log_dhcp_server(server, "REQUEST (rebinding/renewing) (0x%x)", + be32toh(req->message->xid)); + + /* REBINDING / RENEWING */ + if (!req->message->ciaddr) + /* this MUST be filled in with clients IP address */ + return 0; + + address = req->message->ciaddr; + } + + pool_offset = get_pool_offset(server, address); + + /* verify that the requested address is from the pool, and either + owned by the current client or free */ + if (pool_offset >= 0 && + server->bound_leases[pool_offset] == existing_lease) { + DHCPLease *lease; + usec_t time_now = 0; + + if (!existing_lease) { + lease = new0(DHCPLease, 1); + if (!lease) + return -ENOMEM; + lease->address = address; + lease->client_id.data = memdup(req->client_id.data, + req->client_id.length); + if (!lease->client_id.data) { + free(lease); + return -ENOMEM; + } + lease->client_id.length = req->client_id.length; + memcpy(&lease->chaddr, &req->message->chaddr, + ETH_ALEN); + lease->gateway = req->message->giaddr; + } else + lease = existing_lease; + + r = sd_event_now(server->event, + clock_boottime_or_monotonic(), + &time_now); + if (r < 0) { + if (!existing_lease) + dhcp_lease_free(lease); + return r; + } + + lease->expiration = req->lifetime * USEC_PER_SEC + time_now; + + r = server_send_ack(server, req, address); + if (r < 0) { + /* this only fails on critical errors */ + log_dhcp_server_errno(server, r, "Could not send ack: %m"); + + if (!existing_lease) + dhcp_lease_free(lease); + + return r; + } else { + log_dhcp_server(server, "ACK (0x%x)", + be32toh(req->message->xid)); + + server->bound_leases[pool_offset] = lease; + hashmap_put(server->leases_by_client_id, + &lease->client_id, lease); + + return DHCP_ACK; + } + + } else if (init_reboot) { + r = server_send_nak(server, req); + if (r < 0) + /* this only fails on critical errors */ + return log_dhcp_server_errno(server, r, "Could not send nak: %m"); + + log_dhcp_server(server, "NAK (0x%x)", be32toh(req->message->xid)); + return DHCP_NAK; + } + + break; + } + + case DHCP_RELEASE: { + int pool_offset; + + log_dhcp_server(server, "RELEASE (0x%x)", + be32toh(req->message->xid)); + + if (!existing_lease) + return 0; + + if (existing_lease->address != req->message->ciaddr) + return 0; + + pool_offset = get_pool_offset(server, req->message->ciaddr); + if (pool_offset < 0) + return 0; + + if (server->bound_leases[pool_offset] == existing_lease) { + server->bound_leases[pool_offset] = NULL; + hashmap_remove(server->leases_by_client_id, existing_lease); + dhcp_lease_free(existing_lease); + } + + return 0; + }} + + return 0; +} + +static int server_receive_message(sd_event_source *s, int fd, + uint32_t revents, void *userdata) { + _cleanup_free_ DHCPMessage *message = NULL; + uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))]; + sd_dhcp_server *server = userdata; + struct iovec iov = {}; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cmsgbuf, + .msg_controllen = sizeof(cmsgbuf), + }; + struct cmsghdr *cmsg; + ssize_t buflen, len; + int r; + + assert(server); + + buflen = next_datagram_size_fd(fd); + if (buflen < 0) + return buflen; + + message = malloc(buflen); + if (!message) + return -ENOMEM; + + iov = IOVEC_MAKE(message, buflen); + + len = recvmsg(fd, &msg, 0); + if (len < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + return -errno; + } + if ((size_t)len < sizeof(DHCPMessage)) + return 0; + + CMSG_FOREACH(cmsg, &msg) { + if (cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == IP_PKTINFO && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct in_pktinfo))) { + struct in_pktinfo *info = (struct in_pktinfo*)CMSG_DATA(cmsg); + + /* TODO figure out if this can be done as a filter on + * the socket, like for IPv6 */ + if (server->ifindex != info->ipi_ifindex) + return 0; + + break; + } + } + + r = dhcp_server_handle_message(server, message, (size_t) len); + if (r < 0) + log_dhcp_server_errno(server, r, "Couldn't process incoming message: %m"); + + return 0; +} + +int sd_dhcp_server_start(sd_dhcp_server *server) { + int r; + + assert_return(server, -EINVAL); + assert_return(server->event, -EINVAL); + assert_return(!server->receive_message, -EBUSY); + assert_return(server->fd_raw < 0, -EBUSY); + assert_return(server->fd < 0, -EBUSY); + assert_return(server->address != htobe32(INADDR_ANY), -EUNATCH); + + r = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (r < 0) { + r = -errno; + sd_dhcp_server_stop(server); + return r; + } + server->fd_raw = r; + + r = dhcp_network_bind_udp_socket(server->ifindex, INADDR_ANY, DHCP_PORT_SERVER, -1); + if (r < 0) { + sd_dhcp_server_stop(server); + return r; + } + server->fd = r; + + r = sd_event_add_io(server->event, &server->receive_message, + server->fd, EPOLLIN, + server_receive_message, server); + if (r < 0) { + sd_dhcp_server_stop(server); + return r; + } + + r = sd_event_source_set_priority(server->receive_message, + server->event_priority); + if (r < 0) { + sd_dhcp_server_stop(server); + return r; + } + + log_dhcp_server(server, "STARTED"); + + return 0; +} + +int sd_dhcp_server_forcerenew(sd_dhcp_server *server) { + unsigned i; + int r = 0; + + assert_return(server, -EINVAL); + assert(server->bound_leases); + + for (i = 0; i < server->pool_size; i++) { + DHCPLease *lease = server->bound_leases[i]; + + if (!lease || lease == &server->invalid_lease) + continue; + + r = server_send_forcerenew(server, lease->address, + lease->gateway, + lease->chaddr); + if (r < 0) + return r; + + log_dhcp_server(server, "FORCERENEW"); + } + + return r; +} + +int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *tz) { + int r; + + assert_return(server, -EINVAL); + assert_return(timezone_is_valid(tz, LOG_DEBUG), -EINVAL); + + if (streq_ptr(tz, server->timezone)) + return 0; + + r = free_and_strdup(&server->timezone, tz); + if (r < 0) + return r; + + return 1; +} + +int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t) { + assert_return(server, -EINVAL); + + if (t == server->max_lease_time) + return 0; + + server->max_lease_time = t; + return 1; +} + +int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t) { + assert_return(server, -EINVAL); + + if (t == server->default_lease_time) + return 0; + + server->default_lease_time = t; + return 1; +} + +int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n) { + assert_return(server, -EINVAL); + assert_return(dns || n <= 0, -EINVAL); + + if (server->n_dns == n && + memcmp(server->dns, dns, sizeof(struct in_addr) * n) == 0) + return 0; + + if (n <= 0) { + server->dns = mfree(server->dns); + server->n_dns = 0; + } else { + struct in_addr *c; + + c = newdup(struct in_addr, dns, n); + if (!c) + return -ENOMEM; + + free(server->dns); + server->dns = c; + server->n_dns = n; + } + + return 1; +} + +int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n) { + assert_return(server, -EINVAL); + assert_return(ntp || n <= 0, -EINVAL); + + if (server->n_ntp == n && + memcmp(server->ntp, ntp, sizeof(struct in_addr) * n) == 0) + return 0; + + if (n <= 0) { + server->ntp = mfree(server->ntp); + server->n_ntp = 0; + } else { + struct in_addr *c; + + c = newdup(struct in_addr, ntp, n); + if (!c) + return -ENOMEM; + + free(server->ntp); + server->ntp = c; + server->n_ntp = n; + } + + return 1; +} + +int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n) { + assert_return(server, -EINVAL); + assert_return(sip || n <= 0, -EINVAL); + + if (server->n_sip == n && + memcmp(server->sip, sip, sizeof(struct in_addr) * n) == 0) + return 0; + + if (n <= 0) { + server->sip = mfree(server->sip); + server->n_sip = 0; + } else { + struct in_addr *c; + + c = newdup(struct in_addr, sip, n); + if (!c) + return -ENOMEM; + + free(server->sip); + server->sip = c; + server->n_sip = n; + } + + return 1; +} + +int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) { + assert_return(server, -EINVAL); + + if (enabled == server->emit_router) + return 0; + + server->emit_router = enabled; + + return 1; +} + +int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v) { + int r; + + assert_return(server, -EINVAL); + assert_return(v, -EINVAL); + + r = ordered_hashmap_ensure_allocated(&server->raw_option, &dhcp_option_hash_ops); + if (r < 0) + return -ENOMEM; + + r = ordered_hashmap_put(server->raw_option, v, v); + if (r < 0) + return r; + + sd_dhcp_option_ref(v); + + return 1; +} diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c new file mode 100644 index 00000000..9c4ce247 --- /dev/null +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -0,0 +1,1563 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014-2015 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include + +#include "sd-dhcp6-client.h" + +#include "alloc-util.h" +#include "dhcp-identifier.h" +#include "dhcp6-internal.h" +#include "dhcp6-lease-internal.h" +#include "dhcp6-protocol.h" +#include "dns-domain.h" +#include "event-util.h" +#include "fd-util.h" +#include "hostname-util.h" +#include "in-addr-util.h" +#include "network-internal.h" +#include "random-util.h" +#include "socket-util.h" +#include "string-table.h" +#include "util.h" + +#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN + +#define IRT_DEFAULT (1 * USEC_PER_DAY) +#define IRT_MINIMUM (600 * USEC_PER_SEC) + +/* what to request from the server, addresses (IA_NA) and/or prefixes (IA_PD) */ +enum { + DHCP6_REQUEST_IA_NA = 1, + DHCP6_REQUEST_IA_TA = 2, /* currently not used */ + DHCP6_REQUEST_IA_PD = 4, +}; + +struct sd_dhcp6_client { + unsigned n_ref; + + enum DHCP6State state; + sd_event *event; + int event_priority; + int ifindex; + DHCP6Address hint_pd_prefix; + struct in6_addr local_address; + uint8_t mac_addr[MAX_MAC_ADDR_LEN]; + size_t mac_addr_len; + uint16_t arp_type; + DHCP6IA ia_na; + DHCP6IA ia_pd; + sd_event_source *timeout_t1; + sd_event_source *timeout_t2; + unsigned request; + be32_t transaction_id; + usec_t transaction_start; + struct sd_dhcp6_lease *lease; + int fd; + bool information_request; + bool iaid_set; + be16_t *req_opts; + size_t req_opts_allocated; + size_t req_opts_len; + char *fqdn; + sd_event_source *receive_message; + usec_t retransmit_time; + uint8_t retransmit_count; + sd_event_source *timeout_resend; + sd_event_source *timeout_resend_expire; + sd_dhcp6_client_callback_t callback; + void *userdata; + struct duid duid; + size_t duid_len; + usec_t information_request_time_usec; + usec_t information_refresh_time_usec; +}; + +static const uint16_t default_req_opts[] = { + SD_DHCP6_OPTION_DNS_SERVERS, + SD_DHCP6_OPTION_DOMAIN_LIST, + SD_DHCP6_OPTION_NTP_SERVER, + SD_DHCP6_OPTION_SNTP_SERVERS, +}; + +const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = { + [DHCP6_SOLICIT] = "SOLICIT", + [DHCP6_ADVERTISE] = "ADVERTISE", + [DHCP6_REQUEST] = "REQUEST", + [DHCP6_CONFIRM] = "CONFIRM", + [DHCP6_RENEW] = "RENEW", + [DHCP6_REBIND] = "REBIND", + [DHCP6_REPLY] = "REPLY", + [DHCP6_RELEASE] = "RELEASE", + [DHCP6_DECLINE] = "DECLINE", + [DHCP6_RECONFIGURE] = "RECONFIGURE", + [DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST", + [DHCP6_RELAY_FORW] = "RELAY-FORW", + [DHCP6_RELAY_REPL] = "RELAY-REPL", +}; + +DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int); + +const char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = { + [DHCP6_STATUS_SUCCESS] = "Success", + [DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure", + [DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available", + [DHCP6_STATUS_NO_BINDING] = "Binding unavailable", + [DHCP6_STATUS_NOT_ON_LINK] = "Not on link", + [DHCP6_STATUS_USE_MULTICAST] = "Use multicast", +}; + +DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int); + +#define DHCP6_CLIENT_DONT_DESTROY(client) \ + _cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client) + +static int client_start(sd_dhcp6_client *client, enum DHCP6State state); + +int sd_dhcp6_client_set_callback( + sd_dhcp6_client *client, + sd_dhcp6_client_callback_t cb, + void *userdata) { + + assert_return(client, -EINVAL); + + client->callback = cb; + client->userdata = userdata; + + return 0; +} + +int sd_dhcp6_client_set_ifindex(sd_dhcp6_client *client, int ifindex) { + + assert_return(client, -EINVAL); + assert_return(ifindex >= -1, -EINVAL); + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + + client->ifindex = ifindex; + return 0; +} + +int sd_dhcp6_client_set_local_address( + sd_dhcp6_client *client, + const struct in6_addr *local_address) { + + assert_return(client, -EINVAL); + assert_return(local_address, -EINVAL); + assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL); + + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + + client->local_address = *local_address; + + return 0; +} + +int sd_dhcp6_client_set_mac( + sd_dhcp6_client *client, + const uint8_t *addr, size_t addr_len, + uint16_t arp_type) { + + assert_return(client, -EINVAL); + assert_return(addr, -EINVAL); + assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); + assert_return(arp_type > 0, -EINVAL); + + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + + if (arp_type == ARPHRD_ETHER) + assert_return(addr_len == ETH_ALEN, -EINVAL); + else if (arp_type == ARPHRD_INFINIBAND) + assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); + else + return -EINVAL; + + if (client->mac_addr_len == addr_len && + memcmp(&client->mac_addr, addr, addr_len) == 0) + return 0; + + memcpy(&client->mac_addr, addr, addr_len); + client->mac_addr_len = addr_len; + client->arp_type = arp_type; + + return 0; +} + +int sd_dhcp6_client_set_prefix_delegation_hint( + sd_dhcp6_client *client, + uint8_t prefixlen, + const struct in6_addr *pd_address) { + + assert_return(client, -EINVAL); + assert_return(pd_address, -EINVAL); + + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + + client->hint_pd_prefix.iapdprefix.address = *pd_address; + client->hint_pd_prefix.iapdprefix.prefixlen = prefixlen; + + return 0; +} + +static int client_ensure_duid(sd_dhcp6_client *client) { + if (client->duid_len != 0) + return 0; + + return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); +} + +/** + * Sets DUID. If duid is non-null, the DUID is set to duid_type + duid + * without further modification. Otherwise, if duid_type is supported, DUID + * is set based on that type. Otherwise, an error is returned. + */ +static int dhcp6_client_set_duid_internal( + sd_dhcp6_client *client, + uint16_t duid_type, + const void *duid, + size_t duid_len, + usec_t llt_time) { + int r; + + assert_return(client, -EINVAL); + assert_return(duid_len == 0 || duid != NULL, -EINVAL); + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + + if (duid != NULL) { + r = dhcp_validate_duid_len(duid_type, duid_len, true); + if (r < 0) { + r = dhcp_validate_duid_len(duid_type, duid_len, false); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to validate length of DUID: %m"); + log_dhcp6_client(client, "Setting DUID of type %u with unexpected content", duid_type); + } + + client->duid.type = htobe16(duid_type); + memcpy(&client->duid.raw.data, duid, duid_len); + client->duid_len = sizeof(client->duid.type) + duid_len; + } else + switch (duid_type) { + case DUID_TYPE_LLT: + if (client->mac_addr_len == 0) + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set."); + + r = dhcp_identifier_set_duid_llt(&client->duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to set DUID-LLT: %m"); + break; + case DUID_TYPE_EN: + r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to set DUID-EN: %m"); + break; + case DUID_TYPE_LL: + if (client->mac_addr_len == 0) + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set."); + + r = dhcp_identifier_set_duid_ll(&client->duid, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to set DUID-LL: %m"); + break; + case DUID_TYPE_UUID: + r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Failed to set DUID-UUID: %m"); + break; + default: + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type"); + } + + return 0; +} + +int sd_dhcp6_client_set_duid( + sd_dhcp6_client *client, + uint16_t duid_type, + const void *duid, + size_t duid_len) { + return dhcp6_client_set_duid_internal(client, duid_type, duid, duid_len, 0); +} + +int sd_dhcp6_client_set_duid_llt( + sd_dhcp6_client *client, + usec_t llt_time) { + return dhcp6_client_set_duid_internal(client, DUID_TYPE_LLT, NULL, 0, llt_time); +} + +int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) { + assert_return(client, -EINVAL); + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + + client->ia_na.ia_na.id = htobe32(iaid); + client->ia_pd.ia_pd.id = htobe32(iaid); + client->iaid_set = true; + + return 0; +} + +int sd_dhcp6_client_set_fqdn( + sd_dhcp6_client *client, + const char *fqdn) { + + assert_return(client, -EINVAL); + + /* Make sure FQDN qualifies as DNS and as Linux hostname */ + if (fqdn && + !(hostname_is_valid(fqdn, false) && dns_name_is_valid(fqdn) > 0)) + return -EINVAL; + + return free_and_strdup(&client->fqdn, fqdn); +} + +int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled) { + assert_return(client, -EINVAL); + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + + client->information_request = enabled; + + return 0; +} + +int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled) { + assert_return(client, -EINVAL); + assert_return(enabled, -EINVAL); + + *enabled = client->information_request; + + return 0; +} + +int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) { + size_t t; + + assert_return(client, -EINVAL); + assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); + + switch(option) { + + case SD_DHCP6_OPTION_DNS_SERVERS: + case SD_DHCP6_OPTION_DOMAIN_LIST: + case SD_DHCP6_OPTION_SNTP_SERVERS: + case SD_DHCP6_OPTION_NTP_SERVER: + case SD_DHCP6_OPTION_RAPID_COMMIT: + break; + + default: + return -EINVAL; + } + + for (t = 0; t < client->req_opts_len; t++) + if (client->req_opts[t] == htobe16(option)) + return -EEXIST; + + if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated, + client->req_opts_len + 1)) + return -ENOMEM; + + client->req_opts[client->req_opts_len++] = htobe16(option); + + return 0; +} + +int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) { + assert_return(client, -EINVAL); + assert_return(delegation, -EINVAL); + + *delegation = FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD); + + return 0; +} + +int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, int delegation) { + assert_return(client, -EINVAL); + + SET_FLAG(client->request, DHCP6_REQUEST_IA_PD, delegation); + + return 0; +} + +int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client, int *request) { + assert_return(client, -EINVAL); + assert_return(request, -EINVAL); + + *request = FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA); + + return 0; +} + +int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client, int request) { + assert_return(client, -EINVAL); + + SET_FLAG(client->request, DHCP6_REQUEST_IA_NA, request); + + return 0; +} + +int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transaction_id) { + assert_return(client, -EINVAL); + + client->transaction_id = transaction_id; + + return 0; +} + +int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) { + assert_return(client, -EINVAL); + + if (!client->lease) + return -ENOMSG; + + if (ret) + *ret = client->lease; + + return 0; +} + +static void client_notify(sd_dhcp6_client *client, int event) { + assert(client); + + if (client->callback) + client->callback(client, event, client->userdata); +} + +static int client_reset(sd_dhcp6_client *client) { + assert(client); + + client->lease = sd_dhcp6_lease_unref(client->lease); + + client->receive_message = + sd_event_source_unref(client->receive_message); + + client->transaction_id = 0; + client->transaction_start = 0; + + client->retransmit_time = 0; + client->retransmit_count = 0; + + (void) event_source_disable(client->timeout_resend); + (void) event_source_disable(client->timeout_resend_expire); + (void) event_source_disable(client->timeout_t1); + (void) event_source_disable(client->timeout_t2); + + client->state = DHCP6_STATE_STOPPED; + + return 0; +} + +static void client_stop(sd_dhcp6_client *client, int error) { + DHCP6_CLIENT_DONT_DESTROY(client); + + assert(client); + + client_notify(client, error); + + client_reset(client); +} + +static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { + _cleanup_free_ DHCP6Message *message = NULL; + struct in6_addr all_servers = + IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; + size_t len, optlen = 512; + uint8_t *opt; + int r; + usec_t elapsed_usec; + be16_t elapsed_time; + + assert(client); + + len = sizeof(DHCP6Message) + optlen; + + message = malloc0(len); + if (!message) + return -ENOMEM; + + opt = (uint8_t *)(message + 1); + + message->transaction_id = client->transaction_id; + + switch(client->state) { + case DHCP6_STATE_INFORMATION_REQUEST: + message->type = DHCP6_INFORMATION_REQUEST; + + break; + + case DHCP6_STATE_SOLICITATION: + message->type = DHCP6_SOLICIT; + + r = dhcp6_option_append(&opt, &optlen, + SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL); + if (r < 0) + return r; + + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) { + r = dhcp6_option_append_ia(&opt, &optlen, + &client->ia_na); + if (r < 0) + return r; + } + + if (client->fqdn) { + r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn); + if (r < 0) + return r; + } + + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { + r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix); + if (r < 0) + return r; + + opt += r; + optlen -= r; + } + + break; + + case DHCP6_STATE_REQUEST: + case DHCP6_STATE_RENEW: + + if (client->state == DHCP6_STATE_REQUEST) + message->type = DHCP6_REQUEST; + else + message->type = DHCP6_RENEW; + + r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID, + client->lease->serverid_len, + client->lease->serverid); + if (r < 0) + return r; + + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) { + r = dhcp6_option_append_ia(&opt, &optlen, + &client->lease->ia); + if (r < 0) + return r; + } + + if (client->fqdn) { + r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn); + if (r < 0) + return r; + } + + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { + r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); + if (r < 0) + return r; + + opt += r; + optlen -= r; + } + + break; + + case DHCP6_STATE_REBIND: + message->type = DHCP6_REBIND; + + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) { + r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia); + if (r < 0) + return r; + } + + if (client->fqdn) { + r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn); + if (r < 0) + return r; + } + + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { + r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); + if (r < 0) + return r; + + opt += r; + optlen -= r; + } + + break; + + case DHCP6_STATE_STOPPED: + case DHCP6_STATE_BOUND: + return -EINVAL; + } + + r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO, + client->req_opts_len * sizeof(be16_t), + client->req_opts); + if (r < 0) + return r; + + assert(client->duid_len); + r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID, + client->duid_len, &client->duid); + if (r < 0) + return r; + + elapsed_usec = time_now - client->transaction_start; + if (elapsed_usec < 0xffff * USEC_PER_MSEC * 10) + elapsed_time = htobe16(elapsed_usec / USEC_PER_MSEC / 10); + else + elapsed_time = 0xffff; + + r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME, + sizeof(elapsed_time), &elapsed_time); + if (r < 0) + return r; + + r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message, + len - optlen); + if (r < 0) + return r; + + log_dhcp6_client(client, "Sent %s", + dhcp6_message_type_to_string(message->type)); + + return 0; +} + +static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) { + sd_dhcp6_client *client = userdata; + + assert(s); + assert(client); + assert(client->lease); + + (void) event_source_disable(client->timeout_t2); + + log_dhcp6_client(client, "Timeout T2"); + + client_start(client, DHCP6_STATE_REBIND); + + return 0; +} + +static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) { + sd_dhcp6_client *client = userdata; + + assert(s); + assert(client); + assert(client->lease); + + (void) event_source_disable(client->timeout_t1); + + log_dhcp6_client(client, "Timeout T1"); + + client_start(client, DHCP6_STATE_RENEW); + + return 0; +} + +static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, void *userdata) { + sd_dhcp6_client *client = userdata; + DHCP6_CLIENT_DONT_DESTROY(client); + enum DHCP6State state; + + assert(s); + assert(client); + assert(client->event); + + state = client->state; + + client_stop(client, SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE); + + /* RFC 3315, section 18.1.4., says that "...the client may choose to + use a Solicit message to locate a new DHCP server..." */ + if (state == DHCP6_STATE_REBIND) + client_start(client, DHCP6_STATE_SOLICITATION); + + return 0; +} + +static usec_t client_timeout_compute_random(usec_t val) { + return val - (random_u32() % USEC_PER_SEC) * val / 10 / USEC_PER_SEC; +} + +static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userdata) { + int r = 0; + sd_dhcp6_client *client = userdata; + usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0; + usec_t max_retransmit_duration = 0; + uint8_t max_retransmit_count = 0; + char time_string[FORMAT_TIMESPAN_MAX]; + uint32_t expire = 0; + + assert(s); + assert(client); + assert(client->event); + + (void) event_source_disable(client->timeout_resend); + + switch (client->state) { + case DHCP6_STATE_INFORMATION_REQUEST: + init_retransmit_time = DHCP6_INF_TIMEOUT; + max_retransmit_time = DHCP6_INF_MAX_RT; + + break; + + case DHCP6_STATE_SOLICITATION: + + if (client->retransmit_count && client->lease) { + client_start(client, DHCP6_STATE_REQUEST); + return 0; + } + + init_retransmit_time = DHCP6_SOL_TIMEOUT; + max_retransmit_time = DHCP6_SOL_MAX_RT; + + break; + + case DHCP6_STATE_REQUEST: + init_retransmit_time = DHCP6_REQ_TIMEOUT; + max_retransmit_time = DHCP6_REQ_MAX_RT; + max_retransmit_count = DHCP6_REQ_MAX_RC; + + break; + + case DHCP6_STATE_RENEW: + init_retransmit_time = DHCP6_REN_TIMEOUT; + max_retransmit_time = DHCP6_REN_MAX_RT; + + /* RFC 3315, section 18.1.3. says max retransmit duration will + be the remaining time until T2. Instead of setting MRD, + wait for T2 to trigger with the same end result */ + + break; + + case DHCP6_STATE_REBIND: + init_retransmit_time = DHCP6_REB_TIMEOUT; + max_retransmit_time = DHCP6_REB_MAX_RT; + + if (event_source_is_enabled(client->timeout_resend_expire) <= 0) { + r = dhcp6_lease_ia_rebind_expire(&client->lease->ia, + &expire); + if (r < 0) { + client_stop(client, r); + return 0; + } + max_retransmit_duration = expire * USEC_PER_SEC; + } + + break; + + case DHCP6_STATE_STOPPED: + case DHCP6_STATE_BOUND: + return 0; + } + + if (max_retransmit_count && + client->retransmit_count >= max_retransmit_count) { + client_stop(client, SD_DHCP6_CLIENT_EVENT_RETRANS_MAX); + return 0; + } + + r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + goto error; + + r = client_send_message(client, time_now); + if (r >= 0) + client->retransmit_count++; + + if (!client->retransmit_time) { + client->retransmit_time = + client_timeout_compute_random(init_retransmit_time); + + if (client->state == DHCP6_STATE_SOLICITATION) + client->retransmit_time += init_retransmit_time / 10; + + } else { + if (max_retransmit_time && + client->retransmit_time > max_retransmit_time / 2) + client->retransmit_time = client_timeout_compute_random(max_retransmit_time); + else + client->retransmit_time += client_timeout_compute_random(client->retransmit_time); + } + + log_dhcp6_client(client, "Next retransmission in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->retransmit_time, USEC_PER_SEC)); + + r = event_reset_time(client->event, &client->timeout_resend, + clock_boottime_or_monotonic(), + time_now + client->retransmit_time, 10 * USEC_PER_MSEC, + client_timeout_resend, client, + client->event_priority, "dhcp6-resend-timer", true); + if (r < 0) + goto error; + + if (max_retransmit_duration && event_source_is_enabled(client->timeout_resend_expire) <= 0) { + + log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs", + max_retransmit_duration / USEC_PER_SEC); + + r = event_reset_time(client->event, &client->timeout_resend_expire, + clock_boottime_or_monotonic(), + time_now + max_retransmit_duration, USEC_PER_SEC, + client_timeout_resend_expire, client, + client->event_priority, "dhcp6-resend-expire-timer", true); + if (r < 0) + goto error; + } + +error: + if (r < 0) + client_stop(client, r); + + return 0; +} + +static int client_ensure_iaid(sd_dhcp6_client *client) { + int r; + uint32_t iaid; + + assert(client); + + if (client->iaid_set) + return 0; + + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, true, &iaid); + if (r < 0) + return r; + + client->ia_na.ia_na.id = iaid; + client->ia_pd.ia_pd.id = iaid; + client->iaid_set = true; + + return 0; +} + +static int client_parse_message( + sd_dhcp6_client *client, + DHCP6Message *message, + size_t len, + sd_dhcp6_lease *lease) { + + uint32_t lt_t1 = ~0, lt_t2 = ~0; + bool clientid = false; + size_t pos = 0; + usec_t irt = IRT_DEFAULT; + int r; + + assert(client); + assert(message); + assert(len >= sizeof(DHCP6Message)); + assert(lease); + + len -= sizeof(DHCP6Message); + + while (pos < len) { + DHCP6Option *option = (DHCP6Option *) &message->options[pos]; + uint16_t optcode, optlen; + be32_t iaid_lease; + uint8_t *optval; + int status; + + if (len < pos + offsetof(DHCP6Option, data)) + return -ENOBUFS; + + optcode = be16toh(option->code); + optlen = be16toh(option->len); + optval = option->data; + + if (len < pos + offsetof(DHCP6Option, data) + optlen) + return -ENOBUFS; + + switch (optcode) { + case SD_DHCP6_OPTION_CLIENTID: + if (clientid) { + log_dhcp6_client(client, "%s contains multiple clientids", + dhcp6_message_type_to_string(message->type)); + return -EINVAL; + } + + if (optlen != client->duid_len || + memcmp(&client->duid, optval, optlen) != 0) { + log_dhcp6_client(client, "%s DUID does not match", + dhcp6_message_type_to_string(message->type)); + + return -EINVAL; + } + clientid = true; + + break; + + case SD_DHCP6_OPTION_SERVERID: + r = dhcp6_lease_get_serverid(lease, NULL, NULL); + if (r >= 0) { + log_dhcp6_client(client, "%s contains multiple serverids", + dhcp6_message_type_to_string(message->type)); + return -EINVAL; + } + + r = dhcp6_lease_set_serverid(lease, optval, optlen); + if (r < 0) + return r; + + break; + + case SD_DHCP6_OPTION_PREFERENCE: + if (optlen != 1) + return -EINVAL; + + r = dhcp6_lease_set_preference(lease, optval[0]); + if (r < 0) + return r; + + break; + + case SD_DHCP6_OPTION_STATUS_CODE: + status = dhcp6_option_parse_status(option, optlen + sizeof(DHCP6Option)); + if (status < 0) + return status; + + if (status > 0) { + log_dhcp6_client(client, "%s Status %s", + dhcp6_message_type_to_string(message->type), + dhcp6_message_status_to_string(status)); + + return -EINVAL; + } + + break; + + case SD_DHCP6_OPTION_IA_NA: + if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { + log_dhcp6_client(client, "Information request ignoring IA NA option"); + + break; + } + + r = dhcp6_option_parse_ia(option, &lease->ia); + if (r < 0 && r != -ENOMSG) + return r; + + r = dhcp6_lease_get_iaid(lease, &iaid_lease); + if (r < 0) + return r; + + if (client->ia_na.ia_na.id != iaid_lease) { + log_dhcp6_client(client, "%s has wrong IAID for IA NA", + dhcp6_message_type_to_string(message->type)); + return -EINVAL; + } + + if (lease->ia.addresses) { + lt_t1 = MIN(lt_t1, be32toh(lease->ia.ia_na.lifetime_t1)); + lt_t2 = MIN(lt_t2, be32toh(lease->ia.ia_na.lifetime_t1)); + } + + break; + + case SD_DHCP6_OPTION_IA_PD: + if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { + log_dhcp6_client(client, "Information request ignoring IA PD option"); + + break; + } + + r = dhcp6_option_parse_ia(option, &lease->pd); + if (r < 0 && r != -ENOMSG) + return r; + + r = dhcp6_lease_get_pd_iaid(lease, &iaid_lease); + if (r < 0) + return r; + + if (client->ia_pd.ia_pd.id != iaid_lease) { + log_dhcp6_client(client, "%s has wrong IAID for IA PD", + dhcp6_message_type_to_string(message->type)); + return -EINVAL; + } + + if (lease->pd.addresses) { + lt_t1 = MIN(lt_t1, be32toh(lease->pd.ia_pd.lifetime_t1)); + lt_t2 = MIN(lt_t2, be32toh(lease->pd.ia_pd.lifetime_t2)); + } + + break; + + case SD_DHCP6_OPTION_RAPID_COMMIT: + r = dhcp6_lease_set_rapid_commit(lease); + if (r < 0) + return r; + + break; + + case SD_DHCP6_OPTION_DNS_SERVERS: + r = dhcp6_lease_set_dns(lease, optval, optlen); + if (r < 0) + return r; + + break; + + case SD_DHCP6_OPTION_DOMAIN_LIST: + r = dhcp6_lease_set_domains(lease, optval, optlen); + if (r < 0) + return r; + + break; + + case SD_DHCP6_OPTION_NTP_SERVER: + r = dhcp6_lease_set_ntp(lease, optval, optlen); + if (r < 0) + return r; + + break; + + case SD_DHCP6_OPTION_SNTP_SERVERS: + r = dhcp6_lease_set_sntp(lease, optval, optlen); + if (r < 0) + return r; + + break; + + case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME: + if (optlen != 4) + return -EINVAL; + + irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC; + break; + } + + pos += offsetof(DHCP6Option, data) + optlen; + } + + if (!clientid) { + log_dhcp6_client(client, "%s has incomplete options", + dhcp6_message_type_to_string(message->type)); + return -EINVAL; + } + + if (client->state != DHCP6_STATE_INFORMATION_REQUEST) { + r = dhcp6_lease_get_serverid(lease, NULL, NULL); + if (r < 0) { + log_dhcp6_client(client, "%s has no server id", + dhcp6_message_type_to_string(message->type)); + return -EINVAL; + } + + } else { + if (lease->ia.addresses) { + lease->ia.ia_na.lifetime_t1 = htobe32(lt_t1); + lease->ia.ia_na.lifetime_t2 = htobe32(lt_t2); + } + + if (lease->pd.addresses) { + lease->pd.ia_pd.lifetime_t1 = htobe32(lt_t1); + lease->pd.ia_pd.lifetime_t2 = htobe32(lt_t2); + } + } + + client->information_refresh_time_usec = MAX(irt, IRT_MINIMUM); + + return 0; +} + +static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) { + _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; + bool rapid_commit; + int r; + + assert(client); + assert(reply); + + if (reply->type != DHCP6_REPLY) + return 0; + + r = dhcp6_lease_new(&lease); + if (r < 0) + return -ENOMEM; + + r = client_parse_message(client, reply, len, lease); + if (r < 0) + return r; + + if (client->state == DHCP6_STATE_SOLICITATION) { + r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit); + if (r < 0) + return r; + + if (!rapid_commit) + return 0; + } + + sd_dhcp6_lease_unref(client->lease); + client->lease = TAKE_PTR(lease); + + return DHCP6_STATE_BOUND; +} + +static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) { + _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; + uint8_t pref_advertise = 0, pref_lease = 0; + int r; + + if (advertise->type != DHCP6_ADVERTISE) + return 0; + + r = dhcp6_lease_new(&lease); + if (r < 0) + return r; + + r = client_parse_message(client, advertise, len, lease); + if (r < 0) + return r; + + r = dhcp6_lease_get_preference(lease, &pref_advertise); + if (r < 0) + return r; + + r = dhcp6_lease_get_preference(client->lease, &pref_lease); + + if (r < 0 || pref_advertise > pref_lease) { + sd_dhcp6_lease_unref(client->lease); + client->lease = TAKE_PTR(lease); + r = 0; + } + + if (pref_advertise == 255 || client->retransmit_count > 1) + r = DHCP6_STATE_REQUEST; + + return r; +} + +static int client_receive_message( + sd_event_source *s, + int fd, uint32_t + revents, + void *userdata) { + + sd_dhcp6_client *client = userdata; + DHCP6_CLIENT_DONT_DESTROY(client); + _cleanup_free_ DHCP6Message *message = NULL; + ssize_t buflen, len; + int r = 0; + + assert(s); + assert(client); + assert(client->event); + + buflen = next_datagram_size_fd(fd); + if (buflen == -ENETDOWN) { + /* the link is down. Don't return an error or the I/O event + source will be disconnected and we won't be able to receive + packets again when the link comes back. */ + return 0; + } + if (buflen < 0) + return buflen; + + message = malloc(buflen); + if (!message) + return -ENOMEM; + + len = recv(fd, message, buflen, 0); + if (len < 0) { + /* see comment above for why we shouldn't error out on ENETDOWN. */ + if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN)) + return 0; + + return log_dhcp6_client_errno(client, errno, "Could not receive message from UDP socket: %m"); + + } + if ((size_t) len < sizeof(DHCP6Message)) { + log_dhcp6_client(client, "Too small to be DHCP6 message: ignoring"); + return 0; + } + + switch(message->type) { + case DHCP6_SOLICIT: + case DHCP6_REQUEST: + case DHCP6_CONFIRM: + case DHCP6_RENEW: + case DHCP6_REBIND: + case DHCP6_RELEASE: + case DHCP6_DECLINE: + case DHCP6_INFORMATION_REQUEST: + case DHCP6_RELAY_FORW: + case DHCP6_RELAY_REPL: + return 0; + + case DHCP6_ADVERTISE: + case DHCP6_REPLY: + case DHCP6_RECONFIGURE: + break; + + default: + log_dhcp6_client(client, "Unknown message type %d", message->type); + return 0; + } + + if (client->transaction_id != (message->transaction_id & + htobe32(0x00ffffff))) + return 0; + + switch (client->state) { + case DHCP6_STATE_INFORMATION_REQUEST: + r = client_receive_reply(client, message, len); + if (r < 0) + return 0; + + client_notify(client, SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST); + + client_start(client, DHCP6_STATE_STOPPED); + + break; + + case DHCP6_STATE_SOLICITATION: + r = client_receive_advertise(client, message, len); + + if (r == DHCP6_STATE_REQUEST) { + client_start(client, r); + + break; + } + + _fallthrough_; /* for Soliciation Rapid Commit option check */ + case DHCP6_STATE_REQUEST: + case DHCP6_STATE_RENEW: + case DHCP6_STATE_REBIND: + + r = client_receive_reply(client, message, len); + if (r < 0) + return 0; + + if (r == DHCP6_STATE_BOUND) { + + r = client_start(client, DHCP6_STATE_BOUND); + if (r < 0) { + client_stop(client, r); + return 0; + } + + client_notify(client, SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE); + } + + break; + + case DHCP6_STATE_BOUND: + + break; + + case DHCP6_STATE_STOPPED: + return 0; + } + + log_dhcp6_client(client, "Recv %s", + dhcp6_message_type_to_string(message->type)); + + return 0; +} + +static int client_get_lifetime(sd_dhcp6_client *client, uint32_t *lifetime_t1, + uint32_t *lifetime_t2) { + assert_return(client, -EINVAL); + assert_return(client->lease, -EINVAL); + + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA) && client->lease->ia.addresses) { + *lifetime_t1 = be32toh(client->lease->ia.ia_na.lifetime_t1); + *lifetime_t2 = be32toh(client->lease->ia.ia_na.lifetime_t2); + + return 0; + } + + if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD) && client->lease->pd.addresses) { + *lifetime_t1 = be32toh(client->lease->pd.ia_pd.lifetime_t1); + *lifetime_t2 = be32toh(client->lease->pd.ia_pd.lifetime_t2); + + return 0; + } + + return -ENOMSG; +} + +static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { + int r; + usec_t timeout, time_now; + char time_string[FORMAT_TIMESPAN_MAX]; + uint32_t lifetime_t1, lifetime_t2; + + assert_return(client, -EINVAL); + assert_return(client->event, -EINVAL); + assert_return(client->ifindex > 0, -EINVAL); + assert_return(client->state != state, -EINVAL); + + (void) event_source_disable(client->timeout_resend_expire); + (void) event_source_disable(client->timeout_resend); + client->retransmit_time = 0; + client->retransmit_count = 0; + + r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return r; + + if (!client->receive_message) { + r = sd_event_add_io(client->event, &client->receive_message, + client->fd, EPOLLIN, client_receive_message, + client); + if (r < 0) + goto error; + + r = sd_event_source_set_priority(client->receive_message, + client->event_priority); + if (r < 0) + goto error; + + r = sd_event_source_set_description(client->receive_message, + "dhcp6-receive-message"); + if (r < 0) + goto error; + } + + switch (state) { + case DHCP6_STATE_STOPPED: + if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { + client->state = DHCP6_STATE_STOPPED; + + return 0; + } + + _fallthrough_; + case DHCP6_STATE_SOLICITATION: + client->state = DHCP6_STATE_SOLICITATION; + + break; + + case DHCP6_STATE_INFORMATION_REQUEST: + case DHCP6_STATE_REQUEST: + case DHCP6_STATE_RENEW: + case DHCP6_STATE_REBIND: + + client->state = state; + + break; + + case DHCP6_STATE_BOUND: + + r = client_get_lifetime(client, &lifetime_t1, &lifetime_t2); + if (r < 0) + goto error; + + if (lifetime_t1 == 0xffffffff || lifetime_t2 == 0xffffffff) { + log_dhcp6_client(client, "Infinite T1 0x%08x or T2 0x%08x", + lifetime_t1, lifetime_t2); + + return 0; + } + + timeout = client_timeout_compute_random(lifetime_t1 * USEC_PER_SEC); + + log_dhcp6_client(client, "T1 expires in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); + + r = event_reset_time(client->event, &client->timeout_t1, + clock_boottime_or_monotonic(), + time_now + timeout, 10 * USEC_PER_SEC, + client_timeout_t1, client, + client->event_priority, "dhcp6-t1-timeout", true); + if (r < 0) + goto error; + + timeout = client_timeout_compute_random(lifetime_t2 * USEC_PER_SEC); + + log_dhcp6_client(client, "T2 expires in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC)); + + r = event_reset_time(client->event, &client->timeout_t2, + clock_boottime_or_monotonic(), + time_now + timeout, 10 * USEC_PER_SEC, + client_timeout_t2, client, + client->event_priority, "dhcp6-t2-timeout", true); + if (r < 0) + goto error; + + client->state = state; + + return 0; + } + + client->transaction_id = random_u32() & htobe32(0x00ffffff); + client->transaction_start = time_now; + + r = event_reset_time(client->event, &client->timeout_resend, + clock_boottime_or_monotonic(), + 0, 0, + client_timeout_resend, client, + client->event_priority, "dhcp6-resend-timeout", true); + if (r < 0) + goto error; + + return 0; + + error: + client_reset(client); + return r; +} + +int sd_dhcp6_client_stop(sd_dhcp6_client *client) { + assert_return(client, -EINVAL); + + client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP); + + client->fd = safe_close(client->fd); + + return 0; +} + +int sd_dhcp6_client_is_running(sd_dhcp6_client *client) { + assert_return(client, -EINVAL); + + return client->state != DHCP6_STATE_STOPPED; +} + +int sd_dhcp6_client_start(sd_dhcp6_client *client) { + enum DHCP6State state = DHCP6_STATE_SOLICITATION; + int r = 0; + + assert_return(client, -EINVAL); + assert_return(client->event, -EINVAL); + assert_return(client->ifindex > 0, -EINVAL); + assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &client->local_address) > 0, -EINVAL); + + if (!IN_SET(client->state, DHCP6_STATE_STOPPED)) + return -EBUSY; + + if (!client->information_request && !client->request) + return -EINVAL; + + r = client_reset(client); + if (r < 0) + return r; + + r = client_ensure_iaid(client); + if (r < 0) + return r; + + r = client_ensure_duid(client); + if (r < 0) + return r; + + if (client->fd < 0) { + r = dhcp6_network_bind_udp_socket(client->ifindex, &client->local_address); + if (r < 0) { + _cleanup_free_ char *p = NULL; + + (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &client->local_address, &p); + return log_dhcp6_client_errno(client, r, + "Failed to bind to UDP socket at address %s: %m", strna(p)); + } + + client->fd = r; + } + + if (client->information_request) { + usec_t t = now(CLOCK_MONOTONIC); + + if (t < usec_add(client->information_request_time_usec, client->information_refresh_time_usec)) + return 0; + + client->information_request_time_usec = t; + state = DHCP6_STATE_INFORMATION_REQUEST; + } + + log_dhcp6_client(client, "Started in %s mode", + client->information_request? "Information request": + "Managed"); + + return client_start(client, state); +} + +int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority) { + int r; + + assert_return(client, -EINVAL); + assert_return(!client->event, -EBUSY); + + if (event) + client->event = sd_event_ref(event); + else { + r = sd_event_default(&client->event); + if (r < 0) + return 0; + } + + client->event_priority = priority; + + return 0; +} + +int sd_dhcp6_client_detach_event(sd_dhcp6_client *client) { + assert_return(client, -EINVAL); + + client->event = sd_event_unref(client->event); + + return 0; +} + +sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) { + assert_return(client, NULL); + + return client->event; +} + +static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) { + assert(client); + + client->timeout_resend = sd_event_source_unref(client->timeout_resend); + client->timeout_resend_expire = sd_event_source_unref(client->timeout_resend_expire); + client->timeout_t1 = sd_event_source_unref(client->timeout_t1); + client->timeout_t2 = sd_event_source_unref(client->timeout_t2); + + client_reset(client); + + client->fd = safe_close(client->fd); + + sd_dhcp6_client_detach_event(client); + + free(client->req_opts); + free(client->fqdn); + return mfree(client); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_client, sd_dhcp6_client, dhcp6_client_free); + +int sd_dhcp6_client_new(sd_dhcp6_client **ret) { + _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; + _cleanup_free_ be16_t *req_opts = NULL; + size_t t; + + assert_return(ret, -EINVAL); + + req_opts = new(be16_t, ELEMENTSOF(default_req_opts)); + if (!req_opts) + return -ENOMEM; + + for (t = 0; t < ELEMENTSOF(default_req_opts); t++) + req_opts[t] = htobe16(default_req_opts[t]); + + client = new(sd_dhcp6_client, 1); + if (!client) + return -ENOMEM; + + *client = (sd_dhcp6_client) { + .n_ref = 1, + .ia_na.type = SD_DHCP6_OPTION_IA_NA, + .ia_pd.type = SD_DHCP6_OPTION_IA_PD, + .ifindex = -1, + .request = DHCP6_REQUEST_IA_NA, + .fd = -1, + .req_opts_len = ELEMENTSOF(default_req_opts), + .hint_pd_prefix.iapdprefix.lifetime_preferred = (be32_t) -1, + .hint_pd_prefix.iapdprefix.lifetime_valid = (be32_t) -1, + .req_opts = TAKE_PTR(req_opts), + }; + + *ret = TAKE_PTR(client); + + return 0; +} diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c new file mode 100644 index 00000000..8aebb53c --- /dev/null +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -0,0 +1,400 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014-2015 Intel Corporation. All rights reserved. +***/ + +#include + +#include "alloc-util.h" +#include "dhcp6-lease-internal.h" +#include "dhcp6-protocol.h" +#include "strv.h" +#include "util.h" + +int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) { + DHCP6Address *addr; + uint32_t valid = 0, t; + + assert_return(ia, -EINVAL); + assert_return(expire, -EINVAL); + + LIST_FOREACH(addresses, addr, ia->addresses) { + t = be32toh(addr->iaaddr.lifetime_valid); + if (valid < t) + valid = t; + } + + t = be32toh(ia->ia_na.lifetime_t2); + if (t > valid) + return -EINVAL; + + *expire = valid - t; + + return 0; +} + +DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) { + DHCP6Address *address; + + if (!ia) + return NULL; + + while (ia->addresses) { + address = ia->addresses; + + LIST_REMOVE(addresses, ia->addresses, address); + + free(address); + } + + return NULL; +} + +int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, + size_t len) { + uint8_t *serverid; + + assert_return(lease, -EINVAL); + assert_return(id, -EINVAL); + + serverid = memdup(id, len); + if (!serverid) + return -ENOMEM; + + free_and_replace(lease->serverid, serverid); + lease->serverid_len = len; + + return 0; +} + +int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len) { + assert_return(lease, -EINVAL); + + if (!lease->serverid) + return -ENOMSG; + + if (id) + *id = lease->serverid; + if (len) + *len = lease->serverid_len; + + return 0; +} + +int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference) { + assert_return(lease, -EINVAL); + + lease->preference = preference; + + return 0; +} + +int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference) { + assert_return(preference, -EINVAL); + + if (!lease) + return -EINVAL; + + *preference = lease->preference; + + return 0; +} + +int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease) { + assert_return(lease, -EINVAL); + + lease->rapid_commit = true; + + return 0; +} + +int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit) { + assert_return(lease, -EINVAL); + assert_return(rapid_commit, -EINVAL); + + *rapid_commit = lease->rapid_commit; + + return 0; +} + +int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) { + assert_return(lease, -EINVAL); + assert_return(iaid, -EINVAL); + + *iaid = lease->ia.ia_na.id; + + return 0; +} + +int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid) { + assert_return(lease, -EINVAL); + assert_return(iaid, -EINVAL); + + *iaid = lease->pd.ia_pd.id; + + return 0; +} + +int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr, + uint32_t *lifetime_preferred, + uint32_t *lifetime_valid) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + assert_return(lifetime_preferred, -EINVAL); + assert_return(lifetime_valid, -EINVAL); + + if (!lease->addr_iter) + return -ENOMSG; + + memcpy(addr, &lease->addr_iter->iaaddr.address, + sizeof(struct in6_addr)); + *lifetime_preferred = + be32toh(lease->addr_iter->iaaddr.lifetime_preferred); + *lifetime_valid = be32toh(lease->addr_iter->iaaddr.lifetime_valid); + + lease->addr_iter = lease->addr_iter->addresses_next; + + return 0; +} + +void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) { + if (lease) + lease->addr_iter = lease->ia.addresses; +} + +int sd_dhcp6_lease_get_pd(sd_dhcp6_lease *lease, struct in6_addr *prefix, + uint8_t *prefix_len, + uint32_t *lifetime_preferred, + uint32_t *lifetime_valid) { + assert_return(lease, -EINVAL); + assert_return(prefix, -EINVAL); + assert_return(prefix_len, -EINVAL); + assert_return(lifetime_preferred, -EINVAL); + assert_return(lifetime_valid, -EINVAL); + + if (!lease->prefix_iter) + return -ENOMSG; + + memcpy(prefix, &lease->prefix_iter->iapdprefix.address, + sizeof(struct in6_addr)); + *prefix_len = lease->prefix_iter->iapdprefix.prefixlen; + *lifetime_preferred = + be32toh(lease->prefix_iter->iapdprefix.lifetime_preferred); + *lifetime_valid = + be32toh(lease->prefix_iter->iapdprefix.lifetime_valid); + + lease->prefix_iter = lease->prefix_iter->addresses_next; + + return 0; +} + +void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease *lease) { + if (lease) + lease->prefix_iter = lease->pd.addresses; +} + +int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { + int r; + + assert_return(lease, -EINVAL); + assert_return(optval, -EINVAL); + + if (!optlen) + return 0; + + r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns, + lease->dns_count, + &lease->dns_allocated); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Invalid DNS server option: %m"); + + lease->dns_count = r; + + return 0; +} + +int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs) { + assert_return(lease, -EINVAL); + assert_return(addrs, -EINVAL); + + if (lease->dns_count) { + *addrs = lease->dns; + return lease->dns_count; + } + + return -ENOENT; +} + +int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval, + size_t optlen) { + int r; + char **domains; + + assert_return(lease, -EINVAL); + assert_return(optval, -EINVAL); + + if (!optlen) + return 0; + + r = dhcp6_option_parse_domainname(optval, optlen, &domains); + if (r < 0) + return 0; + + strv_free_and_replace(lease->domains, domains); + lease->domains_count = r; + + return r; +} + +int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) { + assert_return(lease, -EINVAL); + assert_return(domains, -EINVAL); + + if (lease->domains_count) { + *domains = lease->domains; + return lease->domains_count; + } + + return -ENOENT; +} + +int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { + int r; + uint16_t subopt; + size_t sublen; + uint8_t *subval; + + assert_return(lease, -EINVAL); + assert_return(optval, -EINVAL); + + lease->ntp = mfree(lease->ntp); + lease->ntp_count = 0; + lease->ntp_allocated = 0; + + while ((r = dhcp6_option_parse(&optval, &optlen, &subopt, &sublen, + &subval)) >= 0) { + int s; + char **servers; + + switch(subopt) { + case DHCP6_NTP_SUBOPTION_SRV_ADDR: + case DHCP6_NTP_SUBOPTION_MC_ADDR: + if (sublen != 16) + return 0; + + s = dhcp6_option_parse_ip6addrs(subval, sublen, + &lease->ntp, + lease->ntp_count, + &lease->ntp_allocated); + if (s < 0) + return s; + + lease->ntp_count = s; + + break; + + case DHCP6_NTP_SUBOPTION_SRV_FQDN: + r = dhcp6_option_parse_domainname(subval, sublen, + &servers); + if (r < 0) + return 0; + + strv_free_and_replace(lease->ntp_fqdn, servers); + lease->ntp_fqdn_count = r; + + break; + } + } + + if (r != -ENOMSG) + return r; + + return 0; +} + +int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) { + int r; + + assert_return(lease, -EINVAL); + assert_return(optval, -EINVAL); + + if (!optlen) + return 0; + + if (lease->ntp || lease->ntp_fqdn) { + log_dhcp6_client(client, "NTP information already provided"); + + return 0; + } + + log_dhcp6_client(client, "Using deprecated SNTP information"); + + r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp, + lease->ntp_count, + &lease->ntp_allocated); + if (r < 0) + return log_dhcp6_client_errno(client, r, "Invalid SNTP server option: %m"); + + lease->ntp_count = r; + + return 0; +} + +int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, + struct in6_addr **addrs) { + assert_return(lease, -EINVAL); + assert_return(addrs, -EINVAL); + + if (lease->ntp_count) { + *addrs = lease->ntp; + return lease->ntp_count; + } + + return -ENOENT; +} + +int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) { + assert_return(lease, -EINVAL); + assert_return(ntp_fqdn, -EINVAL); + + if (lease->ntp_fqdn_count) { + *ntp_fqdn = lease->ntp_fqdn; + return lease->ntp_fqdn_count; + } + + return -ENOENT; +} + +static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) { + assert(lease); + + free(lease->serverid); + dhcp6_lease_free_ia(&lease->ia); + dhcp6_lease_free_ia(&lease->pd); + + free(lease->dns); + + lease->domains = strv_free(lease->domains); + + free(lease->ntp); + + lease->ntp_fqdn = strv_free(lease->ntp_fqdn); + return mfree(lease); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease, sd_dhcp6_lease, dhcp6_lease_free); + +int dhcp6_lease_new(sd_dhcp6_lease **ret) { + sd_dhcp6_lease *lease; + + lease = new0(sd_dhcp6_lease, 1); + if (!lease) + return -ENOMEM; + + lease->n_ref = 1; + + LIST_HEAD_INIT(lease->ia.addresses); + + *ret = lease; + return 0; +} diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c new file mode 100644 index 00000000..d957202a --- /dev/null +++ b/src/libsystemd-network/sd-ipv4acd.c @@ -0,0 +1,485 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Axis Communications AB. All rights reserved. +***/ + +#include +#include +#include +#include +#include + +#include "sd-ipv4acd.h" + +#include "alloc-util.h" +#include "arp-util.h" +#include "ether-addr-util.h" +#include "event-util.h" +#include "fd-util.h" +#include "in-addr-util.h" +#include "list.h" +#include "random-util.h" +#include "siphash24.h" +#include "string-util.h" +#include "time-util.h" + +/* Constants from the RFC */ +#define PROBE_WAIT_USEC (1U * USEC_PER_SEC) +#define PROBE_NUM 3U +#define PROBE_MIN_USEC (1U * USEC_PER_SEC) +#define PROBE_MAX_USEC (2U * USEC_PER_SEC) +#define ANNOUNCE_WAIT_USEC (2U * USEC_PER_SEC) +#define ANNOUNCE_NUM 2U +#define ANNOUNCE_INTERVAL_USEC (2U * USEC_PER_SEC) +#define MAX_CONFLICTS 10U +#define RATE_LIMIT_INTERVAL_USEC (60U * USEC_PER_SEC) +#define DEFEND_INTERVAL_USEC (10U * USEC_PER_SEC) + +typedef enum IPv4ACDState { + IPV4ACD_STATE_INIT, + IPV4ACD_STATE_STARTED, + IPV4ACD_STATE_WAITING_PROBE, + IPV4ACD_STATE_PROBING, + IPV4ACD_STATE_WAITING_ANNOUNCE, + IPV4ACD_STATE_ANNOUNCING, + IPV4ACD_STATE_RUNNING, + _IPV4ACD_STATE_MAX, + _IPV4ACD_STATE_INVALID = -1 +} IPv4ACDState; + +struct sd_ipv4acd { + unsigned n_ref; + + IPv4ACDState state; + int ifindex; + int fd; + + unsigned n_iteration; + unsigned n_conflict; + + sd_event_source *receive_message_event_source; + sd_event_source *timer_event_source; + + usec_t defend_window; + be32_t address; + + /* External */ + struct ether_addr mac_addr; + + sd_event *event; + int event_priority; + sd_ipv4acd_callback_t callback; + void* userdata; +}; + +#define log_ipv4acd_errno(acd, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "IPV4ACD: " fmt, ##__VA_ARGS__) +#define log_ipv4acd(acd, fmt, ...) log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__) + +static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_counter) { + assert(acd); + assert(st < _IPV4ACD_STATE_MAX); + + if (st == acd->state && !reset_counter) + acd->n_iteration++; + else { + acd->state = st; + acd->n_iteration = 0; + } +} + +static void ipv4acd_reset(sd_ipv4acd *acd) { + assert(acd); + + (void) event_source_disable(acd->timer_event_source); + acd->receive_message_event_source = sd_event_source_unref(acd->receive_message_event_source); + + acd->fd = safe_close(acd->fd); + + ipv4acd_set_state(acd, IPV4ACD_STATE_INIT, true); +} + +static sd_ipv4acd *ipv4acd_free(sd_ipv4acd *acd) { + assert(acd); + + acd->timer_event_source = sd_event_source_unref(acd->timer_event_source); + + ipv4acd_reset(acd); + sd_ipv4acd_detach_event(acd); + + return mfree(acd); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4acd, sd_ipv4acd, ipv4acd_free); + +int sd_ipv4acd_new(sd_ipv4acd **ret) { + _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *acd = NULL; + + assert_return(ret, -EINVAL); + + acd = new(sd_ipv4acd, 1); + if (!acd) + return -ENOMEM; + + *acd = (sd_ipv4acd) { + .n_ref = 1, + .state = IPV4ACD_STATE_INIT, + .ifindex = -1, + .fd = -1, + }; + + *ret = TAKE_PTR(acd); + + return 0; +} + +static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) { + assert(acd); + + if (!acd->callback) + return; + + acd->callback(acd, event, acd->userdata); +} + +int sd_ipv4acd_stop(sd_ipv4acd *acd) { + assert_return(acd, -EINVAL); + + ipv4acd_reset(acd); + + log_ipv4acd(acd, "STOPPED"); + + ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP); + + return 0; +} + +static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata); + +static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_usec) { + usec_t next_timeout, time_now; + + assert(acd); + + next_timeout = usec; + + if (random_usec > 0) + next_timeout += (usec_t) random_u64() % random_usec; + + assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &time_now) >= 0); + + return event_reset_time(acd->event, &acd->timer_event_source, + clock_boottime_or_monotonic(), + time_now + next_timeout, 0, + ipv4acd_on_timeout, acd, + acd->event_priority, "ipv4acd-timer", true); +} + +static bool ipv4acd_arp_conflict(sd_ipv4acd *acd, struct ether_arp *arp) { + assert(acd); + assert(arp); + + /* see the BPF */ + if (memcmp(arp->arp_spa, &acd->address, sizeof(acd->address)) == 0) + return true; + + /* the TPA matched instead of the SPA, this is not a conflict */ + return false; +} + +static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) { + sd_ipv4acd *acd = userdata; + int r = 0; + + assert(acd); + + switch (acd->state) { + + case IPV4ACD_STATE_STARTED: + ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_PROBE, true); + + if (acd->n_conflict >= MAX_CONFLICTS) { + char ts[FORMAT_TIMESPAN_MAX]; + log_ipv4acd(acd, "Max conflicts reached, delaying by %s", format_timespan(ts, sizeof(ts), RATE_LIMIT_INTERVAL_USEC, 0)); + + r = ipv4acd_set_next_wakeup(acd, RATE_LIMIT_INTERVAL_USEC, PROBE_WAIT_USEC); + if (r < 0) + goto fail; + } else { + r = ipv4acd_set_next_wakeup(acd, 0, PROBE_WAIT_USEC); + if (r < 0) + goto fail; + } + + break; + + case IPV4ACD_STATE_WAITING_PROBE: + case IPV4ACD_STATE_PROBING: + /* Send a probe */ + r = arp_send_probe(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); + if (r < 0) { + log_ipv4acd_errno(acd, r, "Failed to send ARP probe: %m"); + goto fail; + } else { + _cleanup_free_ char *address = NULL; + union in_addr_union addr = { .in.s_addr = acd->address }; + + (void) in_addr_to_string(AF_INET, &addr, &address); + log_ipv4acd(acd, "Probing %s", strna(address)); + } + + if (acd->n_iteration < PROBE_NUM - 2) { + ipv4acd_set_state(acd, IPV4ACD_STATE_PROBING, false); + + r = ipv4acd_set_next_wakeup(acd, PROBE_MIN_USEC, (PROBE_MAX_USEC-PROBE_MIN_USEC)); + if (r < 0) + goto fail; + } else { + ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_ANNOUNCE, true); + + r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_WAIT_USEC, 0); + if (r < 0) + goto fail; + } + + break; + + case IPV4ACD_STATE_ANNOUNCING: + if (acd->n_iteration >= ANNOUNCE_NUM - 1) { + ipv4acd_set_state(acd, IPV4ACD_STATE_RUNNING, false); + break; + } + + _fallthrough_; + case IPV4ACD_STATE_WAITING_ANNOUNCE: + /* Send announcement packet */ + r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); + if (r < 0) { + log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); + goto fail; + } else + log_ipv4acd(acd, "ANNOUNCE"); + + ipv4acd_set_state(acd, IPV4ACD_STATE_ANNOUNCING, false); + + r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_INTERVAL_USEC, 0); + if (r < 0) + goto fail; + + if (acd->n_iteration == 0) { + acd->n_conflict = 0; + ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_BIND); + } + + break; + + default: + assert_not_reached("Invalid state."); + } + + return 0; + +fail: + sd_ipv4acd_stop(acd); + return 0; +} + +static void ipv4acd_on_conflict(sd_ipv4acd *acd) { + _cleanup_free_ char *address = NULL; + union in_addr_union addr = { .in.s_addr = acd->address }; + + assert(acd); + + acd->n_conflict++; + + (void) in_addr_to_string(AF_INET, &addr, &address); + log_ipv4acd(acd, "Conflict on %s (%u)", strna(address), acd->n_conflict); + + ipv4acd_reset(acd); + ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_CONFLICT); +} + +static int ipv4acd_on_packet( + sd_event_source *s, + int fd, + uint32_t revents, + void *userdata) { + + sd_ipv4acd *acd = userdata; + struct ether_arp packet; + ssize_t n; + int r; + + assert(s); + assert(acd); + assert(fd >= 0); + + n = recv(fd, &packet, sizeof(struct ether_arp), 0); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m"); + goto fail; + } + if ((size_t) n != sizeof(struct ether_arp)) { + log_ipv4acd(acd, "Ignoring too short ARP packet."); + return 0; + } + + switch (acd->state) { + + case IPV4ACD_STATE_ANNOUNCING: + case IPV4ACD_STATE_RUNNING: + + if (ipv4acd_arp_conflict(acd, &packet)) { + usec_t ts; + + assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &ts) >= 0); + + /* Defend address */ + if (ts > acd->defend_window) { + acd->defend_window = ts + DEFEND_INTERVAL_USEC; + r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); + if (r < 0) { + log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); + goto fail; + } else + log_ipv4acd(acd, "DEFEND"); + + } else + ipv4acd_on_conflict(acd); + } + break; + + case IPV4ACD_STATE_WAITING_PROBE: + case IPV4ACD_STATE_PROBING: + case IPV4ACD_STATE_WAITING_ANNOUNCE: + /* BPF ensures this packet indicates a conflict */ + ipv4acd_on_conflict(acd); + break; + + default: + assert_not_reached("Invalid state."); + } + + return 0; + +fail: + sd_ipv4acd_stop(acd); + return 0; +} + +int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int ifindex) { + assert_return(acd, -EINVAL); + assert_return(ifindex > 0, -EINVAL); + assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); + + acd->ifindex = ifindex; + + return 0; +} + +int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr) { + assert_return(acd, -EINVAL); + assert_return(addr, -EINVAL); + assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); + + acd->mac_addr = *addr; + + return 0; +} + +int sd_ipv4acd_detach_event(sd_ipv4acd *acd) { + assert_return(acd, -EINVAL); + + acd->event = sd_event_unref(acd->event); + + return 0; +} + +int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority) { + int r; + + assert_return(acd, -EINVAL); + assert_return(!acd->event, -EBUSY); + + if (event) + acd->event = sd_event_ref(event); + else { + r = sd_event_default(&acd->event); + if (r < 0) + return r; + } + + acd->event_priority = priority; + + return 0; +} + +int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata) { + assert_return(acd, -EINVAL); + + acd->callback = cb; + acd->userdata = userdata; + + return 0; +} + +int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address) { + assert_return(acd, -EINVAL); + assert_return(address, -EINVAL); + assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); + + acd->address = address->s_addr; + + return 0; +} + +int sd_ipv4acd_is_running(sd_ipv4acd *acd) { + assert_return(acd, false); + + return acd->state != IPV4ACD_STATE_INIT; +} + +int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts) { + int r; + + assert_return(acd, -EINVAL); + assert_return(acd->event, -EINVAL); + assert_return(acd->ifindex > 0, -EINVAL); + assert_return(acd->address != 0, -EINVAL); + assert_return(!ether_addr_is_null(&acd->mac_addr), -EINVAL); + assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); + + r = arp_network_bind_raw_socket(acd->ifindex, acd->address, &acd->mac_addr); + if (r < 0) + return r; + + safe_close(acd->fd); + acd->fd = r; + acd->defend_window = 0; + + if (reset_conflicts) + acd->n_conflict = 0; + + r = sd_event_add_io(acd->event, &acd->receive_message_event_source, acd->fd, EPOLLIN, ipv4acd_on_packet, acd); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(acd->receive_message_event_source, acd->event_priority); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(acd->receive_message_event_source, "ipv4acd-receive-message"); + + r = ipv4acd_set_next_wakeup(acd, 0, 0); + if (r < 0) + goto fail; + + ipv4acd_set_state(acd, IPV4ACD_STATE_STARTED, true); + return 0; + +fail: + ipv4acd_reset(acd); + return r; +} diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c new file mode 100644 index 00000000..aa1ece41 --- /dev/null +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -0,0 +1,321 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Axis Communications AB. All rights reserved. +***/ + +#include +#include +#include +#include + +#include "sd-id128.h" +#include "sd-ipv4acd.h" +#include "sd-ipv4ll.h" + +#include "alloc-util.h" +#include "ether-addr-util.h" +#include "in-addr-util.h" +#include "list.h" +#include "random-util.h" +#include "siphash24.h" +#include "sparse-endian.h" +#include "string-util.h" +#include "util.h" + +#define IPV4LL_NETWORK UINT32_C(0xA9FE0000) +#define IPV4LL_NETMASK UINT32_C(0xFFFF0000) + +#define IPV4LL_DONT_DESTROY(ll) \ + _cleanup_(sd_ipv4ll_unrefp) _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll) + +struct sd_ipv4ll { + unsigned n_ref; + + sd_ipv4acd *acd; + + be32_t address; /* the address pushed to ACD */ + struct ether_addr mac; + + struct { + le64_t value; + le64_t generation; + } seed; + bool seed_set; + + /* External */ + be32_t claimed_address; + + sd_ipv4ll_callback_t callback; + void* userdata; +}; + +#define log_ipv4ll_errno(ll, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "IPV4LL: " fmt, ##__VA_ARGS__) +#define log_ipv4ll(ll, fmt, ...) log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__) + +static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata); + +static sd_ipv4ll *ipv4ll_free(sd_ipv4ll *ll) { + assert(ll); + + sd_ipv4acd_unref(ll->acd); + return mfree(ll); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4ll, sd_ipv4ll, ipv4ll_free); + +int sd_ipv4ll_new(sd_ipv4ll **ret) { + _cleanup_(sd_ipv4ll_unrefp) sd_ipv4ll *ll = NULL; + int r; + + assert_return(ret, -EINVAL); + + ll = new0(sd_ipv4ll, 1); + if (!ll) + return -ENOMEM; + + ll->n_ref = 1; + + r = sd_ipv4acd_new(&ll->acd); + if (r < 0) + return r; + + r = sd_ipv4acd_set_callback(ll->acd, ipv4ll_on_acd, ll); + if (r < 0) + return r; + + *ret = TAKE_PTR(ll); + + return 0; +} + +int sd_ipv4ll_stop(sd_ipv4ll *ll) { + assert_return(ll, -EINVAL); + + return sd_ipv4acd_stop(ll->acd); +} + +int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int ifindex) { + assert_return(ll, -EINVAL); + assert_return(ifindex > 0, -EINVAL); + assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); + + return sd_ipv4acd_set_ifindex(ll->acd, ifindex); +} + +int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) { + int r; + + assert_return(ll, -EINVAL); + assert_return(addr, -EINVAL); + assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); + + r = sd_ipv4acd_set_mac(ll->acd, addr); + if (r < 0) + return r; + + ll->mac = *addr; + return 0; +} + +int sd_ipv4ll_detach_event(sd_ipv4ll *ll) { + assert_return(ll, -EINVAL); + + return sd_ipv4acd_detach_event(ll->acd); +} + +int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority) { + assert_return(ll, -EINVAL); + + return sd_ipv4acd_attach_event(ll->acd, event, priority); +} + +int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata) { + assert_return(ll, -EINVAL); + + ll->callback = cb; + ll->userdata = userdata; + + return 0; +} + +int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address) { + assert_return(ll, -EINVAL); + assert_return(address, -EINVAL); + + if (ll->claimed_address == 0) + return -ENOENT; + + address->s_addr = ll->claimed_address; + + return 0; +} + +int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed) { + assert_return(ll, -EINVAL); + assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); + + ll->seed.value = htole64(seed); + ll->seed_set = true; + + return 0; +} + +int sd_ipv4ll_is_running(sd_ipv4ll *ll) { + assert_return(ll, false); + + return sd_ipv4acd_is_running(ll->acd); +} + +static bool ipv4ll_address_is_valid(const struct in_addr *address) { + assert(address); + + if (!in_addr_is_link_local(AF_INET, (const union in_addr_union *) address)) + return false; + + return !IN_SET(be32toh(address->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U); +} + +int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) { + int r; + + assert_return(ll, -EINVAL); + assert_return(address, -EINVAL); + assert_return(ipv4ll_address_is_valid(address), -EINVAL); + + r = sd_ipv4acd_set_address(ll->acd, address); + if (r < 0) + return r; + + ll->address = address->s_addr; + + return 0; +} + +#define PICK_HASH_KEY SD_ID128_MAKE(15,ac,82,a6,d6,3f,49,78,98,77,5d,0c,69,02,94,0b) + +static int ipv4ll_pick_address(sd_ipv4ll *ll) { + _cleanup_free_ char *address = NULL; + be32_t addr; + + assert(ll); + + do { + uint64_t h; + + h = siphash24(&ll->seed, sizeof(ll->seed), PICK_HASH_KEY.bytes); + + /* Increase the generation counter by one */ + ll->seed.generation = htole64(le64toh(ll->seed.generation) + 1); + + addr = htobe32((h & UINT32_C(0x0000FFFF)) | IPV4LL_NETWORK); + } while (addr == ll->address || + IN_SET(be32toh(addr) & 0x0000FF00U, 0x0000U, 0xFF00U)); + + (void) in_addr_to_string(AF_INET, &(union in_addr_union) { .in.s_addr = addr }, &address); + log_ipv4ll(ll, "Picked new IP address %s.", strna(address)); + + return sd_ipv4ll_set_address(ll, &(struct in_addr) { addr }); +} + +#define MAC_HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2) + +static int ipv4ll_start_internal(sd_ipv4ll *ll, bool reset_generation) { + int r; + bool picked_address = false; + + assert_return(ll, -EINVAL); + assert_return(!ether_addr_is_null(&ll->mac), -EINVAL); + + /* If no random seed is set, generate some from the MAC address */ + if (!ll->seed_set) + ll->seed.value = htole64(siphash24(ll->mac.ether_addr_octet, ETH_ALEN, MAC_HASH_KEY.bytes)); + + if (reset_generation) + ll->seed.generation = 0; + + if (ll->address == 0) { + r = ipv4ll_pick_address(ll); + if (r < 0) + return r; + + picked_address = true; + } + + r = sd_ipv4acd_start(ll->acd, reset_generation); + if (r < 0) { + + /* We couldn't start? If so, let's forget the picked address again, the user might make a change and + * retry, and we want the new data to take effect when picking an address. */ + if (picked_address) + ll->address = 0; + + return r; + } + + return 0; +} + +int sd_ipv4ll_start(sd_ipv4ll *ll) { + assert_return(ll, -EINVAL); + assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); + + return ipv4ll_start_internal(ll, true); +} + +int sd_ipv4ll_restart(sd_ipv4ll *ll) { + ll->address = 0; + + return ipv4ll_start_internal(ll, false); +} + +static void ipv4ll_client_notify(sd_ipv4ll *ll, int event) { + assert(ll); + + if (ll->callback) + ll->callback(ll, event, ll->userdata); +} + +void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) { + sd_ipv4ll *ll = userdata; + IPV4LL_DONT_DESTROY(ll); + int r; + + assert(acd); + assert(ll); + + switch (event) { + + case SD_IPV4ACD_EVENT_STOP: + ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); + ll->claimed_address = 0; + break; + + case SD_IPV4ACD_EVENT_BIND: + ll->claimed_address = ll->address; + ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_BIND); + break; + + case SD_IPV4ACD_EVENT_CONFLICT: + /* if an address was already bound we must call up to the + user to handle this, otherwise we just try again */ + if (ll->claimed_address != 0) { + ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_CONFLICT); + + ll->claimed_address = 0; + } else { + r = sd_ipv4ll_restart(ll); + if (r < 0) + goto error; + } + + break; + + default: + assert_not_reached("Invalid IPv4ACD event."); + } + + return; + +error: + ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); +} diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c new file mode 100644 index 00000000..1f28c573 --- /dev/null +++ b/src/libsystemd-network/sd-lldp.c @@ -0,0 +1,498 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-lldp.h" + +#include "alloc-util.h" +#include "ether-addr-util.h" +#include "event-util.h" +#include "fd-util.h" +#include "lldp-internal.h" +#include "lldp-neighbor.h" +#include "lldp-network.h" +#include "memory-util.h" +#include "socket-util.h" +#include "sort-util.h" +#include "string-table.h" + +#define LLDP_DEFAULT_NEIGHBORS_MAX 128U + +static const char * const lldp_event_table[_SD_LLDP_EVENT_MAX] = { + [SD_LLDP_EVENT_ADDED] = "added", + [SD_LLDP_EVENT_REMOVED] = "removed", + [SD_LLDP_EVENT_UPDATED] = "updated", + [SD_LLDP_EVENT_REFRESHED] = "refreshed", +}; + +DEFINE_STRING_TABLE_LOOKUP(lldp_event, sd_lldp_event); + +static void lldp_flush_neighbors(sd_lldp *lldp) { + assert(lldp); + + hashmap_clear(lldp->neighbor_by_id); +} + +static void lldp_callback(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n) { + assert(lldp); + assert(event >= 0 && event < _SD_LLDP_EVENT_MAX); + + if (!lldp->callback) { + log_lldp("Received '%s' event.", lldp_event_to_string(event)); + return; + } + + log_lldp("Invoking callback for '%s' event.", lldp_event_to_string(event)); + lldp->callback(lldp, event, n, lldp->userdata); +} + +static int lldp_make_space(sd_lldp *lldp, size_t extra) { + usec_t t = USEC_INFINITY; + bool changed = false; + + assert(lldp); + + /* Remove all entries that are past their TTL, and more until at least the specified number of extra entries + * are free. */ + + for (;;) { + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; + + n = prioq_peek(lldp->neighbor_by_expiry); + if (!n) + break; + + sd_lldp_neighbor_ref(n); + + if (hashmap_size(lldp->neighbor_by_id) > LESS_BY(lldp->neighbors_max, extra)) + goto remove_one; + + if (t == USEC_INFINITY) + t = now(clock_boottime_or_monotonic()); + + if (n->until > t) + break; + + remove_one: + lldp_neighbor_unlink(n); + lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, n); + changed = true; + } + + return changed; +} + +static bool lldp_keep_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) { + assert(lldp); + assert(n); + + /* Don't keep data with a zero TTL */ + if (n->ttl <= 0) + return false; + + /* Filter out data from the filter address */ + if (!ether_addr_is_null(&lldp->filter_address) && + ether_addr_equal(&lldp->filter_address, &n->source_address)) + return false; + + /* Only add if the neighbor has a capability we are interested in. Note that we also store all neighbors with + * no caps field set. */ + if (n->has_capabilities && + (n->enabled_capabilities & lldp->capability_mask) == 0) + return false; + + /* Keep everything else */ + return true; +} + +static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor); + +static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) { + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *old = NULL; + bool keep; + int r; + + assert(lldp); + assert(n); + assert(!n->lldp); + + keep = lldp_keep_neighbor(lldp, n); + + /* First retrieve the old entry for this MSAP */ + old = hashmap_get(lldp->neighbor_by_id, &n->id); + if (old) { + sd_lldp_neighbor_ref(old); + + if (!keep) { + lldp_neighbor_unlink(old); + lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old); + return 0; + } + + if (lldp_neighbor_equal(n, old)) { + /* Is this equal, then restart the TTL counter, but don't do anything else. */ + old->timestamp = n->timestamp; + lldp_start_timer(lldp, old); + lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old); + return 0; + } + + /* Data changed, remove the old entry, and add a new one */ + lldp_neighbor_unlink(old); + + } else if (!keep) + return 0; + + /* Then, make room for at least one new neighbor */ + lldp_make_space(lldp, 1); + + r = hashmap_put(lldp->neighbor_by_id, &n->id, n); + if (r < 0) + goto finish; + + r = prioq_put(lldp->neighbor_by_expiry, n, &n->prioq_idx); + if (r < 0) { + assert_se(hashmap_remove(lldp->neighbor_by_id, &n->id) == n); + goto finish; + } + + n->lldp = lldp; + + lldp_start_timer(lldp, n); + lldp_callback(lldp, old ? SD_LLDP_EVENT_UPDATED : SD_LLDP_EVENT_ADDED, n); + + return 1; + +finish: + if (old) + lldp_callback(lldp, SD_LLDP_EVENT_REMOVED, old); + + return r; +} + +static int lldp_handle_datagram(sd_lldp *lldp, sd_lldp_neighbor *n) { + int r; + + assert(lldp); + assert(n); + + r = lldp_neighbor_parse(n); + if (r == -EBADMSG) /* Ignore bad messages */ + return 0; + if (r < 0) + return r; + + r = lldp_add_neighbor(lldp, n); + if (r < 0) { + log_lldp_errno(r, "Failed to add datagram. Ignoring."); + return 0; + } + + log_lldp("Successfully processed LLDP datagram."); + return 0; +} + +static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; + ssize_t space, length; + sd_lldp *lldp = userdata; + struct timespec ts; + + assert(fd >= 0); + assert(lldp); + + space = next_datagram_size_fd(fd); + if (space < 0) + return log_lldp_errno(space, "Failed to determine datagram size to read: %m"); + + n = lldp_neighbor_new(space); + if (!n) + return -ENOMEM; + + length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT); + if (length < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + return log_lldp_errno(errno, "Failed to read LLDP datagram: %m"); + } + + if ((size_t) length != n->raw_size) { + log_lldp("Packet size mismatch."); + return -EINVAL; + } + + /* Try to get the timestamp of this packet if it is known */ + if (ioctl(fd, SIOCGSTAMPNS, &ts) >= 0) + triple_timestamp_from_realtime(&n->timestamp, timespec_load(&ts)); + else + triple_timestamp_get(&n->timestamp); + + return lldp_handle_datagram(lldp, n); +} + +static void lldp_reset(sd_lldp *lldp) { + assert(lldp); + + (void) event_source_disable(lldp->timer_event_source); + lldp->io_event_source = sd_event_source_unref(lldp->io_event_source); + lldp->fd = safe_close(lldp->fd); +} + +_public_ int sd_lldp_start(sd_lldp *lldp) { + int r; + + assert_return(lldp, -EINVAL); + assert_return(lldp->event, -EINVAL); + assert_return(lldp->ifindex > 0, -EINVAL); + + if (lldp->fd >= 0) + return 0; + + assert(!lldp->io_event_source); + + lldp->fd = lldp_network_bind_raw_socket(lldp->ifindex); + if (lldp->fd < 0) + return lldp->fd; + + r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io"); + + log_lldp("Started LLDP client"); + return 1; + +fail: + lldp_reset(lldp); + return r; +} + +_public_ int sd_lldp_stop(sd_lldp *lldp) { + assert_return(lldp, -EINVAL); + + if (lldp->fd < 0) + return 0; + + log_lldp("Stopping LLDP client"); + + lldp_reset(lldp); + lldp_flush_neighbors(lldp); + + return 1; +} + +_public_ int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority) { + int r; + + assert_return(lldp, -EINVAL); + assert_return(lldp->fd < 0, -EBUSY); + assert_return(!lldp->event, -EBUSY); + + if (event) + lldp->event = sd_event_ref(event); + else { + r = sd_event_default(&lldp->event); + if (r < 0) + return r; + } + + lldp->event_priority = priority; + + return 0; +} + +_public_ int sd_lldp_detach_event(sd_lldp *lldp) { + + assert_return(lldp, -EINVAL); + assert_return(lldp->fd < 0, -EBUSY); + + lldp->event = sd_event_unref(lldp->event); + return 0; +} + +_public_ sd_event* sd_lldp_get_event(sd_lldp *lldp) { + assert_return(lldp, NULL); + + return lldp->event; +} + +_public_ int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata) { + assert_return(lldp, -EINVAL); + + lldp->callback = cb; + lldp->userdata = userdata; + + return 0; +} + +_public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) { + assert_return(lldp, -EINVAL); + assert_return(ifindex > 0, -EINVAL); + assert_return(lldp->fd < 0, -EBUSY); + + lldp->ifindex = ifindex; + return 0; +} + +static sd_lldp* lldp_free(sd_lldp *lldp) { + assert(lldp); + + lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source); + + lldp_reset(lldp); + sd_lldp_detach_event(lldp); + lldp_flush_neighbors(lldp); + + hashmap_free(lldp->neighbor_by_id); + prioq_free(lldp->neighbor_by_expiry); + return mfree(lldp); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_lldp, sd_lldp, lldp_free); + +_public_ int sd_lldp_new(sd_lldp **ret) { + _cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL; + int r; + + assert_return(ret, -EINVAL); + + lldp = new(sd_lldp, 1); + if (!lldp) + return -ENOMEM; + + *lldp = (sd_lldp) { + .n_ref = 1, + .fd = -1, + .neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX, + .capability_mask = (uint16_t) -1, + }; + + lldp->neighbor_by_id = hashmap_new(&lldp_neighbor_hash_ops); + if (!lldp->neighbor_by_id) + return -ENOMEM; + + r = prioq_ensure_allocated(&lldp->neighbor_by_expiry, lldp_neighbor_prioq_compare_func); + if (r < 0) + return r; + + *ret = TAKE_PTR(lldp); + + return 0; +} + +static int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) { + return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id); +} + +static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) { + sd_lldp *lldp = userdata; + int r; + + r = lldp_make_space(lldp, 0); + if (r < 0) + return log_lldp_errno(r, "Failed to make space: %m"); + + r = lldp_start_timer(lldp, NULL); + if (r < 0) + return log_lldp_errno(r, "Failed to restart timer: %m"); + + return 0; +} + +static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) { + sd_lldp_neighbor *n; + + assert(lldp); + + if (neighbor) + lldp_neighbor_start_ttl(neighbor); + + n = prioq_peek(lldp->neighbor_by_expiry); + if (!n) + return event_source_disable(lldp->timer_event_source); + + if (!lldp->event) + return 0; + + return event_reset_time(lldp->event, &lldp->timer_event_source, + clock_boottime_or_monotonic(), + n->until, 0, + on_timer_event, lldp, + lldp->event_priority, "lldp-timer", true); +} + +_public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) { + sd_lldp_neighbor **l = NULL, *n; + Iterator i; + int k = 0, r; + + assert_return(lldp, -EINVAL); + assert_return(ret, -EINVAL); + + if (hashmap_isempty(lldp->neighbor_by_id)) { /* Special shortcut */ + *ret = NULL; + return 0; + } + + l = new0(sd_lldp_neighbor*, hashmap_size(lldp->neighbor_by_id)); + if (!l) + return -ENOMEM; + + r = lldp_start_timer(lldp, NULL); + if (r < 0) { + free(l); + return r; + } + + HASHMAP_FOREACH(n, lldp->neighbor_by_id, i) + l[k++] = sd_lldp_neighbor_ref(n); + + assert((size_t) k == hashmap_size(lldp->neighbor_by_id)); + + /* Return things in a stable order */ + typesafe_qsort(l, k, neighbor_compare_func); + *ret = l; + + return k; +} + +_public_ int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t m) { + assert_return(lldp, -EINVAL); + assert_return(m <= 0, -EINVAL); + + lldp->neighbors_max = m; + lldp_make_space(lldp, 0); + + return 0; +} + +_public_ int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask) { + assert_return(lldp, -EINVAL); + assert_return(mask != 0, -EINVAL); + + lldp->capability_mask = mask; + + return 0; +} + +_public_ int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *addr) { + assert_return(lldp, -EINVAL); + + /* In order to deal nicely with bridges that send back our own packets, allow one address to be filtered, so + * that our own can be filtered out here. */ + + if (addr) + lldp->filter_address = *addr; + else + zero(lldp->filter_address); + + return 0; +} diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c new file mode 100644 index 00000000..9922203a --- /dev/null +++ b/src/libsystemd-network/sd-ndisc.c @@ -0,0 +1,388 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include +#include + +#include "sd-ndisc.h" + +#include "alloc-util.h" +#include "event-util.h" +#include "fd-util.h" +#include "icmp6-util.h" +#include "in-addr-util.h" +#include "memory-util.h" +#include "ndisc-internal.h" +#include "ndisc-router.h" +#include "random-util.h" +#include "socket-util.h" +#include "string-table.h" +#include "string-util.h" + +#define NDISC_TIMEOUT_NO_RA_USEC (NDISC_ROUTER_SOLICITATION_INTERVAL * NDISC_MAX_ROUTER_SOLICITATIONS) + +static const char * const ndisc_event_table[_SD_NDISC_EVENT_MAX] = { + [SD_NDISC_EVENT_TIMEOUT] = "timeout", + [SD_NDISC_EVENT_ROUTER] = "router", +}; + +DEFINE_STRING_TABLE_LOOKUP(ndisc_event, sd_ndisc_event); + +static void ndisc_callback(sd_ndisc *ndisc, sd_ndisc_event event, sd_ndisc_router *rt) { + assert(ndisc); + assert(event >= 0 && event < _SD_NDISC_EVENT_MAX); + + if (!ndisc->callback) { + log_ndisc("Received '%s' event.", ndisc_event_to_string(event)); + return; + } + + log_ndisc("Invoking callback for '%s' event.", ndisc_event_to_string(event)); + ndisc->callback(ndisc, event, rt, ndisc->userdata); +} + +_public_ int sd_ndisc_set_callback( + sd_ndisc *nd, + sd_ndisc_callback_t callback, + void *userdata) { + + assert_return(nd, -EINVAL); + + nd->callback = callback; + nd->userdata = userdata; + + return 0; +} + +_public_ int sd_ndisc_set_ifindex(sd_ndisc *nd, int ifindex) { + assert_return(nd, -EINVAL); + assert_return(ifindex > 0, -EINVAL); + assert_return(nd->fd < 0, -EBUSY); + + nd->ifindex = ifindex; + return 0; +} + +_public_ int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr) { + assert_return(nd, -EINVAL); + + if (mac_addr) + nd->mac_addr = *mac_addr; + else + zero(nd->mac_addr); + + return 0; +} + +_public_ int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority) { + int r; + + assert_return(nd, -EINVAL); + assert_return(nd->fd < 0, -EBUSY); + assert_return(!nd->event, -EBUSY); + + if (event) + nd->event = sd_event_ref(event); + else { + r = sd_event_default(&nd->event); + if (r < 0) + return 0; + } + + nd->event_priority = priority; + + return 0; +} + +_public_ int sd_ndisc_detach_event(sd_ndisc *nd) { + + assert_return(nd, -EINVAL); + assert_return(nd->fd < 0, -EBUSY); + + nd->event = sd_event_unref(nd->event); + return 0; +} + +_public_ sd_event *sd_ndisc_get_event(sd_ndisc *nd) { + assert_return(nd, NULL); + + return nd->event; +} + +static void ndisc_reset(sd_ndisc *nd) { + assert(nd); + + (void) event_source_disable(nd->timeout_event_source); + (void) event_source_disable(nd->timeout_no_ra); + nd->retransmit_time = 0; + nd->recv_event_source = sd_event_source_unref(nd->recv_event_source); + nd->fd = safe_close(nd->fd); +} + +static sd_ndisc *ndisc_free(sd_ndisc *nd) { + assert(nd); + + nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source); + nd->timeout_no_ra = sd_event_source_unref(nd->timeout_no_ra); + + ndisc_reset(nd); + sd_ndisc_detach_event(nd); + return mfree(nd); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_ndisc, sd_ndisc, ndisc_free); + +_public_ int sd_ndisc_new(sd_ndisc **ret) { + _cleanup_(sd_ndisc_unrefp) sd_ndisc *nd = NULL; + + assert_return(ret, -EINVAL); + + nd = new(sd_ndisc, 1); + if (!nd) + return -ENOMEM; + + *nd = (sd_ndisc) { + .n_ref = 1, + .fd = -1, + }; + + *ret = TAKE_PTR(nd); + + return 0; +} + +_public_ int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *mtu) { + assert_return(nd, -EINVAL); + assert_return(mtu, -EINVAL); + + if (nd->mtu == 0) + return -ENODATA; + + *mtu = nd->mtu; + return 0; +} + +_public_ int sd_ndisc_get_hop_limit(sd_ndisc *nd, uint8_t *ret) { + assert_return(nd, -EINVAL); + assert_return(ret, -EINVAL); + + if (nd->hop_limit == 0) + return -ENODATA; + + *ret = nd->hop_limit; + return 0; +} + +static int ndisc_handle_datagram(sd_ndisc *nd, sd_ndisc_router *rt) { + int r; + + assert(nd); + assert(rt); + + r = ndisc_router_parse(rt); + if (r == -EBADMSG) /* Bad packet */ + return 0; + if (r < 0) + return 0; + + /* Update global variables we keep */ + if (rt->mtu > 0) + nd->mtu = rt->mtu; + if (rt->hop_limit > 0) + nd->hop_limit = rt->hop_limit; + + log_ndisc("Received Router Advertisement: flags %s preference %s lifetime %" PRIu16 " sec", + rt->flags & ND_RA_FLAG_MANAGED ? "MANAGED" : rt->flags & ND_RA_FLAG_OTHER ? "OTHER" : "none", + rt->preference == SD_NDISC_PREFERENCE_HIGH ? "high" : rt->preference == SD_NDISC_PREFERENCE_LOW ? "low" : "medium", + rt->lifetime); + + ndisc_callback(nd, SD_NDISC_EVENT_ROUTER, rt); + return 0; +} + +static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(sd_ndisc_router_unrefp) sd_ndisc_router *rt = NULL; + sd_ndisc *nd = userdata; + ssize_t buflen; + int r; + _cleanup_free_ char *addr = NULL; + + assert(s); + assert(nd); + assert(nd->event); + + buflen = next_datagram_size_fd(fd); + if (buflen < 0) + return log_ndisc_errno(buflen, "Failed to determine datagram size to read: %m"); + + rt = ndisc_router_new(buflen); + if (!rt) + return -ENOMEM; + + r = icmp6_receive(fd, NDISC_ROUTER_RAW(rt), rt->raw_size, &rt->address, + &rt->timestamp); + if (r < 0) { + switch (r) { + case -EADDRNOTAVAIL: + (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &rt->address, &addr); + log_ndisc("Received RA from non-link-local address %s. Ignoring", addr); + break; + + case -EMULTIHOP: + log_ndisc("Received RA with invalid hop limit. Ignoring."); + break; + + case -EPFNOSUPPORT: + log_ndisc("Received invalid source address from ICMPv6 socket. Ignoring."); + break; + + case -EAGAIN: /* ignore spurious wakeups */ + break; + + default: + log_ndisc_errno(r, "Unexpected error while reading from ICMPv6, ignoring: %m"); + break; + } + + return 0; + } + + (void) event_source_disable(nd->timeout_event_source); + + return ndisc_handle_datagram(nd, rt); +} + +static usec_t ndisc_timeout_compute_random(usec_t val) { + /* compute a time that is random within ±10% of the given value */ + return val - val / 10 + + (random_u64() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC; +} + +static int ndisc_timeout(sd_event_source *s, uint64_t usec, void *userdata) { + char time_string[FORMAT_TIMESPAN_MAX]; + sd_ndisc *nd = userdata; + usec_t time_now; + int r; + + assert(s); + assert(nd); + assert(nd->event); + + assert_se(sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now) >= 0); + + if (!nd->retransmit_time) + nd->retransmit_time = ndisc_timeout_compute_random(NDISC_ROUTER_SOLICITATION_INTERVAL); + else { + if (nd->retransmit_time > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL / 2) + nd->retransmit_time = ndisc_timeout_compute_random(NDISC_MAX_ROUTER_SOLICITATION_INTERVAL); + else + nd->retransmit_time += ndisc_timeout_compute_random(nd->retransmit_time); + } + + r = event_reset_time(nd->event, &nd->timeout_event_source, + clock_boottime_or_monotonic(), + time_now + nd->retransmit_time, 10 * USEC_PER_MSEC, + ndisc_timeout, nd, + nd->event_priority, "ndisc-timeout-no-ra", true); + if (r < 0) + goto fail; + + r = icmp6_send_router_solicitation(nd->fd, &nd->mac_addr); + if (r < 0) { + log_ndisc_errno(r, "Error sending Router Solicitation: %m"); + goto fail; + } + + log_ndisc("Sent Router Solicitation, next solicitation in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, + nd->retransmit_time, USEC_PER_SEC)); + + return 0; + +fail: + (void) sd_ndisc_stop(nd); + return 0; +} + +static int ndisc_timeout_no_ra(sd_event_source *s, uint64_t usec, void *userdata) { + sd_ndisc *nd = userdata; + + assert(s); + assert(nd); + + log_ndisc("No RA received before link confirmation timeout"); + + (void) event_source_disable(nd->timeout_no_ra); + ndisc_callback(nd, SD_NDISC_EVENT_TIMEOUT, NULL); + + return 0; +} + +_public_ int sd_ndisc_stop(sd_ndisc *nd) { + assert_return(nd, -EINVAL); + + if (nd->fd < 0) + return 0; + + log_ndisc("Stopping IPv6 Router Solicitation client"); + + ndisc_reset(nd); + return 1; +} + +_public_ int sd_ndisc_start(sd_ndisc *nd) { + int r; + usec_t time_now; + + assert_return(nd, -EINVAL); + assert_return(nd->event, -EINVAL); + assert_return(nd->ifindex > 0, -EINVAL); + + if (nd->fd >= 0) + return 0; + + assert(!nd->recv_event_source); + + r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + goto fail; + + nd->fd = icmp6_bind_router_solicitation(nd->ifindex); + if (nd->fd < 0) + return nd->fd; + + r = sd_event_add_io(nd->event, &nd->recv_event_source, nd->fd, EPOLLIN, ndisc_recv, nd); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(nd->recv_event_source, nd->event_priority); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(nd->recv_event_source, "ndisc-receive-message"); + + r = event_reset_time(nd->event, &nd->timeout_event_source, + clock_boottime_or_monotonic(), + time_now + USEC_PER_SEC / 2, 1 * USEC_PER_SEC, /* See RFC 8415 sec. 18.2.1 */ + ndisc_timeout, nd, + nd->event_priority, "ndisc-timeout", true); + if (r < 0) + goto fail; + + r = event_reset_time(nd->event, &nd->timeout_no_ra, + clock_boottime_or_monotonic(), + time_now + NDISC_TIMEOUT_NO_RA_USEC, 10 * USEC_PER_MSEC, + ndisc_timeout_no_ra, nd, + nd->event_priority, "ndisc-timeout-no-ra", true); + if (r < 0) + goto fail; + + log_ndisc("Started IPv6 Router Solicitation client"); + return 1; + +fail: + ndisc_reset(nd); + return r; +} diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c new file mode 100644 index 00000000..873a2f40 --- /dev/null +++ b/src/libsystemd-network/sd-radv.c @@ -0,0 +1,916 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2017 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include + +#include "sd-radv.h" + +#include "alloc-util.h" +#include "dns-domain.h" +#include "ether-addr-util.h" +#include "event-util.h" +#include "fd-util.h" +#include "icmp6-util.h" +#include "in-addr-util.h" +#include "io-util.h" +#include "macro.h" +#include "memory-util.h" +#include "radv-internal.h" +#include "random-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" + +_public_ int sd_radv_new(sd_radv **ret) { + _cleanup_(sd_radv_unrefp) sd_radv *ra = NULL; + + assert_return(ret, -EINVAL); + + ra = new(sd_radv, 1); + if (!ra) + return -ENOMEM; + + *ra = (sd_radv) { + .n_ref = 1, + .fd = -1, + }; + + *ret = TAKE_PTR(ra); + + return 0; +} + +_public_ int sd_radv_attach_event(sd_radv *ra, sd_event *event, int64_t priority) { + int r; + + assert_return(ra, -EINVAL); + assert_return(!ra->event, -EBUSY); + + if (event) + ra->event = sd_event_ref(event); + else { + r = sd_event_default(&ra->event); + if (r < 0) + return 0; + } + + ra->event_priority = priority; + + return 0; +} + +_public_ int sd_radv_detach_event(sd_radv *ra) { + + assert_return(ra, -EINVAL); + + ra->event = sd_event_unref(ra->event); + return 0; +} + +_public_ sd_event *sd_radv_get_event(sd_radv *ra) { + assert_return(ra, NULL); + + return ra->event; +} + +static void radv_reset(sd_radv *ra) { + assert(ra); + + (void) event_source_disable(ra->timeout_event_source); + + ra->recv_event_source = + sd_event_source_unref(ra->recv_event_source); + + ra->ra_sent = 0; +} + +static sd_radv *radv_free(sd_radv *ra) { + if (!ra) + return NULL; + + while (ra->prefixes) { + sd_radv_prefix *p = ra->prefixes; + + LIST_REMOVE(prefix, ra->prefixes, p); + sd_radv_prefix_unref(p); + } + + while (ra->route_prefixes) { + sd_radv_route_prefix *p = ra->route_prefixes; + + LIST_REMOVE(prefix, ra->route_prefixes, p); + sd_radv_route_prefix_unref(p); + } + + free(ra->rdnss); + free(ra->dnssl); + + ra->timeout_event_source = sd_event_source_unref(ra->timeout_event_source); + + radv_reset(ra); + + sd_radv_detach_event(ra); + + ra->fd = safe_close(ra->fd); + + return mfree(ra); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv, sd_radv, radv_free); + +static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_lifetime) { + sd_radv_route_prefix *rt; + sd_radv_prefix *p; + struct sockaddr_in6 dst_addr = { + .sin6_family = AF_INET6, + .sin6_addr = IN6ADDR_ALL_NODES_MULTICAST_INIT, + }; + struct nd_router_advert adv = {}; + struct { + struct nd_opt_hdr opthdr; + struct ether_addr slladdr; + } _packed_ opt_mac = { + .opthdr = { + .nd_opt_type = ND_OPT_SOURCE_LINKADDR, + .nd_opt_len = (sizeof(struct nd_opt_hdr) + + sizeof(struct ether_addr) - 1) /8 + 1, + }, + }; + struct nd_opt_mtu opt_mtu = { + .nd_opt_mtu_type = ND_OPT_MTU, + .nd_opt_mtu_len = 1, + }; + /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, N routes, RDNSS + and DNSSL */ + struct iovec iov[5 + ra->n_prefixes + ra->n_route_prefixes]; + struct msghdr msg = { + .msg_name = &dst_addr, + .msg_namelen = sizeof(dst_addr), + .msg_iov = iov, + }; + usec_t time_now; + int r; + + assert(ra); + + r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return r; + + if (dst && !IN6_IS_ADDR_UNSPECIFIED(dst)) + dst_addr.sin6_addr = *dst; + + adv.nd_ra_type = ND_ROUTER_ADVERT; + adv.nd_ra_curhoplimit = ra->hop_limit; + adv.nd_ra_flags_reserved = ra->flags; + adv.nd_ra_router_lifetime = htobe16(router_lifetime); + iov[msg.msg_iovlen++] = IOVEC_MAKE(&adv, sizeof(adv)); + + /* MAC address is optional, either because the link does not use L2 + addresses or load sharing is desired. See RFC 4861, Section 4.2 */ + if (!ether_addr_is_null(&ra->mac_addr)) { + opt_mac.slladdr = ra->mac_addr; + iov[msg.msg_iovlen++] = IOVEC_MAKE(&opt_mac, sizeof(opt_mac)); + } + + if (ra->mtu) { + opt_mtu.nd_opt_mtu_mtu = htobe32(ra->mtu); + iov[msg.msg_iovlen++] = IOVEC_MAKE(&opt_mtu, sizeof(opt_mtu)); + } + + LIST_FOREACH(prefix, p, ra->prefixes) { + if (p->valid_until) { + + if (time_now > p->valid_until) + p->opt.valid_lifetime = 0; + else + p->opt.valid_lifetime = htobe32((p->valid_until - time_now) / USEC_PER_SEC); + + if (time_now > p->preferred_until) + p->opt.preferred_lifetime = 0; + else + p->opt.preferred_lifetime = htobe32((p->preferred_until - time_now) / USEC_PER_SEC); + } + iov[msg.msg_iovlen++] = IOVEC_MAKE(&p->opt, sizeof(p->opt)); + } + + LIST_FOREACH(prefix, rt, ra->route_prefixes) + iov[msg.msg_iovlen++] = IOVEC_MAKE(&rt->opt, sizeof(rt->opt)); + + if (ra->rdnss) + iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->rdnss, ra->rdnss->length * 8); + + if (ra->dnssl) + iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->dnssl, ra->dnssl->length * 8); + + if (sendmsg(ra->fd, &msg, 0) < 0) + return -errno; + + return 0; +} + +static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + sd_radv *ra = userdata; + _cleanup_free_ char *addr = NULL; + struct in6_addr src; + triple_timestamp timestamp; + int r; + ssize_t buflen; + _cleanup_free_ char *buf = NULL; + + assert(s); + assert(ra); + assert(ra->event); + + buflen = next_datagram_size_fd(fd); + if (buflen < 0) + return (int) buflen; + + buf = new0(char, buflen); + if (!buf) + return -ENOMEM; + + r = icmp6_receive(fd, buf, buflen, &src, ×tamp); + if (r < 0) { + switch (r) { + case -EADDRNOTAVAIL: + (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &src, &addr); + log_radv("Received RS from non-link-local address %s. Ignoring", addr); + break; + + case -EMULTIHOP: + log_radv("Received RS with invalid hop limit. Ignoring."); + break; + + case -EPFNOSUPPORT: + log_radv("Received invalid source address from ICMPv6 socket. Ignoring."); + break; + + case -EAGAIN: /* ignore spurious wakeups */ + break; + + default: + log_radv_errno(r, "Unexpected error receiving from ICMPv6 socket: %m"); + break; + } + + return 0; + } + + if ((size_t) buflen < sizeof(struct nd_router_solicit)) { + log_radv("Too short packet received"); + return 0; + } + + (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &src, &addr); + + r = radv_send(ra, &src, ra->lifetime); + if (r < 0) + log_radv_errno(r, "Unable to send solicited Router Advertisement to %s: %m", strnull(addr)); + else + log_radv("Sent solicited Router Advertisement to %s", strnull(addr)); + + return 0; +} + +static usec_t radv_compute_timeout(usec_t min, usec_t max) { + assert_return(min <= max, SD_RADV_DEFAULT_MIN_TIMEOUT_USEC); + + /* RFC 4861: min must be no less than 3s, max must be no less than 4s */ + min = MAX(min, 3*USEC_PER_SEC); + max = MAX(max, 4*USEC_PER_SEC); + + return min + (random_u32() % (max - min)); +} + +static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) { + int r; + sd_radv *ra = userdata; + usec_t min_timeout = SD_RADV_DEFAULT_MIN_TIMEOUT_USEC; + usec_t max_timeout = SD_RADV_DEFAULT_MAX_TIMEOUT_USEC; + usec_t time_now, timeout; + char time_string[FORMAT_TIMESPAN_MAX]; + + assert(s); + assert(ra); + assert(ra->event); + + r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + goto fail; + + r = radv_send(ra, NULL, ra->lifetime); + if (r < 0) + log_radv_errno(r, "Unable to send Router Advertisement: %m"); + + /* RFC 4861, Section 6.2.4, sending initial Router Advertisements */ + if (ra->ra_sent < SD_RADV_MAX_INITIAL_RTR_ADVERTISEMENTS) { + max_timeout = SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC; + min_timeout = SD_RADV_MAX_INITIAL_RTR_ADVERT_INTERVAL_USEC / 3; + } + + /* RFC 4861, Section 6.2.1, lifetime must be at least MaxRtrAdvInterval, + so lower the interval here */ + if (ra->lifetime > 0 && (ra->lifetime * USEC_PER_SEC) < max_timeout) { + max_timeout = ra->lifetime * USEC_PER_SEC; + min_timeout = max_timeout / 3; + } + + timeout = radv_compute_timeout(min_timeout, max_timeout); + + log_radv("Next Router Advertisement in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, + timeout, USEC_PER_SEC)); + + r = event_reset_time(ra->event, &ra->timeout_event_source, + clock_boottime_or_monotonic(), + time_now + timeout, MSEC_PER_SEC, + radv_timeout, ra, + ra->event_priority, "radv-timeout", true); + if (r < 0) + goto fail; + + ra->ra_sent++; + + return 0; + +fail: + sd_radv_stop(ra); + + return 0; +} + +_public_ int sd_radv_stop(sd_radv *ra) { + int r; + + assert_return(ra, -EINVAL); + + if (ra->state == SD_RADV_STATE_IDLE) + return 0; + + log_radv("Stopping IPv6 Router Advertisement daemon"); + + /* RFC 4861, Section 6.2.5, send at least one Router Advertisement + with zero lifetime */ + r = radv_send(ra, NULL, 0); + if (r < 0) + log_radv_errno(r, "Unable to send last Router Advertisement with router lifetime set to zero: %m"); + + radv_reset(ra); + ra->fd = safe_close(ra->fd); + ra->state = SD_RADV_STATE_IDLE; + + return 0; +} + +_public_ int sd_radv_start(sd_radv *ra) { + int r; + + assert_return(ra, -EINVAL); + assert_return(ra->event, -EINVAL); + assert_return(ra->ifindex > 0, -EINVAL); + + if (ra->state != SD_RADV_STATE_IDLE) + return 0; + + r = event_reset_time(ra->event, &ra->timeout_event_source, + clock_boottime_or_monotonic(), + 0, 0, + radv_timeout, ra, + ra->event_priority, "radv-timeout", true); + if (r < 0) + goto fail; + + r = icmp6_bind_router_advertisement(ra->ifindex); + if (r < 0) + goto fail; + + ra->fd = r; + + r = sd_event_add_io(ra->event, &ra->recv_event_source, ra->fd, EPOLLIN, radv_recv, ra); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(ra->recv_event_source, ra->event_priority); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(ra->recv_event_source, "radv-receive-message"); + + ra->state = SD_RADV_STATE_ADVERTISING; + + log_radv("Started IPv6 Router Advertisement daemon"); + + return 0; + + fail: + radv_reset(ra); + + return r; +} + +_public_ int sd_radv_set_ifindex(sd_radv *ra, int ifindex) { + assert_return(ra, -EINVAL); + assert_return(ifindex >= -1, -EINVAL); + + if (ra->state != SD_RADV_STATE_IDLE) + return -EBUSY; + + ra->ifindex = ifindex; + + return 0; +} + +_public_ int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr) { + assert_return(ra, -EINVAL); + + if (ra->state != SD_RADV_STATE_IDLE) + return -EBUSY; + + if (mac_addr) + ra->mac_addr = *mac_addr; + else + zero(ra->mac_addr); + + return 0; +} + +_public_ int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu) { + assert_return(ra, -EINVAL); + assert_return(mtu >= 1280, -EINVAL); + + ra->mtu = mtu; + + return 0; +} + +_public_ int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit) { + assert_return(ra, -EINVAL); + + if (ra->state != SD_RADV_STATE_IDLE) + return -EBUSY; + + ra->hop_limit = hop_limit; + + return 0; +} + +_public_ int sd_radv_set_router_lifetime(sd_radv *ra, uint32_t router_lifetime) { + assert_return(ra, -EINVAL); + + if (ra->state != SD_RADV_STATE_IDLE) + return -EBUSY; + + /* RFC 4191, Section 2.2, "...If the Router Lifetime is zero, the + preference value MUST be set to (00) by the sender..." */ + if (router_lifetime == 0 && + (ra->flags & (0x3 << 3)) != (SD_NDISC_PREFERENCE_MEDIUM << 3)) + return -ETIME; + + ra->lifetime = router_lifetime; + + return 0; +} + +_public_ int sd_radv_set_managed_information(sd_radv *ra, int managed) { + assert_return(ra, -EINVAL); + + if (ra->state != SD_RADV_STATE_IDLE) + return -EBUSY; + + SET_FLAG(ra->flags, ND_RA_FLAG_MANAGED, managed); + + return 0; +} + +_public_ int sd_radv_set_other_information(sd_radv *ra, int other) { + assert_return(ra, -EINVAL); + + if (ra->state != SD_RADV_STATE_IDLE) + return -EBUSY; + + SET_FLAG(ra->flags, ND_RA_FLAG_OTHER, other); + + return 0; +} + +_public_ int sd_radv_set_preference(sd_radv *ra, unsigned preference) { + int r = 0; + + assert_return(ra, -EINVAL); + assert_return(IN_SET(preference, + SD_NDISC_PREFERENCE_LOW, + SD_NDISC_PREFERENCE_MEDIUM, + SD_NDISC_PREFERENCE_HIGH), -EINVAL); + + ra->flags = (ra->flags & ~(0x3 << 3)) | (preference << 3); + + return r; +} + +_public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic) { + sd_radv_prefix *cur; + int r; + _cleanup_free_ char *addr_p = NULL; + char time_string_preferred[FORMAT_TIMESPAN_MAX]; + char time_string_valid[FORMAT_TIMESPAN_MAX]; + usec_t time_now, valid, preferred, valid_until, preferred_until; + + assert_return(ra, -EINVAL); + + if (!p) + return -EINVAL; + + /* Refuse prefixes that don't have a prefix set */ + if (IN6_IS_ADDR_UNSPECIFIED(&p->opt.in6_addr)) + return -ENOEXEC; + + LIST_FOREACH(prefix, cur, ra->prefixes) { + + r = in_addr_prefix_intersect(AF_INET6, + (union in_addr_union*) &cur->opt.in6_addr, + cur->opt.prefixlen, + (union in_addr_union*) &p->opt.in6_addr, + p->opt.prefixlen); + if (r > 0) { + _cleanup_free_ char *addr_cur = NULL; + + (void) in_addr_to_string(AF_INET6, + (union in_addr_union*) &p->opt.in6_addr, + &addr_p); + + if (dynamic && cur->opt.prefixlen == p->opt.prefixlen) + goto update; + + (void) in_addr_to_string(AF_INET6, + (union in_addr_union*) &cur->opt.in6_addr, + &addr_cur); + log_radv("IPv6 prefix %s/%u already configured, ignoring %s/%u", + addr_cur, cur->opt.prefixlen, + addr_p, p->opt.prefixlen); + + return -EEXIST; + } + } + + p = sd_radv_prefix_ref(p); + + LIST_APPEND(prefix, ra->prefixes, p); + + ra->n_prefixes++; + + (void) in_addr_to_string(AF_INET6, (union in_addr_union*) &p->opt.in6_addr, &addr_p); + + if (!dynamic) { + log_radv("Added prefix %s/%d", addr_p, p->opt.prefixlen); + return 0; + } + + cur = p; + + update: + r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return r; + + valid = be32toh(p->opt.valid_lifetime) * USEC_PER_SEC; + valid_until = usec_add(valid, time_now); + if (valid_until == USEC_INFINITY) + return -EOVERFLOW; + + preferred = be32toh(p->opt.preferred_lifetime) * USEC_PER_SEC; + preferred_until = usec_add(preferred, time_now); + if (preferred_until == USEC_INFINITY) + return -EOVERFLOW; + + cur->valid_until = valid_until; + cur->preferred_until = preferred_until; + + log_radv("%s prefix %s/%u preferred %s valid %s", + cur? "Updated": "Added", + addr_p, p->opt.prefixlen, + format_timespan(time_string_preferred, FORMAT_TIMESPAN_MAX, + preferred, USEC_PER_SEC), + format_timespan(time_string_valid, FORMAT_TIMESPAN_MAX, + valid, USEC_PER_SEC)); + + return 0; +} + +_public_ sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra, + const struct in6_addr *prefix, + unsigned char prefixlen) { + sd_radv_prefix *cur, *next; + + assert_return(ra, NULL); + assert_return(prefix, NULL); + + LIST_FOREACH_SAFE(prefix, cur, next, ra->prefixes) { + if (prefixlen != cur->opt.prefixlen) + continue; + + if (!in_addr_equal(AF_INET6, + (union in_addr_union *)prefix, + (union in_addr_union *)&cur->opt.in6_addr)) + continue; + + LIST_REMOVE(prefix, ra->prefixes, cur); + ra->n_prefixes--; + sd_radv_prefix_unref(cur); + + break; + } + + return cur; +} + +_public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int dynamic) { + char time_string_valid[FORMAT_TIMESPAN_MAX]; + usec_t time_now, valid, valid_until; + _cleanup_free_ char *pretty = NULL; + sd_radv_route_prefix *cur; + int r; + + assert_return(ra, -EINVAL); + + if (!p) + return -EINVAL; + + (void) in_addr_to_string(AF_INET6, + (union in_addr_union*) &p->opt.in6_addr, + &pretty); + + LIST_FOREACH(prefix, cur, ra->route_prefixes) { + _cleanup_free_ char *addr = NULL; + + r = in_addr_prefix_intersect(AF_INET6, + (union in_addr_union*) &cur->opt.in6_addr, + cur->opt.prefixlen, + (union in_addr_union*) &p->opt.in6_addr, + p->opt.prefixlen); + if (r < 0) + return r; + if (r == 0) + continue; + + if (dynamic && cur->opt.prefixlen == p->opt.prefixlen) + goto update; + + (void) in_addr_to_string(AF_INET6, + (union in_addr_union*) &cur->opt.in6_addr, + &addr); + log_radv("IPv6 route prefix %s/%u already configured, ignoring %s/%u", + strempty(addr), cur->opt.prefixlen, + strempty(pretty), p->opt.prefixlen); + + return -EEXIST; + } + + p = sd_radv_route_prefix_ref(p); + + LIST_APPEND(prefix, ra->route_prefixes, p); + ra->n_route_prefixes++; + + cur = p; + if (!dynamic) { + log_radv("Added prefix %s/%u", strempty(pretty), p->opt.prefixlen); + return 0; + } + + update: + r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return r; + + valid = be32toh(p->opt.lifetime) * USEC_PER_SEC; + valid_until = usec_add(valid, time_now); + if (valid_until == USEC_INFINITY) + return -EOVERFLOW; + + log_radv("%s route prefix %s/%u valid %s", + cur? "Updated": "Added", + strempty(pretty), p->opt.prefixlen, + format_timespan(time_string_valid, FORMAT_TIMESPAN_MAX, valid, USEC_PER_SEC)); + + return 0; +} + +_public_ int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime, + const struct in6_addr *dns, size_t n_dns) { + _cleanup_free_ struct sd_radv_opt_dns *opt_rdnss = NULL; + size_t len; + + assert_return(ra, -EINVAL); + assert_return(n_dns < 128, -EINVAL); + + if (!dns || n_dns == 0) { + ra->rdnss = mfree(ra->rdnss); + ra->n_rdnss = 0; + + return 0; + } + + len = sizeof(struct sd_radv_opt_dns) + sizeof(struct in6_addr) * n_dns; + + opt_rdnss = malloc0(len); + if (!opt_rdnss) + return -ENOMEM; + + opt_rdnss->type = SD_RADV_OPT_RDNSS; + opt_rdnss->length = len / 8; + opt_rdnss->lifetime = htobe32(lifetime); + + memcpy(opt_rdnss + 1, dns, n_dns * sizeof(struct in6_addr)); + + free_and_replace(ra->rdnss, opt_rdnss); + + ra->n_rdnss = n_dns; + + return 0; +} + +_public_ int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime, + char **search_list) { + _cleanup_free_ struct sd_radv_opt_dns *opt_dnssl = NULL; + size_t len = 0; + char **s; + uint8_t *p; + + assert_return(ra, -EINVAL); + + if (strv_isempty(search_list)) { + ra->dnssl = mfree(ra->dnssl); + return 0; + } + + STRV_FOREACH(s, search_list) + len += strlen(*s) + 2; + + len = (sizeof(struct sd_radv_opt_dns) + len + 7) & ~0x7; + + opt_dnssl = malloc0(len); + if (!opt_dnssl) + return -ENOMEM; + + opt_dnssl->type = SD_RADV_OPT_DNSSL; + opt_dnssl->length = len / 8; + opt_dnssl->lifetime = htobe32(lifetime); + + p = (uint8_t *)(opt_dnssl + 1); + len -= sizeof(struct sd_radv_opt_dns); + + STRV_FOREACH(s, search_list) { + int r; + + r = dns_name_to_wire_format(*s, p, len, false); + if (r < 0) + return r; + + if (len < (size_t)r) + return -ENOBUFS; + + p += r; + len -= r; + } + + free_and_replace(ra->dnssl, opt_dnssl); + + return 0; +} + +_public_ int sd_radv_prefix_new(sd_radv_prefix **ret) { + sd_radv_prefix *p; + + assert_return(ret, -EINVAL); + + p = new(sd_radv_prefix, 1); + if (!p) + return -ENOMEM; + + *p = (sd_radv_prefix) { + .n_ref = 1, + + .opt.type = ND_OPT_PREFIX_INFORMATION, + .opt.length = (sizeof(p->opt) - 1)/8 + 1, + .opt.prefixlen = 64, + + /* RFC 4861, Section 6.2.1 */ + .opt.flags = ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO, + + .opt.preferred_lifetime = htobe32(604800), + .opt.valid_lifetime = htobe32(2592000), + }; + + *ret = p; + return 0; +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_prefix, sd_radv_prefix, mfree); + +_public_ int sd_radv_prefix_set_prefix(sd_radv_prefix *p, const struct in6_addr *in6_addr, + unsigned char prefixlen) { + assert_return(p, -EINVAL); + assert_return(in6_addr, -EINVAL); + + if (prefixlen < 3 || prefixlen > 128) + return -EINVAL; + + if (prefixlen > 64) + /* unusual but allowed, log it */ + log_radv("Unusual prefix length %d greater than 64", prefixlen); + + p->opt.in6_addr = *in6_addr; + p->opt.prefixlen = prefixlen; + + return 0; +} + +_public_ int sd_radv_prefix_set_onlink(sd_radv_prefix *p, int onlink) { + assert_return(p, -EINVAL); + + SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_ONLINK, onlink); + + return 0; +} + +_public_ int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix *p, + int address_autoconfiguration) { + assert_return(p, -EINVAL); + + SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_AUTO, address_autoconfiguration); + + return 0; +} + +_public_ int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix *p, + uint32_t valid_lifetime) { + assert_return(p, -EINVAL); + + p->opt.valid_lifetime = htobe32(valid_lifetime); + + return 0; +} + +_public_ int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p, + uint32_t preferred_lifetime) { + assert_return(p, -EINVAL); + + p->opt.preferred_lifetime = htobe32(preferred_lifetime); + + return 0; +} + +_public_ int sd_radv_route_prefix_new(sd_radv_route_prefix **ret) { + sd_radv_route_prefix *p; + + assert_return(ret, -EINVAL); + + p = new(sd_radv_route_prefix, 1); + if (!p) + return -ENOMEM; + + *p = (sd_radv_route_prefix) { + .n_ref = 1, + + .opt.type = SD_RADV_OPT_ROUTE_INFORMATION, + .opt.length = DIV_ROUND_UP(sizeof(p->opt), 8), + .opt.prefixlen = 64, + + .opt.lifetime = htobe32(604800), + }; + + *ret = p; + return 0; +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_route_prefix, sd_radv_route_prefix, mfree); + +_public_ int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, + unsigned char prefixlen) { + assert_return(p, -EINVAL); + assert_return(in6_addr, -EINVAL); + + if (prefixlen > 128) + return -EINVAL; + + if (prefixlen > 64) + /* unusual but allowed, log it */ + log_radv("Unusual prefix length %u greater than 64", prefixlen); + + p->opt.in6_addr = *in6_addr; + p->opt.prefixlen = prefixlen; + + return 0; +} + +_public_ int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint32_t valid_lifetime) { + assert_return(p, -EINVAL); + + p->opt.lifetime = htobe32(valid_lifetime); + + return 0; +} diff --git a/src/libsystemd-network/test-acd.c b/src/libsystemd-network/test-acd.c new file mode 100644 index 00000000..27a1a214 --- /dev/null +++ b/src/libsystemd-network/test-acd.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include +#include + +#include "sd-event.h" +#include "sd-ipv4acd.h" +#include "sd-netlink.h" + +#include "in-addr-util.h" +#include "netlink-util.h" +#include "tests.h" +#include "util.h" + +static void acd_handler(sd_ipv4acd *acd, int event, void *userdata) { + assert_se(acd); + + switch (event) { + case SD_IPV4ACD_EVENT_BIND: + log_info("bound"); + break; + case SD_IPV4ACD_EVENT_CONFLICT: + log_info("conflict"); + break; + case SD_IPV4ACD_EVENT_STOP: + log_error("the client was stopped"); + break; + default: + assert_not_reached("invalid ACD event"); + } +} + +static int client_run(int ifindex, const struct in_addr *pa, const struct ether_addr *ha, sd_event *e) { + sd_ipv4acd *acd; + + assert_se(sd_ipv4acd_new(&acd) >= 0); + assert_se(sd_ipv4acd_attach_event(acd, e, 0) >= 0); + + assert_se(sd_ipv4acd_set_ifindex(acd, ifindex) >= 0); + assert_se(sd_ipv4acd_set_mac(acd, ha) >= 0); + assert_se(sd_ipv4acd_set_address(acd, pa) >= 0); + assert_se(sd_ipv4acd_set_callback(acd, acd_handler, NULL) >= 0); + + log_info("starting IPv4ACD client"); + + assert_se(sd_ipv4acd_start(acd, true) >= 0); + + assert_se(sd_event_loop(e) >= 0); + + assert_se(!sd_ipv4acd_unref(acd)); + + return EXIT_SUCCESS; +} + +static int test_acd(const char *ifname, const char *address) { + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL; + union in_addr_union pa; + struct ether_addr ha; + int ifindex; + + assert_se(in_addr_from_string(AF_INET, address, &pa) >= 0); + + assert_se(sd_event_new(&e) >= 0); + + assert_se(sd_netlink_open(&rtnl) >= 0); + assert_se(sd_netlink_attach_event(rtnl, e, 0) >= 0); + + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, 0) >= 0); + assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, ifname) >= 0); + assert_se(sd_netlink_call(rtnl, m, 0, &reply) >= 0); + + assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0); + assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0); + + client_run(ifindex, &pa.in, &ha, e); + + return EXIT_SUCCESS; +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + if (argc == 3) + return test_acd(argv[1], argv[2]); + else { + log_error("This program takes two arguments.\n" + "\t %s ", program_invocation_short_name); + return EXIT_FAILURE; + } +} diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c new file mode 100644 index 00000000..4e9b388a --- /dev/null +++ b/src/libsystemd-network/test-dhcp-client.c @@ -0,0 +1,582 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include +#include + +#include "sd-dhcp-client.h" +#include "sd-event.h" + +#include "alloc-util.h" +#include "dhcp-identifier.h" +#include "dhcp-internal.h" +#include "dhcp-protocol.h" +#include "fd-util.h" +#include "random-util.h" +#include "tests.h" +#include "util.h" + +static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'}; + +typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp); + +static bool verbose = true; +static int test_fd[2]; +static test_callback_recv_t callback_recv; +static be32_t xid; +static sd_event_source *test_hangcheck; + +static int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) { + assert_not_reached("Test case should have completed in 2 seconds"); + + return 0; +} + +static void test_request_basic(sd_event *e) { + int r; + + sd_dhcp_client *client; + + if (verbose) + printf("* %s\n", __FUNCTION__); + + /* Initialize client without Anonymize settings. */ + r = sd_dhcp_client_new(&client, false); + + assert_se(r >= 0); + assert_se(client); + + r = sd_dhcp_client_attach_event(client, e, 0); + assert_se(r >= 0); + + assert_se(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL); + assert_se(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL); + assert_se(sd_dhcp_client_set_ifindex(NULL, 0) == -EINVAL); + + assert_se(sd_dhcp_client_set_ifindex(client, 15) == 0); + assert_se(sd_dhcp_client_set_ifindex(client, -42) == -EINVAL); + assert_se(sd_dhcp_client_set_ifindex(client, -1) == -EINVAL); + assert_se(sd_dhcp_client_set_ifindex(client, 0) == -EINVAL); + assert_se(sd_dhcp_client_set_ifindex(client, 1) == 0); + + assert_se(sd_dhcp_client_set_hostname(client, "host") == 1); + assert_se(sd_dhcp_client_set_hostname(client, "host.domain") == 1); + assert_se(sd_dhcp_client_set_hostname(client, NULL) == 1); + assert_se(sd_dhcp_client_set_hostname(client, "~host") == -EINVAL); + assert_se(sd_dhcp_client_set_hostname(client, "~host.domain") == -EINVAL); + + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_SUBNET_MASK) == -EEXIST); + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_ROUTER) == -EEXIST); + /* This PRL option is not set when using Anonymize, but in this test + * Anonymize settings are not being used. */ + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_HOST_NAME) == -EEXIST); + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_DOMAIN_NAME) == -EEXIST); + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST); + + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_PAD) == -EINVAL); + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_END) == -EINVAL); + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL); + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_OVERLOAD) == -EINVAL); + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) + == -EINVAL); + + /* RFC7844: option 33 (SD_DHCP_OPTION_STATIC_ROUTE) is set in the + * default PRL when using Anonymize, so it is changed to other option + * that is not set by default, to check that it was set successfully. + * Options not set by default (using or not anonymize) are option 17 + * (SD_DHCP_OPTION_ROOT_PATH) and 42 (SD_DHCP_OPTION_NTP_SERVER) */ + assert_se(sd_dhcp_client_set_request_option(client, 17) == 0); + assert_se(sd_dhcp_client_set_request_option(client, 17) == -EEXIST); + assert_se(sd_dhcp_client_set_request_option(client, 42) == 0); + assert_se(sd_dhcp_client_set_request_option(client, 17) == -EEXIST); + + sd_dhcp_client_unref(client); +} + +static void test_request_anonymize(sd_event *e) { + int r; + + sd_dhcp_client *client; + + if (verbose) + printf("* %s\n", __FUNCTION__); + + /* Initialize client with Anonymize settings. */ + r = sd_dhcp_client_new(&client, true); + + assert_se(r >= 0); + assert_se(client); + + r = sd_dhcp_client_attach_event(client, e, 0); + assert_se(r >= 0); + + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_NETBIOS_NAMESERVER) == -EEXIST); + /* This PRL option is not set when using Anonymize */ + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_HOST_NAME) == 0); + assert_se(sd_dhcp_client_set_request_option(client, + SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) + == -EINVAL); + + /* RFC7844: option 101 (SD_DHCP_OPTION_NEW_TZDB_TIMEZONE) is not set in the + * default PRL when using Anonymize, */ + assert_se(sd_dhcp_client_set_request_option(client, 101) == 0); + assert_se(sd_dhcp_client_set_request_option(client, 101) == -EEXIST); + + sd_dhcp_client_unref(client); +} + +static void test_checksum(void) { + uint8_t buf[20] = { + 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff + }; + + if (verbose) + printf("* %s\n", __FUNCTION__); + + assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae)); +} + +static void test_dhcp_identifier_set_iaid(void) { + uint32_t iaid_legacy; + be32_t iaid; + int ifindex; + + for (;;) { + char ifname[IFNAMSIZ]; + + /* try to find an ifindex which does not exist. I causes dhcp_identifier_set_iaid() + * to hash the MAC address. */ + pseudo_random_bytes(&ifindex, sizeof(ifindex)); + if (ifindex > 0 && !if_indextoname(ifindex, ifname)) + break; + } + + assert_se(dhcp_identifier_set_iaid(ifindex, mac_addr, sizeof(mac_addr), true, &iaid_legacy) >= 0); + assert_se(dhcp_identifier_set_iaid(ifindex, mac_addr, sizeof(mac_addr), false, &iaid) >= 0); + + /* we expect, that the MAC address was hashed. The legacy value is in native + * endianness. */ + assert_se(iaid_legacy == 0x8dde4ba8u); + assert_se(iaid == htole32(0x8dde4ba8u)); +#if __BYTE_ORDER == __LITTLE_ENDIAN + assert_se(iaid == iaid_legacy); +#else + assert_se(iaid == __bswap_32(iaid_legacy)); +#endif +} + +static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) { + switch(code) { + case SD_DHCP_OPTION_CLIENT_IDENTIFIER: + { + uint32_t iaid; + struct duid duid; + size_t duid_len; + + assert_se(dhcp_identifier_set_duid_en(&duid, &duid_len) >= 0); + assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, true, &iaid) >= 0); + + assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len); + assert_se(len == 19); + assert_se(((uint8_t*) option)[0] == 0xff); + + assert_se(memcmp((uint8_t*) option + 1, &iaid, sizeof(iaid)) == 0); + assert_se(memcmp((uint8_t*) option + 5, &duid, duid_len) == 0); + break; + } + + default: + break; + } + + return 0; +} + +int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len) { + size_t size; + _cleanup_free_ DHCPPacket *discover; + uint16_t ip_check, udp_check; + + assert_se(s >= 0); + assert_se(packet); + + size = sizeof(DHCPPacket); + assert_se(len > size); + + discover = memdup(packet, len); + + assert_se(discover->ip.ttl == IPDEFTTL); + assert_se(discover->ip.protocol == IPPROTO_UDP); + assert_se(discover->ip.saddr == INADDR_ANY); + assert_se(discover->ip.daddr == INADDR_BROADCAST); + assert_se(discover->udp.source == be16toh(DHCP_PORT_CLIENT)); + assert_se(discover->udp.dest == be16toh(DHCP_PORT_SERVER)); + + ip_check = discover->ip.check; + + discover->ip.ttl = 0; + discover->ip.check = discover->udp.len; + + udp_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip.ttl, len - 8); + assert_se(udp_check == 0xffff); + + discover->ip.ttl = IPDEFTTL; + discover->ip.check = ip_check; + + ip_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip, sizeof(discover->ip)); + assert_se(ip_check == 0xffff); + + assert_se(discover->dhcp.xid); + assert_se(memcmp(discover->dhcp.chaddr, &mac_addr, ETH_ALEN) == 0); + + size = len - sizeof(struct iphdr) - sizeof(struct udphdr); + + assert_se(callback_recv); + callback_recv(size, &discover->dhcp); + + return 575; +} + +int dhcp_network_bind_raw_socket( + int index, + union sockaddr_union *link, + uint32_t id, + const uint8_t *addr, size_t addr_len, + uint16_t arp_type, uint16_t port) { + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0) + return -errno; + + return test_fd[0]; +} + +int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) { + int fd; + + fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (fd < 0) + return -errno; + + return fd; +} + +int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len) { + return 0; +} + +static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) { + int res; + + res = dhcp_option_parse(dhcp, size, check_options, NULL, NULL); + assert_se(res == DHCP_DISCOVER); + + if (verbose) + printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp->xid)); + + return 0; +} + +static void test_discover_message(sd_event *e) { + sd_dhcp_client *client; + int res, r; + + if (verbose) + printf("* %s\n", __FUNCTION__); + + r = sd_dhcp_client_new(&client, false); + assert_se(r >= 0); + assert_se(client); + + r = sd_dhcp_client_attach_event(client, e, 0); + assert_se(r >= 0); + + assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0); + assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0); + + assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0); + + callback_recv = test_discover_message_verify; + + res = sd_dhcp_client_start(client); + + assert_se(IN_SET(res, 0, -EINPROGRESS)); + + sd_event_run(e, (uint64_t) -1); + + sd_dhcp_client_stop(client); + sd_dhcp_client_unref(client); + + test_fd[1] = safe_close(test_fd[1]); + + callback_recv = NULL; +} + +static uint8_t test_addr_acq_offer[] = { + 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01, + 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44, + 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, + 0x6f, 0x95, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf, + 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x36, + 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00, + 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff, + 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f, + 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74, + 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static uint8_t test_addr_acq_ack[] = { + 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01, + 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44, + 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf, + 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36, + 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00, + 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff, + 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f, + 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74, + 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static int test_addr_acq_acquired(sd_dhcp_client *client, int event, + void *userdata) { + sd_event *e = userdata; + sd_dhcp_lease *lease; + struct in_addr addr; + const struct in_addr *addrs; + + assert_se(client); + assert_se(IN_SET(event, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE, SD_DHCP_CLIENT_EVENT_SELECTING)); + + assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0); + assert_se(lease); + + assert_se(sd_dhcp_lease_get_address(lease, &addr) >= 0); + assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[44], + sizeof(addr.s_addr)) == 0); + + assert_se(sd_dhcp_lease_get_netmask(lease, &addr) >= 0); + assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[285], + sizeof(addr.s_addr)) == 0); + + assert_se(sd_dhcp_lease_get_router(lease, &addrs) == 1); + assert_se(memcmp(&addrs[0].s_addr, &test_addr_acq_ack[308], + sizeof(addrs[0].s_addr)) == 0); + + if (verbose) + printf(" DHCP address acquired\n"); + + sd_event_exit(e, 0); + + return 0; +} + +static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) { + uint16_t udp_check = 0; + uint8_t *msg_bytes = (uint8_t *)request; + int res; + + res = dhcp_option_parse(request, size, check_options, NULL, NULL); + assert_se(res == DHCP_REQUEST); + assert_se(xid == request->xid); + + assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END); + + if (verbose) + printf(" recv DHCP Request 0x%08x\n", be32toh(xid)); + + memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check)); + memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid)); + memcpy(&test_addr_acq_ack[56], &mac_addr, ETHER_ADDR_LEN); + + callback_recv = NULL; + + res = write(test_fd[1], test_addr_acq_ack, + sizeof(test_addr_acq_ack)); + assert_se(res == sizeof(test_addr_acq_ack)); + + if (verbose) + printf(" send DHCP Ack\n"); + + return 0; +}; + +static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) { + uint16_t udp_check = 0; + uint8_t *msg_bytes = (uint8_t *)discover; + int res; + + res = dhcp_option_parse(discover, size, check_options, NULL, NULL); + assert_se(res == DHCP_DISCOVER); + + assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END); + + xid = discover->xid; + + if (verbose) + printf(" recv DHCP Discover 0x%08x\n", be32toh(xid)); + + memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check)); + memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid)); + memcpy(&test_addr_acq_offer[56], &mac_addr, ETHER_ADDR_LEN); + + callback_recv = test_addr_acq_recv_request; + + res = write(test_fd[1], test_addr_acq_offer, + sizeof(test_addr_acq_offer)); + assert_se(res == sizeof(test_addr_acq_offer)); + + if (verbose) + printf(" sent DHCP Offer\n"); + + return 0; +} + +static void test_addr_acq(sd_event *e) { + usec_t time_now = now(clock_boottime_or_monotonic()); + sd_dhcp_client *client; + int res, r; + + if (verbose) + printf("* %s\n", __FUNCTION__); + + r = sd_dhcp_client_new(&client, false); + assert_se(r >= 0); + assert_se(client); + + r = sd_dhcp_client_attach_event(client, e, 0); + assert_se(r >= 0); + + assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0); + assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0); + + assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e) >= 0); + + callback_recv = test_addr_acq_recv_discover; + + assert_se(sd_event_add_time(e, &test_hangcheck, + clock_boottime_or_monotonic(), + time_now + 2 * USEC_PER_SEC, 0, + test_dhcp_hangcheck, NULL) >= 0); + + res = sd_dhcp_client_start(client); + assert_se(IN_SET(res, 0, -EINPROGRESS)); + + assert_se(sd_event_loop(e) >= 0); + + test_hangcheck = sd_event_source_unref(test_hangcheck); + + assert_se(sd_dhcp_client_set_callback(client, NULL, NULL) >= 0); + assert_se(sd_dhcp_client_stop(client) >= 0); + sd_dhcp_client_unref(client); + + test_fd[1] = safe_close(test_fd[1]); + + callback_recv = NULL; + xid = 0; +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_event_unrefp) sd_event *e; + + test_setup_logging(LOG_DEBUG); + + assert_se(sd_event_new(&e) >= 0); + + test_request_basic(e); + test_request_anonymize(e); + test_checksum(); + test_dhcp_identifier_set_iaid(); + + test_discover_message(e); + test_addr_acq(e); + +#if VALGRIND + /* Make sure the async_close thread has finished. + * valgrind would report some of the phread_* structures + * as not cleaned up properly. */ + sleep(1); +#endif + + return 0; +} diff --git a/src/libsystemd-network/test-dhcp-option.c b/src/libsystemd-network/test-dhcp-option.c new file mode 100644 index 00000000..56bd690c --- /dev/null +++ b/src/libsystemd-network/test-dhcp-option.c @@ -0,0 +1,367 @@ +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dhcp-internal.h" +#include "dhcp-protocol.h" +#include "macro.h" +#include "memory-util.h" + +struct option_desc { + uint8_t sname[64]; + int snamelen; + uint8_t file[128]; + int filelen; + uint8_t options[128]; + int len; + bool success; + int filepos; + int snamepos; + int pos; +}; + +static bool verbose = false; + +static struct option_desc option_tests[] = { + { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69 }, 7, false, }, + { {}, 0, {}, 0, { 42, 5, 65, 66, 67, 68, 69, 0, 0, + SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 12, true, }, + { {}, 0, {}, 0, { 8, 255, 70, 71, 72 }, 5, false, }, + { {}, 0, {}, 0, { 0x35, 0x01, 0x05, 0x36, 0x04, 0x01, 0x00, 0xa8, + 0xc0, 0x33, 0x04, 0x00, 0x01, 0x51, 0x80, 0x01, + 0x04, 0xff, 0xff, 0xff, 0x00, 0x03, 0x04, 0xc0, + 0xa8, 0x00, 0x01, 0x06, 0x04, 0xc0, 0xa8, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, + 40, true, }, + { {}, 0, {}, 0, { SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_OFFER, + 42, 3, 0, 0, 0 }, 8, true, }, + { {}, 0, {}, 0, { 42, 2, 1, 2, 44 }, 5, false, }, + + { {}, 0, + { 222, 3, 1, 2, 3, SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_NAK }, 8, + { SD_DHCP_OPTION_OVERLOAD, 1, DHCP_OVERLOAD_FILE }, 3, true, }, + + { { 1, 4, 1, 2, 3, 4, SD_DHCP_OPTION_MESSAGE_TYPE, 1, DHCP_ACK }, 9, + { 222, 3, 1, 2, 3 }, 5, + { SD_DHCP_OPTION_OVERLOAD, 1, + DHCP_OVERLOAD_FILE|DHCP_OVERLOAD_SNAME }, 3, true, }, +}; + +static const char *dhcp_type(int type) { + switch(type) { + case DHCP_DISCOVER: + return "DHCPDISCOVER"; + case DHCP_OFFER: + return "DHCPOFFER"; + case DHCP_REQUEST: + return "DHCPREQUEST"; + case DHCP_DECLINE: + return "DHCPDECLINE"; + case DHCP_ACK: + return "DHCPACK"; + case DHCP_NAK: + return "DHCPNAK"; + case DHCP_RELEASE: + return "DHCPRELEASE"; + default: + return "unknown"; + } +} + +static void test_invalid_buffer_length(void) { + DHCPMessage message; + + assert_se(dhcp_option_parse(&message, 0, NULL, NULL, NULL) == -EINVAL); + assert_se(dhcp_option_parse(&message, sizeof(DHCPMessage) - 1, NULL, NULL, NULL) == -EINVAL); +} + +static void test_message_init(void) { + _cleanup_free_ DHCPMessage *message = NULL; + size_t optlen = 4, optoffset; + size_t len = sizeof(DHCPMessage) + optlen; + uint8_t *magic; + + message = malloc0(len); + + assert_se(dhcp_message_init(message, BOOTREQUEST, 0x12345678, + DHCP_DISCOVER, ARPHRD_ETHER, optlen, &optoffset) >= 0); + + assert_se(message->xid == htobe32(0x12345678)); + assert_se(message->op == BOOTREQUEST); + + magic = (uint8_t*)&message->magic; + + assert_se(magic[0] == 99); + assert_se(magic[1] == 130); + assert_se(magic[2] == 83); + assert_se(magic[3] == 99); + + assert_se(dhcp_option_parse(message, len, NULL, NULL, NULL) >= 0); +} + +static DHCPMessage *create_message(uint8_t *options, uint16_t optlen, + uint8_t *file, uint8_t filelen, + uint8_t *sname, uint8_t snamelen) { + DHCPMessage *message; + size_t len = sizeof(DHCPMessage) + optlen; + + message = malloc0(len); + assert_se(message); + + memcpy_safe(&message->options, options, optlen); + memcpy_safe(&message->file, file, filelen); + memcpy_safe(&message->sname, sname, snamelen); + + return message; +} + +static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen) { + assert(*descpos >= 0); + + while (*descpos < *desclen) { + switch(descoption[*descpos]) { + case SD_DHCP_OPTION_PAD: + *descpos += 1; + break; + + case SD_DHCP_OPTION_MESSAGE_TYPE: + case SD_DHCP_OPTION_OVERLOAD: + *descpos += 3; + break; + + default: + return; + } + } +} + +static int test_options_cb(uint8_t code, uint8_t len, const void *option, void *userdata) { + struct option_desc *desc = userdata; + uint8_t *descoption = NULL; + int *desclen = NULL, *descpos = NULL; + uint8_t optcode = 0; + uint8_t optlen = 0; + uint8_t i; + + assert_se((!desc && !code && !len) || desc); + + if (!desc) + return -EINVAL; + + assert_se(code != SD_DHCP_OPTION_PAD); + assert_se(code != SD_DHCP_OPTION_END); + assert_se(code != SD_DHCP_OPTION_MESSAGE_TYPE); + assert_se(code != SD_DHCP_OPTION_OVERLOAD); + + while (desc->pos >= 0 || desc->filepos >= 0 || desc->snamepos >= 0) { + + if (desc->pos >= 0) { + descoption = &desc->options[0]; + desclen = &desc->len; + descpos = &desc->pos; + } else if (desc->filepos >= 0) { + descoption = &desc->file[0]; + desclen = &desc->filelen; + descpos = &desc->filepos; + } else if (desc->snamepos >= 0) { + descoption = &desc->sname[0]; + desclen = &desc->snamelen; + descpos = &desc->snamepos; + } + + assert_se(descoption && desclen && descpos); + + if (*desclen) + test_ignore_opts(descoption, descpos, desclen); + + if (*descpos < *desclen) + break; + + if (*descpos == *desclen) + *descpos = -1; + } + + assert_se(descpos); + assert_se(*descpos != -1); + + optcode = descoption[*descpos]; + optlen = descoption[*descpos + 1]; + + if (verbose) + printf("DHCP code %2d(%2d) len %2d(%2d) ", code, optcode, + len, optlen); + + assert_se(code == optcode); + assert_se(len == optlen); + + for (i = 0; i < len; i++) { + + if (verbose) + printf("0x%02x(0x%02x) ", ((uint8_t*) option)[i], + descoption[*descpos + 2 + i]); + + assert_se(((uint8_t*) option)[i] == descoption[*descpos + 2 + i]); + } + + if (verbose) + printf("\n"); + + *descpos += optlen + 2; + + test_ignore_opts(descoption, descpos, desclen); + + if (desc->pos != -1 && desc->pos == desc->len) + desc->pos = -1; + + if (desc->filepos != -1 && desc->filepos == desc->filelen) + desc->filepos = -1; + + if (desc->snamepos != -1 && desc->snamepos == desc->snamelen) + desc->snamepos = -1; + + return 0; +} + +static void test_options(struct option_desc *desc) { + uint8_t *options = NULL; + uint8_t *file = NULL; + uint8_t *sname = NULL; + int optlen = 0; + int filelen = 0; + int snamelen = 0; + int buflen = 0; + _cleanup_free_ DHCPMessage *message = NULL; + int res; + + if (desc) { + file = &desc->file[0]; + filelen = desc->filelen; + if (!filelen) + desc->filepos = -1; + + sname = &desc->sname[0]; + snamelen = desc->snamelen; + if (!snamelen) + desc->snamepos = -1; + + options = &desc->options[0]; + optlen = desc->len; + desc->pos = 0; + } + message = create_message(options, optlen, file, filelen, + sname, snamelen); + + buflen = sizeof(DHCPMessage) + optlen; + + if (!desc) { + assert_se((res = dhcp_option_parse(message, buflen, test_options_cb, NULL, NULL)) == -ENOMSG); + } else if (desc->success) { + assert_se((res = dhcp_option_parse(message, buflen, test_options_cb, desc, NULL)) >= 0); + assert_se(desc->pos == -1 && desc->filepos == -1 && desc->snamepos == -1); + } else + assert_se((res = dhcp_option_parse(message, buflen, test_options_cb, desc, NULL)) < 0); + + if (verbose) + printf("DHCP type %s\n", dhcp_type(res)); +} + +static uint8_t options[64] = { + 'A', 'B', 'C', 'D', + 160, 2, 0x11, 0x12, + 0, + 31, 8, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0, + 55, 3, 0x51, 0x52, 0x53, + 17, 7, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 255 +}; + +static void test_option_set(void) { + _cleanup_free_ DHCPMessage *result = NULL; + size_t offset = 0, len, pos; + unsigned i; + + result = malloc0(sizeof(DHCPMessage) + 11); + assert_se(result); + + result->options[0] = 'A'; + result->options[1] = 'B'; + result->options[2] = 'C'; + result->options[3] = 'D'; + + assert_se(dhcp_option_append(result, 0, &offset, 0, SD_DHCP_OPTION_PAD, + 0, NULL) == -ENOBUFS); + assert_se(offset == 0); + + offset = 4; + assert_se(dhcp_option_append(result, 5, &offset, 0, SD_DHCP_OPTION_PAD, + 0, NULL) == -ENOBUFS); + assert_se(offset == 4); + assert_se(dhcp_option_append(result, 6, &offset, 0, SD_DHCP_OPTION_PAD, + 0, NULL) >= 0); + assert_se(offset == 5); + + offset = pos = 4; + len = 11; + while (pos < len && options[pos] != SD_DHCP_OPTION_END) { + assert_se(dhcp_option_append(result, len, &offset, DHCP_OVERLOAD_SNAME, + options[pos], + options[pos + 1], + &options[pos + 2]) >= 0); + + if (options[pos] == SD_DHCP_OPTION_PAD) + pos++; + else + pos += 2 + options[pos + 1]; + + if (pos < len) + assert_se(offset == pos); + } + + for (i = 0; i < 9; i++) { + if (verbose) + printf("%2u: 0x%02x(0x%02x) (options)\n", i, result->options[i], + options[i]); + assert_se(result->options[i] == options[i]); + } + + if (verbose) + printf("%2d: 0x%02x(0x%02x) (options)\n", 9, result->options[9], + SD_DHCP_OPTION_END); + + assert_se(result->options[9] == SD_DHCP_OPTION_END); + + if (verbose) + printf("%2d: 0x%02x(0x%02x) (options)\n", 10, result->options[10], + SD_DHCP_OPTION_PAD); + + assert_se(result->options[10] == SD_DHCP_OPTION_PAD); + + for (i = 0; i < pos - 8; i++) { + if (verbose) + printf("%2u: 0x%02x(0x%02x) (sname)\n", i, result->sname[i], + options[i + 9]); + assert_se(result->sname[i] == options[i + 9]); + } + + if (verbose) + printf ("\n"); +} + +int main(int argc, char *argv[]) { + unsigned i; + + test_invalid_buffer_length(); + test_message_init(); + + test_options(NULL); + + for (i = 0; i < ELEMENTSOF(option_tests); i++) + test_options(&option_tests[i]); + + test_option_set(); + + return 0; +} diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c new file mode 100644 index 00000000..ea998939 --- /dev/null +++ b/src/libsystemd-network/test-dhcp-server.c @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Intel Corporation. All rights reserved. +***/ + +#include + +#include "sd-dhcp-server.h" +#include "sd-event.h" + +#include "dhcp-server-internal.h" +#include "tests.h" + +static void test_pool(struct in_addr *address, unsigned size, int ret) { + _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; + + assert_se(sd_dhcp_server_new(&server, 1) >= 0); + + assert_se(sd_dhcp_server_configure_pool(server, address, 8, 0, size) == ret); +} + +static int test_basic(sd_event *event) { + _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; + struct in_addr address_lo = { + .s_addr = htonl(INADDR_LOOPBACK), + }; + struct in_addr address_any = { + .s_addr = htonl(INADDR_ANY), + }; + int r; + + /* attach to loopback interface */ + assert_se(sd_dhcp_server_new(&server, 1) >= 0); + assert_se(server); + + assert_se(sd_dhcp_server_attach_event(server, event, 0) >= 0); + assert_se(sd_dhcp_server_attach_event(server, event, 0) == -EBUSY); + assert_se(sd_dhcp_server_get_event(server) == event); + assert_se(sd_dhcp_server_detach_event(server) >= 0); + assert_se(!sd_dhcp_server_get_event(server)); + assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0); + assert_se(sd_dhcp_server_attach_event(server, NULL, 0) == -EBUSY); + + assert_se(sd_dhcp_server_ref(server) == server); + assert_se(!sd_dhcp_server_unref(server)); + + assert_se(sd_dhcp_server_start(server) == -EUNATCH); + + assert_se(sd_dhcp_server_configure_pool(server, &address_any, 28, 0, 0) == -EINVAL); + assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 38, 0, 0) == -ERANGE); + assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0); + assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0); + + test_pool(&address_any, 1, -EINVAL); + test_pool(&address_lo, 1, 0); + + r = sd_dhcp_server_start(server); + if (r == -EPERM) + return log_info_errno(r, "sd_dhcp_server_start failed: %m"); + assert_se(r >= 0); + + assert_se(sd_dhcp_server_start(server) == -EBUSY); + assert_se(sd_dhcp_server_stop(server) >= 0); + assert_se(sd_dhcp_server_stop(server) >= 0); + assert_se(sd_dhcp_server_start(server) >= 0); + + return 0; +} + +static void test_message_handler(void) { + _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; + struct { + DHCPMessage message; + struct { + uint8_t code; + uint8_t length; + uint8_t type; + } _packed_ option_type; + struct { + uint8_t code; + uint8_t length; + be32_t address; + } _packed_ option_requested_ip; + struct { + uint8_t code; + uint8_t length; + be32_t address; + } _packed_ option_server_id; + struct { + uint8_t code; + uint8_t length; + uint8_t id[7]; + } _packed_ option_client_id; + uint8_t end; + } _packed_ test = { + .message.op = BOOTREQUEST, + .message.htype = ARPHRD_ETHER, + .message.hlen = ETHER_ADDR_LEN, + .message.xid = htobe32(0x12345678), + .message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' }, + .option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE, + .option_type.length = 1, + .option_type.type = DHCP_DISCOVER, + .end = SD_DHCP_OPTION_END, + }; + struct in_addr address_lo = { + .s_addr = htonl(INADDR_LOOPBACK), + }; + + assert_se(sd_dhcp_server_new(&server, 1) >= 0); + assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0); + assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0); + assert_se(sd_dhcp_server_start(server) >= 0); + + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + + test.end = 0; + /* TODO, shouldn't this fail? */ + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + test.end = SD_DHCP_OPTION_END; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + + test.option_type.code = 0; + test.option_type.length = 0; + test.option_type.type = 0; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + test.option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE; + test.option_type.length = 1; + test.option_type.type = DHCP_DISCOVER; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + + test.message.op = 0; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + test.message.op = BOOTREQUEST; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + + test.message.htype = 0; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + test.message.htype = ARPHRD_ETHER; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + + test.message.hlen = 0; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + test.message.hlen = ETHER_ADDR_LEN; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER); + + test.option_type.type = DHCP_REQUEST; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + test.option_requested_ip.code = SD_DHCP_OPTION_REQUESTED_IP_ADDRESS; + test.option_requested_ip.length = 4; + test.option_requested_ip.address = htobe32(0x12345678); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK); + test.option_server_id.code = SD_DHCP_OPTION_SERVER_IDENTIFIER; + test.option_server_id.length = 4; + test.option_server_id.address = htobe32(INADDR_LOOPBACK); + test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); + + test.option_server_id.address = htobe32(0x12345678); + test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + test.option_server_id.address = htobe32(INADDR_LOOPBACK); + test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); + test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); + + test.option_client_id.code = SD_DHCP_OPTION_CLIENT_IDENTIFIER; + test.option_client_id.length = 7; + test.option_client_id.id[0] = 0x01; + test.option_client_id.id[1] = 'A'; + test.option_client_id.id[2] = 'B'; + test.option_client_id.id[3] = 'C'; + test.option_client_id.id[4] = 'D'; + test.option_client_id.id[5] = 'E'; + test.option_client_id.id[6] = 'F'; + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK); + + test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30); + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0); +} + +static uint64_t client_id_hash_helper(DHCPClientId *id, uint8_t key[HASH_KEY_SIZE]) { + struct siphash state; + + siphash24_init(&state, key); + client_id_hash_func(id, &state); + + return htole64(siphash24_finalize(&state)); +} + +static void test_client_id_hash(void) { + DHCPClientId a = { + .length = 4, + }, b = { + .length = 4, + }; + uint8_t hash_key[HASH_KEY_SIZE] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + }; + + a.data = (uint8_t*)strdup("abcd"); + b.data = (uint8_t*)strdup("abcd"); + + assert_se(client_id_compare_func(&a, &b) == 0); + assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key)); + a.length = 3; + assert_se(client_id_compare_func(&a, &b) != 0); + a.length = 4; + assert_se(client_id_compare_func(&a, &b) == 0); + assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key)); + + b.length = 3; + assert_se(client_id_compare_func(&a, &b) != 0); + b.length = 4; + assert_se(client_id_compare_func(&a, &b) == 0); + assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key)); + + free(b.data); + b.data = (uint8_t*)strdup("abce"); + assert_se(client_id_compare_func(&a, &b) != 0); + + free(a.data); + free(b.data); +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_event_unrefp) sd_event *e; + int r; + + test_setup_logging(LOG_DEBUG); + + assert_se(sd_event_new(&e) >= 0); + + r = test_basic(e); + if (r != 0) + return log_tests_skipped("cannot start dhcp server"); + + test_message_handler(); + test_client_id_hash(); + + return 0; +} diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c new file mode 100644 index 00000000..4b89b320 --- /dev/null +++ b/src/libsystemd-network/test-dhcp6-client.c @@ -0,0 +1,950 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include +#include +#include + +#include "sd-dhcp6-client.h" +#include "sd-event.h" + +#include "dhcp6-internal.h" +#include "dhcp6-lease-internal.h" +#include "dhcp6-protocol.h" +#include "fd-util.h" +#include "macro.h" +#include "memory-util.h" +#include "socket-util.h" +#include "tests.h" +#include "time-util.h" +#include "virt.h" + +static struct ether_addr mac_addr = { + .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} +}; + +static sd_event_source *hangcheck; +static int test_dhcp_fd[2]; +static int test_index = 42; +static int test_client_message_num; +static be32_t test_iaid = 0; +static uint8_t test_duid[14] = { }; + +static int test_client_basic(sd_event *e) { + sd_dhcp6_client *client; + int v; + + log_debug("/* %s */", __func__); + + assert_se(sd_dhcp6_client_new(&client) >= 0); + assert_se(client); + + assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0); + + assert_se(sd_dhcp6_client_set_ifindex(client, 15) == 0); + assert_se(sd_dhcp6_client_set_ifindex(client, -42) == -EINVAL); + assert_se(sd_dhcp6_client_set_ifindex(client, -1) == 0); + assert_se(sd_dhcp6_client_set_ifindex(client, 42) >= 0); + + assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr, + sizeof (mac_addr), + ARPHRD_ETHER) >= 0); + + assert_se(sd_dhcp6_client_set_fqdn(client, "host") == 1); + assert_se(sd_dhcp6_client_set_fqdn(client, "host.domain") == 1); + assert_se(sd_dhcp6_client_set_fqdn(client, NULL) == 1); + assert_se(sd_dhcp6_client_set_fqdn(client, "~host") == -EINVAL); + assert_se(sd_dhcp6_client_set_fqdn(client, "~host.domain") == -EINVAL); + + assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL); + assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EEXIST); + assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) == -EEXIST); + assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVERS) == -EEXIST); + assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN_LIST) == -EEXIST); + assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL); + + assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0); + v = 0; + assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0); + assert_se(v); + assert_se(sd_dhcp6_client_set_information_request(client, 0) >= 0); + v = 42; + assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0); + assert_se(v == 0); + + v = 0; + assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0); + assert_se(v); + v = 0; + assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0); + assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0); + assert_se(v); + v = 42; + assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0); + assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0); + assert_se(v); + + assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0); + assert_se(sd_dhcp6_client_set_prefix_delegation(client, 1) >= 0); + v = 0; + assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0); + assert_se(v); + v = 0; + assert_se(sd_dhcp6_client_get_prefix_delegation(client, &v) >= 0); + assert_se(v); + + assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0); + + assert_se(sd_dhcp6_client_detach_event(client) >= 0); + assert_se(!sd_dhcp6_client_unref(client)); + + return 0; +} + +static int test_option(sd_event *e) { + uint8_t packet[] = { + 'F', 'O', 'O', + 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x07, + 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 0x00, SD_DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09, + '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'B', 'A', 'R', + }; + uint8_t result[] = { + 'F', 'O', 'O', + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 'B', 'A', 'R', + }; + uint16_t optcode; + size_t optlen; + uint8_t *optval, *buf, *out; + size_t zero = 0, pos = 3; + size_t buflen = sizeof(packet), outlen = sizeof(result); + + log_debug("/* %s */", __func__); + + assert_se(buflen == outlen); + + assert_se(dhcp6_option_parse(&buf, &zero, &optcode, &optlen, + &optval) == -ENOMSG); + + buflen -= 3; + buf = &packet[3]; + outlen -= 3; + out = &result[3]; + + assert_se(dhcp6_option_parse(&buf, &buflen, &optcode, &optlen, + &optval) >= 0); + pos += 4 + optlen; + assert_se(buf == &packet[pos]); + assert_se(optcode == SD_DHCP6_OPTION_ORO); + assert_se(optlen == 7); + assert_se(buflen + pos == sizeof(packet)); + + assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen, + optval) >= 0); + assert_se(out == &result[pos]); + assert_se(*out == 0x00); + + assert_se(dhcp6_option_parse(&buf, &buflen, &optcode, &optlen, + &optval) >= 0); + pos += 4 + optlen; + assert_se(buf == &packet[pos]); + assert_se(optcode == SD_DHCP6_OPTION_VENDOR_CLASS); + assert_se(optlen == 9); + assert_se(buflen + pos == sizeof(packet)); + + assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen, + optval) >= 0); + assert_se(out == &result[pos]); + assert_se(*out == 'B'); + + assert_se(memcmp(packet, result, sizeof(packet)) == 0); + + return 0; +} + +static int test_option_status(sd_event *e) { + uint8_t option1[] = { + /* IA NA */ + 0x00, 0x03, 0x00, 0x12, 0x1a, 0x1d, 0x1a, 0x1d, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, + /* status option */ + 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01, + }; + static const uint8_t option2[] = { + /* IA NA */ + 0x00, 0x03, 0x00, 0x2e, 0x1a, 0x1d, 0x1a, 0x1d, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, + /* IA Addr */ + 0x00, 0x05, 0x00, 0x1e, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d, + /* status option */ + 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01, + }; + static const uint8_t option3[] = { + /* IA NA */ + 0x00, 0x03, 0x00, 0x34, 0x1a, 0x1d, 0x1a, 0x1d, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, + /* IA Addr */ + 0x00, 0x05, 0x00, 0x24, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d, + /* status option */ + 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 'f', 'o', + 'o', 'b', 'a', 'r', + }; + static const uint8_t option4[] = { + /* IA PD */ + 0x00, 0x19, 0x00, 0x2f, 0x1a, 0x1d, 0x1a, 0x1d, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, + /* IA PD Prefix */ + 0x00, 0x1a, 0x00, 0x1f, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, + 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, + /* status option */ + 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00, + }; + static const uint8_t option5[] = { + /* IA PD */ + 0x00, 0x19, 0x00, 0x52, 0x1a, 0x1d, 0x1a, 0x1d, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, + /* IA PD Prefix #1 */ + 0x00, 0x1a, 0x00, 0x1f, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, + 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, + /* status option */ + 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00, + /* IA PD Prefix #2 */ + 0x00, 0x1a, 0x00, 0x1f, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x0l, 0xd0, + 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, + 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00, + }; + DHCP6Option *option; + DHCP6IA ia, pd; + int r = 0; + + log_debug("/* %s */", __func__); + + zero(ia); + option = (DHCP6Option *)option1; + assert_se(sizeof(option1) == sizeof(DHCP6Option) + be16toh(option->len)); + + r = dhcp6_option_parse_ia(option, &ia); + assert_se(r == -EINVAL); + assert_se(ia.addresses == NULL); + + option->len = htobe16(17); + r = dhcp6_option_parse_ia(option, &ia); + assert_se(r == -ENOBUFS); + assert_se(ia.addresses == NULL); + + option->len = htobe16(sizeof(DHCP6Option)); + r = dhcp6_option_parse_ia(option, &ia); + assert_se(r == -ENOBUFS); + assert_se(ia.addresses == NULL); + + zero(ia); + option = (DHCP6Option *)option2; + assert_se(sizeof(option2) == sizeof(DHCP6Option) + be16toh(option->len)); + + r = dhcp6_option_parse_ia(option, &ia); + assert_se(r >= 0); + assert_se(ia.addresses == NULL); + + zero(ia); + option = (DHCP6Option *)option3; + assert_se(sizeof(option3) == sizeof(DHCP6Option) + be16toh(option->len)); + + r = dhcp6_option_parse_ia(option, &ia); + assert_se(r >= 0); + assert_se(ia.addresses != NULL); + dhcp6_lease_free_ia(&ia); + + zero(pd); + option = (DHCP6Option *)option4; + assert_se(sizeof(option4) == sizeof(DHCP6Option) + be16toh(option->len)); + + r = dhcp6_option_parse_ia(option, &pd); + assert_se(r == 0); + assert_se(pd.addresses != NULL); + assert_se(memcmp(&pd.ia_pd.id, &option4[4], 4) == 0); + assert_se(memcmp(&pd.ia_pd.lifetime_t1, &option4[8], 4) == 0); + assert_se(memcmp(&pd.ia_pd.lifetime_t2, &option4[12], 4) == 0); + dhcp6_lease_free_ia(&pd); + + zero(pd); + option = (DHCP6Option *)option5; + assert_se(sizeof(option5) == sizeof(DHCP6Option) + be16toh(option->len)); + + r = dhcp6_option_parse_ia(option, &pd); + assert_se(r == 0); + assert_se(pd.addresses != NULL); + dhcp6_lease_free_ia(&pd); + + return 0; +} + +static uint8_t msg_advertise[198] = { + 0x02, 0x0f, 0xb4, 0xe5, 0x00, 0x01, 0x00, 0x0e, + 0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b, 0xf3, 0x30, + 0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x03, + 0x00, 0x5e, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x00, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x78, 0x00, 0x05, + 0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, + 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, + 0x55, 0xad, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, + 0x00, 0xb4, 0x00, 0x0d, 0x00, 0x32, 0x00, 0x00, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x28, + 0x65, 0x73, 0x29, 0x20, 0x72, 0x65, 0x6e, 0x65, + 0x77, 0x65, 0x64, 0x2e, 0x20, 0x47, 0x72, 0x65, + 0x65, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66, + 0x72, 0x6f, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e, + 0x65, 0x74, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, + 0x00, 0x17, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, + 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x0b, + 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, + 0x72, 0x61, 0x00, 0x00, 0x1f, 0x00, 0x10, 0x20, + 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x19, + 0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, + 0x53, 0x00, 0x07, 0x00, 0x01, 0x00 +}; + +static uint8_t msg_reply[173] = { + 0x07, 0xf7, 0x4e, 0x57, 0x00, 0x02, 0x00, 0x0e, + 0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53, + 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, 0x00, 0x01, + 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b, + 0xf3, 0x30, 0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d, + 0x00, 0x03, 0x00, 0x4a, 0x0e, 0xcf, 0xa3, 0x7d, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x78, + 0x00, 0x05, 0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8, + 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, + 0x09, 0x3c, 0x55, 0xad, 0x00, 0x00, 0x00, 0x96, + 0x00, 0x00, 0x00, 0xb4, 0x00, 0x0d, 0x00, 0x1e, + 0x00, 0x00, 0x41, 0x6c, 0x6c, 0x20, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, + 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x00, 0x17, + 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, + 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x18, 0x00, 0x0b, 0x03, 0x6c, + 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61, + 0x00, 0x00, 0x1f, 0x00, 0x10, 0x20, 0x01, 0x0d, + 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01 +}; + +static uint8_t fqdn_wire[16] = { + 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', + 0x05, 'i', 'n', 't', 'r', 'a', 0x00 +}; + +static int test_advertise_option(sd_event *e) { + _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; + DHCP6Message *advertise = (DHCP6Message *)msg_advertise; + size_t len = sizeof(msg_advertise) - sizeof(DHCP6Message), pos = 0; + be32_t val; + uint8_t preference = 255; + struct in6_addr addr; + uint32_t lt_pref, lt_valid; + int r; + uint8_t *opt; + bool opt_clientid = false; + struct in6_addr *addrs; + char **domains; + + log_debug("/* %s */", __func__); + + assert_se(len >= sizeof(DHCP6Message)); + + assert_se(dhcp6_lease_new(&lease) >= 0); + + assert_se(advertise->type == DHCP6_ADVERTISE); + assert_se((be32toh(advertise->transaction_id) & 0x00ffffff) == + 0x0fb4e5); + + while (pos < len) { + DHCP6Option *option = (DHCP6Option *)&advertise->options[pos]; + const uint16_t optcode = be16toh(option->code); + const uint16_t optlen = be16toh(option->len); + uint8_t *optval = option->data; + + switch(optcode) { + case SD_DHCP6_OPTION_CLIENTID: + assert_se(optlen == 14); + + opt_clientid = true; + break; + + case SD_DHCP6_OPTION_IA_NA: + assert_se(optlen == 94); + assert_se(!memcmp(optval, &msg_advertise[26], optlen)); + + val = htobe32(0x0ecfa37d); + assert_se(!memcmp(optval, &val, sizeof(val))); + + val = htobe32(80); + assert_se(!memcmp(optval + 4, &val, sizeof(val))); + + val = htobe32(120); + assert_se(!memcmp(optval + 8, &val, sizeof(val))); + + assert_se(dhcp6_option_parse_ia(option, &lease->ia) >= 0); + + break; + + case SD_DHCP6_OPTION_SERVERID: + assert_se(optlen == 14); + assert_se(!memcmp(optval, &msg_advertise[179], optlen)); + + assert_se(dhcp6_lease_set_serverid(lease, optval, + optlen) >= 0); + break; + + case SD_DHCP6_OPTION_PREFERENCE: + assert_se(optlen == 1); + assert_se(!*optval); + + assert_se(dhcp6_lease_set_preference(lease, + *optval) >= 0); + break; + + case SD_DHCP6_OPTION_ELAPSED_TIME: + assert_se(optlen == 2); + + break; + + case SD_DHCP6_OPTION_DNS_SERVERS: + assert_se(optlen == 16); + assert_se(dhcp6_lease_set_dns(lease, optval, + optlen) >= 0); + break; + + case SD_DHCP6_OPTION_DOMAIN_LIST: + assert_se(optlen == 11); + assert_se(dhcp6_lease_set_domains(lease, optval, + optlen) >= 0); + break; + + case SD_DHCP6_OPTION_SNTP_SERVERS: + assert_se(optlen == 16); + assert_se(dhcp6_lease_set_sntp(lease, optval, + optlen) >= 0); + break; + + default: + break; + } + + pos += sizeof(*option) + optlen; + } + + assert_se(pos == len); + assert_se(opt_clientid); + + sd_dhcp6_lease_reset_address_iter(lease); + assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, + <_valid) >= 0); + assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); + assert_se(lt_pref == 150); + assert_se(lt_valid == 180); + assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, + <_valid) == -ENOMSG); + + sd_dhcp6_lease_reset_address_iter(lease); + assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, + <_valid) >= 0); + assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); + assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, + <_valid) == -ENOMSG); + sd_dhcp6_lease_reset_address_iter(lease); + assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, + <_valid) >= 0); + assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); + assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, + <_valid) == -ENOMSG); + + assert_se(dhcp6_lease_get_serverid(lease, &opt, &len) >= 0); + assert_se(len == 14); + assert_se(!memcmp(opt, &msg_advertise[179], len)); + + assert_se(dhcp6_lease_get_preference(lease, &preference) >= 0); + assert_se(preference == 0); + + r = sd_dhcp6_lease_get_dns(lease, &addrs); + assert_se(r == 1); + assert_se(!memcmp(addrs, &msg_advertise[124], r * 16)); + + r = sd_dhcp6_lease_get_domains(lease, &domains); + assert_se(r == 1); + assert_se(!strcmp("lab.intra", domains[0])); + assert_se(domains[1] == NULL); + + r = sd_dhcp6_lease_get_ntp_addrs(lease, &addrs); + assert_se(r == 1); + assert_se(!memcmp(addrs, &msg_advertise[159], r * 16)); + + return 0; +} + +static int test_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) { + assert_not_reached("Test case should have completed in 2 seconds"); + + return 0; +} + +static void test_client_solicit_cb(sd_dhcp6_client *client, int event, + void *userdata) { + sd_event *e = userdata; + sd_dhcp6_lease *lease; + struct in6_addr *addrs; + char **domains; + + log_debug("/* %s */", __func__); + + assert_se(e); + assert_se(event == SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE); + + assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0); + + assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1); + assert_se(!strcmp("lab.intra", domains[0])); + assert_se(domains[1] == NULL); + + assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1); + assert_se(!memcmp(addrs, &msg_advertise[124], 16)); + + assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1); + assert_se(!memcmp(addrs, &msg_advertise[159], 16)); + + assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EBUSY); + + sd_event_exit(e, 0); +} + +static int test_client_send_reply(DHCP6Message *request) { + DHCP6Message reply; + + reply.transaction_id = request->transaction_id; + reply.type = DHCP6_REPLY; + + memcpy(msg_reply, &reply.transaction_id, 4); + + memcpy(&msg_reply[26], test_duid, sizeof(test_duid)); + + memcpy(&msg_reply[44], &test_iaid, sizeof(test_iaid)); + + assert_se(write(test_dhcp_fd[1], msg_reply, sizeof(msg_reply)) + == sizeof(msg_reply)); + + return 0; +} + +static int test_client_verify_request(DHCP6Message *request, size_t len) { + _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; + size_t pos = 0; + bool found_clientid = false, found_iana = false, found_serverid = false, + found_elapsed_time = false, found_fqdn = false; + struct in6_addr addr; + be32_t val; + uint32_t lt_pref, lt_valid; + + log_debug("/* %s */", __func__); + + assert_se(request->type == DHCP6_REQUEST); + assert_se(dhcp6_lease_new(&lease) >= 0); + + len -= sizeof(DHCP6Message); + + while (pos < len) { + DHCP6Option *option = (DHCP6Option *)&request->options[pos]; + uint16_t optcode = be16toh(option->code); + uint16_t optlen = be16toh(option->len); + uint8_t *optval = option->data; + + switch(optcode) { + case SD_DHCP6_OPTION_CLIENTID: + assert_se(!found_clientid); + found_clientid = true; + + assert_se(!memcmp(optval, &test_duid, + sizeof(test_duid))); + + break; + + case SD_DHCP6_OPTION_IA_NA: + assert_se(!found_iana); + found_iana = true; + + assert_se(optlen == 40); + assert_se(!memcmp(optval, &test_iaid, sizeof(test_iaid))); + + val = htobe32(80); + assert_se(!memcmp(optval + 4, &val, sizeof(val))); + + val = htobe32(120); + assert_se(!memcmp(optval + 8, &val, sizeof(val))); + + assert_se(!dhcp6_option_parse_ia(option, &lease->ia)); + + break; + + case SD_DHCP6_OPTION_SERVERID: + assert_se(!found_serverid); + found_serverid = true; + + assert_se(optlen == 14); + assert_se(!memcmp(&msg_advertise[179], optval, optlen)); + + break; + + case SD_DHCP6_OPTION_ELAPSED_TIME: + assert_se(!found_elapsed_time); + found_elapsed_time = true; + + assert_se(optlen == 2); + + break; + case SD_DHCP6_OPTION_FQDN: + assert_se(!found_fqdn); + found_fqdn = true; + + assert_se(optlen == 17); + + assert_se(optval[0] == 0x01); + assert_se(!memcmp(optval + 1, fqdn_wire, sizeof(fqdn_wire))); + break; + } + + pos += sizeof(*option) + optlen; + } + + assert_se(found_clientid && found_iana && found_serverid && + found_elapsed_time); + + sd_dhcp6_lease_reset_address_iter(lease); + assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, + <_valid) >= 0); + assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr))); + assert_se(lt_pref == 150); + assert_se(lt_valid == 180); + + assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, + <_valid) == -ENOMSG); + + return 0; +} + +static int test_client_send_advertise(DHCP6Message *solicit) { + DHCP6Message advertise; + + advertise.transaction_id = solicit->transaction_id; + advertise.type = DHCP6_ADVERTISE; + + memcpy(msg_advertise, &advertise.transaction_id, 4); + + memcpy(&msg_advertise[8], test_duid, sizeof(test_duid)); + + memcpy(&msg_advertise[26], &test_iaid, sizeof(test_iaid)); + + assert_se(write(test_dhcp_fd[1], msg_advertise, sizeof(msg_advertise)) + == sizeof(msg_advertise)); + + return 0; +} + +static int test_client_verify_solicit(DHCP6Message *solicit, size_t len) { + bool found_clientid = false, found_iana = false, + found_elapsed_time = false, found_fqdn = false; + size_t pos = 0; + + log_debug("/* %s */", __func__); + + assert_se(solicit->type == DHCP6_SOLICIT); + + len -= sizeof(DHCP6Message); + + while (pos < len) { + DHCP6Option *option = (DHCP6Option *)&solicit->options[pos]; + uint16_t optcode = be16toh(option->code); + uint16_t optlen = be16toh(option->len); + uint8_t *optval = option->data; + + switch(optcode) { + case SD_DHCP6_OPTION_CLIENTID: + assert_se(!found_clientid); + found_clientid = true; + + assert_se(optlen == sizeof(test_duid)); + memcpy(&test_duid, optval, sizeof(test_duid)); + + break; + + case SD_DHCP6_OPTION_IA_NA: + assert_se(!found_iana); + found_iana = true; + + assert_se(optlen == 12); + + memcpy(&test_iaid, optval, sizeof(test_iaid)); + + break; + + case SD_DHCP6_OPTION_ELAPSED_TIME: + assert_se(!found_elapsed_time); + found_elapsed_time = true; + + assert_se(optlen == 2); + + break; + + case SD_DHCP6_OPTION_FQDN: + assert_se(!found_fqdn); + found_fqdn = true; + + assert_se(optlen == 17); + + assert_se(optval[0] == 0x01); + assert_se(!memcmp(optval + 1, fqdn_wire, sizeof(fqdn_wire))); + + break; + } + + pos += sizeof(*option) + optlen; + } + + assert_se(pos == len); + assert_se(found_clientid && found_iana && found_elapsed_time); + + return 0; +} + +static void test_client_information_cb(sd_dhcp6_client *client, int event, + void *userdata) { + sd_event *e = userdata; + sd_dhcp6_lease *lease; + struct in6_addr *addrs; + struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; + char **domains; + + log_debug("/* %s */", __func__); + + assert_se(e); + assert_se(event == SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST); + + assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0); + + assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1); + assert_se(!strcmp("lab.intra", domains[0])); + assert_se(domains[1] == NULL); + + assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1); + assert_se(!memcmp(addrs, &msg_advertise[124], 16)); + + assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1); + assert_se(!memcmp(addrs, &msg_advertise[159], 16)); + + assert_se(sd_dhcp6_client_set_information_request(client, false) == -EBUSY); + assert_se(sd_dhcp6_client_set_callback(client, NULL, e) >= 0); + assert_se(sd_dhcp6_client_stop(client) >= 0); + assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0); + + assert_se(sd_dhcp6_client_set_callback(client, + test_client_solicit_cb, e) >= 0); + + assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); + + assert_se(sd_dhcp6_client_start(client) >= 0); + +} + +static int test_client_verify_information_request(DHCP6Message *information_request, + size_t len) { + + _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; + size_t pos = 0; + bool found_clientid = false, found_elapsed_time = false; + struct in6_addr addr; + uint32_t lt_pref, lt_valid; + + log_debug("/* %s */", __func__); + + assert_se(information_request->type == DHCP6_INFORMATION_REQUEST); + assert_se(dhcp6_lease_new(&lease) >= 0); + + len -= sizeof(DHCP6Message); + + while (pos < len) { + DHCP6Option *option = (DHCP6Option *)&information_request->options[pos]; + uint16_t optcode = be16toh(option->code); + uint16_t optlen = be16toh(option->len); + uint8_t *optval = option->data; + + switch(optcode) { + case SD_DHCP6_OPTION_CLIENTID: + assert_se(!found_clientid); + found_clientid = true; + + assert_se(optlen == sizeof(test_duid)); + memcpy(&test_duid, optval, sizeof(test_duid)); + + break; + + case SD_DHCP6_OPTION_IA_NA: + assert_not_reached("IA TA option must not be present"); + + break; + + case SD_DHCP6_OPTION_SERVERID: + assert_not_reached("Server ID option must not be present"); + + break; + + case SD_DHCP6_OPTION_ELAPSED_TIME: + assert_se(!found_elapsed_time); + found_elapsed_time = true; + + assert_se(optlen == 2); + + break; + } + + pos += sizeof(*option) + optlen; + } + + assert_se(pos == len); + assert_se(found_clientid && found_elapsed_time); + + sd_dhcp6_lease_reset_address_iter(lease); + + assert_se(sd_dhcp6_lease_get_address(lease, &addr, <_pref, + <_valid) == -ENOMSG); + + return 0; +} + +int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, + const void *packet, size_t len) { + struct in6_addr mcast = + IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; + DHCP6Message *message; + + assert_se(s == test_dhcp_fd[0]); + assert_se(server_address); + assert_se(packet); + assert_se(len > sizeof(DHCP6Message) + 4); + assert_se(IN6_ARE_ADDR_EQUAL(server_address, &mcast)); + + message = (DHCP6Message *)packet; + + assert_se(message->transaction_id & 0x00ffffff); + + if (test_client_message_num == 0) { + test_client_verify_information_request(message, len); + test_client_send_reply(message); + test_client_message_num++; + } else if (test_client_message_num == 1) { + test_client_verify_solicit(message, len); + test_client_send_advertise(message); + test_client_message_num++; + } else if (test_client_message_num == 2) { + test_client_verify_request(message, len); + test_client_send_reply(message); + test_client_message_num++; + } + + return len; +} + +int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) { + assert_se(index == test_index); + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_dhcp_fd) < 0) + return -errno; + + return test_dhcp_fd[0]; +} + +static int test_client_solicit(sd_event *e) { + sd_dhcp6_client *client; + usec_t time_now = now(clock_boottime_or_monotonic()); + struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; + int val; + + log_debug("/* %s */", __func__); + + assert_se(sd_dhcp6_client_new(&client) >= 0); + assert_se(client); + + assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0); + + assert_se(sd_dhcp6_client_set_ifindex(client, test_index) == 0); + assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr, + sizeof (mac_addr), + ARPHRD_ETHER) >= 0); + assert_se(sd_dhcp6_client_set_fqdn(client, "host.lab.intra") == 1); + + assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0); + assert_se(val == 0); + assert_se(sd_dhcp6_client_set_information_request(client, 42) >= 0); + assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0); + assert_se(val); + + assert_se(sd_dhcp6_client_set_callback(client, + test_client_information_cb, e) >= 0); + + assert_se(sd_event_add_time(e, &hangcheck, clock_boottime_or_monotonic(), + time_now + 2 * USEC_PER_SEC, 0, + test_hangcheck, NULL) >= 0); + + assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); + + assert_se(sd_dhcp6_client_start(client) >= 0); + + sd_event_loop(e); + + hangcheck = sd_event_source_unref(hangcheck); + + assert_se(!sd_dhcp6_client_unref(client)); + + test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]); + + return 0; +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_event_unrefp) sd_event *e; + + assert_se(sd_event_new(&e) >= 0); + + test_setup_logging(LOG_DEBUG); + + test_client_basic(e); + test_option(e); + test_option_status(e); + test_advertise_option(e); + test_client_solicit(e); + + return 0; +} diff --git a/src/libsystemd-network/test-ipv4ll-manual.c b/src/libsystemd-network/test-ipv4ll-manual.c new file mode 100644 index 00000000..fd827ff4 --- /dev/null +++ b/src/libsystemd-network/test-ipv4ll-manual.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-event.h" +#include "sd-ipv4ll.h" +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "in-addr-util.h" +#include "netlink-util.h" +#include "parse-util.h" +#include "string-util.h" +#include "tests.h" +#include "util.h" + +static void ll_handler(sd_ipv4ll *ll, int event, void *userdata) { + _cleanup_free_ char *address = NULL; + struct in_addr addr = {}; + + assert_se(ll); + + if (sd_ipv4ll_get_address(ll, &addr) >= 0) + assert_se(in_addr_to_string(AF_INET, (const union in_addr_union*) &addr, &address) >= 0); + + switch (event) { + case SD_IPV4LL_EVENT_BIND: + log_info("bound %s", strna(address)); + break; + case SD_IPV4LL_EVENT_CONFLICT: + log_info("conflict on %s", strna(address)); + break; + case SD_IPV4LL_EVENT_STOP: + log_error("the client was stopped with address %s", strna(address)); + break; + default: + assert_not_reached("invalid LL event"); + } +} + +static int client_run(int ifindex, const char *seed_str, const struct ether_addr *ha, sd_event *e) { + sd_ipv4ll *ll; + + assert_se(sd_ipv4ll_new(&ll) >= 0); + assert_se(sd_ipv4ll_attach_event(ll, e, 0) >= 0); + + assert_se(sd_ipv4ll_set_ifindex(ll, ifindex) >= 0); + assert_se(sd_ipv4ll_set_mac(ll, ha) >= 0); + assert_se(sd_ipv4ll_set_callback(ll, ll_handler, NULL) >= 0); + + if (seed_str) { + unsigned seed; + + assert_se(safe_atou(seed_str, &seed) >= 0); + + assert_se(sd_ipv4ll_set_address_seed(ll, seed) >= 0); + } + + log_info("starting IPv4LL client"); + + assert_se(sd_ipv4ll_start(ll) >= 0); + + assert_se(sd_event_loop(e) >= 0); + + assert_se(!sd_ipv4ll_unref(ll)); + + return EXIT_SUCCESS; +} + +static int test_ll(const char *ifname, const char *seed) { + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL; + struct ether_addr ha; + int ifindex; + + assert_se(sd_event_new(&e) >= 0); + + assert_se(sd_netlink_open(&rtnl) >= 0); + assert_se(sd_netlink_attach_event(rtnl, e, 0) >= 0); + + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, 0) >= 0); + assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, ifname) >= 0); + assert_se(sd_netlink_call(rtnl, m, 0, &reply) >= 0); + + assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0); + assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0); + + client_run(ifindex, seed, &ha, e); + + return EXIT_SUCCESS; +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + if (argc == 2) + return test_ll(argv[1], NULL); + else if (argc == 3) + return test_ll(argv[1], argv[2]); + else { + log_error("This program takes one or two arguments.\n" + "\t %s []", program_invocation_short_name); + return EXIT_FAILURE; + } +} diff --git a/src/libsystemd-network/test-ipv4ll.c b/src/libsystemd-network/test-ipv4ll.c new file mode 100644 index 00000000..2f319bf7 --- /dev/null +++ b/src/libsystemd-network/test-ipv4ll.c @@ -0,0 +1,205 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Axis Communications AB. All rights reserved. +***/ + +#include +#include +#include +#include +#include +#include + +#include "sd-ipv4ll.h" + +#include "arp-util.h" +#include "fd-util.h" +#include "socket-util.h" +#include "tests.h" +#include "util.h" + +static bool verbose = false; +static bool extended = false; +static int test_fd[2]; + +static int basic_request_handler_bind = 0; +static int basic_request_handler_stop = 0; +static void* basic_request_handler_userdata = (void*) 0xCABCAB; + +static void basic_request_handler(sd_ipv4ll *ll, int event, void *userdata) { + assert_se(userdata == basic_request_handler_userdata); + + switch(event) { + case SD_IPV4LL_EVENT_STOP: + basic_request_handler_stop = 1; + break; + case SD_IPV4LL_EVENT_BIND: + basic_request_handler_bind = 1; + break; + default: + assert_se(0); + break; + } +} + +static int arp_network_send_raw_socket(int fd, int ifindex, + const struct ether_arp *arp) { + assert_se(arp); + assert_se(ifindex > 0); + assert_se(fd >= 0); + + if (send(fd, arp, sizeof(struct ether_arp), 0) < 0) + return -errno; + + return 0; +} + +int arp_send_probe(int fd, int ifindex, + be32_t pa, const struct ether_addr *ha) { + struct ether_arp ea = {}; + + assert_se(fd >= 0); + assert_se(ifindex > 0); + assert_se(pa != 0); + assert_se(ha); + + return arp_network_send_raw_socket(fd, ifindex, &ea); +} + +int arp_send_announcement(int fd, int ifindex, + be32_t pa, const struct ether_addr *ha) { + struct ether_arp ea = {}; + + assert_se(fd >= 0); + assert_se(ifindex > 0); + assert_se(pa != 0); + assert_se(ha); + + return arp_network_send_raw_socket(fd, ifindex, &ea); +} + +int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_addr *eth_mac) { + if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0) + return -errno; + + return test_fd[0]; +} + +static void test_public_api_setters(sd_event *e) { + struct in_addr address = {}; + uint64_t seed = 0; + sd_ipv4ll *ll; + struct ether_addr mac_addr = { + .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}}; + + if (verbose) + printf("* %s\n", __FUNCTION__); + + assert_se(sd_ipv4ll_new(&ll) == 0); + assert_se(ll); + + assert_se(sd_ipv4ll_attach_event(NULL, NULL, 0) == -EINVAL); + assert_se(sd_ipv4ll_attach_event(ll, e, 0) == 0); + assert_se(sd_ipv4ll_attach_event(ll, e, 0) == -EBUSY); + + assert_se(sd_ipv4ll_set_callback(NULL, NULL, NULL) == -EINVAL); + assert_se(sd_ipv4ll_set_callback(ll, NULL, NULL) == 0); + + assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL); + address.s_addr |= htobe32(169U << 24 | 254U << 16); + assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL); + address.s_addr |= htobe32(0x00FF); + assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL); + address.s_addr |= htobe32(0xF000); + assert_se(sd_ipv4ll_set_address(ll, &address) == 0); + address.s_addr |= htobe32(0x0F00); + assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL); + + assert_se(sd_ipv4ll_set_address_seed(NULL, seed) == -EINVAL); + assert_se(sd_ipv4ll_set_address_seed(ll, seed) == 0); + + assert_se(sd_ipv4ll_set_mac(NULL, NULL) == -EINVAL); + assert_se(sd_ipv4ll_set_mac(ll, NULL) == -EINVAL); + assert_se(sd_ipv4ll_set_mac(ll, &mac_addr) == 0); + + assert_se(sd_ipv4ll_set_ifindex(NULL, -1) == -EINVAL); + assert_se(sd_ipv4ll_set_ifindex(ll, -1) == -EINVAL); + assert_se(sd_ipv4ll_set_ifindex(ll, -99) == -EINVAL); + assert_se(sd_ipv4ll_set_ifindex(ll, 1) == 0); + assert_se(sd_ipv4ll_set_ifindex(ll, 99) == 0); + + assert_se(sd_ipv4ll_ref(ll) == ll); + assert_se(sd_ipv4ll_unref(ll) == NULL); + + /* Cleanup */ + assert_se(sd_ipv4ll_unref(ll) == NULL); +} + +static void test_basic_request(sd_event *e) { + + sd_ipv4ll *ll; + struct ether_arp arp; + struct ether_addr mac_addr = { + .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}}; + + if (verbose) + printf("* %s\n", __FUNCTION__); + + assert_se(sd_ipv4ll_new(&ll) == 0); + assert_se(sd_ipv4ll_start(ll) == -EINVAL); + + assert_se(sd_ipv4ll_attach_event(ll, e, 0) == 0); + assert_se(sd_ipv4ll_start(ll) == -EINVAL); + + assert_se(sd_ipv4ll_set_mac(ll, &mac_addr) == 0); + assert_se(sd_ipv4ll_start(ll) == -EINVAL); + + assert_se(sd_ipv4ll_set_callback(ll, basic_request_handler, + basic_request_handler_userdata) == 0); + assert_se(sd_ipv4ll_start(ll) == -EINVAL); + + assert_se(sd_ipv4ll_set_ifindex(ll, 1) == 0); + assert_se(sd_ipv4ll_start(ll) == 0); + + sd_event_run(e, (uint64_t) -1); + assert_se(sd_ipv4ll_start(ll) == -EBUSY); + + assert_se(sd_ipv4ll_is_running(ll)); + + /* PROBE */ + sd_event_run(e, (uint64_t) -1); + assert_se(recv(test_fd[1], &arp, sizeof(struct ether_arp), 0) == sizeof(struct ether_arp)); + + if (extended) { + /* PROBE */ + sd_event_run(e, (uint64_t) -1); + assert_se(recv(test_fd[1], &arp, sizeof(struct ether_arp), 0) == sizeof(struct ether_arp)); + + /* PROBE */ + sd_event_run(e, (uint64_t) -1); + assert_se(recv(test_fd[1], &arp, sizeof(struct ether_arp), 0) == sizeof(struct ether_arp)); + + sd_event_run(e, (uint64_t) -1); + assert_se(basic_request_handler_bind == 1); + } + + sd_ipv4ll_stop(ll); + assert_se(basic_request_handler_stop == 1); + + /* Cleanup */ + assert_se(sd_ipv4ll_unref(ll) == NULL); + safe_close(test_fd[1]); +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + + test_setup_logging(LOG_DEBUG); + + assert_se(sd_event_new(&e) >= 0); + + test_public_api_setters(e); + test_basic_request(e); + + return 0; +} diff --git a/src/libsystemd-network/test-lldp.c b/src/libsystemd-network/test-lldp.c new file mode 100644 index 00000000..a2ac6509 --- /dev/null +++ b/src/libsystemd-network/test-lldp.c @@ -0,0 +1,378 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-event.h" +#include "sd-lldp.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "lldp-network.h" +#include "macro.h" +#include "string-util.h" +#include "tests.h" + +#define TEST_LLDP_PORT "em1" +#define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp" +#define TEST_LLDP_TYPE_SYSTEM_DESC "systemd-lldp-desc" + +static int test_fd[2] = { -1, -1 }; +static int lldp_handler_calls; + +int lldp_network_bind_raw_socket(int ifindex) { + if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0) + return -errno; + + return test_fd[0]; +} + +static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) { + lldp_handler_calls++; +} + +static int start_lldp(sd_lldp **lldp, sd_event *e, sd_lldp_callback_t cb, void *cb_data) { + int r; + + r = sd_lldp_new(lldp); + if (r < 0) + return r; + + r = sd_lldp_set_ifindex(*lldp, 42); + if (r < 0) + return r; + + r = sd_lldp_set_callback(*lldp, cb, cb_data); + if (r < 0) + return r; + + r = sd_lldp_attach_event(*lldp, e, 0); + if (r < 0) + return r; + + r = sd_lldp_start(*lldp); + if (r < 0) + return r; + + return 0; +} + +static int stop_lldp(sd_lldp *lldp) { + int r; + + r = sd_lldp_stop(lldp); + if (r < 0) + return r; + + r = sd_lldp_detach_event(lldp); + if (r < 0) + return r; + + sd_lldp_unref(lldp); + safe_close(test_fd[1]); + + return 0; +} + +static void test_receive_basic_packet(sd_event *e) { + + static const uint8_t frame[] = { + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ + 0x03, 0x04, 0x05, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + /* LLDP optional TLVs */ + 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ + 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ + 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ + 0x00, 0x00 /* End Of LLDPDU */ + }; + + sd_lldp *lldp; + sd_lldp_neighbor **neighbors; + uint8_t type; + const void *data; + uint16_t ttl; + size_t length; + const char *str; + + lldp_handler_calls = 0; + assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0); + + assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame)); + sd_event_run(e, 0); + assert_se(lldp_handler_calls == 1); + assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1); + + assert_se(sd_lldp_neighbor_get_chassis_id(neighbors[0], &type, &data, &length) == 0); + assert_se(type == SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS); + assert_se(length == ETH_ALEN); + assert_se(!memcmp(data, "\x00\x01\x02\x03\x04\x05", ETH_ALEN)); + + assert_se(sd_lldp_neighbor_get_port_id(neighbors[0], &type, &data, &length) == 0); + assert_se(type == SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME); + assert_se(length == 3); + assert_se(!memcmp(data, "1/3", 3)); + + assert_se(sd_lldp_neighbor_get_port_description(neighbors[0], &str) == 0); + assert_se(streq(str, "Port")); + + assert_se(sd_lldp_neighbor_get_system_name(neighbors[0], &str) == 0); + assert_se(streq(str, "SYS")); + + assert_se(sd_lldp_neighbor_get_system_description(neighbors[0], &str) == 0); + assert_se(streq(str, "foo")); + + assert_se(sd_lldp_neighbor_get_ttl(neighbors[0], &ttl) == 0); + assert_se(ttl == 120); + + sd_lldp_neighbor_unref(neighbors[0]); + free(neighbors); + + assert_se(stop_lldp(lldp) == 0); +} + +static void test_receive_incomplete_packet(sd_event *e) { + sd_lldp *lldp; + sd_lldp_neighbor **neighbors; + uint8_t frame[] = { + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ + 0x03, 0x04, 0x05, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ + /* Missing TTL */ + 0x00, 0x00 /* End Of LLDPDU */ + }; + + lldp_handler_calls = 0; + assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0); + + assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame)); + sd_event_run(e, 0); + assert_se(lldp_handler_calls == 0); + assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 0); + + assert_se(stop_lldp(lldp) == 0); +} + +static void test_receive_oui_packet(sd_event *e) { + sd_lldp *lldp; + sd_lldp_neighbor **neighbors; + uint8_t frame[] = { + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ + 0x03, 0x04, 0x05, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port TLV: interface name, "1/3" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + /* LLDP optional TLVs */ + 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x01, /* Port VLAN ID: 0x1234 */ + 0x12, 0x34, + 0xfe, 0x07, 0x00, 0x80, 0xc2, 0x02, /* Port and protocol: flag 1, PPVID 0x7788 */ + 0x01, 0x77, 0x88, + 0xfe, 0x0d, 0x00, 0x80, 0xc2, 0x03, /* VLAN Name: ID 0x1234, name "Vlan51" */ + 0x12, 0x34, 0x06, 0x56, 0x6c, 0x61, + 0x6e, 0x35, 0x31, + 0xfe, 0x06, 0x00, 0x80, 0xc2, 0x06, /* Management VID: 0x0102 */ + 0x01, 0x02, + 0xfe, 0x09, 0x00, 0x80, 0xc2, 0x07, /* Link aggregation: status 1, ID 0x00140012 */ + 0x01, 0x00, 0x14, 0x00, 0x12, + 0xfe, 0x07, 0x00, 0x12, 0x0f, 0x02, /* 802.3 Power via MDI: PSE, MDI enabled */ + 0x07, 0x01, 0x00, + 0x00, 0x00 /* End of LLDPDU */ + }; + + lldp_handler_calls = 0; + assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0); + + assert_se(write(test_fd[1], frame, sizeof(frame)) == sizeof(frame)); + sd_event_run(e, 0); + assert_se(lldp_handler_calls == 1); + assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 1); + + assert_se(sd_lldp_neighbor_tlv_rewind(neighbors[0]) >= 0); + assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_CHASSIS_ID) > 0); + assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0); + assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_PORT_ID) > 0); + assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0); + assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_TTL) > 0); + assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0); + assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID) > 0); + assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0); + assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID) > 0); + assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0); + assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME) > 0); + assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0); + assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID) > 0); + assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0); + assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_1, SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION) > 0); + assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0); + assert_se(sd_lldp_neighbor_tlv_is_oui(neighbors[0], SD_LLDP_OUI_802_3, SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI) > 0); + assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) > 0); + assert_se(sd_lldp_neighbor_tlv_is_type(neighbors[0], SD_LLDP_TYPE_END) > 0); + assert_se(sd_lldp_neighbor_tlv_next(neighbors[0]) == 0); + + sd_lldp_neighbor_unref(neighbors[0]); + free(neighbors); + + assert_se(stop_lldp(lldp) == 0); +} + +static void test_multiple_neighbors_sorted(sd_event *e) { + + static const uint8_t frame1[] = { + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x04, 0x01, '1', '/', '2', /* Chassis component: "1/2" */ + 0x04, 0x04, 0x02, '2', '/', '3', /* Port component: "2/3" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + 0x00, 0x00 /* End Of LLDPDU */ + }; + static const uint8_t frame2[] = { + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x04, 0x01, '2', '/', '1', /* Chassis component: "2/1" */ + 0x04, 0x04, 0x02, '1', '/', '3', /* Port component: "1/3" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + 0x00, 0x00 /* End Of LLDPDU */ + }; + static const uint8_t frame3[] = { + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x05, 0x01, '2', '/', '1', '0', /* Chassis component: "2/10" */ + 0x04, 0x04, 0x02, '1', '/', '0', /* Port component: "1/0" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + 0x00, 0x00 /* End Of LLDPDU */ + }; + static const uint8_t frame4[] = { + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x05, 0x01, '2', '/', '1', '9', /* Chassis component: "2/19" */ + 0x04, 0x04, 0x02, '1', '/', '0', /* Port component: "1/0" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + 0x00, 0x00 /* End Of LLDPDU */ + }; + static const uint8_t frame5[] = { + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x04, 0x01, '1', '/', '2', /* Chassis component: "1/2" */ + 0x04, 0x05, 0x02, '2', '/', '1', '0', /* Port component: "2/10" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + 0x00, 0x00 /* End Of LLDPDU */ + }; + static const uint8_t frame6[] = { + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x04, 0x01, '1', '/', '2', /* Chassis component: "1/2" */ + 0x04, 0x05, 0x02, '2', '/', '3', '9', /* Port component: "2/10" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + 0x00, 0x00 /* End Of LLDPDU */ + }; + static const char* expected[] = { + /* ordered pairs of Chassis+Port */ + "1/2", "2/10", + "1/2", "2/3", + "1/2", "2/39", + "2/1", "1/3", + "2/10", "1/0", + "2/19", "1/0", + }; + + sd_lldp *lldp; + sd_lldp_neighbor **neighbors; + int i; + uint8_t type; + const void *data; + size_t length, expected_length; + uint16_t ttl; + + lldp_handler_calls = 0; + assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0); + + assert_se(write(test_fd[1], frame1, sizeof(frame1)) == sizeof(frame1)); + sd_event_run(e, 0); + assert_se(write(test_fd[1], frame2, sizeof(frame2)) == sizeof(frame2)); + sd_event_run(e, 0); + assert_se(write(test_fd[1], frame3, sizeof(frame3)) == sizeof(frame3)); + sd_event_run(e, 0); + assert_se(write(test_fd[1], frame4, sizeof(frame4)) == sizeof(frame4)); + sd_event_run(e, 0); + assert_se(write(test_fd[1], frame5, sizeof(frame5)) == sizeof(frame5)); + sd_event_run(e, 0); + assert_se(write(test_fd[1], frame6, sizeof(frame6)) == sizeof(frame6)); + sd_event_run(e, 0); + assert_se(lldp_handler_calls == 6); + + assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 6); + + for (i = 0; i < 6; i++) { + assert_se(sd_lldp_neighbor_get_chassis_id(neighbors[i], &type, &data, &length) == 0); + assert_se(type == SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT); + expected_length = strlen(expected[2 * i]); + assert_se(length == expected_length); + assert_se(memcmp(data, expected[2 * i], expected_length) == 0); + + assert_se(sd_lldp_neighbor_get_port_id(neighbors[i], &type, &data, &length) == 0); + assert_se(type == SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT); + expected_length = strlen(expected[2 * i + 1]); + assert_se(length == expected_length); + assert_se(memcmp(data, expected[2 * i + 1], expected_length) == 0); + + assert_se(sd_lldp_neighbor_get_ttl(neighbors[i], &ttl) == 0); + assert_se(ttl == 120); + } + + for (i = 0; i < 6; i++) + sd_lldp_neighbor_unref(neighbors[i]); + free(neighbors); + + assert_se(stop_lldp(lldp) == 0); +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + + test_setup_logging(LOG_DEBUG); + + /* LLDP reception tests */ + assert_se(sd_event_new(&e) == 0); + test_receive_basic_packet(e); + test_receive_incomplete_packet(e); + test_receive_oui_packet(e); + test_multiple_neighbors_sorted(e); + + return 0; +} diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c new file mode 100644 index 00000000..7c6c4663 --- /dev/null +++ b/src/libsystemd-network/test-ndisc-ra.c @@ -0,0 +1,370 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2017 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include + +#include "sd-radv.h" + +#include "alloc-util.h" +#include "hexdecoct.h" +#include "icmp6-util.h" +#include "socket-util.h" +#include "strv.h" +#include "tests.h" + +static struct ether_addr mac_addr = { + .ether_addr_octet = { 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53 } +}; + +static uint8_t advertisement[] = { + /* ICMPv6 Router Advertisement, no checksum */ + 0x86, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x00, 0xb4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Source Link Layer Address Option */ + 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, + /* Prefix Information Option */ + 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4, + 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Prefix Information Option */ + 0x03, 0x04, 0x40, 0xc0, 0x00, 0x27, 0x8d, 0x00, + 0x00, 0x09, 0x3a, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Prefix Information Option */ + 0x03, 0x04, 0x30, 0xc0, 0x00, 0x27, 0x8d, 0x00, + 0x00, 0x09, 0x3a, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* Recursive DNS Server Option */ + 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + /* DNS Search List Option */ + 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, + 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static sd_event_source *test_hangcheck; +static bool test_stopped; +static int test_fd[2]; +static sd_event_source *recv_router_advertisement; +static struct { + struct in6_addr address; + unsigned char prefixlen; + uint32_t valid; + uint32_t preferred; + bool successful; +} prefix[] = { + { { { { 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 64, + 500, 440, true }, + { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 64, + /* indicate default valid and preferred lifetimes for the test code */ + 0, 0, true }, + { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 58, + 0, 0, + /* indicate that this prefix already exists */ + false }, + { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 120, + 0, 0, + /* indicate that this prefix already exists */ + false }, + { { { { 0x20, 0x01, 0x0d, 0xb8, 0x0b, 0x16, 0xd0, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 12, + 0, 0, + /* indicate that this prefix already exists */ + false }, + { { { { 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 48, + 0, 0, true }, + { { { { 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x01, 0x0d, 0xad, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }, 60, + 0, 0, + /* indicate that this prefix already exists */ + false }, +}; + +static const struct in6_addr test_rdnss = { { { 0x20, 0x01, 0x0d, 0xb8, + 0xde, 0xad, 0xbe, 0xef, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 } } }; +static const char *test_dnssl[] = { "lab.intra", + NULL }; + +static int test_rs_hangcheck(sd_event_source *s, uint64_t usec, + void *userdata) { + assert_se(false); + + return 0; +} + +static void test_radv_prefix(void) { + sd_radv_prefix *p; + + printf("* %s\n", __FUNCTION__); + + assert_se(sd_radv_prefix_new(&p) >= 0); + + assert_se(sd_radv_prefix_set_onlink(NULL, true) < 0); + assert_se(sd_radv_prefix_set_onlink(p, true) >= 0); + assert_se(sd_radv_prefix_set_onlink(p, false) >= 0); + + assert_se(sd_radv_prefix_set_address_autoconfiguration(NULL, true) < 0); + assert_se(sd_radv_prefix_set_address_autoconfiguration(p, true) >= 0); + assert_se(sd_radv_prefix_set_address_autoconfiguration(p, false) >= 0); + + assert_se(sd_radv_prefix_set_valid_lifetime(NULL, true) < 0); + assert_se(sd_radv_prefix_set_valid_lifetime(p, ~0) >= 0); + assert_se(sd_radv_prefix_set_valid_lifetime(p, 42) >= 0); + assert_se(sd_radv_prefix_set_valid_lifetime(p, 0) >= 0); + + assert_se(sd_radv_prefix_set_preferred_lifetime(NULL, true) < 0); + assert_se(sd_radv_prefix_set_preferred_lifetime(p, ~0) >= 0); + assert_se(sd_radv_prefix_set_preferred_lifetime(p, 42) >= 0); + assert_se(sd_radv_prefix_set_preferred_lifetime(p, 0) >= 0); + + assert_se(sd_radv_prefix_set_prefix(NULL, NULL, 0) < 0); + assert_se(sd_radv_prefix_set_prefix(p, NULL, 0) < 0); + + assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 64) >= 0); + assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 0) < 0); + assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 1) < 0); + assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 2) < 0); + assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 3) >= 0); + assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 125) >= 0); + assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 128) >= 0); + assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 129) < 0); + assert_se(sd_radv_prefix_set_prefix(p, &prefix[0].address, 255) < 0); + + p = sd_radv_prefix_unref(p); + assert_se(!p); +} + +static void test_radv(void) { + sd_radv *ra; + + printf("* %s\n", __FUNCTION__); + + assert_se(sd_radv_new(&ra) >= 0); + assert_se(ra); + + assert_se(sd_radv_set_ifindex(NULL, 0) < 0); + assert_se(sd_radv_set_ifindex(ra, 0) >= 0); + assert_se(sd_radv_set_ifindex(ra, -1) >= 0); + assert_se(sd_radv_set_ifindex(ra, -2) < 0); + assert_se(sd_radv_set_ifindex(ra, 42) >= 0); + + assert_se(sd_radv_set_mac(NULL, NULL) < 0); + assert_se(sd_radv_set_mac(ra, NULL) >= 0); + assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0); + + assert_se(sd_radv_set_mtu(NULL, 0) < 0); + assert_se(sd_radv_set_mtu(ra, 0) < 0); + assert_se(sd_radv_set_mtu(ra, 1279) < 0); + assert_se(sd_radv_set_mtu(ra, 1280) >= 0); + assert_se(sd_radv_set_mtu(ra, ~0) >= 0); + + assert_se(sd_radv_set_hop_limit(NULL, 0) < 0); + assert_se(sd_radv_set_hop_limit(ra, 0) >= 0); + assert_se(sd_radv_set_hop_limit(ra, ~0) >= 0); + + assert_se(sd_radv_set_router_lifetime(NULL, 0) < 0); + assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0); + assert_se(sd_radv_set_router_lifetime(ra, ~0) >= 0); + + assert_se(sd_radv_set_preference(NULL, 0) < 0); + assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_LOW) >= 0); + assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_MEDIUM) >= 0); + assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0); + assert_se(sd_radv_set_preference(ra, ~0) < 0); + + assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_HIGH) >= 0); + assert_se(sd_radv_set_router_lifetime(ra, 42000) >= 0); + assert_se(sd_radv_set_router_lifetime(ra, 0) < 0); + assert_se(sd_radv_set_preference(ra, SD_NDISC_PREFERENCE_MEDIUM) >= 0); + assert_se(sd_radv_set_router_lifetime(ra, 0) >= 0); + + assert_se(sd_radv_set_managed_information(NULL, true) < 0); + assert_se(sd_radv_set_managed_information(ra, true) >= 0); + assert_se(sd_radv_set_managed_information(ra, false) >= 0); + + assert_se(sd_radv_set_other_information(NULL, true) < 0); + assert_se(sd_radv_set_other_information(ra, true) >= 0); + assert_se(sd_radv_set_other_information(ra, false) >= 0); + + assert_se(sd_radv_set_rdnss(NULL, 0, NULL, 0) < 0); + assert_se(sd_radv_set_rdnss(ra, 0, NULL, 0) >= 0); + assert_se(sd_radv_set_rdnss(ra, 0, NULL, 128) < 0); + assert_se(sd_radv_set_rdnss(ra, 600, &test_rdnss, 0) >= 0); + assert_se(sd_radv_set_rdnss(ra, 600, &test_rdnss, 1) >= 0); + assert_se(sd_radv_set_rdnss(ra, 0, &test_rdnss, 1) >= 0); + assert_se(sd_radv_set_rdnss(ra, 0, NULL, 0) >= 0); + + assert_se(sd_radv_set_dnssl(ra, 0, NULL) >= 0); + assert_se(sd_radv_set_dnssl(ra, 600, NULL) >= 0); + assert_se(sd_radv_set_dnssl(ra, 0, (char **)test_dnssl) >= 0); + assert_se(sd_radv_set_dnssl(ra, 600, (char **)test_dnssl) >= 0); + + ra = sd_radv_unref(ra); + assert_se(!ra); +} + +int icmp6_bind_router_solicitation(int index) { + return -ENOSYS; +} + +int icmp6_bind_router_advertisement(int index) { + assert_se(index == 42); + + return test_fd[1]; +} + +int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) { + + return 0; +} + +int icmp6_receive(int fd, void *iov_base, size_t iov_len, + struct in6_addr *dst, triple_timestamp *timestamp) { + assert_se(read (fd, iov_base, iov_len) == (ssize_t)iov_len); + + if (timestamp) + triple_timestamp_get(timestamp); + + return 0; +} + +static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + sd_radv *ra = userdata; + unsigned char buf[168]; + size_t i; + + assert_se(read(test_fd[0], &buf, sizeof(buf)) == sizeof(buf)); + + /* router lifetime must be zero when test is stopped */ + if (test_stopped) { + advertisement[6] = 0x00; + advertisement[7] = 0x00; + } + + printf ("Received Router Advertisement with lifetime %u\n", + (advertisement[6] << 8) + advertisement[7]); + + /* test only up to buf size, rest is not yet implemented */ + for (i = 0; i < sizeof(buf); i++) { + if (!(i % 8)) + printf("%3zd: ", i); + + printf("0x%02x", buf[i]); + + assert_se(buf[i] == advertisement[i]); + + if ((i + 1) % 8) + printf(", "); + else + printf("\n"); + } + + if (test_stopped) { + sd_event *e; + + e = sd_radv_get_event(ra); + sd_event_exit(e, 0); + + return 0; + } + + assert_se(sd_radv_stop(ra) >= 0); + test_stopped = true; + + return 0; +} + +static void test_ra(void) { + sd_event *e; + sd_radv *ra; + usec_t time_now = now(clock_boottime_or_monotonic()); + unsigned i; + + printf("* %s\n", __FUNCTION__); + + assert_se(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0); + + assert_se(sd_event_new(&e) >= 0); + + assert_se(sd_radv_new(&ra) >= 0); + assert_se(ra); + + assert_se(sd_radv_attach_event(ra, e, 0) >= 0); + + assert_se(sd_radv_set_ifindex(ra, 42) >= 0); + assert_se(sd_radv_set_mac(ra, &mac_addr) >= 0); + assert_se(sd_radv_set_router_lifetime(ra, 180) >= 0); + assert_se(sd_radv_set_hop_limit(ra, 64) >= 0); + assert_se(sd_radv_set_managed_information(ra, true) >= 0); + assert_se(sd_radv_set_other_information(ra, true) >= 0); + assert_se(sd_radv_set_rdnss(ra, 60, &test_rdnss, 1) >= 0); + assert_se(sd_radv_set_dnssl(ra, 60, (char **)test_dnssl) >= 0); + + for (i = 0; i < ELEMENTSOF(prefix); i++) { + sd_radv_prefix *p; + + printf("Test prefix %u\n", i); + assert_se(sd_radv_prefix_new(&p) >= 0); + + assert_se(sd_radv_prefix_set_prefix(p, &prefix[i].address, + prefix[i].prefixlen) >= 0); + if (prefix[i].valid) + assert_se(sd_radv_prefix_set_valid_lifetime(p, prefix[i].valid) >= 0); + if (prefix[i].preferred) + assert_se(sd_radv_prefix_set_preferred_lifetime(p, prefix[i].preferred) >= 0); + + assert_se((sd_radv_add_prefix(ra, p, false) >= 0) == prefix[i].successful); + assert_se(sd_radv_add_prefix(ra, p, false) < 0); + + p = sd_radv_prefix_unref(p); + assert_se(!p); + } + + assert_se(sd_event_add_io(e, &recv_router_advertisement, test_fd[0], + EPOLLIN, radv_recv, ra) >= 0); + + assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), + time_now + 2 *USEC_PER_SEC, 0, + test_rs_hangcheck, NULL) >= 0); + + assert_se(sd_radv_start(ra) >= 0); + + sd_event_loop(e); + + test_hangcheck = sd_event_source_unref(test_hangcheck); + + ra = sd_radv_unref(ra); + assert_se(!ra); + + close(test_fd[0]); + + sd_event_unref(e); +} + +int main(int argc, char *argv[]) { + + test_setup_logging(LOG_DEBUG); + + test_radv_prefix(); + test_radv(); + test_ra(); + + printf("* done\n"); + return 0; +} diff --git a/src/libsystemd-network/test-ndisc-rs.c b/src/libsystemd-network/test-ndisc-rs.c new file mode 100644 index 00000000..c8ee1ec3 --- /dev/null +++ b/src/libsystemd-network/test-ndisc-rs.c @@ -0,0 +1,418 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include + +#include "sd-ndisc.h" + +#include "alloc-util.h" +#include "hexdecoct.h" +#include "icmp6-util.h" +#include "socket-util.h" +#include "strv.h" +#include "ndisc-internal.h" +#include "tests.h" + +static struct ether_addr mac_addr = { + .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'} +}; + +static bool verbose = false; +static sd_event_source *test_hangcheck; +static int test_fd[2]; +static sd_ndisc *test_timeout_nd; + +typedef int (*send_ra_t)(uint8_t flags); +static send_ra_t send_ra_function; + +static void router_dump(sd_ndisc_router *rt) { + struct in6_addr addr; + char buf[FORMAT_TIMESTAMP_MAX]; + uint8_t hop_limit; + uint64_t t, flags; + uint32_t mtu; + uint16_t lifetime; + unsigned preference; + int r; + + assert_se(rt); + + log_info("--"); + assert_se(sd_ndisc_router_get_address(rt, &addr) == -ENODATA); + + assert_se(sd_ndisc_router_get_timestamp(rt, CLOCK_REALTIME, &t) >= 0); + log_info("Timestamp: %s", format_timestamp(buf, sizeof(buf), t)); + + assert_se(sd_ndisc_router_get_timestamp(rt, CLOCK_MONOTONIC, &t) >= 0); + log_info("Monotonic: %" PRIu64, t); + + if (sd_ndisc_router_get_hop_limit(rt, &hop_limit) < 0) + log_info("No hop limit set"); + else + log_info("Hop limit: %u", hop_limit); + + assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0); + log_info("Flags: <%s|%s>", + flags & ND_RA_FLAG_OTHER ? "OTHER" : "", + flags & ND_RA_FLAG_MANAGED ? "MANAGED" : ""); + + assert_se(sd_ndisc_router_get_preference(rt, &preference) >= 0); + log_info("Preference: %s", + preference == SD_NDISC_PREFERENCE_LOW ? "low" : + preference == SD_NDISC_PREFERENCE_HIGH ? "high" : "medium"); + + assert_se(sd_ndisc_router_get_lifetime(rt, &lifetime) >= 0); + log_info("Lifetime: %" PRIu16, lifetime); + + if (sd_ndisc_router_get_mtu(rt, &mtu) < 0) + log_info("No MTU set"); + else + log_info("MTU: %" PRIu32, mtu); + + r = sd_ndisc_router_option_rewind(rt); + for (;;) { + uint8_t type; + + assert_se(r >= 0); + + if (r == 0) + break; + + assert_se(sd_ndisc_router_option_get_type(rt, &type) >= 0); + + log_info(">> Option %u", type); + + switch (type) { + + case SD_NDISC_OPTION_SOURCE_LL_ADDRESS: + case SD_NDISC_OPTION_TARGET_LL_ADDRESS: { + _cleanup_free_ char *c = NULL; + const void *p; + size_t n; + + assert_se(sd_ndisc_router_option_get_raw(rt, &p, &n) >= 0); + assert_se(n > 2); + assert_se(c = hexmem((uint8_t*) p + 2, n - 2)); + + log_info("Address: %s", c); + break; + } + + case SD_NDISC_OPTION_PREFIX_INFORMATION: { + uint32_t lifetime_valid, lifetime_preferred; + unsigned prefix_len; + uint8_t pfl; + struct in6_addr a; + char buff[INET6_ADDRSTRLEN]; + + assert_se(sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid) >= 0); + log_info("Valid Lifetime: %" PRIu32, lifetime_valid); + + assert_se(sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred) >= 0); + log_info("Preferred Lifetime: %" PRIu32, lifetime_preferred); + + assert_se(sd_ndisc_router_prefix_get_flags(rt, &pfl) >= 0); + log_info("Flags: <%s|%s>", + pfl & ND_OPT_PI_FLAG_ONLINK ? "ONLINK" : "", + pfl & ND_OPT_PI_FLAG_AUTO ? "AUTO" : ""); + + assert_se(sd_ndisc_router_prefix_get_prefixlen(rt, &prefix_len) >= 0); + log_info("Prefix Length: %u", prefix_len); + + assert_se(sd_ndisc_router_prefix_get_address(rt, &a) >= 0); + log_info("Prefix: %s", inet_ntop(AF_INET6, &a, buff, sizeof(buff))); + + break; + } + + case SD_NDISC_OPTION_RDNSS: { + const struct in6_addr *a; + uint32_t lt; + int n, i; + + n = sd_ndisc_router_rdnss_get_addresses(rt, &a); + assert_se(n > 0); + + for (i = 0; i < n; i++) { + char buff[INET6_ADDRSTRLEN]; + log_info("DNS: %s", inet_ntop(AF_INET6, a + i, buff, sizeof(buff))); + } + + assert_se(sd_ndisc_router_rdnss_get_lifetime(rt, <) >= 0); + log_info("Lifetime: %" PRIu32, lt); + break; + } + + case SD_NDISC_OPTION_DNSSL: { + _cleanup_strv_free_ char **l = NULL; + uint32_t lt; + int n, i; + + n = sd_ndisc_router_dnssl_get_domains(rt, &l); + assert_se(n > 0); + + for (i = 0; i < n; i++) + log_info("Domain: %s", l[i]); + + assert_se(sd_ndisc_router_dnssl_get_lifetime(rt, <) >= 0); + log_info("Lifetime: %" PRIu32, lt); + break; + }} + + r = sd_ndisc_router_option_next(rt); + } +} + +static int test_rs_hangcheck(sd_event_source *s, uint64_t usec, + void *userdata) { + assert_se(false); + + return 0; +} + +int icmp6_bind_router_solicitation(int index) { + assert_se(index == 42); + + if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0) + return -errno; + + return test_fd[0]; +} + +int icmp6_bind_router_advertisement(int index) { + + return -ENOSYS; +} + +int icmp6_receive(int fd, void *iov_base, size_t iov_len, + struct in6_addr *dst, triple_timestamp *timestamp) { + assert_se(read (fd, iov_base, iov_len) == (ssize_t)iov_len); + + if (timestamp) + triple_timestamp_get(timestamp); + + return 0; +} + +static int send_ra(uint8_t flags) { + uint8_t advertisement[] = { + 0x86, 0x00, 0xde, 0x83, 0x40, 0xc0, 0x00, 0xb4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x01, 0xf4, + 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, + 0x72, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, + }; + + advertisement[5] = flags; + + assert_se(write(test_fd[1], advertisement, sizeof(advertisement)) == + sizeof(advertisement)); + + if (verbose) + printf(" sent RA with flag 0x%02x\n", flags); + + return 0; +} + +int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) { + if (!send_ra_function) + return 0; + + return send_ra_function(0); +} + +static void test_callback(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) { + sd_event *e = userdata; + static unsigned idx = 0; + uint64_t flags_array[] = { + 0, + 0, + 0, + ND_RA_FLAG_OTHER, + ND_RA_FLAG_MANAGED + }; + uint64_t flags; + uint32_t mtu; + + assert_se(nd); + + if (event != SD_NDISC_EVENT_ROUTER) + return; + + router_dump(rt); + + assert_se(sd_ndisc_router_get_flags(rt, &flags) >= 0); + assert_se(flags == flags_array[idx]); + idx++; + + if (verbose) + printf(" got event 0x%02" PRIx64 "\n", flags); + + if (idx < ELEMENTSOF(flags_array)) { + send_ra(flags_array[idx]); + return; + } + + assert_se(sd_ndisc_get_mtu(nd, &mtu) == -ENODATA); + + sd_event_exit(e, 0); +} + +static void test_rs(void) { + sd_event *e; + sd_ndisc *nd; + usec_t time_now = now(clock_boottime_or_monotonic()); + + if (verbose) + printf("* %s\n", __FUNCTION__); + + send_ra_function = send_ra; + + assert_se(sd_event_new(&e) >= 0); + + assert_se(sd_ndisc_new(&nd) >= 0); + assert_se(nd); + + assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0); + + assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0); + assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); + assert_se(sd_ndisc_set_callback(nd, test_callback, e) >= 0); + + assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), + time_now + 2 *USEC_PER_SEC, 0, + test_rs_hangcheck, NULL) >= 0); + + assert_se(sd_ndisc_stop(nd) >= 0); + assert_se(sd_ndisc_start(nd) >= 0); + assert_se(sd_ndisc_stop(nd) >= 0); + + assert_se(sd_ndisc_start(nd) >= 0); + + sd_event_loop(e); + + test_hangcheck = sd_event_source_unref(test_hangcheck); + + nd = sd_ndisc_unref(nd); + assert_se(!nd); + + close(test_fd[1]); + + sd_event_unref(e); +} + +static int test_timeout_value(uint8_t flags) { + static int count = 0; + static usec_t last = 0; + sd_ndisc *nd = test_timeout_nd; + usec_t min, max; + char time_string_min[FORMAT_TIMESPAN_MAX]; + char time_string_nd[FORMAT_TIMESPAN_MAX]; + char time_string_max[FORMAT_TIMESPAN_MAX]; + + assert_se(nd); + assert_se(nd->event); + + if (++count >= 20) + sd_event_exit(nd->event, 0); + + if (last == 0) { + /* initial RT = IRT + RAND*IRT */ + min = NDISC_ROUTER_SOLICITATION_INTERVAL - + NDISC_ROUTER_SOLICITATION_INTERVAL / 10; + max = NDISC_ROUTER_SOLICITATION_INTERVAL + + NDISC_ROUTER_SOLICITATION_INTERVAL / 10; + } else { + /* next RT = 2*RTprev + RAND*RTprev */ + min = 2 * last - last / 10; + max = 2 * last + last / 10; + } + + /* final RT > MRT */ + if (last * 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL) { + min = NDISC_MAX_ROUTER_SOLICITATION_INTERVAL - + NDISC_MAX_ROUTER_SOLICITATION_INTERVAL / 10; + max = NDISC_MAX_ROUTER_SOLICITATION_INTERVAL + + NDISC_MAX_ROUTER_SOLICITATION_INTERVAL / 10; + } + + format_timespan(time_string_min, FORMAT_TIMESPAN_MAX, + min, USEC_PER_MSEC); + format_timespan(time_string_nd, FORMAT_TIMESPAN_MAX, + nd->retransmit_time, USEC_PER_MSEC); + format_timespan(time_string_max, FORMAT_TIMESPAN_MAX, + max, USEC_PER_MSEC); + + log_info("backoff timeout interval %2d %s%s <= %s <= %s", + count, + (last * 2 > NDISC_MAX_ROUTER_SOLICITATION_INTERVAL)? "(max) ": "", + time_string_min, time_string_nd, time_string_max); + + assert_se(min <= nd->retransmit_time); + assert_se(max >= nd->retransmit_time); + + last = nd->retransmit_time; + + assert_se(sd_event_source_set_time(nd->timeout_event_source, 0) >= 0); + + return 0; +} + +static void test_timeout(void) { + sd_event *e; + sd_ndisc *nd; + usec_t time_now = now(clock_boottime_or_monotonic()); + + if (verbose) + printf("* %s\n", __FUNCTION__); + + send_ra_function = test_timeout_value; + + assert_se(sd_event_new(&e) >= 0); + + assert_se(sd_ndisc_new(&nd) >= 0); + assert_se(nd); + + test_timeout_nd = nd; + + assert_se(sd_ndisc_attach_event(nd, e, 0) >= 0); + + assert_se(sd_ndisc_set_ifindex(nd, 42) >= 0); + assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0); + + assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(), + time_now + 2U * USEC_PER_SEC, 0, + test_rs_hangcheck, NULL) >= 0); + + assert_se(sd_ndisc_start(nd) >= 0); + + sd_event_loop(e); + + test_hangcheck = sd_event_source_unref(test_hangcheck); + + nd = sd_ndisc_unref(nd); + + sd_event_unref(e); +} + +int main(int argc, char *argv[]) { + + test_setup_logging(LOG_DEBUG); + + test_rs(); + test_timeout(); + + return 0; +} diff --git a/src/libsystemd-network/test-sd-dhcp-lease.c b/src/libsystemd-network/test-sd-dhcp-lease.c new file mode 100644 index 00000000..0f881809 --- /dev/null +++ b/src/libsystemd-network/test-sd-dhcp-lease.c @@ -0,0 +1,90 @@ +#include + +#include "dhcp-lease-internal.h" +#include "macro.h" +#include "string-util.h" +#include "strv.h" + +/* According to RFC1035 section 4.1.4, a domain name in a message can be either: + * - a sequence of labels ending in a zero octet + * - a pointer + * - a sequence of labels ending with a pointer + */ +static void test_dhcp_lease_parse_search_domains_basic(void) { + int r; + _cleanup_strv_free_ char **domains = NULL; + static const uint8_t optionbuf[] = { + 0x03, 'F', 'O', 'O', 0x03, 'B', 'A', 'R', 0x00, + 0x04, 'A', 'B', 'C', 'D', 0x03, 'E', 'F', 'G', 0x00, + }; + + r = dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf), &domains); + assert_se(r == 2); + assert_se(streq(domains[0], "FOO.BAR")); + assert_se(streq(domains[1], "ABCD.EFG")); +} + +static void test_dhcp_lease_parse_search_domains_ptr(void) { + int r; + _cleanup_strv_free_ char **domains = NULL; + static const uint8_t optionbuf[] = { + 0x03, 'F', 'O', 'O', 0x00, 0xC0, 0x00, + }; + + r = dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf), &domains); + assert_se(r == 2); + assert_se(streq(domains[0], "FOO")); + assert_se(streq(domains[1], "FOO")); +} + +static void test_dhcp_lease_parse_search_domains_labels_and_ptr(void) { + int r; + _cleanup_strv_free_ char **domains = NULL; + static const uint8_t optionbuf[] = { + 0x03, 'F', 'O', 'O', 0x03, 'B', 'A', 'R', 0x00, + 0x03, 'A', 'B', 'C', 0xC0, 0x04, + }; + + r = dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf), &domains); + assert_se(r == 2); + assert_se(streq(domains[0], "FOO.BAR")); + assert_se(streq(domains[1], "ABC.BAR")); +} + +/* Tests for exceptions. */ + +static void test_dhcp_lease_parse_search_domains_no_data(void) { + _cleanup_strv_free_ char **domains = NULL; + static const uint8_t optionbuf[3] = {0, 0, 0}; + + assert_se(dhcp_lease_parse_search_domains(NULL, 0, &domains) == -ENODATA); + assert_se(dhcp_lease_parse_search_domains(optionbuf, 0, &domains) == -ENODATA); +} + +static void test_dhcp_lease_parse_search_domains_loops(void) { + _cleanup_strv_free_ char **domains = NULL; + static const uint8_t optionbuf[] = { + 0x03, 'F', 'O', 'O', 0x00, 0x03, 'B', 'A', 'R', 0xC0, 0x06, + }; + + assert_se(dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf), &domains) == -EBADMSG); +} + +static void test_dhcp_lease_parse_search_domains_wrong_len(void) { + _cleanup_strv_free_ char **domains = NULL; + static const uint8_t optionbuf[] = { + 0x03, 'F', 'O', 'O', 0x03, 'B', 'A', 'R', 0x00, + 0x04, 'A', 'B', 'C', 'D', 0x03, 'E', 'F', 'G', 0x00, + }; + + assert_se(dhcp_lease_parse_search_domains(optionbuf, sizeof(optionbuf) - 5, &domains) == -EBADMSG); +} + +int main(int argc, char *argv[]) { + test_dhcp_lease_parse_search_domains_basic(); + test_dhcp_lease_parse_search_domains_ptr(); + test_dhcp_lease_parse_search_domains_labels_and_ptr(); + test_dhcp_lease_parse_search_domains_no_data(); + test_dhcp_lease_parse_search_domains_loops(); + test_dhcp_lease_parse_search_domains_wrong_len(); +} diff --git a/src/libsystemd/disable-mempool.c b/src/libsystemd/disable-mempool.c new file mode 100644 index 00000000..034bd24d --- /dev/null +++ b/src/libsystemd/disable-mempool.c @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "mempool.h" + +const bool mempool_use_allowed = false; diff --git a/src/libsystemd/libsystemd.pc.in b/src/libsystemd/libsystemd.pc.in new file mode 100644 index 00000000..a010dea2 --- /dev/null +++ b/src/libsystemd/libsystemd.pc.in @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@rootlibdir@ +includedir=@includedir@ + +Name: systemd +Description: systemd Library +URL: @PROJECT_URL@ +Version: @PROJECT_VERSION@ +Libs: -L${libdir} -lsystemd +Cflags: -I${includedir} diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym new file mode 100644 index 00000000..5ec42e0f --- /dev/null +++ b/src/libsystemd/libsystemd.sym @@ -0,0 +1,684 @@ +/*** + SPDX-License-Identifier: LGPL-2.1+ + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. +***/ + +LIBSYSTEMD_209 { +global: + /* sd-journal */ + sd_journal_print; + sd_journal_printv; + sd_journal_send; + sd_journal_sendv; + sd_journal_stream_fd; + sd_journal_open; + sd_journal_close; + sd_journal_previous; + sd_journal_next; + sd_journal_previous_skip; + sd_journal_next_skip; + sd_journal_get_realtime_usec; + sd_journal_get_monotonic_usec; + sd_journal_get_data; + sd_journal_enumerate_data; + sd_journal_restart_data; + sd_journal_add_match; + sd_journal_flush_matches; + sd_journal_seek_head; + sd_journal_seek_tail; + sd_journal_seek_monotonic_usec; + sd_journal_seek_realtime_usec; + sd_journal_seek_cursor; + sd_journal_get_cursor; + sd_journal_get_fd; + sd_journal_process; + sd_journal_print_with_location; + sd_journal_printv_with_location; + sd_journal_send_with_location; + sd_journal_sendv_with_location; + sd_journal_get_cutoff_realtime_usec; + sd_journal_get_cutoff_monotonic_usec; + sd_journal_wait; + sd_journal_open_directory; + sd_journal_add_disjunction; + sd_journal_perror; + sd_journal_perror_with_location; + sd_journal_get_usage; + sd_journal_test_cursor; + sd_journal_query_unique; + sd_journal_enumerate_unique; + sd_journal_restart_unique; + sd_journal_get_catalog; + sd_journal_get_catalog_for_message_id; + sd_journal_set_data_threshold; + sd_journal_get_data_threshold; + sd_journal_reliable_fd; + sd_journal_get_events; + sd_journal_get_timeout; + sd_journal_add_conjunction; + sd_journal_open_files; + sd_journal_open_container; + + /* sd-daemon */ + sd_booted; + sd_is_fifo; + sd_is_mq; + sd_is_socket; + sd_is_socket_inet; + sd_is_socket_unix; + sd_is_special; + sd_listen_fds; + sd_notify; + sd_notifyf; + sd_watchdog_enabled; + + /* sd-id128 */ + sd_id128_to_string; + sd_id128_from_string; + sd_id128_randomize; + sd_id128_get_machine; + sd_id128_get_boot; + + /* sd-login */ + sd_get_seats; + sd_get_sessions; + sd_get_uids; + sd_login_monitor_flush; + sd_login_monitor_get_fd; + sd_login_monitor_new; + sd_login_monitor_unref; + sd_pid_get_owner_uid; + sd_pid_get_session; + sd_seat_can_multi_session; + sd_seat_get_active; + sd_seat_get_sessions; + sd_session_get_seat; + sd_session_get_uid; + sd_session_is_active; + sd_uid_get_seats; + sd_uid_get_sessions; + sd_uid_get_state; + sd_uid_is_on_seat; + sd_pid_get_unit; + sd_session_get_service; + sd_session_get_type; + sd_session_get_class; + sd_session_get_display; + sd_session_get_state; + sd_seat_can_tty; + sd_seat_can_graphical; + sd_session_get_tty; + sd_login_monitor_get_events; + sd_login_monitor_get_timeout; + sd_pid_get_user_unit; + sd_pid_get_machine_name; + sd_get_machine_names; + sd_pid_get_slice; + sd_session_get_vt; + sd_session_is_remote; + sd_session_get_remote_user; + sd_session_get_remote_host; +local: + *; +}; + +LIBSYSTEMD_211 { +global: + sd_machine_get_class; + sd_peer_get_session; + sd_peer_get_owner_uid; + sd_peer_get_unit; + sd_peer_get_user_unit; + sd_peer_get_machine_name; + sd_peer_get_slice; +} LIBSYSTEMD_209; + +LIBSYSTEMD_213 { +global: + sd_uid_get_display; +} LIBSYSTEMD_211; + +LIBSYSTEMD_214 { +global: + sd_pid_notify; + sd_pid_notifyf; +} LIBSYSTEMD_213; + +LIBSYSTEMD_216 { +global: + sd_machine_get_ifindices; +} LIBSYSTEMD_214; + +LIBSYSTEMD_217 { +global: + sd_session_get_desktop; +} LIBSYSTEMD_216; + +LIBSYSTEMD_219 { +global: + sd_pid_notify_with_fds; +} LIBSYSTEMD_217; + +LIBSYSTEMD_220 { +global: + sd_pid_get_user_slice; + sd_peer_get_user_slice; +} LIBSYSTEMD_219; + +LIBSYSTEMD_221 { +global: + /* sd-bus */ + sd_bus_default; + sd_bus_default_user; + sd_bus_default_system; + sd_bus_open; + sd_bus_open_user; + sd_bus_open_system; + sd_bus_open_system_remote; + sd_bus_open_system_machine; + sd_bus_new; + sd_bus_set_address; + sd_bus_set_fd; + sd_bus_set_exec; + sd_bus_get_address; + sd_bus_set_bus_client; + sd_bus_is_bus_client; + sd_bus_set_server; + sd_bus_is_server; + sd_bus_set_anonymous; + sd_bus_is_anonymous; + sd_bus_set_trusted; + sd_bus_is_trusted; + sd_bus_set_monitor; + sd_bus_is_monitor; + sd_bus_set_description; + sd_bus_get_description; + sd_bus_negotiate_creds; + sd_bus_negotiate_timestamp; + sd_bus_negotiate_fds; + sd_bus_can_send; + sd_bus_get_creds_mask; + sd_bus_set_allow_interactive_authorization; + sd_bus_get_allow_interactive_authorization; + sd_bus_start; + sd_bus_close; + sd_bus_try_close; + sd_bus_ref; + sd_bus_unref; + sd_bus_is_open; + sd_bus_get_bus_id; + sd_bus_get_scope; + sd_bus_get_tid; + sd_bus_get_owner_creds; + sd_bus_send; + sd_bus_send_to; + sd_bus_call; + sd_bus_call_async; + sd_bus_get_fd; + sd_bus_get_events; + sd_bus_get_timeout; + sd_bus_process; + sd_bus_process_priority; + sd_bus_wait; + sd_bus_flush; + sd_bus_get_current_slot; + sd_bus_get_current_message; + sd_bus_get_current_handler; + sd_bus_get_current_userdata; + sd_bus_attach_event; + sd_bus_detach_event; + sd_bus_get_event; + sd_bus_add_filter; + sd_bus_add_match; + sd_bus_add_object; + sd_bus_add_fallback; + sd_bus_add_object_vtable; + sd_bus_add_fallback_vtable; + sd_bus_add_node_enumerator; + sd_bus_add_object_manager; + sd_bus_slot_ref; + sd_bus_slot_unref; + sd_bus_slot_get_bus; + sd_bus_slot_get_userdata; + sd_bus_slot_set_userdata; + sd_bus_slot_get_description; + sd_bus_slot_set_description; + sd_bus_slot_get_current_message; + sd_bus_slot_get_current_handler; + sd_bus_slot_get_current_userdata; + sd_bus_message_new_signal; + sd_bus_message_new_method_call; + sd_bus_message_new_method_return; + sd_bus_message_new_method_error; + sd_bus_message_new_method_errorf; + sd_bus_message_new_method_errno; + sd_bus_message_new_method_errnof; + sd_bus_message_ref; + sd_bus_message_unref; + sd_bus_message_get_type; + sd_bus_message_get_cookie; + sd_bus_message_get_reply_cookie; + sd_bus_message_get_priority; + sd_bus_message_get_expect_reply; + sd_bus_message_get_auto_start; + sd_bus_message_get_allow_interactive_authorization; + sd_bus_message_get_signature; + sd_bus_message_get_path; + sd_bus_message_get_interface; + sd_bus_message_get_member; + sd_bus_message_get_destination; + sd_bus_message_get_sender; + sd_bus_message_get_error; + sd_bus_message_get_errno; + sd_bus_message_get_monotonic_usec; + sd_bus_message_get_realtime_usec; + sd_bus_message_get_seqnum; + sd_bus_message_get_bus; + sd_bus_message_get_creds; + sd_bus_message_is_signal; + sd_bus_message_is_method_call; + sd_bus_message_is_method_error; + sd_bus_message_is_empty; + sd_bus_message_has_signature; + sd_bus_message_set_expect_reply; + sd_bus_message_set_auto_start; + sd_bus_message_set_allow_interactive_authorization; + sd_bus_message_set_destination; + sd_bus_message_set_priority; + sd_bus_message_append; + sd_bus_message_append_basic; + sd_bus_message_append_array; + sd_bus_message_append_array_space; + sd_bus_message_append_array_iovec; + sd_bus_message_append_array_memfd; + sd_bus_message_append_string_space; + sd_bus_message_append_string_iovec; + sd_bus_message_append_string_memfd; + sd_bus_message_append_strv; + sd_bus_message_open_container; + sd_bus_message_close_container; + sd_bus_message_copy; + sd_bus_message_read; + sd_bus_message_read_basic; + sd_bus_message_read_array; + sd_bus_message_read_strv; + sd_bus_message_skip; + sd_bus_message_enter_container; + sd_bus_message_exit_container; + sd_bus_message_peek_type; + sd_bus_message_verify_type; + sd_bus_message_at_end; + sd_bus_message_rewind; + sd_bus_get_unique_name; + sd_bus_request_name; + sd_bus_release_name; + sd_bus_list_names; + sd_bus_get_name_creds; + sd_bus_get_name_machine_id; + sd_bus_call_method; + sd_bus_call_method_async; + sd_bus_get_property; + sd_bus_get_property_trivial; + sd_bus_get_property_string; + sd_bus_get_property_strv; + sd_bus_set_property; + sd_bus_reply_method_return; + sd_bus_reply_method_error; + sd_bus_reply_method_errorf; + sd_bus_reply_method_errno; + sd_bus_reply_method_errnof; + sd_bus_emit_signal; + sd_bus_emit_properties_changed_strv; + sd_bus_emit_properties_changed; + sd_bus_emit_interfaces_added_strv; + sd_bus_emit_interfaces_added; + sd_bus_emit_interfaces_removed_strv; + sd_bus_emit_interfaces_removed; + sd_bus_query_sender_creds; + sd_bus_query_sender_privilege; + sd_bus_creds_new_from_pid; + sd_bus_creds_ref; + sd_bus_creds_unref; + sd_bus_creds_get_mask; + sd_bus_creds_get_augmented_mask; + sd_bus_creds_get_pid; + sd_bus_creds_get_ppid; + sd_bus_creds_get_tid; + sd_bus_creds_get_uid; + sd_bus_creds_get_euid; + sd_bus_creds_get_suid; + sd_bus_creds_get_fsuid; + sd_bus_creds_get_gid; + sd_bus_creds_get_egid; + sd_bus_creds_get_sgid; + sd_bus_creds_get_fsgid; + sd_bus_creds_get_supplementary_gids; + sd_bus_creds_get_comm; + sd_bus_creds_get_tid_comm; + sd_bus_creds_get_exe; + sd_bus_creds_get_cmdline; + sd_bus_creds_get_cgroup; + sd_bus_creds_get_unit; + sd_bus_creds_get_slice; + sd_bus_creds_get_user_unit; + sd_bus_creds_get_user_slice; + sd_bus_creds_get_session; + sd_bus_creds_get_owner_uid; + sd_bus_creds_has_effective_cap; + sd_bus_creds_has_permitted_cap; + sd_bus_creds_has_inheritable_cap; + sd_bus_creds_has_bounding_cap; + sd_bus_creds_get_selinux_context; + sd_bus_creds_get_audit_session_id; + sd_bus_creds_get_audit_login_uid; + sd_bus_creds_get_tty; + sd_bus_creds_get_unique_name; + sd_bus_creds_get_well_known_names; + sd_bus_creds_get_description; + sd_bus_error_free; + sd_bus_error_set; + sd_bus_error_setf; + sd_bus_error_set_const; + sd_bus_error_set_errno; + sd_bus_error_set_errnof; + sd_bus_error_set_errnofv; + sd_bus_error_get_errno; + sd_bus_error_copy; + sd_bus_error_is_set; + sd_bus_error_has_name; + sd_bus_error_add_map; + sd_bus_path_encode; + sd_bus_path_decode; + sd_bus_track_new; + sd_bus_track_ref; + sd_bus_track_unref; + sd_bus_track_get_bus; + sd_bus_track_get_userdata; + sd_bus_track_set_userdata; + sd_bus_track_add_sender; + sd_bus_track_remove_sender; + sd_bus_track_add_name; + sd_bus_track_remove_name; + sd_bus_track_count; + sd_bus_track_contains; + sd_bus_track_first; + sd_bus_track_next; + + /* sd-event */ + sd_event_default; + sd_event_new; + sd_event_ref; + sd_event_unref; + sd_event_add_io; + sd_event_add_time; + sd_event_add_signal; + sd_event_add_child; + sd_event_add_defer; + sd_event_add_post; + sd_event_add_exit; + sd_event_prepare; + sd_event_wait; + sd_event_dispatch; + sd_event_run; + sd_event_loop; + sd_event_exit; + sd_event_now; + sd_event_get_fd; + sd_event_get_state; + sd_event_get_tid; + sd_event_get_exit_code; + sd_event_set_watchdog; + sd_event_get_watchdog; + sd_event_source_ref; + sd_event_source_unref; + sd_event_source_get_event; + sd_event_source_get_userdata; + sd_event_source_set_userdata; + sd_event_source_set_description; + sd_event_source_get_description; + sd_event_source_set_prepare; + sd_event_source_get_pending; + sd_event_source_get_priority; + sd_event_source_set_priority; + sd_event_source_get_enabled; + sd_event_source_set_enabled; + sd_event_source_get_io_fd; + sd_event_source_set_io_fd; + sd_event_source_get_io_events; + sd_event_source_set_io_events; + sd_event_source_get_io_revents; + sd_event_source_get_time; + sd_event_source_set_time; + sd_event_source_set_time_accuracy; + sd_event_source_get_time_accuracy; + sd_event_source_get_time_clock; + sd_event_source_get_signal; + sd_event_source_get_child_pid; +} LIBSYSTEMD_220; + +LIBSYSTEMD_222 { +global: + /* sd-bus */ + sd_bus_emit_object_added; + sd_bus_emit_object_removed; + sd_bus_flush_close_unref; +} LIBSYSTEMD_221; + +LIBSYSTEMD_226 { +global: + sd_pid_get_cgroup; + sd_peer_get_cgroup; +} LIBSYSTEMD_222; + +LIBSYSTEMD_227 { +global: + sd_bus_default_flush_close; + sd_bus_path_decode_many; + sd_bus_path_encode_many; + sd_listen_fds_with_names; +} LIBSYSTEMD_226; + +LIBSYSTEMD_229 { +global: + sd_journal_has_runtime_files; + sd_journal_has_persistent_files; + sd_journal_enumerate_fields; + sd_journal_restart_fields; +} LIBSYSTEMD_227; + +LIBSYSTEMD_230 { +global: + sd_journal_open_directory_fd; + sd_journal_open_files_fd; +} LIBSYSTEMD_229; + +LIBSYSTEMD_231 { +global: + sd_event_get_iteration; +} LIBSYSTEMD_230; + +LIBSYSTEMD_232 { +global: + sd_bus_track_set_recursive; + sd_bus_track_get_recursive; + sd_bus_track_count_name; + sd_bus_track_count_sender; + sd_bus_set_exit_on_disconnect; + sd_bus_get_exit_on_disconnect; + sd_id128_get_invocation; +} LIBSYSTEMD_231; + +LIBSYSTEMD_233 { +global: + sd_id128_get_machine_app_specific; + sd_is_socket_sockaddr; +} LIBSYSTEMD_232; + +LIBSYSTEMD_234 { +global: + sd_bus_message_appendv; +} LIBSYSTEMD_233; + +LIBSYSTEMD_236 { +global: + sd_bus_message_new; + sd_bus_message_seal; +} LIBSYSTEMD_234; + +LIBSYSTEMD_237 { +global: + sd_bus_set_watch_bind; + sd_bus_get_watch_bind; + sd_bus_request_name_async; + sd_bus_release_name_async; + sd_bus_add_match_async; + sd_bus_match_signal; + sd_bus_match_signal_async; + sd_bus_is_ready; + sd_bus_set_connected_signal; + sd_bus_get_connected_signal; + sd_bus_set_sender; + sd_bus_get_sender; + sd_bus_message_set_sender; + sd_event_source_get_io_fd_own; + sd_event_source_set_io_fd_own; +} LIBSYSTEMD_236; + +LIBSYSTEMD_238 { +global: + sd_bus_get_n_queued_read; + sd_bus_get_n_queued_write; +} LIBSYSTEMD_237; + +LIBSYSTEMD_239 { +global: + sd_bus_open_with_description; + sd_bus_open_user_with_description; + sd_bus_open_system_with_description; + sd_bus_slot_get_floating; + sd_bus_slot_set_floating; + sd_bus_slot_get_destroy_callback; + sd_bus_slot_set_destroy_callback; + sd_bus_track_get_destroy_callback; + sd_bus_track_set_destroy_callback; + sd_event_add_inotify; + sd_event_source_get_inotify_mask; + sd_event_source_set_destroy_callback; + sd_event_source_get_destroy_callback; +} LIBSYSTEMD_238; + +LIBSYSTEMD_240 { +global: + sd_bus_message_readv; + sd_bus_set_method_call_timeout; + sd_bus_get_method_call_timeout; + + sd_bus_error_move; + + sd_bus_set_close_on_exit; + sd_bus_get_close_on_exit; + + sd_device_ref; + sd_device_unref; + + sd_device_new_from_syspath; + sd_device_new_from_devnum; + sd_device_new_from_subsystem_sysname; + sd_device_new_from_device_id; + + sd_device_get_parent; + sd_device_get_parent_with_subsystem_devtype; + + sd_device_get_syspath; + sd_device_get_subsystem; + sd_device_get_devtype; + sd_device_get_devnum; + sd_device_get_ifindex; + sd_device_get_driver; + sd_device_get_devpath; + sd_device_get_devname; + sd_device_get_sysname; + sd_device_get_sysnum; + + sd_device_get_is_initialized; + sd_device_get_usec_since_initialized; + + sd_device_get_tag_first; + sd_device_get_tag_next; + sd_device_get_devlink_first; + sd_device_get_devlink_next; + sd_device_get_property_first; + sd_device_get_property_next; + sd_device_get_sysattr_first; + sd_device_get_sysattr_next; + + sd_device_has_tag; + sd_device_get_property_value; + sd_device_get_sysattr_value; + + sd_device_set_sysattr_value; + + sd_device_enumerator_new; + sd_device_enumerator_ref; + sd_device_enumerator_unref; + + sd_device_enumerator_get_device_first; + sd_device_enumerator_get_device_next; + sd_device_enumerator_get_subsystem_first; + sd_device_enumerator_get_subsystem_next; + + sd_device_enumerator_add_match_subsystem; + sd_device_enumerator_add_match_sysattr; + sd_device_enumerator_add_match_property; + sd_device_enumerator_add_match_sysname; + sd_device_enumerator_add_match_tag; + sd_device_enumerator_add_match_parent; + sd_device_enumerator_allow_uninitialized; + + sd_hwdb_ref; + sd_hwdb_unref; + + sd_hwdb_new; + + sd_hwdb_get; + + sd_hwdb_seek; + sd_hwdb_enumerate; + + sd_id128_get_boot_app_specific; + + sd_device_monitor_new; + sd_device_monitor_ref; + sd_device_monitor_unref; + + sd_device_monitor_set_receive_buffer_size; + sd_device_monitor_attach_event; + sd_device_monitor_detach_event; + sd_device_monitor_get_event; + sd_device_monitor_get_event_source; + sd_device_monitor_start; + sd_device_monitor_stop; + + sd_device_monitor_filter_add_match_subsystem_devtype; + sd_device_monitor_filter_add_match_tag; + sd_device_monitor_filter_update; + sd_device_monitor_filter_remove; + + sd_event_source_get_floating; + sd_event_source_set_floating; +} LIBSYSTEMD_239; + +LIBSYSTEMD_241 { +global: + sd_bus_close_unref; +} LIBSYSTEMD_240; + +LIBSYSTEMD_243 { +global: + sd_bus_object_vtable_format; + sd_event_source_disable_unref; +} LIBSYSTEMD_241; diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build new file mode 100644 index 00000000..aa1ed9b7 --- /dev/null +++ b/src/libsystemd/meson.build @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +id128_sources = files(''' + sd-id128/id128-util.c + sd-id128/id128-util.h + sd-id128/sd-id128.c +'''.split()) + +sd_daemon_sources = files('sd-daemon/sd-daemon.c') + +sd_event_sources = files(''' + sd-event/event-source.h + sd-event/event-util.c + sd-event/event-util.h + sd-event/sd-event.c +'''.split()) + +sd_login_sources = files('sd-login/sd-login.c') + +libsystemd_sources = files(''' + sd-bus/bus-common-errors.c + sd-bus/bus-common-errors.h + sd-bus/bus-container.c + sd-bus/bus-container.h + sd-bus/bus-control.c + sd-bus/bus-control.h + sd-bus/bus-convenience.c + sd-bus/bus-creds.c + sd-bus/bus-creds.h + sd-bus/bus-dump.c + sd-bus/bus-dump.h + sd-bus/bus-error.c + sd-bus/bus-error.h + sd-bus/bus-gvariant.c + sd-bus/bus-gvariant.h + sd-bus/bus-internal.c + sd-bus/bus-internal.h + sd-bus/bus-introspect.c + sd-bus/bus-introspect.h + sd-bus/bus-kernel.c + sd-bus/bus-kernel.h + sd-bus/bus-match.c + sd-bus/bus-match.h + sd-bus/bus-message.c + sd-bus/bus-message.h + sd-bus/bus-objects.c + sd-bus/bus-objects.h + sd-bus/bus-protocol.h + sd-bus/bus-signature.c + sd-bus/bus-signature.h + sd-bus/bus-slot.c + sd-bus/bus-slot.h + sd-bus/bus-socket.c + sd-bus/bus-socket.h + sd-bus/bus-track.c + sd-bus/bus-track.h + sd-bus/bus-type.c + sd-bus/bus-type.h + sd-bus/sd-bus.c + sd-device/device-enumerator-private.h + sd-device/device-enumerator.c + sd-device/device-internal.h + sd-device/device-monitor-private.h + sd-device/device-monitor.c + sd-device/device-private.c + sd-device/device-private.h + sd-device/device-util.h + sd-device/sd-device.c + sd-hwdb/hwdb-internal.h + sd-hwdb/hwdb-util.c + sd-hwdb/hwdb-util.h + sd-hwdb/sd-hwdb.c + sd-netlink/generic-netlink.c + sd-netlink/generic-netlink.h + sd-netlink/netlink-internal.h + sd-netlink/netlink-message.c + sd-netlink/netlink-slot.c + sd-netlink/netlink-slot.h + sd-netlink/netlink-socket.c + sd-netlink/netlink-types.c + sd-netlink/netlink-types.h + sd-netlink/netlink-util.c + sd-netlink/netlink-util.h + sd-netlink/rtnl-message.c + sd-netlink/sd-netlink.c + sd-network/network-util.c + sd-network/network-util.h + sd-network/sd-network.c + sd-path/sd-path.c + sd-resolve/resolve-private.h + sd-resolve/sd-resolve.c + sd-utf8/sd-utf8.c +'''.split()) + id128_sources + sd_daemon_sources + sd_event_sources + sd_login_sources + +disable_mempool_c = files('disable-mempool.c') + +libsystemd_c_args = ['-fvisibility=default'] + +libsystemd_static = static_library( + 'systemd_static', + libsystemd_sources, + install : false, + include_directories : includes, + link_with : libbasic, + dependencies : [threads, + librt], + c_args : libsystemd_c_args) + +libsystemd_sym = 'src/libsystemd/libsystemd.sym' + +configure_file( + input : 'libsystemd.pc.in', + output : 'libsystemd.pc', + configuration : substs, + install_dir : pkgconfiglibdir == 'no' ? '' : pkgconfiglibdir) diff --git a/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION b/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION new file mode 100644 index 00000000..973a0637 --- /dev/null +++ b/src/libsystemd/sd-bus/GVARIANT-SERIALIZATION @@ -0,0 +1,105 @@ +How we use GVariant for serializing D-Bus messages +-------------------------------------------------- + +We stay close to the original dbus1 framing as possible, but make +certain changes to adapt for GVariant. dbus1 has the following +framing: + + 1. A fixed header of "yyyyuu" + 2. Additional header fields of "a(yv)" + 3. Padding with NUL bytes to pad up to next 8byte boundary + 4. The body + +Note that the body is not padded at the end, the complete message +hence might have a non-aligned size. Reading multiple messages at once +will hence result in possibly unaligned messages in memory. + +The header consists of the following: + + y Endianness, 'l' or 'B' + y Message Type + y Flags + y Protocol version, '1' + u Length of the body, i.e. the length of part 4 above + u 32bit Serial number + + = 12 bytes + +This header is then followed by the fields array, whose first value is +a 32bit array size. + +When using GVariant we keep the basic structure in place, only +slightly alter the header, and define protocol version '2'. The new +header: + + y Endianness, 'l' or 'B' + y Message Type + y Flags + y Protocol version, '2' + u Reserved, must be 0 + t 64bit Cookie + + = 16 bytes + +This is then followed by the GVariant fields array ("a{tv}"), and +finally the actual body as variant (v). Putting this altogether a +packet on dbus2 hence qualifies as a fully compliant GVariant +structure of (yyyyuta{tv}v). + +For details on gvariant, see: + +https://people.gnome.org/~desrt/gvariant-serialisation.pdf + +Regarding the framing of dbus2, also see: + +https://wiki.gnome.org/Projects/GLib/GDBus/Version2 + +The first four bytes of the header are defined the same way for dbus1 +and dbus2. The first bytes contain the endianness field and the +protocol version, so that the remainder of the message can be safely +made sense of just by looking at the first 32bit. + +Note that the length of the body is no longer included in the header +on dbus2! In fact, the message size must be known in advance, from the +underlying transport in order to parse dbus2 messages, while it is +directly included in dbus1 message headers. This change of semantics +is an effect of GVariant's basic design. + +The serial number has been renamed cookie and has been extended from +32bit to 64bit. It is recommended to avoid the higher 32bit of the +cookie field though, to simplify compatibility with dbus1 peers. Note +that not only the cookie/serial field in the fixed header, but also +the reply_cookie/reply_serial additional header field has been +increased from 32bit to 64bit, too! + +The header field identifiers have been extended from 8bit to +64bit. This has been done to simplify things, and has no effect +on the serialization size, as due to alignment for each 8bit +header field identifier 56 bits of padding had to be added. + +Note that the header size changed, due to these changes. However, +consider that on dbus1 the beginning of the fields array contains the +32bit array size (since that is how arrays are encoded on dbus1), +thus, if one considers that size part of the header, instead of the +array, the size of the header on dbus1 and dbus2 stays identical, at +16 bytes. + + 0 4 8 12 16 + Common: | E | T | F | V | ... + + dbus1: | (as above) | Body Length | Serial | Fields Length | Fields array ... + + gvariant: | (as above) | Reserved | Cookie | Fields array ... + +And that's already it. + +Note: To simplify parsing, valid dbus2 messages must include the entire + fixed header and additional header fields in a single non-memfd + message part. Also, the signature string of the body variant all the + way to the end of the message must be in a single non-memfd part + too. The parts for this extended header and footer can be the same + one, and can also continue any amount of additional body bytes. + +Note: The GVariant "MAYBE" type is not supported, so that messages can + be fully converted forth and back between dbus1 and gvariant + representations. diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c new file mode 100644 index 00000000..9ab3286c --- /dev/null +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-bus.h" + +#include "bus-common-errors.h" +#include "bus-error.h" + +BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = { + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_UNIT, ENOENT), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_PID, ESRCH), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID, ENOENT), + SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_EXISTS, EEXIST), + SD_BUS_ERROR_MAP(BUS_ERROR_LOAD_FAILED, EIO), + SD_BUS_ERROR_MAP(BUS_ERROR_BAD_UNIT_SETTING, ENOEXEC), + SD_BUS_ERROR_MAP(BUS_ERROR_JOB_FAILED, EREMOTEIO), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_JOB, ENOENT), + SD_BUS_ERROR_MAP(BUS_ERROR_NOT_SUBSCRIBED, EINVAL), + SD_BUS_ERROR_MAP(BUS_ERROR_ALREADY_SUBSCRIBED, EINVAL), + SD_BUS_ERROR_MAP(BUS_ERROR_ONLY_BY_DEPENDENCY, EINVAL), + SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_JOBS_CONFLICTING, EDEADLK), + SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC, EDEADLK), + SD_BUS_ERROR_MAP(BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, EDEADLK), + SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_MASKED, ERFKILL), + SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_GENERATED, EADDRNOTAVAIL), + SD_BUS_ERROR_MAP(BUS_ERROR_UNIT_LINKED, ELOOP), + SD_BUS_ERROR_MAP(BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, EBADR), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_ISOLATION, EPERM), + SD_BUS_ERROR_MAP(BUS_ERROR_SHUTTING_DOWN, ECANCELED), + SD_BUS_ERROR_MAP(BUS_ERROR_SCOPE_NOT_RUNNING, EHOSTDOWN), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DYNAMIC_USER, ESRCH), + SD_BUS_ERROR_MAP(BUS_ERROR_NOT_REFERENCED, EUNATCH), + SD_BUS_ERROR_MAP(BUS_ERROR_DISK_FULL, ENOSPC), + + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_MACHINE, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_IMAGE, ENOENT), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_MACHINE_FOR_PID, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_MACHINE_EXISTS, EEXIST), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRIVATE_NETWORKING, ENOSYS), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER_MAPPING, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_GROUP_MAPPING, ENXIO), + + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PORTABLE_IMAGE, ENOENT), + SD_BUS_ERROR_MAP(BUS_ERROR_BAD_PORTABLE_IMAGE_TYPE, EMEDIUMTYPE), + + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SESSION, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SESSION_FOR_PID, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_USER, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_USER_FOR_PID, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SEAT, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_NOT_ON_SEAT, EINVAL), + SD_BUS_ERROR_MAP(BUS_ERROR_NOT_IN_CONTROL, EINVAL), + SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_IS_TAKEN, EINVAL), + SD_BUS_ERROR_MAP(BUS_ERROR_DEVICE_NOT_TAKEN, EINVAL), + SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS), + SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP), + SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY), + SD_BUS_ERROR_MAP(BUS_ERROR_NOT_YOUR_DEVICE, EPERM), + + SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_NTP_SUPPORT, EOPNOTSUPP), + + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_PROCESS, ESRCH), + + SD_BUS_ERROR_MAP(BUS_ERROR_NO_NAME_SERVERS, ESRCH), + SD_BUS_ERROR_MAP(BUS_ERROR_INVALID_REPLY, EINVAL), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_RR, ENOENT), + SD_BUS_ERROR_MAP(BUS_ERROR_CNAME_LOOP, EDEADLK), + SD_BUS_ERROR_MAP(BUS_ERROR_ABORTED, ECANCELED), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SERVICE, EUNATCH), + SD_BUS_ERROR_MAP(BUS_ERROR_DNSSEC_FAILED, EHOSTUNREACH), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_TRUST_ANCHOR, EHOSTUNREACH), + SD_BUS_ERROR_MAP(BUS_ERROR_RR_TYPE_UNSUPPORTED, EOPNOTSUPP), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_LINK, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY), + SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN), + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DNSSD_SERVICE, ENOENT), + SD_BUS_ERROR_MAP(BUS_ERROR_DNSSD_SERVICE_EXISTS, EEXIST), + + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "FORMERR", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "SERVFAIL", EHOSTDOWN), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXDOMAIN", ENXIO), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTIMP", ENOSYS), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "REFUSED", EACCES), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YXDOMAIN", EEXIST), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "YRRSET", EEXIST), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NXRRSET", ENOENT), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTAUTH", EACCES), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "NOTZONE", EREMOTE), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADVERS", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADKEY", EKEYREJECTED), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTIME", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADMODE", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADNAME", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADALG", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADTRUNC", EBADMSG), + SD_BUS_ERROR_MAP(_BUS_ERROR_DNS "BADCOOKIE", EBADR), + + SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO), + SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY), + + SD_BUS_ERROR_MAP(BUS_ERROR_NO_PRODUCT_UUID, EOPNOTSUPP), + + SD_BUS_ERROR_MAP(BUS_ERROR_UNMANAGED_INTERFACE, EOPNOTSUPP), + + SD_BUS_ERROR_MAP_END +}; diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h new file mode 100644 index 00000000..106bc159 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "bus-error.h" + +#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit" +#define BUS_ERROR_NO_UNIT_FOR_PID "org.freedesktop.systemd1.NoUnitForPID" +#define BUS_ERROR_NO_UNIT_FOR_INVOCATION_ID "org.freedesktop.systemd1.NoUnitForInvocationID" +#define BUS_ERROR_UNIT_EXISTS "org.freedesktop.systemd1.UnitExists" +#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed" +#define BUS_ERROR_BAD_UNIT_SETTING "org.freedesktop.systemd1.BadUnitSetting" +#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed" +#define BUS_ERROR_NO_SUCH_JOB "org.freedesktop.systemd1.NoSuchJob" +#define BUS_ERROR_NOT_SUBSCRIBED "org.freedesktop.systemd1.NotSubscribed" +#define BUS_ERROR_ALREADY_SUBSCRIBED "org.freedesktop.systemd1.AlreadySubscribed" +#define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency" +#define BUS_ERROR_TRANSACTION_JOBS_CONFLICTING "org.freedesktop.systemd1.TransactionJobsConflicting" +#define BUS_ERROR_TRANSACTION_ORDER_IS_CYCLIC "org.freedesktop.systemd1.TransactionOrderIsCyclic" +#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive" +#define BUS_ERROR_UNIT_MASKED "org.freedesktop.systemd1.UnitMasked" +#define BUS_ERROR_UNIT_GENERATED "org.freedesktop.systemd1.UnitGenerated" +#define BUS_ERROR_UNIT_LINKED "org.freedesktop.systemd1.UnitLinked" +#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable" +#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation" +#define BUS_ERROR_SHUTTING_DOWN "org.freedesktop.systemd1.ShuttingDown" +#define BUS_ERROR_SCOPE_NOT_RUNNING "org.freedesktop.systemd1.ScopeNotRunning" +#define BUS_ERROR_NO_SUCH_DYNAMIC_USER "org.freedesktop.systemd1.NoSuchDynamicUser" +#define BUS_ERROR_NOT_REFERENCED "org.freedesktop.systemd1.NotReferenced" +#define BUS_ERROR_DISK_FULL "org.freedesktop.systemd1.DiskFull" +#define BUS_ERROR_NOTHING_TO_CLEAN "org.freedesktop.systemd1.NothingToClean" +#define BUS_ERROR_UNIT_BUSY "org.freedesktop.systemd1.UnitBusy" + +#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine" +#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage" +#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID" +#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists" +#define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking" +#define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping" +#define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping" + +#define BUS_ERROR_NO_SUCH_PORTABLE_IMAGE "org.freedesktop.portable1.NoSuchImage" +#define BUS_ERROR_BAD_PORTABLE_IMAGE_TYPE "org.freedesktop.portable1.BadImageType" + +#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession" +#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID" +#define BUS_ERROR_NO_SUCH_USER "org.freedesktop.login1.NoSuchUser" +#define BUS_ERROR_NO_USER_FOR_PID "org.freedesktop.login1.NoUserForPID" +#define BUS_ERROR_NO_SUCH_SEAT "org.freedesktop.login1.NoSuchSeat" +#define BUS_ERROR_SESSION_NOT_ON_SEAT "org.freedesktop.login1.SessionNotOnSeat" +#define BUS_ERROR_NOT_IN_CONTROL "org.freedesktop.login1.NotInControl" +#define BUS_ERROR_DEVICE_IS_TAKEN "org.freedesktop.login1.DeviceIsTaken" +#define BUS_ERROR_DEVICE_NOT_TAKEN "org.freedesktop.login1.DeviceNotTaken" +#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress" +#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported" +#define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy" +#define BUS_ERROR_NOT_YOUR_DEVICE "org.freedesktop.login1.NotYourDevice" + +#define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled" +#define BUS_ERROR_NO_NTP_SUPPORT "org.freedesktop.timedate1.NoNTPSupport" + +#define BUS_ERROR_NO_SUCH_PROCESS "org.freedesktop.systemd1.NoSuchProcess" + +#define BUS_ERROR_NO_NAME_SERVERS "org.freedesktop.resolve1.NoNameServers" +#define BUS_ERROR_INVALID_REPLY "org.freedesktop.resolve1.InvalidReply" +#define BUS_ERROR_NO_SUCH_RR "org.freedesktop.resolve1.NoSuchRR" +#define BUS_ERROR_CNAME_LOOP "org.freedesktop.resolve1.CNameLoop" +#define BUS_ERROR_ABORTED "org.freedesktop.resolve1.Aborted" +#define BUS_ERROR_NO_SUCH_SERVICE "org.freedesktop.resolve1.NoSuchService" +#define BUS_ERROR_DNSSEC_FAILED "org.freedesktop.resolve1.DnssecFailed" +#define BUS_ERROR_NO_TRUST_ANCHOR "org.freedesktop.resolve1.NoTrustAnchor" +#define BUS_ERROR_RR_TYPE_UNSUPPORTED "org.freedesktop.resolve1.ResourceRecordTypeUnsupported" +#define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink" +#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy" +#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown" +#define BUS_ERROR_NO_SUCH_DNSSD_SERVICE "org.freedesktop.resolve1.NoSuchDnssdService" +#define BUS_ERROR_DNSSD_SERVICE_EXISTS "org.freedesktop.resolve1.DnssdServiceExists" +#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError." + +#define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer" +#define BUS_ERROR_TRANSFER_IN_PROGRESS "org.freedesktop.import1.TransferInProgress" + +#define BUS_ERROR_NO_PRODUCT_UUID "org.freedesktop.hostname1.NoProductUUID" + +#define BUS_ERROR_UNMANAGED_INTERFACE "org.freedesktop.network1.UnmanagedInterface" + +BUS_ERROR_MAP_ELF_USE(bus_common_errors); diff --git a/src/libsystemd/sd-bus/bus-container.c b/src/libsystemd/sd-bus/bus-container.c new file mode 100644 index 00000000..40b0e8a9 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-container.c @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "bus-container.h" +#include "bus-internal.h" +#include "bus-socket.h" +#include "fd-util.h" +#include "namespace-util.h" +#include "process-util.h" +#include "util.h" + +int bus_container_connect_socket(sd_bus *b) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1; + int r, error_buf = 0; + pid_t child; + ssize_t n; + + assert(b); + assert(b->input_fd < 0); + assert(b->output_fd < 0); + assert(b->nspid > 0 || b->machine); + + if (b->nspid <= 0) { + r = container_get_leader(b->machine, &b->nspid); + if (r < 0) + return r; + } + + r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd); + if (r < 0) + return r; + + b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (b->input_fd < 0) + return -errno; + + b->input_fd = fd_move_above_stdio(b->input_fd); + + b->output_fd = b->input_fd; + + bus_socket_setup(b); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) + return -errno; + + r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG, + pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child); + if (r < 0) + return r; + if (r == 0) { + pair[0] = safe_close(pair[0]); + + r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size); + if (r < 0) { + /* Try to send error up */ + error_buf = errno; + (void) write(pair[1], &error_buf, sizeof(error_buf)); + _exit(EXIT_FAILURE); + } + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + r = wait_for_terminate_and_check("(sd-buscntrns)", child, 0); + if (r < 0) + return r; + if (r != EXIT_SUCCESS) + return -EPROTO; + + n = read(pair[0], &error_buf, sizeof(error_buf)); + if (n < 0) + return -errno; + + if (n > 0) { + if (n != sizeof(error_buf)) + return -EIO; + + if (error_buf < 0) + return -EIO; + + if (error_buf == EINPROGRESS) + return 1; + + if (error_buf > 0) + return -error_buf; + } + + return bus_socket_start_auth(b); +} diff --git a/src/libsystemd/sd-bus/bus-container.h b/src/libsystemd/sd-bus/bus-container.h new file mode 100644 index 00000000..f6ef6880 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-container.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +int bus_container_connect_socket(sd_bus *b); diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c new file mode 100644 index 00000000..b7ca79bb --- /dev/null +++ b/src/libsystemd/sd-bus/bus-control.c @@ -0,0 +1,942 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if HAVE_VALGRIND_MEMCHECK_H +#include +#endif + +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-control.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-util.h" +#include "capability-util.h" +#include "process-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" + +_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) { + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(unique, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!bus->bus_client) + return -EINVAL; + + r = bus_ensure_running(bus); + if (r < 0) + return r; + + *unique = bus->unique_name; + return 0; +} + +static int validate_request_name_parameters( + sd_bus *bus, + const char *name, + uint64_t flags, + uint32_t *ret_param) { + + uint32_t param = 0; + + assert(bus); + assert(name); + assert(ret_param); + + assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL); + assert_return(service_name_is_valid(name), -EINVAL); + assert_return(name[0] != ':', -EINVAL); + + if (!bus->bus_client) + return -EINVAL; + + /* Don't allow requesting the special driver and local names */ + if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local")) + return -EINVAL; + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT) + param |= BUS_NAME_ALLOW_REPLACEMENT; + if (flags & SD_BUS_NAME_REPLACE_EXISTING) + param |= BUS_NAME_REPLACE_EXISTING; + if (!(flags & SD_BUS_NAME_QUEUE)) + param |= BUS_NAME_DO_NOT_QUEUE; + + *ret_param = param; + + return 0; +} + +_public_ int sd_bus_request_name( + sd_bus *bus, + const char *name, + uint64_t flags) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + uint32_t ret, param = 0; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(name, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + r = validate_request_name_parameters(bus, name, flags, ¶m); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "RequestName", + NULL, + &reply, + "su", + name, + param); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "u", &ret); + if (r < 0) + return r; + + switch (ret) { + + case BUS_NAME_ALREADY_OWNER: + return -EALREADY; + + case BUS_NAME_EXISTS: + return -EEXIST; + + case BUS_NAME_IN_QUEUE: + return 0; + + case BUS_NAME_PRIMARY_OWNER: + return 1; + } + + return -EIO; +} + +static int default_request_name_handler( + sd_bus_message *m, + void *userdata, + sd_bus_error *ret_error) { + + uint32_t ret; + int r; + + assert(m); + + if (sd_bus_message_is_method_error(m, NULL)) { + log_debug_errno(sd_bus_message_get_errno(m), + "Unable to request name, failing connection: %s", + sd_bus_message_get_error(m)->message); + + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + r = sd_bus_message_read(m, "u", &ret); + if (r < 0) + return r; + + switch (ret) { + + case BUS_NAME_ALREADY_OWNER: + log_debug("Already owner of requested service name, ignoring."); + return 1; + + case BUS_NAME_IN_QUEUE: + log_debug("In queue for requested service name."); + return 1; + + case BUS_NAME_PRIMARY_OWNER: + log_debug("Successfully acquired requested service name."); + return 1; + + case BUS_NAME_EXISTS: + log_debug("Requested service name already owned, failing connection."); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + log_debug("Unexpected response from RequestName(), failing connection."); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; +} + +_public_ int sd_bus_request_name_async( + sd_bus *bus, + sd_bus_slot **ret_slot, + const char *name, + uint64_t flags, + sd_bus_message_handler_t callback, + void *userdata) { + + uint32_t param = 0; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(name, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + r = validate_request_name_parameters(bus, name, flags, ¶m); + if (r < 0) + return r; + + return sd_bus_call_method_async( + bus, + ret_slot, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "RequestName", + callback ?: default_request_name_handler, + userdata, + "su", + name, + param); +} + +static int validate_release_name_parameters( + sd_bus *bus, + const char *name) { + + assert(bus); + assert(name); + + assert_return(service_name_is_valid(name), -EINVAL); + assert_return(name[0] != ':', -EINVAL); + + if (!bus->bus_client) + return -EINVAL; + + /* Don't allow releasing the special driver and local names */ + if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local")) + return -EINVAL; + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + return 0; +} + +_public_ int sd_bus_release_name( + sd_bus *bus, + const char *name) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + uint32_t ret; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(name, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + r = validate_release_name_parameters(bus, name); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "ReleaseName", + NULL, + &reply, + "s", + name); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "u", &ret); + if (r < 0) + return r; + + switch (ret) { + + case BUS_NAME_NON_EXISTENT: + return -ESRCH; + + case BUS_NAME_NOT_OWNER: + return -EADDRINUSE; + + case BUS_NAME_RELEASED: + return 0; + } + + return -EIO; +} + +static int default_release_name_handler( + sd_bus_message *m, + void *userdata, + sd_bus_error *ret_error) { + + uint32_t ret; + int r; + + assert(m); + + if (sd_bus_message_is_method_error(m, NULL)) { + log_debug_errno(sd_bus_message_get_errno(m), + "Unable to release name, failing connection: %s", + sd_bus_message_get_error(m)->message); + + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + r = sd_bus_message_read(m, "u", &ret); + if (r < 0) + return r; + + switch (ret) { + + case BUS_NAME_NON_EXISTENT: + log_debug("Name asked to release is not taken currently, ignoring."); + return 1; + + case BUS_NAME_NOT_OWNER: + log_debug("Name asked to release is owned by somebody else, ignoring."); + return 1; + + case BUS_NAME_RELEASED: + log_debug("Name successfully released."); + return 1; + } + + log_debug("Unexpected response from ReleaseName(), failing connection."); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; +} + +_public_ int sd_bus_release_name_async( + sd_bus *bus, + sd_bus_slot **ret_slot, + const char *name, + sd_bus_message_handler_t callback, + void *userdata) { + + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(name, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + r = validate_release_name_parameters(bus, name); + if (r < 0) + return r; + + return sd_bus_call_method_async( + bus, + ret_slot, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "ReleaseName", + callback ?: default_release_name_handler, + userdata, + "s", + name); +} + +_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_strv_free_ char **x = NULL, **y = NULL; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(acquired || activatable, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!bus->bus_client) + return -EINVAL; + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (acquired) { + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "ListNames", + NULL, + &reply, + NULL); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(reply, &x); + if (r < 0) + return r; + + reply = sd_bus_message_unref(reply); + } + + if (activatable) { + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "ListActivatableNames", + NULL, + &reply, + NULL); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(reply, &y); + if (r < 0) + return r; + + *activatable = TAKE_PTR(y); + } + + if (acquired) + *acquired = TAKE_PTR(x); + + return 0; +} + +_public_ int sd_bus_get_name_creds( + sd_bus *bus, + const char *name, + uint64_t mask, + sd_bus_creds **creds) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; + const char *unique; + pid_t pid = 0; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(name, -EINVAL); + assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); + assert_return(mask == 0 || creds, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + assert_return(service_name_is_valid(name), -EINVAL); + + if (!bus->bus_client) + return -EINVAL; + + /* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not + * going to match. */ + if (!bus->is_local) + mask &= ~SD_BUS_CREDS_AUGMENT; + + if (streq(name, "org.freedesktop.DBus.Local")) + return -EINVAL; + + if (streq(name, "org.freedesktop.DBus")) + return sd_bus_get_owner_creds(bus, mask, creds); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + /* If the name is unique anyway, we can use it directly */ + unique = name[0] == ':' ? name : NULL; + + /* Only query the owner if the caller wants to know it and the name is not unique anyway, or if the caller just + * wants to check whether a name exists */ + if ((FLAGS_SET(mask, SD_BUS_CREDS_UNIQUE_NAME) && !unique) || mask == 0) { + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetNameOwner", + NULL, + &reply_unique, + "s", + name); + if (r < 0) + return r; + + r = sd_bus_message_read(reply_unique, "s", &unique); + if (r < 0) + return r; + } + + if (mask != 0) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + bool need_pid, need_uid, need_selinux, need_separate_calls; + + c = bus_creds_new(); + if (!c) + return -ENOMEM; + + if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) { + c->unique_name = strdup(unique); + if (!c->unique_name) + return -ENOMEM; + + c->mask |= SD_BUS_CREDS_UNIQUE_NAME; + } + + need_pid = (mask & SD_BUS_CREDS_PID) || + ((mask & SD_BUS_CREDS_AUGMENT) && + (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| + SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID| + SD_BUS_CREDS_SUPPLEMENTARY_GIDS| + SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE| + SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID| + SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS| + SD_BUS_CREDS_SELINUX_CONTEXT| + SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))); + need_uid = mask & SD_BUS_CREDS_EUID; + need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT; + + if (need_pid + need_uid + need_selinux > 1) { + + /* If we need more than one of the credentials, then use GetConnectionCredentials() */ + + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetConnectionCredentials", + &error, + &reply, + "s", + unique ?: name); + + if (r < 0) { + + if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) + return r; + + /* If we got an unknown method error, fall back to the individual calls... */ + need_separate_calls = true; + sd_bus_error_free(&error); + + } else { + need_separate_calls = false; + + r = sd_bus_message_enter_container(reply, 'a', "{sv}"); + if (r < 0) + return r; + + for (;;) { + const char *m; + + r = sd_bus_message_enter_container(reply, 'e', "sv"); + if (r < 0) + return r; + if (r == 0) + break; + + r = sd_bus_message_read(reply, "s", &m); + if (r < 0) + return r; + + if (need_uid && streq(m, "UnixUserID")) { + uint32_t u; + + r = sd_bus_message_read(reply, "v", "u", &u); + if (r < 0) + return r; + + c->euid = u; + c->mask |= SD_BUS_CREDS_EUID; + + } else if (need_pid && streq(m, "ProcessID")) { + uint32_t p; + + r = sd_bus_message_read(reply, "v", "u", &p); + if (r < 0) + return r; + + pid = p; + if (mask & SD_BUS_CREDS_PID) { + c->pid = p; + c->mask |= SD_BUS_CREDS_PID; + } + + } else if (need_selinux && streq(m, "LinuxSecurityLabel")) { + const void *p = NULL; + size_t sz = 0; + + r = sd_bus_message_enter_container(reply, 'v', "ay"); + if (r < 0) + return r; + + r = sd_bus_message_read_array(reply, 'y', &p, &sz); + if (r < 0) + return r; + + free(c->label); + c->label = strndup(p, sz); + if (!c->label) + return -ENOMEM; + + c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return r; + } else { + r = sd_bus_message_skip(reply, "v"); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return r; + + if (need_pid && pid == 0) + return -EPROTO; + } + + } else /* When we only need a single field, then let's use separate calls */ + need_separate_calls = true; + + if (need_separate_calls) { + if (need_pid) { + uint32_t u; + + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetConnectionUnixProcessID", + NULL, + &reply, + "s", + unique ?: name); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "u", &u); + if (r < 0) + return r; + + pid = u; + if (mask & SD_BUS_CREDS_PID) { + c->pid = u; + c->mask |= SD_BUS_CREDS_PID; + } + + reply = sd_bus_message_unref(reply); + } + + if (need_uid) { + uint32_t u; + + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetConnectionUnixUser", + NULL, + &reply, + "s", + unique ?: name); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "u", &u); + if (r < 0) + return r; + + c->euid = u; + c->mask |= SD_BUS_CREDS_EUID; + + reply = sd_bus_message_unref(reply); + } + + if (need_selinux) { + const void *p = NULL; + size_t sz = 0; + + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetConnectionSELinuxSecurityContext", + &error, + &reply, + "s", + unique ?: name); + if (r < 0) { + if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown")) + return r; + + /* no data is fine */ + } else { + r = sd_bus_message_read_array(reply, 'y', &p, &sz); + if (r < 0) + return r; + + c->label = memdup_suffix0(p, sz); + if (!c->label) + return -ENOMEM; + + c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + } + } + } + + r = bus_creds_add_more(c, mask, pid, 0); + if (r < 0) + return r; + } + + if (creds) + *creds = TAKE_PTR(c); + + return 0; +} + +_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; + bool do_label, do_groups; + pid_t pid = 0; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); + assert_return(ret, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (!bus->is_local) + mask &= ~SD_BUS_CREDS_AUGMENT; + + do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT); + do_groups = bus->n_groups != (size_t) -1 && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS); + + /* Avoid allocating anything if we have no chance of returning useful data */ + if (!bus->ucred_valid && !do_label && !do_groups) + return -ENODATA; + + c = bus_creds_new(); + if (!c) + return -ENOMEM; + + if (bus->ucred_valid) { + if (pid_is_valid(bus->ucred.pid)) { + pid = c->pid = bus->ucred.pid; + c->mask |= SD_BUS_CREDS_PID & mask; + } + + if (uid_is_valid(bus->ucred.uid)) { + c->euid = bus->ucred.uid; + c->mask |= SD_BUS_CREDS_EUID & mask; + } + + if (gid_is_valid(bus->ucred.gid)) { + c->egid = bus->ucred.gid; + c->mask |= SD_BUS_CREDS_EGID & mask; + } + } + + if (do_label) { + c->label = strdup(bus->label); + if (!c->label) + return -ENOMEM; + + c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + } + + if (do_groups) { + c->supplementary_gids = newdup(gid_t, bus->groups, bus->n_groups); + if (!c->supplementary_gids) + return -ENOMEM; + + c->n_supplementary_gids = bus->n_groups; + + c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; + } + + r = bus_creds_add_more(c, mask, pid, 0); + if (r < 0) + return r; + + *ret = TAKE_PTR(c); + + return 0; +} + +#define append_eavesdrop(bus, m) \ + ((bus)->is_monitor \ + ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \ + : (m)) + +int bus_add_match_internal( + sd_bus *bus, + const char *match, + uint64_t *ret_counter) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *e; + int r; + + assert(bus); + + if (!bus->bus_client) + return -EINVAL; + + e = append_eavesdrop(bus, match); + + r = sd_bus_call_method( + bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "AddMatch", + NULL, + &reply, + "s", + e); + if (r < 0) + return r; + + /* If the caller asked for it, return the read counter of the reply */ + if (ret_counter) + *ret_counter = reply->read_counter; + + return r; +} + +int bus_add_match_internal_async( + sd_bus *bus, + sd_bus_slot **ret_slot, + const char *match, + sd_bus_message_handler_t callback, + void *userdata) { + + const char *e; + + assert(bus); + + if (!bus->bus_client) + return -EINVAL; + + e = append_eavesdrop(bus, match); + + return sd_bus_call_method_async( + bus, + ret_slot, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "AddMatch", + callback, + userdata, + "s", + e); +} + +int bus_remove_match_internal( + sd_bus *bus, + const char *match) { + + const char *e; + + assert(bus); + assert(match); + + if (!bus->bus_client) + return -EINVAL; + + e = append_eavesdrop(bus, match); + + /* Fire and forget */ + + return sd_bus_call_method_async( + bus, + NULL, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "RemoveMatch", + NULL, + NULL, + "s", + e); +} + +_public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; + const char *mid; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(name, -EINVAL); + assert_return(machine, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + assert_return(service_name_is_valid(name), -EINVAL); + + if (!bus->bus_client) + return -EINVAL; + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (streq_ptr(name, bus->unique_name)) + return sd_id128_get_machine(machine); + + r = sd_bus_message_new_method_call( + bus, + &m, + name, + "/", + "org.freedesktop.DBus.Peer", + "GetMachineId"); + if (r < 0) + return r; + + r = sd_bus_message_set_auto_start(m, false); + if (r < 0) + return r; + + r = sd_bus_call(bus, m, 0, NULL, &reply); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "s", &mid); + if (r < 0) + return r; + + return sd_id128_from_string(mid, machine); +} diff --git a/src/libsystemd/sd-bus/bus-control.h b/src/libsystemd/sd-bus/bus-control.h new file mode 100644 index 00000000..eb1ae75c --- /dev/null +++ b/src/libsystemd/sd-bus/bus-control.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +int bus_add_match_internal(sd_bus *bus, const char *match, uint64_t *ret_counter); +int bus_add_match_internal_async(sd_bus *bus, sd_bus_slot **ret, const char *match, sd_bus_message_handler_t callback, void *userdata); + +int bus_remove_match_internal(sd_bus *bus, const char *match); diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c new file mode 100644 index 00000000..4ec06164 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-convenience.c @@ -0,0 +1,672 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-signature.h" +#include "bus-type.h" +#include "bus-util.h" +#include "string-util.h" + +_public_ int sd_bus_emit_signal( + sd_bus *bus, + const char *path, + const char *interface, + const char *member, + const char *types, ...) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + r = sd_bus_message_new_signal(bus, &m, path, interface, member); + if (r < 0) + return r; + + if (!isempty(types)) { + va_list ap; + + va_start(ap, types); + r = sd_bus_message_appendv(m, types, ap); + va_end(ap); + if (r < 0) + return r; + } + + return sd_bus_send(bus, m, NULL); +} + +_public_ int sd_bus_call_method_async( + sd_bus *bus, + sd_bus_slot **slot, + const char *destination, + const char *path, + const char *interface, + const char *member, + sd_bus_message_handler_t callback, + void *userdata, + const char *types, ...) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member); + if (r < 0) + return r; + + if (!isempty(types)) { + va_list ap; + + va_start(ap, types); + r = sd_bus_message_appendv(m, types, ap); + va_end(ap); + if (r < 0) + return r; + } + + return sd_bus_call_async(bus, slot, m, callback, userdata, 0); +} + +_public_ int sd_bus_call_method( + sd_bus *bus, + const char *destination, + const char *path, + const char *interface, + const char *member, + sd_bus_error *error, + sd_bus_message **reply, + const char *types, ...) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); + + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } + + r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member); + if (r < 0) + goto fail; + + if (!isempty(types)) { + va_list ap; + + va_start(ap, types); + r = sd_bus_message_appendv(m, types, ap); + va_end(ap); + if (r < 0) + goto fail; + } + + return sd_bus_call(bus, m, 0, error, reply); + +fail: + return sd_bus_error_set_errno(error, r); +} + +_public_ int sd_bus_reply_method_return( + sd_bus_message *call, + const char *types, ...) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); + assert_return(call->bus, -EINVAL); + assert_return(!bus_pid_changed(call->bus), -ECHILD); + + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) + return 0; + + r = sd_bus_message_new_method_return(call, &m); + if (r < 0) + return r; + + if (!isempty(types)) { + va_list ap; + + va_start(ap, types); + r = sd_bus_message_appendv(m, types, ap); + va_end(ap); + if (r < 0) + return r; + } + + return sd_bus_send(call->bus, m, NULL); +} + +_public_ int sd_bus_reply_method_error( + sd_bus_message *call, + const sd_bus_error *e) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); + assert_return(sd_bus_error_is_set(e), -EINVAL); + assert_return(call->bus, -EINVAL); + assert_return(!bus_pid_changed(call->bus), -ECHILD); + + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) + return 0; + + r = sd_bus_message_new_method_error(call, &m, e); + if (r < 0) + return r; + + return sd_bus_send(call->bus, m, NULL); +} + +_public_ int sd_bus_reply_method_errorf( + sd_bus_message *call, + const char *name, + const char *format, + ...) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + va_list ap; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); + assert_return(call->bus, -EINVAL); + assert_return(!bus_pid_changed(call->bus), -ECHILD); + + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) + return 0; + + va_start(ap, format); + bus_error_setfv(&error, name, format, ap); + va_end(ap); + + return sd_bus_reply_method_error(call, &error); +} + +_public_ int sd_bus_reply_method_errno( + sd_bus_message *call, + int error, + const sd_bus_error *p) { + + _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); + assert_return(call->bus, -EINVAL); + assert_return(!bus_pid_changed(call->bus), -ECHILD); + + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) + return 0; + + if (sd_bus_error_is_set(p)) + return sd_bus_reply_method_error(call, p); + + sd_bus_error_set_errno(&berror, error); + + return sd_bus_reply_method_error(call, &berror); +} + +_public_ int sd_bus_reply_method_errnof( + sd_bus_message *call, + int error, + const char *format, + ...) { + + _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL; + va_list ap; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); + assert_return(call->bus, -EINVAL); + assert_return(!bus_pid_changed(call->bus), -ECHILD); + + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) + return 0; + + va_start(ap, format); + sd_bus_error_set_errnofv(&berror, error, format, ap); + va_end(ap); + + return sd_bus_reply_method_error(call, &berror); +} + +_public_ int sd_bus_get_property( + sd_bus *bus, + const char *destination, + const char *path, + const char *interface, + const char *member, + sd_bus_error *error, + sd_bus_message **reply, + const char *type) { + + sd_bus_message *rep = NULL; + int r; + + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); + bus_assert_return(member_name_is_valid(member), -EINVAL, error); + bus_assert_return(reply, -EINVAL, error); + bus_assert_return(signature_is_single(type, false), -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); + + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } + + r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(rep, 'v', type); + if (r < 0) { + sd_bus_message_unref(rep); + goto fail; + } + + *reply = rep; + return 0; + +fail: + return sd_bus_error_set_errno(error, r); +} + +_public_ int sd_bus_get_property_trivial( + sd_bus *bus, + const char *destination, + const char *path, + const char *interface, + const char *member, + sd_bus_error *error, + char type, void *ptr) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); + bus_assert_return(member_name_is_valid(member), -EINVAL, error); + bus_assert_return(bus_type_is_trivial(type), -EINVAL, error); + bus_assert_return(ptr, -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); + + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } + + r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type)); + if (r < 0) + goto fail; + + r = sd_bus_message_read_basic(reply, type, ptr); + if (r < 0) + goto fail; + + return 0; + +fail: + return sd_bus_error_set_errno(error, r); +} + +_public_ int sd_bus_get_property_string( + sd_bus *bus, + const char *destination, + const char *path, + const char *interface, + const char *member, + sd_bus_error *error, + char **ret) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *s; + char *n; + int r; + + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); + bus_assert_return(member_name_is_valid(member), -EINVAL, error); + bus_assert_return(ret, -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); + + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } + + r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(reply, 'v', "s"); + if (r < 0) + goto fail; + + r = sd_bus_message_read_basic(reply, 's', &s); + if (r < 0) + goto fail; + + n = strdup(s); + if (!n) { + r = -ENOMEM; + goto fail; + } + + *ret = n; + return 0; + +fail: + return sd_bus_error_set_errno(error, r); +} + +_public_ int sd_bus_get_property_strv( + sd_bus *bus, + const char *destination, + const char *path, + const char *interface, + const char *member, + sd_bus_error *error, + char ***ret) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); + bus_assert_return(member_name_is_valid(member), -EINVAL, error); + bus_assert_return(ret, -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); + + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } + + r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(reply, 'v', NULL); + if (r < 0) + goto fail; + + r = sd_bus_message_read_strv(reply, ret); + if (r < 0) + goto fail; + + return 0; + +fail: + return sd_bus_error_set_errno(error, r); +} + +_public_ int sd_bus_set_property( + sd_bus *bus, + const char *destination, + const char *path, + const char *interface, + const char *member, + sd_bus_error *error, + const char *type, ...) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + va_list ap; + int r; + + bus_assert_return(bus, -EINVAL, error); + bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error); + bus_assert_return(member_name_is_valid(member), -EINVAL, error); + bus_assert_return(signature_is_single(type, false), -EINVAL, error); + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); + + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } + + r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set"); + if (r < 0) + goto fail; + + r = sd_bus_message_append(m, "ss", strempty(interface), member); + if (r < 0) + goto fail; + + r = sd_bus_message_open_container(m, 'v', type); + if (r < 0) + goto fail; + + va_start(ap, type); + r = sd_bus_message_appendv(m, type, ap); + va_end(ap); + if (r < 0) + goto fail; + + r = sd_bus_message_close_container(m); + if (r < 0) + goto fail; + + return sd_bus_call(bus, m, 0, error, NULL); + +fail: + return sd_bus_error_set_errno(error, r); +} + +_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) { + sd_bus_creds *c; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->bus, -EINVAL); + assert_return(!bus_pid_changed(call->bus), -ECHILD); + + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + + c = sd_bus_message_get_creds(call); + + /* All data we need? */ + if (c && (mask & ~c->mask) == 0) { + *creds = sd_bus_creds_ref(c); + return 0; + } + + /* No data passed? Or not enough data passed to retrieve the missing bits? */ + if (!c || !(c->mask & SD_BUS_CREDS_PID)) { + /* We couldn't read anything from the call, let's try + * to get it from the sender or peer. */ + + if (call->sender) + /* There's a sender, but the creds are missing. */ + return sd_bus_get_name_creds(call->bus, call->sender, mask, creds); + else + /* There's no sender. For direct connections + * the credentials of the AF_UNIX peer matter, + * which may be queried via sd_bus_get_owner_creds(). */ + return sd_bus_get_owner_creds(call->bus, mask, creds); + } + + return bus_creds_extend_by_pid(c, mask, creds); +} + +_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + uid_t our_uid; + bool know_caps = false; + int r; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->bus, -EINVAL); + assert_return(!bus_pid_changed(call->bus), -ECHILD); + + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + + if (capability >= 0) { + + r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds); + if (r < 0) + return r; + + /* We cannot use augmented caps for authorization, + * since then data is acquired raceful from + * /proc. This can never actually happen, but let's + * better be safe than sorry, and do an extra check + * here. */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM); + + r = sd_bus_creds_has_effective_cap(creds, capability); + if (r > 0) + return 1; + if (r == 0) + know_caps = true; + } else { + r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + } + + /* Now, check the UID, but only if the capability check wasn't + * sufficient */ + our_uid = getuid(); + if (our_uid != 0 || !know_caps || capability < 0) { + uid_t sender_uid; + + /* We cannot use augmented uid/euid for authorization, + * since then data is acquired raceful from + * /proc. This can never actually happen, but let's + * better be safe than sorry, and do an extra check + * here. */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM); + + /* Try to use the EUID, if we have it. */ + r = sd_bus_creds_get_euid(creds, &sender_uid); + if (r < 0) + r = sd_bus_creds_get_uid(creds, &sender_uid); + + if (r >= 0) { + /* Sender has same UID as us, then let's grant access */ + if (sender_uid == our_uid) + return 1; + + /* Sender is root, we are not root. */ + if (our_uid != 0 && sender_uid == 0) + return 1; + } + } + + return 0; +} + +#define make_expression(sender, path, interface, member) \ + strjoina( \ + "type='signal'", \ + sender ? ",sender='" : "", \ + sender ?: "", \ + sender ? "'" : "", \ + path ? ",path='" : "", \ + path ?: "", \ + path ? "'" : "", \ + interface ? ",interface='" : "", \ + interface ?: "", \ + interface ? "'" : "", \ + member ? ",member='" : "", \ + member ?: "", \ + member ? "'" : "" \ + ) + +_public_ int sd_bus_match_signal( + sd_bus *bus, + sd_bus_slot **ret, + const char *sender, + const char *path, + const char *interface, + const char *member, + sd_bus_message_handler_t callback, + void *userdata) { + + const char *expression; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + assert_return(!sender || service_name_is_valid(sender), -EINVAL); + assert_return(!path || object_path_is_valid(path), -EINVAL); + assert_return(!interface || interface_name_is_valid(interface), -EINVAL); + assert_return(!member || member_name_is_valid(member), -EINVAL); + + expression = make_expression(sender, path, interface, member); + + return sd_bus_add_match(bus, ret, expression, callback, userdata); +} + +_public_ int sd_bus_match_signal_async( + sd_bus *bus, + sd_bus_slot **ret, + const char *sender, + const char *path, + const char *interface, + const char *member, + sd_bus_message_handler_t callback, + sd_bus_message_handler_t install_callback, + void *userdata) { + + const char *expression; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + assert_return(!sender || service_name_is_valid(sender), -EINVAL); + assert_return(!path || object_path_is_valid(path), -EINVAL); + assert_return(!interface || interface_name_is_valid(interface), -EINVAL); + assert_return(!member || member_name_is_valid(member), -EINVAL); + + expression = make_expression(sender, path, interface, member); + + return sd_bus_add_match_async(bus, ret, expression, callback, install_callback, userdata); +} diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c new file mode 100644 index 00000000..908b9e75 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -0,0 +1,1340 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "audit-util.h" +#include "bus-creds.h" +#include "bus-label.h" +#include "bus-message.h" +#include "bus-util.h" +#include "capability-util.h" +#include "cgroup-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "hexdecoct.h" +#include "parse-util.h" +#include "process-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "user-util.h" +#include "util.h" + +enum { + CAP_OFFSET_INHERITABLE = 0, + CAP_OFFSET_PERMITTED = 1, + CAP_OFFSET_EFFECTIVE = 2, + CAP_OFFSET_BOUNDING = 3 +}; + +void bus_creds_done(sd_bus_creds *c) { + assert(c); + + /* For internal bus cred structures that are allocated by + * something else */ + + free(c->session); + free(c->unit); + free(c->user_unit); + free(c->slice); + free(c->user_slice); + free(c->unescaped_description); + free(c->supplementary_gids); + free(c->tty); + + free(c->well_known_names); /* note that this is an strv, but + * we only free the array, not the + * strings the array points to. The + * full strv we only free if + * c->allocated is set, see + * below. */ + + strv_free(c->cmdline_array); +} + +_public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) { + + if (!c) + return NULL; + + if (c->allocated) { + assert(c->n_ref > 0); + c->n_ref++; + } else { + sd_bus_message *m; + + /* If this is an embedded creds structure, then + * forward ref counting to the message */ + m = container_of(c, sd_bus_message, creds); + sd_bus_message_ref(m); + } + + return c; +} + +_public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) { + + if (!c) + return NULL; + + if (c->allocated) { + assert(c->n_ref > 0); + c->n_ref--; + + if (c->n_ref == 0) { + free(c->comm); + free(c->tid_comm); + free(c->exe); + free(c->cmdline); + free(c->cgroup); + free(c->capability); + free(c->label); + free(c->unique_name); + free(c->cgroup_root); + free(c->description); + + c->supplementary_gids = mfree(c->supplementary_gids); + + c->well_known_names = strv_free(c->well_known_names); + + bus_creds_done(c); + + free(c); + } + } else { + sd_bus_message *m; + + m = container_of(c, sd_bus_message, creds); + sd_bus_message_unref(m); + } + + return NULL; +} + +_public_ uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c) { + assert_return(c, 0); + + return c->mask; +} + +_public_ uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c) { + assert_return(c, 0); + + return c->augmented; +} + +sd_bus_creds* bus_creds_new(void) { + sd_bus_creds *c; + + c = new0(sd_bus_creds, 1); + if (!c) + return NULL; + + c->allocated = true; + c->n_ref = 1; + return c; +} + +_public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t mask) { + sd_bus_creds *c; + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(mask <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); + assert_return(ret, -EINVAL); + + if (pid == 0) + pid = getpid_cached(); + + c = bus_creds_new(); + if (!c) + return -ENOMEM; + + r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0); + if (r < 0) { + sd_bus_creds_unref(c); + return r; + } + + /* Check if the process existed at all, in case we haven't + * figured that out already */ + if (!pid_is_alive(pid)) { + sd_bus_creds_unref(c); + return -ESRCH; + } + + *ret = c; + return 0; +} + +_public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) { + assert_return(c, -EINVAL); + assert_return(uid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_UID)) + return -ENODATA; + + *uid = c->uid; + return 0; +} + +_public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) { + assert_return(c, -EINVAL); + assert_return(euid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_EUID)) + return -ENODATA; + + *euid = c->euid; + return 0; +} + +_public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) { + assert_return(c, -EINVAL); + assert_return(suid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_SUID)) + return -ENODATA; + + *suid = c->suid; + return 0; +} + +_public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) { + assert_return(c, -EINVAL); + assert_return(fsuid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_FSUID)) + return -ENODATA; + + *fsuid = c->fsuid; + return 0; +} + +_public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) { + assert_return(c, -EINVAL); + assert_return(gid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_GID)) + return -ENODATA; + + *gid = c->gid; + return 0; +} + +_public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) { + assert_return(c, -EINVAL); + assert_return(egid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_EGID)) + return -ENODATA; + + *egid = c->egid; + return 0; +} + +_public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) { + assert_return(c, -EINVAL); + assert_return(sgid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_SGID)) + return -ENODATA; + + *sgid = c->sgid; + return 0; +} + +_public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) { + assert_return(c, -EINVAL); + assert_return(fsgid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_FSGID)) + return -ENODATA; + + *fsgid = c->fsgid; + return 0; +} + +_public_ int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids) { + assert_return(c, -EINVAL); + assert_return(gids, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)) + return -ENODATA; + + *gids = c->supplementary_gids; + return (int) c->n_supplementary_gids; +} + +_public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) { + assert_return(c, -EINVAL); + assert_return(pid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_PID)) + return -ENODATA; + + assert(c->pid > 0); + *pid = c->pid; + return 0; +} + +_public_ int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid) { + assert_return(c, -EINVAL); + assert_return(ppid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_PPID)) + return -ENODATA; + + /* PID 1 has no parent process. Let's distinguish the case of + * not knowing and not having a parent process by the returned + * error code. */ + if (c->ppid == 0) + return -ENXIO; + + *ppid = c->ppid; + return 0; +} + +_public_ int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid) { + assert_return(c, -EINVAL); + assert_return(tid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_TID)) + return -ENODATA; + + assert(c->tid > 0); + *tid = c->tid; + return 0; +} + +_public_ int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_SELINUX_CONTEXT)) + return -ENODATA; + + assert(c->label); + *ret = c->label; + return 0; +} + +_public_ int sd_bus_creds_get_comm(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_COMM)) + return -ENODATA; + + assert(c->comm); + *ret = c->comm; + return 0; +} + +_public_ int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_TID_COMM)) + return -ENODATA; + + assert(c->tid_comm); + *ret = c->tid_comm; + return 0; +} + +_public_ int sd_bus_creds_get_exe(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_EXE)) + return -ENODATA; + + if (!c->exe) + return -ENXIO; + + *ret = c->exe; + return 0; +} + +_public_ int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_CGROUP)) + return -ENODATA; + + assert(c->cgroup); + *ret = c->cgroup; + return 0; +} + +_public_ int sd_bus_creds_get_unit(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_UNIT)) + return -ENODATA; + + assert(c->cgroup); + + if (!c->unit) { + const char *shifted; + + r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); + if (r < 0) + return r; + + r = cg_path_get_unit(shifted, (char**) &c->unit); + if (r < 0) + return r; + } + + *ret = c->unit; + return 0; +} + +_public_ int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_USER_UNIT)) + return -ENODATA; + + assert(c->cgroup); + + if (!c->user_unit) { + const char *shifted; + + r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); + if (r < 0) + return r; + + r = cg_path_get_user_unit(shifted, (char**) &c->user_unit); + if (r < 0) + return r; + } + + *ret = c->user_unit; + return 0; +} + +_public_ int sd_bus_creds_get_slice(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_SLICE)) + return -ENODATA; + + assert(c->cgroup); + + if (!c->slice) { + const char *shifted; + + r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); + if (r < 0) + return r; + + r = cg_path_get_slice(shifted, (char**) &c->slice); + if (r < 0) + return r; + } + + *ret = c->slice; + return 0; +} + +_public_ int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_USER_SLICE)) + return -ENODATA; + + assert(c->cgroup); + + if (!c->user_slice) { + const char *shifted; + + r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); + if (r < 0) + return r; + + r = cg_path_get_user_slice(shifted, (char**) &c->user_slice); + if (r < 0) + return r; + } + + *ret = c->user_slice; + return 0; +} + +_public_ int sd_bus_creds_get_session(sd_bus_creds *c, const char **ret) { + int r; + + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_SESSION)) + return -ENODATA; + + assert(c->cgroup); + + if (!c->session) { + const char *shifted; + + r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); + if (r < 0) + return r; + + r = cg_path_get_session(shifted, (char**) &c->session); + if (r < 0) + return r; + } + + *ret = c->session; + return 0; +} + +_public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) { + const char *shifted; + int r; + + assert_return(c, -EINVAL); + assert_return(uid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_OWNER_UID)) + return -ENODATA; + + assert(c->cgroup); + + r = cg_shift_path(c->cgroup, c->cgroup_root, &shifted); + if (r < 0) + return r; + + return cg_path_get_owner_uid(shifted, uid); +} + +_public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) { + assert_return(c, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_CMDLINE)) + return -ENODATA; + + if (!c->cmdline) + return -ENXIO; + + if (!c->cmdline_array) { + c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size); + if (!c->cmdline_array) + return -ENOMEM; + } + + *cmdline = c->cmdline_array; + return 0; +} + +_public_ int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid) { + assert_return(c, -EINVAL); + assert_return(sessionid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_AUDIT_SESSION_ID)) + return -ENODATA; + + if (!audit_session_is_valid(c->audit_session_id)) + return -ENXIO; + + *sessionid = c->audit_session_id; + return 0; +} + +_public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) { + assert_return(c, -EINVAL); + assert_return(uid, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_AUDIT_LOGIN_UID)) + return -ENODATA; + + if (!uid_is_valid(c->audit_login_uid)) + return -ENXIO; + + *uid = c->audit_login_uid; + return 0; +} + +_public_ int sd_bus_creds_get_tty(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_TTY)) + return -ENODATA; + + if (!c->tty) + return -ENXIO; + + *ret = c->tty; + return 0; +} + +_public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) { + assert_return(c, -EINVAL); + assert_return(unique_name, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_UNIQUE_NAME)) + return -ENODATA; + + *unique_name = c->unique_name; + return 0; +} + +_public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) { + assert_return(c, -EINVAL); + assert_return(well_known_names, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)) + return -ENODATA; + + /* As a special hack we return the bus driver as well-known + * names list when this is requested. */ + if (c->well_known_names_driver) { + static const char* const wkn[] = { + "org.freedesktop.DBus", + NULL + }; + + *well_known_names = (char**) wkn; + return 0; + } + + if (c->well_known_names_local) { + static const char* const wkn[] = { + "org.freedesktop.DBus.Local", + NULL + }; + + *well_known_names = (char**) wkn; + return 0; + } + + *well_known_names = c->well_known_names; + return 0; +} + +_public_ int sd_bus_creds_get_description(sd_bus_creds *c, const char **ret) { + assert_return(c, -EINVAL); + assert_return(ret, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_DESCRIPTION)) + return -ENODATA; + + assert(c->description); + + if (!c->unescaped_description) { + c->unescaped_description = bus_label_unescape(c->description); + if (!c->unescaped_description) + return -ENOMEM; + } + + *ret = c->unescaped_description; + return 0; +} + +static int has_cap(sd_bus_creds *c, size_t offset, int capability) { + unsigned long lc; + size_t sz; + + assert(c); + assert(capability >= 0); + assert(c->capability); + + lc = cap_last_cap(); + + if ((unsigned long) capability > lc) + return 0; + + /* If the last cap is 63, then there are 64 caps defined, and we need 2 entries á 32bit hence. * + * If the last cap is 64, then there are 65 caps defined, and we need 3 entries á 32bit hence. */ + sz = DIV_ROUND_UP(lc+1, 32LU); + + return !!(c->capability[offset * sz + CAP_TO_INDEX((uint32_t) capability)] & CAP_TO_MASK_CORRECTED((uint32_t) capability)); +} + +_public_ int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability) { + assert_return(c, -EINVAL); + assert_return(capability >= 0, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_EFFECTIVE_CAPS)) + return -ENODATA; + + return has_cap(c, CAP_OFFSET_EFFECTIVE, capability); +} + +_public_ int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability) { + assert_return(c, -EINVAL); + assert_return(capability >= 0, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_PERMITTED_CAPS)) + return -ENODATA; + + return has_cap(c, CAP_OFFSET_PERMITTED, capability); +} + +_public_ int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability) { + assert_return(c, -EINVAL); + assert_return(capability >= 0, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_INHERITABLE_CAPS)) + return -ENODATA; + + return has_cap(c, CAP_OFFSET_INHERITABLE, capability); +} + +_public_ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability) { + assert_return(c, -EINVAL); + assert_return(capability >= 0, -EINVAL); + + if (!(c->mask & SD_BUS_CREDS_BOUNDING_CAPS)) + return -ENODATA; + + return has_cap(c, CAP_OFFSET_BOUNDING, capability); +} + +static int parse_caps(sd_bus_creds *c, unsigned offset, const char *p) { + size_t sz, max; + unsigned i, j; + + assert(c); + assert(p); + + max = DIV_ROUND_UP(cap_last_cap()+1, 32U); + p += strspn(p, WHITESPACE); + + sz = strlen(p); + if (sz % 8 != 0) + return -EINVAL; + + sz /= 8; + if (sz > max) + return -EINVAL; + + if (!c->capability) { + c->capability = new0(uint32_t, max * 4); + if (!c->capability) + return -ENOMEM; + } + + for (i = 0; i < sz; i ++) { + uint32_t v = 0; + + for (j = 0; j < 8; ++j) { + int t; + + t = unhexchar(*p++); + if (t < 0) + return -EINVAL; + + v = (v << 4) | t; + } + + c->capability[offset * max + (sz - i - 1)] = v; + } + + return 0; +} + +int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { + uint64_t missing; + int r; + + assert(c); + assert(c->allocated); + + if (!(mask & SD_BUS_CREDS_AUGMENT)) + return 0; + + /* Try to retrieve PID from creds if it wasn't passed to us */ + if (pid > 0) { + c->pid = pid; + c->mask |= SD_BUS_CREDS_PID; + } else if (c->mask & SD_BUS_CREDS_PID) + pid = c->pid; + else + /* Without pid we cannot do much... */ + return 0; + + /* Try to retrieve TID from creds if it wasn't passed to us */ + if (tid <= 0 && (c->mask & SD_BUS_CREDS_TID)) + tid = c->tid; + + /* Calculate what we shall and can add */ + missing = mask & ~(c->mask|SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_AUGMENT); + if (missing == 0) + return 0; + + if (tid > 0) { + c->tid = tid; + c->mask |= SD_BUS_CREDS_TID; + } + + if (missing & (SD_BUS_CREDS_PPID | + SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID | + SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID | + SD_BUS_CREDS_SUPPLEMENTARY_GIDS | + SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS | + SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) { + + _cleanup_fclose_ FILE *f = NULL; + const char *p; + + p = procfs_file_alloca(pid, "status"); + + f = fopen(p, "re"); + if (!f) { + if (errno == ENOENT) + return -ESRCH; + else if (!IN_SET(errno, EPERM, EACCES)) + return -errno; + } else { + + for (;;) { + _cleanup_free_ char *line = NULL; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + if (missing & SD_BUS_CREDS_PPID) { + p = startswith(line, "PPid:"); + if (p) { + p += strspn(p, WHITESPACE); + + /* Explicitly check for PPID 0 (which is the case for PID 1) */ + if (!streq(p, "0")) { + r = parse_pid(p, &c->ppid); + if (r < 0) + return r; + + } else + c->ppid = 0; + + c->mask |= SD_BUS_CREDS_PPID; + continue; + } + } + + if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) { + p = startswith(line, "Uid:"); + if (p) { + unsigned long uid, euid, suid, fsuid; + + p += strspn(p, WHITESPACE); + if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4) + return -EIO; + + if (missing & SD_BUS_CREDS_UID) + c->uid = (uid_t) uid; + if (missing & SD_BUS_CREDS_EUID) + c->euid = (uid_t) euid; + if (missing & SD_BUS_CREDS_SUID) + c->suid = (uid_t) suid; + if (missing & SD_BUS_CREDS_FSUID) + c->fsuid = (uid_t) fsuid; + + c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID); + continue; + } + } + + if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) { + p = startswith(line, "Gid:"); + if (p) { + unsigned long gid, egid, sgid, fsgid; + + p += strspn(p, WHITESPACE); + if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4) + return -EIO; + + if (missing & SD_BUS_CREDS_GID) + c->gid = (gid_t) gid; + if (missing & SD_BUS_CREDS_EGID) + c->egid = (gid_t) egid; + if (missing & SD_BUS_CREDS_SGID) + c->sgid = (gid_t) sgid; + if (missing & SD_BUS_CREDS_FSGID) + c->fsgid = (gid_t) fsgid; + + c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID); + continue; + } + } + + if (missing & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) { + p = startswith(line, "Groups:"); + if (p) { + size_t allocated = 0; + + for (;;) { + unsigned long g; + int n = 0; + + p += strspn(p, WHITESPACE); + if (*p == 0) + break; + + if (sscanf(p, "%lu%n", &g, &n) != 1) + return -EIO; + + if (!GREEDY_REALLOC(c->supplementary_gids, allocated, c->n_supplementary_gids+1)) + return -ENOMEM; + + c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) g; + p += n; + } + + c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; + continue; + } + } + + if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) { + p = startswith(line, "CapEff:"); + if (p) { + r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p); + if (r < 0) + return r; + + c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS; + continue; + } + } + + if (missing & SD_BUS_CREDS_PERMITTED_CAPS) { + p = startswith(line, "CapPrm:"); + if (p) { + r = parse_caps(c, CAP_OFFSET_PERMITTED, p); + if (r < 0) + return r; + + c->mask |= SD_BUS_CREDS_PERMITTED_CAPS; + continue; + } + } + + if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) { + p = startswith(line, "CapInh:"); + if (p) { + r = parse_caps(c, CAP_OFFSET_INHERITABLE, p); + if (r < 0) + return r; + + c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS; + continue; + } + } + + if (missing & SD_BUS_CREDS_BOUNDING_CAPS) { + p = startswith(line, "CapBnd:"); + if (p) { + r = parse_caps(c, CAP_OFFSET_BOUNDING, p); + if (r < 0) + return r; + + c->mask |= SD_BUS_CREDS_BOUNDING_CAPS; + continue; + } + } + } + } + } + + if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) { + const char *p; + + p = procfs_file_alloca(pid, "attr/current"); + r = read_one_line_file(p, &c->label); + if (r < 0) { + if (!IN_SET(r, -ENOENT, -EINVAL, -EPERM, -EACCES)) + return r; + } else + c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + } + + if (missing & SD_BUS_CREDS_COMM) { + r = get_process_comm(pid, &c->comm); + if (r < 0) { + if (!IN_SET(r, -EPERM, -EACCES)) + return r; + } else + c->mask |= SD_BUS_CREDS_COMM; + } + + if (missing & SD_BUS_CREDS_EXE) { + r = get_process_exe(pid, &c->exe); + if (r == -ESRCH) { + /* Unfortunately we cannot really distinguish + * the case here where the process does not + * exist, and /proc/$PID/exe being unreadable + * because $PID is a kernel thread. Hence, + * assume it is a kernel thread, and rely on + * that this case is caught with a later + * call. */ + c->exe = NULL; + c->mask |= SD_BUS_CREDS_EXE; + } else if (r < 0) { + if (!IN_SET(r, -EPERM, -EACCES)) + return r; + } else + c->mask |= SD_BUS_CREDS_EXE; + } + + if (missing & SD_BUS_CREDS_CMDLINE) { + const char *p; + + p = procfs_file_alloca(pid, "cmdline"); + r = read_full_file(p, &c->cmdline, &c->cmdline_size); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) { + if (!IN_SET(r, -EPERM, -EACCES)) + return r; + } else { + if (c->cmdline_size == 0) + c->cmdline = mfree(c->cmdline); + + c->mask |= SD_BUS_CREDS_CMDLINE; + } + } + + if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) { + _cleanup_free_ char *p = NULL; + + if (asprintf(&p, "/proc/"PID_FMT"/task/"PID_FMT"/comm", pid, tid) < 0) + return -ENOMEM; + + r = read_one_line_file(p, &c->tid_comm); + if (r == -ENOENT) + return -ESRCH; + if (r < 0) { + if (!IN_SET(r, -EPERM, -EACCES)) + return r; + } else + c->mask |= SD_BUS_CREDS_TID_COMM; + } + + if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) { + + if (!c->cgroup) { + r = cg_pid_get_path(NULL, pid, &c->cgroup); + if (r < 0) { + if (!IN_SET(r, -EPERM, -EACCES)) + return r; + } + } + + if (!c->cgroup_root) { + r = cg_get_root_path(&c->cgroup_root); + if (r < 0) + return r; + } + + if (c->cgroup) + c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID); + } + + if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) { + r = audit_session_from_pid(pid, &c->audit_session_id); + if (r == -ENODATA) { + /* ENODATA means: no audit session id assigned */ + c->audit_session_id = AUDIT_SESSION_INVALID; + c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; + } else if (r < 0) { + if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES)) + return r; + } else + c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; + } + + if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) { + r = audit_loginuid_from_pid(pid, &c->audit_login_uid); + if (r == -ENODATA) { + /* ENODATA means: no audit login uid assigned */ + c->audit_login_uid = UID_INVALID; + c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; + } else if (r < 0) { + if (!IN_SET(r, -EOPNOTSUPP, -ENOENT, -EPERM, -EACCES)) + return r; + } else + c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; + } + + if (missing & SD_BUS_CREDS_TTY) { + r = get_ctty(pid, NULL, &c->tty); + if (r == -ENXIO) { + /* ENXIO means: process has no controlling TTY */ + c->tty = NULL; + c->mask |= SD_BUS_CREDS_TTY; + } else if (r < 0) { + if (!IN_SET(r, -EPERM, -EACCES, -ENOENT)) + return r; + } else + c->mask |= SD_BUS_CREDS_TTY; + } + + /* In case only the exe path was to be read we cannot + * distinguish the case where the exe path was unreadable + * because the process was a kernel thread, or when the + * process didn't exist at all. Hence, let's do a final check, + * to be sure. */ + if (!pid_is_alive(pid)) + return -ESRCH; + + if (tid > 0 && tid != pid && !pid_is_unwaited(tid)) + return -ESRCH; + + c->augmented = missing & c->mask; + + return 0; +} + +int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *n = NULL; + int r; + + assert(c); + assert(ret); + + if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) { + /* There's already all data we need, or augmentation + * wasn't turned on. */ + + *ret = sd_bus_creds_ref(c); + return 0; + } + + n = bus_creds_new(); + if (!n) + return -ENOMEM; + + /* Copy the original data over */ + + if (c->mask & mask & SD_BUS_CREDS_PID) { + n->pid = c->pid; + n->mask |= SD_BUS_CREDS_PID; + } + + if (c->mask & mask & SD_BUS_CREDS_TID) { + n->tid = c->tid; + n->mask |= SD_BUS_CREDS_TID; + } + + if (c->mask & mask & SD_BUS_CREDS_PPID) { + n->ppid = c->ppid; + n->mask |= SD_BUS_CREDS_PPID; + } + + if (c->mask & mask & SD_BUS_CREDS_UID) { + n->uid = c->uid; + n->mask |= SD_BUS_CREDS_UID; + } + + if (c->mask & mask & SD_BUS_CREDS_EUID) { + n->euid = c->euid; + n->mask |= SD_BUS_CREDS_EUID; + } + + if (c->mask & mask & SD_BUS_CREDS_SUID) { + n->suid = c->suid; + n->mask |= SD_BUS_CREDS_SUID; + } + + if (c->mask & mask & SD_BUS_CREDS_FSUID) { + n->fsuid = c->fsuid; + n->mask |= SD_BUS_CREDS_FSUID; + } + + if (c->mask & mask & SD_BUS_CREDS_GID) { + n->gid = c->gid; + n->mask |= SD_BUS_CREDS_GID; + } + + if (c->mask & mask & SD_BUS_CREDS_EGID) { + n->egid = c->egid; + n->mask |= SD_BUS_CREDS_EGID; + } + + if (c->mask & mask & SD_BUS_CREDS_SGID) { + n->sgid = c->sgid; + n->mask |= SD_BUS_CREDS_SGID; + } + + if (c->mask & mask & SD_BUS_CREDS_FSGID) { + n->fsgid = c->fsgid; + n->mask |= SD_BUS_CREDS_FSGID; + } + + if (c->mask & mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) { + if (c->supplementary_gids) { + n->supplementary_gids = newdup(gid_t, c->supplementary_gids, c->n_supplementary_gids); + if (!n->supplementary_gids) + return -ENOMEM; + n->n_supplementary_gids = c->n_supplementary_gids; + } else { + n->supplementary_gids = NULL; + n->n_supplementary_gids = 0; + } + + n->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS; + } + + if (c->mask & mask & SD_BUS_CREDS_COMM) { + assert(c->comm); + + n->comm = strdup(c->comm); + if (!n->comm) + return -ENOMEM; + + n->mask |= SD_BUS_CREDS_COMM; + } + + if (c->mask & mask & SD_BUS_CREDS_TID_COMM) { + assert(c->tid_comm); + + n->tid_comm = strdup(c->tid_comm); + if (!n->tid_comm) + return -ENOMEM; + + n->mask |= SD_BUS_CREDS_TID_COMM; + } + + if (c->mask & mask & SD_BUS_CREDS_EXE) { + if (c->exe) { + n->exe = strdup(c->exe); + if (!n->exe) + return -ENOMEM; + } else + n->exe = NULL; + + n->mask |= SD_BUS_CREDS_EXE; + } + + if (c->mask & mask & SD_BUS_CREDS_CMDLINE) { + if (c->cmdline) { + n->cmdline = memdup(c->cmdline, c->cmdline_size); + if (!n->cmdline) + return -ENOMEM; + + n->cmdline_size = c->cmdline_size; + } else { + n->cmdline = NULL; + n->cmdline_size = 0; + } + + n->mask |= SD_BUS_CREDS_CMDLINE; + } + + if (c->mask & mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_OWNER_UID)) { + assert(c->cgroup); + + n->cgroup = strdup(c->cgroup); + if (!n->cgroup) + return -ENOMEM; + + n->cgroup_root = strdup(c->cgroup_root); + if (!n->cgroup_root) + return -ENOMEM; + + n->mask |= mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_USER_SLICE|SD_BUS_CREDS_OWNER_UID); + } + + if (c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS)) { + assert(c->capability); + + n->capability = memdup(c->capability, DIV_ROUND_UP(cap_last_cap()+1, 32U) * 4 * 4); + if (!n->capability) + return -ENOMEM; + + n->mask |= c->mask & mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS); + } + + if (c->mask & mask & SD_BUS_CREDS_SELINUX_CONTEXT) { + assert(c->label); + + n->label = strdup(c->label); + if (!n->label) + return -ENOMEM; + n->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + } + + if (c->mask & mask & SD_BUS_CREDS_AUDIT_SESSION_ID) { + n->audit_session_id = c->audit_session_id; + n->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; + } + if (c->mask & mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) { + n->audit_login_uid = c->audit_login_uid; + n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; + } + + if (c->mask & mask & SD_BUS_CREDS_TTY) { + if (c->tty) { + n->tty = strdup(c->tty); + if (!n->tty) + return -ENOMEM; + } else + n->tty = NULL; + n->mask |= SD_BUS_CREDS_TTY; + } + + if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) { + assert(c->unique_name); + + n->unique_name = strdup(c->unique_name); + if (!n->unique_name) + return -ENOMEM; + n->mask |= SD_BUS_CREDS_UNIQUE_NAME; + } + + if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) { + if (strv_isempty(c->well_known_names)) + n->well_known_names = NULL; + else { + n->well_known_names = strv_copy(c->well_known_names); + if (!n->well_known_names) + return -ENOMEM; + } + n->well_known_names_driver = c->well_known_names_driver; + n->well_known_names_local = c->well_known_names_local; + n->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES; + } + + if (c->mask & mask & SD_BUS_CREDS_DESCRIPTION) { + assert(c->description); + n->description = strdup(c->description); + if (!n->description) + return -ENOMEM; + n->mask |= SD_BUS_CREDS_DESCRIPTION; + } + + n->augmented = c->augmented & n->mask; + + /* Get more data */ + + r = bus_creds_add_more(n, mask, 0, 0); + if (r < 0) + return r; + + *ret = TAKE_PTR(n); + + return 0; +} diff --git a/src/libsystemd/sd-bus/bus-creds.h b/src/libsystemd/sd-bus/bus-creds.h new file mode 100644 index 00000000..508ef9d3 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-creds.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" + +struct sd_bus_creds { + bool allocated; + unsigned n_ref; + + uint64_t mask; + uint64_t augmented; + + uid_t uid; + uid_t euid; + uid_t suid; + uid_t fsuid; + gid_t gid; + gid_t egid; + gid_t sgid; + gid_t fsgid; + + gid_t *supplementary_gids; + unsigned n_supplementary_gids; + + pid_t ppid; + pid_t pid; + pid_t tid; + + char *comm; + char *tid_comm; + char *exe; + + char *cmdline; + size_t cmdline_size; + char **cmdline_array; + + char *cgroup; + char *session; + char *unit; + char *user_unit; + char *slice; + char *user_slice; + + char *tty; + + uint32_t *capability; + + uint32_t audit_session_id; + uid_t audit_login_uid; + + char *label; + + char *unique_name; + + char **well_known_names; + bool well_known_names_driver:1; + bool well_known_names_local:1; + + char *cgroup_root; + + char *description, *unescaped_description; +}; + +sd_bus_creds* bus_creds_new(void); + +void bus_creds_done(sd_bus_creds *c); + +int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid); + +int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret); diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c new file mode 100644 index 00000000..9a6a81d7 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-dump.c @@ -0,0 +1,593 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "bus-dump.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-type.h" +#include "cap-list.h" +#include "capability-util.h" +#include "fileio.h" +#include "format-util.h" +#include "locale-util.h" +#include "macro.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "util.h" + +static char *indent(unsigned level, unsigned flags) { + char *p; + unsigned n, i = 0; + + n = 0; + + if (flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY && level > 0) + level -= 1; + + if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) + n += 2; + + p = new(char, n + level*8 + 1); + if (!p) + return NULL; + + if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) { + p[i++] = ' '; + p[i++] = ' '; + } + + memset(p + i, ' ', level*8); + p[i + level*8] = 0; + + return p; +} + +int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) { + unsigned level = 1; + int r; + + assert(m); + + if (!f) + f = stdout; + + if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) { + fprintf(f, + "%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64, + m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() : + m->header->type == SD_BUS_MESSAGE_METHOD_RETURN ? ansi_highlight_green() : + m->header->type != SD_BUS_MESSAGE_SIGNAL ? ansi_highlight() : "", + special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), + ansi_normal(), + + ansi_highlight(), + bus_message_type_to_string(m->header->type) ?: "(unknown)", + ansi_normal(), + + m->header->endian, + m->header->flags, + m->header->version, + m->priority); + + /* Display synthetic message serial number in a more readable + * format than (uint32_t) -1 */ + if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL) + fprintf(f, " Cookie=-1"); + else + fprintf(f, " Cookie=%" PRIu64, BUS_MESSAGE_COOKIE(m)); + + if (m->reply_cookie != 0) + fprintf(f, " ReplyCookie=%" PRIu64, m->reply_cookie); + + fputs("\n", f); + + if (m->sender) + fprintf(f, " Sender=%s%s%s", ansi_highlight(), m->sender, ansi_normal()); + if (m->destination) + fprintf(f, " Destination=%s%s%s", ansi_highlight(), m->destination, ansi_normal()); + if (m->path) + fprintf(f, " Path=%s%s%s", ansi_highlight(), m->path, ansi_normal()); + if (m->interface) + fprintf(f, " Interface=%s%s%s", ansi_highlight(), m->interface, ansi_normal()); + if (m->member) + fprintf(f, " Member=%s%s%s", ansi_highlight(), m->member, ansi_normal()); + + if (m->sender || m->destination || m->path || m->interface || m->member) + fputs("\n", f); + + if (sd_bus_error_is_set(&m->error)) + fprintf(f, + " ErrorName=%s%s%s" + " ErrorMessage=%s\"%s\"%s\n", + ansi_highlight_red(), strna(m->error.name), ansi_normal(), + ansi_highlight_red(), strna(m->error.message), ansi_normal()); + + if (m->monotonic != 0) + fprintf(f, " Monotonic="USEC_FMT, m->monotonic); + if (m->realtime != 0) + fprintf(f, " Realtime="USEC_FMT, m->realtime); + if (m->seqnum != 0) + fprintf(f, " SequenceNumber=%"PRIu64, m->seqnum); + + if (m->monotonic != 0 || m->realtime != 0 || m->seqnum != 0) + fputs("\n", f); + + bus_creds_dump(&m->creds, f, true); + } + + r = sd_bus_message_rewind(m, !(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)); + if (r < 0) + return log_error_errno(r, "Failed to rewind: %m"); + + if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) { + _cleanup_free_ char *prefix = NULL; + + prefix = indent(0, flags); + if (!prefix) + return log_oom(); + + fprintf(f, "%sMESSAGE \"%s\" {\n", prefix, strempty(m->root_container.signature)); + } + + for (;;) { + _cleanup_free_ char *prefix = NULL; + const char *contents = NULL; + char type; + union { + uint8_t u8; + uint16_t u16; + int16_t s16; + uint32_t u32; + int32_t s32; + uint64_t u64; + int64_t s64; + double d64; + const char *string; + int i; + } basic; + + r = sd_bus_message_peek_type(m, &type, &contents); + if (r < 0) + return log_error_errno(r, "Failed to peek type: %m"); + + if (r == 0) { + if (level <= 1) + break; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return log_error_errno(r, "Failed to exit container: %m"); + + level--; + + prefix = indent(level, flags); + if (!prefix) + return log_oom(); + + fprintf(f, "%s};\n", prefix); + continue; + } + + prefix = indent(level, flags); + if (!prefix) + return log_oom(); + + if (bus_type_is_container(type) > 0) { + r = sd_bus_message_enter_container(m, type, contents); + if (r < 0) + return log_error_errno(r, "Failed to enter container: %m"); + + if (type == SD_BUS_TYPE_ARRAY) + fprintf(f, "%sARRAY \"%s\" {\n", prefix, contents); + else if (type == SD_BUS_TYPE_VARIANT) + fprintf(f, "%sVARIANT \"%s\" {\n", prefix, contents); + else if (type == SD_BUS_TYPE_STRUCT) + fprintf(f, "%sSTRUCT \"%s\" {\n", prefix, contents); + else if (type == SD_BUS_TYPE_DICT_ENTRY) + fprintf(f, "%sDICT_ENTRY \"%s\" {\n", prefix, contents); + + level++; + + continue; + } + + r = sd_bus_message_read_basic(m, type, &basic); + if (r < 0) + return log_error_errno(r, "Failed to get basic: %m"); + + assert(r > 0); + + switch (type) { + + case SD_BUS_TYPE_BYTE: + fprintf(f, "%sBYTE %s%u%s;\n", prefix, ansi_highlight(), basic.u8, ansi_normal()); + break; + + case SD_BUS_TYPE_BOOLEAN: + fprintf(f, "%sBOOLEAN %s%s%s;\n", prefix, ansi_highlight(), true_false(basic.i), ansi_normal()); + break; + + case SD_BUS_TYPE_INT16: + fprintf(f, "%sINT16 %s%i%s;\n", prefix, ansi_highlight(), basic.s16, ansi_normal()); + break; + + case SD_BUS_TYPE_UINT16: + fprintf(f, "%sUINT16 %s%u%s;\n", prefix, ansi_highlight(), basic.u16, ansi_normal()); + break; + + case SD_BUS_TYPE_INT32: + fprintf(f, "%sINT32 %s%i%s;\n", prefix, ansi_highlight(), basic.s32, ansi_normal()); + break; + + case SD_BUS_TYPE_UINT32: + fprintf(f, "%sUINT32 %s%u%s;\n", prefix, ansi_highlight(), basic.u32, ansi_normal()); + break; + + case SD_BUS_TYPE_INT64: + fprintf(f, "%sINT64 %s%"PRIi64"%s;\n", prefix, ansi_highlight(), basic.s64, ansi_normal()); + break; + + case SD_BUS_TYPE_UINT64: + fprintf(f, "%sUINT64 %s%"PRIu64"%s;\n", prefix, ansi_highlight(), basic.u64, ansi_normal()); + break; + + case SD_BUS_TYPE_DOUBLE: + fprintf(f, "%sDOUBLE %s%g%s;\n", prefix, ansi_highlight(), basic.d64, ansi_normal()); + break; + + case SD_BUS_TYPE_STRING: + fprintf(f, "%sSTRING \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal()); + break; + + case SD_BUS_TYPE_OBJECT_PATH: + fprintf(f, "%sOBJECT_PATH \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal()); + break; + + case SD_BUS_TYPE_SIGNATURE: + fprintf(f, "%sSIGNATURE \"%s%s%s\";\n", prefix, ansi_highlight(), basic.string, ansi_normal()); + break; + + case SD_BUS_TYPE_UNIX_FD: + fprintf(f, "%sUNIX_FD %s%i%s;\n", prefix, ansi_highlight(), basic.i, ansi_normal()); + break; + + default: + assert_not_reached("Unknown basic type."); + } + } + + if (!(flags & BUS_MESSAGE_DUMP_SUBTREE_ONLY)) { + _cleanup_free_ char *prefix = NULL; + + prefix = indent(0, flags); + if (!prefix) + return log_oom(); + + fprintf(f, "%s};\n\n", prefix); + } + + return 0; +} + +static void dump_capabilities( + sd_bus_creds *c, + FILE *f, + const char *name, + bool terse, + int (*has)(sd_bus_creds *c, int capability)) { + + unsigned long i, last_cap; + unsigned n = 0; + int r; + + assert(c); + assert(f); + assert(name); + assert(has); + + i = 0; + r = has(c, i); + if (r < 0) + return; + + fprintf(f, "%s%s=%s", terse ? " " : "", name, terse ? "" : ansi_highlight()); + last_cap = cap_last_cap(); + + for (;;) { + if (r > 0) { + + if (n > 0) + fputc(' ', f); + if (n % 4 == 3) + fprintf(f, terse ? "\n " : "\n "); + + fprintf(f, "%s", strna(capability_to_name(i))); + n++; + } + + i++; + + if (i > last_cap) + break; + + r = has(c, i); + } + + fputs("\n", f); + + if (!terse) + fputs(ansi_normal(), f); +} + +int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) { + uid_t owner, audit_loginuid; + uint32_t audit_sessionid; + char **cmdline = NULL, **well_known = NULL; + const char *prefix, *color, *suffix, *s; + int r, q, v, w, z; + + assert(c); + + if (!f) + f = stdout; + + if (terse) { + prefix = " "; + suffix = ""; + color = ""; + } else { + const char *off; + + prefix = ""; + color = ansi_highlight(); + + off = ansi_normal(); + suffix = strjoina(off, "\n"); + } + + if (c->mask & SD_BUS_CREDS_PID) + fprintf(f, "%sPID=%s"PID_FMT"%s", prefix, color, c->pid, suffix); + if (c->mask & SD_BUS_CREDS_TID) + fprintf(f, "%sTID=%s"PID_FMT"%s", prefix, color, c->tid, suffix); + if (c->mask & SD_BUS_CREDS_PPID) { + if (c->ppid == 0) + fprintf(f, "%sPPID=%sn/a%s", prefix, color, suffix); + else + fprintf(f, "%sPPID=%s"PID_FMT"%s", prefix, color, c->ppid, suffix); + } + if (c->mask & SD_BUS_CREDS_TTY) + fprintf(f, "%sTTY=%s%s%s", prefix, color, strna(c->tty), suffix); + + if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID|SD_BUS_CREDS_TTY)))) + fputs("\n", f); + + if (c->mask & SD_BUS_CREDS_UID) + fprintf(f, "%sUID=%s"UID_FMT"%s", prefix, color, c->uid, suffix); + if (c->mask & SD_BUS_CREDS_EUID) + fprintf(f, "%sEUID=%s"UID_FMT"%s", prefix, color, c->euid, suffix); + if (c->mask & SD_BUS_CREDS_SUID) + fprintf(f, "%sSUID=%s"UID_FMT"%s", prefix, color, c->suid, suffix); + if (c->mask & SD_BUS_CREDS_FSUID) + fprintf(f, "%sFSUID=%s"UID_FMT"%s", prefix, color, c->fsuid, suffix); + r = sd_bus_creds_get_owner_uid(c, &owner); + if (r >= 0) + fprintf(f, "%sOwnerUID=%s"UID_FMT"%s", prefix, color, owner, suffix); + if (c->mask & SD_BUS_CREDS_GID) + fprintf(f, "%sGID=%s"GID_FMT"%s", prefix, color, c->gid, suffix); + if (c->mask & SD_BUS_CREDS_EGID) + fprintf(f, "%sEGID=%s"GID_FMT"%s", prefix, color, c->egid, suffix); + if (c->mask & SD_BUS_CREDS_SGID) + fprintf(f, "%sSGID=%s"GID_FMT"%s", prefix, color, c->sgid, suffix); + if (c->mask & SD_BUS_CREDS_FSGID) + fprintf(f, "%sFSGID=%s"GID_FMT"%s", prefix, color, c->fsgid, suffix); + + if (c->mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) { + unsigned i; + + fprintf(f, "%sSupplementaryGIDs=%s", prefix, color); + for (i = 0; i < c->n_supplementary_gids; i++) + fprintf(f, "%s" GID_FMT, i > 0 ? " " : "", c->supplementary_gids[i]); + fprintf(f, "%s", suffix); + } + + if (terse && ((c->mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| + SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID| + SD_BUS_CREDS_SUPPLEMENTARY_GIDS)) || r >= 0)) + fputs("\n", f); + + if (c->mask & SD_BUS_CREDS_COMM) + fprintf(f, "%sComm=%s%s%s", prefix, color, c->comm, suffix); + if (c->mask & SD_BUS_CREDS_TID_COMM) + fprintf(f, "%sTIDComm=%s%s%s", prefix, color, c->tid_comm, suffix); + if (c->mask & SD_BUS_CREDS_EXE) + fprintf(f, "%sExe=%s%s%s", prefix, color, strna(c->exe), suffix); + + if (terse && (c->mask & (SD_BUS_CREDS_EXE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM))) + fputs("\n", f); + + r = sd_bus_creds_get_cmdline(c, &cmdline); + if (r >= 0) { + char **i; + + fprintf(f, "%sCommandLine=%s", prefix, color); + STRV_FOREACH(i, cmdline) { + if (i != cmdline) + fputc(' ', f); + + fputs(*i, f); + } + + fprintf(f, "%s", suffix); + } else if (r != -ENODATA) + fprintf(f, "%sCommandLine=%sn/a%s", prefix, color, suffix); + + if (c->mask & SD_BUS_CREDS_SELINUX_CONTEXT) + fprintf(f, "%sLabel=%s%s%s", prefix, color, c->label, suffix); + if (c->mask & SD_BUS_CREDS_DESCRIPTION) + fprintf(f, "%sDescription=%s%s%s", prefix, color, c->description, suffix); + + if (terse && (c->mask & (SD_BUS_CREDS_SELINUX_CONTEXT|SD_BUS_CREDS_DESCRIPTION))) + fputs("\n", f); + + if (c->mask & SD_BUS_CREDS_CGROUP) + fprintf(f, "%sCGroup=%s%s%s", prefix, color, c->cgroup, suffix); + s = NULL; + r = sd_bus_creds_get_unit(c, &s); + if (r != -ENODATA) + fprintf(f, "%sUnit=%s%s%s", prefix, color, strna(s), suffix); + s = NULL; + v = sd_bus_creds_get_slice(c, &s); + if (v != -ENODATA) + fprintf(f, "%sSlice=%s%s%s", prefix, color, strna(s), suffix); + s = NULL; + q = sd_bus_creds_get_user_unit(c, &s); + if (q != -ENODATA) + fprintf(f, "%sUserUnit=%s%s%s", prefix, color, strna(s), suffix); + s = NULL; + w = sd_bus_creds_get_user_slice(c, &s); + if (w != -ENODATA) + fprintf(f, "%sUserSlice=%s%s%s", prefix, color, strna(s), suffix); + s = NULL; + z = sd_bus_creds_get_session(c, &s); + if (z != -ENODATA) + fprintf(f, "%sSession=%s%s%s", prefix, color, strna(s), suffix); + + if (terse && ((c->mask & SD_BUS_CREDS_CGROUP) || r != -ENODATA || q != -ENODATA || v != -ENODATA || w != -ENODATA || z != -ENODATA)) + fputs("\n", f); + + r = sd_bus_creds_get_audit_login_uid(c, &audit_loginuid); + if (r >= 0) + fprintf(f, "%sAuditLoginUID=%s"UID_FMT"%s", prefix, color, audit_loginuid, suffix); + else if (r != -ENODATA) + fprintf(f, "%sAuditLoginUID=%sn/a%s", prefix, color, suffix); + q = sd_bus_creds_get_audit_session_id(c, &audit_sessionid); + if (q >= 0) + fprintf(f, "%sAuditSessionID=%s%"PRIu32"%s", prefix, color, audit_sessionid, suffix); + else if (q != -ENODATA) + fprintf(f, "%sAuditSessionID=%sn/a%s", prefix, color, suffix); + + if (terse && (r != -ENODATA || q != -ENODATA)) + fputs("\n", f); + + if (c->mask & SD_BUS_CREDS_UNIQUE_NAME) + fprintf(f, "%sUniqueName=%s%s%s", prefix, color, c->unique_name, suffix); + + if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) { + char **i; + + fprintf(f, "%sWellKnownNames=%s", prefix, color); + STRV_FOREACH(i, well_known) { + if (i != well_known) + fputc(' ', f); + + fputs(*i, f); + } + + fprintf(f, "%s", suffix); + } + + if (terse && (c->mask & SD_BUS_CREDS_UNIQUE_NAME || well_known)) + fputc('\n', f); + + dump_capabilities(c, f, "EffectiveCapabilities", terse, sd_bus_creds_has_effective_cap); + dump_capabilities(c, f, "PermittedCapabilities", terse, sd_bus_creds_has_permitted_cap); + dump_capabilities(c, f, "InheritableCapabilities", terse, sd_bus_creds_has_inheritable_cap); + dump_capabilities(c, f, "BoundingCapabilities", terse, sd_bus_creds_has_bounding_cap); + + return 0; +} + +/* + * For details about the file format, see: + * + * http://wiki.wireshark.org/Development/LibpcapFileFormat + */ + +typedef struct _packed_ pcap_hdr_s { + uint32_t magic_number; /* magic number */ + uint16_t version_major; /* major version number */ + uint16_t version_minor; /* minor version number */ + int32_t thiszone; /* GMT to local correction */ + uint32_t sigfigs; /* accuracy of timestamps */ + uint32_t snaplen; /* max length of captured packets, in octets */ + uint32_t network; /* data link type */ +} pcap_hdr_t ; + +typedef struct _packed_ pcaprec_hdr_s { + uint32_t ts_sec; /* timestamp seconds */ + uint32_t ts_usec; /* timestamp microseconds */ + uint32_t incl_len; /* number of octets of packet saved in file */ + uint32_t orig_len; /* actual length of packet */ +} pcaprec_hdr_t; + +int bus_pcap_header(size_t snaplen, FILE *f) { + + pcap_hdr_t hdr = { + .magic_number = 0xa1b2c3d4U, + .version_major = 2, + .version_minor = 4, + .thiszone = 0, /* UTC */ + .sigfigs = 0, + .network = 231, /* D-Bus */ + }; + + if (!f) + f = stdout; + + assert(snaplen > 0); + assert((size_t) (uint32_t) snaplen == snaplen); + + hdr.snaplen = (uint32_t) snaplen; + + fwrite(&hdr, 1, sizeof(hdr), f); + + return fflush_and_check(f); +} + +int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f) { + struct bus_body_part *part; + pcaprec_hdr_t hdr = {}; + struct timeval tv; + unsigned i; + size_t w; + + if (!f) + f = stdout; + + assert(m); + assert(snaplen > 0); + assert((size_t) (uint32_t) snaplen == snaplen); + + if (m->realtime != 0) + timeval_store(&tv, m->realtime); + else + assert_se(gettimeofday(&tv, NULL) >= 0); + + hdr.ts_sec = tv.tv_sec; + hdr.ts_usec = tv.tv_usec; + hdr.orig_len = BUS_MESSAGE_SIZE(m); + hdr.incl_len = MIN(hdr.orig_len, snaplen); + + /* write the pcap header */ + fwrite(&hdr, 1, sizeof(hdr), f); + + /* write the dbus header */ + w = MIN(BUS_MESSAGE_BODY_BEGIN(m), snaplen); + fwrite(m->header, 1, w, f); + snaplen -= w; + + /* write the dbus body */ + MESSAGE_FOREACH_PART(part, i, m) { + if (snaplen <= 0) + break; + + w = MIN(part->size, snaplen); + fwrite(part->data, 1, w, f); + snaplen -= w; + } + + return fflush_and_check(f); +} diff --git a/src/libsystemd/sd-bus/bus-dump.h b/src/libsystemd/sd-bus/bus-dump.h new file mode 100644 index 00000000..a1b67c6b --- /dev/null +++ b/src/libsystemd/sd-bus/bus-dump.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-bus.h" + +enum { + BUS_MESSAGE_DUMP_WITH_HEADER = 1 << 0, + BUS_MESSAGE_DUMP_SUBTREE_ONLY = 1 << 1, +}; + +int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags); + +int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse); + +int bus_pcap_header(size_t snaplen, FILE *f); +int bus_message_pcap_frame(sd_bus_message *m, size_t snaplen, FILE *f); diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c new file mode 100644 index 00000000..f760f0fd --- /dev/null +++ b/src/libsystemd/sd-bus/bus-error.c @@ -0,0 +1,610 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "errno-list.h" +#include "errno-util.h" +#include "string-util.h" +#include "util.h" + +BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = { + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Failed", EACCES), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoMemory", ENOMEM), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ServiceUnknown", EHOSTUNREACH), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NameHasNoOwner", ENXIO), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoReply", ETIMEDOUT), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.IOError", EIO), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.BadAddress", EADDRNOTAVAIL), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NotSupported", EOPNOTSUPP), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.LimitsExceeded", ENOBUFS), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AccessDenied", EACCES), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AuthFailed", EACCES), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InteractiveAuthorizationRequired", EACCES), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoServer", EHOSTDOWN), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Timeout", ETIMEDOUT), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoNetwork", ENONET), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.AddressInUse", EADDRINUSE), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Disconnected", ECONNRESET), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidArgs", EINVAL), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.FileNotFound", ENOENT), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.FileExists", EEXIST), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownMethod", EBADR), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownObject", EBADR), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownInterface", EBADR), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnknownProperty", EBADR), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.PropertyReadOnly", EROFS), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.UnixProcessIdUnknown", ESRCH), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidSignature", EINVAL), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InconsistentMessage", EBADMSG), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.TimedOut", ETIMEDOUT), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.MatchRuleInvalid", EINVAL), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.InvalidFileContent", EINVAL), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.MatchRuleNotFound", ENOENT), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown", ESRCH), + SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ObjectPathInUse", EBUSY), + SD_BUS_ERROR_MAP_END +}; + +/* GCC maps this magically to the beginning and end of the BUS_ERROR_MAP section */ +extern const sd_bus_error_map __start_SYSTEMD_BUS_ERROR_MAP[]; +extern const sd_bus_error_map __stop_SYSTEMD_BUS_ERROR_MAP[]; + +/* Additional maps registered with sd_bus_error_add_map() are in this + * NULL terminated array */ +static const sd_bus_error_map **additional_error_maps = NULL; + +static int bus_error_name_to_errno(const char *name) { + const sd_bus_error_map **map, *m; + const char *p; + int r; + + if (!name) + return EINVAL; + + p = startswith(name, "System.Error."); + if (p) { + r = errno_from_name(p); + if (r < 0) + return EIO; + + return r; + } + + if (additional_error_maps) + for (map = additional_error_maps; *map; map++) + for (m = *map;; m++) { + /* For additional error maps the end marker is actually the end marker */ + if (m->code == BUS_ERROR_MAP_END_MARKER) + break; + + if (streq(m->name, name)) + return m->code; + } + + m = ALIGN_TO_PTR(__start_SYSTEMD_BUS_ERROR_MAP, sizeof(void*)); + while (m < __stop_SYSTEMD_BUS_ERROR_MAP) { + /* For magic ELF error maps, the end marker might + * appear in the middle of things, since multiple maps + * might appear in the same section. Hence, let's skip + * over it, but realign the pointer to the next 8 byte + * boundary, which is the selected alignment for the + * arrays. */ + if (m->code == BUS_ERROR_MAP_END_MARKER) { + m = ALIGN_TO_PTR(m + 1, sizeof(void*)); + continue; + } + + if (streq(m->name, name)) + return m->code; + + m++; + } + + return EIO; +} + +static sd_bus_error errno_to_bus_error_const(int error) { + + if (error < 0) + error = -error; + + switch (error) { + + case ENOMEM: + return BUS_ERROR_OOM; + + case EPERM: + case EACCES: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_ACCESS_DENIED, "Access denied"); + + case EINVAL: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid argument"); + + case ESRCH: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, "No such process"); + + case ENOENT: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_NOT_FOUND, "File not found"); + + case EEXIST: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "File exists"); + + case ETIMEDOUT: + case ETIME: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_TIMEOUT, "Timed out"); + + case EIO: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_IO_ERROR, "Input/output error"); + + case ENETRESET: + case ECONNABORTED: + case ECONNRESET: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_DISCONNECTED, "Disconnected"); + + case EOPNOTSUPP: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NOT_SUPPORTED, "Not supported"); + + case EADDRNOTAVAIL: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_BAD_ADDRESS, "Address not available"); + + case ENOBUFS: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_LIMITS_EXCEEDED, "Limits exceeded"); + + case EADDRINUSE: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_ADDRESS_IN_USE, "Address in use"); + + case EBADMSG: + return SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Inconsistent message"); + } + + return SD_BUS_ERROR_NULL; +} + +static int errno_to_bus_error_name_new(int error, char **ret) { + const char *name; + char *n; + + if (error < 0) + error = -error; + + name = errno_to_name(error); + if (!name) + return 0; + + n = strjoin("System.Error.", name); + if (!n) + return -ENOMEM; + + *ret = n; + return 1; +} + +bool bus_error_is_dirty(sd_bus_error *e) { + if (!e) + return false; + + return e->name || e->message || e->_need_free != 0; +} + +_public_ void sd_bus_error_free(sd_bus_error *e) { + if (!e) + return; + + if (e->_need_free > 0) { + free((void*) e->name); + free((void*) e->message); + } + + *e = SD_BUS_ERROR_NULL; +} + +_public_ int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message) { + + if (!name) + return 0; + if (!e) + goto finish; + + assert_return(!bus_error_is_dirty(e), -EINVAL); + + e->name = strdup(name); + if (!e->name) { + *e = BUS_ERROR_OOM; + return -ENOMEM; + } + + if (message) + e->message = strdup(message); + + e->_need_free = 1; + +finish: + return -bus_error_name_to_errno(name); +} + +int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) { + + if (!name) + return 0; + + if (e) { + assert_return(!bus_error_is_dirty(e), -EINVAL); + + e->name = strdup(name); + if (!e->name) { + *e = BUS_ERROR_OOM; + return -ENOMEM; + } + + /* If we hit OOM on formatting the pretty message, we ignore + * this, since we at least managed to write the error name */ + if (format) + (void) vasprintf((char**) &e->message, format, ap); + + e->_need_free = 1; + } + + return -bus_error_name_to_errno(name); +} + +_public_ int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...) { + + if (format) { + int r; + va_list ap; + + va_start(ap, format); + r = bus_error_setfv(e, name, format, ap); + va_end(ap); + + return r; + } + + return sd_bus_error_set(e, name, NULL); +} + +_public_ int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e) { + + if (!sd_bus_error_is_set(e)) + return 0; + if (!dest) + goto finish; + + assert_return(!bus_error_is_dirty(dest), -EINVAL); + + /* + * _need_free < 0 indicates that the error is temporarily const, needs deep copying + * _need_free == 0 indicates that the error is perpetually const, needs no deep copying + * _need_free > 0 indicates that the error is fully dynamic, needs deep copying + */ + + if (e->_need_free == 0) + *dest = *e; + else { + dest->name = strdup(e->name); + if (!dest->name) { + *dest = BUS_ERROR_OOM; + return -ENOMEM; + } + + if (e->message) + dest->message = strdup(e->message); + + dest->_need_free = 1; + } + +finish: + return -bus_error_name_to_errno(e->name); +} + +_public_ int sd_bus_error_move(sd_bus_error *dest, sd_bus_error *e) { + int r; + + if (!sd_bus_error_is_set(e)) { + + if (dest) + *dest = SD_BUS_ERROR_NULL; + + return 0; + } + + r = -bus_error_name_to_errno(e->name); + + if (dest) { + *dest = *e; + *e = SD_BUS_ERROR_NULL; + } else + sd_bus_error_free(e); + + return r; +} + +_public_ int sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message) { + if (!name) + return 0; + if (!e) + goto finish; + + assert_return(!bus_error_is_dirty(e), -EINVAL); + + *e = SD_BUS_ERROR_MAKE_CONST(name, message); + +finish: + return -bus_error_name_to_errno(name); +} + +_public_ int sd_bus_error_is_set(const sd_bus_error *e) { + if (!e) + return 0; + + return !!e->name; +} + +_public_ int sd_bus_error_has_name(const sd_bus_error *e, const char *name) { + if (!e) + return 0; + + return streq_ptr(e->name, name); +} + +_public_ int sd_bus_error_get_errno(const sd_bus_error* e) { + if (!e) + return 0; + + if (!e->name) + return 0; + + return bus_error_name_to_errno(e->name); +} + +static void bus_error_strerror(sd_bus_error *e, int error) { + size_t k = 64; + char *m; + + assert(e); + + for (;;) { + char *x; + + m = new(char, k); + if (!m) + return; + + errno = 0; + x = strerror_r(error, m, k); + if (errno == ERANGE || strlen(x) >= k - 1) { + free(m); + k *= 2; + continue; + } + + if (errno) { + free(m); + return; + } + + if (x == m) { + if (e->_need_free > 0) { + /* Error is already dynamic, let's just update the message */ + free((char*) e->message); + e->message = x; + + } else { + char *t; + /* Error was const so far, let's make it dynamic, if we can */ + + t = strdup(e->name); + if (!t) { + free(m); + return; + } + + e->_need_free = 1; + e->name = t; + e->message = x; + } + } else { + free(m); + + if (e->_need_free > 0) { + char *t; + + /* Error is dynamic, let's hence make the message also dynamic */ + t = strdup(x); + if (!t) + return; + + free((char*) e->message); + e->message = t; + } else { + /* Error is const, hence we can just override */ + e->message = x; + } + } + + return; + } +} + +_public_ int sd_bus_error_set_errno(sd_bus_error *e, int error) { + + if (error < 0) + error = -error; + + if (!e) + return -error; + if (error == 0) + return -error; + + assert_return(!bus_error_is_dirty(e), -EINVAL); + + /* First, try a const translation */ + *e = errno_to_bus_error_const(error); + + if (!sd_bus_error_is_set(e)) { + int k; + + /* If that didn't work, try a dynamic one. */ + + k = errno_to_bus_error_name_new(error, (char**) &e->name); + if (k > 0) + e->_need_free = 1; + else if (k < 0) { + *e = BUS_ERROR_OOM; + return -error; + } else + *e = BUS_ERROR_FAILED; + } + + /* Now, fill in the message from strerror() if we can */ + bus_error_strerror(e, error); + return -error; +} + +_public_ int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) { + PROTECT_ERRNO; + int r; + + if (error < 0) + error = -error; + + if (!e) + return -error; + if (error == 0) + return 0; + + assert_return(!bus_error_is_dirty(e), -EINVAL); + + /* First, try a const translation */ + *e = errno_to_bus_error_const(error); + + if (!sd_bus_error_is_set(e)) { + int k; + + /* If that didn't work, try a dynamic one */ + + k = errno_to_bus_error_name_new(error, (char**) &e->name); + if (k > 0) + e->_need_free = 1; + else if (k < 0) { + *e = BUS_ERROR_OOM; + return -ENOMEM; + } else + *e = BUS_ERROR_FAILED; + } + + if (format) { + char *m; + + /* Then, let's try to fill in the supplied message */ + + errno = error; /* Make sure that %m resolves to the specified error */ + r = vasprintf(&m, format, ap); + if (r >= 0) { + + if (e->_need_free <= 0) { + char *t; + + t = strdup(e->name); + if (t) { + e->_need_free = 1; + e->name = t; + e->message = m; + return -error; + } + + free(m); + } else { + free((char*) e->message); + e->message = m; + return -error; + } + } + } + + /* If that didn't work, use strerror() for the message */ + bus_error_strerror(e, error); + return -error; +} + +_public_ int sd_bus_error_set_errnof(sd_bus_error *e, int error, const char *format, ...) { + int r; + + if (error < 0) + error = -error; + + if (!e) + return -error; + if (error == 0) + return 0; + + assert_return(!bus_error_is_dirty(e), -EINVAL); + + if (format) { + va_list ap; + + va_start(ap, format); + r = sd_bus_error_set_errnofv(e, error, format, ap); + va_end(ap); + + return r; + } + + return sd_bus_error_set_errno(e, error); +} + +const char *bus_error_message(const sd_bus_error *e, int error) { + + if (e) { + /* Sometimes, the D-Bus server is a little bit too verbose with + * its error messages, so let's override them here */ + if (sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED)) + return "Access denied"; + + if (e->message) + return e->message; + } + + if (error < 0) + error = -error; + + return strerror_safe(error); +} + +static bool map_ok(const sd_bus_error_map *map) { + for (; map->code != BUS_ERROR_MAP_END_MARKER; map++) + if (!map->name || map->code <=0) + return false; + return true; +} + +_public_ int sd_bus_error_add_map(const sd_bus_error_map *map) { + const sd_bus_error_map **maps = NULL; + unsigned n = 0; + + assert_return(map, -EINVAL); + assert_return(map_ok(map), -EINVAL); + + if (additional_error_maps) + for (; additional_error_maps[n] != NULL; n++) + if (additional_error_maps[n] == map) + return 0; + + maps = reallocarray(additional_error_maps, n + 2, sizeof(struct sd_bus_error_map*)); + if (!maps) + return -ENOMEM; + + maps[n] = map; + maps[n+1] = NULL; + + additional_error_maps = maps; + return 1; +} diff --git a/src/libsystemd/sd-bus/bus-error.h b/src/libsystemd/sd-bus/bus-error.h new file mode 100644 index 00000000..a6523e57 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-error.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" + +#include "macro.h" + +bool bus_error_is_dirty(sd_bus_error *e); + +const char *bus_error_message(const sd_bus_error *e, int error); + +int bus_error_setfv(sd_bus_error *e, const char *name, const char *format, va_list ap) _printf_(3,0); +int bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) _printf_(3,0); + +#define BUS_ERROR_OOM SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_MEMORY, "Out of memory") +#define BUS_ERROR_FAILED SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FAILED, "Operation failed") + +/* + * There are two ways to register error maps with the error translation + * logic: by using BUS_ERROR_MAP_ELF_REGISTER, which however only + * works when linked into the same ELF module, or via + * sd_bus_error_add_map() which is the official, external API, that + * works from any module. + * + * Note that BUS_ERROR_MAP_ELF_REGISTER has to be used as decorator in + * the bus error table, and BUS_ERROR_MAP_ELF_USE has to be used at + * least once per compilation unit (i.e. per library), to ensure that + * the error map is really added to the final binary. + */ + +#define BUS_ERROR_MAP_ELF_REGISTER \ + _section_("SYSTEMD_BUS_ERROR_MAP") \ + _used_ \ + _alignptr_ \ + _variable_no_sanitize_address_ + +#define BUS_ERROR_MAP_ELF_USE(errors) \ + extern const sd_bus_error_map errors[]; \ + _used_ \ + static const sd_bus_error_map * const CONCATENATE(errors ## _copy_, __COUNTER__) = errors; + +/* We use something exotic as end marker, to ensure people build the + * maps using the macsd-ros. */ +#define BUS_ERROR_MAP_END_MARKER -'x' + +BUS_ERROR_MAP_ELF_USE(bus_standard_errors); diff --git a/src/libsystemd/sd-bus/bus-gvariant.c b/src/libsystemd/sd-bus/bus-gvariant.c new file mode 100644 index 00000000..ba503b32 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-gvariant.c @@ -0,0 +1,299 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "bus-gvariant.h" +#include "bus-signature.h" +#include "bus-type.h" + +int bus_gvariant_get_size(const char *signature) { + const char *p; + int sum = 0, r; + + /* For fixed size structs. Fails for variable size structs. */ + + p = signature; + while (*p != 0) { + size_t n; + + r = signature_element_length(p, &n); + if (r < 0) + return r; + else { + char t[n+1]; + + memcpy(t, p, n); + t[n] = 0; + + r = bus_gvariant_get_alignment(t); + if (r < 0) + return r; + + sum = ALIGN_TO(sum, r); + } + + switch (*p) { + + case SD_BUS_TYPE_BOOLEAN: + case SD_BUS_TYPE_BYTE: + sum += 1; + break; + + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: + sum += 2; + break; + + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + case SD_BUS_TYPE_UNIX_FD: + sum += 4; + break; + + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: + case SD_BUS_TYPE_DOUBLE: + sum += 8; + break; + + case SD_BUS_TYPE_STRUCT_BEGIN: + case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { + if (n == 2) { + /* unary type () has fixed size of 1 */ + r = 1; + } else { + char t[n-1]; + + memcpy(t, p + 1, n - 2); + t[n - 2] = 0; + + r = bus_gvariant_get_size(t); + if (r < 0) + return r; + } + + sum += r; + break; + } + + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: + case SD_BUS_TYPE_ARRAY: + case SD_BUS_TYPE_VARIANT: + return -EINVAL; + + default: + assert_not_reached("Unknown signature type"); + } + + p += n; + } + + r = bus_gvariant_get_alignment(signature); + if (r < 0) + return r; + + return ALIGN_TO(sum, r); +} + +int bus_gvariant_get_alignment(const char *signature) { + size_t alignment = 1; + const char *p; + int r; + + p = signature; + while (*p != 0 && alignment < 8) { + size_t n; + int a; + + r = signature_element_length(p, &n); + if (r < 0) + return r; + + switch (*p) { + + case SD_BUS_TYPE_BYTE: + case SD_BUS_TYPE_BOOLEAN: + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: + a = 1; + break; + + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: + a = 2; + break; + + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + case SD_BUS_TYPE_UNIX_FD: + a = 4; + break; + + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: + case SD_BUS_TYPE_DOUBLE: + case SD_BUS_TYPE_VARIANT: + a = 8; + break; + + case SD_BUS_TYPE_ARRAY: { + char t[n]; + + memcpy(t, p + 1, n - 1); + t[n - 1] = 0; + + a = bus_gvariant_get_alignment(t); + break; + } + + case SD_BUS_TYPE_STRUCT_BEGIN: + case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { + char t[n-1]; + + memcpy(t, p + 1, n - 2); + t[n - 2] = 0; + + a = bus_gvariant_get_alignment(t); + break; + } + + default: + assert_not_reached("Unknown signature type"); + } + + if (a < 0) + return a; + + assert(a > 0 && a <= 8); + if ((size_t) a > alignment) + alignment = (size_t) a; + + p += n; + } + + return alignment; +} + +int bus_gvariant_is_fixed_size(const char *signature) { + const char *p; + int r; + + assert(signature); + + p = signature; + while (*p != 0) { + size_t n; + + r = signature_element_length(p, &n); + if (r < 0) + return r; + + switch (*p) { + + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: + case SD_BUS_TYPE_ARRAY: + case SD_BUS_TYPE_VARIANT: + return 0; + + case SD_BUS_TYPE_BYTE: + case SD_BUS_TYPE_BOOLEAN: + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + case SD_BUS_TYPE_UNIX_FD: + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: + case SD_BUS_TYPE_DOUBLE: + break; + + case SD_BUS_TYPE_STRUCT_BEGIN: + case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { + char t[n-1]; + + memcpy(t, p + 1, n - 2); + t[n - 2] = 0; + + r = bus_gvariant_is_fixed_size(t); + if (r <= 0) + return r; + break; + } + + default: + assert_not_reached("Unknown signature type"); + } + + p += n; + } + + return true; +} + +size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) { + if (sz + extra <= 0xFF) + return 1; + else if (sz + extra*2 <= 0xFFFF) + return 2; + else if (sz + extra*4 <= 0xFFFFFFFF) + return 4; + else + return 8; +} + +size_t bus_gvariant_read_word_le(void *p, size_t sz) { + union { + uint16_t u16; + uint32_t u32; + uint64_t u64; + } x; + + assert(p); + + if (sz == 1) + return *(uint8_t*) p; + + memcpy(&x, p, sz); + + if (sz == 2) + return le16toh(x.u16); + else if (sz == 4) + return le32toh(x.u32); + else if (sz == 8) + return le64toh(x.u64); + + assert_not_reached("unknown word width"); +} + +void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) { + union { + uint16_t u16; + uint32_t u32; + uint64_t u64; + } x; + + assert(p); + assert(sz == 8 || (value < (1ULL << (sz*8)))); + + if (sz == 1) { + *(uint8_t*) p = value; + return; + } else if (sz == 2) + x.u16 = htole16((uint16_t) value); + else if (sz == 4) + x.u32 = htole32((uint32_t) value); + else if (sz == 8) + x.u64 = htole64((uint64_t) value); + else + assert_not_reached("unknown word width"); + + memcpy(p, &x, sz); +} diff --git a/src/libsystemd/sd-bus/bus-gvariant.h b/src/libsystemd/sd-bus/bus-gvariant.h new file mode 100644 index 00000000..644b5f4b --- /dev/null +++ b/src/libsystemd/sd-bus/bus-gvariant.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "macro.h" + +int bus_gvariant_get_size(const char *signature) _pure_; +int bus_gvariant_get_alignment(const char *signature) _pure_; +int bus_gvariant_is_fixed_size(const char *signature) _pure_; + +size_t bus_gvariant_determine_word_size(size_t sz, size_t extra); +void bus_gvariant_write_word_le(void *p, size_t sz, size_t value); +size_t bus_gvariant_read_word_le(void *p, size_t sz); diff --git a/src/libsystemd/sd-bus/bus-internal.c b/src/libsystemd/sd-bus/bus-internal.c new file mode 100644 index 00000000..d5f8c6db --- /dev/null +++ b/src/libsystemd/sd-bus/bus-internal.c @@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "hexdecoct.h" +#include "string-util.h" + +bool object_path_is_valid(const char *p) { + const char *q; + bool slash; + + if (!p) + return false; + + if (p[0] != '/') + return false; + + if (p[1] == 0) + return true; + + for (slash = true, q = p+1; *q; q++) + if (*q == '/') { + if (slash) + return false; + + slash = true; + } else { + bool good; + + good = + (*q >= 'a' && *q <= 'z') || + (*q >= 'A' && *q <= 'Z') || + (*q >= '0' && *q <= '9') || + *q == '_'; + + if (!good) + return false; + + slash = false; + } + + if (slash) + return false; + + return (q - p) <= BUS_PATH_SIZE_MAX; +} + +char* object_path_startswith(const char *a, const char *b) { + const char *p; + + if (!object_path_is_valid(a) || + !object_path_is_valid(b)) + return NULL; + + if (streq(b, "/")) + return (char*) a + 1; + + p = startswith(a, b); + if (!p) + return NULL; + + if (*p == 0) + return (char*) p; + + if (*p == '/') + return (char*) p + 1; + + return NULL; +} + +bool interface_name_is_valid(const char *p) { + const char *q; + bool dot, found_dot = false; + + if (isempty(p)) + return false; + + for (dot = true, q = p; *q; q++) + if (*q == '.') { + if (dot) + return false; + + found_dot = dot = true; + } else { + bool good; + + good = + (*q >= 'a' && *q <= 'z') || + (*q >= 'A' && *q <= 'Z') || + (!dot && *q >= '0' && *q <= '9') || + *q == '_'; + + if (!good) + return false; + + dot = false; + } + + if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH) + return false; + + if (dot) + return false; + + if (!found_dot) + return false; + + return true; +} + +bool service_name_is_valid(const char *p) { + const char *q; + bool dot, found_dot = false, unique; + + if (isempty(p)) + return false; + + unique = p[0] == ':'; + + for (dot = true, q = unique ? p+1 : p; *q; q++) + if (*q == '.') { + if (dot) + return false; + + found_dot = dot = true; + } else { + bool good; + + good = + (*q >= 'a' && *q <= 'z') || + (*q >= 'A' && *q <= 'Z') || + ((!dot || unique) && *q >= '0' && *q <= '9') || + IN_SET(*q, '_', '-'); + + if (!good) + return false; + + dot = false; + } + + if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH) + return false; + + if (dot) + return false; + + if (!found_dot) + return false; + + return true; +} + +bool member_name_is_valid(const char *p) { + const char *q; + + if (isempty(p)) + return false; + + for (q = p; *q; q++) { + bool good; + + good = + (*q >= 'a' && *q <= 'z') || + (*q >= 'A' && *q <= 'Z') || + (*q >= '0' && *q <= '9') || + *q == '_'; + + if (!good) + return false; + } + + if (q - p > SD_BUS_MAXIMUM_NAME_LENGTH) + return false; + + return true; +} + +/* + * Complex pattern match + * This checks whether @a is a 'complex-prefix' of @b, or @b is a + * 'complex-prefix' of @a, based on strings that consist of labels with @c as + * separator. This function returns true if: + * - both strings are equal + * - either is a prefix of the other and ends with @c + * The second rule makes sure that either string needs to be fully included in + * the other, and the string which is considered the prefix needs to end with a + * separator. + */ +static bool complex_pattern_check(char c, const char *a, const char *b) { + bool separator = false; + + if (!a && !b) + return true; + + if (!a || !b) + return false; + + for (;;) { + if (*a != *b) + return (separator && (*a == 0 || *b == 0)); + + if (*a == 0) + return true; + + separator = *a == c; + + a++, b++; + } +} + +bool namespace_complex_pattern(const char *pattern, const char *value) { + return complex_pattern_check('.', pattern, value); +} + +bool path_complex_pattern(const char *pattern, const char *value) { + return complex_pattern_check('/', pattern, value); +} + +/* + * Simple pattern match + * This checks whether @a is a 'simple-prefix' of @b, based on strings that + * consist of labels with @c as separator. This function returns true, if: + * - if @a and @b are equal + * - if @a is a prefix of @b, and the first following character in @b (or the + * last character in @a) is @c + * The second rule basically makes sure that if @a is a prefix of @b, then @b + * must follow with a new label separated by @c. It cannot extend the label. + */ +static bool simple_pattern_check(char c, const char *a, const char *b) { + bool separator = false; + + if (!a && !b) + return true; + + if (!a || !b) + return false; + + for (;;) { + if (*a != *b) + return *a == 0 && (*b == c || separator); + + if (*a == 0) + return true; + + separator = *a == c; + + a++, b++; + } +} + +bool namespace_simple_pattern(const char *pattern, const char *value) { + return simple_pattern_check('.', pattern, value); +} + +bool path_simple_pattern(const char *pattern, const char *value) { + return simple_pattern_check('/', pattern, value); +} + +int bus_message_type_from_string(const char *s, uint8_t *u) { + if (streq(s, "signal")) + *u = SD_BUS_MESSAGE_SIGNAL; + else if (streq(s, "method_call")) + *u = SD_BUS_MESSAGE_METHOD_CALL; + else if (streq(s, "error")) + *u = SD_BUS_MESSAGE_METHOD_ERROR; + else if (streq(s, "method_return")) + *u = SD_BUS_MESSAGE_METHOD_RETURN; + else + return -EINVAL; + + return 0; +} + +const char *bus_message_type_to_string(uint8_t u) { + if (u == SD_BUS_MESSAGE_SIGNAL) + return "signal"; + else if (u == SD_BUS_MESSAGE_METHOD_CALL) + return "method_call"; + else if (u == SD_BUS_MESSAGE_METHOD_ERROR) + return "error"; + else if (u == SD_BUS_MESSAGE_METHOD_RETURN) + return "method_return"; + else + return NULL; +} + +char *bus_address_escape(const char *v) { + const char *a; + char *r, *b; + + r = new(char, strlen(v)*3+1); + if (!r) + return NULL; + + for (a = v, b = r; *a; a++) { + + if ((*a >= '0' && *a <= '9') || + (*a >= 'a' && *a <= 'z') || + (*a >= 'A' && *a <= 'Z') || + strchr("_-/.", *a)) + *(b++) = *a; + else { + *(b++) = '%'; + *(b++) = hexchar(*a >> 4); + *(b++) = hexchar(*a & 0xF); + } + } + + *b = 0; + return r; +} + +int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) { + assert(m); + + if (r < 0) { + if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) + sd_bus_reply_method_errno(m, r, error); + + } else if (sd_bus_error_is_set(error)) { + if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) + sd_bus_reply_method_error(m, error); + } else + return r; + + log_debug("Failed to process message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s: %s", + bus_message_type_to_string(m->header->type), + strna(sd_bus_message_get_sender(m)), + strna(sd_bus_message_get_destination(m)), + strna(sd_bus_message_get_path(m)), + strna(sd_bus_message_get_interface(m)), + strna(sd_bus_message_get_member(m)), + BUS_MESSAGE_COOKIE(m), + m->reply_cookie, + strna(m->root_container.signature), + strna(m->error.name), + strna(m->error.message), + bus_error_message(error, r)); + + return 1; +} diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h new file mode 100644 index 00000000..352a419e --- /dev/null +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -0,0 +1,415 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" + +#include "bus-error.h" +#include "bus-kernel.h" +#include "bus-match.h" +#include "def.h" +#include "hashmap.h" +#include "list.h" +#include "prioq.h" +#include "socket-util.h" +#include "time-util.h" + +/* Note that we use the new /run prefix here (instead of /var/run) since we require them to be aliases and + * that way we become independent of /var being mounted */ +#define DEFAULT_SYSTEM_BUS_ADDRESS "unix:path=/run/dbus/system_bus_socket" +#define DEFAULT_USER_BUS_ADDRESS_FMT "unix:path=%s/bus" + +struct reply_callback { + sd_bus_message_handler_t callback; + usec_t timeout_usec; /* this is a relative timeout until we reach the BUS_HELLO state, and an absolute one right after */ + uint64_t cookie; + unsigned prioq_idx; +}; + +struct filter_callback { + sd_bus_message_handler_t callback; + + unsigned last_iteration; + + LIST_FIELDS(struct filter_callback, callbacks); +}; + +struct match_callback { + sd_bus_message_handler_t callback; + sd_bus_message_handler_t install_callback; + + sd_bus_slot *install_slot; /* The AddMatch() call */ + + unsigned last_iteration; + + /* Don't dispatch this slot with with messages that arrived in any iteration before or at the this + * one. We use this to ensure that matches don't apply "retroactively" and thus can confuse the + * caller: matches will only match incoming messages from the moment on the match was installed. */ + uint64_t after; + + char *match_string; + + struct bus_match_node *match_node; +}; + +struct node { + char *path; + struct node *parent; + LIST_HEAD(struct node, child); + LIST_FIELDS(struct node, siblings); + + LIST_HEAD(struct node_callback, callbacks); + LIST_HEAD(struct node_vtable, vtables); + LIST_HEAD(struct node_enumerator, enumerators); + LIST_HEAD(struct node_object_manager, object_managers); +}; + +struct node_callback { + struct node *node; + + bool is_fallback:1; + unsigned last_iteration; + + sd_bus_message_handler_t callback; + + LIST_FIELDS(struct node_callback, callbacks); +}; + +struct node_enumerator { + struct node *node; + + sd_bus_node_enumerator_t callback; + + unsigned last_iteration; + + LIST_FIELDS(struct node_enumerator, enumerators); +}; + +struct node_object_manager { + struct node *node; + + LIST_FIELDS(struct node_object_manager, object_managers); +}; + +struct node_vtable { + struct node *node; + + bool is_fallback:1; + unsigned last_iteration; + + char *interface; + const sd_bus_vtable *vtable; + sd_bus_object_find_t find; + + LIST_FIELDS(struct node_vtable, vtables); +}; + +struct vtable_member { + const char *path; + const char *interface; + const char *member; + struct node_vtable *parent; + unsigned last_iteration; + const sd_bus_vtable *vtable; +}; + +typedef enum BusSlotType { + BUS_REPLY_CALLBACK, + BUS_FILTER_CALLBACK, + BUS_MATCH_CALLBACK, + BUS_NODE_CALLBACK, + BUS_NODE_ENUMERATOR, + BUS_NODE_VTABLE, + BUS_NODE_OBJECT_MANAGER, + _BUS_SLOT_INVALID = -1, +} BusSlotType; + +struct sd_bus_slot { + unsigned n_ref; + BusSlotType type:5; + + /* Slots can be "floating" or not. If they are not floating (the usual case) then they reference the bus object + * they are associated with. This means the bus object stays allocated at least as long as there is a slot + * around associated with it. If it is floating, then the slot's lifecycle is bound to the lifecycle of the + * bus: it will be disconnected from the bus when the bus is destroyed, and it keeping the slot reffed hence + * won't mean the bus stays reffed too. Internally this means the reference direction is reversed: floating + * slots objects are referenced by the bus object, and not vice versa. */ + bool floating:1; + + bool match_added:1; + + sd_bus *bus; + void *userdata; + sd_bus_destroy_t destroy_callback; + + char *description; + + LIST_FIELDS(sd_bus_slot, slots); + + union { + struct reply_callback reply_callback; + struct filter_callback filter_callback; + struct match_callback match_callback; + struct node_callback node_callback; + struct node_enumerator node_enumerator; + struct node_object_manager node_object_manager; + struct node_vtable node_vtable; + }; +}; + +enum bus_state { + BUS_UNSET, + BUS_WATCH_BIND, /* waiting for the socket to appear via inotify */ + BUS_OPENING, /* the kernel's connect() is still not ready */ + BUS_AUTHENTICATING, /* we are currently in the "SASL" authorization phase of dbus */ + BUS_HELLO, /* we are waiting for the Hello() response */ + BUS_RUNNING, + BUS_CLOSING, + BUS_CLOSED, + _BUS_STATE_MAX, +}; + +static inline bool BUS_IS_OPEN(enum bus_state state) { + return state > BUS_UNSET && state < BUS_CLOSING; +} + +enum bus_auth { + _BUS_AUTH_INVALID, + BUS_AUTH_EXTERNAL, + BUS_AUTH_ANONYMOUS +}; + +struct sd_bus { + unsigned n_ref; + + enum bus_state state; + int input_fd, output_fd; + int inotify_fd; + int message_version; + int message_endian; + + bool can_fds:1; + bool bus_client:1; + bool ucred_valid:1; + bool is_server:1; + bool anonymous_auth:1; + bool prefer_readv:1; + bool prefer_writev:1; + bool match_callbacks_modified:1; + bool filter_callbacks_modified:1; + bool nodes_modified:1; + bool trusted:1; + bool manual_peer_interface:1; + bool is_system:1; + bool is_user:1; + bool allow_interactive_authorization:1; + bool exit_on_disconnect:1; + bool exited:1; + bool exit_triggered:1; + bool is_local:1; + bool watch_bind:1; + bool is_monitor:1; + bool accept_fd:1; + bool attach_timestamp:1; + bool connected_signal:1; + bool close_on_exit:1; + + signed int use_memfd:2; + + void *rbuffer; + size_t rbuffer_size; + + sd_bus_message **rqueue; + size_t rqueue_size; + size_t rqueue_allocated; + + sd_bus_message **wqueue; + size_t wqueue_size; + size_t windex; + size_t wqueue_allocated; + + uint64_t cookie; + uint64_t read_counter; /* A counter for each incoming msg */ + + char *unique_name; + uint64_t unique_id; + + struct bus_match_node match_callbacks; + Prioq *reply_callbacks_prioq; + OrderedHashmap *reply_callbacks; + LIST_HEAD(struct filter_callback, filter_callbacks); + + Hashmap *nodes; + Hashmap *vtable_methods; + Hashmap *vtable_properties; + + union sockaddr_union sockaddr; + socklen_t sockaddr_size; + + pid_t nspid; + char *machine; + + sd_id128_t server_id; + + char *address; + unsigned address_index; + + int last_connect_error; + + enum bus_auth auth; + unsigned auth_index; + struct iovec auth_iovec[3]; + size_t auth_rbegin; + char *auth_buffer; + usec_t auth_timeout; + + struct ucred ucred; + char *label; + gid_t *groups; + size_t n_groups; + + uint64_t creds_mask; + + int *fds; + size_t n_fds; + + char *exec_path; + char **exec_argv; + + /* We do locking around the memfd cache, since we want to + * allow people to process a sd_bus_message in a different + * thread then it was generated on and free it there. Since + * adding something to the memfd cache might happen when a + * message is released, we hence need to protect this bit with + * a mutex. */ + pthread_mutex_t memfd_cache_mutex; + struct memfd_cache memfd_cache[MEMFD_CACHE_MAX]; + unsigned n_memfd_cache; + + pid_t original_pid; + pid_t busexec_pid; + + unsigned iteration_counter; + + sd_event_source *input_io_event_source; + sd_event_source *output_io_event_source; + sd_event_source *time_event_source; + sd_event_source *quit_event_source; + sd_event_source *inotify_event_source; + sd_event *event; + int event_priority; + + pid_t tid; + + sd_bus_message *current_message; + sd_bus_slot *current_slot; + sd_bus_message_handler_t current_handler; + void *current_userdata; + + sd_bus **default_bus_ptr; + + char *description; + char *patch_sender; + + sd_bus_track *track_queue; + + LIST_HEAD(sd_bus_slot, slots); + LIST_HEAD(sd_bus_track, tracks); + + int *inotify_watches; + size_t n_inotify_watches; + + /* zero means use value specified by $SYSTEMD_BUS_TIMEOUT= environment variable or built-in default */ + usec_t method_call_timeout; +}; + +/* For method calls we timeout at 25s, like in the D-Bus reference implementation */ +#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) + +/* For the authentication phase we grant 90s, to provide extra room during boot, when RNGs and such are not filled up + * with enough entropy yet and might delay the boot */ +#define BUS_AUTH_TIMEOUT ((usec_t) DEFAULT_TIMEOUT_USEC) + +#define BUS_WQUEUE_MAX (384*1024) +#define BUS_RQUEUE_MAX (384*1024) + +#define BUS_MESSAGE_SIZE_MAX (128*1024*1024) +#define BUS_AUTH_SIZE_MAX (64*1024) +/* Note that the D-Bus specification states that bus paths shall have no size limit. We enforce here one + * anyway, since truly unbounded strings are a security problem. The limit we pick is relatively large however, + * to not clash unnecessarily with real-life applications. */ +#define BUS_PATH_SIZE_MAX (64*1024) + +#define BUS_CONTAINER_DEPTH 128 + +/* Defined by the specification as maximum size of an array in bytes */ +#define BUS_ARRAY_MAX_SIZE 67108864 + +#define BUS_FDS_MAX 1024 + +#define BUS_EXEC_ARGV_MAX 256 + +bool interface_name_is_valid(const char *p) _pure_; +bool service_name_is_valid(const char *p) _pure_; +bool member_name_is_valid(const char *p) _pure_; +bool object_path_is_valid(const char *p) _pure_; +char *object_path_startswith(const char *a, const char *b) _pure_; + +bool namespace_complex_pattern(const char *pattern, const char *value) _pure_; +bool path_complex_pattern(const char *pattern, const char *value) _pure_; + +bool namespace_simple_pattern(const char *pattern, const char *value) _pure_; +bool path_simple_pattern(const char *pattern, const char *value) _pure_; + +int bus_message_type_from_string(const char *s, uint8_t *u) _pure_; +const char *bus_message_type_to_string(uint8_t u) _pure_; + +#define error_name_is_valid interface_name_is_valid + +sd_bus *bus_resolve(sd_bus *bus); + +int bus_ensure_running(sd_bus *bus); +int bus_start_running(sd_bus *bus); +int bus_next_address(sd_bus *bus); + +int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m); + +int bus_rqueue_make_room(sd_bus *bus); + +bool bus_pid_changed(sd_bus *bus); + +char *bus_address_escape(const char *v); + +int bus_attach_io_events(sd_bus *b); +int bus_attach_inotify_event(sd_bus *b); + +void bus_close_inotify_fd(sd_bus *b); +void bus_close_io_fds(sd_bus *b); + +#define OBJECT_PATH_FOREACH_PREFIX(prefix, path) \ + for (char *_slash = ({ strcpy((prefix), (path)); streq((prefix), "/") ? NULL : strrchr((prefix), '/'); }) ; \ + _slash && ((_slash[(_slash) == (prefix)] = 0), true); \ + _slash = streq((prefix), "/") ? NULL : strrchr((prefix), '/')) + +/* If we are invoking callbacks of a bus object, ensure unreffing the + * bus from the callback doesn't destroy the object we are working on */ +#define BUS_DONT_DESTROY(bus) \ + _cleanup_(sd_bus_unrefp) _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus) + +int bus_set_address_system(sd_bus *bus); +int bus_set_address_user(sd_bus *bus); +int bus_set_address_system_remote(sd_bus *b, const char *host); +int bus_set_address_system_machine(sd_bus *b, const char *machine); + +int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error); + +#define bus_assert_return(expr, r, error) \ + do { \ + if (!assert_log(expr, #expr)) \ + return sd_bus_error_set_errno(error, r); \ + } while (false) + +void bus_enter_closing(sd_bus *bus); + +void bus_set_state(sd_bus *bus, enum bus_state state); diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c new file mode 100644 index 00000000..e8934489 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-introspect.c @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-internal.h" +#include "bus-introspect.h" +#include "bus-objects.h" +#include "bus-protocol.h" +#include "bus-signature.h" +#include "fd-util.h" +#include "fileio.h" +#include "memory-util.h" +#include "string-util.h" + +int introspect_begin(struct introspect *i, bool trusted) { + assert(i); + + zero(*i); + i->trusted = trusted; + + i->f = open_memstream_unlocked(&i->introspection, &i->size); + if (!i->f) + return -ENOMEM; + + fputs(BUS_INTROSPECT_DOCTYPE + "\n", i->f); + + return 0; +} + +int introspect_write_default_interfaces(struct introspect *i, bool object_manager) { + assert(i); + + fputs(BUS_INTROSPECT_INTERFACE_PEER + BUS_INTROSPECT_INTERFACE_INTROSPECTABLE + BUS_INTROSPECT_INTERFACE_PROPERTIES, i->f); + + if (object_manager) + fputs(BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER, i->f); + + return 0; +} + +int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix) { + char *node; + + assert(i); + assert(prefix); + + while ((node = set_steal_first(s))) { + const char *e; + + e = object_path_startswith(node, prefix); + if (e && e[0]) + fprintf(i->f, " \n", e); + + free(node); + } + + return 0; +} + +static void introspect_write_flags(struct introspect *i, int type, uint64_t flags) { + if (flags & SD_BUS_VTABLE_DEPRECATED) + fputs(" \n", i->f); + + if (type == _SD_BUS_VTABLE_METHOD && (flags & SD_BUS_VTABLE_METHOD_NO_REPLY)) + fputs(" \n", i->f); + + if (IN_SET(type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY)) { + if (flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT) + fputs(" \n", i->f); + + if (flags & SD_BUS_VTABLE_PROPERTY_CONST) + fputs(" \n", i->f); + else if (flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) + fputs(" \n", i->f); + else if (!(flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) + fputs(" \n", i->f); + } + + if (!i->trusted && + IN_SET(type, _SD_BUS_VTABLE_METHOD, _SD_BUS_VTABLE_WRITABLE_PROPERTY) && + !(flags & SD_BUS_VTABLE_UNPRIVILEGED)) + fputs(" \n", i->f); +} + +/* Note that "names" is both an input and an output parameter. It initially points to the first argument name in a + NULL-separated list of strings, and is then advanced with each argument, and the resulting pointer is returned. */ +static int introspect_write_arguments(struct introspect *i, const char *signature, const char **names, const char *direction) { + int r; + + for (;;) { + size_t l; + + if (!*signature) + return 0; + + r = signature_element_length(signature, &l); + if (r < 0) + return r; + + fprintf(i->f, " f, " name=\"%s\"", *names); + *names += strlen(*names) + 1; + } + + if (direction) + fprintf(i->f, " direction=\"%s\"/>\n", direction); + else + fputs("/>\n", i->f); + + signature += l; + } +} + +int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) { + const sd_bus_vtable *vtable = v; + const char *names = ""; + + assert(i); + assert(v); + + for (; v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(vtable, v)) { + + /* Ignore methods, signals and properties that are + * marked "hidden", but do show the interface + * itself */ + + if (v->type != _SD_BUS_VTABLE_START && (v->flags & SD_BUS_VTABLE_HIDDEN)) + continue; + + switch (v->type) { + + case _SD_BUS_VTABLE_START: + if (v->flags & SD_BUS_VTABLE_DEPRECATED) + fputs(" \n", i->f); + break; + + case _SD_BUS_VTABLE_METHOD: + fprintf(i->f, " \n", v->x.method.member); + if (bus_vtable_has_names(vtable)) + names = strempty(v->x.method.names); + introspect_write_arguments(i, strempty(v->x.method.signature), &names, "in"); + introspect_write_arguments(i, strempty(v->x.method.result), &names, "out"); + introspect_write_flags(i, v->type, v->flags); + fputs(" \n", i->f); + break; + + case _SD_BUS_VTABLE_PROPERTY: + case _SD_BUS_VTABLE_WRITABLE_PROPERTY: + fprintf(i->f, " \n", + v->x.property.member, + v->x.property.signature, + v->type == _SD_BUS_VTABLE_WRITABLE_PROPERTY ? "readwrite" : "read"); + introspect_write_flags(i, v->type, v->flags); + fputs(" \n", i->f); + break; + + case _SD_BUS_VTABLE_SIGNAL: + fprintf(i->f, " \n", v->x.signal.member); + if (bus_vtable_has_names(vtable)) + names = strempty(v->x.signal.names); + introspect_write_arguments(i, strempty(v->x.signal.signature), &names, NULL); + introspect_write_flags(i, v->type, v->flags); + fputs(" \n", i->f); + break; + } + + } + + return 0; +} + +int introspect_finish(struct introspect *i, char **ret) { + int r; + + assert(i); + + fputs("\n", i->f); + + r = fflush_and_check(i->f); + if (r < 0) + return r; + + i->f = safe_fclose(i->f); + *ret = TAKE_PTR(i->introspection); + + return 0; +} + +void introspect_free(struct introspect *i) { + assert(i); + + /* Normally introspect_finish() does all the work, this is just a backup for error paths */ + + safe_fclose(i->f); + free(i->introspection); +} diff --git a/src/libsystemd/sd-bus/bus-introspect.h b/src/libsystemd/sd-bus/bus-introspect.h new file mode 100644 index 00000000..ccbb543d --- /dev/null +++ b/src/libsystemd/sd-bus/bus-introspect.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" + +#include "set.h" + +struct introspect { + FILE *f; + char *introspection; + size_t size; + bool trusted; +}; + +int introspect_begin(struct introspect *i, bool trusted); +int introspect_write_default_interfaces(struct introspect *i, bool object_manager); +int introspect_write_child_nodes(struct introspect *i, Set *s, const char *prefix); +int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v); +int introspect_finish(struct introspect *i, char **ret); +void introspect_free(struct introspect *i); diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c new file mode 100644 index 00000000..b74cfa6a --- /dev/null +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if HAVE_VALGRIND_MEMCHECK_H +#include +#endif + +#include +#include +#include +#include + +/* When we include libgen.h because we need dirname() we immediately + * undefine basename() since libgen.h defines it as a macro to the POSIX + * version which is really broken. We prefer GNU basename(). */ +#include +#undef basename + +#include "alloc-util.h" +#include "bus-internal.h" +#include "bus-kernel.h" +#include "bus-label.h" +#include "bus-message.h" +#include "bus-util.h" +#include "capability-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "memfd-util.h" +#include "parse-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "memory-util.h" + +void close_and_munmap(int fd, void *address, size_t size) { + if (size > 0) + assert_se(munmap(address, PAGE_ALIGN(size)) >= 0); + + safe_close(fd); +} + +void bus_flush_memfd(sd_bus *b) { + unsigned i; + + assert(b); + + for (i = 0; i < b->n_memfd_cache; i++) + close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped); +} diff --git a/src/libsystemd/sd-bus/bus-kernel.h b/src/libsystemd/sd-bus/bus-kernel.h new file mode 100644 index 00000000..fbbc43f6 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-kernel.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#define MEMFD_CACHE_MAX 32 + +/* When we cache a memfd block for reuse, we will truncate blocks + * longer than this in order not to keep too much data around. */ +#define MEMFD_CACHE_ITEM_SIZE_MAX (128*1024) + +/* This determines at which minimum size we prefer sending memfds over + * sending vectors */ +#define MEMFD_MIN_SIZE (512*1024) + +struct memfd_cache { + int fd; + void *address; + size_t mapped; + size_t allocated; +}; + +void close_and_munmap(int fd, void *address, size_t size); +void bus_flush_memfd(sd_bus *bus); diff --git a/src/libsystemd/sd-bus/bus-match.c b/src/libsystemd/sd-bus/bus-match.c new file mode 100644 index 00000000..57ce8cca --- /dev/null +++ b/src/libsystemd/sd-bus/bus-match.c @@ -0,0 +1,1102 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-internal.h" +#include "bus-match.h" +#include "bus-message.h" +#include "bus-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "hexdecoct.h" +#include "sort-util.h" +#include "string-util.h" +#include "strv.h" + +/* Example: + * + * A: type=signal,sender=foo,interface=bar + * B: type=signal,sender=quux,interface=fips + * C: type=signal,sender=quux,interface=waldo + * D: type=signal,member=test + * E: sender=miau + * F: type=signal + * G: type=signal + * + * results in this tree: + * + * BUS_MATCH_ROOT + * + BUS_MATCH_MESSAGE_TYPE + * | ` BUS_MATCH_VALUE: value == signal + * | + DBUS_MATCH_SENDER + * | | + BUS_MATCH_VALUE: value == foo + * | | | ` DBUS_MATCH_INTERFACE + * | | | ` BUS_MATCH_VALUE: value == bar + * | | | ` BUS_MATCH_LEAF: A + * | | ` BUS_MATCH_VALUE: value == quux + * | | ` DBUS_MATCH_INTERFACE + * | | | BUS_MATCH_VALUE: value == fips + * | | | ` BUS_MATCH_LEAF: B + * | | ` BUS_MATCH_VALUE: value == waldo + * | | ` BUS_MATCH_LEAF: C + * | + DBUS_MATCH_MEMBER + * | | ` BUS_MATCH_VALUE: value == test + * | | ` BUS_MATCH_LEAF: D + * | + BUS_MATCH_LEAF: F + * | ` BUS_MATCH_LEAF: G + * ` BUS_MATCH_SENDER + * ` BUS_MATCH_VALUE: value == miau + * ` BUS_MATCH_LEAF: E + */ + +static bool BUS_MATCH_IS_COMPARE(enum bus_match_node_type t) { + return t >= BUS_MATCH_SENDER && t <= BUS_MATCH_ARG_HAS_LAST; +} + +static bool BUS_MATCH_CAN_HASH(enum bus_match_node_type t) { + return (t >= BUS_MATCH_MESSAGE_TYPE && t <= BUS_MATCH_PATH) || + (t >= BUS_MATCH_ARG && t <= BUS_MATCH_ARG_LAST) || + (t >= BUS_MATCH_ARG_HAS && t <= BUS_MATCH_ARG_HAS_LAST); +} + +static void bus_match_node_free(struct bus_match_node *node) { + assert(node); + assert(node->parent); + assert(!node->child); + assert(node->type != BUS_MATCH_ROOT); + assert(node->type < _BUS_MATCH_NODE_TYPE_MAX); + + if (node->parent->child) { + /* We are apparently linked into the parent's child + * list. Let's remove us from there. */ + if (node->prev) { + assert(node->prev->next == node); + node->prev->next = node->next; + } else { + assert(node->parent->child == node); + node->parent->child = node->next; + } + + if (node->next) + node->next->prev = node->prev; + } + + if (node->type == BUS_MATCH_VALUE) { + /* We might be in the parent's hash table, so clean + * this up */ + + if (node->parent->type == BUS_MATCH_MESSAGE_TYPE) + hashmap_remove(node->parent->compare.children, UINT_TO_PTR(node->value.u8)); + else if (BUS_MATCH_CAN_HASH(node->parent->type) && node->value.str) + hashmap_remove(node->parent->compare.children, node->value.str); + + free(node->value.str); + } + + if (BUS_MATCH_IS_COMPARE(node->type)) { + assert(hashmap_isempty(node->compare.children)); + hashmap_free(node->compare.children); + } + + free(node); +} + +static bool bus_match_node_maybe_free(struct bus_match_node *node) { + assert(node); + + if (node->type == BUS_MATCH_ROOT) + return false; + + if (node->child) + return false; + + if (BUS_MATCH_IS_COMPARE(node->type) && !hashmap_isempty(node->compare.children)) + return true; + + bus_match_node_free(node); + return true; +} + +static bool value_node_test( + struct bus_match_node *node, + enum bus_match_node_type parent_type, + uint8_t value_u8, + const char *value_str, + char **value_strv, + sd_bus_message *m) { + + assert(node); + assert(node->type == BUS_MATCH_VALUE); + + /* Tests parameters against this value node, doing prefix + * magic and stuff. */ + + switch (parent_type) { + + case BUS_MATCH_MESSAGE_TYPE: + return node->value.u8 == value_u8; + + case BUS_MATCH_SENDER: + if (streq_ptr(node->value.str, value_str)) + return true; + + if (m->creds.mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) { + char **i; + + /* on kdbus we have the well known names list + * in the credentials, let's make use of that + * for an accurate match */ + + STRV_FOREACH(i, m->creds.well_known_names) + if (streq_ptr(node->value.str, *i)) + return true; + + } else { + + /* If we don't have kdbus, we don't know the + * well-known names of the senders. In that, + * let's just hope that dbus-daemon doesn't + * send us stuff we didn't want. */ + + if (node->value.str[0] != ':' && value_str && value_str[0] == ':') + return true; + } + + return false; + + case BUS_MATCH_DESTINATION: + case BUS_MATCH_INTERFACE: + case BUS_MATCH_MEMBER: + case BUS_MATCH_PATH: + case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: + + if (value_str) + return streq_ptr(node->value.str, value_str); + + return false; + + case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: { + char **i; + + STRV_FOREACH(i, value_strv) + if (streq_ptr(node->value.str, *i)) + return true; + + return false; + } + + case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: + if (value_str) + return namespace_simple_pattern(node->value.str, value_str); + + return false; + + case BUS_MATCH_PATH_NAMESPACE: + return path_simple_pattern(node->value.str, value_str); + + case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: + if (value_str) + return path_complex_pattern(node->value.str, value_str); + + return false; + + default: + assert_not_reached("Invalid node type"); + } +} + +static bool value_node_same( + struct bus_match_node *node, + enum bus_match_node_type parent_type, + uint8_t value_u8, + const char *value_str) { + + /* Tests parameters against this value node, not doing prefix + * magic and stuff, i.e. this one actually compares the match + * itself. */ + + assert(node); + assert(node->type == BUS_MATCH_VALUE); + + switch (parent_type) { + + case BUS_MATCH_MESSAGE_TYPE: + return node->value.u8 == value_u8; + + case BUS_MATCH_SENDER: + case BUS_MATCH_DESTINATION: + case BUS_MATCH_INTERFACE: + case BUS_MATCH_MEMBER: + case BUS_MATCH_PATH: + case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: + case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: + case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: + case BUS_MATCH_PATH_NAMESPACE: + case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: + return streq(node->value.str, value_str); + + default: + assert_not_reached("Invalid node type"); + } +} + +int bus_match_run( + sd_bus *bus, + struct bus_match_node *node, + sd_bus_message *m) { + + _cleanup_strv_free_ char **test_strv = NULL; + const char *test_str = NULL; + uint8_t test_u8 = 0; + int r; + + assert(m); + + if (!node) + return 0; + + if (bus && bus->match_callbacks_modified) + return 0; + + /* Not these special semantics: when traversing the tree we + * usually let bus_match_run() when called for a node + * recursively invoke bus_match_run(). There's are two + * exceptions here though, which are BUS_NODE_ROOT (which + * cannot have a sibling), and BUS_NODE_VALUE (whose siblings + * are invoked anyway by its parent. */ + + switch (node->type) { + + case BUS_MATCH_ROOT: + + /* Run all children. Since we cannot have any siblings + * we won't call any. The children of the root node + * are compares or leaves, they will automatically + * call their siblings. */ + return bus_match_run(bus, node->child, m); + + case BUS_MATCH_VALUE: + + /* Run all children. We don't execute any siblings, we + * assume our caller does that. The children of value + * nodes are compares or leaves, they will + * automatically call their siblings */ + + assert(node->child); + return bus_match_run(bus, node->child, m); + + case BUS_MATCH_LEAF: + + if (bus) { + /* Don't run this match as long as the AddMatch() call is not complete yet. + * + * Don't run this match unless the 'after' counter has been reached. + * + * Don't run this match more than once per iteration */ + + if (node->leaf.callback->install_slot || + m->read_counter <= node->leaf.callback->after || + node->leaf.callback->last_iteration == bus->iteration_counter) + return bus_match_run(bus, node->next, m); + + node->leaf.callback->last_iteration = bus->iteration_counter; + } + + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + /* Run the callback. And then invoke siblings. */ + if (node->leaf.callback->callback) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + sd_bus_slot *slot; + + slot = container_of(node->leaf.callback, sd_bus_slot, match_callback); + if (bus) { + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_handler = node->leaf.callback->callback; + bus->current_userdata = slot->userdata; + } + r = node->leaf.callback->callback(m, slot->userdata, &error_buffer); + if (bus) { + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = sd_bus_slot_unref(slot); + } + + r = bus_maybe_reply_error(m, r, &error_buffer); + if (r != 0) + return r; + + if (bus && bus->match_callbacks_modified) + return 0; + } + + return bus_match_run(bus, node->next, m); + + case BUS_MATCH_MESSAGE_TYPE: + test_u8 = m->header->type; + break; + + case BUS_MATCH_SENDER: + test_str = m->sender; + /* FIXME: resolve test_str from a well-known to a unique name first */ + break; + + case BUS_MATCH_DESTINATION: + test_str = m->destination; + break; + + case BUS_MATCH_INTERFACE: + test_str = m->interface; + break; + + case BUS_MATCH_MEMBER: + test_str = m->member; + break; + + case BUS_MATCH_PATH: + case BUS_MATCH_PATH_NAMESPACE: + test_str = m->path; + break; + + case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: + (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG, &test_str); + break; + + case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: + (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_PATH, &test_str); + break; + + case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: + (void) bus_message_get_arg(m, node->type - BUS_MATCH_ARG_NAMESPACE, &test_str); + break; + + case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: + (void) bus_message_get_arg_strv(m, node->type - BUS_MATCH_ARG_HAS, &test_strv); + break; + + default: + assert_not_reached("Unknown match type."); + } + + if (BUS_MATCH_CAN_HASH(node->type)) { + struct bus_match_node *found; + + /* Lookup via hash table, nice! So let's jump directly. */ + + if (test_str) + found = hashmap_get(node->compare.children, test_str); + else if (test_strv) { + char **i; + + STRV_FOREACH(i, test_strv) { + found = hashmap_get(node->compare.children, *i); + if (found) { + r = bus_match_run(bus, found, m); + if (r != 0) + return r; + } + } + + found = NULL; + } else if (node->type == BUS_MATCH_MESSAGE_TYPE) + found = hashmap_get(node->compare.children, UINT_TO_PTR(test_u8)); + else + found = NULL; + + if (found) { + r = bus_match_run(bus, found, m); + if (r != 0) + return r; + } + } else { + struct bus_match_node *c; + + /* No hash table, so let's iterate manually... */ + + for (c = node->child; c; c = c->next) { + if (!value_node_test(c, node->type, test_u8, test_str, test_strv, m)) + continue; + + r = bus_match_run(bus, c, m); + if (r != 0) + return r; + + if (bus && bus->match_callbacks_modified) + return 0; + } + } + + if (bus && bus->match_callbacks_modified) + return 0; + + /* And now, let's invoke our siblings */ + return bus_match_run(bus, node->next, m); +} + +static int bus_match_add_compare_value( + struct bus_match_node *where, + enum bus_match_node_type t, + uint8_t value_u8, + const char *value_str, + struct bus_match_node **ret) { + + struct bus_match_node *c = NULL, *n = NULL; + int r; + + assert(where); + assert(IN_SET(where->type, BUS_MATCH_ROOT, BUS_MATCH_VALUE)); + assert(BUS_MATCH_IS_COMPARE(t)); + assert(ret); + + for (c = where->child; c && c->type != t; c = c->next) + ; + + if (c) { + /* Comparison node already exists? Then let's see if + * the value node exists too. */ + + if (t == BUS_MATCH_MESSAGE_TYPE) + n = hashmap_get(c->compare.children, UINT_TO_PTR(value_u8)); + else if (BUS_MATCH_CAN_HASH(t)) + n = hashmap_get(c->compare.children, value_str); + else { + for (n = c->child; n && !value_node_same(n, t, value_u8, value_str); n = n->next) + ; + } + + if (n) { + *ret = n; + return 0; + } + } else { + /* Comparison node, doesn't exist yet? Then let's + * create it. */ + + c = new0(struct bus_match_node, 1); + if (!c) { + r = -ENOMEM; + goto fail; + } + + c->type = t; + c->parent = where; + c->next = where->child; + if (c->next) + c->next->prev = c; + where->child = c; + + if (t == BUS_MATCH_MESSAGE_TYPE) { + c->compare.children = hashmap_new(NULL); + if (!c->compare.children) { + r = -ENOMEM; + goto fail; + } + } else if (BUS_MATCH_CAN_HASH(t)) { + c->compare.children = hashmap_new(&string_hash_ops); + if (!c->compare.children) { + r = -ENOMEM; + goto fail; + } + } + } + + n = new0(struct bus_match_node, 1); + if (!n) { + r = -ENOMEM; + goto fail; + } + + n->type = BUS_MATCH_VALUE; + n->value.u8 = value_u8; + if (value_str) { + n->value.str = strdup(value_str); + if (!n->value.str) { + r = -ENOMEM; + goto fail; + } + } + + n->parent = c; + if (c->compare.children) { + + if (t == BUS_MATCH_MESSAGE_TYPE) + r = hashmap_put(c->compare.children, UINT_TO_PTR(value_u8), n); + else + r = hashmap_put(c->compare.children, n->value.str, n); + + if (r < 0) + goto fail; + } else { + n->next = c->child; + if (n->next) + n->next->prev = n; + c->child = n; + } + + *ret = n; + return 1; + +fail: + if (c) + bus_match_node_maybe_free(c); + + if (n) { + free(n->value.str); + free(n); + } + + return r; +} + +static int bus_match_add_leaf( + struct bus_match_node *where, + struct match_callback *callback) { + + struct bus_match_node *n; + + assert(where); + assert(IN_SET(where->type, BUS_MATCH_ROOT, BUS_MATCH_VALUE)); + assert(callback); + + n = new0(struct bus_match_node, 1); + if (!n) + return -ENOMEM; + + n->type = BUS_MATCH_LEAF; + n->parent = where; + n->next = where->child; + if (n->next) + n->next->prev = n; + + n->leaf.callback = callback; + callback->match_node = n; + + where->child = n; + + return 1; +} + +enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n) { + assert(k); + + if (n == 4 && startswith(k, "type")) + return BUS_MATCH_MESSAGE_TYPE; + if (n == 6 && startswith(k, "sender")) + return BUS_MATCH_SENDER; + if (n == 11 && startswith(k, "destination")) + return BUS_MATCH_DESTINATION; + if (n == 9 && startswith(k, "interface")) + return BUS_MATCH_INTERFACE; + if (n == 6 && startswith(k, "member")) + return BUS_MATCH_MEMBER; + if (n == 4 && startswith(k, "path")) + return BUS_MATCH_PATH; + if (n == 14 && startswith(k, "path_namespace")) + return BUS_MATCH_PATH_NAMESPACE; + + if (n == 4 && startswith(k, "arg")) { + int j; + + j = undecchar(k[3]); + if (j < 0) + return -EINVAL; + + return BUS_MATCH_ARG + j; + } + + if (n == 5 && startswith(k, "arg")) { + int a, b; + enum bus_match_node_type t; + + a = undecchar(k[3]); + b = undecchar(k[4]); + if (a <= 0 || b < 0) + return -EINVAL; + + t = BUS_MATCH_ARG + a * 10 + b; + if (t > BUS_MATCH_ARG_LAST) + return -EINVAL; + + return t; + } + + if (n == 8 && startswith(k, "arg") && startswith(k + 4, "path")) { + int j; + + j = undecchar(k[3]); + if (j < 0) + return -EINVAL; + + return BUS_MATCH_ARG_PATH + j; + } + + if (n == 9 && startswith(k, "arg") && startswith(k + 5, "path")) { + enum bus_match_node_type t; + int a, b; + + a = undecchar(k[3]); + b = undecchar(k[4]); + if (a <= 0 || b < 0) + return -EINVAL; + + t = BUS_MATCH_ARG_PATH + a * 10 + b; + if (t > BUS_MATCH_ARG_PATH_LAST) + return -EINVAL; + + return t; + } + + if (n == 13 && startswith(k, "arg") && startswith(k + 4, "namespace")) { + int j; + + j = undecchar(k[3]); + if (j < 0) + return -EINVAL; + + return BUS_MATCH_ARG_NAMESPACE + j; + } + + if (n == 14 && startswith(k, "arg") && startswith(k + 5, "namespace")) { + enum bus_match_node_type t; + int a, b; + + a = undecchar(k[3]); + b = undecchar(k[4]); + if (a <= 0 || b < 0) + return -EINVAL; + + t = BUS_MATCH_ARG_NAMESPACE + a * 10 + b; + if (t > BUS_MATCH_ARG_NAMESPACE_LAST) + return -EINVAL; + + return t; + } + + if (n == 7 && startswith(k, "arg") && startswith(k + 4, "has")) { + int j; + + j = undecchar(k[3]); + if (j < 0) + return -EINVAL; + + return BUS_MATCH_ARG_HAS + j; + } + + if (n == 8 && startswith(k, "arg") && startswith(k + 5, "has")) { + enum bus_match_node_type t; + int a, b; + + a = undecchar(k[3]); + b = undecchar(k[4]); + if (a <= 0 || b < 0) + return -EINVAL; + + t = BUS_MATCH_ARG_HAS + a * 10 + b; + if (t > BUS_MATCH_ARG_HAS_LAST) + return -EINVAL; + + return t; + } + + return -EINVAL; +} + +static int match_component_compare(const struct bus_match_component *a, const struct bus_match_component *b) { + return CMP(a->type, b->type); +} + +void bus_match_parse_free(struct bus_match_component *components, unsigned n_components) { + unsigned i; + + for (i = 0; i < n_components; i++) + free(components[i].value_str); + + free(components); +} + +int bus_match_parse( + const char *match, + struct bus_match_component **_components, + unsigned *_n_components) { + + const char *p = match; + struct bus_match_component *components = NULL; + size_t components_allocated = 0; + unsigned n_components = 0, i; + _cleanup_free_ char *value = NULL; + int r; + + assert(match); + assert(_components); + assert(_n_components); + + while (*p != 0) { + const char *eq, *q; + enum bus_match_node_type t; + unsigned j = 0; + size_t value_allocated = 0; + bool escaped = false, quoted; + uint8_t u; + + /* Avahi's match rules appear to include whitespace, skip over it */ + p += strspn(p, " "); + + eq = strchr(p, '='); + if (!eq) + return -EINVAL; + + t = bus_match_node_type_from_string(p, eq - p); + if (t < 0) + return -EINVAL; + + quoted = eq[1] == '\''; + + for (q = eq + 1 + quoted;; q++) { + + if (*q == 0) { + + if (quoted) { + r = -EINVAL; + goto fail; + } else { + if (value) + value[j] = 0; + break; + } + } + + if (!escaped) { + if (*q == '\\') { + escaped = true; + continue; + } + + if (quoted) { + if (*q == '\'') { + if (value) + value[j] = 0; + break; + } + } else { + if (*q == ',') { + if (value) + value[j] = 0; + + break; + } + } + } + + if (!GREEDY_REALLOC(value, value_allocated, j + 2)) { + r = -ENOMEM; + goto fail; + } + + value[j++] = *q; + escaped = false; + } + + if (!value) { + value = strdup(""); + if (!value) { + r = -ENOMEM; + goto fail; + } + } + + if (t == BUS_MATCH_MESSAGE_TYPE) { + r = bus_message_type_from_string(value, &u); + if (r < 0) + goto fail; + + value = mfree(value); + } else + u = 0; + + if (!GREEDY_REALLOC(components, components_allocated, n_components + 1)) { + r = -ENOMEM; + goto fail; + } + + components[n_components].type = t; + components[n_components].value_str = TAKE_PTR(value); + components[n_components].value_u8 = u; + n_components++; + + if (q[quoted] == 0) + break; + + if (q[quoted] != ',') { + r = -EINVAL; + goto fail; + } + + p = q + 1 + quoted; + } + + /* Order the whole thing, so that we always generate the same tree */ + typesafe_qsort(components, n_components, match_component_compare); + + /* Check for duplicates */ + for (i = 0; i+1 < n_components; i++) + if (components[i].type == components[i+1].type) { + r = -EINVAL; + goto fail; + } + + *_components = components; + *_n_components = n_components; + + return 0; + +fail: + bus_match_parse_free(components, n_components); + return r; +} + +char *bus_match_to_string(struct bus_match_component *components, unsigned n_components) { + _cleanup_fclose_ FILE *f = NULL; + char *buffer = NULL; + size_t size = 0; + unsigned i; + int r; + + if (n_components <= 0) + return strdup(""); + + assert(components); + + f = open_memstream_unlocked(&buffer, &size); + if (!f) + return NULL; + + for (i = 0; i < n_components; i++) { + char buf[32]; + + if (i != 0) + fputc(',', f); + + fputs(bus_match_node_type_to_string(components[i].type, buf, sizeof(buf)), f); + fputc('=', f); + fputc('\'', f); + + if (components[i].type == BUS_MATCH_MESSAGE_TYPE) + fputs(bus_message_type_to_string(components[i].value_u8), f); + else + fputs(components[i].value_str, f); + + fputc('\'', f); + } + + r = fflush_and_check(f); + if (r < 0) + return NULL; + + return buffer; +} + +int bus_match_add( + struct bus_match_node *root, + struct bus_match_component *components, + unsigned n_components, + struct match_callback *callback) { + + unsigned i; + struct bus_match_node *n; + int r; + + assert(root); + assert(callback); + + n = root; + for (i = 0; i < n_components; i++) { + r = bus_match_add_compare_value( + n, components[i].type, + components[i].value_u8, components[i].value_str, &n); + if (r < 0) + return r; + } + + return bus_match_add_leaf(n, callback); +} + +int bus_match_remove( + struct bus_match_node *root, + struct match_callback *callback) { + + struct bus_match_node *node, *pp; + + assert(root); + assert(callback); + + node = callback->match_node; + if (!node) + return 0; + + assert(node->type == BUS_MATCH_LEAF); + + callback->match_node = NULL; + + /* Free the leaf */ + pp = node->parent; + bus_match_node_free(node); + + /* Prune the tree above */ + while (pp) { + node = pp; + pp = node->parent; + + if (!bus_match_node_maybe_free(node)) + break; + } + + return 1; +} + +void bus_match_free(struct bus_match_node *node) { + struct bus_match_node *c; + + if (!node) + return; + + if (BUS_MATCH_CAN_HASH(node->type)) { + Iterator i; + + HASHMAP_FOREACH(c, node->compare.children, i) + bus_match_free(c); + + assert(hashmap_isempty(node->compare.children)); + } + + while ((c = node->child)) + bus_match_free(c); + + if (node->type != BUS_MATCH_ROOT) + bus_match_node_free(node); +} + +const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l) { + switch (t) { + + case BUS_MATCH_ROOT: + return "root"; + + case BUS_MATCH_VALUE: + return "value"; + + case BUS_MATCH_LEAF: + return "leaf"; + + case BUS_MATCH_MESSAGE_TYPE: + return "type"; + + case BUS_MATCH_SENDER: + return "sender"; + + case BUS_MATCH_DESTINATION: + return "destination"; + + case BUS_MATCH_INTERFACE: + return "interface"; + + case BUS_MATCH_MEMBER: + return "member"; + + case BUS_MATCH_PATH: + return "path"; + + case BUS_MATCH_PATH_NAMESPACE: + return "path_namespace"; + + case BUS_MATCH_ARG ... BUS_MATCH_ARG_LAST: + snprintf(buf, l, "arg%i", t - BUS_MATCH_ARG); + return buf; + + case BUS_MATCH_ARG_PATH ... BUS_MATCH_ARG_PATH_LAST: + snprintf(buf, l, "arg%ipath", t - BUS_MATCH_ARG_PATH); + return buf; + + case BUS_MATCH_ARG_NAMESPACE ... BUS_MATCH_ARG_NAMESPACE_LAST: + snprintf(buf, l, "arg%inamespace", t - BUS_MATCH_ARG_NAMESPACE); + return buf; + + case BUS_MATCH_ARG_HAS ... BUS_MATCH_ARG_HAS_LAST: + snprintf(buf, l, "arg%ihas", t - BUS_MATCH_ARG_HAS); + return buf; + + default: + return NULL; + } +} + +void bus_match_dump(struct bus_match_node *node, unsigned level) { + struct bus_match_node *c; + _cleanup_free_ char *pfx = NULL; + char buf[32]; + + if (!node) + return; + + pfx = strrep(" ", level); + printf("%s[%s]", strempty(pfx), bus_match_node_type_to_string(node->type, buf, sizeof(buf))); + + if (node->type == BUS_MATCH_VALUE) { + if (node->parent->type == BUS_MATCH_MESSAGE_TYPE) + printf(" <%u>\n", node->value.u8); + else + printf(" <%s>\n", node->value.str); + } else if (node->type == BUS_MATCH_ROOT) + puts(" root"); + else if (node->type == BUS_MATCH_LEAF) + printf(" %p/%p\n", node->leaf.callback->callback, container_of(node->leaf.callback, sd_bus_slot, match_callback)->userdata); + else + putchar('\n'); + + if (BUS_MATCH_CAN_HASH(node->type)) { + Iterator i; + + HASHMAP_FOREACH(c, node->compare.children, i) + bus_match_dump(c, level + 1); + } + + for (c = node->child; c; c = c->next) + bus_match_dump(c, level + 1); +} + +enum bus_match_scope bus_match_get_scope(const struct bus_match_component *components, unsigned n_components) { + bool found_driver = false; + unsigned i; + + if (n_components <= 0) + return BUS_MATCH_GENERIC; + + assert(components); + + /* Checks whether the specified match can only match the + * pseudo-service for local messages, which we detect by + * sender, interface or path. If a match is not restricted to + * local messages, then we check if it only matches on the + * driver. */ + + for (i = 0; i < n_components; i++) { + const struct bus_match_component *c = components + i; + + if (c->type == BUS_MATCH_SENDER) { + if (streq_ptr(c->value_str, "org.freedesktop.DBus.Local")) + return BUS_MATCH_LOCAL; + + if (streq_ptr(c->value_str, "org.freedesktop.DBus")) + found_driver = true; + } + + if (c->type == BUS_MATCH_INTERFACE && streq_ptr(c->value_str, "org.freedesktop.DBus.Local")) + return BUS_MATCH_LOCAL; + + if (c->type == BUS_MATCH_PATH && streq_ptr(c->value_str, "/org/freedesktop/DBus/Local")) + return BUS_MATCH_LOCAL; + } + + return found_driver ? BUS_MATCH_DRIVER : BUS_MATCH_GENERIC; + +} diff --git a/src/libsystemd/sd-bus/bus-match.h b/src/libsystemd/sd-bus/bus-match.h new file mode 100644 index 00000000..a6f67ce0 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-match.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "hashmap.h" + +enum bus_match_node_type { + BUS_MATCH_ROOT, + BUS_MATCH_VALUE, + BUS_MATCH_LEAF, + + /* The following are all different kinds of compare nodes */ + BUS_MATCH_SENDER, + BUS_MATCH_MESSAGE_TYPE, + BUS_MATCH_DESTINATION, + BUS_MATCH_INTERFACE, + BUS_MATCH_MEMBER, + BUS_MATCH_PATH, + BUS_MATCH_PATH_NAMESPACE, + BUS_MATCH_ARG, + BUS_MATCH_ARG_LAST = BUS_MATCH_ARG + 63, + BUS_MATCH_ARG_PATH, + BUS_MATCH_ARG_PATH_LAST = BUS_MATCH_ARG_PATH + 63, + BUS_MATCH_ARG_NAMESPACE, + BUS_MATCH_ARG_NAMESPACE_LAST = BUS_MATCH_ARG_NAMESPACE + 63, + BUS_MATCH_ARG_HAS, + BUS_MATCH_ARG_HAS_LAST = BUS_MATCH_ARG_HAS + 63, + _BUS_MATCH_NODE_TYPE_MAX, + _BUS_MATCH_NODE_TYPE_INVALID = -1 +}; + +struct bus_match_node { + enum bus_match_node_type type; + struct bus_match_node *parent, *next, *prev, *child; + + union { + struct { + char *str; + uint8_t u8; + } value; + struct { + struct match_callback *callback; + } leaf; + struct { + /* If this is set, then the child is NULL */ + Hashmap *children; + } compare; + }; +}; + +struct bus_match_component { + enum bus_match_node_type type; + uint8_t value_u8; + char *value_str; +}; + +enum bus_match_scope { + BUS_MATCH_GENERIC, + BUS_MATCH_LOCAL, + BUS_MATCH_DRIVER, +}; + +int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m); + +int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, struct match_callback *callback); +int bus_match_remove(struct bus_match_node *root, struct match_callback *callback); + +void bus_match_free(struct bus_match_node *node); + +void bus_match_dump(struct bus_match_node *node, unsigned level); + +const char* bus_match_node_type_to_string(enum bus_match_node_type t, char buf[], size_t l); +enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n); + +int bus_match_parse(const char *match, struct bus_match_component **_components, unsigned *_n_components); +void bus_match_parse_free(struct bus_match_component *components, unsigned n_components); +char *bus_match_to_string(struct bus_match_component *components, unsigned n_components); + +enum bus_match_scope bus_match_get_scope(const struct bus_match_component *components, unsigned n_components); diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c new file mode 100644 index 00000000..eb029e44 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-message.c @@ -0,0 +1,5921 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-gvariant.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-signature.h" +#include "bus-type.h" +#include "bus-util.h" +#include "fd-util.h" +#include "io-util.h" +#include "memfd-util.h" +#include "memory-util.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "utf8.h" + +static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored); + +static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) { + + if (!p) + return NULL; + + if (old_base == new_base) + return (void*) p; + + if ((uint8_t*) p < (uint8_t*) old_base) + return (void*) p; + + if ((uint8_t*) p >= (uint8_t*) old_base + sz) + return (void*) p; + + return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base); +} + +static void message_free_part(sd_bus_message *m, struct bus_body_part *part) { + assert(m); + assert(part); + + if (part->memfd >= 0) + close_and_munmap(part->memfd, part->mmap_begin, part->mapped); + else if (part->munmap_this) + munmap(part->mmap_begin, part->mapped); + else if (part->free_this) + free(part->data); + + if (part != &m->body) + free(part); +} + +static void message_reset_parts(sd_bus_message *m) { + struct bus_body_part *part; + + assert(m); + + part = &m->body; + while (m->n_body_parts > 0) { + struct bus_body_part *next = part->next; + message_free_part(m, part); + part = next; + m->n_body_parts--; + } + + m->body_end = NULL; + + m->cached_rindex_part = NULL; + m->cached_rindex_part_begin = 0; +} + +static struct bus_container *message_get_last_container(sd_bus_message *m) { + assert(m); + + if (m->n_containers == 0) + return &m->root_container; + + assert(m->containers); + return m->containers + m->n_containers - 1; +} + +static void message_free_last_container(sd_bus_message *m) { + struct bus_container *c; + + c = message_get_last_container(m); + + free(c->signature); + free(c->peeked_signature); + free(c->offsets); + + /* Move to previous container, but not if we are on root container */ + if (m->n_containers > 0) + m->n_containers--; +} + +static void message_reset_containers(sd_bus_message *m) { + assert(m); + + while (m->n_containers > 0) + message_free_last_container(m); + + m->containers = mfree(m->containers); + m->containers_allocated = 0; + m->root_container.index = 0; +} + +static sd_bus_message* message_free(sd_bus_message *m) { + assert(m); + + if (m->free_header) + free(m->header); + + message_reset_parts(m); + + /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user + * reference to the bus message also is considered a reference to the bus connection itself. */ + + if (m->free_fds) { + close_many(m->fds, m->n_fds); + free(m->fds); + } + + if (m->iovec != m->iovec_fixed) + free(m->iovec); + + message_reset_containers(m); + assert(m->n_containers == 0); + message_free_last_container(m); + + bus_creds_done(&m->creds); + return mfree(m); +} + +static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) { + void *op, *np; + size_t old_size, new_size, start; + + assert(m); + + if (m->poisoned) + return NULL; + + old_size = sizeof(struct bus_header) + m->fields_size; + start = ALIGN_TO(old_size, align); + new_size = start + sz; + + if (new_size < start || + new_size > (size_t) ((uint32_t) -1)) + goto poison; + + if (old_size == new_size) + return (uint8_t*) m->header + old_size; + + if (m->free_header) { + np = realloc(m->header, ALIGN8(new_size)); + if (!np) + goto poison; + } else { + /* Initially, the header is allocated as part of + * the sd_bus_message itself, let's replace it by + * dynamic data */ + + np = malloc(ALIGN8(new_size)); + if (!np) + goto poison; + + memcpy(np, m->header, sizeof(struct bus_header)); + } + + /* Zero out padding */ + if (start > old_size) + memzero((uint8_t*) np + old_size, start - old_size); + + op = m->header; + m->header = np; + m->fields_size = new_size - sizeof(struct bus_header); + + /* Adjust quick access pointers */ + m->path = adjust_pointer(m->path, op, old_size, m->header); + m->interface = adjust_pointer(m->interface, op, old_size, m->header); + m->member = adjust_pointer(m->member, op, old_size, m->header); + m->destination = adjust_pointer(m->destination, op, old_size, m->header); + m->sender = adjust_pointer(m->sender, op, old_size, m->header); + m->error.name = adjust_pointer(m->error.name, op, old_size, m->header); + + m->free_header = true; + + if (add_offset) { + if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets)) + goto poison; + + m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header); + } + + return (uint8_t*) np + start; + +poison: + m->poisoned = true; + return NULL; +} + +static int message_append_field_string( + sd_bus_message *m, + uint64_t h, + char type, + const char *s, + const char **ret) { + + size_t l; + uint8_t *p; + + assert(m); + + /* dbus1 only allows 8bit header field ids */ + if (h > 0xFF) + return -EINVAL; + + /* dbus1 doesn't allow strings over 32bit, let's enforce this + * globally, to not risk convertability */ + l = strlen(s); + if (l > UINT32_MAX) + return -EINVAL; + + /* Signature "(yv)" where the variant contains "s" */ + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + + /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */ + p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true); + if (!p) + return -ENOMEM; + + *((uint64_t*) p) = h; + memcpy(p+8, s, l); + p[8+l] = 0; + p[8+l+1] = 0; + p[8+l+2] = type; + + if (ret) + *ret = (char*) p + 8; + + } else { + /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */ + p = message_extend_fields(m, 8, 4 + 4 + l + 1, false); + if (!p) + return -ENOMEM; + + p[0] = (uint8_t) h; + p[1] = 1; + p[2] = type; + p[3] = 0; + + ((uint32_t*) p)[1] = l; + memcpy(p + 8, s, l + 1); + + if (ret) + *ret = (char*) p + 8; + } + + return 0; +} + +static int message_append_field_signature( + sd_bus_message *m, + uint64_t h, + const char *s, + const char **ret) { + + size_t l; + uint8_t *p; + + assert(m); + + /* dbus1 only allows 8bit header field ids */ + if (h > 0xFF) + return -EINVAL; + + /* dbus1 doesn't allow signatures over 8bit, let's enforce + * this globally, to not risk convertability */ + l = strlen(s); + if (l > SD_BUS_MAXIMUM_SIGNATURE_LENGTH) + return -EINVAL; + + /* Signature "(yv)" where the variant contains "g" */ + + if (BUS_MESSAGE_IS_GVARIANT(m)) + /* For gvariant the serialization is the same as for normal strings */ + return message_append_field_string(m, h, 'g', s, ret); + else { + /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */ + p = message_extend_fields(m, 8, 4 + 1 + l + 1, false); + if (!p) + return -ENOMEM; + + p[0] = (uint8_t) h; + p[1] = 1; + p[2] = SD_BUS_TYPE_SIGNATURE; + p[3] = 0; + p[4] = l; + memcpy(p + 5, s, l + 1); + + if (ret) + *ret = (const char*) p + 5; + } + + return 0; +} + +static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x) { + uint8_t *p; + + assert(m); + + /* dbus1 only allows 8bit header field ids */ + if (h > 0xFF) + return -EINVAL; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + /* (field id 64bit + ((value + NUL + signature string 'u') */ + + p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true); + if (!p) + return -ENOMEM; + + *((uint64_t*) p) = h; + *((uint32_t*) (p + 8)) = x; + p[12] = 0; + p[13] = 'u'; + } else { + /* (field id byte + (signature length + signature 'u' + NUL) + value) */ + p = message_extend_fields(m, 8, 4 + 4, false); + if (!p) + return -ENOMEM; + + p[0] = (uint8_t) h; + p[1] = 1; + p[2] = 'u'; + p[3] = 0; + + ((uint32_t*) p)[1] = x; + } + + return 0; +} + +static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) { + uint8_t *p; + + assert(m); + + /* dbus1 only allows 8bit header field ids */ + if (h > 0xFF) + return -EINVAL; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + /* (field id 64bit + ((value + NUL + signature string 't') */ + + p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true); + if (!p) + return -ENOMEM; + + *((uint64_t*) p) = h; + *((uint64_t*) (p + 8)) = x; + p[16] = 0; + p[17] = 't'; + } else { + /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */ + p = message_extend_fields(m, 8, 4 + 4 + 8, false); + if (!p) + return -ENOMEM; + + p[0] = (uint8_t) h; + p[1] = 1; + p[2] = 't'; + p[3] = 0; + p[4] = 0; + p[5] = 0; + p[6] = 0; + p[7] = 0; + + ((uint64_t*) p)[1] = x; + } + + return 0; +} + +static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) { + assert(m); + + if (BUS_MESSAGE_IS_GVARIANT(m)) + return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie); + else { + /* 64bit cookies are not supported on dbus1 */ + if (cookie > 0xffffffffUL) + return -EOPNOTSUPP; + + return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie); + } +} + +int bus_message_from_header( + sd_bus *bus, + void *header, + size_t header_accessible, + void *footer, + size_t footer_accessible, + size_t message_size, + int *fds, + size_t n_fds, + const char *label, + size_t extra, + sd_bus_message **ret) { + + _cleanup_free_ sd_bus_message *m = NULL; + struct bus_header *h; + size_t a, label_sz; + + assert(bus); + assert(header || header_accessible <= 0); + assert(footer || footer_accessible <= 0); + assert(fds || n_fds <= 0); + assert(ret); + + if (header_accessible < sizeof(struct bus_header)) + return -EBADMSG; + + if (header_accessible > message_size) + return -EBADMSG; + if (footer_accessible > message_size) + return -EBADMSG; + + h = header; + if (!IN_SET(h->version, 1, 2)) + return -EBADMSG; + + if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID) + return -EBADMSG; + + if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN)) + return -EBADMSG; + + /* Note that we are happy with unknown flags in the flags header! */ + + a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); + + if (label) { + label_sz = strlen(label); + a += label_sz + 1; + } + + m = malloc0(a); + if (!m) + return -ENOMEM; + + m->sealed = true; + m->header = header; + m->header_accessible = header_accessible; + m->footer = footer; + m->footer_accessible = footer_accessible; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + size_t ws; + + if (h->dbus2.cookie == 0) + return -EBADMSG; + + /* dbus2 derives the sizes from the message size and + the offset table at the end, since it is formatted as + gvariant "yyyyuta{tv}v". Since the message itself is a + structure with precisely to variable sized entries, + there's only one offset in the table, which marks the + end of the fields array. */ + + ws = bus_gvariant_determine_word_size(message_size, 0); + if (footer_accessible < ws) + return -EBADMSG; + + m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws); + if (ALIGN8(m->fields_size) > message_size - ws) + return -EBADMSG; + if (m->fields_size < sizeof(struct bus_header)) + return -EBADMSG; + + m->fields_size -= sizeof(struct bus_header); + m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size)); + } else { + if (h->dbus1.serial == 0) + return -EBADMSG; + + /* dbus1 has the sizes in the header */ + m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size); + m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size); + + if (sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size != message_size) + return -EBADMSG; + } + + m->fds = fds; + m->n_fds = n_fds; + + if (label) { + m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); + memcpy(m->creds.label, label, label_sz + 1); + + m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + } + + m->n_ref = 1; + m->bus = sd_bus_ref(bus); + + *ret = TAKE_PTR(m); + + return 0; +} + +int bus_message_from_malloc( + sd_bus *bus, + void *buffer, + size_t length, + int *fds, + size_t n_fds, + const char *label, + sd_bus_message **ret) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + size_t sz; + int r; + + r = bus_message_from_header( + bus, + buffer, length, /* in this case the initial bytes and the final bytes are the same */ + buffer, length, + length, + fds, n_fds, + label, + 0, &m); + if (r < 0) + return r; + + sz = length - sizeof(struct bus_header) - ALIGN8(m->fields_size); + if (sz > 0) { + m->n_body_parts = 1; + m->body.data = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(m->fields_size); + m->body.size = sz; + m->body.sealed = true; + m->body.memfd = -1; + } + + m->n_iovec = 1; + m->iovec = m->iovec_fixed; + m->iovec[0] = IOVEC_MAKE(buffer, length); + + r = bus_message_parse_fields(m); + if (r < 0) + return r; + + /* We take possession of the memory and fds now */ + m->free_header = true; + m->free_fds = true; + + *ret = TAKE_PTR(m); + return 0; +} + +_public_ int sd_bus_message_new( + sd_bus *bus, + sd_bus_message **m, + uint8_t type) { + + sd_bus_message *t; + + assert_return(bus, -ENOTCONN); + assert_return(bus->state != BUS_UNSET, -ENOTCONN); + assert_return(m, -EINVAL); + assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL); + + t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header)); + if (!t) + return -ENOMEM; + + t->n_ref = 1; + t->bus = sd_bus_ref(bus); + t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message))); + t->header->endian = BUS_NATIVE_ENDIAN; + t->header->type = type; + t->header->version = bus->message_version; + t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING); + t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t); + + if (bus->allow_interactive_authorization) + t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION; + + *m = t; + return 0; +} + +_public_ int sd_bus_message_new_signal( + sd_bus *bus, + sd_bus_message **m, + const char *path, + const char *interface, + const char *member) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + int r; + + assert_return(bus, -ENOTCONN); + assert_return(bus->state != BUS_UNSET, -ENOTCONN); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(interface_name_is_valid(interface), -EINVAL); + assert_return(member_name_is_valid(member), -EINVAL); + assert_return(m, -EINVAL); + + r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_SIGNAL); + if (r < 0) + return -ENOMEM; + + assert(t); + + t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; + + r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path); + if (r < 0) + return r; + r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface); + if (r < 0) + return r; + r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member); + if (r < 0) + return r; + + *m = TAKE_PTR(t); + return 0; +} + +_public_ int sd_bus_message_new_method_call( + sd_bus *bus, + sd_bus_message **m, + const char *destination, + const char *path, + const char *interface, + const char *member) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + int r; + + assert_return(bus, -ENOTCONN); + assert_return(bus->state != BUS_UNSET, -ENOTCONN); + assert_return(!destination || service_name_is_valid(destination), -EINVAL); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(!interface || interface_name_is_valid(interface), -EINVAL); + assert_return(member_name_is_valid(member), -EINVAL); + assert_return(m, -EINVAL); + + r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_CALL); + if (r < 0) + return -ENOMEM; + + assert(t); + + r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path); + if (r < 0) + return r; + r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member); + if (r < 0) + return r; + + if (interface) { + r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface); + if (r < 0) + return r; + } + + if (destination) { + r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination); + if (r < 0) + return r; + } + + *m = TAKE_PTR(t); + return 0; +} + +static int message_new_reply( + sd_bus_message *call, + uint8_t type, + sd_bus_message **m) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + uint64_t cookie; + int r; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); + assert_return(call->bus->state != BUS_UNSET, -ENOTCONN); + assert_return(m, -EINVAL); + + cookie = BUS_MESSAGE_COOKIE(call); + if (cookie == 0) + return -EOPNOTSUPP; + + r = sd_bus_message_new(call->bus, &t, type); + if (r < 0) + return -ENOMEM; + + assert(t); + + t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; + t->reply_cookie = cookie; + r = message_append_reply_cookie(t, t->reply_cookie); + if (r < 0) + return r; + + if (call->sender) { + r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination); + if (r < 0) + return r; + } + + t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED); + t->enforced_reply_signature = call->enforced_reply_signature; + + *m = TAKE_PTR(t); + return 0; +} + +_public_ int sd_bus_message_new_method_return( + sd_bus_message *call, + sd_bus_message **m) { + + return message_new_reply(call, SD_BUS_MESSAGE_METHOD_RETURN, m); +} + +_public_ int sd_bus_message_new_method_error( + sd_bus_message *call, + sd_bus_message **m, + const sd_bus_error *e) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + int r; + + assert_return(sd_bus_error_is_set(e), -EINVAL); + assert_return(m, -EINVAL); + + r = message_new_reply(call, SD_BUS_MESSAGE_METHOD_ERROR, &t); + if (r < 0) + return r; + + r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name); + if (r < 0) + return r; + + if (e->message) { + r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message); + if (r < 0) + return r; + } + + t->error._need_free = -1; + + *m = TAKE_PTR(t); + return 0; +} + +_public_ int sd_bus_message_new_method_errorf( + sd_bus_message *call, + sd_bus_message **m, + const char *name, + const char *format, + ...) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + va_list ap; + + assert_return(name, -EINVAL); + assert_return(m, -EINVAL); + + va_start(ap, format); + bus_error_setfv(&error, name, format, ap); + va_end(ap); + + return sd_bus_message_new_method_error(call, m, &error); +} + +_public_ int sd_bus_message_new_method_errno( + sd_bus_message *call, + sd_bus_message **m, + int error, + const sd_bus_error *p) { + + _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL; + + if (sd_bus_error_is_set(p)) + return sd_bus_message_new_method_error(call, m, p); + + sd_bus_error_set_errno(&berror, error); + + return sd_bus_message_new_method_error(call, m, &berror); +} + +_public_ int sd_bus_message_new_method_errnof( + sd_bus_message *call, + sd_bus_message **m, + int error, + const char *format, + ...) { + + _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL; + va_list ap; + + va_start(ap, format); + sd_bus_error_set_errnofv(&berror, error, format, ap); + va_end(ap); + + return sd_bus_message_new_method_error(call, m, &berror); +} + +void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m) { + assert(bus); + assert(m); + + m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus.Local"; + m->creds.well_known_names_local = true; + m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask; +} + +void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) { + assert(bus); + assert(m); + + m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus"; + m->creds.well_known_names_driver = true; + m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask; +} + +int bus_message_new_synthetic_error( + sd_bus *bus, + uint64_t cookie, + const sd_bus_error *e, + sd_bus_message **m) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + int r; + + assert(bus); + assert(sd_bus_error_is_set(e)); + assert(m); + + r = sd_bus_message_new(bus, &t, SD_BUS_MESSAGE_METHOD_ERROR); + if (r < 0) + return -ENOMEM; + + assert(t); + + t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; + t->reply_cookie = cookie; + + r = message_append_reply_cookie(t, t->reply_cookie); + if (r < 0) + return r; + + if (bus && bus->unique_name) { + r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination); + if (r < 0) + return r; + } + + r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name); + if (r < 0) + return r; + + if (e->message) { + r = message_append_basic(t, SD_BUS_TYPE_STRING, e->message, (const void**) &t->error.message); + if (r < 0) + return r; + } + + t->error._need_free = -1; + + bus_message_set_sender_driver(bus, t); + + *m = TAKE_PTR(t); + return 0; +} + +_public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) { + if (!m) + return NULL; + + /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at + * least one bus connection object. */ + assert(m->n_ref > 0 || m->n_queued > 0); + + m->n_ref++; + + /* Each user reference to a bus message shall also be considered a ref on the bus */ + sd_bus_ref(m->bus); + return m; +} + +_public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) { + if (!m) + return NULL; + + assert(m->n_ref > 0); + + sd_bus_unref(m->bus); /* Each regular ref is also a ref on the bus connection. Let's hence drop it + * here. Note we have to do this before decrementing our own n_ref here, since + * otherwise, if this message is currently queued sd_bus_unref() might call + * bus_message_unref_queued() for this which might then destroy the message + * while we are still processing it. */ + m->n_ref--; + + if (m->n_ref > 0 || m->n_queued > 0) + return NULL; + + /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful + * to reset the field only after the last reference to the bus is dropped, after all we might keep + * multiple references to the bus, once for each reference kept on ourselves. */ + m->bus = NULL; + + return message_free(m); +} + +sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus) { + if (!m) + return NULL; + + /* If this is a different bus than the message is associated with, then implicitly turn this into a + * regular reference. This means that you can create a memory leak by enqueuing a message generated + * on one bus onto another at the same time as enqueueing a message from the second one on the first, + * as we'll not detect the cyclic references there. */ + if (bus != m->bus) + return sd_bus_message_ref(m); + + assert(m->n_ref > 0 || m->n_queued > 0); + m->n_queued++; + + return m; +} + +sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus) { + if (!m) + return NULL; + + if (bus != m->bus) + return sd_bus_message_unref(m); + + assert(m->n_queued > 0); + m->n_queued--; + + if (m->n_ref > 0 || m->n_queued > 0) + return NULL; + + m->bus = NULL; + + return message_free(m); +} + +_public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) { + assert_return(m, -EINVAL); + assert_return(type, -EINVAL); + + *type = m->header->type; + return 0; +} + +_public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) { + uint64_t c; + + assert_return(m, -EINVAL); + assert_return(cookie, -EINVAL); + + c = BUS_MESSAGE_COOKIE(m); + if (c == 0) + return -ENODATA; + + *cookie = BUS_MESSAGE_COOKIE(m); + return 0; +} + +_public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) { + assert_return(m, -EINVAL); + assert_return(cookie, -EINVAL); + + if (m->reply_cookie == 0) + return -ENODATA; + + *cookie = m->reply_cookie; + return 0; +} + +_public_ int sd_bus_message_get_expect_reply(sd_bus_message *m) { + assert_return(m, -EINVAL); + + return m->header->type == SD_BUS_MESSAGE_METHOD_CALL && + !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED); +} + +_public_ int sd_bus_message_get_auto_start(sd_bus_message *m) { + assert_return(m, -EINVAL); + + return !(m->header->flags & BUS_MESSAGE_NO_AUTO_START); +} + +_public_ int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m) { + assert_return(m, -EINVAL); + + return m->header->type == SD_BUS_MESSAGE_METHOD_CALL && + (m->header->flags & BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION); +} + +_public_ const char *sd_bus_message_get_path(sd_bus_message *m) { + assert_return(m, NULL); + + return m->path; +} + +_public_ const char *sd_bus_message_get_interface(sd_bus_message *m) { + assert_return(m, NULL); + + return m->interface; +} + +_public_ const char *sd_bus_message_get_member(sd_bus_message *m) { + assert_return(m, NULL); + + return m->member; +} + +_public_ const char *sd_bus_message_get_destination(sd_bus_message *m) { + assert_return(m, NULL); + + return m->destination; +} + +_public_ const char *sd_bus_message_get_sender(sd_bus_message *m) { + assert_return(m, NULL); + + return m->sender; +} + +_public_ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) { + assert_return(m, NULL); + + if (!sd_bus_error_is_set(&m->error)) + return NULL; + + return &m->error; +} + +_public_ int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec) { + assert_return(m, -EINVAL); + assert_return(usec, -EINVAL); + + if (m->monotonic <= 0) + return -ENODATA; + + *usec = m->monotonic; + return 0; +} + +_public_ int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec) { + assert_return(m, -EINVAL); + assert_return(usec, -EINVAL); + + if (m->realtime <= 0) + return -ENODATA; + + *usec = m->realtime; + return 0; +} + +_public_ int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t *seqnum) { + assert_return(m, -EINVAL); + assert_return(seqnum, -EINVAL); + + if (m->seqnum <= 0) + return -ENODATA; + + *seqnum = m->seqnum; + return 0; +} + +_public_ sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m) { + assert_return(m, NULL); + + if (m->creds.mask == 0) + return NULL; + + return &m->creds; +} + +_public_ int sd_bus_message_is_signal( + sd_bus_message *m, + const char *interface, + const char *member) { + + assert_return(m, -EINVAL); + + if (m->header->type != SD_BUS_MESSAGE_SIGNAL) + return 0; + + if (interface && !streq_ptr(m->interface, interface)) + return 0; + + if (member && !streq_ptr(m->member, member)) + return 0; + + return 1; +} + +_public_ int sd_bus_message_is_method_call( + sd_bus_message *m, + const char *interface, + const char *member) { + + assert_return(m, -EINVAL); + + if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL) + return 0; + + if (interface && !streq_ptr(m->interface, interface)) + return 0; + + if (member && !streq_ptr(m->member, member)) + return 0; + + return 1; +} + +_public_ int sd_bus_message_is_method_error(sd_bus_message *m, const char *name) { + assert_return(m, -EINVAL); + + if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR) + return 0; + + if (name && !streq_ptr(m->error.name, name)) + return 0; + + return 1; +} + +_public_ int sd_bus_message_set_expect_reply(sd_bus_message *m, int b) { + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EPERM); + + SET_FLAG(m->header->flags, BUS_MESSAGE_NO_REPLY_EXPECTED, !b); + + return 0; +} + +_public_ int sd_bus_message_set_auto_start(sd_bus_message *m, int b) { + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + SET_FLAG(m->header->flags, BUS_MESSAGE_NO_AUTO_START, !b); + + return 0; +} + +_public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b) { + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + SET_FLAG(m->header->flags, BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION, b); + + return 0; +} + +struct bus_body_part *message_append_part(sd_bus_message *m) { + struct bus_body_part *part; + + assert(m); + + if (m->poisoned) + return NULL; + + if (m->n_body_parts <= 0) { + part = &m->body; + zero(*part); + } else { + assert(m->body_end); + + part = new0(struct bus_body_part, 1); + if (!part) { + m->poisoned = true; + return NULL; + } + + m->body_end->next = part; + } + + part->memfd = -1; + m->body_end = part; + m->n_body_parts++; + + return part; +} + +static void part_zero(struct bus_body_part *part, size_t sz) { + assert(part); + assert(sz > 0); + assert(sz < 8); + + /* All other fields can be left in their defaults */ + assert(!part->data); + assert(part->memfd < 0); + + part->size = sz; + part->is_zero = true; + part->sealed = true; +} + +static int part_make_space( + struct sd_bus_message *m, + struct bus_body_part *part, + size_t sz, + void **q) { + + void *n; + + assert(m); + assert(part); + assert(!part->sealed); + + if (m->poisoned) + return -ENOMEM; + + if (part->allocated == 0 || sz > part->allocated) { + size_t new_allocated; + + new_allocated = sz > 0 ? 2 * sz : 64; + n = realloc(part->data, new_allocated); + if (!n) { + m->poisoned = true; + return -ENOMEM; + } + + part->data = n; + part->allocated = new_allocated; + part->free_this = true; + } + + if (q) + *q = part->data ? (uint8_t*) part->data + part->size : NULL; + + part->size = sz; + return 0; +} + +static int message_add_offset(sd_bus_message *m, size_t offset) { + struct bus_container *c; + + assert(m); + assert(BUS_MESSAGE_IS_GVARIANT(m)); + + /* Add offset to current container, unless this is the first + * item in it, which will have the 0 offset, which we can + * ignore. */ + c = message_get_last_container(m); + + if (!c->need_offsets) + return 0; + + if (!GREEDY_REALLOC(c->offsets, c->offsets_allocated, c->n_offsets + 1)) + return -ENOMEM; + + c->offsets[c->n_offsets++] = offset; + return 0; +} + +static void message_extend_containers(sd_bus_message *m, size_t expand) { + struct bus_container *c; + + assert(m); + + if (expand <= 0) + return; + + /* Update counters */ + for (c = m->containers; c < m->containers + m->n_containers; c++) { + + if (c->array_size) + *c->array_size += expand; + } +} + +static void *message_extend_body( + sd_bus_message *m, + size_t align, + size_t sz, + bool add_offset, + bool force_inline) { + + size_t start_body, end_body, padding, added; + void *p; + int r; + + assert(m); + assert(align > 0); + assert(!m->sealed); + + if (m->poisoned) + return NULL; + + start_body = ALIGN_TO((size_t) m->body_size, align); + end_body = start_body + sz; + + padding = start_body - m->body_size; + added = padding + sz; + + /* Check for 32bit overflows */ + if (end_body > (size_t) ((uint32_t) -1) || + end_body < start_body) { + m->poisoned = true; + return NULL; + } + + if (added > 0) { + struct bus_body_part *part = NULL; + bool add_new_part; + + add_new_part = + m->n_body_parts <= 0 || + m->body_end->sealed || + (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) || + (force_inline && m->body_end->size > MEMFD_MIN_SIZE); + /* If this must be an inlined extension, let's create a new part if + * the previous part is large enough to be inlined. */ + + if (add_new_part) { + if (padding > 0) { + part = message_append_part(m); + if (!part) + return NULL; + + part_zero(part, padding); + } + + part = message_append_part(m); + if (!part) + return NULL; + + r = part_make_space(m, part, sz, &p); + if (r < 0) + return NULL; + } else { + struct bus_container *c; + void *op; + size_t os, start_part, end_part; + + part = m->body_end; + op = part->data; + os = part->size; + + start_part = ALIGN_TO(part->size, align); + end_part = start_part + sz; + + r = part_make_space(m, part, end_part, &p); + if (r < 0) + return NULL; + + if (padding > 0) { + memzero(p, padding); + p = (uint8_t*) p + padding; + } + + /* Readjust pointers */ + for (c = m->containers; c < m->containers + m->n_containers; c++) + c->array_size = adjust_pointer(c->array_size, op, os, part->data); + + m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data); + } + } else + /* Return something that is not NULL and is aligned */ + p = (uint8_t*) align; + + m->body_size = end_body; + message_extend_containers(m, added); + + if (add_offset) { + r = message_add_offset(m, end_body); + if (r < 0) { + m->poisoned = true; + return NULL; + } + } + + return p; +} + +static int message_push_fd(sd_bus_message *m, int fd) { + int *f, copy; + + assert(m); + + if (fd < 0) + return -EINVAL; + + if (!m->allow_fds) + return -EOPNOTSUPP; + + copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (copy < 0) + return -errno; + + f = reallocarray(m->fds, sizeof(int), m->n_fds + 1); + if (!f) { + m->poisoned = true; + safe_close(copy); + return -ENOMEM; + } + + m->fds = f; + m->fds[m->n_fds] = copy; + m->free_fds = true; + + return copy; +} + +int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored) { + _cleanup_close_ int fd = -1; + struct bus_container *c; + ssize_t align, sz; + void *a; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(bus_type_is_basic(type), -EINVAL); + assert_return(!m->poisoned, -ESTALE); + + c = message_get_last_container(m); + + if (c->signature && c->signature[c->index]) { + /* Container signature is already set */ + + if (c->signature[c->index] != type) + return -ENXIO; + } else { + char *e; + + /* Maybe we can append to the signature? But only if this is the top-level container */ + if (c->enclosing != 0) + return -ENXIO; + + e = strextend(&c->signature, CHAR_TO_STR(type), NULL); + if (!e) { + m->poisoned = true; + return -ENOMEM; + } + } + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + uint8_t u8; + uint32_t u32; + + switch (type) { + + case SD_BUS_TYPE_SIGNATURE: + case SD_BUS_TYPE_STRING: + p = strempty(p); + + _fallthrough_; + case SD_BUS_TYPE_OBJECT_PATH: + if (!p) + return -EINVAL; + + align = 1; + sz = strlen(p) + 1; + break; + + case SD_BUS_TYPE_BOOLEAN: + + u8 = p && *(int*) p; + p = &u8; + + align = sz = 1; + break; + + case SD_BUS_TYPE_UNIX_FD: + + if (!p) + return -EINVAL; + + fd = message_push_fd(m, *(int*) p); + if (fd < 0) + return fd; + + u32 = m->n_fds; + p = &u32; + + align = sz = 4; + break; + + default: + align = bus_gvariant_get_alignment(CHAR_TO_STR(type)); + sz = bus_gvariant_get_size(CHAR_TO_STR(type)); + break; + } + + assert(align > 0); + assert(sz > 0); + + a = message_extend_body(m, align, sz, true, false); + if (!a) + return -ENOMEM; + + memcpy(a, p, sz); + + if (stored) + *stored = (const uint8_t*) a; + + } else { + uint32_t u32; + + switch (type) { + + case SD_BUS_TYPE_STRING: + /* To make things easy we'll serialize a NULL string + * into the empty string */ + p = strempty(p); + + _fallthrough_; + case SD_BUS_TYPE_OBJECT_PATH: + + if (!p) + return -EINVAL; + + align = 4; + sz = 4 + strlen(p) + 1; + break; + + case SD_BUS_TYPE_SIGNATURE: + + p = strempty(p); + + align = 1; + sz = 1 + strlen(p) + 1; + break; + + case SD_BUS_TYPE_BOOLEAN: + + u32 = p && *(int*) p; + p = &u32; + + align = sz = 4; + break; + + case SD_BUS_TYPE_UNIX_FD: + + if (!p) + return -EINVAL; + + fd = message_push_fd(m, *(int*) p); + if (fd < 0) + return fd; + + u32 = m->n_fds; + p = &u32; + + align = sz = 4; + break; + + default: + align = bus_type_get_alignment(type); + sz = bus_type_get_size(type); + break; + } + + assert(align > 0); + assert(sz > 0); + + a = message_extend_body(m, align, sz, false, false); + if (!a) + return -ENOMEM; + + if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) { + *(uint32_t*) a = sz - 5; + memcpy((uint8_t*) a + 4, p, sz - 4); + + if (stored) + *stored = (const uint8_t*) a + 4; + + } else if (type == SD_BUS_TYPE_SIGNATURE) { + *(uint8_t*) a = sz - 2; + memcpy((uint8_t*) a + 1, p, sz - 1); + + if (stored) + *stored = (const uint8_t*) a + 1; + } else { + memcpy(a, p, sz); + + if (stored) + *stored = a; + } + } + + if (type == SD_BUS_TYPE_UNIX_FD) + m->n_fds++; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index++; + + fd = -1; + return 0; +} + +_public_ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) { + return message_append_basic(m, type, p, NULL); +} + +_public_ int sd_bus_message_append_string_space( + sd_bus_message *m, + size_t size, + char **s) { + + struct bus_container *c; + void *a; + + assert_return(m, -EINVAL); + assert_return(s, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(!m->poisoned, -ESTALE); + + c = message_get_last_container(m); + + if (c->signature && c->signature[c->index]) { + /* Container signature is already set */ + + if (c->signature[c->index] != SD_BUS_TYPE_STRING) + return -ENXIO; + } else { + char *e; + + /* Maybe we can append to the signature? But only if this is the top-level container */ + if (c->enclosing != 0) + return -ENXIO; + + e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL); + if (!e) { + m->poisoned = true; + return -ENOMEM; + } + } + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + a = message_extend_body(m, 1, size + 1, true, false); + if (!a) + return -ENOMEM; + + *s = a; + } else { + a = message_extend_body(m, 4, 4 + size + 1, false, false); + if (!a) + return -ENOMEM; + + *(uint32_t*) a = size; + *s = (char*) a + 4; + } + + (*s)[size] = 0; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index++; + + return 0; +} + +_public_ int sd_bus_message_append_string_iovec( + sd_bus_message *m, + const struct iovec *iov, + unsigned n /* should be size_t, but is API now… 😞 */) { + + size_t size; + unsigned i; + char *p; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(iov || n == 0, -EINVAL); + assert_return(!m->poisoned, -ESTALE); + + size = IOVEC_TOTAL_SIZE(iov, n); + + r = sd_bus_message_append_string_space(m, size, &p); + if (r < 0) + return r; + + for (i = 0; i < n; i++) { + + if (iov[i].iov_base) + memcpy(p, iov[i].iov_base, iov[i].iov_len); + else + memset(p, ' ', iov[i].iov_len); + + p += iov[i].iov_len; + } + + return 0; +} + +static int bus_message_open_array( + sd_bus_message *m, + struct bus_container *c, + const char *contents, + uint32_t **array_size, + size_t *begin, + bool *need_offsets) { + + unsigned nindex; + int alignment, r; + + assert(m); + assert(c); + assert(contents); + assert(array_size); + assert(begin); + assert(need_offsets); + + if (!signature_is_single(contents, true)) + return -EINVAL; + + if (c->signature && c->signature[c->index]) { + + /* Verify the existing signature */ + + if (c->signature[c->index] != SD_BUS_TYPE_ARRAY) + return -ENXIO; + + if (!startswith(c->signature + c->index + 1, contents)) + return -ENXIO; + + nindex = c->index + 1 + strlen(contents); + } else { + char *e; + + if (c->enclosing != 0) + return -ENXIO; + + /* Extend the existing signature */ + + e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_ARRAY), contents, NULL); + if (!e) { + m->poisoned = true; + return -ENOMEM; + } + + nindex = e - c->signature; + } + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + alignment = bus_gvariant_get_alignment(contents); + if (alignment < 0) + return alignment; + + /* Add alignment padding and add to offset list */ + if (!message_extend_body(m, alignment, 0, false, false)) + return -ENOMEM; + + r = bus_gvariant_is_fixed_size(contents); + if (r < 0) + return r; + + *begin = m->body_size; + *need_offsets = r == 0; + } else { + void *a, *op; + size_t os; + struct bus_body_part *o; + + alignment = bus_type_get_alignment(contents[0]); + if (alignment < 0) + return alignment; + + a = message_extend_body(m, 4, 4, false, false); + if (!a) + return -ENOMEM; + + o = m->body_end; + op = m->body_end->data; + os = m->body_end->size; + + /* Add alignment between size and first element */ + if (!message_extend_body(m, alignment, 0, false, false)) + return -ENOMEM; + + /* location of array size might have changed so let's readjust a */ + if (o == m->body_end) + a = adjust_pointer(a, op, os, m->body_end->data); + + *(uint32_t*) a = 0; + *array_size = a; + } + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index = nindex; + + return 0; +} + +static int bus_message_open_variant( + sd_bus_message *m, + struct bus_container *c, + const char *contents) { + + assert(m); + assert(c); + assert(contents); + + if (!signature_is_single(contents, false)) + return -EINVAL; + + if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN) + return -EINVAL; + + if (c->signature && c->signature[c->index]) { + + if (c->signature[c->index] != SD_BUS_TYPE_VARIANT) + return -ENXIO; + + } else { + char *e; + + if (c->enclosing != 0) + return -ENXIO; + + e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_VARIANT), NULL); + if (!e) { + m->poisoned = true; + return -ENOMEM; + } + } + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + /* Variants are always aligned to 8 */ + + if (!message_extend_body(m, 8, 0, false, false)) + return -ENOMEM; + + } else { + size_t l; + void *a; + + l = strlen(contents); + a = message_extend_body(m, 1, 1 + l + 1, false, false); + if (!a) + return -ENOMEM; + + *(uint8_t*) a = l; + memcpy((uint8_t*) a + 1, contents, l + 1); + } + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index++; + + return 0; +} + +static int bus_message_open_struct( + sd_bus_message *m, + struct bus_container *c, + const char *contents, + size_t *begin, + bool *need_offsets) { + + size_t nindex; + int r; + + assert(m); + assert(c); + assert(contents); + assert(begin); + assert(need_offsets); + + if (!signature_is_valid(contents, false)) + return -EINVAL; + + if (c->signature && c->signature[c->index]) { + size_t l; + + l = strlen(contents); + + if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN || + !startswith(c->signature + c->index + 1, contents) || + c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END) + return -ENXIO; + + nindex = c->index + 1 + l + 1; + } else { + char *e; + + if (c->enclosing != 0) + return -ENXIO; + + e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL); + if (!e) { + m->poisoned = true; + return -ENOMEM; + } + + nindex = e - c->signature; + } + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + int alignment; + + alignment = bus_gvariant_get_alignment(contents); + if (alignment < 0) + return alignment; + + if (!message_extend_body(m, alignment, 0, false, false)) + return -ENOMEM; + + r = bus_gvariant_is_fixed_size(contents); + if (r < 0) + return r; + + *begin = m->body_size; + *need_offsets = r == 0; + } else { + /* Align contents to 8 byte boundary */ + if (!message_extend_body(m, 8, 0, false, false)) + return -ENOMEM; + } + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index = nindex; + + return 0; +} + +static int bus_message_open_dict_entry( + sd_bus_message *m, + struct bus_container *c, + const char *contents, + size_t *begin, + bool *need_offsets) { + + int r; + + assert(m); + assert(c); + assert(contents); + assert(begin); + assert(need_offsets); + + if (!signature_is_pair(contents)) + return -EINVAL; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + return -ENXIO; + + if (c->signature && c->signature[c->index]) { + size_t l; + + l = strlen(contents); + + if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN || + !startswith(c->signature + c->index + 1, contents) || + c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END) + return -ENXIO; + } else + return -ENXIO; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + int alignment; + + alignment = bus_gvariant_get_alignment(contents); + if (alignment < 0) + return alignment; + + if (!message_extend_body(m, alignment, 0, false, false)) + return -ENOMEM; + + r = bus_gvariant_is_fixed_size(contents); + if (r < 0) + return r; + + *begin = m->body_size; + *need_offsets = r == 0; + } else { + /* Align contents to 8 byte boundary */ + if (!message_extend_body(m, 8, 0, false, false)) + return -ENOMEM; + } + + return 0; +} + +_public_ int sd_bus_message_open_container( + sd_bus_message *m, + char type, + const char *contents) { + + struct bus_container *c; + uint32_t *array_size = NULL; + _cleanup_free_ char *signature = NULL; + size_t before, begin = 0; + bool need_offsets = false; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(contents, -EINVAL); + assert_return(!m->poisoned, -ESTALE); + + /* Make sure we have space for one more container */ + if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) { + m->poisoned = true; + return -ENOMEM; + } + + c = message_get_last_container(m); + + signature = strdup(contents); + if (!signature) { + m->poisoned = true; + return -ENOMEM; + } + + /* Save old index in the parent container, in case we have to + * abort this container */ + c->saved_index = c->index; + before = m->body_size; + + if (type == SD_BUS_TYPE_ARRAY) + r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets); + else if (type == SD_BUS_TYPE_VARIANT) + r = bus_message_open_variant(m, c, contents); + else if (type == SD_BUS_TYPE_STRUCT) + r = bus_message_open_struct(m, c, contents, &begin, &need_offsets); + else if (type == SD_BUS_TYPE_DICT_ENTRY) + r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets); + else + r = -EINVAL; + if (r < 0) + return r; + + /* OK, let's fill it in */ + m->containers[m->n_containers++] = (struct bus_container) { + .enclosing = type, + .signature = TAKE_PTR(signature), + .array_size = array_size, + .before = before, + .begin = begin, + .need_offsets = need_offsets, + }; + + return 0; +} + +static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) { + + assert(m); + assert(c); + + if (!BUS_MESSAGE_IS_GVARIANT(m)) + return 0; + + if (c->need_offsets) { + size_t payload, sz, i; + uint8_t *a; + + /* Variable-width arrays */ + + payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0; + sz = bus_gvariant_determine_word_size(payload, c->n_offsets); + + a = message_extend_body(m, 1, sz * c->n_offsets, true, false); + if (!a) + return -ENOMEM; + + for (i = 0; i < c->n_offsets; i++) + bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin); + } else { + void *a; + + /* Fixed-width or empty arrays */ + + a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */ + if (!a) + return -ENOMEM; + } + + return 0; +} + +static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) { + uint8_t *a; + size_t l; + + assert(m); + assert(c); + assert(c->signature); + + if (!BUS_MESSAGE_IS_GVARIANT(m)) + return 0; + + l = strlen(c->signature); + + a = message_extend_body(m, 1, 1 + l, true, false); + if (!a) + return -ENOMEM; + + a[0] = 0; + memcpy(a+1, c->signature, l); + + return 0; +} + +static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) { + bool fixed_size = true; + size_t n_variable = 0; + unsigned i = 0; + const char *p; + uint8_t *a; + int r; + + assert(m); + assert(c); + + if (!BUS_MESSAGE_IS_GVARIANT(m)) + return 0; + + p = strempty(c->signature); + while (*p != 0) { + size_t n; + + r = signature_element_length(p, &n); + if (r < 0) + return r; + else { + char t[n+1]; + + memcpy(t, p, n); + t[n] = 0; + + r = bus_gvariant_is_fixed_size(t); + if (r < 0) + return r; + } + + assert(!c->need_offsets || i <= c->n_offsets); + + /* We need to add an offset for each item that has a + * variable size and that is not the last one in the + * list */ + if (r == 0) + fixed_size = false; + if (r == 0 && p[n] != 0) + n_variable++; + + i++; + p += n; + } + + assert(!c->need_offsets || i == c->n_offsets); + assert(c->need_offsets || n_variable == 0); + + if (isempty(c->signature)) { + /* The unary type is encoded as fixed 1 byte padding */ + a = message_extend_body(m, 1, 1, add_offset, false); + if (!a) + return -ENOMEM; + + *a = 0; + } else if (n_variable <= 0) { + int alignment = 1; + + /* Structures with fixed-size members only have to be + * fixed-size themselves. But gvariant requires all fixed-size + * elements to be sized a multiple of their alignment. Hence, + * we must *always* add final padding after the last member so + * the overall size of the structure is properly aligned. */ + if (fixed_size) + alignment = bus_gvariant_get_alignment(strempty(c->signature)); + + assert(alignment > 0); + + a = message_extend_body(m, alignment, 0, add_offset, false); + if (!a) + return -ENOMEM; + } else { + size_t sz; + unsigned j; + + assert(c->offsets[c->n_offsets-1] == m->body_size); + + sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable); + + a = message_extend_body(m, 1, sz * n_variable, add_offset, false); + if (!a) + return -ENOMEM; + + p = strempty(c->signature); + for (i = 0, j = 0; i < c->n_offsets; i++) { + unsigned k; + size_t n; + + r = signature_element_length(p, &n); + if (r < 0) + return r; + else { + char t[n+1]; + + memcpy(t, p, n); + t[n] = 0; + + p += n; + + r = bus_gvariant_is_fixed_size(t); + if (r < 0) + return r; + if (r > 0 || p[0] == 0) + continue; + } + + k = n_variable - 1 - j; + + bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin); + + j++; + } + } + + return 0; +} + +_public_ int sd_bus_message_close_container(sd_bus_message *m) { + struct bus_container *c; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(m->n_containers > 0, -EINVAL); + assert_return(!m->poisoned, -ESTALE); + + c = message_get_last_container(m); + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + if (c->signature && c->signature[c->index] != 0) + return -EINVAL; + + m->n_containers--; + + if (c->enclosing == SD_BUS_TYPE_ARRAY) + r = bus_message_close_array(m, c); + else if (c->enclosing == SD_BUS_TYPE_VARIANT) + r = bus_message_close_variant(m, c); + else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) + r = bus_message_close_struct(m, c, true); + else + assert_not_reached("Unknown container type"); + + free(c->signature); + free(c->offsets); + + return r; +} + +typedef struct { + const char *types; + unsigned n_struct; + unsigned n_array; +} TypeStack; + +static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) { + assert(stack); + assert(max > 0); + + if (*i >= max) + return -EINVAL; + + stack[*i].types = types; + stack[*i].n_struct = n_struct; + stack[*i].n_array = n_array; + (*i)++; + + return 0; +} + +static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) { + assert(stack); + assert(max > 0); + assert(types); + assert(n_struct); + assert(n_array); + + if (*i <= 0) + return 0; + + (*i)--; + *types = stack[*i].types; + *n_struct = stack[*i].n_struct; + *n_array = stack[*i].n_array; + + return 1; +} + +_public_ int sd_bus_message_appendv( + sd_bus_message *m, + const char *types, + va_list ap) { + + unsigned n_array, n_struct; + TypeStack stack[BUS_CONTAINER_DEPTH]; + unsigned stack_ptr = 0; + int r; + + assert_return(m, -EINVAL); + assert_return(types, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(!m->poisoned, -ESTALE); + + n_array = (unsigned) -1; + n_struct = strlen(types); + + for (;;) { + const char *t; + + if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) { + r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array); + if (r < 0) + return r; + if (r == 0) + break; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + continue; + } + + t = types; + if (n_array != (unsigned) -1) + n_array--; + else { + types++; + n_struct--; + } + + switch (*t) { + + case SD_BUS_TYPE_BYTE: { + uint8_t x; + + x = (uint8_t) va_arg(ap, int); + r = sd_bus_message_append_basic(m, *t, &x); + break; + } + + case SD_BUS_TYPE_BOOLEAN: + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + case SD_BUS_TYPE_UNIX_FD: { + uint32_t x; + + /* We assume a boolean is the same as int32_t */ + assert_cc(sizeof(int32_t) == sizeof(int)); + + x = va_arg(ap, uint32_t); + r = sd_bus_message_append_basic(m, *t, &x); + break; + } + + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: { + uint16_t x; + + x = (uint16_t) va_arg(ap, int); + r = sd_bus_message_append_basic(m, *t, &x); + break; + } + + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: { + uint64_t x; + + x = va_arg(ap, uint64_t); + r = sd_bus_message_append_basic(m, *t, &x); + break; + } + + case SD_BUS_TYPE_DOUBLE: { + double x; + + x = va_arg(ap, double); + r = sd_bus_message_append_basic(m, *t, &x); + break; + } + + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: { + const char *x; + + x = va_arg(ap, const char*); + r = sd_bus_message_append_basic(m, *t, x); + break; + } + + case SD_BUS_TYPE_ARRAY: { + size_t k; + + r = signature_element_length(t + 1, &k); + if (r < 0) + return r; + + { + char s[k + 1]; + memcpy(s, t + 1, k); + s[k] = 0; + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, s); + if (r < 0) + return r; + } + + if (n_array == (unsigned) -1) { + types += k; + n_struct -= k; + } + + r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); + if (r < 0) + return r; + + types = t + 1; + n_struct = k; + n_array = va_arg(ap, unsigned); + + break; + } + + case SD_BUS_TYPE_VARIANT: { + const char *s; + + s = va_arg(ap, const char*); + if (!s) + return -EINVAL; + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, s); + if (r < 0) + return r; + + r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); + if (r < 0) + return r; + + types = s; + n_struct = strlen(s); + n_array = (unsigned) -1; + + break; + } + + case SD_BUS_TYPE_STRUCT_BEGIN: + case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { + size_t k; + + r = signature_element_length(t, &k); + if (r < 0) + return r; + + { + char s[k - 1]; + + memcpy(s, t + 1, k - 2); + s[k - 2] = 0; + + r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s); + if (r < 0) + return r; + } + + if (n_array == (unsigned) -1) { + types += k - 1; + n_struct -= k - 1; + } + + r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); + if (r < 0) + return r; + + types = t + 1; + n_struct = k - 2; + n_array = (unsigned) -1; + + break; + } + + default: + r = -EINVAL; + } + + if (r < 0) + return r; + } + + return 1; +} + +_public_ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) { + va_list ap; + int r; + + va_start(ap, types); + r = sd_bus_message_appendv(m, types, ap); + va_end(ap); + + return r; +} + +_public_ int sd_bus_message_append_array_space( + sd_bus_message *m, + char type, + size_t size, + void **ptr) { + + ssize_t align, sz; + void *a; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(bus_type_is_trivial(type) && type != SD_BUS_TYPE_BOOLEAN, -EINVAL); + assert_return(ptr || size == 0, -EINVAL); + assert_return(!m->poisoned, -ESTALE); + + /* alignment and size of the trivial types (except bool) is + * identical for gvariant and dbus1 marshalling */ + align = bus_type_get_alignment(type); + sz = bus_type_get_size(type); + + assert_se(align > 0); + assert_se(sz > 0); + + if (size % sz != 0) + return -EINVAL; + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)); + if (r < 0) + return r; + + a = message_extend_body(m, align, size, false, false); + if (!a) + return -ENOMEM; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + *ptr = a; + return 0; +} + +_public_ int sd_bus_message_append_array( + sd_bus_message *m, + char type, + const void *ptr, + size_t size) { + int r; + void *p; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(bus_type_is_trivial(type), -EINVAL); + assert_return(ptr || size == 0, -EINVAL); + assert_return(!m->poisoned, -ESTALE); + + r = sd_bus_message_append_array_space(m, type, size, &p); + if (r < 0) + return r; + + memcpy_safe(p, ptr, size); + + return 0; +} + +_public_ int sd_bus_message_append_array_iovec( + sd_bus_message *m, + char type, + const struct iovec *iov, + unsigned n /* should be size_t, but is API now… 😞 */) { + + size_t size; + unsigned i; + void *p; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(bus_type_is_trivial(type), -EINVAL); + assert_return(iov || n == 0, -EINVAL); + assert_return(!m->poisoned, -ESTALE); + + size = IOVEC_TOTAL_SIZE(iov, n); + + r = sd_bus_message_append_array_space(m, type, size, &p); + if (r < 0) + return r; + + for (i = 0; i < n; i++) { + + if (iov[i].iov_base) + memcpy(p, iov[i].iov_base, iov[i].iov_len); + else + memzero(p, iov[i].iov_len); + + p = (uint8_t*) p + iov[i].iov_len; + } + + return 0; +} + +_public_ int sd_bus_message_append_array_memfd( + sd_bus_message *m, + char type, + int memfd, + uint64_t offset, + uint64_t size) { + + _cleanup_close_ int copy_fd = -1; + struct bus_body_part *part; + ssize_t align, sz; + uint64_t real_size; + void *a; + int r; + + assert_return(m, -EINVAL); + assert_return(memfd >= 0, -EBADF); + assert_return(bus_type_is_trivial(type), -EINVAL); + assert_return(size > 0, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(!m->poisoned, -ESTALE); + + r = memfd_set_sealed(memfd); + if (r < 0) + return r; + + copy_fd = fcntl(memfd, F_DUPFD_CLOEXEC, 3); + if (copy_fd < 0) + return copy_fd; + + r = memfd_get_size(memfd, &real_size); + if (r < 0) + return r; + + if (offset == 0 && size == (uint64_t) -1) + size = real_size; + else if (offset + size > real_size) + return -EMSGSIZE; + + align = bus_type_get_alignment(type); + sz = bus_type_get_size(type); + + assert_se(align > 0); + assert_se(sz > 0); + + if (offset % align != 0) + return -EINVAL; + + if (size % sz != 0) + return -EINVAL; + + if (size > (uint64_t) (uint32_t) -1) + return -EINVAL; + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)); + if (r < 0) + return r; + + a = message_extend_body(m, align, 0, false, false); + if (!a) + return -ENOMEM; + + part = message_append_part(m); + if (!part) + return -ENOMEM; + + part->memfd = copy_fd; + part->memfd_offset = offset; + part->sealed = true; + part->size = size; + copy_fd = -1; + + m->body_size += size; + message_extend_containers(m, size); + + return sd_bus_message_close_container(m); +} + +_public_ int sd_bus_message_append_string_memfd( + sd_bus_message *m, + int memfd, + uint64_t offset, + uint64_t size) { + + _cleanup_close_ int copy_fd = -1; + struct bus_body_part *part; + struct bus_container *c; + uint64_t real_size; + void *a; + int r; + + assert_return(m, -EINVAL); + assert_return(memfd >= 0, -EBADF); + assert_return(size > 0, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(!m->poisoned, -ESTALE); + + r = memfd_set_sealed(memfd); + if (r < 0) + return r; + + copy_fd = fcntl(memfd, FD_CLOEXEC, 3); + if (copy_fd < 0) + return copy_fd; + + r = memfd_get_size(memfd, &real_size); + if (r < 0) + return r; + + if (offset == 0 && size == (uint64_t) -1) + size = real_size; + else if (offset + size > real_size) + return -EMSGSIZE; + + /* We require this to be NUL terminated */ + if (size == 0) + return -EINVAL; + + if (size > (uint64_t) (uint32_t) -1) + return -EINVAL; + + c = message_get_last_container(m); + if (c->signature && c->signature[c->index]) { + /* Container signature is already set */ + + if (c->signature[c->index] != SD_BUS_TYPE_STRING) + return -ENXIO; + } else { + char *e; + + /* Maybe we can append to the signature? But only if this is the top-level container */ + if (c->enclosing != 0) + return -ENXIO; + + e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL); + if (!e) { + m->poisoned = true; + return -ENOMEM; + } + } + + if (!BUS_MESSAGE_IS_GVARIANT(m)) { + a = message_extend_body(m, 4, 4, false, false); + if (!a) + return -ENOMEM; + + *(uint32_t*) a = size - 1; + } + + part = message_append_part(m); + if (!part) + return -ENOMEM; + + part->memfd = copy_fd; + part->memfd_offset = offset; + part->sealed = true; + part->size = size; + copy_fd = -1; + + m->body_size += size; + message_extend_containers(m, size); + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + r = message_add_offset(m, m->body_size); + if (r < 0) { + m->poisoned = true; + return -ENOMEM; + } + } + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index++; + + return 0; +} + +_public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) { + char **i; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(!m->poisoned, -ESTALE); + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return r; + + STRV_FOREACH(i, l) { + r = sd_bus_message_append_basic(m, 's', *i); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(m); +} + +static int bus_message_close_header(sd_bus_message *m) { + + assert(m); + + /* The actual user data is finished now, we just complete the + variant and struct now (at least on gvariant). Remember + this position, so that during parsing we know where to + put the outer container end. */ + m->user_body_size = m->body_size; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + const char *signature; + size_t sz, l; + void *d; + + /* Add offset table to end of fields array */ + if (m->n_header_offsets >= 1) { + uint8_t *a; + unsigned i; + + assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]); + + sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets); + a = message_extend_fields(m, 1, sz * m->n_header_offsets, false); + if (!a) + return -ENOMEM; + + for (i = 0; i < m->n_header_offsets; i++) + bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]); + } + + /* Add gvariant NUL byte plus signature to the end of + * the body, followed by the final offset pointing to + * the end of the fields array */ + + signature = strempty(m->root_container.signature); + l = strlen(signature); + + sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1); + d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true); + if (!d) + return -ENOMEM; + + *(uint8_t*) d = 0; + *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN; + memcpy((uint8_t*) d + 2, signature, l); + *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END; + + bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size); + + m->footer = d; + m->footer_accessible = 1 + l + 2 + sz; + } else { + m->header->dbus1.fields_size = m->fields_size; + m->header->dbus1.body_size = m->body_size; + } + + return 0; +} + +_public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec) { + struct bus_body_part *part; + size_t a; + unsigned i; + int r; + + assert_return(m, -EINVAL); + + if (m->sealed) + return -EPERM; + + if (m->n_containers > 0) + return -EBADMSG; + + if (m->poisoned) + return -ESTALE; + + if (cookie > 0xffffffffULL && + !BUS_MESSAGE_IS_GVARIANT(m)) + return -EOPNOTSUPP; + + /* In vtables the return signature of method calls is listed, + * let's check if they match if this is a response */ + if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN && + m->enforced_reply_signature && + !streq(strempty(m->root_container.signature), m->enforced_reply_signature)) + return -ENOMSG; + + /* If gvariant marshalling is used we need to close the body structure */ + r = bus_message_close_struct(m, &m->root_container, false); + if (r < 0) + return r; + + /* If there's a non-trivial signature set, then add it in + * here, but only on dbus1 */ + if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) { + r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL); + if (r < 0) + return r; + } + + if (m->n_fds > 0) { + r = message_append_field_uint32(m, BUS_MESSAGE_HEADER_UNIX_FDS, m->n_fds); + if (r < 0) + return r; + } + + r = bus_message_close_header(m); + if (r < 0) + return r; + + if (BUS_MESSAGE_IS_GVARIANT(m)) + m->header->dbus2.cookie = cookie; + else + m->header->dbus1.serial = (uint32_t) cookie; + + m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec; + + /* Add padding at the end of the fields part, since we know + * the body needs to start at an 8 byte alignment. We made + * sure we allocated enough space for this, so all we need to + * do here is to zero it out. */ + a = ALIGN8(m->fields_size) - m->fields_size; + if (a > 0) + memzero((uint8_t*) BUS_MESSAGE_FIELDS(m) + m->fields_size, a); + + /* If this is something we can send as memfd, then let's seal + the memfd now. Note that we can send memfds as payload only + for directed messages, and not for broadcasts. */ + if (m->destination && m->bus->use_memfd) { + MESSAGE_FOREACH_PART(part, i, m) + if (part->memfd >= 0 && + !part->sealed && + (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0) && + part != m->body_end) { /* The last part may never be sent as memfd */ + uint64_t sz; + + /* Try to seal it if that makes + * sense. First, unmap our own map to + * make sure we don't keep it busy. */ + bus_body_part_unmap(part); + + /* Then, sync up real memfd size */ + sz = part->size; + r = memfd_set_size(part->memfd, sz); + if (r < 0) + return r; + + /* Finally, try to seal */ + if (memfd_set_sealed(part->memfd) >= 0) + part->sealed = true; + } + } + + m->root_container.end = m->user_body_size; + m->root_container.index = 0; + m->root_container.offset_index = 0; + m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0; + + m->sealed = true; + + return 0; +} + +int bus_body_part_map(struct bus_body_part *part) { + void *p; + size_t psz, shift; + + assert_se(part); + + if (part->data) + return 0; + + if (part->size <= 0) + return 0; + + /* For smaller zero parts (as used for padding) we don't need to map anything... */ + if (part->memfd < 0 && part->is_zero && part->size < 8) { + static const uint8_t zeroes[7] = { }; + part->data = (void*) zeroes; + return 0; + } + + shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size()); + psz = PAGE_ALIGN(part->size + shift); + + if (part->memfd >= 0) + p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift); + else if (part->is_zero) + p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + else + return -EINVAL; + + if (p == MAP_FAILED) + return -errno; + + part->mapped = psz; + part->mmap_begin = p; + part->data = (uint8_t*) p + shift; + part->munmap_this = true; + + return 0; +} + +void bus_body_part_unmap(struct bus_body_part *part) { + + assert_se(part); + + if (part->memfd < 0) + return; + + if (!part->mmap_begin) + return; + + if (!part->munmap_this) + return; + + assert_se(munmap(part->mmap_begin, part->mapped) == 0); + + part->mmap_begin = NULL; + part->data = NULL; + part->mapped = 0; + part->munmap_this = false; + + return; +} + +static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) { + size_t k, start, end; + + assert(rindex); + assert(align > 0); + + start = ALIGN_TO((size_t) *rindex, align); + end = start + nbytes; + + if (end > sz) + return -EBADMSG; + + /* Verify that padding is 0 */ + for (k = *rindex; k < start; k++) + if (((const uint8_t*) p)[k] != 0) + return -EBADMSG; + + if (r) + *r = (uint8_t*) p + start; + + *rindex = end; + + return 1; +} + +static bool message_end_of_signature(sd_bus_message *m) { + struct bus_container *c; + + assert(m); + + c = message_get_last_container(m); + return !c->signature || c->signature[c->index] == 0; +} + +static bool message_end_of_array(sd_bus_message *m, size_t index) { + struct bus_container *c; + + assert(m); + + c = message_get_last_container(m); + if (c->enclosing != SD_BUS_TYPE_ARRAY) + return false; + + if (BUS_MESSAGE_IS_GVARIANT(m)) + return index >= c->end; + else { + assert(c->array_size); + return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size); + } +} + +_public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) { + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + + if (complete && m->n_containers > 0) + return false; + + if (message_end_of_signature(m)) + return true; + + if (message_end_of_array(m, m->rindex)) + return true; + + return false; +} + +static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t sz, void **p) { + struct bus_body_part *part; + size_t begin; + int r; + + assert(m); + + if (m->cached_rindex_part && index >= m->cached_rindex_part_begin) { + part = m->cached_rindex_part; + begin = m->cached_rindex_part_begin; + } else { + part = &m->body; + begin = 0; + } + + while (part) { + if (index < begin) + return NULL; + + if (index + sz <= begin + part->size) { + + r = bus_body_part_map(part); + if (r < 0) + return NULL; + + if (p) + *p = (uint8_t*) part->data + index - begin; + + m->cached_rindex_part = part; + m->cached_rindex_part_begin = begin; + + return part; + } + + begin += part->size; + part = part->next; + } + + return NULL; +} + +static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) { + int r; + + assert(m); + assert(c); + assert(rindex); + + if (!BUS_MESSAGE_IS_GVARIANT(m)) + return 0; + + if (c->enclosing == SD_BUS_TYPE_ARRAY) { + int sz; + + sz = bus_gvariant_get_size(c->signature); + if (sz < 0) { + int alignment; + + if (c->offset_index+1 >= c->n_offsets) + goto end; + + /* Variable-size array */ + + alignment = bus_gvariant_get_alignment(c->signature); + assert(alignment > 0); + + *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment); + assert(c->offsets[c->offset_index+1] >= *rindex); + c->item_size = c->offsets[c->offset_index+1] - *rindex; + } else { + + if (c->offset_index+1 >= (c->end-c->begin)/sz) + goto end; + + /* Fixed-size array */ + *rindex = c->begin + (c->offset_index+1) * sz; + c->item_size = sz; + } + + c->offset_index++; + + } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) { + + int alignment; + size_t n, j; + + if (c->offset_index+1 >= c->n_offsets) + goto end; + + r = signature_element_length(c->signature + c->index, &n); + if (r < 0) + return r; + + r = signature_element_length(c->signature + c->index + n, &j); + if (r < 0) + return r; + else { + char t[j+1]; + memcpy(t, c->signature + c->index + n, j); + t[j] = 0; + + alignment = bus_gvariant_get_alignment(t); + } + + assert(alignment > 0); + + *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment); + assert(c->offsets[c->offset_index+1] >= *rindex); + c->item_size = c->offsets[c->offset_index+1] - *rindex; + + c->offset_index++; + + } else if (c->enclosing == SD_BUS_TYPE_VARIANT) + goto end; + else + assert_not_reached("Unknown container type"); + + return 0; + +end: + /* Reached the end */ + *rindex = c->end; + c->item_size = 0; + return 0; +} + +static int message_peek_body( + sd_bus_message *m, + size_t *rindex, + size_t align, + size_t nbytes, + void **ret) { + + size_t k, start, end, padding; + struct bus_body_part *part; + uint8_t *q; + + assert(m); + assert(rindex); + assert(align > 0); + + start = ALIGN_TO((size_t) *rindex, align); + padding = start - *rindex; + end = start + nbytes; + + if (end > m->user_body_size) + return -EBADMSG; + + part = find_part(m, *rindex, padding, (void**) &q); + if (!part) + return -EBADMSG; + + if (q) { + /* Verify padding */ + for (k = 0; k < padding; k++) + if (q[k] != 0) + return -EBADMSG; + } + + part = find_part(m, start, nbytes, (void**) &q); + if (!part || (nbytes > 0 && !q)) + return -EBADMSG; + + *rindex = end; + + if (ret) + *ret = q; + + return 0; +} + +static bool validate_nul(const char *s, size_t l) { + + /* Check for NUL chars in the string */ + if (memchr(s, 0, l)) + return false; + + /* Check for NUL termination */ + if (s[l] != 0) + return false; + + return true; +} + +static bool validate_string(const char *s, size_t l) { + + if (!validate_nul(s, l)) + return false; + + /* Check if valid UTF8 */ + if (!utf8_is_valid(s)) + return false; + + return true; +} + +static bool validate_signature(const char *s, size_t l) { + + if (!validate_nul(s, l)) + return false; + + /* Check if valid signature */ + if (!signature_is_valid(s, true)) + return false; + + return true; +} + +static bool validate_object_path(const char *s, size_t l) { + + if (!validate_nul(s, l)) + return false; + + if (!object_path_is_valid(s)) + return false; + + return true; +} + +_public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { + struct bus_container *c; + size_t rindex; + void *q; + int r; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + assert_return(bus_type_is_basic(type), -EINVAL); + + if (message_end_of_signature(m)) + return -ENXIO; + + if (message_end_of_array(m, m->rindex)) + return 0; + + c = message_get_last_container(m); + if (c->signature[c->index] != type) + return -ENXIO; + + rindex = m->rindex; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + + if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) { + bool ok; + + /* D-Bus spec: The marshalling formats for the string-like types all end + * with a single zero (NUL) byte, but that byte is not considered to be part + * of the text. */ + if (c->item_size == 0) + return -EBADMSG; + + r = message_peek_body(m, &rindex, 1, c->item_size, &q); + if (r < 0) + return r; + + if (type == SD_BUS_TYPE_STRING) + ok = validate_string(q, c->item_size-1); + else if (type == SD_BUS_TYPE_OBJECT_PATH) + ok = validate_object_path(q, c->item_size-1); + else + ok = validate_signature(q, c->item_size-1); + + if (!ok) + return -EBADMSG; + + if (p) + *(const char**) p = q; + } else { + int sz, align; + + sz = bus_gvariant_get_size(CHAR_TO_STR(type)); + assert(sz > 0); + if ((size_t) sz != c->item_size) + return -EBADMSG; + + align = bus_gvariant_get_alignment(CHAR_TO_STR(type)); + assert(align > 0); + + r = message_peek_body(m, &rindex, align, c->item_size, &q); + if (r < 0) + return r; + + switch (type) { + + case SD_BUS_TYPE_BYTE: + if (p) + *(uint8_t*) p = *(uint8_t*) q; + break; + + case SD_BUS_TYPE_BOOLEAN: + if (p) + *(int*) p = !!*(uint8_t*) q; + break; + + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: + if (p) + *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q); + break; + + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + if (p) + *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + break; + + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: + case SD_BUS_TYPE_DOUBLE: + if (p) + *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q); + break; + + case SD_BUS_TYPE_UNIX_FD: { + uint32_t j; + + j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + if (j >= m->n_fds) + return -EBADMSG; + + if (p) + *(int*) p = m->fds[j]; + + break; + } + + default: + assert_not_reached("unexpected type"); + } + } + + r = container_next_item(m, c, &rindex); + if (r < 0) + return r; + } else { + + if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) { + uint32_t l; + bool ok; + + r = message_peek_body(m, &rindex, 4, 4, &q); + if (r < 0) + return r; + + l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + if (l == UINT32_MAX) + /* avoid overflow right below */ + return -EBADMSG; + + r = message_peek_body(m, &rindex, 1, l+1, &q); + if (r < 0) + return r; + + if (type == SD_BUS_TYPE_OBJECT_PATH) + ok = validate_object_path(q, l); + else + ok = validate_string(q, l); + if (!ok) + return -EBADMSG; + + if (p) + *(const char**) p = q; + + } else if (type == SD_BUS_TYPE_SIGNATURE) { + uint8_t l; + + r = message_peek_body(m, &rindex, 1, 1, &q); + if (r < 0) + return r; + + l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + + r = message_peek_body(m, &rindex, 1, l+1, &q); + if (r < 0) + return r; + + if (!validate_signature(q, l)) + return -EBADMSG; + + if (p) + *(const char**) p = q; + + } else { + ssize_t sz, align; + + align = bus_type_get_alignment(type); + assert(align > 0); + + sz = bus_type_get_size(type); + assert(sz > 0); + + r = message_peek_body(m, &rindex, align, sz, &q); + if (r < 0) + return r; + + switch (type) { + + case SD_BUS_TYPE_BYTE: + if (p) + *(uint8_t*) p = *(uint8_t*) q; + break; + + case SD_BUS_TYPE_BOOLEAN: + if (p) + *(int*) p = !!*(uint32_t*) q; + break; + + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: + if (p) + *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q); + break; + + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + if (p) + *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + break; + + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: + case SD_BUS_TYPE_DOUBLE: + if (p) + *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q); + break; + + case SD_BUS_TYPE_UNIX_FD: { + uint32_t j; + + j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + if (j >= m->n_fds) + return -EBADMSG; + + if (p) + *(int*) p = m->fds[j]; + break; + } + + default: + assert_not_reached("Unknown basic type..."); + } + } + } + + m->rindex = rindex; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index++; + + return 1; +} + +static int bus_message_enter_array( + sd_bus_message *m, + struct bus_container *c, + const char *contents, + uint32_t **array_size, + size_t *item_size, + size_t **offsets, + size_t *n_offsets) { + + size_t rindex; + void *q; + int r; + + assert(m); + assert(c); + assert(contents); + assert(array_size); + assert(item_size); + assert(offsets); + assert(n_offsets); + + if (!signature_is_single(contents, true)) + return -EINVAL; + + if (!c->signature || c->signature[c->index] == 0) + return -ENXIO; + + if (c->signature[c->index] != SD_BUS_TYPE_ARRAY) + return -ENXIO; + + if (!startswith(c->signature + c->index + 1, contents)) + return -ENXIO; + + rindex = m->rindex; + + if (!BUS_MESSAGE_IS_GVARIANT(m)) { + /* dbus1 */ + int alignment; + + r = message_peek_body(m, &rindex, 4, 4, &q); + if (r < 0) + return r; + + if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE) + return -EBADMSG; + + alignment = bus_type_get_alignment(contents[0]); + if (alignment < 0) + return alignment; + + r = message_peek_body(m, &rindex, alignment, 0, NULL); + if (r < 0) + return r; + + *array_size = (uint32_t*) q; + + } else if (c->item_size <= 0) { + + /* gvariant: empty array */ + *item_size = 0; + *offsets = NULL; + *n_offsets = 0; + + } else if (bus_gvariant_is_fixed_size(contents)) { + + /* gvariant: fixed length array */ + *item_size = bus_gvariant_get_size(contents); + *offsets = NULL; + *n_offsets = 0; + + } else { + size_t where, previous = 0, framing, sz; + int alignment; + unsigned i; + + /* gvariant: variable length array */ + sz = bus_gvariant_determine_word_size(c->item_size, 0); + + where = rindex + c->item_size - sz; + r = message_peek_body(m, &where, 1, sz, &q); + if (r < 0) + return r; + + framing = bus_gvariant_read_word_le(q, sz); + if (framing > c->item_size - sz) + return -EBADMSG; + if ((c->item_size - framing) % sz != 0) + return -EBADMSG; + + *n_offsets = (c->item_size - framing) / sz; + + where = rindex + framing; + r = message_peek_body(m, &where, 1, *n_offsets * sz, &q); + if (r < 0) + return r; + + *offsets = new(size_t, *n_offsets); + if (!*offsets) + return -ENOMEM; + + alignment = bus_gvariant_get_alignment(c->signature); + assert(alignment > 0); + + for (i = 0; i < *n_offsets; i++) { + size_t x, start; + + start = ALIGN_TO(previous, alignment); + + x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz); + if (x > c->item_size - sz) + return -EBADMSG; + if (x < start) + return -EBADMSG; + + (*offsets)[i] = rindex + x; + previous = x; + } + + *item_size = (*offsets)[0] - rindex; + } + + m->rindex = rindex; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index += 1 + strlen(contents); + + return 1; +} + +static int bus_message_enter_variant( + sd_bus_message *m, + struct bus_container *c, + const char *contents, + size_t *item_size) { + + size_t rindex; + uint8_t l; + void *q; + int r; + + assert(m); + assert(c); + assert(contents); + assert(item_size); + + if (!signature_is_single(contents, false)) + return -EINVAL; + + if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN) + return -EINVAL; + + if (!c->signature || c->signature[c->index] == 0) + return -ENXIO; + + if (c->signature[c->index] != SD_BUS_TYPE_VARIANT) + return -ENXIO; + + rindex = m->rindex; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + size_t k, where; + + k = strlen(contents); + if (1+k > c->item_size) + return -EBADMSG; + + where = rindex + c->item_size - (1+k); + r = message_peek_body(m, &where, 1, 1+k, &q); + if (r < 0) + return r; + + if (*(char*) q != 0) + return -EBADMSG; + + if (memcmp((uint8_t*) q+1, contents, k)) + return -ENXIO; + + *item_size = c->item_size - (1+k); + + } else { + r = message_peek_body(m, &rindex, 1, 1, &q); + if (r < 0) + return r; + + l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + + r = message_peek_body(m, &rindex, 1, l+1, &q); + if (r < 0) + return r; + + if (!validate_signature(q, l)) + return -EBADMSG; + + if (!streq(q, contents)) + return -ENXIO; + } + + m->rindex = rindex; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index++; + + return 1; +} + +static int build_struct_offsets( + sd_bus_message *m, + const char *signature, + size_t size, + size_t *item_size, + size_t **offsets, + size_t *n_offsets) { + + unsigned n_variable = 0, n_total = 0, v; + size_t previous, where; + const char *p; + size_t sz; + void *q; + int r; + + assert(m); + assert(item_size); + assert(offsets); + assert(n_offsets); + + if (isempty(signature)) { + /* Unary type is encoded as *fixed* 1 byte padding */ + r = message_peek_body(m, &m->rindex, 1, 1, &q); + if (r < 0) + return r; + + if (*(uint8_t *) q != 0) + return -EBADMSG; + + *item_size = 0; + *offsets = NULL; + *n_offsets = 0; + return 0; + } + + sz = bus_gvariant_determine_word_size(size, 0); + if (sz <= 0) + return -EBADMSG; + + /* First, loop over signature and count variable elements and + * elements in general. We use this to know how large the + * offset array is at the end of the structure. Note that + * GVariant only stores offsets for all variable size elements + * that are not the last item. */ + + p = signature; + while (*p != 0) { + size_t n; + + r = signature_element_length(p, &n); + if (r < 0) + return r; + else { + char t[n+1]; + + memcpy(t, p, n); + t[n] = 0; + + r = bus_gvariant_is_fixed_size(t); + } + + if (r < 0) + return r; + if (r == 0 && p[n] != 0) /* except the last item */ + n_variable++; + n_total++; + + p += n; + } + + if (size < n_variable * sz) + return -EBADMSG; + + where = m->rindex + size - (n_variable * sz); + r = message_peek_body(m, &where, 1, n_variable * sz, &q); + if (r < 0) + return r; + + v = n_variable; + + *offsets = new(size_t, n_total); + if (!*offsets) + return -ENOMEM; + + *n_offsets = 0; + + /* Second, loop again and build an offset table */ + p = signature; + previous = m->rindex; + while (*p != 0) { + size_t n, offset; + int k; + + r = signature_element_length(p, &n); + if (r < 0) + return r; + else { + char t[n+1]; + + memcpy(t, p, n); + t[n] = 0; + + size_t align = bus_gvariant_get_alignment(t); + assert(align > 0); + + /* The possible start of this member after including alignment */ + size_t start = ALIGN_TO(previous, align); + + k = bus_gvariant_get_size(t); + if (k < 0) { + size_t x; + + /* Variable size */ + if (v > 0) { + v--; + + x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz); + if (x >= size) + return -EBADMSG; + } else + /* The last item's end is determined + * from the start of the offset array */ + x = size - (n_variable * sz); + + offset = m->rindex + x; + if (offset < start) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu", + t, align, + offset, + previous, + start); + } else + /* Fixed size */ + offset = start + k; + } + + previous = (*offsets)[(*n_offsets)++] = offset; + p += n; + } + + assert(v == 0); + assert(*n_offsets == n_total); + + *item_size = (*offsets)[0] - m->rindex; + return 0; +} + +static int enter_struct_or_dict_entry( + sd_bus_message *m, + struct bus_container *c, + const char *contents, + size_t *item_size, + size_t **offsets, + size_t *n_offsets) { + + int r; + + assert(m); + assert(c); + assert(contents); + assert(item_size); + assert(offsets); + assert(n_offsets); + + if (!BUS_MESSAGE_IS_GVARIANT(m)) { + + /* dbus1 */ + r = message_peek_body(m, &m->rindex, 8, 0, NULL); + if (r < 0) + return r; + + } else + /* gvariant with contents */ + return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets); + + return 0; +} + +static int bus_message_enter_struct( + sd_bus_message *m, + struct bus_container *c, + const char *contents, + size_t *item_size, + size_t **offsets, + size_t *n_offsets) { + + size_t l; + int r; + + assert(m); + assert(c); + assert(contents); + assert(item_size); + assert(offsets); + assert(n_offsets); + + if (!signature_is_valid(contents, false)) + return -EINVAL; + + if (!c->signature || c->signature[c->index] == 0) + return -ENXIO; + + l = strlen(contents); + + if (c->signature[c->index] != SD_BUS_TYPE_STRUCT_BEGIN || + !startswith(c->signature + c->index + 1, contents) || + c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END) + return -ENXIO; + + r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets); + if (r < 0) + return r; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index += 1 + l + 1; + + return 1; +} + +static int bus_message_enter_dict_entry( + sd_bus_message *m, + struct bus_container *c, + const char *contents, + size_t *item_size, + size_t **offsets, + size_t *n_offsets) { + + size_t l; + int r; + + assert(m); + assert(c); + assert(contents); + + if (!signature_is_pair(contents)) + return -EINVAL; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + return -ENXIO; + + if (!c->signature || c->signature[c->index] == 0) + return 0; + + l = strlen(contents); + + if (c->signature[c->index] != SD_BUS_TYPE_DICT_ENTRY_BEGIN || + !startswith(c->signature + c->index + 1, contents) || + c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END) + return -ENXIO; + + r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets); + if (r < 0) + return r; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index += 1 + l + 1; + + return 1; +} + +_public_ int sd_bus_message_enter_container(sd_bus_message *m, + char type, + const char *contents) { + struct bus_container *c; + uint32_t *array_size = NULL; + _cleanup_free_ char *signature = NULL; + size_t before, end; + _cleanup_free_ size_t *offsets = NULL; + size_t n_offsets = 0, item_size = 0; + int r; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + assert_return(type != 0 || !contents, -EINVAL); + + if (type == 0 || !contents) { + const char *cc; + char tt; + + /* Allow entering into anonymous containers */ + r = sd_bus_message_peek_type(m, &tt, &cc); + if (r < 0) + return r; + + if (type != 0 && type != tt) + return -ENXIO; + + if (contents && !streq(contents, cc)) + return -ENXIO; + + type = tt; + contents = cc; + } + + /* + * We enforce a global limit on container depth, that is much + * higher than the 32 structs and 32 arrays the specification + * mandates. This is simpler to implement for us, and we need + * this only to ensure our container array doesn't grow + * without bounds. We are happy to return any data from a + * message as long as the data itself is valid, even if the + * overall message might be not. + * + * Note that the message signature is validated when + * parsing the headers, and that validation does check the + * 32/32 limit. + * + * Note that the specification defines no limits on the depth + * of stacked variants, but we do. + */ + if (m->n_containers >= BUS_CONTAINER_DEPTH) + return -EBADMSG; + + if (!GREEDY_REALLOC(m->containers, m->containers_allocated, m->n_containers + 1)) + return -ENOMEM; + + if (message_end_of_signature(m)) + return -ENXIO; + + if (message_end_of_array(m, m->rindex)) + return 0; + + c = message_get_last_container(m); + + signature = strdup(contents); + if (!signature) + return -ENOMEM; + + c->saved_index = c->index; + before = m->rindex; + + if (type == SD_BUS_TYPE_ARRAY) + r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets); + else if (type == SD_BUS_TYPE_VARIANT) + r = bus_message_enter_variant(m, c, contents, &item_size); + else if (type == SD_BUS_TYPE_STRUCT) + r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets); + else if (type == SD_BUS_TYPE_DICT_ENTRY) + r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets); + else + r = -EINVAL; + if (r <= 0) + return r; + + /* OK, let's fill it in */ + if (BUS_MESSAGE_IS_GVARIANT(m) && + type == SD_BUS_TYPE_STRUCT && + isempty(signature)) + end = m->rindex + 0; + else + end = m->rindex + c->item_size; + + m->containers[m->n_containers++] = (struct bus_container) { + .enclosing = type, + .signature = TAKE_PTR(signature), + + .before = before, + .begin = m->rindex, + /* Unary type has fixed size of 1, but virtual size of 0 */ + .end = end, + .array_size = array_size, + .item_size = item_size, + .offsets = TAKE_PTR(offsets), + .n_offsets = n_offsets, + }; + + return 1; +} + +_public_ int sd_bus_message_exit_container(sd_bus_message *m) { + struct bus_container *c; + unsigned saved; + int r; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + assert_return(m->n_containers > 0, -ENXIO); + + c = message_get_last_container(m); + + if (c->enclosing != SD_BUS_TYPE_ARRAY) { + if (c->signature && c->signature[c->index] != 0) + return -EBUSY; + } + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + if (m->rindex < c->end) + return -EBUSY; + + } else if (c->enclosing == SD_BUS_TYPE_ARRAY) { + uint32_t l; + + l = BUS_MESSAGE_BSWAP32(m, *c->array_size); + if (c->begin + l != m->rindex) + return -EBUSY; + } + + message_free_last_container(m); + + c = message_get_last_container(m); + saved = c->index; + c->index = c->saved_index; + r = container_next_item(m, c, &m->rindex); + c->index = saved; + if (r < 0) + return r; + + return 1; +} + +static void message_quit_container(sd_bus_message *m) { + struct bus_container *c; + + assert(m); + assert(m->sealed); + assert(m->n_containers > 0); + + /* Undo seeks */ + c = message_get_last_container(m); + assert(m->rindex >= c->before); + m->rindex = c->before; + + /* Free container */ + message_free_last_container(m); + + /* Correct index of new top-level container */ + c = message_get_last_container(m); + c->index = c->saved_index; +} + +_public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) { + struct bus_container *c; + int r; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + + if (message_end_of_signature(m)) + goto eof; + + if (message_end_of_array(m, m->rindex)) + goto eof; + + c = message_get_last_container(m); + + if (bus_type_is_basic(c->signature[c->index])) { + if (contents) + *contents = NULL; + if (type) + *type = c->signature[c->index]; + return 1; + } + + if (c->signature[c->index] == SD_BUS_TYPE_ARRAY) { + + if (contents) { + size_t l; + + r = signature_element_length(c->signature+c->index+1, &l); + if (r < 0) + return r; + + /* signature_element_length does verification internally */ + + /* The array element must not be empty */ + assert(l >= 1); + if (free_and_strndup(&c->peeked_signature, + c->signature + c->index + 1, l) < 0) + return -ENOMEM; + + *contents = c->peeked_signature; + } + + if (type) + *type = SD_BUS_TYPE_ARRAY; + + return 1; + } + + if (IN_SET(c->signature[c->index], SD_BUS_TYPE_STRUCT_BEGIN, SD_BUS_TYPE_DICT_ENTRY_BEGIN)) { + + if (contents) { + size_t l; + + r = signature_element_length(c->signature+c->index, &l); + if (r < 0) + return r; + + assert(l >= 3); + if (free_and_strndup(&c->peeked_signature, + c->signature + c->index + 1, l - 2) < 0) + return -ENOMEM; + + *contents = c->peeked_signature; + } + + if (type) + *type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY; + + return 1; + } + + if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) { + if (contents) { + void *q; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + size_t k; + + if (c->item_size < 2) + return -EBADMSG; + + /* Look for the NUL delimiter that + separates the payload from the + signature. Since the body might be + in a different part that then the + signature we map byte by byte. */ + + for (k = 2; k <= c->item_size; k++) { + size_t where; + + where = m->rindex + c->item_size - k; + r = message_peek_body(m, &where, 1, k, &q); + if (r < 0) + return r; + + if (*(char*) q == 0) + break; + } + + if (k > c->item_size) + return -EBADMSG; + + if (free_and_strndup(&c->peeked_signature, + (char*) q + 1, k - 1) < 0) + return -ENOMEM; + + if (!signature_is_valid(c->peeked_signature, true)) + return -EBADMSG; + + *contents = c->peeked_signature; + } else { + size_t rindex, l; + + rindex = m->rindex; + r = message_peek_body(m, &rindex, 1, 1, &q); + if (r < 0) + return r; + + l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + + r = message_peek_body(m, &rindex, 1, l+1, &q); + if (r < 0) + return r; + + if (!validate_signature(q, l)) + return -EBADMSG; + + *contents = q; + } + } + + if (type) + *type = SD_BUS_TYPE_VARIANT; + + return 1; + } + + return -EINVAL; + +eof: + if (type) + *type = 0; + if (contents) + *contents = NULL; + return 0; +} + +_public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) { + struct bus_container *c; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + + if (complete) { + message_reset_containers(m); + m->rindex = 0; + + c = message_get_last_container(m); + } else { + c = message_get_last_container(m); + + c->index = 0; + m->rindex = c->begin; + } + + c->offset_index = 0; + c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin; + + return !isempty(c->signature); +} + +_public_ int sd_bus_message_readv( + sd_bus_message *m, + const char *types, + va_list ap) { + + unsigned n_array, n_struct; + TypeStack stack[BUS_CONTAINER_DEPTH]; + unsigned stack_ptr = 0; + unsigned n_loop = 0; + int r; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + assert_return(types, -EINVAL); + + if (isempty(types)) + return 0; + + /* Ideally, we'd just call ourselves recursively on every + * complex type. However, the state of a va_list that is + * passed to a function is undefined after that function + * returns. This means we need to decode the va_list linearly + * in a single stackframe. We hence implement our own + * home-grown stack in an array. */ + + n_array = (unsigned) -1; /* length of current array entries */ + n_struct = strlen(types); /* length of current struct contents signature */ + + for (;;) { + const char *t; + + n_loop++; + + if (n_array == 0 || (n_array == (unsigned) -1 && n_struct == 0)) { + r = type_stack_pop(stack, ELEMENTSOF(stack), &stack_ptr, &types, &n_struct, &n_array); + if (r < 0) + return r; + if (r == 0) + break; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + continue; + } + + t = types; + if (n_array != (unsigned) -1) + n_array--; + else { + types++; + n_struct--; + } + + switch (*t) { + + case SD_BUS_TYPE_BYTE: + case SD_BUS_TYPE_BOOLEAN: + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: + case SD_BUS_TYPE_DOUBLE: + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: + case SD_BUS_TYPE_UNIX_FD: { + void *p; + + p = va_arg(ap, void*); + r = sd_bus_message_read_basic(m, *t, p); + if (r < 0) + return r; + if (r == 0) { + if (n_loop <= 1) + return 0; + + return -ENXIO; + } + + break; + } + + case SD_BUS_TYPE_ARRAY: { + size_t k; + + r = signature_element_length(t + 1, &k); + if (r < 0) + return r; + + { + char s[k + 1]; + memcpy(s, t + 1, k); + s[k] = 0; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s); + if (r < 0) + return r; + if (r == 0) { + if (n_loop <= 1) + return 0; + + return -ENXIO; + } + } + + if (n_array == (unsigned) -1) { + types += k; + n_struct -= k; + } + + r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); + if (r < 0) + return r; + + types = t + 1; + n_struct = k; + n_array = va_arg(ap, unsigned); + + break; + } + + case SD_BUS_TYPE_VARIANT: { + const char *s; + + s = va_arg(ap, const char *); + if (!s) + return -EINVAL; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, s); + if (r < 0) + return r; + if (r == 0) { + if (n_loop <= 1) + return 0; + + return -ENXIO; + } + + r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); + if (r < 0) + return r; + + types = s; + n_struct = strlen(s); + n_array = (unsigned) -1; + + break; + } + + case SD_BUS_TYPE_STRUCT_BEGIN: + case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { + size_t k; + + r = signature_element_length(t, &k); + if (r < 0) + return r; + + { + char s[k - 1]; + memcpy(s, t + 1, k - 2); + s[k - 2] = 0; + + r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s); + if (r < 0) + return r; + if (r == 0) { + if (n_loop <= 1) + return 0; + return -ENXIO; + } + } + + if (n_array == (unsigned) -1) { + types += k - 1; + n_struct -= k - 1; + } + + r = type_stack_push(stack, ELEMENTSOF(stack), &stack_ptr, types, n_struct, n_array); + if (r < 0) + return r; + + types = t + 1; + n_struct = k - 2; + n_array = (unsigned) -1; + + break; + } + + default: + return -EINVAL; + } + } + + return 1; +} + +_public_ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) { + va_list ap; + int r; + + va_start(ap, types); + r = sd_bus_message_readv(m, types, ap); + va_end(ap); + + return r; +} + +_public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) { + int r; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + + /* If types is NULL, read exactly one element */ + if (!types) { + struct bus_container *c; + size_t l; + + if (message_end_of_signature(m)) + return -ENXIO; + + if (message_end_of_array(m, m->rindex)) + return 0; + + c = message_get_last_container(m); + + r = signature_element_length(c->signature + c->index, &l); + if (r < 0) + return r; + + types = strndupa(c->signature + c->index, l); + } + + switch (*types) { + + case 0: /* Nothing to drop */ + return 0; + + case SD_BUS_TYPE_BYTE: + case SD_BUS_TYPE_BOOLEAN: + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: + case SD_BUS_TYPE_DOUBLE: + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: + case SD_BUS_TYPE_UNIX_FD: + + r = sd_bus_message_read_basic(m, *types, NULL); + if (r <= 0) + return r; + + r = sd_bus_message_skip(m, types + 1); + if (r < 0) + return r; + + return 1; + + case SD_BUS_TYPE_ARRAY: { + size_t k; + + r = signature_element_length(types + 1, &k); + if (r < 0) + return r; + + { + char s[k+1]; + memcpy(s, types+1, k); + s[k] = 0; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, s); + if (r <= 0) + return r; + + for (;;) { + r = sd_bus_message_skip(m, s); + if (r < 0) + return r; + if (r == 0) + break; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + } + + r = sd_bus_message_skip(m, types + 1 + k); + if (r < 0) + return r; + + return 1; + } + + case SD_BUS_TYPE_VARIANT: { + const char *contents; + char x; + + r = sd_bus_message_peek_type(m, &x, &contents); + if (r <= 0) + return r; + + if (x != SD_BUS_TYPE_VARIANT) + return -ENXIO; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents); + if (r <= 0) + return r; + + r = sd_bus_message_skip(m, contents); + if (r < 0) + return r; + assert(r != 0); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + r = sd_bus_message_skip(m, types + 1); + if (r < 0) + return r; + + return 1; + } + + case SD_BUS_TYPE_STRUCT_BEGIN: + case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { + size_t k; + + r = signature_element_length(types, &k); + if (r < 0) + return r; + + { + char s[k-1]; + memcpy(s, types+1, k-2); + s[k-2] = 0; + + r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s); + if (r <= 0) + return r; + + r = sd_bus_message_skip(m, s); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + } + + r = sd_bus_message_skip(m, types + k); + if (r < 0) + return r; + + return 1; + } + + default: + return -EINVAL; + } +} + +_public_ int sd_bus_message_read_array( + sd_bus_message *m, + char type, + const void **ptr, + size_t *size) { + + struct bus_container *c; + void *p; + size_t sz; + ssize_t align; + int r; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + assert_return(bus_type_is_trivial(type), -EINVAL); + assert_return(ptr, -EINVAL); + assert_return(size, -EINVAL); + assert_return(!BUS_MESSAGE_NEED_BSWAP(m), -EOPNOTSUPP); + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)); + if (r <= 0) + return r; + + c = message_get_last_container(m); + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + align = bus_gvariant_get_alignment(CHAR_TO_STR(type)); + if (align < 0) + return align; + + sz = c->end - c->begin; + } else { + align = bus_type_get_alignment(type); + if (align < 0) + return align; + + sz = BUS_MESSAGE_BSWAP32(m, *c->array_size); + } + + if (sz == 0) + /* Zero length array, let's return some aligned + * pointer that is not NULL */ + p = (uint8_t*) align; + else { + r = message_peek_body(m, &m->rindex, align, sz, &p); + if (r < 0) + goto fail; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + goto fail; + + *ptr = (const void*) p; + *size = sz; + + return 1; + +fail: + message_quit_container(m); + return r; +} + +static int message_peek_fields( + sd_bus_message *m, + size_t *rindex, + size_t align, + size_t nbytes, + void **ret) { + + assert(m); + assert(rindex); + assert(align > 0); + + return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret); +} + +static int message_peek_field_uint32( + sd_bus_message *m, + size_t *ri, + size_t item_size, + uint32_t *ret) { + + int r; + void *q; + + assert(m); + assert(ri); + + if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4) + return -EBADMSG; + + /* identical for gvariant and dbus1 */ + + r = message_peek_fields(m, ri, 4, 4, &q); + if (r < 0) + return r; + + if (ret) + *ret = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + + return 0; +} + +static int message_peek_field_uint64( + sd_bus_message *m, + size_t *ri, + size_t item_size, + uint64_t *ret) { + + int r; + void *q; + + assert(m); + assert(ri); + + if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8) + return -EBADMSG; + + /* identical for gvariant and dbus1 */ + + r = message_peek_fields(m, ri, 8, 8, &q); + if (r < 0) + return r; + + if (ret) + *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q); + + return 0; +} + +static int message_peek_field_string( + sd_bus_message *m, + bool (*validate)(const char *p), + size_t *ri, + size_t item_size, + const char **ret) { + + uint32_t l; + int r; + void *q; + + assert(m); + assert(ri); + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + + if (item_size <= 0) + return -EBADMSG; + + r = message_peek_fields(m, ri, 1, item_size, &q); + if (r < 0) + return r; + + l = item_size - 1; + } else { + r = message_peek_field_uint32(m, ri, 4, &l); + if (r < 0) + return r; + + if (l == UINT32_MAX) + /* avoid overflow right below */ + return -EBADMSG; + + r = message_peek_fields(m, ri, 1, l+1, &q); + if (r < 0) + return r; + } + + if (validate) { + if (!validate_nul(q, l)) + return -EBADMSG; + + if (!validate(q)) + return -EBADMSG; + } else { + if (!validate_string(q, l)) + return -EBADMSG; + } + + if (ret) + *ret = q; + + return 0; +} + +static int message_peek_field_signature( + sd_bus_message *m, + size_t *ri, + size_t item_size, + const char **ret) { + + size_t l; + int r; + void *q; + + assert(m); + assert(ri); + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + + if (item_size <= 0) + return -EBADMSG; + + r = message_peek_fields(m, ri, 1, item_size, &q); + if (r < 0) + return r; + + l = item_size - 1; + } else { + r = message_peek_fields(m, ri, 1, 1, &q); + if (r < 0) + return r; + + l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + + r = message_peek_fields(m, ri, 1, l+1, &q); + if (r < 0) + return r; + } + + if (!validate_signature(q, l)) + return -EBADMSG; + + if (ret) + *ret = q; + + return 0; +} + +static int message_skip_fields( + sd_bus_message *m, + size_t *ri, + uint32_t array_size, + const char **signature) { + + size_t original_index; + int r; + + assert(m); + assert(ri); + assert(signature); + assert(!BUS_MESSAGE_IS_GVARIANT(m)); + + original_index = *ri; + + for (;;) { + char t; + size_t l; + + if (array_size != (uint32_t) -1 && + array_size <= *ri - original_index) + return 0; + + t = **signature; + if (!t) + return 0; + + if (t == SD_BUS_TYPE_STRING) { + + r = message_peek_field_string(m, NULL, ri, 0, NULL); + if (r < 0) + return r; + + (*signature)++; + + } else if (t == SD_BUS_TYPE_OBJECT_PATH) { + + r = message_peek_field_string(m, object_path_is_valid, ri, 0, NULL); + if (r < 0) + return r; + + (*signature)++; + + } else if (t == SD_BUS_TYPE_SIGNATURE) { + + r = message_peek_field_signature(m, ri, 0, NULL); + if (r < 0) + return r; + + (*signature)++; + + } else if (bus_type_is_basic(t)) { + ssize_t align, k; + + align = bus_type_get_alignment(t); + k = bus_type_get_size(t); + assert(align > 0 && k > 0); + + r = message_peek_fields(m, ri, align, k, NULL); + if (r < 0) + return r; + + (*signature)++; + + } else if (t == SD_BUS_TYPE_ARRAY) { + + r = signature_element_length(*signature + 1, &l); + if (r < 0) + return r; + + assert(l >= 1); + { + char sig[l + 1], *s = sig; + uint32_t nas; + int alignment; + + strncpy(sig, *signature + 1, l); + sig[l] = '\0'; + + alignment = bus_type_get_alignment(sig[0]); + if (alignment < 0) + return alignment; + + r = message_peek_field_uint32(m, ri, 0, &nas); + if (r < 0) + return r; + if (nas > BUS_ARRAY_MAX_SIZE) + return -EBADMSG; + + r = message_peek_fields(m, ri, alignment, 0, NULL); + if (r < 0) + return r; + + r = message_skip_fields(m, ri, nas, (const char**) &s); + if (r < 0) + return r; + } + + (*signature) += 1 + l; + + } else if (t == SD_BUS_TYPE_VARIANT) { + const char *s; + + r = message_peek_field_signature(m, ri, 0, &s); + if (r < 0) + return r; + + r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s); + if (r < 0) + return r; + + (*signature)++; + + } else if (IN_SET(t, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) { + + r = signature_element_length(*signature, &l); + if (r < 0) + return r; + + assert(l >= 2); + { + char sig[l + 1], *s = sig; + strncpy(sig, *signature + 1, l); + sig[l] = '\0'; + + r = message_skip_fields(m, ri, (uint32_t) -1, (const char**) &s); + if (r < 0) + return r; + } + + *signature += l; + } else + return -EBADMSG; + } +} + +int bus_message_parse_fields(sd_bus_message *m) { + size_t ri; + int r; + uint32_t unix_fds = 0; + bool unix_fds_set = false; + void *offsets = NULL; + unsigned n_offsets = 0; + size_t sz = 0; + unsigned i = 0; + + assert(m); + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + char *p; + + /* Read the signature from the end of the body variant first */ + sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0); + if (m->footer_accessible < 1 + sz) + return -EBADMSG; + + p = (char*) m->footer + m->footer_accessible - (1 + sz); + for (;;) { + if (p < (char*) m->footer) + return -EBADMSG; + + if (*p == 0) { + _cleanup_free_ char *k = NULL; + size_t l; + + /* We found the beginning of the signature + * string, yay! We require the body to be a + * structure, so verify it and then strip the + * opening/closing brackets. */ + + l = (char*) m->footer + m->footer_accessible - p - (1 + sz); + if (l < 2 || + p[1] != SD_BUS_TYPE_STRUCT_BEGIN || + p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END) + return -EBADMSG; + + k = memdup_suffix0(p + 1 + 1, l - 2); + if (!k) + return -ENOMEM; + + if (!signature_is_valid(k, true)) + return -EBADMSG; + + free_and_replace(m->root_container.signature, k); + break; + } + + p--; + } + + /* Calculate the actual user body size, by removing + * the trailing variant signature and struct offset + * table */ + m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p); + + /* Pull out the offset table for the fields array */ + sz = bus_gvariant_determine_word_size(m->fields_size, 0); + if (sz > 0) { + size_t framing; + void *q; + + ri = m->fields_size - sz; + r = message_peek_fields(m, &ri, 1, sz, &q); + if (r < 0) + return r; + + framing = bus_gvariant_read_word_le(q, sz); + if (framing >= m->fields_size - sz) + return -EBADMSG; + if ((m->fields_size - framing) % sz != 0) + return -EBADMSG; + + ri = framing; + r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets); + if (r < 0) + return r; + + n_offsets = (m->fields_size - framing) / sz; + } + } else + m->user_body_size = m->body_size; + + ri = 0; + while (ri < m->fields_size) { + _cleanup_free_ char *sig = NULL; + const char *signature; + uint64_t field_type; + size_t item_size = (size_t) -1; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + uint64_t *u64; + + if (i >= n_offsets) + break; + + if (i == 0) + ri = 0; + else + ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8); + + r = message_peek_fields(m, &ri, 8, 8, (void**) &u64); + if (r < 0) + return r; + + field_type = BUS_MESSAGE_BSWAP64(m, *u64); + } else { + uint8_t *u8; + + r = message_peek_fields(m, &ri, 8, 1, (void**) &u8); + if (r < 0) + return r; + + field_type = *u8; + } + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + size_t where, end; + char *b; + void *q; + + end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz); + + if (end < ri) + return -EBADMSG; + + where = ri = ALIGN_TO(ri, 8); + item_size = end - ri; + r = message_peek_fields(m, &where, 1, item_size, &q); + if (r < 0) + return r; + + b = memrchr(q, 0, item_size); + if (!b) + return -EBADMSG; + + sig = memdup_suffix0(b+1, item_size - (b+1-(char*) q)); + if (!sig) + return -ENOMEM; + + signature = sig; + item_size = b - (char*) q; + } else { + r = message_peek_field_signature(m, &ri, 0, &signature); + if (r < 0) + return r; + } + + switch (field_type) { + + case _BUS_MESSAGE_HEADER_INVALID: + return -EBADMSG; + + case BUS_MESSAGE_HEADER_PATH: + + if (m->path) + return -EBADMSG; + + if (!streq(signature, "o")) + return -EBADMSG; + + r = message_peek_field_string(m, object_path_is_valid, &ri, item_size, &m->path); + break; + + case BUS_MESSAGE_HEADER_INTERFACE: + + if (m->interface) + return -EBADMSG; + + if (!streq(signature, "s")) + return -EBADMSG; + + r = message_peek_field_string(m, interface_name_is_valid, &ri, item_size, &m->interface); + break; + + case BUS_MESSAGE_HEADER_MEMBER: + + if (m->member) + return -EBADMSG; + + if (!streq(signature, "s")) + return -EBADMSG; + + r = message_peek_field_string(m, member_name_is_valid, &ri, item_size, &m->member); + break; + + case BUS_MESSAGE_HEADER_ERROR_NAME: + + if (m->error.name) + return -EBADMSG; + + if (!streq(signature, "s")) + return -EBADMSG; + + r = message_peek_field_string(m, error_name_is_valid, &ri, item_size, &m->error.name); + if (r >= 0) + m->error._need_free = -1; + + break; + + case BUS_MESSAGE_HEADER_DESTINATION: + + if (m->destination) + return -EBADMSG; + + if (!streq(signature, "s")) + return -EBADMSG; + + r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->destination); + break; + + case BUS_MESSAGE_HEADER_SENDER: + + if (m->sender) + return -EBADMSG; + + if (!streq(signature, "s")) + return -EBADMSG; + + r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender); + + if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client) { + m->creds.unique_name = (char*) m->sender; + m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask; + } + + break; + + case BUS_MESSAGE_HEADER_SIGNATURE: { + const char *s; + char *c; + + if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */ + return -EBADMSG; + + if (m->root_container.signature) + return -EBADMSG; + + if (!streq(signature, "g")) + return -EBADMSG; + + r = message_peek_field_signature(m, &ri, item_size, &s); + if (r < 0) + return r; + + c = strdup(s); + if (!c) + return -ENOMEM; + + free_and_replace(m->root_container.signature, c); + break; + } + + case BUS_MESSAGE_HEADER_REPLY_SERIAL: + + if (m->reply_cookie != 0) + return -EBADMSG; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + /* 64bit on dbus2 */ + + if (!streq(signature, "t")) + return -EBADMSG; + + r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie); + if (r < 0) + return r; + } else { + /* 32bit on dbus1 */ + uint32_t serial; + + if (!streq(signature, "u")) + return -EBADMSG; + + r = message_peek_field_uint32(m, &ri, item_size, &serial); + if (r < 0) + return r; + + m->reply_cookie = serial; + } + + if (m->reply_cookie == 0) + return -EBADMSG; + + break; + + case BUS_MESSAGE_HEADER_UNIX_FDS: + if (unix_fds_set) + return -EBADMSG; + + if (!streq(signature, "u")) + return -EBADMSG; + + r = message_peek_field_uint32(m, &ri, item_size, &unix_fds); + if (r < 0) + return -EBADMSG; + + unix_fds_set = true; + break; + + default: + if (!BUS_MESSAGE_IS_GVARIANT(m)) + r = message_skip_fields(m, &ri, (uint32_t) -1, (const char **) &signature); + } + + if (r < 0) + return r; + + i++; + } + + if (m->n_fds != unix_fds) + return -EBADMSG; + + switch (m->header->type) { + + case SD_BUS_MESSAGE_SIGNAL: + if (!m->path || !m->interface || !m->member) + return -EBADMSG; + + if (m->reply_cookie != 0) + return -EBADMSG; + + break; + + case SD_BUS_MESSAGE_METHOD_CALL: + + if (!m->path || !m->member) + return -EBADMSG; + + if (m->reply_cookie != 0) + return -EBADMSG; + + break; + + case SD_BUS_MESSAGE_METHOD_RETURN: + + if (m->reply_cookie == 0) + return -EBADMSG; + break; + + case SD_BUS_MESSAGE_METHOD_ERROR: + + if (m->reply_cookie == 0 || !m->error.name) + return -EBADMSG; + break; + } + + /* Refuse non-local messages that claim they are local */ + if (streq_ptr(m->path, "/org/freedesktop/DBus/Local")) + return -EBADMSG; + if (streq_ptr(m->interface, "org.freedesktop.DBus.Local")) + return -EBADMSG; + if (streq_ptr(m->sender, "org.freedesktop.DBus.Local")) + return -EBADMSG; + + m->root_container.end = m->user_body_size; + + if (BUS_MESSAGE_IS_GVARIANT(m)) { + r = build_struct_offsets( + m, + m->root_container.signature, + m->user_body_size, + &m->root_container.item_size, + &m->root_container.offsets, + &m->root_container.n_offsets); + if (r == -EINVAL) + return -EBADMSG; + if (r < 0) + return r; + } + + /* Try to read the error message, but if we can't it's a non-issue */ + if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR) + (void) sd_bus_message_read(m, "s", &m->error.message); + + return 0; +} + +_public_ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) { + assert_return(m, -EINVAL); + assert_return(destination, -EINVAL); + assert_return(service_name_is_valid(destination), -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(!m->destination, -EEXIST); + + return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination); +} + +_public_ int sd_bus_message_set_sender(sd_bus_message *m, const char *sender) { + assert_return(m, -EINVAL); + assert_return(sender, -EINVAL); + assert_return(service_name_is_valid(sender), -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(!m->sender, -EEXIST); + + return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender); +} + +int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) { + size_t total; + void *p, *e; + size_t i; + struct bus_body_part *part; + + assert(m); + assert(buffer); + assert(sz); + + total = BUS_MESSAGE_SIZE(m); + + p = malloc(total); + if (!p) + return -ENOMEM; + + e = mempcpy(p, m->header, BUS_MESSAGE_BODY_BEGIN(m)); + MESSAGE_FOREACH_PART(part, i, m) + e = mempcpy(e, part->data, part->size); + + assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p)); + + *buffer = p; + *sz = total; + + return 0; +} + +int bus_message_read_strv_extend(sd_bus_message *m, char ***l) { + const char *s; + int r; + + assert(m); + assert(l); + + r = sd_bus_message_enter_container(m, 'a', "s"); + if (r <= 0) + return r; + + while ((r = sd_bus_message_read_basic(m, 's', &s)) > 0) { + r = strv_extend(l, s); + if (r < 0) + return r; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 1; +} + +_public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) { + _cleanup_strv_free_ char **strv = NULL; + int r; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + assert_return(l, -EINVAL); + + r = bus_message_read_strv_extend(m, &strv); + if (r <= 0) + return r; + + *l = TAKE_PTR(strv); + return 1; +} + +static int bus_message_get_arg_skip( + sd_bus_message *m, + unsigned i, + char *_type, + const char **_contents) { + + unsigned j; + int r; + + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + for (j = 0;; j++) { + const char *contents; + char type; + + r = sd_bus_message_peek_type(m, &type, &contents); + if (r < 0) + return r; + if (r == 0) + return -ENXIO; + + /* Don't match against arguments after the first one we don't understand */ + if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) && + !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g"))) + return -ENXIO; + + if (j >= i) { + if (_contents) + *_contents = contents; + if (_type) + *_type = type; + return 0; + } + + r = sd_bus_message_skip(m, NULL); + if (r < 0) + return r; + } + +} + +int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str) { + char type; + int r; + + assert(m); + assert(str); + + r = bus_message_get_arg_skip(m, i, &type, NULL); + if (r < 0) + return r; + + if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) + return -ENXIO; + + return sd_bus_message_read_basic(m, type, str); +} + +int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv) { + const char *contents; + char type; + int r; + + assert(m); + assert(strv); + + r = bus_message_get_arg_skip(m, i, &type, &contents); + if (r < 0) + return r; + + if (type != SD_BUS_TYPE_ARRAY) + return -ENXIO; + if (!STR_IN_SET(contents, "s", "o", "g")) + return -ENXIO; + + return sd_bus_message_read_strv(m, strv); +} + +_public_ int sd_bus_message_get_errno(sd_bus_message *m) { + assert_return(m, EINVAL); + + if (m->header->type != SD_BUS_MESSAGE_METHOD_ERROR) + return 0; + + return sd_bus_error_get_errno(&m->error); +} + +_public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complete) { + struct bus_container *c; + + assert_return(m, NULL); + + c = complete ? &m->root_container : message_get_last_container(m); + return strempty(c->signature); +} + +_public_ int sd_bus_message_is_empty(sd_bus_message *m) { + assert_return(m, -EINVAL); + + return isempty(m->root_container.signature); +} + +_public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) { + assert_return(m, -EINVAL); + + return streq(strempty(m->root_container.signature), strempty(signature)); +} + +_public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) { + bool done_something = false; + int r; + + assert_return(m, -EINVAL); + assert_return(source, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(source->sealed, -EPERM); + + do { + const char *contents; + char type; + union { + uint8_t u8; + uint16_t u16; + int16_t s16; + uint32_t u32; + int32_t s32; + uint64_t u64; + int64_t s64; + double d64; + const char *string; + int i; + } basic; + + r = sd_bus_message_peek_type(source, &type, &contents); + if (r < 0) + return r; + if (r == 0) + break; + + done_something = true; + + if (bus_type_is_container(type) > 0) { + + r = sd_bus_message_enter_container(source, type, contents); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, type, contents); + if (r < 0) + return r; + + r = sd_bus_message_copy(m, source, true); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(source); + if (r < 0) + return r; + + continue; + } + + r = sd_bus_message_read_basic(source, type, &basic); + if (r < 0) + return r; + + assert(r > 0); + + if (IN_SET(type, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE, SD_BUS_TYPE_STRING)) + r = sd_bus_message_append_basic(m, type, basic.string); + else + r = sd_bus_message_append_basic(m, type, &basic); + + if (r < 0) + return r; + + } while (all); + + return done_something; +} + +_public_ int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents) { + const char *c; + char t; + int r; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + assert_return(!type || bus_type_is_valid(type), -EINVAL); + assert_return(!contents || signature_is_valid(contents, true), -EINVAL); + assert_return(type || contents, -EINVAL); + assert_return(!contents || !type || bus_type_is_container(type), -EINVAL); + + r = sd_bus_message_peek_type(m, &t, &c); + if (r <= 0) + return r; + + if (type != 0 && type != t) + return 0; + + if (contents && !streq_ptr(contents, c)) + return 0; + + return 1; +} + +_public_ sd_bus *sd_bus_message_get_bus(sd_bus_message *m) { + assert_return(m, NULL); + + return m->bus; +} + +int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *n = NULL; + usec_t timeout; + int r; + + assert(bus); + assert(m); + assert(*m); + + switch ((*m)->header->type) { + + case SD_BUS_MESSAGE_SIGNAL: + r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member); + if (r < 0) + return r; + + break; + + case SD_BUS_MESSAGE_METHOD_CALL: + r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member); + if (r < 0) + return r; + + break; + + case SD_BUS_MESSAGE_METHOD_RETURN: + case SD_BUS_MESSAGE_METHOD_ERROR: + + r = sd_bus_message_new(bus, &n, (*m)->header->type); + if (r < 0) + return -ENOMEM; + + assert(n); + + n->reply_cookie = (*m)->reply_cookie; + + r = message_append_reply_cookie(n, n->reply_cookie); + if (r < 0) + return r; + + if ((*m)->header->type == SD_BUS_MESSAGE_METHOD_ERROR && (*m)->error.name) { + r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message); + if (r < 0) + return r; + + n->error._need_free = -1; + } + + break; + + default: + return -EINVAL; + } + + if ((*m)->destination && !n->destination) { + r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination); + if (r < 0) + return r; + } + + if ((*m)->sender && !n->sender) { + r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender); + if (r < 0) + return r; + } + + n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START); + + r = sd_bus_message_copy(n, *m, true); + if (r < 0) + return r; + + timeout = (*m)->timeout; + if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)) { + r = sd_bus_get_method_call_timeout(bus, &timeout); + if (r < 0) + return r; + } + + r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout); + if (r < 0) + return r; + + sd_bus_message_unref(*m); + *m = TAKE_PTR(n); + + return 0; +} + +_public_ int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority) { + assert_return(m, -EINVAL); + assert_return(priority, -EINVAL); + + *priority = m->priority; + return 0; +} + +_public_ int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority) { + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + m->priority = priority; + return 0; +} diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h new file mode 100644 index 00000000..3f39377b --- /dev/null +++ b/src/libsystemd/sd-bus/bus-message.h @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "sd-bus.h" + +#include "bus-creds.h" +#include "bus-protocol.h" +#include "macro.h" +#include "time-util.h" + +struct bus_container { + char enclosing; + bool need_offsets:1; + + /* Indexes into the signature string */ + unsigned index, saved_index; + char *signature; + + size_t before, begin, end; + + /* dbus1: pointer to the array size value, if this is a value */ + uint32_t *array_size; + + /* gvariant: list of offsets to end of children if this is struct/dict entry/array */ + size_t *offsets, n_offsets, offsets_allocated, offset_index; + size_t item_size; + + char *peeked_signature; +}; + +struct bus_body_part { + struct bus_body_part *next; + void *data; + void *mmap_begin; + size_t size; + size_t mapped; + size_t allocated; + uint64_t memfd_offset; + int memfd; + bool free_this:1; + bool munmap_this:1; + bool sealed:1; + bool is_zero:1; +}; + +struct sd_bus_message { + /* Caveat: a message can be referenced in two different ways: the main (user-facing) way will also + * pin the bus connection object the message is associated with. The secondary way ("queued") is used + * when a message is in the read or write queues of the bus connection object, which will not pin the + * bus connection object. This is necessary so that we don't have to have a pair of cyclic references + * between a message that is queued and its connection: as soon as a message is only referenced by + * the connection (by means of being queued) and the connection itself has no other references it + * will be freed. */ + + unsigned n_ref; /* Counter of references that pin the connection */ + unsigned n_queued; /* Counter of references that do not pin the connection */ + + sd_bus *bus; + + uint64_t reply_cookie; + + const char *path; + const char *interface; + const char *member; + const char *destination; + const char *sender; + + sd_bus_error error; + + sd_bus_creds creds; + + usec_t monotonic; + usec_t realtime; + uint64_t seqnum; + int64_t priority; + uint64_t verify_destination_id; + + bool sealed:1; + bool dont_send:1; + bool allow_fds:1; + bool free_header:1; + bool free_fds:1; + bool poisoned:1; + + /* The first and last bytes of the message */ + struct bus_header *header; + void *footer; + + /* How many bytes are accessible in the above pointers */ + size_t header_accessible; + size_t footer_accessible; + + size_t fields_size; + size_t body_size; + size_t user_body_size; + + struct bus_body_part body; + struct bus_body_part *body_end; + unsigned n_body_parts; + + size_t rindex; + struct bus_body_part *cached_rindex_part; + size_t cached_rindex_part_begin; + + uint32_t n_fds; + int *fds; + + struct bus_container root_container, *containers; + size_t n_containers; + size_t containers_allocated; + + struct iovec *iovec; + struct iovec iovec_fixed[2]; + unsigned n_iovec; + + char *peeked_signature; + + /* If set replies to this message must carry the signature + * specified here to successfully seal. This is initialized + * from the vtable data */ + const char *enforced_reply_signature; + + usec_t timeout; + + size_t header_offsets[_BUS_MESSAGE_HEADER_MAX]; + unsigned n_header_offsets; + + uint64_t read_counter; +}; + +static inline bool BUS_MESSAGE_NEED_BSWAP(sd_bus_message *m) { + return m->header->endian != BUS_NATIVE_ENDIAN; +} + +static inline uint16_t BUS_MESSAGE_BSWAP16(sd_bus_message *m, uint16_t u) { + return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_16(u) : u; +} + +static inline uint32_t BUS_MESSAGE_BSWAP32(sd_bus_message *m, uint32_t u) { + return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_32(u) : u; +} + +static inline uint64_t BUS_MESSAGE_BSWAP64(sd_bus_message *m, uint64_t u) { + return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_64(u) : u; +} + +static inline uint64_t BUS_MESSAGE_COOKIE(sd_bus_message *m) { + if (m->header->version == 2) + return BUS_MESSAGE_BSWAP64(m, m->header->dbus2.cookie); + + return BUS_MESSAGE_BSWAP32(m, m->header->dbus1.serial); +} + +static inline size_t BUS_MESSAGE_SIZE(sd_bus_message *m) { + return + sizeof(struct bus_header) + + ALIGN8(m->fields_size) + + m->body_size; +} + +static inline size_t BUS_MESSAGE_BODY_BEGIN(sd_bus_message *m) { + return + sizeof(struct bus_header) + + ALIGN8(m->fields_size); +} + +static inline void* BUS_MESSAGE_FIELDS(sd_bus_message *m) { + return (uint8_t*) m->header + sizeof(struct bus_header); +} + +static inline bool BUS_MESSAGE_IS_GVARIANT(sd_bus_message *m) { + return m->header->version == 2; +} + +int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz); +int bus_message_read_strv_extend(sd_bus_message *m, char ***l); + +int bus_message_from_header( + sd_bus *bus, + void *header, + size_t header_accessible, + void *footer, + size_t footer_accessible, + size_t message_size, + int *fds, + size_t n_fds, + const char *label, + size_t extra, + sd_bus_message **ret); + +int bus_message_from_malloc( + sd_bus *bus, + void *buffer, + size_t length, + int *fds, + size_t n_fds, + const char *label, + sd_bus_message **ret); + +int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str); +int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv); + +int bus_message_parse_fields(sd_bus_message *m); + +struct bus_body_part *message_append_part(sd_bus_message *m); + +#define MESSAGE_FOREACH_PART(part, i, m) \ + for ((i) = 0, (part) = &(m)->body; (i) < (m)->n_body_parts; (i)++, (part) = (part)->next) + +int bus_body_part_map(struct bus_body_part *part); +void bus_body_part_unmap(struct bus_body_part *part); + +int bus_message_to_errno(sd_bus_message *m); + +int bus_message_new_synthetic_error(sd_bus *bus, uint64_t serial, const sd_bus_error *e, sd_bus_message **m); + +int bus_message_remarshal(sd_bus *bus, sd_bus_message **m); + +void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m); +void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m); + +sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus); +sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus); +int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m); diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c new file mode 100644 index 00000000..ae643cac --- /dev/null +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -0,0 +1,3006 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-internal.h" +#include "bus-introspect.h" +#include "bus-message.h" +#include "bus-objects.h" +#include "bus-signature.h" +#include "bus-slot.h" +#include "bus-type.h" +#include "bus-util.h" +#include "missing_capability.h" +#include "set.h" +#include "string-util.h" +#include "strv.h" + +static int node_vtable_get_userdata( + sd_bus *bus, + const char *path, + struct node_vtable *c, + void **userdata, + sd_bus_error *error) { + + sd_bus_slot *s; + void *u, *found_u = NULL; + int r; + + assert(bus); + assert(path); + assert(c); + + s = container_of(c, sd_bus_slot, node_vtable); + u = s->userdata; + if (c->find) { + bus->current_slot = sd_bus_slot_ref(s); + bus->current_userdata = u; + r = c->find(bus, path, c->interface, u, &found_u, error); + bus->current_userdata = NULL; + bus->current_slot = sd_bus_slot_unref(s); + + if (r < 0) + return r; + if (sd_bus_error_is_set(error)) + return -sd_bus_error_get_errno(error); + if (r == 0) + return r; + } else + found_u = u; + + if (userdata) + *userdata = found_u; + + return 1; +} + +static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) { + assert(p); + + return (uint8_t*) u + p->x.method.offset; +} + +static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) { + assert(p); + + return (uint8_t*) u + p->x.property.offset; +} + +static int vtable_property_get_userdata( + sd_bus *bus, + const char *path, + struct vtable_member *p, + void **userdata, + sd_bus_error *error) { + + void *u; + int r; + + assert(bus); + assert(path); + assert(p); + assert(userdata); + + r = node_vtable_get_userdata(bus, path, p->parent, &u, error); + if (r <= 0) + return r; + if (bus->nodes_modified) + return 0; + + *userdata = vtable_property_convert_userdata(p->vtable, u); + return 1; +} + +static int add_enumerated_to_set( + sd_bus *bus, + const char *prefix, + struct node_enumerator *first, + Set *s, + sd_bus_error *error) { + + struct node_enumerator *c; + int r; + + assert(bus); + assert(prefix); + assert(s); + + LIST_FOREACH(enumerators, c, first) { + char **children = NULL, **k; + sd_bus_slot *slot; + + if (bus->nodes_modified) + return 0; + + slot = container_of(c, sd_bus_slot, node_enumerator); + + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_userdata = slot->userdata; + r = c->callback(bus, prefix, slot->userdata, &children, error); + bus->current_userdata = NULL; + bus->current_slot = sd_bus_slot_unref(slot); + + if (r < 0) + return r; + if (sd_bus_error_is_set(error)) + return -sd_bus_error_get_errno(error); + + STRV_FOREACH(k, children) { + if (r < 0) { + free(*k); + continue; + } + + if (!object_path_is_valid(*k)) { + free(*k); + r = -EINVAL; + continue; + } + + if (!object_path_startswith(*k, prefix)) { + free(*k); + continue; + } + + r = set_consume(s, *k); + if (r == -EEXIST) + r = 0; + } + + free(children); + if (r < 0) + return r; + } + + return 0; +} + +enum { + /* if set, add_subtree() works recursively */ + CHILDREN_RECURSIVE = 1 << 0, + /* if set, add_subtree() scans object-manager hierarchies recursively */ + CHILDREN_SUBHIERARCHIES = 1 << 1, +}; + +static int add_subtree_to_set( + sd_bus *bus, + const char *prefix, + struct node *n, + unsigned flags, + Set *s, + sd_bus_error *error) { + + struct node *i; + int r; + + assert(bus); + assert(prefix); + assert(n); + assert(s); + + r = add_enumerated_to_set(bus, prefix, n->enumerators, s, error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + + LIST_FOREACH(siblings, i, n->child) { + char *t; + + if (!object_path_startswith(i->path, prefix)) + continue; + + t = strdup(i->path); + if (!t) + return -ENOMEM; + + r = set_consume(s, t); + if (r < 0 && r != -EEXIST) + return r; + + if ((flags & CHILDREN_RECURSIVE) && + ((flags & CHILDREN_SUBHIERARCHIES) || !i->object_managers)) { + r = add_subtree_to_set(bus, prefix, i, flags, s, error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + } + } + + return 0; +} + +static int get_child_nodes( + sd_bus *bus, + const char *prefix, + struct node *n, + unsigned flags, + Set **_s, + sd_bus_error *error) { + + Set *s = NULL; + int r; + + assert(bus); + assert(prefix); + assert(n); + assert(_s); + + s = set_new(&string_hash_ops); + if (!s) + return -ENOMEM; + + r = add_subtree_to_set(bus, prefix, n, flags, s, error); + if (r < 0) { + set_free_free(s); + return r; + } + + *_s = s; + return 0; +} + +static int node_callbacks_run( + sd_bus *bus, + sd_bus_message *m, + struct node_callback *first, + bool require_fallback, + bool *found_object) { + + struct node_callback *c; + int r; + + assert(bus); + assert(m); + assert(found_object); + + LIST_FOREACH(callbacks, c, first) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + sd_bus_slot *slot; + + if (bus->nodes_modified) + return 0; + + if (require_fallback && !c->is_fallback) + continue; + + *found_object = true; + + if (c->last_iteration == bus->iteration_counter) + continue; + + c->last_iteration = bus->iteration_counter; + + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + slot = container_of(c, sd_bus_slot, node_callback); + + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_handler = c->callback; + bus->current_userdata = slot->userdata; + r = c->callback(m, slot->userdata, &error_buffer); + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = sd_bus_slot_unref(slot); + + r = bus_maybe_reply_error(m, r, &error_buffer); + if (r != 0) + return r; + } + + return 0; +} + +#define CAPABILITY_SHIFT(x) (((x) >> __builtin_ctzll(_SD_BUS_VTABLE_CAPABILITY_MASK)) & 0xFFFF) + +static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) { + uint64_t cap; + int r; + + assert(bus); + assert(m); + assert(c); + + /* If the entire bus is trusted let's grant access */ + if (bus->trusted) + return 0; + + /* If the member is marked UNPRIVILEGED let's grant access */ + if (c->vtable->flags & SD_BUS_VTABLE_UNPRIVILEGED) + return 0; + + /* Check have the caller has the requested capability + * set. Note that the flags value contains the capability + * number plus one, which we need to subtract here. We do this + * so that we have 0 as special value for "default + * capability". */ + cap = CAPABILITY_SHIFT(c->vtable->flags); + if (cap == 0) + cap = CAPABILITY_SHIFT(c->parent->vtable[0].flags); + if (cap == 0) + cap = CAP_SYS_ADMIN; + else + cap--; + + r = sd_bus_query_sender_privilege(m, cap); + if (r < 0) + return r; + if (r > 0) + return 0; + + return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access to %s.%s() not permitted.", c->interface, c->member); +} + +static int method_callbacks_run( + sd_bus *bus, + sd_bus_message *m, + struct vtable_member *c, + bool require_fallback, + bool *found_object) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *signature; + void *u; + int r; + + assert(bus); + assert(m); + assert(c); + assert(found_object); + + if (require_fallback && !c->parent->is_fallback) + return 0; + + r = check_access(bus, m, c, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + + r = node_vtable_get_userdata(bus, m->path, c->parent, &u, &error); + if (r <= 0) + return bus_maybe_reply_error(m, r, &error); + if (bus->nodes_modified) + return 0; + + u = vtable_method_convert_userdata(c->vtable, u); + + *found_object = true; + + if (c->last_iteration == bus->iteration_counter) + return 0; + + c->last_iteration = bus->iteration_counter; + + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + signature = sd_bus_message_get_signature(m, true); + if (!signature) + return -EINVAL; + + if (!streq(strempty(c->vtable->x.method.signature), signature)) + return sd_bus_reply_method_errorf( + m, + SD_BUS_ERROR_INVALID_ARGS, + "Invalid arguments '%s' to call %s.%s(), expecting '%s'.", + signature, c->interface, c->member, strempty(c->vtable->x.method.signature)); + + /* Keep track what the signature of the reply to this message + * should be, so that this can be enforced when sealing the + * reply. */ + m->enforced_reply_signature = strempty(c->vtable->x.method.result); + + if (c->vtable->x.method.handler) { + sd_bus_slot *slot; + + slot = container_of(c->parent, sd_bus_slot, node_vtable); + + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_handler = c->vtable->x.method.handler; + bus->current_userdata = u; + r = c->vtable->x.method.handler(m, u, &error); + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = sd_bus_slot_unref(slot); + + return bus_maybe_reply_error(m, r, &error); + } + + /* If the method callback is NULL, make this a successful NOP */ + r = sd_bus_reply_method_return(m, NULL); + if (r < 0) + return r; + + return 1; +} + +static int invoke_property_get( + sd_bus *bus, + sd_bus_slot *slot, + const sd_bus_vtable *v, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + const void *p; + int r; + + assert(bus); + assert(slot); + assert(v); + assert(path); + assert(interface); + assert(property); + assert(reply); + + if (v->x.property.get) { + + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_userdata = userdata; + r = v->x.property.get(bus, path, interface, property, reply, userdata, error); + bus->current_userdata = NULL; + bus->current_slot = sd_bus_slot_unref(slot); + + if (r < 0) + return r; + if (sd_bus_error_is_set(error)) + return -sd_bus_error_get_errno(error); + return r; + } + + /* Automatic handling if no callback is defined. */ + + if (streq(v->x.property.signature, "as")) + return sd_bus_message_append_strv(reply, *(char***) userdata); + + assert(signature_is_single(v->x.property.signature, false)); + assert(bus_type_is_basic(v->x.property.signature[0])); + + switch (v->x.property.signature[0]) { + + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_SIGNATURE: + p = strempty(*(char**) userdata); + break; + + case SD_BUS_TYPE_OBJECT_PATH: + p = *(char**) userdata; + assert(p); + break; + + default: + p = userdata; + break; + } + + return sd_bus_message_append_basic(reply, v->x.property.signature[0], p); +} + +static int invoke_property_set( + sd_bus *bus, + sd_bus_slot *slot, + const sd_bus_vtable *v, + const char *path, + const char *interface, + const char *property, + sd_bus_message *value, + void *userdata, + sd_bus_error *error) { + + int r; + + assert(bus); + assert(slot); + assert(v); + assert(path); + assert(interface); + assert(property); + assert(value); + + if (v->x.property.set) { + + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_userdata = userdata; + r = v->x.property.set(bus, path, interface, property, value, userdata, error); + bus->current_userdata = NULL; + bus->current_slot = sd_bus_slot_unref(slot); + + if (r < 0) + return r; + if (sd_bus_error_is_set(error)) + return -sd_bus_error_get_errno(error); + return r; + } + + /* Automatic handling if no callback is defined. */ + + assert(signature_is_single(v->x.property.signature, false)); + assert(bus_type_is_basic(v->x.property.signature[0])); + + switch (v->x.property.signature[0]) { + + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_SIGNATURE: { + const char *p; + char *n; + + r = sd_bus_message_read_basic(value, v->x.property.signature[0], &p); + if (r < 0) + return r; + + n = strdup(p); + if (!n) + return -ENOMEM; + + free(*(char**) userdata); + *(char**) userdata = n; + + break; + } + + default: + r = sd_bus_message_read_basic(value, v->x.property.signature[0], userdata); + if (r < 0) + return r; + + break; + } + + return 1; +} + +static int property_get_set_callbacks_run( + sd_bus *bus, + sd_bus_message *m, + struct vtable_member *c, + bool require_fallback, + bool is_get, + bool *found_object) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + sd_bus_slot *slot; + void *u = NULL; + int r; + + assert(bus); + assert(m); + assert(c); + assert(found_object); + + if (require_fallback && !c->parent->is_fallback) + return 0; + + r = vtable_property_get_userdata(bus, m->path, c, &u, &error); + if (r <= 0) + return bus_maybe_reply_error(m, r, &error); + if (bus->nodes_modified) + return 0; + + slot = container_of(c->parent, sd_bus_slot, node_vtable); + + *found_object = true; + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + if (is_get) { + /* Note that we do not protect against reexecution + * here (using the last_iteration check, see below), + * should the node tree have changed and we got called + * again. We assume that property Get() calls are + * ultimately without side-effects or if they aren't + * then at least idempotent. */ + + r = sd_bus_message_open_container(reply, 'v', c->vtable->x.property.signature); + if (r < 0) + return r; + + /* Note that we do not do an access check here. Read + * access to properties is always unrestricted, since + * PropertiesChanged signals broadcast contents + * anyway. */ + + r = invoke_property_get(bus, slot, c->vtable, m->path, c->interface, c->member, reply, u, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + + if (bus->nodes_modified) + return 0; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + } else { + const char *signature = NULL; + char type = 0; + + if (c->vtable->type != _SD_BUS_VTABLE_WRITABLE_PROPERTY) + return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Property '%s' is not writable.", c->member); + + /* Avoid that we call the set routine more than once + * if the processing of this message got restarted + * because the node tree changed. */ + if (c->last_iteration == bus->iteration_counter) + return 0; + + c->last_iteration = bus->iteration_counter; + + r = sd_bus_message_peek_type(m, &type, &signature); + if (r < 0) + return r; + + if (type != 'v') + return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_SIGNATURE, + "Incorrect signature when setting property '%s', expected 'v', got '%c'.", + c->member, type); + if (!streq(strempty(signature), strempty(c->vtable->x.property.signature))) + return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, + "Incorrect parameters for property '%s', expected '%s', got '%s'.", + c->member, strempty(c->vtable->x.property.signature), strempty(signature)); + + r = sd_bus_message_enter_container(m, 'v', c->vtable->x.property.signature); + if (r < 0) + return r; + + r = check_access(bus, m, c, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + + r = invoke_property_set(bus, slot, c->vtable, m->path, c->interface, c->member, m, u, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + + if (bus->nodes_modified) + return 0; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + } + + r = sd_bus_send(bus, reply, NULL); + if (r < 0) + return r; + + return 1; +} + +static int vtable_append_one_property( + sd_bus *bus, + sd_bus_message *reply, + const char *path, + struct node_vtable *c, + const sd_bus_vtable *v, + void *userdata, + sd_bus_error *error) { + + sd_bus_slot *slot; + int r; + + assert(bus); + assert(reply); + assert(path); + assert(c); + assert(v); + + r = sd_bus_message_open_container(reply, 'e', "sv"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "s", v->x.property.member); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'v', v->x.property.signature); + if (r < 0) + return r; + + slot = container_of(c, sd_bus_slot, node_vtable); + + r = invoke_property_get(bus, slot, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return 0; +} + +static int vtable_append_all_properties( + sd_bus *bus, + sd_bus_message *reply, + const char *path, + struct node_vtable *c, + void *userdata, + sd_bus_error *error) { + + const sd_bus_vtable *v; + int r; + + assert(bus); + assert(reply); + assert(path); + assert(c); + + if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN) + return 1; + + v = c->vtable; + for (v = bus_vtable_next(c->vtable, v); v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(c->vtable, v)) { + if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY)) + continue; + + if (v->flags & SD_BUS_VTABLE_HIDDEN) + continue; + + if (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT) + continue; + + r = vtable_append_one_property(bus, reply, path, c, v, userdata, error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + } + + return 1; +} + +static int property_get_all_callbacks_run( + sd_bus *bus, + sd_bus_message *m, + struct node_vtable *first, + bool require_fallback, + const char *iface, + bool *found_object) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + struct node_vtable *c; + bool found_interface; + int r; + + assert(bus); + assert(m); + assert(found_object); + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "{sv}"); + if (r < 0) + return r; + + found_interface = !iface || + streq(iface, "org.freedesktop.DBus.Properties") || + streq(iface, "org.freedesktop.DBus.Peer") || + streq(iface, "org.freedesktop.DBus.Introspectable"); + + LIST_FOREACH(vtables, c, first) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + void *u; + + if (require_fallback && !c->is_fallback) + continue; + + r = node_vtable_get_userdata(bus, m->path, c, &u, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + if (bus->nodes_modified) + return 0; + if (r == 0) + continue; + + *found_object = true; + + if (iface && !streq(c->interface, iface)) + continue; + found_interface = true; + + r = vtable_append_all_properties(bus, reply, m->path, c, u, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + if (bus->nodes_modified) + return 0; + } + + if (!*found_object) + return 0; + + if (!found_interface) { + r = sd_bus_reply_method_errorf( + m, + SD_BUS_ERROR_UNKNOWN_INTERFACE, + "Unknown interface '%s'.", iface); + if (r < 0) + return r; + + return 1; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + r = sd_bus_send(bus, reply, NULL); + if (r < 0) + return r; + + return 1; +} + +static int bus_node_exists( + sd_bus *bus, + struct node *n, + const char *path, + bool require_fallback) { + + struct node_vtable *c; + struct node_callback *k; + int r; + + assert(bus); + assert(n); + assert(path); + + /* Tests if there's anything attached directly to this node + * for the specified path */ + + if (!require_fallback && (n->enumerators || n->object_managers)) + return true; + + LIST_FOREACH(callbacks, k, n->callbacks) { + if (require_fallback && !k->is_fallback) + continue; + + return 1; + } + + LIST_FOREACH(vtables, c, n->vtables) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + if (require_fallback && !c->is_fallback) + continue; + + r = node_vtable_get_userdata(bus, path, c, NULL, &error); + if (r != 0) + return r; + if (bus->nodes_modified) + return 0; + } + + return 0; +} + +int introspect_path( + sd_bus *bus, + const char *path, + struct node *n, + bool require_fallback, + bool ignore_nodes_modified, + bool *found_object, + char **ret, + sd_bus_error *error) { + + _cleanup_set_free_free_ Set *s = NULL; + const char *previous_interface = NULL; + _cleanup_(introspect_free) struct introspect intro = {}; + struct node_vtable *c; + bool empty; + int r; + + if (!n) { + n = hashmap_get(bus->nodes, path); + if (!n) + return -ENOENT; + } + + r = get_child_nodes(bus, path, n, 0, &s, error); + if (r < 0) + return r; + if (bus->nodes_modified && !ignore_nodes_modified) + return 0; + + r = introspect_begin(&intro, bus->trusted); + if (r < 0) + return r; + + r = introspect_write_default_interfaces(&intro, !require_fallback && n->object_managers); + if (r < 0) + return r; + + empty = set_isempty(s); + + LIST_FOREACH(vtables, c, n->vtables) { + if (require_fallback && !c->is_fallback) + continue; + + r = node_vtable_get_userdata(bus, path, c, NULL, error); + if (r < 0) + return r; + if (bus->nodes_modified && !ignore_nodes_modified) + return 0; + if (r == 0) + continue; + + empty = false; + + if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN) + continue; + + if (!streq_ptr(previous_interface, c->interface)) { + if (previous_interface) + fputs(" \n", intro.f); + + fprintf(intro.f, " \n", c->interface); + } + + r = introspect_write_interface(&intro, c->vtable); + if (r < 0) + return r; + + previous_interface = c->interface; + } + + if (previous_interface) + fputs(" \n", intro.f); + + if (empty) { + /* Nothing?, let's see if we exist at all, and if not + * refuse to do anything */ + r = bus_node_exists(bus, n, path, require_fallback); + if (r <= 0) + return r; + if (bus->nodes_modified && !ignore_nodes_modified) + return 0; + } + + if (found_object) + *found_object = true; + + r = introspect_write_child_nodes(&intro, s, path); + if (r < 0) + return r; + + r = introspect_finish(&intro, ret); + if (r < 0) + return r; + + return 1; +} + +static int process_introspect( + sd_bus *bus, + sd_bus_message *m, + struct node *n, + bool require_fallback, + bool *found_object) { + + _cleanup_free_ char *s = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + assert(bus); + assert(m); + assert(n); + assert(found_object); + + r = introspect_path(bus, m->path, n, require_fallback, false, found_object, &s, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + if (r == 0) + /* nodes_modified == true */ + return 0; + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "s", s); + if (r < 0) + return r; + + r = sd_bus_send(bus, reply, NULL); + if (r < 0) + return r; + + return 1; +} + +static int object_manager_serialize_path( + sd_bus *bus, + sd_bus_message *reply, + const char *prefix, + const char *path, + bool require_fallback, + sd_bus_error *error) { + + const char *previous_interface = NULL; + bool found_something = false; + struct node_vtable *i; + struct node *n; + int r; + + assert(bus); + assert(reply); + assert(prefix); + assert(path); + assert(error); + + n = hashmap_get(bus->nodes, prefix); + if (!n) + return 0; + + LIST_FOREACH(vtables, i, n->vtables) { + void *u; + + if (require_fallback && !i->is_fallback) + continue; + + r = node_vtable_get_userdata(bus, path, i, &u, error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + if (r == 0) + continue; + + if (!found_something) { + + /* Open the object part */ + + r = sd_bus_message_open_container(reply, 'e', "oa{sa{sv}}"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "o", path); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "{sa{sv}}"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Peer", 0); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Introspectable", 0); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.Properties", 0); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "{sa{sv}}", "org.freedesktop.DBus.ObjectManager", 0); + if (r < 0) + return r; + + found_something = true; + } + + if (!streq_ptr(previous_interface, i->interface)) { + + /* Maybe close the previous interface part */ + + if (previous_interface) { + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } + + /* Open the new interface part */ + + r = sd_bus_message_open_container(reply, 'e', "sa{sv}"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "s", i->interface); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "{sv}"); + if (r < 0) + return r; + } + + r = vtable_append_all_properties(bus, reply, path, i, u, error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + + previous_interface = i->interface; + } + + if (previous_interface) { + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } + + if (found_something) { + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } + + return 1; +} + +static int object_manager_serialize_path_and_fallbacks( + sd_bus *bus, + sd_bus_message *reply, + const char *path, + sd_bus_error *error) { + + _cleanup_free_ char *prefix = NULL; + size_t pl; + int r; + + assert(bus); + assert(reply); + assert(path); + assert(error); + + /* First, add all vtables registered for this path */ + r = object_manager_serialize_path(bus, reply, path, path, false, error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + + /* Second, add fallback vtables registered for any of the prefixes */ + pl = strlen(path); + assert(pl <= BUS_PATH_SIZE_MAX); + prefix = new(char, pl + 1); + if (!prefix) + return -ENOMEM; + + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = object_manager_serialize_path(bus, reply, prefix, path, true, error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + } + + return 0; +} + +static int process_get_managed_objects( + sd_bus *bus, + sd_bus_message *m, + struct node *n, + bool require_fallback, + bool *found_object) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_set_free_free_ Set *s = NULL; + Iterator i; + char *path; + int r; + + assert(bus); + assert(m); + assert(n); + assert(found_object); + + /* Spec says, GetManagedObjects() is only implemented on the root of a + * sub-tree. Therefore, we require a registered object-manager on + * exactly the queried path, otherwise, we refuse to respond. */ + + if (require_fallback || !n->object_managers) + return 0; + + r = get_child_nodes(bus, m->path, n, CHILDREN_RECURSIVE, &s, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + if (bus->nodes_modified) + return 0; + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "{oa{sa{sv}}}"); + if (r < 0) + return r; + + SET_FOREACH(path, s, i) { + r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + + if (bus->nodes_modified) + return 0; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + r = sd_bus_send(bus, reply, NULL); + if (r < 0) + return r; + + return 1; +} + +static int object_find_and_run( + sd_bus *bus, + sd_bus_message *m, + const char *p, + bool require_fallback, + bool *found_object) { + + struct node *n; + struct vtable_member vtable_key, *v; + int r; + + assert(bus); + assert(m); + assert(p); + assert(found_object); + + n = hashmap_get(bus->nodes, p); + if (!n) + return 0; + + /* First, try object callbacks */ + r = node_callbacks_run(bus, m, n->callbacks, require_fallback, found_object); + if (r != 0) + return r; + if (bus->nodes_modified) + return 0; + + if (!m->interface || !m->member) + return 0; + + /* Then, look for a known method */ + vtable_key.path = (char*) p; + vtable_key.interface = m->interface; + vtable_key.member = m->member; + + v = hashmap_get(bus->vtable_methods, &vtable_key); + if (v) { + r = method_callbacks_run(bus, m, v, require_fallback, found_object); + if (r != 0) + return r; + if (bus->nodes_modified) + return 0; + } + + /* Then, look for a known property */ + if (streq(m->interface, "org.freedesktop.DBus.Properties")) { + bool get = false; + + get = streq(m->member, "Get"); + + if (get || streq(m->member, "Set")) { + + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + vtable_key.path = (char*) p; + + r = sd_bus_message_read(m, "ss", &vtable_key.interface, &vtable_key.member); + if (r < 0) + return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface and member parameters"); + + v = hashmap_get(bus->vtable_properties, &vtable_key); + if (v) { + r = property_get_set_callbacks_run(bus, m, v, require_fallback, get, found_object); + if (r != 0) + return r; + } + + } else if (streq(m->member, "GetAll")) { + const char *iface; + + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + r = sd_bus_message_read(m, "s", &iface); + if (r < 0) + return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected interface parameter"); + + if (iface[0] == 0) + iface = NULL; + + r = property_get_all_callbacks_run(bus, m, n->vtables, require_fallback, iface, found_object); + if (r != 0) + return r; + } + + } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) { + + if (!isempty(sd_bus_message_get_signature(m, true))) + return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters"); + + r = process_introspect(bus, m, n, require_fallback, found_object); + if (r != 0) + return r; + + } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) { + + if (!isempty(sd_bus_message_get_signature(m, true))) + return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters"); + + r = process_get_managed_objects(bus, m, n, require_fallback, found_object); + if (r != 0) + return r; + } + + if (bus->nodes_modified) + return 0; + + if (!*found_object) { + r = bus_node_exists(bus, n, m->path, require_fallback); + if (r < 0) + return bus_maybe_reply_error(m, r, NULL); + if (bus->nodes_modified) + return 0; + if (r > 0) + *found_object = true; + } + + return 0; +} + +int bus_process_object(sd_bus *bus, sd_bus_message *m) { + _cleanup_free_ char *prefix = NULL; + int r; + size_t pl; + bool found_object = false; + + assert(bus); + assert(m); + + if (bus->is_monitor) + return 0; + + if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL) + return 0; + + if (hashmap_isempty(bus->nodes)) + return 0; + + /* Never respond to broadcast messages */ + if (bus->bus_client && !m->destination) + return 0; + + assert(m->path); + assert(m->member); + + pl = strlen(m->path); + assert(pl <= BUS_PATH_SIZE_MAX); + prefix = new(char, pl + 1); + if (!prefix) + return -ENOMEM; + + do { + bus->nodes_modified = false; + + r = object_find_and_run(bus, m, m->path, false, &found_object); + if (r != 0) + return r; + + /* Look for fallback prefixes */ + OBJECT_PATH_FOREACH_PREFIX(prefix, m->path) { + + if (bus->nodes_modified) + break; + + r = object_find_and_run(bus, m, prefix, true, &found_object); + if (r != 0) + return r; + } + + } while (bus->nodes_modified); + + if (!found_object) + return 0; + + if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get") || + sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set")) { + const char *interface = NULL, *property = NULL; + + (void) sd_bus_message_rewind(m, true); + (void) sd_bus_message_read_basic(m, 's', &interface); + (void) sd_bus_message_read_basic(m, 's', &property); + + r = sd_bus_reply_method_errorf( + m, + SD_BUS_ERROR_UNKNOWN_PROPERTY, + "Unknown interface %s or property %s.", strnull(interface), strnull(property)); + } else + r = sd_bus_reply_method_errorf( + m, + SD_BUS_ERROR_UNKNOWN_METHOD, + "Unknown method %s or interface %s.", m->member, m->interface); + + if (r < 0) + return r; + + return 1; +} + +static struct node *bus_node_allocate(sd_bus *bus, const char *path) { + struct node *n, *parent; + const char *e; + _cleanup_free_ char *s = NULL; + char *p; + int r; + + assert(bus); + assert(path); + assert(path[0] == '/'); + + n = hashmap_get(bus->nodes, path); + if (n) + return n; + + r = hashmap_ensure_allocated(&bus->nodes, &string_hash_ops); + if (r < 0) + return NULL; + + s = strdup(path); + if (!s) + return NULL; + + if (streq(path, "/")) + parent = NULL; + else { + e = strrchr(path, '/'); + assert(e); + + p = strndupa(path, MAX(1, e - path)); + + parent = bus_node_allocate(bus, p); + if (!parent) + return NULL; + } + + n = new0(struct node, 1); + if (!n) + return NULL; + + n->parent = parent; + n->path = TAKE_PTR(s); + + r = hashmap_put(bus->nodes, n->path, n); + if (r < 0) { + free(n->path); + return mfree(n); + } + + if (parent) + LIST_PREPEND(siblings, parent->child, n); + + return n; +} + +void bus_node_gc(sd_bus *b, struct node *n) { + assert(b); + + if (!n) + return; + + if (n->child || + n->callbacks || + n->vtables || + n->enumerators || + n->object_managers) + return; + + assert_se(hashmap_remove(b->nodes, n->path) == n); + + if (n->parent) + LIST_REMOVE(siblings, n->parent->child, n); + + free(n->path); + bus_node_gc(b, n->parent); + free(n); +} + +static int bus_find_parent_object_manager(sd_bus *bus, struct node **out, const char *path) { + struct node *n; + + assert(bus); + assert(path); + + n = hashmap_get(bus->nodes, path); + if (!n) { + _cleanup_free_ char *prefix = NULL; + size_t pl; + + pl = strlen(path); + assert(pl <= BUS_PATH_SIZE_MAX); + prefix = new(char, pl + 1); + if (!prefix) + return -ENOMEM; + + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + n = hashmap_get(bus->nodes, prefix); + if (n) + break; + } + } + + while (n && !n->object_managers) + n = n->parent; + + if (out) + *out = n; + return !!n; +} + +static int bus_add_object( + sd_bus *bus, + sd_bus_slot **slot, + bool fallback, + const char *path, + sd_bus_message_handler_t callback, + void *userdata) { + + sd_bus_slot *s; + struct node *n; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(callback, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + n = bus_node_allocate(bus, path); + if (!n) + return -ENOMEM; + + s = bus_slot_allocate(bus, !slot, BUS_NODE_CALLBACK, sizeof(struct node_callback), userdata); + if (!s) { + r = -ENOMEM; + goto fail; + } + + s->node_callback.callback = callback; + s->node_callback.is_fallback = fallback; + + s->node_callback.node = n; + LIST_PREPEND(callbacks, n->callbacks, &s->node_callback); + bus->nodes_modified = true; + + if (slot) + *slot = s; + + return 0; + +fail: + sd_bus_slot_unref(s); + bus_node_gc(bus, n); + + return r; +} + +_public_ int sd_bus_add_object( + sd_bus *bus, + sd_bus_slot **slot, + const char *path, + sd_bus_message_handler_t callback, + void *userdata) { + + return bus_add_object(bus, slot, false, path, callback, userdata); +} + +_public_ int sd_bus_add_fallback( + sd_bus *bus, + sd_bus_slot **slot, + const char *prefix, + sd_bus_message_handler_t callback, + void *userdata) { + + return bus_add_object(bus, slot, true, prefix, callback, userdata); +} + +static void vtable_member_hash_func(const struct vtable_member *m, struct siphash *state) { + assert(m); + + string_hash_func(m->path, state); + string_hash_func(m->interface, state); + string_hash_func(m->member, state); +} + +static int vtable_member_compare_func(const struct vtable_member *x, const struct vtable_member *y) { + int r; + + assert(x); + assert(y); + + r = strcmp(x->path, y->path); + if (r != 0) + return r; + + r = strcmp(x->interface, y->interface); + if (r != 0) + return r; + + return strcmp(x->member, y->member); +} + +DEFINE_PRIVATE_HASH_OPS(vtable_member_hash_ops, struct vtable_member, vtable_member_hash_func, vtable_member_compare_func); + +typedef enum { + NAMES_FIRST_PART = 1 << 0, /* first part of argument name list (input names). It is reset by names_are_valid() */ + NAMES_PRESENT = 1 << 1, /* at least one argument name is present, so the names will checked. + This flag is set and used internally by names_are_valid(), but needs to be stored across calls for 2-parts list */ + NAMES_SINGLE_PART = 1 << 2, /* argument name list consisting of a single part */ +} names_flags; + +static bool names_are_valid(const char *signature, const char **names, names_flags *flags) { + int r; + + if ((*flags & NAMES_FIRST_PART || *flags & NAMES_SINGLE_PART) && **names != '\0') + *flags |= NAMES_PRESENT; + + for (;*flags & NAMES_PRESENT;) { + size_t l; + + if (!*signature) + break; + + r = signature_element_length(signature, &l); + if (r < 0) + return false; + + if (**names != '\0') { + if (!member_name_is_valid(*names)) + return false; + *names += strlen(*names) + 1; + } else if (*flags & NAMES_PRESENT) + return false; + + signature += l; + } + /* let's check if there are more argument names specified than the signature allows */ + if (*flags & NAMES_PRESENT && **names != '\0' && !(*flags & NAMES_FIRST_PART)) + return false; + *flags &= ~NAMES_FIRST_PART; + return true; +} + +/* the current version of this struct is defined in sd-bus-vtable.h, but we need to list here the historical versions + to make sure the calling code is compatible with one of these */ +struct sd_bus_vtable_221 { + uint8_t type:8; + uint64_t flags:56; + union { + struct { + size_t element_size; + } start; + struct { + const char *member; + const char *signature; + const char *result; + sd_bus_message_handler_t handler; + size_t offset; + } method; + struct { + const char *member; + const char *signature; + } signal; + struct { + const char *member; + const char *signature; + sd_bus_property_get_t get; + sd_bus_property_set_t set; + size_t offset; + } property; + } x; +}; +/* Structure size up to v241 */ +#define VTABLE_ELEMENT_SIZE_221 sizeof(struct sd_bus_vtable_221) + +/* Size of the structure when "features" field was added. If the structure definition is augmented, a copy of + * the structure definition will need to be made (similarly to the sd_bus_vtable_221 above), and this + * definition updated to refer to it. */ +#define VTABLE_ELEMENT_SIZE_242 sizeof(struct sd_bus_vtable) + +static int vtable_features(const sd_bus_vtable *vtable) { + if (vtable[0].x.start.element_size < VTABLE_ELEMENT_SIZE_242 || + !vtable[0].x.start.vtable_format_reference) + return 0; + return vtable[0].x.start.features; +} + +bool bus_vtable_has_names(const sd_bus_vtable *vtable) { + return vtable_features(vtable) & _SD_BUS_VTABLE_PARAM_NAMES; +} + +const sd_bus_vtable* bus_vtable_next(const sd_bus_vtable *vtable, const sd_bus_vtable *v) { + return (const sd_bus_vtable*) ((char*) v + vtable[0].x.start.element_size); +} + +static int add_object_vtable_internal( + sd_bus *bus, + sd_bus_slot **slot, + const char *path, + const char *interface, + const sd_bus_vtable *vtable, + bool fallback, + sd_bus_object_find_t find, + void *userdata) { + + sd_bus_slot *s = NULL; + struct node_vtable *i, *existing = NULL; + const sd_bus_vtable *v; + struct node *n; + int r; + const char *names = ""; + names_flags nf; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(interface_name_is_valid(interface), -EINVAL); + assert_return(vtable, -EINVAL); + assert_return(vtable[0].type == _SD_BUS_VTABLE_START, -EINVAL); + assert_return(vtable[0].x.start.element_size == VTABLE_ELEMENT_SIZE_221 || + vtable[0].x.start.element_size >= VTABLE_ELEMENT_SIZE_242, + -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + assert_return(!streq(interface, "org.freedesktop.DBus.Properties") && + !streq(interface, "org.freedesktop.DBus.Introspectable") && + !streq(interface, "org.freedesktop.DBus.Peer") && + !streq(interface, "org.freedesktop.DBus.ObjectManager"), -EINVAL); + + r = hashmap_ensure_allocated(&bus->vtable_methods, &vtable_member_hash_ops); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&bus->vtable_properties, &vtable_member_hash_ops); + if (r < 0) + return r; + + n = bus_node_allocate(bus, path); + if (!n) + return -ENOMEM; + + LIST_FOREACH(vtables, i, n->vtables) { + if (i->is_fallback != fallback) { + r = -EPROTOTYPE; + goto fail; + } + + if (streq(i->interface, interface)) { + + if (i->vtable == vtable) { + r = -EEXIST; + goto fail; + } + + existing = i; + } + } + + s = bus_slot_allocate(bus, !slot, BUS_NODE_VTABLE, sizeof(struct node_vtable), userdata); + if (!s) { + r = -ENOMEM; + goto fail; + } + + s->node_vtable.is_fallback = fallback; + s->node_vtable.vtable = vtable; + s->node_vtable.find = find; + + s->node_vtable.interface = strdup(interface); + if (!s->node_vtable.interface) { + r = -ENOMEM; + goto fail; + } + + v = s->node_vtable.vtable; + for (v = bus_vtable_next(vtable, v); v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(vtable, v)) { + + switch (v->type) { + + case _SD_BUS_VTABLE_METHOD: { + struct vtable_member *m; + nf = NAMES_FIRST_PART; + + if (bus_vtable_has_names(vtable)) + names = strempty(v->x.method.names); + + if (!member_name_is_valid(v->x.method.member) || + !signature_is_valid(strempty(v->x.method.signature), false) || + !signature_is_valid(strempty(v->x.method.result), false) || + !names_are_valid(strempty(v->x.method.signature), &names, &nf) || + !names_are_valid(strempty(v->x.method.result), &names, &nf) || + !(v->x.method.handler || (isempty(v->x.method.signature) && isempty(v->x.method.result))) || + v->flags & (SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) { + r = -EINVAL; + goto fail; + } + + m = new0(struct vtable_member, 1); + if (!m) { + r = -ENOMEM; + goto fail; + } + + m->parent = &s->node_vtable; + m->path = n->path; + m->interface = s->node_vtable.interface; + m->member = v->x.method.member; + m->vtable = v; + + r = hashmap_put(bus->vtable_methods, m, m); + if (r < 0) { + free(m); + goto fail; + } + + break; + } + + case _SD_BUS_VTABLE_WRITABLE_PROPERTY: + + if (!(v->x.property.set || bus_type_is_basic(v->x.property.signature[0]))) { + r = -EINVAL; + goto fail; + } + + if (v->flags & SD_BUS_VTABLE_PROPERTY_CONST) { + r = -EINVAL; + goto fail; + } + + _fallthrough_; + case _SD_BUS_VTABLE_PROPERTY: { + struct vtable_member *m; + + if (!member_name_is_valid(v->x.property.member) || + !signature_is_single(v->x.property.signature, false) || + !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) || + (v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY) || + (!!(v->flags & SD_BUS_VTABLE_PROPERTY_CONST) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) + !!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) > 1 || + ((v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE) && (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)) || + (v->flags & SD_BUS_VTABLE_UNPRIVILEGED && v->type == _SD_BUS_VTABLE_PROPERTY)) { + r = -EINVAL; + goto fail; + } + + m = new0(struct vtable_member, 1); + if (!m) { + r = -ENOMEM; + goto fail; + } + + m->parent = &s->node_vtable; + m->path = n->path; + m->interface = s->node_vtable.interface; + m->member = v->x.property.member; + m->vtable = v; + + r = hashmap_put(bus->vtable_properties, m, m); + if (r < 0) { + free(m); + goto fail; + } + + break; + } + + case _SD_BUS_VTABLE_SIGNAL: + nf = NAMES_SINGLE_PART; + + if (bus_vtable_has_names(vtable)) + names = strempty(v->x.signal.names); + + if (!member_name_is_valid(v->x.signal.member) || + !signature_is_valid(strempty(v->x.signal.signature), false) || + !names_are_valid(strempty(v->x.signal.signature), &names, &nf) || + v->flags & SD_BUS_VTABLE_UNPRIVILEGED) { + r = -EINVAL; + goto fail; + } + + break; + + default: + r = -EINVAL; + goto fail; + } + } + + s->node_vtable.node = n; + LIST_INSERT_AFTER(vtables, n->vtables, existing, &s->node_vtable); + bus->nodes_modified = true; + + if (slot) + *slot = s; + + return 0; + +fail: + sd_bus_slot_unref(s); + bus_node_gc(bus, n); + + return r; +} + +/* This symbol exists solely to tell the linker that the "new" vtable format is used. */ +_public_ const unsigned sd_bus_object_vtable_format = 242; + +_public_ int sd_bus_add_object_vtable( + sd_bus *bus, + sd_bus_slot **slot, + const char *path, + const char *interface, + const sd_bus_vtable *vtable, + void *userdata) { + + return add_object_vtable_internal(bus, slot, path, interface, vtable, false, NULL, userdata); +} + +_public_ int sd_bus_add_fallback_vtable( + sd_bus *bus, + sd_bus_slot **slot, + const char *prefix, + const char *interface, + const sd_bus_vtable *vtable, + sd_bus_object_find_t find, + void *userdata) { + + return add_object_vtable_internal(bus, slot, prefix, interface, vtable, true, find, userdata); +} + +_public_ int sd_bus_add_node_enumerator( + sd_bus *bus, + sd_bus_slot **slot, + const char *path, + sd_bus_node_enumerator_t callback, + void *userdata) { + + sd_bus_slot *s; + struct node *n; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(callback, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + n = bus_node_allocate(bus, path); + if (!n) + return -ENOMEM; + + s = bus_slot_allocate(bus, !slot, BUS_NODE_ENUMERATOR, sizeof(struct node_enumerator), userdata); + if (!s) { + r = -ENOMEM; + goto fail; + } + + s->node_enumerator.callback = callback; + + s->node_enumerator.node = n; + LIST_PREPEND(enumerators, n->enumerators, &s->node_enumerator); + bus->nodes_modified = true; + + if (slot) + *slot = s; + + return 0; + +fail: + sd_bus_slot_unref(s); + bus_node_gc(bus, n); + + return r; +} + +static int emit_properties_changed_on_interface( + sd_bus *bus, + const char *prefix, + const char *path, + const char *interface, + bool require_fallback, + bool *found_interface, + char **names) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + bool has_invalidating = false, has_changing = false; + struct vtable_member key = {}; + struct node_vtable *c; + struct node *n; + char **property; + void *u = NULL; + int r; + + assert(bus); + assert(prefix); + assert(path); + assert(interface); + assert(found_interface); + + n = hashmap_get(bus->nodes, prefix); + if (!n) + return 0; + + r = sd_bus_message_new_signal(bus, &m, path, "org.freedesktop.DBus.Properties", "PropertiesChanged"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "s", interface); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "{sv}"); + if (r < 0) + return r; + + key.path = prefix; + key.interface = interface; + + LIST_FOREACH(vtables, c, n->vtables) { + if (require_fallback && !c->is_fallback) + continue; + + if (!streq(c->interface, interface)) + continue; + + r = node_vtable_get_userdata(bus, path, c, &u, &error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + if (r == 0) + continue; + + *found_interface = true; + + if (names) { + /* If the caller specified a list of + * properties we include exactly those in the + * PropertiesChanged message */ + + STRV_FOREACH(property, names) { + struct vtable_member *v; + + assert_return(member_name_is_valid(*property), -EINVAL); + + key.member = *property; + v = hashmap_get(bus->vtable_properties, &key); + if (!v) + return -ENOENT; + + /* If there are two vtables for the same + * interface, let's handle this property when + * we come to that vtable. */ + if (c != v->parent) + continue; + + assert_return(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE || + v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION, -EDOM); + + assert_return(!(v->vtable->flags & SD_BUS_VTABLE_HIDDEN), -EDOM); + + if (v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) { + has_invalidating = true; + continue; + } + + has_changing = true; + + r = vtable_append_one_property(bus, m, m->path, c, v->vtable, u, &error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + } + } else { + const sd_bus_vtable *v; + + /* If the caller specified no properties list + * we include all properties that are marked + * as changing in the message. */ + + v = c->vtable; + for (v = bus_vtable_next(c->vtable, v); v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(c->vtable, v)) { + if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY)) + continue; + + if (v->flags & SD_BUS_VTABLE_HIDDEN) + continue; + + if (v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION) { + has_invalidating = true; + continue; + } + + if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) + continue; + + has_changing = true; + + r = vtable_append_one_property(bus, m, m->path, c, v, u, &error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + } + } + } + + if (!has_invalidating && !has_changing) + return 0; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return r; + + if (has_invalidating) { + LIST_FOREACH(vtables, c, n->vtables) { + if (require_fallback && !c->is_fallback) + continue; + + if (!streq(c->interface, interface)) + continue; + + r = node_vtable_get_userdata(bus, path, c, &u, &error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + if (r == 0) + continue; + + if (names) { + STRV_FOREACH(property, names) { + struct vtable_member *v; + + key.member = *property; + assert_se(v = hashmap_get(bus->vtable_properties, &key)); + assert(c == v->parent); + + if (!(v->vtable->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) + continue; + + r = sd_bus_message_append(m, "s", *property); + if (r < 0) + return r; + } + } else { + const sd_bus_vtable *v; + + v = c->vtable; + for (v = bus_vtable_next(c->vtable, v); v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(c->vtable, v)) { + if (!IN_SET(v->type, _SD_BUS_VTABLE_PROPERTY, _SD_BUS_VTABLE_WRITABLE_PROPERTY)) + continue; + + if (v->flags & SD_BUS_VTABLE_HIDDEN) + continue; + + if (!(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION)) + continue; + + r = sd_bus_message_append(m, "s", v->x.property.member); + if (r < 0) + return r; + } + } + } + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_send(bus, m, NULL); + if (r < 0) + return r; + + return 1; +} + +_public_ int sd_bus_emit_properties_changed_strv( + sd_bus *bus, + const char *path, + const char *interface, + char **names) { + + _cleanup_free_ char *prefix = NULL; + bool found_interface = false; + size_t pl; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(interface_name_is_valid(interface), -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + /* A non-NULL but empty names list means nothing needs to be + generated. A NULL list OTOH indicates that all properties + that are set to EMITS_CHANGE or EMITS_INVALIDATION shall be + included in the PropertiesChanged message. */ + if (names && names[0] == NULL) + return 0; + + BUS_DONT_DESTROY(bus); + + pl = strlen(path); + assert(pl <= BUS_PATH_SIZE_MAX); + prefix = new(char, pl + 1); + if (!prefix) + return -ENOMEM; + + do { + bus->nodes_modified = false; + + r = emit_properties_changed_on_interface(bus, path, path, interface, false, &found_interface, names); + if (r != 0) + return r; + if (bus->nodes_modified) + continue; + + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, &found_interface, names); + if (r != 0) + return r; + if (bus->nodes_modified) + break; + } + + } while (bus->nodes_modified); + + return found_interface ? 0 : -ENOENT; +} + +_public_ int sd_bus_emit_properties_changed( + sd_bus *bus, + const char *path, + const char *interface, + const char *name, ...) { + + char **names; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(interface_name_is_valid(interface), -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (!name) + return 0; + + names = strv_from_stdarg_alloca(name); + + return sd_bus_emit_properties_changed_strv(bus, path, interface, names); +} + +static int object_added_append_all_prefix( + sd_bus *bus, + sd_bus_message *m, + Set *s, + const char *prefix, + const char *path, + bool require_fallback) { + + const char *previous_interface = NULL; + struct node_vtable *c; + struct node *n; + int r; + + assert(bus); + assert(m); + assert(s); + assert(prefix); + assert(path); + + n = hashmap_get(bus->nodes, prefix); + if (!n) + return 0; + + LIST_FOREACH(vtables, c, n->vtables) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + void *u = NULL; + + if (require_fallback && !c->is_fallback) + continue; + + r = node_vtable_get_userdata(bus, path, c, &u, &error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + if (r == 0) + continue; + + if (!streq_ptr(c->interface, previous_interface)) { + /* If a child-node already handled this interface, we + * skip it on any of its parents. The child vtables + * always fully override any conflicting vtables of + * any parent node. */ + if (set_get(s, c->interface)) + continue; + + r = set_put(s, c->interface); + if (r < 0) + return r; + + if (previous_interface) { + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + } + + r = sd_bus_message_open_container(m, 'e', "sa{sv}"); + if (r < 0) + return r; + r = sd_bus_message_append(m, "s", c->interface); + if (r < 0) + return r; + r = sd_bus_message_open_container(m, 'a', "{sv}"); + if (r < 0) + return r; + + previous_interface = c->interface; + } + + r = vtable_append_all_properties(bus, m, path, c, u, &error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + } + + if (previous_interface) { + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + } + + return 0; +} + +static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *path) { + _cleanup_set_free_ Set *s = NULL; + _cleanup_free_ char *prefix = NULL; + size_t pl; + int r; + + assert(bus); + assert(m); + assert(path); + + /* + * This appends all interfaces registered on path @path. We first add + * the builtin interfaces, which are always available and handled by + * sd-bus. Then, we add all interfaces registered on the exact node, + * followed by all fallback interfaces registered on any parent prefix. + * + * If an interface is registered multiple times on the same node with + * different vtables, we merge all the properties across all vtables. + * However, if a child node has the same interface registered as one of + * its parent nodes has as fallback, we make the child overwrite the + * parent instead of extending it. Therefore, we keep a "Set" of all + * handled interfaces during parent traversal, so we skip interfaces on + * a parent that were overwritten by a child. + */ + + s = set_new(&string_hash_ops); + if (!s) + return -ENOMEM; + + r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Peer", 0); + if (r < 0) + return r; + r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Introspectable", 0); + if (r < 0) + return r; + r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.Properties", 0); + if (r < 0) + return r; + r = sd_bus_message_append(m, "{sa{sv}}", "org.freedesktop.DBus.ObjectManager", 0); + if (r < 0) + return r; + + r = object_added_append_all_prefix(bus, m, s, path, path, false); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + + pl = strlen(path); + assert(pl <= BUS_PATH_SIZE_MAX); + prefix = new(char, pl + 1); + if (!prefix) + return -ENOMEM; + + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = object_added_append_all_prefix(bus, m, s, prefix, path, true); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + } + + return 0; +} + +_public_ int sd_bus_emit_object_added(sd_bus *bus, const char *path) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + struct node *object_manager; + int r; + + /* + * This emits an InterfacesAdded signal on the given path, by iterating + * all registered vtables and fallback vtables on the path. All + * properties are queried and included in the signal. + * This call is equivalent to sd_bus_emit_interfaces_added() with an + * explicit list of registered interfaces. However, unlike + * interfaces_added(), this call can figure out the list of supported + * interfaces itself. Furthermore, it properly adds the builtin + * org.freedesktop.DBus.* interfaces. + */ + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + r = bus_find_parent_object_manager(bus, &object_manager, path); + if (r < 0) + return r; + if (r == 0) + return -ESRCH; + + BUS_DONT_DESTROY(bus); + + do { + bus->nodes_modified = false; + m = sd_bus_message_unref(m); + + r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"); + if (r < 0) + return r; + + r = sd_bus_message_append_basic(m, 'o', path); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "{sa{sv}}"); + if (r < 0) + return r; + + r = object_added_append_all(bus, m, path); + if (r < 0) + return r; + + if (bus->nodes_modified) + continue; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + } while (bus->nodes_modified); + + return sd_bus_send(bus, m, NULL); +} + +static int object_removed_append_all_prefix( + sd_bus *bus, + sd_bus_message *m, + Set *s, + const char *prefix, + const char *path, + bool require_fallback) { + + const char *previous_interface = NULL; + struct node_vtable *c; + struct node *n; + int r; + + assert(bus); + assert(m); + assert(s); + assert(prefix); + assert(path); + + n = hashmap_get(bus->nodes, prefix); + if (!n) + return 0; + + LIST_FOREACH(vtables, c, n->vtables) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + void *u = NULL; + + if (require_fallback && !c->is_fallback) + continue; + if (streq_ptr(c->interface, previous_interface)) + continue; + + /* If a child-node already handled this interface, we + * skip it on any of its parents. The child vtables + * always fully override any conflicting vtables of + * any parent node. */ + if (set_get(s, c->interface)) + continue; + + r = node_vtable_get_userdata(bus, path, c, &u, &error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + if (r == 0) + continue; + + r = set_put(s, c->interface); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "s", c->interface); + if (r < 0) + return r; + + previous_interface = c->interface; + } + + return 0; +} + +static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char *path) { + _cleanup_set_free_ Set *s = NULL; + _cleanup_free_ char *prefix = NULL; + size_t pl; + int r; + + assert(bus); + assert(m); + assert(path); + + /* see sd_bus_emit_object_added() for details */ + + s = set_new(&string_hash_ops); + if (!s) + return -ENOMEM; + + r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Peer"); + if (r < 0) + return r; + r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Introspectable"); + if (r < 0) + return r; + r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.Properties"); + if (r < 0) + return r; + r = sd_bus_message_append(m, "s", "org.freedesktop.DBus.ObjectManager"); + if (r < 0) + return r; + + r = object_removed_append_all_prefix(bus, m, s, path, path, false); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + + pl = strlen(path); + assert(pl <= BUS_PATH_SIZE_MAX); + prefix = new(char, pl + 1); + if (!prefix) + return -ENOMEM; + + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = object_removed_append_all_prefix(bus, m, s, prefix, path, true); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + } + + return 0; +} + +_public_ int sd_bus_emit_object_removed(sd_bus *bus, const char *path) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + struct node *object_manager; + int r; + + /* + * This is like sd_bus_emit_object_added(), but emits an + * InterfacesRemoved signal on the given path. This only includes any + * registered interfaces but skips the properties. Note that this will + * call into the find() callbacks of any registered vtable. Therefore, + * you must call this function before destroying/unlinking your object. + * Otherwise, the list of interfaces will be incomplete. However, note + * that this will *NOT* call into any property callback. Therefore, the + * object might be in an "destructed" state, as long as we can find it. + */ + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + r = bus_find_parent_object_manager(bus, &object_manager, path); + if (r < 0) + return r; + if (r == 0) + return -ESRCH; + + BUS_DONT_DESTROY(bus); + + do { + bus->nodes_modified = false; + m = sd_bus_message_unref(m); + + r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"); + if (r < 0) + return r; + + r = sd_bus_message_append_basic(m, 'o', path); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return r; + + r = object_removed_append_all(bus, m, path); + if (r < 0) + return r; + + if (bus->nodes_modified) + continue; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + } while (bus->nodes_modified); + + return sd_bus_send(bus, m, NULL); +} + +static int interfaces_added_append_one_prefix( + sd_bus *bus, + sd_bus_message *m, + const char *prefix, + const char *path, + const char *interface, + bool require_fallback) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + bool found_interface = false; + struct node_vtable *c; + struct node *n; + void *u = NULL; + int r; + + assert(bus); + assert(m); + assert(prefix); + assert(path); + assert(interface); + + n = hashmap_get(bus->nodes, prefix); + if (!n) + return 0; + + LIST_FOREACH(vtables, c, n->vtables) { + if (require_fallback && !c->is_fallback) + continue; + + if (!streq(c->interface, interface)) + continue; + + r = node_vtable_get_userdata(bus, path, c, &u, &error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + if (r == 0) + continue; + + if (!found_interface) { + r = sd_bus_message_append_basic(m, 's', interface); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "{sv}"); + if (r < 0) + return r; + + found_interface = true; + } + + r = vtable_append_all_properties(bus, m, path, c, u, &error); + if (r < 0) + return r; + if (bus->nodes_modified) + return 0; + } + + if (found_interface) { + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + } + + return found_interface; +} + +static int interfaces_added_append_one( + sd_bus *bus, + sd_bus_message *m, + const char *path, + const char *interface) { + + _cleanup_free_ char *prefix = NULL; + size_t pl; + int r; + + assert(bus); + assert(m); + assert(path); + assert(interface); + + r = interfaces_added_append_one_prefix(bus, m, path, path, interface, false); + if (r != 0) + return r; + if (bus->nodes_modified) + return 0; + + pl = strlen(path); + assert(pl <= BUS_PATH_SIZE_MAX); + prefix = new(char, pl + 1); + if (!prefix) + return -ENOMEM; + + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true); + if (r != 0) + return r; + if (bus->nodes_modified) + return 0; + } + + return -ENOENT; +} + +_public_ int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + struct node *object_manager; + char **i; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (strv_isempty(interfaces)) + return 0; + + r = bus_find_parent_object_manager(bus, &object_manager, path); + if (r < 0) + return r; + if (r == 0) + return -ESRCH; + + BUS_DONT_DESTROY(bus); + + do { + bus->nodes_modified = false; + m = sd_bus_message_unref(m); + + r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"); + if (r < 0) + return r; + + r = sd_bus_message_append_basic(m, 'o', path); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "{sa{sv}}"); + if (r < 0) + return r; + + STRV_FOREACH(i, interfaces) { + assert_return(interface_name_is_valid(*i), -EINVAL); + + r = sd_bus_message_open_container(m, 'e', "sa{sv}"); + if (r < 0) + return r; + + r = interfaces_added_append_one(bus, m, path, *i); + if (r < 0) + return r; + + if (bus->nodes_modified) + break; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + } + + if (bus->nodes_modified) + continue; + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + } while (bus->nodes_modified); + + return sd_bus_send(bus, m, NULL); +} + +_public_ int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) { + char **interfaces; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + interfaces = strv_from_stdarg_alloca(interface); + + return sd_bus_emit_interfaces_added_strv(bus, path, interfaces); +} + +_public_ int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + struct node *object_manager; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (strv_isempty(interfaces)) + return 0; + + r = bus_find_parent_object_manager(bus, &object_manager, path); + if (r < 0) + return r; + if (r == 0) + return -ESRCH; + + r = sd_bus_message_new_signal(bus, &m, object_manager->path, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"); + if (r < 0) + return r; + + r = sd_bus_message_append_basic(m, 'o', path); + if (r < 0) + return r; + + r = sd_bus_message_append_strv(m, interfaces); + if (r < 0) + return r; + + return sd_bus_send(bus, m, NULL); +} + +_public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) { + char **interfaces; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + interfaces = strv_from_stdarg_alloca(interface); + + return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces); +} + +_public_ int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) { + sd_bus_slot *s; + struct node *n; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + n = bus_node_allocate(bus, path); + if (!n) + return -ENOMEM; + + s = bus_slot_allocate(bus, !slot, BUS_NODE_OBJECT_MANAGER, sizeof(struct node_object_manager), NULL); + if (!s) { + r = -ENOMEM; + goto fail; + } + + s->node_object_manager.node = n; + LIST_PREPEND(object_managers, n->object_managers, &s->node_object_manager); + bus->nodes_modified = true; + + if (slot) + *slot = s; + + return 0; + +fail: + sd_bus_slot_unref(s); + bus_node_gc(bus, n); + + return r; +} diff --git a/src/libsystemd/sd-bus/bus-objects.h b/src/libsystemd/sd-bus/bus-objects.h new file mode 100644 index 00000000..f650196a --- /dev/null +++ b/src/libsystemd/sd-bus/bus-objects.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "bus-internal.h" +#include "bus-introspect.h" + +const sd_bus_vtable* bus_vtable_next(const sd_bus_vtable *vtable, const sd_bus_vtable *v); +bool bus_vtable_has_names(const sd_bus_vtable *vtable); +int bus_process_object(sd_bus *bus, sd_bus_message *m); +void bus_node_gc(sd_bus *b, struct node *n); + +int introspect_path( + sd_bus *bus, + const char *path, + struct node *n, + bool require_fallback, + bool ignore_nodes_modified, + bool *found_object, + char **ret, + sd_bus_error *error); diff --git a/src/libsystemd/sd-bus/bus-protocol.h b/src/libsystemd/sd-bus/bus-protocol.h new file mode 100644 index 00000000..d01fd8e6 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-protocol.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +/* Packet header */ + +struct _packed_ bus_header { + /* The first four fields are identical for dbus1, and dbus2 */ + uint8_t endian; + uint8_t type; + uint8_t flags; + uint8_t version; + + union _packed_ { + /* dbus1: Used for SOCK_STREAM connections */ + struct _packed_ { + uint32_t body_size; + + /* Note that what the bus spec calls "serial" we'll call + "cookie" instead, because we don't want to imply that the + cookie was in any way monotonically increasing. */ + uint32_t serial; + uint32_t fields_size; + } dbus1; + + /* dbus2: Used for kdbus connections */ + struct _packed_ { + uint32_t _reserved; + uint64_t cookie; + } dbus2; + + /* Note that both header versions have the same size! */ + }; +}; + +/* Endianness */ + +enum { + _BUS_INVALID_ENDIAN = 0, + BUS_LITTLE_ENDIAN = 'l', + BUS_BIG_ENDIAN = 'B', +#if __BYTE_ORDER == __BIG_ENDIAN + BUS_NATIVE_ENDIAN = BUS_BIG_ENDIAN, + BUS_REVERSE_ENDIAN = BUS_LITTLE_ENDIAN +#else + BUS_NATIVE_ENDIAN = BUS_LITTLE_ENDIAN, + BUS_REVERSE_ENDIAN = BUS_BIG_ENDIAN +#endif +}; + +/* Flags */ + +enum { + BUS_MESSAGE_NO_REPLY_EXPECTED = 1 << 0, + BUS_MESSAGE_NO_AUTO_START = 1 << 1, + BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION = 1 << 2, +}; + +/* Header fields */ + +enum { + _BUS_MESSAGE_HEADER_INVALID = 0, + BUS_MESSAGE_HEADER_PATH, + BUS_MESSAGE_HEADER_INTERFACE, + BUS_MESSAGE_HEADER_MEMBER, + BUS_MESSAGE_HEADER_ERROR_NAME, + BUS_MESSAGE_HEADER_REPLY_SERIAL, + BUS_MESSAGE_HEADER_DESTINATION, + BUS_MESSAGE_HEADER_SENDER, + BUS_MESSAGE_HEADER_SIGNATURE, + BUS_MESSAGE_HEADER_UNIX_FDS, + _BUS_MESSAGE_HEADER_MAX +}; + +/* RequestName parameters */ + +enum { + BUS_NAME_ALLOW_REPLACEMENT = 1 << 0, + BUS_NAME_REPLACE_EXISTING = 1 << 1, + BUS_NAME_DO_NOT_QUEUE = 1 << 2, +}; + +/* RequestName returns */ +enum { + BUS_NAME_PRIMARY_OWNER = 1, + BUS_NAME_IN_QUEUE = 2, + BUS_NAME_EXISTS = 3, + BUS_NAME_ALREADY_OWNER = 4 +}; + +/* ReleaseName returns */ +enum { + BUS_NAME_RELEASED = 1, + BUS_NAME_NON_EXISTENT = 2, + BUS_NAME_NOT_OWNER = 3, +}; + +/* StartServiceByName returns */ +enum { + BUS_START_REPLY_SUCCESS = 1, + BUS_START_REPLY_ALREADY_RUNNING = 2, +}; + +#define BUS_INTROSPECT_DOCTYPE \ + "\n" + +#define BUS_INTROSPECT_INTERFACE_PEER \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" + +#define BUS_INTROSPECT_INTERFACE_INTROSPECTABLE \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" + +#define BUS_INTROSPECT_INTERFACE_PROPERTIES \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" + +#define BUS_INTROSPECT_INTERFACE_OBJECT_MANAGER \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" diff --git a/src/libsystemd/sd-bus/bus-signature.c b/src/libsystemd/sd-bus/bus-signature.c new file mode 100644 index 00000000..b420ba36 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-signature.c @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-bus.h" + +#include "bus-signature.h" +#include "bus-type.h" + +static int signature_element_length_internal( + const char *s, + bool allow_dict_entry, + unsigned array_depth, + unsigned struct_depth, + size_t *l) { + + int r; + + if (!s) + return -EINVAL; + + assert(l); + + if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) { + *l = 1; + return 0; + } + + if (*s == SD_BUS_TYPE_ARRAY) { + size_t t; + + if (array_depth >= 32) + return -EINVAL; + + r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t); + if (r < 0) + return r; + + *l = t + 1; + return 0; + } + + if (*s == SD_BUS_TYPE_STRUCT_BEGIN) { + const char *p = s + 1; + + if (struct_depth >= 32) + return -EINVAL; + + while (*p != SD_BUS_TYPE_STRUCT_END) { + size_t t; + + r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t); + if (r < 0) + return r; + + p += t; + } + + if (p - s < 2) + /* D-Bus spec: Empty structures are not allowed; there + * must be at least one type code between the parentheses. + */ + return -EINVAL; + + *l = p - s + 1; + return 0; + } + + if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) { + const char *p = s + 1; + unsigned n = 0; + + if (struct_depth >= 32) + return -EINVAL; + + while (*p != SD_BUS_TYPE_DICT_ENTRY_END) { + size_t t; + + if (n == 0 && !bus_type_is_basic(*p)) + return -EINVAL; + + r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t); + if (r < 0) + return r; + + p += t; + n++; + } + + if (n != 2) + return -EINVAL; + + *l = p - s + 1; + return 0; + } + + return -EINVAL; +} + +int signature_element_length(const char *s, size_t *l) { + return signature_element_length_internal(s, true, 0, 0, l); +} + +bool signature_is_single(const char *s, bool allow_dict_entry) { + int r; + size_t t; + + if (!s) + return false; + + r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t); + if (r < 0) + return false; + + return s[t] == 0; +} + +bool signature_is_pair(const char *s) { + + if (!s) + return false; + + if (!bus_type_is_basic(*s)) + return false; + + return signature_is_single(s + 1, false); +} + +bool signature_is_valid(const char *s, bool allow_dict_entry) { + const char *p; + int r; + + if (!s) + return false; + + p = s; + while (*p) { + size_t t; + + r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t); + if (r < 0) + return false; + + p += t; + } + + return p - s <= SD_BUS_MAXIMUM_SIGNATURE_LENGTH; +} diff --git a/src/libsystemd/sd-bus/bus-signature.h b/src/libsystemd/sd-bus/bus-signature.h new file mode 100644 index 00000000..b87bec83 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-signature.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +bool signature_is_single(const char *s, bool allow_dict_entry); +bool signature_is_pair(const char *s); +bool signature_is_valid(const char *s, bool allow_dict_entry); + +int signature_element_length(const char *s, size_t *l); diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c new file mode 100644 index 00000000..f90a7f05 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-slot.c @@ -0,0 +1,311 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-control.h" +#include "bus-objects.h" +#include "bus-slot.h" +#include "string-util.h" + +sd_bus_slot *bus_slot_allocate( + sd_bus *bus, + bool floating, + BusSlotType type, + size_t extra, + void *userdata) { + + sd_bus_slot *slot; + + assert(bus); + + slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra); + if (!slot) + return NULL; + + slot->n_ref = 1; + slot->type = type; + slot->bus = bus; + slot->floating = floating; + slot->userdata = userdata; + + if (!floating) + sd_bus_ref(bus); + + LIST_PREPEND(slots, bus->slots, slot); + + return slot; +} + +void bus_slot_disconnect(sd_bus_slot *slot, bool unref) { + sd_bus *bus; + + assert(slot); + + if (!slot->bus) + return; + + switch (slot->type) { + + case BUS_REPLY_CALLBACK: + + if (slot->reply_callback.cookie != 0) + ordered_hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie); + + if (slot->reply_callback.timeout_usec != 0) + prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx); + + break; + + case BUS_FILTER_CALLBACK: + slot->bus->filter_callbacks_modified = true; + LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback); + break; + + case BUS_MATCH_CALLBACK: + + if (slot->match_added) + (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string); + + if (slot->match_callback.install_slot) { + bus_slot_disconnect(slot->match_callback.install_slot, true); + slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot); + } + + slot->bus->match_callbacks_modified = true; + bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback); + + slot->match_callback.match_string = mfree(slot->match_callback.match_string); + + break; + + case BUS_NODE_CALLBACK: + + if (slot->node_callback.node) { + LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback); + slot->bus->nodes_modified = true; + + bus_node_gc(slot->bus, slot->node_callback.node); + } + + break; + + case BUS_NODE_ENUMERATOR: + + if (slot->node_enumerator.node) { + LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator); + slot->bus->nodes_modified = true; + + bus_node_gc(slot->bus, slot->node_enumerator.node); + } + + break; + + case BUS_NODE_OBJECT_MANAGER: + + if (slot->node_object_manager.node) { + LIST_REMOVE(object_managers, slot->node_object_manager.node->object_managers, &slot->node_object_manager); + slot->bus->nodes_modified = true; + + bus_node_gc(slot->bus, slot->node_object_manager.node); + } + + break; + + case BUS_NODE_VTABLE: + + if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) { + const sd_bus_vtable *v; + + for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v = bus_vtable_next(slot->node_vtable.vtable, v)) { + struct vtable_member *x = NULL; + + switch (v->type) { + + case _SD_BUS_VTABLE_METHOD: { + struct vtable_member key; + + key.path = slot->node_vtable.node->path; + key.interface = slot->node_vtable.interface; + key.member = v->x.method.member; + + x = hashmap_remove(slot->bus->vtable_methods, &key); + break; + } + + case _SD_BUS_VTABLE_PROPERTY: + case _SD_BUS_VTABLE_WRITABLE_PROPERTY: { + struct vtable_member key; + + key.path = slot->node_vtable.node->path; + key.interface = slot->node_vtable.interface; + key.member = v->x.method.member; + + x = hashmap_remove(slot->bus->vtable_properties, &key); + break; + }} + + free(x); + } + } + + slot->node_vtable.interface = mfree(slot->node_vtable.interface); + + if (slot->node_vtable.node) { + LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable); + slot->bus->nodes_modified = true; + + bus_node_gc(slot->bus, slot->node_vtable.node); + } + + break; + + default: + assert_not_reached("Wut? Unknown slot type?"); + } + + bus = slot->bus; + + slot->type = _BUS_SLOT_INVALID; + slot->bus = NULL; + LIST_REMOVE(slots, bus->slots, slot); + + if (!slot->floating) + sd_bus_unref(bus); + else if (unref) + sd_bus_slot_unref(slot); +} + +static sd_bus_slot* bus_slot_free(sd_bus_slot *slot) { + assert(slot); + + bus_slot_disconnect(slot, false); + + if (slot->destroy_callback) + slot->destroy_callback(slot->userdata); + + free(slot->description); + return mfree(slot); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_slot, sd_bus_slot, bus_slot_free); + +_public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) { + assert_return(slot, NULL); + + return slot->bus; +} + +_public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) { + assert_return(slot, NULL); + + return slot->userdata; +} + +_public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) { + void *ret; + + assert_return(slot, NULL); + + ret = slot->userdata; + slot->userdata = userdata; + + return ret; +} + +_public_ int sd_bus_slot_set_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t callback) { + assert_return(slot, -EINVAL); + + slot->destroy_callback = callback; + return 0; +} + +_public_ int sd_bus_slot_get_destroy_callback(sd_bus_slot *slot, sd_bus_destroy_t *callback) { + assert_return(slot, -EINVAL); + + if (callback) + *callback = slot->destroy_callback; + + return !!slot->destroy_callback; +} + +_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) { + assert_return(slot, NULL); + assert_return(slot->type >= 0, NULL); + + if (slot->bus->current_slot != slot) + return NULL; + + return slot->bus->current_message; +} + +_public_ sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *slot) { + assert_return(slot, NULL); + assert_return(slot->type >= 0, NULL); + + if (slot->bus->current_slot != slot) + return NULL; + + return slot->bus->current_handler; +} + +_public_ void* sd_bus_slot_get_current_userdata(sd_bus_slot *slot) { + assert_return(slot, NULL); + assert_return(slot->type >= 0, NULL); + + if (slot->bus->current_slot != slot) + return NULL; + + return slot->bus->current_userdata; +} + +_public_ int sd_bus_slot_get_floating(sd_bus_slot *slot) { + assert_return(slot, -EINVAL); + + return slot->floating; +} + +_public_ int sd_bus_slot_set_floating(sd_bus_slot *slot, int b) { + assert_return(slot, -EINVAL); + + if (slot->floating == !!b) + return 0; + + if (!slot->bus) /* already disconnected slots can't be reconnected */ + return -ESTALE; + + slot->floating = b; + + /* When a slot is "floating" then the bus references the slot. Otherwise the slot references the bus. Hence, + * when we move from one to the other, let's increase one reference and decrease the other. */ + + if (b) { + sd_bus_slot_ref(slot); + sd_bus_unref(slot->bus); + } else { + sd_bus_ref(slot->bus); + sd_bus_slot_unref(slot); + } + + return 1; +} + +_public_ int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description) { + assert_return(slot, -EINVAL); + + return free_and_strdup(&slot->description, description); +} + +_public_ int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description) { + assert_return(slot, -EINVAL); + assert_return(description, -EINVAL); + + if (slot->description) + *description = slot->description; + else if (slot->type == BUS_MATCH_CALLBACK) + *description = slot->match_callback.match_string; + else + return -ENXIO; + + return 0; +} diff --git a/src/libsystemd/sd-bus/bus-slot.h b/src/libsystemd/sd-bus/bus-slot.h new file mode 100644 index 00000000..48eb0453 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-slot.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "bus-internal.h" + +sd_bus_slot *bus_slot_allocate(sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata); + +void bus_slot_disconnect(sd_bus_slot *slot, bool unref); diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c new file mode 100644 index 00000000..18d30d01 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -0,0 +1,1329 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-socket.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "hexdecoct.h" +#include "io-util.h" +#include "macro.h" +#include "memory-util.h" +#include "path-util.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "user-util.h" +#include "utf8.h" + +#define SNDBUF_SIZE (8*1024*1024) + +static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) { + + while (size > 0) { + struct iovec *i = iov + *idx; + + if (i->iov_len > size) { + i->iov_base = (uint8_t*) i->iov_base + size; + i->iov_len -= size; + return; + } + + size -= i->iov_len; + + *i = IOVEC_MAKE(NULL, 0); + + (*idx)++; + } +} + +static int append_iovec(sd_bus_message *m, const void *p, size_t sz) { + assert(m); + assert(p); + assert(sz > 0); + + m->iovec[m->n_iovec++] = IOVEC_MAKE((void*) p, sz); + + return 0; +} + +static int bus_message_setup_iovec(sd_bus_message *m) { + struct bus_body_part *part; + unsigned n, i; + int r; + + assert(m); + assert(m->sealed); + + if (m->n_iovec > 0) + return 0; + + assert(!m->iovec); + + n = 1 + m->n_body_parts; + if (n < ELEMENTSOF(m->iovec_fixed)) + m->iovec = m->iovec_fixed; + else { + m->iovec = new(struct iovec, n); + if (!m->iovec) { + r = -ENOMEM; + goto fail; + } + } + + r = append_iovec(m, m->header, BUS_MESSAGE_BODY_BEGIN(m)); + if (r < 0) + goto fail; + + MESSAGE_FOREACH_PART(part, i, m) { + r = bus_body_part_map(part); + if (r < 0) + goto fail; + + r = append_iovec(m, part->data, part->size); + if (r < 0) + goto fail; + } + + assert(n == m->n_iovec); + + return 0; + +fail: + m->poisoned = true; + return r; +} + +bool bus_socket_auth_needs_write(sd_bus *b) { + + unsigned i; + + if (b->auth_index >= ELEMENTSOF(b->auth_iovec)) + return false; + + for (i = b->auth_index; i < ELEMENTSOF(b->auth_iovec); i++) { + struct iovec *j = b->auth_iovec + i; + + if (j->iov_len > 0) + return true; + } + + return false; +} + +static int bus_socket_write_auth(sd_bus *b) { + ssize_t k; + + assert(b); + assert(b->state == BUS_AUTHENTICATING); + + if (!bus_socket_auth_needs_write(b)) + return 0; + + if (b->prefer_writev) + k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index); + else { + struct msghdr mh; + zero(mh); + + mh.msg_iov = b->auth_iovec + b->auth_index; + mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index; + + k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL); + if (k < 0 && errno == ENOTSOCK) { + b->prefer_writev = true; + k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index); + } + } + + if (k < 0) + return errno == EAGAIN ? 0 : -errno; + + iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k); + return 1; +} + +static int bus_socket_auth_verify_client(sd_bus *b) { + char *d, *e, *f, *start; + sd_id128_t peer; + int r; + + assert(b); + + /* + * We expect three response lines: + * "DATA\r\n" + * "OK \r\n" + * "AGREE_UNIX_FD\r\n" (optional) + */ + + d = memmem_safe(b->rbuffer, b->rbuffer_size, "\r\n", 2); + if (!d) + return 0; + + e = memmem(d + 2, b->rbuffer_size - (d - (char*) b->rbuffer) - 2, "\r\n", 2); + if (!e) + return 0; + + if (b->accept_fd) { + f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2); + if (!f) + return 0; + + start = f + 2; + } else { + f = NULL; + start = e + 2; + } + + /* Nice! We got all the lines we need. First check the DATA line. */ + + if (d - (char*) b->rbuffer == 4) { + if (memcmp(b->rbuffer, "DATA", 4)) + return -EPERM; + } else if (d - (char*) b->rbuffer == 3 + 32) { + /* + * Old versions of the server-side implementation of `sd-bus` replied with "OK " to + * "AUTH" requests from a client, even if the "AUTH" line did not contain inlined + * arguments. Therefore, we also accept "OK " here, even though it is technically the + * wrong reply. We ignore the "" parameter, though, since it has no real value. + */ + if (memcmp(b->rbuffer, "OK ", 3)) + return -EPERM; + } else + return -EPERM; + + /* Now check the OK line. */ + + if (e - d != 2 + 3 + 32) + return -EPERM; + + if (memcmp(d + 2, "OK ", 3)) + return -EPERM; + + b->auth = b->anonymous_auth ? BUS_AUTH_ANONYMOUS : BUS_AUTH_EXTERNAL; + + for (unsigned i = 0; i < 32; i += 2) { + int x, y; + + x = unhexchar(d[2 + 3 + i]); + y = unhexchar(d[2 + 3 + i + 1]); + + if (x < 0 || y < 0) + return -EINVAL; + + peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y); + } + + if (!sd_id128_is_null(b->server_id) && + !sd_id128_equal(b->server_id, peer)) + return -EPERM; + + b->server_id = peer; + + /* And possibly check the third line, too */ + + if (f) + b->can_fds = + (f - e == STRLEN("\r\nAGREE_UNIX_FD")) && + memcmp(e + 2, "AGREE_UNIX_FD", + STRLEN("AGREE_UNIX_FD")) == 0; + + b->rbuffer_size -= (start - (char*) b->rbuffer); + memmove(b->rbuffer, start, b->rbuffer_size); + + r = bus_start_running(b); + if (r < 0) + return r; + + return 1; +} + +static bool line_equals(const char *s, size_t m, const char *line) { + size_t l; + + l = strlen(line); + if (l != m) + return false; + + return memcmp(s, line, l) == 0; +} + +static bool line_begins(const char *s, size_t m, const char *word) { + const char *p; + + p = memory_startswith(s, m, word); + return p && (p == (s + m) || *p == ' '); +} + +static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) { + _cleanup_free_ char *token = NULL; + size_t len; + int r; + + if (!b->anonymous_auth) + return 0; + + if (l <= 0) + return 1; + + assert(p[0] == ' '); + p++; l--; + + if (l % 2 != 0) + return 0; + + r = unhexmem(p, l, (void **) &token, &len); + if (r < 0) + return 0; + + if (memchr(token, 0, len)) + return 0; + + return !!utf8_is_valid(token); +} + +static int verify_external_token(sd_bus *b, const char *p, size_t l) { + _cleanup_free_ char *token = NULL; + size_t len; + uid_t u; + int r; + + /* We don't do any real authentication here. Instead, we if + * the owner of this bus wanted authentication he should have + * checked SO_PEERCRED before even creating the bus object. */ + + if (!b->anonymous_auth && !b->ucred_valid) + return 0; + + if (l <= 0) + return 1; + + assert(p[0] == ' '); + p++; l--; + + if (l % 2 != 0) + return 0; + + r = unhexmem(p, l, (void**) &token, &len); + if (r < 0) + return 0; + + if (memchr(token, 0, len)) + return 0; + + r = parse_uid(token, &u); + if (r < 0) + return 0; + + /* We ignore the passed value if anonymous authentication is + * on anyway. */ + if (!b->anonymous_auth && u != b->ucred.uid) + return 0; + + return 1; +} + +static int bus_socket_auth_write(sd_bus *b, const char *t) { + char *p; + size_t l; + + assert(b); + assert(t); + + /* We only make use of the first iovec */ + assert(IN_SET(b->auth_index, 0, 1)); + + l = strlen(t); + p = malloc(b->auth_iovec[0].iov_len + l); + if (!p) + return -ENOMEM; + + memcpy_safe(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len); + memcpy(p + b->auth_iovec[0].iov_len, t, l); + + b->auth_iovec[0].iov_base = p; + b->auth_iovec[0].iov_len += l; + + free(b->auth_buffer); + b->auth_buffer = p; + b->auth_index = 0; + return 0; +} + +static int bus_socket_auth_write_ok(sd_bus *b) { + char t[3 + 32 + 2 + 1]; + + assert(b); + + xsprintf(t, "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id)); + + return bus_socket_auth_write(b, t); +} + +static int bus_socket_auth_verify_server(sd_bus *b) { + char *e; + const char *line; + size_t l; + bool processed = false; + int r; + + assert(b); + + if (b->rbuffer_size < 1) + return 0; + + /* First char must be a NUL byte */ + if (*(char*) b->rbuffer != 0) + return -EIO; + + if (b->rbuffer_size < 3) + return 0; + + /* Begin with the first line */ + if (b->auth_rbegin <= 0) + b->auth_rbegin = 1; + + for (;;) { + /* Check if line is complete */ + line = (char*) b->rbuffer + b->auth_rbegin; + e = memmem(line, b->rbuffer_size - b->auth_rbegin, "\r\n", 2); + if (!e) + return processed; + + l = e - line; + + if (line_begins(line, l, "AUTH ANONYMOUS")) { + + r = verify_anonymous_token(b, + line + strlen("AUTH ANONYMOUS"), + l - strlen("AUTH ANONYMOUS")); + if (r < 0) + return r; + if (r == 0) + r = bus_socket_auth_write(b, "REJECTED\r\n"); + else { + b->auth = BUS_AUTH_ANONYMOUS; + if (l <= strlen("AUTH ANONYMOUS")) + r = bus_socket_auth_write(b, "DATA\r\n"); + else + r = bus_socket_auth_write_ok(b); + } + + } else if (line_begins(line, l, "AUTH EXTERNAL")) { + + r = verify_external_token(b, + line + strlen("AUTH EXTERNAL"), + l - strlen("AUTH EXTERNAL")); + if (r < 0) + return r; + if (r == 0) + r = bus_socket_auth_write(b, "REJECTED\r\n"); + else { + b->auth = BUS_AUTH_EXTERNAL; + if (l <= strlen("AUTH EXTERNAL")) + r = bus_socket_auth_write(b, "DATA\r\n"); + else + r = bus_socket_auth_write_ok(b); + } + + } else if (line_begins(line, l, "AUTH")) + r = bus_socket_auth_write(b, "REJECTED EXTERNAL ANONYMOUS\r\n"); + else if (line_equals(line, l, "CANCEL") || + line_begins(line, l, "ERROR")) { + + b->auth = _BUS_AUTH_INVALID; + r = bus_socket_auth_write(b, "REJECTED\r\n"); + + } else if (line_equals(line, l, "BEGIN")) { + + if (b->auth == _BUS_AUTH_INVALID) + r = bus_socket_auth_write(b, "ERROR\r\n"); + else { + /* We can't leave from the auth phase + * before we haven't written + * everything queued, so let's check + * that */ + + if (bus_socket_auth_needs_write(b)) + return 1; + + b->rbuffer_size -= (e + 2 - (char*) b->rbuffer); + memmove(b->rbuffer, e + 2, b->rbuffer_size); + return bus_start_running(b); + } + + } else if (line_begins(line, l, "DATA")) { + + if (b->auth == _BUS_AUTH_INVALID) + r = bus_socket_auth_write(b, "ERROR\r\n"); + else { + if (b->auth == BUS_AUTH_ANONYMOUS) + r = verify_anonymous_token(b, line + 4, l - 4); + else + r = verify_external_token(b, line + 4, l - 4); + + if (r < 0) + return r; + if (r == 0) { + b->auth = _BUS_AUTH_INVALID; + r = bus_socket_auth_write(b, "REJECTED\r\n"); + } else + r = bus_socket_auth_write_ok(b); + } + } else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) { + if (b->auth == _BUS_AUTH_INVALID || !b->accept_fd) + r = bus_socket_auth_write(b, "ERROR\r\n"); + else { + b->can_fds = true; + r = bus_socket_auth_write(b, "AGREE_UNIX_FD\r\n"); + } + } else + r = bus_socket_auth_write(b, "ERROR\r\n"); + + if (r < 0) + return r; + + b->auth_rbegin = e + 2 - (char*) b->rbuffer; + + processed = true; + } +} + +static int bus_socket_auth_verify(sd_bus *b) { + assert(b); + + if (b->is_server) + return bus_socket_auth_verify_server(b); + else + return bus_socket_auth_verify_client(b); +} + +static int bus_socket_read_auth(sd_bus *b) { + struct msghdr mh; + struct iovec iov = {}; + size_t n; + ssize_t k; + int r; + void *p; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)]; + } control; + bool handle_cmsg = false; + + assert(b); + assert(b->state == BUS_AUTHENTICATING); + + r = bus_socket_auth_verify(b); + if (r != 0) + return r; + + n = MAX(256u, b->rbuffer_size * 2); + + if (n > BUS_AUTH_SIZE_MAX) + n = BUS_AUTH_SIZE_MAX; + + if (b->rbuffer_size >= n) + return -ENOBUFS; + + p = realloc(b->rbuffer, n); + if (!p) + return -ENOMEM; + + b->rbuffer = p; + + iov = IOVEC_MAKE((uint8_t *)b->rbuffer + b->rbuffer_size, n - b->rbuffer_size); + + if (b->prefer_readv) + k = readv(b->input_fd, &iov, 1); + else { + zero(mh); + mh.msg_iov = &iov; + mh.msg_iovlen = 1; + mh.msg_control = &control; + mh.msg_controllen = sizeof(control); + + k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (k < 0 && errno == ENOTSOCK) { + b->prefer_readv = true; + k = readv(b->input_fd, &iov, 1); + } else + handle_cmsg = true; + } + if (k < 0) + return errno == EAGAIN ? 0 : -errno; + if (k == 0) + return -ECONNRESET; + + b->rbuffer_size += k; + + if (handle_cmsg) { + struct cmsghdr *cmsg; + + CMSG_FOREACH(cmsg, &mh) + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) { + int j; + + /* Whut? We received fds during the auth + * protocol? Somebody is playing games with + * us. Close them all, and fail */ + j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); + close_many((int*) CMSG_DATA(cmsg), j); + return -EIO; + } else + log_debug("Got unexpected auxiliary data with level=%d and type=%d", + cmsg->cmsg_level, cmsg->cmsg_type); + } + + r = bus_socket_auth_verify(b); + if (r != 0) + return r; + + return 1; +} + +void bus_socket_setup(sd_bus *b) { + assert(b); + + /* Increase the buffers to 8 MB */ + (void) fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE); + (void) fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE); + + b->message_version = 1; + b->message_endian = 0; +} + +static void bus_get_peercred(sd_bus *b) { + int r; + + assert(b); + assert(!b->ucred_valid); + assert(!b->label); + assert(b->n_groups == (size_t) -1); + + /* Get the peer for socketpair() sockets */ + b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0; + + /* Get the SELinux context of the peer */ + r = getpeersec(b->input_fd, &b->label); + if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT)) + log_debug_errno(r, "Failed to determine peer security context: %m"); + + /* Get the list of auxiliary groups of the peer */ + r = getpeergroups(b->input_fd, &b->groups); + if (r >= 0) + b->n_groups = (size_t) r; + else if (!IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT)) + log_debug_errno(r, "Failed to determine peer's group list: %m"); +} + +static int bus_socket_start_auth_client(sd_bus *b) { + static const char sasl_auth_anonymous[] = { + /* + * We use an arbitrary trace-string for the ANONYMOUS authentication. It can be used by the + * message broker to aid debugging of clients. We fully anonymize the connection and use a + * static default. + */ + "\0AUTH ANONYMOUS\r\n" + /* HEX a n o n y m o u s */ + "DATA 616e6f6e796d6f7573\r\n" + }; + static const char sasl_auth_external[] = { + "\0AUTH EXTERNAL\r\n" + "DATA\r\n" + }; + static const char sasl_negotiate_unix_fd[] = { + "NEGOTIATE_UNIX_FD\r\n" + }; + static const char sasl_begin[] = { + "BEGIN\r\n" + }; + size_t i = 0; + + assert(b); + + if (b->anonymous_auth) + b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_anonymous, sizeof(sasl_auth_anonymous) - 1); + else + b->auth_iovec[i++] = IOVEC_MAKE((char*) sasl_auth_external, sizeof(sasl_auth_external) - 1); + + if (b->accept_fd) + b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_negotiate_unix_fd); + + b->auth_iovec[i++] = IOVEC_MAKE_STRING(sasl_begin); + + return bus_socket_write_auth(b); +} + +int bus_socket_start_auth(sd_bus *b) { + assert(b); + + bus_get_peercred(b); + + bus_set_state(b, BUS_AUTHENTICATING); + b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_AUTH_TIMEOUT; + + if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0) + b->accept_fd = false; + + if (b->output_fd != b->input_fd) + if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0) + b->accept_fd = false; + + if (b->is_server) + return bus_socket_read_auth(b); + else + return bus_socket_start_auth_client(b); +} + +static int bus_socket_inotify_setup(sd_bus *b) { + _cleanup_free_ int *new_watches = NULL; + _cleanup_free_ char *absolute = NULL; + size_t n_allocated = 0, n = 0, done = 0, i; + unsigned max_follow = 32; + const char *p; + int wd, r; + + assert(b); + assert(b->watch_bind); + assert(b->sockaddr.sa.sa_family == AF_UNIX); + assert(b->sockaddr.un.sun_path[0] != 0); + + /* Sets up an inotify fd in case watch_bind is enabled: wait until the configured AF_UNIX file system socket + * appears before connecting to it. The implemented is pretty simplistic: we just subscribe to relevant changes + * to all prefix components of the path, and every time we get an event for that we try to reconnect again, + * without actually caring what precisely the event we got told us. If we still can't connect we re-subscribe + * to all relevant changes of anything in the path, so that our watches include any possibly newly created path + * components. */ + + if (b->inotify_fd < 0) { + b->inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (b->inotify_fd < 0) + return -errno; + + b->inotify_fd = fd_move_above_stdio(b->inotify_fd); + } + + /* Make sure the path is NUL terminated */ + p = strndupa(b->sockaddr.un.sun_path, sizeof(b->sockaddr.un.sun_path)); + + /* Make sure the path is absolute */ + r = path_make_absolute_cwd(p, &absolute); + if (r < 0) + goto fail; + + /* Watch all parent directories, and don't mind any prefix that doesn't exist yet. For the innermost directory + * that exists we want to know when files are created or moved into it. For all parents of it we just care if + * they are removed or renamed. */ + + if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) { + r = -ENOMEM; + goto fail; + } + + /* Start with the top-level directory, which is a bit simpler than the rest, since it can't be a symlink, and + * always exists */ + wd = inotify_add_watch(b->inotify_fd, "/", IN_CREATE|IN_MOVED_TO); + if (wd < 0) { + r = log_debug_errno(errno, "Failed to add inotify watch on /: %m"); + goto fail; + } else + new_watches[n++] = wd; + + for (;;) { + _cleanup_free_ char *component = NULL, *prefix = NULL, *destination = NULL; + size_t n_slashes, n_component; + char *c = NULL; + + n_slashes = strspn(absolute + done, "/"); + n_component = n_slashes + strcspn(absolute + done + n_slashes, "/"); + + if (n_component == 0) /* The end */ + break; + + component = strndup(absolute + done, n_component); + if (!component) { + r = -ENOMEM; + goto fail; + } + + /* A trailing slash? That's a directory, and not a socket then */ + if (path_equal(component, "/")) { + r = -EISDIR; + goto fail; + } + + /* A single dot? Let's eat this up */ + if (path_equal(component, "/.")) { + done += n_component; + continue; + } + + prefix = strndup(absolute, done + n_component); + if (!prefix) { + r = -ENOMEM; + goto fail; + } + + if (!GREEDY_REALLOC(new_watches, n_allocated, n + 1)) { + r = -ENOMEM; + goto fail; + } + + wd = inotify_add_watch(b->inotify_fd, prefix, IN_DELETE_SELF|IN_MOVE_SELF|IN_ATTRIB|IN_CREATE|IN_MOVED_TO|IN_DONT_FOLLOW); + log_debug("Added inotify watch for %s on bus %s: %i", prefix, strna(b->description), wd); + + if (wd < 0) { + if (IN_SET(errno, ENOENT, ELOOP)) + break; /* This component doesn't exist yet, or the path contains a cyclic symlink right now */ + + r = log_debug_errno(errno, "Failed to add inotify watch on %s: %m", empty_to_root(prefix)); + goto fail; + } else + new_watches[n++] = wd; + + /* Check if this is possibly a symlink. If so, let's follow it and watch it too. */ + r = readlink_malloc(prefix, &destination); + if (r == -EINVAL) { /* not a symlink */ + done += n_component; + continue; + } + if (r < 0) + goto fail; + + if (isempty(destination)) { /* Empty symlink target? Yuck! */ + r = -EINVAL; + goto fail; + } + + if (max_follow <= 0) { /* Let's make sure we don't follow symlinks forever */ + r = -ELOOP; + goto fail; + } + + if (path_is_absolute(destination)) { + /* For absolute symlinks we build the new path and start anew */ + c = strjoin(destination, absolute + done + n_component); + done = 0; + } else { + _cleanup_free_ char *t = NULL; + + /* For relative symlinks we replace the last component, and try again */ + t = strndup(absolute, done); + if (!t) + return -ENOMEM; + + c = strjoin(t, "/", destination, absolute + done + n_component); + } + if (!c) { + r = -ENOMEM; + goto fail; + } + + free(absolute); + absolute = c; + + max_follow--; + } + + /* And now, let's remove all watches from the previous iteration we don't need anymore */ + for (i = 0; i < b->n_inotify_watches; i++) { + bool found = false; + size_t j; + + for (j = 0; j < n; j++) + if (new_watches[j] == b->inotify_watches[i]) { + found = true; + break; + } + + if (found) + continue; + + (void) inotify_rm_watch(b->inotify_fd, b->inotify_watches[i]); + } + + free_and_replace(b->inotify_watches, new_watches); + b->n_inotify_watches = n; + + return 0; + +fail: + bus_close_inotify_fd(b); + return r; +} + +int bus_socket_connect(sd_bus *b) { + bool inotify_done = false; + int r; + + assert(b); + + for (;;) { + assert(b->input_fd < 0); + assert(b->output_fd < 0); + assert(b->sockaddr.sa.sa_family != AF_UNSPEC); + + b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (b->input_fd < 0) + return -errno; + + b->input_fd = fd_move_above_stdio(b->input_fd); + + b->output_fd = b->input_fd; + bus_socket_setup(b); + + if (connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size) < 0) { + if (errno == EINPROGRESS) { + + /* If we have any inotify watches open, close them now, we don't need them anymore, as + * we have successfully initiated a connection */ + bus_close_inotify_fd(b); + + /* Note that very likely we are already in BUS_OPENING state here, as we enter it when + * we start parsing the address string. The only reason we set the state explicitly + * here, is to undo BUS_WATCH_BIND, in case we did the inotify magic. */ + bus_set_state(b, BUS_OPENING); + return 1; + } + + if (IN_SET(errno, ENOENT, ECONNREFUSED) && /* ENOENT → unix socket doesn't exist at all; ECONNREFUSED → unix socket stale */ + b->watch_bind && + b->sockaddr.sa.sa_family == AF_UNIX && + b->sockaddr.un.sun_path[0] != 0) { + + /* This connection attempt failed, let's release the socket for now, and start with a + * fresh one when reconnecting. */ + bus_close_io_fds(b); + + if (inotify_done) { + /* inotify set up already, don't do it again, just return now, and remember + * that we are waiting for inotify events now. */ + bus_set_state(b, BUS_WATCH_BIND); + return 1; + } + + /* This is a file system socket, and the inotify logic is enabled. Let's create the necessary inotify fd. */ + r = bus_socket_inotify_setup(b); + if (r < 0) + return r; + + /* Let's now try to connect a second time, because in theory there's otherwise a race + * here: the socket might have been created in the time between our first connect() and + * the time we set up the inotify logic. But let's remember that we set up inotify now, + * so that we don't do the connect() more than twice. */ + inotify_done = true; + + } else + return -errno; + } else + break; + } + + /* Yay, established, we don't need no inotify anymore! */ + bus_close_inotify_fd(b); + + return bus_socket_start_auth(b); +} + +int bus_socket_exec(sd_bus *b) { + int s[2], r; + + assert(b); + assert(b->input_fd < 0); + assert(b->output_fd < 0); + assert(b->exec_path); + assert(b->busexec_pid == 0); + + r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s); + if (r < 0) + return -errno; + + r = safe_fork_full("(sd-busexec)", s+1, 1, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &b->busexec_pid); + if (r < 0) { + safe_close_pair(s); + return r; + } + if (r == 0) { + /* Child */ + + if (rearrange_stdio(s[1], s[1], STDERR_FILENO) < 0) + _exit(EXIT_FAILURE); + + (void) rlimit_nofile_safe(); + + if (b->exec_argv) + execvp(b->exec_path, b->exec_argv); + else { + const char *argv[] = { b->exec_path, NULL }; + execvp(b->exec_path, (char**) argv); + } + + _exit(EXIT_FAILURE); + } + + safe_close(s[1]); + b->output_fd = b->input_fd = fd_move_above_stdio(s[0]); + + bus_socket_setup(b); + + return bus_socket_start_auth(b); +} + +int bus_socket_take_fd(sd_bus *b) { + assert(b); + + bus_socket_setup(b); + + return bus_socket_start_auth(b); +} + +int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { + struct iovec *iov; + ssize_t k; + size_t n; + unsigned j; + int r; + + assert(bus); + assert(m); + assert(idx); + assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO)); + + if (*idx >= BUS_MESSAGE_SIZE(m)) + return 0; + + r = bus_message_setup_iovec(m); + if (r < 0) + return r; + + n = m->n_iovec * sizeof(struct iovec); + iov = newa(struct iovec, n); + memcpy_safe(iov, m->iovec, n); + + j = 0; + iovec_advance(iov, &j, *idx); + + if (bus->prefer_writev) + k = writev(bus->output_fd, iov, m->n_iovec); + else { + struct msghdr mh = { + .msg_iov = iov, + .msg_iovlen = m->n_iovec, + }; + + if (m->n_fds > 0 && *idx == 0) { + struct cmsghdr *control; + + mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds)); + mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds); + control->cmsg_level = SOL_SOCKET; + control->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds); + } + + k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL); + if (k < 0 && errno == ENOTSOCK) { + bus->prefer_writev = true; + k = writev(bus->output_fd, iov, m->n_iovec); + } + } + + if (k < 0) + return errno == EAGAIN ? 0 : -errno; + + *idx += (size_t) k; + return 1; +} + +static int bus_socket_read_message_need(sd_bus *bus, size_t *need) { + uint32_t a, b; + uint8_t e; + uint64_t sum; + + assert(bus); + assert(need); + assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO)); + + if (bus->rbuffer_size < sizeof(struct bus_header)) { + *need = sizeof(struct bus_header) + 8; + + /* Minimum message size: + * + * Header + + * + * Method Call: +2 string headers + * Signal: +3 string headers + * Method Error: +1 string headers + * +1 uint32 headers + * Method Reply: +1 uint32 headers + * + * A string header is at least 9 bytes + * A uint32 header is at least 8 bytes + * + * Hence the minimum message size of a valid message + * is header + 8 bytes */ + + return 0; + } + + a = ((const uint32_t*) bus->rbuffer)[1]; + b = ((const uint32_t*) bus->rbuffer)[3]; + + e = ((const uint8_t*) bus->rbuffer)[0]; + if (e == BUS_LITTLE_ENDIAN) { + a = le32toh(a); + b = le32toh(b); + } else if (e == BUS_BIG_ENDIAN) { + a = be32toh(a); + b = be32toh(b); + } else + return -EBADMSG; + + sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a; + if (sum >= BUS_MESSAGE_SIZE_MAX) + return -ENOBUFS; + + *need = (size_t) sum; + return 0; +} + +static int bus_socket_make_message(sd_bus *bus, size_t size) { + sd_bus_message *t = NULL; + void *b; + int r; + + assert(bus); + assert(bus->rbuffer_size >= size); + assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO)); + + r = bus_rqueue_make_room(bus); + if (r < 0) + return r; + + if (bus->rbuffer_size > size) { + b = memdup((const uint8_t*) bus->rbuffer + size, + bus->rbuffer_size - size); + if (!b) + return -ENOMEM; + } else + b = NULL; + + r = bus_message_from_malloc(bus, + bus->rbuffer, size, + bus->fds, bus->n_fds, + NULL, + &t); + if (r == -EBADMSG) { + log_debug_errno(r, "Received invalid message from connection %s, dropping.", strna(bus->description)); + free(bus->rbuffer); /* We want to drop current rbuffer and proceed with whatever remains in b */ + } else if (r < 0) { + free(b); + return r; + } + + /* rbuffer ownership was either transferred to t, or we got EBADMSG and dropped it. */ + bus->rbuffer = b; + bus->rbuffer_size -= size; + + bus->fds = NULL; + bus->n_fds = 0; + + if (t) { + t->read_counter = ++bus->read_counter; + bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(t, bus); + sd_bus_message_unref(t); + } + + return 1; +} + +int bus_socket_read_message(sd_bus *bus) { + struct msghdr mh; + struct iovec iov = {}; + ssize_t k; + size_t need; + int r; + void *b; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)]; + } control; + bool handle_cmsg = false; + + assert(bus); + assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO)); + + r = bus_socket_read_message_need(bus, &need); + if (r < 0) + return r; + + if (bus->rbuffer_size >= need) + return bus_socket_make_message(bus, need); + + b = realloc(bus->rbuffer, need); + if (!b) + return -ENOMEM; + + bus->rbuffer = b; + + iov = IOVEC_MAKE((uint8_t *)bus->rbuffer + bus->rbuffer_size, need - bus->rbuffer_size); + + if (bus->prefer_readv) + k = readv(bus->input_fd, &iov, 1); + else { + zero(mh); + mh.msg_iov = &iov; + mh.msg_iovlen = 1; + mh.msg_control = &control; + mh.msg_controllen = sizeof(control); + + k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (k < 0 && errno == ENOTSOCK) { + bus->prefer_readv = true; + k = readv(bus->input_fd, &iov, 1); + } else + handle_cmsg = true; + } + if (k < 0) + return errno == EAGAIN ? 0 : -errno; + if (k == 0) + return -ECONNRESET; + + bus->rbuffer_size += k; + + if (handle_cmsg) { + struct cmsghdr *cmsg; + + CMSG_FOREACH(cmsg, &mh) + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) { + int n, *f, i; + + n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); + + if (!bus->can_fds) { + /* Whut? We received fds but this + * isn't actually enabled? Close them, + * and fail */ + + close_many((int*) CMSG_DATA(cmsg), n); + return -EIO; + } + + f = reallocarray(bus->fds, bus->n_fds + n, sizeof(int)); + if (!f) { + close_many((int*) CMSG_DATA(cmsg), n); + return -ENOMEM; + } + + for (i = 0; i < n; i++) + f[bus->n_fds++] = fd_move_above_stdio(((int*) CMSG_DATA(cmsg))[i]); + bus->fds = f; + } else + log_debug("Got unexpected auxiliary data with level=%d and type=%d", + cmsg->cmsg_level, cmsg->cmsg_type); + } + + r = bus_socket_read_message_need(bus, &need); + if (r < 0) + return r; + + if (bus->rbuffer_size >= need) + return bus_socket_make_message(bus, need); + + return 1; +} + +int bus_socket_process_opening(sd_bus *b) { + int error = 0; + socklen_t slen = sizeof(error); + struct pollfd p = { + .fd = b->output_fd, + .events = POLLOUT, + }; + int r; + + assert(b->state == BUS_OPENING); + + r = poll(&p, 1, 0); + if (r < 0) + return -errno; + + if (!(p.revents & (POLLOUT|POLLERR|POLLHUP))) + return 0; + + r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen); + if (r < 0) + b->last_connect_error = errno; + else if (error != 0) + b->last_connect_error = error; + else if (p.revents & (POLLERR|POLLHUP)) + b->last_connect_error = ECONNREFUSED; + else + return bus_socket_start_auth(b); + + return bus_next_address(b); +} + +int bus_socket_process_authenticating(sd_bus *b) { + int r; + + assert(b); + assert(b->state == BUS_AUTHENTICATING); + + if (now(CLOCK_MONOTONIC) >= b->auth_timeout) + return -ETIMEDOUT; + + r = bus_socket_write_auth(b); + if (r != 0) + return r; + + return bus_socket_read_auth(b); +} + +int bus_socket_process_watch_bind(sd_bus *b) { + int r, q; + + assert(b); + assert(b->state == BUS_WATCH_BIND); + assert(b->inotify_fd >= 0); + + r = flush_fd(b->inotify_fd); + if (r <= 0) + return r; + + log_debug("Got inotify event on bus %s.", strna(b->description)); + + /* We flushed events out of the inotify fd. In that case, maybe the socket is valid now? Let's try to connect + * to it again */ + + r = bus_socket_connect(b); + if (r < 0) + return r; + + q = bus_attach_io_events(b); + if (q < 0) + return q; + + q = bus_attach_inotify_event(b); + if (q < 0) + return q; + + return r; +} diff --git a/src/libsystemd/sd-bus/bus-socket.h b/src/libsystemd/sd-bus/bus-socket.h new file mode 100644 index 00000000..f8d24556 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-socket.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +void bus_socket_setup(sd_bus *b); + +int bus_socket_connect(sd_bus *b); +int bus_socket_exec(sd_bus *b); +int bus_socket_take_fd(sd_bus *b); +int bus_socket_start_auth(sd_bus *b); + +int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx); +int bus_socket_read_message(sd_bus *bus); + +int bus_socket_process_opening(sd_bus *b); +int bus_socket_process_authenticating(sd_bus *b); +int bus_socket_process_watch_bind(sd_bus *b); + +bool bus_socket_auth_needs_write(sd_bus *b); diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c new file mode 100644 index 00000000..f6098549 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-track.c @@ -0,0 +1,492 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-internal.h" +#include "bus-track.h" +#include "bus-util.h" + +struct track_item { + unsigned n_ref; + char *name; + sd_bus_slot *slot; +}; + +struct sd_bus_track { + unsigned n_ref; + unsigned n_adding; /* are we in the process of adding a new name? */ + sd_bus *bus; + sd_bus_track_handler_t handler; + void *userdata; + Hashmap *names; + LIST_FIELDS(sd_bus_track, queue); + Iterator iterator; + bool in_list:1; /* In bus->tracks? */ + bool in_queue:1; /* In bus->track_queue? */ + bool modified:1; + bool recursive:1; + sd_bus_destroy_t destroy_callback; + + LIST_FIELDS(sd_bus_track, tracks); +}; + +#define MATCH_FOR_NAME(name) \ + strjoina("type='signal'," \ + "sender='org.freedesktop.DBus'," \ + "path='/org/freedesktop/DBus'," \ + "interface='org.freedesktop.DBus'," \ + "member='NameOwnerChanged'," \ + "arg0='", name, "'") + +static struct track_item* track_item_free(struct track_item *i) { + + if (!i) + return NULL; + + sd_bus_slot_unref(i->slot); + free(i->name); + return mfree(i); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free); +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(track_item_hash_ops, char, string_hash_func, string_compare_func, + struct track_item, track_item_free); + +static void bus_track_add_to_queue(sd_bus_track *track) { + assert(track); + + /* Adds the bus track object to the queue of objects we should dispatch next, subject to a number of + * conditions. */ + + /* Already in the queue? */ + if (track->in_queue) + return; + + /* if we are currently in the process of adding a new name, then let's not enqueue this just yet, let's wait + * until the addition is complete. */ + if (track->n_adding > 0) + return; + + /* still referenced? */ + if (hashmap_size(track->names) > 0) + return; + + /* Nothing to call? */ + if (!track->handler) + return; + + /* Already closed? */ + if (!track->in_list) + return; + + LIST_PREPEND(queue, track->bus->track_queue, track); + track->in_queue = true; +} + +static void bus_track_remove_from_queue(sd_bus_track *track) { + assert(track); + + if (!track->in_queue) + return; + + LIST_REMOVE(queue, track->bus->track_queue, track); + track->in_queue = false; +} + +static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) { + struct track_item *i; + + assert(track); + assert(name); + + i = hashmap_remove(track->names, name); + if (!i) + return 0; + + track_item_free(i); + + bus_track_add_to_queue(track); + + track->modified = true; + return 1; +} + +_public_ int sd_bus_track_new( + sd_bus *bus, + sd_bus_track **track, + sd_bus_track_handler_t handler, + void *userdata) { + + sd_bus_track *t; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(track, -EINVAL); + + if (!bus->bus_client) + return -EINVAL; + + t = new0(sd_bus_track, 1); + if (!t) + return -ENOMEM; + + t->n_ref = 1; + t->handler = handler; + t->userdata = userdata; + t->bus = sd_bus_ref(bus); + + LIST_PREPEND(tracks, bus->tracks, t); + t->in_list = true; + + bus_track_add_to_queue(t); + + *track = t; + return 0; +} + +static sd_bus_track *track_free(sd_bus_track *track) { + assert(track); + + if (track->in_list) + LIST_REMOVE(tracks, track->bus->tracks, track); + + bus_track_remove_from_queue(track); + track->names = hashmap_free(track->names); + track->bus = sd_bus_unref(track->bus); + + if (track->destroy_callback) + track->destroy_callback(track->userdata); + + return mfree(track); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus_track, sd_bus_track, track_free); + +static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + sd_bus_track *track = userdata; + const char *name, *old, *new; + int r; + + assert(message); + assert(track); + + r = sd_bus_message_read(message, "sss", &name, &old, &new); + if (r < 0) + return 0; + + bus_track_remove_name_fully(track, name); + return 0; +} + +_public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { + _cleanup_(track_item_freep) struct track_item *n = NULL; + struct track_item *i; + const char *match; + int r; + + assert_return(track, -EINVAL); + assert_return(service_name_is_valid(name), -EINVAL); + + i = hashmap_get(track->names, name); + if (i) { + if (track->recursive) { + unsigned k = track->n_ref + 1; + + if (k < track->n_ref) /* Check for overflow */ + return -EOVERFLOW; + + track->n_ref = k; + } + + bus_track_remove_from_queue(track); + return 0; + } + + r = hashmap_ensure_allocated(&track->names, &track_item_hash_ops); + if (r < 0) + return r; + + n = new0(struct track_item, 1); + if (!n) + return -ENOMEM; + n->name = strdup(name); + if (!n->name) + return -ENOMEM; + + /* First, subscribe to this name */ + match = MATCH_FOR_NAME(name); + + bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */ + + r = sd_bus_add_match_async(track->bus, &n->slot, match, on_name_owner_changed, NULL, track); + if (r < 0) { + bus_track_add_to_queue(track); + return r; + } + + r = hashmap_put(track->names, n->name, n); + if (r < 0) { + bus_track_add_to_queue(track); + return r; + } + + /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */ + track->n_adding++; /* again, make sure this isn't dispatch while we are working in it */ + r = sd_bus_get_name_creds(track->bus, name, 0, NULL); + track->n_adding--; + if (r < 0) { + hashmap_remove(track->names, name); + bus_track_add_to_queue(track); + return r; + } + + n->n_ref = 1; + n = NULL; + + bus_track_remove_from_queue(track); + track->modified = true; + + return 1; +} + +_public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) { + struct track_item *i; + + assert_return(name, -EINVAL); + + if (!track) /* Treat a NULL track object as an empty track object */ + return 0; + + if (!track->recursive) + return bus_track_remove_name_fully(track, name); + + i = hashmap_get(track->names, name); + if (!i) + return -EUNATCH; + if (i->n_ref <= 0) + return -EUNATCH; + + i->n_ref--; + + if (i->n_ref <= 0) + return bus_track_remove_name_fully(track, name); + + return 1; +} + +_public_ unsigned sd_bus_track_count(sd_bus_track *track) { + + if (!track) /* Let's consider a NULL object equivalent to an empty object */ + return 0; + + /* This signature really should have returned an int, so that we can propagate errors. But well, ... Also, note + * that this returns the number of names being watched, and multiple references to the same name are not + * counted. */ + + return hashmap_size(track->names); +} + +_public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) { + assert_return(name, NULL); + + if (!track) /* Let's consider a NULL object equivalent to an empty object */ + return NULL; + + return hashmap_get(track->names, (void*) name) ? name : NULL; +} + +_public_ const char* sd_bus_track_first(sd_bus_track *track) { + const char *n = NULL; + + if (!track) + return NULL; + + track->modified = false; + track->iterator = ITERATOR_FIRST; + + (void) hashmap_iterate(track->names, &track->iterator, NULL, (const void**) &n); + return n; +} + +_public_ const char* sd_bus_track_next(sd_bus_track *track) { + const char *n = NULL; + + if (!track) + return NULL; + + if (track->modified) + return NULL; + + (void) hashmap_iterate(track->names, &track->iterator, NULL, (const void**) &n); + return n; +} + +_public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) { + const char *sender; + + assert_return(track, -EINVAL); + assert_return(m, -EINVAL); + + if (sd_bus_message_get_bus(m) != track->bus) + return -EINVAL; + + sender = sd_bus_message_get_sender(m); + if (!sender) + return -EINVAL; + + return sd_bus_track_add_name(track, sender); +} + +_public_ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) { + const char *sender; + + assert_return(m, -EINVAL); + + if (!track) /* Treat a NULL track object as an empty track object */ + return 0; + + if (sd_bus_message_get_bus(m) != track->bus) + return -EINVAL; + + sender = sd_bus_message_get_sender(m); + if (!sender) + return -EINVAL; + + return sd_bus_track_remove_name(track, sender); +} + +_public_ sd_bus* sd_bus_track_get_bus(sd_bus_track *track) { + assert_return(track, NULL); + + return track->bus; +} + +void bus_track_dispatch(sd_bus_track *track) { + int r; + + assert(track); + assert(track->handler); + + bus_track_remove_from_queue(track); + + sd_bus_track_ref(track); + + r = track->handler(track, track->userdata); + if (r < 0) + log_debug_errno(r, "Failed to process track handler: %m"); + else if (r == 0) + bus_track_add_to_queue(track); + + sd_bus_track_unref(track); +} + +void bus_track_close(sd_bus_track *track) { + assert(track); + + /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it + * immediately, as we are closing now, but first flush out all names. */ + + if (!track->in_list) + return; /* We already closed this one, don't close it again. */ + + /* Remember that this one is closed now */ + LIST_REMOVE(tracks, track->bus->tracks, track); + track->in_list = false; + + /* If there's no name in this one anyway, we don't have to dispatch */ + if (hashmap_isempty(track->names)) + return; + + /* Let's flush out all names */ + hashmap_clear(track->names); + + /* Invoke handler */ + if (track->handler) + bus_track_dispatch(track); +} + +_public_ void *sd_bus_track_get_userdata(sd_bus_track *track) { + assert_return(track, NULL); + + return track->userdata; +} + +_public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) { + void *ret; + + assert_return(track, NULL); + + ret = track->userdata; + track->userdata = userdata; + + return ret; +} + +_public_ int sd_bus_track_set_destroy_callback(sd_bus_track *track, sd_bus_destroy_t callback) { + assert_return(track, -EINVAL); + + track->destroy_callback = callback; + return 0; +} + +_public_ int sd_bus_track_get_destroy_callback(sd_bus_track *track, sd_bus_destroy_t *ret) { + assert_return(track, -EINVAL); + + if (ret) + *ret = track->destroy_callback; + + return !!track->destroy_callback; +} + +_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) { + assert_return(track, -EINVAL); + + if (track->recursive == !!b) + return 0; + + if (!hashmap_isempty(track->names)) + return -EBUSY; + + track->recursive = b; + return 0; +} + +_public_ int sd_bus_track_get_recursive(sd_bus_track *track) { + assert_return(track, -EINVAL); + + return track->recursive; +} + +_public_ int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m) { + const char *sender; + + assert_return(m, -EINVAL); + + if (!track) /* Let's consider a NULL object equivalent to an empty object */ + return 0; + + if (sd_bus_message_get_bus(m) != track->bus) + return -EINVAL; + + sender = sd_bus_message_get_sender(m); + if (!sender) + return -EINVAL; + + return sd_bus_track_count_name(track, sender); +} + +_public_ int sd_bus_track_count_name(sd_bus_track *track, const char *name) { + struct track_item *i; + + assert_return(service_name_is_valid(name), -EINVAL); + + if (!track) /* Let's consider a NULL object equivalent to an empty object */ + return 0; + + i = hashmap_get(track->names, name); + if (!i) + return 0; + + return i->n_ref; +} diff --git a/src/libsystemd/sd-bus/bus-track.h b/src/libsystemd/sd-bus/bus-track.h new file mode 100644 index 00000000..209b989d --- /dev/null +++ b/src/libsystemd/sd-bus/bus-track.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +void bus_track_dispatch(sd_bus_track *track); +void bus_track_close(sd_bus_track *track); diff --git a/src/libsystemd/sd-bus/bus-type.c b/src/libsystemd/sd-bus/bus-type.c new file mode 100644 index 00000000..18564a53 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-type.c @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-bus.h" + +#include "bus-type.h" + +bool bus_type_is_valid(char c) { + static const char valid[] = { + SD_BUS_TYPE_BYTE, + SD_BUS_TYPE_BOOLEAN, + SD_BUS_TYPE_INT16, + SD_BUS_TYPE_UINT16, + SD_BUS_TYPE_INT32, + SD_BUS_TYPE_UINT32, + SD_BUS_TYPE_INT64, + SD_BUS_TYPE_UINT64, + SD_BUS_TYPE_DOUBLE, + SD_BUS_TYPE_STRING, + SD_BUS_TYPE_OBJECT_PATH, + SD_BUS_TYPE_SIGNATURE, + SD_BUS_TYPE_ARRAY, + SD_BUS_TYPE_VARIANT, + SD_BUS_TYPE_STRUCT, + SD_BUS_TYPE_DICT_ENTRY, + SD_BUS_TYPE_UNIX_FD + }; + + return !!memchr(valid, c, sizeof(valid)); +} + +bool bus_type_is_basic(char c) { + static const char valid[] = { + SD_BUS_TYPE_BYTE, + SD_BUS_TYPE_BOOLEAN, + SD_BUS_TYPE_INT16, + SD_BUS_TYPE_UINT16, + SD_BUS_TYPE_INT32, + SD_BUS_TYPE_UINT32, + SD_BUS_TYPE_INT64, + SD_BUS_TYPE_UINT64, + SD_BUS_TYPE_DOUBLE, + SD_BUS_TYPE_STRING, + SD_BUS_TYPE_OBJECT_PATH, + SD_BUS_TYPE_SIGNATURE, + SD_BUS_TYPE_UNIX_FD + }; + + return !!memchr(valid, c, sizeof(valid)); +} + +bool bus_type_is_trivial(char c) { + static const char valid[] = { + SD_BUS_TYPE_BYTE, + SD_BUS_TYPE_BOOLEAN, + SD_BUS_TYPE_INT16, + SD_BUS_TYPE_UINT16, + SD_BUS_TYPE_INT32, + SD_BUS_TYPE_UINT32, + SD_BUS_TYPE_INT64, + SD_BUS_TYPE_UINT64, + SD_BUS_TYPE_DOUBLE + }; + + return !!memchr(valid, c, sizeof(valid)); +} + +bool bus_type_is_container(char c) { + static const char valid[] = { + SD_BUS_TYPE_ARRAY, + SD_BUS_TYPE_VARIANT, + SD_BUS_TYPE_STRUCT, + SD_BUS_TYPE_DICT_ENTRY + }; + + return !!memchr(valid, c, sizeof(valid)); +} + +int bus_type_get_alignment(char c) { + + switch (c) { + case SD_BUS_TYPE_BYTE: + case SD_BUS_TYPE_SIGNATURE: + case SD_BUS_TYPE_VARIANT: + return 1; + + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: + return 2; + + case SD_BUS_TYPE_BOOLEAN: + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: + case SD_BUS_TYPE_ARRAY: + case SD_BUS_TYPE_UNIX_FD: + return 4; + + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: + case SD_BUS_TYPE_DOUBLE: + case SD_BUS_TYPE_STRUCT: + case SD_BUS_TYPE_STRUCT_BEGIN: + case SD_BUS_TYPE_DICT_ENTRY: + case SD_BUS_TYPE_DICT_ENTRY_BEGIN: + return 8; + } + + return -EINVAL; +} + +int bus_type_get_size(char c) { + + switch (c) { + case SD_BUS_TYPE_BYTE: + return 1; + + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: + return 2; + + case SD_BUS_TYPE_BOOLEAN: + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + case SD_BUS_TYPE_UNIX_FD: + return 4; + + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: + case SD_BUS_TYPE_DOUBLE: + return 8; + } + + return -EINVAL; +} diff --git a/src/libsystemd/sd-bus/bus-type.h b/src/libsystemd/sd-bus/bus-type.h new file mode 100644 index 00000000..0ecd8513 --- /dev/null +++ b/src/libsystemd/sd-bus/bus-type.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +bool bus_type_is_valid(char c) _const_; +bool bus_type_is_basic(char c) _const_; +/* "trivial" is systemd's term for what the D-Bus Specification calls + * a "fixed type": that is, a basic type of fixed length */ +bool bus_type_is_trivial(char c) _const_; +bool bus_type_is_container(char c) _const_; + +int bus_type_get_alignment(char c) _const_; +int bus_type_get_size(char c) _const_; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c new file mode 100644 index 00000000..6933a2b8 --- /dev/null +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -0,0 +1,4233 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-container.h" +#include "bus-control.h" +#include "bus-internal.h" +#include "bus-kernel.h" +#include "bus-label.h" +#include "bus-message.h" +#include "bus-objects.h" +#include "bus-protocol.h" +#include "bus-slot.h" +#include "bus-socket.h" +#include "bus-track.h" +#include "bus-type.h" +#include "bus-util.h" +#include "cgroup-util.h" +#include "def.h" +#include "errno-util.h" +#include "fd-util.h" +#include "hexdecoct.h" +#include "hostname-util.h" +#include "macro.h" +#include "memory-util.h" +#include "missing_syscall.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "string-util.h" +#include "strv.h" + +#define log_debug_bus_message(m) \ + do { \ + sd_bus_message *_mm = (m); \ + log_debug("Got message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s", \ + bus_message_type_to_string(_mm->header->type), \ + strna(sd_bus_message_get_sender(_mm)), \ + strna(sd_bus_message_get_destination(_mm)), \ + strna(sd_bus_message_get_path(_mm)), \ + strna(sd_bus_message_get_interface(_mm)), \ + strna(sd_bus_message_get_member(_mm)), \ + BUS_MESSAGE_COOKIE(_mm), \ + _mm->reply_cookie, \ + strna(_mm->root_container.signature), \ + strna(_mm->error.name), \ + strna(_mm->error.message)); \ + } while (false) + +static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec); +static void bus_detach_io_events(sd_bus *b); +static void bus_detach_inotify_event(sd_bus *b); + +static thread_local sd_bus *default_system_bus = NULL; +static thread_local sd_bus *default_user_bus = NULL; +static thread_local sd_bus *default_starter_bus = NULL; + +static sd_bus **bus_choose_default(int (**bus_open)(sd_bus **)) { + const char *e; + + /* Let's try our best to reuse another cached connection. If + * the starter bus type is set, connect via our normal + * connection logic, ignoring $DBUS_STARTER_ADDRESS, so that + * we can share the connection with the user/system default + * bus. */ + + e = secure_getenv("DBUS_STARTER_BUS_TYPE"); + if (e) { + if (streq(e, "system")) { + if (bus_open) + *bus_open = sd_bus_open_system; + return &default_system_bus; + } else if (STR_IN_SET(e, "user", "session")) { + if (bus_open) + *bus_open = sd_bus_open_user; + return &default_user_bus; + } + } + + /* No type is specified, so we have not other option than to + * use the starter address if it is set. */ + e = secure_getenv("DBUS_STARTER_ADDRESS"); + if (e) { + if (bus_open) + *bus_open = sd_bus_open; + return &default_starter_bus; + } + + /* Finally, if nothing is set use the cached connection for + * the right scope */ + + if (cg_pid_get_owner_uid(0, NULL) >= 0) { + if (bus_open) + *bus_open = sd_bus_open_user; + return &default_user_bus; + } else { + if (bus_open) + *bus_open = sd_bus_open_system; + return &default_system_bus; + } +} + +sd_bus *bus_resolve(sd_bus *bus) { + switch ((uintptr_t) bus) { + case (uintptr_t) SD_BUS_DEFAULT: + return *(bus_choose_default(NULL)); + case (uintptr_t) SD_BUS_DEFAULT_USER: + return default_user_bus; + case (uintptr_t) SD_BUS_DEFAULT_SYSTEM: + return default_system_bus; + default: + return bus; + } +} + +void bus_close_io_fds(sd_bus *b) { + assert(b); + + bus_detach_io_events(b); + + if (b->input_fd != b->output_fd) + safe_close(b->output_fd); + b->output_fd = b->input_fd = safe_close(b->input_fd); +} + +void bus_close_inotify_fd(sd_bus *b) { + assert(b); + + bus_detach_inotify_event(b); + + b->inotify_fd = safe_close(b->inotify_fd); + b->inotify_watches = mfree(b->inotify_watches); + b->n_inotify_watches = 0; +} + +static void bus_reset_queues(sd_bus *b) { + assert(b); + + while (b->rqueue_size > 0) + bus_message_unref_queued(b->rqueue[--b->rqueue_size], b); + + b->rqueue = mfree(b->rqueue); + b->rqueue_allocated = 0; + + while (b->wqueue_size > 0) + bus_message_unref_queued(b->wqueue[--b->wqueue_size], b); + + b->wqueue = mfree(b->wqueue); + b->wqueue_allocated = 0; +} + +static sd_bus* bus_free(sd_bus *b) { + sd_bus_slot *s; + + assert(b); + assert(!b->track_queue); + assert(!b->tracks); + + b->state = BUS_CLOSED; + + sd_bus_detach_event(b); + + while ((s = b->slots)) { + /* At this point only floating slots can still be + * around, because the non-floating ones keep a + * reference to the bus, and we thus couldn't be + * destructing right now... We forcibly disconnect the + * slots here, so that they still can be referenced by + * apps, but are dead. */ + + assert(s->floating); + bus_slot_disconnect(s, true); + } + + if (b->default_bus_ptr) + *b->default_bus_ptr = NULL; + + bus_close_io_fds(b); + bus_close_inotify_fd(b); + + free(b->label); + free(b->groups); + free(b->rbuffer); + free(b->unique_name); + free(b->auth_buffer); + free(b->address); + free(b->machine); + free(b->description); + free(b->patch_sender); + + free(b->exec_path); + strv_free(b->exec_argv); + + close_many(b->fds, b->n_fds); + free(b->fds); + + bus_reset_queues(b); + + ordered_hashmap_free_free(b->reply_callbacks); + prioq_free(b->reply_callbacks_prioq); + + assert(b->match_callbacks.type == BUS_MATCH_ROOT); + bus_match_free(&b->match_callbacks); + + hashmap_free_free(b->vtable_methods); + hashmap_free_free(b->vtable_properties); + + assert(hashmap_isempty(b->nodes)); + hashmap_free(b->nodes); + + bus_flush_memfd(b); + + assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0); + + return mfree(b); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, bus_free); + +_public_ int sd_bus_new(sd_bus **ret) { + _cleanup_free_ sd_bus *b = NULL; + + assert_return(ret, -EINVAL); + + b = new(sd_bus, 1); + if (!b) + return -ENOMEM; + + *b = (sd_bus) { + .n_ref = 1, + .input_fd = -1, + .output_fd = -1, + .inotify_fd = -1, + .message_version = 1, + .creds_mask = SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME, + .accept_fd = true, + .original_pid = getpid_cached(), + .n_groups = (size_t) -1, + .close_on_exit = true, + }; + + /* We guarantee that wqueue always has space for at least one entry */ + if (!GREEDY_REALLOC(b->wqueue, b->wqueue_allocated, 1)) + return -ENOMEM; + + assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0); + + *ret = TAKE_PTR(b); + return 0; +} + +_public_ int sd_bus_set_address(sd_bus *bus, const char *address) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(address, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return free_and_strdup(&bus->address, address); +} + +_public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(input_fd >= 0, -EBADF); + assert_return(output_fd >= 0, -EBADF); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->input_fd = input_fd; + bus->output_fd = output_fd; + return 0; +} + +_public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) { + _cleanup_strv_free_ char **a = NULL; + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(path, -EINVAL); + assert_return(!strv_isempty(argv), -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + a = strv_copy(argv); + if (!a) + return -ENOMEM; + + r = free_and_strdup(&bus->exec_path, path); + if (r < 0) + return r; + + return strv_free_and_replace(bus->exec_argv, a); +} + +_public_ int sd_bus_set_bus_client(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus->patch_sender, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->bus_client = !!b; + return 0; +} + +_public_ int sd_bus_set_monitor(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->is_monitor = !!b; + return 0; +} + +_public_ int sd_bus_negotiate_fds(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->accept_fd = !!b; + return 0; +} + +_public_ int sd_bus_negotiate_timestamp(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + /* This is not actually supported by any of our transports these days, but we do honour it for synthetic + * replies, and maybe one day classic D-Bus learns this too */ + bus->attach_timestamp = !!b; + + return 0; +} + +_public_ int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t mask) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(mask <= _SD_BUS_CREDS_ALL, -EINVAL); + assert_return(!IN_SET(bus->state, BUS_CLOSING, BUS_CLOSED), -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + SET_FLAG(bus->creds_mask, mask, b); + + /* The well knowns we need unconditionally, so that matches can work */ + bus->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME; + + return 0; +} + +_public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(b || sd_id128_equal(server_id, SD_ID128_NULL), -EINVAL); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->is_server = !!b; + bus->server_id = server_id; + return 0; +} + +_public_ int sd_bus_set_anonymous(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->anonymous_auth = !!b; + return 0; +} + +_public_ int sd_bus_set_trusted(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->trusted = !!b; + return 0; +} + +_public_ int sd_bus_set_description(sd_bus *bus, const char *description) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return free_and_strdup(&bus->description, description); +} + +_public_ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->allow_interactive_authorization = !!b; + return 0; +} + +_public_ int sd_bus_get_allow_interactive_authorization(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return bus->allow_interactive_authorization; +} + +_public_ int sd_bus_set_watch_bind(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->watch_bind = !!b; + return 0; +} + +_public_ int sd_bus_get_watch_bind(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return bus->watch_bind; +} + +_public_ int sd_bus_set_connected_signal(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->connected_signal = !!b; + return 0; +} + +_public_ int sd_bus_get_connected_signal(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return bus->connected_signal; +} + +static int synthesize_connected_signal(sd_bus *bus) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + assert(bus); + + /* If enabled, synthesizes a local "Connected" signal mirroring the local "Disconnected" signal. This is called + * whenever we fully established a connection, i.e. after the authorization phase, and after receiving the + * Hello() reply. Or in other words, whenever we enter BUS_RUNNING state. + * + * This is useful so that clients can start doing stuff whenever the connection is fully established in a way + * that works independently from whether we connected to a full bus or just a direct connection. */ + + if (!bus->connected_signal) + return 0; + + r = sd_bus_message_new_signal( + bus, + &m, + "/org/freedesktop/DBus/Local", + "org.freedesktop.DBus.Local", + "Connected"); + if (r < 0) + return r; + + bus_message_set_sender_local(bus, m); + m->read_counter = ++bus->read_counter; + + r = bus_seal_synthetic_message(bus, m); + if (r < 0) + return r; + + r = bus_rqueue_make_room(bus); + if (r < 0) + return r; + + /* Insert at the very front */ + memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size); + bus->rqueue[0] = bus_message_ref_queued(m, bus); + bus->rqueue_size++; + + return 0; +} + +void bus_set_state(sd_bus *bus, enum bus_state state) { + + static const char * const table[_BUS_STATE_MAX] = { + [BUS_UNSET] = "UNSET", + [BUS_WATCH_BIND] = "WATCH_BIND", + [BUS_OPENING] = "OPENING", + [BUS_AUTHENTICATING] = "AUTHENTICATING", + [BUS_HELLO] = "HELLO", + [BUS_RUNNING] = "RUNNING", + [BUS_CLOSING] = "CLOSING", + [BUS_CLOSED] = "CLOSED", + }; + + assert(bus); + assert(state < _BUS_STATE_MAX); + + if (state == bus->state) + return; + + log_debug("Bus %s: changing state %s → %s", strna(bus->description), table[bus->state], table[state]); + bus->state = state; +} + +static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { + const char *s; + sd_bus *bus; + int r; + + assert(reply); + bus = reply->bus; + assert(bus); + assert(IN_SET(bus->state, BUS_HELLO, BUS_CLOSING)); + + r = sd_bus_message_get_errno(reply); + if (r > 0) { + r = -r; + goto fail; + } + + r = sd_bus_message_read(reply, "s", &s); + if (r < 0) + goto fail; + + if (!service_name_is_valid(s) || s[0] != ':') { + r = -EBADMSG; + goto fail; + } + + r = free_and_strdup(&bus->unique_name, s); + if (r < 0) + goto fail; + + if (bus->state == BUS_HELLO) { + bus_set_state(bus, BUS_RUNNING); + + r = synthesize_connected_signal(bus); + if (r < 0) + goto fail; + } + + return 1; + +fail: + /* When Hello() failed, let's propagate this in two ways: first we return the error immediately here, + * which is the propagated up towards the event loop. Let's also invalidate the connection, so that + * if the user then calls back into us again we won't wait any longer. */ + + bus_set_state(bus, BUS_CLOSING); + return r; +} + +static int bus_send_hello(sd_bus *bus) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + assert(bus); + + if (!bus->bus_client) + return 0; + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "Hello"); + if (r < 0) + return r; + + return sd_bus_call_async(bus, NULL, m, hello_callback, NULL, 0); +} + +int bus_start_running(sd_bus *bus) { + struct reply_callback *c; + Iterator i; + usec_t n; + int r; + + assert(bus); + assert(bus->state < BUS_HELLO); + + /* We start all method call timeouts when we enter BUS_HELLO or BUS_RUNNING mode. At this point let's convert + * all relative to absolute timestamps. Note that we do not reshuffle the reply callback priority queue since + * adding a fixed value to all entries should not alter the internal order. */ + + n = now(CLOCK_MONOTONIC); + ORDERED_HASHMAP_FOREACH(c, bus->reply_callbacks, i) { + if (c->timeout_usec == 0) + continue; + + c->timeout_usec = usec_add(n, c->timeout_usec); + } + + if (bus->bus_client) { + bus_set_state(bus, BUS_HELLO); + return 1; + } + + bus_set_state(bus, BUS_RUNNING); + + r = synthesize_connected_signal(bus); + if (r < 0) + return r; + + return 1; +} + +static int parse_address_key(const char **p, const char *key, char **value) { + size_t l, n = 0, allocated = 0; + _cleanup_free_ char *r = NULL; + const char *a; + + assert(p); + assert(*p); + assert(value); + + if (key) { + l = strlen(key); + if (strncmp(*p, key, l) != 0) + return 0; + + if ((*p)[l] != '=') + return 0; + + if (*value) + return -EINVAL; + + a = *p + l + 1; + } else + a = *p; + + while (!IN_SET(*a, ';', ',', 0)) { + char c; + + if (*a == '%') { + int x, y; + + x = unhexchar(a[1]); + if (x < 0) + return x; + + y = unhexchar(a[2]); + if (y < 0) + return y; + + c = (char) ((x << 4) | y); + a += 3; + } else { + c = *a; + a++; + } + + if (!GREEDY_REALLOC(r, allocated, n + 2)) + return -ENOMEM; + + r[n++] = c; + } + + if (!r) { + r = strdup(""); + if (!r) + return -ENOMEM; + } else + r[n] = 0; + + if (*a == ',') + a++; + + *p = a; + + free_and_replace(*value, r); + + return 1; +} + +static void skip_address_key(const char **p) { + assert(p); + assert(*p); + + *p += strcspn(*p, ","); + + if (**p == ',') + (*p)++; +} + +static int parse_unix_address(sd_bus *b, const char **p, char **guid) { + _cleanup_free_ char *path = NULL, *abstract = NULL; + size_t l; + int r; + + assert(b); + assert(p); + assert(*p); + assert(guid); + + while (!IN_SET(**p, 0, ';')) { + r = parse_address_key(p, "guid", guid); + if (r < 0) + return r; + else if (r > 0) + continue; + + r = parse_address_key(p, "path", &path); + if (r < 0) + return r; + else if (r > 0) + continue; + + r = parse_address_key(p, "abstract", &abstract); + if (r < 0) + return r; + else if (r > 0) + continue; + + skip_address_key(p); + } + + if (!path && !abstract) + return -EINVAL; + + if (path && abstract) + return -EINVAL; + + if (path) { + l = strlen(path); + if (l >= sizeof(b->sockaddr.un.sun_path)) /* We insist on NUL termination */ + return -E2BIG; + + b->sockaddr.un = (struct sockaddr_un) { + .sun_family = AF_UNIX, + }; + + memcpy(b->sockaddr.un.sun_path, path, l); + b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l + 1; + + } else { + assert(abstract); + + l = strlen(abstract); + if (l >= sizeof(b->sockaddr.un.sun_path) - 1) /* We insist on NUL termination */ + return -E2BIG; + + b->sockaddr.un = (struct sockaddr_un) { + .sun_family = AF_UNIX, + }; + + memcpy(b->sockaddr.un.sun_path+1, abstract, l); + b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l; + } + + b->is_local = true; + + return 0; +} + +static int parse_tcp_address(sd_bus *b, const char **p, char **guid) { + _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL; + int r; + struct addrinfo *result, hints = { + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_ADDRCONFIG, + }; + + assert(b); + assert(p); + assert(*p); + assert(guid); + + while (!IN_SET(**p, 0, ';')) { + r = parse_address_key(p, "guid", guid); + if (r < 0) + return r; + else if (r > 0) + continue; + + r = parse_address_key(p, "host", &host); + if (r < 0) + return r; + else if (r > 0) + continue; + + r = parse_address_key(p, "port", &port); + if (r < 0) + return r; + else if (r > 0) + continue; + + r = parse_address_key(p, "family", &family); + if (r < 0) + return r; + else if (r > 0) + continue; + + skip_address_key(p); + } + + if (!host || !port) + return -EINVAL; + + if (family) { + if (streq(family, "ipv4")) + hints.ai_family = AF_INET; + else if (streq(family, "ipv6")) + hints.ai_family = AF_INET6; + else + return -EINVAL; + } + + r = getaddrinfo(host, port, &hints, &result); + if (r == EAI_SYSTEM) + return -errno; + else if (r != 0) + return -EADDRNOTAVAIL; + + memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen); + b->sockaddr_size = result->ai_addrlen; + + freeaddrinfo(result); + + b->is_local = false; + + return 0; +} + +static int parse_exec_address(sd_bus *b, const char **p, char **guid) { + char *path = NULL; + unsigned n_argv = 0, j; + char **argv = NULL; + size_t allocated = 0; + int r; + + assert(b); + assert(p); + assert(*p); + assert(guid); + + while (!IN_SET(**p, 0, ';')) { + r = parse_address_key(p, "guid", guid); + if (r < 0) + goto fail; + else if (r > 0) + continue; + + r = parse_address_key(p, "path", &path); + if (r < 0) + goto fail; + else if (r > 0) + continue; + + if (startswith(*p, "argv")) { + unsigned ul; + + errno = 0; + ul = strtoul(*p + 4, (char**) p, 10); + if (errno > 0 || **p != '=' || ul > 256) { + r = -EINVAL; + goto fail; + } + + (*p)++; + + if (ul >= n_argv) { + if (!GREEDY_REALLOC0(argv, allocated, ul + 2)) { + r = -ENOMEM; + goto fail; + } + + n_argv = ul + 1; + } + + r = parse_address_key(p, NULL, argv + ul); + if (r < 0) + goto fail; + + continue; + } + + skip_address_key(p); + } + + if (!path) { + r = -EINVAL; + goto fail; + } + + /* Make sure there are no holes in the array, with the + * exception of argv[0] */ + for (j = 1; j < n_argv; j++) + if (!argv[j]) { + r = -EINVAL; + goto fail; + } + + if (argv && argv[0] == NULL) { + argv[0] = strdup(path); + if (!argv[0]) { + r = -ENOMEM; + goto fail; + } + } + + b->exec_path = path; + b->exec_argv = argv; + + b->is_local = false; + + return 0; + +fail: + for (j = 0; j < n_argv; j++) + free(argv[j]); + + free(argv); + free(path); + return r; +} + +static int parse_container_unix_address(sd_bus *b, const char **p, char **guid) { + _cleanup_free_ char *machine = NULL, *pid = NULL; + int r; + + assert(b); + assert(p); + assert(*p); + assert(guid); + + while (!IN_SET(**p, 0, ';')) { + r = parse_address_key(p, "guid", guid); + if (r < 0) + return r; + else if (r > 0) + continue; + + r = parse_address_key(p, "machine", &machine); + if (r < 0) + return r; + else if (r > 0) + continue; + + r = parse_address_key(p, "pid", &pid); + if (r < 0) + return r; + else if (r > 0) + continue; + + skip_address_key(p); + } + + if (!machine == !pid) + return -EINVAL; + + if (machine) { + if (!streq(machine, ".host") && !machine_name_is_valid(machine)) + return -EINVAL; + + free_and_replace(b->machine, machine); + } else { + b->machine = mfree(b->machine); + } + + if (pid) { + r = parse_pid(pid, &b->nspid); + if (r < 0) + return r; + } else + b->nspid = 0; + + b->sockaddr.un = (struct sockaddr_un) { + .sun_family = AF_UNIX, + /* Note that we use the old /var/run prefix here, to increase compatibility with really old containers */ + .sun_path = "/var/run/dbus/system_bus_socket", + }; + b->sockaddr_size = SOCKADDR_UN_LEN(b->sockaddr.un); + b->is_local = false; + + return 0; +} + +static void bus_reset_parsed_address(sd_bus *b) { + assert(b); + + zero(b->sockaddr); + b->sockaddr_size = 0; + b->exec_argv = strv_free(b->exec_argv); + b->exec_path = mfree(b->exec_path); + b->server_id = SD_ID128_NULL; + b->machine = mfree(b->machine); + b->nspid = 0; +} + +static int bus_parse_next_address(sd_bus *b) { + _cleanup_free_ char *guid = NULL; + const char *a; + int r; + + assert(b); + + if (!b->address) + return 0; + if (b->address[b->address_index] == 0) + return 0; + + bus_reset_parsed_address(b); + + a = b->address + b->address_index; + + while (*a != 0) { + + if (*a == ';') { + a++; + continue; + } + + if (startswith(a, "unix:")) { + a += 5; + + r = parse_unix_address(b, &a, &guid); + if (r < 0) + return r; + break; + + } else if (startswith(a, "tcp:")) { + + a += 4; + r = parse_tcp_address(b, &a, &guid); + if (r < 0) + return r; + + break; + + } else if (startswith(a, "unixexec:")) { + + a += 9; + r = parse_exec_address(b, &a, &guid); + if (r < 0) + return r; + + break; + + } else if (startswith(a, "x-machine-unix:")) { + + a += 15; + r = parse_container_unix_address(b, &a, &guid); + if (r < 0) + return r; + + break; + } + + a = strchr(a, ';'); + if (!a) + return 0; + } + + if (guid) { + r = sd_id128_from_string(guid, &b->server_id); + if (r < 0) + return r; + } + + b->address_index = a - b->address; + return 1; +} + +static void bus_kill_exec(sd_bus *bus) { + if (pid_is_valid(bus->busexec_pid) > 0) { + sigterm_wait(bus->busexec_pid); + bus->busexec_pid = 0; + } +} + +static int bus_start_address(sd_bus *b) { + int r; + + assert(b); + + for (;;) { + bus_close_io_fds(b); + bus_close_inotify_fd(b); + + bus_kill_exec(b); + + /* If you provide multiple different bus-addresses, we + * try all of them in order and use the first one that + * succeeds. */ + + if (b->exec_path) + r = bus_socket_exec(b); + else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) + r = bus_container_connect_socket(b); + else if (b->sockaddr.sa.sa_family != AF_UNSPEC) + r = bus_socket_connect(b); + else + goto next; + + if (r >= 0) { + int q; + + q = bus_attach_io_events(b); + if (q < 0) + return q; + + q = bus_attach_inotify_event(b); + if (q < 0) + return q; + + return r; + } + + b->last_connect_error = -r; + + next: + r = bus_parse_next_address(b); + if (r < 0) + return r; + if (r == 0) + return b->last_connect_error > 0 ? -b->last_connect_error : -ECONNREFUSED; + } +} + +int bus_next_address(sd_bus *b) { + assert(b); + + bus_reset_parsed_address(b); + return bus_start_address(b); +} + +static int bus_start_fd(sd_bus *b) { + struct stat st; + int r; + + assert(b); + assert(b->input_fd >= 0); + assert(b->output_fd >= 0); + + r = fd_nonblock(b->input_fd, true); + if (r < 0) + return r; + + r = fd_cloexec(b->input_fd, true); + if (r < 0) + return r; + + if (b->input_fd != b->output_fd) { + r = fd_nonblock(b->output_fd, true); + if (r < 0) + return r; + + r = fd_cloexec(b->output_fd, true); + if (r < 0) + return r; + } + + if (fstat(b->input_fd, &st) < 0) + return -errno; + + return bus_socket_take_fd(b); +} + +_public_ int sd_bus_start(sd_bus *bus) { + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus_set_state(bus, BUS_OPENING); + + if (bus->is_server && bus->bus_client) + return -EINVAL; + + if (bus->input_fd >= 0) + r = bus_start_fd(bus); + else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->machine) + r = bus_start_address(bus); + else + return -EINVAL; + + if (r < 0) { + sd_bus_close(bus); + return r; + } + + return bus_send_hello(bus); +} + +_public_ int sd_bus_open_with_description(sd_bus **ret, const char *description) { + const char *e; + _cleanup_(bus_freep) sd_bus *b = NULL; + int r; + + assert_return(ret, -EINVAL); + + /* Let's connect to the starter bus if it is set, and + * otherwise to the bus that is appropriate for the scope + * we are running in */ + + e = secure_getenv("DBUS_STARTER_BUS_TYPE"); + if (e) { + if (streq(e, "system")) + return sd_bus_open_system_with_description(ret, description); + else if (STR_IN_SET(e, "session", "user")) + return sd_bus_open_user_with_description(ret, description); + } + + e = secure_getenv("DBUS_STARTER_ADDRESS"); + if (!e) { + if (cg_pid_get_owner_uid(0, NULL) >= 0) + return sd_bus_open_user_with_description(ret, description); + else + return sd_bus_open_system_with_description(ret, description); + } + + r = sd_bus_new(&b); + if (r < 0) + return r; + + r = sd_bus_set_address(b, e); + if (r < 0) + return r; + + b->bus_client = true; + + /* We don't know whether the bus is trusted or not, so better + * be safe, and authenticate everything */ + b->trusted = false; + b->is_local = false; + b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS; + + r = sd_bus_start(b); + if (r < 0) + return r; + + *ret = TAKE_PTR(b); + return 0; +} + +_public_ int sd_bus_open(sd_bus **ret) { + return sd_bus_open_with_description(ret, NULL); +} + +int bus_set_address_system(sd_bus *b) { + const char *e; + assert(b); + + e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS"); + if (e) + return sd_bus_set_address(b, e); + + return sd_bus_set_address(b, DEFAULT_SYSTEM_BUS_ADDRESS); +} + +_public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *description) { + _cleanup_(bus_freep) sd_bus *b = NULL; + int r; + + assert_return(ret, -EINVAL); + + r = sd_bus_new(&b); + if (r < 0) + return r; + + if (description) { + r = sd_bus_set_description(b, description); + if (r < 0) + return r; + } + + r = bus_set_address_system(b); + if (r < 0) + return r; + + b->bus_client = true; + b->is_system = true; + + /* Let's do per-method access control on the system bus. We + * need the caller's UID and capability set for that. */ + b->trusted = false; + b->creds_mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS; + b->is_local = true; + + r = sd_bus_start(b); + if (r < 0) + return r; + + *ret = TAKE_PTR(b); + return 0; +} + +_public_ int sd_bus_open_system(sd_bus **ret) { + return sd_bus_open_system_with_description(ret, NULL); +} + +int bus_set_address_user(sd_bus *b) { + const char *e; + _cleanup_free_ char *ee = NULL, *s = NULL; + + assert(b); + + e = secure_getenv("DBUS_SESSION_BUS_ADDRESS"); + if (e) + return sd_bus_set_address(b, e); + + e = secure_getenv("XDG_RUNTIME_DIR"); + if (!e) + return -ENOENT; + + ee = bus_address_escape(e); + if (!ee) + return -ENOMEM; + + if (asprintf(&s, DEFAULT_USER_BUS_ADDRESS_FMT, ee) < 0) + return -ENOMEM; + + b->address = TAKE_PTR(s); + + return 0; +} + +_public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *description) { + _cleanup_(bus_freep) sd_bus *b = NULL; + int r; + + assert_return(ret, -EINVAL); + + r = sd_bus_new(&b); + if (r < 0) + return r; + + if (description) { + r = sd_bus_set_description(b, description); + if (r < 0) + return r; + } + + r = bus_set_address_user(b); + if (r < 0) + return r; + + b->bus_client = true; + b->is_user = true; + + /* We don't do any per-method access control on the user bus. */ + b->trusted = true; + b->is_local = true; + + r = sd_bus_start(b); + if (r < 0) + return r; + + *ret = TAKE_PTR(b); + return 0; +} + +_public_ int sd_bus_open_user(sd_bus **ret) { + return sd_bus_open_user_with_description(ret, NULL); +} + +int bus_set_address_system_remote(sd_bus *b, const char *host) { + _cleanup_free_ char *e = NULL; + char *m = NULL, *c = NULL, *a, *rbracket = NULL, *p = NULL; + + assert(b); + assert(host); + + /* Skip ":"s in ipv6 addresses */ + if (*host == '[') { + char *t; + + rbracket = strchr(host, ']'); + if (!rbracket) + return -EINVAL; + t = strndupa(host + 1, rbracket - host - 1); + e = bus_address_escape(t); + if (!e) + return -ENOMEM; + } else if ((a = strchr(host, '@'))) { + if (*(a + 1) == '[') { + _cleanup_free_ char *t = NULL; + + rbracket = strchr(a + 1, ']'); + if (!rbracket) + return -EINVAL; + t = new0(char, strlen(host)); + if (!t) + return -ENOMEM; + strncat(t, host, a - host + 1); + strncat(t, a + 2, rbracket - a - 2); + e = bus_address_escape(t); + if (!e) + return -ENOMEM; + } else if (*(a + 1) == '\0' || strchr(a + 1, '@')) + return -EINVAL; + } + + /* Let's see if a port was given */ + m = strchr(rbracket ? rbracket + 1 : host, ':'); + if (m) { + char *t; + bool got_forward_slash = false; + + p = m + 1; + + t = strchr(p, '/'); + if (t) { + p = strndupa(p, t - p); + got_forward_slash = true; + } + + if (!in_charset(p, "0123456789") || *p == '\0') { + if (!machine_name_is_valid(p) || got_forward_slash) + return -EINVAL; + + m = TAKE_PTR(p); + goto interpret_port_as_machine_old_syntax; + } + } + + /* Let's see if a machine was given */ + m = strchr(rbracket ? rbracket + 1 : host, '/'); + if (m) { + m++; +interpret_port_as_machine_old_syntax: + /* Let's make sure this is not a port of some kind, + * and is a valid machine name. */ + if (!in_charset(m, "0123456789") && machine_name_is_valid(m)) + c = strjoina(",argv", p ? "7" : "5", "=--machine=", m); + } + + if (!e) { + char *t; + + t = strndupa(host, strcspn(host, ":/")); + + e = bus_address_escape(t); + if (!e) + return -ENOMEM; + } + + a = strjoin("unixexec:path=ssh,argv1=-xT", p ? ",argv2=-p,argv3=" : "", strempty(p), + ",argv", p ? "4" : "2", "=--,argv", p ? "5" : "3", "=", e, + ",argv", p ? "6" : "4", "=systemd-stdio-bridge", c); + if (!a) + return -ENOMEM; + + return free_and_replace(b->address, a); +} + +_public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) { + _cleanup_(bus_freep) sd_bus *b = NULL; + int r; + + assert_return(host, -EINVAL); + assert_return(ret, -EINVAL); + + r = sd_bus_new(&b); + if (r < 0) + return r; + + r = bus_set_address_system_remote(b, host); + if (r < 0) + return r; + + b->bus_client = true; + b->trusted = false; + b->is_system = true; + b->is_local = false; + + r = sd_bus_start(b); + if (r < 0) + return r; + + *ret = TAKE_PTR(b); + return 0; +} + +int bus_set_address_system_machine(sd_bus *b, const char *machine) { + _cleanup_free_ char *e = NULL; + char *a; + + assert(b); + assert(machine); + + e = bus_address_escape(machine); + if (!e) + return -ENOMEM; + + a = strjoin("x-machine-unix:machine=", e); + if (!a) + return -ENOMEM; + + return free_and_replace(b->address, a); +} + +_public_ int sd_bus_open_system_machine(sd_bus **ret, const char *machine) { + _cleanup_(bus_freep) sd_bus *b = NULL; + int r; + + assert_return(machine, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(streq(machine, ".host") || machine_name_is_valid(machine), -EINVAL); + + r = sd_bus_new(&b); + if (r < 0) + return r; + + r = bus_set_address_system_machine(b, machine); + if (r < 0) + return r; + + b->bus_client = true; + b->trusted = false; + b->is_system = true; + b->is_local = false; + + r = sd_bus_start(b); + if (r < 0) + return r; + + *ret = TAKE_PTR(b); + return 0; +} + +_public_ void sd_bus_close(sd_bus *bus) { + if (!bus) + return; + if (bus->state == BUS_CLOSED) + return; + if (bus_pid_changed(bus)) + return; + + /* Don't leave ssh hanging around */ + bus_kill_exec(bus); + + bus_set_state(bus, BUS_CLOSED); + + sd_bus_detach_event(bus); + + /* Drop all queued messages so that they drop references to + * the bus object and the bus may be freed */ + bus_reset_queues(bus); + + bus_close_io_fds(bus); + bus_close_inotify_fd(bus); +} + +_public_ sd_bus *sd_bus_close_unref(sd_bus *bus) { + if (!bus) + return NULL; + + sd_bus_close(bus); + + return sd_bus_unref(bus); +} + +_public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) { + if (!bus) + return NULL; + + /* Have to do this before flush() to prevent hang */ + bus_kill_exec(bus); + sd_bus_flush(bus); + + return sd_bus_close_unref(bus); +} + +void bus_enter_closing(sd_bus *bus) { + assert(bus); + + if (!IN_SET(bus->state, BUS_WATCH_BIND, BUS_OPENING, BUS_AUTHENTICATING, BUS_HELLO, BUS_RUNNING)) + return; + + bus_set_state(bus, BUS_CLOSING); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_bus, sd_bus, bus_free); + +_public_ int sd_bus_is_open(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return BUS_IS_OPEN(bus->state); +} + +_public_ int sd_bus_is_ready(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return bus->state == BUS_RUNNING; +} + +_public_ int sd_bus_can_send(sd_bus *bus, char type) { + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->state != BUS_UNSET, -ENOTCONN); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (bus->is_monitor) + return 0; + + if (type == SD_BUS_TYPE_UNIX_FD) { + if (!bus->accept_fd) + return 0; + + r = bus_ensure_running(bus); + if (r < 0) + return r; + + return bus->can_fds; + } + + return bus_type_is_valid(type); +} + +_public_ int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id) { + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(id, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + r = bus_ensure_running(bus); + if (r < 0) + return r; + + *id = bus->server_id; + return 0; +} + +#define COOKIE_CYCLED (UINT32_C(1) << 31) + +static uint64_t cookie_inc(uint64_t cookie) { + + /* Stay within the 32bit range, since classic D-Bus can't deal with more */ + if (cookie >= UINT32_MAX) + return COOKIE_CYCLED; /* Don't go back to zero, but use the highest bit for checking + * whether we are looping. */ + + return cookie + 1; +} + +static int next_cookie(sd_bus *b) { + uint64_t new_cookie; + + assert(b); + + new_cookie = cookie_inc(b->cookie); + + /* Small optimization: don't bother with checking for cookie reuse until we overran cookiespace at + * least once, but then do it thorougly. */ + if (FLAGS_SET(new_cookie, COOKIE_CYCLED)) { + uint32_t i; + + /* Check if the cookie is currently in use. If so, pick the next one */ + for (i = 0; i < COOKIE_CYCLED; i++) { + if (!ordered_hashmap_contains(b->reply_callbacks, &new_cookie)) + goto good; + + new_cookie = cookie_inc(new_cookie); + } + + /* Can't fulfill request */ + return -EBUSY; + } + +good: + b->cookie = new_cookie; + return 0; +} + +static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) { + int r; + + assert(b); + assert(m); + + if (m->sealed) { + /* If we copy the same message to multiple + * destinations, avoid using the same cookie + * numbers. */ + b->cookie = MAX(b->cookie, BUS_MESSAGE_COOKIE(m)); + return 0; + } + + if (timeout == 0) { + r = sd_bus_get_method_call_timeout(b, &timeout); + if (r < 0) + return r; + } + + if (!m->sender && b->patch_sender) { + r = sd_bus_message_set_sender(m, b->patch_sender); + if (r < 0) + return r; + } + + r = next_cookie(b); + if (r < 0) + return r; + + return sd_bus_message_seal(m, b->cookie, timeout); +} + +static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) { + bool remarshal = false; + + assert(b); + + /* wrong packet version */ + if (b->message_version != 0 && b->message_version != (*m)->header->version) + remarshal = true; + + /* wrong packet endianness */ + if (b->message_endian != 0 && b->message_endian != (*m)->header->endian) + remarshal = true; + + return remarshal ? bus_message_remarshal(b, m) : 0; +} + +int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) { + assert(b); + assert(m); + + /* Fake some timestamps, if they were requested, and not + * already initialized */ + if (b->attach_timestamp) { + if (m->realtime <= 0) + m->realtime = now(CLOCK_REALTIME); + + if (m->monotonic <= 0) + m->monotonic = now(CLOCK_MONOTONIC); + } + + /* The bus specification says the serial number cannot be 0, + * hence let's fill something in for synthetic messages. Since + * synthetic messages might have a fake sender and we don't + * want to interfere with the real sender's serial numbers we + * pick a fixed, artificial one. We use (uint32_t) -1 rather + * than (uint64_t) -1 since dbus1 only had 32bit identifiers, + * even though kdbus can do 64bit. */ + return sd_bus_message_seal(m, 0xFFFFFFFFULL, 0); +} + +static int bus_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { + int r; + + assert(bus); + assert(m); + + r = bus_socket_write_message(bus, m, idx); + if (r <= 0) + return r; + + if (*idx >= BUS_MESSAGE_SIZE(m)) + log_debug("Sent message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s", + bus_message_type_to_string(m->header->type), + strna(sd_bus_message_get_sender(m)), + strna(sd_bus_message_get_destination(m)), + strna(sd_bus_message_get_path(m)), + strna(sd_bus_message_get_interface(m)), + strna(sd_bus_message_get_member(m)), + BUS_MESSAGE_COOKIE(m), + m->reply_cookie, + strna(m->root_container.signature), + strna(m->error.name), + strna(m->error.message)); + + return r; +} + +static int dispatch_wqueue(sd_bus *bus) { + int r, ret = 0; + + assert(bus); + assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO)); + + while (bus->wqueue_size > 0) { + + r = bus_write_message(bus, bus->wqueue[0], &bus->windex); + if (r < 0) + return r; + else if (r == 0) + /* Didn't do anything this time */ + return ret; + else if (bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) { + /* Fully written. Let's drop the entry from + * the queue. + * + * This isn't particularly optimized, but + * well, this is supposed to be our worst-case + * buffer only, and the socket buffer is + * supposed to be our primary buffer, and if + * it got full, then all bets are off + * anyway. */ + + bus->wqueue_size--; + bus_message_unref_queued(bus->wqueue[0], bus); + memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size); + bus->windex = 0; + + ret = 1; + } + } + + return ret; +} + +static int bus_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { + assert(bus); + + return bus_socket_read_message(bus); +} + +int bus_rqueue_make_room(sd_bus *bus) { + assert(bus); + + if (bus->rqueue_size >= BUS_RQUEUE_MAX) + return -ENOBUFS; + + if (!GREEDY_REALLOC(bus->rqueue, bus->rqueue_allocated, bus->rqueue_size + 1)) + return -ENOMEM; + + return 0; +} + +static void rqueue_drop_one(sd_bus *bus, size_t i) { + assert(bus); + assert(i < bus->rqueue_size); + + bus_message_unref_queued(bus->rqueue[i], bus); + memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); + bus->rqueue_size--; +} + +static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **m) { + int r, ret = 0; + + assert(bus); + assert(m); + assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO)); + + /* Note that the priority logic is only available on kdbus, + * where the rqueue is unused. We check the rqueue here + * anyway, because it's simple... */ + + for (;;) { + if (bus->rqueue_size > 0) { + /* Dispatch a queued message */ + *m = sd_bus_message_ref(bus->rqueue[0]); + rqueue_drop_one(bus, 0); + return 1; + } + + /* Try to read a new message */ + r = bus_read_message(bus, hint_priority, priority); + if (r < 0) + return r; + if (r == 0) { + *m = NULL; + return ret; + } + + ret = 1; + } +} + +_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m); + int r; + + assert_return(m, -EINVAL); + + if (!bus) + bus = m->bus; + + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (m->n_fds > 0) { + r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD); + if (r < 0) + return r; + if (r == 0) + return -EOPNOTSUPP; + } + + /* If the cookie number isn't kept, then we know that no reply + * is expected */ + if (!cookie && !m->sealed) + m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; + + r = bus_seal_message(bus, m, 0); + if (r < 0) + return r; + + /* Remarshall if we have to. This will possibly unref the + * message and place a replacement in m */ + r = bus_remarshal_message(bus, &m); + if (r < 0) + return r; + + /* If this is a reply and no reply was requested, then let's + * suppress this, if we can */ + if (m->dont_send) + goto finish; + + if (IN_SET(bus->state, BUS_RUNNING, BUS_HELLO) && bus->wqueue_size <= 0) { + size_t idx = 0; + + r = bus_write_message(bus, m, &idx); + if (r < 0) { + if (ERRNO_IS_DISCONNECT(r)) { + bus_enter_closing(bus); + return -ECONNRESET; + } + + return r; + } + + if (idx < BUS_MESSAGE_SIZE(m)) { + /* Wasn't fully written. So let's remember how + * much was written. Note that the first entry + * of the wqueue array is always allocated so + * that we always can remember how much was + * written. */ + bus->wqueue[0] = bus_message_ref_queued(m, bus); + bus->wqueue_size = 1; + bus->windex = idx; + } + + } else { + /* Just append it to the queue. */ + + if (bus->wqueue_size >= BUS_WQUEUE_MAX) + return -ENOBUFS; + + if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1)) + return -ENOMEM; + + bus->wqueue[bus->wqueue_size++] = bus_message_ref_queued(m, bus); + } + +finish: + if (cookie) + *cookie = BUS_MESSAGE_COOKIE(m); + + return 1; +} + +_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie) { + int r; + + assert_return(m, -EINVAL); + + if (!bus) + bus = m->bus; + + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (!streq_ptr(m->destination, destination)) { + + if (!destination) + return -EEXIST; + + r = sd_bus_message_set_destination(m, destination); + if (r < 0) + return r; + } + + return sd_bus_send(bus, m, cookie); +} + +static usec_t calc_elapse(sd_bus *bus, uint64_t usec) { + assert(bus); + + if (usec == (uint64_t) -1) + return 0; + + /* We start all timeouts the instant we enter BUS_HELLO/BUS_RUNNING state, so that the don't run in parallel + * with any connection setup states. Hence, if a method callback is started earlier than that we just store the + * relative timestamp, and afterwards the absolute one. */ + + if (IN_SET(bus->state, BUS_WATCH_BIND, BUS_OPENING, BUS_AUTHENTICATING)) + return usec; + else + return now(CLOCK_MONOTONIC) + usec; +} + +static int timeout_compare(const void *a, const void *b) { + const struct reply_callback *x = a, *y = b; + + if (x->timeout_usec != 0 && y->timeout_usec == 0) + return -1; + + if (x->timeout_usec == 0 && y->timeout_usec != 0) + return 1; + + return CMP(x->timeout_usec, y->timeout_usec); +} + +_public_ int sd_bus_call_async( + sd_bus *bus, + sd_bus_slot **slot, + sd_bus_message *_m, + sd_bus_message_handler_t callback, + void *userdata, + uint64_t usec) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m); + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *s = NULL; + int r; + + assert_return(m, -EINVAL); + assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); + assert_return(!m->sealed || (!!callback == !(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)), -EINVAL); + + if (!bus) + bus = m->bus; + + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + /* If no callback is specified and there's no interest in a slot, then there's no reason to ask for a reply */ + if (!callback && !slot && !m->sealed) + m->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; + + r = ordered_hashmap_ensure_allocated(&bus->reply_callbacks, &uint64_hash_ops); + if (r < 0) + return r; + + r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare); + if (r < 0) + return r; + + r = bus_seal_message(bus, m, usec); + if (r < 0) + return r; + + r = bus_remarshal_message(bus, &m); + if (r < 0) + return r; + + if (slot || callback) { + s = bus_slot_allocate(bus, !slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata); + if (!s) + return -ENOMEM; + + s->reply_callback.callback = callback; + + s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m); + r = ordered_hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback); + if (r < 0) { + s->reply_callback.cookie = 0; + return r; + } + + s->reply_callback.timeout_usec = calc_elapse(bus, m->timeout); + if (s->reply_callback.timeout_usec != 0) { + r = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx); + if (r < 0) { + s->reply_callback.timeout_usec = 0; + return r; + } + } + } + + r = sd_bus_send(bus, m, s ? &s->reply_callback.cookie : NULL); + if (r < 0) + return r; + + if (slot) + *slot = s; + s = NULL; + + return r; +} + +int bus_ensure_running(sd_bus *bus) { + int r; + + assert(bus); + + if (IN_SET(bus->state, BUS_UNSET, BUS_CLOSED, BUS_CLOSING)) + return -ENOTCONN; + if (bus->state == BUS_RUNNING) + return 1; + + for (;;) { + r = sd_bus_process(bus, NULL); + if (r < 0) + return r; + if (bus->state == BUS_RUNNING) + return 1; + if (r > 0) + continue; + + r = sd_bus_wait(bus, (uint64_t) -1); + if (r < 0) + return r; + } +} + +_public_ int sd_bus_call( + sd_bus *bus, + sd_bus_message *_m, + uint64_t usec, + sd_bus_error *error, + sd_bus_message **reply) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m); + usec_t timeout; + uint64_t cookie; + size_t i; + int r; + + bus_assert_return(m, -EINVAL, error); + bus_assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL, error); + bus_assert_return(!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL, error); + bus_assert_return(!bus_error_is_dirty(error), -EINVAL, error); + + if (!bus) + bus = m->bus; + + bus_assert_return(!bus_pid_changed(bus), -ECHILD, error); + + if (!BUS_IS_OPEN(bus->state)) { + r = -ENOTCONN; + goto fail; + } + + r = bus_ensure_running(bus); + if (r < 0) + goto fail; + + i = bus->rqueue_size; + + r = bus_seal_message(bus, m, usec); + if (r < 0) + goto fail; + + r = bus_remarshal_message(bus, &m); + if (r < 0) + goto fail; + + r = sd_bus_send(bus, m, &cookie); + if (r < 0) + goto fail; + + timeout = calc_elapse(bus, m->timeout); + + for (;;) { + usec_t left; + + while (i < bus->rqueue_size) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *incoming = NULL; + + incoming = sd_bus_message_ref(bus->rqueue[i]); + + if (incoming->reply_cookie == cookie) { + /* Found a match! */ + + rqueue_drop_one(bus, i); + log_debug_bus_message(incoming); + + if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) { + + if (incoming->n_fds <= 0 || bus->accept_fd) { + if (reply) + *reply = TAKE_PTR(incoming); + + return 1; + } + + return sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry."); + + } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) + return sd_bus_error_copy(error, &incoming->error); + else { + r = -EIO; + goto fail; + } + + } else if (BUS_MESSAGE_COOKIE(incoming) == cookie && + bus->unique_name && + incoming->sender && + streq(bus->unique_name, incoming->sender)) { + + rqueue_drop_one(bus, i); + + /* Our own message? Somebody is trying to send its own client a message, + * let's not dead-lock, let's fail immediately. */ + + r = -ELOOP; + goto fail; + } + + /* Try to read more, right-away */ + i++; + } + + r = bus_read_message(bus, false, 0); + if (r < 0) { + if (ERRNO_IS_DISCONNECT(r)) { + bus_enter_closing(bus); + r = -ECONNRESET; + } + + goto fail; + } + if (r > 0) + continue; + + if (timeout > 0) { + usec_t n; + + n = now(CLOCK_MONOTONIC); + if (n >= timeout) { + r = -ETIMEDOUT; + goto fail; + } + + left = timeout - n; + } else + left = (uint64_t) -1; + + r = bus_poll(bus, true, left); + if (r < 0) + goto fail; + if (r == 0) { + r = -ETIMEDOUT; + goto fail; + } + + r = dispatch_wqueue(bus); + if (r < 0) { + if (ERRNO_IS_DISCONNECT(r)) { + bus_enter_closing(bus); + r = -ECONNRESET; + } + + goto fail; + } + } + +fail: + return sd_bus_error_set_errno(error, r); +} + +_public_ int sd_bus_get_fd(sd_bus *bus) { + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(bus->input_fd == bus->output_fd, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (bus->state == BUS_CLOSED) + return -ENOTCONN; + + if (bus->inotify_fd >= 0) + return bus->inotify_fd; + + if (bus->input_fd >= 0) + return bus->input_fd; + + return -ENOTCONN; +} + +_public_ int sd_bus_get_events(sd_bus *bus) { + int flags = 0; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + switch (bus->state) { + + case BUS_UNSET: + case BUS_CLOSED: + return -ENOTCONN; + + case BUS_WATCH_BIND: + flags |= POLLIN; + break; + + case BUS_OPENING: + flags |= POLLOUT; + break; + + case BUS_AUTHENTICATING: + if (bus_socket_auth_needs_write(bus)) + flags |= POLLOUT; + + flags |= POLLIN; + break; + + case BUS_RUNNING: + case BUS_HELLO: + if (bus->rqueue_size <= 0) + flags |= POLLIN; + if (bus->wqueue_size > 0) + flags |= POLLOUT; + break; + + case BUS_CLOSING: + break; + + default: + assert_not_reached("Unknown state"); + } + + return flags; +} + +_public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) { + struct reply_callback *c; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(timeout_usec, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state) && bus->state != BUS_CLOSING) + return -ENOTCONN; + + if (bus->track_queue) { + *timeout_usec = 0; + return 1; + } + + switch (bus->state) { + + case BUS_AUTHENTICATING: + *timeout_usec = bus->auth_timeout; + return 1; + + case BUS_RUNNING: + case BUS_HELLO: + if (bus->rqueue_size > 0) { + *timeout_usec = 0; + return 1; + } + + c = prioq_peek(bus->reply_callbacks_prioq); + if (!c) { + *timeout_usec = (uint64_t) -1; + return 0; + } + + if (c->timeout_usec == 0) { + *timeout_usec = (uint64_t) -1; + return 0; + } + + *timeout_usec = c->timeout_usec; + return 1; + + case BUS_CLOSING: + *timeout_usec = 0; + return 1; + + case BUS_WATCH_BIND: + case BUS_OPENING: + *timeout_usec = (uint64_t) -1; + return 0; + + default: + assert_not_reached("Unknown or unexpected stat"); + } +} + +static int process_timeout(sd_bus *bus) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* m = NULL; + struct reply_callback *c; + sd_bus_slot *slot; + bool is_hello; + usec_t n; + int r; + + assert(bus); + assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO)); + + c = prioq_peek(bus->reply_callbacks_prioq); + if (!c) + return 0; + + n = now(CLOCK_MONOTONIC); + if (c->timeout_usec > n) + return 0; + + r = bus_message_new_synthetic_error( + bus, + c->cookie, + &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out"), + &m); + if (r < 0) + return r; + + m->read_counter = ++bus->read_counter; + + r = bus_seal_synthetic_message(bus, m); + if (r < 0) + return r; + + assert_se(prioq_pop(bus->reply_callbacks_prioq) == c); + c->timeout_usec = 0; + + ordered_hashmap_remove(bus->reply_callbacks, &c->cookie); + c->cookie = 0; + + slot = container_of(c, sd_bus_slot, reply_callback); + + bus->iteration_counter++; + + is_hello = bus->state == BUS_HELLO && c->callback == hello_callback; + + bus->current_message = m; + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_handler = c->callback; + bus->current_userdata = slot->userdata; + r = c->callback(m, slot->userdata, &error_buffer); + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = NULL; + bus->current_message = NULL; + + if (slot->floating) + bus_slot_disconnect(slot, true); + + sd_bus_slot_unref(slot); + + /* When this is the hello message and it timed out, then make sure to propagate the error up, don't just log + * and ignore the callback handler's return value. */ + if (is_hello) + return r; + + return bus_maybe_reply_error(m, r, &error_buffer); +} + +static int process_hello(sd_bus *bus, sd_bus_message *m) { + assert(bus); + assert(m); + + if (bus->state != BUS_HELLO) + return 0; + + /* Let's make sure the first message on the bus is the HELLO + * reply. But note that we don't actually parse the message + * here (we leave that to the usual handling), we just verify + * we don't let any earlier msg through. */ + + if (!IN_SET(m->header->type, SD_BUS_MESSAGE_METHOD_RETURN, SD_BUS_MESSAGE_METHOD_ERROR)) + return -EIO; + + if (m->reply_cookie != 1) + return -EIO; + + return 0; +} + +static int process_reply(sd_bus *bus, sd_bus_message *m) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *synthetic_reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + struct reply_callback *c; + sd_bus_slot *slot; + bool is_hello; + int r; + + assert(bus); + assert(m); + + if (!IN_SET(m->header->type, SD_BUS_MESSAGE_METHOD_RETURN, SD_BUS_MESSAGE_METHOD_ERROR)) + return 0; + + if (m->destination && bus->unique_name && !streq_ptr(m->destination, bus->unique_name)) + return 0; + + c = ordered_hashmap_remove(bus->reply_callbacks, &m->reply_cookie); + if (!c) + return 0; + + c->cookie = 0; + + slot = container_of(c, sd_bus_slot, reply_callback); + + if (m->n_fds > 0 && !bus->accept_fd) { + + /* If the reply contained a file descriptor which we + * didn't want we pass an error instead. */ + + r = bus_message_new_synthetic_error( + bus, + m->reply_cookie, + &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptor"), + &synthetic_reply); + if (r < 0) + return r; + + /* Copy over original timestamp */ + synthetic_reply->realtime = m->realtime; + synthetic_reply->monotonic = m->monotonic; + synthetic_reply->seqnum = m->seqnum; + synthetic_reply->read_counter = m->read_counter; + + r = bus_seal_synthetic_message(bus, synthetic_reply); + if (r < 0) + return r; + + m = synthetic_reply; + } else { + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + } + + if (c->timeout_usec != 0) { + prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); + c->timeout_usec = 0; + } + + is_hello = bus->state == BUS_HELLO && c->callback == hello_callback; + + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_handler = c->callback; + bus->current_userdata = slot->userdata; + r = c->callback(m, slot->userdata, &error_buffer); + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = NULL; + + if (slot->floating) + bus_slot_disconnect(slot, true); + + sd_bus_slot_unref(slot); + + /* When this is the hello message and it failed, then make sure to propagate the error up, don't just log and + * ignore the callback handler's return value. */ + if (is_hello) + return r; + + return bus_maybe_reply_error(m, r, &error_buffer); +} + +static int process_filter(sd_bus *bus, sd_bus_message *m) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + struct filter_callback *l; + int r; + + assert(bus); + assert(m); + + do { + bus->filter_callbacks_modified = false; + + LIST_FOREACH(callbacks, l, bus->filter_callbacks) { + sd_bus_slot *slot; + + if (bus->filter_callbacks_modified) + break; + + /* Don't run this more than once per iteration */ + if (l->last_iteration == bus->iteration_counter) + continue; + + l->last_iteration = bus->iteration_counter; + + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + slot = container_of(l, sd_bus_slot, filter_callback); + + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_handler = l->callback; + bus->current_userdata = slot->userdata; + r = l->callback(m, slot->userdata, &error_buffer); + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = sd_bus_slot_unref(slot); + + r = bus_maybe_reply_error(m, r, &error_buffer); + if (r != 0) + return r; + + } + + } while (bus->filter_callbacks_modified); + + return 0; +} + +static int process_match(sd_bus *bus, sd_bus_message *m) { + int r; + + assert(bus); + assert(m); + + do { + bus->match_callbacks_modified = false; + + r = bus_match_run(bus, &bus->match_callbacks, m); + if (r != 0) + return r; + + } while (bus->match_callbacks_modified); + + return 0; +} + +static int process_builtin(sd_bus *bus, sd_bus_message *m) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + assert(bus); + assert(m); + + if (bus->is_monitor) + return 0; + + if (bus->manual_peer_interface) + return 0; + + if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL) + return 0; + + if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer")) + return 0; + + if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) + return 1; + + if (streq_ptr(m->member, "Ping")) + r = sd_bus_message_new_method_return(m, &reply); + else if (streq_ptr(m->member, "GetMachineId")) { + sd_id128_t id; + char sid[33]; + + r = sd_id128_get_machine(&id); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid)); + } else { + r = sd_bus_message_new_method_errorf( + m, &reply, + SD_BUS_ERROR_UNKNOWN_METHOD, + "Unknown method '%s' on interface '%s'.", m->member, m->interface); + } + if (r < 0) + return r; + + r = sd_bus_send(bus, reply, NULL); + if (r < 0) + return r; + + return 1; +} + +static int process_fd_check(sd_bus *bus, sd_bus_message *m) { + assert(bus); + assert(m); + + /* If we got a message with a file descriptor which we didn't + * want to accept, then let's drop it. How can this even + * happen? For example, when the kernel queues a message into + * an activatable names's queue which allows fds, and then is + * delivered to us later even though we ourselves did not + * negotiate it. */ + + if (bus->is_monitor) + return 0; + + if (m->n_fds <= 0) + return 0; + + if (bus->accept_fd) + return 0; + + if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL) + return 1; /* just eat it up */ + + return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Message contains file descriptors, which I cannot accept. Sorry."); +} + +static int process_message(sd_bus *bus, sd_bus_message *m) { + int r; + + assert(bus); + assert(m); + + bus->current_message = m; + bus->iteration_counter++; + + log_debug_bus_message(m); + + r = process_hello(bus, m); + if (r != 0) + goto finish; + + r = process_reply(bus, m); + if (r != 0) + goto finish; + + r = process_fd_check(bus, m); + if (r != 0) + goto finish; + + r = process_filter(bus, m); + if (r != 0) + goto finish; + + r = process_match(bus, m); + if (r != 0) + goto finish; + + r = process_builtin(bus, m); + if (r != 0) + goto finish; + + r = bus_process_object(bus, m); + +finish: + bus->current_message = NULL; + return r; +} + +static int dispatch_track(sd_bus *bus) { + assert(bus); + + if (!bus->track_queue) + return 0; + + bus_track_dispatch(bus->track_queue); + return 1; +} + +static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + assert(bus); + assert(IN_SET(bus->state, BUS_RUNNING, BUS_HELLO)); + + r = process_timeout(bus); + if (r != 0) + goto null_message; + + r = dispatch_wqueue(bus); + if (r != 0) + goto null_message; + + r = dispatch_track(bus); + if (r != 0) + goto null_message; + + r = dispatch_rqueue(bus, hint_priority, priority, &m); + if (r < 0) + return r; + if (!m) + goto null_message; + + r = process_message(bus, m); + if (r != 0) + goto null_message; + + if (ret) { + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + *ret = TAKE_PTR(m); + return 1; + } + + if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) { + + log_debug("Unprocessed message call sender=%s object=%s interface=%s member=%s", + strna(sd_bus_message_get_sender(m)), + strna(sd_bus_message_get_path(m)), + strna(sd_bus_message_get_interface(m)), + strna(sd_bus_message_get_member(m))); + + r = sd_bus_reply_method_errorf( + m, + SD_BUS_ERROR_UNKNOWN_OBJECT, + "Unknown object '%s'.", m->path); + if (r < 0) + return r; + } + + return 1; + +null_message: + if (r >= 0 && ret) + *ret = NULL; + + return r; +} + +static int bus_exit_now(sd_bus *bus) { + assert(bus); + + /* Exit due to close, if this is requested. If this is bus object is attached to an event source, invokes + * sd_event_exit(), otherwise invokes libc exit(). */ + + if (bus->exited) /* did we already exit? */ + return 0; + if (!bus->exit_triggered) /* was the exit condition triggered? */ + return 0; + if (!bus->exit_on_disconnect) /* Shall we actually exit on disconnection? */ + return 0; + + bus->exited = true; /* never exit more than once */ + + log_debug("Bus connection disconnected, exiting."); + + if (bus->event) + return sd_event_exit(bus->event, EXIT_FAILURE); + else + exit(EXIT_FAILURE); + + assert_not_reached("exit() didn't exit?"); +} + +static int process_closing_reply_callback(sd_bus *bus, struct reply_callback *c) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + sd_bus_slot *slot; + int r; + + assert(bus); + assert(c); + + r = bus_message_new_synthetic_error( + bus, + c->cookie, + &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"), + &m); + if (r < 0) + return r; + + m->read_counter = ++bus->read_counter; + + r = bus_seal_synthetic_message(bus, m); + if (r < 0) + return r; + + if (c->timeout_usec != 0) { + prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); + c->timeout_usec = 0; + } + + ordered_hashmap_remove(bus->reply_callbacks, &c->cookie); + c->cookie = 0; + + slot = container_of(c, sd_bus_slot, reply_callback); + + bus->iteration_counter++; + + bus->current_message = m; + bus->current_slot = sd_bus_slot_ref(slot); + bus->current_handler = c->callback; + bus->current_userdata = slot->userdata; + r = c->callback(m, slot->userdata, &error_buffer); + bus->current_userdata = NULL; + bus->current_handler = NULL; + bus->current_slot = NULL; + bus->current_message = NULL; + + if (slot->floating) + bus_slot_disconnect(slot, true); + + sd_bus_slot_unref(slot); + + return bus_maybe_reply_error(m, r, &error_buffer); +} + +static int process_closing(sd_bus *bus, sd_bus_message **ret) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + struct reply_callback *c; + int r; + + assert(bus); + assert(bus->state == BUS_CLOSING); + + /* First, fail all outstanding method calls */ + c = ordered_hashmap_first(bus->reply_callbacks); + if (c) + return process_closing_reply_callback(bus, c); + + /* Then, fake-drop all remaining bus tracking references */ + if (bus->tracks) { + bus_track_close(bus->tracks); + return 1; + } + + /* Then, synthesize a Disconnected message */ + r = sd_bus_message_new_signal( + bus, + &m, + "/org/freedesktop/DBus/Local", + "org.freedesktop.DBus.Local", + "Disconnected"); + if (r < 0) + return r; + + bus_message_set_sender_local(bus, m); + m->read_counter = ++bus->read_counter; + + r = bus_seal_synthetic_message(bus, m); + if (r < 0) + return r; + + sd_bus_close(bus); + + bus->current_message = m; + bus->iteration_counter++; + + r = process_filter(bus, m); + if (r != 0) + goto finish; + + r = process_match(bus, m); + if (r != 0) + goto finish; + + /* Nothing else to do, exit now, if the condition holds */ + bus->exit_triggered = true; + (void) bus_exit_now(bus); + + if (ret) + *ret = TAKE_PTR(m); + + r = 1; + +finish: + bus->current_message = NULL; + + return r; +} + +static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **ret) { + int r; + + /* Returns 0 when we didn't do anything. This should cause the + * caller to invoke sd_bus_wait() before returning the next + * time. Returns > 0 when we did something, which possibly + * means *ret is filled in with an unprocessed message. */ + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + /* We don't allow recursively invoking sd_bus_process(). */ + assert_return(!bus->current_message, -EBUSY); + assert(!bus->current_slot); /* This should be NULL whenever bus->current_message is */ + + BUS_DONT_DESTROY(bus); + + switch (bus->state) { + + case BUS_UNSET: + return -ENOTCONN; + + case BUS_CLOSED: + return -ECONNRESET; + + case BUS_WATCH_BIND: + r = bus_socket_process_watch_bind(bus); + break; + + case BUS_OPENING: + r = bus_socket_process_opening(bus); + break; + + case BUS_AUTHENTICATING: + r = bus_socket_process_authenticating(bus); + break; + + case BUS_RUNNING: + case BUS_HELLO: + r = process_running(bus, hint_priority, priority, ret); + if (r >= 0) + return r; + + /* This branch initializes *ret, hence we don't use the generic error checking below */ + break; + + case BUS_CLOSING: + return process_closing(bus, ret); + + default: + assert_not_reached("Unknown state"); + } + + if (ERRNO_IS_DISCONNECT(r)) { + bus_enter_closing(bus); + r = 1; + } else if (r < 0) + return r; + + if (ret) + *ret = NULL; + + return r; +} + +_public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) { + return bus_process_internal(bus, false, 0, ret); +} + +_public_ int sd_bus_process_priority(sd_bus *bus, int64_t priority, sd_bus_message **ret) { + return bus_process_internal(bus, true, priority, ret); +} + +static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) { + struct pollfd p[2] = {}; + int r, n; + struct timespec ts; + usec_t m = USEC_INFINITY; + + assert(bus); + + if (bus->state == BUS_CLOSING) + return 1; + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (bus->state == BUS_WATCH_BIND) { + assert(bus->inotify_fd >= 0); + + p[0].events = POLLIN; + p[0].fd = bus->inotify_fd; + n = 1; + } else { + int e; + + e = sd_bus_get_events(bus); + if (e < 0) + return e; + + if (need_more) + /* The caller really needs some more data, he doesn't + * care about what's already read, or any timeouts + * except its own. */ + e |= POLLIN; + else { + usec_t until; + /* The caller wants to process if there's something to + * process, but doesn't care otherwise */ + + r = sd_bus_get_timeout(bus, &until); + if (r < 0) + return r; + if (r > 0) + m = usec_sub_unsigned(until, now(CLOCK_MONOTONIC)); + } + + p[0].fd = bus->input_fd; + if (bus->output_fd == bus->input_fd) { + p[0].events = e; + n = 1; + } else { + p[0].events = e & POLLIN; + p[1].fd = bus->output_fd; + p[1].events = e & POLLOUT; + n = 2; + } + } + + if (timeout_usec != (uint64_t) -1 && (m == USEC_INFINITY || timeout_usec < m)) + m = timeout_usec; + + r = ppoll(p, n, m == USEC_INFINITY ? NULL : timespec_store(&ts, m), NULL); + if (r < 0) + return -errno; + + return r > 0 ? 1 : 0; +} + +_public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) { + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (bus->state == BUS_CLOSING) + return 0; + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + if (bus->rqueue_size > 0) + return 0; + + return bus_poll(bus, false, timeout_usec); +} + +_public_ int sd_bus_flush(sd_bus *bus) { + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (bus->state == BUS_CLOSING) + return 0; + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + /* We never were connected? Don't hang in inotify for good, as there's no timeout set for it */ + if (bus->state == BUS_WATCH_BIND) + return -EUNATCH; + + r = bus_ensure_running(bus); + if (r < 0) + return r; + + if (bus->wqueue_size <= 0) + return 0; + + for (;;) { + r = dispatch_wqueue(bus); + if (r < 0) { + if (ERRNO_IS_DISCONNECT(r)) { + bus_enter_closing(bus); + return -ECONNRESET; + } + + return r; + } + + if (bus->wqueue_size <= 0) + return 0; + + r = bus_poll(bus, false, (uint64_t) -1); + if (r < 0) + return r; + } +} + +_public_ int sd_bus_add_filter( + sd_bus *bus, + sd_bus_slot **slot, + sd_bus_message_handler_t callback, + void *userdata) { + + sd_bus_slot *s; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(callback, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + s = bus_slot_allocate(bus, !slot, BUS_FILTER_CALLBACK, sizeof(struct filter_callback), userdata); + if (!s) + return -ENOMEM; + + s->filter_callback.callback = callback; + + bus->filter_callbacks_modified = true; + LIST_PREPEND(callbacks, bus->filter_callbacks, &s->filter_callback); + + if (slot) + *slot = s; + + return 0; +} + +static int add_match_callback( + sd_bus_message *m, + void *userdata, + sd_bus_error *ret_error) { + + sd_bus_slot *match_slot = userdata; + bool failed = false; + int r; + + assert(m); + assert(match_slot); + + sd_bus_slot_ref(match_slot); + + if (sd_bus_message_is_method_error(m, NULL)) { + log_debug_errno(sd_bus_message_get_errno(m), + "Unable to add match %s, failing connection: %s", + match_slot->match_callback.match_string, + sd_bus_message_get_error(m)->message); + + failed = true; + } else + log_debug("Match %s successfully installed.", match_slot->match_callback.match_string); + + if (match_slot->match_callback.install_callback) { + sd_bus *bus; + + bus = sd_bus_message_get_bus(m); + + /* This function has been called as slot handler, and we want to call another slot handler. Let's + * update the slot callback metadata temporarily with our own data, and then revert back to the old + * values. */ + + assert(bus->current_slot == match_slot->match_callback.install_slot); + assert(bus->current_handler == add_match_callback); + assert(bus->current_userdata == userdata); + + bus->current_slot = match_slot; + bus->current_handler = match_slot->match_callback.install_callback; + bus->current_userdata = match_slot->userdata; + + r = match_slot->match_callback.install_callback(m, match_slot->userdata, ret_error); + + bus->current_slot = match_slot->match_callback.install_slot; + bus->current_handler = add_match_callback; + bus->current_userdata = userdata; + } else { + if (failed) /* Generic failure handling: destroy the connection */ + bus_enter_closing(sd_bus_message_get_bus(m)); + + r = 1; + } + + /* We don't need the install method reply slot anymore, let's free it */ + match_slot->match_callback.install_slot = sd_bus_slot_unref(match_slot->match_callback.install_slot); + + if (failed && match_slot->floating) + bus_slot_disconnect(match_slot, true); + + sd_bus_slot_unref(match_slot); + + return r; +} + +static int bus_add_match_full( + sd_bus *bus, + sd_bus_slot **slot, + bool asynchronous, + const char *match, + sd_bus_message_handler_t callback, + sd_bus_message_handler_t install_callback, + void *userdata) { + + struct bus_match_component *components = NULL; + unsigned n_components = 0; + sd_bus_slot *s = NULL; + int r = 0; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(match, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + r = bus_match_parse(match, &components, &n_components); + if (r < 0) + goto finish; + + s = bus_slot_allocate(bus, !slot, BUS_MATCH_CALLBACK, sizeof(struct match_callback), userdata); + if (!s) { + r = -ENOMEM; + goto finish; + } + + s->match_callback.callback = callback; + s->match_callback.install_callback = install_callback; + + if (bus->bus_client) { + enum bus_match_scope scope; + + scope = bus_match_get_scope(components, n_components); + + /* Do not install server-side matches for matches against the local service, interface or bus path. */ + if (scope != BUS_MATCH_LOCAL) { + + /* We store the original match string, so that we can use it to remove the match again. */ + + s->match_callback.match_string = strdup(match); + if (!s->match_callback.match_string) { + r = -ENOMEM; + goto finish; + } + + if (asynchronous) { + r = bus_add_match_internal_async(bus, + &s->match_callback.install_slot, + s->match_callback.match_string, + add_match_callback, + s); + + if (r < 0) + return r; + + /* Make the slot of the match call floating now. We need the reference, but we don't + * want that this match pins the bus object, hence we first create it non-floating, but + * then make it floating. */ + r = sd_bus_slot_set_floating(s->match_callback.install_slot, true); + } else + r = bus_add_match_internal(bus, s->match_callback.match_string, &s->match_callback.after); + if (r < 0) + goto finish; + + s->match_added = true; + } + } + + bus->match_callbacks_modified = true; + r = bus_match_add(&bus->match_callbacks, components, n_components, &s->match_callback); + if (r < 0) + goto finish; + + if (slot) + *slot = s; + s = NULL; + +finish: + bus_match_parse_free(components, n_components); + sd_bus_slot_unref(s); + + return r; +} + +_public_ int sd_bus_add_match( + sd_bus *bus, + sd_bus_slot **slot, + const char *match, + sd_bus_message_handler_t callback, + void *userdata) { + + return bus_add_match_full(bus, slot, false, match, callback, NULL, userdata); +} + +_public_ int sd_bus_add_match_async( + sd_bus *bus, + sd_bus_slot **slot, + const char *match, + sd_bus_message_handler_t callback, + sd_bus_message_handler_t install_callback, + void *userdata) { + + return bus_add_match_full(bus, slot, true, match, callback, install_callback, userdata); +} + +bool bus_pid_changed(sd_bus *bus) { + assert(bus); + + /* We don't support people creating a bus connection and + * keeping it around over a fork(). Let's complain. */ + + return bus->original_pid != getpid_cached(); +} + +static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + sd_bus *bus = userdata; + int r; + + assert(bus); + + /* Note that this is called both on input_fd, output_fd as well as inotify_fd events */ + + r = sd_bus_process(bus, NULL); + if (r < 0) { + log_debug_errno(r, "Processing of bus failed, closing down: %m"); + bus_enter_closing(bus); + } + + return 1; +} + +static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) { + sd_bus *bus = userdata; + int r; + + assert(bus); + + r = sd_bus_process(bus, NULL); + if (r < 0) { + log_debug_errno(r, "Processing of bus failed, closing down: %m"); + bus_enter_closing(bus); + } + + return 1; +} + +static int prepare_callback(sd_event_source *s, void *userdata) { + sd_bus *bus = userdata; + int r, e; + usec_t until; + + assert(s); + assert(bus); + + e = sd_bus_get_events(bus); + if (e < 0) { + r = e; + goto fail; + } + + if (bus->output_fd != bus->input_fd) { + + r = sd_event_source_set_io_events(bus->input_io_event_source, e & POLLIN); + if (r < 0) + goto fail; + + r = sd_event_source_set_io_events(bus->output_io_event_source, e & POLLOUT); + } else + r = sd_event_source_set_io_events(bus->input_io_event_source, e); + if (r < 0) + goto fail; + + r = sd_bus_get_timeout(bus, &until); + if (r < 0) + goto fail; + if (r > 0) { + int j; + + j = sd_event_source_set_time(bus->time_event_source, until); + if (j < 0) { + r = j; + goto fail; + } + } + + r = sd_event_source_set_enabled(bus->time_event_source, r > 0); + if (r < 0) + goto fail; + + return 1; + +fail: + log_debug_errno(r, "Preparing of bus events failed, closing down: %m"); + bus_enter_closing(bus); + + return 1; +} + +static int quit_callback(sd_event_source *event, void *userdata) { + sd_bus *bus = userdata; + + assert(event); + + if (bus->close_on_exit) { + sd_bus_flush(bus); + sd_bus_close(bus); + } + + return 1; +} + +int bus_attach_io_events(sd_bus *bus) { + int r; + + assert(bus); + + if (bus->input_fd < 0) + return 0; + + if (!bus->event) + return 0; + + if (!bus->input_io_event_source) { + r = sd_event_add_io(bus->event, &bus->input_io_event_source, bus->input_fd, 0, io_callback, bus); + if (r < 0) + return r; + + r = sd_event_source_set_prepare(bus->input_io_event_source, prepare_callback); + if (r < 0) + return r; + + r = sd_event_source_set_priority(bus->input_io_event_source, bus->event_priority); + if (r < 0) + return r; + + r = sd_event_source_set_description(bus->input_io_event_source, "bus-input"); + } else + r = sd_event_source_set_io_fd(bus->input_io_event_source, bus->input_fd); + + if (r < 0) + return r; + + if (bus->output_fd != bus->input_fd) { + assert(bus->output_fd >= 0); + + if (!bus->output_io_event_source) { + r = sd_event_add_io(bus->event, &bus->output_io_event_source, bus->output_fd, 0, io_callback, bus); + if (r < 0) + return r; + + r = sd_event_source_set_priority(bus->output_io_event_source, bus->event_priority); + if (r < 0) + return r; + + r = sd_event_source_set_description(bus->input_io_event_source, "bus-output"); + } else + r = sd_event_source_set_io_fd(bus->output_io_event_source, bus->output_fd); + + if (r < 0) + return r; + } + + return 0; +} + +static void bus_detach_io_events(sd_bus *bus) { + assert(bus); + + if (bus->input_io_event_source) { + sd_event_source_set_enabled(bus->input_io_event_source, SD_EVENT_OFF); + bus->input_io_event_source = sd_event_source_unref(bus->input_io_event_source); + } + + if (bus->output_io_event_source) { + sd_event_source_set_enabled(bus->output_io_event_source, SD_EVENT_OFF); + bus->output_io_event_source = sd_event_source_unref(bus->output_io_event_source); + } +} + +int bus_attach_inotify_event(sd_bus *bus) { + int r; + + assert(bus); + + if (bus->inotify_fd < 0) + return 0; + + if (!bus->event) + return 0; + + if (!bus->inotify_event_source) { + r = sd_event_add_io(bus->event, &bus->inotify_event_source, bus->inotify_fd, EPOLLIN, io_callback, bus); + if (r < 0) + return r; + + r = sd_event_source_set_priority(bus->inotify_event_source, bus->event_priority); + if (r < 0) + return r; + + r = sd_event_source_set_description(bus->inotify_event_source, "bus-inotify"); + } else + r = sd_event_source_set_io_fd(bus->inotify_event_source, bus->inotify_fd); + if (r < 0) + return r; + + return 0; +} + +static void bus_detach_inotify_event(sd_bus *bus) { + assert(bus); + + if (bus->inotify_event_source) { + sd_event_source_set_enabled(bus->inotify_event_source, SD_EVENT_OFF); + bus->inotify_event_source = sd_event_source_unref(bus->inotify_event_source); + } +} + +_public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) { + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus->event, -EBUSY); + + assert(!bus->input_io_event_source); + assert(!bus->output_io_event_source); + assert(!bus->time_event_source); + + if (event) + bus->event = sd_event_ref(event); + else { + r = sd_event_default(&bus->event); + if (r < 0) + return r; + } + + bus->event_priority = priority; + + r = sd_event_add_time(bus->event, &bus->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, bus); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(bus->time_event_source, priority); + if (r < 0) + goto fail; + + r = sd_event_source_set_description(bus->time_event_source, "bus-time"); + if (r < 0) + goto fail; + + r = sd_event_add_exit(bus->event, &bus->quit_event_source, quit_callback, bus); + if (r < 0) + goto fail; + + r = sd_event_source_set_description(bus->quit_event_source, "bus-exit"); + if (r < 0) + goto fail; + + r = bus_attach_io_events(bus); + if (r < 0) + goto fail; + + r = bus_attach_inotify_event(bus); + if (r < 0) + goto fail; + + return 0; + +fail: + sd_bus_detach_event(bus); + return r; +} + +_public_ int sd_bus_detach_event(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + + if (!bus->event) + return 0; + + bus_detach_io_events(bus); + bus_detach_inotify_event(bus); + + if (bus->time_event_source) { + sd_event_source_set_enabled(bus->time_event_source, SD_EVENT_OFF); + bus->time_event_source = sd_event_source_unref(bus->time_event_source); + } + + if (bus->quit_event_source) { + sd_event_source_set_enabled(bus->quit_event_source, SD_EVENT_OFF); + bus->quit_event_source = sd_event_source_unref(bus->quit_event_source); + } + + bus->event = sd_event_unref(bus->event); + return 1; +} + +_public_ sd_event* sd_bus_get_event(sd_bus *bus) { + assert_return(bus, NULL); + + return bus->event; +} + +_public_ sd_bus_message* sd_bus_get_current_message(sd_bus *bus) { + assert_return(bus, NULL); + + return bus->current_message; +} + +_public_ sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus) { + assert_return(bus, NULL); + + return bus->current_slot; +} + +_public_ sd_bus_message_handler_t sd_bus_get_current_handler(sd_bus *bus) { + assert_return(bus, NULL); + + return bus->current_handler; +} + +_public_ void* sd_bus_get_current_userdata(sd_bus *bus) { + assert_return(bus, NULL); + + return bus->current_userdata; +} + +static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus **ret) { + sd_bus *b = NULL; + int r; + + assert(bus_open); + assert(default_bus); + + if (!ret) + return !!*default_bus; + + if (*default_bus) { + *ret = sd_bus_ref(*default_bus); + return 0; + } + + r = bus_open(&b); + if (r < 0) + return r; + + b->default_bus_ptr = default_bus; + b->tid = gettid(); + *default_bus = b; + + *ret = b; + return 1; +} + +_public_ int sd_bus_default_system(sd_bus **ret) { + return bus_default(sd_bus_open_system, &default_system_bus, ret); +} + +_public_ int sd_bus_default_user(sd_bus **ret) { + return bus_default(sd_bus_open_user, &default_user_bus, ret); +} + +_public_ int sd_bus_default(sd_bus **ret) { + int (*bus_open)(sd_bus **) = NULL; + sd_bus **busp; + + busp = bus_choose_default(&bus_open); + return bus_default(bus_open, busp, ret); +} + +_public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) { + assert_return(b, -EINVAL); + assert_return(tid, -EINVAL); + assert_return(!bus_pid_changed(b), -ECHILD); + + if (b->tid != 0) { + *tid = b->tid; + return 0; + } + + if (b->event) + return sd_event_get_tid(b->event, tid); + + return -ENXIO; +} + +_public_ int sd_bus_path_encode(const char *prefix, const char *external_id, char **ret_path) { + _cleanup_free_ char *e = NULL; + char *ret; + + assert_return(object_path_is_valid(prefix), -EINVAL); + assert_return(external_id, -EINVAL); + assert_return(ret_path, -EINVAL); + + e = bus_label_escape(external_id); + if (!e) + return -ENOMEM; + + ret = path_join(prefix, e); + if (!ret) + return -ENOMEM; + + *ret_path = ret; + return 0; +} + +_public_ int sd_bus_path_decode(const char *path, const char *prefix, char **external_id) { + const char *e; + char *ret; + + assert_return(object_path_is_valid(path), -EINVAL); + assert_return(object_path_is_valid(prefix), -EINVAL); + assert_return(external_id, -EINVAL); + + e = object_path_startswith(path, prefix); + if (!e) { + *external_id = NULL; + return 0; + } + + ret = bus_label_unescape(e); + if (!ret) + return -ENOMEM; + + *external_id = ret; + return 1; +} + +_public_ int sd_bus_path_encode_many(char **out, const char *path_template, ...) { + _cleanup_strv_free_ char **labels = NULL; + char *path, *path_pos, **label_pos; + const char *sep, *template_pos; + size_t path_length; + va_list list; + int r; + + assert_return(out, -EINVAL); + assert_return(path_template, -EINVAL); + + path_length = strlen(path_template); + + va_start(list, path_template); + for (sep = strchr(path_template, '%'); sep; sep = strchr(sep + 1, '%')) { + const char *arg; + char *label; + + arg = va_arg(list, const char *); + if (!arg) { + va_end(list); + return -EINVAL; + } + + label = bus_label_escape(arg); + if (!label) { + va_end(list); + return -ENOMEM; + } + + r = strv_consume(&labels, label); + if (r < 0) { + va_end(list); + return r; + } + + /* add label length, but account for the format character */ + path_length += strlen(label) - 1; + } + va_end(list); + + path = malloc(path_length + 1); + if (!path) + return -ENOMEM; + + path_pos = path; + label_pos = labels; + + for (template_pos = path_template; *template_pos; ) { + sep = strchrnul(template_pos, '%'); + path_pos = mempcpy(path_pos, template_pos, sep - template_pos); + if (!*sep) + break; + + path_pos = stpcpy(path_pos, *label_pos++); + template_pos = sep + 1; + } + + *path_pos = 0; + *out = path; + return 0; +} + +_public_ int sd_bus_path_decode_many(const char *path, const char *path_template, ...) { + _cleanup_strv_free_ char **labels = NULL; + const char *template_pos, *path_pos; + char **label_pos; + va_list list; + int r; + + /* + * This decodes an object-path based on a template argument. The + * template consists of a verbatim path, optionally including special + * directives: + * + * - Each occurrence of '%' in the template matches an arbitrary + * substring of a label in the given path. At most one such + * directive is allowed per label. For each such directive, the + * caller must provide an output parameter (char **) via va_arg. If + * NULL is passed, the given label is verified, but not returned. + * For each matched label, the *decoded* label is stored in the + * passed output argument, and the caller is responsible to free + * it. Note that the output arguments are only modified if the + * actually path matched the template. Otherwise, they're left + * untouched. + * + * This function returns <0 on error, 0 if the path does not match the + * template, 1 if it matched. + */ + + assert_return(path, -EINVAL); + assert_return(path_template, -EINVAL); + + path_pos = path; + + for (template_pos = path_template; *template_pos; ) { + const char *sep; + size_t length; + char *label; + + /* verify everything until the next '%' matches verbatim */ + sep = strchrnul(template_pos, '%'); + length = sep - template_pos; + if (strncmp(path_pos, template_pos, length)) + return 0; + + path_pos += length; + template_pos += length; + + if (!*template_pos) + break; + + /* We found the next '%' character. Everything up until here + * matched. We now skip ahead to the end of this label and make + * sure it matches the tail of the label in the path. Then we + * decode the string in-between and save it for later use. */ + + ++template_pos; /* skip over '%' */ + + sep = strchrnul(template_pos, '/'); + length = sep - template_pos; /* length of suffix to match verbatim */ + + /* verify the suffixes match */ + sep = strchrnul(path_pos, '/'); + if (sep - path_pos < (ssize_t)length || + strncmp(sep - length, template_pos, length)) + return 0; + + template_pos += length; /* skip over matched label */ + length = sep - path_pos - length; /* length of sub-label to decode */ + + /* store unescaped label for later use */ + label = bus_label_unescape_n(path_pos, length); + if (!label) + return -ENOMEM; + + r = strv_consume(&labels, label); + if (r < 0) + return r; + + path_pos = sep; /* skip decoded label and suffix */ + } + + /* end of template must match end of path */ + if (*path_pos) + return 0; + + /* copy the labels over to the caller */ + va_start(list, path_template); + for (label_pos = labels; label_pos && *label_pos; ++label_pos) { + char **arg; + + arg = va_arg(list, char **); + if (arg) + *arg = *label_pos; + else + free(*label_pos); + } + va_end(list); + + labels = mfree(labels); + return 1; +} + +_public_ int sd_bus_try_close(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return -EOPNOTSUPP; +} + +_public_ int sd_bus_get_description(sd_bus *bus, const char **description) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(description, -EINVAL); + assert_return(bus->description, -ENXIO); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (bus->description) + *description = bus->description; + else if (bus->is_system) + *description = "system"; + else if (bus->is_user) + *description = "user"; + else + *description = NULL; + + return 0; +} + +_public_ int sd_bus_get_scope(sd_bus *bus, const char **scope) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(scope, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (bus->is_user) { + *scope = "user"; + return 0; + } + + if (bus->is_system) { + *scope = "system"; + return 0; + } + + return -ENODATA; +} + +_public_ int sd_bus_get_address(sd_bus *bus, const char **address) { + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(address, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (bus->address) { + *address = bus->address; + return 0; + } + + return -ENODATA; +} + +_public_ int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *mask) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(mask, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + *mask = bus->creds_mask; + return 0; +} + +_public_ int sd_bus_is_bus_client(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return bus->bus_client; +} + +_public_ int sd_bus_is_server(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return bus->is_server; +} + +_public_ int sd_bus_is_anonymous(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return bus->anonymous_auth; +} + +_public_ int sd_bus_is_trusted(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return bus->trusted; +} + +_public_ int sd_bus_is_monitor(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + + return bus->is_monitor; +} + +static void flush_close(sd_bus *bus) { + if (!bus) + return; + + /* Flushes and closes the specified bus. We take a ref before, + * to ensure the flushing does not cause the bus to be + * unreferenced. */ + + sd_bus_flush_close_unref(sd_bus_ref(bus)); +} + +_public_ void sd_bus_default_flush_close(void) { + flush_close(default_starter_bus); + flush_close(default_user_bus); + flush_close(default_system_bus); +} + +_public_ int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + + /* Turns on exit-on-disconnect, and triggers it immediately if the bus connection was already + * disconnected. Note that this is triggered exclusively on disconnections triggered by the server side, never + * from the client side. */ + bus->exit_on_disconnect = b; + + /* If the exit condition was triggered already, exit immediately. */ + return bus_exit_now(bus); +} + +_public_ int sd_bus_get_exit_on_disconnect(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + + return bus->exit_on_disconnect; +} + +_public_ int sd_bus_set_sender(sd_bus *bus, const char *sender) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus->bus_client, -EPERM); + assert_return(!sender || service_name_is_valid(sender), -EINVAL); + + return free_and_strdup(&bus->patch_sender, sender); +} + +_public_ int sd_bus_get_sender(sd_bus *bus, const char **ret) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(ret, -EINVAL); + + if (!bus->patch_sender) + return -ENODATA; + + *ret = bus->patch_sender; + return 0; +} + +_public_ int sd_bus_get_n_queued_read(sd_bus *bus, uint64_t *ret) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + assert_return(ret, -EINVAL); + + *ret = bus->rqueue_size; + return 0; +} + +_public_ int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(!bus_pid_changed(bus), -ECHILD); + assert_return(ret, -EINVAL); + + *ret = bus->wqueue_size; + return 0; +} + +_public_ int sd_bus_set_method_call_timeout(sd_bus *bus, uint64_t usec) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + + bus->method_call_timeout = usec; + return 0; +} + +_public_ int sd_bus_get_method_call_timeout(sd_bus *bus, uint64_t *ret) { + const char *e; + usec_t usec; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(ret, -EINVAL); + + if (bus->method_call_timeout != 0) { + *ret = bus->method_call_timeout; + return 0; + } + + e = secure_getenv("SYSTEMD_BUS_TIMEOUT"); + if (e && parse_sec(e, &usec) >= 0 && usec != 0) { + /* Save the parsed value to avoid multiple parsing. To change the timeout value, + * use sd_bus_set_method_call_timeout() instead of setenv(). */ + *ret = bus->method_call_timeout = usec; + return 0; + } + + *ret = bus->method_call_timeout = BUS_DEFAULT_TIMEOUT; + return 0; +} + +_public_ int sd_bus_set_close_on_exit(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + + bus->close_on_exit = b; + return 0; +} + +_public_ int sd_bus_get_close_on_exit(sd_bus *bus) { + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + + return bus->close_on_exit; +} + +int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) { + int r; + + assert_return(bus, -EINVAL); + assert_return(bus = bus_resolve(bus), -ENOPKG); + assert_return(m, -EINVAL); + assert_return(m->sealed, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + + /* Re-enqueue a message for reading. This is primarily useful for PolicyKit-style authentication, + * where we accept a message, then determine we need to interactively authenticate the user, and then + * we want to process the message again. */ + + r = bus_rqueue_make_room(bus); + if (r < 0) + return r; + + bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(m, bus); + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-address.c b/src/libsystemd/sd-bus/test-bus-address.c new file mode 100644 index 00000000..70a6df10 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-address.c @@ -0,0 +1,68 @@ +#include "sd-bus.h" + +#include "bus-internal.h" +#include "log.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" + +static void test_one_address(sd_bus *b, + const char *host, + int result, const char *expected) { + int r; + + r = bus_set_address_system_remote(b, host); + log_info("\"%s\" → %d, \"%s\"", host, r, strna(r >= 0 ? b->address : NULL)); + if (result < 0 || expected) { + assert(r == result); + if (r >= 0) + assert_se(streq(b->address, expected)); + } +} + +static void test_bus_set_address_system_remote(char **args) { + _cleanup_(sd_bus_unrefp) sd_bus *b = NULL; + + assert_se(sd_bus_new(&b) >= 0); + if (!strv_isempty(args)) { + char **a; + STRV_FOREACH(a, args) + test_one_address(b, *a, 0, NULL); + return; + }; + + test_one_address(b, "host", + 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=host,argv4=systemd-stdio-bridge"); + test_one_address(b, "host:123", + 0, "unixexec:path=ssh,argv1=-xT,argv2=-p,argv3=123,argv4=--,argv5=host,argv6=systemd-stdio-bridge"); + test_one_address(b, "host:123:123", + -EINVAL, NULL); + test_one_address(b, "host:", + -EINVAL, NULL); + test_one_address(b, "user@host", + 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=user%40host,argv4=systemd-stdio-bridge"); + test_one_address(b, "user@host@host", + -EINVAL, NULL); + test_one_address(b, "[::1]", + 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=%3a%3a1,argv4=systemd-stdio-bridge"); + test_one_address(b, "user@[::1]", + 0, "unixexec:path=ssh,argv1=-xT,argv2=--,argv3=user%40%3a%3a1,argv4=systemd-stdio-bridge"); + test_one_address(b, "user@[::1]:99", + 0, "unixexec:path=ssh,argv1=-xT,argv2=-p,argv3=99,argv4=--,argv5=user%40%3a%3a1,argv6=systemd-stdio-bridge"); + test_one_address(b, "user@[::1]:", + -EINVAL, NULL); + test_one_address(b, "user@[::1:", + -EINVAL, NULL); + test_one_address(b, "user@", + -EINVAL, NULL); + test_one_address(b, "user@@", + -EINVAL, NULL); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + test_bus_set_address_system_remote(argv + 1); + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-benchmark.c b/src/libsystemd/sd-bus/test-bus-benchmark.c new file mode 100644 index 00000000..8de0a859 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-benchmark.c @@ -0,0 +1,324 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-internal.h" +#include "bus-kernel.h" +#include "bus-util.h" +#include "def.h" +#include "fd-util.h" +#include "missing_resource.h" +#include "time-util.h" +#include "util.h" + +#define MAX_SIZE (2*1024*1024) + +static usec_t arg_loop_usec = 100 * USEC_PER_MSEC; + +typedef enum Type { + TYPE_LEGACY, + TYPE_DIRECT, +} Type; + +static void server(sd_bus *b, size_t *result) { + int r; + + for (;;) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + r = sd_bus_process(b, &m); + assert_se(r >= 0); + + if (r == 0) + assert_se(sd_bus_wait(b, USEC_INFINITY) >= 0); + if (!m) + continue; + + if (sd_bus_message_is_method_call(m, "benchmark.server", "Ping")) + assert_se(sd_bus_reply_method_return(m, NULL) >= 0); + else if (sd_bus_message_is_method_call(m, "benchmark.server", "Work")) { + const void *p; + size_t sz; + + /* Make sure the mmap is mapped */ + assert_se(sd_bus_message_read_array(m, 'y', &p, &sz) > 0); + + r = sd_bus_reply_method_return(m, NULL); + assert_se(r >= 0); + } else if (sd_bus_message_is_method_call(m, "benchmark.server", "Exit")) { + uint64_t res; + assert_se(sd_bus_message_read(m, "t", &res) > 0); + + *result = res; + return; + + } else if (!sd_bus_message_is_signal(m, NULL, NULL)) + assert_not_reached("Unknown method"); + } +} + +static void transaction(sd_bus *b, size_t sz, const char *server_name) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + uint8_t *p; + + assert_se(sd_bus_message_new_method_call(b, &m, server_name, "/", "benchmark.server", "Work") >= 0); + assert_se(sd_bus_message_append_array_space(m, 'y', sz, (void**) &p) >= 0); + + memset(p, 0x80, sz); + + assert_se(sd_bus_call(b, m, 0, NULL, &reply) >= 0); +} + +static void client_bisect(const char *address, const char *server_name) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL; + size_t lsize, rsize, csize; + sd_bus *b; + int r; + + r = sd_bus_new(&b); + assert_se(r >= 0); + + r = sd_bus_set_address(b, address); + assert_se(r >= 0); + + r = sd_bus_start(b); + assert_se(r >= 0); + + r = sd_bus_call_method(b, server_name, "/", "benchmark.server", "Ping", NULL, NULL, NULL); + assert_se(r >= 0); + + lsize = 1; + rsize = MAX_SIZE; + + printf("SIZE\tCOPY\tMEMFD\n"); + + for (;;) { + usec_t t; + unsigned n_copying, n_memfd; + + csize = (lsize + rsize) / 2; + + if (csize <= lsize) + break; + + if (csize <= 0) + break; + + printf("%zu\t", csize); + + b->use_memfd = 0; + + t = now(CLOCK_MONOTONIC); + for (n_copying = 0;; n_copying++) { + transaction(b, csize, server_name); + if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) + break; + } + printf("%u\t", (unsigned) ((n_copying * USEC_PER_SEC) / arg_loop_usec)); + + b->use_memfd = -1; + + t = now(CLOCK_MONOTONIC); + for (n_memfd = 0;; n_memfd++) { + transaction(b, csize, server_name); + if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) + break; + } + printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec)); + + if (n_copying == n_memfd) + break; + + if (n_copying > n_memfd) + lsize = csize; + else + rsize = csize; + } + + b->use_memfd = 1; + assert_se(sd_bus_message_new_method_call(b, &x, server_name, "/", "benchmark.server", "Exit") >= 0); + assert_se(sd_bus_message_append(x, "t", csize) >= 0); + assert_se(sd_bus_send(b, x, NULL) >= 0); + + sd_bus_unref(b); +} + +static void client_chart(Type type, const char *address, const char *server_name, int fd) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *x = NULL; + size_t csize; + sd_bus *b; + int r; + + r = sd_bus_new(&b); + assert_se(r >= 0); + + if (type == TYPE_DIRECT) { + r = sd_bus_set_fd(b, fd, fd); + assert_se(r >= 0); + } else { + r = sd_bus_set_address(b, address); + assert_se(r >= 0); + + r = sd_bus_set_bus_client(b, true); + assert_se(r >= 0); + } + + r = sd_bus_start(b); + assert_se(r >= 0); + + r = sd_bus_call_method(b, server_name, "/", "benchmark.server", "Ping", NULL, NULL, NULL); + assert_se(r >= 0); + + switch (type) { + case TYPE_LEGACY: + printf("SIZE\tLEGACY\n"); + break; + case TYPE_DIRECT: + printf("SIZE\tDIRECT\n"); + break; + } + + for (csize = 1; csize <= MAX_SIZE; csize *= 2) { + usec_t t; + unsigned n_memfd; + + printf("%zu\t", csize); + + t = now(CLOCK_MONOTONIC); + for (n_memfd = 0;; n_memfd++) { + transaction(b, csize, server_name); + if (now(CLOCK_MONOTONIC) >= t + arg_loop_usec) + break; + } + + printf("%u\n", (unsigned) ((n_memfd * USEC_PER_SEC) / arg_loop_usec)); + } + + b->use_memfd = 1; + assert_se(sd_bus_message_new_method_call(b, &x, server_name, "/", "benchmark.server", "Exit") >= 0); + assert_se(sd_bus_message_append(x, "t", csize) >= 0); + assert_se(sd_bus_send(b, x, NULL) >= 0); + + sd_bus_unref(b); +} + +int main(int argc, char *argv[]) { + enum { + MODE_BISECT, + MODE_CHART, + } mode = MODE_BISECT; + Type type = TYPE_LEGACY; + int i, pair[2] = { -1, -1 }; + _cleanup_free_ char *address = NULL, *server_name = NULL; + _cleanup_close_ int bus_ref = -1; + const char *unique; + cpu_set_t cpuset; + size_t result; + sd_bus *b; + pid_t pid; + int r; + + for (i = 1; i < argc; i++) { + if (streq(argv[i], "chart")) { + mode = MODE_CHART; + continue; + } else if (streq(argv[i], "legacy")) { + type = TYPE_LEGACY; + continue; + } else if (streq(argv[i], "direct")) { + type = TYPE_DIRECT; + continue; + } + + assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0); + } + + assert_se(arg_loop_usec > 0); + + if (type == TYPE_LEGACY) { + const char *e; + + e = secure_getenv("DBUS_SESSION_BUS_ADDRESS"); + assert_se(e); + + address = strdup(e); + assert_se(address); + } + + r = sd_bus_new(&b); + assert_se(r >= 0); + + if (type == TYPE_DIRECT) { + assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0); + + r = sd_bus_set_fd(b, pair[0], pair[0]); + assert_se(r >= 0); + + r = sd_bus_set_server(b, true, SD_ID128_NULL); + assert_se(r >= 0); + } else { + r = sd_bus_set_address(b, address); + assert_se(r >= 0); + + r = sd_bus_set_bus_client(b, true); + assert_se(r >= 0); + } + + r = sd_bus_start(b); + assert_se(r >= 0); + + if (type != TYPE_DIRECT) { + r = sd_bus_get_unique_name(b, &unique); + assert_se(r >= 0); + + server_name = strdup(unique); + assert_se(server_name); + } + + sync(); + setpriority(PRIO_PROCESS, 0, -19); + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + CPU_ZERO(&cpuset); + CPU_SET(0, &cpuset); + pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + + safe_close(bus_ref); + sd_bus_unref(b); + + switch (mode) { + case MODE_BISECT: + client_bisect(address, server_name); + break; + + case MODE_CHART: + client_chart(type, address, server_name, pair[1]); + break; + } + + _exit(EXIT_SUCCESS); + } + + CPU_ZERO(&cpuset); + CPU_SET(1, &cpuset); + pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + + server(b, &result); + + if (mode == MODE_BISECT) + printf("Copying/memfd are equally fast at %zu bytes\n", result); + + assert_se(waitpid(pid, NULL, 0) == pid); + + safe_close(pair[1]); + sd_bus_unref(b); + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c new file mode 100644 index 00000000..d9716ae7 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-chat.c @@ -0,0 +1,548 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-internal.h" +#include "bus-match.h" +#include "bus-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "log.h" +#include "macro.h" +#include "tests.h" +#include "util.h" + +static int match_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + log_info("Match triggered! interface=%s member=%s", strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m))); + return 0; +} + +static int object_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + int r; + + if (sd_bus_message_is_method_error(m, NULL)) + return 0; + + if (sd_bus_message_is_method_call(m, "org.object.test", "Foobar")) { + log_info("Invoked Foobar() on %s", sd_bus_message_get_path(m)); + + r = sd_bus_reply_method_return(m, NULL); + if (r < 0) + return log_error_errno(r, "Failed to send reply: %m"); + + return 1; + } + + return 0; +} + +static int server_init(sd_bus **_bus) { + sd_bus *bus = NULL; + sd_id128_t id; + int r; + const char *unique, *desc; + + assert_se(_bus); + + r = sd_bus_open_user_with_description(&bus, "my bus!"); + if (r < 0) { + log_error_errno(r, "Failed to connect to user bus: %m"); + goto fail; + } + + r = sd_bus_get_bus_id(bus, &id); + if (r < 0) { + log_error_errno(r, "Failed to get server ID: %m"); + goto fail; + } + + r = sd_bus_get_unique_name(bus, &unique); + if (r < 0) { + log_error_errno(r, "Failed to get unique name: %m"); + goto fail; + } + + r = sd_bus_get_description(bus, &desc); + assert_se(streq(desc, "my bus!")); + + log_info("Peer ID is " SD_ID128_FORMAT_STR ".", SD_ID128_FORMAT_VAL(id)); + log_info("Unique ID: %s", unique); + log_info("Can send file handles: %i", sd_bus_can_send(bus, 'h')); + + r = sd_bus_request_name(bus, "org.freedesktop.systemd.test", 0); + if (r < 0) { + log_error_errno(r, "Failed to acquire name: %m"); + goto fail; + } + + r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL); + if (r < 0) { + log_error_errno(r, "Failed to add object: %m"); + goto fail; + } + + r = sd_bus_match_signal(bus, NULL, NULL, NULL, "foo.bar", "Notify", match_callback, NULL); + if (r < 0) { + log_error_errno(r, "Failed to request match: %m"); + goto fail; + } + + r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL); + if (r < 0) { + log_error_errno(r, "Failed to add match: %m"); + goto fail; + } + + bus_match_dump(&bus->match_callbacks, 0); + + *_bus = bus; + return 0; + +fail: + sd_bus_unref(bus); + return r; +} + +static int server(sd_bus *bus) { + int r; + bool client1_gone = false, client2_gone = false; + + while (!client1_gone || !client2_gone) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + pid_t pid = 0; + const char *label = NULL; + + r = sd_bus_process(bus, &m); + if (r < 0) { + log_error_errno(r, "Failed to process requests: %m"); + goto fail; + } + + if (r == 0) { + r = sd_bus_wait(bus, (uint64_t) -1); + if (r < 0) { + log_error_errno(r, "Failed to wait: %m"); + goto fail; + } + + continue; + } + + if (!m) + continue; + + sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid); + sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label); + log_info("Got message! member=%s pid="PID_FMT" label=%s", + strna(sd_bus_message_get_member(m)), + pid, + strna(label)); + /* bus_message_dump(m); */ + /* sd_bus_message_rewind(m, true); */ + + if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) { + const char *hello; + _cleanup_free_ char *lowercase = NULL; + + r = sd_bus_message_read(m, "s", &hello); + if (r < 0) { + log_error_errno(r, "Failed to get parameter: %m"); + goto fail; + } + + lowercase = strdup(hello); + if (!lowercase) { + r = log_oom(); + goto fail; + } + + ascii_strlower(lowercase); + + r = sd_bus_reply_method_return(m, "s", lowercase); + if (r < 0) { + log_error_errno(r, "Failed to send reply: %m"); + goto fail; + } + } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) { + + r = sd_bus_reply_method_return(m, NULL); + if (r < 0) { + log_error_errno(r, "Failed to send reply: %m"); + goto fail; + } + + client1_gone = true; + } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) { + + r = sd_bus_reply_method_return(m, NULL); + if (r < 0) { + log_error_errno(r, "Failed to send reply: %m"); + goto fail; + } + + client2_gone = true; + } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) { + + sleep(1); + + r = sd_bus_reply_method_return(m, NULL); + if (r < 0) { + log_error_errno(r, "Failed to send reply: %m"); + goto fail; + } + + } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) { + int fd; + static const char x = 'X'; + + r = sd_bus_message_read(m, "h", &fd); + if (r < 0) { + log_error_errno(r, "Failed to get parameter: %m"); + goto fail; + } + + log_info("Received fd=%d", fd); + + if (write(fd, &x, 1) < 0) { + log_error_errno(errno, "Failed to write to fd: %m"); + safe_close(fd); + goto fail; + } + + r = sd_bus_reply_method_return(m, NULL); + if (r < 0) { + log_error_errno(r, "Failed to send reply: %m"); + goto fail; + } + + } else if (sd_bus_message_is_method_call(m, NULL, NULL)) { + + r = sd_bus_reply_method_error( + m, + &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method.")); + if (r < 0) { + log_error_errno(r, "Failed to send reply: %m"); + goto fail; + } + } + } + + r = 0; + +fail: + if (bus) { + sd_bus_flush(bus); + sd_bus_unref(bus); + } + + return r; +} + +static void* client1(void *p) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *hello; + int r; + _cleanup_close_pair_ int pp[2] = { -1, -1 }; + char x; + + r = sd_bus_open_user(&bus); + if (r < 0) { + log_error_errno(r, "Failed to connect to user bus: %m"); + goto finish; + } + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd.test", + "/", + "org.freedesktop.systemd.test", + "LowerCase", + &error, + &reply, + "s", + "HELLO"); + if (r < 0) { + log_error_errno(r, "Failed to issue method call: %m"); + goto finish; + } + + r = sd_bus_message_read(reply, "s", &hello); + if (r < 0) { + log_error_errno(r, "Failed to get string: %m"); + goto finish; + } + + assert_se(streq(hello, "hello")); + + if (pipe2(pp, O_CLOEXEC|O_NONBLOCK) < 0) { + log_error_errno(errno, "Failed to allocate pipe: %m"); + r = -errno; + goto finish; + } + + log_info("Sending fd=%d", pp[1]); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd.test", + "/", + "org.freedesktop.systemd.test", + "FileDescriptor", + &error, + NULL, + "h", + pp[1]); + if (r < 0) { + log_error_errno(r, "Failed to issue method call: %m"); + goto finish; + } + + errno = 0; + if (read(pp[0], &x, 1) <= 0) { + log_error("Failed to read from pipe: %s", errno != 0 ? strerror_safe(errno) : "early read"); + goto finish; + } + + r = 0; + +finish: + if (bus) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *q; + + r = sd_bus_message_new_method_call( + bus, + &q, + "org.freedesktop.systemd.test", + "/", + "org.freedesktop.systemd.test", + "ExitClient1"); + if (r < 0) + log_error_errno(r, "Failed to allocate method call: %m"); + else + sd_bus_send(bus, q, NULL); + + } + + return INT_TO_PTR(r); +} + +static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + bool *x = userdata; + + log_error_errno(sd_bus_message_get_errno(m), "Quit callback: %m"); + + *x = 1; + return 1; +} + +static void* client2(void *p) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + bool quit = false; + const char *mid; + int r; + + r = sd_bus_open_user(&bus); + if (r < 0) { + log_error_errno(r, "Failed to connect to user bus: %m"); + goto finish; + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd.test", + "/foo/bar/waldo/piep", + "org.object.test", + "Foobar"); + if (r < 0) { + log_error_errno(r, "Failed to allocate method call: %m"); + goto finish; + } + + r = sd_bus_send(bus, m, NULL); + if (r < 0) { + log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); + goto finish; + } + + m = sd_bus_message_unref(m); + + r = sd_bus_message_new_signal( + bus, + &m, + "/foobar", + "foo.bar", + "Notify"); + if (r < 0) { + log_error_errno(r, "Failed to allocate signal: %m"); + goto finish; + } + + r = sd_bus_send(bus, m, NULL); + if (r < 0) { + log_error("Failed to issue signal: %s", bus_error_message(&error, -r)); + goto finish; + } + + m = sd_bus_message_unref(m); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd.test", + "/", + "org.freedesktop.DBus.Peer", + "GetMachineId"); + if (r < 0) { + log_error_errno(r, "Failed to allocate method call: %m"); + goto finish; + } + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) { + log_error("Failed to issue method call: %s", bus_error_message(&error, -r)); + goto finish; + } + + r = sd_bus_message_read(reply, "s", &mid); + if (r < 0) { + log_error_errno(r, "Failed to parse machine ID: %m"); + goto finish; + } + + log_info("Machine ID is %s.", mid); + + m = sd_bus_message_unref(m); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd.test", + "/", + "org.freedesktop.systemd.test", + "Slow"); + if (r < 0) { + log_error_errno(r, "Failed to allocate method call: %m"); + goto finish; + } + + reply = sd_bus_message_unref(reply); + + r = sd_bus_call(bus, m, 200 * USEC_PER_MSEC, &error, &reply); + if (r < 0) + log_info("Failed to issue method call: %s", bus_error_message(&error, -r)); + else + log_info("Slow call succeed."); + + m = sd_bus_message_unref(m); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd.test", + "/", + "org.freedesktop.systemd.test", + "Slow"); + if (r < 0) { + log_error_errno(r, "Failed to allocate method call: %m"); + goto finish; + } + + r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC); + if (r < 0) { + log_info("Failed to issue method call: %s", bus_error_message(&error, -r)); + goto finish; + } + + while (!quit) { + r = sd_bus_process(bus, NULL); + if (r < 0) { + log_error_errno(r, "Failed to process requests: %m"); + goto finish; + } + if (r == 0) { + r = sd_bus_wait(bus, (uint64_t) -1); + if (r < 0) { + log_error_errno(r, "Failed to wait: %m"); + goto finish; + } + } + } + + r = 0; + +finish: + if (bus) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *q; + + r = sd_bus_message_new_method_call( + bus, + &q, + "org.freedesktop.systemd.test", + "/", + "org.freedesktop.systemd.test", + "ExitClient2"); + if (r < 0) { + log_error_errno(r, "Failed to allocate method call: %m"); + goto finish; + } + + (void) sd_bus_send(bus, q, NULL); + } + + return INT_TO_PTR(r); +} + +int main(int argc, char *argv[]) { + pthread_t c1, c2; + sd_bus *bus; + void *p; + int q, r; + + test_setup_logging(LOG_INFO); + + r = server_init(&bus); + if (r < 0) + return log_tests_skipped("Failed to connect to bus"); + + log_info("Initialized..."); + + r = pthread_create(&c1, NULL, client1, bus); + if (r != 0) + return EXIT_FAILURE; + + r = pthread_create(&c2, NULL, client2, bus); + if (r != 0) + return EXIT_FAILURE; + + r = server(bus); + + q = pthread_join(c1, &p); + if (q != 0) + return EXIT_FAILURE; + if (PTR_TO_INT(p) < 0) + return EXIT_FAILURE; + + q = pthread_join(c2, &p); + if (q != 0) + return EXIT_FAILURE; + if (PTR_TO_INT(p) < 0) + return EXIT_FAILURE; + + if (r < 0) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} diff --git a/src/libsystemd/sd-bus/test-bus-cleanup.c b/src/libsystemd/sd-bus/test-bus-cleanup.c new file mode 100644 index 00000000..99d335e3 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-cleanup.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-bus.h" + +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-util.h" +#include "tests.h" + +static bool use_system_bus = false; + +static void test_bus_new(void) { + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + + assert_se(sd_bus_new(&bus) == 0); + assert_se(bus->n_ref == 1); +} + +static int test_bus_open(void) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + r = sd_bus_open_user(&bus); + if (IN_SET(r, -ECONNREFUSED, -ENOENT)) { + r = sd_bus_open_system(&bus); + if (IN_SET(r, -ECONNREFUSED, -ENOENT)) + return r; + use_system_bus = true; + } + + assert_se(r >= 0); + assert_se(bus->n_ref >= 1); /* we send a hello message when opening, so the count is above 1 */ + + return 0; +} + +static void test_bus_new_method_call(void) { + sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + assert_se(use_system_bus ? sd_bus_open_system(&bus) >= 0 : sd_bus_open_user(&bus) >= 0); + + assert_se(sd_bus_message_new_method_call(bus, &m, "a.service.name", "/an/object/path", "an.interface.name", "AMethodName") >= 0); + + assert_se(m->n_ref == 1); /* We hold the only reference to the message */ + assert_se(bus->n_ref >= 2); + sd_bus_flush_close_unref(bus); + assert_se(m->n_ref == 1); +} + +static void test_bus_new_signal(void) { + sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + assert_se(use_system_bus ? sd_bus_open_system(&bus) >= 0 : sd_bus_open_user(&bus) >= 0); + + assert_se(sd_bus_message_new_signal(bus, &m, "/an/object/path", "an.interface.name", "Name") >= 0); + + assert_se(m->n_ref == 1); /* We hold the only reference to the message */ + assert_se(bus->n_ref >= 2); + sd_bus_flush_close_unref(bus); + assert_se(m->n_ref == 1); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_INFO); + + test_bus_new(); + + if (test_bus_open() < 0) + return log_tests_skipped("Failed to connect to bus"); + + test_bus_new_method_call(); + test_bus_new_signal(); + + return EXIT_SUCCESS; +} diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c new file mode 100644 index 00000000..7f7bc491 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-creds.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-bus.h" + +#include "bus-dump.h" +#include "bus-util.h" +#include "cgroup-util.h" +#include "tests.h" + +int main(int argc, char *argv[]) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + int r; + + test_setup_logging(LOG_DEBUG); + + if (cg_unified() == -ENOMEDIUM) + return log_tests_skipped("/sys/fs/cgroup/ not available"); + + r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL); + log_full_errno(r < 0 ? LOG_ERR : LOG_DEBUG, r, "sd_bus_creds_new_from_pid: %m"); + assert_se(r >= 0); + + bus_creds_dump(creds, NULL, true); + + creds = sd_bus_creds_unref(creds); + + r = sd_bus_creds_new_from_pid(&creds, 1, _SD_BUS_CREDS_ALL); + if (r != -EACCES) { + assert_se(r >= 0); + putchar('\n'); + bus_creds_dump(creds, NULL, true); + } + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c new file mode 100644 index 00000000..cb5d6209 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-error.c @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-bus.h" + +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-util.h" +#include "errno-list.h" +#include "errno-util.h" + +static void test_error(void) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL; + const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error"); + const sd_bus_error temporarily_const_error = { + .name = SD_BUS_ERROR_ACCESS_DENIED, + .message = "oh! no", + ._need_free = -1 + }; + + assert_se(!sd_bus_error_is_set(&error)); + assert_se(sd_bus_error_set(&error, SD_BUS_ERROR_NOT_SUPPORTED, "xxx") == -EOPNOTSUPP); + assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED)); + assert_se(streq(error.message, "xxx")); + assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED)); + assert_se(sd_bus_error_get_errno(&error) == EOPNOTSUPP); + assert_se(sd_bus_error_is_set(&error)); + sd_bus_error_free(&error); + + /* Check with no error */ + assert_se(!sd_bus_error_is_set(&error)); + assert_se(sd_bus_error_setf(&error, NULL, "yyy %i", -1) == 0); + assert_se(error.name == NULL); + assert_se(error.message == NULL); + assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); + assert_se(sd_bus_error_get_errno(&error) == 0); + assert_se(!sd_bus_error_is_set(&error)); + + assert_se(sd_bus_error_setf(&error, SD_BUS_ERROR_FILE_NOT_FOUND, "yyy %i", -1) == -ENOENT); + assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND)); + assert_se(streq(error.message, "yyy -1")); + assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND)); + assert_se(sd_bus_error_get_errno(&error) == ENOENT); + assert_se(sd_bus_error_is_set(&error)); + + assert_se(!sd_bus_error_is_set(&second)); + assert_se(second._need_free == 0); + assert_se(error._need_free > 0); + assert_se(sd_bus_error_copy(&second, &error) == -ENOENT); + assert_se(second._need_free > 0); + assert_se(streq(error.name, second.name)); + assert_se(streq(error.message, second.message)); + assert_se(sd_bus_error_get_errno(&second) == ENOENT); + assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_NOT_FOUND)); + assert_se(sd_bus_error_is_set(&second)); + + sd_bus_error_free(&error); + sd_bus_error_free(&second); + + assert_se(!sd_bus_error_is_set(&second)); + assert_se(const_error._need_free == 0); + assert_se(sd_bus_error_copy(&second, &const_error) == -EEXIST); + assert_se(second._need_free == 0); + assert_se(streq(const_error.name, second.name)); + assert_se(streq(const_error.message, second.message)); + assert_se(sd_bus_error_get_errno(&second) == EEXIST); + assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_EXISTS)); + assert_se(sd_bus_error_is_set(&second)); + sd_bus_error_free(&second); + + assert_se(!sd_bus_error_is_set(&second)); + assert_se(temporarily_const_error._need_free < 0); + assert_se(sd_bus_error_copy(&second, &temporarily_const_error) == -EACCES); + assert_se(second._need_free > 0); + assert_se(streq(temporarily_const_error.name, second.name)); + assert_se(streq(temporarily_const_error.message, second.message)); + assert_se(sd_bus_error_get_errno(&second) == EACCES); + assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_ACCESS_DENIED)); + assert_se(sd_bus_error_is_set(&second)); + + assert_se(!sd_bus_error_is_set(&error)); + assert_se(sd_bus_error_set_const(&error, "System.Error.EUCLEAN", "Hallo") == -EUCLEAN); + assert_se(streq(error.name, "System.Error.EUCLEAN")); + assert_se(streq(error.message, "Hallo")); + assert_se(sd_bus_error_has_name(&error, "System.Error.EUCLEAN")); + assert_se(sd_bus_error_get_errno(&error) == EUCLEAN); + assert_se(sd_bus_error_is_set(&error)); + sd_bus_error_free(&error); + + assert_se(!sd_bus_error_is_set(&error)); + assert_se(sd_bus_error_set_errno(&error, EBUSY) == -EBUSY); + assert_se(streq(error.name, "System.Error.EBUSY")); + assert_se(streq(error.message, strerror_safe(EBUSY))); + assert_se(sd_bus_error_has_name(&error, "System.Error.EBUSY")); + assert_se(sd_bus_error_get_errno(&error) == EBUSY); + assert_se(sd_bus_error_is_set(&error)); + sd_bus_error_free(&error); + + assert_se(!sd_bus_error_is_set(&error)); + assert_se(sd_bus_error_set_errnof(&error, EIO, "Waldi %c", 'X') == -EIO); + assert_se(streq(error.name, SD_BUS_ERROR_IO_ERROR)); + assert_se(streq(error.message, "Waldi X")); + assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR)); + assert_se(sd_bus_error_get_errno(&error) == EIO); + assert_se(sd_bus_error_is_set(&error)); + sd_bus_error_free(&error); + + /* Check with no error */ + assert_se(!sd_bus_error_is_set(&error)); + assert_se(sd_bus_error_set_errnof(&error, 0, "Waldi %c", 'X') == 0); + assert_se(error.name == NULL); + assert_se(error.message == NULL); + assert_se(!sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR)); + assert_se(sd_bus_error_get_errno(&error) == 0); + assert_se(!sd_bus_error_is_set(&error)); +} + +extern const sd_bus_error_map __start_SYSTEMD_BUS_ERROR_MAP[]; +extern const sd_bus_error_map __stop_SYSTEMD_BUS_ERROR_MAP[]; + +static void dump_mapping_table(void) { + const sd_bus_error_map *m; + + printf("----- errno mappings ------\n"); + m = ALIGN_TO_PTR(__start_SYSTEMD_BUS_ERROR_MAP, sizeof(void*)); + while (m < __stop_SYSTEMD_BUS_ERROR_MAP) { + + if (m->code == BUS_ERROR_MAP_END_MARKER) { + m = ALIGN_TO_PTR(m + 1, sizeof(void*)); + continue; + } + + printf("%s -> %i/%s\n", strna(m->name), m->code, strna(errno_to_name(m->code))); + m++; + } + printf("---------------------------\n"); +} + +static void test_errno_mapping_standard(void) { + assert_se(sd_bus_error_set(NULL, "System.Error.EUCLEAN", NULL) == -EUCLEAN); + assert_se(sd_bus_error_set(NULL, "System.Error.EBUSY", NULL) == -EBUSY); + assert_se(sd_bus_error_set(NULL, "System.Error.EINVAL", NULL) == -EINVAL); + assert_se(sd_bus_error_set(NULL, "System.Error.WHATSIT", NULL) == -EIO); +} + +BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors[] = { + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error", 5), + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-2", 52), + SD_BUS_ERROR_MAP_END +}; + +BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors2[] = { + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-3", 33), + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-4", 44), + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-33", 333), + SD_BUS_ERROR_MAP_END +}; + +static const sd_bus_error_map test_errors3[] = { + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-88", 888), + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-99", 999), + SD_BUS_ERROR_MAP_END +}; + +static const sd_bus_error_map test_errors4[] = { + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-77", 777), + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-78", 778), + SD_BUS_ERROR_MAP_END +}; + +static const sd_bus_error_map test_errors_bad1[] = { + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", 0), + SD_BUS_ERROR_MAP_END +}; + +static const sd_bus_error_map test_errors_bad2[] = { + SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-1", -1), + SD_BUS_ERROR_MAP_END +}; + +static void test_errno_mapping_custom(void) { + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error", NULL) == -5); + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52); + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-x", NULL) == -EIO); + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-33", NULL) == -333); + + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-88", NULL) == -EIO); + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-99", NULL) == -EIO); + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-77", NULL) == -EIO); + + assert_se(sd_bus_error_add_map(test_errors3) > 0); + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-88", NULL) == -888); + assert_se(sd_bus_error_add_map(test_errors4) > 0); + assert_se(sd_bus_error_add_map(test_errors4) == 0); + assert_se(sd_bus_error_add_map(test_errors3) == 0); + + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-99", NULL) == -999); + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-77", NULL) == -777); + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-78", NULL) == -778); + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-2", NULL) == -52); + assert_se(sd_bus_error_set(NULL, "org.freedesktop.custom-dbus-error-y", NULL) == -EIO); + + assert_se(sd_bus_error_set(NULL, BUS_ERROR_NO_SUCH_UNIT, NULL) == -ENOENT); + + assert_se(sd_bus_error_add_map(test_errors_bad1) == -EINVAL); + assert_se(sd_bus_error_add_map(test_errors_bad2) == -EINVAL); +} + +int main(int argc, char *argv[]) { + dump_mapping_table(); + + test_error(); + test_errno_mapping_standard(); + test_errno_mapping_custom(); + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c new file mode 100644 index 00000000..1a9a35d5 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-gvariant.c @@ -0,0 +1,221 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if HAVE_GLIB +#include +#endif + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-dump.h" +#include "bus-gvariant.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-util.h" +#include "macro.h" +#include "tests.h" +#include "util.h" + +static void test_bus_gvariant_is_fixed_size(void) { + log_info("/* %s */", __func__); + + assert_se(bus_gvariant_is_fixed_size("") > 0); + assert_se(bus_gvariant_is_fixed_size("()") == -EINVAL); + assert_se(bus_gvariant_is_fixed_size("y") > 0); + assert_se(bus_gvariant_is_fixed_size("u") > 0); + assert_se(bus_gvariant_is_fixed_size("b") > 0); + assert_se(bus_gvariant_is_fixed_size("n") > 0); + assert_se(bus_gvariant_is_fixed_size("q") > 0); + assert_se(bus_gvariant_is_fixed_size("i") > 0); + assert_se(bus_gvariant_is_fixed_size("t") > 0); + assert_se(bus_gvariant_is_fixed_size("d") > 0); + assert_se(bus_gvariant_is_fixed_size("s") == 0); + assert_se(bus_gvariant_is_fixed_size("o") == 0); + assert_se(bus_gvariant_is_fixed_size("g") == 0); + assert_se(bus_gvariant_is_fixed_size("h") > 0); + assert_se(bus_gvariant_is_fixed_size("ay") == 0); + assert_se(bus_gvariant_is_fixed_size("v") == 0); + assert_se(bus_gvariant_is_fixed_size("(u)") > 0); + assert_se(bus_gvariant_is_fixed_size("(uuuuy)") > 0); + assert_se(bus_gvariant_is_fixed_size("(uusuuy)") == 0); + assert_se(bus_gvariant_is_fixed_size("a{ss}") == 0); + assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiii)))") > 0); + assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiivi)))") == 0); +} + +static void test_bus_gvariant_get_size(void) { + log_info("/* %s */", __func__); + + assert_se(bus_gvariant_get_size("") == 0); + assert_se(bus_gvariant_get_size("()") == -EINVAL); + assert_se(bus_gvariant_get_size("y") == 1); + assert_se(bus_gvariant_get_size("u") == 4); + assert_se(bus_gvariant_get_size("b") == 1); + assert_se(bus_gvariant_get_size("n") == 2); + assert_se(bus_gvariant_get_size("q") == 2); + assert_se(bus_gvariant_get_size("i") == 4); + assert_se(bus_gvariant_get_size("t") == 8); + assert_se(bus_gvariant_get_size("d") == 8); + assert_se(bus_gvariant_get_size("s") < 0); + assert_se(bus_gvariant_get_size("o") < 0); + assert_se(bus_gvariant_get_size("g") < 0); + assert_se(bus_gvariant_get_size("h") == 4); + assert_se(bus_gvariant_get_size("ay") < 0); + assert_se(bus_gvariant_get_size("v") < 0); + assert_se(bus_gvariant_get_size("(u)") == 4); + assert_se(bus_gvariant_get_size("(uuuuy)") == 20); + assert_se(bus_gvariant_get_size("(uusuuy)") < 0); + assert_se(bus_gvariant_get_size("a{ss}") < 0); + assert_se(bus_gvariant_get_size("((u)yyy(b(iiii)))") == 28); + assert_se(bus_gvariant_get_size("((u)yyy(b(iiivi)))") < 0); + assert_se(bus_gvariant_get_size("((b)(t))") == 16); + assert_se(bus_gvariant_get_size("((b)(b)(t))") == 16); + assert_se(bus_gvariant_get_size("(bt)") == 16); + assert_se(bus_gvariant_get_size("((t)(b))") == 16); + assert_se(bus_gvariant_get_size("(tb)") == 16); + assert_se(bus_gvariant_get_size("((b)(b))") == 2); + assert_se(bus_gvariant_get_size("((t)(t))") == 16); +} + +static void test_bus_gvariant_get_alignment(void) { + log_info("/* %s */", __func__); + + assert_se(bus_gvariant_get_alignment("") == 1); + assert_se(bus_gvariant_get_alignment("()") == -EINVAL); + assert_se(bus_gvariant_get_alignment("y") == 1); + assert_se(bus_gvariant_get_alignment("b") == 1); + assert_se(bus_gvariant_get_alignment("u") == 4); + assert_se(bus_gvariant_get_alignment("s") == 1); + assert_se(bus_gvariant_get_alignment("o") == 1); + assert_se(bus_gvariant_get_alignment("g") == 1); + assert_se(bus_gvariant_get_alignment("v") == 8); + assert_se(bus_gvariant_get_alignment("h") == 4); + assert_se(bus_gvariant_get_alignment("i") == 4); + assert_se(bus_gvariant_get_alignment("t") == 8); + assert_se(bus_gvariant_get_alignment("x") == 8); + assert_se(bus_gvariant_get_alignment("q") == 2); + assert_se(bus_gvariant_get_alignment("n") == 2); + assert_se(bus_gvariant_get_alignment("d") == 8); + assert_se(bus_gvariant_get_alignment("ay") == 1); + assert_se(bus_gvariant_get_alignment("as") == 1); + assert_se(bus_gvariant_get_alignment("au") == 4); + assert_se(bus_gvariant_get_alignment("an") == 2); + assert_se(bus_gvariant_get_alignment("ans") == 2); + assert_se(bus_gvariant_get_alignment("ant") == 8); + assert_se(bus_gvariant_get_alignment("(ss)") == 1); + assert_se(bus_gvariant_get_alignment("(ssu)") == 4); + assert_se(bus_gvariant_get_alignment("a(ssu)") == 4); + assert_se(bus_gvariant_get_alignment("(u)") == 4); + assert_se(bus_gvariant_get_alignment("(uuuuy)") == 4); + assert_se(bus_gvariant_get_alignment("(uusuuy)") == 4); + assert_se(bus_gvariant_get_alignment("a{ss}") == 1); + assert_se(bus_gvariant_get_alignment("((u)yyy(b(iiii)))") == 4); + assert_se(bus_gvariant_get_alignment("((u)yyy(b(iiivi)))") == 8); + assert_se(bus_gvariant_get_alignment("((b)(t))") == 8); + assert_se(bus_gvariant_get_alignment("((b)(b)(t))") == 8); + assert_se(bus_gvariant_get_alignment("(bt)") == 8); + assert_se(bus_gvariant_get_alignment("((t)(b))") == 8); + assert_se(bus_gvariant_get_alignment("(tb)") == 8); + assert_se(bus_gvariant_get_alignment("((b)(b))") == 1); + assert_se(bus_gvariant_get_alignment("((t)(t))") == 8); +} + +static int test_marshal(void) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *n = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ void *blob = NULL; + size_t sz; + int r; + + r = sd_bus_open_user(&bus); + if (r < 0) + r = sd_bus_open_system(&bus); + if (r < 0) + return log_tests_skipped_errno(r, "Failed to connect to bus"); + + bus->message_version = 2; /* dirty hack to enable gvariant */ + + r = sd_bus_message_new_method_call(bus, &m, "a.service.name", + "/an/object/path/which/is/really/really/long/so/that/we/hit/the/eight/bit/boundary/by/quite/some/margin/to/test/this/stuff/that/it/really/works", + "an.interface.name", "AMethodName"); + assert_se(r >= 0); + + assert_cc(sizeof(struct bus_header) == 16); + + assert_se(sd_bus_message_append(m, + "a(usv)", 3, + 4711, "first-string-parameter", "(st)", "X", (uint64_t) 1111, + 4712, "second-string-parameter", "(a(si))", 2, "Y", 5, "Z", 6, + 4713, "third-string-parameter", "(uu)", 1, 2) >= 0); + + assert_se(sd_bus_message_seal(m, 4711, 0) >= 0); + +#if HAVE_GLIB + { + GVariant *v; + char *t; + +#if !defined(GLIB_VERSION_2_36) + g_type_init(); +#endif + + v = g_variant_new_from_data(G_VARIANT_TYPE("(yyyyuta{tv})"), m->header, sizeof(struct bus_header) + m->fields_size, false, NULL, NULL); + assert_se(g_variant_is_normal_form(v)); + t = g_variant_print(v, TRUE); + printf("%s\n", t); + g_free(t); + g_variant_unref(v); + + v = g_variant_new_from_data(G_VARIANT_TYPE("(a(usv))"), m->body.data, m->user_body_size, false, NULL, NULL); + assert_se(g_variant_is_normal_form(v)); + t = g_variant_print(v, TRUE); + printf("%s\n", t); + g_free(t); + g_variant_unref(v); + } +#endif + + assert_se(bus_message_dump(m, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); + + assert_se(bus_message_get_blob(m, &blob, &sz) >= 0); + +#if HAVE_GLIB + { + GVariant *v; + char *t; + + v = g_variant_new_from_data(G_VARIANT_TYPE("(yyyyuta{tv}v)"), blob, sz, false, NULL, NULL); + assert_se(g_variant_is_normal_form(v)); + t = g_variant_print(v, TRUE); + printf("%s\n", t); + g_free(t); + g_variant_unref(v); + } +#endif + + assert_se(bus_message_from_malloc(bus, blob, sz, NULL, 0, NULL, &n) >= 0); + blob = NULL; + + assert_se(bus_message_dump(n, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); + + m = sd_bus_message_unref(m); + + assert_se(sd_bus_message_new_method_call(bus, &m, "a.x", "/a/x", "a.x", "Ax") >= 0); + + assert_se(sd_bus_message_append(m, "as", 0) >= 0); + + assert_se(sd_bus_message_seal(m, 4712, 0) >= 0); + assert_se(bus_message_dump(m, NULL, BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); + + return EXIT_SUCCESS; +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_bus_gvariant_is_fixed_size(); + test_bus_gvariant_get_size(); + test_bus_gvariant_get_alignment(); + + return test_marshal(); +} diff --git a/src/libsystemd/sd-bus/test-bus-introspect.c b/src/libsystemd/sd-bus/test-bus-introspect.c new file mode 100644 index 00000000..9c8d1434 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-introspect.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-introspect.h" +#include "log.h" +#include "tests.h" + +#include "test-vtable-data.h" + +static void test_manual_introspection(const sd_bus_vtable vtable[]) { + struct introspect intro = {}; + _cleanup_free_ char *s = NULL; + + log_info("/* %s */", __func__); + + assert_se(introspect_begin(&intro, false) >= 0); + + fprintf(intro.f, " \n"); + assert_se(introspect_write_interface(&intro, vtable) >= 0); + fputs(" \n", intro.f); + + assert_se(introspect_finish(&intro, &s) == 0); + fputs(s, stdout); + fputs("\n", stdout); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_manual_introspection(test_vtable_1); + test_manual_introspection(test_vtable_2); + test_manual_introspection(test_vtable_deprecated); + test_manual_introspection((const sd_bus_vtable *) vtable_format_221); + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-marshal.c b/src/libsystemd/sd-bus/test-bus-marshal.c new file mode 100644 index 00000000..d7d51ba9 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-marshal.c @@ -0,0 +1,422 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#if HAVE_GLIB +#include +#endif + +#if HAVE_DBUS +#include +#endif + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-dump.h" +#include "bus-label.h" +#include "bus-message.h" +#include "bus-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "tests.h" +#include "util.h" + +static void test_bus_path_encode_unique(void) { + _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL; + + assert_se(bus_path_encode_unique(NULL, "/foo/bar", "some.sender", "a.suffix", &a) >= 0 && streq_ptr(a, "/foo/bar/some_2esender/a_2esuffix")); + assert_se(bus_path_decode_unique(a, "/foo/bar", &b, &c) > 0 && streq_ptr(b, "some.sender") && streq_ptr(c, "a.suffix")); + assert_se(bus_path_decode_unique(a, "/bar/foo", &d, &d) == 0 && !d); + assert_se(bus_path_decode_unique("/foo/bar/onlyOneSuffix", "/foo/bar", &d, &d) == 0 && !d); + assert_se(bus_path_decode_unique("/foo/bar/_/_", "/foo/bar", &d, &e) > 0 && streq_ptr(d, "") && streq_ptr(e, "")); +} + +static void test_bus_path_encode(void) { + _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL; + + assert_se(sd_bus_path_encode("/foo/bar", "waldo", &a) >= 0 && streq(a, "/foo/bar/waldo")); + assert_se(sd_bus_path_decode(a, "/waldo", &b) == 0 && b == NULL); + assert_se(sd_bus_path_decode(a, "/foo/bar", &b) > 0 && streq(b, "waldo")); + + assert_se(sd_bus_path_encode("xxxx", "waldo", &c) < 0); + assert_se(sd_bus_path_encode("/foo/", "waldo", &c) < 0); + + assert_se(sd_bus_path_encode("/foo/bar", "", &c) >= 0 && streq(c, "/foo/bar/_")); + assert_se(sd_bus_path_decode(c, "/foo/bar", &d) > 0 && streq(d, "")); + + assert_se(sd_bus_path_encode("/foo/bar", "foo.bar", &e) >= 0 && streq(e, "/foo/bar/foo_2ebar")); + assert_se(sd_bus_path_decode(e, "/foo/bar", &f) > 0 && streq(f, "foo.bar")); +} + +static void test_bus_path_encode_many(void) { + _cleanup_free_ char *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *f = NULL; + + assert_se(sd_bus_path_decode_many("/foo/bar", "/prefix/%", NULL) == 0); + assert_se(sd_bus_path_decode_many("/prefix/bar", "/prefix/%bar", NULL) == 1); + assert_se(sd_bus_path_decode_many("/foo/bar", "/prefix/%/suffix", NULL) == 0); + assert_se(sd_bus_path_decode_many("/prefix/foobar/suffix", "/prefix/%/suffix", &a) == 1 && streq_ptr(a, "foobar")); + assert_se(sd_bus_path_decode_many("/prefix/one_foo_two/mid/three_bar_four/suffix", "/prefix/one_%_two/mid/three_%_four/suffix", &b, &c) == 1 && streq_ptr(b, "foo") && streq_ptr(c, "bar")); + assert_se(sd_bus_path_decode_many("/prefix/one_foo_two/mid/three_bar_four/suffix", "/prefix/one_%_two/mid/three_%_four/suffix", NULL, &d) == 1 && streq_ptr(d, "bar")); + + assert_se(sd_bus_path_decode_many("/foo/bar", "/foo/bar/%", NULL) == 0); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/bar%", NULL) == 0); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/bar", NULL) == 0); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%bar", NULL) == 0); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/bar/suffix") == 1); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%%/suffix", NULL, NULL) == 0); /* multiple '%' are treated verbatim */ + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/suffi", NULL) == 0); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/suffix", &e) == 1 && streq_ptr(e, "bar")); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/foo/%/%", NULL, NULL) == 1); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%/%", NULL, NULL, NULL) == 1); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "%/%/%", NULL, NULL, NULL) == 0); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%", NULL, NULL) == 0); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/%/", NULL, NULL) == 0); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%/", NULL) == 0); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "/%", NULL) == 0); + assert_se(sd_bus_path_decode_many("/foo/bar/suffix", "%", NULL) == 0); + + assert_se(sd_bus_path_encode_many(&f, "/prefix/one_%_two/mid/three_%_four/suffix", "foo", "bar") >= 0 && streq_ptr(f, "/prefix/one_foo_two/mid/three_bar_four/suffix")); +} + +static void test_bus_label_escape_one(const char *a, const char *b) { + _cleanup_free_ char *t = NULL, *x = NULL, *y = NULL; + + assert_se(t = bus_label_escape(a)); + assert_se(streq(t, b)); + + assert_se(x = bus_label_unescape(t)); + assert_se(streq(a, x)); + + assert_se(y = bus_label_unescape(b)); + assert_se(streq(a, y)); +} + +static void test_bus_label_escape(void) { + test_bus_label_escape_one("foo123bar", "foo123bar"); + test_bus_label_escape_one("foo.bar", "foo_2ebar"); + test_bus_label_escape_one("foo_2ebar", "foo_5f2ebar"); + test_bus_label_escape_one("", "_"); + test_bus_label_escape_one("_", "_5f"); + test_bus_label_escape_one("1", "_31"); + test_bus_label_escape_one(":1", "_3a1"); +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *copy = NULL; + int r, boolean; + const char *x, *x2, *y, *z, *a, *b, *c, *d, *a_signature; + uint8_t u, v; + void *buffer = NULL; + size_t sz; + _cleanup_free_ char *h = NULL; + const int32_t integer_array[] = { -1, -2, 0, 1, 2 }, *return_array; + char *s; + _cleanup_free_ char *first = NULL, *second = NULL, *third = NULL; + _cleanup_fclose_ FILE *ms = NULL; + size_t first_size = 0, second_size = 0, third_size = 0; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + double dbl; + uint64_t u64; + + test_setup_logging(LOG_INFO); + + r = sd_bus_default_user(&bus); + if (r < 0) + r = sd_bus_default_system(&bus); + if (r < 0) + return log_tests_skipped("Failed to connect to bus"); + + r = sd_bus_message_new_method_call(bus, &m, "foobar.waldo", "/", "foobar.waldo", "Piep"); + assert_se(r >= 0); + + r = sd_bus_message_append(m, ""); + assert_se(r >= 0); + + r = sd_bus_message_append(m, "s", "a string"); + assert_se(r >= 0); + + r = sd_bus_message_append(m, "s", NULL); + assert_se(r >= 0); + + r = sd_bus_message_append(m, "asg", 2, "string #1", "string #2", "sba(tt)ss"); + assert_se(r >= 0); + + r = sd_bus_message_append(m, "sass", "foobar", 5, "foo", "bar", "waldo", "piep", "pap", "after"); + assert_se(r >= 0); + + r = sd_bus_message_append(m, "a{yv}", 2, 3, "s", "foo", 5, "s", "waldo"); + assert_se(r >= 0); + + r = sd_bus_message_append(m, "y(ty)y(yt)y", 8, 777ULL, 7, 9, 77, 7777ULL, 10); + assert_se(r >= 0); + + r = sd_bus_message_append(m, "()"); + assert_se(r == -EINVAL); + + r = sd_bus_message_append(m, "ba(ss)", 255, 3, "aaa", "1", "bbb", "2", "ccc", "3"); + assert_se(r >= 0); + + r = sd_bus_message_open_container(m, 'a', "s"); + assert_se(r >= 0); + + r = sd_bus_message_append_basic(m, 's', "foobar"); + assert_se(r >= 0); + + r = sd_bus_message_append_basic(m, 's', "waldo"); + assert_se(r >= 0); + + r = sd_bus_message_close_container(m); + assert_se(r >= 0); + + r = sd_bus_message_append_string_space(m, 5, &s); + assert_se(r >= 0); + strcpy(s, "hallo"); + + r = sd_bus_message_append_array(m, 'i', integer_array, sizeof(integer_array)); + assert_se(r >= 0); + + r = sd_bus_message_append_array(m, 'u', NULL, 0); + assert_se(r >= 0); + + r = sd_bus_message_append(m, "a(stdo)", 1, "foo", 815ULL, 47.0, "/"); + assert_se(r >= 0); + + r = sd_bus_message_seal(m, 4711, 0); + assert_se(r >= 0); + + bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + ms = open_memstream_unlocked(&first, &first_size); + bus_message_dump(m, ms, 0); + fflush(ms); + assert_se(!ferror(ms)); + + r = bus_message_get_blob(m, &buffer, &sz); + assert_se(r >= 0); + + h = cescape_length(buffer, sz); + assert_se(h); + log_info("message size = %zu, contents =\n%s", sz, h); + +#if HAVE_GLIB + /* Work-around for asan bug. See c8d980a3e962aba2ea3a4cedf75fa94890a6d746. */ +#if !HAS_FEATURE_ADDRESS_SANITIZER + { + GDBusMessage *g; + char *p; + +#if !defined(GLIB_VERSION_2_36) + g_type_init(); +#endif + + g = g_dbus_message_new_from_blob(buffer, sz, 0, NULL); + p = g_dbus_message_print(g, 0); + log_info("%s", p); + g_free(p); + g_object_unref(g); + } +#endif +#endif + +#if HAVE_DBUS + { + DBusMessage *w; + DBusError error; + + dbus_error_init(&error); + + w = dbus_message_demarshal(buffer, sz, &error); + if (!w) + log_error("%s", error.message); + else + dbus_message_unref(w); + + dbus_error_free(&error); + } +#endif + + m = sd_bus_message_unref(m); + + r = bus_message_from_malloc(bus, buffer, sz, NULL, 0, NULL, &m); + assert_se(r >= 0); + + bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + fclose(ms); + ms = open_memstream_unlocked(&second, &second_size); + bus_message_dump(m, ms, 0); + fflush(ms); + assert_se(!ferror(ms)); + assert_se(first_size == second_size); + assert_se(memcmp(first, second, first_size) == 0); + + assert_se(sd_bus_message_rewind(m, true) >= 0); + + r = sd_bus_message_read(m, "ssasg", &x, &x2, 2, &y, &z, &a_signature); + assert_se(r > 0); + assert_se(streq(x, "a string")); + assert_se(streq(x2, "")); + assert_se(streq(y, "string #1")); + assert_se(streq(z, "string #2")); + assert_se(streq(a_signature, "sba(tt)ss")); + + r = sd_bus_message_read(m, "sass", &x, 5, &y, &z, &a, &b, &c, &d); + assert_se(r > 0); + assert_se(streq(x, "foobar")); + assert_se(streq(y, "foo")); + assert_se(streq(z, "bar")); + assert_se(streq(a, "waldo")); + assert_se(streq(b, "piep")); + assert_se(streq(c, "pap")); + assert_se(streq(d, "after")); + + r = sd_bus_message_read(m, "a{yv}", 2, &u, "s", &x, &v, "s", &y); + assert_se(r > 0); + assert_se(u == 3); + assert_se(streq(x, "foo")); + assert_se(v == 5); + assert_se(streq(y, "waldo")); + + r = sd_bus_message_read(m, "y(ty)", &v, &u64, &u); + assert_se(r > 0); + assert_se(v == 8); + assert_se(u64 == 777); + assert_se(u == 7); + + r = sd_bus_message_read(m, "y(yt)", &v, &u, &u64); + assert_se(r > 0); + assert_se(v == 9); + assert_se(u == 77); + assert_se(u64 == 7777); + + r = sd_bus_message_read(m, "y", &v); + assert_se(r > 0); + assert_se(v == 10); + + r = sd_bus_message_read(m, "()"); + assert_se(r < 0); + + r = sd_bus_message_read(m, "ba(ss)", &boolean, 3, &x, &y, &a, &b, &c, &d); + assert_se(r > 0); + assert_se(boolean); + assert_se(streq(x, "aaa")); + assert_se(streq(y, "1")); + assert_se(streq(a, "bbb")); + assert_se(streq(b, "2")); + assert_se(streq(c, "ccc")); + assert_se(streq(d, "3")); + + assert_se(sd_bus_message_verify_type(m, 'a', "s") > 0); + + r = sd_bus_message_read(m, "as", 2, &x, &y); + assert_se(r > 0); + assert_se(streq(x, "foobar")); + assert_se(streq(y, "waldo")); + + r = sd_bus_message_read_basic(m, 's', &s); + assert_se(r > 0); + assert_se(streq(s, "hallo")); + + r = sd_bus_message_read_array(m, 'i', (const void**) &return_array, &sz); + assert_se(r > 0); + assert_se(sz == sizeof(integer_array)); + assert_se(memcmp(integer_array, return_array, sz) == 0); + + r = sd_bus_message_read_array(m, 'u', (const void**) &return_array, &sz); + assert_se(r > 0); + assert_se(sz == 0); + + r = sd_bus_message_read(m, "a(stdo)", 1, &x, &u64, &dbl, &y); + assert_se(r > 0); + assert_se(streq(x, "foo")); + assert_se(u64 == 815ULL); + assert_se(fabs(dbl - 47.0) < 0.1); + assert_se(streq(y, "/")); + + r = sd_bus_message_peek_type(m, NULL, NULL); + assert_se(r == 0); + + r = sd_bus_message_new_method_call(bus, ©, "foobar.waldo", "/", "foobar.waldo", "Piep"); + assert_se(r >= 0); + + r = sd_bus_message_rewind(m, true); + assert_se(r >= 0); + + r = sd_bus_message_copy(copy, m, true); + assert_se(r >= 0); + + r = sd_bus_message_seal(copy, 4712, 0); + assert_se(r >= 0); + + fclose(ms); + ms = open_memstream_unlocked(&third, &third_size); + bus_message_dump(copy, ms, 0); + fflush(ms); + assert_se(!ferror(ms)); + + printf("<%.*s>\n", (int) first_size, first); + printf("<%.*s>\n", (int) third_size, third); + + assert_se(first_size == third_size); + assert_se(memcmp(first, third, third_size) == 0); + + r = sd_bus_message_rewind(m, true); + assert_se(r >= 0); + + assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0); + + r = sd_bus_message_skip(m, "ssasg"); + assert_se(r > 0); + + assert_se(sd_bus_message_verify_type(m, 's', NULL) > 0); + + r = sd_bus_message_skip(m, "sass"); + assert_se(r >= 0); + + assert_se(sd_bus_message_verify_type(m, 'a', "{yv}") > 0); + + r = sd_bus_message_skip(m, "a{yv}y(ty)y(yt)y"); + assert_se(r >= 0); + + assert_se(sd_bus_message_verify_type(m, 'b', NULL) > 0); + + r = sd_bus_message_read(m, "b", &boolean); + assert_se(r > 0); + assert_se(boolean); + + r = sd_bus_message_enter_container(m, 0, NULL); + assert_se(r > 0); + + r = sd_bus_message_read(m, "(ss)", &x, &y); + assert_se(r > 0); + + r = sd_bus_message_read(m, "(ss)", &a, &b); + assert_se(r > 0); + + r = sd_bus_message_read(m, "(ss)", &c, &d); + assert_se(r > 0); + + r = sd_bus_message_read(m, "(ss)", &x, &y); + assert_se(r == 0); + + r = sd_bus_message_exit_container(m); + assert_se(r >= 0); + + assert_se(streq(x, "aaa")); + assert_se(streq(y, "1")); + assert_se(streq(a, "bbb")); + assert_se(streq(b, "2")); + assert_se(streq(c, "ccc")); + assert_se(streq(d, "3")); + + test_bus_label_escape(); + test_bus_path_encode(); + test_bus_path_encode_unique(); + test_bus_path_encode_many(); + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-match.c b/src/libsystemd/sd-bus/test-bus-match.c new file mode 100644 index 00000000..47014c40 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-match.c @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-match.h" +#include "bus-message.h" +#include "bus-slot.h" +#include "bus-util.h" +#include "log.h" +#include "macro.h" +#include "memory-util.h" +#include "tests.h" + +static bool mask[32]; + +static int filter(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + log_info("Ran %u", PTR_TO_UINT(userdata)); + assert_se(PTR_TO_UINT(userdata) < ELEMENTSOF(mask)); + mask[PTR_TO_UINT(userdata)] = true; + return 0; +} + +static bool mask_contains(unsigned a[], unsigned n) { + unsigned i, j; + + for (i = 0; i < ELEMENTSOF(mask); i++) { + bool found = false; + + for (j = 0; j < n; j++) + if (a[j] == i) { + found = true; + break; + } + + if (found != mask[i]) + return false; + } + + return true; +} + +static int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char *match, int value) { + struct bus_match_component *components = NULL; + unsigned n_components = 0; + sd_bus_slot *s; + int r; + + s = slots + value; + zero(*s); + + r = bus_match_parse(match, &components, &n_components); + if (r < 0) + return r; + + s->userdata = INT_TO_PTR(value); + s->match_callback.callback = filter; + + r = bus_match_add(root, components, n_components, &s->match_callback); + bus_match_parse_free(components, n_components); + + return r; +} + +static void test_match_scope(const char *match, enum bus_match_scope scope) { + struct bus_match_component *components = NULL; + unsigned n_components = 0; + + assert_se(bus_match_parse(match, &components, &n_components) >= 0); + assert_se(bus_match_get_scope(components, n_components) == scope); + bus_match_parse_free(components, n_components); +} + +int main(int argc, char *argv[]) { + struct bus_match_node root = { + .type = BUS_MATCH_ROOT, + }; + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + enum bus_match_node_type i; + sd_bus_slot slots[19]; + int r; + + test_setup_logging(LOG_INFO); + + r = sd_bus_open_user(&bus); + if (r < 0) + r = sd_bus_open_system(&bus); + if (r < 0) + return log_tests_skipped("Failed to connect to bus"); + + assert_se(match_add(slots, &root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0); + assert_se(match_add(slots, &root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0); + assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0); + assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0); + assert_se(match_add(slots, &root, "", 5) >= 0); + assert_se(match_add(slots, &root, "interface='quux.x'", 6) >= 0); + assert_se(match_add(slots, &root, "interface='bar.x'", 7) >= 0); + assert_se(match_add(slots, &root, "member='waldo',path='/foo/bar'", 8) >= 0); + assert_se(match_add(slots, &root, "path='/foo/bar'", 9) >= 0); + assert_se(match_add(slots, &root, "path_namespace='/foo'", 10) >= 0); + assert_se(match_add(slots, &root, "path_namespace='/foo/quux'", 11) >= 0); + assert_se(match_add(slots, &root, "arg1='two'", 12) >= 0); + assert_se(match_add(slots, &root, "member='waldo',arg2path='/prefix/'", 13) >= 0); + assert_se(match_add(slots, &root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0); + assert_se(match_add(slots, &root, "arg4has='pi'", 15) >= 0); + assert_se(match_add(slots, &root, "arg4has='pa'", 16) >= 0); + assert_se(match_add(slots, &root, "arg4has='po'", 17) >= 0); + assert_se(match_add(slots, &root, "arg4='pi'", 18) >= 0); + + bus_match_dump(&root, 0); + + assert_se(sd_bus_message_new_signal(bus, &m, "/foo/bar", "bar.x", "waldo") >= 0); + assert_se(sd_bus_message_append(m, "ssssas", "one", "two", "/prefix/three", "prefix.four", 3, "pi", "pa", "po") >= 0); + assert_se(sd_bus_message_seal(m, 1, 0) >= 0); + + zero(mask); + assert_se(bus_match_run(NULL, &root, m) == 0); + assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14, 15, 16, 17 }, 11)); + + assert_se(bus_match_remove(&root, &slots[8].match_callback) >= 0); + assert_se(bus_match_remove(&root, &slots[13].match_callback) >= 0); + + bus_match_dump(&root, 0); + + zero(mask); + assert_se(bus_match_run(NULL, &root, m) == 0); + assert_se(mask_contains((unsigned[]) { 9, 5, 10, 12, 14, 7, 15, 16, 17 }, 9)); + + for (i = 0; i < _BUS_MATCH_NODE_TYPE_MAX; i++) { + char buf[32]; + const char *x; + + assert_se(x = bus_match_node_type_to_string(i, buf, sizeof(buf))); + + if (i >= BUS_MATCH_MESSAGE_TYPE) + assert_se(bus_match_node_type_from_string(x, strlen(x)) == i); + } + + bus_match_free(&root); + + test_match_scope("interface='foobar'", BUS_MATCH_GENERIC); + test_match_scope("", BUS_MATCH_GENERIC); + test_match_scope("interface='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL); + test_match_scope("sender='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL); + test_match_scope("member='gurke',path='/org/freedesktop/DBus/Local'", BUS_MATCH_LOCAL); + test_match_scope("arg2='piep',sender='org.freedesktop.DBus',member='waldo'", BUS_MATCH_DRIVER); + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-objects.c b/src/libsystemd/sd-bus/test-bus-objects.c new file mode 100644 index 00000000..3c5bb88f --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-objects.c @@ -0,0 +1,536 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-dump.h" +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-util.h" +#include "log.h" +#include "macro.h" +#include "strv.h" +#include "util.h" + +struct context { + int fds[2]; + bool quit; + char *something; + char *automatic_string_property; + uint32_t automatic_integer_property; +}; + +static int something_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) { + struct context *c = userdata; + const char *s; + char *n = NULL; + int r; + + r = sd_bus_message_read(m, "s", &s); + assert_se(r > 0); + + n = strjoin("<<<", s, ">>>"); + assert_se(n); + + free(c->something); + c->something = n; + + log_info("AlterSomething() called, got %s, returning %s", s, n); + + /* This should fail, since the return type doesn't match */ + assert_se(sd_bus_reply_method_return(m, "u", 4711) == -ENOMSG); + + r = sd_bus_reply_method_return(m, "s", n); + assert_se(r >= 0); + + return 1; +} + +static int exit_handler(sd_bus_message *m, void *userdata, sd_bus_error *error) { + struct context *c = userdata; + int r; + + c->quit = true; + + log_info("Exit called"); + + r = sd_bus_reply_method_return(m, ""); + assert_se(r >= 0); + + return 1; +} + +static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { + struct context *c = userdata; + int r; + + log_info("property get for %s called, returning \"%s\".", property, c->something); + + r = sd_bus_message_append(reply, "s", c->something); + assert_se(r >= 0); + + return 1; +} + +static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) { + struct context *c = userdata; + const char *s; + char *n; + int r; + + log_info("property set for %s called", property); + + r = sd_bus_message_read(value, "s", &s); + assert_se(r >= 0); + + n = strdup(s); + assert_se(n); + + free(c->something); + c->something = n; + + return 1; +} + +static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *s = NULL; + const char *x; + int r; + + assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0); + r = sd_bus_message_append(reply, "s", s); + assert_se(r >= 0); + + assert_se(x = startswith(path, "/value/")); + + assert_se(PTR_TO_UINT(userdata) == 30); + + return 1; +} + +static int notify_test(sd_bus_message *m, void *userdata, sd_bus_error *error) { + int r; + + assert_se(sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0); + + r = sd_bus_reply_method_return(m, NULL); + assert_se(r >= 0); + + return 1; +} + +static int notify_test2(sd_bus_message *m, void *userdata, sd_bus_error *error) { + int r; + + assert_se(sd_bus_emit_properties_changed_strv(sd_bus_message_get_bus(m), m->path, "org.freedesktop.systemd.ValueTest", NULL) >= 0); + + r = sd_bus_reply_method_return(m, NULL); + assert_se(r >= 0); + + return 1; +} + +static int emit_interfaces_added(sd_bus_message *m, void *userdata, sd_bus_error *error) { + int r; + + assert_se(sd_bus_emit_interfaces_added(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0); + + r = sd_bus_reply_method_return(m, NULL); + assert_se(r >= 0); + + return 1; +} + +static int emit_interfaces_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + int r; + + assert_se(sd_bus_emit_interfaces_removed(sd_bus_message_get_bus(m), "/value/a/x", "org.freedesktop.systemd.ValueTest", NULL) >= 0); + + r = sd_bus_reply_method_return(m, NULL); + assert_se(r >= 0); + + return 1; +} + +static int emit_object_added(sd_bus_message *m, void *userdata, sd_bus_error *error) { + int r; + + assert_se(sd_bus_emit_object_added(sd_bus_message_get_bus(m), "/value/a/x") >= 0); + + r = sd_bus_reply_method_return(m, NULL); + assert_se(r >= 0); + + return 1; +} + +static int emit_object_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + int r; + + assert_se(sd_bus_emit_object_removed(sd_bus_message_get_bus(m), "/value/a/x") >= 0); + + r = sd_bus_reply_method_return(m, NULL); + assert_se(r >= 0); + + return 1; +} + +static const sd_bus_vtable vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0), + SD_BUS_METHOD("Exit", "", "", exit_handler, 0), + SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0), + SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, offsetof(struct context, automatic_string_property), 0), + SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, offsetof(struct context, automatic_integer_property), 0), + SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0), + SD_BUS_METHOD("EmitInterfacesAdded", NULL, NULL, emit_interfaces_added, 0), + SD_BUS_METHOD("EmitInterfacesRemoved", NULL, NULL, emit_interfaces_removed, 0), + SD_BUS_METHOD("EmitObjectAdded", NULL, NULL, emit_object_added, 0), + SD_BUS_METHOD("EmitObjectRemoved", NULL, NULL, emit_object_removed, 0), + SD_BUS_VTABLE_END +}; + +static const sd_bus_vtable vtable2[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD("NotifyTest", "", "", notify_test, 0), + SD_BUS_METHOD("NotifyTest2", "", "", notify_test2, 0), + SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0), + SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something), SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_VTABLE_END +}; + +static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + + if (object_path_startswith("/value", path)) + assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c")); + + return 1; +} + +static int enumerator2_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + + if (object_path_startswith("/value/a", path)) + assert_se(*nodes = strv_new("/value/a/x", "/value/a/y", "/value/a/z")); + + return 1; +} + +static void *server(void *p) { + struct context *c = p; + sd_bus *bus = NULL; + sd_id128_t id; + int r; + + c->quit = false; + + assert_se(sd_id128_randomize(&id) >= 0); + + assert_se(sd_bus_new(&bus) >= 0); + assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0); + assert_se(sd_bus_set_server(bus, 1, id) >= 0); + + assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0); + assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0); + assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0); + assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0); + assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0); + assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0); + assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0); + + assert_se(sd_bus_start(bus) >= 0); + + log_error("Entering event loop on server"); + + while (!c->quit) { + log_error("Loop!"); + + r = sd_bus_process(bus, NULL); + if (r < 0) { + log_error_errno(r, "Failed to process requests: %m"); + goto fail; + } + + if (r == 0) { + r = sd_bus_wait(bus, (uint64_t) -1); + if (r < 0) { + log_error_errno(r, "Failed to wait: %m"); + goto fail; + } + + continue; + } + } + + r = 0; + +fail: + if (bus) { + sd_bus_flush(bus); + sd_bus_unref(bus); + } + + return INT_TO_PTR(r); +} + +static int client(struct context *c) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *s; + int r; + + assert_se(sd_bus_new(&bus) >= 0); + assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0); + assert_se(sd_bus_start(bus) >= 0); + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL); + assert_se(r >= 0); + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo"); + assert_se(r >= 0); + + r = sd_bus_message_read(reply, "s", &s); + assert_se(r >= 0); + assert_se(streq(s, "<<>>")); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, ""); + assert_se(r < 0); + assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)); + + sd_bus_error_free(&error); + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo"); + assert_se(r < 0); + assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS)); + + sd_bus_error_free(&error); + + r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s"); + assert_se(r >= 0); + + r = sd_bus_message_read(reply, "s", &s); + assert_se(r >= 0); + assert_se(streq(s, "<<>>")); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test"); + assert_se(r >= 0); + + r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s"); + assert_se(r >= 0); + + r = sd_bus_message_read(reply, "s", &s); + assert_se(r >= 0); + assert_se(streq(s, "test")); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815); + assert_se(r >= 0); + + assert_se(c->automatic_integer_property == 815); + + r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!"); + assert_se(r >= 0); + + assert_se(streq(c->automatic_string_property, "Du Dödel, Du!")); + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); + assert_se(r >= 0); + + r = sd_bus_message_read(reply, "s", &s); + assert_se(r >= 0); + fputs(s, stdout); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s"); + assert_se(r >= 0); + + r = sd_bus_message_read(reply, "s", &s); + assert_se(r >= 0); + log_info("read %s", s); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); + assert_se(r >= 0); + + r = sd_bus_message_read(reply, "s", &s); + assert_se(r >= 0); + fputs(s, stdout); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); + assert_se(r >= 0); + + r = sd_bus_message_read(reply, "s", &s); + assert_se(r >= 0); + fputs(s, stdout); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, ""); + assert_se(r >= 0); + + r = sd_bus_message_read(reply, "s", &s); + assert_se(r >= 0); + fputs(s, stdout); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", ""); + assert_se(r >= 0); + + bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2"); + assert_se(r < 0); + assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE)); + sd_bus_error_free(&error); + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, ""); + assert_se(r < 0); + assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)); + sd_bus_error_free(&error); + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, ""); + assert_se(r >= 0); + + bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, ""); + assert_se(r >= 0); + + r = sd_bus_process(bus, &reply); + assert_se(r > 0); + + assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged")); + bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, ""); + assert_se(r >= 0); + + r = sd_bus_process(bus, &reply); + assert_se(r > 0); + + assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged")); + bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, ""); + assert_se(r >= 0); + + r = sd_bus_process(bus, &reply); + assert_se(r > 0); + + assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded")); + bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, ""); + assert_se(r >= 0); + + r = sd_bus_process(bus, &reply); + assert_se(r > 0); + + assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved")); + bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, ""); + assert_se(r >= 0); + + r = sd_bus_process(bus, &reply); + assert_se(r > 0); + + assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded")); + bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, ""); + assert_se(r >= 0); + + r = sd_bus_process(bus, &reply); + assert_se(r > 0); + + assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved")); + bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER); + + sd_bus_message_unref(reply); + reply = NULL; + + r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, ""); + assert_se(r >= 0); + + sd_bus_flush(bus); + + return 0; +} + +int main(int argc, char *argv[]) { + struct context c = {}; + pthread_t s; + void *p; + int r, q; + + c.automatic_integer_property = 4711; + assert_se(c.automatic_string_property = strdup("dudeldu")); + + assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0); + + r = pthread_create(&s, NULL, server, &c); + if (r != 0) + return -r; + + r = client(&c); + + q = pthread_join(s, &p); + if (q != 0) + return -q; + + if (r < 0) + return r; + + if (PTR_TO_INT(p) < 0) + return PTR_TO_INT(p); + + free(c.something); + free(c.automatic_string_property); + + return EXIT_SUCCESS; +} diff --git a/src/libsystemd/sd-bus/test-bus-queue-ref-cycle.c b/src/libsystemd/sd-bus/test-bus-queue-ref-cycle.c new file mode 100644 index 00000000..17598f3d --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-queue-ref-cycle.c @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#include "sd-bus.h" + +#include "main-func.h" +#include "tests.h" + +static int test_ref_unref(void) { + sd_bus_message *m = NULL; + sd_bus *bus = NULL; + int r; + + /* This test will result in a memory leak in <= v240, but not on v241. Hence to be really useful it + * should be run through a leak tracker such as valgrind. */ + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_tests_skipped("Failed to connect to bus"); + + /* Create a message and enqueue it (this shouldn't send it though as the connection setup is not complete yet) */ + assert_se(sd_bus_message_new_method_call(bus, &m, "foo.bar", "/foo", "quux.quux", "waldo") >= 0); + assert_se(sd_bus_send(bus, m, NULL) >= 0); + + /* Let's now unref the message first and the bus second. */ + m = sd_bus_message_unref(m); + bus = sd_bus_unref(bus); + + /* We should have a memory leak now on <= v240. Let's do this again, but destroy in the opposite + * order. On v240 that too should be a leak. */ + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_tests_skipped("Failed to connect to bus"); + + assert_se(sd_bus_message_new_method_call(bus, &m, "foo.bar", "/foo", "quux.quux", "waldo") >= 0); + assert_se(sd_bus_send(bus, m, NULL) >= 0); + + /* Let's now unref things in the opposite order */ + bus = sd_bus_unref(bus); + m = sd_bus_message_unref(m); + + return 0; +} + +static int run(int argc, char *argv[]) { + int r; + + test_setup_logging(LOG_INFO); + + r = test_ref_unref(); + if (r < 0) + return r; + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c new file mode 100644 index 00000000..82eb35e5 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-server.c @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "bus-internal.h" +#include "bus-util.h" +#include "log.h" +#include "macro.h" +#include "memory-util.h" + +struct context { + int fds[2]; + + bool client_negotiate_unix_fds; + bool server_negotiate_unix_fds; + + bool client_anonymous_auth; + bool server_anonymous_auth; +}; + +static void *server(void *p) { + struct context *c = p; + sd_bus *bus = NULL; + sd_id128_t id; + bool quit = false; + int r; + + assert_se(sd_id128_randomize(&id) >= 0); + + assert_se(sd_bus_new(&bus) >= 0); + assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0); + assert_se(sd_bus_set_server(bus, 1, id) >= 0); + assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0); + assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0); + assert_se(sd_bus_start(bus) >= 0); + + while (!quit) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + + r = sd_bus_process(bus, &m); + if (r < 0) { + log_error_errno(r, "Failed to process requests: %m"); + goto fail; + } + + if (r == 0) { + r = sd_bus_wait(bus, (uint64_t) -1); + if (r < 0) { + log_error_errno(r, "Failed to wait: %m"); + goto fail; + } + + continue; + } + + if (!m) + continue; + + log_info("Got message! member=%s", strna(sd_bus_message_get_member(m))); + + if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) { + + assert_se((sd_bus_can_send(bus, 'h') >= 1) == + (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds)); + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) { + log_error_errno(r, "Failed to allocate return: %m"); + goto fail; + } + + quit = true; + + } else if (sd_bus_message_is_method_call(m, NULL, NULL)) { + r = sd_bus_message_new_method_error( + m, + &reply, + &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method.")); + if (r < 0) { + log_error_errno(r, "Failed to allocate return: %m"); + goto fail; + } + } + + if (reply) { + r = sd_bus_send(bus, reply, NULL); + if (r < 0) { + log_error_errno(r, "Failed to send reply: %m"); + goto fail; + } + } + } + + r = 0; + +fail: + if (bus) { + sd_bus_flush(bus); + sd_bus_unref(bus); + } + + return INT_TO_PTR(r); +} + +static int client(struct context *c) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert_se(sd_bus_new(&bus) >= 0); + assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0); + assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0); + assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0); + assert_se(sd_bus_start(bus) >= 0); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd.test", + "/", + "org.freedesktop.systemd.test", + "Exit"); + if (r < 0) + return log_error_errno(r, "Failed to allocate method call: %m"); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, -r)); + + return 0; +} + +static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_fds, + bool client_anonymous_auth, bool server_anonymous_auth) { + + struct context c; + pthread_t s; + void *p; + int r, q; + + zero(c); + + assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0); + + c.client_negotiate_unix_fds = client_negotiate_unix_fds; + c.server_negotiate_unix_fds = server_negotiate_unix_fds; + c.client_anonymous_auth = client_anonymous_auth; + c.server_anonymous_auth = server_anonymous_auth; + + r = pthread_create(&s, NULL, server, &c); + if (r != 0) + return -r; + + r = client(&c); + + q = pthread_join(s, &p); + if (q != 0) + return -q; + + if (r < 0) + return r; + + if (PTR_TO_INT(p) < 0) + return PTR_TO_INT(p); + + return 0; +} + +int main(int argc, char *argv[]) { + int r; + + r = test_one(true, true, false, false); + assert_se(r >= 0); + + r = test_one(true, false, false, false); + assert_se(r >= 0); + + r = test_one(false, true, false, false); + assert_se(r >= 0); + + r = test_one(false, false, false, false); + assert_se(r >= 0); + + r = test_one(true, true, true, true); + assert_se(r >= 0); + + r = test_one(true, true, false, true); + assert_se(r >= 0); + + r = test_one(true, true, true, false); + assert_se(r == -EPERM); + + return EXIT_SUCCESS; +} diff --git a/src/libsystemd/sd-bus/test-bus-signature.c b/src/libsystemd/sd-bus/test-bus-signature.c new file mode 100644 index 00000000..84648dbc --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-signature.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-internal.h" +#include "bus-signature.h" +#include "log.h" +#include "string-util.h" + +int main(int argc, char *argv[]) { + char prefix[256]; + int r; + + assert_se(signature_is_single("y", false)); + assert_se(signature_is_single("u", false)); + assert_se(signature_is_single("v", false)); + assert_se(signature_is_single("as", false)); + assert_se(signature_is_single("(ss)", false)); + assert_se(!signature_is_single("()", false)); + assert_se(!signature_is_single("(()()()()())", false)); + assert_se(!signature_is_single("(((())))", false)); + assert_se(signature_is_single("((((s))))", false)); + assert_se(signature_is_single("{ss}", true)); + assert_se(signature_is_single("a{ss}", false)); + assert_se(!signature_is_single("uu", false)); + assert_se(!signature_is_single("", false)); + assert_se(!signature_is_single("(", false)); + assert_se(!signature_is_single(")", false)); + assert_se(!signature_is_single("())", false)); + assert_se(!signature_is_single("((())", false)); + assert_se(!signature_is_single("{)", false)); + assert_se(!signature_is_single("{}", true)); + assert_se(!signature_is_single("{sss}", true)); + assert_se(!signature_is_single("{s}", true)); + assert_se(!signature_is_single("{ss}", false)); + assert_se(!signature_is_single("{ass}", true)); + assert_se(!signature_is_single("a}", true)); + + assert_se(signature_is_pair("yy")); + assert_se(signature_is_pair("ss")); + assert_se(signature_is_pair("sas")); + assert_se(signature_is_pair("sv")); + assert_se(signature_is_pair("sa(vs)")); + assert_se(!signature_is_pair("")); + assert_se(!signature_is_pair("va")); + assert_se(!signature_is_pair("sss")); + assert_se(!signature_is_pair("{s}ss")); + + assert_se(signature_is_valid("ssa{ss}sssub", true)); + assert_se(signature_is_valid("ssa{ss}sssub", false)); + assert_se(signature_is_valid("{ss}", true)); + assert_se(!signature_is_valid("{ss}", false)); + assert_se(signature_is_valid("", true)); + assert_se(signature_is_valid("", false)); + + assert_se(signature_is_valid("sssusa(uuubbba(uu)uuuu)a{u(uuuvas)}", false)); + + assert_se(!signature_is_valid("a", false)); + assert_se(signature_is_valid("as", false)); + assert_se(signature_is_valid("aas", false)); + assert_se(signature_is_valid("aaas", false)); + assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad", false)); + assert_se(signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaas", false)); + assert_se(!signature_is_valid("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaau", false)); + + assert_se(signature_is_valid("((((((((((((((((((((((((((((((((s))))))))))))))))))))))))))))))))", false)); + assert_se(!signature_is_valid("((((((((((((((((((((((((((((((((()))))))))))))))))))))))))))))))))", false)); + + assert_se(namespace_complex_pattern("", "")); + assert_se(namespace_complex_pattern("foobar", "foobar")); + assert_se(namespace_complex_pattern("foobar.waldo", "foobar.waldo")); + assert_se(namespace_complex_pattern("foobar.", "foobar.waldo")); + assert_se(namespace_complex_pattern("foobar.waldo", "foobar.")); + assert_se(!namespace_complex_pattern("foobar.waldo", "foobar")); + assert_se(!namespace_complex_pattern("foobar", "foobar.waldo")); + assert_se(!namespace_complex_pattern("", "foo")); + assert_se(!namespace_complex_pattern("foo", "")); + assert_se(!namespace_complex_pattern("foo.", "")); + + assert_se(path_complex_pattern("", "")); + assert_se(!path_complex_pattern("", "/")); + assert_se(!path_complex_pattern("/", "")); + assert_se(path_complex_pattern("/", "/")); + assert_se(path_complex_pattern("/foobar/", "/")); + assert_se(!path_complex_pattern("/foobar/", "/foobar")); + assert_se(path_complex_pattern("/foobar", "/foobar")); + assert_se(!path_complex_pattern("/foobar", "/foobar/")); + assert_se(!path_complex_pattern("/foobar", "/foobar/waldo")); + assert_se(path_complex_pattern("/foobar/", "/foobar/waldo")); + assert_se(path_complex_pattern("/foobar/waldo", "/foobar/")); + + assert_se(path_simple_pattern("/foo/", "/foo/bar/waldo")); + + assert_se(namespace_simple_pattern("", "")); + assert_se(namespace_simple_pattern("", ".foobar")); + assert_se(namespace_simple_pattern("foobar", "foobar")); + assert_se(namespace_simple_pattern("foobar.waldo", "foobar.waldo")); + assert_se(namespace_simple_pattern("foobar", "foobar.waldo")); + assert_se(!namespace_simple_pattern("foobar.waldo", "foobar")); + assert_se(!namespace_simple_pattern("", "foo")); + assert_se(!namespace_simple_pattern("foo", "")); + assert_se(namespace_simple_pattern("foo.", "foo.bar.waldo")); + + assert_se(streq(object_path_startswith("/foo/bar", "/foo"), "bar")); + assert_se(streq(object_path_startswith("/foo", "/foo"), "")); + assert_se(streq(object_path_startswith("/foo", "/"), "foo")); + assert_se(streq(object_path_startswith("/", "/"), "")); + assert_se(!object_path_startswith("/foo", "/bar")); + assert_se(!object_path_startswith("/", "/bar")); + assert_se(!object_path_startswith("/foo", "")); + + assert_se(object_path_is_valid("/foo/bar")); + assert_se(object_path_is_valid("/foo")); + assert_se(object_path_is_valid("/")); + assert_se(object_path_is_valid("/foo5")); + assert_se(object_path_is_valid("/foo_5")); + assert_se(!object_path_is_valid("")); + assert_se(!object_path_is_valid("/foo/")); + assert_se(!object_path_is_valid("//")); + assert_se(!object_path_is_valid("//foo")); + assert_se(!object_path_is_valid("/foo//bar")); + assert_se(!object_path_is_valid("/foo/aaaäöä")); + + OBJECT_PATH_FOREACH_PREFIX(prefix, "/") { + log_info("<%s>", prefix); + assert_not_reached("???"); + } + + r = 0; + OBJECT_PATH_FOREACH_PREFIX(prefix, "/xxx") { + log_info("<%s>", prefix); + assert_se(streq(prefix, "/")); + assert_se(r == 0); + r++; + } + assert_se(r == 1); + + r = 0; + OBJECT_PATH_FOREACH_PREFIX(prefix, "/xxx/yyy/zzz") { + log_info("<%s>", prefix); + assert_se(r != 0 || streq(prefix, "/xxx/yyy")); + assert_se(r != 1 || streq(prefix, "/xxx")); + assert_se(r != 2 || streq(prefix, "/")); + r++; + } + assert_se(r == 3); + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-track.c b/src/libsystemd/sd-bus/test-bus-track.c new file mode 100644 index 00000000..68a00103 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-track.c @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "macro.h" +#include "tests.h" + +static bool track_cb_called_x = false; +static bool track_cb_called_y = false; + +static int track_cb_x(sd_bus_track *t, void *userdata) { + + log_error("TRACK CB X"); + + assert_se(!track_cb_called_x); + track_cb_called_x = true; + + /* This means b's name disappeared. Let's now disconnect, to make sure the track handling on disconnect works + * as it should. */ + + assert_se(shutdown(sd_bus_get_fd(sd_bus_track_get_bus(t)), SHUT_RDWR) >= 0); + return 1; +} + +static int track_cb_y(sd_bus_track *t, void *userdata) { + int r; + + log_error("TRACK CB Y"); + + assert_se(!track_cb_called_y); + track_cb_called_y = true; + + /* We got disconnected, let's close everything */ + + r = sd_event_exit(sd_bus_get_event(sd_bus_track_get_bus(t)), EXIT_SUCCESS); + assert_se(r >= 0); + + return 0; +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(sd_bus_track_unrefp) sd_bus_track *x = NULL, *y = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL; + bool use_system_bus = false; + const char *unique; + int r; + + test_setup_logging(LOG_INFO); + + r = sd_event_default(&event); + assert_se(r >= 0); + + r = sd_bus_open_user(&a); + if (IN_SET(r, -ECONNREFUSED, -ENOENT)) { + r = sd_bus_open_system(&a); + if (IN_SET(r, -ECONNREFUSED, -ENOENT)) + return log_tests_skipped("Failed to connect to bus"); + use_system_bus = true; + } + assert_se(r >= 0); + + r = sd_bus_attach_event(a, event, SD_EVENT_PRIORITY_NORMAL); + assert_se(r >= 0); + + if (use_system_bus) + r = sd_bus_open_system(&b); + else + r = sd_bus_open_user(&b); + assert_se(r >= 0); + + r = sd_bus_attach_event(b, event, SD_EVENT_PRIORITY_NORMAL); + assert_se(r >= 0); + + /* Watch b's name from a */ + r = sd_bus_track_new(a, &x, track_cb_x, NULL); + assert_se(r >= 0); + + r = sd_bus_get_unique_name(b, &unique); + assert_se(r >= 0); + + r = sd_bus_track_add_name(x, unique); + assert_se(r >= 0); + + /* Watch's a's own name from a */ + r = sd_bus_track_new(a, &y, track_cb_y, NULL); + assert_se(r >= 0); + + r = sd_bus_get_unique_name(a, &unique); + assert_se(r >= 0); + + r = sd_bus_track_add_name(y, unique); + assert_se(r >= 0); + + /* Now make b's name disappear */ + sd_bus_close(b); + + r = sd_event_loop(event); + assert_se(r >= 0); + + assert_se(track_cb_called_x); + assert_se(track_cb_called_y); + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-vtable-cc.cc b/src/libsystemd/sd-bus/test-bus-vtable-cc.cc new file mode 120000 index 00000000..abee3986 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-vtable-cc.cc @@ -0,0 +1 @@ +test-bus-vtable.c \ No newline at end of file diff --git a/src/libsystemd/sd-bus/test-bus-vtable.c b/src/libsystemd/sd-bus/test-bus-vtable.c new file mode 100644 index 00000000..b6350027 --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-vtable.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +/* We use system assert.h here, because we don't want to keep macro.h and log.h C++ compatible */ +#undef NDEBUG +#include +#include +#include + +#include "sd-bus-vtable.h" + +#ifndef __cplusplus +# include "bus-objects.h" +#endif + +#include "test-vtable-data.h" + +#define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket" + +static struct context c = {}; +static int happy_finder_object = 0; + +static int happy_finder(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + assert(userdata); + assert(userdata == &c); + +#ifndef __cplusplus + log_info("%s called", __func__); +#endif + + happy_finder_object++; + *found = &happy_finder_object; + return 1; /* found */ +} + +static void test_vtable(void) { + sd_bus *bus = NULL; + int r; + + assert(sd_bus_new(&bus) >= 0); + + assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable", test_vtable_2, &c) >= 0); + assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable2", test_vtable_2, &c) >= 0); + /* the cast on the line below is needed to test with the old version of the table */ + assert(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.testVtable221", + (const sd_bus_vtable *)vtable_format_221, &c) >= 0); + + assert(sd_bus_add_fallback_vtable(bus, NULL, "/fallback", "org.freedesktop.systemd.testVtable2", test_vtable_2, happy_finder, &c) >= 0); + + assert(sd_bus_set_address(bus, DEFAULT_BUS_PATH) >= 0); + r = sd_bus_start(bus); + assert(r == 0 || /* success */ + r == -ENOENT /* dbus is inactive */ ); + +#ifndef __cplusplus + _cleanup_free_ char *s, *s2; + + assert_se(introspect_path(bus, "/foo", NULL, false, true, NULL, &s, NULL) == 1); + fputs(s, stdout); + + assert_se(introspect_path(bus, "/fallback", NULL, false, true, NULL, &s2, NULL) == 1); + fputs(s2, stdout); + + assert_se(happy_finder_object == 1); +#endif + + sd_bus_unref(bus); +} + +int main(int argc, char **argv) { + test_vtable(); + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-bus-watch-bind.c b/src/libsystemd/sd-bus/test-bus-watch-bind.c new file mode 100644 index 00000000..2723866e --- /dev/null +++ b/src/libsystemd/sd-bus/test-bus-watch-bind.c @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-bus.h" +#include "sd-event.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "mkdir.h" +#include "path-util.h" +#include "random-util.h" +#include "rm-rf.h" +#include "socket-util.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "tests.h" + +static int method_foobar(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + log_info("Got Foobar() call."); + + assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0) >= 0); + return sd_bus_reply_method_return(m, NULL); +} + +static int method_exit(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + log_info("Got Exit() call"); + assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 1) >= 0); + return sd_bus_reply_method_return(m, NULL); +} + +static const sd_bus_vtable vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD("Foobar", NULL, NULL, method_foobar, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Exit", NULL, NULL, method_exit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END, +}; + +static void* thread_server(void *p) { + _cleanup_free_ char *suffixed = NULL, *suffixed2 = NULL, *d = NULL; + _cleanup_close_ int fd = -1; + union sockaddr_union u = {}; + const char *path = p; + int salen; + + log_debug("Initializing server"); + + /* Let's play some games, by slowly creating the socket directory, and renaming it in the middle */ + (void) usleep(100 * USEC_PER_MSEC); + + assert_se(mkdir_parents(path, 0755) >= 0); + (void) usleep(100 * USEC_PER_MSEC); + + d = dirname_malloc(path); + assert_se(d); + assert_se(asprintf(&suffixed, "%s.%" PRIx64, d, random_u64()) >= 0); + assert_se(rename(d, suffixed) >= 0); + (void) usleep(100 * USEC_PER_MSEC); + + assert_se(asprintf(&suffixed2, "%s.%" PRIx64, d, random_u64()) >= 0); + assert_se(symlink(suffixed2, d) >= 0); + (void) usleep(100 * USEC_PER_MSEC); + + assert_se(symlink(basename(suffixed), suffixed2) >= 0); + (void) usleep(100 * USEC_PER_MSEC); + + salen = sockaddr_un_set_path(&u.un, path); + assert_se(salen >= 0); + + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + assert_se(fd >= 0); + + assert_se(bind(fd, &u.sa, salen) >= 0); + usleep(100 * USEC_PER_MSEC); + + assert_se(listen(fd, SOMAXCONN) >= 0); + usleep(100 * USEC_PER_MSEC); + + assert_se(touch(path) >= 0); + usleep(100 * USEC_PER_MSEC); + + log_debug("Initialized server"); + + for (;;) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + sd_id128_t id; + int bus_fd, code; + + assert_se(sd_id128_randomize(&id) >= 0); + + assert_se(sd_event_new(&event) >= 0); + + bus_fd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); + assert_se(bus_fd >= 0); + + log_debug("Accepted server connection"); + + assert_se(sd_bus_new(&bus) >= 0); + assert_se(sd_bus_set_description(bus, "server") >= 0); + assert_se(sd_bus_set_fd(bus, bus_fd, bus_fd) >= 0); + assert_se(sd_bus_set_server(bus, true, id) >= 0); + /* assert_se(sd_bus_set_anonymous(bus, true) >= 0); */ + + assert_se(sd_bus_attach_event(bus, event, 0) >= 0); + + assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "foo.TestInterface", vtable, NULL) >= 0); + + assert_se(sd_bus_start(bus) >= 0); + + assert_se(sd_event_loop(event) >= 0); + + assert_se(sd_event_get_exit_code(event, &code) >= 0); + + if (code > 0) + break; + } + + log_debug("Server done"); + + return NULL; +} + +static void* thread_client1(void *p) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const char *path = p, *t; + int r; + + log_debug("Initializing client1"); + + assert_se(sd_bus_new(&bus) >= 0); + assert_se(sd_bus_set_description(bus, "client1") >= 0); + + t = strjoina("unix:path=", path); + assert_se(sd_bus_set_address(bus, t) >= 0); + assert_se(sd_bus_set_watch_bind(bus, true) >= 0); + assert_se(sd_bus_start(bus) >= 0); + + r = sd_bus_call_method(bus, "foo.bar", "/foo", "foo.TestInterface", "Foobar", &error, NULL, NULL); + assert_se(r >= 0); + + log_debug("Client1 done"); + + return NULL; +} + +static int client2_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + assert_se(sd_bus_message_is_method_error(m, NULL) == 0); + assert_se(sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0) >= 0); + return 0; +} + +static void* thread_client2(void *p) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + const char *path = p, *t; + + log_debug("Initializing client2"); + + assert_se(sd_event_new(&event) >= 0); + assert_se(sd_bus_new(&bus) >= 0); + assert_se(sd_bus_set_description(bus, "client2") >= 0); + + t = strjoina("unix:path=", path); + assert_se(sd_bus_set_address(bus, t) >= 0); + assert_se(sd_bus_set_watch_bind(bus, true) >= 0); + assert_se(sd_bus_attach_event(bus, event, 0) >= 0); + assert_se(sd_bus_start(bus) >= 0); + + assert_se(sd_bus_call_method_async(bus, NULL, "foo.bar", "/foo", "foo.TestInterface", "Foobar", client2_callback, NULL, NULL) >= 0); + + assert_se(sd_event_loop(event) >= 0); + + log_debug("Client2 done"); + + return NULL; +} + +static void request_exit(const char *path) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const char *t; + + assert_se(sd_bus_new(&bus) >= 0); + + t = strjoina("unix:path=", path); + assert_se(sd_bus_set_address(bus, t) >= 0); + assert_se(sd_bus_set_watch_bind(bus, true) >= 0); + assert_se(sd_bus_set_description(bus, "request-exit") >= 0); + assert_se(sd_bus_start(bus) >= 0); + + assert_se(sd_bus_call_method(bus, "foo.bar", "/foo", "foo.TestInterface", "Exit", NULL, NULL, NULL) >= 0); +} + +int main(int argc, char *argv[]) { + _cleanup_(rm_rf_physical_and_freep) char *d = NULL; + pthread_t server, client1, client2; + char *path; + + test_setup_logging(LOG_DEBUG); + + /* We use /dev/shm here rather than /tmp, since some weird distros might set up /tmp as some weird fs that + * doesn't support inotify properly. */ + assert_se(mkdtemp_malloc("/dev/shm/systemd-watch-bind-XXXXXX", &d) >= 0); + + path = strjoina(d, "/this/is/a/socket"); + + assert_se(pthread_create(&server, NULL, thread_server, path) == 0); + assert_se(pthread_create(&client1, NULL, thread_client1, path) == 0); + assert_se(pthread_create(&client2, NULL, thread_client2, path) == 0); + + assert_se(pthread_join(client1, NULL) == 0); + assert_se(pthread_join(client2, NULL) == 0); + + request_exit(path); + + assert_se(pthread_join(server, NULL) == 0); + + return 0; +} diff --git a/src/libsystemd/sd-bus/test-vtable-data.h b/src/libsystemd/sd-bus/test-vtable-data.h new file mode 100644 index 00000000..bc898938 --- /dev/null +++ b/src/libsystemd/sd-bus/test-vtable-data.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +/* This is meant to be included in other files, hence no headers */ + +struct context { + bool quit; + char *something; + char *automatic_string_property; + uint32_t automatic_integer_property; +}; + +static int handler(sd_bus_message *m, void *userdata, sd_bus_error *error) { + return 1; +} + +static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { + return 1; +} + +static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) { + return 1; +} + +static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) { + return 1; +} + +static const sd_bus_vtable test_vtable_1[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD("Hello", "ssas", "a(uu)", NULL, 0), + SD_BUS_METHOD("DeprecatedHello", "", "", NULL, SD_BUS_VTABLE_DEPRECATED), + SD_BUS_METHOD("DeprecatedHelloNoReply", "", "", NULL, SD_BUS_VTABLE_DEPRECATED|SD_BUS_VTABLE_METHOD_NO_REPLY), + SD_BUS_SIGNAL("Wowza", "sss", 0), + SD_BUS_SIGNAL("DeprecatedWowza", "ut", SD_BUS_VTABLE_DEPRECATED), + SD_BUS_WRITABLE_PROPERTY("AProperty", "s", get_handler, set_handler, 0, 0), + SD_BUS_PROPERTY("AReadOnlyDeprecatedProperty", "(ut)", get_handler, 0, SD_BUS_VTABLE_DEPRECATED), + SD_BUS_PROPERTY("ChangingProperty", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Invalidating", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_PROPERTY("Constant", "t", get_handler, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_PROPERTY_EXPLICIT), + SD_BUS_VTABLE_END +}; + +static const sd_bus_vtable test_vtable_2[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_METHOD("AlterSomething", "s", "s", handler, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Exit", "", "", handler, 0), + SD_BUS_METHOD_WITH_OFFSET("AlterSomething2", "s", "s", handler, 200, 0), + SD_BUS_METHOD_WITH_OFFSET("Exit2", "", "", handler, 200, 0), + SD_BUS_METHOD_WITH_NAMES_OFFSET("AlterSomething3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path), + "s", SD_BUS_PARAM(returnstring), handler, 200, 0), + SD_BUS_METHOD_WITH_NAMES("Exit3", "bx", SD_BUS_PARAM(with_confirmation) SD_BUS_PARAM(after_msec), + "bb", SD_BUS_PARAM(accepted) SD_BUS_PARAM(scheduled), handler, 0), + SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0), + SD_BUS_PROPERTY("AnExplicitProperty", "s", NULL, offsetof(struct context, something), + SD_BUS_VTABLE_PROPERTY_EXPLICIT|SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0), + SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, + offsetof(struct context, automatic_string_property), 0), + SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, + offsetof(struct context, automatic_integer_property), 0), + SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0), + SD_BUS_SIGNAL("DummySignal", "b", 0), + SD_BUS_SIGNAL("DummySignal2", "so", 0), + SD_BUS_SIGNAL_WITH_NAMES("DummySignal3", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path), 0), + SD_BUS_VTABLE_END +}; + +static const sd_bus_vtable test_vtable_deprecated[] = { + SD_BUS_VTABLE_START(SD_BUS_VTABLE_DEPRECATED), + SD_BUS_VTABLE_END +}; + +struct sd_bus_vtable_221 { + uint8_t type:8; + uint64_t flags:56; + union { + struct { + size_t element_size; + } start; + struct { + const char *member; + const char *signature; + const char *result; + sd_bus_message_handler_t handler; + size_t offset; + } method; + struct { + const char *member; + const char *signature; + } signal; + struct { + const char *member; + const char *signature; + sd_bus_property_get_t get; + sd_bus_property_set_t set; + size_t offset; + } property; + } x; +}; + +static const struct sd_bus_vtable_221 vtable_format_221[] = { + { + .type = _SD_BUS_VTABLE_START, + .flags = 0, + .x = { + .start = { + .element_size = sizeof(struct sd_bus_vtable_221) + }, + }, + }, + { + .type = _SD_BUS_VTABLE_METHOD, + .flags = 0, + .x = { + .method = { + .member = "Exit", + .signature = "", + .result = "", + .handler = handler, + .offset = 0, + }, + }, + }, + { + .type = _SD_BUS_VTABLE_END, + .flags = 0, + .x = { { 0 } }, + } +}; diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c new file mode 100644 index 00000000..ff711943 --- /dev/null +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -0,0 +1,658 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "io-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "socket-util.h" +#include "strv.h" +#include "util.h" + +#define SNDBUF_SIZE (8*1024*1024) + +static void unsetenv_all(bool unset_environment) { + + if (!unset_environment) + return; + + unsetenv("LISTEN_PID"); + unsetenv("LISTEN_FDS"); + unsetenv("LISTEN_FDNAMES"); +} + +_public_ int sd_listen_fds(int unset_environment) { + const char *e; + int n, r, fd; + pid_t pid; + + e = getenv("LISTEN_PID"); + if (!e) { + r = 0; + goto finish; + } + + r = parse_pid(e, &pid); + if (r < 0) + goto finish; + + /* Is this for us? */ + if (getpid_cached() != pid) { + r = 0; + goto finish; + } + + e = getenv("LISTEN_FDS"); + if (!e) { + r = 0; + goto finish; + } + + r = safe_atoi(e, &n); + if (r < 0) + goto finish; + + assert_cc(SD_LISTEN_FDS_START < INT_MAX); + if (n <= 0 || n > INT_MAX - SD_LISTEN_FDS_START) { + r = -EINVAL; + goto finish; + } + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { + r = fd_cloexec(fd, true); + if (r < 0) + goto finish; + } + + r = n; + +finish: + unsetenv_all(unset_environment); + return r; +} + +_public_ int sd_listen_fds_with_names(int unset_environment, char ***names) { + _cleanup_strv_free_ char **l = NULL; + bool have_names; + int n_names = 0, n_fds; + const char *e; + int r; + + if (!names) + return sd_listen_fds(unset_environment); + + e = getenv("LISTEN_FDNAMES"); + if (e) { + n_names = strv_split_extract(&l, e, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (n_names < 0) { + unsetenv_all(unset_environment); + return n_names; + } + + have_names = true; + } else + have_names = false; + + n_fds = sd_listen_fds(unset_environment); + if (n_fds <= 0) + return n_fds; + + if (have_names) { + if (n_names != n_fds) + return -EINVAL; + } else { + r = strv_extend_n(&l, "unknown", n_fds); + if (r < 0) + return r; + } + + *names = TAKE_PTR(l); + + return n_fds; +} + +_public_ int sd_is_fifo(int fd, const char *path) { + struct stat st_fd; + + assert_return(fd >= 0, -EBADF); + + if (fstat(fd, &st_fd) < 0) + return -errno; + + if (!S_ISFIFO(st_fd.st_mode)) + return 0; + + if (path) { + struct stat st_path; + + if (stat(path, &st_path) < 0) { + + if (IN_SET(errno, ENOENT, ENOTDIR)) + return 0; + + return -errno; + } + + return + st_path.st_dev == st_fd.st_dev && + st_path.st_ino == st_fd.st_ino; + } + + return 1; +} + +_public_ int sd_is_special(int fd, const char *path) { + struct stat st_fd; + + assert_return(fd >= 0, -EBADF); + + if (fstat(fd, &st_fd) < 0) + return -errno; + + if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode)) + return 0; + + if (path) { + struct stat st_path; + + if (stat(path, &st_path) < 0) { + + if (IN_SET(errno, ENOENT, ENOTDIR)) + return 0; + + return -errno; + } + + if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode)) + return + st_path.st_dev == st_fd.st_dev && + st_path.st_ino == st_fd.st_ino; + else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode)) + return st_path.st_rdev == st_fd.st_rdev; + else + return 0; + } + + return 1; +} + +static int sd_is_socket_internal(int fd, int type, int listening) { + struct stat st_fd; + + assert_return(fd >= 0, -EBADF); + assert_return(type >= 0, -EINVAL); + + if (fstat(fd, &st_fd) < 0) + return -errno; + + if (!S_ISSOCK(st_fd.st_mode)) + return 0; + + if (type != 0) { + int other_type = 0; + socklen_t l = sizeof(other_type); + + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0) + return -errno; + + if (l != sizeof(other_type)) + return -EINVAL; + + if (other_type != type) + return 0; + } + + if (listening >= 0) { + int accepting = 0; + socklen_t l = sizeof(accepting); + + if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0) + return -errno; + + if (l != sizeof(accepting)) + return -EINVAL; + + if (!accepting != !listening) + return 0; + } + + return 1; +} + +_public_ int sd_is_socket(int fd, int family, int type, int listening) { + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(family >= 0, -EINVAL); + + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) + return r; + + if (family > 0) { + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); + + if (getsockname(fd, &sockaddr.sa, &l) < 0) + return -errno; + + if (l < sizeof(sa_family_t)) + return -EINVAL; + + return sockaddr.sa.sa_family == family; + } + + return 1; +} + +_public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) { + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(IN_SET(family, 0, AF_INET, AF_INET6), -EINVAL); + + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) + return r; + + if (getsockname(fd, &sockaddr.sa, &l) < 0) + return -errno; + + if (l < sizeof(sa_family_t)) + return -EINVAL; + + if (!IN_SET(sockaddr.sa.sa_family, AF_INET, AF_INET6)) + return 0; + + if (family != 0) + if (sockaddr.sa.sa_family != family) + return 0; + + if (port > 0) { + unsigned sa_port; + + r = sockaddr_port(&sockaddr.sa, &sa_port); + if (r < 0) + return r; + + return port == sa_port; + } + + return 1; +} + +_public_ int sd_is_socket_sockaddr(int fd, int type, const struct sockaddr* addr, unsigned addr_len, int listening) { + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(addr, -EINVAL); + assert_return(addr_len >= sizeof(sa_family_t), -ENOBUFS); + assert_return(IN_SET(addr->sa_family, AF_INET, AF_INET6), -EPFNOSUPPORT); + + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) + return r; + + if (getsockname(fd, &sockaddr.sa, &l) < 0) + return -errno; + + if (l < sizeof(sa_family_t)) + return -EINVAL; + + if (sockaddr.sa.sa_family != addr->sa_family) + return 0; + + if (sockaddr.sa.sa_family == AF_INET) { + const struct sockaddr_in *in = (const struct sockaddr_in *) addr; + + if (l < sizeof(struct sockaddr_in) || addr_len < sizeof(struct sockaddr_in)) + return -EINVAL; + + if (in->sin_port != 0 && + sockaddr.in.sin_port != in->sin_port) + return false; + + return sockaddr.in.sin_addr.s_addr == in->sin_addr.s_addr; + + } else { + const struct sockaddr_in6 *in = (const struct sockaddr_in6 *) addr; + + if (l < sizeof(struct sockaddr_in6) || addr_len < sizeof(struct sockaddr_in6)) + return -EINVAL; + + if (in->sin6_port != 0 && + sockaddr.in6.sin6_port != in->sin6_port) + return false; + + if (in->sin6_flowinfo != 0 && + sockaddr.in6.sin6_flowinfo != in->sin6_flowinfo) + return false; + + if (in->sin6_scope_id != 0 && + sockaddr.in6.sin6_scope_id != in->sin6_scope_id) + return false; + + return memcmp(sockaddr.in6.sin6_addr.s6_addr, in->sin6_addr.s6_addr, + sizeof(in->sin6_addr.s6_addr)) == 0; + } +} + +_public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) { + union sockaddr_union sockaddr = {}; + socklen_t l = sizeof(sockaddr); + int r; + + assert_return(fd >= 0, -EBADF); + + r = sd_is_socket_internal(fd, type, listening); + if (r <= 0) + return r; + + if (getsockname(fd, &sockaddr.sa, &l) < 0) + return -errno; + + if (l < sizeof(sa_family_t)) + return -EINVAL; + + if (sockaddr.sa.sa_family != AF_UNIX) + return 0; + + if (path) { + if (length == 0) + length = strlen(path); + + if (length == 0) + /* Unnamed socket */ + return l == offsetof(struct sockaddr_un, sun_path); + + if (path[0]) + /* Normal path socket */ + return + (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) && + memcmp(path, sockaddr.un.sun_path, length+1) == 0; + else + /* Abstract namespace socket */ + return + (l == offsetof(struct sockaddr_un, sun_path) + length) && + memcmp(path, sockaddr.un.sun_path, length) == 0; + } + + return 1; +} + +_public_ int sd_is_mq(int fd, const char *path) { + struct mq_attr attr; + + /* Check that the fd is valid */ + assert_return(fcntl(fd, F_GETFD) >= 0, -errno); + + if (mq_getattr(fd, &attr) < 0) { + if (errno == EBADF) + /* A non-mq fd (or an invalid one, but we ruled that out above) */ + return 0; + return -errno; + } + + if (path) { + char fpath[PATH_MAX]; + struct stat a, b; + + assert_return(path_is_absolute(path), -EINVAL); + + if (fstat(fd, &a) < 0) + return -errno; + + strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12); + fpath[sizeof(fpath)-1] = 0; + + if (stat(fpath, &b) < 0) + return -errno; + + if (a.st_dev != b.st_dev || + a.st_ino != b.st_ino) + return 0; + } + + return 1; +} + +_public_ int sd_pid_notify_with_fds( + pid_t pid, + int unset_environment, + const char *state, + const int *fds, + unsigned n_fds) { + + union sockaddr_union sockaddr = {}; + struct iovec iovec; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_name = &sockaddr, + }; + _cleanup_close_ int fd = -1; + struct cmsghdr *cmsg = NULL; + const char *e; + bool send_ucred; + int r, salen; + + if (!state) { + r = -EINVAL; + goto finish; + } + + if (n_fds > 0 && !fds) { + r = -EINVAL; + goto finish; + } + + e = getenv("NOTIFY_SOCKET"); + if (!e) + return 0; + + salen = sockaddr_un_set_path(&sockaddr.un, e); + if (salen < 0) { + r = salen; + goto finish; + } + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) { + r = -errno; + goto finish; + } + + (void) fd_inc_sndbuf(fd, SNDBUF_SIZE); + + iovec = IOVEC_MAKE_STRING(state); + msghdr.msg_namelen = salen; + + send_ucred = + (pid != 0 && pid != getpid_cached()) || + getuid() != geteuid() || + getgid() != getegid(); + + if (n_fds > 0 || send_ucred) { + /* CMSG_SPACE(0) may return value different than zero, which results in miscalculated controllen. */ + msghdr.msg_controllen = + (n_fds > 0 ? CMSG_SPACE(sizeof(int) * n_fds) : 0) + + (send_ucred ? CMSG_SPACE(sizeof(struct ucred)) : 0); + + msghdr.msg_control = alloca0(msghdr.msg_controllen); + + cmsg = CMSG_FIRSTHDR(&msghdr); + if (n_fds > 0) { + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int) * n_fds); + + memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * n_fds); + + if (send_ucred) + assert_se(cmsg = CMSG_NXTHDR(&msghdr, cmsg)); + } + + if (send_ucred) { + struct ucred *ucred; + + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); + + ucred = (struct ucred*) CMSG_DATA(cmsg); + ucred->pid = pid != 0 ? pid : getpid_cached(); + ucred->uid = getuid(); + ucred->gid = getgid(); + } + } + + /* First try with fake ucred data, as requested */ + if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) { + r = 1; + goto finish; + } + + /* If that failed, try with our own ucred instead */ + if (send_ucred) { + msghdr.msg_controllen -= CMSG_SPACE(sizeof(struct ucred)); + if (msghdr.msg_controllen == 0) + msghdr.msg_control = NULL; + + if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) { + r = 1; + goto finish; + } + } + + r = -errno; + +finish: + if (unset_environment) + unsetenv("NOTIFY_SOCKET"); + + return r; +} + +_public_ int sd_pid_notify(pid_t pid, int unset_environment, const char *state) { + return sd_pid_notify_with_fds(pid, unset_environment, state, NULL, 0); +} + +_public_ int sd_notify(int unset_environment, const char *state) { + return sd_pid_notify_with_fds(0, unset_environment, state, NULL, 0); +} + +_public_ int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...) { + _cleanup_free_ char *p = NULL; + int r; + + if (format) { + va_list ap; + + va_start(ap, format); + r = vasprintf(&p, format, ap); + va_end(ap); + + if (r < 0 || !p) + return -ENOMEM; + } + + return sd_pid_notify(pid, unset_environment, p); +} + +_public_ int sd_notifyf(int unset_environment, const char *format, ...) { + _cleanup_free_ char *p = NULL; + int r; + + if (format) { + va_list ap; + + va_start(ap, format); + r = vasprintf(&p, format, ap); + va_end(ap); + + if (r < 0 || !p) + return -ENOMEM; + } + + return sd_pid_notify(0, unset_environment, p); +} + +_public_ int sd_booted(void) { + /* We test whether the runtime unit file directory has been + * created. This takes place in mount-setup.c, so is + * guaranteed to happen very early during boot. */ + + if (laccess("/run/systemd/system/", F_OK) >= 0) + return true; + + if (errno == ENOENT) + return false; + + return -errno; +} + +_public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) { + const char *s, *p = ""; /* p is set to dummy value to do unsetting */ + uint64_t u; + int r = 0; + + s = getenv("WATCHDOG_USEC"); + if (!s) + goto finish; + + r = safe_atou64(s, &u); + if (r < 0) + goto finish; + if (u <= 0 || u >= USEC_INFINITY) { + r = -EINVAL; + goto finish; + } + + p = getenv("WATCHDOG_PID"); + if (p) { + pid_t pid; + + r = parse_pid(p, &pid); + if (r < 0) + goto finish; + + /* Is this for us? */ + if (getpid_cached() != pid) { + r = 0; + goto finish; + } + } + + if (usec) + *usec = u; + + r = 1; + +finish: + if (unset_environment && s) + unsetenv("WATCHDOG_USEC"); + if (unset_environment && p) + unsetenv("WATCHDOG_PID"); + + return r; +} diff --git a/src/libsystemd/sd-device/device-enumerator-private.h b/src/libsystemd/sd-device/device-enumerator-private.h new file mode 100644 index 00000000..cf2b2614 --- /dev/null +++ b/src/libsystemd/sd-device/device-enumerator-private.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-device.h" + +int device_enumerator_scan_devices(sd_device_enumerator *enumeartor); +int device_enumerator_scan_subsystems(sd_device_enumerator *enumeartor); +int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device); +int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator); +int device_enumerator_add_match_parent_incremental(sd_device_enumerator *enumerator, sd_device *parent); +sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator); +sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator); +sd_device **device_enumerator_get_devices(sd_device_enumerator *enumerator, size_t *ret_n_devices); + +#define FOREACH_DEVICE_AND_SUBSYSTEM(enumerator, device) \ + for (device = device_enumerator_get_first(enumerator); \ + device; \ + device = device_enumerator_get_next(enumerator)) diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c new file mode 100644 index 00000000..a1932f41 --- /dev/null +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -0,0 +1,1035 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-device.h" + +#include "alloc-util.h" +#include "device-enumerator-private.h" +#include "device-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "set.h" +#include "sort-util.h" +#include "string-util.h" +#include "strv.h" + +#define DEVICE_ENUMERATE_MAX_DEPTH 256 + +typedef enum DeviceEnumerationType { + DEVICE_ENUMERATION_TYPE_DEVICES, + DEVICE_ENUMERATION_TYPE_SUBSYSTEMS, + _DEVICE_ENUMERATION_TYPE_MAX, + _DEVICE_ENUMERATION_TYPE_INVALID = -1, +} DeviceEnumerationType; + +struct sd_device_enumerator { + unsigned n_ref; + + DeviceEnumerationType type; + sd_device **devices; + size_t n_devices, n_allocated, current_device_index; + bool scan_uptodate; + + Set *match_subsystem; + Set *nomatch_subsystem; + Hashmap *match_sysattr; + Hashmap *nomatch_sysattr; + Hashmap *match_property; + Set *match_sysname; + Set *match_tag; + Set *match_parent; + bool match_allow_uninitialized; +}; + +_public_ int sd_device_enumerator_new(sd_device_enumerator **ret) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *enumerator = NULL; + + assert(ret); + + enumerator = new(sd_device_enumerator, 1); + if (!enumerator) + return -ENOMEM; + + *enumerator = (sd_device_enumerator) { + .n_ref = 1, + .type = _DEVICE_ENUMERATION_TYPE_INVALID, + }; + + *ret = TAKE_PTR(enumerator); + + return 0; +} + +static sd_device_enumerator *device_enumerator_free(sd_device_enumerator *enumerator) { + size_t i; + + assert(enumerator); + + for (i = 0; i < enumerator->n_devices; i++) + sd_device_unref(enumerator->devices[i]); + + free(enumerator->devices); + set_free_free(enumerator->match_subsystem); + set_free_free(enumerator->nomatch_subsystem); + hashmap_free_free_free(enumerator->match_sysattr); + hashmap_free_free_free(enumerator->nomatch_sysattr); + hashmap_free_free_free(enumerator->match_property); + set_free_free(enumerator->match_sysname); + set_free_free(enumerator->match_tag); + set_free_free(enumerator->match_parent); + + return mfree(enumerator); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_enumerator, sd_device_enumerator, device_enumerator_free); + +_public_ int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match) { + Set **set; + int r; + + assert_return(enumerator, -EINVAL); + assert_return(subsystem, -EINVAL); + + if (match) + set = &enumerator->match_subsystem; + else + set = &enumerator->nomatch_subsystem; + + r = set_ensure_allocated(set, NULL); + if (r < 0) + return r; + + r = set_put_strdup(*set, subsystem); + if (r < 0) + return r; + + enumerator->scan_uptodate = false; + + return 0; +} + +_public_ int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumerator, const char *_sysattr, const char *_value, int match) { + _cleanup_free_ char *sysattr = NULL, *value = NULL; + Hashmap **hashmap; + int r; + + assert_return(enumerator, -EINVAL); + assert_return(_sysattr, -EINVAL); + + if (match) + hashmap = &enumerator->match_sysattr; + else + hashmap = &enumerator->nomatch_sysattr; + + r = hashmap_ensure_allocated(hashmap, NULL); + if (r < 0) + return r; + + sysattr = strdup(_sysattr); + if (!sysattr) + return -ENOMEM; + + if (_value) { + value = strdup(_value); + if (!value) + return -ENOMEM; + } + + r = hashmap_put(*hashmap, sysattr, value); + if (r < 0) + return r; + + sysattr = NULL; + value = NULL; + + enumerator->scan_uptodate = false; + + return 0; +} + +_public_ int sd_device_enumerator_add_match_property(sd_device_enumerator *enumerator, const char *_property, const char *_value) { + _cleanup_free_ char *property = NULL, *value = NULL; + int r; + + assert_return(enumerator, -EINVAL); + assert_return(_property, -EINVAL); + + r = hashmap_ensure_allocated(&enumerator->match_property, NULL); + if (r < 0) + return r; + + property = strdup(_property); + if (!property) + return -ENOMEM; + + if (_value) { + value = strdup(_value); + if (!value) + return -ENOMEM; + } + + r = hashmap_put(enumerator->match_property, property, value); + if (r < 0) + return r; + + property = NULL; + value = NULL; + + enumerator->scan_uptodate = false; + + return 0; +} + +_public_ int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname) { + int r; + + assert_return(enumerator, -EINVAL); + assert_return(sysname, -EINVAL); + + r = set_ensure_allocated(&enumerator->match_sysname, NULL); + if (r < 0) + return r; + + r = set_put_strdup(enumerator->match_sysname, sysname); + if (r < 0) + return r; + + enumerator->scan_uptodate = false; + + return 0; +} + +_public_ int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag) { + int r; + + assert_return(enumerator, -EINVAL); + assert_return(tag, -EINVAL); + + r = set_ensure_allocated(&enumerator->match_tag, NULL); + if (r < 0) + return r; + + r = set_put_strdup(enumerator->match_tag, tag); + if (r < 0) + return r; + + enumerator->scan_uptodate = false; + + return 0; +} + +static void device_enumerator_clear_match_parent(sd_device_enumerator *enumerator) { + if (!enumerator) + return; + + set_clear_free(enumerator->match_parent); +} + +int device_enumerator_add_match_parent_incremental(sd_device_enumerator *enumerator, sd_device *parent) { + const char *path; + int r; + + assert_return(enumerator, -EINVAL); + assert_return(parent, -EINVAL); + + r = sd_device_get_syspath(parent, &path); + if (r < 0) + return r; + + r = set_ensure_allocated(&enumerator->match_parent, NULL); + if (r < 0) + return r; + + r = set_put_strdup(enumerator->match_parent, path); + if (r < 0) + return r; + + enumerator->scan_uptodate = false; + + return 0; +} + +_public_ int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent) { + device_enumerator_clear_match_parent(enumerator); + return device_enumerator_add_match_parent_incremental(enumerator, parent); +} + +_public_ int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator) { + assert_return(enumerator, -EINVAL); + + enumerator->match_allow_uninitialized = true; + + enumerator->scan_uptodate = false; + + return 0; +} + +int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator) { + assert_return(enumerator, -EINVAL); + + enumerator->match_allow_uninitialized = false; + + enumerator->scan_uptodate = false; + + return 0; +} + +static int device_compare(sd_device * const *_a, sd_device * const *_b) { + sd_device *a = *(sd_device **)_a, *b = *(sd_device **)_b; + const char *devpath_a, *devpath_b, *sound_a; + bool delay_a, delay_b; + int r; + + assert_se(sd_device_get_devpath(a, &devpath_a) >= 0); + assert_se(sd_device_get_devpath(b, &devpath_b) >= 0); + + sound_a = strstr(devpath_a, "/sound/card"); + if (sound_a) { + /* For sound cards the control device must be enumerated last to + * make sure it's the final device node that gets ACLs applied. + * Applications rely on this fact and use ACL changes on the + * control node as an indicator that the ACL change of the + * entire sound card completed. The kernel makes this guarantee + * when creating those devices, and hence we should too when + * enumerating them. */ + sound_a += STRLEN("/sound/card"); + sound_a = strchr(sound_a, '/'); + + if (sound_a) { + unsigned prefix_len; + + prefix_len = sound_a - devpath_a; + + if (strncmp(devpath_a, devpath_b, prefix_len) == 0) { + const char *sound_b; + + sound_b = devpath_b + prefix_len; + + if (startswith(sound_a, "/controlC") && + !startswith(sound_b, "/contolC")) + return 1; + + if (!startswith(sound_a, "/controlC") && + startswith(sound_b, "/controlC")) + return -1; + } + } + } + + /* md and dm devices are enumerated after all other devices */ + delay_a = strstr(devpath_a, "/block/md") || strstr(devpath_a, "/block/dm-"); + delay_b = strstr(devpath_b, "/block/md") || strstr(devpath_b, "/block/dm-"); + r = CMP(delay_a, delay_b); + if (r != 0) + return r; + + return strcmp(devpath_a, devpath_b); +} + +int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) { + assert_return(enumerator, -EINVAL); + assert_return(device, -EINVAL); + + if (!GREEDY_REALLOC(enumerator->devices, enumerator->n_allocated, enumerator->n_devices + 1)) + return -ENOMEM; + + enumerator->devices[enumerator->n_devices++] = sd_device_ref(device); + + return 0; +} + +static bool match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) { + const char *value; + int r; + + assert(device); + assert(sysattr); + + r = sd_device_get_sysattr_value(device, sysattr, &value); + if (r < 0) + return false; + + if (!match_value) + return true; + + if (fnmatch(match_value, value, 0) == 0) + return true; + + return false; +} + +static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) { + const char *sysattr; + const char *value; + Iterator i; + + assert(enumerator); + assert(device); + + HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr, i) + if (match_sysattr_value(device, sysattr, value)) + return false; + + HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr, i) + if (!match_sysattr_value(device, sysattr, value)) + return false; + + return true; +} + +static bool match_property(sd_device_enumerator *enumerator, sd_device *device) { + const char *property; + const char *value; + Iterator i; + + assert(enumerator); + assert(device); + + if (hashmap_isempty(enumerator->match_property)) + return true; + + HASHMAP_FOREACH_KEY(value, property, enumerator->match_property, i) { + const char *property_dev, *value_dev; + + FOREACH_DEVICE_PROPERTY(device, property_dev, value_dev) { + if (fnmatch(property, property_dev, 0) != 0) + continue; + + if (!value && !value_dev) + return true; + + if (!value || !value_dev) + continue; + + if (fnmatch(value, value_dev, 0) == 0) + return true; + } + } + + return false; +} + +static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) { + const char *tag; + Iterator i; + + assert(enumerator); + assert(device); + + SET_FOREACH(tag, enumerator->match_tag, i) + if (!sd_device_has_tag(device, tag)) + return false; + + return true; +} + +static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) { + const char *syspath_parent, *syspath; + Iterator i; + + assert(enumerator); + assert(device); + + if (set_isempty(enumerator->match_parent)) + return true; + + assert_se(sd_device_get_syspath(device, &syspath) >= 0); + + SET_FOREACH(syspath_parent, enumerator->match_parent, i) + if (path_startswith(syspath, syspath_parent)) + return true; + + return false; +} + +static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) { + const char *sysname_match; + Iterator i; + + assert(enumerator); + assert(sysname); + + if (set_isempty(enumerator->match_sysname)) + return true; + + SET_FOREACH(sysname_match, enumerator->match_sysname, i) + if (fnmatch(sysname_match, sysname, 0) == 0) + return true; + + return false; +} + +static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, const char *basedir, const char *subdir1, const char *subdir2) { + _cleanup_closedir_ DIR *dir = NULL; + char *path; + struct dirent *dent; + int r = 0; + + assert(enumerator); + assert(basedir); + + path = strjoina("/sys/", basedir, "/"); + + if (subdir1) + path = strjoina(path, subdir1, "/"); + + if (subdir2) + path = strjoina(path, subdir2, "/"); + + dir = opendir(path); + if (!dir) + return -errno; + + FOREACH_DIRENT_ALL(dent, dir, return -errno) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + char syspath[strlen(path) + 1 + strlen(dent->d_name) + 1]; + int initialized, k; + + if (dent->d_name[0] == '.') + continue; + + if (!match_sysname(enumerator, dent->d_name)) + continue; + + (void) sprintf(syspath, "%s%s", path, dent->d_name); + + k = sd_device_new_from_syspath(&device, syspath); + if (k < 0) { + if (k != -ENODEV) + /* this is necessarily racey, so ignore missing devices */ + r = k; + + continue; + } + + initialized = sd_device_get_is_initialized(device); + if (initialized < 0) { + if (initialized != -ENOENT) + /* this is necessarily racey, so ignore missing devices */ + r = initialized; + + continue; + } + + /* + * All devices with a device node or network interfaces + * possibly need udev to adjust the device node permission + * or context, or rename the interface before it can be + * reliably used from other processes. + * + * For now, we can only check these types of devices, we + * might not store a database, and have no way to find out + * for all other types of devices. + */ + if (!enumerator->match_allow_uninitialized && + !initialized && + (sd_device_get_devnum(device, NULL) >= 0 || + sd_device_get_ifindex(device, NULL) >= 0)) + continue; + + if (!match_parent(enumerator, device)) + continue; + + if (!match_tag(enumerator, device)) + continue; + + if (!match_property(enumerator, device)) + continue; + + if (!match_sysattr(enumerator, device)) + continue; + + k = device_enumerator_add_device(enumerator, device); + if (k < 0) + r = k; + } + + return r; +} + +static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) { + const char *subsystem_match; + Iterator i; + + assert(enumerator); + + if (!subsystem) + return false; + + SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem, i) + if (fnmatch(subsystem_match, subsystem, 0) == 0) + return false; + + if (set_isempty(enumerator->match_subsystem)) + return true; + + SET_FOREACH(subsystem_match, enumerator->match_subsystem, i) + if (fnmatch(subsystem_match, subsystem, 0) == 0) + return true; + + return false; +} + +static int enumerator_scan_dir(sd_device_enumerator *enumerator, const char *basedir, const char *subdir, const char *subsystem) { + _cleanup_closedir_ DIR *dir = NULL; + char *path; + struct dirent *dent; + int r = 0; + + path = strjoina("/sys/", basedir); + + dir = opendir(path); + if (!dir) + return -errno; + + log_debug("sd-device-enumerator: Scanning %s", path); + + FOREACH_DIRENT_ALL(dent, dir, return -errno) { + int k; + + if (dent->d_name[0] == '.') + continue; + + if (!match_subsystem(enumerator, subsystem ? : dent->d_name)) + continue; + + k = enumerator_scan_dir_and_add_devices(enumerator, basedir, dent->d_name, subdir); + if (k < 0) + r = k; + } + + return r; +} + +static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const char *tag) { + _cleanup_closedir_ DIR *dir = NULL; + char *path; + struct dirent *dent; + int r = 0; + + assert(enumerator); + assert(tag); + + path = strjoina("/run/udev/tags/", tag); + + dir = opendir(path); + if (!dir) { + if (errno != ENOENT) + return log_debug_errno(errno, "sd-device-enumerator: Failed to open tags directory %s: %m", path); + return 0; + } + + /* TODO: filter away subsystems? */ + + FOREACH_DIRENT_ALL(dent, dir, return -errno) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + const char *subsystem, *sysname; + int k; + + if (dent->d_name[0] == '.') + continue; + + k = sd_device_new_from_device_id(&device, dent->d_name); + if (k < 0) { + if (k != -ENODEV) + /* this is necessarily racy, so ignore missing devices */ + r = k; + + continue; + } + + k = sd_device_get_subsystem(device, &subsystem); + if (k < 0) { + if (k != -ENOENT) + /* this is necessarily racy, so ignore missing devices */ + r = k; + continue; + } + + if (!match_subsystem(enumerator, subsystem)) + continue; + + k = sd_device_get_sysname(device, &sysname); + if (k < 0) { + r = k; + continue; + } + + if (!match_sysname(enumerator, sysname)) + continue; + + if (!match_parent(enumerator, device)) + continue; + + if (!match_property(enumerator, device)) + continue; + + if (!match_sysattr(enumerator, device)) + continue; + + k = device_enumerator_add_device(enumerator, device); + if (k < 0) { + r = k; + continue; + } + } + + return r; +} + +static int enumerator_scan_devices_tags(sd_device_enumerator *enumerator) { + const char *tag; + Iterator i; + int r = 0; + + assert(enumerator); + + SET_FOREACH(tag, enumerator->match_tag, i) { + int k; + + k = enumerator_scan_devices_tag(enumerator, tag); + if (k < 0) + r = k; + } + + return r; +} + +static int parent_add_child(sd_device_enumerator *enumerator, const char *path) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + const char *subsystem, *sysname; + int r; + + r = sd_device_new_from_syspath(&device, path); + if (r == -ENODEV) + /* this is necessarily racy, so ignore missing devices */ + return 0; + else if (r < 0) + return r; + + r = sd_device_get_subsystem(device, &subsystem); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + if (!match_subsystem(enumerator, subsystem)) + return 0; + + r = sd_device_get_sysname(device, &sysname); + if (r < 0) + return r; + + if (!match_sysname(enumerator, sysname)) + return 0; + + if (!match_property(enumerator, device)) + return 0; + + if (!match_sysattr(enumerator, device)) + return 0; + + r = device_enumerator_add_device(enumerator, device); + if (r < 0) + return r; + + return 1; +} + +static int parent_crawl_children(sd_device_enumerator *enumerator, const char *path, unsigned maxdepth) { + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *dent; + int r = 0; + + dir = opendir(path); + if (!dir) + return log_debug_errno(errno, "sd-device-enumerator: Failed to open parent directory %s: %m", path); + + FOREACH_DIRENT_ALL(dent, dir, return -errno) { + _cleanup_free_ char *child = NULL; + int k; + + if (dent->d_name[0] == '.') + continue; + + if (dent->d_type != DT_DIR) + continue; + + child = path_join(path, dent->d_name); + if (!child) + return -ENOMEM; + + k = parent_add_child(enumerator, child); + if (k < 0) + r = k; + + if (maxdepth > 0) + parent_crawl_children(enumerator, child, maxdepth - 1); + else + log_debug("sd-device-enumerator: Max depth reached, %s: ignoring devices", child); + } + + return r; +} + +static int enumerator_scan_devices_children(sd_device_enumerator *enumerator) { + const char *path; + int r = 0, k; + Iterator i; + + SET_FOREACH(path, enumerator->match_parent, i) { + k = parent_add_child(enumerator, path); + if (k < 0) + r = k; + + k = parent_crawl_children(enumerator, path, DEVICE_ENUMERATE_MAX_DEPTH); + if (k < 0) + r = k; + } + + return r; +} + +static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) { + int r = 0; + + log_debug("sd-device-enumerator: Scan all dirs"); + + if (access("/sys/subsystem", F_OK) >= 0) { + /* we have /subsystem/, forget all the old stuff */ + r = enumerator_scan_dir(enumerator, "subsystem", "devices", NULL); + if (r < 0) + return log_debug_errno(r, "sd-device-enumerator: Failed to scan /sys/subsystem: %m"); + } else { + int k; + + k = enumerator_scan_dir(enumerator, "bus", "devices", NULL); + if (k < 0) { + log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/bus: %m"); + r = k; + } + + k = enumerator_scan_dir(enumerator, "class", NULL, NULL); + if (k < 0) { + log_debug_errno(k, "sd-device-enumerator: Failed to scan /sys/class: %m"); + r = k; + } + } + + return r; +} + +static void device_enumerator_dedup_devices(sd_device_enumerator *enumerator) { + sd_device **a, **b, **end; + + assert(enumerator); + + if (enumerator->n_devices <= 1) + return; + + a = enumerator->devices + 1; + b = enumerator->devices; + end = enumerator->devices + enumerator->n_devices; + + for (; a < end; a++) { + const char *devpath_a, *devpath_b; + + assert_se(sd_device_get_devpath(*a, &devpath_a) >= 0); + assert_se(sd_device_get_devpath(*b, &devpath_b) >= 0); + + if (path_equal(devpath_a, devpath_b)) + sd_device_unref(*a); + else + *(++b) = *a; + } + + enumerator->n_devices = b - enumerator->devices + 1; +} + +int device_enumerator_scan_devices(sd_device_enumerator *enumerator) { + int r = 0, k; + size_t i; + + assert(enumerator); + + if (enumerator->scan_uptodate && + enumerator->type == DEVICE_ENUMERATION_TYPE_DEVICES) + return 0; + + for (i = 0; i < enumerator->n_devices; i++) + sd_device_unref(enumerator->devices[i]); + + enumerator->n_devices = 0; + + if (!set_isempty(enumerator->match_tag)) { + k = enumerator_scan_devices_tags(enumerator); + if (k < 0) + r = k; + } else if (enumerator->match_parent) { + k = enumerator_scan_devices_children(enumerator); + if (k < 0) + r = k; + } else { + k = enumerator_scan_devices_all(enumerator); + if (k < 0) + r = k; + } + + typesafe_qsort(enumerator->devices, enumerator->n_devices, device_compare); + device_enumerator_dedup_devices(enumerator); + + enumerator->scan_uptodate = true; + enumerator->type = DEVICE_ENUMERATION_TYPE_DEVICES; + + return r; +} + +_public_ sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator) { + int r; + + assert_return(enumerator, NULL); + + r = device_enumerator_scan_devices(enumerator); + if (r < 0) + return NULL; + + enumerator->current_device_index = 0; + + if (enumerator->n_devices == 0) + return NULL; + + return enumerator->devices[0]; +} + +_public_ sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *enumerator) { + assert_return(enumerator, NULL); + + if (!enumerator->scan_uptodate || + enumerator->type != DEVICE_ENUMERATION_TYPE_DEVICES || + enumerator->current_device_index + 1 >= enumerator->n_devices) + return NULL; + + return enumerator->devices[++enumerator->current_device_index]; +} + +int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) { + const char *subsysdir; + int r = 0, k; + size_t i; + + assert(enumerator); + + if (enumerator->scan_uptodate && + enumerator->type == DEVICE_ENUMERATION_TYPE_SUBSYSTEMS) + return 0; + + for (i = 0; i < enumerator->n_devices; i++) + sd_device_unref(enumerator->devices[i]); + + enumerator->n_devices = 0; + + /* modules */ + if (match_subsystem(enumerator, "module")) { + k = enumerator_scan_dir_and_add_devices(enumerator, "module", NULL, NULL); + if (k < 0) { + log_debug_errno(k, "sd-device-enumerator: Failed to scan modules: %m"); + r = k; + } + } + + if (access("/sys/subsystem", F_OK) >= 0) + subsysdir = "subsystem"; + else + subsysdir = "bus"; + + /* subsystems (only buses support coldplug) */ + if (match_subsystem(enumerator, "subsystem")) { + k = enumerator_scan_dir_and_add_devices(enumerator, subsysdir, NULL, NULL); + if (k < 0) { + log_debug_errno(k, "sd-device-enumerator: Failed to scan subsystems: %m"); + r = k; + } + } + + /* subsystem drivers */ + if (match_subsystem(enumerator, "drivers")) { + k = enumerator_scan_dir(enumerator, subsysdir, "drivers", "drivers"); + if (k < 0) { + log_debug_errno(k, "sd-device-enumerator: Failed to scan drivers: %m"); + r = k; + } + } + + typesafe_qsort(enumerator->devices, enumerator->n_devices, device_compare); + device_enumerator_dedup_devices(enumerator); + + enumerator->scan_uptodate = true; + enumerator->type = DEVICE_ENUMERATION_TYPE_SUBSYSTEMS; + + return r; +} + +_public_ sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerator *enumerator) { + int r; + + assert_return(enumerator, NULL); + + r = device_enumerator_scan_subsystems(enumerator); + if (r < 0) + return NULL; + + enumerator->current_device_index = 0; + + if (enumerator->n_devices == 0) + return NULL; + + return enumerator->devices[0]; +} + +_public_ sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumerator) { + assert_return(enumerator, NULL); + + if (!enumerator->scan_uptodate || + enumerator->type != DEVICE_ENUMERATION_TYPE_SUBSYSTEMS || + enumerator->current_device_index + 1 >= enumerator->n_devices) + return NULL; + + return enumerator->devices[++enumerator->current_device_index]; +} + +sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator) { + assert_return(enumerator, NULL); + + if (!enumerator->scan_uptodate) + return NULL; + + enumerator->current_device_index = 0; + + if (enumerator->n_devices == 0) + return NULL; + + return enumerator->devices[0]; +} + +sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator) { + assert_return(enumerator, NULL); + + if (!enumerator->scan_uptodate || + enumerator->current_device_index + 1 >= enumerator->n_devices) + return NULL; + + return enumerator->devices[++enumerator->current_device_index]; +} + +sd_device **device_enumerator_get_devices(sd_device_enumerator *enumerator, size_t *ret_n_devices) { + assert(enumerator); + assert(ret_n_devices); + + if (!enumerator->scan_uptodate) + return NULL; + + *ret_n_devices = enumerator->n_devices; + return enumerator->devices; +} diff --git a/src/libsystemd/sd-device/device-internal.h b/src/libsystemd/sd-device/device-internal.h new file mode 100644 index 00000000..023fe0fc --- /dev/null +++ b/src/libsystemd/sd-device/device-internal.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-device.h" + +#include "device-private.h" +#include "hashmap.h" +#include "set.h" +#include "time-util.h" + +struct sd_device { + unsigned n_ref; + + int watch_handle; + + sd_device *parent; + + OrderedHashmap *properties; + Iterator properties_iterator; + uint64_t properties_generation; /* changes whenever the properties are changed */ + uint64_t properties_iterator_generation; /* generation when iteration was started */ + + /* the subset of the properties that should be written to the db */ + OrderedHashmap *properties_db; + + Hashmap *sysattr_values; /* cached sysattr values */ + + Set *sysattrs; /* names of sysattrs */ + Iterator sysattrs_iterator; + + Set *tags; + Iterator tags_iterator; + uint64_t tags_generation; /* changes whenever the tags are changed */ + uint64_t tags_iterator_generation; /* generation when iteration was started */ + + Set *devlinks; + Iterator devlinks_iterator; + uint64_t devlinks_generation; /* changes whenever the devlinks are changed */ + uint64_t devlinks_iterator_generation; /* generation when iteration was started */ + int devlink_priority; + + int ifindex; + char *devtype; + char *devname; + dev_t devnum; + + char **properties_strv; /* the properties hashmap as a strv */ + uint8_t *properties_nulstr; /* the same as a nulstr */ + size_t properties_nulstr_len; + + char *syspath; + const char *devpath; + const char *sysnum; + char *sysname; + + char *subsystem; + char *driver_subsystem; /* only set for the 'drivers' subsystem */ + char *driver; + + char *id_filename; + + uint64_t usec_initialized; + + mode_t devmode; + uid_t devuid; + gid_t devgid; + + /* only set when device is passed through netlink */ + DeviceAction action; + uint64_t seqnum; + + bool parent_set:1; /* no need to try to reload parent */ + bool sysattrs_read:1; /* don't try to re-read sysattrs once read */ + bool property_tags_outdated:1; /* need to update TAGS= property */ + bool property_devlinks_outdated:1; /* need to update DEVLINKS= property */ + bool properties_buf_outdated:1; /* need to reread hashmap */ + bool sysname_set:1; /* don't reread sysname */ + bool subsystem_set:1; /* don't reread subsystem */ + bool driver_subsystem_set:1; /* don't reread subsystem */ + bool driver_set:1; /* don't reread driver */ + bool uevent_loaded:1; /* don't reread uevent */ + bool db_loaded; /* don't reread db */ + + bool is_initialized:1; + bool sealed:1; /* don't read more information from uevent/db */ + bool db_persist:1; /* don't clean up the db when switching from initrd to real root */ +}; + +int device_new_aux(sd_device **ret); +int device_add_property_aux(sd_device *device, const char *key, const char *value, bool db); +int device_add_property_internal(sd_device *device, const char *key, const char *value); +int device_read_uevent_file(sd_device *device); + +int device_set_syspath(sd_device *device, const char *_syspath, bool verify); +int device_set_ifindex(sd_device *device, const char *ifindex); +int device_set_devmode(sd_device *device, const char *devmode); +int device_set_devname(sd_device *device, const char *_devname); +int device_set_devtype(sd_device *device, const char *_devtype); +int device_set_devnum(sd_device *device, const char *major, const char *minor); +int device_set_subsystem(sd_device *device, const char *_subsystem); +int device_set_driver(sd_device *device, const char *_driver); +int device_set_usec_initialized(sd_device *device, usec_t when); diff --git a/src/libsystemd/sd-device/device-monitor-private.h b/src/libsystemd/sd-device/device-monitor-private.h new file mode 100644 index 00000000..2659cc3c --- /dev/null +++ b/src/libsystemd/sd-device/device-monitor-private.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-device.h" + +typedef enum MonitorNetlinkGroup { + MONITOR_GROUP_NONE, + MONITOR_GROUP_KERNEL, + MONITOR_GROUP_UDEV, + _MONITOR_NETLINK_GROUP_MAX, + _MONITOR_NETLINK_GROUP_INVALID = -1, +} MonitorNetlinkGroup; + +int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group, int fd); +int device_monitor_disconnect(sd_device_monitor *m); +int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor *sender); +int device_monitor_enable_receiving(sd_device_monitor *m); +int device_monitor_get_fd(sd_device_monitor *m); +int device_monitor_send_device(sd_device_monitor *m, sd_device_monitor *destination, sd_device *device); +int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret); diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c new file mode 100644 index 00000000..42753abe --- /dev/null +++ b/src/libsystemd/sd-device/device-monitor.c @@ -0,0 +1,755 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-device.h" +#include "sd-event.h" + +#include "MurmurHash2.h" +#include "alloc-util.h" +#include "device-monitor-private.h" +#include "device-private.h" +#include "device-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "hashmap.h" +#include "io-util.h" +#include "mountpoint-util.h" +#include "set.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" + +struct sd_device_monitor { + unsigned n_ref; + + int sock; + union sockaddr_union snl; + union sockaddr_union snl_trusted_sender; + bool bound; + + Hashmap *subsystem_filter; + Set *tag_filter; + bool filter_uptodate; + + sd_event *event; + sd_event_source *event_source; + sd_device_monitor_handler_t callback; + void *userdata; +}; + +#define UDEV_MONITOR_MAGIC 0xfeedcafe + +typedef struct monitor_netlink_header { + /* "libudev" prefix to distinguish libudev and kernel messages */ + char prefix[8]; + /* Magic to protect against daemon <-> Library message format mismatch + * Used in the kernel from socket filter rules; needs to be stored in network order */ + unsigned magic; + /* Total length of header structure known to the sender */ + unsigned header_size; + /* Properties string buffer */ + unsigned properties_off; + unsigned properties_len; + /* Hashes of primary device properties strings, to let libudev subscribers + * use in-kernel socket filters; values need to be stored in network order */ + unsigned filter_subsystem_hash; + unsigned filter_devtype_hash; + unsigned filter_tag_bloom_hi; + unsigned filter_tag_bloom_lo; +} monitor_netlink_header; + +static int monitor_set_nl_address(sd_device_monitor *m) { + union sockaddr_union snl; + socklen_t addrlen; + + assert(m); + + /* Get the address the kernel has assigned us. + * It is usually, but not necessarily the pid. */ + addrlen = sizeof(struct sockaddr_nl); + if (getsockname(m->sock, &snl.sa, &addrlen) < 0) + return -errno; + + m->snl.nl.nl_pid = snl.nl.nl_pid; + return 0; +} + +int device_monitor_allow_unicast_sender(sd_device_monitor *m, sd_device_monitor *sender) { + assert_return(m, -EINVAL); + assert_return(sender, -EINVAL); + + m->snl_trusted_sender.nl.nl_pid = sender->snl.nl.nl_pid; + return 0; +} + +_public_ int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size) { + int r, n = (int) size; + + assert_return(m, -EINVAL); + assert_return((size_t) n == size, -EINVAL); + + if (setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUFFORCE, n) < 0) { + r = setsockopt_int(m->sock, SOL_SOCKET, SO_RCVBUF, n); + if (r < 0) + return r; + } + + return 0; +} + +int device_monitor_disconnect(sd_device_monitor *m) { + assert(m); + + m->sock = safe_close(m->sock); + return 0; +} + +int device_monitor_get_fd(sd_device_monitor *m) { + assert_return(m, -EINVAL); + + return m->sock; +} + +int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group, int fd) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL; + _cleanup_close_ int sock = -1; + int r; + + assert_return(ret, -EINVAL); + assert_return(group >= 0 && group < _MONITOR_NETLINK_GROUP_MAX, -EINVAL); + + if (group == MONITOR_GROUP_UDEV && + access("/run/udev/control", F_OK) < 0 && + dev_is_devtmpfs() <= 0) { + + /* + * We do not support subscribing to uevents if no instance of + * udev is running. Uevents would otherwise broadcast the + * processing data of the host into containers, which is not + * desired. + * + * Containers will currently not get any udev uevents, until + * a supporting infrastructure is available. + * + * We do not set a netlink multicast group here, so the socket + * will not receive any messages. + */ + + log_debug("sd-device-monitor: The udev service seems not to be active, disabling the monitor"); + group = MONITOR_GROUP_NONE; + } + + if (fd < 0) { + sock = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); + if (sock < 0) + return log_debug_errno(errno, "sd-device-monitor: Failed to create socket: %m"); + } + + m = new(sd_device_monitor, 1); + if (!m) + return -ENOMEM; + + *m = (sd_device_monitor) { + .n_ref = 1, + .sock = fd >= 0 ? fd : TAKE_FD(sock), + .bound = fd >= 0, + .snl.nl.nl_family = AF_NETLINK, + .snl.nl.nl_groups = group, + }; + + if (fd >= 0) { + r = monitor_set_nl_address(m); + if (r < 0) + return log_debug_errno(r, "sd-device-monitor: Failed to set netlink address: %m"); + } + + *ret = TAKE_PTR(m); + return 0; +} + +_public_ int sd_device_monitor_new(sd_device_monitor **ret) { + return device_monitor_new_full(ret, MONITOR_GROUP_UDEV, -1); +} + +_public_ int sd_device_monitor_stop(sd_device_monitor *m) { + assert_return(m, -EINVAL); + + m->event_source = sd_event_source_unref(m->event_source); + (void) device_monitor_disconnect(m); + + return 0; +} + +static int device_monitor_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + sd_device_monitor *m = userdata; + + assert(m); + + if (device_monitor_receive_device(m, &device) <= 0) + return 0; + + if (m->callback) + return m->callback(m, device, m->userdata); + + return 0; +} + +_public_ int sd_device_monitor_start(sd_device_monitor *m, sd_device_monitor_handler_t callback, void *userdata) { + int r; + + assert_return(m, -EINVAL); + + if (!m->event) { + r = sd_device_monitor_attach_event(m, NULL); + if (r < 0) + return r; + } + + r = device_monitor_enable_receiving(m); + if (r < 0) + return r; + + m->callback = callback; + m->userdata = userdata; + + r = sd_event_add_io(m->event, &m->event_source, m->sock, EPOLLIN, device_monitor_event_handler, m); + if (r < 0) + return r; + + (void) sd_event_source_set_description(m->event_source, "sd-device-monitor"); + + return 0; +} + +_public_ int sd_device_monitor_detach_event(sd_device_monitor *m) { + assert_return(m, -EINVAL); + + (void) sd_device_monitor_stop(m); + m->event = sd_event_unref(m->event); + + return 0; +} + +_public_ int sd_device_monitor_attach_event(sd_device_monitor *m, sd_event *event) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->event, -EBUSY); + + if (event) + m->event = sd_event_ref(event); + else { + r = sd_event_default(&m->event); + if (r < 0) + return r; + } + + return 0; +} + +_public_ sd_event *sd_device_monitor_get_event(sd_device_monitor *m) { + assert_return(m, NULL); + + return m->event; +} + +_public_ sd_event_source *sd_device_monitor_get_event_source(sd_device_monitor *m) { + assert_return(m, NULL); + + return m->event_source; +} + +int device_monitor_enable_receiving(sd_device_monitor *m) { + int r; + + assert_return(m, -EINVAL); + + r = sd_device_monitor_filter_update(m); + if (r < 0) + return log_debug_errno(r, "sd-device-monitor: Failed to update filter: %m"); + + if (!m->bound) { + /* enable receiving of sender credentials */ + r = setsockopt_int(m->sock, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return log_debug_errno(r, "sd-device-monitor: Failed to set socket option SO_PASSCRED: %m"); + + if (bind(m->sock, &m->snl.sa, sizeof(struct sockaddr_nl)) < 0) + return log_debug_errno(errno, "sd-device-monitor: Failed to bind monitoring socket: %m"); + + m->bound = true; + + r = monitor_set_nl_address(m); + if (r < 0) + return log_debug_errno(r, "sd-device-monitor: Failed to set address: %m"); + } + + return 0; +} + +static sd_device_monitor *device_monitor_free(sd_device_monitor *m) { + assert(m); + + (void) sd_device_monitor_detach_event(m); + + hashmap_free_free_free(m->subsystem_filter); + set_free_free(m->tag_filter); + + return mfree(m); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_monitor, sd_device_monitor, device_monitor_free); + +static int passes_filter(sd_device_monitor *m, sd_device *device) { + const char *tag, *subsystem, *devtype, *s, *d = NULL; + Iterator i; + int r; + + assert_return(m, -EINVAL); + assert_return(device, -EINVAL); + + if (hashmap_isempty(m->subsystem_filter)) + goto tag; + + r = sd_device_get_subsystem(device, &s); + if (r < 0) + return r; + + r = sd_device_get_devtype(device, &d); + if (r < 0 && r != -ENOENT) + return r; + + HASHMAP_FOREACH_KEY(devtype, subsystem, m->subsystem_filter, i) { + if (!streq(s, subsystem)) + continue; + + if (!devtype) + goto tag; + + if (!d) + continue; + + if (streq(d, devtype)) + goto tag; + } + + return 0; + +tag: + if (set_isempty(m->tag_filter)) + return 1; + + SET_FOREACH(tag, m->tag_filter, i) + if (sd_device_has_tag(device, tag) > 0) + return 1; + + return 0; +} + +int device_monitor_receive_device(sd_device_monitor *m, sd_device **ret) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + union { + monitor_netlink_header nlh; + char raw[8192]; + } buf; + struct iovec iov = { + .iov_base = &buf, + .iov_len = sizeof(buf) + }; + char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; + union sockaddr_union snl; + struct msghdr smsg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cred_msg, + .msg_controllen = sizeof(cred_msg), + .msg_name = &snl, + .msg_namelen = sizeof(snl), + }; + struct cmsghdr *cmsg; + struct ucred *cred; + ssize_t buflen, bufpos; + bool is_initialized = false; + int r; + + assert(ret); + + buflen = recvmsg(m->sock, &smsg, 0); + if (buflen < 0) { + if (errno != EINTR) + log_debug_errno(errno, "sd-device-monitor: Failed to receive message: %m"); + return -errno; + } + + if (buflen < 32 || (smsg.msg_flags & MSG_TRUNC)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "sd-device-monitor: Invalid message length."); + + if (snl.nl.nl_groups == MONITOR_GROUP_NONE) { + /* unicast message, check if we trust the sender */ + if (m->snl_trusted_sender.nl.nl_pid == 0 || + snl.nl.nl_pid != m->snl_trusted_sender.nl.nl_pid) + return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), + "sd-device-monitor: Unicast netlink message ignored."); + + } else if (snl.nl.nl_groups == MONITOR_GROUP_KERNEL) { + if (snl.nl.nl_pid > 0) + return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), + "sd-device-monitor: Multicast kernel netlink message from PID %"PRIu32" ignored.", snl.nl.nl_pid); + } + + cmsg = CMSG_FIRSTHDR(&smsg); + if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) + return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), + "sd-device-monitor: No sender credentials received, message ignored."); + + cred = (struct ucred*) CMSG_DATA(cmsg); + if (cred->uid != 0) + return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), + "sd-device-monitor: Sender uid="UID_FMT", message ignored.", cred->uid); + + if (streq(buf.raw, "libudev")) { + /* udev message needs proper version magic */ + if (buf.nlh.magic != htobe32(UDEV_MONITOR_MAGIC)) + return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), + "sd-device-monitor: Invalid message signature (%x != %x)", + buf.nlh.magic, htobe32(UDEV_MONITOR_MAGIC)); + + if (buf.nlh.properties_off+32 > (size_t) buflen) + return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), + "sd-device-monitor: Invalid message length (%u > %zd)", + buf.nlh.properties_off+32, buflen); + + bufpos = buf.nlh.properties_off; + + /* devices received from udev are always initialized */ + is_initialized = true; + + } else { + /* kernel message with header */ + bufpos = strlen(buf.raw) + 1; + if ((size_t) bufpos < sizeof("a@/d") || bufpos >= buflen) + return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), + "sd-device-monitor: Invalid message length"); + + /* check message header */ + if (!strstr(buf.raw, "@/")) + return log_debug_errno(SYNTHETIC_ERRNO(EAGAIN), + "sd-device-monitor: Invalid message header"); + } + + r = device_new_from_nulstr(&device, (uint8_t*) &buf.raw[bufpos], buflen - bufpos); + if (r < 0) + return log_debug_errno(r, "sd-device-monitor: Failed to create device from received message: %m"); + + if (is_initialized) + device_set_is_initialized(device); + + /* Skip device, if it does not pass the current filter */ + r = passes_filter(m, device); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device-monitor: Failed to check received device passing filter: %m"); + if (r == 0) + log_device_debug(device, "sd-device-monitor: Received device does not pass filter, ignoring"); + else + *ret = TAKE_PTR(device); + + return r; +} + +static uint32_t string_hash32(const char *str) { + return MurmurHash2(str, strlen(str), 0); +} + +/* Get a bunch of bit numbers out of the hash, and set the bits in our bit field */ +static uint64_t string_bloom64(const char *str) { + uint64_t bits = 0; + uint32_t hash = string_hash32(str); + + bits |= 1LLU << (hash & 63); + bits |= 1LLU << ((hash >> 6) & 63); + bits |= 1LLU << ((hash >> 12) & 63); + bits |= 1LLU << ((hash >> 18) & 63); + return bits; +} + +int device_monitor_send_device( + sd_device_monitor *m, + sd_device_monitor *destination, + sd_device *device) { + + monitor_netlink_header nlh = { + .prefix = "libudev", + .magic = htobe32(UDEV_MONITOR_MAGIC), + .header_size = sizeof nlh, + }; + struct iovec iov[2] = { + { .iov_base = &nlh, .iov_len = sizeof nlh }, + }; + struct msghdr smsg = { + .msg_iov = iov, + .msg_iovlen = 2, + }; + /* default destination for sending */ + union sockaddr_union default_destination = { + .nl.nl_family = AF_NETLINK, + .nl.nl_groups = MONITOR_GROUP_UDEV, + }; + uint64_t tag_bloom_bits; + const char *buf, *val; + ssize_t count; + size_t blen; + int r; + + assert(m); + assert(device); + + r = device_get_properties_nulstr(device, (const uint8_t **) &buf, &blen); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device-monitor: Failed to get device properties: %m"); + if (blen < 32) { + log_device_debug(device, "sd-device-monitor: Length of device property nulstr is too small to contain valid device information"); + return -EINVAL; + } + + /* fill in versioned header */ + r = sd_device_get_subsystem(device, &val); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device-monitor: Failed to get device subsystem: %m"); + nlh.filter_subsystem_hash = htobe32(string_hash32(val)); + + if (sd_device_get_devtype(device, &val) >= 0) + nlh.filter_devtype_hash = htobe32(string_hash32(val)); + + /* add tag bloom filter */ + tag_bloom_bits = 0; + FOREACH_DEVICE_TAG(device, val) + tag_bloom_bits |= string_bloom64(val); + + if (tag_bloom_bits > 0) { + nlh.filter_tag_bloom_hi = htobe32(tag_bloom_bits >> 32); + nlh.filter_tag_bloom_lo = htobe32(tag_bloom_bits & 0xffffffff); + } + + /* add properties list */ + nlh.properties_off = iov[0].iov_len; + nlh.properties_len = blen; + iov[1] = IOVEC_MAKE((char*) buf, blen); + + /* + * Use custom address for target, or the default one. + * + * If we send to a multicast group, we will get + * ECONNREFUSED, which is expected. + */ + smsg.msg_name = destination ? &destination->snl : &default_destination; + smsg.msg_namelen = sizeof(struct sockaddr_nl); + count = sendmsg(m->sock, &smsg, 0); + if (count < 0) { + if (!destination && errno == ECONNREFUSED) { + log_device_debug(device, "sd-device-monitor: Passed to netlink monitor"); + return 0; + } else + return log_device_debug_errno(device, errno, "sd-device-monitor: Failed to send device to netlink monitor: %m"); + } + + log_device_debug(device, "sd-device-monitor: Passed %zi byte to netlink monitor", count); + return count; +} + +static void bpf_stmt(struct sock_filter *ins, unsigned *i, + unsigned short code, unsigned data) { + ins[(*i)++] = (struct sock_filter) { + .code = code, + .k = data, + }; +} + +static void bpf_jmp(struct sock_filter *ins, unsigned *i, + unsigned short code, unsigned data, + unsigned short jt, unsigned short jf) { + ins[(*i)++] = (struct sock_filter) { + .code = code, + .jt = jt, + .jf = jf, + .k = data, + }; +} + +_public_ int sd_device_monitor_filter_update(sd_device_monitor *m) { + struct sock_filter ins[512] = {}; + struct sock_fprog filter; + const char *subsystem, *devtype, *tag; + unsigned i = 0; + Iterator it; + + assert_return(m, -EINVAL); + + if (m->filter_uptodate) + return 0; + + if (hashmap_isempty(m->subsystem_filter) && + set_isempty(m->tag_filter)) { + m->filter_uptodate = true; + return 0; + } + + /* load magic in A */ + bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, magic)); + /* jump if magic matches */ + bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, UDEV_MONITOR_MAGIC, 1, 0); + /* wrong magic, pass packet */ + bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff); + + if (!set_isempty(m->tag_filter)) { + int tag_matches = set_size(m->tag_filter); + + /* add all tags matches */ + SET_FOREACH(tag, m->tag_filter, it) { + uint64_t tag_bloom_bits = string_bloom64(tag); + uint32_t tag_bloom_hi = tag_bloom_bits >> 32; + uint32_t tag_bloom_lo = tag_bloom_bits & 0xffffffff; + + /* load device bloom bits in A */ + bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, filter_tag_bloom_hi)); + /* clear bits (tag bits & bloom bits) */ + bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_hi); + /* jump to next tag if it does not match */ + bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_hi, 0, 3); + + /* load device bloom bits in A */ + bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, filter_tag_bloom_lo)); + /* clear bits (tag bits & bloom bits) */ + bpf_stmt(ins, &i, BPF_ALU|BPF_AND|BPF_K, tag_bloom_lo); + /* jump behind end of tag match block if tag matches */ + tag_matches--; + bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, tag_bloom_lo, 1 + (tag_matches * 6), 0); + } + + /* nothing matched, drop packet */ + bpf_stmt(ins, &i, BPF_RET|BPF_K, 0); + } + + /* add all subsystem matches */ + if (!hashmap_isempty(m->subsystem_filter)) { + HASHMAP_FOREACH_KEY(devtype, subsystem, m->subsystem_filter, it) { + uint32_t hash = string_hash32(subsystem); + + /* load device subsystem value in A */ + bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, filter_subsystem_hash)); + if (!devtype) { + /* jump if subsystem does not match */ + bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1); + } else { + /* jump if subsystem does not match */ + bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 3); + /* load device devtype value in A */ + bpf_stmt(ins, &i, BPF_LD|BPF_W|BPF_ABS, offsetof(monitor_netlink_header, filter_devtype_hash)); + /* jump if value does not match */ + hash = string_hash32(devtype); + bpf_jmp(ins, &i, BPF_JMP|BPF_JEQ|BPF_K, hash, 0, 1); + } + + /* matched, pass packet */ + bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff); + + if (i+1 >= ELEMENTSOF(ins)) + return -E2BIG; + } + + /* nothing matched, drop packet */ + bpf_stmt(ins, &i, BPF_RET|BPF_K, 0); + } + + /* matched, pass packet */ + bpf_stmt(ins, &i, BPF_RET|BPF_K, 0xffffffff); + + /* install filter */ + filter = (struct sock_fprog) { + .len = i, + .filter = ins, + }; + if (setsockopt(m->sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) < 0) + return -errno; + + m->filter_uptodate = true; + return 0; +} + +_public_ int sd_device_monitor_filter_add_match_subsystem_devtype(sd_device_monitor *m, const char *subsystem, const char *devtype) { + _cleanup_free_ char *s = NULL, *d = NULL; + int r; + + assert_return(m, -EINVAL); + assert_return(subsystem, -EINVAL); + + s = strdup(subsystem); + if (!s) + return -ENOMEM; + + if (devtype) { + d = strdup(devtype); + if (!d) + return -ENOMEM; + } + + r = hashmap_ensure_allocated(&m->subsystem_filter, NULL); + if (r < 0) + return r; + + r = hashmap_put(m->subsystem_filter, s, d); + if (r < 0) + return r; + + s = d = NULL; + m->filter_uptodate = false; + + return 0; +} + +_public_ int sd_device_monitor_filter_add_match_tag(sd_device_monitor *m, const char *tag) { + _cleanup_free_ char *t = NULL; + int r; + + assert_return(m, -EINVAL); + assert_return(tag, -EINVAL); + + t = strdup(tag); + if (!t) + return -ENOMEM; + + r = set_ensure_allocated(&m->tag_filter, &string_hash_ops); + if (r < 0) + return r; + + r = set_put(m->tag_filter, t); + if (r == -EEXIST) + return 0; + if (r < 0) + return r; + + TAKE_PTR(t); + m->filter_uptodate = false; + + return 0; +} + +_public_ int sd_device_monitor_filter_remove(sd_device_monitor *m) { + static const struct sock_fprog filter = { 0, NULL }; + + assert_return(m, -EINVAL); + + m->subsystem_filter = hashmap_free_free_free(m->subsystem_filter); + m->tag_filter = set_free_free(m->tag_filter); + + if (setsockopt(m->sock, SOL_SOCKET, SO_DETACH_FILTER, &filter, sizeof(filter)) < 0) + return -errno; + + m->filter_uptodate = true; + return 0; +} diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c new file mode 100644 index 00000000..16f8627b --- /dev/null +++ b/src/libsystemd/sd-device/device-private.c @@ -0,0 +1,1004 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-device.h" + +#include "alloc-util.h" +#include "device-internal.h" +#include "device-private.h" +#include "device-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hashmap.h" +#include "macro.h" +#include "mkdir.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "set.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "strxcpyx.h" +#include "tmpfile-util.h" +#include "user-util.h" + +int device_add_property(sd_device *device, const char *key, const char *value) { + int r; + + assert(device); + assert(key); + + r = device_add_property_aux(device, key, value, false); + if (r < 0) + return r; + + if (key[0] != '.') { + r = device_add_property_aux(device, key, value, true); + if (r < 0) + return r; + } + + return 0; +} + +void device_set_devlink_priority(sd_device *device, int priority) { + assert(device); + + device->devlink_priority = priority; +} + +void device_set_is_initialized(sd_device *device) { + assert(device); + + device->is_initialized = true; +} + +int device_ensure_usec_initialized(sd_device *device, sd_device *device_old) { + usec_t when; + + assert(device); + + if (device_old && device_old->usec_initialized > 0) + when = device_old->usec_initialized; + else + when = now(CLOCK_MONOTONIC); + + return device_set_usec_initialized(device, when); +} + +uint64_t device_get_properties_generation(sd_device *device) { + assert(device); + + return device->properties_generation; +} + +uint64_t device_get_tags_generation(sd_device *device) { + assert(device); + + return device->tags_generation; +} + +uint64_t device_get_devlinks_generation(sd_device *device) { + assert(device); + + return device->devlinks_generation; +} + +int device_get_devnode_mode(sd_device *device, mode_t *mode) { + int r; + + assert(device); + + r = device_read_db(device); + if (r < 0) + return r; + + if (device->devmode == (mode_t) -1) + return -ENOENT; + + if (mode) + *mode = device->devmode; + + return 0; +} + +int device_get_devnode_uid(sd_device *device, uid_t *uid) { + int r; + + assert(device); + + r = device_read_db(device); + if (r < 0) + return r; + + if (device->devuid == (uid_t) -1) + return -ENOENT; + + if (uid) + *uid = device->devuid; + + return 0; +} + +static int device_set_devuid(sd_device *device, const char *uid) { + unsigned u; + int r; + + assert(device); + assert(uid); + + r = safe_atou(uid, &u); + if (r < 0) + return r; + + r = device_add_property_internal(device, "DEVUID", uid); + if (r < 0) + return r; + + device->devuid = u; + + return 0; +} + +int device_get_devnode_gid(sd_device *device, gid_t *gid) { + int r; + + assert(device); + + r = device_read_db(device); + if (r < 0) + return r; + + if (device->devgid == (gid_t) -1) + return -ENOENT; + + if (gid) + *gid = device->devgid; + + return 0; +} + +static int device_set_devgid(sd_device *device, const char *gid) { + unsigned g; + int r; + + assert(device); + assert(gid); + + r = safe_atou(gid, &g); + if (r < 0) + return r; + + r = device_add_property_internal(device, "DEVGID", gid); + if (r < 0) + return r; + + device->devgid = g; + + return 0; +} + +int device_get_action(sd_device *device, DeviceAction *action) { + assert(device); + + if (device->action < 0) + return -ENOENT; + + if (action) + *action = device->action; + + return 0; +} + +static int device_set_action(sd_device *device, const char *action) { + DeviceAction a; + int r; + + assert(device); + assert(action); + + a = device_action_from_string(action); + if (a < 0) + return -EINVAL; + + r = device_add_property_internal(device, "ACTION", action); + if (r < 0) + return r; + + device->action = a; + + return 0; +} + +int device_get_seqnum(sd_device *device, uint64_t *seqnum) { + assert(device); + + if (device->seqnum == 0) + return -ENOENT; + + if (seqnum) + *seqnum = device->seqnum; + + return 0; +} + +static int device_set_seqnum(sd_device *device, const char *str) { + uint64_t seqnum; + int r; + + assert(device); + assert(str); + + r = safe_atou64(str, &seqnum); + if (r < 0) + return r; + if (seqnum == 0) + return -EINVAL; + + r = device_add_property_internal(device, "SEQNUM", str); + if (r < 0) + return r; + + device->seqnum = seqnum; + + return 0; +} + +static int device_amend(sd_device *device, const char *key, const char *value) { + int r; + + assert(device); + assert(key); + assert(value); + + if (streq(key, "DEVPATH")) { + char *path; + + path = strjoina("/sys", value); + + /* the caller must verify or trust this data (e.g., if it comes from the kernel) */ + r = device_set_syspath(device, path, false); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set syspath to '%s': %m", path); + } else if (streq(key, "SUBSYSTEM")) { + r = device_set_subsystem(device, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem to '%s': %m", value); + } else if (streq(key, "DEVTYPE")) { + r = device_set_devtype(device, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set devtype to '%s': %m", value); + } else if (streq(key, "DEVNAME")) { + r = device_set_devname(device, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set devname to '%s': %m", value); + } else if (streq(key, "USEC_INITIALIZED")) { + usec_t t; + + r = safe_atou64(value, &t); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to parse timestamp '%s': %m", value); + + r = device_set_usec_initialized(device, t); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set usec-initialized to '%s': %m", value); + } else if (streq(key, "DRIVER")) { + r = device_set_driver(device, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set driver to '%s': %m", value); + } else if (streq(key, "IFINDEX")) { + r = device_set_ifindex(device, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set ifindex to '%s': %m", value); + } else if (streq(key, "DEVMODE")) { + r = device_set_devmode(device, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set devmode to '%s': %m", value); + } else if (streq(key, "DEVUID")) { + r = device_set_devuid(device, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set devuid to '%s': %m", value); + } else if (streq(key, "DEVGID")) { + r = device_set_devgid(device, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set devgid to '%s': %m", value); + } else if (streq(key, "ACTION")) { + r = device_set_action(device, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set action to '%s': %m", value); + } else if (streq(key, "SEQNUM")) { + r = device_set_seqnum(device, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set SEQNUM to '%s': %m", value); + } else if (streq(key, "DEVLINKS")) { + const char *word, *state; + size_t l; + + FOREACH_WORD(word, l, value, state) { + char devlink[l + 1]; + + strncpy(devlink, word, l); + devlink[l] = '\0'; + + r = device_add_devlink(device, devlink); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", devlink); + } + } else if (streq(key, "TAGS")) { + const char *word, *state; + size_t l; + + FOREACH_WORD_SEPARATOR(word, l, value, ":", state) { + char tag[l + 1]; + + (void) strncpy(tag, word, l); + tag[l] = '\0'; + + r = device_add_tag(device, tag); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", tag); + } + } else { + r = device_add_property_internal(device, key, value); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to add property '%s=%s': %m", key, value); + } + + return 0; +} + +static int device_append(sd_device *device, char *key, const char **_major, const char **_minor) { + const char *major = NULL, *minor = NULL; + char *value; + int r; + + assert(device); + assert(key); + assert(_major); + assert(_minor); + + value = strchr(key, '='); + if (!value) { + log_device_debug(device, "sd-device: Not a key-value pair: '%s'", key); + return -EINVAL; + } + + *value = '\0'; + + value++; + + if (streq(key, "MAJOR")) + major = value; + else if (streq(key, "MINOR")) + minor = value; + else { + r = device_amend(device, key, value); + if (r < 0) + return r; + } + + if (major != 0) + *_major = major; + + if (minor != 0) + *_minor = minor; + + return 0; +} + +void device_seal(sd_device *device) { + assert(device); + + device->sealed = true; +} + +static int device_verify(sd_device *device) { + assert(device); + + if (!device->devpath || !device->subsystem || device->action < 0 || device->seqnum == 0) { + log_device_debug(device, "sd-device: Device created from strv or nulstr lacks devpath, subsystem, action or seqnum."); + return -EINVAL; + } + + device->sealed = true; + + return 0; +} + +int device_new_from_strv(sd_device **ret, char **strv) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + char **key; + const char *major = NULL, *minor = NULL; + int r; + + assert(ret); + assert(strv); + + r = device_new_aux(&device); + if (r < 0) + return r; + + STRV_FOREACH(key, strv) { + r = device_append(device, *key, &major, &minor); + if (r < 0) + return r; + } + + if (major) { + r = device_set_devnum(device, major, minor); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor); + } + + r = device_verify(device); + if (r < 0) + return r; + + *ret = TAKE_PTR(device); + + return 0; +} + +int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + const char *major = NULL, *minor = NULL; + unsigned i = 0; + int r; + + assert(ret); + assert(nulstr); + assert(len); + + r = device_new_aux(&device); + if (r < 0) + return r; + + while (i < len) { + char *key; + const char *end; + + key = (char*)&nulstr[i]; + end = memchr(key, '\0', len - i); + if (!end) { + log_device_debug(device, "sd-device: Failed to parse nulstr"); + return -EINVAL; + } + i += end - key + 1; + + r = device_append(device, key, &major, &minor); + if (r < 0) + return r; + } + + if (major) { + r = device_set_devnum(device, major, minor); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor); + } + + r = device_verify(device); + if (r < 0) + return r; + + *ret = TAKE_PTR(device); + + return 0; +} + +static int device_update_properties_bufs(sd_device *device) { + const char *val, *prop; + _cleanup_free_ char **buf_strv = NULL; + _cleanup_free_ uint8_t *buf_nulstr = NULL; + size_t allocated_nulstr = 0; + size_t nulstr_len = 0, num = 0, i = 0; + + assert(device); + + if (!device->properties_buf_outdated) + return 0; + + FOREACH_DEVICE_PROPERTY(device, prop, val) { + size_t len = 0; + + len = strlen(prop) + 1 + strlen(val); + + buf_nulstr = GREEDY_REALLOC0(buf_nulstr, allocated_nulstr, nulstr_len + len + 2); + if (!buf_nulstr) + return -ENOMEM; + + strscpyl((char *)buf_nulstr + nulstr_len, len + 1, prop, "=", val, NULL); + nulstr_len += len + 1; + ++num; + } + + /* build buf_strv from buf_nulstr */ + buf_strv = new0(char *, num + 1); + if (!buf_strv) + return -ENOMEM; + + NULSTR_FOREACH(val, (char*) buf_nulstr) { + buf_strv[i] = (char *) val; + assert(i < num); + i++; + } + + free_and_replace(device->properties_nulstr, buf_nulstr); + device->properties_nulstr_len = nulstr_len; + free_and_replace(device->properties_strv, buf_strv); + + device->properties_buf_outdated = false; + + return 0; +} + +int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len) { + int r; + + assert(device); + assert(nulstr); + assert(len); + + r = device_update_properties_bufs(device); + if (r < 0) + return r; + + *nulstr = device->properties_nulstr; + *len = device->properties_nulstr_len; + + return 0; +} + +int device_get_properties_strv(sd_device *device, char ***strv) { + int r; + + assert(device); + assert(strv); + + r = device_update_properties_bufs(device); + if (r < 0) + return r; + + *strv = device->properties_strv; + + return 0; +} + +int device_get_devlink_priority(sd_device *device, int *priority) { + int r; + + assert(device); + assert(priority); + + r = device_read_db(device); + if (r < 0) + return r; + + *priority = device->devlink_priority; + + return 0; +} + +int device_get_watch_handle(sd_device *device, int *handle) { + int r; + + assert(device); + + r = device_read_db(device); + if (r < 0) + return r; + + if (device->watch_handle < 0) + return -ENOENT; + + if (handle) + *handle = device->watch_handle; + + return 0; +} + +void device_set_watch_handle(sd_device *device, int handle) { + assert(device); + + device->watch_handle = handle; +} + +int device_rename(sd_device *device, const char *name) { + _cleanup_free_ char *dirname = NULL; + const char *new_syspath, *interface; + int r; + + assert(device); + assert(name); + + dirname = dirname_malloc(device->syspath); + if (!dirname) + return -ENOMEM; + + new_syspath = prefix_roota(dirname, name); + + /* the user must trust that the new name is correct */ + r = device_set_syspath(device, new_syspath, false); + if (r < 0) + return r; + + r = sd_device_get_property_value(device, "INTERFACE", &interface); + if (r >= 0) { + /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */ + r = device_add_property_internal(device, "INTERFACE_OLD", interface); + if (r < 0) + return r; + + r = device_add_property_internal(device, "INTERFACE", name); + if (r < 0) + return r; + } else if (r != -ENOENT) + return r; + + return 0; +} + +int device_shallow_clone(sd_device *old_device, sd_device **new_device) { + _cleanup_(sd_device_unrefp) sd_device *ret = NULL; + int r; + + assert(old_device); + assert(new_device); + + r = device_new_aux(&ret); + if (r < 0) + return r; + + r = device_set_syspath(ret, old_device->syspath, false); + if (r < 0) + return r; + + r = device_set_subsystem(ret, old_device->subsystem); + if (r < 0) + return r; + + ret->devnum = old_device->devnum; + + *new_device = TAKE_PTR(ret); + + return 0; +} + +int device_clone_with_db(sd_device *old_device, sd_device **new_device) { + _cleanup_(sd_device_unrefp) sd_device *ret = NULL; + int r; + + assert(old_device); + assert(new_device); + + r = device_shallow_clone(old_device, &ret); + if (r < 0) + return r; + + r = device_read_db(ret); + if (r < 0) + return r; + + ret->sealed = true; + + *new_device = TAKE_PTR(ret); + + return 0; +} + +int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action) { + _cleanup_(sd_device_unrefp) sd_device *ret = NULL; + int r; + + assert(new_device); + assert(syspath); + assert(action); + + r = sd_device_new_from_syspath(&ret, syspath); + if (r < 0) + return r; + + r = device_read_uevent_file(ret); + if (r < 0) + return r; + + r = device_set_action(ret, action); + if (r < 0) + return r; + + *new_device = TAKE_PTR(ret); + + return 0; +} + +int device_new_from_stat_rdev(sd_device **ret, const struct stat *st) { + char type; + + assert(ret); + assert(st); + + if (S_ISBLK(st->st_mode)) + type = 'b'; + else if (S_ISCHR(st->st_mode)) + type = 'c'; + else + return -ENOTTY; + + return sd_device_new_from_devnum(ret, type, st->st_rdev); +} + +int device_copy_properties(sd_device *device_dst, sd_device *device_src) { + const char *property, *value; + Iterator i; + int r; + + assert(device_dst); + assert(device_src); + + r = device_properties_prepare(device_src); + if (r < 0) + return r; + + ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties_db, i) { + r = device_add_property_aux(device_dst, property, value, true); + if (r < 0) + return r; + } + + ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties, i) { + r = device_add_property_aux(device_dst, property, value, false); + if (r < 0) + return r; + } + + return 0; +} + +void device_cleanup_tags(sd_device *device) { + assert(device); + + set_free_free(device->tags); + device->tags = NULL; + device->property_tags_outdated = true; + device->tags_generation++; +} + +void device_cleanup_devlinks(sd_device *device) { + assert(device); + + set_free_free(device->devlinks); + device->devlinks = NULL; + device->property_devlinks_outdated = true; + device->devlinks_generation++; +} + +void device_remove_tag(sd_device *device, const char *tag) { + assert(device); + assert(tag); + + free(set_remove(device->tags, tag)); + device->property_tags_outdated = true; + device->tags_generation++; +} + +static int device_tag(sd_device *device, const char *tag, bool add) { + const char *id; + char *path; + int r; + + assert(device); + assert(tag); + + r = device_get_id_filename(device, &id); + if (r < 0) + return r; + + path = strjoina("/run/udev/tags/", tag, "/", id); + + if (add) { + r = touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0444); + if (r < 0) + return r; + } else { + r = unlink(path); + if (r < 0 && errno != ENOENT) + return -errno; + } + + return 0; +} + +int device_tag_index(sd_device *device, sd_device *device_old, bool add) { + const char *tag; + int r = 0, k; + + if (add && device_old) { + /* delete possible left-over tags */ + FOREACH_DEVICE_TAG(device_old, tag) { + if (!sd_device_has_tag(device, tag)) { + k = device_tag(device_old, tag, false); + if (r >= 0 && k < 0) + r = k; + } + } + } + + FOREACH_DEVICE_TAG(device, tag) { + k = device_tag(device, tag, add); + if (r >= 0 && k < 0) + r = k; + } + + return r; +} + +static bool device_has_info(sd_device *device) { + assert(device); + + if (!set_isempty(device->devlinks)) + return true; + + if (device->devlink_priority != 0) + return true; + + if (!ordered_hashmap_isempty(device->properties_db)) + return true; + + if (!set_isempty(device->tags)) + return true; + + if (device->watch_handle >= 0) + return true; + + return false; +} + +void device_set_db_persist(sd_device *device) { + assert(device); + + device->db_persist = true; +} + +int device_update_db(sd_device *device) { + const char *id; + char *path; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *path_tmp = NULL; + bool has_info; + int r; + + assert(device); + + has_info = device_has_info(device); + + r = device_get_id_filename(device, &id); + if (r < 0) + return r; + + path = strjoina("/run/udev/data/", id); + + /* do not store anything for otherwise empty devices */ + if (!has_info && major(device->devnum) == 0 && device->ifindex == 0) { + r = unlink(path); + if (r < 0 && errno != ENOENT) + return -errno; + + return 0; + } + + /* write a database file */ + r = mkdir_parents(path, 0755); + if (r < 0) + return r; + + r = fopen_temporary(path, &f, &path_tmp); + if (r < 0) + return r; + + /* + * set 'sticky' bit to indicate that we should not clean the + * database when we transition from initramfs to the real root + */ + if (device->db_persist) { + r = fchmod(fileno(f), 01644); + if (r < 0) { + r = -errno; + goto fail; + } + } else { + r = fchmod(fileno(f), 0644); + if (r < 0) { + r = -errno; + goto fail; + } + } + + if (has_info) { + const char *property, *value, *tag; + Iterator i; + + if (major(device->devnum) > 0) { + const char *devlink; + + FOREACH_DEVICE_DEVLINK(device, devlink) + fprintf(f, "S:%s\n", devlink + STRLEN("/dev/")); + + if (device->devlink_priority != 0) + fprintf(f, "L:%i\n", device->devlink_priority); + + if (device->watch_handle >= 0) + fprintf(f, "W:%i\n", device->watch_handle); + } + + if (device->usec_initialized > 0) + fprintf(f, "I:"USEC_FMT"\n", device->usec_initialized); + + ORDERED_HASHMAP_FOREACH_KEY(value, property, device->properties_db, i) + fprintf(f, "E:%s=%s\n", property, value); + + FOREACH_DEVICE_TAG(device, tag) + fprintf(f, "G:%s\n", tag); + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + r = rename(path_tmp, path); + if (r < 0) { + r = -errno; + goto fail; + } + + log_device_debug(device, "sd-device: Created %s file '%s' for '%s'", has_info ? "db" : "empty", + path, device->devpath); + + return 0; + +fail: + (void) unlink(path); + (void) unlink(path_tmp); + + return log_device_debug_errno(device, r, "sd-device: Failed to create %s file '%s' for '%s'", has_info ? "db" : "empty", path, device->devpath); +} + +int device_delete_db(sd_device *device) { + const char *id; + char *path; + int r; + + assert(device); + + r = device_get_id_filename(device, &id); + if (r < 0) + return r; + + path = strjoina("/run/udev/data/", id); + + r = unlink(path); + if (r < 0 && errno != ENOENT) + return -errno; + + return 0; +} + +static const char* const device_action_table[_DEVICE_ACTION_MAX] = { + [DEVICE_ACTION_ADD] = "add", + [DEVICE_ACTION_REMOVE] = "remove", + [DEVICE_ACTION_CHANGE] = "change", + [DEVICE_ACTION_MOVE] = "move", + [DEVICE_ACTION_ONLINE] = "online", + [DEVICE_ACTION_OFFLINE] = "offline", + [DEVICE_ACTION_BIND] = "bind", + [DEVICE_ACTION_UNBIND] = "unbind", +}; + +DEFINE_STRING_TABLE_LOOKUP(device_action, DeviceAction); + +void dump_device_action_table(void) { + DUMP_STRING_TABLE(device_action, DeviceAction, _DEVICE_ACTION_MAX); +} diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h new file mode 100644 index 00000000..2bde53e9 --- /dev/null +++ b/src/libsystemd/sd-device/device-private.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "sd-device.h" + +#include "macro.h" + +typedef enum DeviceAction { + DEVICE_ACTION_ADD, + DEVICE_ACTION_REMOVE, + DEVICE_ACTION_CHANGE, + DEVICE_ACTION_MOVE, + DEVICE_ACTION_ONLINE, + DEVICE_ACTION_OFFLINE, + DEVICE_ACTION_BIND, + DEVICE_ACTION_UNBIND, + _DEVICE_ACTION_MAX, + _DEVICE_ACTION_INVALID = -1, +} DeviceAction; + +int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len); +int device_new_from_strv(sd_device **ret, char **strv); +int device_new_from_stat_rdev(sd_device **ret, const struct stat *st); + +int device_get_id_filename(sd_device *device, const char **ret); + +int device_get_devlink_priority(sd_device *device, int *priority); +int device_get_watch_handle(sd_device *device, int *handle); +int device_get_devnode_mode(sd_device *device, mode_t *mode); +int device_get_devnode_uid(sd_device *device, uid_t *uid); +int device_get_devnode_gid(sd_device *device, gid_t *gid); +int device_get_action(sd_device *device, DeviceAction *action); +int device_get_seqnum(sd_device *device, uint64_t *seqnum); + +void device_seal(sd_device *device); +void device_set_is_initialized(sd_device *device); +void device_set_watch_handle(sd_device *device, int fd); +void device_set_db_persist(sd_device *device); +void device_set_devlink_priority(sd_device *device, int priority); +int device_ensure_usec_initialized(sd_device *device, sd_device *device_old); +int device_add_devlink(sd_device *device, const char *devlink); +int device_add_property(sd_device *device, const char *property, const char *value); +int device_add_tag(sd_device *device, const char *tag); +void device_remove_tag(sd_device *device, const char *tag); +void device_cleanup_tags(sd_device *device); +void device_cleanup_devlinks(sd_device *device); + +uint64_t device_get_properties_generation(sd_device *device); +uint64_t device_get_tags_generation(sd_device *device); +uint64_t device_get_devlinks_generation(sd_device *device); + +int device_properties_prepare(sd_device *device); +int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len); +int device_get_properties_strv(sd_device *device, char ***strv); + +int device_rename(sd_device *device, const char *name); +int device_shallow_clone(sd_device *old_device, sd_device **new_device); +int device_clone_with_db(sd_device *old_device, sd_device **new_device); +int device_copy_properties(sd_device *device_dst, sd_device *device_src); +int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action); + +int device_tag_index(sd_device *dev, sd_device *dev_old, bool add); +int device_update_db(sd_device *device); +int device_delete_db(sd_device *device); +int device_read_db_internal_filename(sd_device *device, const char *filename); /* For fuzzer */ +int device_read_db_internal(sd_device *device, bool force); +static inline int device_read_db(sd_device *device) { + return device_read_db_internal(device, false); +} + +DeviceAction device_action_from_string(const char *s) _pure_; +const char *device_action_to_string(DeviceAction a) _const_; +void dump_device_action_table(void); diff --git a/src/libsystemd/sd-device/device-util.h b/src/libsystemd/sd-device/device-util.h new file mode 100644 index 00000000..a25682d8 --- /dev/null +++ b/src/libsystemd/sd-device/device-util.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#define FOREACH_DEVICE_PROPERTY(device, key, value) \ + for (key = sd_device_get_property_first(device, &(value)); \ + key; \ + key = sd_device_get_property_next(device, &(value))) + +#define FOREACH_DEVICE_TAG(device, tag) \ + for (tag = sd_device_get_tag_first(device); \ + tag; \ + tag = sd_device_get_tag_next(device)) + +#define FOREACH_DEVICE_SYSATTR(device, attr) \ + for (attr = sd_device_get_sysattr_first(device); \ + attr; \ + attr = sd_device_get_sysattr_next(device)) + +#define FOREACH_DEVICE_DEVLINK(device, devlink) \ + for (devlink = sd_device_get_devlink_first(device); \ + devlink; \ + devlink = sd_device_get_devlink_next(device)) + +#define FOREACH_DEVICE(enumerator, device) \ + for (device = sd_device_enumerator_get_device_first(enumerator); \ + device; \ + device = sd_device_enumerator_get_device_next(enumerator)) + +#define FOREACH_SUBSYSTEM(enumerator, device) \ + for (device = sd_device_enumerator_get_subsystem_first(enumerator); \ + device; \ + device = sd_device_enumerator_get_subsystem_next(enumerator)) + +#define log_device_full(device, level, error, ...) \ + ({ \ + const char *_sysname = NULL; \ + sd_device *_d = (device); \ + int _level = (level), _error = (error); \ + \ + if (_d && _unlikely_(log_get_max_level() >= _level)) \ + (void) sd_device_get_sysname(_d, &_sysname); \ + log_object_internal(_level, _error, PROJECT_FILE, __LINE__, __func__, \ + _sysname ? "DEVICE=" : NULL, _sysname, \ + NULL, NULL, ##__VA_ARGS__); \ + }) + +#define log_device_debug(device, ...) log_device_full(device, LOG_DEBUG, 0, ##__VA_ARGS__) +#define log_device_info(device, ...) log_device_full(device, LOG_INFO, 0, ##__VA_ARGS__) +#define log_device_notice(device, ...) log_device_full(device, LOG_NOTICE, 0, ##__VA_ARGS__) +#define log_device_warning(device, ...) log_device_full(device, LOG_WARNING, 0, ##__VA_ARGS__) +#define log_device_error(device, ...) log_device_full(device, LOG_ERR, 0, ##__VA_ARGS__) + +#define log_device_debug_errno(device, error, ...) log_device_full(device, LOG_DEBUG, error, ##__VA_ARGS__) +#define log_device_info_errno(device, error, ...) log_device_full(device, LOG_INFO, error, ##__VA_ARGS__) +#define log_device_notice_errno(device, error, ...) log_device_full(device, LOG_NOTICE, error, ##__VA_ARGS__) +#define log_device_warning_errno(device, error, ...) log_device_full(device, LOG_WARNING, error, ##__VA_ARGS__) +#define log_device_error_errno(device, error, ...) log_device_full(device, LOG_ERR, error, ##__VA_ARGS__) diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c new file mode 100644 index 00000000..f35612fe --- /dev/null +++ b/src/libsystemd/sd-device/sd-device.c @@ -0,0 +1,1877 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-device.h" + +#include "alloc-util.h" +#include "device-internal.h" +#include "device-private.h" +#include "device-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hashmap.h" +#include "macro.h" +#include "parse-util.h" +#include "path-util.h" +#include "set.h" +#include "socket-util.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "strxcpyx.h" +#include "util.h" + +int device_new_aux(sd_device **ret) { + sd_device *device; + + assert(ret); + + device = new(sd_device, 1); + if (!device) + return -ENOMEM; + + *device = (sd_device) { + .n_ref = 1, + .watch_handle = -1, + .devmode = (mode_t) -1, + .devuid = (uid_t) -1, + .devgid = (gid_t) -1, + .action = _DEVICE_ACTION_INVALID, + }; + + *ret = device; + return 0; +} + +static sd_device *device_free(sd_device *device) { + assert(device); + + sd_device_unref(device->parent); + free(device->syspath); + free(device->sysname); + free(device->devtype); + free(device->devname); + free(device->subsystem); + free(device->driver_subsystem); + free(device->driver); + free(device->id_filename); + free(device->properties_strv); + free(device->properties_nulstr); + + ordered_hashmap_free_free_free(device->properties); + ordered_hashmap_free_free_free(device->properties_db); + hashmap_free_free_free(device->sysattr_values); + set_free_free(device->sysattrs); + set_free_free(device->tags); + set_free_free(device->devlinks); + + return mfree(device); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device, sd_device, device_free); + +int device_add_property_aux(sd_device *device, const char *_key, const char *_value, bool db) { + OrderedHashmap **properties; + + assert(device); + assert(_key); + + if (db) + properties = &device->properties_db; + else + properties = &device->properties; + + if (_value) { + _cleanup_free_ char *key = NULL, *value = NULL, *old_key = NULL, *old_value = NULL; + int r; + + r = ordered_hashmap_ensure_allocated(properties, &string_hash_ops); + if (r < 0) + return r; + + key = strdup(_key); + if (!key) + return -ENOMEM; + + value = strdup(_value); + if (!value) + return -ENOMEM; + + old_value = ordered_hashmap_get2(*properties, key, (void**) &old_key); + + r = ordered_hashmap_replace(*properties, key, value); + if (r < 0) + return r; + + key = NULL; + value = NULL; + } else { + _cleanup_free_ char *key = NULL; + _cleanup_free_ char *value = NULL; + + value = ordered_hashmap_remove2(*properties, _key, (void**) &key); + } + + if (!db) { + device->properties_generation++; + device->properties_buf_outdated = true; + } + + return 0; +} + +int device_add_property_internal(sd_device *device, const char *key, const char *value) { + return device_add_property_aux(device, key, value, false); +} + +int device_set_syspath(sd_device *device, const char *_syspath, bool verify) { + _cleanup_free_ char *syspath = NULL; + const char *devpath; + int r; + + assert(device); + assert(_syspath); + + /* must be a subdirectory of /sys */ + if (!path_startswith(_syspath, "/sys/")) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "sd-device: Syspath '%s' is not a subdirectory of /sys", + _syspath); + + if (verify) { + r = chase_symlinks(_syspath, NULL, 0, &syspath, NULL); + if (r == -ENOENT) + return -ENODEV; /* the device does not exist (any more?) */ + if (r < 0) + return log_debug_errno(r, "sd-device: Failed to get target of '%s': %m", _syspath); + + if (!path_startswith(syspath, "/sys")) { + _cleanup_free_ char *real_sys = NULL, *new_syspath = NULL; + char *p; + + /* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */ + r = chase_symlinks("/sys", NULL, 0, &real_sys, NULL); + if (r < 0) + return log_debug_errno(r, "sd-device: Failed to chase symlink /sys: %m"); + + p = path_startswith(syspath, real_sys); + if (!p) + return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), + "sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'", + syspath, real_sys); + + new_syspath = path_join("/sys", p); + if (!new_syspath) + return -ENOMEM; + + free_and_replace(syspath, new_syspath); + path_simplify(syspath, false); + } + + if (path_startswith(syspath, "/sys/devices/")) { + char *path; + + /* all 'devices' require an 'uevent' file */ + path = strjoina(syspath, "/uevent"); + r = access(path, F_OK); + if (r < 0) { + if (errno == ENOENT) + /* this is not a valid device */ + return -ENODEV; + + return log_debug_errno(errno, "sd-device: %s does not have an uevent file: %m", syspath); + } + } else { + /* everything else just needs to be a directory */ + if (!is_dir(syspath, false)) + return -ENODEV; + } + } else { + syspath = strdup(_syspath); + if (!syspath) + return -ENOMEM; + } + + devpath = syspath + STRLEN("/sys"); + + if (devpath[0] == '\0') + /* '/sys' alone is not a valid device path */ + return -ENODEV; + + r = device_add_property_internal(device, "DEVPATH", devpath); + if (r < 0) + return r; + + free_and_replace(device->syspath, syspath); + device->devpath = devpath; + return 0; +} + +_public_ int sd_device_new_from_syspath(sd_device **ret, const char *syspath) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + int r; + + assert_return(ret, -EINVAL); + assert_return(syspath, -EINVAL); + + r = device_new_aux(&device); + if (r < 0) + return r; + + r = device_set_syspath(device, syspath, true); + if (r < 0) + return r; + + *ret = TAKE_PTR(device); + return 0; +} + +_public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum) { + char *syspath; + char id[DECIMAL_STR_MAX(unsigned) * 2 + 1]; + + assert_return(ret, -EINVAL); + assert_return(IN_SET(type, 'b', 'c'), -EINVAL); + + /* use /sys/dev/{block,char}/: link */ + xsprintf(id, "%u:%u", major(devnum), minor(devnum)); + + syspath = strjoina("/sys/dev/", (type == 'b' ? "block" : "char"), "/", id); + + return sd_device_new_from_syspath(ret, syspath); +} + +_public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname) { + char *name, *syspath; + size_t len = 0; + + assert_return(ret, -EINVAL); + assert_return(subsystem, -EINVAL); + assert_return(sysname, -EINVAL); + + if (streq(subsystem, "subsystem")) { + syspath = strjoina("/sys/subsystem/", sysname); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); + + syspath = strjoina("/sys/bus/", sysname); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); + + syspath = strjoina("/sys/class/", sysname); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); + } else if (streq(subsystem, "module")) { + syspath = strjoina("/sys/module/", sysname); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); + } else if (streq(subsystem, "drivers")) { + char subsys[PATH_MAX]; + char *driver; + + strscpy(subsys, sizeof(subsys), sysname); + driver = strchr(subsys, ':'); + if (driver) { + driver[0] = '\0'; + driver++; + + syspath = strjoina("/sys/subsystem/", subsys, "/drivers/", driver); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); + + syspath = strjoina("/sys/bus/", subsys, "/drivers/", driver); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); + } + } + + /* translate sysname back to sysfs filename */ + name = strdupa(sysname); + while (name[len] != '\0') { + if (name[len] == '/') + name[len] = '!'; + + len++; + } + + syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", name); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); + + syspath = strjoina("/sys/bus/", subsystem, "/devices/", name); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); + + syspath = strjoina("/sys/class/", subsystem, "/", name); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); + + syspath = strjoina("/sys/firmware/", subsystem, "/", sysname); + if (access(syspath, F_OK) >= 0) + return sd_device_new_from_syspath(ret, syspath); + + return -ENODEV; +} + +int device_set_devtype(sd_device *device, const char *_devtype) { + _cleanup_free_ char *devtype = NULL; + int r; + + assert(device); + assert(_devtype); + + devtype = strdup(_devtype); + if (!devtype) + return -ENOMEM; + + r = device_add_property_internal(device, "DEVTYPE", devtype); + if (r < 0) + return r; + + free_and_replace(device->devtype, devtype); + + return 0; +} + +int device_set_ifindex(sd_device *device, const char *_ifindex) { + int ifindex, r; + + assert(device); + assert(_ifindex); + + r = parse_ifindex(_ifindex, &ifindex); + if (r < 0) + return r; + + r = device_add_property_internal(device, "IFINDEX", _ifindex); + if (r < 0) + return r; + + device->ifindex = ifindex; + + return 0; +} + +int device_set_devname(sd_device *device, const char *_devname) { + _cleanup_free_ char *devname = NULL; + int r; + + assert(device); + assert(_devname); + + if (_devname[0] != '/') { + r = asprintf(&devname, "/dev/%s", _devname); + if (r < 0) + return -ENOMEM; + } else { + devname = strdup(_devname); + if (!devname) + return -ENOMEM; + } + + r = device_add_property_internal(device, "DEVNAME", devname); + if (r < 0) + return r; + + free_and_replace(device->devname, devname); + + return 0; +} + +int device_set_devmode(sd_device *device, const char *_devmode) { + unsigned devmode; + int r; + + assert(device); + assert(_devmode); + + r = safe_atou(_devmode, &devmode); + if (r < 0) + return r; + + if (devmode > 07777) + return -EINVAL; + + r = device_add_property_internal(device, "DEVMODE", _devmode); + if (r < 0) + return r; + + device->devmode = devmode; + + return 0; +} + +int device_set_devnum(sd_device *device, const char *major, const char *minor) { + unsigned maj = 0, min = 0; + int r; + + assert(device); + assert(major); + + r = safe_atou(major, &maj); + if (r < 0) + return r; + if (!maj) + return 0; + + if (minor) { + r = safe_atou(minor, &min); + if (r < 0) + return r; + } + + r = device_add_property_internal(device, "MAJOR", major); + if (r < 0) + return r; + + if (minor) { + r = device_add_property_internal(device, "MINOR", minor); + if (r < 0) + return r; + } + + device->devnum = makedev(maj, min); + + return 0; +} + +static int handle_uevent_line(sd_device *device, const char *key, const char *value, const char **major, const char **minor) { + int r; + + assert(device); + assert(key); + assert(value); + assert(major); + assert(minor); + + if (streq(key, "DEVTYPE")) { + r = device_set_devtype(device, value); + if (r < 0) + return r; + } else if (streq(key, "IFINDEX")) { + r = device_set_ifindex(device, value); + if (r < 0) + return r; + } else if (streq(key, "DEVNAME")) { + r = device_set_devname(device, value); + if (r < 0) + return r; + } else if (streq(key, "DEVMODE")) { + r = device_set_devmode(device, value); + if (r < 0) + return r; + } else if (streq(key, "MAJOR")) + *major = value; + else if (streq(key, "MINOR")) + *minor = value; + else { + r = device_add_property_internal(device, key, value); + if (r < 0) + return r; + } + + return 0; +} + +int device_read_uevent_file(sd_device *device) { + _cleanup_free_ char *uevent = NULL; + const char *syspath, *key = NULL, *value = NULL, *major = NULL, *minor = NULL; + char *path; + size_t uevent_len; + unsigned i; + int r; + + enum { + PRE_KEY, + KEY, + PRE_VALUE, + VALUE, + INVALID_LINE, + } state = PRE_KEY; + + assert(device); + + if (device->uevent_loaded || device->sealed) + return 0; + + r = sd_device_get_syspath(device, &syspath); + if (r < 0) + return r; + + path = strjoina(syspath, "/uevent"); + + r = read_full_file(path, &uevent, &uevent_len); + if (r == -EACCES) { + /* empty uevent files may be write-only */ + device->uevent_loaded = true; + return 0; + } + if (r == -ENOENT) + /* some devices may not have uevent files, see set_syspath() */ + return 0; + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to read uevent file '%s': %m", path); + + device->uevent_loaded = true; + + for (i = 0; i < uevent_len; i++) + switch (state) { + case PRE_KEY: + if (!strchr(NEWLINE, uevent[i])) { + key = &uevent[i]; + + state = KEY; + } + + break; + case KEY: + if (uevent[i] == '=') { + uevent[i] = '\0'; + + state = PRE_VALUE; + } else if (strchr(NEWLINE, uevent[i])) { + uevent[i] = '\0'; + log_device_debug(device, "sd-device: Invalid uevent line '%s', ignoring", key); + + state = PRE_KEY; + } + + break; + case PRE_VALUE: + value = &uevent[i]; + state = VALUE; + + _fallthrough_; /* to handle empty property */ + case VALUE: + if (strchr(NEWLINE, uevent[i])) { + uevent[i] = '\0'; + + r = handle_uevent_line(device, key, value, &major, &minor); + if (r < 0) + log_device_debug_errno(device, r, "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m", key, value); + + state = PRE_KEY; + } + + break; + default: + assert_not_reached("Invalid state when parsing uevent file"); + } + + if (major) { + r = device_set_devnum(device, major, minor); + if (r < 0) + log_device_debug_errno(device, r, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major, minor, path); + } + + return 0; +} + +_public_ int sd_device_get_ifindex(sd_device *device, int *ifindex) { + int r; + + assert_return(device, -EINVAL); + + r = device_read_uevent_file(device); + if (r < 0) + return r; + + if (device->ifindex <= 0) + return -ENOENT; + + if (ifindex) + *ifindex = device->ifindex; + + return 0; +} + +_public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) { + int r; + + assert_return(ret, -EINVAL); + assert_return(id, -EINVAL); + + switch (id[0]) { + case 'b': + case 'c': { + dev_t devt; + + if (isempty(id)) + return -EINVAL; + + r = parse_dev(id + 1, &devt); + if (r < 0) + return r; + + return sd_device_new_from_devnum(ret, id[0], devt); + } + + case 'n': { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + _cleanup_close_ int sk = -1; + struct ifreq ifr = {}; + int ifindex; + + r = parse_ifindex(&id[1], &ifr.ifr_ifindex); + if (r < 0) + return r; + + sk = socket_ioctl_fd(); + if (sk < 0) + return sk; + + r = ioctl(sk, SIOCGIFNAME, &ifr); + if (r < 0) + return -errno; + + r = sd_device_new_from_subsystem_sysname(&device, "net", ifr.ifr_name); + if (r < 0) + return r; + + r = sd_device_get_ifindex(device, &ifindex); + if (r < 0) + return r; + + /* this is racey, so we might end up with the wrong device */ + if (ifr.ifr_ifindex != ifindex) + return -ENODEV; + + *ret = TAKE_PTR(device); + return 0; + } + + case '+': { + char subsys[PATH_MAX]; + char *sysname; + + (void) strscpy(subsys, sizeof(subsys), id + 1); + sysname = strchr(subsys, ':'); + if (!sysname) + return -EINVAL; + + sysname[0] = '\0'; + sysname++; + + return sd_device_new_from_subsystem_sysname(ret, subsys, sysname); + } + + default: + return -EINVAL; + } +} + +_public_ int sd_device_get_syspath(sd_device *device, const char **ret) { + assert_return(device, -EINVAL); + assert_return(ret, -EINVAL); + + assert(path_startswith(device->syspath, "/sys/")); + + *ret = device->syspath; + + return 0; +} + +static int device_new_from_child(sd_device **ret, sd_device *child) { + _cleanup_free_ char *path = NULL; + const char *subdir, *syspath; + int r; + + assert(ret); + assert(child); + + r = sd_device_get_syspath(child, &syspath); + if (r < 0) + return r; + + path = strdup(syspath); + if (!path) + return -ENOMEM; + subdir = path + STRLEN("/sys"); + + for (;;) { + char *pos; + + pos = strrchr(subdir, '/'); + if (!pos || pos < subdir + 2) + break; + + *pos = '\0'; + + r = sd_device_new_from_syspath(ret, path); + if (r < 0) + continue; + + return 0; + } + + return -ENODEV; +} + +_public_ int sd_device_get_parent(sd_device *child, sd_device **ret) { + + assert_return(ret, -EINVAL); + assert_return(child, -EINVAL); + + if (!child->parent_set) { + child->parent_set = true; + + (void) device_new_from_child(&child->parent, child); + } + + if (!child->parent) + return -ENOENT; + + *ret = child->parent; + return 0; +} + +int device_set_subsystem(sd_device *device, const char *_subsystem) { + _cleanup_free_ char *subsystem = NULL; + int r; + + assert(device); + assert(_subsystem); + + subsystem = strdup(_subsystem); + if (!subsystem) + return -ENOMEM; + + r = device_add_property_internal(device, "SUBSYSTEM", subsystem); + if (r < 0) + return r; + + device->subsystem_set = true; + return free_and_replace(device->subsystem, subsystem); +} + +static int device_set_drivers_subsystem(sd_device *device, const char *_subsystem) { + _cleanup_free_ char *subsystem = NULL; + int r; + + assert(device); + assert(_subsystem); + assert(*_subsystem); + + subsystem = strdup(_subsystem); + if (!subsystem) + return -ENOMEM; + + r = device_set_subsystem(device, "drivers"); + if (r < 0) + return r; + + return free_and_replace(device->driver_subsystem, subsystem); +} + +_public_ int sd_device_get_subsystem(sd_device *device, const char **ret) { + const char *syspath, *drivers = NULL; + int r; + + assert_return(ret, -EINVAL); + assert_return(device, -EINVAL); + + r = sd_device_get_syspath(device, &syspath); + if (r < 0) + return r; + + if (!device->subsystem_set) { + _cleanup_free_ char *subsystem = NULL; + char *path; + + /* read 'subsystem' link */ + path = strjoina(syspath, "/subsystem"); + r = readlink_value(path, &subsystem); + if (r >= 0) + r = device_set_subsystem(device, subsystem); + /* use implicit names */ + else if (path_startswith(device->devpath, "/module/")) + r = device_set_subsystem(device, "module"); + else if (!(drivers = strstr(syspath, "/drivers/")) && + PATH_STARTSWITH_SET(device->devpath, "/subsystem/", + "/class/", + "/bus/")) + r = device_set_subsystem(device, "subsystem"); + if (r < 0 && r != -ENOENT) + return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for %s: %m", device->devpath); + + device->subsystem_set = true; + } else if (!device->driver_subsystem_set) + drivers = strstr(syspath, "/drivers/"); + + if (!device->driver_subsystem_set) { + if (drivers) { + _cleanup_free_ char *subpath = NULL; + + subpath = strndup(syspath, drivers - syspath); + if (!subpath) + r = -ENOMEM; + else { + const char *subsys; + + subsys = strrchr(subpath, '/'); + if (!subsys) + r = -EINVAL; + else + r = device_set_drivers_subsystem(device, subsys + 1); + } + if (r < 0 && r != -ENOENT) + return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem for driver %s: %m", device->devpath); + } + + device->driver_subsystem_set = true; + } + + if (!device->subsystem) + return -ENOENT; + + *ret = device->subsystem; + return 0; +} + +_public_ int sd_device_get_devtype(sd_device *device, const char **devtype) { + int r; + + assert_return(device, -EINVAL); + + r = device_read_uevent_file(device); + if (r < 0) + return r; + + if (!device->devtype) + return -ENOENT; + + if (devtype) + *devtype = device->devtype; + + return !!device->devtype; +} + +_public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret) { + sd_device *parent = NULL; + int r; + + assert_return(child, -EINVAL); + assert_return(subsystem, -EINVAL); + + r = sd_device_get_parent(child, &parent); + while (r >= 0) { + const char *parent_subsystem = NULL; + const char *parent_devtype = NULL; + + (void) sd_device_get_subsystem(parent, &parent_subsystem); + if (streq_ptr(parent_subsystem, subsystem)) { + if (!devtype) + break; + + (void) sd_device_get_devtype(parent, &parent_devtype); + if (streq_ptr(parent_devtype, devtype)) + break; + } + r = sd_device_get_parent(parent, &parent); + } + + if (r < 0) + return r; + + *ret = parent; + return 0; +} + +_public_ int sd_device_get_devnum(sd_device *device, dev_t *devnum) { + int r; + + assert_return(device, -EINVAL); + + r = device_read_uevent_file(device); + if (r < 0) + return r; + + if (major(device->devnum) <= 0) + return -ENOENT; + + if (devnum) + *devnum = device->devnum; + + return 0; +} + +int device_set_driver(sd_device *device, const char *_driver) { + _cleanup_free_ char *driver = NULL; + int r; + + assert(device); + assert(_driver); + + driver = strdup(_driver); + if (!driver) + return -ENOMEM; + + r = device_add_property_internal(device, "DRIVER", driver); + if (r < 0) + return r; + + device->driver_set = true; + return free_and_replace(device->driver, driver); +} + +_public_ int sd_device_get_driver(sd_device *device, const char **ret) { + assert_return(device, -EINVAL); + assert_return(ret, -EINVAL); + + if (!device->driver_set) { + _cleanup_free_ char *driver = NULL; + const char *syspath; + char *path; + int r; + + r = sd_device_get_syspath(device, &syspath); + if (r < 0) + return r; + + path = strjoina(syspath, "/driver"); + r = readlink_value(path, &driver); + if (r >= 0) { + r = device_set_driver(device, driver); + if (r < 0) + return log_device_debug_errno(device, r, "sd-device: Failed to set driver for %s: %m", device->devpath); + } else if (r == -ENOENT) + device->driver_set = true; + else + return log_device_debug_errno(device, r, "sd-device: Failed to set driver for %s: %m", device->devpath); + } + + if (!device->driver) + return -ENOENT; + + *ret = device->driver; + return 0; +} + +_public_ int sd_device_get_devpath(sd_device *device, const char **devpath) { + assert_return(device, -EINVAL); + assert_return(devpath, -EINVAL); + + assert(device->devpath); + assert(device->devpath[0] == '/'); + + *devpath = device->devpath; + return 0; +} + +_public_ int sd_device_get_devname(sd_device *device, const char **devname) { + int r; + + assert_return(device, -EINVAL); + assert_return(devname, -EINVAL); + + r = device_read_uevent_file(device); + if (r < 0) + return r; + + if (!device->devname) + return -ENOENT; + + assert(path_startswith(device->devname, "/dev/")); + + *devname = device->devname; + return 0; +} + +static int device_set_sysname(sd_device *device) { + _cleanup_free_ char *sysname = NULL; + const char *sysnum = NULL; + const char *pos; + size_t len = 0; + + if (!device->devpath) + return -EINVAL; + + pos = strrchr(device->devpath, '/'); + if (!pos) + return -EINVAL; + pos++; + + /* devpath is not a root directory */ + if (*pos == '\0' || pos <= device->devpath) + return -EINVAL; + + sysname = strdup(pos); + if (!sysname) + return -ENOMEM; + + /* some devices have '!' in their name, change that to '/' */ + while (sysname[len] != '\0') { + if (sysname[len] == '!') + sysname[len] = '/'; + + len++; + } + + /* trailing number */ + while (len > 0 && isdigit(sysname[--len])) + sysnum = &sysname[len]; + + if (len == 0) + sysnum = NULL; + + device->sysname_set = true; + device->sysnum = sysnum; + return free_and_replace(device->sysname, sysname); +} + +_public_ int sd_device_get_sysname(sd_device *device, const char **ret) { + int r; + + assert_return(device, -EINVAL); + assert_return(ret, -EINVAL); + + if (!device->sysname_set) { + r = device_set_sysname(device); + if (r < 0) + return r; + } + + assert_return(device->sysname, -ENOENT); + + *ret = device->sysname; + return 0; +} + +_public_ int sd_device_get_sysnum(sd_device *device, const char **ret) { + int r; + + assert_return(device, -EINVAL); + assert_return(ret, -EINVAL); + + if (!device->sysname_set) { + r = device_set_sysname(device); + if (r < 0) + return r; + } + + if (!device->sysnum) + return -ENOENT; + + *ret = device->sysnum; + return 0; +} + +static bool is_valid_tag(const char *tag) { + assert(tag); + + return !strchr(tag, ':') && !strchr(tag, ' '); +} + +int device_add_tag(sd_device *device, const char *tag) { + int r; + + assert(device); + assert(tag); + + if (!is_valid_tag(tag)) + return -EINVAL; + + r = set_ensure_allocated(&device->tags, &string_hash_ops); + if (r < 0) + return r; + + r = set_put_strdup(device->tags, tag); + if (r < 0) + return r; + + device->tags_generation++; + device->property_tags_outdated = true; + + return 0; +} + +int device_add_devlink(sd_device *device, const char *devlink) { + int r; + + assert(device); + assert(devlink); + + r = set_ensure_allocated(&device->devlinks, &string_hash_ops); + if (r < 0) + return r; + + r = set_put_strdup(device->devlinks, devlink); + if (r < 0) + return r; + + device->devlinks_generation++; + device->property_devlinks_outdated = true; + + return 0; +} + +static int device_add_property_internal_from_string(sd_device *device, const char *str) { + _cleanup_free_ char *key = NULL; + char *value; + int r; + + assert(device); + assert(str); + + key = strdup(str); + if (!key) + return -ENOMEM; + + value = strchr(key, '='); + if (!value) + return -EINVAL; + + *value = '\0'; + + if (isempty(++value)) + value = NULL; + + /* Add the property to both sd_device::properties and sd_device::properties_db, + * as this is called by only handle_db_line(). */ + r = device_add_property_aux(device, key, value, false); + if (r < 0) + return r; + + return device_add_property_aux(device, key, value, true); +} + +int device_set_usec_initialized(sd_device *device, usec_t when) { + char s[DECIMAL_STR_MAX(usec_t)]; + int r; + + assert(device); + + xsprintf(s, USEC_FMT, when); + + r = device_add_property_internal(device, "USEC_INITIALIZED", s); + if (r < 0) + return r; + + device->usec_initialized = when; + return 0; +} + +static int handle_db_line(sd_device *device, char key, const char *value) { + char *path; + int r; + + assert(device); + assert(value); + + switch (key) { + case 'G': + r = device_add_tag(device, value); + if (r < 0) + return r; + + break; + case 'S': + path = strjoina("/dev/", value); + r = device_add_devlink(device, path); + if (r < 0) + return r; + + break; + case 'E': + r = device_add_property_internal_from_string(device, value); + if (r < 0) + return r; + + break; + case 'I': { + usec_t t; + + r = safe_atou64(value, &t); + if (r < 0) + return r; + + r = device_set_usec_initialized(device, t); + if (r < 0) + return r; + + break; + } + case 'L': + r = safe_atoi(value, &device->devlink_priority); + if (r < 0) + return r; + + break; + case 'W': + r = safe_atoi(value, &device->watch_handle); + if (r < 0) + return r; + + break; + default: + log_device_debug(device, "sd-device: Unknown key '%c' in device db, ignoring", key); + } + + return 0; +} + +int device_get_id_filename(sd_device *device, const char **ret) { + assert(device); + assert(ret); + + if (!device->id_filename) { + _cleanup_free_ char *id = NULL; + const char *subsystem; + dev_t devnum; + int ifindex, r; + + r = sd_device_get_subsystem(device, &subsystem); + if (r < 0) + return r; + + if (sd_device_get_devnum(device, &devnum) >= 0) { + assert(subsystem); + + /* use dev_t — b259:131072, c254:0 */ + r = asprintf(&id, "%c%u:%u", + streq(subsystem, "block") ? 'b' : 'c', + major(devnum), minor(devnum)); + if (r < 0) + return -ENOMEM; + } else if (sd_device_get_ifindex(device, &ifindex) >= 0) { + /* use netdev ifindex — n3 */ + r = asprintf(&id, "n%u", (unsigned) ifindex); + if (r < 0) + return -ENOMEM; + } else { + /* use $subsys:$sysname — pci:0000:00:1f.2 + * sysname() has '!' translated, get it from devpath + */ + const char *sysname; + + sysname = basename(device->devpath); + if (!sysname) + return -EINVAL; + + if (!subsystem) + return -EINVAL; + + if (streq(subsystem, "drivers")) { + /* the 'drivers' pseudo-subsystem is special, and needs the real subsystem + * encoded as well */ + r = asprintf(&id, "+drivers:%s:%s", device->driver_subsystem, sysname); + if (r < 0) + return -ENOMEM; + } else { + r = asprintf(&id, "+%s:%s", subsystem, sysname); + if (r < 0) + return -ENOMEM; + } + } + + device->id_filename = TAKE_PTR(id); + } + + *ret = device->id_filename; + return 0; +} + +int device_read_db_internal_filename(sd_device *device, const char *filename) { + _cleanup_free_ char *db = NULL; + const char *value; + size_t db_len, i; + char key; + int r; + + enum { + PRE_KEY, + KEY, + PRE_VALUE, + VALUE, + INVALID_LINE, + } state = PRE_KEY; + + assert(device); + assert(filename); + + r = read_full_file(filename, &db, &db_len); + if (r < 0) { + if (r == -ENOENT) + return 0; + + return log_device_debug_errno(device, r, "sd-device: Failed to read db '%s': %m", filename); + } + + /* devices with a database entry are initialized */ + device->is_initialized = true; + + device->db_loaded = true; + + for (i = 0; i < db_len; i++) { + switch (state) { + case PRE_KEY: + if (!strchr(NEWLINE, db[i])) { + key = db[i]; + + state = KEY; + } + + break; + case KEY: + if (db[i] != ':') { + log_device_debug(device, "sd-device: Invalid db entry with key '%c', ignoring", key); + + state = INVALID_LINE; + } else { + db[i] = '\0'; + + state = PRE_VALUE; + } + + break; + case PRE_VALUE: + value = &db[i]; + + state = VALUE; + + break; + case INVALID_LINE: + if (strchr(NEWLINE, db[i])) + state = PRE_KEY; + + break; + case VALUE: + if (strchr(NEWLINE, db[i])) { + db[i] = '\0'; + r = handle_db_line(device, key, value); + if (r < 0) + log_device_debug_errno(device, r, "sd-device: Failed to handle db entry '%c:%s', ignoring: %m", key, value); + + state = PRE_KEY; + } + + break; + default: + return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL), "sd-device: invalid db syntax."); + } + } + + return 0; +} + +int device_read_db_internal(sd_device *device, bool force) { + const char *id, *path; + int r; + + assert(device); + + if (device->db_loaded || (!force && device->sealed)) + return 0; + + r = device_get_id_filename(device, &id); + if (r < 0) + return r; + + path = strjoina("/run/udev/data/", id); + + return device_read_db_internal_filename(device, path); +} + +_public_ int sd_device_get_is_initialized(sd_device *device) { + int r; + + assert_return(device, -EINVAL); + + r = device_read_db(device); + if (r < 0) + return r; + + return device->is_initialized; +} + +_public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec) { + usec_t now_ts; + int r; + + assert_return(device, -EINVAL); + assert_return(usec, -EINVAL); + + r = device_read_db(device); + if (r < 0) + return r; + + if (!device->is_initialized) + return -EBUSY; + + if (!device->usec_initialized) + return -ENODATA; + + now_ts = now(clock_boottime_or_monotonic()); + + if (now_ts < device->usec_initialized) + return -EIO; + + *usec = now_ts - device->usec_initialized; + return 0; +} + +_public_ const char *sd_device_get_tag_first(sd_device *device) { + void *v; + + assert_return(device, NULL); + + (void) device_read_db(device); + + device->tags_iterator_generation = device->tags_generation; + device->tags_iterator = ITERATOR_FIRST; + + (void) set_iterate(device->tags, &device->tags_iterator, &v); + return v; +} + +_public_ const char *sd_device_get_tag_next(sd_device *device) { + void *v; + + assert_return(device, NULL); + + (void) device_read_db(device); + + if (device->tags_iterator_generation != device->tags_generation) + return NULL; + + (void) set_iterate(device->tags, &device->tags_iterator, &v); + return v; +} + +_public_ const char *sd_device_get_devlink_first(sd_device *device) { + void *v; + + assert_return(device, NULL); + + (void) device_read_db(device); + + device->devlinks_iterator_generation = device->devlinks_generation; + device->devlinks_iterator = ITERATOR_FIRST; + + (void) set_iterate(device->devlinks, &device->devlinks_iterator, &v); + return v; +} + +_public_ const char *sd_device_get_devlink_next(sd_device *device) { + void *v; + + assert_return(device, NULL); + + (void) device_read_db(device); + + if (device->devlinks_iterator_generation != device->devlinks_generation) + return NULL; + + (void) set_iterate(device->devlinks, &device->devlinks_iterator, &v); + return v; +} + +int device_properties_prepare(sd_device *device) { + int r; + + assert(device); + + r = device_read_uevent_file(device); + if (r < 0) + return r; + + r = device_read_db(device); + if (r < 0) + return r; + + if (device->property_devlinks_outdated) { + _cleanup_free_ char *devlinks = NULL; + size_t devlinks_allocated = 0, devlinks_len = 0; + const char *devlink; + + for (devlink = sd_device_get_devlink_first(device); devlink; devlink = sd_device_get_devlink_next(device)) { + char *e; + + if (!GREEDY_REALLOC(devlinks, devlinks_allocated, devlinks_len + strlen(devlink) + 2)) + return -ENOMEM; + if (devlinks_len > 0) + stpcpy(devlinks + devlinks_len++, " "); + e = stpcpy(devlinks + devlinks_len, devlink); + devlinks_len = e - devlinks; + } + + r = device_add_property_internal(device, "DEVLINKS", devlinks); + if (r < 0) + return r; + + device->property_devlinks_outdated = false; + } + + if (device->property_tags_outdated) { + _cleanup_free_ char *tags = NULL; + size_t tags_allocated = 0, tags_len = 0; + const char *tag; + + if (!GREEDY_REALLOC(tags, tags_allocated, 2)) + return -ENOMEM; + stpcpy(tags, ":"); + tags_len++; + + for (tag = sd_device_get_tag_first(device); tag; tag = sd_device_get_tag_next(device)) { + char *e; + + if (!GREEDY_REALLOC(tags, tags_allocated, tags_len + strlen(tag) + 2)) + return -ENOMEM; + e = stpcpy(stpcpy(tags + tags_len, tag), ":"); + tags_len = e - tags; + } + + r = device_add_property_internal(device, "TAGS", tags); + if (r < 0) + return r; + + device->property_tags_outdated = false; + } + + return 0; +} + +_public_ const char *sd_device_get_property_first(sd_device *device, const char **_value) { + const char *key; + int r; + + assert_return(device, NULL); + + r = device_properties_prepare(device); + if (r < 0) + return NULL; + + device->properties_iterator_generation = device->properties_generation; + device->properties_iterator = ITERATOR_FIRST; + + (void) ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)_value, (const void**)&key); + return key; +} + +_public_ const char *sd_device_get_property_next(sd_device *device, const char **_value) { + const char *key; + int r; + + assert_return(device, NULL); + + r = device_properties_prepare(device); + if (r < 0) + return NULL; + + if (device->properties_iterator_generation != device->properties_generation) + return NULL; + + (void) ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)_value, (const void**)&key); + return key; +} + +static int device_sysattrs_read_all(sd_device *device) { + _cleanup_closedir_ DIR *dir = NULL; + const char *syspath; + struct dirent *dent; + int r; + + assert(device); + + if (device->sysattrs_read) + return 0; + + r = sd_device_get_syspath(device, &syspath); + if (r < 0) + return r; + + dir = opendir(syspath); + if (!dir) + return -errno; + + r = set_ensure_allocated(&device->sysattrs, &string_hash_ops); + if (r < 0) + return r; + + FOREACH_DIRENT_ALL(dent, dir, return -errno) { + _cleanup_free_ char *path = NULL; + struct stat statbuf; + + /* only handle symlinks and regular files */ + if (!IN_SET(dent->d_type, DT_LNK, DT_REG)) + continue; + + path = path_join(syspath, dent->d_name); + if (!path) + return -ENOMEM; + + if (lstat(path, &statbuf) != 0) + continue; + + if (!(statbuf.st_mode & S_IRUSR)) + continue; + + r = set_put_strdup(device->sysattrs, dent->d_name); + if (r < 0) + return r; + } + + device->sysattrs_read = true; + + return 0; +} + +_public_ const char *sd_device_get_sysattr_first(sd_device *device) { + void *v; + int r; + + assert_return(device, NULL); + + if (!device->sysattrs_read) { + r = device_sysattrs_read_all(device); + if (r < 0) { + errno = -r; + return NULL; + } + } + + device->sysattrs_iterator = ITERATOR_FIRST; + + (void) set_iterate(device->sysattrs, &device->sysattrs_iterator, &v); + return v; +} + +_public_ const char *sd_device_get_sysattr_next(sd_device *device) { + void *v; + + assert_return(device, NULL); + + if (!device->sysattrs_read) + return NULL; + + (void) set_iterate(device->sysattrs, &device->sysattrs_iterator, &v); + return v; +} + +_public_ int sd_device_has_tag(sd_device *device, const char *tag) { + assert_return(device, -EINVAL); + assert_return(tag, -EINVAL); + + (void) device_read_db(device); + + return !!set_contains(device->tags, tag); +} + +_public_ int sd_device_get_property_value(sd_device *device, const char *key, const char **_value) { + char *value; + int r; + + assert_return(device, -EINVAL); + assert_return(key, -EINVAL); + + r = device_properties_prepare(device); + if (r < 0) + return r; + + value = ordered_hashmap_get(device->properties, key); + if (!value) + return -ENOENT; + + if (_value) + *_value = value; + return 0; +} + +/* replaces the value if it already exists */ +static int device_add_sysattr_value(sd_device *device, const char *_key, char *value) { + _cleanup_free_ char *key = NULL; + _cleanup_free_ char *value_old = NULL; + int r; + + assert(device); + assert(_key); + + r = hashmap_ensure_allocated(&device->sysattr_values, &string_hash_ops); + if (r < 0) + return r; + + value_old = hashmap_remove2(device->sysattr_values, _key, (void **)&key); + if (!key) { + key = strdup(_key); + if (!key) + return -ENOMEM; + } + + r = hashmap_put(device->sysattr_values, key, value); + if (r < 0) + return r; + TAKE_PTR(key); + + return 0; +} + +static int device_get_sysattr_value(sd_device *device, const char *_key, const char **_value) { + const char *key = NULL, *value; + + assert(device); + assert(_key); + + value = hashmap_get2(device->sysattr_values, _key, (void **) &key); + if (!key) + return -ENOENT; + + if (_value) + *_value = value; + return 0; +} + +/* We cache all sysattr lookups. If an attribute does not exist, it is stored + * with a NULL value in the cache, otherwise the returned string is stored */ +_public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value) { + _cleanup_free_ char *value = NULL; + const char *path, *syspath, *cached_value = NULL; + struct stat statbuf; + int r; + + assert_return(device, -EINVAL); + assert_return(sysattr, -EINVAL); + + /* look for possibly already cached result */ + r = device_get_sysattr_value(device, sysattr, &cached_value); + if (r != -ENOENT) { + if (r < 0) + return r; + + if (!cached_value) + /* we looked up the sysattr before and it did not exist */ + return -ENOENT; + + if (_value) + *_value = cached_value; + + return 0; + } + + r = sd_device_get_syspath(device, &syspath); + if (r < 0) + return r; + + path = prefix_roota(syspath, sysattr); + r = lstat(path, &statbuf); + if (r < 0) { + /* remember that we could not access the sysattr */ + r = device_add_sysattr_value(device, sysattr, NULL); + if (r < 0) + return r; + + return -ENOENT; + } else if (S_ISLNK(statbuf.st_mode)) { + /* Some core links return only the last element of the target path, + * these are just values, the paths should not be exposed. */ + if (STR_IN_SET(sysattr, "driver", "subsystem", "module")) { + r = readlink_value(path, &value); + if (r < 0) + return r; + } else + return -EINVAL; + } else if (S_ISDIR(statbuf.st_mode)) { + /* skip directories */ + return -EINVAL; + } else if (!(statbuf.st_mode & S_IRUSR)) { + /* skip non-readable files */ + return -EPERM; + } else { + size_t size; + + /* read attribute value */ + r = read_full_virtual_file(path, &value, &size); + if (r < 0) + return r; + + /* drop trailing newlines */ + while (size > 0 && value[--size] == '\n') + value[size] = '\0'; + } + + r = device_add_sysattr_value(device, sysattr, value); + if (r < 0) + return r; + + *_value = TAKE_PTR(value); + + return 0; +} + +static void device_remove_sysattr_value(sd_device *device, const char *_key) { + _cleanup_free_ char *key = NULL; + + assert(device); + assert(_key); + + free(hashmap_remove2(device->sysattr_values, _key, (void **) &key)); +} + +/* set the attribute and save it in the cache. If a NULL value is passed the + * attribute is cleared from the cache */ +_public_ int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *_value) { + _cleanup_free_ char *value = NULL; + const char *syspath, *path; + size_t len; + int r; + + assert_return(device, -EINVAL); + assert_return(sysattr, -EINVAL); + + if (!_value) { + device_remove_sysattr_value(device, sysattr); + return 0; + } + + r = sd_device_get_syspath(device, &syspath); + if (r < 0) + return r; + + path = prefix_roota(syspath, sysattr); + + len = strlen(_value); + + /* drop trailing newlines */ + while (len > 0 && _value[len - 1] == '\n') + len --; + + /* value length is limited to 4k */ + if (len > 4096) + return -EINVAL; + + value = strndup(_value, len); + if (!value) + return -ENOMEM; + + r = write_string_file(path, value, WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_NOFOLLOW); + if (r < 0) { + if (r == -ELOOP) + return -EINVAL; + if (r == -EISDIR) + return r; + + r = free_and_strdup(&value, ""); + if (r < 0) + return r; + + r = device_add_sysattr_value(device, sysattr, value); + if (r < 0) + return r; + TAKE_PTR(value); + + return -ENXIO; + } + + r = device_add_sysattr_value(device, sysattr, value); + if (r < 0) + return r; + TAKE_PTR(value); + + return 0; +} diff --git a/src/libsystemd/sd-device/test-sd-device-monitor.c b/src/libsystemd/sd-device/test-sd-device-monitor.c new file mode 100644 index 00000000..aa1edaaf --- /dev/null +++ b/src/libsystemd/sd-device/test-sd-device-monitor.c @@ -0,0 +1,218 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-device.h" +#include "sd-event.h" + +#include "device-monitor-private.h" +#include "device-private.h" +#include "device-util.h" +#include "macro.h" +#include "string-util.h" +#include "tests.h" +#include "util.h" +#include "virt.h" + +static int monitor_handler(sd_device_monitor *m, sd_device *d, void *userdata) { + const char *s, *syspath = userdata; + + assert_se(sd_device_get_syspath(d, &s) >= 0); + assert_se(streq(s, syspath)); + + return sd_event_exit(sd_device_monitor_get_event(m), 100); +} + +static int test_receive_device_fail(void) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; + _cleanup_(sd_device_unrefp) sd_device *loopback = NULL; + const char *syspath; + int r; + + log_info("/* %s */", __func__); + + /* Try to send device with invalid action and without seqnum. */ + assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0); + assert_se(device_add_property(loopback, "ACTION", "hoge") >= 0); + + assert_se(sd_device_get_syspath(loopback, &syspath) >= 0); + + assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); + assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); + assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0); + + assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); + assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); + assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); + assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0); + + /* Do not use assert_se() here. */ + r = device_monitor_send_device(monitor_server, monitor_client, loopback); + if (r < 0) + return log_error_errno(r, "Failed to send loopback device: %m"); + + assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0); + + return 0; +} + +static void test_send_receive_one(sd_device *device, bool subsystem_filter, bool tag_filter, bool use_bpf) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; + const char *syspath, *subsystem, *tag, *devtype = NULL; + + log_device_info(device, "/* %s(subsystem_filter=%s, tag_filter=%s, use_bpf=%s) */", __func__, + true_false(subsystem_filter), true_false(tag_filter), true_false(use_bpf)); + + assert_se(sd_device_get_syspath(device, &syspath) >= 0); + + assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); + assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); + assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0); + + assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); + assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); + assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); + assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0); + + if (subsystem_filter) { + assert_se(sd_device_get_subsystem(device, &subsystem) >= 0); + (void) sd_device_get_devtype(device, &devtype); + assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, devtype) >= 0); + } + + if (tag_filter) + FOREACH_DEVICE_TAG(device, tag) + assert_se(sd_device_monitor_filter_add_match_tag(monitor_client, tag) >= 0); + + if ((subsystem_filter || tag_filter) && use_bpf) + assert_se(sd_device_monitor_filter_update(monitor_client) >= 0); + + assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); + assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100); +} + +static void test_subsystem_filter(sd_device *device) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + const char *syspath, *subsystem, *p, *s; + sd_device *d; + + log_info("/* %s */", __func__); + + assert_se(sd_device_get_syspath(device, &syspath) >= 0); + assert_se(sd_device_get_subsystem(device, &subsystem) >= 0); + + assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); + assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); + assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0); + + assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); + assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); + assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, subsystem, NULL) >= 0); + assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); + assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0); + + assert_se(sd_device_enumerator_new(&e) >= 0); + assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, false) >= 0); + FOREACH_DEVICE(e, d) { + assert_se(sd_device_get_syspath(d, &p) >= 0); + assert_se(sd_device_get_subsystem(d, &s) >= 0); + + log_info("Sending device subsystem:%s syspath:%s", s, p); + assert_se(device_monitor_send_device(monitor_server, monitor_client, d) >= 0); + } + + log_info("Sending device subsystem:%s syspath:%s", subsystem, syspath); + assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); + assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100); +} + +static void test_sd_device_monitor_filter_remove(sd_device *device) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor_server = NULL, *monitor_client = NULL; + const char *syspath; + + log_device_info(device, "/* %s */", __func__); + + assert_se(sd_device_get_syspath(device, &syspath) >= 0); + + assert_se(device_monitor_new_full(&monitor_server, MONITOR_GROUP_NONE, -1) >= 0); + assert_se(sd_device_monitor_start(monitor_server, NULL, NULL) >= 0); + assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_server), "sender") >= 0); + + assert_se(device_monitor_new_full(&monitor_client, MONITOR_GROUP_NONE, -1) >= 0); + assert_se(device_monitor_allow_unicast_sender(monitor_client, monitor_server) >= 0); + assert_se(sd_device_monitor_start(monitor_client, monitor_handler, (void *) syspath) >= 0); + assert_se(sd_event_source_set_description(sd_device_monitor_get_event_source(monitor_client), "receiver") >= 0); + + assert_se(sd_device_monitor_filter_add_match_subsystem_devtype(monitor_client, "hoge", NULL) >= 0); + assert_se(sd_device_monitor_filter_update(monitor_client) >= 0); + + assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); + assert_se(sd_event_run(sd_device_monitor_get_event(monitor_client), 0) >= 0); + + assert_se(sd_device_monitor_filter_remove(monitor_client) >= 0); + + assert_se(device_monitor_send_device(monitor_server, monitor_client, device) >= 0); + assert_se(sd_event_loop(sd_device_monitor_get_event(monitor_client)) == 100); +} + +static void test_device_copy_properties(sd_device *device) { + _cleanup_(sd_device_unrefp) sd_device *copy = NULL; + + assert_se(device_shallow_clone(device, ©) >= 0); + assert_se(device_copy_properties(copy, device) >= 0); + + test_send_receive_one(copy, false, false, false); +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_device_unrefp) sd_device *loopback = NULL, *sda = NULL; + int r; + + test_setup_logging(LOG_INFO); + + if (getuid() != 0) + return log_tests_skipped("not root"); + + r = test_receive_device_fail(); + if (r < 0) { + assert_se(r == -EPERM && detect_container() > 0); + return log_tests_skipped("Running in container? Skipping remaining tests"); + } + + assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0); + assert_se(device_add_property(loopback, "ACTION", "add") >= 0); + assert_se(device_add_property(loopback, "SEQNUM", "10") >= 0); + + test_send_receive_one(loopback, false, false, false); + test_send_receive_one(loopback, true, false, false); + test_send_receive_one(loopback, false, true, false); + test_send_receive_one(loopback, true, true, false); + test_send_receive_one(loopback, true, false, true); + test_send_receive_one(loopback, false, true, true); + test_send_receive_one(loopback, true, true, true); + + test_subsystem_filter(loopback); + test_sd_device_monitor_filter_remove(loopback); + test_device_copy_properties(loopback); + + r = sd_device_new_from_subsystem_sysname(&sda, "block", "sda"); + if (r < 0) { + log_info_errno(r, "Failed to create sd_device for sda, skipping remaining tests: %m"); + return 0; + } + + assert_se(device_add_property(sda, "ACTION", "change") >= 0); + assert_se(device_add_property(sda, "SEQNUM", "11") >= 0); + + test_send_receive_one(sda, false, false, false); + test_send_receive_one(sda, true, false, false); + test_send_receive_one(sda, false, true, false); + test_send_receive_one(sda, true, true, false); + test_send_receive_one(sda, true, false, true); + test_send_receive_one(sda, false, true, true); + test_send_receive_one(sda, true, true, true); + + return 0; +} diff --git a/src/libsystemd/sd-device/test-sd-device-thread.c b/src/libsystemd/sd-device/test-sd-device-thread.c new file mode 100644 index 00000000..9f1c0237 --- /dev/null +++ b/src/libsystemd/sd-device/test-sd-device-thread.c @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-device.h" + +#include "device-util.h" +#include "macro.h" + +static void* thread(void *p) { + sd_device **d = p; + + assert_se(!(*d = sd_device_unref(*d))); + + return NULL; +} + +int main(int argc, char *argv[]) { + sd_device *loopback; + pthread_t t; + const char *key, *value; + + assert_se(unsetenv("SYSTEMD_MEMPOOL") == 0); + + assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0); + + FOREACH_DEVICE_PROPERTY(loopback, key, value) + printf("%s=%s\n", key, value); + + assert_se(pthread_create(&t, NULL, thread, &loopback) == 0); + assert_se(pthread_join(t, NULL) == 0); + + assert_se(!loopback); + + return 0; +} diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c new file mode 100644 index 00000000..33a25d57 --- /dev/null +++ b/src/libsystemd/sd-device/test-sd-device.c @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "device-enumerator-private.h" +#include "device-private.h" +#include "device-util.h" +#include "hashmap.h" +#include "string-util.h" +#include "tests.h" +#include "time-util.h" + +static void test_sd_device_one(sd_device *d) { + const char *syspath, *subsystem, *val; + dev_t devnum; + usec_t usec; + int i, r; + + assert_se(sd_device_get_syspath(d, &syspath) >= 0); + + r = sd_device_get_subsystem(d, &subsystem); + assert_se(r >= 0 || r == -ENOENT); + + r = sd_device_get_devtype(d, &val); + assert_se(r >= 0 || r == -ENOENT); + + r = sd_device_get_devnum(d, &devnum); + assert_se((r >= 0 && major(devnum) > 0) || r == -ENOENT); + + r = sd_device_get_ifindex(d, &i); + assert_se((r >= 0 && i > 0) || r == -ENOENT); + + r = sd_device_get_driver(d, &val); + assert_se(r >= 0 || r == -ENOENT); + + assert_se(sd_device_get_devpath(d, &val) >= 0); + + r = sd_device_get_devname(d, &val); + assert_se(r >= 0 || r == -ENOENT); + + assert_se(sd_device_get_sysname(d, &val) >= 0); + + r = sd_device_get_sysnum(d, &val); + assert_se(r >= 0 || r == -ENOENT); + + i = sd_device_get_is_initialized(d); + assert_se(i >= 0); + if (i > 0) { + r = sd_device_get_usec_since_initialized(d, &usec); + assert_se((r >= 0 && usec > 0) || r == -ENODATA); + } + + r = sd_device_get_sysattr_value(d, "name_assign_type", &val); + assert_se(r >= 0 || IN_SET(r, -ENOENT, -EINVAL)); + + r = sd_device_get_property_value(d, "ID_NET_DRIVER", &val); + assert_se(r >= 0 || r == -ENOENT); + + log_info("syspath:%s subsystem:%s initialized:%s", syspath, strna(subsystem), yes_no(i)); +} + +static void test_sd_device_enumerator_devices(void) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *d; + + log_info("/* %s */", __func__); + + assert_se(sd_device_enumerator_new(&e) >= 0); + assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0); + FOREACH_DEVICE(e, d) + test_sd_device_one(d); +} + +static void test_sd_device_enumerator_subsystems(void) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *d; + + log_info("/* %s */", __func__); + + assert_se(sd_device_enumerator_new(&e) >= 0); + assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0); + FOREACH_SUBSYSTEM(e, d) + test_sd_device_one(d); +} + +static void test_sd_device_enumerator_filter_subsystem_one(const char *subsystem, Hashmap *h) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *d, *t; + + assert_se(sd_device_enumerator_new(&e) >= 0); + assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, true) >= 0); + + FOREACH_DEVICE(e, d) { + const char *syspath; + + assert_se(sd_device_get_syspath(d, &syspath) >= 0); + assert_se(t = hashmap_remove(h, syspath)); + assert_se(!sd_device_unref(t)); + + log_debug("Removed subsystem:%s syspath:%s", subsystem, syspath); + } + + assert_se(hashmap_isempty(h)); +} + +static void test_sd_device_enumerator_filter_subsystem(void) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + _cleanup_(hashmap_freep) Hashmap *subsystems; + sd_device *d; + Hashmap *h; + char *s; + + log_info("/* %s */", __func__); + + assert_se(subsystems = hashmap_new(&string_hash_ops)); + assert_se(sd_device_enumerator_new(&e) >= 0); + + FOREACH_DEVICE(e, d) { + const char *syspath, *subsystem; + int r; + + assert_se(sd_device_get_syspath(d, &syspath) >= 0); + + r = sd_device_get_subsystem(d, &subsystem); + assert_se(r >= 0 || r == -ENOENT); + if (r < 0) + continue; + + h = hashmap_get(subsystems, subsystem); + if (!h) { + char *str; + assert_se(str = strdup(subsystem)); + assert_se(h = hashmap_new(&string_hash_ops)); + assert_se(hashmap_put(subsystems, str, h) >= 0); + } + + assert_se(hashmap_put(h, syspath, d) >= 0); + assert_se(sd_device_ref(d)); + + log_debug("Added subsystem:%s syspath:%s", subsystem, syspath); + } + + while ((h = hashmap_steal_first_key_and_value(subsystems, (void**) &s))) { + test_sd_device_enumerator_filter_subsystem_one(s, h); + hashmap_free(h); + free(s); + } +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_INFO); + + test_sd_device_enumerator_devices(); + test_sd_device_enumerator_subsystems(); + test_sd_device_enumerator_filter_subsystem(); + + return 0; +} diff --git a/src/libsystemd/sd-device/test-udev-device-thread.c b/src/libsystemd/sd-device/test-udev-device-thread.c new file mode 100644 index 00000000..2fc0f591 --- /dev/null +++ b/src/libsystemd/sd-device/test-udev-device-thread.c @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "libudev.h" + +#include "macro.h" + +static void* thread(void *p) { + struct udev_device **d = p; + + assert_se(!(*d = udev_device_unref(*d))); + + return NULL; +} + +int main(int argc, char *argv[]) { + struct udev_device *loopback; + pthread_t t; + + assert_se(unsetenv("SYSTEMD_MEMPOOL") == 0); + + assert_se(loopback = udev_device_new_from_syspath(NULL, "/sys/class/net/lo")); + + assert_se(udev_device_get_properties_list_entry(loopback)); + + assert_se(pthread_create(&t, NULL, thread, &loopback) == 0); + assert_se(pthread_join(t, NULL) == 0); + + assert_se(!loopback); + + return 0; +} diff --git a/src/libsystemd/sd-event/event-source.h b/src/libsystemd/sd-event/event-source.h new file mode 100644 index 00000000..99ab8fc1 --- /dev/null +++ b/src/libsystemd/sd-event/event-source.h @@ -0,0 +1,206 @@ +#pragma once +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-event.h" + +#include "fs-util.h" +#include "hashmap.h" +#include "list.h" +#include "prioq.h" + +typedef enum EventSourceType { + SOURCE_IO, + SOURCE_TIME_REALTIME, + SOURCE_TIME_BOOTTIME, + SOURCE_TIME_MONOTONIC, + SOURCE_TIME_REALTIME_ALARM, + SOURCE_TIME_BOOTTIME_ALARM, + SOURCE_SIGNAL, + SOURCE_CHILD, + SOURCE_DEFER, + SOURCE_POST, + SOURCE_EXIT, + SOURCE_WATCHDOG, + SOURCE_INOTIFY, + _SOURCE_EVENT_SOURCE_TYPE_MAX, + _SOURCE_EVENT_SOURCE_TYPE_INVALID = -1 +} EventSourceType; + +/* All objects we use in epoll events start with this value, so that + * we know how to dispatch it */ +typedef enum WakeupType { + WAKEUP_NONE, + WAKEUP_EVENT_SOURCE, + WAKEUP_CLOCK_DATA, + WAKEUP_SIGNAL_DATA, + WAKEUP_INOTIFY_DATA, + _WAKEUP_TYPE_MAX, + _WAKEUP_TYPE_INVALID = -1, +} WakeupType; + +struct inode_data; + +struct sd_event_source { + WakeupType wakeup; + + unsigned n_ref; + + sd_event *event; + void *userdata; + sd_event_handler_t prepare; + + char *description; + + EventSourceType type:5; + signed int enabled:3; + bool pending:1; + bool dispatching:1; + bool floating:1; + + int64_t priority; + unsigned pending_index; + unsigned prepare_index; + uint64_t pending_iteration; + uint64_t prepare_iteration; + + sd_event_destroy_t destroy_callback; + + LIST_FIELDS(sd_event_source, sources); + + union { + struct { + sd_event_io_handler_t callback; + int fd; + uint32_t events; + uint32_t revents; + bool registered:1; + bool owned:1; + } io; + struct { + sd_event_time_handler_t callback; + usec_t next, accuracy; + unsigned earliest_index; + unsigned latest_index; + } time; + struct { + sd_event_signal_handler_t callback; + struct signalfd_siginfo siginfo; + int sig; + } signal; + struct { + sd_event_child_handler_t callback; + siginfo_t siginfo; + pid_t pid; + int options; + } child; + struct { + sd_event_handler_t callback; + } defer; + struct { + sd_event_handler_t callback; + } post; + struct { + sd_event_handler_t callback; + unsigned prioq_index; + } exit; + struct { + sd_event_inotify_handler_t callback; + uint32_t mask; + struct inode_data *inode_data; + LIST_FIELDS(sd_event_source, by_inode_data); + } inotify; + }; +}; + +struct clock_data { + WakeupType wakeup; + int fd; + + /* For all clocks we maintain two priority queues each, one + * ordered for the earliest times the events may be + * dispatched, and one ordered by the latest times they must + * have been dispatched. The range between the top entries in + * the two prioqs is the time window we can freely schedule + * wakeups in */ + + Prioq *earliest; + Prioq *latest; + usec_t next; + + bool needs_rearm:1; +}; + +struct signal_data { + WakeupType wakeup; + + /* For each priority we maintain one signal fd, so that we + * only have to dequeue a single event per priority at a + * time. */ + + int fd; + int64_t priority; + sigset_t sigset; + sd_event_source *current; +}; + +/* A structure listing all event sources currently watching a specific inode */ +struct inode_data { + /* The identifier for the inode, the combination of the .st_dev + .st_ino fields of the file */ + ino_t ino; + dev_t dev; + + /* An fd of the inode to watch. The fd is kept open until the next iteration of the loop, so that we can + * rearrange the priority still until then, as we need the original inode to change the priority as we need to + * add a watch descriptor to the right inotify for the priority which we can only do if we have a handle to the + * original inode. We keep a list of all inode_data objects with an open fd in the to_close list (see below) of + * the sd-event object, so that it is efficient to close everything, before entering the next event loop + * iteration. */ + int fd; + + /* The inotify "watch descriptor" */ + int wd; + + /* The combination of the mask of all inotify watches on this inode we manage. This is also the mask that has + * most recently been set on the watch descriptor. */ + uint32_t combined_mask; + + /* All event sources subscribed to this inode */ + LIST_HEAD(sd_event_source, event_sources); + + /* The inotify object we watch this inode with */ + struct inotify_data *inotify_data; + + /* A linked list of all inode data objects with fds to close (see above) */ + LIST_FIELDS(struct inode_data, to_close); +}; + +/* A structure encapsulating an inotify fd */ +struct inotify_data { + WakeupType wakeup; + + /* For each priority we maintain one inotify fd, so that we only have to dequeue a single event per priority at + * a time */ + + int fd; + int64_t priority; + + Hashmap *inodes; /* The inode_data structures keyed by dev+ino */ + Hashmap *wd; /* The inode_data structures keyed by the watch descriptor for each */ + + /* The buffer we read inotify events into */ + union inotify_event_buffer buffer; + size_t buffer_filled; /* fill level of the buffer */ + + /* How many event sources are currently marked pending for this inotify. We won't read new events off the + * inotify fd as long as there are still pending events on the inotify (because we have no strategy of queuing + * the events locally if they can't be coalesced). */ + unsigned n_pending; + + /* A linked list of all inotify objects with data already read, that still need processing. We keep this list + * to make it efficient to figure out what inotify objects to process data on next. */ + LIST_FIELDS(struct inotify_data, buffered); +}; diff --git a/src/libsystemd/sd-event/event-util.c b/src/libsystemd/sd-event/event-util.c new file mode 100644 index 00000000..43e73d55 --- /dev/null +++ b/src/libsystemd/sd-event/event-util.c @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "event-source.h" +#include "event-util.h" +#include "log.h" +#include "string-util.h" + +int event_reset_time( + sd_event *e, + sd_event_source **s, + clockid_t clock, + uint64_t usec, + uint64_t accuracy, + sd_event_time_handler_t callback, + void *userdata, + int64_t priority, + const char *description, + bool force_reset) { + + bool created = false; + int enabled, r; + clockid_t c; + + assert(e); + assert(s); + + if (*s) { + if (!force_reset) { + r = sd_event_source_get_enabled(*s, &enabled); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to query whether event source \"%s\" is enabled or not: %m", + strna((*s)->description ?: description)); + + if (enabled != SD_EVENT_OFF) + return 0; + } + + r = sd_event_source_get_time_clock(*s, &c); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to get clock id of event source \"%s\": %m", strna((*s)->description ?: description)); + + if (c != clock) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "sd-event: Current clock id %i of event source \"%s\" is different from specified one %i.", + (int)c, + strna((*s)->description ? : description), + (int)clock); + + r = sd_event_source_set_time(*s, usec); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to set time for event source \"%s\": %m", strna((*s)->description ?: description)); + + r = sd_event_source_set_time_accuracy(*s, accuracy); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to set accuracy for event source \"%s\": %m", strna((*s)->description ?: description)); + + /* callback function is not updated, as we do not have sd_event_source_set_time_callback(). */ + + (void) sd_event_source_set_userdata(*s, userdata); + + r = sd_event_source_set_enabled(*s, SD_EVENT_ONESHOT); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to enable event source \"%s\": %m", strna((*s)->description ?: description)); + } else { + r = sd_event_add_time(e, s, clock, usec, accuracy, callback, userdata); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to create timer event \"%s\": %m", strna(description)); + + created = true; + } + + r = sd_event_source_set_priority(*s, priority); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to set priority for event source \"%s\": %m", strna((*s)->description ?: description)); + + if (description) { + r = sd_event_source_set_description(*s, description); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to set description for event source \"%s\": %m", description); + } + + return created; +} + +int event_source_disable(sd_event_source *s) { + if (!s) + return 0; + + return sd_event_source_set_enabled(s, SD_EVENT_OFF); +} + +int event_source_is_enabled(sd_event_source *s) { + if (!s) + return false; + + return sd_event_source_get_enabled(s, NULL); +} diff --git a/src/libsystemd/sd-event/event-util.h b/src/libsystemd/sd-event/event-util.h new file mode 100644 index 00000000..00180955 --- /dev/null +++ b/src/libsystemd/sd-event/event-util.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-event.h" + +int event_reset_time(sd_event *e, sd_event_source **s, + clockid_t clock, uint64_t usec, uint64_t accuracy, + sd_event_time_handler_t callback, void *userdata, + int64_t priority, const char *description, bool force_reset); +int event_source_disable(sd_event_source *s); +int event_source_is_enabled(sd_event_source *s); diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c new file mode 100644 index 00000000..b76dbf3d --- /dev/null +++ b/src/libsystemd/sd-event/sd-event.c @@ -0,0 +1,3551 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-event.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "event-source.h" +#include "fd-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "list.h" +#include "macro.h" +#include "memory-util.h" +#include "missing_syscall.h" +#include "prioq.h" +#include "process-util.h" +#include "set.h" +#include "signal-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "time-util.h" + +#define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC) + +static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = { + [SOURCE_IO] = "io", + [SOURCE_TIME_REALTIME] = "realtime", + [SOURCE_TIME_BOOTTIME] = "bootime", + [SOURCE_TIME_MONOTONIC] = "monotonic", + [SOURCE_TIME_REALTIME_ALARM] = "realtime-alarm", + [SOURCE_TIME_BOOTTIME_ALARM] = "boottime-alarm", + [SOURCE_SIGNAL] = "signal", + [SOURCE_CHILD] = "child", + [SOURCE_DEFER] = "defer", + [SOURCE_POST] = "post", + [SOURCE_EXIT] = "exit", + [SOURCE_WATCHDOG] = "watchdog", + [SOURCE_INOTIFY] = "inotify", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int); + +#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM) + +struct sd_event { + unsigned n_ref; + + int epoll_fd; + int watchdog_fd; + + Prioq *pending; + Prioq *prepare; + + /* timerfd_create() only supports these five clocks so far. We + * can add support for more clocks when the kernel learns to + * deal with them, too. */ + struct clock_data realtime; + struct clock_data boottime; + struct clock_data monotonic; + struct clock_data realtime_alarm; + struct clock_data boottime_alarm; + + usec_t perturb; + + sd_event_source **signal_sources; /* indexed by signal number */ + Hashmap *signal_data; /* indexed by priority */ + + Hashmap *child_sources; + unsigned n_enabled_child_sources; + + Set *post_sources; + + Prioq *exit; + + Hashmap *inotify_data; /* indexed by priority */ + + /* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */ + LIST_HEAD(struct inode_data, inode_data_to_close); + + /* A list of inotify objects that already have events buffered which aren't processed yet */ + LIST_HEAD(struct inotify_data, inotify_data_buffered); + + pid_t original_pid; + + uint64_t iteration; + triple_timestamp timestamp; + int state; + + bool exit_requested:1; + bool need_process_child:1; + bool watchdog:1; + bool profile_delays:1; + + int exit_code; + + pid_t tid; + sd_event **default_event_ptr; + + usec_t watchdog_last, watchdog_period; + + unsigned n_sources; + + LIST_HEAD(sd_event_source, sources); + + usec_t last_run, last_log; + unsigned delays[sizeof(usec_t) * 8]; +}; + +static thread_local sd_event *default_event = NULL; + +static void source_disconnect(sd_event_source *s); +static void event_gc_inode_data(sd_event *e, struct inode_data *d); + +static sd_event *event_resolve(sd_event *e) { + return e == SD_EVENT_DEFAULT ? default_event : e; +} + +static int pending_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + int r; + + assert(x->pending); + assert(y->pending); + + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + + /* Lower priority values first */ + r = CMP(x->priority, y->priority); + if (r != 0) + return r; + + /* Older entries first */ + return CMP(x->pending_iteration, y->pending_iteration); +} + +static int prepare_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + int r; + + assert(x->prepare); + assert(y->prepare); + + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + + /* Move most recently prepared ones last, so that we can stop + * preparing as soon as we hit one that has already been + * prepared in the current iteration */ + r = CMP(x->prepare_iteration, y->prepare_iteration); + if (r != 0) + return r; + + /* Lower priority values first */ + return CMP(x->priority, y->priority); +} + +static int earliest_time_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + + assert(EVENT_SOURCE_IS_TIME(x->type)); + assert(x->type == y->type); + + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + + /* Move the pending ones to the end */ + if (!x->pending && y->pending) + return -1; + if (x->pending && !y->pending) + return 1; + + /* Order by time */ + return CMP(x->time.next, y->time.next); +} + +static usec_t time_event_source_latest(const sd_event_source *s) { + return usec_add(s->time.next, s->time.accuracy); +} + +static int latest_time_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + + assert(EVENT_SOURCE_IS_TIME(x->type)); + assert(x->type == y->type); + + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + + /* Move the pending ones to the end */ + if (!x->pending && y->pending) + return -1; + if (x->pending && !y->pending) + return 1; + + /* Order by time */ + return CMP(time_event_source_latest(x), time_event_source_latest(y)); +} + +static int exit_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + + assert(x->type == SOURCE_EXIT); + assert(y->type == SOURCE_EXIT); + + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + + /* Lower priority values first */ + return CMP(x->priority, y->priority); +} + +static void free_clock_data(struct clock_data *d) { + assert(d); + assert(d->wakeup == WAKEUP_CLOCK_DATA); + + safe_close(d->fd); + prioq_free(d->earliest); + prioq_free(d->latest); +} + +static sd_event *event_free(sd_event *e) { + sd_event_source *s; + + assert(e); + + while ((s = e->sources)) { + assert(s->floating); + source_disconnect(s); + sd_event_source_unref(s); + } + + assert(e->n_sources == 0); + + if (e->default_event_ptr) + *(e->default_event_ptr) = NULL; + + safe_close(e->epoll_fd); + safe_close(e->watchdog_fd); + + free_clock_data(&e->realtime); + free_clock_data(&e->boottime); + free_clock_data(&e->monotonic); + free_clock_data(&e->realtime_alarm); + free_clock_data(&e->boottime_alarm); + + prioq_free(e->pending); + prioq_free(e->prepare); + prioq_free(e->exit); + + free(e->signal_sources); + hashmap_free(e->signal_data); + + hashmap_free(e->inotify_data); + + hashmap_free(e->child_sources); + set_free(e->post_sources); + + return mfree(e); +} + +_public_ int sd_event_new(sd_event** ret) { + sd_event *e; + int r; + + assert_return(ret, -EINVAL); + + e = new(sd_event, 1); + if (!e) + return -ENOMEM; + + *e = (sd_event) { + .n_ref = 1, + .epoll_fd = -1, + .watchdog_fd = -1, + .realtime.wakeup = WAKEUP_CLOCK_DATA, + .realtime.fd = -1, + .realtime.next = USEC_INFINITY, + .boottime.wakeup = WAKEUP_CLOCK_DATA, + .boottime.fd = -1, + .boottime.next = USEC_INFINITY, + .monotonic.wakeup = WAKEUP_CLOCK_DATA, + .monotonic.fd = -1, + .monotonic.next = USEC_INFINITY, + .realtime_alarm.wakeup = WAKEUP_CLOCK_DATA, + .realtime_alarm.fd = -1, + .realtime_alarm.next = USEC_INFINITY, + .boottime_alarm.wakeup = WAKEUP_CLOCK_DATA, + .boottime_alarm.fd = -1, + .boottime_alarm.next = USEC_INFINITY, + .perturb = USEC_INFINITY, + .original_pid = getpid_cached(), + }; + + r = prioq_ensure_allocated(&e->pending, pending_prioq_compare); + if (r < 0) + goto fail; + + e->epoll_fd = epoll_create1(EPOLL_CLOEXEC); + if (e->epoll_fd < 0) { + r = -errno; + goto fail; + } + + e->epoll_fd = fd_move_above_stdio(e->epoll_fd); + + if (secure_getenv("SD_EVENT_PROFILE_DELAYS")) { + log_debug("Event loop profiling enabled. Logarithmic histogram of event loop iterations in the range 2^0 ... 2^63 us will be logged every 5s."); + e->profile_delays = true; + } + + *ret = e; + return 0; + +fail: + event_free(e); + return r; +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free); + +_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) { + if (s) + (void) sd_event_source_set_enabled(s, SD_EVENT_OFF); + return sd_event_source_unref(s); +} + +static bool event_pid_changed(sd_event *e) { + assert(e); + + /* We don't support people creating an event loop and keeping + * it around over a fork(). Let's complain. */ + + return e->original_pid != getpid_cached(); +} + +static void source_io_unregister(sd_event_source *s) { + int r; + + assert(s); + assert(s->type == SOURCE_IO); + + if (event_pid_changed(s->event)) + return; + + if (!s->io.registered) + return; + + r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL); + if (r < 0) + log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll: %m", + strna(s->description), event_source_type_to_string(s->type)); + + s->io.registered = false; +} + +static int source_io_register( + sd_event_source *s, + int enabled, + uint32_t events) { + + struct epoll_event ev; + int r; + + assert(s); + assert(s->type == SOURCE_IO); + assert(enabled != SD_EVENT_OFF); + + ev = (struct epoll_event) { + .events = events | (enabled == SD_EVENT_ONESHOT ? EPOLLONESHOT : 0), + .data.ptr = s, + }; + + if (s->io.registered) + r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->io.fd, &ev); + else + r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_ADD, s->io.fd, &ev); + if (r < 0) + return -errno; + + s->io.registered = true; + + return 0; +} + +static clockid_t event_source_type_to_clock(EventSourceType t) { + + switch (t) { + + case SOURCE_TIME_REALTIME: + return CLOCK_REALTIME; + + case SOURCE_TIME_BOOTTIME: + return CLOCK_BOOTTIME; + + case SOURCE_TIME_MONOTONIC: + return CLOCK_MONOTONIC; + + case SOURCE_TIME_REALTIME_ALARM: + return CLOCK_REALTIME_ALARM; + + case SOURCE_TIME_BOOTTIME_ALARM: + return CLOCK_BOOTTIME_ALARM; + + default: + return (clockid_t) -1; + } +} + +static EventSourceType clock_to_event_source_type(clockid_t clock) { + + switch (clock) { + + case CLOCK_REALTIME: + return SOURCE_TIME_REALTIME; + + case CLOCK_BOOTTIME: + return SOURCE_TIME_BOOTTIME; + + case CLOCK_MONOTONIC: + return SOURCE_TIME_MONOTONIC; + + case CLOCK_REALTIME_ALARM: + return SOURCE_TIME_REALTIME_ALARM; + + case CLOCK_BOOTTIME_ALARM: + return SOURCE_TIME_BOOTTIME_ALARM; + + default: + return _SOURCE_EVENT_SOURCE_TYPE_INVALID; + } +} + +static struct clock_data* event_get_clock_data(sd_event *e, EventSourceType t) { + assert(e); + + switch (t) { + + case SOURCE_TIME_REALTIME: + return &e->realtime; + + case SOURCE_TIME_BOOTTIME: + return &e->boottime; + + case SOURCE_TIME_MONOTONIC: + return &e->monotonic; + + case SOURCE_TIME_REALTIME_ALARM: + return &e->realtime_alarm; + + case SOURCE_TIME_BOOTTIME_ALARM: + return &e->boottime_alarm; + + default: + return NULL; + } +} + +static void event_free_signal_data(sd_event *e, struct signal_data *d) { + assert(e); + + if (!d) + return; + + hashmap_remove(e->signal_data, &d->priority); + safe_close(d->fd); + free(d); +} + +static int event_make_signal_data( + sd_event *e, + int sig, + struct signal_data **ret) { + + struct epoll_event ev; + struct signal_data *d; + bool added = false; + sigset_t ss_copy; + int64_t priority; + int r; + + assert(e); + + if (event_pid_changed(e)) + return -ECHILD; + + if (e->signal_sources && e->signal_sources[sig]) + priority = e->signal_sources[sig]->priority; + else + priority = SD_EVENT_PRIORITY_NORMAL; + + d = hashmap_get(e->signal_data, &priority); + if (d) { + if (sigismember(&d->sigset, sig) > 0) { + if (ret) + *ret = d; + return 0; + } + } else { + r = hashmap_ensure_allocated(&e->signal_data, &uint64_hash_ops); + if (r < 0) + return r; + + d = new(struct signal_data, 1); + if (!d) + return -ENOMEM; + + *d = (struct signal_data) { + .wakeup = WAKEUP_SIGNAL_DATA, + .fd = -1, + .priority = priority, + }; + + r = hashmap_put(e->signal_data, &d->priority, d); + if (r < 0) { + free(d); + return r; + } + + added = true; + } + + ss_copy = d->sigset; + assert_se(sigaddset(&ss_copy, sig) >= 0); + + r = signalfd(d->fd, &ss_copy, SFD_NONBLOCK|SFD_CLOEXEC); + if (r < 0) { + r = -errno; + goto fail; + } + + d->sigset = ss_copy; + + if (d->fd >= 0) { + if (ret) + *ret = d; + return 0; + } + + d->fd = fd_move_above_stdio(r); + + ev = (struct epoll_event) { + .events = EPOLLIN, + .data.ptr = d, + }; + + r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev); + if (r < 0) { + r = -errno; + goto fail; + } + + if (ret) + *ret = d; + + return 0; + +fail: + if (added) + event_free_signal_data(e, d); + + return r; +} + +static void event_unmask_signal_data(sd_event *e, struct signal_data *d, int sig) { + assert(e); + assert(d); + + /* Turns off the specified signal in the signal data + * object. If the signal mask of the object becomes empty that + * way removes it. */ + + if (sigismember(&d->sigset, sig) == 0) + return; + + assert_se(sigdelset(&d->sigset, sig) >= 0); + + if (sigisemptyset(&d->sigset)) { + /* If all the mask is all-zero we can get rid of the structure */ + event_free_signal_data(e, d); + return; + } + + assert(d->fd >= 0); + + if (signalfd(d->fd, &d->sigset, SFD_NONBLOCK|SFD_CLOEXEC) < 0) + log_debug_errno(errno, "Failed to unset signal bit, ignoring: %m"); +} + +static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig) { + struct signal_data *d; + static const int64_t zero_priority = 0; + + assert(e); + + /* Rechecks if the specified signal is still something we are + * interested in. If not, we'll unmask it, and possibly drop + * the signalfd for it. */ + + if (sig == SIGCHLD && + e->n_enabled_child_sources > 0) + return; + + if (e->signal_sources && + e->signal_sources[sig] && + e->signal_sources[sig]->enabled != SD_EVENT_OFF) + return; + + /* + * The specified signal might be enabled in three different queues: + * + * 1) the one that belongs to the priority passed (if it is non-NULL) + * 2) the one that belongs to the priority of the event source of the signal (if there is one) + * 3) the 0 priority (to cover the SIGCHLD case) + * + * Hence, let's remove it from all three here. + */ + + if (priority) { + d = hashmap_get(e->signal_data, priority); + if (d) + event_unmask_signal_data(e, d, sig); + } + + if (e->signal_sources && e->signal_sources[sig]) { + d = hashmap_get(e->signal_data, &e->signal_sources[sig]->priority); + if (d) + event_unmask_signal_data(e, d, sig); + } + + d = hashmap_get(e->signal_data, &zero_priority); + if (d) + event_unmask_signal_data(e, d, sig); +} + +static void source_disconnect(sd_event_source *s) { + sd_event *event; + + assert(s); + + if (!s->event) + return; + + assert(s->event->n_sources > 0); + + switch (s->type) { + + case SOURCE_IO: + if (s->io.fd >= 0) + source_io_unregister(s); + + break; + + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: { + struct clock_data *d; + + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_remove(d->earliest, s, &s->time.earliest_index); + prioq_remove(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + break; + } + + case SOURCE_SIGNAL: + if (s->signal.sig > 0) { + + if (s->event->signal_sources) + s->event->signal_sources[s->signal.sig] = NULL; + + event_gc_signal_data(s->event, &s->priority, s->signal.sig); + } + + break; + + case SOURCE_CHILD: + if (s->child.pid > 0) { + if (s->enabled != SD_EVENT_OFF) { + assert(s->event->n_enabled_child_sources > 0); + s->event->n_enabled_child_sources--; + } + + (void) hashmap_remove(s->event->child_sources, PID_TO_PTR(s->child.pid)); + event_gc_signal_data(s->event, &s->priority, SIGCHLD); + } + + break; + + case SOURCE_DEFER: + /* nothing */ + break; + + case SOURCE_POST: + set_remove(s->event->post_sources, s); + break; + + case SOURCE_EXIT: + prioq_remove(s->event->exit, s, &s->exit.prioq_index); + break; + + case SOURCE_INOTIFY: { + struct inode_data *inode_data; + + inode_data = s->inotify.inode_data; + if (inode_data) { + struct inotify_data *inotify_data; + assert_se(inotify_data = inode_data->inotify_data); + + /* Detach this event source from the inode object */ + LIST_REMOVE(inotify.by_inode_data, inode_data->event_sources, s); + s->inotify.inode_data = NULL; + + if (s->pending) { + assert(inotify_data->n_pending > 0); + inotify_data->n_pending--; + } + + /* Note that we don't reduce the inotify mask for the watch descriptor here if the inode is + * continued to being watched. That's because inotify doesn't really have an API for that: we + * can only change watch masks with access to the original inode either by fd or by path. But + * paths aren't stable, and keeping an O_PATH fd open all the time would mean wasting an fd + * continuously and keeping the mount busy which we can't really do. We could reconstruct the + * original inode from /proc/self/fdinfo/$INOTIFY_FD (as all watch descriptors are listed + * there), but given the need for open_by_handle_at() which is privileged and not universally + * available this would be quite an incomplete solution. Hence we go the other way, leave the + * mask set, even if it is not minimized now, and ignore all events we aren't interested in + * anymore after reception. Yes, this sucks, but … Linux … */ + + /* Maybe release the inode data (and its inotify) */ + event_gc_inode_data(s->event, inode_data); + } + + break; + } + + default: + assert_not_reached("Wut? I shouldn't exist."); + } + + if (s->pending) + prioq_remove(s->event->pending, s, &s->pending_index); + + if (s->prepare) + prioq_remove(s->event->prepare, s, &s->prepare_index); + + event = s->event; + + s->event = NULL; + LIST_REMOVE(sources, event->sources, s); + event->n_sources--; + + /* Note that we don't invalidate the type here, since we still need it in order to close the fd or + * pidfd associated with this event source, which we'll do only on source_free(). */ + + if (!s->floating) + sd_event_unref(event); +} + +static void source_free(sd_event_source *s) { + assert(s); + + source_disconnect(s); + + if (s->type == SOURCE_IO && s->io.owned) + s->io.fd = safe_close(s->io.fd); + + if (s->destroy_callback) + s->destroy_callback(s->userdata); + + free(s->description); + free(s); +} +DEFINE_TRIVIAL_CLEANUP_FUNC(sd_event_source*, source_free); + +static int source_set_pending(sd_event_source *s, bool b) { + int r; + + assert(s); + assert(s->type != SOURCE_EXIT); + + if (s->pending == b) + return 0; + + s->pending = b; + + if (b) { + s->pending_iteration = s->event->iteration; + + r = prioq_put(s->event->pending, s, &s->pending_index); + if (r < 0) { + s->pending = false; + return r; + } + } else + assert_se(prioq_remove(s->event->pending, s, &s->pending_index)); + + if (EVENT_SOURCE_IS_TIME(s->type)) { + struct clock_data *d; + + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + } + + if (s->type == SOURCE_SIGNAL && !b) { + struct signal_data *d; + + d = hashmap_get(s->event->signal_data, &s->priority); + if (d && d->current == s) + d->current = NULL; + } + + if (s->type == SOURCE_INOTIFY) { + + assert(s->inotify.inode_data); + assert(s->inotify.inode_data->inotify_data); + + if (b) + s->inotify.inode_data->inotify_data->n_pending ++; + else { + assert(s->inotify.inode_data->inotify_data->n_pending > 0); + s->inotify.inode_data->inotify_data->n_pending --; + } + } + + return 0; +} + +static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType type) { + sd_event_source *s; + + assert(e); + + s = new(sd_event_source, 1); + if (!s) + return NULL; + + *s = (struct sd_event_source) { + .n_ref = 1, + .event = e, + .floating = floating, + .type = type, + .pending_index = PRIOQ_IDX_NULL, + .prepare_index = PRIOQ_IDX_NULL, + }; + + if (!floating) + sd_event_ref(e); + + LIST_PREPEND(sources, e->sources, s); + e->n_sources++; + + return s; +} + +_public_ int sd_event_add_io( + sd_event *e, + sd_event_source **ret, + int fd, + uint32_t events, + sd_event_io_handler_t callback, + void *userdata) { + + _cleanup_(source_freep) sd_event_source *s = NULL; + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(fd >= 0, -EBADF); + assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + s = source_new(e, !ret, SOURCE_IO); + if (!s) + return -ENOMEM; + + s->wakeup = WAKEUP_EVENT_SOURCE; + s->io.fd = fd; + s->io.events = events; + s->io.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ON; + + r = source_io_register(s, s->enabled, events); + if (r < 0) + return r; + + if (ret) + *ret = s; + TAKE_PTR(s); + + return 0; +} + +static void initialize_perturb(sd_event *e) { + sd_id128_t bootid = {}; + + /* When we sleep for longer, we try to realign the wakeup to + the same time within each minute/second/250ms, so that + events all across the system can be coalesced into a single + CPU wakeup. However, let's take some system-specific + randomness for this value, so that in a network of systems + with synced clocks timer events are distributed a + bit. Here, we calculate a perturbation usec offset from the + boot ID. */ + + if (_likely_(e->perturb != USEC_INFINITY)) + return; + + if (sd_id128_get_boot(&bootid) >= 0) + e->perturb = (bootid.qwords[0] ^ bootid.qwords[1]) % USEC_PER_MINUTE; +} + +static int event_setup_timer_fd( + sd_event *e, + struct clock_data *d, + clockid_t clock) { + + struct epoll_event ev; + int r, fd; + + assert(e); + assert(d); + + if (_likely_(d->fd >= 0)) + return 0; + + fd = timerfd_create(clock, TFD_NONBLOCK|TFD_CLOEXEC); + if (fd < 0) + return -errno; + + fd = fd_move_above_stdio(fd); + + ev = (struct epoll_event) { + .events = EPOLLIN, + .data.ptr = d, + }; + + r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev); + if (r < 0) { + safe_close(fd); + return -errno; + } + + d->fd = fd; + return 0; +} + +static int time_exit_callback(sd_event_source *s, uint64_t usec, void *userdata) { + assert(s); + + return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); +} + +_public_ int sd_event_add_time( + sd_event *e, + sd_event_source **ret, + clockid_t clock, + uint64_t usec, + uint64_t accuracy, + sd_event_time_handler_t callback, + void *userdata) { + + EventSourceType type; + _cleanup_(source_freep) sd_event_source *s = NULL; + struct clock_data *d; + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(accuracy != (uint64_t) -1, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + if (!clock_supported(clock)) /* Checks whether the kernel supports the clock */ + return -EOPNOTSUPP; + + type = clock_to_event_source_type(clock); /* checks whether sd-event supports this clock */ + if (type < 0) + return -EOPNOTSUPP; + + if (!callback) + callback = time_exit_callback; + + d = event_get_clock_data(e, type); + assert(d); + + r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare); + if (r < 0) + return r; + + r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare); + if (r < 0) + return r; + + if (d->fd < 0) { + r = event_setup_timer_fd(e, d, clock); + if (r < 0) + return r; + } + + s = source_new(e, !ret, type); + if (!s) + return -ENOMEM; + + s->time.next = usec; + s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy; + s->time.callback = callback; + s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL; + s->userdata = userdata; + s->enabled = SD_EVENT_ONESHOT; + + d->needs_rearm = true; + + r = prioq_put(d->earliest, s, &s->time.earliest_index); + if (r < 0) + return r; + + r = prioq_put(d->latest, s, &s->time.latest_index); + if (r < 0) + return r; + + if (ret) + *ret = s; + TAKE_PTR(s); + + return 0; +} + +static int signal_exit_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + assert(s); + + return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); +} + +_public_ int sd_event_add_signal( + sd_event *e, + sd_event_source **ret, + int sig, + sd_event_signal_handler_t callback, + void *userdata) { + + _cleanup_(source_freep) sd_event_source *s = NULL; + struct signal_data *d; + sigset_t ss; + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(SIGNAL_VALID(sig), -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + if (!callback) + callback = signal_exit_callback; + + r = pthread_sigmask(SIG_SETMASK, NULL, &ss); + if (r != 0) + return -r; + + if (!sigismember(&ss, sig)) + return -EBUSY; + + if (!e->signal_sources) { + e->signal_sources = new0(sd_event_source*, _NSIG); + if (!e->signal_sources) + return -ENOMEM; + } else if (e->signal_sources[sig]) + return -EBUSY; + + s = source_new(e, !ret, SOURCE_SIGNAL); + if (!s) + return -ENOMEM; + + s->signal.sig = sig; + s->signal.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ON; + + e->signal_sources[sig] = s; + + r = event_make_signal_data(e, sig, &d); + if (r < 0) + return r; + + /* Use the signal name as description for the event source by default */ + (void) sd_event_source_set_description(s, signal_to_string(sig)); + + if (ret) + *ret = s; + TAKE_PTR(s); + + return 0; +} + +_public_ int sd_event_add_child( + sd_event *e, + sd_event_source **ret, + pid_t pid, + int options, + sd_event_child_handler_t callback, + void *userdata) { + + _cleanup_(source_freep) sd_event_source *s = NULL; + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(pid > 1, -EINVAL); + assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL); + assert_return(options != 0, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + r = hashmap_ensure_allocated(&e->child_sources, NULL); + if (r < 0) + return r; + + if (hashmap_contains(e->child_sources, PID_TO_PTR(pid))) + return -EBUSY; + + s = source_new(e, !ret, SOURCE_CHILD); + if (!s) + return -ENOMEM; + + s->child.pid = pid; + s->child.options = options; + s->child.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ONESHOT; + + r = hashmap_put(e->child_sources, PID_TO_PTR(pid), s); + if (r < 0) + return r; + + e->n_enabled_child_sources++; + + r = event_make_signal_data(e, SIGCHLD, NULL); + if (r < 0) { + e->n_enabled_child_sources--; + return r; + } + + e->need_process_child = true; + + if (ret) + *ret = s; + TAKE_PTR(s); + + return 0; +} + +_public_ int sd_event_add_defer( + sd_event *e, + sd_event_source **ret, + sd_event_handler_t callback, + void *userdata) { + + _cleanup_(source_freep) sd_event_source *s = NULL; + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + s = source_new(e, !ret, SOURCE_DEFER); + if (!s) + return -ENOMEM; + + s->defer.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ONESHOT; + + r = source_set_pending(s, true); + if (r < 0) + return r; + + if (ret) + *ret = s; + TAKE_PTR(s); + + return 0; +} + +_public_ int sd_event_add_post( + sd_event *e, + sd_event_source **ret, + sd_event_handler_t callback, + void *userdata) { + + _cleanup_(source_freep) sd_event_source *s = NULL; + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + r = set_ensure_allocated(&e->post_sources, NULL); + if (r < 0) + return r; + + s = source_new(e, !ret, SOURCE_POST); + if (!s) + return -ENOMEM; + + s->post.callback = callback; + s->userdata = userdata; + s->enabled = SD_EVENT_ON; + + r = set_put(e->post_sources, s); + if (r < 0) + return r; + + if (ret) + *ret = s; + TAKE_PTR(s); + + return 0; +} + +_public_ int sd_event_add_exit( + sd_event *e, + sd_event_source **ret, + sd_event_handler_t callback, + void *userdata) { + + _cleanup_(source_freep) sd_event_source *s = NULL; + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + r = prioq_ensure_allocated(&e->exit, exit_prioq_compare); + if (r < 0) + return r; + + s = source_new(e, !ret, SOURCE_EXIT); + if (!s) + return -ENOMEM; + + s->exit.callback = callback; + s->userdata = userdata; + s->exit.prioq_index = PRIOQ_IDX_NULL; + s->enabled = SD_EVENT_ONESHOT; + + r = prioq_put(s->event->exit, s, &s->exit.prioq_index); + if (r < 0) + return r; + + if (ret) + *ret = s; + TAKE_PTR(s); + + return 0; +} + +static void event_free_inotify_data(sd_event *e, struct inotify_data *d) { + assert(e); + + if (!d) + return; + + assert(hashmap_isempty(d->inodes)); + assert(hashmap_isempty(d->wd)); + + if (d->buffer_filled > 0) + LIST_REMOVE(buffered, e->inotify_data_buffered, d); + + hashmap_free(d->inodes); + hashmap_free(d->wd); + + assert_se(hashmap_remove(e->inotify_data, &d->priority) == d); + + if (d->fd >= 0) { + if (epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, d->fd, NULL) < 0) + log_debug_errno(errno, "Failed to remove inotify fd from epoll, ignoring: %m"); + + safe_close(d->fd); + } + free(d); +} + +static int event_make_inotify_data( + sd_event *e, + int64_t priority, + struct inotify_data **ret) { + + _cleanup_close_ int fd = -1; + struct inotify_data *d; + struct epoll_event ev; + int r; + + assert(e); + + d = hashmap_get(e->inotify_data, &priority); + if (d) { + if (ret) + *ret = d; + return 0; + } + + fd = inotify_init1(IN_NONBLOCK|O_CLOEXEC); + if (fd < 0) + return -errno; + + fd = fd_move_above_stdio(fd); + + r = hashmap_ensure_allocated(&e->inotify_data, &uint64_hash_ops); + if (r < 0) + return r; + + d = new(struct inotify_data, 1); + if (!d) + return -ENOMEM; + + *d = (struct inotify_data) { + .wakeup = WAKEUP_INOTIFY_DATA, + .fd = TAKE_FD(fd), + .priority = priority, + }; + + r = hashmap_put(e->inotify_data, &d->priority, d); + if (r < 0) { + d->fd = safe_close(d->fd); + free(d); + return r; + } + + ev = (struct epoll_event) { + .events = EPOLLIN, + .data.ptr = d, + }; + + if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev) < 0) { + r = -errno; + d->fd = safe_close(d->fd); /* let's close this ourselves, as event_free_inotify_data() would otherwise + * remove the fd from the epoll first, which we don't want as we couldn't + * add it in the first place. */ + event_free_inotify_data(e, d); + return r; + } + + if (ret) + *ret = d; + + return 1; +} + +static int inode_data_compare(const struct inode_data *x, const struct inode_data *y) { + int r; + + assert(x); + assert(y); + + r = CMP(x->dev, y->dev); + if (r != 0) + return r; + + return CMP(x->ino, y->ino); +} + +static void inode_data_hash_func(const struct inode_data *d, struct siphash *state) { + assert(d); + + siphash24_compress(&d->dev, sizeof(d->dev), state); + siphash24_compress(&d->ino, sizeof(d->ino), state); +} + +DEFINE_PRIVATE_HASH_OPS(inode_data_hash_ops, struct inode_data, inode_data_hash_func, inode_data_compare); + +static void event_free_inode_data( + sd_event *e, + struct inode_data *d) { + + assert(e); + + if (!d) + return; + + assert(!d->event_sources); + + if (d->fd >= 0) { + LIST_REMOVE(to_close, e->inode_data_to_close, d); + safe_close(d->fd); + } + + if (d->inotify_data) { + + if (d->wd >= 0) { + if (d->inotify_data->fd >= 0) { + /* So here's a problem. At the time this runs the watch descriptor might already be + * invalidated, because an IN_IGNORED event might be queued right the moment we enter + * the syscall. Hence, whenever we get EINVAL, ignore it entirely, since it's a very + * likely case to happen. */ + + if (inotify_rm_watch(d->inotify_data->fd, d->wd) < 0 && errno != EINVAL) + log_debug_errno(errno, "Failed to remove watch descriptor %i from inotify, ignoring: %m", d->wd); + } + + assert_se(hashmap_remove(d->inotify_data->wd, INT_TO_PTR(d->wd)) == d); + } + + assert_se(hashmap_remove(d->inotify_data->inodes, d) == d); + } + + free(d); +} + +static void event_gc_inode_data( + sd_event *e, + struct inode_data *d) { + + struct inotify_data *inotify_data; + + assert(e); + + if (!d) + return; + + if (d->event_sources) + return; + + inotify_data = d->inotify_data; + event_free_inode_data(e, d); + + if (inotify_data && hashmap_isempty(inotify_data->inodes)) + event_free_inotify_data(e, inotify_data); +} + +static int event_make_inode_data( + sd_event *e, + struct inotify_data *inotify_data, + dev_t dev, + ino_t ino, + struct inode_data **ret) { + + struct inode_data *d, key; + int r; + + assert(e); + assert(inotify_data); + + key = (struct inode_data) { + .ino = ino, + .dev = dev, + }; + + d = hashmap_get(inotify_data->inodes, &key); + if (d) { + if (ret) + *ret = d; + + return 0; + } + + r = hashmap_ensure_allocated(&inotify_data->inodes, &inode_data_hash_ops); + if (r < 0) + return r; + + d = new(struct inode_data, 1); + if (!d) + return -ENOMEM; + + *d = (struct inode_data) { + .dev = dev, + .ino = ino, + .wd = -1, + .fd = -1, + .inotify_data = inotify_data, + }; + + r = hashmap_put(inotify_data->inodes, d, d); + if (r < 0) { + free(d); + return r; + } + + if (ret) + *ret = d; + + return 1; +} + +static uint32_t inode_data_determine_mask(struct inode_data *d) { + bool excl_unlink = true; + uint32_t combined = 0; + sd_event_source *s; + + assert(d); + + /* Combines the watch masks of all event sources watching this inode. We generally just OR them together, but + * the IN_EXCL_UNLINK flag is ANDed instead. + * + * Note that we add all sources to the mask here, regardless whether enabled, disabled or oneshot. That's + * because we cannot change the mask anymore after the event source was created once, since the kernel has no + * API for that. Hence we need to subscribe to the maximum mask we ever might be interested in, and suppress + * events we don't care for client-side. */ + + LIST_FOREACH(inotify.by_inode_data, s, d->event_sources) { + + if ((s->inotify.mask & IN_EXCL_UNLINK) == 0) + excl_unlink = false; + + combined |= s->inotify.mask; + } + + return (combined & ~(IN_ONESHOT|IN_DONT_FOLLOW|IN_ONLYDIR|IN_EXCL_UNLINK)) | (excl_unlink ? IN_EXCL_UNLINK : 0); +} + +static int inode_data_realize_watch(sd_event *e, struct inode_data *d) { + uint32_t combined_mask; + int wd, r; + + assert(d); + assert(d->fd >= 0); + + combined_mask = inode_data_determine_mask(d); + + if (d->wd >= 0 && combined_mask == d->combined_mask) + return 0; + + r = hashmap_ensure_allocated(&d->inotify_data->wd, NULL); + if (r < 0) + return r; + + wd = inotify_add_watch_fd(d->inotify_data->fd, d->fd, combined_mask); + if (wd < 0) + return -errno; + + if (d->wd < 0) { + r = hashmap_put(d->inotify_data->wd, INT_TO_PTR(wd), d); + if (r < 0) { + (void) inotify_rm_watch(d->inotify_data->fd, wd); + return r; + } + + d->wd = wd; + + } else if (d->wd != wd) { + + log_debug("Weird, the watch descriptor we already knew for this inode changed?"); + (void) inotify_rm_watch(d->fd, wd); + return -EINVAL; + } + + d->combined_mask = combined_mask; + return 1; +} + +_public_ int sd_event_add_inotify( + sd_event *e, + sd_event_source **ret, + const char *path, + uint32_t mask, + sd_event_inotify_handler_t callback, + void *userdata) { + + struct inotify_data *inotify_data = NULL; + struct inode_data *inode_data = NULL; + _cleanup_close_ int fd = -1; + _cleanup_(source_freep) sd_event_source *s = NULL; + struct stat st; + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(path, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + /* Refuse IN_MASK_ADD since we coalesce watches on the same inode, and hence really don't want to merge + * masks. Or in other words, this whole code exists only to manage IN_MASK_ADD type operations for you, hence + * the user can't use them for us. */ + if (mask & IN_MASK_ADD) + return -EINVAL; + + fd = open(path, O_PATH|O_CLOEXEC| + (mask & IN_ONLYDIR ? O_DIRECTORY : 0)| + (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0)); + if (fd < 0) + return -errno; + + if (fstat(fd, &st) < 0) + return -errno; + + s = source_new(e, !ret, SOURCE_INOTIFY); + if (!s) + return -ENOMEM; + + s->enabled = mask & IN_ONESHOT ? SD_EVENT_ONESHOT : SD_EVENT_ON; + s->inotify.mask = mask; + s->inotify.callback = callback; + s->userdata = userdata; + + /* Allocate an inotify object for this priority, and an inode object within it */ + r = event_make_inotify_data(e, SD_EVENT_PRIORITY_NORMAL, &inotify_data); + if (r < 0) + return r; + + r = event_make_inode_data(e, inotify_data, st.st_dev, st.st_ino, &inode_data); + if (r < 0) { + event_free_inotify_data(e, inotify_data); + return r; + } + + /* Keep the O_PATH fd around until the first iteration of the loop, so that we can still change the priority of + * the event source, until then, for which we need the original inode. */ + if (inode_data->fd < 0) { + inode_data->fd = TAKE_FD(fd); + LIST_PREPEND(to_close, e->inode_data_to_close, inode_data); + } + + /* Link our event source to the inode data object */ + LIST_PREPEND(inotify.by_inode_data, inode_data->event_sources, s); + s->inotify.inode_data = inode_data; + + /* Actually realize the watch now */ + r = inode_data_realize_watch(e, inode_data); + if (r < 0) + return r; + + (void) sd_event_source_set_description(s, path); + + if (ret) + *ret = s; + TAKE_PTR(s); + + return 0; +} + +static sd_event_source* event_source_free(sd_event_source *s) { + if (!s) + return NULL; + + /* Here's a special hack: when we are called from a + * dispatch handler we won't free the event source + * immediately, but we will detach the fd from the + * epoll. This way it is safe for the caller to unref + * the event source and immediately close the fd, but + * we still retain a valid event source object after + * the callback. */ + + if (s->dispatching) { + if (s->type == SOURCE_IO) + source_io_unregister(s); + + source_disconnect(s); + } else + source_free(s); + + return NULL; +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event_source, sd_event_source, event_source_free); + +_public_ int sd_event_source_set_description(sd_event_source *s, const char *description) { + assert_return(s, -EINVAL); + assert_return(!event_pid_changed(s->event), -ECHILD); + + return free_and_strdup(&s->description, description); +} + +_public_ int sd_event_source_get_description(sd_event_source *s, const char **description) { + assert_return(s, -EINVAL); + assert_return(description, -EINVAL); + assert_return(!event_pid_changed(s->event), -ECHILD); + + if (!s->description) + return -ENXIO; + + *description = s->description; + return 0; +} + +_public_ sd_event *sd_event_source_get_event(sd_event_source *s) { + assert_return(s, NULL); + + return s->event; +} + +_public_ int sd_event_source_get_pending(sd_event_source *s) { + assert_return(s, -EINVAL); + assert_return(s->type != SOURCE_EXIT, -EDOM); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + return s->pending; +} + +_public_ int sd_event_source_get_io_fd(sd_event_source *s) { + assert_return(s, -EINVAL); + assert_return(s->type == SOURCE_IO, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + return s->io.fd; +} + +_public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { + int r; + + assert_return(s, -EINVAL); + assert_return(fd >= 0, -EBADF); + assert_return(s->type == SOURCE_IO, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + if (s->io.fd == fd) + return 0; + + if (s->enabled == SD_EVENT_OFF) { + s->io.fd = fd; + s->io.registered = false; + } else { + int saved_fd; + + saved_fd = s->io.fd; + assert(s->io.registered); + + s->io.fd = fd; + s->io.registered = false; + + r = source_io_register(s, s->enabled, s->io.events); + if (r < 0) { + s->io.fd = saved_fd; + s->io.registered = true; + return r; + } + + epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, saved_fd, NULL); + } + + return 0; +} + +_public_ int sd_event_source_get_io_fd_own(sd_event_source *s) { + assert_return(s, -EINVAL); + assert_return(s->type == SOURCE_IO, -EDOM); + + return s->io.owned; +} + +_public_ int sd_event_source_set_io_fd_own(sd_event_source *s, int own) { + assert_return(s, -EINVAL); + assert_return(s->type == SOURCE_IO, -EDOM); + + s->io.owned = own; + return 0; +} + +_public_ int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events) { + assert_return(s, -EINVAL); + assert_return(events, -EINVAL); + assert_return(s->type == SOURCE_IO, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *events = s->io.events; + return 0; +} + +_public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) { + int r; + + assert_return(s, -EINVAL); + assert_return(s->type == SOURCE_IO, -EDOM); + assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + /* edge-triggered updates are never skipped, so we can reset edges */ + if (s->io.events == events && !(events & EPOLLET)) + return 0; + + r = source_set_pending(s, false); + if (r < 0) + return r; + + if (s->enabled != SD_EVENT_OFF) { + r = source_io_register(s, s->enabled, events); + if (r < 0) + return r; + } + + s->io.events = events; + + return 0; +} + +_public_ int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents) { + assert_return(s, -EINVAL); + assert_return(revents, -EINVAL); + assert_return(s->type == SOURCE_IO, -EDOM); + assert_return(s->pending, -ENODATA); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *revents = s->io.revents; + return 0; +} + +_public_ int sd_event_source_get_signal(sd_event_source *s) { + assert_return(s, -EINVAL); + assert_return(s->type == SOURCE_SIGNAL, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + return s->signal.sig; +} + +_public_ int sd_event_source_get_priority(sd_event_source *s, int64_t *priority) { + assert_return(s, -EINVAL); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *priority = s->priority; + return 0; +} + +_public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) { + bool rm_inotify = false, rm_inode = false; + struct inotify_data *new_inotify_data = NULL; + struct inode_data *new_inode_data = NULL; + int r; + + assert_return(s, -EINVAL); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + if (s->priority == priority) + return 0; + + if (s->type == SOURCE_INOTIFY) { + struct inode_data *old_inode_data; + + assert(s->inotify.inode_data); + old_inode_data = s->inotify.inode_data; + + /* We need the original fd to change the priority. If we don't have it we can't change the priority, + * anymore. Note that we close any fds when entering the next event loop iteration, i.e. for inotify + * events we allow priority changes only until the first following iteration. */ + if (old_inode_data->fd < 0) + return -EOPNOTSUPP; + + r = event_make_inotify_data(s->event, priority, &new_inotify_data); + if (r < 0) + return r; + rm_inotify = r > 0; + + r = event_make_inode_data(s->event, new_inotify_data, old_inode_data->dev, old_inode_data->ino, &new_inode_data); + if (r < 0) + goto fail; + rm_inode = r > 0; + + if (new_inode_data->fd < 0) { + /* Duplicate the fd for the new inode object if we don't have any yet */ + new_inode_data->fd = fcntl(old_inode_data->fd, F_DUPFD_CLOEXEC, 3); + if (new_inode_data->fd < 0) { + r = -errno; + goto fail; + } + + LIST_PREPEND(to_close, s->event->inode_data_to_close, new_inode_data); + } + + /* Move the event source to the new inode data structure */ + LIST_REMOVE(inotify.by_inode_data, old_inode_data->event_sources, s); + LIST_PREPEND(inotify.by_inode_data, new_inode_data->event_sources, s); + s->inotify.inode_data = new_inode_data; + + /* Now create the new watch */ + r = inode_data_realize_watch(s->event, new_inode_data); + if (r < 0) { + /* Move it back */ + LIST_REMOVE(inotify.by_inode_data, new_inode_data->event_sources, s); + LIST_PREPEND(inotify.by_inode_data, old_inode_data->event_sources, s); + s->inotify.inode_data = old_inode_data; + goto fail; + } + + s->priority = priority; + + event_gc_inode_data(s->event, old_inode_data); + + } else if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) { + struct signal_data *old, *d; + + /* Move us from the signalfd belonging to the old + * priority to the signalfd of the new priority */ + + assert_se(old = hashmap_get(s->event->signal_data, &s->priority)); + + s->priority = priority; + + r = event_make_signal_data(s->event, s->signal.sig, &d); + if (r < 0) { + s->priority = old->priority; + return r; + } + + event_unmask_signal_data(s->event, old, s->signal.sig); + } else + s->priority = priority; + + if (s->pending) + prioq_reshuffle(s->event->pending, s, &s->pending_index); + + if (s->prepare) + prioq_reshuffle(s->event->prepare, s, &s->prepare_index); + + if (s->type == SOURCE_EXIT) + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); + + return 0; + +fail: + if (rm_inode) + event_free_inode_data(s->event, new_inode_data); + + if (rm_inotify) + event_free_inotify_data(s->event, new_inotify_data); + + return r; +} + +_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) { + assert_return(s, -EINVAL); + assert_return(!event_pid_changed(s->event), -ECHILD); + + if (m) + *m = s->enabled; + return s->enabled != SD_EVENT_OFF; +} + +_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { + int r; + + assert_return(s, -EINVAL); + assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL); + assert_return(!event_pid_changed(s->event), -ECHILD); + + /* If we are dead anyway, we are fine with turning off + * sources, but everything else needs to fail. */ + if (s->event->state == SD_EVENT_FINISHED) + return m == SD_EVENT_OFF ? 0 : -ESTALE; + + if (s->enabled == m) + return 0; + + if (m == SD_EVENT_OFF) { + + /* Unset the pending flag when this event source is disabled */ + if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { + r = source_set_pending(s, false); + if (r < 0) + return r; + } + + switch (s->type) { + + case SOURCE_IO: + source_io_unregister(s); + s->enabled = m; + break; + + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: { + struct clock_data *d; + + s->enabled = m; + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + break; + } + + case SOURCE_SIGNAL: + s->enabled = m; + + event_gc_signal_data(s->event, &s->priority, s->signal.sig); + break; + + case SOURCE_CHILD: + s->enabled = m; + + assert(s->event->n_enabled_child_sources > 0); + s->event->n_enabled_child_sources--; + + event_gc_signal_data(s->event, &s->priority, SIGCHLD); + break; + + case SOURCE_EXIT: + s->enabled = m; + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); + break; + + case SOURCE_DEFER: + case SOURCE_POST: + case SOURCE_INOTIFY: + s->enabled = m; + break; + + default: + assert_not_reached("Wut? I shouldn't exist."); + } + + } else { + + /* Unset the pending flag when this event source is enabled */ + if (s->enabled == SD_EVENT_OFF && !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { + r = source_set_pending(s, false); + if (r < 0) + return r; + } + + switch (s->type) { + + case SOURCE_IO: + r = source_io_register(s, m, s->io.events); + if (r < 0) + return r; + + s->enabled = m; + break; + + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: { + struct clock_data *d; + + s->enabled = m; + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + break; + } + + case SOURCE_SIGNAL: + + s->enabled = m; + + r = event_make_signal_data(s->event, s->signal.sig, NULL); + if (r < 0) { + s->enabled = SD_EVENT_OFF; + event_gc_signal_data(s->event, &s->priority, s->signal.sig); + return r; + } + + break; + + case SOURCE_CHILD: + + if (s->enabled == SD_EVENT_OFF) + s->event->n_enabled_child_sources++; + + s->enabled = m; + + r = event_make_signal_data(s->event, SIGCHLD, NULL); + if (r < 0) { + s->enabled = SD_EVENT_OFF; + s->event->n_enabled_child_sources--; + event_gc_signal_data(s->event, &s->priority, SIGCHLD); + return r; + } + + break; + + case SOURCE_EXIT: + s->enabled = m; + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); + break; + + case SOURCE_DEFER: + case SOURCE_POST: + case SOURCE_INOTIFY: + s->enabled = m; + break; + + default: + assert_not_reached("Wut? I shouldn't exist."); + } + } + + if (s->pending) + prioq_reshuffle(s->event->pending, s, &s->pending_index); + + if (s->prepare) + prioq_reshuffle(s->event->prepare, s, &s->prepare_index); + + return 0; +} + +_public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) { + assert_return(s, -EINVAL); + assert_return(usec, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *usec = s->time.next; + return 0; +} + +_public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { + struct clock_data *d; + int r; + + assert_return(s, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + r = source_set_pending(s, false); + if (r < 0) + return r; + + s->time.next = usec; + + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + + return 0; +} + +_public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec) { + assert_return(s, -EINVAL); + assert_return(usec, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *usec = s->time.accuracy; + return 0; +} + +_public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) { + struct clock_data *d; + int r; + + assert_return(s, -EINVAL); + assert_return(usec != (uint64_t) -1, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + r = source_set_pending(s, false); + if (r < 0) + return r; + + if (usec == 0) + usec = DEFAULT_ACCURACY_USEC; + + s->time.accuracy = usec; + + d = event_get_clock_data(s->event, s->type); + assert(d); + + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + + return 0; +} + +_public_ int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock) { + assert_return(s, -EINVAL); + assert_return(clock, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *clock = event_source_type_to_clock(s->type); + return 0; +} + +_public_ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid) { + assert_return(s, -EINVAL); + assert_return(pid, -EINVAL); + assert_return(s->type == SOURCE_CHILD, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *pid = s->child.pid; + return 0; +} + +_public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *mask) { + assert_return(s, -EINVAL); + assert_return(mask, -EINVAL); + assert_return(s->type == SOURCE_INOTIFY, -EDOM); + assert_return(!event_pid_changed(s->event), -ECHILD); + + *mask = s->inotify.mask; + return 0; +} + +_public_ int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback) { + int r; + + assert_return(s, -EINVAL); + assert_return(s->type != SOURCE_EXIT, -EDOM); + assert_return(s->event->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(s->event), -ECHILD); + + if (s->prepare == callback) + return 0; + + if (callback && s->prepare) { + s->prepare = callback; + return 0; + } + + r = prioq_ensure_allocated(&s->event->prepare, prepare_prioq_compare); + if (r < 0) + return r; + + s->prepare = callback; + + if (callback) { + r = prioq_put(s->event->prepare, s, &s->prepare_index); + if (r < 0) + return r; + } else + prioq_remove(s->event->prepare, s, &s->prepare_index); + + return 0; +} + +_public_ void* sd_event_source_get_userdata(sd_event_source *s) { + assert_return(s, NULL); + + return s->userdata; +} + +_public_ void *sd_event_source_set_userdata(sd_event_source *s, void *userdata) { + void *ret; + + assert_return(s, NULL); + + ret = s->userdata; + s->userdata = userdata; + + return ret; +} + +static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) { + usec_t c; + assert(e); + assert(a <= b); + + if (a <= 0) + return 0; + if (a >= USEC_INFINITY) + return USEC_INFINITY; + + if (b <= a + 1) + return a; + + initialize_perturb(e); + + /* + Find a good time to wake up again between times a and b. We + have two goals here: + + a) We want to wake up as seldom as possible, hence prefer + later times over earlier times. + + b) But if we have to wake up, then let's make sure to + dispatch as much as possible on the entire system. + + We implement this by waking up everywhere at the same time + within any given minute if we can, synchronised via the + perturbation value determined from the boot ID. If we can't, + then we try to find the same spot in every 10s, then 1s and + then 250ms step. Otherwise, we pick the last possible time + to wake up. + */ + + c = (b / USEC_PER_MINUTE) * USEC_PER_MINUTE + e->perturb; + if (c >= b) { + if (_unlikely_(c < USEC_PER_MINUTE)) + return b; + + c -= USEC_PER_MINUTE; + } + + if (c >= a) + return c; + + c = (b / (USEC_PER_SEC*10)) * (USEC_PER_SEC*10) + (e->perturb % (USEC_PER_SEC*10)); + if (c >= b) { + if (_unlikely_(c < USEC_PER_SEC*10)) + return b; + + c -= USEC_PER_SEC*10; + } + + if (c >= a) + return c; + + c = (b / USEC_PER_SEC) * USEC_PER_SEC + (e->perturb % USEC_PER_SEC); + if (c >= b) { + if (_unlikely_(c < USEC_PER_SEC)) + return b; + + c -= USEC_PER_SEC; + } + + if (c >= a) + return c; + + c = (b / (USEC_PER_MSEC*250)) * (USEC_PER_MSEC*250) + (e->perturb % (USEC_PER_MSEC*250)); + if (c >= b) { + if (_unlikely_(c < USEC_PER_MSEC*250)) + return b; + + c -= USEC_PER_MSEC*250; + } + + if (c >= a) + return c; + + return b; +} + +static int event_arm_timer( + sd_event *e, + struct clock_data *d) { + + struct itimerspec its = {}; + sd_event_source *a, *b; + usec_t t; + int r; + + assert(e); + assert(d); + + if (!d->needs_rearm) + return 0; + else + d->needs_rearm = false; + + a = prioq_peek(d->earliest); + if (!a || a->enabled == SD_EVENT_OFF || a->time.next == USEC_INFINITY) { + + if (d->fd < 0) + return 0; + + if (d->next == USEC_INFINITY) + return 0; + + /* disarm */ + r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL); + if (r < 0) + return r; + + d->next = USEC_INFINITY; + return 0; + } + + b = prioq_peek(d->latest); + assert_se(b && b->enabled != SD_EVENT_OFF); + + t = sleep_between(e, a->time.next, time_event_source_latest(b)); + if (d->next == t) + return 0; + + assert_se(d->fd >= 0); + + if (t == 0) { + /* We don' want to disarm here, just mean some time looooong ago. */ + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 1; + } else + timespec_store(&its.it_value, t); + + r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL); + if (r < 0) + return -errno; + + d->next = t; + return 0; +} + +static int process_io(sd_event *e, sd_event_source *s, uint32_t revents) { + assert(e); + assert(s); + assert(s->type == SOURCE_IO); + + /* If the event source was already pending, we just OR in the + * new revents, otherwise we reset the value. The ORing is + * necessary to handle EPOLLONESHOT events properly where + * readability might happen independently of writability, and + * we need to keep track of both */ + + if (s->pending) + s->io.revents |= revents; + else + s->io.revents = revents; + + return source_set_pending(s, true); +} + +static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) { + uint64_t x; + ssize_t ss; + + assert(e); + assert(fd >= 0); + + assert_return(events == EPOLLIN, -EIO); + + ss = read(fd, &x, sizeof(x)); + if (ss < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + return -errno; + } + + if (_unlikely_(ss != sizeof(x))) + return -EIO; + + if (next) + *next = USEC_INFINITY; + + return 0; +} + +static int process_timer( + sd_event *e, + usec_t n, + struct clock_data *d) { + + sd_event_source *s; + int r; + + assert(e); + assert(d); + + for (;;) { + s = prioq_peek(d->earliest); + if (!s || + s->time.next > n || + s->enabled == SD_EVENT_OFF || + s->pending) + break; + + r = source_set_pending(s, true); + if (r < 0) + return r; + + prioq_reshuffle(d->earliest, s, &s->time.earliest_index); + prioq_reshuffle(d->latest, s, &s->time.latest_index); + d->needs_rearm = true; + } + + return 0; +} + +static int process_child(sd_event *e) { + sd_event_source *s; + Iterator i; + int r; + + assert(e); + + e->need_process_child = false; + + /* + So, this is ugly. We iteratively invoke waitid() with P_PID + + WNOHANG for each PID we wait for, instead of using + P_ALL. This is because we only want to get child + information of very specific child processes, and not all + of them. We might not have processed the SIGCHLD even of a + previous invocation and we don't want to maintain a + unbounded *per-child* event queue, hence we really don't + want anything flushed out of the kernel's queue that we + don't care about. Since this is O(n) this means that if you + have a lot of processes you probably want to handle SIGCHLD + yourself. + + We do not reap the children here (by using WNOWAIT), this + is only done after the event source is dispatched so that + the callback still sees the process as a zombie. + */ + + HASHMAP_FOREACH(s, e->child_sources, i) { + assert(s->type == SOURCE_CHILD); + + if (s->pending) + continue; + + if (s->enabled == SD_EVENT_OFF) + continue; + + zero(s->child.siginfo); + r = waitid(P_PID, s->child.pid, &s->child.siginfo, + WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options); + if (r < 0) + return -errno; + + if (s->child.siginfo.si_pid != 0) { + bool zombie = IN_SET(s->child.siginfo.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED); + + if (!zombie && (s->child.options & WEXITED)) { + /* If the child isn't dead then let's + * immediately remove the state change + * from the queue, since there's no + * benefit in leaving it queued */ + + assert(s->child.options & (WSTOPPED|WCONTINUED)); + (void) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED))); + } + + r = source_set_pending(s, true); + if (r < 0) + return r; + } + } + + return 0; +} + +static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { + bool read_one = false; + int r; + + assert(e); + assert(d); + assert_return(events == EPOLLIN, -EIO); + + /* If there's a signal queued on this priority and SIGCHLD is + on this priority too, then make sure to recheck the + children we watch. This is because we only ever dequeue + the first signal per priority, and if we dequeue one, and + SIGCHLD might be enqueued later we wouldn't know, but we + might have higher priority children we care about hence we + need to check that explicitly. */ + + if (sigismember(&d->sigset, SIGCHLD)) + e->need_process_child = true; + + /* If there's already an event source pending for this + * priority we don't read another */ + if (d->current) + return 0; + + for (;;) { + struct signalfd_siginfo si; + ssize_t n; + sd_event_source *s = NULL; + + n = read(d->fd, &si, sizeof(si)); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return read_one; + + return -errno; + } + + if (_unlikely_(n != sizeof(si))) + return -EIO; + + assert(SIGNAL_VALID(si.ssi_signo)); + + read_one = true; + + if (e->signal_sources) + s = e->signal_sources[si.ssi_signo]; + if (!s) + continue; + if (s->pending) + continue; + + s->signal.siginfo = si; + d->current = s; + + r = source_set_pending(s, true); + if (r < 0) + return r; + + return 1; + } +} + +static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t revents) { + ssize_t n; + + assert(e); + assert(d); + + assert_return(revents == EPOLLIN, -EIO); + + /* If there's already an event source pending for this priority, don't read another */ + if (d->n_pending > 0) + return 0; + + /* Is the read buffer non-empty? If so, let's not read more */ + if (d->buffer_filled > 0) + return 0; + + n = read(d->fd, &d->buffer, sizeof(d->buffer)); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + return -errno; + } + + assert(n > 0); + d->buffer_filled = (size_t) n; + LIST_PREPEND(buffered, e->inotify_data_buffered, d); + + return 1; +} + +static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t sz) { + assert(e); + assert(d); + assert(sz <= d->buffer_filled); + + if (sz == 0) + return; + + /* Move the rest to the buffer to the front, in order to get things properly aligned again */ + memmove(d->buffer.raw, d->buffer.raw + sz, d->buffer_filled - sz); + d->buffer_filled -= sz; + + if (d->buffer_filled == 0) + LIST_REMOVE(buffered, e->inotify_data_buffered, d); +} + +static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { + int r; + + assert(e); + assert(d); + + /* If there's already an event source pending for this priority, don't read another */ + if (d->n_pending > 0) + return 0; + + while (d->buffer_filled > 0) { + size_t sz; + + /* Let's validate that the event structures are complete */ + if (d->buffer_filled < offsetof(struct inotify_event, name)) + return -EIO; + + sz = offsetof(struct inotify_event, name) + d->buffer.ev.len; + if (d->buffer_filled < sz) + return -EIO; + + if (d->buffer.ev.mask & IN_Q_OVERFLOW) { + struct inode_data *inode_data; + Iterator i; + + /* The queue overran, let's pass this event to all event sources connected to this inotify + * object */ + + HASHMAP_FOREACH(inode_data, d->inodes, i) { + sd_event_source *s; + + LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { + + if (s->enabled == SD_EVENT_OFF) + continue; + + r = source_set_pending(s, true); + if (r < 0) + return r; + } + } + } else { + struct inode_data *inode_data; + sd_event_source *s; + + /* Find the inode object for this watch descriptor. If IN_IGNORED is set we also remove it from + * our watch descriptor table. */ + if (d->buffer.ev.mask & IN_IGNORED) { + + inode_data = hashmap_remove(d->wd, INT_TO_PTR(d->buffer.ev.wd)); + if (!inode_data) { + event_inotify_data_drop(e, d, sz); + continue; + } + + /* The watch descriptor was removed by the kernel, let's drop it here too */ + inode_data->wd = -1; + } else { + inode_data = hashmap_get(d->wd, INT_TO_PTR(d->buffer.ev.wd)); + if (!inode_data) { + event_inotify_data_drop(e, d, sz); + continue; + } + } + + /* Trigger all event sources that are interested in these events. Also trigger all event + * sources if IN_IGNORED or IN_UNMOUNT is set. */ + LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { + + if (s->enabled == SD_EVENT_OFF) + continue; + + if ((d->buffer.ev.mask & (IN_IGNORED|IN_UNMOUNT)) == 0 && + (s->inotify.mask & d->buffer.ev.mask & IN_ALL_EVENTS) == 0) + continue; + + r = source_set_pending(s, true); + if (r < 0) + return r; + } + } + + /* Something pending now? If so, let's finish, otherwise let's read more. */ + if (d->n_pending > 0) + return 1; + } + + return 0; +} + +static int process_inotify(sd_event *e) { + struct inotify_data *d; + int r, done = 0; + + assert(e); + + LIST_FOREACH(buffered, d, e->inotify_data_buffered) { + r = event_inotify_data_process(e, d); + if (r < 0) + return r; + if (r > 0) + done ++; + } + + return done; +} + +static int source_dispatch(sd_event_source *s) { + EventSourceType saved_type; + int r = 0; + + assert(s); + assert(s->pending || s->type == SOURCE_EXIT); + + /* Save the event source type, here, so that we still know it after the event callback which might invalidate + * the event. */ + saved_type = s->type; + + if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { + r = source_set_pending(s, false); + if (r < 0) + return r; + } + + if (s->type != SOURCE_POST) { + sd_event_source *z; + Iterator i; + + /* If we execute a non-post source, let's mark all + * post sources as pending */ + + SET_FOREACH(z, s->event->post_sources, i) { + if (z->enabled == SD_EVENT_OFF) + continue; + + r = source_set_pending(z, true); + if (r < 0) + return r; + } + } + + if (s->enabled == SD_EVENT_ONESHOT) { + r = sd_event_source_set_enabled(s, SD_EVENT_OFF); + if (r < 0) + return r; + } + + s->dispatching = true; + + switch (s->type) { + + case SOURCE_IO: + r = s->io.callback(s, s->io.fd, s->io.revents, s->userdata); + break; + + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: + r = s->time.callback(s, s->time.next, s->userdata); + break; + + case SOURCE_SIGNAL: + r = s->signal.callback(s, &s->signal.siginfo, s->userdata); + break; + + case SOURCE_CHILD: { + bool zombie; + + zombie = IN_SET(s->child.siginfo.si_code, CLD_EXITED, CLD_KILLED, CLD_DUMPED); + + r = s->child.callback(s, &s->child.siginfo, s->userdata); + + /* Now, reap the PID for good. */ + if (zombie) + (void) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|WEXITED); + + break; + } + + case SOURCE_DEFER: + r = s->defer.callback(s, s->userdata); + break; + + case SOURCE_POST: + r = s->post.callback(s, s->userdata); + break; + + case SOURCE_EXIT: + r = s->exit.callback(s, s->userdata); + break; + + case SOURCE_INOTIFY: { + struct sd_event *e = s->event; + struct inotify_data *d; + size_t sz; + + assert(s->inotify.inode_data); + assert_se(d = s->inotify.inode_data->inotify_data); + + assert(d->buffer_filled >= offsetof(struct inotify_event, name)); + sz = offsetof(struct inotify_event, name) + d->buffer.ev.len; + assert(d->buffer_filled >= sz); + + r = s->inotify.callback(s, &d->buffer.ev, s->userdata); + + /* When no event is pending anymore on this inotify object, then let's drop the event from the + * buffer. */ + if (d->n_pending == 0) + event_inotify_data_drop(e, d, sz); + + break; + } + + case SOURCE_WATCHDOG: + case _SOURCE_EVENT_SOURCE_TYPE_MAX: + case _SOURCE_EVENT_SOURCE_TYPE_INVALID: + assert_not_reached("Wut? I shouldn't exist."); + } + + s->dispatching = false; + + if (r < 0) + log_debug_errno(r, "Event source %s (type %s) returned error, disabling: %m", + strna(s->description), event_source_type_to_string(saved_type)); + + if (s->n_ref == 0) + source_free(s); + else if (r < 0) + sd_event_source_set_enabled(s, SD_EVENT_OFF); + + return 1; +} + +static int event_prepare(sd_event *e) { + int r; + + assert(e); + + for (;;) { + sd_event_source *s; + + s = prioq_peek(e->prepare); + if (!s || s->prepare_iteration == e->iteration || s->enabled == SD_EVENT_OFF) + break; + + s->prepare_iteration = e->iteration; + r = prioq_reshuffle(e->prepare, s, &s->prepare_index); + if (r < 0) + return r; + + assert(s->prepare); + + s->dispatching = true; + r = s->prepare(s, s->userdata); + s->dispatching = false; + + if (r < 0) + log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, disabling: %m", + strna(s->description), event_source_type_to_string(s->type)); + + if (s->n_ref == 0) + source_free(s); + else if (r < 0) + sd_event_source_set_enabled(s, SD_EVENT_OFF); + } + + return 0; +} + +static int dispatch_exit(sd_event *e) { + sd_event_source *p; + _cleanup_(sd_event_unrefp) sd_event *ref = NULL; + int r; + + assert(e); + + p = prioq_peek(e->exit); + if (!p || p->enabled == SD_EVENT_OFF) { + e->state = SD_EVENT_FINISHED; + return 0; + } + + ref = sd_event_ref(e); + e->iteration++; + e->state = SD_EVENT_EXITING; + r = source_dispatch(p); + e->state = SD_EVENT_INITIAL; + return r; +} + +static sd_event_source* event_next_pending(sd_event *e) { + sd_event_source *p; + + assert(e); + + p = prioq_peek(e->pending); + if (!p) + return NULL; + + if (p->enabled == SD_EVENT_OFF) + return NULL; + + return p; +} + +static int arm_watchdog(sd_event *e) { + struct itimerspec its = {}; + usec_t t; + int r; + + assert(e); + assert(e->watchdog_fd >= 0); + + t = sleep_between(e, + e->watchdog_last + (e->watchdog_period / 2), + e->watchdog_last + (e->watchdog_period * 3 / 4)); + + timespec_store(&its.it_value, t); + + /* Make sure we never set the watchdog to 0, which tells the + * kernel to disable it. */ + if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) + its.it_value.tv_nsec = 1; + + r = timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL); + if (r < 0) + return -errno; + + return 0; +} + +static int process_watchdog(sd_event *e) { + assert(e); + + if (!e->watchdog) + return 0; + + /* Don't notify watchdog too often */ + if (e->watchdog_last + e->watchdog_period / 4 > e->timestamp.monotonic) + return 0; + + sd_notify(false, "WATCHDOG=1"); + e->watchdog_last = e->timestamp.monotonic; + + return arm_watchdog(e); +} + +static void event_close_inode_data_fds(sd_event *e) { + struct inode_data *d; + + assert(e); + + /* Close the fds pointing to the inodes to watch now. We need to close them as they might otherwise pin + * filesystems. But we can't close them right-away as we need them as long as the user still wants to make + * adjustments to the even source, such as changing the priority (which requires us to remove and re-add a watch + * for the inode). Hence, let's close them when entering the first iteration after they were added, as a + * compromise. */ + + while ((d = e->inode_data_to_close)) { + assert(d->fd >= 0); + d->fd = safe_close(d->fd); + + LIST_REMOVE(to_close, e->inode_data_to_close, d); + } +} + +_public_ int sd_event_prepare(sd_event *e) { + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); + + if (e->exit_requested) + goto pending; + + e->iteration++; + + e->state = SD_EVENT_PREPARING; + r = event_prepare(e); + e->state = SD_EVENT_INITIAL; + if (r < 0) + return r; + + r = event_arm_timer(e, &e->realtime); + if (r < 0) + return r; + + r = event_arm_timer(e, &e->boottime); + if (r < 0) + return r; + + r = event_arm_timer(e, &e->monotonic); + if (r < 0) + return r; + + r = event_arm_timer(e, &e->realtime_alarm); + if (r < 0) + return r; + + r = event_arm_timer(e, &e->boottime_alarm); + if (r < 0) + return r; + + event_close_inode_data_fds(e); + + if (event_next_pending(e) || e->need_process_child) + goto pending; + + e->state = SD_EVENT_ARMED; + + return 0; + +pending: + e->state = SD_EVENT_ARMED; + r = sd_event_wait(e, 0); + if (r == 0) + e->state = SD_EVENT_ARMED; + + return r; +} + +_public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + struct epoll_event *ev_queue; + unsigned ev_queue_max; + int r, m, i; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(e->state == SD_EVENT_ARMED, -EBUSY); + + if (e->exit_requested) { + e->state = SD_EVENT_PENDING; + return 1; + } + + ev_queue_max = MAX(e->n_sources, 1u); + ev_queue = newa(struct epoll_event, ev_queue_max); + + /* If we still have inotify data buffered, then query the other fds, but don't wait on it */ + if (e->inotify_data_buffered) + timeout = 0; + + m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max, + timeout == (uint64_t) -1 ? -1 : (int) DIV_ROUND_UP(timeout, USEC_PER_MSEC)); + if (m < 0) { + if (errno == EINTR) { + e->state = SD_EVENT_PENDING; + return 1; + } + + r = -errno; + goto finish; + } + + triple_timestamp_get(&e->timestamp); + + for (i = 0; i < m; i++) { + + if (ev_queue[i].data.ptr == INT_TO_PTR(SOURCE_WATCHDOG)) + r = flush_timer(e, e->watchdog_fd, ev_queue[i].events, NULL); + else { + WakeupType *t = ev_queue[i].data.ptr; + + switch (*t) { + + case WAKEUP_EVENT_SOURCE: + r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events); + break; + + case WAKEUP_CLOCK_DATA: { + struct clock_data *d = ev_queue[i].data.ptr; + r = flush_timer(e, d->fd, ev_queue[i].events, &d->next); + break; + } + + case WAKEUP_SIGNAL_DATA: + r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events); + break; + + case WAKEUP_INOTIFY_DATA: + r = event_inotify_data_read(e, ev_queue[i].data.ptr, ev_queue[i].events); + break; + + default: + assert_not_reached("Invalid wake-up pointer"); + } + } + if (r < 0) + goto finish; + } + + r = process_watchdog(e); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp.realtime, &e->realtime); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp.boottime, &e->boottime); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp.monotonic, &e->monotonic); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp.realtime, &e->realtime_alarm); + if (r < 0) + goto finish; + + r = process_timer(e, e->timestamp.boottime, &e->boottime_alarm); + if (r < 0) + goto finish; + + if (e->need_process_child) { + r = process_child(e); + if (r < 0) + goto finish; + } + + r = process_inotify(e); + if (r < 0) + goto finish; + + if (event_next_pending(e)) { + e->state = SD_EVENT_PENDING; + + return 1; + } + + r = 0; + +finish: + e->state = SD_EVENT_INITIAL; + + return r; +} + +_public_ int sd_event_dispatch(sd_event *e) { + sd_event_source *p; + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(e->state == SD_EVENT_PENDING, -EBUSY); + + if (e->exit_requested) + return dispatch_exit(e); + + p = event_next_pending(e); + if (p) { + _cleanup_(sd_event_unrefp) sd_event *ref = NULL; + + ref = sd_event_ref(e); + e->state = SD_EVENT_RUNNING; + r = source_dispatch(p); + e->state = SD_EVENT_INITIAL; + return r; + } + + e->state = SD_EVENT_INITIAL; + + return 1; +} + +static void event_log_delays(sd_event *e) { + char b[ELEMENTSOF(e->delays) * DECIMAL_STR_MAX(unsigned) + 1], *p; + size_t l, i; + + p = b; + l = sizeof(b); + for (i = 0; i < ELEMENTSOF(e->delays); i++) { + l = strpcpyf(&p, l, "%u ", e->delays[i]); + e->delays[i] = 0; + } + log_debug("Event loop iterations: %s", b); +} + +_public_ int sd_event_run(sd_event *e, uint64_t timeout) { + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); + + if (e->profile_delays && e->last_run) { + usec_t this_run; + unsigned l; + + this_run = now(CLOCK_MONOTONIC); + + l = u64log2(this_run - e->last_run); + assert(l < sizeof(e->delays)); + e->delays[l]++; + + if (this_run - e->last_log >= 5*USEC_PER_SEC) { + event_log_delays(e); + e->last_log = this_run; + } + } + + r = sd_event_prepare(e); + if (r == 0) + /* There was nothing? Then wait... */ + r = sd_event_wait(e, timeout); + + if (e->profile_delays) + e->last_run = now(CLOCK_MONOTONIC); + + if (r > 0) { + /* There's something now, then let's dispatch it */ + r = sd_event_dispatch(e); + if (r < 0) + return r; + + return 1; + } + + return r; +} + +_public_ int sd_event_loop(sd_event *e) { + _cleanup_(sd_event_unrefp) sd_event *ref = NULL; + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); + + ref = sd_event_ref(e); + + while (e->state != SD_EVENT_FINISHED) { + r = sd_event_run(e, (uint64_t) -1); + if (r < 0) + return r; + } + + return e->exit_code; +} + +_public_ int sd_event_get_fd(sd_event *e) { + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(!event_pid_changed(e), -ECHILD); + + return e->epoll_fd; +} + +_public_ int sd_event_get_state(sd_event *e) { + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(!event_pid_changed(e), -ECHILD); + + return e->state; +} + +_public_ int sd_event_get_exit_code(sd_event *e, int *code) { + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(code, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + if (!e->exit_requested) + return -ENODATA; + + *code = e->exit_code; + return 0; +} + +_public_ int sd_event_exit(sd_event *e, int code) { + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(!event_pid_changed(e), -ECHILD); + + e->exit_requested = true; + e->exit_code = code; + + return 0; +} + +_public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(usec, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + if (!TRIPLE_TIMESTAMP_HAS_CLOCK(clock)) + return -EOPNOTSUPP; + + /* Generate a clean error in case CLOCK_BOOTTIME is not available. Note that don't use clock_supported() here, + * for a reason: there are systems where CLOCK_BOOTTIME is supported, but CLOCK_BOOTTIME_ALARM is not, but for + * the purpose of getting the time this doesn't matter. */ + if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) && !clock_boottime_supported()) + return -EOPNOTSUPP; + + if (!triple_timestamp_is_set(&e->timestamp)) { + /* Implicitly fall back to now() if we never ran + * before and thus have no cached time. */ + *usec = now(clock); + return 1; + } + + *usec = triple_timestamp_by_clock(&e->timestamp, clock); + return 0; +} + +_public_ int sd_event_default(sd_event **ret) { + sd_event *e = NULL; + int r; + + if (!ret) + return !!default_event; + + if (default_event) { + *ret = sd_event_ref(default_event); + return 0; + } + + r = sd_event_new(&e); + if (r < 0) + return r; + + e->default_event_ptr = &default_event; + e->tid = gettid(); + default_event = e; + + *ret = e; + return 1; +} + +_public_ int sd_event_get_tid(sd_event *e, pid_t *tid) { + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(tid, -EINVAL); + assert_return(!event_pid_changed(e), -ECHILD); + + if (e->tid != 0) { + *tid = e->tid; + return 0; + } + + return -ENXIO; +} + +_public_ int sd_event_set_watchdog(sd_event *e, int b) { + int r; + + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(!event_pid_changed(e), -ECHILD); + + if (e->watchdog == !!b) + return e->watchdog; + + if (b) { + struct epoll_event ev; + + r = sd_watchdog_enabled(false, &e->watchdog_period); + if (r <= 0) + return r; + + /* Issue first ping immediately */ + sd_notify(false, "WATCHDOG=1"); + e->watchdog_last = now(CLOCK_MONOTONIC); + + e->watchdog_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC); + if (e->watchdog_fd < 0) + return -errno; + + r = arm_watchdog(e); + if (r < 0) + goto fail; + + ev = (struct epoll_event) { + .events = EPOLLIN, + .data.ptr = INT_TO_PTR(SOURCE_WATCHDOG), + }; + + r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev); + if (r < 0) { + r = -errno; + goto fail; + } + + } else { + if (e->watchdog_fd >= 0) { + epoll_ctl(e->epoll_fd, EPOLL_CTL_DEL, e->watchdog_fd, NULL); + e->watchdog_fd = safe_close(e->watchdog_fd); + } + } + + e->watchdog = !!b; + return e->watchdog; + +fail: + e->watchdog_fd = safe_close(e->watchdog_fd); + return r; +} + +_public_ int sd_event_get_watchdog(sd_event *e) { + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(!event_pid_changed(e), -ECHILD); + + return e->watchdog; +} + +_public_ int sd_event_get_iteration(sd_event *e, uint64_t *ret) { + assert_return(e, -EINVAL); + assert_return(e = event_resolve(e), -ENOPKG); + assert_return(!event_pid_changed(e), -ECHILD); + + *ret = e->iteration; + return 0; +} + +_public_ int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback) { + assert_return(s, -EINVAL); + + s->destroy_callback = callback; + return 0; +} + +_public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret) { + assert_return(s, -EINVAL); + + if (ret) + *ret = s->destroy_callback; + + return !!s->destroy_callback; +} + +_public_ int sd_event_source_get_floating(sd_event_source *s) { + assert_return(s, -EINVAL); + + return s->floating; +} + +_public_ int sd_event_source_set_floating(sd_event_source *s, int b) { + assert_return(s, -EINVAL); + + if (s->floating == !!b) + return 0; + + if (!s->event) /* Already disconnected */ + return -ESTALE; + + s->floating = b; + + if (b) { + sd_event_source_ref(s); + sd_event_unref(s->event); + } else { + sd_event_ref(s->event); + sd_event_source_unref(s); + } + + return 1; +} diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c new file mode 100644 index 00000000..954b93ad --- /dev/null +++ b/src/libsystemd/sd-event/test-event.c @@ -0,0 +1,496 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-event.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "log.h" +#include "macro.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "rm-rf.h" +#include "signal-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "tests.h" +#include "tmpfile-util.h" +#include "util.h" + +static int prepare_handler(sd_event_source *s, void *userdata) { + log_info("preparing %c", PTR_TO_INT(userdata)); + return 1; +} + +static bool got_a, got_b, got_c, got_unref; +static unsigned got_d; + +static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + sd_event_source_unref(s); + got_unref = true; + return 0; +} + +static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + + log_info("got IO on %c", PTR_TO_INT(userdata)); + + if (userdata == INT_TO_PTR('a')) { + assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); + assert_se(!got_a); + got_a = true; + } else if (userdata == INT_TO_PTR('b')) { + assert_se(!got_b); + got_b = true; + } else if (userdata == INT_TO_PTR('d')) { + got_d++; + if (got_d < 2) + assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0); + else + assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); + } else + assert_not_reached("Yuck!"); + + return 1; +} + +static int child_handler(sd_event_source *s, const siginfo_t *si, void *userdata) { + + assert_se(s); + assert_se(si); + + log_info("got child on %c", PTR_TO_INT(userdata)); + + assert_se(userdata == INT_TO_PTR('f')); + + assert_se(sd_event_exit(sd_event_source_get_event(s), 0) >= 0); + sd_event_source_unref(s); + + return 1; +} + +static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + sd_event_source *p = NULL; + pid_t pid; + + assert_se(s); + assert_se(si); + + log_info("got signal on %c", PTR_TO_INT(userdata)); + + assert_se(userdata == INT_TO_PTR('e')); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) + _exit(EXIT_SUCCESS); + + assert_se(sd_event_add_child(sd_event_source_get_event(s), &p, pid, WEXITED, child_handler, INT_TO_PTR('f')) >= 0); + assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); + + sd_event_source_unref(s); + + return 1; +} + +static int defer_handler(sd_event_source *s, void *userdata) { + sd_event_source *p = NULL; + + assert_se(s); + + log_info("got defer on %c", PTR_TO_INT(userdata)); + + assert_se(userdata == INT_TO_PTR('d')); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0); + + assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0); + assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); + raise(SIGUSR1); + + sd_event_source_unref(s); + + return 1; +} + +static bool do_quit = false; + +static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) { + log_info("got timer on %c", PTR_TO_INT(userdata)); + + if (userdata == INT_TO_PTR('c')) { + + if (do_quit) { + sd_event_source *p; + + assert_se(sd_event_add_defer(sd_event_source_get_event(s), &p, defer_handler, INT_TO_PTR('d')) >= 0); + assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); + } else { + assert_se(!got_c); + got_c = true; + } + } else + assert_not_reached("Huh?"); + + return 2; +} + +static bool got_exit = false; + +static int exit_handler(sd_event_source *s, void *userdata) { + log_info("got quit handler on %c", PTR_TO_INT(userdata)); + + got_exit = true; + + return 3; +} + +static bool got_post = false; + +static int post_handler(sd_event_source *s, void *userdata) { + log_info("got post handler"); + + got_post = true; + + return 2; +} + +static void test_basic(void) { + sd_event *e = NULL; + sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL; + static const char ch = 'x'; + int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 }; + uint64_t event_now; + int64_t priority; + + assert_se(pipe(a) >= 0); + assert_se(pipe(b) >= 0); + assert_se(pipe(d) >= 0); + assert_se(pipe(k) >= 0); + + assert_se(sd_event_default(&e) >= 0); + assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0); + + assert_se(sd_event_set_watchdog(e, true) >= 0); + + /* Test whether we cleanly can destroy an io event source from its own handler */ + got_unref = false; + assert_se(sd_event_add_io(e, &t, k[0], EPOLLIN, unref_handler, NULL) >= 0); + assert_se(write(k[1], &ch, 1) == 1); + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + assert_se(got_unref); + + got_a = false, got_b = false, got_c = false, got_d = 0; + + /* Add a oneshot handler, trigger it, reenable it, and trigger + * it again. */ + assert_se(sd_event_add_io(e, &w, d[0], EPOLLIN, io_handler, INT_TO_PTR('d')) >= 0); + assert_se(sd_event_source_set_enabled(w, SD_EVENT_ONESHOT) >= 0); + assert_se(write(d[1], &ch, 1) >= 0); + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + assert_se(got_d == 1); + assert_se(write(d[1], &ch, 1) >= 0); + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + assert_se(got_d == 2); + + assert_se(sd_event_add_io(e, &x, a[0], EPOLLIN, io_handler, INT_TO_PTR('a')) >= 0); + assert_se(sd_event_add_io(e, &y, b[0], EPOLLIN, io_handler, INT_TO_PTR('b')) >= 0); + assert_se(sd_event_add_time(e, &z, CLOCK_MONOTONIC, 0, 0, time_handler, INT_TO_PTR('c')) >= 0); + assert_se(sd_event_add_exit(e, &q, exit_handler, INT_TO_PTR('g')) >= 0); + + assert_se(sd_event_source_set_priority(x, 99) >= 0); + assert_se(sd_event_source_get_priority(x, &priority) >= 0); + assert_se(priority == 99); + assert_se(sd_event_source_set_enabled(y, SD_EVENT_ONESHOT) >= 0); + assert_se(sd_event_source_set_prepare(x, prepare_handler) >= 0); + assert_se(sd_event_source_set_priority(z, 50) >= 0); + assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0); + assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0); + + /* Test for floating event sources */ + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1, -1) >= 0); + assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0); + + assert_se(write(a[1], &ch, 1) >= 0); + assert_se(write(b[1], &ch, 1) >= 0); + + assert_se(!got_a && !got_b && !got_c); + + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + + assert_se(!got_a && got_b && !got_c); + + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + + assert_se(!got_a && got_b && got_c); + + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + + assert_se(got_a && got_b && got_c); + + sd_event_source_unref(x); + sd_event_source_unref(y); + + do_quit = true; + assert_se(sd_event_add_post(e, NULL, post_handler, NULL) >= 0); + assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0); + assert_se(sd_event_source_set_time(z, event_now + 200 * USEC_PER_MSEC) >= 0); + assert_se(sd_event_source_set_enabled(z, SD_EVENT_ONESHOT) >= 0); + + assert_se(sd_event_loop(e) >= 0); + assert_se(got_post); + assert_se(got_exit); + + sd_event_source_unref(z); + sd_event_source_unref(q); + + sd_event_source_unref(w); + + sd_event_unref(e); + + safe_close_pair(a); + safe_close_pair(b); + safe_close_pair(d); + safe_close_pair(k); +} + +static void test_sd_event_now(void) { + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + uint64_t event_now; + + assert_se(sd_event_new(&e) >= 0); + assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) > 0); + assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) > 0); + assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) > 0); + if (clock_boottime_supported()) { + assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) > 0); + assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) > 0); + } + assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP); + assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP); + + assert_se(sd_event_run(e, 0) == 0); + + assert_se(sd_event_now(e, CLOCK_MONOTONIC, &event_now) == 0); + assert_se(sd_event_now(e, CLOCK_REALTIME, &event_now) == 0); + assert_se(sd_event_now(e, CLOCK_REALTIME_ALARM, &event_now) == 0); + if (clock_boottime_supported()) { + assert_se(sd_event_now(e, CLOCK_BOOTTIME, &event_now) == 0); + assert_se(sd_event_now(e, CLOCK_BOOTTIME_ALARM, &event_now) == 0); + } + assert_se(sd_event_now(e, -1, &event_now) == -EOPNOTSUPP); + assert_se(sd_event_now(e, 900 /* arbitrary big number */, &event_now) == -EOPNOTSUPP); +} + +static int last_rtqueue_sigval = 0; +static int n_rtqueue = 0; + +static int rtqueue_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + last_rtqueue_sigval = si->ssi_int; + n_rtqueue++; + return 0; +} + +static void test_rtqueue(void) { + sd_event_source *u = NULL, *v = NULL, *s = NULL; + sd_event *e = NULL; + + assert_se(sd_event_default(&e) >= 0); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0); + assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0); + assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0); + assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0); + + assert_se(sd_event_source_set_priority(v, -10) >= 0); + + assert_se(sigqueue(getpid_cached(), SIGRTMIN+2, (union sigval) { .sival_int = 1 }) >= 0); + assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 2 }) >= 0); + assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 3 }) >= 0); + assert_se(sigqueue(getpid_cached(), SIGRTMIN+3, (union sigval) { .sival_int = 4 }) >= 0); + assert_se(sigqueue(getpid_cached(), SIGUSR2, (union sigval) { .sival_int = 5 }) >= 0); + + assert_se(n_rtqueue == 0); + assert_se(last_rtqueue_sigval == 0); + + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + assert_se(n_rtqueue == 1); + assert_se(last_rtqueue_sigval == 2); /* first SIGRTMIN+3 */ + + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + assert_se(n_rtqueue == 2); + assert_se(last_rtqueue_sigval == 4); /* second SIGRTMIN+3 */ + + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + assert_se(n_rtqueue == 3); + assert_se(last_rtqueue_sigval == 3); /* first SIGUSR2 */ + + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + assert_se(n_rtqueue == 4); + assert_se(last_rtqueue_sigval == 1); /* SIGRTMIN+2 */ + + assert_se(sd_event_run(e, 0) == 0); /* the other SIGUSR2 is dropped, because the first one was still queued */ + assert_se(n_rtqueue == 4); + assert_se(last_rtqueue_sigval == 1); + + sd_event_source_unref(u); + sd_event_source_unref(v); + sd_event_source_unref(s); + + sd_event_unref(e); +} + +#define CREATE_EVENTS_MAX (70000U) + +struct inotify_context { + bool delete_self_handler_called; + unsigned create_called[CREATE_EVENTS_MAX]; + unsigned create_overflow; + unsigned n_create_events; +}; + +static void maybe_exit(sd_event_source *s, struct inotify_context *c) { + unsigned n; + + assert(s); + assert(c); + + if (!c->delete_self_handler_called) + return; + + for (n = 0; n < 3; n++) { + unsigned i; + + if (c->create_overflow & (1U << n)) + continue; + + for (i = 0; i < c->n_create_events; i++) + if (!(c->create_called[i] & (1U << n))) + return; + } + + sd_event_exit(sd_event_source_get_event(s), 0); +} + +static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) { + struct inotify_context *c = userdata; + const char *description; + unsigned bit, n; + + assert_se(sd_event_source_get_description(s, &description) >= 0); + assert_se(safe_atou(description, &n) >= 0); + + assert_se(n <= 3); + bit = 1U << n; + + if (ev->mask & IN_Q_OVERFLOW) { + log_info("inotify-handler <%s>: overflow", description); + c->create_overflow |= bit; + } else if (ev->mask & IN_CREATE) { + unsigned i; + + log_debug("inotify-handler <%s>: create on %s", description, ev->name); + + if (!streq(ev->name, "sub")) { + assert_se(safe_atou(ev->name, &i) >= 0); + + assert_se(i < c->n_create_events); + c->create_called[i] |= bit; + } + } else if (ev->mask & IN_DELETE) { + log_info("inotify-handler <%s>: delete of %s", description, ev->name); + assert_se(streq(ev->name, "sub")); + } else + assert_not_reached("unexpected inotify event"); + + maybe_exit(s, c); + return 1; +} + +static int delete_self_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) { + struct inotify_context *c = userdata; + + if (ev->mask & IN_Q_OVERFLOW) { + log_info("delete-self-handler: overflow"); + c->delete_self_handler_called = true; + } else if (ev->mask & IN_DELETE_SELF) { + log_info("delete-self-handler: delete-self"); + c->delete_self_handler_called = true; + } else if (ev->mask & IN_IGNORED) { + log_info("delete-self-handler: ignore"); + } else + assert_not_reached("unexpected inotify event (delete-self)"); + + maybe_exit(s, c); + return 1; +} + +static void test_inotify(unsigned n_create_events) { + _cleanup_(rm_rf_physical_and_freep) char *p = NULL; + sd_event_source *a = NULL, *b = NULL, *c = NULL, *d = NULL; + struct inotify_context context = { + .n_create_events = n_create_events, + }; + sd_event *e = NULL; + const char *q; + unsigned i; + + assert_se(sd_event_default(&e) >= 0); + + assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0); + + assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context) >= 0); + assert_se(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context) >= 0); + assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_IDLE) >= 0); + assert_se(sd_event_source_set_priority(b, SD_EVENT_PRIORITY_NORMAL) >= 0); + assert_se(sd_event_add_inotify(e, &c, p, IN_CREATE|IN_DELETE|IN_EXCL_UNLINK, inotify_handler, &context) >= 0); + assert_se(sd_event_source_set_priority(c, SD_EVENT_PRIORITY_IDLE) >= 0); + + assert_se(sd_event_source_set_description(a, "0") >= 0); + assert_se(sd_event_source_set_description(b, "1") >= 0); + assert_se(sd_event_source_set_description(c, "2") >= 0); + + q = strjoina(p, "/sub"); + assert_se(touch(q) >= 0); + assert_se(sd_event_add_inotify(e, &d, q, IN_DELETE_SELF, delete_self_handler, &context) >= 0); + + for (i = 0; i < n_create_events; i++) { + char buf[DECIMAL_STR_MAX(unsigned)+1]; + _cleanup_free_ char *z; + + xsprintf(buf, "%u", i); + assert_se(z = path_join(p, buf)); + + assert_se(touch(z) >= 0); + } + + assert_se(unlink(q) >= 0); + + assert_se(sd_event_loop(e) >= 0); + + sd_event_source_unref(a); + sd_event_source_unref(b); + sd_event_source_unref(c); + sd_event_source_unref(d); + + sd_event_unref(e); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + test_basic(); + test_sd_event_now(); + test_rtqueue(); + + test_inotify(100); /* should work without overflow */ + test_inotify(33000); /* should trigger a q overflow */ + + return 0; +} diff --git a/src/libsystemd/sd-hwdb/hwdb-internal.h b/src/libsystemd/sd-hwdb/hwdb-internal.h new file mode 100644 index 00000000..d82b8c12 --- /dev/null +++ b/src/libsystemd/sd-hwdb/hwdb-internal.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sparse-endian.h" + +#define HWDB_SIG { 'K', 'S', 'L', 'P', 'H', 'H', 'R', 'H' } + +/* on-disk trie objects */ +struct trie_header_f { + uint8_t signature[8]; + + /* version of tool which created the file */ + le64_t tool_version; + le64_t file_size; + + /* size of structures to allow them to grow */ + le64_t header_size; + le64_t node_size; + le64_t child_entry_size; + le64_t value_entry_size; + + /* offset of the root trie node */ + le64_t nodes_root_off; + + /* size of the nodes and string section */ + le64_t nodes_len; + le64_t strings_len; +} _packed_; + +struct trie_node_f { + /* prefix of lookup string, shared by all children */ + le64_t prefix_off; + /* size of children entry array appended to the node */ + uint8_t children_count; + uint8_t padding[7]; + /* size of value entry array appended to the node */ + le64_t values_count; +} _packed_; + +/* array of child entries, follows directly the node record */ +struct trie_child_entry_f { + /* index of the child node */ + uint8_t c; + uint8_t padding[7]; + /* offset of the child node */ + le64_t child_off; +} _packed_; + +/* array of value entries, follows directly the node record/child array */ +struct trie_value_entry_f { + le64_t key_off; + le64_t value_off; +} _packed_; + +/* v2 extends v1 with filename and line-number */ +struct trie_value_entry2_f { + le64_t key_off; + le64_t value_off; + le64_t filename_off; + le32_t line_number; + le16_t file_priority; + le16_t padding; +} _packed_; diff --git a/src/libsystemd/sd-hwdb/hwdb-util.c b/src/libsystemd/sd-hwdb/hwdb-util.c new file mode 100644 index 00000000..c83575c7 --- /dev/null +++ b/src/libsystemd/sd-hwdb/hwdb-util.c @@ -0,0 +1,688 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "conf-files.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hwdb-internal.h" +#include "hwdb-util.h" +#include "label.h" +#include "mkdir.h" +#include "path-util.h" +#include "sort-util.h" +#include "strbuf.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" + +static const char *default_hwdb_bin_dir = "/etc/udev"; +static const char * const conf_file_dirs[] = { + "/etc/udev/hwdb.d", + UDEVLIBEXECDIR "/hwdb.d", + NULL +}; + +/* + * Generic udev properties, key-value database based on modalias strings. + * Uses a Patricia/radix trie to index all matches for efficient lookup. + */ + +/* in-memory trie objects */ +struct trie { + struct trie_node *root; + struct strbuf *strings; + + size_t nodes_count; + size_t children_count; + size_t values_count; +}; + +struct trie_node { + /* prefix, common part for all children of this node */ + size_t prefix_off; + + /* sorted array of pointers to children nodes */ + struct trie_child_entry *children; + uint8_t children_count; + + /* sorted array of key-value pairs */ + struct trie_value_entry *values; + size_t values_count; +}; + +/* children array item with char (0-255) index */ +struct trie_child_entry { + uint8_t c; + struct trie_node *child; +}; + +/* value array item with key-value pairs */ +struct trie_value_entry { + size_t key_off; + size_t value_off; + size_t filename_off; + uint32_t line_number; + uint16_t file_priority; +}; + +static int trie_children_cmp(const struct trie_child_entry *a, const struct trie_child_entry *b) { + return CMP(a->c, b->c); +} + +static int node_add_child(struct trie *trie, struct trie_node *node, struct trie_node *node_child, uint8_t c) { + struct trie_child_entry *child; + + /* extend array, add new entry, sort for bisection */ + child = reallocarray(node->children, node->children_count + 1, sizeof(struct trie_child_entry)); + if (!child) + return -ENOMEM; + + node->children = child; + trie->children_count++; + node->children[node->children_count].c = c; + node->children[node->children_count].child = node_child; + node->children_count++; + typesafe_qsort(node->children, node->children_count, trie_children_cmp); + trie->nodes_count++; + + return 0; +} + +static struct trie_node *node_lookup(const struct trie_node *node, uint8_t c) { + struct trie_child_entry *child; + struct trie_child_entry search; + + search.c = c; + child = typesafe_bsearch(&search, node->children, node->children_count, trie_children_cmp); + if (child) + return child->child; + return NULL; +} + +static void trie_node_cleanup(struct trie_node *node) { + size_t i; + + if (!node) + return; + + for (i = 0; i < node->children_count; i++) + trie_node_cleanup(node->children[i].child); + free(node->children); + free(node->values); + free(node); +} + +static void trie_free(struct trie *trie) { + if (!trie) + return; + + trie_node_cleanup(trie->root); + strbuf_cleanup(trie->strings); + free(trie); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct trie*, trie_free); + +static int trie_values_cmp(const struct trie_value_entry *a, const struct trie_value_entry *b, struct trie *trie) { + return strcmp(trie->strings->buf + a->key_off, + trie->strings->buf + b->key_off); +} + +static int trie_node_add_value(struct trie *trie, struct trie_node *node, + const char *key, const char *value, + const char *filename, uint16_t file_priority, uint32_t line_number, bool compat) { + ssize_t k, v, fn = 0; + struct trie_value_entry *val; + + k = strbuf_add_string(trie->strings, key, strlen(key)); + if (k < 0) + return k; + v = strbuf_add_string(trie->strings, value, strlen(value)); + if (v < 0) + return v; + + if (!compat) { + fn = strbuf_add_string(trie->strings, filename, strlen(filename)); + if (fn < 0) + return fn; + } + + if (node->values_count) { + struct trie_value_entry search = { + .key_off = k, + .value_off = v, + }; + + val = typesafe_bsearch_r(&search, node->values, node->values_count, trie_values_cmp, trie); + if (val) { + /* At this point we have 2 identical properties on the same match-string. + * Since we process files in order, we just replace the previous value. */ + val->value_off = v; + val->filename_off = fn; + val->file_priority = file_priority; + val->line_number = line_number; + return 0; + } + } + + /* extend array, add new entry, sort for bisection */ + val = reallocarray(node->values, node->values_count + 1, sizeof(struct trie_value_entry)); + if (!val) + return -ENOMEM; + trie->values_count++; + node->values = val; + node->values[node->values_count] = (struct trie_value_entry) { + .key_off = k, + .value_off = v, + .filename_off = fn, + .file_priority = file_priority, + .line_number = line_number, + }; + node->values_count++; + typesafe_qsort_r(node->values, node->values_count, trie_values_cmp, trie); + return 0; +} + +static int trie_insert(struct trie *trie, struct trie_node *node, const char *search, + const char *key, const char *value, + const char *filename, uint16_t file_priority, uint32_t line_number, bool compat) { + size_t i = 0; + int r = 0; + + for (;;) { + size_t p; + uint8_t c; + struct trie_node *child; + + for (p = 0; (c = trie->strings->buf[node->prefix_off + p]); p++) { + _cleanup_free_ struct trie_node *new_child = NULL; + _cleanup_free_ char *s = NULL; + ssize_t off; + + if (c == search[i + p]) + continue; + + /* split node */ + new_child = new(struct trie_node, 1); + if (!new_child) + return -ENOMEM; + + /* move values from parent to child */ + *new_child = (struct trie_node) { + .prefix_off = node->prefix_off + p+1, + .children = node->children, + .children_count = node->children_count, + .values = node->values, + .values_count = node->values_count, + }; + + /* update parent; use strdup() because the source gets realloc()d */ + s = strndup(trie->strings->buf + node->prefix_off, p); + if (!s) + return -ENOMEM; + + off = strbuf_add_string(trie->strings, s, p); + if (off < 0) + return off; + + *node = (struct trie_node) { + .prefix_off = off, + }; + r = node_add_child(trie, node, new_child, c); + if (r < 0) + return r; + + new_child = NULL; /* avoid cleanup */ + break; + } + i += p; + + c = search[i]; + if (c == '\0') + return trie_node_add_value(trie, node, key, value, filename, file_priority, line_number, compat); + + child = node_lookup(node, c); + if (!child) { + _cleanup_free_ struct trie_node *new_child = NULL; + ssize_t off; + + /* new child */ + new_child = new(struct trie_node, 1); + if (!new_child) + return -ENOMEM; + + off = strbuf_add_string(trie->strings, search + i+1, strlen(search + i+1)); + if (off < 0) + return off; + + *new_child = (struct trie_node) { + .prefix_off = off, + }; + + r = node_add_child(trie, node, new_child, c); + if (r < 0) + return r; + + child = TAKE_PTR(new_child); + return trie_node_add_value(trie, child, key, value, filename, file_priority, line_number, compat); + } + + node = child; + i++; + } +} + +struct trie_f { + FILE *f; + struct trie *trie; + uint64_t strings_off; + + uint64_t nodes_count; + uint64_t children_count; + uint64_t values_count; +}; + +/* calculate the storage space for the nodes, children arrays, value arrays */ +static void trie_store_nodes_size(struct trie_f *trie, struct trie_node *node, bool compat) { + uint64_t i; + + for (i = 0; i < node->children_count; i++) + trie_store_nodes_size(trie, node->children[i].child, compat); + + trie->strings_off += sizeof(struct trie_node_f); + for (i = 0; i < node->children_count; i++) + trie->strings_off += sizeof(struct trie_child_entry_f); + for (i = 0; i < node->values_count; i++) + trie->strings_off += compat ? sizeof(struct trie_value_entry_f) : sizeof(struct trie_value_entry2_f); +} + +static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node, bool compat) { + uint64_t i; + struct trie_node_f n = { + .prefix_off = htole64(trie->strings_off + node->prefix_off), + .children_count = node->children_count, + .values_count = htole64(node->values_count), + }; + _cleanup_free_ struct trie_child_entry_f *children = NULL; + int64_t node_off; + + if (node->children_count) { + children = new(struct trie_child_entry_f, node->children_count); + if (!children) + return -ENOMEM; + } + + /* post-order recursion */ + for (i = 0; i < node->children_count; i++) { + int64_t child_off; + + child_off = trie_store_nodes(trie, node->children[i].child, compat); + if (child_off < 0) + return child_off; + + children[i] = (struct trie_child_entry_f) { + .c = node->children[i].c, + .child_off = htole64(child_off), + }; + } + + /* write node */ + node_off = ftello(trie->f); + fwrite(&n, sizeof(struct trie_node_f), 1, trie->f); + trie->nodes_count++; + + /* append children array */ + if (node->children_count) { + fwrite(children, sizeof(struct trie_child_entry_f), node->children_count, trie->f); + trie->children_count += node->children_count; + } + + /* append values array */ + for (i = 0; i < node->values_count; i++) { + struct trie_value_entry2_f v = { + .key_off = htole64(trie->strings_off + node->values[i].key_off), + .value_off = htole64(trie->strings_off + node->values[i].value_off), + .filename_off = htole64(trie->strings_off + node->values[i].filename_off), + .line_number = htole32(node->values[i].line_number), + .file_priority = htole16(node->values[i].file_priority), + }; + + fwrite(&v, compat ? sizeof(struct trie_value_entry_f) : sizeof(struct trie_value_entry2_f), 1, trie->f); + } + trie->values_count += node->values_count; + + return node_off; +} + +static int trie_store(struct trie *trie, const char *filename, bool compat) { + struct trie_f t = { + .trie = trie, + }; + _cleanup_free_ char *filename_tmp = NULL; + int64_t pos; + int64_t root_off; + int64_t size; + struct trie_header_f h = { + .signature = HWDB_SIG, + .tool_version = htole64(PROJECT_VERSION), + .header_size = htole64(sizeof(struct trie_header_f)), + .node_size = htole64(sizeof(struct trie_node_f)), + .child_entry_size = htole64(sizeof(struct trie_child_entry_f)), + .value_entry_size = htole64(compat ? sizeof(struct trie_value_entry_f) : sizeof(struct trie_value_entry2_f)), + }; + int r; + + /* calculate size of header, nodes, children entries, value entries */ + t.strings_off = sizeof(struct trie_header_f); + trie_store_nodes_size(&t, trie->root, compat); + + r = fopen_temporary(filename, &t.f, &filename_tmp); + if (r < 0) + return r; + fchmod(fileno(t.f), 0444); + + /* write nodes */ + if (fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET) < 0) + goto error_fclose; + + root_off = trie_store_nodes(&t, trie->root, compat); + h.nodes_root_off = htole64(root_off); + pos = ftello(t.f); + h.nodes_len = htole64(pos - sizeof(struct trie_header_f)); + + /* write string buffer */ + fwrite(trie->strings->buf, trie->strings->len, 1, t.f); + h.strings_len = htole64(trie->strings->len); + + /* write header */ + size = ftello(t.f); + h.file_size = htole64(size); + if (fseeko(t.f, 0, SEEK_SET) < 0) + goto error_fclose; + fwrite(&h, sizeof(struct trie_header_f), 1, t.f); + + if (ferror(t.f)) + goto error_fclose; + if (fflush(t.f) < 0) + goto error_fclose; + if (fsync(fileno(t.f)) < 0) + goto error_fclose; + if (rename(filename_tmp, filename) < 0) + goto error_fclose; + + /* write succeeded */ + fclose(t.f); + + log_debug("=== trie on-disk ==="); + log_debug("size: %8"PRIi64" bytes", size); + log_debug("header: %8zu bytes", sizeof(struct trie_header_f)); + log_debug("nodes: %8"PRIu64" bytes (%8"PRIu64")", + t.nodes_count * sizeof(struct trie_node_f), t.nodes_count); + log_debug("child pointers: %8"PRIu64" bytes (%8"PRIu64")", + t.children_count * sizeof(struct trie_child_entry_f), t.children_count); + log_debug("value pointers: %8"PRIu64" bytes (%8"PRIu64")", + t.values_count * (compat ? sizeof(struct trie_value_entry_f) : sizeof(struct trie_value_entry2_f)), t.values_count); + log_debug("string store: %8zu bytes", trie->strings->len); + log_debug("strings start: %8"PRIu64, t.strings_off); + return 0; + + error_fclose: + r = -errno; + fclose(t.f); + (void) unlink(filename_tmp); + return r; +} + +static int insert_data(struct trie *trie, char **match_list, char *line, const char *filename, + uint16_t file_priority, uint32_t line_number, bool compat) { + char *value, **entry; + + assert(line[0] == ' '); + + value = strchr(line, '='); + if (!value) + return log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL, + "Key-value pair expected but got \"%s\", ignoring", line); + + value[0] = '\0'; + value++; + + /* Replace multiple leading spaces by a single space */ + while (isblank(line[0]) && isblank(line[1])) + line++; + + if (isempty(line + 1) || isempty(value)) + return log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL, + "Empty %s in \"%s=%s\", ignoring", + isempty(line + 1) ? "key" : "value", + line, value); + + STRV_FOREACH(entry, match_list) + trie_insert(trie, trie->root, *entry, line, value, filename, file_priority, line_number, compat); + + return 0; +} + +static int import_file(struct trie *trie, const char *filename, uint16_t file_priority, bool compat) { + enum { + HW_NONE, + HW_MATCH, + HW_DATA, + } state = HW_NONE; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_strv_free_ char **match_list = NULL; + uint32_t line_number = 0; + char *match = NULL; + int r = 0, err; + + f = fopen(filename, "re"); + if (!f) + return -errno; + + for (;;) { + _cleanup_free_ char *line = NULL; + size_t len; + char *pos; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + ++line_number; + + /* comment line */ + if (line[0] == '#') + continue; + + /* strip trailing comment */ + pos = strchr(line, '#'); + if (pos) + pos[0] = '\0'; + + /* strip trailing whitespace */ + len = strlen(line); + while (len > 0 && isspace(line[len-1])) + len--; + line[len] = '\0'; + + switch (state) { + case HW_NONE: + if (len == 0) + break; + + if (line[0] == ' ') { + log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL, + "Match expected but got indented property \"%s\", ignoring line", line); + r = -EINVAL; + break; + } + + /* start of record, first match */ + state = HW_MATCH; + + match = strdup(line); + if (!match) + return -ENOMEM; + + err = strv_consume(&match_list, match); + if (err < 0) + return err; + + break; + + case HW_MATCH: + if (len == 0) { + log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL, + "Property expected, ignoring record with no properties"); + r = -EINVAL; + state = HW_NONE; + strv_clear(match_list); + break; + } + + if (line[0] != ' ') { + /* another match */ + match = strdup(line); + if (!match) + return -ENOMEM; + + err = strv_consume(&match_list, match); + if (err < 0) + return err; + + break; + } + + /* first data */ + state = HW_DATA; + err = insert_data(trie, match_list, line, filename, file_priority, line_number, compat); + if (err < 0) + r = err; + break; + + case HW_DATA: + if (len == 0) { + /* end of record */ + state = HW_NONE; + strv_clear(match_list); + break; + } + + if (line[0] != ' ') { + log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL, + "Property or empty line expected, got \"%s\", ignoring record", line); + r = -EINVAL; + state = HW_NONE; + strv_clear(match_list); + break; + } + + err = insert_data(trie, match_list, line, filename, file_priority, line_number, compat); + if (err < 0) + r = err; + break; + }; + } + + if (state == HW_MATCH) + log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL, + "Property expected, ignoring record with no properties"); + + return r; +} + +int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool compat) { + _cleanup_free_ char *hwdb_bin = NULL; + _cleanup_(trie_freep) struct trie *trie = NULL; + _cleanup_strv_free_ char **files = NULL; + char **f; + uint16_t file_priority = 1; + int r = 0, err; + + /* The argument 'compat' controls the format version of database. If false, then hwdb.bin will be created with + * additional information such that priority, line number, and filename of database source. If true, then hwdb.bin + * will be created without the information. systemd-hwdb command should set the argument false, and 'udevadm hwdb' + * command should set it true. */ + + trie = new0(struct trie, 1); + if (!trie) + return -ENOMEM; + + /* string store */ + trie->strings = strbuf_new(); + if (!trie->strings) + return -ENOMEM; + + /* index */ + trie->root = new0(struct trie_node, 1); + if (!trie->root) + return -ENOMEM; + + trie->nodes_count++; + + err = conf_files_list_strv(&files, ".hwdb", root, 0, conf_file_dirs); + if (err < 0) + return log_error_errno(err, "Failed to enumerate hwdb files: %m"); + + STRV_FOREACH(f, files) { + log_debug("Reading file \"%s\"", *f); + err = import_file(trie, *f, file_priority++, compat); + if (err < 0 && strict) + r = err; + } + + strbuf_complete(trie->strings); + + log_debug("=== trie in-memory ==="); + log_debug("nodes: %8zu bytes (%8zu)", + trie->nodes_count * sizeof(struct trie_node), trie->nodes_count); + log_debug("children arrays: %8zu bytes (%8zu)", + trie->children_count * sizeof(struct trie_child_entry), trie->children_count); + log_debug("values arrays: %8zu bytes (%8zu)", + trie->values_count * sizeof(struct trie_value_entry), trie->values_count); + log_debug("strings: %8zu bytes", + trie->strings->len); + log_debug("strings incoming: %8zu bytes (%8zu)", + trie->strings->in_len, trie->strings->in_count); + log_debug("strings dedup'ed: %8zu bytes (%8zu)", + trie->strings->dedup_len, trie->strings->dedup_count); + + hwdb_bin = path_join(root, hwdb_bin_dir ?: default_hwdb_bin_dir, "hwdb.bin"); + if (!hwdb_bin) + return -ENOMEM; + + mkdir_parents_label(hwdb_bin, 0755); + err = trie_store(trie, hwdb_bin, compat); + if (err < 0) + return log_error_errno(err, "Failed to write database %s: %m", hwdb_bin); + + err = label_fix(hwdb_bin, 0); + if (err < 0) + return err; + + return r; +} + +int hwdb_query(const char *modalias) { + _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; + const char *key, *value; + int r; + + assert(modalias); + + r = sd_hwdb_new(&hwdb); + if (r < 0) + return r; + + SD_HWDB_FOREACH_PROPERTY(hwdb, modalias, key, value) + printf("%s=%s\n", key, value); + + return 0; +} diff --git a/src/libsystemd/sd-hwdb/hwdb-util.h b/src/libsystemd/sd-hwdb/hwdb-util.h new file mode 100644 index 00000000..425b4b3e --- /dev/null +++ b/src/libsystemd/sd-hwdb/hwdb-util.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-hwdb.h" + +bool hwdb_validate(sd_hwdb *hwdb); +int hwdb_update(const char *root, const char *hwdb_bin_dir, bool strict, bool compat); +int hwdb_query(const char *modalias); diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c new file mode 100644 index 00000000..b3febdbb --- /dev/null +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -0,0 +1,466 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2008 Alan Jenkins +***/ + +#include +#include +#include +#include +#include +#include +#include + +#include "sd-hwdb.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "hashmap.h" +#include "hwdb-internal.h" +#include "hwdb-util.h" +#include "nulstr-util.h" +#include "string-util.h" +#include "time-util.h" + +struct sd_hwdb { + unsigned n_ref; + + FILE *f; + struct stat st; + union { + struct trie_header_f *head; + const char *map; + }; + + OrderedHashmap *properties; + Iterator properties_iterator; + bool properties_modified; +}; + +struct linebuf { + char bytes[LINE_MAX]; + size_t size; + size_t len; +}; + +static void linebuf_init(struct linebuf *buf) { + buf->size = 0; + buf->len = 0; +} + +static const char *linebuf_get(struct linebuf *buf) { + if (buf->len + 1 >= sizeof(buf->bytes)) + return NULL; + buf->bytes[buf->len] = '\0'; + return buf->bytes; +} + +static bool linebuf_add(struct linebuf *buf, const char *s, size_t len) { + if (buf->len + len >= sizeof(buf->bytes)) + return false; + memcpy(buf->bytes + buf->len, s, len); + buf->len += len; + return true; +} + +static bool linebuf_add_char(struct linebuf *buf, char c) { + if (buf->len + 1 >= sizeof(buf->bytes)) + return false; + buf->bytes[buf->len++] = c; + return true; +} + +static void linebuf_rem(struct linebuf *buf, size_t count) { + assert(buf->len >= count); + buf->len -= count; +} + +static void linebuf_rem_char(struct linebuf *buf) { + linebuf_rem(buf, 1); +} + +static const struct trie_child_entry_f *trie_node_child(sd_hwdb *hwdb, const struct trie_node_f *node, size_t idx) { + const char *base = (const char *)node; + + base += le64toh(hwdb->head->node_size); + base += idx * le64toh(hwdb->head->child_entry_size); + return (const struct trie_child_entry_f *)base; +} + +static const struct trie_value_entry_f *trie_node_value(sd_hwdb *hwdb, const struct trie_node_f *node, size_t idx) { + const char *base = (const char *)node; + + base += le64toh(hwdb->head->node_size); + base += node->children_count * le64toh(hwdb->head->child_entry_size); + base += idx * le64toh(hwdb->head->value_entry_size); + return (const struct trie_value_entry_f *)base; +} + +static const struct trie_node_f *trie_node_from_off(sd_hwdb *hwdb, le64_t off) { + return (const struct trie_node_f *)(hwdb->map + le64toh(off)); +} + +static const char *trie_string(sd_hwdb *hwdb, le64_t off) { + return hwdb->map + le64toh(off); +} + +static int trie_children_cmp_f(const void *v1, const void *v2) { + const struct trie_child_entry_f *n1 = v1; + const struct trie_child_entry_f *n2 = v2; + + return n1->c - n2->c; +} + +static const struct trie_node_f *node_lookup_f(sd_hwdb *hwdb, const struct trie_node_f *node, uint8_t c) { + struct trie_child_entry_f *child; + struct trie_child_entry_f search; + + search.c = c; + child = bsearch(&search, (const char *)node + le64toh(hwdb->head->node_size), node->children_count, + le64toh(hwdb->head->child_entry_size), trie_children_cmp_f); + if (child) + return trie_node_from_off(hwdb, child->child_off); + return NULL; +} + +static int hwdb_add_property(sd_hwdb *hwdb, const struct trie_value_entry_f *entry) { + const char *key; + int r; + + assert(hwdb); + + key = trie_string(hwdb, entry->key_off); + + /* + * Silently ignore all properties which do not start with a + * space; future extensions might use additional prefixes. + */ + if (key[0] != ' ') + return 0; + + key++; + + if (le64toh(hwdb->head->value_entry_size) >= sizeof(struct trie_value_entry2_f)) { + const struct trie_value_entry2_f *old, *entry2; + + entry2 = (const struct trie_value_entry2_f *)entry; + old = ordered_hashmap_get(hwdb->properties, key); + if (old) { + /* On duplicates, we order by filename priority and line-number. + * + * v2 of the format had 64 bits for the line number. + * v3 reuses top 32 bits of line_number to store the priority. + * We check the top bits — if they are zero we have v2 format. + * This means that v2 clients will print wrong line numbers with + * v3 data. + * + * For v3 data: we compare the priority (of the source file) + * and the line number. + * + * For v2 data: we rely on the fact that the filenames in the hwdb + * are added in the order of priority (higher later), because they + * are *processed* in the order of priority. So we compare the + * indices to determine which file had higher priority. Comparing + * the strings alphabetically would be useless, because those are + * full paths, and e.g. /usr/lib would sort after /etc, even + * though it has lower priority. This is not reliable because of + * suffix compression, but should work for the most common case of + * /usr/lib/udev/hwbd.d and /etc/udev/hwdb.d, and is better than + * not doing the comparison at all. + */ + bool lower; + + if (entry2->file_priority == 0) + lower = entry2->filename_off < old->filename_off || + (entry2->filename_off == old->filename_off && entry2->line_number < old->line_number); + else + lower = entry2->file_priority < old->file_priority || + (entry2->file_priority == old->file_priority && entry2->line_number < old->line_number); + if (lower) + return 0; + } + } + + r = ordered_hashmap_ensure_allocated(&hwdb->properties, &string_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_replace(hwdb->properties, key, (void *)entry); + if (r < 0) + return r; + + hwdb->properties_modified = true; + + return 0; +} + +static int trie_fnmatch_f(sd_hwdb *hwdb, const struct trie_node_f *node, size_t p, + struct linebuf *buf, const char *search) { + size_t len; + size_t i; + const char *prefix; + int err; + + prefix = trie_string(hwdb, node->prefix_off); + len = strlen(prefix + p); + linebuf_add(buf, prefix + p, len); + + for (i = 0; i < node->children_count; i++) { + const struct trie_child_entry_f *child = trie_node_child(hwdb, node, i); + + linebuf_add_char(buf, child->c); + err = trie_fnmatch_f(hwdb, trie_node_from_off(hwdb, child->child_off), 0, buf, search); + if (err < 0) + return err; + linebuf_rem_char(buf); + } + + if (le64toh(node->values_count) && fnmatch(linebuf_get(buf), search, 0) == 0) + for (i = 0; i < le64toh(node->values_count); i++) { + err = hwdb_add_property(hwdb, trie_node_value(hwdb, node, i)); + if (err < 0) + return err; + } + + linebuf_rem(buf, len); + return 0; +} + +static int trie_search_f(sd_hwdb *hwdb, const char *search) { + struct linebuf buf; + const struct trie_node_f *node; + size_t i = 0; + int err; + + linebuf_init(&buf); + + node = trie_node_from_off(hwdb, hwdb->head->nodes_root_off); + while (node) { + const struct trie_node_f *child; + size_t p = 0; + + if (node->prefix_off) { + char c; + + for (; (c = trie_string(hwdb, node->prefix_off)[p]); p++) { + if (IN_SET(c, '*', '?', '[')) + return trie_fnmatch_f(hwdb, node, p, &buf, search + i + p); + if (c != search[i + p]) + return 0; + } + i += p; + } + + child = node_lookup_f(hwdb, node, '*'); + if (child) { + linebuf_add_char(&buf, '*'); + err = trie_fnmatch_f(hwdb, child, 0, &buf, search + i); + if (err < 0) + return err; + linebuf_rem_char(&buf); + } + + child = node_lookup_f(hwdb, node, '?'); + if (child) { + linebuf_add_char(&buf, '?'); + err = trie_fnmatch_f(hwdb, child, 0, &buf, search + i); + if (err < 0) + return err; + linebuf_rem_char(&buf); + } + + child = node_lookup_f(hwdb, node, '['); + if (child) { + linebuf_add_char(&buf, '['); + err = trie_fnmatch_f(hwdb, child, 0, &buf, search + i); + if (err < 0) + return err; + linebuf_rem_char(&buf); + } + + if (search[i] == '\0') { + size_t n; + + for (n = 0; n < le64toh(node->values_count); n++) { + err = hwdb_add_property(hwdb, trie_node_value(hwdb, node, n)); + if (err < 0) + return err; + } + return 0; + } + + child = node_lookup_f(hwdb, node, search[i]); + node = child; + i++; + } + return 0; +} + +static const char hwdb_bin_paths[] = + "/etc/systemd/hwdb/hwdb.bin\0" + "/etc/udev/hwdb.bin\0" + "/usr/lib/systemd/hwdb/hwdb.bin\0" +#if HAVE_SPLIT_USR + "/lib/systemd/hwdb/hwdb.bin\0" +#endif + UDEVLIBEXECDIR "/hwdb.bin\0"; + +_public_ int sd_hwdb_new(sd_hwdb **ret) { + _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; + const char *hwdb_bin_path; + const char sig[] = HWDB_SIG; + + assert_return(ret, -EINVAL); + + hwdb = new0(sd_hwdb, 1); + if (!hwdb) + return -ENOMEM; + + hwdb->n_ref = 1; + + /* find hwdb.bin in hwdb_bin_paths */ + NULSTR_FOREACH(hwdb_bin_path, hwdb_bin_paths) { + log_debug("Trying to open \"%s\"...", hwdb_bin_path); + hwdb->f = fopen(hwdb_bin_path, "re"); + if (hwdb->f) + break; + if (errno != ENOENT) + return log_debug_errno(errno, "Failed to open %s: %m", hwdb_bin_path); + } + + if (!hwdb->f) + return log_debug_errno(SYNTHETIC_ERRNO(ENOENT), + "hwdb.bin does not exist, please run 'systemd-hwdb update'"); + + if (fstat(fileno(hwdb->f), &hwdb->st) < 0) + return log_debug_errno(errno, "Failed to stat %s: %m", hwdb_bin_path); + if (hwdb->st.st_size < (off_t) offsetof(struct trie_header_f, strings_len) + 8) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), + "File %s is too short: %m", hwdb_bin_path); + + hwdb->map = mmap(0, hwdb->st.st_size, PROT_READ, MAP_SHARED, fileno(hwdb->f), 0); + if (hwdb->map == MAP_FAILED) + return log_debug_errno(errno, "Failed to map %s: %m", hwdb_bin_path); + + if (memcmp(hwdb->map, sig, sizeof(hwdb->head->signature)) != 0 || + (size_t) hwdb->st.st_size != le64toh(hwdb->head->file_size)) { + log_debug("Failed to recognize the format of %s", hwdb_bin_path); + return -EINVAL; + } + + log_debug("=== trie on-disk ==="); + log_debug("tool version: %"PRIu64, le64toh(hwdb->head->tool_version)); + log_debug("file size: %8"PRIi64" bytes", hwdb->st.st_size); + log_debug("header size %8"PRIu64" bytes", le64toh(hwdb->head->header_size)); + log_debug("strings %8"PRIu64" bytes", le64toh(hwdb->head->strings_len)); + log_debug("nodes %8"PRIu64" bytes", le64toh(hwdb->head->nodes_len)); + + *ret = TAKE_PTR(hwdb); + + return 0; +} + +static sd_hwdb *hwdb_free(sd_hwdb *hwdb) { + assert(hwdb); + + if (hwdb->map) + munmap((void *)hwdb->map, hwdb->st.st_size); + safe_fclose(hwdb->f); + ordered_hashmap_free(hwdb->properties); + return mfree(hwdb); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_hwdb, sd_hwdb, hwdb_free) + +bool hwdb_validate(sd_hwdb *hwdb) { + bool found = false; + const char* p; + struct stat st; + + if (!hwdb) + return false; + if (!hwdb->f) + return false; + + /* if hwdb.bin doesn't exist anywhere, we need to update */ + NULSTR_FOREACH(p, hwdb_bin_paths) + if (stat(p, &st) >= 0) { + found = true; + break; + } + if (!found) + return true; + + if (timespec_load(&hwdb->st.st_mtim) != timespec_load(&st.st_mtim)) + return true; + return false; +} + +static int properties_prepare(sd_hwdb *hwdb, const char *modalias) { + assert(hwdb); + assert(modalias); + + ordered_hashmap_clear(hwdb->properties); + hwdb->properties_modified = true; + + return trie_search_f(hwdb, modalias); +} + +_public_ int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, const char **_value) { + const struct trie_value_entry_f *entry; + int r; + + assert_return(hwdb, -EINVAL); + assert_return(hwdb->f, -EINVAL); + assert_return(modalias, -EINVAL); + assert_return(_value, -EINVAL); + + r = properties_prepare(hwdb, modalias); + if (r < 0) + return r; + + entry = ordered_hashmap_get(hwdb->properties, key); + if (!entry) + return -ENOENT; + + *_value = trie_string(hwdb, entry->value_off); + + return 0; +} + +_public_ int sd_hwdb_seek(sd_hwdb *hwdb, const char *modalias) { + int r; + + assert_return(hwdb, -EINVAL); + assert_return(hwdb->f, -EINVAL); + assert_return(modalias, -EINVAL); + + r = properties_prepare(hwdb, modalias); + if (r < 0) + return r; + + hwdb->properties_modified = false; + hwdb->properties_iterator = ITERATOR_FIRST; + + return 0; +} + +_public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value) { + const struct trie_value_entry_f *entry; + const void *k; + + assert_return(hwdb, -EINVAL); + assert_return(key, -EINVAL); + assert_return(value, -EINVAL); + + if (hwdb->properties_modified) + return -EAGAIN; + + if (!ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, (void **)&entry, &k)) + return 0; + + *key = k; + *value = trie_string(hwdb, entry->value_off); + + return 1; +} diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c new file mode 100644 index 00000000..9ffd594e --- /dev/null +++ b/src/libsystemd/sd-id128/id128-util.c @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "fd-util.h" +#include "fs-util.h" +#include "hexdecoct.h" +#include "id128-util.h" +#include "io-util.h" +#include "stdio-util.h" + +char *id128_to_uuid_string(sd_id128_t id, char s[37]) { + unsigned n, k = 0; + + assert(s); + + /* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */ + + for (n = 0; n < 16; n++) { + + if (IN_SET(n, 4, 6, 8, 10)) + s[k++] = '-'; + + s[k++] = hexchar(id.bytes[n] >> 4); + s[k++] = hexchar(id.bytes[n] & 0xF); + } + + assert(k == 36); + + s[k] = 0; + + return s; +} + +bool id128_is_valid(const char *s) { + size_t i, l; + + assert(s); + + l = strlen(s); + if (l == 32) { + + /* Plain formatted 128bit hex string */ + + for (i = 0; i < l; i++) { + char c = s[i]; + + if (!(c >= '0' && c <= '9') && + !(c >= 'a' && c <= 'z') && + !(c >= 'A' && c <= 'Z')) + return false; + } + + } else if (l == 36) { + + /* Formatted UUID */ + + for (i = 0; i < l; i++) { + char c = s[i]; + + if (IN_SET(i, 8, 13, 18, 23)) { + if (c != '-') + return false; + } else { + if (!(c >= '0' && c <= '9') && + !(c >= 'a' && c <= 'z') && + !(c >= 'A' && c <= 'Z')) + return false; + } + } + + } else + return false; + + return true; +} + +int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { + char buffer[36 + 2]; + ssize_t l; + + assert(fd >= 0); + assert(f < _ID128_FORMAT_MAX); + + /* Reads an 128bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both + * optionally followed by a newline and nothing else. ID files should really be newline terminated, but if they + * aren't that's OK too, following the rule of "Be conservative in what you send, be liberal in what you + * accept". */ + + l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */ + if (l < 0) + return (int) l; + if (l == 0) /* empty? */ + return -ENOMEDIUM; + + switch (l) { + + case 33: /* plain UUID with trailing newline */ + if (buffer[32] != '\n') + return -EINVAL; + + _fallthrough_; + case 32: /* plain UUID without trailing newline */ + if (f == ID128_UUID) + return -EINVAL; + + buffer[32] = 0; + break; + + case 37: /* RFC UUID with trailing newline */ + if (buffer[36] != '\n') + return -EINVAL; + + _fallthrough_; + case 36: /* RFC UUID without trailing newline */ + if (f == ID128_PLAIN) + return -EINVAL; + + buffer[36] = 0; + break; + + default: + return -EINVAL; + } + + return sd_id128_from_string(buffer, ret); +} + +int id128_read(const char *p, Id128Format f, sd_id128_t *ret) { + _cleanup_close_ int fd = -1; + + fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return -errno; + + return id128_read_fd(fd, f, ret); +} + +int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) { + char buffer[36 + 2]; + size_t sz; + int r; + + assert(fd >= 0); + assert(f < _ID128_FORMAT_MAX); + + if (f != ID128_UUID) { + sd_id128_to_string(id, buffer); + buffer[32] = '\n'; + sz = 33; + } else { + id128_to_uuid_string(id, buffer); + buffer[36] = '\n'; + sz = 37; + } + + r = loop_write(fd, buffer, sz, false); + if (r < 0) + return r; + + if (do_sync) { + if (fsync(fd) < 0) + return -errno; + + r = fsync_directory_of_file(fd); + if (r < 0) + return r; + } + + return 0; +} + +int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) { + _cleanup_close_ int fd = -1; + + fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, 0444); + if (fd < 0) + return -errno; + + return id128_write_fd(fd, f, id, do_sync); +} + +void id128_hash_func(const sd_id128_t *p, struct siphash *state) { + siphash24_compress(p, sizeof(sd_id128_t), state); +} + +int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) { + return memcmp(a, b, 16); +} + +DEFINE_HASH_OPS(id128_hash_ops, sd_id128_t, id128_hash_func, id128_compare_func); diff --git a/src/libsystemd/sd-id128/id128-util.h b/src/libsystemd/sd-id128/id128-util.h new file mode 100644 index 00000000..82a69a77 --- /dev/null +++ b/src/libsystemd/sd-id128/id128-util.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-id128.h" + +#include "hash-funcs.h" +#include "macro.h" + +char *id128_to_uuid_string(sd_id128_t id, char s[37]); + +bool id128_is_valid(const char *s) _pure_; + +typedef enum Id128Format { + ID128_ANY, + ID128_PLAIN, /* formatted as 32 hex chars as-is */ + ID128_UUID, /* formatted as 36 character uuid string */ + _ID128_FORMAT_MAX, +} Id128Format; + +int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret); +int id128_read(const char *p, Id128Format f, sd_id128_t *ret); + +int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync); +int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync); + +void id128_hash_func(const sd_id128_t *p, struct siphash *state); +int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) _pure_; +extern const struct hash_ops id128_hash_ops; diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c new file mode 100644 index 00000000..b331a6b4 --- /dev/null +++ b/src/libsystemd/sd-id128/sd-id128.c @@ -0,0 +1,337 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "hexdecoct.h" +#include "id128-util.h" +#include "io-util.h" +#include "khash.h" +#include "macro.h" +#include "missing_syscall.h" +#include "random-util.h" +#include "user-util.h" +#include "util.h" + +_public_ char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]) { + unsigned n; + + assert_return(s, NULL); + + for (n = 0; n < 16; n++) { + s[n*2] = hexchar(id.bytes[n] >> 4); + s[n*2+1] = hexchar(id.bytes[n] & 0xF); + } + + s[32] = 0; + + return s; +} + +_public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) { + unsigned n, i; + sd_id128_t t; + bool is_guid = false; + + assert_return(s, -EINVAL); + + for (n = 0, i = 0; n < 16;) { + int a, b; + + if (s[i] == '-') { + /* Is this a GUID? Then be nice, and skip over + * the dashes */ + + if (i == 8) + is_guid = true; + else if (IN_SET(i, 13, 18, 23)) { + if (!is_guid) + return -EINVAL; + } else + return -EINVAL; + + i++; + continue; + } + + a = unhexchar(s[i++]); + if (a < 0) + return -EINVAL; + + b = unhexchar(s[i++]); + if (b < 0) + return -EINVAL; + + t.bytes[n++] = (a << 4) | b; + } + + if (i != (is_guid ? 36 : 32)) + return -EINVAL; + + if (s[i] != 0) + return -EINVAL; + + if (ret) + *ret = t; + return 0; +} + +_public_ int sd_id128_get_machine(sd_id128_t *ret) { + static thread_local sd_id128_t saved_machine_id = {}; + int r; + + assert_return(ret, -EINVAL); + + if (sd_id128_is_null(saved_machine_id)) { + r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id); + if (r < 0) + return r; + + if (sd_id128_is_null(saved_machine_id)) + return -ENOMEDIUM; + } + + *ret = saved_machine_id; + return 0; +} + +_public_ int sd_id128_get_boot(sd_id128_t *ret) { + static thread_local sd_id128_t saved_boot_id = {}; + int r; + + assert_return(ret, -EINVAL); + + if (sd_id128_is_null(saved_boot_id)) { + r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id); + if (r < 0) + return r; + } + + *ret = saved_boot_id; + return 0; +} + +static int get_invocation_from_keyring(sd_id128_t *ret) { + _cleanup_free_ char *description = NULL; + char *d, *p, *g, *u, *e; + unsigned long perms; + key_serial_t key; + size_t sz = 256; + uid_t uid; + gid_t gid; + int r, c; + +#define MAX_PERMS ((unsigned long) (KEY_POS_VIEW|KEY_POS_READ|KEY_POS_SEARCH| \ + KEY_USR_VIEW|KEY_USR_READ|KEY_USR_SEARCH)) + + assert(ret); + + key = request_key("user", "invocation_id", NULL, 0); + if (key == -1) { + /* Keyring support not available? No invocation key stored? */ + if (IN_SET(errno, ENOSYS, ENOKEY)) + return -ENXIO; + + return -errno; + } + + for (;;) { + description = new(char, sz); + if (!description) + return -ENOMEM; + + c = keyctl(KEYCTL_DESCRIBE, key, (unsigned long) description, sz, 0); + if (c < 0) + return -errno; + + if ((size_t) c <= sz) + break; + + sz = c; + free(description); + } + + /* The kernel returns a final NUL in the string, verify that. */ + assert(description[c-1] == 0); + + /* Chop off the final description string */ + d = strrchr(description, ';'); + if (!d) + return -EIO; + *d = 0; + + /* Look for the permissions */ + p = strrchr(description, ';'); + if (!p) + return -EIO; + + errno = 0; + perms = strtoul(p + 1, &e, 16); + if (errno > 0) + return -errno; + if (e == p + 1) /* Read at least one character */ + return -EIO; + if (e != d) /* Must reached the end */ + return -EIO; + + if ((perms & ~MAX_PERMS) != 0) + return -EPERM; + + *p = 0; + + /* Look for the group ID */ + g = strrchr(description, ';'); + if (!g) + return -EIO; + r = parse_gid(g + 1, &gid); + if (r < 0) + return r; + if (gid != 0) + return -EPERM; + *g = 0; + + /* Look for the user ID */ + u = strrchr(description, ';'); + if (!u) + return -EIO; + r = parse_uid(u + 1, &uid); + if (r < 0) + return r; + if (uid != 0) + return -EPERM; + + c = keyctl(KEYCTL_READ, key, (unsigned long) ret, sizeof(sd_id128_t), 0); + if (c < 0) + return -errno; + if (c != sizeof(sd_id128_t)) + return -EIO; + + return 0; +} + +static int get_invocation_from_environment(sd_id128_t *ret) { + const char *e; + + assert(ret); + + e = secure_getenv("INVOCATION_ID"); + if (!e) + return -ENXIO; + + return sd_id128_from_string(e, ret); +} + +_public_ int sd_id128_get_invocation(sd_id128_t *ret) { + static thread_local sd_id128_t saved_invocation_id = {}; + int r; + + assert_return(ret, -EINVAL); + + if (sd_id128_is_null(saved_invocation_id)) { + /* We first check the environment. The environment variable is primarily relevant for user + * services, and sufficiently safe as long as no privilege boundary is involved. */ + r = get_invocation_from_environment(&saved_invocation_id); + if (r < 0 && r != -ENXIO) + return r; + + /* The kernel keyring is relevant for system services (as for user services we don't store + * the invocation ID in the keyring, as there'd be no trust benefit in that). */ + r = get_invocation_from_keyring(&saved_invocation_id); + if (r < 0) + return r; + } + + *ret = saved_invocation_id; + return 0; +} + +static sd_id128_t make_v4_uuid(sd_id128_t id) { + /* Stolen from generate_random_uuid() of drivers/char/random.c + * in the kernel sources */ + + /* Set UUID version to 4 --- truly random generation */ + id.bytes[6] = (id.bytes[6] & 0x0F) | 0x40; + + /* Set the UUID variant to DCE */ + id.bytes[8] = (id.bytes[8] & 0x3F) | 0x80; + + return id; +} + +_public_ int sd_id128_randomize(sd_id128_t *ret) { + sd_id128_t t; + int r; + + assert_return(ret, -EINVAL); + + /* We allow usage if x86-64 RDRAND here. It might not be trusted enough for keeping secrets, but it should be + * fine for UUIDS. */ + r = genuine_random_bytes(&t, sizeof t, RANDOM_ALLOW_RDRAND); + if (r < 0) + return r; + + /* Turn this into a valid v4 UUID, to be nice. Note that we + * only guarantee this for newly generated UUIDs, not for + * pre-existing ones. */ + + *ret = make_v4_uuid(t); + return 0; +} + +static int get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret) { + _cleanup_(khash_unrefp) khash *h = NULL; + sd_id128_t result; + const void *p; + int r; + + assert(ret); + + r = khash_new_with_key(&h, "hmac(sha256)", &base, sizeof(base)); + if (r < 0) + return r; + + r = khash_put(h, &app_id, sizeof(app_id)); + if (r < 0) + return r; + + r = khash_digest_data(h, &p); + if (r < 0) + return r; + + /* We chop off the trailing 16 bytes */ + memcpy(&result, p, MIN(khash_get_size(h), sizeof(result))); + + *ret = make_v4_uuid(result); + return 0; +} + +_public_ int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret) { + sd_id128_t id; + int r; + + assert_return(ret, -EINVAL); + + r = sd_id128_get_machine(&id); + if (r < 0) + return r; + + return get_app_specific(id, app_id, ret); +} + +_public_ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret) { + sd_id128_t id; + int r; + + assert_return(ret, -EINVAL); + + r = sd_id128_get_boot(&id); + if (r < 0) + return r; + + return get_app_specific(id, app_id, ret); +} diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c new file mode 100644 index 00000000..fbfd89b6 --- /dev/null +++ b/src/libsystemd/sd-login/sd-login.c @@ -0,0 +1,1058 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-login.h" + +#include "alloc-util.h" +#include "cgroup-util.h" +#include "dirent-util.h" +#include "env-file.h" +#include "escape.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "io-util.h" +#include "login-util.h" +#include "macro.h" +#include "parse-util.h" +#include "path-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" + +/* Error codes: + * + * invalid input parameters → -EINVAL + * invalid fd → -EBADF + * process does not exist → -ESRCH + * cgroup does not exist → -ENOENT + * machine, session does not exist → -ENXIO + * requested metadata on object is missing → -ENODATA + */ + +_public_ int sd_pid_get_session(pid_t pid, char **session) { + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(session, -EINVAL); + + r = cg_pid_get_session(pid, session); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +} + +_public_ int sd_pid_get_unit(pid_t pid, char **unit) { + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(unit, -EINVAL); + + r = cg_pid_get_unit(pid, unit); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +} + +_public_ int sd_pid_get_user_unit(pid_t pid, char **unit) { + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(unit, -EINVAL); + + r = cg_pid_get_user_unit(pid, unit); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +} + +_public_ int sd_pid_get_machine_name(pid_t pid, char **name) { + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(name, -EINVAL); + + r = cg_pid_get_machine_name(pid, name); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +} + +_public_ int sd_pid_get_slice(pid_t pid, char **slice) { + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(slice, -EINVAL); + + r = cg_pid_get_slice(pid, slice); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +} + +_public_ int sd_pid_get_user_slice(pid_t pid, char **slice) { + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(slice, -EINVAL); + + r = cg_pid_get_user_slice(pid, slice); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +} + +_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) { + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(uid, -EINVAL); + + r = cg_pid_get_owner_uid(pid, uid); + return IN_SET(r, -ENXIO, -ENOMEDIUM) ? -ENODATA : r; +} + +_public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) { + char *c; + int r; + + assert_return(pid >= 0, -EINVAL); + assert_return(cgroup, -EINVAL); + + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &c); + if (r < 0) + return r; + + /* The internal APIs return the empty string for the root + * cgroup, let's return the "/" in the public APIs instead, as + * that's easier and less ambiguous for people to grok. */ + if (isempty(c)) { + free(c); + c = strdup("/"); + if (!c) + return -ENOMEM; + + } + + *cgroup = c; + return 0; +} + +_public_ int sd_peer_get_session(int fd, char **session) { + struct ucred ucred = {}; + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(session, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return cg_pid_get_session(ucred.pid, session); +} + +_public_ int sd_peer_get_owner_uid(int fd, uid_t *uid) { + struct ucred ucred; + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(uid, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return cg_pid_get_owner_uid(ucred.pid, uid); +} + +_public_ int sd_peer_get_unit(int fd, char **unit) { + struct ucred ucred; + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(unit, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return cg_pid_get_unit(ucred.pid, unit); +} + +_public_ int sd_peer_get_user_unit(int fd, char **unit) { + struct ucred ucred; + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(unit, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return cg_pid_get_user_unit(ucred.pid, unit); +} + +_public_ int sd_peer_get_machine_name(int fd, char **machine) { + struct ucred ucred; + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(machine, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return cg_pid_get_machine_name(ucred.pid, machine); +} + +_public_ int sd_peer_get_slice(int fd, char **slice) { + struct ucred ucred; + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(slice, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return cg_pid_get_slice(ucred.pid, slice); +} + +_public_ int sd_peer_get_user_slice(int fd, char **slice) { + struct ucred ucred; + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(slice, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return cg_pid_get_user_slice(ucred.pid, slice); +} + +_public_ int sd_peer_get_cgroup(int fd, char **cgroup) { + struct ucred ucred; + int r; + + assert_return(fd >= 0, -EBADF); + assert_return(cgroup, -EINVAL); + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + return sd_pid_get_cgroup(ucred.pid, cgroup); +} + +static int file_of_uid(uid_t uid, char **p) { + + assert_return(uid_is_valid(uid), -EINVAL); + assert(p); + + if (asprintf(p, "/run/systemd/users/" UID_FMT, uid) < 0) + return -ENOMEM; + + return 0; +} + +_public_ int sd_uid_get_state(uid_t uid, char**state) { + _cleanup_free_ char *p = NULL, *s = NULL; + int r; + + assert_return(state, -EINVAL); + + r = file_of_uid(uid, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, "STATE", &s); + if (r == -ENOENT) { + r = free_and_strdup(&s, "offline"); + if (r < 0) + return r; + } else if (r < 0) + return r; + else if (isempty(s)) + return -EIO; + + *state = TAKE_PTR(s); + return 0; +} + +_public_ int sd_uid_get_display(uid_t uid, char **session) { + _cleanup_free_ char *p = NULL, *s = NULL; + int r; + + assert_return(session, -EINVAL); + + r = file_of_uid(uid, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, "DISPLAY", &s); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (isempty(s)) + return -ENODATA; + + *session = TAKE_PTR(s); + + return 0; +} + +static int file_of_seat(const char *seat, char **_p) { + char *p; + int r; + + assert(_p); + + if (seat) { + if (!filename_is_valid(seat)) + return -EINVAL; + + p = path_join("/run/systemd/seats", seat); + } else { + _cleanup_free_ char *buf = NULL; + + r = sd_session_get_seat(NULL, &buf); + if (r < 0) + return r; + + p = path_join("/run/systemd/seats", buf); + } + if (!p) + return -ENOMEM; + + *_p = TAKE_PTR(p); + return 0; +} + +_public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) { + _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL; + size_t l; + int r; + const char *word, *variable, *state; + + assert_return(uid_is_valid(uid), -EINVAL); + + r = file_of_seat(seat, &p); + if (r < 0) + return r; + + variable = require_active ? "ACTIVE_UID" : "UIDS"; + + r = parse_env_file(NULL, p, variable, &s); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + if (isempty(s)) + return 0; + + if (asprintf(&t, UID_FMT, uid) < 0) + return -ENOMEM; + + FOREACH_WORD(word, l, s, state) + if (strneq(t, word, l)) + return 1; + + return 0; +} + +static int uid_get_array(uid_t uid, const char *variable, char ***array) { + _cleanup_free_ char *p = NULL, *s = NULL; + char **a; + int r; + + assert(variable); + + r = file_of_uid(uid, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, variable, &s); + if (r == -ENOENT || (r >= 0 && isempty(s))) { + if (array) + *array = NULL; + return 0; + } + if (r < 0) + return r; + + a = strv_split(s, " "); + if (!a) + return -ENOMEM; + + strv_uniq(a); + r = (int) strv_length(a); + + if (array) + *array = a; + else + strv_free(a); + + return r; +} + +_public_ int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions) { + return uid_get_array( + uid, + require_active == 0 ? "ONLINE_SESSIONS" : + require_active > 0 ? "ACTIVE_SESSIONS" : + "SESSIONS", + sessions); +} + +_public_ int sd_uid_get_seats(uid_t uid, int require_active, char ***seats) { + return uid_get_array( + uid, + require_active == 0 ? "ONLINE_SEATS" : + require_active > 0 ? "ACTIVE_SEATS" : + "SEATS", + seats); +} + +static int file_of_session(const char *session, char **_p) { + char *p; + int r; + + assert(_p); + + if (session) { + if (!session_id_valid(session)) + return -EINVAL; + + p = path_join("/run/systemd/sessions", session); + } else { + _cleanup_free_ char *buf = NULL; + + r = sd_pid_get_session(0, &buf); + if (r < 0) + return r; + + p = path_join("/run/systemd/sessions", buf); + } + + if (!p) + return -ENOMEM; + + *_p = p; + return 0; +} + +_public_ int sd_session_is_active(const char *session) { + _cleanup_free_ char *p = NULL, *s = NULL; + int r; + + r = file_of_session(session, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, "ACTIVE", &s); + if (r == -ENOENT) + return -ENXIO; + if (r < 0) + return r; + if (isempty(s)) + return -EIO; + + return parse_boolean(s); +} + +_public_ int sd_session_is_remote(const char *session) { + _cleanup_free_ char *p = NULL, *s = NULL; + int r; + + r = file_of_session(session, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, "REMOTE", &s); + if (r == -ENOENT) + return -ENXIO; + if (r < 0) + return r; + if (isempty(s)) + return -ENODATA; + + return parse_boolean(s); +} + +_public_ int sd_session_get_state(const char *session, char **state) { + _cleanup_free_ char *p = NULL, *s = NULL; + int r; + + assert_return(state, -EINVAL); + + r = file_of_session(session, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, "STATE", &s); + if (r == -ENOENT) + return -ENXIO; + if (r < 0) + return r; + if (isempty(s)) + return -EIO; + + *state = TAKE_PTR(s); + + return 0; +} + +_public_ int sd_session_get_uid(const char *session, uid_t *uid) { + int r; + _cleanup_free_ char *p = NULL, *s = NULL; + + assert_return(uid, -EINVAL); + + r = file_of_session(session, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, "UID", &s); + if (r == -ENOENT) + return -ENXIO; + if (r < 0) + return r; + if (isempty(s)) + return -EIO; + + return parse_uid(s, uid); +} + +static int session_get_string(const char *session, const char *field, char **value) { + _cleanup_free_ char *p = NULL, *s = NULL; + int r; + + assert_return(value, -EINVAL); + assert(field); + + r = file_of_session(session, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, field, &s); + if (r == -ENOENT) + return -ENXIO; + if (r < 0) + return r; + if (isempty(s)) + return -ENODATA; + + *value = TAKE_PTR(s); + return 0; +} + +_public_ int sd_session_get_seat(const char *session, char **seat) { + return session_get_string(session, "SEAT", seat); +} + +_public_ int sd_session_get_tty(const char *session, char **tty) { + return session_get_string(session, "TTY", tty); +} + +_public_ int sd_session_get_vt(const char *session, unsigned *vtnr) { + _cleanup_free_ char *vtnr_string = NULL; + unsigned u; + int r; + + assert_return(vtnr, -EINVAL); + + r = session_get_string(session, "VTNR", &vtnr_string); + if (r < 0) + return r; + + r = safe_atou(vtnr_string, &u); + if (r < 0) + return r; + + *vtnr = u; + return 0; +} + +_public_ int sd_session_get_service(const char *session, char **service) { + return session_get_string(session, "SERVICE", service); +} + +_public_ int sd_session_get_type(const char *session, char **type) { + return session_get_string(session, "TYPE", type); +} + +_public_ int sd_session_get_class(const char *session, char **class) { + return session_get_string(session, "CLASS", class); +} + +_public_ int sd_session_get_desktop(const char *session, char **desktop) { + _cleanup_free_ char *escaped = NULL; + char *t; + int r; + + assert_return(desktop, -EINVAL); + + r = session_get_string(session, "DESKTOP", &escaped); + if (r < 0) + return r; + + r = cunescape(escaped, 0, &t); + if (r < 0) + return r; + + *desktop = t; + return 0; +} + +_public_ int sd_session_get_display(const char *session, char **display) { + return session_get_string(session, "DISPLAY", display); +} + +_public_ int sd_session_get_remote_user(const char *session, char **remote_user) { + return session_get_string(session, "REMOTE_USER", remote_user); +} + +_public_ int sd_session_get_remote_host(const char *session, char **remote_host) { + return session_get_string(session, "REMOTE_HOST", remote_host); +} + +_public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) { + _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; + int r; + + assert_return(session || uid, -EINVAL); + + r = file_of_seat(seat, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, + "ACTIVE", &s, + "ACTIVE_UID", &t); + if (r == -ENOENT) + return -ENXIO; + if (r < 0) + return r; + + if (session && !s) + return -ENODATA; + + if (uid && !t) + return -ENODATA; + + if (uid && t) { + r = parse_uid(t, uid); + if (r < 0) + return r; + } + + if (session && s) + *session = TAKE_PTR(s); + + return 0; +} + +_public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) { + _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; + _cleanup_strv_free_ char **a = NULL; + _cleanup_free_ uid_t *b = NULL; + unsigned n = 0; + int r; + + r = file_of_seat(seat, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, + "SESSIONS", &s, + "UIDS", &t); + if (r == -ENOENT) + return -ENXIO; + if (r < 0) + return r; + + if (s) { + a = strv_split(s, " "); + if (!a) + return -ENOMEM; + } + + if (uids && t) { + const char *word, *state; + size_t l; + + FOREACH_WORD(word, l, t, state) + n++; + + if (n > 0) { + unsigned i = 0; + + b = new(uid_t, n); + if (!b) + return -ENOMEM; + + FOREACH_WORD(word, l, t, state) { + _cleanup_free_ char *k = NULL; + + k = strndup(word, l); + if (!k) + return -ENOMEM; + + r = parse_uid(k, b + i); + if (r < 0) + return r; + + i++; + } + } + } + + r = (int) strv_length(a); + + if (sessions) + *sessions = TAKE_PTR(a); + + if (uids) + *uids = TAKE_PTR(b); + + if (n_uids) + *n_uids = n; + + return r; +} + +static int seat_get_can(const char *seat, const char *variable) { + _cleanup_free_ char *p = NULL, *s = NULL; + int r; + + assert(variable); + + r = file_of_seat(seat, &p); + if (r < 0) + return r; + + r = parse_env_file(NULL, p, + variable, &s); + if (r == -ENOENT) + return -ENXIO; + if (r < 0) + return r; + if (isempty(s)) + return -ENODATA; + + return parse_boolean(s); +} + +_public_ int sd_seat_can_multi_session(const char *seat) { + return seat_get_can(seat, "CAN_MULTI_SESSION"); +} + +_public_ int sd_seat_can_tty(const char *seat) { + return seat_get_can(seat, "CAN_TTY"); +} + +_public_ int sd_seat_can_graphical(const char *seat) { + return seat_get_can(seat, "CAN_GRAPHICAL"); +} + +_public_ int sd_get_seats(char ***seats) { + int r; + + r = get_files_in_directory("/run/systemd/seats/", seats); + if (r == -ENOENT) { + if (seats) + *seats = NULL; + return 0; + } + return r; +} + +_public_ int sd_get_sessions(char ***sessions) { + int r; + + r = get_files_in_directory("/run/systemd/sessions/", sessions); + if (r == -ENOENT) { + if (sessions) + *sessions = NULL; + return 0; + } + return r; +} + +_public_ int sd_get_uids(uid_t **users) { + _cleanup_closedir_ DIR *d; + struct dirent *de; + int r = 0; + unsigned n = 0; + _cleanup_free_ uid_t *l = NULL; + + d = opendir("/run/systemd/users/"); + if (!d) { + if (errno == ENOENT) { + if (users) + *users = NULL; + return 0; + } + return -errno; + } + + FOREACH_DIRENT_ALL(de, d, return -errno) { + int k; + uid_t uid; + + dirent_ensure_type(d, de); + + if (!dirent_is_file(de)) + continue; + + k = parse_uid(de->d_name, &uid); + if (k < 0) + continue; + + if (users) { + if ((unsigned) r >= n) { + uid_t *t; + + n = MAX(16, 2*r); + t = reallocarray(l, sizeof(uid_t), n); + if (!t) + return -ENOMEM; + + l = t; + } + + assert((unsigned) r < n); + l[r++] = uid; + } else + r++; + } + + if (users) + *users = TAKE_PTR(l); + + return r; +} + +_public_ int sd_get_machine_names(char ***machines) { + _cleanup_strv_free_ char **l = NULL; + char **a, **b; + int r; + + r = get_files_in_directory("/run/systemd/machines/", &l); + if (r == -ENOENT) { + if (machines) + *machines = NULL; + return 0; + } + if (r < 0) + return r; + + if (l) { + r = 0; + + /* Filter out the unit: symlinks */ + for (a = b = l; *a; a++) { + if (startswith(*a, "unit:") || !machine_name_is_valid(*a)) + free(*a); + else { + *b = *a; + b++; + r++; + } + } + + *b = NULL; + } + + if (machines) + *machines = TAKE_PTR(l); + + return r; +} + +_public_ int sd_machine_get_class(const char *machine, char **class) { + _cleanup_free_ char *c = NULL; + const char *p; + int r; + + assert_return(class, -EINVAL); + + if (streq(machine, ".host")) { + c = strdup("host"); + if (!c) + return -ENOMEM; + } else { + if (!machine_name_is_valid(machine)) + return -EINVAL; + + p = strjoina("/run/systemd/machines/", machine); + r = parse_env_file(NULL, p, "CLASS", &c); + if (r == -ENOENT) + return -ENXIO; + if (r < 0) + return r; + if (!c) + return -EIO; + } + + *class = TAKE_PTR(c); + return 0; +} + +_public_ int sd_machine_get_ifindices(const char *machine, int **ifindices) { + _cleanup_free_ char *netif = NULL; + size_t l, allocated = 0, nr = 0; + int *ni = NULL; + const char *p, *word, *state; + int r; + + assert_return(machine_name_is_valid(machine), -EINVAL); + assert_return(ifindices, -EINVAL); + + p = strjoina("/run/systemd/machines/", machine); + r = parse_env_file(NULL, p, "NETIF", &netif); + if (r == -ENOENT) + return -ENXIO; + if (r < 0) + return r; + if (!netif) { + *ifindices = NULL; + return 0; + } + + FOREACH_WORD(word, l, netif, state) { + char buf[l+1]; + int ifi; + + *(char*) (mempcpy(buf, word, l)) = 0; + + if (parse_ifindex(buf, &ifi) < 0) + continue; + + if (!GREEDY_REALLOC(ni, allocated, nr+1)) { + free(ni); + return -ENOMEM; + } + + ni[nr++] = ifi; + } + + *ifindices = ni; + return nr; +} + +static int MONITOR_TO_FD(sd_login_monitor *m) { + return (int) (unsigned long) m - 1; +} + +static sd_login_monitor* FD_TO_MONITOR(int fd) { + return (sd_login_monitor*) (unsigned long) (fd + 1); +} + +_public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) { + _cleanup_close_ int fd = -1; + bool good = false; + int k; + + assert_return(m, -EINVAL); + + fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (fd < 0) + return -errno; + + if (!category || streq(category, "seat")) { + k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE); + if (k < 0) + return -errno; + + good = true; + } + + if (!category || streq(category, "session")) { + k = inotify_add_watch(fd, "/run/systemd/sessions/", IN_MOVED_TO|IN_DELETE); + if (k < 0) + return -errno; + + good = true; + } + + if (!category || streq(category, "uid")) { + k = inotify_add_watch(fd, "/run/systemd/users/", IN_MOVED_TO|IN_DELETE); + if (k < 0) + return -errno; + + good = true; + } + + if (!category || streq(category, "machine")) { + k = inotify_add_watch(fd, "/run/systemd/machines/", IN_MOVED_TO|IN_DELETE); + if (k < 0) + return -errno; + + good = true; + } + + if (!good) + return -EINVAL; + + *m = FD_TO_MONITOR(fd); + fd = -1; + + return 0; +} + +_public_ sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m) { + int fd; + + if (!m) + return NULL; + + fd = MONITOR_TO_FD(m); + close_nointr(fd); + + return NULL; +} + +_public_ int sd_login_monitor_flush(sd_login_monitor *m) { + int r; + + assert_return(m, -EINVAL); + + r = flush_fd(MONITOR_TO_FD(m)); + if (r < 0) + return r; + + return 0; +} + +_public_ int sd_login_monitor_get_fd(sd_login_monitor *m) { + + assert_return(m, -EINVAL); + + return MONITOR_TO_FD(m); +} + +_public_ int sd_login_monitor_get_events(sd_login_monitor *m) { + + assert_return(m, -EINVAL); + + /* For now we will only return POLLIN here, since we don't + * need anything else ever for inotify. However, let's have + * this API to keep our options open should we later on need + * it. */ + return POLLIN; +} + +_public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) { + + assert_return(m, -EINVAL); + assert_return(timeout_usec, -EINVAL); + + /* For now we will only return (uint64_t) -1, since we don't + * need any timeout. However, let's have this API to keep our + * options open should we later on need it. */ + *timeout_usec = (uint64_t) -1; + return 0; +} diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c new file mode 100644 index 00000000..49ed2472 --- /dev/null +++ b/src/libsystemd/sd-login/test-login.c @@ -0,0 +1,287 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-login.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "log.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "util.h" + +static char* format_uids(char **buf, uid_t* uids, int count) { + int pos = 0, k, inc; + size_t size = (DECIMAL_STR_MAX(uid_t) + 1) * count + 1; + + assert_se(*buf = malloc(size)); + + for (k = 0; k < count; k++) { + sprintf(*buf + pos, "%s"UID_FMT"%n", k > 0 ? " " : "", uids[k], &inc); + pos += inc; + } + + assert_se(pos < (ssize_t)size); + (*buf)[pos] = '\0'; + + return *buf; +} + +static void test_login(void) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + _cleanup_free_ char *pp = NULL, *qq = NULL, + *display_session = NULL, *cgroup = NULL, + *display = NULL, *remote_user = NULL, *remote_host = NULL, + *type = NULL, *class = NULL, *state = NULL, *state2 = NULL, + *seat = NULL, *session = NULL, + *unit = NULL, *user_unit = NULL, *slice = NULL; + int r; + uid_t u, u2; + char *t, **seats, **sessions; + + r = sd_pid_get_unit(0, &unit); + assert_se(r >= 0 || r == -ENODATA); + log_info("sd_pid_get_unit(0, …) → \"%s\"", strna(unit)); + + r = sd_pid_get_user_unit(0, &user_unit); + assert_se(r >= 0 || r == -ENODATA); + log_info("sd_pid_get_user_unit(0, …) → \"%s\"", strna(user_unit)); + + r = sd_pid_get_slice(0, &slice); + assert_se(r >= 0 || r == -ENODATA); + log_info("sd_pid_get_slice(0, …) → \"%s\"", strna(slice)); + + r = sd_pid_get_session(0, &session); + if (r < 0) { + log_warning_errno(r, "sd_pid_get_session(0, …): %m"); + if (r == -ENODATA) + log_info("Seems we are not running in a session, skipping some tests."); + } else { + log_info("sd_pid_get_session(0, …) → \"%s\"", session); + + assert_se(sd_pid_get_owner_uid(0, &u2) == 0); + log_info("sd_pid_get_owner_uid(0, …) → "UID_FMT, u2); + + assert_se(sd_pid_get_cgroup(0, &cgroup) == 0); + log_info("sd_pid_get_cgroup(0, …) → \"%s\"", cgroup); + + r = sd_uid_get_display(u2, &display_session); + assert_se(r >= 0 || r == -ENODATA); + log_info("sd_uid_get_display("UID_FMT", …) → \"%s\"", + u2, strnull(display_session)); + + assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0); + sd_peer_get_session(pair[0], &pp); + sd_peer_get_session(pair[1], &qq); + assert_se(streq_ptr(pp, qq)); + + r = sd_uid_get_sessions(u2, false, &sessions); + assert_se(r >= 0); + assert_se(r == (int) strv_length(sessions)); + assert_se(t = strv_join(sessions, " ")); + strv_free(sessions); + log_info("sd_uid_get_sessions("UID_FMT", …) → [%i] \"%s\"", u2, r, t); + free(t); + + assert_se(r == sd_uid_get_sessions(u2, false, NULL)); + + r = sd_uid_get_seats(u2, false, &seats); + assert_se(r >= 0); + assert_se(r == (int) strv_length(seats)); + assert_se(t = strv_join(seats, " ")); + strv_free(seats); + log_info("sd_uid_get_seats("UID_FMT", …) → [%i] \"%s\"", u2, r, t); + free(t); + + assert_se(r == sd_uid_get_seats(u2, false, NULL)); + } + + if (session) { + r = sd_session_is_active(session); + assert_se(r >= 0); + log_info("sd_session_is_active(\"%s\") → %s", session, yes_no(r)); + + r = sd_session_is_remote(session); + assert_se(r >= 0); + log_info("sd_session_is_remote(\"%s\") → %s", session, yes_no(r)); + + r = sd_session_get_state(session, &state); + assert_se(r >= 0); + log_info("sd_session_get_state(\"%s\") → \"%s\"", session, state); + + assert_se(sd_session_get_uid(session, &u) >= 0); + log_info("sd_session_get_uid(\"%s\") → "UID_FMT, session, u); + assert_se(u == u2); + + assert_se(sd_session_get_type(session, &type) >= 0); + log_info("sd_session_get_type(\"%s\") → \"%s\"", session, type); + + assert_se(sd_session_get_class(session, &class) >= 0); + log_info("sd_session_get_class(\"%s\") → \"%s\"", session, class); + + r = sd_session_get_display(session, &display); + assert_se(r >= 0 || r == -ENODATA); + log_info("sd_session_get_display(\"%s\") → \"%s\"", session, strna(display)); + + r = sd_session_get_remote_user(session, &remote_user); + assert_se(r >= 0 || r == -ENODATA); + log_info("sd_session_get_remote_user(\"%s\") → \"%s\"", + session, strna(remote_user)); + + r = sd_session_get_remote_host(session, &remote_host); + assert_se(r >= 0 || r == -ENODATA); + log_info("sd_session_get_remote_host(\"%s\") → \"%s\"", + session, strna(remote_host)); + + r = sd_session_get_seat(session, &seat); + if (r >= 0) { + assert_se(seat); + + log_info("sd_session_get_seat(\"%s\") → \"%s\"", session, seat); + + r = sd_seat_can_multi_session(seat); + assert_se(r >= 0); + log_info("sd_session_can_multi_seat(\"%s\") → %s", seat, yes_no(r)); + + r = sd_seat_can_tty(seat); + assert_se(r >= 0); + log_info("sd_session_can_tty(\"%s\") → %s", seat, yes_no(r)); + + r = sd_seat_can_graphical(seat); + assert_se(r >= 0); + log_info("sd_session_can_graphical(\"%s\") → %s", seat, yes_no(r)); + } else { + log_info_errno(r, "sd_session_get_seat(\"%s\"): %m", session); + assert_se(r == -ENODATA); + } + + assert_se(sd_uid_get_state(u, &state2) >= 0); + log_info("sd_uid_get_state("UID_FMT", …) → %s", u, state2); + } + + if (seat) { + _cleanup_free_ char *session2 = NULL, *buf = NULL; + _cleanup_free_ uid_t *uids = NULL; + unsigned n; + + assert_se(sd_uid_is_on_seat(u, 0, seat) > 0); + + r = sd_seat_get_active(seat, &session2, &u2); + assert_se(r >= 0); + log_info("sd_seat_get_active(\"%s\", …) → \"%s\", "UID_FMT, seat, session2, u2); + + r = sd_uid_is_on_seat(u, 1, seat); + assert_se(r >= 0); + assert_se(!!r == streq(session, session2)); + + r = sd_seat_get_sessions(seat, &sessions, &uids, &n); + assert_se(r >= 0); + assert_se(r == (int) strv_length(sessions)); + assert_se(t = strv_join(sessions, " ")); + strv_free(sessions); + log_info("sd_seat_get_sessions(\"%s\", …) → %i, \"%s\", [%i] {%s}", + seat, r, t, n, format_uids(&buf, uids, n)); + free(t); + + assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r); + } + + r = sd_get_seats(&seats); + assert_se(r >= 0); + assert_se(r == (int) strv_length(seats)); + assert_se(t = strv_join(seats, ", ")); + strv_free(seats); + log_info("sd_get_seats(…) → [%i] \"%s\"", r, t); + t = mfree(t); + + assert_se(sd_get_seats(NULL) == r); + + r = sd_seat_get_active(NULL, &t, NULL); + assert_se(IN_SET(r, 0, -ENODATA)); + log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s", strnull(t)); + free(t); + + r = sd_get_sessions(&sessions); + assert_se(r >= 0); + assert_se(r == (int) strv_length(sessions)); + assert_se(t = strv_join(sessions, ", ")); + strv_free(sessions); + log_info("sd_get_sessions(…) → [%i] \"%s\"", r, t); + free(t); + + assert_se(sd_get_sessions(NULL) == r); + + { + _cleanup_free_ uid_t *uids = NULL; + _cleanup_free_ char *buf = NULL; + + r = sd_get_uids(&uids); + assert_se(r >= 0); + log_info("sd_get_uids(…) → [%i] {%s}", r, format_uids(&buf, uids, r)); + + assert_se(sd_get_uids(NULL) == r); + } + + { + _cleanup_strv_free_ char **machines = NULL; + _cleanup_free_ char *buf = NULL; + + r = sd_get_machine_names(&machines); + assert_se(r >= 0); + assert_se(r == (int) strv_length(machines)); + assert_se(buf = strv_join(machines, " ")); + log_info("sd_get_machines(…) → [%i] \"%s\"", r, buf); + + assert_se(sd_get_machine_names(NULL) == r); + } +} + +static void test_monitor(void) { + sd_login_monitor *m = NULL; + unsigned n; + int r; + + r = sd_login_monitor_new("session", &m); + assert_se(r >= 0); + + for (n = 0; n < 5; n++) { + struct pollfd pollfd = {}; + usec_t timeout, nw; + + assert_se((pollfd.fd = sd_login_monitor_get_fd(m)) >= 0); + assert_se((pollfd.events = sd_login_monitor_get_events(m)) >= 0); + + assert_se(sd_login_monitor_get_timeout(m, &timeout) >= 0); + + nw = now(CLOCK_MONOTONIC); + + r = poll(&pollfd, 1, + timeout == (uint64_t) -1 ? -1 : + timeout > nw ? (int) ((timeout - nw) / 1000) : + 0); + + assert_se(r >= 0); + + sd_login_monitor_flush(m); + printf("Wake!\n"); + } + + sd_login_monitor_unref(m); +} + +int main(int argc, char* argv[]) { + log_parse_environment(); + log_open(); + + log_info("/* Information printed is from the live system */"); + + test_login(); + + if (streq_ptr(argv[1], "-m")) + test_monitor(); + + return 0; +} diff --git a/src/libsystemd/sd-netlink/generic-netlink.c b/src/libsystemd/sd-netlink/generic-netlink.c new file mode 100644 index 00000000..b4971da3 --- /dev/null +++ b/src/libsystemd/sd-netlink/generic-netlink.c @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "generic-netlink.h" +#include "netlink-internal.h" + +typedef struct { + const char* name; + uint8_t version; +} genl_family; + +static const genl_family genl_families[] = { + [SD_GENL_ID_CTRL] = { .name = "", .version = 1 }, + [SD_GENL_WIREGUARD] = { .name = "wireguard", .version = 1 }, + [SD_GENL_FOU] = { .name = "fou", .version = 1 }, + [SD_GENL_L2TP] = { .name = "l2tp", .version = 1 }, + [SD_GENL_MACSEC] = { .name = "macsec", .version = 1 }, + [SD_GENL_NL80211] = { .name = "nl80211", .version = 1 }, +}; + +int sd_genl_socket_open(sd_netlink **ret) { + return netlink_open_family(ret, NETLINK_GENERIC); +} +static int lookup_id(sd_netlink *nl, sd_genl_family family, uint16_t *id); + +static int genl_message_new(sd_netlink *nl, sd_genl_family family, uint16_t nlmsg_type, uint8_t cmd, sd_netlink_message **ret) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + const NLType *genl_cmd_type, *nl_type; + const NLTypeSystem *type_system; + struct genlmsghdr *genl; + size_t size; + int r; + + assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL); + + r = type_system_get_type(&genl_family_type_system_root, &genl_cmd_type, family); + if (r < 0) + return r; + + r = message_new_empty(nl, &m); + if (r < 0) + return r; + + size = NLMSG_SPACE(sizeof(struct genlmsghdr)); + m->hdr = malloc0(size); + if (!m->hdr) + return -ENOMEM; + + m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + + type_get_type_system(genl_cmd_type, &type_system); + + r = type_system_get_type(type_system, &nl_type, cmd); + if (r < 0) + return r; + + m->hdr->nlmsg_len = size; + m->hdr->nlmsg_type = nlmsg_type; + + type_get_type_system(nl_type, &m->containers[0].type_system); + genl = NLMSG_DATA(m->hdr); + genl->cmd = cmd; + genl->version = genl_families[family].version; + + *ret = TAKE_PTR(m); + + return 0; +} + +int sd_genl_message_new(sd_netlink *nl, sd_genl_family family, uint8_t cmd, sd_netlink_message **ret) { + uint16_t id; + int r; + + r = lookup_id(nl, family, &id); + if (r < 0) + return r; + + return genl_message_new(nl, family, id, cmd, ret); +} + +static int lookup_id(sd_netlink *nl, sd_genl_family family, uint16_t *id) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + uint16_t u; + void *v; + int r; + + if (family == SD_GENL_ID_CTRL) { + *id = GENL_ID_CTRL; + return 0; + } + + v = hashmap_get(nl->genl_family_to_nlmsg_type, INT_TO_PTR(family)); + if (v) { + *id = PTR_TO_UINT(v); + return 0; + } + + r = sd_genl_message_new(nl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &req); + if (r < 0) + return r; + + r = sd_netlink_message_append_string(req, CTRL_ATTR_FAMILY_NAME, genl_families[family].name); + if (r < 0) + return r; + + r = sd_netlink_call(nl, req, 0, &reply); + if (r < 0) + return r; + + r = sd_netlink_message_read_u16(reply, CTRL_ATTR_FAMILY_ID, &u); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&nl->genl_family_to_nlmsg_type, NULL); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&nl->nlmsg_type_to_genl_family, NULL); + if (r < 0) + return r; + + r = hashmap_put(nl->genl_family_to_nlmsg_type, INT_TO_PTR(family), UINT_TO_PTR(u)); + if (r < 0) + return r; + + r = hashmap_put(nl->nlmsg_type_to_genl_family, UINT_TO_PTR(u), INT_TO_PTR(family)); + if (r < 0) + return r; + + *id = u; + return 0; +} + +int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t type, sd_genl_family *ret) { + void *p; + + assert_return(nl, -EINVAL); + assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL); + assert(ret); + + if (type == NLMSG_ERROR) + *ret = SD_GENL_ERROR; + else if (type == NLMSG_DONE) + *ret = SD_GENL_DONE; + else if (type == GENL_ID_CTRL) + *ret = SD_GENL_ID_CTRL; + else { + p = hashmap_get(nl->nlmsg_type_to_genl_family, UINT_TO_PTR(type)); + if (!p) + return -EOPNOTSUPP; + + *ret = PTR_TO_INT(p); + } + + return 0; +} + +int sd_genl_message_get_family(const sd_netlink *nl, const sd_netlink_message *m, sd_genl_family *family) { + uint16_t type; + int r; + + assert_return(m, -EINVAL); + assert_return(nl, -EINVAL); + assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL); + assert_return(family, -EINVAL); + + r = sd_netlink_message_get_type(m, &type); + if (r < 0) + return r; + + return nlmsg_type_to_genl_family(nl, type, family); +} diff --git a/src/libsystemd/sd-netlink/generic-netlink.h b/src/libsystemd/sd-netlink/generic-netlink.h new file mode 100644 index 00000000..e9ae5591 --- /dev/null +++ b/src/libsystemd/sd-netlink/generic-netlink.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-netlink.h" + +int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t type, sd_genl_family *ret); diff --git a/src/libsystemd/sd-netlink/netlink-internal.h b/src/libsystemd/sd-netlink/netlink-internal.h new file mode 100644 index 00000000..93f495f2 --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-internal.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-netlink.h" + +#include "list.h" +#include "netlink-types.h" +#include "prioq.h" +#include "time-util.h" + +#define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC)) + +#define RTNL_WQUEUE_MAX 1024 +#define RTNL_RQUEUE_MAX 64*1024 + +#define RTNL_CONTAINER_DEPTH 32 + +struct reply_callback { + sd_netlink_message_handler_t callback; + usec_t timeout; + uint64_t serial; + unsigned prioq_idx; +}; + +struct match_callback { + sd_netlink_message_handler_t callback; + uint16_t type; + + LIST_FIELDS(struct match_callback, match_callbacks); +}; + +typedef enum NetlinkSlotType { + NETLINK_REPLY_CALLBACK, + NETLINK_MATCH_CALLBACK, + _NETLINK_SLOT_INVALID = -1, +} NetlinkSlotType; + +struct sd_netlink_slot { + unsigned n_ref; + sd_netlink *netlink; + void *userdata; + sd_netlink_destroy_t destroy_callback; + NetlinkSlotType type:2; + + bool floating:1; + char *description; + + LIST_FIELDS(sd_netlink_slot, slots); + + union { + struct reply_callback reply_callback; + struct match_callback match_callback; + }; +}; + +struct sd_netlink { + unsigned n_ref; + + int fd; + + union { + struct sockaddr sa; + struct sockaddr_nl nl; + } sockaddr; + + int protocol; + + Hashmap *broadcast_group_refs; + bool broadcast_group_dont_leave:1; /* until we can rely on 4.2 */ + + sd_netlink_message **rqueue; + unsigned rqueue_size; + size_t rqueue_allocated; + + sd_netlink_message **rqueue_partial; + unsigned rqueue_partial_size; + size_t rqueue_partial_allocated; + + struct nlmsghdr *rbuffer; + size_t rbuffer_allocated; + + bool processing:1; + + uint32_t serial; + + struct Prioq *reply_callbacks_prioq; + Hashmap *reply_callbacks; + + LIST_HEAD(struct match_callback, match_callbacks); + + LIST_HEAD(sd_netlink_slot, slots); + + pid_t original_pid; + + sd_event_source *io_event_source; + sd_event_source *time_event_source; + sd_event_source *exit_event_source; + sd_event *event; + + Hashmap *genl_family_to_nlmsg_type; + Hashmap *nlmsg_type_to_genl_family; +}; + +struct netlink_attribute { + size_t offset; /* offset from hdr to attribute */ + bool nested:1; + bool net_byteorder:1; +}; + +struct netlink_container { + const struct NLTypeSystem *type_system; /* the type system of the container */ + size_t offset; /* offset from hdr to the start of the container */ + struct netlink_attribute *attributes; + unsigned short n_attributes; /* number of attributes in container */ +}; + +struct sd_netlink_message { + unsigned n_ref; + + int protocol; + + struct nlmsghdr *hdr; + struct netlink_container containers[RTNL_CONTAINER_DEPTH]; + unsigned n_containers; /* number of containers */ + bool sealed:1; + bool broadcast:1; + + sd_netlink_message *next; /* next in a chain of multi-part messages */ +}; + +int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type); +int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret); + +int netlink_open_family(sd_netlink **ret, int family); + +int socket_open(int family); +int socket_bind(sd_netlink *nl); +int socket_broadcast_group_ref(sd_netlink *nl, unsigned group); +int socket_broadcast_group_unref(sd_netlink *nl, unsigned group); +int socket_write_message(sd_netlink *nl, sd_netlink_message *m); +int socket_read_message(sd_netlink *nl); + +int rtnl_rqueue_make_room(sd_netlink *rtnl); +int rtnl_rqueue_partial_make_room(sd_netlink *rtnl); + +/* Make sure callbacks don't destroy the rtnl connection */ +#define NETLINK_DONT_DESTROY(rtnl) \ + _cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl) diff --git a/src/libsystemd/sd-netlink/netlink-message.c b/src/libsystemd/sd-netlink/netlink-message.c new file mode 100644 index 00000000..295a73fb --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-message.c @@ -0,0 +1,1085 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "format-util.h" +#include "netlink-internal.h" +#include "netlink-types.h" +#include "netlink-util.h" +#include "socket-util.h" +#include "memory-util.h" + +#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL) +#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr; + +#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK) +#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK) + +int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) { + sd_netlink_message *m; + + assert_return(ret, -EINVAL); + + /* Note that 'rtnl' is currently unused, if we start using it internally + we must take care to avoid problems due to mutual references between + buses and their queued messages. See sd-bus. + */ + + m = new(sd_netlink_message, 1); + if (!m) + return -ENOMEM; + + *m = (sd_netlink_message) { + .n_ref = 1, + .protocol = rtnl->protocol, + .sealed = false, + }; + + *ret = m; + + return 0; +} + +int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + const NLType *nl_type; + size_t size; + int r; + + assert_return(rtnl, -EINVAL); + + r = type_system_root_get_type(rtnl, &nl_type, type); + if (r < 0) + return r; + + if (type_get_type(nl_type) != NETLINK_TYPE_NESTED) + return -EINVAL; + + r = message_new_empty(rtnl, &m); + if (r < 0) + return r; + + size = NLMSG_SPACE(type_get_size(nl_type)); + + assert(size >= sizeof(struct nlmsghdr)); + m->hdr = malloc0(size); + if (!m->hdr) + return -ENOMEM; + + m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + + type_get_type_system(nl_type, &m->containers[0].type_system); + m->hdr->nlmsg_len = size; + m->hdr->nlmsg_type = type; + + *ret = TAKE_PTR(m); + + return 0; +} + +int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) { + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + + assert_return(IN_SET(m->hdr->nlmsg_type, RTM_GETLINK, RTM_GETADDR, RTM_GETROUTE, RTM_GETNEIGH, + RTM_GETRULE, RTM_GETADDRLABEL, RTM_GETNEXTHOP), -EINVAL); + + SET_FLAG(m->hdr->nlmsg_flags, NLM_F_DUMP, dump); + + return 0; +} + +DEFINE_TRIVIAL_REF_FUNC(sd_netlink_message, sd_netlink_message); + +sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) { + while (m && --m->n_ref == 0) { + unsigned i; + + free(m->hdr); + + for (i = 0; i <= m->n_containers; i++) + free(m->containers[i].attributes); + + sd_netlink_message *t = m; + m = m->next; + free(t); + } + + return NULL; +} + +int sd_netlink_message_get_type(const sd_netlink_message *m, uint16_t *type) { + assert_return(m, -EINVAL); + assert_return(type, -EINVAL); + + *type = m->hdr->nlmsg_type; + + return 0; +} + +int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags) { + assert_return(m, -EINVAL); + assert_return(flags, -EINVAL); + + m->hdr->nlmsg_flags = flags; + + return 0; +} + +int sd_netlink_message_is_broadcast(const sd_netlink_message *m) { + assert_return(m, -EINVAL); + + return m->broadcast; +} + +/* If successful the updated message will be correctly aligned, if + unsuccessful the old message is untouched. */ +static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *data, size_t data_length) { + uint32_t rta_length; + size_t message_length, padding_length; + struct nlmsghdr *new_hdr; + struct rtattr *rta; + char *padding; + unsigned i; + int offset; + + assert(m); + assert(m->hdr); + assert(!m->sealed); + assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len); + assert(!data || data_length); + + /* get offset of the new attribute */ + offset = m->hdr->nlmsg_len; + + /* get the size of the new rta attribute (with padding at the end) */ + rta_length = RTA_LENGTH(data_length); + + /* get the new message size (with padding at the end) */ + message_length = offset + RTA_ALIGN(rta_length); + + /* buffer should be smaller than both one page or 8K to be accepted by the kernel */ + if (message_length > MIN(page_size(), 8192UL)) + return -ENOBUFS; + + /* realloc to fit the new attribute */ + new_hdr = realloc(m->hdr, message_length); + if (!new_hdr) + return -ENOMEM; + m->hdr = new_hdr; + + /* get pointer to the attribute we are about to add */ + rta = (struct rtattr *) ((uint8_t *) m->hdr + offset); + + /* if we are inside containers, extend them */ + for (i = 0; i < m->n_containers; i++) + GET_CONTAINER(m, i)->rta_len += message_length - offset; + + /* fill in the attribute */ + rta->rta_type = type; + rta->rta_len = rta_length; + if (data) + /* we don't deal with the case where the user lies about the type + * and gives us too little data (so don't do that) + */ + padding = mempcpy(RTA_DATA(rta), data, data_length); + + else + /* if no data was passed, make sure we still initialize the padding + note that we can have data_length > 0 (used by some containers) */ + padding = RTA_DATA(rta); + + /* make sure also the padding at the end of the message is initialized */ + padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding; + memzero(padding, padding_length); + + /* update message size */ + m->hdr->nlmsg_len = message_length; + + return offset; +} + +static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, uint16_t attribute_type, uint16_t data_type) { + const NLType *type; + int r; + + assert(m); + + r = type_system_get_type(m->containers[m->n_containers].type_system, &type, attribute_type); + if (r < 0) + return r; + + if (type_get_type(type) != data_type) + return -EINVAL; + + if (out_size) + *out_size = type_get_size(type); + return 0; +} + +int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data) { + size_t length, size; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(data, -EINVAL); + + r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_STRING); + if (r < 0) + return r; + + if (size) { + length = strnlen(data, size+1); + if (length > size) + return -EINVAL; + } else + length = strlen(data); + + r = add_rtattr(m, type, data, length + 1); + if (r < 0) + return r; + + return 0; +} + +int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type) { + size_t size; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_FLAG); + if (r < 0) + return r; + + r = add_rtattr(m, type, NULL, 0); + if (r < 0) + return r; + + return 0; +} + +int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8); + if (r < 0) + return r; + + r = add_rtattr(m, type, &data, sizeof(uint8_t)); + if (r < 0) + return r; + + return 0; +} + +int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16); + if (r < 0) + return r; + + r = add_rtattr(m, type, &data, sizeof(uint16_t)); + if (r < 0) + return r; + + return 0; +} + +int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32); + if (r < 0) + return r; + + r = add_rtattr(m, type, &data, sizeof(uint32_t)); + if (r < 0) + return r; + + return 0; +} + +int sd_netlink_message_append_u64(sd_netlink_message *m, unsigned short type, uint64_t data) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U64); + if (r < 0) + return r; + + r = add_rtattr(m, type, &data, sizeof(uint64_t)); + if (r < 0) + return r; + + return 0; +} + +int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + r = add_rtattr(m, type, data, len); + if (r < 0) + return r; + + return 0; +} + +int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(data, -EINVAL); + assert_return(IN_SET(family, AF_INET, AF_INET6), -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); + if (r < 0) + return r; + + r = add_rtattr(m, type, data, FAMILY_ADDRESS_SIZE(family)); + if (r < 0) + return r; + + return 0; +} + +int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data) { + return netlink_message_append_in_addr_union(m, type, AF_INET, (const union in_addr_union *) data); +} + +int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data) { + return netlink_message_append_in_addr_union(m, type, AF_INET6, (const union in_addr_union *) data); +} + +int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(data, -EINVAL); + assert_return(IN_SET(data->sa.sa_family, AF_INET, AF_INET6), -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_SOCKADDR); + if (r < 0) + return r; + + r = add_rtattr(m, type, data, data->sa.sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)); + if (r < 0) + return r; + + return 0; +} + +int sd_netlink_message_append_sockaddr_in(sd_netlink_message *m, unsigned short type, const struct sockaddr_in *data) { + return netlink_message_append_sockaddr_union(m, type, (const union sockaddr_union *) data); +} + +int sd_netlink_message_append_sockaddr_in6(sd_netlink_message *m, unsigned short type, const struct sockaddr_in6 *data) { + return netlink_message_append_sockaddr_union(m, type, (const union sockaddr_union *) data); +} + +int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(data, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR); + if (r < 0) + return r; + + r = add_rtattr(m, type, data, ETH_ALEN); + if (r < 0) + return r; + + return 0; +} + +int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(info, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO); + if (r < 0) + return r; + + r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo)); + if (r < 0) + return r; + + return 0; +} + +int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type) { + size_t size; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE); + + r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED); + if (r < 0) { + const NLTypeSystemUnion *type_system_union; + int family; + + r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_UNION); + if (r < 0) + return r; + + r = sd_rtnl_message_get_family(m, &family); + if (r < 0) + return r; + + r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type); + if (r < 0) + return r; + + r = type_system_union_protocol_get_type_system(type_system_union, + &m->containers[m->n_containers + 1].type_system, + family); + if (r < 0) + return r; + } else { + r = type_system_get_type_system(m->containers[m->n_containers].type_system, + &m->containers[m->n_containers + 1].type_system, + type); + if (r < 0) + return r; + } + + r = add_rtattr(m, type | NLA_F_NESTED, NULL, size); + if (r < 0) + return r; + + m->containers[m->n_containers++].offset = r; + + return 0; +} + +int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned short type, const char *key) { + const NLTypeSystemUnion *type_system_union; + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + + r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type); + if (r < 0) + return r; + + r = type_system_union_get_type_system(type_system_union, + &m->containers[m->n_containers + 1].type_system, + key); + if (r < 0) + return r; + + r = sd_netlink_message_append_string(m, type_system_union->match, key); + if (r < 0) + return r; + + /* do we ever need non-null size */ + r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0); + if (r < 0) + return r; + + m->containers[m->n_containers++].offset = r; + + return 0; +} + +int sd_netlink_message_close_container(sd_netlink_message *m) { + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(m->n_containers > 0, -EINVAL); + + m->containers[m->n_containers].type_system = NULL; + m->containers[m->n_containers].offset = 0; + m->n_containers--; + + return 0; +} + +int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type) { + int r; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(m->n_containers > 0, -EINVAL); + + r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0); + if (r < 0) + return r; + + m->containers[m->n_containers].offset = r; + m->n_containers++; + m->containers[m->n_containers].type_system = m->containers[m->n_containers - 1].type_system; + + return 0; +} + +int sd_netlink_message_cancel_array(sd_netlink_message *m) { + unsigned i; + uint32_t rta_len; + + assert_return(m, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(m->n_containers > 1, -EINVAL); + + rta_len = GET_CONTAINER(m, (m->n_containers - 1))->rta_len; + + for (i = 0; i < m->n_containers; i++) + GET_CONTAINER(m, i)->rta_len -= rta_len; + + m->hdr->nlmsg_len -= rta_len; + + m->n_containers--; + m->containers[m->n_containers].type_system = NULL; + + return 0; +} + +static int netlink_message_read_internal(sd_netlink_message *m, unsigned short type, void **data, bool *net_byteorder) { + struct netlink_attribute *attribute; + struct rtattr *rta; + + assert_return(m, -EINVAL); + assert_return(m->sealed, -EPERM); + assert_return(data, -EINVAL); + + assert(m->n_containers < RTNL_CONTAINER_DEPTH); + assert(m->containers[m->n_containers].attributes); + + if (type >= m->containers[m->n_containers].n_attributes) + return -ENODATA; + + attribute = &m->containers[m->n_containers].attributes[type]; + + if (attribute->offset == 0) + return -ENODATA; + + rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset); + + *data = RTA_DATA(rta); + + if (net_byteorder) + *net_byteorder = attribute->net_byteorder; + + return RTA_PAYLOAD(rta); +} + +int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data) { + void *attr_data; + int r; + + assert_return(m, -EINVAL); + + r = netlink_message_read_internal(m, type, &attr_data, NULL); + if (r < 0) + return r; + + if ((size_t) r < size) + return -EIO; + + if (data) + memcpy(data, attr_data, size); + + return r; +} + +int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data) { + void *attr_data; + char *str; + int r; + + assert_return(m, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_STRING); + if (r < 0) + return r; + + r = netlink_message_read_internal(m, type, &attr_data, NULL); + if (r < 0) + return r; + + if (data) { + str = strndup(attr_data, r); + if (!str) + return -ENOMEM; + + *data = str; + } + + return 0; +} + +int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) { + int r; + void *attr_data; + + assert_return(m, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_STRING); + if (r < 0) + return r; + + r = netlink_message_read_internal(m, type, &attr_data, NULL); + if (r < 0) + return r; + else if (strnlen(attr_data, r) >= (size_t) r) + return -EIO; + + if (data) + *data = (const char *) attr_data; + + return 0; +} + +int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data) { + int r; + void *attr_data; + + assert_return(m, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8); + if (r < 0) + return r; + + r = netlink_message_read_internal(m, type, &attr_data, NULL); + if (r < 0) + return r; + else if ((size_t) r < sizeof(uint8_t)) + return -EIO; + + if (data) + *data = *(uint8_t *) attr_data; + + return 0; +} + +int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data) { + void *attr_data; + bool net_byteorder; + int r; + + assert_return(m, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16); + if (r < 0) + return r; + + r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder); + if (r < 0) + return r; + else if ((size_t) r < sizeof(uint16_t)) + return -EIO; + + if (data) { + if (net_byteorder) + *data = be16toh(*(uint16_t *) attr_data); + else + *data = *(uint16_t *) attr_data; + } + + return 0; +} + +int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data) { + void *attr_data; + bool net_byteorder; + int r; + + assert_return(m, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32); + if (r < 0) + return r; + + r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder); + if (r < 0) + return r; + else if ((size_t)r < sizeof(uint32_t)) + return -EIO; + + if (data) { + if (net_byteorder) + *data = be32toh(*(uint32_t *) attr_data); + else + *data = *(uint32_t *) attr_data; + } + + return 0; +} + +int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short type, struct ether_addr *data) { + int r; + void *attr_data; + + assert_return(m, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR); + if (r < 0) + return r; + + r = netlink_message_read_internal(m, type, &attr_data, NULL); + if (r < 0) + return r; + else if ((size_t)r < sizeof(struct ether_addr)) + return -EIO; + + if (data) + memcpy(data, attr_data, sizeof(struct ether_addr)); + + return 0; +} + +int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info) { + int r; + void *attr_data; + + assert_return(m, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO); + if (r < 0) + return r; + + r = netlink_message_read_internal(m, type, &attr_data, NULL); + if (r < 0) + return r; + else if ((size_t)r < sizeof(struct ifa_cacheinfo)) + return -EIO; + + if (info) + memcpy(info, attr_data, sizeof(struct ifa_cacheinfo)); + + return 0; +} + +int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) { + int r; + void *attr_data; + + assert_return(m, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); + if (r < 0) + return r; + + r = netlink_message_read_internal(m, type, &attr_data, NULL); + if (r < 0) + return r; + else if ((size_t)r < sizeof(struct in_addr)) + return -EIO; + + if (data) + memcpy(data, attr_data, sizeof(struct in_addr)); + + return 0; +} + +int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) { + int r; + void *attr_data; + + assert_return(m, -EINVAL); + + r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR); + if (r < 0) + return r; + + r = netlink_message_read_internal(m, type, &attr_data, NULL); + if (r < 0) + return r; + else if ((size_t)r < sizeof(struct in6_addr)) + return -EIO; + + if (data) + memcpy(data, attr_data, sizeof(struct in6_addr)); + + return 0; +} + +static int netlink_container_parse(sd_netlink_message *m, + struct netlink_container *container, + struct rtattr *rta, + unsigned rt_len) { + _cleanup_free_ struct netlink_attribute *attributes = NULL; + size_t n_allocated = 0; + + for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) { + unsigned short type; + + type = RTA_TYPE(rta); + + if (!GREEDY_REALLOC0(attributes, n_allocated, type + 1)) + return -ENOMEM; + + if (attributes[type].offset != 0) + log_debug("rtnl: message parse - overwriting repeated attribute"); + + attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr; + attributes[type].nested = RTA_FLAGS(rta) & NLA_F_NESTED; + attributes[type].net_byteorder = RTA_FLAGS(rta) & NLA_F_NET_BYTEORDER; + } + + container->attributes = TAKE_PTR(attributes); + container->n_attributes = n_allocated; + + return 0; +} + +int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type_id) { + const NLType *nl_type; + const NLTypeSystem *type_system; + void *container; + uint16_t type; + size_t size; + int r; + + assert_return(m, -EINVAL); + assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL); + + r = type_system_get_type(m->containers[m->n_containers].type_system, + &nl_type, + type_id); + if (r < 0) + return r; + + type = type_get_type(nl_type); + + if (type == NETLINK_TYPE_NESTED) { + r = type_system_get_type_system(m->containers[m->n_containers].type_system, + &type_system, + type_id); + if (r < 0) + return r; + } else if (type == NETLINK_TYPE_UNION) { + const NLTypeSystemUnion *type_system_union; + + r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, + &type_system_union, + type_id); + if (r < 0) + return r; + + switch (type_system_union->match_type) { + case NL_MATCH_SIBLING: + { + const char *key; + + r = sd_netlink_message_read_string(m, type_system_union->match, &key); + if (r < 0) + return r; + + r = type_system_union_get_type_system(type_system_union, + &type_system, + key); + if (r < 0) + return r; + + break; + } + case NL_MATCH_PROTOCOL: + { + int family; + + r = sd_rtnl_message_get_family(m, &family); + if (r < 0) + return r; + + r = type_system_union_protocol_get_type_system(type_system_union, + &type_system, + family); + if (r < 0) + return r; + + break; + } + default: + assert_not_reached("sd-netlink: invalid type system union type"); + } + } else + return -EINVAL; + + r = netlink_message_read_internal(m, type_id, &container, NULL); + if (r < 0) + return r; + + size = (size_t)r; + + m->n_containers++; + + r = netlink_container_parse(m, + &m->containers[m->n_containers], + container, + size); + if (r < 0) { + m->n_containers--; + return r; + } + + m->containers[m->n_containers].type_system = type_system; + + return 0; +} + +int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id) { + void *container; + size_t size; + int r; + + assert_return(m, -EINVAL); + assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL); + + r = netlink_message_read_internal(m, type_id, &container, NULL); + if (r < 0) + return r; + + size = (size_t) r; + + m->n_containers++; + + r = netlink_container_parse(m, + &m->containers[m->n_containers], + container, + size); + if (r < 0) { + m->n_containers--; + return r; + } + + m->containers[m->n_containers].type_system = m->containers[m->n_containers - 1].type_system; + + return 0; +} + +int sd_netlink_message_exit_container(sd_netlink_message *m) { + assert_return(m, -EINVAL); + assert_return(m->sealed, -EINVAL); + assert_return(m->n_containers > 0, -EINVAL); + + m->containers[m->n_containers].attributes = mfree(m->containers[m->n_containers].attributes); + m->containers[m->n_containers].type_system = NULL; + + m->n_containers--; + + return 0; +} + +uint32_t rtnl_message_get_serial(sd_netlink_message *m) { + assert(m); + assert(m->hdr); + + return m->hdr->nlmsg_seq; +} + +int sd_netlink_message_is_error(const sd_netlink_message *m) { + assert_return(m, 0); + assert_return(m->hdr, 0); + + return m->hdr->nlmsg_type == NLMSG_ERROR; +} + +int sd_netlink_message_get_errno(const sd_netlink_message *m) { + struct nlmsgerr *err; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + + if (!sd_netlink_message_is_error(m)) + return 0; + + err = NLMSG_DATA(m->hdr); + + return err->error; +} + +int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl) { + const NLType *nl_type; + uint16_t type; + size_t size; + unsigned i; + int r; + + assert_return(m, -EINVAL); + assert_return(genl || m->protocol != NETLINK_GENERIC, -EINVAL); + + /* don't allow appending to message once parsed */ + if (!m->sealed) + rtnl_message_seal(m); + + for (i = 1; i <= m->n_containers; i++) + m->containers[i].attributes = mfree(m->containers[i].attributes); + + m->n_containers = 0; + + if (m->containers[0].attributes) + /* top-level attributes have already been parsed */ + return 0; + + assert(m->hdr); + + r = type_system_root_get_type(genl, &nl_type, m->hdr->nlmsg_type); + if (r < 0) + return r; + + type = type_get_type(nl_type); + size = type_get_size(nl_type); + + if (type == NETLINK_TYPE_NESTED) { + const NLTypeSystem *type_system; + + type_get_type_system(nl_type, &type_system); + + m->containers[0].type_system = type_system; + + r = netlink_container_parse(m, + &m->containers[m->n_containers], + (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)), + NLMSG_PAYLOAD(m->hdr, size)); + if (r < 0) + return r; + } + + return 0; +} + +void rtnl_message_seal(sd_netlink_message *m) { + assert(m); + assert(!m->sealed); + + m->sealed = true; +} + +sd_netlink_message *sd_netlink_message_next(sd_netlink_message *m) { + assert_return(m, NULL); + + return m->next; +} diff --git a/src/libsystemd/sd-netlink/netlink-slot.c b/src/libsystemd/sd-netlink/netlink-slot.c new file mode 100644 index 00000000..94a80a80 --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-slot.c @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "netlink-internal.h" +#include "netlink-slot.h" +#include "string-util.h" + +int netlink_slot_allocate( + sd_netlink *nl, + bool floating, + NetlinkSlotType type, + size_t extra, + void *userdata, + const char *description, + sd_netlink_slot **ret) { + + _cleanup_free_ sd_netlink_slot *slot = NULL; + + assert(nl); + assert(ret); + + slot = malloc0(offsetof(sd_netlink_slot, reply_callback) + extra); + if (!slot) + return -ENOMEM; + + slot->n_ref = 1; + slot->netlink = nl; + slot->userdata = userdata; + slot->type = type; + slot->floating = floating; + + if (description) { + slot->description = strdup(description); + if (!slot->description) + return -ENOMEM; + } + + if (!floating) + sd_netlink_ref(nl); + + LIST_PREPEND(slots, nl->slots, slot); + + *ret = TAKE_PTR(slot); + + return 0; +} + +void netlink_slot_disconnect(sd_netlink_slot *slot, bool unref) { + sd_netlink *nl; + + assert(slot); + + nl = slot->netlink; + if (!nl) + return; + + switch (slot->type) { + + case NETLINK_REPLY_CALLBACK: + (void) hashmap_remove(nl->reply_callbacks, &slot->reply_callback.serial); + + if (slot->reply_callback.timeout != 0) + prioq_remove(nl->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx); + + break; + case NETLINK_MATCH_CALLBACK: + LIST_REMOVE(match_callbacks, nl->match_callbacks, &slot->match_callback); + + switch (slot->match_callback.type) { + case RTM_NEWLINK: + case RTM_DELLINK: + (void) socket_broadcast_group_unref(nl, RTNLGRP_LINK); + + break; + case RTM_NEWADDR: + case RTM_DELADDR: + (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_IFADDR); + (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_IFADDR); + + break; + case RTM_NEWROUTE: + case RTM_DELROUTE: + (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_ROUTE); + (void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_ROUTE); + + break; + } + + break; + default: + assert_not_reached("Wut? Unknown slot type?"); + } + + slot->type = _NETLINK_SLOT_INVALID; + slot->netlink = NULL; + LIST_REMOVE(slots, nl->slots, slot); + + if (!slot->floating) + sd_netlink_unref(nl); + else if (unref) + sd_netlink_slot_unref(slot); +} + +static sd_netlink_slot* netlink_slot_free(sd_netlink_slot *slot) { + assert(slot); + + netlink_slot_disconnect(slot, false); + + if (slot->destroy_callback) + slot->destroy_callback(slot->userdata); + + free(slot->description); + return mfree(slot); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_netlink_slot, sd_netlink_slot, netlink_slot_free); + +sd_netlink *sd_netlink_slot_get_netlink(sd_netlink_slot *slot) { + assert_return(slot, NULL); + + return slot->netlink; +} + +void *sd_netlink_slot_get_userdata(sd_netlink_slot *slot) { + assert_return(slot, NULL); + + return slot->userdata; +} + +void *sd_netlink_slot_set_userdata(sd_netlink_slot *slot, void *userdata) { + void *ret; + + assert_return(slot, NULL); + + ret = slot->userdata; + slot->userdata = userdata; + + return ret; +} + +int sd_netlink_slot_get_destroy_callback(const sd_netlink_slot *slot, sd_netlink_destroy_t *callback) { + assert_return(slot, -EINVAL); + + if (callback) + *callback = slot->destroy_callback; + + return !!slot->destroy_callback; +} + +int sd_netlink_slot_set_destroy_callback(sd_netlink_slot *slot, sd_netlink_destroy_t callback) { + assert_return(slot, -EINVAL); + + slot->destroy_callback = callback; + return 0; +} + +int sd_netlink_slot_get_floating(const sd_netlink_slot *slot) { + assert_return(slot, -EINVAL); + + return slot->floating; +} + +int sd_netlink_slot_set_floating(sd_netlink_slot *slot, int b) { + assert_return(slot, -EINVAL); + + if (slot->floating == !!b) + return 0; + + if (!slot->netlink) /* Already disconnected */ + return -ESTALE; + + slot->floating = b; + + if (b) { + sd_netlink_slot_ref(slot); + sd_netlink_unref(slot->netlink); + } else { + sd_netlink_ref(slot->netlink); + sd_netlink_slot_unref(slot); + } + + return 1; +} + +int sd_netlink_slot_get_description(const sd_netlink_slot *slot, const char **description) { + assert_return(slot, -EINVAL); + + if (description) + *description = slot->description; + + return !!slot->description; +} + +int sd_netlink_slot_set_description(sd_netlink_slot *slot, const char *description) { + assert_return(slot, -EINVAL); + + return free_and_strdup(&slot->description, description); +} diff --git a/src/libsystemd/sd-netlink/netlink-slot.h b/src/libsystemd/sd-netlink/netlink-slot.h new file mode 100644 index 00000000..2641ec6b --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-slot.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-netlink.h" + +int netlink_slot_allocate( + sd_netlink *nl, + bool floating, + NetlinkSlotType type, + size_t extra, + void *userdata, + const char *description, + sd_netlink_slot **ret); +void netlink_slot_disconnect(sd_netlink_slot *slot, bool unref); diff --git a/src/libsystemd/sd-netlink/netlink-socket.c b/src/libsystemd/sd-netlink/netlink-socket.c new file mode 100644 index 00000000..9401c43d --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-socket.c @@ -0,0 +1,453 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "io-util.h" +#include "netlink-internal.h" +#include "netlink-types.h" +#include "netlink-util.h" +#include "socket-util.h" +#include "util.h" + +int socket_open(int family) { + int fd; + + fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, family); + if (fd < 0) + return -errno; + + return fd_move_above_stdio(fd); +} + +static int broadcast_groups_get(sd_netlink *nl) { + _cleanup_free_ uint32_t *groups = NULL; + socklen_t len = 0, old_len; + unsigned i, j; + int r; + + assert(nl); + assert(nl->fd >= 0); + + r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len); + if (r < 0) { + if (errno == ENOPROTOOPT) { + nl->broadcast_group_dont_leave = true; + return 0; + } else + return -errno; + } + + if (len == 0) + return 0; + + groups = new0(uint32_t, len); + if (!groups) + return -ENOMEM; + + old_len = len; + + r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len); + if (r < 0) + return -errno; + + if (old_len != len) + return -EIO; + + r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL); + if (r < 0) + return r; + + for (i = 0; i < len; i++) { + for (j = 0; j < sizeof(uint32_t) * 8; j++) { + uint32_t offset; + unsigned group; + + offset = 1U << j; + + if (!(groups[i] & offset)) + continue; + + group = i * sizeof(uint32_t) * 8 + j + 1; + + r = hashmap_put(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(1)); + if (r < 0) + return r; + } + } + + return 0; +} + +int socket_bind(sd_netlink *nl) { + socklen_t addrlen; + int r; + + r = setsockopt_int(nl->fd, SOL_NETLINK, NETLINK_PKTINFO, true); + if (r < 0) + return r; + + addrlen = sizeof(nl->sockaddr); + + r = bind(nl->fd, &nl->sockaddr.sa, addrlen); + /* ignore EINVAL to allow opening an already bound socket */ + if (r < 0 && errno != EINVAL) + return -errno; + + r = getsockname(nl->fd, &nl->sockaddr.sa, &addrlen); + if (r < 0) + return -errno; + + r = broadcast_groups_get(nl); + if (r < 0) + return r; + + return 0; +} + +static unsigned broadcast_group_get_ref(sd_netlink *nl, unsigned group) { + assert(nl); + + return PTR_TO_UINT(hashmap_get(nl->broadcast_group_refs, UINT_TO_PTR(group))); +} + +static int broadcast_group_set_ref(sd_netlink *nl, unsigned group, unsigned n_ref) { + int r; + + assert(nl); + + r = hashmap_replace(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(n_ref)); + if (r < 0) + return r; + + return 0; +} + +static int broadcast_group_join(sd_netlink *nl, unsigned group) { + int r; + + assert(nl); + assert(nl->fd >= 0); + assert(group > 0); + + r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)); + if (r < 0) + return -errno; + + return 0; +} + +int socket_broadcast_group_ref(sd_netlink *nl, unsigned group) { + unsigned n_ref; + int r; + + assert(nl); + + n_ref = broadcast_group_get_ref(nl, group); + + n_ref++; + + r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL); + if (r < 0) + return r; + + r = broadcast_group_set_ref(nl, group, n_ref); + if (r < 0) + return r; + + if (n_ref > 1) + /* not yet in the group */ + return 0; + + r = broadcast_group_join(nl, group); + if (r < 0) + return r; + + return 0; +} + +static int broadcast_group_leave(sd_netlink *nl, unsigned group) { + int r; + + assert(nl); + assert(nl->fd >= 0); + assert(group > 0); + + if (nl->broadcast_group_dont_leave) + return 0; + + r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &group, sizeof(group)); + if (r < 0) + return -errno; + + return 0; +} + +int socket_broadcast_group_unref(sd_netlink *nl, unsigned group) { + unsigned n_ref; + int r; + + assert(nl); + + n_ref = broadcast_group_get_ref(nl, group); + + assert(n_ref > 0); + + n_ref--; + + r = broadcast_group_set_ref(nl, group, n_ref); + if (r < 0) + return r; + + if (n_ref > 0) + /* still refs left */ + return 0; + + r = broadcast_group_leave(nl, group); + if (r < 0) + return r; + + return 0; +} + +/* returns the number of bytes sent, or a negative error code */ +int socket_write_message(sd_netlink *nl, sd_netlink_message *m) { + union { + struct sockaddr sa; + struct sockaddr_nl nl; + } addr = { + .nl.nl_family = AF_NETLINK, + }; + ssize_t k; + + assert(nl); + assert(m); + assert(m->hdr); + + k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len, + 0, &addr.sa, sizeof(addr)); + if (k < 0) + return -errno; + + return k; +} + +static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) { + union sockaddr_union sender; + uint8_t cmsg_buffer[CMSG_SPACE(sizeof(struct nl_pktinfo))]; + struct msghdr msg = { + .msg_iov = iov, + .msg_iovlen = 1, + .msg_name = &sender, + .msg_namelen = sizeof(sender), + .msg_control = cmsg_buffer, + .msg_controllen = sizeof(cmsg_buffer), + }; + struct cmsghdr *cmsg; + uint32_t group = 0; + ssize_t n; + + assert(fd >= 0); + assert(iov); + + n = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0)); + if (n < 0) { + /* no data */ + if (errno == ENOBUFS) + log_debug("rtnl: kernel receive buffer overrun"); + else if (errno == EAGAIN) + log_debug("rtnl: no data in socket"); + + return IN_SET(errno, EAGAIN, EINTR) ? 0 : -errno; + } + + if (sender.nl.nl_pid != 0) { + /* not from the kernel, ignore */ + log_debug("rtnl: ignoring message from portid %"PRIu32, sender.nl.nl_pid); + + if (peek) { + /* drop the message */ + n = recvmsg(fd, &msg, 0); + if (n < 0) + return IN_SET(errno, EAGAIN, EINTR) ? 0 : -errno; + } + + return 0; + } + + CMSG_FOREACH(cmsg, &msg) { + if (cmsg->cmsg_level == SOL_NETLINK && + cmsg->cmsg_type == NETLINK_PKTINFO && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) { + struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg); + + /* multi-cast group */ + group = pktinfo->group; + } + } + + if (_group) + *_group = group; + + return (int) n; +} + +/* On success, the number of bytes received is returned and *ret points to the received message + * which has a valid header and the correct size. + * If nothing useful was received 0 is returned. + * On failure, a negative error code is returned. + */ +int socket_read_message(sd_netlink *rtnl) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *first = NULL; + struct iovec iov = {}; + uint32_t group = 0; + bool multi_part = false, done = false; + struct nlmsghdr *new_msg; + size_t len; + int r; + unsigned i = 0; + + assert(rtnl); + assert(rtnl->rbuffer); + assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr)); + + /* read nothing, just get the pending message size */ + r = socket_recv_message(rtnl->fd, &iov, NULL, true); + if (r <= 0) + return r; + else + len = (size_t) r; + + /* make room for the pending message */ + if (!greedy_realloc((void **)&rtnl->rbuffer, + &rtnl->rbuffer_allocated, + len, sizeof(uint8_t))) + return -ENOMEM; + + iov = IOVEC_MAKE(rtnl->rbuffer, rtnl->rbuffer_allocated); + + /* read the pending message */ + r = socket_recv_message(rtnl->fd, &iov, &group, false); + if (r <= 0) + return r; + else + len = (size_t) r; + + if (len > rtnl->rbuffer_allocated) + /* message did not fit in read buffer */ + return -EIO; + + if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) { + multi_part = true; + + for (i = 0; i < rtnl->rqueue_partial_size; i++) { + if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) == + rtnl->rbuffer->nlmsg_seq) { + first = rtnl->rqueue_partial[i]; + break; + } + } + } + + for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + const NLType *nl_type; + + if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid) + /* not broadcast and not for us */ + continue; + + if (new_msg->nlmsg_type == NLMSG_NOOP) + /* silently drop noop messages */ + continue; + + if (new_msg->nlmsg_type == NLMSG_DONE) { + /* finished reading multi-part message */ + done = true; + + /* if first is not defined, put NLMSG_DONE into the receive queue. */ + if (first) + continue; + } + + /* check that we support this message type */ + r = type_system_root_get_type(rtnl, &nl_type, new_msg->nlmsg_type); + if (r < 0) { + if (r == -EOPNOTSUPP) + log_debug("sd-netlink: ignored message with unknown type: %i", + new_msg->nlmsg_type); + + continue; + } + + /* check that the size matches the message type */ + if (new_msg->nlmsg_len < NLMSG_LENGTH(type_get_size(nl_type))) { + log_debug("sd-netlink: message is shorter than expected, dropping"); + continue; + } + + r = message_new_empty(rtnl, &m); + if (r < 0) + return r; + + m->broadcast = !!group; + + m->hdr = memdup(new_msg, new_msg->nlmsg_len); + if (!m->hdr) + return -ENOMEM; + + /* seal and parse the top-level message */ + r = sd_netlink_message_rewind(m, rtnl); + if (r < 0) + return r; + + /* push the message onto the multi-part message stack */ + if (first) + m->next = first; + first = TAKE_PTR(m); + } + + if (len > 0) + log_debug("sd-netlink: discarding %zu bytes of incoming message", len); + + if (!first) + return 0; + + if (!multi_part || done) { + /* we got a complete message, push it on the read queue */ + r = rtnl_rqueue_make_room(rtnl); + if (r < 0) + return r; + + rtnl->rqueue[rtnl->rqueue_size++] = TAKE_PTR(first); + + if (multi_part && (i < rtnl->rqueue_partial_size)) { + /* remove the message form the partial read queue */ + memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1, + sizeof(sd_netlink_message*) * (rtnl->rqueue_partial_size - i - 1)); + rtnl->rqueue_partial_size--; + } + + return 1; + } else { + /* we only got a partial multi-part message, push it on the + partial read queue */ + if (i < rtnl->rqueue_partial_size) + rtnl->rqueue_partial[i] = TAKE_PTR(first); + else { + r = rtnl_rqueue_partial_make_room(rtnl); + if (r < 0) + return r; + + rtnl->rqueue_partial[rtnl->rqueue_partial_size++] = TAKE_PTR(first); + } + + return 0; + } +} diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c new file mode 100644 index 00000000..a55460f0 --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -0,0 +1,1221 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-netlink.h" + +#include "generic-netlink.h" +#include "hashmap.h" +#include "macro.h" +#include "netlink-internal.h" +#include "netlink-types.h" +#include "string-table.h" +#include "util.h" + +/* Maximum ARP IP target defined in kernel */ +#define BOND_MAX_ARP_TARGETS 16 + +typedef enum { + BOND_ARP_TARGETS_0, + BOND_ARP_TARGETS_1, + BOND_ARP_TARGETS_2, + BOND_ARP_TARGETS_3, + BOND_ARP_TARGETS_4, + BOND_ARP_TARGETS_5, + BOND_ARP_TARGETS_6, + BOND_ARP_TARGETS_7, + BOND_ARP_TARGETS_8, + BOND_ARP_TARGETS_9, + BOND_ARP_TARGETS_10, + BOND_ARP_TARGETS_11, + BOND_ARP_TARGETS_12, + BOND_ARP_TARGETS_13, + BOND_ARP_TARGETS_14, + BOND_ARP_TARGETS_MAX = BOND_MAX_ARP_TARGETS, +} BondArpTargets; + +struct NLType { + uint16_t type; + size_t size; + const NLTypeSystem *type_system; + const NLTypeSystemUnion *type_system_union; +}; + +struct NLTypeSystem { + uint16_t count; + const NLType *types; +}; + +static const NLTypeSystem rtnl_link_type_system; + +static const NLType empty_types[1] = { + /* fake array to avoid .types==NULL, which denotes invalid type-systems */ +}; + +static const NLTypeSystem empty_type_system = { + .count = 0, + .types = empty_types, +}; + +static const NLType rtnl_link_info_data_veth_types[] = { + [VETH_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, +}; + +static const NLType rtnl_link_info_data_vxcan_types[] = { + [VXCAN_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, +}; + +static const NLType rtnl_link_info_data_ipvlan_types[] = { + [IFLA_IPVLAN_MODE] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 }, +}; + +static const NLType rtnl_link_info_data_macvlan_types[] = { + [IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 }, + [IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 }, +}; + +static const NLType rtnl_link_info_data_bridge_types[] = { + [IFLA_BR_FORWARD_DELAY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BR_HELLO_TIME] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BR_MAX_AGE] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BR_AGEING_TIME] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BR_STP_STATE] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BR_PRIORITY] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_VLAN_FILTERING] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BR_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_GROUP_FWD_MASK] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_ROOT_PORT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_ROOT_PATH_COST] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BR_TOPOLOGY_CHANGE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BR_TOPOLOGY_CHANGE_DETECTED] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BR_HELLO_TIMER] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_TCN_TIMER] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_TOPOLOGY_CHANGE_TIMER] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_GC_TIMER] = { .type = NETLINK_TYPE_U64 }, + [IFLA_BR_GROUP_ADDR] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_FDB_FLUSH] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_MCAST_ROUTER] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BR_MCAST_SNOOPING] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BR_MCAST_QUERY_USE_IFADDR] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BR_MCAST_QUERIER] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BR_MCAST_HASH_ELASTICITY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BR_MCAST_HASH_MAX] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_MCAST_LAST_MEMBER_CNT] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BR_MCAST_STARTUP_QUERY_CNT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_MCAST_LAST_MEMBER_INTVL] = { .type = NETLINK_TYPE_U64 }, + [IFLA_BR_MCAST_MEMBERSHIP_INTVL] = { .type = NETLINK_TYPE_U64 }, + [IFLA_BR_MCAST_QUERIER_INTVL] = { .type = NETLINK_TYPE_U64 }, + [IFLA_BR_MCAST_QUERY_INTVL] = { .type = NETLINK_TYPE_U64 }, + [IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = { .type = NETLINK_TYPE_U64 }, + [IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = { .type = NETLINK_TYPE_U64 }, + [IFLA_BR_NF_CALL_IPTABLES] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BR_NF_CALL_IP6TABLES] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BR_NF_CALL_ARPTABLES] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BR_VLAN_DEFAULT_PVID] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BR_MCAST_IGMP_VERSION] = { .type = NETLINK_TYPE_U8 }, +}; + +static const NLType rtnl_link_info_data_vlan_types[] = { + [IFLA_VLAN_ID] = { .type = NETLINK_TYPE_U16 }, +/* + [IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) }, + [IFLA_VLAN_EGRESS_QOS] = { .type = NETLINK_TYPE_NESTED }, + [IFLA_VLAN_INGRESS_QOS] = { .type = NETLINK_TYPE_NESTED }, +*/ + [IFLA_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 }, +}; + +static const NLType rtnl_link_info_data_vxlan_types[] = { + [IFLA_VXLAN_ID] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VXLAN_GROUP] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_VXLAN_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VXLAN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_VXLAN_TTL] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_TOS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_LEARNING] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_AGEING] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VXLAN_LIMIT] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VXLAN_PORT_RANGE] = { .type = NETLINK_TYPE_U32}, + [IFLA_VXLAN_PROXY] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_RSC] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_L2MISS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_L3MISS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_PORT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_VXLAN_GROUP6] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_VXLAN_LOCAL6] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_VXLAN_UDP_CSUM] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_REMCSUM_TX] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_REMCSUM_RX] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_GBP] = { .type = NETLINK_TYPE_FLAG }, + [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG }, + [IFLA_VXLAN_COLLECT_METADATA] = { .type = NETLINK_TYPE_U8 }, + [IFLA_VXLAN_LABEL] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VXLAN_GPE] = { .type = NETLINK_TYPE_FLAG }, + [IFLA_VXLAN_TTL_INHERIT] = { .type = NETLINK_TYPE_FLAG }, + [IFLA_VXLAN_DF] = { .type = NETLINK_TYPE_U8 }, +}; + +static const NLType rtnl_bond_arp_target_types[] = { + [BOND_ARP_TARGETS_0] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_1] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_2] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_3] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_4] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_5] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_6] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_7] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_8] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_9] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_10] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_11] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_12] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_13] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_14] = { .type = NETLINK_TYPE_U32 }, + [BOND_ARP_TARGETS_MAX] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem rtnl_bond_arp_type_system = { + .count = ELEMENTSOF(rtnl_bond_arp_target_types), + .types = rtnl_bond_arp_target_types, +}; + +static const NLType rtnl_link_info_data_bond_types[] = { + [IFLA_BOND_MODE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_ACTIVE_SLAVE] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_MIIMON] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_UPDELAY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_DOWNDELAY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_USE_CARRIER] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_ARP_INTERVAL] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_ARP_IP_TARGET] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bond_arp_type_system }, + [IFLA_BOND_ARP_VALIDATE] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_ARP_ALL_TARGETS] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_PRIMARY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_PRIMARY_RESELECT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_FAIL_OVER_MAC] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_XMIT_HASH_POLICY] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_RESEND_IGMP] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_NUM_PEER_NOTIF] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_MIN_LINKS] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_LP_INTERVAL] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BOND_AD_LACP_RATE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_AD_SELECT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED }, + [IFLA_BOND_AD_ACTOR_SYS_PRIO] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BOND_AD_USER_PORT_KEY] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NETLINK_TYPE_ETHER_ADDR }, + [IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NETLINK_TYPE_U8 }, +}; + +static const NLType rtnl_link_info_data_iptun_types[] = { + [IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_TOS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_PMTUDISC] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_6RD_PREFIX] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NETLINK_TYPE_U32 }, + [IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_IPTUN_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 }, +}; + +static const NLType rtnl_link_info_data_ipgre_types[] = { + [IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_IKEY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GRE_OKEY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GRE_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_GRE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_GRE_TTL] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GRE_TOS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GRE_PMTUDISC] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GRE_FLOWINFO] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GRE_FLAGS] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GRE_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GRE_ERSPAN_INDEX] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLType rtnl_link_info_data_ipvti_types[] = { + [IFLA_VTI_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VTI_IKEY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VTI_OKEY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_VTI_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, +}; + +static const NLType rtnl_link_info_data_ip6tnl_types[] = { + [IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U32 }, + [IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_IPTUN_FLOWINFO] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLType rtnl_link_info_data_vrf_types[] = { + [IFLA_VRF_TABLE] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLType rtnl_link_info_data_geneve_types[] = { + [IFLA_GENEVE_ID] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GENEVE_TTL] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GENEVE_TOS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GENEVE_PORT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_GENEVE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_GENEVE_REMOTE6] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_GENEVE_UDP_CSUM] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GENEVE_LABEL] = { .type = NETLINK_TYPE_U32 }, + [IFLA_GENEVE_TTL_INHERIT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_GENEVE_DF] = { .type = NETLINK_TYPE_U8 }, +}; + +static const NLType rtnl_link_info_data_can_types[] = { + [IFLA_CAN_BITTIMING] = { .size = sizeof(struct can_bittiming) }, + [IFLA_CAN_RESTART_MS] = { .type = NETLINK_TYPE_U32 }, + [IFLA_CAN_CTRLMODE] = { .size = sizeof(struct can_ctrlmode) }, +}; + +static const NLType rtnl_link_info_data_macsec_types[] = { + [IFLA_MACSEC_SCI] = { .type = NETLINK_TYPE_U64 }, + [IFLA_MACSEC_PORT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_MACSEC_ICV_LEN] = { .type = NETLINK_TYPE_U8 }, + [IFLA_MACSEC_CIPHER_SUITE] = { .type = NETLINK_TYPE_U64 }, + [IFLA_MACSEC_WINDOW] = { .type = NETLINK_TYPE_U32 }, + [IFLA_MACSEC_ENCODING_SA] = { .type = NETLINK_TYPE_U8 }, + [IFLA_MACSEC_ENCRYPT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_MACSEC_PROTECT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_MACSEC_INC_SCI] = { .type = NETLINK_TYPE_U8 }, + [IFLA_MACSEC_ES] = { .type = NETLINK_TYPE_U8 }, + [IFLA_MACSEC_SCB] = { .type = NETLINK_TYPE_U8 }, + [IFLA_MACSEC_REPLAY_PROTECT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_MACSEC_VALIDATION] = { .type = NETLINK_TYPE_U8 }, +}; + +static const NLType rtnl_link_info_data_xfrm_types[] = { + [IFLA_XFRM_LINK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_XFRM_IF_ID] = { .type = NETLINK_TYPE_U32 } +}; + +/* these strings must match the .kind entries in the kernel */ +static const char* const nl_union_link_info_data_table[] = { + [NL_UNION_LINK_INFO_DATA_BOND] = "bond", + [NL_UNION_LINK_INFO_DATA_BRIDGE] = "bridge", + [NL_UNION_LINK_INFO_DATA_VLAN] = "vlan", + [NL_UNION_LINK_INFO_DATA_VETH] = "veth", + [NL_UNION_LINK_INFO_DATA_DUMMY] = "dummy", + [NL_UNION_LINK_INFO_DATA_MACVLAN] = "macvlan", + [NL_UNION_LINK_INFO_DATA_MACVTAP] = "macvtap", + [NL_UNION_LINK_INFO_DATA_IPVLAN] = "ipvlan", + [NL_UNION_LINK_INFO_DATA_IPVTAP] = "ipvtap", + [NL_UNION_LINK_INFO_DATA_VXLAN] = "vxlan", + [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = "ipip", + [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = "gre", + [NL_UNION_LINK_INFO_DATA_ERSPAN] = "erspan", + [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = "gretap", + [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = "ip6gre", + [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = "ip6gretap", + [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = "sit", + [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = "vti", + [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = "vti6", + [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl", + [NL_UNION_LINK_INFO_DATA_VRF] = "vrf", + [NL_UNION_LINK_INFO_DATA_VCAN] = "vcan", + [NL_UNION_LINK_INFO_DATA_GENEVE] = "geneve", + [NL_UNION_LINK_INFO_DATA_VXCAN] = "vxcan", + [NL_UNION_LINK_INFO_DATA_WIREGUARD] = "wireguard", + [NL_UNION_LINK_INFO_DATA_NETDEVSIM] = "netdevsim", + [NL_UNION_LINK_INFO_DATA_CAN] = "can", + [NL_UNION_LINK_INFO_DATA_MACSEC] = "macsec", + [NL_UNION_LINK_INFO_DATA_NLMON] = "nlmon", + [NL_UNION_LINK_INFO_DATA_XFRM] = "xfrm", +}; + +DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData); + +static const NLTypeSystem rtnl_link_info_data_type_systems[] = { + [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types), + .types = rtnl_link_info_data_bond_types }, + [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types), + .types = rtnl_link_info_data_bridge_types }, + [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types), + .types = rtnl_link_info_data_vlan_types }, + [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types), + .types = rtnl_link_info_data_veth_types }, + [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), + .types = rtnl_link_info_data_macvlan_types }, + [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), + .types = rtnl_link_info_data_macvlan_types }, + [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types), + .types = rtnl_link_info_data_ipvlan_types }, + [NL_UNION_LINK_INFO_DATA_IPVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types), + .types = rtnl_link_info_data_ipvlan_types }, + [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types), + .types = rtnl_link_info_data_vxlan_types }, + [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), + .types = rtnl_link_info_data_iptun_types }, + [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_ERSPAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), + .types = rtnl_link_info_data_iptun_types }, + [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), + .types = rtnl_link_info_data_ipvti_types }, + [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), + .types = rtnl_link_info_data_ipvti_types }, + [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types), + .types = rtnl_link_info_data_ip6tnl_types }, + [NL_UNION_LINK_INFO_DATA_VRF] = { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types), + .types = rtnl_link_info_data_vrf_types }, + [NL_UNION_LINK_INFO_DATA_GENEVE] = { .count = ELEMENTSOF(rtnl_link_info_data_geneve_types), + .types = rtnl_link_info_data_geneve_types }, + [NL_UNION_LINK_INFO_DATA_VXCAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxcan_types), + .types = rtnl_link_info_data_vxcan_types }, + [NL_UNION_LINK_INFO_DATA_CAN] = { .count = ELEMENTSOF(rtnl_link_info_data_can_types), + .types = rtnl_link_info_data_can_types }, + [NL_UNION_LINK_INFO_DATA_MACSEC] = { .count = ELEMENTSOF(rtnl_link_info_data_macsec_types), + .types = rtnl_link_info_data_macsec_types }, + [NL_UNION_LINK_INFO_DATA_XFRM] = { .count = ELEMENTSOF(rtnl_link_info_data_xfrm_types), + .types = rtnl_link_info_data_xfrm_types }, +}; + +static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = { + .num = _NL_UNION_LINK_INFO_DATA_MAX, + .lookup = nl_union_link_info_data_from_string, + .type_systems = rtnl_link_info_data_type_systems, + .match_type = NL_MATCH_SIBLING, + .match = IFLA_INFO_KIND, +}; + +static const NLType rtnl_link_info_types[] = { + [IFLA_INFO_KIND] = { .type = NETLINK_TYPE_STRING }, + [IFLA_INFO_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_link_info_data_type_system_union}, +/* + [IFLA_INFO_XSTATS], + [IFLA_INFO_SLAVE_KIND] = { .type = NETLINK_TYPE_STRING }, + [IFLA_INFO_SLAVE_DATA] = { .type = NETLINK_TYPE_NESTED }, +*/ +}; + +static const NLTypeSystem rtnl_link_info_type_system = { + .count = ELEMENTSOF(rtnl_link_info_types), + .types = rtnl_link_info_types, +}; + +static const struct NLType rtnl_prot_info_bridge_port_types[] = { + [IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 }, + [IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_PROXYARP_WIFI] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_ROOT_ID] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_BRIDGE_ID] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_DESIGNATED_PORT] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BRPORT_DESIGNATED_COST] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BRPORT_ID] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BRPORT_NO] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BRPORT_TOPOLOGY_CHANGE_ACK] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_CONFIG_PENDING] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_MESSAGE_AGE_TIMER] = { .type = NETLINK_TYPE_U64 }, + [IFLA_BRPORT_FORWARD_DELAY_TIMER] = { .type = NETLINK_TYPE_U64 }, + [IFLA_BRPORT_HOLD_TIMER] = { .type = NETLINK_TYPE_U64 }, + [IFLA_BRPORT_FLUSH] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_PAD] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_MCAST_FLOOD] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_VLAN_TUNNEL] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_BCAST_FLOOD] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_GROUP_FWD_MASK] = { .type = NETLINK_TYPE_U16 }, + [IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_ISOLATED] = { .type = NETLINK_TYPE_U8 }, + [IFLA_BRPORT_BACKUP_PORT] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem rtnl_prot_info_type_systems[] = { + [AF_BRIDGE] = { .count = ELEMENTSOF(rtnl_prot_info_bridge_port_types), + .types = rtnl_prot_info_bridge_port_types }, +}; + +static const NLTypeSystemUnion rtnl_prot_info_type_system_union = { + .num = AF_MAX, + .type_systems = rtnl_prot_info_type_systems, + .match_type = NL_MATCH_PROTOCOL, +}; + +static const struct NLType rtnl_af_spec_inet6_types[] = { + [IFLA_INET6_FLAGS] = { .type = NETLINK_TYPE_U32 }, +/* + IFLA_INET6_CONF, + IFLA_INET6_STATS, + IFLA_INET6_MCAST, + IFLA_INET6_CACHEINFO, + IFLA_INET6_ICMP6STATS, +*/ + [IFLA_INET6_TOKEN] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFLA_INET6_ADDR_GEN_MODE] = { .type = NETLINK_TYPE_U8 }, +}; + +static const NLTypeSystem rtnl_af_spec_inet6_type_system = { + .count = ELEMENTSOF(rtnl_af_spec_inet6_types), + .types = rtnl_af_spec_inet6_types, +}; + +static const NLType rtnl_af_spec_types[] = { + [AF_INET6] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_inet6_type_system }, +}; + +static const NLTypeSystem rtnl_af_spec_type_system = { + .count = ELEMENTSOF(rtnl_af_spec_types), + .types = rtnl_af_spec_types, +}; + +static const NLType rtnl_link_types[] = { + [IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR }, + [IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR }, + [IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 }, + [IFLA_MTU] = { .type = NETLINK_TYPE_U32 }, + [IFLA_LINK] = { .type = NETLINK_TYPE_U32 }, +/* + [IFLA_QDISC], +*/ + [IFLA_STATS] = { .size = sizeof(struct rtnl_link_stats) }, +/* + [IFLA_COST], + [IFLA_PRIORITY], +*/ + [IFLA_MASTER] = { .type = NETLINK_TYPE_U32 }, +/* + [IFLA_WIRELESS], +*/ + [IFLA_PROTINFO] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_prot_info_type_system_union }, + [IFLA_TXQLEN] = { .type = NETLINK_TYPE_U32 }, +/* + [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, +*/ + [IFLA_WEIGHT] = { .type = NETLINK_TYPE_U32 }, + [IFLA_OPERSTATE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_LINKMODE] = { .type = NETLINK_TYPE_U8 }, + [IFLA_LINKINFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_info_type_system }, + [IFLA_NET_NS_PID] = { .type = NETLINK_TYPE_U32 }, + [IFLA_IFALIAS] = { .type = NETLINK_TYPE_STRING, .size = IFALIASZ - 1 }, +/* + [IFLA_NUM_VF], + [IFLA_VFINFO_LIST] = {. type = NETLINK_TYPE_NESTED, }, +*/ + [IFLA_STATS64] = { .size = sizeof(struct rtnl_link_stats64) }, +/* + [IFLA_VF_PORTS] = { .type = NETLINK_TYPE_NESTED }, + [IFLA_PORT_SELF] = { .type = NETLINK_TYPE_NESTED }, +*/ + [IFLA_AF_SPEC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_type_system }, +/* + [IFLA_VF_PORTS], + [IFLA_PORT_SELF], + [IFLA_AF_SPEC], +*/ + [IFLA_GROUP] = { .type = NETLINK_TYPE_U32 }, + [IFLA_NET_NS_FD] = { .type = NETLINK_TYPE_U32 }, + [IFLA_EXT_MASK] = { .type = NETLINK_TYPE_U32 }, + [IFLA_PROMISCUITY] = { .type = NETLINK_TYPE_U32 }, + [IFLA_NUM_TX_QUEUES] = { .type = NETLINK_TYPE_U32 }, + [IFLA_NUM_RX_QUEUES] = { .type = NETLINK_TYPE_U32 }, + [IFLA_CARRIER] = { .type = NETLINK_TYPE_U8 }, +/* + [IFLA_PHYS_PORT_ID] = { .type = NETLINK_TYPE_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, +*/ + [IFLA_MIN_MTU] = { .type = NETLINK_TYPE_U32 }, + [IFLA_MAX_MTU] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem rtnl_link_type_system = { + .count = ELEMENTSOF(rtnl_link_types), + .types = rtnl_link_types, +}; + +/* IFA_FLAGS was defined in kernel 3.14, but we still support older + * kernels where IFA_MAX is lower. */ +static const NLType rtnl_address_types[] = { + [IFA_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFA_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR }, + [IFA_LABEL] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 }, + [IFA_BROADCAST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ + [IFA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) }, +/* + [IFA_ANYCAST], + [IFA_MULTICAST], +*/ + [IFA_FLAGS] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem rtnl_address_type_system = { + .count = ELEMENTSOF(rtnl_address_types), + .types = rtnl_address_types, +}; + +/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */ + +static const NLType rtnl_route_metrics_types[] = { + [RTAX_MTU] = { .type = NETLINK_TYPE_U32 }, + [RTAX_WINDOW] = { .type = NETLINK_TYPE_U32 }, + [RTAX_RTT] = { .type = NETLINK_TYPE_U32 }, + [RTAX_RTTVAR] = { .type = NETLINK_TYPE_U32 }, + [RTAX_SSTHRESH] = { .type = NETLINK_TYPE_U32 }, + [RTAX_CWND] = { .type = NETLINK_TYPE_U32 }, + [RTAX_ADVMSS] = { .type = NETLINK_TYPE_U32 }, + [RTAX_REORDERING] = { .type = NETLINK_TYPE_U32 }, + [RTAX_HOPLIMIT] = { .type = NETLINK_TYPE_U32 }, + [RTAX_INITCWND] = { .type = NETLINK_TYPE_U32 }, + [RTAX_FEATURES] = { .type = NETLINK_TYPE_U32 }, + [RTAX_RTO_MIN] = { .type = NETLINK_TYPE_U32 }, + [RTAX_INITRWND] = { .type = NETLINK_TYPE_U32 }, + [RTAX_QUICKACK] = { .type = NETLINK_TYPE_U32 }, + [RTAX_CC_ALGO] = { .type = NETLINK_TYPE_U32 }, + [RTAX_FASTOPEN_NO_COOKIE] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem rtnl_route_metrics_type_system = { + .count = ELEMENTSOF(rtnl_route_metrics_types), + .types = rtnl_route_metrics_types, +}; + +static const NLType rtnl_route_types[] = { + [RTA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ + [RTA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ + [RTA_IIF] = { .type = NETLINK_TYPE_U32 }, + [RTA_OIF] = { .type = NETLINK_TYPE_U32 }, + [RTA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR }, + [RTA_PRIORITY] = { .type = NETLINK_TYPE_U32 }, + [RTA_PREFSRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ + [RTA_METRICS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_metrics_type_system}, + [RTA_MULTIPATH] = { .size = sizeof(struct rtnexthop) }, + [RTA_FLOW] = { .type = NETLINK_TYPE_U32 }, /* 6? */ + [RTA_CACHEINFO] = { .size = sizeof(struct rta_cacheinfo) }, + [RTA_TABLE] = { .type = NETLINK_TYPE_U32 }, + [RTA_MARK] = { .type = NETLINK_TYPE_U32 }, + [RTA_MFC_STATS] = { .type = NETLINK_TYPE_U64 }, + [RTA_VIA] = { .type = NETLINK_TYPE_U32 }, + [RTA_NEWDST] = { .type = NETLINK_TYPE_U32 }, + [RTA_PREF] = { .type = NETLINK_TYPE_U8 }, + [RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 }, + [RTA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 }, + [RTA_ENCAP] = { .type = NETLINK_TYPE_NESTED }, /* Multiple type systems i.e. LWTUNNEL_ENCAP_MPLS/LWTUNNEL_ENCAP_IP/LWTUNNEL_ENCAP_ILA etc... */ + [RTA_UID] = { .type = NETLINK_TYPE_U32 }, + [RTA_TTL_PROPAGATE] = { .type = NETLINK_TYPE_U8 }, + [RTA_IP_PROTO] = { .type = NETLINK_TYPE_U8 }, + [RTA_SPORT] = { .type = NETLINK_TYPE_U16 }, + [RTA_DPORT] = { .type = NETLINK_TYPE_U16 }, +}; + +static const NLTypeSystem rtnl_route_type_system = { + .count = ELEMENTSOF(rtnl_route_types), + .types = rtnl_route_types, +}; + +static const NLType rtnl_neigh_types[] = { + [NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, + [NDA_LLADDR] = { /* struct ether_addr, struct in_addr, or struct in6_addr */ }, + [NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) }, + [NDA_PROBES] = { .type = NETLINK_TYPE_U32 }, + [NDA_VLAN] = { .type = NETLINK_TYPE_U16 }, + [NDA_PORT] = { .type = NETLINK_TYPE_U16 }, + [NDA_VNI] = { .type = NETLINK_TYPE_U32 }, + [NDA_IFINDEX] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem rtnl_neigh_type_system = { + .count = ELEMENTSOF(rtnl_neigh_types), + .types = rtnl_neigh_types, +}; + +static const NLType rtnl_addrlabel_types[] = { + [IFAL_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) }, + [IFAL_LABEL] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem rtnl_addrlabel_type_system = { + .count = ELEMENTSOF(rtnl_addrlabel_types), + .types = rtnl_addrlabel_types, +}; + +static const NLType rtnl_routing_policy_rule_types[] = { + [FRA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, + [FRA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, + [FRA_IIFNAME] = { .type = NETLINK_TYPE_STRING }, + [FRA_GOTO] = { .type = NETLINK_TYPE_U32 }, + [FRA_PRIORITY] = { .type = NETLINK_TYPE_U32 }, + [FRA_FWMARK] = { .type = NETLINK_TYPE_U32 }, + [FRA_FLOW] = { .type = NETLINK_TYPE_U32 }, + [FRA_TUN_ID] = { .type = NETLINK_TYPE_U64 }, + [FRA_SUPPRESS_IFGROUP] = { .type = NETLINK_TYPE_U32 }, + [FRA_SUPPRESS_PREFIXLEN] = { .type = NETLINK_TYPE_U32 }, + [FRA_TABLE] = { .type = NETLINK_TYPE_U32 }, + [FRA_FWMASK] = { .type = NETLINK_TYPE_U32 }, + [FRA_OIFNAME] = { .type = NETLINK_TYPE_STRING }, + [FRA_PAD] = { .type = NETLINK_TYPE_U32 }, + [FRA_L3MDEV] = { .type = NETLINK_TYPE_U8 }, + [FRA_UID_RANGE] = { .size = sizeof(struct fib_rule_uid_range) }, + [FRA_PROTOCOL] = { .type = NETLINK_TYPE_U8 }, + [FRA_IP_PROTO] = { .type = NETLINK_TYPE_U8 }, + [FRA_SPORT_RANGE] = { .size = sizeof(struct fib_rule_port_range) }, + [FRA_DPORT_RANGE] = { .size = sizeof(struct fib_rule_port_range) }, +}; + +static const NLTypeSystem rtnl_routing_policy_rule_type_system = { + .count = ELEMENTSOF(rtnl_routing_policy_rule_types), + .types = rtnl_routing_policy_rule_types, +}; + +static const NLType rtnl_nexthop_types[] = { + [NHA_ID] = { .type = NETLINK_TYPE_U32 }, + [NHA_OIF] = { .type = NETLINK_TYPE_U32 }, + [NHA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR }, +}; + +static const NLTypeSystem rtnl_nexthop_type_system = { + .count = ELEMENTSOF(rtnl_nexthop_types), + .types = rtnl_nexthop_types, +}; + +static const NLType rtnl_qdisc_types[] = { + [TCA_KIND] = { .type = NETLINK_TYPE_STRING }, + [TCA_OPTIONS] = { .size = sizeof(struct tc_netem_qopt) }, + [TCA_INGRESS_BLOCK] = { .type = NETLINK_TYPE_U32 }, + [TCA_EGRESS_BLOCK] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem rtnl_qdisc_type_system = { + .count = ELEMENTSOF(rtnl_qdisc_types), + .types = rtnl_qdisc_types, +}; + +static const NLType rtnl_types[] = { + [NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 }, + [NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) }, + [RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, + [RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, + [RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, + [RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) }, + [RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, + [RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, + [RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) }, + [RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, + [RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, + [RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) }, + [RTM_NEWADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) }, + [RTM_DELADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) }, + [RTM_GETADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) }, + [RTM_NEWRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct rtmsg) }, + [RTM_DELRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct rtmsg) }, + [RTM_GETRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct rtmsg) }, + [RTM_NEWNEXTHOP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system, .size = sizeof(struct nhmsg) }, + [RTM_DELNEXTHOP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system, .size = sizeof(struct nhmsg) }, + [RTM_GETNEXTHOP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system, .size = sizeof(struct nhmsg) }, + [RTM_NEWQDISC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_qdisc_type_system, .size = sizeof(struct tcmsg) }, + [RTM_DELQDISC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_qdisc_type_system, .size = sizeof(struct tcmsg) }, + [RTM_GETQDISC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_qdisc_type_system, .size = sizeof(struct tcmsg) }, +}; + +const NLTypeSystem rtnl_type_system_root = { + .count = ELEMENTSOF(rtnl_types), + .types = rtnl_types, +}; + +static const NLType genl_wireguard_allowedip_types[] = { + [WGALLOWEDIP_A_FAMILY] = { .type = NETLINK_TYPE_U16 }, + [WGALLOWEDIP_A_IPADDR] = { .type = NETLINK_TYPE_IN_ADDR }, + [WGALLOWEDIP_A_CIDR_MASK] = { .type = NETLINK_TYPE_U8 }, +}; + +static const NLTypeSystem genl_wireguard_allowedip_type_system = { + .count = ELEMENTSOF(genl_wireguard_allowedip_types), + .types = genl_wireguard_allowedip_types, +}; + +static const NLType genl_wireguard_peer_types[] = { + [WGPEER_A_PUBLIC_KEY] = { .size = WG_KEY_LEN }, + [WGPEER_A_FLAGS] = { .type = NETLINK_TYPE_U32 }, + [WGPEER_A_PRESHARED_KEY] = { .size = WG_KEY_LEN }, + [WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NETLINK_TYPE_U16 }, + [WGPEER_A_ENDPOINT] = { .type = NETLINK_TYPE_SOCKADDR }, + [WGPEER_A_ALLOWEDIPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_allowedip_type_system }, +}; + +static const NLTypeSystem genl_wireguard_peer_type_system = { + .count = ELEMENTSOF(genl_wireguard_peer_types), + .types = genl_wireguard_peer_types, +}; + +static const NLType genl_wireguard_set_device_types[] = { + [WGDEVICE_A_IFINDEX] = { .type = NETLINK_TYPE_U32 }, + [WGDEVICE_A_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ-1 }, + [WGDEVICE_A_FLAGS] = { .type = NETLINK_TYPE_U32 }, + [WGDEVICE_A_PRIVATE_KEY] = { .size = WG_KEY_LEN }, + [WGDEVICE_A_LISTEN_PORT] = { .type = NETLINK_TYPE_U16 }, + [WGDEVICE_A_FWMARK] = { .type = NETLINK_TYPE_U32 }, + [WGDEVICE_A_PEERS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_peer_type_system }, +}; + +static const NLTypeSystem genl_wireguard_set_device_type_system = { + .count = ELEMENTSOF(genl_wireguard_set_device_types), + .types = genl_wireguard_set_device_types, +}; + +static const NLType genl_wireguard_cmds[] = { + [WG_CMD_SET_DEVICE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_set_device_type_system }, +}; + +static const NLTypeSystem genl_wireguard_type_system = { + .count = ELEMENTSOF(genl_wireguard_cmds), + .types = genl_wireguard_cmds, +}; + +static const NLType genl_mcast_group_types[] = { + [CTRL_ATTR_MCAST_GRP_NAME] = { .type = NETLINK_TYPE_STRING }, + [CTRL_ATTR_MCAST_GRP_ID] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem genl_mcast_group_type_system = { + .count = ELEMENTSOF(genl_mcast_group_types), + .types = genl_mcast_group_types, +}; + +static const NLType genl_get_family_types[] = { + [CTRL_ATTR_FAMILY_NAME] = { .type = NETLINK_TYPE_STRING }, + [CTRL_ATTR_FAMILY_ID] = { .type = NETLINK_TYPE_U16 }, + [CTRL_ATTR_MCAST_GROUPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_mcast_group_type_system }, +}; + +static const NLTypeSystem genl_get_family_type_system = { + .count = ELEMENTSOF(genl_get_family_types), + .types = genl_get_family_types, +}; + +static const NLType genl_ctrl_id_ctrl_cmds[] = { + [CTRL_CMD_GETFAMILY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_get_family_type_system }, +}; + +static const NLTypeSystem genl_ctrl_id_ctrl_type_system = { + .count = ELEMENTSOF(genl_ctrl_id_ctrl_cmds), + .types = genl_ctrl_id_ctrl_cmds, +}; + +static const NLType genl_fou_types[] = { + [FOU_ATTR_PORT] = { .type = NETLINK_TYPE_U16 }, + [FOU_ATTR_AF] = { .type = NETLINK_TYPE_U8 }, + [FOU_ATTR_IPPROTO] = { .type = NETLINK_TYPE_U8 }, + [FOU_ATTR_TYPE] = { .type = NETLINK_TYPE_U8 }, + [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG }, + [FOU_ATTR_LOCAL_V4] = { .type = NETLINK_TYPE_IN_ADDR }, + [FOU_ATTR_PEER_V4] = { .type = NETLINK_TYPE_IN_ADDR }, + [FOU_ATTR_LOCAL_V6] = { .type = NETLINK_TYPE_IN_ADDR }, + [FOU_ATTR_PEER_V6] = { .type = NETLINK_TYPE_IN_ADDR}, + [FOU_ATTR_PEER_PORT] = { .type = NETLINK_TYPE_U16}, + [FOU_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32}, +}; + +static const NLTypeSystem genl_fou_type_system = { + .count = ELEMENTSOF(genl_fou_types), + .types = genl_fou_types, +}; + +static const NLType genl_fou_cmds[] = { + [FOU_CMD_ADD] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_type_system }, + [FOU_CMD_DEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_type_system }, + [FOU_CMD_GET] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_type_system }, +}; + +static const NLTypeSystem genl_fou_cmds_type_system = { + .count = ELEMENTSOF(genl_fou_cmds), + .types = genl_fou_cmds, +}; + +static const NLType genl_l2tp_types[] = { + [L2TP_ATTR_PW_TYPE] = { .type = NETLINK_TYPE_U16 }, + [L2TP_ATTR_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 }, + [L2TP_ATTR_OFFSET] = { .type = NETLINK_TYPE_U16 }, + [L2TP_ATTR_DATA_SEQ] = { .type = NETLINK_TYPE_U16 }, + [L2TP_ATTR_L2SPEC_TYPE] = { .type = NETLINK_TYPE_U8 }, + [L2TP_ATTR_L2SPEC_LEN] = { .type = NETLINK_TYPE_U8 }, + [L2TP_ATTR_PROTO_VERSION] = { .type = NETLINK_TYPE_U8 }, + [L2TP_ATTR_IFNAME] = { .type = NETLINK_TYPE_STRING }, + [L2TP_ATTR_CONN_ID] = { .type = NETLINK_TYPE_U32 }, + [L2TP_ATTR_PEER_CONN_ID] = { .type = NETLINK_TYPE_U32 }, + [L2TP_ATTR_SESSION_ID] = { .type = NETLINK_TYPE_U32 }, + [L2TP_ATTR_PEER_SESSION_ID] = { .type = NETLINK_TYPE_U32 }, + [L2TP_ATTR_UDP_CSUM] = { .type = NETLINK_TYPE_U8 }, + [L2TP_ATTR_VLAN_ID] = { .type = NETLINK_TYPE_U16 }, + [L2TP_ATTR_RECV_SEQ] = { .type = NETLINK_TYPE_U8 }, + [L2TP_ATTR_SEND_SEQ] = { .type = NETLINK_TYPE_U8 }, + [L2TP_ATTR_LNS_MODE] = { .type = NETLINK_TYPE_U8 }, + [L2TP_ATTR_USING_IPSEC] = { .type = NETLINK_TYPE_U8 }, + [L2TP_ATTR_FD] = { .type = NETLINK_TYPE_U32 }, + [L2TP_ATTR_IP_SADDR] = { .type = NETLINK_TYPE_IN_ADDR }, + [L2TP_ATTR_IP_DADDR] = { .type = NETLINK_TYPE_IN_ADDR }, + [L2TP_ATTR_UDP_SPORT] = { .type = NETLINK_TYPE_U16 }, + [L2TP_ATTR_UDP_DPORT] = { .type = NETLINK_TYPE_U16 }, + [L2TP_ATTR_IP6_SADDR] = { .type = NETLINK_TYPE_IN_ADDR }, + [L2TP_ATTR_IP6_DADDR] = { .type = NETLINK_TYPE_IN_ADDR }, + [L2TP_ATTR_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_FLAG }, + [L2TP_ATTR_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_FLAG }, +}; + +static const NLTypeSystem genl_l2tp_type_system = { + .count = ELEMENTSOF(genl_l2tp_types), + .types = genl_l2tp_types, +}; + +static const NLType genl_l2tp[] = { + [L2TP_CMD_TUNNEL_CREATE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_type_system }, + [L2TP_CMD_TUNNEL_DELETE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_type_system }, + [L2TP_CMD_TUNNEL_MODIFY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_type_system }, + [L2TP_CMD_TUNNEL_GET] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_type_system }, + [L2TP_CMD_SESSION_CREATE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_type_system }, + [L2TP_CMD_SESSION_DELETE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_type_system }, + [L2TP_CMD_SESSION_MODIFY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_type_system }, + [L2TP_CMD_SESSION_GET] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_type_system }, +}; + +static const NLTypeSystem genl_l2tp_tunnel_session_type_system = { + .count = ELEMENTSOF(genl_l2tp), + .types = genl_l2tp, +}; + +static const NLType genl_rxsc_types[] = { + [MACSEC_RXSC_ATTR_SCI] = { .type = NETLINK_TYPE_U64 }, +}; + +static const NLTypeSystem genl_rxsc_config_type_system = { + .count = ELEMENTSOF(genl_rxsc_types), + .types = genl_rxsc_types, +}; + +static const NLType genl_macsec_rxsc_types[] = { + [MACSEC_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 }, + [MACSEC_ATTR_RXSC_CONFIG] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_rxsc_config_type_system }, +}; + +static const NLTypeSystem genl_macsec_rxsc_type_system = { + .count = ELEMENTSOF(genl_macsec_rxsc_types), + .types = genl_macsec_rxsc_types, +}; + +static const NLType genl_macsec_sa_config_types[] = { + [MACSEC_SA_ATTR_AN] = { .type = NETLINK_TYPE_U8 }, + [MACSEC_SA_ATTR_ACTIVE] = { .type = NETLINK_TYPE_U8 }, + [MACSEC_SA_ATTR_PN] = { .type = NETLINK_TYPE_U32 }, + [MACSEC_SA_ATTR_KEYID] = { .size = MACSEC_KEYID_LEN }, + [MACSEC_SA_ATTR_KEY] = { .size = MACSEC_MAX_KEY_LEN }, +}; + +static const NLTypeSystem genl_macsec_sa_config_type_system = { + .count = ELEMENTSOF(genl_macsec_sa_config_types), + .types = genl_macsec_sa_config_types, +}; + +static const NLType genl_macsec_rxsa_types[] = { + [MACSEC_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 }, + [MACSEC_ATTR_SA_CONFIG] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_sa_config_type_system }, +}; + +static const NLTypeSystem genl_macsec_rxsa_type_system = { + .count = ELEMENTSOF(genl_macsec_rxsa_types), + .types = genl_macsec_rxsa_types, +}; + +static const NLType genl_macsec_sa_types[] = { + [MACSEC_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 }, + [MACSEC_ATTR_RXSC_CONFIG] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_rxsc_config_type_system }, + [MACSEC_ATTR_SA_CONFIG] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_sa_config_type_system }, +}; + +static const NLTypeSystem genl_macsec_sa_type_system = { + .count = ELEMENTSOF(genl_macsec_sa_types), + .types = genl_macsec_sa_types, +}; + +static const NLType genl_macsec[] = { + [MACSEC_CMD_ADD_RXSC] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_rxsc_type_system }, + [MACSEC_CMD_ADD_TXSA] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_rxsa_type_system}, + [MACSEC_CMD_ADD_RXSA] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_sa_type_system }, +}; + +static const NLTypeSystem genl_macsec_device_type_system = { + .count = ELEMENTSOF(genl_macsec), + .types = genl_macsec, +}; + +static const NLType genl_nl80211_types[] = { + [NL80211_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 }, + [NL80211_ATTR_MAC] = { .type = NETLINK_TYPE_ETHER_ADDR }, + [NL80211_ATTR_SSID] = { .type = NETLINK_TYPE_STRING }, + [NL80211_ATTR_IFTYPE] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem genl_nl80211_type_system = { + .count = ELEMENTSOF(genl_nl80211_types), + .types = genl_nl80211_types, +}; + +static const NLType genl_nl80211_cmds[] = { + [NL80211_CMD_GET_WIPHY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_SET_WIPHY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_NEW_WIPHY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_DEL_WIPHY] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_GET_INTERFACE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_SET_INTERFACE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_NEW_INTERFACE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_DEL_INTERFACE] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_GET_STATION] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_SET_STATION] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_NEW_STATION] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, + [NL80211_CMD_DEL_STATION] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system }, +}; + +static const NLTypeSystem genl_nl80211_cmds_type_system = { + .count = ELEMENTSOF(genl_nl80211_cmds), + .types = genl_nl80211_cmds, +}; + +static const NLType genl_families[] = { + [SD_GENL_ID_CTRL] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_id_ctrl_type_system }, + [SD_GENL_WIREGUARD] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_type_system }, + [SD_GENL_FOU] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_cmds_type_system }, + [SD_GENL_L2TP] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_l2tp_tunnel_session_type_system }, + [SD_GENL_MACSEC] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_device_type_system }, + [SD_GENL_NL80211] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_cmds_type_system }, +}; + +/* Mainly used when sending message */ +const NLTypeSystem genl_family_type_system_root = { + .count = ELEMENTSOF(genl_families), + .types = genl_families, +}; + +static const NLType genl_types[] = { + [SD_GENL_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) }, + [SD_GENL_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system }, + [SD_GENL_ID_CTRL] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_get_family_type_system, .size = sizeof(struct genlmsghdr) }, + [SD_GENL_NL80211] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_nl80211_type_system, .size = sizeof(struct genlmsghdr) }, +}; + +/* Mainly used when message received */ +const NLTypeSystem genl_type_system_root = { + .count = ELEMENTSOF(genl_types), + .types = genl_types, +}; + +uint16_t type_get_type(const NLType *type) { + assert(type); + return type->type; +} + +size_t type_get_size(const NLType *type) { + assert(type); + return type->size; +} + +void type_get_type_system(const NLType *nl_type, const NLTypeSystem **ret) { + assert(nl_type); + assert(ret); + assert(nl_type->type == NETLINK_TYPE_NESTED); + assert(nl_type->type_system); + + *ret = nl_type->type_system; +} + +void type_get_type_system_union(const NLType *nl_type, const NLTypeSystemUnion **ret) { + assert(nl_type); + assert(ret); + assert(nl_type->type == NETLINK_TYPE_UNION); + assert(nl_type->type_system_union); + + *ret = nl_type->type_system_union; +} + +uint16_t type_system_get_count(const NLTypeSystem *type_system) { + assert(type_system); + return type_system->count; +} + +const NLTypeSystem *type_system_get_root(int protocol) { + switch (protocol) { + case NETLINK_GENERIC: + return &genl_type_system_root; + default: /* NETLINK_ROUTE: */ + return &rtnl_type_system_root; + } +} + +int type_system_root_get_type(sd_netlink *nl, const NLType **ret, uint16_t type) { + sd_genl_family family; + const NLType *nl_type; + int r; + + if (!nl || nl->protocol != NETLINK_GENERIC) + return type_system_get_type(&rtnl_type_system_root, ret, type); + + r = nlmsg_type_to_genl_family(nl, type, &family); + if (r < 0) + return r; + + if (family >= genl_type_system_root.count) + return -EOPNOTSUPP; + + nl_type = &genl_type_system_root.types[family]; + + if (nl_type->type == NETLINK_TYPE_UNSPEC) + return -EOPNOTSUPP; + + *ret = nl_type; + + return 0; +} + +int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type) { + const NLType *nl_type; + + assert(ret); + assert(type_system); + assert(type_system->types); + + if (type >= type_system->count) + return -EOPNOTSUPP; + + nl_type = &type_system->types[type]; + + if (nl_type->type == NETLINK_TYPE_UNSPEC) + return -EOPNOTSUPP; + + *ret = nl_type; + + return 0; +} + +int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type) { + const NLType *nl_type; + int r; + + assert(ret); + + r = type_system_get_type(type_system, &nl_type, type); + if (r < 0) + return r; + + type_get_type_system(nl_type, ret); + return 0; +} + +int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type) { + const NLType *nl_type; + int r; + + assert(ret); + + r = type_system_get_type(type_system, &nl_type, type); + if (r < 0) + return r; + + type_get_type_system_union(nl_type, ret); + return 0; +} + +int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key) { + int type; + + assert(type_system_union); + assert(type_system_union->match_type == NL_MATCH_SIBLING); + assert(type_system_union->lookup); + assert(type_system_union->type_systems); + assert(ret); + assert(key); + + type = type_system_union->lookup(key); + if (type < 0) + return -EOPNOTSUPP; + + assert(type < type_system_union->num); + + *ret = &type_system_union->type_systems[type]; + + return 0; +} + +int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol) { + const NLTypeSystem *type_system; + + assert(type_system_union); + assert(type_system_union->type_systems); + assert(type_system_union->match_type == NL_MATCH_PROTOCOL); + assert(ret); + + if (protocol >= type_system_union->num) + return -EOPNOTSUPP; + + type_system = &type_system_union->type_systems[protocol]; + if (!type_system->types) + return -EOPNOTSUPP; + + *ret = type_system; + + return 0; +} diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h new file mode 100644 index 00000000..9bc6f683 --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-types.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "macro.h" + +enum { + NETLINK_TYPE_UNSPEC, + NETLINK_TYPE_U8, /* NLA_U8 */ + NETLINK_TYPE_U16, /* NLA_U16 */ + NETLINK_TYPE_U32, /* NLA_U32 */ + NETLINK_TYPE_U64, /* NLA_U64 */ + NETLINK_TYPE_STRING, /* NLA_STRING */ + NETLINK_TYPE_FLAG, /* NLA_FLAG */ + NETLINK_TYPE_IN_ADDR, + NETLINK_TYPE_ETHER_ADDR, + NETLINK_TYPE_CACHE_INFO, + NETLINK_TYPE_NESTED, /* NLA_NESTED */ + NETLINK_TYPE_UNION, + NETLINK_TYPE_SOCKADDR, +}; + +typedef enum NLMatchType { + NL_MATCH_SIBLING, + NL_MATCH_PROTOCOL, +} NLMatchType; + +typedef struct NLTypeSystemUnion NLTypeSystemUnion; +typedef struct NLTypeSystem NLTypeSystem; +typedef struct NLType NLType; + +struct NLTypeSystemUnion { + int num; + NLMatchType match_type; + uint16_t match; + int (*lookup)(const char *); + const NLTypeSystem *type_systems; +}; + +extern const NLTypeSystem genl_family_type_system_root; + +uint16_t type_get_type(const NLType *type); +size_t type_get_size(const NLType *type); +void type_get_type_system(const NLType *type, const NLTypeSystem **ret); +void type_get_type_system_union(const NLType *type, const NLTypeSystemUnion **ret); + +const NLTypeSystem* type_system_get_root(int protocol); +uint16_t type_system_get_count(const NLTypeSystem *type_system); +int type_system_root_get_type(sd_netlink *nl, const NLType **ret, uint16_t type); +int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type); +int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type); +int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type); +int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key); +int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol); + +typedef enum NLUnionLinkInfoData { + NL_UNION_LINK_INFO_DATA_BOND, + NL_UNION_LINK_INFO_DATA_BRIDGE, + NL_UNION_LINK_INFO_DATA_VLAN, + NL_UNION_LINK_INFO_DATA_VETH, + NL_UNION_LINK_INFO_DATA_DUMMY, + NL_UNION_LINK_INFO_DATA_MACVLAN, + NL_UNION_LINK_INFO_DATA_MACVTAP, + NL_UNION_LINK_INFO_DATA_IPVLAN, + NL_UNION_LINK_INFO_DATA_IPVTAP, + NL_UNION_LINK_INFO_DATA_VXLAN, + NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL, + NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL, + NL_UNION_LINK_INFO_DATA_ERSPAN, + NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL, + NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL, + NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL, + NL_UNION_LINK_INFO_DATA_SIT_TUNNEL, + NL_UNION_LINK_INFO_DATA_VTI_TUNNEL, + NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL, + NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL, + NL_UNION_LINK_INFO_DATA_VRF, + NL_UNION_LINK_INFO_DATA_VCAN, + NL_UNION_LINK_INFO_DATA_GENEVE, + NL_UNION_LINK_INFO_DATA_VXCAN, + NL_UNION_LINK_INFO_DATA_WIREGUARD, + NL_UNION_LINK_INFO_DATA_NETDEVSIM, + NL_UNION_LINK_INFO_DATA_CAN, + NL_UNION_LINK_INFO_DATA_MACSEC, + NL_UNION_LINK_INFO_DATA_NLMON, + NL_UNION_LINK_INFO_DATA_XFRM, + _NL_UNION_LINK_INFO_DATA_MAX, + _NL_UNION_LINK_INFO_DATA_INVALID = -1 +} NLUnionLinkInfoData; + +const char *nl_union_link_info_data_to_string(NLUnionLinkInfoData p) _const_; +NLUnionLinkInfoData nl_union_link_info_data_from_string(const char *p) _pure_; diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c new file mode 100644 index 00000000..628ce507 --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-util.c @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-netlink.h" + +#include "netlink-internal.h" +#include "netlink-util.h" + +int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; + int r; + + assert(rtnl); + assert(ifindex > 0); + assert(name); + + if (!ifname_valid(name)) + return -EINVAL; + + if (!*rtnl) { + r = sd_netlink_open(rtnl); + if (r < 0) + return r; + } + + r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); + if (r < 0) + return r; + + r = sd_netlink_message_append_string(message, IFLA_IFNAME, name); + if (r < 0) + return r; + + r = sd_netlink_call(*rtnl, message, 0, NULL); + if (r < 0) + return r; + + return 0; +} + +int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, + const struct ether_addr *mac, uint32_t mtu) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; + int r; + + assert(rtnl); + assert(ifindex > 0); + + if (!alias && !mac && mtu == 0) + return 0; + + if (!*rtnl) { + r = sd_netlink_open(rtnl); + if (r < 0) + return r; + } + + r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); + if (r < 0) + return r; + + if (alias) { + r = sd_netlink_message_append_string(message, IFLA_IFALIAS, alias); + if (r < 0) + return r; + } + + if (mac) { + r = sd_netlink_message_append_ether_addr(message, IFLA_ADDRESS, mac); + if (r < 0) + return r; + } + + if (mtu != 0) { + r = sd_netlink_message_append_u32(message, IFLA_MTU, mtu); + if (r < 0) + return r; + } + + r = sd_netlink_call(*rtnl, message, 0, NULL); + if (r < 0) + return r; + + return 0; +} + +int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret) { + struct nlmsgerr *err; + int r; + + assert(error <= 0); + + r = message_new(rtnl, ret, NLMSG_ERROR); + if (r < 0) + return r; + + (*ret)->hdr->nlmsg_seq = serial; + + err = NLMSG_DATA((*ret)->hdr); + + err->error = error; + + return 0; +} + +int rtnl_log_parse_error(int r) { + return log_error_errno(r, "Failed to parse netlink message: %m"); +} + +int rtnl_log_create_error(int r) { + return log_error_errno(r, "Failed to create netlink message: %m"); +} diff --git a/src/libsystemd/sd-netlink/netlink-util.h b/src/libsystemd/sd-netlink/netlink-util.h new file mode 100644 index 00000000..94410e52 --- /dev/null +++ b/src/libsystemd/sd-netlink/netlink-util.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-netlink.h" + +#include "in-addr-util.h" +#include "socket-util.h" +#include "util.h" + +int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret); +uint32_t rtnl_message_get_serial(sd_netlink_message *m); +void rtnl_message_seal(sd_netlink_message *m); + +static inline bool rtnl_message_type_is_neigh(uint16_t type) { + return IN_SET(type, RTM_NEWNEIGH, RTM_GETNEIGH, RTM_DELNEIGH); +} + +static inline bool rtnl_message_type_is_route(uint16_t type) { + return IN_SET(type, RTM_NEWROUTE, RTM_GETROUTE, RTM_DELROUTE); +} + +static inline bool rtnl_message_type_is_nexthop(uint16_t type) { + return IN_SET(type, RTM_NEWNEXTHOP, RTM_GETNEXTHOP, RTM_DELNEXTHOP); +} + +static inline bool rtnl_message_type_is_link(uint16_t type) { + return IN_SET(type, RTM_NEWLINK, RTM_SETLINK, RTM_GETLINK, RTM_DELLINK); +} + +static inline bool rtnl_message_type_is_addr(uint16_t type) { + return IN_SET(type, RTM_NEWADDR, RTM_GETADDR, RTM_DELADDR); +} + +static inline bool rtnl_message_type_is_addrlabel(uint16_t type) { + return IN_SET(type, RTM_NEWADDRLABEL, RTM_DELADDRLABEL, RTM_GETADDRLABEL); +} + +static inline bool rtnl_message_type_is_routing_policy_rule(uint16_t type) { + return IN_SET(type, RTM_NEWRULE, RTM_DELRULE, RTM_GETRULE); +} + +static inline bool rtnl_message_type_is_qdisc(uint16_t type) { + return IN_SET(type, RTM_NEWQDISC, RTM_DELQDISC, RTM_GETQDISC); +} + +int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name); +int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, uint32_t mtu); + +int rtnl_log_parse_error(int r); +int rtnl_log_create_error(int r); + +#define netlink_call_async(nl, ret_slot, message, callback, destroy_callback, userdata) \ + ({ \ + int (*_callback_)(sd_netlink *, sd_netlink_message *, typeof(userdata)) = callback; \ + void (*_destroy_)(typeof(userdata)) = destroy_callback; \ + sd_netlink_call_async(nl, ret_slot, message, \ + (sd_netlink_message_handler_t) _callback_, \ + (sd_netlink_destroy_t) _destroy_, \ + userdata, 0, __func__); \ + }) + +#define netlink_add_match(nl, ret_slot, metch, callback, destroy_callback, userdata) \ + ({ \ + int (*_callback_)(sd_netlink *, sd_netlink_message *, typeof(userdata)) = callback; \ + void (*_destroy_)(typeof(userdata)) = destroy_callback; \ + sd_netlink_add_match(nl, ret_slot, match, \ + (sd_netlink_message_handler_t) _callback_, \ + (sd_netlink_destroy_t) _destroy_, \ + userdata, __func__); \ + }) + +int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data); +int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data); diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c new file mode 100644 index 00000000..5bf2efd5 --- /dev/null +++ b/src/libsystemd/sd-netlink/rtnl-message.c @@ -0,0 +1,1077 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-netlink.h" + +#include "format-util.h" +#include "netlink-internal.h" +#include "netlink-types.h" +#include "netlink-util.h" +#include "socket-util.h" +#include "util.h" + +int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + if ((rtm->rtm_family == AF_INET && prefixlen > 32) || + (rtm->rtm_family == AF_INET6 && prefixlen > 128)) + return -ERANGE; + + rtm->rtm_dst_len = prefixlen; + + return 0; +} + +int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + if ((rtm->rtm_family == AF_INET && prefixlen > 32) || + (rtm->rtm_family == AF_INET6 && prefixlen > 128)) + return -ERANGE; + + rtm->rtm_src_len = prefixlen; + + return 0; +} + +int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + rtm->rtm_scope = scope; + + return 0; +} + +int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + rtm->rtm_flags = flags; + + return 0; +} + +int sd_rtnl_message_route_get_flags(const sd_netlink_message *m, unsigned *flags) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(flags, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *flags = rtm->rtm_flags; + + return 0; +} + +int sd_rtnl_message_route_set_table(sd_netlink_message *m, unsigned char table) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + rtm->rtm_table = table; + + return 0; +} + +int sd_rtnl_message_route_get_family(const sd_netlink_message *m, int *family) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(family, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *family = rtm->rtm_family; + + return 0; +} + +int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + rtm->rtm_family = family; + + return 0; +} + +int sd_rtnl_message_route_get_type(const sd_netlink_message *m, unsigned char *type) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(type, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *type = rtm->rtm_type; + + return 0; +} + +int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + rtm->rtm_type = type; + + return 0; +} + +int sd_rtnl_message_route_get_protocol(const sd_netlink_message *m, unsigned char *protocol) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(protocol, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *protocol = rtm->rtm_protocol; + + return 0; +} + +int sd_rtnl_message_route_get_scope(const sd_netlink_message *m, unsigned char *scope) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(scope, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *scope = rtm->rtm_scope; + + return 0; +} + +int sd_rtnl_message_route_get_tos(const sd_netlink_message *m, unsigned char *tos) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(tos, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *tos = rtm->rtm_tos; + + return 0; +} + +int sd_rtnl_message_route_get_table(const sd_netlink_message *m, unsigned char *table) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(table, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *table = rtm->rtm_table; + + return 0; +} + +int sd_rtnl_message_route_get_dst_prefixlen(const sd_netlink_message *m, unsigned char *dst_len) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(dst_len, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *dst_len = rtm->rtm_dst_len; + + return 0; +} + +int sd_rtnl_message_route_get_src_prefixlen(const sd_netlink_message *m, unsigned char *src_len) { + struct rtmsg *rtm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); + assert_return(src_len, -EINVAL); + + rtm = NLMSG_DATA(m->hdr); + + *src_len = rtm->rtm_src_len; + + return 0; +} + +int sd_rtnl_message_new_route(sd_netlink *rtnl, sd_netlink_message **ret, + uint16_t nlmsg_type, int rtm_family, + unsigned char rtm_protocol) { + struct rtmsg *rtm; + int r; + + assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL); + assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) || + IN_SET(rtm_family, AF_INET, AF_INET6), -EINVAL); + assert_return(ret, -EINVAL); + + r = message_new(rtnl, ret, nlmsg_type); + if (r < 0) + return r; + + if (nlmsg_type == RTM_NEWROUTE) + (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND; + + rtm = NLMSG_DATA((*ret)->hdr); + + rtm->rtm_family = rtm_family; + rtm->rtm_scope = RT_SCOPE_UNIVERSE; + rtm->rtm_type = RTN_UNICAST; + rtm->rtm_table = RT_TABLE_MAIN; + rtm->rtm_protocol = rtm_protocol; + + return 0; +} + +int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, + uint16_t nhmsg_type, int nh_family, + unsigned char nh_protocol) { + struct nhmsg *nhm; + int r; + + assert_return(rtnl_message_type_is_nexthop(nhmsg_type), -EINVAL); + assert_return((nhmsg_type == RTM_GETNEXTHOP && nh_family == AF_UNSPEC) || + IN_SET(nh_family, AF_INET, AF_INET6), -EINVAL); + assert_return(ret, -EINVAL); + + r = message_new(rtnl, ret, nhmsg_type); + if (r < 0) + return r; + + if (nhmsg_type == RTM_NEWNEXTHOP) + (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND; + + nhm = NLMSG_DATA((*ret)->hdr); + + nhm->nh_family = nh_family; + nhm->nh_scope = RT_SCOPE_UNIVERSE; + nhm->nh_protocol = nh_protocol; + + return 0; +} + +int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags) { + struct nhmsg *nhm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_nexthop(m->hdr->nlmsg_type), -EINVAL); + + nhm = NLMSG_DATA(m->hdr); + nhm->nh_flags |= flags; + + return 0; +} + +int sd_rtnl_message_nexthop_set_family(sd_netlink_message *m, uint8_t family) { + struct nhmsg *nhm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + + nhm = NLMSG_DATA(m->hdr); + nhm->nh_family = family; + + return 0; +} + +int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *family) { + struct nhmsg *nhm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + + nhm = NLMSG_DATA(m->hdr); + *family = nhm->nh_family ; + + return 0; +} + +int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags) { + struct ndmsg *ndm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); + + ndm = NLMSG_DATA(m->hdr); + ndm->ndm_flags |= flags; + + return 0; +} + +int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state) { + struct ndmsg *ndm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); + + ndm = NLMSG_DATA(m->hdr); + ndm->ndm_state |= state; + + return 0; +} + +int sd_rtnl_message_neigh_get_flags(const sd_netlink_message *m, uint8_t *flags) { + struct ndmsg *ndm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); + + ndm = NLMSG_DATA(m->hdr); + *flags = ndm->ndm_flags; + + return 0; +} + +int sd_rtnl_message_neigh_get_state(const sd_netlink_message *m, uint16_t *state) { + struct ndmsg *ndm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); + + ndm = NLMSG_DATA(m->hdr); + *state = ndm->ndm_state; + + return 0; +} + +int sd_rtnl_message_neigh_get_family(const sd_netlink_message *m, int *family) { + struct ndmsg *ndm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); + assert_return(family, -EINVAL); + + ndm = NLMSG_DATA(m->hdr); + + *family = ndm->ndm_family; + + return 0; +} + +int sd_rtnl_message_neigh_get_ifindex(const sd_netlink_message *m, int *index) { + struct ndmsg *ndm; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); + assert_return(index, -EINVAL); + + ndm = NLMSG_DATA(m->hdr); + + *index = ndm->ndm_ifindex; + + return 0; +} + +int sd_rtnl_message_new_neigh(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int index, int ndm_family) { + struct ndmsg *ndm; + int r; + + assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL); + assert_return(IN_SET(ndm_family, AF_UNSPEC, AF_INET, AF_INET6, PF_BRIDGE), -EINVAL); + assert_return(ret, -EINVAL); + + r = message_new(rtnl, ret, nlmsg_type); + if (r < 0) + return r; + + if (nlmsg_type == RTM_NEWNEIGH) + (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND; + + ndm = NLMSG_DATA((*ret)->hdr); + + ndm->ndm_family = ndm_family; + ndm->ndm_ifindex = index; + + return 0; +} + +int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change) { + struct ifinfomsg *ifi; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); + assert_return(change, -EINVAL); + + ifi = NLMSG_DATA(m->hdr); + + ifi->ifi_flags = flags; + ifi->ifi_change = change; + + return 0; +} + +int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type) { + struct ifinfomsg *ifi; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); + + ifi = NLMSG_DATA(m->hdr); + + ifi->ifi_type = type; + + return 0; +} + +int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family) { + struct ifinfomsg *ifi; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); + + ifi = NLMSG_DATA(m->hdr); + + ifi->ifi_family = family; + + return 0; +} + +int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret, + uint16_t nlmsg_type, int index) { + struct ifinfomsg *ifi; + int r; + + assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL); + assert_return(ret, -EINVAL); + + r = message_new(rtnl, ret, nlmsg_type); + if (r < 0) + return r; + + if (nlmsg_type == RTM_NEWLINK) + (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; + + ifi = NLMSG_DATA((*ret)->hdr); + + ifi->ifi_family = AF_UNSPEC; + ifi->ifi_index = index; + + return 0; +} + +int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { + struct ifaddrmsg *ifa; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + + ifa = NLMSG_DATA(m->hdr); + + if ((ifa->ifa_family == AF_INET && prefixlen > 32) || + (ifa->ifa_family == AF_INET6 && prefixlen > 128)) + return -ERANGE; + + ifa->ifa_prefixlen = prefixlen; + + return 0; +} + +int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags) { + struct ifaddrmsg *ifa; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + + ifa = NLMSG_DATA(m->hdr); + + ifa->ifa_flags = flags; + + return 0; +} + +int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope) { + struct ifaddrmsg *ifa; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + + ifa = NLMSG_DATA(m->hdr); + + ifa->ifa_scope = scope; + + return 0; +} + +int sd_rtnl_message_addr_get_family(const sd_netlink_message *m, int *family) { + struct ifaddrmsg *ifa; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + assert_return(family, -EINVAL); + + ifa = NLMSG_DATA(m->hdr); + + *family = ifa->ifa_family; + + return 0; +} + +int sd_rtnl_message_addr_get_prefixlen(const sd_netlink_message *m, unsigned char *prefixlen) { + struct ifaddrmsg *ifa; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + assert_return(prefixlen, -EINVAL); + + ifa = NLMSG_DATA(m->hdr); + + *prefixlen = ifa->ifa_prefixlen; + + return 0; +} + +int sd_rtnl_message_addr_get_scope(const sd_netlink_message *m, unsigned char *scope) { + struct ifaddrmsg *ifa; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + assert_return(scope, -EINVAL); + + ifa = NLMSG_DATA(m->hdr); + + *scope = ifa->ifa_scope; + + return 0; +} + +int sd_rtnl_message_addr_get_flags(const sd_netlink_message *m, unsigned char *flags) { + struct ifaddrmsg *ifa; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + assert_return(flags, -EINVAL); + + ifa = NLMSG_DATA(m->hdr); + + *flags = ifa->ifa_flags; + + return 0; +} + +int sd_rtnl_message_addr_get_ifindex(const sd_netlink_message *m, int *ifindex) { + struct ifaddrmsg *ifa; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); + assert_return(ifindex, -EINVAL); + + ifa = NLMSG_DATA(m->hdr); + + *ifindex = ifa->ifa_index; + + return 0; +} + +int sd_rtnl_message_new_addr(sd_netlink *rtnl, sd_netlink_message **ret, + uint16_t nlmsg_type, int index, + int family) { + struct ifaddrmsg *ifa; + int r; + + assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL); + assert_return((nlmsg_type == RTM_GETADDR && index == 0) || + index > 0, -EINVAL); + assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) || + IN_SET(family, AF_INET, AF_INET6), -EINVAL); + assert_return(ret, -EINVAL); + + r = message_new(rtnl, ret, nlmsg_type); + if (r < 0) + return r; + + if (nlmsg_type == RTM_GETADDR) + (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP; + + ifa = NLMSG_DATA((*ret)->hdr); + + ifa->ifa_index = index; + ifa->ifa_family = family; + if (family == AF_INET) + ifa->ifa_prefixlen = 32; + else if (family == AF_INET6) + ifa->ifa_prefixlen = 128; + + return 0; +} + +int sd_rtnl_message_new_addr_update(sd_netlink *rtnl, sd_netlink_message **ret, + int index, int family) { + int r; + + r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family); + if (r < 0) + return r; + + (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE; + + return 0; +} + +int sd_rtnl_message_link_get_ifindex(const sd_netlink_message *m, int *ifindex) { + struct ifinfomsg *ifi; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); + assert_return(ifindex, -EINVAL); + + ifi = NLMSG_DATA(m->hdr); + + *ifindex = ifi->ifi_index; + + return 0; +} + +int sd_rtnl_message_link_get_flags(const sd_netlink_message *m, unsigned *flags) { + struct ifinfomsg *ifi; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); + assert_return(flags, -EINVAL); + + ifi = NLMSG_DATA(m->hdr); + + *flags = ifi->ifi_flags; + + return 0; +} + +int sd_rtnl_message_link_get_type(const sd_netlink_message *m, unsigned short *type) { + struct ifinfomsg *ifi; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); + assert_return(type, -EINVAL); + + ifi = NLMSG_DATA(m->hdr); + + *type = ifi->ifi_type; + + return 0; +} + +int sd_rtnl_message_get_family(const sd_netlink_message *m, int *family) { + assert_return(m, -EINVAL); + assert_return(family, -EINVAL); + + assert(m->hdr); + + if (rtnl_message_type_is_link(m->hdr->nlmsg_type)) { + struct ifinfomsg *ifi; + + ifi = NLMSG_DATA(m->hdr); + + *family = ifi->ifi_family; + + return 0; + } else if (rtnl_message_type_is_route(m->hdr->nlmsg_type)) { + struct rtmsg *rtm; + + rtm = NLMSG_DATA(m->hdr); + + *family = rtm->rtm_family; + + return 0; + } else if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type)) { + struct ndmsg *ndm; + + ndm = NLMSG_DATA(m->hdr); + + *family = ndm->ndm_family; + + return 0; + } else if (rtnl_message_type_is_addr(m->hdr->nlmsg_type)) { + struct ifaddrmsg *ifa; + + ifa = NLMSG_DATA(m->hdr); + + *family = ifa->ifa_family; + + return 0; + } else if (rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type)) { + struct rtmsg *rtm; + + rtm = NLMSG_DATA(m->hdr); + + *family = rtm->rtm_family; + + return 0; + } else if (rtnl_message_type_is_nexthop(m->hdr->nlmsg_type)) { + struct nhmsg *nhm; + + nhm = NLMSG_DATA(m->hdr); + + *family = nhm->nh_family; + + return 0; + } + + return -EOPNOTSUPP; +} + +int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family) { + struct ifaddrlblmsg *addrlabel; + int r; + + assert_return(rtnl_message_type_is_addrlabel(nlmsg_type), -EINVAL); + assert_return(ret, -EINVAL); + + r = message_new(rtnl, ret, nlmsg_type); + if (r < 0) + return r; + + if (nlmsg_type == RTM_NEWADDRLABEL) + (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; + + addrlabel = NLMSG_DATA((*ret)->hdr); + + addrlabel->ifal_family = ifal_family; + addrlabel->ifal_index = ifindex; + + return 0; +} + +int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { + struct ifaddrlblmsg *addrlabel; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL); + + addrlabel = NLMSG_DATA(m->hdr); + + if (prefixlen > 128) + return -ERANGE; + + addrlabel->ifal_prefixlen = prefixlen; + + return 0; +} + +int sd_rtnl_message_addrlabel_get_prefixlen(const sd_netlink_message *m, unsigned char *prefixlen) { + struct ifaddrlblmsg *addrlabel; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL); + + addrlabel = NLMSG_DATA(m->hdr); + + *prefixlen = addrlabel->ifal_prefixlen; + + return 0; +} + +int sd_rtnl_message_new_routing_policy_rule(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifal_family) { + struct rtmsg *rtm; + int r; + + assert_return(rtnl_message_type_is_routing_policy_rule(nlmsg_type), -EINVAL); + assert_return(ret, -EINVAL); + + r = message_new(rtnl, ret, nlmsg_type); + if (r < 0) + return r; + + if (nlmsg_type == RTM_NEWRULE) + (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; + + rtm = NLMSG_DATA((*ret)->hdr); + rtm->rtm_family = ifal_family; + rtm->rtm_protocol = RTPROT_BOOT; + rtm->rtm_scope = RT_SCOPE_UNIVERSE; + rtm->rtm_type = RTN_UNICAST; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_set_tos(sd_netlink_message *m, unsigned char tos) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + + routing_policy_rule->rtm_tos = tos; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_get_tos(const sd_netlink_message *m, unsigned char *tos) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + + *tos = routing_policy_rule->rtm_tos; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_set_table(sd_netlink_message *m, unsigned char table) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + + routing_policy_rule->rtm_table = table; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_get_table(const sd_netlink_message *m, unsigned char *table) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + + *table = routing_policy_rule->rtm_table; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, unsigned flags) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + routing_policy_rule->rtm_flags |= flags; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_get_flags(const sd_netlink_message *m, unsigned *flags) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + *flags = routing_policy_rule->rtm_flags; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + + routing_policy_rule->rtm_type = type; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_get_rtm_type(const sd_netlink_message *m, unsigned char *type) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + + *type = routing_policy_rule->rtm_type; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(sd_netlink_message *m, unsigned char len) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + + routing_policy_rule->rtm_dst_len = len; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(const sd_netlink_message *m, unsigned char *len) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + + *len = routing_policy_rule->rtm_dst_len; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(sd_netlink_message *m, unsigned char len) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + + routing_policy_rule->rtm_src_len = len; + + return 0; +} + +int sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(const sd_netlink_message *m, unsigned char *len) { + struct rtmsg *routing_policy_rule; + + assert_return(m, -EINVAL); + assert_return(m->hdr, -EINVAL); + assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); + + routing_policy_rule = NLMSG_DATA(m->hdr); + + *len = routing_policy_rule->rtm_src_len; + + return 0; +} + +int sd_rtnl_message_new_qdisc(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int tcm_family, int tcm_ifindex) { + struct tcmsg *tcm; + int r; + + assert_return(rtnl_message_type_is_qdisc(nlmsg_type), -EINVAL); + assert_return(ret, -EINVAL); + + r = message_new(rtnl, ret, nlmsg_type); + if (r < 0) + return r; + + if (nlmsg_type == RTM_NEWQDISC) + (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; + + tcm = NLMSG_DATA((*ret)->hdr); + tcm->tcm_family = tcm_family; + tcm->tcm_ifindex = tcm_ifindex; + + return 0; +} + +int sd_rtnl_message_set_qdisc_parent(sd_netlink_message *m, uint32_t parent) { + struct tcmsg *tcm; + + assert_return(rtnl_message_type_is_qdisc(m->hdr->nlmsg_type), -EINVAL); + + tcm = NLMSG_DATA(m->hdr); + tcm->tcm_parent = parent; + + return 0; +} + +int sd_rtnl_message_set_qdisc_handle(sd_netlink_message *m, uint32_t handle) { + struct tcmsg *tcm; + + assert_return(rtnl_message_type_is_qdisc(m->hdr->nlmsg_type), -EINVAL); + + tcm = NLMSG_DATA(m->hdr); + tcm->tcm_handle = handle; + + return 0; +} diff --git a/src/libsystemd/sd-netlink/sd-netlink.c b/src/libsystemd/sd-netlink/sd-netlink.c new file mode 100644 index 00000000..87350e85 --- /dev/null +++ b/src/libsystemd/sd-netlink/sd-netlink.c @@ -0,0 +1,922 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "hashmap.h" +#include "macro.h" +#include "netlink-internal.h" +#include "netlink-slot.h" +#include "netlink-util.h" +#include "process-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "util.h" + +static int sd_netlink_new(sd_netlink **ret) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + + assert_return(ret, -EINVAL); + + rtnl = new(sd_netlink, 1); + if (!rtnl) + return -ENOMEM; + + *rtnl = (sd_netlink) { + .n_ref = 1, + .fd = -1, + .sockaddr.nl.nl_family = AF_NETLINK, + .original_pid = getpid_cached(), + .protocol = -1, + + /* Change notification responses have sequence 0, so we must + * start our request sequence numbers at 1, or we may confuse our + * responses with notifications from the kernel */ + .serial = 1, + + }; + + /* We guarantee that the read buffer has at least space for + * a message header */ + if (!greedy_realloc((void**)&rtnl->rbuffer, &rtnl->rbuffer_allocated, + sizeof(struct nlmsghdr), sizeof(uint8_t))) + return -ENOMEM; + + *ret = TAKE_PTR(rtnl); + + return 0; +} + +int sd_netlink_new_from_netlink(sd_netlink **ret, int fd) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + socklen_t addrlen; + int r; + + assert_return(ret, -EINVAL); + + r = sd_netlink_new(&rtnl); + if (r < 0) + return r; + + addrlen = sizeof(rtnl->sockaddr); + + r = getsockname(fd, &rtnl->sockaddr.sa, &addrlen); + if (r < 0) + return -errno; + + if (rtnl->sockaddr.nl.nl_family != AF_NETLINK) + return -EINVAL; + + rtnl->fd = fd; + + *ret = TAKE_PTR(rtnl); + + return 0; +} + +static bool rtnl_pid_changed(const sd_netlink *rtnl) { + assert(rtnl); + + /* We don't support people creating an rtnl connection and + * keeping it around over a fork(). Let's complain. */ + + return rtnl->original_pid != getpid_cached(); +} + +int sd_netlink_open_fd(sd_netlink **ret, int fd) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + int r; + int protocol; + socklen_t l; + + assert_return(ret, -EINVAL); + assert_return(fd >= 0, -EBADF); + + r = sd_netlink_new(&rtnl); + if (r < 0) + return r; + + l = sizeof(protocol); + r = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &l); + if (r < 0) + return r; + + rtnl->fd = fd; + rtnl->protocol = protocol; + + r = socket_bind(rtnl); + if (r < 0) { + rtnl->fd = -1; /* on failure, the caller remains owner of the fd, hence don't close it here */ + rtnl->protocol = -1; + return r; + } + + *ret = TAKE_PTR(rtnl); + + return 0; +} + +int netlink_open_family(sd_netlink **ret, int family) { + _cleanup_close_ int fd = -1; + int r; + + fd = socket_open(family); + if (fd < 0) + return fd; + + r = sd_netlink_open_fd(ret, fd); + if (r < 0) + return r; + + fd = -1; + + return 0; +} + +int sd_netlink_open(sd_netlink **ret) { + return netlink_open_family(ret, NETLINK_ROUTE); +} + +int sd_netlink_inc_rcvbuf(sd_netlink *rtnl, size_t size) { + assert_return(rtnl, -EINVAL); + assert_return(!rtnl_pid_changed(rtnl), -ECHILD); + + return fd_inc_rcvbuf(rtnl->fd, size); +} + +static sd_netlink *netlink_free(sd_netlink *rtnl) { + sd_netlink_slot *s; + unsigned i; + + assert(rtnl); + + for (i = 0; i < rtnl->rqueue_size; i++) + sd_netlink_message_unref(rtnl->rqueue[i]); + free(rtnl->rqueue); + + for (i = 0; i < rtnl->rqueue_partial_size; i++) + sd_netlink_message_unref(rtnl->rqueue_partial[i]); + free(rtnl->rqueue_partial); + + free(rtnl->rbuffer); + + while ((s = rtnl->slots)) { + assert(s->floating); + netlink_slot_disconnect(s, true); + } + hashmap_free(rtnl->reply_callbacks); + prioq_free(rtnl->reply_callbacks_prioq); + + sd_event_source_unref(rtnl->io_event_source); + sd_event_source_unref(rtnl->time_event_source); + sd_event_unref(rtnl->event); + + hashmap_free(rtnl->broadcast_group_refs); + + hashmap_free(rtnl->genl_family_to_nlmsg_type); + hashmap_free(rtnl->nlmsg_type_to_genl_family); + + safe_close(rtnl->fd); + return mfree(rtnl); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_netlink, sd_netlink, netlink_free); + +static void rtnl_seal_message(sd_netlink *rtnl, sd_netlink_message *m) { + assert(rtnl); + assert(!rtnl_pid_changed(rtnl)); + assert(m); + assert(m->hdr); + + /* don't use seq == 0, as that is used for broadcasts, so we + would get confused by replies to such messages */ + m->hdr->nlmsg_seq = rtnl->serial++ ? : rtnl->serial++; + + rtnl_message_seal(m); + + return; +} + +int sd_netlink_send(sd_netlink *nl, + sd_netlink_message *message, + uint32_t *serial) { + int r; + + assert_return(nl, -EINVAL); + assert_return(!rtnl_pid_changed(nl), -ECHILD); + assert_return(message, -EINVAL); + assert_return(!message->sealed, -EPERM); + + rtnl_seal_message(nl, message); + + r = socket_write_message(nl, message); + if (r < 0) + return r; + + if (serial) + *serial = rtnl_message_get_serial(message); + + return 1; +} + +int rtnl_rqueue_make_room(sd_netlink *rtnl) { + assert(rtnl); + + if (rtnl->rqueue_size >= RTNL_RQUEUE_MAX) + return log_debug_errno(SYNTHETIC_ERRNO(ENOBUFS), + "rtnl: exhausted the read queue size (%d)", + RTNL_RQUEUE_MAX); + + if (!GREEDY_REALLOC(rtnl->rqueue, rtnl->rqueue_allocated, rtnl->rqueue_size + 1)) + return -ENOMEM; + + return 0; +} + +int rtnl_rqueue_partial_make_room(sd_netlink *rtnl) { + assert(rtnl); + + if (rtnl->rqueue_partial_size >= RTNL_RQUEUE_MAX) + return log_debug_errno(SYNTHETIC_ERRNO(ENOBUFS), + "rtnl: exhausted the partial read queue size (%d)", + RTNL_RQUEUE_MAX); + + if (!GREEDY_REALLOC(rtnl->rqueue_partial, rtnl->rqueue_partial_allocated, + rtnl->rqueue_partial_size + 1)) + return -ENOMEM; + + return 0; +} + +static int dispatch_rqueue(sd_netlink *rtnl, sd_netlink_message **message) { + int r; + + assert(rtnl); + assert(message); + + if (rtnl->rqueue_size <= 0) { + /* Try to read a new message */ + r = socket_read_message(rtnl); + if (r == -ENOBUFS) { /* FIXME: ignore buffer overruns for now */ + log_debug_errno(r, "Got ENOBUFS from netlink socket, ignoring."); + return 1; + } + if (r <= 0) + return r; + } + + /* Dispatch a queued message */ + *message = rtnl->rqueue[0]; + rtnl->rqueue_size--; + memmove(rtnl->rqueue, rtnl->rqueue + 1, sizeof(sd_netlink_message*) * rtnl->rqueue_size); + + return 1; +} + +static int process_timeout(sd_netlink *rtnl) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + struct reply_callback *c; + sd_netlink_slot *slot; + usec_t n; + int r; + + assert(rtnl); + + c = prioq_peek(rtnl->reply_callbacks_prioq); + if (!c) + return 0; + + n = now(CLOCK_MONOTONIC); + if (c->timeout > n) + return 0; + + r = rtnl_message_new_synthetic_error(rtnl, -ETIMEDOUT, c->serial, &m); + if (r < 0) + return r; + + assert_se(prioq_pop(rtnl->reply_callbacks_prioq) == c); + c->timeout = 0; + hashmap_remove(rtnl->reply_callbacks, &c->serial); + + slot = container_of(c, sd_netlink_slot, reply_callback); + + r = c->callback(rtnl, m, slot->userdata); + if (r < 0) + log_debug_errno(r, "sd-netlink: timedout callback %s%s%sfailed: %m", + slot->description ? "'" : "", + strempty(slot->description), + slot->description ? "' " : ""); + + if (slot->floating) + netlink_slot_disconnect(slot, true); + + return 1; +} + +static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) { + struct reply_callback *c; + sd_netlink_slot *slot; + uint64_t serial; + uint16_t type; + int r; + + assert(rtnl); + assert(m); + + serial = rtnl_message_get_serial(m); + c = hashmap_remove(rtnl->reply_callbacks, &serial); + if (!c) + return 0; + + if (c->timeout != 0) { + prioq_remove(rtnl->reply_callbacks_prioq, c, &c->prioq_idx); + c->timeout = 0; + } + + r = sd_netlink_message_get_type(m, &type); + if (r < 0) + return r; + + if (type == NLMSG_DONE) + m = NULL; + + slot = container_of(c, sd_netlink_slot, reply_callback); + + r = c->callback(rtnl, m, slot->userdata); + if (r < 0) + log_debug_errno(r, "sd-netlink: reply callback %s%s%sfailed: %m", + slot->description ? "'" : "", + strempty(slot->description), + slot->description ? "' " : ""); + + if (slot->floating) + netlink_slot_disconnect(slot, true); + + return 1; +} + +static int process_match(sd_netlink *rtnl, sd_netlink_message *m) { + struct match_callback *c; + sd_netlink_slot *slot; + uint16_t type; + int r; + + assert(rtnl); + assert(m); + + r = sd_netlink_message_get_type(m, &type); + if (r < 0) + return r; + + LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) { + if (type == c->type) { + slot = container_of(c, sd_netlink_slot, match_callback); + + r = c->callback(rtnl, m, slot->userdata); + if (r != 0) { + if (r < 0) + log_debug_errno(r, "sd-netlink: match callback %s%s%sfailed: %m", + slot->description ? "'" : "", + strempty(slot->description), + slot->description ? "' " : ""); + + break; + } + } + } + + return 1; +} + +static int process_running(sd_netlink *rtnl, sd_netlink_message **ret) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(rtnl); + + r = process_timeout(rtnl); + if (r != 0) + goto null_message; + + r = dispatch_rqueue(rtnl, &m); + if (r < 0) + return r; + if (!m) + goto null_message; + + if (sd_netlink_message_is_broadcast(m)) { + r = process_match(rtnl, m); + if (r != 0) + goto null_message; + } else { + r = process_reply(rtnl, m); + if (r != 0) + goto null_message; + } + + if (ret) { + *ret = TAKE_PTR(m); + + return 1; + } + + return 1; + +null_message: + if (r >= 0 && ret) + *ret = NULL; + + return r; +} + +int sd_netlink_process(sd_netlink *rtnl, sd_netlink_message **ret) { + NETLINK_DONT_DESTROY(rtnl); + int r; + + assert_return(rtnl, -EINVAL); + assert_return(!rtnl_pid_changed(rtnl), -ECHILD); + assert_return(!rtnl->processing, -EBUSY); + + rtnl->processing = true; + r = process_running(rtnl, ret); + rtnl->processing = false; + + return r; +} + +static usec_t calc_elapse(uint64_t usec) { + if (usec == (uint64_t) -1) + return 0; + + if (usec == 0) + usec = RTNL_DEFAULT_TIMEOUT; + + return now(CLOCK_MONOTONIC) + usec; +} + +static int rtnl_poll(sd_netlink *rtnl, bool need_more, uint64_t timeout_usec) { + struct pollfd p[1] = {}; + struct timespec ts; + usec_t m = USEC_INFINITY; + int r, e; + + assert(rtnl); + + e = sd_netlink_get_events(rtnl); + if (e < 0) + return e; + + if (need_more) + /* Caller wants more data, and doesn't care about + * what's been read or any other timeouts. */ + e |= POLLIN; + else { + usec_t until; + /* Caller wants to process if there is something to + * process, but doesn't care otherwise */ + + r = sd_netlink_get_timeout(rtnl, &until); + if (r < 0) + return r; + if (r > 0) { + usec_t nw; + nw = now(CLOCK_MONOTONIC); + m = until > nw ? until - nw : 0; + } + } + + if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m)) + m = timeout_usec; + + p[0].fd = rtnl->fd; + p[0].events = e; + + r = ppoll(p, 1, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL); + if (r < 0) + return -errno; + + return r > 0 ? 1 : 0; +} + +int sd_netlink_wait(sd_netlink *nl, uint64_t timeout_usec) { + assert_return(nl, -EINVAL); + assert_return(!rtnl_pid_changed(nl), -ECHILD); + + if (nl->rqueue_size > 0) + return 0; + + return rtnl_poll(nl, false, timeout_usec); +} + +static int timeout_compare(const void *a, const void *b) { + const struct reply_callback *x = a, *y = b; + + if (x->timeout != 0 && y->timeout == 0) + return -1; + + if (x->timeout == 0 && y->timeout != 0) + return 1; + + return CMP(x->timeout, y->timeout); +} + +int sd_netlink_call_async( + sd_netlink *nl, + sd_netlink_slot **ret_slot, + sd_netlink_message *m, + sd_netlink_message_handler_t callback, + sd_netlink_destroy_t destroy_callback, + void *userdata, + uint64_t usec, + const char *description) { + _cleanup_free_ sd_netlink_slot *slot = NULL; + uint32_t s; + int r, k; + + assert_return(nl, -EINVAL); + assert_return(m, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(!rtnl_pid_changed(nl), -ECHILD); + + r = hashmap_ensure_allocated(&nl->reply_callbacks, &uint64_hash_ops); + if (r < 0) + return r; + + if (usec != (uint64_t) -1) { + r = prioq_ensure_allocated(&nl->reply_callbacks_prioq, timeout_compare); + if (r < 0) + return r; + } + + r = netlink_slot_allocate(nl, !ret_slot, NETLINK_REPLY_CALLBACK, sizeof(struct reply_callback), userdata, description, &slot); + if (r < 0) + return r; + + slot->reply_callback.callback = callback; + slot->reply_callback.timeout = calc_elapse(usec); + + k = sd_netlink_send(nl, m, &s); + if (k < 0) + return k; + + slot->reply_callback.serial = s; + + r = hashmap_put(nl->reply_callbacks, &slot->reply_callback.serial, &slot->reply_callback); + if (r < 0) + return r; + + if (slot->reply_callback.timeout != 0) { + r = prioq_put(nl->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx); + if (r < 0) { + (void) hashmap_remove(nl->reply_callbacks, &slot->reply_callback.serial); + return r; + } + } + + /* Set this at last. Otherwise, some failures in above call the destroy callback but some do not. */ + slot->destroy_callback = destroy_callback; + + if (ret_slot) + *ret_slot = slot; + + TAKE_PTR(slot); + + return k; +} + +int sd_netlink_call(sd_netlink *rtnl, + sd_netlink_message *message, + uint64_t usec, + sd_netlink_message **ret) { + usec_t timeout; + uint32_t serial; + int r; + + assert_return(rtnl, -EINVAL); + assert_return(!rtnl_pid_changed(rtnl), -ECHILD); + assert_return(message, -EINVAL); + + r = sd_netlink_send(rtnl, message, &serial); + if (r < 0) + return r; + + timeout = calc_elapse(usec); + + for (;;) { + usec_t left; + unsigned i; + + for (i = 0; i < rtnl->rqueue_size; i++) { + uint32_t received_serial; + + received_serial = rtnl_message_get_serial(rtnl->rqueue[i]); + + if (received_serial == serial) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *incoming = NULL; + uint16_t type; + + incoming = rtnl->rqueue[i]; + + /* found a match, remove from rqueue and return it */ + memmove(rtnl->rqueue + i,rtnl->rqueue + i + 1, + sizeof(sd_netlink_message*) * (rtnl->rqueue_size - i - 1)); + rtnl->rqueue_size--; + + r = sd_netlink_message_get_errno(incoming); + if (r < 0) + return r; + + r = sd_netlink_message_get_type(incoming, &type); + if (r < 0) + return r; + + if (type == NLMSG_DONE) { + *ret = NULL; + return 0; + } + + if (ret) + *ret = TAKE_PTR(incoming); + + return 1; + } + } + + r = socket_read_message(rtnl); + if (r < 0) + return r; + if (r > 0) + /* received message, so try to process straight away */ + continue; + + if (timeout > 0) { + usec_t n; + + n = now(CLOCK_MONOTONIC); + if (n >= timeout) + return -ETIMEDOUT; + + left = timeout - n; + } else + left = (uint64_t) -1; + + r = rtnl_poll(rtnl, true, left); + if (r < 0) + return r; + else if (r == 0) + return -ETIMEDOUT; + } +} + +int sd_netlink_get_events(const sd_netlink *rtnl) { + assert_return(rtnl, -EINVAL); + assert_return(!rtnl_pid_changed(rtnl), -ECHILD); + + if (rtnl->rqueue_size == 0) + return POLLIN; + else + return 0; +} + +int sd_netlink_get_timeout(const sd_netlink *rtnl, uint64_t *timeout_usec) { + struct reply_callback *c; + + assert_return(rtnl, -EINVAL); + assert_return(timeout_usec, -EINVAL); + assert_return(!rtnl_pid_changed(rtnl), -ECHILD); + + if (rtnl->rqueue_size > 0) { + *timeout_usec = 0; + return 1; + } + + c = prioq_peek(rtnl->reply_callbacks_prioq); + if (!c) { + *timeout_usec = (uint64_t) -1; + return 0; + } + + *timeout_usec = c->timeout; + + return 1; +} + +static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + sd_netlink *rtnl = userdata; + int r; + + assert(rtnl); + + r = sd_netlink_process(rtnl, NULL); + if (r < 0) + return r; + + return 1; +} + +static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) { + sd_netlink *rtnl = userdata; + int r; + + assert(rtnl); + + r = sd_netlink_process(rtnl, NULL); + if (r < 0) + return r; + + return 1; +} + +static int prepare_callback(sd_event_source *s, void *userdata) { + sd_netlink *rtnl = userdata; + int r, e; + usec_t until; + + assert(s); + assert(rtnl); + + e = sd_netlink_get_events(rtnl); + if (e < 0) + return e; + + r = sd_event_source_set_io_events(rtnl->io_event_source, e); + if (r < 0) + return r; + + r = sd_netlink_get_timeout(rtnl, &until); + if (r < 0) + return r; + if (r > 0) { + int j; + + j = sd_event_source_set_time(rtnl->time_event_source, until); + if (j < 0) + return j; + } + + r = sd_event_source_set_enabled(rtnl->time_event_source, r > 0); + if (r < 0) + return r; + + return 1; +} + +int sd_netlink_attach_event(sd_netlink *rtnl, sd_event *event, int64_t priority) { + int r; + + assert_return(rtnl, -EINVAL); + assert_return(!rtnl->event, -EBUSY); + + assert(!rtnl->io_event_source); + assert(!rtnl->time_event_source); + + if (event) + rtnl->event = sd_event_ref(event); + else { + r = sd_event_default(&rtnl->event); + if (r < 0) + return r; + } + + r = sd_event_add_io(rtnl->event, &rtnl->io_event_source, rtnl->fd, 0, io_callback, rtnl); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(rtnl->io_event_source, priority); + if (r < 0) + goto fail; + + r = sd_event_source_set_description(rtnl->io_event_source, "rtnl-receive-message"); + if (r < 0) + goto fail; + + r = sd_event_source_set_prepare(rtnl->io_event_source, prepare_callback); + if (r < 0) + goto fail; + + r = sd_event_add_time(rtnl->event, &rtnl->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, rtnl); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(rtnl->time_event_source, priority); + if (r < 0) + goto fail; + + r = sd_event_source_set_description(rtnl->time_event_source, "rtnl-timer"); + if (r < 0) + goto fail; + + return 0; + +fail: + sd_netlink_detach_event(rtnl); + return r; +} + +int sd_netlink_detach_event(sd_netlink *rtnl) { + assert_return(rtnl, -EINVAL); + assert_return(rtnl->event, -ENXIO); + + rtnl->io_event_source = sd_event_source_unref(rtnl->io_event_source); + + rtnl->time_event_source = sd_event_source_unref(rtnl->time_event_source); + + rtnl->event = sd_event_unref(rtnl->event); + + return 0; +} + +int sd_netlink_add_match( + sd_netlink *rtnl, + sd_netlink_slot **ret_slot, + uint16_t type, + sd_netlink_message_handler_t callback, + sd_netlink_destroy_t destroy_callback, + void *userdata, + const char *description) { + _cleanup_free_ sd_netlink_slot *slot = NULL; + int r; + + assert_return(rtnl, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(!rtnl_pid_changed(rtnl), -ECHILD); + + r = netlink_slot_allocate(rtnl, !ret_slot, NETLINK_MATCH_CALLBACK, sizeof(struct match_callback), userdata, description, &slot); + if (r < 0) + return r; + + slot->match_callback.callback = callback; + slot->match_callback.type = type; + + switch (type) { + case RTM_NEWLINK: + case RTM_DELLINK: + r = socket_broadcast_group_ref(rtnl, RTNLGRP_LINK); + if (r < 0) + return r; + + break; + case RTM_NEWADDR: + case RTM_DELADDR: + r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_IFADDR); + if (r < 0) + return r; + + r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_IFADDR); + if (r < 0) + return r; + + break; + case RTM_NEWNEIGH: + case RTM_DELNEIGH: + r = socket_broadcast_group_ref(rtnl, RTNLGRP_NEIGH); + if (r < 0) + return r; + + break; + case RTM_NEWROUTE: + case RTM_DELROUTE: + r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_ROUTE); + if (r < 0) + return r; + + r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_ROUTE); + if (r < 0) + return r; + break; + case RTM_NEWRULE: + case RTM_DELRULE: + r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_RULE); + if (r < 0) + return r; + + r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_RULE); + if (r < 0) + return r; + break; + case RTM_NEWNEXTHOP: + case RTM_DELNEXTHOP: + r = socket_broadcast_group_ref(rtnl, RTNLGRP_NEXTHOP); + if (r < 0) + return r; + break; + + default: + return -EOPNOTSUPP; + } + + LIST_PREPEND(match_callbacks, rtnl->match_callbacks, &slot->match_callback); + + /* Set this at last. Otherwise, some failures in above call the destroy callback but some do not. */ + slot->destroy_callback = destroy_callback; + + if (ret_slot) + *ret_slot = slot; + + TAKE_PTR(slot); + + return 0; +} diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c new file mode 100644 index 00000000..d6165703 --- /dev/null +++ b/src/libsystemd/sd-netlink/test-netlink.c @@ -0,0 +1,611 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "ether-addr-util.h" +#include "macro.h" +#include "netlink-util.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "util.h" + +static void test_message_link_bridge(sd_netlink *rtnl) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; + uint32_t cost; + + assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0); + assert_se(sd_rtnl_message_link_set_family(message, PF_BRIDGE) >= 0); + assert_se(sd_netlink_message_open_container(message, IFLA_PROTINFO) >= 0); + assert_se(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0); + assert_se(sd_netlink_message_close_container(message) >= 0); + + assert_se(sd_netlink_message_rewind(message, NULL) >= 0); + + assert_se(sd_netlink_message_enter_container(message, IFLA_PROTINFO) >= 0); + assert_se(sd_netlink_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0); + assert_se(cost == 10); + assert_se(sd_netlink_message_exit_container(message) >= 0); +} + +static void test_link_configure(sd_netlink *rtnl, int ifindex) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; + const char *mac = "98:fe:94:3f:c6:18", *name = "test"; + char buffer[ETHER_ADDR_TO_STRING_MAX]; + uint32_t mtu = 1450, mtu_out; + const char *name_out; + struct ether_addr mac_out; + + /* we'd really like to test NEWLINK, but let's not mess with the running kernel */ + assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0); + assert_se(sd_netlink_message_append_string(message, IFLA_IFNAME, name) >= 0); + assert_se(sd_netlink_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0); + assert_se(sd_netlink_message_append_u32(message, IFLA_MTU, mtu) >= 0); + + assert_se(sd_netlink_call(rtnl, message, 0, NULL) == 1); + assert_se(sd_netlink_message_rewind(message, NULL) >= 0); + + assert_se(sd_netlink_message_read_string(message, IFLA_IFNAME, &name_out) >= 0); + assert_se(streq(name, name_out)); + + assert_se(sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0); + assert_se(streq(mac, ether_addr_to_string(&mac_out, buffer))); + + assert_se(sd_netlink_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0); + assert_se(mtu == mtu_out); +} + +static void test_link_get(sd_netlink *rtnl, int ifindex) { + sd_netlink_message *m; + sd_netlink_message *r; + uint32_t mtu = 1500; + const char *str_data; + uint8_t u8_data; + uint32_t u32_data; + struct ether_addr eth_data; + + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); + assert_se(m); + + /* u8 test cases */ + assert_se(sd_netlink_message_append_u8(m, IFLA_CARRIER, 0) >= 0); + assert_se(sd_netlink_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0); + assert_se(sd_netlink_message_append_u8(m, IFLA_LINKMODE, 0) >= 0); + + /* u32 test cases */ + assert_se(sd_netlink_message_append_u32(m, IFLA_MTU, mtu) >= 0); + assert_se(sd_netlink_message_append_u32(m, IFLA_GROUP, 0) >= 0); + assert_se(sd_netlink_message_append_u32(m, IFLA_TXQLEN, 0) >= 0); + assert_se(sd_netlink_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0); + assert_se(sd_netlink_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0); + + assert_se(sd_netlink_call(rtnl, m, -1, &r) == 1); + + assert_se(sd_netlink_message_read_string(r, IFLA_IFNAME, &str_data) == 0); + + assert_se(sd_netlink_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0); + assert_se(sd_netlink_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0); + assert_se(sd_netlink_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0); + + assert_se(sd_netlink_message_read_u32(r, IFLA_MTU, &u32_data) == 0); + assert_se(sd_netlink_message_read_u32(r, IFLA_GROUP, &u32_data) == 0); + assert_se(sd_netlink_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0); + assert_se(sd_netlink_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0); + assert_se(sd_netlink_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0); + + assert_se(sd_netlink_message_read_ether_addr(r, IFLA_ADDRESS, ð_data) == 0); + + assert_se((m = sd_netlink_message_unref(m)) == NULL); + assert_se((r = sd_netlink_message_unref(r)) == NULL); +} + +static void test_address_get(sd_netlink *rtnl, int ifindex) { + sd_netlink_message *m; + sd_netlink_message *r; + struct in_addr in_data; + struct ifa_cacheinfo cache; + const char *label; + + assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0); + assert_se(m); + + assert_se(sd_netlink_call(rtnl, m, -1, &r) == 1); + + assert_se(sd_netlink_message_read_in_addr(r, IFA_LOCAL, &in_data) == 0); + assert_se(sd_netlink_message_read_in_addr(r, IFA_ADDRESS, &in_data) == 0); + assert_se(sd_netlink_message_read_string(r, IFA_LABEL, &label) == 0); + assert_se(sd_netlink_message_read_cache_info(r, IFA_CACHEINFO, &cache) == 0); + + assert_se((m = sd_netlink_message_unref(m)) == NULL); + assert_se((r = sd_netlink_message_unref(r)) == NULL); + +} + +static void test_route(sd_netlink *rtnl) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req; + struct in_addr addr, addr_data; + uint32_t index = 2, u32_data; + int r; + + r = sd_rtnl_message_new_route(rtnl, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC); + if (r < 0) { + log_error_errno(r, "Could not create RTM_NEWROUTE message: %m"); + return; + } + + addr.s_addr = htonl(INADDR_LOOPBACK); + + r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &addr); + if (r < 0) { + log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m"); + return; + } + + r = sd_netlink_message_append_u32(req, RTA_OIF, index); + if (r < 0) { + log_error_errno(r, "Could not append RTA_OIF attribute: %m"); + return; + } + + assert_se(sd_netlink_message_rewind(req, NULL) >= 0); + + assert_se(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0); + assert_se(addr_data.s_addr == addr.s_addr); + + assert_se(sd_netlink_message_read_u32(req, RTA_OIF, &u32_data) >= 0); + assert_se(u32_data == index); + + assert_se((req = sd_netlink_message_unref(req)) == NULL); +} + +static void test_multiple(void) { + sd_netlink *rtnl1, *rtnl2; + + assert_se(sd_netlink_open(&rtnl1) >= 0); + assert_se(sd_netlink_open(&rtnl2) >= 0); + + rtnl1 = sd_netlink_unref(rtnl1); + rtnl2 = sd_netlink_unref(rtnl2); +} + +static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { + char *ifname = userdata; + const char *data; + + assert_se(rtnl); + assert_se(m); + assert_se(userdata); + + log_info("%s: got link info about %s", __func__, ifname); + free(ifname); + + assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0); + assert_se(streq(data, "lo")); + + return 1; +} + +static void test_event_loop(int ifindex) { + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + char *ifname; + + ifname = strdup("lo2"); + assert_se(ifname); + + assert_se(sd_netlink_open(&rtnl) >= 0); + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); + + assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler, NULL, ifname, 0, NULL) >= 0); + + assert_se(sd_event_default(&event) >= 0); + + assert_se(sd_netlink_attach_event(rtnl, event, 0) >= 0); + + assert_se(sd_event_run(event, 0) >= 0); + + assert_se(sd_netlink_detach_event(rtnl) >= 0); + + assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); +} + +static void test_async_destroy(void *userdata) { +} + +static void test_async(int ifindex) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL; + _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL; + sd_netlink_destroy_t destroy_callback; + const char *description; + char *ifname; + + ifname = strdup("lo"); + assert_se(ifname); + + assert_se(sd_netlink_open(&rtnl) >= 0); + + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); + + assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler, test_async_destroy, ifname, 0, "hogehoge") >= 0); + + assert_se(sd_netlink_slot_get_netlink(slot) == rtnl); + assert_se(sd_netlink_slot_get_userdata(slot) == ifname); + assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 1); + assert_se(destroy_callback == test_async_destroy); + assert_se(sd_netlink_slot_get_floating(slot) == 0); + assert_se(sd_netlink_slot_get_description(slot, &description) == 1); + assert_se(streq(description, "hogehoge")); + + assert_se(sd_netlink_wait(rtnl, 0) >= 0); + assert_se(sd_netlink_process(rtnl, &r) >= 0); + + assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); +} + +static void test_slot_set(int ifindex) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL; + _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL; + sd_netlink_destroy_t destroy_callback; + const char *description; + char *ifname; + + ifname = strdup("lo"); + assert_se(ifname); + + assert_se(sd_netlink_open(&rtnl) >= 0); + + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); + + assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler, NULL, NULL, 0, NULL) >= 0); + + assert_se(sd_netlink_slot_get_netlink(slot) == rtnl); + assert_se(!sd_netlink_slot_get_userdata(slot)); + assert_se(!sd_netlink_slot_set_userdata(slot, ifname)); + assert_se(sd_netlink_slot_get_userdata(slot) == ifname); + assert_se(sd_netlink_slot_get_destroy_callback(slot, NULL) == 0); + assert_se(sd_netlink_slot_set_destroy_callback(slot, test_async_destroy) >= 0); + assert_se(sd_netlink_slot_get_destroy_callback(slot, &destroy_callback) == 1); + assert_se(destroy_callback == test_async_destroy); + assert_se(sd_netlink_slot_get_floating(slot) == 0); + assert_se(sd_netlink_slot_set_floating(slot, 1) == 1); + assert_se(sd_netlink_slot_get_floating(slot) == 1); + assert_se(sd_netlink_slot_get_description(slot, NULL) == 0); + assert_se(sd_netlink_slot_set_description(slot, "hogehoge") >= 0); + assert_se(sd_netlink_slot_get_description(slot, &description) == 1); + assert_se(streq(description, "hogehoge")); + + assert_se(sd_netlink_wait(rtnl, 0) >= 0); + assert_se(sd_netlink_process(rtnl, &r) >= 0); + + assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); +} + +struct test_async_object { + unsigned n_ref; + char *ifname; +}; + +static struct test_async_object *test_async_object_free(struct test_async_object *t) { + assert(t); + + free(t->ifname); + return mfree(t); +} + +DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(struct test_async_object, test_async_object, test_async_object_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct test_async_object *, test_async_object_unref); + +static int link_handler2(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { + struct test_async_object *t = userdata; + const char *data; + + assert_se(rtnl); + assert_se(m); + assert_se(userdata); + + log_info("%s: got link info about %s", __func__, t->ifname); + + assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0); + assert_se(streq(data, "lo")); + + return 1; +} + +static void test_async_object_destroy(void *userdata) { + struct test_async_object *t = userdata; + + assert(userdata); + + log_info("%s: n_ref=%u", __func__, t->n_ref); + test_async_object_unref(t); +} + +static void test_async_destroy_callback(int ifindex) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL; + _cleanup_(test_async_object_unrefp) struct test_async_object *t = NULL; + _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL; + char *ifname; + + assert_se(t = new(struct test_async_object, 1)); + assert_se(ifname = strdup("lo")); + *t = (struct test_async_object) { + .n_ref = 1, + .ifname = ifname, + }; + + assert_se(sd_netlink_open(&rtnl) >= 0); + + /* destroy callback is called after processing message */ + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); + assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0, NULL) >= 0); + + assert_se(t->n_ref == 1); + assert_se(test_async_object_ref(t)); + assert_se(t->n_ref == 2); + + assert_se(sd_netlink_wait(rtnl, 0) >= 0); + assert_se(sd_netlink_process(rtnl, &r) == 1); + assert_se(t->n_ref == 1); + + assert_se(!sd_netlink_message_unref(m)); + + /* destroy callback is called when asynchronous call is cancelled, that is, slot is freed. */ + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); + assert_se(sd_netlink_call_async(rtnl, &slot, m, link_handler2, test_async_object_destroy, t, 0, NULL) >= 0); + + assert_se(t->n_ref == 1); + assert_se(test_async_object_ref(t)); + assert_se(t->n_ref == 2); + + assert_se(!(slot = sd_netlink_slot_unref(slot))); + assert_se(t->n_ref == 1); + + assert_se(!sd_netlink_message_unref(m)); + + /* destroy callback is also called by sd_netlink_unref() */ + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); + assert_se(sd_netlink_call_async(rtnl, NULL, m, link_handler2, test_async_object_destroy, t, 0, NULL) >= 0); + + assert_se(t->n_ref == 1); + assert_se(test_async_object_ref(t)); + assert_se(t->n_ref == 2); + + assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); + assert_se(t->n_ref == 1); +} + +static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { + int *counter = userdata; + int r; + + (*counter)--; + + r = sd_netlink_message_get_errno(m); + + log_info_errno(r, "%d left in pipe. got reply: %m", *counter); + + assert_se(r >= 0); + + return 1; +} + +static void test_pipe(int ifindex) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL; + int counter = 0; + + assert_se(sd_netlink_open(&rtnl) >= 0); + + assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0); + assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0); + + counter++; + assert_se(sd_netlink_call_async(rtnl, NULL, m1, pipe_handler, NULL, &counter, 0, NULL) >= 0); + + counter++; + assert_se(sd_netlink_call_async(rtnl, NULL, m2, pipe_handler, NULL, &counter, 0, NULL) >= 0); + + while (counter > 0) { + assert_se(sd_netlink_wait(rtnl, 0) >= 0); + assert_se(sd_netlink_process(rtnl, NULL) >= 0); + } + + assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); +} + +static void test_container(sd_netlink *rtnl) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + uint16_t u16_data; + uint32_t u32_data; + const char *string_data; + + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0); + + assert_se(sd_netlink_message_open_container(m, IFLA_LINKINFO) >= 0); + assert_se(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "vlan") >= 0); + assert_se(sd_netlink_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0); + assert_se(sd_netlink_message_close_container(m) >= 0); + assert_se(sd_netlink_message_append_string(m, IFLA_INFO_KIND, "vlan") >= 0); + assert_se(sd_netlink_message_close_container(m) >= 0); + assert_se(sd_netlink_message_close_container(m) == -EINVAL); + + assert_se(sd_netlink_message_rewind(m, NULL) >= 0); + + assert_se(sd_netlink_message_enter_container(m, IFLA_LINKINFO) >= 0); + assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0); + assert_se(streq("vlan", string_data)); + + assert_se(sd_netlink_message_enter_container(m, IFLA_INFO_DATA) >= 0); + assert_se(sd_netlink_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0); + assert_se(sd_netlink_message_exit_container(m) >= 0); + + assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0); + assert_se(streq("vlan", string_data)); + assert_se(sd_netlink_message_exit_container(m) >= 0); + + assert_se(sd_netlink_message_read_u32(m, IFLA_LINKINFO, &u32_data) < 0); + + assert_se(sd_netlink_message_exit_container(m) == -EINVAL); +} + +static void test_match(void) { + _cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *s1 = NULL, *s2 = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + + assert_se(sd_netlink_open(&rtnl) >= 0); + + assert_se(sd_netlink_add_match(rtnl, &s1, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0); + assert_se(sd_netlink_add_match(rtnl, &s2, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0); + assert_se(sd_netlink_add_match(rtnl, NULL, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0); + + assert_se(!(s1 = sd_netlink_slot_unref(s1))); + assert_se(!(s2 = sd_netlink_slot_unref(s2))); + + assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); +} + +static void test_get_addresses(sd_netlink *rtnl) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *m; + + assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0); + + assert_se(sd_netlink_call(rtnl, req, 0, &reply) >= 0); + + for (m = reply; m; m = sd_netlink_message_next(m)) { + uint16_t type; + unsigned char scope, flags; + int family, ifindex; + + assert_se(sd_netlink_message_get_type(m, &type) >= 0); + assert_se(type == RTM_NEWADDR); + + assert_se(sd_rtnl_message_addr_get_ifindex(m, &ifindex) >= 0); + assert_se(sd_rtnl_message_addr_get_family(m, &family) >= 0); + assert_se(sd_rtnl_message_addr_get_scope(m, &scope) >= 0); + assert_se(sd_rtnl_message_addr_get_flags(m, &flags) >= 0); + + assert_se(ifindex > 0); + assert_se(IN_SET(family, AF_INET, AF_INET6)); + + log_info("got IPv%u address on ifindex %i", family == AF_INET ? 4: 6, ifindex); + } +} + +static void test_message(sd_netlink *rtnl) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + + assert_se(rtnl_message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m) >= 0); + assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT); +} + +static void test_array(void) { + _cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL; + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + + assert_se(sd_genl_socket_open(&genl) >= 0); + assert_se(sd_genl_message_new(genl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &m) >= 0); + + assert_se(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0); + for (unsigned i = 0; i < 10; i++) { + char name[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)]; + uint32_t id = i + 1000; + + xsprintf(name, "hoge%" PRIu32, id); + assert_se(sd_netlink_message_open_array(m, i + 1) >= 0); + assert_se(sd_netlink_message_append_u32(m, CTRL_ATTR_MCAST_GRP_ID, id) >= 0); + assert_se(sd_netlink_message_append_string(m, CTRL_ATTR_MCAST_GRP_NAME, name) >= 0); + assert_se(sd_netlink_message_close_container(m) >= 0); + } + assert_se(sd_netlink_message_close_container(m) >= 0); + + rtnl_message_seal(m); + assert_se(sd_netlink_message_rewind(m, genl) >= 0); + + assert_se(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0); + for (unsigned i = 0; i < 10; i++) { + char expected[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)]; + const char *name; + uint32_t id; + + assert_se(sd_netlink_message_enter_array(m, i + 1) >= 0); + assert_se(sd_netlink_message_read_u32(m, CTRL_ATTR_MCAST_GRP_ID, &id) >= 0); + assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_MCAST_GRP_NAME, &name) >= 0); + assert_se(sd_netlink_message_exit_container(m) >= 0); + + assert_se(id == i + 1000); + xsprintf(expected, "hoge%" PRIu32, id); + assert_se(streq(name, expected)); + } + assert_se(sd_netlink_message_exit_container(m) >= 0); + +} + +int main(void) { + sd_netlink *rtnl; + sd_netlink_message *m; + sd_netlink_message *r; + const char *string_data; + int if_loopback; + uint16_t type; + + test_match(); + test_multiple(); + + assert_se(sd_netlink_open(&rtnl) >= 0); + assert_se(rtnl); + + test_route(rtnl); + test_message(rtnl); + test_container(rtnl); + test_array(); + + if_loopback = (int) if_nametoindex("lo"); + assert_se(if_loopback > 0); + + test_async(if_loopback); + test_slot_set(if_loopback); + test_async_destroy_callback(if_loopback); + test_pipe(if_loopback); + test_event_loop(if_loopback); + test_link_configure(rtnl, if_loopback); + + test_get_addresses(rtnl); + test_message_link_bridge(rtnl); + + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0); + assert_se(m); + + assert_se(sd_netlink_message_get_type(m, &type) >= 0); + assert_se(type == RTM_GETLINK); + + assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM); + + assert_se(sd_netlink_call(rtnl, m, 0, &r) == 1); + assert_se(sd_netlink_message_get_type(r, &type) >= 0); + assert_se(type == RTM_NEWLINK); + + assert_se((r = sd_netlink_message_unref(r)) == NULL); + + assert_se(sd_netlink_call(rtnl, m, -1, &r) == -EPERM); + assert_se((m = sd_netlink_message_unref(m)) == NULL); + assert_se((r = sd_netlink_message_unref(r)) == NULL); + + test_link_get(rtnl, if_loopback); + test_address_get(rtnl, if_loopback); + + assert_se((m = sd_netlink_message_unref(m)) == NULL); + assert_se((r = sd_netlink_message_unref(r)) == NULL); + assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); + + return EXIT_SUCCESS; +} diff --git a/src/libsystemd/sd-network/network-util.c b/src/libsystemd/sd-network/network-util.c new file mode 100644 index 00000000..08ed9426 --- /dev/null +++ b/src/libsystemd/sd-network/network-util.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "fd-util.h" +#include "network-util.h" +#include "string-table.h" +#include "strv.h" + +bool network_is_online(void) { + _cleanup_free_ char *carrier_state = NULL, *addr_state = NULL; + int r; + + r = sd_network_get_carrier_state(&carrier_state); + if (r < 0) /* if we don't know anything, we consider the system online */ + return true; + + r = sd_network_get_address_state(&addr_state); + if (r < 0) /* if we don't know anything, we consider the system online */ + return true; + + if (STR_IN_SET(carrier_state, "degraded-carrier", "carrier") && + STR_IN_SET(addr_state, "routable", "degraded")) + return true; + + return false; +} + +static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = { + [LINK_OPERSTATE_OFF] = "off", + [LINK_OPERSTATE_NO_CARRIER] = "no-carrier", + [LINK_OPERSTATE_DORMANT] = "dormant", + [LINK_OPERSTATE_DEGRADED_CARRIER] = "degraded-carrier", + [LINK_OPERSTATE_CARRIER] = "carrier", + [LINK_OPERSTATE_DEGRADED] = "degraded", + [LINK_OPERSTATE_ENSLAVED] = "enslaved", + [LINK_OPERSTATE_ROUTABLE] = "routable", +}; + +DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState); + +static const char* const link_carrier_state_table[_LINK_CARRIER_STATE_MAX] = { + [LINK_CARRIER_STATE_OFF] = "off", + [LINK_CARRIER_STATE_NO_CARRIER] = "no-carrier", + [LINK_CARRIER_STATE_DORMANT] = "dormant", + [LINK_CARRIER_STATE_DEGRADED_CARRIER] = "degraded-carrier", + [LINK_CARRIER_STATE_CARRIER] = "carrier", + [LINK_CARRIER_STATE_ENSLAVED] = "enslaved", +}; + +DEFINE_STRING_TABLE_LOOKUP(link_carrier_state, LinkCarrierState); + +static const char* const link_address_state_table[_LINK_ADDRESS_STATE_MAX] = { + [LINK_ADDRESS_STATE_OFF] = "off", + [LINK_ADDRESS_STATE_DEGRADED] = "degraded", + [LINK_ADDRESS_STATE_ROUTABLE] = "routable", +}; + +DEFINE_STRING_TABLE_LOOKUP(link_address_state, LinkAddressState); diff --git a/src/libsystemd/sd-network/network-util.h b/src/libsystemd/sd-network/network-util.h new file mode 100644 index 00000000..a1943539 --- /dev/null +++ b/src/libsystemd/sd-network/network-util.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-network.h" + +#include "macro.h" + +bool network_is_online(void); + +typedef enum LinkOperationalState { + LINK_OPERSTATE_OFF, + LINK_OPERSTATE_NO_CARRIER, + LINK_OPERSTATE_DORMANT, + LINK_OPERSTATE_DEGRADED_CARRIER, + LINK_OPERSTATE_CARRIER, + LINK_OPERSTATE_DEGRADED, + LINK_OPERSTATE_ENSLAVED, + LINK_OPERSTATE_ROUTABLE, + _LINK_OPERSTATE_MAX, + _LINK_OPERSTATE_INVALID = -1 +} LinkOperationalState; + +typedef enum LinkCarrierState { + LINK_CARRIER_STATE_OFF = LINK_OPERSTATE_OFF, + LINK_CARRIER_STATE_NO_CARRIER = LINK_OPERSTATE_NO_CARRIER, + LINK_CARRIER_STATE_DORMANT = LINK_OPERSTATE_DORMANT, + LINK_CARRIER_STATE_DEGRADED_CARRIER = LINK_OPERSTATE_DEGRADED_CARRIER, + LINK_CARRIER_STATE_CARRIER = LINK_OPERSTATE_CARRIER, + LINK_CARRIER_STATE_ENSLAVED = LINK_OPERSTATE_ENSLAVED, + _LINK_CARRIER_STATE_MAX, + _LINK_CARRIER_STATE_INVALID = -1 +} LinkCarrierState; + +typedef enum LinkAddressState { + LINK_ADDRESS_STATE_OFF, + LINK_ADDRESS_STATE_DEGRADED, + LINK_ADDRESS_STATE_ROUTABLE, + _LINK_ADDRESS_STATE_MAX, + _LINK_ADDRESS_STATE_INVALID = -1 +} LinkAddressState; + +const char* link_operstate_to_string(LinkOperationalState s) _const_; +LinkOperationalState link_operstate_from_string(const char *s) _pure_; + +const char* link_carrier_state_to_string(LinkCarrierState s) _const_; +LinkCarrierState link_carrier_state_from_string(const char *s) _pure_; + +const char* link_address_state_to_string(LinkAddressState s) _const_; +LinkAddressState link_address_state_from_string(const char *s) _pure_; diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c new file mode 100644 index 00000000..dc5ccb79 --- /dev/null +++ b/src/libsystemd/sd-network/sd-network.c @@ -0,0 +1,457 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-network.h" + +#include "alloc-util.h" +#include "env-file.h" +#include "fd-util.h" +#include "fs-util.h" +#include "macro.h" +#include "parse-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "util.h" + +static int network_get_string(const char *field, char **ret) { + _cleanup_free_ char *s = NULL; + int r; + + assert_return(ret, -EINVAL); + + r = parse_env_file(NULL, "/run/systemd/netif/state", field, &s); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (isempty(s)) + return -ENODATA; + + *ret = TAKE_PTR(s); + + return 0; +} + +_public_ int sd_network_get_operational_state(char **state) { + return network_get_string("OPER_STATE", state); +} + +_public_ int sd_network_get_carrier_state(char **state) { + return network_get_string("CARRIER_STATE", state); +} + +_public_ int sd_network_get_address_state(char **state) { + return network_get_string("ADDRESS_STATE", state); +} + +static int network_get_strv(const char *key, char ***ret) { + _cleanup_strv_free_ char **a = NULL; + _cleanup_free_ char *s = NULL; + int r; + + assert_return(ret, -EINVAL); + + r = parse_env_file(NULL, "/run/systemd/netif/state", key, &s); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (isempty(s)) { + *ret = NULL; + return 0; + } + + a = strv_split(s, " "); + if (!a) + return -ENOMEM; + + strv_uniq(a); + r = (int) strv_length(a); + + *ret = TAKE_PTR(a); + + return r; +} + +_public_ int sd_network_get_dns(char ***ret) { + return network_get_strv("DNS", ret); +} + +_public_ int sd_network_get_ntp(char ***ret) { + return network_get_strv("NTP", ret); +} + +_public_ int sd_network_get_search_domains(char ***ret) { + return network_get_strv("DOMAINS", ret); +} + +_public_ int sd_network_get_route_domains(char ***ret) { + return network_get_strv("ROUTE_DOMAINS", ret); +} + +static int network_link_get_string(int ifindex, const char *field, char **ret) { + char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; + _cleanup_free_ char *s = NULL; + int r; + + assert_return(ifindex > 0, -EINVAL); + assert_return(ret, -EINVAL); + + xsprintf(path, "/run/systemd/netif/links/%i", ifindex); + + r = parse_env_file(NULL, path, field, &s); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (isempty(s)) + return -ENODATA; + + *ret = TAKE_PTR(s); + + return 0; +} + +static int network_link_get_strv(int ifindex, const char *key, char ***ret) { + char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; + _cleanup_strv_free_ char **a = NULL; + _cleanup_free_ char *s = NULL; + int r; + + assert_return(ifindex > 0, -EINVAL); + assert_return(ret, -EINVAL); + + xsprintf(path, "/run/systemd/netif/links/%i", ifindex); + r = parse_env_file(NULL, path, key, &s); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (isempty(s)) { + *ret = NULL; + return 0; + } + + a = strv_split(s, " "); + if (!a) + return -ENOMEM; + + strv_uniq(a); + r = (int) strv_length(a); + + *ret = TAKE_PTR(a); + + return r; +} + +_public_ int sd_network_link_get_setup_state(int ifindex, char **state) { + return network_link_get_string(ifindex, "ADMIN_STATE", state); +} + +_public_ int sd_network_link_get_network_file(int ifindex, char **filename) { + return network_link_get_string(ifindex, "NETWORK_FILE", filename); +} + +_public_ int sd_network_link_get_operational_state(int ifindex, char **state) { + return network_link_get_string(ifindex, "OPER_STATE", state); +} + +_public_ int sd_network_link_get_carrier_state(int ifindex, char **state) { + return network_link_get_string(ifindex, "CARRIER_STATE", state); +} + +_public_ int sd_network_link_get_address_state(int ifindex, char **state) { + return network_link_get_string(ifindex, "ADDRESS_STATE", state); +} + +_public_ int sd_network_link_get_required_for_online(int ifindex) { + _cleanup_free_ char *s = NULL; + int r; + + r = network_link_get_string(ifindex, "REQUIRED_FOR_ONLINE", &s); + if (r < 0) { + /* Handle -ENODATA as RequiredForOnline=yes, for compatibility */ + if (r == -ENODATA) + return true; + return r; + } + + return parse_boolean(s); +} + +_public_ int sd_network_link_get_required_operstate_for_online(int ifindex, char **state) { + _cleanup_free_ char *s = NULL; + int r; + + assert_return(state, -EINVAL); + + r = network_link_get_string(ifindex, "REQUIRED_OPER_STATE_FOR_ONLINE", &s); + if (r < 0) { + if (r != -ENODATA) + return r; + + /* For compatibility, assuming degraded. */ + s = strdup("degraded"); + if (!s) + return -ENOMEM; + } + + *state = TAKE_PTR(s); + return 0; +} + +_public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) { + return network_link_get_string(ifindex, "LLMNR", llmnr); +} + +_public_ int sd_network_link_get_mdns(int ifindex, char **mdns) { + return network_link_get_string(ifindex, "MDNS", mdns); +} + +_public_ int sd_network_link_get_dns_over_tls(int ifindex, char **dns_over_tls) { + return network_link_get_string(ifindex, "DNS_OVER_TLS", dns_over_tls); +} + +_public_ int sd_network_link_get_dnssec(int ifindex, char **dnssec) { + return network_link_get_string(ifindex, "DNSSEC", dnssec); +} + +_public_ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta) { + return network_link_get_strv(ifindex, "DNSSEC_NTA", nta); +} + +_public_ int sd_network_link_get_timezone(int ifindex, char **ret) { + return network_link_get_string(ifindex, "TIMEZONE", ret); +} + +_public_ int sd_network_link_get_dhcp4_address(int ifindex, char **ret) { + return network_link_get_string(ifindex, "DHCP4_ADDRESS", ret); +} + +_public_ int sd_network_link_get_dns(int ifindex, char ***ret) { + return network_link_get_strv(ifindex, "DNS", ret); +} + +_public_ int sd_network_link_get_ntp(int ifindex, char ***ret) { + return network_link_get_strv(ifindex, "NTP", ret); +} + +_public_ int sd_network_link_get_search_domains(int ifindex, char ***ret) { + return network_link_get_strv(ifindex, "DOMAINS", ret); +} + +_public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) { + return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret); +} + +_public_ int sd_network_link_get_sip_servers(int ifindex, char ***ret) { + return network_link_get_strv(ifindex, "SIP", ret); +} + +_public_ int sd_network_link_get_dns_default_route(int ifindex) { + char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; + _cleanup_free_ char *s = NULL; + int r; + + assert_return(ifindex > 0, -EINVAL); + + xsprintf(path, "/run/systemd/netif/links/%i", ifindex); + + r = parse_env_file(NULL, path, "DNS_DEFAULT_ROUTE", &s); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (isempty(s)) + return -ENODATA; + return parse_boolean(s); +} + +static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) { + char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; + _cleanup_free_ int *ifis = NULL; + _cleanup_free_ char *s = NULL; + size_t allocated = 0, c = 0; + const char *x; + int r; + + assert_return(ifindex > 0, -EINVAL); + assert_return(ret, -EINVAL); + + xsprintf(path, "/run/systemd/netif/links/%i", ifindex); + r = parse_env_file(NULL, path, key, &s); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + + for (x = s;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&x, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + r = parse_ifindex(word, &ifindex); + if (r < 0) + return r; + + if (!GREEDY_REALLOC(ifis, allocated, c + 2)) + return -ENOMEM; + + ifis[c++] = ifindex; + } + + if (ifis) + ifis[c] = 0; /* Let's add a 0 ifindex to the end, to be nice */ + + *ret = TAKE_PTR(ifis); + + return c; +} + +_public_ int sd_network_link_get_carrier_bound_to(int ifindex, int **ret) { + return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_TO", ret); +} + +_public_ int sd_network_link_get_carrier_bound_by(int ifindex, int **ret) { + return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_BY", ret); +} + +static int MONITOR_TO_FD(sd_network_monitor *m) { + return (int) (unsigned long) m - 1; +} + +static sd_network_monitor* FD_TO_MONITOR(int fd) { + return (sd_network_monitor*) (unsigned long) (fd + 1); +} + +static int monitor_add_inotify_watch(int fd) { + int k; + + k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE); + if (k >= 0) + return 0; + else if (errno != ENOENT) + return -errno; + + k = inotify_add_watch(fd, "/run/systemd/netif/", IN_CREATE|IN_ISDIR); + if (k >= 0) + return 0; + else if (errno != ENOENT) + return -errno; + + k = inotify_add_watch(fd, "/run/systemd/", IN_CREATE|IN_ISDIR); + if (k < 0) + return -errno; + + return 0; +} + +_public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) { + _cleanup_close_ int fd = -1; + int k; + bool good = false; + + assert_return(m, -EINVAL); + + fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (fd < 0) + return -errno; + + if (!category || streq(category, "links")) { + k = monitor_add_inotify_watch(fd); + if (k < 0) + return k; + + good = true; + } + + if (!good) + return -EINVAL; + + *m = FD_TO_MONITOR(fd); + fd = -1; + + return 0; +} + +_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) { + int fd; + + if (m) { + fd = MONITOR_TO_FD(m); + close_nointr(fd); + } + + return NULL; +} + +_public_ int sd_network_monitor_flush(sd_network_monitor *m) { + union inotify_event_buffer buffer; + struct inotify_event *e; + ssize_t l; + int fd, k; + + assert_return(m, -EINVAL); + + fd = MONITOR_TO_FD(m); + + l = read(fd, &buffer, sizeof(buffer)); + if (l < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + return -errno; + } + + FOREACH_INOTIFY_EVENT(e, buffer, l) { + if (e->mask & IN_ISDIR) { + k = monitor_add_inotify_watch(fd); + if (k < 0) + return k; + + k = inotify_rm_watch(fd, e->wd); + if (k < 0) + return -errno; + } + } + + return 0; +} + +_public_ int sd_network_monitor_get_fd(sd_network_monitor *m) { + + assert_return(m, -EINVAL); + + return MONITOR_TO_FD(m); +} + +_public_ int sd_network_monitor_get_events(sd_network_monitor *m) { + + assert_return(m, -EINVAL); + + /* For now we will only return POLLIN here, since we don't + * need anything else ever for inotify. However, let's have + * this API to keep our options open should we later on need + * it. */ + return POLLIN; +} + +_public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) { + + assert_return(m, -EINVAL); + assert_return(timeout_usec, -EINVAL); + + /* For now we will only return (uint64_t) -1, since we don't + * need any timeout. However, let's have this API to keep our + * options open should we later on need it. */ + *timeout_usec = (uint64_t) -1; + return 0; +} diff --git a/src/libsystemd/sd-path/sd-path.c b/src/libsystemd/sd-path/sd-path.c new file mode 100644 index 00000000..95d6551e --- /dev/null +++ b/src/libsystemd/sd-path/sd-path.c @@ -0,0 +1,614 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-path.h" + +#include "alloc-util.h" +#include "architecture.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "path-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" + +static int from_environment(const char *envname, const char *fallback, const char **ret) { + assert(ret); + + if (envname) { + const char *e; + + e = secure_getenv(envname); + if (e && path_is_absolute(e)) { + *ret = e; + return 0; + } + } + + if (fallback) { + *ret = fallback; + return 0; + } + + return -ENXIO; +} + +static int from_home_dir(const char *envname, const char *suffix, char **buffer, const char **ret) { + _cleanup_free_ char *h = NULL; + char *cc = NULL; + int r; + + assert(suffix); + assert(buffer); + assert(ret); + + if (envname) { + const char *e = NULL; + + e = secure_getenv(envname); + if (e && path_is_absolute(e)) { + *ret = e; + return 0; + } + } + + r = get_home_dir(&h); + if (r < 0) + return r; + + cc = path_join(h, suffix); + if (!cc) + return -ENOMEM; + + *buffer = cc; + *ret = cc; + return 0; +} + +static int from_user_dir(const char *field, char **buffer, const char **ret) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *b = NULL; + _cleanup_free_ const char *fn = NULL; + const char *c = NULL; + size_t n; + int r; + + assert(field); + assert(buffer); + assert(ret); + + r = from_home_dir("XDG_CONFIG_HOME", ".config", &b, &c); + if (r < 0) + return r; + + fn = path_join(c, "user-dirs.dirs"); + if (!fn) + return -ENOMEM; + + f = fopen(fn, "re"); + if (!f) { + if (errno == ENOENT) + goto fallback; + + return -errno; + } + + /* This is an awful parse, but it follows closely what + * xdg-user-dirs does upstream */ + + n = strlen(field); + for (;;) { + _cleanup_free_ char *line = NULL; + char *l, *p, *e; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + l = strstrip(line); + + if (!strneq(l, field, n)) + continue; + + p = l + n; + p += strspn(p, WHITESPACE); + + if (*p != '=') + continue; + p++; + + p += strspn(p, WHITESPACE); + + if (*p != '"') + continue; + p++; + + e = strrchr(p, '"'); + if (!e) + continue; + *e = 0; + + /* Three syntaxes permitted: relative to $HOME, $HOME itself, and absolute path */ + if (startswith(p, "$HOME/")) { + _cleanup_free_ char *h = NULL; + char *cc; + + r = get_home_dir(&h); + if (r < 0) + return r; + + cc = path_join(h, p+5); + if (!cc) + return -ENOMEM; + + *buffer = cc; + *ret = cc; + return 0; + } else if (streq(p, "$HOME")) { + + r = get_home_dir(buffer); + if (r < 0) + return r; + + *ret = *buffer; + return 0; + } else if (path_is_absolute(p)) { + char *copy; + + copy = strdup(p); + if (!copy) + return -ENOMEM; + + *buffer = copy; + *ret = copy; + return 0; + } + } + +fallback: + /* The desktop directory defaults to $HOME/Desktop, the others to $HOME */ + if (streq(field, "XDG_DESKTOP_DIR")) { + _cleanup_free_ char *h = NULL; + char *cc; + + r = get_home_dir(&h); + if (r < 0) + return r; + + cc = path_join(h, "Desktop"); + if (!cc) + return -ENOMEM; + + *buffer = cc; + *ret = cc; + } else { + + r = get_home_dir(buffer); + if (r < 0) + return r; + + *ret = *buffer; + } + + return 0; +} + +static int get_path(uint64_t type, char **buffer, const char **ret) { + int r; + + assert(buffer); + assert(ret); + + switch (type) { + + case SD_PATH_TEMPORARY: + return tmp_dir(ret); + + case SD_PATH_TEMPORARY_LARGE: + return var_tmp_dir(ret); + + case SD_PATH_SYSTEM_BINARIES: + *ret = "/usr/bin"; + return 0; + + case SD_PATH_SYSTEM_INCLUDE: + *ret = "/usr/include"; + return 0; + + case SD_PATH_SYSTEM_LIBRARY_PRIVATE: + *ret = "/usr/lib"; + return 0; + + case SD_PATH_SYSTEM_LIBRARY_ARCH: + *ret = LIBDIR; + return 0; + + case SD_PATH_SYSTEM_SHARED: + *ret = "/usr/share"; + return 0; + + case SD_PATH_SYSTEM_CONFIGURATION_FACTORY: + *ret = "/usr/share/factory/etc"; + return 0; + + case SD_PATH_SYSTEM_STATE_FACTORY: + *ret = "/usr/share/factory/var"; + return 0; + + case SD_PATH_SYSTEM_CONFIGURATION: + *ret = "/etc"; + return 0; + + case SD_PATH_SYSTEM_RUNTIME: + *ret = "/run"; + return 0; + + case SD_PATH_SYSTEM_RUNTIME_LOGS: + *ret = "/run/log"; + return 0; + + case SD_PATH_SYSTEM_STATE_PRIVATE: + *ret = "/var/lib"; + return 0; + + case SD_PATH_SYSTEM_STATE_LOGS: + *ret = "/var/log"; + return 0; + + case SD_PATH_SYSTEM_STATE_CACHE: + *ret = "/var/cache"; + return 0; + + case SD_PATH_SYSTEM_STATE_SPOOL: + *ret = "/var/spool"; + return 0; + + case SD_PATH_USER_BINARIES: + return from_home_dir(NULL, ".local/bin", buffer, ret); + + case SD_PATH_USER_LIBRARY_PRIVATE: + return from_home_dir(NULL, ".local/lib", buffer, ret); + + case SD_PATH_USER_LIBRARY_ARCH: + return from_home_dir(NULL, ".local/lib/" LIB_ARCH_TUPLE, buffer, ret); + + case SD_PATH_USER_SHARED: + return from_home_dir("XDG_DATA_HOME", ".local/share", buffer, ret); + + case SD_PATH_USER_CONFIGURATION: + return from_home_dir("XDG_CONFIG_HOME", ".config", buffer, ret); + + case SD_PATH_USER_RUNTIME: + return from_environment("XDG_RUNTIME_DIR", NULL, ret); + + case SD_PATH_USER_STATE_CACHE: + return from_home_dir("XDG_CACHE_HOME", ".cache", buffer, ret); + + case SD_PATH_USER: + r = get_home_dir(buffer); + if (r < 0) + return r; + + *ret = *buffer; + return 0; + + case SD_PATH_USER_DOCUMENTS: + return from_user_dir("XDG_DOCUMENTS_DIR", buffer, ret); + + case SD_PATH_USER_MUSIC: + return from_user_dir("XDG_MUSIC_DIR", buffer, ret); + + case SD_PATH_USER_PICTURES: + return from_user_dir("XDG_PICTURES_DIR", buffer, ret); + + case SD_PATH_USER_VIDEOS: + return from_user_dir("XDG_VIDEOS_DIR", buffer, ret); + + case SD_PATH_USER_DOWNLOAD: + return from_user_dir("XDG_DOWNLOAD_DIR", buffer, ret); + + case SD_PATH_USER_PUBLIC: + return from_user_dir("XDG_PUBLICSHARE_DIR", buffer, ret); + + case SD_PATH_USER_TEMPLATES: + return from_user_dir("XDG_TEMPLATES_DIR", buffer, ret); + + case SD_PATH_USER_DESKTOP: + return from_user_dir("XDG_DESKTOP_DIR", buffer, ret); + } + + return -EOPNOTSUPP; +} + +_public_ int sd_path_home(uint64_t type, const char *suffix, char **path) { + _cleanup_free_ char *buffer = NULL; + const char *ret; + char *cc; + int r; + + assert_return(path, -EINVAL); + + if (IN_SET(type, + SD_PATH_SEARCH_BINARIES, + SD_PATH_SEARCH_BINARIES_DEFAULT, + SD_PATH_SEARCH_LIBRARY_PRIVATE, + SD_PATH_SEARCH_LIBRARY_ARCH, + SD_PATH_SEARCH_SHARED, + SD_PATH_SEARCH_CONFIGURATION_FACTORY, + SD_PATH_SEARCH_STATE_FACTORY, + SD_PATH_SEARCH_CONFIGURATION)) { + + _cleanup_strv_free_ char **l = NULL; + + r = sd_path_search(type, suffix, &l); + if (r < 0) + return r; + + buffer = strv_join(l, ":"); + if (!buffer) + return -ENOMEM; + + *path = TAKE_PTR(buffer); + return 0; + } + + r = get_path(type, &buffer, &ret); + if (r < 0) + return r; + + if (!suffix) { + if (!buffer) { + buffer = strdup(ret); + if (!buffer) + return -ENOMEM; + } + + *path = TAKE_PTR(buffer); + return 0; + } + + suffix += strspn(suffix, "/"); + cc = path_join(ret, suffix); + if (!cc) + return -ENOMEM; + + *path = TAKE_PTR(cc); + return 0; +} + +static int search_from_environment( + char ***list, + const char *env_home, + const char *home_suffix, + const char *env_search, + bool env_search_sufficient, + const char *first, ...) { + + _cleanup_strv_free_ char **l = NULL; + const char *e; + char *h = NULL; + int r; + + assert(list); + + if (env_search) { + e = secure_getenv(env_search); + if (e) { + l = strv_split(e, ":"); + if (!l) + return -ENOMEM; + + if (env_search_sufficient) { + *list = TAKE_PTR(l); + return 0; + } + } + } + + if (!l && first) { + va_list ap; + + va_start(ap, first); + l = strv_new_ap(first, ap); + va_end(ap); + + if (!l) + return -ENOMEM; + } + + if (env_home) { + e = secure_getenv(env_home); + if (e && path_is_absolute(e)) { + h = strdup(e); + if (!h) + return -ENOMEM; + } + } + + if (!h && home_suffix) { + e = secure_getenv("HOME"); + if (e && path_is_absolute(e)) { + h = path_join(e, home_suffix); + if (!h) + return -ENOMEM; + } + } + + if (h) { + r = strv_consume_prepend(&l, h); + if (r < 0) + return -ENOMEM; + } + + *list = TAKE_PTR(l); + return 0; +} + +#if HAVE_SPLIT_BIN +# define ARRAY_SBIN_BIN(x) x "sbin", x "bin" +#else +# define ARRAY_SBIN_BIN(x) x "bin" +#endif + +static int get_search(uint64_t type, char ***list) { + + assert(list); + + switch(type) { + + case SD_PATH_SEARCH_BINARIES: + return search_from_environment(list, + NULL, + ".local/bin", + "PATH", + true, + ARRAY_SBIN_BIN("/usr/local/"), + ARRAY_SBIN_BIN("/usr/"), +#if HAVE_SPLIT_USR + ARRAY_SBIN_BIN("/"), +#endif + NULL); + + case SD_PATH_SEARCH_LIBRARY_PRIVATE: + return search_from_environment(list, + NULL, + ".local/lib", + NULL, + false, + "/usr/local/lib", + "/usr/lib", +#if HAVE_SPLIT_USR + "/lib", +#endif + NULL); + + case SD_PATH_SEARCH_LIBRARY_ARCH: + return search_from_environment(list, + NULL, + ".local/lib/" LIB_ARCH_TUPLE, + "LD_LIBRARY_PATH", + true, + LIBDIR, +#if HAVE_SPLIT_USR + ROOTLIBDIR, +#endif + NULL); + + case SD_PATH_SEARCH_SHARED: + return search_from_environment(list, + "XDG_DATA_HOME", + ".local/share", + "XDG_DATA_DIRS", + false, + "/usr/local/share", + "/usr/share", + NULL); + + case SD_PATH_SEARCH_CONFIGURATION_FACTORY: + return search_from_environment(list, + NULL, + NULL, + NULL, + false, + "/usr/local/share/factory/etc", + "/usr/share/factory/etc", + NULL); + + case SD_PATH_SEARCH_STATE_FACTORY: + return search_from_environment(list, + NULL, + NULL, + NULL, + false, + "/usr/local/share/factory/var", + "/usr/share/factory/var", + NULL); + + case SD_PATH_SEARCH_CONFIGURATION: + return search_from_environment(list, + "XDG_CONFIG_HOME", + ".config", + "XDG_CONFIG_DIRS", + false, + "/etc", + NULL); + + case SD_PATH_SEARCH_BINARIES_DEFAULT: { + char **t; + + t = strv_split_nulstr(DEFAULT_PATH_NULSTR); + if (!t) + return -ENOMEM; + + *list = t; + return 0; + }} + + return -EOPNOTSUPP; +} + +_public_ int sd_path_search(uint64_t type, const char *suffix, char ***paths) { + char **i, **j; + _cleanup_strv_free_ char **l = NULL, **n = NULL; + int r; + + assert_return(paths, -EINVAL); + + if (!IN_SET(type, + SD_PATH_SEARCH_BINARIES, + SD_PATH_SEARCH_BINARIES_DEFAULT, + SD_PATH_SEARCH_LIBRARY_PRIVATE, + SD_PATH_SEARCH_LIBRARY_ARCH, + SD_PATH_SEARCH_SHARED, + SD_PATH_SEARCH_CONFIGURATION_FACTORY, + SD_PATH_SEARCH_STATE_FACTORY, + SD_PATH_SEARCH_CONFIGURATION)) { + + char *p; + + r = sd_path_home(type, suffix, &p); + if (r < 0) + return r; + + l = new(char*, 2); + if (!l) { + free(p); + return -ENOMEM; + } + + l[0] = p; + l[1] = NULL; + + *paths = TAKE_PTR(l); + return 0; + } + + r = get_search(type, &l); + if (r < 0) + return r; + + if (!suffix) { + *paths = TAKE_PTR(l); + return 0; + } + + n = new(char*, strv_length(l)+1); + if (!n) + return -ENOMEM; + + j = n; + STRV_FOREACH(i, l) { + *j = path_join(*i, suffix); + if (!*j) + return -ENOMEM; + + j++; + } + + *j = NULL; + *paths = TAKE_PTR(n); + return 0; +} diff --git a/src/libsystemd/sd-resolve/resolve-private.h b/src/libsystemd/sd-resolve/resolve-private.h new file mode 100644 index 00000000..a0feb36f --- /dev/null +++ b/src/libsystemd/sd-resolve/resolve-private.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-resolve.h" + +int resolve_getaddrinfo_with_destroy_callback( + sd_resolve *resolve, sd_resolve_query **q, + const char *node, const char *service, const struct addrinfo *hints, + sd_resolve_getaddrinfo_handler_t callback, + sd_resolve_destroy_t destroy_callback, void *userdata); +int resolve_getnameinfo_with_destroy_callback( + sd_resolve *resolve, sd_resolve_query **q, + const struct sockaddr *sa, socklen_t salen, int flags, uint64_t get, + sd_resolve_getnameinfo_handler_t callback, + sd_resolve_destroy_t destroy_callback, void *userdata); + +#define resolve_getaddrinfo(resolve, ret_query, node, service, hints, callback, destroy_callback, userdata) \ + ({ \ + int (*_callback_)(sd_resolve_query*, int, const struct addrinfo*, typeof(userdata)) = callback; \ + void (*_destroy_)(typeof(userdata)) = destroy_callback; \ + resolve_getaddrinfo_with_destroy_callback( \ + resolve, ret_query, \ + node, service, hints, \ + (sd_resolve_getaddrinfo_handler_t) _callback_, \ + (sd_resolve_destroy_t) _destroy_, \ + userdata); \ + }) + +#define resolve_getnameinfo(resolve, ret_query, sa, salen, flags, get, callback, destroy_callback, userdata) \ + ({ \ + int (*_callback_)(sd_resolve_query*, int, const char*, const char*, typeof(userdata)) = callback; \ + void (*_destroy_)(typeof(userdata)) = destroy_callback; \ + resolve_getaddrinfo_with_destroy_callback( \ + resolve, ret_query, \ + sa, salen, flags, get, \ + (sd_resolve_getnameinfo_handler_t) _callback_, \ + (sd_resolve_destroy_t) _destroy_, \ + userdata); \ + }) diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c new file mode 100644 index 00000000..9d4057f7 --- /dev/null +++ b/src/libsystemd/sd-resolve/sd-resolve.c @@ -0,0 +1,1301 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-resolve.h" + +#include "alloc-util.h" +#include "dns-domain.h" +#include "errno-util.h" +#include "fd-util.h" +#include "io-util.h" +#include "list.h" +#include "memory-util.h" +#include "missing_syscall.h" +#include "process-util.h" +#include "resolve-private.h" +#include "socket-util.h" + +#define WORKERS_MIN 1U +#define WORKERS_MAX 16U +#define QUERIES_MAX 256U +#define BUFSIZE 10240U + +typedef enum { + REQUEST_ADDRINFO, + RESPONSE_ADDRINFO, + REQUEST_NAMEINFO, + RESPONSE_NAMEINFO, + REQUEST_TERMINATE, + RESPONSE_DIED +} QueryType; + +enum { + REQUEST_RECV_FD, + REQUEST_SEND_FD, + RESPONSE_RECV_FD, + RESPONSE_SEND_FD, + _FD_MAX +}; + +struct sd_resolve { + unsigned n_ref; + + bool dead:1; + pid_t original_pid; + + int fds[_FD_MAX]; + + pthread_t workers[WORKERS_MAX]; + unsigned n_valid_workers; + + unsigned current_id; + sd_resolve_query* query_array[QUERIES_MAX]; + unsigned n_queries, n_done, n_outstanding; + + sd_event_source *event_source; + sd_event *event; + + sd_resolve_query *current; + + sd_resolve **default_resolve_ptr; + pid_t tid; + + LIST_HEAD(sd_resolve_query, queries); +}; + +struct sd_resolve_query { + unsigned n_ref; + + sd_resolve *resolve; + + QueryType type:4; + bool done:1; + bool floating:1; + unsigned id; + + int ret; + int _errno; + int _h_errno; + struct addrinfo *addrinfo; + char *serv, *host; + + union { + sd_resolve_getaddrinfo_handler_t getaddrinfo_handler; + sd_resolve_getnameinfo_handler_t getnameinfo_handler; + }; + + void *userdata; + sd_resolve_destroy_t destroy_callback; + + LIST_FIELDS(sd_resolve_query, queries); +}; + +typedef struct RHeader { + QueryType type; + unsigned id; + size_t length; +} RHeader; + +typedef struct AddrInfoRequest { + struct RHeader header; + bool hints_valid; + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t node_len, service_len; +} AddrInfoRequest; + +typedef struct AddrInfoResponse { + struct RHeader header; + int ret; + int _errno; + int _h_errno; + /* followed by addrinfo_serialization[] */ +} AddrInfoResponse; + +typedef struct AddrInfoSerialization { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + size_t canonname_len; + /* Followed by ai_addr amd ai_canonname with variable lengths */ +} AddrInfoSerialization; + +typedef struct NameInfoRequest { + struct RHeader header; + int flags; + socklen_t sockaddr_len; + bool gethost:1, getserv:1; +} NameInfoRequest; + +typedef struct NameInfoResponse { + struct RHeader header; + size_t hostlen, servlen; + int ret; + int _errno; + int _h_errno; +} NameInfoResponse; + +typedef union Packet { + RHeader rheader; + AddrInfoRequest addrinfo_request; + AddrInfoResponse addrinfo_response; + NameInfoRequest nameinfo_request; + NameInfoResponse nameinfo_response; +} Packet; + +static int getaddrinfo_done(sd_resolve_query* q); +static int getnameinfo_done(sd_resolve_query *q); + +static void resolve_query_disconnect(sd_resolve_query *q); + +#define RESOLVE_DONT_DESTROY(resolve) \ + _cleanup_(sd_resolve_unrefp) _unused_ sd_resolve *_dont_destroy_##resolve = sd_resolve_ref(resolve) + +static void query_assign_errno(sd_resolve_query *q, int ret, int error, int h_error) { + assert(q); + + q->ret = ret; + q->_errno = abs(error); + q->_h_errno = h_error; +} + +static int send_died(int out_fd) { + RHeader rh = { + .type = RESPONSE_DIED, + .length = sizeof(RHeader), + }; + + assert(out_fd >= 0); + + if (send(out_fd, &rh, rh.length, MSG_NOSIGNAL) < 0) + return -errno; + + return 0; +} + +static void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) { + AddrInfoSerialization s; + size_t cnl, l; + + assert(p); + assert(ai); + assert(length); + assert(*length <= maxlength); + + cnl = ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0; + l = sizeof(AddrInfoSerialization) + ai->ai_addrlen + cnl; + + if (*length + l > maxlength) + return NULL; + + s = (AddrInfoSerialization) { + .ai_flags = ai->ai_flags, + .ai_family = ai->ai_family, + .ai_socktype = ai->ai_socktype, + .ai_protocol = ai->ai_protocol, + .ai_addrlen = ai->ai_addrlen, + .canonname_len = cnl, + }; + + memcpy((uint8_t*) p, &s, sizeof(AddrInfoSerialization)); + memcpy((uint8_t*) p + sizeof(AddrInfoSerialization), ai->ai_addr, ai->ai_addrlen); + memcpy_safe((char*) p + sizeof(AddrInfoSerialization) + ai->ai_addrlen, + ai->ai_canonname, cnl); + + *length += l; + return (uint8_t*) p + l; +} + +static int send_addrinfo_reply( + int out_fd, + unsigned id, + int ret, + struct addrinfo *ai, + int _errno, + int _h_errno) { + + AddrInfoResponse resp = {}; + union { + AddrInfoSerialization ais; + uint8_t space[BUFSIZE]; + } buffer; + struct iovec iov[2]; + struct msghdr mh; + + assert(out_fd >= 0); + + resp = (AddrInfoResponse) { + .header.type = RESPONSE_ADDRINFO, + .header.id = id, + .header.length = sizeof(AddrInfoResponse), + .ret = ret, + ._errno = _errno, + ._h_errno = _h_errno, + }; + + msan_unpoison(&resp, sizeof(resp)); + + if (ret == 0 && ai) { + void *p = &buffer; + struct addrinfo *k; + + for (k = ai; k; k = k->ai_next) { + p = serialize_addrinfo(p, k, &resp.header.length, (uint8_t*) &buffer + BUFSIZE - (uint8_t*) p); + if (!p) { + freeaddrinfo(ai); + return -ENOBUFS; + } + } + } + + if (ai) + freeaddrinfo(ai); + + iov[0] = IOVEC_MAKE(&resp, sizeof(AddrInfoResponse)); + iov[1] = IOVEC_MAKE(&buffer, resp.header.length - sizeof(AddrInfoResponse)); + + mh = (struct msghdr) { + .msg_iov = iov, + .msg_iovlen = ELEMENTSOF(iov) + }; + + if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0) + return -errno; + + return 0; +} + +static int send_nameinfo_reply( + int out_fd, + unsigned id, + int ret, + const char *host, + const char *serv, + int _errno, + int _h_errno) { + + NameInfoResponse resp = {}; + struct iovec iov[3]; + struct msghdr mh; + size_t hl, sl; + + assert(out_fd >= 0); + + sl = serv ? strlen(serv)+1 : 0; + hl = host ? strlen(host)+1 : 0; + + resp = (NameInfoResponse) { + .header.type = RESPONSE_NAMEINFO, + .header.id = id, + .header.length = sizeof(NameInfoResponse) + hl + sl, + .hostlen = hl, + .servlen = sl, + .ret = ret, + ._errno = _errno, + ._h_errno = _h_errno, + }; + + msan_unpoison(&resp, sizeof(resp)); + + iov[0] = IOVEC_MAKE(&resp, sizeof(NameInfoResponse)); + iov[1] = IOVEC_MAKE((void*) host, hl); + iov[2] = IOVEC_MAKE((void*) serv, sl); + + mh = (struct msghdr) { + .msg_iov = iov, + .msg_iovlen = ELEMENTSOF(iov) + }; + + if (sendmsg(out_fd, &mh, MSG_NOSIGNAL) < 0) + return -errno; + + return 0; +} + +static int handle_request(int out_fd, const Packet *packet, size_t length) { + const RHeader *req; + + assert(out_fd >= 0); + assert(packet); + + req = &packet->rheader; + + assert_return(length >= sizeof(RHeader), -EIO); + assert_return(length == req->length, -EIO); + + switch (req->type) { + + case REQUEST_ADDRINFO: { + const AddrInfoRequest *ai_req = &packet->addrinfo_request; + struct addrinfo hints, *result = NULL; + const char *node, *service; + int ret; + + assert_return(length >= sizeof(AddrInfoRequest), -EBADMSG); + assert_return(length == sizeof(AddrInfoRequest) + ai_req->node_len + ai_req->service_len, -EBADMSG); + + hints = (struct addrinfo) { + .ai_flags = ai_req->ai_flags, + .ai_family = ai_req->ai_family, + .ai_socktype = ai_req->ai_socktype, + .ai_protocol = ai_req->ai_protocol, + }; + + msan_unpoison(&hints, sizeof(hints)); + + node = ai_req->node_len ? (const char*) ai_req + sizeof(AddrInfoRequest) : NULL; + service = ai_req->service_len ? (const char*) ai_req + sizeof(AddrInfoRequest) + ai_req->node_len : NULL; + + ret = getaddrinfo(node, service, + ai_req->hints_valid ? &hints : NULL, + &result); + + /* send_addrinfo_reply() frees result */ + return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno); + } + + case REQUEST_NAMEINFO: { + const NameInfoRequest *ni_req = &packet->nameinfo_request; + char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV]; + union sockaddr_union sa; + int ret; + + assert_return(length >= sizeof(NameInfoRequest), -EBADMSG); + assert_return(length == sizeof(NameInfoRequest) + ni_req->sockaddr_len, -EBADMSG); + assert_return(ni_req->sockaddr_len <= sizeof(sa), -EBADMSG); + + memcpy(&sa, (const uint8_t *) ni_req + sizeof(NameInfoRequest), ni_req->sockaddr_len); + + ret = getnameinfo(&sa.sa, ni_req->sockaddr_len, + ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0, + ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0, + ni_req->flags); + + return send_nameinfo_reply(out_fd, req->id, ret, + ret == 0 && ni_req->gethost ? hostbuf : NULL, + ret == 0 && ni_req->getserv ? servbuf : NULL, + errno, h_errno); + } + + case REQUEST_TERMINATE: + /* Quit */ + return -ECONNRESET; + + default: + assert_not_reached("Unknown request"); + } + + return 0; +} + +static void* thread_worker(void *p) { + sd_resolve *resolve = p; + + /* Assign a pretty name to this thread */ + (void) pthread_setname_np(pthread_self(), "sd-resolve"); + + while (!resolve->dead) { + union { + Packet packet; + uint8_t space[BUFSIZE]; + } buf; + ssize_t length; + + length = recv(resolve->fds[REQUEST_RECV_FD], &buf, sizeof buf, 0); + if (length < 0) { + if (errno == EINTR) + continue; + + break; + } + if (length == 0) + break; + + if (handle_request(resolve->fds[RESPONSE_SEND_FD], &buf.packet, (size_t) length) < 0) + break; + } + + send_died(resolve->fds[RESPONSE_SEND_FD]); + + return NULL; +} + +static int start_threads(sd_resolve *resolve, unsigned extra) { + sigset_t ss, saved_ss; + unsigned n; + int r, k; + + assert_se(sigfillset(&ss) >= 0); + + /* No signals in forked off threads please. We set the mask before forking, so that the threads never exist + * with a different mask than a fully blocked one */ + r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss); + if (r > 0) + return -r; + + n = resolve->n_outstanding + extra; + n = CLAMP(n, WORKERS_MIN, WORKERS_MAX); + + while (resolve->n_valid_workers < n) { + r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve); + if (r > 0) { + r = -r; + goto finish; + } + + resolve->n_valid_workers++; + } + + r = 0; + +finish: + k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL); + if (k > 0 && r >= 0) + r = -k; + + return r; +} + +static bool resolve_pid_changed(sd_resolve *r) { + assert(r); + + /* We don't support people creating a resolver and keeping it + * around after fork(). Let's complain. */ + + return r->original_pid != getpid_cached(); +} + +_public_ int sd_resolve_new(sd_resolve **ret) { + _cleanup_(sd_resolve_unrefp) sd_resolve *resolve = NULL; + int i; + + assert_return(ret, -EINVAL); + + resolve = new0(sd_resolve, 1); + if (!resolve) + return -ENOMEM; + + resolve->n_ref = 1; + resolve->original_pid = getpid_cached(); + + for (i = 0; i < _FD_MAX; i++) + resolve->fds[i] = -1; + + if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + REQUEST_RECV_FD) < 0) + return -errno; + + if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, resolve->fds + RESPONSE_RECV_FD) < 0) + return -errno; + + for (i = 0; i < _FD_MAX; i++) + resolve->fds[i] = fd_move_above_stdio(resolve->fds[i]); + + (void) fd_inc_sndbuf(resolve->fds[REQUEST_SEND_FD], QUERIES_MAX * BUFSIZE); + (void) fd_inc_rcvbuf(resolve->fds[REQUEST_RECV_FD], QUERIES_MAX * BUFSIZE); + (void) fd_inc_sndbuf(resolve->fds[RESPONSE_SEND_FD], QUERIES_MAX * BUFSIZE); + (void) fd_inc_rcvbuf(resolve->fds[RESPONSE_RECV_FD], QUERIES_MAX * BUFSIZE); + + (void) fd_nonblock(resolve->fds[RESPONSE_RECV_FD], true); + + *ret = TAKE_PTR(resolve); + return 0; +} + +_public_ int sd_resolve_default(sd_resolve **ret) { + static thread_local sd_resolve *default_resolve = NULL; + sd_resolve *e = NULL; + int r; + + if (!ret) + return !!default_resolve; + + if (default_resolve) { + *ret = sd_resolve_ref(default_resolve); + return 0; + } + + r = sd_resolve_new(&e); + if (r < 0) + return r; + + e->default_resolve_ptr = &default_resolve; + e->tid = gettid(); + default_resolve = e; + + *ret = e; + return 1; +} + +_public_ int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid) { + assert_return(resolve, -EINVAL); + assert_return(tid, -EINVAL); + assert_return(!resolve_pid_changed(resolve), -ECHILD); + + if (resolve->tid != 0) { + *tid = resolve->tid; + return 0; + } + + if (resolve->event) + return sd_event_get_tid(resolve->event, tid); + + return -ENXIO; +} + +static sd_resolve *resolve_free(sd_resolve *resolve) { + PROTECT_ERRNO; + sd_resolve_query *q; + unsigned i; + + assert(resolve); + + while ((q = resolve->queries)) { + assert(q->floating); + resolve_query_disconnect(q); + sd_resolve_query_unref(q); + } + + if (resolve->default_resolve_ptr) + *(resolve->default_resolve_ptr) = NULL; + + resolve->dead = true; + + sd_resolve_detach_event(resolve); + + if (resolve->fds[REQUEST_SEND_FD] >= 0) { + + RHeader req = { + .type = REQUEST_TERMINATE, + .length = sizeof req, + }; + + /* Send one termination packet for each worker */ + for (i = 0; i < resolve->n_valid_workers; i++) + (void) send(resolve->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL); + } + + /* Now terminate them and wait until they are gone. + If we get an error than most likely the thread already exited. */ + for (i = 0; i < resolve->n_valid_workers; i++) + (void) pthread_join(resolve->workers[i], NULL); + + /* Close all communication channels */ + close_many(resolve->fds, _FD_MAX); + + return mfree(resolve); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_resolve, sd_resolve, resolve_free); + +_public_ int sd_resolve_get_fd(sd_resolve *resolve) { + assert_return(resolve, -EINVAL); + assert_return(!resolve_pid_changed(resolve), -ECHILD); + + return resolve->fds[RESPONSE_RECV_FD]; +} + +_public_ int sd_resolve_get_events(sd_resolve *resolve) { + assert_return(resolve, -EINVAL); + assert_return(!resolve_pid_changed(resolve), -ECHILD); + + return resolve->n_queries > resolve->n_done ? POLLIN : 0; +} + +_public_ int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *usec) { + assert_return(resolve, -EINVAL); + assert_return(usec, -EINVAL); + assert_return(!resolve_pid_changed(resolve), -ECHILD); + + *usec = (uint64_t) -1; + return 0; +} + +static sd_resolve_query *lookup_query(sd_resolve *resolve, unsigned id) { + sd_resolve_query *q; + + assert(resolve); + + q = resolve->query_array[id % QUERIES_MAX]; + if (q) + if (q->id == id) + return q; + + return NULL; +} + +static int complete_query(sd_resolve *resolve, sd_resolve_query *q) { + int r; + + assert(q); + assert(!q->done); + assert(q->resolve == resolve); + + q->done = true; + resolve->n_done++; + + resolve->current = sd_resolve_query_ref(q); + + switch (q->type) { + + case REQUEST_ADDRINFO: + r = getaddrinfo_done(q); + break; + + case REQUEST_NAMEINFO: + r = getnameinfo_done(q); + break; + + default: + assert_not_reached("Cannot complete unknown query type"); + } + + resolve->current = NULL; + + if (q->floating) { + resolve_query_disconnect(q); + sd_resolve_query_unref(q); + } + + sd_resolve_query_unref(q); + + return r; +} + +static int unserialize_addrinfo(const void **p, size_t *length, struct addrinfo **ret_ai) { + AddrInfoSerialization s; + struct addrinfo *ai; + size_t l; + + assert(p); + assert(*p); + assert(ret_ai); + assert(length); + + if (*length < sizeof(AddrInfoSerialization)) + return -EBADMSG; + + memcpy(&s, *p, sizeof(s)); + + l = sizeof(AddrInfoSerialization) + s.ai_addrlen + s.canonname_len; + if (*length < l) + return -EBADMSG; + + ai = new(struct addrinfo, 1); + if (!ai) + return -ENOMEM; + + *ai = (struct addrinfo) { + .ai_flags = s.ai_flags, + .ai_family = s.ai_family, + .ai_socktype = s.ai_socktype, + .ai_protocol = s.ai_protocol, + .ai_addrlen = s.ai_addrlen, + }; + + if (s.ai_addrlen > 0) { + ai->ai_addr = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization), s.ai_addrlen); + if (!ai->ai_addr) { + free(ai); + return -ENOMEM; + } + } + + if (s.canonname_len > 0) { + ai->ai_canonname = memdup((const uint8_t*) *p + sizeof(AddrInfoSerialization) + s.ai_addrlen, s.canonname_len); + if (!ai->ai_canonname) { + free(ai->ai_addr); + free(ai); + return -ENOMEM; + } + } + + *length -= l; + *ret_ai = ai; + *p = ((const uint8_t*) *p) + l; + + return 0; +} + +static int handle_response(sd_resolve *resolve, const Packet *packet, size_t length) { + const RHeader *resp; + sd_resolve_query *q; + int r; + + assert(resolve); + assert(packet); + + resp = &packet->rheader; + assert_return(length >= sizeof(RHeader), -EIO); + assert_return(length == resp->length, -EIO); + + if (resp->type == RESPONSE_DIED) { + resolve->dead = true; + return 0; + } + + assert(resolve->n_outstanding > 0); + resolve->n_outstanding--; + + q = lookup_query(resolve, resp->id); + if (!q) + return 0; + + switch (resp->type) { + + case RESPONSE_ADDRINFO: { + const AddrInfoResponse *ai_resp = &packet->addrinfo_response; + const void *p; + size_t l; + struct addrinfo *prev = NULL; + + assert_return(length >= sizeof(AddrInfoResponse), -EBADMSG); + assert_return(q->type == REQUEST_ADDRINFO, -EBADMSG); + + query_assign_errno(q, ai_resp->ret, ai_resp->_errno, ai_resp->_h_errno); + + l = length - sizeof(AddrInfoResponse); + p = (const uint8_t*) resp + sizeof(AddrInfoResponse); + + while (l > 0 && p) { + struct addrinfo *ai = NULL; + + r = unserialize_addrinfo(&p, &l, &ai); + if (r < 0) { + query_assign_errno(q, EAI_SYSTEM, r, 0); + freeaddrinfo(q->addrinfo); + q->addrinfo = NULL; + break; + } + + if (prev) + prev->ai_next = ai; + else + q->addrinfo = ai; + + prev = ai; + } + + return complete_query(resolve, q); + } + + case RESPONSE_NAMEINFO: { + const NameInfoResponse *ni_resp = &packet->nameinfo_response; + + assert_return(length >= sizeof(NameInfoResponse), -EBADMSG); + assert_return(q->type == REQUEST_NAMEINFO, -EBADMSG); + + if (ni_resp->hostlen > DNS_HOSTNAME_MAX || + ni_resp->servlen > DNS_HOSTNAME_MAX || + sizeof(NameInfoResponse) + ni_resp->hostlen + ni_resp->servlen > length) + query_assign_errno(q, EAI_SYSTEM, EIO, 0); + else { + query_assign_errno(q, ni_resp->ret, ni_resp->_errno, ni_resp->_h_errno); + + if (ni_resp->hostlen > 0) { + q->host = strndup((const char*) ni_resp + sizeof(NameInfoResponse), + ni_resp->hostlen-1); + if (!q->host) + query_assign_errno(q, EAI_MEMORY, ENOMEM, 0); + } + + if (ni_resp->servlen > 0) { + q->serv = strndup((const char*) ni_resp + sizeof(NameInfoResponse) + ni_resp->hostlen, + ni_resp->servlen-1); + if (!q->serv) + query_assign_errno(q, EAI_MEMORY, ENOMEM, 0); + } + } + + return complete_query(resolve, q); + } + + default: + return 0; + } +} + +_public_ int sd_resolve_process(sd_resolve *resolve) { + RESOLVE_DONT_DESTROY(resolve); + + union { + Packet packet; + uint8_t space[BUFSIZE]; + } buf; + ssize_t l; + int r; + + assert_return(resolve, -EINVAL); + assert_return(!resolve_pid_changed(resolve), -ECHILD); + + /* We don't allow recursively invoking sd_resolve_process(). */ + assert_return(!resolve->current, -EBUSY); + + l = recv(resolve->fds[RESPONSE_RECV_FD], &buf, sizeof buf, 0); + if (l < 0) { + if (errno == EAGAIN) + return 0; + + return -errno; + } + if (l == 0) + return -ECONNREFUSED; + + r = handle_response(resolve, &buf.packet, (size_t) l); + if (r < 0) + return r; + + return 1; +} + +_public_ int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec) { + int r; + + assert_return(resolve, -EINVAL); + assert_return(!resolve_pid_changed(resolve), -ECHILD); + + if (resolve->n_done >= resolve->n_queries) + return 0; + + do { + r = fd_wait_for_event(resolve->fds[RESPONSE_RECV_FD], POLLIN, timeout_usec); + } while (r == -EINTR); + + if (r < 0) + return r; + if (r == 0) + return -ETIMEDOUT; + + return sd_resolve_process(resolve); +} + +static int alloc_query(sd_resolve *resolve, bool floating, sd_resolve_query **_q) { + sd_resolve_query *q; + int r; + + assert(resolve); + assert(_q); + + if (resolve->n_queries >= QUERIES_MAX) + return -ENOBUFS; + + r = start_threads(resolve, 1); + if (r < 0) + return r; + + while (resolve->query_array[resolve->current_id % QUERIES_MAX]) + resolve->current_id++; + + q = resolve->query_array[resolve->current_id % QUERIES_MAX] = new0(sd_resolve_query, 1); + if (!q) + return -ENOMEM; + + q->n_ref = 1; + q->resolve = resolve; + q->floating = floating; + q->id = resolve->current_id++; + + if (!floating) + sd_resolve_ref(resolve); + + LIST_PREPEND(queries, resolve->queries, q); + resolve->n_queries++; + + *_q = q; + return 0; +} + +int resolve_getaddrinfo_with_destroy_callback( + sd_resolve *resolve, + sd_resolve_query **ret_query, + const char *node, const char *service, + const struct addrinfo *hints, + sd_resolve_getaddrinfo_handler_t callback, + sd_resolve_destroy_t destroy_callback, + void *userdata) { + + _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL; + size_t node_len, service_len; + AddrInfoRequest req = {}; + struct iovec iov[3]; + struct msghdr mh = {}; + int r; + + assert_return(resolve, -EINVAL); + assert_return(node || service, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(!resolve_pid_changed(resolve), -ECHILD); + + r = alloc_query(resolve, !ret_query, &q); + if (r < 0) + return r; + + q->type = REQUEST_ADDRINFO; + q->getaddrinfo_handler = callback; + q->userdata = userdata; + + node_len = node ? strlen(node) + 1 : 0; + service_len = service ? strlen(service) + 1 : 0; + + req = (AddrInfoRequest) { + .node_len = node_len, + .service_len = service_len, + + .header.id = q->id, + .header.type = REQUEST_ADDRINFO, + .header.length = sizeof(AddrInfoRequest) + node_len + service_len, + + .hints_valid = hints, + .ai_flags = hints ? hints->ai_flags : 0, + .ai_family = hints ? hints->ai_family : 0, + .ai_socktype = hints ? hints->ai_socktype : 0, + .ai_protocol = hints ? hints->ai_protocol : 0, + }; + + msan_unpoison(&req, sizeof(req)); + + iov[mh.msg_iovlen++] = IOVEC_MAKE(&req, sizeof(AddrInfoRequest)); + if (node) + iov[mh.msg_iovlen++] = IOVEC_MAKE((void*) node, req.node_len); + if (service) + iov[mh.msg_iovlen++] = IOVEC_MAKE((void*) service, req.service_len); + mh.msg_iov = iov; + + if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) + return -errno; + + resolve->n_outstanding++; + q->destroy_callback = destroy_callback; + + if (ret_query) + *ret_query = q; + + TAKE_PTR(q); + + return 0; +} + +_public_ int sd_resolve_getaddrinfo( + sd_resolve *resolve, + sd_resolve_query **ret_query, + const char *node, const char *service, + const struct addrinfo *hints, + sd_resolve_getaddrinfo_handler_t callback, + void *userdata) { + + return resolve_getaddrinfo_with_destroy_callback(resolve, ret_query, node, service, hints, callback, NULL, userdata); +} + +static int getaddrinfo_done(sd_resolve_query* q) { + assert(q); + assert(q->done); + assert(q->getaddrinfo_handler); + + errno = q->_errno; + h_errno = q->_h_errno; + + return q->getaddrinfo_handler(q, q->ret, q->addrinfo, q->userdata); +} + +int resolve_getnameinfo_with_destroy_callback( + sd_resolve *resolve, + sd_resolve_query **ret_query, + const struct sockaddr *sa, socklen_t salen, + int flags, + uint64_t get, + sd_resolve_getnameinfo_handler_t callback, + sd_resolve_destroy_t destroy_callback, + void *userdata) { + + _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL; + NameInfoRequest req = {}; + struct iovec iov[2]; + struct msghdr mh; + int r; + + assert_return(resolve, -EINVAL); + assert_return(sa, -EINVAL); + assert_return(salen >= sizeof(struct sockaddr), -EINVAL); + assert_return(salen <= sizeof(union sockaddr_union), -EINVAL); + assert_return((get & ~SD_RESOLVE_GET_BOTH) == 0, -EINVAL); + assert_return(callback, -EINVAL); + assert_return(!resolve_pid_changed(resolve), -ECHILD); + + r = alloc_query(resolve, !ret_query, &q); + if (r < 0) + return r; + + q->type = REQUEST_NAMEINFO; + q->getnameinfo_handler = callback; + q->userdata = userdata; + + req = (NameInfoRequest) { + .header.id = q->id, + .header.type = REQUEST_NAMEINFO, + .header.length = sizeof(NameInfoRequest) + salen, + + .flags = flags, + .sockaddr_len = salen, + .gethost = !!(get & SD_RESOLVE_GET_HOST), + .getserv = !!(get & SD_RESOLVE_GET_SERVICE), + }; + + msan_unpoison(&req, sizeof(req)); + + iov[0] = IOVEC_MAKE(&req, sizeof(NameInfoRequest)); + iov[1] = IOVEC_MAKE((void*) sa, salen); + + mh = (struct msghdr) { + .msg_iov = iov, + .msg_iovlen = ELEMENTSOF(iov) + }; + + if (sendmsg(resolve->fds[REQUEST_SEND_FD], &mh, MSG_NOSIGNAL) < 0) + return -errno; + + resolve->n_outstanding++; + q->destroy_callback = destroy_callback; + + if (ret_query) + *ret_query = q; + + TAKE_PTR(q); + + return 0; +} + +_public_ int sd_resolve_getnameinfo( + sd_resolve *resolve, + sd_resolve_query **ret_query, + const struct sockaddr *sa, socklen_t salen, + int flags, + uint64_t get, + sd_resolve_getnameinfo_handler_t callback, + void *userdata) { + + return resolve_getnameinfo_with_destroy_callback(resolve, ret_query, sa, salen, flags, get, callback, NULL, userdata); +} + +static int getnameinfo_done(sd_resolve_query *q) { + + assert(q); + assert(q->done); + assert(q->getnameinfo_handler); + + errno = q->_errno; + h_errno = q->_h_errno; + + return q->getnameinfo_handler(q, q->ret, q->host, q->serv, q->userdata); +} + +static void resolve_freeaddrinfo(struct addrinfo *ai) { + while (ai) { + struct addrinfo *next = ai->ai_next; + + free(ai->ai_addr); + free(ai->ai_canonname); + free(ai); + ai = next; + } +} + +static void resolve_query_disconnect(sd_resolve_query *q) { + sd_resolve *resolve; + unsigned i; + + assert(q); + + if (!q->resolve) + return; + + resolve = q->resolve; + assert(resolve->n_queries > 0); + + if (q->done) { + assert(resolve->n_done > 0); + resolve->n_done--; + } + + i = q->id % QUERIES_MAX; + assert(resolve->query_array[i] == q); + resolve->query_array[i] = NULL; + LIST_REMOVE(queries, resolve->queries, q); + resolve->n_queries--; + + q->resolve = NULL; + if (!q->floating) + sd_resolve_unref(resolve); +} + +static sd_resolve_query *resolve_query_free(sd_resolve_query *q) { + assert(q); + + resolve_query_disconnect(q); + + if (q->destroy_callback) + q->destroy_callback(q->userdata); + + resolve_freeaddrinfo(q->addrinfo); + free(q->host); + free(q->serv); + + return mfree(q); +} + +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_resolve_query, sd_resolve_query, resolve_query_free); + +_public_ int sd_resolve_query_is_done(sd_resolve_query *q) { + assert_return(q, -EINVAL); + assert_return(!resolve_pid_changed(q->resolve), -ECHILD); + + return q->done; +} + +_public_ void* sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata) { + void *ret; + + assert_return(q, NULL); + assert_return(!resolve_pid_changed(q->resolve), NULL); + + ret = q->userdata; + q->userdata = userdata; + + return ret; +} + +_public_ void* sd_resolve_query_get_userdata(sd_resolve_query *q) { + assert_return(q, NULL); + assert_return(!resolve_pid_changed(q->resolve), NULL); + + return q->userdata; +} + +_public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) { + assert_return(q, NULL); + assert_return(!resolve_pid_changed(q->resolve), NULL); + + return q->resolve; +} + +_public_ int sd_resolve_query_get_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t *destroy_callback) { + assert_return(q, -EINVAL); + + if (destroy_callback) + *destroy_callback = q->destroy_callback; + + return !!q->destroy_callback; +} + +_public_ int sd_resolve_query_set_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t destroy_callback) { + assert_return(q, -EINVAL); + + q->destroy_callback = destroy_callback; + return 0; +} + +_public_ int sd_resolve_query_get_floating(sd_resolve_query *q) { + assert_return(q, -EINVAL); + + return q->floating; +} + +_public_ int sd_resolve_query_set_floating(sd_resolve_query *q, int b) { + assert_return(q, -EINVAL); + + if (q->floating == !!b) + return 0; + + if (!q->resolve) /* Already disconnected */ + return -ESTALE; + + q->floating = b; + + if (b) { + sd_resolve_query_ref(q); + sd_resolve_unref(q->resolve); + } else { + sd_resolve_ref(q->resolve); + sd_resolve_query_unref(q); + } + + return 1; +} + +static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + sd_resolve *resolve = userdata; + int r; + + assert(resolve); + + r = sd_resolve_process(resolve); + if (r < 0) + return r; + + return 1; +} + +_public_ int sd_resolve_attach_event(sd_resolve *resolve, sd_event *event, int64_t priority) { + int r; + + assert_return(resolve, -EINVAL); + assert_return(!resolve->event, -EBUSY); + + assert(!resolve->event_source); + + if (event) + resolve->event = sd_event_ref(event); + else { + r = sd_event_default(&resolve->event); + if (r < 0) + return r; + } + + r = sd_event_add_io(resolve->event, &resolve->event_source, resolve->fds[RESPONSE_RECV_FD], POLLIN, io_callback, resolve); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(resolve->event_source, priority); + if (r < 0) + goto fail; + + return 0; + +fail: + sd_resolve_detach_event(resolve); + return r; +} + +_public_ int sd_resolve_detach_event(sd_resolve *resolve) { + assert_return(resolve, -EINVAL); + + if (!resolve->event) + return 0; + + if (resolve->event_source) { + sd_event_source_set_enabled(resolve->event_source, SD_EVENT_OFF); + resolve->event_source = sd_event_source_unref(resolve->event_source); + } + + resolve->event = sd_event_unref(resolve->event); + return 1; +} + +_public_ sd_event *sd_resolve_get_event(sd_resolve *resolve) { + assert_return(resolve, NULL); + + return resolve->event; +} diff --git a/src/libsystemd/sd-resolve/test-resolve.c b/src/libsystemd/sd-resolve/test-resolve.c new file mode 100644 index 00000000..38a78ee8 --- /dev/null +++ b/src/libsystemd/sd-resolve/test-resolve.c @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-resolve.h" + +#include "alloc-util.h" +#include "macro.h" +#include "socket-util.h" +#include "string-util.h" +#include "time-util.h" + +#define TEST_TIMEOUT_USEC (20*USEC_PER_SEC) + +static int getaddrinfo_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) { + const struct addrinfo *i; + + assert_se(q); + + if (ret != 0) { + log_error("getaddrinfo error: %s %i", gai_strerror(ret), ret); + return 0; + } + + for (i = ai; i; i = i->ai_next) { + _cleanup_free_ char *addr = NULL; + + assert_se(sockaddr_pretty(i->ai_addr, i->ai_addrlen, false, true, &addr) == 0); + puts(addr); + } + + printf("canonical name: %s\n", strna(ai->ai_canonname)); + + return 0; +} + +static int getnameinfo_handler(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata) { + assert_se(q); + + if (ret != 0) { + log_error("getnameinfo error: %s %i", gai_strerror(ret), ret); + return 0; + } + + printf("Host: %s — Serv: %s\n", strna(host), strna(serv)); + return 0; +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q1 = NULL, *q2 = NULL; + _cleanup_(sd_resolve_unrefp) sd_resolve *resolve = NULL; + int r = 0; + + struct addrinfo hints = { + .ai_family = PF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_CANONNAME + }; + + struct sockaddr_in sa = { + .sin_family = AF_INET, + .sin_port = htons(80) + }; + + assert_se(sd_resolve_default(&resolve) >= 0); + + /* Test a floating resolver query */ + r = sd_resolve_getaddrinfo(resolve, NULL, "redhat.com", "http", NULL, getaddrinfo_handler, NULL); + if (r < 0) + log_error_errno(r, "sd_resolve_getaddrinfo(): %m"); + + /* Make a name -> address query */ + r = sd_resolve_getaddrinfo(resolve, &q1, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints, getaddrinfo_handler, NULL); + if (r < 0) + log_error_errno(r, "sd_resolve_getaddrinfo(): %m"); + + /* Make an address -> name query */ + sa.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71"); + r = sd_resolve_getnameinfo(resolve, &q2, (struct sockaddr*) &sa, sizeof(sa), 0, SD_RESOLVE_GET_BOTH, getnameinfo_handler, NULL); + if (r < 0) + log_error_errno(r, "sd_resolve_getnameinfo(): %m"); + + /* Wait until all queries are completed */ + for (;;) { + r = sd_resolve_wait(resolve, TEST_TIMEOUT_USEC); + if (r == 0) + break; + if (r == -ETIMEDOUT) { + /* Let's catch timeouts here, so that we can run safely in a CI that has no reliable DNS. Note + * that we invoke exit() directly here, as the stuck NSS call will not allow us to exit + * cleanly. */ + + log_notice_errno(r, "sd_resolve_wait() timed out, but that's OK"); + exit(EXIT_SUCCESS); + } + if (r < 0) { + log_error_errno(r, "sd_resolve_wait(): %m"); + assert_not_reached("sd_resolve_wait() failed"); + } + } + + return 0; +} diff --git a/src/libsystemd/sd-utf8/sd-utf8.c b/src/libsystemd/sd-utf8/sd-utf8.c new file mode 100644 index 00000000..78323cf7 --- /dev/null +++ b/src/libsystemd/sd-utf8/sd-utf8.c @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-utf8.h" + +#include "utf8.h" +#include "util.h" + +_public_ const char *sd_utf8_is_valid(const char *s) { + assert_return(s, NULL); + + return utf8_is_valid(s); +} + +_public_ const char *sd_ascii_is_valid(const char *s) { + assert_return(s, NULL); + + return ascii_is_valid(s); +} diff --git a/src/libudev/libudev-device-internal.h b/src/libudev/libudev-device-internal.h new file mode 100644 index 00000000..cd6c2a5b --- /dev/null +++ b/src/libudev/libudev-device-internal.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "libudev.h" +#include "sd-device.h" + +struct udev_device; + +struct udev_device *udev_device_new(struct udev *udev, sd_device *device); +sd_device *udev_device_get_sd_device(struct udev_device *udev_device); diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c new file mode 100644 index 00000000..b9933099 --- /dev/null +++ b/src/libudev/libudev-device.c @@ -0,0 +1,873 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libudev.h" +#include "sd-device.h" + +#include "alloc-util.h" +#include "device-private.h" +#include "device-util.h" +#include "libudev-device-internal.h" +#include "libudev-list-internal.h" +#include "parse-util.h" +#include "time-util.h" + +/** + * SECTION:libudev-device + * @short_description: kernel sys devices + * + * Representation of kernel sys devices. Devices are uniquely identified + * by their syspath, every device has exactly one path in the kernel sys + * filesystem. Devices usually belong to a kernel subsystem, and have + * a unique name inside that subsystem. + */ + +/** + * udev_device: + * + * Opaque object representing one kernel sys device. + */ +struct udev_device { + struct udev *udev; + + /* real device object */ + sd_device *device; + + /* legacy */ + unsigned n_ref; + + struct udev_device *parent; + bool parent_set; + + struct udev_list *properties; + uint64_t properties_generation; + struct udev_list *tags; + uint64_t tags_generation; + struct udev_list *devlinks; + uint64_t devlinks_generation; + bool properties_read:1; + bool tags_read:1; + bool devlinks_read:1; + struct udev_list *sysattrs; + bool sysattrs_read; +}; + +/** + * udev_device_get_seqnum: + * @udev_device: udev device + * + * This is only valid if the device was received through a monitor. Devices read from + * sys do not have a sequence number. + * + * Returns: the kernel event sequence number, or 0 if there is no sequence number available. + **/ +_public_ unsigned long long udev_device_get_seqnum(struct udev_device *udev_device) { + uint64_t seqnum; + + assert_return_errno(udev_device, 0, EINVAL); + + if (device_get_seqnum(udev_device->device, &seqnum) < 0) + return 0; + + return seqnum; +} + +/** + * udev_device_get_devnum: + * @udev_device: udev device + * + * Get the device major/minor number. + * + * Returns: the dev_t number. + **/ +_public_ dev_t udev_device_get_devnum(struct udev_device *udev_device) { + dev_t devnum; + int r; + + assert_return_errno(udev_device, makedev(0, 0), EINVAL); + + r = sd_device_get_devnum(udev_device->device, &devnum); + if (r == -ENOENT) + return makedev(0, 0); + if (r < 0) + return_with_errno(makedev(0, 0), r); + + return devnum; +} + +/** + * udev_device_get_driver: + * @udev_device: udev device + * + * Get the kernel driver name. + * + * Returns: the driver name string, or #NULL if there is no driver attached. + **/ +_public_ const char *udev_device_get_driver(struct udev_device *udev_device) { + const char *driver; + int r; + + assert_return_errno(udev_device, NULL, EINVAL); + + r = sd_device_get_driver(udev_device->device, &driver); + if (r < 0) + return_with_errno(NULL, r); + + return driver; +} + +/** + * udev_device_get_devtype: + * @udev_device: udev device + * + * Retrieve the devtype string of the udev device. + * + * Returns: the devtype name of the udev device, or #NULL if it cannot be determined + **/ +_public_ const char *udev_device_get_devtype(struct udev_device *udev_device) { + const char *devtype; + int r; + + assert_return_errno(udev_device, NULL, EINVAL); + + r = sd_device_get_devtype(udev_device->device, &devtype); + if (r == -ENOENT) + return NULL; + if (r < 0) + return_with_errno(NULL, r); + + return devtype; +} + +/** + * udev_device_get_subsystem: + * @udev_device: udev device + * + * Retrieve the subsystem string of the udev device. The string does not + * contain any "/". + * + * Returns: the subsystem name of the udev device, or #NULL if it cannot be determined + **/ +_public_ const char *udev_device_get_subsystem(struct udev_device *udev_device) { + const char *subsystem; + int r; + + assert_return_errno(udev_device, NULL, EINVAL); + + r = sd_device_get_subsystem(udev_device->device, &subsystem); + if (r < 0) + return_with_errno(NULL, r); + + return subsystem; +} + +/** + * udev_device_get_property_value: + * @udev_device: udev device + * @key: property name + * + * Get the value of a given property. + * + * Returns: the property string, or #NULL if there is no such property. + **/ +_public_ const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key) { + const char *value; + int r; + + assert_return_errno(udev_device && key, NULL, EINVAL); + + r = sd_device_get_property_value(udev_device->device, key, &value); + if (r < 0) + return_with_errno(NULL, r); + + return value; +} + +struct udev_device *udev_device_new(struct udev *udev, sd_device *device) { + _cleanup_(udev_list_freep) struct udev_list *properties = NULL, *tags = NULL, *sysattrs = NULL, *devlinks = NULL; + struct udev_device *udev_device; + + assert(device); + + properties = udev_list_new(true); + if (!properties) + return_with_errno(NULL, ENOMEM); + tags = udev_list_new(true); + if (!tags) + return_with_errno(NULL, ENOMEM); + sysattrs = udev_list_new(true); + if (!sysattrs) + return_with_errno(NULL, ENOMEM); + devlinks = udev_list_new(true); + if (!devlinks) + return_with_errno(NULL, ENOMEM); + + udev_device = new(struct udev_device, 1); + if (!udev_device) + return_with_errno(NULL, ENOMEM); + + *udev_device = (struct udev_device) { + .n_ref = 1, + .udev = udev, + .device = sd_device_ref(device), + .properties = TAKE_PTR(properties), + .tags = TAKE_PTR(tags), + .sysattrs = TAKE_PTR(sysattrs), + .devlinks = TAKE_PTR(devlinks), + }; + + return udev_device; +} + +/** + * udev_device_new_from_syspath: + * @udev: udev library context + * @syspath: sys device path including sys directory + * + * Create new udev device, and fill in information from the sys + * device and the udev database entry. The syspath is the absolute + * path to the device, including the sys mount point. + * + * The initial refcount is 1, and needs to be decremented to + * release the resources of the udev device. + * + * Returns: a new udev device, or #NULL, if it does not exist + **/ +_public_ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + int r; + + r = sd_device_new_from_syspath(&device, syspath); + if (r < 0) + return_with_errno(NULL, r); + + return udev_device_new(udev, device); +} + +/** + * udev_device_new_from_devnum: + * @udev: udev library context + * @type: char or block device + * @devnum: device major/minor number + * + * Create new udev device, and fill in information from the sys + * device and the udev database entry. The device is looked-up + * by its major/minor number and type. Character and block device + * numbers are not unique across the two types. + * + * The initial refcount is 1, and needs to be decremented to + * release the resources of the udev device. + * + * Returns: a new udev device, or #NULL, if it does not exist + **/ +_public_ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + int r; + + r = sd_device_new_from_devnum(&device, type, devnum); + if (r < 0) + return_with_errno(NULL, r); + + return udev_device_new(udev, device); +} + +/** + * udev_device_new_from_device_id: + * @udev: udev library context + * @id: text string identifying a kernel device + * + * Create new udev device, and fill in information from the sys + * device and the udev database entry. The device is looked-up + * by a special string: + * b8:2 - block device major:minor + * c128:1 - char device major:minor + * n3 - network device ifindex + * +sound:card29 - kernel driver core subsystem:device name + * + * The initial refcount is 1, and needs to be decremented to + * release the resources of the udev device. + * + * Returns: a new udev device, or #NULL, if it does not exist + **/ +_public_ struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + int r; + + r = sd_device_new_from_device_id(&device, id); + if (r < 0) + return_with_errno(NULL, r); + + return udev_device_new(udev, device); +} + +/** + * udev_device_new_from_subsystem_sysname: + * @udev: udev library context + * @subsystem: the subsystem of the device + * @sysname: the name of the device + * + * Create new udev device, and fill in information from the sys device + * and the udev database entry. The device is looked up by the subsystem + * and name string of the device, like "mem" / "zero", or "block" / "sda". + * + * The initial refcount is 1, and needs to be decremented to + * release the resources of the udev device. + * + * Returns: a new udev device, or #NULL, if it does not exist + **/ +_public_ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + int r; + + r = sd_device_new_from_subsystem_sysname(&device, subsystem, sysname); + if (r < 0) + return_with_errno(NULL, r); + + return udev_device_new(udev, device); +} + +/** + * udev_device_new_from_environment + * @udev: udev library context + * + * Create new udev device, and fill in information from the + * current process environment. This only works reliable if + * the process is called from a udev rule. It is usually used + * for tools executed from IMPORT= rules. + * + * The initial refcount is 1, and needs to be decremented to + * release the resources of the udev device. + * + * Returns: a new udev device, or #NULL, if it does not exist + **/ +_public_ struct udev_device *udev_device_new_from_environment(struct udev *udev) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + int r; + + r = device_new_from_strv(&device, environ); + if (r < 0) + return_with_errno(NULL, r); + + return udev_device_new(udev, device); +} + +static struct udev_device *device_new_from_parent(struct udev_device *child) { + sd_device *parent; + int r; + + assert_return_errno(child, NULL, EINVAL); + + r = sd_device_get_parent(child->device, &parent); + if (r < 0) + return_with_errno(NULL, r); + + return udev_device_new(child->udev, parent); +} + +/** + * udev_device_get_parent: + * @udev_device: the device to start searching from + * + * Find the next parent device, and fill in information from the sys + * device and the udev database entry. + * + * Returned device is not referenced. It is attached to the child + * device, and will be cleaned up when the child device is cleaned up. + * + * It is not necessarily just the upper level directory, empty or not + * recognized sys directories are ignored. + * + * It can be called as many times as needed, without caring about + * references. + * + * Returns: a new udev device, or #NULL, if it no parent exist. + **/ +_public_ struct udev_device *udev_device_get_parent(struct udev_device *udev_device) { + assert_return_errno(udev_device, NULL, EINVAL); + + if (!udev_device->parent_set) { + udev_device->parent_set = true; + udev_device->parent = device_new_from_parent(udev_device); + } + + /* TODO: errno will differ here in case parent == NULL */ + return udev_device->parent; +} + +/** + * udev_device_get_parent_with_subsystem_devtype: + * @udev_device: udev device to start searching from + * @subsystem: the subsystem of the device + * @devtype: the type (DEVTYPE) of the device + * + * Find the next parent device, with a matching subsystem and devtype + * value, and fill in information from the sys device and the udev + * database entry. + * + * If devtype is #NULL, only subsystem is checked, and any devtype will + * match. + * + * Returned device is not referenced. It is attached to the child + * device, and will be cleaned up when the child device is cleaned up. + * + * It can be called as many times as needed, without caring about + * references. + * + * Returns: a new udev device, or #NULL if no matching parent exists. + **/ +_public_ struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, const char *subsystem, const char *devtype) { + sd_device *parent; + int r; + + assert_return_errno(udev_device, NULL, EINVAL); + + /* this relies on the fact that finding the subdevice of a parent or the + parent of a subdevice commute */ + + /* first find the correct sd_device */ + r = sd_device_get_parent_with_subsystem_devtype(udev_device->device, subsystem, devtype, &parent); + if (r < 0) + return_with_errno(NULL, r); + + /* then walk the chain of udev_device parents until the corresponding + one is found */ + while ((udev_device = udev_device_get_parent(udev_device))) + if (udev_device->device == parent) + return udev_device; + + return_with_errno(NULL, ENOENT); +} + +/** + * udev_device_get_udev: + * @udev_device: udev device + * + * Retrieve the udev library context the device was created with. + * + * Returns: the udev library context + **/ +_public_ struct udev *udev_device_get_udev(struct udev_device *udev_device) { + assert_return_errno(udev_device, NULL, EINVAL); + + return udev_device->udev; +} + +static struct udev_device *udev_device_free(struct udev_device *udev_device) { + assert(udev_device); + + sd_device_unref(udev_device->device); + udev_device_unref(udev_device->parent); + + udev_list_free(udev_device->properties); + udev_list_free(udev_device->sysattrs); + udev_list_free(udev_device->tags); + udev_list_free(udev_device->devlinks); + + return mfree(udev_device); +} + +/** + * udev_device_ref: + * @udev_device: udev device + * + * Take a reference of a udev device. + * + * Returns: the passed udev device + **/ + +/** + * udev_device_unref: + * @udev_device: udev device + * + * Drop a reference of a udev device. If the refcount reaches zero, + * the resources of the device will be released. + * + * Returns: #NULL + **/ +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_device, udev_device, udev_device_free); + +/** + * udev_device_get_devpath: + * @udev_device: udev device + * + * Retrieve the kernel devpath value of the udev device. The path + * does not contain the sys mount point, and starts with a '/'. + * + * Returns: the devpath of the udev device + **/ +_public_ const char *udev_device_get_devpath(struct udev_device *udev_device) { + const char *devpath; + int r; + + assert_return_errno(udev_device, NULL, EINVAL); + + r = sd_device_get_devpath(udev_device->device, &devpath); + if (r < 0) + return_with_errno(NULL, r); + + return devpath; +} + +/** + * udev_device_get_syspath: + * @udev_device: udev device + * + * Retrieve the sys path of the udev device. The path is an + * absolute path and starts with the sys mount point. + * + * Returns: the sys path of the udev device + **/ +_public_ const char *udev_device_get_syspath(struct udev_device *udev_device) { + const char *syspath; + int r; + + assert_return_errno(udev_device, NULL, EINVAL); + + r = sd_device_get_syspath(udev_device->device, &syspath); + if (r < 0) + return_with_errno(NULL, r); + + return syspath; +} + +/** + * udev_device_get_sysname: + * @udev_device: udev device + * + * Get the kernel device name in /sys. + * + * Returns: the name string of the device + **/ +_public_ const char *udev_device_get_sysname(struct udev_device *udev_device) { + const char *sysname; + int r; + + assert_return_errno(udev_device, NULL, EINVAL); + + r = sd_device_get_sysname(udev_device->device, &sysname); + if (r < 0) + return_with_errno(NULL, r); + + return sysname; +} + +/** + * udev_device_get_sysnum: + * @udev_device: udev device + * + * Get the instance number of the device. + * + * Returns: the trailing number string of the device name + **/ +_public_ const char *udev_device_get_sysnum(struct udev_device *udev_device) { + const char *sysnum; + int r; + + assert_return_errno(udev_device, NULL, EINVAL); + + r = sd_device_get_sysnum(udev_device->device, &sysnum); + if (r == -ENOENT) + return NULL; + if (r < 0) + return_with_errno(NULL, r); + + return sysnum; +} + +/** + * udev_device_get_devnode: + * @udev_device: udev device + * + * Retrieve the device node file name belonging to the udev device. + * The path is an absolute path, and starts with the device directory. + * + * Returns: the device node file name of the udev device, or #NULL if no device node exists + **/ +_public_ const char *udev_device_get_devnode(struct udev_device *udev_device) { + const char *devnode; + int r; + + assert_return_errno(udev_device, NULL, EINVAL); + + r = sd_device_get_devname(udev_device->device, &devnode); + if (r < 0) + return_with_errno(NULL, r); + + return devnode; +} + +/** + * udev_device_get_devlinks_list_entry: + * @udev_device: udev device + * + * Retrieve the list of device links pointing to the device file of + * the udev device. The next list entry can be retrieved with + * udev_list_entry_get_next(), which returns #NULL if no more entries exist. + * The devlink path can be retrieved from the list entry by + * udev_list_entry_get_name(). The path is an absolute path, and starts with + * the device directory. + * + * Returns: the first entry of the device node link list + **/ +_public_ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device) { + assert_return_errno(udev_device, NULL, EINVAL); + + if (device_get_devlinks_generation(udev_device->device) != udev_device->devlinks_generation || + !udev_device->devlinks_read) { + const char *devlink; + + udev_list_cleanup(udev_device->devlinks); + + FOREACH_DEVICE_DEVLINK(udev_device->device, devlink) + if (!udev_list_entry_add(udev_device->devlinks, devlink, NULL)) + return_with_errno(NULL, ENOMEM); + + udev_device->devlinks_read = true; + udev_device->devlinks_generation = device_get_devlinks_generation(udev_device->device); + } + + return udev_list_get_entry(udev_device->devlinks); +} + +/** + * udev_device_get_event_properties_entry: + * @udev_device: udev device + * + * Retrieve the list of key/value device properties of the udev + * device. The next list entry can be retrieved with udev_list_entry_get_next(), + * which returns #NULL if no more entries exist. The property name + * can be retrieved from the list entry by udev_list_entry_get_name(), + * the property value by udev_list_entry_get_value(). + * + * Returns: the first entry of the property list + **/ +_public_ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device) { + assert_return_errno(udev_device, NULL, EINVAL); + + if (device_get_properties_generation(udev_device->device) != udev_device->properties_generation || + !udev_device->properties_read) { + const char *key, *value; + + udev_list_cleanup(udev_device->properties); + + FOREACH_DEVICE_PROPERTY(udev_device->device, key, value) + if (!udev_list_entry_add(udev_device->properties, key, value)) + return_with_errno(NULL, ENOMEM); + + udev_device->properties_read = true; + udev_device->properties_generation = device_get_properties_generation(udev_device->device); + } + + return udev_list_get_entry(udev_device->properties); +} + +/** + * udev_device_get_action: + * @udev_device: udev device + * + * This is only valid if the device was received through a monitor. Devices read from + * sys do not have an action string. Usual actions are: add, remove, change, move, + * online, offline. + * + * Returns: the kernel action value, or #NULL if there is no action value available. + **/ +_public_ const char *udev_device_get_action(struct udev_device *udev_device) { + DeviceAction action; + + assert_return_errno(udev_device, NULL, EINVAL); + + if (device_get_action(udev_device->device, &action) < 0) + return NULL; + + return device_action_to_string(action); +} + +/** + * udev_device_get_usec_since_initialized: + * @udev_device: udev device + * + * Return the number of microseconds passed since udev set up the + * device for the first time. + * + * This is only implemented for devices with need to store properties + * in the udev database. All other devices return 0 here. + * + * Returns: the number of microseconds since the device was first seen. + **/ +_public_ unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device) { + usec_t ts; + int r; + + assert_return(udev_device, -EINVAL); + + r = sd_device_get_usec_since_initialized(udev_device->device, &ts); + if (r < 0) + return_with_errno(0, r); + + return ts; +} + +/** + * udev_device_get_sysattr_value: + * @udev_device: udev device + * @sysattr: attribute name + * + * The retrieved value is cached in the device. Repeated calls will return the same + * value and not open the attribute again. + * + * Returns: the content of a sys attribute file, or #NULL if there is no sys attribute value. + **/ +_public_ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr) { + const char *value; + int r; + + assert_return_errno(udev_device, NULL, EINVAL); + + r = sd_device_get_sysattr_value(udev_device->device, sysattr, &value); + if (r < 0) + return_with_errno(NULL, r); + + return value; +} + +/** + * udev_device_set_sysattr_value: + * @udev_device: udev device + * @sysattr: attribute name + * @value: new value to be set + * + * Update the contents of the sys attribute and the cached value of the device. + * + * Returns: Negative error code on failure or 0 on success. + **/ +_public_ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value) { + int r; + + assert_return(udev_device, -EINVAL); + + r = sd_device_set_sysattr_value(udev_device->device, sysattr, value); + if (r < 0) + return r; + + return 0; +} + +/** + * udev_device_get_sysattr_list_entry: + * @udev_device: udev device + * + * Retrieve the list of available sysattrs, with value being empty; + * This just return all available sysfs attributes for a particular + * device without reading their values. + * + * Returns: the first entry of the property list + **/ +_public_ struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device) { + assert_return_errno(udev_device, NULL, EINVAL); + + if (!udev_device->sysattrs_read) { + const char *sysattr; + + udev_list_cleanup(udev_device->sysattrs); + + FOREACH_DEVICE_SYSATTR(udev_device->device, sysattr) + if (!udev_list_entry_add(udev_device->sysattrs, sysattr, NULL)) + return_with_errno(NULL, ENOMEM); + + udev_device->sysattrs_read = true; + } + + return udev_list_get_entry(udev_device->sysattrs); +} + +/** + * udev_device_get_is_initialized: + * @udev_device: udev device + * + * Check if udev has already handled the device and has set up + * device node permissions and context, or has renamed a network + * device. + * + * This is only implemented for devices with a device node + * or network interfaces. All other devices return 1 here. + * + * Returns: 1 if the device is set up. 0 otherwise. + **/ +_public_ int udev_device_get_is_initialized(struct udev_device *udev_device) { + int r; + + assert_return(udev_device, -EINVAL); + + r = sd_device_get_is_initialized(udev_device->device); + if (r < 0) + return_with_errno(0, r); + + return r; +} + +/** + * udev_device_get_tags_list_entry: + * @udev_device: udev device + * + * Retrieve the list of tags attached to the udev device. The next + * list entry can be retrieved with udev_list_entry_get_next(), + * which returns #NULL if no more entries exist. The tag string + * can be retrieved from the list entry by udev_list_entry_get_name(). + * + * Returns: the first entry of the tag list + **/ +_public_ struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device) { + assert_return_errno(udev_device, NULL, EINVAL); + + if (device_get_tags_generation(udev_device->device) != udev_device->tags_generation || + !udev_device->tags_read) { + const char *tag; + + udev_list_cleanup(udev_device->tags); + + FOREACH_DEVICE_TAG(udev_device->device, tag) + if (!udev_list_entry_add(udev_device->tags, tag, NULL)) + return_with_errno(NULL, ENOMEM); + + udev_device->tags_read = true; + udev_device->tags_generation = device_get_tags_generation(udev_device->device); + } + + return udev_list_get_entry(udev_device->tags); +} + +/** + * udev_device_has_tag: + * @udev_device: udev device + * @tag: tag name + * + * Check if a given device has a certain tag associated. + * + * Returns: 1 if the tag is found. 0 otherwise. + **/ +_public_ int udev_device_has_tag(struct udev_device *udev_device, const char *tag) { + assert_return(udev_device, 0); + + return sd_device_has_tag(udev_device->device, tag) > 0; +} + +sd_device *udev_device_get_sd_device(struct udev_device *udev_device) { + assert(udev_device); + + return udev_device->device; +} diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c new file mode 100644 index 00000000..a8b3f535 --- /dev/null +++ b/src/libudev/libudev-enumerate.c @@ -0,0 +1,458 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libudev.h" +#include "sd-device.h" + +#include "alloc-util.h" +#include "device-enumerator-private.h" +#include "device-util.h" +#include "libudev-device-internal.h" +#include "libudev-list-internal.h" + +/** + * SECTION:libudev-enumerate + * @short_description: lookup and sort sys devices + * + * Lookup devices in the sys filesystem, filter devices by properties, + * and return a sorted list of devices. + */ + +/** + * udev_enumerate: + * + * Opaque object representing one device lookup/sort context. + */ +struct udev_enumerate { + struct udev *udev; + unsigned n_ref; + struct udev_list *devices_list; + bool devices_uptodate:1; + + sd_device_enumerator *enumerator; +}; + +/** + * udev_enumerate_new: + * @udev: udev library context + * + * Create an enumeration context to scan /sys. + * + * Returns: an enumeration context. + **/ +_public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + _cleanup_(udev_list_freep) struct udev_list *list = NULL; + struct udev_enumerate *udev_enumerate; + int r; + + r = sd_device_enumerator_new(&e); + if (r < 0) + return_with_errno(NULL, r); + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return_with_errno(NULL, r); + + list = udev_list_new(false); + if (!list) + return_with_errno(NULL, ENOMEM); + + udev_enumerate = new(struct udev_enumerate, 1); + if (!udev_enumerate) + return_with_errno(NULL, ENOMEM); + + *udev_enumerate = (struct udev_enumerate) { + .udev = udev, + .n_ref = 1, + .enumerator = TAKE_PTR(e), + .devices_list = TAKE_PTR(list), + }; + + return udev_enumerate; +} + +static struct udev_enumerate *udev_enumerate_free(struct udev_enumerate *udev_enumerate) { + assert(udev_enumerate); + + udev_list_free(udev_enumerate->devices_list); + sd_device_enumerator_unref(udev_enumerate->enumerator); + return mfree(udev_enumerate); +} + +/** + * udev_enumerate_ref: + * @udev_enumerate: context + * + * Take a reference of a enumeration context. + * + * Returns: the passed enumeration context + **/ + +/** + * udev_enumerate_unref: + * @udev_enumerate: context + * + * Drop a reference of an enumeration context. If the refcount reaches zero, + * all resources of the enumeration context will be released. + * + * Returns: #NULL + **/ +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_enumerate, udev_enumerate, udev_enumerate_free); + +/** + * udev_enumerate_get_udev: + * @udev_enumerate: context + * + * Get the udev library context. + * + * Returns: a pointer to the context. + */ +_public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) { + assert_return_errno(udev_enumerate, NULL, EINVAL); + + return udev_enumerate->udev; +} + +/** + * udev_enumerate_get_list_entry: + * @udev_enumerate: context + * + * Get the first entry of the sorted list of device paths. + * + * Returns: a udev_list_entry. + */ +_public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) { + struct udev_list_entry *e; + + assert_return_errno(udev_enumerate, NULL, EINVAL); + + if (!udev_enumerate->devices_uptodate) { + sd_device *device; + + udev_list_cleanup(udev_enumerate->devices_list); + + FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate->enumerator, device) { + const char *syspath; + int r; + + r = sd_device_get_syspath(device, &syspath); + if (r < 0) + return_with_errno(NULL, r); + + if (!udev_list_entry_add(udev_enumerate->devices_list, syspath, NULL)) + return_with_errno(NULL, ENOMEM); + } + + udev_enumerate->devices_uptodate = true; + } + + e = udev_list_get_entry(udev_enumerate->devices_list); + if (!e) + return_with_errno(NULL, ENODATA); + + return e; +} + +/** + * udev_enumerate_add_match_subsystem: + * @udev_enumerate: context + * @subsystem: filter for a subsystem of the device to include in the list + * + * Match only devices belonging to a certain kernel subsystem. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { + int r; + + assert_return(udev_enumerate, -EINVAL); + + if (!subsystem) + return 0; + + r = sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, true); + if (r < 0) + return r; + + udev_enumerate->devices_uptodate = false; + return 0; +} + +/** + * udev_enumerate_add_nomatch_subsystem: + * @udev_enumerate: context + * @subsystem: filter for a subsystem of the device to exclude from the list + * + * Match only devices not belonging to a certain kernel subsystem. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { + int r; + + assert_return(udev_enumerate, -EINVAL); + + if (!subsystem) + return 0; + + r = sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, false); + if (r < 0) + return r; + + udev_enumerate->devices_uptodate = false; + return 0; +} + +/** + * udev_enumerate_add_match_sysattr: + * @udev_enumerate: context + * @sysattr: filter for a sys attribute at the device to include in the list + * @value: optional value of the sys attribute + * + * Match only devices with a certain /sys device attribute. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { + int r; + + assert_return(udev_enumerate, -EINVAL); + + if (!sysattr) + return 0; + + r = sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, true); + if (r < 0) + return r; + + udev_enumerate->devices_uptodate = false; + return 0; +} + +/** + * udev_enumerate_add_nomatch_sysattr: + * @udev_enumerate: context + * @sysattr: filter for a sys attribute at the device to exclude from the list + * @value: optional value of the sys attribute + * + * Match only devices not having a certain /sys device attribute. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { + int r; + + assert_return(udev_enumerate, -EINVAL); + + if (!sysattr) + return 0; + + r = sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, false); + if (r < 0) + return r; + + udev_enumerate->devices_uptodate = false; + return 0; +} + +/** + * udev_enumerate_add_match_property: + * @udev_enumerate: context + * @property: filter for a property of the device to include in the list + * @value: value of the property + * + * Match only devices with a certain property. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) { + int r; + + assert_return(udev_enumerate, -EINVAL); + + if (!property) + return 0; + + r = sd_device_enumerator_add_match_property(udev_enumerate->enumerator, property, value); + if (r < 0) + return r; + + udev_enumerate->devices_uptodate = false; + return 0; +} + +/** + * udev_enumerate_add_match_tag: + * @udev_enumerate: context + * @tag: filter for a tag of the device to include in the list + * + * Match only devices with a certain tag. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) { + int r; + + assert_return(udev_enumerate, -EINVAL); + + if (!tag) + return 0; + + r = sd_device_enumerator_add_match_tag(udev_enumerate->enumerator, tag); + if (r < 0) + return r; + + udev_enumerate->devices_uptodate = false; + return 0; +} + +/** + * udev_enumerate_add_match_parent: + * @udev_enumerate: context + * @parent: parent device where to start searching + * + * Return the devices on the subtree of one given device. The parent + * itself is included in the list. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) { + int r; + + assert_return(udev_enumerate, -EINVAL); + + if (!parent) + return 0; + + r = sd_device_enumerator_add_match_parent(udev_enumerate->enumerator, udev_device_get_sd_device(parent)); + if (r < 0) + return r; + + udev_enumerate->devices_uptodate = false; + return 0; +} + +/** + * udev_enumerate_add_match_is_initialized: + * @udev_enumerate: context + * + * Match only devices which udev has set up already. This makes + * sure, that the device node permissions and context are properly set + * and that network devices are fully renamed. + * + * Usually, devices which are found in the kernel but not already + * handled by udev, have still pending events. Services should subscribe + * to monitor events and wait for these devices to become ready, instead + * of using uninitialized devices. + * + * For now, this will not affect devices which do not have a device node + * and are not network interfaces. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) { + int r; + + assert_return(udev_enumerate, -EINVAL); + + r = device_enumerator_add_match_is_initialized(udev_enumerate->enumerator); + if (r < 0) + return r; + + udev_enumerate->devices_uptodate = false; + return 0; +} + +/** + * udev_enumerate_add_match_sysname: + * @udev_enumerate: context + * @sysname: filter for the name of the device to include in the list + * + * Match only devices with a given /sys device name. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) { + int r; + + assert_return(udev_enumerate, -EINVAL); + + if (!sysname) + return 0; + + r = sd_device_enumerator_add_match_sysname(udev_enumerate->enumerator, sysname); + if (r < 0) + return r; + + udev_enumerate->devices_uptodate = false; + return 0; +} + +/** + * udev_enumerate_add_syspath: + * @udev_enumerate: context + * @syspath: path of a device + * + * Add a device to the list of devices, to retrieve it back sorted in dependency order. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + int r; + + assert_return(udev_enumerate, -EINVAL); + + if (!syspath) + return 0; + + r = sd_device_new_from_syspath(&device, syspath); + if (r < 0) + return r; + + r = device_enumerator_add_device(udev_enumerate->enumerator, device); + if (r < 0) + return r; + + udev_enumerate->devices_uptodate = false; + return 0; +} + +/** + * udev_enumerate_scan_devices: + * @udev_enumerate: udev enumeration context + * + * Scan /sys for all devices which match the given filters. No matches + * will return all currently available devices. + * + * Returns: 0 on success, otherwise a negative error value. + **/ +_public_ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) { + assert_return(udev_enumerate, -EINVAL); + + return device_enumerator_scan_devices(udev_enumerate->enumerator); +} + +/** + * udev_enumerate_scan_subsystems: + * @udev_enumerate: udev enumeration context + * + * Scan /sys for all kernel subsystems, including buses, classes, drivers. + * + * Returns: 0 on success, otherwise a negative error value. + **/ +_public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) { + assert_return(udev_enumerate, -EINVAL); + + return device_enumerator_scan_subsystems(udev_enumerate->enumerator); +} diff --git a/src/libudev/libudev-hwdb.c b/src/libudev/libudev-hwdb.c new file mode 100644 index 00000000..5299e0a1 --- /dev/null +++ b/src/libudev/libudev-hwdb.c @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-hwdb.h" + +#include "alloc-util.h" +#include "hwdb-util.h" +#include "libudev-list-internal.h" + +/** + * SECTION:libudev-hwdb + * @short_description: retrieve properties from the hardware database + * + * Libudev hardware database interface. + */ + +/** + * udev_hwdb: + * + * Opaque object representing the hardware database. + */ +struct udev_hwdb { + unsigned n_ref; + sd_hwdb *hwdb; + struct udev_list *properties_list; +}; + +/** + * udev_hwdb_new: + * @udev: udev library context (unused) + * + * Create a hardware database context to query properties for devices. + * + * Returns: a hwdb context. + **/ +_public_ struct udev_hwdb *udev_hwdb_new(struct udev *udev) { + _cleanup_(udev_list_freep) struct udev_list *list = NULL; + _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb_internal = NULL; + struct udev_hwdb *hwdb; + int r; + + r = sd_hwdb_new(&hwdb_internal); + if (r < 0) + return_with_errno(NULL, r); + + list = udev_list_new(true); + if (!list) + return_with_errno(NULL, ENOMEM); + + hwdb = new(struct udev_hwdb, 1); + if (!hwdb) + return_with_errno(NULL, ENOMEM); + + *hwdb = (struct udev_hwdb) { + .n_ref = 1, + .hwdb = TAKE_PTR(hwdb_internal), + .properties_list = TAKE_PTR(list), + }; + + return hwdb; +} + +static struct udev_hwdb *udev_hwdb_free(struct udev_hwdb *hwdb) { + assert(hwdb); + + sd_hwdb_unref(hwdb->hwdb); + udev_list_free(hwdb->properties_list); + return mfree(hwdb); +} + +/** + * udev_hwdb_ref: + * @hwdb: context + * + * Take a reference of a hwdb context. + * + * Returns: the passed enumeration context + **/ + +/** + * udev_hwdb_unref: + * @hwdb: context + * + * Drop a reference of a hwdb context. If the refcount reaches zero, + * all resources of the hwdb context will be released. + * + * Returns: #NULL + **/ +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_hwdb, udev_hwdb, udev_hwdb_free); + +/** + * udev_hwdb_get_properties_list_entry: + * @hwdb: context + * @modalias: modalias string + * @flags: (unused) + * + * Lookup a matching device in the hardware database. The lookup key is a + * modalias string, whose formats are defined for the Linux kernel modules. + * Examples are: pci:v00008086d00001C2D*, usb:v04F2pB221*. The first entry + * of a list of retrieved properties is returned. + * + * Returns: a udev_list_entry. + */ +_public_ struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned flags) { + const char *key, *value; + struct udev_list_entry *e; + + assert_return_errno(hwdb, NULL, EINVAL); + assert_return_errno(modalias, NULL, EINVAL); + + udev_list_cleanup(hwdb->properties_list); + + SD_HWDB_FOREACH_PROPERTY(hwdb->hwdb, modalias, key, value) + if (!udev_list_entry_add(hwdb->properties_list, key, value)) + return_with_errno(NULL, ENOMEM); + + e = udev_list_get_entry(hwdb->properties_list); + if (!e) + return_with_errno(NULL, ENODATA); + + return e; +} diff --git a/src/libudev/libudev-list-internal.h b/src/libudev/libudev-list-internal.h new file mode 100644 index 00000000..a15b3853 --- /dev/null +++ b/src/libudev/libudev-list-internal.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "libudev.h" + +#include "macro.h" + +struct udev_list; + +struct udev_list *udev_list_new(bool unique); +void udev_list_cleanup(struct udev_list *list); +struct udev_list *udev_list_free(struct udev_list *list); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_list *, udev_list_free); + +struct udev_list_entry *udev_list_get_entry(struct udev_list *list); +struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *name, const char *value); diff --git a/src/libudev/libudev-list.c b/src/libudev/libudev-list.c new file mode 100644 index 00000000..95a9942f --- /dev/null +++ b/src/libudev/libudev-list.c @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "hashmap.h" +#include "libudev-list-internal.h" +#include "list.h" +#include "sort-util.h" + +/** + * SECTION:libudev-list + * @short_description: list operation + * + * Libudev list operations. + */ + +/** + * udev_list_entry: + * + * Opaque object representing one entry in a list. An entry contains + * contains a name, and optionally a value. + */ +struct udev_list_entry { + struct udev_list *list; + char *name; + char *value; + + LIST_FIELDS(struct udev_list_entry, entries); +}; + +struct udev_list { + Hashmap *unique_entries; + LIST_HEAD(struct udev_list_entry, entries); + bool unique:1; + bool uptodate:1; +}; + +static struct udev_list_entry *udev_list_entry_free(struct udev_list_entry *entry) { + if (!entry) + return NULL; + + if (entry->list) { + if (entry->list->unique) + hashmap_remove(entry->list->unique_entries, entry->name); + else + LIST_REMOVE(entries, entry->list->entries, entry); + } + + free(entry->name); + free(entry->value); + + return mfree(entry); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_list_entry *, udev_list_entry_free); + +struct udev_list *udev_list_new(bool unique) { + struct udev_list *list; + + list = new(struct udev_list, 1); + if (!list) + return NULL; + + *list = (struct udev_list) { + .unique = unique, + }; + + return list; +} + +struct udev_list_entry *udev_list_entry_add(struct udev_list *list, const char *_name, const char *_value) { + _cleanup_(udev_list_entry_freep) struct udev_list_entry *entry = NULL; + _cleanup_free_ char *name = NULL, *value = NULL; + int r; + + assert(list); + + name = strdup(_name); + if (!name) + return NULL; + + if (_value) { + value = strdup(_value); + if (!value) + return NULL; + } + + entry = new(struct udev_list_entry, 1); + if (!entry) + return NULL; + + *entry = (struct udev_list_entry) { + .list = list, + .name = TAKE_PTR(name), + .value = TAKE_PTR(value), + }; + + if (list->unique) { + r = hashmap_ensure_allocated(&list->unique_entries, &string_hash_ops); + if (r < 0) + return NULL; + + udev_list_entry_free(hashmap_get(list->unique_entries, entry->name)); + + r = hashmap_put(list->unique_entries, entry->name, entry); + if (r < 0) + return NULL; + + list->uptodate = false; + } else + LIST_APPEND(entries, list->entries, entry); + + return TAKE_PTR(entry); +} + +void udev_list_cleanup(struct udev_list *list) { + struct udev_list_entry *i, *n; + + if (!list) + return; + + if (list->unique) { + hashmap_clear_with_destructor(list->unique_entries, udev_list_entry_free); + list->uptodate = false; + } else + LIST_FOREACH_SAFE(entries, i, n, list->entries) + udev_list_entry_free(i); +} + +struct udev_list *udev_list_free(struct udev_list *list) { + if (!list) + return NULL; + + udev_list_cleanup(list); + hashmap_free(list->unique_entries); + + return mfree(list); +} + +static int udev_list_entry_compare_func(struct udev_list_entry * const *a, struct udev_list_entry * const *b) { + return strcmp((*a)->name, (*b)->name); +} + +struct udev_list_entry *udev_list_get_entry(struct udev_list *list) { + if (!list) + return NULL; + + if (list->unique && !list->uptodate) { + size_t n; + + LIST_HEAD_INIT(list->entries); + + n = hashmap_size(list->unique_entries); + if (n == 0) + ; + else if (n == 1) + LIST_PREPEND(entries, list->entries, hashmap_first(list->unique_entries)); + else { + _cleanup_free_ struct udev_list_entry **buf = NULL; + struct udev_list_entry *entry, **p; + Iterator i; + size_t j; + + buf = new(struct udev_list_entry *, n); + if (!buf) + return NULL; + + p = buf; + HASHMAP_FOREACH(entry, list->unique_entries, i) + *p++ = entry; + + typesafe_qsort(buf, n, udev_list_entry_compare_func); + + for (j = n; j > 0; j--) + LIST_PREPEND(entries, list->entries, buf[j-1]); + } + + list->uptodate = true; + } + + return list->entries; +} + +/** + * udev_list_entry_get_next: + * @list_entry: current entry + * + * Get the next entry from the list. + * + * Returns: udev_list_entry, #NULL if no more entries are available. + */ +_public_ struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry) { + if (!list_entry) + return NULL; + if (list_entry->list->unique && !list_entry->list->uptodate) + return NULL; + return list_entry->entries_next; +} + +/** + * udev_list_entry_get_by_name: + * @list_entry: current entry + * @name: name string to match + * + * Lookup an entry in the list with a certain name. + * + * Returns: udev_list_entry, #NULL if no matching entry is found. + */ +_public_ struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name) { + if (!list_entry) + return NULL; + if (!list_entry->list->unique || !list_entry->list->uptodate) + return NULL; + return hashmap_get(list_entry->list->unique_entries, name); +} + +/** + * udev_list_entry_get_name: + * @list_entry: current entry + * + * Get the name of a list entry. + * + * Returns: the name string of this entry. + */ +_public_ const char *udev_list_entry_get_name(struct udev_list_entry *list_entry) { + if (!list_entry) + return NULL; + return list_entry->name; +} + +/** + * udev_list_entry_get_value: + * @list_entry: current entry + * + * Get the value of list entry. + * + * Returns: the value string of this entry. + */ +_public_ const char *udev_list_entry_get_value(struct udev_list_entry *list_entry) { + if (!list_entry) + return NULL; + return list_entry->value; +} diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c new file mode 100644 index 00000000..5f780e0b --- /dev/null +++ b/src/libudev/libudev-monitor.c @@ -0,0 +1,309 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "libudev.h" + +#include "alloc-util.h" +#include "device-monitor-private.h" +#include "device-private.h" +#include "device-util.h" +#include "libudev-device-internal.h" +#include "string-util.h" + +/** + * SECTION:libudev-monitor + * @short_description: device event source + * + * Connects to a device event source. + */ + +/** + * udev_monitor: + * + * Opaque object handling an event source. + */ +struct udev_monitor { + struct udev *udev; + unsigned n_ref; + sd_device_monitor *monitor; +}; + +static MonitorNetlinkGroup monitor_netlink_group_from_string(const char *name) { + if (!name) + return MONITOR_GROUP_NONE; + if (streq(name, "udev")) + return MONITOR_GROUP_UDEV; + if (streq(name, "kernel")) + return MONITOR_GROUP_KERNEL; + return _MONITOR_NETLINK_GROUP_INVALID; +} + +/** + * udev_monitor_new_from_netlink: + * @udev: udev library context + * @name: name of event source + * + * Create new udev monitor and connect to a specified event + * source. Valid sources identifiers are "udev" and "kernel". + * + * Applications should usually not connect directly to the + * "kernel" events, because the devices might not be usable + * at that time, before udev has configured them, and created + * device nodes. Accessing devices at the same time as udev, + * might result in unpredictable behavior. The "udev" events + * are sent out after udev has finished its event processing, + * all rules have been processed, and needed device nodes are + * created. + * + * The initial refcount is 1, and needs to be decremented to + * release the resources of the udev monitor. + * + * Returns: a new udev monitor, or #NULL, in case of an error + **/ +_public_ struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL; + struct udev_monitor *udev_monitor; + MonitorNetlinkGroup g; + int r; + + g = monitor_netlink_group_from_string(name); + if (g < 0) + return_with_errno(NULL, EINVAL); + + r = device_monitor_new_full(&m, g, -1); + if (r < 0) + return_with_errno(NULL, r); + + udev_monitor = new(struct udev_monitor, 1); + if (!udev_monitor) + return_with_errno(NULL, ENOMEM); + + *udev_monitor = (struct udev_monitor) { + .udev = udev, + .n_ref = 1, + .monitor = TAKE_PTR(m), + }; + + return udev_monitor; +} + +/** + * udev_monitor_filter_update: + * @udev_monitor: monitor + * + * Update the installed socket filter. This is only needed, + * if the filter was removed or changed. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_monitor_filter_update(struct udev_monitor *udev_monitor) { + assert_return(udev_monitor, -EINVAL); + + return sd_device_monitor_filter_update(udev_monitor->monitor); +} + +/** + * udev_monitor_enable_receiving: + * @udev_monitor: the monitor which should receive events + * + * Binds the @udev_monitor socket to the event source. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) { + assert_return(udev_monitor, -EINVAL); + + return device_monitor_enable_receiving(udev_monitor->monitor); +} + +/** + * udev_monitor_set_receive_buffer_size: + * @udev_monitor: the monitor which should receive events + * @size: the size in bytes + * + * Set the size of the kernel socket buffer. This call needs the + * appropriate privileges to succeed. + * + * Returns: 0 on success, otherwise -1 on error. + */ +_public_ int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size) { + assert_return(udev_monitor, -EINVAL); + + return sd_device_monitor_set_receive_buffer_size(udev_monitor->monitor, (size_t) size); +} + +static struct udev_monitor *udev_monitor_free(struct udev_monitor *udev_monitor) { + assert(udev_monitor); + + sd_device_monitor_unref(udev_monitor->monitor); + return mfree(udev_monitor); +} + +/** + * udev_monitor_ref: + * @udev_monitor: udev monitor + * + * Take a reference of a udev monitor. + * + * Returns: the passed udev monitor + **/ + +/** + * udev_monitor_unref: + * @udev_monitor: udev monitor + * + * Drop a reference of a udev monitor. If the refcount reaches zero, + * the bound socket will be closed, and the resources of the monitor + * will be released. + * + * Returns: #NULL + **/ +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_monitor, udev_monitor, udev_monitor_free); + +/** + * udev_monitor_get_udev: + * @udev_monitor: udev monitor + * + * Retrieve the udev library context the monitor was created with. + * + * Returns: the udev library context + **/ +_public_ struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor) { + assert_return(udev_monitor, NULL); + + return udev_monitor->udev; +} + +/** + * udev_monitor_get_fd: + * @udev_monitor: udev monitor + * + * Retrieve the socket file descriptor associated with the monitor. + * + * Returns: the socket file descriptor + **/ +_public_ int udev_monitor_get_fd(struct udev_monitor *udev_monitor) { + assert_return(udev_monitor, -EINVAL); + + return device_monitor_get_fd(udev_monitor->monitor); +} + +static int udev_monitor_receive_sd_device(struct udev_monitor *udev_monitor, sd_device **ret) { + struct pollfd pfd; + int r; + + assert(udev_monitor); + assert(ret); + + pfd = (struct pollfd) { + .fd = device_monitor_get_fd(udev_monitor->monitor), + .events = POLLIN, + }; + + for (;;) { + /* r == 0 means a device is received but it does not pass the current filter. */ + r = device_monitor_receive_device(udev_monitor->monitor, ret); + if (r != 0) + return r; + + for (;;) { + /* wait next message */ + r = poll(&pfd, 1, 0); + if (r < 0) { + if (IN_SET(errno, EINTR, EAGAIN)) + continue; + + return -errno; + } else if (r == 0) + return -EAGAIN; + + /* receive next message */ + break; + } + } +} + +/** + * udev_monitor_receive_device: + * @udev_monitor: udev monitor + * + * Receive data from the udev monitor socket, allocate a new udev + * device, fill in the received data, and return the device. + * + * Only socket connections with uid=0 are accepted. + * + * The monitor socket is by default set to NONBLOCK. A variant of poll() on + * the file descriptor returned by udev_monitor_get_fd() should to be used to + * wake up when new devices arrive, or alternatively the file descriptor + * switched into blocking mode. + * + * The initial refcount is 1, and needs to be decremented to + * release the resources of the udev device. + * + * Returns: a new udev device, or #NULL, in case of an error + **/ +_public_ struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + int r; + + assert_return(udev_monitor, NULL); + + r = udev_monitor_receive_sd_device(udev_monitor, &device); + if (r < 0) + return_with_errno(NULL, r); + + return udev_device_new(udev_monitor->udev, device); +} + +/** + * udev_monitor_filter_add_match_subsystem_devtype: + * @udev_monitor: the monitor + * @subsystem: the subsystem value to match the incoming devices against + * @devtype: the devtype value to match the incoming devices against + * + * This filter is efficiently executed inside the kernel, and libudev subscribers + * will usually not be woken up for devices which do not match. + * + * The filter must be installed before the monitor is switched to listening mode. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, const char *subsystem, const char *devtype) { + assert_return(udev_monitor, -EINVAL); + + return sd_device_monitor_filter_add_match_subsystem_devtype(udev_monitor->monitor, subsystem, devtype); +} + +/** + * udev_monitor_filter_add_match_tag: + * @udev_monitor: the monitor + * @tag: the name of a tag + * + * This filter is efficiently executed inside the kernel, and libudev subscribers + * will usually not be woken up for devices which do not match. + * + * The filter must be installed before the monitor is switched to listening mode. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag) { + assert_return(udev_monitor, -EINVAL); + + return sd_device_monitor_filter_add_match_tag(udev_monitor->monitor, tag); +} + +/** + * udev_monitor_filter_remove: + * @udev_monitor: monitor + * + * Remove all filters from monitor. + * + * Returns: 0 on success, otherwise a negative error value. + */ +_public_ int udev_monitor_filter_remove(struct udev_monitor *udev_monitor) { + assert_return(udev_monitor, -EINVAL); + + return sd_device_monitor_filter_remove(udev_monitor->monitor); +} diff --git a/src/libudev/libudev-queue.c b/src/libudev/libudev-queue.c new file mode 100644 index 00000000..4e055bbc --- /dev/null +++ b/src/libudev/libudev-queue.c @@ -0,0 +1,236 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2009 Alan Jenkins +***/ + +#include +#include +#include +#include +#include + +#include "libudev.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "io-util.h" + +/** + * SECTION:libudev-queue + * @short_description: access to currently active events + * + * This exports the current state of the udev processing queue. + */ + +/** + * udev_queue: + * + * Opaque object representing the current event queue in the udev daemon. + */ +struct udev_queue { + struct udev *udev; + unsigned n_ref; + int fd; +}; + +/** + * udev_queue_new: + * @udev: udev library context + * + * The initial refcount is 1, and needs to be decremented to + * release the resources of the udev queue context. + * + * Returns: the udev queue context, or #NULL on error. + **/ +_public_ struct udev_queue *udev_queue_new(struct udev *udev) { + struct udev_queue *udev_queue; + + udev_queue = new(struct udev_queue, 1); + if (!udev_queue) + return_with_errno(NULL, ENOMEM); + + *udev_queue = (struct udev_queue) { + .udev = udev, + .n_ref = 1, + .fd = -1, + }; + + return udev_queue; +} + +static struct udev_queue *udev_queue_free(struct udev_queue *udev_queue) { + assert(udev_queue); + + safe_close(udev_queue->fd); + return mfree(udev_queue); +} + +/** + * udev_queue_ref: + * @udev_queue: udev queue context + * + * Take a reference of a udev queue context. + * + * Returns: the same udev queue context. + **/ + +/** + * udev_queue_unref: + * @udev_queue: udev queue context + * + * Drop a reference of a udev queue context. If the refcount reaches zero, + * the resources of the queue context will be released. + * + * Returns: #NULL + **/ +DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(struct udev_queue, udev_queue, udev_queue_free); + +/** + * udev_queue_get_udev: + * @udev_queue: udev queue context + * + * Retrieve the udev library context the queue context was created with. + * + * Returns: the udev library context. + **/ +_public_ struct udev *udev_queue_get_udev(struct udev_queue *udev_queue) { + assert_return_errno(udev_queue, NULL, EINVAL); + + return udev_queue->udev; +} + +/** + * udev_queue_get_kernel_seqnum: + * @udev_queue: udev queue context + * + * This function is deprecated. + * + * Returns: 0. + **/ +_public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) { + return 0; +} + +/** + * udev_queue_get_udev_seqnum: + * @udev_queue: udev queue context + * + * This function is deprecated. + * + * Returns: 0. + **/ +_public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) { + return 0; +} + +/** + * udev_queue_get_udev_is_active: + * @udev_queue: udev queue context + * + * Check if udev is active on the system. + * + * Returns: a flag indicating if udev is active. + **/ +_public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) { + return access("/run/udev/control", F_OK) >= 0; +} + +/** + * udev_queue_get_queue_is_empty: + * @udev_queue: udev queue context + * + * Check if udev is currently processing any events. + * + * Returns: a flag indicating if udev is currently handling events. + **/ +_public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) { + return access("/run/udev/queue", F_OK) < 0; +} + +/** + * udev_queue_get_seqnum_sequence_is_finished: + * @udev_queue: udev queue context + * @start: first event sequence number + * @end: last event sequence number + * + * This function is deprecated, it just returns the result of + * udev_queue_get_queue_is_empty(). + * + * Returns: a flag indicating if udev is currently handling events. + **/ +_public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, + unsigned long long int start, unsigned long long int end) { + return udev_queue_get_queue_is_empty(udev_queue); +} + +/** + * udev_queue_get_seqnum_is_finished: + * @udev_queue: udev queue context + * @seqnum: sequence number + * + * This function is deprecated, it just returns the result of + * udev_queue_get_queue_is_empty(). + * + * Returns: a flag indicating if udev is currently handling events. + **/ +_public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) { + return udev_queue_get_queue_is_empty(udev_queue); +} + +/** + * udev_queue_get_queued_list_entry: + * @udev_queue: udev queue context + * + * This function is deprecated. + * + * Returns: NULL. + **/ +_public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) { + return_with_errno(NULL, ENODATA); +} + +/** + * udev_queue_get_fd: + * @udev_queue: udev queue context + * + * Returns: a file descriptor to watch for a queue to become empty. + */ +_public_ int udev_queue_get_fd(struct udev_queue *udev_queue) { + _cleanup_close_ int fd = -1; + + assert_return(udev_queue, -EINVAL); + + if (udev_queue->fd >= 0) + return udev_queue->fd; + + fd = inotify_init1(IN_CLOEXEC); + if (fd < 0) + return -errno; + + if (inotify_add_watch(fd, "/run/udev" , IN_DELETE) < 0) + return -errno; + + udev_queue->fd = TAKE_FD(fd); + return udev_queue->fd; +} + +/** + * udev_queue_flush: + * @udev_queue: udev queue context + * + * Returns: the result of clearing the watch for queue changes. + */ +_public_ int udev_queue_flush(struct udev_queue *udev_queue) { + int r; + + assert_return(udev_queue, -EINVAL); + + if (udev_queue->fd < 0) + return -EINVAL; + + r = flush_fd(udev_queue->fd); + if (r < 0) + return r; + + return 0; +} diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c new file mode 100644 index 00000000..37660d03 --- /dev/null +++ b/src/libudev/libudev-util.c @@ -0,0 +1,214 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-device.h" + +#include "device-nodes.h" +#include "libudev-util.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "utf8.h" + +/** + * SECTION:libudev-util + * @short_description: utils + * + * Utilities useful when dealing with devices and device node names. + */ + +/* handle "[/]" format */ +int util_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, bool read_value) { + char temp[UTIL_PATH_SIZE], *subsys, *sysname, *attr; + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + const char *val; + int r; + + if (string[0] != '[') + return -EINVAL; + + strscpy(temp, sizeof(temp), string); + + subsys = &temp[1]; + + sysname = strchr(subsys, '/'); + if (!sysname) + return -EINVAL; + sysname[0] = '\0'; + sysname = &sysname[1]; + + attr = strchr(sysname, ']'); + if (!attr) + return -EINVAL; + attr[0] = '\0'; + attr = &attr[1]; + if (attr[0] == '/') + attr = &attr[1]; + if (attr[0] == '\0') + attr = NULL; + + if (read_value && !attr) + return -EINVAL; + + r = sd_device_new_from_subsystem_sysname(&dev, subsys, sysname); + if (r < 0) + return r; + + if (read_value) { + r = sd_device_get_sysattr_value(dev, attr, &val); + if (r < 0 && r != -ENOENT) + return r; + if (r == -ENOENT) + result[0] = '\0'; + else + strscpy(result, maxsize, val); + log_debug("value '[%s/%s]%s' is '%s'", subsys, sysname, attr, result); + } else { + r = sd_device_get_syspath(dev, &val); + if (r < 0) + return r; + + strscpyl(result, maxsize, val, attr ? "/" : NULL, attr ?: NULL, NULL); + log_debug("path '[%s/%s]%s' is '%s'", subsys, sysname, strempty(attr), result); + } + return 0; +} + +size_t util_path_encode(const char *src, char *dest, size_t size) { + size_t i, j; + + assert(src); + assert(dest); + + for (i = 0, j = 0; src[i] != '\0'; i++) { + if (src[i] == '/') { + if (j+4 >= size) { + j = 0; + break; + } + memcpy(&dest[j], "\\x2f", 4); + j += 4; + } else if (src[i] == '\\') { + if (j+4 >= size) { + j = 0; + break; + } + memcpy(&dest[j], "\\x5c", 4); + j += 4; + } else { + if (j+1 >= size) { + j = 0; + break; + } + dest[j] = src[i]; + j++; + } + } + dest[j] = '\0'; + return j; +} + +/* + * Copy from 'str' to 'to', while removing all leading and trailing whitespace, + * and replacing each run of consecutive whitespace with a single underscore. + * The chars from 'str' are copied up to the \0 at the end of the string, or + * at most 'len' chars. This appends \0 to 'to', at the end of the copied + * characters. + * + * If 'len' chars are copied into 'to', the final \0 is placed at len+1 + * (i.e. 'to[len] = \0'), so the 'to' buffer must have at least len+1 + * chars available. + * + * Note this may be called with 'str' == 'to', i.e. to replace whitespace + * in-place in a buffer. This function can handle that situation. + * + * Note that only 'len' characters are read from 'str'. + */ +size_t util_replace_whitespace(const char *str, char *to, size_t len) { + bool is_space = false; + size_t i, j; + + assert(str); + assert(to); + + i = strspn(str, WHITESPACE); + + for (j = 0; j < len && i < len && str[i] != '\0'; i++) { + if (isspace(str[i])) { + is_space = true; + continue; + } + + if (is_space) { + if (j + 1 >= len) + break; + + to[j++] = '_'; + is_space = false; + } + to[j++] = str[i]; + } + + to[j] = '\0'; + return j; +} + +/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */ +size_t util_replace_chars(char *str, const char *white) { + size_t i = 0, replaced = 0; + + assert(str); + + while (str[i] != '\0') { + int len; + + if (whitelisted_char_for_devnode(str[i], white)) { + i++; + continue; + } + + /* accept hex encoding */ + if (str[i] == '\\' && str[i+1] == 'x') { + i += 2; + continue; + } + + /* accept valid utf8 */ + len = utf8_encoded_valid_unichar(str + i, (size_t) -1); + if (len > 1) { + i += len; + continue; + } + + /* if space is allowed, replace whitespace with ordinary space */ + if (isspace(str[i]) && white && strchr(white, ' ')) { + str[i] = ' '; + i++; + replaced++; + continue; + } + + /* everything else is replaced with '_' */ + str[i] = '_'; + i++; + replaced++; + } + return replaced; +} + +/** + * udev_util_encode_string: + * @str: input string to be encoded + * @str_enc: output string to store the encoded input string + * @len: maximum size of the output string, which may be + * four times as long as the input string + * + * Encode all potentially unsafe characters of a string to the + * corresponding 2 char hex value prefixed by '\x'. + * + * Returns: 0 if the entire string was copied, non-zero otherwise. + **/ +_public_ int udev_util_encode_string(const char *str, char *str_enc, size_t len) { + return encode_devnode_name(str, str_enc, len); +} diff --git a/src/libudev/libudev-util.h b/src/libudev/libudev-util.h new file mode 100644 index 00000000..32b626eb --- /dev/null +++ b/src/libudev/libudev-util.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "libudev.h" + +#include "macro.h" + +/* libudev-util.c */ +#define UTIL_PATH_SIZE 1024 +#define UTIL_NAME_SIZE 512 +#define UTIL_LINE_SIZE 16384 +#define UDEV_ALLOWED_CHARS_INPUT "/ $%?," +size_t util_path_encode(const char *src, char *dest, size_t size); +size_t util_replace_whitespace(const char *str, char *to, size_t len); +size_t util_replace_chars(char *str, const char *white); +int util_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, bool read_value); + +/* Cleanup functions */ +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_device*, udev_device_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_enumerate*, udev_enumerate_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_monitor*, udev_monitor_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_hwdb*, udev_hwdb_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_queue*, udev_queue_unref); diff --git a/src/libudev/libudev.c b/src/libudev/libudev.c new file mode 100644 index 00000000..b4450727 --- /dev/null +++ b/src/libudev/libudev.c @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "libudev.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "string-util.h" + +/** + * SECTION:libudev + * @short_description: libudev context + */ + +/** + * udev: + * + * Opaque object representing the library context. + */ +struct udev { + unsigned n_ref; + void *userdata; +}; + +/** + * udev_get_userdata: + * @udev: udev library context + * + * Retrieve stored data pointer from library context. This might be useful + * to access from callbacks. + * + * Returns: stored userdata + **/ +_public_ void *udev_get_userdata(struct udev *udev) { + assert_return(udev, NULL); + + return udev->userdata; +} + +/** + * udev_set_userdata: + * @udev: udev library context + * @userdata: data pointer + * + * Store custom @userdata in the library context. + **/ +_public_ void udev_set_userdata(struct udev *udev, void *userdata) { + if (!udev) + return; + + udev->userdata = userdata; +} + +/** + * udev_new: + * + * Create udev library context. This only allocates the basic data structure. + * + * The initial refcount is 1, and needs to be decremented to + * release the resources of the udev library context. + * + * Returns: a new udev library context + **/ +_public_ struct udev *udev_new(void) { + struct udev *udev; + + udev = new(struct udev, 1); + if (!udev) + return_with_errno(NULL, ENOMEM); + + *udev = (struct udev) { + .n_ref = 1, + }; + + return udev; +} + +/** + * udev_ref: + * @udev: udev library context + * + * Take a reference of the udev library context. + * + * Returns: the passed udev library context + **/ +DEFINE_PUBLIC_TRIVIAL_REF_FUNC(struct udev, udev); + +/** + * udev_unref: + * @udev: udev library context + * + * Drop a reference of the udev library context. If the refcount + * reaches zero, the resources of the context will be released. + * + * Returns: the passed udev library context if it has still an active reference, or #NULL otherwise. + **/ +_public_ struct udev *udev_unref(struct udev *udev) { + if (!udev) + return NULL; + + assert(udev->n_ref > 0); + udev->n_ref--; + if (udev->n_ref > 0) + /* This is different from our convetion, but let's keep backward + * compatibility. So, do not use DEFINE_PUBLIC_TRIVIAL_UNREF_FUNC() + * macro to define this function. */ + return udev; + + return mfree(udev); +} + +/** + * udev_set_log_fn: + * @udev: udev library context + * @log_fn: function to be called for log messages + * + * This function is deprecated. + * + **/ +_public_ void udev_set_log_fn( + struct udev *udev, + void (*log_fn)(struct udev *udev, + int priority, const char *file, int line, const char *fn, + const char *format, va_list args)) { + return; +} + +/** + * udev_get_log_priority: + * @udev: udev library context + * + * This function is deprecated. + * + **/ +_public_ int udev_get_log_priority(struct udev *udev) { + return log_get_max_level(); +} + +/** + * udev_set_log_priority: + * @udev: udev library context + * @priority: the new log priority + * + * This function is deprecated. + * + **/ +_public_ void udev_set_log_priority(struct udev *udev, int priority) { + log_set_max_level(priority); +} diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h new file mode 100644 index 00000000..02c2e5e8 --- /dev/null +++ b/src/libudev/libudev.h @@ -0,0 +1,189 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#ifndef _LIBUDEV_H_ +#define _LIBUDEV_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * udev - library context + * + * reads the udev config and system environment + * allows custom logging + */ +struct udev; +struct udev *udev_ref(struct udev *udev); +struct udev *udev_unref(struct udev *udev); +struct udev *udev_new(void); +void udev_set_log_fn(struct udev *udev, + void (*log_fn)(struct udev *udev, + int priority, const char *file, int line, const char *fn, + const char *format, va_list args)) __attribute__((__deprecated__)); +int udev_get_log_priority(struct udev *udev) __attribute__((__deprecated__)); +void udev_set_log_priority(struct udev *udev, int priority) __attribute__((__deprecated__)); +void *udev_get_userdata(struct udev *udev); +void udev_set_userdata(struct udev *udev, void *userdata); + +/* + * udev_list + * + * access to libudev generated lists + */ +struct udev_list_entry; +struct udev_list_entry *udev_list_entry_get_next(struct udev_list_entry *list_entry); +struct udev_list_entry *udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name); +const char *udev_list_entry_get_name(struct udev_list_entry *list_entry); +const char *udev_list_entry_get_value(struct udev_list_entry *list_entry); +/** + * udev_list_entry_foreach: + * @list_entry: entry to store the current position + * @first_entry: first entry to start with + * + * Helper to iterate over all entries of a list. + */ +#define udev_list_entry_foreach(list_entry, first_entry) \ + for (list_entry = first_entry; \ + list_entry; \ + list_entry = udev_list_entry_get_next(list_entry)) + +/* + * udev_device + * + * access to sysfs/kernel devices + */ +struct udev_device; +struct udev_device *udev_device_ref(struct udev_device *udev_device); +struct udev_device *udev_device_unref(struct udev_device *udev_device); +struct udev *udev_device_get_udev(struct udev_device *udev_device); +struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath); +struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum); +struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname); +struct udev_device *udev_device_new_from_device_id(struct udev *udev, const char *id); +struct udev_device *udev_device_new_from_environment(struct udev *udev); +/* udev_device_get_parent_*() does not take a reference on the returned device, it is automatically unref'd with the parent */ +struct udev_device *udev_device_get_parent(struct udev_device *udev_device); +struct udev_device *udev_device_get_parent_with_subsystem_devtype(struct udev_device *udev_device, + const char *subsystem, const char *devtype); +/* retrieve device properties */ +const char *udev_device_get_devpath(struct udev_device *udev_device); +const char *udev_device_get_subsystem(struct udev_device *udev_device); +const char *udev_device_get_devtype(struct udev_device *udev_device); +const char *udev_device_get_syspath(struct udev_device *udev_device); +const char *udev_device_get_sysname(struct udev_device *udev_device); +const char *udev_device_get_sysnum(struct udev_device *udev_device); +const char *udev_device_get_devnode(struct udev_device *udev_device); +int udev_device_get_is_initialized(struct udev_device *udev_device); +struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *udev_device); +struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device *udev_device); +struct udev_list_entry *udev_device_get_tags_list_entry(struct udev_device *udev_device); +struct udev_list_entry *udev_device_get_sysattr_list_entry(struct udev_device *udev_device); +const char *udev_device_get_property_value(struct udev_device *udev_device, const char *key); +const char *udev_device_get_driver(struct udev_device *udev_device); +dev_t udev_device_get_devnum(struct udev_device *udev_device); +const char *udev_device_get_action(struct udev_device *udev_device); +unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device); +unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device); +const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr); +int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value); +int udev_device_has_tag(struct udev_device *udev_device, const char *tag); + +/* + * udev_monitor + * + * access to kernel uevents and udev events + */ +struct udev_monitor; +struct udev_monitor *udev_monitor_ref(struct udev_monitor *udev_monitor); +struct udev_monitor *udev_monitor_unref(struct udev_monitor *udev_monitor); +struct udev *udev_monitor_get_udev(struct udev_monitor *udev_monitor); +/* kernel and udev generated events over netlink */ +struct udev_monitor *udev_monitor_new_from_netlink(struct udev *udev, const char *name); +/* bind socket */ +int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor); +int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size); +int udev_monitor_get_fd(struct udev_monitor *udev_monitor); +struct udev_device *udev_monitor_receive_device(struct udev_monitor *udev_monitor); +/* in-kernel socket filters to select messages that get delivered to a listener */ +int udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor *udev_monitor, + const char *subsystem, const char *devtype); +int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag); +int udev_monitor_filter_update(struct udev_monitor *udev_monitor); +int udev_monitor_filter_remove(struct udev_monitor *udev_monitor); + +/* + * udev_enumerate + * + * search sysfs for specific devices and provide a sorted list + */ +struct udev_enumerate; +struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate); +struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate); +struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate); +struct udev_enumerate *udev_enumerate_new(struct udev *udev); +/* device properties filter */ +int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem); +int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem); +int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value); +int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value); +int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value); +int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname); +int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag); +int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent); +int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate); +int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath); +/* run enumeration with active filters */ +int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate); +int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate); +/* return device list */ +struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate); + +/* + * udev_queue + * + * access to the currently running udev events + */ +struct udev_queue; +struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue); +struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue); +struct udev *udev_queue_get_udev(struct udev_queue *udev_queue); +struct udev_queue *udev_queue_new(struct udev *udev); +unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) __attribute__((__deprecated__)); + unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) __attribute__((__deprecated__)); +int udev_queue_get_udev_is_active(struct udev_queue *udev_queue); +int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue); +int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) __attribute__((__deprecated__)); +int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, + unsigned long long int start, unsigned long long int end) __attribute__((__deprecated__)); +int udev_queue_get_fd(struct udev_queue *udev_queue); +int udev_queue_flush(struct udev_queue *udev_queue); +struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) __attribute__((__deprecated__)); + +/* + * udev_hwdb + * + * access to the static hardware properties database + */ +struct udev_hwdb; +struct udev_hwdb *udev_hwdb_new(struct udev *udev); +struct udev_hwdb *udev_hwdb_ref(struct udev_hwdb *hwdb); +struct udev_hwdb *udev_hwdb_unref(struct udev_hwdb *hwdb); +struct udev_list_entry *udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned flags); + +/* + * udev_util + * + * udev specific utilities + */ +int udev_util_encode_string(const char *str, char *str_enc, size_t len); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/libudev/libudev.pc.in b/src/libudev/libudev.pc.in new file mode 100644 index 00000000..40b34036 --- /dev/null +++ b/src/libudev/libudev.pc.in @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@rootlibdir@ +includedir=@includedir@ + +Name: libudev +Description: Library to access udev device information +Version: @PROJECT_VERSION@ +Libs: -L${libdir} -ludev +Cflags: -I${includedir} diff --git a/src/libudev/libudev.sym b/src/libudev/libudev.sym new file mode 100644 index 00000000..fb2e03e4 --- /dev/null +++ b/src/libudev/libudev.sym @@ -0,0 +1,120 @@ +/*** + SPDX-License-Identifier: LGPL-2.1+ + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. +***/ + +LIBUDEV_183 { +global: + udev_device_get_action; + udev_device_get_devlinks_list_entry; + udev_device_get_devnode; + udev_device_get_devnum; + udev_device_get_devpath; + udev_device_get_devtype; + udev_device_get_driver; + udev_device_get_is_initialized; + udev_device_get_parent; + udev_device_get_parent_with_subsystem_devtype; + udev_device_get_properties_list_entry; + udev_device_get_property_value; + udev_device_get_seqnum; + udev_device_get_subsystem; + udev_device_get_sysattr_list_entry; + udev_device_get_sysattr_value; + udev_device_get_sysname; + udev_device_get_sysnum; + udev_device_get_syspath; + udev_device_get_tags_list_entry; + udev_device_get_udev; + udev_device_get_usec_since_initialized; + udev_device_has_tag; + udev_device_new_from_devnum; + udev_device_new_from_environment; + udev_device_new_from_subsystem_sysname; + udev_device_new_from_syspath; + udev_device_ref; + udev_device_unref; + udev_enumerate_add_match_is_initialized; + udev_enumerate_add_match_parent; + udev_enumerate_add_match_property; + udev_enumerate_add_match_subsystem; + udev_enumerate_add_match_sysattr; + udev_enumerate_add_match_sysname; + udev_enumerate_add_match_tag; + udev_enumerate_add_nomatch_subsystem; + udev_enumerate_add_nomatch_sysattr; + udev_enumerate_add_syspath; + udev_enumerate_get_list_entry; + udev_enumerate_get_udev; + udev_enumerate_new; + udev_enumerate_ref; + udev_enumerate_scan_devices; + udev_enumerate_scan_subsystems; + udev_enumerate_unref; + udev_get_log_priority; + udev_get_userdata; + udev_list_entry_get_by_name; + udev_list_entry_get_name; + udev_list_entry_get_next; + udev_list_entry_get_value; + udev_monitor_enable_receiving; + udev_monitor_filter_add_match_subsystem_devtype; + udev_monitor_filter_add_match_tag; + udev_monitor_filter_remove; + udev_monitor_filter_update; + udev_monitor_get_fd; + udev_monitor_get_udev; + udev_monitor_new_from_netlink; + udev_monitor_receive_device; + udev_monitor_ref; + udev_monitor_set_receive_buffer_size; + udev_monitor_unref; + udev_new; + udev_queue_get_kernel_seqnum; + udev_queue_get_queue_is_empty; + udev_queue_get_queued_list_entry; + udev_queue_get_seqnum_is_finished; + udev_queue_get_seqnum_sequence_is_finished; + udev_queue_get_udev; + udev_queue_get_udev_is_active; + udev_queue_get_udev_seqnum; + udev_queue_new; + udev_queue_ref; + udev_queue_unref; + udev_ref; + udev_set_log_fn; + udev_set_log_priority; + udev_set_userdata; + udev_unref; + udev_util_encode_string; +local: + *; +}; + +LIBUDEV_189 { +global: + udev_device_new_from_device_id; +} LIBUDEV_183; + +LIBUDEV_196 { +global: + udev_hwdb_new; + udev_hwdb_ref; + udev_hwdb_unref; + udev_hwdb_get_properties_list_entry; +} LIBUDEV_189; + +LIBUDEV_199 { +global: + udev_device_set_sysattr_value; +} LIBUDEV_196; + +LIBUDEV_215 { +global: + udev_queue_flush; + udev_queue_get_fd; +} LIBUDEV_199; diff --git a/src/libudev/meson.build b/src/libudev/meson.build new file mode 100644 index 00000000..88189748 --- /dev/null +++ b/src/libudev/meson.build @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +libudev_sources = files(''' + libudev.c + libudev-device.c + libudev-device-internal.h + libudev-enumerate.c + libudev-hwdb.c + libudev-list.c + libudev-list-internal.h + libudev-monitor.c + libudev-queue.c + libudev-util.c + libudev-util.h +'''.split()) + +############################################################ + +libudev_sym = files('libudev.sym') +libudev_sym_path = meson.current_source_dir() + '/libudev.sym' + +install_headers('libudev.h') +libudev_h_path = '@0@/libudev.h'.format(meson.current_source_dir()) + +configure_file( + input : 'libudev.pc.in', + output : 'libudev.pc', + configuration : substs, + install_dir : pkgconfiglibdir == 'no' ? '' : pkgconfiglibdir) diff --git a/src/locale/kbd-model-map b/src/locale/kbd-model-map new file mode 100644 index 00000000..8fa984f8 --- /dev/null +++ b/src/locale/kbd-model-map @@ -0,0 +1,68 @@ +# Generated from system-config-keyboard's model list +# consolelayout xlayout xmodel xvariant xoptions +sg ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp +nl nl pc105 - terminate:ctrl_alt_bksp +mk-utf mk,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +trq tr pc105 - terminate:ctrl_alt_bksp +uk gb pc105 - terminate:ctrl_alt_bksp +is-latin1 is pc105 - terminate:ctrl_alt_bksp +de de pc105 - terminate:ctrl_alt_bksp +la-latin1 latam pc105 - terminate:ctrl_alt_bksp +us us pc105+inet - terminate:ctrl_alt_bksp +ko kr pc105 - terminate:ctrl_alt_bksp +ro-std ro pc105 std terminate:ctrl_alt_bksp +de-latin1 de pc105 - terminate:ctrl_alt_bksp +slovene si pc105 - terminate:ctrl_alt_bksp +hu101 hu pc105 qwerty terminate:ctrl_alt_bksp +jp106 jp jp106 - terminate:ctrl_alt_bksp +croat hr pc105 - terminate:ctrl_alt_bksp +it2 it pc105 - terminate:ctrl_alt_bksp +hu hu pc105 - terminate:ctrl_alt_bksp +sr-latin rs pc105 latin terminate:ctrl_alt_bksp +fi fi pc105 - terminate:ctrl_alt_bksp +fr_CH ch pc105 fr terminate:ctrl_alt_bksp +dk-latin1 dk pc105 - terminate:ctrl_alt_bksp +fr fr pc105 - terminate:ctrl_alt_bksp +it it pc105 - terminate:ctrl_alt_bksp +ua-utf ua,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +fr-latin1 fr pc105 - terminate:ctrl_alt_bksp +sg-latin1 ch pc105 de_nodeadkeys terminate:ctrl_alt_bksp +be-latin1 be pc105 - terminate:ctrl_alt_bksp +dk dk pc105 - terminate:ctrl_alt_bksp +fr-pc fr pc105 - terminate:ctrl_alt_bksp +bg_pho-utf8 bg,us pc105 ,phonetic terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +it-ibm it pc105 - terminate:ctrl_alt_bksp +cz-us-qwertz cz,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +br-abnt2 br abnt2 - terminate:ctrl_alt_bksp +ro ro pc105 - terminate:ctrl_alt_bksp +us-acentos us pc105 intl terminate:ctrl_alt_bksp +pt-latin1 pt pc105 - terminate:ctrl_alt_bksp +ro-std-cedilla ro pc105 std_cedilla terminate:ctrl_alt_bksp +tj_alt-UTF8 tj pc105 - terminate:ctrl_alt_bksp +de-latin1-nodeadkeys de pc105 nodeadkeys terminate:ctrl_alt_bksp +no no pc105 - terminate:ctrl_alt_bksp +bg_bds-utf8 bg,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +dvorak us pc105 dvorak terminate:ctrl_alt_bksp +dvorak us pc105 dvorak-alt-intl terminate:ctrl_alt_bksp +ru ru,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +cz-lat2 cz pc105 qwerty terminate:ctrl_alt_bksp +pl2 pl pc105 - terminate:ctrl_alt_bksp +es es pc105 - terminate:ctrl_alt_bksp +ro-cedilla ro pc105 cedilla terminate:ctrl_alt_bksp +ie ie pc105 - terminate:ctrl_alt_bksp +et ee pc105 - terminate:ctrl_alt_bksp +sk-qwerty sk pc105 - terminate:ctrl_alt_bksp,qwerty +sk-qwertz sk pc105 - terminate:ctrl_alt_bksp +fr-latin9 fr pc105 latin9 terminate:ctrl_alt_bksp +fr_CH-latin1 ch pc105 fr terminate:ctrl_alt_bksp +cf ca pc105 - terminate:ctrl_alt_bksp +sv-latin1 se pc105 - terminate:ctrl_alt_bksp +sr-cy rs pc105 - terminate:ctrl_alt_bksp +gr gr,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +by by,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +il il pc105 - terminate:ctrl_alt_bksp +kazakh kz,us pc105 - terminate:ctrl_alt_bksp,grp:shifts_toggle,grp_led:scroll +lt.baltic lt pc105 - terminate:ctrl_alt_bksp +lt.l4 lt pc105 - terminate:ctrl_alt_bksp +lt lt pc105 - terminate:ctrl_alt_bksp +khmer kh,us pc105 - terminate:ctrl_alt_bksp diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c new file mode 100644 index 00000000..30669a93 --- /dev/null +++ b/src/locale/keymap-util.c @@ -0,0 +1,783 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "bus-polkit.h" +#include "env-file-label.h" +#include "env-file.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio-label.h" +#include "fileio.h" +#include "kbd-util.h" +#include "keymap-util.h" +#include "locale-util.h" +#include "macro.h" +#include "mkdir.h" +#include "nulstr-util.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" + +static bool startswith_comma(const char *s, const char *prefix) { + s = startswith(s, prefix); + if (!s) + return false; + + return IN_SET(*s, ',', '\0'); +} + +static const char* systemd_kbd_model_map(void) { + const char* s; + + s = getenv("SYSTEMD_KBD_MODEL_MAP"); + if (s) + return s; + + return SYSTEMD_KBD_MODEL_MAP; +} + +static const char* systemd_language_fallback_map(void) { + const char* s; + + s = getenv("SYSTEMD_LANGUAGE_FALLBACK_MAP"); + if (s) + return s; + + return SYSTEMD_LANGUAGE_FALLBACK_MAP; +} + +static void context_free_x11(Context *c) { + c->x11_layout = mfree(c->x11_layout); + c->x11_options = mfree(c->x11_options); + c->x11_model = mfree(c->x11_model); + c->x11_variant = mfree(c->x11_variant); +} + +static void context_free_vconsole(Context *c) { + c->vc_keymap = mfree(c->vc_keymap); + c->vc_keymap_toggle = mfree(c->vc_keymap_toggle); +} + +static void context_free_locale(Context *c) { + int p; + + for (p = 0; p < _VARIABLE_LC_MAX; p++) + c->locale[p] = mfree(c->locale[p]); +} + +void context_clear(Context *c) { + context_free_locale(c); + context_free_x11(c); + context_free_vconsole(c); + + sd_bus_message_unref(c->locale_cache); + sd_bus_message_unref(c->x11_cache); + sd_bus_message_unref(c->vc_cache); + + bus_verify_polkit_async_registry_free(c->polkit_registry); +}; + +void locale_simplify(char *locale[_VARIABLE_LC_MAX]) { + int p; + + for (p = VARIABLE_LANG+1; p < _VARIABLE_LC_MAX; p++) + if (isempty(locale[p]) || streq_ptr(locale[VARIABLE_LANG], locale[p])) + locale[p] = mfree(locale[p]); +} + +int locale_read_data(Context *c, sd_bus_message *m) { + struct stat st; + int r; + + /* Do not try to re-read the file within single bus operation. */ + if (m) { + if (m == c->locale_cache) + return 0; + + sd_bus_message_unref(c->locale_cache); + c->locale_cache = sd_bus_message_ref(m); + } + + r = stat("/etc/locale.conf", &st); + if (r < 0 && errno != ENOENT) + return -errno; + + if (r >= 0) { + usec_t t; + + /* If mtime is not changed, then we do not need to re-read the file. */ + t = timespec_load(&st.st_mtim); + if (c->locale_mtime != USEC_INFINITY && t == c->locale_mtime) + return 0; + + c->locale_mtime = t; + context_free_locale(c); + + r = parse_env_file(NULL, "/etc/locale.conf", + "LANG", &c->locale[VARIABLE_LANG], + "LANGUAGE", &c->locale[VARIABLE_LANGUAGE], + "LC_CTYPE", &c->locale[VARIABLE_LC_CTYPE], + "LC_NUMERIC", &c->locale[VARIABLE_LC_NUMERIC], + "LC_TIME", &c->locale[VARIABLE_LC_TIME], + "LC_COLLATE", &c->locale[VARIABLE_LC_COLLATE], + "LC_MONETARY", &c->locale[VARIABLE_LC_MONETARY], + "LC_MESSAGES", &c->locale[VARIABLE_LC_MESSAGES], + "LC_PAPER", &c->locale[VARIABLE_LC_PAPER], + "LC_NAME", &c->locale[VARIABLE_LC_NAME], + "LC_ADDRESS", &c->locale[VARIABLE_LC_ADDRESS], + "LC_TELEPHONE", &c->locale[VARIABLE_LC_TELEPHONE], + "LC_MEASUREMENT", &c->locale[VARIABLE_LC_MEASUREMENT], + "LC_IDENTIFICATION", &c->locale[VARIABLE_LC_IDENTIFICATION]); + if (r < 0) + return r; + } else { + int p; + + c->locale_mtime = USEC_INFINITY; + context_free_locale(c); + + /* Fill in what we got passed from systemd. */ + for (p = 0; p < _VARIABLE_LC_MAX; p++) { + const char *name; + + name = locale_variable_to_string(p); + assert(name); + + r = free_and_strdup(&c->locale[p], empty_to_null(getenv(name))); + if (r < 0) + return r; + } + } + + locale_simplify(c->locale); + return 0; +} + +int vconsole_read_data(Context *c, sd_bus_message *m) { + struct stat st; + usec_t t; + int r; + + /* Do not try to re-read the file within single bus operation. */ + if (m) { + if (m == c->vc_cache) + return 0; + + sd_bus_message_unref(c->vc_cache); + c->vc_cache = sd_bus_message_ref(m); + } + + if (stat("/etc/vconsole.conf", &st) < 0) { + if (errno != ENOENT) + return -errno; + + c->vc_mtime = USEC_INFINITY; + context_free_vconsole(c); + return 0; + } + + /* If mtime is not changed, then we do not need to re-read */ + t = timespec_load(&st.st_mtim); + if (c->vc_mtime != USEC_INFINITY && t == c->vc_mtime) + return 0; + + c->vc_mtime = t; + context_free_vconsole(c); + + r = parse_env_file(NULL, "/etc/vconsole.conf", + "KEYMAP", &c->vc_keymap, + "KEYMAP_TOGGLE", &c->vc_keymap_toggle); + if (r < 0) + return r; + + return 0; +} + +int x11_read_data(Context *c, sd_bus_message *m) { + _cleanup_fclose_ FILE *f = NULL; + bool in_section = false; + struct stat st; + usec_t t; + int r; + + /* Do not try to re-read the file within single bus operation. */ + if (m) { + if (m == c->x11_cache) + return 0; + + sd_bus_message_unref(c->x11_cache); + c->x11_cache = sd_bus_message_ref(m); + } + + if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) < 0) { + if (errno != ENOENT) + return -errno; + + c->x11_mtime = USEC_INFINITY; + context_free_x11(c); + return 0; + } + + /* If mtime is not changed, then we do not need to re-read */ + t = timespec_load(&st.st_mtim); + if (c->x11_mtime != USEC_INFINITY && t == c->x11_mtime) + return 0; + + c->x11_mtime = t; + context_free_x11(c); + + f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re"); + if (!f) + return -errno; + + for (;;) { + _cleanup_free_ char *line = NULL; + char *l; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + l = strstrip(line); + if (IN_SET(l[0], 0, '#')) + continue; + + if (in_section && first_word(l, "Option")) { + _cleanup_strv_free_ char **a = NULL; + + r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_UNQUOTE); + if (r < 0) + return r; + + if (strv_length(a) == 3) { + char **p = NULL; + + if (streq(a[1], "XkbLayout")) + p = &c->x11_layout; + else if (streq(a[1], "XkbModel")) + p = &c->x11_model; + else if (streq(a[1], "XkbVariant")) + p = &c->x11_variant; + else if (streq(a[1], "XkbOptions")) + p = &c->x11_options; + + if (p) { + free_and_replace(*p, a[2]); + } + } + + } else if (!in_section && first_word(l, "Section")) { + _cleanup_strv_free_ char **a = NULL; + + r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_UNQUOTE); + if (r < 0) + return -ENOMEM; + + if (strv_length(a) == 2 && streq(a[1], "InputClass")) + in_section = true; + + } else if (in_section && first_word(l, "EndSection")) + in_section = false; + } + + return 0; +} + +int locale_write_data(Context *c, char ***settings) { + _cleanup_strv_free_ char **l = NULL; + struct stat st; + int r, p; + + /* Set values will be returned as strv in *settings on success. */ + + for (p = 0; p < _VARIABLE_LC_MAX; p++) { + _cleanup_free_ char *t = NULL; + char **u; + const char *name; + + name = locale_variable_to_string(p); + assert(name); + + if (isempty(c->locale[p])) + continue; + + if (asprintf(&t, "%s=%s", name, c->locale[p]) < 0) + return -ENOMEM; + + u = strv_env_set(l, t); + if (!u) + return -ENOMEM; + + strv_free_and_replace(l, u); + } + + if (strv_isempty(l)) { + if (unlink("/etc/locale.conf") < 0) + return errno == ENOENT ? 0 : -errno; + + c->locale_mtime = USEC_INFINITY; + return 0; + } + + r = write_env_file_label("/etc/locale.conf", l); + if (r < 0) + return r; + + *settings = TAKE_PTR(l); + + if (stat("/etc/locale.conf", &st) >= 0) + c->locale_mtime = timespec_load(&st.st_mtim); + + return 0; +} + +int vconsole_write_data(Context *c) { + _cleanup_strv_free_ char **l = NULL; + struct stat st; + int r; + + r = load_env_file(NULL, "/etc/vconsole.conf", &l); + if (r < 0 && r != -ENOENT) + return r; + + if (isempty(c->vc_keymap)) + l = strv_env_unset(l, "KEYMAP"); + else { + _cleanup_free_ char *s = NULL; + char **u; + + s = strjoin("KEYMAP=", c->vc_keymap); + if (!s) + return -ENOMEM; + + u = strv_env_set(l, s); + if (!u) + return -ENOMEM; + + strv_free_and_replace(l, u); + } + + if (isempty(c->vc_keymap_toggle)) + l = strv_env_unset(l, "KEYMAP_TOGGLE"); + else { + _cleanup_free_ char *s = NULL; + char **u; + + s = strjoin("KEYMAP_TOGGLE=", c->vc_keymap_toggle); + if (!s) + return -ENOMEM; + + u = strv_env_set(l, s); + if (!u) + return -ENOMEM; + + strv_free_and_replace(l, u); + } + + if (strv_isempty(l)) { + if (unlink("/etc/vconsole.conf") < 0) + return errno == ENOENT ? 0 : -errno; + + c->vc_mtime = USEC_INFINITY; + return 0; + } + + r = write_env_file_label("/etc/vconsole.conf", l); + if (r < 0) + return r; + + if (stat("/etc/vconsole.conf", &st) >= 0) + c->vc_mtime = timespec_load(&st.st_mtim); + + return 0; +} + +int x11_write_data(Context *c) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *temp_path = NULL; + struct stat st; + int r; + + if (isempty(c->x11_layout) && + isempty(c->x11_model) && + isempty(c->x11_variant) && + isempty(c->x11_options)) { + + if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) + return errno == ENOENT ? 0 : -errno; + + c->vc_mtime = USEC_INFINITY; + return 0; + } + + (void) mkdir_p_label("/etc/X11/xorg.conf.d", 0755); + r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path); + if (r < 0) + return r; + + (void) fchmod(fileno(f), 0644); + + fputs("# Written by systemd-localed(8), read by systemd-localed and Xorg. It's\n" + "# probably wise not to edit this file manually. Use localectl(1) to\n" + "# instruct systemd-localed to update it.\n" + "Section \"InputClass\"\n" + " Identifier \"system-keyboard\"\n" + " MatchIsKeyboard \"on\"\n", f); + + if (!isempty(c->x11_layout)) + fprintf(f, " Option \"XkbLayout\" \"%s\"\n", c->x11_layout); + + if (!isempty(c->x11_model)) + fprintf(f, " Option \"XkbModel\" \"%s\"\n", c->x11_model); + + if (!isempty(c->x11_variant)) + fprintf(f, " Option \"XkbVariant\" \"%s\"\n", c->x11_variant); + + if (!isempty(c->x11_options)) + fprintf(f, " Option \"XkbOptions\" \"%s\"\n", c->x11_options); + + fputs("EndSection\n", f); + + r = fflush_sync_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.conf") < 0) { + r = -errno; + goto fail; + } + + if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) >= 0) + c->x11_mtime = timespec_load(&st.st_mtim); + + return 0; + +fail: + if (temp_path) + (void) unlink(temp_path); + + return r; +} + +static int read_next_mapping(const char* filename, + unsigned min_fields, unsigned max_fields, + FILE *f, unsigned *n, char ***a) { + assert(f); + assert(n); + assert(a); + + for (;;) { + _cleanup_free_ char *line = NULL; + size_t length; + char *l, **b; + int r; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + (*n)++; + + l = strstrip(line); + if (IN_SET(l[0], 0, '#')) + continue; + + r = strv_split_extract(&b, l, WHITESPACE, EXTRACT_UNQUOTE); + if (r < 0) + return r; + + length = strv_length(b); + if (length < min_fields || length > max_fields) { + log_error("Invalid line %s:%u, ignoring.", filename, *n); + strv_free(b); + continue; + + } + + *a = b; + return 1; + } + + return 0; +} + +int vconsole_convert_to_x11(Context *c) { + const char *map; + int modified = -1; + + map = systemd_kbd_model_map(); + + if (isempty(c->vc_keymap)) { + modified = + !isempty(c->x11_layout) || + !isempty(c->x11_model) || + !isempty(c->x11_variant) || + !isempty(c->x11_options); + + context_free_x11(c); + } else { + _cleanup_fclose_ FILE *f = NULL; + unsigned n = 0; + + f = fopen(map, "re"); + if (!f) + return -errno; + + for (;;) { + _cleanup_strv_free_ char **a = NULL; + int r; + + r = read_next_mapping(map, 5, UINT_MAX, f, &n, &a); + if (r < 0) + return r; + if (r == 0) + break; + + if (!streq(c->vc_keymap, a[0])) + continue; + + if (!streq_ptr(c->x11_layout, empty_or_dash_to_null(a[1])) || + !streq_ptr(c->x11_model, empty_or_dash_to_null(a[2])) || + !streq_ptr(c->x11_variant, empty_or_dash_to_null(a[3])) || + !streq_ptr(c->x11_options, empty_or_dash_to_null(a[4]))) { + + if (free_and_strdup(&c->x11_layout, empty_or_dash_to_null(a[1])) < 0 || + free_and_strdup(&c->x11_model, empty_or_dash_to_null(a[2])) < 0 || + free_and_strdup(&c->x11_variant, empty_or_dash_to_null(a[3])) < 0 || + free_and_strdup(&c->x11_options, empty_or_dash_to_null(a[4])) < 0) + return -ENOMEM; + + modified = true; + } + + break; + } + } + + if (modified > 0) + log_info("Changing X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'", + strempty(c->x11_layout), + strempty(c->x11_model), + strempty(c->x11_variant), + strempty(c->x11_options)); + else if (modified < 0) + log_notice("X11 keyboard layout was not modified: no conversion found for \"%s\".", + c->vc_keymap); + else + log_debug("X11 keyboard layout did not need to be modified."); + + return modified > 0; +} + +int find_converted_keymap(const char *x11_layout, const char *x11_variant, char **new_keymap) { + const char *dir; + _cleanup_free_ char *n; + + if (x11_variant) + n = strjoin(x11_layout, "-", x11_variant); + else + n = strdup(x11_layout); + if (!n) + return -ENOMEM; + + NULSTR_FOREACH(dir, KBD_KEYMAP_DIRS) { + _cleanup_free_ char *p = NULL, *pz = NULL; + bool uncompressed; + + p = strjoin(dir, "xkb/", n, ".map"); + pz = strjoin(dir, "xkb/", n, ".map.gz"); + if (!p || !pz) + return -ENOMEM; + + uncompressed = access(p, F_OK) == 0; + if (uncompressed || access(pz, F_OK) == 0) { + log_debug("Found converted keymap %s at %s", + n, uncompressed ? p : pz); + + *new_keymap = TAKE_PTR(n); + return 1; + } + } + + return 0; +} + +int find_legacy_keymap(Context *c, char **ret) { + const char *map; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *new_keymap = NULL; + unsigned n = 0; + unsigned best_matching = 0; + int r; + + assert(!isempty(c->x11_layout)); + + map = systemd_kbd_model_map(); + + f = fopen(map, "re"); + if (!f) + return -errno; + + for (;;) { + _cleanup_strv_free_ char **a = NULL; + unsigned matching = 0; + + r = read_next_mapping(map, 5, UINT_MAX, f, &n, &a); + if (r < 0) + return r; + if (r == 0) + break; + + /* Determine how well matching this entry is */ + if (streq(c->x11_layout, a[1])) + /* If we got an exact match, this is best */ + matching = 10; + else { + /* We have multiple X layouts, look for an + * entry that matches our key with everything + * but the first layout stripped off. */ + if (startswith_comma(c->x11_layout, a[1])) + matching = 5; + else { + _cleanup_free_ char *x = NULL; + + /* If that didn't work, strip off the + * other layouts from the entry, too */ + x = strndup(a[1], strcspn(a[1], ",")); + if (startswith_comma(c->x11_layout, x)) + matching = 1; + } + } + + if (matching > 0) { + if (isempty(c->x11_model) || streq_ptr(c->x11_model, a[2])) { + matching++; + + if (streq_ptr(c->x11_variant, a[3])) { + matching++; + + if (streq_ptr(c->x11_options, a[4])) + matching++; + } + } + } + + /* The best matching entry so far, then let's save that */ + if (matching >= MAX(best_matching, 1u)) { + log_debug("Found legacy keymap %s with score %u", + a[0], matching); + + if (matching > best_matching) { + best_matching = matching; + + r = free_and_strdup(&new_keymap, a[0]); + if (r < 0) + return r; + } + } + } + + if (best_matching < 10 && c->x11_layout) { + /* The best match is only the first part of the X11 + * keymap. Check if we have a converted map which + * matches just the first layout. + */ + char *l, *v = NULL, *converted; + + l = strndupa(c->x11_layout, strcspn(c->x11_layout, ",")); + if (c->x11_variant) + v = strndupa(c->x11_variant, strcspn(c->x11_variant, ",")); + r = find_converted_keymap(l, v, &converted); + if (r < 0) + return r; + if (r > 0) + free_and_replace(new_keymap, converted); + } + + *ret = TAKE_PTR(new_keymap); + return (bool) *ret; +} + +int find_language_fallback(const char *lang, char **language) { + const char *map; + _cleanup_fclose_ FILE *f = NULL; + unsigned n = 0; + + assert(lang); + assert(language); + + map = systemd_language_fallback_map(); + + f = fopen(map, "re"); + if (!f) + return -errno; + + for (;;) { + _cleanup_strv_free_ char **a = NULL; + int r; + + r = read_next_mapping(map, 2, 2, f, &n, &a); + if (r <= 0) + return r; + + if (streq(lang, a[0])) { + assert(strv_length(a) == 2); + *language = TAKE_PTR(a[1]); + return 1; + } + } + + assert_not_reached("should not be here"); +} + +int x11_convert_to_vconsole(Context *c) { + bool modified = false; + + if (isempty(c->x11_layout)) { + modified = + !isempty(c->vc_keymap) || + !isempty(c->vc_keymap_toggle); + + context_free_vconsole(c); + } else { + _cleanup_free_ char *new_keymap = NULL; + int r; + + r = find_converted_keymap(c->x11_layout, c->x11_variant, &new_keymap); + if (r < 0) + return r; + else if (r == 0) { + r = find_legacy_keymap(c, &new_keymap); + if (r < 0) + return r; + } + if (r == 0) + /* We search for layout-variant match first, but then we also look + * for anything which matches just the layout. So it's accurate to say + * that we couldn't find anything which matches the layout. */ + log_notice("No conversion to virtual console map found for \"%s\".", + c->x11_layout); + + if (!streq_ptr(c->vc_keymap, new_keymap)) { + free_and_replace(c->vc_keymap, new_keymap); + c->vc_keymap_toggle = mfree(c->vc_keymap_toggle); + modified = true; + } + } + + if (modified) + log_info("Changing virtual console keymap to '%s' toggle '%s'", + strempty(c->vc_keymap), strempty(c->vc_keymap_toggle)); + else + log_debug("Virtual console keymap was not modified."); + + return modified; +} diff --git a/src/locale/keymap-util.h b/src/locale/keymap-util.h new file mode 100644 index 00000000..6eced842 --- /dev/null +++ b/src/locale/keymap-util.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "hashmap.h" +#include "locale-util.h" +#include "time-util.h" + +typedef struct Context { + sd_bus_message *locale_cache; + usec_t locale_mtime; + char *locale[_VARIABLE_LC_MAX]; + + sd_bus_message *x11_cache; + usec_t x11_mtime; + char *x11_layout; + char *x11_model; + char *x11_variant; + char *x11_options; + + sd_bus_message *vc_cache; + usec_t vc_mtime; + char *vc_keymap; + char *vc_keymap_toggle; + + Hashmap *polkit_registry; +} Context; + +int find_converted_keymap(const char *x11_layout, const char *x11_variant, char **new_keymap); +int find_legacy_keymap(Context *c, char **new_keymap); +int find_language_fallback(const char *lang, char **language); + +int locale_read_data(Context *c, sd_bus_message *m); +int vconsole_read_data(Context *c, sd_bus_message *m); +int x11_read_data(Context *c, sd_bus_message *m); + +void context_clear(Context *c); +int vconsole_convert_to_x11(Context *c); +int vconsole_write_data(Context *c); +int x11_convert_to_vconsole(Context *c); +int x11_write_data(Context *c); +void locale_simplify(char *locale[_VARIABLE_LC_MAX]); +int locale_write_data(Context *c, char ***settings); diff --git a/src/locale/language-fallback-map b/src/locale/language-fallback-map new file mode 100644 index 00000000..d0b02a6b --- /dev/null +++ b/src/locale/language-fallback-map @@ -0,0 +1,13 @@ +csb_PL csb:pl +en_AU en_AU:en_GB +en_IE en_IE:en_GB +en_NZ en_NZ:en_GB +en_ZA en_ZA:en_GB +fr_BE fr_BE:fr_FR +fr_CA fr_CA:fr_FR +fr_CH fr_CH:fr_FR +fr_LU fr_LU:fr_FR +it_CH it_CH:it_IT +mai_IN mai:hi +nds_DE nds:de +szl_PL szl:pl diff --git a/src/locale/localectl.c b/src/locale/localectl.c new file mode 100644 index 00000000..6f2d37d2 --- /dev/null +++ b/src/locale/localectl.c @@ -0,0 +1,530 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "bus-error.h" +#include "bus-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "kbd-util.h" +#include "locale-util.h" +#include "main-func.h" +#include "memory-util.h" +#include "pager.h" +#include "pretty-print.h" +#include "proc-cmdline.h" +#include "set.h" +#include "spawn-polkit-agent.h" +#include "strv.h" +#include "terminal-util.h" +#include "verbs.h" +#include "virt.h" + +static PagerFlags arg_pager_flags = 0; +static bool arg_ask_password = true; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static const char *arg_host = NULL; +static bool arg_convert = true; + +typedef struct StatusInfo { + char **locale; + const char *vconsole_keymap; + const char *vconsole_keymap_toggle; + const char *x11_layout; + const char *x11_model; + const char *x11_variant; + const char *x11_options; +} StatusInfo; + +static void status_info_clear(StatusInfo *info) { + if (info) { + strv_free(info->locale); + zero(*info); + } +} + +static void print_overridden_variables(void) { + _cleanup_(locale_variables_freep) char *variables[_VARIABLE_LC_MAX] = {}; + bool print_warning = true; + LocaleVariable j; + int r; + + if (arg_transport != BUS_TRANSPORT_LOCAL) + return; + + r = proc_cmdline_get_key_many( + PROC_CMDLINE_STRIP_RD_PREFIX, + "locale.LANG", &variables[VARIABLE_LANG], + "locale.LANGUAGE", &variables[VARIABLE_LANGUAGE], + "locale.LC_CTYPE", &variables[VARIABLE_LC_CTYPE], + "locale.LC_NUMERIC", &variables[VARIABLE_LC_NUMERIC], + "locale.LC_TIME", &variables[VARIABLE_LC_TIME], + "locale.LC_COLLATE", &variables[VARIABLE_LC_COLLATE], + "locale.LC_MONETARY", &variables[VARIABLE_LC_MONETARY], + "locale.LC_MESSAGES", &variables[VARIABLE_LC_MESSAGES], + "locale.LC_PAPER", &variables[VARIABLE_LC_PAPER], + "locale.LC_NAME", &variables[VARIABLE_LC_NAME], + "locale.LC_ADDRESS", &variables[VARIABLE_LC_ADDRESS], + "locale.LC_TELEPHONE", &variables[VARIABLE_LC_TELEPHONE], + "locale.LC_MEASUREMENT", &variables[VARIABLE_LC_MEASUREMENT], + "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION]); + if (r < 0 && r != -ENOENT) { + log_warning_errno(r, "Failed to read /proc/cmdline: %m"); + return; + } + + for (j = 0; j < _VARIABLE_LC_MAX; j++) + if (variables[j]) { + if (print_warning) { + log_warning("Warning: Settings on kernel command line override system locale settings in /etc/locale.conf.\n" + " Command Line: %s=%s", locale_variable_to_string(j), variables[j]); + + print_warning = false; + } else + log_warning(" %s=%s", locale_variable_to_string(j), variables[j]); + } +} + +static void print_status_info(StatusInfo *i) { + assert(i); + + if (strv_isempty(i->locale)) + puts(" System Locale: n/a"); + else { + char **j; + + printf(" System Locale: %s\n", i->locale[0]); + STRV_FOREACH(j, i->locale + 1) + printf(" %s\n", *j); + } + + printf(" VC Keymap: %s\n", strna(i->vconsole_keymap)); + if (!isempty(i->vconsole_keymap_toggle)) + printf("VC Toggle Keymap: %s\n", i->vconsole_keymap_toggle); + + printf(" X11 Layout: %s\n", strna(i->x11_layout)); + if (!isempty(i->x11_model)) + printf(" X11 Model: %s\n", i->x11_model); + if (!isempty(i->x11_variant)) + printf(" X11 Variant: %s\n", i->x11_variant); + if (!isempty(i->x11_options)) + printf(" X11 Options: %s\n", i->x11_options); +} + +static int show_status(int argc, char **argv, void *userdata) { + _cleanup_(status_info_clear) StatusInfo info = {}; + static const struct bus_properties_map map[] = { + { "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) }, + { "VConsoleKeymapToggle", "s", NULL, offsetof(StatusInfo, vconsole_keymap_toggle) }, + { "X11Layout", "s", NULL, offsetof(StatusInfo, x11_layout) }, + { "X11Model", "s", NULL, offsetof(StatusInfo, x11_model) }, + { "X11Variant", "s", NULL, offsetof(StatusInfo, x11_variant) }, + { "X11Options", "s", NULL, offsetof(StatusInfo, x11_options) }, + { "Locale", "as", NULL, offsetof(StatusInfo, locale) }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + r = bus_map_all_properties(bus, + "org.freedesktop.locale1", + "/org/freedesktop/locale1", + map, + 0, + &error, + &m, + &info); + if (r < 0) + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); + + print_overridden_variables(); + print_status_info(&info); + + return r; +} + +static int set_locale(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.locale1", + "/org/freedesktop/locale1", + "org.freedesktop.locale1", + "SetLocale"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, argv + 1); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "b", arg_ask_password); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, -r)); + + return 0; +} + +static int list_locales(int argc, char **argv, void *userdata) { + _cleanup_strv_free_ char **l = NULL; + int r; + + r = get_locales(&l); + if (r < 0) + return log_error_errno(r, "Failed to read list of locales: %m"); + + (void) pager_open(arg_pager_flags); + strv_print(l); + + return 0; +} + +static int set_vconsole_keymap(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *map, *toggle_map; + sd_bus *bus = userdata; + int r; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + map = argv[1]; + toggle_map = argc > 2 ? argv[2] : ""; + + r = sd_bus_call_method( + bus, + "org.freedesktop.locale1", + "/org/freedesktop/locale1", + "org.freedesktop.locale1", + "SetVConsoleKeyboard", + &error, + NULL, + "ssbb", map, toggle_map, arg_convert, arg_ask_password); + if (r < 0) + return log_error_errno(r, "Failed to set keymap: %s", bus_error_message(&error, -r)); + + return 0; +} + +static int list_vconsole_keymaps(int argc, char **argv, void *userdata) { + _cleanup_strv_free_ char **l = NULL; + int r; + + r = get_keymaps(&l); + if (r < 0) + return log_error_errno(r, "Failed to read list of keymaps: %m"); + + (void) pager_open(arg_pager_flags); + + strv_print(l); + + return 0; +} + +static int set_x11_keymap(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *layout, *model, *variant, *options; + sd_bus *bus = userdata; + int r; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + layout = argv[1]; + model = argc > 2 ? argv[2] : ""; + variant = argc > 3 ? argv[3] : ""; + options = argc > 4 ? argv[4] : ""; + + r = sd_bus_call_method( + bus, + "org.freedesktop.locale1", + "/org/freedesktop/locale1", + "org.freedesktop.locale1", + "SetX11Keyboard", + &error, + NULL, + "ssssbb", layout, model, variant, options, + arg_convert, arg_ask_password); + if (r < 0) + return log_error_errno(r, "Failed to set keymap: %s", bus_error_message(&error, -r)); + + return 0; +} + +static int list_x11_keymaps(int argc, char **argv, void *userdata) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_strv_free_ char **list = NULL; + enum { + NONE, + MODELS, + LAYOUTS, + VARIANTS, + OPTIONS + } state = NONE, look_for; + int r; + + f = fopen("/usr/share/X11/xkb/rules/base.lst", "re"); + if (!f) + return log_error_errno(errno, "Failed to open keyboard mapping list. %m"); + + if (streq(argv[0], "list-x11-keymap-models")) + look_for = MODELS; + else if (streq(argv[0], "list-x11-keymap-layouts")) + look_for = LAYOUTS; + else if (streq(argv[0], "list-x11-keymap-variants")) + look_for = VARIANTS; + else if (streq(argv[0], "list-x11-keymap-options")) + look_for = OPTIONS; + else + assert_not_reached("Wrong parameter"); + + for (;;) { + _cleanup_free_ char *line = NULL; + char *l, *w; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read keyboard mapping list: %m"); + if (r == 0) + break; + + l = strstrip(line); + + if (isempty(l)) + continue; + + if (l[0] == '!') { + if (startswith(l, "! model")) + state = MODELS; + else if (startswith(l, "! layout")) + state = LAYOUTS; + else if (startswith(l, "! variant")) + state = VARIANTS; + else if (startswith(l, "! option")) + state = OPTIONS; + else + state = NONE; + + continue; + } + + if (state != look_for) + continue; + + w = l + strcspn(l, WHITESPACE); + + if (argc > 1) { + char *e; + + if (*w == 0) + continue; + + *w = 0; + w++; + w += strspn(w, WHITESPACE); + + e = strchr(w, ':'); + if (!e) + continue; + + *e = 0; + + if (!streq(w, argv[1])) + continue; + } else + *w = 0; + + r = strv_extend(&list, l); + if (r < 0) + return log_oom(); + } + + if (strv_isempty(list)) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), + "Couldn't find any entries."); + + strv_sort(list); + strv_uniq(list); + + (void) pager_open(arg_pager_flags); + + strv_print(list); + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("localectl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n\n" + "%sQuery or change system locale and keyboard settings.%s\n" + "\nCommands:\n" + " status Show current locale settings\n" + " set-locale LOCALE... Set system locale\n" + " list-locales Show known locales\n" + " set-keymap MAP [MAP] Set console and X11 keyboard mappings\n" + " list-keymaps Show known virtual console keyboard mappings\n" + " set-x11-keymap LAYOUT [MODEL [VARIANT [OPTIONS]]]\n" + " Set X11 and console keyboard mappings\n" + " list-x11-keymap-models Show known X11 keyboard mapping models\n" + " list-x11-keymap-layouts Show known X11 keyboard mapping layouts\n" + " list-x11-keymap-variants [LAYOUT]\n" + " Show known X11 keyboard mapping variants\n" + " list-x11-keymap-options Show known X11 keyboard mapping options\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --no-ask-password Do not prompt for password\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " --no-convert Don't convert keyboard mappings\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int verb_help(int argc, char **argv, void *userdata) { + return help(); +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_PAGER, + ARG_NO_CONVERT, + ARG_NO_ASK_PASSWORD + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "no-convert", no_argument, NULL, ARG_NO_CONVERT }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_NO_CONVERT: + arg_convert = false; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int localectl_main(sd_bus *bus, int argc, char *argv[]) { + + static const Verb verbs[] = { + { "status", VERB_ANY, 1, VERB_DEFAULT, show_status }, + { "set-locale", 2, VERB_ANY, 0, set_locale }, + { "list-locales", VERB_ANY, 1, 0, list_locales }, + { "set-keymap", 2, 3, 0, set_vconsole_keymap }, + { "list-keymaps", VERB_ANY, 1, 0, list_vconsole_keymaps }, + { "set-x11-keymap", 2, 5, 0, set_x11_keymap }, + { "list-x11-keymap-models", VERB_ANY, 1, 0, list_x11_keymaps }, + { "list-x11-keymap-layouts", VERB_ANY, 1, 0, list_x11_keymaps }, + { "list-x11-keymap-variants", VERB_ANY, 2, 0, list_x11_keymaps }, + { "list-x11-keymap-options", VERB_ANY, 1, 0, list_x11_keymaps }, + { "help", VERB_ANY, VERB_ANY, 0, verb_help }, /* Not documented, but supported since it is created. */ + {} + }; + + return dispatch_verb(argc, argv, verbs, bus); +} + +static int run(int argc, char *argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + setlocale(LC_ALL, ""); + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = bus_connect_transport(arg_transport, arg_host, false, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + return localectl_main(bus, argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/locale/localed.c b/src/locale/localed.c new file mode 100644 index 00000000..09f16d25 --- /dev/null +++ b/src/locale/localed.c @@ -0,0 +1,759 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#if HAVE_XKBCOMMON +#include +#include +#endif + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-message.h" +#include "bus-polkit.h" +#include "def.h" +#include "keymap-util.h" +#include "locale-util.h" +#include "macro.h" +#include "main-func.h" +#include "missing_capability.h" +#include "path-util.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" + +static int locale_update_system_manager(Context *c, sd_bus *bus) { + _cleanup_free_ char **l_unset = NULL; + _cleanup_strv_free_ char **l_set = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + size_t c_set, c_unset; + LocaleVariable p; + int r; + + assert(bus); + + l_unset = new0(char*, _VARIABLE_LC_MAX); + if (!l_unset) + return log_oom(); + + l_set = new0(char*, _VARIABLE_LC_MAX); + if (!l_set) + return log_oom(); + + for (p = 0, c_set = 0, c_unset = 0; p < _VARIABLE_LC_MAX; p++) { + const char *name; + + name = locale_variable_to_string(p); + assert(name); + + if (isempty(c->locale[p])) + l_unset[c_set++] = (char*) name; + else { + char *s; + + s = strjoin(name, "=", c->locale[p]); + if (!s) + return log_oom(); + + l_set[c_unset++] = s; + } + } + + assert(c_set + c_unset == _VARIABLE_LC_MAX); + r = sd_bus_message_new_method_call(bus, &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "UnsetAndSetEnvironment"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, l_unset); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, l_set); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to update the manager environment: %s", bus_error_message(&error, r)); + + return 0; +} + +static int vconsole_reload(sd_bus *bus) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "RestartUnit", + &error, + NULL, + "ss", "systemd-vconsole-setup.service", "replace"); + + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); + + return 0; +} + +static int vconsole_convert_to_x11_and_emit(Context *c, sd_bus_message *m) { + int r; + + assert(m); + + r = x11_read_data(c, m); + if (r < 0) + return r; + + r = vconsole_convert_to_x11(c); + if (r <= 0) + return r; + + /* modified */ + r = x11_write_data(c); + if (r < 0) + return log_error_errno(r, "Failed to write X11 keyboard layout: %m"); + + sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), + "/org/freedesktop/locale1", + "org.freedesktop.locale1", + "X11Layout", "X11Model", "X11Variant", "X11Options", NULL); + + return 1; +} + +static int x11_convert_to_vconsole_and_emit(Context *c, sd_bus_message *m) { + int r; + + assert(m); + + r = vconsole_read_data(c, m); + if (r < 0) + return r; + + r = x11_convert_to_vconsole(c); + if (r <= 0) + return r; + + /* modified */ + r = vconsole_write_data(c); + if (r < 0) + log_error_errno(r, "Failed to save virtual console keymap: %m"); + + sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), + "/org/freedesktop/locale1", + "org.freedesktop.locale1", + "VConsoleKeymap", "VConsoleKeymapToggle", NULL); + + return vconsole_reload(sd_bus_message_get_bus(m)); +} + +static int property_get_locale( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Context *c = userdata; + _cleanup_strv_free_ char **l = NULL; + int p, q, r; + + r = locale_read_data(c, reply); + if (r < 0) + return r; + + l = new0(char*, _VARIABLE_LC_MAX+1); + if (!l) + return -ENOMEM; + + for (p = 0, q = 0; p < _VARIABLE_LC_MAX; p++) { + char *t; + const char *name; + + name = locale_variable_to_string(p); + assert(name); + + if (isempty(c->locale[p])) + continue; + + if (asprintf(&t, "%s=%s", name, c->locale[p]) < 0) + return -ENOMEM; + + l[q++] = t; + } + + return sd_bus_message_append_strv(reply, l); +} + +static int property_get_vconsole( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Context *c = userdata; + int r; + + r = vconsole_read_data(c, reply); + if (r < 0) + return r; + + if (streq(property, "VConsoleKeymap")) + return sd_bus_message_append_basic(reply, 's', c->vc_keymap); + else if (streq(property, "VConsoleKeymapToggle")) + return sd_bus_message_append_basic(reply, 's', c->vc_keymap_toggle); + + return -EINVAL; +} + +static int property_get_xkb( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Context *c = userdata; + int r; + + r = x11_read_data(c, reply); + if (r < 0) + return r; + + if (streq(property, "X11Layout")) + return sd_bus_message_append_basic(reply, 's', c->x11_layout); + else if (streq(property, "X11Model")) + return sd_bus_message_append_basic(reply, 's', c->x11_model); + else if (streq(property, "X11Variant")) + return sd_bus_message_append_basic(reply, 's', c->x11_variant); + else if (streq(property, "X11Options")) + return sd_bus_message_append_basic(reply, 's', c->x11_options); + + return -EINVAL; +} + +static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *error) { + _cleanup_(locale_variables_freep) char *new_locale[_VARIABLE_LC_MAX] = {}; + _cleanup_strv_free_ char **settings = NULL, **l = NULL; + Context *c = userdata; + bool modified = false; + int interactive, p, r; + char **i; + + assert(m); + assert(c); + + r = bus_message_read_strv_extend(m, &l); + if (r < 0) + return r; + + r = sd_bus_message_read_basic(m, 'b', &interactive); + if (r < 0) + return r; + + /* If single locale without variable name is provided, then we assume it is LANG=. */ + if (strv_length(l) == 1 && !strchr(*l, '=')) { + if (!locale_is_valid(*l)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data."); + + new_locale[VARIABLE_LANG] = strdup(*l); + if (!new_locale[VARIABLE_LANG]) + return -ENOMEM; + + l = strv_free(l); + } + + /* Check whether a variable is valid */ + STRV_FOREACH(i, l) { + bool valid = false; + + for (p = 0; p < _VARIABLE_LC_MAX; p++) { + size_t k; + const char *name; + + name = locale_variable_to_string(p); + assert(name); + + k = strlen(name); + if (startswith(*i, name) && + (*i)[k] == '=' && + locale_is_valid((*i) + k + 1)) { + valid = true; + + new_locale[p] = strdup((*i) + k + 1); + if (!new_locale[p]) + return -ENOMEM; + + break; + } + } + + if (!valid) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid Locale data."); + } + + /* If LANG was specified, but not LANGUAGE, check if we should + * set it based on the language fallback table. */ + if (!isempty(new_locale[VARIABLE_LANG]) && + isempty(new_locale[VARIABLE_LANGUAGE])) { + _cleanup_free_ char *language = NULL; + + (void) find_language_fallback(new_locale[VARIABLE_LANG], &language); + if (language) { + log_debug("Converted LANG=%s to LANGUAGE=%s", new_locale[VARIABLE_LANG], language); + free_and_replace(new_locale[VARIABLE_LANGUAGE], language); + } + } + + r = locale_read_data(c, m); + if (r < 0) { + log_error_errno(r, "Failed to read locale data: %m"); + return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to read locale data"); + } + + /* Merge with the current settings */ + for (p = 0; p < _VARIABLE_LC_MAX; p++) + if (!isempty(c->locale[p]) && isempty(new_locale[p])) { + new_locale[p] = strdup(c->locale[p]); + if (!new_locale[p]) + return -ENOMEM; + } + + locale_simplify(new_locale); + + for (p = 0; p < _VARIABLE_LC_MAX; p++) + if (!streq_ptr(c->locale[p], new_locale[p])) { + modified = true; + break; + } + + if (!modified) { + log_debug("Locale settings were not modified."); + return sd_bus_reply_method_return(m, NULL); + } + + r = bus_verify_polkit_async( + m, + CAP_SYS_ADMIN, + "org.freedesktop.locale1.set-locale", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + for (p = 0; p < _VARIABLE_LC_MAX; p++) + free_and_replace(c->locale[p], new_locale[p]); + + r = locale_write_data(c, &settings); + if (r < 0) { + log_error_errno(r, "Failed to set locale: %m"); + return sd_bus_error_set_errnof(error, r, "Failed to set locale: %m"); + } + + (void) locale_update_system_manager(c, sd_bus_message_get_bus(m)); + + if (settings) { + _cleanup_free_ char *line; + + line = strv_join(settings, ", "); + log_info("Changed locale to %s.", strnull(line)); + } else + log_info("Changed locale to unset."); + + (void) sd_bus_emit_properties_changed( + sd_bus_message_get_bus(m), + "/org/freedesktop/locale1", + "org.freedesktop.locale1", + "Locale", NULL); + + return sd_bus_reply_method_return(m, NULL); +} + +static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_error *error) { + Context *c = userdata; + const char *keymap, *keymap_toggle; + int convert, interactive, r; + + assert(m); + assert(c); + + r = sd_bus_message_read(m, "ssbb", &keymap, &keymap_toggle, &convert, &interactive); + if (r < 0) + return r; + + keymap = empty_to_null(keymap); + keymap_toggle = empty_to_null(keymap_toggle); + + r = vconsole_read_data(c, m); + if (r < 0) { + log_error_errno(r, "Failed to read virtual console keymap data: %m"); + return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to read virtual console keymap data"); + } + + if (streq_ptr(keymap, c->vc_keymap) && + streq_ptr(keymap_toggle, c->vc_keymap_toggle)) + return sd_bus_reply_method_return(m, NULL); + + if ((keymap && (!filename_is_valid(keymap) || !string_is_safe(keymap))) || + (keymap_toggle && (!filename_is_valid(keymap_toggle) || !string_is_safe(keymap_toggle)))) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Received invalid keymap data"); + + r = bus_verify_polkit_async( + m, + CAP_SYS_ADMIN, + "org.freedesktop.locale1.set-keyboard", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + if (free_and_strdup(&c->vc_keymap, keymap) < 0 || + free_and_strdup(&c->vc_keymap_toggle, keymap_toggle) < 0) + return -ENOMEM; + + r = vconsole_write_data(c); + if (r < 0) { + log_error_errno(r, "Failed to set virtual console keymap: %m"); + return sd_bus_error_set_errnof(error, r, "Failed to set virtual console keymap: %m"); + } + + log_info("Changed virtual console keymap to '%s' toggle '%s'", + strempty(c->vc_keymap), strempty(c->vc_keymap_toggle)); + + (void) vconsole_reload(sd_bus_message_get_bus(m)); + + (void) sd_bus_emit_properties_changed( + sd_bus_message_get_bus(m), + "/org/freedesktop/locale1", + "org.freedesktop.locale1", + "VConsoleKeymap", "VConsoleKeymapToggle", NULL); + + if (convert) { + r = vconsole_convert_to_x11_and_emit(c, m); + if (r < 0) + log_error_errno(r, "Failed to convert keymap data: %m"); + } + + return sd_bus_reply_method_return(m, NULL); +} + +#if HAVE_XKBCOMMON + +_printf_(3, 0) +static void log_xkb(struct xkb_context *ctx, enum xkb_log_level lvl, const char *format, va_list args) { + const char *fmt; + + fmt = strjoina("libxkbcommon: ", format); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + log_internalv(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, fmt, args); +#pragma GCC diagnostic pop +} + +#define LOAD_SYMBOL(symbol, dl, name) \ + ({ \ + (symbol) = (typeof(symbol)) dlvsym((dl), (name), "V_0.5.0"); \ + (symbol) ? 0 : -EOPNOTSUPP; \ + }) + +static int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) { + + /* We dlopen() the library in order to make the dependency soft. The library (and what it pulls in) is huge + * after all, hence let's support XKB maps when the library is around, and refuse otherwise. The function + * pointers to the shared library are below: */ + + struct xkb_context* (*symbol_xkb_context_new)(enum xkb_context_flags flags) = NULL; + void (*symbol_xkb_context_unref)(struct xkb_context *context) = NULL; + void (*symbol_xkb_context_set_log_fn)(struct xkb_context *context, void (*log_fn)(struct xkb_context *context, enum xkb_log_level level, const char *format, va_list args)) = NULL; + struct xkb_keymap* (*symbol_xkb_keymap_new_from_names)(struct xkb_context *context, const struct xkb_rule_names *names, enum xkb_keymap_compile_flags flags) = NULL; + void (*symbol_xkb_keymap_unref)(struct xkb_keymap *keymap) = NULL; + + const struct xkb_rule_names rmlvo = { + .model = model, + .layout = layout, + .variant = variant, + .options = options, + }; + struct xkb_context *ctx = NULL; + struct xkb_keymap *km = NULL; + void *dl; + int r; + + /* Compile keymap from RMLVO information to check out its validity */ + + dl = dlopen("libxkbcommon.so.0", RTLD_LAZY); + if (!dl) + return -EOPNOTSUPP; + + r = LOAD_SYMBOL(symbol_xkb_context_new, dl, "xkb_context_new"); + if (r < 0) + goto finish; + + r = LOAD_SYMBOL(symbol_xkb_context_unref, dl, "xkb_context_unref"); + if (r < 0) + goto finish; + + r = LOAD_SYMBOL(symbol_xkb_context_set_log_fn, dl, "xkb_context_set_log_fn"); + if (r < 0) + goto finish; + + r = LOAD_SYMBOL(symbol_xkb_keymap_new_from_names, dl, "xkb_keymap_new_from_names"); + if (r < 0) + goto finish; + + r = LOAD_SYMBOL(symbol_xkb_keymap_unref, dl, "xkb_keymap_unref"); + if (r < 0) + goto finish; + + ctx = symbol_xkb_context_new(XKB_CONTEXT_NO_ENVIRONMENT_NAMES); + if (!ctx) { + r = -ENOMEM; + goto finish; + } + + symbol_xkb_context_set_log_fn(ctx, log_xkb); + + km = symbol_xkb_keymap_new_from_names(ctx, &rmlvo, XKB_KEYMAP_COMPILE_NO_FLAGS); + if (!km) { + r = -EINVAL; + goto finish; + } + + r = 0; + +finish: + if (symbol_xkb_keymap_unref && km) + symbol_xkb_keymap_unref(km); + + if (symbol_xkb_context_unref && ctx) + symbol_xkb_context_unref(ctx); + + (void) dlclose(dl); + return r; +} + +#else + +static int verify_xkb_rmlvo(const char *model, const char *layout, const char *variant, const char *options) { + return 0; +} + +#endif + +static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_error *error) { + Context *c = userdata; + const char *layout, *model, *variant, *options; + int convert, interactive, r; + + assert(m); + assert(c); + + r = sd_bus_message_read(m, "ssssbb", &layout, &model, &variant, &options, &convert, &interactive); + if (r < 0) + return r; + + layout = empty_to_null(layout); + model = empty_to_null(model); + variant = empty_to_null(variant); + options = empty_to_null(options); + + r = x11_read_data(c, m); + if (r < 0) { + log_error_errno(r, "Failed to read x11 keyboard layout data: %m"); + return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Failed to read x11 keyboard layout data"); + } + + if (streq_ptr(layout, c->x11_layout) && + streq_ptr(model, c->x11_model) && + streq_ptr(variant, c->x11_variant) && + streq_ptr(options, c->x11_options)) + return sd_bus_reply_method_return(m, NULL); + + if ((layout && !string_is_safe(layout)) || + (model && !string_is_safe(model)) || + (variant && !string_is_safe(variant)) || + (options && !string_is_safe(options))) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Received invalid keyboard data"); + + r = verify_xkb_rmlvo(model, layout, variant, options); + if (r < 0) { + log_error_errno(r, "Cannot compile XKB keymap for new x11 keyboard layout ('%s' / '%s' / '%s' / '%s'): %m", + strempty(model), strempty(layout), strempty(variant), strempty(options)); + + if (r == -EOPNOTSUPP) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Local keyboard configuration not supported on this system."); + + return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Specified keymap cannot be compiled, refusing as invalid."); + } + + r = bus_verify_polkit_async( + m, + CAP_SYS_ADMIN, + "org.freedesktop.locale1.set-keyboard", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + if (free_and_strdup(&c->x11_layout, layout) < 0 || + free_and_strdup(&c->x11_model, model) < 0 || + free_and_strdup(&c->x11_variant, variant) < 0 || + free_and_strdup(&c->x11_options, options) < 0) + return -ENOMEM; + + r = x11_write_data(c); + if (r < 0) { + log_error_errno(r, "Failed to set X11 keyboard layout: %m"); + return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %m"); + } + + log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'", + strempty(c->x11_layout), + strempty(c->x11_model), + strempty(c->x11_variant), + strempty(c->x11_options)); + + (void) sd_bus_emit_properties_changed( + sd_bus_message_get_bus(m), + "/org/freedesktop/locale1", + "org.freedesktop.locale1", + "X11Layout", "X11Model", "X11Variant", "X11Options", NULL); + + if (convert) { + r = x11_convert_to_vconsole_and_emit(c, m); + if (r < 0) + log_error_errno(r, "Failed to convert keymap data: %m"); + } + + return sd_bus_reply_method_return(m, NULL); +} + +static const sd_bus_vtable locale_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Locale", "as", property_get_locale, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("X11Layout", "s", property_get_xkb, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("X11Model", "s", property_get_xkb, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("X11Variant", "s", property_get_xkb, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("X11Options", "s", property_get_xkb, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("VConsoleKeymap", "s", property_get_vconsole, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("VConsoleKeymapToggle", "s", property_get_vconsole, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_METHOD("SetLocale", "asb", NULL, method_set_locale, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetVConsoleKeyboard", "ssbb", NULL, method_set_vc_keyboard, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetX11Keyboard", "ssssbb", NULL, method_set_x11_keyboard, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END +}; + +static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + assert(c); + assert(event); + assert(_bus); + + r = sd_bus_default_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to get system bus connection: %m"); + + r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c); + if (r < 0) + return log_error_errno(r, "Failed to register object: %m"); + + r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.locale1", 0, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + r = sd_bus_attach_event(bus, event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + *_bus = TAKE_PTR(bus); + + return 0; +} + +static int run(int argc, char *argv[]) { + _cleanup_(context_clear) Context context = { + .locale_mtime = USEC_INFINITY, + .vc_mtime = USEC_INFINITY, + .x11_mtime = USEC_INFINITY, + }; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + log_setup_service(); + + umask(0022); + mac_selinux_init(); + + if (argc != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + (void) sd_event_set_watchdog(event, true); + + r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to install SIGINT handler: %m"); + + r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to install SIGTERM handler: %m"); + + r = connect_bus(&context, event, &bus); + if (r < 0) + return r; + + r = bus_event_loop_with_idle(event, bus, "org.freedesktop.locale1", DEFAULT_EXIT_USEC, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/locale/meson.build b/src/locale/meson.build new file mode 100644 index 00000000..e87a10eb --- /dev/null +++ b/src/locale/meson.build @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +systemd_localed_sources = files(''' + localed.c + keymap-util.c + keymap-util.h +'''.split()) + +localectl_sources = files('localectl.c') + +if conf.get('ENABLE_LOCALED') == 1 + install_data('org.freedesktop.locale1.conf', + install_dir : dbuspolicydir) + install_data('org.freedesktop.locale1.service', + install_dir : dbussystemservicedir) + install_data('org.freedesktop.locale1.policy', + install_dir : polkitpolicydir) +endif + +# If you know a way that allows the same variables to be used +# in sources list and concatenated to a string for test_env, +# let me know. +kbd_model_map = join_paths(meson.current_source_dir(), 'kbd-model-map') +language_fallback_map = join_paths(meson.current_source_dir(), 'language-fallback-map') + +if conf.get('ENABLE_LOCALED') == 1 + install_data('kbd-model-map', + 'language-fallback-map', + install_dir : pkgdatadir) +endif + +tests += [ + [['src/locale/test-keymap-util.c', + 'src/locale/keymap-util.c', + 'src/locale/keymap-util.h'], + [libshared], + [libdl]], +] diff --git a/src/locale/org.freedesktop.locale1.conf b/src/locale/org.freedesktop.locale1.conf new file mode 100644 index 00000000..d74cbc11 --- /dev/null +++ b/src/locale/org.freedesktop.locale1.conf @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/locale/org.freedesktop.locale1.policy b/src/locale/org.freedesktop.locale1.policy new file mode 100644 index 00000000..f9241749 --- /dev/null +++ b/src/locale/org.freedesktop.locale1.policy @@ -0,0 +1,42 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Set system locale + Authentication is required to set the system locale. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.locale1.set-keyboard + + + + Set system keyboard settings + Authentication is required to set the system keyboard settings. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + diff --git a/src/locale/org.freedesktop.locale1.service b/src/locale/org.freedesktop.locale1.service new file mode 100644 index 00000000..b15d3954 --- /dev/null +++ b/src/locale/org.freedesktop.locale1.service @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.locale1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.locale1.service diff --git a/src/locale/test-keymap-util.c b/src/locale/test-keymap-util.c new file mode 100644 index 00000000..f96f5b07 --- /dev/null +++ b/src/locale/test-keymap-util.c @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "keymap-util.h" +#include "log.h" +#include "string-util.h" +#include "tests.h" + +static void test_find_language_fallback(void) { + _cleanup_free_ char *ans = NULL, *ans2 = NULL; + + log_info("/*** %s ***/", __func__); + + assert_se(find_language_fallback("foobar", &ans) == 0); + assert_se(ans == NULL); + + assert_se(find_language_fallback("csb", &ans) == 0); + assert_se(ans == NULL); + + assert_se(find_language_fallback("csb_PL", &ans) == 1); + assert_se(streq(ans, "csb:pl")); + + assert_se(find_language_fallback("szl_PL", &ans2) == 1); + assert_se(streq(ans2, "szl:pl")); +} + +static void test_find_converted_keymap(void) { + _cleanup_free_ char *ans = NULL, *ans2 = NULL; + int r; + + log_info("/*** %s ***/", __func__); + + assert_se(find_converted_keymap("pl", "foobar", &ans) == 0); + assert_se(ans == NULL); + + r = find_converted_keymap("pl", NULL, &ans); + if (r == 0) { + log_info("Skipping rest of %s: keymaps are not installed", __func__); + return; + } + + assert_se(r == 1); + assert_se(streq(ans, "pl")); + + assert_se(find_converted_keymap("pl", "dvorak", &ans2) == 1); + assert_se(streq(ans2, "pl-dvorak")); +} + +static void test_find_legacy_keymap(void) { + Context c = {}; + _cleanup_free_ char *ans = NULL, *ans2 = NULL; + + log_info("/*** %s ***/", __func__); + + c.x11_layout = (char*) "foobar"; + assert_se(find_legacy_keymap(&c, &ans) == 0); + assert_se(ans == NULL); + + c.x11_layout = (char*) "pl"; + assert_se(find_legacy_keymap(&c, &ans) == 1); + assert_se(streq(ans, "pl2")); + + c.x11_layout = (char*) "pl,ru"; + assert_se(find_legacy_keymap(&c, &ans2) == 1); + assert_se(streq(ans, "pl2")); +} + +static void test_vconsole_convert_to_x11(void) { + _cleanup_(context_clear) Context c = {}; + + log_info("/*** %s ***/", __func__); + + log_info("/* test emptying first (:) */"); + assert_se(free_and_strdup(&c.x11_layout, "foo") >= 0); + assert_se(free_and_strdup(&c.x11_variant, "bar") >= 0); + assert_se(vconsole_convert_to_x11(&c) == 1); + assert_se(c.x11_layout == NULL); + assert_se(c.x11_variant == NULL); + + log_info("/* test emptying second (:) */"); + + assert_se(vconsole_convert_to_x11(&c) == 0); + assert_se(c.x11_layout == NULL); + assert_se(c.x11_variant == NULL); + + log_info("/* test without variant, new mapping (es:) */"); + assert_se(free_and_strdup(&c.vc_keymap, "es") >= 0); + + assert_se(vconsole_convert_to_x11(&c) == 1); + assert_se(streq(c.x11_layout, "es")); + assert_se(c.x11_variant == NULL); + + log_info("/* test with known variant, new mapping (es:dvorak) */"); + assert_se(free_and_strdup(&c.vc_keymap, "es-dvorak") >= 0); + + assert_se(vconsole_convert_to_x11(&c) == 0); // FIXME + assert_se(streq(c.x11_layout, "es")); + assert_se(c.x11_variant == NULL); // FIXME: "dvorak" + + log_info("/* test with old mapping (fr:latin9) */"); + assert_se(free_and_strdup(&c.vc_keymap, "fr-latin9") >= 0); + + assert_se(vconsole_convert_to_x11(&c) == 1); + assert_se(streq(c.x11_layout, "fr")); + assert_se(streq(c.x11_variant, "latin9")); + + log_info("/* test with a compound mapping (ru,us) */"); + assert_se(free_and_strdup(&c.vc_keymap, "ru") >= 0); + + assert_se(vconsole_convert_to_x11(&c) == 1); + assert_se(streq(c.x11_layout, "ru,us")); + assert_se(c.x11_variant == NULL); + + log_info("/* test with a simple mapping (us) */"); + assert_se(free_and_strdup(&c.vc_keymap, "us") >= 0); + + assert_se(vconsole_convert_to_x11(&c) == 1); + assert_se(streq(c.x11_layout, "us")); + assert_se(c.x11_variant == NULL); +} + +static void test_x11_convert_to_vconsole(void) { + _cleanup_(context_clear) Context c = {}; + int r; + + log_info("/*** %s ***/", __func__); + + log_info("/* test emptying first (:) */"); + assert_se(free_and_strdup(&c.vc_keymap, "foobar") >= 0); + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(c.vc_keymap == NULL); + + log_info("/* test emptying second (:) */"); + + assert_se(x11_convert_to_vconsole(&c) == 0); + assert_se(c.vc_keymap == NULL); + + log_info("/* test without variant, new mapping (es:) */"); + assert_se(free_and_strdup(&c.x11_layout, "es") >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(streq(c.vc_keymap, "es")); + + log_info("/* test with unknown variant, new mapping (es:foobar) */"); + assert_se(free_and_strdup(&c.x11_variant, "foobar") >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 0); + assert_se(streq(c.vc_keymap, "es")); + + log_info("/* test with known variant, new mapping (es:dvorak) */"); + assert_se(free_and_strdup(&c.x11_variant, "dvorak") >= 0); + + r = x11_convert_to_vconsole(&c); + if (r == 0) { + log_info("Skipping rest of %s: keymaps are not installed", __func__); + return; + } + + assert_se(r == 1); + assert_se(streq(c.vc_keymap, "es-dvorak")); + + log_info("/* test with old mapping (fr:latin9) */"); + assert_se(free_and_strdup(&c.x11_layout, "fr") >= 0); + assert_se(free_and_strdup(&c.x11_variant, "latin9") >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(streq(c.vc_keymap, "fr-latin9")); + + log_info("/* test with a compound mapping (us,ru:) */"); + assert_se(free_and_strdup(&c.x11_layout, "us,ru") >= 0); + assert_se(free_and_strdup(&c.x11_variant, NULL) >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(streq(c.vc_keymap, "us")); + + log_info("/* test with a compound mapping (ru,us:) */"); + assert_se(free_and_strdup(&c.x11_layout, "ru,us") >= 0); + assert_se(free_and_strdup(&c.x11_variant, NULL) >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 1); + assert_se(streq(c.vc_keymap, "ru")); + + /* https://bugzilla.redhat.com/show_bug.cgi?id=1333998 */ + log_info("/* test with a simple new mapping (ru:) */"); + assert_se(free_and_strdup(&c.x11_layout, "ru") >= 0); + assert_se(free_and_strdup(&c.x11_variant, NULL) >= 0); + + assert_se(x11_convert_to_vconsole(&c) == 0); + assert_se(streq(c.vc_keymap, "ru")); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_find_language_fallback(); + test_find_converted_keymap(); + test_find_legacy_keymap(); + + test_vconsole_convert_to_x11(); + test_x11_convert_to_vconsole(); + + return 0; +} diff --git a/src/login/70-power-switch.rules b/src/login/70-power-switch.rules new file mode 100644 index 00000000..d69e65b3 --- /dev/null +++ b/src/login/70-power-switch.rules @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +ACTION=="remove", GOTO="power_switch_end" + +SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_SWITCH}=="1", TAG+="power-switch" +SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_KEY}=="1", TAG+="power-switch" + +LABEL="power_switch_end" diff --git a/src/login/70-uaccess.rules.m4 b/src/login/70-uaccess.rules.m4 new file mode 100644 index 00000000..4bb144a9 --- /dev/null +++ b/src/login/70-uaccess.rules.m4 @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +ACTION=="remove", GOTO="uaccess_end" +ENV{MAJOR}=="", GOTO="uaccess_end" + +# PTP/MTP protocol devices, cameras, portable media players +SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="uaccess" + +# Digicams with proprietary protocol +ENV{ID_GPHOTO2}=="?*", TAG+="uaccess" + +# SCSI and USB scanners +ENV{libsane_matched}=="yes", TAG+="uaccess" + +# HPLIP devices (necessary for ink level check and HP tool maintenance) +ENV{ID_HPLIP}=="1", TAG+="uaccess" + +# optical drives +SUBSYSTEM=="block", ENV{ID_CDROM}=="1", TAG+="uaccess" +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", TAG+="uaccess" + +# Sound devices +SUBSYSTEM=="sound", TAG+="uaccess", \ + OPTIONS+="static_node=snd/timer", OPTIONS+="static_node=snd/seq" + +# ffado is an userspace driver for firewire sound cards +SUBSYSTEM=="firewire", ENV{ID_FFADO}=="1", TAG+="uaccess" + +# Webcams, frame grabber, TV cards +SUBSYSTEM=="video4linux", TAG+="uaccess" +SUBSYSTEM=="dvb", TAG+="uaccess" + +# IIDC devices: industrial cameras and some webcams +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", TAG+="uaccess" +SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", TAG+="uaccess" +# AV/C devices: camcorders, set-top boxes, TV sets, audio devices, and more +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", TAG+="uaccess" +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", TAG+="uaccess" + +# DRI video devices +SUBSYSTEM=="drm", KERNEL=="card*", TAG+="uaccess" +m4_ifdef(`GROUP_RENDER_UACCESS',`` +# DRI render nodes +SUBSYSTEM=="drm", KERNEL=="renderD*", TAG+="uaccess"'' +)m4_dnl +m4_ifdef(`DEV_KVM_UACCESS',`` +# KVM +SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess"'' +)m4_dnl + +# smart-card readers +ENV{ID_SMARTCARD_READER}=="?*", TAG+="uaccess" + +# (USB) authentication devices +ENV{ID_SECURITY_TOKEN}=="?*", TAG+="uaccess" + +# PDA devices +ENV{ID_PDA}=="?*", TAG+="uaccess" + +# Programmable remote control +ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess" + +# joysticks +SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="?*", TAG+="uaccess" + +# color measurement devices +ENV{COLOR_MEASUREMENT_DEVICE}=="?*", TAG+="uaccess" + +# DDC/CI device, usually high-end monitors such as the DreamColor +ENV{DDC_DEVICE}=="?*", TAG+="uaccess" + +# media player raw devices (for user-mode drivers, Android SDK, etc.) +SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess" + +# software-defined radio communication devices +ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess" + +# 3D printers, CNC machines, laser cutters, 3D scanners, etc. +ENV{ID_MAKER_TOOL}=="?*", TAG+="uaccess" + +LABEL="uaccess_end" diff --git a/src/login/71-seat.rules.in b/src/login/71-seat.rules.in new file mode 100644 index 00000000..2bbd1836 --- /dev/null +++ b/src/login/71-seat.rules.in @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +ACTION=="remove", GOTO="seat_end" + +TAG=="uaccess", SUBSYSTEM!="sound", TAG+="seat" +SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat" +SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat" +SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat" + +# Assign keyboard and LCD backlights to the seat +SUBSYSTEM=="leds", TAG+="seat" +SUBSYSTEM=="backlight", TAG+="seat" + +# HyperV currently doesn't do DRM, hence we need to synthesize for HyperV's fb device instead +SUBSYSTEM=="graphics", KERNEL=="fb[0-9]", DRIVERS=="hyperv_fb", TAG+="master-of-seat" + +# Allow efifb / uvesafb to be a master if KMS is disabled +SUBSYSTEM=="graphics", KERNEL=="fb[0-9]", IMPORT{cmdline}="nomodeset", TAG+="master-of-seat" + +# Allow any PCI graphics device to be a master and synthesize a seat if KMS +# is disabled and the kernel doesn't have a driver that would work with this device. +SUBSYSTEM=="pci", ENV{ID_PCI_CLASS_FROM_DATABASE}=="Display controller", \ + ENV{DRIVER}=="", IMPORT{cmdline}="nomodeset", TAG+="seat", TAG+="master-of-seat" + +SUBSYSTEM=="drm", KERNEL=="card[0-9]*", TAG+="seat", TAG+="master-of-seat" +SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat" + +# 'Plugable' USB hub, sound, network, graphics adapter +SUBSYSTEM=="usb", ATTR{idVendor}=="2230", ATTR{idProduct}=="000[13]", ENV{ID_AUTOSEAT}="1" + +# qemu (version 2.4+) has a PCI-PCI bridge (-device pci-bridge-seat) to group +# devices belonging to one seat. See: +# http://git.qemu.org/?p=qemu.git;a=blob;f=docs/multiseat.txt +SUBSYSTEM=="pci", ATTR{vendor}=="0x1b36", ATTR{device}=="0x000a", TAG+="seat", ENV{ID_AUTOSEAT}="1" + +# Video adapter of Parallels virtualization platform +# Seat should be synthesized for it. But there's no in-kernel driver for this +# device so matching by vid/pid. +SUBSYSTEM=="pci", ATTRS{vendor}=="0x1ab8", ATTRS{device}=="0x4005", TAG+="seat", TAG+="master-of-seat" + +# Mimo 720, with integrated USB hub, displaylink graphics, and e2i +# touchscreen. This device carries no proper VID/PID in the USB hub, +# but it does carry good ID data in the graphics component, hence we +# check it from the parent. There's a bit of a race here however, +# given that the child devices might not exist yet at the time this +# rule is executed. To work around this we'll trigger the parent from +# the child if we notice that the parent wasn't recognized yet. + +# Match parent +SUBSYSTEM=="usb", ATTR{idVendor}=="058f", ATTR{idProduct}=="6254", \ + ATTR{%k.2/idVendor}=="17e9", ATTR{%k.2/idProduct}=="401a", ATTR{%k.2/product}=="mimo inc", \ + ENV{ID_AUTOSEAT}="1", ENV{ID_AVOID_LOOP}="1" + +# Match child, look for parent's ID_AVOID_LOOP +SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \ + ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \ + IMPORT{parent}="ID_AVOID_LOOP" + +# Match child, retrigger parent +SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \ + ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \ + ENV{ID_AVOID_LOOP}=="", \ + RUN+="@rootbindir@/udevadm trigger --parent-match=%p/.." + +TAG=="seat", ENV{ID_PATH}=="", IMPORT{builtin}="path_id" +TAG=="seat", ENV{ID_FOR_SEAT}=="", ENV{ID_PATH_TAG}!="", ENV{ID_FOR_SEAT}="$env{SUBSYSTEM}-$env{ID_PATH_TAG}" + +SUBSYSTEM=="input", ATTR{name}=="Wiebetech LLC Wiebetech", RUN+="@rootbindir@/loginctl lock-sessions" + +LABEL="seat_end" diff --git a/src/login/73-seat-late.rules.m4 b/src/login/73-seat-late.rules.m4 new file mode 100644 index 00000000..4db8d4dd --- /dev/null +++ b/src/login/73-seat-late.rules.m4 @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +ACTION=="remove", GOTO="seat_late_end" + +ENV{ID_SEAT}=="", ENV{ID_AUTOSEAT}=="1", ENV{ID_FOR_SEAT}!="", ENV{ID_SEAT}="seat-$env{ID_FOR_SEAT}" +ENV{ID_SEAT}=="", IMPORT{parent}="ID_SEAT" + +ENV{ID_SEAT}!="", TAG+="$env{ID_SEAT}" +m4_ifdef(`HAVE_ACL',`` +TAG=="uaccess", ENV{MAJOR}!="", RUN{builtin}+="uaccess"'' +)m4_dnl + +LABEL="seat_late_end" diff --git a/src/login/inhibit.c b/src/login/inhibit.c new file mode 100644 index 00000000..e2e1e036 --- /dev/null +++ b/src/login/inhibit.c @@ -0,0 +1,333 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "fd-util.h" +#include "format-table.h" +#include "format-util.h" +#include "main-func.h" +#include "pager.h" +#include "pretty-print.h" +#include "process-util.h" +#include "signal-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "user-util.h" +#include "util.h" + +static const char* arg_what = "idle:sleep:shutdown"; +static const char* arg_who = NULL; +static const char* arg_why = "Unknown reason"; +static const char* arg_mode = NULL; +static PagerFlags arg_pager_flags = 0; +static bool arg_legend = true; + +static enum { + ACTION_INHIBIT, + ACTION_LIST +} arg_action = ACTION_INHIBIT; + +static int inhibit(sd_bus *bus, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + int fd; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "Inhibit", + error, + &reply, + "ssss", arg_what, arg_who, arg_why, arg_mode); + if (r < 0) + return r; + + r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_UNIX_FD, &fd); + if (r < 0) + return r; + + r = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (r < 0) + return -errno; + + return r; +} + +static int print_inhibitors(sd_bus *bus) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + int r; + + (void) pager_open(arg_pager_flags); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ListInhibitors", + &error, + &reply, + ""); + if (r < 0) + return log_error_errno(r, "Could not get active inhibitors: %s", bus_error_message(&error, r)); + + table = table_new("who", "uid", "user", "pid", "comm", "what", "why", "mode"); + if (!table) + return log_oom(); + + /* If there's not enough space, shorten the "WHY" column, as it's little more than an explaining comment. */ + (void) table_set_weight(table, TABLE_HEADER_CELL(6), 20); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)"); + if (r < 0) + return bus_log_parse_error(r); + + for (;;) { + _cleanup_free_ char *comm = NULL, *u = NULL; + const char *what, *who, *why, *mode; + uint32_t uid, pid; + + r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + if (arg_mode && !streq(mode, arg_mode)) + continue; + + (void) get_process_comm(pid, &comm); + u = uid_to_name(uid); + + r = table_add_many(table, + TABLE_STRING, who, + TABLE_UID, (uid_t) uid, + TABLE_STRING, strna(u), + TABLE_PID, (pid_t) pid, + TABLE_STRING, strna(comm), + TABLE_STRING, what, + TABLE_STRING, why, + TABLE_STRING, mode); + if (r < 0) + return log_error_errno(r, "Failed to add table row: %m"); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + if (table_get_rows(table) > 1) { + r = table_set_sort(table, (size_t) 1, (size_t) 0, (size_t) 5, (size_t) 6, (size_t) -1); + if (r < 0) + return log_error_errno(r, "Failed to sort table: %m"); + + table_set_header(table, arg_legend); + + r = table_print(table, NULL); + if (r < 0) + return log_error_errno(r, "Failed to show table: %m"); + } + + if (arg_legend) { + if (table_get_rows(table) > 1) + printf("\n%zu inhibitors listed.\n", table_get_rows(table) - 1); + else + printf("No inhibitors.\n"); + } + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-inhibit", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n" + "\n%sExecute a process while inhibiting shutdown/sleep/idle.%s\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --no-legend Do not show the headers and footers\n" + " --what=WHAT Operations to inhibit, colon separated list of:\n" + " shutdown, sleep, idle, handle-power-key,\n" + " handle-suspend-key, handle-hibernate-key,\n" + " handle-lid-switch\n" + " --who=STRING A descriptive string who is inhibiting\n" + " --why=STRING A descriptive string why is being inhibited\n" + " --mode=MODE One of block or delay\n" + " --list List active inhibitors\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_WHAT, + ARG_WHO, + ARG_WHY, + ARG_MODE, + ARG_LIST, + ARG_NO_PAGER, + ARG_NO_LEGEND, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "what", required_argument, NULL, ARG_WHAT }, + { "who", required_argument, NULL, ARG_WHO }, + { "why", required_argument, NULL, ARG_WHY }, + { "mode", required_argument, NULL, ARG_MODE }, + { "list", no_argument, NULL, ARG_LIST }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "+h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_WHAT: + arg_what = optarg; + break; + + case ARG_WHO: + arg_who = optarg; + break; + + case ARG_WHY: + arg_why = optarg; + break; + + case ARG_MODE: + arg_mode = optarg; + break; + + case ARG_LIST: + arg_action = ACTION_LIST; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_NO_LEGEND: + arg_legend = false; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_action == ACTION_INHIBIT && optind == argc) + arg_action = ACTION_LIST; + + else if (arg_action == ACTION_INHIBIT && optind >= argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Missing command line to execute."); + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = sd_bus_default_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to connect to bus: %m"); + + if (arg_action == ACTION_LIST) + return print_inhibitors(bus); + else { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_strv_free_ char **arguments = NULL; + _cleanup_free_ char *w = NULL; + _cleanup_close_ int fd = -1; + pid_t pid; + + /* Ignore SIGINT and allow the forked process to receive it */ + (void) ignore_signals(SIGINT, -1); + + if (!arg_who) { + w = strv_join(argv + optind, " "); + if (!w) + return log_oom(); + + arg_who = w; + } + + if (!arg_mode) + arg_mode = "block"; + + fd = inhibit(bus, &error); + if (fd < 0) + return log_error_errno(fd, "Failed to inhibit: %s", bus_error_message(&error, fd)); + + arguments = strv_copy(argv + optind); + if (!arguments) + return log_oom(); + + r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + /* Child */ + execvp(arguments[0], arguments); + log_open(); + log_error_errno(errno, "Failed to execute %s: %m", argv[optind]); + _exit(EXIT_FAILURE); + } + + return wait_for_terminate_and_check(argv[optind], pid, WAIT_LOG); + } +} + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/login/loginctl.c b/src/login/loginctl.c new file mode 100644 index 00000000..6ffd135b --- /dev/null +++ b/src/login/loginctl.c @@ -0,0 +1,1546 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-unit-procs.h" +#include "bus-util.h" +#include "cgroup-show.h" +#include "cgroup-util.h" +#include "format-table.h" +#include "log.h" +#include "logs-show.h" +#include "macro.h" +#include "main-func.h" +#include "memory-util.h" +#include "pager.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "sigbus.h" +#include "signal-util.h" +#include "spawn-polkit-agent.h" +#include "string-table.h" +#include "strv.h" +#include "sysfs-show.h" +#include "terminal-util.h" +#include "unit-name.h" +#include "user-util.h" +#include "verbs.h" + +static char **arg_property = NULL; +static bool arg_all = false; +static bool arg_value = false; +static bool arg_full = false; +static PagerFlags arg_pager_flags = 0; +static bool arg_legend = true; +static const char *arg_kill_who = NULL; +static int arg_signal = SIGTERM; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static char *arg_host = NULL; +static bool arg_ask_password = true; +static unsigned arg_lines = 10; +static OutputMode arg_output = OUTPUT_SHORT; + +STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); + +static OutputFlags get_output_flags(void) { + + return + arg_all * OUTPUT_SHOW_ALL | + (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH | + colors_enabled() * OUTPUT_COLOR; +} + +static int get_session_path(sd_bus *bus, const char *session_id, sd_bus_error *error, char **path) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + char *ans; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "GetSession", + error, &reply, + "s", session_id); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "o", &ans); + if (r < 0) + return r; + + ans = strdup(ans); + if (!ans) + return -ENOMEM; + + *path = ans; + return 0; +} + +static int show_table(Table *table, const char *word) { + int r; + + assert(table); + assert(word); + + if (table_get_rows(table) > 1 || OUTPUT_MODE_IS_JSON(arg_output)) { + r = table_set_sort(table, (size_t) 0, (size_t) -1); + if (r < 0) + return log_error_errno(r, "Failed to sort table: %m"); + + table_set_header(table, arg_legend); + + if (OUTPUT_MODE_IS_JSON(arg_output)) + r = table_print_json(table, NULL, output_mode_to_json_format_flags(arg_output) | JSON_FORMAT_COLOR_AUTO); + else + r = table_print(table, NULL); + if (r < 0) + return log_error_errno(r, "Failed to show table: %m"); + } + + if (arg_legend) { + if (table_get_rows(table) > 1) + printf("\n%zu %s listed.\n", table_get_rows(table) - 1, word); + else + printf("No %s.\n", word); + } + + return 0; +} + +static int list_sessions(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + assert(argv); + + (void) pager_open(arg_pager_flags); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ListSessions", + &error, &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to list sessions: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, 'a', "(susso)"); + if (r < 0) + return bus_log_parse_error(r); + + table = table_new("session", "uid", "user", "seat", "tty"); + if (!table) + return log_oom(); + + /* Right-align the first two fields (since they are numeric) */ + (void) table_set_align_percent(table, TABLE_HEADER_CELL(0), 100); + (void) table_set_align_percent(table, TABLE_HEADER_CELL(1), 100); + + for (;;) { + _cleanup_(sd_bus_error_free) sd_bus_error error_tty = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_tty = NULL; + const char *id, *user, *seat, *object, *tty = NULL; + uint32_t uid; + + r = sd_bus_message_read(reply, "(susso)", &id, &uid, &user, &seat, &object); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + r = sd_bus_get_property( + bus, + "org.freedesktop.login1", + object, + "org.freedesktop.login1.Session", + "TTY", + &error_tty, + &reply_tty, + "s"); + if (r < 0) + log_warning_errno(r, "Failed to get TTY for session %s: %s", id, bus_error_message(&error_tty, r)); + else { + r = sd_bus_message_read(reply_tty, "s", &tty); + if (r < 0) + return bus_log_parse_error(r); + } + + r = table_add_many(table, + TABLE_STRING, id, + TABLE_UID, (uid_t) uid, + TABLE_STRING, user, + TABLE_STRING, seat, + TABLE_STRING, strna(tty)); + if (r < 0) + return log_error_errno(r, "Failed to add row to table: %m"); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return show_table(table, "sessions"); +} + +static int list_users(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + assert(argv); + + (void) pager_open(arg_pager_flags); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ListUsers", + &error, &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to list users: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, 'a', "(uso)"); + if (r < 0) + return bus_log_parse_error(r); + + table = table_new("uid", "user"); + if (!table) + return log_oom(); + + (void) table_set_align_percent(table, TABLE_HEADER_CELL(0), 100); + + for (;;) { + const char *user; + uint32_t uid; + + r = sd_bus_message_read(reply, "(uso)", &uid, &user, NULL); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + r = table_add_many(table, + TABLE_UID, (uid_t) uid, + TABLE_STRING, user); + if (r < 0) + return log_error_errno(r, "Failed to add row to table: %m"); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return show_table(table, "users"); +} + +static int list_seats(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + assert(argv); + + (void) pager_open(arg_pager_flags); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ListSeats", + &error, &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to list seats: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, 'a', "(so)"); + if (r < 0) + return bus_log_parse_error(r); + + table = table_new("seat"); + if (!table) + return log_oom(); + + for (;;) { + const char *seat; + + r = sd_bus_message_read(reply, "(so)", &seat, NULL); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + r = table_add_cell(table, NULL, TABLE_STRING, seat); + if (r < 0) + return log_error_errno(r, "Failed to add row to table: %m"); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return show_table(table, "seats"); +} + +static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit, pid_t leader) { + _cleanup_free_ char *cgroup = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + unsigned c; + int r; + + assert(bus); + assert(unit); + + r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup); + if (r < 0) + return r; + + if (isempty(cgroup)) + return 0; + + c = columns(); + if (c > 18) + c -= 18; + else + c = 0; + + r = unit_show_processes(bus, unit, cgroup, "\t\t ", c, get_output_flags(), &error); + if (r == -EBADR) { + + if (arg_transport == BUS_TRANSPORT_REMOTE) + return 0; + + /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */ + + if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0) + return 0; + + show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, &leader, leader > 0, get_output_flags()); + } else if (r < 0) + return log_error_errno(r, "Failed to dump process list: %s", bus_error_message(&error, r)); + + return 0; +} + +typedef struct SessionStatusInfo { + const char *id; + uid_t uid; + const char *name; + struct dual_timestamp timestamp; + unsigned vtnr; + const char *seat; + const char *tty; + const char *display; + bool remote; + const char *remote_host; + const char *remote_user; + const char *service; + pid_t leader; + const char *type; + const char *class; + const char *state; + const char *scope; + const char *desktop; +} SessionStatusInfo; + +typedef struct UserStatusInfo { + uid_t uid; + bool linger; + const char *name; + struct dual_timestamp timestamp; + const char *state; + char **sessions; + const char *display; + const char *slice; +} UserStatusInfo; + +typedef struct SeatStatusInfo { + const char *id; + const char *active_session; + char **sessions; +} SeatStatusInfo; + +static void user_status_info_clear(UserStatusInfo *info) { + if (info) { + strv_free(info->sessions); + zero(*info); + } +} + +static void seat_status_info_clear(SeatStatusInfo *info) { + if (info) { + strv_free(info->sessions); + zero(*info); + } +} + +static int prop_map_first_of_struct(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + const char *contents; + int r; + + r = sd_bus_message_peek_type(m, NULL, &contents); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, contents); + if (r < 0) + return r; + + r = sd_bus_message_read_basic(m, contents[0], userdata); + if (r < 0) + return r; + + r = sd_bus_message_skip(m, contents+1); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +static int prop_map_sessions_strv(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + const char *name; + int r; + + assert(bus); + assert(m); + + r = sd_bus_message_enter_container(m, 'a', "(so)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(m, "(so)", &name, NULL)) > 0) { + r = strv_extend(userdata, name); + if (r < 0) + return r; + } + if (r < 0) + return r; + + return sd_bus_message_exit_container(m); +} + +static int print_session_status_info(sd_bus *bus, const char *path, bool *new_line) { + + static const struct bus_properties_map map[] = { + { "Id", "s", NULL, offsetof(SessionStatusInfo, id) }, + { "Name", "s", NULL, offsetof(SessionStatusInfo, name) }, + { "TTY", "s", NULL, offsetof(SessionStatusInfo, tty) }, + { "Display", "s", NULL, offsetof(SessionStatusInfo, display) }, + { "RemoteHost", "s", NULL, offsetof(SessionStatusInfo, remote_host) }, + { "RemoteUser", "s", NULL, offsetof(SessionStatusInfo, remote_user) }, + { "Service", "s", NULL, offsetof(SessionStatusInfo, service) }, + { "Desktop", "s", NULL, offsetof(SessionStatusInfo, desktop) }, + { "Type", "s", NULL, offsetof(SessionStatusInfo, type) }, + { "Class", "s", NULL, offsetof(SessionStatusInfo, class) }, + { "Scope", "s", NULL, offsetof(SessionStatusInfo, scope) }, + { "State", "s", NULL, offsetof(SessionStatusInfo, state) }, + { "VTNr", "u", NULL, offsetof(SessionStatusInfo, vtnr) }, + { "Leader", "u", NULL, offsetof(SessionStatusInfo, leader) }, + { "Remote", "b", NULL, offsetof(SessionStatusInfo, remote) }, + { "Timestamp", "t", NULL, offsetof(SessionStatusInfo, timestamp.realtime) }, + { "TimestampMonotonic", "t", NULL, offsetof(SessionStatusInfo, timestamp.monotonic) }, + { "User", "(uo)", prop_map_first_of_struct, offsetof(SessionStatusInfo, uid) }, + { "Seat", "(so)", prop_map_first_of_struct, offsetof(SessionStatusInfo, seat) }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + char since1[FORMAT_TIMESTAMP_RELATIVE_MAX]; + char since2[FORMAT_TIMESTAMP_MAX]; + const char *s1, *s2; + SessionStatusInfo i = {}; + int r; + + r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i); + if (r < 0) + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); + + if (*new_line) + printf("\n"); + + *new_line = true; + + printf("%s - ", strna(i.id)); + + if (i.name) + printf("%s (%"PRIu32")\n", i.name, i.uid); + else + printf("%"PRIu32"\n", i.uid); + + s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime); + s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime); + + if (s1) + printf("\t Since: %s; %s\n", s2, s1); + else if (s2) + printf("\t Since: %s\n", s2); + + if (i.leader > 0) { + _cleanup_free_ char *t = NULL; + + printf("\t Leader: %"PRIu32, i.leader); + + get_process_comm(i.leader, &t); + if (t) + printf(" (%s)", t); + + printf("\n"); + } + + if (!isempty(i.seat)) { + printf("\t Seat: %s", i.seat); + + if (i.vtnr > 0) + printf("; vc%u", i.vtnr); + + printf("\n"); + } + + if (i.tty) + printf("\t TTY: %s\n", i.tty); + else if (i.display) + printf("\t Display: %s\n", i.display); + + if (i.remote_host && i.remote_user) + printf("\t Remote: %s@%s\n", i.remote_user, i.remote_host); + else if (i.remote_host) + printf("\t Remote: %s\n", i.remote_host); + else if (i.remote_user) + printf("\t Remote: user %s\n", i.remote_user); + else if (i.remote) + printf("\t Remote: Yes\n"); + + if (i.service) { + printf("\t Service: %s", i.service); + + if (i.type) + printf("; type %s", i.type); + + if (i.class) + printf("; class %s", i.class); + + printf("\n"); + } else if (i.type) { + printf("\t Type: %s", i.type); + + if (i.class) + printf("; class %s", i.class); + + printf("\n"); + } else if (i.class) + printf("\t Class: %s\n", i.class); + + if (!isempty(i.desktop)) + printf("\t Desktop: %s\n", i.desktop); + + if (i.state) + printf("\t State: %s\n", i.state); + + if (i.scope) { + printf("\t Unit: %s\n", i.scope); + show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader); + + if (arg_transport == BUS_TRANSPORT_LOCAL) { + + show_journal_by_unit( + stdout, + i.scope, + arg_output, + 0, + i.timestamp.monotonic, + arg_lines, + 0, + get_output_flags() | OUTPUT_BEGIN_NEWLINE, + SD_JOURNAL_LOCAL_ONLY, + true, + NULL); + } + } + + return 0; +} + +static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) { + + static const struct bus_properties_map map[] = { + { "Name", "s", NULL, offsetof(UserStatusInfo, name) }, + { "Linger", "b", NULL, offsetof(UserStatusInfo, linger) }, + { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) }, + { "State", "s", NULL, offsetof(UserStatusInfo, state) }, + { "UID", "u", NULL, offsetof(UserStatusInfo, uid) }, + { "Timestamp", "t", NULL, offsetof(UserStatusInfo, timestamp.realtime) }, + { "TimestampMonotonic", "t", NULL, offsetof(UserStatusInfo, timestamp.monotonic) }, + { "Display", "(so)", prop_map_first_of_struct, offsetof(UserStatusInfo, display) }, + { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(UserStatusInfo, sessions) }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + char since1[FORMAT_TIMESTAMP_RELATIVE_MAX]; + char since2[FORMAT_TIMESTAMP_MAX]; + const char *s1, *s2; + _cleanup_(user_status_info_clear) UserStatusInfo i = {}; + int r; + + r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, BUS_MAP_BOOLEAN_AS_BOOL, &error, &m, &i); + if (r < 0) + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); + + if (*new_line) + printf("\n"); + + *new_line = true; + + if (i.name) + printf("%s (%"PRIu32")\n", i.name, i.uid); + else + printf("%"PRIu32"\n", i.uid); + + s1 = format_timestamp_relative(since1, sizeof(since1), i.timestamp.realtime); + s2 = format_timestamp(since2, sizeof(since2), i.timestamp.realtime); + + if (s1) + printf("\t Since: %s; %s\n", s2, s1); + else if (s2) + printf("\t Since: %s\n", s2); + + if (!isempty(i.state)) + printf("\t State: %s\n", i.state); + + if (!strv_isempty(i.sessions)) { + char **l; + printf("\tSessions:"); + + STRV_FOREACH(l, i.sessions) + printf(" %s%s", + streq_ptr(*l, i.display) ? "*" : "", + *l); + + printf("\n"); + } + + printf("\t Linger: %s\n", yes_no(i.linger)); + + if (i.slice) { + printf("\t Unit: %s\n", i.slice); + show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0); + + show_journal_by_unit( + stdout, + i.slice, + arg_output, + 0, + i.timestamp.monotonic, + arg_lines, + 0, + get_output_flags() | OUTPUT_BEGIN_NEWLINE, + SD_JOURNAL_LOCAL_ONLY, + true, + NULL); + } + + return 0; +} + +static int print_seat_status_info(sd_bus *bus, const char *path, bool *new_line) { + + static const struct bus_properties_map map[] = { + { "Id", "s", NULL, offsetof(SeatStatusInfo, id) }, + { "ActiveSession", "(so)", prop_map_first_of_struct, offsetof(SeatStatusInfo, active_session) }, + { "Sessions", "a(so)", prop_map_sessions_strv, offsetof(SeatStatusInfo, sessions) }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(seat_status_info_clear) SeatStatusInfo i = {}; + int r; + + r = bus_map_all_properties(bus, "org.freedesktop.login1", path, map, 0, &error, &m, &i); + if (r < 0) + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); + + if (*new_line) + printf("\n"); + + *new_line = true; + + printf("%s\n", strna(i.id)); + + if (!strv_isempty(i.sessions)) { + char **l; + printf("\tSessions:"); + + STRV_FOREACH(l, i.sessions) { + if (streq_ptr(*l, i.active_session)) + printf(" *%s", *l); + else + printf(" %s", *l); + } + + printf("\n"); + } + + if (arg_transport == BUS_TRANSPORT_LOCAL) { + unsigned c; + + c = columns(); + if (c > 21) + c -= 21; + else + c = 0; + + printf("\t Devices:\n"); + + show_sysfs(i.id, "\t\t ", c, get_output_flags()); + } + + return 0; +} + +static int print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) { + char type; + const char *contents; + int r; + + assert(name); + assert(m); + + r = sd_bus_message_peek_type(m, &type, &contents); + if (r < 0) + return r; + + switch (type) { + + case SD_BUS_TYPE_STRUCT: + + if (contents[0] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) { + const char *s; + + r = sd_bus_message_read(m, "(so)", &s, NULL); + if (r < 0) + return bus_log_parse_error(r); + + if (all || !isempty(s)) + bus_print_property_value(name, expected_value, value, s); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "User")) { + uint32_t uid; + + r = sd_bus_message_read(m, "(uo)", &uid, NULL); + if (r < 0) + return bus_log_parse_error(r); + + if (!uid_is_valid(uid)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid user ID: " UID_FMT, + uid); + + bus_print_property_valuef(name, expected_value, value, UID_FMT, uid); + return 1; + } + break; + + case SD_BUS_TYPE_ARRAY: + + if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) { + const char *s; + bool space = false; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(so)"); + if (r < 0) + return bus_log_parse_error(r); + + if (!value) + printf("%s=", name); + + while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) { + printf("%s%s", space ? " " : "", s); + space = true; + } + + if (space || !value) + printf("\n"); + + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + } + break; + } + + return 0; +} + +static int show_properties(sd_bus *bus, const char *path, bool *new_line) { + int r; + + assert(bus); + assert(path); + assert(new_line); + + if (*new_line) + printf("\n"); + + *new_line = true; + + r = bus_print_all_properties(bus, "org.freedesktop.login1", path, print_property, arg_property, arg_value, arg_all, NULL); + if (r < 0) + return bus_log_parse_error(r); + + return 0; +} + +static int show_session(int argc, char *argv[], void *userdata) { + bool properties, new_line = false; + sd_bus *bus = userdata; + int r, i; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + + assert(bus); + assert(argv); + + properties = !strstr(argv[0], "status"); + + (void) pager_open(arg_pager_flags); + + if (argc <= 1) { + /* If no argument is specified inspect the manager itself */ + if (properties) + return show_properties(bus, "/org/freedesktop/login1", &new_line); + + return print_session_status_info(bus, "/org/freedesktop/login1/session/auto", &new_line); + } + + for (i = 1; i < argc; i++) { + r = get_session_path(bus, argv[i], &error, &path); + if (r < 0) + return log_error_errno(r, "Failed to get session path: %s", bus_error_message(&error, r)); + + if (properties) + r = show_properties(bus, path, &new_line); + else + r = print_session_status_info(bus, path, &new_line); + + if (r < 0) + return r; + } + + return 0; +} + +static int show_user(int argc, char *argv[], void *userdata) { + bool properties, new_line = false; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + assert(argv); + + properties = !strstr(argv[0], "status"); + + (void) pager_open(arg_pager_flags); + + if (argc <= 1) { + /* If no argument is specified inspect the manager itself */ + if (properties) + return show_properties(bus, "/org/freedesktop/login1", &new_line); + + return print_user_status_info(bus, "/org/freedesktop/login1/user/self", &new_line); + } + + for (i = 1; i < argc; i++) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL; + const char *path = NULL; + uid_t uid; + + r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0); + if (r < 0) + return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "GetUser", + &error, &reply, + "u", (uint32_t) uid); + if (r < 0) + return log_error_errno(r, "Failed to get user: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "o", &path); + if (r < 0) + return bus_log_parse_error(r); + + if (properties) + r = show_properties(bus, path, &new_line); + else + r = print_user_status_info(bus, path, &new_line); + + if (r < 0) + return r; + } + + return 0; +} + +static int show_seat(int argc, char *argv[], void *userdata) { + bool properties, new_line = false; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + assert(argv); + + properties = !strstr(argv[0], "status"); + + (void) pager_open(arg_pager_flags); + + if (argc <= 1) { + /* If no argument is specified inspect the manager itself */ + if (properties) + return show_properties(bus, "/org/freedesktop/login1", &new_line); + + return print_seat_status_info(bus, "/org/freedesktop/login1/seat/auto", &new_line); + } + + for (i = 1; i < argc; i++) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message * reply = NULL; + const char *path = NULL; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "GetSeat", + &error, &reply, + "s", argv[i]); + if (r < 0) + return log_error_errno(r, "Failed to get seat: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "o", &path); + if (r < 0) + return bus_log_parse_error(r); + + if (properties) + r = show_properties(bus, path, &new_line); + else + r = print_seat_status_info(bus, path, &new_line); + + if (r < 0) + return r; + } + + return 0; +} + +static int activate(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + assert(argv); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + if (argc < 2) { + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1/session/auto", + "org.freedesktop.login1.Session", + streq(argv[0], "lock-session") ? "Lock" : + streq(argv[0], "unlock-session") ? "Unlock" : + streq(argv[0], "terminate-session") ? "Terminate" : + "Activate", + &error, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); + + return 0; + } + + for (i = 1; i < argc; i++) { + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + streq(argv[0], "lock-session") ? "LockSession" : + streq(argv[0], "unlock-session") ? "UnlockSession" : + streq(argv[0], "terminate-session") ? "TerminateSession" : + "ActivateSession", + &error, NULL, + "s", argv[i]); + if (r < 0) + return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int kill_session(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + assert(argv); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + if (!arg_kill_who) + arg_kill_who = "all"; + + for (i = 1; i < argc; i++) { + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "KillSession", + &error, NULL, + "ssi", argv[i], arg_kill_who, arg_signal); + if (r < 0) + return log_error_errno(r, "Could not kill session: %s", bus_error_message(&error, -r)); + } + + return 0; +} + +static int enable_linger(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + char* short_argv[3]; + bool b; + int r, i; + + assert(bus); + assert(argv); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + b = streq(argv[0], "enable-linger"); + + if (argc < 2) { + /* No argument? Let's use an empty user name, + * then logind will use our user. */ + + short_argv[0] = argv[0]; + short_argv[1] = (char*) ""; + short_argv[2] = NULL; + argv = short_argv; + argc = 2; + } + + for (i = 1; i < argc; i++) { + uid_t uid; + + if (isempty(argv[i])) + uid = UID_INVALID; + else { + r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0); + if (r < 0) + return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); + } + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetUserLinger", + &error, NULL, + "ubb", (uint32_t) uid, b, true); + if (r < 0) + return log_error_errno(r, "Could not enable linger: %s", bus_error_message(&error, -r)); + } + + return 0; +} + +static int terminate_user(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + assert(argv); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + for (i = 1; i < argc; i++) { + uid_t uid; + + r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0); + if (r < 0) + return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "TerminateUser", + &error, NULL, + "u", (uint32_t) uid); + if (r < 0) + return log_error_errno(r, "Could not terminate user: %s", bus_error_message(&error, -r)); + } + + return 0; +} + +static int kill_user(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + assert(argv); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + if (!arg_kill_who) + arg_kill_who = "all"; + + for (i = 1; i < argc; i++) { + uid_t uid; + + r = get_user_creds((const char**) (argv+i), &uid, NULL, NULL, NULL, 0); + if (r < 0) + return log_error_errno(r, "Failed to look up user %s: %m", argv[i]); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "KillUser", + &error, NULL, + "ui", (uint32_t) uid, arg_signal); + if (r < 0) + return log_error_errno(r, "Could not kill user: %s", bus_error_message(&error, -r)); + } + + return 0; +} + +static int attach(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + assert(argv); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + for (i = 2; i < argc; i++) { + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "AttachDevice", + &error, NULL, + "ssb", argv[1], argv[i], true); + + if (r < 0) + return log_error_errno(r, "Could not attach device: %s", bus_error_message(&error, -r)); + } + + return 0; +} + +static int flush_devices(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + assert(argv); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "FlushDevices", + &error, NULL, + "b", true); + if (r < 0) + return log_error_errno(r, "Could not flush devices: %s", bus_error_message(&error, -r)); + + return 0; +} + +static int lock_sessions(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + assert(argv); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + streq(argv[0], "lock-sessions") ? "LockSessions" : "UnlockSessions", + &error, NULL, + NULL); + if (r < 0) + return log_error_errno(r, "Could not lock sessions: %s", bus_error_message(&error, -r)); + + return 0; +} + +static int terminate_seat(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + assert(argv); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + for (i = 1; i < argc; i++) { + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "TerminateSeat", + &error, NULL, + "s", argv[i]); + if (r < 0) + return log_error_errno(r, "Could not terminate seat: %s", bus_error_message(&error, -r)); + } + + return 0; +} + +static int help(int argc, char *argv[], void *userdata) { + _cleanup_free_ char *link = NULL; + int r; + + (void) pager_open(arg_pager_flags); + + r = terminal_urlify_man("loginctl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n\n" + "%sSend control commands to or query the login manager.%s\n" + "\nSession Commands:\n" + " list-sessions List sessions\n" + " session-status [ID...] Show session status\n" + " show-session [ID...] Show properties of sessions or the manager\n" + " activate [ID] Activate a session\n" + " lock-session [ID...] Screen lock one or more sessions\n" + " unlock-session [ID...] Screen unlock one or more sessions\n" + " lock-sessions Screen lock all current sessions\n" + " unlock-sessions Screen unlock all current sessions\n" + " terminate-session ID... Terminate one or more sessions\n" + " kill-session ID... Send signal to processes of a session\n" + "\nUser Commands:\n" + " list-users List users\n" + " user-status [USER...] Show user status\n" + " show-user [USER...] Show properties of users or the manager\n" + " enable-linger [USER...] Enable linger state of one or more users\n" + " disable-linger [USER...] Disable linger state of one or more users\n" + " terminate-user USER... Terminate all sessions of one or more users\n" + " kill-user USER... Send signal to processes of a user\n" + "\nSeat Commands:\n" + " list-seats List seats\n" + " seat-status [NAME...] Show seat status\n" + " show-seat [NAME...] Show properties of seats or the manager\n" + " attach NAME DEVICE... Attach one or more devices to a seat\n" + " flush-devices Flush all device associations\n" + " terminate-seat NAME... Terminate all sessions on one or more seats\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --no-legend Do not show the headers and footers\n" + " --no-ask-password Don't prompt for password\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " -p --property=NAME Show only properties by this name\n" + " -a --all Show all properties, including empty ones\n" + " --value When showing properties, only print the value\n" + " -l --full Do not ellipsize output\n" + " --kill-who=WHO Who to send signal to\n" + " -s --signal=SIGNAL Which signal to send\n" + " -n --lines=INTEGER Number of journal entries to show\n" + " -o --output=STRING Change journal output mode (short, short-precise,\n" + " short-iso, short-iso-precise, short-full,\n" + " short-monotonic, short-unix, verbose, export,\n" + " json, json-pretty, json-sse, json-seq, cat,\n" + " with-unit)\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_VALUE, + ARG_NO_PAGER, + ARG_NO_LEGEND, + ARG_KILL_WHO, + ARG_NO_ASK_PASSWORD, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "property", required_argument, NULL, 'p' }, + { "all", no_argument, NULL, 'a' }, + { "value", no_argument, NULL, ARG_VALUE }, + { "full", no_argument, NULL, 'l' }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, + { "kill-who", required_argument, NULL, ARG_KILL_WHO }, + { "signal", required_argument, NULL, 's' }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "lines", required_argument, NULL, 'n' }, + { "output", required_argument, NULL, 'o' }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hp:als:H:M:n:o:", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(0, NULL, NULL); + + case ARG_VERSION: + return version(); + + case 'p': { + r = strv_extend(&arg_property, optarg); + if (r < 0) + return log_oom(); + + /* If the user asked for a particular + * property, show it to him, even if it is + * empty. */ + arg_all = true; + break; + } + + case 'a': + arg_all = true; + break; + + case ARG_VALUE: + arg_value = true; + break; + + case 'l': + arg_full = true; + break; + + case 'n': + if (safe_atou(optarg, &arg_lines) < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse lines '%s'", optarg); + break; + + case 'o': + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX); + return 0; + } + + arg_output = output_mode_from_string(optarg); + if (arg_output < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown output '%s'.", optarg); + + if (OUTPUT_MODE_IS_JSON(arg_output)) + arg_legend = false; + + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_NO_LEGEND: + arg_legend = false; + break; + + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + + case ARG_KILL_WHO: + arg_kill_who = optarg; + break; + + case 's': + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(signal, int, _NSIG); + return 0; + } + + arg_signal = signal_from_string(optarg); + if (arg_signal < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse signal string %s.", optarg); + break; + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int loginctl_main(int argc, char *argv[], sd_bus *bus) { + + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "list-sessions", VERB_ANY, 1, VERB_DEFAULT, list_sessions }, + { "session-status", VERB_ANY, VERB_ANY, 0, show_session }, + { "show-session", VERB_ANY, VERB_ANY, 0, show_session }, + { "activate", VERB_ANY, 2, 0, activate }, + { "lock-session", VERB_ANY, VERB_ANY, 0, activate }, + { "unlock-session", VERB_ANY, VERB_ANY, 0, activate }, + { "lock-sessions", VERB_ANY, 1, 0, lock_sessions }, + { "unlock-sessions", VERB_ANY, 1, 0, lock_sessions }, + { "terminate-session", 2, VERB_ANY, 0, activate }, + { "kill-session", 2, VERB_ANY, 0, kill_session }, + { "list-users", VERB_ANY, 1, 0, list_users }, + { "user-status", VERB_ANY, VERB_ANY, 0, show_user }, + { "show-user", VERB_ANY, VERB_ANY, 0, show_user }, + { "enable-linger", VERB_ANY, VERB_ANY, 0, enable_linger }, + { "disable-linger", VERB_ANY, VERB_ANY, 0, enable_linger }, + { "terminate-user", 2, VERB_ANY, 0, terminate_user }, + { "kill-user", 2, VERB_ANY, 0, kill_user }, + { "list-seats", VERB_ANY, 1, 0, list_seats }, + { "seat-status", VERB_ANY, VERB_ANY, 0, show_seat }, + { "show-seat", VERB_ANY, VERB_ANY, 0, show_seat }, + { "attach", 3, VERB_ANY, 0, attach }, + { "flush-devices", VERB_ANY, 1, 0, flush_devices }, + { "terminate-seat", 2, VERB_ANY, 0, terminate_seat }, + {} + }; + + return dispatch_verb(argc, argv, verbs, bus); +} + +static int run(int argc, char *argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + setlocale(LC_ALL, ""); + log_show_color(true); + log_parse_environment(); + log_open(); + + /* The journal merging logic potentially needs a lot of fds. */ + (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); + + sigbus_install(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = bus_connect_transport(arg_transport, arg_host, false, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + (void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password); + + return loginctl_main(argc, argv, bus); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c new file mode 100644 index 00000000..ff192c53 --- /dev/null +++ b/src/login/logind-acl.c @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-device.h" + +#include "acl-util.h" +#include "alloc-util.h" +#include "device-util.h" +#include "dirent-util.h" +#include "escape.h" +#include "fd-util.h" +#include "format-util.h" +#include "logind-acl.h" +#include "set.h" +#include "string-util.h" +#include "util.h" + +static int flush_acl(acl_t acl) { + acl_entry_t i; + int found; + bool changed = false; + + assert(acl); + + for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); + found > 0; + found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { + + acl_tag_t tag; + + if (acl_get_tag_type(i, &tag) < 0) + return -errno; + + if (tag != ACL_USER) + continue; + + if (acl_delete_entry(acl, i) < 0) + return -errno; + + changed = true; + } + + if (found < 0) + return -errno; + + return changed; +} + +int devnode_acl(const char *path, + bool flush, + bool del, uid_t old_uid, + bool add, uid_t new_uid) { + + acl_t acl; + int r = 0; + bool changed = false; + + assert(path); + + acl = acl_get_file(path, ACL_TYPE_ACCESS); + if (!acl) + return -errno; + + if (flush) { + + r = flush_acl(acl); + if (r < 0) + goto finish; + if (r > 0) + changed = true; + + } else if (del && old_uid > 0) { + acl_entry_t entry; + + r = acl_find_uid(acl, old_uid, &entry); + if (r < 0) + goto finish; + + if (r > 0) { + if (acl_delete_entry(acl, entry) < 0) { + r = -errno; + goto finish; + } + + changed = true; + } + } + + if (add && new_uid > 0) { + acl_entry_t entry; + acl_permset_t permset; + int rd, wt; + + r = acl_find_uid(acl, new_uid, &entry); + if (r < 0) + goto finish; + + if (r == 0) { + if (acl_create_entry(&acl, &entry) < 0) { + r = -errno; + goto finish; + } + + if (acl_set_tag_type(entry, ACL_USER) < 0 || + acl_set_qualifier(entry, &new_uid) < 0) { + r = -errno; + goto finish; + } + } + + if (acl_get_permset(entry, &permset) < 0) { + r = -errno; + goto finish; + } + + rd = acl_get_perm(permset, ACL_READ); + if (rd < 0) { + r = -errno; + goto finish; + } + + wt = acl_get_perm(permset, ACL_WRITE); + if (wt < 0) { + r = -errno; + goto finish; + } + + if (!rd || !wt) { + + if (acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0) { + r = -errno; + goto finish; + } + + changed = true; + } + } + + if (!changed) + goto finish; + + if (acl_calc_mask(&acl) < 0) { + r = -errno; + goto finish; + } + + if (acl_set_file(path, ACL_TYPE_ACCESS, acl) < 0) { + r = -errno; + goto finish; + } + + r = 0; + +finish: + acl_free(acl); + + return r; +} + +int devnode_acl_all(const char *seat, + bool flush, + bool del, uid_t old_uid, + bool add, uid_t new_uid) { + + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + _cleanup_set_free_free_ Set *nodes = NULL; + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *dent; + sd_device *d; + Iterator i; + char *n; + int r; + + nodes = set_new(&path_hash_ops); + if (!nodes) + return -ENOMEM; + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + if (isempty(seat)) + seat = "seat0"; + + /* We can only match by one tag in libudev. We choose + * "uaccess" for that. If we could match for two tags here we + * could add the seat name as second match tag, but this would + * be hardly optimizable in libudev, and hence checking the + * second tag manually in our loop is a good solution. */ + r = sd_device_enumerator_add_match_tag(e, "uaccess"); + if (r < 0) + return r; + + FOREACH_DEVICE(e, d) { + const char *node, *sn; + + if (sd_device_get_property_value(d, "ID_SEAT", &sn) < 0 || isempty(sn)) + sn = "seat0"; + + if (!streq(seat, sn)) + continue; + + /* In case people mistag devices with nodes, we need to ignore this */ + if (sd_device_get_devname(d, &node) < 0) + continue; + + log_device_debug(d, "Found udev node %s for seat %s", node, seat); + r = set_put_strdup(nodes, node); + if (r < 0) + return r; + } + + /* udev exports "dead" device nodes to allow module on-demand loading, + * these devices are not known to the kernel at this moment */ + dir = opendir("/run/udev/static_node-tags/uaccess"); + if (dir) { + FOREACH_DIRENT(dent, dir, return -errno) { + _cleanup_free_ char *unescaped_devname = NULL; + + if (cunescape(dent->d_name, UNESCAPE_RELAX, &unescaped_devname) < 0) + return -ENOMEM; + + n = path_join("/dev", unescaped_devname); + if (!n) + return -ENOMEM; + + log_debug("Found static node %s for seat %s", n, seat); + r = set_consume(nodes, n); + if (r == -EEXIST) + continue; + if (r < 0) + return r; + } + } + + r = 0; + SET_FOREACH(n, nodes, i) { + int k; + + log_debug("Changing ACLs at %s for seat %s (uid "UID_FMT"→"UID_FMT"%s%s)", + n, seat, old_uid, new_uid, + del ? " del" : "", add ? " add" : ""); + + k = devnode_acl(n, flush, del, old_uid, add, new_uid); + if (k == -ENOENT) + log_debug("Device %s disappeared while setting ACLs", n); + else if (k < 0 && r == 0) + r = k; + } + + return r; +} diff --git a/src/login/logind-acl.h b/src/login/logind-acl.h new file mode 100644 index 00000000..00e286d7 --- /dev/null +++ b/src/login/logind-acl.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#if HAVE_ACL + +int devnode_acl(const char *path, + bool flush, + bool del, uid_t old_uid, + bool add, uid_t new_uid); + +int devnode_acl_all(const char *seat, + bool flush, + bool del, uid_t old_uid, + bool add, uid_t new_uid); +#else + +static inline int devnode_acl(const char *path, + bool flush, + bool del, uid_t old_uid, + bool add, uid_t new_uid) { + return 0; +} + +static inline int devnode_acl_all(const char *seat, + bool flush, + bool del, uid_t old_uid, + bool add, uid_t new_uid) { + return 0; +} + +#endif diff --git a/src/login/logind-action.c b/src/login/logind-action.c new file mode 100644 index 00000000..140953ee --- /dev/null +++ b/src/login/logind-action.c @@ -0,0 +1,184 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "conf-parser.h" +#include "format-util.h" +#include "logind-action.h" +#include "logind-dbus.h" +#include "logind-session-dbus.h" +#include "process-util.h" +#include "sleep-config.h" +#include "special.h" +#include "string-table.h" +#include "terminal-util.h" +#include "user-util.h" + +const char* manager_target_for_action(HandleAction handle) { + static const char * const target_table[_HANDLE_ACTION_MAX] = { + [HANDLE_POWEROFF] = SPECIAL_POWEROFF_TARGET, + [HANDLE_REBOOT] = SPECIAL_REBOOT_TARGET, + [HANDLE_HALT] = SPECIAL_HALT_TARGET, + [HANDLE_KEXEC] = SPECIAL_KEXEC_TARGET, + [HANDLE_SUSPEND] = SPECIAL_SUSPEND_TARGET, + [HANDLE_HIBERNATE] = SPECIAL_HIBERNATE_TARGET, + [HANDLE_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET, + [HANDLE_SUSPEND_THEN_HIBERNATE] = SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, + }; + + assert(handle >= 0); + if (handle < (ssize_t) ELEMENTSOF(target_table)) + return target_table[handle]; + return NULL; +} + +int manager_handle_action( + Manager *m, + InhibitWhat inhibit_key, + HandleAction handle, + bool ignore_inhibited, + bool is_edge) { + + static const char * const message_table[_HANDLE_ACTION_MAX] = { + [HANDLE_POWEROFF] = "Powering Off...", + [HANDLE_REBOOT] = "Rebooting...", + [HANDLE_HALT] = "Halting...", + [HANDLE_KEXEC] = "Rebooting via kexec...", + [HANDLE_SUSPEND] = "Suspending...", + [HANDLE_HIBERNATE] = "Hibernating...", + [HANDLE_HYBRID_SLEEP] = "Hibernating and suspending...", + [HANDLE_SUSPEND_THEN_HIBERNATE] = "Suspending, then hibernating...", + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + InhibitWhat inhibit_operation; + Inhibitor *offending = NULL; + bool supported; + const char *target; + int r; + + assert(m); + + /* If the key handling is turned off, don't do anything */ + if (handle == HANDLE_IGNORE) { + log_debug("Refusing operation, as it is turned off."); + return 0; + } + + if (inhibit_key == INHIBIT_HANDLE_LID_SWITCH) { + /* If the last system suspend or startup is too close, + * let's not suspend for now, to give USB docking + * stations some time to settle so that we can + * properly watch its displays. */ + if (m->lid_switch_ignore_event_source) { + log_debug("Ignoring lid switch request, system startup or resume too close."); + return 0; + } + } + + /* If the key handling is inhibited, don't do anything */ + if (inhibit_key > 0) { + if (manager_is_inhibited(m, inhibit_key, INHIBIT_BLOCK, NULL, true, false, 0, NULL)) { + log_debug("Refusing %s operation, %s is inhibited.", + handle_action_to_string(handle), + inhibit_what_to_string(inhibit_key)); + return 0; + } + } + + /* Locking is handled differently from the rest. */ + if (handle == HANDLE_LOCK) { + if (!is_edge) + return 0; + + log_info("Locking sessions..."); + session_send_lock_all(m, true); + return 1; + } + + if (handle == HANDLE_SUSPEND) + supported = can_sleep("suspend") > 0; + else if (handle == HANDLE_HIBERNATE) + supported = can_sleep("hibernate") > 0; + else if (handle == HANDLE_HYBRID_SLEEP) + supported = can_sleep("hybrid-sleep") > 0; + else if (handle == HANDLE_SUSPEND_THEN_HIBERNATE) + supported = can_sleep("suspend-then-hibernate") > 0; + else if (handle == HANDLE_KEXEC) + supported = access(KEXEC, X_OK) >= 0; + else + supported = true; + + if (!supported && IN_SET(handle, HANDLE_HIBERNATE, HANDLE_HYBRID_SLEEP, HANDLE_SUSPEND_THEN_HIBERNATE)) { + supported = can_sleep("suspend") > 0; + if (supported) { + log_notice("Requested %s operation is not supported, using regular suspend instead.", + handle_action_to_string(handle)); + handle = HANDLE_SUSPEND; + } + } + + if (!supported) + return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Requested %s operation not supported, ignoring.", handle_action_to_string(handle)); + + if (m->action_what > 0) + return log_debug_errno(SYNTHETIC_ERRNO(EALREADY), + "Action already in progress (%s), ignoring requested %s operation.", + inhibit_what_to_string(m->action_what), + handle_action_to_string(handle)); + + assert_se(target = manager_target_for_action(handle)); + + inhibit_operation = IN_SET(handle, HANDLE_SUSPEND, HANDLE_HIBERNATE, + HANDLE_HYBRID_SLEEP, + HANDLE_SUSPEND_THEN_HIBERNATE) ? INHIBIT_SLEEP : INHIBIT_SHUTDOWN; + + /* If the actual operation is inhibited, warn and fail */ + if (!ignore_inhibited && + manager_is_inhibited(m, inhibit_operation, INHIBIT_BLOCK, NULL, false, false, 0, &offending)) { + _cleanup_free_ char *comm = NULL, *u = NULL; + + (void) get_process_comm(offending->pid, &comm); + u = uid_to_name(offending->uid); + + /* If this is just a recheck of the lid switch then don't warn about anything */ + log_full(is_edge ? LOG_ERR : LOG_DEBUG, + "Refusing %s operation, %s is inhibited by UID "UID_FMT"/%s, PID "PID_FMT"/%s.", + handle_action_to_string(handle), + inhibit_what_to_string(inhibit_operation), + offending->uid, strna(u), + offending->pid, strna(comm)); + + return is_edge ? -EPERM : 0; + } + + log_info("%s", message_table[handle]); + + r = bus_manager_shutdown_or_sleep_now_or_later(m, target, inhibit_operation, &error); + if (r < 0) + return log_error_errno(r, "Failed to execute %s operation: %s", + handle_action_to_string(handle), + bus_error_message(&error, r)); + + return 1; +} + +static const char* const handle_action_table[_HANDLE_ACTION_MAX] = { + [HANDLE_IGNORE] = "ignore", + [HANDLE_POWEROFF] = "poweroff", + [HANDLE_REBOOT] = "reboot", + [HANDLE_HALT] = "halt", + [HANDLE_KEXEC] = "kexec", + [HANDLE_SUSPEND] = "suspend", + [HANDLE_HIBERNATE] = "hibernate", + [HANDLE_HYBRID_SLEEP] = "hybrid-sleep", + [HANDLE_SUSPEND_THEN_HIBERNATE] = "suspend-then-hibernate", + [HANDLE_LOCK] = "lock", +}; + +DEFINE_STRING_TABLE_LOOKUP(handle_action, HandleAction); +DEFINE_CONFIG_PARSE_ENUM(config_parse_handle_action, handle_action, HandleAction, "Failed to parse handle action setting"); diff --git a/src/login/logind-action.h b/src/login/logind-action.h new file mode 100644 index 00000000..a45aab78 --- /dev/null +++ b/src/login/logind-action.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" + +typedef enum HandleAction { + HANDLE_IGNORE, + HANDLE_POWEROFF, + HANDLE_REBOOT, + HANDLE_HALT, + HANDLE_KEXEC, + HANDLE_SUSPEND, + HANDLE_HIBERNATE, + HANDLE_HYBRID_SLEEP, + HANDLE_SUSPEND_THEN_HIBERNATE, + HANDLE_LOCK, + _HANDLE_ACTION_MAX, + _HANDLE_ACTION_INVALID = -1 +} HandleAction; + +#include "logind-inhibit.h" +#include "logind.h" + +int manager_handle_action( + Manager *m, + InhibitWhat inhibit_key, + HandleAction handle, + bool ignore_inhibited, + bool is_edge); + +const char* handle_action_to_string(HandleAction h) _const_; +HandleAction handle_action_from_string(const char *s) _pure_; + +const char* manager_target_for_action(HandleAction handle); + +CONFIG_PARSER_PROTOTYPE(config_parse_handle_action); diff --git a/src/login/logind-brightness.c b/src/login/logind-brightness.c new file mode 100644 index 00000000..3f4b65e1 --- /dev/null +++ b/src/login/logind-brightness.c @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-util.h" +#include "device-util.h" +#include "hash-funcs.h" +#include "logind-brightness.h" +#include "logind.h" +#include "process-util.h" +#include "stdio-util.h" + +/* Brightness and LED devices tend to be very slow to write to (often being I2C and such). Writes to the + * sysfs attributes are synchronous, and hence will freeze our process on access. We can't really have that, + * hence we add some complexity: whenever we need to write to the brightness attribute, we do so in a forked + * off process, which terminates when it is done. Watching that process allows us to watch completion of the + * write operation. + * + * To make this even more complex: clients are likely to send us many write requests in a short time-frame + * (because they implement reactive brightness sliders on screen). Let's coalesce writes to make this + * efficient: whenever we get requests to change brightness while we are still writing to the brightness + * attribute, let's remember the request and restart a new one when the initial operation finished. When we + * get another request while one is ongoing and one is pending we'll replace the pending one with the new + * one. + * + * The bus messages are answered when the first write operation finishes that started either due to the + * request or due to a later request that overrode the requested one. + * + * Yes, this is complex, but I don't see an easier way if we want to be both efficient and still support + * completion notification. */ + +typedef struct BrightnessWriter { + Manager *manager; + + sd_device *device; + char *path; + + pid_t child; + + uint32_t brightness; + bool again; + + Set *current_messages; + Set *pending_messages; + + sd_event_source* child_event_source; +} BrightnessWriter; + +static void brightness_writer_free(BrightnessWriter *w) { + if (!w) + return; + + if (w->manager && w->path) + (void) hashmap_remove_value(w->manager->brightness_writers, w->path, w); + + sd_device_unref(w->device); + free(w->path); + + set_free(w->current_messages); + set_free(w->pending_messages); + + w->child_event_source = sd_event_source_unref(w->child_event_source); + + free(w); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(BrightnessWriter*, brightness_writer_free); + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + brightness_writer_hash_ops, + char, + string_hash_func, + string_compare_func, + BrightnessWriter, + brightness_writer_free); + +static void brightness_writer_reply(BrightnessWriter *w, int error) { + int r; + + assert(w); + + for (;;) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + m = set_steal_first(w->current_messages); + if (!m) + break; + + if (error == 0) + r = sd_bus_reply_method_return(m, NULL); + else + r = sd_bus_reply_method_errnof(m, error, "Failed to write to brightness device: %m"); + if (r < 0) + log_warning_errno(r, "Failed to send method reply, ignoring: %m"); + } +} + +static int brightness_writer_fork(BrightnessWriter *w); + +static int on_brightness_writer_exit(sd_event_source *s, const siginfo_t *si, void *userdata) { + BrightnessWriter *w = userdata; + int r; + + assert(s); + assert(si); + assert(w); + + assert(si->si_pid == w->child); + w->child = 0; + w->child_event_source = sd_event_source_unref(w->child_event_source); + + brightness_writer_reply(w, + si->si_code == CLD_EXITED && + si->si_status == EXIT_SUCCESS ? 0 : -EPROTO); + + if (w->again) { + /* Another request to change the brightness has been queued. Act on it, but make the pending + * messages the current ones. */ + w->again = false; + set_free(w->current_messages); + w->current_messages = TAKE_PTR(w->pending_messages); + + r = brightness_writer_fork(w); + if (r >= 0) + return 0; + + brightness_writer_reply(w, r); + } + + brightness_writer_free(w); + return 0; +} + +static int brightness_writer_fork(BrightnessWriter *w) { + int r; + + assert(w); + assert(w->manager); + assert(w->child == 0); + assert(!w->child_event_source); + + r = safe_fork("(sd-bright)", FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG, &w->child); + if (r < 0) + return r; + if (r == 0) { + char brs[DECIMAL_STR_MAX(uint32_t)+1]; + + /* Child */ + xsprintf(brs, "%" PRIu32, w->brightness); + + r = sd_device_set_sysattr_value(w->device, "brightness", brs); + if (r < 0) { + log_device_error_errno(w->device, r, "Failed to write brightness to device: %m"); + _exit(EXIT_FAILURE); + } + + _exit(EXIT_SUCCESS); + } + + r = sd_event_add_child(w->manager->event, &w->child_event_source, w->child, WEXITED, on_brightness_writer_exit, w); + if (r < 0) + return log_error_errno(r, "Failed to watch brightness writer child " PID_FMT ": %m", w->child); + + return 0; +} + +static int set_add_message(Set **set, sd_bus_message *message) { + int r; + + assert(set); + + if (!message) + return 0; + + r = sd_bus_message_get_expect_reply(message); + if (r <= 0) + return r; + + r = set_ensure_allocated(set, &bus_message_hash_ops); + if (r < 0) + return r; + + r = set_put(*set, message); + if (r < 0) + return r; + + sd_bus_message_ref(message); + return 1; +} + +int manager_write_brightness( + Manager *m, + sd_device *device, + uint32_t brightness, + sd_bus_message *message) { + + _cleanup_(brightness_writer_freep) BrightnessWriter *w = NULL; + BrightnessWriter *existing; + const char *path; + int r; + + assert(m); + assert(device); + + r = sd_device_get_syspath(device, &path); + if (r < 0) + return log_device_error_errno(device, r, "Failed to get sysfs path for brightness device: %m"); + + existing = hashmap_get(m->brightness_writers, path); + if (existing) { + /* There's already a writer for this device. Let's update it with the new brightness, and add + * our message to the set of message to reply when done. */ + + r = set_add_message(&existing->pending_messages, message); + if (r < 0) + return log_error_errno(r, "Failed to add message to set: %m"); + + /* We override any previously requested brightness here: we coalesce writes, and the newest + * requested brightness is the one we'll put into effect. */ + existing->brightness = brightness; + existing->again = true; /* request another iteration of the writer when the current one is + * complete */ + return 0; + } + + r = hashmap_ensure_allocated(&m->brightness_writers, &brightness_writer_hash_ops); + if (r < 0) + return log_oom(); + + w = new(BrightnessWriter, 1); + if (!w) + return log_oom(); + + *w = (BrightnessWriter) { + .device = sd_device_ref(device), + .path = strdup(path), + .brightness = brightness, + }; + + if (!w->path) + return log_oom(); + + r = hashmap_put(m->brightness_writers, w->path, w); + if (r < 0) + return log_error_errno(r, "Failed to add brightness writer to hashmap: %m"); + w->manager = m; + + r = set_add_message(&w->current_messages, message); + if (r < 0) + return log_error_errno(r, "Failed to add message to set: %m"); + + r = brightness_writer_fork(w); + if (r < 0) + return r; + + TAKE_PTR(w); + return 0; +} diff --git a/src/login/logind-brightness.h b/src/login/logind-brightness.h new file mode 100644 index 00000000..b22ee37b --- /dev/null +++ b/src/login/logind-brightness.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-device.h" + +#include "logind.h" + +int manager_write_brightness(Manager *m, sd_device *device, uint32_t brightness, sd_bus_message *message); diff --git a/src/login/logind-button.c b/src/login/logind-button.c new file mode 100644 index 00000000..9ec235a1 --- /dev/null +++ b/src/login/logind-button.c @@ -0,0 +1,368 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "logind-button.h" +#include "missing_input.h" +#include "string-util.h" +#include "util.h" + +#define CONST_MAX4(a, b, c, d) CONST_MAX(CONST_MAX(a, b), CONST_MAX(c, d)) + +#define ULONG_BITS (sizeof(unsigned long)*8) + +static bool bitset_get(const unsigned long *bits, unsigned i) { + return (bits[i / ULONG_BITS] >> (i % ULONG_BITS)) & 1UL; +} + +static void bitset_put(unsigned long *bits, unsigned i) { + bits[i / ULONG_BITS] |= (unsigned long) 1 << (i % ULONG_BITS); +} + +Button* button_new(Manager *m, const char *name) { + Button *b; + + assert(m); + assert(name); + + b = new0(Button, 1); + if (!b) + return NULL; + + b->name = strdup(name); + if (!b->name) + return mfree(b); + + if (hashmap_put(m->buttons, b->name, b) < 0) { + free(b->name); + return mfree(b); + } + + b->manager = m; + b->fd = -1; + + return b; +} + +void button_free(Button *b) { + assert(b); + + hashmap_remove(b->manager->buttons, b->name); + + sd_event_source_unref(b->io_event_source); + sd_event_source_unref(b->check_event_source); + + if (b->fd >= 0) + /* If the device has been unplugged close() returns + * ENODEV, let's ignore this, hence we don't use + * safe_close() */ + (void) close(b->fd); + + free(b->name); + free(b->seat); + free(b); +} + +int button_set_seat(Button *b, const char *sn) { + char *s; + + assert(b); + assert(sn); + + s = strdup(sn); + if (!s) + return -ENOMEM; + + free(b->seat); + b->seat = s; + + return 0; +} + +static void button_lid_switch_handle_action(Manager *manager, bool is_edge) { + HandleAction handle_action; + + assert(manager); + + /* If we are docked or on external power, handle the lid switch + * differently */ + if (manager_is_docked_or_external_displays(manager)) + handle_action = manager->handle_lid_switch_docked; + else if (manager->handle_lid_switch_ep != _HANDLE_ACTION_INVALID && + manager_is_on_external_power()) + handle_action = manager->handle_lid_switch_ep; + else + handle_action = manager->handle_lid_switch; + + manager_handle_action(manager, INHIBIT_HANDLE_LID_SWITCH, handle_action, manager->lid_switch_ignore_inhibited, is_edge); +} + +static int button_recheck(sd_event_source *e, void *userdata) { + Button *b = userdata; + + assert(b); + assert(b->lid_closed); + + button_lid_switch_handle_action(b->manager, false); + return 1; +} + +static int button_install_check_event_source(Button *b) { + int r; + assert(b); + + /* Install a post handler, so that we keep rechecking as long as the lid is closed. */ + + if (b->check_event_source) + return 0; + + r = sd_event_add_post(b->manager->event, &b->check_event_source, button_recheck, b); + if (r < 0) + return r; + + return sd_event_source_set_priority(b->check_event_source, SD_EVENT_PRIORITY_IDLE+1); +} + +static int button_dispatch(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Button *b = userdata; + struct input_event ev; + ssize_t l; + + assert(s); + assert(fd == b->fd); + assert(b); + + l = read(b->fd, &ev, sizeof(ev)); + if (l < 0) + return errno != EAGAIN ? -errno : 0; + if ((size_t) l < sizeof(ev)) + return -EIO; + + if (ev.type == EV_KEY && ev.value > 0) { + + switch (ev.code) { + + case KEY_POWER: + case KEY_POWER2: + log_struct(LOG_INFO, + LOG_MESSAGE("Power key pressed."), + "MESSAGE_ID=" SD_MESSAGE_POWER_KEY_STR); + + manager_handle_action(b->manager, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true); + break; + + /* The kernel is a bit confused here: + + KEY_SLEEP = suspend-to-ram, which everybody else calls "suspend" + KEY_SUSPEND = suspend-to-disk, which everybody else calls "hibernate" + */ + + case KEY_SLEEP: + log_struct(LOG_INFO, + LOG_MESSAGE("Suspend key pressed."), + "MESSAGE_ID=" SD_MESSAGE_SUSPEND_KEY_STR); + + manager_handle_action(b->manager, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true); + break; + + case KEY_SUSPEND: + log_struct(LOG_INFO, + LOG_MESSAGE("Hibernate key pressed."), + "MESSAGE_ID=" SD_MESSAGE_HIBERNATE_KEY_STR); + + manager_handle_action(b->manager, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true); + break; + } + + } else if (ev.type == EV_SW && ev.value > 0) { + + if (ev.code == SW_LID) { + log_struct(LOG_INFO, + LOG_MESSAGE("Lid closed."), + "MESSAGE_ID=" SD_MESSAGE_LID_CLOSED_STR); + + b->lid_closed = true; + button_lid_switch_handle_action(b->manager, true); + button_install_check_event_source(b); + + } else if (ev.code == SW_DOCK) { + log_struct(LOG_INFO, + LOG_MESSAGE("System docked."), + "MESSAGE_ID=" SD_MESSAGE_SYSTEM_DOCKED_STR); + + b->docked = true; + } + + } else if (ev.type == EV_SW && ev.value == 0) { + + if (ev.code == SW_LID) { + log_struct(LOG_INFO, + LOG_MESSAGE("Lid opened."), + "MESSAGE_ID=" SD_MESSAGE_LID_OPENED_STR); + + b->lid_closed = false; + b->check_event_source = sd_event_source_unref(b->check_event_source); + + } else if (ev.code == SW_DOCK) { + log_struct(LOG_INFO, + LOG_MESSAGE("System undocked."), + "MESSAGE_ID=" SD_MESSAGE_SYSTEM_UNDOCKED_STR); + + b->docked = false; + } + } + + return 0; +} + +static int button_suitable(int fd) { + unsigned long types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1]; + + assert(fd >= 0); + + if (ioctl(fd, EVIOCGBIT(EV_SYN, sizeof types), types) < 0) + return -errno; + + if (bitset_get(types, EV_KEY)) { + unsigned long keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1]; + + if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof keys), keys) < 0) + return -errno; + + if (bitset_get(keys, KEY_POWER) || + bitset_get(keys, KEY_POWER2) || + bitset_get(keys, KEY_SLEEP) || + bitset_get(keys, KEY_SUSPEND)) + return true; + } + + if (bitset_get(types, EV_SW)) { + unsigned long switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1]; + + if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof switches), switches) < 0) + return -errno; + + if (bitset_get(switches, SW_LID) || + bitset_get(switches, SW_DOCK)) + return true; + } + + return false; +} + +static int button_set_mask(const char *name, int fd) { + unsigned long + types[CONST_MAX(EV_KEY, EV_SW)/ULONG_BITS+1] = {}, + keys[CONST_MAX4(KEY_POWER, KEY_POWER2, KEY_SLEEP, KEY_SUSPEND)/ULONG_BITS+1] = {}, + switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {}; + struct input_mask mask; + + assert(name); + assert(fd >= 0); + + bitset_put(types, EV_KEY); + bitset_put(types, EV_SW); + + mask = (struct input_mask) { + .type = EV_SYN, + .codes_size = sizeof(types), + .codes_ptr = PTR_TO_UINT64(types), + }; + + if (ioctl(fd, EVIOCSMASK, &mask) < 0) + /* Log only at debug level if the kernel doesn't do EVIOCSMASK yet */ + return log_full_errno(IN_SET(errno, ENOTTY, EOPNOTSUPP, EINVAL) ? LOG_DEBUG : LOG_WARNING, + errno, "Failed to set EV_SYN event mask on /dev/input/%s: %m", name); + + bitset_put(keys, KEY_POWER); + bitset_put(keys, KEY_POWER2); + bitset_put(keys, KEY_SLEEP); + bitset_put(keys, KEY_SUSPEND); + + mask = (struct input_mask) { + .type = EV_KEY, + .codes_size = sizeof(keys), + .codes_ptr = PTR_TO_UINT64(keys), + }; + + if (ioctl(fd, EVIOCSMASK, &mask) < 0) + return log_warning_errno(errno, "Failed to set EV_KEY event mask on /dev/input/%s: %m", name); + + bitset_put(switches, SW_LID); + bitset_put(switches, SW_DOCK); + + mask = (struct input_mask) { + .type = EV_SW, + .codes_size = sizeof(switches), + .codes_ptr = PTR_TO_UINT64(switches), + }; + + if (ioctl(fd, EVIOCSMASK, &mask) < 0) + return log_warning_errno(errno, "Failed to set EV_SW event mask on /dev/input/%s: %m", name); + + return 0; +} + +int button_open(Button *b) { + _cleanup_close_ int fd = -1; + const char *p; + char name[256]; + int r; + + assert(b); + + b->fd = safe_close(b->fd); + + p = strjoina("/dev/input/", b->name); + + fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); + if (fd < 0) + return log_warning_errno(errno, "Failed to open %s: %m", p); + + r = button_suitable(fd); + if (r < 0) + return log_warning_errno(r, "Failed to determine whether input device %s is relevant to us: %m", p); + if (r == 0) + return log_debug_errno(SYNTHETIC_ERRNO(EADDRNOTAVAIL), + "Device %s does not expose keys or switches relevant to us, ignoring.", p); + + if (ioctl(fd, EVIOCGNAME(sizeof name), name) < 0) + return log_error_errno(errno, "Failed to get input name for %s: %m", p); + + (void) button_set_mask(b->name, fd); + + b->io_event_source = sd_event_source_unref(b->io_event_source); + r = sd_event_add_io(b->manager->event, &b->io_event_source, fd, EPOLLIN, button_dispatch, b); + if (r < 0) + return log_error_errno(r, "Failed to add button event for %s: %m", p); + + b->fd = TAKE_FD(fd); + log_info("Watching system buttons on %s (%s)", p, name); + return 0; +} + +int button_check_switches(Button *b) { + unsigned long switches[CONST_MAX(SW_LID, SW_DOCK)/ULONG_BITS+1] = {}; + assert(b); + + if (b->fd < 0) + return -EINVAL; + + if (ioctl(b->fd, EVIOCGSW(sizeof(switches)), switches) < 0) + return -errno; + + b->lid_closed = bitset_get(switches, SW_LID); + b->docked = bitset_get(switches, SW_DOCK); + + if (b->lid_closed) + button_install_check_event_source(b); + + return 0; +} diff --git a/src/login/logind-button.h b/src/login/logind-button.h new file mode 100644 index 00000000..d009851c --- /dev/null +++ b/src/login/logind-button.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Button Button; + +#include "logind.h" + +struct Button { + Manager *manager; + + sd_event_source *io_event_source; + sd_event_source *check_event_source; + + char *name; + char *seat; + int fd; + + bool lid_closed; + bool docked; +}; + +Button* button_new(Manager *m, const char *name); +void button_free(Button *b); +int button_open(Button *b); +int button_set_seat(Button *b, const char *sn); +int button_check_switches(Button *b); diff --git a/src/login/logind-core.c b/src/login/logind-core.c new file mode 100644 index 00000000..e84b3809 --- /dev/null +++ b/src/login/logind-core.c @@ -0,0 +1,817 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#if ENABLE_UTMP +#include +#endif + +#include "sd-device.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "cgroup-util.h" +#include "conf-parser.h" +#include "device-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "limits-util.h" +#include "logind.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "udev-util.h" +#include "user-util.h" + +void manager_reset_config(Manager *m) { + assert(m); + + m->n_autovts = 6; + m->reserve_vt = 6; + m->remove_ipc = true; + m->inhibit_delay_max = 5 * USEC_PER_SEC; + m->user_stop_delay = 10 * USEC_PER_SEC; + + m->handle_power_key = HANDLE_POWEROFF; + m->handle_suspend_key = HANDLE_SUSPEND; + m->handle_hibernate_key = HANDLE_HIBERNATE; + m->handle_lid_switch = HANDLE_SUSPEND; + m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID; + m->handle_lid_switch_docked = HANDLE_IGNORE; + m->power_key_ignore_inhibited = false; + m->suspend_key_ignore_inhibited = false; + m->hibernate_key_ignore_inhibited = false; + m->lid_switch_ignore_inhibited = true; + + m->holdoff_timeout_usec = 30 * USEC_PER_SEC; + + m->idle_action_usec = 30 * USEC_PER_MINUTE; + m->idle_action = HANDLE_IGNORE; + + m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */ + m->sessions_max = 8192; + m->inhibitors_max = 8192; + + m->kill_user_processes = KILL_USER_PROCESSES; + + m->kill_only_users = strv_free(m->kill_only_users); + m->kill_exclude_users = strv_free(m->kill_exclude_users); +} + +int manager_parse_config_file(Manager *m) { + assert(m); + + return config_parse_many_nulstr(PKGSYSCONFDIR "/logind.conf", + CONF_PATHS_NULSTR("systemd/logind.conf.d"), + "Login\0", + config_item_perf_lookup, logind_gperf_lookup, + CONFIG_PARSE_WARN, m); +} + +int manager_add_device(Manager *m, const char *sysfs, bool master, Device **ret_device) { + Device *d; + + assert(m); + assert(sysfs); + + d = hashmap_get(m->devices, sysfs); + if (d) + /* we support adding master-flags, but not removing them */ + d->master = d->master || master; + else { + d = device_new(m, sysfs, master); + if (!d) + return -ENOMEM; + } + + if (ret_device) + *ret_device = d; + + return 0; +} + +int manager_add_seat(Manager *m, const char *id, Seat **ret_seat) { + Seat *s; + int r; + + assert(m); + assert(id); + + s = hashmap_get(m->seats, id); + if (!s) { + r = seat_new(&s, m, id); + if (r < 0) + return r; + } + + if (ret_seat) + *ret_seat = s; + + return 0; +} + +int manager_add_session(Manager *m, const char *id, Session **ret_session) { + Session *s; + int r; + + assert(m); + assert(id); + + s = hashmap_get(m->sessions, id); + if (!s) { + r = session_new(&s, m, id); + if (r < 0) + return r; + } + + if (ret_session) + *ret_session = s; + + return 0; +} + +int manager_add_user( + Manager *m, + uid_t uid, + gid_t gid, + const char *name, + const char *home, + User **ret_user) { + + User *u; + int r; + + assert(m); + assert(name); + + u = hashmap_get(m->users, UID_TO_PTR(uid)); + if (!u) { + r = user_new(&u, m, uid, gid, name, home); + if (r < 0) + return r; + } + + if (ret_user) + *ret_user = u; + + return 0; +} + +int manager_add_user_by_name( + Manager *m, + const char *name, + User **ret_user) { + + const char *home = NULL; + uid_t uid; + gid_t gid; + int r; + + assert(m); + assert(name); + + r = get_user_creds(&name, &uid, &gid, &home, NULL, 0); + if (r < 0) + return r; + + return manager_add_user(m, uid, gid, name, home, ret_user); +} + +int manager_add_user_by_uid(Manager *m, uid_t uid, User **ret_user) { + struct passwd *p; + + assert(m); + + errno = 0; + p = getpwuid(uid); + if (!p) + return errno_or_else(ENOENT); + + return manager_add_user(m, uid, p->pw_gid, p->pw_name, p->pw_dir, ret_user); +} + +int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **ret) { + Inhibitor *i; + int r; + + assert(m); + assert(id); + + i = hashmap_get(m->inhibitors, id); + if (!i) { + r = inhibitor_new(&i, m, id); + if (r < 0) + return r; + } + + if (ret) + *ret = i; + + return 0; +} + +int manager_add_button(Manager *m, const char *name, Button **ret_button) { + Button *b; + + assert(m); + assert(name); + + b = hashmap_get(m->buttons, name); + if (!b) { + b = button_new(m, name); + if (!b) + return -ENOMEM; + } + + if (ret_button) + *ret_button = b; + + return 0; +} + +int manager_process_seat_device(Manager *m, sd_device *d) { + Device *device; + int r; + + assert(m); + + if (device_for_action(d, DEVICE_ACTION_REMOVE)) { + const char *syspath; + + r = sd_device_get_syspath(d, &syspath); + if (r < 0) + return 0; + + device = hashmap_get(m->devices, syspath); + if (!device) + return 0; + + seat_add_to_gc_queue(device->seat); + device_free(device); + + } else { + const char *sn, *syspath; + bool master; + Seat *seat; + + if (sd_device_get_property_value(d, "ID_SEAT", &sn) < 0 || isempty(sn)) + sn = "seat0"; + + if (!seat_name_is_valid(sn)) { + log_device_warning(d, "Device with invalid seat name %s found, ignoring.", sn); + return 0; + } + + seat = hashmap_get(m->seats, sn); + master = sd_device_has_tag(d, "master-of-seat") > 0; + + /* Ignore non-master devices for unknown seats */ + if (!master && !seat) + return 0; + + r = sd_device_get_syspath(d, &syspath); + if (r < 0) + return r; + + r = manager_add_device(m, syspath, master, &device); + if (r < 0) + return r; + + if (!seat) { + r = manager_add_seat(m, sn, &seat); + if (r < 0) { + if (!device->seat) + device_free(device); + + return r; + } + } + + device_attach(device, seat); + seat_start(seat); + } + + return 0; +} + +int manager_process_button_device(Manager *m, sd_device *d) { + const char *sysname; + Button *b; + int r; + + assert(m); + + r = sd_device_get_sysname(d, &sysname); + if (r < 0) + return r; + + if (device_for_action(d, DEVICE_ACTION_REMOVE)) { + + b = hashmap_get(m->buttons, sysname); + if (!b) + return 0; + + button_free(b); + + } else { + const char *sn; + + r = manager_add_button(m, sysname, &b); + if (r < 0) + return r; + + if (sd_device_get_property_value(d, "ID_SEAT", &sn) < 0 || isempty(sn)) + sn = "seat0"; + + button_set_seat(b, sn); + + r = button_open(b); + if (r < 0) /* event device doesn't have any keys or switches relevant to us? (or any other error + * opening the device?) let's close the button again. */ + button_free(b); + } + + return 0; +} + +int manager_get_session_by_pid(Manager *m, pid_t pid, Session **ret) { + _cleanup_free_ char *unit = NULL; + Session *s; + int r; + + assert(m); + + if (!pid_is_valid(pid)) + return -EINVAL; + + s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(pid)); + if (!s) { + r = cg_pid_get_unit(pid, &unit); + if (r >= 0) + s = hashmap_get(m->session_units, unit); + } + + if (ret) + *ret = s; + + return !!s; +} + +int manager_get_user_by_pid(Manager *m, pid_t pid, User **ret) { + _cleanup_free_ char *unit = NULL; + User *u = NULL; + int r; + + assert(m); + + if (!pid_is_valid(pid)) + return -EINVAL; + + r = cg_pid_get_slice(pid, &unit); + if (r >= 0) + u = hashmap_get(m->user_units, unit); + + if (ret) + *ret = u; + + return !!u; +} + +int manager_get_idle_hint(Manager *m, dual_timestamp *t) { + Session *s; + bool idle_hint; + dual_timestamp ts = DUAL_TIMESTAMP_NULL; + Iterator i; + + assert(m); + + idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL); + + HASHMAP_FOREACH(s, m->sessions, i) { + dual_timestamp k; + int ih; + + ih = session_get_idle_hint(s, &k); + if (ih < 0) + return ih; + + if (!ih) { + if (!idle_hint) { + if (k.monotonic < ts.monotonic) + ts = k; + } else { + idle_hint = false; + ts = k; + } + } else if (idle_hint) { + + if (k.monotonic > ts.monotonic) + ts = k; + } + } + + if (t) + *t = ts; + + return idle_hint; +} + +bool manager_shall_kill(Manager *m, const char *user) { + assert(m); + assert(user); + + if (!m->kill_exclude_users && streq(user, "root")) + return false; + + if (strv_contains(m->kill_exclude_users, user)) + return false; + + if (!strv_isempty(m->kill_only_users)) + return strv_contains(m->kill_only_users, user); + + return m->kill_user_processes; +} + +int config_parse_n_autovts( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + unsigned *n = data; + unsigned o; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou(rvalue, &o); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse number of autovts, ignoring: %s", rvalue); + return 0; + } + + if (o > 15) { + log_syntax(unit, LOG_ERR, filename, line, r, "A maximum of 15 autovts are supported, ignoring: %s", rvalue); + return 0; + } + + *n = o; + return 0; +} + +static int vt_is_busy(unsigned vtnr) { + struct vt_stat vt_stat; + int r = 0; + _cleanup_close_ int fd; + + assert(vtnr >= 1); + + /* VT_GETSTATE "cannot return state for more than 16 VTs, since v_state is short" */ + assert(vtnr <= 15); + + /* We explicitly open /dev/tty1 here instead of /dev/tty0. If + * we'd open the latter we'd open the foreground tty which + * hence would be unconditionally busy. By opening /dev/tty1 + * we avoid this. Since tty1 is special and needs to be an + * explicitly loaded getty or DM this is safe. */ + + fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return -errno; + + if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0) + r = -errno; + else + r = !!(vt_stat.v_state & (1 << vtnr)); + + return r; +} + +int manager_spawn_autovt(Manager *m, unsigned vtnr) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned)]; + int r; + + assert(m); + assert(vtnr >= 1); + + if (vtnr > m->n_autovts && + vtnr != m->reserve_vt) + return 0; + + if (vtnr != m->reserve_vt) { + /* If this is the reserved TTY, we'll start the getty + * on it in any case, but otherwise only if it is not + * busy. */ + + r = vt_is_busy(vtnr); + if (r < 0) + return r; + else if (r > 0) + return -EBUSY; + } + + snprintf(name, sizeof(name), "autovt@tty%u.service", vtnr); + r = sd_bus_call_method( + m->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + &error, + NULL, + "ss", name, "fail"); + if (r < 0) + return log_error_errno(r, "Failed to start %s: %s", name, bus_error_message(&error, r)); + + return 0; +} + +bool manager_is_lid_closed(Manager *m) { + Iterator i; + Button *b; + + HASHMAP_FOREACH(b, m->buttons, i) + if (b->lid_closed) + return true; + + return false; +} + +static bool manager_is_docked(Manager *m) { + Iterator i; + Button *b; + + HASHMAP_FOREACH(b, m->buttons, i) + if (b->docked) + return true; + + return false; +} + +static int manager_count_external_displays(Manager *m) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *d; + int r, n = 0; + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_subsystem(e, "drm", true); + if (r < 0) + return r; + + FOREACH_DEVICE(e, d) { + const char *status, *enabled, *dash, *nn, *subsys; + sd_device *p; + + if (sd_device_get_parent(d, &p) < 0) + continue; + + /* If the parent shares the same subsystem as the + * device we are looking at then it is a connector, + * which is what we are interested in. */ + if (sd_device_get_subsystem(p, &subsys) < 0 || !streq(subsys, "drm")) + continue; + + if (sd_device_get_sysname(d, &nn) < 0) + continue; + + /* Ignore internal displays: the type is encoded in the sysfs name, as the second dash separated item + * (the first is the card name, the last the connector number). We implement a blacklist of external + * displays here, rather than a whitelist of internal ones, to ensure we don't block suspends too + * eagerly. */ + dash = strchr(nn, '-'); + if (!dash) + continue; + + dash++; + if (!STARTSWITH_SET(dash, + "VGA-", "DVI-I-", "DVI-D-", "DVI-A-" + "Composite-", "SVIDEO-", "Component-", + "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-")) + continue; + + /* Ignore ports that are not enabled */ + if (sd_device_get_sysattr_value(d, "enabled", &enabled) < 0 || !streq(enabled, "enabled")) + continue; + + /* We count any connector which is not explicitly + * "disconnected" as connected. */ + if (sd_device_get_sysattr_value(d, "status", &status) < 0 || !streq(status, "disconnected")) + n++; + } + + return n; +} + +bool manager_is_docked_or_external_displays(Manager *m) { + int n; + + /* If we are docked don't react to lid closing */ + if (manager_is_docked(m)) { + log_debug("System is docked."); + return true; + } + + /* If we have more than one display connected, + * assume that we are docked. */ + n = manager_count_external_displays(m); + if (n < 0) + log_warning_errno(n, "Display counting failed: %m"); + else if (n >= 1) { + log_debug("External (%i) displays connected.", n); + return true; + } + + return false; +} + +bool manager_is_on_external_power(void) { + int r; + + /* For now we only check for AC power, but 'external power' can apply to anything that isn't an internal + * battery */ + r = on_ac_power(); + if (r < 0) + log_warning_errno(r, "Failed to read AC power status: %m"); + + return r != 0; /* Treat failure as 'on AC' */ +} + +bool manager_all_buttons_ignored(Manager *m) { + assert(m); + + if (m->handle_power_key != HANDLE_IGNORE) + return false; + if (m->handle_suspend_key != HANDLE_IGNORE) + return false; + if (m->handle_hibernate_key != HANDLE_IGNORE) + return false; + if (m->handle_lid_switch != HANDLE_IGNORE) + return false; + if (!IN_SET(m->handle_lid_switch_ep, _HANDLE_ACTION_INVALID, HANDLE_IGNORE)) + return false; + if (m->handle_lid_switch_docked != HANDLE_IGNORE) + return false; + + return true; +} + +int manager_read_utmp(Manager *m) { +#if ENABLE_UTMP + int r; + + assert(m); + + if (utmpxname(_PATH_UTMPX) < 0) + return log_error_errno(errno, "Failed to set utmp path to " _PATH_UTMPX ": %m"); + + setutxent(); + + for (;;) { + _cleanup_free_ char *t = NULL; + struct utmpx *u; + const char *c; + Session *s; + + errno = 0; + u = getutxent(); + if (!u) { + if (errno != 0) + log_warning_errno(errno, "Failed to read " _PATH_UTMPX ", ignoring: %m"); + r = 0; + break; + } + + if (u->ut_type != USER_PROCESS) + continue; + + if (!pid_is_valid(u->ut_pid)) + continue; + + t = strndup(u->ut_line, sizeof(u->ut_line)); + if (!t) { + r = log_oom(); + break; + } + + c = path_startswith(t, "/dev/"); + if (c) { + r = free_and_strdup(&t, c); + if (r < 0) { + log_oom(); + break; + } + } + + if (isempty(t)) + continue; + + s = hashmap_get(m->sessions_by_leader, PID_TO_PTR(u->ut_pid)); + if (!s) + continue; + + if (s->tty_validity == TTY_FROM_UTMP && !streq_ptr(s->tty, t)) { + /* This may happen on multiplexed SSH connection (i.e. 'SSH connection sharing'). In + * this case PAM and utmp sessions don't match. In such a case let's invalidate the TTY + * information and never acquire it again. */ + + s->tty = mfree(s->tty); + s->tty_validity = TTY_UTMP_INCONSISTENT; + log_debug("Session '%s' has inconsistent TTY information, dropping TTY information.", s->id); + continue; + } + + /* Never override what we figured out once */ + if (s->tty || s->tty_validity >= 0) + continue; + + s->tty = TAKE_PTR(t); + s->tty_validity = TTY_FROM_UTMP; + log_debug("Acquired TTY information '%s' from utmp for session '%s'.", s->tty, s->id); + } + + endutxent(); + return r; +#else + return 0; +#endif +} + +#if ENABLE_UTMP +static int manager_dispatch_utmp(sd_event_source *s, const struct inotify_event *event, void *userdata) { + Manager *m = userdata; + + assert(m); + + /* If there's indication the file itself might have been removed or became otherwise unavailable, then let's + * reestablish the watch on whatever there's now. */ + if ((event->mask & (IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF|IN_Q_OVERFLOW|IN_UNMOUNT)) != 0) + manager_connect_utmp(m); + + (void) manager_read_utmp(m); + return 0; +} +#endif + +void manager_connect_utmp(Manager *m) { +#if ENABLE_UTMP + sd_event_source *s = NULL; + int r; + + assert(m); + + /* Watch utmp for changes via inotify. We do this to deal with tools such as ssh, which will register the PAM + * session early, and acquire a TTY only much later for the connection. Thus during PAM the TTY won't be known + * yet. ssh will register itself with utmp when it finally acquired the TTY. Hence, let's make use of this, and + * watch utmp for the TTY asynchronously. We use the PAM session's leader PID as key, to find the right entry. + * + * Yes, relying on utmp is pretty ugly, but it's good enough for informational purposes, as well as idle + * detection (which, for tty sessions, relies on the TTY used) */ + + r = sd_event_add_inotify(m->event, &s, _PATH_UTMPX, IN_MODIFY|IN_MOVE_SELF|IN_DELETE_SELF|IN_ATTRIB, manager_dispatch_utmp, m); + if (r < 0) + log_full_errno(r == -ENOENT ? LOG_DEBUG: LOG_WARNING, r, "Failed to create inotify watch on " _PATH_UTMPX ", ignoring: %m"); + else { + r = sd_event_source_set_priority(s, SD_EVENT_PRIORITY_IDLE); + if (r < 0) + log_warning_errno(r, "Failed to adjust utmp event source priority, ignoring: %m"); + + (void) sd_event_source_set_description(s, "utmp"); + } + + sd_event_source_unref(m->utmp_event_source); + m->utmp_event_source = s; +#endif +} + +void manager_reconnect_utmp(Manager *m) { +#if ENABLE_UTMP + assert(m); + + if (m->utmp_event_source) + return; + + manager_connect_utmp(m); +#endif +} diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c new file mode 100644 index 00000000..ff731555 --- /dev/null +++ b/src/login/logind-dbus.c @@ -0,0 +1,3898 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-device.h" +#include "sd-messages.h" + +#include "alloc-util.h" +#include "audit-util.h" +#include "bootspec.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-polkit.h" +#include "bus-unit-util.h" +#include "bus-util.h" +#include "cgroup-util.h" +#include "device-util.h" +#include "dirent-util.h" +#include "efi-loader.h" +#include "efivars.h" +#include "env-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio-label.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "logind-dbus.h" +#include "logind-seat-dbus.h" +#include "logind-session-dbus.h" +#include "logind-user-dbus.h" +#include "logind.h" +#include "missing_capability.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "reboot-util.h" +#include "selinux-util.h" +#include "sleep-config.h" +#include "special.h" +#include "stdio-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "unit-name.h" +#include "user-util.h" +#include "utmp-wtmp.h" +#include "virt.h" + +static int get_sender_session( + Manager *m, + sd_bus_message *message, + bool consult_display, + sd_bus_error *error, + Session **ret) { + + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + Session *session = NULL; + const char *name; + int r; + + /* Acquire the sender's session. This first checks if the sending process is inside a session itself, + * and returns that. If not and 'consult_display' is true, this returns the display session of the + * owning user of the caller. */ + + r = sd_bus_query_sender_creds(message, + SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT| + (consult_display ? SD_BUS_CREDS_OWNER_UID : 0), &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_session(creds, &name); + if (r < 0) { + if (r != -ENXIO) + return r; + + if (consult_display) { + uid_t uid; + + r = sd_bus_creds_get_owner_uid(creds, &uid); + if (r < 0) { + if (r != -ENXIO) + return r; + } else { + User *user; + + user = hashmap_get(m->users, UID_TO_PTR(uid)); + if (user) + session = user->display; + } + } + } else + session = hashmap_get(m->sessions, name); + + if (!session) + return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, + consult_display ? + "Caller does not belong to any known session and doesn't own any suitable session." : + "Caller does not belong to any known session."); + + *ret = session; + return 0; +} + +int manager_get_session_from_creds( + Manager *m, + sd_bus_message *message, + const char *name, + sd_bus_error *error, + Session **ret) { + + Session *session; + + assert(m); + assert(ret); + + if (SEAT_IS_SELF(name)) /* the caller's own session */ + return get_sender_session(m, message, false, error, ret); + if (SEAT_IS_AUTO(name)) /* The caller's own session if they have one, otherwise their user's display session */ + return get_sender_session(m, message, true, error, ret); + + session = hashmap_get(m->sessions, name); + if (!session) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name); + + *ret = session; + return 0; +} + +static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + uid_t uid; + User *user; + int r; + + /* Note that we get the owner UID of the session, not the actual client UID here! */ + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_owner_uid(creds, &uid); + if (r < 0) { + if (r != -ENXIO) + return r; + + user = NULL; + } else + user = hashmap_get(m->users, UID_TO_PTR(uid)); + + if (!user) + return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, + "Caller does not belong to any logged in or lingering user"); + + *ret = user; + return 0; +} + +int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) { + User *user; + + assert(m); + assert(ret); + + if (!uid_is_valid(uid)) + return get_sender_user(m, message, error, ret); + + user = hashmap_get(m->users, UID_TO_PTR(uid)); + if (!user) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, + "User ID "UID_FMT" is not logged in or lingering", uid); + + *ret = user; + return 0; +} + +int manager_get_seat_from_creds( + Manager *m, + sd_bus_message *message, + const char *name, + sd_bus_error *error, + Seat **ret) { + + Seat *seat; + int r; + + assert(m); + assert(ret); + + if (SEAT_IS_SELF(name) || SEAT_IS_AUTO(name)) { + Session *session; + + /* Use these special seat names as session names */ + r = manager_get_session_from_creds(m, message, name, error, &session); + if (r < 0) + return r; + + seat = session->seat; + if (!seat) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session '%s' has no seat.", session->id); + } else { + seat = hashmap_get(m->seats, name); + if (!seat) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name); + } + + *ret = seat; + return 0; +} + +static int return_test_polkit( + sd_bus_message *message, + int capability, + const char *action, + const char **details, + uid_t good_user, + sd_bus_error *e) { + + const char *result; + bool challenge; + int r; + + r = bus_test_polkit(message, capability, action, details, good_user, &challenge, e); + if (r < 0) + return r; + + if (r > 0) + result = "yes"; + else if (challenge) + result = "challenge"; + else + result = "no"; + + return sd_bus_reply_method_return(message, "s", result); +} + +static int property_get_idle_hint( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(bus); + assert(reply); + assert(m); + + return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0); +} + +static int property_get_idle_since_hint( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + dual_timestamp t = DUAL_TIMESTAMP_NULL; + + assert(bus); + assert(reply); + assert(m); + + manager_get_idle_hint(m, &t); + + return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic); +} + +static int property_get_inhibited( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + InhibitWhat w; + + assert(bus); + assert(reply); + assert(m); + + w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY); + + return sd_bus_message_append(reply, "s", inhibit_what_to_string(w)); +} + +static int property_get_preparing( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + bool b; + + assert(bus); + assert(reply); + assert(m); + + if (streq(property, "PreparingForShutdown")) + b = m->action_what & INHIBIT_SHUTDOWN; + else + b = m->action_what & INHIBIT_SLEEP; + + return sd_bus_message_append(reply, "b", b); +} + +static int property_get_scheduled_shutdown( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + int r; + + assert(bus); + assert(reply); + assert(m); + + r = sd_bus_message_open_container(reply, 'r', "st"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout); + if (r < 0) + return r; + + return sd_bus_message_close_container(reply); +} + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction); +static BUS_DEFINE_PROPERTY_GET(property_get_docked, "b", Manager, manager_is_docked_or_external_displays); +static BUS_DEFINE_PROPERTY_GET(property_get_lid_closed, "b", Manager, manager_is_lid_closed); +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_on_external_power, "b", manager_is_on_external_power); +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_compat_user_tasks_max, "t", CGROUP_LIMIT_MAX); +static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "t", Hashmap *, (uint64_t) hashmap_size); + +static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *p = NULL; + Manager *m = userdata; + const char *name; + Session *session; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_get_session_from_creds(m, message, name, error, &session); + if (r < 0) + return r; + + p = session_bus_path(session); + if (!p) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", p); +} + +/* Get login session of a process. This is not what you are looking for these days, + * as apps may instead belong to a user service unit. This includes terminal + * emulators and hence command-line apps. */ +static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *p = NULL; + Session *session = NULL; + Manager *m = userdata; + pid_t pid; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(pid_t) == sizeof(uint32_t)); + + r = sd_bus_message_read(message, "u", &pid); + if (r < 0) + return r; + if (pid < 0) + return -EINVAL; + + if (pid == 0) { + r = manager_get_session_from_creds(m, message, NULL, error, &session); + if (r < 0) + return r; + } else { + r = manager_get_session_by_pid(m, pid, &session); + if (r < 0) + return r; + + if (!session) + return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, + "PID "PID_FMT" does not belong to any known session", pid); + } + + p = session_bus_path(session); + if (!p) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", p); +} + +static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *p = NULL; + Manager *m = userdata; + uint32_t uid; + User *user; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "u", &uid); + if (r < 0) + return r; + + r = manager_get_user_from_creds(m, message, uid, error, &user); + if (r < 0) + return r; + + p = user_bus_path(user); + if (!p) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", p); +} + +static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *p = NULL; + Manager *m = userdata; + User *user = NULL; + pid_t pid; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(pid_t) == sizeof(uint32_t)); + + r = sd_bus_message_read(message, "u", &pid); + if (r < 0) + return r; + if (pid < 0) + return -EINVAL; + + if (pid == 0) { + r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user); + if (r < 0) + return r; + } else { + r = manager_get_user_by_pid(m, pid, &user); + if (r < 0) + return r; + if (!user) + return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, + "PID "PID_FMT" does not belong to any logged in user or lingering user", + pid); + } + + p = user_bus_path(user); + if (!p) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", p); +} + +static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *p = NULL; + Manager *m = userdata; + const char *name; + Seat *seat; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_get_seat_from_creds(m, message, name, error, &seat); + if (r < 0) + return r; + + p = seat_bus_path(seat); + if (!p) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", p); +} + +static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + Session *session; + Iterator i; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(susso)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(session, m->sessions, i) { + _cleanup_free_ char *p = NULL; + + p = session_bus_path(session); + if (!p) + return -ENOMEM; + + r = sd_bus_message_append(reply, "(susso)", + session->id, + (uint32_t) session->user->uid, + session->user->name, + session->seat ? session->seat->id : "", + p); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + User *user; + Iterator i; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(uso)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(user, m->users, i) { + _cleanup_free_ char *p = NULL; + + p = user_bus_path(user); + if (!p) + return -ENOMEM; + + r = sd_bus_message_append(reply, "(uso)", + (uint32_t) user->uid, + user->name, + p); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + Seat *seat; + Iterator i; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(so)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(seat, m->seats, i) { + _cleanup_free_ char *p = NULL; + + p = seat_bus_path(seat); + if (!p) + return -ENOMEM; + + r = sd_bus_message_append(reply, "(so)", seat->id, p); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + Inhibitor *inhibitor; + Iterator i; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(ssssuu)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(inhibitor, m->inhibitors, i) { + + r = sd_bus_message_append(reply, "(ssssuu)", + strempty(inhibit_what_to_string(inhibitor->what)), + strempty(inhibitor->who), + strempty(inhibitor->why), + strempty(inhibit_mode_to_string(inhibitor->mode)), + (uint32_t) inhibitor->uid, + (uint32_t) inhibitor->pid); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop; + _cleanup_free_ char *id = NULL; + Session *session = NULL; + uint32_t audit_id = 0; + Manager *m = userdata; + User *user = NULL; + Seat *seat = NULL; + pid_t leader; + uid_t uid; + int remote; + uint32_t vtnr = 0; + SessionType t; + SessionClass c; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(pid_t) == sizeof(uint32_t)); + assert_cc(sizeof(uid_t) == sizeof(uint32_t)); + + r = sd_bus_message_read(message, "uusssssussbss", + &uid, &leader, &service, &type, &class, &desktop, &cseat, + &vtnr, &tty, &display, &remote, &remote_user, &remote_host); + if (r < 0) + return r; + + if (!uid_is_valid(uid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID"); + if (leader < 0 || leader == 1 || leader == getpid_cached()) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID"); + + if (isempty(type)) + t = _SESSION_TYPE_INVALID; + else { + t = session_type_from_string(type); + if (t < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Invalid session type %s", type); + } + + if (isempty(class)) + c = _SESSION_CLASS_INVALID; + else { + c = session_class_from_string(class); + if (c < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Invalid session class %s", class); + } + + if (isempty(desktop)) + desktop = NULL; + else { + if (!string_is_safe(desktop)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Invalid desktop string %s", desktop); + } + + if (isempty(cseat)) + seat = NULL; + else { + seat = hashmap_get(m->seats, cseat); + if (!seat) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, + "No seat '%s' known", cseat); + } + + if (tty_is_vc(tty)) { + int v; + + if (!seat) + seat = m->seat0; + else if (seat != m->seat0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "TTY %s is virtual console but seat %s is not seat0", tty, seat->id); + + v = vtnr_from_tty(tty); + if (v <= 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Cannot determine VT number from virtual console TTY %s", tty); + + if (vtnr == 0) + vtnr = (uint32_t) v; + else if (vtnr != (uint32_t) v) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Specified TTY and VT number do not match"); + + } else if (tty_is_console(tty)) { + + if (!seat) + seat = m->seat0; + else if (seat != m->seat0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Console TTY specified but seat is not seat0"); + + if (vtnr != 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Console TTY specified but VT number is not 0"); + } + + if (seat) { + if (seat_has_vts(seat)) { + if (vtnr <= 0 || vtnr > 63) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "VT number out of range"); + } else { + if (vtnr != 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Seat has no VTs but VT number not 0"); + } + } + + if (t == _SESSION_TYPE_INVALID) { + if (!isempty(display)) + t = SESSION_X11; + else if (!isempty(tty)) + t = SESSION_TTY; + else + t = SESSION_UNSPECIFIED; + } + + if (c == _SESSION_CLASS_INVALID) { + if (t == SESSION_UNSPECIFIED) + c = SESSION_BACKGROUND; + else + c = SESSION_USER; + } + + if (leader == 0) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, (pid_t*) &leader); + if (r < 0) + return r; + } + + /* Check if we are already in a logind session. Or if we are in user@.service + * which is a special PAM session that avoids creating a logind session. */ + r = manager_get_user_by_pid(m, leader, NULL); + if (r < 0) + return r; + if (r > 0) + return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, + "Already running in a session or user slice"); + + /* + * Old gdm and lightdm start the user-session on the same VT as + * the greeter session. But they destroy the greeter session + * after the user-session and want the user-session to take + * over the VT. We need to support this for + * backwards-compatibility, so make sure we allow new sessions + * on a VT that a greeter is running on. Furthermore, to allow + * re-logins, we have to allow a greeter to take over a used VT for + * the exact same reasons. + */ + if (c != SESSION_GREETER && + vtnr > 0 && + vtnr < m->seat0->position_count && + m->seat0->positions[vtnr] && + m->seat0->positions[vtnr]->class != SESSION_GREETER) + return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session"); + + if (hashmap_size(m->sessions) >= m->sessions_max) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, + "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", + m->sessions_max); + + (void) audit_session_from_pid(leader, &audit_id); + if (audit_session_is_valid(audit_id)) { + /* Keep our session IDs and the audit session IDs in sync */ + + if (asprintf(&id, "%"PRIu32, audit_id) < 0) + return -ENOMEM; + + /* Wut? There's already a session by this name and we didn't find it above? Weird, then let's + * not trust the audit data and let's better register a new ID */ + if (hashmap_contains(m->sessions, id)) { + log_warning("Existing logind session ID %s used by new audit session, ignoring.", id); + audit_id = AUDIT_SESSION_INVALID; + id = mfree(id); + } + } + + if (!id) { + do { + id = mfree(id); + + if (asprintf(&id, "c%lu", ++m->session_counter) < 0) + return -ENOMEM; + + } while (hashmap_contains(m->sessions, id)); + } + + /* The generated names should not clash with 'auto' or 'self' */ + assert(!SESSION_IS_SELF(id)); + assert(!SESSION_IS_AUTO(id)); + + /* If we are not watching utmp already, try again */ + manager_reconnect_utmp(m); + + r = manager_add_user_by_uid(m, uid, &user); + if (r < 0) + goto fail; + + r = manager_add_session(m, id, &session); + if (r < 0) + goto fail; + + session_set_user(session, user); + r = session_set_leader(session, leader); + if (r < 0) + goto fail; + + session->type = t; + session->class = c; + session->remote = remote; + session->vtnr = vtnr; + + if (!isempty(tty)) { + session->tty = strdup(tty); + if (!session->tty) { + r = -ENOMEM; + goto fail; + } + + session->tty_validity = TTY_FROM_PAM; + } + + if (!isempty(display)) { + session->display = strdup(display); + if (!session->display) { + r = -ENOMEM; + goto fail; + } + } + + if (!isempty(remote_user)) { + session->remote_user = strdup(remote_user); + if (!session->remote_user) { + r = -ENOMEM; + goto fail; + } + } + + if (!isempty(remote_host)) { + session->remote_host = strdup(remote_host); + if (!session->remote_host) { + r = -ENOMEM; + goto fail; + } + } + + if (!isempty(service)) { + session->service = strdup(service); + if (!session->service) { + r = -ENOMEM; + goto fail; + } + } + + if (!isempty(desktop)) { + session->desktop = strdup(desktop); + if (!session->desktop) { + r = -ENOMEM; + goto fail; + } + } + + if (seat) { + r = seat_attach_session(seat, session); + if (r < 0) + goto fail; + } + + r = sd_bus_message_enter_container(message, 'a', "(sv)"); + if (r < 0) + goto fail; + + r = session_start(session, message, error); + if (r < 0) + goto fail; + + r = sd_bus_message_exit_container(message); + if (r < 0) + goto fail; + + session->create_message = sd_bus_message_ref(message); + + /* Now, let's wait until the slice unit and stuff got created. We send the reply back from + * session_send_create_reply(). */ + + return 1; + +fail: + if (session) + session_add_to_gc_queue(session); + + if (user) + user_add_to_gc_queue(user); + + return r; +} + +static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + Session *session; + const char *name; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_get_session_from_creds(m, message, name, error, &session); + if (r < 0) + return r; + + r = session_release(session); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + Session *session; + const char *name; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_get_session_from_creds(m, message, name, error, &session); + if (r < 0) + return r; + + return bus_session_method_activate(message, session, error); +} + +static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *session_name, *seat_name; + Manager *m = userdata; + Session *session; + Seat *seat; + int r; + + assert(message); + assert(m); + + /* Same as ActivateSession() but refuses to work if the seat doesn't match */ + + r = sd_bus_message_read(message, "ss", &session_name, &seat_name); + if (r < 0) + return r; + + r = manager_get_session_from_creds(m, message, session_name, error, &session); + if (r < 0) + return r; + + r = manager_get_seat_from_creds(m, message, seat_name, error, &seat); + if (r < 0) + return r; + + if (session->seat != seat) + return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, + "Session %s not on seat %s", session_name, seat_name); + + r = session_activate(session); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + Session *session; + const char *name; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_get_session_from_creds(m, message, name, error, &session); + if (r < 0) + return r; + + return bus_session_method_lock(message, session, error); +} + +static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.lock-sessions", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions")); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *name; + Manager *m = userdata; + Session *session; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_get_session_from_creds(m, message, name, error, &session); + if (r < 0) + return r; + + return bus_session_method_kill(message, session, error); +} + +static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + uint32_t uid; + User *user; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "u", &uid); + if (r < 0) + return r; + + r = manager_get_user_from_creds(m, message, uid, error, &user); + if (r < 0) + return r; + + return bus_user_method_kill(message, user, error); +} + +static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Session *session; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_get_session_from_creds(m, message, name, error, &session); + if (r < 0) + return r; + + return bus_session_method_terminate(message, session, error); +} + +static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + uint32_t uid; + User *user; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "u", &uid); + if (r < 0) + return r; + + r = manager_get_user_from_creds(m, message, uid, error, &user); + if (r < 0) + return r; + + return bus_user_method_terminate(message, user, error); +} + +static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *name; + Seat *seat; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = manager_get_seat_from_creds(m, message, name, error, &seat); + if (r < 0) + return r; + + return bus_seat_method_terminate(message, seat, error); +} + +static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + _cleanup_free_ char *cc = NULL; + Manager *m = userdata; + int r, b, interactive; + struct passwd *pw; + const char *path; + uint32_t uid, auth_uid; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive); + if (r < 0) + return r; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID | + SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); + if (r < 0) + return r; + + if (!uid_is_valid(uid)) { + /* Note that we get the owner UID of the session or user unit, + * not the actual client UID here! */ + r = sd_bus_creds_get_owner_uid(creds, &uid); + if (r < 0) + return r; + } + + /* owner_uid is racy, so for authorization we must use euid */ + r = sd_bus_creds_get_euid(creds, &auth_uid); + if (r < 0) + return r; + + errno = 0; + pw = getpwuid(uid); + if (!pw) + return errno_or_else(ENOENT); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + uid == auth_uid ? "org.freedesktop.login1.set-self-linger" : + "org.freedesktop.login1.set-user-linger", + NULL, + interactive, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + (void) mkdir_p_label("/var/lib/systemd", 0755); + r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + return r; + + cc = cescape(pw->pw_name); + if (!cc) + return -ENOMEM; + + path = strjoina("/var/lib/systemd/linger/", cc); + if (b) { + User *u; + + r = touch(path); + if (r < 0) + return r; + + if (manager_add_user_by_uid(m, uid, &u) >= 0) + user_start(u); + + } else { + User *u; + + r = unlink(path); + if (r < 0 && errno != ENOENT) + return -errno; + + u = hashmap_get(m->users, UID_TO_PTR(uid)); + if (u) + user_add_to_gc_queue(u); + } + + return sd_bus_reply_method_return(message, NULL); +} + +static int trigger_device(Manager *m, sd_device *d) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + int r; + + assert(m); + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + if (d) { + r = sd_device_enumerator_add_match_parent(e, d); + if (r < 0) + return r; + } + + FOREACH_DEVICE(e, d) { + _cleanup_free_ char *t = NULL; + const char *p; + + r = sd_device_get_syspath(d, &p); + if (r < 0) + return r; + + t = path_join(p, "uevent"); + if (!t) + return -ENOMEM; + + (void) write_string_file(t, "change", WRITE_STRING_FILE_DISABLE_BUFFER); + } + + return 0; +} + +static int attach_device(Manager *m, const char *seat, const char *sysfs) { + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + _cleanup_free_ char *rule = NULL, *file = NULL; + const char *id_for_seat; + int r; + + assert(m); + assert(seat); + assert(sysfs); + + r = sd_device_new_from_syspath(&d, sysfs); + if (r < 0) + return r; + + if (sd_device_has_tag(d, "seat") <= 0) + return -ENODEV; + + if (sd_device_get_property_value(d, "ID_FOR_SEAT", &id_for_seat) < 0) + return -ENODEV; + + if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0) + return -ENOMEM; + + if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0) + return -ENOMEM; + + (void) mkdir_p_label("/etc/udev/rules.d", 0755); + r = write_string_file_atomic_label(file, rule); + if (r < 0) + return r; + + return trigger_device(m, d); +} + +static int flush_devices(Manager *m) { + _cleanup_closedir_ DIR *d; + + assert(m); + + d = opendir("/etc/udev/rules.d"); + if (!d) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m"); + } else { + struct dirent *de; + + FOREACH_DIRENT_ALL(de, d, break) { + dirent_ensure_type(d, de); + if (!dirent_is_file(de)) + continue; + + if (!startswith(de->d_name, "72-seat-")) + continue; + + if (!endswith(de->d_name, ".rules")) + continue; + + if (unlinkat(dirfd(d), de->d_name, 0) < 0) + log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name); + } + } + + return trigger_device(m, NULL); +} + +static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *sysfs, *seat; + Manager *m = userdata; + int interactive, r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive); + if (r < 0) + return r; + + if (!path_is_normalized(sysfs)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", sysfs); + if (!path_startswith(sysfs, "/sys")) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs); + + if (SEAT_IS_SELF(seat) || SEAT_IS_AUTO(seat)) { + Seat *found; + + r = manager_get_seat_from_creds(m, message, seat, error, &found); + if (r < 0) + return r; + + seat = found->id; + + } else if (!seat_name_is_valid(seat)) /* Note that a seat does not have to exist yet for this operation to succeed */ + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat name %s is not valid", seat); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.attach-device", + NULL, + interactive, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = attach_device(m, seat, sysfs); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + int interactive, r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "b", &interactive); + if (r < 0) + return r; + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.flush-devices", + NULL, + interactive, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = flush_devices(m); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int have_multiple_sessions( + Manager *m, + uid_t uid) { + + Session *session; + Iterator i; + + assert(m); + + /* Check for other users' sessions. Greeter sessions do not + * count, and non-login sessions do not count either. */ + HASHMAP_FOREACH(session, m->sessions, i) + if (session->class == SESSION_USER && + session->user->uid != uid) + return true; + + return false; +} + +static int bus_manager_log_shutdown( + Manager *m, + const char *unit_name) { + + const char *p, *q; + + assert(m); + assert(unit_name); + + if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) { + p = "MESSAGE=System is powering down"; + q = "SHUTDOWN=power-off"; + } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) { + p = "MESSAGE=System is rebooting"; + q = "SHUTDOWN=reboot"; + } else if (streq(unit_name, SPECIAL_HALT_TARGET)) { + p = "MESSAGE=System is halting"; + q = "SHUTDOWN=halt"; + } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) { + p = "MESSAGE=System is rebooting with kexec"; + q = "SHUTDOWN=kexec"; + } else { + p = "MESSAGE=System is shutting down"; + q = NULL; + } + + if (isempty(m->wall_message)) + p = strjoina(p, "."); + else + p = strjoina(p, " (", m->wall_message, ")."); + + return log_struct(LOG_NOTICE, + "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR, + p, + q); +} + +static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) { + Manager *m = userdata; + + assert(e); + assert(m); + + m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source); + return 0; +} + +int manager_set_lid_switch_ignore(Manager *m, usec_t until) { + int r; + + assert(m); + + if (until <= now(CLOCK_MONOTONIC)) + return 0; + + /* We want to ignore the lid switch for a while after each + * suspend, and after boot-up. Hence let's install a timer for + * this. As long as the event source exists we ignore the lid + * switch. */ + + if (m->lid_switch_ignore_event_source) { + usec_t u; + + r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u); + if (r < 0) + return r; + + if (until <= u) + return 0; + + r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until); + } else + r = sd_event_add_time( + m->event, + &m->lid_switch_ignore_event_source, + CLOCK_MONOTONIC, + until, 0, + lid_switch_ignore_handler, m); + + return r; +} + +static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { + int active = _active; + + assert(m); + assert(IN_SET(w, INHIBIT_SHUTDOWN, INHIBIT_SLEEP)); + + return sd_bus_emit_signal(m->bus, + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + w == INHIBIT_SHUTDOWN ? "PrepareForShutdown" : "PrepareForSleep", + "b", + active); +} + +static int execute_shutdown_or_sleep( + Manager *m, + InhibitWhat w, + const char *unit_name, + sd_bus_error *error) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *p; + int r; + + assert(m); + assert(w > 0); + assert(w < _INHIBIT_WHAT_MAX); + assert(unit_name); + + if (w == INHIBIT_SHUTDOWN) + bus_manager_log_shutdown(m, unit_name); + + r = sd_bus_call_method( + m->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + error, + &reply, + "ss", unit_name, "replace-irreversibly"); + if (r < 0) + goto error; + + r = sd_bus_message_read(reply, "o", &p); + if (r < 0) + goto error; + + r = free_and_strdup(&m->action_job, p); + if (r < 0) + goto error; + + m->action_unit = unit_name; + m->action_what = w; + + /* Make sure the lid switch is ignored for a while */ + manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec); + + return 0; + +error: + /* Tell people that they now may take a lock again */ + (void) send_prepare_for(m, w, false); + + return r; +} + +int manager_dispatch_delayed(Manager *manager, bool timeout) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + Inhibitor *offending = NULL; + int r; + + assert(manager); + + if (manager->action_what == 0 || manager->action_job) + return 0; + + if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) { + _cleanup_free_ char *comm = NULL, *u = NULL; + + if (!timeout) + return 0; + + (void) get_process_comm(offending->pid, &comm); + u = uid_to_name(offending->uid); + + log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.", + offending->uid, strna(u), + offending->pid, strna(comm)); + } + + /* Actually do the operation */ + r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error); + if (r < 0) { + log_warning("Error during inhibitor-delayed operation (already returned success to client): %s", + bus_error_message(&error, r)); + + manager->action_unit = NULL; + manager->action_what = 0; + return r; + } + + return 1; +} + +static int manager_inhibit_timeout_handler( + sd_event_source *s, + uint64_t usec, + void *userdata) { + + Manager *manager = userdata; + int r; + + assert(manager); + assert(manager->inhibit_timeout_source == s); + + r = manager_dispatch_delayed(manager, true); + return (r < 0) ? r : 0; +} + +static int delay_shutdown_or_sleep( + Manager *m, + InhibitWhat w, + const char *unit_name) { + + int r; + usec_t timeout_val; + + assert(m); + assert(w >= 0); + assert(w < _INHIBIT_WHAT_MAX); + assert(unit_name); + + timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max; + + if (m->inhibit_timeout_source) { + r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val); + if (r < 0) + return log_error_errno(r, "sd_event_source_set_time() failed: %m"); + + r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT); + if (r < 0) + return log_error_errno(r, "sd_event_source_set_enabled() failed: %m"); + } else { + r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC, + timeout_val, 0, manager_inhibit_timeout_handler, m); + if (r < 0) + return r; + } + + m->action_unit = unit_name; + m->action_what = w; + + return 0; +} + +int bus_manager_shutdown_or_sleep_now_or_later( + Manager *m, + const char *unit_name, + InhibitWhat w, + sd_bus_error *error) { + + _cleanup_free_ char *load_state = NULL; + bool delayed; + int r; + + assert(m); + assert(unit_name); + assert(w > 0); + assert(w < _INHIBIT_WHAT_MAX); + assert(!m->action_job); + + r = unit_load_state(m->bus, unit_name, &load_state); + if (r < 0) + return r; + + if (!streq(load_state, "loaded")) + return log_notice_errno(SYNTHETIC_ERRNO(EACCES), + "Unit %s is %s, refusing operation.", + unit_name, load_state); + + /* Tell everybody to prepare for shutdown/sleep */ + (void) send_prepare_for(m, w, true); + + delayed = + m->inhibit_delay_max > 0 && + manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL); + + if (delayed) + /* Shutdown is delayed, keep in mind what we + * want to do, and start a timeout */ + r = delay_shutdown_or_sleep(m, w, unit_name); + else + /* Shutdown is not delayed, execute it + * immediately */ + r = execute_shutdown_or_sleep(m, w, unit_name, error); + + return r; +} + +static int verify_shutdown_creds( + Manager *m, + sd_bus_message *message, + InhibitWhat w, + bool interactive, + const char *action, + const char *action_multiple_sessions, + const char *action_ignore_inhibit, + sd_bus_error *error) { + + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + bool multiple_sessions, blocked; + uid_t uid; + int r; + + assert(m); + assert(message); + assert(w >= 0); + assert(w <= _INHIBIT_WHAT_MAX); + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_euid(creds, &uid); + if (r < 0) + return r; + + r = have_multiple_sessions(m, uid); + if (r < 0) + return r; + + multiple_sessions = r > 0; + blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL); + + if (multiple_sessions && action_multiple_sessions) { + r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + } + + if (blocked && action_ignore_inhibit) { + r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + } + + if (!multiple_sessions && !blocked && action) { + r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + } + + return 0; +} + +static int method_do_shutdown_or_sleep( + Manager *m, + sd_bus_message *message, + const char *unit_name, + InhibitWhat w, + const char *action, + const char *action_multiple_sessions, + const char *action_ignore_inhibit, + const char *sleep_verb, + sd_bus_error *error) { + + int interactive, r; + + assert(m); + assert(message); + assert(unit_name); + assert(w >= 0); + assert(w <= _INHIBIT_WHAT_MAX); + + r = sd_bus_message_read(message, "b", &interactive); + if (r < 0) + return r; + + /* Don't allow multiple jobs being executed at the same time */ + if (m->action_what > 0) + return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, + "There's already a shutdown or sleep operation in progress"); + + if (sleep_verb) { + r = can_sleep(sleep_verb); + if (r == -ENOSPC) + return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, + "Not enough swap space for hibernation"); + if (r == 0) + return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, + "Sleep verb \"%s\" not supported", sleep_verb); + if (r < 0) + return r; + } + + r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions, + action_ignore_inhibit, error); + if (r != 0) + return r; + + r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_do_shutdown_or_sleep( + m, message, + SPECIAL_POWEROFF_TARGET, + INHIBIT_SHUTDOWN, + "org.freedesktop.login1.power-off", + "org.freedesktop.login1.power-off-multiple-sessions", + "org.freedesktop.login1.power-off-ignore-inhibit", + NULL, + error); +} + +static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_do_shutdown_or_sleep( + m, message, + SPECIAL_REBOOT_TARGET, + INHIBIT_SHUTDOWN, + "org.freedesktop.login1.reboot", + "org.freedesktop.login1.reboot-multiple-sessions", + "org.freedesktop.login1.reboot-ignore-inhibit", + NULL, + error); +} + +static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_do_shutdown_or_sleep( + m, message, + SPECIAL_HALT_TARGET, + INHIBIT_SHUTDOWN, + "org.freedesktop.login1.halt", + "org.freedesktop.login1.halt-multiple-sessions", + "org.freedesktop.login1.halt-ignore-inhibit", + NULL, + error); +} + +static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_do_shutdown_or_sleep( + m, message, + SPECIAL_SUSPEND_TARGET, + INHIBIT_SLEEP, + "org.freedesktop.login1.suspend", + "org.freedesktop.login1.suspend-multiple-sessions", + "org.freedesktop.login1.suspend-ignore-inhibit", + "suspend", + error); +} + +static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_do_shutdown_or_sleep( + m, message, + SPECIAL_HIBERNATE_TARGET, + INHIBIT_SLEEP, + "org.freedesktop.login1.hibernate", + "org.freedesktop.login1.hibernate-multiple-sessions", + "org.freedesktop.login1.hibernate-ignore-inhibit", + "hibernate", + error); +} + +static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_do_shutdown_or_sleep( + m, message, + SPECIAL_HYBRID_SLEEP_TARGET, + INHIBIT_SLEEP, + "org.freedesktop.login1.hibernate", + "org.freedesktop.login1.hibernate-multiple-sessions", + "org.freedesktop.login1.hibernate-ignore-inhibit", + "hybrid-sleep", + error); +} + +static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_do_shutdown_or_sleep( + m, message, + SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, + INHIBIT_SLEEP, + "org.freedesktop.login1.hibernate", + "org.freedesktop.login1.hibernate-multiple-sessions", + "org.freedesktop.login1.hibernate-ignore-inhibit", + "hybrid-sleep", + error); +} + +static int nologin_timeout_handler( + sd_event_source *s, + uint64_t usec, + void *userdata) { + + Manager *m = userdata; + + log_info("Creating /run/nologin, blocking further logins..."); + + m->unlink_nologin = + create_shutdown_run_nologin_or_warn() >= 0; + + return 0; +} + +static int update_schedule_file(Manager *m) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(m); + + r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + return log_error_errno(r, "Failed to create shutdown subdirectory: %m"); + + r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path); + if (r < 0) + return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m"); + + (void) fchmod(fileno(f), 0644); + + fprintf(f, + "USEC="USEC_FMT"\n" + "WARN_WALL=%i\n" + "MODE=%s\n", + m->scheduled_shutdown_timeout, + m->enable_wall_messages, + m->scheduled_shutdown_type); + + if (!isempty(m->wall_message)) { + _cleanup_free_ char *t; + + t = cescape(m->wall_message); + if (!t) { + r = -ENOMEM; + goto fail; + } + + fprintf(f, "WALL_MESSAGE=%s\n", t); + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + (void) unlink(temp_path); + (void) unlink("/run/systemd/shutdown/scheduled"); + + return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m"); +} + +static void reset_scheduled_shutdown(Manager *m) { + assert(m); + + m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source); + m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source); + m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source); + + m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type); + m->scheduled_shutdown_timeout = 0; + m->shutdown_dry_run = false; + + if (m->unlink_nologin) { + (void) unlink_or_warn("/run/nologin"); + m->unlink_nologin = false; + } + + (void) unlink("/run/systemd/shutdown/scheduled"); +} + +static int manager_scheduled_shutdown_handler( + sd_event_source *s, + uint64_t usec, + void *userdata) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + Manager *m = userdata; + const char *target; + int r; + + assert(m); + + if (isempty(m->scheduled_shutdown_type)) + return 0; + + if (streq(m->scheduled_shutdown_type, "poweroff")) + target = SPECIAL_POWEROFF_TARGET; + else if (streq(m->scheduled_shutdown_type, "reboot")) + target = SPECIAL_REBOOT_TARGET; + else if (streq(m->scheduled_shutdown_type, "halt")) + target = SPECIAL_HALT_TARGET; + else + assert_not_reached("unexpected shutdown type"); + + /* Don't allow multiple jobs being executed at the same time */ + if (m->action_what > 0) { + r = -EALREADY; + log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target); + goto error; + } + + if (m->shutdown_dry_run) { + /* We do not process delay inhibitors here. Otherwise, we + * would have to be considered "in progress" (like the check + * above) for some seconds after our admin has seen the final + * wall message. */ + + bus_manager_log_shutdown(m, target); + log_info("Running in dry run, suppressing action."); + reset_scheduled_shutdown(m); + + return 0; + } + + r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error); + if (r < 0) { + log_error_errno(r, "Scheduled shutdown to %s failed: %m", target); + goto error; + } + + return 0; + +error: + reset_scheduled_shutdown(m); + return r; +} + +static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + const char *action_multiple_sessions = NULL; + const char *action_ignore_inhibit = NULL; + const char *action = NULL; + uint64_t elapse; + char *type; + int r; + bool dry_run = false; + + assert(m); + assert(message); + + r = sd_bus_message_read(message, "st", &type, &elapse); + if (r < 0) + return r; + + if (startswith(type, "dry-")) { + type += 4; + dry_run = true; + } + + if (streq(type, "poweroff")) { + action = "org.freedesktop.login1.power-off"; + action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions"; + action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit"; + } else if (streq(type, "reboot")) { + action = "org.freedesktop.login1.reboot"; + action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions"; + action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit"; + } else if (streq(type, "halt")) { + action = "org.freedesktop.login1.halt"; + action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions"; + action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit"; + } else + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type"); + + r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false, + action, action_multiple_sessions, action_ignore_inhibit, error); + if (r != 0) + return r; + + if (m->scheduled_shutdown_timeout_source) { + r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse); + if (r < 0) + return log_error_errno(r, "sd_event_source_set_time() failed: %m"); + + r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT); + if (r < 0) + return log_error_errno(r, "sd_event_source_set_enabled() failed: %m"); + } else { + r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source, + CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m); + if (r < 0) + return log_error_errno(r, "sd_event_add_time() failed: %m"); + } + + r = free_and_strdup(&m->scheduled_shutdown_type, type); + if (r < 0) { + m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source); + return log_oom(); + } + + m->shutdown_dry_run = dry_run; + + if (m->nologin_timeout_source) { + r = sd_event_source_set_time(m->nologin_timeout_source, elapse); + if (r < 0) + return log_error_errno(r, "sd_event_source_set_time() failed: %m"); + + r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT); + if (r < 0) + return log_error_errno(r, "sd_event_source_set_enabled() failed: %m"); + } else { + r = sd_event_add_time(m->event, &m->nologin_timeout_source, + CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m); + if (r < 0) + return log_error_errno(r, "sd_event_add_time() failed: %m"); + } + + m->scheduled_shutdown_timeout = elapse; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds); + if (r >= 0) { + const char *tty = NULL; + + (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid); + (void) sd_bus_creds_get_tty(creds, &tty); + + r = free_and_strdup(&m->scheduled_shutdown_tty, tty); + if (r < 0) { + m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source); + return log_oom(); + } + } + + r = manager_setup_wall_message_timer(m); + if (r < 0) + return r; + + r = update_schedule_file(m); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + bool cancelled; + + assert(m); + assert(message); + + cancelled = m->scheduled_shutdown_type != NULL; + reset_scheduled_shutdown(m); + + if (cancelled && m->enable_wall_messages) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + _cleanup_free_ char *username = NULL; + const char *tty = NULL; + uid_t uid = 0; + int r; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds); + if (r >= 0) { + (void) sd_bus_creds_get_uid(creds, &uid); + (void) sd_bus_creds_get_tty(creds, &tty); + } + + username = uid_to_name(uid); + utmp_wall("The system shutdown has been cancelled", + username, tty, logind_wall_tty_filter, m); + } + + return sd_bus_reply_method_return(message, "b", cancelled); +} + +static int method_can_shutdown_or_sleep( + Manager *m, + sd_bus_message *message, + InhibitWhat w, + const char *action, + const char *action_multiple_sessions, + const char *action_ignore_inhibit, + const char *sleep_verb, + sd_bus_error *error) { + + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + HandleAction handle; + bool multiple_sessions, challenge, blocked; + const char *result = NULL; + uid_t uid; + int r; + + assert(m); + assert(message); + assert(w >= 0); + assert(w <= _INHIBIT_WHAT_MAX); + assert(action); + assert(action_multiple_sessions); + assert(action_ignore_inhibit); + + if (sleep_verb) { + r = can_sleep(sleep_verb); + if (IN_SET(r, 0, -ENOSPC)) + return sd_bus_reply_method_return(message, "s", "na"); + if (r < 0) + return r; + } + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_euid(creds, &uid); + if (r < 0) + return r; + + r = have_multiple_sessions(m, uid); + if (r < 0) + return r; + + multiple_sessions = r > 0; + blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL); + + handle = handle_action_from_string(sleep_verb); + if (handle >= 0) { + const char *target; + + target = manager_target_for_action(handle); + if (target) { + _cleanup_free_ char *load_state = NULL; + + r = unit_load_state(m->bus, target, &load_state); + if (r < 0) + return r; + + if (!streq(load_state, "loaded")) { + result = "no"; + goto finish; + } + } + } + + if (multiple_sessions) { + r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error); + if (r < 0) + return r; + + if (r > 0) + result = "yes"; + else if (challenge) + result = "challenge"; + else + result = "no"; + } + + if (blocked) { + r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error); + if (r < 0) + return r; + + if (r > 0) { + if (!result) + result = "yes"; + } else if (challenge) { + if (!result || streq(result, "yes")) + result = "challenge"; + } else + result = "no"; + } + + if (!multiple_sessions && !blocked) { + /* If neither inhibit nor multiple sessions + * apply then just check the normal policy */ + + r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error); + if (r < 0) + return r; + + if (r > 0) + result = "yes"; + else if (challenge) + result = "challenge"; + else + result = "no"; + } + + finish: + return sd_bus_reply_method_return(message, "s", result); +} + +static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_can_shutdown_or_sleep( + m, message, + INHIBIT_SHUTDOWN, + "org.freedesktop.login1.power-off", + "org.freedesktop.login1.power-off-multiple-sessions", + "org.freedesktop.login1.power-off-ignore-inhibit", + NULL, + error); +} + +static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_can_shutdown_or_sleep( + m, message, + INHIBIT_SHUTDOWN, + "org.freedesktop.login1.reboot", + "org.freedesktop.login1.reboot-multiple-sessions", + "org.freedesktop.login1.reboot-ignore-inhibit", + NULL, + error); +} + +static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_can_shutdown_or_sleep( + m, message, + INHIBIT_SHUTDOWN, + "org.freedesktop.login1.halt", + "org.freedesktop.login1.halt-multiple-sessions", + "org.freedesktop.login1.halt-ignore-inhibit", + NULL, + error); +} + +static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_can_shutdown_or_sleep( + m, message, + INHIBIT_SLEEP, + "org.freedesktop.login1.suspend", + "org.freedesktop.login1.suspend-multiple-sessions", + "org.freedesktop.login1.suspend-ignore-inhibit", + "suspend", + error); +} + +static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_can_shutdown_or_sleep( + m, message, + INHIBIT_SLEEP, + "org.freedesktop.login1.hibernate", + "org.freedesktop.login1.hibernate-multiple-sessions", + "org.freedesktop.login1.hibernate-ignore-inhibit", + "hibernate", + error); +} + +static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_can_shutdown_or_sleep( + m, message, + INHIBIT_SLEEP, + "org.freedesktop.login1.hibernate", + "org.freedesktop.login1.hibernate-multiple-sessions", + "org.freedesktop.login1.hibernate-ignore-inhibit", + "hybrid-sleep", + error); +} + +static int method_can_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + return method_can_shutdown_or_sleep( + m, message, + INHIBIT_SLEEP, + "org.freedesktop.login1.hibernate", + "org.freedesktop.login1.hibernate-multiple-sessions", + "org.freedesktop.login1.hibernate-ignore-inhibit", + "suspend-then-hibernate", + error); +} + +static int property_get_reboot_parameter( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + _cleanup_free_ char *parameter = NULL; + int r; + + assert(bus); + assert(reply); + assert(userdata); + + r = read_reboot_parameter(¶meter); + if (r < 0) + return r; + + return sd_bus_message_append(reply, "s", parameter); +} + +static int method_set_reboot_parameter( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + const char *arg; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &arg); + if (r < 0) + return r; + + r = detect_container(); + if (r < 0) + return r; + if (r > 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, + "Reboot parameter not supported in containers, refusing."); + + r = bus_verify_polkit_async(message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.set-reboot-parameter", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = update_reboot_parameter_and_warn(arg, false); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_can_reboot_parameter( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = detect_container(); + if (r < 0) + return r; + if (r > 0) /* Inside containers, specifying a reboot parameter, doesn't make much sense */ + return sd_bus_reply_method_return(message, "s", "na"); + + return return_test_polkit( + message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.set-reboot-parameter", + NULL, + UID_INVALID, + error); +} + +static int property_get_reboot_to_firmware_setup( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + int r; + + assert(bus); + assert(reply); + assert(userdata); + + r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP"); + if (r == -ENXIO) { + /* EFI case: let's see what is currently configured in the EFI variables */ + r = efi_get_reboot_to_firmware(); + if (r < 0 && r != -EOPNOTSUPP) + log_warning_errno(r, "Failed to determine reboot-to-firmware-setup state: %m"); + } else if (r < 0) + log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m"); + else if (r > 0) { + /* Non-EFI case: let's see whether /run/systemd/reboot-to-firmware-setup exists. */ + if (access("/run/systemd/reboot-to-firmware-setup", F_OK) < 0) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to check whether /run/systemd/reboot-to-firmware-setup exists: %m"); + + r = false; + } else + r = true; + } + + return sd_bus_message_append(reply, "b", r > 0); +} + +static int method_set_reboot_to_firmware_setup( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + bool use_efi; + int b, r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP"); + if (r == -ENXIO) { + /* EFI case: let's see what the firmware supports */ + + r = efi_reboot_to_firmware_supported(); + if (r == -EOPNOTSUPP) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware."); + if (r < 0) + return r; + + use_efi = true; + + } else if (r <= 0) { + /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to off */ + + if (r < 0) + log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m"); + + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware."); + } else + /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to on */ + use_efi = false; + + r = bus_verify_polkit_async(message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.set-reboot-to-firmware-setup", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + if (use_efi) { + r = efi_set_reboot_to_firmware(b); + if (r < 0) + return r; + } else { + if (b) { + r = touch("/run/systemd/reboot-to-firmware-setup"); + if (r < 0) + return r; + } else { + if (unlink("/run/systemd/reboot-to-firmware-setup") < 0 && errno != ENOENT) + return -errno; + } + } + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_can_reboot_to_firmware_setup( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP"); + if (r == -ENXIO) { + /* EFI case: let's see what the firmware supports */ + + r = efi_reboot_to_firmware_supported(); + if (r < 0) { + if (r != -EOPNOTSUPP) + log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m"); + + return sd_bus_reply_method_return(message, "s", "na"); + } + + } else if (r <= 0) { + /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP */ + + if (r < 0) + log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m"); + + return sd_bus_reply_method_return(message, "s", "na"); + } + + return return_test_polkit( + message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.set-reboot-to-firmware-setup", + NULL, + UID_INVALID, + error); +} + +static int property_get_reboot_to_boot_loader_menu( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + uint64_t x = UINT64_MAX; + int r; + + assert(bus); + assert(reply); + assert(userdata); + + r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU"); + if (r == -ENXIO) { + _cleanup_free_ char *v = NULL; + + /* EFI case: returns the current value of LoaderConfigTimeoutOneShot. Three cases are distuingished: + * + * 1. Variable not set, boot into boot loader menu is not enabled (we return UINT64_MAX to the user) + * 2. Variable set to "0", boot into boot loader menu is enabled with no timeout (we return 0 to the user) + * 3. Variable set to numeric value formatted in ASCII, boot into boot loader menu with the specified timeout in seconds + */ + + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v); + if (r < 0) { + if (r != -ENOENT) + log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable: %m"); + } else { + uint64_t sec; + + r = safe_atou64(v, &sec); + if (r < 0) + log_warning_errno(r, "Failed to parse LoaderConfigTimeoutOneShot value '%s': %m", v); + else if (sec > (USEC_INFINITY / USEC_PER_SEC)) + log_warning("LoaderConfigTimeoutOneShot too large, ignoring: %m"); + else + x = sec * USEC_PER_SEC; /* return in µs */ + } + + } else if (r < 0) + log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m"); + else if (r > 0) { + _cleanup_free_ char *v = NULL; + + /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-menu. */ + + r = read_one_line_file("/run/systemd/reboot-to-boot-loader-menu", &v); + if (r < 0) { + if (r != -ENOENT) + log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-menu: %m"); + } else { + r = safe_atou64(v, &x); + if (r < 0) + log_warning_errno(r, "Failed to parse /run/systemd/reboot-to-boot-loader-menu: %m"); + } + } + + return sd_bus_message_append(reply, "t", x); +} + +static int method_set_reboot_to_boot_loader_menu( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + bool use_efi; + uint64_t x; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "t", &x); + if (r < 0) + return r; + + r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU"); + if (r == -ENXIO) { + uint64_t features; + + /* EFI case: let's see if booting into boot loader menu is supported. */ + + r = efi_loader_get_features(&features); + if (r < 0) + log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m"); + if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu."); + + use_efi = true; + + } else if (r <= 0) { + /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to off */ + + if (r < 0) + log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m"); + + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu."); + } else + /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to on */ + use_efi = false; + + r = bus_verify_polkit_async(message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.set-reboot-to-boot-loader-menu", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + if (use_efi) { + if (x == UINT64_MAX) + r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", NULL, 0); + else { + char buf[DECIMAL_STR_MAX(uint64_t) + 1]; + xsprintf(buf, "%" PRIu64, DIV_ROUND_UP(x, USEC_PER_SEC)); /* second granularity */ + + r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", buf); + } + if (r < 0) + return r; + } else { + if (x == UINT64_MAX) { + if (unlink("/run/systemd/reboot-to-loader-menu") < 0 && errno != ENOENT) + return -errno; + } else { + char buf[DECIMAL_STR_MAX(uint64_t) + 1]; + + xsprintf(buf, "%" PRIu64, x); /* µs granularity */ + + r = write_string_file_atomic_label("/run/systemd/reboot-to-loader-menu", buf); + if (r < 0) + return r; + } + } + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_can_reboot_to_boot_loader_menu( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU"); + if (r == -ENXIO) { + uint64_t features = 0; + + /* EFI case, let's see if booting into boot loader menu is supported. */ + + r = efi_loader_get_features(&features); + if (r < 0) + log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m"); + if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT)) + return sd_bus_reply_method_return(message, "s", "na"); + + } else if (r <= 0) { + /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU */ + + if (r < 0) + log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m"); + + return sd_bus_reply_method_return(message, "s", "na"); + } + + return return_test_polkit( + message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.set-reboot-to-boot-loader-menu", + NULL, + UID_INVALID, + error); +} + +static int property_get_reboot_to_boot_loader_entry( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *v = NULL; + int r; + + assert(bus); + assert(reply); + assert(userdata); + + r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY"); + if (r == -ENXIO) { + /* EFI case: let's read the LoaderEntryOneShot variable */ + + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &v); + if (r < 0) { + if (r != -ENOENT) + log_warning_errno(r, "Failed to read LoaderEntryOneShot variable: %m"); + } else if (!efi_loader_entry_name_valid(v)) { + log_warning("LoaderEntryOneShot contains invalid entry name '%s', ignoring.", v); + v = mfree(v); + } + } else if (r < 0) + log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m"); + else if (r > 0) { + + /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-entry. */ + + r = read_one_line_file("/run/systemd/reboot-to-boot-loader-entry", &v); + if (r < 0) { + if (r != -ENOENT) + log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-entry: %m"); + } else if (!efi_loader_entry_name_valid(v)) { + log_warning("/run/systemd/reboot-to-boot-loader-entry is not valid, ignoring."); + v = mfree(v); + } + } + + return sd_bus_message_append(reply, "s", v); +} + +static int boot_loader_entry_exists(const char *id) { + _cleanup_(boot_config_free) BootConfig config = {}; + int r; + + assert(id); + + r = boot_entries_load_config_auto(NULL, NULL, &config); + if (r < 0 && r != -ENOKEY) /* don't complain if no GPT is found, hence skip ENOKEY */ + return r; + + (void) boot_entries_augment_from_loader(&config, true); + + return boot_config_has_entry(&config, id); +} + +static int method_set_reboot_to_boot_loader_entry( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + bool use_efi; + const char *v; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &v); + if (r < 0) + return r; + + if (isempty(v)) + v = NULL; + else if (efi_loader_entry_name_valid(v)) { + r = boot_loader_entry_exists(v); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader entry '%s' is not known.", v); + } else + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Boot loader entry name '%s' is not valid, refusing.", v); + + r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY"); + if (r == -ENXIO) { + uint64_t features; + + /* EFI case: let's see if booting into boot loader entry is supported. */ + + r = efi_loader_get_features(&features); + if (r < 0) + log_warning_errno(r, "Failed to determine whether reboot into boot loader entry is supported: %m"); + if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry."); + + use_efi = true; + + } else if (r <= 0) { + /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to off */ + + if (r < 0) + log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m"); + + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry."); + } else + /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to on */ + use_efi = false; + + r = bus_verify_polkit_async(message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.set-reboot-to-boot-loader-entry", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + if (use_efi) { + if (isempty(v)) + /* Delete item */ + r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderEntryOneShot", NULL, 0); + else + r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", v); + if (r < 0) + return r; + } else { + if (isempty(v)) { + if (unlink("/run/systemd/reboot-to-boot-loader-entry") < 0 && errno != ENOENT) + return -errno; + } else { + r = write_string_file_atomic_label("/run/systemd/reboot-boot-to-loader-entry", v); + if (r < 0) + return r; + } + } + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_can_reboot_to_boot_loader_entry( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + int r; + + assert(message); + assert(m); + + r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY"); + if (r == -ENXIO) { + uint64_t features = 0; + + /* EFI case, let's see if booting into boot loader entry is supported. */ + + r = efi_loader_get_features(&features); + if (r < 0) + log_warning_errno(r, "Failed to determine whether reboot to boot loader entry is supported: %m"); + if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT)) + return sd_bus_reply_method_return(message, "s", "na"); + + } else if (r <= 0) { + /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY */ + + if (r < 0) + log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m"); + + return sd_bus_reply_method_return(message, "s", "na"); + } + + return return_test_polkit( + message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.set-reboot-to-boot-loader-entry", + NULL, + UID_INVALID, + error); +} + +static int property_get_boot_loader_entries( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_(boot_config_free) BootConfig config = {}; + size_t i; + int r; + + assert(bus); + assert(reply); + assert(userdata); + + r = boot_entries_load_config_auto(NULL, NULL, &config); + if (r < 0 && r != -ENOKEY) /* don't complain if there's no GPT found */ + return r; + + (void) boot_entries_augment_from_loader(&config, true); + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + for (i = 0; i < config.n_entries; i++) { + BootEntry *e = config.entries + i; + + r = sd_bus_message_append(reply, "s", e->id); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int method_set_wall_message( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + int r; + Manager *m = userdata; + char *wall_message; + unsigned enable_wall_messages; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.set-wall-message", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = free_and_strdup(&m->wall_message, empty_to_null(wall_message)); + if (r < 0) + return log_oom(); + + m->enable_wall_messages = enable_wall_messages; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + const char *who, *why, *what, *mode; + _cleanup_free_ char *id = NULL; + _cleanup_close_ int fifo_fd = -1; + Manager *m = userdata; + Inhibitor *i = NULL; + InhibitMode mm; + InhibitWhat w; + pid_t pid; + uid_t uid; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode); + if (r < 0) + return r; + + w = inhibit_what_from_string(what); + if (w <= 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Invalid what specification %s", what); + + mm = inhibit_mode_from_string(mode); + if (mm < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Invalid mode specification %s", mode); + + /* Delay is only supported for shutdown/sleep */ + if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP))) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Delay inhibitors only supported for shutdown and sleep"); + + /* Don't allow taking delay locks while we are already + * executing the operation. We shouldn't create the impression + * that the lock was successful if the machine is about to go + * down/suspend any moment. */ + if (m->action_what & w) + return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, + "The operation inhibition has been requested for is already running"); + + r = bus_verify_polkit_async( + message, + CAP_SYS_BOOT, + w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") : + w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") : + w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" : + w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" : + w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" : + w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" : + "org.freedesktop.login1.inhibit-handle-lid-switch", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_euid(creds, &uid); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + + if (hashmap_size(m->inhibitors) >= m->inhibitors_max) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, + "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", + m->inhibitors_max); + + do { + id = mfree(id); + + if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0) + return -ENOMEM; + + } while (hashmap_get(m->inhibitors, id)); + + r = manager_add_inhibitor(m, id, &i); + if (r < 0) + return r; + + i->what = w; + i->mode = mm; + i->pid = pid; + i->uid = uid; + i->why = strdup(why); + i->who = strdup(who); + + if (!i->why || !i->who) { + r = -ENOMEM; + goto fail; + } + + fifo_fd = inhibitor_create_fifo(i); + if (fifo_fd < 0) { + r = fifo_fd; + goto fail; + } + + r = inhibitor_start(i); + if (r < 0) + goto fail; + + return sd_bus_reply_method_return(message, "h", fifo_fd); + +fail: + if (i) + inhibitor_free(i); + + return r; +} + +const sd_bus_vtable manager_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0), + SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0), + + SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RebootParameter", "s", property_get_reboot_parameter, 0, 0), + SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, 0), + SD_BUS_PROPERTY("RebootToBootLoaderMenu", "t", property_get_reboot_to_boot_loader_menu, 0, 0), + SD_BUS_PROPERTY("RebootToBootLoaderEntry", "s", property_get_reboot_to_boot_loader_entry, 0, 0), + SD_BUS_PROPERTY("BootLoaderEntries", "as", property_get_boot_loader_entries, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("UserStopDelayUSec", "t", NULL, offsetof(Manager, user_stop_delay), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0), + SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0), + SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0), + SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0), + SD_BUS_PROPERTY("LidClosed", "b", property_get_lid_closed, 0, 0), + SD_BUS_PROPERTY("OnExternalPower", "b", property_get_on_external_power, 0, 0), + SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RuntimeDirectorySize", "t", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_hashmap_size, offsetof(Manager, inhibitors), 0), + SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0), + SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + + SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0), + SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0), + SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SuspendThenHibernate", "b", NULL, method_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanSuspendThenHibernate", NULL, "s", method_can_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanRebootParameter", NULL, "s", method_can_reboot_parameter, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetRebootParameter", "s", NULL, method_set_reboot_parameter, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanRebootToBootLoaderMenu", NULL, "s", method_can_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetRebootToBootLoaderMenu", "t", NULL, method_set_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanRebootToBootLoaderEntry", NULL, "s", method_can_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetRebootToBootLoaderEntry", "s", NULL, method_set_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_SIGNAL("SessionNew", "so", 0), + SD_BUS_SIGNAL("SessionRemoved", "so", 0), + SD_BUS_SIGNAL("UserNew", "uo", 0), + SD_BUS_SIGNAL("UserRemoved", "uo", 0), + SD_BUS_SIGNAL("SeatNew", "so", 0), + SD_BUS_SIGNAL("SeatRemoved", "so", 0), + SD_BUS_SIGNAL("PrepareForShutdown", "b", 0), + SD_BUS_SIGNAL("PrepareForSleep", "b", 0), + + SD_BUS_VTABLE_END +}; + +static int session_jobs_reply(Session *s, const char *unit, const char *result) { + assert(s); + assert(unit); + + if (!s->started) + return 0; + + if (result && !streq(result, "done")) { + _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL; + + sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, + "Start job for unit '%s' failed with '%s'", unit, result); + return session_send_create_reply(s, &e); + } + + return session_send_create_reply(s, NULL); +} + +int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *path, *result, *unit; + Manager *m = userdata; + Session *session; + uint32_t id; + User *user; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + if (m->action_job && streq(m->action_job, path)) { + log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what)); + + /* Tell people that they now may take a lock again */ + (void) send_prepare_for(m, m->action_what, false); + + m->action_job = mfree(m->action_job); + m->action_unit = NULL; + m->action_what = 0; + return 0; + } + + session = hashmap_get(m->session_units, unit); + if (session) { + if (streq_ptr(path, session->scope_job)) { + session->scope_job = mfree(session->scope_job); + (void) session_jobs_reply(session, unit, result); + + session_save(session); + user_save(session->user); + } + + session_add_to_gc_queue(session); + } + + user = hashmap_get(m->user_units, unit); + if (user) { + if (streq_ptr(path, user->service_job)) { + user->service_job = mfree(user->service_job); + + LIST_FOREACH(sessions_by_user, session, user->sessions) + (void) session_jobs_reply(session, unit, NULL /* don't propagate user service failures to the client */); + + user_save(user); + } + + user_add_to_gc_queue(user); + } + + return 0; +} + +int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *path, *unit; + Manager *m = userdata; + Session *session; + User *user; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "so", &unit, &path); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + session = hashmap_get(m->session_units, unit); + if (session) + session_add_to_gc_queue(session); + + user = hashmap_get(m->user_units, unit); + if (user) + user_add_to_gc_queue(user); + + return 0; +} + +int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *unit = NULL; + Manager *m = userdata; + const char *path; + Session *session; + User *user; + int r; + + assert(message); + assert(m); + + path = sd_bus_message_get_path(message); + if (!path) + return 0; + + r = unit_name_from_dbus_path(path, &unit); + if (r == -EINVAL) /* not a unit */ + return 0; + if (r < 0) { + log_oom(); + return 0; + } + + session = hashmap_get(m->session_units, unit); + if (session) + session_add_to_gc_queue(session); + + user = hashmap_get(m->user_units, unit); + if (user) + user_add_to_gc_queue(user); + + return 0; +} + +int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + Session *session; + Iterator i; + int b, r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + if (b) + return 0; + + /* systemd finished reloading, let's recheck all our sessions */ + log_debug("System manager has been reloaded, rechecking sessions..."); + + HASHMAP_FOREACH(session, m->sessions, i) + session_add_to_gc_queue(session); + + return 0; +} + +int manager_send_changed(Manager *manager, const char *property, ...) { + char **l; + + assert(manager); + + l = strv_from_stdarg_alloca(property); + + return sd_bus_emit_properties_changed_strv( + manager->bus, + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + l); +} + +static int strdup_job(sd_bus_message *reply, char **job) { + const char *j; + char *copy; + int r; + + r = sd_bus_message_read(reply, "o", &j); + if (r < 0) + return r; + + copy = strdup(j); + if (!copy) + return -ENOMEM; + + *job = copy; + return 1; +} + +int manager_start_scope( + Manager *manager, + const char *scope, + pid_t pid, + const char *slice, + const char *description, + char **wants, + char **after, + const char *requires_mounts_for, + sd_bus_message *more_properties, + sd_bus_error *error, + char **job) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + char **i; + int r; + + assert(manager); + assert(scope); + assert(pid > 1); + assert(job); + + r = sd_bus_message_new_method_call( + manager->bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "ss", strempty(scope), "fail"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return r; + + if (!isempty(slice)) { + r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice); + if (r < 0) + return r; + } + + if (!isempty(description)) { + r = sd_bus_message_append(m, "(sv)", "Description", "s", description); + if (r < 0) + return r; + } + + STRV_FOREACH(i, wants) { + r = sd_bus_message_append(m, "(sv)", "Wants", "as", 1, *i); + if (r < 0) + return r; + } + + STRV_FOREACH(i, after) { + r = sd_bus_message_append(m, "(sv)", "After", "as", 1, *i); + if (r < 0) + return r; + } + + if (!empty_or_root(requires_mounts_for)) { + r = sd_bus_message_append(m, "(sv)", "RequiresMountsFor", "as", 1, requires_mounts_for); + if (r < 0) + return r; + } + + /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore + * SIGTERM */ + r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid); + if (r < 0) + return r; + + /* disable TasksMax= for the session scope, rely on the slice setting for it */ + r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", (uint64_t)-1); + if (r < 0) + return bus_log_create_error(r); + + if (more_properties) { + /* If TasksMax also appears here, it will overwrite the default value set above */ + r = sd_bus_message_copy(m, more_properties, true); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "a(sa(sv))", 0); + if (r < 0) + return r; + + r = sd_bus_call(manager->bus, m, 0, error, &reply); + if (r < 0) + return r; + + return strdup_job(reply, job); +} + +int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + assert(manager); + assert(unit); + assert(job); + + r = sd_bus_call_method( + manager->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + error, + &reply, + "ss", unit, "replace"); + if (r < 0) + return r; + + return strdup_job(reply, job); +} + +int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + assert(manager); + assert(unit); + assert(job); + + r = sd_bus_call_method( + manager->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StopUnit", + error, + &reply, + "ss", unit, "fail"); + if (r < 0) { + if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || + sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) { + + *job = NULL; + sd_bus_error_free(error); + return 0; + } + + return r; + } + + return strdup_job(reply, job); +} + +int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *ret_error) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + int r; + + assert(manager); + assert(scope); + + path = unit_dbus_path_from_name(scope); + if (!path) + return -ENOMEM; + + r = sd_bus_call_method( + manager->bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Scope", + "Abandon", + &error, + NULL, + NULL); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || + sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED) || + sd_bus_error_has_name(&error, BUS_ERROR_SCOPE_NOT_RUNNING)) + return 0; + + sd_bus_error_move(ret_error, &error); + return r; + } + + return 1; +} + +int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) { + assert(manager); + assert(unit); + + return sd_bus_call_method( + manager->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "KillUnit", + error, + NULL, + "ssi", unit, who == KILL_LEADER ? "main" : "all", signo); +} + +int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *ret_error) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *path = NULL; + const char *state; + int r; + + assert(manager); + assert(unit); + + path = unit_dbus_path_from_name(unit); + if (!path) + return -ENOMEM; + + r = sd_bus_get_property( + manager->bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + "ActiveState", + &error, + &reply, + "s"); + if (r < 0) { + /* systemd might have dropped off momentarily, let's + * not make this an error */ + if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || + sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) + return true; + + /* If the unit is already unloaded then it's not + * active */ + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || + sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) + return false; + + sd_bus_error_move(ret_error, &error); + return r; + } + + r = sd_bus_message_read(reply, "s", &state); + if (r < 0) + return r; + + return !STR_IN_SET(state, "inactive", "failed"); +} + +int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *ret_error) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + assert(manager); + assert(path); + + r = sd_bus_get_property( + manager->bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Job", + "State", + &error, + &reply, + "s"); + if (r < 0) { + if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || + sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) + return true; + + if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) + return false; + + sd_bus_error_move(ret_error, &error); + return r; + } + + /* We don't actually care about the state really. The fact + * that we could read the job state is enough for us */ + + return true; +} diff --git a/src/login/logind-dbus.h b/src/login/logind-dbus.h new file mode 100644 index 00000000..6c73a965 --- /dev/null +++ b/src/login/logind-dbus.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "logind.h" +#include "logind-session.h" +#include "logind-user.h" + +int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret); +int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret); +int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret); + +int manager_dispatch_delayed(Manager *manager, bool timeout); + +int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name, InhibitWhat w, sd_bus_error *error); + +int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error); +int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error); +int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error); +int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error); + +int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_; + +int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job); +int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); +int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); +int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error); +int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error); +int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *error); +int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *error); diff --git a/src/login/logind-device.c b/src/login/logind-device.c new file mode 100644 index 00000000..9a622172 --- /dev/null +++ b/src/login/logind-device.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "logind-device.h" +#include "logind-seat-dbus.h" +#include "util.h" + +Device* device_new(Manager *m, const char *sysfs, bool master) { + Device *d; + + assert(m); + assert(sysfs); + + d = new0(Device, 1); + if (!d) + return NULL; + + d->sysfs = strdup(sysfs); + if (!d->sysfs) + return mfree(d); + + if (hashmap_put(m->devices, d->sysfs, d) < 0) { + free(d->sysfs); + return mfree(d); + } + + d->manager = m; + d->master = master; + dual_timestamp_get(&d->timestamp); + + return d; +} + +static void device_detach(Device *d) { + Seat *s; + SessionDevice *sd; + + assert(d); + + if (!d->seat) + return; + + while ((sd = d->session_devices)) + session_device_free(sd); + + s = d->seat; + LIST_REMOVE(devices, d->seat->devices, d); + d->seat = NULL; + + if (!seat_has_master_device(s)) { + seat_add_to_gc_queue(s); + seat_send_changed(s, "CanGraphical", NULL); + } +} + +void device_free(Device *d) { + assert(d); + + device_detach(d); + + hashmap_remove(d->manager->devices, d->sysfs); + + free(d->sysfs); + free(d); +} + +void device_attach(Device *d, Seat *s) { + Device *i; + bool had_master; + + assert(d); + assert(s); + + if (d->seat == s) + return; + + if (d->seat) + device_detach(d); + + d->seat = s; + had_master = seat_has_master_device(s); + + /* We keep the device list sorted by the "master" flag. That is, master + * devices are at the front, other devices at the tail. As there is no + * way to easily add devices at the list-tail, we need to iterate the + * list to find the first non-master device when adding non-master + * devices. We assume there is only a few (normally 1) master devices + * per seat, so we iterate only a few times. */ + + if (d->master || !s->devices) + LIST_PREPEND(devices, s->devices, d); + else + LIST_FOREACH(devices, i, s->devices) { + if (!i->devices_next || !i->master) { + LIST_INSERT_AFTER(devices, s->devices, i, d); + break; + } + } + + if (!had_master && d->master && s->started) { + seat_save(s); + seat_send_changed(s, "CanGraphical", NULL); + } +} diff --git a/src/login/logind-device.h b/src/login/logind-device.h new file mode 100644 index 00000000..cc6e5236 --- /dev/null +++ b/src/login/logind-device.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Device Device; + +#include "list.h" +#include "logind-seat.h" +#include "logind-session-device.h" + +struct Device { + Manager *manager; + + char *sysfs; + Seat *seat; + bool master; + + dual_timestamp timestamp; + + LIST_FIELDS(struct Device, devices); + LIST_HEAD(SessionDevice, session_devices); +}; + +Device* device_new(Manager *m, const char *sysfs, bool master); +void device_free(Device *d); +void device_attach(Device *d, Seat *s); diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf new file mode 100644 index 00000000..983795da --- /dev/null +++ b/src/login/logind-gperf.gperf @@ -0,0 +1,44 @@ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif +#include +#include "conf-parser.h" +#include "logind.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name logind_gperf_hash +%define lookup-function-name logind_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +Login.NAutoVTs, config_parse_n_autovts, 0, offsetof(Manager, n_autovts) +Login.ReserveVT, config_parse_unsigned, 0, offsetof(Manager, reserve_vt) +Login.KillUserProcesses, config_parse_bool, 0, offsetof(Manager, kill_user_processes) +Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users) +Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users) +Login.InhibitDelayMaxSec, config_parse_sec, 0, offsetof(Manager, inhibit_delay_max) +Login.UserStopDelaySec, config_parse_sec, 0, offsetof(Manager, user_stop_delay) +Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manager, handle_power_key) +Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key) +Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key) +Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch) +Login.HandleLidSwitchExternalPower, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep) +Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked) +Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited) +Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited) +Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited) +Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited) +Login.HoldoffTimeoutSec, config_parse_sec, 0, offsetof(Manager, holdoff_timeout_usec) +Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action) +Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec) +Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size) +Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc) +Login.InhibitorsMax, config_parse_uint64, 0, offsetof(Manager, inhibitors_max) +Login.SessionsMax, config_parse_uint64, 0, offsetof(Manager, sessions_max) +Login.UserTasksMax, config_parse_compat_user_tasks_max, 0, 0 diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c new file mode 100644 index 00000000..1d335f91 --- /dev/null +++ b/src/login/logind-inhibit.c @@ -0,0 +1,518 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "env-file.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "io-util.h" +#include "logind-dbus.h" +#include "logind-inhibit.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "string-table.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "user-util.h" +#include "util.h" + +static void inhibitor_remove_fifo(Inhibitor *i); + +int inhibitor_new(Inhibitor **ret, Manager *m, const char* id) { + _cleanup_(inhibitor_freep) Inhibitor *i = NULL; + int r; + + assert(ret); + assert(m); + assert(id); + + i = new(Inhibitor, 1); + if (!i) + return -ENOMEM; + + *i = (Inhibitor) { + .manager = m, + .what = _INHIBIT_WHAT_INVALID, + .mode = _INHIBIT_MODE_INVALID, + .uid = UID_INVALID, + .fifo_fd = -1, + }; + + i->state_file = path_join("/run/systemd/inhibit", id); + if (!i->state_file) + return -ENOMEM; + + i->id = basename(i->state_file); + + r = hashmap_put(m->inhibitors, i->id, i); + if (r < 0) + return r; + + *ret = TAKE_PTR(i); + return 0; +} + +Inhibitor* inhibitor_free(Inhibitor *i) { + + if (!i) + return NULL; + + free(i->who); + free(i->why); + + sd_event_source_unref(i->event_source); + safe_close(i->fifo_fd); + + hashmap_remove(i->manager->inhibitors, i->id); + + /* Note that we don't remove neither the state file nor the fifo path here, since we want both to + * survive daemon restarts */ + free(i->state_file); + free(i->fifo_path); + + return mfree(i); +} + +static int inhibitor_save(Inhibitor *i) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(i); + + r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + goto fail; + + r = fopen_temporary(i->state_file, &f, &temp_path); + if (r < 0) + goto fail; + + (void) fchmod(fileno(f), 0644); + + fprintf(f, + "# This is private data. Do not parse.\n" + "WHAT=%s\n" + "MODE=%s\n" + "UID="UID_FMT"\n" + "PID="PID_FMT"\n", + inhibit_what_to_string(i->what), + inhibit_mode_to_string(i->mode), + i->uid, + i->pid); + + if (i->who) { + _cleanup_free_ char *cc = NULL; + + cc = cescape(i->who); + if (!cc) { + r = -ENOMEM; + goto fail; + } + + fprintf(f, "WHO=%s\n", cc); + } + + if (i->why) { + _cleanup_free_ char *cc = NULL; + + cc = cescape(i->why); + if (!cc) { + r = -ENOMEM; + goto fail; + } + + fprintf(f, "WHY=%s\n", cc); + } + + if (i->fifo_path) + fprintf(f, "FIFO=%s\n", i->fifo_path); + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, i->state_file) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + (void) unlink(i->state_file); + + if (temp_path) + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save inhibit data %s: %m", i->state_file); +} + +static int bus_manager_send_inhibited_change(Inhibitor *i) { + const char *property; + + assert(i); + + property = i->mode == INHIBIT_BLOCK ? "BlockInhibited" : "DelayInhibited"; + + return manager_send_changed(i->manager, property, NULL); +} + +int inhibitor_start(Inhibitor *i) { + assert(i); + + if (i->started) + return 0; + + dual_timestamp_get(&i->since); + + log_debug("Inhibitor %s (%s) pid="PID_FMT" uid="UID_FMT" mode=%s started.", + strna(i->who), strna(i->why), + i->pid, i->uid, + inhibit_mode_to_string(i->mode)); + + i->started = true; + + inhibitor_save(i); + + bus_manager_send_inhibited_change(i); + + return 0; +} + +void inhibitor_stop(Inhibitor *i) { + assert(i); + + if (i->started) + log_debug("Inhibitor %s (%s) pid="PID_FMT" uid="UID_FMT" mode=%s stopped.", + strna(i->who), strna(i->why), + i->pid, i->uid, + inhibit_mode_to_string(i->mode)); + + inhibitor_remove_fifo(i); + + if (i->state_file) + (void) unlink(i->state_file); + + i->started = false; + + bus_manager_send_inhibited_change(i); +} + +int inhibitor_load(Inhibitor *i) { + + _cleanup_free_ char + *what = NULL, + *uid = NULL, + *pid = NULL, + *who = NULL, + *why = NULL, + *mode = NULL; + + InhibitWhat w; + InhibitMode mm; + char *cc; + int r; + + r = parse_env_file(NULL, i->state_file, + "WHAT", &what, + "UID", &uid, + "PID", &pid, + "WHO", &who, + "WHY", &why, + "MODE", &mode, + "FIFO", &i->fifo_path); + if (r < 0) + return log_error_errno(r, "Failed to read %s: %m", i->state_file); + + w = what ? inhibit_what_from_string(what) : 0; + if (w >= 0) + i->what = w; + + mm = mode ? inhibit_mode_from_string(mode) : INHIBIT_BLOCK; + if (mm >= 0) + i->mode = mm; + + if (uid) { + r = parse_uid(uid, &i->uid); + if (r < 0) + log_debug_errno(r, "Failed to parse UID of inhibitor: %s", uid); + } + + if (pid) { + r = parse_pid(pid, &i->pid); + if (r < 0) + log_debug_errno(r, "Failed to parse PID of inhibitor: %s", pid); + } + + if (who) { + r = cunescape(who, 0, &cc); + if (r < 0) + return log_oom(); + + free_and_replace(i->who, cc); + } + + if (why) { + r = cunescape(why, 0, &cc); + if (r < 0) + return log_oom(); + + free_and_replace(i->why, cc); + } + + if (i->fifo_path) { + _cleanup_close_ int fd = -1; + + /* Let's re-open the FIFO on both sides, and close the writing side right away */ + fd = inhibitor_create_fifo(i); + if (fd < 0) + return log_error_errno(fd, "Failed to reopen FIFO: %m"); + } + + return 0; +} + +static int inhibitor_dispatch_fifo(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Inhibitor *i = userdata; + + assert(s); + assert(fd == i->fifo_fd); + assert(i); + + inhibitor_stop(i); + inhibitor_free(i); + + return 0; +} + +int inhibitor_create_fifo(Inhibitor *i) { + int r; + + assert(i); + + /* Create FIFO */ + if (!i->fifo_path) { + r = mkdir_safe_label("/run/systemd/inhibit", 0755, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + return r; + + i->fifo_path = strjoin("/run/systemd/inhibit/", i->id, ".ref"); + if (!i->fifo_path) + return -ENOMEM; + + if (mkfifo(i->fifo_path, 0600) < 0 && errno != EEXIST) + return -errno; + } + + /* Open reading side */ + if (i->fifo_fd < 0) { + i->fifo_fd = open(i->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (i->fifo_fd < 0) + return -errno; + } + + if (!i->event_source) { + r = sd_event_add_io(i->manager->event, &i->event_source, i->fifo_fd, 0, inhibitor_dispatch_fifo, i); + if (r < 0) + return r; + + r = sd_event_source_set_priority(i->event_source, SD_EVENT_PRIORITY_IDLE-10); + if (r < 0) + return r; + + (void) sd_event_source_set_description(i->event_source, "inhibitor-ref"); + } + + /* Open writing side */ + r = open(i->fifo_path, O_WRONLY|O_CLOEXEC|O_NONBLOCK); + if (r < 0) + return -errno; + + return r; +} + +static void inhibitor_remove_fifo(Inhibitor *i) { + assert(i); + + i->event_source = sd_event_source_unref(i->event_source); + i->fifo_fd = safe_close(i->fifo_fd); + + if (i->fifo_path) { + (void) unlink(i->fifo_path); + i->fifo_path = mfree(i->fifo_path); + } +} + +bool inhibitor_is_orphan(Inhibitor *i) { + assert(i); + + if (!i->started) + return true; + + if (!i->fifo_path) + return true; + + if (i->fifo_fd < 0) + return true; + + if (pipe_eof(i->fifo_fd) != 0) + return true; + + return false; +} + +InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm) { + Inhibitor *i; + Iterator j; + InhibitWhat what = 0; + + assert(m); + + HASHMAP_FOREACH(i, m->inhibitors, j) + if (i->mode == mm && i->started) + what |= i->what; + + return what; +} + +static int pid_is_active(Manager *m, pid_t pid) { + Session *s; + int r; + + /* Get client session. This is not what you are looking for these days. + * FIXME #6852 */ + r = manager_get_session_by_pid(m, pid, &s); + if (r < 0) + return r; + + /* If there's no session assigned to it, then it's globally + * active on all ttys */ + if (r == 0) + return 1; + + return session_is_active(s); +} + +bool manager_is_inhibited( + Manager *m, + InhibitWhat w, + InhibitMode mm, + dual_timestamp *since, + bool ignore_inactive, + bool ignore_uid, + uid_t uid, + Inhibitor **offending) { + + Inhibitor *i; + Iterator j; + struct dual_timestamp ts = DUAL_TIMESTAMP_NULL; + bool inhibited = false; + + assert(m); + assert(w > 0 && w < _INHIBIT_WHAT_MAX); + + HASHMAP_FOREACH(i, m->inhibitors, j) { + if (!i->started) + continue; + + if (!(i->what & w)) + continue; + + if (i->mode != mm) + continue; + + if (ignore_inactive && pid_is_active(m, i->pid) <= 0) + continue; + + if (ignore_uid && i->uid == uid) + continue; + + if (!inhibited || + i->since.monotonic < ts.monotonic) + ts = i->since; + + inhibited = true; + + if (offending) + *offending = i; + } + + if (since) + *since = ts; + + return inhibited; +} + +const char *inhibit_what_to_string(InhibitWhat w) { + static thread_local char buffer[97]; + char *p; + + if (w < 0 || w >= _INHIBIT_WHAT_MAX) + return NULL; + + p = buffer; + if (w & INHIBIT_SHUTDOWN) + p = stpcpy(p, "shutdown:"); + if (w & INHIBIT_SLEEP) + p = stpcpy(p, "sleep:"); + if (w & INHIBIT_IDLE) + p = stpcpy(p, "idle:"); + if (w & INHIBIT_HANDLE_POWER_KEY) + p = stpcpy(p, "handle-power-key:"); + if (w & INHIBIT_HANDLE_SUSPEND_KEY) + p = stpcpy(p, "handle-suspend-key:"); + if (w & INHIBIT_HANDLE_HIBERNATE_KEY) + p = stpcpy(p, "handle-hibernate-key:"); + if (w & INHIBIT_HANDLE_LID_SWITCH) + p = stpcpy(p, "handle-lid-switch:"); + + if (p > buffer) + *(p-1) = 0; + else + *p = 0; + + return buffer; +} + +InhibitWhat inhibit_what_from_string(const char *s) { + InhibitWhat what = 0; + const char *word, *state; + size_t l; + + FOREACH_WORD_SEPARATOR(word, l, s, ":", state) { + if (l == 8 && strneq(word, "shutdown", l)) + what |= INHIBIT_SHUTDOWN; + else if (l == 5 && strneq(word, "sleep", l)) + what |= INHIBIT_SLEEP; + else if (l == 4 && strneq(word, "idle", l)) + what |= INHIBIT_IDLE; + else if (l == 16 && strneq(word, "handle-power-key", l)) + what |= INHIBIT_HANDLE_POWER_KEY; + else if (l == 18 && strneq(word, "handle-suspend-key", l)) + what |= INHIBIT_HANDLE_SUSPEND_KEY; + else if (l == 20 && strneq(word, "handle-hibernate-key", l)) + what |= INHIBIT_HANDLE_HIBERNATE_KEY; + else if (l == 17 && strneq(word, "handle-lid-switch", l)) + what |= INHIBIT_HANDLE_LID_SWITCH; + else + return _INHIBIT_WHAT_INVALID; + } + + return what; +} + +static const char* const inhibit_mode_table[_INHIBIT_MODE_MAX] = { + [INHIBIT_BLOCK] = "block", + [INHIBIT_DELAY] = "delay" +}; + +DEFINE_STRING_TABLE_LOOKUP(inhibit_mode, InhibitMode); diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h new file mode 100644 index 00000000..cea67a08 --- /dev/null +++ b/src/login/logind-inhibit.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Inhibitor Inhibitor; + +typedef enum InhibitWhat { + INHIBIT_SHUTDOWN = 1 << 0, + INHIBIT_SLEEP = 1 << 1, + INHIBIT_IDLE = 1 << 2, + INHIBIT_HANDLE_POWER_KEY = 1 << 3, + INHIBIT_HANDLE_SUSPEND_KEY = 1 << 4, + INHIBIT_HANDLE_HIBERNATE_KEY = 1 << 5, + INHIBIT_HANDLE_LID_SWITCH = 1 << 6, + _INHIBIT_WHAT_MAX = 1 << 7, + _INHIBIT_WHAT_INVALID = -1 +} InhibitWhat; + +typedef enum InhibitMode { + INHIBIT_BLOCK, + INHIBIT_DELAY, + _INHIBIT_MODE_MAX, + _INHIBIT_MODE_INVALID = -1 +} InhibitMode; + +#include "logind.h" + +struct Inhibitor { + Manager *manager; + + sd_event_source *event_source; + + const char *id; + char *state_file; + + bool started; + + InhibitWhat what; + char *who; + char *why; + InhibitMode mode; + + pid_t pid; + uid_t uid; + + dual_timestamp since; + + char *fifo_path; + int fifo_fd; +}; + +int inhibitor_new(Inhibitor **ret, Manager *m, const char* id); +Inhibitor* inhibitor_free(Inhibitor *i); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Inhibitor*, inhibitor_free); + +int inhibitor_load(Inhibitor *i); + +int inhibitor_start(Inhibitor *i); +void inhibitor_stop(Inhibitor *i); + +int inhibitor_create_fifo(Inhibitor *i); + +bool inhibitor_is_orphan(Inhibitor *i); + +InhibitWhat manager_inhibit_what(Manager *m, InhibitMode mm); +bool manager_is_inhibited(Manager *m, InhibitWhat w, InhibitMode mm, dual_timestamp *since, bool ignore_inactive, bool ignore_uid, uid_t uid, Inhibitor **offending); + +const char *inhibit_what_to_string(InhibitWhat k); +InhibitWhat inhibit_what_from_string(const char *s); + +const char *inhibit_mode_to_string(InhibitMode k); +InhibitMode inhibit_mode_from_string(const char *s); diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c new file mode 100644 index 00000000..5b41e60f --- /dev/null +++ b/src/login/logind-seat-dbus.c @@ -0,0 +1,412 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-label.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "logind-dbus.h" +#include "logind-seat-dbus.h" +#include "logind-seat.h" +#include "logind-session-dbus.h" +#include "logind.h" +#include "missing_capability.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" + +static BUS_DEFINE_PROPERTY_GET(property_get_can_multi_session, "b", Seat, seat_can_multi_session); +static BUS_DEFINE_PROPERTY_GET(property_get_can_tty, "b", Seat, seat_can_tty); +static BUS_DEFINE_PROPERTY_GET(property_get_can_graphical, "b", Seat, seat_can_graphical); + +static int property_get_active_session( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *p = NULL; + Seat *s = userdata; + + assert(bus); + assert(reply); + assert(s); + + p = s->active ? session_bus_path(s->active) : strdup("/"); + if (!p) + return -ENOMEM; + + return sd_bus_message_append(reply, "(so)", s->active ? s->active->id : "", p); +} + +static int property_get_sessions( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Seat *s = userdata; + Session *session; + int r; + + assert(bus); + assert(reply); + assert(s); + + r = sd_bus_message_open_container(reply, 'a', "(so)"); + if (r < 0) + return r; + + LIST_FOREACH(sessions_by_seat, session, s->sessions) { + _cleanup_free_ char *p = NULL; + + p = session_bus_path(session); + if (!p) + return -ENOMEM; + + r = sd_bus_message_append(reply, "(so)", session->id, p); + if (r < 0) + return r; + + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return 1; +} + +static int property_get_idle_hint( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Seat *s = userdata; + + assert(bus); + assert(reply); + assert(s); + + return sd_bus_message_append(reply, "b", seat_get_idle_hint(s, NULL) > 0); +} + +static int property_get_idle_since_hint( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Seat *s = userdata; + dual_timestamp t; + uint64_t u; + int r; + + assert(bus); + assert(reply); + assert(s); + + r = seat_get_idle_hint(s, &t); + if (r < 0) + return r; + + u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic; + + return sd_bus_message_append(reply, "t", u); +} + +int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Seat *s = userdata; + int r; + + assert(message); + assert(s); + + r = bus_verify_polkit_async( + message, + CAP_KILL, + "org.freedesktop.login1.manage", + NULL, + false, + UID_INVALID, + &s->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = seat_stop_sessions(s, true); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Seat *s = userdata; + const char *name; + Session *session; + int r; + + assert(message); + assert(s); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + session = hashmap_get(s->manager->sessions, name); + if (!session) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name); + + if (session->seat != s) + return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id); + + r = session_activate(session); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Seat *s = userdata; + unsigned to; + int r; + + assert(message); + assert(s); + + r = sd_bus_message_read(message, "u", &to); + if (r < 0) + return r; + + if (to <= 0) + return -EINVAL; + + r = seat_switch_to(s, to); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Seat *s = userdata; + int r; + + assert(message); + assert(s); + + r = seat_switch_to_next(s); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Seat *s = userdata; + int r; + + assert(message); + assert(s); + + r = seat_switch_to_previous(s); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +const sd_bus_vtable seat_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Seat, id), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ActiveSession", "(so)", property_get_active_session, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("CanMultiSession", "b", property_get_can_multi_session, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CanTTY", "b", property_get_can_tty, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CanGraphical", "b", property_get_can_graphical, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, 0), + SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + + SD_BUS_METHOD("Terminate", NULL, NULL, bus_seat_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SwitchTo", "u", NULL, method_switch_to, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SwitchToNext", NULL, NULL, method_switch_to_next, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SwitchToPrevious", NULL, NULL, method_switch_to_previous, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_VTABLE_END +}; + +int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + _cleanup_free_ char *e = NULL; + sd_bus_message *message; + Manager *m = userdata; + const char *p; + Seat *seat; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + p = startswith(path, "/org/freedesktop/login1/seat/"); + if (!p) + return 0; + + e = bus_label_unescape(p); + if (!e) + return -ENOMEM; + + message = sd_bus_get_current_message(bus); + + r = manager_get_seat_from_creds(m, message, e, error, &seat); + if (r == -ENXIO) { + sd_bus_error_free(error); + return 0; + } + if (r < 0) + return r; + + *found = seat; + return 1; +} + +char *seat_bus_path(Seat *s) { + _cleanup_free_ char *t = NULL; + + assert(s); + + t = bus_label_escape(s->id); + if (!t) + return NULL; + + return strjoin("/org/freedesktop/login1/seat/", t); +} + +int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + sd_bus_message *message; + Manager *m = userdata; + Seat *seat; + Iterator i; + int r; + + assert(bus); + assert(path); + assert(nodes); + + HASHMAP_FOREACH(seat, m->seats, i) { + char *p; + + p = seat_bus_path(seat); + if (!p) + return -ENOMEM; + + r = strv_consume(&l, p); + if (r < 0) + return r; + } + + message = sd_bus_get_current_message(bus); + if (message) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); + if (r >= 0) { + bool may_auto = false; + const char *name; + + r = sd_bus_creds_get_session(creds, &name); + if (r >= 0) { + Session *session; + + session = hashmap_get(m->sessions, name); + if (session && session->seat) { + r = strv_extend(&l, "/org/freedesktop/login1/seat/self"); + if (r < 0) + return r; + + may_auto = true; + } + } + + if (!may_auto) { + uid_t uid; + + r = sd_bus_creds_get_owner_uid(creds, &uid); + if (r >= 0) { + User *user; + + user = hashmap_get(m->users, UID_TO_PTR(uid)); + may_auto = user && user->display && user->display->seat; + } + } + + if (may_auto) { + r = strv_extend(&l, "/org/freedesktop/login1/seat/auto"); + if (r < 0) + return r; + } + } + } + + *nodes = TAKE_PTR(l); + return 1; +} + +int seat_send_signal(Seat *s, bool new_seat) { + _cleanup_free_ char *p = NULL; + + assert(s); + + p = seat_bus_path(s); + if (!p) + return -ENOMEM; + + return sd_bus_emit_signal( + s->manager->bus, + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + new_seat ? "SeatNew" : "SeatRemoved", + "so", s->id, p); +} + +int seat_send_changed(Seat *s, const char *properties, ...) { + _cleanup_free_ char *p = NULL; + char **l; + + assert(s); + + if (!s->started) + return 0; + + p = seat_bus_path(s); + if (!p) + return -ENOMEM; + + l = strv_from_stdarg_alloca(properties); + + return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Seat", l); +} diff --git a/src/login/logind-seat-dbus.h b/src/login/logind-seat-dbus.h new file mode 100644 index 00000000..2590f649 --- /dev/null +++ b/src/login/logind-seat-dbus.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "logind-seat.h" + +extern const sd_bus_vtable seat_vtable[]; + +int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); +int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +char *seat_bus_path(Seat *s); + +int seat_send_signal(Seat *s, bool new_seat); +int seat_send_changed(Seat *s, const char *properties, ...) _sentinel_; + +int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c new file mode 100644 index 00000000..026bcf4d --- /dev/null +++ b/src/login/logind-seat.c @@ -0,0 +1,671 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "logind-acl.h" +#include "logind-seat-dbus.h" +#include "logind-seat.h" +#include "logind-session-dbus.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "util.h" + +int seat_new(Seat** ret, Manager *m, const char *id) { + _cleanup_(seat_freep) Seat *s = NULL; + int r; + + assert(ret); + assert(m); + assert(id); + + if (!seat_name_is_valid(id)) + return -EINVAL; + + s = new(Seat, 1); + if (!s) + return -ENOMEM; + + *s = (Seat) { + .manager = m, + }; + + s->state_file = path_join("/run/systemd/seats", id); + if (!s->state_file) + return -ENOMEM; + + s->id = basename(s->state_file); + + r = hashmap_put(m->seats, s->id, s); + if (r < 0) + return r; + + *ret = TAKE_PTR(s); + return 0; +} + +Seat* seat_free(Seat *s) { + if (!s) + return NULL; + + if (s->in_gc_queue) + LIST_REMOVE(gc_queue, s->manager->seat_gc_queue, s); + + while (s->sessions) + session_free(s->sessions); + + assert(!s->active); + + while (s->devices) + device_free(s->devices); + + hashmap_remove(s->manager->seats, s->id); + + free(s->positions); + free(s->state_file); + + return mfree(s); +} + +int seat_save(Seat *s) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(s); + + if (!s->started) + return 0; + + r = mkdir_safe_label("/run/systemd/seats", 0755, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + goto fail; + + r = fopen_temporary(s->state_file, &f, &temp_path); + if (r < 0) + goto fail; + + (void) fchmod(fileno(f), 0644); + + fprintf(f, + "# This is private data. Do not parse.\n" + "IS_SEAT0=%i\n" + "CAN_MULTI_SESSION=%i\n" + "CAN_TTY=%i\n" + "CAN_GRAPHICAL=%i\n", + seat_is_seat0(s), + seat_can_multi_session(s), + seat_can_tty(s), + seat_can_graphical(s)); + + if (s->active) { + assert(s->active->user); + + fprintf(f, + "ACTIVE=%s\n" + "ACTIVE_UID="UID_FMT"\n", + s->active->id, + s->active->user->uid); + } + + if (s->sessions) { + Session *i; + + fputs("SESSIONS=", f); + LIST_FOREACH(sessions_by_seat, i, s->sessions) { + fprintf(f, + "%s%c", + i->id, + i->sessions_by_seat_next ? ' ' : '\n'); + } + + fputs("UIDS=", f); + LIST_FOREACH(sessions_by_seat, i, s->sessions) + fprintf(f, + UID_FMT"%c", + i->user->uid, + i->sessions_by_seat_next ? ' ' : '\n'); + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, s->state_file) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + (void) unlink(s->state_file); + + if (temp_path) + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save seat data %s: %m", s->state_file); +} + +int seat_load(Seat *s) { + assert(s); + + /* There isn't actually anything to read here ... */ + + return 0; +} + +static int vt_allocate(unsigned vtnr) { + char p[sizeof("/dev/tty") + DECIMAL_STR_MAX(unsigned)]; + _cleanup_close_ int fd = -1; + + assert(vtnr >= 1); + + xsprintf(p, "/dev/tty%u", vtnr); + fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC); + if (fd < 0) + return fd; + + return 0; +} + +int seat_preallocate_vts(Seat *s) { + int r = 0; + unsigned i; + + assert(s); + assert(s->manager); + + if (s->manager->n_autovts <= 0) + return 0; + + if (!seat_has_vts(s)) + return 0; + + log_debug("Preallocating VTs..."); + + for (i = 1; i <= s->manager->n_autovts; i++) { + int q; + + q = vt_allocate(i); + if (q < 0) + r = log_error_errno(q, "Failed to preallocate VT %u: %m", i); + } + + return r; +} + +int seat_apply_acls(Seat *s, Session *old_active) { + int r; + + assert(s); + + r = devnode_acl_all(s->id, + false, + !!old_active, old_active ? old_active->user->uid : 0, + !!s->active, s->active ? s->active->user->uid : 0); + + if (r < 0) + return log_error_errno(r, "Failed to apply ACLs: %m"); + + return 0; +} + +int seat_set_active(Seat *s, Session *session) { + Session *old_active; + + assert(s); + assert(!session || session->seat == s); + + if (session == s->active) + return 0; + + old_active = s->active; + s->active = session; + + if (old_active) { + session_device_pause_all(old_active); + session_send_changed(old_active, "Active", NULL); + } + + (void) seat_apply_acls(s, old_active); + + if (session && session->started) { + session_send_changed(session, "Active", NULL); + session_device_resume_all(session); + } + + if (!session || session->started) + seat_send_changed(s, "ActiveSession", NULL); + + seat_save(s); + + if (session) { + session_save(session); + user_save(session->user); + } + + if (old_active) { + session_save(old_active); + if (!session || session->user != old_active->user) + user_save(old_active->user); + } + + return 0; +} + +int seat_switch_to(Seat *s, unsigned num) { + /* Public session positions skip 0 (there is only F1-F12). Maybe it + * will get reassigned in the future, so return error for now. */ + if (num == 0) + return -EINVAL; + + if (num >= s->position_count || !s->positions[num]) { + /* allow switching to unused VTs to trigger auto-activate */ + if (seat_has_vts(s) && num < 64) + return chvt(num); + + return -EINVAL; + } + + return session_activate(s->positions[num]); +} + +int seat_switch_to_next(Seat *s) { + unsigned start, i; + + if (s->position_count == 0) + return -EINVAL; + + start = 1; + if (s->active && s->active->position > 0) + start = s->active->position; + + for (i = start + 1; i < s->position_count; ++i) + if (s->positions[i]) + return session_activate(s->positions[i]); + + for (i = 1; i < start; ++i) + if (s->positions[i]) + return session_activate(s->positions[i]); + + return -EINVAL; +} + +int seat_switch_to_previous(Seat *s) { + unsigned start, i; + + if (s->position_count == 0) + return -EINVAL; + + start = 1; + if (s->active && s->active->position > 0) + start = s->active->position; + + for (i = start - 1; i > 0; --i) + if (s->positions[i]) + return session_activate(s->positions[i]); + + for (i = s->position_count - 1; i > start; --i) + if (s->positions[i]) + return session_activate(s->positions[i]); + + return -EINVAL; +} + +int seat_active_vt_changed(Seat *s, unsigned vtnr) { + Session *i, *new_active = NULL; + int r; + + assert(s); + assert(vtnr >= 1); + + if (!seat_has_vts(s)) + return -EINVAL; + + log_debug("VT changed to %u", vtnr); + + /* we might have earlier closing sessions on the same VT, so try to + * find a running one first */ + LIST_FOREACH(sessions_by_seat, i, s->sessions) + if (i->vtnr == vtnr && !i->stopping) { + new_active = i; + break; + } + + if (!new_active) { + /* no running one? then we can't decide which one is the + * active one, let the first one win */ + LIST_FOREACH(sessions_by_seat, i, s->sessions) + if (i->vtnr == vtnr) { + new_active = i; + break; + } + } + + r = seat_set_active(s, new_active); + manager_spawn_autovt(s->manager, vtnr); + + return r; +} + +int seat_read_active_vt(Seat *s) { + char t[64]; + ssize_t k; + int vtnr; + + assert(s); + + if (!seat_has_vts(s)) + return 0; + + if (lseek(s->manager->console_active_fd, SEEK_SET, 0) < 0) + return log_error_errno(errno, "lseek on console_active_fd failed: %m"); + + k = read(s->manager->console_active_fd, t, sizeof(t)-1); + if (k <= 0) { + log_error("Failed to read current console: %s", k < 0 ? strerror_safe(errno) : "EOF"); + return k < 0 ? -errno : -EIO; + } + + t[k] = 0; + truncate_nl(t); + + vtnr = vtnr_from_tty(t); + if (vtnr < 0) { + log_error_errno(vtnr, "Hm, /sys/class/tty/tty0/active is badly formatted: %m"); + return -EIO; + } + + return seat_active_vt_changed(s, vtnr); +} + +int seat_start(Seat *s) { + assert(s); + + if (s->started) + return 0; + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_SEAT_START_STR, + "SEAT_ID=%s", s->id, + LOG_MESSAGE("New seat %s.", s->id)); + + /* Initialize VT magic stuff */ + seat_preallocate_vts(s); + + /* Read current VT */ + seat_read_active_vt(s); + + s->started = true; + + /* Save seat data */ + seat_save(s); + + seat_send_signal(s, true); + + return 0; +} + +int seat_stop(Seat *s, bool force) { + int r; + + assert(s); + + if (s->started) + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_SEAT_STOP_STR, + "SEAT_ID=%s", s->id, + LOG_MESSAGE("Removed seat %s.", s->id)); + + r = seat_stop_sessions(s, force); + + (void) unlink(s->state_file); + seat_add_to_gc_queue(s); + + if (s->started) + seat_send_signal(s, false); + + s->started = false; + + return r; +} + +int seat_stop_sessions(Seat *s, bool force) { + Session *session; + int r = 0, k; + + assert(s); + + LIST_FOREACH(sessions_by_seat, session, s->sessions) { + k = session_stop(session, force); + if (k < 0) + r = k; + } + + return r; +} + +void seat_evict_position(Seat *s, Session *session) { + Session *iter; + unsigned pos = session->position; + + session->position = 0; + + if (pos == 0) + return; + + if (pos < s->position_count && s->positions[pos] == session) { + s->positions[pos] = NULL; + + /* There might be another session claiming the same + * position (eg., during gdm->session transition), so let's look + * for it and set it on the free slot. */ + LIST_FOREACH(sessions_by_seat, iter, s->sessions) { + if (iter->position == pos && session_get_state(iter) != SESSION_CLOSING) { + s->positions[pos] = iter; + break; + } + } + } +} + +void seat_claim_position(Seat *s, Session *session, unsigned pos) { + /* with VTs, the position is always the same as the VTnr */ + if (seat_has_vts(s)) + pos = session->vtnr; + + if (!GREEDY_REALLOC0(s->positions, s->position_count, pos + 1)) + return; + + seat_evict_position(s, session); + + session->position = pos; + if (pos > 0) + s->positions[pos] = session; +} + +static void seat_assign_position(Seat *s, Session *session) { + unsigned pos; + + if (session->position > 0) + return; + + for (pos = 1; pos < s->position_count; ++pos) + if (!s->positions[pos]) + break; + + seat_claim_position(s, session, pos); +} + +int seat_attach_session(Seat *s, Session *session) { + assert(s); + assert(session); + assert(!session->seat); + + if (!seat_has_vts(s) != !session->vtnr) + return -EINVAL; + + session->seat = s; + LIST_PREPEND(sessions_by_seat, s->sessions, session); + seat_assign_position(s, session); + + /* On seats with VTs, the VT logic defines which session is active. On + * seats without VTs, we automatically activate new sessions. */ + if (!seat_has_vts(s)) + seat_set_active(s, session); + + return 0; +} + +void seat_complete_switch(Seat *s) { + Session *session; + + assert(s); + + /* if no session-switch is pending or if it got canceled, do nothing */ + if (!s->pending_switch) + return; + + session = TAKE_PTR(s->pending_switch); + + seat_set_active(s, session); +} + +bool seat_has_vts(Seat *s) { + assert(s); + + return seat_is_seat0(s) && s->manager->console_active_fd >= 0; +} + +bool seat_is_seat0(Seat *s) { + assert(s); + + return s->manager->seat0 == s; +} + +bool seat_can_multi_session(Seat *s) { + assert(s); + + return seat_has_vts(s); +} + +bool seat_can_tty(Seat *s) { + assert(s); + + return seat_has_vts(s); +} + +bool seat_has_master_device(Seat *s) { + assert(s); + + /* device list is ordered by "master" flag */ + return !!s->devices && s->devices->master; +} + +bool seat_can_graphical(Seat *s) { + assert(s); + + return seat_has_master_device(s); +} + +int seat_get_idle_hint(Seat *s, dual_timestamp *t) { + Session *session; + bool idle_hint = true; + dual_timestamp ts = DUAL_TIMESTAMP_NULL; + + assert(s); + + LIST_FOREACH(sessions_by_seat, session, s->sessions) { + dual_timestamp k; + int ih; + + ih = session_get_idle_hint(session, &k); + if (ih < 0) + return ih; + + if (!ih) { + if (!idle_hint) { + if (k.monotonic > ts.monotonic) + ts = k; + } else { + idle_hint = false; + ts = k; + } + } else if (idle_hint) { + + if (k.monotonic > ts.monotonic) + ts = k; + } + } + + if (t) + *t = ts; + + return idle_hint; +} + +bool seat_may_gc(Seat *s, bool drop_not_started) { + assert(s); + + if (drop_not_started && !s->started) + return true; + + if (seat_is_seat0(s)) + return false; + + return !seat_has_master_device(s); +} + +void seat_add_to_gc_queue(Seat *s) { + assert(s); + + if (s->in_gc_queue) + return; + + LIST_PREPEND(gc_queue, s->manager->seat_gc_queue, s); + s->in_gc_queue = true; +} + +static bool seat_name_valid_char(char c) { + return + (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + IN_SET(c, '-', '_'); +} + +bool seat_name_is_valid(const char *name) { + const char *p; + + assert(name); + + if (!startswith(name, "seat")) + return false; + + if (!name[4]) + return false; + + for (p = name; *p; p++) + if (!seat_name_valid_char(*p)) + return false; + + if (strlen(name) > 255) + return false; + + return true; +} diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h new file mode 100644 index 00000000..64cdf2f2 --- /dev/null +++ b/src/login/logind-seat.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Seat Seat; + +#include "list.h" +#include "logind-session.h" + +struct Seat { + Manager *manager; + char *id; + + char *state_file; + + LIST_HEAD(Device, devices); + + Session *active; + Session *pending_switch; + LIST_HEAD(Session, sessions); + + Session **positions; + size_t position_count; + + bool in_gc_queue:1; + bool started:1; + + LIST_FIELDS(Seat, gc_queue); +}; + +int seat_new(Seat **ret, Manager *m, const char *id); +Seat* seat_free(Seat *s); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Seat *, seat_free); + +int seat_save(Seat *s); +int seat_load(Seat *s); + +int seat_apply_acls(Seat *s, Session *old_active); +int seat_set_active(Seat *s, Session *session); +int seat_switch_to(Seat *s, unsigned num); +int seat_switch_to_next(Seat *s); +int seat_switch_to_previous(Seat *s); +int seat_active_vt_changed(Seat *s, unsigned vtnr); +int seat_read_active_vt(Seat *s); +int seat_preallocate_vts(Seat *s); + +int seat_attach_session(Seat *s, Session *session); +void seat_complete_switch(Seat *s); +void seat_evict_position(Seat *s, Session *session); +void seat_claim_position(Seat *s, Session *session, unsigned pos); + +bool seat_has_vts(Seat *s); +bool seat_is_seat0(Seat *s); +bool seat_can_multi_session(Seat *s); +bool seat_can_tty(Seat *s); +bool seat_has_master_device(Seat *s); +bool seat_can_graphical(Seat *s); + +int seat_get_idle_hint(Seat *s, dual_timestamp *t); + +int seat_start(Seat *s); +int seat_stop(Seat *s, bool force); +int seat_stop_sessions(Seat *s, bool force); + +bool seat_may_gc(Seat *s, bool drop_not_started); +void seat_add_to_gc_queue(Seat *s); + +bool seat_name_is_valid(const char *name); + +static inline bool SEAT_IS_SELF(const char *name) { + return isempty(name) || streq(name, "self"); +} + +static inline bool SEAT_IS_AUTO(const char *name) { + return streq_ptr(name, "auto"); +} diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c new file mode 100644 index 00000000..03f470cf --- /dev/null +++ b/src/login/logind-session-dbus.c @@ -0,0 +1,842 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-label.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "fd-util.h" +#include "logind-brightness.h" +#include "logind-dbus.h" +#include "logind-seat-dbus.h" +#include "logind-session-dbus.h" +#include "logind-session-device.h" +#include "logind-session.h" +#include "logind-user-dbus.h" +#include "logind.h" +#include "missing_capability.h" +#include "path-util.h" +#include "signal-util.h" +#include "stat-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" + +static int property_get_user( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *p = NULL; + Session *s = userdata; + + assert(bus); + assert(reply); + assert(s); + + p = user_bus_path(s->user); + if (!p) + return -ENOMEM; + + return sd_bus_message_append(reply, "(uo)", (uint32_t) s->user->uid, p); +} + +static int property_get_name( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Session *s = userdata; + + assert(bus); + assert(reply); + assert(s); + + return sd_bus_message_append(reply, "s", s->user->name); +} + +static int property_get_seat( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *p = NULL; + Session *s = userdata; + + assert(bus); + assert(reply); + assert(s); + + p = s->seat ? seat_bus_path(s->seat) : strdup("/"); + if (!p) + return -ENOMEM; + + return sd_bus_message_append(reply, "(so)", s->seat ? s->seat->id : "", p); +} + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass); +static BUS_DEFINE_PROPERTY_GET(property_get_active, "b", Session, session_is_active); +static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Session, session_get_state, session_state_to_string); + +static int property_get_idle_hint( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Session *s = userdata; + + assert(bus); + assert(reply); + assert(s); + + return sd_bus_message_append(reply, "b", session_get_idle_hint(s, NULL) > 0); +} + +static int property_get_idle_since_hint( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Session *s = userdata; + dual_timestamp t = DUAL_TIMESTAMP_NULL; + uint64_t u; + int r; + + assert(bus); + assert(reply); + assert(s); + + r = session_get_idle_hint(s, &t); + if (r < 0) + return r; + + u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic; + + return sd_bus_message_append(reply, "t", u); +} + +static int property_get_locked_hint( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Session *s = userdata; + + assert(bus); + assert(reply); + assert(s); + + return sd_bus_message_append(reply, "b", session_get_locked_hint(s) > 0); +} + +int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Session *s = userdata; + int r; + + assert(message); + assert(s); + + r = bus_verify_polkit_async( + message, + CAP_KILL, + "org.freedesktop.login1.manage", + NULL, + false, + s->user->uid, + &s->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = session_stop(s, true); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Session *s = userdata; + int r; + + assert(message); + assert(s); + + r = session_activate(s); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Session *s = userdata; + int r; + + assert(message); + assert(s); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.login1.lock-sessions", + NULL, + false, + s->user->uid, + &s->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock")); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + Session *s = userdata; + uid_t uid; + int r, b; + + assert(message); + assert(s); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_euid(creds, &uid); + if (r < 0) + return r; + + if (uid != 0 && uid != s->user->uid) + return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint"); + + r = session_set_idle_hint(s, b); + if (r == -ENOTTY) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Idle hint control is not supported on non-graphical sessions."); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_set_locked_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + Session *s = userdata; + uid_t uid; + int r, b; + + assert(message); + assert(s); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_euid(creds, &uid); + if (r < 0) + return r; + + if (uid != 0 && uid != s->user->uid) + return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set locked hint"); + + session_set_locked_hint(s, b); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Session *s = userdata; + const char *swho; + int32_t signo; + KillWho who; + int r; + + assert(message); + assert(s); + + r = sd_bus_message_read(message, "si", &swho, &signo); + if (r < 0) + return r; + + if (isempty(swho)) + who = KILL_ALL; + else { + who = kill_who_from_string(swho); + if (who < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho); + } + + if (!SIGNAL_VALID(signo)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo); + + r = bus_verify_polkit_async( + message, + CAP_KILL, + "org.freedesktop.login1.manage", + NULL, + false, + s->user->uid, + &s->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = session_kill(s, who, signo); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + Session *s = userdata; + int r, force; + uid_t uid; + + assert(message); + assert(s); + + r = sd_bus_message_read(message, "b", &force); + if (r < 0) + return r; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_euid(creds, &uid); + if (r < 0) + return r; + + if (uid != 0 && (force || uid != s->user->uid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control"); + + r = session_set_controller(s, sd_bus_message_get_sender(message), force, true); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_release_control(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Session *s = userdata; + + assert(message); + assert(s); + + if (!session_is_controller(s, sd_bus_message_get_sender(message))) + return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session"); + + session_drop_controller(s); + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Session *s = userdata; + uint32_t major, minor; + SessionDevice *sd; + dev_t dev; + int r; + + assert(message); + assert(s); + + r = sd_bus_message_read(message, "uu", &major, &minor); + if (r < 0) + return r; + + if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid."); + + if (!session_is_controller(s, sd_bus_message_get_sender(message))) + return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session"); + + dev = makedev(major, minor); + sd = hashmap_get(s->devices, &dev); + if (sd) + /* We don't allow retrieving a device multiple times. + * The related ReleaseDevice call is not ref-counted. + * The caller should use dup() if it requires more + * than one fd (it would be functionally + * equivalent). */ + return sd_bus_error_setf(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken"); + + r = session_device_new(s, dev, true, &sd); + if (r < 0) + return r; + + r = session_device_save(sd); + if (r < 0) + goto error; + + r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active); + if (r < 0) + goto error; + + session_save(s); + return 1; + +error: + session_device_free(sd); + return r; +} + +static int method_release_device(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Session *s = userdata; + uint32_t major, minor; + SessionDevice *sd; + dev_t dev; + int r; + + assert(message); + assert(s); + + r = sd_bus_message_read(message, "uu", &major, &minor); + if (r < 0) + return r; + + if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid."); + + if (!session_is_controller(s, sd_bus_message_get_sender(message))) + return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session"); + + dev = makedev(major, minor); + sd = hashmap_get(s->devices, &dev); + if (!sd) + return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken"); + + session_device_free(sd); + session_save(s); + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_pause_device_complete(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Session *s = userdata; + uint32_t major, minor; + SessionDevice *sd; + dev_t dev; + int r; + + assert(message); + assert(s); + + r = sd_bus_message_read(message, "uu", &major, &minor); + if (r < 0) + return r; + + if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid."); + + if (!session_is_controller(s, sd_bus_message_get_sender(message))) + return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session"); + + dev = makedev(major, minor); + sd = hashmap_get(s->devices, &dev); + if (!sd) + return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken"); + + session_device_complete_pause(sd); + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_set_brightness(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + const char *subsystem, *name, *seat; + Session *s = userdata; + uint32_t brightness; + uid_t uid; + int r; + + assert(message); + assert(s); + + r = sd_bus_message_read(message, "ssu", &subsystem, &name, &brightness); + if (r < 0) + return r; + + if (!STR_IN_SET(subsystem, "backlight", "leds")) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Subsystem type %s not supported, must be one of 'backlight' or 'leds'.", subsystem); + if (!filename_is_valid(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not a valid device name %s, refusing.", name); + + if (!s->seat) + return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Your session has no seat, refusing."); + if (s->seat->active != s) + return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Session is not in foreground, refusing."); + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_euid(creds, &uid); + if (r < 0) + return r; + + if (uid != 0 && uid != s->user->uid) + return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may change brightness."); + + r = sd_device_new_from_subsystem_sysname(&d, subsystem, name); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to open device %s:%s: %m", subsystem, name); + + if (sd_device_get_property_value(d, "ID_SEAT", &seat) >= 0 && !streq_ptr(seat, s->seat->id)) + return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Device %s:%s does not belong to your seat %s, refusing.", subsystem, name, s->seat->id); + + r = manager_write_brightness(s->manager, d, brightness, message); + if (r < 0) + return r; + + return 1; +} + +const sd_bus_vtable session_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("State", "s", property_get_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + + SD_BUS_METHOD("Terminate", NULL, NULL, bus_session_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Activate", NULL, NULL, bus_session_method_activate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Lock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Unlock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLockedHint", "b", NULL, method_set_locked_hint, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Kill", "si", NULL, bus_session_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetBrightness", "ssu", NULL, method_set_brightness, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_SIGNAL("PauseDevice", "uus", 0), + SD_BUS_SIGNAL("ResumeDevice", "uuh", 0), + SD_BUS_SIGNAL("Lock", NULL, 0), + SD_BUS_SIGNAL("Unlock", NULL, 0), + + SD_BUS_VTABLE_END +}; + +int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + _cleanup_free_ char *e = NULL; + sd_bus_message *message; + Manager *m = userdata; + Session *session; + const char *p; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + p = startswith(path, "/org/freedesktop/login1/session/"); + if (!p) + return 0; + + e = bus_label_unescape(p); + if (!e) + return -ENOMEM; + + message = sd_bus_get_current_message(bus); + + r = manager_get_session_from_creds(m, message, e, error, &session); + if (r == -ENXIO) { + sd_bus_error_free(error); + return 0; + } + if (r < 0) + return r; + + *found = session; + return 1; +} + +char *session_bus_path(Session *s) { + _cleanup_free_ char *t = NULL; + + assert(s); + + t = bus_label_escape(s->id); + if (!t) + return NULL; + + return strjoin("/org/freedesktop/login1/session/", t); +} + +int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + sd_bus_message *message; + Manager *m = userdata; + Session *session; + Iterator i; + int r; + + assert(bus); + assert(path); + assert(nodes); + + HASHMAP_FOREACH(session, m->sessions, i) { + char *p; + + p = session_bus_path(session); + if (!p) + return -ENOMEM; + + r = strv_consume(&l, p); + if (r < 0) + return r; + } + + message = sd_bus_get_current_message(bus); + if (message) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); + if (r >= 0) { + bool may_auto = false; + const char *name; + + r = sd_bus_creds_get_session(creds, &name); + if (r >= 0) { + session = hashmap_get(m->sessions, name); + if (session) { + r = strv_extend(&l, "/org/freedesktop/login1/session/self"); + if (r < 0) + return r; + + may_auto = true; + } + } + + if (!may_auto) { + uid_t uid; + + r = sd_bus_creds_get_owner_uid(creds, &uid); + if (r >= 0) { + User *user; + + user = hashmap_get(m->users, UID_TO_PTR(uid)); + may_auto = user && user->display; + } + } + + if (may_auto) { + r = strv_extend(&l, "/org/freedesktop/login1/session/auto"); + if (r < 0) + return r; + } + } + } + + *nodes = TAKE_PTR(l); + return 1; +} + +int session_send_signal(Session *s, bool new_session) { + _cleanup_free_ char *p = NULL; + + assert(s); + + p = session_bus_path(s); + if (!p) + return -ENOMEM; + + return sd_bus_emit_signal( + s->manager->bus, + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + new_session ? "SessionNew" : "SessionRemoved", + "so", s->id, p); +} + +int session_send_changed(Session *s, const char *properties, ...) { + _cleanup_free_ char *p = NULL; + char **l; + + assert(s); + + if (!s->started) + return 0; + + p = session_bus_path(s); + if (!p) + return -ENOMEM; + + l = strv_from_stdarg_alloca(properties); + + return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Session", l); +} + +int session_send_lock(Session *s, bool lock) { + _cleanup_free_ char *p = NULL; + + assert(s); + + p = session_bus_path(s); + if (!p) + return -ENOMEM; + + return sd_bus_emit_signal( + s->manager->bus, + p, + "org.freedesktop.login1.Session", + lock ? "Lock" : "Unlock", + NULL); +} + +int session_send_lock_all(Manager *m, bool lock) { + Session *session; + Iterator i; + int r = 0; + + assert(m); + + HASHMAP_FOREACH(session, m->sessions, i) { + int k; + + k = session_send_lock(session, lock); + if (k < 0) + r = k; + } + + return r; +} + +static bool session_ready(Session *s) { + assert(s); + + /* Returns true when the session is ready, i.e. all jobs we enqueued for it are done (regardless if successful or not) */ + + return !s->scope_job && + !s->user->service_job; +} + +int session_send_create_reply(Session *s, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL; + _cleanup_close_ int fifo_fd = -1; + _cleanup_free_ char *p = NULL; + + assert(s); + + /* This is called after the session scope and the user service were successfully created, and finishes where + * bus_manager_create_session() left off. */ + + if (!s->create_message) + return 0; + + if (!sd_bus_error_is_set(error) && !session_ready(s)) + return 0; + + c = TAKE_PTR(s->create_message); + if (error) + return sd_bus_reply_method_error(c, error); + + fifo_fd = session_create_fifo(s); + if (fifo_fd < 0) + return fifo_fd; + + /* Update the session state file before we notify the client about the result. */ + session_save(s); + + p = session_bus_path(s); + if (!p) + return -ENOMEM; + + log_debug("Sending reply about created session: " + "id=%s object_path=%s uid=%u runtime_path=%s " + "session_fd=%d seat=%s vtnr=%u", + s->id, + p, + (uint32_t) s->user->uid, + s->user->runtime_path, + fifo_fd, + s->seat ? s->seat->id : "", + (uint32_t) s->vtnr); + + return sd_bus_reply_method_return( + c, "soshusub", + s->id, + p, + s->user->runtime_path, + fifo_fd, + (uint32_t) s->user->uid, + s->seat ? s->seat->id : "", + (uint32_t) s->vtnr, + false); +} diff --git a/src/login/logind-session-dbus.h b/src/login/logind-session-dbus.h new file mode 100644 index 00000000..9d2315cc --- /dev/null +++ b/src/login/logind-session-dbus.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "logind-session.h" + +extern const sd_bus_vtable session_vtable[]; +int session_node_enumerator(sd_bus *bus, const char *path,void *userdata, char ***nodes, sd_bus_error *error); +int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +char *session_bus_path(Session *s); + +int session_send_signal(Session *s, bool new_session); +int session_send_changed(Session *s, const char *properties, ...) _sentinel_; +int session_send_lock(Session *s, bool lock); +int session_send_lock_all(Manager *m, bool lock); + +int session_send_create_reply(Session *s, sd_bus_error *error); + +int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c new file mode 100644 index 00000000..23df756a --- /dev/null +++ b/src/login/logind-session-device.c @@ -0,0 +1,523 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-device.h" +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "bus-util.h" +#include "fd-util.h" +#include "logind-session-dbus.h" +#include "logind-session-device.h" +#include "missing_drm.h" +#include "missing_input.h" +#include "parse-util.h" +#include "util.h" + +enum SessionDeviceNotifications { + SESSION_DEVICE_RESUME, + SESSION_DEVICE_TRY_PAUSE, + SESSION_DEVICE_PAUSE, + SESSION_DEVICE_RELEASE, +}; + +static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotifications type) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *path = NULL; + const char *t = NULL; + uint32_t major, minor; + int r; + + assert(sd); + + major = major(sd->dev); + minor = minor(sd->dev); + + if (!sd->session->controller) + return 0; + + path = session_bus_path(sd->session); + if (!path) + return -ENOMEM; + + r = sd_bus_message_new_signal( + sd->session->manager->bus, + &m, path, + "org.freedesktop.login1.Session", + (type == SESSION_DEVICE_RESUME) ? "ResumeDevice" : "PauseDevice"); + if (!m) + return r; + + r = sd_bus_message_set_destination(m, sd->session->controller); + if (r < 0) + return r; + + switch (type) { + + case SESSION_DEVICE_RESUME: + r = sd_bus_message_append(m, "uuh", major, minor, sd->fd); + if (r < 0) + return r; + break; + + case SESSION_DEVICE_TRY_PAUSE: + t = "pause"; + break; + + case SESSION_DEVICE_PAUSE: + t = "force"; + break; + + case SESSION_DEVICE_RELEASE: + t = "gone"; + break; + + default: + return -EINVAL; + } + + if (t) { + r = sd_bus_message_append(m, "uus", major, minor, t); + if (r < 0) + return r; + } + + return sd_bus_send(sd->session->manager->bus, m, NULL); +} + +static void sd_eviocrevoke(int fd) { + static bool warned = false; + + assert(fd >= 0); + + if (ioctl(fd, EVIOCREVOKE, NULL) < 0) { + + if (errno == EINVAL && !warned) { + log_warning_errno(errno, "Kernel does not support evdev-revocation: %m"); + warned = true; + } + } +} + +static int sd_drmsetmaster(int fd) { + assert(fd >= 0); + + if (ioctl(fd, DRM_IOCTL_SET_MASTER, 0) < 0) + return -errno; + + return 0; +} + +static int sd_drmdropmaster(int fd) { + assert(fd >= 0); + + if (ioctl(fd, DRM_IOCTL_DROP_MASTER, 0) < 0) + return -errno; + + return 0; +} + +static int session_device_open(SessionDevice *sd, bool active) { + int fd, r; + + assert(sd); + assert(sd->type != DEVICE_TYPE_UNKNOWN); + assert(sd->node); + + /* open device and try to get an udev_device from it */ + fd = open(sd->node, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); + if (fd < 0) + return -errno; + + switch (sd->type) { + + case DEVICE_TYPE_DRM: + if (active) { + /* Weird legacy DRM semantics might return an error even though we're master. No way to detect + * that so fail at all times and let caller retry in inactive state. */ + r = sd_drmsetmaster(fd); + if (r < 0) { + close_nointr(fd); + return r; + } + } else + /* DRM-Master is granted to the first user who opens a device automatically (ughh, + * racy!). Hence, we just drop DRM-Master in case we were the first. */ + (void) sd_drmdropmaster(fd); + break; + + case DEVICE_TYPE_EVDEV: + if (!active) + sd_eviocrevoke(fd); + break; + + case DEVICE_TYPE_UNKNOWN: + default: + /* fallback for devices without synchronizations */ + break; + } + + return fd; +} + +static int session_device_start(SessionDevice *sd) { + int r; + + assert(sd); + assert(session_is_active(sd->session)); + + if (sd->active) + return 0; + + switch (sd->type) { + + case DEVICE_TYPE_DRM: + if (sd->fd < 0) + return log_error_errno(SYNTHETIC_ERRNO(EBADF), + "Failed to re-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)"); + + /* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we + * keep the device paused. Maybe at some point we have a drmStealMaster(). */ + r = sd_drmsetmaster(sd->fd); + if (r < 0) + return r; + break; + + case DEVICE_TYPE_EVDEV: + /* Evdev devices are revoked while inactive. Reopen it and we are fine. */ + r = session_device_open(sd, true); + if (r < 0) + return r; + + /* For evdev devices, the file descriptor might be left uninitialized. This might happen while resuming + * into a session and logind has been restarted right before. */ + safe_close(sd->fd); + sd->fd = r; + break; + + case DEVICE_TYPE_UNKNOWN: + default: + /* fallback for devices without synchronizations */ + break; + } + + sd->active = true; + return 0; +} + +static void session_device_stop(SessionDevice *sd) { + assert(sd); + + if (!sd->active) + return; + + switch (sd->type) { + + case DEVICE_TYPE_DRM: + if (sd->fd < 0) { + log_error("Failed to de-activate DRM fd, as the fd was lost (maybe logind restart went wrong?)"); + return; + } + + /* On DRM devices we simply drop DRM-Master but keep it open. + * This allows the user to keep resources allocated. The + * CAP_SYS_ADMIN restriction to DRM-Master prevents users from + * circumventing this. */ + sd_drmdropmaster(sd->fd); + break; + + case DEVICE_TYPE_EVDEV: + /* Revoke access on evdev file-descriptors during deactivation. + * This will basically prevent any operations on the fd and + * cannot be undone. Good side is: it needs no CAP_SYS_ADMIN + * protection this way. */ + sd_eviocrevoke(sd->fd); + break; + + case DEVICE_TYPE_UNKNOWN: + default: + /* fallback for devices without synchronization */ + break; + } + + sd->active = false; +} + +static DeviceType detect_device_type(sd_device *dev) { + const char *sysname, *subsystem; + DeviceType type = DEVICE_TYPE_UNKNOWN; + + if (sd_device_get_sysname(dev, &sysname) < 0 || + sd_device_get_subsystem(dev, &subsystem) < 0) + return type; + + if (streq(subsystem, "drm")) { + if (startswith(sysname, "card")) + type = DEVICE_TYPE_DRM; + } else if (streq(subsystem, "input")) { + if (startswith(sysname, "event")) + type = DEVICE_TYPE_EVDEV; + } + + return type; +} + +static int session_device_verify(SessionDevice *sd) { + _cleanup_(sd_device_unrefp) sd_device *p = NULL; + const char *sp, *node; + sd_device *dev; + int r; + + r = sd_device_new_from_devnum(&p, 'c', sd->dev); + if (r < 0) + return r; + + dev = p; + + if (sd_device_get_syspath(dev, &sp) < 0 || + sd_device_get_devname(dev, &node) < 0) + return -EINVAL; + + /* detect device type so we can find the correct sysfs parent */ + sd->type = detect_device_type(dev); + if (sd->type == DEVICE_TYPE_UNKNOWN) + return -ENODEV; + + else if (sd->type == DEVICE_TYPE_EVDEV) { + /* for evdev devices we need the parent node as device */ + if (sd_device_get_parent_with_subsystem_devtype(p, "input", NULL, &dev) < 0) + return -ENODEV; + if (sd_device_get_syspath(dev, &sp) < 0) + return -ENODEV; + + } else if (sd->type != DEVICE_TYPE_DRM) + /* Prevent opening unsupported devices. Especially devices of + * subsystem "input" must be opened via the evdev node as + * we require EVIOCREVOKE. */ + return -ENODEV; + + /* search for an existing seat device and return it if available */ + sd->device = hashmap_get(sd->session->manager->devices, sp); + if (!sd->device) { + /* The caller might have gotten the udev event before we were + * able to process it. Hence, fake the "add" event and let the + * logind-manager handle the new device. */ + r = manager_process_seat_device(sd->session->manager, dev); + if (r < 0) + return r; + + /* if it's still not available, then the device is invalid */ + sd->device = hashmap_get(sd->session->manager->devices, sp); + if (!sd->device) + return -ENODEV; + } + + if (sd->device->seat != sd->session->seat) + return -EPERM; + + sd->node = strdup(node); + if (!sd->node) + return -ENOMEM; + + return 0; +} + +int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice **out) { + SessionDevice *sd; + int r; + + assert(s); + assert(out); + + if (!s->seat) + return -EPERM; + + sd = new0(SessionDevice, 1); + if (!sd) + return -ENOMEM; + + sd->session = s; + sd->dev = dev; + sd->fd = -1; + sd->type = DEVICE_TYPE_UNKNOWN; + + r = session_device_verify(sd); + if (r < 0) + goto error; + + r = hashmap_put(s->devices, &sd->dev, sd); + if (r < 0) + goto error; + + if (open_device) { + /* Open the device for the first time. We need a valid fd to pass back + * to the caller. If the session is not active, this _might_ immediately + * revoke access and thus invalidate the fd. But this is still needed + * to pass a valid fd back. */ + sd->active = session_is_active(s); + r = session_device_open(sd, sd->active); + if (r < 0) { + /* EINVAL _may_ mean a master is active; retry inactive */ + if (sd->active && r == -EINVAL) { + sd->active = false; + r = session_device_open(sd, false); + } + if (r < 0) + goto error; + } + sd->fd = r; + } + + LIST_PREPEND(sd_by_device, sd->device->session_devices, sd); + + *out = sd; + return 0; + +error: + hashmap_remove(s->devices, &sd->dev); + free(sd->node); + free(sd); + return r; +} + +void session_device_free(SessionDevice *sd) { + assert(sd); + + /* Make sure to remove the pushed fd. */ + if (sd->pushed_fd) + (void) sd_notifyf(false, + "FDSTOREREMOVE=1\n" + "FDNAME=session-%s-device-%u-%u", + sd->session->id, major(sd->dev), minor(sd->dev)); + + session_device_stop(sd); + session_device_notify(sd, SESSION_DEVICE_RELEASE); + safe_close(sd->fd); + + LIST_REMOVE(sd_by_device, sd->device->session_devices, sd); + + hashmap_remove(sd->session->devices, &sd->dev); + + free(sd->node); + free(sd); +} + +void session_device_complete_pause(SessionDevice *sd) { + SessionDevice *iter; + Iterator i; + + if (!sd->active) + return; + + session_device_stop(sd); + + /* if not all devices are paused, wait for further completion events */ + HASHMAP_FOREACH(iter, sd->session->devices, i) + if (iter->active) + return; + + /* complete any pending session switch */ + seat_complete_switch(sd->session->seat); +} + +void session_device_resume_all(Session *s) { + SessionDevice *sd; + Iterator i; + + assert(s); + + HASHMAP_FOREACH(sd, s->devices, i) { + if (sd->active) + continue; + + if (session_device_start(sd) < 0) + continue; + if (session_device_save(sd) < 0) + continue; + + session_device_notify(sd, SESSION_DEVICE_RESUME); + } +} + +void session_device_pause_all(Session *s) { + SessionDevice *sd; + Iterator i; + + assert(s); + + HASHMAP_FOREACH(sd, s->devices, i) { + if (!sd->active) + continue; + + session_device_stop(sd); + session_device_notify(sd, SESSION_DEVICE_PAUSE); + } +} + +unsigned session_device_try_pause_all(Session *s) { + unsigned num_pending = 0; + SessionDevice *sd; + Iterator i; + + assert(s); + + HASHMAP_FOREACH(sd, s->devices, i) { + if (!sd->active) + continue; + + session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE); + num_pending++; + } + + return num_pending; +} + +int session_device_save(SessionDevice *sd) { + _cleanup_free_ char *m = NULL; + const char *id; + int r; + + assert(sd); + + /* Store device fd in PID1. It will send it back to us on restart so revocation will continue to work. To make + * things simple, send fds for all type of devices even if they don't support the revocation mechanism so we + * don't have to handle them differently later. + * + * Note: for device supporting revocation, PID1 will drop a stored fd automatically if the corresponding device + * is revoked. */ + + if (sd->pushed_fd) + return 0; + + /* Session ID does not contain separators. */ + id = sd->session->id; + assert(*(id + strcspn(id, "-\n")) == '\0'); + + r = asprintf(&m, "FDSTORE=1\n" + "FDNAME=session-%s-device-%u-%u\n", + id, major(sd->dev), minor(sd->dev)); + if (r < 0) + return r; + + r = sd_pid_notify_with_fds(0, false, m, &sd->fd, 1); + if (r < 0) + return r; + + sd->pushed_fd = true; + return 1; +} + +void session_device_attach_fd(SessionDevice *sd, int fd, bool active) { + assert(fd >= 0); + assert(sd); + assert(sd->fd < 0); + assert(!sd->active); + + sd->fd = fd; + sd->pushed_fd = true; + sd->active = active; +} diff --git a/src/login/logind-session-device.h b/src/login/logind-session-device.h new file mode 100644 index 00000000..6c20403d --- /dev/null +++ b/src/login/logind-session-device.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef enum DeviceType DeviceType; +typedef struct SessionDevice SessionDevice; + +#include "list.h" +#include "logind.h" + +enum DeviceType { + DEVICE_TYPE_UNKNOWN, + DEVICE_TYPE_DRM, + DEVICE_TYPE_EVDEV, +}; + +struct SessionDevice { + Session *session; + Device *device; + + dev_t dev; + char *node; + int fd; + DeviceType type:3; + bool active:1; + bool pushed_fd:1; + + LIST_FIELDS(struct SessionDevice, sd_by_device); +}; + +int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice **out); +void session_device_free(SessionDevice *sd); +void session_device_complete_pause(SessionDevice *sd); + +void session_device_resume_all(Session *s); +void session_device_pause_all(Session *s); +unsigned session_device_try_pause_all(Session *s); + +int session_device_save(SessionDevice *sd); +void session_device_attach_fd(SessionDevice *sd, int fd, bool active); diff --git a/src/login/logind-session.c b/src/login/logind-session.c new file mode 100644 index 00000000..a9be416f --- /dev/null +++ b/src/login/logind-session.c @@ -0,0 +1,1432 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "audit-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "env-file.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "io-util.h" +#include "logind-dbus.h" +#include "logind-seat-dbus.h" +#include "logind-session-dbus.h" +#include "logind-session.h" +#include "logind-user-dbus.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "serialize.h" +#include "string-table.h" +#include "strv.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "user-util.h" +#include "util.h" + +#define RELEASE_USEC (20*USEC_PER_SEC) + +static void session_remove_fifo(Session *s); +static void session_restore_vt(Session *s); + +int session_new(Session **ret, Manager *m, const char *id) { + _cleanup_(session_freep) Session *s = NULL; + int r; + + assert(ret); + assert(m); + assert(id); + + if (!session_id_valid(id)) + return -EINVAL; + + s = new(Session, 1); + if (!s) + return -ENOMEM; + + *s = (Session) { + .manager = m, + .fifo_fd = -1, + .vtfd = -1, + .audit_id = AUDIT_SESSION_INVALID, + .tty_validity = _TTY_VALIDITY_INVALID, + }; + + s->state_file = path_join("/run/systemd/sessions", id); + if (!s->state_file) + return -ENOMEM; + + s->id = basename(s->state_file); + + s->devices = hashmap_new(&devt_hash_ops); + if (!s->devices) + return -ENOMEM; + + r = hashmap_put(m->sessions, s->id, s); + if (r < 0) + return r; + + *ret = TAKE_PTR(s); + return 0; +} + +Session* session_free(Session *s) { + SessionDevice *sd; + + if (!s) + return NULL; + + if (s->in_gc_queue) + LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s); + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + + session_drop_controller(s); + + while ((sd = hashmap_first(s->devices))) + session_device_free(sd); + + hashmap_free(s->devices); + + if (s->user) { + LIST_REMOVE(sessions_by_user, s->user->sessions, s); + + if (s->user->display == s) + s->user->display = NULL; + + user_update_last_session_timer(s->user); + } + + if (s->seat) { + if (s->seat->active == s) + s->seat->active = NULL; + if (s->seat->pending_switch == s) + s->seat->pending_switch = NULL; + + seat_evict_position(s->seat, s); + LIST_REMOVE(sessions_by_seat, s->seat->sessions, s); + } + + if (s->scope) { + hashmap_remove(s->manager->session_units, s->scope); + free(s->scope); + } + + if (pid_is_valid(s->leader)) + (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader), s); + + free(s->scope_job); + + sd_bus_message_unref(s->create_message); + + free(s->tty); + free(s->display); + free(s->remote_host); + free(s->remote_user); + free(s->service); + free(s->desktop); + + hashmap_remove(s->manager->sessions, s->id); + + sd_event_source_unref(s->fifo_event_source); + safe_close(s->fifo_fd); + + /* Note that we remove neither the state file nor the fifo path here, since we want both to survive + * daemon restarts */ + free(s->state_file); + free(s->fifo_path); + + return mfree(s); +} + +void session_set_user(Session *s, User *u) { + assert(s); + assert(!s->user); + + s->user = u; + LIST_PREPEND(sessions_by_user, u->sessions, s); + + user_update_last_session_timer(u); +} + +int session_set_leader(Session *s, pid_t pid) { + int r; + + assert(s); + + if (!pid_is_valid(pid)) + return -EINVAL; + + if (s->leader == pid) + return 0; + + r = hashmap_put(s->manager->sessions_by_leader, PID_TO_PTR(pid), s); + if (r < 0) + return r; + + if (pid_is_valid(s->leader)) + (void) hashmap_remove_value(s->manager->sessions_by_leader, PID_TO_PTR(s->leader), s); + + s->leader = pid; + (void) audit_session_from_pid(pid, &s->audit_id); + + return 1; +} + +static void session_save_devices(Session *s, FILE *f) { + SessionDevice *sd; + Iterator i; + + if (!hashmap_isempty(s->devices)) { + fprintf(f, "DEVICES="); + HASHMAP_FOREACH(sd, s->devices, i) + fprintf(f, "%u:%u ", major(sd->dev), minor(sd->dev)); + fprintf(f, "\n"); + } +} + +int session_save(Session *s) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r = 0; + + assert(s); + + if (!s->user) + return -ESTALE; + + if (!s->started) + return 0; + + r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + goto fail; + + r = fopen_temporary(s->state_file, &f, &temp_path); + if (r < 0) + goto fail; + + (void) fchmod(fileno(f), 0644); + + fprintf(f, + "# This is private data. Do not parse.\n" + "UID="UID_FMT"\n" + "USER=%s\n" + "ACTIVE=%i\n" + "IS_DISPLAY=%i\n" + "STATE=%s\n" + "REMOTE=%i\n", + s->user->uid, + s->user->name, + session_is_active(s), + s->user->display == s, + session_state_to_string(session_get_state(s)), + s->remote); + + if (s->type >= 0) + fprintf(f, "TYPE=%s\n", session_type_to_string(s->type)); + + if (s->class >= 0) + fprintf(f, "CLASS=%s\n", session_class_to_string(s->class)); + + if (s->scope) + fprintf(f, "SCOPE=%s\n", s->scope); + if (s->scope_job) + fprintf(f, "SCOPE_JOB=%s\n", s->scope_job); + + if (s->fifo_path) + fprintf(f, "FIFO=%s\n", s->fifo_path); + + if (s->seat) + fprintf(f, "SEAT=%s\n", s->seat->id); + + if (s->tty) + fprintf(f, "TTY=%s\n", s->tty); + + if (s->tty_validity >= 0) + fprintf(f, "TTY_VALIDITY=%s\n", tty_validity_to_string(s->tty_validity)); + + if (s->display) + fprintf(f, "DISPLAY=%s\n", s->display); + + if (s->remote_host) { + _cleanup_free_ char *escaped; + + escaped = cescape(s->remote_host); + if (!escaped) { + r = -ENOMEM; + goto fail; + } + + fprintf(f, "REMOTE_HOST=%s\n", escaped); + } + + if (s->remote_user) { + _cleanup_free_ char *escaped; + + escaped = cescape(s->remote_user); + if (!escaped) { + r = -ENOMEM; + goto fail; + } + + fprintf(f, "REMOTE_USER=%s\n", escaped); + } + + if (s->service) { + _cleanup_free_ char *escaped; + + escaped = cescape(s->service); + if (!escaped) { + r = -ENOMEM; + goto fail; + } + + fprintf(f, "SERVICE=%s\n", escaped); + } + + if (s->desktop) { + _cleanup_free_ char *escaped; + + escaped = cescape(s->desktop); + if (!escaped) { + r = -ENOMEM; + goto fail; + } + + fprintf(f, "DESKTOP=%s\n", escaped); + } + + if (s->seat && seat_has_vts(s->seat)) + fprintf(f, "VTNR=%u\n", s->vtnr); + + if (!s->vtnr) + fprintf(f, "POSITION=%u\n", s->position); + + if (pid_is_valid(s->leader)) + fprintf(f, "LEADER="PID_FMT"\n", s->leader); + + if (audit_session_is_valid(s->audit_id)) + fprintf(f, "AUDIT=%"PRIu32"\n", s->audit_id); + + if (dual_timestamp_is_set(&s->timestamp)) + fprintf(f, + "REALTIME="USEC_FMT"\n" + "MONOTONIC="USEC_FMT"\n", + s->timestamp.realtime, + s->timestamp.monotonic); + + if (s->controller) { + fprintf(f, "CONTROLLER=%s\n", s->controller); + session_save_devices(s, f); + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, s->state_file) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + (void) unlink(s->state_file); + + if (temp_path) + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save session data %s: %m", s->state_file); +} + +static int session_load_devices(Session *s, const char *devices) { + const char *p; + int r = 0; + + assert(s); + + for (p = devices;;) { + _cleanup_free_ char *word = NULL; + SessionDevice *sd; + dev_t dev; + int k; + + k = extract_first_word(&p, &word, NULL, 0); + if (k == 0) + break; + if (k < 0) { + r = k; + break; + } + + k = parse_dev(word, &dev); + if (k < 0) { + r = k; + continue; + } + + /* The file descriptors for loaded devices will be reattached later. */ + k = session_device_new(s, dev, false, &sd); + if (k < 0) + r = k; + } + + if (r < 0) + log_error_errno(r, "Loading session devices for session %s failed: %m", s->id); + + return r; +} + +int session_load(Session *s) { + _cleanup_free_ char *remote = NULL, + *seat = NULL, + *tty_validity = NULL, + *vtnr = NULL, + *state = NULL, + *position = NULL, + *leader = NULL, + *type = NULL, + *class = NULL, + *uid = NULL, + *realtime = NULL, + *monotonic = NULL, + *controller = NULL, + *active = NULL, + *devices = NULL, + *is_display = NULL; + + int k, r; + + assert(s); + + r = parse_env_file(NULL, s->state_file, + "REMOTE", &remote, + "SCOPE", &s->scope, + "SCOPE_JOB", &s->scope_job, + "FIFO", &s->fifo_path, + "SEAT", &seat, + "TTY", &s->tty, + "TTY_VALIDITY", &tty_validity, + "DISPLAY", &s->display, + "REMOTE_HOST", &s->remote_host, + "REMOTE_USER", &s->remote_user, + "SERVICE", &s->service, + "DESKTOP", &s->desktop, + "VTNR", &vtnr, + "STATE", &state, + "POSITION", &position, + "LEADER", &leader, + "TYPE", &type, + "CLASS", &class, + "UID", &uid, + "REALTIME", &realtime, + "MONOTONIC", &monotonic, + "CONTROLLER", &controller, + "ACTIVE", &active, + "DEVICES", &devices, + "IS_DISPLAY", &is_display); + + if (r < 0) + return log_error_errno(r, "Failed to read %s: %m", s->state_file); + + if (!s->user) { + uid_t u; + User *user; + + if (!uid) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), + "UID not specified for session %s", + s->id); + + r = parse_uid(uid, &u); + if (r < 0) { + log_error("Failed to parse UID value %s for session %s.", uid, s->id); + return r; + } + + user = hashmap_get(s->manager->users, UID_TO_PTR(u)); + if (!user) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), + "User of session %s not known.", + s->id); + + session_set_user(s, user); + } + + if (remote) { + k = parse_boolean(remote); + if (k >= 0) + s->remote = k; + } + + if (vtnr) + safe_atou(vtnr, &s->vtnr); + + if (seat && !s->seat) { + Seat *o; + + o = hashmap_get(s->manager->seats, seat); + if (o) + r = seat_attach_session(o, s); + if (!o || r < 0) + log_error("Cannot attach session %s to seat %s", s->id, seat); + } + + if (!s->seat || !seat_has_vts(s->seat)) + s->vtnr = 0; + + if (position && s->seat) { + unsigned npos; + + safe_atou(position, &npos); + seat_claim_position(s->seat, s, npos); + } + + if (tty_validity) { + TTYValidity v; + + v = tty_validity_from_string(tty_validity); + if (v < 0) + log_debug("Failed to parse TTY validity: %s", tty_validity); + else + s->tty_validity = v; + } + + if (leader) { + pid_t pid; + + r = parse_pid(leader, &pid); + if (r < 0) + log_debug_errno(r, "Failed to parse leader PID of session: %s", leader); + else { + r = session_set_leader(s, pid); + if (r < 0) + log_warning_errno(r, "Failed to set session leader PID, ignoring: %m"); + } + } + + if (type) { + SessionType t; + + t = session_type_from_string(type); + if (t >= 0) + s->type = t; + } + + if (class) { + SessionClass c; + + c = session_class_from_string(class); + if (c >= 0) + s->class = c; + } + + if (state && streq(state, "closing")) + s->stopping = true; + + if (s->fifo_path) { + int fd; + + /* If we open an unopened pipe for reading we will not + get an EOF. to trigger an EOF we hence open it for + writing, but close it right away which then will + trigger the EOF. This will happen immediately if no + other process has the FIFO open for writing, i. e. + when the session died before logind (re)started. */ + + fd = session_create_fifo(s); + safe_close(fd); + } + + if (realtime) + (void) deserialize_usec(realtime, &s->timestamp.realtime); + if (monotonic) + (void) deserialize_usec(monotonic, &s->timestamp.monotonic); + + if (active) { + k = parse_boolean(active); + if (k >= 0) + s->was_active = k; + } + + if (is_display) { + /* Note that when enumerating users are loaded before sessions, hence the display session to use is + * something we have to store along with the session and not the user, as in that case we couldn't + * apply it at the time we load the user. */ + + k = parse_boolean(is_display); + if (k < 0) + log_warning_errno(k, "Failed to parse IS_DISPLAY session property: %m"); + else if (k > 0) + s->user->display = s; + } + + if (controller) { + if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) { + session_set_controller(s, controller, false, false); + session_load_devices(s, devices); + } else + session_restore_vt(s); + } + + return r; +} + +int session_activate(Session *s) { + unsigned num_pending; + + assert(s); + assert(s->user); + + if (!s->seat) + return -EOPNOTSUPP; + + if (s->seat->active == s) + return 0; + + /* on seats with VTs, we let VTs manage session-switching */ + if (seat_has_vts(s->seat)) { + if (s->vtnr == 0) + return -EOPNOTSUPP; + + return chvt(s->vtnr); + } + + /* On seats without VTs, we implement session-switching in logind. We + * try to pause all session-devices and wait until the session + * controller acknowledged them. Once all devices are asleep, we simply + * switch the active session and be done. + * We save the session we want to switch to in seat->pending_switch and + * seat_complete_switch() will perform the final switch. */ + + s->seat->pending_switch = s; + + /* if no devices are running, immediately perform the session switch */ + num_pending = session_device_try_pause_all(s); + if (!num_pending) + seat_complete_switch(s->seat); + + return 0; +} + +static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_error *error) { + int r; + + assert(s); + assert(s->user); + + if (!s->scope) { + _cleanup_free_ char *scope = NULL; + const char *description; + + s->scope_job = mfree(s->scope_job); + + scope = strjoin("session-", s->id, ".scope"); + if (!scope) + return log_oom(); + + description = strjoina("Session ", s->id, " of user ", s->user->name); + + r = manager_start_scope( + s->manager, + scope, + s->leader, + s->user->slice, + description, + /* These two have StopWhenUnneeded= set, hence add a dep towards them */ + STRV_MAKE(s->user->runtime_dir_service, + s->user->service), + /* And order us after some more */ + STRV_MAKE("systemd-logind.service", + "systemd-user-sessions.service", + s->user->runtime_dir_service, + s->user->service), + s->user->home, + properties, + error, + &s->scope_job); + if (r < 0) + return log_error_errno(r, "Failed to start session scope %s: %s", + scope, bus_error_message(error, r)); + + s->scope = TAKE_PTR(scope); + } + + (void) hashmap_put(s->manager->session_units, s->scope, s); + + return 0; +} + +int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) { + int r; + + assert(s); + + if (!s->user) + return -ESTALE; + + if (s->stopping) + return -EINVAL; + + if (s->started) + return 0; + + r = user_start(s->user); + if (r < 0) + return r; + + r = session_start_scope(s, properties, error); + if (r < 0) + return r; + + log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_SESSION_START_STR, + "SESSION_ID=%s", s->id, + "USER_ID=%s", s->user->name, + "LEADER="PID_FMT, s->leader, + LOG_MESSAGE("New session %s of user %s.", s->id, s->user->name)); + + if (!dual_timestamp_is_set(&s->timestamp)) + dual_timestamp_get(&s->timestamp); + + if (s->seat) + seat_read_active_vt(s->seat); + + s->started = true; + + user_elect_display(s->user); + + /* Save data */ + session_save(s); + user_save(s->user); + if (s->seat) + seat_save(s->seat); + + /* Send signals */ + session_send_signal(s, true); + user_send_changed(s->user, "Display", NULL); + if (s->seat) { + if (s->seat->active == s) + seat_send_changed(s->seat, "ActiveSession", NULL); + } + + return 0; +} + +static int session_stop_scope(Session *s, bool force) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(s); + + if (!s->scope) + return 0; + + /* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything + * that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log + * when killing any processes left after this point. */ + r = manager_abandon_scope(s->manager, s->scope, &error); + if (r < 0) { + log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r)); + sd_bus_error_free(&error); + } + + s->scope_job = mfree(s->scope_job); + + /* Optionally, let's kill everything that's left now. */ + if (force || manager_shall_kill(s->manager, s->user->name)) { + + r = manager_stop_unit(s->manager, s->scope, &error, &s->scope_job); + if (r < 0) { + if (force) + return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r)); + + log_warning_errno(r, "Failed to stop session scope, ignoring: %s", bus_error_message(&error, r)); + } + } else { + + /* With no killing, this session is allowed to persist in "closing" state indefinitely. + * Therefore session stop and session removal may be two distinct events. + * Session stop is quite significant on its own, let's log it. */ + log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO, + "SESSION_ID=%s", s->id, + "USER_ID=%s", s->user->name, + "LEADER="PID_FMT, s->leader, + LOG_MESSAGE("Session %s logged out. Waiting for processes to exit.", s->id)); + } + + return 0; +} + +int session_stop(Session *s, bool force) { + int r; + + assert(s); + + /* This is called whenever we begin with tearing down a session record. It's called in four cases: explicit API + * request via the bus (either directly for the session object or for the seat or user object this session + * belongs to; 'force' is true), or due to automatic GC (i.e. scope vanished; 'force' is false), or because the + * session FIFO saw an EOF ('force' is false), or because the release timer hit ('force' is false). */ + + if (!s->user) + return -ESTALE; + if (!s->started) + return 0; + if (s->stopping) + return 0; + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + + if (s->seat) + seat_evict_position(s->seat, s); + + /* We are going down, don't care about FIFOs anymore */ + session_remove_fifo(s); + + /* Kill cgroup */ + r = session_stop_scope(s, force); + + s->stopping = true; + + user_elect_display(s->user); + + session_save(s); + user_save(s->user); + + return r; +} + +int session_finalize(Session *s) { + SessionDevice *sd; + + assert(s); + + if (!s->user) + return -ESTALE; + + if (s->started) + log_struct(s->class == SESSION_BACKGROUND ? LOG_DEBUG : LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_SESSION_STOP_STR, + "SESSION_ID=%s", s->id, + "USER_ID=%s", s->user->name, + "LEADER="PID_FMT, s->leader, + LOG_MESSAGE("Removed session %s.", s->id)); + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + + if (s->seat) + seat_evict_position(s->seat, s); + + /* Kill session devices */ + while ((sd = hashmap_first(s->devices))) + session_device_free(sd); + + (void) unlink(s->state_file); + session_add_to_gc_queue(s); + user_add_to_gc_queue(s->user); + + if (s->started) { + session_send_signal(s, false); + s->started = false; + } + + if (s->seat) { + if (s->seat->active == s) + seat_set_active(s->seat, NULL); + + seat_save(s->seat); + } + + user_save(s->user); + user_send_changed(s->user, "Display", NULL); + + return 0; +} + +static int release_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) { + Session *s = userdata; + + assert(es); + assert(s); + + session_stop(s, false); + return 0; +} + +int session_release(Session *s) { + assert(s); + + if (!s->started || s->stopping) + return 0; + + if (s->timer_event_source) + return 0; + + return sd_event_add_time(s->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, + usec_add(now(CLOCK_MONOTONIC), RELEASE_USEC), 0, + release_timeout_callback, s); +} + +bool session_is_active(Session *s) { + assert(s); + + if (!s->seat) + return true; + + return s->seat->active == s; +} + +static int get_tty_atime(const char *tty, usec_t *atime) { + _cleanup_free_ char *p = NULL; + struct stat st; + + assert(tty); + assert(atime); + + if (!path_is_absolute(tty)) { + p = path_join("/dev", tty); + if (!p) + return -ENOMEM; + + tty = p; + } else if (!path_startswith(tty, "/dev/")) + return -ENOENT; + + if (lstat(tty, &st) < 0) + return -errno; + + *atime = timespec_load(&st.st_atim); + return 0; +} + +static int get_process_ctty_atime(pid_t pid, usec_t *atime) { + _cleanup_free_ char *p = NULL; + int r; + + assert(pid > 0); + assert(atime); + + r = get_ctty(pid, NULL, &p); + if (r < 0) + return r; + + return get_tty_atime(p, atime); +} + +int session_get_idle_hint(Session *s, dual_timestamp *t) { + usec_t atime = 0; + int r; + + assert(s); + + /* Graphical sessions have an explicit idle hint */ + if (SESSION_TYPE_IS_GRAPHICAL(s->type)) { + if (t) + *t = s->idle_hint_timestamp; + + return s->idle_hint; + } + + /* For sessions with an explicitly configured tty, let's check its atime */ + if (s->tty) { + r = get_tty_atime(s->tty, &atime); + if (r >= 0) + goto found_atime; + } + + /* For sessions with a leader but no explicitly configured tty, let's check the controlling tty of + * the leader */ + if (pid_is_valid(s->leader)) { + r = get_process_ctty_atime(s->leader, &atime); + if (r >= 0) + goto found_atime; + } + + if (t) + *t = DUAL_TIMESTAMP_NULL; + + return false; + +found_atime: + if (t) + dual_timestamp_from_realtime(t, atime); + + if (s->manager->idle_action_usec <= 0) + return false; + + return usec_add(atime, s->manager->idle_action_usec) <= now(CLOCK_REALTIME); +} + +int session_set_idle_hint(Session *s, bool b) { + assert(s); + + if (!SESSION_TYPE_IS_GRAPHICAL(s->type)) + return -ENOTTY; + + if (s->idle_hint == b) + return 0; + + s->idle_hint = b; + dual_timestamp_get(&s->idle_hint_timestamp); + + session_send_changed(s, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL); + + if (s->seat) + seat_send_changed(s->seat, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL); + + user_send_changed(s->user, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL); + manager_send_changed(s->manager, "IdleHint", "IdleSinceHint", "IdleSinceHintMonotonic", NULL); + + return 1; +} + +int session_get_locked_hint(Session *s) { + assert(s); + + return s->locked_hint; +} + +void session_set_locked_hint(Session *s, bool b) { + assert(s); + + if (s->locked_hint == b) + return; + + s->locked_hint = b; + + session_send_changed(s, "LockedHint", NULL); +} + +static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + Session *s = userdata; + + assert(s); + assert(s->fifo_fd == fd); + + /* EOF on the FIFO means the session died abnormally. */ + + session_remove_fifo(s); + session_stop(s, false); + + return 1; +} + +int session_create_fifo(Session *s) { + int r; + + assert(s); + + /* Create FIFO */ + if (!s->fifo_path) { + r = mkdir_safe_label("/run/systemd/sessions", 0755, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + return r; + + s->fifo_path = strjoin("/run/systemd/sessions/", s->id, ".ref"); + if (!s->fifo_path) + return -ENOMEM; + + if (mkfifo(s->fifo_path, 0600) < 0 && errno != EEXIST) + return -errno; + } + + /* Open reading side */ + if (s->fifo_fd < 0) { + s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (s->fifo_fd < 0) + return -errno; + } + + if (!s->fifo_event_source) { + r = sd_event_add_io(s->manager->event, &s->fifo_event_source, s->fifo_fd, 0, session_dispatch_fifo, s); + if (r < 0) + return r; + + /* Let's make sure we noticed dead sessions before we process new bus requests (which might create new + * sessions). */ + r = sd_event_source_set_priority(s->fifo_event_source, SD_EVENT_PRIORITY_NORMAL-10); + if (r < 0) + return r; + } + + /* Open writing side */ + r = open(s->fifo_path, O_WRONLY|O_CLOEXEC|O_NONBLOCK); + if (r < 0) + return -errno; + + return r; +} + +static void session_remove_fifo(Session *s) { + assert(s); + + s->fifo_event_source = sd_event_source_unref(s->fifo_event_source); + s->fifo_fd = safe_close(s->fifo_fd); + + if (s->fifo_path) { + (void) unlink(s->fifo_path); + s->fifo_path = mfree(s->fifo_path); + } +} + +bool session_may_gc(Session *s, bool drop_not_started) { + int r; + + assert(s); + + if (drop_not_started && !s->started) + return true; + + if (!s->user) + return true; + + if (s->fifo_fd >= 0) { + if (pipe_eof(s->fifo_fd) <= 0) + return false; + } + + if (s->scope_job) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = manager_job_is_active(s->manager, s->scope_job, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", s->scope_job, bus_error_message(&error, r)); + if (r != 0) + return false; + } + + if (s->scope) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = manager_unit_is_active(s->manager, s->scope, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", s->scope, bus_error_message(&error, r)); + if (r != 0) + return false; + } + + return true; +} + +void session_add_to_gc_queue(Session *s) { + assert(s); + + if (s->in_gc_queue) + return; + + LIST_PREPEND(gc_queue, s->manager->session_gc_queue, s); + s->in_gc_queue = true; +} + +SessionState session_get_state(Session *s) { + assert(s); + + /* always check closing first */ + if (s->stopping || s->timer_event_source) + return SESSION_CLOSING; + + if (s->scope_job || s->fifo_fd < 0) + return SESSION_OPENING; + + if (session_is_active(s)) + return SESSION_ACTIVE; + + return SESSION_ONLINE; +} + +int session_kill(Session *s, KillWho who, int signo) { + assert(s); + + if (!s->scope) + return -ESRCH; + + return manager_kill_unit(s->manager, s->scope, who, signo, NULL); +} + +static int session_open_vt(Session *s) { + char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)]; + + if (s->vtnr < 1) + return -ENODEV; + + if (s->vtfd >= 0) + return s->vtfd; + + sprintf(path, "/dev/tty%u", s->vtnr); + s->vtfd = open_terminal(path, O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY); + if (s->vtfd < 0) + return log_error_errno(s->vtfd, "cannot open VT %s of session %s: %m", path, s->id); + + return s->vtfd; +} + +static int session_prepare_vt(Session *s) { + int vt, r; + struct vt_mode mode = {}; + + if (s->vtnr < 1) + return 0; + + vt = session_open_vt(s); + if (vt < 0) + return vt; + + r = fchown(vt, s->user->uid, -1); + if (r < 0) { + r = log_error_errno(errno, + "Cannot change owner of /dev/tty%u: %m", + s->vtnr); + goto error; + } + + r = ioctl(vt, KDSKBMODE, K_OFF); + if (r < 0) { + r = log_error_errno(errno, + "Cannot set K_OFF on /dev/tty%u: %m", + s->vtnr); + goto error; + } + + r = ioctl(vt, KDSETMODE, KD_GRAPHICS); + if (r < 0) { + r = log_error_errno(errno, + "Cannot set KD_GRAPHICS on /dev/tty%u: %m", + s->vtnr); + goto error; + } + + /* Oh, thanks to the VT layer, VT_AUTO does not work with KD_GRAPHICS. + * So we need a dummy handler here which just acknowledges *all* VT + * switch requests. */ + mode.mode = VT_PROCESS; + mode.relsig = SIGRTMIN; + mode.acqsig = SIGRTMIN + 1; + r = ioctl(vt, VT_SETMODE, &mode); + if (r < 0) { + r = log_error_errno(errno, + "Cannot set VT_PROCESS on /dev/tty%u: %m", + s->vtnr); + goto error; + } + + return 0; + +error: + session_restore_vt(s); + return r; +} + +static void session_restore_vt(Session *s) { + int r; + + r = vt_restore(s->vtfd); + if (r == -EIO) { + int vt, old_fd; + + /* It might happen if the controlling process exited before or while we were + * restoring the VT as it would leave the old file-descriptor in a hung-up + * state. In this case let's retry with a fresh handle to the virtual terminal. */ + + /* We do a little dance to avoid having the terminal be available + * for reuse before we've cleaned it up. */ + old_fd = TAKE_FD(s->vtfd); + + vt = session_open_vt(s); + safe_close(old_fd); + + if (vt >= 0) + r = vt_restore(vt); + } + + if (r < 0) + log_warning_errno(r, "Failed to restore VT, ignoring: %m"); + + s->vtfd = safe_close(s->vtfd); +} + +void session_leave_vt(Session *s) { + int r; + + assert(s); + + /* This is called whenever we get a VT-switch signal from the kernel. + * We acknowledge all of them unconditionally. Note that session are + * free to overwrite those handlers and we only register them for + * sessions with controllers. Legacy sessions are not affected. + * However, if we switch from a non-legacy to a legacy session, we must + * make sure to pause all device before acknowledging the switch. We + * process the real switch only after we are notified via sysfs, so the + * legacy session might have already started using the devices. If we + * don't pause the devices before the switch, we might confuse the + * session we switch to. */ + + if (s->vtfd < 0) + return; + + session_device_pause_all(s); + r = vt_release(s->vtfd, false); + if (r < 0) + log_debug_errno(r, "Cannot release VT of session %s: %m", s->id); +} + +bool session_is_controller(Session *s, const char *sender) { + assert(s); + + return streq_ptr(s->controller, sender); +} + +static void session_release_controller(Session *s, bool notify) { + _cleanup_free_ char *name = NULL; + SessionDevice *sd; + + if (!s->controller) + return; + + name = s->controller; + + /* By resetting the controller before releasing the devices, we won't + * send notification signals. This avoids sending useless notifications + * if the controller is released on disconnects. */ + if (!notify) + s->controller = NULL; + + while ((sd = hashmap_first(s->devices))) + session_device_free(sd); + + s->controller = NULL; + s->track = sd_bus_track_unref(s->track); +} + +static int on_bus_track(sd_bus_track *track, void *userdata) { + Session *s = userdata; + + assert(track); + assert(s); + + session_drop_controller(s); + + return 0; +} + +int session_set_controller(Session *s, const char *sender, bool force, bool prepare) { + _cleanup_free_ char *name = NULL; + int r; + + assert(s); + assert(sender); + + if (session_is_controller(s, sender)) + return 0; + if (s->controller && !force) + return -EBUSY; + + name = strdup(sender); + if (!name) + return -ENOMEM; + + s->track = sd_bus_track_unref(s->track); + r = sd_bus_track_new(s->manager->bus, &s->track, on_bus_track, s); + if (r < 0) + return r; + + r = sd_bus_track_add_name(s->track, name); + if (r < 0) + return r; + + /* When setting a session controller, we forcibly mute the VT and set + * it into graphics-mode. Applications can override that by changing + * VT state after calling TakeControl(). However, this serves as a good + * default and well-behaving controllers can now ignore VTs entirely. + * Note that we reset the VT on ReleaseControl() and if the controller + * exits. + * If logind crashes/restarts, we restore the controller during restart + * (without preparing the VT since the controller has probably overridden + * VT state by now) or reset the VT in case it crashed/exited, too. */ + if (prepare) { + r = session_prepare_vt(s); + if (r < 0) { + s->track = sd_bus_track_unref(s->track); + return r; + } + } + + session_release_controller(s, true); + s->controller = TAKE_PTR(name); + session_save(s); + + return 0; +} + +void session_drop_controller(Session *s) { + assert(s); + + if (!s->controller) + return; + + s->track = sd_bus_track_unref(s->track); + session_release_controller(s, false); + session_save(s); + session_restore_vt(s); +} + +static const char* const session_state_table[_SESSION_STATE_MAX] = { + [SESSION_OPENING] = "opening", + [SESSION_ONLINE] = "online", + [SESSION_ACTIVE] = "active", + [SESSION_CLOSING] = "closing" +}; + +DEFINE_STRING_TABLE_LOOKUP(session_state, SessionState); + +static const char* const session_type_table[_SESSION_TYPE_MAX] = { + [SESSION_UNSPECIFIED] = "unspecified", + [SESSION_TTY] = "tty", + [SESSION_X11] = "x11", + [SESSION_WAYLAND] = "wayland", + [SESSION_MIR] = "mir", + [SESSION_WEB] = "web", +}; + +DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType); + +static const char* const session_class_table[_SESSION_CLASS_MAX] = { + [SESSION_USER] = "user", + [SESSION_GREETER] = "greeter", + [SESSION_LOCK_SCREEN] = "lock-screen", + [SESSION_BACKGROUND] = "background" +}; + +DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass); + +static const char* const kill_who_table[_KILL_WHO_MAX] = { + [KILL_LEADER] = "leader", + [KILL_ALL] = "all" +}; + +DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho); + +static const char* const tty_validity_table[_TTY_VALIDITY_MAX] = { + [TTY_FROM_PAM] = "from-pam", + [TTY_FROM_UTMP] = "from-utmp", + [TTY_UTMP_INCONSISTENT] = "utmp-inconsistent", +}; + +DEFINE_STRING_TABLE_LOOKUP(tty_validity, TTYValidity); diff --git a/src/login/logind-session.h b/src/login/logind-session.h new file mode 100644 index 00000000..c51392be --- /dev/null +++ b/src/login/logind-session.h @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Session Session; +typedef enum KillWho KillWho; + +#include "list.h" +#include "login-util.h" +#include "logind-user.h" +#include "string-util.h" + +typedef enum SessionState { + SESSION_OPENING, /* Session scope is being created */ + SESSION_ONLINE, /* Logged in */ + SESSION_ACTIVE, /* Logged in and in the fg */ + SESSION_CLOSING, /* Logged out, but scope is still there */ + _SESSION_STATE_MAX, + _SESSION_STATE_INVALID = -1 +} SessionState; + +typedef enum SessionClass { + SESSION_USER, + SESSION_GREETER, + SESSION_LOCK_SCREEN, + SESSION_BACKGROUND, + _SESSION_CLASS_MAX, + _SESSION_CLASS_INVALID = -1 +} SessionClass; + +typedef enum SessionType { + SESSION_UNSPECIFIED, + SESSION_TTY, + SESSION_X11, + SESSION_WAYLAND, + SESSION_MIR, + SESSION_WEB, + _SESSION_TYPE_MAX, + _SESSION_TYPE_INVALID = -1 +} SessionType; + +#define SESSION_TYPE_IS_GRAPHICAL(type) IN_SET(type, SESSION_X11, SESSION_WAYLAND, SESSION_MIR) + +enum KillWho { + KILL_LEADER, + KILL_ALL, + _KILL_WHO_MAX, + _KILL_WHO_INVALID = -1 +}; + +typedef enum TTYValidity { + TTY_FROM_PAM, + TTY_FROM_UTMP, + TTY_UTMP_INCONSISTENT, /* may happen on ssh sessions with multiplexed TTYs */ + _TTY_VALIDITY_MAX, + _TTY_VALIDITY_INVALID = -1, +} TTYValidity; + +struct Session { + Manager *manager; + + const char *id; + unsigned position; + SessionType type; + SessionClass class; + + char *state_file; + + User *user; + + dual_timestamp timestamp; + + char *display; + char *tty; + TTYValidity tty_validity; + + bool remote; + char *remote_user; + char *remote_host; + char *service; + char *desktop; + + char *scope; + char *scope_job; + + Seat *seat; + unsigned vtnr; + int vtfd; + + pid_t leader; + uint32_t audit_id; + + int fifo_fd; + char *fifo_path; + + sd_event_source *fifo_event_source; + + bool idle_hint; + dual_timestamp idle_hint_timestamp; + + bool locked_hint; + + bool in_gc_queue:1; + bool started:1; + bool stopping:1; + + bool was_active:1; + + sd_bus_message *create_message; + + /* Set up when a client requested to release the session via the bus */ + sd_event_source *timer_event_source; + + char *controller; + Hashmap *devices; + sd_bus_track *track; + + LIST_FIELDS(Session, sessions_by_user); + LIST_FIELDS(Session, sessions_by_seat); + + LIST_FIELDS(Session, gc_queue); +}; + +int session_new(Session **ret, Manager *m, const char *id); +Session* session_free(Session *s); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Session *, session_free); + +void session_set_user(Session *s, User *u); +int session_set_leader(Session *s, pid_t pid); +bool session_may_gc(Session *s, bool drop_not_started); +void session_add_to_gc_queue(Session *s); +int session_activate(Session *s); +bool session_is_active(Session *s); +int session_get_idle_hint(Session *s, dual_timestamp *t); +int session_set_idle_hint(Session *s, bool b); +int session_get_locked_hint(Session *s); +void session_set_locked_hint(Session *s, bool b); +int session_create_fifo(Session *s); +int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error); +int session_stop(Session *s, bool force); +int session_finalize(Session *s); +int session_release(Session *s); +int session_save(Session *s); +int session_load(Session *s); +int session_kill(Session *s, KillWho who, int signo); + +SessionState session_get_state(Session *u); + +const char* session_state_to_string(SessionState t) _const_; +SessionState session_state_from_string(const char *s) _pure_; + +const char* session_type_to_string(SessionType t) _const_; +SessionType session_type_from_string(const char *s) _pure_; + +const char* session_class_to_string(SessionClass t) _const_; +SessionClass session_class_from_string(const char *s) _pure_; + +const char *kill_who_to_string(KillWho k) _const_; +KillWho kill_who_from_string(const char *s) _pure_; + +const char* tty_validity_to_string(TTYValidity t) _const_; +TTYValidity tty_validity_from_string(const char *s) _pure_; + +void session_leave_vt(Session *s); + +bool session_is_controller(Session *s, const char *sender); +int session_set_controller(Session *s, const char *sender, bool force, bool prepare); +void session_drop_controller(Session *s); + +static inline bool SESSION_IS_SELF(const char *name) { + return isempty(name) || streq(name, "self"); +} + +static inline bool SESSION_IS_AUTO(const char *name) { + return streq_ptr(name, "auto"); +} diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c new file mode 100644 index 00000000..d9f1dfe4 --- /dev/null +++ b/src/login/logind-user-dbus.c @@ -0,0 +1,368 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "format-util.h" +#include "logind-dbus.h" +#include "logind-session-dbus.h" +#include "logind-user-dbus.h" +#include "logind-user.h" +#include "logind.h" +#include "missing_capability.h" +#include "signal-util.h" +#include "strv.h" +#include "user-util.h" + +static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", User, user_get_state, user_state_to_string); + +static int property_get_display( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_free_ char *p = NULL; + User *u = userdata; + + assert(bus); + assert(reply); + assert(u); + + p = u->display ? session_bus_path(u->display) : strdup("/"); + if (!p) + return -ENOMEM; + + return sd_bus_message_append(reply, "(so)", u->display ? u->display->id : "", p); +} + +static int property_get_sessions( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + User *u = userdata; + Session *session; + int r; + + assert(bus); + assert(reply); + assert(u); + + r = sd_bus_message_open_container(reply, 'a', "(so)"); + if (r < 0) + return r; + + LIST_FOREACH(sessions_by_user, session, u->sessions) { + _cleanup_free_ char *p = NULL; + + p = session_bus_path(session); + if (!p) + return -ENOMEM; + + r = sd_bus_message_append(reply, "(so)", session->id, p); + if (r < 0) + return r; + + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_idle_hint( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + User *u = userdata; + + assert(bus); + assert(reply); + assert(u); + + return sd_bus_message_append(reply, "b", user_get_idle_hint(u, NULL) > 0); +} + +static int property_get_idle_since_hint( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + User *u = userdata; + dual_timestamp t = DUAL_TIMESTAMP_NULL; + uint64_t k; + + assert(bus); + assert(reply); + assert(u); + + (void) user_get_idle_hint(u, &t); + k = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic; + + return sd_bus_message_append(reply, "t", k); +} + +static int property_get_linger( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + User *u = userdata; + int r; + + assert(bus); + assert(reply); + assert(u); + + r = user_check_linger_file(u); + + return sd_bus_message_append(reply, "b", r > 0); +} + +int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) { + User *u = userdata; + int r; + + assert(message); + assert(u); + + r = bus_verify_polkit_async( + message, + CAP_KILL, + "org.freedesktop.login1.manage", + NULL, + false, + u->uid, + &u->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = user_stop(u, true); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) { + User *u = userdata; + int32_t signo; + int r; + + assert(message); + assert(u); + + r = bus_verify_polkit_async( + message, + CAP_KILL, + "org.freedesktop.login1.manage", + NULL, + false, + u->uid, + &u->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = sd_bus_message_read(message, "i", &signo); + if (r < 0) + return r; + + if (!SIGNAL_VALID(signo)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo); + + r = user_kill(u, signo); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +const sd_bus_vtable user_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("UID", "u", bus_property_get_uid, offsetof(User, uid), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(User, gid), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Name", "s", NULL, offsetof(User, name), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(User, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RuntimePath", "s", NULL, offsetof(User, runtime_path), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Service", "s", NULL, offsetof(User, service), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Slice", "s", NULL, offsetof(User, slice), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Display", "(so)", property_get_display, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0), + SD_BUS_PROPERTY("Sessions", "a(so)", property_get_sessions, 0, 0), + SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0), + + SD_BUS_METHOD("Terminate", NULL, NULL, bus_user_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Kill", "i", NULL, bus_user_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_VTABLE_END +}; + +int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + uid_t uid; + User *user; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + if (streq(path, "/org/freedesktop/login1/user/self")) { + sd_bus_message *message; + + message = sd_bus_get_current_message(bus); + + r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user); + if (r == -ENXIO) { + sd_bus_error_free(error); + return 0; + } + if (r < 0) + return r; + } else { + const char *p; + + p = startswith(path, "/org/freedesktop/login1/user/_"); + if (!p) + return 0; + + r = parse_uid(p, &uid); + if (r < 0) + return 0; + + user = hashmap_get(m->users, UID_TO_PTR(uid)); + if (!user) + return 0; + } + + *found = user; + return 1; +} + +char *user_bus_path(User *u) { + char *s; + + assert(u); + + if (asprintf(&s, "/org/freedesktop/login1/user/_"UID_FMT, u->uid) < 0) + return NULL; + + return s; +} + +int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + sd_bus_message *message; + Manager *m = userdata; + User *user; + Iterator i; + int r; + + assert(bus); + assert(path); + assert(nodes); + + HASHMAP_FOREACH(user, m->users, i) { + char *p; + + p = user_bus_path(user); + if (!p) + return -ENOMEM; + + r = strv_consume(&l, p); + if (r < 0) + return r; + } + + message = sd_bus_get_current_message(bus); + if (message) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); + if (r >= 0) { + uid_t uid; + + r = sd_bus_creds_get_owner_uid(creds, &uid); + if (r >= 0) { + user = hashmap_get(m->users, UID_TO_PTR(uid)); + if (user) { + r = strv_extend(&l, "/org/freedesktop/login1/user/self"); + if (r < 0) + return r; + } + } + } + } + + *nodes = TAKE_PTR(l); + + return 1; +} + +int user_send_signal(User *u, bool new_user) { + _cleanup_free_ char *p = NULL; + + assert(u); + + p = user_bus_path(u); + if (!p) + return -ENOMEM; + + return sd_bus_emit_signal( + u->manager->bus, + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + new_user ? "UserNew" : "UserRemoved", + "uo", (uint32_t) u->uid, p); +} + +int user_send_changed(User *u, const char *properties, ...) { + _cleanup_free_ char *p = NULL; + char **l; + + assert(u); + + if (!u->started) + return 0; + + p = user_bus_path(u); + if (!p) + return -ENOMEM; + + l = strv_from_stdarg_alloca(properties); + + return sd_bus_emit_properties_changed_strv(u->manager->bus, p, "org.freedesktop.login1.User", l); +} diff --git a/src/login/logind-user-dbus.h b/src/login/logind-user-dbus.h new file mode 100644 index 00000000..acfcb981 --- /dev/null +++ b/src/login/logind-user-dbus.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "logind-user.h" + +extern const sd_bus_vtable user_vtable[]; +int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); +int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +char *user_bus_path(User *s); + +int user_send_signal(User *u, bool new_user); +int user_send_changed(User *u, const char *properties, ...) _sentinel_; + +int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/login/logind-user.c b/src/login/logind-user.c new file mode 100644 index 00000000..1550431b --- /dev/null +++ b/src/login/logind-user.c @@ -0,0 +1,861 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-util.h" +#include "cgroup-util.h" +#include "clean-ipc.h" +#include "env-file.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "label.h" +#include "limits-util.h" +#include "logind-dbus.h" +#include "logind-user.h" +#include "logind-user-dbus.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "serialize.h" +#include "special.h" +#include "stdio-util.h" +#include "string-table.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "unit-name.h" +#include "user-util.h" +#include "util.h" + +int user_new(User **ret, + Manager *m, + uid_t uid, + gid_t gid, + const char *name, + const char *home) { + + _cleanup_(user_freep) User *u = NULL; + char lu[DECIMAL_STR_MAX(uid_t) + 1]; + int r; + + assert(ret); + assert(m); + assert(name); + + u = new(User, 1); + if (!u) + return -ENOMEM; + + *u = (User) { + .manager = m, + .uid = uid, + .gid = gid, + .last_session_timestamp = USEC_INFINITY, + }; + + u->name = strdup(name); + if (!u->name) + return -ENOMEM; + + u->home = strdup(home); + if (!u->home) + return -ENOMEM; + + path_simplify(u->home, true); + + if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0) + return -ENOMEM; + + if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0) + return -ENOMEM; + + xsprintf(lu, UID_FMT, uid); + r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice); + if (r < 0) + return r; + + r = unit_name_build("user", lu, ".service", &u->service); + if (r < 0) + return r; + + r = unit_name_build("user-runtime-dir", lu, ".service", &u->runtime_dir_service); + if (r < 0) + return r; + + r = hashmap_put(m->users, UID_TO_PTR(uid), u); + if (r < 0) + return r; + + r = hashmap_put(m->user_units, u->slice, u); + if (r < 0) + return r; + + r = hashmap_put(m->user_units, u->service, u); + if (r < 0) + return r; + + r = hashmap_put(m->user_units, u->runtime_dir_service, u); + if (r < 0) + return r; + + *ret = TAKE_PTR(u); + return 0; +} + +User *user_free(User *u) { + if (!u) + return NULL; + + if (u->in_gc_queue) + LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u); + + while (u->sessions) + session_free(u->sessions); + + if (u->service) + hashmap_remove_value(u->manager->user_units, u->service, u); + + if (u->runtime_dir_service) + hashmap_remove_value(u->manager->user_units, u->runtime_dir_service, u); + + if (u->slice) + hashmap_remove_value(u->manager->user_units, u->slice, u); + + hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u); + + (void) sd_event_source_unref(u->timer_event_source); + + u->service_job = mfree(u->service_job); + + u->service = mfree(u->service); + u->runtime_dir_service = mfree(u->runtime_dir_service); + u->slice = mfree(u->slice); + u->runtime_path = mfree(u->runtime_path); + u->state_file = mfree(u->state_file); + u->name = mfree(u->name); + u->home = mfree(u->home); + + return mfree(u); +} + +static int user_save_internal(User *u) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(u); + assert(u->state_file); + + r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + goto fail; + + r = fopen_temporary(u->state_file, &f, &temp_path); + if (r < 0) + goto fail; + + (void) fchmod(fileno(f), 0644); + + fprintf(f, + "# This is private data. Do not parse.\n" + "NAME=%s\n" + "STATE=%s\n" /* friendly user-facing state */ + "STOPPING=%s\n", /* low-level state */ + u->name, + user_state_to_string(user_get_state(u)), + yes_no(u->stopping)); + + /* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */ + if (u->runtime_path) + fprintf(f, "RUNTIME=%s\n", u->runtime_path); + + if (u->service_job) + fprintf(f, "SERVICE_JOB=%s\n", u->service_job); + + if (u->display) + fprintf(f, "DISPLAY=%s\n", u->display->id); + + if (dual_timestamp_is_set(&u->timestamp)) + fprintf(f, + "REALTIME="USEC_FMT"\n" + "MONOTONIC="USEC_FMT"\n", + u->timestamp.realtime, + u->timestamp.monotonic); + + if (u->last_session_timestamp != USEC_INFINITY) + fprintf(f, "LAST_SESSION_TIMESTAMP=" USEC_FMT "\n", + u->last_session_timestamp); + + if (u->sessions) { + Session *i; + bool first; + + fputs("SESSIONS=", f); + first = true; + LIST_FOREACH(sessions_by_user, i, u->sessions) { + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->id, f); + } + + fputs("\nSEATS=", f); + first = true; + LIST_FOREACH(sessions_by_user, i, u->sessions) { + if (!i->seat) + continue; + + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->seat->id, f); + } + + fputs("\nACTIVE_SESSIONS=", f); + first = true; + LIST_FOREACH(sessions_by_user, i, u->sessions) { + if (!session_is_active(i)) + continue; + + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->id, f); + } + + fputs("\nONLINE_SESSIONS=", f); + first = true; + LIST_FOREACH(sessions_by_user, i, u->sessions) { + if (session_get_state(i) == SESSION_CLOSING) + continue; + + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->id, f); + } + + fputs("\nACTIVE_SEATS=", f); + first = true; + LIST_FOREACH(sessions_by_user, i, u->sessions) { + if (!session_is_active(i) || !i->seat) + continue; + + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->seat->id, f); + } + + fputs("\nONLINE_SEATS=", f); + first = true; + LIST_FOREACH(sessions_by_user, i, u->sessions) { + if (session_get_state(i) == SESSION_CLOSING || !i->seat) + continue; + + if (first) + first = false; + else + fputc(' ', f); + + fputs(i->seat->id, f); + } + fputc('\n', f); + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, u->state_file) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + (void) unlink(u->state_file); + + if (temp_path) + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save user data %s: %m", u->state_file); +} + +int user_save(User *u) { + assert(u); + + if (!u->started) + return 0; + + return user_save_internal(u); +} + +int user_load(User *u) { + _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *stopping = NULL, *last_session_timestamp = NULL; + int r; + + assert(u); + + r = parse_env_file(NULL, u->state_file, + "SERVICE_JOB", &u->service_job, + "STOPPING", &stopping, + "REALTIME", &realtime, + "MONOTONIC", &monotonic, + "LAST_SESSION_TIMESTAMP", &last_session_timestamp); + if (r == -ENOENT) + return 0; + if (r < 0) + return log_error_errno(r, "Failed to read %s: %m", u->state_file); + + if (stopping) { + r = parse_boolean(stopping); + if (r < 0) + log_debug_errno(r, "Failed to parse 'STOPPING' boolean: %s", stopping); + else + u->stopping = r; + } + + if (realtime) + (void) deserialize_usec(realtime, &u->timestamp.realtime); + if (monotonic) + (void) deserialize_usec(monotonic, &u->timestamp.monotonic); + if (last_session_timestamp) + (void) deserialize_usec(last_session_timestamp, &u->last_session_timestamp); + + return 0; +} + +static void user_start_service(User *u) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(u); + + /* Start the service containing the "systemd --user" instance (user@.service). Note that we don't explicitly + * start the per-user slice or the systemd-runtime-dir@.service instance, as those are pulled in both by + * user@.service and the session scopes as dependencies. */ + + u->service_job = mfree(u->service_job); + + r = manager_start_unit(u->manager, u->service, &error, &u->service_job); + if (r < 0) + log_full_errno(sd_bus_error_has_name(&error, BUS_ERROR_UNIT_MASKED) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to start user service '%s', ignoring: %s", u->service, bus_error_message(&error, r)); +} + +int user_start(User *u) { + assert(u); + + if (u->started && !u->stopping) + return 0; + + /* If u->stopping is set, the user is marked for removal and service stop-jobs are queued. We have to clear + * that flag before queueing the start-jobs again. If they succeed, the user object can be re-used just fine + * (pid1 takes care of job-ordering and proper restart), but if they fail, we want to force another user_stop() + * so possibly pending units are stopped. */ + u->stopping = false; + + if (!u->started) + log_debug("Starting services for new user %s.", u->name); + + /* Save the user data so far, because pam_systemd will read the XDG_RUNTIME_DIR out of it while starting up + * systemd --user. We need to do user_save_internal() because we have not "officially" started yet. */ + user_save_internal(u); + + /* Start user@UID.service */ + user_start_service(u); + + if (!u->started) { + if (!dual_timestamp_is_set(&u->timestamp)) + dual_timestamp_get(&u->timestamp); + user_send_signal(u, true); + u->started = true; + } + + /* Save new user data */ + user_save(u); + + return 0; +} + +static void user_stop_service(User *u) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(u); + assert(u->service); + + /* The reverse of user_start_service(). Note that we only stop user@UID.service here, and let StopWhenUnneeded= + * deal with the slice and the user-runtime-dir@.service instance. */ + + u->service_job = mfree(u->service_job); + + r = manager_stop_unit(u->manager, u->service, &error, &u->service_job); + if (r < 0) + log_warning_errno(r, "Failed to stop user service '%s', ignoring: %s", u->service, bus_error_message(&error, r)); +} + +int user_stop(User *u, bool force) { + Session *s; + int r = 0; + assert(u); + + /* This is called whenever we begin with tearing down a user record. It's called in two cases: explicit API + * request to do so via the bus (in which case 'force' is true) and automatically due to GC, if there's no + * session left pinning it (in which case 'force' is false). Note that this just initiates tearing down of the + * user, the User object will remain in memory until user_finalize() is called, see below. */ + + if (!u->started) + return 0; + + if (u->stopping) { /* Stop jobs have already been queued */ + user_save(u); + return 0; + } + + LIST_FOREACH(sessions_by_user, s, u->sessions) { + int k; + + k = session_stop(s, force); + if (k < 0) + r = k; + } + + user_stop_service(u); + + u->stopping = true; + + user_save(u); + + return r; +} + +int user_finalize(User *u) { + Session *s; + int r = 0, k; + + assert(u); + + /* Called when the user is really ready to be freed, i.e. when all unit stop jobs and suchlike for it are + * done. This is called as a result of an earlier user_done() when all jobs are completed. */ + + if (u->started) + log_debug("User %s logged out.", u->name); + + LIST_FOREACH(sessions_by_user, s, u->sessions) { + k = session_finalize(s); + if (k < 0) + r = k; + } + + /* Clean SysV + POSIX IPC objects, but only if this is not a system user. Background: in many setups cronjobs + * are run in full PAM and thus logind sessions, even if the code run doesn't belong to actual users but to + * system components. Since enable RemoveIPC= globally for all users, we need to be a bit careful with such + * cases, as we shouldn't accidentally remove a system service's IPC objects while it is running, just because + * a cronjob running as the same user just finished. Hence: exclude system users generally from IPC clean-up, + * and do it only for normal users. */ + if (u->manager->remove_ipc && !uid_is_system(u->uid)) { + k = clean_ipc_by_uid(u->uid); + if (k < 0) + r = k; + } + + (void) unlink(u->state_file); + user_add_to_gc_queue(u); + + if (u->started) { + user_send_signal(u, false); + u->started = false; + } + + return r; +} + +int user_get_idle_hint(User *u, dual_timestamp *t) { + Session *s; + bool idle_hint = true; + dual_timestamp ts = DUAL_TIMESTAMP_NULL; + + assert(u); + + LIST_FOREACH(sessions_by_user, s, u->sessions) { + dual_timestamp k; + int ih; + + ih = session_get_idle_hint(s, &k); + if (ih < 0) + return ih; + + if (!ih) { + if (!idle_hint) { + if (k.monotonic < ts.monotonic) + ts = k; + } else { + idle_hint = false; + ts = k; + } + } else if (idle_hint) { + + if (k.monotonic > ts.monotonic) + ts = k; + } + } + + if (t) + *t = ts; + + return idle_hint; +} + +int user_check_linger_file(User *u) { + _cleanup_free_ char *cc = NULL; + char *p = NULL; + + cc = cescape(u->name); + if (!cc) + return -ENOMEM; + + p = strjoina("/var/lib/systemd/linger/", cc); + if (access(p, F_OK) < 0) { + if (errno != ENOENT) + return -errno; + + return false; + } + + return true; +} + +static bool user_unit_active(User *u) { + const char *i; + int r; + + assert(u->service); + assert(u->runtime_dir_service); + assert(u->slice); + + FOREACH_STRING(i, u->service, u->runtime_dir_service, u->slice) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = manager_unit_is_active(u->manager, i, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring: %s", u->service, bus_error_message(&error, r)); + if (r != 0) + return true; + } + + return false; +} + +bool user_may_gc(User *u, bool drop_not_started) { + int r; + + assert(u); + + if (drop_not_started && !u->started) + return true; + + if (u->sessions) + return false; + + if (u->last_session_timestamp != USEC_INFINITY) { + /* All sessions have been closed. Let's see if we shall leave the user record around for a bit */ + + if (u->manager->user_stop_delay == USEC_INFINITY) + return false; /* Leave it around forever! */ + if (u->manager->user_stop_delay > 0 && + now(CLOCK_MONOTONIC) < usec_add(u->last_session_timestamp, u->manager->user_stop_delay)) + return false; /* Leave it around for a bit longer. */ + } + + /* Is this a user that shall stay around forever ("linger")? Before we say "no" to GC'ing for lingering users, let's check + * if any of the three units that we maintain for this user is still around. If none of them is, + * there's no need to keep this user around even if lingering is enabled. */ + if (user_check_linger_file(u) > 0 && user_unit_active(u)) + return false; + + /* Check if our job is still pending */ + if (u->service_job) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = manager_job_is_active(u->manager, u->service_job, &error); + if (r < 0) + log_debug_errno(r, "Failed to determine whether job '%s' is pending, ignoring: %s", u->service_job, bus_error_message(&error, r)); + if (r != 0) + return false; + } + + /* Note that we don't care if the three units we manage for each user object are up or not, as we are managing + * their state rather than tracking it. */ + + return true; +} + +void user_add_to_gc_queue(User *u) { + assert(u); + + if (u->in_gc_queue) + return; + + LIST_PREPEND(gc_queue, u->manager->user_gc_queue, u); + u->in_gc_queue = true; +} + +UserState user_get_state(User *u) { + Session *i; + + assert(u); + + if (u->stopping) + return USER_CLOSING; + + if (!u->started || u->service_job) + return USER_OPENING; + + if (u->sessions) { + bool all_closing = true; + + LIST_FOREACH(sessions_by_user, i, u->sessions) { + SessionState state; + + state = session_get_state(i); + if (state == SESSION_ACTIVE) + return USER_ACTIVE; + if (state != SESSION_CLOSING) + all_closing = false; + } + + return all_closing ? USER_CLOSING : USER_ONLINE; + } + + if (user_check_linger_file(u) > 0 && user_unit_active(u)) + return USER_LINGERING; + + return USER_CLOSING; +} + +int user_kill(User *u, int signo) { + assert(u); + + return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL); +} + +static bool elect_display_filter(Session *s) { + /* Return true if the session is a candidate for the user’s ‘primary session’ or ‘display’. */ + assert(s); + + return IN_SET(s->class, SESSION_USER, SESSION_GREETER) && s->started && !s->stopping; +} + +static int elect_display_compare(Session *s1, Session *s2) { + /* Indexed by SessionType. Lower numbers mean more preferred. */ + static const int type_ranks[_SESSION_TYPE_MAX] = { + [SESSION_UNSPECIFIED] = 0, + [SESSION_TTY] = -2, + [SESSION_X11] = -3, + [SESSION_WAYLAND] = -3, + [SESSION_MIR] = -3, + [SESSION_WEB] = -1, + }; + + /* Calculate the partial order relationship between s1 and s2, + * returning < 0 if s1 is preferred as the user’s ‘primary session’, + * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2 + * is preferred. + * + * s1 or s2 may be NULL. */ + if (!s1 && !s2) + return 0; + + if ((s1 == NULL) != (s2 == NULL)) + return (s1 == NULL) - (s2 == NULL); + + if (s1->stopping != s2->stopping) + return s1->stopping - s2->stopping; + + if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER)) + return (s1->class != SESSION_USER) - (s2->class != SESSION_USER); + + if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID)) + return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID); + + if (s1->type != s2->type) + return type_ranks[s1->type] - type_ranks[s2->type]; + + return 0; +} + +void user_elect_display(User *u) { + Session *s; + + assert(u); + + /* This elects a primary session for each user, which we call the "display". We try to keep the assignment + * stable, but we "upgrade" to better choices. */ + log_debug("Electing new display for user %s", u->name); + + LIST_FOREACH(sessions_by_user, s, u->sessions) { + if (!elect_display_filter(s)) { + log_debug("Ignoring session %s", s->id); + continue; + } + + if (elect_display_compare(s, u->display) < 0) { + log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-"); + u->display = s; + } + } +} + +static int user_stop_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) { + User *u = userdata; + + assert(u); + user_add_to_gc_queue(u); + + return 0; +} + +void user_update_last_session_timer(User *u) { + int r; + + assert(u); + + if (u->sessions) { + /* There are sessions, turn off the timer */ + u->last_session_timestamp = USEC_INFINITY; + u->timer_event_source = sd_event_source_unref(u->timer_event_source); + return; + } + + if (u->last_session_timestamp != USEC_INFINITY) + return; /* Timer already started */ + + u->last_session_timestamp = now(CLOCK_MONOTONIC); + + assert(!u->timer_event_source); + + if (IN_SET(u->manager->user_stop_delay, 0, USEC_INFINITY)) + return; + + if (sd_event_get_state(u->manager->event) == SD_EVENT_FINISHED) { + log_debug("Not allocating user stop timeout, since we are already exiting."); + return; + } + + r = sd_event_add_time(u->manager->event, + &u->timer_event_source, + CLOCK_MONOTONIC, + usec_add(u->last_session_timestamp, u->manager->user_stop_delay), 0, + user_stop_timeout_callback, u); + if (r < 0) + log_warning_errno(r, "Failed to enqueue user stop event source, ignoring: %m"); + + if (DEBUG_LOGGING) { + char s[FORMAT_TIMESPAN_MAX]; + + log_debug("Last session of user '%s' logged out, terminating user context in %s.", + u->name, + format_timespan(s, sizeof(s), u->manager->user_stop_delay, USEC_PER_MSEC)); + } +} + +static const char* const user_state_table[_USER_STATE_MAX] = { + [USER_OFFLINE] = "offline", + [USER_OPENING] = "opening", + [USER_LINGERING] = "lingering", + [USER_ONLINE] = "online", + [USER_ACTIVE] = "active", + [USER_CLOSING] = "closing" +}; + +DEFINE_STRING_TABLE_LOOKUP(user_state, UserState); + +int config_parse_tmpfs_size( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint64_t *sz = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* First, try to parse as percentage */ + r = parse_permille(rvalue); + if (r > 0 && r < 1000) + *sz = physical_memory_scale(r, 1000U); + else { + uint64_t k; + + /* If the passed argument was not a percentage, or out of range, parse as byte size */ + + r = parse_size(rvalue, 1024, &k); + if (r >= 0 && (k <= 0 || (uint64_t) (size_t) k != k)) + r = -ERANGE; + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue); + return 0; + } + + *sz = PAGE_ALIGN((size_t) k); + } + + return 0; +} + +int config_parse_compat_user_tasks_max( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + assert(filename); + assert(lvalue); + assert(rvalue); + + log_syntax(unit, LOG_NOTICE, filename, line, 0, + "Support for option %s= has been removed.", + lvalue); + log_info("Hint: try creating /etc/systemd/system/user-.slice.d/50-limits.conf with:\n" + " [Slice]\n" + " TasksMax=%s", + rvalue); + return 0; +} diff --git a/src/login/logind-user.h b/src/login/logind-user.h new file mode 100644 index 00000000..4bd65d83 --- /dev/null +++ b/src/login/logind-user.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct User User; + +#include "conf-parser.h" +#include "list.h" +#include "logind.h" + +typedef enum UserState { + USER_OFFLINE, /* Not logged in at all */ + USER_OPENING, /* Is logging in */ + USER_LINGERING, /* Lingering has been enabled by the admin for this user */ + USER_ONLINE, /* User logged in */ + USER_ACTIVE, /* User logged in and has a session in the fg */ + USER_CLOSING, /* User logged out, but processes still remain and lingering is not enabled */ + _USER_STATE_MAX, + _USER_STATE_INVALID = -1 +} UserState; + +struct User { + Manager *manager; + uid_t uid; + gid_t gid; + char *name; + char *home; + char *state_file; + char *runtime_path; + + char *slice; /* user-UID.slice */ + char *service; /* user@UID.service */ + char *runtime_dir_service; /* user-runtime-dir@UID.service */ + + char *service_job; + + Session *display; + + dual_timestamp timestamp; /* When this User object was 'started' the first time */ + usec_t last_session_timestamp; /* When the number of sessions of this user went from 1 to 0 the last time */ + + /* Set up when the last session of the user logs out */ + sd_event_source *timer_event_source; + + bool in_gc_queue:1; + + bool started:1; /* Whenever the user being started, has been started or is being stopped again. */ + bool stopping:1; /* Whenever the user is being stopped or has been stopped. */ + + LIST_HEAD(Session, sessions); + LIST_FIELDS(User, gc_queue); +}; + +int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name, const char *home); +User *user_free(User *u); + +DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free); + +bool user_may_gc(User *u, bool drop_not_started); +void user_add_to_gc_queue(User *u); +int user_start(User *u); +int user_stop(User *u, bool force); +int user_finalize(User *u); +UserState user_get_state(User *u); +int user_get_idle_hint(User *u, dual_timestamp *t); +int user_save(User *u); +int user_load(User *u); +int user_kill(User *u, int signo); +int user_check_linger_file(User *u); +void user_elect_display(User *u); +void user_update_last_session_timer(User *u); + +const char* user_state_to_string(UserState s) _const_; +UserState user_state_from_string(const char *s) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_compat_user_tasks_max); diff --git a/src/login/logind-utmp.c b/src/login/logind-utmp.c new file mode 100644 index 00000000..d2a58902 --- /dev/null +++ b/src/login/logind-utmp.c @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "audit-util.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-util.h" +#include "format-util.h" +#include "logind.h" +#include "path-util.h" +#include "special.h" +#include "strv.h" +#include "unit-name.h" +#include "user-util.h" +#include "utmp-wtmp.h" + +_const_ static usec_t when_wall(usec_t n, usec_t elapse) { + + usec_t left; + unsigned i; + static const int wall_timers[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 25, 40, 55, 70, 100, 130, 150, 180, + }; + + /* If the time is already passed, then don't announce */ + if (n >= elapse) + return 0; + + left = elapse - n; + + for (i = 1; i < ELEMENTSOF(wall_timers); i++) + if (wall_timers[i] * USEC_PER_MINUTE >= left) + return left - wall_timers[i-1] * USEC_PER_MINUTE; + + return left % USEC_PER_HOUR; +} + +bool logind_wall_tty_filter(const char *tty, void *userdata) { + Manager *m = userdata; + const char *p; + + assert(m); + + if (!m->scheduled_shutdown_tty) + return true; + + p = path_startswith(tty, "/dev/"); + if (!p) + return true; + + return !streq(p, m->scheduled_shutdown_tty); +} + +static int warn_wall(Manager *m, usec_t n) { + char date[FORMAT_TIMESTAMP_MAX] = {}; + _cleanup_free_ char *l = NULL, *username = NULL; + usec_t left; + int r; + + assert(m); + + if (!m->enable_wall_messages) + return 0; + + left = m->scheduled_shutdown_timeout > n; + + r = asprintf(&l, "%s%sThe system is going down for %s %s%s!", + strempty(m->wall_message), + isempty(m->wall_message) ? "" : "\n", + m->scheduled_shutdown_type, + left ? "at " : "NOW", + left ? format_timestamp(date, sizeof(date), m->scheduled_shutdown_timeout) : ""); + if (r < 0) { + log_oom(); + return 0; + } + + username = uid_to_name(m->scheduled_shutdown_uid); + utmp_wall(l, username, m->scheduled_shutdown_tty, logind_wall_tty_filter, m); + + return 1; +} + +static int wall_message_timeout_handler( + sd_event_source *s, + uint64_t usec, + void *userdata) { + + Manager *m = userdata; + usec_t n, next; + int r; + + assert(m); + assert(s == m->wall_message_timeout_source); + + n = now(CLOCK_REALTIME); + + r = warn_wall(m, n); + if (r == 0) + return 0; + + next = when_wall(n, m->scheduled_shutdown_timeout); + if (next > 0) { + r = sd_event_source_set_time(s, n + next); + if (r < 0) + return log_error_errno(r, "sd_event_source_set_time() failed. %m"); + + r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT); + if (r < 0) + return log_error_errno(r, "sd_event_source_set_enabled() failed. %m"); + } + + return 0; +} + +int manager_setup_wall_message_timer(Manager *m) { + + usec_t n, elapse; + int r; + + assert(m); + + n = now(CLOCK_REALTIME); + elapse = m->scheduled_shutdown_timeout; + + /* wall message handling */ + + if (isempty(m->scheduled_shutdown_type)) { + warn_wall(m, n); + return 0; + } + + if (elapse < n) + return 0; + + /* Warn immediately if less than 15 minutes are left */ + if (elapse - n < 15 * USEC_PER_MINUTE) { + r = warn_wall(m, n); + if (r == 0) + return 0; + } + + elapse = when_wall(n, elapse); + if (elapse == 0) + return 0; + + if (m->wall_message_timeout_source) { + r = sd_event_source_set_time(m->wall_message_timeout_source, n + elapse); + if (r < 0) + return log_error_errno(r, "sd_event_source_set_time() failed. %m"); + + r = sd_event_source_set_enabled(m->wall_message_timeout_source, SD_EVENT_ONESHOT); + if (r < 0) + return log_error_errno(r, "sd_event_source_set_enabled() failed. %m"); + } else { + r = sd_event_add_time(m->event, &m->wall_message_timeout_source, + CLOCK_REALTIME, n + elapse, 0, wall_message_timeout_handler, m); + if (r < 0) + return log_error_errno(r, "sd_event_add_time() failed. %m"); + } + + return 0; +} diff --git a/src/login/logind.c b/src/login/logind.c new file mode 100644 index 00000000..8f3708d2 --- /dev/null +++ b/src/login/logind.c @@ -0,0 +1,1244 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-device.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-polkit.h" +#include "cgroup-util.h" +#include "def.h" +#include "device-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "logind-dbus.h" +#include "logind-seat-dbus.h" +#include "logind-session-dbus.h" +#include "logind-user-dbus.h" +#include "logind.h" +#include "main-func.h" +#include "parse-util.h" +#include "process-util.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "udev-util.h" + +static Manager* manager_unref(Manager *m); +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref); + +static int manager_new(Manager **ret) { + _cleanup_(manager_unrefp) Manager *m = NULL; + int r; + + assert(ret); + + m = new(Manager, 1); + if (!m) + return -ENOMEM; + + *m = (Manager) { + .console_active_fd = -1, + .reserve_vt_fd = -1, + .idle_action_not_before_usec = now(CLOCK_MONOTONIC), + }; + + m->devices = hashmap_new(&string_hash_ops); + m->seats = hashmap_new(&string_hash_ops); + m->sessions = hashmap_new(&string_hash_ops); + m->sessions_by_leader = hashmap_new(NULL); + m->users = hashmap_new(NULL); + m->inhibitors = hashmap_new(&string_hash_ops); + m->buttons = hashmap_new(&string_hash_ops); + + m->user_units = hashmap_new(&string_hash_ops); + m->session_units = hashmap_new(&string_hash_ops); + + if (!m->devices || !m->seats || !m->sessions || !m->sessions_by_leader || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units) + return -ENOMEM; + + r = sd_event_default(&m->event); + if (r < 0) + return r; + + r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); + if (r < 0) + return r; + + r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); + if (r < 0) + return r; + + (void) sd_event_set_watchdog(m->event, true); + + manager_reset_config(m); + + *ret = TAKE_PTR(m); + return 0; +} + +static Manager* manager_unref(Manager *m) { + Session *session; + User *u; + Device *d; + Seat *s; + Inhibitor *i; + Button *b; + + if (!m) + return NULL; + + while ((session = hashmap_first(m->sessions))) + session_free(session); + + while ((u = hashmap_first(m->users))) + user_free(u); + + while ((d = hashmap_first(m->devices))) + device_free(d); + + while ((s = hashmap_first(m->seats))) + seat_free(s); + + while ((i = hashmap_first(m->inhibitors))) + inhibitor_free(i); + + while ((b = hashmap_first(m->buttons))) + button_free(b); + + hashmap_free(m->devices); + hashmap_free(m->seats); + hashmap_free(m->sessions); + hashmap_free(m->sessions_by_leader); + hashmap_free(m->users); + hashmap_free(m->inhibitors); + hashmap_free(m->buttons); + hashmap_free(m->brightness_writers); + + hashmap_free(m->user_units); + hashmap_free(m->session_units); + + sd_event_source_unref(m->idle_action_event_source); + sd_event_source_unref(m->inhibit_timeout_source); + sd_event_source_unref(m->scheduled_shutdown_timeout_source); + sd_event_source_unref(m->nologin_timeout_source); + sd_event_source_unref(m->wall_message_timeout_source); + + sd_event_source_unref(m->console_active_event_source); + sd_event_source_unref(m->lid_switch_ignore_event_source); + +#if ENABLE_UTMP + sd_event_source_unref(m->utmp_event_source); +#endif + + safe_close(m->console_active_fd); + + sd_device_monitor_unref(m->device_seat_monitor); + sd_device_monitor_unref(m->device_monitor); + sd_device_monitor_unref(m->device_vcsa_monitor); + sd_device_monitor_unref(m->device_button_monitor); + + if (m->unlink_nologin) + (void) unlink_or_warn("/run/nologin"); + + bus_verify_polkit_async_registry_free(m->polkit_registry); + + sd_bus_flush_close_unref(m->bus); + sd_event_unref(m->event); + + safe_close(m->reserve_vt_fd); + + strv_free(m->kill_only_users); + strv_free(m->kill_exclude_users); + + free(m->scheduled_shutdown_type); + free(m->scheduled_shutdown_tty); + free(m->wall_message); + free(m->action_job); + + return mfree(m); +} + +static int manager_enumerate_devices(Manager *m) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *d; + int r; + + assert(m); + + /* Loads devices from udev and creates seats for them as + * necessary */ + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_tag(e, "master-of-seat"); + if (r < 0) + return r; + + FOREACH_DEVICE(e, d) { + int k; + + k = manager_process_seat_device(m, d); + if (k < 0) + r = k; + } + + return r; +} + +static int manager_enumerate_buttons(Manager *m) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *d; + int r; + + assert(m); + + /* Loads buttons from udev */ + + if (manager_all_buttons_ignored(m)) + return 0; + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_subsystem(e, "input", true); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_tag(e, "power-switch"); + if (r < 0) + return r; + + FOREACH_DEVICE(e, d) { + int k; + + k = manager_process_button_device(m, d); + if (k < 0) + r = k; + } + + return r; +} + +static int manager_enumerate_seats(Manager *m) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r = 0; + + assert(m); + + /* This loads data about seats stored on disk, but does not + * actually create any seats. Removes data of seats that no + * longer exist. */ + + d = opendir("/run/systemd/seats"); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open /run/systemd/seats: %m"); + } + + FOREACH_DIRENT(de, d, return -errno) { + Seat *s; + int k; + + if (!dirent_is_file(de)) + continue; + + s = hashmap_get(m->seats, de->d_name); + if (!s) { + if (unlinkat(dirfd(d), de->d_name, 0) < 0) + log_warning("Failed to remove /run/systemd/seats/%s: %m", + de->d_name); + continue; + } + + k = seat_load(s); + if (k < 0) + r = k; + } + + return r; +} + +static int manager_enumerate_linger_users(Manager *m) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r = 0; + + assert(m); + + d = opendir("/var/lib/systemd/linger"); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open /var/lib/systemd/linger/: %m"); + } + + FOREACH_DIRENT(de, d, return -errno) { + int k; + + dirent_ensure_type(d, de); + if (!dirent_is_file(de)) + continue; + + k = manager_add_user_by_name(m, de->d_name, NULL); + if (k < 0) + r = log_warning_errno(k, "Couldn't add lingering user %s, ignoring: %m", de->d_name); + } + + return r; +} + +static int manager_enumerate_users(Manager *m) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r, k; + + assert(m); + + /* Add lingering users */ + r = manager_enumerate_linger_users(m); + + /* Read in user data stored on disk */ + d = opendir("/run/systemd/users"); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open /run/systemd/users: %m"); + } + + FOREACH_DIRENT(de, d, return -errno) { + User *u; + + if (!dirent_is_file(de)) + continue; + + k = manager_add_user_by_name(m, de->d_name, &u); + if (k < 0) { + r = log_warning_errno(k, "Failed to add user by file name %s, ignoring: %m", de->d_name); + continue; + } + + user_add_to_gc_queue(u); + + k = user_load(u); + if (k < 0) + r = k; + } + + return r; +} + +static int parse_fdname(const char *fdname, char **session_id, dev_t *dev) { + _cleanup_strv_free_ char **parts = NULL; + _cleanup_free_ char *id = NULL; + unsigned major, minor; + int r; + + parts = strv_split(fdname, "-"); + if (!parts) + return -ENOMEM; + if (strv_length(parts) != 5) + return -EINVAL; + + if (!streq(parts[0], "session")) + return -EINVAL; + + id = strdup(parts[1]); + if (!id) + return -ENOMEM; + + if (!streq(parts[2], "device")) + return -EINVAL; + + r = safe_atou(parts[3], &major); + if (r < 0) + return r; + r = safe_atou(parts[4], &minor); + if (r < 0) + return r; + + *dev = makedev(major, minor); + *session_id = TAKE_PTR(id); + + return 0; +} + +static int deliver_fd(Manager *m, const char *fdname, int fd) { + _cleanup_free_ char *id = NULL; + SessionDevice *sd; + struct stat st; + Session *s; + dev_t dev; + int r; + + assert(m); + assert(fd >= 0); + + r = parse_fdname(fdname, &id, &dev); + if (r < 0) + return log_debug_errno(r, "Failed to parse fd name %s: %m", fdname); + + s = hashmap_get(m->sessions, id); + if (!s) + /* If the session doesn't exist anymore, the associated session device attached to this fd + * doesn't either. Let's simply close this fd. */ + return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Failed to attach fd for unknown session: %s", id); + + if (fstat(fd, &st) < 0) + /* The device is allowed to go away at a random point, in which case fstat() failing is + * expected. */ + return log_debug_errno(errno, "Failed to stat device fd for session %s: %m", id); + + if (!S_ISCHR(st.st_mode) || st.st_rdev != dev) + return log_debug_errno(SYNTHETIC_ERRNO(ENODEV), "Device fd doesn't point to the expected character device node"); + + sd = hashmap_get(s->devices, &dev); + if (!sd) + /* Weird, we got an fd for a session device which wasn't recorded in the session state + * file... */ + return log_warning_errno(SYNTHETIC_ERRNO(ENODEV), "Got fd for missing session device [%u:%u] in session %s", + major(dev), minor(dev), s->id); + + log_debug("Attaching fd to session device [%u:%u] for session %s", + major(dev), minor(dev), s->id); + + session_device_attach_fd(sd, fd, s->was_active); + return 0; +} + +static int manager_attach_fds(Manager *m) { + _cleanup_strv_free_ char **fdnames = NULL; + int n; + + /* Upon restart, PID1 will send us back all fds of session devices that we previously opened. Each + * file descriptor is associated with a given session. The session ids are passed through FDNAMES. */ + + n = sd_listen_fds_with_names(true, &fdnames); + if (n < 0) + return log_warning_errno(n, "Failed to acquire passed fd list: %m"); + if (n == 0) + return 0; + + for (int i = 0; i < n; i++) { + int fd = SD_LISTEN_FDS_START + i; + + if (deliver_fd(m, fdnames[i], fd) >= 0) + continue; + + /* Hmm, we couldn't deliver the fd to any session device object? If so, let's close the fd */ + safe_close(fd); + + /* Remove from fdstore as well */ + (void) sd_notifyf(false, + "FDSTOREREMOVE=1\n" + "FDNAME=%s", fdnames[i]); + } + + return 0; +} + +static int manager_enumerate_sessions(Manager *m) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r = 0, k; + + assert(m); + + /* Read in session data stored on disk */ + d = opendir("/run/systemd/sessions"); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open /run/systemd/sessions: %m"); + } + + FOREACH_DIRENT(de, d, return -errno) { + struct Session *s; + + if (!dirent_is_file(de)) + continue; + + k = manager_add_session(m, de->d_name, &s); + if (k < 0) { + r = log_warning_errno(k, "Failed to add session by file name %s, ignoring: %m", de->d_name); + continue; + } + + session_add_to_gc_queue(s); + + k = session_load(s); + if (k < 0) + r = k; + } + + /* We might be restarted and PID1 could have sent us back the session device fds we previously + * saved. */ + (void) manager_attach_fds(m); + + return r; +} + +static int manager_enumerate_inhibitors(Manager *m) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r = 0; + + assert(m); + + d = opendir("/run/systemd/inhibit"); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open /run/systemd/inhibit: %m"); + } + + FOREACH_DIRENT(de, d, return -errno) { + int k; + Inhibitor *i; + + if (!dirent_is_file(de)) + continue; + + k = manager_add_inhibitor(m, de->d_name, &i); + if (k < 0) { + r = log_warning_errno(k, "Couldn't add inhibitor %s, ignoring: %m", de->d_name); + continue; + } + + k = inhibitor_load(i); + if (k < 0) + r = k; + } + + return r; +} + +static int manager_dispatch_seat_udev(sd_device_monitor *monitor, sd_device *device, void *userdata) { + Manager *m = userdata; + + assert(m); + assert(device); + + manager_process_seat_device(m, device); + return 0; +} + +static int manager_dispatch_device_udev(sd_device_monitor *monitor, sd_device *device, void *userdata) { + Manager *m = userdata; + + assert(m); + assert(device); + + manager_process_seat_device(m, device); + return 0; +} + +static int manager_dispatch_vcsa_udev(sd_device_monitor *monitor, sd_device *device, void *userdata) { + Manager *m = userdata; + const char *name; + + assert(m); + assert(device); + + /* Whenever a VCSA device is removed try to reallocate our + * VTs, to make sure our auto VTs never go away. */ + + if (sd_device_get_sysname(device, &name) >= 0 && + startswith(name, "vcsa") && + device_for_action(device, DEVICE_ACTION_REMOVE)) + seat_preallocate_vts(m->seat0); + + return 0; +} + +static int manager_dispatch_button_udev(sd_device_monitor *monitor, sd_device *device, void *userdata) { + Manager *m = userdata; + + assert(m); + assert(device); + + manager_process_button_device(m, device); + return 0; +} + +static int manager_dispatch_console(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + + assert(m); + assert(m->seat0); + assert(m->console_active_fd == fd); + + seat_read_active_vt(m->seat0); + return 0; +} + +static int manager_reserve_vt(Manager *m) { + _cleanup_free_ char *p = NULL; + + assert(m); + + if (m->reserve_vt <= 0) + return 0; + + if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0) + return log_oom(); + + m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (m->reserve_vt_fd < 0) { + + /* Don't complain on VT-less systems */ + if (errno != ENOENT) + log_warning_errno(errno, "Failed to pin reserved VT: %m"); + return -errno; + } + + return 0; +} + +static int manager_connect_bus(Manager *m) { + int r; + + assert(m); + assert(!m->bus); + + r = sd_bus_default_system(&m->bus); + if (r < 0) + return log_error_errno(r, "Failed to connect to system bus: %m"); + + r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m); + if (r < 0) + return log_error_errno(r, "Failed to add manager object vtable: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to add seat object vtable: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add seat enumerator: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to add session object vtable: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add session enumerator: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to add user object vtable: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add user enumerator: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "JobRemoved", + match_job_removed, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to request match for JobRemoved: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "UnitRemoved", + match_unit_removed, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to request match for UnitRemoved: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.systemd1", + NULL, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + match_properties_changed, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to request match for PropertiesChanged: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Reloading", + match_reloading, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to request match for Reloading: %m"); + + r = sd_bus_call_method_async( + m->bus, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Subscribe", + NULL, NULL, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to enable subscription: %m"); + + r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.login1", 0, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + r = sd_bus_attach_event(m->bus, m->event, SD_EVENT_PRIORITY_NORMAL); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + return 0; +} + +static int manager_vt_switch(sd_event_source *src, const struct signalfd_siginfo *si, void *data) { + Manager *m = data; + Session *active, *iter; + + /* + * We got a VT-switch signal and we have to acknowledge it immediately. + * Preferably, we'd just use m->seat0->active->vtfd, but unfortunately, + * old user-space might run multiple sessions on a single VT, *sigh*. + * Therefore, we have to iterate all sessions and find one with a vtfd + * on the requested VT. + * As only VTs with active controllers have VT_PROCESS set, our current + * notion of the active VT might be wrong (for instance if the switch + * happens while we setup VT_PROCESS). Therefore, read the current VT + * first and then use s->active->vtnr as reference. Note that this is + * not racy, as no further VT-switch can happen as long as we're in + * synchronous VT_PROCESS mode. + */ + + assert(m->seat0); + seat_read_active_vt(m->seat0); + + active = m->seat0->active; + if (!active || active->vtnr < 1) { + _cleanup_close_ int fd = -1; + int r; + + /* We are requested to acknowledge the VT-switch signal by the kernel but + * there's no registered sessions for the current VT. Normally this + * shouldn't happen but something wrong might have happened when we tried + * to release the VT. Better be safe than sorry, and try to release the VT + * one more time otherwise the user will be locked with the current VT. */ + + log_warning("Received VT_PROCESS signal without a registered session, restoring VT."); + + /* At this point we only have the kernel mapping for referring to the + * current VT. */ + fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) { + log_warning_errno(fd, "Failed to open, ignoring: %m"); + return 0; + } + + r = vt_release(fd, true); + if (r < 0) + log_warning_errno(r, "Failed to release VT, ignoring: %m"); + + return 0; + } + + if (active->vtfd >= 0) { + session_leave_vt(active); + } else { + LIST_FOREACH(sessions_by_seat, iter, m->seat0->sessions) { + if (iter->vtnr == active->vtnr && iter->vtfd >= 0) { + session_leave_vt(iter); + break; + } + } + } + + return 0; +} + +static int manager_connect_console(Manager *m) { + int r; + + assert(m); + assert(m->console_active_fd < 0); + + /* On certain systems (such as S390, Xen, and containers) /dev/tty0 does not exist (as there is no VC), so + * don't fail if we can't open it. */ + + if (access("/dev/tty0", F_OK) < 0) + return 0; + + m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (m->console_active_fd < 0) { + + /* On some systems /dev/tty0 may exist even though /sys/class/tty/tty0 does not. These are broken, but + * common. Let's complain but continue anyway. */ + if (errno == ENOENT) { + log_warning_errno(errno, "System has /dev/tty0 but not /sys/class/tty/tty0/active which is broken, ignoring: %m"); + return 0; + } + + return log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m"); + } + + r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m); + if (r < 0) + return log_error_errno(r, "Failed to watch foreground console: %m"); + + /* + * SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used + * as VT-acquire signal. We ignore any acquire-events (yes, we still + * have to provide a valid signal-number for it!) and acknowledge all + * release events immediately. + */ + + if (SIGRTMIN + 1 > SIGRTMAX) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Not enough real-time signals available: %u-%u", + SIGRTMIN, SIGRTMAX); + + assert_se(ignore_signals(SIGRTMIN + 1, -1) >= 0); + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN, -1) >= 0); + + r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m); + if (r < 0) + return log_error_errno(r, "Failed to subscribe to signal: %m"); + + return 0; +} + +static int manager_connect_udev(Manager *m) { + int r; + + assert(m); + assert(!m->device_seat_monitor); + assert(!m->device_monitor); + assert(!m->device_vcsa_monitor); + assert(!m->device_button_monitor); + + r = sd_device_monitor_new(&m->device_seat_monitor); + if (r < 0) + return r; + + r = sd_device_monitor_filter_add_match_tag(m->device_seat_monitor, "master-of-seat"); + if (r < 0) + return r; + + r = sd_device_monitor_attach_event(m->device_seat_monitor, m->event); + if (r < 0) + return r; + + r = sd_device_monitor_start(m->device_seat_monitor, manager_dispatch_seat_udev, m); + if (r < 0) + return r; + + (void) sd_event_source_set_description(sd_device_monitor_get_event_source(m->device_seat_monitor), "logind-seat-monitor"); + + r = sd_device_monitor_new(&m->device_monitor); + if (r < 0) + return r; + + r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "input", NULL); + if (r < 0) + return r; + + r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "graphics", NULL); + if (r < 0) + return r; + + r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "drm", NULL); + if (r < 0) + return r; + + r = sd_device_monitor_attach_event(m->device_monitor, m->event); + if (r < 0) + return r; + + r = sd_device_monitor_start(m->device_monitor, manager_dispatch_device_udev, m); + if (r < 0) + return r; + + (void) sd_event_source_set_description(sd_device_monitor_get_event_source(m->device_monitor), "logind-device-monitor"); + + /* Don't watch keys if nobody cares */ + if (!manager_all_buttons_ignored(m)) { + r = sd_device_monitor_new(&m->device_button_monitor); + if (r < 0) + return r; + + r = sd_device_monitor_filter_add_match_tag(m->device_button_monitor, "power-switch"); + if (r < 0) + return r; + + r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_button_monitor, "input", NULL); + if (r < 0) + return r; + + r = sd_device_monitor_attach_event(m->device_button_monitor, m->event); + if (r < 0) + return r; + + r = sd_device_monitor_start(m->device_button_monitor, manager_dispatch_button_udev, m); + if (r < 0) + return r; + + (void) sd_event_source_set_description(sd_device_monitor_get_event_source(m->device_button_monitor), "logind-button-monitor"); + } + + /* Don't bother watching VCSA devices, if nobody cares */ + if (m->n_autovts > 0 && m->console_active_fd >= 0) { + + r = sd_device_monitor_new(&m->device_vcsa_monitor); + if (r < 0) + return r; + + r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_vcsa_monitor, "vc", NULL); + if (r < 0) + return r; + + r = sd_device_monitor_attach_event(m->device_vcsa_monitor, m->event); + if (r < 0) + return r; + + r = sd_device_monitor_start(m->device_vcsa_monitor, manager_dispatch_vcsa_udev, m); + if (r < 0) + return r; + + (void) sd_event_source_set_description(sd_device_monitor_get_event_source(m->device_vcsa_monitor), "logind-vcsa-monitor"); + } + + return 0; +} + +static void manager_gc(Manager *m, bool drop_not_started) { + Seat *seat; + Session *session; + User *user; + + assert(m); + + while ((seat = m->seat_gc_queue)) { + LIST_REMOVE(gc_queue, m->seat_gc_queue, seat); + seat->in_gc_queue = false; + + if (seat_may_gc(seat, drop_not_started)) { + seat_stop(seat, false); + seat_free(seat); + } + } + + while ((session = m->session_gc_queue)) { + LIST_REMOVE(gc_queue, m->session_gc_queue, session); + session->in_gc_queue = false; + + /* First, if we are not closing yet, initiate stopping */ + if (session_may_gc(session, drop_not_started) && + session_get_state(session) != SESSION_CLOSING) + (void) session_stop(session, false); + + /* Normally, this should make the session referenced + * again, if it doesn't then let's get rid of it + * immediately */ + if (session_may_gc(session, drop_not_started)) { + (void) session_finalize(session); + session_free(session); + } + } + + while ((user = m->user_gc_queue)) { + LIST_REMOVE(gc_queue, m->user_gc_queue, user); + user->in_gc_queue = false; + + /* First step: queue stop jobs */ + if (user_may_gc(user, drop_not_started)) + (void) user_stop(user, false); + + /* Second step: finalize user */ + if (user_may_gc(user, drop_not_started)) { + (void) user_finalize(user); + user_free(user); + } + } +} + +static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *userdata) { + Manager *m = userdata; + struct dual_timestamp since; + usec_t n, elapse; + int r; + + assert(m); + + if (m->idle_action == HANDLE_IGNORE || + m->idle_action_usec <= 0) + return 0; + + n = now(CLOCK_MONOTONIC); + + r = manager_get_idle_hint(m, &since); + if (r <= 0) + /* Not idle. Let's check if after a timeout it might be idle then. */ + elapse = n + m->idle_action_usec; + else { + /* Idle! Let's see if it's time to do something, or if + * we shall sleep for longer. */ + + if (n >= since.monotonic + m->idle_action_usec && + (m->idle_action_not_before_usec <= 0 || n >= m->idle_action_not_before_usec + m->idle_action_usec)) { + log_info("System idle. Doing %s operation.", handle_action_to_string(m->idle_action)); + + manager_handle_action(m, 0, m->idle_action, false, false); + m->idle_action_not_before_usec = n; + } + + elapse = MAX(since.monotonic, m->idle_action_not_before_usec) + m->idle_action_usec; + } + + if (!m->idle_action_event_source) { + + r = sd_event_add_time( + m->event, + &m->idle_action_event_source, + CLOCK_MONOTONIC, + elapse, USEC_PER_SEC*30, + manager_dispatch_idle_action, m); + if (r < 0) + return log_error_errno(r, "Failed to add idle event source: %m"); + + r = sd_event_source_set_priority(m->idle_action_event_source, SD_EVENT_PRIORITY_IDLE+10); + if (r < 0) + return log_error_errno(r, "Failed to set idle event source priority: %m"); + } else { + r = sd_event_source_set_time(m->idle_action_event_source, elapse); + if (r < 0) + return log_error_errno(r, "Failed to set idle event timer: %m"); + + r = sd_event_source_set_enabled(m->idle_action_event_source, SD_EVENT_ONESHOT); + if (r < 0) + return log_error_errno(r, "Failed to enable idle event timer: %m"); + } + + return 0; +} + +static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *m = userdata; + int r; + + manager_reset_config(m); + r = manager_parse_config_file(m); + if (r < 0) + log_warning_errno(r, "Failed to parse config file, using defaults: %m"); + else + log_info("Config file reloaded."); + + return 0; +} + +static int manager_startup(Manager *m) { + int r; + Seat *seat; + Session *session; + User *user; + Button *button; + Inhibitor *inhibitor; + Iterator i; + + assert(m); + + r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m); + if (r < 0) + return log_error_errno(r, "Failed to register SIGHUP handler: %m"); + + /* Connect to utmp */ + manager_connect_utmp(m); + + /* Connect to console */ + r = manager_connect_console(m); + if (r < 0) + return r; + + /* Connect to udev */ + r = manager_connect_udev(m); + if (r < 0) + return log_error_errno(r, "Failed to create udev watchers: %m"); + + /* Connect to the bus */ + r = manager_connect_bus(m); + if (r < 0) + return r; + + /* Instantiate magic seat 0 */ + r = manager_add_seat(m, "seat0", &m->seat0); + if (r < 0) + return log_error_errno(r, "Failed to add seat0: %m"); + + r = manager_set_lid_switch_ignore(m, 0 + m->holdoff_timeout_usec); + if (r < 0) + log_warning_errno(r, "Failed to set up lid switch ignore event source: %m"); + + /* Deserialize state */ + r = manager_enumerate_devices(m); + if (r < 0) + log_warning_errno(r, "Device enumeration failed: %m"); + + r = manager_enumerate_seats(m); + if (r < 0) + log_warning_errno(r, "Seat enumeration failed: %m"); + + r = manager_enumerate_users(m); + if (r < 0) + log_warning_errno(r, "User enumeration failed: %m"); + + r = manager_enumerate_sessions(m); + if (r < 0) + log_warning_errno(r, "Session enumeration failed: %m"); + + r = manager_enumerate_inhibitors(m); + if (r < 0) + log_warning_errno(r, "Inhibitor enumeration failed: %m"); + + r = manager_enumerate_buttons(m); + if (r < 0) + log_warning_errno(r, "Button enumeration failed: %m"); + + /* Remove stale objects before we start them */ + manager_gc(m, false); + + /* Reserve the special reserved VT */ + manager_reserve_vt(m); + + /* Read in utmp if it exists */ + manager_read_utmp(m); + + /* And start everything */ + HASHMAP_FOREACH(seat, m->seats, i) + (void) seat_start(seat); + + HASHMAP_FOREACH(user, m->users, i) + (void) user_start(user); + + HASHMAP_FOREACH(session, m->sessions, i) + (void) session_start(session, NULL, NULL); + + HASHMAP_FOREACH(inhibitor, m->inhibitors, i) { + (void) inhibitor_start(inhibitor); + + /* Let's see if the inhibitor is dead now, then remove it */ + if (inhibitor_is_orphan(inhibitor)) { + inhibitor_stop(inhibitor); + inhibitor_free(inhibitor); + } + } + + HASHMAP_FOREACH(button, m->buttons, i) + button_check_switches(button); + + manager_dispatch_idle_action(NULL, 0, m); + + return 0; +} + +static int manager_run(Manager *m) { + int r; + + assert(m); + + for (;;) { + r = sd_event_get_state(m->event); + if (r < 0) + return r; + if (r == SD_EVENT_FINISHED) + return 0; + + manager_gc(m, true); + + r = manager_dispatch_delayed(m, false); + if (r < 0) + return r; + if (r > 0) + continue; + + r = sd_event_run(m->event, (uint64_t) -1); + if (r < 0) + return r; + } +} + +static int run(int argc, char *argv[]) { + _cleanup_(manager_unrefp) Manager *m = NULL; + int r; + + log_set_facility(LOG_AUTH); + log_setup_service(); + + umask(0022); + + if (argc != 1) { + log_error("This program takes no arguments."); + return -EINVAL; + } + + r = mac_selinux_init(); + if (r < 0) + return log_error_errno(r, "Could not initialize labelling: %m"); + + /* Always create the directories people can create inotify watches in. Note that some applications might check + * for the existence of /run/systemd/seats/ to determine whether logind is available, so please always make + * sure these directories are created early on and unconditionally. */ + (void) mkdir_label("/run/systemd/seats", 0755); + (void) mkdir_label("/run/systemd/users", 0755); + (void) mkdir_label("/run/systemd/sessions", 0755); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGHUP, SIGTERM, SIGINT, SIGCHLD, -1) >= 0); + + r = manager_new(&m); + if (r < 0) + return log_error_errno(r, "Failed to allocate manager object: %m"); + + (void) manager_parse_config_file(m); + + r = manager_startup(m); + if (r < 0) + return log_error_errno(r, "Failed to fully start up daemon: %m"); + + log_debug("systemd-logind running as pid "PID_FMT, getpid_cached()); + (void) sd_notify(false, + "READY=1\n" + "STATUS=Processing requests..."); + + r = manager_run(m); + + log_debug("systemd-logind stopped as pid "PID_FMT, getpid_cached()); + (void) sd_notify(false, + "STOPPING=1\n" + "STATUS=Shutting down..."); + + return r; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in new file mode 100644 index 00000000..1029e29b --- /dev/null +++ b/src/login/logind.conf.in @@ -0,0 +1,37 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See logind.conf(5) for details. + +[Login] +#NAutoVTs=6 +#ReserveVT=6 +#KillUserProcesses=@KILL_USER_PROCESSES@ +#KillOnlyUsers= +#KillExcludeUsers=root +#InhibitDelayMaxSec=5 +#HandlePowerKey=poweroff +#HandleSuspendKey=suspend +#HandleHibernateKey=hibernate +#HandleLidSwitch=suspend +#HandleLidSwitchExternalPower=suspend +#HandleLidSwitchDocked=ignore +#PowerKeyIgnoreInhibited=no +#SuspendKeyIgnoreInhibited=no +#HibernateKeyIgnoreInhibited=no +#LidSwitchIgnoreInhibited=yes +#HoldoffTimeoutSec=30s +#IdleAction=ignore +#IdleActionSec=30min +#RuntimeDirectorySize=10% +#RemoveIPC=yes +#InhibitorsMax=8192 +#SessionsMax=8192 diff --git a/src/login/logind.h b/src/login/logind.h new file mode 100644 index 00000000..f0f8928e --- /dev/null +++ b/src/login/logind.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" +#include "sd-device.h" +#include "sd-event.h" + +#include "conf-parser.h" +#include "hashmap.h" +#include "list.h" +#include "set.h" +#include "time-util.h" + +typedef struct Manager Manager; + +#include "logind-action.h" +#include "logind-button.h" +#include "logind-device.h" +#include "logind-inhibit.h" + +struct Manager { + sd_event *event; + sd_bus *bus; + + Hashmap *devices; + Hashmap *seats; + Hashmap *sessions; + Hashmap *sessions_by_leader; + Hashmap *users; + Hashmap *inhibitors; + Hashmap *buttons; + Hashmap *brightness_writers; + + LIST_HEAD(Seat, seat_gc_queue); + LIST_HEAD(Session, session_gc_queue); + LIST_HEAD(User, user_gc_queue); + + sd_device_monitor *device_seat_monitor, *device_monitor, *device_vcsa_monitor, *device_button_monitor; + + sd_event_source *console_active_event_source; + +#if ENABLE_UTMP + sd_event_source *utmp_event_source; +#endif + + int console_active_fd; + + unsigned n_autovts; + + unsigned reserve_vt; + int reserve_vt_fd; + + Seat *seat0; + + char **kill_only_users, **kill_exclude_users; + bool kill_user_processes; + + unsigned long session_counter; + unsigned long inhibit_counter; + + Hashmap *session_units; + Hashmap *user_units; + + usec_t inhibit_delay_max; + usec_t user_stop_delay; + + /* If an action is currently being executed or is delayed, + * this is != 0 and encodes what is being done */ + InhibitWhat action_what; + + /* If a shutdown/suspend was delayed due to a inhibitor this + contains the unit name we are supposed to start after the + delay is over */ + const char *action_unit; + + /* If a shutdown/suspend is currently executed, then this is + * the job of it */ + char *action_job; + sd_event_source *inhibit_timeout_source; + + char *scheduled_shutdown_type; + usec_t scheduled_shutdown_timeout; + sd_event_source *scheduled_shutdown_timeout_source; + uid_t scheduled_shutdown_uid; + char *scheduled_shutdown_tty; + sd_event_source *nologin_timeout_source; + bool unlink_nologin; + + char *wall_message; + unsigned enable_wall_messages; + sd_event_source *wall_message_timeout_source; + + bool shutdown_dry_run; + + sd_event_source *idle_action_event_source; + usec_t idle_action_usec; + usec_t idle_action_not_before_usec; + HandleAction idle_action; + + HandleAction handle_power_key; + HandleAction handle_suspend_key; + HandleAction handle_hibernate_key; + HandleAction handle_lid_switch; + HandleAction handle_lid_switch_ep; + HandleAction handle_lid_switch_docked; + + bool power_key_ignore_inhibited; + bool suspend_key_ignore_inhibited; + bool hibernate_key_ignore_inhibited; + bool lid_switch_ignore_inhibited; + + bool remove_ipc; + + Hashmap *polkit_registry; + + usec_t holdoff_timeout_usec; + sd_event_source *lid_switch_ignore_event_source; + + uint64_t runtime_dir_size; + uint64_t sessions_max; + uint64_t inhibitors_max; +}; + +void manager_reset_config(Manager *m); +int manager_parse_config_file(Manager *m); + +int manager_add_device(Manager *m, const char *sysfs, bool master, Device **ret_device); +int manager_add_button(Manager *m, const char *name, Button **ret_button); +int manager_add_seat(Manager *m, const char *id, Seat **ret_seat); +int manager_add_session(Manager *m, const char *id, Session **ret_session); +int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, const char *home, User **ret_user); +int manager_add_user_by_name(Manager *m, const char *name, User **ret_user); +int manager_add_user_by_uid(Manager *m, uid_t uid, User **ret_user); +int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **ret_inhibitor); + +int manager_process_seat_device(Manager *m, sd_device *d); +int manager_process_button_device(Manager *m, sd_device *d); + +int manager_spawn_autovt(Manager *m, unsigned vtnr); + +bool manager_shall_kill(Manager *m, const char *user); + +int manager_get_idle_hint(Manager *m, dual_timestamp *t); + +int manager_get_user_by_pid(Manager *m, pid_t pid, User **user); +int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session); + +bool manager_is_lid_closed(Manager *m); +bool manager_is_docked_or_external_displays(Manager *m); +bool manager_is_on_external_power(void); +bool manager_all_buttons_ignored(Manager *m); + +int manager_read_utmp(Manager *m); +void manager_connect_utmp(Manager *m); +void manager_reconnect_utmp(Manager *m); + +extern const sd_bus_vtable manager_vtable[]; + +/* gperf lookup function */ +const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE length); + +int manager_set_lid_switch_ignore(Manager *m, usec_t until); + +CONFIG_PARSER_PROTOTYPE(config_parse_n_autovts); +CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs_size); + +int manager_setup_wall_message_timer(Manager *m); +bool logind_wall_tty_filter(const char *tty, void *userdata); diff --git a/src/login/meson.build b/src/login/meson.build new file mode 100644 index 00000000..0a7d3d54 --- /dev/null +++ b/src/login/meson.build @@ -0,0 +1,122 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +systemd_logind_sources = files(''' + logind.c + logind.h +'''.split()) + +logind_gperf_c = custom_target( + 'logind_gperf.c', + input : 'logind-gperf.gperf', + output : 'logind-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + +liblogind_core_sources = files(''' + logind-acl.h + logind-action.c + logind-action.h + logind-brightness.c + logind-brightness.h + logind-button.c + logind-button.h + logind-core.c + logind-dbus.c + logind-dbus.h + logind-device.c + logind-device.h + logind-inhibit.c + logind-inhibit.h + logind-seat-dbus.c + logind-seat-dbus.h + logind-seat.c + logind-seat.h + logind-session-dbus.c + logind-session-dbus.h + logind-session-device.c + logind-session-device.h + logind-session.c + logind-session.h + logind-user-dbus.c + logind-user-dbus.h + logind-user.c + logind-user.h + logind-utmp.c +'''.split()) + +liblogind_core_sources += [logind_gperf_c] + +logind_acl_c = files('logind-acl.c') +if conf.get('HAVE_ACL') == 1 + liblogind_core_sources += logind_acl_c +endif + +liblogind_core = static_library( + 'logind-core', + liblogind_core_sources, + include_directories : includes, + dependencies : [libacl]) + +loginctl_sources = files(''' + loginctl.c + sysfs-show.h + sysfs-show.c +'''.split()) + +user_runtime_dir_sources = files(''' + user-runtime-dir.c +'''.split()) + +pam_systemd_sym = 'src/login/pam_systemd.sym' +pam_systemd_c = files('pam_systemd.c') + +if conf.get('ENABLE_LOGIND') == 1 + logind_conf = configure_file( + input : 'logind.conf.in', + output : 'logind.conf', + configuration : substs) + install_data(logind_conf, + install_dir : pkgsysconfdir) + + install_data('org.freedesktop.login1.conf', + install_dir : dbuspolicydir) + install_data('org.freedesktop.login1.service', + install_dir : dbussystemservicedir) + install_data('org.freedesktop.login1.policy', + install_dir : polkitpolicydir) + + install_data('70-power-switch.rules', install_dir : udevrulesdir) + + seat_rules = configure_file( + input : '71-seat.rules.in', + output : '71-seat.rules', + configuration : substs) + install_data(seat_rules, + install_dir : udevrulesdir) + + custom_target( + '70-uaccess.rules', + input : '70-uaccess.rules.m4', + output: '70-uaccess.rules', + command : [meson_apply_m4, config_h, '@INPUT@'], + capture : true, + install : conf.get('HAVE_ACL') == 1, + install_dir : udevrulesdir) + + custom_target( + '73-seat-late.rules', + input : '73-seat-late.rules.m4', + output: '73-seat-late.rules', + command : [meson_apply_m4, config_h, '@INPUT@'], + capture : true, + install : true, + install_dir : udevrulesdir) + + custom_target( + 'systemd-user', + input : 'systemd-user.m4', + output: 'systemd-user', + command : [meson_apply_m4, config_h, '@INPUT@'], + capture : true, + install : pamconfdir != 'no', + install_dir : pamconfdir) +endif diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf new file mode 100644 index 00000000..124a2581 --- /dev/null +++ b/src/login/org.freedesktop.login1.conf @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/login/org.freedesktop.login1.policy b/src/login/org.freedesktop.login1.policy new file mode 100644 index 00000000..6dc79aa3 --- /dev/null +++ b/src/login/org.freedesktop.login1.policy @@ -0,0 +1,394 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Allow applications to inhibit system shutdown + Authentication is required for an application to inhibit system shutdown. + + no + yes + yes + + org.freedesktop.login1.inhibit-delay-shutdown org.freedesktop.login1.inhibit-block-sleep org.freedesktop.login1.inhibit-delay-sleep org.freedesktop.login1.inhibit-block-idle + + + + Allow applications to delay system shutdown + Authentication is required for an application to delay system shutdown. + + yes + yes + yes + + org.freedesktop.login1.inhibit-delay-sleep + + + + Allow applications to inhibit system sleep + Authentication is required for an application to inhibit system sleep. + + no + yes + yes + + org.freedesktop.login1.inhibit-delay-sleep org.freedesktop.login1.inhibit-block-idle + + + + Allow applications to delay system sleep + Authentication is required for an application to delay system sleep. + + yes + yes + yes + + + + + Allow applications to inhibit automatic system suspend + Authentication is required for an application to inhibit automatic system suspend. + + yes + yes + yes + + + + + Allow applications to inhibit system handling of the power key + Authentication is required for an application to inhibit system handling of the power key. + + no + yes + yes + + org.freedesktop.login1.inhibit-handle-suspend-key org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch + + + + Allow applications to inhibit system handling of the suspend key + Authentication is required for an application to inhibit system handling of the suspend key. + + no + yes + yes + + org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch + + + + Allow applications to inhibit system handling of the hibernate key + Authentication is required for an application to inhibit system handling of the hibernate key. + + no + yes + yes + + + + + Allow applications to inhibit system handling of the lid switch + Authentication is required for an application to inhibit system handling of the lid switch. + + no + yes + yes + + + + + Allow non-logged-in user to run programs + Explicit request is required to run programs as a non-logged-in user. + + yes + yes + yes + + + + + Allow non-logged-in users to run programs + Authentication is required to run programs as a non-logged-in user. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Allow attaching devices to seats + Authentication is required for attaching a device to a seat. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.flush-devices + + + + Flush device to seat attachments + Authentication is required for resetting how devices are attached to seats. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Power off the system + Authentication is required for powering off the system. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.set-wall-message + + + + Power off the system while other users are logged in + Authentication is required for powering off the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.power-off + + + + Power off the system while an application asked to inhibit it + Authentication is required for powering off the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.power-off + + + + Reboot the system + Authentication is required for rebooting the system. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.set-wall-message + + + + Reboot the system while other users are logged in + Authentication is required for rebooting the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.reboot + + + + Reboot the system while an application asked to inhibit it + Authentication is required for rebooting the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.reboot + + + + Halt the system + Authentication is required for halting the system. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.set-wall-message + + + + Halt the system while other users are logged in + Authentication is required for halting the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.halt + + + + Halt the system while an application asked to inhibit it + Authentication is required for halting the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.halt + + + + Suspend the system + Authentication is required for suspending the system. + + auth_admin_keep + auth_admin_keep + yes + + + + + Suspend the system while other users are logged in + Authentication is required for suspending the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.suspend + + + + Suspend the system while an application asked to inhibit it + Authentication is required for suspending the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.suspend + + + + Hibernate the system + Authentication is required for hibernating the system. + + auth_admin_keep + auth_admin_keep + yes + + + + + Hibernate the system while other users are logged in + Authentication is required for hibernating the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.hibernate + + + + Hibernate the system while an application asked to inhibit it + Authentication is required for hibernating the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.hibernate + + + + Manage active sessions, users and seats + Authentication is required for managing active sessions, users and seats. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Lock or unlock active sessions + Authentication is required to lock or unlock active sessions. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Set the reboot "reason" in the kernel + Authentication is required to set the reboot "reason" in the kernel. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.reboot + + + + Indicate to the firmware to boot to setup interface + Authentication is required to indicate to the firmware to boot to setup interface. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.reboot + + + + Indicate to the boot loader to boot to the boot loader menu + Authentication is required to indicate to the boot loader to boot to the boot loader menu. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.reboot + + + + Indicate to the boot loader to boot a specific entry + Authentication is required to indicate to the boot loader to boot into a specific boot loader entry. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.reboot + + + + Set a wall message + Authentication is required to set a wall message + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + diff --git a/src/login/org.freedesktop.login1.service b/src/login/org.freedesktop.login1.service new file mode 100644 index 00000000..68f1ed0f --- /dev/null +++ b/src/login/org.freedesktop.login1.service @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.login1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.login1.service diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c new file mode 100644 index 00000000..aa6e5ea7 --- /dev/null +++ b/src/login/pam_systemd.c @@ -0,0 +1,818 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "audit-util.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-internal.h" +#include "bus-util.h" +#include "cgroup-setup.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "hostname-util.h" +#include "login-util.h" +#include "macro.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "strv.h" +#include "terminal-util.h" + +#define LOGIN_SLOW_BUS_CALL_TIMEOUT_USEC (2*USEC_PER_MINUTE) + +static int parse_argv( + pam_handle_t *handle, + int argc, const char **argv, + const char **class, + const char **type, + const char **desktop, + bool *debug) { + + unsigned i; + + assert(argc >= 0); + assert(argc == 0 || argv); + + for (i = 0; i < (unsigned) argc; i++) { + const char *p; + + if ((p = startswith(argv[i], "class="))) { + if (class) + *class = p; + + } else if ((p = startswith(argv[i], "type="))) { + if (type) + *type = p; + + } else if ((p = startswith(argv[i], "desktop="))) { + if (desktop) + *desktop = p; + + } else if (streq(argv[i], "debug")) { + if (debug) + *debug = true; + + } else if ((p = startswith(argv[i], "debug="))) { + int k; + + k = parse_boolean(p); + if (k < 0) + pam_syslog(handle, LOG_WARNING, "Failed to parse debug= argument, ignoring: %s", p); + else if (debug) + *debug = k; + + } else + pam_syslog(handle, LOG_WARNING, "Unknown parameter '%s', ignoring", argv[i]); + } + + return 0; +} + +static int get_user_data( + pam_handle_t *handle, + const char **ret_username, + struct passwd **ret_pw) { + + const char *username = NULL; + struct passwd *pw = NULL; + int r; + + assert(handle); + assert(ret_username); + assert(ret_pw); + + r = pam_get_user(handle, &username, NULL); + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to get user name: %s", pam_strerror(handle, r)); + return r; + } + + if (isempty(username)) { + pam_syslog(handle, LOG_ERR, "User name not valid."); + return PAM_AUTH_ERR; + } + + pw = pam_modutil_getpwnam(handle, username); + if (!pw) { + pam_syslog(handle, LOG_ERR, "Failed to get user data."); + return PAM_USER_UNKNOWN; + } + + *ret_pw = pw; + *ret_username = username; + + return PAM_SUCCESS; +} + +static bool display_is_local(const char *display) { + assert(display); + + return + display[0] == ':' && + display[1] >= '0' && + display[1] <= '9'; +} + +static int socket_from_display(const char *display, char **path) { + size_t k; + char *f, *c; + + assert(display); + assert(path); + + if (!display_is_local(display)) + return -EINVAL; + + k = strspn(display+1, "0123456789"); + + f = new(char, STRLEN("/tmp/.X11-unix/X") + k + 1); + if (!f) + return -ENOMEM; + + c = stpcpy(f, "/tmp/.X11-unix/X"); + memcpy(c, display+1, k); + c[k] = 0; + + *path = f; + + return 0; +} + +static int get_seat_from_display(const char *display, const char **seat, uint32_t *vtnr) { + union sockaddr_union sa = {}; + _cleanup_free_ char *p = NULL, *tty = NULL; + _cleanup_close_ int fd = -1; + struct ucred ucred; + int v, r, salen; + + assert(display); + assert(vtnr); + + /* We deduce the X11 socket from the display name, then use + * SO_PEERCRED to determine the X11 server process, ask for + * the controlling tty of that and if it's a VC then we know + * the seat and the virtual terminal. Sounds ugly, is only + * semi-ugly. */ + + r = socket_from_display(display, &p); + if (r < 0) + return r; + salen = sockaddr_un_set_path(&sa.un, p); + if (salen < 0) + return salen; + + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); + if (fd < 0) + return -errno; + + if (connect(fd, &sa.sa, salen) < 0) + return -errno; + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + r = get_ctty(ucred.pid, NULL, &tty); + if (r < 0) + return r; + + v = vtnr_from_tty(tty); + if (v < 0) + return v; + else if (v == 0) + return -ENOENT; + + if (seat) + *seat = "seat0"; + *vtnr = (uint32_t) v; + + return 0; +} + +static int export_legacy_dbus_address( + pam_handle_t *handle, + uid_t uid, + const char *runtime) { + + const char *s; + _cleanup_free_ char *t = NULL; + int r = PAM_BUF_ERR; + + /* We need to export $DBUS_SESSION_BUS_ADDRESS because various applications will not connect + * correctly to the bus without it. This setting matches what dbus.socket does for the user + * session using 'systemctl --user set-environment'. We want to have the same configuration + * in processes started from the PAM session. + * + * The setting of the address is guarded by the access() check because it is also possible to compile + * dbus without --enable-user-session, in which case this socket is not used, and + * $DBUS_SESSION_BUS_ADDRESS should not be set. An alternative approach would to not do the access() + * check here, and let applications try on their own, by using "unix:path=%s/bus;autolaunch:". But we + * expect the socket to be present by the time we do this check, so we can just as well check once + * here. */ + + s = strjoina(runtime, "/bus"); + if (access(s, F_OK) < 0) + return PAM_SUCCESS; + + if (asprintf(&t, DEFAULT_USER_BUS_ADDRESS_FMT, runtime) < 0) + goto error; + + r = pam_misc_setenv(handle, "DBUS_SESSION_BUS_ADDRESS", t, 0); + if (r != PAM_SUCCESS) + goto error; + + return PAM_SUCCESS; + +error: + pam_syslog(handle, LOG_ERR, "Failed to set bus variable."); + return r; +} + +static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) { + uint64_t val; + int r; + + if (isempty(limit)) + return 0; + + if (streq(limit, "infinity")) { + r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", (uint64_t)-1); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r)); + return r; + } + } else { + r = parse_permille(limit); + if (r >= 0) { + r = sd_bus_message_append(m, "(sv)", "MemoryMaxScale", "u", (uint32_t) (((uint64_t) r * UINT32_MAX) / 1000U)); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r)); + return r; + } + } else { + r = parse_size(limit, 1024, &val); + if (r >= 0) { + r = sd_bus_message_append(m, "(sv)", "MemoryMax", "t", val); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r)); + return r; + } + } else + pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.memory_max: %s, ignoring.", limit); + } + } + + return 0; +} + +static int append_session_runtime_max_sec(pam_handle_t *handle, sd_bus_message *m, const char *limit) { + usec_t val; + int r; + + /* No need to parse "infinity" here, it will be set by default later in scope_init() */ + if (isempty(limit) || streq(limit, "infinity")) + return 0; + + r = parse_sec(limit, &val); + if (r >= 0) { + r = sd_bus_message_append(m, "(sv)", "RuntimeMaxUSec", "t", (uint64_t) val); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r)); + return r; + } + } else + pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.runtime_max_sec: %s, ignoring.", limit); + + return 0; +} + +static int append_session_tasks_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) { + uint64_t val; + int r; + + /* No need to parse "infinity" here, it will be set unconditionally later in manager_start_scope() */ + if (isempty(limit) || streq(limit, "infinity")) + return 0; + + r = safe_atou64(limit, &val); + if (r >= 0) { + r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", val); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r)); + return r; + } + } else + pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.tasks_max: %s, ignoring.", limit); + + return 0; +} + +static int append_session_cg_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit, const char *field) { + uint64_t val; + int r; + + if (isempty(limit)) + return 0; + + r = cg_weight_parse(limit, &val); + if (r >= 0) { + r = sd_bus_message_append(m, "(sv)", field, "t", val); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r)); + return r; + } + } else if (streq(field, "CPUWeight")) + pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.cpu_weight: %s, ignoring.", limit); + else + pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.io_weight: %s, ignoring.", limit); + + return 0; +} + +static const char* getenv_harder(pam_handle_t *handle, const char *key, const char *fallback) { + const char *v; + + assert(handle); + assert(key); + + /* Looks for an environment variable, preferably in the environment block associated with the + * specified PAM handle, falling back to the process' block instead. Why check both? Because we want + * to permit configuration of session properties from unit files that invoke PAM services, so that + * PAM services don't have to be reworked to set systemd-specific properties, but these properties + * can still be set from the unit file Environment= block. */ + + v = pam_getenv(handle, key); + if (!isempty(v)) + return v; + + /* We use secure_getenv() here, since we might get loaded into su/sudo, which are SUID. Ideally + * they'd clean up the environment before invoking foreign code (such as PAM modules), but alas they + * currently don't (to be precise, they clean up the environment they pass to their children, but + * not their own environ[]). */ + v = secure_getenv(key); + if (!isempty(v)) + return v; + + return fallback; +} + +static int update_environment(pam_handle_t *handle, const char *key, const char *value) { + int r; + + assert(handle); + assert(key); + + /* Updates the environment, but only if there's actually a value set. Also, log about errors */ + + if (isempty(value)) + return PAM_SUCCESS; + + r = pam_misc_setenv(handle, key, value, 0); + if (r != PAM_SUCCESS) + pam_syslog(handle, LOG_ERR, "Failed to set environment variable %s: %s", key, pam_strerror(handle, r)); + + return r; +} + +static bool validate_runtime_directory(pam_handle_t *handle, const char *path, uid_t uid) { + struct stat st; + + assert(handle); + assert(path); + + /* Just some extra paranoia: let's not set $XDG_RUNTIME_DIR if the directory we'd set it to isn't actually set + * up properly for us. */ + + if (lstat(path, &st) < 0) { + pam_syslog(handle, LOG_ERR, "Failed to stat() runtime directory '%s': %s", path, strerror_safe(errno)); + goto fail; + } + + if (!S_ISDIR(st.st_mode)) { + pam_syslog(handle, LOG_ERR, "Runtime directory '%s' is not actually a directory.", path); + goto fail; + } + + if (st.st_uid != uid) { + pam_syslog(handle, LOG_ERR, "Runtime directory '%s' is not owned by UID " UID_FMT ", as it should.", path, uid); + goto fail; + } + + return true; + +fail: + pam_syslog(handle, LOG_WARNING, "Not setting $XDG_RUNTIME_DIR, as the directory is not in order."); + return false; +} + +_public_ PAM_EXTERN int pam_sm_open_session( + pam_handle_t *handle, + int flags, + int argc, const char **argv) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + const char + *username, *id, *object_path, *runtime_path, + *service = NULL, + *tty = NULL, *display = NULL, + *remote_user = NULL, *remote_host = NULL, + *seat = NULL, + *type = NULL, *class = NULL, + *class_pam = NULL, *type_pam = NULL, *cvtnr = NULL, *desktop = NULL, *desktop_pam = NULL, + *memory_max = NULL, *tasks_max = NULL, *cpu_weight = NULL, *io_weight = NULL, *runtime_max_sec = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int session_fd = -1, existing, r; + bool debug = false, remote; + struct passwd *pw; + uint32_t vtnr = 0; + uid_t original_uid; + + assert(handle); + + /* Make this a NOP on non-logind systems */ + if (!logind_running()) + return PAM_SUCCESS; + + if (parse_argv(handle, + argc, argv, + &class_pam, + &type_pam, + &desktop_pam, + &debug) < 0) + return PAM_SESSION_ERR; + + if (debug) + pam_syslog(handle, LOG_DEBUG, "pam-systemd initializing"); + + r = get_user_data(handle, &username, &pw); + if (r != PAM_SUCCESS) + return r; + + /* Make sure we don't enter a loop by talking to + * systemd-logind when it is actually waiting for the + * background to finish start-up. If the service is + * "systemd-user" we simply set XDG_RUNTIME_DIR and + * leave. */ + + (void) pam_get_item(handle, PAM_SERVICE, (const void**) &service); + if (streq_ptr(service, "systemd-user")) { + char rt[STRLEN("/run/user/") + DECIMAL_STR_MAX(uid_t)]; + + xsprintf(rt, "/run/user/"UID_FMT, pw->pw_uid); + if (validate_runtime_directory(handle, rt, pw->pw_uid)) { + r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0); + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to set runtime dir: %s", pam_strerror(handle, r)); + return r; + } + } + + r = export_legacy_dbus_address(handle, pw->pw_uid, rt); + if (r != PAM_SUCCESS) + return r; + + return PAM_SUCCESS; + } + + /* Otherwise, we ask logind to create a session for us */ + + (void) pam_get_item(handle, PAM_XDISPLAY, (const void**) &display); + (void) pam_get_item(handle, PAM_TTY, (const void**) &tty); + (void) pam_get_item(handle, PAM_RUSER, (const void**) &remote_user); + (void) pam_get_item(handle, PAM_RHOST, (const void**) &remote_host); + + seat = getenv_harder(handle, "XDG_SEAT", NULL); + cvtnr = getenv_harder(handle, "XDG_VTNR", NULL); + type = getenv_harder(handle, "XDG_SESSION_TYPE", type_pam); + class = getenv_harder(handle, "XDG_SESSION_CLASS", class_pam); + desktop = getenv_harder(handle, "XDG_SESSION_DESKTOP", desktop_pam); + + tty = strempty(tty); + + if (strchr(tty, ':')) { + /* A tty with a colon is usually an X11 display, placed there to show up in utmp. We rearrange things + * and don't pretend that an X display was a tty. */ + if (isempty(display)) + display = tty; + tty = NULL; + + } else if (streq(tty, "cron")) { + /* cron is setting PAM_TTY to "cron" for some reason (the commit carries no information why, but + * probably because it wants to set it to something as pam_time/pam_access/… require PAM_TTY to be set + * (as they otherwise even try to update it!) — but cron doesn't actually allocate a TTY for its forked + * off processes.) */ + type = "unspecified"; + class = "background"; + tty = NULL; + + } else if (streq(tty, "ssh")) { + /* ssh has been setting PAM_TTY to "ssh" (for the same reason as cron does this, see above. For further + * details look for "PAM_TTY_KLUDGE" in the openssh sources). */ + type ="tty"; + class = "user"; + tty = NULL; /* This one is particularly sad, as this means that ssh sessions — even though usually + * associated with a pty — won't be tracked by their tty in logind. This is because ssh + * does the PAM session registration early for new connections, and registers a pty only + * much later (this is because it doesn't know yet if it needs one at all, as whether to + * register a pty or not is negotiated much later in the protocol). */ + + } else + /* Chop off leading /dev prefix that some clients specify, but others do not. */ + tty = skip_dev_prefix(tty); + + /* If this fails vtnr will be 0, that's intended */ + if (!isempty(cvtnr)) + (void) safe_atou32(cvtnr, &vtnr); + + if (!isempty(display) && !vtnr) { + if (isempty(seat)) + (void) get_seat_from_display(display, &seat, &vtnr); + else if (streq(seat, "seat0")) + (void) get_seat_from_display(display, NULL, &vtnr); + } + + if (seat && !streq(seat, "seat0") && vtnr != 0) { + if (debug) + pam_syslog(handle, LOG_DEBUG, "Ignoring vtnr %"PRIu32" for %s which is not seat0", vtnr, seat); + vtnr = 0; + } + + if (isempty(type)) + type = !isempty(display) ? "x11" : + !isempty(tty) ? "tty" : "unspecified"; + + if (isempty(class)) + class = streq(type, "unspecified") ? "background" : "user"; + + remote = !isempty(remote_host) && !is_localhost(remote_host); + + (void) pam_get_data(handle, "systemd.memory_max", (const void **)&memory_max); + (void) pam_get_data(handle, "systemd.tasks_max", (const void **)&tasks_max); + (void) pam_get_data(handle, "systemd.cpu_weight", (const void **)&cpu_weight); + (void) pam_get_data(handle, "systemd.io_weight", (const void **)&io_weight); + (void) pam_get_data(handle, "systemd.runtime_max_sec", (const void **)&runtime_max_sec); + + /* Talk to logind over the message bus */ + + r = sd_bus_open_system(&bus); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror_safe(r)); + return PAM_SESSION_ERR; + } + + if (debug) { + pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: " + "uid="UID_FMT" pid="PID_FMT" service=%s type=%s class=%s desktop=%s seat=%s vtnr=%"PRIu32" tty=%s display=%s remote=%s remote_user=%s remote_host=%s", + pw->pw_uid, getpid_cached(), + strempty(service), + type, class, strempty(desktop), + strempty(seat), vtnr, strempty(tty), strempty(display), + yes_no(remote), strempty(remote_user), strempty(remote_host)); + pam_syslog(handle, LOG_DEBUG, "Session limits: " + "memory_max=%s tasks_max=%s cpu_weight=%s io_weight=%s runtime_max_sec=%s", + strna(memory_max), strna(tasks_max), strna(cpu_weight), strna(io_weight), strna(runtime_max_sec)); + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "CreateSession"); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to create CreateSession method call: %s", strerror_safe(r)); + return PAM_SESSION_ERR; + } + + r = sd_bus_message_append(m, "uusssssussbss", + (uint32_t) pw->pw_uid, + 0, + service, + type, + class, + desktop, + seat, + vtnr, + tty, + display, + remote, + remote_user, + remote_host); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror_safe(r)); + return PAM_SESSION_ERR; + } + + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to open message container: %s", strerror_safe(r)); + return PAM_SYSTEM_ERR; + } + + r = append_session_memory_max(handle, m, memory_max); + if (r < 0) + return PAM_SESSION_ERR; + + r = append_session_runtime_max_sec(handle, m, runtime_max_sec); + if (r < 0) + return PAM_SESSION_ERR; + + r = append_session_tasks_max(handle, m, tasks_max); + if (r < 0) + return PAM_SESSION_ERR; + + r = append_session_cg_weight(handle, m, cpu_weight, "CPUWeight"); + if (r < 0) + return PAM_SESSION_ERR; + + r = append_session_cg_weight(handle, m, io_weight, "IOWeight"); + if (r < 0) + return PAM_SESSION_ERR; + + r = sd_bus_message_close_container(m); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to close message container: %s", strerror_safe(r)); + return PAM_SYSTEM_ERR; + } + + r = sd_bus_call(bus, m, LOGIN_SLOW_BUS_CALL_TIMEOUT_USEC, &error, &reply); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) { + if (debug) + pam_syslog(handle, LOG_DEBUG, "Not creating session: %s", bus_error_message(&error, r)); + return PAM_SUCCESS; + } else { + pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r)); + return PAM_SESSION_ERR; + } + } + + r = sd_bus_message_read(reply, + "soshusub", + &id, + &object_path, + &runtime_path, + &session_fd, + &original_uid, + &seat, + &vtnr, + &existing); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to parse message: %s", strerror_safe(r)); + return PAM_SESSION_ERR; + } + + if (debug) + pam_syslog(handle, LOG_DEBUG, "Reply from logind: " + "id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u original_uid=%u", + id, object_path, runtime_path, session_fd, seat, vtnr, original_uid); + + r = update_environment(handle, "XDG_SESSION_ID", id); + if (r != PAM_SUCCESS) + return r; + + if (original_uid == pw->pw_uid) { + /* Don't set $XDG_RUNTIME_DIR if the user we now + * authenticated for does not match the original user + * of the session. We do this in order not to result + * in privileged apps clobbering the runtime directory + * unnecessarily. */ + + if (validate_runtime_directory(handle, runtime_path, pw->pw_uid)) { + r = update_environment(handle, "XDG_RUNTIME_DIR", runtime_path); + if (r != PAM_SUCCESS) + return r; + } + + r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path); + if (r != PAM_SUCCESS) + return r; + } + + /* Most likely we got the session/type/class from environment variables, but might have gotten the data + * somewhere else (for example PAM module parameters). Let's now update the environment variables, so that this + * data is inherited into the session processes, and programs can rely on them to be initialized. */ + + r = update_environment(handle, "XDG_SESSION_TYPE", type); + if (r != PAM_SUCCESS) + return r; + + r = update_environment(handle, "XDG_SESSION_CLASS", class); + if (r != PAM_SUCCESS) + return r; + + r = update_environment(handle, "XDG_SESSION_DESKTOP", desktop); + if (r != PAM_SUCCESS) + return r; + + r = update_environment(handle, "XDG_SEAT", seat); + if (r != PAM_SUCCESS) + return r; + + if (vtnr > 0) { + char buf[DECIMAL_STR_MAX(vtnr)]; + sprintf(buf, "%u", vtnr); + + r = update_environment(handle, "XDG_VTNR", buf); + if (r != PAM_SUCCESS) + return r; + } + + r = pam_set_data(handle, "systemd.existing", INT_TO_PTR(!!existing), NULL); + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to install existing flag: %s", pam_strerror(handle, r)); + return r; + } + + if (session_fd >= 0) { + session_fd = fcntl(session_fd, F_DUPFD_CLOEXEC, 3); + if (session_fd < 0) { + pam_syslog(handle, LOG_ERR, "Failed to dup session fd: %m"); + return PAM_SESSION_ERR; + } + + r = pam_set_data(handle, "systemd.session-fd", FD_TO_PTR(session_fd), NULL); + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to install session fd: %s", pam_strerror(handle, r)); + safe_close(session_fd); + return r; + } + } + + return PAM_SUCCESS; +} + +_public_ PAM_EXTERN int pam_sm_close_session( + pam_handle_t *handle, + int flags, + int argc, const char **argv) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const void *existing = NULL; + const char *id; + int r; + + assert(handle); + + /* Only release session if it wasn't pre-existing when we + * tried to create it */ + (void) pam_get_data(handle, "systemd.existing", &existing); + + id = pam_getenv(handle, "XDG_SESSION_ID"); + if (id && !existing) { + + /* Before we go and close the FIFO we need to tell + * logind that this is a clean session shutdown, so + * that it doesn't just go and slaughter us + * immediately after closing the fd */ + + r = sd_bus_open_system(&bus); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to connect to system bus: %s", strerror_safe(r)); + return PAM_SESSION_ERR; + } + + r = sd_bus_call_method(bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ReleaseSession", + &error, + NULL, + "s", + id); + if (r < 0) { + pam_syslog(handle, LOG_ERR, "Failed to release session: %s", bus_error_message(&error, r)); + return PAM_SESSION_ERR; + } + } + + /* Note that we are knowingly leaking the FIFO fd here. This + * way, logind can watch us die. If we closed it here it would + * not have any clue when that is completed. Given that one + * cannot really have multiple PAM sessions open from the same + * process this means we will leak one FD at max. */ + + return PAM_SUCCESS; +} diff --git a/src/login/pam_systemd.sym b/src/login/pam_systemd.sym new file mode 100644 index 00000000..030a00ec --- /dev/null +++ b/src/login/pam_systemd.sym @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +{ +global: + pam_sm_close_session; + pam_sm_open_session; +local: *; +}; diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c new file mode 100644 index 00000000..a66be28a --- /dev/null +++ b/src/login/sysfs-show.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-device.h" + +#include "alloc-util.h" +#include "device-enumerator-private.h" +#include "locale-util.h" +#include "path-util.h" +#include "string-util.h" +#include "sysfs-show.h" +#include "terminal-util.h" +#include "util.h" + +static int show_sysfs_one( + const char *seat, + sd_device **dev_list, + size_t *i_dev, + size_t n_dev, + const char *sub, + const char *prefix, + unsigned n_columns, + OutputFlags flags) { + + size_t max_width; + int r; + + assert(seat); + assert(dev_list); + assert(i_dev); + assert(prefix); + + if (flags & OUTPUT_FULL_WIDTH) + max_width = (size_t) -1; + else if (n_columns < 10) + max_width = 10; + else + max_width = n_columns; + + while (*i_dev < n_dev) { + const char *sysfs, *sn, *name = NULL, *subsystem, *sysname; + _cleanup_free_ char *k = NULL, *l = NULL; + size_t lookahead; + bool is_master; + + if (sd_device_get_syspath(dev_list[*i_dev], &sysfs) < 0 || + !path_startswith(sysfs, sub)) + return 0; + + if (sd_device_get_property_value(dev_list[*i_dev], "ID_SEAT", &sn) < 0 || isempty(sn)) + sn = "seat0"; + + /* Explicitly also check for tag 'seat' here */ + if (!streq(seat, sn) || + sd_device_has_tag(dev_list[*i_dev], "seat") <= 0 || + sd_device_get_subsystem(dev_list[*i_dev], &subsystem) < 0 || + sd_device_get_sysname(dev_list[*i_dev], &sysname) < 0) { + (*i_dev)++; + continue; + } + + is_master = sd_device_has_tag(dev_list[*i_dev], "master-of-seat") > 0; + + if (sd_device_get_sysattr_value(dev_list[*i_dev], "name", &name) < 0) + (void) sd_device_get_sysattr_value(dev_list[*i_dev], "id", &name); + + /* Look if there's more coming after this */ + for (lookahead = *i_dev + 1; lookahead < n_dev; lookahead++) { + const char *lookahead_sysfs; + + if (sd_device_get_syspath(dev_list[lookahead], &lookahead_sysfs) < 0) + continue; + + if (path_startswith(lookahead_sysfs, sub) && + !path_startswith(lookahead_sysfs, sysfs)) { + const char *lookahead_sn; + + if (sd_device_get_property_value(dev_list[lookahead], "ID_SEAT", &lookahead_sn) < 0 || + isempty(lookahead_sn)) + lookahead_sn = "seat0"; + + if (streq(seat, lookahead_sn) && sd_device_has_tag(dev_list[lookahead], "seat") > 0) + break; + } + } + + k = ellipsize(sysfs, max_width, 20); + if (!k) + return -ENOMEM; + + printf("%s%s%s\n", prefix, special_glyph(lookahead < n_dev ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT), k); + + if (asprintf(&l, + "%s%s:%s%s%s%s", + is_master ? "[MASTER] " : "", + subsystem, sysname, + name ? " \"" : "", strempty(name), name ? "\"" : "") < 0) + return -ENOMEM; + + free(k); + k = ellipsize(l, max_width, 70); + if (!k) + return -ENOMEM; + + printf("%s%s%s\n", prefix, lookahead < n_dev ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " ", k); + + if (++(*i_dev) < n_dev) { + _cleanup_free_ char *p = NULL; + + p = strjoin(prefix, lookahead < n_dev ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " "); + if (!p) + return -ENOMEM; + + r = show_sysfs_one(seat, dev_list, i_dev, n_dev, sysfs, p, + n_columns == (unsigned) -1 || n_columns < 2 ? n_columns : n_columns - 2, + flags); + if (r < 0) + return r; + } + + } + + return 0; +} + +int show_sysfs(const char *seat, const char *prefix, unsigned n_columns, OutputFlags flags) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + size_t n_dev = 0, i = 0; + sd_device **dev_list; + int r; + + if (n_columns <= 0) + n_columns = columns(); + + prefix = strempty(prefix); + + if (isempty(seat)) + seat = "seat0"; + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_tag(e, streq(seat, "seat0") ? "seat" : seat); + if (r < 0) + return r; + + r = device_enumerator_scan_devices(e); + if (r < 0) + return r; + + dev_list = device_enumerator_get_devices(e, &n_dev); + + if (dev_list && n_dev > 0) + show_sysfs_one(seat, dev_list, &i, n_dev, "/", prefix, n_columns, flags); + else + printf("%s%s%s\n", prefix, special_glyph(SPECIAL_GLYPH_TREE_RIGHT), "(none)"); + + return 0; +} diff --git a/src/login/sysfs-show.h b/src/login/sysfs-show.h new file mode 100644 index 00000000..c05b9775 --- /dev/null +++ b/src/login/sysfs-show.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "output-mode.h" + +int show_sysfs(const char *seat, const char *prefix, unsigned columns, OutputFlags flags); diff --git a/src/login/systemd-user.m4 b/src/login/systemd-user.m4 new file mode 100644 index 00000000..4f85b4b7 --- /dev/null +++ b/src/login/systemd-user.m4 @@ -0,0 +1,12 @@ +# This file is part of systemd. +# +# Used by systemd --user instances. + +account required pam_unix.so +m4_ifdef(`HAVE_SELINUX', +session required pam_selinux.so close +session required pam_selinux.so nottys open +)m4_dnl +session required pam_loginuid.so +session optional pam_keyinit.so force revoke +session optional pam_systemd.so diff --git a/src/login/test-inhibit.c b/src/login/test-inhibit.c new file mode 100644 index 00000000..7f9013bf --- /dev/null +++ b/src/login/test-inhibit.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "bus-util.h" +#include "fd-util.h" +#include "macro.h" +#include "util.h" + +static int inhibit(sd_bus *bus, const char *what) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *who = "Test Tool", *reason = "Just because!", *mode = "block"; + int fd; + int r; + + r = sd_bus_call_method(bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "Inhibit", + &error, + &reply, + "ssss", what, who, reason, mode); + assert_se(r >= 0); + + r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_UNIX_FD, &fd); + assert_se(r >= 0); + assert_se(fd >= 0); + + return fcntl(fd, F_DUPFD_CLOEXEC, 3); +} + +static void print_inhibitors(sd_bus *bus) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *what, *who, *why, *mode; + uint32_t uid, pid; + unsigned n = 0; + int r; + + r = sd_bus_call_method(bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ListInhibitors", + &error, + &reply, + ""); + assert_se(r >= 0); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)"); + assert_se(r >= 0); + + while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) { + printf("what=<%s> who=<%s> why=<%s> mode=<%s> uid=<%"PRIu32"> pid=<%"PRIu32">\n", + what, who, why, mode, uid, pid); + + n++; + } + assert_se(r >= 0); + + printf("%u inhibitors\n", n); +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + int fd1, fd2; + int r; + + r = sd_bus_open_system(&bus); + assert_se(r >= 0); + + print_inhibitors(bus); + + fd1 = inhibit(bus, "sleep"); + assert_se(fd1 >= 0); + print_inhibitors(bus); + + fd2 = inhibit(bus, "idle:shutdown"); + assert_se(fd2 >= 0); + print_inhibitors(bus); + + safe_close(fd1); + sleep(1); + print_inhibitors(bus); + + safe_close(fd2); + sleep(1); + print_inhibitors(bus); + + return 0; +} diff --git a/src/login/test-login-shared.c b/src/login/test-login-shared.c new file mode 100644 index 00000000..02ff57ab --- /dev/null +++ b/src/login/test-login-shared.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "login-util.h" +#include "macro.h" + +static void test_session_id_valid(void) { + assert_se(session_id_valid("c1")); + assert_se(session_id_valid("1234")); + + assert_se(!session_id_valid("1-2")); + assert_se(!session_id_valid("")); + assert_se(!session_id_valid("\tid")); +} + +int main(int argc, char* argv[]) { + log_parse_environment(); + log_open(); + + test_session_id_valid(); + + return 0; +} diff --git a/src/login/test-login-tables.c b/src/login/test-login-tables.c new file mode 100644 index 00000000..02b87196 --- /dev/null +++ b/src/login/test-login-tables.c @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "logind-action.h" +#include "logind-session.h" +#include "test-tables.h" + +int main(int argc, char **argv) { + test_table(handle_action, HANDLE_ACTION); + test_table(inhibit_mode, INHIBIT_MODE); + test_table(kill_who, KILL_WHO); + test_table(session_class, SESSION_CLASS); + test_table(session_state, SESSION_STATE); + test_table(session_type, SESSION_TYPE); + test_table(user_state, USER_STATE); + + return EXIT_SUCCESS; +} diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c new file mode 100644 index 00000000..c8a56256 --- /dev/null +++ b/src/login/user-runtime-dir.c @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "bus-error.h" +#include "fs-util.h" +#include "format-util.h" +#include "label.h" +#include "main-func.h" +#include "mkdir.h" +#include "mountpoint-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "selinux-util.h" +#include "smack-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" + +static int acquire_runtime_dir_size(uint64_t *ret) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + r = sd_bus_default_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to connect to system bus: %m"); + + r = sd_bus_get_property_trivial(bus, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "RuntimeDirectorySize", &error, 't', ret); + if (r < 0) + return log_error_errno(r, "Failed to acquire runtime directory size: %s", bus_error_message(&error, r)); + + return 0; +} + +static int user_mkdir_runtime_path( + const char *runtime_path, + uid_t uid, + gid_t gid, + uint64_t runtime_dir_size) { + + int r; + + assert(runtime_path); + assert(path_is_absolute(runtime_path)); + assert(uid_is_valid(uid)); + assert(gid_is_valid(gid)); + + r = mkdir_safe_label("/run/user", 0755, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + return log_error_errno(r, "Failed to create /run/user: %m"); + + if (path_is_mount_point(runtime_path, NULL, 0) >= 0) + log_debug("%s is already a mount point", runtime_path); + else { + char options[sizeof("mode=0700,uid=,gid=,size=,smackfsroot=*") + + DECIMAL_STR_MAX(uid_t) + + DECIMAL_STR_MAX(gid_t) + + DECIMAL_STR_MAX(uint64_t)]; + + xsprintf(options, + "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%" PRIu64 "%s", + uid, gid, runtime_dir_size, + mac_smack_use() ? ",smackfsroot=*" : ""); + + (void) mkdir_label(runtime_path, 0700); + + r = mount("tmpfs", runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, options); + if (r < 0) { + if (!IN_SET(errno, EPERM, EACCES)) { + r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", runtime_path); + goto fail; + } + + log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s.\n" + "Assuming containerized execution, ignoring: %m", runtime_path); + + r = chmod_and_chown(runtime_path, 0700, uid, gid); + if (r < 0) { + log_error_errno(r, "Failed to change ownership and mode of \"%s\": %m", runtime_path); + goto fail; + } + } + + r = label_fix(runtime_path, 0); + if (r < 0) + log_warning_errno(r, "Failed to fix label of \"%s\", ignoring: %m", runtime_path); + } + + return 0; + +fail: + /* Try to clean up, but ignore errors */ + (void) rmdir(runtime_path); + return r; +} + +static int user_remove_runtime_path(const char *runtime_path) { + int r; + + assert(runtime_path); + assert(path_is_absolute(runtime_path)); + + r = rm_rf(runtime_path, 0); + if (r < 0) + log_debug_errno(r, "Failed to remove runtime directory %s (before unmounting), ignoring: %m", runtime_path); + + /* Ignore cases where the directory isn't mounted, as that's quite possible, if we lacked the permissions to + * mount something */ + r = umount2(runtime_path, MNT_DETACH); + if (r < 0 && !IN_SET(errno, EINVAL, ENOENT)) + log_debug_errno(errno, "Failed to unmount user runtime directory %s, ignoring: %m", runtime_path); + + r = rm_rf(runtime_path, REMOVE_ROOT); + if (r < 0 && r != -ENOENT) + return log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", runtime_path); + + return 0; +} + +static int do_mount(const char *user) { + char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)]; + uint64_t runtime_dir_size; + uid_t uid; + gid_t gid; + int r; + + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); + if (r < 0) + return log_error_errno(r, + r == -ESRCH ? "No such user \"%s\"" : + r == -ENOMSG ? "UID \"%s\" is invalid or has an invalid main group" + : "Failed to look up user \"%s\": %m", + user); + + r = acquire_runtime_dir_size(&runtime_dir_size); + if (r < 0) + return r; + + xsprintf(runtime_path, "/run/user/" UID_FMT, uid); + + log_debug("Will mount %s owned by "UID_FMT":"GID_FMT, runtime_path, uid, gid); + return user_mkdir_runtime_path(runtime_path, uid, gid, runtime_dir_size); +} + +static int do_umount(const char *user) { + char runtime_path[sizeof("/run/user") + DECIMAL_STR_MAX(uid_t)]; + uid_t uid; + int r; + + /* The user may be already removed. So, first try to parse the string by parse_uid(), + * and if it fails, fallback to get_user_creds().*/ + if (parse_uid(user, &uid) < 0) { + r = get_user_creds(&user, &uid, NULL, NULL, NULL, 0); + if (r < 0) + return log_error_errno(r, + r == -ESRCH ? "No such user \"%s\"" : + r == -ENOMSG ? "UID \"%s\" is invalid or has an invalid main group" + : "Failed to look up user \"%s\": %m", + user); + } + + xsprintf(runtime_path, "/run/user/" UID_FMT, uid); + + log_debug("Will remove %s", runtime_path); + return user_remove_runtime_path(runtime_path); +} + +static int run(int argc, char *argv[]) { + int r; + + log_parse_environment(); + log_open(); + + if (argc != 3) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program takes two arguments."); + if (!STR_IN_SET(argv[1], "start", "stop")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "First argument must be either \"start\" or \"stop\"."); + + r = mac_selinux_init(); + if (r < 0) + return log_error_errno(r, "Could not initialize labelling: %m\n"); + + umask(0022); + + if (streq(argv[1], "start")) + return do_mount(argv[2]); + if (streq(argv[1], "stop")) + return do_umount(argv[2]); + assert_not_reached("Unknown verb!"); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c new file mode 100644 index 00000000..872b00c1 --- /dev/null +++ b/src/machine-id-setup/machine-id-setup-main.c @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "id128-util.h" +#include "log.h" +#include "machine-id-setup.h" +#include "main-func.h" +#include "path-util.h" +#include "pretty-print.h" +#include "util.h" + +static char *arg_root = NULL; +static bool arg_commit = false; +static bool arg_print = false; + +STATIC_DESTRUCTOR_REGISTER(arg_root, freep); + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-machine-id-setup", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n\n" + "Initialize /etc/machine-id from a random source.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --root=ROOT Filesystem root\n" + " --commit Commit transient ID\n" + " --print Print used machine ID\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_ROOT, + ARG_COMMIT, + ARG_PRINT, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "root", required_argument, NULL, ARG_ROOT }, + { "commit", no_argument, NULL, ARG_COMMIT }, + { "print", no_argument, NULL, ARG_PRINT }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_ROOT: + r = parse_path_argument_and_warn(optarg, true, &arg_root); + if (r < 0) + return r; + break; + + case ARG_COMMIT: + arg_commit = true; + break; + + case ARG_PRINT: + arg_print = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Extraneous arguments"); + + return 1; +} + +static int run(int argc, char *argv[]) { + char buf[SD_ID128_STRING_MAX]; + sd_id128_t id; + int r; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (arg_commit) { + const char *etc_machine_id; + + r = machine_id_commit(arg_root); + if (r < 0) + return r; + + etc_machine_id = prefix_roota(arg_root, "/etc/machine-id"); + r = id128_read(etc_machine_id, ID128_PLAIN, &id); + if (r < 0) + return log_error_errno(r, "Failed to read machine ID back: %m"); + } else { + r = machine_id_setup(arg_root, SD_ID128_NULL, &id); + if (r < 0) + return r; + } + + if (arg_print) + puts(sd_id128_to_string(id, buf)); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c new file mode 100644 index 00000000..294ef349 --- /dev/null +++ b/src/machine/image-dbus.c @@ -0,0 +1,499 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "bus-label.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "copy.h" +#include "dissect-image.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "image-dbus.h" +#include "io-util.h" +#include "loop-util.h" +#include "machine-image.h" +#include "missing_capability.h" +#include "mount-util.h" +#include "process-util.h" +#include "raw-clone.h" +#include "strv.h" +#include "user-util.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, image_type, ImageType); + +int bus_image_method_remove( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; + Image *image = userdata; + Manager *m = image->userdata; + pid_t child; + int r; + + assert(message); + assert(image); + + if (m->n_operations >= OPERATIONS_MAX) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations."); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-images", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) + return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); + + r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); + if (r == 0) { + errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]); + + r = image_remove(image); + if (r < 0) { + (void) write(errno_pipe_fd[1], &r, sizeof(r)); + _exit(EXIT_FAILURE); + } + + _exit(EXIT_SUCCESS); + } + + errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); + + r = operation_new(m, NULL, child, message, errno_pipe_fd[0], NULL); + if (r < 0) { + (void) sigkill_wait(child); + return r; + } + + errno_pipe_fd[0] = -1; + + return 1; +} + +int bus_image_method_rename( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Image *image = userdata; + Manager *m = image->userdata; + const char *new_name; + int r; + + assert(message); + assert(image); + + r = sd_bus_message_read(message, "s", &new_name); + if (r < 0) + return r; + + if (!image_name_is_valid(new_name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-images", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = image_rename(image, new_name); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_image_method_clone( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; + Image *image = userdata; + Manager *m = image->userdata; + const char *new_name; + int r, read_only; + pid_t child; + + assert(message); + assert(image); + assert(m); + + if (m->n_operations >= OPERATIONS_MAX) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations."); + + r = sd_bus_message_read(message, "sb", &new_name, &read_only); + if (r < 0) + return r; + + if (!image_name_is_valid(new_name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-images", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) + return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); + + r = safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); + if (r == 0) { + errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]); + + r = image_clone(image, new_name, read_only); + if (r < 0) { + (void) write(errno_pipe_fd[1], &r, sizeof(r)); + _exit(EXIT_FAILURE); + } + + _exit(EXIT_SUCCESS); + } + + errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); + + r = operation_new(m, NULL, child, message, errno_pipe_fd[0], NULL); + if (r < 0) { + (void) sigkill_wait(child); + return r; + } + + errno_pipe_fd[0] = -1; + + return 1; +} + +int bus_image_method_mark_read_only( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Image *image = userdata; + Manager *m = image->userdata; + int r, read_only; + + assert(message); + + r = sd_bus_message_read(message, "b", &read_only); + if (r < 0) + return r; + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-images", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = image_read_only(image, read_only); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_image_method_set_limit( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Image *image = userdata; + Manager *m = image->userdata; + uint64_t limit; + int r; + + assert(message); + + r = sd_bus_message_read(message, "t", &limit); + if (r < 0) + return r; + if (!FILE_SIZE_VALID_OR_INFINITY(limit)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range"); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-images", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = image_set_limit(image, limit); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_image_method_get_hostname( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Image *image = userdata; + int r; + + if (!image->metadata_valid) { + r = image_read_metadata(image); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m"); + } + + return sd_bus_reply_method_return(message, "s", image->hostname); +} + +int bus_image_method_get_machine_id( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Image *image = userdata; + int r; + + if (!image->metadata_valid) { + r = image_read_metadata(image); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m"); + } + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + if (sd_id128_is_null(image->machine_id)) /* Add an empty array if the ID is zero */ + r = sd_bus_message_append(reply, "ay", 0); + else + r = sd_bus_message_append_array(reply, 'y', image->machine_id.bytes, 16); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +int bus_image_method_get_machine_info( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Image *image = userdata; + int r; + + if (!image->metadata_valid) { + r = image_read_metadata(image); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m"); + } + + return bus_reply_pair_array(message, image->machine_info); +} + +int bus_image_method_get_os_release( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Image *image = userdata; + int r; + + if (!image->metadata_valid) { + r = image_read_metadata(image); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m"); + } + + return bus_reply_pair_array(message, image->os_release); +} + +const sd_bus_vtable image_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0), + SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0), + SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0), + SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0), + SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0), + SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0), + SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0), + SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0), + SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0), + SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0), + SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Rename", "s", NULL, bus_image_method_rename, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetHostname", NULL, "s", bus_image_method_get_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineID", NULL, "ay", bus_image_method_get_machine_id, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineInfo", NULL, "a{ss}", bus_image_method_get_machine_info, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_image_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END +}; + +static int image_flush_cache(sd_event_source *s, void *userdata) { + Manager *m = userdata; + + assert(s); + assert(m); + + hashmap_clear(m->image_cache); + return 0; +} + +int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + _cleanup_free_ char *e = NULL; + Manager *m = userdata; + Image *image = NULL; + const char *p; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + + p = startswith(path, "/org/freedesktop/machine1/image/"); + if (!p) + return 0; + + e = bus_label_unescape(p); + if (!e) + return -ENOMEM; + + image = hashmap_get(m->image_cache, e); + if (image) { + *found = image; + return 1; + } + + r = hashmap_ensure_allocated(&m->image_cache, &image_hash_ops); + if (r < 0) + return r; + + if (!m->image_cache_defer_event) { + r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_flush_cache, m); + if (r < 0) + return r; + + r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE); + if (r < 0) + return r; + } + + r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT); + if (r < 0) + return r; + + r = image_find(IMAGE_MACHINE, e, &image); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + image->userdata = m; + + r = hashmap_put(m->image_cache, image->name, image); + if (r < 0) { + image_unref(image); + return r; + } + + *found = image; + return 1; +} + +char *image_bus_path(const char *name) { + _cleanup_free_ char *e = NULL; + + assert(name); + + e = bus_label_escape(name); + if (!e) + return NULL; + + return strjoin("/org/freedesktop/machine1/image/", e); +} + +int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_hashmap_free_ Hashmap *images = NULL; + _cleanup_strv_free_ char **l = NULL; + Image *image; + Iterator i; + int r; + + assert(bus); + assert(path); + assert(nodes); + + images = hashmap_new(&image_hash_ops); + if (!images) + return -ENOMEM; + + r = image_discover(IMAGE_MACHINE, images); + if (r < 0) + return r; + + HASHMAP_FOREACH(image, images, i) { + char *p; + + p = image_bus_path(image->name); + if (!p) + return -ENOMEM; + + r = strv_consume(&l, p); + if (r < 0) + return r; + } + + *nodes = TAKE_PTR(l); + + return 1; +} diff --git a/src/machine/image-dbus.h b/src/machine/image-dbus.h new file mode 100644 index 00000000..a918b77d --- /dev/null +++ b/src/machine/image-dbus.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "machined.h" + +extern const sd_bus_vtable image_vtable[]; + +char *image_bus_path(const char *name); + +int image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +int image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); + +int bus_image_method_remove(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_rename(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_clone(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_mark_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_set_limit(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_get_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_get_machine_id(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_get_machine_info(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c new file mode 100644 index 00000000..a2990452 --- /dev/null +++ b/src/machine/machine-dbus.c @@ -0,0 +1,1485 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +/* When we include libgen.h because we need dirname() we immediately + * undefine basename() since libgen.h defines it as a macro to the POSIX + * version which is really broken. We prefer GNU basename(). */ +#include +#undef basename + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-internal.h" +#include "bus-label.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "copy.h" +#include "env-file.h" +#include "env-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "in-addr-util.h" +#include "io-util.h" +#include "local-addresses.h" +#include "machine-dbus.h" +#include "machine.h" +#include "missing_capability.h" +#include "mkdir.h" +#include "namespace-util.h" +#include "os-util.h" +#include "path-util.h" +#include "process-util.h" +#include "signal-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "user-util.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass); +static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Machine, machine_get_state, machine_state_to_string); + +static int property_get_netif( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Machine *m = userdata; + + assert(bus); + assert(reply); + assert(m); + + assert_cc(sizeof(int) == sizeof(int32_t)); + + return sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int)); +} + +int bus_machine_method_unregister(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Machine *m = userdata; + int r; + + assert(message); + assert(m); + + r = bus_verify_polkit_async( + message, + CAP_KILL, + "org.freedesktop.machine1.manage-machines", + NULL, + false, + UID_INVALID, + &m->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = machine_finalize(m); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Machine *m = userdata; + int r; + + assert(message); + assert(m); + + r = bus_verify_polkit_async( + message, + CAP_KILL, + "org.freedesktop.machine1.manage-machines", + NULL, + false, + UID_INVALID, + &m->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = machine_stop(m); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Machine *m = userdata; + const char *swho; + int32_t signo; + KillWho who; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "si", &swho, &signo); + if (r < 0) + return r; + + if (isempty(swho)) + who = KILL_ALL; + else { + who = kill_who_from_string(swho); + if (who < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho); + } + + if (!SIGNAL_VALID(signo)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo); + + r = bus_verify_polkit_async( + message, + CAP_KILL, + "org.freedesktop.machine1.manage-machines", + NULL, + false, + UID_INVALID, + &m->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = machine_kill(m, who, signo); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Machine *m = userdata; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(iay)"); + if (r < 0) + return r; + + switch (m->class) { + + case MACHINE_HOST: { + _cleanup_free_ struct local_address *addresses = NULL; + struct local_address *a; + int n, i; + + n = local_addresses(NULL, 0, AF_UNSPEC, &addresses); + if (n < 0) + return n; + + for (a = addresses, i = 0; i < n; a++, i++) { + + r = sd_bus_message_open_container(reply, 'r', "iay"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "i", addresses[i].family); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', &addresses[i].address, FAMILY_ADDRESS_SIZE(addresses[i].family)); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } + + break; + } + + case MACHINE_CONTAINER: { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + _cleanup_free_ char *us = NULL, *them = NULL; + _cleanup_close_ int netns_fd = -1; + const char *p; + pid_t child; + + r = readlink_malloc("/proc/self/ns/net", &us); + if (r < 0) + return r; + + p = procfs_file_alloca(m->leader, "ns/net"); + r = readlink_malloc(p, &them); + if (r < 0) + return r; + + if (streq(us, them)) + return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name); + + r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL, NULL); + if (r < 0) + return r; + + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) + return -errno; + + r = namespace_fork("(sd-addrns)", "(sd-addr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG, + -1, -1, netns_fd, -1, -1, &child); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); + if (r == 0) { + _cleanup_free_ struct local_address *addresses = NULL; + struct local_address *a; + int i, n; + + pair[0] = safe_close(pair[0]); + + n = local_addresses(NULL, 0, AF_UNSPEC, &addresses); + if (n < 0) + _exit(EXIT_FAILURE); + + for (a = addresses, i = 0; i < n; a++, i++) { + struct iovec iov[2] = { + { .iov_base = &a->family, .iov_len = sizeof(a->family) }, + { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) }, + }; + + r = writev(pair[1], iov, 2); + if (r < 0) + _exit(EXIT_FAILURE); + } + + pair[1] = safe_close(pair[1]); + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + for (;;) { + int family; + ssize_t n; + union in_addr_union in_addr; + struct iovec iov[2]; + struct msghdr mh = { + .msg_iov = iov, + .msg_iovlen = 2, + }; + + iov[0] = IOVEC_MAKE(&family, sizeof(family)); + iov[1] = IOVEC_MAKE(&in_addr, sizeof(in_addr)); + + n = recvmsg(pair[0], &mh, 0); + if (n < 0) + return -errno; + if ((size_t) n < sizeof(family)) + break; + + r = sd_bus_message_open_container(reply, 'r', "iay"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "i", family); + if (r < 0) + return r; + + switch (family) { + + case AF_INET: + if (n != sizeof(struct in_addr) + sizeof(family)) + return -EIO; + + r = sd_bus_message_append_array(reply, 'y', &in_addr.in, sizeof(in_addr.in)); + break; + + case AF_INET6: + if (n != sizeof(struct in6_addr) + sizeof(family)) + return -EIO; + + r = sd_bus_message_append_array(reply, 'y', &in_addr.in6, sizeof(in_addr.in6)); + break; + } + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } + + r = wait_for_terminate_and_check("(sd-addrns)", child, 0); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m"); + if (r != EXIT_SUCCESS) + return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally."); + break; + } + + default: + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines."); + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +#define EXIT_NOT_FOUND 2 + +int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Machine *m = userdata; + int r; + + assert(message); + assert(m); + + switch (m->class) { + + case MACHINE_HOST: + r = load_os_release_pairs(NULL, &l); + if (r < 0) + return r; + + break; + + case MACHINE_CONTAINER: { + _cleanup_close_ int mntns_fd = -1, root_fd = -1, pidns_fd = -1; + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + _cleanup_fclose_ FILE *f = NULL; + pid_t child; + + r = namespace_open(m->leader, &pidns_fd, &mntns_fd, NULL, NULL, &root_fd); + if (r < 0) + return r; + + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0) + return -errno; + + r = namespace_fork("(sd-osrelns)", "(sd-osrel)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG, + pidns_fd, mntns_fd, -1, -1, root_fd, + &child); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); + if (r == 0) { + int fd = -1; + + pair[0] = safe_close(pair[0]); + + r = open_os_release(NULL, NULL, &fd); + if (r == -ENOENT) + _exit(EXIT_NOT_FOUND); + if (r < 0) + _exit(EXIT_FAILURE); + + r = copy_bytes(fd, pair[1], (uint64_t) -1, 0); + if (r < 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + f = fdopen(pair[0], "r"); + if (!f) + return -errno; + + pair[0] = -1; + + r = load_env_file_pairs(f, "/etc/os-release", &l); + if (r < 0) + return r; + + r = wait_for_terminate_and_check("(sd-osrelns)", child, 0); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m"); + if (r == EXIT_NOT_FOUND) + return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Machine does not contain OS release information"); + if (r != EXIT_SUCCESS) + return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally."); + + break; + } + + default: + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines."); + } + + return bus_reply_pair_array(message, l); +} + +int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *pty_name = NULL; + _cleanup_close_ int master = -1; + Machine *m = userdata; + int r; + + assert(message); + assert(m); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-open-pty" : "org.freedesktop.machine1.open-pty", + NULL, + false, + UID_INVALID, + &m->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name); + if (master < 0) + return master; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "hs", master, pty_name); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) { + int r; + + assert(m); + assert(ret); + + switch (m->class) { + + case MACHINE_HOST: + *ret = NULL; + break; + + case MACHINE_CONTAINER: { + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; + char *address; + + r = sd_bus_new(&bus); + if (r < 0) + return r; + + if (asprintf(&address, "x-machine-kernel:pid=%1$" PID_PRI ";x-machine-unix:pid=%1$" PID_PRI, m->leader) < 0) + return -ENOMEM; + + bus->address = address; + bus->bus_client = true; + bus->trusted = false; + bus->is_system = true; + + r = sd_bus_start(bus); + if (r == -ENOENT) + return sd_bus_error_set_errnof(error, r, "There is no system bus in container %s.", m->name); + if (r < 0) + return r; + + *ret = TAKE_PTR(bus); + break; + } + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *pty_name = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *allocated_bus = NULL; + _cleanup_close_ int master = -1; + sd_bus *container_bus = NULL; + Machine *m = userdata; + const char *p, *getty; + int r; + + assert(message); + assert(m); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-login" : "org.freedesktop.machine1.login", + NULL, + false, + UID_INVALID, + &m->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name); + if (master < 0) + return master; + + p = path_startswith(pty_name, "/dev/pts/"); + assert(p); + + r = container_bus_new(m, error, &allocated_bus); + if (r < 0) + return r; + + container_bus = allocated_bus ?: m->manager->bus; + + getty = strjoina("container-getty@", p, ".service"); + + r = sd_bus_call_method( + container_bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + error, NULL, + "ss", getty, "replace"); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "hs", master, pty_name); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *tm = NULL; + _cleanup_free_ char *pty_name = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *allocated_bus = NULL; + sd_bus *container_bus = NULL; + _cleanup_close_ int master = -1, slave = -1; + _cleanup_strv_free_ char **env = NULL, **args_wire = NULL, **args = NULL; + Machine *m = userdata; + const char *p, *unit, *user, *path, *description, *utmp_id; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "ss", &user, &path); + if (r < 0) + return r; + user = empty_to_null(user); + r = sd_bus_message_read_strv(message, &args_wire); + if (r < 0) + return r; + if (isempty(path)) { + path = "/bin/sh"; + + args = new0(char*, 3 + 1); + if (!args) + return -ENOMEM; + args[0] = strdup("sh"); + if (!args[0]) + return -ENOMEM; + args[1] = strdup("-c"); + if (!args[1]) + return -ENOMEM; + r = asprintf(&args[2], + "shell=$(getent passwd %s 2>/dev/null | { IFS=: read _ _ _ _ _ _ x; echo \"$x\"; })\n"\ + "exec \"${shell:-/bin/sh}\" -l", /* -l is means --login */ + isempty(user) ? "root" : user); + if (r < 0) { + args[2] = NULL; + return -ENOMEM; + } + } else { + if (!path_is_absolute(path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified path '%s' is not absolute", path); + args = TAKE_PTR(args_wire); + if (strv_isempty(args)) { + args = strv_free(args); + + args = strv_new(path); + if (!args) + return -ENOMEM; + } + } + + r = sd_bus_message_read_strv(message, &env); + if (r < 0) + return r; + if (!strv_env_is_valid(env)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments"); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-shell" : "org.freedesktop.machine1.shell", + NULL, + false, + UID_INVALID, + &m->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name); + if (master < 0) + return master; + + p = path_startswith(pty_name, "/dev/pts/"); + assert(p); + + slave = machine_open_terminal(m, pty_name, O_RDWR|O_NOCTTY|O_CLOEXEC); + if (slave < 0) + return slave; + + utmp_id = path_startswith(pty_name, "/dev/"); + assert(utmp_id); + + r = container_bus_new(m, error, &allocated_bus); + if (r < 0) + return r; + + container_bus = allocated_bus ?: m->manager->bus; + + r = sd_bus_message_new_method_call( + container_bus, + &tm, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return r; + + /* Name and mode */ + unit = strjoina("container-shell@", p, ".service"); + r = sd_bus_message_append(tm, "ss", unit, "fail"); + if (r < 0) + return r; + + /* Properties */ + r = sd_bus_message_open_container(tm, 'a', "(sv)"); + if (r < 0) + return r; + + description = strjoina("Shell for User ", isempty(user) ? "root" : user); + r = sd_bus_message_append(tm, + "(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)", + "Description", "s", description, + "StandardInputFileDescriptor", "h", slave, + "StandardOutputFileDescriptor", "h", slave, + "StandardErrorFileDescriptor", "h", slave, + "SendSIGHUP", "b", true, + "IgnoreSIGPIPE", "b", false, + "KillMode", "s", "mixed", + "TTYReset", "b", true, + "UtmpIdentifier", "s", utmp_id, + "UtmpMode", "s", "user", + "PAMName", "s", "login", + "WorkingDirectory", "s", "-~"); + if (r < 0) + return r; + + r = sd_bus_message_append(tm, "(sv)", "User", "s", isempty(user) ? "root" : user); + if (r < 0) + return r; + + if (!strv_isempty(env)) { + r = sd_bus_message_open_container(tm, 'r', "sv"); + if (r < 0) + return r; + + r = sd_bus_message_append(tm, "s", "Environment"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(tm, 'v', "as"); + if (r < 0) + return r; + + r = sd_bus_message_append_strv(tm, env); + if (r < 0) + return r; + + r = sd_bus_message_close_container(tm); + if (r < 0) + return r; + + r = sd_bus_message_close_container(tm); + if (r < 0) + return r; + } + + /* Exec container */ + r = sd_bus_message_open_container(tm, 'r', "sv"); + if (r < 0) + return r; + + r = sd_bus_message_append(tm, "s", "ExecStart"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(tm, 'v', "a(sasb)"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(tm, 'a', "(sasb)"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(tm, 'r', "sasb"); + if (r < 0) + return r; + + r = sd_bus_message_append(tm, "s", path); + if (r < 0) + return r; + + r = sd_bus_message_append_strv(tm, args); + if (r < 0) + return r; + + r = sd_bus_message_append(tm, "b", true); + if (r < 0) + return r; + + r = sd_bus_message_close_container(tm); + if (r < 0) + return r; + + r = sd_bus_message_close_container(tm); + if (r < 0) + return r; + + r = sd_bus_message_close_container(tm); + if (r < 0) + return r; + + r = sd_bus_message_close_container(tm); + if (r < 0) + return r; + + r = sd_bus_message_close_container(tm); + if (r < 0) + return r; + + /* Auxiliary units */ + r = sd_bus_message_append(tm, "a(sa(sv))", 0); + if (r < 0) + return r; + + r = sd_bus_call(container_bus, tm, 0, error, NULL); + if (r < 0) + return r; + + slave = safe_close(slave); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "hs", master, pty_name); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; + char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p; + bool mount_slave_created = false, mount_slave_mounted = false, + mount_tmp_created = false, mount_tmp_mounted = false, + mount_outside_created = false, mount_outside_mounted = false; + _cleanup_free_ char *chased_src = NULL; + int read_only, make_file_or_directory; + const char *dest, *src; + Machine *m = userdata; + struct stat st; + pid_t child; + uid_t uid; + int r; + + assert(message); + assert(m); + + if (m->class != MACHINE_CONTAINER) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines."); + + r = sd_bus_message_read(message, "ssbb", &src, &dest, &read_only, &make_file_or_directory); + if (r < 0) + return r; + + if (!path_is_absolute(src) || !path_is_normalized(src)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../."); + + if (isempty(dest)) + dest = src; + else if (!path_is_absolute(dest) || !path_is_normalized(dest)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../."); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-machines", + NULL, + false, + UID_INVALID, + &m->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = machine_get_uid_shift(m, &uid); + if (r < 0) + return r; + if (uid != 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Can't bind mount on container with user namespacing applied."); + + /* One day, when bind mounting /proc/self/fd/n works across + * namespace boundaries we should rework this logic to make + * use of it... */ + + p = strjoina("/run/systemd/nspawn/propagate/", m->name, "/"); + if (laccess(p, F_OK) < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points."); + + r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, &chased_src, NULL); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to resolve source path: %m"); + + if (lstat(chased_src, &st) < 0) + return sd_bus_error_set_errnof(error, errno, "Failed to stat() source path: %m"); + if (S_ISLNK(st.st_mode)) /* This shouldn't really happen, given that we just chased the symlinks above, but let's better be safe… */ + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Source directory can't be a symbolic link"); + + /* Our goal is to install a new bind mount into the container, + possibly read-only. This is irritatingly complex + unfortunately, currently. + + First, we start by creating a private playground in /tmp, + that we can mount MS_SLAVE. (Which is necessary, since + MS_MOVE cannot be applied to mounts with MS_SHARED parent + mounts.) */ + + if (!mkdtemp(mount_slave)) + return sd_bus_error_set_errnof(error, errno, "Failed to create playground %s: %m", mount_slave); + + mount_slave_created = true; + + if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) { + r = sd_bus_error_set_errnof(error, errno, "Failed to make bind mount %s: %m", mount_slave); + goto finish; + } + + mount_slave_mounted = true; + + if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) { + r = sd_bus_error_set_errnof(error, errno, "Failed to remount slave %s: %m", mount_slave); + goto finish; + } + + /* Second, we mount the source file or directory to a directory inside of our MS_SLAVE playground. */ + mount_tmp = strjoina(mount_slave, "/mount"); + if (S_ISDIR(st.st_mode)) + r = mkdir_errno_wrapper(mount_tmp, 0700); + else + r = touch(mount_tmp); + if (r < 0) { + sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount point %s: %m", mount_tmp); + goto finish; + } + + mount_tmp_created = true; + + if (mount(chased_src, mount_tmp, NULL, MS_BIND, NULL) < 0) { + r = sd_bus_error_set_errnof(error, errno, "Failed to mount %s: %m", chased_src); + goto finish; + } + + mount_tmp_mounted = true; + + /* Third, we remount the new bind mount read-only if requested. */ + if (read_only) + if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) { + r = sd_bus_error_set_errnof(error, errno, "Failed to remount read-only %s: %m", mount_tmp); + goto finish; + } + + /* Fourth, we move the new bind mount into the propagation directory. This way it will appear there read-only + * right-away. */ + + mount_outside = strjoina("/run/systemd/nspawn/propagate/", m->name, "/XXXXXX"); + if (S_ISDIR(st.st_mode)) + r = mkdtemp(mount_outside) ? 0 : -errno; + else { + r = mkostemp_safe(mount_outside); + safe_close(r); + } + if (r < 0) { + sd_bus_error_set_errnof(error, errno, "Cannot create propagation file or directory %s: %m", mount_outside); + goto finish; + } + + mount_outside_created = true; + + if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) { + r = sd_bus_error_set_errnof(error, errno, "Failed to move %s to %s: %m", mount_tmp, mount_outside); + goto finish; + } + + mount_outside_mounted = true; + mount_tmp_mounted = false; + + if (S_ISDIR(st.st_mode)) + (void) rmdir(mount_tmp); + else + (void) unlink(mount_tmp); + mount_tmp_created = false; + + (void) umount(mount_slave); + mount_slave_mounted = false; + + (void) rmdir(mount_slave); + mount_slave_created = false; + + if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) { + r = sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); + goto finish; + } + + r = safe_fork("(sd-bindmnt)", FORK_RESET_SIGNALS, &child); + if (r < 0) { + sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); + goto finish; + } + if (r == 0) { + const char *mount_inside; + int mntfd; + const char *q; + + errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]); + + q = procfs_file_alloca(m->leader, "ns/mnt"); + mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (mntfd < 0) { + r = log_error_errno(errno, "Failed to open mount namespace of leader: %m"); + goto child_fail; + } + + if (setns(mntfd, CLONE_NEWNS) < 0) { + r = log_error_errno(errno, "Failed to join namespace of leader: %m"); + goto child_fail; + } + + if (make_file_or_directory) { + if (S_ISDIR(st.st_mode)) + (void) mkdir_p(dest, 0755); + else { + (void) mkdir_parents(dest, 0755); + safe_close(open(dest, O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600)); + } + } + + /* Fifth, move the mount to the right place inside */ + mount_inside = strjoina("/run/systemd/nspawn/incoming/", basename(mount_outside)); + if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) { + r = log_error_errno(errno, "Failed to mount: %m"); + goto child_fail; + } + + _exit(EXIT_SUCCESS); + + child_fail: + (void) write(errno_pipe_fd[1], &r, sizeof(r)); + errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); + + _exit(EXIT_FAILURE); + } + + errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); + + r = wait_for_terminate_and_check("(sd-bindmnt)", child, 0); + if (r < 0) { + r = sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m"); + goto finish; + } + if (r != EXIT_SUCCESS) { + if (read(errno_pipe_fd[0], &r, sizeof(r)) == sizeof(r)) + r = sd_bus_error_set_errnof(error, r, "Failed to mount: %m"); + else + r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child failed."); + goto finish; + } + + r = sd_bus_reply_method_return(message, NULL); + +finish: + if (mount_outside_mounted) + (void) umount(mount_outside); + if (mount_outside_created) { + if (S_ISDIR(st.st_mode)) + (void) rmdir(mount_outside); + else + (void) unlink(mount_outside); + } + + if (mount_tmp_mounted) + (void) umount(mount_tmp); + if (mount_tmp_created) { + if (S_ISDIR(st.st_mode)) + (void) rmdir(mount_tmp); + else + (void) unlink(mount_tmp); + } + + if (mount_slave_mounted) + (void) umount(mount_slave); + if (mount_slave_created) + (void) rmdir(mount_slave); + + return r; +} + +int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *src, *dest, *host_path, *container_path, *host_basename, *container_basename, *container_dirname; + _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; + CopyFlags copy_flags = COPY_REFLINK|COPY_MERGE; + _cleanup_close_ int hostfd = -1; + Machine *m = userdata; + bool copy_from; + pid_t child; + uid_t uid_shift; + char *t; + int r; + + assert(message); + assert(m); + + if (m->manager->n_operations >= OPERATIONS_MAX) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing copies."); + + if (m->class != MACHINE_CONTAINER) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines."); + + r = sd_bus_message_read(message, "ss", &src, &dest); + if (r < 0) + return r; + + if (!path_is_absolute(src)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute."); + + if (isempty(dest)) + dest = src; + else if (!path_is_absolute(dest)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute."); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-machines", + NULL, + false, + UID_INVALID, + &m->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = machine_get_uid_shift(m, &uid_shift); + if (r < 0) + return r; + + copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom"); + + if (copy_from) { + container_path = src; + host_path = dest; + } else { + host_path = src; + container_path = dest; + } + + host_basename = basename(host_path); + + container_basename = basename(container_path); + t = strdupa(container_path); + container_dirname = dirname(t); + + hostfd = open_parent(host_path, O_CLOEXEC, 0); + if (hostfd < 0) + return sd_bus_error_set_errnof(error, hostfd, "Failed to open host directory %s: %m", host_path); + + if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) + return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); + + r = safe_fork("(sd-copy)", FORK_RESET_SIGNALS, &child); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); + if (r == 0) { + int containerfd; + const char *q; + int mntfd; + + errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]); + + q = procfs_file_alloca(m->leader, "ns/mnt"); + mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (mntfd < 0) { + r = log_error_errno(errno, "Failed to open mount namespace of leader: %m"); + goto child_fail; + } + + if (setns(mntfd, CLONE_NEWNS) < 0) { + r = log_error_errno(errno, "Failed to join namespace of leader: %m"); + goto child_fail; + } + + containerfd = open(container_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY); + if (containerfd < 0) { + r = log_error_errno(errno, "Failed to open destination directory: %m"); + goto child_fail; + } + + /* Run the actual copy operation. Note that when an UID shift is set we'll either clamp the UID/GID to + * 0 or to the actual UID shift depending on the direction we copy. If no UID shift is set we'll copy + * the UID/GIDs as they are. */ + if (copy_from) + r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, uid_shift == 0 ? UID_INVALID : 0, uid_shift == 0 ? GID_INVALID : 0, copy_flags); + else + r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, uid_shift == 0 ? UID_INVALID : uid_shift, uid_shift == 0 ? GID_INVALID : uid_shift, copy_flags); + + hostfd = safe_close(hostfd); + containerfd = safe_close(containerfd); + + if (r < 0) { + r = log_error_errno(r, "Failed to copy tree: %m"); + goto child_fail; + } + + _exit(EXIT_SUCCESS); + + child_fail: + (void) write(errno_pipe_fd[1], &r, sizeof(r)); + _exit(EXIT_FAILURE); + } + + errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); + + /* Copying might take a while, hence install a watch on the child, and return */ + + r = operation_new(m->manager, m, child, message, errno_pipe_fd[0], NULL); + if (r < 0) { + (void) sigkill_wait(child); + return r; + } + errno_pipe_fd[0] = -1; + + return 1; +} + +int bus_machine_method_open_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_close_ int fd = -1; + Machine *m = userdata; + int r; + + assert(message); + assert(m); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-machines", + NULL, + false, + UID_INVALID, + &m->manager->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + switch (m->class) { + + case MACHINE_HOST: + fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (fd < 0) + return -errno; + + break; + + case MACHINE_CONTAINER: { + _cleanup_close_ int mntns_fd = -1, root_fd = -1; + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + pid_t child; + + r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd); + if (r < 0) + return r; + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0) + return -errno; + + r = namespace_fork("(sd-openrootns)", "(sd-openroot)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG, + -1, mntns_fd, -1, -1, root_fd, &child); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); + if (r == 0) { + _cleanup_close_ int dfd = -1; + + pair[0] = safe_close(pair[0]); + + dfd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (dfd < 0) + _exit(EXIT_FAILURE); + + r = send_one_fd(pair[1], dfd, 0); + dfd = safe_close(dfd); + if (r < 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + r = wait_for_terminate_and_check("(sd-openrootns)", child, 0); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m"); + if (r != EXIT_SUCCESS) + return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally."); + + fd = receive_one_fd(pair[0], MSG_DONTWAIT); + if (fd < 0) + return fd; + + break; + } + + default: + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening the root directory is only supported on container machines."); + } + + return sd_bus_reply_method_return(message, "h", fd); +} + +int bus_machine_method_get_uid_shift(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Machine *m = userdata; + uid_t shift = 0; + int r; + + assert(message); + assert(m); + + /* You wonder why this is a method and not a property? Well, properties are not supposed to return errors, but + * we kinda have to for this. */ + + if (m->class == MACHINE_HOST) + return sd_bus_reply_method_return(message, "u", UINT32_C(0)); + + if (m->class != MACHINE_CONTAINER) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "UID/GID shift may only be determined for container machines."); + + r = machine_get_uid_shift(m, &shift); + if (r == -ENXIO) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Machine %s uses a complex UID/GID mapping, cannot determine shift", m->name); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "u", (uint32_t) shift); +} + +const sd_bus_vtable machine_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Id", "ay", bus_property_get_id128, offsetof(Machine, id), SD_BUS_VTABLE_PROPERTY_CONST), + BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Unit", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NetworkInterfaces", "ai", property_get_netif, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0), + SD_BUS_METHOD("Terminate", NULL, NULL, bus_machine_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Kill", "si", NULL, bus_machine_method_kill, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetAddresses", NULL, "a(iay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_machine_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUIDShift", NULL, "u", bus_machine_method_get_uid_shift, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("OpenPTY", NULL, "hs", bus_machine_method_open_pty, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("OpenLogin", NULL, "hs", bus_machine_method_open_login, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("OpenShell", "ssasas", "hs", bus_machine_method_open_shell, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("BindMount", "ssbb", NULL, bus_machine_method_bind_mount, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CopyFrom", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CopyTo", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("OpenRootDirectory", NULL, "h", bus_machine_method_open_root_directory, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END +}; + +int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + Machine *machine; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + if (streq(path, "/org/freedesktop/machine1/machine/self")) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + sd_bus_message *message; + pid_t pid; + + message = sd_bus_get_current_message(bus); + if (!message) + return 0; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + + r = manager_get_machine_by_pid(m, pid, &machine); + if (r <= 0) + return 0; + } else { + _cleanup_free_ char *e = NULL; + const char *p; + + p = startswith(path, "/org/freedesktop/machine1/machine/"); + if (!p) + return 0; + + e = bus_label_unescape(p); + if (!e) + return -ENOMEM; + + machine = hashmap_get(m->machines, e); + if (!machine) + return 0; + } + + *found = machine; + return 1; +} + +char *machine_bus_path(Machine *m) { + _cleanup_free_ char *e = NULL; + + assert(m); + + e = bus_label_escape(m->name); + if (!e) + return NULL; + + return strjoin("/org/freedesktop/machine1/machine/", e); +} + +int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Machine *machine = NULL; + Manager *m = userdata; + Iterator i; + int r; + + assert(bus); + assert(path); + assert(nodes); + + HASHMAP_FOREACH(machine, m->machines, i) { + char *p; + + p = machine_bus_path(machine); + if (!p) + return -ENOMEM; + + r = strv_consume(&l, p); + if (r < 0) + return r; + } + + *nodes = TAKE_PTR(l); + + return 1; +} + +int machine_send_signal(Machine *m, bool new_machine) { + _cleanup_free_ char *p = NULL; + + assert(m); + + p = machine_bus_path(m); + if (!p) + return -ENOMEM; + + return sd_bus_emit_signal( + m->manager->bus, + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + new_machine ? "MachineNew" : "MachineRemoved", + "so", m->name, p); +} + +int machine_send_create_reply(Machine *m, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL; + _cleanup_free_ char *p = NULL; + + assert(m); + + if (!m->create_message) + return 0; + + c = TAKE_PTR(m->create_message); + + if (error) + return sd_bus_reply_method_error(c, error); + + /* Update the machine state file before we notify the client + * about the result. */ + machine_save(m); + + p = machine_bus_path(m); + if (!p) + return -ENOMEM; + + return sd_bus_reply_method_return(c, "o", p); +} diff --git a/src/machine/machine-dbus.h b/src/machine/machine-dbus.h new file mode 100644 index 00000000..d9f3c59c --- /dev/null +++ b/src/machine/machine-dbus.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "machine.h" + +extern const sd_bus_vtable machine_vtable[]; + +char *machine_bus_path(Machine *s); +int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); + +int bus_machine_method_unregister(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_open_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_machine_method_get_uid_shift(sd_bus_message *message, void *userdata, sd_bus_error *error); + +int machine_send_signal(Machine *m, bool new_machine); +int machine_send_create_reply(Machine *m, sd_bus_error *error); diff --git a/src/machine/machine.c b/src/machine/machine.c new file mode 100644 index 00000000..efe327f3 --- /dev/null +++ b/src/machine/machine.c @@ -0,0 +1,772 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "env-file.h" +#include "errno-util.h" +#include "escape.h" +#include "extract-word.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "hashmap.h" +#include "machine-dbus.h" +#include "machine.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "serialize.h" +#include "special.h" +#include "stdio-util.h" +#include "string-table.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "unit-name.h" +#include "user-util.h" +#include "util.h" + +Machine* machine_new(Manager *manager, MachineClass class, const char *name) { + Machine *m; + + assert(manager); + assert(class < _MACHINE_CLASS_MAX); + assert(name); + + /* Passing class == _MACHINE_CLASS_INVALID here is fine. It + * means as much as "we don't know yet", and that we'll figure + * it out later when loading the state file. */ + + m = new0(Machine, 1); + if (!m) + return NULL; + + m->name = strdup(name); + if (!m->name) + goto fail; + + if (class != MACHINE_HOST) { + m->state_file = path_join("/run/systemd/machines", m->name); + if (!m->state_file) + goto fail; + } + + m->class = class; + + if (hashmap_put(manager->machines, m->name, m) < 0) + goto fail; + + m->manager = manager; + + return m; + +fail: + free(m->state_file); + free(m->name); + return mfree(m); +} + +Machine* machine_free(Machine *m) { + if (!m) + return NULL; + + while (m->operations) + operation_free(m->operations); + + if (m->in_gc_queue) + LIST_REMOVE(gc_queue, m->manager->machine_gc_queue, m); + + machine_release_unit(m); + + free(m->scope_job); + + (void) hashmap_remove(m->manager->machines, m->name); + + if (m->manager->host_machine == m) + m->manager->host_machine = NULL; + + if (m->leader > 0) + (void) hashmap_remove_value(m->manager->machine_leaders, PID_TO_PTR(m->leader), m); + + sd_bus_message_unref(m->create_message); + + free(m->name); + free(m->state_file); + free(m->service); + free(m->root_directory); + free(m->netif); + return mfree(m); +} + +int machine_save(Machine *m) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(m); + + if (!m->state_file) + return 0; + + if (!m->started) + return 0; + + r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, MKDIR_WARN_MODE); + if (r < 0) + goto fail; + + r = fopen_temporary(m->state_file, &f, &temp_path); + if (r < 0) + goto fail; + + (void) fchmod(fileno(f), 0644); + + fprintf(f, + "# This is private data. Do not parse.\n" + "NAME=%s\n", + m->name); + + if (m->unit) { + _cleanup_free_ char *escaped; + + escaped = cescape(m->unit); + if (!escaped) { + r = -ENOMEM; + goto fail; + } + + fprintf(f, "SCOPE=%s\n", escaped); /* We continue to call this "SCOPE=" because it is internal only, and we want to stay compatible with old files */ + } + + if (m->scope_job) + fprintf(f, "SCOPE_JOB=%s\n", m->scope_job); + + if (m->service) { + _cleanup_free_ char *escaped; + + escaped = cescape(m->service); + if (!escaped) { + r = -ENOMEM; + goto fail; + } + fprintf(f, "SERVICE=%s\n", escaped); + } + + if (m->root_directory) { + _cleanup_free_ char *escaped; + + escaped = cescape(m->root_directory); + if (!escaped) { + r = -ENOMEM; + goto fail; + } + fprintf(f, "ROOT=%s\n", escaped); + } + + if (!sd_id128_is_null(m->id)) + fprintf(f, "ID=" SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(m->id)); + + if (m->leader != 0) + fprintf(f, "LEADER="PID_FMT"\n", m->leader); + + if (m->class != _MACHINE_CLASS_INVALID) + fprintf(f, "CLASS=%s\n", machine_class_to_string(m->class)); + + if (dual_timestamp_is_set(&m->timestamp)) + fprintf(f, + "REALTIME="USEC_FMT"\n" + "MONOTONIC="USEC_FMT"\n", + m->timestamp.realtime, + m->timestamp.monotonic); + + if (m->n_netif > 0) { + size_t i; + + fputs("NETIF=", f); + + for (i = 0; i < m->n_netif; i++) { + if (i != 0) + fputc(' ', f); + + fprintf(f, "%i", m->netif[i]); + } + + fputc('\n', f); + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, m->state_file) < 0) { + r = -errno; + goto fail; + } + + if (m->unit) { + char *sl; + + /* Create a symlink from the unit name to the machine + * name, so that we can quickly find the machine for + * each given unit. Ignore error. */ + sl = strjoina("/run/systemd/machines/unit:", m->unit); + (void) symlink(m->name, sl); + } + + return 0; + +fail: + (void) unlink(m->state_file); + + if (temp_path) + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save machine data %s: %m", m->state_file); +} + +static void machine_unlink(Machine *m) { + assert(m); + + if (m->unit) { + char *sl; + + sl = strjoina("/run/systemd/machines/unit:", m->unit); + (void) unlink(sl); + } + + if (m->state_file) + (void) unlink(m->state_file); +} + +int machine_load(Machine *m) { + _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *id = NULL, *leader = NULL, *class = NULL, *netif = NULL; + int r; + + assert(m); + + if (!m->state_file) + return 0; + + r = parse_env_file(NULL, m->state_file, + "SCOPE", &m->unit, + "SCOPE_JOB", &m->scope_job, + "SERVICE", &m->service, + "ROOT", &m->root_directory, + "ID", &id, + "LEADER", &leader, + "CLASS", &class, + "REALTIME", &realtime, + "MONOTONIC", &monotonic, + "NETIF", &netif); + if (r < 0) { + if (r == -ENOENT) + return 0; + + return log_error_errno(r, "Failed to read %s: %m", m->state_file); + } + + if (id) + sd_id128_from_string(id, &m->id); + + if (leader) + parse_pid(leader, &m->leader); + + if (class) { + MachineClass c; + + c = machine_class_from_string(class); + if (c >= 0) + m->class = c; + } + + if (realtime) + (void) deserialize_usec(realtime, &m->timestamp.realtime); + if (monotonic) + (void) deserialize_usec(monotonic, &m->timestamp.monotonic); + + if (netif) { + size_t allocated = 0, nr = 0; + const char *p; + int *ni = NULL; + + p = netif; + for (;;) { + _cleanup_free_ char *word = NULL; + int ifi; + + r = extract_first_word(&p, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_warning_errno(r, "Failed to parse NETIF: %s", netif); + break; + } + + if (parse_ifindex(word, &ifi) < 0) + continue; + + if (!GREEDY_REALLOC(ni, allocated, nr+1)) { + free(ni); + return log_oom(); + } + + ni[nr++] = ifi; + } + + free(m->netif); + m->netif = ni; + m->n_netif = nr; + } + + return r; +} + +static int machine_start_scope( + Machine *machine, + sd_bus_message *more_properties, + sd_bus_error *error) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_free_ char *escaped = NULL, *unit = NULL; + const char *description; + int r; + + assert(machine); + assert(machine->leader > 0); + assert(!machine->unit); + + escaped = unit_name_escape(machine->name); + if (!escaped) + return log_oom(); + + unit = strjoin("machine-", escaped, ".scope"); + if (!unit) + return log_oom(); + + r = sd_bus_message_new_method_call( + machine->manager->bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "ss", unit, "fail"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "(sv)", "Slice", "s", SPECIAL_MACHINE_SLICE); + if (r < 0) + return r; + + description = strjoina(machine->class == MACHINE_VM ? "Virtual Machine " : "Container ", machine->name); + r = sd_bus_message_append(m, "(sv)", "Description", "s", description); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)", + "PIDs", "au", 1, machine->leader, + "Delegate", "b", 1, + "CollectMode", "s", "inactive-or-failed", + "AddRef", "b", 1, + "TasksMax", "t", UINT64_C(16384)); + if (r < 0) + return r; + + if (more_properties) { + r = sd_bus_message_copy(m, more_properties, true); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "a(sa(sv))", 0); + if (r < 0) + return r; + + r = sd_bus_call(NULL, m, 0, error, &reply); + if (r < 0) + return r; + + machine->unit = TAKE_PTR(unit); + machine->referenced = true; + + const char *job; + r = sd_bus_message_read(reply, "o", &job); + if (r < 0) + return r; + + return free_and_strdup(&machine->scope_job, job); +} + +static int machine_ensure_scope(Machine *m, sd_bus_message *properties, sd_bus_error *error) { + int r; + + assert(m); + assert(m->class != MACHINE_HOST); + + if (!m->unit) { + r = machine_start_scope(m, properties, error); + if (r < 0) + return log_error_errno(r, "Failed to start machine scope: %s", bus_error_message(error, r)); + } + + assert(m->unit); + hashmap_put(m->manager->machine_units, m->unit, m); + + return 0; +} + +int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) { + int r; + + assert(m); + + if (!IN_SET(m->class, MACHINE_CONTAINER, MACHINE_VM)) + return -EOPNOTSUPP; + + if (m->started) + return 0; + + r = hashmap_put(m->manager->machine_leaders, PID_TO_PTR(m->leader), m); + if (r < 0) + return r; + + /* Create cgroup */ + r = machine_ensure_scope(m, properties, error); + if (r < 0) + return r; + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_MACHINE_START_STR, + "NAME=%s", m->name, + "LEADER="PID_FMT, m->leader, + LOG_MESSAGE("New machine %s.", m->name)); + + if (!dual_timestamp_is_set(&m->timestamp)) + dual_timestamp_get(&m->timestamp); + + m->started = true; + + /* Save new machine data */ + machine_save(m); + + machine_send_signal(m, true); + (void) manager_enqueue_nscd_cache_flush(m->manager); + + return 0; +} + +int machine_stop(Machine *m) { + int r; + + assert(m); + + if (!IN_SET(m->class, MACHINE_CONTAINER, MACHINE_VM)) + return -EOPNOTSUPP; + + if (m->unit) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + char *job = NULL; + + r = manager_stop_unit(m->manager, m->unit, &error, &job); + if (r < 0) + return log_error_errno(r, "Failed to stop machine scope: %s", bus_error_message(&error, r)); + + free_and_replace(m->scope_job, job); + } + + m->stopping = true; + + machine_save(m); + (void) manager_enqueue_nscd_cache_flush(m->manager); + + return 0; +} + +int machine_finalize(Machine *m) { + assert(m); + + if (m->started) { + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_MACHINE_STOP_STR, + "NAME=%s", m->name, + "LEADER="PID_FMT, m->leader, + LOG_MESSAGE("Machine %s terminated.", m->name)); + + m->stopping = true; /* The machine is supposed to be going away. Don't try to kill it. */ + } + + machine_unlink(m); + machine_add_to_gc_queue(m); + + if (m->started) { + machine_send_signal(m, false); + m->started = false; + } + + return 0; +} + +bool machine_may_gc(Machine *m, bool drop_not_started) { + assert(m); + + if (m->class == MACHINE_HOST) + return false; + + if (drop_not_started && !m->started) + return true; + + if (m->scope_job && manager_job_is_active(m->manager, m->scope_job)) + return false; + + if (m->unit && manager_unit_is_active(m->manager, m->unit)) + return false; + + return true; +} + +void machine_add_to_gc_queue(Machine *m) { + assert(m); + + if (m->in_gc_queue) + return; + + LIST_PREPEND(gc_queue, m->manager->machine_gc_queue, m); + m->in_gc_queue = true; +} + +MachineState machine_get_state(Machine *s) { + assert(s); + + if (s->class == MACHINE_HOST) + return MACHINE_RUNNING; + + if (s->stopping) + return MACHINE_CLOSING; + + if (s->scope_job) + return MACHINE_OPENING; + + return MACHINE_RUNNING; +} + +int machine_kill(Machine *m, KillWho who, int signo) { + assert(m); + + if (!IN_SET(m->class, MACHINE_VM, MACHINE_CONTAINER)) + return -EOPNOTSUPP; + + if (!m->unit) + return -ESRCH; + + if (who == KILL_LEADER) { + /* If we shall simply kill the leader, do so directly */ + + if (kill(m->leader, signo) < 0) + return -errno; + + return 0; + } + + /* Otherwise, make PID 1 do it for us, for the entire cgroup */ + return manager_kill_unit(m->manager, m->unit, signo, NULL); +} + +int machine_openpt(Machine *m, int flags, char **ret_slave) { + assert(m); + + switch (m->class) { + + case MACHINE_HOST: + + return openpt_allocate(flags, ret_slave); + + case MACHINE_CONTAINER: + if (m->leader <= 0) + return -EINVAL; + + return openpt_allocate_in_namespace(m->leader, flags, ret_slave); + + default: + return -EOPNOTSUPP; + } +} + +int machine_open_terminal(Machine *m, const char *path, int mode) { + assert(m); + + switch (m->class) { + + case MACHINE_HOST: + return open_terminal(path, mode); + + case MACHINE_CONTAINER: + if (m->leader <= 0) + return -EINVAL; + + return open_terminal_in_namespace(m->leader, path, mode); + + default: + return -EOPNOTSUPP; + } +} + +void machine_release_unit(Machine *m) { + assert(m); + + if (!m->unit) + return; + + if (m->referenced) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + r = manager_unref_unit(m->manager, m->unit, &error); + if (r < 0) + log_warning_errno(r, "Failed to drop reference to machine scope, ignoring: %s", + bus_error_message(&error, r)); + + m->referenced = false; + } + + (void) hashmap_remove(m->manager->machine_units, m->unit); + m->unit = mfree(m->unit); +} + +int machine_get_uid_shift(Machine *m, uid_t *ret) { + char p[STRLEN("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1]; + uid_t uid_base, uid_shift, uid_range; + gid_t gid_base, gid_shift, gid_range; + _cleanup_fclose_ FILE *f = NULL; + int k, r; + + assert(m); + assert(ret); + + /* Return the base UID/GID of the specified machine. Note that this only works for containers with simple + * mappings. In most cases setups should be simple like this, and administrators should only care about the + * basic offset a container has relative to the host. This is what this function exposes. + * + * If we encounter any more complex mappings we politely refuse this with ENXIO. */ + + if (m->class == MACHINE_HOST) { + *ret = 0; + return 0; + } + + if (m->class != MACHINE_CONTAINER) + return -EOPNOTSUPP; + + xsprintf(p, "/proc/" PID_FMT "/uid_map", m->leader); + f = fopen(p, "re"); + if (!f) { + if (errno == ENOENT) { + /* If the file doesn't exist, user namespacing is off in the kernel, return a zero mapping hence. */ + *ret = 0; + return 0; + } + + return -errno; + } + + /* Read the first line. There's at least one. */ + errno = 0; + k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT "\n", &uid_base, &uid_shift, &uid_range); + if (k != 3) { + if (ferror(f)) + return errno_or_else(EIO); + + return -EBADMSG; + } + + /* Not a mapping starting at 0? Then it's a complex mapping we can't expose here. */ + if (uid_base != 0) + return -ENXIO; + /* Insist that at least the nobody user is mapped, everything else is weird, and hence complex, and we don't support it */ + if (uid_range < UID_NOBODY) + return -ENXIO; + + /* If there's more than one line, then we don't support this mapping. */ + r = safe_fgetc(f, NULL); + if (r < 0) + return r; + if (r != 0) /* Insist on EOF */ + return -ENXIO; + + fclose(f); + + xsprintf(p, "/proc/" PID_FMT "/gid_map", m->leader); + f = fopen(p, "re"); + if (!f) + return -errno; + + /* Read the first line. There's at least one. */ + errno = 0; + k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT "\n", &gid_base, &gid_shift, &gid_range); + if (k != 3) { + if (ferror(f)) + return errno_or_else(EIO); + + return -EBADMSG; + } + + /* If there's more than one line, then we don't support this file. */ + r = safe_fgetc(f, NULL); + if (r < 0) + return r; + if (r != 0) /* Insist on EOF */ + return -ENXIO; + + /* If the UID and GID mapping doesn't match, we don't support this mapping. */ + if (uid_base != (uid_t) gid_base) + return -ENXIO; + if (uid_shift != (uid_t) gid_shift) + return -ENXIO; + if (uid_range != (uid_t) gid_range) + return -ENXIO; + + *ret = uid_shift; + return 0; +} + +static const char* const machine_class_table[_MACHINE_CLASS_MAX] = { + [MACHINE_CONTAINER] = "container", + [MACHINE_VM] = "vm", + [MACHINE_HOST] = "host", +}; + +DEFINE_STRING_TABLE_LOOKUP(machine_class, MachineClass); + +static const char* const machine_state_table[_MACHINE_STATE_MAX] = { + [MACHINE_OPENING] = "opening", + [MACHINE_RUNNING] = "running", + [MACHINE_CLOSING] = "closing" +}; + +DEFINE_STRING_TABLE_LOOKUP(machine_state, MachineState); + +static const char* const kill_who_table[_KILL_WHO_MAX] = { + [KILL_LEADER] = "leader", + [KILL_ALL] = "all" +}; + +DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho); diff --git a/src/machine/machine.h b/src/machine/machine.h new file mode 100644 index 00000000..0a39e610 --- /dev/null +++ b/src/machine/machine.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Machine Machine; +typedef enum KillWho KillWho; + +#include "list.h" +#include "machined.h" +#include "operation.h" +#include "time-util.h" + +typedef enum MachineState { + MACHINE_OPENING, /* Machine is being registered */ + MACHINE_RUNNING, /* Machine is running */ + MACHINE_CLOSING, /* Machine is terminating */ + _MACHINE_STATE_MAX, + _MACHINE_STATE_INVALID = -1 +} MachineState; + +typedef enum MachineClass { + MACHINE_CONTAINER, + MACHINE_VM, + MACHINE_HOST, + _MACHINE_CLASS_MAX, + _MACHINE_CLASS_INVALID = -1 +} MachineClass; + +enum KillWho { + KILL_LEADER, + KILL_ALL, + _KILL_WHO_MAX, + _KILL_WHO_INVALID = -1 +}; + +struct Machine { + Manager *manager; + + char *name; + sd_id128_t id; + + MachineClass class; + + char *state_file; + char *service; + char *root_directory; + + char *unit; + char *scope_job; + + pid_t leader; + + dual_timestamp timestamp; + + bool in_gc_queue:1; + bool started:1; + bool stopping:1; + bool referenced:1; + + sd_bus_message *create_message; + + int *netif; + size_t n_netif; + + LIST_HEAD(Operation, operations); + + LIST_FIELDS(Machine, gc_queue); +}; + +Machine* machine_new(Manager *manager, MachineClass class, const char *name); +Machine* machine_free(Machine *m); +bool machine_may_gc(Machine *m, bool drop_not_started); +void machine_add_to_gc_queue(Machine *m); +int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error); +int machine_stop(Machine *m); +int machine_finalize(Machine *m); +int machine_save(Machine *m); +int machine_load(Machine *m); +int machine_kill(Machine *m, KillWho who, int signo); + +void machine_release_unit(Machine *m); + +MachineState machine_get_state(Machine *u); + +const char* machine_class_to_string(MachineClass t) _const_; +MachineClass machine_class_from_string(const char *s) _pure_; + +const char* machine_state_to_string(MachineState t) _const_; +MachineState machine_state_from_string(const char *s) _pure_; + +const char *kill_who_to_string(KillWho k) _const_; +KillWho kill_who_from_string(const char *s) _pure_; + +int machine_openpt(Machine *m, int flags, char **ret_slave); +int machine_open_terminal(Machine *m, const char *path, int mode); + +int machine_get_uid_shift(Machine *m, uid_t *ret); diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c new file mode 100644 index 00000000..4b02b081 --- /dev/null +++ b/src/machine/machinectl.c @@ -0,0 +1,3130 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-unit-procs.h" +#include "bus-unit-util.h" +#include "bus-util.h" +#include "bus-wait-for-jobs.h" +#include "cgroup-show.h" +#include "cgroup-util.h" +#include "copy.h" +#include "def.h" +#include "env-util.h" +#include "fd-util.h" +#include "format-table.h" +#include "hostname-util.h" +#include "import-util.h" +#include "locale-util.h" +#include "log.h" +#include "logs-show.h" +#include "macro.h" +#include "main-func.h" +#include "mkdir.h" +#include "nulstr-util.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "process-util.h" +#include "ptyfwd.h" +#include "rlimit-util.h" +#include "sigbus.h" +#include "signal-util.h" +#include "sort-util.h" +#include "spawn-ask-password-agent.h" +#include "spawn-polkit-agent.h" +#include "stdio-util.h" +#include "string-table.h" +#include "strv.h" +#include "terminal-util.h" +#include "unit-name.h" +#include "verbs.h" +#include "web-util.h" + +#define ALL_IP_ADDRESSES -1 + +static char **arg_property = NULL; +static bool arg_all = false; +static bool arg_value = false; +static bool arg_full = false; +static PagerFlags arg_pager_flags = 0; +static bool arg_legend = true; +static const char *arg_kill_who = NULL; +static int arg_signal = SIGTERM; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static const char *arg_host = NULL; +static bool arg_read_only = false; +static bool arg_mkdir = false; +static bool arg_quiet = false; +static bool arg_ask_password = true; +static unsigned arg_lines = 10; +static OutputMode arg_output = OUTPUT_SHORT; +static bool arg_force = false; +static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE; +static const char* arg_format = NULL; +static const char *arg_uid = NULL; +static char **arg_setenv = NULL; +static int arg_addrs = 1; + +STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep); + +static OutputFlags get_output_flags(void) { + return + arg_all * OUTPUT_SHOW_ALL | + (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH | + colors_enabled() * OUTPUT_COLOR | + !arg_quiet * OUTPUT_WARN_CUTOFF; +} + +static int call_get_os_release(sd_bus *bus, const char *method, const char *name, const char *query, ...) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *k, *v, *iter, **query_res = NULL; + size_t count = 0, awaited_args = 0; + va_list ap; + int r; + + assert(bus); + assert(name); + assert(query); + + NULSTR_FOREACH(iter, query) + awaited_args++; + query_res = newa0(const char *, awaited_args); + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + method, + &error, + &reply, "s", name); + if (r < 0) + return log_debug_errno(r, "Failed to call '%s()': %s", method, bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, 'a', "{ss}"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "{ss}", &k, &v)) > 0) { + count = 0; + NULSTR_FOREACH(iter, query) { + if (streq(k, iter)) { + query_res[count] = v; + break; + } + count++; + } + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + va_start(ap, query); + for (count = 0; count < awaited_args; count++) { + char *val, **out; + + out = va_arg(ap, char **); + assert(out); + if (query_res[count]) { + val = strdup(query_res[count]); + if (!val) { + va_end(ap); + return -ENOMEM; + } + *out = val; + } + } + va_end(ap); + + return 0; +} + +static int call_get_addresses(sd_bus *bus, const char *name, int ifi, const char *prefix, const char *prefix2, int n_addr, char **ret) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *addresses = NULL; + bool truncate = false; + unsigned n = 0; + int r; + + assert(bus); + assert(name); + assert(prefix); + assert(prefix2); + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetMachineAddresses", + NULL, + &reply, + "s", name); + if (r < 0) + return log_debug_errno(r, "Could not get addresses: %s", bus_error_message(&error, r)); + + addresses = strdup(prefix); + if (!addresses) + return log_oom(); + prefix = ""; + + r = sd_bus_message_enter_container(reply, 'a', "(iay)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) { + int family; + const void *a; + size_t sz; + char buf_ifi[DECIMAL_STR_MAX(int) + 2], buffer[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)]; + + r = sd_bus_message_read(reply, "i", &family); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_array(reply, 'y', &a, &sz); + if (r < 0) + return bus_log_parse_error(r); + + if (n_addr != 0) { + if (family == AF_INET6 && ifi > 0) + xsprintf(buf_ifi, "%%%i", ifi); + else + strcpy(buf_ifi, ""); + + if (!strextend(&addresses, prefix, inet_ntop(family, a, buffer, sizeof(buffer)), buf_ifi, NULL)) + return log_oom(); + } else + truncate = true; + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + prefix = prefix2; + + if (n_addr > 0) + n_addr --; + + n++; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + if (truncate) { + + if (!strextend(&addresses, special_glyph(SPECIAL_GLYPH_ELLIPSIS), NULL)) + return -ENOMEM; + + } + + *ret = TAKE_PTR(addresses); + return (int) n; +} + +static int show_table(Table *table, const char *word) { + int r; + + assert(table); + assert(word); + + if (table_get_rows(table) > 1 || OUTPUT_MODE_IS_JSON(arg_output)) { + r = table_set_sort(table, (size_t) 0, (size_t) -1); + if (r < 0) + return log_error_errno(r, "Failed to sort table: %m"); + + table_set_header(table, arg_legend); + + if (OUTPUT_MODE_IS_JSON(arg_output)) + r = table_print_json(table, NULL, output_mode_to_json_format_flags(arg_output) | JSON_FORMAT_COLOR_AUTO); + else + r = table_print(table, NULL); + if (r < 0) + return log_error_errno(r, "Failed to show table: %m"); + } + + if (arg_legend) { + if (table_get_rows(table) > 1) + printf("\n%zu %s listed.\n", table_get_rows(table) - 1, word); + else + printf("No %s.\n", word); + } + + return 0; +} + +static int list_machines(int argc, char *argv[], void *userdata) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + (void) pager_open(arg_pager_flags); + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "ListMachines", + &error, + &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Could not get machines: %s", bus_error_message(&error, r)); + + table = table_new("machine", "class", "service", "os", "version", "addresses"); + if (!table) + return log_oom(); + + r = sd_bus_message_enter_container(reply, 'a', "(ssso)"); + if (r < 0) + return bus_log_parse_error(r); + + for (;;) { + _cleanup_free_ char *os = NULL, *version_id = NULL, *addresses = NULL; + const char *name, *class, *service; + + r = sd_bus_message_read(reply, "(ssso)", &name, &class, &service, NULL); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + if (name[0] == '.' && !arg_all) + continue; + + (void) call_get_os_release( + bus, + "GetMachineOSRelease", + name, + "ID\0" + "VERSION_ID\0", + &os, + &version_id); + + (void) call_get_addresses( + bus, + name, + 0, + "", + " ", + arg_addrs, + &addresses); + + r = table_add_many(table, + TABLE_STRING, name, + TABLE_STRING, class, + TABLE_STRING, empty_to_dash(service), + TABLE_STRING, empty_to_dash(os), + TABLE_STRING, empty_to_dash(version_id), + TABLE_STRING, empty_to_dash(addresses)); + if (r < 0) + return log_error_errno(r, "Failed to add table row: %m"); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return show_table(table, "machines"); +} + +static int list_images(int argc, char *argv[], void *userdata) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + (void) pager_open(arg_pager_flags); + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "ListImages", + &error, + &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Could not get images: %s", bus_error_message(&error, r)); + + table = table_new("name", "type", "ro", "usage", "created", "modified"); + if (!table) + return log_oom(); + + (void) table_set_align_percent(table, TABLE_HEADER_CELL(3), 100); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssbttto)"); + if (r < 0) + return bus_log_parse_error(r); + + for (;;) { + uint64_t crtime, mtime, size; + const char *name, *type; + TableCell *cell; + bool ro_bool; + int ro_int; + + r = sd_bus_message_read(reply, "(ssbttto)", &name, &type, &ro_int, &crtime, &mtime, &size, NULL); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + if (name[0] == '.' && !arg_all) + continue; + + r = table_add_many(table, + TABLE_STRING, name, + TABLE_STRING, type); + if (r < 0) + return log_error_errno(r, "Failed to add table row: %m"); + + ro_bool = ro_int; + r = table_add_cell(table, &cell, TABLE_BOOLEAN, &ro_bool); + if (r < 0) + return log_error_errno(r, "Failed to add table cell: %m"); + + if (ro_bool) { + r = table_set_color(table, cell, ansi_highlight_red()); + if (r < 0) + return log_error_errno(r, "Failed to set table cell color: %m"); + } + + r = table_add_many(table, + TABLE_SIZE, size, + TABLE_TIMESTAMP, crtime, + TABLE_TIMESTAMP, mtime); + if (r < 0) + return log_error_errno(r, "Failed to add table row: %m"); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return show_table(table, "images"); +} + +static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) { + _cleanup_free_ char *cgroup = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + unsigned c; + + assert(bus); + assert(unit); + + r = show_cgroup_get_unit_path_and_warn(bus, unit, &cgroup); + if (r < 0) + return r; + + if (isempty(cgroup)) + return 0; + + c = columns(); + if (c > 18) + c -= 18; + else + c = 0; + + r = unit_show_processes(bus, unit, cgroup, "\t\t ", c, get_output_flags(), &error); + if (r == -EBADR) { + + if (arg_transport == BUS_TRANSPORT_REMOTE) + return 0; + + /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */ + + if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0) + return 0; + + show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, &leader, leader > 0, get_output_flags()); + } else if (r < 0) + return log_error_errno(r, "Failed to dump process list: %s", bus_error_message(&error, r)); + + return 0; +} + +static int print_os_release(sd_bus *bus, const char *method, const char *name, const char *prefix) { + _cleanup_free_ char *pretty = NULL; + int r; + + assert(bus); + assert(name); + assert(prefix); + + r = call_get_os_release(bus, method, name, "PRETTY_NAME\0", &pretty, NULL); + if (r < 0) + return r; + + if (pretty) + printf("%s%s\n", prefix, pretty); + + return 0; +} + +static int print_uid_shift(sd_bus *bus, const char *name) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + uint32_t shift; + int r; + + assert(bus); + assert(name); + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetMachineUIDShift", + &error, + &reply, + "s", name); + if (r < 0) + return log_debug_errno(r, "Failed to query UID/GID shift: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "u", &shift); + if (r < 0) + return r; + + if (shift == 0) /* Don't show trivial mappings */ + return 0; + + printf(" UID Shift: %" PRIu32 "\n", shift); + return 0; +} + +typedef struct MachineStatusInfo { + const char *name; + sd_id128_t id; + const char *class; + const char *service; + const char *unit; + const char *root_directory; + pid_t leader; + struct dual_timestamp timestamp; + int *netif; + size_t n_netif; +} MachineStatusInfo; + +static void machine_status_info_clear(MachineStatusInfo *info) { + if (info) { + free(info->netif); + zero(*info); + } +} + +static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) { + char since1[FORMAT_TIMESTAMP_RELATIVE_MAX]; + char since2[FORMAT_TIMESTAMP_MAX]; + _cleanup_free_ char *addresses = NULL; + const char *s1, *s2; + int ifi = -1; + + assert(bus); + assert(i); + + fputs(strna(i->name), stdout); + + if (!sd_id128_is_null(i->id)) + printf("(" SD_ID128_FORMAT_STR ")\n", SD_ID128_FORMAT_VAL(i->id)); + else + putchar('\n'); + + s1 = format_timestamp_relative(since1, sizeof(since1), i->timestamp.realtime); + s2 = format_timestamp(since2, sizeof(since2), i->timestamp.realtime); + + if (s1) + printf("\t Since: %s; %s\n", s2, s1); + else if (s2) + printf("\t Since: %s\n", s2); + + if (i->leader > 0) { + _cleanup_free_ char *t = NULL; + + printf("\t Leader: %u", (unsigned) i->leader); + + get_process_comm(i->leader, &t); + if (t) + printf(" (%s)", t); + + putchar('\n'); + } + + if (i->service) { + printf("\t Service: %s", i->service); + + if (i->class) + printf("; class %s", i->class); + + putchar('\n'); + } else if (i->class) + printf("\t Class: %s\n", i->class); + + if (i->root_directory) + printf("\t Root: %s\n", i->root_directory); + + if (i->n_netif > 0) { + size_t c; + + fputs("\t Iface:", stdout); + + for (c = 0; c < i->n_netif; c++) { + char name[IF_NAMESIZE+1]; + + if (format_ifname(i->netif[c], name)) { + fputc(' ', stdout); + fputs(name, stdout); + + if (ifi < 0) + ifi = i->netif[c]; + else + ifi = 0; + } else + printf(" %i", i->netif[c]); + } + + fputc('\n', stdout); + } + + if (call_get_addresses(bus, i->name, ifi, + "\t Address: ", "\n\t ", ALL_IP_ADDRESSES, + &addresses) > 0) { + fputs(addresses, stdout); + fputc('\n', stdout); + } + + print_os_release(bus, "GetMachineOSRelease", i->name, "\t OS: "); + + print_uid_shift(bus, i->name); + + if (i->unit) { + printf("\t Unit: %s\n", i->unit); + show_unit_cgroup(bus, i->unit, i->leader); + + if (arg_transport == BUS_TRANSPORT_LOCAL) + + show_journal_by_unit( + stdout, + i->unit, + arg_output, + 0, + i->timestamp.monotonic, + arg_lines, + 0, + get_output_flags() | OUTPUT_BEGIN_NEWLINE, + SD_JOURNAL_LOCAL_ONLY, + true, + NULL); + } +} + +static int map_netif(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + MachineStatusInfo *i = userdata; + size_t l; + const void *v; + int r; + + assert_cc(sizeof(int32_t) == sizeof(int)); + r = sd_bus_message_read_array(m, SD_BUS_TYPE_INT32, &v, &l); + if (r < 0) + return r; + if (r == 0) + return -EBADMSG; + + i->n_netif = l / sizeof(int32_t); + i->netif = memdup(v, l); + if (!i->netif) + return -ENOMEM; + + return 0; +} + +static int show_machine_info(const char *verb, sd_bus *bus, const char *path, bool *new_line) { + + static const struct bus_properties_map map[] = { + { "Name", "s", NULL, offsetof(MachineStatusInfo, name) }, + { "Class", "s", NULL, offsetof(MachineStatusInfo, class) }, + { "Service", "s", NULL, offsetof(MachineStatusInfo, service) }, + { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) }, + { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) }, + { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) }, + { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp.realtime) }, + { "TimestampMonotonic", "t", NULL, offsetof(MachineStatusInfo, timestamp.monotonic) }, + { "Id", "ay", bus_map_id128, offsetof(MachineStatusInfo, id) }, + { "NetworkInterfaces", "ai", map_netif, 0 }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(machine_status_info_clear) MachineStatusInfo info = {}; + int r; + + assert(verb); + assert(bus); + assert(path); + assert(new_line); + + r = bus_map_all_properties(bus, + "org.freedesktop.machine1", + path, + map, + 0, + &error, + &m, + &info); + if (r < 0) + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); + + if (*new_line) + printf("\n"); + *new_line = true; + + print_machine_status_info(bus, &info); + + return r; +} + +static int show_machine_properties(sd_bus *bus, const char *path, bool *new_line) { + int r; + + assert(bus); + assert(path); + assert(new_line); + + if (*new_line) + printf("\n"); + + *new_line = true; + + r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, NULL, arg_property, arg_value, arg_all, NULL); + if (r < 0) + log_error_errno(r, "Could not get properties: %m"); + + return r; +} + +static int show_machine(int argc, char *argv[], void *userdata) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + bool properties, new_line = false; + sd_bus *bus = userdata; + int r = 0, i; + + assert(bus); + + properties = !strstr(argv[0], "status"); + + (void) pager_open(arg_pager_flags); + + if (properties && argc <= 1) { + + /* If no argument is specified, inspect the manager + * itself */ + r = show_machine_properties(bus, "/org/freedesktop/machine1", &new_line); + if (r < 0) + return r; + } + + for (i = 1; i < argc; i++) { + const char *path = NULL; + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetMachine", + &error, + &reply, + "s", argv[i]); + if (r < 0) + return log_error_errno(r, "Could not get path to machine: %s", bus_error_message(&error, -r)); + + r = sd_bus_message_read(reply, "o", &path); + if (r < 0) + return bus_log_parse_error(r); + + if (properties) + r = show_machine_properties(bus, path, &new_line); + else + r = show_machine_info(argv[0], bus, path, &new_line); + } + + return r; +} + +static int print_image_hostname(sd_bus *bus, const char *name) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *hn; + int r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetImageHostname", + NULL, &reply, "s", name); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "s", &hn); + if (r < 0) + return r; + + if (!isempty(hn)) + printf("\tHostname: %s\n", hn); + + return 0; +} + +static int print_image_machine_id(sd_bus *bus, const char *name) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + sd_id128_t id = SD_ID128_NULL; + const void *p; + size_t size; + int r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetImageMachineID", + NULL, &reply, "s", name); + if (r < 0) + return r; + + r = sd_bus_message_read_array(reply, 'y', &p, &size); + if (r < 0) + return r; + + if (size == sizeof(sd_id128_t)) + memcpy(&id, p, size); + + if (!sd_id128_is_null(id)) + printf(" Machine ID: " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id)); + + return 0; +} + +static int print_image_machine_info(sd_bus *bus, const char *name) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetImageMachineInfo", + NULL, &reply, "s", name); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(reply, 'a', "{ss}"); + if (r < 0) + return r; + + for (;;) { + const char *p, *q; + + r = sd_bus_message_read(reply, "{ss}", &p, &q); + if (r < 0) + return r; + if (r == 0) + break; + + if (streq(p, "DEPLOYMENT")) + printf(" Deployment: %s\n", q); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return r; + + return 0; +} + +typedef struct ImageStatusInfo { + const char *name; + const char *path; + const char *type; + bool read_only; + usec_t crtime; + usec_t mtime; + uint64_t usage; + uint64_t limit; + uint64_t usage_exclusive; + uint64_t limit_exclusive; +} ImageStatusInfo; + +static void print_image_status_info(sd_bus *bus, ImageStatusInfo *i) { + char ts_relative[FORMAT_TIMESTAMP_RELATIVE_MAX]; + char ts_absolute[FORMAT_TIMESTAMP_MAX]; + char bs[FORMAT_BYTES_MAX]; + char bs_exclusive[FORMAT_BYTES_MAX]; + const char *s1, *s2, *s3, *s4; + + assert(bus); + assert(i); + + if (i->name) { + fputs(i->name, stdout); + putchar('\n'); + } + + if (i->type) + printf("\t Type: %s\n", i->type); + + if (i->path) + printf("\t Path: %s\n", i->path); + + (void) print_image_hostname(bus, i->name); + (void) print_image_machine_id(bus, i->name); + (void) print_image_machine_info(bus, i->name); + + print_os_release(bus, "GetImageOSRelease", i->name, "\t OS: "); + + printf("\t RO: %s%s%s\n", + i->read_only ? ansi_highlight_red() : "", + i->read_only ? "read-only" : "writable", + i->read_only ? ansi_normal() : ""); + + s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->crtime); + s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->crtime); + if (s1 && s2) + printf("\t Created: %s; %s\n", s2, s1); + else if (s2) + printf("\t Created: %s\n", s2); + + s1 = format_timestamp_relative(ts_relative, sizeof(ts_relative), i->mtime); + s2 = format_timestamp(ts_absolute, sizeof(ts_absolute), i->mtime); + if (s1 && s2) + printf("\tModified: %s; %s\n", s2, s1); + else if (s2) + printf("\tModified: %s\n", s2); + + s3 = format_bytes(bs, sizeof(bs), i->usage); + s4 = i->usage_exclusive != i->usage ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->usage_exclusive) : NULL; + if (s3 && s4) + printf("\t Usage: %s (exclusive: %s)\n", s3, s4); + else if (s3) + printf("\t Usage: %s\n", s3); + + s3 = format_bytes(bs, sizeof(bs), i->limit); + s4 = i->limit_exclusive != i->limit ? format_bytes(bs_exclusive, sizeof(bs_exclusive), i->limit_exclusive) : NULL; + if (s3 && s4) + printf("\t Limit: %s (exclusive: %s)\n", s3, s4); + else if (s3) + printf("\t Limit: %s\n", s3); +} + +static int show_image_info(sd_bus *bus, const char *path, bool *new_line) { + + static const struct bus_properties_map map[] = { + { "Name", "s", NULL, offsetof(ImageStatusInfo, name) }, + { "Path", "s", NULL, offsetof(ImageStatusInfo, path) }, + { "Type", "s", NULL, offsetof(ImageStatusInfo, type) }, + { "ReadOnly", "b", NULL, offsetof(ImageStatusInfo, read_only) }, + { "CreationTimestamp", "t", NULL, offsetof(ImageStatusInfo, crtime) }, + { "ModificationTimestamp", "t", NULL, offsetof(ImageStatusInfo, mtime) }, + { "Usage", "t", NULL, offsetof(ImageStatusInfo, usage) }, + { "Limit", "t", NULL, offsetof(ImageStatusInfo, limit) }, + { "UsageExclusive", "t", NULL, offsetof(ImageStatusInfo, usage_exclusive) }, + { "LimitExclusive", "t", NULL, offsetof(ImageStatusInfo, limit_exclusive) }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + ImageStatusInfo info = {}; + int r; + + assert(bus); + assert(path); + assert(new_line); + + r = bus_map_all_properties(bus, + "org.freedesktop.machine1", + path, + map, + BUS_MAP_BOOLEAN_AS_BOOL, + &error, + &m, + &info); + if (r < 0) + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); + + if (*new_line) + printf("\n"); + *new_line = true; + + print_image_status_info(bus, &info); + + return r; +} + +typedef struct PoolStatusInfo { + const char *path; + uint64_t usage; + uint64_t limit; +} PoolStatusInfo; + +static void print_pool_status_info(sd_bus *bus, PoolStatusInfo *i) { + char bs[FORMAT_BYTES_MAX], *s; + + if (i->path) + printf("\t Path: %s\n", i->path); + + s = format_bytes(bs, sizeof(bs), i->usage); + if (s) + printf("\t Usage: %s\n", s); + + s = format_bytes(bs, sizeof(bs), i->limit); + if (s) + printf("\t Limit: %s\n", s); +} + +static int show_pool_info(sd_bus *bus) { + + static const struct bus_properties_map map[] = { + { "PoolPath", "s", NULL, offsetof(PoolStatusInfo, path) }, + { "PoolUsage", "t", NULL, offsetof(PoolStatusInfo, usage) }, + { "PoolLimit", "t", NULL, offsetof(PoolStatusInfo, limit) }, + {} + }; + + PoolStatusInfo info = { + .usage = (uint64_t) -1, + .limit = (uint64_t) -1, + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + assert(bus); + + r = bus_map_all_properties(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + map, + 0, + &error, + &m, + &info); + if (r < 0) + return log_error_errno(r, "Could not get properties: %s", bus_error_message(&error, r)); + + print_pool_status_info(bus, &info); + + return 0; +} + +static int show_image_properties(sd_bus *bus, const char *path, bool *new_line) { + int r; + + assert(bus); + assert(path); + assert(new_line); + + if (*new_line) + printf("\n"); + + *new_line = true; + + r = bus_print_all_properties(bus, "org.freedesktop.machine1", path, NULL, arg_property, arg_value, arg_all, NULL); + if (r < 0) + log_error_errno(r, "Could not get properties: %m"); + + return r; +} + +static int show_image(int argc, char *argv[], void *userdata) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + bool properties, new_line = false; + sd_bus *bus = userdata; + int r = 0, i; + + assert(bus); + + properties = !strstr(argv[0], "status"); + + (void) pager_open(arg_pager_flags); + + if (argc <= 1) { + + /* If no argument is specified, inspect the manager + * itself */ + + if (properties) + r = show_image_properties(bus, "/org/freedesktop/machine1", &new_line); + else + r = show_pool_info(bus); + if (r < 0) + return r; + } + + for (i = 1; i < argc; i++) { + const char *path = NULL; + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetImage", + &error, + &reply, + "s", argv[i]); + if (r < 0) + return log_error_errno(r, "Could not get path to image: %s", bus_error_message(&error, -r)); + + r = sd_bus_message_read(reply, "o", &path); + if (r < 0) + return bus_log_parse_error(r); + + if (properties) + r = show_image_properties(bus, path, &new_line); + else + r = show_image_info(bus, path, &new_line); + } + + return r; +} + +static int kill_machine(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + if (!arg_kill_who) + arg_kill_who = "all"; + + for (i = 1; i < argc; i++) { + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "KillMachine", + &error, + NULL, + "ssi", argv[i], arg_kill_who, arg_signal); + if (r < 0) + return log_error_errno(r, "Could not kill machine: %s", bus_error_message(&error, -r)); + } + + return 0; +} + +static int reboot_machine(int argc, char *argv[], void *userdata) { + arg_kill_who = "leader"; + arg_signal = SIGINT; /* sysvinit + systemd */ + + return kill_machine(argc, argv, userdata); +} + +static int poweroff_machine(int argc, char *argv[], void *userdata) { + arg_kill_who = "leader"; + arg_signal = SIGRTMIN+4; /* only systemd */ + + return kill_machine(argc, argv, userdata); +} + +static int terminate_machine(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + for (i = 1; i < argc; i++) { + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "TerminateMachine", + &error, + NULL, + "s", argv[i]); + if (r < 0) + return log_error_errno(r, "Could not terminate machine: %s", bus_error_message(&error, -r)); + } + + return 0; +} + +static int copy_files(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *abs_host_path = NULL; + char *dest, *host_path, *container_path; + sd_bus *bus = userdata; + bool copy_from; + int r; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + copy_from = streq(argv[0], "copy-from"); + dest = argv[3] ?: argv[2]; + host_path = copy_from ? dest : argv[2]; + container_path = copy_from ? argv[2] : dest; + + if (!path_is_absolute(host_path)) { + r = path_make_absolute_cwd(host_path, &abs_host_path); + if (r < 0) + return log_error_errno(r, "Failed to make path absolute: %m"); + + host_path = abs_host_path; + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + copy_from ? "CopyFromMachine" : "CopyToMachine"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append( + m, + "sss", + argv[1], + copy_from ? container_path : host_path, + copy_from ? host_path : container_path); + if (r < 0) + return bus_log_create_error(r); + + /* This is a slow operation, hence turn off any method call timeouts */ + r = sd_bus_call(bus, m, USEC_INFINITY, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to copy: %s", bus_error_message(&error, r)); + + return 0; +} + +static int bind_mount(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "BindMountMachine", + &error, + NULL, + "sssbb", + argv[1], + argv[2], + argv[3], + arg_read_only, + arg_mkdir); + if (r < 0) + return log_error_errno(r, "Failed to bind mount: %s", bus_error_message(&error, -r)); + + return 0; +} + +static int on_machine_removed(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + PTYForward ** forward = (PTYForward**) userdata; + int r; + + assert(m); + assert(forward); + + if (*forward) { + /* If the forwarder is already initialized, tell it to + * exit on the next vhangup(), so that we still flush + * out what might be queued and exit then. */ + + r = pty_forward_set_ignore_vhangup(*forward, false); + if (r >= 0) + return 0; + + log_error_errno(r, "Failed to set ignore_vhangup flag: %m"); + } + + /* On error, or when the forwarder is not initialized yet, quit immediately */ + sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), EXIT_FAILURE); + return 0; +} + +static int process_forward(sd_event *event, PTYForward **forward, int master, PTYForwardFlags flags, const char *name) { + char last_char = 0; + bool machine_died; + int r; + + assert(event); + assert(master >= 0); + assert(name); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); + + if (!arg_quiet) { + if (streq(name, ".host")) + log_info("Connected to the local host. Press ^] three times within 1s to exit session."); + else + log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", name); + } + + (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); + (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); + + r = pty_forward_new(event, master, flags, forward); + if (r < 0) + return log_error_errno(r, "Failed to create PTY forwarder: %m"); + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + pty_forward_get_last_char(*forward, &last_char); + + machine_died = + (flags & PTY_FORWARD_IGNORE_VHANGUP) && + pty_forward_get_ignore_vhangup(*forward) == 0; + + *forward = pty_forward_free(*forward); + + if (last_char != '\n') + fputc('\n', stdout); + + if (!arg_quiet) { + if (machine_died) + log_info("Machine %s terminated.", name); + else if (streq(name, ".host")) + log_info("Connection to the local host terminated."); + else + log_info("Connection to machine %s terminated.", name); + } + + return 0; +} + +static int parse_machine_uid(const char *spec, const char **machine, char **uid) { + /* + * Whatever is specified in the spec takes priority over global arguments. + */ + char *_uid = NULL; + const char *_machine = NULL; + + if (spec) { + const char *at; + + at = strchr(spec, '@'); + if (at) { + if (at == spec) + /* Do the same as ssh and refuse "@host". */ + return -EINVAL; + + _machine = at + 1; + _uid = strndup(spec, at - spec); + if (!_uid) + return -ENOMEM; + } else + _machine = spec; + }; + + if (arg_uid && !_uid) { + _uid = strdup(arg_uid); + if (!_uid) + return -ENOMEM; + } + + *uid = _uid; + *machine = isempty(_machine) ? ".host" : _machine; + return 0; +} + +static int login_machine(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(pty_forward_freep) PTYForward *forward = NULL; + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + int master = -1, r; + sd_bus *bus = userdata; + const char *match, *machine; + + assert(bus); + + if (!strv_isempty(arg_setenv) || arg_uid) { + log_error("--setenv= and --uid= are not supported for 'login'. Use 'shell' instead."); + return -EINVAL; + } + + if (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) { + log_error("Login only supported on local machines."); + return -EOPNOTSUPP; + } + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to get event loop: %m"); + + r = sd_bus_attach_event(bus, event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + machine = argc < 2 || isempty(argv[1]) ? ".host" : argv[1]; + + match = strjoina("type='signal'," + "sender='org.freedesktop.machine1'," + "path='/org/freedesktop/machine1',", + "interface='org.freedesktop.machine1.Manager'," + "member='MachineRemoved'," + "arg0='", machine, "'"); + + r = sd_bus_add_match_async(bus, &slot, match, on_machine_removed, NULL, &forward); + if (r < 0) + return log_error_errno(r, "Failed to request machine removal match: %m"); + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "OpenMachineLogin", + &error, + &reply, + "s", machine); + if (r < 0) + return log_error_errno(r, "Failed to get login PTY: %s", bus_error_message(&error, -r)); + + r = sd_bus_message_read(reply, "hs", &master, NULL); + if (r < 0) + return bus_log_parse_error(r); + + return process_forward(event, &forward, master, PTY_FORWARD_IGNORE_VHANGUP, machine); +} + +static int shell_machine(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(pty_forward_freep) PTYForward *forward = NULL; + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + int master = -1, r; + sd_bus *bus = userdata; + const char *match, *machine, *path; + _cleanup_free_ char *uid = NULL; + + assert(bus); + + if (!IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) { + log_error("Shell only supported on local machines."); + return -EOPNOTSUPP; + } + + /* Pass $TERM to shell session, if not explicitly specified. */ + if (!strv_find_prefix(arg_setenv, "TERM=")) { + const char *t; + + t = strv_find_prefix(environ, "TERM="); + if (t) { + if (strv_extend(&arg_setenv, t) < 0) + return log_oom(); + } + } + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to get event loop: %m"); + + r = sd_bus_attach_event(bus, event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + r = parse_machine_uid(argc >= 2 ? argv[1] : NULL, &machine, &uid); + if (r < 0) + return log_error_errno(r, "Failed to parse machine specification: %m"); + + match = strjoina("type='signal'," + "sender='org.freedesktop.machine1'," + "path='/org/freedesktop/machine1',", + "interface='org.freedesktop.machine1.Manager'," + "member='MachineRemoved'," + "arg0='", machine, "'"); + + r = sd_bus_add_match_async(bus, &slot, match, on_machine_removed, NULL, &forward); + if (r < 0) + return log_error_errno(r, "Failed to request machine removal match: %m"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "OpenMachineShell"); + if (r < 0) + return bus_log_create_error(r); + + path = argc < 3 || isempty(argv[2]) ? NULL : argv[2]; + + r = sd_bus_message_append(m, "sss", machine, uid, path); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, strv_length(argv) <= 3 ? NULL : argv + 2); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, arg_setenv); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to get shell PTY: %s", bus_error_message(&error, -r)); + + r = sd_bus_message_read(reply, "hs", &master, NULL); + if (r < 0) + return bus_log_parse_error(r); + + return process_forward(event, &forward, master, 0, machine); +} + +static int remove_image(int argc, char *argv[], void *userdata) { + sd_bus *bus = userdata; + int r, i; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + for (i = 1; i < argc; i++) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "RemoveImage"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", argv[i]); + if (r < 0) + return bus_log_create_error(r); + + /* This is a slow operation, hence turn off any method call timeouts */ + r = sd_bus_call(bus, m, USEC_INFINITY, &error, NULL); + if (r < 0) + return log_error_errno(r, "Could not remove image: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int rename_image(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "RenameImage", + &error, + NULL, + "ss", argv[1], argv[2]); + if (r < 0) + return log_error_errno(r, "Could not rename image: %s", bus_error_message(&error, -r)); + + return 0; +} + +static int clone_image(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "CloneImage"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "ssb", argv[1], argv[2], arg_read_only); + if (r < 0) + return bus_log_create_error(r); + + /* This is a slow operation, hence turn off any method call timeouts */ + r = sd_bus_call(bus, m, USEC_INFINITY, &error, NULL); + if (r < 0) + return log_error_errno(r, "Could not clone image: %s", bus_error_message(&error, r)); + + return 0; +} + +static int read_only_image(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int b = true, r; + + assert(bus); + + if (argc > 2) { + b = parse_boolean(argv[2]); + if (b < 0) { + log_error("Failed to parse boolean argument: %s", argv[2]); + return -EINVAL; + } + } + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "MarkImageReadOnly", + &error, + NULL, + "sb", argv[1], b); + if (r < 0) + return log_error_errno(r, "Could not mark image read-only: %s", bus_error_message(&error, -r)); + + return 0; +} + +static int image_exists(sd_bus *bus, const char *name) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + assert(name); + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetImage", + &error, + NULL, + "s", name); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_IMAGE)) + return 0; + + return log_error_errno(r, "Failed to check whether image %s exists: %s", name, bus_error_message(&error, -r)); + } + + return 1; +} + +static int make_service_name(const char *name, char **ret) { + int r; + + assert(name); + assert(ret); + + if (!machine_name_is_valid(name)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid machine name %s.", name); + + r = unit_name_build("systemd-nspawn", name, ".service", ret); + if (r < 0) + return log_error_errno(r, "Failed to build unit name: %m"); + + return 0; +} + +static int start_machine(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + ask_password_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_oom(); + + for (i = 1; i < argc; i++) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *unit = NULL; + const char *object; + + r = make_service_name(argv[i], &unit); + if (r < 0) + return r; + + r = image_exists(bus, argv[i]); + if (r < 0) + return r; + if (r == 0) { + log_error("Machine image '%s' does not exist.", argv[i]); + return -ENXIO; + } + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + &error, + &reply, + "ss", unit, "fail"); + if (r < 0) + return log_error_errno(r, "Failed to start unit: %s", bus_error_message(&error, -r)); + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_add(w, object); + if (r < 0) + return log_oom(); + } + + r = bus_wait_for_jobs(w, arg_quiet, NULL); + if (r < 0) + return r; + + return 0; +} + +static int enable_machine(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + const char *method = NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + method = streq(argv[0], "enable") ? "EnableUnitFiles" : "DisableUnitFiles"; + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + method); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return bus_log_create_error(r); + + for (i = 1; i < argc; i++) { + _cleanup_free_ char *unit = NULL; + + r = make_service_name(argv[i], &unit); + if (r < 0) + return r; + + r = image_exists(bus, argv[i]); + if (r < 0) + return r; + if (r == 0) { + log_error("Machine image '%s' does not exist.", argv[i]); + return -ENXIO; + } + + r = sd_bus_message_append(m, "s", unit); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + if (streq(argv[0], "enable")) + r = sd_bus_message_append(m, "bb", false, false); + else + r = sd_bus_message_append(m, "b", false); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to enable or disable unit: %s", bus_error_message(&error, -r)); + + if (streq(argv[0], "enable")) { + r = sd_bus_message_read(reply, "b", NULL); + if (r < 0) + return bus_log_parse_error(r); + } + + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes); + if (r < 0) + goto finish; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Reload", + &error, + NULL, + NULL); + if (r < 0) { + log_error("Failed to reload daemon: %s", bus_error_message(&error, -r)); + goto finish; + } + + r = 0; + +finish: + unit_file_changes_free(changes, n_changes); + + return r; +} + +static int match_log_message(sd_bus_message *m, void *userdata, sd_bus_error *error) { + const char **our_path = userdata, *line; + unsigned priority; + int r; + + assert(m); + assert(our_path); + + r = sd_bus_message_read(m, "us", &priority, &line); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + if (!streq_ptr(*our_path, sd_bus_message_get_path(m))) + return 0; + + if (arg_quiet && LOG_PRI(priority) >= LOG_INFO) + return 0; + + log_full(priority, "%s", line); + return 0; +} + +static int match_transfer_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + const char **our_path = userdata, *path, *result; + uint32_t id; + int r; + + assert(m); + assert(our_path); + + r = sd_bus_message_read(m, "uos", &id, &path, &result); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + if (!streq_ptr(*our_path, path)) + return 0; + + sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), !streq_ptr(result, "done")); + return 0; +} + +static int transfer_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + assert(s); + assert(si); + + if (!arg_quiet) + log_info("Continuing download in the background. Use \"machinectl cancel-transfer %" PRIu32 "\" to abort transfer.", PTR_TO_UINT32(userdata)); + + sd_event_exit(sd_event_source_get_event(s), EINTR); + return 0; +} + +static int transfer_image_common(sd_bus *bus, sd_bus_message *m) { + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot_job_removed = NULL, *slot_log_message = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_event_unrefp) sd_event* event = NULL; + const char *path = NULL; + uint32_t id; + int r; + + assert(bus); + assert(m); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to get event loop: %m"); + + r = sd_bus_attach_event(bus, event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + r = sd_bus_match_signal_async( + bus, + &slot_job_removed, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "TransferRemoved", + match_transfer_removed, NULL, &path); + if (r < 0) + return log_error_errno(r, "Failed to request match: %m"); + + r = sd_bus_match_signal_async( + bus, + &slot_log_message, + "org.freedesktop.import1", + NULL, + "org.freedesktop.import1.Transfer", + "LogMessage", + match_log_message, NULL, &path); + if (r < 0) + return log_error_errno(r, "Failed to request match: %m"); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to transfer image: %s", bus_error_message(&error, -r)); + + r = sd_bus_message_read(reply, "uo", &id, &path); + if (r < 0) + return bus_log_parse_error(r); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + + if (!arg_quiet) + log_info("Enqueued transfer job %u. Press C-c to continue download in background.", id); + + (void) sd_event_add_signal(event, NULL, SIGINT, transfer_signal_handler, UINT32_TO_PTR(id)); + (void) sd_event_add_signal(event, NULL, SIGTERM, transfer_signal_handler, UINT32_TO_PTR(id)); + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + return -r; +} + +static int import_tar(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *ll = NULL, *fn = NULL; + const char *local = NULL, *path = NULL; + _cleanup_close_ int fd = -1; + sd_bus *bus = userdata; + int r; + + assert(bus); + + if (argc >= 2) + path = empty_or_dash_to_null(argv[1]); + + if (argc >= 3) + local = empty_or_dash_to_null(argv[2]); + else if (path) { + r = path_extract_filename(path, &fn); + if (r < 0) + return log_error_errno(r, "Cannot extract container name from filename: %m"); + + local = fn; + } + if (!local) { + log_error("Need either path or local name."); + return -EINVAL; + } + + r = tar_strip_suffixes(local, &ll); + if (r < 0) + return log_oom(); + + local = ll; + + if (!machine_name_is_valid(local)) { + log_error("Local name %s is not a suitable machine name.", local); + return -EINVAL; + } + + if (path) { + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return log_error_errno(errno, "Failed to open %s: %m", path); + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "ImportTar"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append( + m, + "hsbb", + fd >= 0 ? fd : STDIN_FILENO, + local, + arg_force, + arg_read_only); + if (r < 0) + return bus_log_create_error(r); + + return transfer_image_common(bus, m); +} + +static int import_raw(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *ll = NULL, *fn = NULL; + const char *local = NULL, *path = NULL; + _cleanup_close_ int fd = -1; + sd_bus *bus = userdata; + int r; + + assert(bus); + + if (argc >= 2) + path = empty_or_dash_to_null(argv[1]); + + if (argc >= 3) + local = empty_or_dash_to_null(argv[2]); + else if (path) { + r = path_extract_filename(path, &fn); + if (r < 0) + return log_error_errno(r, "Cannot extract container name from filename: %m"); + + local = fn; + } + if (!local) { + log_error("Need either path or local name."); + return -EINVAL; + } + + r = raw_strip_suffixes(local, &ll); + if (r < 0) + return log_oom(); + + local = ll; + + if (!machine_name_is_valid(local)) { + log_error("Local name %s is not a suitable machine name.", local); + return -EINVAL; + } + + if (path) { + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return log_error_errno(errno, "Failed to open %s: %m", path); + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "ImportRaw"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append( + m, + "hsbb", + fd >= 0 ? fd : STDIN_FILENO, + local, + arg_force, + arg_read_only); + if (r < 0) + return bus_log_create_error(r); + + return transfer_image_common(bus, m); +} + +static int import_fs(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + const char *local = NULL, *path = NULL; + _cleanup_free_ char *fn = NULL; + _cleanup_close_ int fd = -1; + sd_bus *bus = userdata; + int r; + + assert(bus); + + if (argc >= 2) + path = empty_or_dash_to_null(argv[1]); + + if (argc >= 3) + local = empty_or_dash_to_null(argv[2]); + else if (path) { + r = path_extract_filename(path, &fn); + if (r < 0) + return log_error_errno(r, "Cannot extract container name from filename: %m"); + + local = fn; + } + if (!local) { + log_error("Need either path or local name."); + return -EINVAL; + } + + if (!machine_name_is_valid(local)) { + log_error("Local name %s is not a suitable machine name.", local); + return -EINVAL; + } + + if (path) { + fd = open(path, O_DIRECTORY|O_RDONLY|O_CLOEXEC); + if (fd < 0) + return log_error_errno(errno, "Failed to open directory '%s': %m", path); + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "ImportFileSystem"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append( + m, + "hsbb", + fd >= 0 ? fd : STDIN_FILENO, + local, + arg_force, + arg_read_only); + if (r < 0) + return bus_log_create_error(r); + + return transfer_image_common(bus, m); +} + +static void determine_compression_from_filename(const char *p) { + if (arg_format) + return; + + if (!p) + return; + + if (endswith(p, ".xz")) + arg_format = "xz"; + else if (endswith(p, ".gz")) + arg_format = "gzip"; + else if (endswith(p, ".bz2")) + arg_format = "bzip2"; +} + +static int export_tar(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_close_ int fd = -1; + const char *local = NULL, *path = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + local = argv[1]; + if (!machine_name_is_valid(local)) { + log_error("Machine name %s is not valid.", local); + return -EINVAL; + } + + if (argc >= 3) + path = argv[2]; + path = empty_or_dash_to_null(path); + + if (path) { + determine_compression_from_filename(path); + + fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666); + if (fd < 0) + return log_error_errno(errno, "Failed to open %s: %m", path); + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "ExportTar"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append( + m, + "shs", + local, + fd >= 0 ? fd : STDOUT_FILENO, + arg_format); + if (r < 0) + return bus_log_create_error(r); + + return transfer_image_common(bus, m); +} + +static int export_raw(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_close_ int fd = -1; + const char *local = NULL, *path = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + local = argv[1]; + if (!machine_name_is_valid(local)) { + log_error("Machine name %s is not valid.", local); + return -EINVAL; + } + + if (argc >= 3) + path = argv[2]; + path = empty_or_dash_to_null(path); + + if (path) { + determine_compression_from_filename(path); + + fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC|O_NOCTTY, 0666); + if (fd < 0) + return log_error_errno(errno, "Failed to open %s: %m", path); + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "ExportRaw"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append( + m, + "shs", + local, + fd >= 0 ? fd : STDOUT_FILENO, + arg_format); + if (r < 0) + return bus_log_create_error(r); + + return transfer_image_common(bus, m); +} + +static int pull_tar(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *l = NULL, *ll = NULL; + const char *local, *remote; + sd_bus *bus = userdata; + int r; + + assert(bus); + + remote = argv[1]; + if (!http_url_is_valid(remote)) { + log_error("URL '%s' is not valid.", remote); + return -EINVAL; + } + + if (argc >= 3) + local = argv[2]; + else { + r = import_url_last_component(remote, &l); + if (r < 0) + return log_error_errno(r, "Failed to get final component of URL: %m"); + + local = l; + } + + local = empty_or_dash_to_null(local); + + if (local) { + r = tar_strip_suffixes(local, &ll); + if (r < 0) + return log_oom(); + + local = ll; + + if (!machine_name_is_valid(local)) { + log_error("Local name %s is not a suitable machine name.", local); + return -EINVAL; + } + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "PullTar"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append( + m, + "sssb", + remote, + local, + import_verify_to_string(arg_verify), + arg_force); + if (r < 0) + return bus_log_create_error(r); + + return transfer_image_common(bus, m); +} + +static int pull_raw(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *l = NULL, *ll = NULL; + const char *local, *remote; + sd_bus *bus = userdata; + int r; + + assert(bus); + + remote = argv[1]; + if (!http_url_is_valid(remote)) { + log_error("URL '%s' is not valid.", remote); + return -EINVAL; + } + + if (argc >= 3) + local = argv[2]; + else { + r = import_url_last_component(remote, &l); + if (r < 0) + return log_error_errno(r, "Failed to get final component of URL: %m"); + + local = l; + } + + local = empty_or_dash_to_null(local); + + if (local) { + r = raw_strip_suffixes(local, &ll); + if (r < 0) + return log_oom(); + + local = ll; + + if (!machine_name_is_valid(local)) { + log_error("Local name %s is not a suitable machine name.", local); + return -EINVAL; + } + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "PullRaw"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append( + m, + "sssb", + remote, + local, + import_verify_to_string(arg_verify), + arg_force); + if (r < 0) + return bus_log_create_error(r); + + return transfer_image_common(bus, m); +} + +typedef struct TransferInfo { + uint32_t id; + const char *type; + const char *remote; + const char *local; + double progress; +} TransferInfo; + +static int compare_transfer_info(const TransferInfo *a, const TransferInfo *b) { + return strcmp(a->local, b->local); +} + +static int list_transfers(int argc, char *argv[], void *userdata) { + size_t max_type = STRLEN("TYPE"), max_local = STRLEN("LOCAL"), max_remote = STRLEN("REMOTE"); + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ TransferInfo *transfers = NULL; + size_t n_transfers = 0, n_allocated = 0, j; + const char *type, *remote, *local; + sd_bus *bus = userdata; + uint32_t id, max_id = 0; + double progress; + int r; + + (void) pager_open(arg_pager_flags); + + r = sd_bus_call_method(bus, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "ListTransfers", + &error, + &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Could not get transfers: %s", bus_error_message(&error, -r)); + + r = sd_bus_message_enter_container(reply, 'a', "(usssdo)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "(usssdo)", &id, &type, &remote, &local, &progress, NULL)) > 0) { + size_t l; + + if (!GREEDY_REALLOC(transfers, n_allocated, n_transfers + 1)) + return log_oom(); + + transfers[n_transfers].id = id; + transfers[n_transfers].type = type; + transfers[n_transfers].remote = remote; + transfers[n_transfers].local = local; + transfers[n_transfers].progress = progress; + + l = strlen(type); + if (l > max_type) + max_type = l; + + l = strlen(remote); + if (l > max_remote) + max_remote = l; + + l = strlen(local); + if (l > max_local) + max_local = l; + + if (id > max_id) + max_id = id; + + n_transfers++; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + typesafe_qsort(transfers, n_transfers, compare_transfer_info); + + if (arg_legend && n_transfers > 0) + printf("%-*s %-*s %-*s %-*s %-*s\n", + (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), "ID", + (int) 7, "PERCENT", + (int) max_type, "TYPE", + (int) max_local, "LOCAL", + (int) max_remote, "REMOTE"); + + for (j = 0; j < n_transfers; j++) + + if (transfers[j].progress < 0) + printf("%*" PRIu32 " %*s %-*s %-*s %-*s\n", + (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id, + (int) 7, "n/a", + (int) max_type, transfers[j].type, + (int) max_local, transfers[j].local, + (int) max_remote, transfers[j].remote); + else + printf("%*" PRIu32 " %*u%% %-*s %-*s %-*s\n", + (int) MAX(2U, DECIMAL_STR_WIDTH(max_id)), transfers[j].id, + (int) 6, (unsigned) (transfers[j].progress * 100), + (int) max_type, transfers[j].type, + (int) max_local, transfers[j].local, + (int) max_remote, transfers[j].remote); + + if (arg_legend) { + if (n_transfers > 0) + printf("\n%zu transfers listed.\n", n_transfers); + else + printf("No transfers.\n"); + } + + return 0; +} + +static int cancel_transfer(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, i; + + assert(bus); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + for (i = 1; i < argc; i++) { + uint32_t id; + + r = safe_atou32(argv[i], &id); + if (r < 0) + return log_error_errno(r, "Failed to parse transfer id: %s", argv[i]); + + r = sd_bus_call_method( + bus, + "org.freedesktop.import1", + "/org/freedesktop/import1", + "org.freedesktop.import1.Manager", + "CancelTransfer", + &error, + NULL, + "u", id); + if (r < 0) + return log_error_errno(r, "Could not cancel transfer: %s", bus_error_message(&error, -r)); + } + + return 0; +} + +static int set_limit(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + uint64_t limit; + int r; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + if (STR_IN_SET(argv[argc-1], "-", "none", "infinity")) + limit = (uint64_t) -1; + else { + r = parse_size(argv[argc-1], 1024, &limit); + if (r < 0) + return log_error_errno(r, "Failed to parse size: %s", argv[argc-1]); + } + + if (argc > 2) + /* With two arguments changes the quota limit of the + * specified image */ + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "SetImageLimit", + &error, + NULL, + "st", argv[1], limit); + else + /* With one argument changes the pool quota limit */ + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "SetPoolLimit", + &error, + NULL, + "t", limit); + + if (r < 0) + return log_error_errno(r, "Could not set limit: %s", bus_error_message(&error, r)); + + return 0; +} + +static int clean_images(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + uint64_t usage, total = 0; + char fb[FORMAT_BYTES_MAX]; + sd_bus *bus = userdata; + const char *name; + unsigned c = 0; + int r; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "CleanPool"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", arg_all ? "all" : "hidden"); + if (r < 0) + return bus_log_create_error(r); + + /* This is a slow operation, hence permit a longer time for completion. */ + r = sd_bus_call(bus, m, USEC_INFINITY, &error, &reply); + if (r < 0) + return log_error_errno(r, "Could not clean pool: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, 'a', "(st)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "(st)", &name, &usage)) > 0) { + if (usage == UINT64_MAX) { + log_info("Removed image '%s'", name); + total = UINT64_MAX; + } else { + log_info("Removed image '%s'. Freed exclusive disk space: %s", + name, format_bytes(fb, sizeof(fb), usage)); + if (total != UINT64_MAX) + total += usage; + } + c++; + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + if (total == UINT64_MAX) + log_info("Removed %u images in total.", c); + else + log_info("Removed %u images in total. Total freed exclusive disk space: %s.", + c, format_bytes(fb, sizeof(fb), total)); + + return 0; +} + +static int help(int argc, char *argv[], void *userdata) { + _cleanup_free_ char *link = NULL; + int r; + + (void) pager_open(arg_pager_flags); + + r = terminal_urlify_man("machinectl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n\n" + "%sSend control commands to or query the virtual machine and container%s\n" + "%sregistration manager.%s\n" + "\nMachine Commands:\n" + " list List running VMs and containers\n" + " status NAME... Show VM/container details\n" + " show [NAME...] Show properties of one or more VMs/containers\n" + " start NAME... Start container as a service\n" + " login [NAME] Get a login prompt in a container or on the\n" + " local host\n" + " shell [[USER@]NAME [COMMAND...]]\n" + " Invoke a shell (or other command) in a container\n" + " or on the local host\n" + " enable NAME... Enable automatic container start at boot\n" + " disable NAME... Disable automatic container start at boot\n" + " poweroff NAME... Power off one or more containers\n" + " reboot NAME... Reboot one or more containers\n" + " terminate NAME... Terminate one or more VMs/containers\n" + " kill NAME... Send signal to processes of a VM/container\n" + " copy-to NAME PATH [PATH] Copy files from the host to a container\n" + " copy-from NAME PATH [PATH] Copy files from a container to the host\n" + " bind NAME PATH [PATH] Bind mount a path from the host into a container\n\n" + "Image Commands:\n" + " list-images Show available container and VM images\n" + " image-status [NAME...] Show image details\n" + " show-image [NAME...] Show properties of image\n" + " clone NAME NAME Clone an image\n" + " rename NAME NAME Rename an image\n" + " read-only NAME [BOOL] Mark or unmark image read-only\n" + " remove NAME... Remove an image\n" + " set-limit [NAME] BYTES Set image or pool size limit (disk quota)\n" + " clean Remove hidden (or all) images\n\n" + "Image Transfer Commands:\n" + " pull-tar URL [NAME] Download a TAR container image\n" + " pull-raw URL [NAME] Download a RAW container or VM image\n" + " import-tar FILE [NAME] Import a local TAR container image\n" + " import-raw FILE [NAME] Import a local RAW container or VM image\n" + " import-fs DIRECTORY [NAME] Import a local directory container image\n" + " export-tar NAME [FILE] Export a TAR container image locally\n" + " export-raw NAME [FILE] Export a RAW container or VM image locally\n" + " list-transfers Show list of downloads in progress\n" + " cancel-transfer Cancel a download\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --no-legend Do not show the headers and footers\n" + " --no-ask-password Do not ask for system passwords\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " -p --property=NAME Show only properties by this name\n" + " -q --quiet Suppress output\n" + " -a --all Show all properties, including empty ones\n" + " --value When showing properties, only print the value\n" + " -l --full Do not ellipsize output\n" + " --kill-who=WHO Who to send signal to\n" + " -s --signal=SIGNAL Which signal to send\n" + " --uid=USER Specify user ID to invoke shell as\n" + " -E --setenv=VAR=VALUE Add an environment variable for shell\n" + " --read-only Create read-only bind mount\n" + " --mkdir Create directory before bind mounting, if missing\n" + " -n --lines=INTEGER Number of journal entries to show\n" + " --max-addresses=INTEGER Number of internet addresses to show at most\n" + " -o --output=STRING Change journal output mode (short, short-precise,\n" + " short-iso, short-iso-precise, short-full,\n" + " short-monotonic, short-unix, verbose, export,\n" + " json, json-pretty, json-sse, json-seq, cat,\n" + " with-unit)\n" + " --verify=MODE Verification mode for downloaded images (no,\n" + " checksum, signature)\n" + " --force Download image even if already exists\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_PAGER, + ARG_NO_LEGEND, + ARG_VALUE, + ARG_KILL_WHO, + ARG_READ_ONLY, + ARG_MKDIR, + ARG_NO_ASK_PASSWORD, + ARG_VERIFY, + ARG_FORCE, + ARG_FORMAT, + ARG_UID, + ARG_NUMBER_IPS, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "property", required_argument, NULL, 'p' }, + { "all", no_argument, NULL, 'a' }, + { "value", no_argument, NULL, ARG_VALUE }, + { "full", no_argument, NULL, 'l' }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, + { "kill-who", required_argument, NULL, ARG_KILL_WHO }, + { "signal", required_argument, NULL, 's' }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "read-only", no_argument, NULL, ARG_READ_ONLY }, + { "mkdir", no_argument, NULL, ARG_MKDIR }, + { "quiet", no_argument, NULL, 'q' }, + { "lines", required_argument, NULL, 'n' }, + { "output", required_argument, NULL, 'o' }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "verify", required_argument, NULL, ARG_VERIFY }, + { "force", no_argument, NULL, ARG_FORCE }, + { "format", required_argument, NULL, ARG_FORMAT }, + { "uid", required_argument, NULL, ARG_UID }, + { "setenv", required_argument, NULL, 'E' }, + { "max-addresses", required_argument, NULL, ARG_NUMBER_IPS }, + {} + }; + + bool reorder = false; + int c, r, shell = -1; + + assert(argc >= 0); + assert(argv); + + for (;;) { + static const char option_string[] = "-hp:als:H:M:qn:o:E:"; + + c = getopt_long(argc, argv, option_string + reorder, options, NULL); + if (c < 0) + break; + + switch (c) { + + case 1: /* getopt_long() returns 1 if "-" was the first character of the option string, and a + * non-option argument was discovered. */ + + assert(!reorder); + + /* We generally are fine with the fact that getopt_long() reorders the command line, and looks + * for switches after the main verb. However, for "shell" we really don't want that, since we + * want that switches specified after the machine name are passed to the program to execute, + * and not processed by us. To make this possible, we'll first invoke getopt_long() with + * reordering disabled (i.e. with the "-" prefix in the option string), looking for the first + * non-option parameter. If it's the verb "shell" we remember its position and continue + * processing options. In this case, as soon as we hit the next non-option argument we found + * the machine name, and stop further processing. If the first non-option argument is any other + * verb than "shell" we switch to normal reordering mode and continue processing arguments + * normally. */ + + if (shell >= 0) { + /* If we already found the "shell" verb on the command line, and now found the next + * non-option argument, then this is the machine name and we should stop processing + * further arguments. */ + optind --; /* don't process this argument, go one step back */ + goto done; + } + if (streq(optarg, "shell")) + /* Remember the position of the "shell" verb, and continue processing normally. */ + shell = optind - 1; + else { + int saved_optind; + + /* OK, this is some other verb. In this case, turn on reordering again, and continue + * processing normally. */ + reorder = true; + + /* We changed the option string. getopt_long() only looks at it again if we invoke it + * at least once with a reset option index. Hence, let's reset the option index here, + * then invoke getopt_long() again (ignoring what it has to say, after all we most + * likely already processed it), and the bump the option index so that we read the + * intended argument again. */ + saved_optind = optind; + optind = 0; + (void) getopt_long(argc, argv, option_string + reorder, options, NULL); + optind = saved_optind - 1; /* go one step back, process this argument again */ + } + + break; + + case 'h': + return help(0, NULL, NULL); + + case ARG_VERSION: + return version(); + + case 'p': + r = strv_extend(&arg_property, optarg); + if (r < 0) + return log_oom(); + + /* If the user asked for a particular + * property, show it to him, even if it is + * empty. */ + arg_all = true; + break; + + case 'a': + arg_all = true; + break; + + case ARG_VALUE: + arg_value = true; + break; + + case 'l': + arg_full = true; + break; + + case 'n': + if (safe_atou(optarg, &arg_lines) < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse lines '%s'", optarg); + break; + + case 'o': + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX); + return 0; + } + + arg_output = output_mode_from_string(optarg); + if (arg_output < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown output '%s'.", optarg); + + if (OUTPUT_MODE_IS_JSON(arg_output)) + arg_legend = false; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_NO_LEGEND: + arg_legend = false; + break; + + case ARG_KILL_WHO: + arg_kill_who = optarg; + break; + + case 's': + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(signal, int, _NSIG); + return 0; + } + + arg_signal = signal_from_string(optarg); + if (arg_signal < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse signal string %s.", optarg); + break; + + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case ARG_READ_ONLY: + arg_read_only = true; + break; + + case ARG_MKDIR: + arg_mkdir = true; + break; + + case 'q': + arg_quiet = true; + break; + + case ARG_VERIFY: + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(import_verify, ImportVerify, _IMPORT_VERIFY_MAX); + return 0; + } + + arg_verify = import_verify_from_string(optarg); + if (arg_verify < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse --verify= setting: %s", optarg); + break; + + case ARG_FORCE: + arg_force = true; + break; + + case ARG_FORMAT: + if (!STR_IN_SET(optarg, "uncompressed", "xz", "gzip", "bzip2")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown format: %s", optarg); + + arg_format = optarg; + break; + + case ARG_UID: + arg_uid = optarg; + break; + + case 'E': + if (!env_assignment_is_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Environment assignment invalid: %s", optarg); + + r = strv_extend(&arg_setenv, optarg); + if (r < 0) + return log_oom(); + break; + + case ARG_NUMBER_IPS: + if (streq(optarg, "all")) + arg_addrs = ALL_IP_ADDRESSES; + else if (safe_atoi(optarg, &arg_addrs) < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid number of IPs"); + else if (arg_addrs < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Number of IPs cannot be negative"); + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + } + +done: + if (shell >= 0) { + char *t; + int i; + + /* We found the "shell" verb while processing the argument list. Since we turned off reordering of the + * argument list initially let's readjust it now, and move the "shell" verb to the back. */ + + optind -= 1; /* place the option index where the "shell" verb will be placed */ + + t = argv[shell]; + for (i = shell; i < optind; i++) + argv[i] = argv[i+1]; + argv[optind] = t; + } + + return 1; +} + +static int machinectl_main(int argc, char *argv[], sd_bus *bus) { + + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "list", VERB_ANY, 1, VERB_DEFAULT, list_machines }, + { "list-images", VERB_ANY, 1, 0, list_images }, + { "status", 2, VERB_ANY, 0, show_machine }, + { "image-status", VERB_ANY, VERB_ANY, 0, show_image }, + { "show", VERB_ANY, VERB_ANY, 0, show_machine }, + { "show-image", VERB_ANY, VERB_ANY, 0, show_image }, + { "terminate", 2, VERB_ANY, 0, terminate_machine }, + { "reboot", 2, VERB_ANY, 0, reboot_machine }, + { "poweroff", 2, VERB_ANY, 0, poweroff_machine }, + { "stop", 2, VERB_ANY, 0, poweroff_machine }, /* Convenience alias */ + { "kill", 2, VERB_ANY, 0, kill_machine }, + { "login", VERB_ANY, 2, 0, login_machine }, + { "shell", VERB_ANY, VERB_ANY, 0, shell_machine }, + { "bind", 3, 4, 0, bind_mount }, + { "copy-to", 3, 4, 0, copy_files }, + { "copy-from", 3, 4, 0, copy_files }, + { "remove", 2, VERB_ANY, 0, remove_image }, + { "rename", 3, 3, 0, rename_image }, + { "clone", 3, 3, 0, clone_image }, + { "read-only", 2, 3, 0, read_only_image }, + { "start", 2, VERB_ANY, 0, start_machine }, + { "enable", 2, VERB_ANY, 0, enable_machine }, + { "disable", 2, VERB_ANY, 0, enable_machine }, + { "import-tar", 2, 3, 0, import_tar }, + { "import-raw", 2, 3, 0, import_raw }, + { "import-fs", 2, 3, 0, import_fs }, + { "export-tar", 2, 3, 0, export_tar }, + { "export-raw", 2, 3, 0, export_raw }, + { "pull-tar", 2, 3, 0, pull_tar }, + { "pull-raw", 2, 3, 0, pull_raw }, + { "list-transfers", VERB_ANY, 1, 0, list_transfers }, + { "cancel-transfer", 2, VERB_ANY, 0, cancel_transfer }, + { "set-limit", 2, 3, 0, set_limit }, + { "clean", VERB_ANY, 1, 0, clean_images }, + {} + }; + + return dispatch_verb(argc, argv, verbs, bus); +} + +static int run(int argc, char *argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + setlocale(LC_ALL, ""); + log_show_color(true); + log_parse_environment(); + log_open(); + + /* The journal merging logic potentially needs a lot of fds. */ + (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); + + sigbus_install(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = bus_connect_transport(arg_transport, arg_host, false, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + (void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password); + + return machinectl_main(argc, argv, bus); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/machine/machined-core.c b/src/machine/machined-core.c new file mode 100644 index 00000000..6a404805 --- /dev/null +++ b/src/machine/machined-core.c @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "machined.h" +#include "nscd-flush.h" +#include "strv.h" + +static int on_nscd_cache_flush_event(sd_event_source *s, void *userdata) { + /* Let's ask glibc's nscd daemon to flush its caches. We request this for the three database machines may show + * up in: the hosts database (for resolvable machine names) and the user and group databases (for the user ns + * ranges). */ + + (void) nscd_flush_cache(STRV_MAKE("passwd", "group", "hosts")); + return 0; +} + +int manager_enqueue_nscd_cache_flush(Manager *m) { + int r; + + assert(m); + + if (!m->nscd_cache_flush_event) { + r = sd_event_add_defer(m->event, &m->nscd_cache_flush_event, on_nscd_cache_flush_event, m); + if (r < 0) + return log_error_errno(r, "Failed to allocate NSCD cache flush event: %m"); + + sd_event_source_set_description(m->nscd_cache_flush_event, "nscd-cache-flush"); + } + + r = sd_event_source_set_enabled(m->nscd_cache_flush_event, SD_EVENT_ONESHOT); + if (r < 0) { + m->nscd_cache_flush_event = sd_event_source_unref(m->nscd_cache_flush_event); + return log_error_errno(r, "Failed to enable NSCD cache flush event: %m"); + } + + return 0; +} diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c new file mode 100644 index 00000000..d0cc0767 --- /dev/null +++ b/src/machine/machined-dbus.c @@ -0,0 +1,1497 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "bus-common-errors.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "cgroup-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "hostname-util.h" +#include "image-dbus.h" +#include "io-util.h" +#include "machine-dbus.h" +#include "machine-image.h" +#include "machine-pool.h" +#include "machined.h" +#include "missing_capability.h" +#include "path-util.h" +#include "process-util.h" +#include "stdio-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "unit-name.h" +#include "user-util.h" + +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_pool_path, "s", "/var/lib/machines"); + +static int property_get_pool_usage( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_close_ int fd = -1; + uint64_t usage = (uint64_t) -1; + + assert(bus); + assert(reply); + + fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (fd >= 0) { + BtrfsQuotaInfo q; + + if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0) + usage = q.referenced; + } + + return sd_bus_message_append(reply, "t", usage); +} + +static int property_get_pool_limit( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_close_ int fd = -1; + uint64_t size = (uint64_t) -1; + + assert(bus); + assert(reply); + + fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (fd >= 0) { + BtrfsQuotaInfo q; + + if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0) + size = q.referenced_max; + } + + return sd_bus_message_append(reply, "t", size); +} + +static int method_get_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *p = NULL; + Manager *m = userdata; + Machine *machine; + const char *name; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + machine = hashmap_get(m->machines, name); + if (!machine) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); + + p = machine_bus_path(machine); + if (!p) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", p); +} + +static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *p = NULL; + Manager *m = userdata; + const char *name; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = image_find(IMAGE_MACHINE, name, NULL); + if (r == -ENOENT) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); + if (r < 0) + return r; + + p = image_bus_path(name); + if (!p) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", p); +} + +static int method_get_machine_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *p = NULL; + Manager *m = userdata; + Machine *machine = NULL; + pid_t pid; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(pid_t) == sizeof(uint32_t)); + + r = sd_bus_message_read(message, "u", &pid); + if (r < 0) + return r; + + if (pid < 0) + return -EINVAL; + + if (pid == 0) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_pid(creds, &pid); + if (r < 0) + return r; + } + + r = manager_get_machine_by_pid(m, pid, &machine); + if (r < 0) + return r; + if (!machine) + return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid); + + p = machine_bus_path(machine); + if (!p) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", p); +} + +static int method_list_machines(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *m = userdata; + Machine *machine; + Iterator i; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + r = sd_bus_message_open_container(reply, 'a', "(ssso)"); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + HASHMAP_FOREACH(machine, m->machines, i) { + _cleanup_free_ char *p = NULL; + + p = machine_bus_path(machine); + if (!p) + return -ENOMEM; + + r = sd_bus_message_append(reply, "(ssso)", + machine->name, + strempty(machine_class_to_string(machine->class)), + machine->service, + p); + if (r < 0) + return sd_bus_error_set_errno(error, r); + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, bool read_network, Machine **_m, sd_bus_error *error) { + const char *name, *service, *class, *root_directory; + const int32_t *netif = NULL; + MachineClass c; + uint32_t leader; + sd_id128_t id; + const void *v; + Machine *m; + size_t n, n_netif = 0; + int r; + + assert(manager); + assert(message); + assert(_m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + if (!machine_name_is_valid(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name"); + + r = sd_bus_message_read_array(message, 'y', &v, &n); + if (r < 0) + return r; + if (n == 0) + id = SD_ID128_NULL; + else if (n == 16) + memcpy(&id, v, n); + else + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter"); + + r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory); + if (r < 0) + return r; + + if (read_network) { + size_t i; + + r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif); + if (r < 0) + return r; + + n_netif /= sizeof(int32_t); + + for (i = 0; i < n_netif; i++) { + if (netif[i] <= 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]); + } + } + + if (isempty(class)) + c = _MACHINE_CLASS_INVALID; + else { + c = machine_class_from_string(class); + if (c < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter"); + } + + if (leader == 1) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID"); + + if (!isempty(root_directory) && !path_is_absolute(root_directory)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path"); + + if (leader == 0) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds); + if (r < 0) + return r; + + assert_cc(sizeof(uint32_t) == sizeof(pid_t)); + + r = sd_bus_creds_get_pid(creds, (pid_t*) &leader); + if (r < 0) + return r; + } + + if (hashmap_get(manager->machines, name)) + return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name); + + r = manager_add_machine(manager, name, &m); + if (r < 0) + return r; + + m->leader = leader; + m->class = c; + m->id = id; + + if (!isempty(service)) { + m->service = strdup(service); + if (!m->service) { + r = -ENOMEM; + goto fail; + } + } + + if (!isempty(root_directory)) { + m->root_directory = strdup(root_directory); + if (!m->root_directory) { + r = -ENOMEM; + goto fail; + } + } + + if (n_netif > 0) { + assert_cc(sizeof(int32_t) == sizeof(int)); + m->netif = memdup(netif, sizeof(int32_t) * n_netif); + if (!m->netif) { + r = -ENOMEM; + goto fail; + } + + m->n_netif = n_netif; + } + + *_m = m; + + return 1; + +fail: + machine_add_to_gc_queue(m); + return r; +} + +static int method_create_machine_internal(sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) { + Manager *manager = userdata; + Machine *m = NULL; + int r; + + assert(message); + assert(manager); + + r = method_create_or_register_machine(manager, message, read_network, &m, error); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(message, 'a', "(sv)"); + if (r < 0) + goto fail; + + r = machine_start(m, message, error); + if (r < 0) + goto fail; + + m->create_message = sd_bus_message_ref(message); + return 1; + +fail: + machine_add_to_gc_queue(m); + return r; +} + +static int method_create_machine_with_network(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_create_machine_internal(message, true, userdata, error); +} + +static int method_create_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_create_machine_internal(message, false, userdata, error); +} + +static int method_register_machine_internal(sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) { + Manager *manager = userdata; + _cleanup_free_ char *p = NULL; + Machine *m = NULL; + int r; + + assert(message); + assert(manager); + + r = method_create_or_register_machine(manager, message, read_network, &m, error); + if (r < 0) + return r; + + r = cg_pid_get_unit(m->leader, &m->unit); + if (r < 0) { + r = sd_bus_error_set_errnof(error, r, + "Failed to determine unit of process "PID_FMT" : %m", + m->leader); + goto fail; + } + + r = machine_start(m, NULL, error); + if (r < 0) + goto fail; + + p = machine_bus_path(m); + if (!p) { + r = -ENOMEM; + goto fail; + } + + return sd_bus_reply_method_return(message, "o", p); + +fail: + machine_add_to_gc_queue(m); + return r; +} + +static int method_register_machine_with_network(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_register_machine_internal(message, true, userdata, error); +} + +static int method_register_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return method_register_machine_internal(message, false, userdata, error); +} + +static int redirect_method_to_machine(sd_bus_message *message, Manager *m, sd_bus_error *error, sd_bus_message_handler_t method) { + Machine *machine; + const char *name; + int r; + + assert(message); + assert(m); + assert(method); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + machine = hashmap_get(m->machines, name); + if (!machine) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); + + return method(message, machine, error); +} + +static int method_unregister_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_unregister); +} + +static int method_terminate_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_terminate); +} + +static int method_kill_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_kill); +} + +static int method_get_machine_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_addresses); +} + +static int method_get_machine_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_os_release); +} + +static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_hashmap_free_ Hashmap *images = NULL; + Manager *m = userdata; + Image *image; + Iterator i; + int r; + + assert(message); + assert(m); + + images = hashmap_new(&image_hash_ops); + if (!images) + return -ENOMEM; + + r = image_discover(IMAGE_MACHINE, images); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(ssbttto)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(image, images, i) { + _cleanup_free_ char *p = NULL; + + p = image_bus_path(image->name); + if (!p) + return -ENOMEM; + + r = sd_bus_message_append(reply, "(ssbttto)", + image->name, + image_type_to_string(image->type), + image->read_only, + image->crtime, + image->mtime, + image->usage, + p); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_open_machine_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_pty); +} + +static int method_open_machine_login(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_login); +} + +static int method_open_machine_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_shell); +} + +static int method_bind_mount_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_bind_mount); +} + +static int method_copy_machine(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_copy); +} + +static int method_open_machine_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_open_root_directory); +} + +static int method_get_machine_uid_shift(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_machine(message, userdata, error, bus_machine_method_get_uid_shift); +} + +static int redirect_method_to_image(sd_bus_message *message, Manager *m, sd_bus_error *error, sd_bus_message_handler_t method) { + _cleanup_(image_unrefp) Image* i = NULL; + const char *name; + int r; + + assert(message); + assert(m); + assert(method); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + if (!image_name_is_valid(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name); + + r = image_find(IMAGE_MACHINE, name, &i); + if (r == -ENOENT) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); + if (r < 0) + return r; + + i->userdata = m; + return method(message, i, error); +} + +static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(message, userdata, error, bus_image_method_remove); +} + +static int method_rename_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(message, userdata, error, bus_image_method_rename); +} + +static int method_clone_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(message, userdata, error, bus_image_method_clone); +} + +static int method_mark_image_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(message, userdata, error, bus_image_method_mark_read_only); +} + +static int method_get_image_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(message, userdata, error, bus_image_method_get_hostname); +} + +static int method_get_image_machine_id(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(message, userdata, error, bus_image_method_get_machine_id); +} + +static int method_get_image_machine_info(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(message, userdata, error, bus_image_method_get_machine_info); +} + +static int method_get_image_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(message, userdata, error, bus_image_method_get_os_release); +} + +static int clean_pool_done(Operation *operation, int ret, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_fclose_ FILE *f = NULL; + bool success; + size_t n; + int r; + + assert(operation); + assert(operation->extra_fd >= 0); + + if (lseek(operation->extra_fd, 0, SEEK_SET) == (off_t) -1) + return -errno; + + f = fdopen(operation->extra_fd, "r"); + if (!f) + return -errno; + + operation->extra_fd = -1; + + /* The resulting temporary file starts with a boolean value that indicates success or not. */ + errno = 0; + n = fread(&success, 1, sizeof(success), f); + if (n != sizeof(success)) + return ret < 0 ? ret : errno_or_else(EIO); + + if (ret < 0) { + _cleanup_free_ char *name = NULL; + + /* The clean-up operation failed. In this case the resulting temporary file should contain a boolean + * set to false followed by the name of the failed image. Let's try to read this and use it for the + * error message. If we can't read it, don't mind, and return the naked error. */ + + if (success) /* The resulting temporary file could not be updated, ignore it. */ + return ret; + + r = read_nul_string(f, LONG_LINE_MAX, &name); + if (r <= 0) /* Same here... */ + return ret; + + return sd_bus_error_set_errnof(error, ret, "Failed to remove image %s: %m", name); + } + + assert(success); + + r = sd_bus_message_new_method_return(operation->message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(st)"); + if (r < 0) + return r; + + /* On success the resulting temporary file will contain a list of image names that were removed followed by + * their size on disk. Let's read that and turn it into a bus message. */ + for (;;) { + _cleanup_free_ char *name = NULL; + uint64_t size; + + r = read_nul_string(f, LONG_LINE_MAX, &name); + if (r < 0) + return r; + if (r == 0) /* reached the end */ + break; + + errno = 0; + n = fread(&size, 1, sizeof(size), f); + if (n != sizeof(size)) + return errno_or_else(EIO); + + r = sd_bus_message_append(reply, "(st)", name, size); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_error *error) { + enum { + REMOVE_ALL, + REMOVE_HIDDEN, + } mode; + + _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; + _cleanup_close_ int result_fd = -1; + Manager *m = userdata; + Operation *operation; + const char *mm; + pid_t child; + int r; + + assert(message); + + if (m->n_operations >= OPERATIONS_MAX) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations."); + + r = sd_bus_message_read(message, "s", &mm); + if (r < 0) + return r; + + if (streq(mm, "all")) + mode = REMOVE_ALL; + else if (streq(mm, "hidden")) + mode = REMOVE_HIDDEN; + else + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mode '%s'.", mm); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-machines", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) + return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); + + /* Create a temporary file we can dump information about deleted images into. We use a temporary file for this + * instead of a pipe or so, since this might grow quit large in theory and we don't want to process this + * continuously */ + result_fd = open_tmpfile_unlinkable(NULL, O_RDWR|O_CLOEXEC); + if (result_fd < 0) + return -errno; + + /* This might be a slow operation, run it asynchronously in a background process */ + r = safe_fork("(sd-clean)", FORK_RESET_SIGNALS, &child); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); + if (r == 0) { + _cleanup_hashmap_free_ Hashmap *images = NULL; + bool success = true; + Image *image; + Iterator i; + ssize_t l; + + errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]); + + images = hashmap_new(&image_hash_ops); + if (!images) { + r = -ENOMEM; + goto child_fail; + } + + r = image_discover(IMAGE_MACHINE, images); + if (r < 0) + goto child_fail; + + l = write(result_fd, &success, sizeof(success)); + if (l < 0) { + r = -errno; + goto child_fail; + } + + HASHMAP_FOREACH(image, images, i) { + + /* We can't remove vendor images (i.e. those in /usr) */ + if (IMAGE_IS_VENDOR(image)) + continue; + + if (IMAGE_IS_HOST(image)) + continue; + + if (mode == REMOVE_HIDDEN && !IMAGE_IS_HIDDEN(image)) + continue; + + r = image_remove(image); + if (r == -EBUSY) /* keep images that are currently being used. */ + continue; + if (r < 0) { + /* If the operation failed, let's override everything we wrote, and instead write there at which image we failed. */ + success = false; + (void) ftruncate(result_fd, 0); + (void) lseek(result_fd, 0, SEEK_SET); + (void) write(result_fd, &success, sizeof(success)); + (void) write(result_fd, image->name, strlen(image->name)+1); + goto child_fail; + } + + l = write(result_fd, image->name, strlen(image->name)+1); + if (l < 0) { + r = -errno; + goto child_fail; + } + + l = write(result_fd, &image->usage_exclusive, sizeof(image->usage_exclusive)); + if (l < 0) { + r = -errno; + goto child_fail; + } + } + + result_fd = safe_close(result_fd); + _exit(EXIT_SUCCESS); + + child_fail: + (void) write(errno_pipe_fd[1], &r, sizeof(r)); + _exit(EXIT_FAILURE); + } + + errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); + + /* The clean-up might take a while, hence install a watch on the child and return */ + + r = operation_new(m, NULL, child, message, errno_pipe_fd[0], &operation); + if (r < 0) { + (void) sigkill_wait(child); + return r; + } + + operation->extra_fd = result_fd; + operation->done = clean_pool_done; + + result_fd = -1; + errno_pipe_fd[0] = -1; + + return 1; +} + +static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + uint64_t limit; + int r; + + assert(message); + + r = sd_bus_message_read(message, "t", &limit); + if (r < 0) + return r; + if (!FILE_SIZE_VALID_OR_INFINITY(limit)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range"); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.machine1.manage-machines", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + /* Set up the machine directory if necessary */ + r = setup_machine_directory(error); + if (r < 0) + return r; + + (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit); + + r = btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit); + if (r == -ENOTTY) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs."); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m"); + + return sd_bus_reply_method_return(message, NULL); +} + +static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(message, userdata, error, bus_image_method_set_limit); +} + +static int method_map_from_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_fclose_ FILE *f = NULL; + Manager *m = userdata; + const char *name, *p; + Machine *machine; + uint32_t uid; + int r; + + r = sd_bus_message_read(message, "su", &name, &uid); + if (r < 0) + return r; + + if (!uid_is_valid(uid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid); + + machine = hashmap_get(m->machines, name); + if (!machine) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); + + if (machine->class != MACHINE_CONTAINER) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines."); + + p = procfs_file_alloca(machine->leader, "uid_map"); + f = fopen(p, "re"); + if (!f) + return -errno; + + for (;;) { + uid_t uid_base, uid_shift, uid_range, converted; + int k; + + errno = 0; + k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range); + if (k < 0 && feof(f)) + break; + if (k != 3) { + if (ferror(f)) + return errno_or_else(EIO); + + return -EIO; + } + + if (uid < uid_base || uid >= uid_base + uid_range) + continue; + + converted = uid - uid_base + uid_shift; + if (!uid_is_valid(converted)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid); + + return sd_bus_reply_method_return(message, "u", (uint32_t) converted); + } + + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching user mappings.", name); +} + +static int method_map_to_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + Machine *machine; + uid_t uid; + Iterator i; + int r; + + r = sd_bus_message_read(message, "u", &uid); + if (r < 0) + return r; + if (!uid_is_valid(uid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid); + if (uid < 0x10000) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "User " UID_FMT " belongs to host UID range", uid); + + HASHMAP_FOREACH(machine, m->machines, i) { + _cleanup_fclose_ FILE *f = NULL; + char p[STRLEN("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1]; + + if (machine->class != MACHINE_CONTAINER) + continue; + + xsprintf(p, "/proc/" UID_FMT "/uid_map", machine->leader); + f = fopen(p, "re"); + if (!f) { + log_warning_errno(errno, "Failed to open %s, ignoring,", p); + continue; + } + + for (;;) { + _cleanup_free_ char *o = NULL; + uid_t uid_base, uid_shift, uid_range, converted; + int k; + + errno = 0; + k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range); + if (k < 0 && feof(f)) + break; + if (k != 3) { + if (ferror(f)) + return errno_or_else(EIO); + + return -EIO; + } + + /* The private user namespace is disabled, ignoring. */ + if (uid_shift == 0) + continue; + + if (uid < uid_shift || uid >= uid_shift + uid_range) + continue; + + converted = (uid - uid_shift + uid_base); + if (!uid_is_valid(converted)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid); + + o = machine_bus_path(machine); + if (!o) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted); + } + } + + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "No matching user mapping for " UID_FMT ".", uid); +} + +static int method_map_from_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) { + _cleanup_fclose_ FILE *f = NULL; + Manager *m = groupdata; + const char *name, *p; + Machine *machine; + uint32_t gid; + int r; + + r = sd_bus_message_read(message, "su", &name, &gid); + if (r < 0) + return r; + + if (!gid_is_valid(gid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid); + + machine = hashmap_get(m->machines, name); + if (!machine) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name); + + if (machine->class != MACHINE_CONTAINER) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines."); + + p = procfs_file_alloca(machine->leader, "gid_map"); + f = fopen(p, "re"); + if (!f) + return -errno; + + for (;;) { + gid_t gid_base, gid_shift, gid_range, converted; + int k; + + errno = 0; + k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range); + if (k < 0 && feof(f)) + break; + if (k != 3) { + if (ferror(f)) + return errno_or_else(EIO); + + return -EIO; + } + + if (gid < gid_base || gid >= gid_base + gid_range) + continue; + + converted = gid - gid_base + gid_shift; + if (!gid_is_valid(converted)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid); + + return sd_bus_reply_method_return(message, "u", (uint32_t) converted); + } + + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Machine '%s' has no matching group mappings.", name); +} + +static int method_map_to_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) { + Manager *m = groupdata; + Machine *machine; + gid_t gid; + Iterator i; + int r; + + r = sd_bus_message_read(message, "u", &gid); + if (r < 0) + return r; + if (!gid_is_valid(gid)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid); + if (gid < 0x10000) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Group " GID_FMT " belongs to host GID range", gid); + + HASHMAP_FOREACH(machine, m->machines, i) { + _cleanup_fclose_ FILE *f = NULL; + char p[STRLEN("/proc//gid_map") + DECIMAL_STR_MAX(pid_t) + 1]; + + if (machine->class != MACHINE_CONTAINER) + continue; + + xsprintf(p, "/proc/" GID_FMT "/gid_map", machine->leader); + f = fopen(p, "re"); + if (!f) { + log_warning_errno(errno, "Failed to open %s, ignoring,", p); + continue; + } + + for (;;) { + _cleanup_free_ char *o = NULL; + gid_t gid_base, gid_shift, gid_range, converted; + int k; + + errno = 0; + k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range); + if (k < 0 && feof(f)) + break; + if (k != 3) { + if (ferror(f)) + return errno_or_else(EIO); + + return -EIO; + } + + /* The private user namespace is disabled, ignoring. */ + if (gid_shift == 0) + continue; + + if (gid < gid_shift || gid >= gid_shift + gid_range) + continue; + + converted = (gid - gid_shift + gid_base); + if (!gid_is_valid(converted)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid); + + o = machine_bus_path(machine); + if (!o) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted); + } + } + + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "No matching group mapping for " GID_FMT ".", gid); +} + +const sd_bus_vtable manager_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0), + SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0), + SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0), + SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListImages", NULL, "a(ssbttto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0), + SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0), + SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0), + SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0), + SD_BUS_METHOD("UnregisterMachine", "s", NULL, method_unregister_machine, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0), + SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("OpenMachineShell", "sssasas", "hs", method_open_machine_shell, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("OpenMachineRootDirectory", "s", "h", method_open_machine_root_directory, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineUIDShift", "s", "u", method_get_machine_uid_shift, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImageHostname", "s", "s", method_get_image_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImageMachineID", "s", "ay", method_get_image_machine_id, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImageMachineInfo", "s", "a{ss}", method_get_image_machine_info, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImageOSRelease", "s", "a{ss}", method_get_image_os_release, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CleanPool", "s", "a(st)", method_clean_pool, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_SIGNAL("MachineNew", "so", 0), + SD_BUS_SIGNAL("MachineRemoved", "so", 0), + SD_BUS_VTABLE_END +}; + +int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *path, *result, *unit; + Manager *m = userdata; + Machine *machine; + uint32_t id; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + machine = hashmap_get(m->machine_units, unit); + if (!machine) + return 0; + + if (streq_ptr(path, machine->scope_job)) { + machine->scope_job = mfree(machine->scope_job); + + if (machine->started) { + if (streq(result, "done")) + machine_send_create_reply(machine, NULL); + else { + _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL; + + sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result); + + machine_send_create_reply(machine, &e); + } + } + + machine_save(machine); + } + + machine_add_to_gc_queue(machine); + return 0; +} + +int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *unit = NULL; + const char *path; + Manager *m = userdata; + Machine *machine; + int r; + + assert(message); + assert(m); + + path = sd_bus_message_get_path(message); + if (!path) + return 0; + + r = unit_name_from_dbus_path(path, &unit); + if (r == -EINVAL) /* not for a unit */ + return 0; + if (r < 0) { + log_oom(); + return 0; + } + + machine = hashmap_get(m->machine_units, unit); + if (!machine) + return 0; + + machine_add_to_gc_queue(machine); + return 0; +} + +int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *path, *unit; + Manager *m = userdata; + Machine *machine; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "so", &unit, &path); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + machine = hashmap_get(m->machine_units, unit); + if (!machine) + return 0; + + machine_add_to_gc_queue(machine); + return 0; +} + +int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + Machine *machine; + Iterator i; + int b, r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + if (b) + return 0; + + /* systemd finished reloading, let's recheck all our machines */ + log_debug("System manager has been reloaded, rechecking machines..."); + + HASHMAP_FOREACH(machine, m->machines, i) + machine_add_to_gc_queue(machine); + + return 0; +} + +int manager_unref_unit( + Manager *m, + const char *unit, + sd_bus_error *error) { + + assert(m); + assert(unit); + + return sd_bus_call_method( + m->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "UnrefUnit", + error, + NULL, + "s", + unit); +} + +int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + assert(manager); + assert(unit); + + r = sd_bus_call_method( + manager->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StopUnit", + error, + &reply, + "ss", unit, "fail"); + if (r < 0) { + if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) || + sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) { + + if (job) + *job = NULL; + + sd_bus_error_free(error); + return 0; + } + + return r; + } + + if (job) { + const char *j; + char *copy; + + r = sd_bus_message_read(reply, "o", &j); + if (r < 0) + return r; + + copy = strdup(j); + if (!copy) + return -ENOMEM; + + *job = copy; + } + + return 1; +} + +int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) { + assert(manager); + assert(unit); + + return sd_bus_call_method( + manager->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "KillUnit", + error, + NULL, + "ssi", unit, "all", signo); +} + +int manager_unit_is_active(Manager *manager, const char *unit) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *path = NULL; + const char *state; + int r; + + assert(manager); + assert(unit); + + path = unit_dbus_path_from_name(unit); + if (!path) + return -ENOMEM; + + r = sd_bus_get_property( + manager->bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + "ActiveState", + &error, + &reply, + "s"); + if (r < 0) { + if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || + sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) + return true; + + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) || + sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) + return false; + + return r; + } + + r = sd_bus_message_read(reply, "s", &state); + if (r < 0) + return -EINVAL; + + return !STR_IN_SET(state, "inactive", "failed"); +} + +int manager_job_is_active(Manager *manager, const char *path) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + + assert(manager); + assert(path); + + r = sd_bus_get_property( + manager->bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Job", + "State", + &error, + &reply, + "s"); + if (r < 0) { + if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) || + sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED)) + return true; + + if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT)) + return false; + + return r; + } + + /* We don't actually care about the state really. The fact + * that we could read the job state is enough for us */ + + return true; +} + +int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) { + Machine *mm; + int r; + + assert(m); + assert(pid >= 1); + assert(machine); + + mm = hashmap_get(m->machine_leaders, PID_TO_PTR(pid)); + if (!mm) { + _cleanup_free_ char *unit = NULL; + + r = cg_pid_get_unit(pid, &unit); + if (r >= 0) + mm = hashmap_get(m->machine_units, unit); + } + if (!mm) + return 0; + + *machine = mm; + return 1; +} + +int manager_add_machine(Manager *m, const char *name, Machine **_machine) { + Machine *machine; + + assert(m); + assert(name); + + machine = hashmap_get(m->machines, name); + if (!machine) { + machine = machine_new(m, _MACHINE_CLASS_INVALID, name); + if (!machine) + return -ENOMEM; + } + + if (_machine) + *_machine = machine; + + return 0; +} diff --git a/src/machine/machined.c b/src/machine/machined.c new file mode 100644 index 00000000..ace2131c --- /dev/null +++ b/src/machine/machined.c @@ -0,0 +1,392 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-polkit.h" +#include "cgroup-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "hostname-util.h" +#include "label.h" +#include "machine-image.h" +#include "machined.h" +#include "main-func.h" +#include "process-util.h" +#include "signal-util.h" +#include "special.h" + +static Manager* manager_unref(Manager *m); +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref); + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(machine_hash_ops, char, string_hash_func, string_compare_func, Machine, machine_free); + +static int manager_new(Manager **ret) { + _cleanup_(manager_unrefp) Manager *m = NULL; + int r; + + assert(ret); + + m = new0(Manager, 1); + if (!m) + return -ENOMEM; + + m->machines = hashmap_new(&machine_hash_ops); + m->machine_units = hashmap_new(&string_hash_ops); + m->machine_leaders = hashmap_new(NULL); + + if (!m->machines || !m->machine_units || !m->machine_leaders) + return -ENOMEM; + + r = sd_event_default(&m->event); + if (r < 0) + return r; + + r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); + if (r < 0) + return r; + + r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); + if (r < 0) + return r; + + (void) sd_event_set_watchdog(m->event, true); + + *ret = TAKE_PTR(m); + return 0; +} + +static Manager* manager_unref(Manager *m) { + if (!m) + return NULL; + + while (m->operations) + operation_free(m->operations); + + assert(m->n_operations == 0); + + hashmap_free(m->machines); /* This will free all machines, so that the machine_units/machine_leaders is empty */ + hashmap_free(m->machine_units); + hashmap_free(m->machine_leaders); + hashmap_free(m->image_cache); + + sd_event_source_unref(m->image_cache_defer_event); + sd_event_source_unref(m->nscd_cache_flush_event); + + bus_verify_polkit_async_registry_free(m->polkit_registry); + + sd_bus_flush_close_unref(m->bus); + sd_event_unref(m->event); + + return mfree(m); +} + +static int manager_add_host_machine(Manager *m) { + _cleanup_free_ char *rd = NULL, *unit = NULL; + sd_id128_t mid; + Machine *t; + int r; + + if (m->host_machine) + return 0; + + r = sd_id128_get_machine(&mid); + if (r < 0) + return log_error_errno(r, "Failed to get machine ID: %m"); + + rd = strdup("/"); + if (!rd) + return log_oom(); + + unit = strdup(SPECIAL_ROOT_SLICE); + if (!unit) + return log_oom(); + + t = machine_new(m, MACHINE_HOST, ".host"); + if (!t) + return log_oom(); + + t->leader = 1; + t->id = mid; + + t->root_directory = TAKE_PTR(rd); + t->unit = TAKE_PTR(unit); + + dual_timestamp_from_boottime_or_monotonic(&t->timestamp, 0); + + m->host_machine = t; + + return 0; +} + +static int manager_enumerate_machines(Manager *m) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r = 0; + + assert(m); + + r = manager_add_host_machine(m); + if (r < 0) + return r; + + /* Read in machine data stored on disk */ + d = opendir("/run/systemd/machines"); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open /run/systemd/machines: %m"); + } + + FOREACH_DIRENT(de, d, return -errno) { + struct Machine *machine; + int k; + + if (!dirent_is_file(de)) + continue; + + /* Ignore symlinks that map the unit name to the machine */ + if (startswith(de->d_name, "unit:")) + continue; + + if (!machine_name_is_valid(de->d_name)) + continue; + + k = manager_add_machine(m, de->d_name, &machine); + if (k < 0) { + r = log_error_errno(k, "Failed to add machine by file name %s: %m", de->d_name); + continue; + } + + machine_add_to_gc_queue(machine); + + k = machine_load(machine); + if (k < 0) + r = k; + } + + return r; +} + +static int manager_connect_bus(Manager *m) { + int r; + + assert(m); + assert(!m->bus); + + r = sd_bus_default_system(&m->bus); + if (r < 0) + return log_error_errno(r, "Failed to connect to system bus: %m"); + + r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m); + if (r < 0) + return log_error_errno(r, "Failed to add manager object vtable: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to add machine object vtable: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/machine", machine_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add machine enumerator: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/image", "org.freedesktop.machine1.Image", image_vtable, image_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to add image object vtable: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/image", image_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add image enumerator: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "JobRemoved", + match_job_removed, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to add match for JobRemoved: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "UnitRemoved", + match_unit_removed, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to request match for UnitRemoved: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.systemd1", + NULL, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + match_properties_changed, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to request match for PropertiesChanged: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Reloading", + match_reloading, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to request match for Reloading: %m"); + + r = sd_bus_call_method_async( + m->bus, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Subscribe", + NULL, NULL, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to enable subscription: %m"); + + r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.machine1", 0, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + r = sd_bus_attach_event(m->bus, m->event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + return 0; +} + +static void manager_gc(Manager *m, bool drop_not_started) { + Machine *machine; + + assert(m); + + while ((machine = m->machine_gc_queue)) { + LIST_REMOVE(gc_queue, m->machine_gc_queue, machine); + machine->in_gc_queue = false; + + /* First, if we are not closing yet, initiate stopping */ + if (machine_may_gc(machine, drop_not_started) && + machine_get_state(machine) != MACHINE_CLOSING) + machine_stop(machine); + + /* Now, the stop probably made this referenced + * again, but if it didn't, then it's time to let it + * go entirely. */ + if (machine_may_gc(machine, drop_not_started)) { + machine_finalize(machine); + machine_free(machine); + } + } +} + +static int manager_startup(Manager *m) { + Machine *machine; + Iterator i; + int r; + + assert(m); + + /* Connect to the bus */ + r = manager_connect_bus(m); + if (r < 0) + return r; + + /* Deserialize state */ + manager_enumerate_machines(m); + + /* Remove stale objects before we start them */ + manager_gc(m, false); + + /* And start everything */ + HASHMAP_FOREACH(machine, m->machines, i) + machine_start(machine, NULL, NULL); + + return 0; +} + +static bool check_idle(void *userdata) { + Manager *m = userdata; + + if (m->operations) + return false; + + manager_gc(m, true); + + return hashmap_isempty(m->machines); +} + +static int manager_run(Manager *m) { + assert(m); + + return bus_event_loop_with_idle( + m->event, + m->bus, + "org.freedesktop.machine1", + DEFAULT_EXIT_USEC, + check_idle, m); +} + +static int run(int argc, char *argv[]) { + _cleanup_(manager_unrefp) Manager *m = NULL; + int r; + + log_set_facility(LOG_AUTH); + log_setup_service(); + + umask(0022); + + if (argc != 1) { + log_error("This program takes no arguments."); + return -EINVAL; + } + + /* Always create the directories people can create inotify watches in. Note that some applications might check + * for the existence of /run/systemd/machines/ to determine whether machined is available, so please always + * make sure this check stays in. */ + (void) mkdir_label("/run/systemd/machines", 0755); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, -1) >= 0); + + r = manager_new(&m); + if (r < 0) + return log_error_errno(r, "Failed to allocate manager object: %m"); + + r = manager_startup(m); + if (r < 0) + return log_error_errno(r, "Failed to fully start up daemon: %m"); + + log_debug("systemd-machined running as pid "PID_FMT, getpid_cached()); + (void) sd_notify(false, + "READY=1\n" + "STATUS=Processing requests..."); + + r = manager_run(m); + + log_debug("systemd-machined stopped as pid "PID_FMT, getpid_cached()); + (void) sd_notify(false, + "STOPPING=1\n" + "STATUS=Shutting down..."); + + return r; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/machine/machined.h b/src/machine/machined.h new file mode 100644 index 00000000..205d90f8 --- /dev/null +++ b/src/machine/machined.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" +#include "sd-event.h" + +#include "hashmap.h" +#include "list.h" + +typedef struct Manager Manager; + +#include "image-dbus.h" +#include "machine-dbus.h" +#include "machine.h" +#include "operation.h" + +struct Manager { + sd_event *event; + sd_bus *bus; + + Hashmap *machines; + Hashmap *machine_units; + Hashmap *machine_leaders; + + Hashmap *polkit_registry; + + Hashmap *image_cache; + sd_event_source *image_cache_defer_event; + + LIST_HEAD(Machine, machine_gc_queue); + + Machine *host_machine; + + LIST_HEAD(Operation, operations); + unsigned n_operations; + + sd_event_source *nscd_cache_flush_event; +}; + +int manager_add_machine(Manager *m, const char *name, Machine **_machine); +int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine); + +extern const sd_bus_vtable manager_vtable[]; + +int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error); +int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error); +int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error); +int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error); + +int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); +int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error); +int manager_unref_unit(Manager *m, const char *unit, sd_bus_error *error); +int manager_unit_is_active(Manager *manager, const char *unit); +int manager_job_is_active(Manager *manager, const char *path); + +int manager_enqueue_nscd_cache_flush(Manager *m); diff --git a/src/machine/meson.build b/src/machine/meson.build new file mode 100644 index 00000000..bc670714 --- /dev/null +++ b/src/machine/meson.build @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +systemd_machined_sources = files(''' + machined.c + machined.h +'''.split()) + +libmachine_core_sources = files(''' + machine.c + machine.h + machined-dbus.c + machined-core.c + machine-dbus.c + machine-dbus.h + image-dbus.c + image-dbus.h + operation.c + operation.h +'''.split()) + +libmachine_core = static_library( + 'machine-core', + libmachine_core_sources, + include_directories : includes, + dependencies : [threads]) + +if conf.get('ENABLE_MACHINED') == 1 + install_data('org.freedesktop.machine1.conf', + install_dir : dbuspolicydir) + install_data('org.freedesktop.machine1.service', + install_dir : dbussystemservicedir) + install_data('org.freedesktop.machine1.policy', + install_dir : polkitpolicydir) +endif + +tests += [ + [['src/machine/test-machine-tables.c'], + [libmachine_core, + libshared], + [threads], + 'ENABLE_MACHINED'], +] diff --git a/src/machine/operation.c b/src/machine/operation.c new file mode 100644 index 00000000..42c51f36 --- /dev/null +++ b/src/machine/operation.c @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "operation.h" +#include "process-util.h" + +static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + Operation *o = userdata; + int r; + + assert(o); + assert(si); + + log_debug("Operating " PID_FMT " is now complete with code=%s status=%i", + o->pid, + sigchld_code_to_string(si->si_code), si->si_status); + + o->pid = 0; + + if (si->si_code != CLD_EXITED) { + r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally."); + goto fail; + } + + if (si->si_status == EXIT_SUCCESS) + r = 0; + else if (read(o->errno_fd, &r, sizeof(r)) != sizeof(r)) { /* Try to acquire error code for failed operation */ + r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child failed."); + goto fail; + } + + if (o->done) { + /* A completion routine is set for this operation, call it. */ + r = o->done(o, r, &error); + if (r < 0) { + if (!sd_bus_error_is_set(&error)) + sd_bus_error_set_errno(&error, r); + + goto fail; + } + + } else { + /* The default operation when done is to simply return an error on failure or an empty success + * message on success. */ + if (r < 0) { + sd_bus_error_set_errno(&error, r); + goto fail; + } + + r = sd_bus_reply_method_return(o->message, NULL); + if (r < 0) + log_error_errno(r, "Failed to reply to message: %m"); + } + + operation_free(o); + return 0; + +fail: + r = sd_bus_reply_method_error(o->message, &error); + if (r < 0) + log_error_errno(r, "Failed to reply to message: %m"); + + operation_free(o); + return 0; +} + +int operation_new(Manager *manager, Machine *machine, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret) { + Operation *o; + int r; + + assert(manager); + assert(child > 1); + assert(message); + assert(errno_fd >= 0); + + o = new0(Operation, 1); + if (!o) + return -ENOMEM; + + o->extra_fd = -1; + + r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o); + if (r < 0) { + free(o); + return r; + } + + o->pid = child; + o->message = sd_bus_message_ref(message); + o->errno_fd = errno_fd; + + LIST_PREPEND(operations, manager->operations, o); + manager->n_operations++; + o->manager = manager; + + if (machine) { + LIST_PREPEND(operations_by_machine, machine->operations, o); + o->machine = machine; + } + + log_debug("Started new operation " PID_FMT ".", child); + + /* At this point we took ownership of both the child and the errno file descriptor! */ + + if (ret) + *ret = o; + + return 0; +} + +Operation *operation_free(Operation *o) { + if (!o) + return NULL; + + sd_event_source_unref(o->event_source); + + safe_close(o->errno_fd); + safe_close(o->extra_fd); + + if (o->pid > 1) + (void) sigkill_wait(o->pid); + + sd_bus_message_unref(o->message); + + if (o->manager) { + LIST_REMOVE(operations, o->manager->operations, o); + o->manager->n_operations--; + } + + if (o->machine) + LIST_REMOVE(operations_by_machine, o->machine->operations, o); + + return mfree(o); +} diff --git a/src/machine/operation.h b/src/machine/operation.h new file mode 100644 index 00000000..0e330285 --- /dev/null +++ b/src/machine/operation.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" +#include "sd-event.h" + +#include "list.h" + +typedef struct Operation Operation; + +#include "machined.h" + +#define OPERATIONS_MAX 64 + +struct Operation { + Manager *manager; + Machine *machine; + pid_t pid; + sd_bus_message *message; + int errno_fd; + int extra_fd; + sd_event_source *event_source; + int (*done)(Operation *o, int ret, sd_bus_error *error); + LIST_FIELDS(Operation, operations); + LIST_FIELDS(Operation, operations_by_machine); +}; + +int operation_new(Manager *manager, Machine *machine, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret); +Operation *operation_free(Operation *o); diff --git a/src/machine/org.freedesktop.machine1.conf b/src/machine/org.freedesktop.machine1.conf new file mode 100644 index 00000000..eafbf6bd --- /dev/null +++ b/src/machine/org.freedesktop.machine1.conf @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/machine/org.freedesktop.machine1.policy b/src/machine/org.freedesktop.machine1.policy new file mode 100644 index 00000000..039c3d45 --- /dev/null +++ b/src/machine/org.freedesktop.machine1.policy @@ -0,0 +1,104 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Log into a local container + Authentication is required to log into a local container. + + auth_admin + auth_admin + auth_admin_keep + + + + + Log into the local host + Authentication is required to log into the local host. + + auth_admin + auth_admin + yes + + + + + Acquire a shell in a local container + Authentication is required to acquire a shell in a local container. + + auth_admin + auth_admin + auth_admin_keep + + org.freedesktop.login1.login + + + + Acquire a shell on the local host + Authentication is required to acquire a shell on the local host. + + auth_admin + auth_admin + auth_admin_keep + + org.freedesktop.login1.host-login + + + + Acquire a pseudo TTY in a local container + Authentication is required to acquire a pseudo TTY in a local container. + + auth_admin + auth_admin + auth_admin_keep + + + + + Acquire a pseudo TTY on the local host + Authentication is required to acquire a pseudo TTY on the local host. + + auth_admin + auth_admin + auth_admin_keep + + + + + Manage local virtual machines and containers + Authentication is required to manage local virtual machines and containers. + + auth_admin + auth_admin + auth_admin_keep + + org.freedesktop.login1.shell org.freedesktop.login1.login + + + + Manage local virtual machine and container images + Authentication is required to manage local virtual machine and container images. + + auth_admin + auth_admin + auth_admin_keep + + + + diff --git a/src/machine/org.freedesktop.machine1.service b/src/machine/org.freedesktop.machine1.service new file mode 100644 index 00000000..d07bcae6 --- /dev/null +++ b/src/machine/org.freedesktop.machine1.service @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.machine1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.machine1.service diff --git a/src/machine/test-machine-tables.c b/src/machine/test-machine-tables.c new file mode 100644 index 00000000..04db7d82 --- /dev/null +++ b/src/machine/test-machine-tables.c @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "machine.h" +#include "test-tables.h" + +int main(int argc, char **argv) { + test_table(kill_who, KILL_WHO); + test_table(machine_class, MACHINE_CLASS); + test_table(machine_state, MACHINE_STATE); + + return EXIT_SUCCESS; +} diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c new file mode 100644 index 00000000..337a4603 --- /dev/null +++ b/src/modules-load/modules-load.c @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "conf-files.h" +#include "def.h" +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "main-func.h" +#include "module-util.h" +#include "pretty-print.h" +#include "proc-cmdline.h" +#include "string-util.h" +#include "strv.h" +#include "util.h" + +static char **arg_proc_cmdline_modules = NULL; +static const char conf_file_dirs[] = CONF_PATHS_NULSTR("modules-load.d"); + +STATIC_DESTRUCTOR_REGISTER(arg_proc_cmdline_modules, strv_freep); + +static void systemd_kmod_log(void *data, int priority, const char *file, int line, + const char *fn, const char *format, va_list args) { + + DISABLE_WARNING_FORMAT_NONLITERAL; + log_internalv(priority, 0, file, line, fn, format, args); + REENABLE_WARNING; +} + +static int add_modules(const char *p) { + _cleanup_strv_free_ char **k = NULL; + + k = strv_split(p, ","); + if (!k) + return log_oom(); + + if (strv_extend_strv(&arg_proc_cmdline_modules, k, true) < 0) + return log_oom(); + + return 0; +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + int r; + + if (proc_cmdline_key_streq(key, "modules_load")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = add_modules(value); + if (r < 0) + return r; + } + + return 0; +} + +static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) { + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(ctx); + assert(path); + + r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f); + if (r < 0) { + if (ignore_enoent && r == -ENOENT) + return 0; + + return log_error_errno(r, "Failed to open %s: %m", path); + } + + log_debug("apply: %s", path); + for (;;) { + _cleanup_free_ char *line = NULL; + char *l; + int k; + + k = read_line(f, LONG_LINE_MAX, &line); + if (k < 0) + return log_error_errno(k, "Failed to read file '%s': %m", path); + if (k == 0) + break; + + l = strstrip(line); + if (isempty(l)) + continue; + if (strchr(COMMENTS, *l)) + continue; + + k = module_load_and_warn(ctx, l, true); + if (k == -ENOENT) + continue; + if (k < 0 && r >= 0) + r = k; + } + + return r; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-modules-load.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" + "Loads statically configured kernel modules.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(kmod_unrefp) struct kmod_ctx *ctx = NULL; + int r, k; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + log_setup_service(); + + umask(0022); + + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + ctx = kmod_new(NULL, NULL); + if (!ctx) { + log_error("Failed to allocate memory for kmod."); + return -ENOMEM; + } + + kmod_load_resources(ctx); + kmod_set_log_fn(ctx, systemd_kmod_log, NULL); + + r = 0; + + if (argc > optind) { + int i; + + for (i = optind; i < argc; i++) { + k = apply_file(ctx, argv[i], false); + if (k < 0 && r == 0) + r = k; + } + + } else { + _cleanup_strv_free_ char **files = NULL; + char **fn, **i; + + STRV_FOREACH(i, arg_proc_cmdline_modules) { + k = module_load_and_warn(ctx, *i, true); + if (k == -ENOENT) + continue; + if (k < 0 && r == 0) + r = k; + } + + k = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs); + if (k < 0) { + log_error_errno(k, "Failed to enumerate modules-load.d files: %m"); + if (r == 0) + r = k; + return r; + } + + STRV_FOREACH(fn, files) { + k = apply_file(ctx, *fn, true); + if (k < 0 && r == 0) + r = k; + } + } + + return r; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c new file mode 100644 index 00000000..9f0220a7 --- /dev/null +++ b/src/mount/mount-tool.c @@ -0,0 +1,1615 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-bus.h" +#include "sd-device.h" + +#include "bus-error.h" +#include "bus-unit-util.h" +#include "bus-util.h" +#include "bus-wait-for-jobs.h" +#include "device-util.h" +#include "dirent-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "fstab-util.h" +#include "libmount-util.h" +#include "main-func.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "sort-util.h" +#include "spawn-polkit-agent.h" +#include "stat-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "unit-def.h" +#include "unit-name.h" +#include "user-util.h" + +enum { + ACTION_DEFAULT, + ACTION_MOUNT, + ACTION_AUTOMOUNT, + ACTION_UMOUNT, + ACTION_LIST, +} arg_action = ACTION_DEFAULT; + +static bool arg_no_block = false; +static PagerFlags arg_pager_flags = 0; +static bool arg_ask_password = true; +static bool arg_quiet = false; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static bool arg_user = false; +static const char *arg_host = NULL; +static bool arg_discover = false; +static char *arg_mount_what = NULL; +static char *arg_mount_where = NULL; +static char *arg_mount_type = NULL; +static char *arg_mount_options = NULL; +static char *arg_description = NULL; +static char **arg_property = NULL; +static usec_t arg_timeout_idle = USEC_INFINITY; +static bool arg_timeout_idle_set = false; +static char **arg_automount_property = NULL; +static int arg_bind_device = -1; +static uid_t arg_uid = UID_INVALID; +static gid_t arg_gid = GID_INVALID; +static bool arg_fsck = true; +static bool arg_aggressive_gc = false; + +STATIC_DESTRUCTOR_REGISTER(arg_mount_what, freep); +STATIC_DESTRUCTOR_REGISTER(arg_mount_where, freep); +STATIC_DESTRUCTOR_REGISTER(arg_mount_type, freep); +STATIC_DESTRUCTOR_REGISTER(arg_mount_options, freep); +STATIC_DESTRUCTOR_REGISTER(arg_description, freep); +STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_automount_property, strv_freep); + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-mount", "1", &link); + if (r < 0) + return log_oom(); + + printf("systemd-mount [OPTIONS...] WHAT [WHERE]\n" + "systemd-mount [OPTIONS...] --list\n" + "%s [OPTIONS...] %sWHAT|WHERE...\n\n" + "Establish a mount or auto-mount point transiently.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-block Do not wait until operation finished\n" + " --no-pager Do not pipe output into a pager\n" + " --no-ask-password Do not prompt for password\n" + " -q --quiet Suppress information messages during runtime\n" + " --user Run as user unit\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " --discover Discover mount device metadata\n" + " -t --type=TYPE File system type\n" + " -o --options=OPTIONS Mount options\n" + " --owner=USER Add uid= and gid= options for USER\n" + " --fsck=no Don't run file system check before mount\n" + " --description=TEXT Description for unit\n" + " -p --property=NAME=VALUE Set mount unit property\n" + " -A --automount=BOOL Create an auto-mount point\n" + " --timeout-idle-sec=SEC Specify automount idle timeout\n" + " --automount-property=NAME=VALUE\n" + " Set automount unit property\n" + " --bind-device Bind automount unit to device\n" + " --list List mountable block devices\n" + " -u --umount Unmount mount points\n" + " -G --collect Unload unit after it stopped, even when failed\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , streq(program_invocation_short_name, "systemd-umount") ? "" : "--umount " + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_BLOCK, + ARG_NO_PAGER, + ARG_NO_ASK_PASSWORD, + ARG_USER, + ARG_SYSTEM, + ARG_DISCOVER, + ARG_MOUNT_TYPE, + ARG_MOUNT_OPTIONS, + ARG_OWNER, + ARG_FSCK, + ARG_DESCRIPTION, + ARG_TIMEOUT_IDLE, + ARG_AUTOMOUNT, + ARG_AUTOMOUNT_PROPERTY, + ARG_BIND_DEVICE, + ARG_LIST, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-block", no_argument, NULL, ARG_NO_BLOCK }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "quiet", no_argument, NULL, 'q' }, + { "user", no_argument, NULL, ARG_USER }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "discover", no_argument, NULL, ARG_DISCOVER }, + { "type", required_argument, NULL, 't' }, + { "options", required_argument, NULL, 'o' }, + { "owner", required_argument, NULL, ARG_OWNER }, + { "fsck", required_argument, NULL, ARG_FSCK }, + { "description", required_argument, NULL, ARG_DESCRIPTION }, + { "property", required_argument, NULL, 'p' }, + { "automount", required_argument, NULL, ARG_AUTOMOUNT }, + { "timeout-idle-sec", required_argument, NULL, ARG_TIMEOUT_IDLE }, + { "automount-property", required_argument, NULL, ARG_AUTOMOUNT_PROPERTY }, + { "bind-device", no_argument, NULL, ARG_BIND_DEVICE }, + { "list", no_argument, NULL, ARG_LIST }, + { "umount", no_argument, NULL, 'u' }, + { "unmount", no_argument, NULL, 'u' }, + { "collect", no_argument, NULL, 'G' }, + {}, + }; + + int r, c; + + assert(argc >= 0); + assert(argv); + + if (strstr(program_invocation_short_name, "systemd-umount")) + arg_action = ACTION_UMOUNT; + + while ((c = getopt_long(argc, argv, "hqH:M:t:o:p:AuG", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_NO_BLOCK: + arg_no_block = true; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + + case 'q': + arg_quiet = true; + break; + + case ARG_USER: + arg_user = true; + break; + + case ARG_SYSTEM: + arg_user = false; + break; + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case ARG_DISCOVER: + arg_discover = true; + break; + + case 't': + if (free_and_strdup(&arg_mount_type, optarg) < 0) + return log_oom(); + break; + + case 'o': + if (free_and_strdup(&arg_mount_options, optarg) < 0) + return log_oom(); + break; + + case ARG_OWNER: { + const char *user = optarg; + + r = get_user_creds(&user, &arg_uid, &arg_gid, NULL, NULL, 0); + if (r < 0) + return log_error_errno(r, + r == -EBADMSG ? "UID or GID of user %s are invalid." + : "Cannot use \"%s\" as owner: %m", + optarg); + break; + } + + case ARG_FSCK: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --fsck= argument: %s", optarg); + + arg_fsck = r; + break; + + case ARG_DESCRIPTION: + if (free_and_strdup(&arg_description, optarg) < 0) + return log_oom(); + break; + + case 'p': + if (strv_extend(&arg_property, optarg) < 0) + return log_oom(); + + break; + + case 'A': + arg_action = ACTION_AUTOMOUNT; + break; + + case ARG_AUTOMOUNT: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "--automount= expects a valid boolean parameter: %s", optarg); + + arg_action = r ? ACTION_AUTOMOUNT : ACTION_MOUNT; + break; + + case ARG_TIMEOUT_IDLE: + r = parse_sec(optarg, &arg_timeout_idle); + if (r < 0) + return log_error_errno(r, "Failed to parse timeout: %s", optarg); + + break; + + case ARG_AUTOMOUNT_PROPERTY: + if (strv_extend(&arg_automount_property, optarg) < 0) + return log_oom(); + + break; + + case ARG_BIND_DEVICE: + arg_bind_device = true; + break; + + case ARG_LIST: + arg_action = ACTION_LIST; + break; + + case 'u': + arg_action = ACTION_UMOUNT; + break; + + case 'G': + arg_aggressive_gc = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Execution in user context is not supported on non-local systems."); + + if (arg_action == ACTION_LIST) { + if (optind < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many arguments."); + + if (arg_transport != BUS_TRANSPORT_LOCAL) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Listing devices only supported locally."); + } else if (arg_action == ACTION_UMOUNT) { + if (optind >= argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "At least one argument required."); + + if (arg_transport != BUS_TRANSPORT_LOCAL) { + int i; + + for (i = optind; i < argc; i++) + if (!path_is_absolute(argv[i]) ) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Only absolute path is supported: %s", argv[i]); + } + } else { + if (optind >= argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "At least one argument required."); + + if (argc > optind+2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "At most two arguments required."); + + if (arg_mount_type && (fstype_is_api_vfs(arg_mount_type) || fstype_is_network(arg_mount_type))) { + arg_mount_what = strdup(argv[optind]); + if (!arg_mount_what) + return log_oom(); + + } else if (arg_transport == BUS_TRANSPORT_LOCAL) { + _cleanup_free_ char *u = NULL; + + u = fstab_node_to_udev_node(argv[optind]); + if (!u) + return log_oom(); + + r = chase_symlinks(u, NULL, 0, &arg_mount_what, NULL); + if (r < 0) + return log_error_errno(r, "Failed to make path %s absolute: %m", u); + } else { + arg_mount_what = strdup(argv[optind]); + if (!arg_mount_what) + return log_oom(); + + path_simplify(arg_mount_what, false); + + if (!path_is_absolute(arg_mount_what)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Only absolute path is supported: %s", arg_mount_what); + } + + if (argc > optind+1) { + if (arg_transport == BUS_TRANSPORT_LOCAL) { + r = chase_symlinks(argv[optind+1], NULL, CHASE_NONEXISTENT, &arg_mount_where, NULL); + if (r < 0) + return log_error_errno(r, "Failed to make path %s absolute: %m", argv[optind+1]); + } else { + arg_mount_where = strdup(argv[optind+1]); + if (!arg_mount_where) + return log_oom(); + + path_simplify(arg_mount_where, false); + + if (!path_is_absolute(arg_mount_where)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Only absolute path is supported: %s", arg_mount_where); + } + } else + arg_discover = true; + + if (arg_discover && arg_transport != BUS_TRANSPORT_LOCAL) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Automatic mount location discovery is only supported locally."); + } + + return 1; +} + +static int transient_unit_set_properties(sd_bus_message *m, UnitType t, char **properties) { + int r; + + if (!isempty(arg_description)) { + r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description); + if (r < 0) + return r; + } + + if (arg_bind_device && is_device_path(arg_mount_what)) { + _cleanup_free_ char *device_unit = NULL; + + r = unit_name_from_path(arg_mount_what, ".device", &device_unit); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "(sv)(sv)", + "After", "as", 1, device_unit, + "BindsTo", "as", 1, device_unit); + if (r < 0) + return r; + } + + if (arg_aggressive_gc) { + r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed"); + if (r < 0) + return r; + } + + r = bus_append_unit_property_assignment_many(m, t, properties); + if (r < 0) + return r; + + return 0; +} + +static int transient_mount_set_properties(sd_bus_message *m) { + _cleanup_free_ char *options = NULL; + int r; + + assert(m); + + r = transient_unit_set_properties(m, UNIT_MOUNT, arg_property); + if (r < 0) + return r; + + if (arg_mount_what) { + r = sd_bus_message_append(m, "(sv)", "What", "s", arg_mount_what); + if (r < 0) + return r; + } + + if (arg_mount_type) { + r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_mount_type); + if (r < 0) + return r; + } + + /* Prepend uid=…,gid=… if arg_uid is set */ + if (arg_uid != UID_INVALID) { + r = asprintf(&options, + "uid=" UID_FMT ",gid=" GID_FMT "%s%s", + arg_uid, arg_gid, + arg_mount_options ? "," : "", strempty(arg_mount_options)); + if (r < 0) + return -ENOMEM; + } + + if (options || arg_mount_options) { + log_debug("Using mount options: %s", options ?: arg_mount_options); + + r = sd_bus_message_append(m, "(sv)", "Options", "s", options ?: arg_mount_options); + if (r < 0) + return r; + } else + log_debug("Not using any mount options"); + + if (arg_fsck) { + _cleanup_free_ char *fsck = NULL; + + r = unit_name_from_path_instance("systemd-fsck", arg_mount_what, ".service", &fsck); + if (r < 0) + return r; + + r = sd_bus_message_append(m, + "(sv)(sv)", + "Requires", "as", 1, fsck, + "After", "as", 1, fsck); + if (r < 0) + return r; + } + + return 0; +} + +static int transient_automount_set_properties(sd_bus_message *m) { + int r; + + assert(m); + + r = transient_unit_set_properties(m, UNIT_AUTOMOUNT, arg_automount_property); + if (r < 0) + return r; + + if (arg_timeout_idle != USEC_INFINITY) { + r = sd_bus_message_append(m, "(sv)", "TimeoutIdleUSec", "t", arg_timeout_idle); + if (r < 0) + return r; + } + + return 0; +} + +static int start_transient_mount( + sd_bus *bus, + char **argv) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_free_ char *mount_unit = NULL; + int r; + + if (!arg_no_block) { + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Could not watch jobs: %m"); + } + + r = unit_name_from_path(arg_mount_where, ".mount", &mount_unit); + if (r < 0) + return log_error_errno(r, "Failed to make mount unit name: %m"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); + if (r < 0) + return bus_log_create_error(r); + + /* Name and mode */ + r = sd_bus_message_append(m, "ss", mount_unit, "fail"); + if (r < 0) + return bus_log_create_error(r); + + /* Properties */ + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = transient_mount_set_properties(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + /* Auxiliary units */ + r = sd_bus_message_append(m, "a(sa(sv))", 0); + if (r < 0) + return bus_log_create_error(r); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to start transient mount unit: %s", bus_error_message(&error, r)); + + if (w) { + const char *object; + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_one(w, object, arg_quiet); + if (r < 0) + return r; + } + + if (!arg_quiet) + log_info("Started unit %s%s%s for mount point: %s%s%s", + ansi_highlight(), mount_unit, ansi_normal(), + ansi_highlight(), arg_mount_where, ansi_normal()); + + return 0; +} + +static int start_transient_automount( + sd_bus *bus, + char **argv) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_free_ char *automount_unit = NULL, *mount_unit = NULL; + int r; + + if (!arg_no_block) { + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Could not watch jobs: %m"); + } + + r = unit_name_from_path(arg_mount_where, ".automount", &automount_unit); + if (r < 0) + return log_error_errno(r, "Failed to make automount unit name: %m"); + + r = unit_name_from_path(arg_mount_where, ".mount", &mount_unit); + if (r < 0) + return log_error_errno(r, "Failed to make mount unit name: %m"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); + if (r < 0) + return bus_log_create_error(r); + + /* Name and mode */ + r = sd_bus_message_append(m, "ss", automount_unit, "fail"); + if (r < 0) + return bus_log_create_error(r); + + /* Properties */ + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = transient_automount_set_properties(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + /* Auxiliary units */ + r = sd_bus_message_open_container(m, 'a', "(sa(sv))"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'r', "sa(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", mount_unit); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = transient_mount_set_properties(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to start transient automount unit: %s", bus_error_message(&error, r)); + + if (w) { + const char *object; + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_one(w, object, arg_quiet); + if (r < 0) + return r; + } + + if (!arg_quiet) + log_info("Started unit %s%s%s for mount point: %s%s%s", + ansi_highlight(), automount_unit, ansi_normal(), + ansi_highlight(), arg_mount_where, ansi_normal()); + + return 0; +} + +static int find_mount_points(const char *what, char ***list) { + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; + _cleanup_strv_free_ char **l = NULL; + size_t bufsize = 0, n = 0; + int r; + + assert(what); + assert(list); + + /* Returns all mount points obtained from /proc/self/mountinfo in *list, + * and the number of mount points as return value. */ + + r = libmount_parse(NULL, NULL, &table, &iter); + if (r < 0) + return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); + + for (;;) { + struct libmnt_fs *fs; + const char *source, *target; + + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) + break; + if (r < 0) + return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m"); + + source = mnt_fs_get_source(fs); + target = mnt_fs_get_target(fs); + if (!source || !target) + continue; + + if (!path_equal(source, what)) + continue; + + /* one extra slot is needed for the terminating NULL */ + if (!GREEDY_REALLOC0(l, bufsize, n + 2)) + return log_oom(); + + l[n] = strdup(target); + if (!l[n]) + return log_oom(); + n++; + } + + if (!GREEDY_REALLOC0(l, bufsize, n + 1)) + return log_oom(); + + *list = TAKE_PTR(l); + return n; +} + +static int find_loop_device(const char *backing_file, char **loop_dev) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + _cleanup_free_ char *l = NULL; + + assert(backing_file); + assert(loop_dev); + + d = opendir("/sys/devices/virtual/block"); + if (!d) + return -errno; + + FOREACH_DIRENT(de, d, return -errno) { + _cleanup_free_ char *sys = NULL, *fname = NULL; + int r; + + dirent_ensure_type(d, de); + + if (de->d_type != DT_DIR) + continue; + + if (!startswith(de->d_name, "loop")) + continue; + + sys = path_join("/sys/devices/virtual/block", de->d_name, "loop/backing_file"); + if (!sys) + return -ENOMEM; + + r = read_one_line_file(sys, &fname); + if (r < 0) { + log_debug_errno(r, "Failed to read %s, ignoring: %m", sys); + continue; + } + + if (files_same(fname, backing_file, 0) <= 0) + continue; + + l = path_join("/dev", de->d_name); + if (!l) + return -ENOMEM; + + break; + } + + if (!l) + return -ENXIO; + + *loop_dev = TAKE_PTR(l); + + return 0; +} + +static int stop_mount( + sd_bus *bus, + const char *where, + const char *suffix) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_free_ char *mount_unit = NULL; + int r; + + if (!arg_no_block) { + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Could not watch jobs: %m"); + } + + r = unit_name_from_path(where, suffix, &mount_unit); + if (r < 0) + return log_error_errno(r, "Failed to make %s unit name from path %s: %m", suffix + 1, where); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StopUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); + if (r < 0) + return bus_log_create_error(r); + + /* Name and mode */ + r = sd_bus_message_append(m, "ss", mount_unit, "fail"); + if (r < 0) + return bus_log_create_error(r); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) { + if (streq(suffix, ".automount") && + sd_bus_error_has_name(&error, "org.freedesktop.systemd1.NoSuchUnit")) + return 0; + return log_error_errno(r, "Failed to stop %s unit: %s", suffix + 1, bus_error_message(&error, r)); + } + + if (w) { + const char *object; + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_one(w, object, arg_quiet); + if (r < 0) + return r; + } + + if (!arg_quiet) + log_info("Stopped unit %s%s%s for mount point: %s%s%s", + ansi_highlight(), mount_unit, ansi_normal(), + ansi_highlight(), where, ansi_normal()); + + return 0; +} + +static int stop_mounts( + sd_bus *bus, + const char *where) { + + int r; + + if (path_equal(where, "/")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Refusing to operate on root directory: %s", where); + + if (!path_is_normalized(where)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Path contains non-normalized components: %s", where); + + r = stop_mount(bus, where, ".mount"); + if (r < 0) + return r; + + r = stop_mount(bus, where, ".automount"); + if (r < 0) + return r; + + return 0; +} + +static int umount_by_device(sd_bus *bus, const char *what) { + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + _cleanup_strv_free_ char **list = NULL; + struct stat st; + const char *v; + char **l; + int r, r2 = 0; + + assert(what); + + if (stat(what, &st) < 0) + return log_error_errno(errno, "Can't stat %s: %m", what); + + if (!S_ISBLK(st.st_mode)) { + log_error("Not a block device: %s", what); + return -ENOTBLK; + } + + r = sd_device_new_from_devnum(&d, 'b', st.st_rdev); + if (r < 0) + return log_error_errno(r, "Failed to get device from device number: %m"); + + r = sd_device_get_property_value(d, "ID_FS_USAGE", &v); + if (r < 0) + return log_device_error_errno(d, r, "Failed to get device property: %m"); + + if (!streq(v, "filesystem")) { + log_device_error(d, "%s does not contain a known file system.", what); + return -EINVAL; + } + + if (sd_device_get_property_value(d, "SYSTEMD_MOUNT_WHERE", &v) >= 0) + r2 = stop_mounts(bus, v); + + r = find_mount_points(what, &list); + if (r < 0) + return r; + + for (l = list; *l; l++) { + r = stop_mounts(bus, *l); + if (r < 0) + r2 = r; + } + + return r2; +} + +static int umount_loop(sd_bus *bus, const char *backing_file) { + _cleanup_free_ char *loop_dev = NULL; + int r; + + assert(backing_file); + + r = find_loop_device(backing_file, &loop_dev); + if (r < 0) + return log_error_errno(r, r == -ENXIO ? "File %s is not mounted." : "Can't get loop device for %s: %m", backing_file); + + return umount_by_device(bus, loop_dev); +} + +static int action_umount( + sd_bus *bus, + int argc, + char **argv) { + + int i, r, r2 = 0; + + if (arg_transport != BUS_TRANSPORT_LOCAL) { + for (i = optind; i < argc; i++) { + _cleanup_free_ char *p = NULL; + + p = strdup(argv[i]); + if (!p) + return log_oom(); + + path_simplify(p, false); + + r = stop_mounts(bus, p); + if (r < 0) + r2 = r; + } + return r2; + } + + for (i = optind; i < argc; i++) { + _cleanup_free_ char *u = NULL, *p = NULL; + struct stat st; + + u = fstab_node_to_udev_node(argv[i]); + if (!u) + return log_oom(); + + r = chase_symlinks(u, NULL, 0, &p, NULL); + if (r < 0) { + r2 = log_error_errno(r, "Failed to make path %s absolute: %m", argv[i]); + continue; + } + + if (stat(p, &st) < 0) + return log_error_errno(errno, "Can't stat %s (from %s): %m", p, argv[i]); + + if (S_ISBLK(st.st_mode)) + r = umount_by_device(bus, p); + else if (S_ISREG(st.st_mode)) + r = umount_loop(bus, p); + else if (S_ISDIR(st.st_mode)) + r = stop_mounts(bus, p); + else { + log_error("Invalid file type: %s (from %s)", p, argv[i]); + r = -EINVAL; + } + + if (r < 0) + r2 = r; + } + + return r2; +} + +static int acquire_mount_type(sd_device *d) { + const char *v; + + assert(d); + + if (arg_mount_type) + return 0; + + if (sd_device_get_property_value(d, "ID_FS_TYPE", &v) < 0) + return 0; + + arg_mount_type = strdup(v); + if (!arg_mount_type) + return log_oom(); + + log_debug("Discovered type=%s", arg_mount_type); + return 1; +} + +static int acquire_mount_options(sd_device *d) { + const char *v; + + assert(d); + + if (arg_mount_options) + return 0; + + if (sd_device_get_property_value(d, "SYSTEMD_MOUNT_OPTIONS", &v) < 0) + return 0; + + arg_mount_options = strdup(v); + if (!arg_mount_options) + return log_oom(); + + log_debug("Discovered options=%s", arg_mount_options); + return 1; +} + +static const char *get_model(sd_device *d) { + const char *model; + + assert(d); + + if (sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model) >= 0) + return model; + + if (sd_device_get_property_value(d, "ID_MODEL", &model) >= 0) + return model; + + return NULL; +} + +static const char* get_label(sd_device *d) { + const char *label; + + assert(d); + + if (sd_device_get_property_value(d, "ID_FS_LABEL", &label) >= 0) + return label; + + if (sd_device_get_property_value(d, "ID_PART_ENTRY_NAME", &label) >= 0) + return label; + + return NULL; +} + +static int acquire_mount_where(sd_device *d) { + const char *v; + + if (arg_mount_where) + return 0; + + if (sd_device_get_property_value(d, "SYSTEMD_MOUNT_WHERE", &v) < 0) { + _cleanup_free_ char *escaped = NULL; + const char *name; + + name = get_label(d); + if (!name) + name = get_model(d); + if (!name) { + const char *dn; + + if (sd_device_get_devname(d, &dn) < 0) + return 0; + + name = basename(dn); + } + + escaped = xescape(name, "\\"); + if (!escaped) + return log_oom(); + if (!filename_is_valid(escaped)) + return 0; + + arg_mount_where = path_join("/run/media/system", escaped); + } else + arg_mount_where = strdup(v); + + if (!arg_mount_where) + return log_oom(); + + log_debug("Discovered where=%s", arg_mount_where); + return 1; +} + +static int acquire_mount_where_for_loop_dev(const char *loop_dev) { + _cleanup_strv_free_ char **list = NULL; + int r; + + if (arg_mount_where) + return 0; + + r = find_mount_points(loop_dev, &list); + if (r < 0) + return r; + else if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Can't find mount point of %s. It is expected that %s is already mounted on a place.", + loop_dev, loop_dev); + else if (r >= 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s is mounted on %d places. It is expected that %s is mounted on a place.", + loop_dev, r, loop_dev); + + arg_mount_where = strdup(list[0]); + if (!arg_mount_where) + return log_oom(); + + log_debug("Discovered where=%s", arg_mount_where); + return 1; +} + +static int acquire_description(sd_device *d) { + const char *model, *label; + + if (arg_description) + return 0; + + model = get_model(d); + + label = get_label(d); + if (!label) + (void) sd_device_get_property_value(d, "ID_PART_ENTRY_NUMBER", &label); + + if (model && label) + arg_description = strjoin(model, " ", label); + else if (label) + arg_description = strdup(label); + else if (model) + arg_description = strdup(model); + else + return 0; + + if (!arg_description) + return log_oom(); + + log_debug("Discovered description=%s", arg_description); + return 1; +} + +static int acquire_removable(sd_device *d) { + const char *v; + + /* Shortcut this if there's no reason to check it */ + if (arg_action != ACTION_DEFAULT && arg_timeout_idle_set && arg_bind_device >= 0) + return 0; + + for (;;) { + if (sd_device_get_sysattr_value(d, "removable", &v) > 0) + break; + + if (sd_device_get_parent(d, &d) < 0) + return 0; + + if (sd_device_get_subsystem(d, &v) < 0 || !streq(v, "block")) + return 0; + } + + if (parse_boolean(v) <= 0) + return 0; + + log_debug("Discovered removable device."); + + if (arg_action == ACTION_DEFAULT) { + log_debug("Automatically turning on automount."); + arg_action = ACTION_AUTOMOUNT; + } + + if (!arg_timeout_idle_set) { + log_debug("Setting idle timeout to 1s."); + arg_timeout_idle = USEC_PER_SEC; + } + + if (arg_bind_device < 0) { + log_debug("Binding automount unit to device."); + arg_bind_device = true; + } + + return 1; +} + +static int discover_loop_backing_file(void) { + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + _cleanup_free_ char *loop_dev = NULL; + struct stat st; + const char *v; + int r; + + r = find_loop_device(arg_mount_what, &loop_dev); + if (r < 0 && r != -ENXIO) + return log_error_errno(errno, "Can't get loop device for %s: %m", arg_mount_what); + + if (r == -ENXIO) { + _cleanup_free_ char *escaped = NULL; + + if (arg_mount_where) + return 0; + + escaped = xescape(basename(arg_mount_what), "\\"); + if (!escaped) + return log_oom(); + if (!filename_is_valid(escaped)) { + log_error("Escaped name %s is not a valid filename.", escaped); + return -EINVAL; + } + + arg_mount_where = path_join("/run/media/system", escaped); + if (!arg_mount_where) + return log_oom(); + + log_debug("Discovered where=%s", arg_mount_where); + return 0; + } + + if (stat(loop_dev, &st) < 0) + return log_error_errno(errno, "Can't stat %s: %m", loop_dev); + + if (!S_ISBLK(st.st_mode)) { + log_error("Invalid file type: %s", loop_dev); + return -EINVAL; + } + + r = sd_device_new_from_devnum(&d, 'b', st.st_rdev); + if (r < 0) + return log_error_errno(r, "Failed to get device from device number: %m"); + + if (sd_device_get_property_value(d, "ID_FS_USAGE", &v) < 0 || !streq(v, "filesystem")) { + log_device_error(d, "%s does not contain a known file system.", arg_mount_what); + return -EINVAL; + } + + r = acquire_mount_type(d); + if (r < 0) + return r; + + r = acquire_mount_options(d); + if (r < 0) + return r; + + r = acquire_mount_where_for_loop_dev(loop_dev); + if (r < 0) + return r; + + r = acquire_description(d); + if (r < 0) + return r; + + return 0; +} + +static int discover_device(void) { + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + struct stat st; + const char *v; + int r; + + if (stat(arg_mount_what, &st) < 0) + return log_error_errno(errno, "Can't stat %s: %m", arg_mount_what); + + if (S_ISREG(st.st_mode)) + return discover_loop_backing_file(); + + if (!S_ISBLK(st.st_mode)) { + log_error("Invalid file type: %s", arg_mount_what); + return -EINVAL; + } + + r = sd_device_new_from_devnum(&d, 'b', st.st_rdev); + if (r < 0) + return log_error_errno(r, "Failed to get device from device number: %m"); + + if (sd_device_get_property_value(d, "ID_FS_USAGE", &v) < 0 || !streq(v, "filesystem")) { + log_error("%s does not contain a known file system.", arg_mount_what); + return -EINVAL; + } + + r = acquire_mount_type(d); + if (r < 0) + return r; + + r = acquire_mount_options(d); + if (r < 0) + return r; + + r = acquire_mount_where(d); + if (r < 0) + return r; + + r = acquire_description(d); + if (r < 0) + return r; + + r = acquire_removable(d); + if (r < 0) + return r; + + return 0; +} + +enum { + COLUMN_NODE, + COLUMN_PATH, + COLUMN_MODEL, + COLUMN_WWN, + COLUMN_FSTYPE, + COLUMN_LABEL, + COLUMN_UUID, + _COLUMN_MAX, +}; + +struct item { + char* columns[_COLUMN_MAX]; +}; + +static int compare_item(const struct item *a, const struct item *b) { + if (a->columns[COLUMN_NODE] == b->columns[COLUMN_NODE]) + return 0; + if (!a->columns[COLUMN_NODE]) + return 1; + if (!b->columns[COLUMN_NODE]) + return -1; + + return path_compare(a->columns[COLUMN_NODE], b->columns[COLUMN_NODE]); +} + +static int list_devices(void) { + + static const char * const titles[_COLUMN_MAX] = { + [COLUMN_NODE] = "NODE", + [COLUMN_PATH] = "PATH", + [COLUMN_MODEL] = "MODEL", + [COLUMN_WWN] = "WWN", + [COLUMN_FSTYPE] = "TYPE", + [COLUMN_LABEL] = "LABEL", + [COLUMN_UUID] = "UUID" + }; + + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + size_t n_allocated = 0, n = 0, i; + size_t column_width[_COLUMN_MAX]; + struct item *items = NULL; + sd_device *d; + unsigned c; + int r; + + for (c = 0; c < _COLUMN_MAX; c++) + column_width[c] = strlen(titles[c]); + + r = sd_device_enumerator_new(&e); + if (r < 0) + return log_oom(); + + r = sd_device_enumerator_add_match_subsystem(e, "block", true); + if (r < 0) + return log_error_errno(r, "Failed to add block match: %m"); + + r = sd_device_enumerator_add_match_property(e, "ID_FS_USAGE", "filesystem"); + if (r < 0) + return log_error_errno(r, "Failed to add property match: %m"); + + FOREACH_DEVICE(e, d) { + struct item *j; + + if (!GREEDY_REALLOC0(items, n_allocated, n+1)) { + r = log_oom(); + goto finish; + } + + j = items + n++; + + for (c = 0; c < _COLUMN_MAX; c++) { + const char *x = NULL; + size_t k; + + switch (c) { + + case COLUMN_NODE: + (void) sd_device_get_devname(d, &x); + break; + + case COLUMN_PATH: + (void) sd_device_get_property_value(d, "ID_PATH", &x); + break; + + case COLUMN_MODEL: + x = get_model(d); + break; + + case COLUMN_WWN: + (void) sd_device_get_property_value(d, "ID_WWN", &x); + break; + + case COLUMN_FSTYPE: + (void) sd_device_get_property_value(d, "ID_FS_TYPE", &x); + break; + + case COLUMN_LABEL: + x = get_label(d); + break; + + case COLUMN_UUID: + (void) sd_device_get_property_value(d, "ID_FS_UUID", &x); + break; + } + + if (isempty(x)) + continue; + + j->columns[c] = strdup(x); + if (!j->columns[c]) { + r = log_oom(); + goto finish; + } + + k = strlen(x); + if (k > column_width[c]) + column_width[c] = k; + } + } + + if (n == 0) { + log_info("No devices found."); + goto finish; + } + + typesafe_qsort(items, n, compare_item); + + (void) pager_open(arg_pager_flags); + + fputs(ansi_underline(), stdout); + for (c = 0; c < _COLUMN_MAX; c++) { + if (c > 0) + fputc(' ', stdout); + + printf("%-*s", (int) column_width[c], titles[c]); + } + fputs(ansi_normal(), stdout); + fputc('\n', stdout); + + for (i = 0; i < n; i++) { + for (c = 0; c < _COLUMN_MAX; c++) { + if (c > 0) + fputc(' ', stdout); + + printf("%-*s", (int) column_width[c], strna(items[i].columns[c])); + } + fputc('\n', stdout); + } + + r = 0; + +finish: + for (i = 0; i < n; i++) + for (c = 0; c < _COLUMN_MAX; c++) + free(items[i].columns[c]); + + free(items); + return r; +} + +static int run(int argc, char* argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (arg_action == ACTION_LIST) + return list_devices(); + + r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + if (arg_action == ACTION_UMOUNT) + return action_umount(bus, argc, argv); + + if ((!arg_mount_type || !fstype_is_network(arg_mount_type)) + && !path_is_normalized(arg_mount_what)) { + log_error("Path contains non-normalized components: %s", arg_mount_what); + return -EINVAL; + } + + if (arg_discover) { + r = discover_device(); + if (r < 0) + return r; + } + + if (!arg_mount_where) { + log_error("Can't figure out where to mount %s.", arg_mount_what); + return -EINVAL; + } + + if (path_equal(arg_mount_where, "/")) { + log_error("Refusing to operate on root directory."); + return -EINVAL; + } + + if (!path_is_normalized(arg_mount_where)) { + log_error("Path contains non-normalized components: %s", arg_mount_where); + return -EINVAL; + } + + if (streq_ptr(arg_mount_type, "auto")) + arg_mount_type = mfree(arg_mount_type); + if (streq_ptr(arg_mount_options, "defaults")) + arg_mount_options = mfree(arg_mount_options); + + if (!is_device_path(arg_mount_what)) + arg_fsck = false; + + if (arg_fsck && arg_mount_type && arg_transport == BUS_TRANSPORT_LOCAL) { + r = fsck_exists(arg_mount_type); + if (r < 0) + log_warning_errno(r, "Couldn't determine whether fsck for %s exists, proceeding anyway.", arg_mount_type); + else if (r == 0) { + log_debug("Disabling file system check as fsck for %s doesn't exist.", arg_mount_type); + arg_fsck = false; /* fsck doesn't exist, let's not attempt it */ + } + } + + /* The kernel (properly) refuses mounting file systems with unknown uid=,gid= options, + * but not for all filesystem types. Let's try to catch the cases where the option + * would be used if the file system does not support it. It is also possible to + * autodetect the file system, but that's only possible with disk-based file systems + * which incidentally seem to be implemented more carefully and reject unknown options, + * so it's probably OK that we do the check only when the type is specified. + */ + if (arg_mount_type && + !streq(arg_mount_type, "auto") && + arg_uid != UID_INVALID && + !fstype_can_uid_gid(arg_mount_type)) { + log_error("File system type %s is not known to support uid=/gid=, refusing.", + arg_mount_type); + return -EOPNOTSUPP; + } + + switch (arg_action) { + + case ACTION_MOUNT: + case ACTION_DEFAULT: + r = start_transient_mount(bus, argv + optind); + break; + + case ACTION_AUTOMOUNT: + r = start_transient_automount(bus, argv + optind); + break; + + default: + assert_not_reached("Unexpected action."); + } + + return r; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/network/fuzz-netdev-parser.c b/src/network/fuzz-netdev-parser.c new file mode 100644 index 00000000..78c8d0c2 --- /dev/null +++ b/src/network/fuzz-netdev-parser.c @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fd-util.h" +#include "fs-util.h" +#include "fuzz.h" +#include "networkd-manager.h" +#include "tmpfile-util.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(manager_freep) Manager *manager = NULL; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_(unlink_tempfilep) char netdev_config[] = "/tmp/fuzz-networkd.XXXXXX"; + + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + assert_se(fmkostemp_safe(netdev_config, "r+", &f) == 0); + if (size != 0) + assert_se(fwrite(data, size, 1, f) == 1); + + fflush(f); + assert_se(manager_new(&manager) >= 0); + (void) netdev_load_one(manager, netdev_config); + return 0; +} diff --git a/src/network/fuzz-network-parser.c b/src/network/fuzz-network-parser.c new file mode 100644 index 00000000..732b5b21 --- /dev/null +++ b/src/network/fuzz-network-parser.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fd-util.h" +#include "fs-util.h" +#include "fuzz.h" +#include "networkd-manager.h" +#include "tmpfile-util.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(manager_freep) Manager *manager = NULL; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_(unlink_tempfilep) char network_config[] = "/tmp/fuzz-networkd.XXXXXX"; + + if (size > 65535) + return 0; + + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + assert_se(fmkostemp_safe(network_config, "r+", &f) == 0); + if (size != 0) + assert_se(fwrite(data, size, 1, f) == 1); + + fflush(f); + assert_se(manager_new(&manager) >= 0); + (void) network_load_one(manager, &manager->networks, network_config); + return 0; +} diff --git a/src/network/fuzz-network-parser.options b/src/network/fuzz-network-parser.options new file mode 100644 index 00000000..0824b19f --- /dev/null +++ b/src/network/fuzz-network-parser.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/src/network/generator/main.c b/src/network/generator/main.c new file mode 100644 index 00000000..75bd2b4b --- /dev/null +++ b/src/network/generator/main.c @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "fd-util.h" +#include "generator.h" +#include "macro.h" +#include "main-func.h" +#include "mkdir.h" +#include "network-generator.h" +#include "path-util.h" +#include "proc-cmdline.h" + +#define NETWORKD_UNIT_DIRECTORY "/run/systemd/network" + +static const char *arg_root = NULL; + +static int network_save(Network *network, const char *dest_dir) { + _cleanup_free_ char *filename = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(network); + + r = asprintf(&filename, "%s-%s.network", + isempty(network->ifname) ? "91" : "90", + isempty(network->ifname) ? "default" : network->ifname); + if (r < 0) + return log_oom(); + + r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f); + if (r < 0) + return r; + + network_dump(network, f); + + return 0; +} + +static int netdev_save(NetDev *netdev, const char *dest_dir) { + _cleanup_free_ char *filename = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(netdev); + + r = asprintf(&filename, "90-%s.netdev", + netdev->ifname); + if (r < 0) + return log_oom(); + + r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f); + if (r < 0) + return r; + + netdev_dump(netdev, f); + + return 0; +} + +static int link_save(Link *link, const char *dest_dir) { + _cleanup_free_ char *filename = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(link); + + r = asprintf(&filename, "90-%s.link", + link->ifname); + if (r < 0) + return log_oom(); + + r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f); + if (r < 0) + return r; + + link_dump(link, f); + + return 0; +} + +static int context_save(Context *context) { + Network *network; + NetDev *netdev; + Link *link; + Iterator i; + int k, r = 0; + const char *p; + + p = prefix_roota(arg_root, NETWORKD_UNIT_DIRECTORY); + + r = mkdir_p(p, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create directory " NETWORKD_UNIT_DIRECTORY ": %m"); + + HASHMAP_FOREACH(network, context->networks_by_name, i) { + k = network_save(network, p); + if (k < 0 && r >= 0) + r = k; + } + + HASHMAP_FOREACH(netdev, context->netdevs_by_name, i) { + k = netdev_save(netdev, p); + if (k < 0 && r >= 0) + r = k; + } + + HASHMAP_FOREACH(link, context->links_by_name, i) { + k = link_save(link, p); + if (k < 0 && r >= 0) + r = k; + } + + return r; +} + +static int help(void) { + printf("%s [OPTIONS...] [-- KERNEL_CMDLINE]\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --root=PATH Operate on an alternate filesystem root\n" + , program_invocation_short_name + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_ROOT, + }; + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "root", required_argument, NULL, ARG_ROOT }, + {}, + }; + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_ROOT: + arg_root = optarg; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(context_clear) Context context = {}; + int i, r; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (optind >= argc) { + r = proc_cmdline_parse(parse_cmdline_item, &context, 0); + if (r < 0) + return log_warning_errno(r, "Failed to parse kernel command line: %m"); + } else { + for (i = optind; i < argc; i++) { + _cleanup_free_ char *word = NULL; + char *value; + + word = strdup(argv[i]); + if (!word) + return log_oom(); + + value = strchr(word, '='); + if (value) + *(value++) = 0; + + r = parse_cmdline_item(word, value, &context); + if (r < 0) + return log_warning_errno(r, "Failed to parse command line \"%s%s%s\": %m", + word, value ? "=" : "", strempty(value)); + } + } + + r = context_merge_networks(&context); + if (r < 0) + return log_warning_errno(r, "Failed to merge multiple command line options: %m"); + + return context_save(&context); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/network/generator/network-generator.c b/src/network/generator/network-generator.c new file mode 100644 index 00000000..81afa953 --- /dev/null +++ b/src/network/generator/network-generator.c @@ -0,0 +1,1232 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "ether-addr-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "hostname-util.h" +#include "log.h" +#include "macro.h" +#include "network-generator.h" +#include "parse-util.h" +#include "proc-cmdline.h" +#include "socket-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" + +/* + # .network + ip={dhcp|on|any|dhcp6|auto6|either6} + ip=:{dhcp|on|any|dhcp6|auto6}[:[][:]] + ip=:[]:::::{none|off|dhcp|on|any|dhcp6|auto6|ibft}[:[][:]] + ip=:[]:::::{none|off|dhcp|on|any|dhcp6|auto6|ibft}[:[][:]] + rd.route=/:[:] + nameserver= [nameserver= ...] + rd.peerdns=0 + + # .link + ifname=: + + # .netdev + vlan=: + bond=[::[:[:]]] + team=: # not supported + bridge=: + + # ignored + bootdev= + BOOTIF= + rd.bootif=0 + biosdevname=0 + rd.neednet=1 +*/ + +static const char * const dracut_dhcp_type_table[_DHCP_TYPE_MAX] = { + [DHCP_TYPE_NONE] = "none", + [DHCP_TYPE_OFF] = "off", + [DHCP_TYPE_ON] = "on", + [DHCP_TYPE_ANY] = "any", + [DHCP_TYPE_DHCP] = "dhcp", + [DHCP_TYPE_DHCP6] = "dhcp6", + [DHCP_TYPE_AUTO6] = "auto6", + [DHCP_TYPE_EITHER6] = "either6", + [DHCP_TYPE_IBFT] = "ibft", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dracut_dhcp_type, DHCPType); + +static const char * const networkd_dhcp_type_table[_DHCP_TYPE_MAX] = { + [DHCP_TYPE_NONE] = "no", + [DHCP_TYPE_OFF] = "no", + [DHCP_TYPE_ON] = "yes", + [DHCP_TYPE_ANY] = "yes", + [DHCP_TYPE_DHCP] = "ipv4", + [DHCP_TYPE_DHCP6] = "ipv6", + [DHCP_TYPE_AUTO6] = "no", /* TODO: enable other setting? */ + [DHCP_TYPE_EITHER6] = "ipv6", /* TODO: enable other setting? */ + [DHCP_TYPE_IBFT] = "no", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(networkd_dhcp_type, DHCPType); + +static Address *address_free(Address *address) { + if (!address) + return NULL; + + if (address->network) + LIST_REMOVE(addresses, address->network->addresses, address); + + return mfree(address); +} + +static int address_new(Network *network, int family, unsigned char prefixlen, + union in_addr_union *addr, union in_addr_union *peer, Address **ret) { + Address *address; + + assert(network); + + address = new(Address, 1); + if (!address) + return -ENOMEM; + + *address = (Address) { + .family = family, + .prefixlen = prefixlen, + .address = *addr, + .peer = *peer, + }; + + LIST_PREPEND(addresses, network->addresses, address); + + address->network = network; + + if (ret) + *ret = address; + return 0; +} + +static Route *route_free(Route *route) { + if (!route) + return NULL; + + if (route->network) + LIST_REMOVE(routes, route->network->routes, route); + + return mfree(route); +} + +static int route_new(Network *network, int family, unsigned char prefixlen, + union in_addr_union *dest, union in_addr_union *gateway, Route **ret) { + Route *route; + + assert(network); + + route = new(Route, 1); + if (!route) + return -ENOMEM; + + *route = (Route) { + .family = family, + .prefixlen = prefixlen, + .dest = dest ? *dest : IN_ADDR_NULL, + .gateway = *gateway, + }; + + LIST_PREPEND(routes, network->routes, route); + + route->network = network; + + if (ret) + *ret = route; + return 0; +} + +static Network *network_free(Network *network) { + Address *address; + Route *route; + + if (!network) + return NULL; + + free(network->ifname); + free(network->hostname); + strv_free(network->dns); + free(network->vlan); + free(network->bridge); + free(network->bond); + + while ((address = network->addresses)) + address_free(address); + + while ((route = network->routes)) + route_free(route); + + return mfree(network); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free); + +static int network_new(Context *context, const char *name, Network **ret) { + _cleanup_(network_freep) Network *network = NULL; + _cleanup_free_ char *ifname = NULL; + int r; + + assert(context); + + if (!isempty(name) && !ifname_valid(name)) + return -EINVAL; + + ifname = strdup(name); + if (!ifname) + return -ENOMEM; + + network = new(Network, 1); + if (!network) + return -ENOMEM; + + *network = (Network) { + .ifname = TAKE_PTR(ifname), + .dhcp_type = _DHCP_TYPE_INVALID, + .dhcp_use_dns = -1, + }; + + r = hashmap_ensure_allocated(&context->networks_by_name, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(context->networks_by_name, network->ifname, network); + if (r < 0) + return r; + + if (ret) + *ret = network; + + TAKE_PTR(network); + return 0; +} + +Network *network_get(Context *context, const char *ifname) { + return hashmap_get(context->networks_by_name, ifname); +} + +static NetDev *netdev_free(NetDev *netdev) { + if (!netdev) + return NULL; + + free(netdev->ifname); + free(netdev->kind); + return mfree(netdev); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_free); + +static int netdev_new(Context *context, const char *_kind, const char *_ifname, NetDev **ret) { + _cleanup_(netdev_freep) NetDev *netdev = NULL; + _cleanup_free_ char *kind = NULL, *ifname = NULL; + int r; + + assert(context); + + if (!ifname_valid(_ifname)) + return -EINVAL; + + kind = strdup(_kind); + if (!kind) + return -ENOMEM; + + ifname = strdup(_ifname); + if (!ifname) + return -ENOMEM; + + netdev = new(NetDev, 1); + if (!netdev) + return -ENOMEM; + + *netdev = (NetDev) { + .kind = TAKE_PTR(kind), + .ifname = TAKE_PTR(ifname), + }; + + r = hashmap_ensure_allocated(&context->netdevs_by_name, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(context->netdevs_by_name, netdev->ifname, netdev); + if (r < 0) + return r; + + if (ret) + *ret = netdev; + + TAKE_PTR(netdev); + return 0; +} + +NetDev *netdev_get(Context *context, const char *ifname) { + return hashmap_get(context->netdevs_by_name, ifname); +} + +static Link *link_free(Link *link) { + if (!link) + return NULL; + + free(link->ifname); + return mfree(link); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); + +static int link_new(Context *context, const char *name, struct ether_addr *mac, Link **ret) { + _cleanup_(link_freep) Link *link = NULL; + _cleanup_free_ char *ifname = NULL; + int r; + + assert(context); + + if (!ifname_valid(name)) + return -EINVAL; + + ifname = strdup(name); + if (!ifname) + return -ENOMEM; + + link = new(Link, 1); + if (!link) + return -ENOMEM; + + *link = (Link) { + .ifname = TAKE_PTR(ifname), + .mac = *mac, + }; + + r = hashmap_ensure_allocated(&context->links_by_name, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(context->links_by_name, link->ifname, link); + if (r < 0) + return r; + + if (ret) + *ret = link; + + TAKE_PTR(link); + return 0; +} + +Link *link_get(Context *context, const char *ifname) { + return hashmap_get(context->links_by_name, ifname); +} + +static int network_set_dhcp_type(Context *context, const char *ifname, const char *dhcp_type) { + Network *network; + DHCPType t; + int r; + + t = dracut_dhcp_type_from_string(dhcp_type); + if (t < 0) + return -EINVAL; + + network = network_get(context, ifname); + if (!network) { + r = network_new(context, ifname, &network); + if (r < 0) + return r; + } + + network->dhcp_type = t; + return 0; +} + +static int network_set_hostname(Context *context, const char *ifname, const char *hostname) { + Network *network; + + network = network_get(context, ifname); + if (!network) + return -ENODEV; + + return free_and_strdup(&network->hostname, hostname); +} + +static int network_set_mtu(Context *context, const char *ifname, int family, const char *mtu) { + Network *network; + + network = network_get(context, ifname); + if (!network) + return -ENODEV; + + return parse_mtu(family, mtu, &network->mtu); +} + +static int network_set_mac_address(Context *context, const char *ifname, const char *mac) { + Network *network; + + network = network_get(context, ifname); + if (!network) + return -ENODEV; + + return ether_addr_from_string(mac, &network->mac); +} + +static int network_set_address(Context *context, const char *ifname, int family, unsigned char prefixlen, + union in_addr_union *addr, union in_addr_union *peer) { + Network *network; + + if (in_addr_is_null(family, addr) != 0) + return 0; + + network = network_get(context, ifname); + if (!network) + return -ENODEV; + + return address_new(network, family, prefixlen, addr, peer, NULL); +} + +static int network_set_route(Context *context, const char *ifname, int family, unsigned char prefixlen, + union in_addr_union *dest, union in_addr_union *gateway) { + Network *network; + int r; + + if (in_addr_is_null(family, gateway) != 0) + return 0; + + network = network_get(context, ifname); + if (!network) { + r = network_new(context, ifname, &network); + if (r < 0) + return r; + } + + return route_new(network, family, prefixlen, dest, gateway, NULL); +} + +static int network_set_dns(Context *context, const char *ifname, const char *dns) { + union in_addr_union a; + Network *network; + int family, r; + + r = in_addr_from_string_auto(dns, &family, &a); + if (r < 0) + return r; + + network = network_get(context, ifname); + if (!network) { + r = network_new(context, ifname, &network); + if (r < 0) + return r; + } + + return strv_extend(&network->dns, dns); +} + +static int network_set_dhcp_use_dns(Context *context, const char *ifname, bool value) { + Network *network; + int r; + + network = network_get(context, ifname); + if (!network) { + r = network_new(context, ifname, &network); + if (r < 0) + return r; + } + + network->dhcp_use_dns = value; + + return 0; +} + +static int network_set_vlan(Context *context, const char *ifname, const char *value) { + Network *network; + int r; + + network = network_get(context, ifname); + if (!network) { + r = network_new(context, ifname, &network); + if (r < 0) + return r; + } + + return free_and_strdup(&network->vlan, value); +} + +static int network_set_bridge(Context *context, const char *ifname, const char *value) { + Network *network; + int r; + + network = network_get(context, ifname); + if (!network) { + r = network_new(context, ifname, &network); + if (r < 0) + return r; + } + + return free_and_strdup(&network->bridge, value); +} + +static int network_set_bond(Context *context, const char *ifname, const char *value) { + Network *network; + int r; + + network = network_get(context, ifname); + if (!network) { + r = network_new(context, ifname, &network); + if (r < 0) + return r; + } + + return free_and_strdup(&network->bond, value); +} + +static int parse_cmdline_ip_mtu_mac(Context *context, const char *ifname, int family, const char *value) { + const char *mtu, *p; + int r; + + /* [][:] */ + + p = strchr(value, ':'); + if (!p) + mtu = value; + else + mtu = strndupa(value, p - value); + + r = network_set_mtu(context, ifname, family, mtu); + if (r < 0) + return r; + + if (!p) + return 0; + + r = network_set_mac_address(context, ifname, p + 1); + if (r < 0) + return r; + + return 0; +} + +static int parse_ip_address_one(int family, const char **value, union in_addr_union *ret) { + const char *p = *value, *q, *buf; + int r; + + if (p[0] == ':') { + *value = p + 1; + return 0; + } + + if (family == AF_INET6) { + if (p[0] != '[') + return -EINVAL; + + q = strchr(p + 1, ']'); + if (!q) + return -EINVAL; + + if (q[1] != ':') + return -EINVAL; + + buf = strndupa(p + 1, q - p - 1); + p = q + 2; + } else { + q = strchr(p, ':'); + if (!q) + return -EINVAL; + + buf = strndupa(p, q - p); + p = q + 1; + } + + r = in_addr_from_string(family, buf, ret); + if (r < 0) + return r; + + *value = p; + return 1; +} + +static int parse_netmask_or_prefixlen(int family, const char **value, unsigned char *ret) { + union in_addr_union netmask; + const char *p, *q; + int r; + + r = parse_ip_address_one(family, value, &netmask); + if (r > 0) { + if (family == AF_INET6) + /* TODO: Not supported yet. */ + return -EINVAL; + + *ret = in4_addr_netmask_to_prefixlen(&netmask.in); + } else if (r == 0) + *ret = family == AF_INET6 ? 128 : 32; + else { + p = strchr(*value, ':'); + if (!p) + return -EINVAL; + + q = strndupa(*value, p - *value); + r = safe_atou8(q, ret); + if (r < 0) + return r; + + *value = p + 1; + } + + return 0; +} + +static int parse_cmdline_ip_address(Context *context, int family, const char *value) { + union in_addr_union addr = {}, peer = {}, gateway = {}; + const char *hostname, *ifname, *dhcp_type, *dns, *p; + unsigned char prefixlen; + int r; + + /* ip=:[]:::::{none|off|dhcp|on|any|dhcp6|auto6|ibft}[:[][:]] + * ip=:[]:::::{none|off|dhcp|on|any|dhcp6|auto6|ibft}[:[][:]] */ + + r = parse_ip_address_one(family, &value, &addr); + if (r < 0) + return r; + r = parse_ip_address_one(family, &value, &peer); + if (r < 0) + return r; + r = parse_ip_address_one(family, &value, &gateway); + if (r < 0) + return r; + r = parse_netmask_or_prefixlen(family, &value, &prefixlen); + if (r < 0) + return r; + + /* hostname */ + p = strchr(value, ':'); + if (!p) + return -EINVAL; + + hostname = strndupa(value, p - value); + if (!hostname_is_valid(hostname, false)) + return -EINVAL; + + value = p + 1; + + /* ifname */ + p = strchr(value, ':'); + if (!p) + return -EINVAL; + + ifname = strndupa(value, p - value); + + value = p + 1; + + /* dhcp_type */ + p = strchr(value, ':'); + if (!p) + dhcp_type = value; + else + dhcp_type = strndupa(value, p - value); + + r = network_set_dhcp_type(context, ifname, dhcp_type); + if (r < 0) + return r; + + /* set values */ + r = network_set_hostname(context, ifname, hostname); + if (r < 0) + return r; + + r = network_set_address(context, ifname, family, prefixlen, &addr, &peer); + if (r < 0) + return r; + + r = network_set_route(context, ifname, family, 0, NULL, &gateway); + if (r < 0) + return r; + + if (!p) + return 0; + + /* First, try [][:] */ + r = parse_cmdline_ip_mtu_mac(context, ifname, AF_UNSPEC, p + 1); + if (r >= 0) + return 0; + + /* Next, try [][:] */ + value = p + 1; + p = strchr(value, ':'); + if (!p) { + r = network_set_dns(context, ifname, value); + if (r < 0) + return r; + } else { + dns = strndupa(value, p - value); + r = network_set_dns(context, ifname, dns); + if (r < 0) + return r; + r = network_set_dns(context, ifname, p + 1); + if (r < 0) + return r; + } + + return 0; +} + +static int parse_cmdline_ip_interface(Context *context, const char *value) { + const char *ifname, *dhcp_type, *p; + int r; + + /* ip=:{dhcp|on|any|dhcp6|auto6}[:[][:]] */ + + p = strchr(value, ':'); + if (!p) + return -EINVAL; + + ifname = strndupa(value, p - value); + + value = p + 1; + p = strchr(value, ':'); + if (!p) + dhcp_type = value; + else + dhcp_type = strndupa(value, p - value); + + r = network_set_dhcp_type(context, ifname, dhcp_type); + if (r < 0) + return r; + + if (!p) + return 0; + + return parse_cmdline_ip_mtu_mac(context, ifname, AF_UNSPEC, p + 1); +} + +static int parse_cmdline_ip(Context *context, const char *key, const char *value) { + const char *p; + int r; + + if (proc_cmdline_value_missing(key, value)) + return -EINVAL; + + p = strchr(value, ':'); + if (!p) + /* ip={dhcp|on|any|dhcp6|auto6|either6} */ + return network_set_dhcp_type(context, "", value); + + if (value[0] == '[') + return parse_cmdline_ip_address(context, AF_INET6, value); + + r = parse_cmdline_ip_address(context, AF_INET, value); + if (r < 0) + return parse_cmdline_ip_interface(context, value); + + return 0; +} + +static int parse_cmdline_rd_route(Context *context, const char *key, const char *value) { + union in_addr_union addr = {}, gateway = {}; + unsigned char prefixlen; + const char *buf, *p; + int family, r; + + /* rd.route=/:[:] */ + + if (proc_cmdline_value_missing(key, value)) + return -EINVAL; + + if (value[0] == '[') { + p = strchr(value, ']'); + if (!p) + return -EINVAL; + + if (p[1] != ':') + return -EINVAL; + + buf = strndupa(value + 1, p - value - 1); + value = p + 2; + family = AF_INET6; + } else { + p = strchr(value, ':'); + if (!p) + return -EINVAL; + + buf = strndupa(value, p - value); + value = p + 1; + family = AF_INET; + } + + r = in_addr_prefix_from_string(buf, family, &addr, &prefixlen); + if (r < 0) + return r; + + p = strchr(value, ':'); + if (!p) + value = strjoina(value, ":"); + + r = parse_ip_address_one(family, &value, &gateway); + if (r < 0) + return r; + + return network_set_route(context, value, family, prefixlen, &addr, &gateway); +} + +static int parse_cmdline_nameserver(Context *context, const char *key, const char *value) { + if (proc_cmdline_value_missing(key, value)) + return -EINVAL; + + return network_set_dns(context, "", value); +} + +static int parse_cmdline_rd_peerdns(Context *context, const char *key, const char *value) { + int r; + + if (proc_cmdline_value_missing(key, value)) + return network_set_dhcp_use_dns(context, "", true); + + r = parse_boolean(value); + if (r < 0) + return r; + + return network_set_dhcp_use_dns(context, "", r); +} + +static int parse_cmdline_vlan(Context *context, const char *key, const char *value) { + const char *name, *p; + NetDev *netdev; + int r; + + if (proc_cmdline_value_missing(key, value)) + return -EINVAL; + + p = strchr(value, ':'); + if (!p) + return -EINVAL; + + name = strndupa(value, p - value); + + netdev = netdev_get(context, name); + if (!netdev) { + r = netdev_new(context, "vlan", name, &netdev); + if (r < 0) + return r; + } + + return network_set_vlan(context, p + 1, name); +} + +static int parse_cmdline_bridge(Context *context, const char *key, const char *value) { + const char *name, *p; + NetDev *netdev; + int r; + + if (proc_cmdline_value_missing(key, value)) + return -EINVAL; + + p = strchr(value, ':'); + if (!p) + return -EINVAL; + + name = strndupa(value, p - value); + + netdev = netdev_get(context, name); + if (!netdev) { + r = netdev_new(context, "bridge", name, &netdev); + if (r < 0) + return r; + } + + p++; + if (isempty(p)) + return -EINVAL; + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, ",", 0); + if (r <= 0) + return r; + + r = network_set_bridge(context, word, name); + if (r < 0) + return r; + } +} + +static int parse_cmdline_bond(Context *context, const char *key, const char *value) { + const char *name, *slaves, *p; + NetDev *netdev; + int r; + + if (proc_cmdline_value_missing(key, value)) + return -EINVAL; + + p = strchr(value, ':'); + if (!p) + return -EINVAL; + + name = strndupa(value, p - value); + + netdev = netdev_get(context, name); + if (!netdev) { + r = netdev_new(context, "bond", name, &netdev); + if (r < 0) + return r; + } + + value = p + 1; + p = strchr(value, ':'); + if (!p) + slaves = value; + else + slaves = strndupa(value, p - value); + + if (isempty(slaves)) + return -EINVAL; + + for (const char *q = slaves; ; ) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&q, &word, ",", 0); + if (r == 0) + break; + if (r < 0) + return r; + + r = network_set_bond(context, word, name); + if (r < 0) + return r; + } + + if (!p) + return 0; + + value = p + 1; + p = strchr(value, ':'); + if (!p) + /* TODO: set bonding options */ + return 0; + + return parse_mtu(AF_UNSPEC, p + 1, &netdev->mtu); +} + +static int parse_cmdline_ifname(Context *context, const char *key, const char *value) { + struct ether_addr mac; + const char *name, *p; + int r; + + /* ifname=: */ + + if (proc_cmdline_value_missing(key, value)) + return -EINVAL; + + p = strchr(value, ':'); + if (!p) + return -EINVAL; + + name = strndupa(value, p - value); + + r = ether_addr_from_string(p + 1, &mac); + if (r < 0) + return r; + + return link_new(context, name, &mac, NULL); +} + +int parse_cmdline_item(const char *key, const char *value, void *data) { + Context *context = data; + + assert(key); + assert(data); + + if (streq(key, "ip")) + return parse_cmdline_ip(context, key, value); + if (streq(key, "rd.route")) + return parse_cmdline_rd_route(context, key, value); + if (streq(key, "nameserver")) + return parse_cmdline_nameserver(context, key, value); + if (streq(key, "rd.peerdns")) + return parse_cmdline_rd_peerdns(context, key, value); + if (streq(key, "vlan")) + return parse_cmdline_vlan(context, key, value); + if (streq(key, "bridge")) + return parse_cmdline_bridge(context, key, value); + if (streq(key, "bond")) + return parse_cmdline_bond(context, key, value); + if (streq(key, "ifname")) + return parse_cmdline_ifname(context, key, value); + + return 0; +} + +int context_merge_networks(Context *context) { + Network *all, *network; + Route *route; + Iterator i; + int r; + + assert(context); + + /* Copy settings about the following options + rd.route=/:[:] + nameserver= [nameserver= ...] + rd.peerdns=0 */ + + all = network_get(context, ""); + if (!all) + return 0; + + if (hashmap_size(context->networks_by_name) <= 1) + return 0; + + HASHMAP_FOREACH(network, context->networks_by_name, i) { + if (network == all) + continue; + + network->dhcp_use_dns = all->dhcp_use_dns; + + r = strv_extend_strv(&network->dns, all->dns, false); + if (r < 0) + return r; + + LIST_FOREACH(routes, route, all->routes) { + r = route_new(network, route->family, route->prefixlen, &route->dest, &route->gateway, NULL); + if (r < 0) + return r; + } + } + + assert_se(hashmap_remove(context->networks_by_name, "") == all); + network_free(all); + return 0; +} + +void context_clear(Context *context) { + if (!context) + return; + + hashmap_free_with_destructor(context->networks_by_name, network_free); + hashmap_free_with_destructor(context->netdevs_by_name, netdev_free); + hashmap_free_with_destructor(context->links_by_name, link_free); +} + +static int address_dump(Address *address, FILE *f) { + _cleanup_free_ char *addr = NULL, *peer = NULL; + int r; + + r = in_addr_prefix_to_string(address->family, &address->address, address->prefixlen, &addr); + if (r < 0) + return r; + + if (in_addr_is_null(address->family, &address->peer) == 0) { + r = in_addr_to_string(address->family, &address->peer, &peer); + if (r < 0) + return r; + } + + fprintf(f, + "\n[Address]\n" + "Address=%s\n", + addr); + + if (peer) + fprintf(f, "Peer=%s\n", peer); + + return 0; +} + +static int route_dump(Route *route, FILE *f) { + _cleanup_free_ char *dest = NULL, *gateway = NULL; + int r; + + if (in_addr_is_null(route->family, &route->dest) == 0) { + r = in_addr_prefix_to_string(route->family, &route->dest, route->prefixlen, &dest); + if (r < 0) + return r; + } + + r = in_addr_to_string(route->family, &route->gateway, &gateway); + if (r < 0) + return r; + + fputs("\n[Route]\n", f); + if (dest) + fprintf(f, "Destination=%s\n", dest); + fprintf(f, "Gateway=%s\n", gateway); + + return 0; +} + +void network_dump(Network *network, FILE *f) { + char mac[ETHER_ADDR_TO_STRING_MAX]; + Address *address; + Route *route; + const char *dhcp; + char **dns; + + assert(network); + assert(f); + + fprintf(f, + "[Match]\n" + "Name=%s\n", + isempty(network->ifname) ? "*" : network->ifname); + + fputs("\n[Link]\n", f); + + if (!ether_addr_is_null(&network->mac)) + fprintf(f, "MACAddress=%s\n", ether_addr_to_string(&network->mac, mac)); + if (network->mtu > 0) + fprintf(f, "MTUBytes=%" PRIu32 "\n", network->mtu); + + fputs("\n[Network]\n", f); + + dhcp = networkd_dhcp_type_to_string(network->dhcp_type); + if (dhcp) + fprintf(f, "DHCP=%s\n", dhcp); + + if (!strv_isempty(network->dns)) + STRV_FOREACH(dns, network->dns) + fprintf(f, "DNS=%s\n", *dns); + + if (network->vlan) + fprintf(f, "VLAN=%s\n", network->vlan); + + if (network->bridge) + fprintf(f, "Bridge=%s\n", network->bridge); + + if (network->bond) + fprintf(f, "Bond=%s\n", network->bond); + + fputs("\n[DHCP]\n", f); + + if (!isempty(network->hostname)) + fprintf(f, "Hostname=%s\n", network->hostname); + + if (network->dhcp_use_dns >= 0) + fprintf(f, "UseDNS=%s\n", yes_no(network->dhcp_use_dns)); + + LIST_FOREACH(addresses, address, network->addresses) + (void) address_dump(address, f); + + LIST_FOREACH(routes, route, network->routes) + (void) route_dump(route, f); +} + +void netdev_dump(NetDev *netdev, FILE *f) { + assert(netdev); + assert(f); + + fprintf(f, + "[NetDev]\n" + "Kind=%s\n" + "Name=%s\n", + netdev->kind, + netdev->ifname); + + if (netdev->mtu > 0) + fprintf(f, "MTUBytes=%" PRIu32 "\n", netdev->mtu); +} + +void link_dump(Link *link, FILE *f) { + char mac[ETHER_ADDR_TO_STRING_MAX]; + + assert(link); + assert(f); + + fputs("[Match]\n", f); + + if (!ether_addr_is_null(&link->mac)) + fprintf(f, "MACAddress=%s\n", ether_addr_to_string(&link->mac, mac)); + + fprintf(f, + "\n[Link]\n" + "Name=%s\n", + link->ifname); +} + +int network_format(Network *network, char **ret) { + _cleanup_free_ char *s = NULL; + size_t sz = 0; + int r; + + assert(network); + assert(ret); + + { + _cleanup_fclose_ FILE *f = NULL; + + f = open_memstream_unlocked(&s, &sz); + if (!f) + return -ENOMEM; + + network_dump(network, f); + + /* Add terminating 0, so that the output buffer is a valid string. */ + fputc('\0', f); + + r = fflush_and_check(f); + } + if (r < 0) + return r; + + assert(s); + *ret = TAKE_PTR(s); + assert(sz > 0); + return (int) sz - 1; +} + +int netdev_format(NetDev *netdev, char **ret) { + _cleanup_free_ char *s = NULL; + size_t sz = 0; + int r; + + assert(netdev); + assert(ret); + + { + _cleanup_fclose_ FILE *f = NULL; + + f = open_memstream_unlocked(&s, &sz); + if (!f) + return -ENOMEM; + + netdev_dump(netdev, f); + + /* Add terminating 0, so that the output buffer is a valid string. */ + fputc('\0', f); + + r = fflush_and_check(f); + } + if (r < 0) + return r; + + assert(s); + *ret = TAKE_PTR(s); + assert(sz > 0); + return (int) sz - 1; +} + +int link_format(Link *link, char **ret) { + _cleanup_free_ char *s = NULL; + size_t sz = 0; + int r; + + assert(link); + assert(ret); + + { + _cleanup_fclose_ FILE *f = NULL; + + f = open_memstream_unlocked(&s, &sz); + if (!f) + return -ENOMEM; + + link_dump(link, f); + + /* Add terminating 0, so that the output buffer is a valid string. */ + fputc('\0', f); + + r = fflush_and_check(f); + } + if (r < 0) + return r; + + assert(s); + *ret = TAKE_PTR(s); + assert(sz > 0); + return (int) sz - 1; +} diff --git a/src/network/generator/network-generator.h b/src/network/generator/network-generator.h new file mode 100644 index 00000000..3d75b132 --- /dev/null +++ b/src/network/generator/network-generator.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "hashmap.h" +#include "in-addr-util.h" +#include "list.h" + +typedef enum DHCPType { + DHCP_TYPE_NONE, + DHCP_TYPE_OFF, + DHCP_TYPE_ON, + DHCP_TYPE_ANY, + DHCP_TYPE_DHCP, + DHCP_TYPE_DHCP6, + DHCP_TYPE_AUTO6, + DHCP_TYPE_EITHER6, + DHCP_TYPE_IBFT, + _DHCP_TYPE_MAX, + _DHCP_TYPE_INVALID = -1, +} DHCPType; + +typedef struct Address Address; +typedef struct Link Link; +typedef struct NetDev NetDev; +typedef struct Network Network; +typedef struct Route Route; +typedef struct Context Context; + +struct Address { + Network *network; + + union in_addr_union address, peer; + unsigned char prefixlen; + int family; + + LIST_FIELDS(Address, addresses); +}; + +struct Route { + Network *network; + + union in_addr_union dest, gateway; + unsigned char prefixlen; + int family; + + LIST_FIELDS(Route, routes); +}; + +struct Network { + /* [Match] */ + char *ifname; + + /* [Link] */ + struct ether_addr mac; + uint32_t mtu; + + /* [Network] */ + DHCPType dhcp_type; + char **dns; + char *vlan; + char *bridge; + char *bond; + + /* [DHCP] */ + char *hostname; + int dhcp_use_dns; + + LIST_HEAD(Address, addresses); + LIST_HEAD(Route, routes); +}; + +struct NetDev { + /* [NetDev] */ + char *ifname; + char *kind; + uint32_t mtu; +}; + +struct Link { + /* [Match] */ + char *ifname; + struct ether_addr mac; +}; + +typedef struct Context { + Hashmap *networks_by_name; + Hashmap *netdevs_by_name; + Hashmap *links_by_name; +} Context; + +int parse_cmdline_item(const char *key, const char *value, void *data); +int context_merge_networks(Context *context); +void context_clear(Context *context); + +Network *network_get(Context *context, const char *ifname); +void network_dump(Network *network, FILE *f); +int network_format(Network *network, char **ret); + +NetDev *netdev_get(Context *context, const char *ifname); +void netdev_dump(NetDev *netdev, FILE *f); +int netdev_format(NetDev *netdev, char **ret); + +Link *link_get(Context *context, const char *ifname); +void link_dump(Link *link, FILE *f); +int link_format(Link *link, char **ret); diff --git a/src/network/generator/test-network-generator.c b/src/network/generator/test-network-generator.c new file mode 100644 index 00000000..efcbdefd --- /dev/null +++ b/src/network/generator/test-network-generator.c @@ -0,0 +1,438 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "macro.h" +#include "network-generator.h" +#include "string-util.h" + +static void test_network_one(const char *ifname, const char *key, const char *value, const char *expected) { + _cleanup_(context_clear) Context context = {}; + _cleanup_free_ char *output = NULL; + Network *network; + + printf("# %s=%s\n", key, value); + assert_se(parse_cmdline_item(key, value, &context) >= 0); + assert_se(network = network_get(&context, ifname)); + assert_se(network_format(network, &output) >= 0); + puts(output); + assert_se(streq(output, expected)); +} + +static void test_network_two(const char *ifname, + const char *key1, const char *value1, + const char *key2, const char *value2, + const char *expected) { + _cleanup_(context_clear) Context context = {}; + _cleanup_free_ char *output = NULL; + Network *network; + + printf("# %s=%s\n", key1, value1); + printf("# %s=%s\n", key2, value2); + assert_se(parse_cmdline_item(key1, value1, &context) >= 0); + assert_se(parse_cmdline_item(key2, value2, &context) >= 0); + assert_se(context_merge_networks(&context) >= 0); + assert_se(network = network_get(&context, ifname)); + assert_se(network_format(network, &output) >= 0); + puts(output); + assert_se(streq(output, expected)); +} + +static void test_netdev_one(const char *ifname, const char *key, const char *value, const char *expected) { + _cleanup_(context_clear) Context context = {}; + _cleanup_free_ char *output = NULL; + NetDev *netdev; + + printf("# %s=%s\n", key, value); + assert_se(parse_cmdline_item(key, value, &context) >= 0); + assert_se(netdev = netdev_get(&context, ifname)); + assert_se(netdev_format(netdev, &output) >= 0); + puts(output); + assert_se(streq(output, expected)); +} + +static void test_link_one(const char *ifname, const char *key, const char *value, const char *expected) { + _cleanup_(context_clear) Context context = {}; + _cleanup_free_ char *output = NULL; + Link *link; + + printf("# %s=%s\n", key, value); + assert_se(parse_cmdline_item(key, value, &context) >= 0); + assert_se(link = link_get(&context, ifname)); + assert_se(link_format(link, &output) >= 0); + puts(output); + assert_se(streq(output, expected)); +} + +int main(int argc, char *argv[]) { + test_network_one("", "ip", "dhcp6", + "[Match]\n" + "Name=*\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=ipv6\n" + "\n[DHCP]\n" + ); + + test_network_one("eth0", "ip", "eth0:dhcp", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=ipv4\n" + "\n[DHCP]\n" + ); + + test_network_one("eth0", "ip", "eth0:dhcp:1530", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "MTUBytes=1530\n" + "\n[Network]\n" + "DHCP=ipv4\n" + "\n[DHCP]\n" + ); + + test_network_one("eth0", "ip", "eth0:dhcp:1530:00:11:22:33:44:55", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "MACAddress=00:11:22:33:44:55\n" + "MTUBytes=1530\n" + "\n[Network]\n" + "DHCP=ipv4\n" + "\n[DHCP]\n" + ); + + test_network_one("eth0", "ip", "192.168.0.10::192.168.0.1:255.255.255.0:hogehoge:eth0:on", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + test_network_one("eth0", "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "Peer=192.168.0.2\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + test_network_one("eth0", "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on:1530", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "MTUBytes=1530\n" + "\n[Network]\n" + "DHCP=yes\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "Peer=192.168.0.2\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + test_network_one("eth0", "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on:1530:00:11:22:33:44:55", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "MACAddress=00:11:22:33:44:55\n" + "MTUBytes=1530\n" + "\n[Network]\n" + "DHCP=yes\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "Peer=192.168.0.2\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + test_network_one("eth0", "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on:10.10.10.10", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "DNS=10.10.10.10\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "Peer=192.168.0.2\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + test_network_one("eth0", "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on:10.10.10.10:10.10.10.11", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "DNS=10.10.10.10\n" + "DNS=10.10.10.11\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "Peer=192.168.0.2\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + test_network_one("eth0", "ip", "[2001:1234:56:8f63::10]::[2001:1234:56:8f63::1]:64:hogehoge:eth0:on", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=2001:1234:56:8f63::10/64\n" + "\n[Route]\n" + "Gateway=2001:1234:56:8f63::1\n" + ); + + test_network_one("eth0", "ip", "[2001:1234:56:8f63::10]:[2001:1234:56:8f63::2]:[2001:1234:56:8f63::1]:64:hogehoge:eth0:on", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=2001:1234:56:8f63::10/64\n" + "Peer=2001:1234:56:8f63::2\n" + "\n[Route]\n" + "Gateway=2001:1234:56:8f63::1\n" + ); + + test_network_one("", "rd.route", "10.1.2.3/16:10.0.2.3", + "[Match]\n" + "Name=*\n" + "\n[Link]\n" + "\n[Network]\n" + "\n[DHCP]\n" + "\n[Route]\n" + "Destination=10.1.2.3/16\n" + "Gateway=10.0.2.3\n" + ); + + test_network_one("eth0", "rd.route", "10.1.2.3/16:10.0.2.3:eth0", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "\n[DHCP]\n" + "\n[Route]\n" + "Destination=10.1.2.3/16\n" + "Gateway=10.0.2.3\n" + ); + + test_network_one("", "nameserver", "10.1.2.3", + "[Match]\n" + "Name=*\n" + "\n[Link]\n" + "\n[Network]\n" + "DNS=10.1.2.3\n" + "\n[DHCP]\n" + ); + + test_network_one("", "rd.peerdns", "0", + "[Match]\n" + "Name=*\n" + "\n[Link]\n" + "\n[Network]\n" + "\n[DHCP]\n" + "UseDNS=no\n" + ); + + test_network_one("", "rd.peerdns", "1", + "[Match]\n" + "Name=*\n" + "\n[Link]\n" + "\n[Network]\n" + "\n[DHCP]\n" + "UseDNS=yes\n" + ); + + test_network_one("eth0", "vlan", "vlan99:eth0", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "VLAN=vlan99\n" + "\n[DHCP]\n" + ); + + test_network_one("eth0", "bridge", "bridge99:eth0,eth1", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "Bridge=bridge99\n" + "\n[DHCP]\n" + ); + + test_network_one("eth1", "bridge", "bridge99:eth0,eth1", + "[Match]\n" + "Name=eth1\n" + "\n[Link]\n" + "\n[Network]\n" + "Bridge=bridge99\n" + "\n[DHCP]\n" + ); + + test_network_one("eth0", "bond", "bond99:eth0,eth1", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "Bond=bond99\n" + "\n[DHCP]\n" + ); + + test_network_one("eth1", "bond", "bond99:eth0,eth1::1530", + "[Match]\n" + "Name=eth1\n" + "\n[Link]\n" + "\n[Network]\n" + "Bond=bond99\n" + "\n[DHCP]\n" + ); + + test_netdev_one("bond99", "bond", "bond99:eth0,eth1::1530", + "[NetDev]\n" + "Kind=bond\n" + "Name=bond99\n" + "MTUBytes=1530\n" + ); + + test_link_one("hogehoge", "ifname", "hogehoge:00:11:22:33:44:55", + "[Match]\n" + "MACAddress=00:11:22:33:44:55\n" + "\n[Link]\n" + "Name=hogehoge\n" + ); + + test_network_two("eth0", + "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on:10.10.10.10:10.10.10.11", + "rd.route", "10.1.2.3/16:10.0.2.3", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "DNS=10.10.10.10\n" + "DNS=10.10.10.11\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "Peer=192.168.0.2\n" + "\n[Route]\n" + "Destination=10.1.2.3/16\n" + "Gateway=10.0.2.3\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + test_network_two("eth0", + "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on", + "nameserver", "10.1.2.3", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "DNS=10.1.2.3\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "Peer=192.168.0.2\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + test_network_two("eth0", + "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on:10.10.10.10:10.10.10.11", + "nameserver", "10.1.2.3", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "DNS=10.10.10.10\n" + "DNS=10.10.10.11\n" + "DNS=10.1.2.3\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "Peer=192.168.0.2\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + test_network_two("eth0", + "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on:10.10.10.10:10.10.10.11", + "rd.peerdns", "1", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "DNS=10.10.10.10\n" + "DNS=10.10.10.11\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "UseDNS=yes\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "Peer=192.168.0.2\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + test_network_two("eth0", + "ip", "192.168.0.10:192.168.0.2:192.168.0.1:255.255.255.0:hogehoge:eth0:on:10.10.10.10:10.10.10.11", + "bridge", "bridge99:eth0,eth1", + "[Match]\n" + "Name=eth0\n" + "\n[Link]\n" + "\n[Network]\n" + "DHCP=yes\n" + "DNS=10.10.10.10\n" + "DNS=10.10.10.11\n" + "Bridge=bridge99\n" + "\n[DHCP]\n" + "Hostname=hogehoge\n" + "\n[Address]\n" + "Address=192.168.0.10/24\n" + "Peer=192.168.0.2\n" + "\n[Route]\n" + "Gateway=192.168.0.1\n" + ); + + return 0; +} diff --git a/src/network/meson.build b/src/network/meson.build new file mode 100644 index 00000000..d5022791 --- /dev/null +++ b/src/network/meson.build @@ -0,0 +1,243 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +sources = files(''' + netdev/bond.c + netdev/bond.h + netdev/bridge.c + netdev/bridge.h + netdev/dummy.c + netdev/dummy.h + netdev/ipvlan.c + netdev/ipvlan.h + netdev/macvlan.c + netdev/macvlan.h + netdev/netdev.c + netdev/netdev.h + netdev/nlmon.c + netdev/nlmon.h + netdev/tunnel.c + netdev/tunnel.h + netdev/tuntap.c + netdev/tuntap.h + netdev/vcan.c + netdev/vcan.h + netdev/veth.c + netdev/veth.h + netdev/vlan.c + netdev/vlan.h + netdev/vrf.c + netdev/vrf.h + netdev/vxlan.c + netdev/vxlan.h + netdev/geneve.c + netdev/geneve.h + netdev/vxcan.c + netdev/vxcan.h + netdev/wireguard.c + netdev/wireguard.h + netdev/netdevsim.c + netdev/netdevsim.h + netdev/fou-tunnel.c + netdev/fou-tunnel.h + netdev/l2tp-tunnel.c + netdev/l2tp-tunnel.h + netdev/macsec.c + netdev/macsec.h + netdev/xfrm.c + netdev/xfrm.h + networkd-address-label.c + networkd-address-label.h + networkd-address-pool.c + networkd-address-pool.h + networkd-address.c + networkd-address.h + networkd-brvlan.c + networkd-brvlan.h + networkd-can.c + networkd-can.h + networkd-conf.c + networkd-conf.h + networkd-dhcp-common.c + networkd-dhcp-common.h + networkd-dhcp-server.c + networkd-dhcp-server.h + networkd-dhcp4.c + networkd-dhcp4.h + networkd-dhcp6.c + networkd-dhcp6.h + networkd-fdb.c + networkd-fdb.h + networkd-ipv4ll.c + networkd-ipv4ll.h + networkd-ipv6-proxy-ndp.c + networkd-ipv6-proxy-ndp.h + networkd-link-bus.c + networkd-link-bus.h + networkd-link.c + networkd-link.h + networkd-lldp-rx.c + networkd-lldp-rx.h + networkd-lldp-tx.c + networkd-lldp-tx.h + networkd-manager-bus.c + networkd-manager-bus.h + networkd-manager.c + networkd-manager.h + networkd-ndisc.c + networkd-ndisc.h + networkd-neighbor.c + networkd-neighbor.h + networkd-radv.c + networkd-radv.h + networkd-network-bus.c + networkd-network-bus.h + networkd-network.c + networkd-network.h + networkd-nexthop.c + networkd-nexthop.h + networkd-route.c + networkd-route.h + networkd-routing-policy-rule.c + networkd-routing-policy-rule.h + networkd-speed-meter.c + networkd-speed-meter.h + networkd-util.c + networkd-util.h + networkd-wifi.c + networkd-wifi.h + tc/netem.c + tc/netem.h + tc/qdisc.c + tc/qdisc.h + tc/tc-util.c + tc/tc-util.h +'''.split()) + +systemd_networkd_sources = files('networkd.c') + +systemd_networkd_wait_online_sources = files(''' + wait-online/link.c + wait-online/link.h + wait-online/manager.c + wait-online/manager.h + wait-online/wait-online.c +'''.split()) + network_internal_h + +networkctl_sources = files('networkctl.c') + +network_generator_sources = files(''' + generator/main.c + generator/network-generator.c + generator/network-generator.h +'''.split()) + +network_include_dir = [includes, include_directories(['.', 'netdev', 'tc'])] + +if conf.get('ENABLE_NETWORKD') == 1 + networkd_gperf_c = custom_target( + 'networkd-gperf.c', + input : 'networkd-gperf.gperf', + output : 'networkd-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + + networkd_network_gperf_c = custom_target( + 'networkd-network-gperf.c', + input : 'networkd-network-gperf.gperf', + output : 'networkd-network-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + + netdev_gperf_c = custom_target( + 'netdev-gperf.c', + input : 'netdev/netdev-gperf.gperf', + output : 'netdev-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + + libnetworkd_core = static_library( + 'networkd-core', + sources, + network_internal_h, + networkd_gperf_c, + networkd_network_gperf_c, + netdev_gperf_c, + include_directories : network_include_dir, + link_with : [libshared]) + + install_data('org.freedesktop.network1.conf', + install_dir : dbuspolicydir) + install_data('org.freedesktop.network1.service', + install_dir : dbussystemservicedir) + install_data('org.freedesktop.network1.policy', + install_dir : polkitpolicydir) + if install_polkit + install_data('systemd-networkd.rules', + install_dir : polkitrulesdir) + endif + if install_polkit_pkla + install_data('systemd-networkd.pkla', + install_dir : polkitpkladir) + endif + + install_data('networkd.conf', + install_dir : pkgsysconfdir) + + fuzzers += [ + [['src/network/fuzz-netdev-parser.c', + 'src/fuzz/fuzz.h'], + [libnetworkd_core, + libudev_static, + libsystemd_network, + libshared], + [threads], + [], + network_include_dir], + + [['src/network/fuzz-network-parser.c', + 'src/fuzz/fuzz.h'], + [libnetworkd_core, + libudev_static, + libsystemd_network, + libshared], + [threads], + [], + network_include_dir], + ] + + tests += [ + [['src/network/test-networkd-conf.c'], + [libnetworkd_core, + libsystemd_network, + libudev], + [], '', '', [], network_include_dir], + + [['src/network/test-network.c'], + [libnetworkd_core, + libudev_static, + libsystemd_network, + libshared], + [threads], + '', '', [], network_include_dir], + + [['src/network/test-routing-policy-rule.c'], + [libnetworkd_core, + libsystemd_network, + libudev], + [], '', '', [], network_include_dir], + + [['src/network/test-network-tables.c', + test_tables_h], + [libnetworkd_core, + libudev_static, + libudev_core, + libsystemd_network, + libshared], + [threads], + '', '', [], + [network_include_dir] + libudev_core_includes], + + [['src/network/generator/test-network-generator.c', + 'src/network/generator/network-generator.c', + 'src/network/generator/network-generator.h'], + [libshared], + [], '', '', [], network_include_dir], + ] +endif diff --git a/src/network/netdev/bond.c b/src/network/netdev/bond.c new file mode 100644 index 00000000..185b1554 --- /dev/null +++ b/src/network/netdev/bond.c @@ -0,0 +1,594 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bond.h" +#include "conf-parser.h" +#include "ether-addr-util.h" +#include "extract-word.h" +#include "netlink-util.h" +#include "networkd-manager.h" +#include "string-table.h" +#include "string-util.h" + +/* + * Number of seconds between instances where the bonding + * driver sends learning packets to each slaves peer switch + */ +#define LEARNING_PACKETS_INTERVAL_MIN_SEC (1 * USEC_PER_SEC) +#define LEARNING_PACKETS_INTERVAL_MAX_SEC (0x7fffffff * USEC_PER_SEC) + +/* Number of IGMP membership reports to be issued after + * a failover event. + */ +#define RESEND_IGMP_MIN 0 +#define RESEND_IGMP_MAX 255 +#define RESEND_IGMP_DEFAULT 1 + +/* + * Number of packets to transmit through a slave before + * moving to the next one. + */ +#define PACKETS_PER_SLAVE_MIN 0 +#define PACKETS_PER_SLAVE_MAX 65535 +#define PACKETS_PER_SLAVE_DEFAULT 1 + +/* + * Number of peer notifications (gratuitous ARPs and + * unsolicited IPv6 Neighbor Advertisements) to be issued after a + * failover event. + */ +#define GRATUITOUS_ARP_MIN 0 +#define GRATUITOUS_ARP_MAX 255 +#define GRATUITOUS_ARP_DEFAULT 1 + +static const char* const bond_mode_table[_NETDEV_BOND_MODE_MAX] = { + [NETDEV_BOND_MODE_BALANCE_RR] = "balance-rr", + [NETDEV_BOND_MODE_ACTIVE_BACKUP] = "active-backup", + [NETDEV_BOND_MODE_BALANCE_XOR] = "balance-xor", + [NETDEV_BOND_MODE_BROADCAST] = "broadcast", + [NETDEV_BOND_MODE_802_3AD] = "802.3ad", + [NETDEV_BOND_MODE_BALANCE_TLB] = "balance-tlb", + [NETDEV_BOND_MODE_BALANCE_ALB] = "balance-alb", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_mode, BondMode); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_mode, bond_mode, BondMode, "Failed to parse bond mode"); + +static const char* const bond_xmit_hash_policy_table[_NETDEV_BOND_XMIT_HASH_POLICY_MAX] = { + [NETDEV_BOND_XMIT_HASH_POLICY_LAYER2] = "layer2", + [NETDEV_BOND_XMIT_HASH_POLICY_LAYER34] = "layer3+4", + [NETDEV_BOND_XMIT_HASH_POLICY_LAYER23] = "layer2+3", + [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23] = "encap2+3", + [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34] = "encap3+4", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_xmit_hash_policy, BondXmitHashPolicy); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_xmit_hash_policy, + bond_xmit_hash_policy, + BondXmitHashPolicy, + "Failed to parse bond transmit hash policy") + +static const char* const bond_lacp_rate_table[_NETDEV_BOND_LACP_RATE_MAX] = { + [NETDEV_BOND_LACP_RATE_SLOW] = "slow", + [NETDEV_BOND_LACP_RATE_FAST] = "fast", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_lacp_rate, BondLacpRate); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_lacp_rate, bond_lacp_rate, BondLacpRate, "Failed to parse bond lacp rate") + +static const char* const bond_ad_select_table[_NETDEV_BOND_AD_SELECT_MAX] = { + [NETDEV_BOND_AD_SELECT_STABLE] = "stable", + [NETDEV_BOND_AD_SELECT_BANDWIDTH] = "bandwidth", + [NETDEV_BOND_AD_SELECT_COUNT] = "count", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_ad_select, BondAdSelect); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_ad_select, bond_ad_select, BondAdSelect, "Failed to parse bond AD select"); + +static const char* const bond_fail_over_mac_table[_NETDEV_BOND_FAIL_OVER_MAC_MAX] = { + [NETDEV_BOND_FAIL_OVER_MAC_NONE] = "none", + [NETDEV_BOND_FAIL_OVER_MAC_ACTIVE] = "active", + [NETDEV_BOND_FAIL_OVER_MAC_FOLLOW] = "follow", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_fail_over_mac, BondFailOverMac); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_fail_over_mac, bond_fail_over_mac, BondFailOverMac, "Failed to parse bond fail over MAC"); + +static const char *const bond_arp_validate_table[_NETDEV_BOND_ARP_VALIDATE_MAX] = { + [NETDEV_BOND_ARP_VALIDATE_NONE] = "none", + [NETDEV_BOND_ARP_VALIDATE_ACTIVE]= "active", + [NETDEV_BOND_ARP_VALIDATE_BACKUP]= "backup", + [NETDEV_BOND_ARP_VALIDATE_ALL]= "all", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_arp_validate, BondArpValidate); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_arp_validate, bond_arp_validate, BondArpValidate, "Failed to parse bond arp validate"); + +static const char *const bond_arp_all_targets_table[_NETDEV_BOND_ARP_ALL_TARGETS_MAX] = { + [NETDEV_BOND_ARP_ALL_TARGETS_ANY] = "any", + [NETDEV_BOND_ARP_ALL_TARGETS_ALL] = "all", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_arp_all_targets, BondArpAllTargets); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_arp_all_targets, bond_arp_all_targets, BondArpAllTargets, "Failed to parse bond Arp all targets"); + +static const char *const bond_primary_reselect_table[_NETDEV_BOND_PRIMARY_RESELECT_MAX] = { + [NETDEV_BOND_PRIMARY_RESELECT_ALWAYS] = "always", + [NETDEV_BOND_PRIMARY_RESELECT_BETTER]= "better", + [NETDEV_BOND_PRIMARY_RESELECT_FAILURE]= "failure", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_primary_reselect, BondPrimaryReselect); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_primary_reselect, bond_primary_reselect, BondPrimaryReselect, "Failed to parse bond primary reselect"); + +static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + Bond *b; + int r; + + assert(netdev); + assert(!link); + assert(m); + + b = BOND(netdev); + + assert(b); + + if (b->mode != _NETDEV_BOND_MODE_INVALID) { + r = sd_netlink_message_append_u8(m, IFLA_BOND_MODE, b->mode); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MODE attribute: %m"); + } + + if (b->xmit_hash_policy != _NETDEV_BOND_XMIT_HASH_POLICY_INVALID) { + r = sd_netlink_message_append_u8(m, IFLA_BOND_XMIT_HASH_POLICY, b->xmit_hash_policy); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_XMIT_HASH_POLICY attribute: %m"); + } + + if (b->lacp_rate != _NETDEV_BOND_LACP_RATE_INVALID && + b->mode == NETDEV_BOND_MODE_802_3AD) { + r = sd_netlink_message_append_u8(m, IFLA_BOND_AD_LACP_RATE, b->lacp_rate); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_LACP_RATE attribute: %m"); + } + + if (b->miimon != 0) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_MIIMON, b->miimon / USEC_PER_MSEC); + if (r < 0) + log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_BOND_MIIMON attribute: %m"); + } + + if (b->downdelay != 0) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_DOWNDELAY, b->downdelay / USEC_PER_MSEC); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_DOWNDELAY attribute: %m"); + } + + if (b->updelay != 0) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_UPDELAY, b->updelay / USEC_PER_MSEC); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_UPDELAY attribute: %m"); + } + + if (b->arp_interval != 0) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_INTERVAL, b->arp_interval / USEC_PER_MSEC); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_INTERVAL attribute: %m"); + + if (b->lp_interval >= LEARNING_PACKETS_INTERVAL_MIN_SEC && + b->lp_interval <= LEARNING_PACKETS_INTERVAL_MAX_SEC) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_LP_INTERVAL, b->lp_interval / USEC_PER_SEC); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_LP_INTERVAL attribute: %m"); + } + } + + if (b->ad_select != _NETDEV_BOND_AD_SELECT_INVALID && + b->mode == NETDEV_BOND_MODE_802_3AD) { + r = sd_netlink_message_append_u8(m, IFLA_BOND_AD_SELECT, b->ad_select); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_SELECT attribute: %m"); + } + + if (b->fail_over_mac != _NETDEV_BOND_FAIL_OVER_MAC_INVALID && + b->mode == NETDEV_BOND_MODE_ACTIVE_BACKUP) { + r = sd_netlink_message_append_u8(m, IFLA_BOND_FAIL_OVER_MAC, b->fail_over_mac); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_FAIL_OVER_MAC attribute: %m"); + } + + if (b->arp_validate != _NETDEV_BOND_ARP_VALIDATE_INVALID) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_VALIDATE, b->arp_validate); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_VALIDATE attribute: %m"); + } + + if (b->arp_all_targets != _NETDEV_BOND_ARP_ALL_TARGETS_INVALID) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->arp_all_targets); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); + } + + if (b->primary_reselect != _NETDEV_BOND_PRIMARY_RESELECT_INVALID) { + r = sd_netlink_message_append_u8(m, IFLA_BOND_PRIMARY_RESELECT, b->primary_reselect); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_PRIMARY_RESELECT attribute: %m"); + } + + if (b->resend_igmp <= RESEND_IGMP_MAX) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_RESEND_IGMP, b->resend_igmp); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_RESEND_IGMP attribute: %m"); + } + + if (b->packets_per_slave <= PACKETS_PER_SLAVE_MAX && + b->mode == NETDEV_BOND_MODE_BALANCE_RR) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_PACKETS_PER_SLAVE, b->packets_per_slave); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_PACKETS_PER_SLAVE attribute: %m"); + } + + if (b->num_grat_arp <= GRATUITOUS_ARP_MAX) { + r = sd_netlink_message_append_u8(m, IFLA_BOND_NUM_PEER_NOTIF, b->num_grat_arp); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_NUM_PEER_NOTIF attribute: %m"); + } + + if (b->min_links != 0) { + r = sd_netlink_message_append_u32(m, IFLA_BOND_MIN_LINKS, b->min_links); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MIN_LINKS attribute: %m"); + } + + if (b->ad_actor_sys_prio != 0) { + r = sd_netlink_message_append_u16(m, IFLA_BOND_AD_ACTOR_SYS_PRIO, b->ad_actor_sys_prio); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_ACTOR_SYS_PRIO attribute: %m"); + } + + if (b->ad_user_port_key != 0) { + r = sd_netlink_message_append_u16(m, IFLA_BOND_AD_USER_PORT_KEY, b->ad_user_port_key); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_USER_PORT_KEY attribute: %m"); + } + + if (!ether_addr_is_null(&b->ad_actor_system)) { + r = sd_netlink_message_append_ether_addr(m, IFLA_BOND_AD_ACTOR_SYSTEM, &b->ad_actor_system); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_ACTOR_SYSTEM attribute: %m"); + } + + r = sd_netlink_message_append_u8(m, IFLA_BOND_ALL_SLAVES_ACTIVE, b->all_slaves_active); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ALL_SLAVES_ACTIVE attribute: %m"); + + if (b->tlb_dynamic_lb >= 0) { + r = sd_netlink_message_append_u8(m, IFLA_BOND_TLB_DYNAMIC_LB, b->tlb_dynamic_lb); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_TLB_DYNAMIC_LB attribute: %m"); + } + + if (b->arp_interval > 0 && !ordered_set_isempty(b->arp_ip_targets)) { + Iterator i; + void *val; + int n = 0; + + r = sd_netlink_message_open_container(m, IFLA_BOND_ARP_IP_TARGET); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not open contaniner IFLA_BOND_ARP_IP_TARGET : %m"); + + ORDERED_SET_FOREACH(val, b->arp_ip_targets, i) { + r = sd_netlink_message_append_u32(m, n++, PTR_TO_UINT32(val)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); + } + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not close contaniner IFLA_BOND_ARP_IP_TARGET : %m"); + } + + return 0; +} + +static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) { + log_link_warning_errno(link, r, "Could not set bonding interface: %m"); + return 1; + } + + return 1; +} + +int link_set_bond(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->network); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->network->bond->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK); + if (r < 0) + return log_link_error_errno(link, r, "Could not set netlink flags: %m"); + + r = sd_netlink_message_open_container(req, IFLA_LINKINFO); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m"); + + r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, "bond"); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m"); + + if (link->network->active_slave) { + r = sd_netlink_message_append_u32(req, IFLA_BOND_ACTIVE_SLAVE, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BOND_ACTIVE_SLAVE attribute: %m"); + } + + if (link->network->primary_slave) { + r = sd_netlink_message_append_u32(req, IFLA_BOND_PRIMARY, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BOND_PRIMARY attribute: %m"); + } + + r = sd_netlink_message_close_container(req); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m"); + + r = sd_netlink_message_close_container(req); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bond_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return r; +} + +int config_parse_arp_ip_target_address( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Bond *b = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + b->arp_ip_targets = ordered_set_free(b->arp_ip_targets); + return 0; + } + + for (;;) { + _cleanup_free_ char *n = NULL; + union in_addr_union ip; + + r = extract_first_word(&rvalue, &n, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse Bond ARP ip target address, ignoring assignment: %s", + rvalue); + return 0; + } + if (r == 0) + return 0; + + r = in_addr_from_string(AF_INET, n, &ip); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Bond ARP ip target address is invalid, ignoring assignment: %s", n); + continue; + } + + r = ordered_set_ensure_allocated(&b->arp_ip_targets, NULL); + if (r < 0) + return log_oom(); + + if (ordered_set_size(b->arp_ip_targets) >= NETDEV_BOND_ARP_TARGETS_MAX) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Too many ARP ip targets are specified. The maximum number is %d. Ignoring assignment: %s", + NETDEV_BOND_ARP_TARGETS_MAX, n); + continue; + } + + r = ordered_set_put(b->arp_ip_targets, UINT32_TO_PTR(ip.in.s_addr)); + if (r == -EEXIST) + log_syntax(unit, LOG_WARNING, filename, line, r, + "Bond ARP ip target address is duplicated, ignoring assignment: %s", n); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to store bond ARP ip target address '%s', ignoring assignment: %m", n); + } +} + +int config_parse_ad_actor_sys_prio( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Bond *b = userdata; + uint16_t v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou16(rvalue, &v); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse actor system priority '%s', ignoring: %m", rvalue); + return 0; + } + + if (v == 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse actor system priority '%s'. Range is [1,65535], ignoring.", + rvalue); + return 0; + } + + b->ad_actor_sys_prio = v; + + return 0; +} + +int config_parse_ad_user_port_key( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Bond *b = userdata; + uint16_t v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou16(rvalue, &v); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse user port key '%s', ignoring: %m", rvalue); + return 0; + } + + if (v > 1023) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse user port key '%s'. Range is [0…1023], ignoring.", rvalue); + return 0; + } + + b->ad_user_port_key = v; + + return 0; +} + +int config_parse_ad_actor_system( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Bond *b = userdata; + struct ether_addr n; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = ether_addr_from_string(rvalue, &n); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Not a valid MAC address %s. Ignoring assignment: %m", + rvalue); + return 0; + } + if (ether_addr_is_null(&n) || (n.ether_addr_octet[0] & 0x01)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Not a valid MAC address %s, can not be null or multicast. Ignoring assignment.", + rvalue); + return 0; + } + + b->ad_actor_system = n; + + return 0; +} + +static void bond_done(NetDev *netdev) { + Bond *b; + + assert(netdev); + b = BOND(netdev); + assert(b); + + ordered_set_free(b->arp_ip_targets); +} + +static void bond_init(NetDev *netdev) { + Bond *b; + + assert(netdev); + + b = BOND(netdev); + + assert(b); + + b->mode = _NETDEV_BOND_MODE_INVALID; + b->xmit_hash_policy = _NETDEV_BOND_XMIT_HASH_POLICY_INVALID; + b->lacp_rate = _NETDEV_BOND_LACP_RATE_INVALID; + b->ad_select = _NETDEV_BOND_AD_SELECT_INVALID; + b->fail_over_mac = _NETDEV_BOND_FAIL_OVER_MAC_INVALID; + b->arp_validate = _NETDEV_BOND_ARP_VALIDATE_INVALID; + b->arp_all_targets = _NETDEV_BOND_ARP_ALL_TARGETS_INVALID; + b->primary_reselect = _NETDEV_BOND_PRIMARY_RESELECT_INVALID; + + b->all_slaves_active = false; + b->tlb_dynamic_lb = -1; + + b->resend_igmp = RESEND_IGMP_DEFAULT; + b->packets_per_slave = PACKETS_PER_SLAVE_DEFAULT; + b->num_grat_arp = GRATUITOUS_ARP_DEFAULT; + b->lp_interval = LEARNING_PACKETS_INTERVAL_MIN_SEC; +} + +const NetDevVTable bond_vtable = { + .object_size = sizeof(Bond), + .init = bond_init, + .done = bond_done, + .sections = "Match\0NetDev\0Bond\0", + .fill_message_create = netdev_bond_fill_message_create, + .create_type = NETDEV_CREATE_MASTER, + .generate_mac = true, +}; diff --git a/src/network/netdev/bond.h b/src/network/netdev/bond.h new file mode 100644 index 00000000..28796a3a --- /dev/null +++ b/src/network/netdev/bond.h @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "in-addr-util.h" +#include "netdev.h" +#include "ordered-set.h" + +/* + * Maximum number of targets supported by the kernel for a single + * bond netdev. + */ +#define NETDEV_BOND_ARP_TARGETS_MAX 16 + +typedef enum BondMode { + NETDEV_BOND_MODE_BALANCE_RR = BOND_MODE_ROUNDROBIN, + NETDEV_BOND_MODE_ACTIVE_BACKUP = BOND_MODE_ACTIVEBACKUP, + NETDEV_BOND_MODE_BALANCE_XOR = BOND_MODE_XOR, + NETDEV_BOND_MODE_BROADCAST = BOND_MODE_BROADCAST, + NETDEV_BOND_MODE_802_3AD = BOND_MODE_8023AD, + NETDEV_BOND_MODE_BALANCE_TLB = BOND_MODE_TLB, + NETDEV_BOND_MODE_BALANCE_ALB = BOND_MODE_ALB, + _NETDEV_BOND_MODE_MAX, + _NETDEV_BOND_MODE_INVALID = -1 +} BondMode; + +typedef enum BondXmitHashPolicy { + NETDEV_BOND_XMIT_HASH_POLICY_LAYER2 = BOND_XMIT_POLICY_LAYER2, + NETDEV_BOND_XMIT_HASH_POLICY_LAYER34 = BOND_XMIT_POLICY_LAYER34, + NETDEV_BOND_XMIT_HASH_POLICY_LAYER23 = BOND_XMIT_POLICY_LAYER23, + NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23 = BOND_XMIT_POLICY_ENCAP23, + NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34 = BOND_XMIT_POLICY_ENCAP34, + _NETDEV_BOND_XMIT_HASH_POLICY_MAX, + _NETDEV_BOND_XMIT_HASH_POLICY_INVALID = -1 +} BondXmitHashPolicy; + +typedef enum BondLacpRate { + NETDEV_BOND_LACP_RATE_SLOW, + NETDEV_BOND_LACP_RATE_FAST, + _NETDEV_BOND_LACP_RATE_MAX, + _NETDEV_BOND_LACP_RATE_INVALID = -1, +} BondLacpRate; + +typedef enum BondAdSelect { + NETDEV_BOND_AD_SELECT_STABLE, + NETDEV_BOND_AD_SELECT_BANDWIDTH, + NETDEV_BOND_AD_SELECT_COUNT, + _NETDEV_BOND_AD_SELECT_MAX, + _NETDEV_BOND_AD_SELECT_INVALID = -1, +} BondAdSelect; + +typedef enum BondFailOverMac { + NETDEV_BOND_FAIL_OVER_MAC_NONE, + NETDEV_BOND_FAIL_OVER_MAC_ACTIVE, + NETDEV_BOND_FAIL_OVER_MAC_FOLLOW, + _NETDEV_BOND_FAIL_OVER_MAC_MAX, + _NETDEV_BOND_FAIL_OVER_MAC_INVALID = -1, +} BondFailOverMac; + +typedef enum BondArpValidate { + NETDEV_BOND_ARP_VALIDATE_NONE, + NETDEV_BOND_ARP_VALIDATE_ACTIVE, + NETDEV_BOND_ARP_VALIDATE_BACKUP, + NETDEV_BOND_ARP_VALIDATE_ALL, + _NETDEV_BOND_ARP_VALIDATE_MAX, + _NETDEV_BOND_ARP_VALIDATE_INVALID = -1, +} BondArpValidate; + +typedef enum BondArpAllTargets { + NETDEV_BOND_ARP_ALL_TARGETS_ANY, + NETDEV_BOND_ARP_ALL_TARGETS_ALL, + _NETDEV_BOND_ARP_ALL_TARGETS_MAX, + _NETDEV_BOND_ARP_ALL_TARGETS_INVALID = -1, +} BondArpAllTargets; + +typedef enum BondPrimaryReselect { + NETDEV_BOND_PRIMARY_RESELECT_ALWAYS, + NETDEV_BOND_PRIMARY_RESELECT_BETTER, + NETDEV_BOND_PRIMARY_RESELECT_FAILURE, + _NETDEV_BOND_PRIMARY_RESELECT_MAX, + _NETDEV_BOND_PRIMARY_RESELECT_INVALID = -1, +} BondPrimaryReselect; + +typedef struct Bond { + NetDev meta; + + BondMode mode; + BondXmitHashPolicy xmit_hash_policy; + BondLacpRate lacp_rate; + BondAdSelect ad_select; + BondFailOverMac fail_over_mac; + BondArpValidate arp_validate; + BondArpAllTargets arp_all_targets; + BondPrimaryReselect primary_reselect; + + int tlb_dynamic_lb; + + bool all_slaves_active; + + unsigned resend_igmp; + unsigned packets_per_slave; + unsigned num_grat_arp; + unsigned min_links; + + uint16_t ad_actor_sys_prio; + uint16_t ad_user_port_key; + struct ether_addr ad_actor_system; + + usec_t miimon; + usec_t updelay; + usec_t downdelay; + usec_t arp_interval; + usec_t lp_interval; + + OrderedSet *arp_ip_targets; +} Bond; + +DEFINE_NETDEV_CAST(BOND, Bond); +extern const NetDevVTable bond_vtable; + +int link_set_bond(Link *link); + +const char *bond_mode_to_string(BondMode d) _const_; +BondMode bond_mode_from_string(const char *d) _pure_; + +const char *bond_xmit_hash_policy_to_string(BondXmitHashPolicy d) _const_; +BondXmitHashPolicy bond_xmit_hash_policy_from_string(const char *d) _pure_; + +const char *bond_lacp_rate_to_string(BondLacpRate d) _const_; +BondLacpRate bond_lacp_rate_from_string(const char *d) _pure_; + +const char *bond_fail_over_mac_to_string(BondFailOverMac d) _const_; +BondFailOverMac bond_fail_over_mac_from_string(const char *d) _pure_; + +const char *bond_ad_select_to_string(BondAdSelect d) _const_; +BondAdSelect bond_ad_select_from_string(const char *d) _pure_; + +const char *bond_arp_validate_to_string(BondArpValidate d) _const_; +BondArpValidate bond_arp_validate_from_string(const char *d) _pure_; + +const char *bond_arp_all_targets_to_string(BondArpAllTargets d) _const_; +BondArpAllTargets bond_arp_all_targets_from_string(const char *d) _pure_; + +const char *bond_primary_reselect_to_string(BondPrimaryReselect d) _const_; +BondPrimaryReselect bond_primary_reselect_from_string(const char *d) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_bond_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_bond_xmit_hash_policy); +CONFIG_PARSER_PROTOTYPE(config_parse_bond_lacp_rate); +CONFIG_PARSER_PROTOTYPE(config_parse_bond_ad_select); +CONFIG_PARSER_PROTOTYPE(config_parse_bond_fail_over_mac); +CONFIG_PARSER_PROTOTYPE(config_parse_bond_arp_validate); +CONFIG_PARSER_PROTOTYPE(config_parse_bond_arp_all_targets); +CONFIG_PARSER_PROTOTYPE(config_parse_bond_primary_reselect); +CONFIG_PARSER_PROTOTYPE(config_parse_arp_ip_target_address); +CONFIG_PARSER_PROTOTYPE(config_parse_ad_actor_sys_prio); +CONFIG_PARSER_PROTOTYPE(config_parse_ad_user_port_key); +CONFIG_PARSER_PROTOTYPE(config_parse_ad_actor_system); diff --git a/src/network/netdev/bridge.c b/src/network/netdev/bridge.c new file mode 100644 index 00000000..59a40fae --- /dev/null +++ b/src/network/netdev/bridge.c @@ -0,0 +1,361 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "bridge.h" +#include "netlink-util.h" +#include "network-internal.h" +#include "networkd-manager.h" +#include "string-table.h" +#include "vlan-util.h" + +static const char* const multicast_router_table[_MULTICAST_ROUTER_MAX] = { + [MULTICAST_ROUTER_NONE] = "no", + [MULTICAST_ROUTER_TEMPORARY_QUERY] = "query", + [MULTICAST_ROUTER_PERMANENT] = "permanent", + [MULTICAST_ROUTER_TEMPORARY] = "temporary", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(multicast_router, MulticastRouter, _MULTICAST_ROUTER_INVALID); +DEFINE_CONFIG_PARSE_ENUM(config_parse_multicast_router, multicast_router, MulticastRouter, + "Failed to parse bridge multicast router setting"); + +/* callback for bridge netdev's parameter set */ +static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) { + int r; + + assert(netdev); + assert(m); + + r = sd_netlink_message_get_errno(m); + if (r < 0) { + log_netdev_warning_errno(netdev, r, "Bridge parameters could not be set: %m"); + return 1; + } + + log_netdev_debug(netdev, "Bridge parameters set success"); + + return 1; +} + +static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + Bridge *b; + int r; + + assert(netdev); + + b = BRIDGE(netdev); + + assert(b); + + r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, netdev->ifindex); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK); + if (r < 0) + return log_link_error_errno(link, r, "Could not set netlink flags: %m"); + + r = sd_netlink_message_open_container(req, IFLA_LINKINFO); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); + + r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); + + /* convert to jiffes */ + if (b->forward_delay != USEC_INFINITY) { + r = sd_netlink_message_append_u32(req, IFLA_BR_FORWARD_DELAY, usec_to_jiffies(b->forward_delay)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_FORWARD_DELAY attribute: %m"); + } + + if (b->hello_time > 0) { + r = sd_netlink_message_append_u32(req, IFLA_BR_HELLO_TIME, usec_to_jiffies(b->hello_time)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_HELLO_TIME attribute: %m"); + } + + if (b->max_age > 0) { + r = sd_netlink_message_append_u32(req, IFLA_BR_MAX_AGE, usec_to_jiffies(b->max_age)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MAX_AGE attribute: %m"); + } + + if (b->ageing_time != USEC_INFINITY) { + r = sd_netlink_message_append_u32(req, IFLA_BR_AGEING_TIME, usec_to_jiffies(b->ageing_time)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_AGEING_TIME attribute: %m"); + } + + if (b->priority > 0) { + r = sd_netlink_message_append_u16(req, IFLA_BR_PRIORITY, b->priority); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_PRIORITY attribute: %m"); + } + + if (b->group_fwd_mask > 0) { + r = sd_netlink_message_append_u16(req, IFLA_BR_GROUP_FWD_MASK, b->group_fwd_mask); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_GROUP_FWD_MASK attribute: %m"); + } + + if (b->default_pvid != VLANID_INVALID) { + r = sd_netlink_message_append_u16(req, IFLA_BR_VLAN_DEFAULT_PVID, b->default_pvid); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_DEFAULT_PVID attribute: %m"); + } + + if (b->mcast_querier >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BR_MCAST_QUERIER, b->mcast_querier); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MCAST_QUERIER attribute: %m"); + } + + if (b->mcast_snooping >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BR_MCAST_SNOOPING, b->mcast_snooping); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MCAST_SNOOPING attribute: %m"); + } + + if (b->vlan_filtering >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BR_VLAN_FILTERING, b->vlan_filtering); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_FILTERING attribute: %m"); + } + + if (b->stp >= 0) { + r = sd_netlink_message_append_u32(req, IFLA_BR_STP_STATE, b->stp); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_STP_STATE attribute: %m"); + } + + if (b->igmp_version > 0) { + r = sd_netlink_message_append_u8(req, IFLA_BR_MCAST_IGMP_VERSION, b->igmp_version); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MCAST_IGMP_VERSION attribute: %m"); + } + + r = sd_netlink_message_close_container(req); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); + + r = sd_netlink_message_close_container(req); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); + + r = netlink_call_async(netdev->manager->rtnl, NULL, req, netdev_bridge_set_handler, + netdev_destroy_callback, netdev); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); + + netdev_ref(netdev); + + return r; +} + +static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) { + log_link_warning_errno(link, r, "Could not set bridge interface: %m"); + return 1; + } + + return 1; +} + +int link_set_bridge(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->network); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_rtnl_message_link_set_family(req, PF_BRIDGE); + if (r < 0) + return log_link_error_errno(link, r, "Could not set message family: %m"); + + r = sd_netlink_message_open_container(req, IFLA_PROTINFO); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m"); + + if (link->network->use_bpdu >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, link->network->use_bpdu); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m"); + } + + if (link->network->hairpin >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m"); + } + + if (link->network->fast_leave >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m"); + } + + if (link->network->allow_port_to_be_root >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, link->network->allow_port_to_be_root); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m"); + } + + if (link->network->unicast_flood >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m"); + } + + if (link->network->multicast_flood >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_FLOOD, link->network->multicast_flood); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_FLOOD attribute: %m"); + } + + if (link->network->multicast_to_unicast >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m"); + } + + if (link->network->neighbor_suppression >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_NEIGH_SUPPRESS, link->network->neighbor_suppression); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_NEIGH_SUPPRESS attribute: %m"); + } + + if (link->network->learning >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_LEARNING, link->network->learning); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_LEARNING attribute: %m"); + } + + if (link->network->bridge_proxy_arp >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP, link->network->bridge_proxy_arp); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROXYARP attribute: %m"); + } + + if (link->network->bridge_proxy_arp_wifi >= 0) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP_WIFI, link->network->bridge_proxy_arp_wifi); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROXYARP_WIFI attribute: %m"); + } + + if (link->network->cost != 0) { + r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m"); + } + + if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) { + r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PRIORITY attribute: %m"); + } + + if (link->network->multicast_router != _MULTICAST_ROUTER_INVALID) { + r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MULTICAST_ROUTER, link->network->multicast_router); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MULTICAST_ROUTER attribute: %m"); + } + + r = sd_netlink_message_close_container(req); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bridge_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return r; +} + +int config_parse_bridge_igmp_version( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Bridge *b = userdata; + uint8_t u; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + b->igmp_version = 0; /* 0 means unset. */ + return 0; + } + + r = safe_atou8(rvalue, &u); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse bridge's multicast IGMP version number '%s', ignoring assignment: %m", + rvalue); + return 0; + } + if (!IN_SET(u, 2, 3)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid bridge's multicast IGMP version number '%s', ignoring assignment.", rvalue); + return 0; + } + + b->igmp_version = u; + + return 0; +} + +static void bridge_init(NetDev *n) { + Bridge *b; + + b = BRIDGE(n); + + assert(b); + + b->mcast_querier = -1; + b->mcast_snooping = -1; + b->vlan_filtering = -1; + b->stp = -1; + b->default_pvid = VLANID_INVALID; + b->forward_delay = USEC_INFINITY; + b->ageing_time = USEC_INFINITY; +} + +const NetDevVTable bridge_vtable = { + .object_size = sizeof(Bridge), + .init = bridge_init, + .sections = "Match\0NetDev\0Bridge\0", + .post_create = netdev_bridge_post_create, + .create_type = NETDEV_CREATE_MASTER, +}; diff --git a/src/network/netdev/bridge.h b/src/network/netdev/bridge.h new file mode 100644 index 00000000..b0a728e5 --- /dev/null +++ b/src/network/netdev/bridge.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "conf-parser.h" +#include "netdev.h" + +typedef struct Bridge { + NetDev meta; + + int mcast_querier; + int mcast_snooping; + int vlan_filtering; + int stp; + uint16_t priority; + uint16_t group_fwd_mask; + uint16_t default_pvid; + uint8_t igmp_version; + + usec_t forward_delay; + usec_t hello_time; + usec_t max_age; + usec_t ageing_time; +} Bridge; + +typedef enum MulticastRouter { + MULTICAST_ROUTER_NONE = MDB_RTR_TYPE_DISABLED, + MULTICAST_ROUTER_TEMPORARY_QUERY = MDB_RTR_TYPE_TEMP_QUERY, + MULTICAST_ROUTER_PERMANENT = MDB_RTR_TYPE_PERM, + MULTICAST_ROUTER_TEMPORARY = MDB_RTR_TYPE_TEMP, + _MULTICAST_ROUTER_MAX, + _MULTICAST_ROUTER_INVALID = -1, +} MulticastRouter; + +DEFINE_NETDEV_CAST(BRIDGE, Bridge); +extern const NetDevVTable bridge_vtable; + +int link_set_bridge(Link *link); + +const char* multicast_router_to_string(MulticastRouter i) _const_; +MulticastRouter multicast_router_from_string(const char *s) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_multicast_router); +CONFIG_PARSER_PROTOTYPE(config_parse_bridge_igmp_version); diff --git a/src/network/netdev/dummy.c b/src/network/netdev/dummy.c new file mode 100644 index 00000000..23c733cb --- /dev/null +++ b/src/network/netdev/dummy.c @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "dummy.h" + +const NetDevVTable dummy_vtable = { + .object_size = sizeof(Dummy), + .sections = "Match\0NetDev\0", + .create_type = NETDEV_CREATE_INDEPENDENT, + .generate_mac = true, +}; diff --git a/src/network/netdev/dummy.h b/src/network/netdev/dummy.h new file mode 100644 index 00000000..f9354147 --- /dev/null +++ b/src/network/netdev/dummy.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "netdev.h" + +typedef struct Dummy { + NetDev meta; +} Dummy; + +DEFINE_NETDEV_CAST(DUMMY, Dummy); +extern const NetDevVTable dummy_vtable; diff --git a/src/network/netdev/fou-tunnel.c b/src/network/netdev/fou-tunnel.c new file mode 100644 index 00000000..7627ccee --- /dev/null +++ b/src/network/netdev/fou-tunnel.c @@ -0,0 +1,269 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "conf-parser.h" +#include "fou-tunnel.h" +#include "ip-protocol-list.h" +#include "netlink-util.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "string-table.h" +#include "string-util.h" +#include "util.h" + +static const char* const fou_encap_type_table[_NETDEV_FOO_OVER_UDP_ENCAP_MAX] = { + [NETDEV_FOO_OVER_UDP_ENCAP_DIRECT] = "FooOverUDP", + [NETDEV_FOO_OVER_UDP_ENCAP_GUE] = "GenericUDPEncapsulation", +}; + +DEFINE_STRING_TABLE_LOOKUP(fou_encap_type, FooOverUDPEncapType); +DEFINE_CONFIG_PARSE_ENUM(config_parse_fou_encap_type, fou_encap_type, FooOverUDPEncapType, + "Failed to parse Encapsulation="); + +static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **ret) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + FouTunnel *t; + uint8_t encap_type; + int r; + + assert(netdev); + + t = FOU(netdev); + + assert(t); + + r = sd_genl_message_new(netdev->manager->genl, SD_GENL_FOU, FOU_CMD_ADD, &m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m"); + + r = sd_netlink_message_append_u16(m, FOU_ATTR_PORT, htobe16(t->port)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PORT attribute: %m"); + + if (IN_SET(t->peer_family, AF_INET, AF_INET6)) { + r = sd_netlink_message_append_u16(m, FOU_ATTR_PEER_PORT, htobe16(t->peer_port)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PEER_PORT attribute: %m"); + } + + switch (t->fou_encap_type) { + case NETDEV_FOO_OVER_UDP_ENCAP_DIRECT: + encap_type = FOU_ENCAP_DIRECT; + break; + case NETDEV_FOO_OVER_UDP_ENCAP_GUE: + encap_type = FOU_ENCAP_GUE; + break; + default: + assert_not_reached("invalid encap type"); + } + + r = sd_netlink_message_append_u8(m, FOU_ATTR_TYPE, encap_type); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_TYPE attribute: %m"); + + r = sd_netlink_message_append_u8(m, FOU_ATTR_AF, AF_INET); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_AF attribute: %m"); + + r = sd_netlink_message_append_u8(m, FOU_ATTR_IPPROTO, t->fou_protocol); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_IPPROTO attribute: %m"); + + if (t->local_family == AF_INET) { + r = sd_netlink_message_append_in_addr(m, FOU_ATTR_LOCAL_V4, &t->local.in); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_LOCAL_V4 attribute: %m"); + } else if (t->local_family == AF_INET6) { + r = sd_netlink_message_append_in6_addr(m, FOU_ATTR_LOCAL_V6, &t->local.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_LOCAL_V6 attribute: %m"); + } + + if (t->peer_family == AF_INET) { + r = sd_netlink_message_append_in_addr(m, FOU_ATTR_PEER_V4, &t->peer.in); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PEER_V4 attribute: %m"); + } else if (t->peer_family == AF_INET6){ + r = sd_netlink_message_append_in6_addr(m, FOU_ATTR_PEER_V6, &t->peer.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PEER_V6 attribute: %m"); + } + + *ret = TAKE_PTR(m); + return 0; +} + +static int fou_tunnel_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) { + int r; + + assert(netdev); + assert(netdev->state != _NETDEV_STATE_INVALID); + + r = sd_netlink_message_get_errno(m); + if (r == -EEXIST) + log_netdev_info(netdev, "netdev exists, using existing without changing its parameters"); + else if (r < 0) { + log_netdev_warning_errno(netdev, r, "netdev could not be created: %m"); + netdev_drop(netdev); + + return 1; + } + + log_netdev_debug(netdev, "FooOverUDP tunnel is created"); + return 1; +} + +static int netdev_fou_tunnel_create(NetDev *netdev) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(netdev); + assert(FOU(netdev)); + + r = netdev_fill_fou_tunnel_message(netdev, &m); + if (r < 0) + return r; + + r = netlink_call_async(netdev->manager->genl, NULL, m, fou_tunnel_create_handler, + netdev_destroy_callback, netdev); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to create FooOverUDP tunnel: %m"); + + netdev_ref(netdev); + return 0; +} + +int config_parse_ip_protocol( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint8_t *protocol = data; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + assert_cc(IPPROTO_MAX-1 <= UINT8_MAX); + + r = parse_ip_protocol(rvalue); + if (r < 0) { + r = safe_atou8(rvalue, protocol); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse IP protocol '%s' for Foo over UDP tunnel, " + "ignoring assignment: %m", rvalue); + return 0; + } + + *protocol = r; + return 0; +} + +int config_parse_fou_tunnel_address( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + union in_addr_union *addr = data; + FouTunnel *t = userdata; + int r, *f; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(lvalue, "Local")) + f = &t->local_family; + else + f = &t->peer_family; + + r = in_addr_from_string_auto(rvalue, f, addr); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, + "Foo over UDP tunnel '%s' address is invalid, ignoring assignment: %s", + lvalue, rvalue); + + return 0; +} + +static int netdev_fou_tunnel_verify(NetDev *netdev, const char *filename) { + FouTunnel *t; + + assert(netdev); + assert(filename); + + t = FOU(netdev); + + assert(t); + + switch (t->fou_encap_type) { + case NETDEV_FOO_OVER_UDP_ENCAP_DIRECT: + if (t->fou_protocol <= 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "FooOverUDP protocol not configured in %s. Rejecting configuration.", + filename); + break; + case NETDEV_FOO_OVER_UDP_ENCAP_GUE: + if (t->fou_protocol > 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "FooOverUDP GUE can't be set with protocol configured in %s. Rejecting configuration.", + filename); + break; + default: + assert_not_reached("Invalid fou encap type"); + } + + if (t->peer_family == AF_UNSPEC && t->peer_port > 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "FooOverUDP peer port is set but peer address not configured in %s. Rejecting configuration.", + filename); + else if (t->peer_family != AF_UNSPEC && t->peer_port == 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "FooOverUDP peer port not set but peer address is configured in %s. Rejecting configuration.", + filename); + return 0; +} + +static void fou_tunnel_init(NetDev *netdev) { + FouTunnel *t; + + assert(netdev); + + t = FOU(netdev); + + assert(t); + + t->fou_encap_type = NETDEV_FOO_OVER_UDP_ENCAP_DIRECT; +} + +const NetDevVTable foutnl_vtable = { + .object_size = sizeof(FouTunnel), + .init = fou_tunnel_init, + .sections = "Match\0NetDev\0FooOverUDP\0", + .create = netdev_fou_tunnel_create, + .create_type = NETDEV_CREATE_INDEPENDENT, + .config_verify = netdev_fou_tunnel_verify, +}; diff --git a/src/network/netdev/fou-tunnel.h b/src/network/netdev/fou-tunnel.h new file mode 100644 index 00000000..caa3b760 --- /dev/null +++ b/src/network/netdev/fou-tunnel.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "in-addr-util.h" +#include "netdev.h" + +typedef enum FooOverUDPEncapType { + NETDEV_FOO_OVER_UDP_ENCAP_UNSPEC = FOU_ENCAP_UNSPEC, + NETDEV_FOO_OVER_UDP_ENCAP_DIRECT = FOU_ENCAP_DIRECT, + NETDEV_FOO_OVER_UDP_ENCAP_GUE = FOU_ENCAP_GUE, + _NETDEV_FOO_OVER_UDP_ENCAP_MAX, + _NETDEV_FOO_OVER_UDP_ENCAP_INVALID = -1, +} FooOverUDPEncapType; + +typedef struct FouTunnel { + NetDev meta; + + uint8_t fou_protocol; + + uint16_t port; + uint16_t peer_port; + + int local_family; + int peer_family; + + FooOverUDPEncapType fou_encap_type; + union in_addr_union local; + union in_addr_union peer; +} FouTunnel; + +DEFINE_NETDEV_CAST(FOU, FouTunnel); +extern const NetDevVTable foutnl_vtable; + +const char *fou_encap_type_to_string(FooOverUDPEncapType d) _const_; +FooOverUDPEncapType fou_encap_type_from_string(const char *d) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_fou_encap_type); +CONFIG_PARSER_PROTOTYPE(config_parse_ip_protocol); +CONFIG_PARSER_PROTOTYPE(config_parse_fou_tunnel_address); diff --git a/src/network/netdev/geneve.c b/src/network/netdev/geneve.c new file mode 100644 index 00000000..771e0292 --- /dev/null +++ b/src/network/netdev/geneve.c @@ -0,0 +1,356 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "conf-parser.h" +#include "extract-word.h" +#include "geneve.h" +#include "netlink-util.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" + +#define GENEVE_FLOW_LABEL_MAX_MASK 0xFFFFFU +#define DEFAULT_GENEVE_DESTINATION_PORT 6081 + +static const char* const geneve_df_table[_NETDEV_GENEVE_DF_MAX] = { + [NETDEV_GENEVE_DF_NO] = "no", + [NETDEV_GENEVE_DF_YES] = "yes", + [NETDEV_GENEVE_DF_INHERIT] = "inherit", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(geneve_df, GeneveDF, NETDEV_GENEVE_DF_YES); +DEFINE_CONFIG_PARSE_ENUM(config_parse_geneve_df, geneve_df, GeneveDF, "Failed to parse Geneve IPDoNotFragment= setting"); + +/* callback for geneve netdev's created without a backing Link */ +static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) { + int r; + + assert(netdev); + assert(netdev->state != _NETDEV_STATE_INVALID); + + r = sd_netlink_message_get_errno(m); + if (r == -EEXIST) + log_netdev_info(netdev, "Geneve netdev exists, using existing without changing its parameters"); + else if (r < 0) { + log_netdev_warning_errno(netdev, r, "Geneve netdev could not be created: %m"); + netdev_drop(netdev); + + return 1; + } + + log_netdev_debug(netdev, "Geneve created"); + + return 1; +} + +static int netdev_geneve_create(NetDev *netdev) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + Geneve *v; + int r; + + assert(netdev); + + v = GENEVE(netdev); + + r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m"); + + r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m"); + + if (netdev->mac) { + r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m"); + } + + if (netdev->mtu != 0) { + r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m"); + } + + r = sd_netlink_message_open_container(m, IFLA_LINKINFO); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); + + r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); + + if (v->id <= GENEVE_VID_MAX) { + r = sd_netlink_message_append_u32(m, IFLA_GENEVE_ID, v->id); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_ID attribute: %m"); + } + + if (in_addr_is_null(v->remote_family, &v->remote) == 0) { + if (v->remote_family == AF_INET) + r = sd_netlink_message_append_in_addr(m, IFLA_GENEVE_REMOTE, &v->remote.in); + else + r = sd_netlink_message_append_in6_addr(m, IFLA_GENEVE_REMOTE6, &v->remote.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_REMOTE/IFLA_GENEVE_REMOTE6 attribute: %m"); + } + + if (v->inherit) { + r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL_INHERIT, 1); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL_INHERIT attribute: %m"); + } else { + r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL, v->ttl); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL attribute: %m"); + } + + r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TOS, v->tos); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TOS attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_CSUM, v->udpcsum); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_CSUM attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_TX attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_RX attribute: %m"); + + if (v->dest_port != DEFAULT_GENEVE_DESTINATION_PORT) { + r = sd_netlink_message_append_u16(m, IFLA_GENEVE_PORT, htobe16(v->dest_port)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_PORT attribute: %m"); + } + + if (v->flow_label > 0) { + r = sd_netlink_message_append_u32(m, IFLA_GENEVE_LABEL, htobe32(v->flow_label)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_LABEL attribute: %m"); + } + + if (v->geneve_df != _NETDEV_GENEVE_DF_INVALID) { + r = sd_netlink_message_append_u8(m, IFLA_GENEVE_DF, v->geneve_df); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_DF attribute: %m"); + } + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); + + r = netlink_call_async(netdev->manager->rtnl, NULL, m, geneve_netdev_create_handler, + netdev_destroy_callback, netdev); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); + + netdev_ref(netdev); + netdev->state = NETDEV_STATE_CREATING; + + log_netdev_debug(netdev, "Creating"); + + return r; +} + +int config_parse_geneve_vni(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Geneve *v = userdata; + uint32_t f; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou32(rvalue, &f); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve VNI '%s'.", rvalue); + return 0; + } + + if (f > GENEVE_VID_MAX){ + log_syntax(unit, LOG_ERR, filename, line, r, "Geneve VNI out is of range '%s'.", rvalue); + return 0; + } + + v->id = f; + + return 0; +} + +int config_parse_geneve_address(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Geneve *v = userdata; + union in_addr_union *addr = data, buffer; + int r, f; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = in_addr_from_string_auto(rvalue, &f, &buffer); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "geneve '%s' address is invalid, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + r = in_addr_is_multicast(f, &buffer); + if (r > 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "geneve invalid multicast '%s' address, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + v->remote_family = f; + *addr = buffer; + + return 0; +} + +int config_parse_geneve_flow_label(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Geneve *v = userdata; + uint32_t f; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou32(rvalue, &f); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve flow label '%s'.", rvalue); + return 0; + } + + if (f & ~GENEVE_FLOW_LABEL_MAX_MASK) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Geneve flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue); + return 0; + } + + v->flow_label = f; + + return 0; +} + +int config_parse_geneve_ttl(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Geneve *v = userdata; + unsigned f; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(rvalue, "inherit")) + v->inherit = true; + else { + r = safe_atou(rvalue, &f); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse Geneve TTL '%s', ignoring assignment: %m", rvalue); + return 0; + } + + if (f > 255) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid Geneve TTL '%s'. TTL must be <= 255. Ignoring assignment.", rvalue); + return 0; + } + + v->ttl = f; + } + + return 0; +} + +static int netdev_geneve_verify(NetDev *netdev, const char *filename) { + Geneve *v = GENEVE(netdev); + + assert(netdev); + assert(v); + assert(filename); + + if (v->id > GENEVE_VID_MAX) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: Geneve without valid VNI (or Virtual Network Identifier) configured. Ignoring.", + filename); + + return 0; +} + +static void geneve_init(NetDev *netdev) { + Geneve *v; + + assert(netdev); + + v = GENEVE(netdev); + + assert(v); + + v->id = GENEVE_VID_MAX + 1; + v->geneve_df = _NETDEV_GENEVE_DF_INVALID; + v->dest_port = DEFAULT_GENEVE_DESTINATION_PORT; + v->udpcsum = false; + v->udp6zerocsumtx = false; + v->udp6zerocsumrx = false; +} + +const NetDevVTable geneve_vtable = { + .object_size = sizeof(Geneve), + .init = geneve_init, + .sections = "Match\0NetDev\0GENEVE\0", + .create = netdev_geneve_create, + .create_type = NETDEV_CREATE_INDEPENDENT, + .config_verify = netdev_geneve_verify, + .generate_mac = true, +}; diff --git a/src/network/netdev/geneve.h b/src/network/netdev/geneve.h new file mode 100644 index 00000000..2ac3c1e8 --- /dev/null +++ b/src/network/netdev/geneve.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Geneve Geneve; + +#include "in-addr-util.h" +#include "netdev.h" +#include "networkd-network.h" + +#define GENEVE_VID_MAX (1u << 24) - 1 + +typedef enum GeneveDF { + NETDEV_GENEVE_DF_NO = GENEVE_DF_UNSET, + NETDEV_GENEVE_DF_YES = GENEVE_DF_SET, + NETDEV_GENEVE_DF_INHERIT = GENEVE_DF_INHERIT, + _NETDEV_GENEVE_DF_MAX, + _NETDEV_GENEVE_DF_INVALID = -1 +} GeneveDF; + +struct Geneve { + NetDev meta; + + uint32_t id; + uint32_t flow_label; + + int remote_family; + + uint8_t tos; + uint8_t ttl; + + uint16_t dest_port; + + bool udpcsum; + bool udp6zerocsumtx; + bool udp6zerocsumrx; + bool inherit; + + GeneveDF geneve_df; + union in_addr_union remote; +}; + +DEFINE_NETDEV_CAST(GENEVE, Geneve); +extern const NetDevVTable geneve_vtable; + +const char *geneve_df_to_string(GeneveDF d) _const_; +GeneveDF geneve_df_from_string(const char *d) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_geneve_vni); +CONFIG_PARSER_PROTOTYPE(config_parse_geneve_address); +CONFIG_PARSER_PROTOTYPE(config_parse_geneve_flow_label); +CONFIG_PARSER_PROTOTYPE(config_parse_geneve_df); +CONFIG_PARSER_PROTOTYPE(config_parse_geneve_ttl); diff --git a/src/network/netdev/ipvlan.c b/src/network/netdev/ipvlan.c new file mode 100644 index 00000000..53b4bc94 --- /dev/null +++ b/src/network/netdev/ipvlan.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "conf-parser.h" +#include "ipvlan.h" +#include "networkd-link.h" +#include "string-table.h" + +static const char* const ipvlan_mode_table[_NETDEV_IPVLAN_MODE_MAX] = { + [NETDEV_IPVLAN_MODE_L2] = "L2", + [NETDEV_IPVLAN_MODE_L3] = "L3", + [NETDEV_IPVLAN_MODE_L3S] = "L3S", +}; + +DEFINE_STRING_TABLE_LOOKUP(ipvlan_mode, IPVlanMode); +DEFINE_CONFIG_PARSE_ENUM(config_parse_ipvlan_mode, ipvlan_mode, IPVlanMode, "Failed to parse ipvlan mode"); + +static const char* const ipvlan_flags_table[_NETDEV_IPVLAN_FLAGS_MAX] = { + [NETDEV_IPVLAN_FLAGS_BRIGDE] = "bridge", + [NETDEV_IPVLAN_FLAGS_PRIVATE] = "private", + [NETDEV_IPVLAN_FLAGS_VEPA] = "vepa", +}; + +DEFINE_STRING_TABLE_LOOKUP(ipvlan_flags, IPVlanFlags); +DEFINE_CONFIG_PARSE_ENUM(config_parse_ipvlan_flags, ipvlan_flags, IPVlanFlags, "Failed to parse ipvlan flags"); + +static int netdev_ipvlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { + IPVlan *m; + int r; + + assert(netdev); + assert(link); + assert(netdev->ifname); + + if (netdev->kind == NETDEV_KIND_IPVLAN) + m = IPVLAN(netdev); + else + m = IPVTAP(netdev); + + assert(m); + + if (m->mode != _NETDEV_IPVLAN_MODE_INVALID) { + r = sd_netlink_message_append_u16(req, IFLA_IPVLAN_MODE, m->mode); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPVLAN_MODE attribute: %m"); + } + + if (m->flags != _NETDEV_IPVLAN_FLAGS_INVALID) { + r = sd_netlink_message_append_u16(req, IFLA_IPVLAN_FLAGS, m->flags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPVLAN_FLAGS attribute: %m"); + } + + return 0; +} + +static void ipvlan_init(NetDev *n) { + IPVlan *m; + + assert(n); + + if (n->kind == NETDEV_KIND_IPVLAN) + m = IPVLAN(n); + else + m = IPVTAP(n); + + assert(m); + + m->mode = _NETDEV_IPVLAN_MODE_INVALID; + m->flags = _NETDEV_IPVLAN_FLAGS_INVALID; +} + +const NetDevVTable ipvlan_vtable = { + .object_size = sizeof(IPVlan), + .init = ipvlan_init, + .sections = "Match\0NetDev\0IPVLAN\0", + .fill_message_create = netdev_ipvlan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .generate_mac = true, +}; + +const NetDevVTable ipvtap_vtable = { + .object_size = sizeof(IPVlan), + .init = ipvlan_init, + .sections = "Match\0NetDev\0IPVTAP\0", + .fill_message_create = netdev_ipvlan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .generate_mac = true, +}; + +IPVlanMode link_get_ipvlan_mode(Link *link) { + NetDev *netdev; + + if (!streq_ptr(link->kind, "ipvlan")) + return _NETDEV_IPVLAN_MODE_INVALID; + + if (netdev_get(link->manager, link->ifname, &netdev) < 0) + return _NETDEV_IPVLAN_MODE_INVALID; + + if (netdev->kind != NETDEV_KIND_IPVLAN) + return _NETDEV_IPVLAN_MODE_INVALID; + + return IPVLAN(netdev)->mode; +} diff --git a/src/network/netdev/ipvlan.h b/src/network/netdev/ipvlan.h new file mode 100644 index 00000000..171407b7 --- /dev/null +++ b/src/network/netdev/ipvlan.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "netdev.h" + +typedef enum IPVlanMode { + NETDEV_IPVLAN_MODE_L2 = IPVLAN_MODE_L2, + NETDEV_IPVLAN_MODE_L3 = IPVLAN_MODE_L3, + NETDEV_IPVLAN_MODE_L3S = IPVLAN_MODE_L3S, + _NETDEV_IPVLAN_MODE_MAX, + _NETDEV_IPVLAN_MODE_INVALID = -1 +} IPVlanMode; + +typedef enum IPVlanFlags { + NETDEV_IPVLAN_FLAGS_BRIGDE, + NETDEV_IPVLAN_FLAGS_PRIVATE = IPVLAN_F_PRIVATE, + NETDEV_IPVLAN_FLAGS_VEPA = IPVLAN_F_VEPA, + _NETDEV_IPVLAN_FLAGS_MAX, + _NETDEV_IPVLAN_FLAGS_INVALID = -1 +} IPVlanFlags; + +typedef struct IPVlan { + NetDev meta; + + IPVlanMode mode; + IPVlanFlags flags; +} IPVlan; + +DEFINE_NETDEV_CAST(IPVLAN, IPVlan); +DEFINE_NETDEV_CAST(IPVTAP, IPVlan); +extern const NetDevVTable ipvlan_vtable; +extern const NetDevVTable ipvtap_vtable; + +const char *ipvlan_mode_to_string(IPVlanMode d) _const_; +IPVlanMode ipvlan_mode_from_string(const char *d) _pure_; + +const char *ipvlan_flags_to_string(IPVlanFlags d) _const_; +IPVlanFlags ipvlan_flags_from_string(const char *d) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_ipvlan_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_ipvlan_flags); + +IPVlanMode link_get_ipvlan_mode(Link *link); diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c new file mode 100644 index 00000000..f10506af --- /dev/null +++ b/src/network/netdev/l2tp-tunnel.c @@ -0,0 +1,731 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "conf-parser.h" +#include "hashmap.h" +#include "l2tp-tunnel.h" +#include "netlink-util.h" +#include "networkd-address.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "socket-util.h" +#include "string-table.h" +#include "string-util.h" +#include "util.h" + +static const char* const l2tp_l2spec_type_table[_NETDEV_L2TP_L2SPECTYPE_MAX] = { + [NETDEV_L2TP_L2SPECTYPE_NONE] = "none", + [NETDEV_L2TP_L2SPECTYPE_DEFAULT] = "default", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_l2spec_type, L2tpL2specType); + +static const char* const l2tp_encap_type_table[_NETDEV_L2TP_ENCAPTYPE_MAX] = { + [NETDEV_L2TP_ENCAPTYPE_UDP] = "udp", + [NETDEV_L2TP_ENCAPTYPE_IP] = "ip", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_encap_type, L2tpEncapType); +DEFINE_CONFIG_PARSE_ENUM(config_parse_l2tp_encap_type, l2tp_encap_type, L2tpEncapType, "Failed to parse L2TP Encapsulation Type"); + +static const char* const l2tp_local_address_type_table[_NETDEV_L2TP_LOCAL_ADDRESS_MAX] = { + [NETDEV_L2TP_LOCAL_ADDRESS_AUTO] = "auto", + [NETDEV_L2TP_LOCAL_ADDRESS_STATIC] = "static", + [NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC] = "dynamic", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(l2tp_local_address_type, L2tpLocalAddressType); + +static void l2tp_session_free(L2tpSession *s) { + if (!s) + return; + + if (s->tunnel && s->section) + ordered_hashmap_remove(s->tunnel->sessions_by_section, s); + + network_config_section_free(s->section); + + free(s->name); + + free(s); +} + +DEFINE_NETWORK_SECTION_FUNCTIONS(L2tpSession, l2tp_session_free); + +static int l2tp_session_new_static(L2tpTunnel *t, const char *filename, unsigned section_line, L2tpSession **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(l2tp_session_freep) L2tpSession *s = NULL; + int r; + + assert(t); + assert(ret); + assert(filename); + assert(section_line > 0); + + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + s = ordered_hashmap_get(t->sessions_by_section, n); + if (s) { + *ret = TAKE_PTR(s); + return 0; + } + + s = new(L2tpSession, 1); + if (!s) + return -ENOMEM; + + *s = (L2tpSession) { + .l2tp_l2spec_type = NETDEV_L2TP_L2SPECTYPE_DEFAULT, + .tunnel = t, + .section = TAKE_PTR(n), + }; + + r = ordered_hashmap_ensure_allocated(&t->sessions_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(t->sessions_by_section, s->section, s); + if (r < 0) + return r; + + *ret = TAKE_PTR(s); + return 0; +} + +static int netdev_l2tp_fill_message_tunnel(NetDev *netdev, union in_addr_union *local_address, sd_netlink_message **ret) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + uint16_t encap_type; + L2tpTunnel *t; + int r; + + assert(netdev); + assert(local_address); + + t = L2TP(netdev); + + assert(t); + + r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_TUNNEL_CREATE, &m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m"); + + r = sd_netlink_message_append_u32(m, L2TP_ATTR_CONN_ID, t->tunnel_id); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_CONN_ID attribute: %m"); + + r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_CONN_ID, t->peer_tunnel_id); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_CONN_ID attribute: %m"); + + r = sd_netlink_message_append_u8(m, L2TP_ATTR_PROTO_VERSION, 3); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PROTO_VERSION attribute: %m"); + + switch(t->l2tp_encap_type) { + case NETDEV_L2TP_ENCAPTYPE_IP: + encap_type = L2TP_ENCAPTYPE_IP; + break; + case NETDEV_L2TP_ENCAPTYPE_UDP: + default: + encap_type = L2TP_ENCAPTYPE_UDP; + break; + } + + r = sd_netlink_message_append_u16(m, L2TP_ATTR_ENCAP_TYPE, encap_type); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_ENCAP_TYPE attribute: %m"); + + if (t->family == AF_INET) { + r = sd_netlink_message_append_in_addr(m, L2TP_ATTR_IP_SADDR, &local_address->in); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP_SADDR attribute: %m"); + + r = sd_netlink_message_append_in_addr(m, L2TP_ATTR_IP_DADDR, &t->remote.in); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP_DADDR attribute: %m"); + } else { + r = sd_netlink_message_append_in6_addr(m, L2TP_ATTR_IP6_SADDR, &local_address->in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP6_SADDR attribute: %m"); + + r = sd_netlink_message_append_in6_addr(m, L2TP_ATTR_IP6_DADDR, &t->remote.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IP6_DADDR attribute: %m"); + } + + if (encap_type == L2TP_ENCAPTYPE_UDP) { + r = sd_netlink_message_append_u16(m, L2TP_ATTR_UDP_SPORT, t->l2tp_udp_sport); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_SPORT, attribute: %m"); + + r = sd_netlink_message_append_u16(m, L2TP_ATTR_UDP_DPORT, t->l2tp_udp_dport); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_DPORT attribute: %m"); + + if (t->udp_csum) { + r = sd_netlink_message_append_u8(m, L2TP_ATTR_UDP_CSUM, t->udp_csum); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_CSUM attribute: %m"); + } + + if (t->udp6_csum_tx) { + r = sd_netlink_message_append_flag(m, L2TP_ATTR_UDP_ZERO_CSUM6_TX); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_ZERO_CSUM6_TX attribute: %m"); + } + + if (t->udp6_csum_rx) { + r = sd_netlink_message_append_flag(m, L2TP_ATTR_UDP_ZERO_CSUM6_RX); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_UDP_ZERO_CSUM6_RX attribute: %m"); + } + } + + *ret = TAKE_PTR(m); + + return 0; +} + +static int netdev_l2tp_fill_message_session(NetDev *netdev, L2tpSession *session, sd_netlink_message **ret) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + uint16_t l2_spec_len; + uint8_t l2_spec_type; + int r; + + assert(netdev); + assert(session); + assert(session->tunnel); + + r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_SESSION_CREATE, &m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m"); + + r = sd_netlink_message_append_u32(m, L2TP_ATTR_CONN_ID, session->tunnel->tunnel_id); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_CONN_ID attribute: %m"); + + r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_CONN_ID, session->tunnel->peer_tunnel_id); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_CONN_ID attribute: %m"); + + r = sd_netlink_message_append_u32(m, L2TP_ATTR_SESSION_ID, session->session_id); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_SESSION_ID attribute: %m"); + + r = sd_netlink_message_append_u32(m, L2TP_ATTR_PEER_SESSION_ID, session->peer_session_id); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PEER_SESSION_ID attribute: %m"); + + r = sd_netlink_message_append_u16(m, L2TP_ATTR_PW_TYPE, L2TP_PWTYPE_ETH); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_PW_TYPE attribute: %m"); + + switch (session->l2tp_l2spec_type) { + case NETDEV_L2TP_L2SPECTYPE_NONE: + l2_spec_type = L2TP_L2SPECTYPE_NONE; + l2_spec_len = 0; + break; + case NETDEV_L2TP_L2SPECTYPE_DEFAULT: + default: + l2_spec_type = L2TP_L2SPECTYPE_DEFAULT; + l2_spec_len = 4; + break; + } + + r = sd_netlink_message_append_u8(m, L2TP_ATTR_L2SPEC_TYPE, l2_spec_type); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_L2SPEC_TYPE attribute: %m"); + + r = sd_netlink_message_append_u8(m, L2TP_ATTR_L2SPEC_LEN, l2_spec_len); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_L2SPEC_LEN attribute: %m"); + + r = sd_netlink_message_append_string(m, L2TP_ATTR_IFNAME, session->name); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append L2TP_ATTR_IFNAME attribute: %m"); + + *ret = TAKE_PTR(m); + + return 0; +} + +static int l2tp_acquire_local_address_one(L2tpTunnel *t, Address *a, union in_addr_union *ret) { + if (a->family != t->family) + return -EINVAL; + + if (in_addr_is_null(a->family, &a->in_addr_peer) <= 0) + return -EINVAL; + + if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_STATIC && + !FLAGS_SET(a->flags, IFA_F_PERMANENT)) + return -EINVAL; + + if (t->local_address_type == NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC && + FLAGS_SET(a->flags, IFA_F_PERMANENT)) + return -EINVAL; + + *ret = a->in_addr; + return 0; +} + +static int l2tp_acquire_local_address(L2tpTunnel *t, Link *link, union in_addr_union *ret) { + Address *a; + Iterator i; + + assert(t); + assert(link); + assert(ret); + assert(IN_SET(t->family, AF_INET, AF_INET6)); + + if (!in_addr_is_null(t->family, &t->local)) { + /* local address is explicitly specified. */ + *ret = t->local; + return 0; + } + + SET_FOREACH(a, link->addresses, i) + if (l2tp_acquire_local_address_one(t, a, ret) >= 0) + return 1; + + SET_FOREACH(a, link->addresses_foreign, i) + if (l2tp_acquire_local_address_one(t, a, ret) >= 0) + return 1; + + return -ENODATA; +} + +static void l2tp_session_destroy_callback(L2tpSession *session) { + if (!session) + return; + + netdev_unref(NETDEV(session->tunnel)); +} + +static int l2tp_create_session_handler(sd_netlink *rtnl, sd_netlink_message *m, L2tpSession *session) { + NetDev *netdev; + int r; + + assert(session); + assert(session->tunnel); + + netdev = NETDEV(session->tunnel); + + r = sd_netlink_message_get_errno(m); + if (r == -EEXIST) + log_netdev_info(netdev, "L2TP session %s exists, using existing without changing its parameters", + session->name); + else if (r < 0) { + log_netdev_warning_errno(netdev, r, "L2TP session %s could not be created: %m", session->name); + return 1; + } + + log_netdev_debug(netdev, "L2TP session %s created", session->name); + return 1; +} + +static int l2tp_create_session(NetDev *netdev, L2tpSession *session) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *n = NULL; + int r; + + r = netdev_l2tp_fill_message_session(netdev, session, &n); + if (r < 0) + return r; + + r = netlink_call_async(netdev->manager->genl, NULL, n, l2tp_create_session_handler, + l2tp_session_destroy_callback, session); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to create L2TP session %s: %m", session->name); + + netdev_ref(netdev); + return 0; +} + +static int l2tp_create_tunnel_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) { + L2tpSession *session; + L2tpTunnel *t; + Iterator i; + int r; + + assert(netdev); + assert(netdev->state != _NETDEV_STATE_INVALID); + + t = L2TP(netdev); + + assert(t); + + r = sd_netlink_message_get_errno(m); + if (r == -EEXIST) + log_netdev_info(netdev, "netdev exists, using existing without changing its parameters"); + else if (r < 0) { + log_netdev_warning_errno(netdev, r, "netdev could not be created: %m"); + netdev_drop(netdev); + + return 1; + } + + log_netdev_debug(netdev, "L2TP tunnel is created"); + + ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section, i) + (void) l2tp_create_session(netdev, session); + + return 1; +} + +static int l2tp_create_tunnel(NetDev *netdev, Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + union in_addr_union local_address; + L2tpTunnel *t; + int r; + + assert(netdev); + + t = L2TP(netdev); + + assert(t); + + r = l2tp_acquire_local_address(t, link, &local_address); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not find local address."); + + if (r > 0 && DEBUG_LOGGING) { + _cleanup_free_ char *str = NULL; + + (void) in_addr_to_string(t->family, &local_address, &str); + log_netdev_debug(netdev, "Local address %s acquired.", strna(str)); + } + + r = netdev_l2tp_fill_message_tunnel(netdev, &local_address, &m); + if (r < 0) + return r; + + r = netlink_call_async(netdev->manager->genl, NULL, m, l2tp_create_tunnel_handler, + netdev_destroy_callback, netdev); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to create L2TP tunnel: %m"); + + netdev_ref(netdev); + + return 0; +} + +int config_parse_l2tp_tunnel_address( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + L2tpTunnel *t = userdata; + union in_addr_union *addr = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(lvalue, "Local")) { + L2tpLocalAddressType addr_type; + + if (isempty(rvalue)) + addr_type = NETDEV_L2TP_LOCAL_ADDRESS_AUTO; + else + addr_type = l2tp_local_address_type_from_string(rvalue); + + if (addr_type >= 0) { + if (in_addr_is_null(t->family, &t->remote) != 0) + /* If Remote= is not specified yet, then also clear family. */ + t->family = AF_UNSPEC; + + t->local = IN_ADDR_NULL; + t->local_address_type = addr_type; + + return 0; + } + } + + if (t->family == AF_UNSPEC) + r = in_addr_from_string_auto(rvalue, &t->family, addr); + else + r = in_addr_from_string(t->family, rvalue, addr); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid L2TP Tunnel address specified in %s='%s', ignoring assignment: %m", lvalue, rvalue); + return 0; + } + + return 0; +} + +int config_parse_l2tp_tunnel_id( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint32_t *id = data, k; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou32(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse L2TP tunnel id. Ignoring assignment: %s", rvalue); + return 0; + } + + if (k == 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid L2TP tunnel id. Ignoring assignment: %s", rvalue); + return 0; + } + + *id = k; + + return 0; +} + +int config_parse_l2tp_session_id( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL; + L2tpTunnel *t = userdata; + uint32_t k; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = l2tp_session_new_static(t, filename, section_line, &session); + if (r < 0) + return r; + + r = safe_atou32(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse L2TP session id. Ignoring assignment: %s", rvalue); + return 0; + } + + if (k == 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid L2TP session id. Ignoring assignment: %s", rvalue); + return 0; + } + + if (streq(lvalue, "SessionId")) + session->session_id = k; + else + session->peer_session_id = k; + + session = NULL; + return 0; +} + +int config_parse_l2tp_session_l2spec( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL; + L2tpTunnel *t = userdata; + L2tpL2specType spec; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = l2tp_session_new_static(t, filename, section_line, &session); + if (r < 0) + return r; + + spec = l2tp_l2spec_type_from_string(rvalue); + if (spec < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse layer2 specific header type. Ignoring assignment: %s", rvalue); + return 0; + } + + session->l2tp_l2spec_type = spec; + + session = NULL; + return 0; +} + +int config_parse_l2tp_session_name( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(l2tp_session_free_or_set_invalidp) L2tpSession *session = NULL; + L2tpTunnel *t = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = l2tp_session_new_static(t, filename, section_line, &session); + if (r < 0) + return r; + + if (!ifname_valid(rvalue)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse L2TP tunnel session name. Ignoring assignment: %s", rvalue); + return 0; + } + + r = free_and_strdup(&session->name, rvalue); + if (r < 0) + return log_oom(); + + session = NULL; + return 0; +} + +static void l2tp_tunnel_init(NetDev *netdev) { + L2tpTunnel *t; + + assert(netdev); + + t = L2TP(netdev); + + assert(t); + + t->l2tp_encap_type = NETDEV_L2TP_ENCAPTYPE_UDP; + t->udp6_csum_rx = true; + t->udp6_csum_tx = true; +} + +static int l2tp_session_verify(L2tpSession *session) { + NetDev *netdev; + + assert(session); + assert(session->tunnel); + + netdev = NETDEV(session->tunnel); + + if (section_is_invalid(session->section)) + return -EINVAL; + + if (!session->name) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: L2TP session without name configured. " + "Ignoring [L2TPSession] section from line %u", + session->section->filename, session->section->line); + + if (session->session_id == 0 || session->peer_session_id == 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: L2TP session without session IDs configured. " + "Ignoring [L2TPSession] section from line %u", + session->section->filename, session->section->line); + + return 0; +} + +static int netdev_l2tp_tunnel_verify(NetDev *netdev, const char *filename) { + L2tpTunnel *t; + L2tpSession *session; + Iterator i; + + assert(netdev); + assert(filename); + + t = L2TP(netdev); + + assert(t); + + if (!IN_SET(t->family, AF_INET, AF_INET6)) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: L2TP tunnel with invalid address family configured. Ignoring", + filename); + + if (in_addr_is_null(t->family, &t->remote)) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: L2TP tunnel without a remote address configured. Ignoring", + filename); + + if (t->tunnel_id == 0 || t->peer_tunnel_id == 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: L2TP tunnel without tunnel IDs configured. Ignoring", + filename); + + ORDERED_HASHMAP_FOREACH(session, t->sessions_by_section, i) + if (l2tp_session_verify(session) < 0) + l2tp_session_free(session); + + return 0; +} + +static void l2tp_tunnel_done(NetDev *netdev) { + L2tpTunnel *t; + + assert(netdev); + + t = L2TP(netdev); + + assert(t); + + ordered_hashmap_free_with_destructor(t->sessions_by_section, l2tp_session_free); +} + +const NetDevVTable l2tptnl_vtable = { + .object_size = sizeof(L2tpTunnel), + .init = l2tp_tunnel_init, + .sections = "Match\0NetDev\0L2TP\0L2TPSession\0", + .create_after_configured = l2tp_create_tunnel, + .done = l2tp_tunnel_done, + .create_type = NETDEV_CREATE_AFTER_CONFIGURED, + .config_verify = netdev_l2tp_tunnel_verify, +}; diff --git a/src/network/netdev/l2tp-tunnel.h b/src/network/netdev/l2tp-tunnel.h new file mode 100644 index 00000000..d314b987 --- /dev/null +++ b/src/network/netdev/l2tp-tunnel.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "in-addr-util.h" +#include "netdev.h" +#include "networkd-util.h" + +typedef enum L2tpL2specType { + NETDEV_L2TP_L2SPECTYPE_NONE = L2TP_L2SPECTYPE_NONE, + NETDEV_L2TP_L2SPECTYPE_DEFAULT = L2TP_L2SPECTYPE_DEFAULT, + _NETDEV_L2TP_L2SPECTYPE_MAX, + _NETDEV_L2TP_L2SPECTYPE_INVALID = -1, +} L2tpL2specType; + +typedef enum L2tpEncapType { + NETDEV_L2TP_ENCAPTYPE_UDP = L2TP_ENCAPTYPE_UDP, + NETDEV_L2TP_ENCAPTYPE_IP = L2TP_ENCAPTYPE_IP, + _NETDEV_L2TP_ENCAPTYPE_MAX, + _NETDEV_L2TP_ENCAPTYPE_INVALID = -1, +} L2tpEncapType; + +typedef enum L2tpLocalAddressType { + NETDEV_L2TP_LOCAL_ADDRESS_AUTO, + NETDEV_L2TP_LOCAL_ADDRESS_STATIC, + NETDEV_L2TP_LOCAL_ADDRESS_DYNAMIC, + _NETDEV_L2TP_LOCAL_ADDRESS_MAX, + _NETDEV_L2TP_LOCAL_ADDRESS_INVALID = -1, +} L2tpLocalAddressType; + +typedef struct L2tpTunnel L2tpTunnel; + +typedef struct L2tpSession { + L2tpTunnel *tunnel; + NetworkConfigSection *section; + + char *name; + + uint32_t session_id; + uint32_t peer_session_id; + L2tpL2specType l2tp_l2spec_type; +} L2tpSession; + +struct L2tpTunnel { + NetDev meta; + + uint16_t l2tp_udp_sport; + uint16_t l2tp_udp_dport; + + uint32_t tunnel_id; + uint32_t peer_tunnel_id; + + int family; + + bool udp_csum; + bool udp6_csum_rx; + bool udp6_csum_tx; + + L2tpLocalAddressType local_address_type; + union in_addr_union local; + union in_addr_union remote; + + L2tpEncapType l2tp_encap_type; + + OrderedHashmap *sessions_by_section; +}; + +DEFINE_NETDEV_CAST(L2TP, L2tpTunnel); +extern const NetDevVTable l2tptnl_vtable; + +CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_tunnel_address); +CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_tunnel_id); +CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_encap_type); +CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_session_l2spec); +CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_session_id); +CONFIG_PARSER_PROTOTYPE(config_parse_l2tp_session_name); diff --git a/src/network/netdev/macsec.c b/src/network/netdev/macsec.c new file mode 100644 index 00000000..25dc23ff --- /dev/null +++ b/src/network/netdev/macsec.c @@ -0,0 +1,1245 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "conf-parser.h" +#include "fileio.h" +#include "hashmap.h" +#include "hexdecoct.h" +#include "macsec.h" +#include "memory-util.h" +#include "netlink-util.h" +#include "network-internal.h" +#include "networkd-address.h" +#include "networkd-manager.h" +#include "path-util.h" +#include "socket-util.h" +#include "string-table.h" +#include "string-util.h" +#include "util.h" + +static void security_association_clear(SecurityAssociation *sa) { + if (!sa) + return; + + explicit_bzero_safe(sa->key, sa->key_len); + free(sa->key); + free(sa->key_file); +} + +static void security_association_init(SecurityAssociation *sa) { + assert(sa); + + sa->activate = -1; + sa->use_for_encoding = -1; +} + +static void macsec_receive_association_free(ReceiveAssociation *c) { + if (!c) + return; + + if (c->macsec && c->section) + ordered_hashmap_remove(c->macsec->receive_associations_by_section, c->section); + + network_config_section_free(c->section); + security_association_clear(&c->sa); + + free(c); +} + +DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveAssociation, macsec_receive_association_free); + +static int macsec_receive_association_new_static(MACsec *s, const char *filename, unsigned section_line, ReceiveAssociation **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(macsec_receive_association_freep) ReceiveAssociation *c = NULL; + int r; + + assert(s); + assert(ret); + assert(filename); + assert(section_line > 0); + + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + c = ordered_hashmap_get(s->receive_associations_by_section, n); + if (c) { + *ret = TAKE_PTR(c); + return 0; + } + + c = new(ReceiveAssociation, 1); + if (!c) + return -ENOMEM; + + *c = (ReceiveAssociation) { + .macsec = s, + .section = TAKE_PTR(n), + }; + + security_association_init(&c->sa); + + r = ordered_hashmap_ensure_allocated(&s->receive_associations_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(s->receive_associations_by_section, c->section, c); + if (r < 0) + return r; + + *ret = TAKE_PTR(c); + + return 0; +} + +static void macsec_receive_channel_free(ReceiveChannel *c) { + if (!c) + return; + + if (c->macsec) { + if (c->sci.as_uint64 > 0) + ordered_hashmap_remove(c->macsec->receive_channels, &c->sci.as_uint64); + + if (c->section) + ordered_hashmap_remove(c->macsec->receive_channels_by_section, c->section); + } + + network_config_section_free(c->section); + + free(c); +} + +DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveChannel, macsec_receive_channel_free); + +static int macsec_receive_channel_new(MACsec *s, uint64_t sci, ReceiveChannel **ret) { + ReceiveChannel *c; + + assert(s); + + c = new(ReceiveChannel, 1); + if (!c) + return -ENOMEM; + + *c = (ReceiveChannel) { + .macsec = s, + .sci.as_uint64 = sci, + }; + + *ret = c; + return 0; +} + +static int macsec_receive_channel_new_static(MACsec *s, const char *filename, unsigned section_line, ReceiveChannel **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(macsec_receive_channel_freep) ReceiveChannel *c = NULL; + int r; + + assert(s); + assert(ret); + assert(filename); + assert(section_line > 0); + + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + c = ordered_hashmap_get(s->receive_channels_by_section, n); + if (c) { + *ret = TAKE_PTR(c); + return 0; + } + + r = macsec_receive_channel_new(s, 0, &c); + if (r < 0) + return r; + + c->section = TAKE_PTR(n); + + r = ordered_hashmap_ensure_allocated(&s->receive_channels_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(s->receive_channels_by_section, c->section, c); + if (r < 0) + return r; + + *ret = TAKE_PTR(c); + + return 0; +} + +static void macsec_transmit_association_free(TransmitAssociation *a) { + if (!a) + return; + + if (a->macsec && a->section) + ordered_hashmap_remove(a->macsec->transmit_associations_by_section, a->section); + + network_config_section_free(a->section); + security_association_clear(&a->sa); + + free(a); +} + +DEFINE_NETWORK_SECTION_FUNCTIONS(TransmitAssociation, macsec_transmit_association_free); + +static int macsec_transmit_association_new_static(MACsec *s, const char *filename, unsigned section_line, TransmitAssociation **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(macsec_transmit_association_freep) TransmitAssociation *a = NULL; + int r; + + assert(s); + assert(ret); + assert(filename); + assert(section_line > 0); + + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + a = ordered_hashmap_get(s->transmit_associations_by_section, n); + if (a) { + *ret = TAKE_PTR(a); + return 0; + } + + a = new(TransmitAssociation, 1); + if (!a) + return -ENOMEM; + + *a = (TransmitAssociation) { + .macsec = s, + .section = TAKE_PTR(n), + }; + + security_association_init(&a->sa); + + r = ordered_hashmap_ensure_allocated(&s->transmit_associations_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(s->transmit_associations_by_section, a->section, a); + if (r < 0) + return r; + + *ret = TAKE_PTR(a); + + return 0; +} + +static int netdev_macsec_fill_message(NetDev *netdev, int command, sd_netlink_message **ret) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(netdev); + assert(netdev->ifindex > 0); + + r = sd_genl_message_new(netdev->manager->genl, SD_GENL_MACSEC, command, &m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m"); + + r = sd_netlink_message_append_u32(m, MACSEC_ATTR_IFINDEX, netdev->ifindex); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_ATTR_IFINDEX attribute: %m"); + + *ret = TAKE_PTR(m); + + return 0; +} + +static int netdev_macsec_fill_message_sci(NetDev *netdev, MACsecSCI *sci, sd_netlink_message *m) { + int r; + + assert(netdev); + assert(m); + assert(sci); + + r = sd_netlink_message_open_container(m, MACSEC_ATTR_RXSC_CONFIG); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_ATTR_RXSC_CONFIG attribute: %m"); + + r = sd_netlink_message_append_u64(m, MACSEC_RXSC_ATTR_SCI, sci->as_uint64); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_RXSC_ATTR_SCI attribute: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_ATTR_RXSC_CONFIG attribute: %m"); + + return 0; +} + +static int netdev_macsec_fill_message_sa(NetDev *netdev, SecurityAssociation *a, sd_netlink_message *m) { + int r; + + assert(netdev); + assert(a); + assert(m); + + r = sd_netlink_message_open_container(m, MACSEC_ATTR_SA_CONFIG); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_ATTR_SA_CONFIG attribute: %m"); + + r = sd_netlink_message_append_u8(m, MACSEC_SA_ATTR_AN, a->association_number); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_SA_ATTR_AN attribute: %m"); + + if (a->packet_number > 0) { + r = sd_netlink_message_append_u32(m, MACSEC_SA_ATTR_PN, a->packet_number); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_SA_ATTR_PN attribute: %m"); + } + + if (a->key_len > 0) { + r = sd_netlink_message_append_data(m, MACSEC_SA_ATTR_KEYID, a->key_id, MACSEC_KEYID_LEN); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_SA_ATTR_KEYID attribute: %m"); + + r = sd_netlink_message_append_data(m, MACSEC_SA_ATTR_KEY, a->key, a->key_len); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_SA_ATTR_KEY attribute: %m"); + } + + if (a->activate >= 0) { + r = sd_netlink_message_append_u8(m, MACSEC_SA_ATTR_ACTIVE, a->activate); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_SA_ATTR_ACTIVE attribute: %m"); + } + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append MACSEC_ATTR_SA_CONFIG attribute: %m"); + + return 0; +} + +static int macsec_receive_association_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) { + int r; + + assert(netdev); + assert(netdev->state != _NETDEV_STATE_INVALID); + + r = sd_netlink_message_get_errno(m); + if (r == -EEXIST) + log_netdev_info(netdev, + "MACsec receive secure association exists, " + "using existing without changing its parameters"); + else if (r < 0) { + log_netdev_warning_errno(netdev, r, + "Failed to add receive secure association: %m"); + netdev_drop(netdev); + + return 1; + } + + log_netdev_debug(netdev, "Receive secure association is configured"); + + return 1; +} + +static int netdev_macsec_configure_receive_association(NetDev *netdev, ReceiveAssociation *a) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(netdev); + assert(a); + + r = netdev_macsec_fill_message(netdev, MACSEC_CMD_ADD_RXSA, &m); + if (r < 0) + return r; + + r = netdev_macsec_fill_message_sa(netdev, &a->sa, m); + if (r < 0) + return r; + + r = netdev_macsec_fill_message_sci(netdev, &a->sci, m); + if (r < 0) + return r; + + r = netlink_call_async(netdev->manager->genl, NULL, m, macsec_receive_association_handler, + netdev_destroy_callback, netdev); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to configure receive secure association: %m"); + + netdev_ref(netdev); + + return 0; +} + +static int macsec_receive_channel_handler(sd_netlink *rtnl, sd_netlink_message *m, ReceiveChannel *c) { + NetDev *netdev; + unsigned i; + int r; + + assert(c); + assert(c->macsec); + + netdev = NETDEV(c->macsec); + + assert(netdev->state != _NETDEV_STATE_INVALID); + + r = sd_netlink_message_get_errno(m); + if (r == -EEXIST) + log_netdev_debug(netdev, + "MACsec receive channel exists, " + "using existing without changing its parameters"); + else if (r < 0) { + log_netdev_warning_errno(netdev, r, + "Failed to add receive secure channel: %m"); + netdev_drop(netdev); + + return 1; + } + + log_netdev_debug(netdev, "Receive channel is configured"); + + for (i = 0; i < c->n_rxsa; i++) { + r = netdev_macsec_configure_receive_association(netdev, c->rxsa[i]); + if (r < 0) { + log_netdev_warning_errno(netdev, r, + "Failed to configure receive security association: %m"); + netdev_drop(netdev); + return 1; + } + } + + return 1; +} + +static void receive_channel_destroy_callback(ReceiveChannel *c) { + assert(c); + assert(c->macsec); + + netdev_unref(NETDEV(c->macsec)); +} + +static int netdev_macsec_configure_receive_channel(NetDev *netdev, ReceiveChannel *c) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(netdev); + assert(c); + + r = netdev_macsec_fill_message(netdev, MACSEC_CMD_ADD_RXSC, &m); + if (r < 0) + return r; + + r = netdev_macsec_fill_message_sci(netdev, &c->sci, m); + if (r < 0) + return r; + + r = netlink_call_async(netdev->manager->genl, NULL, m, macsec_receive_channel_handler, + receive_channel_destroy_callback, c); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to configure receive channel: %m"); + + netdev_ref(netdev); + + return 0; +} + +static int macsec_transmit_association_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) { + int r; + + assert(netdev); + assert(netdev->state != _NETDEV_STATE_INVALID); + + r = sd_netlink_message_get_errno(m); + if (r == -EEXIST) + log_netdev_info(netdev, + "MACsec transmit secure association exists, " + "using existing without changing its parameters"); + else if (r < 0) { + log_netdev_warning_errno(netdev, r, + "Failed to add transmit secure association: %m"); + netdev_drop(netdev); + + return 1; + } + + log_netdev_debug(netdev, "Transmit secure association is configured"); + + return 1; +} + +static int netdev_macsec_configure_transmit_association(NetDev *netdev, TransmitAssociation *a) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(netdev); + assert(a); + + r = netdev_macsec_fill_message(netdev, MACSEC_CMD_ADD_TXSA, &m); + if (r < 0) + return r; + + r = netdev_macsec_fill_message_sa(netdev, &a->sa, m); + if (r < 0) + return r; + + r = netlink_call_async(netdev->manager->genl, NULL, m, macsec_transmit_association_handler, + netdev_destroy_callback, netdev); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to configure transmit secure association: %m"); + + netdev_ref(netdev); + + return 0; +} + +static int netdev_macsec_configure(NetDev *netdev, Link *link, sd_netlink_message *m) { + TransmitAssociation *a; + ReceiveChannel *c; + Iterator i; + MACsec *s; + int r; + + assert(netdev); + s = MACSEC(netdev); + assert(s); + + ORDERED_HASHMAP_FOREACH(a, s->transmit_associations_by_section, i) { + r = netdev_macsec_configure_transmit_association(netdev, a); + if (r < 0) + return r; + } + + ORDERED_HASHMAP_FOREACH(c, s->receive_channels, i) { + r = netdev_macsec_configure_receive_channel(netdev, c); + if (r < 0) + return r; + } + + return 0; +} + +static int netdev_macsec_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + MACsec *v; + int r; + + assert(netdev); + assert(m); + + v = MACSEC(netdev); + + if (v->port > 0) { + r = sd_netlink_message_append_u16(m, IFLA_MACSEC_PORT, v->port); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACSEC_PORT attribute: %m"); + } + + if (v->encrypt >= 0) { + r = sd_netlink_message_append_u8(m, IFLA_MACSEC_ENCRYPT, v->encrypt); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACSEC_ENCRYPT attribute: %m"); + } + + r = sd_netlink_message_append_u8(m, IFLA_MACSEC_ENCODING_SA, v->encoding_an); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACSEC_ENCODING_SA attribute: %m"); + + return r; +} + +int config_parse_macsec_port( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL; + _cleanup_(macsec_receive_channel_free_or_set_invalidp) ReceiveChannel *c = NULL; + MACsec *s = userdata; + uint16_t port; + void *dest; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + /* This parses port used to make Secure Channel Identifier (SCI) */ + + if (streq(section, "MACsec")) + dest = &s->port; + else if (streq(section, "MACsecReceiveChannel")) { + r = macsec_receive_channel_new_static(s, filename, section_line, &c); + if (r < 0) + return r; + + dest = &c->sci.port; + } else { + assert(streq(section, "MACsecReceiveAssociation")); + + r = macsec_receive_association_new_static(s, filename, section_line, &b); + if (r < 0) + return r; + + dest = &b->sci.port; + } + + r = parse_ip_port(rvalue, &port); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse port '%s' for secure channel identifier. Ignoring assignment: %m", + rvalue); + return 0; + } + + unaligned_write_be16(dest, port); + + TAKE_PTR(b); + TAKE_PTR(c); + + return 0; +} + +int config_parse_macsec_hw_address( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL; + _cleanup_(macsec_receive_channel_free_or_set_invalidp) ReceiveChannel *c = NULL; + MACsec *s = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(section, "MACsecReceiveChannel")) + r = macsec_receive_channel_new_static(s, filename, section_line, &c); + else + r = macsec_receive_association_new_static(s, filename, section_line, &b); + if (r < 0) + return r; + + r = ether_addr_from_string(rvalue, b ? &b->sci.mac : &c->sci.mac); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse MAC address for secure channel identifier. " + "Ignoring assignment: %s", rvalue); + return 0; + } + + TAKE_PTR(b); + TAKE_PTR(c); + + return 0; +} + +int config_parse_macsec_packet_number( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL; + _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL; + MACsec *s = userdata; + uint32_t val, *dest; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(section, "MACsecTransmitAssociation")) + r = macsec_transmit_association_new_static(s, filename, section_line, &a); + else + r = macsec_receive_association_new_static(s, filename, section_line, &b); + if (r < 0) + return r; + + dest = a ? &a->sa.packet_number : &b->sa.packet_number; + + r = safe_atou32(rvalue, &val); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse packet number. Ignoring assignment: %s", rvalue); + return 0; + } + if (streq(section, "MACsecTransmitAssociation") && val == 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid packet number. Ignoring assignment: %s", rvalue); + return 0; + } + + *dest = val; + TAKE_PTR(a); + TAKE_PTR(b); + + return 0; +} + +int config_parse_macsec_key( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL; + _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL; + _cleanup_(erase_and_freep) void *p = NULL; + MACsec *s = userdata; + SecurityAssociation *dest; + size_t l; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + (void) warn_file_is_world_accessible(filename, NULL, unit, line); + + if (streq(section, "MACsecTransmitAssociation")) + r = macsec_transmit_association_new_static(s, filename, section_line, &a); + else + r = macsec_receive_association_new_static(s, filename, section_line, &b); + if (r < 0) + return r; + + dest = a ? &a->sa : &b->sa; + + r = unhexmem_full(rvalue, strlen(rvalue), true, &p, &l); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse key. Ignoring assignment: %m"); + return 0; + } + + if (l != 16) { + /* See DEFAULT_SAK_LEN in drivers/net/macsec.c */ + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid key length (%zu). Ignoring assignment", l); + return 0; + } + + explicit_bzero_safe(dest->key, dest->key_len); + free_and_replace(dest->key, p); + dest->key_len = l; + + TAKE_PTR(a); + TAKE_PTR(b); + + return 0; +} + +int config_parse_macsec_key_file( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL; + _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL; + _cleanup_free_ char *path = NULL; + MACsec *s = userdata; + char **dest; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(section, "MACsecTransmitAssociation")) + r = macsec_transmit_association_new_static(s, filename, section_line, &a); + else + r = macsec_receive_association_new_static(s, filename, section_line, &b); + if (r < 0) + return r; + + dest = a ? &a->sa.key_file : &b->sa.key_file; + + if (isempty(rvalue)) { + *dest = mfree(*dest); + return 0; + } + + path = strdup(rvalue); + if (!path) + return log_oom(); + + if (path_simplify_and_warn(path, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue) < 0) + return 0; + + free_and_replace(*dest, path); + TAKE_PTR(a); + TAKE_PTR(b); + + return 0; +} + +int config_parse_macsec_key_id( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL; + _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL; + _cleanup_free_ void *p; + MACsec *s = userdata; + uint8_t *dest; + size_t l; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(section, "MACsecTransmitAssociation")) + r = macsec_transmit_association_new_static(s, filename, section_line, &a); + else + r = macsec_receive_association_new_static(s, filename, section_line, &b); + if (r < 0) + return r; + + r = unhexmem(rvalue, strlen(rvalue), &p, &l); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse KeyId \"%s\": %m", rvalue); + return 0; + } + if (l > MACSEC_KEYID_LEN) + return log_syntax(unit, LOG_ERR, filename, line, 0, + "Specified KeyId is larger then the allowed maximum (%zu > %u), ignoring: %s", + l, MACSEC_KEYID_LEN, rvalue); + + dest = a ? a->sa.key_id : b->sa.key_id; + memcpy_safe(dest, p, l); + memzero(dest + l, MACSEC_KEYID_LEN - l); + + TAKE_PTR(a); + TAKE_PTR(b); + + return 0; +} + +int config_parse_macsec_sa_activate( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL; + _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL; + MACsec *s = userdata; + int *dest; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(section, "MACsecTransmitAssociation")) + r = macsec_transmit_association_new_static(s, filename, section_line, &a); + else + r = macsec_receive_association_new_static(s, filename, section_line, &b); + if (r < 0) + return r; + + dest = a ? &a->sa.activate : &b->sa.activate; + + if (isempty(rvalue)) + r = -1; + else { + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse activation mode of %s security association. " + "Ignoring assignment: %s", + streq(section, "MACsecTransmitAssociation") ? "transmit" : "receive", + rvalue); + return 0; + } + } + + *dest = r; + TAKE_PTR(a); + TAKE_PTR(b); + + return 0; +} + +int config_parse_macsec_use_for_encoding( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL; + MACsec *s = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = macsec_transmit_association_new_static(s, filename, section_line, &a); + if (r < 0) + return r; + + if (isempty(rvalue)) + r = -1; + else { + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse %s= setting. Ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + } + + a->sa.use_for_encoding = r; + if (a->sa.use_for_encoding > 0) + a->sa.activate = true; + + TAKE_PTR(a); + + return 0; +} + +static int macsec_read_key_file(NetDev *netdev, SecurityAssociation *sa) { + _cleanup_(erase_and_freep) uint8_t *key = NULL; + size_t key_len; + int r; + + assert(netdev); + assert(sa); + + if (!sa->key_file) + return 0; + + (void) warn_file_is_world_accessible(sa->key_file, NULL, NULL, 0); + + r = read_full_file_full(sa->key_file, READ_FULL_FILE_SECURE | READ_FULL_FILE_UNHEX, (char **) &key, &key_len); + if (r < 0) + return log_netdev_error_errno(netdev, r, + "Failed to read key from '%s', ignoring: %m", + sa->key_file); + + if (key_len != 16) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "Invalid key length (%zu bytes), ignoring: %m", key_len); + + explicit_bzero_safe(sa->key, sa->key_len); + free_and_replace(sa->key, key); + sa->key_len = key_len; + + return 0; +} + +static int macsec_receive_channel_verify(ReceiveChannel *c) { + NetDev *netdev; + int r; + + assert(c); + assert(c->macsec); + + netdev = NETDEV(c->macsec); + + if (section_is_invalid(c->section)) + return -EINVAL; + + if (ether_addr_is_null(&c->sci.mac)) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: MACsec receive channel without MAC address configured. " + "Ignoring [MACsecReceiveChannel] section from line %u", + c->section->filename, c->section->line); + + if (c->sci.port == 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: MACsec receive channel without port configured. " + "Ignoring [MACsecReceiveChannel] section from line %u", + c->section->filename, c->section->line); + + r = ordered_hashmap_ensure_allocated(&c->macsec->receive_channels, &uint64_hash_ops); + if (r < 0) + return log_oom(); + + r = ordered_hashmap_put(c->macsec->receive_channels, &c->sci.as_uint64, c); + if (r == -EEXIST) + return log_netdev_error_errno(netdev, r, + "%s: Multiple [MACsecReceiveChannel] sections have same SCI, " + "Ignoring [MACsecReceiveChannel] section from line %u", + c->section->filename, c->section->line); + if (r < 0) + return log_netdev_error_errno(netdev, r, + "%s: Failed to store [MACsecReceiveChannel] section at hashmap, " + "Ignoring [MACsecReceiveChannel] section from line %u", + c->section->filename, c->section->line); + return 0; +} + +static int macsec_transmit_association_verify(TransmitAssociation *t) { + NetDev *netdev; + int r; + + assert(t); + assert(t->macsec); + + netdev = NETDEV(t->macsec); + + if (section_is_invalid(t->section)) + return -EINVAL; + + if (t->sa.packet_number == 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: MACsec transmit secure association without PacketNumber= configured. " + "Ignoring [MACsecTransmitAssociation] section from line %u", + t->section->filename, t->section->line); + + r = macsec_read_key_file(netdev, &t->sa); + if (r < 0) + return r; + + if (t->sa.key_len <= 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: MACsec transmit secure association without key configured. " + "Ignoring [MACsecTransmitAssociation] section from line %u", + t->section->filename, t->section->line); + + return 0; +} + +static int macsec_receive_association_verify(ReceiveAssociation *a) { + ReceiveChannel *c; + NetDev *netdev; + int r; + + assert(a); + assert(a->macsec); + + netdev = NETDEV(a->macsec); + + if (section_is_invalid(a->section)) + return -EINVAL; + + r = macsec_read_key_file(netdev, &a->sa); + if (r < 0) + return r; + + if (a->sa.key_len <= 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: MACsec receive secure association without key configured. " + "Ignoring [MACsecReceiveAssociation] section from line %u", + a->section->filename, a->section->line); + + if (ether_addr_is_null(&a->sci.mac)) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: MACsec receive secure association without MAC address configured. " + "Ignoring [MACsecReceiveAssociation] section from line %u", + a->section->filename, a->section->line); + + if (a->sci.port == 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: MACsec receive secure association without port configured. " + "Ignoring [MACsecReceiveAssociation] section from line %u", + a->section->filename, a->section->line); + + c = ordered_hashmap_get(a->macsec->receive_channels, &a->sci.as_uint64); + if (!c) { + _cleanup_(macsec_receive_channel_freep) ReceiveChannel *new_channel = NULL; + + r = macsec_receive_channel_new(a->macsec, a->sci.as_uint64, &new_channel); + if (r < 0) + return log_oom(); + + r = ordered_hashmap_ensure_allocated(&a->macsec->receive_channels, &uint64_hash_ops); + if (r < 0) + return log_oom(); + + r = ordered_hashmap_put(a->macsec->receive_channels, &new_channel->sci.as_uint64, new_channel); + if (r < 0) + return log_netdev_error_errno(netdev, r, + "%s: Failed to store receive channel at hashmap, " + "Ignoring [MACsecReceiveAssociation] section from line %u", + a->section->filename, a->section->line); + c = TAKE_PTR(new_channel); + } + if (c->n_rxsa >= MACSEC_MAX_ASSOCIATION_NUMBER) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(ERANGE), + "%s: Too many [MACsecReceiveAssociation] sections for the same receive channel, " + "Ignoring [MACsecReceiveAssociation] section from line %u", + a->section->filename, a->section->line); + + a->sa.association_number = c->n_rxsa; + c->rxsa[c->n_rxsa++] = a; + + return 0; +} + +static int netdev_macsec_verify(NetDev *netdev, const char *filename) { + MACsec *v = MACSEC(netdev); + TransmitAssociation *a; + ReceiveAssociation *n; + ReceiveChannel *c; + Iterator i; + uint8_t an, encoding_an; + bool use_for_encoding; + int r; + + assert(netdev); + assert(v); + assert(filename); + + ORDERED_HASHMAP_FOREACH(c, v->receive_channels_by_section, i) { + r = macsec_receive_channel_verify(c); + if (r < 0) + macsec_receive_channel_free(c); + } + + an = 0; + use_for_encoding = false; + encoding_an = 0; + ORDERED_HASHMAP_FOREACH(a, v->transmit_associations_by_section, i) { + r = macsec_transmit_association_verify(a); + if (r < 0) { + macsec_transmit_association_free(a); + continue; + } + + if (an >= MACSEC_MAX_ASSOCIATION_NUMBER) { + log_netdev_error(netdev, + "%s: Too many [MACsecTransmitAssociation] sections configured. " + "Ignoring [MACsecTransmitAssociation] section from line %u", + a->section->filename, a->section->line); + macsec_transmit_association_free(a); + continue; + } + + a->sa.association_number = an++; + + if (a->sa.use_for_encoding > 0) { + if (use_for_encoding) { + log_netdev_warning(netdev, + "%s: Multiple security associations are set to be used for transmit channel." + "Disabling UseForEncoding= in [MACsecTransmitAssociation] section from line %u", + a->section->filename, a->section->line); + a->sa.use_for_encoding = false; + } else { + encoding_an = a->sa.association_number; + use_for_encoding = true; + } + } + } + + assert(encoding_an < MACSEC_MAX_ASSOCIATION_NUMBER); + v->encoding_an = encoding_an; + + ORDERED_HASHMAP_FOREACH(n, v->receive_associations_by_section, i) { + r = macsec_receive_association_verify(n); + if (r < 0) + macsec_receive_association_free(n); + } + + return 0; +} + +static void macsec_init(NetDev *netdev) { + MACsec *v; + + assert(netdev); + + v = MACSEC(netdev); + + assert(v); + + v->encrypt = -1; +} + +static void macsec_done(NetDev *netdev) { + MACsec *t; + + assert(netdev); + + t = MACSEC(netdev); + + assert(t); + + ordered_hashmap_free_with_destructor(t->receive_channels, macsec_receive_channel_free); + ordered_hashmap_free_with_destructor(t->receive_channels_by_section, macsec_receive_channel_free); + ordered_hashmap_free_with_destructor(t->transmit_associations_by_section, macsec_transmit_association_free); + ordered_hashmap_free_with_destructor(t->receive_associations_by_section, macsec_receive_association_free); +} + +const NetDevVTable macsec_vtable = { + .object_size = sizeof(MACsec), + .init = macsec_init, + .sections = "Match\0NetDev\0MACsec\0MACsecReceiveChannel\0MACsecTransmitAssociation\0MACsecReceiveAssociation\0", + .fill_message_create = netdev_macsec_fill_message_create, + .post_create = netdev_macsec_configure, + .done = macsec_done, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_macsec_verify, + .generate_mac = true, +}; diff --git a/src/network/netdev/macsec.h b/src/network/netdev/macsec.h new file mode 100644 index 00000000..2a3443a6 --- /dev/null +++ b/src/network/netdev/macsec.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "in-addr-util.h" +#include "netdev.h" +#include "networkd-util.h" +#include "sparse-endian.h" + +/* See the definition of MACSEC_NUM_AN in kernel's drivers/net/macsec.c */ +#define MACSEC_MAX_ASSOCIATION_NUMBER 4 + +typedef struct MACsec MACsec; + +typedef union MACsecSCI { + uint64_t as_uint64; + + struct { + struct ether_addr mac; + be16_t port; + } _packed_; +} MACsecSCI; + +assert_cc(sizeof(MACsecSCI) == sizeof(uint64_t)); + +typedef struct SecurityAssociation { + uint8_t association_number; + uint32_t packet_number; + uint8_t key_id[MACSEC_KEYID_LEN]; + uint8_t *key; + uint32_t key_len; + char *key_file; + int activate; + int use_for_encoding; +} SecurityAssociation; + +typedef struct TransmitAssociation { + MACsec *macsec; + NetworkConfigSection *section; + + SecurityAssociation sa; +} TransmitAssociation; + +typedef struct ReceiveAssociation { + MACsec *macsec; + NetworkConfigSection *section; + + MACsecSCI sci; + SecurityAssociation sa; +} ReceiveAssociation; + +typedef struct ReceiveChannel { + MACsec *macsec; + NetworkConfigSection *section; + + MACsecSCI sci; + ReceiveAssociation *rxsa[MACSEC_MAX_ASSOCIATION_NUMBER]; + unsigned n_rxsa; +} ReceiveChannel; + +struct MACsec { + NetDev meta; + + uint16_t port; + int encrypt; + uint8_t encoding_an; + + OrderedHashmap *receive_channels; + OrderedHashmap *receive_channels_by_section; + OrderedHashmap *transmit_associations_by_section; + OrderedHashmap *receive_associations_by_section; +}; + +DEFINE_NETDEV_CAST(MACSEC, MACsec); +extern const NetDevVTable macsec_vtable; + +CONFIG_PARSER_PROTOTYPE(config_parse_macsec_port); +CONFIG_PARSER_PROTOTYPE(config_parse_macsec_hw_address); +CONFIG_PARSER_PROTOTYPE(config_parse_macsec_packet_number); +CONFIG_PARSER_PROTOTYPE(config_parse_macsec_key_id); +CONFIG_PARSER_PROTOTYPE(config_parse_macsec_key); +CONFIG_PARSER_PROTOTYPE(config_parse_macsec_key_file); +CONFIG_PARSER_PROTOTYPE(config_parse_macsec_sa_activate); +CONFIG_PARSER_PROTOTYPE(config_parse_macsec_use_for_encoding); diff --git a/src/network/netdev/macvlan.c b/src/network/netdev/macvlan.c new file mode 100644 index 00000000..fe596c29 --- /dev/null +++ b/src/network/netdev/macvlan.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "conf-parser.h" +#include "macvlan.h" +#include "string-table.h" + +static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = { + [NETDEV_MACVLAN_MODE_PRIVATE] = "private", + [NETDEV_MACVLAN_MODE_VEPA] = "vepa", + [NETDEV_MACVLAN_MODE_BRIDGE] = "bridge", + [NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru", +}; + +DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode); +DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode"); + +static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { + MacVlan *m; + int r; + + assert(netdev); + assert(link); + assert(netdev->ifname); + + if (netdev->kind == NETDEV_KIND_MACVLAN) + m = MACVLAN(netdev); + else + m = MACVTAP(netdev); + + assert(m); + + if (m->mode != _NETDEV_MACVLAN_MODE_INVALID) { + r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MODE, m->mode); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACVLAN_MODE attribute: %m"); + } + + return 0; +} + +static void macvlan_init(NetDev *n) { + MacVlan *m; + + assert(n); + + if (n->kind == NETDEV_KIND_MACVLAN) + m = MACVLAN(n); + else + m = MACVTAP(n); + + assert(m); + + m->mode = _NETDEV_MACVLAN_MODE_INVALID; +} + +const NetDevVTable macvtap_vtable = { + .object_size = sizeof(MacVlan), + .init = macvlan_init, + .sections = "Match\0NetDev\0MACVTAP\0", + .fill_message_create = netdev_macvlan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .generate_mac = true, +}; + +const NetDevVTable macvlan_vtable = { + .object_size = sizeof(MacVlan), + .init = macvlan_init, + .sections = "Match\0NetDev\0MACVLAN\0", + .fill_message_create = netdev_macvlan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .generate_mac = true, +}; diff --git a/src/network/netdev/macvlan.h b/src/network/netdev/macvlan.h new file mode 100644 index 00000000..5d81be32 --- /dev/null +++ b/src/network/netdev/macvlan.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct MacVlan MacVlan; + +#include "netdev.h" + +typedef enum MacVlanMode { + NETDEV_MACVLAN_MODE_PRIVATE = MACVLAN_MODE_PRIVATE, + NETDEV_MACVLAN_MODE_VEPA = MACVLAN_MODE_VEPA, + NETDEV_MACVLAN_MODE_BRIDGE = MACVLAN_MODE_BRIDGE, + NETDEV_MACVLAN_MODE_PASSTHRU = MACVLAN_MODE_PASSTHRU, + _NETDEV_MACVLAN_MODE_MAX, + _NETDEV_MACVLAN_MODE_INVALID = -1 +} MacVlanMode; + +struct MacVlan { + NetDev meta; + + MacVlanMode mode; +}; + +DEFINE_NETDEV_CAST(MACVLAN, MacVlan); +DEFINE_NETDEV_CAST(MACVTAP, MacVlan); +extern const NetDevVTable macvlan_vtable; +extern const NetDevVTable macvtap_vtable; + +const char *macvlan_mode_to_string(MacVlanMode d) _const_; +MacVlanMode macvlan_mode_from_string(const char *d) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_macvlan_mode); diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf new file mode 100644 index 00000000..09a5f482 --- /dev/null +++ b/src/network/netdev/netdev-gperf.gperf @@ -0,0 +1,225 @@ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif +#include +#include "bond.h" +#include "bridge.h" +#include "conf-parser.h" +#include "geneve.h" +#include "ipvlan.h" +#include "macsec.h" +#include "macvlan.h" +#include "tunnel.h" +#include "tuntap.h" +#include "veth.h" +#include "vlan-util.h" +#include "vlan.h" +#include "vxlan.h" +#include "vrf.h" +#include "netdev.h" +#include "network-internal.h" +#include "vxcan.h" +#include "wireguard.h" +#include "fou-tunnel.h" +#include "l2tp-tunnel.h" +#include "xfrm.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name network_netdev_gperf_hash +%define lookup-function-name network_netdev_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(NetDev, conditions) +Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(NetDev, conditions) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, conditions) +Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(NetDev, conditions) +Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(NetDev, conditions) +NetDev.Description, config_parse_string, 0, offsetof(NetDev, description) +NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname) +NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind) +NetDev.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(NetDev, mtu) +NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac) +VLAN.Id, config_parse_vlanid, 0, offsetof(VLan, id) +VLAN.GVRP, config_parse_tristate, 0, offsetof(VLan, gvrp) +VLAN.MVRP, config_parse_tristate, 0, offsetof(VLan, mvrp) +VLAN.LooseBinding, config_parse_tristate, 0, offsetof(VLan, loose_binding) +VLAN.ReorderHeader, config_parse_tristate, 0, offsetof(VLan, reorder_hdr) +MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) +MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) +IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode) +IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags) +IPVTAP.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode) +IPVTAP.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags) +Tunnel.Local, config_parse_tunnel_address, 0, offsetof(Tunnel, local) +Tunnel.Remote, config_parse_tunnel_address, 0, offsetof(Tunnel, remote) +Tunnel.TOS, config_parse_unsigned, 0, offsetof(Tunnel, tos) +Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl) +Tunnel.Key, config_parse_tunnel_key, 0, offsetof(Tunnel, key) +Tunnel.InputKey, config_parse_tunnel_key, 0, offsetof(Tunnel, ikey) +Tunnel.OutputKey, config_parse_tunnel_key, 0, offsetof(Tunnel, okey) +Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc) +Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode) +Tunnel.IPv6FlowLabel, config_parse_ipv6_flowlabel, 0, offsetof(Tunnel, ipv6_flowlabel) +Tunnel.CopyDSCP, config_parse_bool, 0, offsetof(Tunnel, copy_dscp) +Tunnel.EncapsulationLimit, config_parse_encap_limit, 0, offsetof(Tunnel, encap_limit) +Tunnel.Independent, config_parse_bool, 0, offsetof(Tunnel, independent) +Tunnel.AssignToLoopback, config_parse_bool, 0, offsetof(Tunnel, assign_to_loopback) +Tunnel.AllowLocalRemote, config_parse_tristate, 0, offsetof(Tunnel, allow_localremote) +Tunnel.FooOverUDP, config_parse_bool, 0, offsetof(Tunnel, fou_tunnel) +Tunnel.FOUDestinationPort, config_parse_ip_port, 0, offsetof(Tunnel, fou_destination_port) +Tunnel.FOUSourcePort, config_parse_ip_port, 0, offsetof(Tunnel, encap_src_port) +Tunnel.Encapsulation, config_parse_fou_encap_type, 0, offsetof(Tunnel, fou_encap_type) +Tunnel.IPv6RapidDeploymentPrefix, config_parse_6rd_prefix, 0, 0 +Tunnel.ERSPANIndex, config_parse_uint32, 0, offsetof(Tunnel, erspan_index) +Tunnel.SerializeTunneledPackets, config_parse_tristate, 0, offsetof(Tunnel, gre_erspan_sequence) +Tunnel.ISATAP, config_parse_tristate, 0, offsetof(Tunnel, isatap) +FooOverUDP.Protocol, config_parse_ip_protocol, 0, offsetof(FouTunnel, fou_protocol) +FooOverUDP.Encapsulation, config_parse_fou_encap_type, 0, offsetof(FouTunnel, fou_encap_type) +FooOverUDP.Port, config_parse_ip_port, 0, offsetof(FouTunnel, port) +FooOverUDP.PeerPort, config_parse_ip_port, 0, offsetof(FouTunnel, peer_port) +FooOverUDP.Local, config_parse_fou_tunnel_address, 0, offsetof(FouTunnel, local) +FooOverUDP.Peer, config_parse_fou_tunnel_address, 0, offsetof(FouTunnel, peer) +L2TP.TunnelId, config_parse_l2tp_tunnel_id, 0, offsetof(L2tpTunnel, tunnel_id) +L2TP.PeerTunnelId, config_parse_l2tp_tunnel_id, 0, offsetof(L2tpTunnel, peer_tunnel_id) +L2TP.UDPSourcePort, config_parse_ip_port, 0, offsetof(L2tpTunnel, l2tp_udp_sport) +L2TP.UDPDestinationPort, config_parse_ip_port, 0, offsetof(L2tpTunnel, l2tp_udp_dport) +L2TP.Local, config_parse_l2tp_tunnel_address, 0, offsetof(L2tpTunnel, local) +L2TP.Remote, config_parse_l2tp_tunnel_address, 0, offsetof(L2tpTunnel, remote) +L2TP.EncapsulationType, config_parse_l2tp_encap_type, 0, offsetof(L2tpTunnel, l2tp_encap_type) +L2TP.UDPCheckSum, config_parse_bool, 0, offsetof(L2tpTunnel, udp_csum) +L2TP.UDP6CheckSumRx, config_parse_bool, 0, offsetof(L2tpTunnel, udp6_csum_rx) +L2TP.UDP6CheckSumTx, config_parse_bool, 0, offsetof(L2tpTunnel, udp6_csum_tx) +L2TPSession.SessionId, config_parse_l2tp_session_id, 0, 0 +L2TPSession.PeerSessionId, config_parse_l2tp_session_id, 0, 0 +L2TPSession.Layer2SpecificHeader, config_parse_l2tp_session_l2spec, 0, 0 +L2TPSession.Name, config_parse_l2tp_session_name, 0, 0 +Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer) +Peer.MACAddress, config_parse_hwaddr, 0, offsetof(Veth, mac_peer) +VXCAN.Peer, config_parse_ifname, 0, offsetof(VxCan, ifname_peer) +VXLAN.VNI, config_parse_uint32, 0, offsetof(VxLan, vni) +VXLAN.Id, config_parse_uint32, 0, offsetof(VxLan, vni) /* deprecated */ +VXLAN.Group, config_parse_vxlan_address, 0, offsetof(VxLan, group) +VXLAN.Local, config_parse_vxlan_address, 0, offsetof(VxLan, local) +VXLAN.Remote, config_parse_vxlan_address, 0, offsetof(VxLan, remote) +VXLAN.TOS, config_parse_unsigned, 0, offsetof(VxLan, tos) +VXLAN.TTL, config_parse_vxlan_ttl, 0, offsetof(VxLan, ttl) +VXLAN.MacLearning, config_parse_bool, 0, offsetof(VxLan, learning) +VXLAN.ARPProxy, config_parse_bool, 0, offsetof(VxLan, arp_proxy) +VXLAN.ReduceARPProxy, config_parse_bool, 0, offsetof(VxLan, arp_proxy) +VXLAN.L2MissNotification, config_parse_bool, 0, offsetof(VxLan, l2miss) +VXLAN.L3MissNotification, config_parse_bool, 0, offsetof(VxLan, l3miss) +VXLAN.RouteShortCircuit, config_parse_bool, 0, offsetof(VxLan, route_short_circuit) +VXLAN.UDPCheckSum, config_parse_bool, 0, offsetof(VxLan, udpcsum) +VXLAN.UDPChecksum, config_parse_bool, 0, offsetof(VxLan, udpcsum) +VXLAN.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx) +VXLAN.UDP6ZeroChecksumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx) +VXLAN.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx) +VXLAN.UDP6ZeroChecksumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx) +VXLAN.RemoteChecksumTx, config_parse_bool, 0, offsetof(VxLan, remote_csum_tx) +VXLAN.RemoteChecksumRx, config_parse_bool, 0, offsetof(VxLan, remote_csum_rx) +VXLAN.FDBAgeingSec, config_parse_sec, 0, offsetof(VxLan, fdb_ageing) +VXLAN.GroupPolicyExtension, config_parse_bool, 0, offsetof(VxLan, group_policy) +VXLAN.GenericProtocolExtension, config_parse_bool, 0, offsetof(VxLan, generic_protocol_extension) +VXLAN.MaximumFDBEntries, config_parse_unsigned, 0, offsetof(VxLan, max_fdb) +VXLAN.PortRange, config_parse_port_range, 0, 0 +VXLAN.DestinationPort, config_parse_ip_port, 0, offsetof(VxLan, dest_port) +VXLAN.FlowLabel, config_parse_flow_label, 0, 0 +VXLAN.IPDoNotFragment, config_parse_df, 0, offsetof(VxLan, df) +GENEVE.Id, config_parse_geneve_vni, 0, offsetof(Geneve, id) +GENEVE.Remote, config_parse_geneve_address, 0, offsetof(Geneve, remote) +GENEVE.TOS, config_parse_uint8, 0, offsetof(Geneve, tos) +GENEVE.TTL, config_parse_geneve_ttl, 0, offsetof(Geneve, ttl) +GENEVE.UDPChecksum, config_parse_bool, 0, offsetof(Geneve, udpcsum) +GENEVE.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumrx) +GENEVE.UDP6ZeroChecksumRx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumrx) +GENEVE.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumtx) +GENEVE.UDP6ZeroChecksumTx, config_parse_bool, 0, offsetof(Geneve, udp6zerocsumtx) +GENEVE.DestinationPort, config_parse_ip_port, 0, offsetof(Geneve, dest_port) +GENEVE.IPDoNotFragment, config_parse_geneve_df, 0, offsetof(Geneve, geneve_df) +GENEVE.FlowLabel, config_parse_geneve_flow_label, 0, 0 +MACsec.Port, config_parse_macsec_port, 0, 0 +MACsec.Encrypt, config_parse_tristate, 0, offsetof(MACsec, encrypt) +MACsecReceiveChannel.Port, config_parse_macsec_port, 0, 0 +MACsecReceiveChannel.MACAddress, config_parse_macsec_hw_address, 0, 0 +MACsecTransmitAssociation.PacketNumber, config_parse_macsec_packet_number, 0, 0 +MACsecTransmitAssociation.KeyId, config_parse_macsec_key_id, 0, 0 +MACsecTransmitAssociation.Key, config_parse_macsec_key, 0, 0 +MACsecTransmitAssociation.KeyFile, config_parse_macsec_key_file, 0, 0 +MACsecTransmitAssociation.Activate, config_parse_macsec_sa_activate, 0, 0 +MACsecTransmitAssociation.UseForEncoding, config_parse_macsec_use_for_encoding, 0, 0 +MACsecReceiveAssociation.Port, config_parse_macsec_port, 0, 0 +MACsecReceiveAssociation.MACAddress, config_parse_macsec_hw_address, 0, 0 +MACsecReceiveAssociation.PacketNumber, config_parse_macsec_packet_number, 0, 0 +MACsecReceiveAssociation.KeyId, config_parse_macsec_key_id, 0, 0 +MACsecReceiveAssociation.Key, config_parse_macsec_key, 0, 0 +MACsecReceiveAssociation.KeyFile, config_parse_macsec_key_file, 0, 0 +MACsecReceiveAssociation.Activate, config_parse_macsec_sa_activate, 0, 0 +Tun.OneQueue, config_parse_warn_compat, DISABLED_LEGACY, 0 +Tun.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) +Tun.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) +Tun.VNetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr) +Tun.User, config_parse_string, 0, offsetof(TunTap, user_name) +Tun.Group, config_parse_string, 0, offsetof(TunTap, group_name) +Tap.OneQueue, config_parse_warn_compat, DISABLED_LEGACY, 0 +Tap.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) +Tap.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) +Tap.VNetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr) +Tap.User, config_parse_string, 0, offsetof(TunTap, user_name) +Tap.Group, config_parse_string, 0, offsetof(TunTap, group_name) +Bond.Mode, config_parse_bond_mode, 0, offsetof(Bond, mode) +Bond.TransmitHashPolicy, config_parse_bond_xmit_hash_policy, 0, offsetof(Bond, xmit_hash_policy) +Bond.LACPTransmitRate, config_parse_bond_lacp_rate, 0, offsetof(Bond, lacp_rate) +Bond.AdSelect, config_parse_bond_ad_select, 0, offsetof(Bond, ad_select) +Bond.FailOverMACPolicy, config_parse_bond_fail_over_mac, 0, offsetof(Bond, fail_over_mac) +Bond.ARPIPTargets, config_parse_arp_ip_target_address, 0, 0 +Bond.ARPValidate, config_parse_bond_arp_validate, 0, offsetof(Bond, arp_validate) +Bond.ARPAllTargets, config_parse_bond_arp_all_targets, 0, offsetof(Bond, arp_all_targets) +Bond.PrimaryReselectPolicy, config_parse_bond_primary_reselect, 0, offsetof(Bond, primary_reselect) +Bond.ResendIGMP, config_parse_unsigned, 0, offsetof(Bond, resend_igmp) +Bond.PacketsPerSlave, config_parse_unsigned, 0, offsetof(Bond, packets_per_slave) +Bond.GratuitousARP, config_parse_unsigned, 0, offsetof(Bond, num_grat_arp) +Bond.AllSlavesActive, config_parse_bool, 0, offsetof(Bond, all_slaves_active) +Bond.DynamicTransmitLoadBalancing, config_parse_tristate, 0, offsetof(Bond, tlb_dynamic_lb) +Bond.MinLinks, config_parse_unsigned, 0, offsetof(Bond, min_links) +Bond.MIIMonitorSec, config_parse_sec, 0, offsetof(Bond, miimon) +Bond.UpDelaySec, config_parse_sec, 0, offsetof(Bond, updelay) +Bond.DownDelaySec, config_parse_sec, 0, offsetof(Bond, downdelay) +Bond.ARPIntervalSec, config_parse_sec, 0, offsetof(Bond, arp_interval) +Bond.LearnPacketIntervalSec, config_parse_sec, 0, offsetof(Bond, lp_interval) +Bond.AdActorSystemPriority, config_parse_ad_actor_sys_prio, 0, offsetof(Bond, ad_actor_sys_prio) +Bond.AdUserPortKey, config_parse_ad_user_port_key, 0, offsetof(Bond, ad_user_port_key) +Bond.AdActorSystem, config_parse_ad_actor_system, 0, offsetof(Bond, ad_actor_system) +Bridge.HelloTimeSec, config_parse_sec, 0, offsetof(Bridge, hello_time) +Bridge.MaxAgeSec, config_parse_sec, 0, offsetof(Bridge, max_age) +Bridge.AgeingTimeSec, config_parse_sec, 0, offsetof(Bridge, ageing_time) +Bridge.ForwardDelaySec, config_parse_sec, 0, offsetof(Bridge, forward_delay) +Bridge.Priority, config_parse_uint16, 0, offsetof(Bridge, priority) +Bridge.GroupForwardMask, config_parse_uint16, 0, offsetof(Bridge, group_fwd_mask) +Bridge.DefaultPVID, config_parse_default_port_vlanid, 0, offsetof(Bridge, default_pvid) +Bridge.MulticastQuerier, config_parse_tristate, 0, offsetof(Bridge, mcast_querier) +Bridge.MulticastSnooping, config_parse_tristate, 0, offsetof(Bridge, mcast_snooping) +Bridge.VLANFiltering, config_parse_tristate, 0, offsetof(Bridge, vlan_filtering) +Bridge.STP, config_parse_tristate, 0, offsetof(Bridge, stp) +Bridge.MulticastIGMPVersion, config_parse_uint8, 0, offsetof(Bridge, igmp_version) +VRF.TableId, config_parse_uint32, 0, offsetof(Vrf, table) /* deprecated */ +VRF.Table, config_parse_uint32, 0, offsetof(Vrf, table) +WireGuard.FirewallMark, config_parse_unsigned, 0, offsetof(Wireguard, fwmark) +WireGuard.FwMark, config_parse_unsigned, 0, offsetof(Wireguard, fwmark) /* deprecated */ +WireGuard.ListenPort, config_parse_wireguard_listen_port, 0, offsetof(Wireguard, port) +WireGuard.PrivateKey, config_parse_wireguard_private_key, 0, 0 +WireGuard.PrivateKeyFile, config_parse_wireguard_private_key_file, 0, 0 +WireGuardPeer.AllowedIPs, config_parse_wireguard_allowed_ips, 0, 0 +WireGuardPeer.Endpoint, config_parse_wireguard_endpoint, 0, 0 +WireGuardPeer.PublicKey, config_parse_wireguard_public_key, 0, 0 +WireGuardPeer.PresharedKey, config_parse_wireguard_preshared_key, 0, 0 +WireGuardPeer.PresharedKeyFile, config_parse_wireguard_preshared_key_file, 0, 0 +WireGuardPeer.PersistentKeepalive, config_parse_wireguard_keepalive, 0, 0 +Xfrm.InterfaceId, config_parse_uint32, 0, offsetof(Xfrm, if_id) +Xfrm.Independent, config_parse_bool, 0, offsetof(Xfrm, independent) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c new file mode 100644 index 00000000..6908c4e8 --- /dev/null +++ b/src/network/netdev/netdev.c @@ -0,0 +1,852 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "bond.h" +#include "bridge.h" +#include "conf-files.h" +#include "conf-parser.h" +#include "dummy.h" +#include "fd-util.h" +#include "fou-tunnel.h" +#include "geneve.h" +#include "ipvlan.h" +#include "l2tp-tunnel.h" +#include "list.h" +#include "macsec.h" +#include "macvlan.h" +#include "netdev.h" +#include "netdevsim.h" +#include "netlink-util.h" +#include "network-internal.h" +#include "networkd-manager.h" +#include "nlmon.h" +#include "siphash24.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "tunnel.h" +#include "tuntap.h" +#include "vcan.h" +#include "veth.h" +#include "vlan.h" +#include "vrf.h" +#include "vxcan.h" +#include "vxlan.h" +#include "wireguard.h" +#include "xfrm.h" + +const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { + [NETDEV_KIND_BRIDGE] = &bridge_vtable, + [NETDEV_KIND_BOND] = &bond_vtable, + [NETDEV_KIND_VLAN] = &vlan_vtable, + [NETDEV_KIND_MACVLAN] = &macvlan_vtable, + [NETDEV_KIND_MACVTAP] = &macvtap_vtable, + [NETDEV_KIND_IPVLAN] = &ipvlan_vtable, + [NETDEV_KIND_IPVTAP] = &ipvtap_vtable, + [NETDEV_KIND_VXLAN] = &vxlan_vtable, + [NETDEV_KIND_IPIP] = &ipip_vtable, + [NETDEV_KIND_GRE] = &gre_vtable, + [NETDEV_KIND_GRETAP] = &gretap_vtable, + [NETDEV_KIND_IP6GRE] = &ip6gre_vtable, + [NETDEV_KIND_IP6GRETAP] = &ip6gretap_vtable, + [NETDEV_KIND_SIT] = &sit_vtable, + [NETDEV_KIND_VTI] = &vti_vtable, + [NETDEV_KIND_VTI6] = &vti6_vtable, + [NETDEV_KIND_VETH] = &veth_vtable, + [NETDEV_KIND_DUMMY] = &dummy_vtable, + [NETDEV_KIND_TUN] = &tun_vtable, + [NETDEV_KIND_TAP] = &tap_vtable, + [NETDEV_KIND_IP6TNL] = &ip6tnl_vtable, + [NETDEV_KIND_VRF] = &vrf_vtable, + [NETDEV_KIND_VCAN] = &vcan_vtable, + [NETDEV_KIND_GENEVE] = &geneve_vtable, + [NETDEV_KIND_VXCAN] = &vxcan_vtable, + [NETDEV_KIND_WIREGUARD] = &wireguard_vtable, + [NETDEV_KIND_NETDEVSIM] = &netdevsim_vtable, + [NETDEV_KIND_FOU] = &foutnl_vtable, + [NETDEV_KIND_ERSPAN] = &erspan_vtable, + [NETDEV_KIND_L2TP] = &l2tptnl_vtable, + [NETDEV_KIND_MACSEC] = &macsec_vtable, + [NETDEV_KIND_NLMON] = &nlmon_vtable, + [NETDEV_KIND_XFRM] = &xfrm_vtable, +}; + +static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { + [NETDEV_KIND_BRIDGE] = "bridge", + [NETDEV_KIND_BOND] = "bond", + [NETDEV_KIND_VLAN] = "vlan", + [NETDEV_KIND_MACVLAN] = "macvlan", + [NETDEV_KIND_MACVTAP] = "macvtap", + [NETDEV_KIND_IPVLAN] = "ipvlan", + [NETDEV_KIND_IPVTAP] = "ipvtap", + [NETDEV_KIND_VXLAN] = "vxlan", + [NETDEV_KIND_IPIP] = "ipip", + [NETDEV_KIND_GRE] = "gre", + [NETDEV_KIND_GRETAP] = "gretap", + [NETDEV_KIND_IP6GRE] = "ip6gre", + [NETDEV_KIND_IP6GRETAP] = "ip6gretap", + [NETDEV_KIND_SIT] = "sit", + [NETDEV_KIND_VETH] = "veth", + [NETDEV_KIND_VTI] = "vti", + [NETDEV_KIND_VTI6] = "vti6", + [NETDEV_KIND_DUMMY] = "dummy", + [NETDEV_KIND_TUN] = "tun", + [NETDEV_KIND_TAP] = "tap", + [NETDEV_KIND_IP6TNL] = "ip6tnl", + [NETDEV_KIND_VRF] = "vrf", + [NETDEV_KIND_VCAN] = "vcan", + [NETDEV_KIND_GENEVE] = "geneve", + [NETDEV_KIND_VXCAN] = "vxcan", + [NETDEV_KIND_WIREGUARD] = "wireguard", + [NETDEV_KIND_NETDEVSIM] = "netdevsim", + [NETDEV_KIND_FOU] = "fou", + [NETDEV_KIND_ERSPAN] = "erspan", + [NETDEV_KIND_L2TP] = "l2tp", + [NETDEV_KIND_MACSEC] = "macsec", + [NETDEV_KIND_NLMON] = "nlmon", + [NETDEV_KIND_XFRM] = "xfrm", +}; + +DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind); + +int config_parse_netdev_kind( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + NetDevKind k, *kind = data; + + assert(rvalue); + assert(data); + + k = netdev_kind_from_string(rvalue); + if (k < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse netdev kind, ignoring assignment: %s", rvalue); + return 0; + } + + if (*kind != _NETDEV_KIND_INVALID && *kind != k) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Specified netdev kind is different from the previous value '%s', ignoring assignment: %s", + netdev_kind_to_string(*kind), rvalue); + return 0; + } + + *kind = k; + + return 0; +} + +static void netdev_callbacks_clear(NetDev *netdev) { + netdev_join_callback *callback; + + if (!netdev) + return; + + while ((callback = netdev->callbacks)) { + LIST_REMOVE(callbacks, netdev->callbacks, callback); + link_unref(callback->link); + free(callback); + } +} + +bool netdev_is_managed(NetDev *netdev) { + if (!netdev || !netdev->manager || !netdev->ifname) + return false; + + return hashmap_get(netdev->manager->netdevs, netdev->ifname) == netdev; +} + +static void netdev_detach_from_manager(NetDev *netdev) { + if (netdev->ifname && netdev->manager) + hashmap_remove(netdev->manager->netdevs, netdev->ifname); +} + +static NetDev *netdev_free(NetDev *netdev) { + assert(netdev); + + netdev_callbacks_clear(netdev); + + netdev_detach_from_manager(netdev); + + free(netdev->filename); + + free(netdev->description); + free(netdev->ifname); + free(netdev->mac); + condition_free_list(netdev->conditions); + + /* Invoke the per-kind done() destructor, but only if the state field is initialized. We conditionalize that + * because we parse .netdev files twice: once to determine the kind (with a short, minimal NetDev structure + * allocation, with no room for per-kind fields), and once to read the kind's properties (with a full, + * comprehensive NetDev structure allocation with enough space for whatever the specific kind needs). Now, in + * the first case we shouldn't try to destruct the per-kind NetDev fields on destruction, in the second case we + * should. We use the state field to discern the two cases: it's _NETDEV_STATE_INVALID on the first "raw" + * call. */ + if (netdev->state != _NETDEV_STATE_INVALID && + NETDEV_VTABLE(netdev) && + NETDEV_VTABLE(netdev)->done) + NETDEV_VTABLE(netdev)->done(netdev); + + return mfree(netdev); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(NetDev, netdev, netdev_free); + +void netdev_drop(NetDev *netdev) { + if (!netdev || netdev->state == NETDEV_STATE_LINGER) + return; + + netdev->state = NETDEV_STATE_LINGER; + + log_netdev_debug(netdev, "netdev removed"); + + netdev_callbacks_clear(netdev); + + netdev_detach_from_manager(netdev); + + netdev_unref(netdev); + + return; +} + +int netdev_get(Manager *manager, const char *name, NetDev **ret) { + NetDev *netdev; + + assert(manager); + assert(name); + assert(ret); + + netdev = hashmap_get(manager->netdevs, name); + if (!netdev) { + *ret = NULL; + return -ENOENT; + } + + *ret = netdev; + + return 0; +} + +static int netdev_enter_failed(NetDev *netdev) { + netdev->state = NETDEV_STATE_FAILED; + + netdev_callbacks_clear(netdev); + + return 0; +} + +static int netdev_enslave_ready(NetDev *netdev, Link* link, link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(netdev); + assert(netdev->state == NETDEV_STATE_READY); + assert(netdev->manager); + assert(netdev->manager->rtnl); + assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF)); + assert(link); + assert(callback); + + if (link->flags & IFF_UP && netdev->kind == NETDEV_KIND_BOND) { + log_netdev_debug(netdev, "Link '%s' was up when attempting to enslave it. Bringing link down.", link->ifname); + r = link_down(link, NULL); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not bring link down: %m"); + } + + r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_netlink_message_append_u32(req, IFLA_MASTER, netdev->ifindex); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_MASTER attribute: %m"); + + r = netlink_call_async(netdev->manager->rtnl, NULL, req, callback, + link_netlink_destroy_callback, link); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + log_netdev_debug(netdev, "Enslaving link '%s'", link->ifname); + + return 0; +} + +static int netdev_enter_ready(NetDev *netdev) { + netdev_join_callback *callback, *callback_next; + int r; + + assert(netdev); + assert(netdev->ifname); + + if (netdev->state != NETDEV_STATE_CREATING) + return 0; + + netdev->state = NETDEV_STATE_READY; + + log_netdev_info(netdev, "netdev ready"); + + LIST_FOREACH_SAFE(callbacks, callback, callback_next, netdev->callbacks) { + /* enslave the links that were attempted to be enslaved before the + * link was ready */ + r = netdev_enslave_ready(netdev, callback->link, callback->callback); + if (r < 0) + return r; + + LIST_REMOVE(callbacks, netdev->callbacks, callback); + link_unref(callback->link); + free(callback); + } + + if (NETDEV_VTABLE(netdev)->post_create) + NETDEV_VTABLE(netdev)->post_create(netdev, NULL, NULL); + + return 0; +} + +/* callback for netdev's created without a backing Link */ +static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) { + int r; + + assert(netdev); + assert(netdev->state != _NETDEV_STATE_INVALID); + + r = sd_netlink_message_get_errno(m); + if (r == -EEXIST) + log_netdev_info(netdev, "netdev exists, using existing without changing its parameters"); + else if (r < 0) { + log_netdev_warning_errno(netdev, r, "netdev could not be created: %m"); + netdev_drop(netdev); + + return 1; + } + + log_netdev_debug(netdev, "Created"); + + return 1; +} + +static int netdev_enslave(NetDev *netdev, Link *link, link_netlink_message_handler_t callback) { + int r; + + assert(netdev); + assert(netdev->manager); + assert(netdev->manager->rtnl); + assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF)); + + if (netdev->state == NETDEV_STATE_READY) { + r = netdev_enslave_ready(netdev, link, callback); + if (r < 0) + return r; + } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + + r = rtnl_message_new_synthetic_error(netdev->manager->rtnl, -ENODEV, 0, &m); + if (r >= 0) + callback(netdev->manager->rtnl, m, link); + } else { + /* the netdev is not yet read, save this request for when it is */ + netdev_join_callback *cb; + + cb = new(netdev_join_callback, 1); + if (!cb) + return log_oom(); + + *cb = (netdev_join_callback) { + .callback = callback, + .link = link_ref(link), + }; + + LIST_PREPEND(callbacks, netdev->callbacks, cb); + + log_netdev_debug(netdev, "Will enslave '%s', when ready", link->ifname); + } + + return 0; +} + +int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { + uint16_t type; + const char *kind; + const char *received_kind; + const char *received_name; + int r, ifindex; + + assert(netdev); + assert(message); + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not get rtnl message type: %m"); + + if (type != RTM_NEWLINK) { + log_netdev_error(netdev, "Cannot set ifindex from unexpected rtnl message type."); + return -EINVAL; + } + + r = sd_rtnl_message_link_get_ifindex(message, &ifindex); + if (r < 0) { + log_netdev_error_errno(netdev, r, "Could not get ifindex: %m"); + netdev_enter_failed(netdev); + return r; + } else if (ifindex <= 0) { + log_netdev_error(netdev, "Got invalid ifindex: %d", ifindex); + netdev_enter_failed(netdev); + return -EINVAL; + } + + if (netdev->ifindex > 0) { + if (netdev->ifindex != ifindex) { + log_netdev_error(netdev, "Could not set ifindex to %d, already set to %d", + ifindex, netdev->ifindex); + netdev_enter_failed(netdev); + return -EEXIST; + } else + /* ifindex already set to the same for this netdev */ + return 0; + } + + r = sd_netlink_message_read_string(message, IFLA_IFNAME, &received_name); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not get IFNAME: %m"); + + if (!streq(netdev->ifname, received_name)) { + log_netdev_error(netdev, "Received newlink with wrong IFNAME %s", received_name); + netdev_enter_failed(netdev); + return r; + } + + r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not get LINKINFO: %m"); + + r = sd_netlink_message_read_string(message, IFLA_INFO_KIND, &received_kind); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not get KIND: %m"); + + r = sd_netlink_message_exit_container(message); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not exit container: %m"); + + if (netdev->kind == NETDEV_KIND_TAP) + /* the kernel does not distinguish between tun and tap */ + kind = "tun"; + else { + kind = netdev_kind_to_string(netdev->kind); + if (!kind) { + log_netdev_error(netdev, "Could not get kind"); + netdev_enter_failed(netdev); + return -EINVAL; + } + } + + if (!streq(kind, received_kind)) { + log_netdev_error(netdev, + "Received newlink with wrong KIND %s, " + "expected %s", received_kind, kind); + netdev_enter_failed(netdev); + return r; + } + + netdev->ifindex = ifindex; + + log_netdev_debug(netdev, "netdev has index %d", netdev->ifindex); + + netdev_enter_ready(netdev); + + return 0; +} + +#define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48) + +int netdev_get_mac(const char *ifname, struct ether_addr **ret) { + _cleanup_free_ struct ether_addr *mac = NULL; + uint64_t result; + size_t l, sz; + uint8_t *v; + int r; + + assert(ifname); + assert(ret); + + mac = new0(struct ether_addr, 1); + if (!mac) + return -ENOMEM; + + l = strlen(ifname); + sz = sizeof(sd_id128_t) + l; + v = newa(uint8_t, sz); + + /* fetch some persistent data unique to the machine */ + r = sd_id128_get_machine((sd_id128_t*) v); + if (r < 0) + return r; + + /* combine with some data unique (on this machine) to this + * netdev */ + memcpy(v + sizeof(sd_id128_t), ifname, l); + + /* Let's hash the host machine ID plus the container name. We + * use a fixed, but originally randomly created hash key here. */ + result = siphash24(v, sz, HASH_KEY.bytes); + + assert_cc(ETH_ALEN <= sizeof(result)); + memcpy(mac->ether_addr_octet, &result, ETH_ALEN); + + /* see eth_random_addr in the kernel */ + mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */ + mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */ + + *ret = TAKE_PTR(mac); + + return 0; +} + +static int netdev_create(NetDev *netdev, Link *link, link_netlink_message_handler_t callback) { + int r; + + assert(netdev); + assert(!link || callback); + + /* create netdev */ + if (NETDEV_VTABLE(netdev)->create) { + assert(!link); + + r = NETDEV_VTABLE(netdev)->create(netdev); + if (r < 0) + return r; + + log_netdev_debug(netdev, "Created"); + } else { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + + r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m"); + + r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m"); + + if (netdev->mac) { + r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m"); + } + + if (netdev->mtu) { + r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m"); + } + + if (link) { + r = sd_netlink_message_append_u32(m, IFLA_LINK, link->ifindex); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINK attribute: %m"); + } + + r = sd_netlink_message_open_container(m, IFLA_LINKINFO); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); + + r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); + + if (NETDEV_VTABLE(netdev)->fill_message_create) { + r = NETDEV_VTABLE(netdev)->fill_message_create(netdev, link, m); + if (r < 0) + return r; + } + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); + + if (link) { + r = netlink_call_async(netdev->manager->rtnl, NULL, m, callback, + link_netlink_destroy_callback, link); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + } else { + r = netlink_call_async(netdev->manager->rtnl, NULL, m, netdev_create_handler, + netdev_destroy_callback, netdev); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); + + netdev_ref(netdev); + } + + netdev->state = NETDEV_STATE_CREATING; + + log_netdev_debug(netdev, "Creating"); + } + + return 0; +} + +static int netdev_create_after_configured(NetDev *netdev, Link *link) { + assert(netdev); + assert(link); + assert(NETDEV_VTABLE(netdev)->create_after_configured); + + return NETDEV_VTABLE(netdev)->create_after_configured(netdev, link); +} + +/* the callback must be called, possibly after a timeout, as otherwise the Link will hang */ +int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t callback) { + int r; + + assert(netdev); + assert(netdev->manager); + assert(netdev->manager->rtnl); + + switch (netdev_get_create_type(netdev)) { + case NETDEV_CREATE_MASTER: + r = netdev_enslave(netdev, link, callback); + if (r < 0) + return r; + + break; + case NETDEV_CREATE_STACKED: + r = netdev_create(netdev, link, callback); + if (r < 0) + return r; + + break; + case NETDEV_CREATE_AFTER_CONFIGURED: + r = netdev_create_after_configured(netdev, link); + if (r < 0) + return r; + break; + default: + assert_not_reached("Can not join independent netdev"); + } + + return 0; +} + +int netdev_load_one(Manager *manager, const char *filename) { + _cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL; + _cleanup_fclose_ FILE *file = NULL; + const char *dropin_dirname; + bool independent = false; + int r; + + assert(manager); + assert(filename); + + file = fopen(filename, "re"); + if (!file) { + if (errno == ENOENT) + return 0; + + return -errno; + } + + if (null_or_empty_fd(fileno(file))) { + log_debug("Skipping empty file: %s", filename); + return 0; + } + + netdev_raw = new(NetDev, 1); + if (!netdev_raw) + return log_oom(); + + *netdev_raw = (NetDev) { + .n_ref = 1, + .kind = _NETDEV_KIND_INVALID, + .state = _NETDEV_STATE_INVALID, /* an invalid state means done() of the implementation won't be called on destruction */ + }; + + dropin_dirname = strjoina(basename(filename), ".d"); + r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname, + "Match\0NetDev\0", + config_item_perf_lookup, network_netdev_gperf_lookup, + CONFIG_PARSE_WARN|CONFIG_PARSE_RELAXED, netdev_raw); + if (r < 0) + return r; + + /* skip out early if configuration does not match the environment */ + if (!condition_test_list(netdev_raw->conditions, NULL, NULL, NULL)) { + log_debug("%s: Conditions in the file do not match the system environment, skipping.", filename); + return 0; + } + + if (netdev_raw->kind == _NETDEV_KIND_INVALID) { + log_warning("NetDev has no Kind= configured in %s. Ignoring", filename); + return 0; + } + + if (!netdev_raw->ifname) { + log_warning("NetDev without Name= configured in %s. Ignoring", filename); + return 0; + } + + r = fseek(file, 0, SEEK_SET); + if (r < 0) + return -errno; + + netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size); + if (!netdev) + return log_oom(); + + netdev->n_ref = 1; + netdev->manager = manager; + netdev->kind = netdev_raw->kind; + netdev->state = NETDEV_STATE_LOADING; /* we initialize the state here for the first time, + so that done() will be called on destruction */ + + if (NETDEV_VTABLE(netdev)->init) + NETDEV_VTABLE(netdev)->init(netdev); + + r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname, + NETDEV_VTABLE(netdev)->sections, + config_item_perf_lookup, network_netdev_gperf_lookup, + CONFIG_PARSE_WARN, netdev); + if (r < 0) + return r; + + /* verify configuration */ + if (NETDEV_VTABLE(netdev)->config_verify) { + r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename); + if (r < 0) + return 0; + } + + netdev->filename = strdup(filename); + if (!netdev->filename) + return log_oom(); + + if (!netdev->mac && NETDEV_VTABLE(netdev)->generate_mac) { + r = netdev_get_mac(netdev->ifname, &netdev->mac); + if (r < 0) + return log_netdev_error_errno(netdev, r, + "Failed to generate predictable MAC address for %s: %m", + netdev->ifname); + } + + r = hashmap_ensure_allocated(&netdev->manager->netdevs, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev); + if (r == -EEXIST) { + NetDev *n = hashmap_get(netdev->manager->netdevs, netdev->ifname); + + assert(n); + if (!streq(netdev->filename, n->filename)) + log_netdev_warning_errno(netdev, r, + "The setting Name=%s in %s conflicts with the one in %s, ignoring", + netdev->ifname, netdev->filename, n->filename); + + /* Clear ifname before netdev_free() is called. Otherwise, the NetDev object 'n' is + * removed from the hashmap 'manager->netdevs'. */ + netdev->ifname = mfree(netdev->ifname); + return 0; + } + if (r < 0) + return r; + + LIST_HEAD_INIT(netdev->callbacks); + + log_netdev_debug(netdev, "loaded %s", netdev_kind_to_string(netdev->kind)); + + if (IN_SET(netdev_get_create_type(netdev), NETDEV_CREATE_MASTER, NETDEV_CREATE_INDEPENDENT)) { + r = netdev_create(netdev, NULL, NULL); + if (r < 0) + return r; + } + + switch (netdev->kind) { + case NETDEV_KIND_IPIP: + independent = IPIP(netdev)->independent; + break; + case NETDEV_KIND_GRE: + independent = GRE(netdev)->independent; + break; + case NETDEV_KIND_GRETAP: + independent = GRETAP(netdev)->independent; + break; + case NETDEV_KIND_IP6GRE: + independent = IP6GRE(netdev)->independent; + break; + case NETDEV_KIND_IP6GRETAP: + independent = IP6GRETAP(netdev)->independent; + break; + case NETDEV_KIND_SIT: + independent = SIT(netdev)->independent; + break; + case NETDEV_KIND_VTI: + independent = VTI(netdev)->independent; + break; + case NETDEV_KIND_VTI6: + independent = VTI6(netdev)->independent; + break; + case NETDEV_KIND_IP6TNL: + independent = IP6TNL(netdev)->independent; + break; + case NETDEV_KIND_ERSPAN: + independent = ERSPAN(netdev)->independent; + break; + case NETDEV_KIND_XFRM: + independent = XFRM(netdev)->independent; + break; + default: + break; + } + + if (independent) { + r = netdev_create(netdev, NULL, NULL); + if (r < 0) + return r; + } + + netdev = NULL; + + return 0; +} + +int netdev_load(Manager *manager, bool reload) { + _cleanup_strv_free_ char **files = NULL; + char **f; + int r; + + assert(manager); + + if (!reload) + hashmap_clear_with_destructor(manager->netdevs, netdev_unref); + + r = conf_files_list_strv(&files, ".netdev", NULL, 0, NETWORK_DIRS); + if (r < 0) + return log_error_errno(r, "Failed to enumerate netdev files: %m"); + + STRV_FOREACH(f, files) { + r = netdev_load_one(manager, *f); + if (r < 0) + log_error_errno(r, "Failed to load %s, ignoring: %m", *f); + } + + return 0; +} diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h new file mode 100644 index 00000000..8d16ec57 --- /dev/null +++ b/src/network/netdev/netdev.h @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-netlink.h" + +#include "conf-parser.h" +#include "list.h" +#include "networkd-link.h" +#include "time-util.h" + +typedef struct netdev_join_callback netdev_join_callback; + +struct netdev_join_callback { + link_netlink_message_handler_t callback; + Link *link; + + LIST_FIELDS(netdev_join_callback, callbacks); +}; + +typedef enum NetDevKind { + NETDEV_KIND_BRIDGE, + NETDEV_KIND_BOND, + NETDEV_KIND_VLAN, + NETDEV_KIND_MACVLAN, + NETDEV_KIND_MACVTAP, + NETDEV_KIND_IPVLAN, + NETDEV_KIND_IPVTAP, + NETDEV_KIND_VXLAN, + NETDEV_KIND_IPIP, + NETDEV_KIND_GRE, + NETDEV_KIND_GRETAP, + NETDEV_KIND_IP6GRE, + NETDEV_KIND_IP6GRETAP, + NETDEV_KIND_SIT, + NETDEV_KIND_VETH, + NETDEV_KIND_VTI, + NETDEV_KIND_VTI6, + NETDEV_KIND_IP6TNL, + NETDEV_KIND_DUMMY, + NETDEV_KIND_TUN, + NETDEV_KIND_TAP, + NETDEV_KIND_VRF, + NETDEV_KIND_VCAN, + NETDEV_KIND_GENEVE, + NETDEV_KIND_VXCAN, + NETDEV_KIND_WIREGUARD, + NETDEV_KIND_NETDEVSIM, + NETDEV_KIND_FOU, + NETDEV_KIND_ERSPAN, + NETDEV_KIND_L2TP, + NETDEV_KIND_MACSEC, + NETDEV_KIND_NLMON, + NETDEV_KIND_XFRM, + _NETDEV_KIND_MAX, + _NETDEV_KIND_TUNNEL, /* Used by config_parse_stacked_netdev() */ + _NETDEV_KIND_INVALID = -1 +} NetDevKind; + +typedef enum NetDevState { + NETDEV_STATE_LOADING, + NETDEV_STATE_FAILED, + NETDEV_STATE_CREATING, + NETDEV_STATE_READY, + NETDEV_STATE_LINGER, + _NETDEV_STATE_MAX, + _NETDEV_STATE_INVALID = -1, +} NetDevState; + +typedef enum NetDevCreateType { + NETDEV_CREATE_INDEPENDENT, + NETDEV_CREATE_MASTER, + NETDEV_CREATE_STACKED, + NETDEV_CREATE_AFTER_CONFIGURED, + _NETDEV_CREATE_MAX, + _NETDEV_CREATE_INVALID = -1, +} NetDevCreateType; + +typedef struct Manager Manager; +typedef struct Condition Condition; + +typedef struct NetDev { + Manager *manager; + + unsigned n_ref; + + char *filename; + + LIST_HEAD(Condition, conditions); + + NetDevState state; + NetDevKind kind; + char *description; + char *ifname; + struct ether_addr *mac; + uint32_t mtu; + int ifindex; + + LIST_HEAD(netdev_join_callback, callbacks); +} NetDev; + +typedef struct NetDevVTable { + /* How much memory does an object of this unit type need */ + size_t object_size; + + /* Config file sections this netdev kind understands, separated + * by NUL chars */ + const char *sections; + + /* This should reset all type-specific variables. This should + * not allocate memory, and is called with zero-initialized + * data. It should hence only initialize variables that need + * to be set != 0. */ + void (*init)(NetDev *n); + + /* This should free all kind-specific variables. It should be + * idempotent. */ + void (*done)(NetDev *n); + + /* fill in message to create netdev */ + int (*fill_message_create)(NetDev *netdev, Link *link, sd_netlink_message *message); + + /* specifies if netdev is independent, or a master device or a stacked device */ + NetDevCreateType create_type; + + /* create netdev, if not done via rtnl */ + int (*create)(NetDev *netdev); + + /* create netdev after link is fully configured */ + int (*create_after_configured)(NetDev *netdev, Link *link); + + /* perform additional configuration after netdev has been createad */ + int (*post_create)(NetDev *netdev, Link *link, sd_netlink_message *message); + + /* verify that compulsory configuration options were specified */ + int (*config_verify)(NetDev *netdev, const char *filename); + + /* Generate MAC address or not When MACAddress= is not specified. */ + bool generate_mac; +} NetDevVTable; + +extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX]; + +#define NETDEV_VTABLE(n) ((n)->kind != _NETDEV_KIND_INVALID ? netdev_vtable[(n)->kind] : NULL) + +/* For casting a netdev into the various netdev kinds */ +#define DEFINE_NETDEV_CAST(UPPERCASE, MixedCase) \ + static inline MixedCase* UPPERCASE(NetDev *n) { \ + if (_unlikely_(!n || \ + n->kind != NETDEV_KIND_##UPPERCASE) || \ + n->state == _NETDEV_STATE_INVALID) \ + return NULL; \ + \ + return (MixedCase*) n; \ + } + +/* For casting the various netdev kinds into a netdev */ +#define NETDEV(n) (&(n)->meta) + +int netdev_load(Manager *manager, bool reload); +int netdev_load_one(Manager *manager, const char *filename); +void netdev_drop(NetDev *netdev); + +NetDev *netdev_unref(NetDev *netdev); +NetDev *netdev_ref(NetDev *netdev); +DEFINE_TRIVIAL_DESTRUCTOR(netdev_destroy_callback, NetDev, netdev_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref); + +bool netdev_is_managed(NetDev *netdev); +int netdev_get(Manager *manager, const char *name, NetDev **ret); +int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink); +int netdev_get_mac(const char *ifname, struct ether_addr **ret); +int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t cb); +int netdev_join_after_configured(NetDev *netdev, Link *link, link_netlink_message_handler_t callback); + +const char *netdev_kind_to_string(NetDevKind d) _const_; +NetDevKind netdev_kind_from_string(const char *d) _pure_; + +static inline NetDevCreateType netdev_get_create_type(NetDev *netdev) { + assert(netdev); + assert(NETDEV_VTABLE(netdev)); + + return NETDEV_VTABLE(netdev)->create_type; +} + +CONFIG_PARSER_PROTOTYPE(config_parse_netdev_kind); + +/* gperf */ +const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, GPERF_LEN_TYPE length); + +/* Macros which append INTERFACE= to the message */ + +#define log_netdev_full(netdev, level, error, ...) \ + ({ \ + const NetDev *_n = (netdev); \ + _n ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _n->ifname, NULL, NULL, ##__VA_ARGS__) : \ + log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ + }) + +#define log_netdev_debug(netdev, ...) log_netdev_full(netdev, LOG_DEBUG, 0, ##__VA_ARGS__) +#define log_netdev_info(netdev, ...) log_netdev_full(netdev, LOG_INFO, 0, ##__VA_ARGS__) +#define log_netdev_notice(netdev, ...) log_netdev_full(netdev, LOG_NOTICE, 0, ##__VA_ARGS__) +#define log_netdev_warning(netdev, ...) log_netdev_full(netdev, LOG_WARNING, 0, ## __VA_ARGS__) +#define log_netdev_error(netdev, ...) log_netdev_full(netdev, LOG_ERR, 0, ##__VA_ARGS__) + +#define log_netdev_debug_errno(netdev, error, ...) log_netdev_full(netdev, LOG_DEBUG, error, ##__VA_ARGS__) +#define log_netdev_info_errno(netdev, error, ...) log_netdev_full(netdev, LOG_INFO, error, ##__VA_ARGS__) +#define log_netdev_notice_errno(netdev, error, ...) log_netdev_full(netdev, LOG_NOTICE, error, ##__VA_ARGS__) +#define log_netdev_warning_errno(netdev, error, ...) log_netdev_full(netdev, LOG_WARNING, error, ##__VA_ARGS__) +#define log_netdev_error_errno(netdev, error, ...) log_netdev_full(netdev, LOG_ERR, error, ##__VA_ARGS__) + +#define LOG_NETDEV_MESSAGE(netdev, fmt, ...) "MESSAGE=%s: " fmt, (netdev)->ifname, ##__VA_ARGS__ +#define LOG_NETDEV_INTERFACE(netdev) "INTERFACE=%s", (netdev)->ifname diff --git a/src/network/netdev/netdevsim.c b/src/network/netdev/netdevsim.c new file mode 100644 index 00000000..96f3932c --- /dev/null +++ b/src/network/netdev/netdevsim.c @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "netdevsim.h" + +const NetDevVTable netdevsim_vtable = { + .object_size = sizeof(NetDevSim), + .sections = "Match\0NetDev\0", + .create_type = NETDEV_CREATE_INDEPENDENT, + .generate_mac = true, +}; diff --git a/src/network/netdev/netdevsim.h b/src/network/netdev/netdevsim.h new file mode 100644 index 00000000..4622f4a0 --- /dev/null +++ b/src/network/netdev/netdevsim.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct NetDevSim NetDevSim; + +#include "netdev.h" + +struct NetDevSim { + NetDev meta; +}; + +DEFINE_NETDEV_CAST(NETDEVSIM, NetDevSim); +extern const NetDevVTable netdevsim_vtable; diff --git a/src/network/netdev/nlmon.c b/src/network/netdev/nlmon.c new file mode 100644 index 00000000..3a6179f5 --- /dev/null +++ b/src/network/netdev/nlmon.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "nlmon.h" + +static int netdev_nlmon_verify(NetDev *netdev, const char *filename) { + assert(netdev); + assert(filename); + + if (netdev->mac) { + log_netdev_warning(netdev, "%s: MACAddress= is not supported. Ignoring", filename); + netdev->mac = mfree(netdev->mac); + } + + return 0; +} + +const NetDevVTable nlmon_vtable = { + .object_size = sizeof(NLMon), + .sections = "Match\0NetDev\0", + .create_type = NETDEV_CREATE_INDEPENDENT, + .config_verify = netdev_nlmon_verify, +}; diff --git a/src/network/netdev/nlmon.h b/src/network/netdev/nlmon.h new file mode 100644 index 00000000..b5f65f61 --- /dev/null +++ b/src/network/netdev/nlmon.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct NLMon NLMon; + +#include "netdev.h" + +struct NLMon { + NetDev meta; +}; + +DEFINE_NETDEV_CAST(NLMON, NLMon); + +extern const NetDevVTable nlmon_vtable; diff --git a/src/network/netdev/tunnel.c b/src/network/netdev/tunnel.c new file mode 100644 index 00000000..a3bad941 --- /dev/null +++ b/src/network/netdev/tunnel.c @@ -0,0 +1,903 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "conf-parser.h" +#include "missing_network.h" +#include "netlink-util.h" +#include "parse-util.h" +#include "string-table.h" +#include "string-util.h" +#include "tunnel.h" +#include "util.h" + +#define DEFAULT_TNL_HOP_LIMIT 64 +#define IP6_FLOWINFO_FLOWLABEL htobe32(0x000FFFFF) +#define IP6_TNL_F_ALLOW_LOCAL_REMOTE 0x40 + +static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = { + [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6", + [NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6", + [NETDEV_IP6_TNL_MODE_ANYIP6] = "any", +}; + +DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode); +DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode"); + +static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + Tunnel *t; + int r; + + assert(netdev); + + if (netdev->kind == NETDEV_KIND_IPIP) + t = IPIP(netdev); + else + t = SIT(netdev); + + assert(m); + assert(t); + + if (link || t->assign_to_loopback) { + r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); + } + + r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); + + r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m"); + + if (t->fou_tunnel) { + r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_TYPE, t->fou_encap_type); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_TYPE attribute: %m"); + + r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_SPORT, htobe16(t->encap_src_port)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_SPORT attribute: %m"); + + r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_DPORT, htobe16(t->fou_destination_port)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_DPORT attribute: %m"); + } + + if (netdev->kind == NETDEV_KIND_SIT) { + if (t->sixrd_prefixlen > 0) { + r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_6RD_PREFIX, &t->sixrd_prefix); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_6RD_PREFIX attribute: %m"); + + /* u16 is deliberate here, even though we're passing a netmask that can never be >128. The kernel is + * expecting to receive the prefixlen as a u16. + */ + r = sd_netlink_message_append_u16(m, IFLA_IPTUN_6RD_PREFIXLEN, t->sixrd_prefixlen); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_6RD_PREFIXLEN attribute: %m"); + } + + if (t->isatap >= 0) { + uint16_t flags = 0; + + SET_FLAG(flags, SIT_ISATAP, t->isatap); + + r = sd_netlink_message_append_u16(m, IFLA_IPTUN_FLAGS, flags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m"); + } + } + + return r; +} + +static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + uint32_t ikey = 0; + uint32_t okey = 0; + uint16_t iflags = 0; + uint16_t oflags = 0; + Tunnel *t; + int r; + + assert(netdev); + assert(m); + + switch (netdev->kind) { + case NETDEV_KIND_GRE: + t = GRE(netdev); + break; + case NETDEV_KIND_ERSPAN: + t = ERSPAN(netdev); + break; + case NETDEV_KIND_GRETAP: + t = GRETAP(netdev); + break; + default: + assert_not_reached("invalid netdev kind"); + } + + assert(t); + + if (link || t->assign_to_loopback) { + r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); + } + + if (netdev->kind == NETDEV_KIND_ERSPAN) { + r = sd_netlink_message_append_u32(m, IFLA_GRE_ERSPAN_INDEX, t->erspan_index); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ERSPAN_INDEX attribute: %m"); + } + + r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m"); + + r = sd_netlink_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_GRE_TOS, t->tos); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TOS attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_PMTUDISC attribute: %m"); + + if (t->key != 0) { + ikey = okey = htobe32(t->key); + iflags |= GRE_KEY; + oflags |= GRE_KEY; + } + + if (t->ikey != 0) { + ikey = htobe32(t->ikey); + iflags |= GRE_KEY; + } + + if (t->okey != 0) { + okey = htobe32(t->okey); + oflags |= GRE_KEY; + } + + if (t->gre_erspan_sequence > 0) { + iflags |= GRE_SEQ; + oflags |= GRE_SEQ; + } else if (t->gre_erspan_sequence == 0) { + iflags &= ~GRE_SEQ; + oflags &= ~GRE_SEQ; + } + + r = sd_netlink_message_append_u32(m, IFLA_GRE_IKEY, ikey); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IKEY attribute: %m"); + + r = sd_netlink_message_append_u32(m, IFLA_GRE_OKEY, okey); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OKEY attribute: %m"); + + r = sd_netlink_message_append_u16(m, IFLA_GRE_IFLAGS, iflags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IFLAGS attribute: %m"); + + r = sd_netlink_message_append_u16(m, IFLA_GRE_OFLAGS, oflags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OFLAGS, attribute: %m"); + + if (t->fou_tunnel) { + r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_TYPE, t->fou_encap_type); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_TYPE attribute: %m"); + + r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_SPORT, htobe16(t->encap_src_port)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_SPORT attribute: %m"); + + r = sd_netlink_message_append_u16(m, IFLA_GRE_ENCAP_DPORT, htobe16(t->fou_destination_port)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_ENCAP_DPORT attribute: %m"); + } + + return r; +} + +static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + uint32_t ikey = 0; + uint32_t okey = 0; + uint16_t iflags = 0; + uint16_t oflags = 0; + Tunnel *t; + int r; + + assert(netdev); + + if (netdev->kind == NETDEV_KIND_IP6GRE) + t = IP6GRE(netdev); + else + t = IP6GRETAP(netdev); + + assert(t); + assert(m); + + if (link || t->assign_to_loopback) { + r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); + } + + r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m"); + + r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m"); + + if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) { + r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m"); + } + + r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m"); + + if (t->key != 0) { + ikey = okey = htobe32(t->key); + iflags |= GRE_KEY; + oflags |= GRE_KEY; + } + + if (t->ikey != 0) { + ikey = htobe32(t->ikey); + iflags |= GRE_KEY; + } + + if (t->okey != 0) { + okey = htobe32(t->okey); + oflags |= GRE_KEY; + } + + r = sd_netlink_message_append_u32(m, IFLA_GRE_IKEY, ikey); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IKEY attribute: %m"); + + r = sd_netlink_message_append_u32(m, IFLA_GRE_OKEY, okey); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OKEY attribute: %m"); + + r = sd_netlink_message_append_u16(m, IFLA_GRE_IFLAGS, iflags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_IFLAGS attribute: %m"); + + r = sd_netlink_message_append_u16(m, IFLA_GRE_OFLAGS, oflags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_OFLAGS, attribute: %m"); + + return r; +} + +static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + uint32_t ikey, okey; + Tunnel *t; + int r; + + assert(netdev); + assert(m); + + if (netdev->kind == NETDEV_KIND_VTI) + t = VTI(netdev); + else + t = VTI6(netdev); + + assert(t); + + if (link || t->assign_to_loopback) { + r = sd_netlink_message_append_u32(m, IFLA_VTI_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_LINK attribute: %m"); + } + + if (t->key != 0) + ikey = okey = htobe32(t->key); + else { + ikey = htobe32(t->ikey); + okey = htobe32(t->okey); + } + + r = sd_netlink_message_append_u32(m, IFLA_VTI_IKEY, ikey); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_IKEY attribute: %m"); + + r = sd_netlink_message_append_u32(m, IFLA_VTI_OKEY, okey); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_OKEY attribute: %m"); + + r = netlink_message_append_in_addr_union(m, IFLA_VTI_LOCAL, t->family, &t->local); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_LOCAL attribute: %m"); + + r = netlink_message_append_in_addr_union(m, IFLA_VTI_REMOTE, t->family, &t->remote); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_REMOTE attribute: %m"); + + return r; +} + +static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + Tunnel *t = IP6TNL(netdev); + uint8_t proto; + int r; + + assert(netdev); + assert(m); + assert(t); + + if (link || t->assign_to_loopback) { + r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); + } + + r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); + + r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); + + if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) { + r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m"); + } + + if (t->copy_dscp) + t->flags |= IP6_TNL_F_RCV_DSCP_COPY; + + if (t->allow_localremote >= 0) + SET_FLAG(t->flags, IP6_TNL_F_ALLOW_LOCAL_REMOTE, t->allow_localremote); + + if (t->encap_limit != IPV6_DEFAULT_TNL_ENCAP_LIMIT) { + r = sd_netlink_message_append_u8(m, IFLA_IPTUN_ENCAP_LIMIT, t->encap_limit); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_LIMIT attribute: %m"); + } + + r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m"); + + switch (t->ip6tnl_mode) { + case NETDEV_IP6_TNL_MODE_IP6IP6: + proto = IPPROTO_IPV6; + break; + case NETDEV_IP6_TNL_MODE_IPIP6: + proto = IPPROTO_IPIP; + break; + case NETDEV_IP6_TNL_MODE_ANYIP6: + default: + proto = 0; + break; + } + + r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PROTO attribute: %m"); + + return r; +} + +static int netdev_tunnel_verify(NetDev *netdev, const char *filename) { + Tunnel *t = NULL; + + assert(netdev); + assert(filename); + + switch (netdev->kind) { + case NETDEV_KIND_IPIP: + t = IPIP(netdev); + break; + case NETDEV_KIND_SIT: + t = SIT(netdev); + break; + case NETDEV_KIND_GRE: + t = GRE(netdev); + break; + case NETDEV_KIND_GRETAP: + t = GRETAP(netdev); + break; + case NETDEV_KIND_IP6GRE: + t = IP6GRE(netdev); + break; + case NETDEV_KIND_IP6GRETAP: + t = IP6GRETAP(netdev); + break; + case NETDEV_KIND_VTI: + t = VTI(netdev); + break; + case NETDEV_KIND_VTI6: + t = VTI6(netdev); + break; + case NETDEV_KIND_IP6TNL: + t = IP6TNL(netdev); + break; + case NETDEV_KIND_ERSPAN: + t = ERSPAN(netdev); + break; + default: + assert_not_reached("Invalid tunnel kind"); + } + + assert(t); + + if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_IPIP, NETDEV_KIND_SIT, NETDEV_KIND_GRE) && + !IN_SET(t->family, AF_UNSPEC, AF_INET)) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "vti/ipip/sit/gre tunnel without a local/remote IPv4 address configured in %s. Ignoring", filename); + + if (IN_SET(netdev->kind, NETDEV_KIND_GRETAP, NETDEV_KIND_ERSPAN) && + (t->family != AF_INET || in_addr_is_null(t->family, &t->remote))) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "gretap/erspan tunnel without a remote IPv4 address configured in %s. Ignoring", filename); + + if ((IN_SET(netdev->kind, NETDEV_KIND_VTI6, NETDEV_KIND_IP6TNL) && t->family != AF_INET6) || + (netdev->kind == NETDEV_KIND_IP6GRE && !IN_SET(t->family, AF_UNSPEC, AF_INET6))) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "vti6/ip6tnl/ip6gre tunnel without a local/remote IPv6 address configured in %s. Ignoring", filename); + + if (netdev->kind == NETDEV_KIND_IP6GRETAP && + (t->family != AF_INET6 || in_addr_is_null(t->family, &t->remote))) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "ip6gretap tunnel without a remote IPv6 address configured in %s. Ignoring", filename); + + if (netdev->kind == NETDEV_KIND_IP6TNL && + t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "ip6tnl without mode configured in %s. Ignoring", filename); + + if (t->fou_tunnel && t->fou_destination_port <= 0) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "FooOverUDP missing port configured in %s. Ignoring", filename); + + if (netdev->kind == NETDEV_KIND_ERSPAN && (t->erspan_index >= (1 << 20) || t->erspan_index == 0)) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Invalid erspan index %d. Ignoring", t->erspan_index); + + /* netlink_message_append_in_addr_union() is used for vti/vti6. So, t->family cannot be AF_UNSPEC. */ + if (netdev->kind == NETDEV_KIND_VTI) + t->family = AF_INET; + + return 0; +} + +int config_parse_tunnel_address(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Tunnel *t = userdata; + union in_addr_union *addr = data, buffer; + int r, f; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* This is used to parse addresses on both local and remote ends of the tunnel. + * Address families must match. + * + * "any" is a special value which means that the address is unspecified. + */ + + if (streq(rvalue, "any")) { + *addr = IN_ADDR_NULL; + + /* As a special case, if both the local and remote addresses are + * unspecified, also clear the address family. + */ + if (t->family != AF_UNSPEC && + in_addr_is_null(t->family, &t->local) != 0 && + in_addr_is_null(t->family, &t->remote) != 0) + t->family = AF_UNSPEC; + return 0; + } + + r = in_addr_from_string_auto(rvalue, &f, &buffer); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue); + return 0; + } + + if (t->family != AF_UNSPEC && t->family != f) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Tunnel addresses incompatible, ignoring assignment: %s", rvalue); + return 0; + } + + t->family = f; + *addr = buffer; + return 0; +} + +int config_parse_tunnel_key(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + union in_addr_union buffer; + Tunnel *t = userdata; + uint32_t k; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = in_addr_from_string(AF_INET, rvalue, &buffer); + if (r < 0) { + r = safe_atou32(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse tunnel key ignoring assignment: %s", rvalue); + return 0; + } + } else + k = be32toh(buffer.in.s_addr); + + if (streq(lvalue, "Key")) + t->key = k; + else if (streq(lvalue, "InputKey")) + t->ikey = k; + else + t->okey = k; + + return 0; +} + +int config_parse_ipv6_flowlabel(const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + IPv6FlowLabel *ipv6_flowlabel = data; + Tunnel *t = userdata; + int k = 0; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(ipv6_flowlabel); + + if (streq(rvalue, "inherit")) { + *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL; + t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; + } else { + r = config_parse_int(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata); + if (r < 0) + return r; + + if (k > 0xFFFFF) + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue); + else { + *ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL; + t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; + } + } + + return 0; +} + +int config_parse_encap_limit(const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Tunnel *t = userdata; + int k = 0; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (streq(rvalue, "none")) + t->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT; + else { + r = safe_atoi(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Tunnel Encapsulation Limit option, ignoring: %s", rvalue); + return 0; + } + + if (k > 255 || k < 0) + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid Tunnel Encapsulation value, ignoring: %d", k); + else { + t->encap_limit = k; + t->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT; + } + } + + return 0; +} + +int config_parse_6rd_prefix(const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Tunnel *t = userdata; + + assert(filename); + assert(lvalue); + assert(rvalue); + + union in_addr_union p; + uint8_t l; + int r; + + r = in_addr_prefix_from_string(rvalue, AF_INET6, &p, &l); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse 6rd prefix \"%s\", ignoring: %m", rvalue); + return 0; + } + if (l == 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "6rd prefix length of \"%s\" must be greater than zero, ignoring", rvalue); + return 0; + } + + t->sixrd_prefix = p.in6; + t->sixrd_prefixlen = l; + + return 0; +} + +static void ipip_sit_init(NetDev *n) { + Tunnel *t; + + assert(n); + + switch (n->kind) { + case NETDEV_KIND_IPIP: + t = IPIP(n); + break; + case NETDEV_KIND_SIT: + t = SIT(n); + break; + default: + assert_not_reached("invalid netdev kind"); + } + + assert(t); + + t->pmtudisc = true; + t->fou_encap_type = NETDEV_FOO_OVER_UDP_ENCAP_DIRECT; + t->isatap = -1; +} + +static void vti_init(NetDev *n) { + Tunnel *t; + + assert(n); + + if (n->kind == NETDEV_KIND_VTI) + t = VTI(n); + else + t = VTI6(n); + + assert(t); + + t->pmtudisc = true; +} + +static void gre_erspan_init(NetDev *n) { + Tunnel *t; + + assert(n); + + switch (n->kind) { + case NETDEV_KIND_GRE: + t = GRE(n); + break; + case NETDEV_KIND_ERSPAN: + t = ERSPAN(n); + break; + case NETDEV_KIND_GRETAP: + t = GRETAP(n); + break; + default: + assert_not_reached("invalid netdev kind"); + } + + assert(t); + + t->pmtudisc = true; + t->gre_erspan_sequence = -1; + t->fou_encap_type = NETDEV_FOO_OVER_UDP_ENCAP_DIRECT; +} + +static void ip6gre_init(NetDev *n) { + Tunnel *t; + + assert(n); + + if (n->kind == NETDEV_KIND_IP6GRE) + t = IP6GRE(n); + else + t = IP6GRETAP(n); + + assert(t); + + t->ttl = DEFAULT_TNL_HOP_LIMIT; +} + +static void ip6tnl_init(NetDev *n) { + Tunnel *t = IP6TNL(n); + + assert(n); + assert(t); + + t->ttl = DEFAULT_TNL_HOP_LIMIT; + t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT; + t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID; + t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID; + t->allow_localremote = -1; +} + +const NetDevVTable ipip_vtable = { + .object_size = sizeof(Tunnel), + .init = ipip_sit_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_ipip_sit_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, + .generate_mac = true, +}; + +const NetDevVTable sit_vtable = { + .object_size = sizeof(Tunnel), + .init = ipip_sit_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_ipip_sit_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, + .generate_mac = true, +}; + +const NetDevVTable vti_vtable = { + .object_size = sizeof(Tunnel), + .init = vti_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_vti_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, + .generate_mac = true, +}; + +const NetDevVTable vti6_vtable = { + .object_size = sizeof(Tunnel), + .init = vti_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_vti_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, + .generate_mac = true, +}; + +const NetDevVTable gre_vtable = { + .object_size = sizeof(Tunnel), + .init = gre_erspan_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_gre_erspan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, + .generate_mac = true, +}; + +const NetDevVTable gretap_vtable = { + .object_size = sizeof(Tunnel), + .init = gre_erspan_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_gre_erspan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, + .generate_mac = true, +}; + +const NetDevVTable ip6gre_vtable = { + .object_size = sizeof(Tunnel), + .init = ip6gre_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_ip6gre_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, + .generate_mac = true, +}; + +const NetDevVTable ip6gretap_vtable = { + .object_size = sizeof(Tunnel), + .init = ip6gre_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_ip6gre_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, + .generate_mac = true, +}; + +const NetDevVTable ip6tnl_vtable = { + .object_size = sizeof(Tunnel), + .init = ip6tnl_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_ip6tnl_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, + .generate_mac = true, +}; + +const NetDevVTable erspan_vtable = { + .object_size = sizeof(Tunnel), + .init = gre_erspan_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_gre_erspan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, + .generate_mac = true, +}; diff --git a/src/network/netdev/tunnel.h b/src/network/netdev/tunnel.h new file mode 100644 index 00000000..6480d93e --- /dev/null +++ b/src/network/netdev/tunnel.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "in-addr-util.h" + +#include "conf-parser.h" +#include "fou-tunnel.h" +#include "netdev.h" + +typedef enum Ip6TnlMode { + NETDEV_IP6_TNL_MODE_IP6IP6, + NETDEV_IP6_TNL_MODE_IPIP6, + NETDEV_IP6_TNL_MODE_ANYIP6, + _NETDEV_IP6_TNL_MODE_MAX, + _NETDEV_IP6_TNL_MODE_INVALID = -1, +} Ip6TnlMode; + +typedef enum IPv6FlowLabel { + NETDEV_IPV6_FLOWLABEL_INHERIT = 0xFFFFF + 1, + _NETDEV_IPV6_FLOWLABEL_MAX, + _NETDEV_IPV6_FLOWLABEL_INVALID = -1, +} IPv6FlowLabel; + +typedef struct Tunnel { + NetDev meta; + + uint8_t encap_limit; + + int family; + int ipv6_flowlabel; + int allow_localremote; + int gre_erspan_sequence; + int isatap; + + unsigned ttl; + unsigned tos; + unsigned flags; + + uint32_t key; + uint32_t ikey; + uint32_t okey; + uint32_t erspan_index; + + union in_addr_union local; + union in_addr_union remote; + + Ip6TnlMode ip6tnl_mode; + FooOverUDPEncapType fou_encap_type; + + bool pmtudisc; + bool copy_dscp; + bool independent; + bool fou_tunnel; + bool assign_to_loopback; + + uint16_t encap_src_port; + uint16_t fou_destination_port; + + struct in6_addr sixrd_prefix; + uint8_t sixrd_prefixlen; +} Tunnel; + +DEFINE_NETDEV_CAST(IPIP, Tunnel); +DEFINE_NETDEV_CAST(GRE, Tunnel); +DEFINE_NETDEV_CAST(GRETAP, Tunnel); +DEFINE_NETDEV_CAST(IP6GRE, Tunnel); +DEFINE_NETDEV_CAST(IP6GRETAP, Tunnel); +DEFINE_NETDEV_CAST(SIT, Tunnel); +DEFINE_NETDEV_CAST(VTI, Tunnel); +DEFINE_NETDEV_CAST(VTI6, Tunnel); +DEFINE_NETDEV_CAST(IP6TNL, Tunnel); +DEFINE_NETDEV_CAST(ERSPAN, Tunnel); +extern const NetDevVTable ipip_vtable; +extern const NetDevVTable sit_vtable; +extern const NetDevVTable vti_vtable; +extern const NetDevVTable vti6_vtable; +extern const NetDevVTable gre_vtable; +extern const NetDevVTable gretap_vtable; +extern const NetDevVTable ip6gre_vtable; +extern const NetDevVTable ip6gretap_vtable; +extern const NetDevVTable ip6tnl_vtable; +extern const NetDevVTable erspan_vtable; + +const char *ip6tnl_mode_to_string(Ip6TnlMode d) _const_; +Ip6TnlMode ip6tnl_mode_from_string(const char *d) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_ip6tnl_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_address); +CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_flowlabel); +CONFIG_PARSER_PROTOTYPE(config_parse_encap_limit); +CONFIG_PARSER_PROTOTYPE(config_parse_tunnel_key); +CONFIG_PARSER_PROTOTYPE(config_parse_6rd_prefix); diff --git a/src/network/netdev/tuntap.c b/src/network/netdev/tuntap.c new file mode 100644 index 00000000..ce69ef41 --- /dev/null +++ b/src/network/netdev/tuntap.c @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "tuntap.h" +#include "user-util.h" + +#define TUN_DEV "/dev/net/tun" + +static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) { + TunTap *t; + + assert(netdev); + assert(netdev->ifname); + assert(ifr); + + if (netdev->kind == NETDEV_KIND_TAP) { + t = TAP(netdev); + ifr->ifr_flags |= IFF_TAP; + } else { + t = TUN(netdev); + ifr->ifr_flags |= IFF_TUN; + } + + if (!t->packet_info) + ifr->ifr_flags |= IFF_NO_PI; + + if (t->multi_queue) + ifr->ifr_flags |= IFF_MULTI_QUEUE; + + if (t->vnet_hdr) + ifr->ifr_flags |= IFF_VNET_HDR; + + strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1); + + return 0; +} + +static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { + _cleanup_close_ int fd; + TunTap *t = NULL; + const char *user; + const char *group; + uid_t uid; + gid_t gid; + int r; + + assert(netdev); + assert(ifr); + + fd = open(TUN_DEV, O_RDWR|O_CLOEXEC); + if (fd < 0) + return log_netdev_error_errno(netdev, -errno, "Failed to open tun dev: %m"); + + if (ioctl(fd, TUNSETIFF, ifr) < 0) + return log_netdev_error_errno(netdev, -errno, "TUNSETIFF failed on tun dev: %m"); + + if (netdev->kind == NETDEV_KIND_TAP) + t = TAP(netdev); + else + t = TUN(netdev); + + assert(t); + + if (t->user_name) { + user = t->user_name; + + r = get_user_creds(&user, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Cannot resolve user name %s: %m", t->user_name); + + if (ioctl(fd, TUNSETOWNER, uid) < 0) + return log_netdev_error_errno(netdev, -errno, "TUNSETOWNER failed on tun dev: %m"); + } + + if (t->group_name) { + group = t->group_name; + + r = get_group_creds(&group, &gid, USER_CREDS_ALLOW_MISSING); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Cannot resolve group name %s: %m", t->group_name); + + if (ioctl(fd, TUNSETGROUP, gid) < 0) + return log_netdev_error_errno(netdev, -errno, "TUNSETGROUP failed on tun dev: %m"); + + } + + if (ioctl(fd, TUNSETPERSIST, 1) < 0) + return log_netdev_error_errno(netdev, -errno, "TUNSETPERSIST failed on tun dev: %m"); + + return 0; +} + +static int netdev_create_tuntap(NetDev *netdev) { + struct ifreq ifr = {}; + int r; + + r = netdev_fill_tuntap_message(netdev, &ifr); + if (r < 0) + return r; + + return netdev_tuntap_add(netdev, &ifr); +} + +static void tuntap_done(NetDev *netdev) { + TunTap *t = NULL; + + assert(netdev); + + if (netdev->kind == NETDEV_KIND_TUN) + t = TUN(netdev); + else + t = TAP(netdev); + + assert(t); + + t->user_name = mfree(t->user_name); + t->group_name = mfree(t->group_name); +} + +static int tuntap_verify(NetDev *netdev, const char *filename) { + assert(netdev); + + if (netdev->mtu != 0) + log_netdev_warning(netdev, + "MTUBytes= configured for %s device in %s will be ignored.\n" + "Please set it in the corresponding .network file.", + netdev_kind_to_string(netdev->kind), filename); + + if (netdev->mac) + log_netdev_warning(netdev, + "MACAddress= configured for %s device in %s will be ignored.\n" + "Please set it in the corresponding .network file.", + netdev_kind_to_string(netdev->kind), filename); + + return 0; +} + +const NetDevVTable tun_vtable = { + .object_size = sizeof(TunTap), + .sections = "Match\0NetDev\0Tun\0", + .config_verify = tuntap_verify, + .done = tuntap_done, + .create = netdev_create_tuntap, + .create_type = NETDEV_CREATE_INDEPENDENT, +}; + +const NetDevVTable tap_vtable = { + .object_size = sizeof(TunTap), + .sections = "Match\0NetDev\0Tap\0", + .config_verify = tuntap_verify, + .done = tuntap_done, + .create = netdev_create_tuntap, + .create_type = NETDEV_CREATE_INDEPENDENT, +}; diff --git a/src/network/netdev/tuntap.h b/src/network/netdev/tuntap.h new file mode 100644 index 00000000..8a80b633 --- /dev/null +++ b/src/network/netdev/tuntap.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct TunTap TunTap; + +#include "netdev.h" + +struct TunTap { + NetDev meta; + + char *user_name; + char *group_name; + bool multi_queue; + bool packet_info; + bool vnet_hdr; +}; + +DEFINE_NETDEV_CAST(TUN, TunTap); +DEFINE_NETDEV_CAST(TAP, TunTap); +extern const NetDevVTable tun_vtable; +extern const NetDevVTable tap_vtable; diff --git a/src/network/netdev/vcan.c b/src/network/netdev/vcan.c new file mode 100644 index 00000000..9b3ab48f --- /dev/null +++ b/src/network/netdev/vcan.c @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "vcan.h" + +const NetDevVTable vcan_vtable = { + .object_size = sizeof(VCan), + .sections = "Match\0NetDev\0", + .create_type = NETDEV_CREATE_INDEPENDENT, + .generate_mac = true, +}; diff --git a/src/network/netdev/vcan.h b/src/network/netdev/vcan.h new file mode 100644 index 00000000..d8af07e3 --- /dev/null +++ b/src/network/netdev/vcan.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct VCan VCan; + +#include +#include + +#include "netdev.h" + +struct VCan { + NetDev meta; +}; + +DEFINE_NETDEV_CAST(VCAN, VCan); + +extern const NetDevVTable vcan_vtable; diff --git a/src/network/netdev/veth.c b/src/network/netdev/veth.c new file mode 100644 index 00000000..4ed9e815 --- /dev/null +++ b/src/network/netdev/veth.c @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "veth.h" + +static int netdev_veth_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + Veth *v; + int r; + + assert(netdev); + assert(!link); + assert(m); + + v = VETH(netdev); + + assert(v); + + r = sd_netlink_message_open_container(m, VETH_INFO_PEER); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append VETH_INFO_PEER attribute: %m"); + + if (v->ifname_peer) { + r = sd_netlink_message_append_string(m, IFLA_IFNAME, v->ifname_peer); + if (r < 0) + return log_error_errno(r, "Failed to add netlink interface name: %m"); + } + + if (v->mac_peer) { + r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, v->mac_peer); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m"); + } + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); + + return r; +} + +static int netdev_veth_verify(NetDev *netdev, const char *filename) { + Veth *v; + int r; + + assert(netdev); + assert(filename); + + v = VETH(netdev); + + assert(v); + + if (!v->ifname_peer) { + log_warning("Veth NetDev without peer name configured in %s. Ignoring", + filename); + return -EINVAL; + } + + if (!v->mac_peer) { + r = netdev_get_mac(v->ifname_peer, &v->mac_peer); + if (r < 0) { + log_warning("Failed to generate predictable MAC address for %s. Ignoring", + v->ifname_peer); + return -EINVAL; + } + } + + return 0; +} + +static void veth_done(NetDev *n) { + Veth *v; + + assert(n); + + v = VETH(n); + + assert(v); + + free(v->ifname_peer); + free(v->mac_peer); +} + +const NetDevVTable veth_vtable = { + .object_size = sizeof(Veth), + .sections = "Match\0NetDev\0Peer\0", + .done = veth_done, + .fill_message_create = netdev_veth_fill_message_create, + .create_type = NETDEV_CREATE_INDEPENDENT, + .config_verify = netdev_veth_verify, + .generate_mac = true, +}; diff --git a/src/network/netdev/veth.h b/src/network/netdev/veth.h new file mode 100644 index 00000000..6a0728b1 --- /dev/null +++ b/src/network/netdev/veth.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Veth Veth; + +#include "netdev.h" + +struct Veth { + NetDev meta; + + char *ifname_peer; + struct ether_addr *mac_peer; +}; + +DEFINE_NETDEV_CAST(VETH, Veth); +extern const NetDevVTable veth_vtable; diff --git a/src/network/netdev/vlan.c b/src/network/netdev/vlan.c new file mode 100644 index 00000000..1b4e5bc2 --- /dev/null +++ b/src/network/netdev/vlan.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "vlan-util.h" +#include "vlan.h" + +static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { + struct ifla_vlan_flags flags = {}; + VLan *v; + int r; + + assert(netdev); + assert(link); + assert(req); + + v = VLAN(netdev); + + assert(v); + + r = sd_netlink_message_append_u16(req, IFLA_VLAN_ID, v->id); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_ID attribute: %m"); + + if (v->gvrp != -1) { + flags.mask |= VLAN_FLAG_GVRP; + SET_FLAG(flags.flags, VLAN_FLAG_GVRP, v->gvrp); + } + + if (v->mvrp != -1) { + flags.mask |= VLAN_FLAG_MVRP; + SET_FLAG(flags.flags, VLAN_FLAG_MVRP, v->mvrp); + } + + if (v->reorder_hdr != -1) { + flags.mask |= VLAN_FLAG_REORDER_HDR; + SET_FLAG(flags.flags, VLAN_FLAG_REORDER_HDR, v->reorder_hdr); + } + + if (v->loose_binding != -1) { + flags.mask |= VLAN_FLAG_LOOSE_BINDING; + SET_FLAG(flags.flags, VLAN_FLAG_LOOSE_BINDING, v->loose_binding); + } + + r = sd_netlink_message_append_data(req, IFLA_VLAN_FLAGS, &flags, sizeof(struct ifla_vlan_flags)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_FLAGS attribute: %m"); + + return 0; +} + +static int netdev_vlan_verify(NetDev *netdev, const char *filename) { + VLan *v; + + assert(netdev); + assert(filename); + + v = VLAN(netdev); + + assert(v); + + if (v->id == VLANID_INVALID) { + log_warning("VLAN without valid Id (%"PRIu16") configured in %s.", v->id, filename); + return -EINVAL; + } + + return 0; +} + +static void vlan_init(NetDev *netdev) { + VLan *v = VLAN(netdev); + + assert(netdev); + assert(v); + + v->id = VLANID_INVALID; + v->gvrp = -1; + v->mvrp = -1; + v->loose_binding = -1; + v->reorder_hdr = -1; +} + +const NetDevVTable vlan_vtable = { + .object_size = sizeof(VLan), + .init = vlan_init, + .sections = "Match\0NetDev\0VLAN\0", + .fill_message_create = netdev_vlan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_vlan_verify, +}; diff --git a/src/network/netdev/vlan.h b/src/network/netdev/vlan.h new file mode 100644 index 00000000..7f6cb147 --- /dev/null +++ b/src/network/netdev/vlan.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct VLan VLan; + +#include "netdev.h" + +struct VLan { + NetDev meta; + + uint16_t id; + + int gvrp; + int mvrp; + int loose_binding; + int reorder_hdr; +}; + +DEFINE_NETDEV_CAST(VLAN, VLan); +extern const NetDevVTable vlan_vtable; diff --git a/src/network/netdev/vrf.c b/src/network/netdev/vrf.c new file mode 100644 index 00000000..dc7a9672 --- /dev/null +++ b/src/network/netdev/vrf.c @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "vrf.h" + +static int netdev_vrf_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + Vrf *v; + int r; + + assert(netdev); + assert(!link); + assert(m); + + v = VRF(netdev); + + assert(v); + + r = sd_netlink_message_append_u32(m, IFLA_VRF_TABLE, v->table); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IPLA_VRF_TABLE attribute: %m"); + + return r; +} + +const NetDevVTable vrf_vtable = { + .object_size = sizeof(Vrf), + .sections = "Match\0NetDev\0VRF\0", + .fill_message_create = netdev_vrf_fill_message_create, + .create_type = NETDEV_CREATE_MASTER, + .generate_mac = true, +}; diff --git a/src/network/netdev/vrf.h b/src/network/netdev/vrf.h new file mode 100644 index 00000000..a0bff913 --- /dev/null +++ b/src/network/netdev/vrf.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Vrf Vrf; + +#include "netdev.h" + +struct Vrf { + NetDev meta; + + uint32_t table; +}; + +DEFINE_NETDEV_CAST(VRF, Vrf); +extern const NetDevVTable vrf_vtable; diff --git a/src/network/netdev/vxcan.c b/src/network/netdev/vxcan.c new file mode 100644 index 00000000..d1c3f091 --- /dev/null +++ b/src/network/netdev/vxcan.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "vxcan.h" + +static int netdev_vxcan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + VxCan *v; + int r; + + assert(netdev); + assert(!link); + assert(m); + + v = VXCAN(netdev); + + assert(v); + + r = sd_netlink_message_open_container(m, VXCAN_INFO_PEER); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append VXCAN_INFO_PEER attribute: %m"); + + if (v->ifname_peer) { + r = sd_netlink_message_append_string(m, IFLA_IFNAME, v->ifname_peer); + if (r < 0) + return log_error_errno(r, "Failed to add vxcan netlink interface peer name: %m"); + } + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append VXCAN_INFO_PEER attribute: %m"); + + return r; +} + +static int netdev_vxcan_verify(NetDev *netdev, const char *filename) { + VxCan *v; + + assert(netdev); + assert(filename); + + v = VXCAN(netdev); + + assert(v); + + if (!v->ifname_peer) { + log_warning("VxCan NetDev without peer name configured in %s. Ignoring", filename); + return -EINVAL; + } + + return 0; +} + +static void vxcan_done(NetDev *n) { + VxCan *v; + + assert(n); + + v = VXCAN(n); + + assert(v); + + free(v->ifname_peer); +} + +const NetDevVTable vxcan_vtable = { + .object_size = sizeof(VxCan), + .sections = "Match\0NetDev\0VXCAN\0", + .done = vxcan_done, + .fill_message_create = netdev_vxcan_fill_message_create, + .create_type = NETDEV_CREATE_INDEPENDENT, + .config_verify = netdev_vxcan_verify, + .generate_mac = true, +}; diff --git a/src/network/netdev/vxcan.h b/src/network/netdev/vxcan.h new file mode 100644 index 00000000..4531a673 --- /dev/null +++ b/src/network/netdev/vxcan.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct VxCan VxCan; + +#include "netdev.h" + +struct VxCan { + NetDev meta; + + char *ifname_peer; +}; + +DEFINE_NETDEV_CAST(VXCAN, VxCan); + +extern const NetDevVTable vxcan_vtable; diff --git a/src/network/netdev/vxlan.c b/src/network/netdev/vxlan.c new file mode 100644 index 00000000..92f6005d --- /dev/null +++ b/src/network/netdev/vxlan.c @@ -0,0 +1,379 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "conf-parser.h" +#include "alloc-util.h" +#include "extract-word.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "parse-util.h" +#include "vxlan.h" + +static const char* const df_table[_NETDEV_VXLAN_DF_MAX] = { + [NETDEV_VXLAN_DF_NO] = "no", + [NETDEV_VXLAN_DF_YES] = "yes", + [NETDEV_VXLAN_DF_INHERIT] = "inherit", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(df, VxLanDF, NETDEV_VXLAN_DF_YES); +DEFINE_CONFIG_PARSE_ENUM(config_parse_df, df, VxLanDF, "Failed to parse VXLAN IPDoNotFragment= setting"); + +static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + VxLan *v; + int r; + + assert(netdev); + assert(link); + assert(m); + + v = VXLAN(netdev); + + assert(v); + + if (v->vni <= VXLAN_VID_MAX) { + r = sd_netlink_message_append_u32(m, IFLA_VXLAN_ID, v->vni); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_ID attribute: %m"); + } + + if (in_addr_is_null(v->remote_family, &v->remote) == 0) { + if (v->remote_family == AF_INET) + r = sd_netlink_message_append_in_addr(m, IFLA_VXLAN_GROUP, &v->remote.in); + else + r = sd_netlink_message_append_in6_addr(m, IFLA_VXLAN_GROUP6, &v->remote.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GROUP attribute: %m"); + } + + if (in_addr_is_null(v->local_family, &v->local) == 0) { + if (v->local_family == AF_INET) + r = sd_netlink_message_append_in_addr(m, IFLA_VXLAN_LOCAL, &v->local.in); + else + r = sd_netlink_message_append_in6_addr(m, IFLA_VXLAN_LOCAL6, &v->local.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LOCAL attribute: %m"); + } + + r = sd_netlink_message_append_u32(m, IFLA_VXLAN_LINK, link->ifindex); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LINK attribute: %m"); + + if (v->inherit) { + r = sd_netlink_message_append_flag(m, IFLA_VXLAN_TTL_INHERIT); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TTL_INHERIT attribute: %m"); + } else { + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_TTL, v->ttl); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TTL attribute: %m"); + } + + if (v->tos != 0) { + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_TOS, v->tos); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TOS attribute: %m"); + } + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_LEARNING, v->learning); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LEARNING attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_RSC, v->route_short_circuit); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_RSC attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_PROXY, v->arp_proxy); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PROXY attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_L2MISS, v->l2miss); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_L2MISS attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_L3MISS, v->l3miss); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_L3MISS attribute: %m"); + + if (v->fdb_ageing != 0) { + r = sd_netlink_message_append_u32(m, IFLA_VXLAN_AGEING, v->fdb_ageing / USEC_PER_SEC); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_AGEING attribute: %m"); + } + + if (v->max_fdb != 0) { + r = sd_netlink_message_append_u32(m, IFLA_VXLAN_LIMIT, v->max_fdb); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LIMIT attribute: %m"); + } + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_UDP_CSUM, v->udpcsum); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_CSUM attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_TX attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_REMCSUM_TX, v->remote_csum_tx); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_REMCSUM_TX attribute: %m"); + + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_REMCSUM_RX, v->remote_csum_rx); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_REMCSUM_RX attribute: %m"); + + r = sd_netlink_message_append_u16(m, IFLA_VXLAN_PORT, htobe16(v->dest_port)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT attribute: %m"); + + if (v->port_range.low != 0 || v->port_range.high != 0) { + struct ifla_vxlan_port_range port_range; + + port_range.low = htobe16(v->port_range.low); + port_range.high = htobe16(v->port_range.high); + + r = sd_netlink_message_append_data(m, IFLA_VXLAN_PORT_RANGE, &port_range, sizeof(port_range)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT_RANGE attribute: %m"); + } + + r = sd_netlink_message_append_u32(m, IFLA_VXLAN_LABEL, htobe32(v->flow_label)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LABEL attribute: %m"); + + if (v->group_policy) { + r = sd_netlink_message_append_flag(m, IFLA_VXLAN_GBP); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GBP attribute: %m"); + } + + if (v->generic_protocol_extension) { + r = sd_netlink_message_append_flag(m, IFLA_VXLAN_GPE); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GPE attribute: %m"); + } + + if (v->df != _NETDEV_VXLAN_DF_INVALID) { + r = sd_netlink_message_append_u8(m, IFLA_VXLAN_DF, v->df); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_DF attribute: %m"); + } + + return r; +} + +int config_parse_vxlan_address(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + VxLan *v = userdata; + union in_addr_union *addr = data, buffer; + int r, f; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = in_addr_from_string_auto(rvalue, &f, &buffer); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "vxlan '%s' address is invalid, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + r = in_addr_is_multicast(f, &buffer); + + if (streq(lvalue, "Group")) { + if (r <= 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "vxlan %s invalid multicast address, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + v->group_family = f; + } else { + if (r > 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "vxlan %s cannot be a multicast address, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + if (streq(lvalue, "Remote")) + v->remote_family = f; + else + v->local_family = f; + } + + *addr = buffer; + + return 0; +} + +int config_parse_port_range(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + VxLan *v = userdata; + uint16_t low, high; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_ip_port_range(rvalue, &low, &high); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse VXLAN port range '%s'. Port should be greater than 0 and less than 65535.", rvalue); + return 0; + } + + v->port_range.low = low; + v->port_range.high = high; + + return 0; +} + +int config_parse_flow_label(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + VxLan *v = userdata; + unsigned f; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou(rvalue, &f); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN flow label '%s'.", rvalue); + return 0; + } + + if (f & ~VXLAN_FLOW_LABEL_MAX_MASK) { + log_syntax(unit, LOG_ERR, filename, line, r, + "VXLAN flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue); + return 0; + } + + v->flow_label = f; + + return 0; +} + +int config_parse_vxlan_ttl(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + VxLan *v = userdata; + unsigned f; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(rvalue, "inherit")) + v->inherit = true; + else { + r = safe_atou(rvalue, &f); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse VXLAN TTL '%s', ignoring assignment: %m", rvalue); + return 0; + } + + if (f > 255) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid VXLAN TTL '%s'. TTL must be <= 255. Ignoring assignment.", rvalue); + return 0; + } + + v->ttl = f; + } + + return 0; +} + +static int netdev_vxlan_verify(NetDev *netdev, const char *filename) { + VxLan *v = VXLAN(netdev); + + assert(netdev); + assert(v); + assert(filename); + + if (v->vni > VXLAN_VID_MAX) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: VXLAN without valid VNI (or VXLAN Segment ID) configured. Ignoring.", + filename); + + if (v->ttl > 255) + return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: VXLAN TTL must be <= 255. Ignoring.", + filename); + + if (!v->dest_port && v->generic_protocol_extension) + v->dest_port = 4790; + + return 0; +} + +static void vxlan_init(NetDev *netdev) { + VxLan *v; + + assert(netdev); + + v = VXLAN(netdev); + + assert(v); + + v->vni = VXLAN_VID_MAX + 1; + v->df = _NETDEV_VXLAN_DF_INVALID; + v->learning = true; + v->udpcsum = false; + v->udp6zerocsumtx = false; + v->udp6zerocsumrx = false; +} + +const NetDevVTable vxlan_vtable = { + .object_size = sizeof(VxLan), + .init = vxlan_init, + .sections = "Match\0NetDev\0VXLAN\0", + .fill_message_create = netdev_vxlan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_vxlan_verify, + .generate_mac = true, +}; diff --git a/src/network/netdev/vxlan.h b/src/network/netdev/vxlan.h new file mode 100644 index 00000000..cf8ae884 --- /dev/null +++ b/src/network/netdev/vxlan.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct VxLan VxLan; + +#include + +#include "in-addr-util.h" +#include "netdev.h" + +#define VXLAN_VID_MAX (1u << 24) - 1 +#define VXLAN_FLOW_LABEL_MAX_MASK 0xFFFFFU + +typedef enum VxLanDF { + NETDEV_VXLAN_DF_NO = VXLAN_DF_UNSET, + NETDEV_VXLAN_DF_YES = VXLAN_DF_SET, + NETDEV_VXLAN_DF_INHERIT = VXLAN_DF_INHERIT, + _NETDEV_VXLAN_DF_MAX, + _NETDEV_VXLAN_DF_INVALID = -1 +} VxLanDF; + +struct VxLan { + NetDev meta; + + uint32_t vni; + + int remote_family; + int local_family; + int group_family; + + VxLanDF df; + + union in_addr_union remote; + union in_addr_union local; + union in_addr_union group; + + unsigned tos; + unsigned ttl; + unsigned max_fdb; + unsigned flow_label; + + uint16_t dest_port; + + usec_t fdb_ageing; + + bool learning; + bool arp_proxy; + bool route_short_circuit; + bool l2miss; + bool l3miss; + bool udpcsum; + bool udp6zerocsumtx; + bool udp6zerocsumrx; + bool remote_csum_tx; + bool remote_csum_rx; + bool group_policy; + bool generic_protocol_extension; + bool inherit; + + struct ifla_vxlan_port_range port_range; +}; + +DEFINE_NETDEV_CAST(VXLAN, VxLan); +extern const NetDevVTable vxlan_vtable; + +const char *df_to_string(VxLanDF d) _const_; +VxLanDF df_from_string(const char *d) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_vxlan_address); +CONFIG_PARSER_PROTOTYPE(config_parse_port_range); +CONFIG_PARSER_PROTOTYPE(config_parse_flow_label); +CONFIG_PARSER_PROTOTYPE(config_parse_df); +CONFIG_PARSER_PROTOTYPE(config_parse_vxlan_ttl); diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c new file mode 100644 index 00000000..4a122858 --- /dev/null +++ b/src/network/netdev/wireguard.c @@ -0,0 +1,977 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2015-2017 Jason A. Donenfeld . All Rights Reserved. +***/ + +#include +#include + +#include "sd-resolve.h" + +#include "alloc-util.h" +#include "event-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "hexdecoct.h" +#include "memory-util.h" +#include "netlink-util.h" +#include "networkd-manager.h" +#include "networkd-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "resolve-private.h" +#include "string-util.h" +#include "strv.h" +#include "wireguard.h" + +static void resolve_endpoints(NetDev *netdev); + +static void wireguard_peer_free(WireguardPeer *peer) { + WireguardIPmask *mask; + + if (!peer) + return; + + if (peer->wireguard) { + LIST_REMOVE(peers, peer->wireguard->peers, peer); + + set_remove(peer->wireguard->peers_with_unresolved_endpoint, peer); + set_remove(peer->wireguard->peers_with_failed_endpoint, peer); + + if (peer->section) + hashmap_remove(peer->wireguard->peers_by_section, peer->section); + } + + network_config_section_free(peer->section); + + while ((mask = peer->ipmasks)) { + LIST_REMOVE(ipmasks, peer->ipmasks, mask); + free(mask); + } + + free(peer->endpoint_host); + free(peer->endpoint_port); + free(peer->preshared_key_file); + explicit_bzero_safe(peer->preshared_key, WG_KEY_LEN); + + free(peer); +} + +DEFINE_NETWORK_SECTION_FUNCTIONS(WireguardPeer, wireguard_peer_free); + +static int wireguard_peer_new_static(Wireguard *w, const char *filename, unsigned section_line, WireguardPeer **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(wireguard_peer_freep) WireguardPeer *peer = NULL; + int r; + + assert(w); + assert(ret); + assert(filename); + assert(section_line > 0); + + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + peer = hashmap_get(w->peers_by_section, n); + if (peer) { + *ret = TAKE_PTR(peer); + return 0; + } + + peer = new(WireguardPeer, 1); + if (!peer) + return -ENOMEM; + + *peer = (WireguardPeer) { + .flags = WGPEER_F_REPLACE_ALLOWEDIPS, + .wireguard = w, + .section = TAKE_PTR(n), + }; + + LIST_PREPEND(peers, w->peers, peer); + + r = hashmap_ensure_allocated(&w->peers_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(w->peers_by_section, peer->section, peer); + if (r < 0) + return r; + + *ret = TAKE_PTR(peer); + return 0; +} + +static int wireguard_set_ipmask_one(NetDev *netdev, sd_netlink_message *message, const WireguardIPmask *mask, uint16_t index) { + int r; + + assert(message); + assert(mask); + assert(index > 0); + + /* This returns 1 on success, 0 on recoverable error, and negative errno on failure. */ + + r = sd_netlink_message_open_array(message, index); + if (r < 0) + return 0; + + r = sd_netlink_message_append_u16(message, WGALLOWEDIP_A_FAMILY, mask->family); + if (r < 0) + goto cancel; + + r = netlink_message_append_in_addr_union(message, WGALLOWEDIP_A_IPADDR, mask->family, &mask->ip); + if (r < 0) + goto cancel; + + r = sd_netlink_message_append_u8(message, WGALLOWEDIP_A_CIDR_MASK, mask->cidr); + if (r < 0) + goto cancel; + + r = sd_netlink_message_close_container(message); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not add wireguard allowed ip: %m"); + + return 1; + +cancel: + r = sd_netlink_message_cancel_array(message); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not cancel wireguard allowed ip message attribute: %m"); + + return 0; +} + +static int wireguard_set_peer_one(NetDev *netdev, sd_netlink_message *message, const WireguardPeer *peer, uint16_t index, WireguardIPmask **mask_start) { + WireguardIPmask *mask, *start; + uint16_t j = 0; + int r; + + assert(message); + assert(peer); + assert(index > 0); + assert(mask_start); + + /* This returns 1 on success, 0 on recoverable error, and negative errno on failure. */ + + start = *mask_start ?: peer->ipmasks; + + r = sd_netlink_message_open_array(message, index); + if (r < 0) + return 0; + + r = sd_netlink_message_append_data(message, WGPEER_A_PUBLIC_KEY, &peer->public_key, sizeof(peer->public_key)); + if (r < 0) + goto cancel; + + if (!*mask_start) { + r = sd_netlink_message_append_data(message, WGPEER_A_PRESHARED_KEY, &peer->preshared_key, WG_KEY_LEN); + if (r < 0) + goto cancel; + + r = sd_netlink_message_append_u32(message, WGPEER_A_FLAGS, peer->flags); + if (r < 0) + goto cancel; + + r = sd_netlink_message_append_u16(message, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, peer->persistent_keepalive_interval); + if (r < 0) + goto cancel; + + if (IN_SET(peer->endpoint.sa.sa_family, AF_INET, AF_INET6)) { + r = netlink_message_append_sockaddr_union(message, WGPEER_A_ENDPOINT, &peer->endpoint); + if (r < 0) + goto cancel; + } + } + + r = sd_netlink_message_open_container(message, WGPEER_A_ALLOWEDIPS); + if (r < 0) + goto cancel; + + LIST_FOREACH(ipmasks, mask, start) { + r = wireguard_set_ipmask_one(netdev, message, mask, ++j); + if (r < 0) + return r; + if (r == 0) + break; + } + + r = sd_netlink_message_close_container(message); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not add wireguard allowed ip: %m"); + + r = sd_netlink_message_close_container(message); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not add wireguard peer: %m"); + + *mask_start = mask; /* Start next cycle from this mask. */ + return !mask; + +cancel: + r = sd_netlink_message_cancel_array(message); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not cancel wireguard peers: %m"); + + return 0; +} + +static int wireguard_set_interface(NetDev *netdev) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; + WireguardIPmask *mask_start = NULL; + WireguardPeer *peer, *peer_start; + uint32_t serial; + Wireguard *w; + int r; + + assert(netdev); + w = WIREGUARD(netdev); + assert(w); + + for (peer_start = w->peers; peer_start; ) { + uint16_t i = 0; + + message = sd_netlink_message_unref(message); + + r = sd_genl_message_new(netdev->manager->genl, SD_GENL_WIREGUARD, WG_CMD_SET_DEVICE, &message); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m"); + + r = sd_netlink_message_append_string(message, WGDEVICE_A_IFNAME, netdev->ifname); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append wireguard interface name: %m"); + + if (peer_start == w->peers) { + r = sd_netlink_message_append_data(message, WGDEVICE_A_PRIVATE_KEY, &w->private_key, WG_KEY_LEN); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append wireguard private key: %m"); + + r = sd_netlink_message_append_u16(message, WGDEVICE_A_LISTEN_PORT, w->port); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append wireguard port: %m"); + + r = sd_netlink_message_append_u32(message, WGDEVICE_A_FWMARK, w->fwmark); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append wireguard fwmark: %m"); + + r = sd_netlink_message_append_u32(message, WGDEVICE_A_FLAGS, w->flags); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append wireguard flags: %m"); + } + + r = sd_netlink_message_open_container(message, WGDEVICE_A_PEERS); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append wireguard peer attributes: %m"); + + LIST_FOREACH(peers, peer, peer_start) { + r = wireguard_set_peer_one(netdev, message, peer, ++i, &mask_start); + if (r < 0) + return r; + if (r == 0) + break; + } + peer_start = peer; /* Start next cycle from this peer. */ + + r = sd_netlink_message_close_container(message); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not close wireguard container: %m"); + + r = sd_netlink_send(netdev->manager->genl, message, &serial); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not set wireguard device: %m"); + } + + return 0; +} + +static void wireguard_peer_destroy_callback(WireguardPeer *peer) { + NetDev *netdev; + + assert(peer); + assert(peer->wireguard); + + netdev = NETDEV(peer->wireguard); + + if (section_is_invalid(peer->section)) + wireguard_peer_free(peer); + + netdev_unref(netdev); +} + +static int on_resolve_retry(sd_event_source *s, usec_t usec, void *userdata) { + NetDev *netdev = userdata; + Wireguard *w; + + assert(netdev); + w = WIREGUARD(netdev); + assert(w); + + if (!netdev_is_managed(netdev)) + return 0; + + assert(set_isempty(w->peers_with_unresolved_endpoint)); + + SWAP_TWO(w->peers_with_unresolved_endpoint, w->peers_with_failed_endpoint); + + resolve_endpoints(netdev); + + return 0; +} + +/* + * Given the number of retries this function will return will an exponential + * increasing time in milliseconds to wait starting at 200ms and capped at 25 seconds. + */ +static int exponential_backoff_milliseconds(unsigned n_retries) { + return (2 << MIN(n_retries, 7U)) * 100 * USEC_PER_MSEC; +} + +static int wireguard_resolve_handler(sd_resolve_query *q, + int ret, + const struct addrinfo *ai, + WireguardPeer *peer) { + NetDev *netdev; + Wireguard *w; + int r; + + assert(peer); + assert(peer->wireguard); + + w = peer->wireguard; + netdev = NETDEV(w); + + if (!netdev_is_managed(netdev)) + return 0; + + if (ret != 0) { + log_netdev_error(netdev, "Failed to resolve host '%s:%s': %s", peer->endpoint_host, peer->endpoint_port, gai_strerror(ret)); + + r = set_ensure_allocated(&w->peers_with_failed_endpoint, NULL); + if (r < 0) { + log_oom(); + peer->section->invalid = true; + goto resolve_next; + } + + r = set_put(w->peers_with_failed_endpoint, peer); + if (r < 0) { + log_netdev_error(netdev, "Failed to save a peer, dropping the peer: %m"); + peer->section->invalid = true; + goto resolve_next; + } + + } else if ((ai->ai_family == AF_INET && ai->ai_addrlen == sizeof(struct sockaddr_in)) || + (ai->ai_family == AF_INET6 && ai->ai_addrlen == sizeof(struct sockaddr_in6))) + memcpy(&peer->endpoint, ai->ai_addr, ai->ai_addrlen); + else + log_netdev_error(netdev, "Neither IPv4 nor IPv6 address found for peer endpoint %s:%s, ignoring the address.", + peer->endpoint_host, peer->endpoint_port); + +resolve_next: + if (!set_isempty(w->peers_with_unresolved_endpoint)) { + resolve_endpoints(netdev); + return 0; + } + + (void) wireguard_set_interface(netdev); + + if (!set_isempty(w->peers_with_failed_endpoint)) { + usec_t usec; + + w->n_retries++; + usec = usec_add(now(CLOCK_MONOTONIC), exponential_backoff_milliseconds(w->n_retries)); + r = event_reset_time(netdev->manager->event, &w->resolve_retry_event_source, + CLOCK_MONOTONIC, usec, 0, on_resolve_retry, netdev, + 0, "wireguard-resolve-retry", true); + if (r < 0) { + log_netdev_warning_errno(netdev, r, "Could not arm resolve retry handler: %m"); + return 0; + } + } + + return 0; +} + +static void resolve_endpoints(NetDev *netdev) { + static const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_DGRAM, + .ai_protocol = IPPROTO_UDP + }; + WireguardPeer *peer; + Wireguard *w; + Iterator i; + int r; + + assert(netdev); + w = WIREGUARD(netdev); + assert(w); + + SET_FOREACH(peer, w->peers_with_unresolved_endpoint, i) { + r = resolve_getaddrinfo(netdev->manager->resolve, + NULL, + peer->endpoint_host, + peer->endpoint_port, + &hints, + wireguard_resolve_handler, + wireguard_peer_destroy_callback, + peer); + if (r == -ENOBUFS) + break; + if (r < 0) { + log_netdev_error_errno(netdev, r, "Failed to create resolver: %m"); + continue; + } + + /* Avoid freeing netdev. It will be unrefed by the destroy callback. */ + netdev_ref(netdev); + + (void) set_remove(w->peers_with_unresolved_endpoint, peer); + } +} + +static int netdev_wireguard_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + assert(netdev); + assert(WIREGUARD(netdev)); + + (void) wireguard_set_interface(netdev); + resolve_endpoints(netdev); + return 0; +} + +int config_parse_wireguard_listen_port( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint16_t *s = data; + int r; + + assert(rvalue); + assert(data); + + if (isempty(rvalue) || streq(rvalue, "auto")) { + *s = 0; + return 0; + } + + r = parse_ip_port(rvalue, s); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid port specification, ignoring assignment: %s", rvalue); + return 0; + } + + return 0; +} + +static int wireguard_decode_key_and_warn( + const char *rvalue, + uint8_t ret[static WG_KEY_LEN], + const char *unit, + const char *filename, + unsigned line, + const char *lvalue) { + + _cleanup_(erase_and_freep) void *key = NULL; + size_t len; + int r; + + assert(rvalue); + assert(ret); + assert(filename); + assert(lvalue); + + if (isempty(rvalue)) { + memzero(ret, WG_KEY_LEN); + return 0; + } + + if (!streq(lvalue, "PublicKey")) + (void) warn_file_is_world_accessible(filename, NULL, unit, line); + + r = unbase64mem_full(rvalue, strlen(rvalue), true, &key, &len); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to decode wireguard key provided by %s=, ignoring assignment: %m", lvalue); + if (len != WG_KEY_LEN) + return log_syntax(unit, LOG_ERR, filename, line, 0, + "Wireguard key provided by %s= has invalid length (%zu bytes), ignoring assignment.", + lvalue, len); + + memcpy(ret, key, WG_KEY_LEN); + return 0; +} + +int config_parse_wireguard_private_key( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Wireguard *w; + + assert(data); + w = WIREGUARD(data); + assert(w); + + (void) wireguard_decode_key_and_warn(rvalue, w->private_key, unit, filename, line, lvalue); + return 0; +} + +int config_parse_wireguard_private_key_file( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *path = NULL; + Wireguard *w; + + assert(data); + w = WIREGUARD(data); + assert(w); + + if (isempty(rvalue)) { + w->private_key_file = mfree(w->private_key_file); + return 0; + } + + path = strdup(rvalue); + if (!path) + return log_oom(); + + if (path_simplify_and_warn(path, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue) < 0) + return 0; + + return free_and_replace(w->private_key_file, path); +} + +int config_parse_wireguard_preshared_key( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; + Wireguard *w; + int r; + + assert(data); + w = WIREGUARD(data); + assert(w); + + r = wireguard_peer_new_static(w, filename, section_line, &peer); + if (r < 0) + return r; + + r = wireguard_decode_key_and_warn(rvalue, peer->preshared_key, unit, filename, line, lvalue); + if (r < 0) + return r; + + TAKE_PTR(peer); + return 0; +} + +int config_parse_wireguard_preshared_key_file( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; + _cleanup_free_ char *path = NULL; + Wireguard *w; + int r; + + assert(data); + w = WIREGUARD(data); + assert(w); + + r = wireguard_peer_new_static(w, filename, section_line, &peer); + if (r < 0) + return r; + + if (isempty(rvalue)) { + peer->preshared_key_file = mfree(peer->preshared_key_file); + TAKE_PTR(peer); + return 0; + } + + path = strdup(rvalue); + if (!path) + return log_oom(); + + if (path_simplify_and_warn(path, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue) < 0) + return 0; + + free_and_replace(peer->preshared_key_file, path); + TAKE_PTR(peer); + return 0; +} + +int config_parse_wireguard_public_key( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; + Wireguard *w; + int r; + + assert(data); + w = WIREGUARD(data); + assert(w); + + r = wireguard_peer_new_static(w, filename, section_line, &peer); + if (r < 0) + return r; + + r = wireguard_decode_key_and_warn(rvalue, peer->public_key, unit, filename, line, lvalue); + if (r < 0) + return r; + + TAKE_PTR(peer); + return 0; +} + +int config_parse_wireguard_allowed_ips( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; + union in_addr_union addr; + unsigned char prefixlen; + int r, family; + Wireguard *w; + WireguardIPmask *ipmask; + + assert(rvalue); + assert(data); + + w = WIREGUARD(data); + assert(w); + + r = wireguard_peer_new_static(w, filename, section_line, &peer); + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&rvalue, &word, "," WHITESPACE, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to split allowed ips \"%s\" option: %m", rvalue); + break; + } + + r = in_addr_prefix_from_string_auto(word, &family, &addr, &prefixlen); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Network address is invalid, ignoring assignment: %s", word); + continue; + } + + ipmask = new(WireguardIPmask, 1); + if (!ipmask) + return log_oom(); + + *ipmask = (WireguardIPmask) { + .family = family, + .ip.in6 = addr.in6, + .cidr = prefixlen, + }; + + LIST_PREPEND(ipmasks, peer->ipmasks, ipmask); + } + + TAKE_PTR(peer); + return 0; +} + +int config_parse_wireguard_endpoint( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; + const char *begin, *end; + Wireguard *w; + size_t len; + int r; + + assert(data); + assert(rvalue); + + w = WIREGUARD(data); + assert(w); + + r = wireguard_peer_new_static(w, filename, section_line, &peer); + if (r < 0) + return r; + + if (rvalue[0] == '[') { + begin = &rvalue[1]; + end = strchr(rvalue, ']'); + if (!end) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Unable to find matching brace of endpoint, ignoring assignment: %s", + rvalue); + return 0; + } + len = end - begin; + ++end; + if (*end != ':' || !*(end + 1)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Unable to find port of endpoint, ignoring assignment: %s", + rvalue); + return 0; + } + ++end; + } else { + begin = rvalue; + end = strrchr(rvalue, ':'); + if (!end || !*(end + 1)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Unable to find port of endpoint, ignoring assignment: %s", + rvalue); + return 0; + } + len = end - begin; + ++end; + } + + r = free_and_strndup(&peer->endpoint_host, begin, len); + if (r < 0) + return log_oom(); + + r = free_and_strdup(&peer->endpoint_port, end); + if (r < 0) + return log_oom(); + + r = set_ensure_allocated(&w->peers_with_unresolved_endpoint, NULL); + if (r < 0) + return log_oom(); + + r = set_put(w->peers_with_unresolved_endpoint, peer); + if (r < 0) + return r; + + TAKE_PTR(peer); + return 0; +} + +int config_parse_wireguard_keepalive( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(wireguard_peer_free_or_set_invalidp) WireguardPeer *peer = NULL; + uint16_t keepalive = 0; + Wireguard *w; + int r; + + assert(rvalue); + assert(data); + + w = WIREGUARD(data); + assert(w); + + r = wireguard_peer_new_static(w, filename, section_line, &peer); + if (r < 0) + return r; + + if (streq(rvalue, "off")) + keepalive = 0; + else { + r = safe_atou16(rvalue, &keepalive); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "The persistent keepalive interval must be 0-65535. Ignore assignment: %s", + rvalue); + return 0; + } + } + + peer->persistent_keepalive_interval = keepalive; + + TAKE_PTR(peer); + return 0; +} + +static void wireguard_init(NetDev *netdev) { + Wireguard *w; + + assert(netdev); + w = WIREGUARD(netdev); + assert(w); + + w->flags = WGDEVICE_F_REPLACE_PEERS; +} + +static void wireguard_done(NetDev *netdev) { + Wireguard *w; + + assert(netdev); + w = WIREGUARD(netdev); + assert(w); + + sd_event_source_unref(w->resolve_retry_event_source); + + explicit_bzero_safe(w->private_key, WG_KEY_LEN); + free(w->private_key_file); + + hashmap_free_with_destructor(w->peers_by_section, wireguard_peer_free); + set_free(w->peers_with_unresolved_endpoint); + set_free(w->peers_with_failed_endpoint); +} + +static int wireguard_read_key_file(const char *filename, uint8_t dest[static WG_KEY_LEN]) { + _cleanup_(erase_and_freep) char *key = NULL; + size_t key_len; + int r; + + if (!filename) + return 0; + + assert(dest); + + (void) warn_file_is_world_accessible(filename, NULL, NULL, 0); + + r = read_full_file_full(filename, READ_FULL_FILE_SECURE | READ_FULL_FILE_UNBASE64, &key, &key_len); + if (r < 0) + return r; + + if (key_len != WG_KEY_LEN) + return -EINVAL; + + memcpy(dest, key, WG_KEY_LEN); + return 0; +} + +static int wireguard_peer_verify(WireguardPeer *peer) { + NetDev *netdev = NETDEV(peer->wireguard); + int r; + + if (section_is_invalid(peer->section)) + return -EINVAL; + + if (eqzero(peer->public_key)) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: WireGuardPeer section without PublicKey= configured. " + "Ignoring [WireGuardPeer] section from line %u.", + peer->section->filename, peer->section->line); + + r = wireguard_read_key_file(peer->preshared_key_file, peer->preshared_key); + if (r < 0) + return log_netdev_error_errno(netdev, r, + "%s: Failed to read preshared key from '%s'. " + "Ignoring [WireGuardPeer] section from line %u.", + peer->section->filename, peer->preshared_key_file, + peer->section->line); + + return 0; +} + +static int wireguard_verify(NetDev *netdev, const char *filename) { + WireguardPeer *peer, *peer_next; + Wireguard *w; + int r; + + assert(netdev); + w = WIREGUARD(netdev); + assert(w); + + r = wireguard_read_key_file(w->private_key_file, w->private_key); + if (r < 0) + return log_netdev_error_errno(netdev, r, + "Failed to read private key from %s. Dropping network device %s.", + w->private_key_file, netdev->ifname); + + if (eqzero(w->private_key)) + return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), + "%s: Missing PrivateKey= or PrivateKeyFile=, " + "Dropping network device %s.", + filename, netdev->ifname); + + LIST_FOREACH_SAFE(peers, peer, peer_next, w->peers) + if (wireguard_peer_verify(peer) < 0) + wireguard_peer_free(peer); + + return 0; +} + +const NetDevVTable wireguard_vtable = { + .object_size = sizeof(Wireguard), + .sections = "Match\0NetDev\0WireGuard\0WireGuardPeer\0", + .post_create = netdev_wireguard_post_create, + .init = wireguard_init, + .done = wireguard_done, + .create_type = NETDEV_CREATE_INDEPENDENT, + .config_verify = wireguard_verify, + .generate_mac = true, +}; diff --git a/src/network/netdev/wireguard.h b/src/network/netdev/wireguard.h new file mode 100644 index 00000000..ce336c98 --- /dev/null +++ b/src/network/netdev/wireguard.h @@ -0,0 +1,70 @@ +#pragma once + +typedef struct Wireguard Wireguard; + +#include +#include + +#include "in-addr-util.h" +#include "netdev.h" +#include "socket-util.h" + +typedef struct WireguardIPmask { + uint16_t family; + union in_addr_union ip; + uint8_t cidr; + + LIST_FIELDS(struct WireguardIPmask, ipmasks); +} WireguardIPmask; + +typedef struct WireguardPeer { + Wireguard *wireguard; + NetworkConfigSection *section; + + uint8_t public_key[WG_KEY_LEN]; + uint8_t preshared_key[WG_KEY_LEN]; + char *preshared_key_file; + uint32_t flags; + uint16_t persistent_keepalive_interval; + + union sockaddr_union endpoint; + char *endpoint_host; + char *endpoint_port; + + LIST_HEAD(WireguardIPmask, ipmasks); + LIST_FIELDS(struct WireguardPeer, peers); +} WireguardPeer; + +struct Wireguard { + NetDev meta; + unsigned last_peer_section; + + uint32_t flags; + uint8_t private_key[WG_KEY_LEN]; + char *private_key_file; + uint16_t port; + uint32_t fwmark; + + Hashmap *peers_by_section; + Set *peers_with_unresolved_endpoint; + Set *peers_with_failed_endpoint; + + LIST_HEAD(WireguardPeer, peers); + + unsigned n_retries; + sd_event_source *resolve_retry_event_source; +}; + +DEFINE_NETDEV_CAST(WIREGUARD, Wireguard); +extern const NetDevVTable wireguard_vtable; + +CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_allowed_ips); +CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_endpoint); +CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_listen_port); + +CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_public_key); +CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key); +CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_private_key_file); +CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_preshared_key); +CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_preshared_key_file); +CONFIG_PARSER_PROTOTYPE(config_parse_wireguard_keepalive); diff --git a/src/network/netdev/xfrm.c b/src/network/netdev/xfrm.c new file mode 100644 index 00000000..7157af4d --- /dev/null +++ b/src/network/netdev/xfrm.c @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "missing_network.h" +#include "xfrm.h" + +static int xfrm_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *message) { + Xfrm *x; + int r; + + assert(netdev); + assert(message); + + x = XFRM(netdev); + + assert(link || x->independent); + + r = sd_netlink_message_append_u32(message, IFLA_XFRM_LINK, link ? link->ifindex : LOOPBACK_IFINDEX); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_XFRM_LINK: %m"); + + r = sd_netlink_message_append_u32(message, IFLA_XFRM_IF_ID, x->if_id); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_XFRM_IF_ID: %m"); + + return 0; +} + +const NetDevVTable xfrm_vtable = { + .object_size = sizeof(Xfrm), + .sections = "Match\0NetDev\0Xfrm\0", + .fill_message_create = xfrm_fill_message_create, + .create_type = NETDEV_CREATE_STACKED +}; diff --git a/src/network/netdev/xfrm.h b/src/network/netdev/xfrm.h new file mode 100644 index 00000000..889d3619 --- /dev/null +++ b/src/network/netdev/xfrm.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "netdev.h" + +typedef struct Xfrm { + NetDev meta; + + uint32_t if_id; + bool independent; +} Xfrm; + +DEFINE_NETDEV_CAST(XFRM, Xfrm); +extern const NetDevVTable xfrm_vtable; diff --git a/src/network/networkctl.c b/src/network/networkctl.c new file mode 100644 index 00000000..78035a84 --- /dev/null +++ b/src/network/networkctl.c @@ -0,0 +1,2017 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-device.h" +#include "sd-hwdb.h" +#include "sd-lldp.h" +#include "sd-netlink.h" +#include "sd-network.h" + +#include "alloc-util.h" +#include "arphrd-list.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-util.h" +#include "device-util.h" +#include "escape.h" +#include "ether-addr-util.h" +#include "ethtool-util.h" +#include "fd-util.h" +#include "format-table.h" +#include "format-util.h" +#include "hwdb-util.h" +#include "local-addresses.h" +#include "locale-util.h" +#include "macro.h" +#include "main-func.h" +#include "netlink-util.h" +#include "pager.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "set.h" +#include "socket-util.h" +#include "sort-util.h" +#include "sparse-endian.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "strxcpyx.h" +#include "terminal-util.h" +#include "verbs.h" +#include "wifi-util.h" + +/* Kernel defines MODULE_NAME_LEN as 64 - sizeof(unsigned long). So, 64 is enough. */ +#define NETDEV_KIND_MAX 64 + +/* use 128 kB for receive socket kernel queue, we shouldn't need more here */ +#define RCVBUF_SIZE (128*1024) + +static PagerFlags arg_pager_flags = 0; +static bool arg_legend = true; +static bool arg_all = false; +static bool arg_stats = false; + +static char *link_get_type_string(unsigned short iftype, sd_device *d) { + const char *t, *devtype; + char *p; + + if (d && + sd_device_get_devtype(d, &devtype) >= 0 && + !isempty(devtype)) + return strdup(devtype); + + t = arphrd_to_name(iftype); + if (!t) + return NULL; + + p = strdup(t); + if (!p) + return NULL; + + ascii_strlower(p); + return p; +} + +static void operational_state_to_color(const char *name, const char *state, const char **on, const char **off) { + assert(on); + assert(off); + + if (STRPTR_IN_SET(state, "routable", "enslaved") || + (streq_ptr(name, "lo") && streq_ptr(state, "carrier"))) { + *on = ansi_highlight_green(); + *off = ansi_normal(); + } else if (streq_ptr(state, "degraded")) { + *on = ansi_highlight_yellow(); + *off = ansi_normal(); + } else + *on = *off = ""; +} + +static void setup_state_to_color(const char *state, const char **on, const char **off) { + assert(on); + assert(off); + + if (streq_ptr(state, "configured")) { + *on = ansi_highlight_green(); + *off = ansi_normal(); + } else if (streq_ptr(state, "configuring")) { + *on = ansi_highlight_yellow(); + *off = ansi_normal(); + } else if (STRPTR_IN_SET(state, "failed", "linger")) { + *on = ansi_highlight_red(); + *off = ansi_normal(); + } else + *on = *off = ""; +} + +typedef struct VxLanInfo { + uint32_t vni; + uint32_t link; + + int local_family; + int group_family; + + union in_addr_union local; + union in_addr_union group; + + uint16_t dest_port; + +} VxLanInfo; + +typedef struct LinkInfo { + char name[IFNAMSIZ+1]; + char netdev_kind[NETDEV_KIND_MAX]; + sd_device *sd_device; + int ifindex; + unsigned short iftype; + struct ether_addr mac_address; + uint32_t mtu; + uint32_t min_mtu; + uint32_t max_mtu; + uint32_t tx_queues; + uint32_t rx_queues; + + union { + struct rtnl_link_stats64 stats64; + struct rtnl_link_stats stats; + }; + + uint64_t tx_bitrate; + uint64_t rx_bitrate; + + /* bridge info */ + uint32_t forward_delay; + uint32_t hello_time; + uint32_t max_age; + uint32_t ageing_time; + uint32_t stp_state; + uint16_t priority; + uint8_t mcast_igmp_version; + + /* vxlan info */ + VxLanInfo vxlan_info; + + /* ethtool info */ + int autonegotiation; + size_t speed; + Duplex duplex; + NetDevPort port; + + /* wlan info */ + enum nl80211_iftype wlan_iftype; + char *ssid; + struct ether_addr bssid; + + bool has_mac_address:1; + bool has_tx_queues:1; + bool has_rx_queues:1; + bool has_stats64:1; + bool has_stats:1; + bool has_bitrates:1; + bool has_ethtool_link_info:1; + bool has_wlan_link_info:1; + + bool needs_freeing:1; +} LinkInfo; + +static int link_info_compare(const LinkInfo *a, const LinkInfo *b) { + return CMP(a->ifindex, b->ifindex); +} + +static const LinkInfo* link_info_array_free(LinkInfo *array) { + for (unsigned i = 0; array && array[i].needs_freeing; i++) { + sd_device_unref(array[i].sd_device); + free(array[i].ssid); + } + + return mfree(array); +} +DEFINE_TRIVIAL_CLEANUP_FUNC(LinkInfo*, link_info_array_free); + +static int decode_netdev(sd_netlink_message *m, LinkInfo *info) { + const char *received_kind; + int r; + + assert(m); + assert(info); + + r = sd_netlink_message_enter_container(m, IFLA_LINKINFO); + if (r < 0) + return r; + + r = sd_netlink_message_read_string(m, IFLA_INFO_KIND, &received_kind); + if (r < 0) + return r; + + r = sd_netlink_message_enter_container(m, IFLA_INFO_DATA); + if (r < 0) + return r; + + if (streq(received_kind, "bridge")) { + (void) sd_netlink_message_read_u32(m, IFLA_BR_FORWARD_DELAY, &info->forward_delay); + (void) sd_netlink_message_read_u32(m, IFLA_BR_HELLO_TIME, &info->hello_time); + (void) sd_netlink_message_read_u32(m, IFLA_BR_MAX_AGE, &info->max_age); + (void) sd_netlink_message_read_u32(m, IFLA_BR_AGEING_TIME, &info->ageing_time); + (void) sd_netlink_message_read_u32(m, IFLA_BR_STP_STATE, &info->stp_state); + (void) sd_netlink_message_read_u16(m, IFLA_BR_PRIORITY, &info->priority); + (void) sd_netlink_message_read_u8(m, IFLA_BR_MCAST_IGMP_VERSION, &info->mcast_igmp_version); + + } else if (streq(received_kind, "vxlan")) { + (void) sd_netlink_message_read_u32(m, IFLA_VXLAN_ID, &info->vxlan_info.vni); + + r = sd_netlink_message_read_in_addr(m, IFLA_VXLAN_GROUP, &info->vxlan_info.group.in); + if (r >= 0) + info->vxlan_info.group_family = AF_INET; + else { + r = sd_netlink_message_read_in6_addr(m, IFLA_VXLAN_GROUP6, &info->vxlan_info.group.in6); + if (r >= 0) + info->vxlan_info.group_family = AF_INET6; + } + + r = sd_netlink_message_read_in_addr(m, IFLA_VXLAN_LOCAL, &info->vxlan_info.local.in); + if (r >= 0) + info->vxlan_info.local_family = AF_INET; + else { + r = sd_netlink_message_read_in6_addr(m, IFLA_VXLAN_LOCAL6, &info->vxlan_info.local.in6); + if (r >= 0) + info->vxlan_info.local_family = AF_INET6; + } + + (void) sd_netlink_message_read_u32(m, IFLA_VXLAN_LINK, &info->vxlan_info.link); + (void) sd_netlink_message_read_u16(m, IFLA_VXLAN_PORT, &info->vxlan_info.dest_port); + } + + strncpy(info->netdev_kind, received_kind, IFNAMSIZ); + + (void) sd_netlink_message_exit_container(m); + (void) sd_netlink_message_exit_container(m); + + return 0; +} + +static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns) { + const char *name; + int ifindex, r; + uint16_t type; + + assert(m); + assert(info); + + r = sd_netlink_message_get_type(m, &type); + if (r < 0) + return r; + + if (type != RTM_NEWLINK) + return 0; + + r = sd_rtnl_message_link_get_ifindex(m, &ifindex); + if (r < 0) + return r; + + r = sd_netlink_message_read_string(m, IFLA_IFNAME, &name); + if (r < 0) + return r; + + if (patterns) { + char str[DECIMAL_STR_MAX(int)]; + + xsprintf(str, "%i", ifindex); + + if (!strv_fnmatch(patterns, str, 0) && !strv_fnmatch(patterns, name, 0)) + return 0; + } + + r = sd_rtnl_message_link_get_type(m, &info->iftype); + if (r < 0) + return r; + + strscpy(info->name, sizeof info->name, name); + info->ifindex = ifindex; + + info->has_mac_address = + sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &info->mac_address) >= 0 && + memcmp(&info->mac_address, ÐER_ADDR_NULL, sizeof(struct ether_addr)) != 0; + + (void) sd_netlink_message_read_u32(m, IFLA_MTU, &info->mtu); + (void) sd_netlink_message_read_u32(m, IFLA_MIN_MTU, &info->min_mtu); + (void) sd_netlink_message_read_u32(m, IFLA_MAX_MTU, &info->max_mtu); + + info->has_rx_queues = + sd_netlink_message_read_u32(m, IFLA_NUM_RX_QUEUES, &info->rx_queues) >= 0 && + info->rx_queues > 0; + + info->has_tx_queues = + sd_netlink_message_read_u32(m, IFLA_NUM_TX_QUEUES, &info->tx_queues) >= 0 && + info->tx_queues > 0; + + if (sd_netlink_message_read(m, IFLA_STATS64, sizeof info->stats64, &info->stats64) >= 0) + info->has_stats64 = true; + else if (sd_netlink_message_read(m, IFLA_STATS, sizeof info->stats, &info->stats) >= 0) + info->has_stats = true; + + /* fill kind info */ + (void) decode_netdev(m, info); + + return 1; +} + +static int acquire_link_bitrates(sd_bus *bus, LinkInfo *link) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL, *ifindex_str = NULL; + int r; + + if (asprintf(&ifindex_str, "%i", link->ifindex) < 0) + return -ENOMEM; + + r = sd_bus_path_encode("/org/freedesktop/network1/link", ifindex_str, &path); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + path, + "org.freedesktop.DBus.Properties", + "Get", + &error, + &reply, + "ss", + "org.freedesktop.network1.Link", + "BitRates"); + if (r < 0) { + bool quiet = sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_PROPERTY); + + return log_full_errno(quiet ? LOG_DEBUG : LOG_WARNING, + r, "Failed to query link bit rates: %s", bus_error_message(&error, r)); + } + + r = sd_bus_message_enter_container(reply, 'v', "(tt)"); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read(reply, "(tt)", &link->tx_bitrate, &link->rx_bitrate); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + link->has_bitrates = link->tx_bitrate != UINT64_MAX && link->rx_bitrate != UINT64_MAX; + + return 0; +} + +static void acquire_ether_link_info(int *fd, LinkInfo *link) { + if (ethtool_get_link_info(fd, link->name, + &link->autonegotiation, + &link->speed, + &link->duplex, + &link->port) >= 0) + link->has_ethtool_link_info = true; +} + +static void acquire_wlan_link_info(LinkInfo *link) { + _cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL; + const char *type = NULL; + int r, k = 0; + + if (link->sd_device) + (void) sd_device_get_devtype(link->sd_device, &type); + if (!streq_ptr(type, "wlan")) + return; + + r = sd_genl_socket_open(&genl); + if (r < 0) { + log_debug_errno(r, "Failed to open generic netlink socket: %m"); + return; + } + + (void) sd_netlink_inc_rcvbuf(genl, RCVBUF_SIZE); + + r = wifi_get_interface(genl, link->ifindex, &link->wlan_iftype, &link->ssid); + if (r < 0) + log_debug_errno(r, "%s: failed to query ssid: %m", link->name); + + if (link->wlan_iftype == NL80211_IFTYPE_STATION) { + k = wifi_get_station(genl, link->ifindex, &link->bssid); + if (k < 0) + log_debug_errno(k, "%s: failed to query bssid: %m", link->name); + } + + link->has_wlan_link_info = r > 0 || k > 0; +} + +static int acquire_link_info(sd_bus *bus, sd_netlink *rtnl, char **patterns, LinkInfo **ret) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + _cleanup_(link_info_array_freep) LinkInfo *links = NULL; + _cleanup_close_ int fd = -1; + size_t allocated = 0, c = 0, j; + sd_netlink_message *i; + int r; + + assert(rtnl); + assert(ret); + + r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0); + if (r < 0) + return rtnl_log_create_error(r); + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return rtnl_log_create_error(r); + + r = sd_netlink_call(rtnl, req, 0, &reply); + if (r < 0) + return log_error_errno(r, "Failed to enumerate links: %m"); + + for (i = reply; i; i = sd_netlink_message_next(i)) { + if (!GREEDY_REALLOC0(links, allocated, c + 2)) /* We keep one trailing one as marker */ + return -ENOMEM; + + r = decode_link(i, links + c, patterns); + if (r < 0) + return r; + if (r == 0) + continue; + + links[c].needs_freeing = true; + + char devid[2 + DECIMAL_STR_MAX(int)]; + xsprintf(devid, "n%i", links[c].ifindex); + (void) sd_device_new_from_device_id(&links[c].sd_device, devid); + + acquire_ether_link_info(&fd, &links[c]); + acquire_wlan_link_info(&links[c]); + + c++; + } + + typesafe_qsort(links, c, link_info_compare); + + if (bus) + for (j = 0; j < c; j++) + (void) acquire_link_bitrates(bus, links + j); + + *ret = TAKE_PTR(links); + + return (int) c; +} + +static int list_links(int argc, char *argv[], void *userdata) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(link_info_array_freep) LinkInfo *links = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + TableCell *cell; + int c, i, r; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + c = acquire_link_info(NULL, rtnl, argc > 1 ? argv + 1 : NULL, &links); + if (c < 0) + return c; + + (void) pager_open(arg_pager_flags); + + table = table_new("idx", "link", "type", "operational", "setup"); + if (!table) + return log_oom(); + + table_set_header(table, arg_legend); + + assert_se(cell = table_get_cell(table, 0, 0)); + (void) table_set_minimum_width(table, cell, 3); + (void) table_set_weight(table, cell, 0); + (void) table_set_ellipsize_percent(table, cell, 100); + (void) table_set_align_percent(table, cell, 100); + + assert_se(cell = table_get_cell(table, 0, 1)); + (void) table_set_ellipsize_percent(table, cell, 100); + + for (i = 0; i < c; i++) { + _cleanup_free_ char *setup_state = NULL, *operational_state = NULL; + const char *on_color_operational, *off_color_operational, + *on_color_setup, *off_color_setup; + _cleanup_free_ char *t = NULL; + + (void) sd_network_link_get_operational_state(links[i].ifindex, &operational_state); + operational_state_to_color(links[i].name, operational_state, &on_color_operational, &off_color_operational); + + r = sd_network_link_get_setup_state(links[i].ifindex, &setup_state); + if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */ + setup_state = strdup("unmanaged"); + setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); + + t = link_get_type_string(links[i].iftype, links[i].sd_device); + + r = table_add_many(table, + TABLE_INT, links[i].ifindex, + TABLE_STRING, links[i].name, + TABLE_STRING, strna(t), + TABLE_STRING, strna(operational_state), + TABLE_SET_COLOR, on_color_operational, + TABLE_STRING, strna(setup_state), + TABLE_SET_COLOR, on_color_setup); + if (r < 0) + return r; + } + + r = table_print(table, NULL); + if (r < 0) + return log_error_errno(r, "Failed to print table: %m"); + + if (arg_legend) + printf("\n%i links listed.\n", c); + + return 0; +} + +/* IEEE Organizationally Unique Identifier vendor string */ +static int ieee_oui(sd_hwdb *hwdb, const struct ether_addr *mac, char **ret) { + const char *description; + char modalias[STRLEN("OUI:XXYYXXYYXXYY") + 1], *desc; + int r; + + assert(ret); + + if (!hwdb) + return -EINVAL; + + if (!mac) + return -EINVAL; + + /* skip commonly misused 00:00:00 (Xerox) prefix */ + if (memcmp(mac, "\0\0\0", 3) == 0) + return -EINVAL; + + xsprintf(modalias, "OUI:" ETHER_ADDR_FORMAT_STR, + ETHER_ADDR_FORMAT_VAL(*mac)); + + r = sd_hwdb_get(hwdb, modalias, "ID_OUI_FROM_DATABASE", &description); + if (r < 0) + return r; + + desc = strdup(description); + if (!desc) + return -ENOMEM; + + *ret = desc; + + return 0; +} + +static int get_gateway_description( + sd_netlink *rtnl, + sd_hwdb *hwdb, + int ifindex, + int family, + union in_addr_union *gateway, + char **gateway_description) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *m; + int r; + + assert(rtnl); + assert(ifindex >= 0); + assert(IN_SET(family, AF_INET, AF_INET6)); + assert(gateway); + assert(gateway_description); + + r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_GETNEIGH, ifindex, family); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (m = reply; m; m = sd_netlink_message_next(m)) { + union in_addr_union gw = IN_ADDR_NULL; + struct ether_addr mac = ETHER_ADDR_NULL; + uint16_t type; + int ifi, fam; + + r = sd_netlink_message_get_errno(m); + if (r < 0) { + log_error_errno(r, "got error: %m"); + continue; + } + + r = sd_netlink_message_get_type(m, &type); + if (r < 0) { + log_error_errno(r, "could not get type: %m"); + continue; + } + + if (type != RTM_NEWNEIGH) { + log_error("type is not RTM_NEWNEIGH"); + continue; + } + + r = sd_rtnl_message_neigh_get_family(m, &fam); + if (r < 0) { + log_error_errno(r, "could not get family: %m"); + continue; + } + + if (fam != family) { + log_error("family is not correct"); + continue; + } + + r = sd_rtnl_message_neigh_get_ifindex(m, &ifi); + if (r < 0) { + log_error_errno(r, "could not get ifindex: %m"); + continue; + } + + if (ifindex > 0 && ifi != ifindex) + continue; + + switch (fam) { + case AF_INET: + r = sd_netlink_message_read_in_addr(m, NDA_DST, &gw.in); + if (r < 0) + continue; + + break; + case AF_INET6: + r = sd_netlink_message_read_in6_addr(m, NDA_DST, &gw.in6); + if (r < 0) + continue; + + break; + default: + continue; + } + + if (!in_addr_equal(fam, &gw, gateway)) + continue; + + r = sd_netlink_message_read(m, NDA_LLADDR, sizeof(mac), &mac); + if (r < 0) + continue; + + r = ieee_oui(hwdb, &mac, gateway_description); + if (r < 0) + continue; + + return 0; + } + + return -ENODATA; +} + +static int dump_gateways( + sd_netlink *rtnl, + sd_hwdb *hwdb, + Table *table, + int ifindex) { + _cleanup_free_ struct local_address *local = NULL; + int r, n, i; + + assert(rtnl); + assert(table); + + n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local); + if (n < 0) + return n; + + for (i = 0; i < n; i++) { + _cleanup_free_ char *gateway = NULL, *description = NULL, *with_description = NULL; + + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, i == 0 ? "Gateway:" : ""); + if (r < 0) + return r; + + r = in_addr_to_string(local[i].family, &local[i].address, &gateway); + if (r < 0) + return r; + + r = get_gateway_description(rtnl, hwdb, local[i].ifindex, local[i].family, &local[i].address, &description); + if (r < 0) + log_debug_errno(r, "Could not get description of gateway: %m"); + + if (description) { + with_description = strjoin(gateway, " (", description, ")"); + if (!with_description) + return -ENOMEM; + } + + /* Show interface name for the entry if we show + * entries for all interfaces */ + if (ifindex <= 0) { + char name[IF_NAMESIZE+1]; + + r = table_add_cell_stringf(table, NULL, "%s on %s", with_description ?: gateway, + format_ifname_full(local[i].ifindex, name, FORMAT_IFNAME_IFINDEX_WITH_PERCENT)); + } else + r = table_add_cell(table, NULL, TABLE_STRING, with_description ?: gateway); + if (r < 0) + return r; + } + + return 0; +} + +static int dump_addresses( + sd_netlink *rtnl, + Table *table, + int ifindex) { + + _cleanup_free_ struct local_address *local = NULL; + _cleanup_free_ char *dhcp4_address = NULL; + int r, n, i; + + assert(rtnl); + assert(table); + + n = local_addresses(rtnl, ifindex, AF_UNSPEC, &local); + if (n < 0) + return n; + + (void) sd_network_link_get_dhcp4_address(ifindex, &dhcp4_address); + + for (i = 0; i < n; i++) { + _cleanup_free_ char *pretty = NULL; + + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, i == 0 ? "Address:" : ""); + if (r < 0) + return r; + + r = in_addr_to_string(local[i].family, &local[i].address, &pretty); + if (r < 0) + return r; + + if (dhcp4_address && streq(pretty, dhcp4_address)) { + _cleanup_free_ char *p = NULL; + + p = pretty; + pretty = strjoin(pretty , " (DHCP4)"); + if (!pretty) + return log_oom(); + } + + if (ifindex <= 0) { + char name[IF_NAMESIZE+1]; + + r = table_add_cell_stringf(table, NULL, "%s on %s", pretty, + format_ifname_full(local[i].ifindex, name, FORMAT_IFNAME_IFINDEX_WITH_PERCENT)); + } else + r = table_add_cell(table, NULL, TABLE_STRING, pretty); + if (r < 0) + return r; + } + + return 0; +} + +static int dump_address_labels(sd_netlink *rtnl) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + sd_netlink_message *m; + TableCell *cell; + int r; + + assert(rtnl); + + r = sd_rtnl_message_new_addrlabel(rtnl, &req, RTM_GETADDRLABEL, 0, AF_INET6); + if (r < 0) + return log_error_errno(r, "Could not allocate RTM_GETADDRLABEL message: %m"); + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(rtnl, req, 0, &reply); + if (r < 0) + return r; + + table = table_new("label", "prefix/prefixlen"); + if (!table) + return -ENOMEM; + + r = table_set_sort(table, 0, SIZE_MAX); + if (r < 0) + return r; + + assert_se(cell = table_get_cell(table, 0, 0)); + (void) table_set_align_percent(table, cell, 100); + (void) table_set_ellipsize_percent(table, cell, 100); + + assert_se(cell = table_get_cell(table, 0, 1)); + (void) table_set_align_percent(table, cell, 100); + + for (m = reply; m; m = sd_netlink_message_next(m)) { + _cleanup_free_ char *pretty = NULL; + union in_addr_union prefix = IN_ADDR_NULL; + uint8_t prefixlen; + uint32_t label; + + r = sd_netlink_message_get_errno(m); + if (r < 0) { + log_error_errno(r, "got error: %m"); + continue; + } + + r = sd_netlink_message_read_u32(m, IFAL_LABEL, &label); + if (r < 0 && r != -ENODATA) { + log_error_errno(r, "Could not read IFAL_LABEL, ignoring: %m"); + continue; + } + + r = sd_netlink_message_read_in6_addr(m, IFAL_ADDRESS, &prefix.in6); + if (r < 0) + continue; + + r = in_addr_to_string(AF_INET6, &prefix, &pretty); + if (r < 0) + continue; + + r = sd_rtnl_message_addrlabel_get_prefixlen(m, &prefixlen); + if (r < 0) + continue; + + r = table_add_cell(table, NULL, TABLE_UINT32, &label); + if (r < 0) + return r; + + r = table_add_cell_stringf(table, NULL, "%s/%u", pretty, prefixlen); + if (r < 0) + return r; + } + + return table_print(table, NULL); +} + +static int list_address_labels(int argc, char *argv[], void *userdata) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + int r; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + dump_address_labels(rtnl); + + return 0; +} + +static int open_lldp_neighbors(int ifindex, FILE **ret) { + _cleanup_free_ char *p = NULL; + FILE *f; + + if (asprintf(&p, "/run/systemd/netif/lldp/%i", ifindex) < 0) + return -ENOMEM; + + f = fopen(p, "re"); + if (!f) + return -errno; + + *ret = f; + return 0; +} + +static int next_lldp_neighbor(FILE *f, sd_lldp_neighbor **ret) { + _cleanup_free_ void *raw = NULL; + size_t l; + le64_t u; + int r; + + assert(f); + assert(ret); + + l = fread(&u, 1, sizeof(u), f); + if (l == 0 && feof(f)) + return 0; + if (l != sizeof(u)) + return -EBADMSG; + + /* each LLDP packet is at most MTU size, but let's allow up to 4KiB just in case */ + if (le64toh(u) >= 4096) + return -EBADMSG; + + raw = new(uint8_t, le64toh(u)); + if (!raw) + return -ENOMEM; + + if (fread(raw, 1, le64toh(u), f) != le64toh(u)) + return -EBADMSG; + + r = sd_lldp_neighbor_from_raw(ret, raw, le64toh(u)); + if (r < 0) + return r; + + return 1; +} + +static int dump_lldp_neighbors(Table *table, const char *prefix, int ifindex) { + _cleanup_fclose_ FILE *f = NULL; + int r, c = 0; + + assert(table); + assert(prefix); + assert(ifindex > 0); + + r = open_lldp_neighbors(ifindex, &f); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + for (;;) { + const char *system_name = NULL, *port_id = NULL, *port_description = NULL; + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; + + r = next_lldp_neighbor(f, &n); + if (r < 0) + return r; + if (r == 0) + break; + + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, c == 0 ? prefix : ""); + if (r < 0) + return r; + + (void) sd_lldp_neighbor_get_system_name(n, &system_name); + (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id); + (void) sd_lldp_neighbor_get_port_description(n, &port_description); + + r = table_add_cell_stringf(table, NULL, + "%s on port %s%s%s%s", + strna(system_name), strna(port_id), + isempty(port_description) ? "" : " (", + strempty(port_description), + isempty(port_description) ? "" : ")"); + if (r < 0) + return r; + + c++; + } + + return c; +} + +static int dump_ifindexes(Table *table, const char *prefix, const int *ifindexes) { + unsigned c; + int r; + + assert(prefix); + + if (!ifindexes || ifindexes[0] <= 0) + return 0; + + for (c = 0; ifindexes[c] > 0; c++) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, c == 0 ? prefix : "", + TABLE_IFINDEX, ifindexes[c]); + if (r < 0) + return r; + } + + return 0; +} + +static int dump_list(Table *table, const char *prefix, char **l) { + char **i; + int r; + + if (strv_isempty(l)) + return 0; + + STRV_FOREACH(i, l) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, i == l ? prefix : "", + TABLE_STRING, *i); + if (r < 0) + return r; + } + + return 0; +} + +#define DUMP_STATS_ONE(name, val_name) \ + r = table_add_many(table, \ + TABLE_EMPTY, \ + TABLE_STRING, name ":"); \ + if (r < 0) \ + return r; \ + r = table_add_cell(table, NULL, \ + info->has_stats64 ? TABLE_UINT64 : TABLE_UINT32, \ + info->has_stats64 ? (void*) &info->stats64.val_name : (void*) &info->stats.val_name); \ + if (r < 0) \ + return r; + +static int dump_statistics(Table *table, const LinkInfo *info) { + int r; + + if (!arg_stats) + return 0; + + if (!info->has_stats64 && !info->has_stats) + return 0; + + DUMP_STATS_ONE("Rx Packets", rx_packets); + DUMP_STATS_ONE("Tx Packets", tx_packets); + DUMP_STATS_ONE("Rx Bytes", rx_bytes); + DUMP_STATS_ONE("Tx Bytes", tx_bytes); + DUMP_STATS_ONE("Rx Errors", rx_errors); + DUMP_STATS_ONE("Tx Errors", tx_errors); + DUMP_STATS_ONE("Rx Dropped", rx_dropped); + DUMP_STATS_ONE("Tx Dropped", tx_dropped); + DUMP_STATS_ONE("Multicast Packets", multicast); + DUMP_STATS_ONE("Collisions", collisions); + + return 0; +} + +static int link_status_one( + sd_netlink *rtnl, + sd_hwdb *hwdb, + const LinkInfo *info) { + + _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL; + _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL; + _cleanup_free_ char *t = NULL, *network = NULL; + const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL; + const char *on_color_operational, *off_color_operational, + *on_color_setup, *off_color_setup; + _cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + TableCell *cell; + int r; + + assert(rtnl); + assert(info); + + (void) sd_network_link_get_operational_state(info->ifindex, &operational_state); + operational_state_to_color(info->name, operational_state, &on_color_operational, &off_color_operational); + + r = sd_network_link_get_setup_state(info->ifindex, &setup_state); + if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */ + setup_state = strdup("unmanaged"); + setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); + + (void) sd_network_link_get_dns(info->ifindex, &dns); + (void) sd_network_link_get_search_domains(info->ifindex, &search_domains); + (void) sd_network_link_get_route_domains(info->ifindex, &route_domains); + (void) sd_network_link_get_ntp(info->ifindex, &ntp); + + if (info->sd_device) { + (void) sd_device_get_property_value(info->sd_device, "ID_NET_LINK_FILE", &link); + (void) sd_device_get_property_value(info->sd_device, "ID_NET_DRIVER", &driver); + (void) sd_device_get_property_value(info->sd_device, "ID_PATH", &path); + + if (sd_device_get_property_value(info->sd_device, "ID_VENDOR_FROM_DATABASE", &vendor) < 0) + (void) sd_device_get_property_value(info->sd_device, "ID_VENDOR", &vendor); + + if (sd_device_get_property_value(info->sd_device, "ID_MODEL_FROM_DATABASE", &model) < 0) + (void) sd_device_get_property_value(info->sd_device, "ID_MODEL", &model); + } + + t = link_get_type_string(info->iftype, info->sd_device); + + (void) sd_network_link_get_network_file(info->ifindex, &network); + + (void) sd_network_link_get_carrier_bound_to(info->ifindex, &carrier_bound_to); + (void) sd_network_link_get_carrier_bound_by(info->ifindex, &carrier_bound_by); + + table = table_new("dot", "key", "value"); + if (!table) + return -ENOMEM; + + assert_se(cell = table_get_cell(table, 0, 0)); + (void) table_set_ellipsize_percent(table, cell, 100); + + assert_se(cell = table_get_cell(table, 0, 1)); + (void) table_set_ellipsize_percent(table, cell, 100); + + table_set_header(table, false); + + r = table_add_many(table, + TABLE_STRING, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), + TABLE_SET_COLOR, on_color_operational); + if (r < 0) + return r; + r = table_add_cell_stringf(table, &cell, "%i: %s", info->ifindex, info->name); + if (r < 0) + return r; + (void) table_set_align_percent(table, cell, 0); + + r = table_add_many(table, + TABLE_EMPTY, + TABLE_EMPTY, + TABLE_STRING, "Link File:", + TABLE_SET_ALIGN_PERCENT, 100, + TABLE_STRING, strna(link), + TABLE_EMPTY, + TABLE_STRING, "Network File:", + TABLE_STRING, strna(network), + TABLE_EMPTY, + TABLE_STRING, "Type:", + TABLE_STRING, strna(t), + TABLE_EMPTY, + TABLE_STRING, "State:"); + if (r < 0) + return r; + r = table_add_cell_stringf(table, NULL, "%s%s%s (%s%s%s)", + on_color_operational, strna(operational_state), off_color_operational, + on_color_setup, strna(setup_state), off_color_setup); + if (r < 0) + return r; + + if (path) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Path:", + TABLE_STRING, path); + if (r < 0) + return r; + } + if (driver) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Driver:", + TABLE_STRING, driver); + if (r < 0) + return r; + } + if (vendor) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Vendor:", + TABLE_STRING, vendor); + if (r < 0) + return r; + } + if (model) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Model:", + TABLE_STRING, model); + if (r < 0) + return r; + } + + if (info->has_mac_address) { + _cleanup_free_ char *description = NULL; + char ea[ETHER_ADDR_TO_STRING_MAX]; + + (void) ieee_oui(hwdb, &info->mac_address, &description); + + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "HW Address:"); + if (r < 0) + return r; + r = table_add_cell_stringf(table, NULL, "%s%s%s%s", + ether_addr_to_string(&info->mac_address, ea), + description ? " (" : "", + strempty(description), + description ? ")" : ""); + if (r < 0) + return r; + } + + if (info->mtu > 0) { + char min_str[DECIMAL_STR_MAX(uint32_t)], max_str[DECIMAL_STR_MAX(uint32_t)]; + + xsprintf(min_str, "%" PRIu32, info->min_mtu); + xsprintf(max_str, "%" PRIu32, info->max_mtu); + + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "MTU:"); + if (r < 0) + return r; + r = table_add_cell_stringf(table, NULL, "%" PRIu32 "%s%s%s%s%s%s%s", + info->mtu, + info->min_mtu > 0 || info->max_mtu > 0 ? " (" : "", + info->min_mtu > 0 ? "min: " : "", + info->min_mtu > 0 ? min_str : "", + info->min_mtu > 0 && info->max_mtu > 0 ? ", " : "", + info->max_mtu > 0 ? "max: " : "", + info->max_mtu > 0 ? max_str : "", + info->min_mtu > 0 || info->max_mtu > 0 ? ")" : ""); + if (r < 0) + return r; + } + + if (streq_ptr(info->netdev_kind, "bridge")) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Forward Delay:", + TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->forward_delay), + TABLE_EMPTY, + TABLE_STRING, "Hello Time:", + TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->hello_time), + TABLE_EMPTY, + TABLE_STRING, "Max Age:", + TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->max_age), + TABLE_EMPTY, + TABLE_STRING, "Ageing Time:", + TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->ageing_time), + TABLE_EMPTY, + TABLE_STRING, "Priority:", + TABLE_UINT16, info->priority, + TABLE_EMPTY, + TABLE_STRING, "STP:", + TABLE_BOOLEAN, info->stp_state > 0, + TABLE_EMPTY, + TABLE_STRING, "Multicast IGMP Version:", + TABLE_UINT8, info->mcast_igmp_version); + if (r < 0) + return r; + + } else if (streq_ptr(info->netdev_kind, "vxlan")) { + if (info->vxlan_info.vni > 0) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "VNI:", + TABLE_UINT32, info->vxlan_info.vni); + if (r < 0) + return r; + } + + if (IN_SET(info->vxlan_info.group_family, AF_INET, AF_INET6)) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Group:", + info->vxlan_info.group_family == AF_INET ? TABLE_IN_ADDR : TABLE_IN6_ADDR, + &info->vxlan_info.group); + if (r < 0) + return r; + } + + if (IN_SET(info->vxlan_info.local_family, AF_INET, AF_INET6)) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Local:", + info->vxlan_info.local_family == AF_INET ? TABLE_IN_ADDR : TABLE_IN6_ADDR, + &info->vxlan_info.local); + if (r < 0) + return r; + } + + if (info->vxlan_info.dest_port > 0) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Destination Port:", + TABLE_UINT16, be16toh(info->vxlan_info.dest_port)); + if (r < 0) + return r; + } + + if (info->vxlan_info.link > 0) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Underlying Device:", + TABLE_IFINDEX, info->vxlan_info.link); + if (r < 0) + return r; + } + } + + if (info->has_wlan_link_info) { + _cleanup_free_ char *esc = NULL; + char buf[ETHER_ADDR_TO_STRING_MAX]; + + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "WiFi access point:"); + if (r < 0) + return r; + + if (info->ssid) + esc = cescape(info->ssid); + + r = table_add_cell_stringf(table, NULL, "%s (%s)", + strnull(esc), + ether_addr_to_string(&info->bssid, buf)); + if (r < 0) + return r; + } + + if (info->has_bitrates) { + char tx[FORMAT_BYTES_MAX], rx[FORMAT_BYTES_MAX]; + + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Bit Rate (Tx/Rx):"); + if (r < 0) + return r; + r = table_add_cell_stringf(table, NULL, "%sbps/%sbps", + format_bytes_full(tx, sizeof tx, info->tx_bitrate, 0), + format_bytes_full(rx, sizeof rx, info->rx_bitrate, 0)); + if (r < 0) + return r; + } + + if (info->has_tx_queues || info->has_rx_queues) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Queue Length (Tx/Rx):"); + if (r < 0) + return r; + r = table_add_cell_stringf(table, NULL, "%" PRIu32 "/%" PRIu32, info->tx_queues, info->rx_queues); + if (r < 0) + return r; + } + + if (info->has_ethtool_link_info) { + const char *duplex = duplex_to_string(info->duplex); + const char *port = port_to_string(info->port); + + if (IN_SET(info->autonegotiation, AUTONEG_DISABLE, AUTONEG_ENABLE)) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Auto negotiation:", + TABLE_BOOLEAN, info->autonegotiation == AUTONEG_ENABLE); + if (r < 0) + return r; + } + + if (info->speed > 0) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Speed:", + TABLE_BPS, (uint64_t) info->speed); + if (r < 0) + return r; + } + + if (duplex) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Duplex:", + TABLE_STRING, duplex); + if (r < 0) + return r; + } + + if (port) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Port:", + TABLE_STRING, port); + if (r < 0) + return r; + } + } + + r = dump_addresses(rtnl, table, info->ifindex); + if (r < 0) + return r; + r = dump_gateways(rtnl, hwdb, table, info->ifindex); + if (r < 0) + return r; + r = dump_list(table, "DNS:", dns); + if (r < 0) + return r; + r = dump_list(table, "Search Domains:", search_domains); + if (r < 0) + return r; + r = dump_list(table, "Route Domains:", route_domains); + if (r < 0) + return r; + r = dump_list(table, "NTP:", ntp); + if (r < 0) + return r; + r = dump_ifindexes(table, "Carrier Bound To:", carrier_bound_to); + if (r < 0) + return r; + r = dump_ifindexes(table, "Carrier Bound By:", carrier_bound_by); + if (r < 0) + return r; + + (void) sd_network_link_get_timezone(info->ifindex, &tz); + if (tz) { + r = table_add_many(table, + TABLE_EMPTY, + TABLE_STRING, "Time Zone:", + TABLE_STRING, tz); + if (r < 0) + return r; + } + + r = dump_lldp_neighbors(table, "Connected To:", info->ifindex); + if (r < 0) + return r; + + r = dump_statistics(table, info); + if (r < 0) + return r; + + return table_print(table, NULL); +} + +static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) { + _cleanup_free_ char *operational_state = NULL; + _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL; + const char *on_color_operational, *off_color_operational; + _cleanup_(table_unrefp) Table *table = NULL; + TableCell *cell; + int r; + + assert(rtnl); + + (void) sd_network_get_operational_state(&operational_state); + operational_state_to_color(NULL, operational_state, &on_color_operational, &off_color_operational); + + table = table_new("dot", "key", "value"); + if (!table) + return -ENOMEM; + + assert_se(cell = table_get_cell(table, 0, 0)); + (void) table_set_ellipsize_percent(table, cell, 100); + + assert_se(cell = table_get_cell(table, 0, 1)); + (void) table_set_align_percent(table, cell, 100); + (void) table_set_ellipsize_percent(table, cell, 100); + + table_set_header(table, false); + + r = table_add_many(table, + TABLE_STRING, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), + TABLE_SET_COLOR, on_color_operational, + TABLE_STRING, "State:", + TABLE_STRING, strna(operational_state), + TABLE_SET_COLOR, on_color_operational); + + r = dump_addresses(rtnl, table, 0); + if (r < 0) + return r; + r = dump_gateways(rtnl, hwdb, table, 0); + if (r < 0) + return r; + + (void) sd_network_get_dns(&dns); + r = dump_list(table, "DNS:", dns); + if (r < 0) + return r; + + (void) sd_network_get_search_domains(&search_domains); + r = dump_list(table, "Search Domains:", search_domains); + if (r < 0) + return r; + + (void) sd_network_get_route_domains(&route_domains); + r = dump_list(table, "Route Domains:", route_domains); + if (r < 0) + return r; + + (void) sd_network_get_ntp(&ntp); + r = dump_list(table, "NTP:", ntp); + if (r < 0) + return r; + + return table_print(table, NULL); +} + +static int link_status(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; + _cleanup_(link_info_array_freep) LinkInfo *links = NULL; + int r, c, i; + + (void) pager_open(arg_pager_flags); + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to connect system bus: %m"); + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + r = sd_hwdb_new(&hwdb); + if (r < 0) + log_debug_errno(r, "Failed to open hardware database: %m"); + + if (arg_all) + c = acquire_link_info(bus, rtnl, NULL, &links); + else if (argc <= 1) + return system_status(rtnl, hwdb); + else + c = acquire_link_info(bus, rtnl, argv + 1, &links); + if (c < 0) + return c; + + for (i = 0; i < c; i++) { + if (i > 0) + fputc('\n', stdout); + + link_status_one(rtnl, hwdb, links + i); + } + + return 0; +} + +static char *lldp_capabilities_to_string(uint16_t x) { + static const char characters[] = { + 'o', 'p', 'b', 'w', 'r', 't', 'd', 'a', 'c', 's', 'm', + }; + char *ret; + unsigned i; + + ret = new(char, ELEMENTSOF(characters) + 1); + if (!ret) + return NULL; + + for (i = 0; i < ELEMENTSOF(characters); i++) + ret[i] = (x & (1U << i)) ? characters[i] : '.'; + + ret[i] = 0; + return ret; +} + +static void lldp_capabilities_legend(uint16_t x) { + unsigned w, i, cols = columns(); + static const char* const table[] = { + "o - Other", + "p - Repeater", + "b - Bridge", + "w - WLAN Access Point", + "r - Router", + "t - Telephone", + "d - DOCSIS cable device", + "a - Station", + "c - Customer VLAN", + "s - Service VLAN", + "m - Two-port MAC Relay (TPMR)", + }; + + if (x == 0) + return; + + printf("\nCapability Flags:\n"); + for (w = 0, i = 0; i < ELEMENTSOF(table); i++) + if (x & (1U << i) || arg_all) { + bool newline; + + newline = w + strlen(table[i]) + (w == 0 ? 0 : 2) > cols; + if (newline) + w = 0; + w += printf("%s%s%s", newline ? "\n" : "", w == 0 ? "" : "; ", table[i]); + } + puts(""); +} + +static int link_lldp_status(int argc, char *argv[], void *userdata) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(link_info_array_freep) LinkInfo *links = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + int i, r, c, m = 0; + uint16_t all = 0; + TableCell *cell; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + c = acquire_link_info(NULL, rtnl, argc > 1 ? argv + 1 : NULL, &links); + if (c < 0) + return c; + + (void) pager_open(arg_pager_flags); + + table = table_new("link", + "chassis id", + "system name", + "caps", + "port id", + "port description"); + if (!table) + return -ENOMEM; + + table_set_header(table, arg_legend); + + assert_se(cell = table_get_cell(table, 0, 0)); + table_set_minimum_width(table, cell, 16); + + assert_se(cell = table_get_cell(table, 0, 1)); + table_set_minimum_width(table, cell, 17); + + assert_se(cell = table_get_cell(table, 0, 2)); + table_set_minimum_width(table, cell, 16); + + assert_se(cell = table_get_cell(table, 0, 3)); + table_set_minimum_width(table, cell, 11); + + assert_se(cell = table_get_cell(table, 0, 4)); + table_set_minimum_width(table, cell, 17); + + assert_se(cell = table_get_cell(table, 0, 5)); + table_set_minimum_width(table, cell, 16); + + for (i = 0; i < c; i++) { + _cleanup_fclose_ FILE *f = NULL; + + r = open_lldp_neighbors(links[i].ifindex, &f); + if (r == -ENOENT) + continue; + if (r < 0) { + log_warning_errno(r, "Failed to open LLDP data for %i, ignoring: %m", links[i].ifindex); + continue; + } + + for (;;) { + _cleanup_free_ char *cid = NULL, *pid = NULL, *sname = NULL, *pdesc = NULL, *capabilities = NULL; + const char *chassis_id = NULL, *port_id = NULL, *system_name = NULL, *port_description = NULL; + _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; + uint16_t cc; + + r = next_lldp_neighbor(f, &n); + if (r < 0) { + log_warning_errno(r, "Failed to read neighbor data: %m"); + break; + } + if (r == 0) + break; + + (void) sd_lldp_neighbor_get_chassis_id_as_string(n, &chassis_id); + (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id); + (void) sd_lldp_neighbor_get_system_name(n, &system_name); + (void) sd_lldp_neighbor_get_port_description(n, &port_description); + + if (chassis_id) { + cid = ellipsize(chassis_id, 17, 100); + if (cid) + chassis_id = cid; + } + + if (port_id) { + pid = ellipsize(port_id, 17, 100); + if (pid) + port_id = pid; + } + + if (system_name) { + sname = ellipsize(system_name, 16, 100); + if (sname) + system_name = sname; + } + + if (port_description) { + pdesc = ellipsize(port_description, 16, 100); + if (pdesc) + port_description = pdesc; + } + + if (sd_lldp_neighbor_get_enabled_capabilities(n, &cc) >= 0) { + capabilities = lldp_capabilities_to_string(cc); + all |= cc; + } + + r = table_add_many(table, + TABLE_STRING, links[i].name, + TABLE_STRING, strna(chassis_id), + TABLE_STRING, strna(system_name), + TABLE_STRING, strna(capabilities), + TABLE_STRING, strna(port_id), + TABLE_STRING, strna(port_description)); + if (r < 0) + return r; + + m++; + } + } + + r = table_print(table, NULL); + if (r < 0) + return r; + + if (arg_legend) { + lldp_capabilities_legend(all); + printf("\n%i neighbors listed.\n", m); + } + + return 0; +} + +static int link_delete_send_message(sd_netlink *rtnl, int index) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(rtnl); + + r = sd_rtnl_message_new_link(rtnl, &req, RTM_DELLINK, index); + if (r < 0) + return rtnl_log_create_error(r); + + r = sd_netlink_call(rtnl, req, 0, NULL); + if (r < 0) + return r; + + return 0; +} + +static int link_delete(int argc, char *argv[], void *userdata) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_set_free_ Set *indexes = NULL; + int index, r, i; + Iterator j; + void *p; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + indexes = set_new(NULL); + if (!indexes) + return log_oom(); + + for (i = 1; i < argc; i++) { + r = parse_ifindex_or_ifname(argv[i], &index); + if (r < 0) + return log_error_errno(r, "Failed to resolve interface %s", argv[i]); + + r = set_put(indexes, INT_TO_PTR(index)); + if (r < 0) + return log_oom(); + } + + SET_FOREACH(p, indexes, j) { + index = PTR_TO_INT(p); + r = link_delete_send_message(rtnl, index); + if (r < 0) { + char ifname[IF_NAMESIZE + 1]; + + return log_error_errno(r, "Failed to delete interface %s: %m", + format_ifname_full(index, ifname, FORMAT_IFNAME_IFINDEX)); + } + } + + return r; +} + +static int link_renew_one(sd_bus *bus, int index, const char *name) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "RenewLink", + &error, + NULL, + "i", index); + if (r < 0) + return log_error_errno(r, "Failed to renew dynamic configuration of interface %s: %s", + name, bus_error_message(&error, r)); + + return 0; +} + +static int link_renew(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int index, i, k = 0, r; + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to connect system bus: %m"); + + for (i = 1; i < argc; i++) { + r = parse_ifindex_or_ifname(argv[i], &index); + if (r < 0) + return log_error_errno(r, "Failed to resolve interface %s", argv[i]); + + r = link_renew_one(bus, index, argv[i]); + if (r < 0 && k >= 0) + k = r; + } + + return k; +} + +static int verb_reload(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to connect system bus: %m"); + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "Reload", + &error, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to reload network settings: %m"); + + return 0; +} + +static int verb_reconfigure(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_set_free_ Set *indexes = NULL; + int index, i, r; + Iterator j; + void *p; + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to connect system bus: %m"); + + indexes = set_new(NULL); + if (!indexes) + return log_oom(); + + for (i = 1; i < argc; i++) { + r = parse_ifindex_or_ifname(argv[i], &index); + if (r < 0) + return log_error_errno(r, "Failed to resolve interface %s", argv[i]); + + r = set_put(indexes, INT_TO_PTR(index)); + if (r < 0) + return log_oom(); + } + + SET_FOREACH(p, indexes, j) { + index = PTR_TO_INT(p); + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "ReconfigureLink", + &error, NULL, "i", index); + if (r < 0) { + char ifname[IF_NAMESIZE + 1]; + + return log_error_errno(r, "Failed to reconfigure network interface %s: %m", format_ifname_full(index, ifname, FORMAT_IFNAME_IFINDEX)); + } + } + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("networkctl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND\n\n" + "%sQuery and control the networking subsystem.%s\n" + "\nCommands:\n" + " list [PATTERN...] List links\n" + " status [PATTERN...] Show link status\n" + " lldp [PATTERN...] Show LLDP neighbors\n" + " label Show current address label entries in the kernel\n" + " delete DEVICES... Delete virtual netdevs\n" + " renew DEVICES... Renew dynamic configurations\n" + " reconfigure DEVICES... Reconfigure interfaces\n" + " reload Reload .network and .netdev files\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --no-legend Do not show the headers and footers\n" + " -a --all Show status for all links\n" + " -s --stats Show detailed link statics\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_PAGER, + ARG_NO_LEGEND, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, + { "all", no_argument, NULL, 'a' }, + { "stats", no_argument, NULL, 's' }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "has", options, NULL)) >= 0) { + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_NO_LEGEND: + arg_legend = false; + break; + + case 'a': + arg_all = true; + break; + + case 's': + arg_stats = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + } + + return 1; +} + +static int networkctl_main(int argc, char *argv[]) { + static const Verb verbs[] = { + { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links }, + { "status", VERB_ANY, VERB_ANY, 0, link_status }, + { "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status }, + { "label", VERB_ANY, VERB_ANY, 0, list_address_labels }, + { "delete", 2, VERB_ANY, 0, link_delete }, + { "renew", 2, VERB_ANY, 0, link_renew }, + { "reconfigure", 2, VERB_ANY, 0, verb_reconfigure }, + { "reload", 1, 1, 0, verb_reload }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static void warn_networkd_missing(void) { + + if (access("/run/systemd/netif/state", F_OK) >= 0) + return; + + fprintf(stderr, "WARNING: systemd-networkd is not running, output will be incomplete.\n\n"); +} + +static int run(int argc, char* argv[]) { + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + warn_networkd_missing(); + + return networkctl_main(argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/network/networkd-address-label.c b/src/network/networkd-address-label.c new file mode 100644 index 00000000..108f4e87 --- /dev/null +++ b/src/network/networkd-address-label.c @@ -0,0 +1,231 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "conf-parser.h" +#include "networkd-address-label.h" +#include "netlink-util.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "socket-util.h" + +void address_label_free(AddressLabel *label) { + if (!label) + return; + + if (label->network) { + LIST_REMOVE(labels, label->network->address_labels, label); + assert(label->network->n_address_labels > 0); + label->network->n_address_labels--; + + if (label->section) { + hashmap_remove(label->network->address_labels_by_section, label->section); + network_config_section_free(label->section); + } + } + + free(label); +} + +static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(address_label_freep) AddressLabel *label = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + label = hashmap_get(network->address_labels_by_section, n); + if (label) { + *ret = TAKE_PTR(label); + + return 0; + } + } + + label = new(AddressLabel, 1); + if (!label) + return -ENOMEM; + + *label = (AddressLabel) { + .network = network, + }; + + LIST_APPEND(labels, network->address_labels, label); + network->n_address_labels++; + + if (filename) { + label->section = TAKE_PTR(n); + + r = hashmap_ensure_allocated(&network->address_labels_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(network->address_labels_by_section, label->section, label); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(label); + + return 0; +} + +static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(rtnl); + assert(m); + assert(link); + assert(link->ifname); + assert(link->address_label_messages > 0); + + link->address_label_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_warning_errno(link, r, "could not set address label: %m"); + link_enter_failed(link); + return 1; + } else if (r >= 0) + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + if (link->address_label_messages == 0) + log_link_debug(link, "Addresses label set"); + + return 1; +} + +int address_label_configure( + AddressLabel *label, + Link *link, + link_netlink_message_handler_t callback, + bool update) { + + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(label); + assert(link); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + + r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &req, RTM_NEWADDRLABEL, + link->ifindex, AF_INET6); + if (r < 0) + return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m"); + + r = sd_rtnl_message_addrlabel_set_prefixlen(req, label->prefixlen); + if (r < 0) + return log_error_errno(r, "Could not set prefixlen: %m"); + + r = sd_netlink_message_append_u32(req, IFAL_LABEL, label->label); + if (r < 0) + return log_error_errno(r, "Could not append IFAL_LABEL attribute: %m"); + + r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &label->in_addr.in6); + if (r < 0) + return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, + callback ?: address_label_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_error_errno(r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +int config_parse_address_label_prefix(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_label_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = in_addr_prefix_from_string(rvalue, AF_INET6, &n->in_addr, &n->prefixlen); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring assignment: %s", rvalue); + return 0; + } + + n = NULL; + + return 0; +} + +int config_parse_address_label( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL; + Network *network = userdata; + uint32_t k; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_label_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = safe_atou32(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address label, ignoring: %s", rvalue); + return 0; + } + + if (k == 0xffffffffUL) { + log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring: %s", rvalue); + return 0; + } + + n->label = k; + n = NULL; + + return 0; +} diff --git a/src/network/networkd-address-label.h b/src/network/networkd-address-label.h new file mode 100644 index 00000000..595072a1 --- /dev/null +++ b/src/network/networkd-address-label.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "conf-parser.h" +#include "in-addr-util.h" + +typedef struct AddressLabel AddressLabel; + +#include "networkd-link.h" +#include "networkd-network.h" +#include "networkd-util.h" + +typedef struct Network Network; +typedef struct Link Link; +typedef struct NetworkConfigSection NetworkConfigSection; + +struct AddressLabel { + Network *network; + NetworkConfigSection *section; + + unsigned char prefixlen; + uint32_t label; + + union in_addr_union in_addr; + + LIST_FIELDS(AddressLabel, labels); +}; + +void address_label_free(AddressLabel *label); + +DEFINE_NETWORK_SECTION_FUNCTIONS(AddressLabel, address_label_free); + +int address_label_configure(AddressLabel *address, Link *link, link_netlink_message_handler_t callback, bool update); + +CONFIG_PARSER_PROTOTYPE(config_parse_address_label); +CONFIG_PARSER_PROTOTYPE(config_parse_address_label_prefix); diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c new file mode 100644 index 00000000..db6c1456 --- /dev/null +++ b/src/network/networkd-address-pool.c @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "networkd-address-pool.h" +#include "networkd-manager.h" +#include "set.h" +#include "string-util.h" + +#define RANDOM_PREFIX_TRIAL_MAX 1024 + +static int address_pool_new( + Manager *m, + AddressPool **ret, + int family, + const union in_addr_union *u, + unsigned prefixlen) { + + AddressPool *p; + + assert(m); + assert(ret); + assert(u); + + p = new(AddressPool, 1); + if (!p) + return -ENOMEM; + + *p = (AddressPool) { + .manager = m, + .family = family, + .prefixlen = prefixlen, + .in_addr = *u, + }; + + LIST_PREPEND(address_pools, m->address_pools, p); + + *ret = p; + return 0; +} + +int address_pool_new_from_string( + Manager *m, + AddressPool **ret, + int family, + const char *p, + unsigned prefixlen) { + + union in_addr_union u; + int r; + + assert(m); + assert(ret); + assert(p); + + r = in_addr_from_string(family, p, &u); + if (r < 0) + return r; + + return address_pool_new(m, ret, family, &u, prefixlen); +} + +void address_pool_free(AddressPool *p) { + + if (!p) + return; + + if (p->manager) + LIST_REMOVE(address_pools, p->manager->address_pools, p); + + free(p); +} + +static bool address_pool_prefix_is_taken( + AddressPool *p, + const union in_addr_union *u, + unsigned prefixlen) { + + Iterator i; + Link *l; + Network *n; + + assert(p); + assert(u); + + HASHMAP_FOREACH(l, p->manager->links, i) { + Address *a; + Iterator j; + + /* Don't clash with assigned addresses */ + SET_FOREACH(a, l->addresses, j) { + if (a->family != p->family) + continue; + + if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen)) + return true; + } + + /* Don't clash with addresses already pulled from the pool, but not assigned yet */ + LIST_FOREACH(addresses, a, l->pool_addresses) { + if (a->family != p->family) + continue; + + if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen)) + return true; + } + } + + /* And don't clash with configured but un-assigned addresses either */ + ORDERED_HASHMAP_FOREACH(n, p->manager->networks, i) { + Address *a; + + LIST_FOREACH(addresses, a, n->static_addresses) { + if (a->family != p->family) + continue; + + if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen)) + return true; + } + } + + return false; +} + +int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found) { + union in_addr_union u; + unsigned i; + int r; + + assert(p); + assert(prefixlen > 0); + assert(found); + + if (p->prefixlen >= prefixlen) + return 0; + + u = p->in_addr; + + for (i = 0; i < RANDOM_PREFIX_TRIAL_MAX; i++) { + r = in_addr_random_prefix(p->family, &u, p->prefixlen, prefixlen); + if (r <= 0) + return r; + + if (!address_pool_prefix_is_taken(p, &u, prefixlen)) { + if (DEBUG_LOGGING) { + _cleanup_free_ char *s = NULL; + + (void) in_addr_to_string(p->family, &u, &s); + log_debug("Found range %s/%u", strna(s), prefixlen); + } + + *found = u; + return 1; + } + } + + return 0; +} diff --git a/src/network/networkd-address-pool.h b/src/network/networkd-address-pool.h new file mode 100644 index 00000000..7db1c4f2 --- /dev/null +++ b/src/network/networkd-address-pool.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct AddressPool AddressPool; + +#include "in-addr-util.h" +#include "list.h" + +typedef struct Manager Manager; + +struct AddressPool { + Manager *manager; + + int family; + unsigned prefixlen; + + union in_addr_union in_addr; + + LIST_FIELDS(AddressPool, address_pools); +}; + +int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen); +void address_pool_free(AddressPool *p); + +int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c new file mode 100644 index 00000000..85797719 --- /dev/null +++ b/src/network/networkd-address.c @@ -0,0 +1,987 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "conf-parser.h" +#include "firewall-util.h" +#include "memory-util.h" +#include "missing_network.h" +#include "netlink-util.h" +#include "networkd-address.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "set.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" +#include "utf8.h" + +#define ADDRESSES_PER_LINK_MAX 2048U +#define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U + +int address_new(Address **ret) { + _cleanup_(address_freep) Address *address = NULL; + + address = new(Address, 1); + if (!address) + return -ENOMEM; + + *address = (Address) { + .family = AF_UNSPEC, + .scope = RT_SCOPE_UNIVERSE, + .cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME, + .cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME, + .prefix_route = true, + }; + + *ret = TAKE_PTR(address); + + return 0; +} + +static int address_new_static(Network *network, const char *filename, unsigned section_line, Address **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(address_freep) Address *address = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + address = hashmap_get(network->addresses_by_section, n); + if (address) { + *ret = TAKE_PTR(address); + + return 0; + } + } + + if (network->n_static_addresses >= STATIC_ADDRESSES_PER_NETWORK_MAX) + return -E2BIG; + + r = address_new(&address); + if (r < 0) + return r; + + address->network = network; + LIST_APPEND(addresses, network->static_addresses, address); + network->n_static_addresses++; + + if (filename) { + address->section = TAKE_PTR(n); + + r = hashmap_ensure_allocated(&network->addresses_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(network->addresses_by_section, address->section, address); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(address); + + return 0; +} + +void address_free(Address *address) { + if (!address) + return; + + if (address->network) { + LIST_REMOVE(addresses, address->network->static_addresses, address); + assert(address->network->n_static_addresses > 0); + address->network->n_static_addresses--; + + if (address->section) + hashmap_remove(address->network->addresses_by_section, address->section); + } + + if (address->link) { + set_remove(address->link->addresses, address); + set_remove(address->link->addresses_foreign, address); + + if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address)) + memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr)); + } + + network_config_section_free(address->section); + free(address->label); + free(address); +} + +static uint32_t address_prefix(const Address *a) { + assert(a); + + /* make sure we don't try to shift by 32. + * See ISO/IEC 9899:TC3 § 6.5.7.3. */ + if (a->prefixlen == 0) + return 0; + + if (a->in_addr_peer.in.s_addr != 0) + return be32toh(a->in_addr_peer.in.s_addr) >> (32 - a->prefixlen); + else + return be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen); +} + +static void address_hash_func(const Address *a, struct siphash *state) { + assert(a); + + siphash24_compress(&a->family, sizeof(a->family), state); + + switch (a->family) { + case AF_INET: + siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state); + + /* peer prefix */ + uint32_t prefix = address_prefix(a); + siphash24_compress(&prefix, sizeof(prefix), state); + + _fallthrough_; + case AF_INET6: + /* local address */ + siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state); + + break; + default: + /* treat any other address family as AF_UNSPEC */ + break; + } +} + +static int address_compare_func(const Address *a1, const Address *a2) { + int r; + + r = CMP(a1->family, a2->family); + if (r != 0) + return r; + + switch (a1->family) { + /* use the same notion of equality as the kernel does */ + case AF_INET: + r = CMP(a1->prefixlen, a2->prefixlen); + if (r != 0) + return r; + + uint32_t prefix1 = address_prefix(a1); + uint32_t prefix2 = address_prefix(a2); + r = CMP(prefix1, prefix2); + if (r != 0) + return r; + + _fallthrough_; + case AF_INET6: + return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family)); + default: + /* treat any other address family as AF_UNSPEC */ + return 0; + } +} + +DEFINE_PRIVATE_HASH_OPS(address_hash_ops, Address, address_hash_func, address_compare_func); + +bool address_equal(Address *a1, Address *a2) { + if (a1 == a2) + return true; + + if (!a1 || !a2) + return false; + + return address_compare_func(a1, a2) == 0; +} + +static int address_establish(Address *address, Link *link) { + bool masq; + int r; + + assert(address); + assert(link); + + masq = link->network && + link->network->ip_masquerade && + address->family == AF_INET && + address->scope < RT_SCOPE_LINK; + + /* Add firewall entry if this is requested */ + if (address->ip_masquerade_done != masq) { + union in_addr_union masked = address->in_addr; + in_addr_mask(address->family, &masked, address->prefixlen); + + r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); + if (r < 0) + return r; + + address->ip_masquerade_done = masq; + } + + return 0; +} + +static int address_add_internal(Link *link, Set **addresses, + int family, + const union in_addr_union *in_addr, + unsigned char prefixlen, + Address **ret) { + _cleanup_(address_freep) Address *address = NULL; + int r; + + assert(link); + assert(addresses); + assert(in_addr); + + r = address_new(&address); + if (r < 0) + return r; + + address->family = family; + address->in_addr = *in_addr; + address->prefixlen = prefixlen; + /* Consider address tentative until we get the real flags from the kernel */ + address->flags = IFA_F_TENTATIVE; + + r = set_ensure_allocated(addresses, &address_hash_ops); + if (r < 0) + return r; + + r = set_put(*addresses, address); + if (r < 0) + return r; + if (r == 0) + return -EEXIST; + + address->link = link; + + if (ret) + *ret = address; + + address = NULL; + + return 0; +} + +int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { + return address_add_internal(link, &link->addresses_foreign, family, in_addr, prefixlen, ret); +} + +int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { + Address *address; + int r; + + r = address_get(link, family, in_addr, prefixlen, &address); + if (r == -ENOENT) { + /* Address does not exist, create a new one */ + r = address_add_internal(link, &link->addresses, family, in_addr, prefixlen, &address); + if (r < 0) + return r; + } else if (r == 0) { + /* Take over a foreign address */ + r = set_ensure_allocated(&link->addresses, &address_hash_ops); + if (r < 0) + return r; + + r = set_put(link->addresses, address); + if (r < 0) + return r; + + set_remove(link->addresses_foreign, address); + } else if (r == 1) { + /* Already exists, do nothing */ + ; + } else + return r; + + if (ret) + *ret = address; + + return 0; +} + +static int address_release(Address *address) { + int r; + + assert(address); + assert(address->link); + + /* Remove masquerading firewall entry if it was added */ + if (address->ip_masquerade_done) { + union in_addr_union masked = address->in_addr; + in_addr_mask(address->family, &masked, address->prefixlen); + + r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); + if (r < 0) + return r; + + address->ip_masquerade_done = false; + } + + return 0; +} + +int address_update( + Address *address, + unsigned char flags, + unsigned char scope, + const struct ifa_cacheinfo *cinfo) { + + bool ready; + int r; + + assert(address); + assert(cinfo); + assert_return(address->link, 1); + + if (IN_SET(address->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + ready = address_is_ready(address); + + address->flags = flags; + address->scope = scope; + address->cinfo = *cinfo; + + link_update_operstate(address->link, true); + link_check_ready(address->link); + + if (!ready && + address_is_ready(address) && + address->family == AF_INET6 && + in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 && + in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) { + + r = link_ipv6ll_gained(address->link, &address->in_addr.in6); + if (r < 0) + return r; + } + + return 0; +} + +int address_drop(Address *address) { + Link *link; + bool ready; + int r; + + assert(address); + + ready = address_is_ready(address); + link = address->link; + + r = address_release(address); + if (r < 0) + log_link_warning_errno(link, r, "Failed to disable IP masquerading, ignoring: %m"); + + address_free(address); + + link_update_operstate(link, true); + + if (link && !ready) + link_check_ready(link); + + return 0; +} + +int address_get(Link *link, + int family, + const union in_addr_union *in_addr, + unsigned char prefixlen, + Address **ret) { + + Address address, *existing; + + assert(link); + assert(in_addr); + + address = (Address) { + .family = family, + .in_addr = *in_addr, + .prefixlen = prefixlen, + }; + + existing = set_get(link->addresses, &address); + if (existing) { + if (ret) + *ret = existing; + return 1; + } + + existing = set_get(link->addresses_foreign, &address); + if (existing) { + if (ret) + *ret = existing; + return 0; + } + + return -ENOENT; +} + +static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EADDRNOTAVAIL) + log_link_warning_errno(link, r, "Could not drop address: %m"); + + return 1; +} + +int address_remove( + Address *address, + Link *link, + link_netlink_message_handler_t callback) { + + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(address); + assert(IN_SET(address->family, AF_INET, AF_INET6)); + assert(link); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *b = NULL; + + (void) in_addr_to_string(address->family, &address->in_addr, &b); + log_link_debug(link, "Removing address %s", strna(b)); + } + + r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR, + link->ifindex, address->family); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m"); + + r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Could not set prefixlen: %m"); + + r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, + callback ?: address_remove_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static int address_acquire(Link *link, Address *original, Address **ret) { + union in_addr_union in_addr = IN_ADDR_NULL; + struct in_addr broadcast = {}; + _cleanup_(address_freep) Address *na = NULL; + int r; + + assert(link); + assert(original); + assert(ret); + + /* Something useful was configured? just use it */ + r = in_addr_is_null(original->family, &original->in_addr); + if (r <= 0) + return r; + + /* The address is configured to be 0.0.0.0 or [::] by the user? + * Then let's acquire something more useful from the pool. */ + r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr); + if (r < 0) + return r; + if (r == 0) + return -EBUSY; + + if (original->family == AF_INET) { + /* Pick first address in range for ourselves ... */ + in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1); + + /* .. and use last as broadcast address */ + if (original->prefixlen > 30) + broadcast.s_addr = 0; + else + broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen); + } else if (original->family == AF_INET6) + in_addr.in6.s6_addr[15] |= 1; + + r = address_new(&na); + if (r < 0) + return r; + + na->family = original->family; + na->prefixlen = original->prefixlen; + na->scope = original->scope; + na->cinfo = original->cinfo; + + if (original->label) { + na->label = strdup(original->label); + if (!na->label) + return -ENOMEM; + } + + na->broadcast = broadcast; + na->in_addr = in_addr; + + LIST_PREPEND(addresses, link->pool_addresses, na); + + *ret = TAKE_PTR(na); + + return 0; +} + +int address_configure( + Address *address, + Link *link, + link_netlink_message_handler_t callback, + bool update) { + + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(address); + assert(IN_SET(address->family, AF_INET, AF_INET6)); + assert(link); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + assert(callback); + + /* If this is a new address, then refuse adding more than the limit */ + if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 && + set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX) + return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG), + "Too many addresses are configured, refusing: %m"); + + r = address_acquire(link, address, &address); + if (r < 0) + return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m"); + + if (update) + r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req, + link->ifindex, address->family); + else + r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR, + link->ifindex, address->family); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m"); + + r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Could not set prefixlen: %m"); + + address->flags |= IFA_F_PERMANENT; + + if (address->home_address) + address->flags |= IFA_F_HOMEADDRESS; + + if (address->duplicate_address_detection) + address->flags |= IFA_F_NODAD; + + if (address->manage_temporary_address) + address->flags |= IFA_F_MANAGETEMPADDR; + + if (!address->prefix_route) + address->flags |= IFA_F_NOPREFIXROUTE; + + if (address->autojoin) + address->flags |= IFA_F_MCAUTOJOIN; + + r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff)); + if (r < 0) + return log_link_error_errno(link, r, "Could not set flags: %m"); + + if (address->flags & ~0xff) { + r = sd_netlink_message_append_u32(req, IFA_FLAGS, address->flags); + if (r < 0) + return log_link_error_errno(link, r, "Could not set extended flags: %m"); + } + + r = sd_rtnl_message_addr_set_scope(req, address->scope); + if (r < 0) + return log_link_error_errno(link, r, "Could not set scope: %m"); + + r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m"); + + if (in_addr_is_null(address->family, &address->in_addr_peer) == 0) { + r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m"); + } else if (address->family == AF_INET && address->prefixlen <= 30) { + r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m"); + } + + if (address->label) { + r = sd_netlink_message_append_string(req, IFA_LABEL, address->label); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m"); + } + + r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m"); + + r = address_establish(address, link); + if (r < 0) + log_link_warning_errno(link, r, "Could not enable IP masquerading, ignoring: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link); + if (r < 0) { + address_release(address); + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + } + + link_ref(link); + + if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer)) + r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, NULL); + else + r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL); + if (r < 0) { + address_release(address); + return log_link_error_errno(link, r, "Could not add address: %m"); + } + + return 1; +} + +int config_parse_broadcast( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(address_free_or_set_invalidp) Address *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + if (n->family == AF_INET6) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue); + return 0; + } + + r = in_addr_from_string(AF_INET, rvalue, (union in_addr_union*) &n->broadcast); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Broadcast is invalid, ignoring assignment: %s", rvalue); + return 0; + } + + n->family = AF_INET; + n = NULL; + + return 0; +} + +int config_parse_address(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(address_free_or_set_invalidp) Address *n = NULL; + union in_addr_union buffer; + unsigned char prefixlen; + int r, f; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(section, "Network")) { + /* we are not in an Address section, so treat + * this as the special '0' section */ + r = address_new_static(network, NULL, 0, &n); + } else + r = address_new_static(network, filename, section_line, &n); + + if (r < 0) + return r; + + /* Address=address/prefixlen */ + r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_REFUSE, &f, &buffer, &prefixlen); + if (r == -ENOANO) { + log_syntax(unit, LOG_ERR, filename, line, r, + "An address '%s' is specified without prefix length. " + "The behavior of parsing addresses without prefix length will be changed in the future release. " + "Please specify prefix length explicitly.", rvalue); + + r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_LEGACY, &f, &buffer, &prefixlen); + } + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid address '%s', ignoring assignment: %m", rvalue); + return 0; + } + + if (n->family != AF_UNSPEC && f != n->family) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Address is incompatible, ignoring assignment: %s", rvalue); + return 0; + } + + if (in_addr_is_null(f, &buffer)) { + /* Will use address from address pool. Note that for ipv6 case, prefix of the address + * pool is 8, but 40 bit is used by the global ID and 16 bit by the subnet ID. So, + * let's limit the prefix length to 64 or larger. See RFC4193. */ + if ((f == AF_INET && prefixlen < 8) || + (f == AF_INET6 && prefixlen < 64)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Null address with invalid prefixlen='%u', ignoring assignment: %s", + prefixlen, rvalue); + return 0; + } + } + + n->family = f; + n->prefixlen = prefixlen; + + if (streq(lvalue, "Address")) + n->in_addr = buffer; + else + n->in_addr_peer = buffer; + + if (n->family == AF_INET && n->broadcast.s_addr == 0 && n->prefixlen <= 30) + n->broadcast.s_addr = n->in_addr.in.s_addr | htobe32(0xfffffffflu >> n->prefixlen); + + n = NULL; + + return 0; +} + +int config_parse_label( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(address_free_or_set_invalidp) Address *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + if (!address_label_valid(rvalue)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Interface label is too long or invalid, ignoring assignment: %s", rvalue); + return 0; + } + + r = free_and_strdup(&n->label, rvalue); + if (r < 0) + return log_oom(); + + n = NULL; + return 0; +} + +int config_parse_lifetime(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; + _cleanup_(address_free_or_set_invalidp) Address *n = NULL; + unsigned k; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + /* We accept only "forever", "infinity", or "0". */ + if (STR_IN_SET(rvalue, "forever", "infinity")) + k = CACHE_INFO_INFINITY_LIFE_TIME; + else if (streq(rvalue, "0")) + k = 0; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid PreferredLifetime= value, ignoring: %s", rvalue); + return 0; + } + + n->cinfo.ifa_prefered = k; + n = NULL; + + return 0; +} + +int config_parse_address_flags(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; + _cleanup_(address_free_or_set_invalidp) Address *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse address flag, ignoring: %s", rvalue); + return 0; + } + + if (streq(lvalue, "HomeAddress")) + n->home_address = r; + else if (streq(lvalue, "DuplicateAddressDetection")) + n->duplicate_address_detection = r; + else if (streq(lvalue, "ManageTemporaryAddress")) + n->manage_temporary_address = r; + else if (streq(lvalue, "PrefixRoute")) + n->prefix_route = !r; + else if (streq(lvalue, "AddPrefixRoute")) + n->prefix_route = r; + else if (streq(lvalue, "AutoJoin")) + n->autojoin = r; + else + assert_not_reached("Invalid address flag type."); + + n = NULL; + return 0; +} + +int config_parse_address_scope(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; + _cleanup_(address_free_or_set_invalidp) Address *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = address_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + if (streq(rvalue, "host")) + n->scope = RT_SCOPE_HOST; + else if (streq(rvalue, "link")) + n->scope = RT_SCOPE_LINK; + else if (streq(rvalue, "global")) + n->scope = RT_SCOPE_UNIVERSE; + else { + r = safe_atou8(rvalue , &n->scope); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Could not parse address scope \"%s\", ignoring assignment: %m", rvalue); + return 0; + } + } + + n = NULL; + return 0; +} + +bool address_is_ready(const Address *a) { + assert(a); + + return !(a->flags & IFA_F_TENTATIVE); +} + +int address_section_verify(Address *address) { + if (section_is_invalid(address->section)) + return -EINVAL; + + if (address->family == AF_UNSPEC) { + assert(address->section); + + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Address section without Address= field configured. " + "Ignoring [Address] section from line %u.", + address->section->filename, address->section->line); + } + + return 0; +} diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h new file mode 100644 index 00000000..455985d2 --- /dev/null +++ b/src/network/networkd-address.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "conf-parser.h" +#include "in-addr-util.h" + +typedef struct Address Address; + +#include "networkd-link.h" +#include "networkd-network.h" +#include "networkd-util.h" + +#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU + +typedef struct Network Network; +typedef struct Link Link; +typedef struct NetworkConfigSection NetworkConfigSection; + +struct Address { + Network *network; + NetworkConfigSection *section; + + Link *link; + + int family; + unsigned char prefixlen; + unsigned char scope; + uint32_t flags; + char *label; + + struct in_addr broadcast; + struct ifa_cacheinfo cinfo; + + union in_addr_union in_addr; + union in_addr_union in_addr_peer; + + bool ip_masquerade_done:1; + bool duplicate_address_detection; + bool manage_temporary_address; + bool home_address; + bool prefix_route; + bool autojoin; + + LIST_FIELDS(Address, addresses); +}; + +int address_new(Address **ret); +void address_free(Address *address); +int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); +int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); +int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); +int address_update(Address *address, unsigned char flags, unsigned char scope, const struct ifa_cacheinfo *cinfo); +int address_drop(Address *address); +int address_configure(Address *address, Link *link, link_netlink_message_handler_t callback, bool update); +int address_remove(Address *address, Link *link, link_netlink_message_handler_t callback); +bool address_equal(Address *a1, Address *a2); +bool address_is_ready(const Address *a); +int address_section_verify(Address *a); + +DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free); + +CONFIG_PARSER_PROTOTYPE(config_parse_address); +CONFIG_PARSER_PROTOTYPE(config_parse_broadcast); +CONFIG_PARSER_PROTOTYPE(config_parse_label); +CONFIG_PARSER_PROTOTYPE(config_parse_lifetime); +CONFIG_PARSER_PROTOTYPE(config_parse_address_flags); +CONFIG_PARSER_PROTOTYPE(config_parse_address_scope); diff --git a/src/network/networkd-brvlan.c b/src/network/networkd-brvlan.c new file mode 100644 index 00000000..c3c5d535 --- /dev/null +++ b/src/network/networkd-brvlan.c @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2016 BISDN GmbH. All rights reserved. +***/ + +#include +#include +#include + +#include "alloc-util.h" +#include "conf-parser.h" +#include "netlink-util.h" +#include "networkd-brvlan.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "networkd-network.h" +#include "parse-util.h" +#include "vlan-util.h" + +static bool is_bit_set(unsigned bit, uint32_t scope) { + assert(bit < sizeof(scope)*8); + return scope & (UINT32_C(1) << bit); +} + +static void set_bit(unsigned nr, uint32_t *addr) { + if (nr < BRIDGE_VLAN_BITMAP_MAX) + addr[nr / 32] |= (UINT32_C(1) << (nr % 32)); +} + +static int find_next_bit(int i, uint32_t x) { + int j; + + if (i >= 32) + return -1; + + /* find first bit */ + if (i < 0) + return BUILTIN_FFS_U32(x); + + /* mask off prior finds to get next */ + j = __builtin_ffs(x >> i); + return j ? j + i : 0; +} + +static int append_vlan_info_data(Link *const link, sd_netlink_message *req, uint16_t pvid, const uint32_t *br_vid_bitmap, const uint32_t *br_untagged_bitmap) { + struct bridge_vlan_info br_vlan; + int i, j, k, r, cnt; + uint16_t begin, end; + bool done, untagged = false; + + assert(link); + assert(req); + assert(br_vid_bitmap); + assert(br_untagged_bitmap); + + cnt = 0; + + begin = end = UINT16_MAX; + for (k = 0; k < BRIDGE_VLAN_BITMAP_LEN; k++) { + unsigned base_bit; + uint32_t vid_map = br_vid_bitmap[k]; + uint32_t untagged_map = br_untagged_bitmap[k]; + + base_bit = k * 32; + i = -1; + done = false; + do { + j = find_next_bit(i, vid_map); + if (j > 0) { + /* first hit of any bit */ + if (begin == UINT16_MAX && end == UINT16_MAX) { + begin = end = j - 1 + base_bit; + untagged = is_bit_set(j - 1, untagged_map); + goto next; + } + + /* this bit is a continuation of prior bits */ + if (j - 2 + base_bit == end && untagged == is_bit_set(j - 1, untagged_map) && (uint16_t)j - 1 + base_bit != pvid && (uint16_t)begin != pvid) { + end++; + goto next; + } + } else + done = true; + + if (begin != UINT16_MAX) { + cnt++; + if (done && k < BRIDGE_VLAN_BITMAP_LEN - 1) + break; + + br_vlan.flags = 0; + if (untagged) + br_vlan.flags |= BRIDGE_VLAN_INFO_UNTAGGED; + + if (begin == end) { + br_vlan.vid = begin; + + if (begin == pvid) + br_vlan.flags |= BRIDGE_VLAN_INFO_PVID; + + r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan)); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m"); + } else { + br_vlan.vid = begin; + br_vlan.flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN; + + r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan)); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m"); + + br_vlan.vid = end; + br_vlan.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN; + br_vlan.flags |= BRIDGE_VLAN_INFO_RANGE_END; + + r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan)); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m"); + } + + if (done) + break; + } + if (j > 0) { + begin = end = j - 1 + base_bit; + untagged = is_bit_set(j - 1, untagged_map); + } + + next: + i = j; + } while (!done); + } + + assert(cnt > 0); + return cnt; +} + +static int set_brvlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) + log_link_error_errno(link, r, "Could not add VLAN to bridge port: %m"); + + return 1; +} + +int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + sd_netlink *rtnl; + uint16_t flags; + int r; + + assert(link); + assert(link->manager); + assert(br_vid_bitmap); + assert(br_untagged_bitmap); + assert(link->network); + + /* pvid might not be in br_vid_bitmap yet */ + if (pvid) + set_bit(pvid, br_vid_bitmap); + + rtnl = link->manager->rtnl; + + /* create new RTM message */ + r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_rtnl_message_link_set_family(req, PF_BRIDGE); + if (r < 0) + return log_link_error_errno(link, r, "Could not set message family: %m"); + + r = sd_netlink_message_open_container(req, IFLA_AF_SPEC); + if (r < 0) + return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m"); + + /* master needs flag self */ + if (!link->network->bridge) { + flags = BRIDGE_FLAGS_SELF; + sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(uint16_t)); + } + + /* add vlan info */ + r = append_vlan_info_data(link, req, pvid, br_vid_bitmap, br_untagged_bitmap); + if (r < 0) + return log_link_error_errno(link, r, "Could not append VLANs: %m"); + + r = sd_netlink_message_close_container(req); + if (r < 0) + return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); + + /* send message to the kernel */ + r = netlink_call_async(rtnl, NULL, req, set_brvlan_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +int config_parse_brvlan_pvid(const char *unit, const char *filename, + unsigned line, const char *section, + unsigned section_line, const char *lvalue, + int ltype, const char *rvalue, void *data, + void *userdata) { + Network *network = userdata; + uint16_t pvid; + int r; + + r = parse_vlanid(rvalue, &pvid); + if (r < 0) + return r; + + network->pvid = pvid; + network->use_br_vlan = true; + + return 0; +} + +int config_parse_brvlan_vlan(const char *unit, const char *filename, + unsigned line, const char *section, + unsigned section_line, const char *lvalue, + int ltype, const char *rvalue, void *data, + void *userdata) { + Network *network = userdata; + uint16_t vid, vid_end; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_vid_range(rvalue, &vid, &vid_end); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VLAN, ignoring: %s", rvalue); + return 0; + } + + for (; vid <= vid_end; vid++) + set_bit(vid, network->br_vid_bitmap); + + network->use_br_vlan = true; + return 0; +} + +int config_parse_brvlan_untagged(const char *unit, const char *filename, + unsigned line, const char *section, + unsigned section_line, const char *lvalue, + int ltype, const char *rvalue, void *data, + void *userdata) { + Network *network = userdata; + int r; + uint16_t vid, vid_end; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_vid_range(rvalue, &vid, &vid_end); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Could not parse VLAN: %s", rvalue); + return 0; + } + + for (; vid <= vid_end; vid++) { + set_bit(vid, network->br_vid_bitmap); + set_bit(vid, network->br_untagged_bitmap); + } + + network->use_br_vlan = true; + return 0; +} diff --git a/src/network/networkd-brvlan.h b/src/network/networkd-brvlan.h new file mode 100644 index 00000000..75330340 --- /dev/null +++ b/src/network/networkd-brvlan.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2016 BISDN GmbH. All rights reserved. +***/ + +#include + +#include "conf-parser.h" + +#define BRIDGE_VLAN_BITMAP_MAX 4096 +#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32) + +typedef struct Link Link; + +int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap); + +CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_pvid); +CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_vlan); +CONFIG_PARSER_PROTOTYPE(config_parse_brvlan_untagged); diff --git a/src/network/networkd-can.c b/src/network/networkd-can.c new file mode 100644 index 00000000..5755df57 --- /dev/null +++ b/src/network/networkd-can.c @@ -0,0 +1,231 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "netlink-util.h" +#include "networkd-can.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "string-util.h" + +static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + /* we warn but don't fail the link, as it may be brought up later */ + log_link_warning_errno(link, r, "Could not bring up interface: %m"); + + return 1; +} + +static int link_up_can(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + + log_link_debug(link, "Bringing CAN link up"); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP); + if (r < 0) + return log_link_error_errno(link, r, "Could not set link flags: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + log_link_debug(link, "Set link"); + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_error_errno(link, r, "Failed to configure CAN link: %m"); + link_enter_failed(link); + } + + return 1; +} + +static int link_set_can(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(link); + assert(link->network); + assert(link->manager); + assert(link->manager->rtnl); + + log_link_debug(link, "Configuring CAN link."); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Failed to allocate netlink message: %m"); + + r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK); + if (r < 0) + return log_link_error_errno(link, r, "Could not set netlink flags: %m"); + + r = sd_netlink_message_open_container(m, IFLA_LINKINFO); + if (r < 0) + return log_link_error_errno(link, r, "Failed to open netlink container: %m"); + + r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, link->kind); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m"); + + if (link->network->can_bitrate > 0 || link->network->can_sample_point > 0) { + struct can_bittiming bt = { + .bitrate = link->network->can_bitrate, + .sample_point = link->network->can_sample_point, + }; + + if (link->network->can_bitrate > UINT32_MAX) { + log_link_error(link, "bitrate (%zu) too big.", link->network->can_bitrate); + return -ERANGE; + } + + log_link_debug(link, "Setting bitrate = %d bit/s", bt.bitrate); + if (link->network->can_sample_point > 0) + log_link_debug(link, "Setting sample point = %d.%d%%", bt.sample_point / 10, bt.sample_point % 10); + else + log_link_debug(link, "Using default sample point"); + + r = sd_netlink_message_append_data(m, IFLA_CAN_BITTIMING, &bt, sizeof(bt)); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_CAN_BITTIMING attribute: %m"); + } + + if (link->network->can_restart_us > 0) { + char time_string[FORMAT_TIMESPAN_MAX]; + uint64_t restart_ms; + + if (link->network->can_restart_us == USEC_INFINITY) + restart_ms = 0; + else + restart_ms = DIV_ROUND_UP(link->network->can_restart_us, USEC_PER_MSEC); + + format_timespan(time_string, FORMAT_TIMESPAN_MAX, restart_ms * 1000, MSEC_PER_SEC); + + if (restart_ms > UINT32_MAX) { + log_link_error(link, "restart timeout (%s) too big.", time_string); + return -ERANGE; + } + + log_link_debug(link, "Setting restart = %s", time_string); + + r = sd_netlink_message_append_u32(m, IFLA_CAN_RESTART_MS, restart_ms); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_CAN_RESTART_MS attribute: %m"); + } + + if (link->network->can_triple_sampling >= 0) { + struct can_ctrlmode cm = { + .mask = CAN_CTRLMODE_3_SAMPLES, + .flags = link->network->can_triple_sampling ? CAN_CTRLMODE_3_SAMPLES : 0, + }; + + log_link_debug(link, "%sabling triple-sampling", link->network->can_triple_sampling ? "En" : "Dis"); + + r = sd_netlink_message_append_data(m, IFLA_CAN_CTRLMODE, &cm, sizeof(cm)); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_CAN_CTRLMODE attribute: %m"); + } + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_link_error_errno(link, r, "Failed to close netlink container: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_link_error_errno(link, r, "Failed to close netlink container: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, m, link_set_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + if (!(link->flags & IFF_UP)) + return link_up_can(link); + + return 0; +} + +static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) { + log_link_warning_errno(link, r, "Could not bring down interface: %m"); + link_enter_failed(link); + return 1; + } + + r = link_set_can(link); + if (r < 0) + link_enter_failed(link); + + return 1; +} + +int link_configure_can(Link *link) { + int r; + + link_set_state(link, LINK_STATE_CONFIGURING); + + if (streq_ptr(link->kind, "can")) { + /* The CAN interface must be down to configure bitrate, etc... */ + if ((link->flags & IFF_UP)) { + r = link_down(link, link_down_handler); + if (r < 0) { + link_enter_failed(link); + return r; + } + } else { + r = link_set_can(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + + return 0; + } + + if (!(link->flags & IFF_UP)) { + r = link_up_can(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + + return 0; +} diff --git a/src/network/networkd-can.h b/src/network/networkd-can.h new file mode 100644 index 00000000..c744bdfe --- /dev/null +++ b/src/network/networkd-can.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct Link Link; + +int link_configure_can(Link *link); diff --git a/src/network/networkd-conf.c b/src/network/networkd-conf.c new file mode 100644 index 00000000..eef7788c --- /dev/null +++ b/src/network/networkd-conf.c @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Vinay Kulkarni + ***/ + +#include +#include + +#include "conf-parser.h" +#include "def.h" +#include "dhcp-identifier.h" +#include "extract-word.h" +#include "hexdecoct.h" +#include "networkd-conf.h" +#include "networkd-manager.h" +#include "networkd-network.h" +#include "networkd-speed-meter.h" +#include "networkd-dhcp4.h" +#include "string-table.h" + +int manager_parse_config_file(Manager *m) { + int r; + + assert(m); + + r = config_parse_many_nulstr(PKGSYSCONFDIR "/networkd.conf", + CONF_PATHS_NULSTR("systemd/networkd.conf.d"), + "Network\0DHCP\0", + config_item_perf_lookup, networkd_gperf_lookup, + CONFIG_PARSE_WARN, m); + if (r < 0) + return r; + + if (m->use_speed_meter && m->speed_meter_interval_usec < SPEED_METER_MINIMUM_TIME_INTERVAL) { + char buf[FORMAT_TIMESPAN_MAX]; + + log_warning("SpeedMeterIntervalSec= is too small, using %s.", + format_timespan(buf, sizeof buf, SPEED_METER_MINIMUM_TIME_INTERVAL, USEC_PER_SEC)); + m->speed_meter_interval_usec = SPEED_METER_MINIMUM_TIME_INTERVAL; + } + + return 0; +} + +static const char* const duid_type_table[_DUID_TYPE_MAX] = { + [DUID_TYPE_LLT] = "link-layer-time", + [DUID_TYPE_EN] = "vendor", + [DUID_TYPE_LL] = "link-layer", + [DUID_TYPE_UUID] = "uuid", +}; +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType); + +int config_parse_duid_type( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *type_string = NULL; + const char *p = rvalue; + DUID *duid = data; + DUIDType type; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(duid); + + r = extract_first_word(&p, &type_string, ":", 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + if (r == 0) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to extract DUID type from '%s', ignoring.", rvalue); + return 0; + } + + type = duid_type_from_string(type_string); + if (type < 0) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to parse DUID type '%s', ignoring.", type_string); + return 0; + } + + if (!isempty(p)) { + usec_t u; + + if (type != DUID_TYPE_LLT) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + return 0; + } + + r = parse_timestamp(p, &u); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse timestamp, ignoring: %s", p); + return 0; + } + + duid->llt_time = u; + } + + duid->type = type; + + return 0; +} + +int config_parse_duid_rawdata( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + DUID *ret = data; + uint8_t raw_data[MAX_DUID_LEN]; + unsigned count = 0; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(ret); + + /* RawData contains DUID in format "NN:NN:NN..." */ + for (;;) { + int n1, n2, len, r; + uint32_t byte; + _cleanup_free_ char *cbyte = NULL; + + r = extract_first_word(&rvalue, &cbyte, ":", 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to read DUID, ignoring assignment: %s.", rvalue); + return 0; + } + if (r == 0) + break; + if (count >= MAX_DUID_LEN) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue); + return 0; + } + + len = strlen(cbyte); + if (!IN_SET(len, 1, 2)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid length - DUID byte: %s, ignoring assignment: %s.", cbyte, rvalue); + return 0; + } + n1 = unhexchar(cbyte[0]); + if (len == 2) + n2 = unhexchar(cbyte[1]); + else + n2 = 0; + + if (n1 < 0 || n2 < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid DUID byte: %s. Ignoring assignment: %s.", cbyte, rvalue); + return 0; + } + + byte = ((uint8_t) n1 << (4 * (len-1))) | (uint8_t) n2; + raw_data[count++] = byte; + } + + assert_cc(sizeof(raw_data) == sizeof(ret->raw_data)); + memcpy(ret->raw_data, raw_data, count); + ret->raw_data_len = count; + return 0; +} + +int config_parse_ip_service_type( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (streq(rvalue, "CS4")) + *((int *)data) = IPTOS_CLASS_CS4; + else if (streq(rvalue, "CS6")) + *((int *)data) = IPTOS_CLASS_CS6; + else + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Failed to parse IPServiceType type '%s', ignoring.", rvalue); + + return 0; +} diff --git a/src/network/networkd-conf.h b/src/network/networkd-conf.h new file mode 100644 index 00000000..a615998f --- /dev/null +++ b/src/network/networkd-conf.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2014 Vinay Kulkarni +***/ + +#include "conf-parser.h" + +typedef struct Manager Manager; + +int manager_parse_config_file(Manager *m); + +const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, GPERF_LEN_TYPE length); + +CONFIG_PARSER_PROTOTYPE(config_parse_duid_type); +CONFIG_PARSER_PROTOTYPE(config_parse_duid_rawdata); +CONFIG_PARSER_PROTOTYPE(config_parse_ip_service_type); diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c new file mode 100644 index 00000000..6465a8cf --- /dev/null +++ b/src/network/networkd-dhcp-common.c @@ -0,0 +1,448 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "dhcp-internal.h" +#include "escape.h" +#include "in-addr-util.h" +#include "networkd-dhcp-common.h" +#include "networkd-network.h" +#include "parse-util.h" +#include "string-table.h" +#include "strv.h" + +int config_parse_dhcp( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + AddressFamily *dhcp = data, s; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* Note that this is mostly like + * config_parse_address_family(), except that it + * understands some old names for the enum values */ + + s = address_family_from_string(rvalue); + if (s < 0) { + + /* Previously, we had a slightly different enum here, + * support its values for compatibility. */ + + if (streq(rvalue, "none")) + s = ADDRESS_FAMILY_NO; + else if (streq(rvalue, "v4")) + s = ADDRESS_FAMILY_IPV4; + else if (streq(rvalue, "v6")) + s = ADDRESS_FAMILY_IPV6; + else if (streq(rvalue, "both")) + s = ADDRESS_FAMILY_YES; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse DHCP option, ignoring: %s", rvalue); + return 0; + } + + log_syntax(unit, LOG_WARNING, filename, line, 0, + "DHCP=%s is deprecated, please use DHCP=%s instead.", + rvalue, address_family_to_string(s)); + } + + *dhcp = s; + return 0; +} + +int config_parse_dhcp_use_dns( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse UseDNS=%s, ignoring assignment: %m", rvalue); + return 0; + } + + network->dhcp_use_dns = r; + network->dhcp6_use_dns = r; + + return 0; +} + +int config_parse_dhcp_use_sip( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse UseSIP=%s, ignoring assignment: %m", rvalue); + return 0; + } + + network->dhcp_use_sip = r; + + return 0; +} + +int config_parse_dhcp_use_ntp( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse UseNTP=%s, ignoring assignment: %m", rvalue); + return 0; + } + + network->dhcp_use_ntp = r; + network->dhcp6_use_ntp = r; + + return 0; +} + +int config_parse_section_route_table( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + uint32_t rt; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou32(rvalue, &rt); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue); + return 0; + } + + if (STRPTR_IN_SET(section, "DHCP", "DHCPv4")) { + network->dhcp_route_table = rt; + network->dhcp_route_table_set = true; + } else { /* section is IPv6AcceptRA */ + network->ipv6_accept_ra_route_table = rt; + network->ipv6_accept_ra_route_table_set = true; + } + + return 0; +} + +int config_parse_iaid(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = data; + uint32_t iaid; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(network); + + r = safe_atou32(rvalue, &iaid); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Unable to read IAID, ignoring assignment: %s", rvalue); + return 0; + } + + network->iaid = iaid; + network->iaid_set = true; + + return 0; +} + +int config_parse_dhcp6_pd_hint( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = in_addr_prefix_from_string(rvalue, AF_INET6, (union in_addr_union *) &network->dhcp6_pd_address, &network->dhcp6_pd_length); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse PrefixDelegationHint=%s, ignoring assignment", rvalue); + return 0; + } + + if (network->dhcp6_pd_length < 1 || network->dhcp6_pd_length > 128) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid prefix length='%d', ignoring assignment", network->dhcp6_pd_length); + network->dhcp6_pd_length = 0; + return 0; + } + + return 0; +} + +int config_parse_dhcp_send_option( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt = NULL, *old = NULL; + _cleanup_free_ char *word = NULL, *q = NULL; + OrderedHashmap **options = data; + union in_addr_union addr; + DHCPOptionDataType type; + uint8_t u, uint8_data; + uint16_t uint16_data; + uint32_t uint32_data; + const void *udata; + const char *p; + ssize_t sz; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + *options = ordered_hashmap_free(*options); + return 0; + } + + p = rvalue; + r = extract_first_word(&p, &word, ":", 0); + if (r == -ENOMEM) + return log_oom(); + if (r <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid DHCP option, ignoring assignment: %s", rvalue); + return 0; + } + + r = safe_atou8(word, &u); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid DHCP option, ignoring assignment: %s", rvalue); + return 0; + } + if (u < 1 || u >= 255) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid DHCP option, valid range is 1-254, ignoring assignment: %s", rvalue); + return 0; + } + + word = mfree(word); + r = extract_first_word(&p, &word, ":", 0); + if (r == -ENOMEM) + return log_oom(); + if (r <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid DHCP option, ignoring assignment: %s", rvalue); + return 0; + } + + type = dhcp_option_data_type_from_string(word); + if (type < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid DHCP option data type, ignoring assignment: %s", p); + return 0; + } + + switch(type) { + case DHCP_OPTION_DATA_UINT8:{ + r = safe_atou8(p, &uint8_data); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DHCPv4 uint8 data, ignoring assignment: %s", p); + return 0; + } + + udata = &uint8_data; + sz = sizeof(uint8_t); + break; + } + case DHCP_OPTION_DATA_UINT16:{ + r = safe_atou16(p, &uint16_data); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DHCPv4 uint16 data, ignoring assignment: %s", p); + return 0; + } + + udata = &uint16_data; + sz = sizeof(uint16_t); + break; + } + case DHCP_OPTION_DATA_UINT32: { + r = safe_atou32(p, &uint32_data); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DHCPv4 uint32 data, ignoring assignment: %s", p); + return 0; + } + + udata = &uint32_data; + sz = sizeof(uint32_t); + + break; + } + case DHCP_OPTION_DATA_IPV4ADDRESS: { + r = in_addr_from_string(AF_INET, p, &addr); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DHCPv4 ipv4address data, ignoring assignment: %s", p); + return 0; + } + + udata = &addr.in; + sz = sizeof(addr.in.s_addr); + break; + } + case DHCP_OPTION_DATA_STRING: + sz = cunescape(p, 0, &q); + if (sz < 0) { + log_syntax(unit, LOG_ERR, filename, line, sz, + "Failed to decode DHCPv4 option data, ignoring assignment: %s", p); + } + + udata = q; + break; + default: + return -EINVAL; + } + + r = sd_dhcp_option_new(u, udata, sz, &opt); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to store DHCPv4 option '%s', ignoring assignment: %m", rvalue); + return 0; + } + + r = ordered_hashmap_ensure_allocated(options, &dhcp_option_hash_ops); + if (r < 0) + return log_oom(); + + /* Overwrite existing option */ + old = ordered_hashmap_remove(*options, UINT_TO_PTR(u)); + r = ordered_hashmap_put(*options, UINT_TO_PTR(u), opt); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to store DHCPv4 option '%s', ignoring assignment: %m", rvalue); + return 0; + } + + TAKE_PTR(opt); + return 0; +} + +DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, + "Failed to parse DHCP use domains setting"); + +static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = { + [DHCP_USE_DOMAINS_NO] = "no", + [DHCP_USE_DOMAINS_ROUTE] = "route", + [DHCP_USE_DOMAINS_YES] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES); + +static const char * const dhcp_option_data_type_table[_DHCP_OPTION_DATA_MAX] = { + [DHCP_OPTION_DATA_UINT8] = "uint8", + [DHCP_OPTION_DATA_UINT16] = "uint16", + [DHCP_OPTION_DATA_UINT32] = "uint32", + [DHCP_OPTION_DATA_STRING] = "string", + [DHCP_OPTION_DATA_IPV4ADDRESS] = "ipv4address", +}; + +DEFINE_STRING_TABLE_LOOKUP(dhcp_option_data_type, DHCPOptionDataType); diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h new file mode 100644 index 00000000..1d6ddbb8 --- /dev/null +++ b/src/network/networkd-dhcp-common.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "dhcp-identifier.h" +#include "time-util.h" + +#define DHCP_ROUTE_METRIC 1024 + +typedef enum DHCPUseDomains { + DHCP_USE_DOMAINS_NO, + DHCP_USE_DOMAINS_YES, + DHCP_USE_DOMAINS_ROUTE, + _DHCP_USE_DOMAINS_MAX, + _DHCP_USE_DOMAINS_INVALID = -1, +} DHCPUseDomains; + +typedef enum DHCPOptionDataType { + DHCP_OPTION_DATA_UINT8, + DHCP_OPTION_DATA_UINT16, + DHCP_OPTION_DATA_UINT32, + DHCP_OPTION_DATA_STRING, + DHCP_OPTION_DATA_IPV4ADDRESS, + _DHCP_OPTION_DATA_MAX, + _DHCP_OPTION_DATA_INVALID, +} DHCPOptionDataType; + +typedef struct DUID { + /* Value of Type in [DHCP] section */ + DUIDType type; + + uint8_t raw_data_len; + uint8_t raw_data[MAX_DUID_LEN]; + usec_t llt_time; +} DUID; + +const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; +DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; + +const char *dhcp_option_data_type_to_string(DHCPOptionDataType d) _const_; +DHCPOptionDataType dhcp_option_data_type_from_string(const char *d) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_dns); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_ntp); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_sip); +CONFIG_PARSER_PROTOTYPE(config_parse_iaid); +CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option); diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c new file mode 100644 index 00000000..fc1cd5ca --- /dev/null +++ b/src/network/networkd-dhcp-server.c @@ -0,0 +1,480 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-dhcp-server.h" + +#include "networkd-dhcp-server.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "networkd-network.h" +#include "parse-util.h" +#include "strv.h" +#include "string-table.h" +#include "string-util.h" + +static Address* link_find_dhcp_server_address(Link *link) { + Address *address; + + assert(link); + assert(link->network); + + /* The first statically configured address if there is any */ + LIST_FOREACH(addresses, address, link->network->static_addresses) { + + if (address->family != AF_INET) + continue; + + if (in_addr_is_null(address->family, &address->in_addr)) + continue; + + return address; + } + + /* If that didn't work, find a suitable address we got from the pool */ + LIST_FOREACH(addresses, address, link->pool_addresses) { + if (address->family != AF_INET) + continue; + + return address; + } + + return NULL; +} + +static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { + _cleanup_free_ struct in_addr *addresses = NULL; + size_t n_addresses = 0, n_allocated = 0; + unsigned i; + + log_debug("Copying DNS server information from %s", link->ifname); + + if (!link->network) + return 0; + + for (i = 0; i < link->network->n_dns; i++) { + struct in_addr ia; + + /* Only look for IPv4 addresses */ + if (link->network->dns[i].family != AF_INET) + continue; + + ia = link->network->dns[i].address.in; + + /* Never propagate obviously borked data */ + if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia)) + continue; + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) + return log_oom(); + + addresses[n_addresses++] = ia; + } + + if (link->network->dhcp_use_dns && link->dhcp_lease) { + const struct in_addr *da = NULL; + int j, n; + + n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da); + if (n > 0) { + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) + return log_oom(); + + for (j = 0; j < n; j++) + if (in4_addr_is_non_local(&da[j])) + addresses[n_addresses++] = da[j]; + } + } + + if (n_addresses <= 0) + return 0; + + return sd_dhcp_server_set_dns(s, addresses, n_addresses); +} + +static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { + _cleanup_free_ struct in_addr *addresses = NULL; + size_t n_addresses = 0, n_allocated = 0; + char **a; + + if (!link->network) + return 0; + + log_debug("Copying NTP server information from %s", link->ifname); + + STRV_FOREACH(a, link->network->ntp) { + union in_addr_union ia; + + /* Only look for IPv4 addresses */ + if (in_addr_from_string(AF_INET, *a, &ia) <= 0) + continue; + + /* Never propagate obviously borked data */ + if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in)) + continue; + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) + return log_oom(); + + addresses[n_addresses++] = ia.in; + } + + if (link->network->dhcp_use_ntp && link->dhcp_lease) { + const struct in_addr *da = NULL; + int j, n; + + n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da); + if (n > 0) { + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) + return log_oom(); + + for (j = 0; j < n; j++) + if (in4_addr_is_non_local(&da[j])) + addresses[n_addresses++] = da[j]; + } + } + + if (n_addresses <= 0) + return 0; + + return sd_dhcp_server_set_ntp(s, addresses, n_addresses); +} + +static int link_push_uplink_sip_to_dhcp_server(Link *link, sd_dhcp_server *s) { + _cleanup_free_ struct in_addr *addresses = NULL; + size_t n_addresses = 0, n_allocated = 0; + char **a; + + if (!link->network) + return 0; + + log_debug("Copying SIP server information from %s", link->ifname); + + STRV_FOREACH(a, link->network->sip) { + union in_addr_union ia; + + /* Only look for IPv4 addresses */ + if (in_addr_from_string(AF_INET, *a, &ia) <= 0) + continue; + + /* Never propagate obviously borked data */ + if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in)) + continue; + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) + return log_oom(); + + addresses[n_addresses++] = ia.in; + } + + if (link->network->dhcp_use_sip && link->dhcp_lease) { + const struct in_addr *da = NULL; + int j, n; + + n = sd_dhcp_lease_get_sip(link->dhcp_lease, &da); + if (n > 0) { + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) + return log_oom(); + + for (j = 0; j < n; j++) + if (in4_addr_is_non_local(&da[j])) + addresses[n_addresses++] = da[j]; + } + } + + if (n_addresses <= 0) + return 0; + + return sd_dhcp_server_set_sip(s, addresses, n_addresses); +} + +int dhcp4_server_configure(Link *link) { + bool acquired_uplink = false; + sd_dhcp_option *p; + Link *uplink = NULL; + Address *address; + Iterator i; + int r; + + address = link_find_dhcp_server_address(link); + if (!address) + return log_link_error_errno(link, SYNTHETIC_ERRNO(EBUSY), + "Failed to find suitable address for DHCPv4 server instance."); + + /* use the server address' subnet as the pool */ + r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen, + link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size); + if (r < 0) + return log_link_error_errno(link, r, "Failed to configure address pool for DHCPv4 server instance: %m"); + + /* TODO: + r = sd_dhcp_server_set_router(link->dhcp_server, &main_address->in_addr.in); + if (r < 0) + return r; + */ + + if (link->network->dhcp_server_max_lease_time_usec > 0) { + r = sd_dhcp_server_set_max_lease_time(link->dhcp_server, + DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC)); + if (r < 0) + return log_link_error_errno(link, r, "Failed to set maximum lease time for DHCPv4 server instance: %m"); + } + + if (link->network->dhcp_server_default_lease_time_usec > 0) { + r = sd_dhcp_server_set_default_lease_time(link->dhcp_server, + DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC)); + if (r < 0) + return log_link_error_errno(link, r, "Failed to set default lease time for DHCPv4 server instance: %m"); + } + + if (link->network->dhcp_server_emit_dns) { + if (link->network->n_dhcp_server_dns > 0) + r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns); + else { + uplink = manager_find_uplink(link->manager, link); + acquired_uplink = true; + + if (!uplink) { + log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink."); + r = 0; + } else + r = link_push_uplink_dns_to_dhcp_server(uplink, link->dhcp_server); + } + if (r < 0) + log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m"); + } + + if (link->network->dhcp_server_emit_ntp) { + if (link->network->n_dhcp_server_ntp > 0) + r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp); + else { + if (!acquired_uplink) + uplink = manager_find_uplink(link->manager, link); + + if (!uplink) { + log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink."); + r = 0; + } else + r = link_push_uplink_ntp_to_dhcp_server(uplink, link->dhcp_server); + + } + if (r < 0) + log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m"); + } + + if (link->network->dhcp_server_emit_sip) { + if (link->network->n_dhcp_server_sip > 0) + r = sd_dhcp_server_set_sip(link->dhcp_server, link->network->dhcp_server_sip, link->network->n_dhcp_server_sip); + else { + if (!acquired_uplink) + uplink = manager_find_uplink(link->manager, link); + + if (!uplink) { + log_link_debug(link, "Not emitting sip server information on link, couldn't find suitable uplink."); + r = 0; + } else + r = link_push_uplink_sip_to_dhcp_server(uplink, link->dhcp_server); + + } + if (r < 0) + log_link_warning_errno(link, r, "Failed to set SIP server for DHCP server, ignoring: %m"); + } + + r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router); + if (r < 0) + return log_link_error_errno(link, r, "Failed to set router emission for DHCP server: %m"); + + if (link->network->dhcp_server_emit_timezone) { + _cleanup_free_ char *buffer = NULL; + const char *tz; + + if (link->network->dhcp_server_timezone) + tz = link->network->dhcp_server_timezone; + else { + r = get_timezone(&buffer); + if (r < 0) + return log_error_errno(r, "Failed to determine timezone: %m"); + + tz = buffer; + } + + r = sd_dhcp_server_set_timezone(link->dhcp_server, tz); + if (r < 0) + return log_link_error_errno(link, r, "Failed to set timezone for DHCP server: %m"); + } + + ORDERED_HASHMAP_FOREACH(p, link->network->dhcp_server_send_options, i) { + r = sd_dhcp_server_add_option(link->dhcp_server, p); + if (r == -EEXIST) + continue; + if (r < 0) + return log_link_error_errno(link, r, "Failed to set DHCPv4 option: %m"); + } + + if (!sd_dhcp_server_is_running(link->dhcp_server)) { + r = sd_dhcp_server_start(link->dhcp_server); + if (r < 0) + return log_link_error_errno(link, r, "Could not start DHCPv4 server instance: %m"); + } + + return 0; +} + +int config_parse_dhcp_server_dns( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + union in_addr_union a; + struct in_addr *m; + + r = extract_first_word(&p, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + break; + + r = in_addr_from_string(AF_INET, w, &a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DNS server address '%s', ignoring assignment: %m", w); + continue; + } + + m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr)); + if (!m) + return log_oom(); + + m[n->n_dhcp_server_dns++] = a.in; + n->dhcp_server_dns = m; + } + + return 0; +} + +int config_parse_dhcp_server_ntp( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + union in_addr_union a; + struct in_addr *m; + + r = extract_first_word(&p, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + return 0; + + r = in_addr_from_string(AF_INET, w, &a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse NTP server address '%s', ignoring: %m", w); + continue; + } + + m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr)); + if (!m) + return log_oom(); + + m[n->n_dhcp_server_ntp++] = a.in; + n->dhcp_server_ntp = m; + } +} + +int config_parse_dhcp_server_sip( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + union in_addr_union a; + struct in_addr *m; + + r = extract_first_word(&p, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + return 0; + + r = in_addr_from_string(AF_INET, w, &a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse SIP server address '%s', ignoring: %m", w); + continue; + } + + m = reallocarray(n->dhcp_server_sip, n->n_dhcp_server_sip + 1, sizeof(struct in_addr)); + if (!m) + return log_oom(); + + m[n->n_dhcp_server_sip++] = a.in; + n->dhcp_server_sip = m; + } +} diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h new file mode 100644 index 00000000..c90d48ec --- /dev/null +++ b/src/network/networkd-dhcp-server.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "networkd-link.h" +#include "networkd-util.h" + +typedef struct Link Link; + +int dhcp4_server_configure(Link *link); + +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_sip); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c new file mode 100644 index 00000000..95c8b925 --- /dev/null +++ b/src/network/networkd-dhcp4.c @@ -0,0 +1,1576 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "dhcp-client-internal.h" +#include "hostname-util.h" +#include "parse-util.h" +#include "network-internal.h" +#include "networkd-dhcp4.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "networkd-network.h" +#include "string-table.h" +#include "string-util.h" +#include "sysctl-util.h" + +static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all); +static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all); +static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all); +static int dhcp_remove_address(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, link_netlink_message_handler_t callback); +static int dhcp_remove_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link); +static int dhcp_lease_renew(sd_dhcp_client *client, Link *link); + +void dhcp4_release_old_lease(Link *link) { + struct in_addr address = {}, address_old = {}; + + assert(link); + + if (!link->dhcp_lease_old) + return; + + assert(link->dhcp_lease); + + (void) sd_dhcp_lease_get_address(link->dhcp_lease_old, &address_old); + (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address); + + (void) dhcp_remove_routes(link, link->dhcp_lease_old, &address_old, false); + (void) dhcp_remove_router(link, link->dhcp_lease_old, &address_old, false); + (void) dhcp_remove_dns_routes(link, link->dhcp_lease_old, &address_old, false); + + if (!in4_addr_equal(&address_old, &address)) + (void) dhcp_remove_address(link, link->dhcp_lease_old, &address_old, NULL); + + link->dhcp_lease_old = sd_dhcp_lease_unref(link->dhcp_lease_old); + link_dirty(link); +} + +static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->dhcp4_messages > 0); + + link->dhcp4_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r == -ENETUNREACH && !link->dhcp4_route_retrying) { + + /* It seems kernel does not support that the prefix route cannot be configured with + * route table. Let's once drop the config and reconfigure them later. */ + + log_link_debug_errno(link, r, "Could not set DHCPv4 route, retrying later: %m"); + link->dhcp4_route_failed = true; + link->manager->dhcp4_prefix_root_cannot_set_table = true; + } else if (r < 0 && r != -EEXIST) { + log_link_error_errno(link, r, "Could not set DHCPv4 route: %m"); + link_enter_failed(link); + return 1; + } + + if (link->dhcp4_messages == 0) { + if (link->dhcp4_route_failed) { + struct in_addr address = {}; + + link->dhcp4_route_failed = false; + link->dhcp4_route_retrying = true; + + (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address); + (void) dhcp_remove_routes(link, link->dhcp_lease, &address, true); + (void) dhcp_remove_router(link, link->dhcp_lease, &address, true); + (void) dhcp_remove_dns_routes(link, link->dhcp_lease, &address, true); + (void) dhcp_remove_address(link, link->dhcp_lease, &address, dhcp_remove_address_handler); + + return 1; + } + link->dhcp4_configured = true; + /* New address and routes are configured now. Let's release old lease. */ + dhcp4_release_old_lease(link); + link_check_ready(link); + } + + return 1; +} + +static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) { + assert(route); + assert(self_addr); + + if (in4_addr_is_localhost(&route->dst.in) || + (!in4_addr_is_null(self_addr) && in4_addr_equal(&route->dst.in, self_addr))) + return RT_SCOPE_HOST; + else if (in4_addr_is_null(&route->gw.in)) + return RT_SCOPE_LINK; + else + return RT_SCOPE_UNIVERSE; +} + +static bool link_prefixroute(Link *link) { + return !link->network->dhcp_route_table_set || + link->network->dhcp_route_table == RT_TABLE_MAIN || + link->manager->dhcp4_prefix_root_cannot_set_table; +} + +static int dhcp_route_configure(Route **route, Link *link) { + int r; + + assert(route); + assert(*route); + assert(link); + + if (set_contains(link->dhcp_routes, *route)) + return 0; + + r = route_configure(*route, link, dhcp4_route_handler); + if (r <= 0) + return r; + + link->dhcp4_messages++; + + r = set_put(link->dhcp_routes, *route); + if (r < 0) + return r; + + TAKE_PTR(*route); + return 0; +} + +static int link_set_dns_routes(Link *link, const struct in_addr *address) { + const struct in_addr *dns; + uint32_t table; + int i, n, r; + + assert(link); + assert(link->dhcp_lease); + assert(link->network); + + if (!link->network->dhcp_use_dns || + !link->network->dhcp_routes_to_dns) + return 0; + + n = sd_dhcp_lease_get_dns(link->dhcp_lease, &dns); + if (IN_SET(n, 0, -ENODATA)) + return 0; + if (n < 0) + return log_link_warning_errno(link, n, "DHCP error: could not get DNS servers: %m"); + + table = link_get_dhcp_route_table(link); + + for (i = 0; i < n; i ++) { + _cleanup_(route_freep) Route *route = NULL; + + r = route_new(&route); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate route: %m"); + + /* Set routes to DNS servers. */ + + route->family = AF_INET; + route->dst.in = dns[i]; + route->dst_prefixlen = 32; + route->prefsrc.in = *address; + route->scope = RT_SCOPE_LINK; + route->protocol = RTPROT_DHCP; + route->priority = link->network->dhcp_route_metric; + route->table = table; + + r = dhcp_route_configure(&route, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not set route to DNS server: %m"); + } + + return 0; +} + +static int dhcp_prefix_route_from_lease( + const sd_dhcp_lease *lease, + uint32_t table, + const struct in_addr *address, + Route **ret_route) { + + Route *route; + struct in_addr netmask; + int r; + + r = sd_dhcp_lease_get_netmask((sd_dhcp_lease*) lease, &netmask); + if (r < 0) + return r; + + r = route_new(&route); + if (r < 0) + return r; + + route->family = AF_INET; + route->dst.in.s_addr = address->s_addr & netmask.s_addr; + route->dst_prefixlen = in4_addr_netmask_to_prefixlen(&netmask); + route->prefsrc.in = *address; + route->scope = RT_SCOPE_LINK; + route->protocol = RTPROT_DHCP; + route->table = table; + *ret_route = route; + return 0; +} + +static int link_set_dhcp_routes(Link *link) { + _cleanup_free_ sd_dhcp_route **static_routes = NULL; + bool classless_route = false, static_route = false; + const struct in_addr *router; + struct in_addr address; + int r, n, i; + uint32_t table; + + assert(link); + + if (!link->dhcp_lease) /* link went down while we configured the IP addresses? */ + return 0; + + if (!link->network) /* link went down while we configured the IP addresses? */ + return 0; + + if (!link->network->dhcp_use_routes) + return 0; + + if (!link_has_carrier(link) && !link->network->configure_without_carrier) + /* During configuring addresses, the link lost its carrier. As networkd is dropping + * the addresses now, let's not configure the routes either. */ + return 0; + + r = set_ensure_allocated(&link->dhcp_routes, &route_hash_ops); + if (r < 0) + return log_oom(); + + /* Clear old entries in case the set was already allocated */ + set_clear(link->dhcp_routes); + + table = link_get_dhcp_route_table(link); + + r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); + if (r < 0) + return log_link_warning_errno(link, r, "DHCP error: could not get address: %m"); + + if (!link_prefixroute(link)) { + _cleanup_(route_freep) Route *prefix_route = NULL; + + r = dhcp_prefix_route_from_lease(link->dhcp_lease, table, &address, &prefix_route); + if (r < 0) + return log_link_error_errno(link, r, "Could not create prefix route: %m"); + + r = dhcp_route_configure(&prefix_route, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not set prefix route: %m"); + } + + n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes); + if (n == -ENODATA) + log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m"); + else if (n < 0) + log_link_debug_errno(link, n, "DHCP: could not get routes: %m"); + + for (i = 0; i < n; i++) { + switch (sd_dhcp_route_get_option(static_routes[i])) { + case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE: + classless_route = true; + break; + case SD_DHCP_OPTION_STATIC_ROUTE: + static_route = true; + break; + } + } + + for (i = 0; i < n; i++) { + _cleanup_(route_freep) Route *route = NULL; + + /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option, + the DHCP client MUST ignore the Static Routes option. */ + if (classless_route && + sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE) + continue; + + r = route_new(&route); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate route: %m"); + + route->family = AF_INET; + route->protocol = RTPROT_DHCP; + assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0); + assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0); + assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0); + route->priority = link->network->dhcp_route_metric; + route->table = table; + route->scope = route_scope_from_address(route, &address); + if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE)) + route->prefsrc.in = address; + + if (set_contains(link->dhcp_routes, route)) + continue; + + r = dhcp_route_configure(&route, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not set route: %m"); + } + + r = sd_dhcp_lease_get_router(link->dhcp_lease, &router); + if (IN_SET(r, 0, -ENODATA)) + log_link_info(link, "DHCP: No gateway received from DHCP server."); + else if (r < 0) + log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m"); + else if (in4_addr_is_null(&router[0])) + log_link_info(link, "DHCP: Received gateway is null."); + + /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and + a Router option, the DHCP client MUST ignore the Router option. */ + if (classless_route && static_route) + log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option"); + + if (r > 0 && !classless_route && !in4_addr_is_null(&router[0])) { + _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL; + + r = route_new(&route_gw); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate route: %m"); + + /* The dhcp netmask may mask out the gateway. Add an explicit + * route for the gw host so that we can route no matter the + * netmask or existing kernel route tables. */ + route_gw->family = AF_INET; + route_gw->dst.in = router[0]; + route_gw->dst_prefixlen = 32; + route_gw->prefsrc.in = address; + route_gw->scope = RT_SCOPE_LINK; + route_gw->protocol = RTPROT_DHCP; + route_gw->priority = link->network->dhcp_route_metric; + route_gw->table = table; + + r = dhcp_route_configure(&route_gw, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not set host route: %m"); + + r = route_new(&route); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate route: %m"); + + route->family = AF_INET; + route->gw.in = router[0]; + route->prefsrc.in = address; + route->protocol = RTPROT_DHCP; + route->priority = link->network->dhcp_route_metric; + route->table = table; + + r = dhcp_route_configure(&route, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not set router: %m"); + } + + return link_set_dns_routes(link, &address); +} + +static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) { + _cleanup_free_ sd_dhcp_route **routes = NULL; + uint32_t table; + int n, i, r; + + assert(link); + assert(address); + + if (!link->network->dhcp_use_routes) + return 0; + + n = sd_dhcp_lease_get_routes(lease, &routes); + if (IN_SET(n, 0, -ENODATA)) + return 0; + else if (n < 0) + return log_link_error_errno(link, n, "DHCP error: Failed to get routes: %m"); + + table = link_get_dhcp_route_table(link); + + for (i = 0; i < n; i++) { + _cleanup_(route_freep) Route *route = NULL; + + r = route_new(&route); + if (r < 0) + return log_oom(); + + route->family = AF_INET; + assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0); + assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0); + assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0); + route->priority = link->network->dhcp_route_metric; + route->table = table; + route->scope = route_scope_from_address(route, address); + if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE)) + route->prefsrc.in = *address; + + if (!remove_all && set_contains(link->dhcp_routes, route)) + continue; + + (void) route_remove(route, link, NULL); + } + + return n; +} + +static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) { + _cleanup_(route_freep) Route *route_gw = NULL, *route = NULL; + const struct in_addr *router; + uint32_t table; + int r; + + assert(link); + assert(address); + + if (!link->network->dhcp_use_routes) + return 0; + + r = sd_dhcp_lease_get_router(lease, &router); + if (IN_SET(r, 0, -ENODATA)) { + log_link_debug(link, "DHCP: No gateway received from DHCP server."); + return 0; + } else if (r < 0) + return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m"); + else if (in4_addr_is_null(&router[0])) { + log_link_info(link, "DHCP: Received gateway is null, ignoring."); + return 0; + } + + table = link_get_dhcp_route_table(link); + + r = route_new(&route_gw); + if (r < 0) + return log_oom(); + + route_gw->family = AF_INET; + route_gw->dst.in = router[0]; + route_gw->dst_prefixlen = 32; + route_gw->prefsrc.in = *address; + route_gw->scope = RT_SCOPE_LINK; + route_gw->protocol = RTPROT_DHCP; + route_gw->priority = link->network->dhcp_route_metric; + route_gw->table = table; + + if (remove_all || !set_contains(link->dhcp_routes, route_gw)) + (void) route_remove(route_gw, link, NULL); + + r = route_new(&route); + if (r < 0) + return log_oom(); + + route->family = AF_INET; + route->gw.in = router[0]; + route->prefsrc.in = *address; + route->protocol = RTPROT_DHCP; + route->priority = link->network->dhcp_route_metric; + route->table = table; + + if (remove_all || !set_contains(link->dhcp_routes, route)) + (void) route_remove(route, link, NULL); + + return 0; +} + +static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) { + const struct in_addr *dns; + uint32_t table; + int i, n, r; + + assert(link); + assert(lease); + assert(link->network); + + if (!link->network->dhcp_use_dns || + !link->network->dhcp_routes_to_dns) + return 0; + + n = sd_dhcp_lease_get_dns(lease, &dns); + if (IN_SET(n, 0, -ENODATA)) + return 0; + if (n < 0) + return log_link_warning_errno(link, n, "DHCP error: could not get DNS servers: %m"); + + table = link_get_dhcp_route_table(link); + + for (i = 0; i < n; i ++) { + _cleanup_(route_freep) Route *route = NULL; + + r = route_new(&route); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate route: %m"); + + route->family = AF_INET; + route->dst.in = dns[i]; + route->dst_prefixlen = 32; + route->prefsrc.in = *address; + route->scope = RT_SCOPE_LINK; + route->protocol = RTPROT_DHCP; + route->priority = link->network->dhcp_route_metric; + route->table = table; + + if (!remove_all && set_contains(link->dhcp_routes, route)) + continue; + + (void) route_remove(route, link, NULL); + } + + if (!link_prefixroute(link)) { + _cleanup_(route_freep) Route *prefix_route = NULL; + + r = dhcp_prefix_route_from_lease(lease, table, address, &prefix_route); + if (r < 0) + return log_link_warning_errno(link, r, "Could not delete prefix route: %m"); + + if (remove_all || !set_contains(link->dhcp_routes, prefix_route)) + (void) route_remove(prefix_route, link, NULL); + } + + return 0; +} + +static int dhcp_remove_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + /* This is only used when retrying to assign the address received from DHCPv4 server. + * See dhcp4_route_handler(). */ + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_debug_errno(link, r, "Failed to remove DHCPv4 address, ignoring: %m"); + else + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + (void) dhcp_lease_renew(link->dhcp_client, link); + return 1; +} + +static int dhcp_remove_address( + Link *link, sd_dhcp_lease *lease, + const struct in_addr *address, + link_netlink_message_handler_t callback) { + + _cleanup_(address_freep) Address *a = NULL; + struct in_addr netmask; + int r; + + assert(link); + assert(address); + + if (in4_addr_is_null(address)) + return 0; + + r = address_new(&a); + if (r < 0) + return log_oom(); + + a->family = AF_INET; + a->in_addr.in = *address; + + if (sd_dhcp_lease_get_netmask(lease, &netmask) >= 0) + a->prefixlen = in4_addr_netmask_to_prefixlen(&netmask); + + (void) address_remove(a, link, callback); + + return 0; +} + +static int dhcp_reset_mtu(Link *link) { + uint16_t mtu; + int r; + + assert(link); + + if (!link->network->dhcp_use_mtu) + return 0; + + r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu); + if (r < 0) + return r; + + if (link->original_mtu == mtu) + return 0; + + r = link_set_mtu(link, link->original_mtu); + if (r < 0) { + log_link_error_errno(link, r, "DHCP error: could not reset MTU: %m"); + link_enter_failed(link); + return r; + } + + return 0; +} + +static int dhcp_reset_hostname(Link *link) { + const char *hostname; + int r; + + assert(link); + + if (!link->network->dhcp_use_hostname) + return 0; + + hostname = link->network->dhcp_hostname; + if (!hostname) + (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname); + + if (!hostname) + return 0; + + /* If a hostname was set due to the lease, then unset it now. */ + r = manager_set_hostname(link->manager, NULL); + if (r < 0) + return log_link_error_errno(link, r, "DHCP error: Failed to reset transient hostname: %m"); + + return 0; +} + +static int dhcp_lease_lost(Link *link) { + struct in_addr address = {}; + + assert(link); + assert(link->dhcp_lease); + + log_link_info(link, "DHCP lease lost"); + + link->dhcp4_configured = false; + + (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address); + (void) dhcp_remove_routes(link, link->dhcp_lease, &address, true); + (void) dhcp_remove_router(link, link->dhcp_lease, &address, true); + (void) dhcp_remove_dns_routes(link, link->dhcp_lease, &address, true); + (void) dhcp_remove_address(link, link->dhcp_lease, &address, NULL); + (void) dhcp_reset_mtu(link); + (void) dhcp_reset_hostname(link); + + link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease); + link_dirty(link); + + return 0; +} + +static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_error_errno(link, r, "Could not set DHCPv4 address: %m"); + link_enter_failed(link); + return 1; + } else if (r >= 0) + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + r = link_set_dhcp_routes(link); + if (r < 0) { + link_enter_failed(link); + return 1; + } + + /* Add back static routes since kernel removes while DHCPv4 address is removed from when lease expires */ + r = link_request_set_routes(link); + if (r < 0) { + link_enter_failed(link); + return 1; + } + + if (link->dhcp4_messages == 0) { + link->dhcp4_configured = true; + /* The new address is configured, and no route is requested. + * Let's drop the old lease. */ + dhcp4_release_old_lease(link); + link_check_ready(link); + } + + return 1; +} + +static int dhcp4_update_address(Link *link, + struct in_addr *address, + struct in_addr *netmask, + uint32_t lifetime) { + _cleanup_(address_freep) Address *addr = NULL; + unsigned prefixlen; + int r; + + assert(address); + assert(netmask); + assert(lifetime); + + prefixlen = in4_addr_netmask_to_prefixlen(netmask); + + r = address_new(&addr); + if (r < 0) + return r; + + addr->family = AF_INET; + addr->in_addr.in.s_addr = address->s_addr; + addr->cinfo.ifa_prefered = lifetime; + addr->cinfo.ifa_valid = lifetime; + addr->prefixlen = prefixlen; + addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr; + addr->prefix_route = link_prefixroute(link); + + /* allow reusing an existing address and simply update its lifetime + * in case it already exists */ + r = address_configure(addr, link, dhcp4_address_handler, true); + if (r < 0) + return r; + + return 0; +} + +static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) { + sd_dhcp_lease *lease; + struct in_addr address; + struct in_addr netmask; + uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME; + int r; + + assert(link); + assert(client); + assert(link->network); + + r = sd_dhcp_client_get_lease(client, &lease); + if (r < 0) + return log_link_warning_errno(link, r, "DHCP error: no lease: %m"); + + sd_dhcp_lease_unref(link->dhcp_lease); + link->dhcp4_configured = false; + link->dhcp_lease = sd_dhcp_lease_ref(lease); + link_dirty(link); + + r = sd_dhcp_lease_get_address(lease, &address); + if (r < 0) + return log_link_warning_errno(link, r, "DHCP error: no address: %m"); + + r = sd_dhcp_lease_get_netmask(lease, &netmask); + if (r < 0) + return log_link_warning_errno(link, r, "DHCP error: no netmask: %m"); + + if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) { + r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime); + if (r < 0) + return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m"); + } + + r = dhcp4_update_address(link, &address, &netmask, lifetime); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update IP address: %m"); + + return 0; +} + +static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { + const struct in_addr *router; + sd_dhcp_lease *lease; + struct in_addr address; + struct in_addr netmask; + unsigned prefixlen; + uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME; + int r; + + assert(client); + assert(link); + + link->dhcp4_configured = false; + + r = sd_dhcp_client_get_lease(client, &lease); + if (r < 0) + return log_link_error_errno(link, r, "DHCP error: No lease: %m"); + + r = sd_dhcp_lease_get_address(lease, &address); + if (r < 0) + return log_link_error_errno(link, r, "DHCP error: No address: %m"); + + r = sd_dhcp_lease_get_netmask(lease, &netmask); + if (r < 0) + return log_link_error_errno(link, r, "DHCP error: No netmask: %m"); + + prefixlen = in4_addr_netmask_to_prefixlen(&netmask); + + if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) { + r = sd_dhcp_lease_get_lifetime(lease, &lifetime); + if (r < 0) + return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m"); + } + + r = sd_dhcp_lease_get_router(lease, &router); + if (r < 0 && r != -ENODATA) + return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m"); + + if (r > 0 && !in4_addr_is_null(&router[0])) + log_struct(LOG_INFO, + LOG_LINK_INTERFACE(link), + LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u", + ADDRESS_FMT_VAL(address), + prefixlen, + ADDRESS_FMT_VAL(router[0])), + "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address), + "PREFIXLEN=%u", prefixlen, + "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(router[0])); + else + log_struct(LOG_INFO, + LOG_LINK_INTERFACE(link), + LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u", + ADDRESS_FMT_VAL(address), + prefixlen), + "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address), + "PREFIXLEN=%u", prefixlen); + + link->dhcp_lease = sd_dhcp_lease_ref(lease); + link_dirty(link); + + if (link->network->dhcp_use_mtu) { + uint16_t mtu; + + r = sd_dhcp_lease_get_mtu(lease, &mtu); + if (r >= 0) { + r = link_set_mtu(link, mtu); + if (r < 0) + log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu); + } + } + + if (link->network->dhcp_use_hostname) { + const char *dhcpname = NULL; + _cleanup_free_ char *hostname = NULL; + + if (link->network->dhcp_hostname) + dhcpname = link->network->dhcp_hostname; + else + (void) sd_dhcp_lease_get_hostname(lease, &dhcpname); + + if (dhcpname) { + r = shorten_overlong(dhcpname, &hostname); + if (r < 0) + log_link_warning_errno(link, r, "Unable to shorten overlong DHCP hostname '%s', ignoring: %m", dhcpname); + if (r == 1) + log_link_notice(link, "Overlong DHCP hostname received, shortened from '%s' to '%s'", dhcpname, hostname); + } + + if (hostname) { + r = manager_set_hostname(link->manager, hostname); + if (r < 0) + log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname); + } + } + + if (link->network->dhcp_use_timezone) { + const char *tz = NULL; + + (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz); + + if (tz) { + r = manager_set_timezone(link->manager, tz); + if (r < 0) + log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz); + } + } + + r = dhcp4_update_address(link, &address, &netmask, lifetime); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update IP address: %m"); + + return 0; +} + +static int dhcp_lease_ip_change(sd_dhcp_client *client, Link *link) { + int r; + + link->dhcp_lease_old = TAKE_PTR(link->dhcp_lease); + + /* On ip address change, to keep the connectability, we would like to assign new address and + * routes, and then release old lease. There are two possible success paths: + * + * 1. new address and routes are configured. + * -> handled by dhcp_release_old_lease() in dhcp4_route_handler(). + * 2. new address is configured and no route is requested. + * -> handled by dhcp_release_old_lease() in dhcp4_address_handler(). + * + * On error in assigning new address and routes, then the link always enters to the failed + * state. And link_enter_failed() leads to the DHCP client to be stopped. So, + * dhcp_release_old_lease() will be also called by link_stop_clients(). + */ + + r = dhcp_lease_acquired(client, link); + if (r < 0) { + /* If it fails, then the new address is not configured yet. + * So, let's simply drop the old lease. */ + sd_dhcp_lease_unref(link->dhcp_lease); + link->dhcp_lease = TAKE_PTR(link->dhcp_lease_old); + (void) dhcp_lease_lost(link); + return r; + } + + return 0; +} + +static int dhcp_server_is_black_listed(Link *link, sd_dhcp_client *client) { + sd_dhcp_lease *lease; + struct in_addr addr; + int r; + + assert(link); + assert(link->network); + assert(client); + + r = sd_dhcp_client_get_lease(client, &lease); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get DHCP lease: %m"); + + r = sd_dhcp_lease_get_server_identifier(lease, &addr); + if (r < 0) + return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m"); + + if (set_contains(link->network->dhcp_black_listed_ip, UINT32_TO_PTR(addr.s_addr))) { + log_struct(LOG_DEBUG, + LOG_LINK_INTERFACE(link), + LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in black listed ip addresses, ignoring offer", + ADDRESS_FMT_VAL(addr))); + return true; + } + + return false; +} + +static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) { + Link *link = userdata; + int r; + + assert(link); + assert(link->network); + assert(link->manager); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 0; + + switch (event) { + case SD_DHCP_CLIENT_EVENT_STOP: + + if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4)) { + assert(link->ipv4ll); + + log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address"); + + r = sd_ipv4ll_start(link->ipv4ll); + if (r < 0) + return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m"); + } + + if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) { + log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it."); + return 0; + } + + if (link->dhcp_lease) { + if (link->network->dhcp_send_release) + (void) sd_dhcp_client_send_release(client); + + r = dhcp_lease_lost(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + + break; + case SD_DHCP_CLIENT_EVENT_EXPIRED: + if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) { + log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it."); + return 0; + } + + if (link->dhcp_lease) { + r = dhcp_lease_lost(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + + break; + case SD_DHCP_CLIENT_EVENT_IP_CHANGE: + if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) { + log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it."); + return 0; + } + + r = dhcp_lease_ip_change(client, link); + if (r < 0) { + link_enter_failed(link); + return r; + } + + break; + case SD_DHCP_CLIENT_EVENT_RENEW: + r = dhcp_lease_renew(client, link); + if (r < 0) { + link_enter_failed(link); + return r; + } + break; + case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE: + r = dhcp_lease_acquired(client, link); + if (r < 0) { + link_enter_failed(link); + return r; + } + break; + case SD_DHCP_CLIENT_EVENT_SELECTING: + r = dhcp_server_is_black_listed(link, client); + if (r < 0) + return r; + if (r != 0) + return -ENOMSG; + break; + default: + if (event < 0) + log_link_warning_errno(link, event, "DHCP error: Client failed: %m"); + else + log_link_warning(link, "DHCP unknown event: %i", event); + break; + } + + return 0; +} + +static int dhcp4_set_hostname(Link *link) { + _cleanup_free_ char *hostname = NULL; + const char *hn; + int r; + + assert(link); + + if (!link->network->dhcp_send_hostname) + hn = NULL; + else if (link->network->dhcp_hostname) + hn = link->network->dhcp_hostname; + else { + r = gethostname_strict(&hostname); + if (r < 0 && r != -ENXIO) /* ENXIO: no hostname set or hostname is "localhost" */ + return r; + + hn = hostname; + } + + r = sd_dhcp_client_set_hostname(link->dhcp_client, hn); + if (r == -EINVAL && hostname) + /* Ignore error when the machine's hostname is not suitable to send in DHCP packet. */ + log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set hostname from kernel hostname, ignoring: %m"); + else if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set hostname: %m"); + + return 0; +} + +static bool promote_secondaries_enabled(const char *ifname) { + _cleanup_free_ char *promote_secondaries_sysctl = NULL; + char *promote_secondaries_path; + int r; + + promote_secondaries_path = strjoina("net/ipv4/conf/", ifname, "/promote_secondaries"); + r = sysctl_read(promote_secondaries_path, &promote_secondaries_sysctl); + if (r < 0) { + log_debug_errno(r, "Cannot read sysctl %s", promote_secondaries_path); + return false; + } + + truncate_nl(promote_secondaries_sysctl); + r = parse_boolean(promote_secondaries_sysctl); + if (r < 0) + log_warning_errno(r, "Cannot parse sysctl %s with content %s as boolean", promote_secondaries_path, promote_secondaries_sysctl); + return r > 0; +} + +/* dhcp4_set_promote_secondaries will ensure this interface has + * the "promote_secondaries" option in the kernel set. If this sysctl + * is not set DHCP will work only as long as the IP address does not + * changes between leases. The kernel will remove all secondary IP + * addresses of an interface otherwise. The way systemd-network works + * is that the new IP of a lease is added as a secondary IP and when + * the primary one expires it relies on the kernel to promote the + * secondary IP. See also https://github.com/systemd/systemd/issues/7163 + */ +int dhcp4_set_promote_secondaries(Link *link) { + int r; + + assert(link); + assert(link->network); + assert(link->network->dhcp & ADDRESS_FAMILY_IPV4); + + /* check if the kernel has promote_secondaries enabled for our + * interface. If it is not globally enabled or enabled for the + * specific interface we must either enable it. + */ + if (!(promote_secondaries_enabled("all") || promote_secondaries_enabled(link->ifname))) { + char *promote_secondaries_path = NULL; + + log_link_debug(link, "promote_secondaries is unset, setting it"); + promote_secondaries_path = strjoina("net/ipv4/conf/", link->ifname, "/promote_secondaries"); + r = sysctl_write(promote_secondaries_path, "1"); + if (r < 0) + log_link_warning_errno(link, r, "cannot set sysctl %s to 1", promote_secondaries_path); + return r > 0; + } + + return 0; +} + +int dhcp4_set_client_identifier(Link *link) { + int r; + + assert(link); + assert(link->network); + assert(link->dhcp_client); + + switch (link->network->dhcp_client_identifier) { + case DHCP_CLIENT_ID_DUID: { + /* If configured, apply user specified DUID and IAID */ + const DUID *duid = link_get_duid(link); + + if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0) + r = sd_dhcp_client_set_iaid_duid_llt(link->dhcp_client, + link->network->iaid_set, + link->network->iaid, + duid->llt_time); + else + r = sd_dhcp_client_set_iaid_duid(link->dhcp_client, + link->network->iaid_set, + link->network->iaid, + duid->type, + duid->raw_data_len > 0 ? duid->raw_data : NULL, + duid->raw_data_len); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set IAID+DUID: %m"); + break; + } + case DHCP_CLIENT_ID_DUID_ONLY: { + /* If configured, apply user specified DUID */ + const DUID *duid = link_get_duid(link); + + if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0) + r = sd_dhcp_client_set_duid_llt(link->dhcp_client, + duid->llt_time); + else + r = sd_dhcp_client_set_duid(link->dhcp_client, + duid->type, + duid->raw_data_len > 0 ? duid->raw_data : NULL, + duid->raw_data_len); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m"); + break; + } + case DHCP_CLIENT_ID_MAC: + r = sd_dhcp_client_set_client_id(link->dhcp_client, + ARPHRD_ETHER, + (const uint8_t *) &link->mac, + sizeof(link->mac)); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set client ID: %m"); + break; + default: + assert_not_reached("Unknown client identifier type."); + } + + return 0; +} + +int dhcp4_configure(Link *link) { + sd_dhcp_option *send_option; + void *request_options; + Iterator i; + int r; + + assert(link); + assert(link->network); + assert(link->network->dhcp & ADDRESS_FAMILY_IPV4); + + if (!link->dhcp_client) { + r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to create DHCP4 client: %m"); + } + + r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to attach event: %m"); + + r = sd_dhcp_client_set_mac(link->dhcp_client, + (const uint8_t *) &link->mac, + sizeof (link->mac), ARPHRD_ETHER); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set MAC address: %m"); + + r = sd_dhcp_client_set_ifindex(link->dhcp_client, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set ifindex: %m"); + + r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set callback: %m"); + + r = sd_dhcp_client_set_request_broadcast(link->dhcp_client, + link->network->dhcp_broadcast); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for broadcast: %m"); + + if (link->mtu) { + r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set MTU: %m"); + } + + if (link->network->dhcp_use_mtu) { + r = sd_dhcp_client_set_request_option(link->dhcp_client, + SD_DHCP_OPTION_INTERFACE_MTU); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for MTU: %m"); + } + + /* NOTE: even if this variable is called "use", it also "sends" PRL + * options, maybe there should be a different configuration variable + * to send or not route options?. */ + /* NOTE: when using Anonymize=yes, routes PRL options are sent + * by default, so they don't need to be added here. */ + if (link->network->dhcp_use_routes && !link->network->dhcp_anonymize) { + r = sd_dhcp_client_set_request_option(link->dhcp_client, + SD_DHCP_OPTION_STATIC_ROUTE); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for static route: %m"); + + r = sd_dhcp_client_set_request_option(link->dhcp_client, + SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for classless static route: %m"); + } + + if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO && !link->network->dhcp_anonymize) { + r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_DOMAIN_SEARCH_LIST); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for domain search list: %m"); + } + + if (link->network->dhcp_use_ntp) { + r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for NTP server: %m"); + } + + if (link->network->dhcp_use_sip) { + r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_SIP_SERVER); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for SIP server: %m"); + } + + if (link->network->dhcp_use_timezone) { + r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for timezone: %m"); + } + + SET_FOREACH(request_options, link->network->dhcp_request_options, i) { + uint32_t option = PTR_TO_UINT32(request_options); + + r = sd_dhcp_client_set_request_option(link->dhcp_client, option); + if (r == -EEXIST) { + log_link_debug(link, "DHCP4 CLIENT: Failed to set request flag for '%u' already exists, ignoring.", option); + continue; + } + + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for '%u': %m", option); + } + + ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_options, i) { + r = sd_dhcp_client_set_dhcp_option(link->dhcp_client, send_option); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set send option: %m"); + } + + r = dhcp4_set_hostname(link); + if (r < 0) + return r; + + if (link->network->dhcp_vendor_class_identifier) { + r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client, + link->network->dhcp_vendor_class_identifier); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set vendor class identifier: %m"); + } + + if (link->network->dhcp_user_class) { + r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set user class: %m"); + } + + if (link->network->dhcp_client_port) { + r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set listen port: %m"); + } + + if (link->network->dhcp_max_attempts > 0) { + r = sd_dhcp_client_set_max_attempts(link->dhcp_client, link->network->dhcp_max_attempts); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set max attempts: %m"); + } + + if (link->network->ip_service_type > 0) { + r = sd_dhcp_client_set_service_type(link->dhcp_client, link->network->ip_service_type); + if (r < 0) + return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set ip service type: %m"); + } + return dhcp4_set_client_identifier(link); +} + +int config_parse_dhcp_max_attempts( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + uint64_t a; + int r; + + assert(network); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + network->dhcp_max_attempts = 0; + return 0; + } + + if (streq(rvalue, "infinity")) { + network->dhcp_max_attempts = (uint64_t) -1; + return 0; + } + + r = safe_atou64(rvalue, &a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue); + return 0; + } + + if (a == 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue); + return 0; + } + + network->dhcp_max_attempts = a; + + return 0; +} + +int config_parse_dhcp_black_listed_ip_address( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip); + return 0; + } + + for (p = rvalue;;) { + _cleanup_free_ char *n = NULL; + union in_addr_union ip; + + r = extract_first_word(&p, &n, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DHCP black listed ip address, ignoring assignment: %s", + rvalue); + return 0; + } + if (r == 0) + return 0; + + r = in_addr_from_string(AF_INET, n, &ip); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "DHCP black listed ip address is invalid, ignoring assignment: %s", n); + continue; + } + + r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL); + if (r < 0) + return log_oom(); + + r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr)); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n); + } + + return 0; +} + +int config_parse_dhcp_user_class( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char ***l = data; + int r; + + assert(l); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + *l = strv_free(*l); + return 0; + } + + for (;;) { + _cleanup_free_ char *w = NULL; + + r = extract_first_word(&rvalue, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to split user classes option, ignoring: %s", rvalue); + break; + } + if (r == 0) + break; + + if (strlen(w) > 255) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "%s length is not in the range 1-255, ignoring.", w); + continue; + } + + r = strv_push(l, w); + if (r < 0) + return log_oom(); + + w = NULL; + } + + return 0; +} + +int config_parse_dhcp_request_options( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + network->dhcp_request_options = set_free(network->dhcp_request_options); + return 0; + } + + for (p = rvalue;;) { + _cleanup_free_ char *n = NULL; + uint32_t i; + + r = extract_first_word(&p, &n, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse DHCP request option, ignoring assignment: %s", + rvalue); + return 0; + } + if (r == 0) + return 0; + + r = safe_atou32(n, &i); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "DHCP request option is invalid, ignoring assignment: %s", n); + continue; + } + + if (i < 1 || i >= 255) { + log_syntax(unit, LOG_ERR, filename, line, r, + "DHCP request option is invalid, valid range is 1-254, ignoring assignment: %s", n); + continue; + } + + r = set_ensure_allocated(&network->dhcp_request_options, NULL); + if (r < 0) + return log_oom(); + + r = set_put(network->dhcp_request_options, UINT32_TO_PTR(i)); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to store DHCP request option '%s', ignoring assignment: %m", n); + } + + return 0; +} + +static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = { + [DHCP_CLIENT_ID_MAC] = "mac", + [DHCP_CLIENT_ID_DUID] = "duid", + [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier); +DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier, + "Failed to parse client identifier type"); diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h new file mode 100644 index 00000000..fce11ef6 --- /dev/null +++ b/src/network/networkd-dhcp4.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" + +typedef struct Link Link; + +typedef enum DHCPClientIdentifier { + DHCP_CLIENT_ID_MAC, + DHCP_CLIENT_ID_DUID, + /* The following option may not be good for RFC regarding DHCP (3315 and 4361). + * But some setups require this. E.g., Sky Broadband, the second largest provider in the UK + * requires the client id to be set to a custom string, reported at + * https://github.com/systemd/systemd/issues/7828 */ + DHCP_CLIENT_ID_DUID_ONLY, + _DHCP_CLIENT_ID_MAX, + _DHCP_CLIENT_ID_INVALID = -1, +} DHCPClientIdentifier; + +void dhcp4_release_old_lease(Link *link); +int dhcp4_configure(Link *link); +int dhcp4_set_client_identifier(Link *link); +int dhcp4_set_promote_secondaries(Link *link); + +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options); diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c new file mode 100644 index 00000000..647623ac --- /dev/null +++ b/src/network/networkd-dhcp6.c @@ -0,0 +1,838 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include +#include +#include +#include "sd-radv.h" + +#include "sd-dhcp6-client.h" + +#include "hashmap.h" +#include "hostname-util.h" +#include "missing_network.h" +#include "network-internal.h" +#include "networkd-dhcp6.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "siphash24.h" +#include "string-util.h" +#include "radv-internal.h" + +static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link); +static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr); +static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link); +static int dhcp6_prefix_remove_all(Manager *m, Link *link); + +static bool dhcp6_get_prefix_delegation(Link *link) { + if (!link->network) + return false; + + return IN_SET(link->network->router_prefix_delegation, + RADV_PREFIX_DELEGATION_DHCP6, + RADV_PREFIX_DELEGATION_BOTH); +} + +static bool dhcp6_enable_prefix_delegation(Link *dhcp6_link) { + Manager *manager; + Link *l; + Iterator i; + + assert(dhcp6_link); + + manager = dhcp6_link->manager; + assert(manager); + + HASHMAP_FOREACH(l, manager->links, i) { + if (l == dhcp6_link) + continue; + + if (!dhcp6_get_prefix_delegation(l)) + continue; + + return true; + } + + return false; +} + +static int dhcp6_lease_information_acquired(sd_dhcp6_client *client, + Link *link) { + return 0; +} + +static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix, + uint8_t prefix_len, + uint32_t lifetime_preferred, + uint32_t lifetime_valid) { + sd_radv *radv = link->radv; + int r; + _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL; + + r = sd_radv_prefix_new(&p); + if (r < 0) + return r; + + r = sd_radv_prefix_set_prefix(p, prefix, prefix_len); + if (r < 0) + return r; + + r = sd_radv_prefix_set_preferred_lifetime(p, lifetime_preferred); + if (r < 0) + return r; + + r = sd_radv_prefix_set_valid_lifetime(p, lifetime_valid); + if (r < 0) + return r; + + r = sd_radv_stop(radv); + if (r < 0) + return r; + + r = sd_radv_add_prefix(radv, p, true); + if (r < 0 && r != -EEXIST) + return r; + + r = dhcp6_prefix_add(link->manager, prefix, link); + if (r < 0) + return r; + + return sd_radv_start(radv); +} + +static int dhcp6_route_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_debug_errno(link, r, "Received error on unreachable route removal for DHCPv6 delegated subnet: %m"); + + return 1; +} + +int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link) { + int r; + sd_dhcp6_lease *lease; + union in_addr_union pd_prefix; + uint8_t pd_prefix_len; + uint32_t lifetime_preferred, lifetime_valid; + + r = sd_dhcp6_client_get_lease(client, &lease); + if (r < 0) + return r; + + sd_dhcp6_lease_reset_pd_prefix_iter(lease); + + while (sd_dhcp6_lease_get_pd(lease, &pd_prefix.in6, &pd_prefix_len, + &lifetime_preferred, + &lifetime_valid) >= 0) { + _cleanup_free_ char *buf = NULL; + _cleanup_(route_freep) Route *route = NULL; + + if (pd_prefix_len >= 64) + continue; + + (void) in_addr_to_string(AF_INET6, &pd_prefix, &buf); + + r = route_new(&route); + if (r < 0) + return r; + + route->family = AF_INET6; + route->dst = pd_prefix; + route->dst_prefixlen = pd_prefix_len; + route->type = RTN_UNREACHABLE; + + r = route_remove(route, link, dhcp6_route_remove_handler); + if (r < 0) { + log_link_warning_errno(link, r, "Cannot delete unreachable route for DHCPv6 delegated subnet %s/%u: %m", + strnull(buf), + pd_prefix_len); + continue; + } + + log_link_debug(link, "Removing unreachable route %s/%u", + strnull(buf), pd_prefix_len); + } + + return 0; +} + +static int dhcp6_pd_prefix_distribute(Link *dhcp6_link, Iterator *i, + struct in6_addr *pd_prefix, + uint8_t pd_prefix_len, + uint32_t lifetime_preferred, + uint32_t lifetime_valid) { + Link *link; + Manager *manager = dhcp6_link->manager; + union in_addr_union prefix; + uint64_t n_prefixes, n_used = 0; + _cleanup_free_ char *buf = NULL; + _cleanup_free_ char *assigned_buf = NULL; + int r; + + assert(manager); + assert(pd_prefix_len <= 64); + + prefix.in6 = *pd_prefix; + + r = in_addr_mask(AF_INET6, &prefix, pd_prefix_len); + if (r < 0) + return r; + + n_prefixes = UINT64_C(1) << (64 - pd_prefix_len); + + (void) in_addr_to_string(AF_INET6, &prefix, &buf); + log_link_debug(dhcp6_link, "Assigning up to %" PRIu64 " prefixes from %s/%u", + n_prefixes, strnull(buf), pd_prefix_len); + + while (hashmap_iterate(manager->links, i, (void **)&link, NULL)) { + Link *assigned_link; + + if (n_used == n_prefixes) { + log_link_debug(dhcp6_link, "Assigned %" PRIu64 "/%" PRIu64 " prefixes from %s/%u", + n_used, n_prefixes, strnull(buf), pd_prefix_len); + + return -EAGAIN; + } + + if (link == dhcp6_link) + continue; + + if (!dhcp6_get_prefix_delegation(link)) + continue; + + assigned_link = dhcp6_prefix_get(manager, &prefix.in6); + if (assigned_link && assigned_link != link) + continue; + + (void) in_addr_to_string(AF_INET6, &prefix, &assigned_buf); + r = dhcp6_pd_prefix_assign(link, &prefix.in6, 64, + lifetime_preferred, lifetime_valid); + if (r < 0) { + log_link_error_errno(link, r, "Unable to %s prefix %s/64 from %s/%u for link: %m", + assigned_link ? "update": "assign", + strnull(assigned_buf), + strnull(buf), pd_prefix_len); + + if (!assigned_link) + continue; + + } else + log_link_debug(link, "Assigned prefix %" PRIu64 "/%" PRIu64 " %s/64 from %s/%u to link", + n_used + 1, n_prefixes, + strnull(assigned_buf), + strnull(buf), pd_prefix_len); + + n_used++; + + r = in_addr_prefix_next(AF_INET6, &prefix, 64); + if (r < 0 && n_used < n_prefixes) + return r; + } + + return 0; +} + +static int dhcp6_route_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) + log_link_debug_errno(link, r, "Received error when adding unreachable route for DHCPv6 delegated subnet: %m"); + + return 1; +} + +static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) { + int r; + sd_dhcp6_lease *lease; + union in_addr_union pd_prefix; + uint8_t pd_prefix_len; + uint32_t lifetime_preferred, lifetime_valid; + Iterator i = ITERATOR_FIRST; + + r = sd_dhcp6_client_get_lease(client, &lease); + if (r < 0) + return r; + + sd_dhcp6_lease_reset_pd_prefix_iter(lease); + + while (sd_dhcp6_lease_get_pd(lease, &pd_prefix.in6, &pd_prefix_len, + &lifetime_preferred, + &lifetime_valid) >= 0) { + + _cleanup_free_ char *buf = NULL; + + (void) in_addr_to_string(AF_INET6, &pd_prefix, &buf); + + if (pd_prefix_len > 64) { + log_link_debug(link, "PD Prefix length > 64, ignoring prefix %s/%u", + strnull(buf), pd_prefix_len); + continue; + } + + if (pd_prefix_len < 48) + log_link_warning(link, "PD Prefix length < 48, looks unusual %s/%u", + strnull(buf), pd_prefix_len); + + if (pd_prefix_len < 64) { + _cleanup_(route_freep) Route *route = NULL; + + r = route_new(&route); + if (r < 0) + return r; + + route->family = AF_INET6; + route->dst = pd_prefix; + route->dst_prefixlen = pd_prefix_len; + route->table = link_get_dhcp_route_table(link); + route->type = RTN_UNREACHABLE; + + r = route_configure(route, link, dhcp6_route_handler); + if (r < 0) { + log_link_warning_errno(link, r, "Cannot configure unreachable route for delegated subnet %s/%u: %m", + strnull(buf), + pd_prefix_len); + continue; + } + + log_link_debug(link, "Configuring unreachable route for %s/%u", + strnull(buf), pd_prefix_len); + } else + log_link_debug(link, "Not adding a blocking route since distributed prefix is /64"); + + r = dhcp6_pd_prefix_distribute(link, &i, &pd_prefix.in6, + pd_prefix_len, + lifetime_preferred, + lifetime_valid); + if (r < 0 && r != -EAGAIN) + return r; + + if (r >= 0) + i = ITERATOR_FIRST; + } + + return 0; +} + +int dhcp6_request_prefix_delegation(Link *link) { + Link *l; + Iterator i; + + assert_return(link, -EINVAL); + assert_return(link->manager, -EOPNOTSUPP); + + if (dhcp6_get_prefix_delegation(link) <= 0) + return 0; + + log_link_debug(link, "Requesting DHCPv6 prefixes to be delegated for new link"); + + HASHMAP_FOREACH(l, link->manager->links, i) { + int r, enabled; + + if (l == link) + continue; + + if (!l->dhcp6_client) + continue; + + r = sd_dhcp6_client_get_prefix_delegation(l->dhcp6_client, &enabled); + if (r < 0) { + log_link_warning_errno(l, r, "Cannot get prefix delegation when adding new link"); + continue; + } + + if (enabled == 0) { + r = sd_dhcp6_client_set_prefix_delegation(l->dhcp6_client, 1); + if (r < 0) { + log_link_warning_errno(l, r, "Cannot enable prefix delegation when adding new link"); + continue; + } + } + + r = sd_dhcp6_client_is_running(l->dhcp6_client); + if (r <= 0) + continue; + + if (enabled != 0) { + log_link_debug(l, "Requesting re-assignment of delegated prefixes after adding new link"); + (void) dhcp6_lease_pd_prefix_acquired(l->dhcp6_client, l); + + continue; + } + + r = sd_dhcp6_client_stop(l->dhcp6_client); + if (r < 0) { + log_link_warning_errno(l, r, "Cannot stop DHCPv6 prefix delegation client after adding new link"); + continue; + } + + r = sd_dhcp6_client_start(l->dhcp6_client); + if (r < 0) { + log_link_warning_errno(l, r, "Cannot restart DHCPv6 prefix delegation client after adding new link"); + continue; + } + + log_link_debug(l, "Restarted DHCPv6 client to acquire prefix delegations after adding new link"); + } + + return 0; +} + +static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_error_errno(link, r, "Could not set DHCPv6 address: %m"); + link_enter_failed(link); + return 1; + } else if (r >= 0) + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + r = link_request_set_routes(link); + if (r < 0) { + link_enter_failed(link); + return 1; + } + + return 1; +} + +static int dhcp6_address_change( + Link *link, + struct in6_addr *ip6_addr, + uint32_t lifetime_preferred, + uint32_t lifetime_valid) { + + _cleanup_(address_freep) Address *addr = NULL; + _cleanup_free_ char *buffer = NULL; + int r; + + r = address_new(&addr); + if (r < 0) + return r; + + addr->family = AF_INET6; + addr->in_addr.in6 = *ip6_addr; + addr->flags = IFA_F_NOPREFIXROUTE; + addr->prefixlen = 128; + addr->cinfo.ifa_prefered = lifetime_preferred; + addr->cinfo.ifa_valid = lifetime_valid; + + (void) in_addr_to_string(addr->family, &addr->in_addr, &buffer); + log_link_info(link, + "DHCPv6 address %s/%d timeout preferred %d valid %d", + strnull(buffer), addr->prefixlen, lifetime_preferred, lifetime_valid); + + r = address_configure(addr, link, dhcp6_address_handler, true); + if (r < 0) + return log_link_warning_errno(link, r, "Could not assign DHCPv6 address: %m"); + + return 0; +} + +static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) { + int r; + sd_dhcp6_lease *lease; + struct in6_addr ip6_addr; + uint32_t lifetime_preferred, lifetime_valid; + + r = sd_dhcp6_client_get_lease(client, &lease); + if (r < 0) + return r; + + sd_dhcp6_lease_reset_address_iter(lease); + + while (sd_dhcp6_lease_get_address(lease, &ip6_addr, + &lifetime_preferred, + &lifetime_valid) >= 0) { + + r = dhcp6_address_change(link, &ip6_addr, lifetime_preferred, lifetime_valid); + if (r < 0) + return r; + } + + return 0; +} + +static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) { + int r; + Link *link = userdata; + + assert(link); + assert(link->network); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return; + + switch(event) { + case SD_DHCP6_CLIENT_EVENT_STOP: + case SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE: + case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX: + if (sd_dhcp6_client_get_lease(client, NULL) >= 0) + log_link_warning(link, "DHCPv6 lease lost"); + + (void) dhcp6_lease_pd_prefix_lost(client, link); + (void) dhcp6_prefix_remove_all(link->manager, link); + + link_dirty(link); + link->dhcp6_configured = false; + break; + + case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE: + r = dhcp6_lease_address_acquired(client, link); + if (r < 0) { + link_enter_failed(link); + return; + } + + r = dhcp6_lease_pd_prefix_acquired(client, link); + if (r < 0) + log_link_debug(link, "DHCPv6 did not receive prefixes to delegate"); + + _fallthrough_; + case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST: + r = dhcp6_lease_information_acquired(client, link); + if (r < 0) { + link_enter_failed(link); + return; + } + + link_dirty(link); + link->dhcp6_configured = true; + break; + + default: + if (event < 0) + log_link_warning_errno(link, event, "DHCPv6 error: %m"); + else + log_link_warning(link, "DHCPv6 unknown event: %d", event); + return; + } + + link_check_ready(link); +} + +int dhcp6_request_address(Link *link, int ir) { + int r, inf_req, pd; + bool running; + + assert(link); + assert(link->dhcp6_client); + assert(link->network); + assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0); + + r = sd_dhcp6_client_is_running(link->dhcp6_client); + if (r < 0) + return r; + running = r; + + r = sd_dhcp6_client_get_prefix_delegation(link->dhcp6_client, &pd); + if (r < 0) + return r; + + if (pd && ir && link->network->dhcp6_force_pd_other_information) { + log_link_debug(link, "Enabling managed mode to request DHCPv6 PD with 'Other Information' set"); + + r = sd_dhcp6_client_set_address_request(link->dhcp6_client, + false); + if (r < 0 ) + return r; + + ir = false; + } + + if (running) { + r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req); + if (r < 0) + return r; + + if (inf_req == ir) + return 0; + + r = sd_dhcp6_client_stop(link->dhcp6_client); + if (r < 0) + return r; + } else { + r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address); + if (r < 0) + return r; + } + + r = sd_dhcp6_client_set_information_request(link->dhcp6_client, ir); + if (r < 0) + return r; + + r = sd_dhcp6_client_start(link->dhcp6_client); + if (r < 0) + return r; + + return 0; +} + +static int dhcp6_set_hostname(sd_dhcp6_client *client, Link *link) { + _cleanup_free_ char *hostname = NULL; + const char *hn; + int r; + + assert(link); + + if (!link->network->dhcp_send_hostname) + hn = NULL; + else if (link->network->dhcp_hostname) + hn = link->network->dhcp_hostname; + else { + r = gethostname_strict(&hostname); + if (r < 0 && r != -ENXIO) /* ENXIO: no hostname set or hostname is "localhost" */ + return r; + + hn = hostname; + } + + r = sd_dhcp6_client_set_fqdn(client, hn); + if (r == -EINVAL && hostname) + /* Ignore error when the machine's hostname is not suitable to send in DHCP packet. */ + log_link_warning_errno(link, r, "DHCP6 CLIENT: Failed to set hostname from kernel hostname, ignoring: %m"); + else if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set hostname: %m"); + + return 0; +} + +int dhcp6_configure(Link *link) { + _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; + const DUID *duid; + int r; + + assert(link); + assert(link->network); + + if (link->dhcp6_client) + return 0; + + r = sd_dhcp6_client_new(&client); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to create DHCP6 client: %m"); + + r = sd_dhcp6_client_attach_event(client, NULL, 0); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to attach event: %m"); + + r = sd_dhcp6_client_set_mac(client, + (const uint8_t *) &link->mac, + sizeof (link->mac), ARPHRD_ETHER); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set MAC address: %m"); + + if (link->network->iaid_set) { + r = sd_dhcp6_client_set_iaid(client, link->network->iaid); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set IAID: %m"); + } + + duid = link_get_duid(link); + if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0) + r = sd_dhcp6_client_set_duid_llt(client, duid->llt_time); + else + r = sd_dhcp6_client_set_duid(client, + duid->type, + duid->raw_data_len > 0 ? duid->raw_data : NULL, + duid->raw_data_len); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set DUID: %m"); + + r = dhcp6_set_hostname(client, link); + if (r < 0) + return r; + + r = sd_dhcp6_client_set_ifindex(client, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set ifindex: %m"); + + if (link->network->rapid_commit) { + r = sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_RAPID_COMMIT); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set request flag for rapid commit: %m"); + } + + r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set callback: %m"); + + if (dhcp6_enable_prefix_delegation(link)) { + r = sd_dhcp6_client_set_prefix_delegation(client, true); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set prefix delegation: %m"); + } + + if (link->network->dhcp6_pd_length > 0) { + r = sd_dhcp6_client_set_prefix_delegation_hint(client, link->network->dhcp6_pd_length, &link->network->dhcp6_pd_address); + if (r < 0) + return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set prefix hint: %m"); + } + + link->dhcp6_client = TAKE_PTR(client); + + return 0; +} + +static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr) { + assert_return(m, NULL); + assert_return(addr, NULL); + + return hashmap_get(m->dhcp6_prefixes, addr); +} + +static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_debug_errno(link, r, "Received error adding DHCPv6 Prefix Delegation route: %m"); + link_enter_failed(link); + return 1; + } + + return 1; +} + +static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) { + _cleanup_(route_freep) Route *route = NULL; + _cleanup_free_ struct in6_addr *a = NULL; + _cleanup_free_ char *buf = NULL; + Link *assigned_link; + int r; + + assert_return(m, -EINVAL); + assert_return(addr, -EINVAL); + + r = route_new(&route); + if (r < 0) + return r; + + route->family = AF_INET6; + route->dst.in6 = *addr; + route->dst_prefixlen = 64; + + r = route_configure(route, link, dhcp6_route_add_handler); + if (r < 0) + return r; + + (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf); + log_link_debug(link, "Adding prefix route %s/64", strnull(buf)); + + assigned_link = hashmap_get(m->dhcp6_prefixes, addr); + if (assigned_link) { + assert(assigned_link == link); + return 0; + } + + a = newdup(struct in6_addr, addr, 1); + if (!a) + return -ENOMEM; + + r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &in6_addr_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(m->dhcp6_prefixes, a, link); + if (r < 0) + return r; + + TAKE_PTR(a); + link_ref(link); + return 0; +} + +static int dhcp6_prefix_remove_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) { + log_link_debug_errno(link, r, "Received error on DHCPv6 Prefix Delegation route removal: %m"); + link_enter_failed(link); + return 1; + } + + return 1; +} + +int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr) { + _cleanup_free_ struct in6_addr *a = NULL; + _cleanup_(link_unrefp) Link *l = NULL; + _cleanup_(route_freep) Route *route = NULL; + _cleanup_free_ char *buf = NULL; + int r; + + assert_return(m, -EINVAL); + assert_return(addr, -EINVAL); + + l = hashmap_remove2(m->dhcp6_prefixes, addr, (void **) &a); + if (!l) + return -EINVAL; + + (void) sd_radv_remove_prefix(l->radv, addr, 64); + + r = route_new(&route); + if (r < 0) + return r; + + route->family = AF_INET6; + route->dst.in6 = *addr; + route->dst_prefixlen = 64; + + r = route_remove(route, l, dhcp6_prefix_remove_handler); + if (r < 0) + return r; + + (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf); + log_link_debug(l, "Removing prefix route %s/64", strnull(buf)); + + return 0; +} + +static int dhcp6_prefix_remove_all(Manager *m, Link *link) { + struct in6_addr *addr; + Iterator i; + Link *l; + + assert_return(m, -EINVAL); + assert_return(link, -EINVAL); + + HASHMAP_FOREACH_KEY(l, addr, m->dhcp6_prefixes, i) + if (l == link) + (void) dhcp6_prefix_remove(m, addr); + + return 0; +} diff --git a/src/network/networkd-dhcp6.h b/src/network/networkd-dhcp6.h new file mode 100644 index 00000000..26d810f4 --- /dev/null +++ b/src/network/networkd-dhcp6.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-dhcp6-client.h" + +#include "conf-parser.h" + +typedef struct Link Link; +typedef struct Manager Manager; + +int dhcp6_request_prefix_delegation(Link *link); +int dhcp6_configure(Link *link); +int dhcp6_request_address(Link *link, int ir); +int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link); +int dhcp6_prefix_remove(Manager *m, struct in6_addr *addr); diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c new file mode 100644 index 00000000..07c77a3f --- /dev/null +++ b/src/network/networkd-fdb.c @@ -0,0 +1,392 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include +#include + +#include "alloc-util.h" +#include "bridge.h" +#include "conf-parser.h" +#include "netlink-util.h" +#include "networkd-fdb.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "string-util.h" +#include "string-table.h" +#include "util.h" +#include "vlan-util.h" +#include "vxlan.h" + +#define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U + +static const char* const fdb_ntf_flags_table[_NEIGHBOR_CACHE_ENTRY_FLAGS_MAX] = { + [NEIGHBOR_CACHE_ENTRY_FLAGS_USE] = "use", + [NEIGHBOR_CACHE_ENTRY_FLAGS_SELF] = "self", + [NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER] = "master", + [NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER] = "router", +}; + +DEFINE_STRING_TABLE_LOOKUP(fdb_ntf_flags, NeighborCacheEntryFlags); + +/* create a new FDB entry or get an existing one. */ +static int fdb_entry_new_static( + Network *network, + const char *filename, + unsigned section_line, + FdbEntry **ret) { + + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(fdb_entry_freep) FdbEntry *fdb_entry = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + /* search entry in hashmap first. */ + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + fdb_entry = hashmap_get(network->fdb_entries_by_section, n); + if (fdb_entry) { + *ret = TAKE_PTR(fdb_entry); + + return 0; + } + } + + if (network->n_static_fdb_entries >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX) + return -E2BIG; + + /* allocate space for and FDB entry. */ + fdb_entry = new(FdbEntry, 1); + if (!fdb_entry) + return -ENOMEM; + + /* init FDB structure. */ + *fdb_entry = (FdbEntry) { + .network = network, + .vni = VXLAN_VID_MAX + 1, + .fdb_ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF, + }; + + LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry); + network->n_static_fdb_entries++; + + if (filename) { + fdb_entry->section = TAKE_PTR(n); + + r = hashmap_ensure_allocated(&network->fdb_entries_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(network->fdb_entries_by_section, fdb_entry->section, fdb_entry); + if (r < 0) + return r; + } + + /* return allocated FDB structure. */ + *ret = TAKE_PTR(fdb_entry); + + return 0; +} + +static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_error_errno(link, r, "Could not add FDB entry: %m"); + link_enter_failed(link); + return 1; + } + + return 1; +} + +/* send a request to the kernel to add a FDB entry in its static MAC table. */ +int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->network); + assert(link->manager); + assert(fdb_entry); + + /* create new RTM message */ + r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE); + if (r < 0) + return rtnl_log_create_error(r); + + r = sd_rtnl_message_neigh_set_flags(req, fdb_entry->fdb_ntf_flags); + if (r < 0) + return rtnl_log_create_error(r); + + /* only NUD_PERMANENT state supported. */ + r = sd_rtnl_message_neigh_set_state(req, NUD_NOARP | NUD_PERMANENT); + if (r < 0) + return rtnl_log_create_error(r); + + r = sd_netlink_message_append_data(req, NDA_LLADDR, &fdb_entry->mac_addr, sizeof(fdb_entry->mac_addr)); + if (r < 0) + return rtnl_log_create_error(r); + + /* VLAN Id is optional. We'll add VLAN Id only if it's specified. */ + if (fdb_entry->vlan_id > 0) { + r = sd_netlink_message_append_u16(req, NDA_VLAN, fdb_entry->vlan_id); + if (r < 0) + return rtnl_log_create_error(r); + } + + if (!in_addr_is_null(fdb_entry->family, &fdb_entry->destination_addr)) { + r = netlink_message_append_in_addr_union(req, NDA_DST, fdb_entry->family, &fdb_entry->destination_addr); + if (r < 0) + return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); + } + + if (fdb_entry->vni <= VXLAN_VID_MAX) { + r = sd_netlink_message_append_u32(req, NDA_VNI, fdb_entry->vni); + if (r < 0) + return log_link_error_errno(link, r, "Could not append NDA_VNI attribute: %m"); + } + + /* send message to the kernel to update its internal static MAC table. */ + r = netlink_call_async(link->manager->rtnl, NULL, req, set_fdb_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 1; +} + +/* remove and FDB entry. */ +void fdb_entry_free(FdbEntry *fdb_entry) { + if (!fdb_entry) + return; + + if (fdb_entry->network) { + LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry); + assert(fdb_entry->network->n_static_fdb_entries > 0); + fdb_entry->network->n_static_fdb_entries--; + + if (fdb_entry->section) + hashmap_remove(fdb_entry->network->fdb_entries_by_section, fdb_entry->section); + } + + network_config_section_free(fdb_entry->section); + free(fdb_entry); +} + +/* parse the HW address from config files. */ +int config_parse_fdb_hwaddr( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = fdb_entry_new_static(network, filename, section_line, &fdb_entry); + if (r < 0) + return log_oom(); + + r = ether_addr_from_string(rvalue, &fdb_entry->mac_addr); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue); + return 0; + } + + fdb_entry = NULL; + + return 0; +} + +/* parse the VLAN Id from config files. */ +int config_parse_fdb_vlan_id( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = fdb_entry_new_static(network, filename, section_line, &fdb_entry); + if (r < 0) + return log_oom(); + + r = config_parse_vlanid(unit, filename, line, section, + section_line, lvalue, ltype, + rvalue, &fdb_entry->vlan_id, userdata); + if (r < 0) + return r; + + fdb_entry = NULL; + + return 0; +} + +int config_parse_fdb_destination( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = fdb_entry_new_static(network, filename, section_line, &fdb_entry); + if (r < 0) + return log_oom(); + + r = in_addr_from_string_auto(rvalue, &fdb_entry->family, &fdb_entry->destination_addr); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, + "FDB destination IP address is invalid, ignoring assignment: %s", + rvalue); + + fdb_entry = NULL; + + return 0; +} + +int config_parse_fdb_vxlan_vni( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL; + Network *network = userdata; + uint32_t vni; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = fdb_entry_new_static(network, filename, section_line, &fdb_entry); + if (r < 0) + return log_oom(); + + r = safe_atou32(rvalue, &vni); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse VXLAN Network Identifier (VNI), ignoring assignment: %s", + rvalue); + return 0; + } + + if (vni > VXLAN_VID_MAX) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "FDB invalid VXLAN Network Identifier (VNI), ignoring assignment: %s", + rvalue); + return 0; + } + + fdb_entry->vni = vni; + fdb_entry = NULL; + + return 0; +} + +int config_parse_fdb_ntf_flags( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL; + Network *network = userdata; + NeighborCacheEntryFlags f; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = fdb_entry_new_static(network, filename, section_line, &fdb_entry); + if (r < 0) + return log_oom(); + + f = fdb_ntf_flags_from_string(rvalue); + if (f < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "FDB failed to parse AssociatedWith=, ignoring assignment: %s", + rvalue); + return 0; + } + + fdb_entry->fdb_ntf_flags = f; + fdb_entry = NULL; + + return 0; +} diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h new file mode 100644 index 00000000..5e24ad6a --- /dev/null +++ b/src/network/networkd-fdb.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include + +#include "conf-parser.h" +#include "list.h" +#include "macro.h" +#include "networkd-util.h" + +typedef struct Network Network; +typedef struct FdbEntry FdbEntry; +typedef struct Link Link; +typedef struct NetworkConfigSection NetworkConfigSection; + +typedef enum NeighborCacheEntryFlags { + NEIGHBOR_CACHE_ENTRY_FLAGS_USE = NTF_USE, + NEIGHBOR_CACHE_ENTRY_FLAGS_SELF = NTF_SELF, + NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER = NTF_MASTER, + NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER = NTF_ROUTER, + _NEIGHBOR_CACHE_ENTRY_FLAGS_MAX, + _NEIGHBOR_CACHE_ENTRY_FLAGS_INVALID = -1, +} NeighborCacheEntryFlags; + +struct FdbEntry { + Network *network; + NetworkConfigSection *section; + + uint32_t vni; + + int family; + uint16_t vlan_id; + + struct ether_addr mac_addr; + union in_addr_union destination_addr; + NeighborCacheEntryFlags fdb_ntf_flags; + + LIST_FIELDS(FdbEntry, static_fdb_entries); +}; + +void fdb_entry_free(FdbEntry *fdb_entry); +int fdb_entry_configure(Link *link, FdbEntry *fdb_entry); + +DEFINE_NETWORK_SECTION_FUNCTIONS(FdbEntry, fdb_entry_free); + +const char* fdb_ntf_flags_to_string(NeighborCacheEntryFlags i) _const_; +NeighborCacheEntryFlags fdb_ntf_flags_from_string(const char *s) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr); +CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id); +CONFIG_PARSER_PROTOTYPE(config_parse_fdb_destination); +CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vxlan_vni); +CONFIG_PARSER_PROTOTYPE(config_parse_fdb_ntf_flags); diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf new file mode 100644 index 00000000..d74d3755 --- /dev/null +++ b/src/network/networkd-gperf.gperf @@ -0,0 +1,24 @@ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif +#include +#include "conf-parser.h" +#include "networkd-conf.h" +#include "networkd-manager.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name networkd_gperf_hash +%define lookup-function-name networkd_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +Network.SpeedMeter, config_parse_bool, 0, offsetof(Manager, use_speed_meter) +Network.SpeedMeterIntervalSec, config_parse_sec, 0, offsetof(Manager, speed_meter_interval_usec) +DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Manager, duid) +DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, duid) diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c new file mode 100644 index 00000000..6216a06d --- /dev/null +++ b/src/network/networkd-ipv4ll.c @@ -0,0 +1,225 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "network-internal.h" +#include "networkd-address.h" +#include "networkd-ipv4ll.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "parse-util.h" + +static int ipv4ll_address_lost(Link *link) { + _cleanup_(address_freep) Address *address = NULL; + struct in_addr addr; + int r; + + assert(link); + + link->ipv4ll_address = false; + + r = sd_ipv4ll_get_address(link->ipv4ll, &addr); + if (r < 0) + return 0; + + log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr)); + + r = address_new(&address); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate address: %m"); + + address->family = AF_INET; + address->in_addr.in = addr; + address->prefixlen = 16; + address->scope = RT_SCOPE_LINK; + + r = address_remove(address, link, NULL); + if (r < 0) + return r; + + link_check_ready(link); + + return 0; +} + +static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(!link->ipv4ll_address); + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_error_errno(link, r, "could not set ipv4ll address: %m"); + link_enter_failed(link); + return 1; + } else if (r >= 0) + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + link->ipv4ll_address = true; + link_check_ready(link); + + return 1; +} + +static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { + _cleanup_(address_freep) Address *ll_addr = NULL; + struct in_addr address; + int r; + + assert(ll); + assert(link); + + link->ipv4ll_address = false; + + r = sd_ipv4ll_get_address(ll, &address); + if (r == -ENOENT) + return 0; + else if (r < 0) + return r; + + log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u", + ADDRESS_FMT_VAL(address)); + + r = address_new(&ll_addr); + if (r < 0) + return r; + + ll_addr->family = AF_INET; + ll_addr->in_addr.in = address; + ll_addr->prefixlen = 16; + ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htobe32(0xfffffffflu >> ll_addr->prefixlen); + ll_addr->scope = RT_SCOPE_LINK; + + r = address_configure(ll_addr, link, ipv4ll_address_handler, false); + if (r < 0) + return r; + + return 0; +} + +static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata) { + Link *link = userdata; + int r; + + assert(link); + assert(link->network); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return; + + switch(event) { + case SD_IPV4LL_EVENT_STOP: + r = ipv4ll_address_lost(link); + if (r < 0) { + link_enter_failed(link); + return; + } + break; + case SD_IPV4LL_EVENT_CONFLICT: + r = ipv4ll_address_lost(link); + if (r < 0) { + link_enter_failed(link); + return; + } + + r = sd_ipv4ll_restart(ll); + if (r < 0) + log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m"); + break; + case SD_IPV4LL_EVENT_BIND: + r = ipv4ll_address_claimed(ll, link); + if (r < 0) { + log_link_error(link, "Failed to configure ipv4ll address: %m"); + link_enter_failed(link); + return; + } + break; + default: + log_link_warning(link, "IPv4 link-local unknown event: %d", event); + break; + } +} + +int ipv4ll_configure(Link *link) { + uint64_t seed; + int r; + + assert(link); + assert(link->network); + assert(link->network->link_local & (ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)); + + if (!link->ipv4ll) { + r = sd_ipv4ll_new(&link->ipv4ll); + if (r < 0) + return r; + } + + if (link->sd_device && + net_get_unique_predictable_data(link->sd_device, true, &seed) >= 0) { + r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed); + if (r < 0) + return r; + } + + r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0); + if (r < 0) + return r; + + r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); + if (r < 0) + return r; + + r = sd_ipv4ll_set_ifindex(link->ipv4ll, link->ifindex); + if (r < 0) + return r; + + r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link); + if (r < 0) + return r; + + return 0; +} + +int config_parse_ipv4ll( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + AddressFamily *link_local = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* Note that this is mostly like + * config_parse_address_family(), except that it + * applies only to IPv4 */ + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse %s=%s, ignoring assignment. " + "Note that the setting %s= is deprecated, please use LinkLocalAddressing= instead.", + lvalue, rvalue, lvalue); + return 0; + } + + SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, r); + + log_syntax(unit, LOG_WARNING, filename, line, 0, + "%s=%s is deprecated, please use LinkLocalAddressing=%s instead.", + lvalue, rvalue, address_family_to_string(*link_local)); + + return 0; +} diff --git a/src/network/networkd-ipv4ll.h b/src/network/networkd-ipv4ll.h new file mode 100644 index 00000000..49b6fb56 --- /dev/null +++ b/src/network/networkd-ipv4ll.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" + +#define IPV4LL_ROUTE_METRIC 2048 + +typedef struct Link Link; + +int ipv4ll_configure(Link *link); + +CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll); diff --git a/src/network/networkd-ipv6-proxy-ndp.c b/src/network/networkd-ipv6-proxy-ndp.c new file mode 100644 index 00000000..863171b0 --- /dev/null +++ b/src/network/networkd-ipv6-proxy-ndp.c @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "fileio.h" +#include "netlink-util.h" +#include "networkd-ipv6-proxy-ndp.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "networkd-network.h" +#include "socket-util.h" +#include "string-util.h" +#include "sysctl-util.h" + +static bool ipv6_proxy_ndp_is_needed(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->ipv6_proxy_ndp >= 0) + return link->network->ipv6_proxy_ndp; + + if (link->network->n_ipv6_proxy_ndp_addresses == 0) + return false; + + return true; +} + +static int ipv6_proxy_ndp_set(Link *link) { + bool v; + int r; + + assert(link); + + if (!socket_ipv6_is_supported()) + return 0; + + v = ipv6_proxy_ndp_is_needed(link); + + r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure proxy NDP for interface: %m"); + + return 0; +} + +static int ipv6_proxy_ndp_address_new_static(Network *network, IPv6ProxyNDPAddress **ret) { + _cleanup_(ipv6_proxy_ndp_address_freep) IPv6ProxyNDPAddress *ipv6_proxy_ndp_address = NULL; + + assert(network); + assert(ret); + + /* allocate space for IPv6ProxyNDPAddress entry */ + ipv6_proxy_ndp_address = new(IPv6ProxyNDPAddress, 1); + if (!ipv6_proxy_ndp_address) + return -ENOMEM; + + *ipv6_proxy_ndp_address = (IPv6ProxyNDPAddress) { + .network = network, + }; + + LIST_PREPEND(ipv6_proxy_ndp_addresses, network->ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address); + network->n_ipv6_proxy_ndp_addresses++; + + *ret = TAKE_PTR(ipv6_proxy_ndp_address); + + return 0; +} + +void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address) { + if (!ipv6_proxy_ndp_address) + return; + + if (ipv6_proxy_ndp_address->network) { + LIST_REMOVE(ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address->network->ipv6_proxy_ndp_addresses, + ipv6_proxy_ndp_address); + + assert(ipv6_proxy_ndp_address->network->n_ipv6_proxy_ndp_addresses > 0); + ipv6_proxy_ndp_address->network->n_ipv6_proxy_ndp_addresses--; + } + + free(ipv6_proxy_ndp_address); +} + +int config_parse_ipv6_proxy_ndp_address( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(ipv6_proxy_ndp_address_freep) IPv6ProxyNDPAddress *ipv6_proxy_ndp_address = NULL; + int r; + union in_addr_union buffer; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = ipv6_proxy_ndp_address_new_static(network, &ipv6_proxy_ndp_address); + if (r < 0) + return r; + + r = in_addr_from_string(AF_INET6, rvalue, &buffer); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 proxy NDP address, ignoring: %s", + rvalue); + return 0; + } + + if (in_addr_is_null(AF_INET6, &buffer)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "IPv6 proxy NDP address cannot be the ANY address, ignoring: %s", rvalue); + return 0; + } + + ipv6_proxy_ndp_address->in_addr = buffer.in6; + ipv6_proxy_ndp_address = NULL; + + return 0; +} + +static int set_ipv6_proxy_ndp_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) + log_link_error_errno(link, r, "Could not add IPv6 proxy ndp address entry: %m"); + + return 1; +} + +/* send a request to the kernel to add a IPv6 Proxy entry to the neighbour table */ +int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy_ndp_address) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + sd_netlink *rtnl; + int r; + + assert(link); + assert(link->network); + assert(link->manager); + assert(ipv6_proxy_ndp_address); + + rtnl = link->manager->rtnl; + + /* create new netlink message */ + r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, AF_INET6); + if (r < 0) + return rtnl_log_create_error(r); + + r = sd_rtnl_message_neigh_set_flags(req, NLM_F_REQUEST | NTF_PROXY); + if (r < 0) + return rtnl_log_create_error(r); + + r = sd_netlink_message_append_in6_addr(req, NDA_DST, &ipv6_proxy_ndp_address->in_addr); + if (r < 0) + return rtnl_log_create_error(r); + + r = netlink_call_async(rtnl, NULL, req, set_ipv6_proxy_ndp_address_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +/* configure all ipv6 proxy ndp addresses */ +int ipv6_proxy_ndp_addresses_configure(Link *link) { + IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; + int r; + + assert(link); + + /* enable or disable proxy_ndp itself depending on whether ipv6_proxy_ndp_addresses are set or not */ + r = ipv6_proxy_ndp_set(link); + if (r != 0) + return r; + + LIST_FOREACH(ipv6_proxy_ndp_addresses, ipv6_proxy_ndp_address, link->network->ipv6_proxy_ndp_addresses) { + r = ipv6_proxy_ndp_address_configure(link, ipv6_proxy_ndp_address); + if (r != 0) + return r; + } + return 0; +} diff --git a/src/network/networkd-ipv6-proxy-ndp.h b/src/network/networkd-ipv6-proxy-ndp.h new file mode 100644 index 00000000..d6666bea --- /dev/null +++ b/src/network/networkd-ipv6-proxy-ndp.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "list.h" +#include "macro.h" + +typedef struct Network Network; +typedef struct IPv6ProxyNDPAddress IPv6ProxyNDPAddress; +typedef struct Link Link; + +struct IPv6ProxyNDPAddress { + Network *network; + struct in6_addr in_addr; + + LIST_FIELDS(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); +}; + +void ipv6_proxy_ndp_address_free(IPv6ProxyNDPAddress *ipv6_proxy_ndp_address); +int ipv6_proxy_ndp_address_configure(Link *link, IPv6ProxyNDPAddress *ipv6_proxy_ndp_address); +int ipv6_proxy_ndp_addresses_configure(Link *link); + +DEFINE_TRIVIAL_CLEANUP_FUNC(IPv6ProxyNDPAddress*, ipv6_proxy_ndp_address_free); + +CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_proxy_ndp_address); diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c new file mode 100644 index 00000000..d25ab20a --- /dev/null +++ b/src/network/networkd-link-bus.c @@ -0,0 +1,759 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "dns-domain.h" +#include "networkd-link-bus.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "resolve-util.h" +#include "strv.h" +#include "user-util.h" + +BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); +BUS_DEFINE_PROPERTY_GET_ENUM(property_get_carrier_state, link_carrier_state, LinkCarrierState); +BUS_DEFINE_PROPERTY_GET_ENUM(property_get_address_state, link_address_state, LinkAddressState); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState); + +static int property_get_bit_rates( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Link *link = userdata; + Manager *manager; + double interval_sec; + uint64_t tx, rx; + + assert(bus); + assert(reply); + assert(userdata); + + manager = link->manager; + + if (!manager->use_speed_meter || + manager->speed_meter_usec_old == 0 || + !link->stats_updated) + return sd_bus_message_append(reply, "(tt)", UINT64_MAX, UINT64_MAX); + + assert(manager->speed_meter_usec_new > manager->speed_meter_usec_old); + interval_sec = (manager->speed_meter_usec_new - manager->speed_meter_usec_old) / USEC_PER_SEC; + + if (link->stats_new.tx_bytes > link->stats_old.tx_bytes) + tx = (uint64_t) ((link->stats_new.tx_bytes - link->stats_old.tx_bytes) / interval_sec); + else + tx = (uint64_t) ((UINT64_MAX - (link->stats_old.tx_bytes - link->stats_new.tx_bytes)) / interval_sec); + + if (link->stats_new.rx_bytes > link->stats_old.rx_bytes) + rx = (uint64_t) ((link->stats_new.rx_bytes - link->stats_old.rx_bytes) / interval_sec); + else + rx = (uint64_t) ((UINT64_MAX - (link->stats_old.rx_bytes - link->stats_new.rx_bytes)) / interval_sec); + + return sd_bus_message_append(reply, "(tt)", tx, rx); +} + +static int verify_managed_link(Link *l, sd_bus_error *error) { + assert(l); + + if (l->flags & IFF_LOOPBACK) + return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->ifname); + + return 0; +} + +int bus_link_method_set_ntp_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_strv_free_ char **ntp = NULL; + Link *l = userdata; + int r; + char **i; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(message, &ntp); + if (r < 0) + return r; + + STRV_FOREACH(i, ntp) { + r = dns_name_is_valid_or_address(*i); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NTP server: %s", *i); + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.set-ntp-servers", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + strv_free_and_replace(l->ntp, ntp); + + (void) link_dirty(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ struct in_addr_data *dns = NULL; + size_t allocated = 0, n = 0; + Link *l = userdata; + int r; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(message, 'a', "(iay)"); + if (r < 0) + return r; + + for (;;) { + int family; + size_t sz; + const void *d; + + assert_cc(sizeof(int) == sizeof(int32_t)); + + r = sd_bus_message_enter_container(message, 'r', "iay"); + if (r < 0) + return r; + if (r == 0) + break; + + r = sd_bus_message_read(message, "i", &family); + if (r < 0) + return r; + + if (!IN_SET(family, AF_INET, AF_INET6)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); + + r = sd_bus_message_read_array(message, 'y', &d, &sz); + if (r < 0) + return r; + if (sz != FAMILY_ADDRESS_SIZE(family)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size"); + + if (!dns_server_address_valid(family, d)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address"); + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!GREEDY_REALLOC(dns, allocated, n+1)) + return -ENOMEM; + + dns[n].family = family; + memcpy(&dns[n].address, d, sz); + n++; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.set-dns-servers", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + free_and_replace(l->dns, dns); + l->n_dns = n; + + (void) link_dirty(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(ordered_set_freep) OrderedSet *search_domains = NULL, *route_domains = NULL; + Link *l = userdata; + int r; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(message, 'a', "(sb)"); + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *str = NULL; + OrderedSet **domains; + const char *name; + int route_only; + + r = sd_bus_message_read(message, "(sb)", &name, &route_only); + if (r < 0) + return r; + if (r == 0) + break; + + r = dns_name_is_valid(name); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name); + if (!route_only && dns_name_is_root(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain"); + + r = dns_name_normalize(name, 0, &str); + if (r < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name); + + domains = route_only ? &route_domains : &search_domains; + r = ordered_set_ensure_allocated(domains, &string_hash_ops); + if (r < 0) + return r; + + r = ordered_set_put(*domains, str); + if (r < 0) + return r; + + TAKE_PTR(str); + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.set-domains", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + ordered_set_free_free(l->search_domains); + ordered_set_free_free(l->route_domains); + l->search_domains = TAKE_PTR(search_domains); + l->route_domains = TAKE_PTR(route_domains); + + (void) link_dirty(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + int r, b; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.set-default-route", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + if (l->dns_default_route != b) { + l->dns_default_route = b; + (void) link_dirty(l); + } + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + ResolveSupport mode; + const char *llmnr; + int r; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &llmnr); + if (r < 0) + return r; + + if (isempty(llmnr)) + mode = RESOLVE_SUPPORT_YES; + else { + mode = resolve_support_from_string(llmnr); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr); + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.set-llmnr", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + if (l->llmnr != mode) { + l->llmnr = mode; + (void) link_dirty(l); + } + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + ResolveSupport mode; + const char *mdns; + int r; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &mdns); + if (r < 0) + return r; + + if (isempty(mdns)) + mode = RESOLVE_SUPPORT_NO; + else { + mode = resolve_support_from_string(mdns); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns); + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.set-mdns", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + if (l->mdns != mode) { + l->mdns = mode; + (void) link_dirty(l); + } + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + const char *dns_over_tls; + DnsOverTlsMode mode; + int r; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &dns_over_tls); + if (r < 0) + return r; + + if (isempty(dns_over_tls)) + mode = _DNS_OVER_TLS_MODE_INVALID; + else { + mode = dns_over_tls_mode_from_string(dns_over_tls); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSOverTLS setting: %s", dns_over_tls); + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.set-dns-over-tls", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + if (l->dns_over_tls_mode != mode) { + l->dns_over_tls_mode = mode; + (void) link_dirty(l); + } + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + const char *dnssec; + DnssecMode mode; + int r; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &dnssec); + if (r < 0) + return r; + + if (isempty(dnssec)) + mode = _DNSSEC_MODE_INVALID; + else { + mode = dnssec_mode_from_string(dnssec); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec); + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.set-dnssec", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + if (l->dnssec_mode != mode) { + l->dnssec_mode = mode; + (void) link_dirty(l); + } + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_set_free_free_ Set *ns = NULL; + _cleanup_strv_free_ char **ntas = NULL; + Link *l = userdata; + int r; + char **i; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read_strv(message, &ntas); + if (r < 0) + return r; + + STRV_FOREACH(i, ntas) { + r = dns_name_is_valid(*i); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid negative trust anchor domain: %s", *i); + } + + ns = set_new(&dns_name_hash_ops); + if (!ns) + return -ENOMEM; + + STRV_FOREACH(i, ntas) { + r = set_put_strdup(ns, *i); + if (r < 0) + return r; + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.set-dnssec-negative-trust-anchors", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + set_free_free(l->dnssec_negative_trust_anchors); + l->dnssec_negative_trust_anchors = TAKE_PTR(ns); + + (void) link_dirty(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_revert_ntp(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + int r; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.revert-ntp", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + link_ntp_settings_clear(l); + (void) link_dirty(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_revert_dns(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + int r; + + assert(message); + assert(l); + + r = verify_managed_link(l, error); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.revert-dns", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + link_dns_settings_clear(l); + (void) link_dirty(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_renew(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + int r; + + assert(l); + + if (!l->network) + return sd_bus_error_setf(error, BUS_ERROR_UNMANAGED_INTERFACE, + "Interface %s is not managed by systemd-networkd", + l->ifname); + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.renew", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + if (l->dhcp_client) { + r = sd_dhcp_client_send_renew(l->dhcp_client); + if (r < 0) + return r; + } + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + int r; + + assert(message); + assert(l); + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.reconfigure", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + r = link_reconfigure(l, true); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +const sd_bus_vtable link_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Link, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Link, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("BitRates", "(tt)", property_get_bit_rates, 0, 0), + + SD_BUS_METHOD("SetNTP", "as", NULL, bus_link_method_set_ntp_servers, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_domains, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDefaultRoute", "b", NULL, bus_link_method_set_default_route, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDNSOverTLS", "s", NULL, bus_link_method_set_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RevertNTP", NULL, NULL, bus_link_method_revert_ntp, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RevertDNS", NULL, NULL, bus_link_method_revert_dns, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Renew", NULL, NULL, bus_link_method_renew, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Reconfigure", NULL, NULL, bus_link_method_reconfigure, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_VTABLE_END +}; + +char *link_bus_path(Link *link) { + _cleanup_free_ char *ifindex = NULL; + char *p; + int r; + + assert(link); + assert(link->ifindex > 0); + + if (asprintf(&ifindex, "%d", link->ifindex) < 0) + return NULL; + + r = sd_bus_path_encode("/org/freedesktop/network1/link", ifindex, &p); + if (r < 0) + return NULL; + + return p; +} + +int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + unsigned c = 0; + Link *link; + Iterator i; + + assert(bus); + assert(path); + assert(m); + assert(nodes); + + l = new0(char*, hashmap_size(m->links) + 1); + if (!l) + return -ENOMEM; + + HASHMAP_FOREACH(link, m->links, i) { + char *p; + + p = link_bus_path(link); + if (!p) + return -ENOMEM; + + l[c++] = p; + } + + l[c] = NULL; + *nodes = TAKE_PTR(l); + + return 1; +} + +int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + _cleanup_free_ char *identifier = NULL; + Manager *m = userdata; + Link *link; + int ifindex, r; + + assert(bus); + assert(path); + assert(interface); + assert(m); + assert(found); + + r = sd_bus_path_decode(path, "/org/freedesktop/network1/link", &identifier); + if (r <= 0) + return 0; + + r = parse_ifindex(identifier, &ifindex); + if (r < 0) + return 0; + + r = link_get(m, ifindex, &link); + if (r < 0) + return 0; + + *found = link; + + return 1; +} + +int link_send_changed_strv(Link *link, char **properties) { + _cleanup_free_ char *p = NULL; + + assert(link); + assert(link->manager); + assert(properties); + + if (!link->manager->bus) + return 0; + + p = link_bus_path(link); + if (!p) + return -ENOMEM; + + return sd_bus_emit_properties_changed_strv( + link->manager->bus, + p, + "org.freedesktop.network1.Link", + properties); +} + +int link_send_changed(Link *link, const char *property, ...) { + char **properties; + + properties = strv_from_stdarg_alloca(property); + + return link_send_changed_strv(link, properties); +} diff --git a/src/network/networkd-link-bus.h b/src/network/networkd-link-bus.h new file mode 100644 index 00000000..09e4ad68 --- /dev/null +++ b/src/network/networkd-link-bus.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "macro.h" + +typedef struct Link Link; + +extern const sd_bus_vtable link_vtable[]; + +char *link_bus_path(Link *link); +int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); +int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +int link_send_changed_strv(Link *link, char **properties); +int link_send_changed(Link *link, const char *property, ...) _sentinel_; + +int property_get_operational_state(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); +int property_get_carrier_state(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); +int property_get_address_state(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); + +int bus_link_method_set_ntp_servers(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_revert_ntp(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_revert_dns(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_renew(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c new file mode 100644 index 00000000..2e60adbf --- /dev/null +++ b/src/network/networkd-link.c @@ -0,0 +1,4100 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "bond.h" +#include "bridge.h" +#include "bus-util.h" +#include "dhcp-identifier.h" +#include "dhcp-lease-internal.h" +#include "env-file.h" +#include "fd-util.h" +#include "fileio.h" +#include "ipvlan.h" +#include "missing_network.h" +#include "netlink-util.h" +#include "network-internal.h" +#include "networkd-can.h" +#include "networkd-dhcp-server.h" +#include "networkd-dhcp4.h" +#include "networkd-dhcp6.h" +#include "networkd-ipv4ll.h" +#include "networkd-ipv6-proxy-ndp.h" +#include "networkd-link-bus.h" +#include "networkd-link.h" +#include "networkd-lldp-tx.h" +#include "networkd-manager.h" +#include "networkd-ndisc.h" +#include "networkd-neighbor.h" +#include "networkd-radv.h" +#include "networkd-routing-policy-rule.h" +#include "networkd-wifi.h" +#include "qdisc.h" +#include "set.h" +#include "socket-util.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "strv.h" +#include "sysctl-util.h" +#include "tmpfile-util.h" +#include "udev-util.h" +#include "util.h" +#include "vrf.h" + +uint32_t link_get_vrf_table(Link *link) { + return link->network->vrf ? VRF(link->network->vrf)->table : RT_TABLE_MAIN; +} + +uint32_t link_get_dhcp_route_table(Link *link) { + /* When the interface is part of an VRF use the VRFs routing table, unless + * another table is explicitly specified. */ + if (link->network->dhcp_route_table_set) + return link->network->dhcp_route_table; + return link_get_vrf_table(link); +} + +uint32_t link_get_ipv6_accept_ra_route_table(Link *link) { + if (link->network->ipv6_accept_ra_route_table_set) + return link->network->ipv6_accept_ra_route_table; + return link_get_vrf_table(link); +} + +DUID* link_get_duid(Link *link) { + if (link->network->duid.type != _DUID_TYPE_INVALID) + return &link->network->duid; + else + return &link->manager->duid; +} + +static bool link_dhcp6_enabled(Link *link) { + assert(link); + + if (!socket_ipv6_is_supported()) + return false; + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->bond) + return false; + + if (link->iftype == ARPHRD_CAN) + return false; + + return link->network->dhcp & ADDRESS_FAMILY_IPV6; +} + +static bool link_dhcp4_enabled(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->bond) + return false; + + if (link->iftype == ARPHRD_CAN) + return false; + + return link->network->dhcp & ADDRESS_FAMILY_IPV4; +} + +static bool link_dhcp4_server_enabled(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->bond) + return false; + + if (link->iftype == ARPHRD_CAN) + return false; + + return link->network->dhcp_server; +} + +bool link_ipv4ll_enabled(Link *link, AddressFamily mask) { + assert(link); + assert((mask & ~(ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) == 0); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->iftype == ARPHRD_CAN) + return false; + + if (STRPTR_IN_SET(link->kind, + "vrf", "wireguard", "ipip", "gre", "ip6gre","ip6tnl", "sit", "vti", + "vti6", "nlmon", "xfrm")) + return false; + + /* L3 or L3S mode do not support ARP. */ + if (IN_SET(link_get_ipvlan_mode(link), NETDEV_IPVLAN_MODE_L3, NETDEV_IPVLAN_MODE_L3S)) + return false; + + if (link->network->bond) + return false; + + return link->network->link_local & mask; +} + +static bool link_ipv6ll_enabled(Link *link) { + assert(link); + + if (!socket_ipv6_is_supported()) + return false; + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->iftype == ARPHRD_CAN) + return false; + + if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti", "nlmon")) + return false; + + if (link->network->bond) + return false; + + return link->network->link_local & ADDRESS_FAMILY_IPV6; +} + +static bool link_ipv6_enabled(Link *link) { + assert(link); + + if (!socket_ipv6_is_supported()) + return false; + + if (link->network->bond) + return false; + + if (link->iftype == ARPHRD_CAN) + return false; + + /* DHCPv6 client will not be started if no IPv6 link-local address is configured. */ + if (link_ipv6ll_enabled(link)) + return true; + + if (network_has_static_ipv6_configurations(link->network)) + return true; + + return false; +} + +static bool link_radv_enabled(Link *link) { + assert(link); + + if (!link_ipv6ll_enabled(link)) + return false; + + return link->network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE; +} + +static bool link_ipv4_forward_enabled(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->ip_forward == _ADDRESS_FAMILY_INVALID) + return false; + + return link->network->ip_forward & ADDRESS_FAMILY_IPV4; +} + +static bool link_ipv6_forward_enabled(Link *link) { + assert(link); + + if (!socket_ipv6_is_supported()) + return false; + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->ip_forward == _ADDRESS_FAMILY_INVALID) + return false; + + return link->network->ip_forward & ADDRESS_FAMILY_IPV6; +} + +static bool link_proxy_arp_enabled(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (link->network->proxy_arp < 0) + return false; + + return true; +} + +static bool link_ipv6_accept_ra_enabled(Link *link) { + assert(link); + + if (!socket_ipv6_is_supported()) + return false; + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + if (!link_ipv6ll_enabled(link)) + return false; + + /* If unset use system default (enabled if local forwarding is disabled. + * disabled if local forwarding is enabled). + * If set, ignore or enforce RA independent of local forwarding state. + */ + if (link->network->ipv6_accept_ra < 0) + /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */ + return !link_ipv6_forward_enabled(link); + else if (link->network->ipv6_accept_ra > 0) + /* accept RA even if ip_forward is enabled */ + return true; + else + /* ignore RA */ + return false; +} + +static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) { + assert(link); + + if (!socket_ipv6_is_supported()) + return _IPV6_PRIVACY_EXTENSIONS_INVALID; + + if (link->flags & IFF_LOOPBACK) + return _IPV6_PRIVACY_EXTENSIONS_INVALID; + + if (!link->network) + return _IPV6_PRIVACY_EXTENSIONS_INVALID; + + return link->network->ipv6_privacy_extensions; +} + +static int link_update_ipv6_sysctl(Link *link) { + bool enabled; + int r; + + if (link->flags & IFF_LOOPBACK) + return 0; + + enabled = link_ipv6_enabled(link); + if (enabled) { + r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false); + if (r < 0) + return log_link_warning_errno(link, r, "Cannot enable IPv6: %m"); + + log_link_info(link, "IPv6 successfully enabled"); + } + + return 0; +} + +static bool link_is_enslaved(Link *link) { + if (link->flags & IFF_SLAVE) + /* Even if the link is not managed by networkd, honor IFF_SLAVE flag. */ + return true; + + if (!link->network) + return false; + + if (link->master_ifindex > 0 && link->network->bridge) + return true; + + /* TODO: add conditions for other netdevs. */ + + return false; +} + +static void link_update_master_operstate(Link *link, NetDev *netdev) { + Link *master; + + if (!netdev) + return; + + if (link_get(link->manager, netdev->ifindex, &master) < 0) + return; + + link_update_operstate(master, true); +} + +void link_update_operstate(Link *link, bool also_update_master) { + LinkOperationalState operstate; + LinkCarrierState carrier_state; + LinkAddressState address_state; + _cleanup_strv_free_ char **p = NULL; + uint8_t scope = RT_SCOPE_NOWHERE; + bool changed = false; + Address *address; + Iterator i; + + assert(link); + + if (link->kernel_operstate == IF_OPER_DORMANT) + carrier_state = LINK_CARRIER_STATE_DORMANT; + else if (link_has_carrier(link)) { + if (link_is_enslaved(link)) + carrier_state = LINK_CARRIER_STATE_ENSLAVED; + else + carrier_state = LINK_CARRIER_STATE_CARRIER; + } else if (link->flags & IFF_UP) + carrier_state = LINK_CARRIER_STATE_NO_CARRIER; + else + carrier_state = LINK_CARRIER_STATE_OFF; + + if (carrier_state >= LINK_CARRIER_STATE_CARRIER) { + Link *slave; + + SET_FOREACH(slave, link->slaves, i) { + link_update_operstate(slave, false); + + if (slave->carrier_state < LINK_CARRIER_STATE_CARRIER) + carrier_state = LINK_CARRIER_STATE_DEGRADED_CARRIER; + } + } + + SET_FOREACH(address, link->addresses, i) { + if (!address_is_ready(address)) + continue; + + if (address->scope < scope) + scope = address->scope; + } + + /* for operstate we also take foreign addresses into account */ + SET_FOREACH(address, link->addresses_foreign, i) { + if (!address_is_ready(address)) + continue; + + if (address->scope < scope) + scope = address->scope; + } + + if (scope < RT_SCOPE_SITE) + /* universally accessible addresses found */ + address_state = LINK_ADDRESS_STATE_ROUTABLE; + else if (scope < RT_SCOPE_HOST) + /* only link or site local addresses found */ + address_state = LINK_ADDRESS_STATE_DEGRADED; + else + /* no useful addresses found */ + address_state = LINK_ADDRESS_STATE_OFF; + + /* Mapping of address and carrier state vs operational state + * carrier state + * | off | no-carrier | dormant | degraded-carrier | carrier | enslaved + * ------------------------------------------------------------------------------ + * off | off | no-carrier | dormant | degraded-carrier | carrier | enslaved + * address_state degraded | off | no-carrier | dormant | degraded-carrier | degraded | enslaved + * routable | off | no-carrier | dormant | degraded-carrier | routable | routable + */ + + if (carrier_state < LINK_CARRIER_STATE_CARRIER || address_state == LINK_ADDRESS_STATE_OFF) + operstate = (LinkOperationalState) carrier_state; + else if (address_state == LINK_ADDRESS_STATE_ROUTABLE) + operstate = LINK_OPERSTATE_ROUTABLE; + else if (carrier_state == LINK_CARRIER_STATE_CARRIER) + operstate = LINK_OPERSTATE_DEGRADED; + else + operstate = LINK_OPERSTATE_ENSLAVED; + + if (link->carrier_state != carrier_state) { + link->carrier_state = carrier_state; + changed = true; + if (strv_extend(&p, "CarrierState") < 0) + log_oom(); + } + + if (link->address_state != address_state) { + link->address_state = address_state; + changed = true; + if (strv_extend(&p, "AddressState") < 0) + log_oom(); + } + + if (link->operstate != operstate) { + link->operstate = operstate; + changed = true; + if (strv_extend(&p, "OperationalState") < 0) + log_oom(); + } + + if (p) + link_send_changed_strv(link, p); + if (changed) + link_dirty(link); + + if (also_update_master && link->network) { + link_update_master_operstate(link, link->network->bond); + link_update_master_operstate(link, link->network->bridge); + } +} + +#define FLAG_STRING(string, flag, old, new) \ + (((old ^ new) & flag) \ + ? ((old & flag) ? (" -" string) : (" +" string)) \ + : "") + +static int link_update_flags(Link *link, sd_netlink_message *m, bool force_update_operstate) { + unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags; + uint8_t operstate; + int r; + + assert(link); + + r = sd_rtnl_message_link_get_flags(m, &flags); + if (r < 0) + return log_link_warning_errno(link, r, "Could not get link flags: %m"); + + r = sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &operstate); + if (r < 0) + /* if we got a message without operstate, take it to mean + the state was unchanged */ + operstate = link->kernel_operstate; + + if (!force_update_operstate && (link->flags == flags) && (link->kernel_operstate == operstate)) + return 0; + + if (link->flags != flags) { + log_link_debug(link, "Flags change:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags), + FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags), + FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags), + FLAG_STRING("UP", IFF_UP, link->flags, flags), + FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags), + FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags), + FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags), + FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags), + FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags), + FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags), + FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags), + FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags), + FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags), + FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags), + FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags), + FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags), + FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags), + FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags), + FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags)); + + unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP | + IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING | + IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT | + IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL | + IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP | + IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO); + unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags); + unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags); + + /* link flags are currently at most 18 bits, let's align to + * printing 20 */ + if (unknown_flags_added) + log_link_debug(link, + "Unknown link flags gained: %#.5x (ignoring)", + unknown_flags_added); + + if (unknown_flags_removed) + log_link_debug(link, + "Unknown link flags lost: %#.5x (ignoring)", + unknown_flags_removed); + } + + link->flags = flags; + link->kernel_operstate = operstate; + + link_update_operstate(link, true); + + return 0; +} + +static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { + _cleanup_(link_unrefp) Link *link = NULL; + uint16_t type; + const char *ifname, *kind = NULL; + int r, ifindex; + unsigned short iftype; + + assert(manager); + assert(message); + assert(ret); + + /* check for link kind */ + r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); + if (r == 0) { + (void) sd_netlink_message_read_string(message, IFLA_INFO_KIND, &kind); + r = sd_netlink_message_exit_container(message); + if (r < 0) + return r; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) + return r; + else if (type != RTM_NEWLINK) + return -EINVAL; + + r = sd_rtnl_message_link_get_ifindex(message, &ifindex); + if (r < 0) + return r; + else if (ifindex <= 0) + return -EINVAL; + + r = sd_rtnl_message_link_get_type(message, &iftype); + if (r < 0) + return r; + + r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname); + if (r < 0) + return r; + + link = new(Link, 1); + if (!link) + return -ENOMEM; + + *link = (Link) { + .n_ref = 1, + .manager = manager, + .state = LINK_STATE_PENDING, + .ifindex = ifindex, + .iftype = iftype, + + .n_dns = (unsigned) -1, + .dns_default_route = -1, + .llmnr = _RESOLVE_SUPPORT_INVALID, + .mdns = _RESOLVE_SUPPORT_INVALID, + .dnssec_mode = _DNSSEC_MODE_INVALID, + .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID, + }; + + link->ifname = strdup(ifname); + if (!link->ifname) + return -ENOMEM; + + if (kind) { + link->kind = strdup(kind); + if (!link->kind) + return -ENOMEM; + } + + r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t *)&link->master_ifindex); + if (r < 0) + log_link_debug_errno(link, r, "New device has no master, continuing without"); + + r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac); + if (r < 0) + log_link_debug_errno(link, r, "MAC address not found for new device, continuing without"); + + if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0) + return -ENOMEM; + + if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0) + return -ENOMEM; + + if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0) + return -ENOMEM; + + r = hashmap_ensure_allocated(&manager->links, NULL); + if (r < 0) + return r; + + r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link); + if (r < 0) + return r; + + r = link_update_flags(link, message, false); + if (r < 0) + return r; + + *ret = TAKE_PTR(link); + + return 0; +} + +void link_ntp_settings_clear(Link *link) { + link->ntp = strv_free(link->ntp); +} + +void link_dns_settings_clear(Link *link) { + link->dns = mfree(link->dns); + link->n_dns = (unsigned) -1; + + link->search_domains = ordered_set_free_free(link->search_domains); + link->route_domains = ordered_set_free_free(link->route_domains); + + link->dns_default_route = -1; + link->llmnr = _RESOLVE_SUPPORT_INVALID; + link->mdns = _RESOLVE_SUPPORT_INVALID; + link->dnssec_mode = _DNSSEC_MODE_INVALID; + link->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID; + + link->dnssec_negative_trust_anchors = set_free_free(link->dnssec_negative_trust_anchors); +} + +static void link_free_engines(Link *link) { + if (!link) + return; + + link->dhcp_server = sd_dhcp_server_unref(link->dhcp_server); + link->dhcp_client = sd_dhcp_client_unref(link->dhcp_client); + link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease); + link->dhcp_routes = set_free(link->dhcp_routes); + + link->lldp = sd_lldp_unref(link->lldp); + + ndisc_flush(link); + + link->ipv4ll = sd_ipv4ll_unref(link->ipv4ll); + link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); + link->ndisc = sd_ndisc_unref(link->ndisc); + link->radv = sd_radv_unref(link->radv); +} + +static Link *link_free(Link *link) { + Address *address; + + assert(link); + + link_ntp_settings_clear(link); + link_dns_settings_clear(link); + + link->routes = set_free_with_destructor(link->routes, route_free); + link->routes_foreign = set_free_with_destructor(link->routes_foreign, route_free); + + link->nexthops = set_free_with_destructor(link->nexthops, nexthop_free); + link->nexthops_foreign = set_free_with_destructor(link->nexthops_foreign, nexthop_free); + + link->neighbors = set_free_with_destructor(link->neighbors, neighbor_free); + link->neighbors_foreign = set_free_with_destructor(link->neighbors_foreign, neighbor_free); + + link->addresses = set_free_with_destructor(link->addresses, address_free); + link->addresses_foreign = set_free_with_destructor(link->addresses_foreign, address_free); + + while ((address = link->pool_addresses)) { + LIST_REMOVE(addresses, link->pool_addresses, address); + address_free(address); + } + + link_lldp_emit_stop(link); + link_free_engines(link); + free(link->lease_file); + free(link->lldp_file); + + free(link->ifname); + free(link->kind); + free(link->ssid); + + (void) unlink(link->state_file); + free(link->state_file); + + sd_device_unref(link->sd_device); + + hashmap_free(link->bound_to_links); + hashmap_free(link->bound_by_links); + + set_free_with_destructor(link->slaves, link_unref); + + network_unref(link->network); + + return mfree(link); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(Link, link, link_free); + +int link_get(Manager *m, int ifindex, Link **ret) { + Link *link; + + assert(m); + assert(ifindex); + assert(ret); + + link = hashmap_get(m->links, INT_TO_PTR(ifindex)); + if (!link) + return -ENODEV; + + *ret = link; + + return 0; +} + +void link_set_state(Link *link, LinkState state) { + assert(link); + + if (link->state == state) + return; + + log_link_debug(link, "State changed: %s -> %s", + link_state_to_string(link->state), + link_state_to_string(state)); + + link->state = state; + + link_send_changed(link, "AdministrativeState", NULL); +} + +static void link_enter_unmanaged(Link *link) { + assert(link); + + link_set_state(link, LINK_STATE_UNMANAGED); + + link_dirty(link); +} + +int link_stop_clients(Link *link, bool may_keep_dhcp) { + int r = 0, k; + + assert(link); + assert(link->manager); + assert(link->manager->event); + + dhcp4_release_old_lease(link); + + bool keep_dhcp = may_keep_dhcp && + link->network && + (link->manager->restarting || + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP_ON_STOP)); + + if (link->dhcp_client && !keep_dhcp) { + k = sd_dhcp_client_stop(link->dhcp_client); + if (k < 0) + r = log_link_warning_errno(link, k, "Could not stop DHCPv4 client: %m"); + } + + if (link->ipv4ll) { + k = sd_ipv4ll_stop(link->ipv4ll); + if (k < 0) + r = log_link_warning_errno(link, k, "Could not stop IPv4 link-local: %m"); + } + + if (link->dhcp6_client) { + k = sd_dhcp6_client_stop(link->dhcp6_client); + if (k < 0) + r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m"); + } + + if (link->ndisc) { + k = sd_ndisc_stop(link->ndisc); + if (k < 0) + r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m"); + } + + if (link->radv) { + k = sd_radv_stop(link->radv); + if (k < 0) + r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Advertisement: %m"); + } + + link_lldp_emit_stop(link); + return r; +} + +void link_enter_failed(Link *link) { + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return; + + log_link_warning(link, "Failed"); + + link_set_state(link, LINK_STATE_FAILED); + + link_stop_clients(link, false); + + link_dirty(link); +} + +static int link_join_netdevs_after_configured(Link *link) { + NetDev *netdev; + Iterator i; + int r; + + HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) { + if (netdev->ifindex > 0) + /* Assume already enslaved. */ + continue; + + if (netdev_get_create_type(netdev) != NETDEV_CREATE_AFTER_CONFIGURED) + continue; + + log_struct(LOG_DEBUG, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(netdev), + LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname)); + + r = netdev_join(netdev, link, NULL); + if (r < 0) + return log_struct_errno(LOG_WARNING, r, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(netdev), + LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname)); + } + + return 0; +} + +static void link_enter_configured(Link *link) { + assert(link); + assert(link->network); + + if (link->state != LINK_STATE_CONFIGURING) + return; + + link_set_state(link, LINK_STATE_CONFIGURED); + + (void) link_join_netdevs_after_configured(link); + + link_dirty(link); +} + +static int link_request_set_routing_policy_rule(Link *link) { + RoutingPolicyRule *rule, *rrule = NULL; + int r; + + assert(link); + assert(link->network); + + link->routing_policy_rules_configured = false; + + LIST_FOREACH(rules, rule, link->network->rules) { + r = routing_policy_rule_get(link->manager, rule, &rrule); + if (r >= 0) { + if (r == 0) + (void) routing_policy_rule_make_local(link->manager, rrule); + continue; + } + + r = routing_policy_rule_configure(rule, link, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set routing policy rules: %m"); + if (r > 0) + link->routing_policy_rule_messages++; + } + + routing_policy_rule_purge(link->manager, link); + if (link->routing_policy_rule_messages == 0) { + link->routing_policy_rules_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting routing policy rules"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + +static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->nexthop_messages > 0); + assert(IN_SET(link->state, LINK_STATE_CONFIGURING, + LINK_STATE_FAILED, LINK_STATE_LINGER)); + + link->nexthop_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_warning_errno(link, r, "Could not set nexthop: %m"); + link_enter_failed(link); + return 1; + } + + if (link->nexthop_messages == 0) { + log_link_debug(link, "Nexthop set"); + link->static_nexthops_configured = true; + link_check_ready(link); + } + + return 1; +} + +int link_request_set_nexthop(Link *link) { + NextHop *nh; + int r; + + LIST_FOREACH(nexthops, nh, link->network->static_nexthops) { + r = nexthop_configure(nh, link, nexthop_handler); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set nexthop: %m"); + if (r > 0) + link->nexthop_messages++; + } + + if (link->nexthop_messages == 0) { + link->static_nexthops_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting nexthop"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 1; +} + +static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->route_messages > 0); + assert(IN_SET(link->state, LINK_STATE_CONFIGURING, + LINK_STATE_FAILED, LINK_STATE_LINGER)); + + link->route_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_warning_errno(link, r, "Could not set route: %m"); + link_enter_failed(link); + return 1; + } + + if (link->route_messages == 0) { + log_link_debug(link, "Routes set"); + link->static_routes_configured = true; + link_check_ready(link); + } + + return 1; +} + +int link_request_set_routes(Link *link) { + enum { + PHASE_NON_GATEWAY, /* First phase: Routes without a gateway */ + PHASE_GATEWAY, /* Second phase: Routes with a gateway */ + _PHASE_MAX + } phase; + Route *rt; + int r; + + assert(link); + assert(link->network); + assert(link->addresses_configured); + assert(link->address_messages == 0); + assert(link->state != _LINK_STATE_INVALID); + + link->static_routes_configured = false; + link->static_routes_ready = false; + + if (!link_has_carrier(link) && !link->network->configure_without_carrier) + /* During configuring addresses, the link lost its carrier. As networkd is dropping + * the addresses now, let's not configure the routes either. */ + return 0; + + r = link_request_set_routing_policy_rule(link); + if (r < 0) + return r; + + /* First add the routes that enable us to talk to gateways, then add in the others that need a gateway. */ + for (phase = 0; phase < _PHASE_MAX; phase++) + LIST_FOREACH(routes, rt, link->network->static_routes) { + + if (in_addr_is_null(rt->family, &rt->gw) != (phase == PHASE_NON_GATEWAY)) + continue; + + r = route_configure(rt, link, route_handler); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set routes: %m"); + if (r > 0) + link->route_messages++; + } + + if (link->route_messages == 0) { + link->static_routes_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting routes"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + +void link_check_ready(Link *link) { + Address *a; + Iterator i; + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return; + + if (!link->network) + return; + + if (!link->addresses_configured) + return; + + if (!link->neighbors_configured) + return; + + SET_FOREACH(a, link->addresses, i) + if (!address_is_ready(a)) + return; + + if (!link->addresses_ready) { + link->addresses_ready = true; + r = link_request_set_routes(link); + if (r < 0) + link_enter_failed(link); + return; + } + + if (!link->static_routes_configured) + return; + + if (!link->static_routes_ready) { + link->static_routes_ready = true; + r = link_request_set_nexthop(link); + if (r < 0) + link_enter_failed(link); + return; + } + + if (!link->static_nexthops_configured) + return; + + if (!link->routing_policy_rules_configured) + return; + + if (!link->qdiscs_configured) + return; + + if (link_has_carrier(link) || !link->network->configure_without_carrier) { + + if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address) + return; + + if (link_ipv6ll_enabled(link) && + in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address)) + return; + + if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) && + !link->dhcp4_configured && + !link->dhcp6_configured && + !(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address)) + /* When DHCP is enabled, at least one protocol must provide an address, or + * an IPv4ll fallback address must be configured. */ + return; + + if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured) + return; + } + + if (link->state != LINK_STATE_CONFIGURED) + link_enter_configured(link); + + return; +} + +static int link_request_set_neighbors(Link *link) { + Neighbor *neighbor; + int r; + + assert(link); + assert(link->network); + assert(link->state != _LINK_STATE_INVALID); + + link->neighbors_configured = false; + + LIST_FOREACH(neighbors, neighbor, link->network->neighbors) { + r = neighbor_configure(neighbor, link, NULL); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set neighbor: %m"); + } + + if (link->neighbor_messages == 0) { + link->neighbors_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting neighbors"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + +static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(rtnl); + assert(m); + assert(link); + assert(link->ifname); + assert(link->address_messages > 0); + assert(IN_SET(link->state, LINK_STATE_CONFIGURING, + LINK_STATE_FAILED, LINK_STATE_LINGER)); + + link->address_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_warning_errno(link, r, "could not set address: %m"); + link_enter_failed(link); + return 1; + } else if (r >= 0) + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + if (link->address_messages == 0) { + log_link_debug(link, "Addresses set"); + link->addresses_configured = true; + link_check_ready(link); + } + + return 1; +} + +static int link_set_bridge_fdb(Link *link) { + FdbEntry *fdb_entry; + int r; + + LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) { + r = fdb_entry_configure(link, fdb_entry); + if (r < 0) + return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m"); + } + + return 0; +} + +static int link_request_set_addresses(Link *link) { + AddressLabel *label; + Address *ad; + int r; + + assert(link); + assert(link->network); + assert(link->state != _LINK_STATE_INVALID); + + /* Reset all *_configured flags we are configuring. */ + link->addresses_configured = false; + link->addresses_ready = false; + link->neighbors_configured = false; + link->static_routes_configured = false; + link->static_routes_ready = false; + link->static_nexthops_configured = false; + link->routing_policy_rules_configured = false; + + r = link_set_bridge_fdb(link); + if (r < 0) + return r; + + r = link_request_set_neighbors(link); + if (r < 0) + return r; + + LIST_FOREACH(addresses, ad, link->network->static_addresses) { + bool update; + + update = address_get(link, ad->family, &ad->in_addr, ad->prefixlen, NULL) > 0; + + r = address_configure(ad, link, address_handler, update); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set addresses: %m"); + if (r > 0) + link->address_messages++; + } + + LIST_FOREACH(labels, label, link->network->address_labels) { + r = address_label_configure(label, link, NULL, false); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set address label: %m"); + + link->address_label_messages++; + } + + /* now that we can figure out a default address for the dhcp server, + start it */ + if (link_dhcp4_server_enabled(link) && (link->flags & IFF_UP)) { + r = dhcp4_server_configure(link); + if (r < 0) + return r; + log_link_debug(link, "Offering DHCPv4 leases"); + } + + if (link->address_messages == 0) { + link->addresses_configured = true; + link_check_ready(link); + } else { + log_link_debug(link, "Setting addresses"); + link_set_state(link, LINK_STATE_CONFIGURING); + } + + return 0; +} + +static int link_set_bridge_vlan(Link *link) { + int r; + + r = br_vlan_configure(link, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap); + if (r < 0) + log_link_error_errno(link, r, "Failed to assign VLANs to bridge port: %m"); + + return r; +} + +static int link_set_proxy_arp(Link *link) { + int r; + + if (!link_proxy_arp_enabled(link)) + return 0; + + r = sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface: %m"); + + return 0; +} + +static int link_configure_after_setting_mtu(Link *link); + +static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + + link->setting_mtu = false; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_warning_errno(link, r, "Could not set MTU, ignoring: %m"); + else + log_link_debug(link, "Setting MTU done."); + + if (link->state == LINK_STATE_INITIALIZED) { + r = link_configure_after_setting_mtu(link); + if (r < 0) + link_enter_failed(link); + } + + return 1; +} + +int link_set_mtu(Link *link, uint32_t mtu) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + + if (mtu == 0 || link->setting_mtu) + return 0; + + if (link->mtu == mtu) + return 0; + + log_link_debug(link, "Setting MTU: %" PRIu32, mtu); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes + * on the interface. Bump up MTU bytes to IPV6_MTU_MIN. */ + if (link_ipv6_enabled(link) && mtu < IPV6_MIN_MTU) { + + log_link_warning(link, "Bumping MTU to " STRINGIFY(IPV6_MIN_MTU) ", as " + "IPv6 is requested and requires a minimum MTU of " STRINGIFY(IPV6_MIN_MTU) " bytes"); + + mtu = IPV6_MIN_MTU; + } + + r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu); + if (r < 0) + return log_link_error_errno(link, r, "Could not append MTU: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, set_mtu_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + link->setting_mtu = true; + + return 0; +} + +static bool link_reduces_vlan_mtu(Link *link) { + /* See netif_reduces_vlan_mtu() in kernel. */ + return streq_ptr(link->kind, "macsec"); +} + +static uint32_t link_get_requested_mtu_by_stacked_netdevs(Link *link) { + uint32_t mtu = 0; + NetDev *dev; + Iterator i; + + HASHMAP_FOREACH(dev, link->network->stacked_netdevs, i) + if (dev->kind == NETDEV_KIND_VLAN && dev->mtu > 0) + /* See vlan_dev_change_mtu() in kernel. */ + mtu = MAX(mtu, link_reduces_vlan_mtu(link) ? dev->mtu + 4 : dev->mtu); + + else if (dev->kind == NETDEV_KIND_MACVLAN && dev->mtu > mtu) + /* See macvlan_change_mtu() in kernel. */ + mtu = dev->mtu; + + return mtu; +} + +static int link_configure_mtu(Link *link) { + uint32_t mtu; + + assert(link); + assert(link->network); + + if (link->network->mtu > 0) + return link_set_mtu(link, link->network->mtu); + + mtu = link_get_requested_mtu_by_stacked_netdevs(link); + if (link->mtu >= mtu) + return 0; + + log_link_notice(link, "Bumping MTU bytes from %"PRIu32" to %"PRIu32" because of stacked device. " + "If it is not desired, then please explicitly specify MTUBytes= setting.", + link->mtu, mtu); + + return link_set_mtu(link, mtu); +} + +static int set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_warning_errno(link, r, "Could not set link flags, ignoring: %m"); + + return 1; +} + +static int link_set_flags(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + unsigned ifi_change = 0; + unsigned ifi_flags = 0; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + if (link->network->arp < 0 && link->network->multicast < 0 && link->network->allmulticast < 0) + return 0; + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + if (link->network->arp >= 0) { + ifi_change |= IFF_NOARP; + SET_FLAG(ifi_flags, IFF_NOARP, link->network->arp == 0); + } + + if (link->network->multicast >= 0) { + ifi_change |= IFF_MULTICAST; + SET_FLAG(ifi_flags, IFF_MULTICAST, link->network->multicast); + } + + if (link->network->allmulticast >= 0) { + ifi_change |= IFF_ALLMULTI; + SET_FLAG(ifi_flags, IFF_ALLMULTI, link->network->allmulticast); + } + + r = sd_rtnl_message_link_set_flags(req, ifi_flags, ifi_change); + if (r < 0) + return log_link_error_errno(link, r, "Could not set link flags: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, set_flags_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static int link_acquire_ipv6_conf(Link *link) { + int r; + + assert(link); + + if (link_ipv6_accept_ra_enabled(link)) { + assert(link->ndisc); + + log_link_debug(link, "Discovering IPv6 routers"); + + r = sd_ndisc_start(link->ndisc); + if (r < 0 && r != -EBUSY) + return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m"); + } + + if (link_radv_enabled(link)) { + assert(link->radv); + assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0); + + log_link_debug(link, "Starting IPv6 Router Advertisements"); + + r = sd_radv_start(link->radv); + if (r < 0 && r != -EBUSY) + return log_link_warning_errno(link, r, "Could not start IPv6 Router Advertisement: %m"); + } + + (void) dhcp6_request_prefix_delegation(link); + + return 0; +} + +static int link_acquire_ipv4_conf(Link *link) { + int r; + + assert(link); + assert(link->manager); + assert(link->manager->event); + + if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4)) { + assert(link->ipv4ll); + + log_link_debug(link, "Acquiring IPv4 link-local address"); + + r = sd_ipv4ll_start(link->ipv4ll); + if (r < 0) + return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m"); + } + + if (link_dhcp4_enabled(link)) { + assert(link->dhcp_client); + + log_link_debug(link, "Acquiring DHCPv4 lease"); + + r = sd_dhcp_client_start(link->dhcp_client); + if (r < 0) + return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m"); + } + + return 0; +} + +static int link_acquire_conf(Link *link) { + int r; + + assert(link); + + r = link_acquire_ipv4_conf(link); + if (r < 0) + return r; + + if (!in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address)) { + r = link_acquire_ipv6_conf(link); + if (r < 0) + return r; + } + + if (link_lldp_emit_enabled(link)) { + r = link_lldp_emit_start(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to start LLDP transmission: %m"); + } + + return 0; +} + +bool link_has_carrier(Link *link) { + /* see Documentation/networking/operstates.txt in the kernel sources */ + + if (link->kernel_operstate == IF_OPER_UP) + return true; + + if (link->kernel_operstate == IF_OPER_UNKNOWN) + /* operstate may not be implemented, so fall back to flags */ + if (FLAGS_SET(link->flags, IFF_LOWER_UP | IFF_RUNNING) && + !FLAGS_SET(link->flags, IFF_DORMANT)) + return true; + + return false; +} + +static int link_address_genmode_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_warning_errno(link, r, "Could not set address genmode for interface, ignoring: %m"); + + return 1; +} + +static int link_configure_addrgen_mode(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + uint8_t ipv6ll_mode; + int r; + + assert(link); + assert(link->network); + assert(link->manager); + assert(link->manager->rtnl); + + if (!socket_ipv6_is_supported()) + return 0; + + log_link_debug(link, "Setting address genmode for link"); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_netlink_message_open_container(req, IFLA_AF_SPEC); + if (r < 0) + return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m"); + + r = sd_netlink_message_open_container(req, AF_INET6); + if (r < 0) + return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m"); + + if (!link_ipv6ll_enabled(link)) + ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE; + else if (sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL) < 0) + /* The file may not exist. And event if it exists, when stable_secret is unset, + * reading the file fails with EIO. */ + ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64; + else + ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY; + + r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m"); + + r = sd_netlink_message_close_container(req); + if (r < 0) + return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m"); + + r = sd_netlink_message_close_container(req); + if (r < 0) + return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, link_address_genmode_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + /* we warn but don't fail the link, as it may be brought up later */ + log_link_warning_errno(link, r, "Could not bring up interface: %m"); + + return 1; +} + +static int link_up(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->network); + assert(link->manager); + assert(link->manager->rtnl); + + log_link_debug(link, "Bringing link up"); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + /* set it free if not enslaved with networkd */ + if (!link->network->bridge && !link->network->bond && !link->network->vrf) { + r = sd_netlink_message_append_u32(req, IFLA_MASTER, 0); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_MASTER attribute: %m"); + } + + r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP); + if (r < 0) + return log_link_error_errno(link, r, "Could not set link flags: %m"); + + if (link->network->mac) { + r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac); + if (r < 0) + return log_link_error_errno(link, r, "Could not set MAC address: %m"); + } + + r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_warning_errno(link, r, "Could not bring down interface: %m"); + + return 1; +} + +int link_down(Link *link, link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + + log_link_debug(link, "Bringing link down"); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, + RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP); + if (r < 0) + return log_link_error_errno(link, r, "Could not set link flags: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, + callback ?: link_down_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static int link_handle_bound_to_list(Link *link) { + Link *l; + Iterator i; + int r; + bool required_up = false; + bool link_is_up = false; + + assert(link); + + if (hashmap_isempty(link->bound_to_links)) + return 0; + + if (link->flags & IFF_UP) + link_is_up = true; + + HASHMAP_FOREACH (l, link->bound_to_links, i) + if (link_has_carrier(l)) { + required_up = true; + break; + } + + if (!required_up && link_is_up) { + r = link_down(link, NULL); + if (r < 0) + return r; + } else if (required_up && !link_is_up) { + r = link_up(link); + if (r < 0) + return r; + } + + return 0; +} + +static int link_handle_bound_by_list(Link *link) { + Iterator i; + Link *l; + int r; + + assert(link); + + if (hashmap_isempty(link->bound_by_links)) + return 0; + + HASHMAP_FOREACH (l, link->bound_by_links, i) { + r = link_handle_bound_to_list(l); + if (r < 0) + return r; + } + + return 0; +} + +static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) { + int r; + + assert(link); + assert(carrier); + + if (link == carrier) + return 0; + + if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex))) + return 0; + + r = hashmap_ensure_allocated(h, NULL); + if (r < 0) + return r; + + r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier); + if (r < 0) + return r; + + return 0; +} + +static int link_new_bound_by_list(Link *link) { + Manager *m; + Link *carrier; + Iterator i; + int r; + bool list_updated = false; + + assert(link); + assert(link->manager); + + m = link->manager; + + HASHMAP_FOREACH(carrier, m->links, i) { + if (!carrier->network) + continue; + + if (strv_isempty(carrier->network->bind_carrier)) + continue; + + if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) { + r = link_put_carrier(link, carrier, &link->bound_by_links); + if (r < 0) + return r; + + list_updated = true; + } + } + + if (list_updated) + link_dirty(link); + + HASHMAP_FOREACH(carrier, link->bound_by_links, i) { + r = link_put_carrier(carrier, link, &carrier->bound_to_links); + if (r < 0) + return r; + + link_dirty(carrier); + } + + return 0; +} + +static int link_new_bound_to_list(Link *link) { + Manager *m; + Link *carrier; + Iterator i; + int r; + bool list_updated = false; + + assert(link); + assert(link->manager); + + if (!link->network) + return 0; + + if (strv_isempty(link->network->bind_carrier)) + return 0; + + m = link->manager; + + HASHMAP_FOREACH (carrier, m->links, i) { + if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) { + r = link_put_carrier(link, carrier, &link->bound_to_links); + if (r < 0) + return r; + + list_updated = true; + } + } + + if (list_updated) + link_dirty(link); + + HASHMAP_FOREACH (carrier, link->bound_to_links, i) { + r = link_put_carrier(carrier, link, &carrier->bound_by_links); + if (r < 0) + return r; + + link_dirty(carrier); + } + + return 0; +} + +static int link_new_carrier_maps(Link *link) { + int r; + + r = link_new_bound_by_list(link); + if (r < 0) + return r; + + r = link_handle_bound_by_list(link); + if (r < 0) + return r; + + r = link_new_bound_to_list(link); + if (r < 0) + return r; + + r = link_handle_bound_to_list(link); + if (r < 0) + return r; + + return 0; +} + +static void link_free_bound_to_list(Link *link) { + Link *bound_to; + Iterator i; + + HASHMAP_FOREACH (bound_to, link->bound_to_links, i) { + hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex)); + + if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex))) + link_dirty(bound_to); + } + + return; +} + +static void link_free_bound_by_list(Link *link) { + Link *bound_by; + Iterator i; + + HASHMAP_FOREACH (bound_by, link->bound_by_links, i) { + hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex)); + + if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) { + link_dirty(bound_by); + link_handle_bound_to_list(bound_by); + } + } + + return; +} + +static void link_free_carrier_maps(Link *link) { + bool list_updated = false; + + assert(link); + + if (!hashmap_isempty(link->bound_to_links)) { + link_free_bound_to_list(link); + list_updated = true; + } + + if (!hashmap_isempty(link->bound_by_links)) { + link_free_bound_by_list(link); + list_updated = true; + } + + if (list_updated) + link_dirty(link); + + return; +} + +static int link_append_to_master(Link *link, NetDev *netdev) { + Link *master; + int r; + + assert(link); + assert(netdev); + + r = link_get(link->manager, netdev->ifindex, &master); + if (r < 0) + return r; + + r = set_ensure_allocated(&master->slaves, NULL); + if (r < 0) + return r; + + r = set_put(master->slaves, link); + if (r <= 0) + return r; + + link_ref(link); + return 0; +} + +static void link_drop_from_master(Link *link, NetDev *netdev) { + Link *master; + + assert(link); + + if (!link->manager || !netdev) + return; + + if (link_get(link->manager, netdev->ifindex, &master) < 0) + return; + + link_unref(set_remove(master->slaves, link)); +} + +static void link_detach_from_manager(Link *link) { + if (!link || !link->manager) + return; + + link_unref(set_remove(link->manager->links_requesting_uuid, link)); + link_clean(link); + + /* The following must be called at last. */ + assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link); + link_unref(link); +} + +void link_drop(Link *link) { + if (!link || link->state == LINK_STATE_LINGER) + return; + + link_set_state(link, LINK_STATE_LINGER); + + link_free_carrier_maps(link); + + if (link->network) { + link_drop_from_master(link, link->network->bridge); + link_drop_from_master(link, link->network->bond); + } + + log_link_debug(link, "Link removed"); + + (void) unlink(link->state_file); + link_detach_from_manager(link); +} + +static int link_joined(Link *link) { + int r; + + assert(link); + assert(link->network); + + if (!hashmap_isempty(link->bound_to_links)) { + r = link_handle_bound_to_list(link); + if (r < 0) + return r; + } else if (!(link->flags & IFF_UP)) { + r = link_up(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + + if (link->network->bridge) { + r = link_set_bridge(link); + if (r < 0) + log_link_error_errno(link, r, "Could not set bridge message: %m"); + + r = link_append_to_master(link, link->network->bridge); + if (r < 0) + log_link_error_errno(link, r, "Failed to add to bridge master's slave list: %m"); + } + + if (link->network->bond) { + r = link_set_bond(link); + if (r < 0) + log_link_error_errno(link, r, "Could not set bond message: %m"); + + r = link_append_to_master(link, link->network->bond); + if (r < 0) + log_link_error_errno(link, r, "Failed to add to bond master's slave list: %m"); + } + + if (link->network->use_br_vlan && + (link->network->bridge || streq_ptr("bridge", link->kind))) { + r = link_set_bridge_vlan(link); + if (r < 0) + log_link_error_errno(link, r, "Could not set bridge vlan: %m"); + } + + /* Skip setting up addresses until it gets carrier, + or it would try to set addresses twice, + which is bad for non-idempotent steps. */ + if (!link_has_carrier(link) && !link->network->configure_without_carrier) + return 0; + + link_set_state(link, LINK_STATE_CONFIGURING); + return link_request_set_addresses(link); +} + +static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->network); + assert(link->enslaving > 0); + + link->enslaving--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_error_errno(link, r, "Could not join netdev: %m"); + link_enter_failed(link); + return 1; + } + + log_link_debug(link, "Joined netdev"); + + if (link->enslaving == 0) { + r = link_joined(link); + if (r < 0) + link_enter_failed(link); + } + + return 1; +} + +static int link_enter_join_netdev(Link *link) { + NetDev *netdev; + Iterator i; + int r; + + assert(link); + assert(link->network); + assert(link->state == LINK_STATE_INITIALIZED); + + link_set_state(link, LINK_STATE_CONFIGURING); + + link_dirty(link); + link->enslaving = 0; + + if (link->network->bond) { + if (link->network->bond->state == NETDEV_STATE_READY && + link->network->bond->ifindex == link->master_ifindex) + return link_joined(link); + + log_struct(LOG_DEBUG, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(link->network->bond), + LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname)); + + link->enslaving++; + + r = netdev_join(link->network->bond, link, netdev_join_handler); + if (r < 0) { + log_struct_errno(LOG_WARNING, r, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(link->network->bond), + LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname)); + link_enter_failed(link); + return r; + } + } + + if (link->network->bridge) { + log_struct(LOG_DEBUG, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(link->network->bridge), + LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname)); + + link->enslaving++; + + r = netdev_join(link->network->bridge, link, netdev_join_handler); + if (r < 0) { + log_struct_errno(LOG_WARNING, r, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(link->network->bridge), + LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname)); + link_enter_failed(link); + return r; + } + } + + if (link->network->vrf) { + log_struct(LOG_DEBUG, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(link->network->vrf), + LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->vrf->ifname)); + + link->enslaving++; + + r = netdev_join(link->network->vrf, link, netdev_join_handler); + if (r < 0) { + log_struct_errno(LOG_WARNING, r, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(link->network->vrf), + LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->vrf->ifname)); + link_enter_failed(link); + return r; + } + } + + HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) { + + if (netdev->ifindex > 0) + /* Assume already enslaved. */ + continue; + + if (netdev_get_create_type(netdev) != NETDEV_CREATE_STACKED) + continue; + + log_struct(LOG_DEBUG, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(netdev), + LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname)); + + link->enslaving++; + + r = netdev_join(netdev, link, netdev_join_handler); + if (r < 0) { + log_struct_errno(LOG_WARNING, r, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(netdev), + LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname)); + link_enter_failed(link); + return r; + } + } + + if (link->enslaving == 0) + return link_joined(link); + + return 0; +} + +static int link_set_ipv4_forward(Link *link) { + int r; + + if (!link_ipv4_forward_enabled(link)) + return 0; + + /* We propagate the forwarding flag from one interface to the + * global setting one way. This means: as long as at least one + * interface was configured at any time that had IP forwarding + * enabled the setting will stay on for good. We do this + * primarily to keep IPv4 and IPv6 packet forwarding behaviour + * somewhat in sync (see below). */ + + r = sysctl_write_ip_property(AF_INET, NULL, "ip_forward", "1"); + if (r < 0) + log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m"); + + return 0; +} + +static int link_set_ipv6_forward(Link *link) { + int r; + + if (!link_ipv6_forward_enabled(link)) + return 0; + + /* On Linux, the IPv6 stack does not know a per-interface + * packet forwarding setting: either packet forwarding is on + * for all, or off for all. We hence don't bother with a + * per-interface setting, but simply propagate the interface + * flag, if it is set, to the global flag, one-way. Note that + * while IPv4 would allow a per-interface flag, we expose the + * same behaviour there and also propagate the setting from + * one to all, to keep things simple (see above). */ + + r = sysctl_write_ip_property(AF_INET6, "all", "forwarding", "1"); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m"); + + return 0; +} + +static int link_set_ipv6_privacy_extensions(Link *link) { + IPv6PrivacyExtensions s; + int r; + + s = link_ipv6_privacy_extensions(link); + if (s < 0) + return 0; + + r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) link->network->ipv6_privacy_extensions); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m"); + + return 0; +} + +static int link_set_ipv6_accept_ra(Link *link) { + int r; + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + r = sysctl_write_ip_property(AF_INET6, link->ifname, "accept_ra", "0"); + if (r < 0) + log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m"); + + return 0; +} + +static int link_set_ipv6_dad_transmits(Link *link) { + int r; + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + if (link->network->ipv6_dad_transmits < 0) + return 0; + + r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "dad_transmits", link->network->ipv6_dad_transmits); + if (r < 0) + log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m"); + + return 0; +} + +static int link_set_ipv6_hop_limit(Link *link) { + int r; + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + if (link->network->ipv6_hop_limit < 0) + return 0; + + r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "hop_limit", link->network->ipv6_hop_limit); + if (r < 0) + log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m"); + + return 0; +} + +static int link_set_ipv6_mtu(Link *link) { + int r; + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (link->network->ipv6_mtu == 0) + return 0; + + /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes + * on the interface. Bump up IPv6 MTU bytes to IPV6_MTU_MIN. */ + if (link->network->ipv6_mtu < IPV6_MIN_MTU) { + log_link_notice(link, "Bumping IPv6 MTU to "STRINGIFY(IPV6_MIN_MTU)" byte minimum required"); + link->network->ipv6_mtu = IPV6_MIN_MTU; + } + + r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", link->network->ipv6_mtu); + if (r < 0) { + if (link->mtu < link->network->ipv6_mtu) + log_link_warning(link, "Cannot set IPv6 MTU %"PRIu32" higher than device MTU %"PRIu32, + link->network->ipv6_mtu, link->mtu); + else + log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m"); + } + + link->ipv6_mtu_set = true; + + return 0; +} + +static bool link_is_static_address_configured(Link *link, Address *address) { + Address *net_address; + + assert(link); + assert(address); + + if (!link->network) + return false; + + LIST_FOREACH(addresses, net_address, link->network->static_addresses) + if (address_equal(net_address, address)) + return true; + + return false; +} + +static bool link_is_neighbor_configured(Link *link, Neighbor *neighbor) { + Neighbor *net_neighbor; + + assert(link); + assert(neighbor); + + if (!link->network) + return false; + + LIST_FOREACH(neighbors, net_neighbor, link->network->neighbors) + if (neighbor_equal(net_neighbor, neighbor)) + return true; + + return false; +} + +static bool link_is_static_route_configured(Link *link, Route *route) { + Route *net_route; + + assert(link); + assert(route); + + if (!link->network) + return false; + + LIST_FOREACH(routes, net_route, link->network->static_routes) + if (route_equal(net_route, route)) + return true; + + return false; +} + +static bool link_address_is_dynamic(Link *link, Address *address) { + Route *route; + Iterator i; + + assert(link); + assert(address); + + if (address->cinfo.ifa_prefered != CACHE_INFO_INFINITY_LIFE_TIME) + return true; + + /* Even when the address is leased from a DHCP server, networkd assign the address + * without lifetime when KeepConfiguration=dhcp. So, let's check that we have + * corresponding routes with RTPROT_DHCP. */ + SET_FOREACH(route, link->routes_foreign, i) { + if (route->protocol != RTPROT_DHCP) + continue; + + if (address->family != route->family) + continue; + + if (in_addr_equal(address->family, &address->in_addr, &route->prefsrc)) + return true; + } + + return false; +} + +static int link_drop_foreign_config(Link *link) { + Address *address; + Neighbor *neighbor; + Route *route; + Iterator i; + int r; + + SET_FOREACH(address, link->addresses_foreign, i) { + /* we consider IPv6LL addresses to be managed by the kernel */ + if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) + continue; + + if (link_address_is_dynamic(link, address)) { + if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + } else if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + + if (link_is_static_address_configured(link, address)) { + r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Failed to add address: %m"); + } else { + r = address_remove(address, link, NULL); + if (r < 0) + return r; + } + } + + SET_FOREACH(neighbor, link->neighbors_foreign, i) { + if (link_is_neighbor_configured(link, neighbor)) { + r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL); + if (r < 0) + return r; + } else { + r = neighbor_remove(neighbor, link, NULL); + if (r < 0) + return r; + } + } + + SET_FOREACH(route, link->routes_foreign, i) { + /* do not touch routes managed by the kernel */ + if (route->protocol == RTPROT_KERNEL) + continue; + + /* do not touch multicast route added by kernel */ + /* FIXME: Why the kernel adds this route with protocol RTPROT_BOOT??? We need to investigate that. + * https://tools.ietf.org/html/rfc4862#section-5.4 may explain why. */ + if (route->protocol == RTPROT_BOOT && + route->family == AF_INET6 && + route->dst_prefixlen == 8 && + in_addr_equal(AF_INET6, &route->dst, &(union in_addr_union) { .in6 = {{{ 0xff,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }}} })) + continue; + + if (route->protocol == RTPROT_STATIC && link->network && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + + if (route->protocol == RTPROT_DHCP && link->network && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + + if (link_is_static_route_configured(link, route)) { + r = route_add(link, route, NULL); + if (r < 0) + return r; + } else { + r = route_remove(route, link, NULL); + if (r < 0) + return r; + } + } + + return 0; +} + +static int link_drop_config(Link *link) { + Address *address, *pool_address; + Neighbor *neighbor; + Route *route; + Iterator i; + int r; + + SET_FOREACH(address, link->addresses, i) { + /* we consider IPv6LL addresses to be managed by the kernel */ + if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link)) + continue; + + r = address_remove(address, link, NULL); + if (r < 0) + return r; + + /* If this address came from an address pool, clean up the pool */ + LIST_FOREACH(addresses, pool_address, link->pool_addresses) { + if (address_equal(address, pool_address)) { + LIST_REMOVE(addresses, link->pool_addresses, pool_address); + address_free(pool_address); + break; + } + } + } + + SET_FOREACH(neighbor, link->neighbors, i) { + r = neighbor_remove(neighbor, link, NULL); + if (r < 0) + return r; + } + + SET_FOREACH(route, link->routes, i) { + /* do not touch routes managed by the kernel */ + if (route->protocol == RTPROT_KERNEL) + continue; + + r = route_remove(route, link, NULL); + if (r < 0) + return r; + } + + ndisc_flush(link); + + return 0; +} + +static int link_configure_qdiscs(Link *link) { + QDiscs *qdisc; + Iterator i; + int r; + + link->qdiscs_configured = false; + link->qdisc_messages = 0; + + ORDERED_HASHMAP_FOREACH(qdisc, link->network->qdiscs_by_section, i) { + r = qdisc_configure(link, qdisc); + if (r < 0) + return r; + } + + if (link->qdisc_messages == 0) + link->qdiscs_configured = true; + else + log_link_debug(link, "Configuring QDiscs"); + + return 0; +} + +static int link_configure(Link *link) { + int r; + + assert(link); + assert(link->network); + assert(link->state == LINK_STATE_INITIALIZED); + + r = link_configure_qdiscs(link); + if (r < 0) + return r; + + if (link->iftype == ARPHRD_CAN) + return link_configure_can(link); + + /* Drop foreign config, but ignore loopback or critical devices. + * We do not want to remove loopback address or addresses used for root NFS. */ + if (!(link->flags & IFF_LOOPBACK) && + link->network->keep_configuration != KEEP_CONFIGURATION_YES) { + r = link_drop_foreign_config(link); + if (r < 0) + return r; + } + + /* If IPv6 configured that is static IPv6 address and IPv6LL autoconfiguration is enabled + * for this interface, then enable IPv6 */ + (void) link_update_ipv6_sysctl(link); + + r = link_set_proxy_arp(link); + if (r < 0) + return r; + + r = ipv6_proxy_ndp_addresses_configure(link); + if (r < 0) + return r; + + r = link_set_ipv4_forward(link); + if (r < 0) + return r; + + r = link_set_ipv6_forward(link); + if (r < 0) + return r; + + r = link_set_ipv6_privacy_extensions(link); + if (r < 0) + return r; + + r = link_set_ipv6_accept_ra(link); + if (r < 0) + return r; + + r = link_set_ipv6_dad_transmits(link); + if (r < 0) + return r; + + r = link_set_ipv6_hop_limit(link); + if (r < 0) + return r; + + r = link_set_flags(link); + if (r < 0) + return r; + + if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_FALLBACK_IPV4)) { + r = ipv4ll_configure(link); + if (r < 0) + return r; + } + + if (link_dhcp4_enabled(link)) { + r = dhcp4_set_promote_secondaries(link); + if (r < 0) + return r; + + r = dhcp4_configure(link); + if (r < 0) + return r; + } + + if (link_dhcp4_server_enabled(link)) { + r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex); + if (r < 0) + return r; + + r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0); + if (r < 0) + return r; + } + + if (link_dhcp6_enabled(link) || + link_ipv6_accept_ra_enabled(link)) { + r = dhcp6_configure(link); + if (r < 0) + return r; + } + + if (link_ipv6_accept_ra_enabled(link)) { + r = ndisc_configure(link); + if (r < 0) + return r; + } + + if (link_radv_enabled(link)) { + r = radv_configure(link); + if (r < 0) + return r; + } + + if (link_lldp_rx_enabled(link)) { + r = link_lldp_rx_configure(link); + if (r < 0) + return r; + } + + r = link_configure_mtu(link); + if (r < 0) + return r; + + r = link_configure_addrgen_mode(link); + if (r < 0) + return r; + + return link_configure_after_setting_mtu(link); +} + +static int link_configure_after_setting_mtu(Link *link) { + int r; + + assert(link); + assert(link->network); + assert(link->state == LINK_STATE_INITIALIZED); + + if (link->setting_mtu) + return 0; + + /* The kernel resets ipv6 mtu after changing device mtu; + * we must set this here, after we've set device mtu */ + r = link_set_ipv6_mtu(link); + if (r < 0) + return r; + + if (link_has_carrier(link) || link->network->configure_without_carrier) { + r = link_acquire_conf(link); + if (r < 0) + return r; + } + + return link_enter_join_netdev(link); +} + +static int duid_set_uuid(DUID *duid, sd_id128_t uuid) { + assert(duid); + + if (duid->raw_data_len > 0) + return 0; + + if (duid->type != DUID_TYPE_UUID) + return -EINVAL; + + memcpy(&duid->raw_data, &uuid, sizeof(sd_id128_t)); + duid->raw_data_len = sizeof(sd_id128_t); + + return 1; +} + +int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + Manager *manager = userdata; + const sd_bus_error *e; + const void *a; + size_t sz; + DUID *duid; + Link *link; + int r; + + assert(m); + assert(manager); + + e = sd_bus_message_get_error(m); + if (e) { + log_error_errno(sd_bus_error_get_errno(e), + "Could not get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %s", + e->message); + goto configure; + } + + r = sd_bus_message_read_array(m, 'y', &a, &sz); + if (r < 0) + goto configure; + + if (sz != sizeof(sd_id128_t)) { + log_error("Invalid product UUID. Falling back to use machine-app-specific ID as DUID-UUID."); + goto configure; + } + + memcpy(&manager->product_uuid, a, sz); + while ((duid = set_steal_first(manager->duids_requesting_uuid))) + (void) duid_set_uuid(duid, manager->product_uuid); + + manager->duids_requesting_uuid = set_free(manager->duids_requesting_uuid); + +configure: + while ((link = set_steal_first(manager->links_requesting_uuid))) { + link_unref(link); + + r = link_configure(link); + if (r < 0) + link_enter_failed(link); + } + + manager->links_requesting_uuid = set_free(manager->links_requesting_uuid); + + /* To avoid calling GetProductUUID() bus method so frequently, set the flag below + * even if the method fails. */ + manager->has_product_uuid = true; + + return 1; +} + +static bool link_requires_uuid(Link *link) { + const DUID *duid; + + assert(link); + assert(link->manager); + assert(link->network); + + duid = link_get_duid(link); + if (duid->type != DUID_TYPE_UUID || duid->raw_data_len != 0) + return false; + + if (link_dhcp4_enabled(link) && IN_SET(link->network->dhcp_client_identifier, DHCP_CLIENT_ID_DUID, DHCP_CLIENT_ID_DUID_ONLY)) + return true; + + if (link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link)) + return true; + + return false; +} + +static int link_configure_duid(Link *link) { + Manager *m; + DUID *duid; + int r; + + assert(link); + assert(link->manager); + assert(link->network); + + m = link->manager; + duid = link_get_duid(link); + + if (!link_requires_uuid(link)) + return 1; + + if (m->has_product_uuid) { + (void) duid_set_uuid(duid, m->product_uuid); + return 1; + } + + if (!m->links_requesting_uuid) { + r = manager_request_product_uuid(m, link); + if (r < 0) { + if (r == -ENOMEM) + return r; + + log_link_warning_errno(link, r, + "Failed to get product UUID. Falling back to use machine-app-specific ID as DUID-UUID: %m"); + return 1; + } + } else { + r = set_put(m->links_requesting_uuid, link); + if (r < 0) + return log_oom(); + + r = set_put(m->duids_requesting_uuid, duid); + if (r < 0) + return log_oom(); + + link_ref(link); + } + + return 0; +} + +int link_reconfigure(Link *link, bool force) { + Network *network; + int r; + + if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER)) + return 0; + + r = network_get(link->manager, link->sd_device, link->ifname, + &link->mac, link->wlan_iftype, link->ssid, &link->bssid, &network); + if (r == -ENOENT) { + link_enter_unmanaged(link); + return 0; + } else if (r == 0 && network->unmanaged) { + link_enter_unmanaged(link); + return 0; + } else if (r < 0) + return r; + + if (link->network == network && !force) + return 0; + + log_link_info(link, "Re-configuring with %s", network->filename); + + /* Dropping old .network file */ + r = link_stop_clients(link, false); + if (r < 0) { + link_enter_failed(link); + return r; + } + + if (link_dhcp4_server_enabled(link)) + (void) sd_dhcp_server_stop(link->dhcp_server); + + r = link_drop_config(link); + if (r < 0) + return r; + + if (!IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING, LINK_STATE_INITIALIZED)) { + log_link_debug(link, "State is %s, dropping config", link_state_to_string(link->state)); + r = link_drop_foreign_config(link); + if (r < 0) + return r; + } + + link_free_carrier_maps(link); + link_free_engines(link); + link->network = network_unref(link->network); + + /* Then, apply new .network file */ + r = network_apply(network, link); + if (r < 0) + return r; + + r = link_new_carrier_maps(link); + if (r < 0) + return r; + + link_set_state(link, LINK_STATE_INITIALIZED); + + /* link_configure_duid() returns 0 if it requests product UUID. In that case, + * link_configure() is called later asynchronously. */ + r = link_configure_duid(link); + if (r <= 0) + return r; + + r = link_configure(link); + if (r < 0) + return r; + + return 0; +} + +static int link_initialized_and_synced(Link *link) { + Network *network; + int r; + + assert(link); + assert(link->ifname); + assert(link->manager); + + /* We may get called either from the asynchronous netlink callback, + * or directly for link_add() if running in a container. See link_add(). */ + if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED)) + return 0; + + log_link_debug(link, "Link state is up-to-date"); + link_set_state(link, LINK_STATE_INITIALIZED); + + r = link_new_bound_by_list(link); + if (r < 0) + return r; + + r = link_handle_bound_by_list(link); + if (r < 0) + return r; + + if (!link->network) { + r = wifi_get_info(link); + if (r < 0) + return r; + + r = network_get(link->manager, link->sd_device, link->ifname, + &link->mac, link->wlan_iftype, link->ssid, &link->bssid, &network); + if (r == -ENOENT) { + link_enter_unmanaged(link); + return 0; + } else if (r == 0 && network->unmanaged) { + link_enter_unmanaged(link); + return 0; + } else if (r < 0) + return r; + + if (link->flags & IFF_LOOPBACK) { + if (network->link_local != ADDRESS_FAMILY_NO) + log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link"); + + if (network->dhcp != ADDRESS_FAMILY_NO) + log_link_debug(link, "Ignoring DHCP clients for loopback link"); + + if (network->dhcp_server) + log_link_debug(link, "Ignoring DHCP server for loopback link"); + } + + r = network_apply(network, link); + if (r < 0) + return r; + } + + r = link_new_bound_to_list(link); + if (r < 0) + return r; + + /* link_configure_duid() returns 0 if it requests product UUID. In that case, + * link_configure() is called later asynchronously. */ + r = link_configure_duid(link); + if (r <= 0) + return r; + + r = link_configure(link); + if (r < 0) + return r; + + return 0; +} + +static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + r = link_initialized_and_synced(link); + if (r < 0) + link_enter_failed(link); + return 1; +} + +int link_initialized(Link *link, sd_device *device) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + assert(device); + + if (link->state != LINK_STATE_PENDING) + return 0; + + if (link->sd_device) + return 0; + + log_link_debug(link, "udev initialized link"); + link_set_state(link, LINK_STATE_INITIALIZED); + + link->sd_device = sd_device_ref(device); + + /* udev has initialized the link, but we don't know if we have yet + * processed the NEWLINK messages with the latest state. Do a GETLINK, + * when it returns we know that the pending NEWLINKs have already been + * processed and that we are up-to-date */ + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK, + link->ifindex); + if (r < 0) + return r; + + r = netlink_call_async(link->manager->rtnl, NULL, req, link_initialized_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return r; + + link_ref(link); + + return 0; +} + +static int link_load(Link *link) { + _cleanup_free_ char *network_file = NULL, + *addresses = NULL, + *routes = NULL, + *dhcp4_address = NULL, + *ipv4ll_address = NULL; + union in_addr_union address; + const char *p; + int r; + + assert(link); + + r = parse_env_file(NULL, link->state_file, + "NETWORK_FILE", &network_file, + "ADDRESSES", &addresses, + "ROUTES", &routes, + "DHCP4_ADDRESS", &dhcp4_address, + "IPV4LL_ADDRESS", &ipv4ll_address); + if (r < 0 && r != -ENOENT) + return log_link_error_errno(link, r, "Failed to read %s: %m", link->state_file); + + if (network_file) { + Network *network; + char *suffix; + + /* drop suffix */ + suffix = strrchr(network_file, '.'); + if (!suffix) { + log_link_debug(link, "Failed to get network name from %s", network_file); + goto network_file_fail; + } + *suffix = '\0'; + + r = network_get_by_name(link->manager, basename(network_file), &network); + if (r < 0) { + log_link_debug_errno(link, r, "Failed to get network %s: %m", basename(network_file)); + goto network_file_fail; + } + + r = network_apply(network, link); + if (r < 0) + return log_link_error_errno(link, r, "Failed to apply network %s: %m", basename(network_file)); + } + +network_file_fail: + + if (addresses) { + p = addresses; + + for (;;) { + _cleanup_free_ char *address_str = NULL; + char *prefixlen_str; + int family; + unsigned char prefixlen; + + r = extract_first_word(&p, &address_str, NULL, 0); + if (r < 0) { + log_link_debug_errno(link, r, "Failed to extract next address string: %m"); + continue; + } + if (r == 0) + break; + + prefixlen_str = strchr(address_str, '/'); + if (!prefixlen_str) { + log_link_debug(link, "Failed to parse address and prefix length %s", address_str); + continue; + } + + *prefixlen_str++ = '\0'; + + r = sscanf(prefixlen_str, "%hhu", &prefixlen); + if (r != 1) { + log_link_error(link, "Failed to parse prefixlen %s", prefixlen_str); + continue; + } + + r = in_addr_from_string_auto(address_str, &family, &address); + if (r < 0) { + log_link_debug_errno(link, r, "Failed to parse address %s: %m", address_str); + continue; + } + + r = address_add(link, family, &address, prefixlen, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Failed to add address: %m"); + } + } + + if (routes) { + p = routes; + + for (;;) { + _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; + _cleanup_(route_freep) Route *tmp = NULL; + _cleanup_free_ char *route_str = NULL; + char *prefixlen_str; + Route *route; + + r = extract_first_word(&p, &route_str, NULL, 0); + if (r < 0) { + log_link_debug_errno(link, r, "Failed to extract next route string: %m"); + continue; + } + if (r == 0) + break; + + prefixlen_str = strchr(route_str, '/'); + if (!prefixlen_str) { + log_link_debug(link, "Failed to parse route %s", route_str); + continue; + } + + *prefixlen_str++ = '\0'; + + r = route_new(&tmp); + if (r < 0) + return log_oom(); + + r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%"PRIu32"/"USEC_FMT, &tmp->dst_prefixlen, &tmp->tos, &tmp->priority, &tmp->table, &tmp->lifetime); + if (r != 5) { + log_link_debug(link, + "Failed to parse destination prefix length, tos, priority, table or expiration %s", + prefixlen_str); + continue; + } + + r = in_addr_from_string_auto(route_str, &tmp->family, &tmp->dst); + if (r < 0) { + log_link_debug_errno(link, r, "Failed to parse route destination %s: %m", route_str); + continue; + } + + r = route_add(link, tmp, &route); + if (r < 0) + return log_link_error_errno(link, r, "Failed to add route: %m"); + + if (route->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) { + r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), route->lifetime, + 0, route_expire_handler, route); + if (r < 0) + log_link_warning_errno(link, r, "Could not arm route expiration handler: %m"); + } + + sd_event_source_unref(route->expire); + route->expire = TAKE_PTR(expire); + } + } + + if (dhcp4_address) { + r = in_addr_from_string(AF_INET, dhcp4_address, &address); + if (r < 0) { + log_link_debug_errno(link, r, "Failed to parse DHCPv4 address %s: %m", dhcp4_address); + goto dhcp4_address_fail; + } + + r = sd_dhcp_client_new(&link->dhcp_client, link->network ? link->network->dhcp_anonymize : 0); + if (r < 0) + return log_link_error_errno(link, r, "Failed to create DHCPv4 client: %m"); + + r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in); + if (r < 0) + return log_link_error_errno(link, r, "Failed to set initial DHCPv4 address %s: %m", dhcp4_address); + } + +dhcp4_address_fail: + + if (ipv4ll_address) { + r = in_addr_from_string(AF_INET, ipv4ll_address, &address); + if (r < 0) { + log_link_debug_errno(link, r, "Failed to parse IPv4LL address %s: %m", ipv4ll_address); + goto ipv4ll_address_fail; + } + + r = sd_ipv4ll_new(&link->ipv4ll); + if (r < 0) + return log_link_error_errno(link, r, "Failed to create IPv4LL client: %m"); + + r = sd_ipv4ll_set_address(link->ipv4ll, &address.in); + if (r < 0) + return log_link_error_errno(link, r, "Failed to set initial IPv4LL address %s: %m", ipv4ll_address); + } + +ipv4ll_address_fail: + + return 0; +} + +int link_add(Manager *m, sd_netlink_message *message, Link **ret) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + char ifindex_str[2 + DECIMAL_STR_MAX(int)]; + Link *link; + int r; + + assert(m); + assert(m->rtnl); + assert(message); + assert(ret); + + r = link_new(m, message, ret); + if (r < 0) + return r; + + link = *ret; + + log_link_debug(link, "Link %d added", link->ifindex); + + r = link_load(link); + if (r < 0) + return r; + + if (path_is_read_only_fs("/sys") <= 0) { + /* udev should be around */ + sprintf(ifindex_str, "n%d", link->ifindex); + r = sd_device_new_from_device_id(&device, ifindex_str); + if (r < 0) { + log_link_warning_errno(link, r, "Could not find device, waiting for device initialization: %m"); + return 0; + } + + r = sd_device_get_is_initialized(device); + if (r < 0) { + log_link_warning_errno(link, r, "Could not determine whether the device is initialized: %m"); + goto failed; + } + if (r == 0) { + /* not yet ready */ + log_link_debug(link, "link pending udev initialization..."); + return 0; + } + + r = device_is_renaming(device); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to determine the device is being renamed: %m"); + goto failed; + } + if (r > 0) { + log_link_debug(link, "Interface is being renamed, pending initialization."); + return 0; + } + + r = link_initialized(link, device); + if (r < 0) + goto failed; + } else { + r = link_initialized_and_synced(link); + if (r < 0) + goto failed; + } + + return 0; +failed: + link_enter_failed(link); + return r; +} + +int link_ipv6ll_gained(Link *link, const struct in6_addr *address) { + int r; + + assert(link); + + log_link_info(link, "Gained IPv6LL"); + + link->ipv6ll_address = *address; + link_check_ready(link); + + if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) { + r = link_acquire_ipv6_conf(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + + return 0; +} + +static int link_carrier_gained(Link *link) { + int r; + + assert(link); + + r = wifi_get_info(link); + if (r < 0) + return r; + if (r > 0) { + r = link_reconfigure(link, false); + if (r < 0) + return r; + } + + if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) { + r = link_acquire_conf(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + + link_set_state(link, LINK_STATE_CONFIGURING); + r = link_request_set_addresses(link); + if (r < 0) + return r; + } + + r = link_handle_bound_by_list(link); + if (r < 0) + return r; + + return 0; +} + +static int link_carrier_lost(Link *link) { + int r; + + assert(link); + + if (link->network && link->network->ignore_carrier_loss) + return 0; + + /* Some devices reset itself while setting the MTU. This causes the DHCP client fall into a loop. + * setting_mtu keep track whether the device got reset because of setting MTU and does not drop the + * configuration and stop the clients as well. */ + if (link->setting_mtu) + return 0; + + r = link_stop_clients(link, false); + if (r < 0) { + link_enter_failed(link); + return r; + } + + if (link_dhcp4_server_enabled(link)) + (void) sd_dhcp_server_stop(link->dhcp_server); + + r = link_drop_config(link); + if (r < 0) + return r; + + if (!IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING, LINK_STATE_INITIALIZED)) { + log_link_debug(link, "State is %s, dropping config", link_state_to_string(link->state)); + r = link_drop_foreign_config(link); + if (r < 0) + return r; + } + + r = link_handle_bound_by_list(link); + if (r < 0) + return r; + + return 0; +} + +int link_carrier_reset(Link *link) { + int r; + + assert(link); + + if (link_has_carrier(link)) { + r = link_carrier_lost(link); + if (r < 0) + return r; + + r = link_carrier_gained(link); + if (r < 0) + return r; + + log_link_info(link, "Reset carrier"); + } + + return 0; +} + +/* This is called every time an interface admin state changes to up; + * specifically, when IFF_UP flag changes from unset to set */ +static int link_admin_state_up(Link *link) { + int r; + + /* We set the ipv6 mtu after the device mtu, but the kernel resets + * ipv6 mtu on NETDEV_UP, so we need to reset it. The check for + * ipv6_mtu_set prevents this from trying to set it too early before + * the link->network has been setup; we only need to reset it + * here if we've already set it during normal initialization. */ + if (link->ipv6_mtu_set) { + r = link_set_ipv6_mtu(link); + if (r < 0) + return r; + } + + return 0; +} + +int link_update(Link *link, sd_netlink_message *m) { + struct ether_addr mac; + const char *ifname; + uint32_t mtu; + bool had_carrier, carrier_gained, carrier_lost, link_was_admin_up; + int old_master, r; + + assert(link); + assert(link->ifname); + assert(m); + + if (link->state == LINK_STATE_LINGER) { + log_link_info(link, "Link re-added"); + link_set_state(link, LINK_STATE_CONFIGURING); + + r = link_new_carrier_maps(link); + if (r < 0) + return r; + } + + r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname); + if (r >= 0 && !streq(ifname, link->ifname)) { + Manager *manager = link->manager; + + log_link_info(link, "Interface name change detected, %s has been renamed to %s.", link->ifname, ifname); + + link_drop(link); + r = link_add(manager, m, &link); + if (r < 0) + return r; + } + + r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu); + if (r >= 0 && mtu > 0) { + link->mtu = mtu; + if (link->original_mtu == 0) { + link->original_mtu = mtu; + log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu); + } + + if (link->dhcp_client) { + r = sd_dhcp_client_set_mtu(link->dhcp_client, + link->mtu); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m"); + } + + if (link->radv) { + r = sd_radv_set_mtu(link->radv, link->mtu); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set MTU for Router Advertisement: %m"); + } + } + + /* The kernel may broadcast NEWLINK messages without the MAC address + set, simply ignore them. */ + r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac); + if (r >= 0) { + if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, + ETH_ALEN)) { + + memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, + ETH_ALEN); + + log_link_debug(link, "MAC address: " + "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", + mac.ether_addr_octet[0], + mac.ether_addr_octet[1], + mac.ether_addr_octet[2], + mac.ether_addr_octet[3], + mac.ether_addr_octet[4], + mac.ether_addr_octet[5]); + + if (link->ipv4ll) { + r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m"); + } + + if (link->dhcp_client) { + r = sd_dhcp_client_set_mac(link->dhcp_client, + (const uint8_t *) &link->mac, + sizeof (link->mac), + ARPHRD_ETHER); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); + + r = dhcp4_set_client_identifier(link); + if (r < 0) + return r; + } + + if (link->dhcp6_client) { + const DUID* duid = link_get_duid(link); + + r = sd_dhcp6_client_set_mac(link->dhcp6_client, + (const uint8_t *) &link->mac, + sizeof (link->mac), + ARPHRD_ETHER); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m"); + + if (link->network->iaid_set) { + r = sd_dhcp6_client_set_iaid(link->dhcp6_client, + link->network->iaid); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m"); + } + + r = sd_dhcp6_client_set_duid(link->dhcp6_client, + duid->type, + duid->raw_data_len > 0 ? duid->raw_data : NULL, + duid->raw_data_len); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m"); + } + + if (link->radv) { + r = sd_radv_set_mac(link->radv, &link->mac); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC for Router Advertisement: %m"); + } + + if (link->ndisc) { + r = sd_ndisc_set_mac(link->ndisc, &link->mac); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC for ndisc: %m"); + } + } + } + + old_master = link->master_ifindex; + (void) sd_netlink_message_read_u32(m, IFLA_MASTER, (uint32_t *) &link->master_ifindex); + + link_was_admin_up = link->flags & IFF_UP; + had_carrier = link_has_carrier(link); + + r = link_update_flags(link, m, old_master != link->master_ifindex); + if (r < 0) + return r; + + if (!link_was_admin_up && (link->flags & IFF_UP)) { + log_link_info(link, "Link UP"); + + r = link_admin_state_up(link); + if (r < 0) + return r; + } else if (link_was_admin_up && !(link->flags & IFF_UP)) + log_link_info(link, "Link DOWN"); + + r = link_update_lldp(link); + if (r < 0) + return r; + + carrier_gained = !had_carrier && link_has_carrier(link); + carrier_lost = had_carrier && !link_has_carrier(link); + + if (carrier_gained) { + log_link_info(link, "Gained carrier"); + + r = link_carrier_gained(link); + if (r < 0) + return r; + } else if (carrier_lost) { + log_link_info(link, "Lost carrier"); + + r = link_carrier_lost(link); + if (r < 0) + return r; + } + + return 0; +} + +static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) { + bool space = false; + Iterator i; + Link *link; + + assert(f); + assert(prefix); + + if (hashmap_isempty(h)) + return; + + fputs(prefix, f); + HASHMAP_FOREACH(link, h, i) { + if (space) + fputc(' ', f); + + fprintf(f, "%i", link->ifindex); + space = true; + } + + fputc('\n', f); +} + +static void link_save_dns(FILE *f, struct in_addr_data *dns, unsigned n_dns, bool *space) { + unsigned j; + int r; + + for (j = 0; j < n_dns; j++) { + _cleanup_free_ char *b = NULL; + + r = in_addr_to_string(dns[j].family, &dns[j].address, &b); + if (r < 0) { + log_debug_errno(r, "Failed to format address, ignoring: %m"); + continue; + } + + if (*space) + fputc(' ', f); + fputs(b, f); + *space = true; + } +} + +int link_save(Link *link) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *admin_state, *oper_state, *carrier_state, *address_state; + Address *a; + Route *route; + Iterator i; + int r; + + assert(link); + assert(link->state_file); + assert(link->lease_file); + assert(link->manager); + + if (link->state == LINK_STATE_LINGER) { + (void) unlink(link->state_file); + return 0; + } + + link_lldp_save(link); + + admin_state = link_state_to_string(link->state); + assert(admin_state); + + oper_state = link_operstate_to_string(link->operstate); + assert(oper_state); + + carrier_state = link_carrier_state_to_string(link->carrier_state); + assert(carrier_state); + + address_state = link_address_state_to_string(link->address_state); + assert(address_state); + + r = fopen_temporary(link->state_file, &f, &temp_path); + if (r < 0) + goto fail; + + (void) fchmod(fileno(f), 0644); + + fprintf(f, + "# This is private data. Do not parse.\n" + "ADMIN_STATE=%s\n" + "OPER_STATE=%s\n" + "CARRIER_STATE=%s\n" + "ADDRESS_STATE=%s\n", + admin_state, oper_state, carrier_state, address_state); + + if (link->network) { + char **dhcp6_domains = NULL, **dhcp_domains = NULL; + const char *dhcp_domainname = NULL, *p; + sd_dhcp6_lease *dhcp6_lease = NULL; + bool space; + + fprintf(f, "REQUIRED_FOR_ONLINE=%s\n", + yes_no(link->network->required_for_online)); + + fprintf(f, "REQUIRED_OPER_STATE_FOR_ONLINE=%s\n", + strempty(link_operstate_to_string(link->network->required_operstate_for_online))); + + if (link->dhcp6_client) { + r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease); + if (r < 0 && r != -ENOMSG) + log_link_debug(link, "No DHCPv6 lease"); + } + + fprintf(f, "NETWORK_FILE=%s\n", link->network->filename); + + fputs("DNS=", f); + space = false; + + if (link->n_dns != (unsigned) -1) + link_save_dns(f, link->dns, link->n_dns, &space); + else + link_save_dns(f, link->network->dns, link->network->n_dns, &space); + + if (link->network->dhcp_use_dns && + link->dhcp_lease) { + const struct in_addr *addresses; + + r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); + if (r > 0) + if (serialize_in_addrs(f, addresses, r, space, in4_addr_is_non_local) > 0) + space = true; + } + + if (link->network->dhcp6_use_dns && dhcp6_lease) { + struct in6_addr *in6_addrs; + + r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs); + if (r > 0) { + if (space) + fputc(' ', f); + serialize_in6_addrs(f, in6_addrs, r); + space = true; + } + } + + /* Make sure to flush out old entries before we use the NDISC data */ + ndisc_vacuum(link); + + if (link->network->ipv6_accept_ra_use_dns && link->ndisc_rdnss) { + NDiscRDNSS *dd; + + SET_FOREACH(dd, link->ndisc_rdnss, i) { + if (space) + fputc(' ', f); + + serialize_in6_addrs(f, &dd->address, 1); + space = true; + } + } + + fputc('\n', f); + + fputs("NTP=", f); + space = false; + fputstrv(f, link->ntp ?: link->network->ntp, NULL, &space); + + if (link->network->dhcp_use_ntp && + link->dhcp_lease) { + const struct in_addr *addresses; + + r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); + if (r > 0) + if (serialize_in_addrs(f, addresses, r, space, in4_addr_is_non_local) > 0) + space = true; + } + + fputc('\n', f); + + fputs("SIP=", f); + space = false; + fputstrv(f, link->network->sip, NULL, &space); + + if (link->network->dhcp_use_sip && + link->dhcp_lease) { + const struct in_addr *addresses; + + r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses); + if (r > 0) + if (serialize_in_addrs(f, addresses, r, space, in4_addr_is_non_local) > 0) + space = true; + } + + if (link->network->dhcp6_use_ntp && dhcp6_lease) { + struct in6_addr *in6_addrs; + char **hosts; + + r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease, + &in6_addrs); + if (r > 0) { + if (space) + fputc(' ', f); + serialize_in6_addrs(f, in6_addrs, r); + space = true; + } + + r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts); + if (r > 0) + fputstrv(f, hosts, NULL, &space); + } + + fputc('\n', f); + + if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { + if (link->dhcp_lease) { + (void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname); + (void) sd_dhcp_lease_get_search_domains(link->dhcp_lease, &dhcp_domains); + } + if (dhcp6_lease) + (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains); + } + + fputs("DOMAINS=", f); + space = false; + ORDERED_SET_FOREACH(p, link->search_domains ?: link->network->search_domains, i) + fputs_with_space(f, p, NULL, &space); + + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) { + if (dhcp_domainname) + fputs_with_space(f, dhcp_domainname, NULL, &space); + if (dhcp_domains) + fputstrv(f, dhcp_domains, NULL, &space); + if (dhcp6_domains) + fputstrv(f, dhcp6_domains, NULL, &space); + } + + if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_YES) { + NDiscDNSSL *dd; + + SET_FOREACH(dd, link->ndisc_dnssl, i) + fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space); + } + + fputc('\n', f); + + fputs("ROUTE_DOMAINS=", f); + space = false; + ORDERED_SET_FOREACH(p, link->route_domains ?: link->network->route_domains, i) + fputs_with_space(f, p, NULL, &space); + + if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) { + if (dhcp_domainname) + fputs_with_space(f, dhcp_domainname, NULL, &space); + if (dhcp_domains) + fputstrv(f, dhcp_domains, NULL, &space); + if (dhcp6_domains) + fputstrv(f, dhcp6_domains, NULL, &space); + } + + if (link->network->ipv6_accept_ra_use_domains == DHCP_USE_DOMAINS_ROUTE) { + NDiscDNSSL *dd; + + SET_FOREACH(dd, link->ndisc_dnssl, i) + fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space); + } + + fputc('\n', f); + + fprintf(f, "LLMNR=%s\n", + resolve_support_to_string(link->llmnr >= 0 ? link->llmnr : link->network->llmnr)); + fprintf(f, "MDNS=%s\n", + resolve_support_to_string(link->mdns >= 0 ? link->mdns : link->network->mdns)); + if (link->dns_default_route >= 0) + fprintf(f, "DNS_DEFAULT_ROUTE=%s\n", yes_no(link->dns_default_route)); + else if (link->network->dns_default_route >= 0) + fprintf(f, "DNS_DEFAULT_ROUTE=%s\n", yes_no(link->network->dns_default_route)); + + if (link->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID) + fprintf(f, "DNS_OVER_TLS=%s\n", + dns_over_tls_mode_to_string(link->dns_over_tls_mode)); + else if (link->network->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID) + fprintf(f, "DNS_OVER_TLS=%s\n", + dns_over_tls_mode_to_string(link->network->dns_over_tls_mode)); + + if (link->dnssec_mode != _DNSSEC_MODE_INVALID) + fprintf(f, "DNSSEC=%s\n", + dnssec_mode_to_string(link->dnssec_mode)); + else if (link->network->dnssec_mode != _DNSSEC_MODE_INVALID) + fprintf(f, "DNSSEC=%s\n", + dnssec_mode_to_string(link->network->dnssec_mode)); + + if (!set_isempty(link->dnssec_negative_trust_anchors)) { + const char *n; + + fputs("DNSSEC_NTA=", f); + space = false; + SET_FOREACH(n, link->dnssec_negative_trust_anchors, i) + fputs_with_space(f, n, NULL, &space); + fputc('\n', f); + } else if (!set_isempty(link->network->dnssec_negative_trust_anchors)) { + const char *n; + + fputs("DNSSEC_NTA=", f); + space = false; + SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) + fputs_with_space(f, n, NULL, &space); + fputc('\n', f); + } + + fputs("ADDRESSES=", f); + space = false; + SET_FOREACH(a, link->addresses, i) { + _cleanup_free_ char *address_str = NULL; + + r = in_addr_to_string(a->family, &a->in_addr, &address_str); + if (r < 0) + goto fail; + + fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen); + space = true; + } + fputc('\n', f); + + fputs("ROUTES=", f); + space = false; + SET_FOREACH(route, link->routes, i) { + _cleanup_free_ char *route_str = NULL; + + r = in_addr_to_string(route->family, &route->dst, &route_str); + if (r < 0) + goto fail; + + fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%"PRIu32"/"USEC_FMT, + space ? " " : "", route_str, + route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime); + space = true; + } + + fputc('\n', f); + } + + print_link_hashmap(f, "CARRIER_BOUND_TO=", link->bound_to_links); + print_link_hashmap(f, "CARRIER_BOUND_BY=", link->bound_by_links); + + if (link->dhcp_lease) { + struct in_addr address; + const char *tz = NULL; + + assert(link->network); + + r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz); + if (r >= 0) + fprintf(f, "TIMEZONE=%s\n", tz); + + r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); + if (r >= 0) { + fputs("DHCP4_ADDRESS=", f); + serialize_in_addrs(f, &address, 1, false, NULL); + fputc('\n', f); + } + + r = dhcp_lease_save(link->dhcp_lease, link->lease_file); + if (r < 0) + goto fail; + + fprintf(f, + "DHCP_LEASE=%s\n", + link->lease_file); + } else + (void) unlink(link->lease_file); + + if (link->ipv4ll) { + struct in_addr address; + + r = sd_ipv4ll_get_address(link->ipv4ll, &address); + if (r >= 0) { + fputs("IPV4LL_ADDRESS=", f); + serialize_in_addrs(f, &address, 1, false, NULL); + fputc('\n', f); + } + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, link->state_file) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + (void) unlink(link->state_file); + if (temp_path) + (void) unlink(temp_path); + + return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file); +} + +/* The serialized state in /run is no longer up-to-date. */ +void link_dirty(Link *link) { + int r; + + assert(link); + + /* mark manager dirty as link is dirty */ + manager_dirty(link->manager); + + r = set_ensure_allocated(&link->manager->dirty_links, NULL); + if (r < 0) + /* allocation errors are ignored */ + return; + + r = set_put(link->manager->dirty_links, link); + if (r <= 0) + /* don't take another ref if the link was already dirty */ + return; + + link_ref(link); +} + +/* The serialized state in /run is up-to-date */ +void link_clean(Link *link) { + assert(link); + assert(link->manager); + + link_unref(set_remove(link->manager->dirty_links, link)); +} + +static const char* const link_state_table[_LINK_STATE_MAX] = { + [LINK_STATE_PENDING] = "pending", + [LINK_STATE_INITIALIZED] = "initialized", + [LINK_STATE_CONFIGURING] = "configuring", + [LINK_STATE_CONFIGURED] = "configured", + [LINK_STATE_UNMANAGED] = "unmanaged", + [LINK_STATE_FAILED] = "failed", + [LINK_STATE_LINGER] = "linger", +}; + +DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h new file mode 100644 index 00000000..e0fa70c2 --- /dev/null +++ b/src/network/networkd-link.h @@ -0,0 +1,221 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-bus.h" +#include "sd-device.h" +#include "sd-dhcp-client.h" +#include "sd-dhcp-server.h" +#include "sd-dhcp6-client.h" +#include "sd-ipv4ll.h" +#include "sd-lldp.h" +#include "sd-ndisc.h" +#include "sd-radv.h" +#include "sd-netlink.h" + +#include "list.h" +#include "log-link.h" +#include "network-util.h" +#include "networkd-util.h" +#include "ordered-set.h" +#include "resolve-util.h" +#include "set.h" + +typedef enum LinkState { + LINK_STATE_PENDING, /* udev has not initialized the link */ + LINK_STATE_INITIALIZED, /* udev has initialized the link */ + LINK_STATE_CONFIGURING, /* configuring addresses, routes, etc. */ + LINK_STATE_CONFIGURED, /* everything is configured */ + LINK_STATE_UNMANAGED, /* Unmanaged=yes is set */ + LINK_STATE_FAILED, /* at least one configuration process failed */ + LINK_STATE_LINGER, /* RTM_DELLINK for the link has been received */ + _LINK_STATE_MAX, + _LINK_STATE_INVALID = -1 +} LinkState; + +typedef struct Manager Manager; +typedef struct Network Network; +typedef struct Address Address; +typedef struct DUID DUID; + +typedef struct Link { + Manager *manager; + + unsigned n_ref; + + int ifindex; + int master_ifindex; + char *ifname; + char *kind; + unsigned short iftype; + char *state_file; + struct ether_addr mac; + struct in6_addr ipv6ll_address; + uint32_t mtu; + sd_device *sd_device; + + /* wlan */ + enum nl80211_iftype wlan_iftype; + char *ssid; + struct ether_addr bssid; + + unsigned flags; + uint8_t kernel_operstate; + + Network *network; + + LinkState state; + LinkOperationalState operstate; + LinkCarrierState carrier_state; + LinkAddressState address_state; + + unsigned address_messages; + unsigned address_label_messages; + unsigned neighbor_messages; + unsigned route_messages; + unsigned nexthop_messages; + unsigned routing_policy_rule_messages; + unsigned routing_policy_rule_remove_messages; + unsigned qdisc_messages; + unsigned enslaving; + + Set *addresses; + Set *addresses_foreign; + Set *neighbors; + Set *neighbors_foreign; + Set *routes; + Set *routes_foreign; + Set *nexthops; + Set *nexthops_foreign; + + sd_dhcp_client *dhcp_client; + sd_dhcp_lease *dhcp_lease, *dhcp_lease_old; + Set *dhcp_routes; + char *lease_file; + uint32_t original_mtu; + unsigned dhcp4_messages; + bool dhcp4_route_failed:1; + bool dhcp4_route_retrying:1; + bool dhcp4_configured:1; + bool dhcp6_configured:1; + + unsigned ndisc_messages; + bool ndisc_configured; + + sd_ipv4ll *ipv4ll; + bool ipv4ll_address:1; + + bool addresses_configured:1; + bool addresses_ready:1; + bool neighbors_configured:1; + bool static_routes_configured:1; + bool static_routes_ready:1; + bool static_nexthops_configured:1; + bool routing_policy_rules_configured:1; + bool qdiscs_configured:1; + bool setting_mtu:1; + bool ipv6_mtu_set:1; + + LIST_HEAD(Address, pool_addresses); + + sd_dhcp_server *dhcp_server; + + sd_ndisc *ndisc; + Set *ndisc_rdnss; + Set *ndisc_dnssl; + + sd_radv *radv; + + sd_dhcp6_client *dhcp6_client; + + /* This is about LLDP reception */ + sd_lldp *lldp; + char *lldp_file; + + /* This is about LLDP transmission */ + unsigned lldp_tx_fast; /* The LLDP txFast counter (See 802.1ab-2009, section 9.2.5.18) */ + sd_event_source *lldp_emit_event_source; + + Hashmap *bound_by_links; + Hashmap *bound_to_links; + Set *slaves; + + /* For speed meter */ + struct rtnl_link_stats64 stats_old, stats_new; + bool stats_updated; + + /* All kinds of DNS configuration */ + struct in_addr_data *dns; + unsigned n_dns; + OrderedSet *search_domains, *route_domains; + + int dns_default_route; + ResolveSupport llmnr; + ResolveSupport mdns; + DnssecMode dnssec_mode; + DnsOverTlsMode dns_over_tls_mode; + Set *dnssec_negative_trust_anchors; + + char **ntp; +} Link; + +typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*); + +DUID *link_get_duid(Link *link); +int get_product_uuid_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error); + +void link_ntp_settings_clear(Link *link); +void link_dns_settings_clear(Link *link); +Link *link_unref(Link *link); +Link *link_ref(Link *link); +DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); +DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_destroy_callback, Link, link_unref); + +int link_get(Manager *m, int ifindex, Link **ret); +int link_add(Manager *manager, sd_netlink_message *message, Link **ret); +void link_drop(Link *link); + +int link_down(Link *link, link_netlink_message_handler_t callback); + +void link_enter_failed(Link *link); +int link_initialized(Link *link, sd_device *device); + +void link_set_state(Link *link, LinkState state); +void link_check_ready(Link *link); + +void link_update_operstate(Link *link, bool also_update_bond_master); +int link_update(Link *link, sd_netlink_message *message); + +void link_dirty(Link *link); +void link_clean(Link *link); +int link_save(Link *link); + +int link_carrier_reset(Link *link); +bool link_has_carrier(Link *link); + +int link_ipv6ll_gained(Link *link, const struct in6_addr *address); + +int link_set_mtu(Link *link, uint32_t mtu); + +bool link_ipv4ll_enabled(Link *link, AddressFamily mask); + +int link_stop_clients(Link *link, bool may_keep_dhcp); + +const char* link_state_to_string(LinkState s) _const_; +LinkState link_state_from_string(const char *s) _pure_; + +uint32_t link_get_vrf_table(Link *link); +uint32_t link_get_dhcp_route_table(Link *link); +uint32_t link_get_ipv6_accept_ra_route_table(Link *link); +int link_request_set_routes(Link *link); +int link_request_set_nexthop(Link *link); + +int link_reconfigure(Link *link, bool force); + +#define ADDRESS_FMT_VAL(address) \ + be32toh((address).s_addr) >> 24, \ + (be32toh((address).s_addr) >> 16) & 0xFFu, \ + (be32toh((address).s_addr) >> 8) & 0xFFu, \ + be32toh((address).s_addr) & 0xFFu diff --git a/src/network/networkd-lldp-rx.c b/src/network/networkd-lldp-rx.c new file mode 100644 index 00000000..0631cc96 --- /dev/null +++ b/src/network/networkd-lldp-rx.c @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "fd-util.h" +#include "fileio.h" +#include "networkd-link.h" +#include "networkd-lldp-rx.h" +#include "networkd-lldp-tx.h" +#include "networkd-network.h" +#include "string-table.h" +#include "string-util.h" +#include "tmpfile-util.h" + +DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting."); + +static const char* const lldp_mode_table[_LLDP_MODE_MAX] = { + [LLDP_MODE_NO] = "no", + [LLDP_MODE_YES] = "yes", + [LLDP_MODE_ROUTERS_ONLY] = "routers-only", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES); + +bool link_lldp_rx_enabled(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (link->iftype != ARPHRD_ETHER) + return false; + + if (!link->network) + return false; + + /* LLDP should be handled on bridge slaves as those have a direct + * connection to their peers not on the bridge master. Linux doesn't + * even (by default) forward lldp packets to the bridge master.*/ + if (streq_ptr("bridge", link->kind)) + return false; + + return link->network->lldp_mode != LLDP_MODE_NO; +} + +static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) { + Link *link = userdata; + int r; + + assert(link); + + (void) link_lldp_save(link); + + if (link_lldp_emit_enabled(link) && event == SD_LLDP_EVENT_ADDED) { + /* If we received information about a new neighbor, restart the LLDP "fast" logic */ + + log_link_debug(link, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission."); + + r = link_lldp_emit_start(link); + if (r < 0) + log_link_warning_errno(link, r, "Failed to restart LLDP transmission: %m"); + } +} + +int link_lldp_rx_configure(Link *link) { + int r; + + r = sd_lldp_new(&link->lldp); + if (r < 0) + return r; + + r = sd_lldp_set_ifindex(link->lldp, link->ifindex); + if (r < 0) + return r; + + r = sd_lldp_match_capabilities(link->lldp, + link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ? + SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS : + SD_LLDP_SYSTEM_CAPABILITIES_ALL); + if (r < 0) + return r; + + r = sd_lldp_set_filter_address(link->lldp, &link->mac); + if (r < 0) + return r; + + r = sd_lldp_attach_event(link->lldp, NULL, 0); + if (r < 0) + return r; + + r = sd_lldp_set_callback(link->lldp, lldp_handler, link); + if (r < 0) + return r; + + r = link_update_lldp(link); + if (r < 0) + return r; + + return 0; +} + +int link_update_lldp(Link *link) { + int r; + + assert(link); + + if (!link->lldp) + return 0; + + if (link->flags & IFF_UP) { + r = sd_lldp_start(link->lldp); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to start LLDP: %m"); + if (r > 0) + log_link_debug(link, "Started LLDP."); + } else { + r = sd_lldp_stop(link->lldp); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to stop LLDP: %m"); + if (r > 0) + log_link_debug(link, "Stopped LLDP."); + } + + return r; +} + +int link_lldp_save(Link *link) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + sd_lldp_neighbor **l = NULL; + int n = 0, r, i; + + assert(link); + assert(link->lldp_file); + + if (!link->lldp) { + (void) unlink(link->lldp_file); + return 0; + } + + r = sd_lldp_get_neighbors(link->lldp, &l); + if (r < 0) + goto finish; + if (r == 0) { + (void) unlink(link->lldp_file); + goto finish; + } + + n = r; + + r = fopen_temporary(link->lldp_file, &f, &temp_path); + if (r < 0) + goto finish; + + fchmod(fileno(f), 0644); + + for (i = 0; i < n; i++) { + const void *p; + le64_t u; + size_t sz; + + r = sd_lldp_neighbor_get_raw(l[i], &p, &sz); + if (r < 0) + goto finish; + + u = htole64(sz); + (void) fwrite(&u, 1, sizeof(u), f); + (void) fwrite(p, 1, sz, f); + } + + r = fflush_and_check(f); + if (r < 0) + goto finish; + + if (rename(temp_path, link->lldp_file) < 0) { + r = -errno; + goto finish; + } + +finish: + if (r < 0) { + (void) unlink(link->lldp_file); + if (temp_path) + (void) unlink(temp_path); + + log_link_error_errno(link, r, "Failed to save LLDP data to %s: %m", link->lldp_file); + } + + if (l) { + for (i = 0; i < n; i++) + sd_lldp_neighbor_unref(l[i]); + free(l); + } + + return r; +} diff --git a/src/network/networkd-lldp-rx.h b/src/network/networkd-lldp-rx.h new file mode 100644 index 00000000..12f512f6 --- /dev/null +++ b/src/network/networkd-lldp-rx.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "conf-parser.h" + +typedef struct Link Link; + +typedef enum LLDPMode { + LLDP_MODE_NO = 0, + LLDP_MODE_YES = 1, + LLDP_MODE_ROUTERS_ONLY = 2, + _LLDP_MODE_MAX, + _LLDP_MODE_INVALID = -1, +} LLDPMode; + +bool link_lldp_rx_enabled(Link *link); +int link_lldp_rx_configure(Link *link); +int link_update_lldp(Link *link); +int link_lldp_save(Link *link); + +const char* lldp_mode_to_string(LLDPMode m) _const_; +LLDPMode lldp_mode_from_string(const char *s) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mode); diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c new file mode 100644 index 00000000..51db60e1 --- /dev/null +++ b/src/network/networkd-lldp-tx.c @@ -0,0 +1,416 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "env-file.h" +#include "fd-util.h" +#include "hostname-util.h" +#include "missing_network.h" +#include "networkd-link.h" +#include "networkd-lldp-tx.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "random-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "unaligned.h" + +/* The LLDP spec calls this "txFastInit", see 9.2.5.19 */ +#define LLDP_TX_FAST_INIT 4U + +/* The LLDP spec calls this "msgTxHold", see 9.2.5.6 */ +#define LLDP_TX_HOLD 4U + +/* The jitter range to add, see 9.2.2. */ +#define LLDP_JITTER_USEC (400U * USEC_PER_MSEC) + +/* The LLDP spec calls this msgTxInterval, but we subtract half the jitter off it. */ +#define LLDP_TX_INTERVAL_USEC (30U * USEC_PER_SEC - LLDP_JITTER_USEC / 2) + +/* The LLDP spec calls this msgFastTx, but we subtract half the jitter off it. */ +#define LLDP_FAST_TX_USEC (1U * USEC_PER_SEC - LLDP_JITTER_USEC / 2) + +static const struct ether_addr lldp_multicast_addr[_LLDP_EMIT_MAX] = { + [LLDP_EMIT_NEAREST_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }}, + [LLDP_EMIT_NON_TPMR_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }}, + [LLDP_EMIT_CUSTOMER_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }}, +}; + +bool link_lldp_emit_enabled(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return false; + + if (link->iftype != ARPHRD_ETHER) + return false; + + if (!link->network) + return false; + + return link->network->lldp_emit != LLDP_EMIT_NO; +} + +static int lldp_write_tlv_header(uint8_t **p, uint8_t id, size_t sz) { + assert(p); + + if (id > 127) + return -EBADMSG; + if (sz > 511) + return -ENOBUFS; + + (*p)[0] = (id << 1) | !!(sz & 256); + (*p)[1] = sz & 255; + + *p = *p + 2; + return 0; +} + +static int lldp_make_packet( + LLDPEmit mode, + const struct ether_addr *hwaddr, + const char *machine_id, + const char *ifname, + uint16_t ttl, + const char *port_description, + const char *hostname, + const char *pretty_hostname, + uint16_t system_capabilities, + uint16_t enabled_capabilities, + void **ret, size_t *sz) { + + size_t machine_id_length, ifname_length, port_description_length = 0, hostname_length = 0, pretty_hostname_length = 0; + _cleanup_free_ void *packet = NULL; + struct ether_header *h; + uint8_t *p; + size_t l; + int r; + + assert(mode > LLDP_EMIT_NO); + assert(mode < _LLDP_EMIT_MAX); + assert(hwaddr); + assert(machine_id); + assert(ifname); + assert(ret); + assert(sz); + + machine_id_length = strlen(machine_id); + ifname_length = strlen(ifname); + + if (port_description) + port_description_length = strlen(port_description); + + if (hostname) + hostname_length = strlen(hostname); + + if (pretty_hostname) + pretty_hostname_length = strlen(pretty_hostname); + + l = sizeof(struct ether_header) + + /* Chassis ID */ + 2 + 1 + machine_id_length + + /* Port ID */ + 2 + 1 + ifname_length + + /* TTL */ + 2 + 2 + + /* System Capabilities */ + 2 + 4 + + /* End */ + 2; + + /* Port Description */ + if (port_description) + l += 2 + port_description_length; + + /* System Name */ + if (hostname) + l += 2 + hostname_length; + + /* System Description */ + if (pretty_hostname) + l += 2 + pretty_hostname_length; + + packet = malloc(l); + if (!packet) + return -ENOMEM; + + h = (struct ether_header*) packet; + h->ether_type = htobe16(ETHERTYPE_LLDP); + memcpy(h->ether_dhost, lldp_multicast_addr + mode, ETH_ALEN); + memcpy(h->ether_shost, hwaddr, ETH_ALEN); + + p = (uint8_t*) packet + sizeof(struct ether_header); + + r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_CHASSIS_ID, 1 + machine_id_length); + if (r < 0) + return r; + *(p++) = SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED; + p = mempcpy(p, machine_id, machine_id_length); + + r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_ID, 1 + ifname_length); + if (r < 0) + return r; + *(p++) = SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME; + p = mempcpy(p, ifname, ifname_length); + + r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_TTL, 2); + if (r < 0) + return r; + unaligned_write_be16(p, ttl); + p += 2; + + if (port_description) { + r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_DESCRIPTION, port_description_length); + if (r < 0) + return r; + p = mempcpy(p, port_description, port_description_length); + } + + if (hostname) { + r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_NAME, hostname_length); + if (r < 0) + return r; + p = mempcpy(p, hostname, hostname_length); + } + + if (pretty_hostname) { + r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_DESCRIPTION, pretty_hostname_length); + if (r < 0) + return r; + p = mempcpy(p, pretty_hostname, pretty_hostname_length); + } + + r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_CAPABILITIES, 4); + if (r < 0) + return r; + unaligned_write_be16(p, system_capabilities); + p += 2; + unaligned_write_be16(p, enabled_capabilities); + p += 2; + + r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_END, 0); + if (r < 0) + return r; + + assert(p == (uint8_t*) packet + l); + + *ret = TAKE_PTR(packet); + *sz = l; + + return 0; +} + +static int lldp_send_packet( + int ifindex, + const struct ether_addr *address, + const void *packet, + size_t packet_size) { + + union sockaddr_union sa = { + .ll.sll_family = AF_PACKET, + .ll.sll_protocol = htobe16(ETHERTYPE_LLDP), + .ll.sll_ifindex = ifindex, + .ll.sll_halen = ETH_ALEN, + }; + + _cleanup_close_ int fd = -1; + ssize_t l; + + assert(ifindex > 0); + assert(address); + assert(packet || packet_size <= 0); + + memcpy(sa.ll.sll_addr, address, ETH_ALEN); + + fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC, IPPROTO_RAW); + if (fd < 0) + return -errno; + + l = sendto(fd, packet, packet_size, MSG_NOSIGNAL, &sa.sa, sizeof(sa.ll)); + if (l < 0) + return -errno; + + if ((size_t) l != packet_size) + return -EIO; + + return 0; +} + +static int link_send_lldp(Link *link) { + char machine_id_string[SD_ID128_STRING_MAX]; + _cleanup_free_ char *hostname = NULL, *pretty_hostname = NULL; + _cleanup_free_ void *packet = NULL; + size_t packet_size = 0; + sd_id128_t machine_id; + uint16_t caps; + usec_t ttl; + int r; + + assert(link); + + if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) + return 0; + + assert(link->network->lldp_emit < _LLDP_EMIT_MAX); + + r = sd_id128_get_machine(&machine_id); + if (r < 0) + return r; + + (void) gethostname_strict(&hostname); + (void) parse_env_file(NULL, "/etc/machine-info", "PRETTY_HOSTNAME", &pretty_hostname); + + assert_cc(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1 <= (UINT16_MAX - 1) * USEC_PER_SEC); + ttl = DIV_ROUND_UP(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1, USEC_PER_SEC); + + caps = (link->network && link->network->ip_forward != ADDRESS_FAMILY_NO) ? + SD_LLDP_SYSTEM_CAPABILITIES_ROUTER : + SD_LLDP_SYSTEM_CAPABILITIES_STATION; + + r = lldp_make_packet(link->network->lldp_emit, + &link->mac, + sd_id128_to_string(machine_id, machine_id_string), + link->ifname, + (uint16_t) ttl, + link->network ? link->network->description : NULL, + hostname, + pretty_hostname, + SD_LLDP_SYSTEM_CAPABILITIES_STATION|SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|SD_LLDP_SYSTEM_CAPABILITIES_ROUTER, + caps, + &packet, &packet_size); + if (r < 0) + return r; + + return lldp_send_packet(link->ifindex, lldp_multicast_addr + link->network->lldp_emit, packet, packet_size); +} + +static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) { + Link *link = userdata; + usec_t current, delay, next; + int r; + + assert(s); + assert(userdata); + + log_link_debug(link, "Sending LLDP packet..."); + + r = link_send_lldp(link); + if (r < 0) + log_link_debug_errno(link, r, "Failed to send LLDP packet, ignoring: %m"); + + if (link->lldp_tx_fast > 0) + link->lldp_tx_fast--; + + assert_se(sd_event_now(sd_event_source_get_event(s), clock_boottime_or_monotonic(), ¤t) >= 0); + + delay = link->lldp_tx_fast > 0 ? LLDP_FAST_TX_USEC : LLDP_TX_INTERVAL_USEC; + next = usec_add(usec_add(current, delay), (usec_t) random_u64() % LLDP_JITTER_USEC); + + r = sd_event_source_set_time(s, next); + if (r < 0) + return log_link_error_errno(link, r, "Failed to restart LLDP timer: %m"); + + r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT); + if (r < 0) + return log_link_error_errno(link, r, "Failed to enable LLDP timer: %m"); + + return 0; +} + +int link_lldp_emit_start(Link *link) { + usec_t next; + int r; + + assert(link); + + if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) { + link_lldp_emit_stop(link); + return 0; + } + + /* Starts the LLDP transmission in "fast" mode. If it is already started, turns "fast" mode back on again. */ + + link->lldp_tx_fast = LLDP_TX_FAST_INIT; + + next = usec_add(usec_add(now(clock_boottime_or_monotonic()), LLDP_FAST_TX_USEC), + (usec_t) random_u64() % LLDP_JITTER_USEC); + + if (link->lldp_emit_event_source) { + usec_t old; + + /* Lower the timeout, maybe */ + r = sd_event_source_get_time(link->lldp_emit_event_source, &old); + if (r < 0) + return r; + + if (old <= next) + return 0; + + return sd_event_source_set_time(link->lldp_emit_event_source, next); + } else { + r = sd_event_add_time( + link->manager->event, + &link->lldp_emit_event_source, + clock_boottime_or_monotonic(), + next, + 0, + on_lldp_timer, + link); + if (r < 0) + return r; + + (void) sd_event_source_set_description(link->lldp_emit_event_source, "lldp-tx"); + } + + return 0; +} + +void link_lldp_emit_stop(Link *link) { + assert(link); + + link->lldp_emit_event_source = sd_event_source_unref(link->lldp_emit_event_source); +} + +int config_parse_lldp_emit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + LLDPEmit *emit = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) + *emit = LLDP_EMIT_NO; + else if (streq(rvalue, "nearest-bridge")) + *emit = LLDP_EMIT_NEAREST_BRIDGE; + else if (streq(rvalue, "non-tpmr-bridge")) + *emit = LLDP_EMIT_NON_TPMR_BRIDGE; + else if (streq(rvalue, "customer-bridge")) + *emit = LLDP_EMIT_CUSTOMER_BRIDGE; + else { + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse LLDP emission setting, ignoring: %s", rvalue); + return 0; + } + + *emit = r ? LLDP_EMIT_NEAREST_BRIDGE : LLDP_EMIT_NO; + } + + return 0; +} diff --git a/src/network/networkd-lldp-tx.h b/src/network/networkd-lldp-tx.h new file mode 100644 index 00000000..561becda --- /dev/null +++ b/src/network/networkd-lldp-tx.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "conf-parser.h" + +typedef struct Link Link; + +typedef enum LLDPEmit { + LLDP_EMIT_NO, + LLDP_EMIT_NEAREST_BRIDGE, + LLDP_EMIT_NON_TPMR_BRIDGE, + LLDP_EMIT_CUSTOMER_BRIDGE, + _LLDP_EMIT_MAX, +} LLDPEmit; + +bool link_lldp_emit_enabled(Link *link); +int link_lldp_emit_start(Link *link); +void link_lldp_emit_stop(Link *link); + +CONFIG_PARSER_PROTOTYPE(config_parse_lldp_emit); diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c new file mode 100644 index 00000000..d97cc0ce --- /dev/null +++ b/src/network/networkd-manager-bus.c @@ -0,0 +1,269 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-polkit.h" +#include "networkd-link-bus.h" +#include "networkd-link.h" +#include "networkd-manager-bus.h" +#include "networkd-manager.h" +#include "path-util.h" +#include "strv.h" +#include "user-util.h" + +static int method_list_links(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Manager *manager = userdata; + Iterator i; + Link *link; + int r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(iso)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(link, manager->links, i) { + _cleanup_free_ char *path = NULL; + + path = link_bus_path(link); + if (!path) + return -ENOMEM; + + r = sd_bus_message_append( + reply, "(iso)", + link->ifindex, + link->ifname, + empty_to_root(path)); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_get_link_by_name(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *path = NULL; + Manager *manager = userdata; + const char *name; + int index, r; + Link *link; + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + index = if_nametoindex(name); + if (index <= 0) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %s not known", name); + + link = hashmap_get(manager->links, INT_TO_PTR(index)); + if (!link) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %s not known", name); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + path = link_bus_path(link); + if (!path) + return -ENOMEM; + + r = sd_bus_message_append(reply, "io", link->ifindex, empty_to_root(path)); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int method_get_link_by_index(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *path = NULL; + Manager *manager = userdata; + int32_t index; + Link *link; + int r; + + r = sd_bus_message_read(message, "i", &index); + if (r < 0) + return r; + + link = hashmap_get(manager->links, INT_TO_PTR((int) index)); + if (!link) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %" PRIi32 " not known", index); + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + path = link_bus_path(link); + if (!path) + return -ENOMEM; + + r = sd_bus_message_append(reply, "so", link->ifname, empty_to_root(path)); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) { + int ifindex, r; + Link *l; + + assert(m); + assert(message); + assert(handler); + + assert_cc(sizeof(int) == sizeof(int32_t)); + r = sd_bus_message_read(message, "i", &ifindex); + if (r < 0) + return r; + + if (ifindex <= 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index"); + + l = hashmap_get(m->links, INT_TO_PTR(ifindex)); + if (!l) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex); + + return handler(message, l, error); +} + +static int bus_method_set_link_ntp_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_ntp_servers, error); +} + +static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_dns_servers, error); +} + +static int bus_method_set_link_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_domains, error); +} + +static int bus_method_set_link_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_default_route, error); +} + +static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_llmnr, error); +} + +static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_mdns, error); +} + +static int bus_method_set_link_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_dns_over_tls, error); +} + +static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_dnssec, error); +} + +static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error); +} + +static int bus_method_revert_link_ntp(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_revert_ntp, error); +} + +static int bus_method_revert_link_dns(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_revert_dns, error); +} + +static int bus_method_renew_link(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_renew, error); +} + +static int bus_method_reconfigure_link(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_reconfigure, error); +} + +static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *manager = userdata; + Iterator i; + Link *link; + int r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.network1.reload", + NULL, true, UID_INVALID, + &manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + r = netdev_load(manager, true); + if (r < 0) + return r; + + r = network_reload(manager); + if (r < 0) + return r; + + HASHMAP_FOREACH(link, manager->links, i) { + r = link_reconfigure(link, false); + if (r < 0) + return r; + } + + return sd_bus_reply_method_return(message, NULL); +} + +const sd_bus_vtable manager_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Manager, operational_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Manager, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Manager, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + + SD_BUS_METHOD("ListLinks", NULL, "a(iso)", method_list_links, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetLinkByName", "s", "io", method_get_link_by_name, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetLinkByIndex", "i", "so", method_get_link_by_index, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkNTP", "ias", NULL, bus_method_set_link_ntp_servers, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_domains, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDefaultRoute", "ib", NULL, bus_method_set_link_default_route, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDNSOverTLS", "is", NULL, bus_method_set_link_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RevertLinkNTP", "i", NULL, bus_method_revert_link_ntp, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RevertLinkDNS", "i", NULL, bus_method_revert_link_dns, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RenewLink", "i", NULL, bus_method_renew_link, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReconfigureLink", "i", NULL, bus_method_reconfigure_link, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Reload", NULL, NULL, bus_method_reload, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_VTABLE_END +}; + +int manager_send_changed_strv(Manager *manager, char **properties) { + assert(manager); + assert(properties); + + if (!manager->bus) + return 0; + + return sd_bus_emit_properties_changed_strv( + manager->bus, + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + properties); +} diff --git a/src/network/networkd-manager-bus.h b/src/network/networkd-manager-bus.h new file mode 100644 index 00000000..e19d7069 --- /dev/null +++ b/src/network/networkd-manager-bus.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +typedef struct Manager Manager; + +extern const sd_bus_vtable manager_vtable[]; + +int manager_send_changed_strv(Manager *m, char **properties); diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c new file mode 100644 index 00000000..cbb3fa96 --- /dev/null +++ b/src/network/networkd-manager.c @@ -0,0 +1,2308 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "conf-parser.h" +#include "def.h" +#include "device-private.h" +#include "device-util.h" +#include "dns-domain.h" +#include "fd-util.h" +#include "fileio.h" +#include "local-addresses.h" +#include "netlink-util.h" +#include "network-internal.h" +#include "networkd-dhcp6.h" +#include "networkd-link-bus.h" +#include "networkd-manager-bus.h" +#include "networkd-manager.h" +#include "networkd-network-bus.h" +#include "networkd-speed-meter.h" +#include "ordered-set.h" +#include "path-util.h" +#include "set.h" +#include "signal-util.h" +#include "strv.h" +#include "sysctl-util.h" +#include "tmpfile-util.h" +#include "udev-util.h" +#include "virt.h" + +/* use 8 MB for receive socket kernel queue. */ +#define RCVBUF_SIZE (8*1024*1024) + +static int setup_default_address_pool(Manager *m) { + AddressPool *p; + int r; + + assert(m); + + /* Add in the well-known private address ranges. */ + + r = address_pool_new_from_string(m, &p, AF_INET6, "fd00::", 8); + if (r < 0) + return r; + + r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8); + if (r < 0) + return r; + + r = address_pool_new_from_string(m, &p, AF_INET, "172.16.0.0", 12); + if (r < 0) + return r; + + r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16); + if (r < 0) + return r; + + return 0; +} + +static int manager_reset_all(Manager *m) { + Link *link; + Iterator i; + int r; + + assert(m); + + HASHMAP_FOREACH(link, m->links, i) { + r = link_carrier_reset(link); + if (r < 0) + log_link_warning_errno(link, r, "Could not reset carrier: %m"); + } + + return 0; +} + +static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { + Manager *m = userdata; + int b, r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) { + log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m"); + return 0; + } + + if (b) + return 0; + + log_debug("Coming back from suspend, resetting all connections..."); + + (void) manager_reset_all(m); + + return 0; +} + +static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { + Manager *m = userdata; + + assert(message); + assert(m); + + /* Did we get a timezone or transient hostname from DHCP while D-Bus wasn't up yet? */ + if (m->dynamic_hostname) + (void) manager_set_hostname(m, m->dynamic_hostname); + if (m->dynamic_timezone) + (void) manager_set_timezone(m, m->dynamic_timezone); + if (m->links_requesting_uuid) + (void) manager_request_product_uuid(m, NULL); + + return 0; +} + +int manager_connect_bus(Manager *m) { + int r; + + assert(m); + + if (m->bus) + return 0; + + r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-network"); + if (r < 0) + return log_error_errno(r, "Failed to connect to bus: %m"); + + r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m); + if (r < 0) + return log_error_errno(r, "Failed to add manager object vtable: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link", link_vtable, link_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to add link object vtable: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", link_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add link enumerator: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to add network object vtable: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/network", network_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add network enumerator: %m"); + + r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.network1", 0, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + r = sd_bus_attach_event(m->bus, m->event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.DBus.Local", + NULL, + "org.freedesktop.DBus.Local", + "Connected", + on_connected, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to request match on Connected signal: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "PrepareForSleep", + match_prepare_for_sleep, NULL, m); + if (r < 0) + log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m"); + + return 0; +} + +static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata) { + Manager *m = userdata; + DeviceAction action; + Link *link = NULL; + int r, ifindex; + + assert(m); + assert(device); + + r = device_get_action(device, &action); + if (r < 0) { + log_device_debug_errno(device, r, "Failed to get udev action, ignoring device: %m"); + return 0; + } + + if (!IN_SET(action, DEVICE_ACTION_ADD, DEVICE_ACTION_CHANGE, DEVICE_ACTION_MOVE)) { + log_device_debug(device, "Ignoring udev %s event for device.", device_action_to_string(action)); + return 0; + } + + r = sd_device_get_ifindex(device, &ifindex); + if (r < 0) { + log_device_debug_errno(device, r, "Ignoring udev ADD event for device without ifindex or with invalid ifindex: %m"); + return 0; + } + + r = device_is_renaming(device); + if (r < 0) { + log_device_error_errno(device, r, "Failed to determine the device is renamed or not, ignoring '%s' uevent: %m", + device_action_to_string(action)); + return 0; + } + if (r > 0) { + log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed: %m"); + return 0; + } + + r = link_get(m, ifindex, &link); + if (r < 0) { + if (r != -ENODEV) + log_debug_errno(r, "Failed to get link from ifindex %i, ignoring: %m", ifindex); + return 0; + } + + (void) link_initialized(link, device); + + return 0; +} + +static int manager_connect_udev(Manager *m) { + int r; + + /* udev does not initialize devices inside containers, + * so we rely on them being already initialized before + * entering the container */ + if (detect_container() > 0) + return 0; + + r = sd_device_monitor_new(&m->device_monitor); + if (r < 0) + return log_error_errno(r, "Failed to initialize device monitor: %m"); + + r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL); + if (r < 0) + return log_error_errno(r, "Could not add device monitor filter: %m"); + + r = sd_device_monitor_attach_event(m->device_monitor, m->event); + if (r < 0) + return log_error_errno(r, "Failed to attach event to device monitor: %m"); + + r = sd_device_monitor_start(m->device_monitor, manager_udev_process_link, m); + if (r < 0) + return log_error_errno(r, "Failed to start device monitor: %m"); + + return 0; +} + +int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { + _cleanup_(route_freep) Route *tmp = NULL; + Route *route = NULL; + Manager *m = userdata; + Link *link = NULL; + uint32_t ifindex; + uint16_t type; + unsigned char table; + int r; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_warning_errno(r, "rtnl: failed to receive route message, ignoring: %m"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWROUTE, RTM_DELROUTE)) { + log_warning("rtnl: received unexpected message type %u when processing route, ignoring.", type); + return 0; + } + + r = sd_netlink_message_read_u32(message, RTA_OIF, &ifindex); + if (r == -ENODATA) { + log_debug("rtnl: received route message without ifindex, ignoring"); + return 0; + } else if (r < 0) { + log_warning_errno(r, "rtnl: could not get ifindex from route message, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received route message with invalid ifindex %d, ignoring.", ifindex); + return 0; + } + + r = link_get(m, ifindex, &link); + if (r < 0 || !link) { + /* when enumerating we might be out of sync, but we will + * get the route again, so just ignore it */ + if (!m->enumerating) + log_warning("rtnl: received route message for link (%d) we do not know about, ignoring", ifindex); + return 0; + } + + r = route_new(&tmp); + if (r < 0) + return log_oom(); + + r = sd_rtnl_message_route_get_family(message, &tmp->family); + if (r < 0 || !IN_SET(tmp->family, AF_INET, AF_INET6)) { + log_link_warning(link, "rtnl: received route message with invalid family, ignoring"); + return 0; + } + + r = sd_rtnl_message_route_get_protocol(message, &tmp->protocol); + if (r < 0) { + log_warning_errno(r, "rtnl: received route message with invalid route protocol: %m"); + return 0; + } + + switch (tmp->family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, RTA_DST, &tmp->dst.in); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &tmp->gw.in); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in_addr(message, RTA_SRC, &tmp->src.in); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &tmp->prefsrc.in); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m"); + return 0; + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, RTA_DST, &tmp->dst.in6); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &tmp->gw.in6); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &tmp->src.in6); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &tmp->prefsrc.in6); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m"); + return 0; + } + + break; + + default: + assert_not_reached("Received route message with unsupported address family"); + return 0; + } + + r = sd_rtnl_message_route_get_dst_prefixlen(message, &tmp->dst_prefixlen); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid destination prefixlen, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_route_get_src_prefixlen(message, &tmp->src_prefixlen); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid source prefixlen, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_route_get_scope(message, &tmp->scope); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid scope, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_route_get_tos(message, &tmp->tos); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid tos, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_route_get_type(message, &tmp->type); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid type, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_route_get_table(message, &table); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid table, ignoring: %m"); + return 0; + } + tmp->table = table; + + r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &tmp->priority); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid priority, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_enter_container(message, RTA_METRICS); + if (r < 0 && r != -ENODATA) { + log_link_error_errno(link, r, "rtnl: Could not enter RTA_METRICS container: %m"); + return 0; + } + if (r >= 0) { + r = sd_netlink_message_read_u32(message, RTAX_INITCWND, &tmp->initcwnd); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid initcwnd, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, RTAX_INITRWND, &tmp->initrwnd); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: received route message with invalid initrwnd, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_exit_container(message); + if (r < 0) { + log_link_error_errno(link, r, "rtnl: Could not exit from RTA_METRICS container: %m"); + return 0; + } + } + + (void) route_get(link, tmp, &route); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL, + *buf_src = NULL, *buf_gw = NULL, *buf_prefsrc = NULL; + char buf_scope[ROUTE_SCOPE_STR_MAX], buf_table[ROUTE_TABLE_STR_MAX], + buf_protocol[ROUTE_PROTOCOL_STR_MAX]; + + if (!in_addr_is_null(tmp->family, &tmp->dst)) { + (void) in_addr_to_string(tmp->family, &tmp->dst, &buf_dst); + (void) asprintf(&buf_dst_prefixlen, "/%u", tmp->dst_prefixlen); + } + if (!in_addr_is_null(tmp->family, &tmp->src)) + (void) in_addr_to_string(tmp->family, &tmp->src, &buf_src); + if (!in_addr_is_null(tmp->family, &tmp->gw)) + (void) in_addr_to_string(tmp->family, &tmp->gw, &buf_gw); + if (!in_addr_is_null(tmp->family, &tmp->prefsrc)) + (void) in_addr_to_string(tmp->family, &tmp->prefsrc, &buf_prefsrc); + + log_link_debug(link, + "%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s", + type == RTM_DELROUTE ? "Forgetting" : route ? "Received remembered" : "Remembering", + strna(buf_dst), strempty(buf_dst_prefixlen), + strna(buf_src), strna(buf_gw), strna(buf_prefsrc), + format_route_scope(tmp->scope, buf_scope, sizeof buf_scope), + format_route_table(tmp->table, buf_table, sizeof buf_table), + format_route_protocol(tmp->protocol, buf_protocol, sizeof buf_protocol), + strna(route_type_to_string(tmp->type))); + } + + switch (type) { + case RTM_NEWROUTE: + if (!route) { + /* A route appeared that we did not request */ + r = route_add_foreign(link, tmp, &route); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m"); + return 0; + } + } + + break; + + case RTM_DELROUTE: + route_free(route); + break; + + default: + assert_not_reached("Received route message with invalid RTNL message type"); + } + + return 1; +} + +static int manager_rtnl_process_neighbor_lladdr(sd_netlink_message *message, union lladdr_union *lladdr, size_t *size, char **str) { + int r; + + assert(message); + assert(lladdr); + assert(size); + assert(str); + + *str = NULL; + + r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in6), &lladdr->ip.in6); + if (r >= 0) { + *size = sizeof(lladdr->ip.in6); + if (in_addr_to_string(AF_INET6, &lladdr->ip, str) < 0) + log_warning_errno(r, "Could not print lower address: %m"); + return r; + } + + r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->mac), &lladdr->mac); + if (r >= 0) { + *size = sizeof(lladdr->mac); + *str = new(char, ETHER_ADDR_TO_STRING_MAX); + if (!*str) { + log_oom(); + return r; + } + ether_addr_to_string(&lladdr->mac, *str); + return r; + } + + r = sd_netlink_message_read(message, NDA_LLADDR, sizeof(lladdr->ip.in), &lladdr->ip.in); + if (r >= 0) { + *size = sizeof(lladdr->ip.in); + if (in_addr_to_string(AF_INET, &lladdr->ip, str) < 0) + log_warning_errno(r, "Could not print lower address: %m"); + return r; + } + + return r; +} + +int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { + Manager *m = userdata; + Link *link = NULL; + Neighbor *neighbor = NULL; + int ifindex, family, r; + uint16_t type, state; + union in_addr_union in_addr = IN_ADDR_NULL; + _cleanup_free_ char *addr_str = NULL; + union lladdr_union lladdr; + size_t lladdr_size = 0; + _cleanup_free_ char *lladdr_str = NULL; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_warning_errno(r, "rtnl: failed to receive neighbor message, ignoring: %m"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWNEIGH, RTM_DELNEIGH)) { + log_warning("rtnl: received unexpected message type %u when processing neighbor, ignoring.", type); + return 0; + } + + r = sd_rtnl_message_neigh_get_state(message, &state); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid state, ignoring: %m"); + return 0; + } else if (!FLAGS_SET(state, NUD_PERMANENT)) { + log_debug("rtnl: received non-static neighbor, ignoring."); + return 0; + } + + r = sd_rtnl_message_neigh_get_ifindex(message, &ifindex); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received neighbor message with invalid ifindex %d, ignoring.", ifindex); + return 0; + } + + r = link_get(m, ifindex, &link); + if (r < 0 || !link) { + /* when enumerating we might be out of sync, but we will get the neighbor again, so just + * ignore it */ + if (!m->enumerating) + log_warning("rtnl: received neighbor for link '%d' we don't know about, ignoring.", ifindex); + return 0; + } + + r = sd_rtnl_message_neigh_get_family(message, &family); + if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { + log_link_warning(link, "rtnl: received neighbor message with invalid family, ignoring."); + return 0; + } + + switch (family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, NDA_DST, &in_addr.in); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m"); + return 0; + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, NDA_DST, &in_addr.in6); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received neighbor message without valid address, ignoring: %m"); + return 0; + } + + break; + + default: + assert_not_reached("Received unsupported address family"); + } + + if (in_addr_to_string(family, &in_addr, &addr_str) < 0) + log_link_warning_errno(link, r, "Could not print address: %m"); + + r = manager_rtnl_process_neighbor_lladdr(message, &lladdr, &lladdr_size, &lladdr_str); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received neighbor message with invalid lladdr, ignoring: %m"); + return 0; + } + + (void) neighbor_get(link, family, &in_addr, &lladdr, lladdr_size, &neighbor); + + switch (type) { + case RTM_NEWNEIGH: + if (neighbor) + log_link_debug(link, "Remembering neighbor: %s->%s", + strnull(addr_str), strnull(lladdr_str)); + else { + /* A neighbor appeared that we did not request */ + r = neighbor_add_foreign(link, family, &in_addr, &lladdr, lladdr_size, &neighbor); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to remember foreign neighbor %s->%s, ignoring: %m", + strnull(addr_str), strnull(lladdr_str)); + return 0; + } else + log_link_debug(link, "Remembering foreign neighbor: %s->%s", + strnull(addr_str), strnull(lladdr_str)); + } + + break; + + case RTM_DELNEIGH: + if (neighbor) { + log_link_debug(link, "Forgetting neighbor: %s->%s", + strnull(addr_str), strnull(lladdr_str)); + (void) neighbor_free(neighbor); + } else + log_link_debug(link, "Kernel removed a neighbor we don't remember: %s->%s, ignoring.", + strnull(addr_str), strnull(lladdr_str)); + + break; + + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + +int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { + _cleanup_free_ char *buf = NULL; + Manager *m = userdata; + Link *link = NULL; + uint16_t type; + unsigned char flags, prefixlen, scope; + union in_addr_union in_addr = IN_ADDR_NULL; + struct ifa_cacheinfo cinfo; + Address *address = NULL; + char valid_buf[FORMAT_TIMESPAN_MAX]; + const char *valid_str = NULL; + int ifindex, family, r; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_warning_errno(r, "rtnl: failed to receive address message, ignoring: %m"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWADDR, RTM_DELADDR)) { + log_warning("rtnl: received unexpected message type %u when processing address, ignoring.", type); + return 0; + } + + r = sd_rtnl_message_addr_get_ifindex(message, &ifindex); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received address message with invalid ifindex %d, ignoring.", ifindex); + return 0; + } + + r = link_get(m, ifindex, &link); + if (r < 0 || !link) { + /* when enumerating we might be out of sync, but we will get the address again, so just + * ignore it */ + if (!m->enumerating) + log_warning("rtnl: received address for link '%d' we don't know about, ignoring.", ifindex); + return 0; + } + + r = sd_rtnl_message_addr_get_family(message, &family); + if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { + log_link_warning(link, "rtnl: received address message with invalid family, ignoring."); + return 0; + } + + r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message with invalid prefixlen, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_addr_get_scope(message, &scope); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message with invalid scope, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_addr_get_flags(message, &flags); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message with invalid flags, ignoring: %m"); + return 0; + } + + switch (family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m"); + return 0; + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6); + if (r < 0) { + log_link_warning_errno(link, r, "rtnl: received address message without valid address, ignoring: %m"); + return 0; + } + + break; + + default: + assert_not_reached("Received unsupported address family"); + } + + r = in_addr_to_string(family, &in_addr, &buf); + if (r < 0) + log_link_warning_errno(link, r, "Could not print address: %m"); + + r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); + if (r < 0 && r != -ENODATA) { + log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m"); + return 0; + } else if (r >= 0 && cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME) + valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, + cinfo.ifa_valid * USEC_PER_SEC, + USEC_PER_SEC); + + (void) address_get(link, family, &in_addr, prefixlen, &address); + + switch (type) { + case RTM_NEWADDR: + if (address) + log_link_debug(link, "Remembering updated address: %s/%u (valid %s%s)", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + else { + /* An address appeared that we did not request */ + r = address_add_foreign(link, family, &in_addr, prefixlen, &address); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to remember foreign address %s/%u, ignoring: %m", + strnull(buf), prefixlen); + return 0; + } else + log_link_debug(link, "Remembering foreign address: %s/%u (valid %s%s)", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + } + + /* address_update() logs internally, so we don't need to. */ + (void) address_update(address, flags, scope, &cinfo); + + break; + + case RTM_DELADDR: + if (address) { + log_link_debug(link, "Forgetting address: %s/%u (valid %s%s)", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + (void) address_drop(address); + } else + log_link_debug(link, "Kernel removed an address we don't remember: %s/%u (valid %s%s), ignoring.", + strnull(buf), prefixlen, + valid_str ? "for " : "forever", strempty(valid_str)); + + break; + + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + +static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { + Manager *m = userdata; + Link *link = NULL; + NetDev *netdev = NULL; + uint16_t type; + const char *name; + int r, ifindex; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_warning_errno(r, "rtnl: Could not receive link message, ignoring: %m"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWLINK, RTM_DELLINK)) { + log_warning("rtnl: Received unexpected message type %u when processing link, ignoring.", type); + return 0; + } + + r = sd_rtnl_message_link_get_ifindex(message, &ifindex); + if (r < 0) { + log_warning_errno(r, "rtnl: Could not get ifindex from link message, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received link message with invalid ifindex %d, ignoring.", ifindex); + return 0; + } + + r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name); + if (r < 0) { + log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m"); + return 0; + } + + (void) link_get(m, ifindex, &link); + (void) netdev_get(m, name, &netdev); + + switch (type) { + case RTM_NEWLINK: + if (!link) { + /* link is new, so add it */ + r = link_add(m, message, &link); + if (r < 0) { + log_warning_errno(r, "Could not process new link message, ignoring: %m"); + return 0; + } + } + + if (netdev) { + /* netdev exists, so make sure the ifindex matches */ + r = netdev_set_ifindex(netdev, message); + if (r < 0) { + log_warning_errno(r, "Could not process new link message for netdev, ignoring: %m"); + return 0; + } + } + + r = link_update(link, message); + if (r < 0) { + log_warning_errno(r, "Could not process link message, ignoring: %m"); + return 0; + } + + break; + + case RTM_DELLINK: + link_drop(link); + netdev_drop(netdev); + + break; + + default: + assert_not_reached("Received link message with invalid RTNL message type."); + } + + return 1; +} + +int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { + _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL; + _cleanup_free_ char *from = NULL, *to = NULL; + RoutingPolicyRule *rule = NULL; + const char *iif = NULL, *oif = NULL; + Manager *m = userdata; + unsigned flags; + uint16_t type; + int r; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_warning_errno(r, "rtnl: failed to receive rule message, ignoring: %m"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWRULE, RTM_DELRULE)) { + log_warning("rtnl: received unexpected message type %u when processing rule, ignoring.", type); + return 0; + } + + r = routing_policy_rule_new(&tmp); + if (r < 0) { + log_oom(); + return 0; + } + + r = sd_rtnl_message_get_family(message, &tmp->family); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get rule family, ignoring: %m"); + return 0; + } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { + log_debug("rtnl: received rule message with invalid family %d, ignoring.", tmp->family); + return 0; + } + + switch (tmp->family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, FRA_SRC, &tmp->from.in); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m"); + return 0; + } else if (r >= 0) { + r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen); + if (r < 0) { + log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m"); + return 0; + } + } + + r = sd_netlink_message_read_in_addr(message, FRA_DST, &tmp->to.in); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m"); + return 0; + } else if (r >= 0) { + r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen); + if (r < 0) { + log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m"); + return 0; + } + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, FRA_SRC, &tmp->from.in6); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m"); + return 0; + } else if (r >= 0) { + r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen); + if (r < 0) { + log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m"); + return 0; + } + } + + r = sd_netlink_message_read_in6_addr(message, FRA_DST, &tmp->to.in6); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m"); + return 0; + } else if (r >= 0) { + r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen); + if (r < 0) { + log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m"); + return 0; + } + } + + break; + + default: + assert_not_reached("Received rule message with unsupported address family"); + } + + if (tmp->from_prefixlen == 0 && tmp->to_prefixlen == 0) + return 0; + + r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags); + if (r < 0) { + log_warning_errno(r, "rtnl: received rule message without valid flag, ignoring: %m"); + return 0; + } + tmp->invert_rule = flags & FIB_RULE_INVERT; + + r = sd_netlink_message_read_u32(message, FRA_FWMARK, &tmp->fwmark); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, FRA_FWMASK, &tmp->fwmask); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, FRA_PRIORITY, &tmp->priority); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, FRA_TABLE, &tmp->table); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_TABLE attribute, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_routing_policy_rule_get_tos(message, &tmp->tos); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get ip rule TOS, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_string(message, FRA_IIFNAME, &iif); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m"); + return 0; + } + r = free_and_strdup(&tmp->iif, iif); + if (r < 0) + return log_oom(); + + r = sd_netlink_message_read_string(message, FRA_OIFNAME, &oif); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m"); + return 0; + } + r = free_and_strdup(&tmp->oif, oif); + if (r < 0) + return log_oom(); + + r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->protocol); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read(message, FRA_SPORT_RANGE, sizeof(tmp->sport), &tmp->sport); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read(message, FRA_DPORT_RANGE, sizeof(tmp->dport), &tmp->dport); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m"); + return 0; + } + + (void) routing_policy_rule_get(m, tmp, &rule); + + if (DEBUG_LOGGING) { + (void) in_addr_to_string(tmp->family, &tmp->from, &from); + (void) in_addr_to_string(tmp->family, &tmp->to, &to); + } + + switch (type) { + case RTM_NEWRULE: + if (!rule) { + log_debug("Remembering foreign routing policy rule: %s/%u -> %s/%u, iif: %s, oif: %s, table: %u", + from, tmp->from_prefixlen, to, tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); + r = routing_policy_rule_add_foreign(m, tmp, &rule); + if (r < 0) { + log_warning_errno(r, "Could not remember foreign rule, ignoring: %m"); + return 0; + } + } + break; + case RTM_DELRULE: + log_debug("Forgetting routing policy rule: %s/%u -> %s/%u, iif: %s, oif: %s, table: %u", + from, tmp->from_prefixlen, to, tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table); + routing_policy_rule_free(rule); + + break; + + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + +int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { + _cleanup_(nexthop_freep) NextHop *tmp = NULL; + _cleanup_free_ char *gateway = NULL; + NextHop *nexthop = NULL; + Manager *m = userdata; + Link *link = NULL; + uint16_t type; + int r; + + assert(rtnl); + assert(message); + assert(m); + + if (sd_netlink_message_is_error(message)) { + r = sd_netlink_message_get_errno(message); + if (r < 0) + log_warning_errno(r, "rtnl: failed to receive rule message, ignoring: %m"); + + return 0; + } + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get message type, ignoring: %m"); + return 0; + } else if (!IN_SET(type, RTM_NEWNEXTHOP, RTM_DELNEXTHOP)) { + log_warning("rtnl: received unexpected message type %u when processing nexthop, ignoring.", type); + return 0; + } + + r = nexthop_new(&tmp); + if (r < 0) + return log_oom(); + + r = sd_rtnl_message_get_family(message, &tmp->family); + if (r < 0) { + log_warning_errno(r, "rtnl: could not get nexthop family, ignoring: %m"); + return 0; + } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) { + log_debug("rtnl: received nexthop message with invalid family %d, ignoring.", tmp->family); + return 0; + } + + switch (tmp->family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(message, NHA_GATEWAY, &tmp->gw.in); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); + return 0; + } + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(message, NHA_GATEWAY, &tmp->gw.in6); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_GATEWAY attribute, ignoring: %m"); + return 0; + } + break; + + default: + assert_not_reached("Received rule message with unsupported address family"); + } + + r = sd_netlink_message_read_u32(message, NHA_ID, &tmp->id); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_ID attribute, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_read_u32(message, NHA_OIF, &tmp->oif); + if (r < 0 && r != -ENODATA) { + log_warning_errno(r, "rtnl: could not get NHA_OIF attribute, ignoring: %m"); + return 0; + } + + r = link_get(m, tmp->oif, &link); + if (r < 0 || !link) { + if (!m->enumerating) + log_warning("rtnl: received nexthop message for link (%d) we do not know about, ignoring", tmp->oif); + return 0; + } + + (void) nexthop_get(link, tmp, &nexthop); + + if (DEBUG_LOGGING) + (void) in_addr_to_string(tmp->family, &tmp->gw, &gateway); + + switch (type) { + case RTM_NEWNEXTHOP: + if (!nexthop) { + log_debug("Remembering foreign nexthop: %s, oif: %d, id: %d", gateway, tmp->oif, tmp->id); + r = nexthop_add_foreign(link, tmp, &nexthop); + if (r < 0) { + log_warning_errno(r, "Could not remember foreign nexthop, ignoring: %m"); + return 0; + } + } + break; + case RTM_DELNEXTHOP: + log_debug("Forgetting foreign nexthop: %s, oif: %d, id: %d", gateway, tmp->oif, tmp->id); + nexthop_free(nexthop); + + break; + + default: + assert_not_reached("Received invalid RTNL message type"); + } + + return 1; +} + +static int systemd_netlink_fd(void) { + int n, fd, rtnl_fd = -EINVAL; + + n = sd_listen_fds(true); + if (n <= 0) + return -EINVAL; + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { + if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) { + if (rtnl_fd >= 0) + return -EINVAL; + + rtnl_fd = fd; + } + } + + return rtnl_fd; +} + +static int manager_connect_genl(Manager *m) { + int r; + + assert(m); + + r = sd_genl_socket_open(&m->genl); + if (r < 0) + return r; + + r = sd_netlink_inc_rcvbuf(m->genl, RCVBUF_SIZE); + if (r < 0) + return r; + + r = sd_netlink_attach_event(m->genl, m->event, 0); + if (r < 0) + return r; + + return 0; +} + +static int manager_connect_rtnl(Manager *m) { + int fd, r; + + assert(m); + + fd = systemd_netlink_fd(); + if (fd < 0) + r = sd_netlink_open(&m->rtnl); + else + r = sd_netlink_open_fd(&m->rtnl, fd); + if (r < 0) + return r; + + r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE); + if (r < 0) + return r; + + r = sd_netlink_attach_event(m->rtnl, m->event, 0); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop"); + if (r < 0) + return r; + + return 0; +} + +static int ordered_set_put_in_addr_data(OrderedSet *s, const struct in_addr_data *address) { + char *p; + int r; + + assert(s); + assert(address); + + r = in_addr_to_string(address->family, &address->address, &p); + if (r < 0) + return r; + + r = ordered_set_consume(s, p); + if (r == -EEXIST) + return 0; + + return r; +} + +static int ordered_set_put_in_addr_datav(OrderedSet *s, const struct in_addr_data *addresses, unsigned n) { + int r, c = 0; + unsigned i; + + assert(s); + assert(addresses || n == 0); + + for (i = 0; i < n; i++) { + r = ordered_set_put_in_addr_data(s, addresses+i); + if (r < 0) + return r; + + c += r; + } + + return c; +} + +static int ordered_set_put_in4_addr(OrderedSet *s, const struct in_addr *address) { + char *p; + int r; + + assert(s); + assert(address); + + r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p); + if (r < 0) + return r; + + r = ordered_set_consume(s, p); + if (r == -EEXIST) + return 0; + + return r; +} + +static int ordered_set_put_in4_addrv(OrderedSet *s, + const struct in_addr *addresses, + size_t n, + bool (*predicate)(const struct in_addr *addr)) { + int r, c = 0; + size_t i; + + assert(s); + assert(n == 0 || addresses); + + for (i = 0; i < n; i++) { + if (predicate && !predicate(&addresses[i])) + continue; + r = ordered_set_put_in4_addr(s, addresses+i); + if (r < 0) + return r; + + c += r; + } + + return c; +} + +static int manager_save(Manager *m) { + _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL; + const char *operstate_str, *carrier_state_str, *address_state_str; + LinkOperationalState operstate = LINK_OPERSTATE_OFF; + LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF; + LinkAddressState address_state = LINK_ADDRESS_STATE_OFF; + _cleanup_free_ char *temp_path = NULL; + _cleanup_strv_free_ char **p = NULL; + _cleanup_fclose_ FILE *f = NULL; + Link *link; + Iterator i; + int r; + + assert(m); + assert(m->state_file); + + /* We add all NTP and DNS server to a set, to filter out duplicates */ + dns = ordered_set_new(&string_hash_ops); + if (!dns) + return -ENOMEM; + + ntp = ordered_set_new(&string_hash_ops); + if (!ntp) + return -ENOMEM; + + sip = ordered_set_new(&string_hash_ops); + if (!sip) + return -ENOMEM; + + search_domains = ordered_set_new(&dns_name_hash_ops); + if (!search_domains) + return -ENOMEM; + + route_domains = ordered_set_new(&dns_name_hash_ops); + if (!route_domains) + return -ENOMEM; + + HASHMAP_FOREACH(link, m->links, i) { + if (link->flags & IFF_LOOPBACK) + continue; + + if (link->operstate > operstate) + operstate = link->operstate; + + if (link->carrier_state > carrier_state) + carrier_state = link->carrier_state; + + if (link->address_state > address_state) + address_state = link->address_state; + + if (!link->network) + continue; + + /* First add the static configured entries */ + r = ordered_set_put_in_addr_datav(dns, link->network->dns, link->network->n_dns); + if (r < 0) + return r; + + r = ordered_set_put_strdupv(ntp, link->ntp ?: link->network->ntp); + if (r < 0) + return r; + + r = ordered_set_put_string_set(search_domains, link->search_domains ?: link->network->search_domains); + if (r < 0) + return r; + + r = ordered_set_put_string_set(route_domains, link->route_domains ?: link->network->route_domains); + if (r < 0) + return r; + + if (!link->dhcp_lease) + continue; + + /* Secondly, add the entries acquired via DHCP */ + if (link->network->dhcp_use_dns) { + const struct in_addr *addresses; + + r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); + if (r > 0) { + r = ordered_set_put_in4_addrv(dns, addresses, r, in4_addr_is_non_local); + if (r < 0) + return r; + } else if (r < 0 && r != -ENODATA) + return r; + } + + if (link->network->dhcp_use_ntp) { + const struct in_addr *addresses; + + r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); + if (r > 0) { + r = ordered_set_put_in4_addrv(ntp, addresses, r, in4_addr_is_non_local); + if (r < 0) + return r; + } else if (r < 0 && r != -ENODATA) + return r; + } + + if (link->network->dhcp_use_sip) { + const struct in_addr *addresses; + + r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses); + if (r > 0) { + r = ordered_set_put_in4_addrv(sip, addresses, r, in4_addr_is_non_local); + if (r < 0) + return r; + } else if (r < 0 && r != -ENODATA) + return r; + } + + if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { + const char *domainname; + char **domains = NULL; + + OrderedSet *target_domains = (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) ? search_domains : route_domains; + r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); + if (r >= 0) { + r = ordered_set_put_strdup(target_domains, domainname); + if (r < 0) + return r; + } else if (r != -ENODATA) + return r; + + r = sd_dhcp_lease_get_search_domains(link->dhcp_lease, &domains); + if (r >= 0) { + r = ordered_set_put_strdupv(target_domains, domains); + if (r < 0) + return r; + } else if (r != -ENODATA) + return r; + } + } + + if (carrier_state >= LINK_CARRIER_STATE_ENSLAVED) + carrier_state = LINK_CARRIER_STATE_CARRIER; + + operstate_str = link_operstate_to_string(operstate); + assert(operstate_str); + + carrier_state_str = link_carrier_state_to_string(carrier_state); + assert(carrier_state_str); + + address_state_str = link_address_state_to_string(address_state); + assert(address_state_str); + + r = fopen_temporary(m->state_file, &f, &temp_path); + if (r < 0) + return r; + + (void) fchmod(fileno(f), 0644); + + fprintf(f, + "# This is private data. Do not parse.\n" + "OPER_STATE=%s\n" + "CARRIER_STATE=%s\n" + "ADDRESS_STATE=%s\n", + operstate_str, carrier_state_str, address_state_str); + + ordered_set_print(f, "DNS=", dns); + ordered_set_print(f, "NTP=", ntp); + ordered_set_print(f, "SIP=", sip); + ordered_set_print(f, "DOMAINS=", search_domains); + ordered_set_print(f, "ROUTE_DOMAINS=", route_domains); + + r = routing_policy_serialize_rules(m->rules, f); + if (r < 0) + goto fail; + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, m->state_file) < 0) { + r = -errno; + goto fail; + } + + if (m->operational_state != operstate) { + m->operational_state = operstate; + if (strv_extend(&p, "OperationalState") < 0) + log_oom(); + } + + if (m->carrier_state != carrier_state) { + m->carrier_state = carrier_state; + if (strv_extend(&p, "CarrierState") < 0) + log_oom(); + } + + if (m->address_state != address_state) { + m->address_state = address_state; + if (strv_extend(&p, "AddressState") < 0) + log_oom(); + } + + if (p) { + r = manager_send_changed_strv(m, p); + if (r < 0) + log_error_errno(r, "Could not emit changed properties: %m"); + } + + m->dirty = false; + + return 0; + +fail: + (void) unlink(m->state_file); + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save network state to %s: %m", m->state_file); +} + +static int manager_dirty_handler(sd_event_source *s, void *userdata) { + Manager *m = userdata; + Link *link; + Iterator i; + + assert(m); + + if (m->dirty) + manager_save(m); + + SET_FOREACH(link, m->dirty_links, i) + if (link_save(link) >= 0) + link_clean(link); + + return 1; +} + +static int signal_terminate_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *m = userdata; + + assert(m); + m->restarting = false; + + log_debug("Terminate operation initiated."); + + return sd_event_exit(sd_event_source_get_event(s), 0); +} + +static int signal_restart_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *m = userdata; + + assert(m); + m->restarting = true; + + log_debug("Restart operation initiated."); + + return sd_event_exit(sd_event_source_get_event(s), 0); +} + +int manager_new(Manager **ret) { + _cleanup_(manager_freep) Manager *m = NULL; + int r; + + m = new(Manager, 1); + if (!m) + return -ENOMEM; + + *m = (Manager) { + .speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL, + }; + + m->state_file = strdup("/run/systemd/netif/state"); + if (!m->state_file) + return -ENOMEM; + + r = sd_event_default(&m->event); + if (r < 0) + return r; + + assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR2, -1) >= 0); + + (void) sd_event_set_watchdog(m->event, true); + (void) sd_event_add_signal(m->event, NULL, SIGTERM, signal_terminate_callback, m); + (void) sd_event_add_signal(m->event, NULL, SIGINT, signal_terminate_callback, m); + (void) sd_event_add_signal(m->event, NULL, SIGUSR2, signal_restart_callback, m); + + r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m); + if (r < 0) + return r; + + r = manager_connect_rtnl(m); + if (r < 0) + return r; + + r = manager_connect_genl(m); + if (r < 0) + return r; + + r = manager_connect_udev(m); + if (r < 0) + return r; + + r = sd_resolve_default(&m->resolve); + if (r < 0) + return r; + + r = sd_resolve_attach_event(m->resolve, m->event, 0); + if (r < 0) + return r; + + r = setup_default_address_pool(m); + if (r < 0) + return r; + + m->duid.type = DUID_TYPE_EN; + + (void) routing_policy_load_rules(m->state_file, &m->rules_saved); + + *ret = TAKE_PTR(m); + + return 0; +} + +void manager_free(Manager *m) { + struct in6_addr *a; + AddressPool *pool; + Link *link; + + if (!m) + return; + + free(m->state_file); + + while ((a = hashmap_first_key(m->dhcp6_prefixes))) + (void) dhcp6_prefix_remove(m, a); + m->dhcp6_prefixes = hashmap_free(m->dhcp6_prefixes); + + while ((link = hashmap_steal_first(m->links))) { + if (link->dhcp6_client) + (void) dhcp6_lease_pd_prefix_lost(link->dhcp6_client, link); + + (void) link_stop_clients(link, true); + + link_unref(link); + } + + m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref); + m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref); + m->links = hashmap_free_with_destructor(m->links, link_unref); + + m->duids_requesting_uuid = set_free(m->duids_requesting_uuid); + m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref); + + m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref); + + while ((pool = m->address_pools)) + address_pool_free(pool); + + /* routing_policy_rule_free() access m->rules and m->rules_foreign. + * So, it is necessary to set NULL after the sets are freed. */ + m->rules = set_free_with_destructor(m->rules, routing_policy_rule_free); + m->rules_foreign = set_free_with_destructor(m->rules_foreign, routing_policy_rule_free); + set_free_with_destructor(m->rules_saved, routing_policy_rule_free); + + sd_netlink_unref(m->rtnl); + sd_netlink_unref(m->genl); + sd_resolve_unref(m->resolve); + + sd_event_source_unref(m->speed_meter_event_source); + sd_event_unref(m->event); + + sd_device_monitor_unref(m->device_monitor); + + bus_verify_polkit_async_registry_free(m->polkit_registry); + sd_bus_flush_close_unref(m->bus); + + free(m->dynamic_timezone); + free(m->dynamic_hostname); + + free(m); +} + +int manager_start(Manager *m) { + Link *link; + Iterator i; + int r; + + assert(m); + + r = manager_start_speed_meter(m); + if (r < 0) + return log_error_errno(r, "Failed to initialize speed meter: %m"); + + /* The dirty handler will deal with future serialization, but the first one + must be done explicitly. */ + + manager_save(m); + + HASHMAP_FOREACH(link, m->links, i) + link_save(link); + + return 0; +} + +int manager_load_config(Manager *m) { + int r; + + /* update timestamp */ + paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, true); + + r = netdev_load(m, false); + if (r < 0) + return r; + + r = network_load(m, &m->networks); + if (r < 0) + return r; + + return 0; +} + +bool manager_should_reload(Manager *m) { + return paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, false); +} + +int manager_rtnl_enumerate_links(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *link; + int r; + + assert(m); + assert(m->rtnl); + + r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (link = reply; link; link = sd_netlink_message_next(link)) { + int k; + + m->enumerating = true; + + k = manager_rtnl_process_link(m->rtnl, link, m); + if (k < 0) + r = k; + + m->enumerating = false; + } + + return r; +} + +int manager_rtnl_enumerate_addresses(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *addr; + int r; + + assert(m); + assert(m->rtnl); + + r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, 0); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (addr = reply; addr; addr = sd_netlink_message_next(addr)) { + int k; + + m->enumerating = true; + + k = manager_rtnl_process_address(m->rtnl, addr, m); + if (k < 0) + r = k; + + m->enumerating = false; + } + + return r; +} + +int manager_rtnl_enumerate_neighbors(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *neigh; + int r; + + assert(m); + assert(m->rtnl); + + r = sd_rtnl_message_new_neigh(m->rtnl, &req, RTM_GETNEIGH, 0, AF_UNSPEC); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (neigh = reply; neigh; neigh = sd_netlink_message_next(neigh)) { + int k; + + m->enumerating = true; + + k = manager_rtnl_process_neighbor(m->rtnl, neigh, m); + if (k < 0) + r = k; + + m->enumerating = false; + } + + return r; +} + +int manager_rtnl_enumerate_routes(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *route; + int r; + + assert(m); + assert(m->rtnl); + + r = sd_rtnl_message_new_route(m->rtnl, &req, RTM_GETROUTE, 0, 0); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (route = reply; route; route = sd_netlink_message_next(route)) { + int k; + + m->enumerating = true; + + k = manager_rtnl_process_route(m->rtnl, route, m); + if (k < 0) + r = k; + + m->enumerating = false; + } + + return r; +} + +int manager_rtnl_enumerate_rules(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *rule; + int r; + + assert(m); + assert(m->rtnl); + + r = sd_rtnl_message_new_routing_policy_rule(m->rtnl, &req, RTM_GETRULE, 0); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) { + if (r == -EOPNOTSUPP) { + log_debug("FIB Rules are not supported by the kernel. Ignoring."); + return 0; + } + + return r; + } + + for (rule = reply; rule; rule = sd_netlink_message_next(rule)) { + int k; + + m->enumerating = true; + + k = manager_rtnl_process_rule(m->rtnl, rule, m); + if (k < 0) + r = k; + + m->enumerating = false; + } + + return r; +} + +int manager_rtnl_enumerate_nexthop(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *nexthop; + int r; + + assert(m); + assert(m->rtnl); + + r = sd_rtnl_message_new_nexthop(m->rtnl, &req, RTM_GETNEXTHOP, 0, 0); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) { + if (r == -EOPNOTSUPP) { + log_debug("Nexthop are not supported by the kernel. Ignoring."); + return 0; + } + + return r; + } + + for (nexthop = reply; nexthop; nexthop = sd_netlink_message_next(nexthop)) { + int k; + + m->enumerating = true; + + k = manager_rtnl_process_nexthop(m->rtnl, nexthop, m); + if (k < 0) + r = k; + + m->enumerating = false; + } + + return r; +} + +int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) { + AddressPool *p; + int r; + + assert(m); + assert(prefixlen > 0); + assert(found); + + LIST_FOREACH(address_pools, p, m->address_pools) { + if (p->family != family) + continue; + + r = address_pool_acquire(p, prefixlen, found); + if (r != 0) + return r; + } + + return 0; +} + +Link* manager_find_uplink(Manager *m, Link *exclude) { + _cleanup_free_ struct local_address *gateways = NULL; + int n, i; + + assert(m); + + /* Looks for a suitable "uplink", via black magic: an + * interface that is up and where the default route with the + * highest priority points to. */ + + n = local_gateways(m->rtnl, 0, AF_UNSPEC, &gateways); + if (n < 0) { + log_warning_errno(n, "Failed to determine list of default gateways: %m"); + return NULL; + } + + for (i = 0; i < n; i++) { + Link *link; + + link = hashmap_get(m->links, INT_TO_PTR(gateways[i].ifindex)); + if (!link) { + log_debug("Weird, found a gateway for a link we don't know. Ignoring."); + continue; + } + + if (link == exclude) + continue; + + if (link->operstate < LINK_OPERSTATE_ROUTABLE) + continue; + + return link; + } + + return NULL; +} + +void manager_dirty(Manager *manager) { + assert(manager); + + /* the serialized state in /run is no longer up-to-date */ + manager->dirty = true; +} + +static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + Manager *manager = userdata; + const sd_bus_error *e; + + assert(m); + assert(manager); + + e = sd_bus_message_get_error(m); + if (e) + log_warning_errno(sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message); + + return 1; +} + +int manager_set_hostname(Manager *m, const char *hostname) { + int r; + + log_debug("Setting transient hostname: '%s'", strna(hostname)); + + if (free_and_strdup(&m->dynamic_hostname, hostname) < 0) + return log_oom(); + + if (!m->bus || sd_bus_is_ready(m->bus) <= 0) { + log_debug("Not connected to system bus, setting hostname later."); + return 0; + } + + r = sd_bus_call_method_async( + m->bus, + NULL, + "org.freedesktop.hostname1", + "/org/freedesktop/hostname1", + "org.freedesktop.hostname1", + "SetHostname", + set_hostname_handler, + m, + "sb", + hostname, + false); + + if (r < 0) + return log_error_errno(r, "Could not set transient hostname: %m"); + + return 0; +} + +static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + Manager *manager = userdata; + const sd_bus_error *e; + + assert(m); + assert(manager); + + e = sd_bus_message_get_error(m); + if (e) + log_warning_errno(sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message); + + return 1; +} + +int manager_set_timezone(Manager *m, const char *tz) { + int r; + + assert(m); + assert(tz); + + log_debug("Setting system timezone: '%s'", tz); + if (free_and_strdup(&m->dynamic_timezone, tz) < 0) + return log_oom(); + + if (!m->bus || sd_bus_is_ready(m->bus) <= 0) { + log_debug("Not connected to system bus, setting timezone later."); + return 0; + } + + r = sd_bus_call_method_async( + m->bus, + NULL, + "org.freedesktop.timedate1", + "/org/freedesktop/timedate1", + "org.freedesktop.timedate1", + "SetTimezone", + set_timezone_handler, + m, + "sb", + tz, + false); + if (r < 0) + return log_error_errno(r, "Could not set timezone: %m"); + + return 0; +} + +int manager_request_product_uuid(Manager *m, Link *link) { + int r; + + assert(m); + + if (m->has_product_uuid) + return 0; + + log_debug("Requesting product UUID"); + + if (link) { + DUID *duid; + + assert_se(duid = link_get_duid(link)); + + r = set_ensure_allocated(&m->links_requesting_uuid, NULL); + if (r < 0) + return log_oom(); + + r = set_ensure_allocated(&m->duids_requesting_uuid, NULL); + if (r < 0) + return log_oom(); + + r = set_put(m->links_requesting_uuid, link); + if (r < 0) + return log_oom(); + + r = set_put(m->duids_requesting_uuid, duid); + if (r < 0) + return log_oom(); + + link_ref(link); + } + + if (!m->bus || sd_bus_is_ready(m->bus) <= 0) { + log_debug("Not connected to system bus, requesting product UUID later."); + return 0; + } + + r = sd_bus_call_method_async( + m->bus, + NULL, + "org.freedesktop.hostname1", + "/org/freedesktop/hostname1", + "org.freedesktop.hostname1", + "GetProductUUID", + get_product_uuid_handler, + m, + "b", + false); + if (r < 0) + return log_warning_errno(r, "Failed to get product UUID: %m"); + + return 0; +} diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h new file mode 100644 index 00000000..f2f309ff --- /dev/null +++ b/src/network/networkd-manager.h @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-device.h" +#include "sd-event.h" +#include "sd-id128.h" +#include "sd-netlink.h" +#include "sd-resolve.h" + +#include "dhcp-identifier.h" +#include "hashmap.h" +#include "list.h" +#include "time-util.h" + +#include "networkd-address-pool.h" +#include "networkd-link.h" +#include "networkd-network.h" + +struct Manager { + sd_netlink *rtnl; + /* lazy initialized */ + sd_netlink *genl; + sd_event *event; + sd_resolve *resolve; + sd_bus *bus; + sd_device_monitor *device_monitor; + Hashmap *polkit_registry; + + bool enumerating:1; + bool dirty:1; + bool restarting:1; + + Set *dirty_links; + + char *state_file; + LinkOperationalState operational_state; + LinkCarrierState carrier_state; + LinkAddressState address_state; + + Hashmap *links; + Hashmap *netdevs; + OrderedHashmap *networks; + Hashmap *dhcp6_prefixes; + LIST_HEAD(AddressPool, address_pools); + + usec_t network_dirs_ts_usec; + + DUID duid; + sd_id128_t product_uuid; + bool has_product_uuid; + Set *links_requesting_uuid; + Set *duids_requesting_uuid; + + char* dynamic_hostname; + char* dynamic_timezone; + + Set *rules; + Set *rules_foreign; + Set *rules_saved; + + /* For link speed meter*/ + bool use_speed_meter; + sd_event_source *speed_meter_event_source; + usec_t speed_meter_interval_usec; + usec_t speed_meter_usec_new; + usec_t speed_meter_usec_old; + + bool dhcp4_prefix_root_cannot_set_table; +}; + +int manager_new(Manager **ret); +void manager_free(Manager *m); + +int manager_connect_bus(Manager *m); +int manager_start(Manager *m); + +int manager_load_config(Manager *m); +bool manager_should_reload(Manager *m); + +int manager_rtnl_enumerate_links(Manager *m); +int manager_rtnl_enumerate_addresses(Manager *m); +int manager_rtnl_enumerate_neighbors(Manager *m); +int manager_rtnl_enumerate_routes(Manager *m); +int manager_rtnl_enumerate_rules(Manager *m); +int manager_rtnl_enumerate_nexthop(Manager *m); + +int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, void *userdata); +int manager_rtnl_process_neighbor(sd_netlink *nl, sd_netlink_message *message, void *userdata); +int manager_rtnl_process_route(sd_netlink *nl, sd_netlink_message *message, void *userdata); +int manager_rtnl_process_rule(sd_netlink *nl, sd_netlink_message *message, void *userdata); +int manager_rtnl_process_nexthop(sd_netlink *nl, sd_netlink_message *message, void *userdata); + +void manager_dirty(Manager *m); + +int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found); + +Link* manager_find_uplink(Manager *m, Link *exclude); + +int manager_set_hostname(Manager *m, const char *hostname); +int manager_set_timezone(Manager *m, const char *timezone); +int manager_request_product_uuid(Manager *m, Link *link); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c new file mode 100644 index 00000000..402d1acd --- /dev/null +++ b/src/network/networkd-ndisc.c @@ -0,0 +1,808 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Intel Corporation. All rights reserved. +***/ + +#include +#include + +#include "sd-ndisc.h" + +#include "missing_network.h" +#include "networkd-dhcp6.h" +#include "networkd-manager.h" +#include "networkd-ndisc.h" +#include "networkd-route.h" +#include "strv.h" + +#define NDISC_DNSSL_MAX 64U +#define NDISC_RDNSS_MAX 64U +#define NDISC_PREFIX_LFT_MIN 7200U + +static int ndisc_netlink_route_message_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->ndisc_messages > 0); + + link->ndisc_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_error_errno(link, r, "Could not set NDisc route or address: %m"); + link_enter_failed(link); + return 1; + } + + if (link->ndisc_messages == 0) { + link->ndisc_configured = true; + r = link_request_set_routes(link); + if (r < 0) { + link_enter_failed(link); + return 1; + } + link_check_ready(link); + } + + return 1; +} + +static int ndisc_netlink_address_message_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->ndisc_messages > 0); + + link->ndisc_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_error_errno(link, r, "Could not set NDisc route or address: %m"); + link_enter_failed(link); + return 1; + } else if (r >= 0) + (void) manager_rtnl_process_address(rtnl, m, link->manager); + + if (link->ndisc_messages == 0) { + link->ndisc_configured = true; + r = link_request_set_routes(link); + if (r < 0) { + link_enter_failed(link); + return 1; + } + link_check_ready(link); + } + + return 1; +} + +static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { + _cleanup_(route_freep) Route *route = NULL; + union in_addr_union gateway; + uint16_t lifetime; + unsigned preference; + uint32_t mtu; + usec_t time_now; + int r; + Address *address; + Iterator i; + + assert(link); + assert(rt); + + r = sd_ndisc_router_get_lifetime(rt, &lifetime); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); + + if (lifetime == 0) /* not a default router */ + return 0; + + r = sd_ndisc_router_get_address(rt, &gateway.in6); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); + + SET_FOREACH(address, link->addresses, i) { + if (address->family != AF_INET6) + continue; + if (in_addr_equal(AF_INET6, &gateway, &address->in_addr)) { + _cleanup_free_ char *buffer = NULL; + + (void) in_addr_to_string(AF_INET6, &address->in_addr, &buffer); + log_link_debug(link, "No NDisc route added, gateway %s matches local address", + strnull(buffer)); + return 0; + } + } + + SET_FOREACH(address, link->addresses_foreign, i) { + if (address->family != AF_INET6) + continue; + if (in_addr_equal(AF_INET6, &gateway, &address->in_addr)) { + _cleanup_free_ char *buffer = NULL; + + (void) in_addr_to_string(AF_INET6, &address->in_addr, &buffer); + log_link_debug(link, "No NDisc route added, gateway %s matches local address", + strnull(buffer)); + return 0; + } + } + + r = sd_ndisc_router_get_preference(rt, &preference); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m"); + + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); + + r = sd_ndisc_router_get_mtu(rt, &mtu); + if (r == -ENODATA) + mtu = 0; + else if (r < 0) + return log_link_warning_errno(link, r, "Failed to get default router MTU from RA: %m"); + + r = route_new(&route); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate route: %m"); + + route->family = AF_INET6; + route->table = link_get_ipv6_accept_ra_route_table(link); + route->priority = link->network->dhcp_route_metric; + route->protocol = RTPROT_RA; + route->pref = preference; + route->gw = gateway; + route->lifetime = time_now + lifetime * USEC_PER_SEC; + route->mtu = mtu; + + r = route_configure(route, link, ndisc_netlink_route_message_handler); + if (r < 0) { + log_link_warning_errno(link, r, "Could not set default route: %m"); + link_enter_failed(link); + return r; + } + if (r > 0) + link->ndisc_messages++; + + return 0; +} + +static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) { + _cleanup_(address_freep) Address *address = NULL; + Address *existing_address; + uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining; + usec_t time_now; + unsigned prefixlen; + int r; + + assert(link); + assert(rt); + + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); + + r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix length: %m"); + + r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m"); + + r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m"); + + /* The preferred lifetime is never greater than the valid lifetime */ + if (lifetime_preferred > lifetime_valid) + return 0; + + r = address_new(&address); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate address: %m"); + + address->family = AF_INET6; + r = sd_ndisc_router_prefix_get_address(rt, &address->in_addr.in6); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix address: %m"); + + if (in_addr_is_null(AF_INET6, (const union in_addr_union *) &link->network->ipv6_token) == 0) + memcpy(((char *)&address->in_addr.in6) + 8, ((char *)&link->network->ipv6_token) + 8, 8); + else { + /* see RFC4291 section 2.5.1 */ + address->in_addr.in6.s6_addr[8] = link->mac.ether_addr_octet[0]; + address->in_addr.in6.s6_addr[8] ^= 1 << 1; + address->in_addr.in6.s6_addr[9] = link->mac.ether_addr_octet[1]; + address->in_addr.in6.s6_addr[10] = link->mac.ether_addr_octet[2]; + address->in_addr.in6.s6_addr[11] = 0xff; + address->in_addr.in6.s6_addr[12] = 0xfe; + address->in_addr.in6.s6_addr[13] = link->mac.ether_addr_octet[3]; + address->in_addr.in6.s6_addr[14] = link->mac.ether_addr_octet[4]; + address->in_addr.in6.s6_addr[15] = link->mac.ether_addr_octet[5]; + } + address->prefixlen = prefixlen; + address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR; + address->cinfo.ifa_prefered = lifetime_preferred; + + /* see RFC4862 section 5.5.3.e */ + r = address_get(link, address->family, &address->in_addr, address->prefixlen, &existing_address); + if (r > 0) { + lifetime_remaining = existing_address->cinfo.tstamp / 100 + existing_address->cinfo.ifa_valid - time_now / USEC_PER_SEC; + if (lifetime_valid > NDISC_PREFIX_LFT_MIN || lifetime_valid > lifetime_remaining) + address->cinfo.ifa_valid = lifetime_valid; + else if (lifetime_remaining <= NDISC_PREFIX_LFT_MIN) + address->cinfo.ifa_valid = lifetime_remaining; + else + address->cinfo.ifa_valid = NDISC_PREFIX_LFT_MIN; + } else if (lifetime_valid > 0) + address->cinfo.ifa_valid = lifetime_valid; + else + return 0; /* see RFC4862 section 5.5.3.d */ + + if (address->cinfo.ifa_valid == 0) + return 0; + + r = address_configure(address, link, ndisc_netlink_address_message_handler, true); + if (r < 0) { + log_link_warning_errno(link, r, "Could not set SLAAC address: %m"); + link_enter_failed(link); + return r; + } + if (r > 0) + link->ndisc_messages++; + + return 0; +} + +static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { + _cleanup_(route_freep) Route *route = NULL; + usec_t time_now; + uint32_t lifetime; + unsigned prefixlen; + int r; + + assert(link); + assert(rt); + + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); + + r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix length: %m"); + + r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix lifetime: %m"); + + r = route_new(&route); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate route: %m"); + + route->family = AF_INET6; + route->table = link_get_ipv6_accept_ra_route_table(link); + route->priority = link->network->dhcp_route_metric; + route->protocol = RTPROT_RA; + route->flags = RTM_F_PREFIX; + route->dst_prefixlen = prefixlen; + route->lifetime = time_now + lifetime * USEC_PER_SEC; + + r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix address: %m"); + + r = route_configure(route, link, ndisc_netlink_route_message_handler); + if (r < 0) { + log_link_warning_errno(link, r, "Could not set prefix route: %m"); + link_enter_failed(link); + return r; + } + if (r > 0) + link->ndisc_messages++; + + return 0; +} + +static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { + _cleanup_(route_freep) Route *route = NULL; + struct in6_addr gateway; + uint32_t lifetime; + unsigned preference, prefixlen; + usec_t time_now; + int r; + + assert(link); + + r = sd_ndisc_router_route_get_lifetime(rt, &lifetime); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); + + if (lifetime == 0) + return 0; + + r = sd_ndisc_router_get_address(rt, &gateway); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); + + r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get route prefix length: %m"); + + r = sd_ndisc_router_route_get_preference(rt, &preference); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m"); + + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); + + r = route_new(&route); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate route: %m"); + + route->family = AF_INET6; + route->table = link_get_ipv6_accept_ra_route_table(link); + route->protocol = RTPROT_RA; + route->pref = preference; + route->gw.in6 = gateway; + route->dst_prefixlen = prefixlen; + route->lifetime = time_now + lifetime * USEC_PER_SEC; + + r = sd_ndisc_router_route_get_address(rt, &route->dst.in6); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get route address: %m"); + + r = route_configure(route, link, ndisc_netlink_route_message_handler); + if (r < 0) { + log_link_warning_errno(link, r, "Could not set additional route: %m"); + link_enter_failed(link); + return r; + } + if (r > 0) + link->ndisc_messages++; + + return 0; +} + +static void ndisc_rdnss_hash_func(const NDiscRDNSS *x, struct siphash *state) { + siphash24_compress(&x->address, sizeof(x->address), state); +} + +static int ndisc_rdnss_compare_func(const NDiscRDNSS *a, const NDiscRDNSS *b) { + return memcmp(&a->address, &b->address, sizeof(a->address)); +} + +DEFINE_PRIVATE_HASH_OPS(ndisc_rdnss_hash_ops, NDiscRDNSS, ndisc_rdnss_hash_func, ndisc_rdnss_compare_func); + +static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { + uint32_t lifetime; + const struct in6_addr *a; + usec_t time_now; + int i, n, r; + + assert(link); + assert(rt); + + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); + + r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m"); + + n = sd_ndisc_router_rdnss_get_addresses(rt, &a); + if (n < 0) + return log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m"); + + for (i = 0; i < n; i++) { + _cleanup_free_ NDiscRDNSS *x = NULL; + NDiscRDNSS d = { + .address = a[i], + }, *y; + + if (lifetime == 0) { + (void) set_remove(link->ndisc_rdnss, &d); + link_dirty(link); + continue; + } + + y = set_get(link->ndisc_rdnss, &d); + if (y) { + y->valid_until = time_now + lifetime * USEC_PER_SEC; + continue; + } + + ndisc_vacuum(link); + + if (set_size(link->ndisc_rdnss) >= NDISC_RDNSS_MAX) { + log_link_warning(link, "Too many RDNSS records per link, ignoring."); + continue; + } + + r = set_ensure_allocated(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops); + if (r < 0) + return log_oom(); + + x = new(NDiscRDNSS, 1); + if (!x) + return log_oom(); + + *x = (NDiscRDNSS) { + .address = a[i], + .valid_until = time_now + lifetime * USEC_PER_SEC, + }; + + r = set_put(link->ndisc_rdnss, x); + if (r < 0) + return log_oom(); + + TAKE_PTR(x); + + assert(r > 0); + link_dirty(link); + } + + return 0; +} + +static void ndisc_dnssl_hash_func(const NDiscDNSSL *x, struct siphash *state) { + siphash24_compress(NDISC_DNSSL_DOMAIN(x), strlen(NDISC_DNSSL_DOMAIN(x)), state); +} + +static int ndisc_dnssl_compare_func(const NDiscDNSSL *a, const NDiscDNSSL *b) { + return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b)); +} + +DEFINE_PRIVATE_HASH_OPS(ndisc_dnssl_hash_ops, NDiscDNSSL, ndisc_dnssl_hash_func, ndisc_dnssl_compare_func); + +static void ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { + _cleanup_strv_free_ char **l = NULL; + uint32_t lifetime; + usec_t time_now; + char **i; + int r; + + assert(link); + assert(rt); + + r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); + return; + } + + r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m"); + return; + } + + r = sd_ndisc_router_dnssl_get_domains(rt, &l); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to get RDNSS addresses: %m"); + return; + } + + STRV_FOREACH(i, l) { + _cleanup_free_ NDiscDNSSL *s; + NDiscDNSSL *x; + + s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*i) + 1); + if (!s) { + log_oom(); + return; + } + + strcpy(NDISC_DNSSL_DOMAIN(s), *i); + + if (lifetime == 0) { + (void) set_remove(link->ndisc_dnssl, s); + link_dirty(link); + continue; + } + + x = set_get(link->ndisc_dnssl, s); + if (x) { + x->valid_until = time_now + lifetime * USEC_PER_SEC; + continue; + } + + ndisc_vacuum(link); + + if (set_size(link->ndisc_dnssl) >= NDISC_DNSSL_MAX) { + log_link_warning(link, "Too many DNSSL records per link, ignoring."); + continue; + } + + r = set_ensure_allocated(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops); + if (r < 0) { + log_oom(); + return; + } + + s->valid_until = time_now + lifetime * USEC_PER_SEC; + + r = set_put(link->ndisc_dnssl, s); + if (r < 0) { + log_oom(); + return; + } + + s = NULL; + assert(r > 0); + link_dirty(link); + } +} + +static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { + int r; + + assert(link); + assert(link->network); + assert(rt); + + r = sd_ndisc_router_option_rewind(rt); + for (;;) { + uint8_t type; + + if (r < 0) + return log_link_warning_errno(link, r, "Failed to iterate through options: %m"); + if (r == 0) /* EOF */ + break; + + r = sd_ndisc_router_option_get_type(rt, &type); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get RA option type: %m"); + + switch (type) { + + case SD_NDISC_OPTION_PREFIX_INFORMATION: { + union in_addr_union a; + uint8_t flags; + + r = sd_ndisc_router_prefix_get_address(rt, &a.in6); + if (r < 0) + return log_link_error_errno(link, r, "Failed to get prefix address: %m"); + + if (set_contains(link->network->ndisc_black_listed_prefix, &a.in6)) { + if (DEBUG_LOGGING) { + _cleanup_free_ char *b = NULL; + + (void) in_addr_to_string(AF_INET6, &a, &b); + log_link_debug(link, "Prefix '%s' is black listed, ignoring", strna(b)); + } + + break; + } + + r = sd_ndisc_router_prefix_get_flags(rt, &flags); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get RA prefix flags: %m"); + + if (link->network->ipv6_accept_ra_use_onlink_prefix && + FLAGS_SET(flags, ND_OPT_PI_FLAG_ONLINK)) + (void) ndisc_router_process_onlink_prefix(link, rt); + + if (link->network->ipv6_accept_ra_use_autonomous_prefix && + FLAGS_SET(flags, ND_OPT_PI_FLAG_AUTO)) + (void) ndisc_router_process_autonomous_prefix(link, rt); + + break; + } + + case SD_NDISC_OPTION_ROUTE_INFORMATION: + (void) ndisc_router_process_route(link, rt); + break; + + case SD_NDISC_OPTION_RDNSS: + if (link->network->ipv6_accept_ra_use_dns) + (void) ndisc_router_process_rdnss(link, rt); + break; + + case SD_NDISC_OPTION_DNSSL: + if (link->network->ipv6_accept_ra_use_dns) + (void) ndisc_router_process_dnssl(link, rt); + break; + } + + r = sd_ndisc_router_option_next(rt); + } + + return 0; +} + +static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { + uint64_t flags; + int r; + + assert(link); + assert(link->network); + assert(link->manager); + assert(rt); + + r = sd_ndisc_router_get_flags(rt, &flags); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to get RA flags: %m"); + + if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) { + /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */ + r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED)); + if (r < 0 && r != -EBUSY) + log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m"); + else { + log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request"); + r = 0; + } + } + + (void) ndisc_router_process_default(link, rt); + (void) ndisc_router_process_options(link, rt); + + return r; +} + +static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) { + Link *link = userdata; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return; + + switch (event) { + + case SD_NDISC_EVENT_ROUTER: + (void) ndisc_router_handler(link, rt); + break; + + case SD_NDISC_EVENT_TIMEOUT: + link->ndisc_configured = true; + link_check_ready(link); + + break; + default: + log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event); + } +} + +int ndisc_configure(Link *link) { + int r; + + assert(link); + + r = sd_ndisc_new(&link->ndisc); + if (r < 0) + return r; + + r = sd_ndisc_attach_event(link->ndisc, NULL, 0); + if (r < 0) + return r; + + r = sd_ndisc_set_mac(link->ndisc, &link->mac); + if (r < 0) + return r; + + r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex); + if (r < 0) + return r; + + r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link); + if (r < 0) + return r; + + return 0; +} + +void ndisc_vacuum(Link *link) { + NDiscRDNSS *r; + NDiscDNSSL *d; + Iterator i; + usec_t time_now; + + assert(link); + + /* Removes all RDNSS and DNSSL entries whose validity time has passed */ + + time_now = now(clock_boottime_or_monotonic()); + + SET_FOREACH(r, link->ndisc_rdnss, i) + if (r->valid_until < time_now) { + free(set_remove(link->ndisc_rdnss, r)); + link_dirty(link); + } + + SET_FOREACH(d, link->ndisc_dnssl, i) + if (d->valid_until < time_now) { + free(set_remove(link->ndisc_dnssl, d)); + link_dirty(link); + } +} + +void ndisc_flush(Link *link) { + assert(link); + + /* Removes all RDNSS and DNSSL entries, without exception */ + + link->ndisc_rdnss = set_free_free(link->ndisc_rdnss); + link->ndisc_dnssl = set_free_free(link->ndisc_dnssl); +} + +int config_parse_ndisc_black_listed_prefix( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + const char *p; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + network->ndisc_black_listed_prefix = set_free_free(network->ndisc_black_listed_prefix); + return 0; + } + + for (p = rvalue;;) { + _cleanup_free_ char *n = NULL; + _cleanup_free_ struct in6_addr *a = NULL; + union in_addr_union ip; + + r = extract_first_word(&p, &n, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse NDISC black listed prefix, ignoring assignment: %s", + rvalue); + return 0; + } + if (r == 0) + return 0; + + r = in_addr_from_string(AF_INET6, n, &ip); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "NDISC black listed prefix is invalid, ignoring assignment: %s", n); + continue; + } + + if (set_contains(network->ndisc_black_listed_prefix, &ip.in6)) + continue; + + r = set_ensure_allocated(&network->ndisc_black_listed_prefix, &in6_addr_hash_ops); + if (r < 0) + return log_oom(); + + a = newdup(struct in6_addr, &ip.in6, 1); + if (!a) + return log_oom(); + + r = set_put(network->ndisc_black_listed_prefix, a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n); + continue; + } + + TAKE_PTR(a); + } + + return 0; +} diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h new file mode 100644 index 00000000..dc0a44f5 --- /dev/null +++ b/src/network/networkd-ndisc.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "networkd-link.h" +#include "time-util.h" + +typedef struct NDiscRDNSS { + usec_t valid_until; + struct in6_addr address; +} NDiscRDNSS; + +typedef struct NDiscDNSSL { + usec_t valid_until; + /* The domain name follows immediately. */ +} NDiscDNSSL; + +static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) { + return ((char*) n) + ALIGN(sizeof(NDiscDNSSL)); +} + +int ndisc_configure(Link *link); +void ndisc_vacuum(Link *link); +void ndisc_flush(Link *link); + +CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_black_listed_prefix); diff --git a/src/network/networkd-neighbor.c b/src/network/networkd-neighbor.c new file mode 100644 index 00000000..fd61ebd5 --- /dev/null +++ b/src/network/networkd-neighbor.c @@ -0,0 +1,506 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "conf-parser.h" +#include "ether-addr-util.h" +#include "hashmap.h" +#include "in-addr-util.h" +#include "netlink-util.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "networkd-neighbor.h" +#include "set.h" + +void neighbor_free(Neighbor *neighbor) { + if (!neighbor) + return; + + if (neighbor->network) { + LIST_REMOVE(neighbors, neighbor->network->neighbors, neighbor); + assert(neighbor->network->n_neighbors > 0); + neighbor->network->n_neighbors--; + + if (neighbor->section) + hashmap_remove(neighbor->network->neighbors_by_section, neighbor->section); + } + + network_config_section_free(neighbor->section); + + if (neighbor->link) { + set_remove(neighbor->link->neighbors, neighbor); + set_remove(neighbor->link->neighbors_foreign, neighbor); + } + + free(neighbor); +} + +static int neighbor_new_static(Network *network, const char *filename, unsigned section_line, Neighbor **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(neighbor_freep) Neighbor *neighbor = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + neighbor = hashmap_get(network->neighbors_by_section, n); + if (neighbor) { + *ret = TAKE_PTR(neighbor); + + return 0; + } + } + + neighbor = new(Neighbor, 1); + if (!neighbor) + return -ENOMEM; + + *neighbor = (Neighbor) { + .network = network, + .family = AF_UNSPEC, + }; + + LIST_APPEND(neighbors, network->neighbors, neighbor); + network->n_neighbors++; + + if (filename) { + neighbor->section = TAKE_PTR(n); + + r = hashmap_ensure_allocated(&network->neighbors_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(network->neighbors_by_section, neighbor->section, neighbor); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(neighbor); + + return 0; +} + +static int neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->neighbor_messages > 0); + + link->neighbor_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) + /* Neighbor may not exist yet. So, do not enter failed state here. */ + log_link_warning_errno(link, r, "Could not set neighbor, ignoring: %m"); + + if (link->neighbor_messages == 0) { + log_link_debug(link, "Neighbors set"); + link->neighbors_configured = true; + link_check_ready(link); + } + + return 1; +} + +int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(neighbor); + assert(link); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + + r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, + link->ifindex, neighbor->family); + if (r < 0) + return log_error_errno(r, "Could not allocate RTM_NEWNEIGH message: %m"); + + r = sd_rtnl_message_neigh_set_state(req, NUD_PERMANENT); + if (r < 0) + return log_error_errno(r, "Could not set state: %m"); + + r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE); + if (r < 0) + return log_error_errno(r, "Could not set flags: %m"); + + r = sd_netlink_message_append_data(req, NDA_LLADDR, &neighbor->lladdr, neighbor->lladdr_size); + if (r < 0) + return log_error_errno(r, "Could not append NDA_LLADDR attribute: %m"); + + r = netlink_message_append_in_addr_union(req, NDA_DST, neighbor->family, &neighbor->in_addr); + if (r < 0) + return log_error_errno(r, "Could not append NDA_DST attribute: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_configure_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_error_errno(r, "Could not send rtnetlink message: %m"); + + link->neighbor_messages++; + link_ref(link); + + r = neighbor_add(link, neighbor->family, &neighbor->in_addr, &neighbor->lladdr, neighbor->lladdr_size, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Could not add neighbor: %m"); + + return 0; +} + +static int neighbor_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -ESRCH) + /* Neighbor may not exist because it already got deleted, ignore that. */ + log_link_warning_errno(link, r, "Could not remove neighbor: %m"); + + return 1; +} + +int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(neighbor); + assert(link); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + + r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_DELNEIGH, + link->ifindex, neighbor->family); + if (r < 0) + return log_error_errno(r, "Could not allocate RTM_DELNEIGH message: %m"); + + r = netlink_message_append_in_addr_union(req, NDA_DST, neighbor->family, &neighbor->in_addr); + if (r < 0) + return log_error_errno(r, "Could not append NDA_DST attribute: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, callback ?: neighbor_remove_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_error_errno(r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static void neighbor_hash_func(const Neighbor *neighbor, struct siphash *state) { + assert(neighbor); + + siphash24_compress(&neighbor->family, sizeof(neighbor->family), state); + siphash24_compress(&neighbor->lladdr_size, sizeof(neighbor->lladdr_size), state); + + switch (neighbor->family) { + case AF_INET: + case AF_INET6: + /* Equality of neighbors are given by the pair (addr,lladdr) */ + siphash24_compress(&neighbor->in_addr, FAMILY_ADDRESS_SIZE(neighbor->family), state); + break; + default: + /* treat any other address family as AF_UNSPEC */ + break; + } + + siphash24_compress(&neighbor->lladdr, neighbor->lladdr_size, state); +} + +static int neighbor_compare_func(const Neighbor *a, const Neighbor *b) { + int r; + + r = CMP(a->family, b->family); + if (r != 0) + return r; + + r = CMP(a->lladdr_size, b->lladdr_size); + if (r != 0) + return r; + + switch (a->family) { + case AF_INET: + case AF_INET6: + r = memcmp(&a->in_addr, &b->in_addr, FAMILY_ADDRESS_SIZE(a->family)); + if (r != 0) + return r; + } + + return memcmp(&a->lladdr, &b->lladdr, a->lladdr_size); +} + +DEFINE_PRIVATE_HASH_OPS(neighbor_hash_ops, Neighbor, neighbor_hash_func, neighbor_compare_func); + +int neighbor_get(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) { + Neighbor neighbor, *existing; + + assert(link); + assert(addr); + assert(lladdr); + + neighbor = (Neighbor) { + .family = family, + .in_addr = *addr, + .lladdr = *lladdr, + .lladdr_size = lladdr_size, + }; + + existing = set_get(link->neighbors, &neighbor); + if (existing) { + if (ret) + *ret = existing; + return 1; + } + + existing = set_get(link->neighbors_foreign, &neighbor); + if (existing) { + if (ret) + *ret = existing; + return 0; + } + + return -ENOENT; +} + +static int neighbor_add_internal(Link *link, Set **neighbors, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) { + _cleanup_(neighbor_freep) Neighbor *neighbor = NULL; + int r; + + assert(link); + assert(neighbors); + assert(addr); + assert(lladdr); + + neighbor = new(Neighbor, 1); + if (!neighbor) + return -ENOMEM; + + *neighbor = (Neighbor) { + .family = family, + .in_addr = *addr, + .lladdr = *lladdr, + .lladdr_size = lladdr_size, + }; + + r = set_ensure_allocated(neighbors, &neighbor_hash_ops); + if (r < 0) + return r; + + r = set_put(*neighbors, neighbor); + if (r < 0) + return r; + if (r == 0) + return -EEXIST; + + neighbor->link = link; + + if (ret) + *ret = neighbor; + + neighbor = NULL; + + return 0; +} + +int neighbor_add(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) { + Neighbor *neighbor; + int r; + + r = neighbor_get(link, family, addr, lladdr, lladdr_size, &neighbor); + if (r == -ENOENT) { + /* Neighbor doesn't exist, make a new one */ + r = neighbor_add_internal(link, &link->neighbors, family, addr, lladdr, lladdr_size, &neighbor); + if (r < 0) + return r; + } else if (r == 0) { + /* Neighbor is foreign, claim it as recognized */ + r = set_ensure_allocated(&link->neighbors, &neighbor_hash_ops); + if (r < 0) + return r; + + r = set_put(link->neighbors, neighbor); + if (r < 0) + return r; + + set_remove(link->neighbors_foreign, neighbor); + } else if (r == 1) { + /* Neighbor already exists */ + } else + return r; + + if (ret) + *ret = neighbor; + return 0; +} + +int neighbor_add_foreign(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret) { + return neighbor_add_internal(link, &link->neighbors_foreign, family, addr, lladdr, lladdr_size, ret); +} + +bool neighbor_equal(const Neighbor *n1, const Neighbor *n2) { + if (n1 == n2) + return true; + + if (!n1 || !n2) + return false; + + return neighbor_compare_func(n1, n2) == 0; +} + +int neighbor_section_verify(Neighbor *neighbor) { + if (section_is_invalid(neighbor->section)) + return -EINVAL; + + if (neighbor->family == AF_UNSPEC) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Neighbor section without Address= configured. " + "Ignoring [Neighbor] section from line %u.", + neighbor->section->filename, neighbor->section->line); + + if (neighbor->lladdr_size == 0) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Neighbor section without LinkLayerAddress= configured. " + "Ignoring [Neighbor] section from line %u.", + neighbor->section->filename, neighbor->section->line); + + return 0; +} + +int config_parse_neighbor_address( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = neighbor_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = in_addr_from_string_auto(rvalue, &n->family, &n->in_addr); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Neighbor Address is invalid, ignoring assignment: %s", rvalue); + return 0; + } + + TAKE_PTR(n); + + return 0; +} + +int config_parse_neighbor_lladdr( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL; + int family, r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = neighbor_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = ether_addr_from_string(rvalue, &n->lladdr.mac); + if (r >= 0) + n->lladdr_size = sizeof(n->lladdr.mac); + else { + r = in_addr_from_string_auto(rvalue, &family, &n->lladdr.ip); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Neighbor LinkLayerAddress= is invalid, ignoring assignment: %s", + rvalue); + return 0; + } + n->lladdr_size = family == AF_INET ? sizeof(n->lladdr.ip.in) : sizeof(n->lladdr.ip.in6); + } + + TAKE_PTR(n); + + return 0; +} + +int config_parse_neighbor_hwaddr( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(neighbor_free_or_set_invalidp) Neighbor *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = neighbor_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = ether_addr_from_string(rvalue, &n->lladdr.mac); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Neighbor MACAddress= is invalid, ignoring assignment: %s", rvalue); + return 0; + } + + n->lladdr_size = sizeof(n->lladdr.mac); + TAKE_PTR(n); + + return 0; +} diff --git a/src/network/networkd-neighbor.h b/src/network/networkd-neighbor.h new file mode 100644 index 00000000..97ee1f6d --- /dev/null +++ b/src/network/networkd-neighbor.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-netlink.h" + +#include "conf-parser.h" +#include "ether-addr-util.h" +#include "in-addr-util.h" +#include "list.h" +#include "macro.h" + +typedef struct Neighbor Neighbor; + +#include "networkd-link.h" +#include "networkd-network.h" +#include "networkd-util.h" + +union lladdr_union { + struct ether_addr mac; + union in_addr_union ip; +}; + +struct Neighbor { + Network *network; + Link *link; + NetworkConfigSection *section; + + int family; + union in_addr_union in_addr; + union lladdr_union lladdr; + size_t lladdr_size; + + LIST_FIELDS(Neighbor, neighbors); +}; + +void neighbor_free(Neighbor *neighbor); + +DEFINE_NETWORK_SECTION_FUNCTIONS(Neighbor, neighbor_free); + +int neighbor_configure(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback); +int neighbor_remove(Neighbor *neighbor, Link *link, link_netlink_message_handler_t callback); + +int neighbor_get(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret); +int neighbor_add(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret); +int neighbor_add_foreign(Link *link, int family, const union in_addr_union *addr, const union lladdr_union *lladdr, size_t lladdr_size, Neighbor **ret); +bool neighbor_equal(const Neighbor *n1, const Neighbor *n2); + +int neighbor_section_verify(Neighbor *neighbor); + +CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address); +CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_hwaddr); +CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_lladdr); diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c new file mode 100644 index 00000000..a895f726 --- /dev/null +++ b/src/network/networkd-network-bus.c @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "ether-addr-util.h" +#include "networkd-manager.h" +#include "networkd-network-bus.h" +#include "string-util.h" +#include "strv.h" + +static int property_get_ether_addrs( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + char buf[ETHER_ADDR_TO_STRING_MAX]; + const struct ether_addr *p; + Iterator i; + Set *s; + int r; + + assert(bus); + assert(reply); + assert(userdata); + + s = *(Set **) userdata; + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + SET_FOREACH(p, s, i) { + r = sd_bus_message_append(reply, "s", ether_addr_to_string(p, buf)); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +const sd_bus_vtable network_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("Description", "s", NULL, offsetof(Network, description), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Network, filename), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, offsetof(Network, match_mac), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MatchPath", "as", NULL, offsetof(Network, match_path), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MatchDriver", "as", NULL, offsetof(Network, match_driver), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MatchType", "as", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("MatchName", "as", NULL, offsetof(Network, match_name), SD_BUS_VTABLE_PROPERTY_CONST), + + SD_BUS_VTABLE_END +}; + +static char *network_bus_path(Network *network) { + _cleanup_free_ char *name = NULL; + char *networkname, *d, *path; + int r; + + assert(network); + assert(network->filename); + + name = strdup(network->filename); + if (!name) + return NULL; + + networkname = basename(name); + + d = strrchr(networkname, '.'); + if (!d) + return NULL; + + assert(streq(d, ".network")); + + *d = '\0'; + + r = sd_bus_path_encode("/org/freedesktop/network1/network", networkname, &path); + if (r < 0) + return NULL; + + return path; +} + +int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + Network *network; + Iterator i; + int r; + + assert(bus); + assert(path); + assert(m); + assert(nodes); + + ORDERED_HASHMAP_FOREACH(network, m->networks, i) { + char *p; + + p = network_bus_path(network); + if (!p) + return -ENOMEM; + + r = strv_consume(&l, p); + if (r < 0) + return r; + } + + *nodes = TAKE_PTR(l); + + return 1; +} + +int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + Manager *m = userdata; + Network *network; + _cleanup_free_ char *name = NULL; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(m); + assert(found); + + r = sd_bus_path_decode(path, "/org/freedesktop/network1/network", &name); + if (r < 0) + return 0; + + r = network_get_by_name(m, name, &network); + if (r < 0) + return 0; + + *found = network; + + return 1; +} diff --git a/src/network/networkd-network-bus.h b/src/network/networkd-network-bus.h new file mode 100644 index 00000000..650e145d --- /dev/null +++ b/src/network/networkd-network-bus.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +typedef struct Link Link; + +extern const sd_bus_vtable network_vtable[]; + +int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); +int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf new file mode 100644 index 00000000..f7e68be1 --- /dev/null +++ b/src/network/networkd-network-gperf.gperf @@ -0,0 +1,281 @@ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif +#include +#include "conf-parser.h" +#include "netem.h" +#include "network-internal.h" +#include "networkd-conf.h" +#include "networkd-dhcp-common.h" +#include "networkd-dhcp-server.h" +#include "networkd-dhcp4.h" +#include "networkd-ipv4ll.h" +#include "networkd-ndisc.h" +#include "networkd-network.h" +#include "qdisc.h" +#include "vlan-util.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name network_network_gperf_hash +%define lookup-function-name network_network_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +Match.MACAddress, config_parse_hwaddrs, 0, offsetof(Network, match_mac) +Match.Path, config_parse_match_strv, 0, offsetof(Network, match_path) +Match.Driver, config_parse_match_strv, 0, offsetof(Network, match_driver) +Match.Type, config_parse_match_strv, 0, offsetof(Network, match_type) +Match.WLANInterfaceType, config_parse_match_strv, 0, offsetof(Network, match_wlan_iftype) +Match.SSID, config_parse_match_strv, 0, offsetof(Network, match_ssid) +Match.BSSID, config_parse_hwaddrs, 0, offsetof(Network, match_bssid) +Match.Name, config_parse_match_ifnames, 0, offsetof(Network, match_name) +Match.Property, config_parse_match_property, 0, offsetof(Network, match_property) +Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions) +Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, conditions) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, conditions) +Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(Network, conditions) +Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, conditions) +Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac) +Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(Network, mtu) +Link.ARP, config_parse_tristate, 0, offsetof(Network, arp) +Link.Multicast, config_parse_tristate, 0, offsetof(Network, multicast) +Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast) +Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged) +Link.RequiredForOnline, config_parse_required_for_online, 0, 0 +Network.Description, config_parse_string, 0, offsetof(Network, description) +Network.Bridge, config_parse_ifname, 0, offsetof(Network, bridge_name) +Network.Bond, config_parse_ifname, 0, offsetof(Network, bond_name) +Network.VLAN, config_parse_stacked_netdev, NETDEV_KIND_VLAN, offsetof(Network, stacked_netdev_names) +Network.MACVLAN, config_parse_stacked_netdev, NETDEV_KIND_MACVLAN, offsetof(Network, stacked_netdev_names) +Network.MACVTAP, config_parse_stacked_netdev, NETDEV_KIND_MACVTAP, offsetof(Network, stacked_netdev_names) +Network.IPVLAN, config_parse_stacked_netdev, NETDEV_KIND_IPVLAN, offsetof(Network, stacked_netdev_names) +Network.IPVTAP, config_parse_stacked_netdev, NETDEV_KIND_IPVTAP, offsetof(Network, stacked_netdev_names) +Network.VXLAN, config_parse_stacked_netdev, NETDEV_KIND_VXLAN, offsetof(Network, stacked_netdev_names) +Network.L2TP, config_parse_stacked_netdev, NETDEV_KIND_L2TP, offsetof(Network, stacked_netdev_names) +Network.MACsec, config_parse_stacked_netdev, NETDEV_KIND_MACSEC, offsetof(Network, stacked_netdev_names) +Network.Tunnel, config_parse_stacked_netdev, _NETDEV_KIND_TUNNEL, offsetof(Network, stacked_netdev_names) +Network.Xfrm, config_parse_stacked_netdev, NETDEV_KIND_XFRM, offsetof(Network, stacked_netdev_names) +Network.VRF, config_parse_ifname, 0, offsetof(Network, vrf_name) +Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp) +Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server) +Network.LinkLocalAddressing, config_parse_link_local_address_family, 0, offsetof(Network, link_local) +Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route) +Network.DefaultRouteOnDevice, config_parse_bool, 0, offsetof(Network, default_route_on_device) +Network.IPv6Token, config_parse_ipv6token, 0, offsetof(Network, ipv6_token) +Network.LLDP, config_parse_lldp_mode, 0, offsetof(Network, lldp_mode) +Network.EmitLLDP, config_parse_lldp_emit, 0, offsetof(Network, lldp_emit) +Network.Address, config_parse_address, 0, 0 +Network.Gateway, config_parse_gateway, 0, 0 +Network.Domains, config_parse_domains, 0, 0 +Network.DNS, config_parse_dns, 0, 0 +Network.DNSDefaultRoute, config_parse_tristate, 0, offsetof(Network, dns_default_route) +Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr) +Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns) +Network.DNSOverTLS, config_parse_dns_over_tls_mode, 0, offsetof(Network, dns_over_tls_mode) +Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode) +Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, 0 +Network.NTP, config_parse_ntp, 0, offsetof(Network, ntp) +Network.IPForward, config_parse_address_family_with_kernel, 0, offsetof(Network, ip_forward) +Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade) +Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions) +Network.IPv6AcceptRA, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra) +Network.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra) +Network.IPv6DuplicateAddressDetection, config_parse_int, 0, offsetof(Network, ipv6_dad_transmits) +Network.IPv6HopLimit, config_parse_int, 0, offsetof(Network, ipv6_hop_limit) +Network.IPv6ProxyNDP, config_parse_tristate, 0, offsetof(Network, ipv6_proxy_ndp) +Network.IPv6MTUBytes, config_parse_mtu, AF_INET6, offsetof(Network, ipv6_mtu) +Network.ActiveSlave, config_parse_bool, 0, offsetof(Network, active_slave) +Network.PrimarySlave, config_parse_bool, 0, offsetof(Network, primary_slave) +Network.IPv4ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp) +Network.ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp) +Network.IPv6ProxyNDPAddress, config_parse_ipv6_proxy_ndp_address, 0, 0 +Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier) +Network.ConfigureWithoutCarrier, config_parse_bool, 0, offsetof(Network, configure_without_carrier) +Network.IgnoreCarrierLoss, config_parse_bool, 0, offsetof(Network, ignore_carrier_loss) +Network.KeepConfiguration, config_parse_keep_configuration, 0, offsetof(Network, keep_configuration) +Address.Address, config_parse_address, 0, 0 +Address.Peer, config_parse_address, 0, 0 +Address.Broadcast, config_parse_broadcast, 0, 0 +Address.Label, config_parse_label, 0, 0 +Address.PreferredLifetime, config_parse_lifetime, 0, 0 +Address.HomeAddress, config_parse_address_flags, 0, 0 +Address.DuplicateAddressDetection, config_parse_address_flags, 0, 0 +Address.ManageTemporaryAddress, config_parse_address_flags, 0, 0 +Address.PrefixRoute, config_parse_address_flags, 0, 0 /* deprecated */ +Address.AddPrefixRoute, config_parse_address_flags, 0, 0 +Address.AutoJoin, config_parse_address_flags, 0, 0 +Address.Scope, config_parse_address_scope, 0, 0 +IPv6AddressLabel.Prefix, config_parse_address_label_prefix, 0, 0 +IPv6AddressLabel.Label, config_parse_address_label, 0, 0 +Neighbor.Address, config_parse_neighbor_address, 0, 0 +Neighbor.LinkLayerAddress, config_parse_neighbor_lladdr, 0, 0 +Neighbor.MACAddress, config_parse_neighbor_hwaddr, 0, 0 /* deprecated */ +RoutingPolicyRule.TypeOfService, config_parse_routing_policy_rule_tos, 0, 0 +RoutingPolicyRule.Priority, config_parse_routing_policy_rule_priority, 0, 0 +RoutingPolicyRule.Table, config_parse_routing_policy_rule_table, 0, 0 +RoutingPolicyRule.FirewallMark, config_parse_routing_policy_rule_fwmark_mask, 0, 0 +RoutingPolicyRule.From, config_parse_routing_policy_rule_prefix, 0, 0 +RoutingPolicyRule.To, config_parse_routing_policy_rule_prefix, 0, 0 +RoutingPolicyRule.IncomingInterface, config_parse_routing_policy_rule_device, 0, 0 +RoutingPolicyRule.OutgoingInterface, config_parse_routing_policy_rule_device, 0, 0 +RoutingPolicyRule.IPProtocol, config_parse_routing_policy_rule_ip_protocol, 0, 0 +RoutingPolicyRule.SourcePort, config_parse_routing_policy_rule_port_range, 0, 0 +RoutingPolicyRule.DestinationPort, config_parse_routing_policy_rule_port_range, 0, 0 +RoutingPolicyRule.InvertRule, config_parse_routing_policy_rule_invert, 0, 0 +RoutingPolicyRule.Family, config_parse_routing_policy_rule_family, 0, 0 +Route.Gateway, config_parse_gateway, 0, 0 +Route.Destination, config_parse_destination, 0, 0 +Route.Source, config_parse_destination, 0, 0 +Route.Metric, config_parse_route_priority, 0, 0 +Route.Scope, config_parse_route_scope, 0, 0 +Route.PreferredSource, config_parse_preferred_src, 0, 0 +Route.Table, config_parse_route_table, 0, 0 +Route.MTUBytes, config_parse_route_mtu, AF_UNSPEC, 0 +Route.GatewayOnLink, config_parse_gateway_onlink, 0, 0 +Route.GatewayOnlink, config_parse_gateway_onlink, 0, 0 +Route.IPv6Preference, config_parse_ipv6_route_preference, 0, 0 +Route.Protocol, config_parse_route_protocol, 0, 0 +Route.Type, config_parse_route_type, 0, 0 +Route.InitialCongestionWindow, config_parse_tcp_window, 0, 0 +Route.InitialAdvertisedReceiveWindow, config_parse_tcp_window, 0, 0 +Route.QuickAck, config_parse_quickack, 0, 0 +Route.FastOpenNoCookie, config_parse_fast_open_no_cookie, 0, 0 +Route.TTLPropagate, config_parse_route_ttl_propagate, 0, 0 +NextHop.Id, config_parse_nexthop_id, 0, 0 +NextHop.Gateway, config_parse_nexthop_gateway, 0, 0 +DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) +DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns) +DHCPv4.RoutesToDNS, config_parse_bool, 0, offsetof(Network, dhcp_routes_to_dns) +DHCPv4.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_use_ntp) +DHCPv4.UseSIP, config_parse_bool, 0, offsetof(Network, dhcp_use_sip) +DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) +DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) +DHCPv4.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) +DHCPv4.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes) +DHCPv4.RequestOptions, config_parse_dhcp_request_options, 0, 0 +DHCPv4.Anonymize, config_parse_bool, 0, offsetof(Network, dhcp_anonymize) +DHCPv4.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname) +DHCPv4.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname) +DHCPv4.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast) +DHCPv4.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier) +DHCPv4.MaxAttempts, config_parse_dhcp_max_attempts, 0, 0 +DHCPv4.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class) +DHCPv4.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid) +DHCPv4.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid) +DHCPv4.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) +DHCPv4.RouteTable, config_parse_section_route_table, 0, 0 +DHCPv4.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) +DHCPv4.IAID, config_parse_iaid, 0, 0 +DHCPv4.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) +DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release) +DHCPv4.BlackList, config_parse_dhcp_black_listed_ip_address, 0, 0 +DHCPv4.IPServiceType, config_parse_ip_service_type, 0, offsetof(Network, ip_service_type) +DHCPv4.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_options) +DHCPv6.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp6_use_dns) +DHCPv6.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp6_use_ntp) +DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit) +DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information) +DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0 +IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_autonomous_prefix) +IPv6AcceptRA.UseOnLinkPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_onlink_prefix) +IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns) +IPv6AcceptRA.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains) +IPv6AcceptRA.RouteTable, config_parse_section_route_table, 0, 0 +IPv6AcceptRA.BlackList, config_parse_ndisc_black_listed_prefix, 0, 0 +DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) +DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec) +DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns) +DHCPServer.DNS, config_parse_dhcp_server_dns, 0, 0 +DHCPServer.EmitNTP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_ntp) +DHCPServer.NTP, config_parse_dhcp_server_ntp, 0, 0 +DHCPServer.EmitSIP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_sip) +DHCPServer.SIP, config_parse_dhcp_server_sip, 0, 0 +DHCPServer.EmitRouter, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_router) +DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone) +DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone) +DHCPServer.PoolOffset, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_offset) +DHCPServer.PoolSize, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_size) +DHCPServer.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_options) +Bridge.Cost, config_parse_uint32, 0, offsetof(Network, cost) +Bridge.UseBPDU, config_parse_tristate, 0, offsetof(Network, use_bpdu) +Bridge.HairPin, config_parse_tristate, 0, offsetof(Network, hairpin) +Bridge.FastLeave, config_parse_tristate, 0, offsetof(Network, fast_leave) +Bridge.AllowPortToBeRoot, config_parse_tristate, 0, offsetof(Network, allow_port_to_be_root) +Bridge.UnicastFlood, config_parse_tristate, 0, offsetof(Network, unicast_flood) +Bridge.MulticastFlood, config_parse_tristate, 0, offsetof(Network, multicast_flood) +Bridge.MulticastToUnicast, config_parse_tristate, 0, offsetof(Network, multicast_to_unicast) +Bridge.NeighborSuppression, config_parse_tristate, 0, offsetof(Network, neighbor_suppression) +Bridge.Learning, config_parse_tristate, 0, offsetof(Network, learning) +Bridge.ProxyARP, config_parse_tristate, 0, offsetof(Network, bridge_proxy_arp) +Bridge.ProxyARPWiFi, config_parse_tristate, 0, offsetof(Network, bridge_proxy_arp_wifi) +Bridge.Priority, config_parse_bridge_port_priority, 0, offsetof(Network, priority) +Bridge.MulticastRouter, config_parse_multicast_router, 0, offsetof(Network, multicast_router) +BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0 +BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0 +BridgeFDB.Destination, config_parse_fdb_destination, 0, 0 +BridgeFDB.VNI, config_parse_fdb_vxlan_vni, 0, 0 +BridgeFDB.AssociatedWith, config_parse_fdb_ntf_flags, 0, 0 +BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0 +BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0 +BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0 +Network.IPv6PrefixDelegation, config_parse_router_prefix_delegation, 0, 0 +IPv6PrefixDelegation.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec) +IPv6PrefixDelegation.Managed, config_parse_bool, 0, offsetof(Network, router_managed) +IPv6PrefixDelegation.OtherInformation, config_parse_bool, 0, offsetof(Network, router_other_information) +IPv6PrefixDelegation.RouterPreference, config_parse_router_preference, 0, 0 +IPv6PrefixDelegation.EmitDNS, config_parse_bool, 0, offsetof(Network, router_emit_dns) +IPv6PrefixDelegation.DNS, config_parse_radv_dns, 0, 0 +IPv6PrefixDelegation.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains) +IPv6PrefixDelegation.Domains, config_parse_radv_search_domains, 0, 0 +IPv6PrefixDelegation.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec) +IPv6Prefix.Prefix, config_parse_prefix, 0, 0 +IPv6Prefix.OnLink, config_parse_prefix_flags, 0, 0 +IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0 +IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, 0, 0 +IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0 +IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0 +IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0 +CAN.BitRate, config_parse_si_size, 0, offsetof(Network, can_bitrate) +CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point) +CAN.RestartSec, config_parse_sec, 0, offsetof(Network, can_restart_us) +CAN.TripleSampling, config_parse_tristate, 0, offsetof(Network, can_triple_sampling) +TrafficControlQueueingDiscipline.Parent, config_parse_tc_qdiscs_parent, 0, 0 +TrafficControlQueueingDiscipline.NetworkEmulatorDelaySec, config_parse_tc_network_emulator_delay, 0, 0 +TrafficControlQueueingDiscipline.NetworkEmulatorDelayJitterSec, config_parse_tc_network_emulator_delay, 0, 0 +TrafficControlQueueingDiscipline.NetworkEmulatorLossRate, config_parse_tc_network_emulator_rate, 0, 0 +TrafficControlQueueingDiscipline.NetworkEmulatorDuplicateRate, config_parse_tc_network_emulator_rate, 0, 0 +TrafficControlQueueingDiscipline.NetworkEmulatorPacketLimit, config_parse_tc_network_emulator_packet_limit, 0, 0 +/* backwards compatibility: do not add new entries to this section */ +Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) +DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) +DHCP.UseDNS, config_parse_dhcp_use_dns, 0, 0 +DHCP.UseNTP, config_parse_dhcp_use_ntp, 0, 0 +DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) +DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) +DHCP.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) +DHCP.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) +DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes) +DHCP.Anonymize, config_parse_bool, 0, offsetof(Network, dhcp_anonymize) +DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname) +DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname) +DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast) +DHCP.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical) +DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier) +DHCP.UserClass, config_parse_dhcp_user_class, 0, offsetof(Network, dhcp_user_class) +DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid) +DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid) +DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) +DHCP.RouteTable, config_parse_section_route_table, 0, 0 +DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) +DHCP.IAID, config_parse_iaid, 0, 0 +DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) +DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit) +DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information) +DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) +DHCPv4.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c new file mode 100644 index 00000000..6e443975 --- /dev/null +++ b/src/network/networkd-network.c @@ -0,0 +1,1330 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "conf-files.h" +#include "conf-parser.h" +#include "dns-domain.h" +#include "fd-util.h" +#include "hostname-util.h" +#include "in-addr-util.h" +#include "networkd-dhcp-server.h" +#include "network-internal.h" +#include "networkd-manager.h" +#include "networkd-network.h" +#include "parse-util.h" +#include "set.h" +#include "socket-util.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "util.h" + +/* Let's assume that anything above this number is a user misconfiguration. */ +#define MAX_NTP_SERVERS 128 + +/* Set defaults following RFC7844 */ +void network_apply_anonymize_if_set(Network *network) { + if (!network->dhcp_anonymize) + return; + /* RFC7844 3.7 + SHOULD NOT send the Host Name option */ + network->dhcp_send_hostname = false; + /* RFC7844 section 3.: + MAY contain the Client Identifier option + Section 3.5: + clients MUST use client identifiers based solely + on the link-layer address */ + /* NOTE: Using MAC, as it does not reveal extra information, + * and some servers might not answer if this option is not sent */ + network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC; + /* RFC 7844 3.10: + SHOULD NOT use the Vendor Class Identifier option */ + network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier); + /* RFC7844 section 3.6.: + The client intending to protect its privacy SHOULD only request a + minimal number of options in the PRL and SHOULD also randomly shuffle + the ordering of option codes in the PRL. If this random ordering + cannot be implemented, the client MAY order the option codes in the + PRL by option code number (lowest to highest). + */ + /* NOTE: dhcp_use_mtu is false by default, + * though it was not initiallized to any value in network_load_one. + * Maybe there should be another var called *send*? + * (to use the MTU sent by the server but to do not send + * the option in the PRL). */ + network->dhcp_use_mtu = false; + /* NOTE: when Anonymize=yes, the PRL route options are sent by default, + * but this is needed to use them. */ + network->dhcp_use_routes = true; + /* RFC7844 section 3.6. + * same comments as previous option */ + network->dhcp_use_timezone = false; +} + +static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) { + const char *kind_string; + NetDev *netdev; + int r; + + /* For test-networkd-conf, the check must be earlier than the assertions. */ + if (!name) + return 0; + + assert(network); + assert(network->manager); + assert(network->filename); + assert(ret_netdev); + + if (kind == _NETDEV_KIND_TUNNEL) + kind_string = "tunnel"; + else { + kind_string = netdev_kind_to_string(kind); + if (!kind_string) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Invalid NetDev kind of %s, ignoring assignment.", + network->filename, name); + } + + r = netdev_get(network->manager, name, &netdev); + if (r < 0) + return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.", + network->filename, name); + + if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL && + IN_SET(netdev->kind, + NETDEV_KIND_IPIP, + NETDEV_KIND_SIT, + NETDEV_KIND_GRE, + NETDEV_KIND_GRETAP, + NETDEV_KIND_IP6GRE, + NETDEV_KIND_IP6GRETAP, + NETDEV_KIND_VTI, + NETDEV_KIND_VTI6, + NETDEV_KIND_IP6TNL, + NETDEV_KIND_ERSPAN))) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: NetDev %s is not a %s, ignoring assignment", + network->filename, name, kind_string); + + *ret_netdev = netdev_ref(netdev); + return 1; +} + +static int network_resolve_stacked_netdevs(Network *network) { + void *name, *kind; + Iterator i; + int r; + + assert(network); + + HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names, i) { + _cleanup_(netdev_unrefp) NetDev *netdev = NULL; + + r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev); + if (r <= 0) + continue; + + r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops); + if (r < 0) + return log_oom(); + + r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev); + if (r < 0) + return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m", + network->filename, (const char *) name); + + netdev = NULL; + } + + return 0; +} + +int network_verify(Network *network) { + RoutePrefix *route_prefix, *route_prefix_next; + RoutingPolicyRule *rule, *rule_next; + Neighbor *neighbor, *neighbor_next; + AddressLabel *label, *label_next; + NextHop *nexthop, *nextnop_next; + Address *address, *address_next; + Prefix *prefix, *prefix_next; + Route *route, *route_next; + FdbEntry *fdb, *fdb_next; + + assert(network); + assert(network->filename); + + if (set_isempty(network->match_mac) && strv_isempty(network->match_path) && + strv_isempty(network->match_driver) && strv_isempty(network->match_type) && + strv_isempty(network->match_name) && strv_isempty(network->match_property) && + strv_isempty(network->match_ssid) && !network->conditions) + log_warning("%s: No valid settings found in the [Match] section. " + "The file will match all interfaces. " + "If that is intended, please add Name=* in the [Match] section.", + network->filename); + + /* skip out early if configuration does not match the environment */ + if (!condition_test_list(network->conditions, NULL, NULL, NULL)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Conditions in the file do not match the system environment, skipping.", + network->filename); + + (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond); + (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge); + (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf); + (void) network_resolve_stacked_netdevs(network); + + /* Free unnecessary entries. */ + network->bond_name = mfree(network->bond_name); + network->bridge_name = mfree(network->bridge_name); + network->vrf_name = mfree(network->vrf_name); + network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names); + + if (network->bond) { + /* Bonding slave does not support addressing. */ + if (network->ipv6_accept_ra > 0) { + log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.", + network->filename); + network->ipv6_accept_ra = 0; + } + if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) { + log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.", + network->filename); + network->link_local = ADDRESS_FAMILY_NO; + } + if (network->dhcp != ADDRESS_FAMILY_NO) { + log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.", + network->filename); + network->dhcp = ADDRESS_FAMILY_NO; + } + if (network->dhcp_server) { + log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.", + network->filename); + network->dhcp_server = false; + } + if (network->n_static_addresses > 0) { + log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.", + network->filename); + while ((address = network->static_addresses)) + address_free(address); + } + if (network->n_static_routes > 0) { + log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.", + network->filename); + while ((route = network->static_routes)) + route_free(route); + } + } + + if (network->link_local < 0) + network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6; + + if (!FLAGS_SET(network->link_local, ADDRESS_FAMILY_IPV6)) { + if (network->ipv6_accept_ra > 0) { + log_warning("%s: IPv6AcceptRA= is enabled by the .network file but IPv6 link local addressing is disabled. " + "Disabling IPv6AcceptRA=.", network->filename); + network->ipv6_accept_ra = false; + } + + if (FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV6)) { + log_warning("%s: DHCPv6 client is enabled by the .network file but IPv6 link local addressing is disabled. " + "Disabling DHCPv6 client.", network->filename); + SET_FLAG(network->dhcp, ADDRESS_FAMILY_IPV6, false); + } + + if (network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE) { + log_warning("%s: IPv6PrefixDelegation= is enabled but IPv6 link local addressing is disabled. " + "Disabling IPv6PrefixDelegation=.", network->filename); + network->router_prefix_delegation = RADV_PREFIX_DELEGATION_NONE; + } + } + + if (FLAGS_SET(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4) && + !FLAGS_SET(network->dhcp, ADDRESS_FAMILY_IPV4)) { + log_warning("%s: fallback assignment of IPv4 link local address is enabled but DHCPv4 is disabled. " + "Disabling the fallback assignment.", network->filename); + SET_FLAG(network->link_local, ADDRESS_FAMILY_FALLBACK_IPV4, false); + } + + if (network->ipv6_accept_ra < 0 && network->bridge) + network->ipv6_accept_ra = false; + + /* IPMasquerade=yes implies IPForward=yes */ + if (network->ip_masquerade) + network->ip_forward |= ADDRESS_FAMILY_IPV4; + + if (network->mtu > 0 && network->dhcp_use_mtu) { + log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. " + "Disabling UseMTU=.", network->filename); + network->dhcp_use_mtu = false; + } + + if (network->dhcp_critical >= 0) { + if (network->keep_configuration >= 0) + log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. " + "Ignoring CriticalConnection=.", network->filename); + else if (network->dhcp_critical) + /* CriticalConnection=yes also preserve foreign static configurations. */ + network->keep_configuration = KEEP_CONFIGURATION_YES; + else + network->keep_configuration = KEEP_CONFIGURATION_NO; + } + + if (network->keep_configuration < 0) + network->keep_configuration = KEEP_CONFIGURATION_NO; + + LIST_FOREACH_SAFE(addresses, address, address_next, network->static_addresses) + if (address_section_verify(address) < 0) + address_free(address); + + LIST_FOREACH_SAFE(routes, route, route_next, network->static_routes) + if (route_section_verify(route, network) < 0) + route_free(route); + + LIST_FOREACH_SAFE(nexthops, nexthop, nextnop_next, network->static_nexthops) + if (nexthop_section_verify(nexthop) < 0) + nexthop_free(nexthop); + + LIST_FOREACH_SAFE(static_fdb_entries, fdb, fdb_next, network->static_fdb_entries) + if (section_is_invalid(fdb->section)) + fdb_entry_free(fdb); + + LIST_FOREACH_SAFE(neighbors, neighbor, neighbor_next, network->neighbors) + if (neighbor_section_verify(neighbor) < 0) + neighbor_free(neighbor); + + LIST_FOREACH_SAFE(labels, label, label_next, network->address_labels) + if (section_is_invalid(label->section)) + address_label_free(label); + + LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_prefixes) + if (section_is_invalid(prefix->section)) + prefix_free(prefix); + + LIST_FOREACH_SAFE(route_prefixes, route_prefix, route_prefix_next, network->static_route_prefixes) + if (section_is_invalid(route_prefix->section)) + route_prefix_free(route_prefix); + + LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules) + if (routing_policy_rule_section_verify(rule) < 0) + routing_policy_rule_free(rule); + + return 0; +} + +int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) { + _cleanup_free_ char *fname = NULL, *name = NULL; + _cleanup_(network_unrefp) Network *network = NULL; + _cleanup_fclose_ FILE *file = NULL; + const char *dropin_dirname; + char *d; + int r; + + assert(manager); + assert(filename); + + file = fopen(filename, "re"); + if (!file) { + if (errno == ENOENT) + return 0; + + return -errno; + } + + if (null_or_empty_fd(fileno(file))) { + log_debug("Skipping empty file: %s", filename); + return 0; + } + + fname = strdup(filename); + if (!fname) + return log_oom(); + + name = strdup(basename(filename)); + if (!name) + return log_oom(); + + d = strrchr(name, '.'); + if (!d) + return -EINVAL; + + *d = '\0'; + + dropin_dirname = strjoina(name, ".network.d"); + + network = new(Network, 1); + if (!network) + return log_oom(); + + *network = (Network) { + .filename = TAKE_PTR(fname), + .name = TAKE_PTR(name), + + .manager = manager, + .n_ref = 1, + + .required_for_online = true, + .required_operstate_for_online = LINK_OPERSTATE_DEGRADED, + .dhcp = ADDRESS_FAMILY_NO, + .dhcp_critical = -1, + .dhcp_use_ntp = true, + .dhcp_use_sip = true, + .dhcp_use_dns = true, + .dhcp_use_hostname = true, + .dhcp_use_routes = true, + /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */ + .dhcp_send_hostname = true, + .dhcp_send_release = true, + /* To enable/disable RFC7844 Anonymity Profiles */ + .dhcp_anonymize = false, + .dhcp_route_metric = DHCP_ROUTE_METRIC, + /* NOTE: this var might be overwritten by network_apply_anonymize_if_set */ + .dhcp_client_identifier = DHCP_CLIENT_ID_DUID, + .dhcp_route_table = RT_TABLE_MAIN, + .dhcp_route_table_set = false, + /* NOTE: from man: UseMTU=... Defaults to false*/ + .dhcp_use_mtu = false, + /* NOTE: from man: UseTimezone=... Defaults to "no".*/ + .dhcp_use_timezone = false, + .rapid_commit = true, + + .dhcp6_use_ntp = true, + .dhcp6_use_dns = true, + + .dhcp_server_emit_dns = true, + .dhcp_server_emit_ntp = true, + .dhcp_server_emit_sip = true, + .dhcp_server_emit_router = true, + .dhcp_server_emit_timezone = true, + + .router_emit_dns = true, + .router_emit_domains = true, + + .use_bpdu = -1, + .hairpin = -1, + .fast_leave = -1, + .allow_port_to_be_root = -1, + .unicast_flood = -1, + .multicast_flood = -1, + .multicast_to_unicast = -1, + .neighbor_suppression = -1, + .learning = -1, + .bridge_proxy_arp = -1, + .bridge_proxy_arp_wifi = -1, + .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID, + .multicast_router = _MULTICAST_ROUTER_INVALID, + + .lldp_mode = LLDP_MODE_ROUTERS_ONLY, + + .dns_default_route = -1, + .llmnr = RESOLVE_SUPPORT_YES, + .mdns = RESOLVE_SUPPORT_NO, + .dnssec_mode = _DNSSEC_MODE_INVALID, + .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID, + + /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */ + .link_local = _ADDRESS_FAMILY_INVALID, + + .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO, + .ipv6_accept_ra = -1, + .ipv6_dad_transmits = -1, + .ipv6_hop_limit = -1, + .ipv6_proxy_ndp = -1, + .duid.type = _DUID_TYPE_INVALID, + .proxy_arp = -1, + .arp = -1, + .multicast = -1, + .allmulticast = -1, + .ipv6_accept_ra_use_dns = true, + .ipv6_accept_ra_use_autonomous_prefix = true, + .ipv6_accept_ra_use_onlink_prefix = true, + .ipv6_accept_ra_route_table = RT_TABLE_MAIN, + .ipv6_accept_ra_route_table_set = false, + + .keep_configuration = _KEEP_CONFIGURATION_INVALID, + + .can_triple_sampling = -1, + .ip_service_type = -1, + }; + + r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname, + "Match\0" + "Link\0" + "Network\0" + "Address\0" + "Neighbor\0" + "IPv6AddressLabel\0" + "RoutingPolicyRule\0" + "Route\0" + "NextHop\0" + "DHCP\0" /* compat */ + "DHCPv4\0" + "DHCPv6\0" + "DHCPServer\0" + "IPv6AcceptRA\0" + "IPv6NDPProxyAddress\0" + "Bridge\0" + "BridgeFDB\0" + "BridgeVLAN\0" + "IPv6PrefixDelegation\0" + "IPv6Prefix\0" + "IPv6RoutePrefix\0" + "TrafficControlQueueingDiscipline\0" + "CAN\0", + config_item_perf_lookup, network_network_gperf_lookup, + CONFIG_PARSE_WARN, network); + if (r < 0) + return r; + + network_apply_anonymize_if_set(network); + + r = network_add_ipv4ll_route(network); + if (r < 0) + log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename); + + r = network_add_default_route_on_device(network); + if (r < 0) + log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m", + network->filename); + + struct stat stats; + if (stat(filename, &stats) < 0) + return -errno; + network->timestamp = timespec_load(&stats.st_mtim); + + if (network_verify(network) < 0) + /* Ignore .network files that do not match the conditions. */ + return 0; + + r = ordered_hashmap_ensure_allocated(networks, &string_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(*networks, network->name, network); + if (r < 0) + return r; + + network = NULL; + return 0; +} + +int network_load(Manager *manager, OrderedHashmap **networks) { + _cleanup_strv_free_ char **files = NULL; + char **f; + int r; + + assert(manager); + + ordered_hashmap_clear_with_destructor(*networks, network_unref); + + r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS); + if (r < 0) + return log_error_errno(r, "Failed to enumerate network files: %m"); + + STRV_FOREACH(f, files) { + r = network_load_one(manager, networks, *f); + if (r < 0) + log_error_errno(r, "Failed to load %s, ignoring: %m", *f); + } + + return 0; +} + +int network_reload(Manager *manager) { + OrderedHashmap *new_networks = NULL; + Network *n, *old; + Iterator i; + int r; + + assert(manager); + + r = network_load(manager, &new_networks); + if (r < 0) + goto failure; + + ORDERED_HASHMAP_FOREACH(n, new_networks, i) { + r = network_get_by_name(manager, n->name, &old); + if (r < 0) + continue; /* The .network file is new. */ + + if (n->timestamp != old->timestamp) + continue; /* The .network file is modified. */ + + if (!streq(n->filename, old->filename)) + continue; + + r = ordered_hashmap_replace(new_networks, old->name, old); + if (r < 0) + goto failure; + + network_ref(old); + network_unref(n); + } + + ordered_hashmap_free_with_destructor(manager->networks, network_unref); + manager->networks = new_networks; + + return 0; + +failure: + ordered_hashmap_free_with_destructor(new_networks, network_unref); + + return r; +} + +static Network *network_free(Network *network) { + IPv6ProxyNDPAddress *ipv6_proxy_ndp_address; + RoutePrefix *route_prefix; + RoutingPolicyRule *rule; + AddressLabel *label; + FdbEntry *fdb_entry; + Neighbor *neighbor; + Address *address; + NextHop *nexthop; + Prefix *prefix; + Route *route; + + if (!network) + return NULL; + + free(network->filename); + + set_free_free(network->match_mac); + strv_free(network->match_path); + strv_free(network->match_driver); + strv_free(network->match_type); + strv_free(network->match_name); + strv_free(network->match_property); + strv_free(network->match_wlan_iftype); + strv_free(network->match_ssid); + set_free_free(network->match_bssid); + condition_free_list(network->conditions); + + free(network->description); + free(network->dhcp_vendor_class_identifier); + strv_free(network->dhcp_user_class); + free(network->dhcp_hostname); + set_free(network->dhcp_black_listed_ip); + set_free(network->dhcp_request_options); + free(network->mac); + + strv_free(network->ntp); + free(network->dns); + strv_free(network->sip); + ordered_set_free_free(network->search_domains); + ordered_set_free_free(network->route_domains); + strv_free(network->bind_carrier); + + ordered_set_free_free(network->router_search_domains); + free(network->router_dns); + set_free_free(network->ndisc_black_listed_prefix); + + free(network->bridge_name); + free(network->bond_name); + free(network->vrf_name); + hashmap_free_free_key(network->stacked_netdev_names); + netdev_unref(network->bridge); + netdev_unref(network->bond); + netdev_unref(network->vrf); + hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref); + + while ((route = network->static_routes)) + route_free(route); + + while ((nexthop = network->static_nexthops)) + nexthop_free(nexthop); + + while ((address = network->static_addresses)) + address_free(address); + + while ((fdb_entry = network->static_fdb_entries)) + fdb_entry_free(fdb_entry); + + while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses)) + ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address); + + while ((neighbor = network->neighbors)) + neighbor_free(neighbor); + + while ((label = network->address_labels)) + address_label_free(label); + + while ((prefix = network->static_prefixes)) + prefix_free(prefix); + + while ((route_prefix = network->static_route_prefixes)) + route_prefix_free(route_prefix); + + while ((rule = network->rules)) + routing_policy_rule_free(rule); + + hashmap_free(network->addresses_by_section); + hashmap_free(network->routes_by_section); + hashmap_free(network->nexthops_by_section); + hashmap_free(network->fdb_entries_by_section); + hashmap_free(network->neighbors_by_section); + hashmap_free(network->address_labels_by_section); + hashmap_free(network->prefixes_by_section); + hashmap_free(network->route_prefixes_by_section); + hashmap_free(network->rules_by_section); + ordered_hashmap_free_with_destructor(network->qdiscs_by_section, qdisc_free); + + if (network->manager && + network->manager->duids_requesting_uuid) + set_remove(network->manager->duids_requesting_uuid, &network->duid); + + free(network->name); + + free(network->dhcp_server_timezone); + free(network->dhcp_server_dns); + free(network->dhcp_server_ntp); + free(network->dhcp_server_sip); + + set_free_free(network->dnssec_negative_trust_anchors); + + ordered_hashmap_free(network->dhcp_client_send_options); + ordered_hashmap_free(network->dhcp_server_send_options); + + return mfree(network); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free); + +int network_get_by_name(Manager *manager, const char *name, Network **ret) { + Network *network; + + assert(manager); + assert(name); + assert(ret); + + network = ordered_hashmap_get(manager->networks, name); + if (!network) + return -ENOENT; + + *ret = network; + + return 0; +} + +int network_get(Manager *manager, sd_device *device, + const char *ifname, const struct ether_addr *address, + enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid, + Network **ret) { + Network *network; + Iterator i; + + assert(manager); + assert(ret); + + ORDERED_HASHMAP_FOREACH(network, manager->networks, i) + if (net_match_config(network->match_mac, network->match_path, network->match_driver, + network->match_type, network->match_name, network->match_property, + network->match_wlan_iftype, network->match_ssid, network->match_bssid, + device, address, ifname, wlan_iftype, ssid, bssid)) { + if (network->match_name && device) { + const char *attr; + uint8_t name_assign_type = NET_NAME_UNKNOWN; + + if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0) + (void) safe_atou8(attr, &name_assign_type); + + if (name_assign_type == NET_NAME_ENUM) + log_warning("%s: found matching network '%s', based on potentially unpredictable ifname", + ifname, network->filename); + else + log_debug("%s: found matching network '%s'", ifname, network->filename); + } else + log_debug("%s: found matching network '%s'", ifname, network->filename); + + *ret = network; + return 0; + } + + *ret = NULL; + + return -ENOENT; +} + +int network_apply(Network *network, Link *link) { + assert(network); + assert(link); + + link->network = network_ref(network); + + if (network->n_dns > 0 || + !strv_isempty(network->ntp) || + !ordered_set_isempty(network->search_domains) || + !ordered_set_isempty(network->route_domains)) + link_dirty(link); + + return 0; +} + +bool network_has_static_ipv6_configurations(Network *network) { + Address *address; + Route *route; + FdbEntry *fdb; + Neighbor *neighbor; + + assert(network); + + LIST_FOREACH(addresses, address, network->static_addresses) + if (address->family == AF_INET6) + return true; + + LIST_FOREACH(routes, route, network->static_routes) + if (route->family == AF_INET6) + return true; + + LIST_FOREACH(static_fdb_entries, fdb, network->static_fdb_entries) + if (fdb->family == AF_INET6) + return true; + + LIST_FOREACH(neighbors, neighbor, network->neighbors) + if (neighbor->family == AF_INET6) + return true; + + if (!LIST_IS_EMPTY(network->address_labels)) + return true; + + if (!LIST_IS_EMPTY(network->static_prefixes)) + return true; + + return false; +} + +int config_parse_stacked_netdev(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + _cleanup_free_ char *name = NULL; + NetDevKind kind = ltype; + Hashmap **h = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + assert(IN_SET(kind, + NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP, + NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN, + NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL, + NETDEV_KIND_XFRM)); + + if (!ifname_valid(rvalue)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue); + return 0; + } + + name = strdup(rvalue); + if (!name) + return log_oom(); + + r = hashmap_ensure_allocated(h, &string_hash_ops); + if (r < 0) + return log_oom(); + + r = hashmap_put(*h, name, INT_TO_PTR(kind)); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, + "Cannot add NetDev '%s' to network, ignoring assignment: %m", name); + else if (r == 0) + log_syntax(unit, LOG_DEBUG, filename, line, r, + "NetDev '%s' specified twice, ignoring.", name); + else + name = NULL; + + return 0; +} + +int config_parse_domains( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const char *p; + Network *n = data; + int r; + + assert(n); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + n->search_domains = ordered_set_free_free(n->search_domains); + n->route_domains = ordered_set_free_free(n->route_domains); + return 0; + } + + p = rvalue; + for (;;) { + _cleanup_free_ char *w = NULL, *normalized = NULL; + const char *domain; + bool is_route; + + r = extract_first_word(&p, &w, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract search or route domain, ignoring: %s", rvalue); + break; + } + if (r == 0) + break; + + is_route = w[0] == '~'; + domain = is_route ? w + 1 : w; + + if (dns_name_is_root(domain) || streq(domain, "*")) { + /* If the root domain appears as is, or the special token "*" is found, we'll + * consider this as routing domain, unconditionally. */ + is_route = true; + domain = "."; /* make sure we don't allow empty strings, thus write the root + * domain as "." */ + } else { + r = dns_name_normalize(domain, 0, &normalized); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "'%s' is not a valid domain name, ignoring.", domain); + continue; + } + + domain = normalized; + + if (is_localhost(domain)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "'localhost' domain may not be configured as search or route domain, ignoring assignment: %s", + domain); + continue; + } + } + + OrderedSet **set = is_route ? &n->route_domains : &n->search_domains; + r = ordered_set_ensure_allocated(set, &string_hash_ops); + if (r < 0) + return r; + + r = ordered_set_put_strdup(*set, domain); + if (r < 0) + return log_oom(); + } + + return 0; +} + +int config_parse_ipv6token( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + union in_addr_union buffer; + struct in6_addr *token = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(token); + + r = in_addr_from_string(AF_INET6, rvalue, &buffer); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse IPv6 token, ignoring: %s", rvalue); + return 0; + } + + if (in_addr_is_null(AF_INET6, &buffer)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "IPv6 token cannot be the ANY address, ignoring: %s", rvalue); + return 0; + } + + if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue); + return 0; + } + + *token = buffer.in6; + + return 0; +} + +static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = { + [IPV6_PRIVACY_EXTENSIONS_NO] = "no", + [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public", + [IPV6_PRIVACY_EXTENSIONS_YES] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions, + IPV6_PRIVACY_EXTENSIONS_YES); + +int config_parse_ipv6_privacy_extensions( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + IPv6PrivacyExtensions s, *ipv6_privacy_extensions = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(ipv6_privacy_extensions); + + s = ipv6_privacy_extensions_from_string(rvalue); + if (s < 0) { + if (streq(rvalue, "kernel")) + s = _IPV6_PRIVACY_EXTENSIONS_INVALID; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue); + return 0; + } + } + + *ipv6_privacy_extensions = s; + + return 0; +} + +int config_parse_hostname( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *hn = NULL; + char **hostname = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata); + if (r < 0) + return r; + + if (!hostname_is_valid(hn, false)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Hostname is not valid, ignoring assignment: %s", rvalue); + return 0; + } + + r = dns_name_is_valid(hn); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue); + return 0; + } + if (r == 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue); + return 0; + } + + return free_and_replace(*hostname, hn); +} + +int config_parse_timezone( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *tz = NULL; + char **datap = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata); + if (r < 0) + return r; + + if (!timezone_is_valid(tz, LOG_ERR)) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Timezone is not valid, ignoring assignment: %s", rvalue); + return 0; + } + + return free_and_replace(*datap, tz); +} + +int config_parse_dns( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *n = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + union in_addr_union a; + struct in_addr_data *m; + int family; + + r = extract_first_word(&rvalue, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid syntax, ignoring: %s", rvalue); + break; + } + if (r == 0) + break; + + r = in_addr_from_string_auto(w, &family, &a); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse dns server address, ignoring: %s", w); + continue; + } + + m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data)); + if (!m) + return log_oom(); + + m[n->n_dns++] = (struct in_addr_data) { + .family = family, + .address = a, + }; + + n->dns = m; + } + + return 0; +} + +int config_parse_dnssec_negative_trust_anchors( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + const char *p = rvalue; + Network *n = data; + int r; + + assert(n); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors); + return 0; + } + + for (;;) { + _cleanup_free_ char *w = NULL; + + r = extract_first_word(&p, &w, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract negative trust anchor domain, ignoring: %s", rvalue); + break; + } + if (r == 0) + break; + + r = dns_name_is_valid(w); + if (r <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "%s is not a valid domain name, ignoring.", w); + continue; + } + + r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops); + if (r < 0) + return log_oom(); + + r = set_put(n->dnssec_negative_trust_anchors, w); + if (r < 0) + return log_oom(); + if (r > 0) + w = NULL; + } + + return 0; +} + +int config_parse_ntp( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char ***l = data; + int r; + + assert(l); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + *l = strv_free(*l); + return 0; + } + + for (;;) { + _cleanup_free_ char *w = NULL; + + r = extract_first_word(&rvalue, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract NTP server name, ignoring: %s", rvalue); + break; + } + if (r == 0) + break; + + r = dns_name_is_valid_or_address(w); + if (r <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "%s is not a valid domain name or IP address, ignoring.", w); + continue; + } + + if (strv_length(*l) > MAX_NTP_SERVERS) { + log_syntax(unit, LOG_WARNING, filename, line, 0, + "More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.", + MAX_NTP_SERVERS, w); + break; + } + + r = strv_consume(l, TAKE_PTR(w)); + if (r < 0) + return log_oom(); + } + + return 0; +} + +int config_parse_required_for_online( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + LinkOperationalState s; + bool required = true; + int r; + + if (isempty(rvalue)) { + network->required_for_online = true; + network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED; + return 0; + } + + s = link_operstate_from_string(rvalue); + if (s < 0) { + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse %s= setting, ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + required = r; + s = LINK_OPERSTATE_DEGRADED; + } + + network->required_for_online = required; + network->required_operstate_for_online = s; + + return 0; +} + +DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration, + "Failed to parse KeepConfiguration= setting"); + +static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = { + [KEEP_CONFIGURATION_NO] = "no", + [KEEP_CONFIGURATION_DHCP_ON_STOP] = "dhcp-on-stop", + [KEEP_CONFIGURATION_DHCP] = "dhcp", + [KEEP_CONFIGURATION_STATIC] = "static", + [KEEP_CONFIGURATION_YES] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h new file mode 100644 index 00000000..aa74bb4a --- /dev/null +++ b/src/network/networkd-network.h @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" +#include "sd-device.h" + +#include "bridge.h" +#include "condition.h" +#include "conf-parser.h" +#include "hashmap.h" +#include "netdev.h" +#include "networkd-address-label.h" +#include "networkd-address.h" +#include "networkd-brvlan.h" +#include "networkd-dhcp-common.h" +#include "networkd-dhcp4.h" +#include "networkd-dhcp-server.h" +#include "networkd-fdb.h" +#include "networkd-ipv6-proxy-ndp.h" +#include "networkd-lldp-rx.h" +#include "networkd-lldp-tx.h" +#include "networkd-neighbor.h" +#include "networkd-nexthop.h" +#include "networkd-radv.h" +#include "networkd-route.h" +#include "networkd-routing-policy-rule.h" +#include "networkd-util.h" +#include "ordered-set.h" +#include "qdisc.h" +#include "resolve-util.h" + +typedef enum IPv6PrivacyExtensions { + /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ + IPV6_PRIVACY_EXTENSIONS_NO, + IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC, + IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */ + _IPV6_PRIVACY_EXTENSIONS_MAX, + _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, +} IPv6PrivacyExtensions; + +typedef enum KeepConfiguration { + KEEP_CONFIGURATION_NO = 0, + KEEP_CONFIGURATION_DHCP_ON_START = 1 << 0, + KEEP_CONFIGURATION_DHCP_ON_STOP = 1 << 1, + KEEP_CONFIGURATION_DHCP = KEEP_CONFIGURATION_DHCP_ON_START | KEEP_CONFIGURATION_DHCP_ON_STOP, + KEEP_CONFIGURATION_STATIC = 1 << 2, + KEEP_CONFIGURATION_YES = KEEP_CONFIGURATION_DHCP | KEEP_CONFIGURATION_STATIC, + _KEEP_CONFIGURATION_MAX, + _KEEP_CONFIGURATION_INVALID = -1, +} KeepConfiguration; + +typedef struct Manager Manager; + +struct Network { + Manager *manager; + + char *filename; + char *name; + usec_t timestamp; + + unsigned n_ref; + + Set *match_mac; + char **match_path; + char **match_driver; + char **match_type; + char **match_name; + char **match_property; + char **match_wlan_iftype; + char **match_ssid; + Set *match_bssid; + LIST_HEAD(Condition, conditions); + + char *description; + + NetDev *bridge; + NetDev *bond; + NetDev *vrf; + NetDev *xfrm; + Hashmap *stacked_netdevs; + char *bridge_name; + char *bond_name; + char *vrf_name; + Hashmap *stacked_netdev_names; + + /* DHCP Client Support */ + AddressFamily dhcp; + DHCPClientIdentifier dhcp_client_identifier; + char *dhcp_vendor_class_identifier; + char **dhcp_user_class; + char *dhcp_hostname; + uint64_t dhcp_max_attempts; + unsigned dhcp_route_metric; + uint32_t dhcp_route_table; + uint16_t dhcp_client_port; + int dhcp_critical; + int ip_service_type; + bool dhcp_anonymize; + bool dhcp_send_hostname; + bool dhcp_broadcast; + bool dhcp_use_dns; + bool dhcp_routes_to_dns; + bool dhcp_use_ntp; + bool dhcp_use_sip; + bool dhcp_use_mtu; + bool dhcp_use_routes; + bool dhcp_use_timezone; + bool rapid_commit; + bool dhcp_use_hostname; + bool dhcp_route_table_set; + bool dhcp_send_release; + DHCPUseDomains dhcp_use_domains; + Set *dhcp_black_listed_ip; + Set *dhcp_request_options; + OrderedHashmap *dhcp_client_send_options; + OrderedHashmap *dhcp_server_send_options; + + /* DHCPv6 Client support*/ + bool dhcp6_use_dns; + bool dhcp6_use_ntp; + uint8_t dhcp6_pd_length; + struct in6_addr dhcp6_pd_address; + + /* DHCP Server Support */ + bool dhcp_server; + + bool dhcp_server_emit_dns; + struct in_addr *dhcp_server_dns; + unsigned n_dhcp_server_dns; + + bool dhcp_server_emit_ntp; + struct in_addr *dhcp_server_ntp; + unsigned n_dhcp_server_ntp; + + bool dhcp_server_emit_sip; + struct in_addr *dhcp_server_sip; + unsigned n_dhcp_server_sip; + + bool dhcp_server_emit_router; + bool dhcp_server_emit_timezone; + char *dhcp_server_timezone; + usec_t dhcp_server_default_lease_time_usec, dhcp_server_max_lease_time_usec; + uint32_t dhcp_server_pool_offset; + uint32_t dhcp_server_pool_size; + + /* IPV4LL Support */ + AddressFamily link_local; + bool ipv4ll_route; + + bool default_route_on_device; + + /* IPv6 prefix delegation support */ + RADVPrefixDelegation router_prefix_delegation; + usec_t router_lifetime_usec; + uint8_t router_preference; + bool router_managed; + bool router_other_information; + bool router_emit_dns; + bool router_emit_domains; + usec_t router_dns_lifetime_usec; + struct in6_addr *router_dns; + unsigned n_router_dns; + OrderedSet *router_search_domains; + bool dhcp6_force_pd_other_information; /* Start DHCPv6 PD also when 'O' + RA flag is set, see RFC 7084, + WPD-4 */ + + /* Bridge Support */ + int use_bpdu; + int hairpin; + int fast_leave; + int allow_port_to_be_root; + int unicast_flood; + int multicast_flood; + int multicast_to_unicast; + int neighbor_suppression; + int learning; + int bridge_proxy_arp; + int bridge_proxy_arp_wifi; + uint32_t cost; + uint16_t priority; + MulticastRouter multicast_router; + + bool use_br_vlan; + uint16_t pvid; + uint32_t br_vid_bitmap[BRIDGE_VLAN_BITMAP_LEN]; + uint32_t br_untagged_bitmap[BRIDGE_VLAN_BITMAP_LEN]; + + /* CAN support */ + size_t can_bitrate; + unsigned can_sample_point; + usec_t can_restart_us; + int can_triple_sampling; + + AddressFamily ip_forward; + bool ip_masquerade; + + int ipv6_accept_ra; + int ipv6_dad_transmits; + int ipv6_hop_limit; + int ipv6_proxy_ndp; + int proxy_arp; + uint32_t ipv6_mtu; + + bool ipv6_accept_ra_use_dns; + bool ipv6_accept_ra_use_autonomous_prefix; + bool ipv6_accept_ra_use_onlink_prefix; + bool active_slave; + bool primary_slave; + DHCPUseDomains ipv6_accept_ra_use_domains; + uint32_t ipv6_accept_ra_route_table; + bool ipv6_accept_ra_route_table_set; + Set *ndisc_black_listed_prefix; + + union in_addr_union ipv6_token; + IPv6PrivacyExtensions ipv6_privacy_extensions; + + struct ether_addr *mac; + uint32_t mtu; + int arp; + int multicast; + int allmulticast; + bool unmanaged; + bool configure_without_carrier; + bool ignore_carrier_loss; + KeepConfiguration keep_configuration; + uint32_t iaid; + DUID duid; + + bool iaid_set; + + bool required_for_online; /* Is this network required to be considered online? */ + LinkOperationalState required_operstate_for_online; + + LLDPMode lldp_mode; /* LLDP reception */ + LLDPEmit lldp_emit; /* LLDP transmission */ + + LIST_HEAD(Address, static_addresses); + LIST_HEAD(Route, static_routes); + LIST_HEAD(NextHop, static_nexthops); + LIST_HEAD(FdbEntry, static_fdb_entries); + LIST_HEAD(IPv6ProxyNDPAddress, ipv6_proxy_ndp_addresses); + LIST_HEAD(Neighbor, neighbors); + LIST_HEAD(AddressLabel, address_labels); + LIST_HEAD(Prefix, static_prefixes); + LIST_HEAD(RoutePrefix, static_route_prefixes); + LIST_HEAD(RoutingPolicyRule, rules); + + unsigned n_static_addresses; + unsigned n_static_routes; + unsigned n_static_nexthops; + unsigned n_static_fdb_entries; + unsigned n_ipv6_proxy_ndp_addresses; + unsigned n_neighbors; + unsigned n_address_labels; + unsigned n_static_prefixes; + unsigned n_static_route_prefixes; + unsigned n_rules; + + Hashmap *addresses_by_section; + Hashmap *routes_by_section; + Hashmap *nexthops_by_section; + Hashmap *fdb_entries_by_section; + Hashmap *neighbors_by_section; + Hashmap *address_labels_by_section; + Hashmap *prefixes_by_section; + Hashmap *route_prefixes_by_section; + Hashmap *rules_by_section; + OrderedHashmap *qdiscs_by_section; + + /* All kinds of DNS configuration */ + struct in_addr_data *dns; + unsigned n_dns; + OrderedSet *search_domains, *route_domains; + + int dns_default_route; + ResolveSupport llmnr; + ResolveSupport mdns; + DnssecMode dnssec_mode; + DnsOverTlsMode dns_over_tls_mode; + Set *dnssec_negative_trust_anchors; + + char **ntp; + char **sip; + char **bind_carrier; +}; + +Network *network_ref(Network *network); +Network *network_unref(Network *network); +DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_unref); + +int network_load(Manager *manager, OrderedHashmap **networks); +int network_reload(Manager *manager); +int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename); +int network_verify(Network *network); + +int network_get_by_name(Manager *manager, const char *name, Network **ret); +int network_get(Manager *manager, sd_device *device, const char *ifname, const struct ether_addr *mac, + enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid, Network **ret); +int network_apply(Network *network, Link *link); +void network_apply_anonymize_if_set(Network *network); + +bool network_has_static_ipv6_configurations(Network *network); + +CONFIG_PARSER_PROTOTYPE(config_parse_stacked_netdev); +CONFIG_PARSER_PROTOTYPE(config_parse_tunnel); +CONFIG_PARSER_PROTOTYPE(config_parse_ipv6token); +CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions); +CONFIG_PARSER_PROTOTYPE(config_parse_domains); +CONFIG_PARSER_PROTOTYPE(config_parse_dns); +CONFIG_PARSER_PROTOTYPE(config_parse_hostname); +CONFIG_PARSER_PROTOTYPE(config_parse_timezone); +CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors); +CONFIG_PARSER_PROTOTYPE(config_parse_ntp); +CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online); +CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration); + +const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length); + +const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; +IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; + +const char* keep_configuration_to_string(KeepConfiguration i) _const_; +KeepConfiguration keep_configuration_from_string(const char *s) _pure_; diff --git a/src/network/networkd-nexthop.c b/src/network/networkd-nexthop.c new file mode 100644 index 00000000..9658fe30 --- /dev/null +++ b/src/network/networkd-nexthop.c @@ -0,0 +1,473 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * Copyright © 2019 VMware, Inc. + */ + +#include + +#include "alloc-util.h" +#include "conf-parser.h" +#include "in-addr-util.h" +#include "netlink-util.h" +#include "networkd-manager.h" +#include "networkd-nexthop.h" +#include "parse-util.h" +#include "set.h" +#include "string-util.h" +#include "util.h" + +int nexthop_new(NextHop **ret) { + _cleanup_(nexthop_freep) NextHop *nexthop = NULL; + + nexthop = new(NextHop, 1); + if (!nexthop) + return -ENOMEM; + + *nexthop = (NextHop) { + .family = AF_UNSPEC, + }; + + *ret = TAKE_PTR(nexthop); + + return 0; +} + +static int nexthop_new_static(Network *network, const char *filename, unsigned section_line, NextHop **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(nexthop_freep) NextHop *nexthop = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + nexthop = hashmap_get(network->nexthops_by_section, n); + if (nexthop) { + *ret = TAKE_PTR(nexthop); + + return 0; + } + } + + r = nexthop_new(&nexthop); + if (r < 0) + return r; + + nexthop->protocol = RTPROT_STATIC; + nexthop->network = network; + LIST_PREPEND(nexthops, network->static_nexthops, nexthop); + network->n_static_nexthops++; + + if (filename) { + nexthop->section = TAKE_PTR(n); + + r = hashmap_ensure_allocated(&network->nexthops_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(network->nexthops_by_section, nexthop->section, nexthop); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(nexthop); + + return 0; +} + +void nexthop_free(NextHop *nexthop) { + if (!nexthop) + return; + + if (nexthop->network) { + LIST_REMOVE(nexthops, nexthop->network->static_nexthops, nexthop); + + assert(nexthop->network->n_static_nexthops > 0); + nexthop->network->n_static_nexthops--; + + if (nexthop->section) + hashmap_remove(nexthop->network->nexthops_by_section, nexthop->section); + } + + network_config_section_free(nexthop->section); + + if (nexthop->link) { + set_remove(nexthop->link->nexthops, nexthop); + set_remove(nexthop->link->nexthops_foreign, nexthop); + } + + free(nexthop); +} + +static void nexthop_hash_func(const NextHop *nexthop, struct siphash *state) { + assert(nexthop); + + siphash24_compress(&nexthop->id, sizeof(nexthop->id), state); + siphash24_compress(&nexthop->oif, sizeof(nexthop->oif), state); + siphash24_compress(&nexthop->family, sizeof(nexthop->family), state); + + switch (nexthop->family) { + case AF_INET: + case AF_INET6: + siphash24_compress(&nexthop->gw, FAMILY_ADDRESS_SIZE(nexthop->family), state); + + break; + default: + /* treat any other address family as AF_UNSPEC */ + break; + } +} + +static int nexthop_compare_func(const NextHop *a, const NextHop *b) { + int r; + + r = CMP(a->id, b->id); + if (r != 0) + return r; + + r = CMP(a->oif, b->oif); + if (r != 0) + return r; + + r = CMP(a->family, b->family); + if (r != 0) + return r; + + switch (a->family) { + case AF_INET: + case AF_INET6: + + r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family)); + if (r != 0) + return r; + + return 0; + default: + /* treat any other address family as AF_UNSPEC */ + return 0; + } +} + +DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( + nexthop_hash_ops, + NextHop, + nexthop_hash_func, + nexthop_compare_func, + nexthop_free); + +bool nexthop_equal(NextHop *r1, NextHop *r2) { + if (r1 == r2) + return true; + + if (!r1 || !r2) + return false; + + return nexthop_compare_func(r1, r2) == 0; +} + +int nexthop_get(Link *link, NextHop *in, NextHop **ret) { + NextHop *existing; + + assert(link); + assert(in); + + existing = set_get(link->nexthops, in); + if (existing) { + if (ret) + *ret = existing; + return 1; + } + + existing = set_get(link->nexthops_foreign, in); + if (existing) { + if (ret) + *ret = existing; + return 0; + } + + return -ENOENT; +} + +static int nexthop_add_internal(Link *link, Set **nexthops, NextHop *in, NextHop **ret) { + _cleanup_(nexthop_freep) NextHop *nexthop = NULL; + int r; + + assert(link); + assert(nexthops); + assert(in); + + r = nexthop_new(&nexthop); + if (r < 0) + return r; + + nexthop->id = in->id; + nexthop->oif = in->oif; + nexthop->family = in->family; + nexthop->gw = in->gw; + + r = set_ensure_allocated(nexthops, &nexthop_hash_ops); + if (r < 0) + return r; + + r = set_put(*nexthops, nexthop); + if (r < 0) + return r; + if (r == 0) + return -EEXIST; + + nexthop->link = link; + + if (ret) + *ret = nexthop; + + nexthop = NULL; + + return 0; +} + +int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret) { + return nexthop_add_internal(link, &link->nexthops_foreign, in, ret); +} + +int nexthop_add(Link *link, NextHop *in, NextHop **ret) { + NextHop *nexthop; + int r; + + r = nexthop_get(link, in, &nexthop); + if (r == -ENOENT) { + /* NextHop does not exist, create a new one */ + r = nexthop_add_internal(link, &link->nexthops, in, &nexthop); + if (r < 0) + return r; + } else if (r == 0) { + /* Take over a foreign nexthop */ + r = set_ensure_allocated(&link->nexthops, &nexthop_hash_ops); + if (r < 0) + return r; + + r = set_put(link->nexthops, nexthop); + if (r < 0) + return r; + + set_remove(link->nexthops_foreign, nexthop); + } else if (r == 1) { + /* NextHop exists, do nothing */ + ; + } else + return r; + + if (ret) + *ret = nexthop; + + return 0; +} + +static int nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -ESRCH) + log_link_warning_errno(link, r, "Could not drop nexthop: %m"); + + return 1; +} + +int nexthop_remove(NextHop *nexthop, Link *link, + link_netlink_message_handler_t callback) { + + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + assert(link->ifindex > 0); + assert(IN_SET(nexthop->family, AF_INET, AF_INET6)); + + r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &req, + RTM_DELNEXTHOP, nexthop->family, + nexthop->protocol); + if (r < 0) + return log_link_error_errno(link, r, "Could not create RTM_DELNEXTHOP message: %m"); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *gw = NULL; + + if (!in_addr_is_null(nexthop->family, &nexthop->gw)) + (void) in_addr_to_string(nexthop->family, &nexthop->gw, &gw); + + log_link_debug(link, "Removing nexthop: gw: %s", strna(gw)); + } + + if (in_addr_is_null(nexthop->family, &nexthop->gw) == 0) { + r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, nexthop->family, &nexthop->gw); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m"); + } + + r = netlink_call_async(link->manager->rtnl, NULL, req, + callback ?: nexthop_remove_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +int nexthop_configure( + NextHop *nexthop, + Link *link, + link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + assert(link->ifindex > 0); + assert(IN_SET(nexthop->family, AF_INET, AF_INET6)); + assert(callback); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *gw = NULL; + + if (!in_addr_is_null(nexthop->family, &nexthop->gw)) + (void) in_addr_to_string(nexthop->family, &nexthop->gw, &gw); + + log_link_debug(link, "Configuring nexthop: gw: %s", strna(gw)); + } + + r = sd_rtnl_message_new_nexthop(link->manager->rtnl, &req, + RTM_NEWNEXTHOP, nexthop->family, + nexthop->protocol); + if (r < 0) + return log_link_error_errno(link, r, "Could not create RTM_NEWNEXTHOP message: %m"); + + r = sd_netlink_message_append_u32(req, NHA_ID, nexthop->id); + if (r < 0) + return log_link_error_errno(link, r, "Could not append NHA_ID attribute: %m"); + + r = sd_netlink_message_append_u32(req, NHA_OIF, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not append NHA_OIF attribute: %m"); + + if (in_addr_is_null(nexthop->family, &nexthop->gw) == 0) { + r = netlink_message_append_in_addr_union(req, NHA_GATEWAY, nexthop->family, &nexthop->gw); + if (r < 0) + return log_link_error_errno(link, r, "Could not append NHA_GATEWAY attribute: %m"); + + r = sd_rtnl_message_nexthop_set_family(req, nexthop->family); + if (r < 0) + return log_link_error_errno(link, r, "Could not set nexthop family: %m"); + } + + r = netlink_call_async(link->manager->rtnl, NULL, req, callback, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + r = nexthop_add(link, nexthop, &nexthop); + if (r < 0) + return log_link_error_errno(link, r, "Could not add nexthop: %m"); + + return 1; +} + +int nexthop_section_verify(NextHop *nh) { + if (section_is_invalid(nh->section)) + return -EINVAL; + + if (in_addr_is_null(nh->family, &nh->gw) < 0) + return -EINVAL; + + return 0; +} + +int config_parse_nexthop_id( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(nexthop_free_or_set_invalidp) NextHop *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = nexthop_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = safe_atou32(rvalue, &n->id); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Could not parse nexthop id \"%s\", ignoring assignment: %m", rvalue); + return 0; + } + + TAKE_PTR(n); + return 0; +} + +int config_parse_nexthop_gateway( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(nexthop_free_or_set_invalidp) NextHop *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = nexthop_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = in_addr_from_string_auto(rvalue, &n->family, &n->gw); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue); + return 0; + } + + TAKE_PTR(n); + return 0; +} diff --git a/src/network/networkd-nexthop.h b/src/network/networkd-nexthop.h new file mode 100644 index 00000000..28cbdad7 --- /dev/null +++ b/src/network/networkd-nexthop.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * Copyright © 2019 VMware, Inc. + */ + +#pragma once + +#include "conf-parser.h" +#include "macro.h" + +typedef struct NextHop NextHop; +typedef struct NetworkConfigSection NetworkConfigSection; + +#include "networkd-network.h" +#include "networkd-util.h" + +struct NextHop { + Network *network; + NetworkConfigSection *section; + + Link *link; + + unsigned char protocol; + + int family; + uint32_t oif; + uint32_t id; + + union in_addr_union gw; + + LIST_FIELDS(NextHop, nexthops); +}; + +extern const struct hash_ops nexthop_hash_ops; + +int nexthop_new(NextHop **ret); +void nexthop_free(NextHop *nexthop); +int nexthop_configure(NextHop *nexthop, Link *link, link_netlink_message_handler_t callback); +int nexthop_remove(NextHop *nexthop, Link *link, link_netlink_message_handler_t callback); + +int nexthop_get(Link *link, NextHop *in, NextHop **ret); +int nexthop_add(Link *link, NextHop *in, NextHop **ret); +int nexthop_add_foreign(Link *link, NextHop *in, NextHop **ret); +bool nexthop_equal(NextHop *r1, NextHop *r2); + +int nexthop_section_verify(NextHop *nexthop); + +DEFINE_NETWORK_SECTION_FUNCTIONS(NextHop, nexthop_free); + +CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_id); +CONFIG_PARSER_PROTOTYPE(config_parse_nexthop_gateway); diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c new file mode 100644 index 00000000..d48609f9 --- /dev/null +++ b/src/network/networkd-radv.c @@ -0,0 +1,806 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2017 Intel Corporation. All rights reserved. +***/ + +#include +#include + +#include "dns-domain.h" +#include "networkd-address.h" +#include "networkd-manager.h" +#include "networkd-radv.h" +#include "parse-util.h" +#include "sd-radv.h" +#include "string-util.h" +#include "string-table.h" +#include "strv.h" + +void prefix_free(Prefix *prefix) { + if (!prefix) + return; + + if (prefix->network) { + LIST_REMOVE(prefixes, prefix->network->static_prefixes, prefix); + assert(prefix->network->n_static_prefixes > 0); + prefix->network->n_static_prefixes--; + + if (prefix->section) + hashmap_remove(prefix->network->prefixes_by_section, + prefix->section); + } + + network_config_section_free(prefix->section); + sd_radv_prefix_unref(prefix->radv_prefix); + + free(prefix); +} + +static int prefix_new(Prefix **ret) { + _cleanup_(prefix_freep) Prefix *prefix = NULL; + + prefix = new0(Prefix, 1); + if (!prefix) + return -ENOMEM; + + if (sd_radv_prefix_new(&prefix->radv_prefix) < 0) + return -ENOMEM; + + *ret = TAKE_PTR(prefix); + + return 0; +} + +static int prefix_new_static(Network *network, const char *filename, + unsigned section_line, Prefix **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(prefix_freep) Prefix *prefix = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + if (section_line) { + prefix = hashmap_get(network->prefixes_by_section, n); + if (prefix) { + *ret = TAKE_PTR(prefix); + + return 0; + } + } + } + + r = prefix_new(&prefix); + if (r < 0) + return r; + + prefix->network = network; + LIST_APPEND(prefixes, network->static_prefixes, prefix); + network->n_static_prefixes++; + + if (filename) { + prefix->section = TAKE_PTR(n); + + r = hashmap_ensure_allocated(&network->prefixes_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(network->prefixes_by_section, prefix->section, prefix); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(prefix); + + return 0; +} + +static int route_prefix_new(RoutePrefix **ret) { + _cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL; + + prefix = new0(RoutePrefix, 1); + if (!prefix) + return -ENOMEM; + + if (sd_radv_route_prefix_new(&prefix->radv_route_prefix) < 0) + return -ENOMEM; + + *ret = TAKE_PTR(prefix); + + return 0; +} + +void route_prefix_free(RoutePrefix *prefix) { + if (!prefix) + return; + + if (prefix->network) { + LIST_REMOVE(route_prefixes, prefix->network->static_route_prefixes, prefix); + assert(prefix->network->n_static_route_prefixes > 0); + prefix->network->n_static_route_prefixes--; + + if (prefix->section) + hashmap_remove(prefix->network->route_prefixes_by_section, + prefix->section); + } + + network_config_section_free(prefix->section); + sd_radv_route_prefix_unref(prefix->radv_route_prefix); + + free(prefix); +} + +static int route_prefix_new_static(Network *network, const char *filename, + unsigned section_line, RoutePrefix **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(route_prefix_freep) RoutePrefix *prefix = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + if (section_line) { + prefix = hashmap_get(network->route_prefixes_by_section, n); + if (prefix) { + *ret = TAKE_PTR(prefix); + + return 0; + } + } + } + + r = route_prefix_new(&prefix); + if (r < 0) + return r; + + prefix->network = network; + LIST_APPEND(route_prefixes, network->static_route_prefixes, prefix); + network->n_static_route_prefixes++; + + if (filename) { + prefix->section = TAKE_PTR(n); + + r = hashmap_ensure_allocated(&network->route_prefixes_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(network->route_prefixes_by_section, prefix->section, prefix); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(prefix); + + return 0; +} + +int config_parse_prefix(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; + uint8_t prefixlen = 64; + union in_addr_union in6addr; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = prefix_new_static(network, filename, section_line, &p); + if (r < 0) + return r; + + r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Prefix is invalid, ignoring assignment: %s", rvalue); + return 0; + } + + if (sd_radv_prefix_set_prefix(p->radv_prefix, &in6addr.in6, prefixlen) < 0) + return -EADDRNOTAVAIL; + + log_syntax(unit, LOG_INFO, filename, line, r, "Found prefix %s", rvalue); + + p = NULL; + + return 0; +} + +int config_parse_prefix_flags(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; + _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; + int r, val; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = prefix_new_static(network, filename, section_line, &p); + if (r < 0) + return r; + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address flag, ignoring: %s", rvalue); + return 0; + } + + val = r; + + if (streq(lvalue, "OnLink")) + r = sd_radv_prefix_set_onlink(p->radv_prefix, val); + else if (streq(lvalue, "AddressAutoconfiguration")) + r = sd_radv_prefix_set_address_autoconfiguration(p->radv_prefix, val); + if (r < 0) + return r; + + p = NULL; + + return 0; +} + +int config_parse_prefix_lifetime(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; + _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; + usec_t usec; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = prefix_new_static(network, filename, section_line, &p); + if (r < 0) + return r; + + r = parse_sec(rvalue, &usec); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Lifetime is invalid, ignoring assignment: %s", rvalue); + return 0; + } + + /* a value of 0xffffffff represents infinity */ + if (streq(lvalue, "PreferredLifetimeSec")) + r = sd_radv_prefix_set_preferred_lifetime(p->radv_prefix, + DIV_ROUND_UP(usec, USEC_PER_SEC)); + else if (streq(lvalue, "ValidLifetimeSec")) + r = sd_radv_prefix_set_valid_lifetime(p->radv_prefix, + DIV_ROUND_UP(usec, USEC_PER_SEC)); + if (r < 0) + return r; + + p = NULL; + + return 0; +} + +int config_parse_route_prefix(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL; + uint8_t prefixlen = 64; + union in_addr_union in6addr; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_prefix_new_static(network, filename, section_line, &p); + if (r < 0) + return r; + + r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Route prefix is invalid, ignoring assignment: %s", rvalue); + return 0; + } + + if (sd_radv_prefix_set_route_prefix(p->radv_route_prefix, &in6addr.in6, prefixlen) < 0) + return -EADDRNOTAVAIL; + + log_syntax(unit, LOG_INFO, filename, line, r, "Found route prefix %s", rvalue); + + p = NULL; + + return 0; +} + +int config_parse_route_prefix_lifetime(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; + _cleanup_(route_prefix_free_or_set_invalidp) RoutePrefix *p = NULL; + usec_t usec; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_prefix_new_static(network, filename, section_line, &p); + if (r < 0) + return r; + + r = parse_sec(rvalue, &usec); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Route lifetime is invalid, ignoring assignment: %s", rvalue); + return 0; + } + + /* a value of 0xffffffff represents infinity */ + r = sd_radv_route_prefix_set_lifetime(p->radv_route_prefix, DIV_ROUND_UP(usec, USEC_PER_SEC)); + if (r < 0) + return r; + + p = NULL; + + return 0; +} + +static int radv_get_ip6dns(Network *network, struct in6_addr **dns, + size_t *n_dns) { + _cleanup_free_ struct in6_addr *addresses = NULL; + size_t i, n_addresses = 0, n_allocated = 0; + + assert(network); + assert(dns); + assert(n_dns); + + for (i = 0; i < network->n_dns; i++) { + union in_addr_union *addr; + + if (network->dns[i].family != AF_INET6) + continue; + + addr = &network->dns[i].address; + + if (in_addr_is_null(AF_INET6, addr) || + in_addr_is_link_local(AF_INET6, addr) || + in_addr_is_localhost(AF_INET6, addr)) + continue; + + if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) + return -ENOMEM; + + addresses[n_addresses++] = addr->in6; + } + + if (addresses) { + *dns = TAKE_PTR(addresses); + + *n_dns = n_addresses; + } + + return n_addresses; +} + +static int radv_set_dns(Link *link, Link *uplink) { + _cleanup_free_ struct in6_addr *dns = NULL; + size_t n_dns; + usec_t lifetime_usec; + int r; + + if (!link->network->router_emit_dns) + return 0; + + if (link->network->router_dns) { + dns = newdup(struct in6_addr, link->network->router_dns, + link->network->n_router_dns); + if (!dns) + return -ENOMEM; + + n_dns = link->network->n_router_dns; + lifetime_usec = link->network->router_dns_lifetime_usec; + + goto set_dns; + } + + lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC; + + r = radv_get_ip6dns(link->network, &dns, &n_dns); + if (r > 0) + goto set_dns; + + if (uplink) { + if (!uplink->network) { + log_link_debug(uplink, "Cannot fetch DNS servers as uplink interface is not managed by us"); + return 0; + } + + r = radv_get_ip6dns(uplink->network, &dns, &n_dns); + if (r > 0) + goto set_dns; + } + + return 0; + + set_dns: + return sd_radv_set_rdnss(link->radv, + DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), + dns, n_dns); +} + +static int radv_set_domains(Link *link, Link *uplink) { + OrderedSet *search_domains; + usec_t lifetime_usec; + _cleanup_free_ char **s = NULL; /* just free() because the strings are owned by the set */ + + if (!link->network->router_emit_domains) + return 0; + + search_domains = link->network->router_search_domains; + lifetime_usec = link->network->router_dns_lifetime_usec; + + if (search_domains) + goto set_domains; + + lifetime_usec = SD_RADV_DEFAULT_DNS_LIFETIME_USEC; + + search_domains = link->network->search_domains; + if (search_domains) + goto set_domains; + + if (uplink) { + if (!uplink->network) { + log_link_debug(uplink, "Cannot fetch DNS search domains as uplink interface is not managed by us"); + return 0; + } + + search_domains = uplink->network->search_domains; + if (search_domains) + goto set_domains; + } + + return 0; + + set_domains: + s = ordered_set_get_strv(search_domains); + if (!s) + return log_oom(); + + return sd_radv_set_dnssl(link->radv, + DIV_ROUND_UP(lifetime_usec, USEC_PER_SEC), + s); + +} + +int radv_emit_dns(Link *link) { + Link *uplink; + int r; + + uplink = manager_find_uplink(link->manager, link); + + r = radv_set_dns(link, uplink); + if (r < 0) + log_link_warning_errno(link, r, "Could not set RA DNS: %m"); + + r = radv_set_domains(link, uplink); + if (r < 0) + log_link_warning_errno(link, r, "Could not set RA Domains: %m"); + + return 0; +} + +int radv_configure(Link *link) { + RoutePrefix *q; + Prefix *p; + int r; + + assert(link); + assert(link->network); + + r = sd_radv_new(&link->radv); + if (r < 0) + return r; + + r = sd_radv_attach_event(link->radv, NULL, 0); + if (r < 0) + return r; + + r = sd_radv_set_mac(link->radv, &link->mac); + if (r < 0) + return r; + + r = sd_radv_set_ifindex(link->radv, link->ifindex); + if (r < 0) + return r; + + r = sd_radv_set_managed_information(link->radv, link->network->router_managed); + if (r < 0) + return r; + + r = sd_radv_set_other_information(link->radv, link->network->router_other_information); + if (r < 0) + return r; + + /* a value of 0xffffffff represents infinity, 0x0 means this host is + not a router */ + r = sd_radv_set_router_lifetime(link->radv, + DIV_ROUND_UP(link->network->router_lifetime_usec, USEC_PER_SEC)); + if (r < 0) + return r; + + if (link->network->router_lifetime_usec > 0) { + r = sd_radv_set_preference(link->radv, + link->network->router_preference); + if (r < 0) + return r; + } + + if (IN_SET(link->network->router_prefix_delegation, + RADV_PREFIX_DELEGATION_STATIC, + RADV_PREFIX_DELEGATION_BOTH)) { + + LIST_FOREACH(prefixes, p, link->network->static_prefixes) { + r = sd_radv_add_prefix(link->radv, p->radv_prefix, false); + if (r == -EEXIST) + continue; + if (r == -ENOEXEC) { + log_link_warning_errno(link, r, "[IPv6Prefix] section configured without Prefix= setting, ignoring section."); + continue; + } + if (r < 0) + return r; + } + + LIST_FOREACH(route_prefixes, q, link->network->static_route_prefixes) { + r = sd_radv_add_route_prefix(link->radv, q->radv_route_prefix, false); + if (r == -EEXIST) + continue; + if (r < 0) + return r; + } + + } + + return radv_emit_dns(link); +} + +int config_parse_radv_dns( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + union in_addr_union a; + + r = extract_first_word(&p, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + break; + + if (in_addr_from_string(AF_INET6, w, &a) >= 0) { + struct in6_addr *m; + + m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr)); + if (!m) + return log_oom(); + + m[n->n_router_dns++] = a.in6; + n->router_dns = m; + + } else + log_syntax(unit, LOG_ERR, filename, line, 0, + "Failed to parse DNS server address, ignoring: %s", w); + } + + return 0; +} + +int config_parse_radv_search_domains( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL, *idna = NULL; + + r = extract_first_word(&p, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + break; + + r = dns_name_apply_idna(w, &idna); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to apply IDNA to domain name '%s', ignoring: %m", w); + continue; + } else if (r == 0) + /* transfer ownership to simplify subsequent operations */ + idna = TAKE_PTR(w); + + r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops); + if (r < 0) + return r; + + r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna)); + if (r < 0) + return r; + } + + return 0; +} + +static const char * const radv_prefix_delegation_table[_RADV_PREFIX_DELEGATION_MAX] = { + [RADV_PREFIX_DELEGATION_NONE] = "no", + [RADV_PREFIX_DELEGATION_STATIC] = "static", + [RADV_PREFIX_DELEGATION_DHCP6] = "dhcpv6", + [RADV_PREFIX_DELEGATION_BOTH] = "yes", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN( + radv_prefix_delegation, + RADVPrefixDelegation, + RADV_PREFIX_DELEGATION_BOTH); + +int config_parse_router_prefix_delegation( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + RADVPrefixDelegation d; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + d = radv_prefix_delegation_from_string(rvalue); + if (d < 0) { + log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid router prefix delegation '%s', ignoring assignment.", rvalue); + return 0; + } + + network->router_prefix_delegation = d; + + return 0; +} + +int config_parse_router_preference(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(rvalue, "high")) + network->router_preference = SD_NDISC_PREFERENCE_HIGH; + else if (STR_IN_SET(rvalue, "medium", "normal", "default")) + network->router_preference = SD_NDISC_PREFERENCE_MEDIUM; + else if (streq(rvalue, "low")) + network->router_preference = SD_NDISC_PREFERENCE_LOW; + else + log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Router preference '%s' is invalid, ignoring assignment: %m", rvalue); + + return 0; +} diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h new file mode 100644 index 00000000..21b323e8 --- /dev/null +++ b/src/network/networkd-radv.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2017 Intel Corporation. All rights reserved. +***/ + +#include "conf-parser.h" +#include "networkd-address.h" +#include "networkd-link.h" +#include "networkd-util.h" + +typedef struct Prefix Prefix; +typedef struct RoutePrefix RoutePrefix; + +typedef enum RADVPrefixDelegation { + RADV_PREFIX_DELEGATION_NONE, + RADV_PREFIX_DELEGATION_STATIC, + RADV_PREFIX_DELEGATION_DHCP6, + RADV_PREFIX_DELEGATION_BOTH, + _RADV_PREFIX_DELEGATION_MAX, + _RADV_PREFIX_DELEGATION_INVALID = -1, +} RADVPrefixDelegation; + +struct Prefix { + Network *network; + NetworkConfigSection *section; + + sd_radv_prefix *radv_prefix; + + LIST_FIELDS(Prefix, prefixes); +}; + +struct RoutePrefix { + Network *network; + NetworkConfigSection *section; + + sd_radv_route_prefix *radv_route_prefix; + + LIST_FIELDS(RoutePrefix, route_prefixes); +}; + +void prefix_free(Prefix *prefix); + +DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free); + +void route_prefix_free(RoutePrefix *prefix); + +DEFINE_NETWORK_SECTION_FUNCTIONS(RoutePrefix, route_prefix_free); + +int radv_emit_dns(Link *link); +int radv_configure(Link *link); + +const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_; +RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_router_prefix_delegation); +CONFIG_PARSER_PROTOTYPE(config_parse_router_preference); +CONFIG_PARSER_PROTOTYPE(config_parse_prefix); +CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags); +CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime); +CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns); +CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains); +CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix); +CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix_lifetime); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c new file mode 100644 index 00000000..592de4e4 --- /dev/null +++ b/src/network/networkd-route.c @@ -0,0 +1,1517 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "conf-parser.h" +#include "in-addr-util.h" +#include "missing_network.h" +#include "netlink-util.h" +#include "networkd-ipv4ll.h" +#include "networkd-manager.h" +#include "networkd-route.h" +#include "parse-util.h" +#include "set.h" +#include "string-table.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "sysctl-util.h" +#include "util.h" + +#define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U + +static unsigned routes_max(void) { + static thread_local unsigned cached = 0; + + _cleanup_free_ char *s4 = NULL, *s6 = NULL; + unsigned val4 = ROUTES_DEFAULT_MAX_PER_FAMILY, val6 = ROUTES_DEFAULT_MAX_PER_FAMILY; + + if (cached > 0) + return cached; + + if (sysctl_read("net/ipv4/route/max_size", &s4) >= 0) { + truncate_nl(s4); + if (safe_atou(s4, &val4) >= 0 && + val4 == 2147483647U) + /* This is the default "no limit" value in the kernel */ + val4 = ROUTES_DEFAULT_MAX_PER_FAMILY; + } + + if (sysctl_read("net/ipv6/route/max_size", &s6) >= 0) { + truncate_nl(s6); + (void) safe_atou(s6, &val6); + } + + cached = MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val4) + + MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val6); + return cached; +} + +int route_new(Route **ret) { + _cleanup_(route_freep) Route *route = NULL; + + route = new(Route, 1); + if (!route) + return -ENOMEM; + + *route = (Route) { + .family = AF_UNSPEC, + .scope = RT_SCOPE_UNIVERSE, + .protocol = RTPROT_UNSPEC, + .type = RTN_UNICAST, + .table = RT_TABLE_MAIN, + .lifetime = USEC_INFINITY, + .quickack = -1, + .fast_open_no_cookie = -1, + .gateway_onlink = -1, + .ttl_propagate = -1, + }; + + *ret = TAKE_PTR(route); + + return 0; +} + +static int route_new_static(Network *network, const char *filename, unsigned section_line, Route **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(route_freep) Route *route = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + route = hashmap_get(network->routes_by_section, n); + if (route) { + *ret = TAKE_PTR(route); + + return 0; + } + } + + if (network->n_static_routes >= routes_max()) + return -E2BIG; + + r = route_new(&route); + if (r < 0) + return r; + + route->protocol = RTPROT_STATIC; + route->network = network; + LIST_PREPEND(routes, network->static_routes, route); + network->n_static_routes++; + + if (filename) { + route->section = TAKE_PTR(n); + + r = hashmap_ensure_allocated(&network->routes_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(network->routes_by_section, route->section, route); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(route); + + return 0; +} + +void route_free(Route *route) { + if (!route) + return; + + if (route->network) { + LIST_REMOVE(routes, route->network->static_routes, route); + + assert(route->network->n_static_routes > 0); + route->network->n_static_routes--; + + if (route->section) + hashmap_remove(route->network->routes_by_section, route->section); + } + + network_config_section_free(route->section); + + if (route->link) { + set_remove(route->link->routes, route); + set_remove(route->link->routes_foreign, route); + } + + sd_event_source_unref(route->expire); + + free(route); +} + +static void route_hash_func(const Route *route, struct siphash *state) { + assert(route); + + siphash24_compress(&route->family, sizeof(route->family), state); + + switch (route->family) { + case AF_INET: + case AF_INET6: + siphash24_compress(&route->dst_prefixlen, sizeof(route->dst_prefixlen), state); + siphash24_compress(&route->dst, FAMILY_ADDRESS_SIZE(route->family), state); + + siphash24_compress(&route->src_prefixlen, sizeof(route->src_prefixlen), state); + siphash24_compress(&route->src, FAMILY_ADDRESS_SIZE(route->family), state); + + siphash24_compress(&route->gw, FAMILY_ADDRESS_SIZE(route->family), state); + + siphash24_compress(&route->prefsrc, FAMILY_ADDRESS_SIZE(route->family), state); + + siphash24_compress(&route->tos, sizeof(route->tos), state); + siphash24_compress(&route->priority, sizeof(route->priority), state); + siphash24_compress(&route->table, sizeof(route->table), state); + siphash24_compress(&route->protocol, sizeof(route->protocol), state); + siphash24_compress(&route->scope, sizeof(route->scope), state); + siphash24_compress(&route->type, sizeof(route->type), state); + + siphash24_compress(&route->initcwnd, sizeof(route->initcwnd), state); + siphash24_compress(&route->initrwnd, sizeof(route->initrwnd), state); + + break; + default: + /* treat any other address family as AF_UNSPEC */ + break; + } +} + +static int route_compare_func(const Route *a, const Route *b) { + int r; + + r = CMP(a->family, b->family); + if (r != 0) + return r; + + switch (a->family) { + case AF_INET: + case AF_INET6: + r = CMP(a->dst_prefixlen, b->dst_prefixlen); + if (r != 0) + return r; + + r = memcmp(&a->dst, &b->dst, FAMILY_ADDRESS_SIZE(a->family)); + if (r != 0) + return r; + + r = CMP(a->src_prefixlen, b->src_prefixlen); + if (r != 0) + return r; + + r = memcmp(&a->src, &b->src, FAMILY_ADDRESS_SIZE(a->family)); + if (r != 0) + return r; + + r = memcmp(&a->gw, &b->gw, FAMILY_ADDRESS_SIZE(a->family)); + if (r != 0) + return r; + + r = memcmp(&a->prefsrc, &b->prefsrc, FAMILY_ADDRESS_SIZE(a->family)); + if (r != 0) + return r; + + r = CMP(a->tos, b->tos); + if (r != 0) + return r; + + r = CMP(a->priority, b->priority); + if (r != 0) + return r; + + r = CMP(a->table, b->table); + if (r != 0) + return r; + + r = CMP(a->protocol, b->protocol); + if (r != 0) + return r; + + r = CMP(a->scope, b->scope); + if (r != 0) + return r; + + r = CMP(a->type, b->type); + if (r != 0) + return r; + + r = CMP(a->initcwnd, b->initcwnd); + if (r != 0) + return r; + + r = CMP(a->initrwnd, b->initrwnd); + if (r != 0) + return r; + + return 0; + default: + /* treat any other address family as AF_UNSPEC */ + return 0; + } +} + +DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR( + route_hash_ops, + Route, + route_hash_func, + route_compare_func, + route_free); + +bool route_equal(Route *r1, Route *r2) { + if (r1 == r2) + return true; + + if (!r1 || !r2) + return false; + + return route_compare_func(r1, r2) == 0; +} + +int route_get(Link *link, Route *in, Route **ret) { + + Route *existing; + + assert(link); + assert(in); + + existing = set_get(link->routes, in); + if (existing) { + if (ret) + *ret = existing; + return 1; + } + + existing = set_get(link->routes_foreign, in); + if (existing) { + if (ret) + *ret = existing; + return 0; + } + + return -ENOENT; +} + +static int route_add_internal(Link *link, Set **routes, Route *in, Route **ret) { + + _cleanup_(route_freep) Route *route = NULL; + int r; + + assert(link); + assert(routes); + assert(in); + + r = route_new(&route); + if (r < 0) + return r; + + route->family = in->family; + route->src = in->src; + route->src_prefixlen = in->src_prefixlen; + route->dst = in->dst; + route->dst_prefixlen = in->dst_prefixlen; + route->gw = in->gw; + route->prefsrc = in->prefsrc; + route->scope = in->scope; + route->protocol = in->protocol; + route->type = in->type; + route->tos = in->tos; + route->priority = in->priority; + route->table = in->table; + route->initcwnd = in->initcwnd; + route->initrwnd = in->initrwnd; + route->lifetime = in->lifetime; + + r = set_ensure_allocated(routes, &route_hash_ops); + if (r < 0) + return r; + + r = set_put(*routes, route); + if (r < 0) + return r; + if (r == 0) + return -EEXIST; + + route->link = link; + + if (ret) + *ret = route; + + route = NULL; + + return 0; +} + +int route_add_foreign(Link *link, Route *in, Route **ret) { + return route_add_internal(link, &link->routes_foreign, in, ret); +} + +int route_add(Link *link, Route *in, Route **ret) { + + Route *route; + int r; + + r = route_get(link, in, &route); + if (r == -ENOENT) { + /* Route does not exist, create a new one */ + r = route_add_internal(link, &link->routes, in, &route); + if (r < 0) + return r; + } else if (r == 0) { + /* Take over a foreign route */ + r = set_ensure_allocated(&link->routes, &route_hash_ops); + if (r < 0) + return r; + + r = set_put(link->routes, route); + if (r < 0) + return r; + + set_remove(link->routes_foreign, route); + } else if (r == 1) { + /* Route exists, do nothing */ + ; + } else + return r; + + if (ret) + *ret = route; + + return 0; +} + +static int route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -ESRCH) + log_link_warning_errno(link, r, "Could not drop route: %m"); + + return 1; +} + +int route_remove(Route *route, Link *link, + link_netlink_message_handler_t callback) { + + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + assert(link->ifindex > 0); + assert(IN_SET(route->family, AF_INET, AF_INET6)); + + r = sd_rtnl_message_new_route(link->manager->rtnl, &req, + RTM_DELROUTE, route->family, + route->protocol); + if (r < 0) + return log_link_error_errno(link, r, "Could not create RTM_DELROUTE message: %m"); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL; + char scope[ROUTE_SCOPE_STR_MAX], table[ROUTE_TABLE_STR_MAX], protocol[ROUTE_PROTOCOL_STR_MAX]; + + if (!in_addr_is_null(route->family, &route->dst)) { + (void) in_addr_to_string(route->family, &route->dst, &dst); + (void) asprintf(&dst_prefixlen, "/%u", route->dst_prefixlen); + } + if (!in_addr_is_null(route->family, &route->src)) + (void) in_addr_to_string(route->family, &route->src, &src); + if (!in_addr_is_null(route->family, &route->gw)) + (void) in_addr_to_string(route->family, &route->gw, &gw); + if (!in_addr_is_null(route->family, &route->prefsrc)) + (void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc); + + log_link_debug(link, "Removing route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s", + strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc), + format_route_scope(route->scope, scope, sizeof(scope)), + format_route_table(route->table, table, sizeof(table)), + format_route_protocol(route->protocol, protocol, sizeof(protocol)), + strna(route_type_to_string(route->type))); + } + + if (in_addr_is_null(route->family, &route->gw) == 0) { + r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->family, &route->gw); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m"); + } + + if (route->dst_prefixlen) { + r = netlink_message_append_in_addr_union(req, RTA_DST, route->family, &route->dst); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_DST attribute: %m"); + + r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Could not set destination prefix length: %m"); + } + + if (route->src_prefixlen) { + r = netlink_message_append_in_addr_union(req, RTA_SRC, route->family, &route->src); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_SRC attribute: %m"); + + r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Could not set source prefix length: %m"); + } + + if (in_addr_is_null(route->family, &route->prefsrc) == 0) { + r = netlink_message_append_in_addr_union(req, RTA_PREFSRC, route->family, &route->prefsrc); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_PREFSRC attribute: %m"); + } + + r = sd_rtnl_message_route_set_scope(req, route->scope); + if (r < 0) + return log_link_error_errno(link, r, "Could not set scope: %m"); + + r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m"); + + if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) { + r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m"); + } + + r = netlink_call_async(link->manager->rtnl, NULL, req, + callback ?: route_remove_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { + Route *route = userdata; + int r; + + assert(route); + + r = route_remove(route, route->link, NULL); + if (r < 0) + log_warning_errno(r, "Could not remove route: %m"); + else + route_free(route); + + return 1; +} + +int route_configure( + Route *route, + Link *link, + link_netlink_message_handler_t callback) { + + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + assert(link->ifindex > 0); + assert(IN_SET(route->family, AF_INET, AF_INET6)); + assert(callback); + + if (route_get(link, route, NULL) <= 0 && + set_size(link->routes) >= routes_max()) + return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG), + "Too many routes are configured, refusing: %m"); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL; + char scope[ROUTE_SCOPE_STR_MAX], table[ROUTE_TABLE_STR_MAX], protocol[ROUTE_PROTOCOL_STR_MAX]; + + if (!in_addr_is_null(route->family, &route->dst)) { + (void) in_addr_to_string(route->family, &route->dst, &dst); + (void) asprintf(&dst_prefixlen, "/%u", route->dst_prefixlen); + } + if (!in_addr_is_null(route->family, &route->src)) + (void) in_addr_to_string(route->family, &route->src, &src); + if (!in_addr_is_null(route->family, &route->gw)) + (void) in_addr_to_string(route->family, &route->gw, &gw); + if (!in_addr_is_null(route->family, &route->prefsrc)) + (void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc); + + log_link_debug(link, "Configuring route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s", + strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc), + format_route_scope(route->scope, scope, sizeof(scope)), + format_route_table(route->table, table, sizeof(table)), + format_route_protocol(route->protocol, protocol, sizeof(protocol)), + strna(route_type_to_string(route->type))); + } + + r = sd_rtnl_message_new_route(link->manager->rtnl, &req, + RTM_NEWROUTE, route->family, + route->protocol); + if (r < 0) + return log_link_error_errno(link, r, "Could not create RTM_NEWROUTE message: %m"); + + if (in_addr_is_null(route->family, &route->gw) == 0) { + r = netlink_message_append_in_addr_union(req, RTA_GATEWAY, route->family, &route->gw); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_GATEWAY attribute: %m"); + + r = sd_rtnl_message_route_set_family(req, route->family); + if (r < 0) + return log_link_error_errno(link, r, "Could not set route family: %m"); + } + + if (route->dst_prefixlen > 0) { + r = netlink_message_append_in_addr_union(req, RTA_DST, route->family, &route->dst); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_DST attribute: %m"); + + r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Could not set destination prefix length: %m"); + } + + if (route->src_prefixlen > 0) { + r = netlink_message_append_in_addr_union(req, RTA_SRC, route->family, &route->src); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_SRC attribute: %m"); + + r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen); + if (r < 0) + return log_link_error_errno(link, r, "Could not set source prefix length: %m"); + } + + if (in_addr_is_null(route->family, &route->prefsrc) == 0) { + r = netlink_message_append_in_addr_union(req, RTA_PREFSRC, route->family, &route->prefsrc); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_PREFSRC attribute: %m"); + } + + r = sd_rtnl_message_route_set_scope(req, route->scope); + if (r < 0) + return log_link_error_errno(link, r, "Could not set scope: %m"); + + if (route->gateway_onlink >= 0) + SET_FLAG(route->flags, RTNH_F_ONLINK, route->gateway_onlink); + + r = sd_rtnl_message_route_set_flags(req, route->flags); + if (r < 0) + return log_link_error_errno(link, r, "Could not set flags: %m"); + + if (route->table != RT_TABLE_MAIN) { + if (route->table < 256) { + r = sd_rtnl_message_route_set_table(req, route->table); + if (r < 0) + return log_link_error_errno(link, r, "Could not set route table: %m"); + } else { + r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC); + if (r < 0) + return log_link_error_errno(link, r, "Could not set route table: %m"); + + /* Table attribute to allow more than 256. */ + r = sd_netlink_message_append_data(req, RTA_TABLE, &route->table, sizeof(route->table)); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_TABLE attribute: %m"); + } + } + + r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_PRIORITY attribute: %m"); + + r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_PREF attribute: %m"); + + if (route->lifetime != USEC_INFINITY && kernel_route_expiration_supported()) { + r = sd_netlink_message_append_u32(req, RTA_EXPIRES, + DIV_ROUND_UP(usec_sub_unsigned(route->lifetime, now(clock_boottime_or_monotonic())), USEC_PER_SEC)); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_EXPIRES attribute: %m"); + } + + r = sd_rtnl_message_route_set_type(req, route->type); + if (r < 0) + return log_link_error_errno(link, r, "Could not set route type: %m"); + + if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW)) { + r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m"); + } + + if (route->ttl_propagate >= 0) { + r = sd_netlink_message_append_u8(req, RTA_TTL_PROPAGATE, route->ttl_propagate); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_TTL_PROPAGATE attribute: %m"); + } + + r = sd_netlink_message_open_container(req, RTA_METRICS); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m"); + + if (route->mtu > 0) { + r = sd_netlink_message_append_u32(req, RTAX_MTU, route->mtu); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTAX_MTU attribute: %m"); + } + + if (route->initcwnd > 0) { + r = sd_netlink_message_append_u32(req, RTAX_INITCWND, route->initcwnd); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTAX_INITCWND attribute: %m"); + } + + if (route->initrwnd > 0) { + r = sd_netlink_message_append_u32(req, RTAX_INITRWND, route->initrwnd); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m"); + } + + if (route->quickack >= 0) { + r = sd_netlink_message_append_u32(req, RTAX_QUICKACK, route->quickack); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTAX_QUICKACK attribute: %m"); + } + + if (route->fast_open_no_cookie >= 0) { + r = sd_netlink_message_append_u32(req, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTAX_FASTOPEN_NO_COOKIE attribute: %m"); + } + + r = sd_netlink_message_close_container(req); + if (r < 0) + return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m"); + + r = netlink_call_async(link->manager->rtnl, NULL, req, callback, + link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + r = route_add(link, route, &route); + if (r < 0) + return log_link_error_errno(link, r, "Could not add route: %m"); + + /* TODO: drop expiration handling once it can be pushed into the kernel */ + if (route->lifetime != USEC_INFINITY && !kernel_route_expiration_supported()) { + r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), + route->lifetime, 0, route_expire_handler, route); + if (r < 0) + return log_link_error_errno(link, r, "Could not arm expiration timer: %m"); + } + + sd_event_source_unref(route->expire); + route->expire = TAKE_PTR(expire); + + return 1; +} + +int network_add_ipv4ll_route(Network *network) { + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r; + + assert(network); + + if (!network->ipv4ll_route) + return 0; + + /* IPv4LLRoute= is in [Network] section. */ + r = route_new_static(network, NULL, 0, &n); + if (r < 0) + return r; + + r = in_addr_from_string(AF_INET, "169.254.0.0", &n->dst); + if (r < 0) + return r; + + n->family = AF_INET; + n->dst_prefixlen = 16; + n->scope = RT_SCOPE_LINK; + n->scope_set = true; + n->table_set = true; + n->priority = IPV4LL_ROUTE_METRIC; + n->protocol = RTPROT_STATIC; + + TAKE_PTR(n); + return 0; +} + +int network_add_default_route_on_device(Network *network) { + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r; + + assert(network); + + if (!network->default_route_on_device) + return 0; + + /* DefaultRouteOnDevice= is in [Network] section. */ + r = route_new_static(network, NULL, 0, &n); + if (r < 0) + return r; + + n->family = AF_INET; + n->scope = RT_SCOPE_LINK; + n->scope_set = true; + n->protocol = RTPROT_STATIC; + + TAKE_PTR(n); + return 0; +} + +static const char * const route_type_table[__RTN_MAX] = { + [RTN_UNICAST] = "unicast", + [RTN_LOCAL] = "local", + [RTN_BROADCAST] = "broadcast", + [RTN_ANYCAST] = "anycast", + [RTN_MULTICAST] = "multicast", + [RTN_BLACKHOLE] = "blackhole", + [RTN_UNREACHABLE] = "unreachable", + [RTN_PROHIBIT] = "prohibit", + [RTN_THROW] = "throw", + [RTN_NAT] = "nat", + [RTN_XRESOLVE] = "xresolve", +}; + +assert_cc(__RTN_MAX <= UCHAR_MAX); +DEFINE_STRING_TABLE_LOOKUP(route_type, int); + +static const char * const route_scope_table[] = { + [RT_SCOPE_UNIVERSE] = "global", + [RT_SCOPE_SITE] = "site", + [RT_SCOPE_LINK] = "link", + [RT_SCOPE_HOST] = "host", + [RT_SCOPE_NOWHERE] = "nowhere", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_scope, int); + +const char *format_route_scope(int scope, char *buf, size_t size) { + const char *s; + char *p = buf; + + s = route_scope_to_string(scope); + if (s) + strpcpy(&p, size, s); + else + strpcpyf(&p, size, "%d", scope); + + return buf; +} + +static const char * const route_table_table[] = { + [RT_TABLE_DEFAULT] = "default", + [RT_TABLE_MAIN] = "main", + [RT_TABLE_LOCAL] = "local", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_table, int); + +const char *format_route_table(int table, char *buf, size_t size) { + const char *s; + char *p = buf; + + s = route_table_to_string(table); + if (s) + strpcpy(&p, size, s); + else + strpcpyf(&p, size, "%d", table); + + return buf; +} + +static const char * const route_protocol_table[] = { + [RTPROT_KERNEL] = "kernel", + [RTPROT_BOOT] = "boot", + [RTPROT_STATIC] = "static", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(route_protocol, int); + +static const char * const route_protocol_full_table[] = { + [RTPROT_REDIRECT] = "redirect", + [RTPROT_KERNEL] = "kernel", + [RTPROT_BOOT] = "boot", + [RTPROT_STATIC] = "static", + [RTPROT_GATED] = "gated", + [RTPROT_RA] = "ra", + [RTPROT_MRT] = "mrt", + [RTPROT_ZEBRA] = "zebra", + [RTPROT_BIRD] = "bird", + [RTPROT_DNROUTED] = "dnrouted", + [RTPROT_XORP] = "xorp", + [RTPROT_NTK] = "ntk", + [RTPROT_DHCP] = "dhcp", + [RTPROT_MROUTED] = "mrouted", + [RTPROT_BABEL] = "babel", + [RTPROT_BGP] = "bgp", + [RTPROT_ISIS] = "isis", + [RTPROT_OSPF] = "ospf", + [RTPROT_RIP] = "rip", + [RTPROT_EIGRP] = "eigrp", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(route_protocol_full, int); + +const char *format_route_protocol(int protocol, char *buf, size_t size) { + const char *s; + char *p = buf; + + s = route_protocol_full_to_string(protocol); + if (s) + strpcpy(&p, size, s); + else + strpcpyf(&p, size, "%d", protocol); + + return buf; +} + +int config_parse_gateway( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(section, "Network")) { + /* we are not in an Route section, so treat + * this as the special '0' section */ + r = route_new_static(network, NULL, 0, &n); + } else + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + if (n->family == AF_UNSPEC) + r = in_addr_from_string_auto(rvalue, &n->family, &n->gw); + else + r = in_addr_from_string(n->family, rvalue, &n->gw); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue); + return 0; + } + + TAKE_PTR(n); + return 0; +} + +int config_parse_preferred_src( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + if (n->family == AF_UNSPEC) + r = in_addr_from_string_auto(rvalue, &n->family, &n->prefsrc); + else + r = in_addr_from_string(n->family, rvalue, &n->prefsrc); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue); + return 0; + } + + TAKE_PTR(n); + return 0; +} + +int config_parse_destination( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + union in_addr_union *buffer; + unsigned char *prefixlen; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + if (streq(lvalue, "Destination")) { + buffer = &n->dst; + prefixlen = &n->dst_prefixlen; + } else if (streq(lvalue, "Source")) { + buffer = &n->src; + prefixlen = &n->src_prefixlen; + } else + assert_not_reached(lvalue); + + if (n->family == AF_UNSPEC) + r = in_addr_prefix_from_string_auto(rvalue, &n->family, buffer, prefixlen); + else + r = in_addr_prefix_from_string(rvalue, n->family, buffer, prefixlen); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, + "Invalid %s='%s', ignoring assignment: %m", lvalue, rvalue); + return 0; + } + + TAKE_PTR(n); + return 0; +} + +int config_parse_route_priority( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = safe_atou32(rvalue, &n->priority); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue); + return 0; + } + + TAKE_PTR(n); + return 0; +} + +int config_parse_route_scope( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = route_scope_from_string(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown route scope: %s", rvalue); + return 0; + } + + n->scope = r; + n->scope_set = true; + TAKE_PTR(n); + return 0; +} + +int config_parse_route_table( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = route_table_from_string(rvalue); + if (r >= 0) + n->table = r; + else { + r = safe_atou32(rvalue, &n->table); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue); + return 0; + } + } + + n->table_set = true; + TAKE_PTR(n); + return 0; +} + +int config_parse_gateway_onlink( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Could not parse %s=\"%s\", ignoring assignment: %m", lvalue, rvalue); + return 0; + } + + n->gateway_onlink = r; + + TAKE_PTR(n); + return 0; +} + +int config_parse_ipv6_route_preference( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r; + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + if (streq(rvalue, "low")) + n->pref = ICMPV6_ROUTER_PREF_LOW; + else if (streq(rvalue, "medium")) + n->pref = ICMPV6_ROUTER_PREF_MEDIUM; + else if (streq(rvalue, "high")) + n->pref = ICMPV6_ROUTER_PREF_HIGH; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown route preference: %s", rvalue); + return 0; + } + + TAKE_PTR(n); + return 0; +} + +int config_parse_route_protocol( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r; + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = route_protocol_from_string(rvalue); + if (r >= 0) + n->protocol = r; + else { + r = safe_atou8(rvalue , &n->protocol); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Could not parse route protocol \"%s\", ignoring assignment: %m", rvalue); + return 0; + } + } + + TAKE_PTR(n); + return 0; +} + +int config_parse_route_type( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int t, r; + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + t = route_type_from_string(rvalue); + if (t < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Could not parse route type \"%s\", ignoring assignment: %m", rvalue); + return 0; + } + + n->type = (unsigned char) t; + + TAKE_PTR(n); + return 0; +} + +int config_parse_tcp_window( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + Network *network = userdata; + uint64_t k; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = parse_size(rvalue, 1024, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Could not parse TCP %s \"%s\", ignoring assignment: %m", lvalue, rvalue); + return 0; + } + if (k > UINT32_MAX) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Specified TCP %s \"%s\" is too large, ignoring assignment: %m", lvalue, rvalue); + return 0; + } + + if (streq(lvalue, "InitialCongestionWindow")) + n->initcwnd = k; + else if (streq(lvalue, "InitialAdvertisedReceiveWindow")) + n->initrwnd = k; + else + assert_not_reached("Invalid TCP window type."); + + TAKE_PTR(n); + return 0; +} + +int config_parse_quickack( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + Network *network = userdata; + int k, r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + k = parse_boolean(rvalue); + if (k < 0) { + log_syntax(unit, LOG_ERR, filename, line, k, + "Failed to parse TCP quickack, ignoring: %s", rvalue); + return 0; + } + + n->quickack = !!k; + TAKE_PTR(n); + return 0; +} + +int config_parse_fast_open_no_cookie( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + Network *network = userdata; + int k, r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + k = parse_boolean(rvalue); + if (k < 0) { + log_syntax(unit, LOG_ERR, filename, line, k, + "Failed to parse TCP fastopen no cookie, ignoring: %s", rvalue); + return 0; + } + + n->fast_open_no_cookie = k; + TAKE_PTR(n); + return 0; +} + +int config_parse_route_mtu( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = config_parse_mtu(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &n->mtu, userdata); + if (r < 0) + return r; + + TAKE_PTR(n); + return 0; +} + +int config_parse_route_ttl_propagate( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = userdata; + _cleanup_(route_free_or_set_invalidp) Route *n = NULL; + int r, k; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = route_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + k = parse_boolean(rvalue); + if (k < 0) { + log_syntax(unit, LOG_ERR, filename, line, k, + "Failed to parse TTLPropagate= value, ignoring: %s", rvalue); + return 0; + } + + n->ttl_propagate = k; + + TAKE_PTR(n); + return 0; +} + +int route_section_verify(Route *route, Network *network) { + if (section_is_invalid(route->section)) + return -EINVAL; + + if (route->family == AF_UNSPEC) { + assert(route->section); + + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: Route section without Gateway=, Destination=, Source=, " + "or PreferredSource= field configured. " + "Ignoring [Route] section from line %u.", + route->section->filename, route->section->line); + } + + if (!route->table_set && IN_SET(route->type, RTN_LOCAL, RTN_BROADCAST, RTN_ANYCAST, RTN_NAT)) + route->table = RT_TABLE_LOCAL; + + if (!route->scope_set && route->family != AF_INET6) { + if (IN_SET(route->type, RTN_LOCAL, RTN_NAT)) + route->scope = RT_SCOPE_HOST; + else if (IN_SET(route->type, RTN_BROADCAST, RTN_ANYCAST, RTN_MULTICAST)) + route->scope = RT_SCOPE_LINK; + } + + if (network->n_static_addresses == 0 && + in_addr_is_null(route->family, &route->gw) == 0 && + route->gateway_onlink < 0) { + log_warning("%s: Gateway= without static address configured. " + "Enabling GatewayOnLink= option.", + network->filename); + route->gateway_onlink = true; + } + + return 0; +} diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h new file mode 100644 index 00000000..89d54020 --- /dev/null +++ b/src/network/networkd-route.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "macro.h" + +typedef struct Route Route; +typedef struct NetworkConfigSection NetworkConfigSection; + +#include "networkd-network.h" +#include "networkd-util.h" + +struct Route { + Network *network; + NetworkConfigSection *section; + + Link *link; + + int family; + int quickack; + int fast_open_no_cookie; + int ttl_propagate; + + unsigned char dst_prefixlen; + unsigned char src_prefixlen; + unsigned char scope; + bool scope_set; + unsigned char protocol; /* RTPROT_* */ + unsigned char type; /* RTN_* */ + unsigned char tos; + uint32_t priority; /* note that ip(8) calls this 'metric' */ + uint32_t table; + bool table_set; + uint32_t mtu; + uint32_t initcwnd; + uint32_t initrwnd; + unsigned char pref; + unsigned flags; + int gateway_onlink; + + union in_addr_union gw; + union in_addr_union dst; + union in_addr_union src; + union in_addr_union prefsrc; + + usec_t lifetime; + sd_event_source *expire; + + LIST_FIELDS(Route, routes); +}; + +extern const struct hash_ops route_hash_ops; + +int route_new(Route **ret); +void route_free(Route *route); +int route_configure(Route *route, Link *link, link_netlink_message_handler_t callback); +int route_remove(Route *route, Link *link, link_netlink_message_handler_t callback); + +int route_get(Link *link, Route *in, Route **ret); +int route_add(Link *link, Route *in, Route **ret); +int route_add_foreign(Link *link, Route *in, Route **ret); +bool route_equal(Route *r1, Route *r2); + +int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata); +int route_section_verify(Route *route, Network *network); + +DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free); + +int network_add_ipv4ll_route(Network *network); +int network_add_default_route_on_device(Network *network); + +const char* route_type_to_string(int t) _const_; +int route_type_from_string(const char *s) _pure_; + +#define ROUTE_SCOPE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("nowhere") + 1) +const char *format_route_scope(int scope, char *buf, size_t size); + +#define ROUTE_TABLE_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("default") + 1) +const char *format_route_table(int table, char *buf, size_t size); + +#define ROUTE_PROTOCOL_STR_MAX CONST_MAX(DECIMAL_STR_MAX(int), STRLEN("redirect") + 1) +const char *format_route_protocol(int protocol, char *buf, size_t size); + +CONFIG_PARSER_PROTOTYPE(config_parse_gateway); +CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src); +CONFIG_PARSER_PROTOTYPE(config_parse_destination); +CONFIG_PARSER_PROTOTYPE(config_parse_route_priority); +CONFIG_PARSER_PROTOTYPE(config_parse_route_scope); +CONFIG_PARSER_PROTOTYPE(config_parse_route_table); +CONFIG_PARSER_PROTOTYPE(config_parse_gateway_onlink); +CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_route_preference); +CONFIG_PARSER_PROTOTYPE(config_parse_route_protocol); +CONFIG_PARSER_PROTOTYPE(config_parse_route_type); +CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window); +CONFIG_PARSER_PROTOTYPE(config_parse_quickack); +CONFIG_PARSER_PROTOTYPE(config_parse_fast_open_no_cookie); +CONFIG_PARSER_PROTOTYPE(config_parse_route_ttl_propagate); +CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu); diff --git a/src/network/networkd-routing-policy-rule.c b/src/network/networkd-routing-policy-rule.c new file mode 100644 index 00000000..8203f87c --- /dev/null +++ b/src/network/networkd-routing-policy-rule.c @@ -0,0 +1,1378 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "af-list.h" +#include "alloc-util.h" +#include "conf-parser.h" +#include "fileio.h" +#include "ip-protocol-list.h" +#include "networkd-routing-policy-rule.h" +#include "netlink-util.h" +#include "networkd-manager.h" +#include "networkd-util.h" +#include "parse-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" + +int routing_policy_rule_new(RoutingPolicyRule **ret) { + RoutingPolicyRule *rule; + + rule = new(RoutingPolicyRule, 1); + if (!rule) + return -ENOMEM; + + *rule = (RoutingPolicyRule) { + .table = RT_TABLE_MAIN, + }; + + *ret = rule; + return 0; +} + +void routing_policy_rule_free(RoutingPolicyRule *rule) { + + if (!rule) + return; + + if (rule->network) { + LIST_REMOVE(rules, rule->network->rules, rule); + assert(rule->network->n_rules > 0); + rule->network->n_rules--; + + if (rule->section) + hashmap_remove(rule->network->rules_by_section, rule->section); + } + + if (rule->manager) { + if (set_get(rule->manager->rules, rule) == rule) + set_remove(rule->manager->rules, rule); + if (set_get(rule->manager->rules_foreign, rule) == rule) + set_remove(rule->manager->rules_foreign, rule); + } + + network_config_section_free(rule->section); + free(rule->iif); + free(rule->oif); + free(rule); +} + +static int routing_policy_rule_copy(RoutingPolicyRule *dest, RoutingPolicyRule *src) { + _cleanup_free_ char *iif = NULL, *oif = NULL; + + assert(dest); + assert(src); + + if (src->iif) { + iif = strdup(src->iif); + if (!iif) + return -ENOMEM; + } + + if (src->oif) { + oif = strdup(src->oif); + if (!oif) + return -ENOMEM; + } + + dest->family = src->family; + dest->from = src->from; + dest->from_prefixlen = src->from_prefixlen; + dest->to = src->to; + dest->to_prefixlen = src->to_prefixlen; + dest->invert_rule = src->invert_rule; + dest->tos = src->tos; + dest->fwmark = src->fwmark; + dest->fwmask = src->fwmask; + dest->priority = src->priority; + dest->table = src->table; + dest->iif = TAKE_PTR(iif); + dest->oif = TAKE_PTR(oif); + dest->protocol = src->protocol; + dest->sport = src->sport; + dest->dport = src->dport; + + return 0; +} + +static void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash *state) { + assert(rule); + + siphash24_compress(&rule->family, sizeof(rule->family), state); + + switch (rule->family) { + case AF_INET: + case AF_INET6: + siphash24_compress(&rule->from, FAMILY_ADDRESS_SIZE(rule->family), state); + siphash24_compress(&rule->from_prefixlen, sizeof(rule->from_prefixlen), state); + + siphash24_compress(&rule->to, FAMILY_ADDRESS_SIZE(rule->family), state); + siphash24_compress(&rule->to_prefixlen, sizeof(rule->to_prefixlen), state); + + siphash24_compress_boolean(rule->invert_rule, state); + + siphash24_compress(&rule->tos, sizeof(rule->tos), state); + siphash24_compress(&rule->fwmark, sizeof(rule->fwmark), state); + siphash24_compress(&rule->fwmask, sizeof(rule->fwmask), state); + siphash24_compress(&rule->priority, sizeof(rule->priority), state); + siphash24_compress(&rule->table, sizeof(rule->table), state); + + siphash24_compress(&rule->protocol, sizeof(rule->protocol), state); + siphash24_compress(&rule->sport, sizeof(rule->sport), state); + siphash24_compress(&rule->dport, sizeof(rule->dport), state); + + if (rule->iif) + siphash24_compress(rule->iif, strlen(rule->iif), state); + + if (rule->oif) + siphash24_compress(rule->oif, strlen(rule->oif), state); + + break; + default: + /* treat any other address family as AF_UNSPEC */ + break; + } +} + +static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPolicyRule *b) { + int r; + + r = CMP(a->family, b->family); + if (r != 0) + return r; + + switch (a->family) { + case AF_INET: + case AF_INET6: + r = CMP(a->from_prefixlen, b->from_prefixlen); + if (r != 0) + return r; + + r = memcmp(&a->from, &b->from, FAMILY_ADDRESS_SIZE(a->family)); + if (r != 0) + return r; + + r = CMP(a->to_prefixlen, b->to_prefixlen); + if (r != 0) + return r; + + r = memcmp(&a->to, &b->to, FAMILY_ADDRESS_SIZE(a->family)); + if (r != 0) + return r; + + r = CMP(a->invert_rule, b->invert_rule); + if (r != 0) + return r; + + r = CMP(a->tos, b->tos); + if (r != 0) + return r; + + r = CMP(a->fwmark, b->fwmark); + if (r != 0) + return r; + + r = CMP(a->fwmask, b->fwmask); + if (r != 0) + return r; + + r = CMP(a->priority, b->priority); + if (r != 0) + return r; + + r = CMP(a->table, b->table); + if (r != 0) + return r; + + r = CMP(a->protocol, b->protocol); + if (r != 0) + return r; + + r = memcmp(&a->sport, &b->sport, sizeof(a->sport)); + if (r != 0) + return r; + + r = memcmp(&a->dport, &b->dport, sizeof(a->dport)); + if (r != 0) + return r; + + r = strcmp_ptr(a->iif, b->iif); + if (r != 0) + return r; + + r = strcmp_ptr(a->oif, b->oif); + if (r != 0) + return r; + + return 0; + default: + /* treat any other address family as AF_UNSPEC */ + return 0; + } +} + +DEFINE_PRIVATE_HASH_OPS(routing_policy_rule_hash_ops, RoutingPolicyRule, routing_policy_rule_hash_func, routing_policy_rule_compare_func); + +int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) { + + RoutingPolicyRule *existing; + + assert(m); + + existing = set_get(m->rules, rule); + if (existing) { + if (ret) + *ret = existing; + return 1; + } + + existing = set_get(m->rules_foreign, rule); + if (existing) { + if (ret) + *ret = existing; + return 0; + } + + return -ENOENT; +} + +int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule) { + int r; + + assert(m); + + if (set_contains(m->rules_foreign, rule)) { + set_remove(m->rules_foreign, rule); + + r = set_ensure_allocated(&m->rules, &routing_policy_rule_hash_ops); + if (r < 0) + return r; + + r = set_put(m->rules, rule); + if (r < 0) + return r; + if (r == 0) + routing_policy_rule_free(rule); + } + + return -ENOENT; +} + +static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPolicyRule *in, RoutingPolicyRule **ret) { + _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL; + int r; + + assert(m); + assert(rules); + assert(in); + + r = routing_policy_rule_new(&rule); + if (r < 0) + return r; + + rule->manager = m; + + r = routing_policy_rule_copy(rule, in); + if (r < 0) + return r; + + r = set_ensure_allocated(rules, &routing_policy_rule_hash_ops); + if (r < 0) + return r; + + r = set_put(*rules, rule); + if (r < 0) + return r; + if (r == 0) + return -EEXIST; + + if (ret) + *ret = rule; + + TAKE_PTR(rule); + return 0; +} + +static int routing_policy_rule_add(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) { + return routing_policy_rule_add_internal(m, &m->rules, rule, ret); +} + +int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret) { + return routing_policy_rule_add_internal(m, &m->rules_foreign, rule, ret); +} + +static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(m); + assert(link); + assert(link->ifname); + + link->routing_policy_rule_remove_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + log_link_warning_errno(link, r, "Could not drop routing policy rule: %m"); + + return 1; +} + +int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *link, link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(routing_policy_rule); + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + assert(link->ifindex > 0); + assert(IN_SET(routing_policy_rule->family, AF_INET, AF_INET6)); + + r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_DELRULE, routing_policy_rule->family); + if (r < 0) + return log_error_errno(r, "Could not allocate RTM_DELRULE message: %m"); + + if (in_addr_is_null(routing_policy_rule->family, &routing_policy_rule->from) == 0) { + r = netlink_message_append_in_addr_union(m, FRA_SRC, routing_policy_rule->family, &routing_policy_rule->from); + if (r < 0) + return log_error_errno(r, "Could not append FRA_SRC attribute: %m"); + + r = sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m, routing_policy_rule->from_prefixlen); + if (r < 0) + return log_error_errno(r, "Could not set source prefix length: %m"); + } + + if (in_addr_is_null(routing_policy_rule->family, &routing_policy_rule->to) == 0) { + r = netlink_message_append_in_addr_union(m, FRA_DST, routing_policy_rule->family, &routing_policy_rule->to); + if (r < 0) + return log_error_errno(r, "Could not append FRA_DST attribute: %m"); + + r = sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m, routing_policy_rule->to_prefixlen); + if (r < 0) + return log_error_errno(r, "Could not set destination prefix length: %m"); + } + + r = netlink_call_async(link->manager->rtnl, NULL, m, + callback ?: routing_policy_rule_remove_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_error_errno(r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static int routing_policy_rule_new_static(Network *network, const char *filename, unsigned section_line, RoutingPolicyRule **ret) { + _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL; + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + rule = hashmap_get(network->rules_by_section, n); + if (rule) { + *ret = TAKE_PTR(rule); + + return 0; + } + } + + r = routing_policy_rule_new(&rule); + if (r < 0) + return r; + + rule->network = network; + LIST_APPEND(rules, network->rules, rule); + network->n_rules++; + + if (filename) { + rule->section = TAKE_PTR(n); + + r = hashmap_ensure_allocated(&network->rules_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(network->rules_by_section, rule->section, rule); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(rule); + + return 0; +} + +static int routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(rtnl); + assert(m); + assert(link); + assert(link->ifname); + assert(link->routing_policy_rule_messages > 0); + + link->routing_policy_rule_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_warning_errno(link, r, "Could not add routing policy rule: %m"); + link_enter_failed(link); + return 1; + } + + if (link->routing_policy_rule_messages == 0) { + log_link_debug(link, "Routing policy rule configured"); + link->routing_policy_rules_configured = true; + link_check_ready(link); + } + + return 1; +} + +int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netlink_message_handler_t callback) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(rule); + assert(link); + assert(link->ifindex > 0); + assert(link->manager); + assert(link->manager->rtnl); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *from = NULL, *to = NULL; + + (void) in_addr_to_string(rule->family, &rule->from, &from); + (void) in_addr_to_string(rule->family, &rule->to, &to); + + log_debug("Configuring routing policy rule: %s/%u -> %s/%u, iif: %s, oif: %s, table: %u", + from, rule->from_prefixlen, to, rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table); + } + + r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family); + if (r < 0) + return log_error_errno(r, "Could not allocate RTM_NEWRULE message: %m"); + + if (in_addr_is_null(rule->family, &rule->from) == 0) { + r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from); + if (r < 0) + return log_error_errno(r, "Could not append FRA_SRC attribute: %m"); + + r = sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(m, rule->from_prefixlen); + if (r < 0) + return log_error_errno(r, "Could not set source prefix length: %m"); + } + + if (in_addr_is_null(rule->family, &rule->to) == 0) { + r = netlink_message_append_in_addr_union(m, FRA_DST, rule->family, &rule->to); + if (r < 0) + return log_error_errno(r, "Could not append FRA_DST attribute: %m"); + + r = sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(m, rule->to_prefixlen); + if (r < 0) + return log_error_errno(r, "Could not set destination prefix length: %m"); + } + + r = sd_netlink_message_append_u32(m, FRA_PRIORITY, rule->priority); + if (r < 0) + return log_error_errno(r, "Could not append FRA_PRIORITY attribute: %m"); + + if (rule->tos > 0) { + r = sd_rtnl_message_routing_policy_rule_set_tos(m, rule->tos); + if (r < 0) + return log_error_errno(r, "Could not set ip rule tos: %m"); + } + + if (rule->table < 256) { + r = sd_rtnl_message_routing_policy_rule_set_table(m, rule->table); + if (r < 0) + return log_error_errno(r, "Could not set ip rule table: %m"); + } else { + r = sd_rtnl_message_routing_policy_rule_set_table(m, RT_TABLE_UNSPEC); + if (r < 0) + return log_error_errno(r, "Could not set ip rule table: %m"); + + r = sd_netlink_message_append_u32(m, FRA_TABLE, rule->table); + if (r < 0) + return log_error_errno(r, "Could not append FRA_TABLE attribute: %m"); + } + + if (rule->fwmark > 0) { + r = sd_netlink_message_append_u32(m, FRA_FWMARK, rule->fwmark); + if (r < 0) + return log_error_errno(r, "Could not append FRA_FWMARK attribute: %m"); + } + + if (rule->fwmask > 0) { + r = sd_netlink_message_append_u32(m, FRA_FWMASK, rule->fwmask); + if (r < 0) + return log_error_errno(r, "Could not append FRA_FWMASK attribute: %m"); + } + + if (rule->iif) { + r = sd_netlink_message_append_string(m, FRA_IFNAME, rule->iif); + if (r < 0) + return log_error_errno(r, "Could not append FRA_IFNAME attribute: %m"); + } + + if (rule->oif) { + r = sd_netlink_message_append_string(m, FRA_OIFNAME, rule->oif); + if (r < 0) + return log_error_errno(r, "Could not append FRA_OIFNAME attribute: %m"); + } + + r = sd_netlink_message_append_u8(m, FRA_IP_PROTO, rule->protocol); + if (r < 0) + return log_error_errno(r, "Could not append FRA_IP_PROTO attribute: %m"); + + if (rule->sport.start != 0 || rule->sport.end != 0) { + r = sd_netlink_message_append_data(m, FRA_SPORT_RANGE, &rule->sport, sizeof(rule->sport)); + if (r < 0) + return log_error_errno(r, "Could not append FRA_SPORT_RANGE attribute: %m"); + } + + if (rule->dport.start != 0 || rule->dport.end != 0) { + r = sd_netlink_message_append_data(m, FRA_DPORT_RANGE, &rule->dport, sizeof(rule->dport)); + if (r < 0) + return log_error_errno(r, "Could not append FRA_DPORT_RANGE attribute: %m"); + } + + if (rule->invert_rule) { + r = sd_rtnl_message_routing_policy_rule_set_flags(m, FIB_RULE_INVERT); + if (r < 0) + return log_error_errno(r, "Could not append FIB_RULE_INVERT attribute: %m"); + } + + rule->link = link; + + r = netlink_call_async(link->manager->rtnl, NULL, m, + callback ?: routing_policy_rule_handler, + link_netlink_destroy_callback, link); + if (r < 0) + return log_error_errno(r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + r = routing_policy_rule_add(link->manager, rule, NULL); + if (r < 0) + return log_error_errno(r, "Could not add rule: %m"); + + return 1; +} + +int routing_policy_rule_section_verify(RoutingPolicyRule *rule) { + int r; + + if (section_is_invalid(rule->section)) + return -EINVAL; + + if ((rule->family == AF_INET && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) || + (rule->family == AF_INET6 && FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4))) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: address family specified by Family= conflicts with the address " + "specified by To= or From=. Ignoring [RoutingPolicyRule] section from line %u.", + rule->section->filename, rule->section->line); + + if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6)) { + _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule6 = NULL; + + assert(rule->family == AF_UNSPEC); + + /* When Family=both, we need to copy the section, AF_INET and AF_INET6. */ + + r = routing_policy_rule_new_static(rule->network, NULL, 0, &rule6); + if (r < 0) + return r; + + r = routing_policy_rule_copy(rule6, rule); + if (r < 0) + return r; + + rule->family = AF_INET; + rule6->family = AF_INET6; + + TAKE_PTR(rule6); + } + + if (rule->family == AF_UNSPEC) { + if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) + rule->family = AF_INET6; + else + rule->family = AF_INET; + } + + return 0; +} + +static int parse_fwmark_fwmask(const char *s, uint32_t *fwmark, uint32_t *fwmask) { + _cleanup_free_ char *f = NULL; + char *p; + int r; + + assert(s); + + f = strdup(s); + if (!f) + return -ENOMEM; + + p = strchr(f, '/'); + if (p) + *p++ = '\0'; + + r = safe_atou32(f, fwmark); + if (r < 0) + return log_error_errno(r, "Failed to parse RPDB rule firewall mark, ignoring: %s", f); + + if (p) { + r = safe_atou32(p, fwmask); + if (r < 0) + return log_error_errno(r, "Failed to parse RPDB rule mask, ignoring: %s", f); + } + + return 0; +} + +int config_parse_routing_policy_rule_tos( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = safe_atou8(rvalue, &n->tos); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule tos, ignoring: %s", rvalue); + return 0; + } + + n = NULL; + + return 0; +} + +int config_parse_routing_policy_rule_priority( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = safe_atou32(rvalue, &n->priority); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule priority, ignoring: %s", rvalue); + return 0; + } + + n = NULL; + + return 0; +} + +int config_parse_routing_policy_rule_table( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = safe_atou32(rvalue, &n->table); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule table, ignoring: %s", rvalue); + return 0; + } + + n = NULL; + + return 0; +} + +int config_parse_routing_policy_rule_fwmark_mask( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = parse_fwmark_fwmask(rvalue, &n->fwmark, &n->fwmask); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", rvalue); + return 0; + } + + n = NULL; + + return 0; +} + +int config_parse_routing_policy_rule_prefix( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + union in_addr_union *buffer; + uint8_t *prefixlen; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + if (streq(lvalue, "To")) { + buffer = &n->to; + prefixlen = &n->to_prefixlen; + } else { + buffer = &n->from; + prefixlen = &n->from_prefixlen; + } + + if (n->family == AF_UNSPEC) + r = in_addr_prefix_from_string_auto(rvalue, &n->family, buffer, prefixlen); + else + r = in_addr_prefix_from_string(rvalue, n->family, buffer, prefixlen); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "RPDB rule prefix is invalid, ignoring assignment: %s", rvalue); + return 0; + } + + n = NULL; + + return 0; +} + +int config_parse_routing_policy_rule_device( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + if (!ifname_valid(rvalue)) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse '%s' interface name, ignoring: %s", lvalue, rvalue); + return 0; + } + + if (streq(lvalue, "IncomingInterface")) { + r = free_and_strdup(&n->iif, rvalue); + if (r < 0) + return log_oom(); + } else { + r = free_and_strdup(&n->oif, rvalue); + if (r < 0) + return log_oom(); + } + + n = NULL; + + return 0; +} + +int config_parse_routing_policy_rule_port_range( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + uint16_t low, high; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = parse_ip_port_range(rvalue, &low, &high); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse routing policy rule port range '%s'", rvalue); + return 0; + } + + if (streq(lvalue, "SourcePort")) { + n->sport.start = low; + n->sport.end = high; + } else { + n->dport.start = low; + n->dport.end = high; + } + + n = NULL; + + return 0; +} + +int config_parse_routing_policy_rule_ip_protocol( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = parse_ip_protocol(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IP protocol '%s' for routing policy rule, ignoring: %m", rvalue); + return 0; + } + + n->protocol = r; + + n = NULL; + + return 0; +} + +int config_parse_routing_policy_rule_invert( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule invert, ignoring: %s", rvalue); + return 0; + } + + n->invert_rule = r; + + n = NULL; + + return 0; +} + +int config_parse_routing_policy_rule_family( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(routing_policy_rule_free_or_set_invalidp) RoutingPolicyRule *n = NULL; + Network *network = userdata; + AddressFamily a; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = routing_policy_rule_new_static(network, filename, section_line, &n); + if (r < 0) + return r; + + a = routing_policy_rule_address_family_from_string(rvalue); + if (a < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, + "Invalid address family '%s', ignoring.", rvalue); + return 0; + } + + n->address_family = a; + n = NULL; + + return 0; +} + +static int routing_policy_rule_read_full_file(const char *state_file, char **ret) { + _cleanup_free_ char *s = NULL; + size_t size; + int r; + + assert(state_file); + + r = read_full_file(state_file, &s, &size); + if (r == -ENOENT) + return -ENODATA; + if (r < 0) + return r; + if (size <= 0) + return -ENODATA; + + *ret = TAKE_PTR(s); + + return size; +} + +int routing_policy_serialize_rules(Set *rules, FILE *f) { + RoutingPolicyRule *rule = NULL; + Iterator i; + int r; + + assert(f); + + SET_FOREACH(rule, rules, i) { + _cleanup_free_ char *from_str = NULL, *to_str = NULL; + bool space = false; + const char *family_str; + + fputs("RULE=", f); + + if (!in_addr_is_null(rule->family, &rule->from)) { + r = in_addr_to_string(rule->family, &rule->from, &from_str); + if (r < 0) + return r; + + fprintf(f, "from=%s/%hhu", + from_str, rule->from_prefixlen); + space = true; + } + + if (!in_addr_is_null(rule->family, &rule->to)) { + r = in_addr_to_string(rule->family, &rule->to, &to_str); + if (r < 0) + return r; + + fprintf(f, "%sto=%s/%hhu", + space ? " " : "", + to_str, rule->to_prefixlen); + space = true; + } + + family_str = af_to_name(rule->family); + if (family_str) + fprintf(f, "%sfamily=%s", + space ? " " : "", + family_str); + + if (rule->tos != 0) { + fprintf(f, "%stos=%hhu", + space ? " " : "", + rule->tos); + space = true; + } + + fprintf(f, "%spriority=%"PRIu32, + space ? " " : "", + rule->priority); + + if (rule->fwmark != 0) { + fprintf(f, "%sfwmark=%"PRIu32"/%"PRIu32, + space ? " " : "", + rule->fwmark, rule->fwmask); + space = true; + } + + if (rule->iif) { + fprintf(f, "%siif=%s", + space ? " " : "", + rule->iif); + space = true; + } + + if (rule->oif) { + fprintf(f, "%soif=%s", + space ? " " : "", + rule->oif); + space = true; + } + + if (rule->protocol != 0) { + fprintf(f, "%sprotocol=%hhu", + space ? " " : "", + rule->protocol); + space = true; + } + + if (rule->sport.start != 0 || rule->sport.end != 0) { + fprintf(f, "%ssourcesport=%"PRIu16"-%"PRIu16, + space ? " " : "", + rule->sport.start, rule->sport.end); + space = true; + } + + if (rule->dport.start != 0 || rule->dport.end != 0) { + fprintf(f, "%sdestinationport=%"PRIu16"-%"PRIu16, + space ? " " : "", + rule->dport.start, rule->dport.end); + space = true; + } + + fprintf(f, "%stable=%"PRIu32 "\n", + space ? " " : "", + rule->table); + } + + return 0; +} + +int routing_policy_load_rules(const char *state_file, Set **rules) { + _cleanup_strv_free_ char **l = NULL; + _cleanup_free_ char *data = NULL; + uint16_t low = 0, high = 0; + const char *p; + char **i; + int r; + + assert(state_file); + assert(rules); + + r = routing_policy_rule_read_full_file(state_file, &data); + if (r <= 0) + return r; + + l = strv_split_newlines(data); + if (!l) + return -ENOMEM; + + r = set_ensure_allocated(rules, &routing_policy_rule_hash_ops); + if (r < 0) + return r; + + STRV_FOREACH(i, l) { + _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL; + + p = startswith(*i, "RULE="); + if (!p) + continue; + + r = routing_policy_rule_new(&rule); + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *word = NULL, *a = NULL, *b = NULL; + + r = extract_first_word(&p, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + r = split_pair(word, "=", &a, &b); + if (r < 0) + continue; + + if (STR_IN_SET(a, "from", "to")) { + union in_addr_union *buffer; + uint8_t *prefixlen; + + if (streq(a, "to")) { + buffer = &rule->to; + prefixlen = &rule->to_prefixlen; + } else { + buffer = &rule->from; + prefixlen = &rule->from_prefixlen; + } + + r = in_addr_prefix_from_string_auto(b, &rule->family, buffer, prefixlen); + if (r < 0) { + log_error_errno(r, "RPDB rule prefix is invalid, ignoring assignment: %s", b); + continue; + } + + } else if (streq(a, "family")) { + r = af_from_name(b); + if (r < 0) { + log_error_errno(r, "Failed to parse RPDB rule family, ignoring: %s", b); + continue; + } + rule->family = r; + } else if (streq(a, "tos")) { + r = safe_atou8(b, &rule->tos); + if (r < 0) { + log_error_errno(r, "Failed to parse RPDB rule tos, ignoring: %s", b); + continue; + } + } else if (streq(a, "table")) { + r = safe_atou32(b, &rule->table); + if (r < 0) { + log_error_errno(r, "Failed to parse RPDB rule table, ignoring: %s", b); + continue; + } + } else if (streq(a, "priority")) { + r = safe_atou32(b, &rule->priority); + if (r < 0) { + log_error_errno(r, "Failed to parse RPDB rule priority, ignoring: %s", b); + continue; + } + } else if (streq(a, "fwmark")) { + + r = parse_fwmark_fwmask(b, &rule->fwmark, &rule->fwmask); + if (r < 0) { + log_error_errno(r, "Failed to parse RPDB rule firewall mark or mask, ignoring: %s", a); + continue; + } + } else if (streq(a, "iif")) { + + if (free_and_strdup(&rule->iif, b) < 0) + return log_oom(); + + } else if (streq(a, "oif")) { + + if (free_and_strdup(&rule->oif, b) < 0) + return log_oom(); + } else if (streq(a, "protocol")) { + r = safe_atou8(b, &rule->protocol); + if (r < 0) { + log_error_errno(r, "Failed to parse RPDB rule protocol, ignoring: %s", b); + continue; + } + } else if (streq(a, "sourceport")) { + + r = parse_ip_port_range(b, &low, &high); + if (r < 0) { + log_error_errno(r, "Invalid routing policy rule source port range, ignoring assignment:'%s'", b); + continue; + } + + rule->sport.start = low; + rule->sport.end = high; + + } else if (streq(a, "destinationport")) { + + r = parse_ip_port_range(b, &low, &high); + if (r < 0) { + log_error_errno(r, "Invalid routing policy rule destination port range, ignoring assignment:'%s'", b); + continue; + } + + rule->dport.start = low; + rule->dport.end = high; + } + } + + r = set_put(*rules, rule); + if (r < 0) { + log_warning_errno(r, "Failed to add RPDB rule to saved DB, ignoring: %s", p); + continue; + } + if (r > 0) + rule = NULL; + } + + return 0; +} + +static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule *rule) { + RoutingPolicyRule *link_rule; + Iterator i; + Link *link; + + assert(m); + assert(rule); + + HASHMAP_FOREACH(link, m->links, i) { + if (!link->network) + continue; + + LIST_FOREACH(rules, link_rule, link->network->rules) + if (routing_policy_rule_compare_func(link_rule, rule) == 0) + return true; + } + + return false; +} + +void routing_policy_rule_purge(Manager *m, Link *link) { + RoutingPolicyRule *rule, *existing; + Iterator i; + int r; + + assert(m); + assert(link); + + SET_FOREACH(rule, m->rules_saved, i) { + existing = set_get(m->rules_foreign, rule); + if (!existing) + continue; /* Saved rule does not exist anymore. */ + + if (manager_links_have_routing_policy_rule(m, existing)) + continue; /* Existing links have the saved rule. */ + + /* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it + * later when it is requested. */ + + r = routing_policy_rule_remove(existing, link, NULL); + if (r < 0) { + log_warning_errno(r, "Could not remove routing policy rules: %m"); + continue; + } + + link->routing_policy_rule_remove_messages++; + + assert_se(set_remove(m->rules_foreign, existing) == existing); + routing_policy_rule_free(existing); + } +} diff --git a/src/network/networkd-routing-policy-rule.h b/src/network/networkd-routing-policy-rule.h new file mode 100644 index 00000000..6b8e3102 --- /dev/null +++ b/src/network/networkd-routing-policy-rule.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "in-addr-util.h" +#include "conf-parser.h" + +typedef struct RoutingPolicyRule RoutingPolicyRule; + +#include "networkd-link.h" +#include "networkd-network.h" +#include "networkd-util.h" + +typedef struct Network Network; +typedef struct Link Link; +typedef struct NetworkConfigSection NetworkConfigSection; +typedef struct Manager Manager; + +struct RoutingPolicyRule { + Manager *manager; + Network *network; + Link *link; + NetworkConfigSection *section; + + bool invert_rule; + + uint8_t tos; + uint8_t protocol; + + uint32_t table; + uint32_t fwmark; + uint32_t fwmask; + uint32_t priority; + + AddressFamily address_family; /* Specified by Family= */ + int family; /* Automatically determined by From= or To= */ + unsigned char to_prefixlen; + unsigned char from_prefixlen; + + char *iif; + char *oif; + + union in_addr_union to; + union in_addr_union from; + + struct fib_rule_port_range sport; + struct fib_rule_port_range dport; + + LIST_FIELDS(RoutingPolicyRule, rules); +}; + +int routing_policy_rule_new(RoutingPolicyRule **ret); +void routing_policy_rule_free(RoutingPolicyRule *rule); + +DEFINE_NETWORK_SECTION_FUNCTIONS(RoutingPolicyRule, routing_policy_rule_free); +int routing_policy_rule_section_verify(RoutingPolicyRule *rule); + +int routing_policy_rule_configure(RoutingPolicyRule *address, Link *link, link_netlink_message_handler_t callback); +int routing_policy_rule_remove(RoutingPolicyRule *routing_policy_rule, Link *link, link_netlink_message_handler_t callback); + +int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret); +int routing_policy_rule_get(Manager *m, RoutingPolicyRule *rule, RoutingPolicyRule **ret); +int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule); +int routing_policy_serialize_rules(Set *rules, FILE *f); +int routing_policy_load_rules(const char *state_file, Set **rules); +void routing_policy_rule_purge(Manager *m, Link *link); + +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_tos); +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_table); +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_fwmark_mask); +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_prefix); +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_priority); +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_device); +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_port_range); +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_ip_protocol); +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_invert); +CONFIG_PARSER_PROTOTYPE(config_parse_routing_policy_rule_family); diff --git a/src/network/networkd-speed-meter.c b/src/network/networkd-speed-meter.c new file mode 100644 index 00000000..c4fc56b0 --- /dev/null +++ b/src/network/networkd-speed-meter.c @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-event.h" +#include "sd-netlink.h" + +#include "networkd-link-bus.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "networkd-speed-meter.h" + +static int process_message(Manager *manager, sd_netlink_message *message) { + uint16_t type; + int ifindex, r; + Link *link; + + r = sd_netlink_message_get_type(message, &type); + if (r < 0) + return r; + + if (type != RTM_NEWLINK) + return 0; + + r = sd_rtnl_message_link_get_ifindex(message, &ifindex); + if (r < 0) + return r; + + link = hashmap_get(manager->links, INT_TO_PTR(ifindex)); + if (!link) + return -ENODEV; + + link->stats_old = link->stats_new; + + r = sd_netlink_message_read(message, IFLA_STATS64, sizeof link->stats_new, &link->stats_new); + if (r < 0) + return r; + + link->stats_updated = true; + + return 0; +} + +static int speed_meter_handler(sd_event_source *s, uint64_t usec, void *userdata) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + Manager *manager = userdata; + sd_netlink_message *i; + usec_t usec_now; + Iterator j; + Link *link; + int r; + + assert(s); + assert(userdata); + + r = sd_event_now(sd_event_source_get_event(s), CLOCK_MONOTONIC, &usec_now); + if (r < 0) + return r; + + r = sd_event_source_set_time(s, usec_now + manager->speed_meter_interval_usec); + if (r < 0) + return r; + + manager->speed_meter_usec_old = manager->speed_meter_usec_new; + manager->speed_meter_usec_new = usec_now; + + HASHMAP_FOREACH(link, manager->links, j) + link->stats_updated = false; + + r = sd_rtnl_message_new_link(manager->rtnl, &req, RTM_GETLINK, 0); + if (r < 0) { + log_warning_errno(r, "Failed to allocate RTM_GETLINK netlink message, ignoring: %m"); + return 0; + } + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) { + log_warning_errno(r, "Failed to set dump flag, ignoring: %m"); + return 0; + } + + r = sd_netlink_call(manager->rtnl, req, 0, &reply); + if (r < 0) { + log_warning_errno(r, "Failed to call RTM_GETLINK, ignoring: %m"); + return 0; + } + + for (i = reply; i; i = sd_netlink_message_next(i)) + (void) process_message(manager, i); + + return 0; +} + +int manager_start_speed_meter(Manager *manager) { + _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL; + int r; + + assert(manager); + assert(manager->event); + + if (!manager->use_speed_meter) + return 0; + + r = sd_event_add_time(manager->event, &s, CLOCK_MONOTONIC, 0, 0, speed_meter_handler, manager); + if (r < 0) + return r; + + r = sd_event_source_set_enabled(s, SD_EVENT_ON); + if (r < 0) + return r; + + manager->speed_meter_event_source = TAKE_PTR(s); + return 0; +} diff --git a/src/network/networkd-speed-meter.h b/src/network/networkd-speed-meter.h new file mode 100644 index 00000000..f5727784 --- /dev/null +++ b/src/network/networkd-speed-meter.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/* Default interval is 10sec. The speed meter periodically make networkd + * to be woke up. So, too small interval value is not desired. + * We set the minimum value 100msec = 0.1sec. */ +#define SPEED_METER_DEFAULT_TIME_INTERVAL (10 * USEC_PER_SEC) +#define SPEED_METER_MINIMUM_TIME_INTERVAL (100 * USEC_PER_MSEC) + +typedef struct Manager Manager; + +int manager_start_speed_meter(Manager *m); diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c new file mode 100644 index 00000000..3fd26836 --- /dev/null +++ b/src/network/networkd-util.c @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "condition.h" +#include "conf-parser.h" +#include "networkd-util.h" +#include "parse-util.h" +#include "string-table.h" +#include "string-util.h" +#include "util.h" + +static const char * const address_family_table[_ADDRESS_FAMILY_MAX] = { + [ADDRESS_FAMILY_NO] = "no", + [ADDRESS_FAMILY_YES] = "yes", + [ADDRESS_FAMILY_IPV4] = "ipv4", + [ADDRESS_FAMILY_IPV6] = "ipv6", +}; + +static const char * const link_local_address_family_table[_ADDRESS_FAMILY_MAX] = { + [ADDRESS_FAMILY_NO] = "no", + [ADDRESS_FAMILY_YES] = "yes", + [ADDRESS_FAMILY_IPV4] = "ipv4", + [ADDRESS_FAMILY_IPV6] = "ipv6", + [ADDRESS_FAMILY_FALLBACK] = "fallback", + [ADDRESS_FAMILY_FALLBACK_IPV4] = "ipv4-fallback", +}; + +static const char * const routing_policy_rule_address_family_table[_ADDRESS_FAMILY_MAX] = { + [ADDRESS_FAMILY_YES] = "both", + [ADDRESS_FAMILY_IPV4] = "ipv4", + [ADDRESS_FAMILY_IPV6] = "ipv6", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES); +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(link_local_address_family, AddressFamily, ADDRESS_FAMILY_YES); +DEFINE_STRING_TABLE_LOOKUP(routing_policy_rule_address_family, AddressFamily); +DEFINE_CONFIG_PARSE_ENUM(config_parse_link_local_address_family, link_local_address_family, + AddressFamily, "Failed to parse option"); + +int config_parse_address_family_with_kernel( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + AddressFamily *fwd = data, s; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* This function is mostly obsolete now. It simply redirects + * "kernel" to "no". In older networkd versions we used to + * distinguish IPForward=off from IPForward=kernel, where the + * former would explicitly turn off forwarding while the + * latter would simply not touch the setting. But that logic + * is gone, hence silently accept the old setting, but turn it + * to "no". */ + + s = address_family_from_string(rvalue); + if (s < 0) { + if (streq(rvalue, "kernel")) + s = ADDRESS_FAMILY_NO; + else { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue); + return 0; + } + } + + *fwd = s; + + return 0; +} + +/* Router lifetime can be set with netlink interface since kernel >= 4.5 + * so for the supported kernel we don't need to expire routes in userspace */ +int kernel_route_expiration_supported(void) { + static int cached = -1; + int r; + + if (cached < 0) { + Condition c = { + .type = CONDITION_KERNEL_VERSION, + .parameter = (char *) ">= 4.5" + }; + r = condition_test(&c); + if (r < 0) + return r; + + cached = r; + } + return cached; +} + +static void network_config_hash_func(const NetworkConfigSection *c, struct siphash *state) { + siphash24_compress(c->filename, strlen(c->filename), state); + siphash24_compress(&c->line, sizeof(c->line), state); +} + +static int network_config_compare_func(const NetworkConfigSection *x, const NetworkConfigSection *y) { + int r; + + r = strcmp(x->filename, y->filename); + if (r != 0) + return r; + + return CMP(x->line, y->line); +} + +DEFINE_HASH_OPS(network_config_hash_ops, NetworkConfigSection, network_config_hash_func, network_config_compare_func); + +int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s) { + NetworkConfigSection *cs; + + cs = malloc0(offsetof(NetworkConfigSection, filename) + strlen(filename) + 1); + if (!cs) + return -ENOMEM; + + strcpy(cs->filename, filename); + cs->line = line; + + *s = TAKE_PTR(cs); + + return 0; +} + +void network_config_section_free(NetworkConfigSection *cs) { + free(cs); +} diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h new file mode 100644 index 00000000..3a57819f --- /dev/null +++ b/src/network/networkd-util.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "hash-funcs.h" +#include "macro.h" + +typedef enum AddressFamily { + /* This is a bitmask, though it usually doesn't feel that way! */ + ADDRESS_FAMILY_NO = 0, + ADDRESS_FAMILY_IPV4 = 1 << 0, + ADDRESS_FAMILY_IPV6 = 1 << 1, + ADDRESS_FAMILY_YES = ADDRESS_FAMILY_IPV4 | ADDRESS_FAMILY_IPV6, + ADDRESS_FAMILY_FALLBACK_IPV4 = 1 << 2, + ADDRESS_FAMILY_FALLBACK = ADDRESS_FAMILY_FALLBACK_IPV4 | ADDRESS_FAMILY_IPV6, + _ADDRESS_FAMILY_MAX, + _ADDRESS_FAMILY_INVALID = -1, +} AddressFamily; + +typedef struct NetworkConfigSection { + unsigned line; + bool invalid; + char filename[]; +} NetworkConfigSection; + +CONFIG_PARSER_PROTOTYPE(config_parse_link_local_address_family); +CONFIG_PARSER_PROTOTYPE(config_parse_address_family_with_kernel); + +const char *address_family_to_string(AddressFamily b) _const_; +AddressFamily address_family_from_string(const char *s) _pure_; + +const char *link_local_address_family_to_string(AddressFamily b) _const_; +AddressFamily link_local_address_family_from_string(const char *s) _pure_; + +const char *routing_policy_rule_address_family_to_string(AddressFamily b) _const_; +AddressFamily routing_policy_rule_address_family_from_string(const char *s) _pure_; + +int kernel_route_expiration_supported(void); + +int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s); +void network_config_section_free(NetworkConfigSection *network); +DEFINE_TRIVIAL_CLEANUP_FUNC(NetworkConfigSection*, network_config_section_free); +extern const struct hash_ops network_config_hash_ops; + +static inline bool section_is_invalid(NetworkConfigSection *section) { + /* If this returns false, then it does _not_ mean the section is valid. */ + + if (!section) + return false; + + return section->invalid; +} + +#define DEFINE_NETWORK_SECTION_FUNCTIONS(type, free_func) \ + static inline void free_func##_or_set_invalid(type *p) { \ + assert(p); \ + \ + if (p->section) \ + p->section->invalid = true; \ + else \ + free_func(p); \ + } \ + DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func); \ + DEFINE_TRIVIAL_CLEANUP_FUNC(type*, free_func##_or_set_invalid); diff --git a/src/network/networkd-wifi.c b/src/network/networkd-wifi.c new file mode 100644 index 00000000..14a86874 --- /dev/null +++ b/src/network/networkd-wifi.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "bus-util.h" +#include "netlink-internal.h" +#include "netlink-util.h" +#include "networkd-link.h" +#include "networkd-manager.h" +#include "networkd-wifi.h" +#include "string-util.h" +#include "wifi-util.h" + +int wifi_get_info(Link *link) { + const char *type; + int r, s = 0; + + assert(link); + + if (!link->sd_device) + return 0; + + r = sd_device_get_devtype(link->sd_device, &type); + if (r == -ENOENT) + return 0; + else if (r < 0) + return r; + + if (!streq(type, "wlan")) + return 0; + + _cleanup_free_ char *ssid = NULL; + r = wifi_get_interface(link->manager->genl, link->ifindex, &link->wlan_iftype, &ssid); + if (r < 0) + return r; + if (r > 0 && streq_ptr(link->ssid, ssid)) + r = 0; + free_and_replace(link->ssid, ssid); + + if (link->wlan_iftype == NL80211_IFTYPE_STATION) { + struct ether_addr old_bssid = link->bssid; + s = wifi_get_station(link->manager->genl, link->ifindex, &link->bssid); + if (s < 0) + return s; + if (s > 0 && memcmp(&old_bssid, &link->bssid, sizeof old_bssid) == 0) + s = 0; + } + + if (r > 0 || s > 0) { + char buf[ETHER_ADDR_TO_STRING_MAX]; + + if (link->wlan_iftype == NL80211_IFTYPE_STATION && link->ssid) + log_link_info(link, "Connected WiFi access point: %s (%s)", + link->ssid, ether_addr_to_string(&link->bssid, buf)); + return 1; + } + return 0; +} diff --git a/src/network/networkd-wifi.h b/src/network/networkd-wifi.h new file mode 100644 index 00000000..57aa1533 --- /dev/null +++ b/src/network/networkd-wifi.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +typedef struct Link Link; + +int wifi_get_info(Link *link); diff --git a/src/network/networkd.c b/src/network/networkd.c new file mode 100644 index 00000000..c7ce64b9 --- /dev/null +++ b/src/network/networkd.c @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-event.h" + +#include "capability-util.h" +#include "daemon-util.h" +#include "main-func.h" +#include "mkdir.h" +#include "networkd-conf.h" +#include "networkd-manager.h" +#include "signal-util.h" +#include "user-util.h" + +static int run(int argc, char *argv[]) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + const char *user = "systemd-network"; + uid_t uid; + gid_t gid; + int r; + + log_setup_service(); + + umask(0022); + + if (argc != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); + + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); + if (r < 0) + return log_error_errno(r, "Cannot resolve user name %s: %m", user); + + /* Create runtime directory. This is not necessary when networkd is + * started with "RuntimeDirectory=systemd/netif", or after + * systemd-tmpfiles-setup.service. */ + r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid, MKDIR_WARN_MODE); + if (r < 0) + log_warning_errno(r, "Could not create runtime directory: %m"); + + /* Drop privileges, but only if we have been started as root. If we are not running as root we assume all + * privileges are already dropped. */ + if (geteuid() == 0) { + r = drop_privileges(uid, gid, + (1ULL << CAP_NET_ADMIN) | + (1ULL << CAP_NET_BIND_SERVICE) | + (1ULL << CAP_NET_BROADCAST) | + (1ULL << CAP_NET_RAW)); + if (r < 0) + return log_error_errno(r, "Failed to drop privileges: %m"); + } + + /* Always create the directories people can create inotify watches in. + * It is necessary to create the following subdirectories after drop_privileges() + * to support old kernels not supporting AmbientCapabilities=. */ + r = mkdir_safe_label("/run/systemd/netif/links", 0755, uid, gid, MKDIR_WARN_MODE); + if (r < 0) + log_warning_errno(r, "Could not create runtime directory 'links': %m"); + + r = mkdir_safe_label("/run/systemd/netif/leases", 0755, uid, gid, MKDIR_WARN_MODE); + if (r < 0) + log_warning_errno(r, "Could not create runtime directory 'leases': %m"); + + r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, uid, gid, MKDIR_WARN_MODE); + if (r < 0) + log_warning_errno(r, "Could not create runtime directory 'lldp': %m"); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + + r = manager_new(&m); + if (r < 0) + return log_error_errno(r, "Could not create manager: %m"); + + r = manager_connect_bus(m); + if (r < 0) + return log_error_errno(r, "Could not connect to bus: %m"); + + r = manager_parse_config_file(m); + if (r < 0) + log_warning_errno(r, "Failed to parse configuration file: %m"); + + r = manager_load_config(m); + if (r < 0) + return log_error_errno(r, "Could not load configuration files: %m"); + + r = manager_rtnl_enumerate_links(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate links: %m"); + + r = manager_rtnl_enumerate_addresses(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate addresses: %m"); + + r = manager_rtnl_enumerate_neighbors(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate neighbors: %m"); + + r = manager_rtnl_enumerate_routes(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate routes: %m"); + + r = manager_rtnl_enumerate_rules(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate rules: %m"); + + r = manager_rtnl_enumerate_nexthop(m); + if (r < 0) + return log_error_errno(r, "Could not enumerate nexthop: %m"); + + r = manager_start(m); + if (r < 0) + return log_error_errno(r, "Could not start manager: %m"); + + log_info("Enumeration completed"); + + notify_message = notify_start(NOTIFY_READY, NOTIFY_STOPPING); + + r = sd_event_loop(m->event); + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/network/networkd.conf b/src/network/networkd.conf new file mode 100644 index 00000000..c5667da9 --- /dev/null +++ b/src/network/networkd.conf @@ -0,0 +1,20 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See networkd.conf(5) for details + +[Network] +#SpeedMeter=no +#SpeedMeterIntervalSec=10sec + +[DHCP] +#DUIDType=vendor +#DUIDRawData= diff --git a/src/network/org.freedesktop.network1.conf b/src/network/org.freedesktop.network1.conf new file mode 100644 index 00000000..366c6307 --- /dev/null +++ b/src/network/org.freedesktop.network1.conf @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/network/org.freedesktop.network1.policy b/src/network/org.freedesktop.network1.policy new file mode 100644 index 00000000..9b1895e6 --- /dev/null +++ b/src/network/org.freedesktop.network1.policy @@ -0,0 +1,175 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Set NTP servers + Authentication is required to set NTP servers. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Set DNS servers + Authentication is required to set DNS servers. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Set domains + Authentication is required to set domains. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Set default route + Authentication is required to set default route. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Enable/disable LLMNR + Authentication is required to enable or disable LLMNR. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Enable/disable multicast DNS + Authentication is required to enable or disable multicast DNS. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Enable/disable DNS over TLS + Authentication is required to enable or disable DNS over TLS. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Enable/disable DNSSEC + Authentication is required to enable or disable DNSSEC. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Set DNSSEC Negative Trust Anchors + Authentication is required to set DNSSEC Negative Trust Anchors. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Revert NTP settings + Authentication is required to reset NTP settings. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Revert DNS settings + Authentication is required to reset DNS settings. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Renew dynamic addresses + Authentication is required to renew dynamic addresses. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Reload network settings + Authentication is required to reload network settings. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + + Reconfigure network interface + Authentication is required to reconfigure network interface. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-network + + + diff --git a/src/network/org.freedesktop.network1.service b/src/network/org.freedesktop.network1.service new file mode 100644 index 00000000..641a1a5c --- /dev/null +++ b/src/network/org.freedesktop.network1.service @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.network1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.network1.service diff --git a/src/network/systemd-networkd.pkla b/src/network/systemd-networkd.pkla new file mode 100644 index 00000000..4d1bb458 --- /dev/null +++ b/src/network/systemd-networkd.pkla @@ -0,0 +1,4 @@ +[Allow systemd-networkd to set timezone and transient hostname] +Identity=unix-user:systemd-network +Action=org.freedesktop.hostname1.set-hostname;org.freedesktop.hostname1.get-product-uuid;org.freedesktop.timedate1.set-timezone; +ResultAny=yes diff --git a/src/network/systemd-networkd.rules b/src/network/systemd-networkd.rules new file mode 100644 index 00000000..b9077c1e --- /dev/null +++ b/src/network/systemd-networkd.rules @@ -0,0 +1,10 @@ +// Allow systemd-networkd to set timezone, get product UUID, +// and transient hostname +polkit.addRule(function(action, subject) { + if ((action.id == "org.freedesktop.hostname1.set-hostname" || + action.id == "org.freedesktop.hostname1.get-product-uuid" || + action.id == "org.freedesktop.timedate1.set-timezone") && + subject.user == "systemd-network") { + return polkit.Result.YES; + } +}); diff --git a/src/network/tc/netem.c b/src/network/tc/netem.c new file mode 100644 index 00000000..053af3e7 --- /dev/null +++ b/src/network/tc/netem.c @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * Copyright © 2019 VMware, Inc. */ + +#include +#include + +#include "alloc-util.h" +#include "conf-parser.h" +#include "hashmap.h" +#include "in-addr-util.h" +#include "netem.h" +#include "netlink-util.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "qdisc.h" +#include "string-util.h" +#include "tc-util.h" +#include "util.h" + +int network_emulator_new(NetworkEmulator **ret) { + NetworkEmulator *ne = NULL; + + ne = new(NetworkEmulator, 1); + if (!ne) + return -ENOMEM; + + *ne = (NetworkEmulator) { + .delay = USEC_INFINITY, + .jitter = USEC_INFINITY, + }; + + *ret = TAKE_PTR(ne); + + return 0; +} + +int network_emulator_fill_message(Link *link, QDiscs *qdisc, sd_netlink_message *req) { + struct tc_netem_qopt opt = { + .limit = 1000, + }; + int r; + + assert(link); + assert(qdisc); + assert(req); + + if (qdisc->ne.limit > 0) + opt.limit = qdisc->ne.limit; + + if (qdisc->ne.loss > 0) + opt.loss = qdisc->ne.loss; + + if (qdisc->ne.duplicate > 0) + opt.duplicate = qdisc->ne.duplicate; + + if (qdisc->ne.delay != USEC_INFINITY) { + r = tc_time_to_tick(qdisc->ne.delay, &opt.latency); + if (r < 0) + return log_link_error_errno(link, r, "Failed to calculate latency in TCA_OPTION: %m"); + } + + if (qdisc->ne.jitter != USEC_INFINITY) { + r = tc_time_to_tick(qdisc->ne.jitter, &opt.jitter); + if (r < 0) + return log_link_error_errno(link, r, "Failed to calculate jitter in TCA_OPTION: %m"); + } + + r = sd_netlink_message_append_data(req, TCA_OPTIONS, &opt, sizeof(struct tc_netem_qopt)); + if (r < 0) + return log_link_error_errno(link, r, "Could not append TCA_OPTION attribute: %m"); + + return 0; +} + +int config_parse_tc_network_emulator_delay( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(qdisc_free_or_set_invalidp) QDiscs *qdisc = NULL; + Network *network = data; + usec_t u; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = qdisc_new_static(network, filename, section_line, &qdisc); + if (r < 0) + return r; + + if (isempty(rvalue)) { + if (streq(lvalue, "NetworkEmulatorDelaySec")) + qdisc->ne.delay = USEC_INFINITY; + else if (streq(lvalue, "NetworkEmulatorDelayJitterSec")) + qdisc->ne.jitter = USEC_INFINITY; + + qdisc = NULL; + return 0; + } + + r = parse_sec(rvalue, &u); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse '%s=', ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + if (streq(lvalue, "NetworkEmulatorDelaySec")) + qdisc->ne.delay = u; + else if (streq(lvalue, "NetworkEmulatorDelayJitterSec")) + qdisc->ne.jitter = u; + + qdisc->has_network_emulator = true; + qdisc = NULL; + + return 0; +} + +int config_parse_tc_network_emulator_rate( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(qdisc_free_or_set_invalidp) QDiscs *qdisc = NULL; + Network *network = data; + uint32_t rate; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = qdisc_new_static(network, filename, section_line, &qdisc); + if (r < 0) + return r; + + if (isempty(rvalue)) { + qdisc->ne.loss = 0; + + qdisc = NULL; + return 0; + } + + r = parse_tc_percent(rvalue, &rate); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse '%s=', ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + if (streq(lvalue, "NetworkEmulatorLossRate")) + qdisc->ne.loss = rate; + else if (streq(lvalue, "NetworkEmulatorDuplicateRate")) + qdisc->ne.duplicate = rate; + + qdisc = NULL; + return 0; +} + +int config_parse_tc_network_emulator_packet_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(qdisc_free_or_set_invalidp) QDiscs *qdisc = NULL; + Network *network = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = qdisc_new_static(network, filename, section_line, &qdisc); + if (r < 0) + return r; + + if (isempty(rvalue)) { + qdisc->ne.limit = 0; + qdisc = NULL; + + return 0; + } + + r = safe_atou(rvalue, &qdisc->ne.limit); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse 'NetworkEmulatorPacketLimit=', ignoring assignment: %s", + rvalue); + return 0; + } + + qdisc = NULL; + return 0; +} diff --git a/src/network/tc/netem.h b/src/network/tc/netem.h new file mode 100644 index 00000000..43abf20a --- /dev/null +++ b/src/network/tc/netem.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * Copyright © 2019 VMware, Inc. */ +#pragma once + +#include "sd-netlink.h" + +#include "conf-parser.h" +#include "networkd-link.h" +#include "time-util.h" + +typedef struct QDiscs QDiscs; + +typedef struct NetworkEmulator { + usec_t delay; + usec_t jitter; + + uint32_t limit; + uint32_t loss; + uint32_t duplicate; +} NetworkEmulator; + +int network_emulator_new(NetworkEmulator **ret); +int network_emulator_fill_message(Link *link, QDiscs *qdisc, sd_netlink_message *req); + +CONFIG_PARSER_PROTOTYPE(config_parse_tc_network_emulator_delay); +CONFIG_PARSER_PROTOTYPE(config_parse_tc_network_emulator_rate); +CONFIG_PARSER_PROTOTYPE(config_parse_tc_network_emulator_packet_limit); diff --git a/src/network/tc/qdisc.c b/src/network/tc/qdisc.c new file mode 100644 index 00000000..e99329bd --- /dev/null +++ b/src/network/tc/qdisc.c @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * Copyright © 2019 VMware, Inc. */ + +#include + +#include "alloc-util.h" +#include "conf-parser.h" +#include "in-addr-util.h" +#include "netlink-util.h" +#include "networkd-manager.h" +#include "parse-util.h" +#include "qdisc.h" +#include "set.h" +#include "string-util.h" +#include "util.h" + +static int qdisc_new(QDiscs **ret) { + QDiscs *qdisc; + + qdisc = new(QDiscs, 1); + if (!qdisc) + return -ENOMEM; + + *qdisc = (QDiscs) { + .family = AF_UNSPEC, + .parent = TC_H_ROOT, + }; + + *ret = TAKE_PTR(qdisc); + + return 0; +} + +int qdisc_new_static(Network *network, const char *filename, unsigned section_line, QDiscs **ret) { + _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; + _cleanup_(qdisc_freep) QDiscs *qdisc = NULL; + int r; + + assert(network); + assert(ret); + assert(!!filename == (section_line > 0)); + + if (filename) { + r = network_config_section_new(filename, section_line, &n); + if (r < 0) + return r; + + qdisc = ordered_hashmap_get(network->qdiscs_by_section, n); + if (qdisc) { + *ret = TAKE_PTR(qdisc); + + return 0; + } + } + + r = qdisc_new(&qdisc); + if (r < 0) + return r; + + qdisc->network = network; + + if (filename) { + qdisc->section = TAKE_PTR(n); + + r = ordered_hashmap_ensure_allocated(&network->qdiscs_by_section, &network_config_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(network->qdiscs_by_section, qdisc->section, qdisc); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(qdisc); + + return 0; +} + +void qdisc_free(QDiscs *qdisc) { + if (!qdisc) + return; + + if (qdisc->network && qdisc->section) + ordered_hashmap_remove(qdisc->network->qdiscs_by_section, qdisc->section); + + network_config_section_free(qdisc->section); + + free(qdisc); +} + +static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { + int r; + + assert(link); + assert(link->qdisc_messages > 0); + link->qdisc_messages--; + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_netlink_message_get_errno(m); + if (r < 0 && r != -EEXIST) { + log_link_error_errno(link, r, "Could not set QDisc: %m"); + link_enter_failed(link); + return 1; + } + + if (link->qdisc_messages == 0) { + log_link_debug(link, "QDiscs configured"); + link->qdiscs_configured = true; + link_check_ready(link); + } + + return 1; +} + +int qdisc_configure(Link *link, QDiscs *qdisc) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + _cleanup_free_ char *tca_kind = NULL; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + assert(link->ifindex > 0); + + r = sd_rtnl_message_new_qdisc(link->manager->rtnl, &req, RTM_NEWQDISC, qdisc->family, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not create RTM_NEWQDISC message: %m"); + + r = sd_rtnl_message_set_qdisc_parent(req, qdisc->parent); + if (r < 0) + return log_link_error_errno(link, r, "Could not create tcm_parent message: %m"); + + if (qdisc->parent == TC_H_CLSACT) { + tca_kind = strdup("clsact"); + if (!tca_kind) + return log_oom(); + + r = sd_rtnl_message_set_qdisc_handle(req, TC_H_MAKE(TC_H_CLSACT, 0)); + if (r < 0) + return log_link_error_errno(link, r, "Could not set tcm_handle message: %m"); + } + + if (qdisc->has_network_emulator) { + r = free_and_strdup(&tca_kind, "netem"); + if (r < 0) + return log_oom(); + + r = network_emulator_fill_message(link, qdisc, req); + if (r < 0) + return r; + } + + if (tca_kind) { + r = sd_netlink_message_append_string(req, TCA_KIND, tca_kind); + if (r < 0) + return log_link_error_errno(link, r, "Could not append TCA_KIND attribute: %m"); + } + + r = netlink_call_async(link->manager->rtnl, NULL, req, qdisc_handler, link_netlink_destroy_callback, link); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + link->qdisc_messages++; + + return 0; +} + +int config_parse_tc_qdiscs_parent( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_(qdisc_free_or_set_invalidp) QDiscs *qdisc = NULL; + Network *network = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = qdisc_new_static(network, filename, section_line, &qdisc); + if (r < 0) + return r; + + if (streq(rvalue, "root")) + qdisc->parent = TC_H_ROOT; + else if (streq(rvalue, "clsact")) + qdisc->parent = TC_H_CLSACT; + else { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse [QueueDiscs] 'Parent=', ignoring assignment: %s", + rvalue); + return 0; + } + + qdisc = NULL; + + return 0; +} diff --git a/src/network/tc/qdisc.h b/src/network/tc/qdisc.h new file mode 100644 index 00000000..315d93d1 --- /dev/null +++ b/src/network/tc/qdisc.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * Copyright © 2019 VMware, Inc. */ +#pragma once + +#include "conf-parser.h" +#include "netem.h" +#include "networkd-link.h" +#include "networkd-network.h" +#include "networkd-util.h" + +typedef struct QDiscs { + NetworkConfigSection *section; + Network *network; + + int family; + + uint32_t handle; + uint32_t parent; + + bool has_network_emulator:1; + + NetworkEmulator ne; +} QDiscs; + +void qdisc_free(QDiscs *qdisc); +int qdisc_new_static(Network *network, const char *filename, unsigned section_line, QDiscs **ret); + +int qdisc_configure(Link *link, QDiscs *qdisc); + +DEFINE_NETWORK_SECTION_FUNCTIONS(QDiscs, qdisc_free); + +CONFIG_PARSER_PROTOTYPE(config_parse_tc_qdiscs_parent); diff --git a/src/network/tc/tc-util.c b/src/network/tc/tc-util.c new file mode 100644 index 00000000..7e1cf53e --- /dev/null +++ b/src/network/tc/tc-util.c @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * Copyright © 2019 VMware, Inc. */ + +#include "alloc-util.h" +#include "fileio.h" +#include "parse-util.h" +#include "tc-util.h" +#include "time-util.h" + +static int tc_init(double *ticks_in_usec) { + uint32_t clock_resolution, ticks_to_usec, usec_to_ticks; + _cleanup_free_ char *line = NULL; + double clock_factor; + int r; + + r = read_one_line_file("/proc/net/psched", &line); + if (r < 0) + return r; + + r = sscanf(line, "%08x%08x%08x", &ticks_to_usec, &usec_to_ticks, &clock_resolution); + if (r < 3) + return -EIO; + + clock_factor = (double) clock_resolution / USEC_PER_SEC; + *ticks_in_usec = (double) ticks_to_usec / usec_to_ticks * clock_factor; + + return 0; +} + +int tc_time_to_tick(usec_t t, uint32_t *ret) { + static double ticks_in_usec = -1; + usec_t a; + int r; + + assert(ret); + + if (ticks_in_usec < 0) { + r = tc_init(&ticks_in_usec); + if (r < 0) + return r; + } + + a = t * ticks_in_usec; + if (a > UINT32_MAX) + return -ERANGE; + + *ret = a; + return 0; +} + +int parse_tc_percent(const char *s, uint32_t *percent) { + int r; + + assert(s); + assert(percent); + + r = parse_permille(s); + if (r < 0) + return r; + + *percent = (double) r / 1000 * UINT32_MAX; + return 0; +} diff --git a/src/network/tc/tc-util.h b/src/network/tc/tc-util.h new file mode 100644 index 00000000..ce7ab405 --- /dev/null +++ b/src/network/tc/tc-util.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * Copyright © 2019 VMware, Inc. */ +#pragma once + +#include "time-util.h" + +int tc_time_to_tick(usec_t t, uint32_t *ret); +int parse_tc_percent(const char *s, uint32_t *percent); diff --git a/src/network/test-network-tables.c b/src/network/test-network-tables.c new file mode 100644 index 00000000..25b93963 --- /dev/null +++ b/src/network/test-network-tables.c @@ -0,0 +1,47 @@ +#include "bond.h" +#include "dhcp6-internal.h" +#include "dhcp6-protocol.h" +#include "ethtool-util.h" +#include "ipvlan.h" +#include "lldp-internal.h" +#include "macvlan.h" +#include "ndisc-internal.h" +#include "netlink-internal.h" +#include "networkd-link.h" +#include "networkd-network.h" +#include "networkd-util.h" +#include "test-tables.h" +#include "tunnel.h" + +int main(int argc, char **argv) { + test_table(bond_ad_select, NETDEV_BOND_AD_SELECT); + test_table(bond_arp_all_targets, NETDEV_BOND_ARP_ALL_TARGETS); + test_table(bond_arp_validate, NETDEV_BOND_ARP_VALIDATE); + test_table(bond_fail_over_mac, NETDEV_BOND_FAIL_OVER_MAC); + test_table(bond_lacp_rate, NETDEV_BOND_LACP_RATE); + test_table(bond_mode, NETDEV_BOND_MODE); + test_table(bond_primary_reselect, NETDEV_BOND_PRIMARY_RESELECT); + test_table(bond_xmit_hash_policy, NETDEV_BOND_XMIT_HASH_POLICY); + test_table(dhcp6_message_status, DHCP6_STATUS); + test_table_sparse(dhcp6_message_type, DHCP6_MESSAGE); /* enum starts from 1 */ + test_table(dhcp_use_domains, DHCP_USE_DOMAINS); + test_table(duplex, DUP); + test_table(ip6tnl_mode, NETDEV_IP6_TNL_MODE); + test_table(ipv6_privacy_extensions, IPV6_PRIVACY_EXTENSIONS); + test_table(ipvlan_flags, NETDEV_IPVLAN_FLAGS); + test_table(link_operstate, LINK_OPERSTATE); + /* test_table(link_state, LINK_STATE); — not a reversible mapping */ + test_table(lldp_mode, LLDP_MODE); + test_table(netdev_kind, NETDEV_KIND); + test_table(nl_union_link_info_data, NL_UNION_LINK_INFO_DATA); + test_table(radv_prefix_delegation, RADV_PREFIX_DELEGATION); + test_table(wol, WOL); + test_table(lldp_event, SD_LLDP_EVENT); + test_table(ndisc_event, SD_NDISC_EVENT); + + test_table_sparse(ipvlan_mode, NETDEV_IPVLAN_MODE); + test_table_sparse(macvlan_mode, NETDEV_MACVLAN_MODE); + test_table_sparse(address_family, ADDRESS_FAMILY); + + return EXIT_SUCCESS; +} diff --git a/src/network/test-network.c b/src/network/test-network.c new file mode 100644 index 00000000..873d996e --- /dev/null +++ b/src/network/test-network.c @@ -0,0 +1,249 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-device.h" + +#include "alloc-util.h" +#include "dhcp-lease-internal.h" +#include "hostname-util.h" +#include "network-internal.h" +#include "networkd-manager.h" +#include "string-util.h" +#include "tests.h" + +static void test_deserialize_in_addr(void) { + _cleanup_free_ struct in_addr *addresses = NULL; + _cleanup_free_ struct in6_addr *addresses6 = NULL; + union in_addr_union a, b, c, d, e, f; + int size; + const char *addresses_string = "192.168.0.1 0:0:0:0:0:FFFF:204.152.189.116 192.168.0.2 ::1 192.168.0.3 1:0:0:0:0:0:0:8"; + + assert_se(in_addr_from_string(AF_INET, "0:0:0:0:0:FFFF:204.152.189.116", &a) < 0); + assert_se(in_addr_from_string(AF_INET6, "192.168.0.1", &d) < 0); + + assert_se(in_addr_from_string(AF_INET, "192.168.0.1", &a) >= 0); + assert_se(in_addr_from_string(AF_INET, "192.168.0.2", &b) >= 0); + assert_se(in_addr_from_string(AF_INET, "192.168.0.3", &c) >= 0); + assert_se(in_addr_from_string(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116", &d) >= 0); + assert_se(in_addr_from_string(AF_INET6, "::1", &e) >= 0); + assert_se(in_addr_from_string(AF_INET6, "1:0:0:0:0:0:0:8", &f) >= 0); + + assert_se((size = deserialize_in_addrs(&addresses, addresses_string)) >= 0); + assert_se(size == 3); + assert_se(in_addr_equal(AF_INET, &a, (union in_addr_union *) &addresses[0])); + assert_se(in_addr_equal(AF_INET, &b, (union in_addr_union *) &addresses[1])); + assert_se(in_addr_equal(AF_INET, &c, (union in_addr_union *) &addresses[2])); + + assert_se((size = deserialize_in6_addrs(&addresses6, addresses_string)) >= 0); + assert_se(size == 3); + assert_se(in_addr_equal(AF_INET6, &d, (union in_addr_union *) &addresses6[0])); + assert_se(in_addr_equal(AF_INET6, &e, (union in_addr_union *) &addresses6[1])); + assert_se(in_addr_equal(AF_INET6, &f, (union in_addr_union *) &addresses6[2])); +} + +static void test_deserialize_dhcp_routes(void) { + size_t size, allocated; + + { + _cleanup_free_ struct sd_dhcp_route *routes = NULL; + assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, "") >= 0); + assert_se(size == 0); + } + + { + /* no errors */ + _cleanup_free_ struct sd_dhcp_route *routes = NULL; + const char *routes_string = "192.168.0.0/16,192.168.0.1 10.1.2.0/24,10.1.2.1 0.0.0.0/0,10.0.1.1"; + + assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0); + + assert_se(size == 3); + assert_se(routes[0].dst_addr.s_addr == inet_addr("192.168.0.0")); + assert_se(routes[0].gw_addr.s_addr == inet_addr("192.168.0.1")); + assert_se(routes[0].dst_prefixlen == 16); + + assert_se(routes[1].dst_addr.s_addr == inet_addr("10.1.2.0")); + assert_se(routes[1].gw_addr.s_addr == inet_addr("10.1.2.1")); + assert_se(routes[1].dst_prefixlen == 24); + + assert_se(routes[2].dst_addr.s_addr == inet_addr("0.0.0.0")); + assert_se(routes[2].gw_addr.s_addr == inet_addr("10.0.1.1")); + assert_se(routes[2].dst_prefixlen == 0); + } + + { + /* error in second word */ + _cleanup_free_ struct sd_dhcp_route *routes = NULL; + const char *routes_string = "192.168.0.0/16,192.168.0.1 10.1.2.0#24,10.1.2.1 0.0.0.0/0,10.0.1.1"; + + assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0); + + assert_se(size == 2); + assert_se(routes[0].dst_addr.s_addr == inet_addr("192.168.0.0")); + assert_se(routes[0].gw_addr.s_addr == inet_addr("192.168.0.1")); + assert_se(routes[0].dst_prefixlen == 16); + + assert_se(routes[1].dst_addr.s_addr == inet_addr("0.0.0.0")); + assert_se(routes[1].gw_addr.s_addr == inet_addr("10.0.1.1")); + assert_se(routes[1].dst_prefixlen == 0); + } + + { + /* error in every word */ + _cleanup_free_ struct sd_dhcp_route *routes = NULL; + const char *routes_string = "192.168.0.0/55,192.168.0.1 10.1.2.0#24,10.1.2.1 0.0.0.0/0,10.0.1.X"; + + assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0); + assert_se(size == 0); + } +} + +static int test_load_config(Manager *manager) { + int r; +/* TODO: should_reload, is false if the config dirs do not exist, so + * so we can't do this test here, move it to a test for paths_check_timestamps + * directly + * + * assert_se(network_should_reload(manager) == true); +*/ + + r = manager_load_config(manager); + if (r == -EPERM) + return r; + assert_se(r >= 0); + + assert_se(manager_should_reload(manager) == false); + + return 0; +} + +static void test_network_get(Manager *manager, sd_device *loopback) { + Network *network; + const struct ether_addr mac = ETHER_ADDR_NULL; + + /* let's assume that the test machine does not have a .network file + that applies to the loopback device... */ + assert_se(network_get(manager, loopback, "lo", &mac, 0, NULL, NULL, &network) == -ENOENT); + assert_se(!network); +} + +static void test_address_equality(void) { + _cleanup_(address_freep) Address *a1 = NULL, *a2 = NULL; + + assert_se(address_new(&a1) >= 0); + assert_se(address_new(&a2) >= 0); + + assert_se(address_equal(NULL, NULL)); + assert_se(!address_equal(a1, NULL)); + assert_se(!address_equal(NULL, a2)); + assert_se(address_equal(a1, a2)); + + a1->family = AF_INET; + assert_se(!address_equal(a1, a2)); + + a2->family = AF_INET; + assert_se(address_equal(a1, a2)); + + assert_se(in_addr_from_string(AF_INET, "192.168.3.9", &a1->in_addr) >= 0); + assert_se(!address_equal(a1, a2)); + assert_se(in_addr_from_string(AF_INET, "192.168.3.9", &a2->in_addr) >= 0); + assert_se(address_equal(a1, a2)); + assert_se(in_addr_from_string(AF_INET, "192.168.3.10", &a1->in_addr_peer) >= 0); + assert_se(address_equal(a1, a2)); + assert_se(in_addr_from_string(AF_INET, "192.168.3.11", &a2->in_addr_peer) >= 0); + assert_se(address_equal(a1, a2)); + a1->prefixlen = 10; + assert_se(!address_equal(a1, a2)); + a2->prefixlen = 10; + assert_se(address_equal(a1, a2)); + + a1->family = AF_INET6; + assert_se(!address_equal(a1, a2)); + + a2->family = AF_INET6; + assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr) >= 0); + assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr) >= 0); + assert_se(address_equal(a1, a2)); + + a2->prefixlen = 8; + assert_se(address_equal(a1, a2)); + + assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::1", &a2->in_addr) >= 0); + assert_se(!address_equal(a1, a2)); +} + +static void test_dhcp_hostname_shorten_overlong(void) { + int r; + + { + /* simple hostname, no actions, no errors */ + _cleanup_free_ char *shortened = NULL; + r = shorten_overlong("name1", &shortened); + assert_se(r == 0); + assert_se(streq("name1", shortened)); + } + + { + /* simple fqdn, no actions, no errors */ + _cleanup_free_ char *shortened = NULL; + r = shorten_overlong("name1.example.com", &shortened); + assert_se(r == 0); + assert_se(streq("name1.example.com", shortened)); + } + + { + /* overlong fqdn, cut to first dot, no errors */ + _cleanup_free_ char *shortened = NULL; + r = shorten_overlong("name1.test-dhcp-this-one-here-is-a-very-very-long-domain.example.com", &shortened); + assert_se(r == 1); + assert_se(streq("name1", shortened)); + } + + { + /* overlong hostname, cut to HOST_MAX_LEN, no errors */ + _cleanup_free_ char *shortened = NULL; + r = shorten_overlong("test-dhcp-this-one-here-is-a-very-very-long-hostname-without-domainname", &shortened); + assert_se(r == 1); + assert_se(streq("test-dhcp-this-one-here-is-a-very-very-long-hostname-without-dom", shortened)); + } + + { + /* overlong fqdn, cut to first dot, empty result error */ + _cleanup_free_ char *shortened = NULL; + r = shorten_overlong(".test-dhcp-this-one-here-is-a-very-very-long-hostname.example.com", &shortened); + assert_se(r == -EDOM); + assert_se(shortened == NULL); + } + +} + +int main(void) { + _cleanup_(manager_freep) Manager *manager = NULL; + _cleanup_(sd_device_unrefp) sd_device *loopback = NULL; + int ifindex, r; + + test_setup_logging(LOG_INFO); + + test_deserialize_in_addr(); + test_deserialize_dhcp_routes(); + test_address_equality(); + test_dhcp_hostname_shorten_overlong(); + + assert_se(manager_new(&manager) >= 0); + + r = test_load_config(manager); + if (r == -EPERM) + return log_tests_skipped("Cannot load configuration"); + assert_se(r == 0); + + assert_se(sd_device_new_from_syspath(&loopback, "/sys/class/net/lo") >= 0); + assert_se(loopback); + assert_se(sd_device_get_ifindex(loopback, &ifindex) >= 0); + assert_se(ifindex == 1); + + test_network_get(manager, loopback); + + assert_se(manager_rtnl_enumerate_links(manager) >= 0); +} diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c new file mode 100644 index 00000000..2007acb7 --- /dev/null +++ b/src/network/test-networkd-conf.c @@ -0,0 +1,258 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "ether-addr-util.h" +#include "hexdecoct.h" +#include "log.h" +#include "macro.h" +#include "set.h" +#include "string-util.h" + +#include "network-internal.h" +#include "networkd-conf.h" +#include "networkd-network.h" + +static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected, usec_t expected_time) { + DUID actual = {}; + int r; + + r = config_parse_duid_type("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL); + log_info_errno(r, "\"%s\" → %d (%m)", rvalue, actual.type); + assert_se(r == ret); + assert_se(expected == actual.type); + if (expected == DUID_TYPE_LLT) + assert_se(expected_time == actual.llt_time); +} + +static void test_config_parse_duid_type(void) { + test_config_parse_duid_type_one("", 0, 0, 0); + test_config_parse_duid_type_one("link-layer-time", 0, DUID_TYPE_LLT, 0); + test_config_parse_duid_type_one("link-layer-time:2000-01-01 00:00:00 UTC", 0, DUID_TYPE_LLT, (usec_t) 946684800000000); + test_config_parse_duid_type_one("vendor", 0, DUID_TYPE_EN, 0); + test_config_parse_duid_type_one("vendor:2000-01-01 00:00:00 UTC", 0, 0, 0); + test_config_parse_duid_type_one("link-layer", 0, DUID_TYPE_LL, 0); + test_config_parse_duid_type_one("link-layer:2000-01-01 00:00:00 UTC", 0, 0, 0); + test_config_parse_duid_type_one("uuid", 0, DUID_TYPE_UUID, 0); + test_config_parse_duid_type_one("uuid:2000-01-01 00:00:00 UTC", 0, 0, 0); + test_config_parse_duid_type_one("foo", 0, 0, 0); + test_config_parse_duid_type_one("foo:2000-01-01 00:00:00 UTC", 0, 0, 0); +} + +static void test_config_parse_duid_rawdata_one(const char *rvalue, int ret, const DUID* expected) { + DUID actual = {}; + int r; + _cleanup_free_ char *d = NULL; + + r = config_parse_duid_rawdata("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL); + d = hexmem(actual.raw_data, actual.raw_data_len); + log_info_errno(r, "\"%s\" → \"%s\" (%m)", + rvalue, strnull(d)); + assert_se(r == ret); + if (expected) { + assert_se(actual.raw_data_len == expected->raw_data_len); + assert_se(memcmp(actual.raw_data, expected->raw_data, expected->raw_data_len) == 0); + } +} + +static void test_config_parse_hwaddr_one(const char *rvalue, int ret, const struct ether_addr* expected) { + struct ether_addr *actual = NULL; + int r; + + r = config_parse_hwaddr("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL); + assert_se(ret == r); + if (expected) { + assert_se(actual); + assert_se(ether_addr_equal(expected, actual)); + } else + assert_se(actual == NULL); + + free(actual); +} + +static void test_config_parse_hwaddrs_one(const char *rvalue, const struct ether_addr* list, size_t n) { + _cleanup_set_free_free_ Set *s = NULL; + size_t m; + + assert_se(config_parse_hwaddrs("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &s, NULL) == 0); + assert_se(set_size(s) == n); + + for (m = 0; m < n; m++) { + _cleanup_free_ struct ether_addr *q = NULL; + + assert_se(q = set_remove(s, &list[m])); + } + + assert_se(set_size(s) == 0); +} + +#define BYTES_0_128 "0:1:2:3:4:5:6:7:8:9:a:b:c:d:e:f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f:20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:2f:30:31:32:33:34:35:36:37:38:39:3a:3b:3c:3d:3e:3f:40:41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:50:51:52:53:54:55:56:57:58:59:5a:5b:5c:5d:5e:5f:60:61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:70:71:72:73:74:75:76:77:78:79:7a:7b:7c:7d:7e:7f:80" + +#define BYTES_1_128 {0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80} + +static void test_config_parse_duid_rawdata(void) { + test_config_parse_duid_rawdata_one("", 0, &(DUID){}); + test_config_parse_duid_rawdata_one("00:11:22:33:44:55:66:77", 0, + &(DUID){0, 8, {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}}); + test_config_parse_duid_rawdata_one("00:11:22:", 0, + &(DUID){0, 3, {0x00,0x11,0x22}}); + test_config_parse_duid_rawdata_one("000:11:22", 0, &(DUID){}); /* error, output is all zeros */ + test_config_parse_duid_rawdata_one("00:111:22", 0, &(DUID){}); + test_config_parse_duid_rawdata_one("0:1:2:3:4:5:6:7", 0, + &(DUID){0, 8, {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}}); + test_config_parse_duid_rawdata_one("11::", 0, &(DUID){0, 1, {0x11}}); /* FIXME: should this be an error? */ + test_config_parse_duid_rawdata_one("abcdef", 0, &(DUID){}); + test_config_parse_duid_rawdata_one(BYTES_0_128, 0, &(DUID){}); + test_config_parse_duid_rawdata_one(BYTES_0_128 + 2, 0, &(DUID){0, 128, BYTES_1_128}); +} + +static void test_config_parse_hwaddr(void) { + const struct ether_addr t[] = { + { .ether_addr_octet = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } }, + { .ether_addr_octet = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } }, + }; + + test_config_parse_hwaddr_one("", 0, NULL); + test_config_parse_hwaddr_one("no:ta:ma:ca:dd:re", 0, NULL); + test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:fx", 0, NULL); + test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff", 0, &t[0]); + test_config_parse_hwaddr_one(" aa:bb:cc:dd:ee:ff", 0, &t[0]); + test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\n", 0, NULL); + test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\nxxx", 0, NULL); + test_config_parse_hwaddr_one("aa:bb:cc: dd:ee:ff", 0, NULL); + test_config_parse_hwaddr_one("aa:bb:cc:d d:ee:ff", 0, NULL); + test_config_parse_hwaddr_one("aa:bb:cc:dd:ee", 0, NULL); + test_config_parse_hwaddr_one("9:aa:bb:cc:dd:ee:ff", 0, NULL); + test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff:gg", 0, NULL); + test_config_parse_hwaddr_one("aa:Bb:CC:dd:ee:ff", 0, &t[0]); + test_config_parse_hwaddr_one("01:23:45:67:89:aB", 0, &t[1]); + test_config_parse_hwaddr_one("1:23:45:67:89:aB", 0, &t[1]); + test_config_parse_hwaddr_one("aa-bb-cc-dd-ee-ff", 0, &t[0]); + test_config_parse_hwaddr_one("AA-BB-CC-DD-EE-FF", 0, &t[0]); + test_config_parse_hwaddr_one("01-23-45-67-89-ab", 0, &t[1]); + test_config_parse_hwaddr_one("aabb.ccdd.eeff", 0, &t[0]); + test_config_parse_hwaddr_one("0123.4567.89ab", 0, &t[1]); + test_config_parse_hwaddr_one("123.4567.89ab.", 0, NULL); + test_config_parse_hwaddr_one("aabbcc.ddeeff", 0, NULL); + test_config_parse_hwaddr_one("aabbccddeeff", 0, NULL); + test_config_parse_hwaddr_one("aabbccddee:ff", 0, NULL); + test_config_parse_hwaddr_one("012345.6789ab", 0, NULL); + test_config_parse_hwaddr_one("123.4567.89ab", 0, &t[1]); + + test_config_parse_hwaddrs_one("", t, 0); + test_config_parse_hwaddrs_one("no:ta:ma:ca:dd:re", t, 0); + test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:fx", t, 0); + test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff", t, 1); + test_config_parse_hwaddrs_one(" aa:bb:cc:dd:ee:ff", t, 1); + test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff \t\n", t, 1); + test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff \t\nxxx", t, 1); + test_config_parse_hwaddrs_one("aa:bb:cc: dd:ee:ff", t, 0); + test_config_parse_hwaddrs_one("aa:bb:cc:d d:ee:ff", t, 0); + test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee", t, 0); + test_config_parse_hwaddrs_one("9:aa:bb:cc:dd:ee:ff", t, 0); + test_config_parse_hwaddrs_one("aa:bb:cc:dd:ee:ff:gg", t, 0); + test_config_parse_hwaddrs_one("aa:Bb:CC:dd:ee:ff", t, 1); + test_config_parse_hwaddrs_one("01:23:45:67:89:aB", &t[1], 1); + test_config_parse_hwaddrs_one("1:23:45:67:89:aB", &t[1], 1); + test_config_parse_hwaddrs_one("aa-bb-cc-dd-ee-ff", t, 1); + test_config_parse_hwaddrs_one("AA-BB-CC-DD-EE-FF", t, 1); + test_config_parse_hwaddrs_one("01-23-45-67-89-ab", &t[1], 1); + test_config_parse_hwaddrs_one("aabb.ccdd.eeff", t, 1); + test_config_parse_hwaddrs_one("0123.4567.89ab", &t[1], 1); + test_config_parse_hwaddrs_one("123.4567.89ab.", t, 0); + test_config_parse_hwaddrs_one("aabbcc.ddeeff", t, 0); + test_config_parse_hwaddrs_one("aabbccddeeff", t, 0); + test_config_parse_hwaddrs_one("aabbccddee:ff", t, 0); + test_config_parse_hwaddrs_one("012345.6789ab", t, 0); + test_config_parse_hwaddrs_one("123.4567.89ab", &t[1], 1); + + test_config_parse_hwaddrs_one("123.4567.89ab aa:bb:cc:dd:ee:ff 01-23-45-67-89-ab aa:Bb:CC:dd:ee:ff", t, 2); + test_config_parse_hwaddrs_one("123.4567.89ab aa:bb:cc:dd:ee:fx hogehoge 01-23-45-67-89-ab aaaa aa:Bb:CC:dd:ee:ff", t, 2); +} + +static void test_config_parse_address_one(const char *rvalue, int family, unsigned n_addresses, const union in_addr_union *u, unsigned char prefixlen) { + _cleanup_(network_unrefp) Network *network = NULL; + + assert_se(network = new0(Network, 1)); + network->n_ref = 1; + assert_se(network->filename = strdup("hogehoge.network")); + assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match_name, network) == 0); + assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0); + assert_se(network->n_static_addresses == 1); + assert_se(network_verify(network) >= 0); + assert_se(network->n_static_addresses == n_addresses); + if (n_addresses > 0) { + assert_se(network->static_addresses); + assert_se(network->static_addresses->prefixlen == prefixlen); + assert_se(network->static_addresses->family == family); + assert_se(in_addr_equal(family, &network->static_addresses->in_addr, u)); + /* TODO: check Address.in_addr and Address.broadcast */ + } +} + +static void test_config_parse_address(void) { + test_config_parse_address_one("", AF_INET, 0, NULL, 0); + test_config_parse_address_one("/", AF_INET, 0, NULL, 0); + test_config_parse_address_one("/8", AF_INET, 0, NULL, 0); + test_config_parse_address_one("1.2.3.4", AF_INET, 1, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 8); + test_config_parse_address_one("1.2.3.4/0", AF_INET, 1, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0); + test_config_parse_address_one("1.2.3.4/1", AF_INET, 1, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1); + test_config_parse_address_one("1.2.3.4/2", AF_INET, 1, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2); + test_config_parse_address_one("1.2.3.4/32", AF_INET, 1, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32); + test_config_parse_address_one("1.2.3.4/33", AF_INET, 0, NULL, 0); + test_config_parse_address_one("1.2.3.4/-1", AF_INET, 0, NULL, 0); + + test_config_parse_address_one("", AF_INET6, 0, NULL, 0); + test_config_parse_address_one("/", AF_INET6, 0, NULL, 0); + test_config_parse_address_one("/8", AF_INET6, 0, NULL, 0); + test_config_parse_address_one("::1", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0); + test_config_parse_address_one("::1/0", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0); + test_config_parse_address_one("::1/1", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1); + test_config_parse_address_one("::1/2", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2); + test_config_parse_address_one("::1/32", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32); + test_config_parse_address_one("::1/33", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33); + test_config_parse_address_one("::1/64", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64); + test_config_parse_address_one("::1/128", AF_INET6, 1, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128); + test_config_parse_address_one("::1/129", AF_INET6, 0, NULL, 0); + test_config_parse_address_one("::1/-1", AF_INET6, 0, NULL, 0); +} + +static void test_config_parse_match_ifnames(void) { + _cleanup_strv_free_ char **names = NULL; + + assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "!hoge hogehoge foo", &names, NULL) == 0); + assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "!baz", &names, NULL) == 0); + assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "aaa bbb ccc", &names, NULL) == 0); + + strv_equal(names, STRV_MAKE("!hoge", "!hogehoge", "!foo", "!baz", "aaa", "bbb", "ccc")); +} + +static void test_config_parse_match_strv(void) { + _cleanup_strv_free_ char **names = NULL; + + assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, "!hoge hogehoge foo", &names, NULL) == 0); + assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, "!baz", &names, NULL) == 0); + assert_se(config_parse_match_strv("network", "filename", 1, "section", 1, "Name", 0, + "KEY=val \"KEY2=val with space\" \"KEY3=val with \\\"quotation\\\"\"", &names, NULL) == 0); + + assert_se(strv_equal(names, + STRV_MAKE("!hoge", + "!hogehoge", + "!foo", + "!baz", + "KEY=val", + "KEY2=val with space", + "KEY3=val with \\quotation\\"))); +} + +int main(int argc, char **argv) { + log_parse_environment(); + log_open(); + + test_config_parse_duid_type(); + test_config_parse_duid_rawdata(); + test_config_parse_hwaddr(); + test_config_parse_address(); + test_config_parse_match_ifnames(); + test_config_parse_match_strv(); + + return 0; +} diff --git a/src/network/test-routing-policy-rule.c b/src/network/test-routing-policy-rule.c new file mode 100644 index 00000000..d441099b --- /dev/null +++ b/src/network/test-routing-policy-rule.c @@ -0,0 +1,92 @@ +/*** + SPDX-License-Identifier: LGPL-2.1+ +***/ + +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "macro.h" +#include "network-internal.h" +#include "networkd-manager.h" +#include "string-util.h" +#include "tests.h" +#include "tmpfile-util.h" + +static void test_rule_serialization(const char *title, const char *ruleset, const char *expected) { + char pattern[] = "/tmp/systemd-test-routing-policy-rule.XXXXXX", + pattern2[] = "/tmp/systemd-test-routing-policy-rule.XXXXXX", + pattern3[] = "/tmp/systemd-test-routing-policy-rule.XXXXXX"; + const char *cmd; + int fd, fd2, fd3; + _cleanup_fclose_ FILE *f = NULL, *f2 = NULL, *f3 = NULL; + Set *rules = NULL; + _cleanup_free_ char *buf = NULL; + size_t buf_size; + + log_info("========== %s ==========", title); + log_info("put:\n%s\n", ruleset); + + fd = mkostemp_safe(pattern); + assert_se(fd >= 0); + assert_se(f = fdopen(fd, "a+")); + assert_se(write_string_stream(f, ruleset, 0) == 0); + + assert_se(routing_policy_load_rules(pattern, &rules) == 0); + + fd2 = mkostemp_safe(pattern2); + assert_se(fd2 >= 0); + assert_se(f2 = fdopen(fd2, "a+")); + + assert_se(routing_policy_serialize_rules(rules, f2) == 0); + assert_se(fflush_and_check(f2) == 0); + + assert_se(read_full_file(pattern2, &buf, &buf_size) == 0); + + log_info("got:\n%s", buf); + + fd3 = mkostemp_safe(pattern3); + assert_se(fd3 >= 0); + assert_se(f3 = fdopen(fd3, "w")); + assert_se(write_string_stream(f3, expected ?: ruleset, 0) == 0); + + cmd = strjoina("diff -u ", pattern3, " ", pattern2); + log_info("$ %s", cmd); + assert_se(system(cmd) == 0); + + set_free_with_destructor(rules, routing_policy_rule_free); +} + +int main(int argc, char **argv) { + _cleanup_free_ char *p = NULL; + + test_setup_logging(LOG_DEBUG); + + test_rule_serialization("basic parsing", + "RULE=from=1.2.3.4/32 to=2.3.4.5/32 family=AF_INET tos=5 priority=0 fwmark=1/2 table=10", NULL); + + test_rule_serialization("ignored values", + "RULE=something=to=ignore from=1.2.3.4/32 from=1.2.3.4/32" + " \t to=2.3.4.5/24 to=2.3.4.5/32 tos=5 fwmark=2 fwmark=1 table=10 table=20", + "RULE=from=1.2.3.4/32" + " to=2.3.4.5/32 family=AF_INET tos=5 priority=0 fwmark=1/0 table=20"); + + test_rule_serialization("ipv6", + "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 table=6", NULL); + + assert_se(asprintf(&p, "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 table=%d", RT_TABLE_MAIN) >= 0); + test_rule_serialization("default table", + "RULE=from=1::2/64 to=2::3/64", p); + + test_rule_serialization("incoming interface", + "RULE=from=1::2/64 to=2::3/64 table=1 iif=lo", + "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 iif=lo table=1"); + + test_rule_serialization("outgoing interface", + "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 oif=eth0 table=1", NULL); + + test_rule_serialization("freeing interface names", + "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 iif=e0 iif=e1 oif=e0 oif=e1 table=1", + "RULE=from=1::2/64 to=2::3/64 family=AF_INET6 priority=0 iif=e1 oif=e1 table=1"); + + return 0; +} diff --git a/src/network/wait-online/link.c b/src/network/wait-online/link.c new file mode 100644 index 00000000..a13373f7 --- /dev/null +++ b/src/network/wait-online/link.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-network.h" + +#include "alloc-util.h" +#include "hashmap.h" +#include "link.h" +#include "manager.h" +#include "string-util.h" + +int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) { + _cleanup_(link_freep) Link *l = NULL; + _cleanup_free_ char *n = NULL; + int r; + + assert(m); + assert(ifindex > 0); + + r = hashmap_ensure_allocated(&m->links, NULL); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&m->links_by_name, &string_hash_ops); + if (r < 0) + return r; + + n = strdup(ifname); + if (!n) + return -ENOMEM; + + l = new(Link, 1); + if (!l) + return -ENOMEM; + + *l = (Link) { + .manager = m, + .ifname = TAKE_PTR(n), + .ifindex = ifindex, + .required_operstate = LINK_OPERSTATE_DEGRADED, + }; + + r = hashmap_put(m->links_by_name, l->ifname, l); + if (r < 0) + return r; + + r = hashmap_put(m->links, INT_TO_PTR(ifindex), l); + if (r < 0) + return r; + + if (ret) + *ret = l; + + TAKE_PTR(l); + return 0; +} + +Link *link_free(Link *l) { + + if (!l) + return NULL; + + if (l->manager) { + hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex)); + hashmap_remove(l->manager->links_by_name, l->ifname); + } + + free(l->state); + free(l->ifname); + return mfree(l); + } + +int link_update_rtnl(Link *l, sd_netlink_message *m) { + const char *ifname; + int r; + + assert(l); + assert(l->manager); + assert(m); + + r = sd_rtnl_message_link_get_flags(m, &l->flags); + if (r < 0) + return r; + + r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname); + if (r < 0) + return r; + + if (!streq(l->ifname, ifname)) { + char *new_ifname; + + new_ifname = strdup(ifname); + if (!new_ifname) + return -ENOMEM; + + assert_se(hashmap_remove(l->manager->links_by_name, l->ifname) == l); + free_and_replace(l->ifname, new_ifname); + + r = hashmap_put(l->manager->links_by_name, l->ifname, l); + if (r < 0) + return r; + } + + return 0; +} + +int link_update_monitor(Link *l) { + _cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *state = NULL; + LinkOperationalState s; + int r, ret = 0; + + assert(l); + assert(l->ifname); + + r = sd_network_link_get_required_for_online(l->ifindex); + if (r < 0) + ret = log_link_debug_errno(l, r, "Failed to determine whether the link is required for online or not, " + "ignoring: %m"); + else + l->required_for_online = r > 0; + + r = sd_network_link_get_required_operstate_for_online(l->ifindex, &required_operstate); + if (r < 0) + ret = log_link_debug_errno(l, r, "Failed to get required operational state, ignoring: %m"); + else { + s = link_operstate_from_string(required_operstate); + if (s < 0) + ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL), + "Failed to parse required operational state, ignoring: %m"); + else + l->required_operstate = s; + } + + r = sd_network_link_get_operational_state(l->ifindex, &operstate); + if (r < 0) + ret = log_link_debug_errno(l, r, "Failed to get operational state, ignoring: %m"); + else { + s = link_operstate_from_string(operstate); + if (s < 0) + ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL), + "Failed to parse operational state, ignoring: %m"); + else + l->operational_state = s; + } + + r = sd_network_link_get_setup_state(l->ifindex, &state); + if (r < 0) + ret = log_link_debug_errno(l, r, "Failed to get setup state, ignoring: %m"); + else + free_and_replace(l->state, state); + + return ret; +} diff --git a/src/network/wait-online/link.h b/src/network/wait-online/link.h new file mode 100644 index 00000000..d58129df --- /dev/null +++ b/src/network/wait-online/link.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-netlink.h" + +#include "log-link.h" +#include "network-util.h" + +typedef struct Link Link; +typedef struct Manager Manager; + +struct Link { + Manager *manager; + + int ifindex; + char *ifname; + unsigned flags; + + bool required_for_online; + LinkOperationalState required_operstate; + LinkOperationalState operational_state; + char *state; +}; + +int link_new(Manager *m, Link **ret, int ifindex, const char *ifname); +Link *link_free(Link *l); +int link_update_rtnl(Link *l, sd_netlink_message *m); +int link_update_monitor(Link *l); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); diff --git a/src/network/wait-online/manager.c b/src/network/wait-online/manager.c new file mode 100644 index 00000000..6de3df94 --- /dev/null +++ b/src/network/wait-online/manager.c @@ -0,0 +1,359 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "link.h" +#include "manager.h" +#include "netlink-util.h" +#include "network-internal.h" +#include "strv.h" +#include "time-util.h" +#include "util.h" + +static bool manager_ignore_link(Manager *m, Link *link) { + assert(m); + assert(link); + + /* always ignore the loopback interface */ + if (link->flags & IFF_LOOPBACK) + return true; + + /* if interfaces are given on the command line, ignore all others */ + if (m->interfaces && !hashmap_contains(m->interfaces, link->ifname)) + return true; + + if (!link->required_for_online) + return true; + + /* ignore interfaces we explicitly are asked to ignore */ + return strv_fnmatch(m->ignore, link->ifname, 0); +} + +static int manager_link_is_online(Manager *m, Link *l, LinkOperationalState s) { + /* This returns the following: + * -EAGAIN: not processed by udev or networkd + * 0: operstate is not enough + * 1: online */ + + if (!l->state) + return log_link_debug_errno(l, SYNTHETIC_ERRNO(EAGAIN), + "link has not yet been processed by udev"); + + if (STR_IN_SET(l->state, "configuring", "pending")) + return log_link_debug_errno(l, SYNTHETIC_ERRNO(EAGAIN), + "link is being processed by networkd"); + + if (s < 0) + s = m->required_operstate >= 0 ? m->required_operstate : l->required_operstate; + + if (l->operational_state < s) { + log_link_debug(l, "Operational state '%s' is below '%s'", + link_operstate_to_string(l->operational_state), + link_operstate_to_string(s)); + return 0; + } + + return 1; +} + +bool manager_configured(Manager *m) { + bool one_ready = false; + Iterator i; + const char *ifname; + void *p; + Link *l; + int r; + + if (!hashmap_isempty(m->interfaces)) { + /* wait for all the links given on the command line to appear */ + HASHMAP_FOREACH_KEY(p, ifname, m->interfaces, i) { + LinkOperationalState s = PTR_TO_INT(p); + + l = hashmap_get(m->links_by_name, ifname); + if (!l) { + log_debug("still waiting for %s", ifname); + if (!m->any) + return false; + continue; + } + + if (manager_link_is_online(m, l, s) <= 0) { + if (!m->any) + return false; + continue; + } + + one_ready = true; + } + + /* all interfaces given by the command line are online, or + * one of the specified interfaces is online. */ + return one_ready; + } + + /* wait for all links networkd manages to be in admin state 'configured' + * and at least one link to gain a carrier */ + HASHMAP_FOREACH(l, m->links, i) { + if (manager_ignore_link(m, l)) { + log_link_debug(l, "link is ignored"); + continue; + } + + r = manager_link_is_online(m, l, _LINK_OPERSTATE_INVALID); + if (r < 0 && !m->any) + return false; + if (r > 0) + /* we wait for at least one link to be ready, + * regardless of who manages it */ + one_ready = true; + } + + return one_ready; +} + +static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { + Manager *m = userdata; + uint16_t type; + Link *l; + const char *ifname; + int ifindex, r; + + assert(rtnl); + assert(m); + assert(mm); + + r = sd_netlink_message_get_type(mm, &type); + if (r < 0) { + log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m"); + return 0; + } + + r = sd_rtnl_message_link_get_ifindex(mm, &ifindex); + if (r < 0) { + log_warning_errno(r, "rtnl: Could not get ifindex from link, ignoring: %m"); + return 0; + } else if (ifindex <= 0) { + log_warning("rtnl: received link message with invalid ifindex %d, ignoring", ifindex); + return 0; + } + + r = sd_netlink_message_read_string(mm, IFLA_IFNAME, &ifname); + if (r < 0) { + log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m"); + return 0; + } + + l = hashmap_get(m->links, INT_TO_PTR(ifindex)); + + switch (type) { + + case RTM_NEWLINK: + if (!l) { + log_debug("Found link %i", ifindex); + + r = link_new(m, &l, ifindex, ifname); + if (r < 0) + return log_error_errno(r, "Failed to create link object: %m"); + } + + r = link_update_rtnl(l, mm); + if (r < 0) + log_link_warning_errno(l, r, "Failed to process RTNL link message, ignoring: %m"); + + r = link_update_monitor(l); + if (r < 0 && r != -ENODATA) + log_link_warning_errno(l, r, "Failed to update link state, ignoring: %m"); + + break; + + case RTM_DELLINK: + if (l) { + log_link_debug(l, "Removing link"); + link_free(l); + } + + break; + } + + return 0; +} + +static int on_rtnl_event(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { + Manager *m = userdata; + int r; + + r = manager_process_link(rtnl, mm, m); + if (r < 0) + return r; + + if (manager_configured(m)) + sd_event_exit(m->event, 0); + + return 1; +} + +static int manager_rtnl_listen(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *i; + int r; + + assert(m); + + /* First, subscribe to interfaces coming and going */ + r = sd_netlink_open(&m->rtnl); + if (r < 0) + return r; + + r = sd_netlink_attach_event(m->rtnl, m->event, 0); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, on_rtnl_event, NULL, m, "wait-online-on-NEWLINK"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELLINK, on_rtnl_event, NULL, m, "wait-online-on-DELLINK"); + if (r < 0) + return r; + + /* Then, enumerate all links */ + r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (i = reply; i; i = sd_netlink_message_next(i)) { + r = manager_process_link(m->rtnl, i, m); + if (r < 0) + return r; + } + + return r; +} + +static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + Iterator i; + Link *l; + int r; + + assert(m); + + sd_network_monitor_flush(m->network_monitor); + + HASHMAP_FOREACH(l, m->links, i) { + r = link_update_monitor(l); + if (r < 0 && r != -ENODATA) + log_link_warning_errno(l, r, "Failed to update link state, ignoring: %m"); + } + + if (manager_configured(m)) + sd_event_exit(m->event, 0); + + return 0; +} + +static int manager_network_monitor_listen(Manager *m) { + int r, fd, events; + + assert(m); + + r = sd_network_monitor_new(&m->network_monitor, NULL); + if (r < 0) + return r; + + fd = sd_network_monitor_get_fd(m->network_monitor); + if (fd < 0) + return fd; + + events = sd_network_monitor_get_events(m->network_monitor); + if (events < 0) + return events; + + r = sd_event_add_io(m->event, &m->network_monitor_event_source, + fd, events, &on_network_event, m); + if (r < 0) + return r; + + return 0; +} + +int manager_new(Manager **ret, Hashmap *interfaces, char **ignore, + LinkOperationalState required_operstate, + bool any, usec_t timeout) { + _cleanup_(manager_freep) Manager *m = NULL; + int r; + + assert(ret); + + m = new(Manager, 1); + if (!m) + return -ENOMEM; + + *m = (Manager) { + .interfaces = interfaces, + .ignore = ignore, + .required_operstate = required_operstate, + .any = any, + }; + + r = sd_event_default(&m->event); + if (r < 0) + return r; + + (void) sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); + (void) sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); + + if (timeout > 0) { + usec_t usec; + + usec = now(clock_boottime_or_monotonic()) + timeout; + + r = sd_event_add_time(m->event, NULL, clock_boottime_or_monotonic(), usec, 0, NULL, INT_TO_PTR(-ETIMEDOUT)); + if (r < 0) + return r; + } + + sd_event_set_watchdog(m->event, true); + + r = manager_network_monitor_listen(m); + if (r < 0) + return r; + + r = manager_rtnl_listen(m); + if (r < 0) + return r; + + *ret = TAKE_PTR(m); + + return 0; +} + +void manager_free(Manager *m) { + if (!m) + return; + + hashmap_free_with_destructor(m->links, link_free); + hashmap_free(m->links_by_name); + + sd_event_source_unref(m->network_monitor_event_source); + sd_network_monitor_unref(m->network_monitor); + + sd_event_source_unref(m->rtnl_event_source); + sd_netlink_unref(m->rtnl); + + sd_event_unref(m->event); + free(m); + + return; +} diff --git a/src/network/wait-online/manager.h b/src/network/wait-online/manager.h new file mode 100644 index 00000000..dd7d847d --- /dev/null +++ b/src/network/wait-online/manager.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" +#include "sd-netlink.h" +#include "sd-network.h" + +#include "hashmap.h" +#include "network-util.h" +#include "time-util.h" + +typedef struct Manager Manager; +typedef struct Link Link; + +struct Manager { + Hashmap *links; + Hashmap *links_by_name; + + /* Do not free the two members below. */ + Hashmap *interfaces; + char **ignore; + + LinkOperationalState required_operstate; + bool any; + + sd_netlink *rtnl; + sd_event_source *rtnl_event_source; + + sd_network_monitor *network_monitor; + sd_event_source *network_monitor_event_source; + + sd_event *event; +}; + +void manager_free(Manager *m); +int manager_new(Manager **ret, Hashmap *interfaces, char **ignore, + LinkOperationalState required_operstate, + bool any, usec_t timeout); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); + +bool manager_configured(Manager *m); diff --git a/src/network/wait-online/wait-online.c b/src/network/wait-online/wait-online.c new file mode 100644 index 00000000..4ce2ac31 --- /dev/null +++ b/src/network/wait-online/wait-online.c @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-daemon.h" + +#include "daemon-util.h" +#include "main-func.h" +#include "manager.h" +#include "pretty-print.h" +#include "signal-util.h" +#include "socket-util.h" +#include "strv.h" + +static bool arg_quiet = false; +static usec_t arg_timeout = 120 * USEC_PER_SEC; +static Hashmap *arg_interfaces = NULL; +static char **arg_ignore = NULL; +static LinkOperationalState arg_required_operstate = _LINK_OPERSTATE_INVALID; +static bool arg_any = false; + +STATIC_DESTRUCTOR_REGISTER(arg_interfaces, hashmap_free_free_keyp); +STATIC_DESTRUCTOR_REGISTER(arg_ignore, strv_freep); + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-networkd-wait-online.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n\n" + "Block until network is configured.\n\n" + " -h --help Show this help\n" + " --version Print version string\n" + " -q --quiet Do not show status information\n" + " -i --interface=INTERFACE[:OPERSTATE]\n" + " Block until at least these interfaces have appeared\n" + " --ignore=INTERFACE Don't take these interfaces into account\n" + " -o --operational-state=OPERSTATE\n" + " Required operational state\n" + " --any Wait until at least one of the interfaces is online\n" + " --timeout=SECS Maximum time to wait for network connectivity\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_interface_with_operstate(const char *str) { + _cleanup_free_ char *ifname = NULL; + LinkOperationalState s; + const char *p; + int r; + + assert(str); + + p = strchr(str, ':'); + if (p) { + if (isempty(p + 1)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Operational state is empty."); + + s = link_operstate_from_string(p + 1); + if (s < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid operational state '%s'", p + 1); + + ifname = strndup(optarg, p - optarg); + } else { + s = _LINK_OPERSTATE_INVALID; + ifname = strdup(str); + } + if (!ifname) + return log_oom(); + + if (!ifname_valid(ifname)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid interface name '%s'", ifname); + + r = hashmap_ensure_allocated(&arg_interfaces, &string_hash_ops); + if (r < 0) + return log_oom(); + + r = hashmap_put(arg_interfaces, ifname, INT_TO_PTR(s)); + if (r < 0) + return log_error_errno(r, "Failed to store interface name: %m"); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Interface name %s is already specified", ifname); + + TAKE_PTR(ifname); + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_IGNORE, + ARG_ANY, + ARG_TIMEOUT, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "quiet", no_argument, NULL, 'q' }, + { "interface", required_argument, NULL, 'i' }, + { "ignore", required_argument, NULL, ARG_IGNORE }, + { "operational-state", required_argument, NULL, 'o' }, + { "any", no_argument, NULL, ARG_ANY }, + { "timeout", required_argument, NULL, ARG_TIMEOUT }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hi:qo:", options, NULL)) >= 0) + + switch (c) { + + case 'h': + help(); + return 0; + + case 'q': + arg_quiet = true; + break; + + case ARG_VERSION: + return version(); + + case 'i': + r = parse_interface_with_operstate(optarg); + if (r < 0) + return r; + break; + + case ARG_IGNORE: + if (strv_extend(&arg_ignore, optarg) < 0) + return log_oom(); + + break; + + case 'o': { + LinkOperationalState s; + + s = link_operstate_from_string(optarg); + if (s < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid operational state '%s'", optarg); + + arg_required_operstate = s; + break; + } + case ARG_ANY: + arg_any = true; + break; + + case ARG_TIMEOUT: + r = parse_sec(optarg, &arg_timeout); + if (r < 0) + return r; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + int r; + + log_setup_service(); + + umask(0022); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (arg_quiet) + log_set_max_level(LOG_ERR); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + + r = manager_new(&m, arg_interfaces, arg_ignore, arg_required_operstate, arg_any, arg_timeout); + if (r < 0) + return log_error_errno(r, "Could not create manager: %m"); + + if (manager_configured(m)) + goto success; + + notify_message = notify_start("READY=1\n" + "STATUS=Waiting for network connections...", + "STATUS=Failed to wait for network connectivity..."); + + r = sd_event_loop(m->event); + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); + +success: + notify_message = "STATUS=All interfaces configured..."; + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/notify/notify.c b/src/notify/notify.c new file mode 100644 index 00000000..a76f3376 --- /dev/null +++ b/src/notify/notify.c @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "env-util.h" +#include "format-util.h" +#include "log.h" +#include "main-func.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "user-util.h" +#include "util.h" + +static bool arg_ready = false; +static pid_t arg_pid = 0; +static const char *arg_status = NULL; +static bool arg_booted = false; +static uid_t arg_uid = UID_INVALID; +static gid_t arg_gid = GID_INVALID; + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-notify", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [VARIABLE=VALUE...]\n" + "\n%sNotify the init system about service status updates.%s\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --ready Inform the init system about service start-up completion\n" + " --pid[=PID] Set main PID of daemon\n" + " --uid=USER Set user to send from\n" + " --status=TEXT Set status text\n" + " --booted Check if the system was booted up with systemd\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_READY = 0x100, + ARG_VERSION, + ARG_PID, + ARG_STATUS, + ARG_BOOTED, + ARG_UID, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "ready", no_argument, NULL, ARG_READY }, + { "pid", optional_argument, NULL, ARG_PID }, + { "status", required_argument, NULL, ARG_STATUS }, + { "booted", no_argument, NULL, ARG_BOOTED }, + { "uid", required_argument, NULL, ARG_UID }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) { + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_READY: + arg_ready = true; + break; + + case ARG_PID: + + if (optarg) { + if (parse_pid(optarg, &arg_pid) < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse PID %s.", optarg); + } else + arg_pid = getppid(); + + break; + + case ARG_STATUS: + arg_status = optarg; + break; + + case ARG_BOOTED: + arg_booted = true; + break; + + case ARG_UID: { + const char *u = optarg; + + r = get_user_creds(&u, &arg_uid, &arg_gid, NULL, NULL, 0); + if (r == -ESRCH) /* If the user doesn't exist, then accept it anyway as numeric */ + r = parse_uid(u, &arg_uid); + if (r < 0) + return log_error_errno(r, "Can't resolve user %s: %m", optarg); + + break; + } + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + } + + if (optind >= argc && + !arg_ready && + !arg_status && + !arg_pid && + !arg_booted) { + help(); + return -EINVAL; + } + + return 1; +} + +static int run(int argc, char* argv[]) { + _cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL; + _cleanup_strv_free_ char **final_env = NULL; + char* our_env[4]; + unsigned i = 0; + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (arg_booted) + return sd_booted() <= 0; + + if (arg_ready) + our_env[i++] = (char*) "READY=1"; + + if (arg_status) { + status = strjoin("STATUS=", arg_status); + if (!status) + return log_oom(); + + our_env[i++] = status; + } + + if (arg_pid > 0) { + if (asprintf(&cpid, "MAINPID="PID_FMT, arg_pid) < 0) + return log_oom(); + + our_env[i++] = cpid; + } + + our_env[i++] = NULL; + + final_env = strv_env_merge(2, our_env, argv + optind); + if (!final_env) + return log_oom(); + + if (strv_isempty(final_env)) + return 0; + + n = strv_join(final_env, "\n"); + if (!n) + return log_oom(); + + /* If this is requested change to the requested UID/GID. Note that we only change the real UID here, and leave + the effective UID in effect (which is 0 for this to work). That's because we want the privileges to fake the + ucred data, and sd_pid_notify() uses the real UID for filling in ucred. */ + + if (arg_gid != GID_INVALID && + setregid(arg_gid, (gid_t) -1) < 0) + return log_error_errno(errno, "Failed to change GID: %m"); + + if (arg_uid != UID_INVALID && + setreuid(arg_uid, (uid_t) -1) < 0) + return log_error_errno(errno, "Failed to change UID: %m"); + + r = sd_pid_notify(arg_pid ? arg_pid : getppid(), false, n); + if (r < 0) + return log_error_errno(r, "Failed to notify init system: %m"); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "No status data could be sent: $NOTIFY_SOCKET was not set"); + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/nspawn/meson.build b/src/nspawn/meson.build new file mode 100644 index 00000000..c049ac67 --- /dev/null +++ b/src/nspawn/meson.build @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +libnspawn_core_sources = files(''' + nspawn-cgroup.c + nspawn-cgroup.h + nspawn-def.h + nspawn-expose-ports.c + nspawn-expose-ports.h + nspawn-mount.c + nspawn-mount.h + nspawn-network.c + nspawn-network.h + nspawn-oci.c + nspawn-oci.h + nspawn-patch-uid.c + nspawn-patch-uid.h + nspawn-register.c + nspawn-register.h + nspawn-seccomp.c + nspawn-seccomp.h + nspawn-settings.c + nspawn-settings.h + nspawn-setuid.c + nspawn-setuid.h + nspawn-stub-pid1.c + nspawn-stub-pid1.h +'''.split()) + +nspawn_gperf_c = custom_target( + 'nspawn-gperf.c', + input : 'nspawn-gperf.gperf', + output : 'nspawn-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + +libnspawn_core_sources += [nspawn_gperf_c] + +libnspawn_core = static_library( + 'nspawn-core', + libnspawn_core_sources, + include_directories : includes, + dependencies : [libacl, + libseccomp, + libselinux]) + +systemd_nspawn_sources = files('nspawn.c') + +tests += [ + [['src/nspawn/test-nspawn-tables.c'], + [libnspawn_core, + libshared], + [libseccomp]], + + [['src/nspawn/test-patch-uid.c'], + [libnspawn_core, + libshared], + [libacl], + '', 'manual'], +] diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c new file mode 100644 index 00000000..f5048d94 --- /dev/null +++ b/src/nspawn/nspawn-cgroup.c @@ -0,0 +1,609 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "cgroup-setup.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "mkdir.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "nspawn-cgroup.h" +#include "nspawn-mount.h" +#include "path-util.h" +#include "rm-rf.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" + +static int chown_cgroup_path(const char *path, uid_t uid_shift) { + _cleanup_close_ int fd = -1; + const char *fn; + + fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (fd < 0) + return -errno; + + FOREACH_STRING(fn, + ".", + "cgroup.clone_children", + "cgroup.controllers", + "cgroup.events", + "cgroup.procs", + "cgroup.stat", + "cgroup.subtree_control", + "cgroup.threads", + "notify_on_release", + "tasks") + if (fchownat(fd, fn, uid_shift, uid_shift, 0) < 0) + log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, + "Failed to chown \"%s/%s\", ignoring: %m", path, fn); + + return 0; +} + +int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) { + _cleanup_free_ char *path = NULL, *fs = NULL; + int r; + + r = cg_pid_get_path(NULL, pid, &path); + if (r < 0) + return log_error_errno(r, "Failed to get container cgroup path: %m"); + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs); + if (r < 0) + return log_error_errno(r, "Failed to get file system path for container cgroup: %m"); + + r = chown_cgroup_path(fs, uid_shift); + if (r < 0) + return log_error_errno(r, "Failed to chown() cgroup %s: %m", fs); + + if (unified_requested == CGROUP_UNIFIED_SYSTEMD || (unified_requested == CGROUP_UNIFIED_NONE && cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0)) { + _cleanup_free_ char *lfs = NULL; + /* Always propagate access rights from unified to legacy controller */ + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, NULL, &lfs); + if (r < 0) + return log_error_errno(r, "Failed to get file system path for container cgroup: %m"); + + r = chown_cgroup_path(lfs, uid_shift); + if (r < 0) + return log_error_errno(r, "Failed to chown() cgroup %s: %m", lfs); + } + + return 0; +} + +int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) { + _cleanup_free_ char *cgroup = NULL; + char tree[] = "/tmp/unifiedXXXXXX", pid_string[DECIMAL_STR_MAX(pid) + 1]; + bool undo_mount = false; + const char *fn; + int r, unified_controller; + + unified_controller = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (unified_controller < 0) + return log_error_errno(unified_controller, "Failed to determine whether the systemd hierarchy is unified: %m"); + if ((unified_controller > 0) == (unified_requested >= CGROUP_UNIFIED_SYSTEMD)) + return 0; + + /* When the host uses the legacy cgroup setup, but the + * container shall use the unified hierarchy, let's make sure + * we copy the path from the name=systemd hierarchy into the + * unified hierarchy. Similar for the reverse situation. */ + + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup); + if (r < 0) + return log_error_errno(r, "Failed to get control group of " PID_FMT ": %m", pid); + + /* In order to access the unified hierarchy we need to mount it */ + if (!mkdtemp(tree)) + return log_error_errno(errno, "Failed to generate temporary mount point for unified hierarchy: %m"); + + if (unified_controller > 0) + r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup", + MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); + else + r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup2", + MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); + if (r < 0) + goto finish; + + undo_mount = true; + + /* If nspawn dies abruptly the cgroup hierarchy created below + * its unit isn't cleaned up. So, let's remove it + * https://github.com/systemd/systemd/pull/4223#issuecomment-252519810 */ + fn = strjoina(tree, cgroup); + (void) rm_rf(fn, REMOVE_ROOT|REMOVE_ONLY_DIRECTORIES); + + fn = strjoina(tree, cgroup, "/cgroup.procs"); + + sprintf(pid_string, PID_FMT, pid); + r = write_string_file(fn, pid_string, WRITE_STRING_FILE_DISABLE_BUFFER|WRITE_STRING_FILE_MKDIR_0755); + if (r < 0) { + log_error_errno(r, "Failed to move process: %m"); + goto finish; + } + + fn = strjoina(tree, cgroup); + r = chown_cgroup_path(fn, uid_shift); + if (r < 0) + log_error_errno(r, "Failed to chown() cgroup %s: %m", fn); +finish: + if (undo_mount) + (void) umount_verbose(tree); + + (void) rmdir(tree); + return r; +} + +int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested) { + _cleanup_free_ char *cgroup = NULL; + CGroupMask supported; + const char *payload; + int r; + + assert(pid > 1); + + /* In the unified hierarchy inner nodes may only contain subgroups, but not processes. Hence, if we running in + * the unified hierarchy and the container does the same, and we did not create a scope unit for the container + * move us and the container into two separate subcgroups. + * + * Moreover, container payloads such as systemd try to manage the cgroup they run in in full (i.e. including + * its attributes), while the host systemd will only delegate cgroups for children of the cgroup created for a + * delegation unit, instead of the cgroup itself. This means, if we'd pass on the cgroup allocated from the + * host systemd directly to the payload, the host and payload systemd might fight for the cgroup + * attributes. Hence, let's insert an intermediary cgroup to cover that case too. + * + * Note that we only bother with the main hierarchy here, not with any secondary ones. On the unified setup + * that's fine because there's only one hierarchy anyway and controllers are enabled directly on it. On the + * legacy setup, this is fine too, since delegation of controllers is generally not safe there, hence we won't + * do it. */ + + r = cg_mask_supported(&supported); + if (r < 0) + return log_error_errno(r, "Failed to determine supported controllers: %m"); + + if (keep_unit) + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup); + else + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup); + if (r < 0) + return log_error_errno(r, "Failed to get our control group: %m"); + + payload = strjoina(cgroup, "/payload"); + r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, payload, pid); + if (r < 0) + return log_error_errno(r, "Failed to create %s subcgroup: %m", payload); + + if (keep_unit) { + const char *supervisor; + + supervisor = strjoina(cgroup, "/supervisor"); + r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, supervisor, 0); + if (r < 0) + return log_error_errno(r, "Failed to create %s subcgroup: %m", supervisor); + } + + /* Try to enable as many controllers as possible for the new payload. */ + (void) cg_enable_everywhere(supported, supported, cgroup, NULL); + return 0; +} + +/* Retrieve existing subsystems. This function is called in a new cgroup + * namespace. + */ +static int get_process_controllers(Set **ret) { + _cleanup_set_free_free_ Set *controllers = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(ret); + + controllers = set_new(&string_hash_ops); + if (!controllers) + return -ENOMEM; + + f = fopen("/proc/self/cgroup", "re"); + if (!f) + return errno == ENOENT ? -ESRCH : -errno; + + for (;;) { + _cleanup_free_ char *line = NULL; + char *e, *l; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + l = strchr(line, ':'); + if (!l) + continue; + + l++; + e = strchr(l, ':'); + if (!e) + continue; + + *e = 0; + + if (STR_IN_SET(l, "", "name=systemd", "name=unified")) + continue; + + r = set_put_strdup(controllers, l); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(controllers); + + return 0; +} + +static int mount_legacy_cgroup_hierarchy( + const char *dest, + const char *controller, + const char *hierarchy, + bool read_only) { + + const char *to, *fstype, *opts; + int r; + + to = strjoina(strempty(dest), "/sys/fs/cgroup/", hierarchy); + + r = path_is_mount_point(to, dest, 0); + if (r < 0 && r != -ENOENT) + return log_error_errno(r, "Failed to determine if %s is mounted already: %m", to); + if (r > 0) + return 0; + + (void) mkdir_p(to, 0755); + + /* The superblock mount options of the mount point need to be + * identical to the hosts', and hence writable... */ + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER_HYBRID)) { + fstype = "cgroup2"; + opts = NULL; + } else if (streq(controller, SYSTEMD_CGROUP_CONTROLLER_LEGACY)) { + fstype = "cgroup"; + opts = "none,name=systemd,xattr"; + } else { + fstype = "cgroup"; + opts = controller; + } + + r = mount_verbose(LOG_ERR, "cgroup", to, fstype, MS_NOSUID|MS_NOEXEC|MS_NODEV, opts); + if (r < 0) + return r; + + /* ... hence let's only make the bind mount read-only, not the superblock. */ + if (read_only) { + r = mount_verbose(LOG_ERR, NULL, to, NULL, + MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL); + if (r < 0) + return r; + } + + return 1; +} + +/* Mount a legacy cgroup hierarchy when cgroup namespaces are supported. */ +static int mount_legacy_cgns_supported( + const char *dest, + CGroupUnified unified_requested, + bool userns, + uid_t uid_shift, + uid_t uid_range, + const char *selinux_apifs_context) { + + _cleanup_set_free_free_ Set *controllers = NULL; + const char *cgroup_root = "/sys/fs/cgroup", *c; + int r; + + (void) mkdir_p(cgroup_root, 0755); + + /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */ + r = path_is_mount_point(cgroup_root, dest, AT_SYMLINK_FOLLOW); + if (r < 0) + return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m"); + if (r == 0) { + _cleanup_free_ char *options = NULL; + + /* When cgroup namespaces are enabled and user namespaces are + * used then the mount of the cgroupfs is done *inside* the new + * user namespace. We're root in the new user namespace and the + * kernel will happily translate our uid/gid to the correct + * uid/gid as seen from e.g. /proc/1/mountinfo. So we simply + * pass uid 0 and not uid_shift to tmpfs_patch_options(). + */ + r = tmpfs_patch_options("mode=755", 0, selinux_apifs_context, &options); + if (r < 0) + return log_oom(); + + r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs", + MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options); + if (r < 0) + return r; + } + + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) + goto skip_controllers; + + r = get_process_controllers(&controllers); + if (r < 0) + return log_error_errno(r, "Failed to determine cgroup controllers: %m"); + + for (;;) { + _cleanup_free_ const char *controller = NULL; + + controller = set_steal_first(controllers); + if (!controller) + break; + + r = mount_legacy_cgroup_hierarchy("", controller, controller, !userns); + if (r < 0) + return r; + + /* When multiple hierarchies are co-mounted, make their + * constituting individual hierarchies a symlink to the + * co-mount. + */ + c = controller; + for (;;) { + _cleanup_free_ char *target = NULL, *tok = NULL; + + r = extract_first_word(&c, &tok, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to extract co-mounted cgroup controller: %m"); + if (r == 0) + break; + + if (streq(controller, tok)) + break; + + target = path_join("/sys/fs/cgroup/", tok); + if (!target) + return log_oom(); + + r = symlink_idempotent(controller, target, false); + if (r == -EINVAL) + return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m"); + if (r < 0) + return log_error_errno(r, "Failed to create symlink for combined hierarchy: %m"); + } + } + +skip_controllers: + if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) { + r = mount_legacy_cgroup_hierarchy("", SYSTEMD_CGROUP_CONTROLLER_HYBRID, "unified", false); + if (r < 0) + return r; + } + + r = mount_legacy_cgroup_hierarchy("", SYSTEMD_CGROUP_CONTROLLER_LEGACY, "systemd", false); + if (r < 0) + return r; + + if (!userns) + return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL, + MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); + + return 0; +} + +/* Mount legacy cgroup hierarchy when cgroup namespaces are unsupported. */ +static int mount_legacy_cgns_unsupported( + const char *dest, + CGroupUnified unified_requested, + bool userns, + uid_t uid_shift, + uid_t uid_range, + const char *selinux_apifs_context) { + + _cleanup_set_free_free_ Set *controllers = NULL; + const char *cgroup_root; + int r; + + cgroup_root = prefix_roota(dest, "/sys/fs/cgroup"); + + (void) mkdir_p(cgroup_root, 0755); + + /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */ + r = path_is_mount_point(cgroup_root, dest, AT_SYMLINK_FOLLOW); + if (r < 0) + return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m"); + if (r == 0) { + _cleanup_free_ char *options = NULL; + + r = tmpfs_patch_options("mode=755", uid_shift == 0 ? UID_INVALID : uid_shift, selinux_apifs_context, &options); + if (r < 0) + return log_oom(); + + r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs", + MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options); + if (r < 0) + return r; + } + + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) + goto skip_controllers; + + r = cg_kernel_controllers(&controllers); + if (r < 0) + return log_error_errno(r, "Failed to determine cgroup controllers: %m"); + + for (;;) { + _cleanup_free_ char *controller = NULL, *origin = NULL, *combined = NULL; + + controller = set_steal_first(controllers); + if (!controller) + break; + + origin = path_join("/sys/fs/cgroup/", controller); + if (!origin) + return log_oom(); + + r = readlink_malloc(origin, &combined); + if (r == -EINVAL) { + /* Not a symbolic link, but directly a single cgroup hierarchy */ + + r = mount_legacy_cgroup_hierarchy(dest, controller, controller, true); + if (r < 0) + return r; + + } else if (r < 0) + return log_error_errno(r, "Failed to read link %s: %m", origin); + else { + _cleanup_free_ char *target = NULL; + + target = path_join(dest, origin); + if (!target) + return log_oom(); + + /* A symbolic link, a combination of controllers in one hierarchy */ + + if (!filename_is_valid(combined)) { + log_warning("Ignoring invalid combined hierarchy %s.", combined); + continue; + } + + r = mount_legacy_cgroup_hierarchy(dest, combined, combined, true); + if (r < 0) + return r; + + r = symlink_idempotent(combined, target, false); + if (r == -EINVAL) + return log_error_errno(r, "Invalid existing symlink for combined hierarchy: %m"); + if (r < 0) + return log_error_errno(r, "Failed to create symlink for combined hierarchy: %m"); + } + } + +skip_controllers: + if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) { + r = mount_legacy_cgroup_hierarchy(dest, SYSTEMD_CGROUP_CONTROLLER_HYBRID, "unified", false); + if (r < 0) + return r; + } + + r = mount_legacy_cgroup_hierarchy(dest, SYSTEMD_CGROUP_CONTROLLER_LEGACY, "systemd", false); + if (r < 0) + return r; + + return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL, + MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); +} + +static int mount_unified_cgroups(const char *dest) { + const char *p; + int r; + + assert(dest); + + p = prefix_roota(dest, "/sys/fs/cgroup"); + + (void) mkdir_p(p, 0755); + + r = path_is_mount_point(p, dest, AT_SYMLINK_FOLLOW); + if (r < 0) + return log_error_errno(r, "Failed to determine if %s is mounted already: %m", p); + if (r > 0) { + p = prefix_roota(dest, "/sys/fs/cgroup/cgroup.procs"); + if (access(p, F_OK) >= 0) + return 0; + if (errno != ENOENT) + return log_error_errno(errno, "Failed to determine if mount point %s contains the unified cgroup hierarchy: %m", p); + + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s is already mounted but not a unified cgroup hierarchy. Refusing.", p); + } + + return mount_verbose(LOG_ERR, "cgroup", p, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); +} + +int mount_cgroups( + const char *dest, + CGroupUnified unified_requested, + bool userns, + uid_t uid_shift, + uid_t uid_range, + const char *selinux_apifs_context, + bool use_cgns) { + + if (unified_requested >= CGROUP_UNIFIED_ALL) + return mount_unified_cgroups(dest); + if (use_cgns) + return mount_legacy_cgns_supported(dest, unified_requested, userns, uid_shift, uid_range, selinux_apifs_context); + + return mount_legacy_cgns_unsupported(dest, unified_requested, userns, uid_shift, uid_range, selinux_apifs_context); +} + +static int mount_systemd_cgroup_writable_one(const char *root, const char *own) { + int r; + + assert(root); + assert(own); + + /* Make our own cgroup a (writable) bind mount */ + r = mount_verbose(LOG_ERR, own, own, NULL, MS_BIND, NULL); + if (r < 0) + return r; + + /* And then remount the systemd cgroup root read-only */ + return mount_verbose(LOG_ERR, NULL, root, NULL, + MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL); +} + +int mount_systemd_cgroup_writable( + const char *dest, + CGroupUnified unified_requested) { + + _cleanup_free_ char *own_cgroup_path = NULL; + const char *root, *own; + int r; + + assert(dest); + + r = cg_pid_get_path(NULL, 0, &own_cgroup_path); + if (r < 0) + return log_error_errno(r, "Failed to determine our own cgroup path: %m"); + + /* If we are living in the top-level, then there's nothing to do... */ + if (path_equal(own_cgroup_path, "/")) + return 0; + + if (unified_requested >= CGROUP_UNIFIED_ALL) { + + root = prefix_roota(dest, "/sys/fs/cgroup"); + own = strjoina(root, own_cgroup_path); + + } else { + + if (unified_requested >= CGROUP_UNIFIED_SYSTEMD) { + root = prefix_roota(dest, "/sys/fs/cgroup/unified"); + own = strjoina(root, own_cgroup_path); + + r = mount_systemd_cgroup_writable_one(root, own); + if (r < 0) + return r; + } + + root = prefix_roota(dest, "/sys/fs/cgroup/systemd"); + own = strjoina(root, own_cgroup_path); + } + + return mount_systemd_cgroup_writable_one(root, own); +} diff --git a/src/nspawn/nspawn-cgroup.h b/src/nspawn/nspawn-cgroup.h new file mode 100644 index 00000000..035e8fbd --- /dev/null +++ b/src/nspawn/nspawn-cgroup.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "cgroup-util.h" + +int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift); +int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift); +int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested); + +int mount_cgroups(const char *dest, CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns); +int mount_systemd_cgroup_writable(const char *dest, CGroupUnified unified_requested); diff --git a/src/nspawn/nspawn-def.h b/src/nspawn/nspawn-def.h new file mode 100644 index 00000000..9b54cda2 --- /dev/null +++ b/src/nspawn/nspawn-def.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +/* While we are chmod()ing a directory tree, we set the top-level UID base to this "busy" base, so that we can always + * recognize trees we are were chmod()ing recursively and got interrupted in */ +#define UID_BUSY_BASE ((uid_t) UINT32_C(0xFFFE0000)) +#define UID_BUSY_MASK ((uid_t) UINT32_C(0xFFFF0000)) diff --git a/src/nspawn/nspawn-expose-ports.c b/src/nspawn/nspawn-expose-ports.c new file mode 100644 index 00000000..10e61927 --- /dev/null +++ b/src/nspawn/nspawn-expose-ports.c @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "firewall-util.h" +#include "in-addr-util.h" +#include "local-addresses.h" +#include "netlink-util.h" +#include "nspawn-expose-ports.h" +#include "parse-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "util.h" + +int expose_port_parse(ExposePort **l, const char *s) { + + const char *split, *e; + uint16_t container_port, host_port; + int protocol; + ExposePort *p; + int r; + + assert(l); + assert(s); + + if ((e = startswith(s, "tcp:"))) + protocol = IPPROTO_TCP; + else if ((e = startswith(s, "udp:"))) + protocol = IPPROTO_UDP; + else { + e = s; + protocol = IPPROTO_TCP; + } + + split = strchr(e, ':'); + if (split) { + char v[split - e + 1]; + + memcpy(v, e, split - e); + v[split - e] = 0; + + r = parse_ip_port(v, &host_port); + if (r < 0) + return -EINVAL; + + r = parse_ip_port(split + 1, &container_port); + } else { + r = parse_ip_port(e, &container_port); + host_port = container_port; + } + + if (r < 0) + return -EINVAL; + + LIST_FOREACH(ports, p, *l) + if (p->protocol == protocol && p->host_port == host_port) + return -EEXIST; + + p = new(ExposePort, 1); + if (!p) + return -ENOMEM; + + p->protocol = protocol; + p->host_port = host_port; + p->container_port = container_port; + + LIST_PREPEND(ports, *l, p); + + return 0; +} + +void expose_port_free_all(ExposePort *p) { + + while (p) { + ExposePort *q = p; + LIST_REMOVE(ports, p, q); + free(q); + } +} + +int expose_port_flush(ExposePort* l, union in_addr_union *exposed) { + ExposePort *p; + int r, af = AF_INET; + + assert(exposed); + + if (!l) + return 0; + + if (in_addr_is_null(af, exposed)) + return 0; + + log_debug("Lost IP address."); + + LIST_FOREACH(ports, p, l) { + r = fw_add_local_dnat(false, + af, + p->protocol, + NULL, + NULL, 0, + NULL, 0, + p->host_port, + exposed, + p->container_port, + NULL); + if (r < 0) + log_warning_errno(r, "Failed to modify firewall: %m"); + } + + *exposed = IN_ADDR_NULL; + return 0; +} + +int expose_port_execute(sd_netlink *rtnl, ExposePort *l, union in_addr_union *exposed) { + _cleanup_free_ struct local_address *addresses = NULL; + _cleanup_free_ char *pretty = NULL; + union in_addr_union new_exposed; + ExposePort *p; + bool add; + int af = AF_INET, r; + + assert(exposed); + + /* Invoked each time an address is added or removed inside the + * container */ + + if (!l) + return 0; + + r = local_addresses(rtnl, 0, af, &addresses); + if (r < 0) + return log_error_errno(r, "Failed to enumerate local addresses: %m"); + + add = r > 0 && + addresses[0].family == af && + addresses[0].scope < RT_SCOPE_LINK; + + if (!add) + return expose_port_flush(l, exposed); + + new_exposed = addresses[0].address; + if (in_addr_equal(af, exposed, &new_exposed)) + return 0; + + in_addr_to_string(af, &new_exposed, &pretty); + log_debug("New container IP is %s.", strna(pretty)); + + LIST_FOREACH(ports, p, l) { + + r = fw_add_local_dnat(true, + af, + p->protocol, + NULL, + NULL, 0, + NULL, 0, + p->host_port, + &new_exposed, + p->container_port, + in_addr_is_null(af, exposed) ? NULL : exposed); + if (r < 0) + log_warning_errno(r, "Failed to modify firewall: %m"); + } + + *exposed = new_exposed; + return 0; +} + +int expose_port_send_rtnl(int send_fd) { + _cleanup_close_ int fd = -1; + int r; + + assert(send_fd >= 0); + + fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_ROUTE); + if (fd < 0) + return log_error_errno(errno, "Failed to allocate container netlink: %m"); + + /* Store away the fd in the socket, so that it stays open as + * long as we run the child */ + r = send_one_fd(send_fd, fd, 0); + if (r < 0) + return log_error_errno(r, "Failed to send netlink fd: %m"); + + return 0; +} + +int expose_port_watch_rtnl( + sd_event *event, + int recv_fd, + sd_netlink_message_handler_t handler, + union in_addr_union *exposed, + sd_netlink **ret) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + int fd, r; + + assert(event); + assert(recv_fd >= 0); + assert(ret); + + fd = receive_one_fd(recv_fd, 0); + if (fd < 0) + return log_error_errno(fd, "Failed to recv netlink fd: %m"); + + r = sd_netlink_open_fd(&rtnl, fd); + if (r < 0) { + safe_close(fd); + return log_error_errno(r, "Failed to create rtnl object: %m"); + } + + r = sd_netlink_add_match(rtnl, NULL, RTM_NEWADDR, handler, NULL, exposed, "nspawn-NEWADDR"); + if (r < 0) + return log_error_errno(r, "Failed to subscribe to RTM_NEWADDR messages: %m"); + + r = sd_netlink_add_match(rtnl, NULL, RTM_DELADDR, handler, NULL, exposed, "nspawn-DELADDR"); + if (r < 0) + return log_error_errno(r, "Failed to subscribe to RTM_DELADDR messages: %m"); + + r = sd_netlink_attach_event(rtnl, event, 0); + if (r < 0) + return log_error_errno(r, "Failed to add to event loop: %m"); + + *ret = TAKE_PTR(rtnl); + + return 0; +} diff --git a/src/nspawn/nspawn-expose-ports.h b/src/nspawn/nspawn-expose-ports.h new file mode 100644 index 00000000..7ed7bee0 --- /dev/null +++ b/src/nspawn/nspawn-expose-ports.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-event.h" +#include "sd-netlink.h" + +#include "in-addr-util.h" +#include "list.h" + +typedef struct ExposePort { + int protocol; + uint16_t host_port; + uint16_t container_port; + LIST_FIELDS(struct ExposePort, ports); +} ExposePort; + +void expose_port_free_all(ExposePort *p); +int expose_port_parse(ExposePort **l, const char *s); + +int expose_port_watch_rtnl(sd_event *event, int recv_fd, sd_netlink_message_handler_t handler, union in_addr_union *exposed, sd_netlink **ret); +int expose_port_send_rtnl(int send_fd); + +int expose_port_execute(sd_netlink *rtnl, ExposePort *l, union in_addr_union *exposed); +int expose_port_flush(ExposePort* l, union in_addr_union *exposed); diff --git a/src/nspawn/nspawn-gperf.gperf b/src/nspawn/nspawn-gperf.gperf new file mode 100644 index 00000000..79304d21 --- /dev/null +++ b/src/nspawn/nspawn-gperf.gperf @@ -0,0 +1,77 @@ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif +#include +#include "conf-parser.h" +#include "nspawn-settings.h" +#include "nspawn-expose-ports.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name nspawn_gperf_hash +%define lookup-function-name nspawn_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +Exec.Boot, config_parse_boot, 0, 0 +Exec.Ephemeral, config_parse_bool, 0, offsetof(Settings, ephemeral) +Exec.ProcessTwo, config_parse_pid2, 0, 0 +Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters) +Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment) +Exec.User, config_parse_string, 0, offsetof(Settings, user) +Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability) +Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability) +Exec.KillSignal, config_parse_signal, 0, offsetof(Settings, kill_signal) +Exec.Personality, config_parse_personality, 0, offsetof(Settings, personality) +Exec.MachineID, config_parse_id128, 0, offsetof(Settings, machine_id) +Exec.WorkingDirectory, config_parse_path, 0, offsetof(Settings, working_directory) +Exec.PivotRoot, config_parse_pivot_root, 0, 0 +Exec.PrivateUsers, config_parse_private_users, 0, 0 +Exec.NotifyReady, config_parse_bool, 0, offsetof(Settings, notify_ready) +Exec.SystemCallFilter, config_parse_syscall_filter, 0, 0, +Exec.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof(Settings, rlimit) +Exec.LimitFSIZE, config_parse_rlimit, RLIMIT_FSIZE, offsetof(Settings, rlimit) +Exec.LimitDATA, config_parse_rlimit, RLIMIT_DATA, offsetof(Settings, rlimit) +Exec.LimitSTACK, config_parse_rlimit, RLIMIT_STACK, offsetof(Settings, rlimit) +Exec.LimitCORE, config_parse_rlimit, RLIMIT_CORE, offsetof(Settings, rlimit) +Exec.LimitRSS, config_parse_rlimit, RLIMIT_RSS, offsetof(Settings, rlimit) +Exec.LimitNOFILE, config_parse_rlimit, RLIMIT_NOFILE, offsetof(Settings, rlimit) +Exec.LimitAS, config_parse_rlimit, RLIMIT_AS, offsetof(Settings, rlimit) +Exec.LimitNPROC, config_parse_rlimit, RLIMIT_NPROC, offsetof(Settings, rlimit) +Exec.LimitMEMLOCK, config_parse_rlimit, RLIMIT_MEMLOCK, offsetof(Settings, rlimit) +Exec.LimitLOCKS, config_parse_rlimit, RLIMIT_LOCKS, offsetof(Settings, rlimit) +Exec.LimitSIGPENDING, config_parse_rlimit, RLIMIT_SIGPENDING, offsetof(Settings, rlimit) +Exec.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, offsetof(Settings, rlimit) +Exec.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof(Settings, rlimit) +Exec.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof(Settings, rlimit) +Exec.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof(Settings, rlimit) +Exec.Hostname, config_parse_hostname, 0, offsetof(Settings, hostname) +Exec.NoNewPrivileges, config_parse_tristate, 0, offsetof(Settings, no_new_privileges) +Exec.OOMScoreAdjust, config_parse_oom_score_adjust, 0, 0 +Exec.CPUAffinity, config_parse_cpu_affinity, 0, 0 +Exec.ResolvConf, config_parse_resolv_conf, 0, offsetof(Settings, resolv_conf) +Exec.LinkJournal, config_parse_link_journal, 0, 0 +Exec.Timezone, config_parse_timezone, 0, offsetof(Settings, timezone) +Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only) +Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode) +Files.Bind, config_parse_bind, 0, 0 +Files.BindReadOnly, config_parse_bind, 1, 0 +Files.TemporaryFileSystem, config_parse_tmpfs, 0, 0 +Files.Inaccessible, config_parse_inaccessible, 0, 0 +Files.Overlay, config_parse_overlay, 0, 0 +Files.OverlayReadOnly, config_parse_overlay, 1, 0 +Files.PrivateUsersChown, config_parse_tristate, 0, offsetof(Settings, userns_chown) +Network.Private, config_parse_tristate, 0, offsetof(Settings, private_network) +Network.Interface, config_parse_strv, 0, offsetof(Settings, network_interfaces) +Network.MACVLAN, config_parse_strv, 0, offsetof(Settings, network_macvlan) +Network.IPVLAN, config_parse_strv, 0, offsetof(Settings, network_ipvlan) +Network.VirtualEthernet, config_parse_tristate, 0, offsetof(Settings, network_veth) +Network.VirtualEthernetExtra, config_parse_veth_extra, 0, 0 +Network.Bridge, config_parse_ifname, 0, offsetof(Settings, network_bridge) +Network.Zone, config_parse_network_zone, 0, 0 +Network.Port, config_parse_expose_port, 0, 0 diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c new file mode 100644 index 00000000..6407503c --- /dev/null +++ b/src/nspawn/nspawn-mount.c @@ -0,0 +1,1298 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "escape.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "label.h" +#include "mkdir.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "nspawn-mount.h" +#include "parse-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "set.h" +#include "sort-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "user-util.h" + +CustomMount* custom_mount_add(CustomMount **l, size_t *n, CustomMountType t) { + CustomMount *c, *ret; + + assert(l); + assert(n); + assert(t >= 0); + assert(t < _CUSTOM_MOUNT_TYPE_MAX); + + c = reallocarray(*l, *n + 1, sizeof(CustomMount)); + if (!c) + return NULL; + + *l = c; + ret = *l + *n; + (*n)++; + + *ret = (CustomMount) { .type = t }; + + return ret; +} + +void custom_mount_free_all(CustomMount *l, size_t n) { + size_t i; + + for (i = 0; i < n; i++) { + CustomMount *m = l + i; + + free(m->source); + free(m->destination); + free(m->options); + + if (m->work_dir) { + (void) rm_rf(m->work_dir, REMOVE_ROOT|REMOVE_PHYSICAL); + free(m->work_dir); + } + + if (m->rm_rf_tmpdir) { + (void) rm_rf(m->rm_rf_tmpdir, REMOVE_ROOT|REMOVE_PHYSICAL); + free(m->rm_rf_tmpdir); + } + + strv_free(m->lower); + free(m->type_argument); + } + + free(l); +} + +static int custom_mount_compare(const CustomMount *a, const CustomMount *b) { + int r; + + r = path_compare(a->destination, b->destination); + if (r != 0) + return r; + + return CMP(a->type, b->type); +} + +static bool source_path_is_valid(const char *p) { + assert(p); + + if (*p == '+') + p++; + + return path_is_absolute(p); +} + +static char *resolve_source_path(const char *dest, const char *source) { + + if (!source) + return NULL; + + if (source[0] == '+') + return path_join(dest, source + 1); + + return strdup(source); +} + +int custom_mount_prepare_all(const char *dest, CustomMount *l, size_t n) { + size_t i; + int r; + + /* Prepare all custom mounts. This will make source we know all temporary directories. This is called in the + * parent process, so that we know the temporary directories to remove on exit before we fork off the + * children. */ + + assert(l || n == 0); + + /* Order the custom mounts, and make sure we have a working directory */ + typesafe_qsort(l, n, custom_mount_compare); + + for (i = 0; i < n; i++) { + CustomMount *m = l + i; + + /* /proc we mount in the inner child, i.e. when we acquired CLONE_NEWPID. All other mounts we mount + * already in the outer child, so that the mounts are already established before CLONE_NEWPID and in + * particular CLONE_NEWUSER. This also means any custom mounts below /proc also need to be mounted in + * the inner child, not the outer one. Determine this here. */ + m->in_userns = path_startswith(m->destination, "/proc"); + + if (m->type == CUSTOM_MOUNT_BIND) { + if (m->source) { + char *s; + + s = resolve_source_path(dest, m->source); + if (!s) + return log_oom(); + + free_and_replace(m->source, s); + } else { + /* No source specified? In that case, use a throw-away temporary directory in /var/tmp */ + + m->rm_rf_tmpdir = strdup("/var/tmp/nspawn-temp-XXXXXX"); + if (!m->rm_rf_tmpdir) + return log_oom(); + + if (!mkdtemp(m->rm_rf_tmpdir)) { + m->rm_rf_tmpdir = mfree(m->rm_rf_tmpdir); + return log_error_errno(errno, "Failed to acquire temporary directory: %m"); + } + + m->source = path_join(m->rm_rf_tmpdir, "src"); + if (!m->source) + return log_oom(); + + if (mkdir(m->source, 0755) < 0) + return log_error_errno(errno, "Failed to create %s: %m", m->source); + } + } + + if (m->type == CUSTOM_MOUNT_OVERLAY) { + char **j; + + STRV_FOREACH(j, m->lower) { + char *s; + + s = resolve_source_path(dest, *j); + if (!s) + return log_oom(); + + free_and_replace(*j, s); + } + + if (m->work_dir) { + char *s; + + s = resolve_source_path(dest, m->work_dir); + if (!s) + return log_oom(); + + free_and_replace(m->work_dir, s); + } else { + assert(m->source); + + r = tempfn_random(m->source, NULL, &m->work_dir); + if (r < 0) + return log_error_errno(r, "Failed to acquire working directory: %m"); + } + + (void) mkdir_label(m->work_dir, 0700); + } + } + + return 0; +} + +int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) { + _cleanup_free_ char *source = NULL, *destination = NULL, *opts = NULL; + const char *p = s; + CustomMount *m; + int r; + + assert(l); + assert(n); + + r = extract_many_words(&p, ":", EXTRACT_DONT_COALESCE_SEPARATORS, &source, &destination, NULL); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + if (r == 1) { + destination = strdup(source[0] == '+' ? source+1 : source); + if (!destination) + return -ENOMEM; + } + if (r == 2 && !isempty(p)) { + opts = strdup(p); + if (!opts) + return -ENOMEM; + } + + if (isempty(source)) + source = mfree(source); + else if (!source_path_is_valid(source)) + return -EINVAL; + + if (!path_is_absolute(destination)) + return -EINVAL; + if (empty_or_root(destination)) + return -EINVAL; + + m = custom_mount_add(l, n, CUSTOM_MOUNT_BIND); + if (!m) + return -ENOMEM; + + m->source = TAKE_PTR(source); + m->destination = TAKE_PTR(destination); + m->read_only = read_only; + m->options = TAKE_PTR(opts); + + return 0; +} + +int tmpfs_mount_parse(CustomMount **l, size_t *n, const char *s) { + _cleanup_free_ char *path = NULL, *opts = NULL; + const char *p = s; + CustomMount *m; + int r; + + assert(l); + assert(n); + assert(s); + + r = extract_first_word(&p, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + if (isempty(p)) + opts = strdup("mode=0755"); + else + opts = strdup(p); + if (!opts) + return -ENOMEM; + + if (!path_is_absolute(path)) + return -EINVAL; + if (empty_or_root(path)) + return -EINVAL; + + m = custom_mount_add(l, n, CUSTOM_MOUNT_TMPFS); + if (!m) + return -ENOMEM; + + m->destination = TAKE_PTR(path); + m->options = TAKE_PTR(opts); + + return 0; +} + +int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) { + _cleanup_free_ char *upper = NULL, *destination = NULL; + _cleanup_strv_free_ char **lower = NULL; + CustomMount *m; + int k; + + k = strv_split_extract(&lower, s, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (k < 0) + return k; + if (k < 2) + return -EADDRNOTAVAIL; + if (k == 2) { + /* If two parameters are specified, the first one is the lower, the second one the upper directory. And + * we'll also define the destination mount point the same as the upper. */ + + if (!source_path_is_valid(lower[0]) || + !source_path_is_valid(lower[1])) + return -EINVAL; + + upper = TAKE_PTR(lower[1]); + + destination = strdup(upper[0] == '+' ? upper+1 : upper); /* take the destination without "+" prefix */ + if (!destination) + return -ENOMEM; + } else { + char **i; + + /* If more than two parameters are specified, the last one is the destination, the second to last one + * the "upper", and all before that the "lower" directories. */ + + destination = lower[k - 1]; + upper = TAKE_PTR(lower[k - 2]); + + STRV_FOREACH(i, lower) + if (!source_path_is_valid(*i)) + return -EINVAL; + + /* If the upper directory is unspecified, then let's create it automatically as a throw-away directory + * in /var/tmp */ + if (isempty(upper)) + upper = mfree(upper); + else if (!source_path_is_valid(upper)) + return -EINVAL; + + if (!path_is_absolute(destination)) + return -EINVAL; + } + + if (empty_or_root(destination)) + return -EINVAL; + + m = custom_mount_add(l, n, CUSTOM_MOUNT_OVERLAY); + if (!m) + return -ENOMEM; + + m->destination = TAKE_PTR(destination); + m->source = TAKE_PTR(upper); + m->lower = TAKE_PTR(lower); + m->read_only = read_only; + + return 0; +} + +int inaccessible_mount_parse(CustomMount **l, size_t *n, const char *s) { + _cleanup_free_ char *path = NULL; + CustomMount *m; + + assert(l); + assert(n); + assert(s); + + if (!path_is_absolute(s)) + return -EINVAL; + + path = strdup(s); + if (!path) + return -ENOMEM; + + m = custom_mount_add(l, n, CUSTOM_MOUNT_INACCESSIBLE); + if (!m) + return -ENOMEM; + + m->destination = TAKE_PTR(path); + return 0; +} + +int tmpfs_patch_options( + const char *options, + uid_t uid_shift, + const char *selinux_apifs_context, + char **ret) { + + char *buf = NULL; + + if (uid_shift != UID_INVALID) { + if (asprintf(&buf, "%s%suid=" UID_FMT ",gid=" UID_FMT, + strempty(options), options ? "," : "", + uid_shift, uid_shift) < 0) + return -ENOMEM; + + options = buf; + } + +#if HAVE_SELINUX + if (selinux_apifs_context) { + char *t; + + t = strjoin(strempty(options), options ? "," : "", + "context=\"", selinux_apifs_context, "\""); + free(buf); + if (!t) + return -ENOMEM; + + buf = t; + } +#endif + + if (!buf && options) { + buf = strdup(options); + if (!buf) + return -ENOMEM; + } + *ret = buf; + + return !!buf; +} + +int mount_sysfs(const char *dest, MountSettingsMask mount_settings) { + const char *full, *top, *x; + int r; + unsigned long extra_flags = 0; + + top = prefix_roota(dest, "/sys"); + r = path_is_fs_type(top, SYSFS_MAGIC); + if (r < 0) + return log_error_errno(r, "Failed to determine filesystem type of %s: %m", top); + /* /sys might already be mounted as sysfs by the outer child in the + * !netns case. In this case, it's all good. Don't touch it because we + * don't have the right to do so, see https://github.com/systemd/systemd/issues/1555. + */ + if (r > 0) + return 0; + + full = prefix_roota(top, "/full"); + + (void) mkdir(full, 0755); + + if (mount_settings & MOUNT_APPLY_APIVFS_RO) + extra_flags |= MS_RDONLY; + + r = mount_verbose(LOG_ERR, "sysfs", full, "sysfs", + MS_NOSUID|MS_NOEXEC|MS_NODEV|extra_flags, NULL); + if (r < 0) + return r; + + FOREACH_STRING(x, "block", "bus", "class", "dev", "devices", "kernel") { + _cleanup_free_ char *from = NULL, *to = NULL; + + from = path_join(full, x); + if (!from) + return log_oom(); + + to = path_join(top, x); + if (!to) + return log_oom(); + + (void) mkdir(to, 0755); + + r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL); + if (r < 0) + return r; + + r = mount_verbose(LOG_ERR, NULL, to, NULL, + MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT|extra_flags, NULL); + if (r < 0) + return r; + } + + r = umount_verbose(full); + if (r < 0) + return r; + + if (rmdir(full) < 0) + return log_error_errno(errno, "Failed to remove %s: %m", full); + + /* Create mountpoint for cgroups. Otherwise we are not allowed since we + * remount /sys read-only. + */ + x = prefix_roota(top, "/fs/cgroup"); + (void) mkdir_p(x, 0755); + + return mount_verbose(LOG_ERR, NULL, top, NULL, + MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT|extra_flags, NULL); +} + +static int mkdir_userns(const char *path, mode_t mode, uid_t uid_shift) { + int r; + + assert(path); + + r = mkdir_errno_wrapper(path, mode); + if (r < 0 && r != -EEXIST) + return r; + + if (uid_shift == UID_INVALID) + return 0; + + if (lchown(path, uid_shift, uid_shift) < 0) + return -errno; + + return 0; +} + +static int mkdir_userns_p(const char *prefix, const char *path, mode_t mode, uid_t uid_shift) { + const char *p, *e; + int r; + + assert(path); + + if (prefix && !path_startswith(path, prefix)) + return -ENOTDIR; + + /* create every parent directory in the path, except the last component */ + p = path + strspn(path, "/"); + for (;;) { + char t[strlen(path) + 1]; + + e = p + strcspn(p, "/"); + p = e + strspn(e, "/"); + + /* Is this the last component? If so, then we're done */ + if (*p == 0) + break; + + memcpy(t, path, e - path); + t[e-path] = 0; + + if (prefix && path_startswith(prefix, t)) + continue; + + r = mkdir_userns(t, mode, uid_shift); + if (r < 0) + return r; + } + + return mkdir_userns(path, mode, uid_shift); +} + +int mount_all(const char *dest, + MountSettingsMask mount_settings, + uid_t uid_shift, + const char *selinux_apifs_context) { + +#define PROC_INACCESSIBLE_REG(path) \ + { "/run/systemd/inaccessible/reg", (path), NULL, NULL, MS_BIND, \ + MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */ \ + { NULL, (path), NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, \ + MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO } /* Then, make it r/o */ + +#define PROC_READ_ONLY(path) \ + { (path), (path), NULL, NULL, MS_BIND, \ + MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */ \ + { NULL, (path), NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, \ + MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO } /* Then, make it r/o */ + + typedef struct MountPoint { + const char *what; + const char *where; + const char *type; + const char *options; + unsigned long flags; + MountSettingsMask mount_settings; + } MountPoint; + + static const MountPoint mount_table[] = { + /* First we list inner child mounts (i.e. mounts applied *after* entering user namespacing) */ + { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + MOUNT_FATAL|MOUNT_IN_USERNS }, + + { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, + MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */ + + { "/proc/sys/net", "/proc/sys/net", NULL, NULL, MS_BIND, + MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_APIVFS_NETNS }, /* (except for this) */ + + { NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, + MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */ + + /* Make these files inaccessible to container payloads: they potentially leak information about kernel + * internals or the host's execution environment to the container */ + PROC_INACCESSIBLE_REG("/proc/kallsyms"), + PROC_INACCESSIBLE_REG("/proc/kcore"), + PROC_INACCESSIBLE_REG("/proc/keys"), + PROC_INACCESSIBLE_REG("/proc/sysrq-trigger"), + PROC_INACCESSIBLE_REG("/proc/timer_list"), + + /* Make these directories read-only to container payloads: they show hardware information, and in some + * cases contain tunables the container really shouldn't have access to. */ + PROC_READ_ONLY("/proc/acpi"), + PROC_READ_ONLY("/proc/apm"), + PROC_READ_ONLY("/proc/asound"), + PROC_READ_ONLY("/proc/bus"), + PROC_READ_ONLY("/proc/fs"), + PROC_READ_ONLY("/proc/irq"), + PROC_READ_ONLY("/proc/scsi"), + + { "mqueue", "/dev/mqueue", "mqueue", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + MOUNT_IN_USERNS }, + + /* Then we list outer child mounts (i.e. mounts applied *before* entering user namespacing) */ + { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + MOUNT_FATAL|MOUNT_APPLY_TMPFS_TMP }, + { "tmpfs", "/sys", "tmpfs", "mode=555", MS_NOSUID|MS_NOEXEC|MS_NODEV, + MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS }, + { "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, + MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO }, /* skipped if above was mounted */ + { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + MOUNT_FATAL }, /* skipped if above was mounted */ + { "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, + MOUNT_FATAL }, + { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + MOUNT_FATAL }, + { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + MOUNT_FATAL }, + +#if HAVE_SELINUX + { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, + 0 }, /* Bind mount first */ + { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, + 0 }, /* Then, make it r/o */ +#endif + }; + + bool use_userns = (mount_settings & MOUNT_USE_USERNS); + bool netns = (mount_settings & MOUNT_APPLY_APIVFS_NETNS); + bool ro = (mount_settings & MOUNT_APPLY_APIVFS_RO); + bool in_userns = (mount_settings & MOUNT_IN_USERNS); + bool tmpfs_tmp = (mount_settings & MOUNT_APPLY_TMPFS_TMP); + size_t k; + int r; + + for (k = 0; k < ELEMENTSOF(mount_table); k++) { + _cleanup_free_ char *where = NULL, *options = NULL; + const char *o; + bool fatal = (mount_table[k].mount_settings & MOUNT_FATAL); + + if (in_userns != (bool)(mount_table[k].mount_settings & MOUNT_IN_USERNS)) + continue; + + if (!netns && (bool)(mount_table[k].mount_settings & MOUNT_APPLY_APIVFS_NETNS)) + continue; + + if (!ro && (bool)(mount_table[k].mount_settings & MOUNT_APPLY_APIVFS_RO)) + continue; + + if (!tmpfs_tmp && (bool)(mount_table[k].mount_settings & MOUNT_APPLY_TMPFS_TMP)) + continue; + + r = chase_symlinks(mount_table[k].where, dest, CHASE_NONEXISTENT|CHASE_PREFIX_ROOT, &where, NULL); + if (r < 0) + return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].where); + + /* Skip this entry if it is not a remount. */ + if (mount_table[k].what) { + r = path_is_mount_point(where, NULL, 0); + if (r < 0 && r != -ENOENT) + return log_error_errno(r, "Failed to detect whether %s is a mount point: %m", where); + if (r > 0) + continue; + } + + r = mkdir_userns_p(dest, where, 0755, (use_userns && !in_userns) ? uid_shift : UID_INVALID); + if (r < 0 && r != -EEXIST) { + if (fatal && r != -EROFS) + return log_error_errno(r, "Failed to create directory %s: %m", where); + + log_debug_errno(r, "Failed to create directory %s: %m", where); + /* If we failed mkdir() or chown() due to the root + * directory being read only, attempt to mount this fs + * anyway and let mount_verbose log any errors */ + if (r != -EROFS) + continue; + } + + o = mount_table[k].options; + if (streq_ptr(mount_table[k].type, "tmpfs")) { + r = tmpfs_patch_options(o, in_userns ? 0 : uid_shift, selinux_apifs_context, &options); + if (r < 0) + return log_oom(); + if (r > 0) + o = options; + } + + r = mount_verbose(fatal ? LOG_ERR : LOG_DEBUG, + mount_table[k].what, + where, + mount_table[k].type, + mount_table[k].flags, + o); + if (r < 0 && fatal) + return r; + } + + return 0; +} + +static int parse_mount_bind_options(const char *options, unsigned long *mount_flags, char **mount_opts) { + const char *p = options; + unsigned long flags = *mount_flags; + char *opts = NULL; + int r; + + assert(options); + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to extract mount option: %m"); + if (r == 0) + break; + + if (streq(word, "rbind")) + flags |= MS_REC; + else if (streq(word, "norbind")) + flags &= ~MS_REC; + else { + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid bind mount option: %s", + word); + } + } + + *mount_flags = flags; + /* in the future mount_opts will hold string options for mount(2) */ + *mount_opts = opts; + + return 0; +} + +static int mount_bind(const char *dest, CustomMount *m) { + _cleanup_free_ char *mount_opts = NULL, *where = NULL; + unsigned long mount_flags = MS_BIND | MS_REC; + struct stat source_st, dest_st; + int r; + + assert(dest); + assert(m); + + if (m->options) { + r = parse_mount_bind_options(m->options, &mount_flags, &mount_opts); + if (r < 0) + return r; + } + + if (stat(m->source, &source_st) < 0) + return log_error_errno(errno, "Failed to stat %s: %m", m->source); + + r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); + if (r < 0) + return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); + if (r > 0) { /* Path exists already? */ + + if (stat(where, &dest_st) < 0) + return log_error_errno(errno, "Failed to stat %s: %m", where); + + if (S_ISDIR(source_st.st_mode) && !S_ISDIR(dest_st.st_mode)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot bind mount directory %s on file %s.", + m->source, where); + + if (!S_ISDIR(source_st.st_mode) && S_ISDIR(dest_st.st_mode)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot bind mount file %s on directory %s.", + m->source, where); + + } else { /* Path doesn't exist yet? */ + r = mkdir_parents_label(where, 0755); + if (r < 0) + return log_error_errno(r, "Failed to make parents of %s: %m", where); + + /* Create the mount point. Any non-directory file can be + * mounted on any non-directory file (regular, fifo, socket, + * char, block). + */ + if (S_ISDIR(source_st.st_mode)) + r = mkdir_label(where, 0755); + else + r = touch(where); + if (r < 0) + return log_error_errno(r, "Failed to create mount point %s: %m", where); + } + + r = mount_verbose(LOG_ERR, m->source, where, NULL, mount_flags, mount_opts); + if (r < 0) + return r; + + if (m->read_only) { + r = bind_remount_recursive(where, MS_RDONLY, MS_RDONLY, NULL); + if (r < 0) + return log_error_errno(r, "Read-only bind mount failed: %m"); + } + + return 0; +} + +static int mount_tmpfs( + const char *dest, + CustomMount *m, + bool userns, uid_t uid_shift, uid_t uid_range, + const char *selinux_apifs_context) { + + const char *options; + _cleanup_free_ char *buf = NULL, *where = NULL; + int r; + + assert(dest); + assert(m); + + r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); + if (r < 0) + return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); + if (r == 0) { /* Doesn't exist yet? */ + r = mkdir_p_label(where, 0755); + if (r < 0) + return log_error_errno(r, "Creating mount point for tmpfs %s failed: %m", where); + } + + r = tmpfs_patch_options(m->options, uid_shift == 0 ? UID_INVALID : uid_shift, selinux_apifs_context, &buf); + if (r < 0) + return log_oom(); + options = r > 0 ? buf : m->options; + + return mount_verbose(LOG_ERR, "tmpfs", where, "tmpfs", MS_NODEV|MS_STRICTATIME, options); +} + +static char *joined_and_escaped_lower_dirs(char **lower) { + _cleanup_strv_free_ char **sv = NULL; + + sv = strv_copy(lower); + if (!sv) + return NULL; + + strv_reverse(sv); + + if (!strv_shell_escape(sv, ",:")) + return NULL; + + return strv_join(sv, ":"); +} + +static int mount_overlay(const char *dest, CustomMount *m) { + _cleanup_free_ char *lower = NULL, *where = NULL, *escaped_source = NULL; + const char *options; + int r; + + assert(dest); + assert(m); + + r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); + if (r < 0) + return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); + if (r == 0) { /* Doesn't exist yet? */ + r = mkdir_label(where, 0755); + if (r < 0) + return log_error_errno(r, "Creating mount point for overlay %s failed: %m", where); + } + + (void) mkdir_p_label(m->source, 0755); + + lower = joined_and_escaped_lower_dirs(m->lower); + if (!lower) + return log_oom(); + + escaped_source = shell_escape(m->source, ",:"); + if (!escaped_source) + return log_oom(); + + if (m->read_only) + options = strjoina("lowerdir=", escaped_source, ":", lower); + else { + _cleanup_free_ char *escaped_work_dir = NULL; + + escaped_work_dir = shell_escape(m->work_dir, ",:"); + if (!escaped_work_dir) + return log_oom(); + + options = strjoina("lowerdir=", lower, ",upperdir=", escaped_source, ",workdir=", escaped_work_dir); + } + + return mount_verbose(LOG_ERR, "overlay", where, "overlay", m->read_only ? MS_RDONLY : 0, options); +} + +static int mount_inaccessible(const char *dest, CustomMount *m) { + _cleanup_free_ char *where = NULL; + const char *source; + struct stat st; + int r; + + assert(dest); + assert(m); + + r = chase_symlinks_and_stat(m->destination, dest, CHASE_PREFIX_ROOT, &where, &st, NULL); + if (r < 0) { + log_full_errno(m->graceful ? LOG_DEBUG : LOG_ERR, r, "Failed to resolve %s/%s: %m", dest, m->destination); + return m->graceful ? 0 : r; + } + + assert_se(source = mode_to_inaccessible_node(st.st_mode)); + + r = mount_verbose(m->graceful ? LOG_DEBUG : LOG_ERR, source, where, NULL, MS_BIND, NULL); + if (r < 0) + return m->graceful ? 0 : r; + + r = mount_verbose(m->graceful ? LOG_DEBUG : LOG_ERR, NULL, where, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL); + if (r < 0) { + umount_verbose(where); + return m->graceful ? 0 : r; + } + + return 0; +} + +static int mount_arbitrary(const char *dest, CustomMount *m) { + _cleanup_free_ char *where = NULL; + int r; + + assert(dest); + assert(m); + + r = chase_symlinks(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); + if (r < 0) + return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, m->destination); + if (r == 0) { /* Doesn't exist yet? */ + r = mkdir_p_label(where, 0755); + if (r < 0) + return log_error_errno(r, "Creating mount point for mount %s failed: %m", where); + } + + return mount_verbose(LOG_ERR, m->source, where, m->type_argument, 0, m->options); +} + +int mount_custom( + const char *dest, + CustomMount *mounts, size_t n, + bool userns, uid_t uid_shift, uid_t uid_range, + const char *selinux_apifs_context, + bool in_userns) { + + size_t i; + int r; + + assert(dest); + + for (i = 0; i < n; i++) { + CustomMount *m = mounts + i; + + if (m->in_userns != in_userns) + continue; + + switch (m->type) { + + case CUSTOM_MOUNT_BIND: + r = mount_bind(dest, m); + break; + + case CUSTOM_MOUNT_TMPFS: + r = mount_tmpfs(dest, m, userns, uid_shift, uid_range, selinux_apifs_context); + break; + + case CUSTOM_MOUNT_OVERLAY: + r = mount_overlay(dest, m); + break; + + case CUSTOM_MOUNT_INACCESSIBLE: + r = mount_inaccessible(dest, m); + break; + + case CUSTOM_MOUNT_ARBITRARY: + r = mount_arbitrary(dest, m); + break; + + default: + assert_not_reached("Unknown custom mount type"); + } + + if (r < 0) + return r; + } + + return 0; +} + +static int setup_volatile_state( + const char *directory, + bool userns, uid_t uid_shift, uid_t uid_range, + const char *selinux_apifs_context) { + + _cleanup_free_ char *buf = NULL; + const char *p, *options; + int r; + + assert(directory); + + /* --volatile=state means we simply overmount /var with a tmpfs, and the rest read-only. */ + + r = bind_remount_recursive(directory, MS_RDONLY, MS_RDONLY, NULL); + if (r < 0) + return log_error_errno(r, "Failed to remount %s read-only: %m", directory); + + p = prefix_roota(directory, "/var"); + r = mkdir(p, 0755); + if (r < 0 && errno != EEXIST) + return log_error_errno(errno, "Failed to create %s: %m", directory); + + options = "mode=755"; + r = tmpfs_patch_options(options, uid_shift == 0 ? UID_INVALID : uid_shift, selinux_apifs_context, &buf); + if (r < 0) + return log_oom(); + if (r > 0) + options = buf; + + return mount_verbose(LOG_ERR, "tmpfs", p, "tmpfs", MS_STRICTATIME, options); +} + +static int setup_volatile_yes( + const char *directory, + bool userns, uid_t uid_shift, uid_t uid_range, + const char *selinux_apifs_context) { + + bool tmpfs_mounted = false, bind_mounted = false; + char template[] = "/tmp/nspawn-volatile-XXXXXX"; + _cleanup_free_ char *buf = NULL, *bindir = NULL; + const char *f, *t, *options; + struct stat st; + int r; + + assert(directory); + + /* --volatile=yes means we mount a tmpfs to the root dir, and the original /usr to use inside it, and + * that read-only. Before we start setting this up let's validate if the image has the /usr merge + * implemented, and let's output a friendly log message if it hasn't. */ + + bindir = path_join(directory, "/bin"); + if (!bindir) + return log_oom(); + if (lstat(bindir, &st) < 0) { + if (errno != ENOENT) + return log_error_errno(errno, "Failed to stat /bin directory below image: %m"); + + /* ENOENT is fine, just means the image is probably just a naked /usr and we can create the + * rest. */ + } else if (S_ISDIR(st.st_mode)) + return log_error_errno(SYNTHETIC_ERRNO(EISDIR), + "Sorry, --volatile=yes mode is not supported with OS images that have not merged /bin/, /sbin/, /lib/, /lib64/ into /usr/. " + "Please work with your distribution and help them adopt the merged /usr scheme."); + else if (!S_ISLNK(st.st_mode)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Error starting image: if --volatile=yes is used /bin must be a symlink (for merged /usr support) or non-existent (in which case a symlink is created automatically)."); + + if (!mkdtemp(template)) + return log_error_errno(errno, "Failed to create temporary directory: %m"); + + options = "mode=755"; + r = tmpfs_patch_options(options, uid_shift == 0 ? UID_INVALID : uid_shift, selinux_apifs_context, &buf); + if (r < 0) + goto fail; + if (r > 0) + options = buf; + + r = mount_verbose(LOG_ERR, "tmpfs", template, "tmpfs", MS_STRICTATIME, options); + if (r < 0) + goto fail; + + tmpfs_mounted = true; + + f = prefix_roota(directory, "/usr"); + t = prefix_roota(template, "/usr"); + + r = mkdir(t, 0755); + if (r < 0 && errno != EEXIST) { + r = log_error_errno(errno, "Failed to create %s: %m", t); + goto fail; + } + + r = mount_verbose(LOG_ERR, f, t, NULL, MS_BIND|MS_REC, NULL); + if (r < 0) + goto fail; + + bind_mounted = true; + + r = bind_remount_recursive(t, MS_RDONLY, MS_RDONLY, NULL); + if (r < 0) { + log_error_errno(r, "Failed to remount %s read-only: %m", t); + goto fail; + } + + r = mount_verbose(LOG_ERR, template, directory, NULL, MS_MOVE, NULL); + if (r < 0) + goto fail; + + (void) rmdir(template); + + return 0; + +fail: + if (bind_mounted) + (void) umount_verbose(t); + + if (tmpfs_mounted) + (void) umount_verbose(template); + (void) rmdir(template); + return r; +} + +static int setup_volatile_overlay( + const char *directory, + bool userns, uid_t uid_shift, uid_t uid_range, + const char *selinux_apifs_context) { + + _cleanup_free_ char *buf = NULL, *escaped_directory = NULL, *escaped_upper = NULL, *escaped_work = NULL; + char template[] = "/tmp/nspawn-volatile-XXXXXX"; + const char *upper, *work, *options; + bool tmpfs_mounted = false; + int r; + + assert(directory); + + /* --volatile=overlay means we mount an overlayfs to the root dir. */ + + if (!mkdtemp(template)) + return log_error_errno(errno, "Failed to create temporary directory: %m"); + + options = "mode=755"; + r = tmpfs_patch_options(options, uid_shift == 0 ? UID_INVALID : uid_shift, selinux_apifs_context, &buf); + if (r < 0) + goto finish; + if (r > 0) + options = buf; + + r = mount_verbose(LOG_ERR, "tmpfs", template, "tmpfs", MS_STRICTATIME, options); + if (r < 0) + goto finish; + + tmpfs_mounted = true; + + upper = strjoina(template, "/upper"); + work = strjoina(template, "/work"); + + if (mkdir(upper, 0755) < 0) { + r = log_error_errno(errno, "Failed to create %s: %m", upper); + goto finish; + } + if (mkdir(work, 0755) < 0) { + r = log_error_errno(errno, "Failed to create %s: %m", work); + goto finish; + } + + /* And now, let's overmount the root dir with an overlayfs that uses the root dir as lower dir. It's kinda nice + * that the kernel allows us to do that without going through some mount point rearrangements. */ + + escaped_directory = shell_escape(directory, ",:"); + escaped_upper = shell_escape(upper, ",:"); + escaped_work = shell_escape(work, ",:"); + if (!escaped_directory || !escaped_upper || !escaped_work) { + r = -ENOMEM; + goto finish; + } + + options = strjoina("lowerdir=", escaped_directory, ",upperdir=", escaped_upper, ",workdir=", escaped_work); + r = mount_verbose(LOG_ERR, "overlay", directory, "overlay", 0, options); + +finish: + if (tmpfs_mounted) + (void) umount_verbose(template); + + (void) rmdir(template); + return r; +} + +int setup_volatile_mode( + const char *directory, + VolatileMode mode, + bool userns, uid_t uid_shift, uid_t uid_range, + const char *selinux_apifs_context) { + + switch (mode) { + + case VOLATILE_YES: + return setup_volatile_yes(directory, userns, uid_shift, uid_range, selinux_apifs_context); + + case VOLATILE_STATE: + return setup_volatile_state(directory, userns, uid_shift, uid_range, selinux_apifs_context); + + case VOLATILE_OVERLAY: + return setup_volatile_overlay(directory, userns, uid_shift, uid_range, selinux_apifs_context); + + default: + return 0; + } +} + +/* Expects *pivot_root_new and *pivot_root_old to be initialised to allocated memory or NULL. */ +int pivot_root_parse(char **pivot_root_new, char **pivot_root_old, const char *s) { + _cleanup_free_ char *root_new = NULL, *root_old = NULL; + const char *p = s; + int r; + + assert(pivot_root_new); + assert(pivot_root_old); + + r = extract_first_word(&p, &root_new, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + if (isempty(p)) + root_old = NULL; + else { + root_old = strdup(p); + if (!root_old) + return -ENOMEM; + } + + if (!path_is_absolute(root_new)) + return -EINVAL; + if (root_old && !path_is_absolute(root_old)) + return -EINVAL; + + free_and_replace(*pivot_root_new, root_new); + free_and_replace(*pivot_root_old, root_old); + + return 0; +} + +int setup_pivot_root(const char *directory, const char *pivot_root_new, const char *pivot_root_old) { + _cleanup_free_ char *directory_pivot_root_new = NULL; + _cleanup_free_ char *pivot_tmp_pivot_root_old = NULL; + char pivot_tmp[] = "/tmp/nspawn-pivot-XXXXXX"; + bool remove_pivot_tmp = false; + int r; + + assert(directory); + + if (!pivot_root_new) + return 0; + + /* Pivot pivot_root_new to / and the existing / to pivot_root_old. + * If pivot_root_old is NULL, the existing / disappears. + * This requires a temporary directory, pivot_tmp, which is + * not a child of either. + * + * This is typically used for OSTree-style containers, where + * the root partition contains several sysroots which could be + * run. Normally, one would be chosen by the bootloader and + * pivoted to / by initramfs. + * + * For example, for an OSTree deployment, pivot_root_new + * would be: /ostree/deploy/$os/deploy/$checksum. Note that this + * code doesn’t do the /var mount which OSTree expects: use + * --bind +/sysroot/ostree/deploy/$os/var:/var for that. + * + * So in the OSTree case, we’ll end up with something like: + * - directory = /tmp/nspawn-root-123456 + * - pivot_root_new = /ostree/deploy/os/deploy/123abc + * - pivot_root_old = /sysroot + * - directory_pivot_root_new = + * /tmp/nspawn-root-123456/ostree/deploy/os/deploy/123abc + * - pivot_tmp = /tmp/nspawn-pivot-123456 + * - pivot_tmp_pivot_root_old = /tmp/nspawn-pivot-123456/sysroot + * + * Requires all file systems at directory and below to be mounted + * MS_PRIVATE or MS_SLAVE so they can be moved. + */ + directory_pivot_root_new = path_join(directory, pivot_root_new); + if (!directory_pivot_root_new) + return log_oom(); + + /* Remount directory_pivot_root_new to make it movable. */ + r = mount_verbose(LOG_ERR, directory_pivot_root_new, directory_pivot_root_new, NULL, MS_BIND, NULL); + if (r < 0) + goto done; + + if (pivot_root_old) { + if (!mkdtemp(pivot_tmp)) { + r = log_error_errno(errno, "Failed to create temporary directory: %m"); + goto done; + } + + remove_pivot_tmp = true; + pivot_tmp_pivot_root_old = path_join(pivot_tmp, pivot_root_old); + if (!pivot_tmp_pivot_root_old) { + r = log_oom(); + goto done; + } + + r = mount_verbose(LOG_ERR, directory_pivot_root_new, pivot_tmp, NULL, MS_MOVE, NULL); + if (r < 0) + goto done; + + r = mount_verbose(LOG_ERR, directory, pivot_tmp_pivot_root_old, NULL, MS_MOVE, NULL); + if (r < 0) + goto done; + + r = mount_verbose(LOG_ERR, pivot_tmp, directory, NULL, MS_MOVE, NULL); + if (r < 0) + goto done; + } else { + r = mount_verbose(LOG_ERR, directory_pivot_root_new, directory, NULL, MS_MOVE, NULL); + if (r < 0) + goto done; + } + +done: + if (remove_pivot_tmp) + (void) rmdir(pivot_tmp); + + return r; +} diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h new file mode 100644 index 00000000..ff6990c7 --- /dev/null +++ b/src/nspawn/nspawn-mount.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "cgroup-util.h" +#include "volatile-util.h" + +typedef enum MountSettingsMask { + MOUNT_FATAL = 1 << 0, /* if set, a mount error is considered fatal */ + MOUNT_USE_USERNS = 1 << 1, /* if set, mounts are patched considering uid/gid shifts in a user namespace */ + MOUNT_IN_USERNS = 1 << 2, /* if set, the mount is executed in the inner child, otherwise in the outer child */ + MOUNT_APPLY_APIVFS_RO = 1 << 3, /* if set, /proc/sys, and /sys will be mounted read-only, otherwise read-write. */ + MOUNT_APPLY_APIVFS_NETNS = 1 << 4, /* if set, /proc/sys/net will be mounted read-write. + Works only if MOUNT_APPLY_APIVFS_RO is also set. */ + MOUNT_APPLY_TMPFS_TMP = 1 << 5, /* if set, /tmp will be mounted as tmpfs */ +} MountSettingsMask; + +typedef enum CustomMountType { + CUSTOM_MOUNT_BIND, + CUSTOM_MOUNT_TMPFS, + CUSTOM_MOUNT_OVERLAY, + CUSTOM_MOUNT_INACCESSIBLE, + CUSTOM_MOUNT_ARBITRARY, + _CUSTOM_MOUNT_TYPE_MAX, + _CUSTOM_MOUNT_TYPE_INVALID = -1 +} CustomMountType; + +typedef struct CustomMount { + CustomMountType type; + bool read_only; + char *source; /* for overlayfs this is the upper directory */ + char *destination; + char *options; + char *work_dir; + char **lower; + char *rm_rf_tmpdir; + char *type_argument; /* only for CUSTOM_MOUNT_ARBITRARY */ + bool graceful; + bool in_userns; +} CustomMount; + +CustomMount* custom_mount_add(CustomMount **l, size_t *n, CustomMountType t); +void custom_mount_free_all(CustomMount *l, size_t n); +int custom_mount_prepare_all(const char *dest, CustomMount *l, size_t n); + +int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only); +int tmpfs_mount_parse(CustomMount **l, size_t *n, const char *s); +int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only); +int inaccessible_mount_parse(CustomMount **l, size_t *n, const char *s); + +int mount_all(const char *dest, MountSettingsMask mount_settings, uid_t uid_shift, const char *selinux_apifs_context); +int mount_sysfs(const char *dest, MountSettingsMask mount_settings); + +int mount_custom(const char *dest, CustomMount *mounts, size_t n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool in_userns); + +int setup_volatile_mode(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context); + +int pivot_root_parse(char **pivot_root_new, char **pivot_root_old, const char *s); +int setup_pivot_root(const char *directory, const char *pivot_root_new, const char *pivot_root_old); + +int tmpfs_patch_options(const char *options,uid_t uid_shift, const char *selinux_apifs_context, char **ret); diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c new file mode 100644 index 00000000..fa1ec05b --- /dev/null +++ b/src/nspawn/nspawn-network.c @@ -0,0 +1,671 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-device.h" +#include "sd-id128.h" +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "ether-addr-util.h" +#include "lockfile-util.h" +#include "missing_network.h" +#include "netlink-util.h" +#include "nspawn-network.h" +#include "parse-util.h" +#include "siphash24.h" +#include "socket-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "udev-util.h" +#include "util.h" + +#define HOST_HASH_KEY SD_ID128_MAKE(1a,37,6f,c7,46,ec,45,0b,ad,a3,d5,31,06,60,5d,b1) +#define CONTAINER_HASH_KEY SD_ID128_MAKE(c3,c4,f9,19,b5,57,b2,1c,e6,cf,14,27,03,9c,ee,a2) +#define VETH_EXTRA_HOST_HASH_KEY SD_ID128_MAKE(48,c7,f6,b7,ea,9d,4c,9e,b7,28,d4,de,91,d5,bf,66) +#define VETH_EXTRA_CONTAINER_HASH_KEY SD_ID128_MAKE(af,50,17,61,ce,f9,4d,35,84,0d,2b,20,54,be,ce,59) +#define MACVLAN_HASH_KEY SD_ID128_MAKE(00,13,6d,bc,66,83,44,81,bb,0c,f9,51,1f,24,a6,6f) + +static int remove_one_link(sd_netlink *rtnl, const char *name) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + if (isempty(name)) + return 0; + + r = sd_rtnl_message_new_link(rtnl, &m, RTM_DELLINK, 0); + if (r < 0) + return log_error_errno(r, "Failed to allocate netlink message: %m"); + + r = sd_netlink_message_append_string(m, IFLA_IFNAME, name); + if (r < 0) + return log_error_errno(r, "Failed to add netlink interface name: %m"); + + r = sd_netlink_call(rtnl, m, 0, NULL); + if (r == -ENODEV) /* Already gone */ + return 0; + if (r < 0) + return log_error_errno(r, "Failed to remove interface %s: %m", name); + + return 1; +} + +static int generate_mac( + const char *machine_name, + struct ether_addr *mac, + sd_id128_t hash_key, + uint64_t idx) { + + uint64_t result; + size_t l, sz; + uint8_t *v, *i; + int r; + + l = strlen(machine_name); + sz = sizeof(sd_id128_t) + l; + if (idx > 0) + sz += sizeof(idx); + + v = newa(uint8_t, sz); + + /* fetch some persistent data unique to the host */ + r = sd_id128_get_machine((sd_id128_t*) v); + if (r < 0) + return r; + + /* combine with some data unique (on this host) to this + * container instance */ + i = mempcpy(v + sizeof(sd_id128_t), machine_name, l); + if (idx > 0) { + idx = htole64(idx); + memcpy(i, &idx, sizeof(idx)); + } + + /* Let's hash the host machine ID plus the container name. We + * use a fixed, but originally randomly created hash key here. */ + result = htole64(siphash24(v, sz, hash_key.bytes)); + + assert_cc(ETH_ALEN <= sizeof(result)); + memcpy(mac->ether_addr_octet, &result, ETH_ALEN); + + /* see eth_random_addr in the kernel */ + mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */ + mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */ + + return 0; +} + +static int add_veth( + sd_netlink *rtnl, + pid_t pid, + const char *ifname_host, + const struct ether_addr *mac_host, + const char *ifname_container, + const struct ether_addr *mac_container) { + + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + assert(rtnl); + assert(ifname_host); + assert(mac_host); + assert(ifname_container); + assert(mac_container); + + r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0); + if (r < 0) + return log_error_errno(r, "Failed to allocate netlink message: %m"); + + r = sd_netlink_message_append_string(m, IFLA_IFNAME, ifname_host); + if (r < 0) + return log_error_errno(r, "Failed to add netlink interface name: %m"); + + r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, mac_host); + if (r < 0) + return log_error_errno(r, "Failed to add netlink MAC address: %m"); + + r = sd_netlink_message_open_container(m, IFLA_LINKINFO); + if (r < 0) + return log_error_errno(r, "Failed to open netlink container: %m"); + + r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "veth"); + if (r < 0) + return log_error_errno(r, "Failed to open netlink container: %m"); + + r = sd_netlink_message_open_container(m, VETH_INFO_PEER); + if (r < 0) + return log_error_errno(r, "Failed to open netlink container: %m"); + + r = sd_netlink_message_append_string(m, IFLA_IFNAME, ifname_container); + if (r < 0) + return log_error_errno(r, "Failed to add netlink interface name: %m"); + + r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, mac_container); + if (r < 0) + return log_error_errno(r, "Failed to add netlink MAC address: %m"); + + r = sd_netlink_message_append_u32(m, IFLA_NET_NS_PID, pid); + if (r < 0) + return log_error_errno(r, "Failed to add netlink namespace field: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_error_errno(r, "Failed to close netlink container: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_error_errno(r, "Failed to close netlink container: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_error_errno(r, "Failed to close netlink container: %m"); + + r = sd_netlink_call(rtnl, m, 0, NULL); + if (r < 0) + return log_error_errno(r, "Failed to add new veth interfaces (%s:%s): %m", ifname_host, ifname_container); + + return 0; +} + +int setup_veth(const char *machine_name, + pid_t pid, + char iface_name[IFNAMSIZ], + bool bridge) { + + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + struct ether_addr mac_host, mac_container; + int r, i; + + assert(machine_name); + assert(pid > 0); + assert(iface_name); + + /* Use two different interface name prefixes depending whether + * we are in bridge mode or not. */ + snprintf(iface_name, IFNAMSIZ - 1, "%s-%s", + bridge ? "vb" : "ve", machine_name); + + r = generate_mac(machine_name, &mac_container, CONTAINER_HASH_KEY, 0); + if (r < 0) + return log_error_errno(r, "Failed to generate predictable MAC address for container side: %m"); + + r = generate_mac(machine_name, &mac_host, HOST_HASH_KEY, 0); + if (r < 0) + return log_error_errno(r, "Failed to generate predictable MAC address for host side: %m"); + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + r = add_veth(rtnl, pid, iface_name, &mac_host, "host0", &mac_container); + if (r < 0) + return r; + + r = parse_ifindex_or_ifname(iface_name, &i); + if (r < 0) + return log_error_errno(r, "Failed to resolve interface %s: %m", iface_name); + + return i; +} + +int setup_veth_extra( + const char *machine_name, + pid_t pid, + char **pairs) { + + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + uint64_t idx = 0; + char **a, **b; + int r; + + assert(machine_name); + assert(pid > 0); + + if (strv_isempty(pairs)) + return 0; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + STRV_FOREACH_PAIR(a, b, pairs) { + struct ether_addr mac_host, mac_container; + + r = generate_mac(machine_name, &mac_container, VETH_EXTRA_CONTAINER_HASH_KEY, idx); + if (r < 0) + return log_error_errno(r, "Failed to generate predictable MAC address for container side of extra veth link: %m"); + + r = generate_mac(machine_name, &mac_host, VETH_EXTRA_HOST_HASH_KEY, idx); + if (r < 0) + return log_error_errno(r, "Failed to generate predictable MAC address for container side of extra veth link: %m"); + + r = add_veth(rtnl, pid, *a, &mac_host, *b, &mac_container); + if (r < 0) + return r; + + idx++; + } + + return 0; +} + +static int join_bridge(sd_netlink *rtnl, const char *veth_name, const char *bridge_name) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r, bridge_ifi; + + assert(rtnl); + assert(veth_name); + assert(bridge_name); + + r = parse_ifindex_or_ifname(bridge_name, &bridge_ifi); + if (r < 0) + return r; + + r = sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, 0); + if (r < 0) + return r; + + r = sd_rtnl_message_link_set_flags(m, IFF_UP, IFF_UP); + if (r < 0) + return r; + + r = sd_netlink_message_append_string(m, IFLA_IFNAME, veth_name); + if (r < 0) + return r; + + r = sd_netlink_message_append_u32(m, IFLA_MASTER, bridge_ifi); + if (r < 0) + return r; + + r = sd_netlink_call(rtnl, m, 0, NULL); + if (r < 0) + return r; + + return bridge_ifi; +} + +static int create_bridge(sd_netlink *rtnl, const char *bridge_name) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int r; + + r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0); + if (r < 0) + return r; + + r = sd_netlink_message_append_string(m, IFLA_IFNAME, bridge_name); + if (r < 0) + return r; + + r = sd_netlink_message_open_container(m, IFLA_LINKINFO); + if (r < 0) + return r; + + r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "bridge"); + if (r < 0) + return r; + + r = sd_netlink_message_close_container(m); + if (r < 0) + return r; + + r = sd_netlink_message_close_container(m); + if (r < 0) + return r; + + r = sd_netlink_call(rtnl, m, 0, NULL); + if (r < 0) + return r; + + return 0; +} + +int setup_bridge(const char *veth_name, const char *bridge_name, bool create) { + _cleanup_(release_lock_file) LockFile bridge_lock = LOCK_FILE_INIT; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + int r, bridge_ifi; + unsigned n = 0; + + assert(veth_name); + assert(bridge_name); + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + if (create) { + /* We take a system-wide lock here, so that we can safely check whether there's still a member in the + * bridge before removing it, without risking interference from other nspawn instances. */ + + r = make_lock_file("/run/systemd/nspawn-network-zone", LOCK_EX, &bridge_lock); + if (r < 0) + return log_error_errno(r, "Failed to take network zone lock: %m"); + } + + for (;;) { + bridge_ifi = join_bridge(rtnl, veth_name, bridge_name); + if (bridge_ifi >= 0) + return bridge_ifi; + if (bridge_ifi != -ENODEV || !create || n > 10) + return log_error_errno(bridge_ifi, "Failed to add interface %s to bridge %s: %m", veth_name, bridge_name); + + /* Count attempts, so that we don't enter an endless loop here. */ + n++; + + /* The bridge doesn't exist yet. Let's create it */ + r = create_bridge(rtnl, bridge_name); + if (r < 0) + return log_error_errno(r, "Failed to create bridge interface %s: %m", bridge_name); + + /* Try again, now that the bridge exists */ + } +} + +int remove_bridge(const char *bridge_name) { + _cleanup_(release_lock_file) LockFile bridge_lock = LOCK_FILE_INIT; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + const char *path; + int r; + + /* Removes the specified bridge, but only if it is currently empty */ + + if (isempty(bridge_name)) + return 0; + + r = make_lock_file("/run/systemd/nspawn-network-zone", LOCK_EX, &bridge_lock); + if (r < 0) + return log_error_errno(r, "Failed to take network zone lock: %m"); + + path = strjoina("/sys/class/net/", bridge_name, "/brif"); + + r = dir_is_empty(path); + if (r == -ENOENT) /* Already gone? */ + return 0; + if (r < 0) + return log_error_errno(r, "Can't detect if bridge %s is empty: %m", bridge_name); + if (r == 0) /* Still populated, leave it around */ + return 0; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + return remove_one_link(rtnl, bridge_name); +} + +static int parse_interface(const char *name) { + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + int ifi, r; + + r = parse_ifindex_or_ifname(name, &ifi); + if (r < 0) + return log_error_errno(r, "Failed to resolve interface %s: %m", name); + + if (path_is_read_only_fs("/sys") <= 0) { + char ifi_str[2 + DECIMAL_STR_MAX(int)]; + + /* udev should be around. */ + + sprintf(ifi_str, "n%i", ifi); + r = sd_device_new_from_device_id(&d, ifi_str); + if (r < 0) + return log_error_errno(r, "Failed to get device %s: %m", name); + + r = sd_device_get_is_initialized(d); + if (r < 0) + return log_error_errno(r, "Failed to determine whether interface %s is initialized: %m", name); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Network interface %s is not initialized yet.", name); + + r = device_is_renaming(d); + if (r < 0) + return log_error_errno(r, "Failed to determine the interface %s is being renamed: %m", name); + if (r > 0) + return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Interface %s is being renamed.", name); + } + + return ifi; +} + +int move_network_interfaces(pid_t pid, char **ifaces) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + char **i; + int r; + + if (strv_isempty(ifaces)) + return 0; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + STRV_FOREACH(i, ifaces) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + int ifi; + + ifi = parse_interface(*i); + if (ifi < 0) + return ifi; + + r = sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, ifi); + if (r < 0) + return log_error_errno(r, "Failed to allocate netlink message: %m"); + + r = sd_netlink_message_append_u32(m, IFLA_NET_NS_PID, pid); + if (r < 0) + return log_error_errno(r, "Failed to append namespace PID to netlink message: %m"); + + r = sd_netlink_call(rtnl, m, 0, NULL); + if (r < 0) + return log_error_errno(r, "Failed to move interface %s to namespace: %m", *i); + } + + return 0; +} + +int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + unsigned idx = 0; + char **i; + int r; + + if (strv_isempty(ifaces)) + return 0; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + STRV_FOREACH(i, ifaces) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + _cleanup_free_ char *n = NULL; + struct ether_addr mac; + int ifi; + + ifi = parse_interface(*i); + if (ifi < 0) + return ifi; + + r = generate_mac(machine_name, &mac, MACVLAN_HASH_KEY, idx++); + if (r < 0) + return log_error_errno(r, "Failed to create MACVLAN MAC address: %m"); + + r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0); + if (r < 0) + return log_error_errno(r, "Failed to allocate netlink message: %m"); + + r = sd_netlink_message_append_u32(m, IFLA_LINK, ifi); + if (r < 0) + return log_error_errno(r, "Failed to add netlink interface index: %m"); + + n = strjoin("mv-", *i); + if (!n) + return log_oom(); + + strshorten(n, IFNAMSIZ-1); + + r = sd_netlink_message_append_string(m, IFLA_IFNAME, n); + if (r < 0) + return log_error_errno(r, "Failed to add netlink interface name: %m"); + + r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, &mac); + if (r < 0) + return log_error_errno(r, "Failed to add netlink MAC address: %m"); + + r = sd_netlink_message_append_u32(m, IFLA_NET_NS_PID, pid); + if (r < 0) + return log_error_errno(r, "Failed to add netlink namespace field: %m"); + + r = sd_netlink_message_open_container(m, IFLA_LINKINFO); + if (r < 0) + return log_error_errno(r, "Failed to open netlink container: %m"); + + r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "macvlan"); + if (r < 0) + return log_error_errno(r, "Failed to open netlink container: %m"); + + r = sd_netlink_message_append_u32(m, IFLA_MACVLAN_MODE, MACVLAN_MODE_BRIDGE); + if (r < 0) + return log_error_errno(r, "Failed to append macvlan mode: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_error_errno(r, "Failed to close netlink container: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_error_errno(r, "Failed to close netlink container: %m"); + + r = sd_netlink_call(rtnl, m, 0, NULL); + if (r < 0) + return log_error_errno(r, "Failed to add new macvlan interfaces: %m"); + } + + return 0; +} + +int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + char **i; + int r; + + if (strv_isempty(ifaces)) + return 0; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + STRV_FOREACH(i, ifaces) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; + _cleanup_free_ char *n = NULL; + int ifi; + + ifi = parse_interface(*i); + if (ifi < 0) + return ifi; + + r = sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0); + if (r < 0) + return log_error_errno(r, "Failed to allocate netlink message: %m"); + + r = sd_netlink_message_append_u32(m, IFLA_LINK, ifi); + if (r < 0) + return log_error_errno(r, "Failed to add netlink interface index: %m"); + + n = strjoin("iv-", *i); + if (!n) + return log_oom(); + + strshorten(n, IFNAMSIZ-1); + + r = sd_netlink_message_append_string(m, IFLA_IFNAME, n); + if (r < 0) + return log_error_errno(r, "Failed to add netlink interface name: %m"); + + r = sd_netlink_message_append_u32(m, IFLA_NET_NS_PID, pid); + if (r < 0) + return log_error_errno(r, "Failed to add netlink namespace field: %m"); + + r = sd_netlink_message_open_container(m, IFLA_LINKINFO); + if (r < 0) + return log_error_errno(r, "Failed to open netlink container: %m"); + + r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "ipvlan"); + if (r < 0) + return log_error_errno(r, "Failed to open netlink container: %m"); + + r = sd_netlink_message_append_u16(m, IFLA_IPVLAN_MODE, IPVLAN_MODE_L2); + if (r < 0) + return log_error_errno(r, "Failed to add ipvlan mode: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_error_errno(r, "Failed to close netlink container: %m"); + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_error_errno(r, "Failed to close netlink container: %m"); + + r = sd_netlink_call(rtnl, m, 0, NULL); + if (r < 0) + return log_error_errno(r, "Failed to add new ipvlan interfaces: %m"); + } + + return 0; +} + +int veth_extra_parse(char ***l, const char *p) { + _cleanup_free_ char *a = NULL, *b = NULL; + int r; + + r = extract_first_word(&p, &a, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + if (r == 0 || !ifname_valid(a)) + return -EINVAL; + + r = extract_first_word(&p, &b, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return r; + if (r == 0 || !ifname_valid(b)) { + free(b); + b = strdup(a); + if (!b) + return -ENOMEM; + } + + if (p) + return -EINVAL; + + r = strv_push_pair(l, a, b); + if (r < 0) + return -ENOMEM; + + a = b = NULL; + return 0; +} + +int remove_veth_links(const char *primary, char **pairs) { + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + char **a, **b; + int r; + + /* In some cases the kernel might pin the veth links between host and container even after the namespace + * died. Hence, let's better remove them explicitly too. */ + + if (isempty(primary) && strv_isempty(pairs)) + return 0; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + remove_one_link(rtnl, primary); + + STRV_FOREACH_PAIR(a, b, pairs) + remove_one_link(rtnl, *a); + + return 0; +} diff --git a/src/nspawn/nspawn-network.h b/src/nspawn/nspawn-network.h new file mode 100644 index 00000000..32ea21cc --- /dev/null +++ b/src/nspawn/nspawn-network.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +int setup_veth(const char *machine_name, pid_t pid, char iface_name[IFNAMSIZ], bool bridge); +int setup_veth_extra(const char *machine_name, pid_t pid, char **pairs); + +int setup_bridge(const char *veth_name, const char *bridge_name, bool create); +int remove_bridge(const char *bridge_name); + +int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces); +int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces); + +int move_network_interfaces(pid_t pid, char **ifaces); + +int veth_extra_parse(char ***l, const char *p); + +int remove_veth_links(const char *primary, char **pairs); diff --git a/src/nspawn/nspawn-oci.c b/src/nspawn/nspawn-oci.c new file mode 100644 index 00000000..4519c74b --- /dev/null +++ b/src/nspawn/nspawn-oci.c @@ -0,0 +1,2266 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#if HAVE_SECCOMP +#include +#endif + +#include "bus-util.h" +#include "cap-list.h" +#include "cpu-set-util.h" +#include "env-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "json.h" +#include "missing_sched.h" +#include "nspawn-oci.h" +#include "path-util.h" +#include "rlimit-util.h" +#if HAVE_SECCOMP +#include "seccomp-util.h" +#endif +#include "stat-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" + +/* TODO: + * OCI runtime tool implementation + * hooks + * + * Spec issues: + * + * How is RLIM_INFINITY supposed to be encoded? + * configured effective caps is bullshit, as execv() corrupts it anyway + * pipes bind mounted is *very* different from pipes newly created, comments regarding bind mount or not are bogus + * annotation values structured? or string? + * configurable file system namespace path, but then also root path? wtf? + * apply sysctl inside of the container? or outside? + * how is unlimited pids tasks limit to be encoded? + * what are the defaults for caps if not specified? + * what are the default uid/gid mappings if one is missing but the other set, or when user ns is on but no namespace configured + * the source field of "mounts" is really weird, as it cannot realistically be relative to the bundle, since we never know if that's what the fs wants + * spec contradicts itself on the mount "type" field, as the example uses "bind" as type, but it's not listed in /proc/filesystem, and is something made up by /bin/mount + * if type of mount is left out, what shall be assumed? "bind"? + * readonly mounts is entirely redundant? + * should escaping be applied when joining mount options with ","? + * devices cgroup support is bogus, "allow" and "deny" on the kernel level is about adding/removing entries, not about access + * spec needs to say that "rwm" devices cgroup combination can't be the empty string + * cgrouspv1 crap: kernel, kernelTCP, swapiness, disableOOMKiller, swap, devices, leafWeight + * general: it shouldn't leak lower level abstractions this obviously + * unmanagable cgroups stuff: realtimeRuntime/realtimePeriod + * needs to say what happense when some option is not specified, i.e. which defautls apply + * no architecture? no personality? + * seccomp example and logic is simply broken: there's no constant "SCMP_ACT_ERRNO". + * spec should say what to do with unknown props + * /bin/mount regarding NFS and FUSE required? + * what does terminal=false mean? + * sysctl inside or outside? whitelisting? + * swapiness typo -> swappiness + * + * Unsupported: + * + * apparmorProfile + * selinuxLabel + mountLabel + * hugepageLimits + * network + * rdma + * intelRdt + * swappiness, disableOOMKiller, kernel, kernelTCP, leafWeight (because it's dead, cgroupsv2 can't do it and hence systemd neither) + * + * Non-slice cgroup paths + * Propagation that is not slave + shared + * more than one uid/gid mapping, mappings with a container base != 0, or non-matching uid/gid mappings + * device cgroups access = false items that are not catchall + * device cgroups matches where minor is specified, but major isn't. similar where major is specified but char/block is not. also, any match that only has a type set that has less than "rwm" set. also, any entry that has none of rwm set. + * + */ + +static int oci_unexpected(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Unexpected OCI element '%s' of type '%s'.", name, json_variant_type_to_string(json_variant_type(v))); +} + +static int oci_unsupported(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP), + "Unsupported OCI element '%s' of type '%s'.", name, json_variant_type_to_string(json_variant_type(v))); +} + +static int oci_terminal(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + + /* If not specified, or set to true, we'll default to either an interactive or a read-only + * console. If specified as false, we'll forcibly move to "pipe" mode though. */ + s->console_mode = json_variant_boolean(v) ? _CONSOLE_MODE_INVALID : CONSOLE_PIPE; + return 0; +} + +static int oci_console_dimension(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { + unsigned *u = userdata; + uintmax_t k; + + assert(u); + + k = json_variant_unsigned(variant); + if (k == 0) + return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), + "Console size field '%s' is too small.", strna(name)); + if (k > USHRT_MAX) /* TIOCSWINSZ's struct winsize uses "unsigned short" for width and height */ + return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), + "Console size field '%s' is too large.", strna(name)); + + *u = (unsigned) k; + return 0; +} + +static int oci_console_size(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + static const JsonDispatch table[] = { + { "height", JSON_VARIANT_UNSIGNED, oci_console_dimension, offsetof(Settings, console_height), JSON_MANDATORY }, + { "width", JSON_VARIANT_UNSIGNED, oci_console_dimension, offsetof(Settings, console_width), JSON_MANDATORY }, + {} + }; + + return json_dispatch(v, table, oci_unexpected, flags, userdata); +} + +static int oci_absolute_path(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + char **p = userdata; + const char *n; + + assert(p); + + n = json_variant_string(v); + + if (!path_is_absolute(n)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Path in JSON field '%s' is not absolute: %s", strna(name), n); + + return free_and_strdup_warn(p, n); +} + +static int oci_env(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + char ***l = userdata; + JsonVariant *e; + int r; + + assert(l); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + const char *n; + + if (!json_variant_is_string(e)) + return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), + "Environment array contains non-string."); + + assert_se(n = json_variant_string(e)); + + if (!env_assignment_is_valid(n)) + return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), + "Environment assignment not valid: %s", n); + + r = strv_extend(l, n); + if (r < 0) + return log_oom(); + } + + return 0; +} + +static int oci_args(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + _cleanup_strv_free_ char **l = NULL; + char ***value = userdata; + JsonVariant *e; + int r; + + assert(value); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + const char *n; + + if (!json_variant_is_string(e)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Argument is not a string."); + + assert_se(n = json_variant_string(e)); + + r = strv_extend(&l, n); + if (r < 0) + return log_oom(); + } + + if (strv_isempty(l)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Argument list empty, refusing."); + + if (isempty(l[0])) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Executable name is empty, refusing."); + + return strv_free_and_replace(*value, l); +} + +static int oci_rlimit_type(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + const char *z; + int t, *type = userdata; + + assert_se(type); + + z = startswith(json_variant_string(v), "RLIMIT_"); + if (!z) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "rlimit entry's name does not begin with 'RLIMIT_', refusing: %s", + json_variant_string(v)); + + t = rlimit_from_string(z); + if (t < 0) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "rlimit name unknown: %s", json_variant_string(v)); + + *type = t; + return 0; +} + +static int oci_rlimit_value(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + rlim_t z, *value = userdata; + + assert(value); + + if (json_variant_is_negative(v)) + z = RLIM_INFINITY; + else { + if (!json_variant_is_unsigned(v)) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "rlimits limit not unsigned, refusing."); + + z = (rlim_t) json_variant_unsigned(v); + + if ((uintmax_t) z != json_variant_unsigned(v)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "rlimits limit out of range, refusing."); + } + + *value = z; + return 0; +} + +static int oci_rlimits(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + Settings *s = userdata; + JsonVariant *e; + int r; + + assert(s); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + + struct rlimit_data { + int type; + rlim_t soft; + rlim_t hard; + } data = { + .type = -1, + .soft = RLIM_INFINITY, + .hard = RLIM_INFINITY, + }; + + static const JsonDispatch table[] = { + { "soft", JSON_VARIANT_NUMBER, oci_rlimit_value, offsetof(struct rlimit_data, soft), JSON_MANDATORY }, + { "hard", JSON_VARIANT_NUMBER, oci_rlimit_value, offsetof(struct rlimit_data, hard), JSON_MANDATORY }, + { "type", JSON_VARIANT_STRING, oci_rlimit_type, offsetof(struct rlimit_data, type), JSON_MANDATORY }, + {} + }; + + r = json_dispatch(e, table, oci_unexpected, flags, &data); + if (r < 0) + return r; + + assert(data.type >= 0); + assert(data.type < _RLIMIT_MAX); + + if (s->rlimit[data.type]) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "rlimits array contains duplicate entry, refusing."); + + s->rlimit[data.type] = new(struct rlimit, 1); + if (!s->rlimit[data.type]) + return log_oom(); + + *s->rlimit[data.type] = (struct rlimit) { + .rlim_cur = data.soft, + .rlim_max = data.hard, + }; + + } + return 0; +} + +static int oci_capability_array(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + uint64_t *mask = userdata, m = 0; + JsonVariant *e; + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + const char *n; + int cap; + + if (!json_variant_is_string(e)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Entry in capabilities array is not a string."); + + assert_se(n = json_variant_string(e)); + + cap = capability_from_name(n); + if (cap < 0) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Unknown capability: %s", n); + + m |= UINT64_C(1) << cap; + } + + if (*mask == (uint64_t) -1) + *mask = m; + else + *mask |= m; + + return 0; +} + +static int oci_capabilities(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + static const JsonDispatch table[] = { + { "effective", JSON_VARIANT_ARRAY, oci_capability_array, offsetof(CapabilityQuintet, effective) }, + { "bounding", JSON_VARIANT_ARRAY, oci_capability_array, offsetof(CapabilityQuintet, bounding) }, + { "inheritable", JSON_VARIANT_ARRAY, oci_capability_array, offsetof(CapabilityQuintet, inheritable) }, + { "permitted", JSON_VARIANT_ARRAY, oci_capability_array, offsetof(CapabilityQuintet, permitted) }, + { "ambient", JSON_VARIANT_ARRAY, oci_capability_array, offsetof(CapabilityQuintet, ambient) }, + {} + }; + + Settings *s = userdata; + int r; + + assert(s); + + r = json_dispatch(v, table, oci_unexpected, flags, &s->full_capabilities); + if (r < 0) + return r; + + if (s->full_capabilities.bounding != (uint64_t) -1) { + s->capability = s->full_capabilities.bounding; + s->drop_capability = ~s->full_capabilities.bounding; + } + + return 0; +} + +static int oci_oom_score_adj(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + intmax_t k; + + assert(s); + + k = json_variant_integer(v); + if (k < OOM_SCORE_ADJ_MIN || k > OOM_SCORE_ADJ_MAX) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "oomScoreAdj value out of range: %ji", k); + + s->oom_score_adjust = (int) k; + s->oom_score_adjust_set = true; + + return 0; +} + +static int oci_uid_gid(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + uid_t *uid = userdata, u; + uintmax_t k; + + assert(uid); + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + + k = json_variant_unsigned(v); + u = (uid_t) k; + if ((uintmax_t) u != k) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "UID/GID out of range: %ji", k); + + if (!uid_is_valid(u)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "UID/GID is not valid: " UID_FMT, u); + + *uid = u; + return 0; +} + +static int oci_supplementary_gids(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + JsonVariant *e; + int r; + + assert(s); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + gid_t gid, *a; + + if (!json_variant_is_unsigned(e)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Supplementary GID entry is not a UID."); + + r = oci_uid_gid(name, e, flags, &gid); + if (r < 0) + return r; + + a = reallocarray(s->supplementary_gids, s->n_supplementary_gids + 1, sizeof(gid_t)); + if (!a) + return log_oom(); + + s->supplementary_gids = a; + s->supplementary_gids[s->n_supplementary_gids++] = gid; + } + + return 0; +} + +static int oci_user(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + static const JsonDispatch table[] = { + { "uid", JSON_VARIANT_UNSIGNED, oci_uid_gid, offsetof(Settings, uid), JSON_MANDATORY }, + { "gid", JSON_VARIANT_UNSIGNED, oci_uid_gid, offsetof(Settings, gid), JSON_MANDATORY }, + { "additionalGids", JSON_VARIANT_ARRAY, oci_supplementary_gids, 0, 0 }, + {} + }; + + return json_dispatch(v, table, oci_unexpected, flags, userdata); +} + +static int oci_process(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + static const JsonDispatch table[] = { + { "terminal", JSON_VARIANT_BOOLEAN, oci_terminal, 0, 0 }, + { "consoleSize", JSON_VARIANT_OBJECT, oci_console_size, 0, 0 }, + { "cwd", JSON_VARIANT_STRING, oci_absolute_path, offsetof(Settings, working_directory), 0 }, + { "env", JSON_VARIANT_ARRAY, oci_env, offsetof(Settings, environment), 0 }, + { "args", JSON_VARIANT_ARRAY, oci_args, offsetof(Settings, parameters), 0 }, + { "rlimits", JSON_VARIANT_ARRAY, oci_rlimits, 0, 0 }, + { "apparmorProfile", JSON_VARIANT_STRING, oci_unsupported, 0, JSON_PERMISSIVE }, + { "capabilities", JSON_VARIANT_OBJECT, oci_capabilities, 0, 0 }, + { "noNewPrivileges", JSON_VARIANT_BOOLEAN, json_dispatch_boolean, offsetof(Settings, no_new_privileges), 0 }, + { "oomScoreAdj", JSON_VARIANT_INTEGER, oci_oom_score_adj, 0, 0 }, + { "selinuxLabel", JSON_VARIANT_STRING, oci_unsupported, 0, JSON_PERMISSIVE }, + { "user", JSON_VARIANT_OBJECT, oci_user, 0, 0 }, + {} + }; + + return json_dispatch(v, table, oci_unexpected, flags, userdata); +} + +static int oci_root(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + static const JsonDispatch table[] = { + { "path", JSON_VARIANT_STRING, json_dispatch_string, offsetof(Settings, root) }, + { "readonly", JSON_VARIANT_BOOLEAN, json_dispatch_boolean, offsetof(Settings, read_only) }, + {} + }; + + return json_dispatch(v, table, oci_unexpected, flags, userdata); +} + +static int oci_hostname(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + const char *n; + + assert(s); + + assert_se(n = json_variant_string(v)); + + if (!hostname_is_valid(n, false)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Hostname string is not a valid hostname: %s", n); + + return free_and_strdup_warn(&s->hostname, n); +} + +static bool oci_exclude_mount(const char *path) { + + /* Returns "true" for all mounts we insist to mount on our own, and hence ignore the OCI data. */ + + if (PATH_IN_SET(path, + "/dev", + "/dev/mqueue", + "/dev/pts", + "/dev/shm", + "/proc", + "/proc/acpi", + "/proc/apm", + "/proc/asound", + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/kallsyms", + "/proc/kcore", + "/proc/keys", + "/proc/scsi", + "/proc/sys", + "/proc/sys/net", + "/proc/sysrq-trigger", + "/proc/timer_list", + "/run", + "/sys", + "/sys", + "/sys/fs/selinux", + "/tmp")) + return true; + + /* Similar, skip the whole /sys/fs/cgroups subtree */ + if (path_startswith(path, "/sys/fs/cgroup")) + return true; + + return false; +} + +typedef struct oci_mount_data { + char *destination; + char *source; + char *type; + char **options; +} oci_mount_data; + +static void cleanup_oci_mount_data(oci_mount_data *data) { + free(data->destination); + free(data->source); + strv_free(data->options); + free(data->type); +} + +static int oci_mounts(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + JsonVariant *e; + int r; + + assert(s); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + static const JsonDispatch table[] = { + { "destination", JSON_VARIANT_STRING, oci_absolute_path, offsetof(oci_mount_data, destination), JSON_MANDATORY }, + { "source", JSON_VARIANT_STRING, json_dispatch_string, offsetof(oci_mount_data, source), 0 }, + { "options", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(oci_mount_data, options), 0, }, + { "type", JSON_VARIANT_STRING, json_dispatch_string, offsetof(oci_mount_data, type), 0 }, + {} + }; + + _cleanup_free_ char *joined_options = NULL; + CustomMount *m; + _cleanup_(cleanup_oci_mount_data) oci_mount_data data = {}; + + r = json_dispatch(e, table, oci_unexpected, flags, &data); + if (r < 0) + return r; + + if (!path_is_absolute(data.destination)) + return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), + "Mount destination not an absolute path: %s", data.destination); + + if (oci_exclude_mount(data.destination)) + continue; + + if (data.options) { + joined_options = strv_join(data.options, ","); + if (!joined_options) + return log_oom(); + } + + if (!data.type || streq(data.type, "bind")) { + if (data.source && !path_is_absolute(data.source)) { + char *joined; + + joined = path_join(s->bundle, data.source); + if (!joined) + return log_oom(); + + free_and_replace(data.source, joined); + } + + data.type = mfree(data.type); + + m = custom_mount_add(&s->custom_mounts, &s->n_custom_mounts, CUSTOM_MOUNT_BIND); + } else + m = custom_mount_add(&s->custom_mounts, &s->n_custom_mounts, CUSTOM_MOUNT_ARBITRARY); + if (!m) + return log_oom(); + + m->destination = TAKE_PTR(data.destination); + m->source = TAKE_PTR(data.source); + m->options = TAKE_PTR(joined_options); + m->type_argument = TAKE_PTR(data.type); + } + + return 0; +} + +static int oci_namespace_type(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + unsigned long *nsflags = userdata; + const char *n; + + assert(nsflags); + assert_se(n = json_variant_string(v)); + + /* We don't use namespace_flags_from_string() here, as the OCI spec uses slightly different names than the + * kernel here. */ + if (streq(n, "pid")) + *nsflags = CLONE_NEWPID; + else if (streq(n, "network")) + *nsflags = CLONE_NEWNET; + else if (streq(n, "mount")) + *nsflags = CLONE_NEWNS; + else if (streq(n, "ipc")) + *nsflags = CLONE_NEWIPC; + else if (streq(n, "uts")) + *nsflags = CLONE_NEWUTS; + else if (streq(n, "user")) + *nsflags = CLONE_NEWUSER; + else if (streq(n, "cgroup")) + *nsflags = CLONE_NEWCGROUP; + else + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Unknown cgroup type, refusing: %s", n); + + return 0; +} + +static int oci_namespaces(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + unsigned long n = 0; + JsonVariant *e; + int r; + + assert_se(s); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + + struct namespace_data { + unsigned long type; + char *path; + } data = {}; + + static const JsonDispatch table[] = { + { "type", JSON_VARIANT_STRING, oci_namespace_type, offsetof(struct namespace_data, type), JSON_MANDATORY }, + { "path", JSON_VARIANT_STRING, oci_absolute_path, offsetof(struct namespace_data, path), 0 }, + {} + }; + + r = json_dispatch(e, table, oci_unexpected, flags, &data); + if (r < 0) { + free(data.path); + return r; + } + + if (data.path) { + if (data.type != CLONE_NEWNET) { + free(data.path); + return json_log(e, flags, SYNTHETIC_ERRNO(EOPNOTSUPP), + "Specifying namespace path for non-network namespace is not supported."); + } + + if (s->network_namespace_path) { + free(data.path); + return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), + "Network namespace path specified more than once, refusing."); + } + + free(s->network_namespace_path); + s->network_namespace_path = data.path; + } + + if (FLAGS_SET(n, data.type)) { + return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), + "Duplicate namespace specification, refusing."); + } + + n |= data.type; + } + + if (!FLAGS_SET(n, CLONE_NEWNS)) + return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP), + "Containers without file system namespace aren't supported."); + + s->private_network = FLAGS_SET(n, CLONE_NEWNET); + s->userns_mode = FLAGS_SET(n, CLONE_NEWUSER) ? USER_NAMESPACE_FIXED : USER_NAMESPACE_NO; + s->use_cgns = FLAGS_SET(n, CLONE_NEWCGROUP); + + s->clone_ns_flags = n & (CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS); + + return 0; +} + +static int oci_uid_gid_range(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + uid_t *uid = userdata, u; + uintmax_t k; + + assert(uid); + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + + /* This is very much like oci_uid_gid(), except the checks are a bit different, as this is a UID range rather + * than a specific UID, and hence (uid_t) -1 has no special significance. OTOH a range of zero makes no + * sense. */ + + k = json_variant_unsigned(v); + u = (uid_t) k; + if ((uintmax_t) u != k) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "UID/GID out of range: %ji", k); + if (u == 0) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "UID/GID range can't be zero."); + + *uid = u; + return 0; +} + +static int oci_uid_gid_mappings(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + struct mapping_data { + uid_t host_id; + uid_t container_id; + uid_t range; + } data = { + .host_id = UID_INVALID, + .container_id = UID_INVALID, + .range = 0, + }; + + static const JsonDispatch table[] = { + { "containerID", JSON_VARIANT_UNSIGNED, oci_uid_gid, offsetof(struct mapping_data, container_id), JSON_MANDATORY }, + { "hostID", JSON_VARIANT_UNSIGNED, oci_uid_gid, offsetof(struct mapping_data, host_id), JSON_MANDATORY }, + { "size", JSON_VARIANT_UNSIGNED, oci_uid_gid_range, offsetof(struct mapping_data, range), JSON_MANDATORY }, + {} + }; + + Settings *s = userdata; + JsonVariant *e; + int r; + + assert(s); + + if (json_variant_elements(v) == 0) + return 0; + + if (json_variant_elements(v) > 1) + return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP), + "UID/GID mappings with more than one entry are not supported."); + + assert_se(e = json_variant_by_index(v, 0)); + + r = json_dispatch(e, table, oci_unexpected, flags, &data); + if (r < 0) + return r; + + if (data.host_id + data.range < data.host_id || + data.container_id + data.range < data.container_id) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "UID/GID range goes beyond UID/GID validity range, refusing."); + + if (data.container_id != 0) + return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP), + "UID/GID mappings with a non-zero container base are not supported."); + + if (data.range < 0x10000) + json_log(v, flags|JSON_WARNING, 0, + "UID/GID mapping with less than 65536 UID/GIDS set up, you are looking for trouble."); + + if (s->uid_range != UID_INVALID && + (s->uid_shift != data.host_id || s->uid_range != data.range)) + return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP), + "Non-matching UID and GID mappings are not supported."); + + s->uid_shift = data.host_id; + s->uid_range = data.range; + + return 0; +} + +static int oci_device_type(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + mode_t *mode = userdata; + const char *t; + + assert(mode); + assert_se(t = json_variant_string(v)); + + if (STR_IN_SET(t, "c", "u")) + *mode = (*mode & ~S_IFMT) | S_IFCHR; + else if (streq(t, "b")) + *mode = (*mode & ~S_IFMT) | S_IFBLK; + else if (streq(t, "p")) + *mode = (*mode & ~S_IFMT) | S_IFIFO; + else + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Unknown device type: %s", t); + + return 0; +} + +static int oci_device_major(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + unsigned *u = userdata; + uintmax_t k; + + assert_se(u); + + k = json_variant_unsigned(v); + if (!DEVICE_MAJOR_VALID(k)) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "Device major %ji out of range.", k); + + *u = (unsigned) k; + return 0; +} + +static int oci_device_minor(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + unsigned *u = userdata; + uintmax_t k; + + assert_se(u); + + k = json_variant_unsigned(v); + if (!DEVICE_MINOR_VALID(k)) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "Device minor %ji out of range.", k); + + *u = (unsigned) k; + return 0; +} + +static int oci_device_file_mode(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + mode_t *mode = userdata, m; + uintmax_t k; + + assert(mode); + + k = json_variant_unsigned(v); + m = (mode_t) k; + + if ((m & ~07777) != 0 || (uintmax_t) m != k) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "fileMode out of range, refusing."); + + *mode = m; + return 0; +} + +static int oci_devices(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + JsonVariant *e; + int r; + + assert(s); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + + static const JsonDispatch table[] = { + { "type", JSON_VARIANT_STRING, oci_device_type, offsetof(DeviceNode, mode), JSON_MANDATORY }, + { "path", JSON_VARIANT_STRING, oci_absolute_path, offsetof(DeviceNode, path), JSON_MANDATORY }, + { "major", JSON_VARIANT_UNSIGNED, oci_device_major, offsetof(DeviceNode, major), 0 }, + { "minor", JSON_VARIANT_UNSIGNED, oci_device_minor, offsetof(DeviceNode, minor), 0 }, + { "fileMode", JSON_VARIANT_UNSIGNED, oci_device_file_mode, offsetof(DeviceNode, mode), 0 }, + { "uid", JSON_VARIANT_UNSIGNED, oci_uid_gid, offsetof(DeviceNode, uid), 0 }, + { "gid", JSON_VARIANT_UNSIGNED, oci_uid_gid, offsetof(DeviceNode, gid), 0 }, + {} + }; + + DeviceNode *node, *nodes; + + nodes = reallocarray(s->extra_nodes, s->n_extra_nodes + 1, sizeof(DeviceNode)); + if (!nodes) + return log_oom(); + + s->extra_nodes = nodes; + + node = nodes + s->n_extra_nodes; + *node = (DeviceNode) { + .uid = UID_INVALID, + .gid = GID_INVALID, + .major = (unsigned) -1, + .minor = (unsigned) -1, + .mode = 0644, + }; + + r = json_dispatch(e, table, oci_unexpected, flags, node); + if (r < 0) + goto fail_element; + + if (S_ISCHR(node->mode) || S_ISBLK(node->mode)) { + _cleanup_free_ char *path = NULL; + + if (node->major == (unsigned) -1 || node->minor == (unsigned) -1) { + r = json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), + "Major/minor required when device node is device node"); + goto fail_element; + } + + /* Suppress a couple of implicit device nodes */ + r = device_path_make_canonical(node->mode, makedev(node->major, node->minor), &path); + if (r < 0) + json_log(e, flags|JSON_DEBUG, 0, "Failed to resolve device node %u:%u, ignoring: %m", node->major, node->minor); + else { + if (PATH_IN_SET(path, + "/dev/null", + "/dev/zero", + "/dev/full", + "/dev/random", + "/dev/urandom", + "/dev/tty", + "/dev/net/tun", + "/dev/ptmx", + "/dev/pts/ptmx", + "/dev/console")) { + + json_log(e, flags|JSON_DEBUG, 0, "Ignoring devices item for device '%s', as it is implicitly created anyway.", path); + free(node->path); + continue; + } + } + } + + s->n_extra_nodes++; + continue; + + fail_element: + free(node->path); + return r; + } + + return 0; +} + +static int oci_cgroups_path(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + _cleanup_free_ char *slice = NULL, *backwards = NULL; + Settings *s = userdata; + const char *p; + int r; + + assert(s); + + assert_se(p = json_variant_string(v)); + + r = cg_path_get_slice(p, &slice); + if (r < 0) + return json_log(v, flags, r, "Couldn't derive slice unit name from path '%s': %m", p); + + r = cg_slice_to_path(slice, &backwards); + if (r < 0) + return json_log(v, flags, r, "Couldn't convert slice unit name '%s' back to path: %m", slice); + + if (!path_equal(backwards, p)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Control group path '%s' does not refer to slice unit, refusing.", p); + + free_and_replace(s->slice, slice); + return 0; +} + +static int oci_cgroup_device_type(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + mode_t *mode = userdata; + const char *n; + + assert_se(n = json_variant_string(v)); + + if (streq(n, "c")) + *mode = S_IFCHR; + else if (streq(n, "b")) + *mode = S_IFBLK; + else + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Control group device type unknown: %s", n); + + return 0; +} + +struct device_data { + bool allow; + bool r; + bool w; + bool m; + mode_t type; + unsigned major; + unsigned minor; +}; + +static int oci_cgroup_device_access(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + struct device_data *d = userdata; + bool r = false, w = false, m = false; + const char *s; + size_t i; + + assert_se(s = json_variant_string(v)); + + for (i = 0; s[i]; i++) + if (s[i] == 'r') + r = true; + else if (s[i] == 'w') + w = true; + else if (s[i] == 'm') + m = true; + else + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Unknown device access character '%c'.", s[i]); + + d->r = r; + d->w = w; + d->m = m; + + return 0; +} + +static int oci_cgroup_devices(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + _cleanup_free_ struct device_data *list = NULL; + Settings *s = userdata; + size_t n_list = 0, i; + bool noop = false; + JsonVariant *e; + int r; + + assert(s); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + + struct device_data data = { + .major = (unsigned) -1, + .minor = (unsigned) -1, + }, *a; + + static const JsonDispatch table[] = { + { "allow", JSON_VARIANT_BOOLEAN, json_dispatch_boolean, offsetof(struct device_data, allow), JSON_MANDATORY }, + { "type", JSON_VARIANT_STRING, oci_cgroup_device_type, offsetof(struct device_data, type), 0 }, + { "major", JSON_VARIANT_UNSIGNED, oci_device_major, offsetof(struct device_data, major), 0 }, + { "minor", JSON_VARIANT_UNSIGNED, oci_device_minor, offsetof(struct device_data, minor), 0 }, + { "access", JSON_VARIANT_STRING, oci_cgroup_device_access, 0, 0 }, + {} + }; + + r = json_dispatch(e, table, oci_unexpected, flags, &data); + if (r < 0) + return r; + + if (!data.allow) { + /* The fact that OCI allows 'deny' entries makes really no sense, as 'allow' vs. 'deny' for the + * devices cgroup controller is really not about whitelisting and blacklisting but about adding + * and removing entries from the whitelist. Since we always start out with an empty whitelist + * we hence ignore the whole thing, as removing entries which don't exist make no sense. We'll + * log about this, since this is really borked in the spec, with one exception: the entry + * that's supposed to drop the kernel's default we ignore silently */ + + if (!data.r || !data.w || !data.m || data.type != 0 || data.major != (unsigned) -1 || data.minor != (unsigned) -1) + json_log(v, flags|JSON_WARNING, 0, "Devices cgroup whitelist with arbitrary 'allow' entries not supported, ignoring."); + + /* We ignore the 'deny' entry as for us that's implied */ + continue; + } + + if (!data.r && !data.w && !data.m) { + json_log(v, flags|LOG_WARNING, 0, "Device cgroup whitelist entry with no effect found, ignoring."); + continue; + } + + if (data.minor != (unsigned) -1 && data.major == (unsigned) -1) + return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP), + "Device cgroup whitelist entries with minors but no majors not supported."); + + if (data.major != (unsigned) -1 && data.type == 0) + return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP), + "Device cgroup whitelist entries with majors but no device node type not supported."); + + if (data.type == 0) { + if (data.r && data.w && data.m) /* a catchall whitelist entry means we are looking at a noop */ + noop = true; + else + return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP), + "Device cgroup whitelist entries with no type not supported."); + } + + a = reallocarray(list, n_list + 1, sizeof(struct device_data)); + if (!a) + return log_oom(); + + list = a; + list[n_list++] = data; + } + + if (noop) + return 0; + + r = settings_allocate_properties(s); + if (r < 0) + return r; + + r = sd_bus_message_open_container(s->properties, 'r', "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(s->properties, "s", "DeviceAllow"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(s->properties, 'v', "a(ss)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(s->properties, 'a', "(ss)"); + if (r < 0) + return bus_log_create_error(r); + + for (i = 0; i < n_list; i++) { + _cleanup_free_ char *pattern = NULL; + char access[4]; + size_t n = 0; + + if (list[i].minor == (unsigned) -1) { + const char *t; + + if (list[i].type == S_IFBLK) + t = "block"; + else { + assert(list[i].type == S_IFCHR); + t = "char"; + } + + if (list[i].major == (unsigned) -1) { + pattern = strjoin(t, "-*"); + if (!pattern) + return log_oom(); + } else { + if (asprintf(&pattern, "%s-%u", t, list[i].major) < 0) + return log_oom(); + } + + } else { + assert(list[i].major != (unsigned) -1); /* If a minor is specified, then a major also needs to be specified */ + + r = device_path_make_major_minor(list[i].type, makedev(list[i].major, list[i].minor), &pattern); + if (r < 0) + return log_oom(); + } + + if (list[i].r) + access[n++] = 'r'; + if (list[i].w) + access[n++] = 'w'; + if (list[i].m) + access[n++] = 'm'; + access[n] = 0; + + assert(n > 0); + + r = sd_bus_message_append(s->properties, "(ss)", pattern, access); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(s->properties); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(s->properties); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(s->properties); + if (r < 0) + return bus_log_create_error(r); + + return 0; +} + +static int oci_cgroup_memory_limit(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + uint64_t *m = userdata; + uintmax_t k; + + assert(m); + + if (json_variant_is_negative(v)) { + *m = UINT64_MAX; + return 0; + } + + if (!json_variant_is_unsigned(v)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Memory limit is not an unsigned integer"); + + k = json_variant_unsigned(v); + if (k >= UINT64_MAX) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "Memory limit too large: %ji", k); + + *m = (uint64_t) k; + return 0; +} + +static int oci_cgroup_memory(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + struct memory_data { + uint64_t limit; + uint64_t reservation; + uint64_t swap; + } data = { + .limit = UINT64_MAX, + .reservation = UINT64_MAX, + .swap = UINT64_MAX, + }; + + static const JsonDispatch table[] = { + { "limit", JSON_VARIANT_NUMBER, oci_cgroup_memory_limit, offsetof(struct memory_data, limit), 0 }, + { "reservation", JSON_VARIANT_NUMBER, oci_cgroup_memory_limit, offsetof(struct memory_data, reservation), 0 }, + { "swap", JSON_VARIANT_NUMBER, oci_cgroup_memory_limit, offsetof(struct memory_data, swap), 0 }, + { "kernel", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE }, + { "kernelTCP", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE }, + { "swapiness", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE }, + { "disableOOMKiller", JSON_VARIANT_NUMBER, oci_unsupported, 0, JSON_PERMISSIVE }, + {} + }; + + Settings *s = userdata; + int r; + + r = json_dispatch(v, table, oci_unexpected, flags, &data); + if (r < 0) + return r; + + if (data.swap != UINT64_MAX) { + if (data.limit == UINT64_MAX) + json_log(v, flags|LOG_WARNING, 0, "swap limit without memory limit is not supported, ignoring."); + else if (data.swap < data.limit) + json_log(v, flags|LOG_WARNING, 0, "swap limit is below memory limit, ignoring."); + else { + r = settings_allocate_properties(s); + if (r < 0) + return r; + + r = sd_bus_message_append(s->properties, "(sv)", "MemorySwapMax", "t", data.swap - data.limit); + if (r < 0) + return bus_log_create_error(r); + } + } + + if (data.limit != UINT64_MAX) { + r = settings_allocate_properties(s); + if (r < 0) + return r; + + r = sd_bus_message_append(s->properties, "(sv)", "MemoryMax", "t", data.limit); + if (r < 0) + return bus_log_create_error(r); + } + + if (data.reservation != UINT64_MAX) { + r = settings_allocate_properties(s); + if (r < 0) + return r; + + r = sd_bus_message_append(s->properties, "(sv)", "MemoryLow", "t", data.reservation); + if (r < 0) + return bus_log_create_error(r); + } + + return 0; +} + +struct cpu_data { + uint64_t shares; + uint64_t quota; + uint64_t period; + CPUSet cpu_set; +}; + +static int oci_cgroup_cpu_shares(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + uint64_t *u = userdata; + uintmax_t k; + + assert(u); + + k = json_variant_unsigned(v); + if (k < CGROUP_CPU_SHARES_MIN || k > CGROUP_CPU_SHARES_MAX) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "shares value out of range."); + + *u = (uint64_t) k; + return 0; +} + +static int oci_cgroup_cpu_quota(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + uint64_t *u = userdata; + uintmax_t k; + + assert(u); + + k = json_variant_unsigned(v); + if (k <= 0 || k >= UINT64_MAX) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "period/quota value out of range."); + + *u = (uint64_t) k; + return 0; +} + +static int oci_cgroup_cpu_cpus(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + struct cpu_data *data = userdata; + CPUSet set; + const char *n; + int r; + + assert(data); + + assert_se(n = json_variant_string(v)); + + r = parse_cpu_set(n, &set); + if (r < 0) + return json_log(v, flags, r, "Failed to parse CPU set specification: %s", n); + + cpu_set_reset(&data->cpu_set); + data->cpu_set = set; + + return 0; +} + +static int oci_cgroup_cpu(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + static const JsonDispatch table[] = { + { "shares", JSON_VARIANT_UNSIGNED, oci_cgroup_cpu_shares, offsetof(struct cpu_data, shares), 0 }, + { "quota", JSON_VARIANT_UNSIGNED, oci_cgroup_cpu_quota, offsetof(struct cpu_data, quota), 0 }, + { "period", JSON_VARIANT_UNSIGNED, oci_cgroup_cpu_quota, offsetof(struct cpu_data, period), 0 }, + { "realtimeRuntime", JSON_VARIANT_UNSIGNED, oci_unsupported, 0, 0 }, + { "realtimePeriod", JSON_VARIANT_UNSIGNED, oci_unsupported, 0, 0 }, + { "cpus", JSON_VARIANT_STRING, oci_cgroup_cpu_cpus, 0, 0 }, + { "mems", JSON_VARIANT_STRING, oci_unsupported, 0, 0 }, + {} + }; + + struct cpu_data data = { + .shares = UINT64_MAX, + .quota = UINT64_MAX, + .period = UINT64_MAX, + }; + + Settings *s = userdata; + int r; + + r = json_dispatch(v, table, oci_unexpected, flags, &data); + if (r < 0) { + cpu_set_reset(&data.cpu_set); + return r; + } + + cpu_set_reset(&s->cpu_set); + s->cpu_set = data.cpu_set; + + if (data.shares != UINT64_MAX) { + r = settings_allocate_properties(s); + if (r < 0) + return r; + + r = sd_bus_message_append(s->properties, "(sv)", "CPUShares", "t", data.shares); + if (r < 0) + return bus_log_create_error(r); + } + + if (data.quota != UINT64_MAX && data.period != UINT64_MAX) { + r = settings_allocate_properties(s); + if (r < 0) + return r; + + r = sd_bus_message_append(s->properties, "(sv)", "CPUQuotaPerSecUSec", "t", (uint64_t) (data.quota * USEC_PER_SEC / data.period)); + if (r < 0) + return bus_log_create_error(r); + + } else if ((data.quota != UINT64_MAX) != (data.period != UINT64_MAX)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "CPU quota and period not used together."); + + return 0; +} + +static int oci_cgroup_block_io_weight(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + uintmax_t k; + int r; + + assert(s); + + k = json_variant_unsigned(v); + if (k < CGROUP_BLKIO_WEIGHT_MIN || k > CGROUP_BLKIO_WEIGHT_MAX) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "Block I/O weight out of range."); + + r = settings_allocate_properties(s); + if (r < 0) + return r; + + r = sd_bus_message_append(s->properties, "(sv)", "BlockIOWeight", "t", (uint64_t) k); + if (r < 0) + return bus_log_create_error(r); + + return 0; +} + +static int oci_cgroup_block_io_weight_device(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + JsonVariant *e; + int r; + + assert(s); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + struct device_data { + unsigned major; + unsigned minor; + uintmax_t weight; + } data = { + .major = (unsigned) -1, + .minor = (unsigned) -1, + .weight = UINTMAX_MAX, + }; + + static const JsonDispatch table[] = { + { "major", JSON_VARIANT_UNSIGNED, oci_device_major, offsetof(struct device_data, major), JSON_MANDATORY }, + { "minor", JSON_VARIANT_UNSIGNED, oci_device_minor, offsetof(struct device_data, minor), JSON_MANDATORY }, + { "weight", JSON_VARIANT_UNSIGNED, json_dispatch_unsigned, offsetof(struct device_data, weight), 0 }, + { "leafWeight", JSON_VARIANT_INTEGER, oci_unsupported, 0, JSON_PERMISSIVE }, + {} + }; + + _cleanup_free_ char *path = NULL; + + r = json_dispatch(e, table, oci_unexpected, flags, &data); + if (r < 0) + return r; + + if (data.weight == UINTMAX_MAX) + continue; + + if (data.weight < CGROUP_BLKIO_WEIGHT_MIN || data.weight > CGROUP_BLKIO_WEIGHT_MAX) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "Block I/O device weight out of range."); + + r = device_path_make_major_minor(S_IFBLK, makedev(data.major, data.minor), &path); + if (r < 0) + return json_log(v, flags, r, "Failed to build device path: %m"); + + r = settings_allocate_properties(s); + if (r < 0) + return r; + + r = sd_bus_message_append(s->properties, "(sv)", "BlockIODeviceWeight", "a(st)", 1, path, (uint64_t) data.weight); + if (r < 0) + return bus_log_create_error(r); + } + + return 0; +} + +static int oci_cgroup_block_io_throttle(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + const char *pname; + JsonVariant *e; + int r; + + assert(s); + + pname = streq(name, "throttleReadBpsDevice") ? "IOReadBandwidthMax" : + streq(name, "throttleWriteBpsDevice") ? "IOWriteBandwidthMax" : + streq(name, "throttleReadIOPSDevice") ? "IOReadIOPSMax" : + "IOWriteIOPSMax"; + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + struct device_data { + unsigned major; + unsigned minor; + uintmax_t rate; + } data = { + .major = (unsigned) -1, + .minor = (unsigned) -1, + }; + + static const JsonDispatch table[] = { + { "major", JSON_VARIANT_UNSIGNED, oci_device_major, offsetof(struct device_data, major), JSON_MANDATORY }, + { "minor", JSON_VARIANT_UNSIGNED, oci_device_minor, offsetof(struct device_data, minor), JSON_MANDATORY }, + { "rate", JSON_VARIANT_UNSIGNED, json_dispatch_unsigned, offsetof(struct device_data, rate), JSON_MANDATORY }, + {} + }; + + _cleanup_free_ char *path = NULL; + + r = json_dispatch(e, table, oci_unexpected, flags, &data); + if (r < 0) + return r; + + if (data.rate >= UINT64_MAX) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "Block I/O device rate out of range."); + + r = device_path_make_major_minor(S_IFBLK, makedev(data.major, data.minor), &path); + if (r < 0) + return json_log(v, flags, r, "Failed to build device path: %m"); + + r = settings_allocate_properties(s); + if (r < 0) + return r; + + r = sd_bus_message_append(s->properties, "(sv)", pname, "a(st)", 1, path, (uint64_t) data.rate); + if (r < 0) + return bus_log_create_error(r); + } + + return 0; +} + +static int oci_cgroup_block_io(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + static const JsonDispatch table[] = { + { "weight", JSON_VARIANT_UNSIGNED, oci_cgroup_block_io_weight, 0, 0 }, + { "leafWeight", JSON_VARIANT_UNSIGNED, oci_unsupported, 0, JSON_PERMISSIVE }, + { "weightDevice", JSON_VARIANT_ARRAY, oci_cgroup_block_io_weight_device, 0, 0 }, + { "throttleReadBpsDevice", JSON_VARIANT_ARRAY, oci_cgroup_block_io_throttle, 0, 0 }, + { "throttleWriteBpsDevice", JSON_VARIANT_ARRAY, oci_cgroup_block_io_throttle, 0, 0 }, + { "throttleReadIOPSDevice", JSON_VARIANT_ARRAY, oci_cgroup_block_io_throttle, 0, 0 }, + { "throttleWriteIOPSDevice", JSON_VARIANT_ARRAY, oci_cgroup_block_io_throttle, 0, 0 }, + {} + }; + + return json_dispatch(v, table, oci_unexpected, flags, userdata); +} + +static int oci_cgroup_pids(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + static const JsonDispatch table[] = { + { "limit", JSON_VARIANT_NUMBER, json_dispatch_variant, 0, JSON_MANDATORY }, + {} + }; + + _cleanup_(json_variant_unrefp) JsonVariant *k = NULL; + Settings *s = userdata; + uint64_t m; + int r; + + assert(s); + + r = json_dispatch(v, table, oci_unexpected, flags, &k); + if (r < 0) + return r; + + if (json_variant_is_negative(k)) + m = UINT64_MAX; + else { + if (!json_variant_is_unsigned(k)) + return json_log(k, flags, SYNTHETIC_ERRNO(EINVAL), + "pids limit not unsigned integer, refusing."); + + m = (uint64_t) json_variant_unsigned(k); + + if ((uintmax_t) m != json_variant_unsigned(k)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "pids limit out of range, refusing."); + } + + r = settings_allocate_properties(s); + if (r < 0) + return r; + + r = sd_bus_message_append(s->properties, "(sv)", "TasksMax", "t", m); + if (r < 0) + return bus_log_create_error(r); + + return 0; +} + +static int oci_resources(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + static const JsonDispatch table[] = { + { "devices", JSON_VARIANT_ARRAY, oci_cgroup_devices, 0, 0 }, + { "memory", JSON_VARIANT_OBJECT, oci_cgroup_memory, 0, 0 }, + { "cpu", JSON_VARIANT_OBJECT, oci_cgroup_cpu, 0, 0 }, + { "blockIO", JSON_VARIANT_OBJECT, oci_cgroup_block_io, 0, 0 }, + { "hugepageLimits", JSON_VARIANT_ARRAY, oci_unsupported, 0, 0 }, + { "network", JSON_VARIANT_OBJECT, oci_unsupported, 0, 0 }, + { "pids", JSON_VARIANT_OBJECT, oci_cgroup_pids, 0, 0 }, + { "rdma", JSON_VARIANT_OBJECT, oci_unsupported, 0, 0 }, + {} + }; + + return json_dispatch(v, table, oci_unexpected, flags, userdata); +} + +static bool sysctl_key_valid(const char *s) { + bool dot = true; + + /* Note that we are a bit stricter here than in systemd-sysctl, as that inherited semantics from the old sysctl + * tool, which were really weird (as it swaps / and . in both ways) */ + + if (isempty(s)) + return false; + + for (; *s; s++) { + + if (*s <= ' ' || *s >= 127) + return false; + if (*s == '/') + return false; + if (*s == '.') { + + if (dot) /* Don't allow two dots next to each other (or at the beginning) */ + return false; + + dot = true; + } else + dot = false; + } + + if (dot) /* don't allow a dot at the end */ + return false; + + return true; +} + +static int oci_sysctl(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + JsonVariant *w; + const char *k; + int r; + + assert(s); + + JSON_VARIANT_OBJECT_FOREACH(k, w, v) { + const char *m; + + if (!json_variant_is_string(w)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "sysctl parameter is not a string, refusing."); + + assert_se(m = json_variant_string(w)); + + if (sysctl_key_valid(k)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "sysctl key invalid, refusing: %s", k); + + r = strv_extend_strv(&s->sysctl, STRV_MAKE(k, m), false); + if (r < 0) + return log_oom(); + } + + return 0; +} + +#if HAVE_SECCOMP +static int oci_seccomp_action_from_string(const char *name, uint32_t *ret) { + + static const struct { + const char *name; + uint32_t action; + } table[] = { + { "SCMP_ACT_ALLOW", SCMP_ACT_ALLOW }, + { "SCMP_ACT_ERRNO", SCMP_ACT_ERRNO(EPERM) }, /* the OCI spec doesn't document the error, but it appears EPERM is supposed to be used */ + { "SCMP_ACT_KILL", SCMP_ACT_KILL }, +#ifdef SCMP_ACT_KILL_PROCESS + { "SCMP_ACT_KILL_PROCESS", SCMP_ACT_KILL_PROCESS }, +#endif +#ifdef SCMP_ACT_KILL_THREAD + { "SCMP_ACT_KILL_THREAD", SCMP_ACT_KILL_THREAD }, +#endif +#ifdef SCMP_ACT_LOG + { "SCMP_ACT_LOG", SCMP_ACT_LOG }, +#endif + { "SCMP_ACT_TRAP", SCMP_ACT_TRAP }, + + /* We don't support SCMP_ACT_TRACE because that requires a tracer, and that doesn't really make sense + * here */ + }; + + size_t i; + + for (i = 0; i < ELEMENTSOF(table); i++) + if (streq_ptr(name, table[i].name)) { + *ret = table[i].action; + return 0; + } + + return -EINVAL; +} + +static int oci_seccomp_arch_from_string(const char *name, uint32_t *ret) { + + static const struct { + const char *name; + uint32_t arch; + } table[] = { + { "SCMP_ARCH_AARCH64", SCMP_ARCH_AARCH64 }, + { "SCMP_ARCH_ARM", SCMP_ARCH_ARM }, + { "SCMP_ARCH_MIPS", SCMP_ARCH_MIPS }, + { "SCMP_ARCH_MIPS64", SCMP_ARCH_MIPS64 }, + { "SCMP_ARCH_MIPS64N32", SCMP_ARCH_MIPS64N32 }, + { "SCMP_ARCH_MIPSEL", SCMP_ARCH_MIPSEL }, + { "SCMP_ARCH_MIPSEL64", SCMP_ARCH_MIPSEL64 }, + { "SCMP_ARCH_MIPSEL64N32", SCMP_ARCH_MIPSEL64N32 }, + { "SCMP_ARCH_NATIVE", SCMP_ARCH_NATIVE }, +#ifdef SCMP_ARCH_PARISC + { "SCMP_ARCH_PARISC", SCMP_ARCH_PARISC }, +#endif +#ifdef SCMP_ARCH_PARISC64 + { "SCMP_ARCH_PARISC64", SCMP_ARCH_PARISC64 }, +#endif + { "SCMP_ARCH_PPC", SCMP_ARCH_PPC }, + { "SCMP_ARCH_PPC64", SCMP_ARCH_PPC64 }, + { "SCMP_ARCH_PPC64LE", SCMP_ARCH_PPC64LE }, + { "SCMP_ARCH_S390", SCMP_ARCH_S390 }, + { "SCMP_ARCH_S390X", SCMP_ARCH_S390X }, + { "SCMP_ARCH_X32", SCMP_ARCH_X32 }, + { "SCMP_ARCH_X86", SCMP_ARCH_X86 }, + { "SCMP_ARCH_X86_64", SCMP_ARCH_X86_64 }, + }; + + size_t i; + + for (i = 0; i < ELEMENTSOF(table); i++) + if (streq_ptr(table[i].name, name)) { + *ret = table[i].arch; + return 0; + } + + return -EINVAL; +} + +static int oci_seccomp_compare_from_string(const char *name, enum scmp_compare *ret) { + + static const struct { + const char *name; + enum scmp_compare op; + } table[] = { + { "SCMP_CMP_NE", SCMP_CMP_NE }, + { "SCMP_CMP_LT", SCMP_CMP_LT }, + { "SCMP_CMP_LE", SCMP_CMP_LE }, + { "SCMP_CMP_EQ", SCMP_CMP_EQ }, + { "SCMP_CMP_GE", SCMP_CMP_GE }, + { "SCMP_CMP_GT", SCMP_CMP_GT }, + { "SCMP_CMP_MASKED_EQ", SCMP_CMP_MASKED_EQ }, + }; + + size_t i; + + for (i = 0; i < ELEMENTSOF(table); i++) + if (streq_ptr(table[i].name, name)) { + *ret = table[i].op; + return 0; + } + + return -EINVAL; +} + +static int oci_seccomp_archs(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + scmp_filter_ctx *sc = userdata; + JsonVariant *e; + int r; + + assert(sc); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + uint32_t a; + + if (!json_variant_is_string(e)) + return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), + "Architecture entry is not a string"); + + r = oci_seccomp_arch_from_string(json_variant_string(e), &a); + if (r < 0) + return json_log(e, flags, r, "Unknown architecture: %s", json_variant_string(e)); + + r = seccomp_arch_add(sc, a); + if (r == -EEXIST) + continue; + if (r < 0) + return json_log(e, flags, r, "Failed to add architecture to seccomp filter: %m"); + } + + return 0; +} + +struct syscall_rule { + char **names; + uint32_t action; + struct scmp_arg_cmp *arguments; + size_t n_arguments; +}; + +static void syscall_rule_free(struct syscall_rule *rule) { + assert(rule); + + strv_free(rule->names); + free(rule->arguments); +}; + +static int oci_seccomp_action(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + uint32_t *action = userdata; + int r; + + assert(action); + + r = oci_seccomp_action_from_string(json_variant_string(v), action); + if (r < 0) + return json_log(v, flags, r, "Unknown system call action '%s': %m", json_variant_string(v)); + + return 0; +} + +static int oci_seccomp_op(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + enum scmp_compare *op = userdata; + int r; + + assert(op); + + r = oci_seccomp_compare_from_string(json_variant_string(v), op); + if (r < 0) + return json_log(v, flags, r, "Unknown seccomp operator '%s': %m", json_variant_string(v)); + + return 0; +} + +static int oci_seccomp_args(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + struct syscall_rule *rule = userdata; + JsonVariant *e; + int r; + + assert(rule); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + static const struct JsonDispatch table[] = { + { "index", JSON_VARIANT_UNSIGNED, json_dispatch_uint32, offsetof(struct scmp_arg_cmp, arg), JSON_MANDATORY }, + { "value", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(struct scmp_arg_cmp, datum_a), JSON_MANDATORY }, + { "valueTwo", JSON_VARIANT_UNSIGNED, json_dispatch_uint64, offsetof(struct scmp_arg_cmp, datum_b), 0 }, + { "op", JSON_VARIANT_STRING, oci_seccomp_op, offsetof(struct scmp_arg_cmp, op), JSON_MANDATORY }, + {}, + }; + + struct scmp_arg_cmp *a, *p; + int expected; + + a = reallocarray(rule->arguments, rule->n_arguments + 1, sizeof(struct syscall_rule)); + if (!a) + return log_oom(); + + rule->arguments = a; + p = rule->arguments + rule->n_arguments; + + *p = (struct scmp_arg_cmp) { + .arg = 0, + .datum_a = 0, + .datum_b = 0, + .op = 0, + }; + + r = json_dispatch(e, table, oci_unexpected, flags, p); + if (r < 0) + return r; + + expected = p->op == SCMP_CMP_MASKED_EQ ? 4 : 3; + if (r != expected) + json_log(e, flags|JSON_WARNING, 0, "Wrong number of system call arguments for JSON data data, ignoring."); + + /* Note that we are a bit sloppy here and do not insist that SCMP_CMP_MASKED_EQ gets two datum values, + * and the other only one. That's because buildah for example by default calls things with + * SCMP_CMP_MASKED_EQ but only one argument. We use 0 when the value is not specified. */ + + rule->n_arguments++; + } + + return 0; +} + +static int oci_seccomp_syscalls(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + scmp_filter_ctx *sc = userdata; + JsonVariant *e; + int r; + + assert(sc); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + static const JsonDispatch table[] = { + { "names", JSON_VARIANT_ARRAY, json_dispatch_strv, offsetof(struct syscall_rule, names), JSON_MANDATORY }, + { "action", JSON_VARIANT_STRING, oci_seccomp_action, offsetof(struct syscall_rule, action), JSON_MANDATORY }, + { "args", JSON_VARIANT_ARRAY, oci_seccomp_args, 0, 0 }, + }; + struct syscall_rule rule = { + .action = (uint32_t) -1, + }; + char **i; + + r = json_dispatch(e, table, oci_unexpected, flags, &rule); + if (r < 0) + goto fail_rule; + + if (strv_isempty(rule.names)) { + json_log(e, flags, 0, "System call name list is empty."); + r = -EINVAL; + goto fail_rule; + } + + STRV_FOREACH(i, rule.names) { + int nr; + + nr = seccomp_syscall_resolve_name(*i); + if (nr == __NR_SCMP_ERROR) { + log_debug("Unknown syscall %s, skipping.", *i); + continue; + } + + r = seccomp_rule_add_array(sc, rule.action, nr, rule.n_arguments, rule.arguments); + if (r < 0) + goto fail_rule; + } + + syscall_rule_free(&rule); + continue; + + fail_rule: + syscall_rule_free(&rule); + return r; + } + + return 0; +} +#endif + +static int oci_seccomp(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + +#if HAVE_SECCOMP + static const JsonDispatch table[] = { + { "defaultAction", JSON_VARIANT_STRING, NULL, 0, JSON_MANDATORY }, + { "architectures", JSON_VARIANT_ARRAY, oci_seccomp_archs, 0, 0 }, + { "syscalls", JSON_VARIANT_ARRAY, oci_seccomp_syscalls, 0, 0 }, + {} + }; + + _cleanup_(seccomp_releasep) scmp_filter_ctx sc = NULL; + Settings *s = userdata; + JsonVariant *def; + uint32_t d; + int r; + + assert(s); + + def = json_variant_by_key(v, "defaultAction"); + if (!def) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), "defaultAction element missing."); + + if (!json_variant_is_string(def)) + return json_log(def, flags, SYNTHETIC_ERRNO(EINVAL), "defaultAction is not a string."); + + r = oci_seccomp_action_from_string(json_variant_string(def), &d); + if (r < 0) + return json_log(def, flags, r, "Unknown default action: %s", json_variant_string(def)); + + sc = seccomp_init(d); + if (!sc) + return json_log(v, flags, SYNTHETIC_ERRNO(ENOMEM), "Couldn't allocate seccomp object."); + + r = json_dispatch(v, table, oci_unexpected, flags, sc); + if (r < 0) + return r; + + seccomp_release(s->seccomp); + s->seccomp = TAKE_PTR(sc); + return 0; +#else + return json_log(v, flags, SYNTHETIC_ERRNO(EOPNOTSUPP), "libseccomp support not enabled, can't parse seccomp object."); +#endif +} + +static int oci_rootfs_propagation(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + const char *s; + + s = json_variant_string(v); + + if (streq(s, "shared")) + return 0; + + json_log(v, flags|JSON_DEBUG, 0, "Ignoring rootfsPropagation setting '%s'.", s); + return 0; +} + +static int oci_masked_paths(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + JsonVariant *e; + + assert(s); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + _cleanup_free_ char *destination = NULL; + CustomMount *m; + const char *p; + + if (!json_variant_is_string(e)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Path is not a string, refusing."); + + assert_se(p = json_variant_string(e)); + + if (!path_is_absolute(p)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Path is not not absolute, refusing: %s", p); + + if (oci_exclude_mount(p)) + continue; + + destination = strdup(p); + if (!destination) + return log_oom(); + + m = custom_mount_add(&s->custom_mounts, &s->n_custom_mounts, CUSTOM_MOUNT_INACCESSIBLE); + if (!m) + return log_oom(); + + m->destination = TAKE_PTR(destination); + + /* The spec doesn't say this, but apparently pre-existing implementations are lenient towards + * non-existing paths to mask. Let's hence be too. */ + m->graceful = true; + } + + return 0; +} + +static int oci_readonly_paths(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + JsonVariant *e; + + assert(s); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + _cleanup_free_ char *source = NULL, *destination = NULL; + CustomMount *m; + const char *p; + + if (!json_variant_is_string(e)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Path is not a string, refusing."); + + assert_se(p = json_variant_string(e)); + + if (!path_is_absolute(p)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Path is not not absolute, refusing: %s", p); + + if (oci_exclude_mount(p)) + continue; + + source = strjoin("+", p); + if (!source) + return log_oom(); + + destination = strdup(p); + if (!destination) + return log_oom(); + + m = custom_mount_add(&s->custom_mounts, &s->n_custom_mounts, CUSTOM_MOUNT_BIND); + if (!m) + return log_oom(); + + m->source = TAKE_PTR(source); + m->destination = TAKE_PTR(destination); + m->read_only = true; + } + + return 0; +} + +static int oci_linux(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + static const JsonDispatch table[] = { + { "namespaces", JSON_VARIANT_ARRAY, oci_namespaces, 0, 0 }, + { "uidMappings", JSON_VARIANT_ARRAY, oci_uid_gid_mappings, 0, 0 }, + { "gidMappings", JSON_VARIANT_ARRAY, oci_uid_gid_mappings, 0, 0 }, + { "devices", JSON_VARIANT_ARRAY, oci_devices, 0, 0 }, + { "cgroupsPath", JSON_VARIANT_STRING, oci_cgroups_path, 0, 0 }, + { "resources", JSON_VARIANT_OBJECT, oci_resources, 0, 0 }, + { "intelRdt", JSON_VARIANT_OBJECT, oci_unsupported, 0, JSON_PERMISSIVE }, + { "sysctl", JSON_VARIANT_OBJECT, oci_sysctl, 0, 0 }, + { "seccomp", JSON_VARIANT_OBJECT, oci_seccomp, 0, 0 }, + { "rootfsPropagation", JSON_VARIANT_STRING, oci_rootfs_propagation, 0, 0 }, + { "maskedPaths", JSON_VARIANT_ARRAY, oci_masked_paths, 0, 0 }, + { "readonlyPaths", JSON_VARIANT_ARRAY, oci_readonly_paths, 0, 0 }, + { "mountLabel", JSON_VARIANT_STRING, oci_unsupported, 0, JSON_PERMISSIVE }, + {} + }; + + return json_dispatch(v, table, oci_unexpected, flags, userdata); +} + +static int oci_hook_timeout(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + usec_t *u = userdata; + uintmax_t k; + + k = json_variant_unsigned(v); + if (k == 0 || k > (UINT64_MAX-1)/USEC_PER_SEC) + return json_log(v, flags, SYNTHETIC_ERRNO(ERANGE), + "Hook timeout value out of range."); + + *u = k * USEC_PER_SEC; + return 0; +} + +static int oci_hooks_array(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + Settings *s = userdata; + JsonVariant *e; + int r; + + assert(s); + + JSON_VARIANT_ARRAY_FOREACH(e, v) { + + static const JsonDispatch table[] = { + { "path", JSON_VARIANT_STRING, oci_absolute_path, offsetof(OciHook, path), JSON_MANDATORY }, + { "args", JSON_VARIANT_ARRAY, oci_args, offsetof(OciHook, args), 0 }, + { "env", JSON_VARIANT_ARRAY, oci_env, offsetof(OciHook, env), 0 }, + { "timeout", JSON_VARIANT_UNSIGNED, oci_hook_timeout, offsetof(OciHook, timeout), 0 }, + {} + }; + + OciHook *a, **array, *new_item; + size_t *n_array; + + if (streq(name, "prestart")) { + array = &s->oci_hooks_prestart; + n_array = &s->n_oci_hooks_prestart; + } else if (streq(name, "poststart")) { + array = &s->oci_hooks_poststart; + n_array = &s->n_oci_hooks_poststart; + } else { + assert(streq(name, "poststop")); + array = &s->oci_hooks_poststop; + n_array = &s->n_oci_hooks_poststop; + } + + a = reallocarray(*array, *n_array + 1, sizeof(OciHook)); + if (!a) + return log_oom(); + + *array = a; + new_item = a + *n_array; + + *new_item = (OciHook) { + .timeout = USEC_INFINITY, + }; + + r = json_dispatch(e, table, oci_unexpected, flags, userdata); + if (r < 0) { + free(new_item->path); + strv_free(new_item->args); + strv_free(new_item->env); + return r; + } + + (*n_array) ++; + } + + return 0; +} + +static int oci_hooks(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + + static const JsonDispatch table[] = { + { "prestart", JSON_VARIANT_OBJECT, oci_hooks_array, 0, 0 }, + { "poststart", JSON_VARIANT_OBJECT, oci_hooks_array, 0, 0 }, + { "poststop", JSON_VARIANT_OBJECT, oci_hooks_array, 0, 0 }, + {} + }; + + return json_dispatch(v, table, oci_unexpected, flags, userdata); +} + +static int oci_annotations(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) { + JsonVariant *w; + const char *k; + + JSON_VARIANT_OBJECT_FOREACH(k, w, v) { + + if (isempty(k)) + return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL), + "Annotation with empty key, refusing."); + + if (!json_variant_is_string(w)) + return json_log(w, flags, SYNTHETIC_ERRNO(EINVAL), + "Annotation has non-string value, refusing."); + + json_log(w, flags|JSON_DEBUG, 0, "Ignoring annotation '%s' with value '%s'.", k, json_variant_string(w)); + } + + return 0; +} + +int oci_load(FILE *f, const char *bundle, Settings **ret) { + + static const JsonDispatch table[] = { + { "ociVersion", JSON_VARIANT_STRING, NULL, 0, JSON_MANDATORY }, + { "process", JSON_VARIANT_OBJECT, oci_process, 0, 0 }, + { "root", JSON_VARIANT_OBJECT, oci_root, 0, 0 }, + { "hostname", JSON_VARIANT_STRING, oci_hostname, 0, 0 }, + { "mounts", JSON_VARIANT_ARRAY, oci_mounts, 0, 0 }, + { "linux", JSON_VARIANT_OBJECT, oci_linux, 0, 0 }, + { "hooks", JSON_VARIANT_OBJECT, oci_hooks, 0, 0 }, + { "annotations", JSON_VARIANT_OBJECT, oci_annotations, 0, 0 }, + {} + }; + + _cleanup_(json_variant_unrefp) JsonVariant *oci = NULL; + _cleanup_(settings_freep) Settings *s = NULL; + unsigned line = 0, column = 0; + JsonVariant *v; + const char *path; + int r; + + assert_se(bundle); + + path = strjoina(bundle, "/config.json"); + + r = json_parse_file(f, path, &oci, &line, &column); + if (r < 0) { + if (line != 0 && column != 0) + return log_error_errno(r, "Failed to parse '%s' at %u:%u: %m", path, line, column); + else + return log_error_errno(r, "Failed to parse '%s': %m", path); + } + + v = json_variant_by_key(oci, "ociVersion"); + if (!v) { + log_error("JSON file '%s' is not an OCI bundle configuration file. Refusing.", path); + return -EINVAL; + } + if (!streq_ptr(json_variant_string(v), "1.0.0")) { + log_error("OCI bundle version not supported: %s", strna(json_variant_string(v))); + return -EINVAL; + } + + // { + // _cleanup_free_ char *formatted = NULL; + // assert_se(json_variant_format(oci, JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR, &formatted) >= 0); + // fputs(formatted, stdout); + // } + + s = settings_new(); + if (!s) + return log_oom(); + + s->start_mode = START_PID1; + s->resolv_conf = RESOLV_CONF_OFF; + s->link_journal = LINK_NO; + s->timezone = TIMEZONE_OFF; + + s->bundle = strdup(bundle); + if (!s->bundle) + return log_oom(); + + r = json_dispatch(oci, table, oci_unexpected, 0, s); + if (r < 0) + return r; + + if (s->properties) { + r = sd_bus_message_seal(s->properties, 0, 0); + if (r < 0) + return log_error_errno(r, "Cannot seal properties bus message: %m"); + } + + *ret = TAKE_PTR(s); + return 0; +} diff --git a/src/nspawn/nspawn-oci.h b/src/nspawn/nspawn-oci.h new file mode 100644 index 00000000..d23a2f3d --- /dev/null +++ b/src/nspawn/nspawn-oci.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "nspawn-settings.h" + +int oci_load(FILE *f, const char *path, Settings **ret); diff --git a/src/nspawn/nspawn-patch-uid.c b/src/nspawn/nspawn-patch-uid.c new file mode 100644 index 00000000..fc591e27 --- /dev/null +++ b/src/nspawn/nspawn-patch-uid.c @@ -0,0 +1,485 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "acl-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "missing_magic.h" +#include "nspawn-def.h" +#include "nspawn-patch-uid.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" + +#if HAVE_ACL + +static int get_acl(int fd, const char *name, acl_type_t type, acl_t *ret) { + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; + acl_t acl; + + assert(fd >= 0); + assert(ret); + + if (name) { + _cleanup_close_ int child_fd = -1; + + child_fd = openat(fd, name, O_PATH|O_CLOEXEC|O_NOFOLLOW); + if (child_fd < 0) + return -errno; + + xsprintf(procfs_path, "/proc/self/fd/%i", child_fd); + acl = acl_get_file(procfs_path, type); + } else if (type == ACL_TYPE_ACCESS) + acl = acl_get_fd(fd); + else { + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + acl = acl_get_file(procfs_path, type); + } + if (!acl) + return -errno; + + *ret = acl; + return 0; +} + +static int set_acl(int fd, const char *name, acl_type_t type, acl_t acl) { + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; + int r; + + assert(fd >= 0); + assert(acl); + + if (name) { + _cleanup_close_ int child_fd = -1; + + child_fd = openat(fd, name, O_PATH|O_CLOEXEC|O_NOFOLLOW); + if (child_fd < 0) + return -errno; + + xsprintf(procfs_path, "/proc/self/fd/%i", child_fd); + r = acl_set_file(procfs_path, type, acl); + } else if (type == ACL_TYPE_ACCESS) + r = acl_set_fd(fd, acl); + else { + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + r = acl_set_file(procfs_path, type, acl); + } + if (r < 0) + return -errno; + + return 0; +} + +static int shift_acl(acl_t acl, uid_t shift, acl_t *ret) { + _cleanup_(acl_freep) acl_t copy = NULL; + acl_entry_t i; + int r; + + assert(acl); + assert(ret); + + r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); + if (r < 0) + return -errno; + while (r > 0) { + uid_t *old_uid, new_uid; + bool modify = false; + acl_tag_t tag; + + if (acl_get_tag_type(i, &tag) < 0) + return -errno; + + if (IN_SET(tag, ACL_USER, ACL_GROUP)) { + + /* We don't distinguish here between uid_t and gid_t, let's make sure the compiler checks that + * this is actually OK */ + assert_cc(sizeof(uid_t) == sizeof(gid_t)); + + old_uid = acl_get_qualifier(i); + if (!old_uid) + return -errno; + + new_uid = shift | (*old_uid & UINT32_C(0xFFFF)); + if (!uid_is_valid(new_uid)) + return -EINVAL; + + modify = new_uid != *old_uid; + if (modify && !copy) { + int n; + + /* There's no copy of the ACL yet? if so, let's create one, and start the loop from the + * beginning, so that we copy all entries, starting from the first, this time. */ + + n = acl_entries(acl); + if (n < 0) + return -errno; + + copy = acl_init(n); + if (!copy) + return -errno; + + /* Seek back to the beginning */ + r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); + if (r < 0) + return -errno; + continue; + } + } + + if (copy) { + acl_entry_t new_entry; + + if (acl_create_entry(©, &new_entry) < 0) + return -errno; + + if (acl_copy_entry(new_entry, i) < 0) + return -errno; + + if (modify) + if (acl_set_qualifier(new_entry, &new_uid) < 0) + return -errno; + } + + r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i); + if (r < 0) + return -errno; + } + + *ret = TAKE_PTR(copy); + + return !!*ret; +} + +static int patch_acls(int fd, const char *name, const struct stat *st, uid_t shift) { + _cleanup_(acl_freep) acl_t acl = NULL, shifted = NULL; + bool changed = false; + int r; + + assert(fd >= 0); + assert(st); + + /* ACLs are not supported on symlinks, there's no point in trying */ + if (S_ISLNK(st->st_mode)) + return 0; + + r = get_acl(fd, name, ACL_TYPE_ACCESS, &acl); + if (r == -EOPNOTSUPP) + return 0; + if (r < 0) + return r; + + r = shift_acl(acl, shift, &shifted); + if (r < 0) + return r; + if (r > 0) { + r = set_acl(fd, name, ACL_TYPE_ACCESS, shifted); + if (r < 0) + return r; + + changed = true; + } + + if (S_ISDIR(st->st_mode)) { + acl_free(acl); + acl_free(shifted); + + acl = shifted = NULL; + + r = get_acl(fd, name, ACL_TYPE_DEFAULT, &acl); + if (r < 0) + return r; + + r = shift_acl(acl, shift, &shifted); + if (r < 0) + return r; + if (r > 0) { + r = set_acl(fd, name, ACL_TYPE_DEFAULT, shifted); + if (r < 0) + return r; + + changed = true; + } + } + + return changed; +} + +#else + +static int patch_acls(int fd, const char *name, const struct stat *st, uid_t shift) { + return 0; +} + +#endif + +static int patch_fd(int fd, const char *name, const struct stat *st, uid_t shift) { + uid_t new_uid; + gid_t new_gid; + bool changed = false; + int r; + + assert(fd >= 0); + assert(st); + + new_uid = shift | (st->st_uid & UINT32_C(0xFFFF)); + new_gid = (gid_t) shift | (st->st_gid & UINT32_C(0xFFFF)); + + if (!uid_is_valid(new_uid) || !gid_is_valid(new_gid)) + return -EINVAL; + + if (st->st_uid != new_uid || st->st_gid != new_gid) { + if (name) + r = fchownat(fd, name, new_uid, new_gid, AT_SYMLINK_NOFOLLOW); + else + r = fchown(fd, new_uid, new_gid); + if (r < 0) + return -errno; + + /* The Linux kernel alters the mode in some cases of chown(). Let's undo this. */ + if (name) { + if (!S_ISLNK(st->st_mode)) + r = fchmodat(fd, name, st->st_mode, 0); + else /* AT_SYMLINK_NOFOLLOW is not available for fchmodat() */ + r = 0; + } else + r = fchmod(fd, st->st_mode); + if (r < 0) + return -errno; + + changed = true; + } + + r = patch_acls(fd, name, st, shift); + if (r < 0) + return r; + + return r > 0 || changed; +} + +/* + * Check if the filesystem is fully compatible with user namespaces or + * UID/GID patching. Some filesystems in this list can be fully mounted inside + * user namespaces, however their inodes may relate to host resources or only + * valid in the global user namespace, therefore no patching should be applied. + */ +static int is_fs_fully_userns_compatible(const struct statfs *sfs) { + + assert(sfs); + + return F_TYPE_EQUAL(sfs->f_type, BINFMTFS_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, CGROUP_SUPER_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, CGROUP2_SUPER_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, DEBUGFS_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, DEVPTS_SUPER_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, EFIVARFS_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, HUGETLBFS_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, MQUEUE_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, PROC_SUPER_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, PSTOREFS_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, SELINUX_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, SMACK_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, SECURITYFS_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, BPF_FS_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, TRACEFS_MAGIC) || + F_TYPE_EQUAL(sfs->f_type, SYSFS_MAGIC); +} + +static int recurse_fd(int fd, bool donate_fd, const struct stat *st, uid_t shift, bool is_toplevel) { + _cleanup_closedir_ DIR *d = NULL; + bool changed = false; + struct statfs sfs; + int r; + + assert(fd >= 0); + + if (fstatfs(fd, &sfs) < 0) + return -errno; + + /* We generally want to permit crossing of mount boundaries when patching the UIDs/GIDs. However, we probably + * shouldn't do this for /proc and /sys if that is already mounted into place. Hence, let's stop the recursion + * when we hit procfs, sysfs or some other special file systems. */ + + r = is_fs_fully_userns_compatible(&sfs); + if (r < 0) + goto finish; + if (r > 0) { + r = 0; /* don't recurse */ + goto finish; + } + + /* Also, if we hit a read-only file system, then don't bother, skip the whole subtree */ + if ((sfs.f_flags & ST_RDONLY) || + access_fd(fd, W_OK) == -EROFS) + goto read_only; + + if (S_ISDIR(st->st_mode)) { + struct dirent *de; + + if (!donate_fd) { + int copy; + + copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (copy < 0) { + r = -errno; + goto finish; + } + + fd = copy; + donate_fd = true; + } + + d = fdopendir(fd); + if (!d) { + r = -errno; + goto finish; + } + fd = -1; + + FOREACH_DIRENT_ALL(de, d, r = -errno; goto finish) { + struct stat fst; + + if (dot_or_dot_dot(de->d_name)) + continue; + + if (fstatat(dirfd(d), de->d_name, &fst, AT_SYMLINK_NOFOLLOW) < 0) { + r = -errno; + goto finish; + } + + if (S_ISDIR(fst.st_mode)) { + int subdir_fd; + + subdir_fd = openat(dirfd(d), de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (subdir_fd < 0) { + r = -errno; + goto finish; + + } + + r = recurse_fd(subdir_fd, true, &fst, shift, false); + if (r < 0) + goto finish; + if (r > 0) + changed = true; + + } else { + r = patch_fd(dirfd(d), de->d_name, &fst, shift); + if (r < 0) + goto finish; + if (r > 0) + changed = true; + } + } + } + + /* After we descended, also patch the directory itself. It's key to do this in this order so that the top-level + * directory is patched as very last object in the tree, so that we can use it as quick indicator whether the + * tree is properly chown()ed already. */ + r = patch_fd(d ? dirfd(d) : fd, NULL, st, shift); + if (r == -EROFS) + goto read_only; + if (r > 0) + changed = true; + + r = changed; + goto finish; + +read_only: + if (!is_toplevel) { + _cleanup_free_ char *name = NULL; + + /* When we hit a ready-only subtree we simply skip it, but log about it. */ + (void) fd_get_path(fd, &name); + log_debug("Skipping read-only file or directory %s.", strna(name)); + r = changed; + } + +finish: + if (donate_fd) + safe_close(fd); + + return r; +} + +static int fd_patch_uid_internal(int fd, bool donate_fd, uid_t shift, uid_t range) { + struct stat st; + int r; + + assert(fd >= 0); + + /* Recursively adjusts the UID/GIDs of all files of a directory tree. This is used to automatically fix up an + * OS tree to the used user namespace UID range. Note that this automatic adjustment only works for UID ranges + * following the concept that the upper 16bit of a UID identify the container, and the lower 16bit are the actual + * UID within the container. */ + + if ((shift & 0xFFFF) != 0) { + /* We only support containers where the shift starts at a 2^16 boundary */ + r = -EOPNOTSUPP; + goto finish; + } + + if (shift == UID_BUSY_BASE) { + r = -EINVAL; + goto finish; + } + + if (range != 0x10000) { + /* We only support containers with 16bit UID ranges for the patching logic */ + r = -EOPNOTSUPP; + goto finish; + } + + if (fstat(fd, &st) < 0) { + r = -errno; + goto finish; + } + + if ((uint32_t) st.st_uid >> 16 != (uint32_t) st.st_gid >> 16) { + /* We only support containers where the uid/gid container ID match */ + r = -EBADE; + goto finish; + } + + /* Try to detect if the range is already right. Of course, this a pretty drastic optimization, as we assume + * that if the top-level dir has the right upper 16bit assigned, then everything below will have too... */ + if (((uint32_t) (st.st_uid ^ shift) >> 16) == 0) + return 0; + + /* Before we start recursively chowning, mark the top-level dir as "busy" by chowning it to the "busy" + * range. Should we be interrupted in the middle of our work, we'll see it owned by this user and will start + * chown()ing it again, unconditionally, as the busy UID is not a valid UID we'd everpick for ourselves. */ + + if ((st.st_uid & UID_BUSY_MASK) != UID_BUSY_BASE) { + if (fchown(fd, + UID_BUSY_BASE | (st.st_uid & ~UID_BUSY_MASK), + (gid_t) UID_BUSY_BASE | (st.st_gid & ~(gid_t) UID_BUSY_MASK)) < 0) { + r = -errno; + goto finish; + } + } + + return recurse_fd(fd, donate_fd, &st, shift, true); + +finish: + if (donate_fd) + safe_close(fd); + + return r; +} + +int path_patch_uid(const char *path, uid_t shift, uid_t range) { + int fd; + + fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (fd < 0) + return -errno; + + return fd_patch_uid_internal(fd, true, shift, range); +} diff --git a/src/nspawn/nspawn-patch-uid.h b/src/nspawn/nspawn-patch-uid.h new file mode 100644 index 00000000..b7c6ce2b --- /dev/null +++ b/src/nspawn/nspawn-patch-uid.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#pragma once + +#include + +int path_patch_uid(const char *path, uid_t shift, uid_t range); diff --git a/src/nspawn/nspawn-register.c b/src/nspawn/nspawn-register.c new file mode 100644 index 00000000..9b7ca5e3 --- /dev/null +++ b/src/nspawn/nspawn-register.c @@ -0,0 +1,403 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-bus.h" + +#include "bus-error.h" +#include "bus-unit-util.h" +#include "bus-util.h" +#include "bus-wait-for-jobs.h" +#include "nspawn-register.h" +#include "special.h" +#include "stat-util.h" +#include "strv.h" +#include "util.h" + +static int append_machine_properties( + sd_bus_message *m, + CustomMount *mounts, + unsigned n_mounts, + int kill_signal) { + + unsigned j; + int r; + + assert(m); + + r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed"); + if (r < 0) + return bus_log_create_error(r); + + /* If you make changes here, also make sure to update systemd-nspawn@.service, to keep the device policies in + * sync regardless if we are run with or without the --keep-unit switch. */ + r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2, + /* Allow the container to + * access and create the API + * device nodes, so that + * PrivateDevices= in the + * container can work + * fine */ + "/dev/net/tun", "rwm", + /* Allow the container + * access to ptys. However, + * do not permit the + * container to ever create + * these device nodes. */ + "char-pts", "rw"); + if (r < 0) + return bus_log_create_error(r); + + for (j = 0; j < n_mounts; j++) { + CustomMount *cm = mounts + j; + + if (cm->type != CUSTOM_MOUNT_BIND) + continue; + + r = is_device_node(cm->source); + if (r == -ENOENT) { + /* The bind source might only appear as the image is put together, hence don't complain */ + log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source); + continue; + } + if (r < 0) + return log_error_errno(r, "Failed to stat %s: %m", cm->source); + + if (r) { + r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1, + cm->source, cm->read_only ? "r" : "rw"); + if (r < 0) + return log_error_errno(r, "Failed to append message arguments: %m"); + } + } + + if (kill_signal != 0) { + r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed"); + if (r < 0) + return bus_log_create_error(r); + } + + return 0; +} + +static int append_controller_property(sd_bus *bus, sd_bus_message *m) { + const char *unique; + int r; + + assert(bus); + assert(m); + + r = sd_bus_get_unique_name(bus, &unique); + if (r < 0) + return log_error_errno(r, "Failed to get unique name: %m"); + + r = sd_bus_message_append(m, "(sv)", "Controller", "s", unique); + if (r < 0) + return bus_log_create_error(r); + + return 0; +} + +int register_machine( + sd_bus *bus, + const char *machine_name, + pid_t pid, + const char *directory, + sd_id128_t uuid, + int local_ifindex, + const char *slice, + CustomMount *mounts, + unsigned n_mounts, + int kill_signal, + char **properties, + sd_bus_message *properties_message, + bool keep_unit, + const char *service) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + + if (keep_unit) { + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "RegisterMachineWithNetwork", + &error, + NULL, + "sayssusai", + machine_name, + SD_BUS_MESSAGE_APPEND_ID128(uuid), + service, + "container", + (uint32_t) pid, + strempty(directory), + local_ifindex > 0 ? 1 : 0, local_ifindex); + } else { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "CreateMachineWithNetwork"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append( + m, + "sayssusai", + machine_name, + SD_BUS_MESSAGE_APPEND_ID128(uuid), + service, + "container", + (uint32_t) pid, + strempty(directory), + local_ifindex > 0 ? 1 : 0, local_ifindex); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + if (!isempty(slice)) { + r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice); + if (r < 0) + return bus_log_create_error(r); + } + + r = append_controller_property(bus, m); + if (r < 0) + return r; + + r = append_machine_properties( + m, + mounts, + n_mounts, + kill_signal); + if (r < 0) + return r; + + if (properties_message) { + r = sd_bus_message_copy(m, properties_message, true); + if (r < 0) + return bus_log_create_error(r); + } + + r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, NULL); + } + + if (r < 0) + return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r)); + + return 0; +} + +int unregister_machine( + sd_bus *bus, + const char *machine_name) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + + r = sd_bus_call_method( + bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "UnregisterMachine", + &error, + NULL, + "s", + machine_name); + if (r < 0) + log_debug("Failed to unregister machine: %s", bus_error_message(&error, r)); + + return 0; +} + +int allocate_scope( + sd_bus *bus, + const char *machine_name, + pid_t pid, + const char *slice, + CustomMount *mounts, + unsigned n_mounts, + int kill_signal, + char **properties, + sd_bus_message *properties_message) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_free_ char *scope = NULL; + const char *description, *object; + int r; + + assert(bus); + + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Could not watch job: %m"); + + r = unit_name_mangle_with_suffix(machine_name, "as machine name", 0, ".scope", &scope); + if (r < 0) + return log_error_errno(r, "Failed to mangle scope name: %m"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "ss", scope, "fail"); + if (r < 0) + return bus_log_create_error(r); + + /* Properties */ + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + description = strjoina("Container ", machine_name); + + r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)(sv)", + "PIDs", "au", 1, pid, + "Description", "s", description, + "Delegate", "b", 1, + "CollectMode", "s", "inactive-or-failed", + "AddRef", "b", 1, + "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice); + if (r < 0) + return bus_log_create_error(r); + + r = append_controller_property(bus, m); + if (r < 0) + return r; + + if (properties_message) { + r = sd_bus_message_copy(m, properties_message, true); + if (r < 0) + return bus_log_create_error(r); + } + + r = append_machine_properties( + m, + mounts, + n_mounts, + kill_signal); + if (r < 0) + return r; + + r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + /* No auxiliary units */ + r = sd_bus_message_append( + m, + "a(sa(sv))", + 0); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to allocate scope: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_one(w, object, false); + if (r < 0) + return r; + + return 0; +} + +int terminate_scope( + sd_bus *bus, + const char *machine_name) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *scope = NULL; + int r; + + r = unit_name_mangle_with_suffix(machine_name, "to terminate", 0, ".scope", &scope); + if (r < 0) + return log_error_errno(r, "Failed to mangle scope name: %m"); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "AbandonScope", + &error, + NULL, + "s", + scope); + if (r < 0) { + log_debug_errno(r, "Failed to abandon scope '%s', ignoring: %s", scope, bus_error_message(&error, r)); + sd_bus_error_free(&error); + } + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "KillUnit", + &error, + NULL, + "ssi", + scope, + "all", + (int32_t) SIGKILL); + if (r < 0) { + log_debug_errno(r, "Failed to SIGKILL scope '%s', ignoring: %s", scope, bus_error_message(&error, r)); + sd_bus_error_free(&error); + } + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "UnrefUnit", + &error, + NULL, + "s", + scope); + if (r < 0) + log_debug_errno(r, "Failed to drop reference to scope '%s', ignoring: %s", scope, bus_error_message(&error, r)); + + return 0; +} diff --git a/src/nspawn/nspawn-register.h b/src/nspawn/nspawn-register.h new file mode 100644 index 00000000..07cca7fa --- /dev/null +++ b/src/nspawn/nspawn-register.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-id128.h" + +#include "nspawn-mount.h" + +int register_machine(sd_bus *bus, const char *machine_name, pid_t pid, const char *directory, sd_id128_t uuid, int local_ifindex, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties, sd_bus_message *properties_message, bool keep_unit, const char *service); +int unregister_machine(sd_bus *bus, const char *machine_name); + +int allocate_scope(sd_bus *bus, const char *machine_name, pid_t pid, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties, sd_bus_message *properties_message); +int terminate_scope(sd_bus *bus, const char *machine_name); diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c new file mode 100644 index 00000000..f94f131f --- /dev/null +++ b/src/nspawn/nspawn-seccomp.c @@ -0,0 +1,238 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#if HAVE_SECCOMP +#include +#endif + +#include "alloc-util.h" +#include "log.h" +#include "nspawn-seccomp.h" +#if HAVE_SECCOMP +#include "seccomp-util.h" +#endif +#include "string-util.h" +#include "strv.h" + +#if HAVE_SECCOMP + +static int seccomp_add_default_syscall_filter( + scmp_filter_ctx ctx, + uint32_t arch, + uint64_t cap_list_retain, + char **syscall_whitelist, + char **syscall_blacklist) { + + static const struct { + uint64_t capability; + const char* name; + } whitelist[] = { + /* Let's use set names where we can */ + { 0, "@aio" }, + { 0, "@basic-io" }, + { 0, "@chown" }, + { 0, "@default" }, + { 0, "@file-system" }, + { 0, "@io-event" }, + { 0, "@ipc" }, + { 0, "@mount" }, + { 0, "@network-io" }, + { 0, "@process" }, + { 0, "@resources" }, + { 0, "@setuid" }, + { 0, "@signal" }, + { 0, "@sync" }, + { 0, "@timer" }, + + /* The following four are sets we optionally enable, in case the caps have been configured for it */ + { CAP_SYS_TIME, "@clock" }, + { CAP_SYS_MODULE, "@module" }, + { CAP_SYS_RAWIO, "@raw-io" }, + { CAP_IPC_LOCK, "@memlock" }, + + /* Plus a good set of additional syscalls which are not part of any of the groups above */ + { 0, "brk" }, + { 0, "capget" }, + { 0, "capset" }, + { 0, "copy_file_range" }, + { 0, "fadvise64" }, + { 0, "fadvise64_64" }, + { 0, "flock" }, + { 0, "get_mempolicy" }, + { 0, "getcpu" }, + { 0, "getpriority" }, + { 0, "getrandom" }, + { 0, "ioctl" }, + { 0, "ioprio_get" }, + { 0, "kcmp" }, + { 0, "madvise" }, + { 0, "mincore" }, + { 0, "mprotect" }, + { 0, "mremap" }, + { 0, "name_to_handle_at" }, + { 0, "oldolduname" }, + { 0, "olduname" }, + { 0, "personality" }, + { 0, "readahead" }, + { 0, "readdir" }, + { 0, "remap_file_pages" }, + { 0, "sched_get_priority_max" }, + { 0, "sched_get_priority_min" }, + { 0, "sched_getaffinity" }, + { 0, "sched_getattr" }, + { 0, "sched_getparam" }, + { 0, "sched_getscheduler" }, + { 0, "sched_rr_get_interval" }, + { 0, "sched_yield" }, + { 0, "seccomp" }, + { 0, "sendfile" }, + { 0, "sendfile64" }, + { 0, "setdomainname" }, + { 0, "setfsgid" }, + { 0, "setfsgid32" }, + { 0, "setfsuid" }, + { 0, "setfsuid32" }, + { 0, "sethostname" }, + { 0, "setpgid" }, + { 0, "setsid" }, + { 0, "splice" }, + { 0, "sysinfo" }, + { 0, "tee" }, + { 0, "umask" }, + { 0, "uname" }, + { 0, "userfaultfd" }, + { 0, "vmsplice" }, + + /* The following individual syscalls are added depending on specified caps */ + { CAP_SYS_PACCT, "acct" }, + { CAP_SYS_PTRACE, "process_vm_readv" }, + { CAP_SYS_PTRACE, "process_vm_writev" }, + { CAP_SYS_PTRACE, "ptrace" }, + { CAP_SYS_BOOT, "reboot" }, + { CAP_SYSLOG, "syslog" }, + { CAP_SYS_TTY_CONFIG, "vhangup" }, + + /* + * The following syscalls and groups are knowingly excluded: + * + * @cpu-emulation + * @keyring (NB: keyring is not namespaced!) + * @obsolete + * @pkey + * @swap + * + * bpf (NB: bpffs is not namespaced!) + * fanotify_init + * fanotify_mark + * kexec_file_load + * kexec_load + * lookup_dcookie + * nfsservctl + * open_by_handle_at + * perf_event_open + * quotactl + */ + }; + + char **p; + int r; + + for (size_t i = 0; i < ELEMENTSOF(whitelist); i++) { + if (whitelist[i].capability != 0 && (cap_list_retain & (1ULL << whitelist[i].capability)) == 0) + continue; + + r = seccomp_add_syscall_filter_item(ctx, whitelist[i].name, SCMP_ACT_ALLOW, syscall_blacklist, false); + if (r < 0) + return log_error_errno(r, "Failed to add syscall filter item %s: %m", whitelist[i].name); + } + + STRV_FOREACH(p, syscall_whitelist) { + r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist, true); + if (r < 0) + log_warning_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", + *p, seccomp_arch_to_string(arch)); + } + + return 0; +} + +int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **syscall_blacklist) { + uint32_t arch; + int r; + + if (!is_seccomp_available()) { + log_debug("SECCOMP features not detected in the kernel, disabling SECCOMP filterering"); + return 0; + } + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + + log_debug("Applying whitelist on architecture: %s", seccomp_arch_to_string(arch)); + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ERRNO(EPERM)); + if (r < 0) + return log_error_errno(r, "Failed to allocate seccomp object: %m"); + + r = seccomp_add_default_syscall_filter(seccomp, arch, cap_list_retain, syscall_whitelist, syscall_blacklist); + if (r < 0) + return r; + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return log_error_errno(r, "Failed to install seccomp filter: %m"); + if (r < 0) + log_debug_errno(r, "Failed to install filter set for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + + log_debug("Applying NETLINK_AUDIT mask on architecture: %s", seccomp_arch_to_string(arch)); + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); + if (r < 0) + return log_error_errno(r, "Failed to allocate seccomp object: %m"); + + /* + Audit is broken in containers, much of the userspace audit hookup will fail if running inside a + container. We don't care and just turn off creation of audit sockets. + + This will make socket(AF_NETLINK, *, NETLINK_AUDIT) fail with EAFNOSUPPORT which audit userspace uses + as indication that audit is disabled in the kernel. + */ + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EAFNOSUPPORT), + SCMP_SYS(socket), + 2, + SCMP_A0(SCMP_CMP_EQ, AF_NETLINK), + SCMP_A2(SCMP_CMP_EQ, NETLINK_AUDIT)); + if (r < 0) { + log_debug_errno(r, "Failed to add audit seccomp rule, ignoring: %m"); + continue; + } + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return log_error_errno(r, "Failed to install seccomp audit filter: %m"); + if (r < 0) + log_debug_errno(r, "Failed to install filter set for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +#else + +int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **syscall_blacklist) { + return 0; +} + +#endif diff --git a/src/nspawn/nspawn-seccomp.h b/src/nspawn/nspawn-seccomp.h new file mode 100644 index 00000000..d852eef6 --- /dev/null +++ b/src/nspawn/nspawn-seccomp.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **syscall_blacklist); diff --git a/src/nspawn/nspawn-settings.c b/src/nspawn/nspawn-settings.c new file mode 100644 index 00000000..5fb5b49b --- /dev/null +++ b/src/nspawn/nspawn-settings.c @@ -0,0 +1,899 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "cap-list.h" +#include "conf-parser.h" +#include "cpu-set-util.h" +#include "hostname-util.h" +#include "nspawn-network.h" +#include "nspawn-settings.h" +#include "parse-util.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "socket-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" + +Settings *settings_new(void) { + Settings *s; + + s = new(Settings, 1); + if (!s) + return NULL; + + *s = (Settings) { + .start_mode = _START_MODE_INVALID, + .personality = PERSONALITY_INVALID, + + .resolv_conf = _RESOLV_CONF_MODE_INVALID, + .link_journal = _LINK_JOURNAL_INVALID, + .timezone = _TIMEZONE_MODE_INVALID, + + .userns_mode = _USER_NAMESPACE_MODE_INVALID, + .userns_chown = -1, + .uid_shift = UID_INVALID, + .uid_range = UID_INVALID, + + .no_new_privileges = -1, + + .read_only = -1, + .volatile_mode = _VOLATILE_MODE_INVALID, + + .private_network = -1, + .network_veth = -1, + + .full_capabilities = CAPABILITY_QUINTET_NULL, + + .uid = UID_INVALID, + .gid = GID_INVALID, + + .console_mode = _CONSOLE_MODE_INVALID, + .console_width = (unsigned) -1, + .console_height = (unsigned) -1, + + .clone_ns_flags = (unsigned long) -1, + .use_cgns = -1, + }; + + return s; +} + +int settings_load(FILE *f, const char *path, Settings **ret) { + _cleanup_(settings_freep) Settings *s = NULL; + int r; + + assert(path); + assert(ret); + + s = settings_new(); + if (!s) + return -ENOMEM; + + r = config_parse(NULL, path, f, + "Exec\0" + "Network\0" + "Files\0", + config_item_perf_lookup, nspawn_gperf_lookup, + CONFIG_PARSE_WARN, + s); + if (r < 0) + return r; + + /* Make sure that if userns_mode is set, userns_chown is set to something appropriate, and vice versa. Either + * both fields shall be initialized or neither. */ + if (s->userns_mode == USER_NAMESPACE_PICK) + s->userns_chown = true; + else if (s->userns_mode != _USER_NAMESPACE_MODE_INVALID && s->userns_chown < 0) + s->userns_chown = false; + + if (s->userns_chown >= 0 && s->userns_mode == _USER_NAMESPACE_MODE_INVALID) + s->userns_mode = USER_NAMESPACE_NO; + + *ret = TAKE_PTR(s); + return 0; +} + +static void free_oci_hooks(OciHook *h, size_t n) { + size_t i; + + assert(h || n == 0); + + for (i = 0; i < n; i++) { + free(h[i].path); + strv_free(h[i].args); + strv_free(h[i].env); + } + + free(h); +} + +void device_node_array_free(DeviceNode *node, size_t n) { + size_t i; + + for (i = 0; i < n; i++) + free(node[i].path); + + free(node); +} + +Settings* settings_free(Settings *s) { + if (!s) + return NULL; + + strv_free(s->parameters); + strv_free(s->environment); + free(s->user); + free(s->pivot_root_new); + free(s->pivot_root_old); + free(s->working_directory); + strv_free(s->syscall_whitelist); + strv_free(s->syscall_blacklist); + rlimit_free_all(s->rlimit); + free(s->hostname); + cpu_set_reset(&s->cpu_set); + + strv_free(s->network_interfaces); + strv_free(s->network_macvlan); + strv_free(s->network_ipvlan); + strv_free(s->network_veth_extra); + free(s->network_bridge); + free(s->network_zone); + expose_port_free_all(s->expose_ports); + + custom_mount_free_all(s->custom_mounts, s->n_custom_mounts); + + free(s->bundle); + free(s->root); + + free_oci_hooks(s->oci_hooks_prestart, s->n_oci_hooks_prestart); + free_oci_hooks(s->oci_hooks_poststart, s->n_oci_hooks_poststart); + free_oci_hooks(s->oci_hooks_poststop, s->n_oci_hooks_poststop); + + free(s->slice); + sd_bus_message_unref(s->properties); + + free(s->supplementary_gids); + device_node_array_free(s->extra_nodes, s->n_extra_nodes); + free(s->network_namespace_path); + + strv_free(s->sysctl); + +#if HAVE_SECCOMP + seccomp_release(s->seccomp); +#endif + + return mfree(s); +} + +bool settings_private_network(Settings *s) { + assert(s); + + return + s->private_network > 0 || + s->network_veth > 0 || + s->network_bridge || + s->network_zone || + s->network_interfaces || + s->network_macvlan || + s->network_ipvlan || + s->network_veth_extra; +} + +bool settings_network_veth(Settings *s) { + assert(s); + + return + s->network_veth > 0 || + s->network_bridge || + s->network_zone; +} + +int settings_allocate_properties(Settings *s) { + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + int r; + + assert(s); + + if (s->properties) + return 0; + + r = sd_bus_default_system(&bus); + if (r < 0) + return r; + + r = sd_bus_message_new(bus, &s->properties, SD_BUS_MESSAGE_METHOD_CALL); + if (r < 0) + return r; + + return 0; +} + +DEFINE_CONFIG_PARSE_ENUM(config_parse_volatile_mode, volatile_mode, VolatileMode, "Failed to parse volatile mode"); + +int config_parse_expose_port( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *s = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = expose_port_parse(&s->expose_ports, rvalue); + if (r == -EEXIST) { + log_syntax(unit, LOG_ERR, filename, line, r, "Duplicate port specification, ignoring: %s", rvalue); + return 0; + } + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse host port %s: %m", rvalue); + return 0; + } + + return 0; +} + +int config_parse_capability( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint64_t u = 0, *result = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&rvalue, &word, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract capability string, ignoring: %s", rvalue); + return 0; + } + if (r == 0) + break; + + if (streq(word, "all")) + u = (uint64_t) -1; + else { + r = capability_from_name(word); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse capability, ignoring: %s", word); + continue; + } + + u |= UINT64_C(1) << r; + } + } + + if (u == 0) + return 0; + + *result |= u; + return 0; +} + +int config_parse_id128( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + sd_id128_t t, *result = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = sd_id128_from_string(rvalue, &t); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse 128bit ID/UUID, ignoring: %s", rvalue); + return 0; + } + + *result = t; + return 0; +} + +int config_parse_pivot_root( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = pivot_root_parse(&settings->pivot_root_new, &settings->pivot_root_old, rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid pivot root mount specification %s: %m", rvalue); + return 0; + } + + return 0; +} + +int config_parse_bind( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = bind_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue, ltype); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid bind mount specification %s: %m", rvalue); + return 0; + } + + return 0; +} + +int config_parse_tmpfs( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = tmpfs_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid temporary file system specification %s: %m", rvalue); + return 0; + } + + return 0; +} + +int config_parse_inaccessible( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = inaccessible_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid inaccessible file system specification %s: %m", rvalue); + return 0; + } + + return 0; +} + +int config_parse_overlay( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = overlay_mount_parse(&settings->custom_mounts, &settings->n_custom_mounts, rvalue, ltype); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid overlay file system specification %s, ignoring: %m", rvalue); + + return 0; +} + +int config_parse_veth_extra( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = veth_extra_parse(&settings->network_veth_extra, rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid extra virtual Ethernet link specification %s: %m", rvalue); + return 0; + } + + return 0; +} + +int config_parse_network_zone( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + _cleanup_free_ char *j = NULL; + + assert(filename); + assert(lvalue); + assert(rvalue); + + j = strjoin("vz-", rvalue); + if (!ifname_valid(j)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid network zone name, ignoring: %s", rvalue); + return 0; + } + + free_and_replace(settings->network_zone, j); + + return 0; +} + +int config_parse_boot( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Boot= parameter %s, ignoring: %m", rvalue); + return 0; + } + + if (r > 0) { + if (settings->start_mode == START_PID2) + goto conflict; + + settings->start_mode = START_BOOT; + } else { + if (settings->start_mode == START_BOOT) + goto conflict; + + if (settings->start_mode < 0) + settings->start_mode = START_PID1; + } + + return 0; + +conflict: + log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); + return 0; +} + +int config_parse_pid2( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse ProcessTwo= parameter %s, ignoring: %m", rvalue); + return 0; + } + + if (r > 0) { + if (settings->start_mode == START_BOOT) + goto conflict; + + settings->start_mode = START_PID2; + } else { + if (settings->start_mode == START_PID2) + goto conflict; + + if (settings->start_mode < 0) + settings->start_mode = START_PID1; + } + + return 0; + +conflict: + log_syntax(unit, LOG_ERR, filename, line, r, "Conflicting Boot= or ProcessTwo= setting found. Ignoring."); + return 0; +} + +int config_parse_private_users( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + r = parse_boolean(rvalue); + if (r == 0) { + /* no: User namespacing off */ + settings->userns_mode = USER_NAMESPACE_NO; + settings->uid_shift = UID_INVALID; + settings->uid_range = UINT32_C(0x10000); + } else if (r > 0) { + /* yes: User namespacing on, UID range is read from root dir */ + settings->userns_mode = USER_NAMESPACE_FIXED; + settings->uid_shift = UID_INVALID; + settings->uid_range = UINT32_C(0x10000); + } else if (streq(rvalue, "pick")) { + /* pick: User namespacing on, UID range is picked randomly */ + settings->userns_mode = USER_NAMESPACE_PICK; + settings->uid_shift = UID_INVALID; + settings->uid_range = UINT32_C(0x10000); + } else { + const char *range, *shift; + uid_t sh, rn; + + /* anything else: User namespacing on, UID range is explicitly configured */ + + range = strchr(rvalue, ':'); + if (range) { + shift = strndupa(rvalue, range - rvalue); + range++; + + r = safe_atou32(range, &rn); + if (r < 0 || rn <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "UID/GID range invalid, ignoring: %s", range); + return 0; + } + } else { + shift = rvalue; + rn = UINT32_C(0x10000); + } + + r = parse_uid(shift, &sh); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "UID/GID shift invalid, ignoring: %s", range); + return 0; + } + + settings->userns_mode = USER_NAMESPACE_FIXED; + settings->uid_shift = sh; + settings->uid_range = rn; + } + + return 0; +} + +int config_parse_syscall_filter( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + bool negative; + const char *items; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + negative = rvalue[0] == '~'; + items = negative ? rvalue + 1 : rvalue; + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&items, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse SystemCallFilter= parameter %s, ignoring: %m", rvalue); + return 0; + } + + if (negative) + r = strv_extend(&settings->syscall_blacklist, word); + else + r = strv_extend(&settings->syscall_whitelist, word); + if (r < 0) + return log_oom(); + } + + return 0; +} + +int config_parse_hostname( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char **s = data; + + assert(rvalue); + assert(s); + + if (!hostname_is_valid(rvalue, false)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid hostname, ignoring: %s", rvalue); + return 0; + } + + if (free_and_strdup(s, empty_to_null(rvalue)) < 0) + return log_oom(); + + return 0; +} + +int config_parse_oom_score_adjust( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int oa, r; + + assert(rvalue); + assert(settings); + + if (isempty(rvalue)) { + settings->oom_score_adjust_set = false; + return 0; + } + + r = parse_oom_score_adjust(rvalue, &oa); + if (r == -ERANGE) { + log_syntax(unit, LOG_ERR, filename, line, r, "OOM score adjust value out of range, ignoring: %s", rvalue); + return 0; + } + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse the OOM score adjust value, ignoring: %s", rvalue); + return 0; + } + + settings->oom_score_adjust = oa; + settings->oom_score_adjust_set = true; + + return 0; +} + +int config_parse_cpu_affinity( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + + assert(rvalue); + assert(settings); + + return parse_cpu_set_extend(rvalue, &settings->cpu_set, true, unit, filename, line, lvalue); +} + +DEFINE_CONFIG_PARSE_ENUM(config_parse_resolv_conf, resolv_conf_mode, ResolvConfMode, "Failed to parse resolv.conf mode"); + +static const char *const resolv_conf_mode_table[_RESOLV_CONF_MODE_MAX] = { + [RESOLV_CONF_OFF] = "off", + [RESOLV_CONF_COPY_HOST] = "copy-host", + [RESOLV_CONF_COPY_STATIC] = "copy-static", + [RESOLV_CONF_BIND_HOST] = "bind-host", + [RESOLV_CONF_BIND_STATIC] = "bind-static", + [RESOLV_CONF_DELETE] = "delete", + [RESOLV_CONF_AUTO] = "auto", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolv_conf_mode, ResolvConfMode, RESOLV_CONF_AUTO); + +int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try) { + assert(s); + assert(ret_mode); + assert(ret_try); + + if (streq(s, "auto")) { + *ret_mode = LINK_AUTO; + *ret_try = false; + } else if (streq(s, "no")) { + *ret_mode = LINK_NO; + *ret_try = false; + } else if (streq(s, "guest")) { + *ret_mode = LINK_GUEST; + *ret_try = false; + } else if (streq(s, "host")) { + *ret_mode = LINK_HOST; + *ret_try = false; + } else if (streq(s, "try-guest")) { + *ret_mode = LINK_GUEST; + *ret_try = true; + } else if (streq(s, "try-host")) { + *ret_mode = LINK_HOST; + *ret_try = true; + } else + return -EINVAL; + + return 0; +} + +int config_parse_link_journal( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Settings *settings = data; + int r; + + assert(rvalue); + assert(settings); + + r = parse_link_journal(rvalue, &settings->link_journal, &settings->link_journal_try); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse link journal mode, ignoring: %s", rvalue); + return 0; + } + + return 0; +} + +DEFINE_CONFIG_PARSE_ENUM(config_parse_timezone, timezone_mode, TimezoneMode, "Failed to parse timezone mode"); + +static const char *const timezone_mode_table[_TIMEZONE_MODE_MAX] = { + [TIMEZONE_OFF] = "off", + [TIMEZONE_COPY] = "copy", + [TIMEZONE_BIND] = "bind", + [TIMEZONE_SYMLINK] = "symlink", + [TIMEZONE_DELETE] = "delete", + [TIMEZONE_AUTO] = "auto", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(timezone_mode, TimezoneMode, TIMEZONE_AUTO); diff --git a/src/nspawn/nspawn-settings.h b/src/nspawn/nspawn-settings.h new file mode 100644 index 00000000..f1a1a754 --- /dev/null +++ b/src/nspawn/nspawn-settings.h @@ -0,0 +1,258 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#if HAVE_SECCOMP +#include +#endif + +#include "sd-bus.h" +#include "sd-id128.h" + +#include "capability-util.h" +#include "conf-parser.h" +#include "cpu-set-util.h" +#include "macro.h" +#include "missing_resource.h" +#include "nspawn-expose-ports.h" +#include "nspawn-mount.h" +#include "time-util.h" + +typedef enum StartMode { + START_PID1, /* Run parameters as command line as process 1 */ + START_PID2, /* Use stub init process as PID 1, run parameters as command line as process 2 */ + START_BOOT, /* Search for init system, pass arguments as parameters */ + _START_MODE_MAX, + _START_MODE_INVALID = -1 +} StartMode; + +typedef enum UserNamespaceMode { + USER_NAMESPACE_NO, + USER_NAMESPACE_FIXED, + USER_NAMESPACE_PICK, + _USER_NAMESPACE_MODE_MAX, + _USER_NAMESPACE_MODE_INVALID = -1, +} UserNamespaceMode; + +typedef enum ResolvConfMode { + RESOLV_CONF_OFF, + RESOLV_CONF_COPY_HOST, + RESOLV_CONF_COPY_STATIC, + RESOLV_CONF_BIND_HOST, + RESOLV_CONF_BIND_STATIC, + RESOLV_CONF_DELETE, + RESOLV_CONF_AUTO, + _RESOLV_CONF_MODE_MAX, + _RESOLV_CONF_MODE_INVALID = -1 +} ResolvConfMode; + +typedef enum LinkJournal { + LINK_NO, + LINK_AUTO, + LINK_HOST, + LINK_GUEST, + _LINK_JOURNAL_MAX, + _LINK_JOURNAL_INVALID = -1 +} LinkJournal; + +typedef enum TimezoneMode { + TIMEZONE_OFF, + TIMEZONE_COPY, + TIMEZONE_BIND, + TIMEZONE_SYMLINK, + TIMEZONE_DELETE, + TIMEZONE_AUTO, + _TIMEZONE_MODE_MAX, + _TIMEZONE_MODE_INVALID = -1 +} TimezoneMode; + +typedef enum ConsoleMode { + CONSOLE_INTERACTIVE, + CONSOLE_READ_ONLY, + CONSOLE_PASSIVE, + CONSOLE_PIPE, + _CONSOLE_MODE_MAX, + _CONSOLE_MODE_INVALID = -1, +} ConsoleMode; + +typedef enum SettingsMask { + SETTING_START_MODE = UINT64_C(1) << 0, + SETTING_ENVIRONMENT = UINT64_C(1) << 1, + SETTING_USER = UINT64_C(1) << 2, + SETTING_CAPABILITY = UINT64_C(1) << 3, + SETTING_KILL_SIGNAL = UINT64_C(1) << 4, + SETTING_PERSONALITY = UINT64_C(1) << 5, + SETTING_MACHINE_ID = UINT64_C(1) << 6, + SETTING_NETWORK = UINT64_C(1) << 7, + SETTING_EXPOSE_PORTS = UINT64_C(1) << 8, + SETTING_READ_ONLY = UINT64_C(1) << 9, + SETTING_VOLATILE_MODE = UINT64_C(1) << 10, + SETTING_CUSTOM_MOUNTS = UINT64_C(1) << 11, + SETTING_WORKING_DIRECTORY = UINT64_C(1) << 12, + SETTING_USERNS = UINT64_C(1) << 13, + SETTING_NOTIFY_READY = UINT64_C(1) << 14, + SETTING_PIVOT_ROOT = UINT64_C(1) << 15, + SETTING_SYSCALL_FILTER = UINT64_C(1) << 16, + SETTING_HOSTNAME = UINT64_C(1) << 17, + SETTING_NO_NEW_PRIVILEGES = UINT64_C(1) << 18, + SETTING_OOM_SCORE_ADJUST = UINT64_C(1) << 19, + SETTING_CPU_AFFINITY = UINT64_C(1) << 20, + SETTING_RESOLV_CONF = UINT64_C(1) << 21, + SETTING_LINK_JOURNAL = UINT64_C(1) << 22, + SETTING_TIMEZONE = UINT64_C(1) << 23, + SETTING_EPHEMERAL = UINT64_C(1) << 24, + SETTING_SLICE = UINT64_C(1) << 25, + SETTING_DIRECTORY = UINT64_C(1) << 26, + SETTING_USE_CGNS = UINT64_C(1) << 27, + SETTING_CLONE_NS_FLAGS = UINT64_C(1) << 28, + SETTING_CONSOLE_MODE = UINT64_C(1) << 29, + SETTING_RLIMIT_FIRST = UINT64_C(1) << 30, /* we define one bit per resource limit here */ + SETTING_RLIMIT_LAST = UINT64_C(1) << (30 + _RLIMIT_MAX - 1), + _SETTINGS_MASK_ALL = (UINT64_C(1) << (30 + _RLIMIT_MAX)) -1, + _SETTING_FORCE_ENUM_WIDTH = UINT64_MAX +} SettingsMask; + +/* We want to use SETTING_RLIMIT_FIRST in shifts, so make sure it is really 64 bits + * when used in expressions. */ +#define SETTING_RLIMIT_FIRST ((uint64_t) SETTING_RLIMIT_FIRST) +#define SETTING_RLIMIT_LAST ((uint64_t) SETTING_RLIMIT_LAST) + +assert_cc(sizeof(SettingsMask) == 8); +assert_cc(sizeof(SETTING_RLIMIT_FIRST) == 8); +assert_cc(sizeof(SETTING_RLIMIT_LAST) == 8); + +typedef struct DeviceNode { + char *path; + unsigned major; + unsigned minor; + mode_t mode; + uid_t uid; + gid_t gid; +} DeviceNode; + +typedef struct OciHook { + char *path; + char **args; + char **env; + usec_t timeout; +} OciHook; + +typedef struct Settings { + /* [Run] */ + StartMode start_mode; + bool ephemeral; + char **parameters; + char **environment; + char *user; + uint64_t capability; + uint64_t drop_capability; + int kill_signal; + unsigned long personality; + sd_id128_t machine_id; + char *working_directory; + char *pivot_root_new; + char *pivot_root_old; + UserNamespaceMode userns_mode; + uid_t uid_shift, uid_range; + bool notify_ready; + char **syscall_whitelist; + char **syscall_blacklist; + struct rlimit *rlimit[_RLIMIT_MAX]; + char *hostname; + int no_new_privileges; + int oom_score_adjust; + bool oom_score_adjust_set; + CPUSet cpu_set; + ResolvConfMode resolv_conf; + LinkJournal link_journal; + bool link_journal_try; + TimezoneMode timezone; + + /* [Image] */ + int read_only; + VolatileMode volatile_mode; + CustomMount *custom_mounts; + size_t n_custom_mounts; + int userns_chown; + + /* [Network] */ + int private_network; + int network_veth; + char *network_bridge; + char *network_zone; + char **network_interfaces; + char **network_macvlan; + char **network_ipvlan; + char **network_veth_extra; + ExposePort *expose_ports; + + /* Additional fields, that are specific to OCI runtime case */ + char *bundle; + char *root; + OciHook *oci_hooks_prestart, *oci_hooks_poststart, *oci_hooks_poststop; + size_t n_oci_hooks_prestart, n_oci_hooks_poststart, n_oci_hooks_poststop; + char *slice; + sd_bus_message *properties; + CapabilityQuintet full_capabilities; + uid_t uid; + gid_t gid; + gid_t *supplementary_gids; + size_t n_supplementary_gids; + unsigned console_width, console_height; + ConsoleMode console_mode; + DeviceNode *extra_nodes; + size_t n_extra_nodes; + unsigned long clone_ns_flags; + char *network_namespace_path; + int use_cgns; + char **sysctl; +#if HAVE_SECCOMP + scmp_filter_ctx seccomp; +#endif +} Settings; + +Settings *settings_new(void); +int settings_load(FILE *f, const char *path, Settings **ret); +Settings* settings_free(Settings *s); + +bool settings_network_veth(Settings *s); +bool settings_private_network(Settings *s); +int settings_allocate_properties(Settings *s); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Settings*, settings_free); + +const struct ConfigPerfItem* nspawn_gperf_lookup(const char *key, GPERF_LEN_TYPE length); + +CONFIG_PARSER_PROTOTYPE(config_parse_capability); +CONFIG_PARSER_PROTOTYPE(config_parse_id128); +CONFIG_PARSER_PROTOTYPE(config_parse_expose_port); +CONFIG_PARSER_PROTOTYPE(config_parse_volatile_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_pivot_root); +CONFIG_PARSER_PROTOTYPE(config_parse_bind); +CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs); +CONFIG_PARSER_PROTOTYPE(config_parse_overlay); +CONFIG_PARSER_PROTOTYPE(config_parse_inaccessible); +CONFIG_PARSER_PROTOTYPE(config_parse_veth_extra); +CONFIG_PARSER_PROTOTYPE(config_parse_network_zone); +CONFIG_PARSER_PROTOTYPE(config_parse_boot); +CONFIG_PARSER_PROTOTYPE(config_parse_pid2); +CONFIG_PARSER_PROTOTYPE(config_parse_private_users); +CONFIG_PARSER_PROTOTYPE(config_parse_syscall_filter); +CONFIG_PARSER_PROTOTYPE(config_parse_hostname); +CONFIG_PARSER_PROTOTYPE(config_parse_oom_score_adjust); +CONFIG_PARSER_PROTOTYPE(config_parse_cpu_affinity); +CONFIG_PARSER_PROTOTYPE(config_parse_resolv_conf); +CONFIG_PARSER_PROTOTYPE(config_parse_link_journal); +CONFIG_PARSER_PROTOTYPE(config_parse_timezone); + +const char *resolv_conf_mode_to_string(ResolvConfMode a) _const_; +ResolvConfMode resolv_conf_mode_from_string(const char *s) _pure_; + +const char *timezone_mode_to_string(TimezoneMode a) _const_; +TimezoneMode timezone_mode_from_string(const char *s) _pure_; + +int parse_link_journal(const char *s, LinkJournal *ret_mode, bool *ret_try); + +void device_node_array_free(DeviceNode *node, size_t n); diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c new file mode 100644 index 00000000..cb2b2272 --- /dev/null +++ b/src/nspawn/nspawn-setuid.c @@ -0,0 +1,243 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "def.h" +#include "errno.h" +#include "fd-util.h" +#include "fileio.h" +#include "mkdir.h" +#include "nspawn-setuid.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "signal-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" + +static int spawn_getent(const char *database, const char *key, pid_t *rpid) { + int pipe_fds[2], r; + pid_t pid; + + assert(database); + assert(key); + assert(rpid); + + if (pipe2(pipe_fds, O_CLOEXEC) < 0) + return log_error_errno(errno, "Failed to allocate pipe: %m"); + + r = safe_fork("(getent)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid); + if (r < 0) { + safe_close_pair(pipe_fds); + return r; + } + if (r == 0) { + char *empty_env = NULL; + + safe_close(pipe_fds[0]); + + if (rearrange_stdio(-1, pipe_fds[1], -1) < 0) + _exit(EXIT_FAILURE); + + (void) close_all_fds(NULL, 0); + + (void) rlimit_nofile_safe(); + + execle("/usr/bin/getent", "getent", database, key, NULL, &empty_env); + execle("/bin/getent", "getent", database, key, NULL, &empty_env); + _exit(EXIT_FAILURE); + } + + pipe_fds[1] = safe_close(pipe_fds[1]); + + *rpid = pid; + + return pipe_fds[0]; +} + +int change_uid_gid_raw( + uid_t uid, + gid_t gid, + const gid_t *supplementary_gids, + size_t n_supplementary_gids) { + + if (!uid_is_valid(uid)) + uid = 0; + if (!gid_is_valid(gid)) + gid = 0; + + (void) fchown(STDIN_FILENO, uid, gid); + (void) fchown(STDOUT_FILENO, uid, gid); + (void) fchown(STDERR_FILENO, uid, gid); + + if (setgroups(n_supplementary_gids, supplementary_gids) < 0) + return log_error_errno(errno, "Failed to set auxiliary groups: %m"); + + if (setresgid(gid, gid, gid) < 0) + return log_error_errno(errno, "setresgid() failed: %m"); + + if (setresuid(uid, uid, uid) < 0) + return log_error_errno(errno, "setresuid() failed: %m"); + + return 0; +} + +int change_uid_gid(const char *user, char **_home) { + char *x, *u, *g, *h; + const char *word, *state; + _cleanup_free_ gid_t *gids = NULL; + _cleanup_free_ char *home = NULL, *line = NULL; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_close_ int fd = -1; + unsigned n_gids = 0; + size_t sz = 0, l; + uid_t uid; + gid_t gid; + pid_t pid; + int r; + + assert(_home); + + if (!user || STR_IN_SET(user, "root", "0")) { + /* Reset everything fully to 0, just in case */ + + r = reset_uid_gid(); + if (r < 0) + return log_error_errno(r, "Failed to become root: %m"); + + *_home = NULL; + return 0; + } + + /* First, get user credentials */ + fd = spawn_getent("passwd", user, &pid); + if (fd < 0) + return fd; + + f = fdopen(fd, "r"); + if (!f) + return log_oom(); + fd = -1; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), + "Failed to resolve user %s.", user); + if (r < 0) + return log_error_errno(r, "Failed to read from getent: %m"); + + (void) wait_for_terminate_and_check("getent passwd", pid, WAIT_LOG); + + x = strchr(line, ':'); + if (!x) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "/etc/passwd entry has invalid user field."); + + u = strchr(x+1, ':'); + if (!u) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "/etc/passwd entry has invalid password field."); + + u++; + g = strchr(u, ':'); + if (!g) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "/etc/passwd entry has invalid UID field."); + + *g = 0; + g++; + x = strchr(g, ':'); + if (!x) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "/etc/passwd entry has invalid GID field."); + + *x = 0; + h = strchr(x+1, ':'); + if (!h) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "/etc/passwd entry has invalid GECOS field."); + + h++; + x = strchr(h, ':'); + if (!x) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "/etc/passwd entry has invalid home directory field."); + + *x = 0; + + r = parse_uid(u, &uid); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Failed to parse UID of user."); + + r = parse_gid(g, &gid); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Failed to parse GID of user."); + + home = strdup(h); + if (!home) + return log_oom(); + + f = safe_fclose(f); + line = mfree(line); + + /* Second, get group memberships */ + fd = spawn_getent("initgroups", user, &pid); + if (fd < 0) + return fd; + + f = fdopen(fd, "r"); + if (!f) + return log_oom(); + fd = -1; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), + "Failed to resolve user %s.", user); + if (r < 0) + return log_error_errno(r, "Failed to read from getent: %m"); + + (void) wait_for_terminate_and_check("getent initgroups", pid, WAIT_LOG); + + /* Skip over the username and subsequent separator whitespace */ + x = line; + x += strcspn(x, WHITESPACE); + x += strspn(x, WHITESPACE); + + FOREACH_WORD(word, l, x, state) { + char c[l+1]; + + memcpy(c, word, l); + c[l] = 0; + + if (!GREEDY_REALLOC(gids, sz, n_gids+1)) + return log_oom(); + + r = parse_gid(c, &gids[n_gids++]); + if (r < 0) + return log_error_errno(r, "Failed to parse group data from getent: %m"); + } + + r = mkdir_parents(home, 0775); + if (r < 0) + return log_error_errno(r, "Failed to make home root directory: %m"); + + r = mkdir_safe(home, 0755, uid, gid, 0); + if (r < 0 && !IN_SET(r, -EEXIST, -ENOTDIR)) + return log_error_errno(r, "Failed to make home directory: %m"); + + r = change_uid_gid_raw(uid, gid, gids, n_gids); + if (r < 0) + return r; + + if (_home) + *_home = TAKE_PTR(home); + + return 0; +} diff --git a/src/nspawn/nspawn-setuid.h b/src/nspawn/nspawn-setuid.h new file mode 100644 index 00000000..9a2b05eb --- /dev/null +++ b/src/nspawn/nspawn-setuid.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int change_uid_gid_raw(uid_t uid, gid_t gid, const gid_t *supplementary_gids, size_t n_supplementary_gids); +int change_uid_gid(const char *user, char **ret_home); diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c new file mode 100644 index 00000000..d86dd231 --- /dev/null +++ b/src/nspawn/nspawn-stub-pid1.c @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "def.h" +#include "exit-status.h" +#include "fd-util.h" +#include "log.h" +#include "nspawn-stub-pid1.h" +#include "process-util.h" +#include "signal-util.h" +#include "time-util.h" + +static int reset_environ(const char *new_environment, size_t length) { + unsigned long start, end; + + start = (unsigned long) new_environment; + end = start + length; + + if (prctl(PR_SET_MM, PR_SET_MM_ENV_START, start, 0, 0) < 0) + return -errno; + + if (prctl(PR_SET_MM, PR_SET_MM_ENV_END, end, 0, 0) < 0) + return -errno; + + return 0; +} + +int stub_pid1(sd_id128_t uuid) { + enum { + STATE_RUNNING, + STATE_REBOOT, + STATE_POWEROFF, + } state = STATE_RUNNING; + + sigset_t fullmask, oldmask, waitmask; + usec_t quit_usec = USEC_INFINITY; + pid_t pid; + int r; + + /* The new environment we set up, on the stack. */ + char new_environment[] = + "container=systemd-nspawn\0" + "container_uuid=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; + + /* Implements a stub PID 1, that reaps all processes and processes a couple of standard signals. This is useful + * for allowing arbitrary processes run in a container, and still have all zombies reaped. */ + + assert_se(sigfillset(&fullmask) >= 0); + assert_se(sigprocmask(SIG_BLOCK, &fullmask, &oldmask) >= 0); + + /* Surrender the terminal this stub may control so that child processes can have a controlling terminal + * without resorting to setsid hacks. */ + r = ioctl(STDIN_FILENO, TIOCNOTTY); + if (r < 0 && errno != ENOTTY) + return log_error_errno(errno, "Failed to surrender controlling terminal: %m"); + + pid = fork(); + if (pid < 0) + return log_error_errno(errno, "Failed to fork child pid: %m"); + + if (pid == 0) { + /* Return in the child */ + assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0); + setsid(); + return 0; + } + + reset_all_signal_handlers(); + + log_close(); + (void) close_all_fds(NULL, 0); + log_open(); + + /* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also, + * set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ + * find them set. */ + sd_id128_to_string(uuid, new_environment + sizeof(new_environment) - SD_ID128_STRING_MAX); + reset_environ(new_environment, sizeof(new_environment)); + + (void) rename_process("(sd-stubinit)"); + + assert_se(sigemptyset(&waitmask) >= 0); + assert_se(sigset_add_many(&waitmask, + SIGCHLD, /* posix: process died */ + SIGINT, /* sysv: ctrl-alt-del */ + SIGRTMIN+3, /* systemd: halt */ + SIGRTMIN+4, /* systemd: poweroff */ + SIGRTMIN+5, /* systemd: reboot */ + SIGRTMIN+6, /* systemd: kexec */ + SIGRTMIN+13, /* systemd: halt */ + SIGRTMIN+14, /* systemd: poweroff */ + SIGRTMIN+15, /* systemd: reboot */ + SIGRTMIN+16, /* systemd: kexec */ + -1) >= 0); + + /* Note that we ignore SIGTERM (sysv's reexec), SIGHUP (reload), and all other signals here, since we don't + * support reexec/reloading in this stub process. */ + + for (;;) { + siginfo_t si; + usec_t current_usec; + + si.si_pid = 0; + r = waitid(P_ALL, 0, &si, WEXITED|WNOHANG); + if (r < 0) { + r = log_error_errno(errno, "Failed to reap children: %m"); + goto finish; + } + + current_usec = now(CLOCK_MONOTONIC); + + if (si.si_pid == pid || current_usec >= quit_usec) { + + /* The child we started ourselves died or we reached a timeout. */ + + if (state == STATE_REBOOT) { /* dispatch a queued reboot */ + (void) reboot(RB_AUTOBOOT); + r = log_error_errno(errno, "Failed to reboot: %m"); + goto finish; + + } else if (state == STATE_POWEROFF) + (void) reboot(RB_POWER_OFF); /* if this fails, fall back to normal exit. */ + + if (si.si_pid == pid && si.si_code == CLD_EXITED) + r = si.si_status; /* pass on exit code */ + else + r = EXIT_EXCEPTION; /* signal, coredump, timeout, … */ + + goto finish; + } + if (si.si_pid != 0) + /* We reaped something. Retry until there's nothing more to reap. */ + continue; + + if (quit_usec == USEC_INFINITY) + r = sigwaitinfo(&waitmask, &si); + else { + struct timespec ts; + r = sigtimedwait(&waitmask, &si, timespec_store(&ts, quit_usec - current_usec)); + } + if (r < 0) { + if (errno == EINTR) /* strace -p attach can result in EINTR, let's handle this nicely. */ + continue; + if (errno == EAGAIN) /* timeout reached */ + continue; + + r = log_error_errno(errno, "Failed to wait for signal: %m"); + goto finish; + } + + if (si.si_signo == SIGCHLD) + continue; /* Let's reap this */ + + if (state != STATE_RUNNING) + continue; + + /* Would love to use a switch() statement here, but SIGRTMIN is actually a function call, not a + * constant… */ + + if (si.si_signo == SIGRTMIN+3 || + si.si_signo == SIGRTMIN+4 || + si.si_signo == SIGRTMIN+13 || + si.si_signo == SIGRTMIN+14) + + state = STATE_POWEROFF; + + else if (si.si_signo == SIGINT || + si.si_signo == SIGRTMIN+5 || + si.si_signo == SIGRTMIN+6 || + si.si_signo == SIGRTMIN+15 || + si.si_signo == SIGRTMIN+16) + + state = STATE_REBOOT; + else + assert_not_reached("Got unexpected signal"); + + r = kill_and_sigcont(pid, SIGTERM); + + /* Let's send a SIGHUP after the SIGTERM, as shells tend to ignore SIGTERM but do react to SIGHUP. We + * do it strictly in this order, so that the SIGTERM is dispatched first, and SIGHUP second for those + * processes which handle both. That's because services tend to bind configuration reload or something + * else to SIGHUP. */ + + if (r != -ESRCH) + (void) kill(pid, SIGHUP); + + quit_usec = now(CLOCK_MONOTONIC) + DEFAULT_TIMEOUT_USEC; + } + +finish: + _exit(r < 0 ? EXIT_FAILURE : r); +} diff --git a/src/nspawn/nspawn-stub-pid1.h b/src/nspawn/nspawn-stub-pid1.h new file mode 100644 index 00000000..8982d503 --- /dev/null +++ b/src/nspawn/nspawn-stub-pid1.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-id128.h" + +int stub_pid1(sd_id128_t uuid); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c new file mode 100644 index 00000000..873a7659 --- /dev/null +++ b/src/nspawn/nspawn.c @@ -0,0 +1,5171 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if HAVE_BLKID +#endif +#include +#include +#include +#include +#if HAVE_SELINUX +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-daemon.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "barrier.h" +#include "base-filesystem.h" +#include "blkid-util.h" +#include "btrfs-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "cap-list.h" +#include "capability-util.h" +#include "cgroup-util.h" +#include "copy.h" +#include "cpu-set-util.h" +#include "dev-setup.h" +#include "dissect-image.h" +#include "env-util.h" +#include "fd-util.h" +#include "fdset.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "gpt.h" +#include "hexdecoct.h" +#include "hostname-util.h" +#include "id128-util.h" +#include "log.h" +#include "loop-util.h" +#include "loopback-setup.h" +#include "machine-image.h" +#include "macro.h" +#include "main-func.h" +#include "missing_sched.h" +#include "mkdir.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "namespace-util.h" +#include "netlink-util.h" +#include "nspawn-cgroup.h" +#include "nspawn-def.h" +#include "nspawn-expose-ports.h" +#include "nspawn-mount.h" +#include "nspawn-network.h" +#include "nspawn-oci.h" +#include "nspawn-patch-uid.h" +#include "nspawn-register.h" +#include "nspawn-seccomp.h" +#include "nspawn-settings.h" +#include "nspawn-setuid.h" +#include "nspawn-stub-pid1.h" +#include "nulstr-util.h" +#include "os-util.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "process-util.h" +#include "ptyfwd.h" +#include "random-util.h" +#include "raw-clone.h" +#include "rlimit-util.h" +#include "rm-rf.h" +#if HAVE_SECCOMP +#include "seccomp-util.h" +#endif +#include "selinux-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "sysctl-util.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "umask-util.h" +#include "unit-name.h" +#include "user-util.h" +#include "util.h" + +#if HAVE_SPLIT_USR +#define STATIC_RESOLV_CONF "/lib/systemd/resolv.conf" +#else +#define STATIC_RESOLV_CONF "/usr/lib/systemd/resolv.conf" +#endif + +/* nspawn is listening on the socket at the path in the constant nspawn_notify_socket_path + * nspawn_notify_socket_path is relative to the container + * the init process in the container pid can send messages to nspawn following the sd_notify(3) protocol */ +#define NSPAWN_NOTIFY_SOCKET_PATH "/run/systemd/nspawn/notify" + +#define EXIT_FORCE_RESTART 133 + +typedef enum ContainerStatus { + CONTAINER_TERMINATED, + CONTAINER_REBOOTED, +} ContainerStatus; + +static char *arg_directory = NULL; +static char *arg_template = NULL; +static char *arg_chdir = NULL; +static char *arg_pivot_root_new = NULL; +static char *arg_pivot_root_old = NULL; +static char *arg_user = NULL; +static uid_t arg_uid = UID_INVALID; +static gid_t arg_gid = GID_INVALID; +static gid_t* arg_supplementary_gids = NULL; +static size_t arg_n_supplementary_gids = 0; +static sd_id128_t arg_uuid = {}; +static char *arg_machine = NULL; /* The name used by the host to refer to this */ +static char *arg_hostname = NULL; /* The name the payload sees by default */ +static const char *arg_selinux_context = NULL; +static const char *arg_selinux_apifs_context = NULL; +static char *arg_slice = NULL; +static bool arg_private_network = false; +static bool arg_read_only = false; +static StartMode arg_start_mode = START_PID1; +static bool arg_ephemeral = false; +static LinkJournal arg_link_journal = LINK_AUTO; +static bool arg_link_journal_try = false; +static uint64_t arg_caps_retain = + (1ULL << CAP_AUDIT_CONTROL) | + (1ULL << CAP_AUDIT_WRITE) | + (1ULL << CAP_CHOWN) | + (1ULL << CAP_DAC_OVERRIDE) | + (1ULL << CAP_DAC_READ_SEARCH) | + (1ULL << CAP_FOWNER) | + (1ULL << CAP_FSETID) | + (1ULL << CAP_IPC_OWNER) | + (1ULL << CAP_KILL) | + (1ULL << CAP_LEASE) | + (1ULL << CAP_LINUX_IMMUTABLE) | + (1ULL << CAP_MKNOD) | + (1ULL << CAP_NET_BIND_SERVICE) | + (1ULL << CAP_NET_BROADCAST) | + (1ULL << CAP_NET_RAW) | + (1ULL << CAP_SETFCAP) | + (1ULL << CAP_SETGID) | + (1ULL << CAP_SETPCAP) | + (1ULL << CAP_SETUID) | + (1ULL << CAP_SYS_ADMIN) | + (1ULL << CAP_SYS_BOOT) | + (1ULL << CAP_SYS_CHROOT) | + (1ULL << CAP_SYS_NICE) | + (1ULL << CAP_SYS_PTRACE) | + (1ULL << CAP_SYS_RESOURCE) | + (1ULL << CAP_SYS_TTY_CONFIG); +static CapabilityQuintet arg_full_capabilities = CAPABILITY_QUINTET_NULL; +static CustomMount *arg_custom_mounts = NULL; +static size_t arg_n_custom_mounts = 0; +static char **arg_setenv = NULL; +static bool arg_quiet = false; +static bool arg_register = true; +static bool arg_keep_unit = false; +static char **arg_network_interfaces = NULL; +static char **arg_network_macvlan = NULL; +static char **arg_network_ipvlan = NULL; +static bool arg_network_veth = false; +static char **arg_network_veth_extra = NULL; +static char *arg_network_bridge = NULL; +static char *arg_network_zone = NULL; +static char *arg_network_namespace_path = NULL; +static PagerFlags arg_pager_flags = 0; +static unsigned long arg_personality = PERSONALITY_INVALID; +static char *arg_image = NULL; +static char *arg_oci_bundle = NULL; +static VolatileMode arg_volatile_mode = VOLATILE_NO; +static ExposePort *arg_expose_ports = NULL; +static char **arg_property = NULL; +static sd_bus_message *arg_property_message = NULL; +static UserNamespaceMode arg_userns_mode = USER_NAMESPACE_NO; +static uid_t arg_uid_shift = UID_INVALID, arg_uid_range = 0x10000U; +static bool arg_userns_chown = false; +static int arg_kill_signal = 0; +static CGroupUnified arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_UNKNOWN; +static SettingsMask arg_settings_mask = 0; +static int arg_settings_trusted = -1; +static char **arg_parameters = NULL; +static const char *arg_container_service_name = "systemd-nspawn"; +static bool arg_notify_ready = false; +static bool arg_use_cgns = true; +static unsigned long arg_clone_ns_flags = CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS; +static MountSettingsMask arg_mount_settings = MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_TMPFS_TMP; +static void *arg_root_hash = NULL; +static size_t arg_root_hash_size = 0; +static char **arg_syscall_whitelist = NULL; +static char **arg_syscall_blacklist = NULL; +#if HAVE_SECCOMP +static scmp_filter_ctx arg_seccomp = NULL; +#endif +static struct rlimit *arg_rlimit[_RLIMIT_MAX] = {}; +static bool arg_no_new_privileges = false; +static int arg_oom_score_adjust = 0; +static bool arg_oom_score_adjust_set = false; +static CPUSet arg_cpu_set = {}; +static ResolvConfMode arg_resolv_conf = RESOLV_CONF_AUTO; +static TimezoneMode arg_timezone = TIMEZONE_AUTO; +static unsigned arg_console_width = (unsigned) -1, arg_console_height = (unsigned) -1; +static DeviceNode* arg_extra_nodes = NULL; +static size_t arg_n_extra_nodes = 0; +static char **arg_sysctl = NULL; +static ConsoleMode arg_console_mode = _CONSOLE_MODE_INVALID; + +STATIC_DESTRUCTOR_REGISTER(arg_directory, freep); +STATIC_DESTRUCTOR_REGISTER(arg_template, freep); +STATIC_DESTRUCTOR_REGISTER(arg_chdir, freep); +STATIC_DESTRUCTOR_REGISTER(arg_pivot_root_new, freep); +STATIC_DESTRUCTOR_REGISTER(arg_pivot_root_old, freep); +STATIC_DESTRUCTOR_REGISTER(arg_user, freep); +STATIC_DESTRUCTOR_REGISTER(arg_supplementary_gids, freep); +STATIC_DESTRUCTOR_REGISTER(arg_machine, freep); +STATIC_DESTRUCTOR_REGISTER(arg_hostname, freep); +STATIC_DESTRUCTOR_REGISTER(arg_slice, freep); +STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_network_interfaces, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_network_macvlan, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_network_ipvlan, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_network_veth_extra, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_network_bridge, freep); +STATIC_DESTRUCTOR_REGISTER(arg_network_zone, freep); +STATIC_DESTRUCTOR_REGISTER(arg_network_namespace_path, freep); +STATIC_DESTRUCTOR_REGISTER(arg_image, freep); +STATIC_DESTRUCTOR_REGISTER(arg_oci_bundle, freep); +STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_property_message, sd_bus_message_unrefp); +STATIC_DESTRUCTOR_REGISTER(arg_parameters, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep); +STATIC_DESTRUCTOR_REGISTER(arg_syscall_whitelist, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_syscall_blacklist, strv_freep); +#if HAVE_SECCOMP +STATIC_DESTRUCTOR_REGISTER(arg_seccomp, seccomp_releasep); +#endif +STATIC_DESTRUCTOR_REGISTER(arg_cpu_set, cpu_set_reset); +STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep); + +static int handle_arg_console(const char *arg) { + if (streq(arg, "help")) { + puts("interactive\n" + "read-only\n" + "passive\n" + "pipe"); + return 0; + } + + if (streq(arg, "interactive")) + arg_console_mode = CONSOLE_INTERACTIVE; + else if (streq(arg, "read-only")) + arg_console_mode = CONSOLE_READ_ONLY; + else if (streq(arg, "passive")) + arg_console_mode = CONSOLE_PASSIVE; + else if (streq(arg, "pipe")) + arg_console_mode = CONSOLE_PIPE; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg); + + arg_settings_mask |= SETTING_CONSOLE_MODE; + return 1; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + (void) pager_open(arg_pager_flags); + + r = terminal_urlify_man("systemd-nspawn", "1", &link); + if (r < 0) + return log_oom(); + + printf("%1$s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n" + "%5$sSpawn a command or OS in a light-weight container.%6$s\n\n" + " -h --help Show this help\n" + " --version Print version string\n" + " -q --quiet Do not show status information\n" + " --no-pager Do not pipe output into a pager\n" + " --settings=BOOLEAN Load additional settings from .nspawn file\n\n" + "%3$sImage:%4$s\n" + " -D --directory=PATH Root directory for the container\n" + " --template=PATH Initialize root directory from template directory,\n" + " if missing\n" + " -x --ephemeral Run container with snapshot of root directory, and\n" + " remove it after exit\n" + " -i --image=PATH Root file system disk image (or device node) for\n" + " the container\n" + " --oci-bundle=PATH OCI bundle directory\n" + " --read-only Mount the root directory read-only\n" + " --volatile[=MODE] Run the system in volatile mode\n" + " --root-hash=HASH Specify verity root hash for root disk image\n" + " --pivot-root=PATH[:PATH]\n" + " Pivot root to given directory in the container\n\n" + "%3$sExecution:%4$s\n" + " -a --as-pid2 Maintain a stub init as PID1, invoke binary as PID2\n" + " -b --boot Boot up full system (i.e. invoke init)\n" + " --chdir=PATH Set working directory in the container\n" + " -E --setenv=NAME=VALUE Pass an environment variable to PID 1\n" + " -u --user=USER Run the command under specified user or UID\n" + " --kill-signal=SIGNAL Select signal to use for shutting down PID 1\n" + " --notify-ready=BOOLEAN Receive notifications from the child init process\n\n" + "%3$sSystem Identity:%4$s\n" + " -M --machine=NAME Set the machine name for the container\n" + " --hostname=NAME Override the hostname for the container\n" + " --uuid=UUID Set a specific machine UUID for the container\n\n" + "%3$sProperties:%4$s\n" + " -S --slice=SLICE Place the container in the specified slice\n" + " --property=NAME=VALUE Set scope unit property\n" + " --register=BOOLEAN Register container as machine\n" + " --keep-unit Do not register a scope for the machine, reuse\n" + " the service unit nspawn is running in\n\n" + "%3$sUser Namespacing:%4$s\n" + " -U --private-users=pick Run within user namespace, autoselect UID/GID range\n" + " --private-users[=UIDBASE[:NUIDS]]\n" + " Similar, but with user configured UID/GID range\n" + " --private-users-chown Adjust OS tree ownership to private UID/GID range\n\n" + "%3$sNetworking:%4$s\n" + " --private-network Disable network in container\n" + " --network-interface=INTERFACE\n" + " Assign an existing network interface to the\n" + " container\n" + " --network-macvlan=INTERFACE\n" + " Create a macvlan network interface based on an\n" + " existing network interface to the container\n" + " --network-ipvlan=INTERFACE\n" + " Create a ipvlan network interface based on an\n" + " existing network interface to the container\n" + " -n --network-veth Add a virtual Ethernet connection between host\n" + " and container\n" + " --network-veth-extra=HOSTIF[:CONTAINERIF]\n" + " Add an additional virtual Ethernet link between\n" + " host and container\n" + " --network-bridge=INTERFACE\n" + " Add a virtual Ethernet connection to the container\n" + " and attach it to an existing bridge on the host\n" + " --network-zone=NAME Similar, but attach the new interface to an\n" + " an automatically managed bridge interface\n" + " --network-namespace-path=PATH\n" + " Set network namespace to the one represented by\n" + " the specified kernel namespace file node\n" + " -p --port=[PROTOCOL:]HOSTPORT[:CONTAINERPORT]\n" + " Expose a container IP port on the host\n\n" + "%3$sSecurity:%4$s\n" + " --capability=CAP In addition to the default, retain specified\n" + " capability\n" + " --drop-capability=CAP Drop the specified capability from the default set\n" + " --no-new-privileges Set PR_SET_NO_NEW_PRIVS flag for container payload\n" + " --system-call-filter=LIST|~LIST\n" + " Permit/prohibit specific system calls\n" + " -Z --selinux-context=SECLABEL\n" + " Set the SELinux security context to be used by\n" + " processes in the container\n" + " -L --selinux-apifs-context=SECLABEL\n" + " Set the SELinux security context to be used by\n" + " API/tmpfs file systems in the container\n\n" + "%3$sResources:%4$s\n" + " --rlimit=NAME=LIMIT Set a resource limit for the payload\n" + " --oom-score-adjust=VALUE\n" + " Adjust the OOM score value for the payload\n" + " --cpu-affinity=CPUS Adjust the CPU affinity of the container\n" + " --personality=ARCH Pick personality for this container\n\n" + "%3$sIntegration:%4$s\n" + " --resolv-conf=MODE Select mode of /etc/resolv.conf initialization\n" + " --timezone=MODE Select mode of /etc/localtime initialization\n" + " --link-journal=MODE Link up guest journal, one of no, auto, guest, \n" + " host, try-guest, try-host\n" + " -j Equivalent to --link-journal=try-guest\n\n" + "%3$sMounts:%4$s\n" + " --bind=PATH[:PATH[:OPTIONS]]\n" + " Bind mount a file or directory from the host into\n" + " the container\n" + " --bind-ro=PATH[:PATH[:OPTIONS]\n" + " Similar, but creates a read-only bind mount\n" + " --inaccessible=PATH Over-mount file node with inaccessible node to mask\n" + " it\n" + " --tmpfs=PATH:[OPTIONS] Mount an empty tmpfs to the specified directory\n" + " --overlay=PATH[:PATH...]:PATH\n" + " Create an overlay mount from the host to \n" + " the container\n" + " --overlay-ro=PATH[:PATH...]:PATH\n" + " Similar, but creates a read-only overlay mount\n\n" + "%3$sInput/Output:%4$s\n" + " --console=MODE Select how stdin/stdout/stderr and /dev/console are\n" + " set up for the container.\n" + " -P --pipe Equivalent to --console=pipe\n" + "\nSee the %2$s for details.\n" + , program_invocation_short_name + , link + , ansi_underline(), ansi_normal() + , ansi_highlight(), ansi_normal() + ); + + return 0; +} + +static int custom_mount_check_all(void) { + size_t i; + + for (i = 0; i < arg_n_custom_mounts; i++) { + CustomMount *m = &arg_custom_mounts[i]; + + if (path_equal(m->destination, "/") && arg_userns_mode != USER_NAMESPACE_NO) { + if (arg_userns_chown) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--private-users-chown may not be combined with custom root mounts."); + else if (arg_uid_shift == UID_INVALID) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--private-users with automatic UID shift may not be combined with custom root mounts."); + } + } + + return 0; +} + +static int detect_unified_cgroup_hierarchy_from_environment(void) { + const char *e, *var = "SYSTEMD_NSPAWN_UNIFIED_HIERARCHY"; + int r; + + /* Allow the user to control whether the unified hierarchy is used */ + + e = getenv(var); + if (!e) { + /* $UNIFIED_CGROUP_HIERARCHY has been renamed to $SYSTEMD_NSPAWN_UNIFIED_HIERARCHY. */ + var = "UNIFIED_CGROUP_HIERARCHY"; + e = getenv(var); + } + + if (!isempty(e)) { + r = parse_boolean(e); + if (r < 0) + return log_error_errno(r, "Failed to parse $%s: %m", var); + if (r > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; + else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; + } + + return 0; +} + +static int detect_unified_cgroup_hierarchy_from_image(const char *directory) { + int r; + + /* Let's inherit the mode to use from the host system, but let's take into consideration what systemd + * in the image actually supports. */ + r = cg_all_unified(); + if (r < 0) + return log_error_errno(r, "Failed to determine whether we are in all unified mode."); + if (r > 0) { + /* Unified cgroup hierarchy support was added in 230. Unfortunately the detection + * routine only detects 231, so we'll have a false negative here for 230. */ + r = systemd_installation_has_version(directory, 230); + if (r < 0) + return log_error_errno(r, "Failed to determine systemd version in container: %m"); + if (r > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; + else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; + } else if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0) { + /* Mixed cgroup hierarchy support was added in 233 */ + r = systemd_installation_has_version(directory, 233); + if (r < 0) + return log_error_errno(r, "Failed to determine systemd version in container: %m"); + if (r > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_SYSTEMD; + else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; + } else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; + + log_debug("Using %s hierarchy for container.", + arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_NONE ? "legacy" : + arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_SYSTEMD ? "hybrid" : "unified"); + + return 0; +} + +static int parse_capability_spec(const char *spec, uint64_t *ret_mask) { + uint64_t mask = 0; + int r; + + for (;;) { + _cleanup_free_ char *t = NULL; + + r = extract_first_word(&spec, &t, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse capability %s.", t); + if (r == 0) + break; + + if (streq(t, "help")) { + for (int i = 0; i < capability_list_length(); i++) { + const char *name; + + name = capability_to_name(i); + if (name) + puts(name); + } + + return 0; /* quit */ + } + + if (streq(t, "all")) + mask = (uint64_t) -1; + else { + r = capability_from_name(t); + if (r < 0) + return log_error_errno(r, "Failed to parse capability %s.", t); + + mask |= 1ULL << r; + } + } + + *ret_mask = mask; + return 1; /* continue */ +} + +static int parse_share_ns_env(const char *name, unsigned long ns_flag) { + int r; + + r = getenv_bool(name); + if (r == -ENXIO) + return 0; + if (r < 0) + return log_error_errno(r, "Failed to parse $%s: %m", name); + + arg_clone_ns_flags = (arg_clone_ns_flags & ~ns_flag) | (r > 0 ? 0 : ns_flag); + arg_settings_mask |= SETTING_CLONE_NS_FLAGS; + return 0; +} + +static int parse_mount_settings_env(void) { + const char *e; + int r; + + r = getenv_bool("SYSTEMD_NSPAWN_TMPFS_TMP"); + if (r < 0 && r != -ENXIO) + return log_error_errno(r, "Failed to parse $SYSTEMD_NSPAWN_TMPFS_TMP: %m"); + if (r >= 0) + SET_FLAG(arg_mount_settings, MOUNT_APPLY_TMPFS_TMP, r > 0); + + e = getenv("SYSTEMD_NSPAWN_API_VFS_WRITABLE"); + if (streq_ptr(e, "network")) + arg_mount_settings |= MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_APIVFS_NETNS; + + else if (e) { + r = parse_boolean(e); + if (r < 0) + return log_error_errno(r, "Failed to parse $SYSTEMD_NSPAWN_API_VFS_WRITABLE: %m"); + + SET_FLAG(arg_mount_settings, MOUNT_APPLY_APIVFS_RO, r == 0); + SET_FLAG(arg_mount_settings, MOUNT_APPLY_APIVFS_NETNS, false); + } + + return 0; +} + +static int parse_environment(void) { + const char *e; + int r; + + r = parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_IPC", CLONE_NEWIPC); + if (r < 0) + return r; + r = parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_PID", CLONE_NEWPID); + if (r < 0) + return r; + r = parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_UTS", CLONE_NEWUTS); + if (r < 0) + return r; + r = parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_SYSTEM", CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS); + if (r < 0) + return r; + + r = parse_mount_settings_env(); + if (r < 0) + return r; + + /* SYSTEMD_NSPAWN_USE_CGNS=0 can be used to disable CLONE_NEWCGROUP use, + * even if it is supported. If not supported, it has no effect. */ + if (!cg_ns_supported()) + arg_use_cgns = false; + else { + r = getenv_bool("SYSTEMD_NSPAWN_USE_CGNS"); + if (r < 0) { + if (r != -ENXIO) + return log_error_errno(r, "Failed to parse $SYSTEMD_NSPAWN_USE_CGNS: %m"); + + arg_use_cgns = true; + } else { + arg_use_cgns = r > 0; + arg_settings_mask |= SETTING_USE_CGNS; + } + } + + e = getenv("SYSTEMD_NSPAWN_CONTAINER_SERVICE"); + if (e) + arg_container_service_name = e; + + return detect_unified_cgroup_hierarchy_from_environment(); +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_PRIVATE_NETWORK, + ARG_UUID, + ARG_READ_ONLY, + ARG_CAPABILITY, + ARG_DROP_CAPABILITY, + ARG_LINK_JOURNAL, + ARG_BIND, + ARG_BIND_RO, + ARG_TMPFS, + ARG_OVERLAY, + ARG_OVERLAY_RO, + ARG_INACCESSIBLE, + ARG_SHARE_SYSTEM, + ARG_REGISTER, + ARG_KEEP_UNIT, + ARG_NETWORK_INTERFACE, + ARG_NETWORK_MACVLAN, + ARG_NETWORK_IPVLAN, + ARG_NETWORK_BRIDGE, + ARG_NETWORK_ZONE, + ARG_NETWORK_VETH_EXTRA, + ARG_NETWORK_NAMESPACE_PATH, + ARG_PERSONALITY, + ARG_VOLATILE, + ARG_TEMPLATE, + ARG_PROPERTY, + ARG_PRIVATE_USERS, + ARG_KILL_SIGNAL, + ARG_SETTINGS, + ARG_CHDIR, + ARG_PIVOT_ROOT, + ARG_PRIVATE_USERS_CHOWN, + ARG_NOTIFY_READY, + ARG_ROOT_HASH, + ARG_SYSTEM_CALL_FILTER, + ARG_RLIMIT, + ARG_HOSTNAME, + ARG_NO_NEW_PRIVILEGES, + ARG_OOM_SCORE_ADJUST, + ARG_CPU_AFFINITY, + ARG_RESOLV_CONF, + ARG_TIMEZONE, + ARG_CONSOLE, + ARG_PIPE, + ARG_OCI_BUNDLE, + ARG_NO_PAGER, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "directory", required_argument, NULL, 'D' }, + { "template", required_argument, NULL, ARG_TEMPLATE }, + { "ephemeral", no_argument, NULL, 'x' }, + { "user", required_argument, NULL, 'u' }, + { "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK }, + { "as-pid2", no_argument, NULL, 'a' }, + { "boot", no_argument, NULL, 'b' }, + { "uuid", required_argument, NULL, ARG_UUID }, + { "read-only", no_argument, NULL, ARG_READ_ONLY }, + { "capability", required_argument, NULL, ARG_CAPABILITY }, + { "drop-capability", required_argument, NULL, ARG_DROP_CAPABILITY }, + { "no-new-privileges", required_argument, NULL, ARG_NO_NEW_PRIVILEGES }, + { "link-journal", required_argument, NULL, ARG_LINK_JOURNAL }, + { "bind", required_argument, NULL, ARG_BIND }, + { "bind-ro", required_argument, NULL, ARG_BIND_RO }, + { "tmpfs", required_argument, NULL, ARG_TMPFS }, + { "overlay", required_argument, NULL, ARG_OVERLAY }, + { "overlay-ro", required_argument, NULL, ARG_OVERLAY_RO }, + { "inaccessible", required_argument, NULL, ARG_INACCESSIBLE }, + { "machine", required_argument, NULL, 'M' }, + { "hostname", required_argument, NULL, ARG_HOSTNAME }, + { "slice", required_argument, NULL, 'S' }, + { "setenv", required_argument, NULL, 'E' }, + { "selinux-context", required_argument, NULL, 'Z' }, + { "selinux-apifs-context", required_argument, NULL, 'L' }, + { "quiet", no_argument, NULL, 'q' }, + { "share-system", no_argument, NULL, ARG_SHARE_SYSTEM }, /* not documented */ + { "register", required_argument, NULL, ARG_REGISTER }, + { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT }, + { "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE }, + { "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN }, + { "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN }, + { "network-veth", no_argument, NULL, 'n' }, + { "network-veth-extra", required_argument, NULL, ARG_NETWORK_VETH_EXTRA }, + { "network-bridge", required_argument, NULL, ARG_NETWORK_BRIDGE }, + { "network-zone", required_argument, NULL, ARG_NETWORK_ZONE }, + { "network-namespace-path", required_argument, NULL, ARG_NETWORK_NAMESPACE_PATH }, + { "personality", required_argument, NULL, ARG_PERSONALITY }, + { "image", required_argument, NULL, 'i' }, + { "volatile", optional_argument, NULL, ARG_VOLATILE }, + { "port", required_argument, NULL, 'p' }, + { "property", required_argument, NULL, ARG_PROPERTY }, + { "private-users", optional_argument, NULL, ARG_PRIVATE_USERS }, + { "private-users-chown", optional_argument, NULL, ARG_PRIVATE_USERS_CHOWN }, + { "kill-signal", required_argument, NULL, ARG_KILL_SIGNAL }, + { "settings", required_argument, NULL, ARG_SETTINGS }, + { "chdir", required_argument, NULL, ARG_CHDIR }, + { "pivot-root", required_argument, NULL, ARG_PIVOT_ROOT }, + { "notify-ready", required_argument, NULL, ARG_NOTIFY_READY }, + { "root-hash", required_argument, NULL, ARG_ROOT_HASH }, + { "system-call-filter", required_argument, NULL, ARG_SYSTEM_CALL_FILTER }, + { "rlimit", required_argument, NULL, ARG_RLIMIT }, + { "oom-score-adjust", required_argument, NULL, ARG_OOM_SCORE_ADJUST }, + { "cpu-affinity", required_argument, NULL, ARG_CPU_AFFINITY }, + { "resolv-conf", required_argument, NULL, ARG_RESOLV_CONF }, + { "timezone", required_argument, NULL, ARG_TIMEZONE }, + { "console", required_argument, NULL, ARG_CONSOLE }, + { "pipe", no_argument, NULL, ARG_PIPE }, + { "oci-bundle", required_argument, NULL, ARG_OCI_BUNDLE }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + {} + }; + + int c, r; + uint64_t plus = 0, minus = 0; + bool mask_all_settings = false, mask_no_settings = false; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "+hD:u:abL:M:jS:Z:qi:xp:nUE:P", options, NULL)) >= 0) + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case 'D': + r = parse_path_argument_and_warn(optarg, false, &arg_directory); + if (r < 0) + return r; + + arg_settings_mask |= SETTING_DIRECTORY; + break; + + case ARG_TEMPLATE: + r = parse_path_argument_and_warn(optarg, false, &arg_template); + if (r < 0) + return r; + + arg_settings_mask |= SETTING_DIRECTORY; + break; + + case 'i': + r = parse_path_argument_and_warn(optarg, false, &arg_image); + if (r < 0) + return r; + + arg_settings_mask |= SETTING_DIRECTORY; + break; + + case ARG_OCI_BUNDLE: + r = parse_path_argument_and_warn(optarg, false, &arg_oci_bundle); + if (r < 0) + return r; + + break; + + case 'x': + arg_ephemeral = true; + arg_settings_mask |= SETTING_EPHEMERAL; + break; + + case 'u': + r = free_and_strdup(&arg_user, optarg); + if (r < 0) + return log_oom(); + + arg_settings_mask |= SETTING_USER; + break; + + case ARG_NETWORK_ZONE: { + char *j; + + j = strjoin("vz-", optarg); + if (!j) + return log_oom(); + + if (!ifname_valid(j)) { + log_error("Network zone name not valid: %s", j); + free(j); + return -EINVAL; + } + + free_and_replace(arg_network_zone, j); + + arg_network_veth = true; + arg_private_network = true; + arg_settings_mask |= SETTING_NETWORK; + break; + } + + case ARG_NETWORK_BRIDGE: + + if (!ifname_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Bridge interface name not valid: %s", optarg); + + r = free_and_strdup(&arg_network_bridge, optarg); + if (r < 0) + return log_oom(); + + _fallthrough_; + case 'n': + arg_network_veth = true; + arg_private_network = true; + arg_settings_mask |= SETTING_NETWORK; + break; + + case ARG_NETWORK_VETH_EXTRA: + r = veth_extra_parse(&arg_network_veth_extra, optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --network-veth-extra= parameter: %s", optarg); + + arg_private_network = true; + arg_settings_mask |= SETTING_NETWORK; + break; + + case ARG_NETWORK_INTERFACE: + if (!ifname_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Network interface name not valid: %s", optarg); + + if (strv_extend(&arg_network_interfaces, optarg) < 0) + return log_oom(); + + arg_private_network = true; + arg_settings_mask |= SETTING_NETWORK; + break; + + case ARG_NETWORK_MACVLAN: + + if (!ifname_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "MACVLAN network interface name not valid: %s", optarg); + + if (strv_extend(&arg_network_macvlan, optarg) < 0) + return log_oom(); + + arg_private_network = true; + arg_settings_mask |= SETTING_NETWORK; + break; + + case ARG_NETWORK_IPVLAN: + + if (!ifname_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "IPVLAN network interface name not valid: %s", optarg); + + if (strv_extend(&arg_network_ipvlan, optarg) < 0) + return log_oom(); + + _fallthrough_; + case ARG_PRIVATE_NETWORK: + arg_private_network = true; + arg_settings_mask |= SETTING_NETWORK; + break; + + case ARG_NETWORK_NAMESPACE_PATH: + r = parse_path_argument_and_warn(optarg, false, &arg_network_namespace_path); + if (r < 0) + return r; + + arg_settings_mask |= SETTING_NETWORK; + break; + + case 'b': + if (arg_start_mode == START_PID2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--boot and --as-pid2 may not be combined."); + + arg_start_mode = START_BOOT; + arg_settings_mask |= SETTING_START_MODE; + break; + + case 'a': + if (arg_start_mode == START_BOOT) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--boot and --as-pid2 may not be combined."); + + arg_start_mode = START_PID2; + arg_settings_mask |= SETTING_START_MODE; + break; + + case ARG_UUID: + r = sd_id128_from_string(optarg, &arg_uuid); + if (r < 0) + return log_error_errno(r, "Invalid UUID: %s", optarg); + + if (sd_id128_is_null(arg_uuid)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Machine UUID may not be all zeroes."); + + arg_settings_mask |= SETTING_MACHINE_ID; + break; + + case 'S': { + _cleanup_free_ char *mangled = NULL; + + r = unit_name_mangle_with_suffix(optarg, NULL, UNIT_NAME_MANGLE_WARN, ".slice", &mangled); + if (r < 0) + return log_oom(); + + free_and_replace(arg_slice, mangled); + arg_settings_mask |= SETTING_SLICE; + break; + } + + case 'M': + if (isempty(optarg)) + arg_machine = mfree(arg_machine); + else { + if (!machine_name_is_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid machine name: %s", optarg); + + r = free_and_strdup(&arg_machine, optarg); + if (r < 0) + return log_oom(); + } + break; + + case ARG_HOSTNAME: + if (isempty(optarg)) + arg_hostname = mfree(arg_hostname); + else { + if (!hostname_is_valid(optarg, false)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid hostname: %s", optarg); + + r = free_and_strdup(&arg_hostname, optarg); + if (r < 0) + return log_oom(); + } + + arg_settings_mask |= SETTING_HOSTNAME; + break; + + case 'Z': + arg_selinux_context = optarg; + break; + + case 'L': + arg_selinux_apifs_context = optarg; + break; + + case ARG_READ_ONLY: + arg_read_only = true; + arg_settings_mask |= SETTING_READ_ONLY; + break; + + case ARG_CAPABILITY: + case ARG_DROP_CAPABILITY: { + uint64_t m; + r = parse_capability_spec(optarg, &m); + if (r <= 0) + return r; + + if (c == ARG_CAPABILITY) + plus |= m; + else + minus |= m; + arg_settings_mask |= SETTING_CAPABILITY; + break; + } + case ARG_NO_NEW_PRIVILEGES: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --no-new-privileges= argument: %s", optarg); + + arg_no_new_privileges = r; + arg_settings_mask |= SETTING_NO_NEW_PRIVILEGES; + break; + + case 'j': + arg_link_journal = LINK_GUEST; + arg_link_journal_try = true; + arg_settings_mask |= SETTING_LINK_JOURNAL; + break; + + case ARG_LINK_JOURNAL: + r = parse_link_journal(optarg, &arg_link_journal, &arg_link_journal_try); + if (r < 0) + return log_error_errno(r, "Failed to parse link journal mode %s", optarg); + + arg_settings_mask |= SETTING_LINK_JOURNAL; + break; + + case ARG_BIND: + case ARG_BIND_RO: + r = bind_mount_parse(&arg_custom_mounts, &arg_n_custom_mounts, optarg, c == ARG_BIND_RO); + if (r < 0) + return log_error_errno(r, "Failed to parse --bind(-ro)= argument %s: %m", optarg); + + arg_settings_mask |= SETTING_CUSTOM_MOUNTS; + break; + + case ARG_TMPFS: + r = tmpfs_mount_parse(&arg_custom_mounts, &arg_n_custom_mounts, optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --tmpfs= argument %s: %m", optarg); + + arg_settings_mask |= SETTING_CUSTOM_MOUNTS; + break; + + case ARG_OVERLAY: + case ARG_OVERLAY_RO: + r = overlay_mount_parse(&arg_custom_mounts, &arg_n_custom_mounts, optarg, c == ARG_OVERLAY_RO); + if (r == -EADDRNOTAVAIL) + return log_error_errno(r, "--overlay(-ro)= needs at least two colon-separated directories specified."); + if (r < 0) + return log_error_errno(r, "Failed to parse --overlay(-ro)= argument %s: %m", optarg); + + arg_settings_mask |= SETTING_CUSTOM_MOUNTS; + break; + + case ARG_INACCESSIBLE: + r = inaccessible_mount_parse(&arg_custom_mounts, &arg_n_custom_mounts, optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --inaccessible= argument %s: %m", optarg); + + arg_settings_mask |= SETTING_CUSTOM_MOUNTS; + break; + + case 'E': { + char **n; + + if (!env_assignment_is_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Environment variable assignment '%s' is not valid.", optarg); + + n = strv_env_set(arg_setenv, optarg); + if (!n) + return log_oom(); + + strv_free_and_replace(arg_setenv, n); + arg_settings_mask |= SETTING_ENVIRONMENT; + break; + } + + case 'q': + arg_quiet = true; + break; + + case ARG_SHARE_SYSTEM: + /* We don't officially support this anymore, except for compat reasons. People should use the + * $SYSTEMD_NSPAWN_SHARE_* environment variables instead. */ + log_warning("Please do not use --share-system anymore, use $SYSTEMD_NSPAWN_SHARE_* instead."); + arg_clone_ns_flags = 0; + break; + + case ARG_REGISTER: + r = parse_boolean(optarg); + if (r < 0) { + log_error("Failed to parse --register= argument: %s", optarg); + return r; + } + + arg_register = r; + break; + + case ARG_KEEP_UNIT: + arg_keep_unit = true; + break; + + case ARG_PERSONALITY: + + arg_personality = personality_from_string(optarg); + if (arg_personality == PERSONALITY_INVALID) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown or unsupported personality '%s'.", optarg); + + arg_settings_mask |= SETTING_PERSONALITY; + break; + + case ARG_VOLATILE: + + if (!optarg) + arg_volatile_mode = VOLATILE_YES; + else if (streq(optarg, "help")) { + DUMP_STRING_TABLE(volatile_mode, VolatileMode, _VOLATILE_MODE_MAX); + return 0; + } else { + VolatileMode m; + + m = volatile_mode_from_string(optarg); + if (m < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse --volatile= argument: %s", optarg); + else + arg_volatile_mode = m; + } + + arg_settings_mask |= SETTING_VOLATILE_MODE; + break; + + case 'p': + r = expose_port_parse(&arg_expose_ports, optarg); + if (r == -EEXIST) + return log_error_errno(r, "Duplicate port specification: %s", optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse host port %s: %m", optarg); + + arg_settings_mask |= SETTING_EXPOSE_PORTS; + break; + + case ARG_PROPERTY: + if (strv_extend(&arg_property, optarg) < 0) + return log_oom(); + + break; + + case ARG_PRIVATE_USERS: { + int boolean = -1; + + if (!optarg) + boolean = true; + else if (!in_charset(optarg, DIGITS)) + /* do *not* parse numbers as booleans */ + boolean = parse_boolean(optarg); + + if (boolean == false) { + /* no: User namespacing off */ + arg_userns_mode = USER_NAMESPACE_NO; + arg_uid_shift = UID_INVALID; + arg_uid_range = UINT32_C(0x10000); + } else if (boolean == true) { + /* yes: User namespacing on, UID range is read from root dir */ + arg_userns_mode = USER_NAMESPACE_FIXED; + arg_uid_shift = UID_INVALID; + arg_uid_range = UINT32_C(0x10000); + } else if (streq(optarg, "pick")) { + /* pick: User namespacing on, UID range is picked randomly */ + arg_userns_mode = USER_NAMESPACE_PICK; + arg_uid_shift = UID_INVALID; + arg_uid_range = UINT32_C(0x10000); + } else { + _cleanup_free_ char *buffer = NULL; + const char *range, *shift; + + /* anything else: User namespacing on, UID range is explicitly configured */ + + range = strchr(optarg, ':'); + if (range) { + buffer = strndup(optarg, range - optarg); + if (!buffer) + return log_oom(); + shift = buffer; + + range++; + r = safe_atou32(range, &arg_uid_range); + if (r < 0) + return log_error_errno(r, "Failed to parse UID range \"%s\": %m", range); + } else + shift = optarg; + + r = parse_uid(shift, &arg_uid_shift); + if (r < 0) + return log_error_errno(r, "Failed to parse UID \"%s\": %m", optarg); + + arg_userns_mode = USER_NAMESPACE_FIXED; + } + + if (arg_uid_range <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "UID range cannot be 0."); + + arg_settings_mask |= SETTING_USERNS; + break; + } + + case 'U': + if (userns_supported()) { + arg_userns_mode = USER_NAMESPACE_PICK; + arg_uid_shift = UID_INVALID; + arg_uid_range = UINT32_C(0x10000); + + arg_settings_mask |= SETTING_USERNS; + } + + break; + + case ARG_PRIVATE_USERS_CHOWN: + arg_userns_chown = true; + + arg_settings_mask |= SETTING_USERNS; + break; + + case ARG_KILL_SIGNAL: + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(signal, int, _NSIG); + return 0; + } + + arg_kill_signal = signal_from_string(optarg); + if (arg_kill_signal < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot parse signal: %s", optarg); + + arg_settings_mask |= SETTING_KILL_SIGNAL; + break; + + case ARG_SETTINGS: + + /* no → do not read files + * yes → read files, do not override cmdline, trust only subset + * override → read files, override cmdline, trust only subset + * trusted → read files, do not override cmdline, trust all + */ + + r = parse_boolean(optarg); + if (r < 0) { + if (streq(optarg, "trusted")) { + mask_all_settings = false; + mask_no_settings = false; + arg_settings_trusted = true; + + } else if (streq(optarg, "override")) { + mask_all_settings = false; + mask_no_settings = true; + arg_settings_trusted = -1; + } else + return log_error_errno(r, "Failed to parse --settings= argument: %s", optarg); + } else if (r > 0) { + /* yes */ + mask_all_settings = false; + mask_no_settings = false; + arg_settings_trusted = -1; + } else { + /* no */ + mask_all_settings = true; + mask_no_settings = false; + arg_settings_trusted = false; + } + + break; + + case ARG_CHDIR: + if (!path_is_absolute(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Working directory %s is not an absolute path.", optarg); + + r = free_and_strdup(&arg_chdir, optarg); + if (r < 0) + return log_oom(); + + arg_settings_mask |= SETTING_WORKING_DIRECTORY; + break; + + case ARG_PIVOT_ROOT: + r = pivot_root_parse(&arg_pivot_root_new, &arg_pivot_root_old, optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --pivot-root= argument %s: %m", optarg); + + arg_settings_mask |= SETTING_PIVOT_ROOT; + break; + + case ARG_NOTIFY_READY: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s is not a valid notify mode. Valid modes are: yes, no, and ready.", optarg); + arg_notify_ready = r; + arg_settings_mask |= SETTING_NOTIFY_READY; + break; + + case ARG_ROOT_HASH: { + void *k; + size_t l; + + r = unhexmem(optarg, strlen(optarg), &k, &l); + if (r < 0) + return log_error_errno(r, "Failed to parse root hash: %s", optarg); + if (l < sizeof(sd_id128_t)) { + free(k); + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Root hash must be at least 128bit long: %s", optarg); + } + + free(arg_root_hash); + arg_root_hash = k; + arg_root_hash_size = l; + break; + } + + case ARG_SYSTEM_CALL_FILTER: { + bool negative; + const char *items; + + negative = optarg[0] == '~'; + items = negative ? optarg + 1 : optarg; + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&items, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_error_errno(r, "Failed to parse system call filter: %m"); + + if (negative) + r = strv_extend(&arg_syscall_blacklist, word); + else + r = strv_extend(&arg_syscall_whitelist, word); + if (r < 0) + return log_oom(); + } + + arg_settings_mask |= SETTING_SYSCALL_FILTER; + break; + } + + case ARG_RLIMIT: { + const char *eq; + _cleanup_free_ char *name = NULL; + int rl; + + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(rlimit, int, _RLIMIT_MAX); + return 0; + } + + eq = strchr(optarg, '='); + if (!eq) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--rlimit= expects an '=' assignment."); + + name = strndup(optarg, eq - optarg); + if (!name) + return log_oom(); + + rl = rlimit_from_string_harder(name); + if (rl < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown resource limit: %s", name); + + if (!arg_rlimit[rl]) { + arg_rlimit[rl] = new0(struct rlimit, 1); + if (!arg_rlimit[rl]) + return log_oom(); + } + + r = rlimit_parse(rl, eq + 1, arg_rlimit[rl]); + if (r < 0) + return log_error_errno(r, "Failed to parse resource limit: %s", eq + 1); + + arg_settings_mask |= SETTING_RLIMIT_FIRST << rl; + break; + } + + case ARG_OOM_SCORE_ADJUST: + r = parse_oom_score_adjust(optarg, &arg_oom_score_adjust); + if (r < 0) + return log_error_errno(r, "Failed to parse --oom-score-adjust= parameter: %s", optarg); + + arg_oom_score_adjust_set = true; + arg_settings_mask |= SETTING_OOM_SCORE_ADJUST; + break; + + case ARG_CPU_AFFINITY: { + CPUSet cpuset; + + r = parse_cpu_set(optarg, &cpuset); + if (r < 0) + return log_error_errno(r, "Failed to parse CPU affinity mask %s: %m", optarg); + + cpu_set_reset(&arg_cpu_set); + arg_cpu_set = cpuset; + arg_settings_mask |= SETTING_CPU_AFFINITY; + break; + } + + case ARG_RESOLV_CONF: + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(resolv_conf_mode, ResolvConfMode, _RESOLV_CONF_MODE_MAX); + return 0; + } + + arg_resolv_conf = resolv_conf_mode_from_string(optarg); + if (arg_resolv_conf < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse /etc/resolv.conf mode: %s", optarg); + + arg_settings_mask |= SETTING_RESOLV_CONF; + break; + + case ARG_TIMEZONE: + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(timezone_mode, TimezoneMode, _TIMEZONE_MODE_MAX); + return 0; + } + + arg_timezone = timezone_mode_from_string(optarg); + if (arg_timezone < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse /etc/localtime mode: %s", optarg); + + arg_settings_mask |= SETTING_TIMEZONE; + break; + + case ARG_CONSOLE: + r = handle_arg_console(optarg); + if (r <= 0) + return r; + break; + + case 'P': + case ARG_PIPE: + r = handle_arg_console("pipe"); + if (r <= 0) + return r; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (argc > optind) { + strv_free(arg_parameters); + arg_parameters = strv_copy(argv + optind); + if (!arg_parameters) + return log_oom(); + + arg_settings_mask |= SETTING_START_MODE; + } + + if (arg_ephemeral && arg_template && !arg_directory) + /* User asked for ephemeral execution but specified --template= instead of --directory=. Semantically + * such an invocation makes some sense, see https://github.com/systemd/systemd/issues/3667. Let's + * accept this here, and silently make "--ephemeral --template=" equivalent to "--ephemeral + * --directory=". */ + arg_directory = TAKE_PTR(arg_template); + + arg_caps_retain = (arg_caps_retain | plus | (arg_private_network ? UINT64_C(1) << CAP_NET_ADMIN : 0)) & ~minus; + + /* Make sure to parse environment before we reset the settings mask below */ + r = parse_environment(); + if (r < 0) + return r; + + /* Load all settings from .nspawn files */ + if (mask_no_settings) + arg_settings_mask = 0; + + /* Don't load any settings from .nspawn files */ + if (mask_all_settings) + arg_settings_mask = _SETTINGS_MASK_ALL; + + return 1; +} + +static int verify_arguments(void) { + int r; + + if (arg_start_mode == START_PID2 && arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_UNKNOWN) { + /* If we are running the stub init in the container, we don't need to look at what the init + * in the container supports, because we are not using it. Let's immediately pick the right + * setting based on the host system configuration. + * + * We only do this, if the user didn't use an environment variable to override the detection. + */ + + r = cg_all_unified(); + if (r < 0) + return log_error_errno(r, "Failed to determine whether we are in all unified mode."); + if (r > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL; + else if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0) + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_SYSTEMD; + else + arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE; + } + + if (arg_userns_mode != USER_NAMESPACE_NO) + arg_mount_settings |= MOUNT_USE_USERNS; + + if (arg_private_network) + arg_mount_settings |= MOUNT_APPLY_APIVFS_NETNS; + + if (!(arg_clone_ns_flags & CLONE_NEWPID) || + !(arg_clone_ns_flags & CLONE_NEWUTS)) { + arg_register = false; + if (arg_start_mode != START_PID1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--boot cannot be used without namespacing."); + } + + if (arg_userns_mode == USER_NAMESPACE_PICK) + arg_userns_chown = true; + + if (arg_start_mode == START_BOOT && arg_kill_signal <= 0) + arg_kill_signal = SIGRTMIN+3; + + if (arg_volatile_mode != VOLATILE_NO) /* Make sure all file systems contained in the image are mounted read-only if we are in volatile mode */ + arg_read_only = true; + + if (arg_keep_unit && arg_register && cg_pid_get_owner_uid(0, NULL) >= 0) + /* Save the user from accidentally registering either user-$SESSION.scope or user@.service. + * The latter is not technically a user session, but we don't need to labour the point. */ + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--keep-unit --register=yes may not be used when invoked from a user session."); + + if (arg_directory && arg_image) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--directory= and --image= may not be combined."); + + if (arg_template && arg_image) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--template= and --image= may not be combined."); + + if (arg_template && !(arg_directory || arg_machine)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--template= needs --directory= or --machine=."); + + if (arg_ephemeral && arg_template) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--ephemeral and --template= may not be combined."); + + if (arg_ephemeral && !IN_SET(arg_link_journal, LINK_NO, LINK_AUTO)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--ephemeral and --link-journal= may not be combined."); + + if (arg_userns_mode != USER_NAMESPACE_NO && !userns_supported()) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "--private-users= is not supported, kernel compiled without user namespace support."); + + if (arg_userns_chown && arg_read_only) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--read-only and --private-users-chown may not be combined."); + + /* We don't support --private-users-chown together with any of the volatile modes since we couldn't + * change the read-only part of the tree (i.e. /usr) anyway, or because it would trigger a massive + * copy-up (in case of overlay) making the entire exercise pointless. */ + if (arg_userns_chown && arg_volatile_mode != VOLATILE_NO) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--volatile= and --private-users-chown may not be combined."); + + /* If --network-namespace-path is given with any other network-related option, we need to error out, + * to avoid conflicts between different network options. */ + if (arg_network_namespace_path && + (arg_network_interfaces || arg_network_macvlan || + arg_network_ipvlan || arg_network_veth_extra || + arg_network_bridge || arg_network_zone || + arg_network_veth || arg_private_network)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--network-namespace-path= cannot be combined with other network options."); + + if (arg_network_bridge && arg_network_zone) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--network-bridge= and --network-zone= may not be combined."); + + if (arg_userns_mode != USER_NAMESPACE_NO && (arg_mount_settings & MOUNT_APPLY_APIVFS_NETNS) && !arg_private_network) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid namespacing settings. Mounting sysfs with --private-users requires --private-network."); + + if (arg_userns_mode != USER_NAMESPACE_NO && !(arg_mount_settings & MOUNT_APPLY_APIVFS_RO)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot combine --private-users with read-write mounts."); + + if (arg_expose_ports && !arg_private_network) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot use --port= without private networking."); + +#if ! HAVE_LIBIPTC + if (arg_expose_ports) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "--port= is not supported, compiled without libiptc support."); +#endif + + r = custom_mount_check_all(); + if (r < 0) + return r; + + return 0; +} + +static int userns_lchown(const char *p, uid_t uid, gid_t gid) { + assert(p); + + if (arg_userns_mode == USER_NAMESPACE_NO) + return 0; + + if (uid == UID_INVALID && gid == GID_INVALID) + return 0; + + if (uid != UID_INVALID) { + uid += arg_uid_shift; + + if (uid < arg_uid_shift || uid >= arg_uid_shift + arg_uid_range) + return -EOVERFLOW; + } + + if (gid != GID_INVALID) { + gid += (gid_t) arg_uid_shift; + + if (gid < (gid_t) arg_uid_shift || gid >= (gid_t) (arg_uid_shift + arg_uid_range)) + return -EOVERFLOW; + } + + if (lchown(p, uid, gid) < 0) + return -errno; + + return 0; +} + +static int userns_mkdir(const char *root, const char *path, mode_t mode, uid_t uid, gid_t gid) { + const char *q; + int r; + + q = prefix_roota(root, path); + r = mkdir_errno_wrapper(q, mode); + if (r == -EEXIST) + return 0; + if (r < 0) + return r; + + return userns_lchown(q, uid, gid); +} + +static const char *timezone_from_path(const char *path) { + return PATH_STARTSWITH_SET( + path, + "../usr/share/zoneinfo/", + "/usr/share/zoneinfo/"); +} + +static bool etc_writable(void) { + return !arg_read_only || IN_SET(arg_volatile_mode, VOLATILE_YES, VOLATILE_OVERLAY); +} + +static int setup_timezone(const char *dest) { + _cleanup_free_ char *p = NULL, *etc = NULL; + const char *where, *check; + TimezoneMode m; + int r; + + assert(dest); + + if (IN_SET(arg_timezone, TIMEZONE_AUTO, TIMEZONE_SYMLINK)) { + r = readlink_malloc("/etc/localtime", &p); + if (r == -ENOENT && arg_timezone == TIMEZONE_AUTO) + m = etc_writable() ? TIMEZONE_DELETE : TIMEZONE_OFF; + else if (r == -EINVAL && arg_timezone == TIMEZONE_AUTO) /* regular file? */ + m = etc_writable() ? TIMEZONE_COPY : TIMEZONE_BIND; + else if (r < 0) { + log_warning_errno(r, "Failed to read host's /etc/localtime symlink, not updating container timezone: %m"); + /* To handle warning, delete /etc/localtime and replace it with a symbolic link to a time zone data + * file. + * + * Example: + * ln -s /usr/share/zoneinfo/UTC /etc/localtime + */ + return 0; + } else if (arg_timezone == TIMEZONE_AUTO) + m = etc_writable() ? TIMEZONE_SYMLINK : TIMEZONE_BIND; + else + m = arg_timezone; + } else + m = arg_timezone; + + if (m == TIMEZONE_OFF) + return 0; + + r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc, NULL); + if (r < 0) { + log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m"); + return 0; + } + + where = strjoina(etc, "/localtime"); + + switch (m) { + + case TIMEZONE_DELETE: + if (unlink(where) < 0) + log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, "Failed to remove '%s', ignoring: %m", where); + + return 0; + + case TIMEZONE_SYMLINK: { + _cleanup_free_ char *q = NULL; + const char *z, *what; + + z = timezone_from_path(p); + if (!z) { + log_warning("/etc/localtime does not point into /usr/share/zoneinfo/, not updating container timezone."); + return 0; + } + + r = readlink_malloc(where, &q); + if (r >= 0 && streq_ptr(timezone_from_path(q), z)) + return 0; /* Already pointing to the right place? Then do nothing .. */ + + check = strjoina(dest, "/usr/share/zoneinfo/", z); + r = chase_symlinks(check, dest, 0, NULL, NULL); + if (r < 0) + log_debug_errno(r, "Timezone %s does not exist (or is not accessible) in container, not creating symlink: %m", z); + else { + if (unlink(where) < 0 && errno != ENOENT) { + log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING, /* Don't complain on read-only images */ + errno, "Failed to remove existing timezone info %s in container, ignoring: %m", where); + return 0; + } + + what = strjoina("../usr/share/zoneinfo/", z); + if (symlink(what, where) < 0) { + log_full_errno(IN_SET(errno, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING, + errno, "Failed to correct timezone of container, ignoring: %m"); + return 0; + } + + break; + } + + _fallthrough_; + } + + case TIMEZONE_BIND: { + _cleanup_free_ char *resolved = NULL; + int found; + + found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved, NULL); + if (found < 0) { + log_warning_errno(found, "Failed to resolve /etc/localtime path in container, ignoring: %m"); + return 0; + } + + if (found == 0) /* missing? */ + (void) touch(resolved); + + r = mount_verbose(LOG_WARNING, "/etc/localtime", resolved, NULL, MS_BIND, NULL); + if (r >= 0) + return mount_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); + + _fallthrough_; + } + + case TIMEZONE_COPY: + /* If mounting failed, try to copy */ + r = copy_file_atomic("/etc/localtime", where, 0644, 0, 0, COPY_REFLINK|COPY_REPLACE); + if (r < 0) { + log_full_errno(IN_SET(r, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to copy /etc/localtime to %s, ignoring: %m", where); + return 0; + } + + break; + + default: + assert_not_reached("unexpected mode"); + } + + /* Fix permissions of the symlink or file copy we just created */ + r = userns_lchown(where, 0, 0); + if (r < 0) + log_warning_errno(r, "Failed to chown /etc/localtime, ignoring: %m"); + + return 0; +} + +static int have_resolv_conf(const char *path) { + assert(path); + + if (access(path, F_OK) < 0) { + if (errno == ENOENT) + return 0; + + return log_debug_errno(errno, "Failed to determine whether '%s' is available: %m", path); + } + + return 1; +} + +static int resolved_listening(void) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *dns_stub_listener_mode = NULL; + int r; + + /* Check if resolved is listening */ + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_debug_errno(r, "Failed to open system bus: %m"); + + r = bus_name_has_owner(bus, "org.freedesktop.resolve1", NULL); + if (r < 0) + return log_debug_errno(r, "Failed to check whether the 'org.freedesktop.resolve1' bus name is taken: %m"); + if (r == 0) + return 0; + + r = sd_bus_get_property_string(bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "DNSStubListener", + &error, + &dns_stub_listener_mode); + if (r < 0) + return log_debug_errno(r, "Failed to query DNSStubListener property: %s", bus_error_message(&error, r)); + + return STR_IN_SET(dns_stub_listener_mode, "udp", "yes"); +} + +static int setup_resolv_conf(const char *dest) { + _cleanup_free_ char *etc = NULL; + const char *where, *what; + ResolvConfMode m; + int r; + + assert(dest); + + if (arg_resolv_conf == RESOLV_CONF_AUTO) { + if (arg_private_network) + m = RESOLV_CONF_OFF; + else if (have_resolv_conf(STATIC_RESOLV_CONF) > 0 && resolved_listening() > 0) + m = etc_writable() ? RESOLV_CONF_COPY_STATIC : RESOLV_CONF_BIND_STATIC; + else if (have_resolv_conf("/etc/resolv.conf") > 0) + m = etc_writable() ? RESOLV_CONF_COPY_HOST : RESOLV_CONF_BIND_HOST; + else + m = etc_writable() ? RESOLV_CONF_DELETE : RESOLV_CONF_OFF; + } else + m = arg_resolv_conf; + + if (m == RESOLV_CONF_OFF) + return 0; + + r = chase_symlinks("/etc", dest, CHASE_PREFIX_ROOT, &etc, NULL); + if (r < 0) { + log_warning_errno(r, "Failed to resolve /etc path in container, ignoring: %m"); + return 0; + } + + where = strjoina(etc, "/resolv.conf"); + + if (m == RESOLV_CONF_DELETE) { + if (unlink(where) < 0) + log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, "Failed to remove '%s', ignoring: %m", where); + + return 0; + } + + if (IN_SET(m, RESOLV_CONF_BIND_STATIC, RESOLV_CONF_COPY_STATIC)) + what = STATIC_RESOLV_CONF; + else + what = "/etc/resolv.conf"; + + if (IN_SET(m, RESOLV_CONF_BIND_HOST, RESOLV_CONF_BIND_STATIC)) { + _cleanup_free_ char *resolved = NULL; + int found; + + found = chase_symlinks(where, dest, CHASE_NONEXISTENT, &resolved, NULL); + if (found < 0) { + log_warning_errno(found, "Failed to resolve /etc/resolv.conf path in container, ignoring: %m"); + return 0; + } + + if (found == 0) /* missing? */ + (void) touch(resolved); + + r = mount_verbose(LOG_WARNING, what, resolved, NULL, MS_BIND, NULL); + if (r >= 0) + return mount_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); + } + + /* If that didn't work, let's copy the file */ + r = copy_file(what, where, O_TRUNC|O_NOFOLLOW, 0644, 0, 0, COPY_REFLINK); + if (r < 0) { + /* If the file already exists as symlink, let's suppress the warning, under the assumption that + * resolved or something similar runs inside and the symlink points there. + * + * If the disk image is read-only, there's also no point in complaining. + */ + log_full_errno(!IN_SET(RESOLV_CONF_COPY_HOST, RESOLV_CONF_COPY_STATIC) && IN_SET(r, -ELOOP, -EROFS, -EACCES, -EPERM) ? LOG_DEBUG : LOG_WARNING, r, + "Failed to copy /etc/resolv.conf to %s, ignoring: %m", where); + return 0; + } + + r = userns_lchown(where, 0, 0); + if (r < 0) + log_warning_errno(r, "Failed to chown /etc/resolv.conf, ignoring: %m"); + + return 0; +} + +static int setup_boot_id(void) { + _cleanup_(unlink_and_freep) char *from = NULL; + _cleanup_free_ char *path = NULL; + sd_id128_t rnd = SD_ID128_NULL; + const char *to; + int r; + + /* Generate a new randomized boot ID, so that each boot-up of the container gets a new one */ + + r = tempfn_random_child("/run", "proc-sys-kernel-random-boot-id", &path); + if (r < 0) + return log_error_errno(r, "Failed to generate random boot ID path: %m"); + + r = sd_id128_randomize(&rnd); + if (r < 0) + return log_error_errno(r, "Failed to generate random boot id: %m"); + + r = id128_write(path, ID128_UUID, rnd, false); + if (r < 0) + return log_error_errno(r, "Failed to write boot id: %m"); + + from = TAKE_PTR(path); + to = "/proc/sys/kernel/random/boot_id"; + + r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL); + if (r < 0) + return r; + + return mount_verbose(LOG_ERR, NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); +} + +static int copy_devnodes(const char *dest) { + static const char devnodes[] = + "null\0" + "zero\0" + "full\0" + "random\0" + "urandom\0" + "tty\0" + "net/tun\0"; + + _cleanup_umask_ mode_t u; + const char *d; + int r = 0; + + assert(dest); + + u = umask(0000); + + /* Create /dev/net, so that we can create /dev/net/tun in it */ + if (userns_mkdir(dest, "/dev/net", 0755, 0, 0) < 0) + return log_error_errno(r, "Failed to create /dev/net directory: %m"); + + NULSTR_FOREACH(d, devnodes) { + _cleanup_free_ char *from = NULL, *to = NULL; + struct stat st; + + from = path_join("/dev/", d); + if (!from) + return log_oom(); + + to = path_join(dest, from); + if (!to) + return log_oom(); + + if (stat(from, &st) < 0) { + + if (errno != ENOENT) + return log_error_errno(errno, "Failed to stat %s: %m", from); + + } else if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "%s is not a char or block device, cannot copy.", from); + else { + _cleanup_free_ char *sl = NULL, *prefixed = NULL, *dn = NULL, *t = NULL; + + if (mknod(to, st.st_mode, st.st_rdev) < 0) { + /* Explicitly warn the user when /dev is already populated. */ + if (errno == EEXIST) + log_notice("%s/dev is pre-mounted and pre-populated. If a pre-mounted /dev is provided it needs to be an unpopulated file system.", dest); + if (errno != EPERM) + return log_error_errno(errno, "mknod(%s) failed: %m", to); + + /* Some systems abusively restrict mknod but allow bind mounts. */ + r = touch(to); + if (r < 0) + return log_error_errno(r, "touch (%s) failed: %m", to); + r = mount_verbose(LOG_DEBUG, from, to, NULL, MS_BIND, NULL); + if (r < 0) + return log_error_errno(r, "Both mknod and bind mount (%s) failed: %m", to); + } + + r = userns_lchown(to, 0, 0); + if (r < 0) + return log_error_errno(r, "chown() of device node %s failed: %m", to); + + dn = path_join("/dev", S_ISCHR(st.st_mode) ? "char" : "block"); + if (!dn) + return log_oom(); + + r = userns_mkdir(dest, dn, 0755, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to create '%s': %m", dn); + + if (asprintf(&sl, "%s/%u:%u", dn, major(st.st_rdev), minor(st.st_rdev)) < 0) + return log_oom(); + + prefixed = path_join(dest, sl); + if (!prefixed) + return log_oom(); + + t = path_join("..", d); + if (!t) + return log_oom(); + + if (symlink(t, prefixed) < 0) + log_debug_errno(errno, "Failed to symlink '%s' to '%s': %m", t, prefixed); + } + } + + return r; +} + +static int make_extra_nodes(const char *dest) { + _cleanup_umask_ mode_t u; + size_t i; + int r; + + u = umask(0000); + + for (i = 0; i < arg_n_extra_nodes; i++) { + _cleanup_free_ char *path = NULL; + DeviceNode *n = arg_extra_nodes + i; + + path = path_join(dest, n->path); + if (!path) + return log_oom(); + + if (mknod(path, n->mode, S_ISCHR(n->mode) || S_ISBLK(n->mode) ? makedev(n->major, n->minor) : 0) < 0) + return log_error_errno(errno, "Failed to create device node '%s': %m", path); + + r = chmod_and_chown(path, n->mode, n->uid, n->gid); + if (r < 0) + return log_error_errno(r, "Failed to adjust device node ownership of '%s': %m", path); + } + + return 0; +} + +static int setup_pts(const char *dest) { + _cleanup_free_ char *options = NULL; + const char *p; + int r; + +#if HAVE_SELINUX + if (arg_selinux_apifs_context) + (void) asprintf(&options, + "newinstance,ptmxmode=0666,mode=620,gid=" GID_FMT ",context=\"%s\"", + arg_uid_shift + TTY_GID, + arg_selinux_apifs_context); + else +#endif + (void) asprintf(&options, + "newinstance,ptmxmode=0666,mode=620,gid=" GID_FMT, + arg_uid_shift + TTY_GID); + + if (!options) + return log_oom(); + + /* Mount /dev/pts itself */ + p = prefix_roota(dest, "/dev/pts"); + r = mkdir_errno_wrapper(p, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create /dev/pts: %m"); + + r = mount_verbose(LOG_ERR, "devpts", p, "devpts", MS_NOSUID|MS_NOEXEC, options); + if (r < 0) + return r; + r = userns_lchown(p, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to chown /dev/pts: %m"); + + /* Create /dev/ptmx symlink */ + p = prefix_roota(dest, "/dev/ptmx"); + if (symlink("pts/ptmx", p) < 0) + return log_error_errno(errno, "Failed to create /dev/ptmx symlink: %m"); + r = userns_lchown(p, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to chown /dev/ptmx: %m"); + + /* And fix /dev/pts/ptmx ownership */ + p = prefix_roota(dest, "/dev/pts/ptmx"); + r = userns_lchown(p, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to chown /dev/pts/ptmx: %m"); + + return 0; +} + +static int setup_stdio_as_dev_console(void) { + int terminal; + int r; + + terminal = open_terminal("/dev/console", O_RDWR); + if (terminal < 0) + return log_error_errno(terminal, "Failed to open console: %m"); + + /* Make sure we can continue logging to the original stderr, even if + * stderr points elsewhere now */ + r = log_dup_console(); + if (r < 0) + return log_error_errno(r, "Failed to duplicate stderr: %m"); + + /* invalidates 'terminal' on success and failure */ + r = rearrange_stdio(terminal, terminal, terminal); + if (r < 0) + return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m"); + + return 0; +} + +static int setup_dev_console(const char *console) { + _cleanup_free_ char *p = NULL; + int r; + + /* Create /dev/console symlink */ + r = path_make_relative("/dev", console, &p); + if (r < 0) + return log_error_errno(r, "Failed to create relative path: %m"); + + if (symlink(p, "/dev/console") < 0) + return log_error_errno(errno, "Failed to create /dev/console symlink: %m"); + + return 0; +} + +static int setup_keyring(void) { + key_serial_t keyring; + + /* Allocate a new session keyring for the container. This makes sure the keyring of the session systemd-nspawn + * was invoked from doesn't leak into the container. Note that by default we block keyctl() and request_key() + * anyway via seccomp so doing this operation isn't strictly necessary, but in case people explicitly whitelist + * these system calls let's make sure we don't leak anything into the container. */ + + keyring = keyctl(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0); + if (keyring == -1) { + if (errno == ENOSYS) + log_debug_errno(errno, "Kernel keyring not supported, ignoring."); + else if (IN_SET(errno, EACCES, EPERM)) + log_debug_errno(errno, "Kernel keyring access prohibited, ignoring."); + else + return log_error_errno(errno, "Setting up kernel keyring failed: %m"); + } + + return 0; +} + +static int setup_kmsg(int kmsg_socket) { + _cleanup_(unlink_and_freep) char *from = NULL; + _cleanup_free_ char *fifo = NULL; + _cleanup_close_ int fd = -1; + _cleanup_umask_ mode_t u; + int r; + + assert(kmsg_socket >= 0); + + u = umask(0000); + + /* We create the kmsg FIFO as as temporary file in /run, but immediately delete it after bind mounting it to + * /proc/kmsg. While FIFOs on the reading side behave very similar to /proc/kmsg, their writing side behaves + * differently from /dev/kmsg in that writing blocks when nothing is reading. In order to avoid any problems + * with containers deadlocking due to this we simply make /dev/kmsg unavailable to the container. */ + + r = tempfn_random_child("/run", "proc-kmsg", &fifo); + if (r < 0) + return log_error_errno(r, "Failed to generate kmsg path: %m"); + + if (mkfifo(fifo, 0600) < 0) + return log_error_errno(errno, "mkfifo() for /run/kmsg failed: %m"); + + from = TAKE_PTR(fifo); + + r = mount_verbose(LOG_ERR, from, "/proc/kmsg", NULL, MS_BIND, NULL); + if (r < 0) + return r; + + fd = open(from, O_RDWR|O_NONBLOCK|O_CLOEXEC); + if (fd < 0) + return log_error_errno(errno, "Failed to open fifo: %m"); + + /* Store away the fd in the socket, so that it stays open as long as we run the child */ + r = send_one_fd(kmsg_socket, fd, 0); + if (r < 0) + return log_error_errno(r, "Failed to send FIFO fd: %m"); + + return 0; +} + +static int on_address_change(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { + union in_addr_union *exposed = userdata; + + assert(rtnl); + assert(m); + assert(exposed); + + expose_port_execute(rtnl, arg_expose_ports, exposed); + return 0; +} + +static int setup_hostname(void) { + int r; + + if ((arg_clone_ns_flags & CLONE_NEWUTS) == 0) + return 0; + + r = sethostname_idempotent(arg_hostname ?: arg_machine); + if (r < 0) + return log_error_errno(r, "Failed to set hostname: %m"); + + return 0; +} + +static int setup_journal(const char *directory) { + _cleanup_free_ char *d = NULL; + const char *dirname, *p, *q; + sd_id128_t this_id; + char id[33]; + bool try; + int r; + + /* Don't link journals in ephemeral mode */ + if (arg_ephemeral) + return 0; + + if (arg_link_journal == LINK_NO) + return 0; + + try = arg_link_journal_try || arg_link_journal == LINK_AUTO; + + r = sd_id128_get_machine(&this_id); + if (r < 0) + return log_error_errno(r, "Failed to retrieve machine ID: %m"); + + if (sd_id128_equal(arg_uuid, this_id)) { + log_full(try ? LOG_WARNING : LOG_ERR, + "Host and machine ids are equal (%s): refusing to link journals", sd_id128_to_string(arg_uuid, id)); + if (try) + return 0; + return -EEXIST; + } + + FOREACH_STRING(dirname, "/var", "/var/log", "/var/log/journal") { + r = userns_mkdir(directory, dirname, 0755, 0, 0); + if (r < 0) { + bool ignore = r == -EROFS && try; + log_full_errno(ignore ? LOG_DEBUG : LOG_ERR, r, + "Failed to create %s%s: %m", dirname, ignore ? ", ignoring" : ""); + return ignore ? 0 : r; + } + } + + (void) sd_id128_to_string(arg_uuid, id); + + p = strjoina("/var/log/journal/", id); + q = prefix_roota(directory, p); + + if (path_is_mount_point(p, NULL, 0) > 0) { + if (try) + return 0; + + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "%s: already a mount point, refusing to use for journal", p); + } + + if (path_is_mount_point(q, NULL, 0) > 0) { + if (try) + return 0; + + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "%s: already a mount point, refusing to use for journal", q); + } + + r = readlink_and_make_absolute(p, &d); + if (r >= 0) { + if (IN_SET(arg_link_journal, LINK_GUEST, LINK_AUTO) && + path_equal(d, q)) { + + r = userns_mkdir(directory, p, 0755, 0, 0); + if (r < 0) + log_warning_errno(r, "Failed to create directory %s: %m", q); + return 0; + } + + if (unlink(p) < 0) + return log_error_errno(errno, "Failed to remove symlink %s: %m", p); + } else if (r == -EINVAL) { + + if (arg_link_journal == LINK_GUEST && + rmdir(p) < 0) { + + if (errno == ENOTDIR) { + log_error("%s already exists and is neither a symlink nor a directory", p); + return r; + } else + return log_error_errno(errno, "Failed to remove %s: %m", p); + } + } else if (r != -ENOENT) + return log_error_errno(r, "readlink(%s) failed: %m", p); + + if (arg_link_journal == LINK_GUEST) { + + if (symlink(q, p) < 0) { + if (try) { + log_debug_errno(errno, "Failed to symlink %s to %s, skipping journal setup: %m", q, p); + return 0; + } else + return log_error_errno(errno, "Failed to symlink %s to %s: %m", q, p); + } + + r = userns_mkdir(directory, p, 0755, 0, 0); + if (r < 0) + log_warning_errno(r, "Failed to create directory %s: %m", q); + return 0; + } + + if (arg_link_journal == LINK_HOST) { + /* don't create parents here — if the host doesn't have + * permanent journal set up, don't force it here */ + + r = mkdir_errno_wrapper(p, 0755); + if (r < 0 && r != -EEXIST) { + if (try) { + log_debug_errno(r, "Failed to create %s, skipping journal setup: %m", p); + return 0; + } else + return log_error_errno(r, "Failed to create %s: %m", p); + } + + } else if (access(p, F_OK) < 0) + return 0; + + if (dir_is_empty(q) == 0) + log_warning("%s is not empty, proceeding anyway.", q); + + r = userns_mkdir(directory, p, 0755, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to create %s: %m", q); + + r = mount_verbose(LOG_DEBUG, p, q, NULL, MS_BIND, NULL); + if (r < 0) + return log_error_errno(errno, "Failed to bind mount journal from host into guest: %m"); + + return 0; +} + +static int drop_capabilities(uid_t uid) { + CapabilityQuintet q; + + /* Let's initialize all five capability sets to something valid. If the quintet was configured via + * OCI use that, but fill in missing bits. If it wasn't then derive the quintet in full from + * arg_caps_retain. */ + + if (capability_quintet_is_set(&arg_full_capabilities)) { + q = arg_full_capabilities; + + if (q.bounding == (uint64_t) -1) + q.bounding = uid == 0 ? arg_caps_retain : 0; + + if (q.effective == (uint64_t) -1) + q.effective = uid == 0 ? q.bounding : 0; + + if (q.inheritable == (uint64_t) -1) + q.inheritable = uid == 0 ? q.bounding : 0; + + if (q.permitted == (uint64_t) -1) + q.permitted = uid == 0 ? q.bounding : 0; + + if (q.ambient == (uint64_t) -1 && ambient_capabilities_supported()) + q.ambient = 0; + + if (capability_quintet_mangle(&q)) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Cannot set capabilities that are not in the current bounding set."); + + } else { + q = (CapabilityQuintet) { + .bounding = arg_caps_retain, + .effective = uid == 0 ? arg_caps_retain : 0, + .inheritable = uid == 0 ? arg_caps_retain : 0, + .permitted = uid == 0 ? arg_caps_retain : 0, + .ambient = ambient_capabilities_supported() ? 0 : (uint64_t) -1, + }; + + /* If we're not using OCI, proceed with mangled capabilities (so we don't error out) + * in order to maintain the same behavior as systemd < 242. */ + if (capability_quintet_mangle(&q)) + log_full(arg_quiet ? LOG_DEBUG : LOG_WARNING, + "Some capabilities will not be set because they are not in the current bounding set."); + + } + + return capability_quintet_enforce(&q); +} + +static int reset_audit_loginuid(void) { + _cleanup_free_ char *p = NULL; + int r; + + if ((arg_clone_ns_flags & CLONE_NEWPID) == 0) + return 0; + + r = read_one_line_file("/proc/self/loginuid", &p); + if (r == -ENOENT) + return 0; + if (r < 0) + return log_error_errno(r, "Failed to read /proc/self/loginuid: %m"); + + /* Already reset? */ + if (streq(p, "4294967295")) + return 0; + + r = write_string_file("/proc/self/loginuid", "4294967295", WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) { + log_error_errno(r, + "Failed to reset audit login UID. This probably means that your kernel is too\n" + "old and you have audit enabled. Note that the auditing subsystem is known to\n" + "be incompatible with containers on old kernels. Please make sure to upgrade\n" + "your kernel or to off auditing with 'audit=0' on the kernel command line before\n" + "using systemd-nspawn. Sleeping for 5s... (%m)"); + + sleep(5); + } + + return 0; +} + +static int setup_propagate(const char *root) { + const char *p, *q; + int r; + + (void) mkdir_p("/run/systemd/nspawn/", 0755); + (void) mkdir_p("/run/systemd/nspawn/propagate", 0600); + p = strjoina("/run/systemd/nspawn/propagate/", arg_machine); + (void) mkdir_p(p, 0600); + + r = userns_mkdir(root, "/run/systemd", 0755, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to create /run/systemd: %m"); + + r = userns_mkdir(root, "/run/systemd/nspawn", 0755, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to create /run/systemd/nspawn: %m"); + + r = userns_mkdir(root, "/run/systemd/nspawn/incoming", 0600, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to create /run/systemd/nspawn/incoming: %m"); + + q = prefix_roota(root, "/run/systemd/nspawn/incoming"); + r = mount_verbose(LOG_ERR, p, q, NULL, MS_BIND, NULL); + if (r < 0) + return r; + + r = mount_verbose(LOG_ERR, NULL, q, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL); + if (r < 0) + return r; + + /* machined will MS_MOVE into that directory, and that's only + * supported for non-shared mounts. */ + return mount_verbose(LOG_ERR, NULL, q, NULL, MS_SLAVE, NULL); +} + +static int setup_machine_id(const char *directory) { + const char *etc_machine_id; + sd_id128_t id; + int r; + + /* If the UUID in the container is already set, then that's what counts, and we use. If it isn't set, and the + * caller passed --uuid=, then we'll pass it in the $container_uuid env var to PID 1 of the container. The + * assumption is that PID 1 will then write it to /etc/machine-id to make it persistent. If --uuid= is not + * passed we generate a random UUID, and pass it via $container_uuid. In effect this means that /etc/machine-id + * in the container and our idea of the container UUID will always be in sync (at least if PID 1 in the + * container behaves nicely). */ + + etc_machine_id = prefix_roota(directory, "/etc/machine-id"); + + r = id128_read(etc_machine_id, ID128_PLAIN, &id); + if (r < 0) { + if (!IN_SET(r, -ENOENT, -ENOMEDIUM)) /* If the file is missing or empty, we don't mind */ + return log_error_errno(r, "Failed to read machine ID from container image: %m"); + + if (sd_id128_is_null(arg_uuid)) { + r = sd_id128_randomize(&arg_uuid); + if (r < 0) + return log_error_errno(r, "Failed to acquire randomized machine UUID: %m"); + } + } else { + if (sd_id128_is_null(id)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Machine ID in container image is zero, refusing."); + + arg_uuid = id; + } + + return 0; +} + +static int recursive_chown(const char *directory, uid_t shift, uid_t range) { + int r; + + assert(directory); + + if (arg_userns_mode == USER_NAMESPACE_NO || !arg_userns_chown) + return 0; + + r = path_patch_uid(directory, arg_uid_shift, arg_uid_range); + if (r == -EOPNOTSUPP) + return log_error_errno(r, "Automatic UID/GID adjusting is only supported for UID/GID ranges starting at multiples of 2^16 with a range of 2^16."); + if (r == -EBADE) + return log_error_errno(r, "Upper 16 bits of root directory UID and GID do not match."); + if (r < 0) + return log_error_errno(r, "Failed to adjust UID/GID shift of OS tree: %m"); + if (r == 0) + log_debug("Root directory of image is already owned by the right UID/GID range, skipping recursive chown operation."); + else + log_debug("Patched directory tree to match UID/GID range."); + + return r; +} + +/* + * Return values: + * < 0 : wait_for_terminate() failed to get the state of the + * container, the container was terminated by a signal, or + * failed for an unknown reason. No change is made to the + * container argument. + * > 0 : The program executed in the container terminated with an + * error. The exit code of the program executed in the + * container is returned. The container argument has been set + * to CONTAINER_TERMINATED. + * 0 : The container is being rebooted, has been shut down or exited + * successfully. The container argument has been set to either + * CONTAINER_TERMINATED or CONTAINER_REBOOTED. + * + * That is, success is indicated by a return value of zero, and an + * error is indicated by a non-zero value. + */ +static int wait_for_container(pid_t pid, ContainerStatus *container) { + siginfo_t status; + int r; + + r = wait_for_terminate(pid, &status); + if (r < 0) + return log_warning_errno(r, "Failed to wait for container: %m"); + + switch (status.si_code) { + + case CLD_EXITED: + if (status.si_status == 0) + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "Container %s exited successfully.", arg_machine); + else + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "Container %s failed with error code %i.", arg_machine, status.si_status); + + *container = CONTAINER_TERMINATED; + return status.si_status; + + case CLD_KILLED: + if (status.si_status == SIGINT) { + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "Container %s has been shut down.", arg_machine); + *container = CONTAINER_TERMINATED; + return 0; + + } else if (status.si_status == SIGHUP) { + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, "Container %s is being rebooted.", arg_machine); + *container = CONTAINER_REBOOTED; + return 0; + } + + _fallthrough_; + case CLD_DUMPED: + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Container %s terminated by signal %s.", arg_machine, signal_to_string(status.si_status)); + + default: + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Container %s failed due to unknown reason.", arg_machine); + } +} + +static int on_orderly_shutdown(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + pid_t pid; + + pid = PTR_TO_PID(userdata); + if (pid > 0) { + if (kill(pid, arg_kill_signal) >= 0) { + log_info("Trying to halt container. Send SIGTERM again to trigger immediate termination."); + sd_event_source_set_userdata(s, NULL); + return 0; + } + } + + sd_event_exit(sd_event_source_get_event(s), 0); + return 0; +} + +static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *ssi, void *userdata) { + pid_t pid; + + assert(s); + assert(ssi); + + pid = PTR_TO_PID(userdata); + + for (;;) { + siginfo_t si = {}; + + if (waitid(P_ALL, 0, &si, WNOHANG|WNOWAIT|WEXITED) < 0) + return log_error_errno(errno, "Failed to waitid(): %m"); + if (si.si_pid == 0) /* No pending children. */ + break; + if (si.si_pid == pid) { + /* The main process we care for has exited. Return from + * signal handler but leave the zombie. */ + sd_event_exit(sd_event_source_get_event(s), 0); + break; + } + + /* Reap all other children. */ + (void) waitid(P_PID, si.si_pid, &si, WNOHANG|WEXITED); + } + + return 0; +} + +static int on_request_stop(sd_bus_message *m, void *userdata, sd_bus_error *error) { + pid_t pid; + + assert(m); + + pid = PTR_TO_PID(userdata); + + if (arg_kill_signal > 0) { + log_info("Container termination requested. Attempting to halt container."); + (void) kill(pid, arg_kill_signal); + } else { + log_info("Container termination requested. Exiting."); + sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), 0); + } + + return 0; +} + +static int determine_names(void) { + int r; + + if (arg_template && !arg_directory && arg_machine) { + + /* If --template= was specified then we should not + * search for a machine, but instead create a new one + * in /var/lib/machine. */ + + arg_directory = path_join("/var/lib/machines", arg_machine); + if (!arg_directory) + return log_oom(); + } + + if (!arg_image && !arg_directory) { + if (arg_machine) { + _cleanup_(image_unrefp) Image *i = NULL; + + r = image_find(IMAGE_MACHINE, arg_machine, &i); + if (r == -ENOENT) + return log_error_errno(r, "No image for machine '%s'.", arg_machine); + if (r < 0) + return log_error_errno(r, "Failed to find image for machine '%s': %m", arg_machine); + + if (IN_SET(i->type, IMAGE_RAW, IMAGE_BLOCK)) + r = free_and_strdup(&arg_image, i->path); + else + r = free_and_strdup(&arg_directory, i->path); + if (r < 0) + return log_oom(); + + if (!arg_ephemeral) + arg_read_only = arg_read_only || i->read_only; + } else { + r = safe_getcwd(&arg_directory); + if (r < 0) + return log_error_errno(r, "Failed to determine current directory: %m"); + } + + if (!arg_directory && !arg_image) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine path, please use -D or -i."); + } + + if (!arg_machine) { + if (arg_directory && path_equal(arg_directory, "/")) + arg_machine = gethostname_malloc(); + else { + if (arg_image) { + char *e; + + arg_machine = strdup(basename(arg_image)); + + /* Truncate suffix if there is one */ + e = endswith(arg_machine, ".raw"); + if (e) + *e = 0; + } else + arg_machine = strdup(basename(arg_directory)); + } + if (!arg_machine) + return log_oom(); + + hostname_cleanup(arg_machine); + if (!machine_name_is_valid(arg_machine)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine machine name automatically, please use -M."); + + if (arg_ephemeral) { + char *b; + + /* Add a random suffix when this is an + * ephemeral machine, so that we can run many + * instances at once without manually having + * to specify -M each time. */ + + if (asprintf(&b, "%s-%016" PRIx64, arg_machine, random_u64()) < 0) + return log_oom(); + + free(arg_machine); + arg_machine = b; + } + } + + return 0; +} + +static int chase_symlinks_and_update(char **p, unsigned flags) { + char *chased; + int r; + + assert(p); + + if (!*p) + return 0; + + r = chase_symlinks(*p, NULL, flags, &chased, NULL); + if (r < 0) + return log_error_errno(r, "Failed to resolve path %s: %m", *p); + + return free_and_replace(*p, chased); +} + +static int determine_uid_shift(const char *directory) { + int r; + + if (arg_userns_mode == USER_NAMESPACE_NO) { + arg_uid_shift = 0; + return 0; + } + + if (arg_uid_shift == UID_INVALID) { + struct stat st; + + r = stat(directory, &st); + if (r < 0) + return log_error_errno(errno, "Failed to determine UID base of %s: %m", directory); + + arg_uid_shift = st.st_uid & UINT32_C(0xffff0000); + + if (arg_uid_shift != (st.st_gid & UINT32_C(0xffff0000))) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "UID and GID base of %s don't match.", directory); + + arg_uid_range = UINT32_C(0x10000); + } + + if (arg_uid_shift > (uid_t) -1 - arg_uid_range) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "UID base too high for UID range."); + + return 0; +} + +static unsigned long effective_clone_ns_flags(void) { + unsigned long flags = arg_clone_ns_flags; + + if (arg_private_network) + flags |= CLONE_NEWNET; + if (arg_use_cgns) + flags |= CLONE_NEWCGROUP; + if (arg_userns_mode != USER_NAMESPACE_NO) + flags |= CLONE_NEWUSER; + + return flags; +} + +static int patch_sysctl(void) { + + /* This table is inspired by runc's sysctl() function */ + static const struct { + const char *key; + bool prefix; + unsigned long clone_flags; + } safe_sysctl[] = { + { "kernel.hostname", false, CLONE_NEWUTS }, + { "kernel.domainname", false, CLONE_NEWUTS }, + { "kernel.msgmax", false, CLONE_NEWIPC }, + { "kernel.msgmnb", false, CLONE_NEWIPC }, + { "kernel.msgmni", false, CLONE_NEWIPC }, + { "kernel.sem", false, CLONE_NEWIPC }, + { "kernel.shmall", false, CLONE_NEWIPC }, + { "kernel.shmmax", false, CLONE_NEWIPC }, + { "kernel.shmmni", false, CLONE_NEWIPC }, + { "fs.mqueue.", true, CLONE_NEWIPC }, + { "net.", true, CLONE_NEWNET }, + }; + + unsigned long flags; + char **k, **v; + int r; + + flags = effective_clone_ns_flags(); + + STRV_FOREACH_PAIR(k, v, arg_sysctl) { + bool good = false; + size_t i; + + for (i = 0; i < ELEMENTSOF(safe_sysctl); i++) { + + if (!FLAGS_SET(flags, safe_sysctl[i].clone_flags)) + continue; + + if (safe_sysctl[i].prefix) + good = startswith(*k, safe_sysctl[i].key); + else + good = streq(*k, safe_sysctl[i].key); + + if (good) + break; + } + + if (!good) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Refusing to write to sysctl '%s', as it is not safe in the selected namespaces.", *k); + + r = sysctl_write(*k, *v); + if (r < 0) + return log_error_errno(r, "Failed to write sysctl '%s': %m", *k); + } + + return 0; +} + +static int inner_child( + Barrier *barrier, + const char *directory, + bool secondary, + int kmsg_socket, + int rtnl_socket, + int master_pty_socket, + FDSet *fds) { + + _cleanup_free_ char *home = NULL; + char as_uuid[37]; + size_t n_env = 1; + const char *envp[] = { + "PATH=" DEFAULT_PATH_COMPAT, + NULL, /* container */ + NULL, /* TERM */ + NULL, /* HOME */ + NULL, /* USER */ + NULL, /* LOGNAME */ + NULL, /* container_uuid */ + NULL, /* LISTEN_FDS */ + NULL, /* LISTEN_PID */ + NULL, /* NOTIFY_SOCKET */ + NULL + }; + const char *exec_target; + _cleanup_strv_free_ char **env_use = NULL; + int r, which_failed; + + /* This is the "inner" child process, i.e. the one forked off by the "outer" child process, which is the one + * the container manager itself forked off. At the time of clone() it gained its own CLONE_NEWNS, CLONE_NEWPID, + * CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWUSER namespaces. Note that it has its own CLONE_NEWNS namespace, + * separate from the CLONE_NEWNS created for the "outer" child, and also separate from the host's CLONE_NEWNS + * namespace. The reason for having two levels of CLONE_NEWNS namespaces is that the "inner" one is owned by + * the CLONE_NEWUSER namespace of the container, while the "outer" one is owned by the host's CLONE_NEWUSER + * namespace. + * + * Note at this point we have no CLONE_NEWNET namespace yet. We'll acquire that one later through + * unshare(). See below. */ + + assert(barrier); + assert(directory); + assert(kmsg_socket >= 0); + + log_debug("Inner child is initializing."); + + if (arg_userns_mode != USER_NAMESPACE_NO) { + /* Tell the parent, that it now can write the UID map. */ + (void) barrier_place(barrier); /* #1 */ + + /* Wait until the parent wrote the UID map */ + if (!barrier_place_and_sync(barrier)) /* #2 */ + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), + "Parent died too early"); + } + + r = reset_uid_gid(); + if (r < 0) + return log_error_errno(r, "Couldn't become new root: %m"); + + r = mount_all(NULL, + arg_mount_settings | MOUNT_IN_USERNS, + arg_uid_shift, + arg_selinux_apifs_context); + if (r < 0) + return r; + + if (!arg_network_namespace_path && arg_private_network) { + r = unshare(CLONE_NEWNET); + if (r < 0) + return log_error_errno(errno, "Failed to unshare network namespace: %m"); + + /* Tell the parent that it can setup network interfaces. */ + (void) barrier_place(barrier); /* #3 */ + } + + r = mount_sysfs(NULL, arg_mount_settings); + if (r < 0) + return r; + + /* Wait until we are cgroup-ified, so that we + * can mount the right cgroup path writable */ + if (!barrier_place_and_sync(barrier)) /* #4 */ + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), + "Parent died too early"); + + if (arg_use_cgns) { + r = unshare(CLONE_NEWCGROUP); + if (r < 0) + return log_error_errno(errno, "Failed to unshare cgroup namespace: %m"); + r = mount_cgroups( + "", + arg_unified_cgroup_hierarchy, + arg_userns_mode != USER_NAMESPACE_NO, + arg_uid_shift, + arg_uid_range, + arg_selinux_apifs_context, + true); + if (r < 0) + return r; + } else { + r = mount_systemd_cgroup_writable("", arg_unified_cgroup_hierarchy); + if (r < 0) + return r; + } + + r = setup_boot_id(); + if (r < 0) + return r; + + r = setup_kmsg(kmsg_socket); + if (r < 0) + return r; + kmsg_socket = safe_close(kmsg_socket); + + r = mount_custom( + "/", + arg_custom_mounts, + arg_n_custom_mounts, + false, + 0, + 0, + arg_selinux_apifs_context, + true); + if (r < 0) + return r; + + if (setsid() < 0) + return log_error_errno(errno, "setsid() failed: %m"); + + if (arg_private_network) + loopback_setup(); + + if (arg_expose_ports) { + r = expose_port_send_rtnl(rtnl_socket); + if (r < 0) + return r; + rtnl_socket = safe_close(rtnl_socket); + } + + if (arg_console_mode != CONSOLE_PIPE) { + _cleanup_close_ int master = -1; + _cleanup_free_ char *console = NULL; + + /* Allocate a pty and make it available as /dev/console. */ + master = openpt_allocate(O_RDWR|O_NONBLOCK, &console); + if (master < 0) + return log_error_errno(master, "Failed to allocate a pty: %m"); + + r = setup_dev_console(console); + if (r < 0) + return log_error_errno(r, "Failed to setup /dev/console: %m"); + + r = send_one_fd(master_pty_socket, master, 0); + if (r < 0) + return log_error_errno(r, "Failed to send master fd: %m"); + master_pty_socket = safe_close(master_pty_socket); + + r = setup_stdio_as_dev_console(); + if (r < 0) + return r; + } + + r = patch_sysctl(); + if (r < 0) + return r; + + if (arg_oom_score_adjust_set) { + r = set_oom_score_adjust(arg_oom_score_adjust); + if (r < 0) + return log_error_errno(r, "Failed to adjust OOM score: %m"); + } + + if (arg_cpu_set.set) + if (sched_setaffinity(0, arg_cpu_set.allocated, arg_cpu_set.set) < 0) + return log_error_errno(errno, "Failed to set CPU affinity: %m"); + + (void) setup_hostname(); + + if (arg_personality != PERSONALITY_INVALID) { + r = safe_personality(arg_personality); + if (r < 0) + return log_error_errno(r, "personality() failed: %m"); + } else if (secondary) { + r = safe_personality(PER_LINUX32); + if (r < 0) + return log_error_errno(r, "personality() failed: %m"); + } + + r = setrlimit_closest_all((const struct rlimit *const*) arg_rlimit, &which_failed); + if (r < 0) + return log_error_errno(r, "Failed to apply resource limit RLIMIT_%s: %m", rlimit_to_string(which_failed)); + +#if HAVE_SECCOMP + if (arg_seccomp) { + + if (is_seccomp_available()) { + + r = seccomp_load(arg_seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return log_error_errno(r, "Failed to install seccomp filter: %m"); + if (r < 0) + log_debug_errno(r, "Failed to install seccomp filter: %m"); + } + } else +#endif + { + r = setup_seccomp(arg_caps_retain, arg_syscall_whitelist, arg_syscall_blacklist); + if (r < 0) + return r; + } + +#if HAVE_SELINUX + if (arg_selinux_context) + if (setexeccon(arg_selinux_context) < 0) + return log_error_errno(errno, "setexeccon(\"%s\") failed: %m", arg_selinux_context); +#endif + + /* Make sure we keep the caps across the uid/gid dropping, so that we can retain some selected caps + * if we need to later on. */ + if (prctl(PR_SET_KEEPCAPS, 1) < 0) + return log_error_errno(errno, "Failed to set PR_SET_KEEPCAPS: %m"); + + if (uid_is_valid(arg_uid) || gid_is_valid(arg_gid)) + r = change_uid_gid_raw(arg_uid, arg_gid, arg_supplementary_gids, arg_n_supplementary_gids); + else + r = change_uid_gid(arg_user, &home); + if (r < 0) + return r; + + r = drop_capabilities(getuid()); + if (r < 0) + return log_error_errno(r, "Dropping capabilities failed: %m"); + + if (arg_no_new_privileges) + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) + return log_error_errno(errno, "Failed to disable new privileges: %m"); + + /* LXC sets container=lxc, so follow the scheme here */ + envp[n_env++] = strjoina("container=", arg_container_service_name); + + envp[n_env] = strv_find_prefix(environ, "TERM="); + if (envp[n_env]) + n_env++; + + if (home || !uid_is_valid(arg_uid) || arg_uid == 0) + if (asprintf((char**)(envp + n_env++), "HOME=%s", home ?: "/root") < 0) + return log_oom(); + + if (arg_user || !uid_is_valid(arg_uid) || arg_uid == 0) + if (asprintf((char**)(envp + n_env++), "USER=%s", arg_user ?: "root") < 0 || + asprintf((char**)(envp + n_env++), "LOGNAME=%s", arg_user ? arg_user : "root") < 0) + return log_oom(); + + assert(!sd_id128_is_null(arg_uuid)); + + if (asprintf((char**)(envp + n_env++), "container_uuid=%s", id128_to_uuid_string(arg_uuid, as_uuid)) < 0) + return log_oom(); + + if (fdset_size(fds) > 0) { + r = fdset_cloexec(fds, false); + if (r < 0) + return log_error_errno(r, "Failed to unset O_CLOEXEC for file descriptors."); + + if ((asprintf((char **)(envp + n_env++), "LISTEN_FDS=%u", fdset_size(fds)) < 0) || + (asprintf((char **)(envp + n_env++), "LISTEN_PID=1") < 0)) + return log_oom(); + } + if (asprintf((char **)(envp + n_env++), "NOTIFY_SOCKET=%s", NSPAWN_NOTIFY_SOCKET_PATH) < 0) + return log_oom(); + + env_use = strv_env_merge(2, envp, arg_setenv); + if (!env_use) + return log_oom(); + + /* Let the parent know that we are ready and + * wait until the parent is ready with the + * setup, too... */ + if (!barrier_place_and_sync(barrier)) /* #5 */ + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), + "Parent died too early"); + + if (arg_chdir) + if (chdir(arg_chdir) < 0) + return log_error_errno(errno, "Failed to change to specified working directory %s: %m", arg_chdir); + + if (arg_start_mode == START_PID2) { + r = stub_pid1(arg_uuid); + if (r < 0) + return r; + } + + log_debug("Inner child completed, invoking payload."); + + /* Now, explicitly close the log, so that we then can close all remaining fds. Closing the log explicitly first + * has the benefit that the logging subsystem knows about it, and is thus ready to be reopened should we need + * it again. Note that the other fds closed here are at least the locking and barrier fds. */ + log_close(); + log_set_open_when_needed(true); + + (void) fdset_close_others(fds); + + if (arg_start_mode == START_BOOT) { + char **a; + size_t m; + + /* Automatically search for the init system */ + + m = strv_length(arg_parameters); + a = newa(char*, m + 2); + memcpy_safe(a + 1, arg_parameters, m * sizeof(char*)); + a[1 + m] = NULL; + + a[0] = (char*) "/usr/lib/systemd/systemd"; + execve(a[0], a, env_use); + + a[0] = (char*) "/lib/systemd/systemd"; + execve(a[0], a, env_use); + + a[0] = (char*) "/sbin/init"; + execve(a[0], a, env_use); + + exec_target = "/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init"; + } else if (!strv_isempty(arg_parameters)) { + const char *dollar_path; + + exec_target = arg_parameters[0]; + + /* Use the user supplied search $PATH if there is one, or DEFAULT_PATH_COMPAT if not to search the + * binary. */ + dollar_path = strv_env_get(env_use, "PATH"); + if (dollar_path) { + if (putenv((char*) dollar_path) != 0) + return log_error_errno(errno, "Failed to update $PATH: %m"); + } + + execvpe(arg_parameters[0], arg_parameters, env_use); + } else { + if (!arg_chdir) + /* If we cannot change the directory, we'll end up in /, that is expected. */ + (void) chdir(home ?: "/root"); + + execle("/bin/bash", "-bash", NULL, env_use); + execle("/bin/sh", "-sh", NULL, env_use); + + exec_target = "/bin/bash, /bin/sh"; + } + + return log_error_errno(errno, "execv(%s) failed: %m", exec_target); +} + +static int setup_sd_notify_child(void) { + _cleanup_close_ int fd = -1; + union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = NSPAWN_NOTIFY_SOCKET_PATH, + }; + int r; + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return log_error_errno(errno, "Failed to allocate notification socket: %m"); + + (void) mkdir_parents(NSPAWN_NOTIFY_SOCKET_PATH, 0755); + (void) sockaddr_un_unlink(&sa.un); + + r = bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return log_error_errno(errno, "bind(" NSPAWN_NOTIFY_SOCKET_PATH ") failed: %m"); + + r = userns_lchown(NSPAWN_NOTIFY_SOCKET_PATH, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to chown " NSPAWN_NOTIFY_SOCKET_PATH ": %m"); + + r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return log_error_errno(r, "SO_PASSCRED failed: %m"); + + return TAKE_FD(fd); +} + +static int outer_child( + Barrier *barrier, + const char *directory, + DissectedImage *dissected_image, + bool secondary, + int pid_socket, + int uuid_socket, + int notify_socket, + int kmsg_socket, + int rtnl_socket, + int uid_shift_socket, + int master_pty_socket, + int unified_cgroup_hierarchy_socket, + FDSet *fds, + int netns_fd) { + + _cleanup_close_ int fd = -1; + pid_t pid; + ssize_t l; + int r; + + /* This is the "outer" child process, i.e the one forked off by the container manager itself. It already has + * its own CLONE_NEWNS namespace (which was created by the clone()). It still lives in the host's CLONE_NEWPID, + * CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWUSER and CLONE_NEWNET namespaces. After it completed a number of + * initializations a second child (the "inner" one) is forked off it, and it exits. */ + + assert(barrier); + assert(directory); + assert(pid_socket >= 0); + assert(uuid_socket >= 0); + assert(notify_socket >= 0); + assert(master_pty_socket >= 0); + assert(kmsg_socket >= 0); + + log_debug("Outer child is initializing."); + + if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0) + return log_error_errno(errno, "PR_SET_PDEATHSIG failed: %m"); + + r = reset_audit_loginuid(); + if (r < 0) + return r; + + /* Mark everything as slave, so that we still + * receive mounts from the real root, but don't + * propagate mounts to the real root. */ + r = mount_verbose(LOG_ERR, NULL, "/", NULL, MS_SLAVE|MS_REC, NULL); + if (r < 0) + return r; + + if (dissected_image) { + /* If we are operating on a disk image, then mount its root directory now, but leave out the rest. We + * can read the UID shift from it if we need to. Further down we'll mount the rest, but then with the + * uid shift known. That way we can mount VFAT file systems shifted to the right place right away. This + * makes sure ESP partitions and userns are compatible. */ + + r = dissected_image_mount(dissected_image, directory, arg_uid_shift, + DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_DISCARD_ON_LOOP| + (arg_read_only ? DISSECT_IMAGE_READ_ONLY : 0)| + (arg_start_mode == START_BOOT ? DISSECT_IMAGE_VALIDATE_OS : 0)); + if (r < 0) + return r; + } + + r = determine_uid_shift(directory); + if (r < 0) + return r; + + if (arg_userns_mode != USER_NAMESPACE_NO) { + /* Let the parent know which UID shift we read from the image */ + l = send(uid_shift_socket, &arg_uid_shift, sizeof(arg_uid_shift), MSG_NOSIGNAL); + if (l < 0) + return log_error_errno(errno, "Failed to send UID shift: %m"); + if (l != sizeof(arg_uid_shift)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Short write while sending UID shift."); + + if (arg_userns_mode == USER_NAMESPACE_PICK) { + /* When we are supposed to pick the UID shift, the parent will check now whether the UID shift + * we just read from the image is available. If yes, it will send the UID shift back to us, if + * not it will pick a different one, and send it back to us. */ + + l = recv(uid_shift_socket, &arg_uid_shift, sizeof(arg_uid_shift), 0); + if (l < 0) + return log_error_errno(errno, "Failed to recv UID shift: %m"); + if (l != sizeof(arg_uid_shift)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Short read while receiving UID shift."); + } + + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, + "Selected user namespace base " UID_FMT " and range " UID_FMT ".", arg_uid_shift, arg_uid_range); + } + + if (path_equal(directory, "/")) { + /* If the directory we shall boot is the host, let's operate on a bind mount at a different + * place, so that we can make changes to its mount structure (for example, to implement + * --volatile=) without this interfering with our ability to access files such as + * /etc/localtime to copy into the container. Note that we use a fixed place for this + * (instead of a temporary directory, since we are living in our own mount namspace here + * already, and thus don't need to be afraid of colliding with anyone else's mounts).*/ + (void) mkdir_p("/run/systemd/nspawn-root", 0755); + + r = mount_verbose(LOG_ERR, "/", "/run/systemd/nspawn-root", NULL, MS_BIND|MS_REC, NULL); + if (r < 0) + return r; + + directory = "/run/systemd/nspawn-root"; + + } else if (!dissected_image) { + /* Turn directory into bind mount (we need that so that we can move the bind mount to root + * later on). */ + r = mount_verbose(LOG_ERR, directory, directory, NULL, MS_BIND|MS_REC, NULL); + if (r < 0) + return r; + } + + r = setup_pivot_root( + directory, + arg_pivot_root_new, + arg_pivot_root_old); + if (r < 0) + return r; + + r = setup_volatile_mode( + directory, + arg_volatile_mode, + arg_userns_mode != USER_NAMESPACE_NO, + arg_uid_shift, + arg_uid_range, + arg_selinux_apifs_context); + if (r < 0) + return r; + + if (dissected_image) { + /* Now we know the uid shift, let's now mount everything else that might be in the image. */ + r = dissected_image_mount(dissected_image, directory, arg_uid_shift, + DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY|DISSECT_IMAGE_DISCARD_ON_LOOP|(arg_read_only ? DISSECT_IMAGE_READ_ONLY : 0)); + if (r < 0) + return r; + } + + if (arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_UNKNOWN) { + /* OK, we don't know yet which cgroup mode to use yet. Let's figure it out, and tell the parent. */ + + r = detect_unified_cgroup_hierarchy_from_image(directory); + if (r < 0) + return r; + + l = send(unified_cgroup_hierarchy_socket, &arg_unified_cgroup_hierarchy, sizeof(arg_unified_cgroup_hierarchy), MSG_NOSIGNAL); + if (l < 0) + return log_error_errno(errno, "Failed to send cgroup mode: %m"); + if (l != sizeof(arg_unified_cgroup_hierarchy)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Short write while sending cgroup mode."); + + unified_cgroup_hierarchy_socket = safe_close(unified_cgroup_hierarchy_socket); + } + + /* Mark everything as shared so our mounts get propagated down. This is + * required to make new bind mounts available in systemd services + * inside the container that create a new mount namespace. + * See https://github.com/systemd/systemd/issues/3860 + * Further submounts (such as /dev) done after this will inherit the + * shared propagation mode. */ + r = mount_verbose(LOG_ERR, NULL, directory, NULL, MS_SHARED|MS_REC, NULL); + if (r < 0) + return r; + + r = recursive_chown(directory, arg_uid_shift, arg_uid_range); + if (r < 0) + return r; + + r = base_filesystem_create(directory, arg_uid_shift, (gid_t) arg_uid_shift); + if (r < 0) + return r; + + if (arg_read_only && arg_volatile_mode == VOLATILE_NO) { + r = bind_remount_recursive(directory, MS_RDONLY, MS_RDONLY, NULL); + if (r < 0) + return log_error_errno(r, "Failed to make tree read-only: %m"); + } + + r = mount_all(directory, + arg_mount_settings, + arg_uid_shift, + arg_selinux_apifs_context); + if (r < 0) + return r; + + r = copy_devnodes(directory); + if (r < 0) + return r; + + r = make_extra_nodes(directory); + if (r < 0) + return r; + + (void) dev_setup(directory, arg_uid_shift, arg_uid_shift); + (void) make_inaccessible_nodes(directory, arg_uid_shift, arg_uid_shift); + + r = setup_pts(directory); + if (r < 0) + return r; + + r = setup_propagate(directory); + if (r < 0) + return r; + + r = setup_keyring(); + if (r < 0) + return r; + + r = setup_timezone(directory); + if (r < 0) + return r; + + r = setup_resolv_conf(directory); + if (r < 0) + return r; + + r = setup_machine_id(directory); + if (r < 0) + return r; + + r = setup_journal(directory); + if (r < 0) + return r; + + r = mount_custom( + directory, + arg_custom_mounts, + arg_n_custom_mounts, + arg_userns_mode != USER_NAMESPACE_NO, + arg_uid_shift, + arg_uid_range, + arg_selinux_apifs_context, + false); + if (r < 0) + return r; + + if (!arg_use_cgns) { + r = mount_cgroups( + directory, + arg_unified_cgroup_hierarchy, + arg_userns_mode != USER_NAMESPACE_NO, + arg_uid_shift, + arg_uid_range, + arg_selinux_apifs_context, + false); + if (r < 0) + return r; + } + + r = mount_move_root(directory); + if (r < 0) + return log_error_errno(r, "Failed to move root directory: %m"); + + fd = setup_sd_notify_child(); + if (fd < 0) + return fd; + + pid = raw_clone(SIGCHLD|CLONE_NEWNS| + arg_clone_ns_flags | + (arg_userns_mode != USER_NAMESPACE_NO ? CLONE_NEWUSER : 0)); + if (pid < 0) + return log_error_errno(errno, "Failed to fork inner child: %m"); + if (pid == 0) { + pid_socket = safe_close(pid_socket); + uuid_socket = safe_close(uuid_socket); + notify_socket = safe_close(notify_socket); + uid_shift_socket = safe_close(uid_shift_socket); + + /* The inner child has all namespaces that are + * requested, so that we all are owned by the user if + * user namespaces are turned on. */ + + if (arg_network_namespace_path) { + r = namespace_enter(-1, -1, netns_fd, -1, -1); + if (r < 0) + return log_error_errno(r, "Failed to join network namespace: %m"); + } + + r = inner_child(barrier, directory, secondary, kmsg_socket, rtnl_socket, master_pty_socket, fds); + if (r < 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + l = send(pid_socket, &pid, sizeof(pid), MSG_NOSIGNAL); + if (l < 0) + return log_error_errno(errno, "Failed to send PID: %m"); + if (l != sizeof(pid)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Short write while sending PID."); + + l = send(uuid_socket, &arg_uuid, sizeof(arg_uuid), MSG_NOSIGNAL); + if (l < 0) + return log_error_errno(errno, "Failed to send machine ID: %m"); + if (l != sizeof(arg_uuid)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Short write while sending machine ID."); + + l = send_one_fd(notify_socket, fd, 0); + if (l < 0) + return log_error_errno(l, "Failed to send notify fd: %m"); + + pid_socket = safe_close(pid_socket); + uuid_socket = safe_close(uuid_socket); + notify_socket = safe_close(notify_socket); + master_pty_socket = safe_close(master_pty_socket); + kmsg_socket = safe_close(kmsg_socket); + rtnl_socket = safe_close(rtnl_socket); + netns_fd = safe_close(netns_fd); + + return 0; +} + +static int uid_shift_pick(uid_t *shift, LockFile *ret_lock_file) { + bool tried_hashed = false; + unsigned n_tries = 100; + uid_t candidate; + int r; + + assert(shift); + assert(ret_lock_file); + assert(arg_userns_mode == USER_NAMESPACE_PICK); + assert(arg_uid_range == 0x10000U); + + candidate = *shift; + + (void) mkdir("/run/systemd/nspawn-uid", 0755); + + for (;;) { + char lock_path[STRLEN("/run/systemd/nspawn-uid/") + DECIMAL_STR_MAX(uid_t) + 1]; + _cleanup_(release_lock_file) LockFile lf = LOCK_FILE_INIT; + + if (--n_tries <= 0) + return -EBUSY; + + if (candidate < CONTAINER_UID_BASE_MIN || candidate > CONTAINER_UID_BASE_MAX) + goto next; + if ((candidate & UINT32_C(0xFFFF)) != 0) + goto next; + + xsprintf(lock_path, "/run/systemd/nspawn-uid/" UID_FMT, candidate); + r = make_lock_file(lock_path, LOCK_EX|LOCK_NB, &lf); + if (r == -EBUSY) /* Range already taken by another nspawn instance */ + goto next; + if (r < 0) + return r; + + /* Make some superficial checks whether the range is currently known in the user database */ + if (getpwuid(candidate)) + goto next; + if (getpwuid(candidate + UINT32_C(0xFFFE))) + goto next; + if (getgrgid(candidate)) + goto next; + if (getgrgid(candidate + UINT32_C(0xFFFE))) + goto next; + + *ret_lock_file = lf; + lf = (struct LockFile) LOCK_FILE_INIT; + *shift = candidate; + return 0; + + next: + if (arg_machine && !tried_hashed) { + /* Try to hash the base from the container name */ + + static const uint8_t hash_key[] = { + 0xe1, 0x56, 0xe0, 0xf0, 0x4a, 0xf0, 0x41, 0xaf, + 0x96, 0x41, 0xcf, 0x41, 0x33, 0x94, 0xff, 0x72 + }; + + candidate = (uid_t) siphash24(arg_machine, strlen(arg_machine), hash_key); + + tried_hashed = true; + } else + random_bytes(&candidate, sizeof(candidate)); + + candidate = (candidate % (CONTAINER_UID_BASE_MAX - CONTAINER_UID_BASE_MIN)) + CONTAINER_UID_BASE_MIN; + candidate &= (uid_t) UINT32_C(0xFFFF0000); + } +} + +static int setup_uid_map(pid_t pid) { + char uid_map[STRLEN("/proc//uid_map") + DECIMAL_STR_MAX(uid_t) + 1], line[DECIMAL_STR_MAX(uid_t)*3+3+1]; + int r; + + assert(pid > 1); + + xsprintf(uid_map, "/proc/" PID_FMT "/uid_map", pid); + xsprintf(line, UID_FMT " " UID_FMT " " UID_FMT "\n", 0, arg_uid_shift, arg_uid_range); + r = write_string_file(uid_map, line, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return log_error_errno(r, "Failed to write UID map: %m"); + + /* We always assign the same UID and GID ranges */ + xsprintf(uid_map, "/proc/" PID_FMT "/gid_map", pid); + r = write_string_file(uid_map, line, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return log_error_errno(r, "Failed to write GID map: %m"); + + return 0; +} + +static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + char buf[NOTIFY_BUFFER_MAX+1]; + char *p = NULL; + struct iovec iovec = { + .iov_base = buf, + .iov_len = sizeof(buf)-1, + }; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + + CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)]; + } control = {}; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + struct cmsghdr *cmsg; + struct ucred *ucred = NULL; + ssize_t n; + pid_t inner_child_pid; + _cleanup_strv_free_ char **tags = NULL; + + assert(userdata); + + inner_child_pid = PTR_TO_PID(userdata); + + if (revents != EPOLLIN) { + log_warning("Got unexpected poll event for notify fd."); + return 0; + } + + n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + return log_warning_errno(errno, "Couldn't read notification socket: %m"); + } + cmsg_close_all(&msghdr); + + CMSG_FOREACH(cmsg, &msghdr) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + + ucred = (struct ucred*) CMSG_DATA(cmsg); + } + } + + if (!ucred || ucred->pid != inner_child_pid) { + log_debug("Received notify message without valid credentials. Ignoring."); + return 0; + } + + if ((size_t) n >= sizeof(buf)) { + log_warning("Received notify message exceeded maximum size. Ignoring."); + return 0; + } + + buf[n] = 0; + tags = strv_split(buf, "\n\r"); + if (!tags) + return log_oom(); + + if (strv_find(tags, "READY=1")) + (void) sd_notifyf(false, "READY=1\n"); + + p = strv_find_startswith(tags, "STATUS="); + if (p) + (void) sd_notifyf(false, "STATUS=Container running: %s", p); + + return 0; +} + +static int setup_sd_notify_parent(sd_event *event, int fd, pid_t *inner_child_pid, sd_event_source **notify_event_source) { + int r; + + r = sd_event_add_io(event, notify_event_source, fd, EPOLLIN, nspawn_dispatch_notify_fd, inner_child_pid); + if (r < 0) + return log_error_errno(r, "Failed to allocate notify event source: %m"); + + (void) sd_event_source_set_description(*notify_event_source, "nspawn-notify"); + + return 0; +} + +static int merge_settings(Settings *settings, const char *path) { + int rl; + + assert(settings); + assert(path); + + /* Copy over bits from the settings, unless they have been explicitly masked by command line switches. Note + * that this steals the fields of the Settings* structure, and hence modifies it. */ + + if ((arg_settings_mask & SETTING_START_MODE) == 0 && + settings->start_mode >= 0) { + arg_start_mode = settings->start_mode; + strv_free_and_replace(arg_parameters, settings->parameters); + } + + if ((arg_settings_mask & SETTING_EPHEMERAL) == 0) + arg_ephemeral = settings->ephemeral; + + if ((arg_settings_mask & SETTING_DIRECTORY) == 0 && + settings->root) { + + if (!arg_settings_trusted) + log_warning("Ignoring root directory setting, file %s is not trusted.", path); + else + free_and_replace(arg_directory, settings->root); + } + + if ((arg_settings_mask & SETTING_PIVOT_ROOT) == 0 && + settings->pivot_root_new) { + free_and_replace(arg_pivot_root_new, settings->pivot_root_new); + free_and_replace(arg_pivot_root_old, settings->pivot_root_old); + } + + if ((arg_settings_mask & SETTING_WORKING_DIRECTORY) == 0 && + settings->working_directory) + free_and_replace(arg_chdir, settings->working_directory); + + if ((arg_settings_mask & SETTING_ENVIRONMENT) == 0 && + settings->environment) + strv_free_and_replace(arg_setenv, settings->environment); + + if ((arg_settings_mask & SETTING_USER) == 0) { + + if (settings->user) + free_and_replace(arg_user, settings->user); + + if (uid_is_valid(settings->uid)) + arg_uid = settings->uid; + if (gid_is_valid(settings->gid)) + arg_gid = settings->gid; + if (settings->n_supplementary_gids > 0) { + free_and_replace(arg_supplementary_gids, settings->supplementary_gids); + arg_n_supplementary_gids = settings->n_supplementary_gids; + } + } + + if ((arg_settings_mask & SETTING_CAPABILITY) == 0) { + uint64_t plus, minus; + uint64_t network_minus = 0; + + /* Note that we copy both the simple plus/minus caps here, and the full quintet from the + * Settings structure */ + + plus = settings->capability; + minus = settings->drop_capability; + + if ((arg_settings_mask & SETTING_NETWORK) == 0) { + if (settings_private_network(settings)) + plus |= UINT64_C(1) << CAP_NET_ADMIN; + else + network_minus |= UINT64_C(1) << CAP_NET_ADMIN; + } + + if (!arg_settings_trusted && plus != 0) { + if (settings->capability != 0) + log_warning("Ignoring Capability= setting, file %s is not trusted.", path); + } else { + arg_caps_retain &= ~network_minus; + arg_caps_retain |= plus; + } + + arg_caps_retain &= ~minus; + + /* Copy the full capabilities over too */ + if (capability_quintet_is_set(&settings->full_capabilities)) { + if (!arg_settings_trusted) + log_warning("Ignoring capability settings, file %s is not trusted.", path); + else + arg_full_capabilities = settings->full_capabilities; + } + } + + if ((arg_settings_mask & SETTING_KILL_SIGNAL) == 0 && + settings->kill_signal > 0) + arg_kill_signal = settings->kill_signal; + + if ((arg_settings_mask & SETTING_PERSONALITY) == 0 && + settings->personality != PERSONALITY_INVALID) + arg_personality = settings->personality; + + if ((arg_settings_mask & SETTING_MACHINE_ID) == 0 && + !sd_id128_is_null(settings->machine_id)) { + + if (!arg_settings_trusted) + log_warning("Ignoring MachineID= setting, file %s is not trusted.", path); + else + arg_uuid = settings->machine_id; + } + + if ((arg_settings_mask & SETTING_READ_ONLY) == 0 && + settings->read_only >= 0) + arg_read_only = settings->read_only; + + if ((arg_settings_mask & SETTING_VOLATILE_MODE) == 0 && + settings->volatile_mode != _VOLATILE_MODE_INVALID) + arg_volatile_mode = settings->volatile_mode; + + if ((arg_settings_mask & SETTING_CUSTOM_MOUNTS) == 0 && + settings->n_custom_mounts > 0) { + + if (!arg_settings_trusted) + log_warning("Ignoring TemporaryFileSystem=, Bind= and BindReadOnly= settings, file %s is not trusted.", path); + else { + custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts); + arg_custom_mounts = TAKE_PTR(settings->custom_mounts); + arg_n_custom_mounts = settings->n_custom_mounts; + settings->n_custom_mounts = 0; + } + } + + if ((arg_settings_mask & SETTING_NETWORK) == 0 && + (settings->private_network >= 0 || + settings->network_veth >= 0 || + settings->network_bridge || + settings->network_zone || + settings->network_interfaces || + settings->network_macvlan || + settings->network_ipvlan || + settings->network_veth_extra || + settings->network_namespace_path)) { + + if (!arg_settings_trusted) + log_warning("Ignoring network settings, file %s is not trusted.", path); + else { + arg_network_veth = settings_network_veth(settings); + arg_private_network = settings_private_network(settings); + + strv_free_and_replace(arg_network_interfaces, settings->network_interfaces); + strv_free_and_replace(arg_network_macvlan, settings->network_macvlan); + strv_free_and_replace(arg_network_ipvlan, settings->network_ipvlan); + strv_free_and_replace(arg_network_veth_extra, settings->network_veth_extra); + + free_and_replace(arg_network_bridge, settings->network_bridge); + free_and_replace(arg_network_zone, settings->network_zone); + + free_and_replace(arg_network_namespace_path, settings->network_namespace_path); + } + } + + if ((arg_settings_mask & SETTING_EXPOSE_PORTS) == 0 && + settings->expose_ports) { + + if (!arg_settings_trusted) + log_warning("Ignoring Port= setting, file %s is not trusted.", path); + else { + expose_port_free_all(arg_expose_ports); + arg_expose_ports = TAKE_PTR(settings->expose_ports); + } + } + + if ((arg_settings_mask & SETTING_USERNS) == 0 && + settings->userns_mode != _USER_NAMESPACE_MODE_INVALID) { + + if (!arg_settings_trusted) + log_warning("Ignoring PrivateUsers= and PrivateUsersChown= settings, file %s is not trusted.", path); + else { + arg_userns_mode = settings->userns_mode; + arg_uid_shift = settings->uid_shift; + arg_uid_range = settings->uid_range; + arg_userns_chown = settings->userns_chown; + } + } + + if ((arg_settings_mask & SETTING_NOTIFY_READY) == 0) + arg_notify_ready = settings->notify_ready; + + if ((arg_settings_mask & SETTING_SYSCALL_FILTER) == 0) { + + if (!arg_settings_trusted && !strv_isempty(settings->syscall_whitelist)) + log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", path); + else { + strv_free_and_replace(arg_syscall_whitelist, settings->syscall_whitelist); + strv_free_and_replace(arg_syscall_blacklist, settings->syscall_blacklist); + } + +#if HAVE_SECCOMP + if (!arg_settings_trusted && settings->seccomp) + log_warning("Ignoring SECCOMP filter, file %s is not trusted.", path); + else { + seccomp_release(arg_seccomp); + arg_seccomp = TAKE_PTR(settings->seccomp); + } +#endif + } + + for (rl = 0; rl < _RLIMIT_MAX; rl ++) { + if ((arg_settings_mask & (SETTING_RLIMIT_FIRST << rl))) + continue; + + if (!settings->rlimit[rl]) + continue; + + if (!arg_settings_trusted) { + log_warning("Ignoring Limit%s= setting, file '%s' is not trusted.", rlimit_to_string(rl), path); + continue; + } + + free_and_replace(arg_rlimit[rl], settings->rlimit[rl]); + } + + if ((arg_settings_mask & SETTING_HOSTNAME) == 0 && + settings->hostname) + free_and_replace(arg_hostname, settings->hostname); + + if ((arg_settings_mask & SETTING_NO_NEW_PRIVILEGES) == 0 && + settings->no_new_privileges >= 0) + arg_no_new_privileges = settings->no_new_privileges; + + if ((arg_settings_mask & SETTING_OOM_SCORE_ADJUST) == 0 && + settings->oom_score_adjust_set) { + + if (!arg_settings_trusted) + log_warning("Ignoring OOMScoreAdjust= setting, file '%s' is not trusted.", path); + else { + arg_oom_score_adjust = settings->oom_score_adjust; + arg_oom_score_adjust_set = true; + } + } + + if ((arg_settings_mask & SETTING_CPU_AFFINITY) == 0 && + settings->cpu_set.set) { + + if (!arg_settings_trusted) + log_warning("Ignoring CPUAffinity= setting, file '%s' is not trusted.", path); + else { + cpu_set_reset(&arg_cpu_set); + arg_cpu_set = settings->cpu_set; + settings->cpu_set = (CPUSet) {}; + } + } + + if ((arg_settings_mask & SETTING_RESOLV_CONF) == 0 && + settings->resolv_conf != _RESOLV_CONF_MODE_INVALID) + arg_resolv_conf = settings->resolv_conf; + + if ((arg_settings_mask & SETTING_LINK_JOURNAL) == 0 && + settings->link_journal != _LINK_JOURNAL_INVALID) { + + if (!arg_settings_trusted) + log_warning("Ignoring journal link setting, file '%s' is not trusted.", path); + else { + arg_link_journal = settings->link_journal; + arg_link_journal_try = settings->link_journal_try; + } + } + + if ((arg_settings_mask & SETTING_TIMEZONE) == 0 && + settings->timezone != _TIMEZONE_MODE_INVALID) + arg_timezone = settings->timezone; + + if ((arg_settings_mask & SETTING_SLICE) == 0 && + settings->slice) { + + if (!arg_settings_trusted) + log_warning("Ignoring slice setting, file '%s' is not trusted.", path); + else + free_and_replace(arg_slice, settings->slice); + } + + if ((arg_settings_mask & SETTING_USE_CGNS) == 0 && + settings->use_cgns >= 0) { + + if (!arg_settings_trusted) + log_warning("Ignoring cgroup namespace setting, file '%s' is not trusted.", path); + else + arg_use_cgns = settings->use_cgns; + } + + if ((arg_settings_mask & SETTING_CLONE_NS_FLAGS) == 0 && + settings->clone_ns_flags != (unsigned long) -1) { + + if (!arg_settings_trusted) + log_warning("Ignoring namespace setting, file '%s' is not trusted.", path); + else + arg_clone_ns_flags = settings->clone_ns_flags; + } + + if ((arg_settings_mask & SETTING_CONSOLE_MODE) == 0 && + settings->console_mode >= 0) { + + if (!arg_settings_trusted) + log_warning("Ignoring console mode setting, file '%s' is not trusted.", path); + else + arg_console_mode = settings->console_mode; + } + + /* The following properties can only be set through the OCI settings logic, not from the command line, hence we + * don't consult arg_settings_mask for them. */ + + sd_bus_message_unref(arg_property_message); + arg_property_message = TAKE_PTR(settings->properties); + + arg_console_width = settings->console_width; + arg_console_height = settings->console_height; + + device_node_array_free(arg_extra_nodes, arg_n_extra_nodes); + arg_extra_nodes = TAKE_PTR(settings->extra_nodes); + arg_n_extra_nodes = settings->n_extra_nodes; + + return 0; +} + +static int load_settings(void) { + _cleanup_(settings_freep) Settings *settings = NULL; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *p = NULL; + const char *fn, *i; + int r; + + if (arg_oci_bundle) + return 0; + + /* If all settings are masked, there's no point in looking for + * the settings file */ + if ((arg_settings_mask & _SETTINGS_MASK_ALL) == _SETTINGS_MASK_ALL) + return 0; + + fn = strjoina(arg_machine, ".nspawn"); + + /* We first look in the admin's directories in /etc and /run */ + FOREACH_STRING(i, "/etc/systemd/nspawn", "/run/systemd/nspawn") { + _cleanup_free_ char *j = NULL; + + j = path_join(i, fn); + if (!j) + return log_oom(); + + f = fopen(j, "re"); + if (f) { + p = TAKE_PTR(j); + + /* By default, we trust configuration from /etc and /run */ + if (arg_settings_trusted < 0) + arg_settings_trusted = true; + + break; + } + + if (errno != ENOENT) + return log_error_errno(errno, "Failed to open %s: %m", j); + } + + if (!f) { + /* After that, let's look for a file next to the + * actual image we shall boot. */ + + if (arg_image) { + p = file_in_same_dir(arg_image, fn); + if (!p) + return log_oom(); + } else if (arg_directory && !path_equal(arg_directory, "/")) { + p = file_in_same_dir(arg_directory, fn); + if (!p) + return log_oom(); + } + + if (p) { + f = fopen(p, "re"); + if (!f && errno != ENOENT) + return log_error_errno(errno, "Failed to open %s: %m", p); + + /* By default, we do not trust configuration from /var/lib/machines */ + if (arg_settings_trusted < 0) + arg_settings_trusted = false; + } + } + + if (!f) + return 0; + + log_debug("Settings are trusted: %s", yes_no(arg_settings_trusted)); + + r = settings_load(f, p, &settings); + if (r < 0) + return r; + + return merge_settings(settings, p); +} + +static int load_oci_bundle(void) { + _cleanup_(settings_freep) Settings *settings = NULL; + int r; + + if (!arg_oci_bundle) + return 0; + + /* By default let's trust OCI bundles */ + if (arg_settings_trusted < 0) + arg_settings_trusted = true; + + r = oci_load(NULL, arg_oci_bundle, &settings); + if (r < 0) + return r; + + return merge_settings(settings, arg_oci_bundle); +} + +static int run_container( + DissectedImage *dissected_image, + bool secondary, + FDSet *fds, + char veth_name[IFNAMSIZ], bool *veth_created, + union in_addr_union *exposed, + int *master, pid_t *pid, int *ret) { + + static const struct sigaction sa = { + .sa_handler = nop_signal_handler, + .sa_flags = SA_NOCLDSTOP|SA_RESTART, + }; + + _cleanup_(release_lock_file) LockFile uid_shift_lock = LOCK_FILE_INIT; + _cleanup_close_ int etc_passwd_lock = -1; + _cleanup_close_pair_ int + kmsg_socket_pair[2] = { -1, -1 }, + rtnl_socket_pair[2] = { -1, -1 }, + pid_socket_pair[2] = { -1, -1 }, + uuid_socket_pair[2] = { -1, -1 }, + notify_socket_pair[2] = { -1, -1 }, + uid_shift_socket_pair[2] = { -1, -1 }, + master_pty_socket_pair[2] = { -1, -1 }, + unified_cgroup_hierarchy_socket_pair[2] = { -1, -1}; + + _cleanup_close_ int notify_socket = -1; + _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL; + _cleanup_(sd_event_source_unrefp) sd_event_source *notify_event_source = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(pty_forward_freep) PTYForward *forward = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + ContainerStatus container_status = 0; + int ifi = 0, r; + ssize_t l; + sigset_t mask_chld; + _cleanup_close_ int netns_fd = -1; + + assert_se(sigemptyset(&mask_chld) == 0); + assert_se(sigaddset(&mask_chld, SIGCHLD) == 0); + + if (arg_userns_mode == USER_NAMESPACE_PICK) { + /* When we shall pick the UID/GID range, let's first lock /etc/passwd, so that we can safely + * check with getpwuid() if the specific user already exists. Note that /etc might be + * read-only, in which case this will fail with EROFS. But that's really OK, as in that case we + * can be reasonably sure that no users are going to be added. Note that getpwuid() checks are + * really just an extra safety net. We kinda assume that the UID range we allocate from is + * really ours. */ + + etc_passwd_lock = take_etc_passwd_lock(NULL); + if (etc_passwd_lock < 0 && etc_passwd_lock != -EROFS) + return log_error_errno(etc_passwd_lock, "Failed to take /etc/passwd lock: %m"); + } + + r = barrier_create(&barrier); + if (r < 0) + return log_error_errno(r, "Cannot initialize IPC barrier: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) + return log_error_errno(errno, "Failed to create kmsg socket pair: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, rtnl_socket_pair) < 0) + return log_error_errno(errno, "Failed to create rtnl socket pair: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pid_socket_pair) < 0) + return log_error_errno(errno, "Failed to create pid socket pair: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, uuid_socket_pair) < 0) + return log_error_errno(errno, "Failed to create id socket pair: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, notify_socket_pair) < 0) + return log_error_errno(errno, "Failed to create notify socket pair: %m"); + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, master_pty_socket_pair) < 0) + return log_error_errno(errno, "Failed to create console socket pair: %m"); + + if (arg_userns_mode != USER_NAMESPACE_NO) + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, uid_shift_socket_pair) < 0) + return log_error_errno(errno, "Failed to create uid shift socket pair: %m"); + + if (arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_UNKNOWN) + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, unified_cgroup_hierarchy_socket_pair) < 0) + return log_error_errno(errno, "Failed to create unified cgroup socket pair: %m"); + + /* Child can be killed before execv(), so handle SIGCHLD in order to interrupt + * parent's blocking calls and give it a chance to call wait() and terminate. */ + r = sigprocmask(SIG_UNBLOCK, &mask_chld, NULL); + if (r < 0) + return log_error_errno(errno, "Failed to change the signal mask: %m"); + + r = sigaction(SIGCHLD, &sa, NULL); + if (r < 0) + return log_error_errno(errno, "Failed to install SIGCHLD handler: %m"); + + if (arg_network_namespace_path) { + netns_fd = open(arg_network_namespace_path, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (netns_fd < 0) + return log_error_errno(errno, "Cannot open file %s: %m", arg_network_namespace_path); + + r = fd_is_network_ns(netns_fd); + if (r == -EUCLEAN) + log_debug_errno(r, "Cannot determine if passed network namespace path '%s' really refers to a network namespace, assuming it does.", arg_network_namespace_path); + else if (r < 0) + return log_error_errno(r, "Failed to check %s fs type: %m", arg_network_namespace_path); + else if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Path %s doesn't refer to a network namespace, refusing.", arg_network_namespace_path); + } + + *pid = raw_clone(SIGCHLD|CLONE_NEWNS); + if (*pid < 0) + return log_error_errno(errno, "clone() failed%s: %m", + errno == EINVAL ? + ", do you have namespace support enabled in your kernel? (You need UTS, IPC, PID and NET namespacing built in)" : ""); + + if (*pid == 0) { + /* The outer child only has a file system namespace. */ + barrier_set_role(&barrier, BARRIER_CHILD); + + kmsg_socket_pair[0] = safe_close(kmsg_socket_pair[0]); + rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]); + pid_socket_pair[0] = safe_close(pid_socket_pair[0]); + uuid_socket_pair[0] = safe_close(uuid_socket_pair[0]); + notify_socket_pair[0] = safe_close(notify_socket_pair[0]); + master_pty_socket_pair[0] = safe_close(master_pty_socket_pair[0]); + uid_shift_socket_pair[0] = safe_close(uid_shift_socket_pair[0]); + unified_cgroup_hierarchy_socket_pair[0] = safe_close(unified_cgroup_hierarchy_socket_pair[0]); + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + + r = outer_child(&barrier, + arg_directory, + dissected_image, + secondary, + pid_socket_pair[1], + uuid_socket_pair[1], + notify_socket_pair[1], + kmsg_socket_pair[1], + rtnl_socket_pair[1], + uid_shift_socket_pair[1], + master_pty_socket_pair[1], + unified_cgroup_hierarchy_socket_pair[1], + fds, + netns_fd); + if (r < 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + barrier_set_role(&barrier, BARRIER_PARENT); + + fdset_close(fds); + + kmsg_socket_pair[1] = safe_close(kmsg_socket_pair[1]); + rtnl_socket_pair[1] = safe_close(rtnl_socket_pair[1]); + pid_socket_pair[1] = safe_close(pid_socket_pair[1]); + uuid_socket_pair[1] = safe_close(uuid_socket_pair[1]); + notify_socket_pair[1] = safe_close(notify_socket_pair[1]); + master_pty_socket_pair[1] = safe_close(master_pty_socket_pair[1]); + uid_shift_socket_pair[1] = safe_close(uid_shift_socket_pair[1]); + unified_cgroup_hierarchy_socket_pair[1] = safe_close(unified_cgroup_hierarchy_socket_pair[1]); + + if (arg_userns_mode != USER_NAMESPACE_NO) { + /* The child just let us know the UID shift it might have read from the image. */ + l = recv(uid_shift_socket_pair[0], &arg_uid_shift, sizeof arg_uid_shift, 0); + if (l < 0) + return log_error_errno(errno, "Failed to read UID shift: %m"); + if (l != sizeof arg_uid_shift) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading UID shift."); + + if (arg_userns_mode == USER_NAMESPACE_PICK) { + /* If we are supposed to pick the UID shift, let's try to use the shift read from the + * image, but if that's already in use, pick a new one, and report back to the child, + * which one we now picked. */ + + r = uid_shift_pick(&arg_uid_shift, &uid_shift_lock); + if (r < 0) + return log_error_errno(r, "Failed to pick suitable UID/GID range: %m"); + + l = send(uid_shift_socket_pair[0], &arg_uid_shift, sizeof arg_uid_shift, MSG_NOSIGNAL); + if (l < 0) + return log_error_errno(errno, "Failed to send UID shift: %m"); + if (l != sizeof arg_uid_shift) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write while writing UID shift."); + } + } + + if (arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_UNKNOWN) { + /* The child let us know the support cgroup mode it might have read from the image. */ + l = recv(unified_cgroup_hierarchy_socket_pair[0], &arg_unified_cgroup_hierarchy, sizeof(arg_unified_cgroup_hierarchy), 0); + if (l < 0) + return log_error_errno(errno, "Failed to read cgroup mode: %m"); + if (l != sizeof(arg_unified_cgroup_hierarchy)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading cgroup mode (%zu bytes).%s", + l, l == 0 ? " The child is most likely dead." : ""); + } + + /* Wait for the outer child. */ + r = wait_for_terminate_and_check("(sd-namespace)", *pid, WAIT_LOG_ABNORMAL); + if (r < 0) + return r; + if (r != EXIT_SUCCESS) + return -EIO; + + /* And now retrieve the PID of the inner child. */ + l = recv(pid_socket_pair[0], pid, sizeof *pid, 0); + if (l < 0) + return log_error_errno(errno, "Failed to read inner child PID: %m"); + if (l != sizeof *pid) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading inner child PID."); + + /* We also retrieve container UUID in case it was generated by outer child */ + l = recv(uuid_socket_pair[0], &arg_uuid, sizeof arg_uuid, 0); + if (l < 0) + return log_error_errno(errno, "Failed to read container machine ID: %m"); + if (l != sizeof(arg_uuid)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading container machined ID."); + + /* We also retrieve the socket used for notifications generated by outer child */ + notify_socket = receive_one_fd(notify_socket_pair[0], 0); + if (notify_socket < 0) + return log_error_errno(notify_socket, + "Failed to receive notification socket from the outer child: %m"); + + log_debug("Init process invoked as PID "PID_FMT, *pid); + + if (arg_userns_mode != USER_NAMESPACE_NO) { + if (!barrier_place_and_sync(&barrier)) /* #1 */ + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early."); + + r = setup_uid_map(*pid); + if (r < 0) + return r; + + (void) barrier_place(&barrier); /* #2 */ + } + + if (arg_private_network) { + if (!arg_network_namespace_path) { + /* Wait until the child has unshared its network namespace. */ + if (!barrier_place_and_sync(&barrier)) /* #3 */ + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early"); + } + + r = move_network_interfaces(*pid, arg_network_interfaces); + if (r < 0) + return r; + + if (arg_network_veth) { + r = setup_veth(arg_machine, *pid, veth_name, + arg_network_bridge || arg_network_zone); + if (r < 0) + return r; + else if (r > 0) + ifi = r; + + if (arg_network_bridge) { + /* Add the interface to a bridge */ + r = setup_bridge(veth_name, arg_network_bridge, false); + if (r < 0) + return r; + if (r > 0) + ifi = r; + } else if (arg_network_zone) { + /* Add the interface to a bridge, possibly creating it */ + r = setup_bridge(veth_name, arg_network_zone, true); + if (r < 0) + return r; + if (r > 0) + ifi = r; + } + } + + r = setup_veth_extra(arg_machine, *pid, arg_network_veth_extra); + if (r < 0) + return r; + + /* We created the primary and extra veth links now; let's remember this, so that we know to + remove them later on. Note that we don't bother with removing veth links that were created + here when their setup failed half-way, because in that case the kernel should be able to + remove them on its own, since they cannot be referenced by anything yet. */ + *veth_created = true; + + r = setup_macvlan(arg_machine, *pid, arg_network_macvlan); + if (r < 0) + return r; + + r = setup_ipvlan(arg_machine, *pid, arg_network_ipvlan); + if (r < 0) + return r; + } + + if (arg_register || !arg_keep_unit) { + r = sd_bus_default_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to open system bus: %m"); + + r = sd_bus_set_close_on_exit(bus, false); + if (r < 0) + return log_error_errno(r, "Failed to disable close-on-exit behaviour: %m"); + } + + if (!arg_keep_unit) { + /* When a new scope is created for this container, then we'll be registered as its controller, in which + * case PID 1 will send us a friendly RequestStop signal, when it is asked to terminate the + * scope. Let's hook into that, and cleanly shut down the container, and print a friendly message. */ + + r = sd_bus_match_signal_async( + bus, + NULL, + "org.freedesktop.systemd1", + NULL, + "org.freedesktop.systemd1.Scope", + "RequestStop", + on_request_stop, NULL, PID_TO_PTR(*pid)); + if (r < 0) + return log_error_errno(r, "Failed to request RequestStop match: %m"); + } + + if (arg_register) { + r = register_machine( + bus, + arg_machine, + *pid, + arg_directory, + arg_uuid, + ifi, + arg_slice, + arg_custom_mounts, arg_n_custom_mounts, + arg_kill_signal, + arg_property, + arg_property_message, + arg_keep_unit, + arg_container_service_name); + if (r < 0) + return r; + + } else if (!arg_keep_unit) { + r = allocate_scope( + bus, + arg_machine, + *pid, + arg_slice, + arg_custom_mounts, arg_n_custom_mounts, + arg_kill_signal, + arg_property, + arg_property_message); + if (r < 0) + return r; + + } else if (arg_slice || arg_property) + log_notice("Machine and scope registration turned off, --slice= and --property= settings will have no effect."); + + r = create_subcgroup(*pid, arg_keep_unit, arg_unified_cgroup_hierarchy); + if (r < 0) + return r; + + r = sync_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift); + if (r < 0) + return r; + + r = chown_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift); + if (r < 0) + return r; + + /* Notify the child that the parent is ready with all + * its setup (including cgroup-ification), and that + * the child can now hand over control to the code to + * run inside the container. */ + (void) barrier_place(&barrier); /* #4 */ + + /* Block SIGCHLD here, before notifying child. + * process_pty() will handle it with the other signals. */ + assert_se(sigprocmask(SIG_BLOCK, &mask_chld, NULL) >= 0); + + /* Reset signal to default */ + r = default_signals(SIGCHLD, -1); + if (r < 0) + return log_error_errno(r, "Failed to reset SIGCHLD: %m"); + + r = sd_event_new(&event); + if (r < 0) + return log_error_errno(r, "Failed to get default event source: %m"); + + (void) sd_event_set_watchdog(event, true); + + if (bus) { + r = sd_bus_attach_event(bus, event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + } + + r = setup_sd_notify_parent(event, notify_socket, PID_TO_PTR(*pid), ¬ify_event_source); + if (r < 0) + return r; + + /* Let the child know that we are ready and wait that the child is completely ready now. */ + if (!barrier_place_and_sync(&barrier)) /* #5 */ + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early."); + + /* At this point we have made use of the UID we picked, and thus nss-mymachines + * will make them appear in getpwuid(), thus we can release the /etc/passwd lock. */ + etc_passwd_lock = safe_close(etc_passwd_lock); + + (void) sd_notifyf(false, + "STATUS=Container running.\n" + "X_NSPAWN_LEADER_PID=" PID_FMT, *pid); + if (!arg_notify_ready) + (void) sd_notify(false, "READY=1\n"); + + if (arg_kill_signal > 0) { + /* Try to kill the init system on SIGINT or SIGTERM */ + (void) sd_event_add_signal(event, NULL, SIGINT, on_orderly_shutdown, PID_TO_PTR(*pid)); + (void) sd_event_add_signal(event, NULL, SIGTERM, on_orderly_shutdown, PID_TO_PTR(*pid)); + } else { + /* Immediately exit */ + (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); + (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); + } + + /* Exit when the child exits */ + (void) sd_event_add_signal(event, NULL, SIGCHLD, on_sigchld, PID_TO_PTR(*pid)); + + if (arg_expose_ports) { + r = expose_port_watch_rtnl(event, rtnl_socket_pair[0], on_address_change, exposed, &rtnl); + if (r < 0) + return r; + + (void) expose_port_execute(rtnl, arg_expose_ports, exposed); + } + + rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]); + + if (arg_console_mode != CONSOLE_PIPE) { + _cleanup_close_ int fd = -1; + PTYForwardFlags flags = 0; + + /* Retrieve the master pty allocated by inner child */ + fd = receive_one_fd(master_pty_socket_pair[0], 0); + if (fd < 0) + return log_error_errno(fd, "Failed to receive master pty from the inner child: %m"); + + switch (arg_console_mode) { + + case CONSOLE_READ_ONLY: + flags |= PTY_FORWARD_READ_ONLY; + + _fallthrough_; + + case CONSOLE_INTERACTIVE: + flags |= PTY_FORWARD_IGNORE_VHANGUP; + + r = pty_forward_new(event, fd, flags, &forward); + if (r < 0) + return log_error_errno(r, "Failed to create PTY forwarder: %m"); + + if (arg_console_width != (unsigned) -1 || arg_console_height != (unsigned) -1) + (void) pty_forward_set_width_height(forward, + arg_console_width, + arg_console_height); + break; + + default: + assert(arg_console_mode == CONSOLE_PASSIVE); + } + + *master = TAKE_FD(fd); + } + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + if (forward) { + char last_char = 0; + + (void) pty_forward_get_last_char(forward, &last_char); + forward = pty_forward_free(forward); + + if (!arg_quiet && last_char != '\n') + putc('\n', stdout); + } + + /* Kill if it is not dead yet anyway */ + if (!arg_register && !arg_keep_unit && bus) + terminate_scope(bus, arg_machine); + + /* Normally redundant, but better safe than sorry */ + (void) kill(*pid, SIGKILL); + + r = wait_for_container(*pid, &container_status); + *pid = 0; + + /* Tell machined that we are gone. */ + if (bus) + (void) unregister_machine(bus, arg_machine); + + if (r < 0) + /* We failed to wait for the container, or the container exited abnormally. */ + return r; + if (r > 0 || container_status == CONTAINER_TERMINATED) { + /* r > 0 → The container exited with a non-zero status. + * As a special case, we need to replace 133 with a different value, + * because 133 is special-cased in the service file to reboot the container. + * otherwise → The container exited with zero status and a reboot was not requested. + */ + if (r == EXIT_FORCE_RESTART) + r = EXIT_FAILURE; /* replace 133 with the general failure code */ + *ret = r; + return 0; /* finito */ + } + + /* CONTAINER_REBOOTED, loop again */ + + if (arg_keep_unit) { + /* Special handling if we are running as a service: instead of simply + * restarting the machine we want to restart the entire service, so let's + * inform systemd about this with the special exit code 133. The service + * file uses RestartForceExitStatus=133 so that this results in a full + * nspawn restart. This is necessary since we might have cgroup parameters + * set we want to have flushed out. */ + *ret = EXIT_FORCE_RESTART; + return 0; /* finito */ + } + + expose_port_flush(arg_expose_ports, exposed); + + (void) remove_veth_links(veth_name, arg_network_veth_extra); + *veth_created = false; + return 1; /* loop again */ +} + +static int initialize_rlimits(void) { + /* The default resource limits the kernel passes to PID 1, as per kernel 4.16. Let's pass our container payload + * the same values as the kernel originally passed to PID 1, in order to minimize differences between host and + * container execution environments. */ + + static const struct rlimit kernel_defaults[_RLIMIT_MAX] = { + [RLIMIT_AS] = { RLIM_INFINITY, RLIM_INFINITY }, + [RLIMIT_CORE] = { 0, RLIM_INFINITY }, + [RLIMIT_CPU] = { RLIM_INFINITY, RLIM_INFINITY }, + [RLIMIT_DATA] = { RLIM_INFINITY, RLIM_INFINITY }, + [RLIMIT_FSIZE] = { RLIM_INFINITY, RLIM_INFINITY }, + [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, + [RLIMIT_MEMLOCK] = { 65536, 65536 }, + [RLIMIT_MSGQUEUE] = { 819200, 819200 }, + [RLIMIT_NICE] = { 0, 0 }, + [RLIMIT_NOFILE] = { 1024, 4096 }, + [RLIMIT_RSS] = { RLIM_INFINITY, RLIM_INFINITY }, + [RLIMIT_RTPRIO] = { 0, 0 }, + [RLIMIT_RTTIME] = { RLIM_INFINITY, RLIM_INFINITY }, + [RLIMIT_STACK] = { 8388608, RLIM_INFINITY }, + + /* The kernel scales the default for RLIMIT_NPROC and RLIMIT_SIGPENDING based on the system's amount of + * RAM. To provide best compatibility we'll read these limits off PID 1 instead of hardcoding them + * here. This is safe as we know that PID 1 doesn't change these two limits and thus the original + * kernel's initialization should still be valid during runtime — at least if PID 1 is systemd. Note + * that PID 1 changes a number of other resource limits during early initialization which is why we + * don't read the other limits from PID 1 but prefer the static table above. */ + }; + + int rl; + + for (rl = 0; rl < _RLIMIT_MAX; rl++) { + /* Let's only fill in what the user hasn't explicitly configured anyway */ + if ((arg_settings_mask & (SETTING_RLIMIT_FIRST << rl)) == 0) { + const struct rlimit *v; + struct rlimit buffer; + + if (IN_SET(rl, RLIMIT_NPROC, RLIMIT_SIGPENDING)) { + /* For these two let's read the limits off PID 1. See above for an explanation. */ + + if (prlimit(1, rl, NULL, &buffer) < 0) + return log_error_errno(errno, "Failed to read resource limit RLIMIT_%s of PID 1: %m", rlimit_to_string(rl)); + + v = &buffer; + } else + v = kernel_defaults + rl; + + arg_rlimit[rl] = newdup(struct rlimit, v, 1); + if (!arg_rlimit[rl]) + return log_oom(); + } + + if (DEBUG_LOGGING) { + _cleanup_free_ char *k = NULL; + + (void) rlimit_format(arg_rlimit[rl], &k); + log_debug("Setting RLIMIT_%s to %s.", rlimit_to_string(rl), k); + } + } + + return 0; +} + +static int run(int argc, char *argv[]) { + bool secondary = false, remove_directory = false, remove_image = false, + veth_created = false, remove_tmprootdir = false; + _cleanup_close_ int master = -1; + _cleanup_fdset_free_ FDSet *fds = NULL; + int r, n_fd_passed, ret = EXIT_SUCCESS; + char veth_name[IFNAMSIZ] = ""; + union in_addr_union exposed = {}; + _cleanup_(release_lock_file) LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT; + char tmprootdir[] = "/tmp/nspawn-root-XXXXXX"; + _cleanup_(loop_device_unrefp) LoopDevice *loop = NULL; + _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL; + _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL; + pid_t pid = 0; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + + r = must_be_root(); + if (r < 0) + goto finish; + + r = initialize_rlimits(); + if (r < 0) + goto finish; + + r = load_oci_bundle(); + if (r < 0) + goto finish; + + r = determine_names(); + if (r < 0) + goto finish; + + r = load_settings(); + if (r < 0) + goto finish; + + r = cg_unified(); + if (r < 0) { + log_error_errno(r, "Failed to determine whether the unified cgroups hierarchy is used: %m"); + goto finish; + } + + r = verify_arguments(); + if (r < 0) + goto finish; + + /* Reapply environment settings. */ + (void) detect_unified_cgroup_hierarchy_from_environment(); + + /* Ignore SIGPIPE here, because we use splice() on the ptyfwd stuff and that will generate SIGPIPE if + * the result is closed. Note that the container payload child will reset signal mask+handler anyway, + * so just turning this off here means we only turn it off in nspawn itself, not any children. */ + (void) ignore_signals(SIGPIPE, -1); + + n_fd_passed = sd_listen_fds(false); + if (n_fd_passed > 0) { + r = fdset_new_listen_fds(&fds, false); + if (r < 0) { + log_error_errno(r, "Failed to collect file descriptors: %m"); + goto finish; + } + } + + /* The "default" umask. This is appropriate for most file and directory + * operations performed by nspawn, and is the umask that will be used for + * the child. Functions like copy_devnodes() change the umask temporarily. */ + umask(0022); + + if (arg_directory) { + assert(!arg_image); + + /* Safety precaution: let's not allow running images from the live host OS image, as long as + * /var from the host will propagate into container dynamically (because bad things happen if + * two systems write to the same /var). Let's allow it for the special cases where /var is + * either copied (i.e. --ephemeral) or replaced (i.e. --volatile=yes|state). */ + if (path_equal(arg_directory, "/") && !(arg_ephemeral || IN_SET(arg_volatile_mode, VOLATILE_YES, VOLATILE_STATE))) { + log_error("Spawning container on root directory is not supported. Consider using --ephemeral, --volatile=yes or --volatile=state."); + r = -EINVAL; + goto finish; + } + + if (arg_ephemeral) { + _cleanup_free_ char *np = NULL; + + r = chase_symlinks_and_update(&arg_directory, 0); + if (r < 0) + goto finish; + + /* If the specified path is a mount point we generate the new snapshot immediately + * inside it under a random name. However if the specified is not a mount point we + * create the new snapshot in the parent directory, just next to it. */ + r = path_is_mount_point(arg_directory, NULL, 0); + if (r < 0) { + log_error_errno(r, "Failed to determine whether directory %s is mount point: %m", arg_directory); + goto finish; + } + if (r > 0) + r = tempfn_random_child(arg_directory, "machine.", &np); + else + r = tempfn_random(arg_directory, "machine.", &np); + if (r < 0) { + log_error_errno(r, "Failed to generate name for directory snapshot: %m"); + goto finish; + } + + /* We take an exclusive lock on this image, since it's our private, ephemeral copy + * only owned by us and noone else. */ + r = image_path_lock(np, LOCK_EX|LOCK_NB, &tree_global_lock, &tree_local_lock); + if (r < 0) { + log_error_errno(r, "Failed to lock %s: %m", np); + goto finish; + } + + { + BLOCK_SIGNALS(SIGINT); + r = btrfs_subvol_snapshot(arg_directory, np, + (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | + BTRFS_SNAPSHOT_FALLBACK_COPY | + BTRFS_SNAPSHOT_FALLBACK_DIRECTORY | + BTRFS_SNAPSHOT_RECURSIVE | + BTRFS_SNAPSHOT_QUOTA | + BTRFS_SNAPSHOT_SIGINT); + } + if (r == -EINTR) { + log_error_errno(r, "Interrupted while copying file system tree to %s, removed again.", np); + goto finish; + } + if (r < 0) { + log_error_errno(r, "Failed to create snapshot %s from %s: %m", np, arg_directory); + goto finish; + } + + free_and_replace(arg_directory, np); + remove_directory = true; + } else { + r = chase_symlinks_and_update(&arg_directory, arg_template ? CHASE_NONEXISTENT : 0); + if (r < 0) + goto finish; + + r = image_path_lock(arg_directory, (arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB, &tree_global_lock, &tree_local_lock); + if (r == -EBUSY) { + log_error_errno(r, "Directory tree %s is currently busy.", arg_directory); + goto finish; + } + if (r < 0) { + log_error_errno(r, "Failed to lock %s: %m", arg_directory); + goto finish; + } + + if (arg_template) { + r = chase_symlinks_and_update(&arg_template, 0); + if (r < 0) + goto finish; + + { + BLOCK_SIGNALS(SIGINT); + r = btrfs_subvol_snapshot(arg_template, arg_directory, + (arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | + BTRFS_SNAPSHOT_FALLBACK_COPY | + BTRFS_SNAPSHOT_FALLBACK_DIRECTORY | + BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE | + BTRFS_SNAPSHOT_RECURSIVE | + BTRFS_SNAPSHOT_QUOTA | + BTRFS_SNAPSHOT_SIGINT); + } + if (r == -EEXIST) + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, + "Directory %s already exists, not populating from template %s.", arg_directory, arg_template); + else if (r == -EINTR) { + log_error_errno(r, "Interrupted while copying file system tree to %s, removed again.", arg_directory); + goto finish; + } else if (r < 0) { + log_error_errno(r, "Couldn't create snapshot %s from %s: %m", arg_directory, arg_template); + goto finish; + } else + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, + "Populated %s from template %s.", arg_directory, arg_template); + } + } + + if (arg_start_mode == START_BOOT) { + const char *p; + + if (arg_pivot_root_new) + p = prefix_roota(arg_directory, arg_pivot_root_new); + else + p = arg_directory; + + if (path_is_os_tree(p) <= 0) { + log_error("Directory %s doesn't look like an OS root directory (os-release file is missing). Refusing.", p); + r = -EINVAL; + goto finish; + } + } else { + const char *p, *q; + + if (arg_pivot_root_new) + p = prefix_roota(arg_directory, arg_pivot_root_new); + else + p = arg_directory; + + q = strjoina(p, "/usr/"); + + if (laccess(q, F_OK) < 0) { + log_error("Directory %s doesn't look like it has an OS tree. Refusing.", p); + r = -EINVAL; + goto finish; + } + } + + } else { + assert(arg_image); + assert(!arg_template); + + r = chase_symlinks_and_update(&arg_image, 0); + if (r < 0) + goto finish; + + if (arg_ephemeral) { + _cleanup_free_ char *np = NULL; + + r = tempfn_random(arg_image, "machine.", &np); + if (r < 0) { + log_error_errno(r, "Failed to generate name for image snapshot: %m"); + goto finish; + } + + /* Always take an exclusive lock on our own ephemeral copy. */ + r = image_path_lock(np, LOCK_EX|LOCK_NB, &tree_global_lock, &tree_local_lock); + if (r < 0) { + r = log_error_errno(r, "Failed to create image lock: %m"); + goto finish; + } + + { + BLOCK_SIGNALS(SIGINT); + r = copy_file(arg_image, np, O_EXCL, arg_read_only ? 0400 : 0600, FS_NOCOW_FL, FS_NOCOW_FL, COPY_REFLINK|COPY_CRTIME|COPY_SIGINT); + } + if (r == -EINTR) { + log_error_errno(r, "Interrupted while copying image file to %s, removed again.", np); + goto finish; + } + if (r < 0) { + r = log_error_errno(r, "Failed to copy image file: %m"); + goto finish; + } + + free_and_replace(arg_image, np); + remove_image = true; + } else { + r = image_path_lock(arg_image, (arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB, &tree_global_lock, &tree_local_lock); + if (r == -EBUSY) { + r = log_error_errno(r, "Disk image %s is currently busy.", arg_image); + goto finish; + } + if (r < 0) { + r = log_error_errno(r, "Failed to create image lock: %m"); + goto finish; + } + + if (!arg_root_hash) { + r = root_hash_load(arg_image, &arg_root_hash, &arg_root_hash_size); + if (r < 0) { + log_error_errno(r, "Failed to load root hash file for %s: %m", arg_image); + goto finish; + } + } + } + + if (!mkdtemp(tmprootdir)) { + r = log_error_errno(errno, "Failed to create temporary directory: %m"); + goto finish; + } + + remove_tmprootdir = true; + + arg_directory = strdup(tmprootdir); + if (!arg_directory) { + r = log_oom(); + goto finish; + } + + r = loop_device_make_by_path(arg_image, arg_read_only ? O_RDONLY : O_RDWR, &loop); + if (r < 0) { + log_error_errno(r, "Failed to set up loopback block device: %m"); + goto finish; + } + + r = dissect_image_and_warn( + loop->fd, + arg_image, + arg_root_hash, arg_root_hash_size, + DISSECT_IMAGE_REQUIRE_ROOT, + &dissected_image); + if (r == -ENOPKG) { + /* dissected_image_and_warn() already printed a brief error message. Extend on that with more details */ + log_notice("Note that the disk image needs to\n" + " a) either contain only a single MBR partition of type 0x83 that is marked bootable\n" + " b) or contain a single GPT partition of type 0FC63DAF-8483-4772-8E79-3D69D8477DE4\n" + " c) or follow http://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/\n" + " d) or contain a file system without a partition table\n" + "in order to be bootable with systemd-nspawn."); + goto finish; + } + if (r < 0) + goto finish; + + if (!arg_root_hash && dissected_image->can_verity) + log_notice("Note: image %s contains verity information, but no root hash specified! Proceeding without integrity checking.", arg_image); + + r = dissected_image_decrypt_interactively(dissected_image, NULL, arg_root_hash, arg_root_hash_size, 0, &decrypted_image); + if (r < 0) + goto finish; + + /* Now that we mounted the image, let's try to remove it again, if it is ephemeral */ + if (remove_image && unlink(arg_image) >= 0) + remove_image = false; + } + + r = custom_mount_prepare_all(arg_directory, arg_custom_mounts, arg_n_custom_mounts); + if (r < 0) + goto finish; + + if (arg_console_mode < 0) + arg_console_mode = + isatty(STDIN_FILENO) > 0 && + isatty(STDOUT_FILENO) > 0 ? CONSOLE_INTERACTIVE : CONSOLE_READ_ONLY; + + if (arg_console_mode == CONSOLE_PIPE) /* if we pass STDERR on to the container, don't add our own logs into it too */ + arg_quiet = true; + + if (!arg_quiet) + log_info("Spawning container %s on %s.\nPress ^] three times within 1s to kill container.", + arg_machine, arg_image ?: arg_directory); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); + + if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) < 0) { + r = log_error_errno(errno, "Failed to become subreaper: %m"); + goto finish; + } + + for (;;) { + r = run_container(dissected_image, + secondary, + fds, + veth_name, &veth_created, + &exposed, &master, + &pid, &ret); + if (r <= 0) + break; + } + +finish: + (void) sd_notify(false, + r == 0 && ret == EXIT_FORCE_RESTART ? "STOPPING=1\nSTATUS=Restarting..." : + "STOPPING=1\nSTATUS=Terminating..."); + + if (pid > 0) + (void) kill(pid, SIGKILL); + + /* Try to flush whatever is still queued in the pty */ + if (master >= 0) { + (void) copy_bytes(master, STDOUT_FILENO, (uint64_t) -1, 0); + master = safe_close(master); + } + + if (pid > 0) + (void) wait_for_terminate(pid, NULL); + + pager_close(); + + if (remove_directory && arg_directory) { + int k; + + k = rm_rf(arg_directory, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + if (k < 0) + log_warning_errno(k, "Cannot remove '%s', ignoring: %m", arg_directory); + } + + if (remove_image && arg_image) { + if (unlink(arg_image) < 0) + log_warning_errno(errno, "Can't remove image file '%s', ignoring: %m", arg_image); + } + + if (remove_tmprootdir) { + if (rmdir(tmprootdir) < 0) + log_debug_errno(errno, "Can't remove temporary root directory '%s', ignoring: %m", tmprootdir); + } + + if (arg_machine) { + const char *p; + + p = strjoina("/run/systemd/nspawn/propagate/", arg_machine); + (void) rm_rf(p, REMOVE_ROOT); + } + + expose_port_flush(arg_expose_ports, &exposed); + + if (veth_created) + (void) remove_veth_links(veth_name, arg_network_veth_extra); + (void) remove_bridge(arg_network_zone); + + custom_mount_free_all(arg_custom_mounts, arg_n_custom_mounts); + expose_port_free_all(arg_expose_ports); + rlimit_free_all(arg_rlimit); + device_node_array_free(arg_extra_nodes, arg_n_extra_nodes); + + if (r < 0) + return r; + + return ret; +} + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/nspawn/test-nspawn-tables.c b/src/nspawn/test-nspawn-tables.c new file mode 100644 index 00000000..2c5f2ef6 --- /dev/null +++ b/src/nspawn/test-nspawn-tables.c @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "nspawn-settings.h" +#include "test-tables.h" + +int main(int argc, char **argv) { + test_table(resolv_conf_mode, RESOLV_CONF_MODE); + test_table(timezone_mode, TIMEZONE_MODE); + + return 0; +} diff --git a/src/nspawn/test-patch-uid.c b/src/nspawn/test-patch-uid.c new file mode 100644 index 00000000..a6829629 --- /dev/null +++ b/src/nspawn/test-patch-uid.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "log.h" +#include "nspawn-patch-uid.h" +#include "user-util.h" +#include "string-util.h" +#include "tests.h" + +int main(int argc, char *argv[]) { + uid_t shift, range; + int r; + + test_setup_logging(LOG_DEBUG); + + if (argc != 4) { + log_error("Expected PATH SHIFT RANGE parameters."); + return EXIT_FAILURE; + } + + r = parse_uid(argv[2], &shift); + if (r < 0) { + log_error_errno(r, "Failed to parse UID shift %s.", argv[2]); + return EXIT_FAILURE; + } + + r = parse_gid(argv[3], &range); + if (r < 0) { + log_error_errno(r, "Failed to parse UID range %s.", argv[3]); + return EXIT_FAILURE; + } + + r = path_patch_uid(argv[1], shift, range); + if (r < 0) { + log_error_errno(r, "Failed to patch directory tree: %m"); + return EXIT_FAILURE; + } + + log_info("Changed: %s", yes_no(r)); + + return EXIT_SUCCESS; +} diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c new file mode 100644 index 00000000..8c16b7f3 --- /dev/null +++ b/src/nss-myhostname/nss-myhostname.c @@ -0,0 +1,500 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "errno-util.h" +#include "hostname-util.h" +#include "local-addresses.h" +#include "macro.h" +#include "nss-util.h" +#include "signal-util.h" +#include "string-util.h" + +/* We use 127.0.0.2 as IPv4 address. This has the advantage over + * 127.0.0.1 that it can be translated back to the local hostname. For + * IPv6 we use ::1 which unfortunately will not translate back to the + * hostname but instead something like "localhost" or so. */ + +#define LOCALADDRESS_IPV4 (htobe32(0x7F000002)) +#define LOCALADDRESS_IPV6 &in6addr_loopback + +NSS_GETHOSTBYNAME_PROTOTYPES(myhostname); +NSS_GETHOSTBYADDR_PROTOTYPES(myhostname); + +enum nss_status _nss_myhostname_gethostbyname4_r( + const char *name, + struct gaih_addrtuple **pat, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp) { + + struct gaih_addrtuple *r_tuple, *r_tuple_prev = NULL; + _cleanup_free_ struct local_address *addresses = NULL; + _cleanup_free_ char *hn = NULL; + const char *canonical = NULL; + int n_addresses = 0; + uint32_t local_address_ipv4; + struct local_address *a; + size_t l, idx, ms; + char *r_name; + unsigned n; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(pat); + assert(buffer); + assert(errnop); + assert(h_errnop); + + if (is_localhost(name)) { + /* We respond to 'localhost', so that /etc/hosts + * is optional */ + + canonical = "localhost"; + local_address_ipv4 = htobe32(INADDR_LOOPBACK); + + } else if (is_gateway_hostname(name)) { + + n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses); + if (n_addresses <= 0) + goto not_found; + + canonical = "_gateway"; + + } else { + hn = gethostname_malloc(); + if (!hn) { + UNPROTECT_ERRNO; + *errnop = ENOMEM; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_TRYAGAIN; + } + + /* We respond to our local host name, our hostname suffixed with a single dot. */ + if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) + goto not_found; + + n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses); + if (n_addresses < 0) + n_addresses = 0; + + canonical = hn; + local_address_ipv4 = LOCALADDRESS_IPV4; + } + + l = strlen(canonical); + ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * (n_addresses > 0 ? n_addresses : 2); + if (buflen < ms) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + /* First, fill in hostname */ + r_name = buffer; + memcpy(r_name, canonical, l+1); + idx = ALIGN(l+1); + + assert(n_addresses >= 0); + if (n_addresses == 0) { + /* Second, fill in IPv6 tuple */ + r_tuple = (struct gaih_addrtuple*) (buffer + idx); + r_tuple->next = r_tuple_prev; + r_tuple->name = r_name; + r_tuple->family = AF_INET6; + memcpy(r_tuple->addr, LOCALADDRESS_IPV6, 16); + r_tuple->scopeid = 0; + + idx += ALIGN(sizeof(struct gaih_addrtuple)); + r_tuple_prev = r_tuple; + + /* Third, fill in IPv4 tuple */ + r_tuple = (struct gaih_addrtuple*) (buffer + idx); + r_tuple->next = r_tuple_prev; + r_tuple->name = r_name; + r_tuple->family = AF_INET; + *(uint32_t*) r_tuple->addr = local_address_ipv4; + r_tuple->scopeid = 0; + + idx += ALIGN(sizeof(struct gaih_addrtuple)); + r_tuple_prev = r_tuple; + } + + /* Fourth, fill actual addresses in, but in backwards order */ + for (a = addresses + n_addresses - 1, n = 0; (int) n < n_addresses; n++, a--) { + r_tuple = (struct gaih_addrtuple*) (buffer + idx); + r_tuple->next = r_tuple_prev; + r_tuple->name = r_name; + r_tuple->family = a->family; + r_tuple->scopeid = a->family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&a->address.in6) ? a->ifindex : 0; + memcpy(r_tuple->addr, &a->address, 16); + + idx += ALIGN(sizeof(struct gaih_addrtuple)); + r_tuple_prev = r_tuple; + } + + /* Verify the size matches */ + assert(idx == ms); + + /* Nscd expects us to store the first record in **pat. */ + if (*pat) + **pat = *r_tuple_prev; + else + *pat = r_tuple_prev; + + if (ttlp) + *ttlp = 0; + + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ + *h_errnop = NETDB_SUCCESS; + h_errno = 0; + + return NSS_STATUS_SUCCESS; + +not_found: + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; +} + +static enum nss_status fill_in_hostent( + const char *canonical, const char *additional, + int af, + struct local_address *addresses, unsigned n_addresses, + uint32_t local_address_ipv4, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp) { + + size_t l_canonical, l_additional, idx, ms, alen; + char *r_addr, *r_name, *r_aliases, *r_alias = NULL, *r_addr_list; + struct local_address *a; + unsigned n, c; + + assert(canonical); + assert(result); + assert(buffer); + assert(errnop); + assert(h_errnop); + + PROTECT_ERRNO; + + alen = FAMILY_ADDRESS_SIZE(af); + + for (a = addresses, n = 0, c = 0; n < n_addresses; a++, n++) + if (af == a->family) + c++; + + l_canonical = strlen(canonical); + l_additional = strlen_ptr(additional); + ms = ALIGN(l_canonical+1)+ + (additional ? ALIGN(l_additional+1) : 0) + + sizeof(char*) + + (additional ? sizeof(char*) : 0) + + (c > 0 ? c : 1) * ALIGN(alen) + + (c > 0 ? c+1 : 2) * sizeof(char*); + + if (buflen < ms) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + /* First, fill in hostnames */ + r_name = buffer; + memcpy(r_name, canonical, l_canonical+1); + idx = ALIGN(l_canonical+1); + + if (additional) { + r_alias = buffer + idx; + memcpy(r_alias, additional, l_additional+1); + idx += ALIGN(l_additional+1); + } + + /* Second, create aliases array */ + r_aliases = buffer + idx; + if (additional) { + ((char**) r_aliases)[0] = r_alias; + ((char**) r_aliases)[1] = NULL; + idx += 2*sizeof(char*); + } else { + ((char**) r_aliases)[0] = NULL; + idx += sizeof(char*); + } + + /* Third, add addresses */ + r_addr = buffer + idx; + if (c > 0) { + unsigned i = 0; + + for (a = addresses, n = 0; n < n_addresses; a++, n++) { + if (af != a->family) + continue; + + memcpy(r_addr + i*ALIGN(alen), &a->address, alen); + i++; + } + + assert(i == c); + idx += c*ALIGN(alen); + } else { + if (af == AF_INET) + *(uint32_t*) r_addr = local_address_ipv4; + else + memcpy(r_addr, LOCALADDRESS_IPV6, 16); + + idx += ALIGN(alen); + } + + /* Fourth, add address pointer array */ + r_addr_list = buffer + idx; + if (c > 0) { + unsigned i; + + for (i = 0; i < c; i++) + ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen); + + ((char**) r_addr_list)[i] = NULL; + idx += (c+1) * sizeof(char*); + + } else { + ((char**) r_addr_list)[0] = r_addr; + ((char**) r_addr_list)[1] = NULL; + idx += 2 * sizeof(char*); + } + + /* Verify the size matches */ + assert(idx == ms); + + result->h_name = r_name; + result->h_aliases = (char**) r_aliases; + result->h_addrtype = af; + result->h_length = alen; + result->h_addr_list = (char**) r_addr_list; + + if (ttlp) + *ttlp = 0; + + if (canonp) + *canonp = r_name; + + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ + *h_errnop = NETDB_SUCCESS; + h_errno = 0; + + return NSS_STATUS_SUCCESS; +} + +enum nss_status _nss_myhostname_gethostbyname3_r( + const char *name, + int af, + struct hostent *host, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp) { + + _cleanup_free_ struct local_address *addresses = NULL; + const char *canonical, *additional = NULL; + _cleanup_free_ char *hn = NULL; + uint32_t local_address_ipv4 = 0; + int n_addresses = 0; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(host); + assert(buffer); + assert(errnop); + assert(h_errnop); + + if (af == AF_UNSPEC) + af = AF_INET; + + if (!IN_SET(af, AF_INET, AF_INET6)) { + UNPROTECT_ERRNO; + *errnop = EAFNOSUPPORT; + *h_errnop = NO_DATA; + return NSS_STATUS_UNAVAIL; + } + + if (is_localhost(name)) { + canonical = "localhost"; + local_address_ipv4 = htobe32(INADDR_LOOPBACK); + + } else if (is_gateway_hostname(name)) { + + n_addresses = local_gateways(NULL, 0, af, &addresses); + if (n_addresses <= 0) + goto not_found; + + canonical = "_gateway"; + + } else { + hn = gethostname_malloc(); + if (!hn) { + UNPROTECT_ERRNO; + *errnop = ENOMEM; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_TRYAGAIN; + } + + if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) + goto not_found; + + n_addresses = local_addresses(NULL, 0, af, &addresses); + if (n_addresses < 0) + n_addresses = 0; + + canonical = hn; + additional = n_addresses <= 0 && af == AF_INET6 ? "localhost" : NULL; + local_address_ipv4 = LOCALADDRESS_IPV4; + } + + UNPROTECT_ERRNO; + + return fill_in_hostent( + canonical, additional, + af, + addresses, n_addresses, + local_address_ipv4, + host, + buffer, buflen, + errnop, h_errnop, + ttlp, + canonp); + +not_found: + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; +} + +enum nss_status _nss_myhostname_gethostbyaddr2_r( + const void* addr, socklen_t len, + int af, + struct hostent *host, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp) { + + const char *canonical = NULL, *additional = NULL; + uint32_t local_address_ipv4 = LOCALADDRESS_IPV4; + _cleanup_free_ struct local_address *addresses = NULL; + _cleanup_free_ char *hn = NULL; + int n_addresses = 0; + struct local_address *a; + bool additional_from_hostname = false; + unsigned n; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(addr); + assert(host); + assert(buffer); + assert(errnop); + assert(h_errnop); + + if (!IN_SET(af, AF_INET, AF_INET6)) { + UNPROTECT_ERRNO; + *errnop = EAFNOSUPPORT; + *h_errnop = NO_DATA; + return NSS_STATUS_UNAVAIL; + } + + if (len != FAMILY_ADDRESS_SIZE(af)) { + UNPROTECT_ERRNO; + *errnop = EINVAL; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + } + + if (af == AF_INET) { + if ((*(uint32_t*) addr) == LOCALADDRESS_IPV4) + goto found; + + if ((*(uint32_t*) addr) == htobe32(INADDR_LOOPBACK)) { + canonical = "localhost"; + local_address_ipv4 = htobe32(INADDR_LOOPBACK); + goto found; + } + + } else { + assert(af == AF_INET6); + + if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) { + canonical = "localhost"; + additional_from_hostname = true; + goto found; + } + } + + n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses); + for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { + if (af != a->family) + continue; + + if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) + goto found; + } + + addresses = mfree(addresses); + + n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses); + for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { + if (af != a->family) + continue; + + if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) { + canonical = "_gateway"; + goto found; + } + } + + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + +found: + if (!canonical || additional_from_hostname) { + hn = gethostname_malloc(); + if (!hn) { + UNPROTECT_ERRNO; + *errnop = ENOMEM; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_TRYAGAIN; + } + + if (!canonical) + canonical = hn; + else + additional = hn; + } + + UNPROTECT_ERRNO; + return fill_in_hostent( + canonical, additional, + af, + addresses, n_addresses, + local_address_ipv4, + host, + buffer, buflen, + errnop, h_errnop, + ttlp, + NULL); +} + +NSS_GETHOSTBYNAME_FALLBACKS(myhostname); +NSS_GETHOSTBYADDR_FALLBACKS(myhostname); diff --git a/src/nss-myhostname/nss-myhostname.sym b/src/nss-myhostname/nss-myhostname.sym new file mode 100644 index 00000000..fc7aa995 --- /dev/null +++ b/src/nss-myhostname/nss-myhostname.sym @@ -0,0 +1,19 @@ +/*** + SPDX-License-Identifier: LGPL-2.1+ + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. +***/ + +{ +global: + _nss_myhostname_gethostbyname_r; + _nss_myhostname_gethostbyname2_r; + _nss_myhostname_gethostbyname3_r; + _nss_myhostname_gethostbyname4_r; + _nss_myhostname_gethostbyaddr_r; + _nss_myhostname_gethostbyaddr2_r; +local: *; +}; diff --git a/src/nss-mymachines/nss-mymachines.c b/src/nss-mymachines/nss-mymachines.c new file mode 100644 index 00000000..364356da --- /dev/null +++ b/src/nss-mymachines/nss-mymachines.c @@ -0,0 +1,778 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" +#include "sd-login.h" + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "env-util.h" +#include "errno-util.h" +#include "format-util.h" +#include "hostname-util.h" +#include "in-addr-util.h" +#include "macro.h" +#include "memory-util.h" +#include "nss-util.h" +#include "signal-util.h" +#include "string-util.h" +#include "user-util.h" + +NSS_GETHOSTBYNAME_PROTOTYPES(mymachines); +NSS_GETPW_PROTOTYPES(mymachines); +NSS_GETGR_PROTOTYPES(mymachines); + +#define HOST_UID_LIMIT ((uid_t) UINT32_C(0x10000)) +#define HOST_GID_LIMIT ((gid_t) UINT32_C(0x10000)) + +static int count_addresses(sd_bus_message *m, int af, unsigned *ret) { + unsigned c = 0; + int r; + + assert(m); + assert(ret); + + while ((r = sd_bus_message_enter_container(m, 'r', "iay")) > 0) { + int family; + + r = sd_bus_message_read(m, "i", &family); + if (r < 0) + return r; + + r = sd_bus_message_skip(m, "ay"); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + if (af != AF_UNSPEC && family != af) + continue; + + c++; + } + if (r < 0) + return r; + + r = sd_bus_message_rewind(m, false); + if (r < 0) + return r; + + *ret = c; + return 0; +} + +static bool avoid_deadlock(void) { + + /* Check whether this lookup might have a chance of deadlocking because we are called from the service manager + * code activating systemd-machined.service. After all, we shouldn't synchronously do lookups to + * systemd-machined if we are required to finish before it can be started. This of course won't detect all + * possible dead locks of this kind, but it should work for the most obvious cases. */ + + if (geteuid() != 0) /* Ignore the env vars unless we are privileged. */ + return false; + + return streq_ptr(getenv("SYSTEMD_ACTIVATION_UNIT"), "systemd-machined.service") && + streq_ptr(getenv("SYSTEMD_ACTIVATION_SCOPE"), "system"); +} + +enum nss_status _nss_mymachines_gethostbyname4_r( + const char *name, + struct gaih_addrtuple **pat, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp) { + + struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ int *ifindices = NULL; + _cleanup_free_ char *class = NULL; + size_t l, ms, idx; + unsigned i = 0, c = 0; + char *r_name; + int n_ifindices, r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(pat); + assert(buffer); + assert(errnop); + assert(h_errnop); + + r = sd_machine_get_class(name, &class); + if (r < 0) + goto fail; + if (!streq(class, "container")) { + r = -ENOTTY; + goto fail; + } + + n_ifindices = sd_machine_get_ifindices(name, &ifindices); + if (n_ifindices < 0) { + r = n_ifindices; + goto fail; + } + + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetMachineAddresses", + NULL, + &reply, + "s", name); + if (r < 0) + goto fail; + + r = sd_bus_message_enter_container(reply, 'a', "(iay)"); + if (r < 0) + goto fail; + + r = count_addresses(reply, AF_UNSPEC, &c); + if (r < 0) + goto fail; + + if (c <= 0) { + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + + l = strlen(name); + ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c; + if (buflen < ms) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + /* First, append name */ + r_name = buffer; + memcpy(r_name, name, l+1); + idx = ALIGN(l+1); + + /* Second, append addresses */ + r_tuple_first = (struct gaih_addrtuple*) (buffer + idx); + while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) { + int family; + const void *a; + size_t sz; + + r = sd_bus_message_read(reply, "i", &family); + if (r < 0) + goto fail; + + r = sd_bus_message_read_array(reply, 'y', &a, &sz); + if (r < 0) + goto fail; + + r = sd_bus_message_exit_container(reply); + if (r < 0) + goto fail; + + if (!IN_SET(family, AF_INET, AF_INET6)) { + r = -EAFNOSUPPORT; + goto fail; + } + + if (sz != FAMILY_ADDRESS_SIZE(family)) { + r = -EINVAL; + goto fail; + } + + r_tuple = (struct gaih_addrtuple*) (buffer + idx); + r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple))); + r_tuple->name = r_name; + r_tuple->family = family; + r_tuple->scopeid = n_ifindices == 1 ? ifindices[0] : 0; + memcpy(r_tuple->addr, a, sz); + + idx += ALIGN(sizeof(struct gaih_addrtuple)); + i++; + } + + assert(i == c); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + goto fail; + + assert(idx == ms); + + if (*pat) + **pat = *r_tuple_first; + else + *pat = r_tuple_first; + + if (ttlp) + *ttlp = 0; + + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ + *h_errnop = NETDB_SUCCESS; + h_errno = 0; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; +} + +enum nss_status _nss_mymachines_gethostbyname3_r( + const char *name, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *class = NULL; + unsigned c = 0, i = 0; + char *r_name, *r_aliases, *r_addr, *r_addr_list; + size_t l, idx, ms, alen; + int r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(result); + assert(buffer); + assert(errnop); + assert(h_errnop); + + if (af == AF_UNSPEC) + af = AF_INET; + + if (af != AF_INET && af != AF_INET6) { + r = -EAFNOSUPPORT; + goto fail; + } + + r = sd_machine_get_class(name, &class); + if (r < 0) + goto fail; + if (!streq(class, "container")) { + r = -ENOTTY; + goto fail; + } + + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "GetMachineAddresses", + NULL, + &reply, + "s", name); + if (r < 0) + goto fail; + + r = sd_bus_message_enter_container(reply, 'a', "(iay)"); + if (r < 0) + goto fail; + + r = count_addresses(reply, af, &c); + if (r < 0) + goto fail; + + if (c <= 0) { + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + + alen = FAMILY_ADDRESS_SIZE(af); + l = strlen(name); + + ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*); + + if (buflen < ms) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + /* First, append name */ + r_name = buffer; + memcpy(r_name, name, l+1); + idx = ALIGN(l+1); + + /* Second, create aliases array */ + r_aliases = buffer + idx; + ((char**) r_aliases)[0] = NULL; + idx += sizeof(char*); + + /* Third, append addresses */ + r_addr = buffer + idx; + while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) { + int family; + const void *a; + size_t sz; + + r = sd_bus_message_read(reply, "i", &family); + if (r < 0) + goto fail; + + r = sd_bus_message_read_array(reply, 'y', &a, &sz); + if (r < 0) + goto fail; + + r = sd_bus_message_exit_container(reply); + if (r < 0) + goto fail; + + if (family != af) + continue; + + if (sz != alen) { + r = -EINVAL; + goto fail; + } + + memcpy(r_addr + i*ALIGN(alen), a, alen); + i++; + } + + assert(i == c); + idx += c * ALIGN(alen); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + goto fail; + + /* Third, append address pointer array */ + r_addr_list = buffer + idx; + for (i = 0; i < c; i++) + ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen); + + ((char**) r_addr_list)[i] = NULL; + idx += (c+1) * sizeof(char*); + + assert(idx == ms); + + result->h_name = r_name; + result->h_aliases = (char**) r_aliases; + result->h_addrtype = af; + result->h_length = alen; + result->h_addr_list = (char**) r_addr_list; + + if (ttlp) + *ttlp = 0; + + if (canonp) + *canonp = r_name; + + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ + *h_errnop = NETDB_SUCCESS; + h_errno = 0; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; +} + +NSS_GETHOSTBYNAME_FALLBACKS(mymachines); + +enum nss_status _nss_mymachines_getpwnam_r( + const char *name, + struct passwd *pwd, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const char *p, *e, *machine; + uint32_t mapped; + uid_t uid; + size_t l; + int r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(pwd); + + p = startswith(name, "vu-"); + if (!p) + return NSS_STATUS_NOTFOUND; + + e = strrchr(p, '-'); + if (!e || e == p) + return NSS_STATUS_NOTFOUND; + + if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */ + return NSS_STATUS_NOTFOUND; + + r = parse_uid(e + 1, &uid); + if (r < 0) + return NSS_STATUS_NOTFOUND; + + machine = strndupa(p, e - p); + if (!machine_name_is_valid(machine)) + return NSS_STATUS_NOTFOUND; + + if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) + /* Make sure we can't deadlock if we are invoked by dbus-daemon. This way, it won't be able to resolve + * these UIDs, but that should be unproblematic as containers should never be able to connect to a bus + * running on the host. */ + return NSS_STATUS_NOTFOUND; + + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "MapFromMachineUser", + &error, + &reply, + "su", + machine, (uint32_t) uid); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING)) + return NSS_STATUS_NOTFOUND; + + goto fail; + } + + r = sd_bus_message_read(reply, "u", &mapped); + if (r < 0) + goto fail; + + /* Refuse to work if the mapped address is in the host UID range, or if there was no mapping at all. */ + if (mapped < HOST_UID_LIMIT || mapped == uid) + return NSS_STATUS_NOTFOUND; + + l = strlen(name); + if (buflen < l+1) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + memcpy(buffer, name, l+1); + + pwd->pw_name = buffer; + pwd->pw_uid = mapped; + pwd->pw_gid = GID_NOBODY; + pwd->pw_gecos = buffer; + pwd->pw_passwd = (char*) "*"; /* locked */ + pwd->pw_dir = (char*) "/"; + pwd->pw_shell = (char*) NOLOGIN; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} + +enum nss_status _nss_mymachines_getpwuid_r( + uid_t uid, + struct passwd *pwd, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const char *machine; + uint32_t mapped; + int r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + if (!uid_is_valid(uid)) + return NSS_STATUS_NOTFOUND; + + /* We consider all uids < 65536 host uids */ + if (uid < HOST_UID_LIMIT) + return NSS_STATUS_NOTFOUND; + + if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) + return NSS_STATUS_NOTFOUND; + + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "MapToMachineUser", + &error, + &reply, + "u", + (uint32_t) uid); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING)) + return NSS_STATUS_NOTFOUND; + + goto fail; + } + + r = sd_bus_message_read(reply, "sou", &machine, NULL, &mapped); + if (r < 0) + goto fail; + + if (mapped == uid) + return NSS_STATUS_NOTFOUND; + + if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + pwd->pw_name = buffer; + pwd->pw_uid = uid; + pwd->pw_gid = GID_NOBODY; + pwd->pw_gecos = buffer; + pwd->pw_passwd = (char*) "*"; /* locked */ + pwd->pw_dir = (char*) "/"; + pwd->pw_shell = (char*) NOLOGIN; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} + +#pragma GCC diagnostic ignored "-Wsizeof-pointer-memaccess" + +enum nss_status _nss_mymachines_getgrnam_r( + const char *name, + struct group *gr, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const char *p, *e, *machine; + uint32_t mapped; + uid_t gid; + size_t l; + int r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(gr); + + p = startswith(name, "vg-"); + if (!p) + return NSS_STATUS_NOTFOUND; + + e = strrchr(p, '-'); + if (!e || e == p) + return NSS_STATUS_NOTFOUND; + + if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */ + return NSS_STATUS_NOTFOUND; + + r = parse_gid(e + 1, &gid); + if (r < 0) + return NSS_STATUS_NOTFOUND; + + machine = strndupa(p, e - p); + if (!machine_name_is_valid(machine)) + return NSS_STATUS_NOTFOUND; + + if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) + return NSS_STATUS_NOTFOUND; + + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "MapFromMachineGroup", + &error, + &reply, + "su", + machine, (uint32_t) gid); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING)) + return NSS_STATUS_NOTFOUND; + + goto fail; + } + + r = sd_bus_message_read(reply, "u", &mapped); + if (r < 0) + goto fail; + + if (mapped < HOST_GID_LIMIT || mapped == gid) + return NSS_STATUS_NOTFOUND; + + l = sizeof(char*) + strlen(name) + 1; + if (buflen < l) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + memzero(buffer, sizeof(char*)); + strcpy(buffer + sizeof(char*), name); + + gr->gr_name = buffer + sizeof(char*); + gr->gr_gid = mapped; + gr->gr_passwd = (char*) "*"; /* locked */ + gr->gr_mem = (char**) buffer; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} + +enum nss_status _nss_mymachines_getgrgid_r( + gid_t gid, + struct group *gr, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const char *machine; + uint32_t mapped; + int r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + if (!gid_is_valid(gid)) + return NSS_STATUS_NOTFOUND; + + /* We consider all gids < 65536 host gids */ + if (gid < HOST_GID_LIMIT) + return NSS_STATUS_NOTFOUND; + + if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) + return NSS_STATUS_NOTFOUND; + + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_call_method(bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "MapToMachineGroup", + &error, + &reply, + "u", + (uint32_t) gid); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING)) + return NSS_STATUS_NOTFOUND; + + goto fail; + } + + r = sd_bus_message_read(reply, "sou", &machine, NULL, &mapped); + if (r < 0) + goto fail; + + if (mapped == gid) + return NSS_STATUS_NOTFOUND; + + if (buflen < sizeof(char*) + 1) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + memzero(buffer, sizeof(char*)); + if (snprintf(buffer + sizeof(char*), buflen - sizeof(char*), "vg-%s-" GID_FMT, machine, (gid_t) mapped) >= (int) buflen) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + gr->gr_name = buffer + sizeof(char*); + gr->gr_gid = gid; + gr->gr_passwd = (char*) "*"; /* locked */ + gr->gr_mem = (char**) buffer; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} diff --git a/src/nss-mymachines/nss-mymachines.sym b/src/nss-mymachines/nss-mymachines.sym new file mode 100644 index 00000000..ade64474 --- /dev/null +++ b/src/nss-mymachines/nss-mymachines.sym @@ -0,0 +1,21 @@ +/*** + SPDX-License-Identifier: LGPL-2.1+ + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. +***/ + +{ +global: + _nss_mymachines_gethostbyname_r; + _nss_mymachines_gethostbyname2_r; + _nss_mymachines_gethostbyname3_r; + _nss_mymachines_gethostbyname4_r; + _nss_mymachines_getpwnam_r; + _nss_mymachines_getpwuid_r; + _nss_mymachines_getgrnam_r; + _nss_mymachines_getgrgid_r; +local: *; +}; diff --git a/src/nss-resolve/nss-resolve.c b/src/nss-resolve/nss-resolve.c new file mode 100644 index 00000000..de46a8d4 --- /dev/null +++ b/src/nss-resolve/nss-resolve.c @@ -0,0 +1,652 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "bus-common-errors.h" +#include "errno-util.h" +#include "in-addr-util.h" +#include "macro.h" +#include "nss-util.h" +#include "resolved-def.h" +#include "signal-util.h" +#include "string-util.h" + +NSS_GETHOSTBYNAME_PROTOTYPES(resolve); +NSS_GETHOSTBYADDR_PROTOTYPES(resolve); + +static bool bus_error_shall_fallback(sd_bus_error *e) { + return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) || + sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) || + sd_bus_error_has_name(e, SD_BUS_ERROR_NO_REPLY) || + sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED) || + sd_bus_error_has_name(e, SD_BUS_ERROR_DISCONNECTED) || + sd_bus_error_has_name(e, SD_BUS_ERROR_TIMEOUT); +} + +static int count_addresses(sd_bus_message *m, int af, const char **canonical) { + int c = 0, r; + + assert(m); + assert(canonical); + + r = sd_bus_message_enter_container(m, 'a', "(iiay)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_enter_container(m, 'r', "iiay")) > 0) { + int family, ifindex; + + assert_cc(sizeof(int32_t) == sizeof(int)); + + r = sd_bus_message_read(m, "ii", &ifindex, &family); + if (r < 0) + return r; + + r = sd_bus_message_skip(m, "ay"); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + if (af != AF_UNSPEC && family != af) + continue; + + c++; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + r = sd_bus_message_read(m, "s", canonical); + if (r < 0) + return r; + + r = sd_bus_message_rewind(m, true); + if (r < 0) + return r; + + return c; +} + +static uint32_t ifindex_to_scopeid(int family, const void *a, int ifindex) { + struct in6_addr in6; + + if (family != AF_INET6) + return 0; + + /* Some apps can't deal with the scope ID attached to non-link-local addresses. Hence, let's suppress that. */ + + assert(sizeof(in6) == FAMILY_ADDRESS_SIZE(AF_INET6)); + memcpy(&in6, a, sizeof(struct in6_addr)); + + return IN6_IS_ADDR_LINKLOCAL(&in6) ? ifindex : 0; +} + +static bool avoid_deadlock(void) { + + /* Check whether this lookup might have a chance of deadlocking because we are called from the service manager + * code activating systemd-resolved.service. After all, we shouldn't synchronously do lookups to + * systemd-resolved if we are required to finish before it can be started. This of course won't detect all + * possible dead locks of this kind, but it should work for the most obvious cases. */ + + if (geteuid() != 0) /* Ignore the env vars unless we are privileged. */ + return false; + + return streq_ptr(getenv("SYSTEMD_ACTIVATION_UNIT"), "systemd-resolved.service") && + streq_ptr(getenv("SYSTEMD_ACTIVATION_SCOPE"), "system"); +} + +enum nss_status _nss_resolve_gethostbyname4_r( + const char *name, + struct gaih_addrtuple **pat, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const char *canonical = NULL; + size_t l, ms, idx; + char *r_name; + int c, r, i = 0; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(pat); + assert(buffer); + assert(errnop); + assert(h_errnop); + + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_message_new_method_call( + bus, + &req, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResolveHostname"); + if (r < 0) + goto fail; + + r = sd_bus_message_set_auto_start(req, false); + if (r < 0) + goto fail; + + r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0); + if (r < 0) + goto fail; + + r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); + if (r < 0) { + if (!bus_error_shall_fallback(&error)) + goto not_found; + + /* Return NSS_STATUS_UNAVAIL when communication with systemd-resolved fails, + allowing falling back to other nss modules. Treat all other error conditions as + NOTFOUND. This includes DNSSEC errors and suchlike. (We don't use UNAVAIL in this + case so that the nsswitch.conf configuration can distinguish such executed but + negative replies from complete failure to talk to resolved). */ + goto fail; + } + + c = count_addresses(reply, AF_UNSPEC, &canonical); + if (c < 0) { + r = c; + goto fail; + } + if (c == 0) + goto not_found; + + if (isempty(canonical)) + canonical = name; + + l = strlen(canonical); + ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c; + if (buflen < ms) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + /* First, append name */ + r_name = buffer; + memcpy(r_name, canonical, l+1); + idx = ALIGN(l+1); + + /* Second, append addresses */ + r_tuple_first = (struct gaih_addrtuple*) (buffer + idx); + + r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); + if (r < 0) + goto fail; + + while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { + int family, ifindex; + const void *a; + size_t sz; + + assert_cc(sizeof(int32_t) == sizeof(int)); + + r = sd_bus_message_read(reply, "ii", &ifindex, &family); + if (r < 0) + goto fail; + + if (ifindex < 0) { + r = -EINVAL; + goto fail; + } + + r = sd_bus_message_read_array(reply, 'y', &a, &sz); + if (r < 0) + goto fail; + + r = sd_bus_message_exit_container(reply); + if (r < 0) + goto fail; + + if (!IN_SET(family, AF_INET, AF_INET6)) + continue; + + if (sz != FAMILY_ADDRESS_SIZE(family)) { + r = -EINVAL; + goto fail; + } + + r_tuple = (struct gaih_addrtuple*) (buffer + idx); + r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple))); + r_tuple->name = r_name; + r_tuple->family = family; + r_tuple->scopeid = ifindex_to_scopeid(family, a, ifindex); + memcpy(r_tuple->addr, a, sz); + + idx += ALIGN(sizeof(struct gaih_addrtuple)); + i++; + } + if (r < 0) + goto fail; + + assert(i == c); + assert(idx == ms); + + if (*pat) + **pat = *r_tuple_first; + else + *pat = r_tuple_first; + + if (ttlp) + *ttlp = 0; + + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ + *h_errnop = NETDB_SUCCESS; + h_errno = 0; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + +not_found: + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; +} + +enum nss_status _nss_resolve_gethostbyname3_r( + const char *name, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + char *r_name, *r_aliases, *r_addr, *r_addr_list; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + size_t l, idx, ms, alen; + const char *canonical; + int c, r, i = 0; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(result); + assert(buffer); + assert(errnop); + assert(h_errnop); + + if (af == AF_UNSPEC) + af = AF_INET; + + if (!IN_SET(af, AF_INET, AF_INET6)) { + r = -EAFNOSUPPORT; + goto fail; + } + + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_message_new_method_call( + bus, + &req, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResolveHostname"); + if (r < 0) + goto fail; + + r = sd_bus_message_set_auto_start(req, false); + if (r < 0) + goto fail; + + r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0); + if (r < 0) + goto fail; + + r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); + if (r < 0) { + if (!bus_error_shall_fallback(&error)) + goto not_found; + + goto fail; + } + + c = count_addresses(reply, af, &canonical); + if (c < 0) { + r = c; + goto fail; + } + if (c == 0) + goto not_found; + + if (isempty(canonical)) + canonical = name; + + alen = FAMILY_ADDRESS_SIZE(af); + l = strlen(canonical); + + ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*); + + if (buflen < ms) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + /* First, append name */ + r_name = buffer; + memcpy(r_name, canonical, l+1); + idx = ALIGN(l+1); + + /* Second, create empty aliases array */ + r_aliases = buffer + idx; + ((char**) r_aliases)[0] = NULL; + idx += sizeof(char*); + + /* Third, append addresses */ + r_addr = buffer + idx; + + r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); + if (r < 0) + goto fail; + + while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { + int ifindex, family; + const void *a; + size_t sz; + + r = sd_bus_message_read(reply, "ii", &ifindex, &family); + if (r < 0) + goto fail; + + if (ifindex < 0) { + r = -EINVAL; + goto fail; + } + + r = sd_bus_message_read_array(reply, 'y', &a, &sz); + if (r < 0) + goto fail; + + r = sd_bus_message_exit_container(reply); + if (r < 0) + goto fail; + + if (family != af) + continue; + + if (sz != alen) { + r = -EINVAL; + goto fail; + } + + memcpy(r_addr + i*ALIGN(alen), a, alen); + i++; + } + if (r < 0) + goto fail; + + assert(i == c); + idx += c * ALIGN(alen); + + /* Fourth, append address pointer array */ + r_addr_list = buffer + idx; + for (i = 0; i < c; i++) + ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen); + + ((char**) r_addr_list)[i] = NULL; + idx += (c+1) * sizeof(char*); + + assert(idx == ms); + + result->h_name = r_name; + result->h_aliases = (char**) r_aliases; + result->h_addrtype = af; + result->h_length = alen; + result->h_addr_list = (char**) r_addr_list; + + if (ttlp) + *ttlp = 0; + + if (canonp) + *canonp = r_name; + + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ + *h_errnop = NETDB_SUCCESS; + h_errno = 0; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + +not_found: + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; +} + +enum nss_status _nss_resolve_gethostbyaddr2_r( + const void* addr, socklen_t len, + int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + char *r_name, *r_aliases, *r_addr, *r_addr_list; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + unsigned c = 0, i = 0; + size_t ms = 0, idx; + const char *n; + int r, ifindex; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(addr); + assert(result); + assert(buffer); + assert(errnop); + assert(h_errnop); + + if (!IN_SET(af, AF_INET, AF_INET6)) { + UNPROTECT_ERRNO; + *errnop = EAFNOSUPPORT; + *h_errnop = NO_DATA; + return NSS_STATUS_UNAVAIL; + } + + if (len != FAMILY_ADDRESS_SIZE(af)) { + r = -EINVAL; + goto fail; + } + + if (avoid_deadlock()) { + r = -EDEADLK; + goto fail; + } + + r = sd_bus_open_system(&bus); + if (r < 0) + goto fail; + + r = sd_bus_message_new_method_call( + bus, + &req, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResolveAddress"); + if (r < 0) + goto fail; + + r = sd_bus_message_set_auto_start(req, false); + if (r < 0) + goto fail; + + r = sd_bus_message_append(req, "ii", 0, af); + if (r < 0) + goto fail; + + r = sd_bus_message_append_array(req, 'y', addr, len); + if (r < 0) + goto fail; + + r = sd_bus_message_append(req, "t", (uint64_t) 0); + if (r < 0) + goto fail; + + r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); + if (r < 0) { + if (!bus_error_shall_fallback(&error)) + goto not_found; + + goto fail; + } + + r = sd_bus_message_enter_container(reply, 'a', "(is)"); + if (r < 0) + goto fail; + + while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) { + + if (ifindex < 0) { + r = -EINVAL; + goto fail; + } + + c++; + ms += ALIGN(strlen(n) + 1); + } + if (r < 0) + goto fail; + + r = sd_bus_message_rewind(reply, false); + if (r < 0) + goto fail; + + if (c <= 0) + goto not_found; + + ms += ALIGN(len) + /* the address */ + 2 * sizeof(char*) + /* pointers to the address, plus trailing NULL */ + c * sizeof(char*); /* pointers to aliases, plus trailing NULL */ + + if (buflen < ms) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + /* First, place address */ + r_addr = buffer; + memcpy(r_addr, addr, len); + idx = ALIGN(len); + + /* Second, place address list */ + r_addr_list = buffer + idx; + ((char**) r_addr_list)[0] = r_addr; + ((char**) r_addr_list)[1] = NULL; + idx += sizeof(char*) * 2; + + /* Third, reserve space for the aliases array */ + r_aliases = buffer + idx; + idx += sizeof(char*) * c; + + /* Fourth, place aliases */ + i = 0; + r_name = buffer + idx; + while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) { + char *p; + size_t l; + + l = strlen(n); + p = buffer + idx; + memcpy(p, n, l+1); + + if (i > 0) + ((char**) r_aliases)[i-1] = p; + i++; + + idx += ALIGN(l+1); + } + if (r < 0) + goto fail; + + ((char**) r_aliases)[c-1] = NULL; + assert(idx == ms); + + result->h_name = r_name; + result->h_aliases = (char**) r_aliases; + result->h_addrtype = af; + result->h_length = len; + result->h_addr_list = (char**) r_addr_list; + + if (ttlp) + *ttlp = 0; + + /* Explicitly reset both *h_errnop and h_errno to work around + * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ + *h_errnop = NETDB_SUCCESS; + h_errno = 0; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + +not_found: + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; +} + +NSS_GETHOSTBYNAME_FALLBACKS(resolve); +NSS_GETHOSTBYADDR_FALLBACKS(resolve); diff --git a/src/nss-resolve/nss-resolve.sym b/src/nss-resolve/nss-resolve.sym new file mode 100644 index 00000000..e690a009 --- /dev/null +++ b/src/nss-resolve/nss-resolve.sym @@ -0,0 +1,19 @@ +/*** + SPDX-License-Identifier: LGPL-2.1+ + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. +***/ + +{ +global: + _nss_resolve_gethostbyname_r; + _nss_resolve_gethostbyname2_r; + _nss_resolve_gethostbyname3_r; + _nss_resolve_gethostbyname4_r; + _nss_resolve_gethostbyaddr_r; + _nss_resolve_gethostbyaddr2_r; +local: *; +}; diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c new file mode 100644 index 00000000..8ef1cd5e --- /dev/null +++ b/src/nss-systemd/nss-systemd.c @@ -0,0 +1,835 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "dirent-util.h" +#include "env-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "list.h" +#include "macro.h" +#include "nss-util.h" +#include "signal-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "user-util.h" +#include "util.h" + +#define DYNAMIC_USER_GECOS "Dynamic User" +#define DYNAMIC_USER_PASSWD "*" /* locked */ +#define DYNAMIC_USER_DIR "/" +#define DYNAMIC_USER_SHELL NOLOGIN + +static const struct passwd root_passwd = { + .pw_name = (char*) "root", + .pw_passwd = (char*) "x", /* see shadow file */ + .pw_uid = 0, + .pw_gid = 0, + .pw_gecos = (char*) "Super User", + .pw_dir = (char*) "/root", + .pw_shell = (char*) "/bin/sh", +}; + +static const struct passwd nobody_passwd = { + .pw_name = (char*) NOBODY_USER_NAME, + .pw_passwd = (char*) "*", /* locked */ + .pw_uid = UID_NOBODY, + .pw_gid = GID_NOBODY, + .pw_gecos = (char*) "User Nobody", + .pw_dir = (char*) "/", + .pw_shell = (char*) NOLOGIN, +}; + +static const struct group root_group = { + .gr_name = (char*) "root", + .gr_gid = 0, + .gr_passwd = (char*) "x", /* see shadow file */ + .gr_mem = (char*[]) { NULL }, +}; + +static const struct group nobody_group = { + .gr_name = (char*) NOBODY_GROUP_NAME, + .gr_gid = GID_NOBODY, + .gr_passwd = (char*) "*", /* locked */ + .gr_mem = (char*[]) { NULL }, +}; + +typedef struct UserEntry UserEntry; +typedef struct GetentData GetentData; + +struct UserEntry { + uid_t id; + char *name; + + GetentData *data; + LIST_FIELDS(UserEntry, entries); +}; + +struct GetentData { + /* As explained in NOTES section of getpwent_r(3) as 'getpwent_r() is not really + * reentrant since it shares the reading position in the stream with all other threads', + * we need to protect the data in UserEntry from multithreaded programs which may call + * setpwent(), getpwent_r(), or endpwent() simultaneously. So, each function locks the + * data by using the mutex below. */ + pthread_mutex_t mutex; + + UserEntry *position; + LIST_HEAD(UserEntry, entries); +}; + +static GetentData getpwent_data = { PTHREAD_MUTEX_INITIALIZER, NULL, NULL }; +static GetentData getgrent_data = { PTHREAD_MUTEX_INITIALIZER, NULL, NULL }; + +NSS_GETPW_PROTOTYPES(systemd); +NSS_GETGR_PROTOTYPES(systemd); +enum nss_status _nss_systemd_endpwent(void) _public_; +enum nss_status _nss_systemd_setpwent(int stayopen) _public_; +enum nss_status _nss_systemd_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) _public_; +enum nss_status _nss_systemd_endgrent(void) _public_; +enum nss_status _nss_systemd_setgrent(int stayopen) _public_; +enum nss_status _nss_systemd_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) _public_; + +static int direct_lookup_name(const char *name, uid_t *ret) { + _cleanup_free_ char *s = NULL; + const char *path; + int r; + + assert(name); + + /* Normally, we go via the bus to resolve names. That has the benefit that it is available from any mount + * namespace and subject to proper authentication. However, there's one problem: if our module is called from + * dbus-daemon itself we really can't use D-Bus to communicate. In this case, resort to a client-side hack, + * and look for the dynamic names directly. This is pretty ugly, but breaks the cyclic dependency. */ + + path = strjoina("/run/systemd/dynamic-uid/direct:", name); + r = readlink_malloc(path, &s); + if (r < 0) + return r; + + return parse_uid(s, ret); +} + +static int direct_lookup_uid(uid_t uid, char **ret) { + char path[STRLEN("/run/systemd/dynamic-uid/direct:") + DECIMAL_STR_MAX(uid_t) + 1], *s; + int r; + + xsprintf(path, "/run/systemd/dynamic-uid/direct:" UID_FMT, uid); + + r = readlink_malloc(path, &s); + if (r < 0) + return r; + if (!valid_user_group_name(s)) { /* extra safety check */ + free(s); + return -EINVAL; + } + + *ret = s; + return 0; +} + +enum nss_status _nss_systemd_getpwnam_r( + const char *name, + struct passwd *pwd, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + uint32_t translated; + size_t l; + int bypass, r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(pwd); + + /* If the username is not valid, then we don't know it. Ideally libc would filter these for us anyway. We don't + * generate EINVAL here, because it isn't really out business to complain about invalid user names. */ + if (!valid_user_group_name(name)) + return NSS_STATUS_NOTFOUND; + + /* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */ + if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { + if (streq(name, root_passwd.pw_name)) { + *pwd = root_passwd; + return NSS_STATUS_SUCCESS; + } + if (synthesize_nobody() && + streq(name, nobody_passwd.pw_name)) { + *pwd = nobody_passwd; + return NSS_STATUS_SUCCESS; + } + } + + /* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */ + if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) + return NSS_STATUS_NOTFOUND; + + bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); + if (bypass <= 0) { + r = sd_bus_open_system(&bus); + if (r < 0) + bypass = 1; + } + + if (bypass > 0) { + r = direct_lookup_name(name, (uid_t*) &translated); + if (r == -ENOENT) + return NSS_STATUS_NOTFOUND; + if (r < 0) + goto fail; + } else { + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByName", + &error, + &reply, + "s", + name); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + return NSS_STATUS_NOTFOUND; + + goto fail; + } + + r = sd_bus_message_read(reply, "u", &translated); + if (r < 0) + goto fail; + } + + l = strlen(name); + if (buflen < l+1) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + memcpy(buffer, name, l+1); + + pwd->pw_name = buffer; + pwd->pw_uid = (uid_t) translated; + pwd->pw_gid = (uid_t) translated; + pwd->pw_gecos = (char*) DYNAMIC_USER_GECOS; + pwd->pw_passwd = (char*) DYNAMIC_USER_PASSWD; + pwd->pw_dir = (char*) DYNAMIC_USER_DIR; + pwd->pw_shell = (char*) DYNAMIC_USER_SHELL; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} + +enum nss_status _nss_systemd_getpwuid_r( + uid_t uid, + struct passwd *pwd, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *direct = NULL; + const char *translated; + size_t l; + int bypass, r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + if (!uid_is_valid(uid)) + return NSS_STATUS_NOTFOUND; + + /* Synthesize data for the root user and for nobody in case they are missing from /etc/passwd */ + if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { + if (uid == root_passwd.pw_uid) { + *pwd = root_passwd; + return NSS_STATUS_SUCCESS; + } + if (synthesize_nobody() && + uid == nobody_passwd.pw_uid) { + *pwd = nobody_passwd; + return NSS_STATUS_SUCCESS; + } + } + + if (!uid_is_dynamic(uid)) + return NSS_STATUS_NOTFOUND; + + if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) + return NSS_STATUS_NOTFOUND; + + bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); + if (bypass <= 0) { + r = sd_bus_open_system(&bus); + if (r < 0) + bypass = 1; + } + + if (bypass > 0) { + r = direct_lookup_uid(uid, &direct); + if (r == -ENOENT) + return NSS_STATUS_NOTFOUND; + if (r < 0) + goto fail; + + translated = direct; + + } else { + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByUID", + &error, + &reply, + "u", + (uint32_t) uid); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + return NSS_STATUS_NOTFOUND; + + goto fail; + } + + r = sd_bus_message_read(reply, "s", &translated); + if (r < 0) + goto fail; + } + + l = strlen(translated) + 1; + if (buflen < l) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + memcpy(buffer, translated, l); + + pwd->pw_name = buffer; + pwd->pw_uid = uid; + pwd->pw_gid = uid; + pwd->pw_gecos = (char*) DYNAMIC_USER_GECOS; + pwd->pw_passwd = (char*) DYNAMIC_USER_PASSWD; + pwd->pw_dir = (char*) DYNAMIC_USER_DIR; + pwd->pw_shell = (char*) DYNAMIC_USER_SHELL; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} + +#pragma GCC diagnostic ignored "-Wsizeof-pointer-memaccess" + +enum nss_status _nss_systemd_getgrnam_r( + const char *name, + struct group *gr, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + uint32_t translated; + size_t l; + int bypass, r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(name); + assert(gr); + + if (!valid_user_group_name(name)) + return NSS_STATUS_NOTFOUND; + + /* Synthesize records for root and nobody, in case they are missing form /etc/group */ + if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { + if (streq(name, root_group.gr_name)) { + *gr = root_group; + return NSS_STATUS_SUCCESS; + } + if (synthesize_nobody() && + streq(name, nobody_group.gr_name)) { + *gr = nobody_group; + return NSS_STATUS_SUCCESS; + } + } + + if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) + return NSS_STATUS_NOTFOUND; + + bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); + if (bypass <= 0) { + r = sd_bus_open_system(&bus); + if (r < 0) + bypass = 1; + } + + if (bypass > 0) { + r = direct_lookup_name(name, (uid_t*) &translated); + if (r == -ENOENT) + return NSS_STATUS_NOTFOUND; + if (r < 0) + goto fail; + } else { + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByName", + &error, + &reply, + "s", + name); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + return NSS_STATUS_NOTFOUND; + + goto fail; + } + + r = sd_bus_message_read(reply, "u", &translated); + if (r < 0) + goto fail; + } + + l = sizeof(char*) + strlen(name) + 1; + if (buflen < l) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + memzero(buffer, sizeof(char*)); + strcpy(buffer + sizeof(char*), name); + + gr->gr_name = buffer + sizeof(char*); + gr->gr_gid = (gid_t) translated; + gr->gr_passwd = (char*) DYNAMIC_USER_PASSWD; + gr->gr_mem = (char**) buffer; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} + +enum nss_status _nss_systemd_getgrgid_r( + gid_t gid, + struct group *gr, + char *buffer, size_t buflen, + int *errnop) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *direct = NULL; + const char *translated; + size_t l; + int bypass, r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + if (!gid_is_valid(gid)) + return NSS_STATUS_NOTFOUND; + + /* Synthesize records for root and nobody, in case they are missing from /etc/group */ + if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) { + if (gid == root_group.gr_gid) { + *gr = root_group; + return NSS_STATUS_SUCCESS; + } + if (synthesize_nobody() && + gid == nobody_group.gr_gid) { + *gr = nobody_group; + return NSS_STATUS_SUCCESS; + } + } + + if (!gid_is_dynamic(gid)) + return NSS_STATUS_NOTFOUND; + + if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) + return NSS_STATUS_NOTFOUND; + + bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); + if (bypass <= 0) { + r = sd_bus_open_system(&bus); + if (r < 0) + bypass = 1; + } + + if (bypass > 0) { + r = direct_lookup_uid(gid, &direct); + if (r == -ENOENT) + return NSS_STATUS_NOTFOUND; + if (r < 0) + goto fail; + + translated = direct; + + } else { + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LookupDynamicUserByUID", + &error, + &reply, + "u", + (uint32_t) gid); + if (r < 0) { + if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER)) + return NSS_STATUS_NOTFOUND; + + goto fail; + } + + r = sd_bus_message_read(reply, "s", &translated); + if (r < 0) + goto fail; + } + + l = sizeof(char*) + strlen(translated) + 1; + if (buflen < l) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } + + memzero(buffer, sizeof(char*)); + strcpy(buffer + sizeof(char*), translated); + + gr->gr_name = buffer + sizeof(char*); + gr->gr_gid = gid; + gr->gr_passwd = (char*) DYNAMIC_USER_PASSWD; + gr->gr_mem = (char**) buffer; + + return NSS_STATUS_SUCCESS; + +fail: + UNPROTECT_ERRNO; + *errnop = -r; + return NSS_STATUS_UNAVAIL; +} + +static void user_entry_free(UserEntry *p) { + if (!p) + return; + + if (p->data) + LIST_REMOVE(entries, p->data->entries, p); + + free(p->name); + free(p); +} + +static int user_entry_add(GetentData *data, const char *name, uid_t id) { + UserEntry *p; + + assert(data); + + /* This happens when User= or Group= already exists statically. */ + if (!uid_is_dynamic(id)) + return -EINVAL; + + p = new0(UserEntry, 1); + if (!p) + return -ENOMEM; + + p->name = strdup(name); + if (!p->name) { + free(p); + return -ENOMEM; + } + p->id = id; + p->data = data; + + LIST_PREPEND(entries, data->entries, p); + + return 0; +} + +static void systemd_endent(GetentData *data) { + UserEntry *p; + + assert(data); + + while ((p = data->entries)) + user_entry_free(p); + + data->position = NULL; +} + +static enum nss_status nss_systemd_endent(GetentData *p) { + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert_se(pthread_mutex_lock(&p->mutex) == 0); + systemd_endent(p); + assert_se(pthread_mutex_unlock(&p->mutex) == 0); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status _nss_systemd_endpwent(void) { + return nss_systemd_endent(&getpwent_data); +} + +enum nss_status _nss_systemd_endgrent(void) { + return nss_systemd_endent(&getgrent_data); +} + +static int direct_enumeration(GetentData *p) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r; + + assert(p); + + d = opendir("/run/systemd/dynamic-uid/"); + if (!d) + return -errno; + + FOREACH_DIRENT(de, d, return -errno) { + _cleanup_free_ char *name = NULL; + uid_t uid, verified; + + if (!dirent_is_file(de)) + continue; + + r = parse_uid(de->d_name, &uid); + if (r < 0) + continue; + + r = direct_lookup_uid(uid, &name); + if (r == -ENOMEM) + return r; + if (r < 0) + continue; + + r = direct_lookup_name(name, &verified); + if (r < 0) + continue; + + if (uid != verified) + continue; + + r = user_entry_add(p, name, uid); + if (r == -ENOMEM) + return r; + if (r < 0) + continue; + } + + return 0; +} + +static enum nss_status systemd_setent(GetentData *p) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + const char *name; + uid_t id; + int bypass, r; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(p); + + assert_se(pthread_mutex_lock(&p->mutex) == 0); + + systemd_endent(p); + + if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0) + goto finish; + + bypass = getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS"); + + if (bypass <= 0) { + r = sd_bus_open_system(&bus); + if (r < 0) + bypass = 1; + } + + if (bypass > 0) { + r = direct_enumeration(p); + if (r < 0) + goto fail; + + goto finish; + } + + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetDynamicUsers", + &error, + &reply, + NULL); + if (r < 0) + goto fail; + + r = sd_bus_message_enter_container(reply, 'a', "(us)"); + if (r < 0) + goto fail; + + while ((r = sd_bus_message_read(reply, "(us)", &id, &name)) > 0) { + r = user_entry_add(p, name, id); + if (r == -ENOMEM) + goto fail; + if (r < 0) + continue; + } + if (r < 0) + goto fail; + + r = sd_bus_message_exit_container(reply); + if (r < 0) + goto fail; + +finish: + p->position = p->entries; + assert_se(pthread_mutex_unlock(&p->mutex) == 0); + + return NSS_STATUS_SUCCESS; + +fail: + systemd_endent(p); + assert_se(pthread_mutex_unlock(&p->mutex) == 0); + + return NSS_STATUS_UNAVAIL; +} + +enum nss_status _nss_systemd_setpwent(int stayopen) { + return systemd_setent(&getpwent_data); +} + +enum nss_status _nss_systemd_setgrent(int stayopen) { + return systemd_setent(&getgrent_data); +} + +enum nss_status _nss_systemd_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) { + enum nss_status ret; + UserEntry *p; + size_t len; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(result); + assert(buffer); + assert(errnop); + + assert_se(pthread_mutex_lock(&getpwent_data.mutex) == 0); + + LIST_FOREACH(entries, p, getpwent_data.position) { + len = strlen(p->name) + 1; + if (buflen < len) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + ret = NSS_STATUS_TRYAGAIN; + goto finalize; + } + + memcpy(buffer, p->name, len); + + result->pw_name = buffer; + result->pw_uid = p->id; + result->pw_gid = p->id; + result->pw_gecos = (char*) DYNAMIC_USER_GECOS; + result->pw_passwd = (char*) DYNAMIC_USER_PASSWD; + result->pw_dir = (char*) DYNAMIC_USER_DIR; + result->pw_shell = (char*) DYNAMIC_USER_SHELL; + break; + } + if (!p) { + ret = NSS_STATUS_NOTFOUND; + goto finalize; + } + + /* On success, step to the next entry. */ + p = p->entries_next; + ret = NSS_STATUS_SUCCESS; + +finalize: + /* Save position for the next call. */ + getpwent_data.position = p; + + assert_se(pthread_mutex_unlock(&getpwent_data.mutex) == 0); + + return ret; +} + +enum nss_status _nss_systemd_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) { + enum nss_status ret; + UserEntry *p; + size_t len; + + PROTECT_ERRNO; + BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); + + assert(result); + assert(buffer); + assert(errnop); + + assert_se(pthread_mutex_lock(&getgrent_data.mutex) == 0); + + LIST_FOREACH(entries, p, getgrent_data.position) { + len = sizeof(char*) + strlen(p->name) + 1; + if (buflen < len) { + UNPROTECT_ERRNO; + *errnop = ERANGE; + ret = NSS_STATUS_TRYAGAIN; + goto finalize; + } + + memzero(buffer, sizeof(char*)); + strcpy(buffer + sizeof(char*), p->name); + + result->gr_name = buffer + sizeof(char*); + result->gr_gid = p->id; + result->gr_passwd = (char*) DYNAMIC_USER_PASSWD; + result->gr_mem = (char**) buffer; + break; + } + if (!p) { + ret = NSS_STATUS_NOTFOUND; + goto finalize; + } + + /* On success, step to the next entry. */ + p = p->entries_next; + ret = NSS_STATUS_SUCCESS; + +finalize: + /* Save position for the next call. */ + getgrent_data.position = p; + + assert_se(pthread_mutex_unlock(&getgrent_data.mutex) == 0); + + return ret; +} diff --git a/src/nss-systemd/nss-systemd.sym b/src/nss-systemd/nss-systemd.sym new file mode 100644 index 00000000..ff63382b --- /dev/null +++ b/src/nss-systemd/nss-systemd.sym @@ -0,0 +1,23 @@ +/*** + SPDX-License-Identifier: LGPL-2.1+ + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. +***/ + +{ +global: + _nss_systemd_getpwnam_r; + _nss_systemd_getpwuid_r; + _nss_systemd_endpwent; + _nss_systemd_setpwent; + _nss_systemd_getpwent_r; + _nss_systemd_getgrnam_r; + _nss_systemd_getgrgid_r; + _nss_systemd_endgrent; + _nss_systemd_setgrent; + _nss_systemd_getgrent_r; +local: *; +}; diff --git a/src/partition/growfs.c b/src/partition/growfs.c new file mode 100644 index 00000000..1dbc9a46 --- /dev/null +++ b/src/partition/growfs.c @@ -0,0 +1,330 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "blockdev-util.h" +#include "crypt-util.h" +#include "device-nodes.h" +#include "dissect-image.h" +#include "escape.h" +#include "fd-util.h" +#include "format-util.h" +#include "log.h" +#include "missing_fs.h" +#include "mountpoint-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "stat-util.h" +#include "strv.h" +#include "util.h" + +static const char *arg_target = NULL; +static bool arg_dry_run = false; + +static int resize_ext4(const char *path, int mountfd, int devfd, uint64_t numblocks, uint64_t blocksize) { + assert((uint64_t) (int) blocksize == blocksize); + + if (arg_dry_run) + return 0; + + if (ioctl(mountfd, EXT4_IOC_RESIZE_FS, &numblocks) != 0) + return log_error_errno(errno, "Failed to resize \"%s\" to %"PRIu64" blocks (ext4): %m", + path, numblocks); + + return 0; +} + +static int resize_btrfs(const char *path, int mountfd, int devfd, uint64_t numblocks, uint64_t blocksize) { + struct btrfs_ioctl_vol_args args = {}; + int r; + + assert((uint64_t) (int) blocksize == blocksize); + + /* https://bugzilla.kernel.org/show_bug.cgi?id=118111 */ + if (numblocks * blocksize < 256*1024*1024) { + log_warning("%s: resizing of btrfs volumes smaller than 256M is not supported", path); + return -EOPNOTSUPP; + } + + r = snprintf(args.name, sizeof(args.name), "%"PRIu64, numblocks * blocksize); + /* The buffer is large enough for any number to fit... */ + assert((size_t) r < sizeof(args.name)); + + if (arg_dry_run) + return 0; + + if (ioctl(mountfd, BTRFS_IOC_RESIZE, &args) != 0) + return log_error_errno(errno, "Failed to resize \"%s\" to %"PRIu64" blocks (btrfs): %m", + path, numblocks); + + return 0; +} + +#if HAVE_LIBCRYPTSETUP +static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_devno) { + _cleanup_free_ char *devpath = NULL, *main_devpath = NULL; + _cleanup_(crypt_freep) struct crypt_device *cd = NULL; + _cleanup_close_ int main_devfd = -1; + uint64_t size; + int r; + + r = device_path_make_major_minor(S_IFBLK, main_devno, &main_devpath); + if (r < 0) + return log_error_errno(r, "Failed to format device major/minor path: %m"); + + main_devfd = open(main_devpath, O_RDONLY|O_CLOEXEC); + if (main_devfd < 0) + return log_error_errno(errno, "Failed to open \"%s\": %m", main_devpath); + + if (ioctl(main_devfd, BLKGETSIZE64, &size) != 0) + return log_error_errno(errno, "Failed to query size of \"%s\" (before resize): %m", + main_devpath); + + log_debug("%s is %"PRIu64" bytes", main_devpath, size); + r = device_path_make_major_minor(S_IFBLK, devno, &devpath); + if (r < 0) + return log_error_errno(r, "Failed to format major/minor path: %m"); + + r = crypt_init(&cd, devpath); + if (r < 0) + return log_error_errno(r, "crypt_init(\"%s\") failed: %m", devpath); + + crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); + + r = crypt_load(cd, CRYPT_LUKS, NULL); + if (r < 0) + return log_debug_errno(r, "Failed to load LUKS metadata for %s: %m", devpath); + + if (arg_dry_run) + return 0; + + r = crypt_resize(cd, main_devpath, 0); + if (r < 0) + return log_error_errno(r, "crypt_resize() of %s failed: %m", devpath); + + if (ioctl(main_devfd, BLKGETSIZE64, &size) != 0) + log_warning_errno(errno, "Failed to query size of \"%s\" (after resize): %m", + devpath); + else + log_debug("%s is now %"PRIu64" bytes", main_devpath, size); + + return 1; +} +#endif + +static int maybe_resize_slave_device(const char *mountpath, dev_t main_devno) { + _cleanup_free_ char *fstype = NULL, *devpath = NULL; + dev_t devno; + int r; + +#if HAVE_LIBCRYPTSETUP + crypt_set_log_callback(NULL, cryptsetup_log_glue, NULL); + if (DEBUG_LOGGING) + crypt_set_debug_level(CRYPT_DEBUG_ALL); +#endif + + r = get_block_device_harder(mountpath, &devno); + if (r < 0) + return log_error_errno(r, "Failed to determine underlying block device of \"%s\": %m", + mountpath); + + log_debug("Underlying device %d:%d, main dev %d:%d, %s", + major(devno), minor(devno), + major(main_devno), minor(main_devno), + devno == main_devno ? "same" : "different"); + if (devno == main_devno) + return 0; + + r = device_path_make_major_minor(S_IFBLK, devno, &devpath); + if (r < 0) + return log_error_errno(r, "Failed to format device major/minor path: %m"); + + r = probe_filesystem(devpath, &fstype); + if (r == -EUCLEAN) + return log_warning_errno(r, "Cannot reliably determine probe \"%s\", refusing to proceed.", devpath); + if (r < 0) + return log_warning_errno(r, "Failed to probe \"%s\": %m", devpath); + +#if HAVE_LIBCRYPTSETUP + if (streq_ptr(fstype, "crypto_LUKS")) + return resize_crypt_luks_device(devno, fstype, main_devno); +#endif + + log_debug("Don't know how to resize %s of type %s, ignoring", devpath, strnull(fstype)); + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-growfs@.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] /path/to/mountpoint\n\n" + "Grow filesystem or encrypted payload to device size.\n\n" + "Options:\n" + " -h --help Show this help and exit\n" + " --version Print version string and exit\n" + " -n --dry-run Just print what would be done\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + }; + + int c; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version" , no_argument, NULL, ARG_VERSION }, + { "dry-run", no_argument, NULL, 'n' }, + {} + }; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hn", options, NULL)) >= 0) + switch(c) { + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case 'n': + arg_dry_run = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind + 1 != argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s excepts exactly one argument (the mount point).", + program_invocation_short_name); + + arg_target = argv[optind]; + + return 1; +} + +int main(int argc, char *argv[]) { + _cleanup_close_ int mountfd = -1, devfd = -1; + _cleanup_free_ char *devpath = NULL; + uint64_t size, numblocks; + char fb[FORMAT_BYTES_MAX]; + struct statfs sfs; + dev_t devno; + int blocksize; + int r; + + log_setup_service(); + + r = parse_argv(argc, argv); + if (r < 0) + return EXIT_FAILURE; + if (r == 0) + return EXIT_SUCCESS; + + r = path_is_mount_point(arg_target, NULL, 0); + if (r < 0) { + log_error_errno(r, "Failed to check if \"%s\" is a mount point: %m", arg_target); + return EXIT_FAILURE; + } + if (r == 0) { + log_error_errno(r, "\"%s\" is not a mount point: %m", arg_target); + return EXIT_FAILURE; + } + + r = get_block_device(arg_target, &devno); + if (r < 0) { + log_error_errno(r, "Failed to determine block device of \"%s\": %m", arg_target); + return EXIT_FAILURE; + } + + r = maybe_resize_slave_device(arg_target, devno); + if (r < 0) + return EXIT_FAILURE; + + mountfd = open(arg_target, O_RDONLY|O_CLOEXEC); + if (mountfd < 0) { + log_error_errno(errno, "Failed to open \"%s\": %m", arg_target); + return EXIT_FAILURE; + } + + r = device_path_make_major_minor(S_IFBLK, devno, &devpath); + if (r < 0) { + log_error_errno(r, "Failed to format device major/minor path: %m"); + return EXIT_FAILURE; + } + + devfd = open(devpath, O_RDONLY|O_CLOEXEC); + if (devfd < 0) { + log_error_errno(errno, "Failed to open \"%s\": %m", devpath); + return EXIT_FAILURE; + } + + if (ioctl(devfd, BLKBSZGET, &blocksize) != 0) { + log_error_errno(errno, "Failed to query block size of \"%s\": %m", devpath); + return EXIT_FAILURE; + } + + if (ioctl(devfd, BLKGETSIZE64, &size) != 0) { + log_error_errno(errno, "Failed to query size of \"%s\": %m", devpath); + return EXIT_FAILURE; + } + + if (size % blocksize != 0) + log_notice("Partition size %"PRIu64" is not a multiple of the blocksize %d," + " ignoring %"PRIu64" bytes", size, blocksize, size % blocksize); + + numblocks = size / blocksize; + + if (fstatfs(mountfd, &sfs) < 0) { + log_error_errno(errno, "Failed to stat file system \"%s\": %m", arg_target); + return EXIT_FAILURE; + } + + switch(sfs.f_type) { + case EXT4_SUPER_MAGIC: + r = resize_ext4(arg_target, mountfd, devfd, numblocks, blocksize); + break; + case BTRFS_SUPER_MAGIC: + r = resize_btrfs(arg_target, mountfd, devfd, numblocks, blocksize); + break; + default: + log_error("Don't know how to resize fs %llx on \"%s\"", + (long long unsigned) sfs.f_type, arg_target); + return EXIT_FAILURE; + } + + if (r < 0) + return EXIT_FAILURE; + + log_info("Successfully resized \"%s\" to %s bytes (%"PRIu64" blocks of %d bytes).", + arg_target, format_bytes(fb, sizeof fb, size), numblocks, blocksize); + return EXIT_SUCCESS; +} diff --git a/src/partition/makefs.c b/src/partition/makefs.c new file mode 100644 index 00000000..ee4907f7 --- /dev/null +++ b/src/partition/makefs.c @@ -0,0 +1,82 @@ +/*** + SPDX-License-Identifier: LGPL-2.1+ +***/ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dissect-image.h" +#include "main-func.h" +#include "process-util.h" +#include "signal-util.h" +#include "string-util.h" + +static int makefs(const char *type, const char *device) { + const char *mkfs; + pid_t pid; + int r; + + if (streq(type, "swap")) + mkfs = "/sbin/mkswap"; + else + mkfs = strjoina("/sbin/mkfs.", type); + if (access(mkfs, X_OK) != 0) + return log_error_errno(errno, "%s is not executable: %m", mkfs); + + r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + const char *cmdline[3] = { mkfs, device, NULL }; + + /* Child */ + + execv(cmdline[0], (char**) cmdline); + _exit(EXIT_FAILURE); + } + + return wait_for_terminate_and_check(mkfs, pid, WAIT_LOG); +} + +static int run(int argc, char *argv[]) { + const char *device, *type; + _cleanup_free_ char *detected = NULL; + struct stat st; + int r; + + log_setup_service(); + + if (argc != 3) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program expects two arguments."); + + type = argv[1]; + device = argv[2]; + + if (stat(device, &st) < 0) + return log_error_errno(errno, "Failed to stat \"%s\": %m", device); + + if (!S_ISBLK(st.st_mode)) + log_info("%s is not a block device.", device); + + r = probe_filesystem(device, &detected); + if (r < 0) + return log_warning_errno(r, + r == -EUCLEAN ? + "Cannot reliably determine probe \"%s\", refusing to proceed." : + "Failed to probe \"%s\": %m", + device); + + if (detected) { + log_info("%s is not empty (type %s), exiting", device, detected); + return 0; + } + + return makefs(type, device); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/path/path.c b/src/path/path.c new file mode 100644 index 00000000..568b5fb0 --- /dev/null +++ b/src/path/path.c @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-path.h" + +#include "alloc-util.h" +#include "log.h" +#include "macro.h" +#include "main-func.h" +#include "pretty-print.h" +#include "string-util.h" +#include "util.h" + +static const char *arg_suffix = NULL; + +static const char* const path_table[_SD_PATH_MAX] = { + [SD_PATH_TEMPORARY] = "temporary", + [SD_PATH_TEMPORARY_LARGE] = "temporary-large", + [SD_PATH_SYSTEM_BINARIES] = "system-binaries", + [SD_PATH_SYSTEM_INCLUDE] = "system-include", + [SD_PATH_SYSTEM_LIBRARY_PRIVATE] = "system-library-private", + [SD_PATH_SYSTEM_LIBRARY_ARCH] = "system-library-arch", + [SD_PATH_SYSTEM_SHARED] = "system-shared", + [SD_PATH_SYSTEM_CONFIGURATION_FACTORY] = "system-configuration-factory", + [SD_PATH_SYSTEM_STATE_FACTORY] = "system-state-factory", + [SD_PATH_SYSTEM_CONFIGURATION] = "system-configuration", + [SD_PATH_SYSTEM_RUNTIME] = "system-runtime", + [SD_PATH_SYSTEM_RUNTIME_LOGS] = "system-runtime-logs", + [SD_PATH_SYSTEM_STATE_PRIVATE] = "system-state-private", + [SD_PATH_SYSTEM_STATE_LOGS] = "system-state-logs", + [SD_PATH_SYSTEM_STATE_CACHE] = "system-state-cache", + [SD_PATH_SYSTEM_STATE_SPOOL] = "system-state-spool", + [SD_PATH_USER_BINARIES] = "user-binaries", + [SD_PATH_USER_LIBRARY_PRIVATE] = "user-library-private", + [SD_PATH_USER_LIBRARY_ARCH] = "user-library-arch", + [SD_PATH_USER_SHARED] = "user-shared", + [SD_PATH_USER_CONFIGURATION] = "user-configuration", + [SD_PATH_USER_RUNTIME] = "user-runtime", + [SD_PATH_USER_STATE_CACHE] = "user-state-cache", + [SD_PATH_USER] = "user", + [SD_PATH_USER_DOCUMENTS] = "user-documents", + [SD_PATH_USER_MUSIC] = "user-music", + [SD_PATH_USER_PICTURES] = "user-pictures", + [SD_PATH_USER_VIDEOS] = "user-videos", + [SD_PATH_USER_DOWNLOAD] = "user-download", + [SD_PATH_USER_PUBLIC] = "user-public", + [SD_PATH_USER_TEMPLATES] = "user-templates", + [SD_PATH_USER_DESKTOP] = "user-desktop", + [SD_PATH_SEARCH_BINARIES] = "search-binaries", + [SD_PATH_SEARCH_BINARIES_DEFAULT] = "search-binaries-default", + [SD_PATH_SEARCH_LIBRARY_PRIVATE] = "search-library-private", + [SD_PATH_SEARCH_LIBRARY_ARCH] = "search-library-arch", + [SD_PATH_SEARCH_SHARED] = "search-shared", + [SD_PATH_SEARCH_CONFIGURATION_FACTORY] = "search-configuration-factory", + [SD_PATH_SEARCH_STATE_FACTORY] = "search-state-factory", + [SD_PATH_SEARCH_CONFIGURATION] = "search-configuration", +}; + +static int list_homes(void) { + uint64_t i = 0; + int r = 0; + + for (i = 0; i < ELEMENTSOF(path_table); i++) { + _cleanup_free_ char *p = NULL; + int q; + + q = sd_path_home(i, arg_suffix, &p); + if (q == -ENXIO) + continue; + if (q < 0) { + log_error_errno(r, "Failed to query %s: %m", path_table[i]); + r = q; + continue; + } + + printf("%s: %s\n", path_table[i], p); + } + + return r; +} + +static int print_home(const char *n) { + uint64_t i = 0; + int r; + + for (i = 0; i < ELEMENTSOF(path_table); i++) { + if (streq(path_table[i], n)) { + _cleanup_free_ char *p = NULL; + + r = sd_path_home(i, arg_suffix, &p); + if (r < 0) + return log_error_errno(r, "Failed to query %s: %m", n); + + printf("%s\n", p); + return 0; + } + } + + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Path %s not known.", n); +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-path", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [NAME...]\n\n" + "Show system and user paths.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --suffix=SUFFIX Suffix to append to paths\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_SUFFIX, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "suffix", required_argument, NULL, ARG_SUFFIX }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_SUFFIX: + arg_suffix = optarg; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int run(int argc, char* argv[]) { + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (argc > optind) { + int i, q; + + for (i = optind; i < argc; i++) { + q = print_home(argv[i]); + if (q < 0) + r = q; + } + + return r; + } else + return list_homes(); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/portable/meson.build b/src/portable/meson.build new file mode 100644 index 00000000..dc571634 --- /dev/null +++ b/src/portable/meson.build @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +systemd_portabled_sources = files(''' + portable.c + portable.h + portabled-bus.c + portabled-image-bus.c + portabled-image-bus.h + portabled-image.c + portabled-image.h + portabled-operation.c + portabled-operation.h + portabled.c + portabled.h +'''.split()) + +if conf.get('ENABLE_PORTABLED') == 1 + install_data('org.freedesktop.portable1.conf', + install_dir : dbuspolicydir) + install_data('org.freedesktop.portable1.service', + install_dir : dbussystemservicedir) + install_data('org.freedesktop.portable1.policy', + install_dir : polkitpolicydir) + + install_data('profile/default/service.conf', install_dir : join_paths(profiledir, 'default')) + install_data('profile/nonetwork/service.conf', install_dir : join_paths(profiledir, 'nonetwork')) + install_data('profile/strict/service.conf', install_dir : join_paths(profiledir, 'strict')) + install_data('profile/trusted/service.conf', install_dir : join_paths(profiledir, 'trusted')) +endif diff --git a/src/portable/org.freedesktop.portable1.conf b/src/portable/org.freedesktop.portable1.conf new file mode 100644 index 00000000..31d41af1 --- /dev/null +++ b/src/portable/org.freedesktop.portable1.conf @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/portable/org.freedesktop.portable1.policy b/src/portable/org.freedesktop.portable1.policy new file mode 100644 index 00000000..50bb44c4 --- /dev/null +++ b/src/portable/org.freedesktop.portable1.policy @@ -0,0 +1,43 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Inspect a portable service image + Authentication is required to inspect a portable service image. + + auth_admin + auth_admin + auth_admin_keep + + + + + Attach or detach a portable service image + Authentication is required to attach or detach a portable service image. + + auth_admin + auth_admin + auth_admin_keep + + org.freedesktop.systemd1.reload-daemon + + + + Delete or modify portable service image + Authentication is required to delete or modify a portable service image. + + auth_admin + auth_admin + auth_admin_keep + + + + diff --git a/src/portable/org.freedesktop.portable1.service b/src/portable/org.freedesktop.portable1.service new file mode 100644 index 00000000..eff37b01 --- /dev/null +++ b/src/portable/org.freedesktop.portable1.service @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +[D-BUS Service] +Name=org.freedesktop.portable1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.portable1.service diff --git a/src/portable/portable.c b/src/portable/portable.c new file mode 100644 index 00000000..34b123e8 --- /dev/null +++ b/src/portable/portable.c @@ -0,0 +1,1442 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-common-errors.h" +#include "bus-error.h" +#include "conf-files.h" +#include "copy.h" +#include "def.h" +#include "dirent-util.h" +#include "dissect-image.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "install.h" +#include "io-util.h" +#include "locale-util.h" +#include "loop-util.h" +#include "machine-image.h" +#include "mkdir.h" +#include "nulstr-util.h" +#include "os-util.h" +#include "path-lookup.h" +#include "portable.h" +#include "process-util.h" +#include "set.h" +#include "signal-util.h" +#include "socket-util.h" +#include "sort-util.h" +#include "string-table.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "user-util.h" + +static const char profile_dirs[] = CONF_PATHS_NULSTR("systemd/portable/profile"); + +/* Markers used in the first line of our 20-portable.conf unit file drop-in to determine, that a) the unit file was + * dropped there by the portable service logic and b) for which image it was dropped there. */ +#define PORTABLE_DROPIN_MARKER_BEGIN "# Drop-in created for image '" +#define PORTABLE_DROPIN_MARKER_END "', do not edit." + +static bool prefix_match(const char *unit, const char *prefix) { + const char *p; + + p = startswith(unit, prefix); + if (!p) + return false; + + /* Only respect prefixes followed by dash or dot or when there's a complete match */ + return IN_SET(*p, '-', '.', '@', 0); +} + +static bool unit_match(const char *unit, char **matches) { + const char *dot; + char **i; + + dot = strrchr(unit, '.'); + if (!dot) + return false; + + if (!STR_IN_SET(dot, ".service", ".socket", ".target", ".timer", ".path")) + return false; + + /* Empty match expression means: everything */ + if (strv_isempty(matches)) + return true; + + /* Otherwise, at least one needs to match */ + STRV_FOREACH(i, matches) + if (prefix_match(unit, *i)) + return true; + + return false; +} + +static PortableMetadata *portable_metadata_new(const char *name, int fd) { + PortableMetadata *m; + + m = malloc0(offsetof(PortableMetadata, name) + strlen(name) + 1); + if (!m) + return NULL; + + strcpy(m->name, name); + m->fd = fd; + + return m; +} + +PortableMetadata *portable_metadata_unref(PortableMetadata *i) { + if (!i) + return NULL; + + safe_close(i->fd); + free(i->source); + + return mfree(i); +} + +static int compare_metadata(PortableMetadata *const *x, PortableMetadata *const *y) { + return strcmp((*x)->name, (*y)->name); +} + +int portable_metadata_hashmap_to_sorted_array(Hashmap *unit_files, PortableMetadata ***ret) { + + _cleanup_free_ PortableMetadata **sorted = NULL; + Iterator iterator; + PortableMetadata *item; + size_t k = 0; + + sorted = new(PortableMetadata*, hashmap_size(unit_files)); + if (!sorted) + return -ENOMEM; + + HASHMAP_FOREACH(item, unit_files, iterator) + sorted[k++] = item; + + assert(k == hashmap_size(unit_files)); + + typesafe_qsort(sorted, k, compare_metadata); + + *ret = TAKE_PTR(sorted); + return 0; +} + +static int send_item( + int socket_fd, + const char *name, + int fd) { + + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int))]; + } control = {}; + struct iovec iovec; + struct msghdr mh = { + .msg_control = &control, + .msg_controllen = sizeof(control), + .msg_iov = &iovec, + .msg_iovlen = 1, + }; + struct cmsghdr *cmsg; + _cleanup_close_ int data_fd = -1; + + assert(socket_fd >= 0); + assert(name); + assert(fd >= 0); + + data_fd = fd_duplicate_data_fd(fd); + if (data_fd < 0) + return data_fd; + + cmsg = CMSG_FIRSTHDR(&mh); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &data_fd, sizeof(int)); + + mh.msg_controllen = CMSG_SPACE(sizeof(int)); + iovec = IOVEC_MAKE_STRING(name); + + if (sendmsg(socket_fd, &mh, MSG_NOSIGNAL) < 0) + return -errno; + + return 0; +} + +static int recv_item( + int socket_fd, + char **ret_name, + int *ret_fd) { + + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(int))]; + } control = {}; + char buffer[PATH_MAX+2]; + struct iovec iov = IOVEC_INIT(buffer, sizeof(buffer)-1); + struct msghdr mh = { + .msg_control = &control, + .msg_controllen = sizeof(control), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + struct cmsghdr *cmsg; + _cleanup_close_ int found_fd = -1; + char *copy; + ssize_t n; + + assert(socket_fd >= 0); + assert(ret_name); + assert(ret_fd); + + n = recvmsg(socket_fd, &mh, MSG_CMSG_CLOEXEC); + if (n < 0) + return -errno; + + CMSG_FOREACH(cmsg, &mh) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) { + + if (cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { + assert(found_fd < 0); + found_fd = *(int*) CMSG_DATA(cmsg); + break; + } + + cmsg_close_all(&mh); + return -EIO; + } + } + + buffer[n] = 0; + + copy = strdup(buffer); + if (!copy) + return -ENOMEM; + + *ret_name = copy; + *ret_fd = TAKE_FD(found_fd); + + return 0; +} + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(portable_metadata_hash_ops, char, string_hash_func, string_compare_func, + PortableMetadata, portable_metadata_unref); + +static int extract_now( + const char *where, + char **matches, + int socket_fd, + PortableMetadata **ret_os_release, + Hashmap **ret_unit_files) { + + _cleanup_hashmap_free_ Hashmap *unit_files = NULL; + _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_close_ int os_release_fd = -1; + _cleanup_free_ char *os_release_path = NULL; + char **i; + int r; + + /* Extracts the metadata from a directory tree 'where'. Extracts two kinds of information: the /etc/os-release + * data, and all unit files matching the specified expression. Note that this function is called in two very + * different but also similar contexts. When the tool gets invoked on a directory tree, we'll process it + * directly, and in-process, and thus can return the requested data directly, via 'ret_os_release' and + * 'ret_unit_files'. However, if the tool is invoked on a raw disk image — which needs to be mounted first — we + * are invoked in a child process with private mounts and then need to send the collected data to our + * parent. To handle both cases in one call this function also gets a 'socket_fd' parameter, which when >= 0 is + * used to send the data to the parent. */ + + assert(where); + + /* First, find /etc/os-release and send it upstream (or just save it). */ + r = open_os_release(where, &os_release_path, &os_release_fd); + if (r < 0) + log_debug_errno(r, "Couldn't acquire os-release file, ignoring: %m"); + else { + if (socket_fd >= 0) { + r = send_item(socket_fd, "/etc/os-release", os_release_fd); + if (r < 0) + return log_debug_errno(r, "Failed to send os-release file: %m"); + } + + if (ret_os_release) { + os_release = portable_metadata_new("/etc/os-release", os_release_fd); + if (!os_release) + return -ENOMEM; + + os_release_fd = -1; + os_release->source = TAKE_PTR(os_release_path); + } + } + + /* Then, send unit file data to the parent (or/and add it to the hashmap). For that we use our usual unit + * discovery logic. Note that we force looking inside of /lib/systemd/system/ for units too, as we mightbe + * compiled for a split-usr system but the image might be a legacy-usr one. */ + r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, where); + if (r < 0) + return log_debug_errno(r, "Failed to acquire lookup paths: %m"); + + unit_files = hashmap_new(&portable_metadata_hash_ops); + if (!unit_files) + return -ENOMEM; + + STRV_FOREACH(i, paths.search_path) { + _cleanup_free_ char *resolved = NULL; + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + + r = chase_symlinks_and_opendir(*i, where, 0, &resolved, &d); + if (r < 0) { + log_debug_errno(r, "Failed to open unit path '%s', ignoring: %m", *i); + continue; + } + + FOREACH_DIRENT(de, d, return log_debug_errno(errno, "Failed to read directory: %m")) { + _cleanup_(portable_metadata_unrefp) PortableMetadata *m = NULL; + _cleanup_close_ int fd = -1; + + if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) + continue; + + if (!unit_match(de->d_name, matches)) + continue; + + /* Filter out duplicates */ + if (hashmap_get(unit_files, de->d_name)) + continue; + + dirent_ensure_type(d, de); + if (!IN_SET(de->d_type, DT_LNK, DT_REG)) + continue; + + fd = openat(dirfd(d), de->d_name, O_CLOEXEC|O_RDONLY); + if (fd < 0) { + log_debug_errno(errno, "Failed to open unit file '%s', ignoring: %m", de->d_name); + continue; + } + + if (socket_fd >= 0) { + r = send_item(socket_fd, de->d_name, fd); + if (r < 0) + return log_debug_errno(r, "Failed to send unit metadata to parent: %m"); + } + + m = portable_metadata_new(de->d_name, fd); + if (!m) + return -ENOMEM; + fd = -1; + + m->source = path_join(resolved, de->d_name); + if (!m->source) + return -ENOMEM; + + r = hashmap_put(unit_files, m->name, m); + if (r < 0) + return log_debug_errno(r, "Failed to add unit to hashmap: %m"); + m = NULL; + } + } + + if (ret_os_release) + *ret_os_release = TAKE_PTR(os_release); + if (ret_unit_files) + *ret_unit_files = TAKE_PTR(unit_files); + + return 0; +} + +static int portable_extract_by_path( + const char *path, + char **matches, + PortableMetadata **ret_os_release, + Hashmap **ret_unit_files, + sd_bus_error *error) { + + _cleanup_hashmap_free_ Hashmap *unit_files = NULL; + _cleanup_(portable_metadata_unrefp) PortableMetadata* os_release = NULL; + _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; + int r; + + assert(path); + + r = loop_device_make_by_path(path, O_RDONLY, &d); + if (r == -EISDIR) { + /* We can't turn this into a loop-back block device, and this returns EISDIR? Then this is a directory + * tree and not a raw device. It's easy then. */ + + r = extract_now(path, matches, -1, &os_release, &unit_files); + if (r < 0) + return r; + + } else if (r < 0) + return log_debug_errno(r, "Failed to set up loopback device: %m"); + else { + _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; + _cleanup_(rmdir_and_freep) char *tmpdir = NULL; + _cleanup_(close_pairp) int seq[2] = { -1, -1 }; + _cleanup_(sigkill_waitp) pid_t child = 0; + + /* We now have a loopback block device, let's fork off a child in its own mount namespace, mount it + * there, and extract the metadata we need. The metadata is sent from the child back to us. */ + + BLOCK_SIGNALS(SIGCHLD); + + r = mkdtemp_malloc("/tmp/inspect-XXXXXX", &tmpdir); + if (r < 0) + return log_debug_errno(r, "Failed to create temporary directory: %m"); + + r = dissect_image(d->fd, NULL, 0, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP, &m); + if (r == -ENOPKG) + sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't identify a suitable partition table or file system in '%s'.", path); + else if (r == -EADDRNOTAVAIL) + sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "No root partition for specified root hash found in '%s'.", path); + else if (r == -ENOTUNIQ) + sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Multiple suitable root partitions found in image '%s'.", path); + else if (r == -ENXIO) + sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "No suitable root partition found in image '%s'.", path); + else if (r == -EPROTONOSUPPORT) + sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device '%s' is loopback block device with partition scanning turned off, please turn it on.", path); + if (r < 0) + return r; + + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, seq) < 0) + return log_debug_errno(errno, "Failed to allocated SOCK_SEQPACKET socket: %m"); + + r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_LOG, &child); + if (r < 0) + return r; + if (r == 0) { + seq[0] = safe_close(seq[0]); + + r = dissected_image_mount(m, tmpdir, UID_INVALID, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_VALIDATE_OS); + if (r < 0) { + log_debug_errno(r, "Failed to mount dissected image: %m"); + goto child_finish; + } + + r = extract_now(tmpdir, matches, seq[1], NULL, NULL); + + child_finish: + _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); + } + + seq[1] = safe_close(seq[1]); + + unit_files = hashmap_new(&portable_metadata_hash_ops); + if (!unit_files) + return -ENOMEM; + + for (;;) { + _cleanup_(portable_metadata_unrefp) PortableMetadata *add = NULL; + _cleanup_free_ char *name = NULL; + _cleanup_close_ int fd = -1; + + r = recv_item(seq[0], &name, &fd); + if (r < 0) + return log_debug_errno(r, "Failed to receive item: %m"); + + /* We can't really distinguish a zero-length datagram without any fds from EOF (both are signalled the + * same way by recvmsg()). Hence, accept either as end notification. */ + if (isempty(name) && fd < 0) + break; + + if (isempty(name) || fd < 0) { + log_debug("Invalid item sent from child."); + return -EINVAL; + } + + add = portable_metadata_new(name, fd); + if (!add) + return -ENOMEM; + fd = -1; + + /* Note that we do not initialize 'add->source' here, as the source path is not usable here as + * it refers to a path only valid in the short-living namespaced child process we forked + * here. */ + + if (PORTABLE_METADATA_IS_UNIT(add)) { + r = hashmap_put(unit_files, add->name, add); + if (r < 0) + return log_debug_errno(r, "Failed to add item to unit file list: %m"); + + add = NULL; + + } else if (PORTABLE_METADATA_IS_OS_RELEASE(add)) { + + assert(!os_release); + os_release = TAKE_PTR(add); + } else + assert_not_reached("Unexpected metadata item from child."); + } + + r = wait_for_terminate_and_check("(sd-dissect)", child, 0); + if (r < 0) + return r; + child = 0; + } + + if (!os_release) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image '%s' lacks os-release data, refusing.", path); + + if (hashmap_isempty(unit_files)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't find any matching unit files in image '%s', refusing.", path); + + if (ret_unit_files) + *ret_unit_files = TAKE_PTR(unit_files); + + if (ret_os_release) + *ret_os_release = TAKE_PTR(os_release); + + return 0; +} + +int portable_extract( + const char *name_or_path, + char **matches, + PortableMetadata **ret_os_release, + Hashmap **ret_unit_files, + sd_bus_error *error) { + + _cleanup_(image_unrefp) Image *image = NULL; + int r; + + assert(name_or_path); + + r = image_find_harder(IMAGE_PORTABLE, name_or_path, &image); + if (r < 0) + return r; + + return portable_extract_by_path(image->path, matches, ret_os_release, ret_unit_files, error); +} + +static int unit_file_is_active( + sd_bus *bus, + const char *name, + sd_bus_error *error) { + + static const char *const active_states[] = { + "activating", + "active", + "reloading", + "deactivating", + NULL, + }; + int r; + + if (!bus) + return false; + + /* If we are looking at a plain or instance things are easy, we can just query the state */ + if (unit_name_is_valid(name, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) { + _cleanup_free_ char *path = NULL, *buf = NULL; + + path = unit_dbus_path_from_name(name); + if (!path) + return -ENOMEM; + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + "ActiveState", + error, + &buf); + if (r < 0) + return log_debug_errno(r, "Failed to retrieve unit state: %s", bus_error_message(error, r)); + + return strv_contains((char**) active_states, buf); + } + + /* Otherwise we need to enumerate. But let's build the most restricted query we can */ + if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + const char *at, *prefix, *joined; + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListUnitsByPatterns"); + if (r < 0) + return r; + + r = sd_bus_message_append_strv(m, (char**) active_states); + if (r < 0) + return r; + + at = strchr(name, '@'); + assert(at); + + prefix = strndupa(name, at + 1 - name); + joined = strjoina(prefix, "*", at + 1); + + r = sd_bus_message_append_strv(m, STRV_MAKE(joined)); + if (r < 0) + return r; + + r = sd_bus_call(bus, m, 0, error, &reply); + if (r < 0) + return log_debug_errno(r, "Failed to list units: %s", bus_error_message(error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_STRUCT, "ssssssouso"); + if (r < 0) + return r; + + return r > 0; + } + + return -EINVAL; +} + +static int portable_changes_add( + PortableChange **changes, + size_t *n_changes, + PortableChangeType type, + const char *path, + const char *source) { + + _cleanup_free_ char *p = NULL, *s = NULL; + PortableChange *c; + + assert(path); + assert(!changes == !n_changes); + + if (!changes) + return 0; + + c = reallocarray(*changes, *n_changes + 1, sizeof(PortableChange)); + if (!c) + return -ENOMEM; + *changes = c; + + p = strdup(path); + if (!p) + return -ENOMEM; + + path_simplify(p, false); + + if (source) { + s = strdup(source); + if (!s) + return -ENOMEM; + + path_simplify(s, false); + } + + c[(*n_changes)++] = (PortableChange) { + .type = type, + .path = TAKE_PTR(p), + .source = TAKE_PTR(s), + }; + + return 0; +} + +static int portable_changes_add_with_prefix( + PortableChange **changes, + size_t *n_changes, + PortableChangeType type, + const char *prefix, + const char *path, + const char *source) { + + assert(path); + assert(!changes == !n_changes); + + if (!changes) + return 0; + + if (prefix) { + path = prefix_roota(prefix, path); + + if (source) + source = prefix_roota(prefix, source); + } + + return portable_changes_add(changes, n_changes, type, path, source); +} + +void portable_changes_free(PortableChange *changes, size_t n_changes) { + size_t i; + + assert(changes || n_changes == 0); + + for (i = 0; i < n_changes; i++) { + free(changes[i].path); + free(changes[i].source); + } + + free(changes); +} + +static int install_chroot_dropin( + const char *image_path, + ImageType type, + const PortableMetadata *m, + const char *dropin_dir, + char **ret_dropin, + PortableChange **changes, + size_t *n_changes) { + + _cleanup_free_ char *text = NULL, *dropin = NULL; + int r; + + assert(image_path); + assert(m); + assert(dropin_dir); + + dropin = path_join(dropin_dir, "20-portable.conf"); + if (!dropin) + return -ENOMEM; + + text = strjoin(PORTABLE_DROPIN_MARKER_BEGIN, image_path, PORTABLE_DROPIN_MARKER_END "\n"); + if (!text) + return -ENOMEM; + + if (endswith(m->name, ".service")) + if (!strextend(&text, + "\n" + "[Service]\n", + IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) ? "RootDirectory=" : "RootImage=", image_path, "\n" + "Environment=PORTABLE=", basename(image_path), "\n" + "LogExtraFields=PORTABLE=", basename(image_path), "\n", + NULL)) + + return -ENOMEM; + + r = write_string_file(dropin, text, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); + if (r < 0) + return log_debug_errno(r, "Failed to write '%s': %m", dropin); + + (void) portable_changes_add(changes, n_changes, PORTABLE_WRITE, dropin, NULL); + + if (ret_dropin) + *ret_dropin = TAKE_PTR(dropin); + + return 0; +} + +static int find_profile(const char *name, const char *unit, char **ret) { + const char *p, *dot; + + assert(name); + assert(ret); + + assert_se(dot = strrchr(unit, '.')); + + NULSTR_FOREACH(p, profile_dirs) { + _cleanup_free_ char *joined; + + joined = strjoin(p, "/", name, "/", dot + 1, ".conf"); + if (!joined) + return -ENOMEM; + + if (laccess(joined, F_OK) >= 0) { + *ret = TAKE_PTR(joined); + return 0; + } + + if (errno != ENOENT) + return -errno; + } + + return -ENOENT; +} + +static int install_profile_dropin( + const char *image_path, + const PortableMetadata *m, + const char *dropin_dir, + const char *profile, + PortableFlags flags, + char **ret_dropin, + PortableChange **changes, + size_t *n_changes) { + + _cleanup_free_ char *dropin = NULL, *from = NULL; + int r; + + assert(image_path); + assert(m); + assert(dropin_dir); + + if (!profile) + return 0; + + r = find_profile(profile, m->name, &from); + if (r < 0) { + if (r != -ENOENT) + return log_debug_errno(errno, "Profile '%s' is not accessible: %m", profile); + + log_debug_errno(errno, "Skipping link to profile '%s', as it does not exist: %m", profile); + return 0; + } + + dropin = path_join(dropin_dir, "10-profile.conf"); + if (!dropin) + return -ENOMEM; + + if (flags & PORTABLE_PREFER_COPY) { + + r = copy_file_atomic(from, dropin, 0644, 0, 0, COPY_REFLINK); + if (r < 0) + return log_debug_errno(r, "Failed to copy %s %s %s: %m", from, special_glyph(SPECIAL_GLYPH_ARROW), dropin); + + (void) portable_changes_add(changes, n_changes, PORTABLE_COPY, dropin, from); + + } else { + + if (symlink(from, dropin) < 0) + return log_debug_errno(errno, "Failed to link %s %s %s: %m", from, special_glyph(SPECIAL_GLYPH_ARROW), dropin); + + (void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, dropin, from); + } + + if (ret_dropin) + *ret_dropin = TAKE_PTR(dropin); + + return 0; +} + +static const char *attached_path(const LookupPaths *paths, PortableFlags flags) { + const char *where; + + assert(paths); + + if (flags & PORTABLE_RUNTIME) + where = paths->runtime_attached; + else + where = paths->persistent_attached; + + assert(where); + return where; +} + +static int attach_unit_file( + const LookupPaths *paths, + const char *image_path, + ImageType type, + const PortableMetadata *m, + const char *profile, + PortableFlags flags, + PortableChange **changes, + size_t *n_changes) { + + _cleanup_(unlink_and_freep) char *chroot_dropin = NULL, *profile_dropin = NULL; + _cleanup_(rmdir_and_freep) char *dropin_dir = NULL; + const char *where, *path; + int r; + + assert(paths); + assert(image_path); + assert(m); + assert(PORTABLE_METADATA_IS_UNIT(m)); + + where = attached_path(paths, flags); + + (void) mkdir_parents(where, 0755); + if (mkdir(where, 0755) < 0) { + if (errno != EEXIST) + return -errno; + } else + (void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, where, NULL); + + path = prefix_roota(where, m->name); + dropin_dir = strjoin(path, ".d"); + if (!dropin_dir) + return -ENOMEM; + + if (mkdir(dropin_dir, 0755) < 0) { + if (errno != EEXIST) + return -errno; + } else + (void) portable_changes_add(changes, n_changes, PORTABLE_MKDIR, dropin_dir, NULL); + + /* We install the drop-ins first, and the actual unit file last to achieve somewhat atomic behaviour if PID 1 + * is reloaded while we are creating things here: as long as only the drop-ins exist the unit doesn't exist at + * all for PID 1. */ + + r = install_chroot_dropin(image_path, type, m, dropin_dir, &chroot_dropin, changes, n_changes); + if (r < 0) + return r; + + r = install_profile_dropin(image_path, m, dropin_dir, profile, flags, &profile_dropin, changes, n_changes); + if (r < 0) + return r; + + if ((flags & PORTABLE_PREFER_SYMLINK) && m->source) { + + if (symlink(m->source, path) < 0) + return log_debug_errno(errno, "Failed to symlink unit file '%s': %m", path); + + (void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, path, m->source); + + } else { + _cleanup_(unlink_and_freep) char *tmp = NULL; + _cleanup_close_ int fd = -1; + + fd = open_tmpfile_linkable(where, O_WRONLY|O_CLOEXEC, &tmp); + if (fd < 0) + return log_debug_errno(fd, "Failed to create unit file '%s': %m", path); + + r = copy_bytes(m->fd, fd, UINT64_MAX, COPY_REFLINK); + if (r < 0) + return log_debug_errno(r, "Failed to copy unit file '%s': %m", path); + + if (fchmod(fd, 0644) < 0) + return log_debug_errno(errno, "Failed to change unit file access mode for '%s': %m", path); + + r = link_tmpfile(fd, tmp, path); + if (r < 0) + return log_debug_errno(r, "Failed to install unit file '%s': %m", path); + + tmp = mfree(tmp); + + (void) portable_changes_add(changes, n_changes, PORTABLE_COPY, path, m->source); + } + + /* All is established now, now let's disable any rollbacks */ + chroot_dropin = mfree(chroot_dropin); + profile_dropin = mfree(profile_dropin); + dropin_dir = mfree(dropin_dir); + + return 0; +} + +static int image_symlink( + const char *image_path, + PortableFlags flags, + char **ret) { + + const char *fn, *where; + char *joined = NULL; + + assert(image_path); + assert(ret); + + fn = last_path_component(image_path); + + if (flags & PORTABLE_RUNTIME) + where = "/run/portables/"; + else + where = "/etc/portables/"; + + joined = strjoin(where, fn); + if (!joined) + return -ENOMEM; + + *ret = joined; + return 0; +} + +static int install_image_symlink( + const char *image_path, + PortableFlags flags, + PortableChange **changes, + size_t *n_changes) { + + _cleanup_free_ char *sl = NULL; + int r; + + assert(image_path); + + /* If the image is outside of the image search also link it into it, so that it can be found with short image + * names and is listed among the images. */ + + if (image_in_search_path(IMAGE_PORTABLE, image_path)) + return 0; + + r = image_symlink(image_path, flags, &sl); + if (r < 0) + return log_debug_errno(r, "Failed to generate image symlink path: %m"); + + (void) mkdir_parents(sl, 0755); + + if (symlink(image_path, sl) < 0) + return log_debug_errno(errno, "Failed to link %s %s %s: %m", image_path, special_glyph(SPECIAL_GLYPH_ARROW), sl); + + (void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, sl, image_path); + return 0; +} + +int portable_attach( + sd_bus *bus, + const char *name_or_path, + char **matches, + const char *profile, + PortableFlags flags, + PortableChange **changes, + size_t *n_changes, + sd_bus_error *error) { + + _cleanup_hashmap_free_ Hashmap *unit_files = NULL; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(image_unrefp) Image *image = NULL; + PortableMetadata *item; + Iterator iterator; + int r; + + assert(name_or_path); + + r = image_find_harder(IMAGE_PORTABLE, name_or_path, &image); + if (r < 0) + return r; + + r = portable_extract_by_path(image->path, matches, NULL, &unit_files, error); + if (r < 0) + return r; + + r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL); + if (r < 0) + return r; + + HASHMAP_FOREACH(item, unit_files, iterator) { + r = unit_file_exists(UNIT_FILE_SYSTEM, &paths, item->name); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to determine whether unit '%s' exists on the host: %m", item->name); + if (r > 0) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' exists on the host already, refusing.", item->name); + + r = unit_file_is_active(bus, item->name, error); + if (r < 0) + return r; + if (r > 0) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active already, refusing.", item->name); + } + + HASHMAP_FOREACH(item, unit_files, iterator) { + r = attach_unit_file(&paths, image->path, image->type, item, profile, flags, changes, n_changes); + if (r < 0) + return r; + } + + /* We don't care too much for the image symlink, it's just a convenience thing, it's not necessary for proper + * operation otherwise. */ + (void) install_image_symlink(image->path, flags, changes, n_changes); + + return 0; +} + +static bool marker_matches_image(const char *marker, const char *name_or_path) { + const char *a; + + assert(marker); + assert(name_or_path); + + a = last_path_component(marker); + + if (image_name_is_valid(name_or_path)) { + const char *e; + + /* We shall match against an image name. In that case let's compare the last component, and optionally + * allow either a suffix of ".raw" or a series of "/". */ + + e = startswith(a, name_or_path); + if (!e) + return false; + + return + e[strspn(e, "/")] == 0 || + streq(e, ".raw"); + } else { + const char *b; + size_t l; + + /* We shall match against a path. Let's ignore any prefix here though, as often there are many ways to + * reach the same file. However, in this mode, let's validate any file suffix. */ + + l = strcspn(a, "/"); + b = last_path_component(name_or_path); + + if (strcspn(b, "/") != l) + return false; + + return memcmp(a, b, l) == 0; + } +} + +static int test_chroot_dropin( + DIR *d, + const char *where, + const char *fname, + const char *name_or_path, + char **ret_marker) { + + _cleanup_free_ char *line = NULL, *marker = NULL; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_close_ int fd = -1; + const char *p, *e, *k; + int r; + + assert(d); + assert(where); + assert(fname); + + /* We recognize unis created from portable images via the drop-in we created for them */ + + p = strjoina(fname, ".d/20-portable.conf"); + fd = openat(dirfd(d), p, O_RDONLY|O_CLOEXEC); + if (fd < 0) { + if (errno == ENOENT) + return 0; + + return log_debug_errno(errno, "Failed to open %s/%s: %m", where, p); + } + + r = fdopen_unlocked(fd, "r", &f); + if (r < 0) + return log_debug_errno(r, "Failed to convert file handle: %m"); + TAKE_FD(fd); + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_debug_errno(r, "Failed to read from %s/%s: %m", where, p); + + e = startswith(line, PORTABLE_DROPIN_MARKER_BEGIN); + if (!e) + return 0; + + k = endswith(e, PORTABLE_DROPIN_MARKER_END); + if (!k) + return 0; + + marker = strndup(e, k - e); + if (!marker) + return -ENOMEM; + + if (!name_or_path) + r = true; + else + r = marker_matches_image(marker, name_or_path); + + if (ret_marker) + *ret_marker = TAKE_PTR(marker); + + return r; +} + +int portable_detach( + sd_bus *bus, + const char *name_or_path, + PortableFlags flags, + PortableChange **changes, + size_t *n_changes, + sd_bus_error *error) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_set_free_free_ Set *unit_files = NULL, *markers = NULL; + _cleanup_closedir_ DIR *d = NULL; + const char *where, *item; + Iterator iterator; + struct dirent *de; + int ret = 0; + int r; + + assert(name_or_path); + + r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL); + if (r < 0) + return r; + + where = attached_path(&paths, flags); + + d = opendir(where); + if (!d) { + if (errno == ENOENT) + goto not_found; + + return log_debug_errno(errno, "Failed to open '%s' directory: %m", where); + } + + unit_files = set_new(&string_hash_ops); + if (!unit_files) + return -ENOMEM; + + markers = set_new(&path_hash_ops); + if (!markers) + return -ENOMEM; + + FOREACH_DIRENT(de, d, return log_debug_errno(errno, "Failed to enumerate '%s' directory: %m", where)) { + _cleanup_free_ char *marker = NULL; + UnitFileState state; + + if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) + continue; + + /* Filter out duplicates */ + if (set_get(unit_files, de->d_name)) + continue; + + dirent_ensure_type(d, de); + if (!IN_SET(de->d_type, DT_LNK, DT_REG)) + continue; + + r = test_chroot_dropin(d, where, de->d_name, name_or_path, &marker); + if (r < 0) + return r; + if (r == 0) + continue; + + r = unit_file_lookup_state(UNIT_FILE_SYSTEM, &paths, de->d_name, &state); + if (r < 0) + return log_debug_errno(r, "Failed to determine unit file state of '%s': %m", de->d_name); + if (!IN_SET(state, UNIT_FILE_STATIC, UNIT_FILE_DISABLED, UNIT_FILE_LINKED, UNIT_FILE_RUNTIME, UNIT_FILE_LINKED_RUNTIME)) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is in state '%s', can't detach.", de->d_name, unit_file_state_to_string(state)); + + r = unit_file_is_active(bus, de->d_name, error); + if (r < 0) + return r; + if (r > 0) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active, can't detach.", de->d_name); + + r = set_put_strdup(unit_files, de->d_name); + if (r < 0) + return log_debug_errno(r, "Failed to add unit name '%s' to set: %m", de->d_name); + + if (path_is_absolute(marker) && + !image_in_search_path(IMAGE_PORTABLE, marker)) { + + r = set_ensure_allocated(&markers, &path_hash_ops); + if (r < 0) + return r; + + r = set_put(markers, marker); + if (r >= 0) + marker = NULL; + else if (r != -EEXIST) + return r; + } + } + + if (set_isempty(unit_files)) + goto not_found; + + SET_FOREACH(item, unit_files, iterator) { + _cleanup_free_ char *md = NULL; + const char *suffix; + + if (unlinkat(dirfd(d), item, 0) < 0) { + log_debug_errno(errno, "Can't remove unit file %s/%s: %m", where, item); + + if (errno != ENOENT && ret >= 0) + ret = -errno; + } else + portable_changes_add_with_prefix(changes, n_changes, PORTABLE_UNLINK, where, item, NULL); + + FOREACH_STRING(suffix, ".d/10-profile.conf", ".d/20-portable.conf") { + _cleanup_free_ char *dropin = NULL; + + dropin = strjoin(item, suffix); + if (!dropin) + return -ENOMEM; + + if (unlinkat(dirfd(d), dropin, 0) < 0) { + log_debug_errno(errno, "Can't remove drop-in %s/%s: %m", where, dropin); + + if (errno != ENOENT && ret >= 0) + ret = -errno; + } else + portable_changes_add_with_prefix(changes, n_changes, PORTABLE_UNLINK, where, dropin, NULL); + } + + md = strjoin(item, ".d"); + if (!md) + return -ENOMEM; + + if (unlinkat(dirfd(d), md, AT_REMOVEDIR) < 0) { + log_debug_errno(errno, "Can't remove drop-in directory %s/%s: %m", where, md); + + if (errno != ENOENT && ret >= 0) + ret = -errno; + } else + portable_changes_add_with_prefix(changes, n_changes, PORTABLE_UNLINK, where, md, NULL); + } + + /* Now, also drop any image symlink, for images outside of the sarch path */ + SET_FOREACH(item, markers, iterator) { + _cleanup_free_ char *sl = NULL; + struct stat st; + + r = image_symlink(item, flags, &sl); + if (r < 0) { + log_debug_errno(r, "Failed to determine image symlink for '%s', ignoring: %m", item); + continue; + } + + if (lstat(sl, &st) < 0) { + log_debug_errno(errno, "Failed to stat '%s', ignoring: %m", sl); + continue; + } + + if (!S_ISLNK(st.st_mode)) { + log_debug("Image '%s' is not a symlink, ignoring.", sl); + continue; + } + + if (unlink(sl) < 0) { + log_debug_errno(errno, "Can't remove image symlink '%s': %m", sl); + + if (errno != ENOENT && ret >= 0) + ret = -errno; + } else + portable_changes_add(changes, n_changes, PORTABLE_UNLINK, sl, NULL); + } + + /* Try to remove the unit file directory, if we can */ + if (rmdir(where) >= 0) + portable_changes_add(changes, n_changes, PORTABLE_UNLINK, where, NULL); + + return ret; + +not_found: + log_debug("No unit files associated with '%s' found. Image not attached?", name_or_path); + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "No unit files associated with '%s' found. Image not attached?", name_or_path); +} + +static int portable_get_state_internal( + sd_bus *bus, + const char *name_or_path, + PortableFlags flags, + PortableState *ret, + sd_bus_error *error) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + bool found_enabled = false, found_running = false; + _cleanup_set_free_free_ Set *unit_files = NULL; + _cleanup_closedir_ DIR *d = NULL; + const char *where; + struct dirent *de; + int r; + + assert(name_or_path); + assert(ret); + + r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL); + if (r < 0) + return r; + + where = attached_path(&paths, flags); + + d = opendir(where); + if (!d) { + if (errno == ENOENT) { + /* If the 'attached' directory doesn't exist at all, then we know for sure this image isn't attached. */ + *ret = PORTABLE_DETACHED; + return 0; + } + + return log_debug_errno(errno, "Failed to open '%s' directory: %m", where); + } + + unit_files = set_new(&string_hash_ops); + if (!unit_files) + return -ENOMEM; + + FOREACH_DIRENT(de, d, return log_debug_errno(errno, "Failed to enumerate '%s' directory: %m", where)) { + UnitFileState state; + + if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) + continue; + + /* Filter out duplicates */ + if (set_get(unit_files, de->d_name)) + continue; + + dirent_ensure_type(d, de); + if (!IN_SET(de->d_type, DT_LNK, DT_REG)) + continue; + + r = test_chroot_dropin(d, where, de->d_name, name_or_path, NULL); + if (r < 0) + return r; + if (r == 0) + continue; + + r = unit_file_lookup_state(UNIT_FILE_SYSTEM, &paths, de->d_name, &state); + if (r < 0) + return log_debug_errno(r, "Failed to determine unit file state of '%s': %m", de->d_name); + if (!IN_SET(state, UNIT_FILE_STATIC, UNIT_FILE_DISABLED, UNIT_FILE_LINKED, UNIT_FILE_LINKED_RUNTIME)) + found_enabled = true; + + r = unit_file_is_active(bus, de->d_name, error); + if (r < 0) + return r; + if (r > 0) + found_running = true; + + r = set_put_strdup(unit_files, de->d_name); + if (r < 0) + return log_debug_errno(r, "Failed to add unit name '%s' to set: %m", de->d_name); + } + + *ret = found_running ? (!set_isempty(unit_files) && (flags & PORTABLE_RUNTIME) ? PORTABLE_RUNNING_RUNTIME : PORTABLE_RUNNING) : + found_enabled ? (flags & PORTABLE_RUNTIME ? PORTABLE_ENABLED_RUNTIME : PORTABLE_ENABLED) : + !set_isempty(unit_files) ? (flags & PORTABLE_RUNTIME ? PORTABLE_ATTACHED_RUNTIME : PORTABLE_ATTACHED) : PORTABLE_DETACHED; + + return 0; +} + +int portable_get_state( + sd_bus *bus, + const char *name_or_path, + PortableFlags flags, + PortableState *ret, + sd_bus_error *error) { + + PortableState state; + int r; + + assert(name_or_path); + assert(ret); + + /* We look for matching units twice: once in the regular directories, and once in the runtime directories — but + * the latter only if we didn't find anything in the former. */ + + r = portable_get_state_internal(bus, name_or_path, flags & ~PORTABLE_RUNTIME, &state, error); + if (r < 0) + return r; + + if (state == PORTABLE_DETACHED) { + r = portable_get_state_internal(bus, name_or_path, flags | PORTABLE_RUNTIME, &state, error); + if (r < 0) + return r; + } + + *ret = state; + return 0; +} + +int portable_get_profiles(char ***ret) { + assert(ret); + + return conf_files_list_nulstr(ret, NULL, NULL, CONF_FILES_DIRECTORY|CONF_FILES_BASENAME|CONF_FILES_FILTER_MASKED, profile_dirs); +} + +static const char* const portable_change_type_table[_PORTABLE_CHANGE_TYPE_MAX] = { + [PORTABLE_COPY] = "copy", + [PORTABLE_MKDIR] = "mkdir", + [PORTABLE_SYMLINK] = "symlink", + [PORTABLE_UNLINK] = "unlink", + [PORTABLE_WRITE] = "write", +}; + +DEFINE_STRING_TABLE_LOOKUP(portable_change_type, PortableChangeType); + +static const char* const portable_state_table[_PORTABLE_STATE_MAX] = { + [PORTABLE_DETACHED] = "detached", + [PORTABLE_ATTACHED] = "attached", + [PORTABLE_ATTACHED_RUNTIME] = "attached-runtime", + [PORTABLE_ENABLED] = "enabled", + [PORTABLE_ENABLED_RUNTIME] = "enabled-runtime", + [PORTABLE_RUNNING] = "running", + [PORTABLE_RUNNING_RUNTIME] = "running-runtime", +}; + +DEFINE_STRING_TABLE_LOOKUP(portable_state, PortableState); diff --git a/src/portable/portable.h b/src/portable/portable.h new file mode 100644 index 00000000..ad81b584 --- /dev/null +++ b/src/portable/portable.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "hashmap.h" +#include "macro.h" +#include "set.h" +#include "string-util.h" + +typedef struct PortableMetadata { + int fd; + char *source; + char name[]; +} PortableMetadata; + +#define PORTABLE_METADATA_IS_OS_RELEASE(m) (streq((m)->name, "/etc/os-release")) +#define PORTABLE_METADATA_IS_UNIT(m) (!IN_SET((m)->name[0], 0, '/')) + +typedef enum PortableFlags { + PORTABLE_PREFER_COPY = 1 << 0, + PORTABLE_PREFER_SYMLINK = 1 << 1, + PORTABLE_RUNTIME = 1 << 2, +} PortableFlags; + +typedef enum PortableChangeType { + PORTABLE_COPY, + PORTABLE_SYMLINK, + PORTABLE_UNLINK, + PORTABLE_WRITE, + PORTABLE_MKDIR, + _PORTABLE_CHANGE_TYPE_MAX, + _PORTABLE_CHANGE_TYPE_INVALID = INT_MIN, +} PortableChangeType; + +typedef enum PortableState { + PORTABLE_DETACHED, + PORTABLE_ATTACHED, + PORTABLE_ATTACHED_RUNTIME, + PORTABLE_ENABLED, + PORTABLE_ENABLED_RUNTIME, + PORTABLE_RUNNING, + PORTABLE_RUNNING_RUNTIME, + _PORTABLE_STATE_MAX, + _PORTABLE_STATE_INVALID = -1 +} PortableState; + +typedef struct PortableChange { + int type; /* PortableFileChangeType or negative error number */ + char *path; + char *source; +} PortableChange; + +PortableMetadata *portable_metadata_unref(PortableMetadata *i); +DEFINE_TRIVIAL_CLEANUP_FUNC(PortableMetadata*, portable_metadata_unref); + +int portable_metadata_hashmap_to_sorted_array(Hashmap *unit_files, PortableMetadata ***ret); + +int portable_extract(const char *image, char **matches, PortableMetadata **ret_os_release, Hashmap **ret_unit_files, sd_bus_error *error); + +int portable_attach(sd_bus *bus, const char *name_or_path, char **matches, const char *profile, PortableFlags flags, PortableChange **changes, size_t *n_changes, sd_bus_error *error); +int portable_detach(sd_bus *bus, const char *name_or_path, PortableFlags flags, PortableChange **changes, size_t *n_changes, sd_bus_error *error); + +int portable_get_state(sd_bus *bus, const char *name_or_path, PortableFlags flags, PortableState *ret, sd_bus_error *error); + +int portable_get_profiles(char ***ret); + +void portable_changes_free(PortableChange *changes, size_t n_changes); + +const char *portable_change_type_to_string(PortableChangeType t) _const_; +PortableChangeType portable_change_type_from_string(const char *t) _pure_; + +const char *portable_state_to_string(PortableState t) _const_; +PortableState portable_state_from_string(const char *t) _pure_; diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c new file mode 100644 index 00000000..7246c6c8 --- /dev/null +++ b/src/portable/portablectl.c @@ -0,0 +1,973 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "def.h" +#include "dirent-util.h" +#include "env-file.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-table.h" +#include "fs-util.h" +#include "locale-util.h" +#include "machine-image.h" +#include "main-func.h" +#include "pager.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "spawn-polkit-agent.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "verbs.h" + +static PagerFlags arg_pager_flags = 0; +static bool arg_legend = true; +static bool arg_ask_password = true; +static bool arg_quiet = false; +static const char *arg_profile = "default"; +static const char* arg_copy_mode = NULL; +static bool arg_runtime = false; +static bool arg_reload = true; +static bool arg_cat = false; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static const char *arg_host = NULL; + +static int determine_image(const char *image, bool permit_non_existing, char **ret) { + int r; + + /* If the specified name is a valid image name, we pass it as-is to portabled, which will search for it in the + * usual search directories. Otherwise we presume it's a path, and will normalize it on the client's side + * (among other things, to make the path independent of the client's working directory) before passing it + * over. */ + + if (image_name_is_valid(image)) { + char *c; + + if (!arg_quiet && laccess(image, F_OK) >= 0) + log_warning("Ambiguous invocation: current working directory contains file matching non-path argument '%s', ignoring. " + "Prefix argument with './' to force reference to file in current working directory.", image); + + c = strdup(image); + if (!c) + return log_oom(); + + *ret = c; + return 0; + } + + if (arg_transport != BUS_TRANSPORT_LOCAL) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Operations on images by path not supported when connecting to remote systems."); + + r = chase_symlinks(image, NULL, CHASE_TRAIL_SLASH | (permit_non_existing ? CHASE_NONEXISTENT : 0), ret, NULL); + if (r < 0) + return log_error_errno(r, "Cannot normalize specified image path '%s': %m", image); + + return 0; +} + +static int extract_prefix(const char *path, char **ret) { + _cleanup_free_ char *name = NULL; + const char *bn, *underscore; + size_t m; + + bn = basename(path); + + underscore = strchr(bn, '_'); + if (underscore) + m = underscore - bn; + else { + const char *e; + + e = endswith(bn, ".raw"); + if (!e) + e = strchr(bn, 0); + + m = e - bn; + } + + name = strndup(bn, m); + if (!name) + return -ENOMEM; + + /* A slightly reduced version of what's permitted in unit names. With ':' and '\' are removed, as well as '_' + * which we use as delimiter for the second part of the image string, which we ignore for now. */ + if (!in_charset(name, DIGITS LETTERS "-.")) + return -EINVAL; + + if (!filename_is_valid(name)) + return -EINVAL; + + *ret = TAKE_PTR(name); + + return 0; +} + +static int determine_matches(const char *image, char **l, bool allow_any, char ***ret) { + _cleanup_strv_free_ char **k = NULL; + int r; + + /* Determine the matches to apply. If the list is empty we derive the match from the image name. If the list + * contains exactly the "-" we return a wildcard list (which is the empty list), but only if this is expressly + * permitted. */ + + if (strv_isempty(l)) { + char *prefix; + + r = extract_prefix(image, &prefix); + if (r < 0) + return log_error_errno(r, "Failed to extract prefix of image name '%s': %m", image); + + if (!arg_quiet) + log_info("(Matching unit files with prefix '%s'.)", prefix); + + r = strv_consume(&k, prefix); + if (r < 0) + return log_oom(); + + } else if (strv_equal(l, STRV_MAKE("-"))) { + + if (!allow_any) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Refusing all unit file match."); + + if (!arg_quiet) + log_info("(Matching all unit files.)"); + } else { + + k = strv_copy(l); + if (!k) + return log_oom(); + + if (!arg_quiet) { + _cleanup_free_ char *joined = NULL; + + joined = strv_join(k, "', '"); + if (!joined) + return log_oom(); + + log_info("(Matching unit files with prefixes '%s'.)", joined); + } + } + + *ret = TAKE_PTR(k); + + return 0; +} + +static int acquire_bus(sd_bus **bus) { + int r; + + assert(bus); + + if (*bus) + return 0; + + r = bus_connect_transport(arg_transport, arg_host, false, bus); + if (r < 0) + return log_error_errno(r, "Failed to connect to bus: %m"); + + (void) sd_bus_set_allow_interactive_authorization(*bus, arg_ask_password); + + return 0; +} + +static int maybe_reload(sd_bus **bus) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + if (!arg_reload) + return 0; + + r = acquire_bus(bus); + if (r < 0) + return r; + + r = sd_bus_message_new_method_call( + *bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Reload"); + if (r < 0) + return bus_log_create_error(r); + + /* Reloading the daemon may take long, hence set a longer timeout here */ + r = sd_bus_call(*bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r)); + + return 0; +} + +static int inspect_image(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_strv_free_ char **matches = NULL; + _cleanup_free_ char *image = NULL; + bool nl = false, header = false; + const void *data; + const char *path; + size_t sz; + int r; + + r = determine_image(argv[1], false, &image); + if (r < 0) + return r; + + r = determine_matches(argv[1], argv + 2, true, &matches); + if (r < 0) + return r; + + r = acquire_bus(&bus); + if (r < 0) + return r; + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.portable1", + "/org/freedesktop/portable1", + "org.freedesktop.portable1.Manager", + "GetImageMetadata"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", image); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, matches); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to inspect image metadata: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "s", &path); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_array(reply, 'y', &data, &sz); + if (r < 0) + return bus_log_parse_error(r); + + (void) pager_open(arg_pager_flags); + + if (arg_cat) { + printf("%s-- OS Release: --%s\n", ansi_highlight(), ansi_normal()); + fwrite(data, sz, 1, stdout); + fflush(stdout); + nl = true; + } else { + _cleanup_free_ char *pretty_portable = NULL, *pretty_os = NULL; + _cleanup_fclose_ FILE *f; + + f = fmemopen_unlocked((void*) data, sz, "re"); + if (!f) + return log_error_errno(errno, "Failed to open /etc/os-release buffer: %m"); + + r = parse_env_file(f, "/etc/os-release", + "PORTABLE_PRETTY_NAME", &pretty_portable, + "PRETTY_NAME", &pretty_os); + if (r < 0) + return log_error_errno(r, "Failed to parse /etc/os-release: %m"); + + printf("Image:\n\t%s\n" + "Portable Service:\n\t%s\n" + "Operating System:\n\t%s\n", + path, + strna(pretty_portable), + strna(pretty_os)); + } + + r = sd_bus_message_enter_container(reply, 'a', "{say}"); + if (r < 0) + return bus_log_parse_error(r); + + for (;;) { + const char *name; + + r = sd_bus_message_enter_container(reply, 'e', "say"); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + r = sd_bus_message_read(reply, "s", &name); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_array(reply, 'y', &data, &sz); + if (r < 0) + return bus_log_parse_error(r); + + if (arg_cat) { + if (nl) + fputc('\n', stdout); + + printf("%s-- Unit file: %s --%s\n", ansi_highlight(), name, ansi_normal()); + fwrite(data, sz, 1, stdout); + fflush(stdout); + nl = true; + } else { + if (!header) { + fputs("Unit files:\n", stdout); + header = true; + } + + fputc('\t', stdout); + fputs(name, stdout); + fputc('\n', stdout); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return 0; +} + +static int print_changes(sd_bus_message *m) { + int r; + + if (arg_quiet) + return 0; + + r = sd_bus_message_enter_container(m, 'a', "(sss)"); + if (r < 0) + return bus_log_parse_error(r); + + for (;;) { + const char *type, *path, *source; + + r = sd_bus_message_read(m, "(sss)", &type, &path, &source); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + if (streq(type, "symlink")) + log_info("Created symlink %s %s %s.", path, special_glyph(SPECIAL_GLYPH_ARROW), source); + else if (streq(type, "copy")) { + if (isempty(source)) + log_info("Copied %s.", path); + else + log_info("Copied %s %s %s.", source, special_glyph(SPECIAL_GLYPH_ARROW), path); + } else if (streq(type, "unlink")) + log_info("Removed %s.", path); + else if (streq(type, "write")) + log_info("Written %s.", path); + else if (streq(type, "mkdir")) + log_info("Created directory %s.", path); + else + log_error("Unexpected change: %s/%s/%s", type, path, source); + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +static int attach_image(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_strv_free_ char **matches = NULL; + _cleanup_free_ char *image = NULL; + int r; + + r = determine_image(argv[1], false, &image); + if (r < 0) + return r; + + r = determine_matches(argv[1], argv + 2, false, &matches); + if (r < 0) + return r; + + r = acquire_bus(&bus); + if (r < 0) + return r; + + (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.portable1", + "/org/freedesktop/portable1", + "org.freedesktop.portable1.Manager", + "AttachImage"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", image); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, matches); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "sbs", arg_profile, arg_runtime, arg_copy_mode); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to attach image: %s", bus_error_message(&error, r)); + + (void) maybe_reload(&bus); + + print_changes(reply); + return 0; +} + +static int detach_image(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *image = NULL; + int r; + + r = determine_image(argv[1], true, &image); + if (r < 0) + return r; + + r = acquire_bus(&bus); + if (r < 0) + return r; + + (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call_method( + bus, + "org.freedesktop.portable1", + "/org/freedesktop/portable1", + "org.freedesktop.portable1.Manager", + "DetachImage", + &error, + &reply, + "sb", image, arg_runtime); + if (r < 0) + return log_error_errno(r, "Failed to detach image: %s", bus_error_message(&error, r)); + + (void) maybe_reload(&bus); + + print_changes(reply); + return 0; +} + +static int list_images(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(table_unrefp) Table *table = NULL; + int r; + + r = acquire_bus(&bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.portable1", + "/org/freedesktop/portable1", + "org.freedesktop.portable1.Manager", + "ListImages", + &error, + &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to list images: %s", bus_error_message(&error, r)); + + table = table_new("name", "type", "ro", "crtime", "mtime", "usage", "state"); + if (!table) + return log_oom(); + + r = sd_bus_message_enter_container(reply, 'a', "(ssbtttso)"); + if (r < 0) + return bus_log_parse_error(r); + + for (;;) { + const char *name, *type, *state; + uint64_t crtime, mtime, usage; + TableCell *cell; + bool ro_bool; + int ro_int; + + r = sd_bus_message_read(reply, "(ssbtttso)", &name, &type, &ro_int, &crtime, &mtime, &usage, &state, NULL); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + r = table_add_many(table, + TABLE_STRING, name, + TABLE_STRING, type); + if (r < 0) + return log_error_errno(r, "Failed to add row to table: %m"); + + ro_bool = ro_int; + r = table_add_cell(table, &cell, TABLE_BOOLEAN, &ro_bool); + if (r < 0) + return log_error_errno(r, "Failed to add row to table: %m"); + + if (ro_bool) { + r = table_set_color(table, cell, ansi_highlight_red()); + if (r < 0) + return log_error_errno(r, "Failed to set table cell color: %m"); + } + + r = table_add_many(table, + TABLE_TIMESTAMP, crtime, + TABLE_TIMESTAMP, mtime, + TABLE_SIZE, usage); + if (r < 0) + return log_error_errno(r, "Failed to add row to table: %m"); + + r = table_add_cell(table, &cell, TABLE_STRING, state); + if (r < 0) + return log_error_errno(r, "Failed to add row to table: %m"); + + if (!streq(state, "detached")) { + r = table_set_color(table, cell, ansi_highlight_green()); + if (r < 0) + return log_error_errno(r, "Failed to set table cell color: %m"); + } + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + if (table_get_rows(table) > 1) { + r = table_set_sort(table, (size_t) 0, (size_t) -1); + if (r < 0) + return log_error_errno(r, "Failed to sort table: %m"); + + table_set_header(table, arg_legend); + + r = table_print(table, NULL); + if (r < 0) + return log_error_errno(r, "Failed to show table: %m"); + } + + if (arg_legend) { + if (table_get_rows(table) > 1) + printf("\n%zu images listed.\n", table_get_rows(table) - 1); + else + printf("No images.\n"); + } + + return 0; +} + +static int remove_image(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r, i; + + r = acquire_bus(&bus); + if (r < 0) + return r; + + (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + for (i = 1; i < argc; i++) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.portable1", + "/org/freedesktop/portable1", + "org.freedesktop.portable1.Manager", + "RemoveImage"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", argv[i]); + if (r < 0) + return bus_log_create_error(r); + + /* This is a slow operation, hence turn off any method call timeouts */ + r = sd_bus_call(bus, m, USEC_INFINITY, &error, NULL); + if (r < 0) + return log_error_errno(r, "Could not remove image: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int read_only_image(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int b = true, r; + + if (argc > 2) { + b = parse_boolean(argv[2]); + if (b < 0) + return log_error_errno(b, "Failed to parse boolean argument: %s", argv[2]); + } + + r = acquire_bus(&bus); + if (r < 0) + return r; + + (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call_method( + bus, + "org.freedesktop.portable1", + "/org/freedesktop/portable1", + "org.freedesktop.portable1.Manager", + "MarkImageReadOnly", + &error, + NULL, + "sb", argv[1], b); + if (r < 0) + return log_error_errno(r, "Could not mark image read-only: %s", bus_error_message(&error, r)); + + return 0; +} + +static int set_limit(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + uint64_t limit; + int r; + + r = acquire_bus(&bus); + if (r < 0) + return r; + + (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + if (STR_IN_SET(argv[argc-1], "-", "none", "infinity")) + limit = (uint64_t) -1; + else { + r = parse_size(argv[argc-1], 1024, &limit); + if (r < 0) + return log_error_errno(r, "Failed to parse size: %s", argv[argc-1]); + } + + if (argc > 2) + /* With two arguments changes the quota limit of the specified image */ + r = sd_bus_call_method( + bus, + "org.freedesktop.portable1", + "/org/freedesktop/portable1", + "org.freedesktop.portable1.Manager", + "SetImageLimit", + &error, + NULL, + "st", argv[1], limit); + else + /* With one argument changes the pool quota limit */ + r = sd_bus_call_method( + bus, + "org.freedesktop.portable1", + "/org/freedesktop/portable1", + "org.freedesktop.portable1.Manager", + "SetPoolLimit", + &error, + NULL, + "t", limit); + + if (r < 0) + return log_error_errno(r, "Could not set limit: %s", bus_error_message(&error, r)); + + return 0; +} + +static int is_image_attached(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *image = NULL; + const char *state; + int r; + + r = determine_image(argv[1], true, &image); + if (r < 0) + return r; + + r = acquire_bus(&bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.portable1", + "/org/freedesktop/portable1", + "org.freedesktop.portable1.Manager", + "GetImageState", + &error, + &reply, + "s", image); + if (r < 0) + return log_error_errno(r, "Failed to get image state: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "s", &state); + if (r < 0) + return r; + + if (!arg_quiet) + puts(state); + + return streq(state, "detached"); +} + +static int dump_profiles(void) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_strv_free_ char **l = NULL; + char **i; + int r; + + r = acquire_bus(&bus); + if (r < 0) + return r; + + r = sd_bus_get_property_strv( + bus, + "org.freedesktop.portable1", + "/org/freedesktop/portable1", + "org.freedesktop.portable1.Manager", + "Profiles", + &error, + &l); + if (r < 0) + return log_error_errno(r, "Failed to acquire list of profiles: %s", bus_error_message(&error, r)); + + if (arg_legend) + log_info("Available unit profiles:"); + + STRV_FOREACH(i, l) { + fputs(*i, stdout); + fputc('\n', stdout); + } + + return 0; +} + +static int help(int argc, char *argv[], void *userdata) { + _cleanup_free_ char *link = NULL; + int r; + + (void) pager_open(arg_pager_flags); + + r = terminal_urlify_man("portablectl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n\n" + "%sAttach or detach portable services from the local system.%s\n" + "\nCommands:\n" + " list List available portable service images\n" + " attach NAME|PATH [PREFIX...]\n" + " Attach the specified portable service image\n" + " detach NAME|PATH Detach the specified portable service image\n" + " inspect NAME|PATH [PREFIX...]\n" + " Show details of specified portable service image\n" + " is-attached NAME|PATH Query if portable service image is attached\n" + " read-only NAME|PATH [BOOL] Mark or unmark portable service image read-only\n" + " remove NAME|PATH... Remove a portable service image\n" + " set-limit [NAME|PATH] Set image or pool size limit (disk quota)\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --no-legend Do not show the headers and footers\n" + " --no-ask-password Do not ask for system passwords\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " -q --quiet Suppress informational messages\n" + " -p --profile=PROFILE Pick security profile for portable service\n" + " --copy=copy|auto|symlink Prefer copying or symlinks if possible\n" + " --runtime Attach portable service until next reboot only\n" + " --no-reload Don't reload the system and service manager\n" + " --cat When inspecting include unit and os-release file\n" + " contents\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_PAGER, + ARG_NO_LEGEND, + ARG_NO_ASK_PASSWORD, + ARG_COPY, + ARG_RUNTIME, + ARG_NO_RELOAD, + ARG_CAT, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "quiet", no_argument, NULL, 'q' }, + { "profile", required_argument, NULL, 'p' }, + { "copy", required_argument, NULL, ARG_COPY }, + { "runtime", no_argument, NULL, ARG_RUNTIME }, + { "no-reload", no_argument, NULL, ARG_NO_RELOAD }, + { "cat", no_argument, NULL, ARG_CAT }, + {} + }; + + assert(argc >= 0); + assert(argv); + + for (;;) { + int c; + + c = getopt_long(argc, argv, "hH:M:qp:", options, NULL); + if (c < 0) + break; + + switch (c) { + + case 'h': + return help(0, NULL, NULL); + + case ARG_VERSION: + return version(); + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_NO_LEGEND: + arg_legend = false; + break; + + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case 'q': + arg_quiet = true; + break; + + case 'p': + if (streq(optarg, "help")) + return dump_profiles(); + + if (!filename_is_valid(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unit profile name not valid: %s", optarg); + + arg_profile = optarg; + break; + + case ARG_COPY: + if (streq(optarg, "auto")) + arg_copy_mode = NULL; + else if (STR_IN_SET(optarg, "copy", "symlink")) + arg_copy_mode = optarg; + else if (streq(optarg, "help")) { + puts("auto\n" + "copy\n" + "symlink"); + return 0; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse --copy= argument: %s", optarg); + + break; + + case ARG_RUNTIME: + arg_runtime = true; + break; + + case ARG_NO_RELOAD: + arg_reload = false; + break; + + case ARG_CAT: + arg_cat = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + } + + return 1; +} + +static int run(int argc, char *argv[]) { + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, help }, + { "list", VERB_ANY, 1, VERB_DEFAULT, list_images }, + { "attach", 2, VERB_ANY, 0, attach_image }, + { "detach", 2, 2, 0, detach_image }, + { "inspect", 2, VERB_ANY, 0, inspect_image }, + { "is-attached", 2, 2, 0, is_image_attached }, + { "read-only", 2, 3, 0, read_only_image }, + { "remove", 2, VERB_ANY, 0, remove_image }, + { "set-limit", 3, 3, 0, set_limit }, + {} + }; + + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/portable/portabled-bus.c b/src/portable/portabled-bus.c new file mode 100644 index 00000000..0fa05434 --- /dev/null +++ b/src/portable/portabled-bus.c @@ -0,0 +1,403 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "bus-common-errors.h" +#include "bus-polkit.h" +#include "fd-util.h" +#include "io-util.h" +#include "machine-image.h" +#include "missing_capability.h" +#include "portable.h" +#include "portabled-bus.h" +#include "portabled-image-bus.h" +#include "portabled-image.h" +#include "portabled.h" +#include "strv.h" +#include "user-util.h" + +static int property_get_pool_path( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + assert(bus); + assert(reply); + + return sd_bus_message_append(reply, "s", "/var/lib/portables"); +} + +static int property_get_pool_usage( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_close_ int fd = -1; + uint64_t usage = (uint64_t) -1; + + assert(bus); + assert(reply); + + fd = open("/var/lib/portables", O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (fd >= 0) { + BtrfsQuotaInfo q; + + if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0) + usage = q.referenced; + } + + return sd_bus_message_append(reply, "t", usage); +} + +static int property_get_pool_limit( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_close_ int fd = -1; + uint64_t size = (uint64_t) -1; + + assert(bus); + assert(reply); + + fd = open("/var/lib/portables", O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (fd >= 0) { + BtrfsQuotaInfo q; + + if (btrfs_subvol_get_subtree_quota_fd(fd, 0, &q) >= 0) + size = q.referenced_max; + } + + return sd_bus_message_append(reply, "t", size); +} + +static int property_get_profiles( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + _cleanup_strv_free_ char **l = NULL; + int r; + + assert(bus); + assert(reply); + + r = portable_get_profiles(&l); + if (r < 0) + return r; + + return sd_bus_message_append_strv(reply, l); +} + +static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *p = NULL; + Manager *m = userdata; + const char *name; + Image *image; + int r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + r = bus_image_acquire(m, message, name, NULL, BUS_IMAGE_REFUSE_BY_PATH, NULL, &image, error); + if (r < 0) + return r; + + r = bus_image_path(image, &p); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "o", p); +} + +static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_hashmap_free_ Hashmap *images = NULL; + Manager *m = userdata; + Image *image; + Iterator i; + int r; + + assert(message); + assert(m); + + images = hashmap_new(&image_hash_ops); + if (!images) + return -ENOMEM; + + r = manager_image_cache_discover(m, images, error); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(ssbtttso)"); + if (r < 0) + return r; + + HASHMAP_FOREACH(image, images, i) { + _cleanup_(sd_bus_error_free) sd_bus_error error_state = SD_BUS_ERROR_NULL; + PortableState state = _PORTABLE_STATE_INVALID; + _cleanup_free_ char *p = NULL; + + r = bus_image_path(image, &p); + if (r < 0) + return r; + + r = portable_get_state( + sd_bus_message_get_bus(message), + image->path, + 0, + &state, + &error_state); + if (r < 0) + log_debug_errno(r, "Failed to get state of image '%s', ignoring: %s", + image->path, bus_error_message(&error_state, r)); + + r = sd_bus_message_append(reply, "(ssbtttso)", + image->name, + image_type_to_string(image->type), + image->read_only, + image->crtime, + image->mtime, + image->usage, + portable_state_to_string(state), + p); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int redirect_method_to_image( + Manager *m, + sd_bus_message *message, + sd_bus_error *error, + int (*method)(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error* error)) { + + const char *name_or_path; + int r; + + assert(m); + assert(message); + assert(method); + + r = sd_bus_message_read(message, "s", &name_or_path); + if (r < 0) + return r; + + return method(m, message, name_or_path, NULL, error); +} + +static int method_get_image_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(userdata, message, error, bus_image_common_get_os_release); +} + +static int method_get_image_metadata(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(userdata, message, error, bus_image_common_get_metadata); +} + +static int method_get_image_state(sd_bus_message *message, void *userdata, sd_bus_error *error) { + const char *name_or_path; + PortableState state; + int r; + + assert(message); + + r = sd_bus_message_read(message, "s", &name_or_path); + if (r < 0) + return r; + + r = portable_get_state( + sd_bus_message_get_bus(message), + name_or_path, + 0, + &state, + error); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "s", portable_state_to_string(state)); +} + +static int method_attach_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(userdata, message, error, bus_image_common_attach); +} + +static int method_detach_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { + PortableChange *changes = NULL; + Manager *m = userdata; + size_t n_changes = 0; + const char *name_or_path; + int r, runtime; + + assert(message); + assert(m); + + /* Note that we do not redirect detaching to the image object here, because we want to allow that users can + * detach already deleted images too, in case the user already deleted an image before properly detaching + * it. */ + + r = sd_bus_message_read(message, "sb", &name_or_path, &runtime); + if (r < 0) + return r; + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.portable1.attach-images", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = portable_detach( + sd_bus_message_get_bus(message), + name_or_path, + runtime ? PORTABLE_RUNTIME : 0, + &changes, + &n_changes, + error); + if (r < 0) + goto finish; + + r = reply_portable_changes(message, changes, n_changes); + +finish: + portable_changes_free(changes, n_changes); + return r; +} + +static int method_remove_image(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(userdata, message, error, bus_image_common_remove); +} + +static int method_mark_image_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(userdata, message, error, bus_image_common_mark_read_only); +} + +static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return redirect_method_to_image(userdata, message, error, bus_image_common_set_limit); +} + +static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + uint64_t limit; + int r; + + assert(message); + + r = sd_bus_message_read(message, "t", &limit); + if (r < 0) + return r; + if (!FILE_SIZE_VALID_OR_INFINITY(limit)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range"); + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.portable1.manage-images", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + (void) btrfs_qgroup_set_limit("/var/lib/portables", 0, limit); + + r = btrfs_subvol_set_subtree_quota_limit("/var/lib/portables", 0, limit); + if (r == -ENOTTY) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs."); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m"); + + return sd_bus_reply_method_return(message, NULL); +} + +const sd_bus_vtable manager_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0), + SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0), + SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0), + SD_BUS_PROPERTY("Profiles", "as", property_get_profiles, 0, 0), + SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListImages", NULL, "a(ssbtttso)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImageOSRelease", "s", "a{ss}", method_get_image_os_release, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImageMetadata", "sas", "saya{say}", method_get_image_metadata, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImageState", "s", "s", method_get_image_state, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("AttachImage", "sassbs", "a(sss)", method_attach_image, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("DetachImage", "sb", "a(sss)", method_detach_image, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END +}; + +int reply_portable_changes(sd_bus_message *m, const PortableChange *changes, size_t n_changes) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + size_t i; + int r; + + assert(m); + assert(changes || n_changes == 0); + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(sss)"); + if (r < 0) + return r; + + for (i = 0; i < n_changes; i++) { + r = sd_bus_message_append(reply, "(sss)", + portable_change_type_to_string(changes[i].type), + changes[i].path, + changes[i].source); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} diff --git a/src/portable/portabled-bus.h b/src/portable/portabled-bus.h new file mode 100644 index 00000000..5810517c --- /dev/null +++ b/src/portable/portabled-bus.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "portable.h" + +extern const sd_bus_vtable manager_vtable[]; + +int reply_portable_changes(sd_bus_message *m, const PortableChange *changes, size_t n_changes); diff --git a/src/portable/portabled-image-bus.c b/src/portable/portabled-image-bus.c new file mode 100644 index 00000000..2bd1c495 --- /dev/null +++ b/src/portable/portabled-image-bus.c @@ -0,0 +1,742 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-label.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "io-util.h" +#include "machine-image.h" +#include "missing_capability.h" +#include "portable.h" +#include "portabled-bus.h" +#include "portabled-image-bus.h" +#include "portabled-image.h" +#include "portabled.h" +#include "process-util.h" +#include "strv.h" +#include "user-util.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, image_type, ImageType); + +int bus_image_common_get_os_release( + Manager *m, + sd_bus_message *message, + const char *name_or_path, + Image *image, + sd_bus_error *error) { + + int r; + + assert(name_or_path || image); + assert(message); + + if (!m) { + assert(image); + m = image->userdata; + } + + r = bus_image_acquire(m, + message, + name_or_path, + image, + BUS_IMAGE_AUTHENTICATE_BY_PATH, + "org.freedesktop.portable1.inspect-images", + &image, + error); + if (r < 0) + return r; + if (r == 0) /* Will call us back */ + return 1; + + if (!image->metadata_valid) { + r = image_read_metadata(image); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m"); + } + + return bus_reply_pair_array(message, image->os_release); +} + +static int bus_image_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_image_common_get_os_release(NULL, message, NULL, userdata, error); +} + +static int append_fd(sd_bus_message *m, PortableMetadata *d) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *buf = NULL; + size_t n; + int r; + + assert(m); + assert(d); + assert(d->fd >= 0); + + f = fdopen(d->fd, "r"); + if (!f) + return -errno; + + d->fd = -1; + + r = read_full_stream(f, &buf, &n); + if (r < 0) + return r; + + return sd_bus_message_append_array(m, 'y', buf, n); +} + +int bus_image_common_get_metadata( + Manager *m, + sd_bus_message *message, + const char *name_or_path, + Image *image, + sd_bus_error *error) { + + _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL; + _cleanup_hashmap_free_ Hashmap *unit_files = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ PortableMetadata **sorted = NULL; + _cleanup_strv_free_ char **matches = NULL; + size_t i; + int r; + + assert(name_or_path || image); + assert(message); + + if (!m) { + assert(image); + m = image->userdata; + } + + r = sd_bus_message_read_strv(message, &matches); + if (r < 0) + return r; + + r = bus_image_acquire(m, + message, + name_or_path, + image, + BUS_IMAGE_AUTHENTICATE_BY_PATH, + "org.freedesktop.portable1.inspect-images", + &image, + error); + if (r < 0) + return r; + if (r == 0) /* Will call us back */ + return 1; + + r = portable_extract( + image->path, + matches, + &os_release, + &unit_files, + error); + if (r < 0) + return r; + + r = portable_metadata_hashmap_to_sorted_array(unit_files, &sorted); + if (r < 0) + return r; + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "s", image->path); + if (r < 0) + return r; + + r = append_fd(reply, os_release); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "{say}"); + if (r < 0) + return r; + + for (i = 0; i < hashmap_size(unit_files); i++) { + + r = sd_bus_message_open_container(reply, 'e', "say"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "s", sorted[i]->name); + if (r < 0) + return r; + + r = append_fd(reply, sorted[i]); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static int bus_image_method_get_metadata(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_image_common_get_metadata(NULL, message, NULL, userdata, error); +} + +static int bus_image_method_get_state( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + Image *image = userdata; + PortableState state; + int r; + + assert(message); + assert(image); + + r = portable_get_state( + sd_bus_message_get_bus(message), + image->path, + 0, + &state, + error); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, "s", portable_state_to_string(state)); +} + +int bus_image_common_attach( + Manager *m, + sd_bus_message *message, + const char *name_or_path, + Image *image, + sd_bus_error *error) { + + _cleanup_strv_free_ char **matches = NULL; + PortableChange *changes = NULL; + PortableFlags flags = 0; + const char *profile, *copy_mode; + size_t n_changes = 0; + int runtime, r; + + assert(message); + assert(name_or_path || image); + + if (!m) { + assert(image); + m = image->userdata; + } + + r = sd_bus_message_read_strv(message, &matches); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "sbs", &profile, &runtime, ©_mode); + if (r < 0) + return r; + + if (streq(copy_mode, "symlink")) + flags |= PORTABLE_PREFER_SYMLINK; + else if (streq(copy_mode, "copy")) + flags |= PORTABLE_PREFER_COPY; + else if (!isempty(copy_mode)) + return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Unknown copy mode '%s'", copy_mode); + + if (runtime) + flags |= PORTABLE_RUNTIME; + + r = bus_image_acquire(m, + message, + name_or_path, + image, + BUS_IMAGE_AUTHENTICATE_ALL, + "org.freedesktop.portable1.attach-images", + &image, + error); + if (r < 0) + return r; + if (r == 0) /* Will call us back */ + return 1; + + r = portable_attach( + sd_bus_message_get_bus(message), + image->path, + matches, + profile, + flags, + &changes, + &n_changes, + error); + if (r < 0) + goto finish; + + r = reply_portable_changes(message, changes, n_changes); + +finish: + portable_changes_free(changes, n_changes); + return r; +} + +static int bus_image_method_attach(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_image_common_attach(NULL, message, NULL, userdata, error); +} + +static int bus_image_method_detach( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { + + PortableChange *changes = NULL; + Image *image = userdata; + Manager *m = image->userdata; + size_t n_changes = 0; + int r, runtime; + + assert(message); + assert(image); + assert(m); + + r = sd_bus_message_read(message, "b", &runtime); + if (r < 0) + return r; + + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + "org.freedesktop.portable1.attach-images", + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = portable_detach( + sd_bus_message_get_bus(message), + image->path, + runtime ? PORTABLE_RUNTIME : 0, + &changes, + &n_changes, + error); + if (r < 0) + goto finish; + + r = reply_portable_changes(message, changes, n_changes); + +finish: + portable_changes_free(changes, n_changes); + return r; +} + +int bus_image_common_remove( + Manager *m, + sd_bus_message *message, + const char *name_or_path, + Image *image, + sd_bus_error *error) { + + _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 }; + _cleanup_(sigkill_waitp) pid_t child = 0; + PortableState state; + int r; + + assert(message); + assert(name_or_path || image); + + if (!m) { + assert(image); + m = image->userdata; + } + + if (m->n_operations >= OPERATIONS_MAX) + return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations."); + + r = bus_image_acquire(m, + message, + name_or_path, + image, + BUS_IMAGE_AUTHENTICATE_ALL, + "org.freedesktop.portable1.manage-images", + &image, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = portable_get_state( + sd_bus_message_get_bus(message), + image->path, + 0, + &state, + error); + if (r < 0) + return r; + + if (state != PORTABLE_DETACHED) + return sd_bus_error_set_errnof(error, EBUSY, "Image '%s' is not detached, refusing.", image->path); + + if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) + return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m"); + + r = safe_fork("(sd-imgrm)", FORK_RESET_SIGNALS, &child); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m"); + if (r == 0) { + errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]); + + r = image_remove(image); + if (r < 0) { + (void) write(errno_pipe_fd[1], &r, sizeof(r)); + _exit(EXIT_FAILURE); + } + + _exit(EXIT_SUCCESS); + } + + errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]); + + r = operation_new(m, child, message, errno_pipe_fd[0], NULL); + if (r < 0) + return r; + + child = 0; + errno_pipe_fd[0] = -1; + + return 1; +} + +static int bus_image_method_remove(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_image_common_remove(NULL, message, NULL, userdata, error); +} + +int bus_image_common_mark_read_only( + Manager *m, + sd_bus_message *message, + const char *name_or_path, + Image *image, + sd_bus_error *error) { + + int r, read_only; + + assert(message); + assert(name_or_path || image); + + if (!m) { + assert(image); + m = image->userdata; + } + + r = sd_bus_message_read(message, "b", &read_only); + if (r < 0) + return r; + + r = bus_image_acquire(m, + message, + name_or_path, + image, + BUS_IMAGE_AUTHENTICATE_ALL, + "org.freedesktop.portable1.manage-images", + &image, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = image_read_only(image, read_only); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int bus_image_method_mark_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_image_common_mark_read_only(NULL, message, NULL, userdata, error); +} + +int bus_image_common_set_limit( + Manager *m, + sd_bus_message *message, + const char *name_or_path, + Image *image, + sd_bus_error *error) { + + uint64_t limit; + int r; + + assert(message); + assert(name_or_path || image); + + if (!m) { + assert(image); + m = image->userdata; + } + + r = sd_bus_message_read(message, "t", &limit); + if (r < 0) + return r; + if (!FILE_SIZE_VALID_OR_INFINITY(limit)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range"); + + r = bus_image_acquire(m, + message, + name_or_path, + image, + BUS_IMAGE_AUTHENTICATE_ALL, + "org.freedesktop.portable1.manage-images", + &image, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Will call us back */ + + r = image_set_limit(image, limit); + if (r < 0) + return r; + + return sd_bus_reply_method_return(message, NULL); +} + +static int bus_image_method_set_limit(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return bus_image_common_set_limit(NULL, message, NULL, userdata, error); +} + +const sd_bus_vtable image_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Image, name), 0), + SD_BUS_PROPERTY("Path", "s", NULL, offsetof(Image, path), 0), + SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Image, type), 0), + SD_BUS_PROPERTY("ReadOnly", "b", bus_property_get_bool, offsetof(Image, read_only), 0), + SD_BUS_PROPERTY("CreationTimestamp", "t", NULL, offsetof(Image, crtime), 0), + SD_BUS_PROPERTY("ModificationTimestamp", "t", NULL, offsetof(Image, mtime), 0), + SD_BUS_PROPERTY("Usage", "t", NULL, offsetof(Image, usage), 0), + SD_BUS_PROPERTY("Limit", "t", NULL, offsetof(Image, limit), 0), + SD_BUS_PROPERTY("UsageExclusive", "t", NULL, offsetof(Image, usage_exclusive), 0), + SD_BUS_PROPERTY("LimitExclusive", "t", NULL, offsetof(Image, limit_exclusive), 0), + SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_image_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMetadata", "as", "saya{say}", bus_image_method_get_metadata, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetState", NULL, "s", bus_image_method_get_state, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Attach", "assbs", "a(sss)", bus_image_method_attach, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Detach", "b", "a(sss)", bus_image_method_detach, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Remove", NULL, NULL, bus_image_method_remove, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END +}; + +int bus_image_path(Image *image, char **ret) { + assert(image); + assert(ret); + + if (!image->discoverable) + return -EINVAL; + + return sd_bus_path_encode("/org/freedesktop/portable1/image", image->name, ret); +} + +int bus_image_acquire( + Manager *m, + sd_bus_message *message, + const char *name_or_path, + Image *image, + ImageAcquireMode mode, + const char *polkit_action, + Image **ret, + sd_bus_error *error) { + + _cleanup_(image_unrefp) Image *loaded = NULL; + Image *cached; + int r; + + assert(m); + assert(message); + assert(name_or_path || image); + assert(mode >= 0); + assert(mode < _BUS_IMAGE_ACQUIRE_MODE_MAX); + assert(polkit_action || mode == BUS_IMAGE_REFUSE_BY_PATH); + assert(ret); + + /* Acquires an 'Image' object if not acquired yet, and enforces necessary authentication while doing so. */ + + if (mode == BUS_IMAGE_AUTHENTICATE_ALL) { + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + polkit_action, + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) { /* Will call us back */ + *ret = NULL; + return 0; + } + } + + /* Already passed in? */ + if (image) { + *ret = image; + return 1; + } + + /* Let's see if this image is already cached? */ + cached = manager_image_cache_get(m, name_or_path); + if (cached) { + *ret = cached; + return 1; + } + + if (image_name_is_valid(name_or_path)) { + + /* If it's a short name, let's search for it */ + r = image_find(IMAGE_PORTABLE, name_or_path, &loaded); + if (r == -ENOENT) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PORTABLE_IMAGE, "No image '%s' found.", name_or_path); + + /* other errors are handled below… */ + } else { + /* Don't accept path if this is always forbidden */ + if (mode == BUS_IMAGE_REFUSE_BY_PATH) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Expected image name, not path in place of '%s'.", name_or_path); + + if (!path_is_absolute(name_or_path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is not valid or not a valid path.", name_or_path); + + if (!path_is_normalized(name_or_path)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image path '%s' is not normalized.", name_or_path); + + if (mode == BUS_IMAGE_AUTHENTICATE_BY_PATH) { + r = bus_verify_polkit_async( + message, + CAP_SYS_ADMIN, + polkit_action, + NULL, + false, + UID_INVALID, + &m->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) { /* Will call us back */ + *ret = NULL; + return 0; + } + } + + r = image_from_path(name_or_path, &loaded); + } + if (r == -EMEDIUMTYPE) { + sd_bus_error_setf(error, BUS_ERROR_BAD_PORTABLE_IMAGE_TYPE, "Typ of image '%s' not recognized; supported image types are directories/btrfs subvolumes, block devices, and raw disk image files with suffix '.raw'.", name_or_path); + return r; + } + if (r < 0) + return r; + + /* Add what we just loaded to the cache. This has as side-effect that the object stays in memory until the + * cache is purged again, i.e. at least for the current event loop iteration, which is all we need, and which + * means we don't actually need to ref the return object. */ + r = manager_image_cache_add(m, loaded); + if (r < 0) + return r; + + *ret = loaded; + return 1; +} + +int bus_image_object_find( + sd_bus *bus, + const char *path, + const char *interface, + void *userdata, + void **found, + sd_bus_error *error) { + + _cleanup_free_ char *e = NULL; + Manager *m = userdata; + Image *image = NULL; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + + r = sd_bus_path_decode(path, "/org/freedesktop/portable1/image", &e); + if (r < 0) + return 0; + if (r == 0) + goto not_found; + + r = bus_image_acquire(m, sd_bus_get_current_message(bus), e, NULL, BUS_IMAGE_REFUSE_BY_PATH, NULL, &image, error); + if (r == -ENOENT) + goto not_found; + if (r < 0) + return r; + + *found = image; + return 1; + +not_found: + *found = NULL; + return 0; +} + +int bus_image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_hashmap_free_ Hashmap *images = NULL; + _cleanup_strv_free_ char **l = NULL; + size_t n_allocated = 0, n = 0; + Manager *m = userdata; + Image *image; + Iterator i; + int r; + + assert(bus); + assert(path); + assert(nodes); + + images = hashmap_new(&image_hash_ops); + if (!images) + return -ENOMEM; + + r = manager_image_cache_discover(m, images, error); + if (r < 0) + return r; + + HASHMAP_FOREACH(image, images, i) { + char *p; + + r = bus_image_path(image, &p); + if (r < 0) + return r; + + if (!GREEDY_REALLOC(l, n_allocated, n+2)) { + free(p); + return -ENOMEM; + } + + l[n++] = p; + l[n] = NULL; + } + + *nodes = TAKE_PTR(l); + + return 1; +} diff --git a/src/portable/portabled-image-bus.h b/src/portable/portabled-image-bus.h new file mode 100644 index 00000000..825dea26 --- /dev/null +++ b/src/portable/portabled-image-bus.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "machine-image.h" +#include "portabled.h" + +int bus_image_common_get_os_release(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error); +int bus_image_common_get_metadata(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error); +int bus_image_common_attach(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error); +int bus_image_common_remove(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error); +int bus_image_common_mark_read_only(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error); +int bus_image_common_set_limit(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, sd_bus_error *error); + +extern const sd_bus_vtable image_vtable[]; + +int bus_image_path(Image *image, char **ret); + +/* So here's some complexity: some of operations can either take an image name, or a fully qualified file system path + * to an image. We need to authenticate differently when processing these two: images referenced via simple image names + * mean the images are located in the image search path and thus safe for limited read access for unprivileged + * clients. For operations on images located anywhere else we need explicit authentication however, so that + * unprivileged clients can't make us open arbitrary files in the file system. + * + * The "Image" bus objects directly represent images in the image search path, but do not exist for path-referenced + * images. Hence, when requesting a bus object we need to refuse references by file system path, but still allow + * references by image name. Depending on the operation to execute potentially we need to authenticate in all cases. */ + +typedef enum ImageAcquireMode { + BUS_IMAGE_REFUSE_BY_PATH, /* allow by name + prohibit by path */ + BUS_IMAGE_AUTHENTICATE_BY_PATH, /* allow by name + polkit by path */ + BUS_IMAGE_AUTHENTICATE_ALL, /* polkit by name + polkit by path */ + _BUS_IMAGE_ACQUIRE_MODE_MAX, + _BUS_IMAGE_ACQUIRE_MODE_INVALID = -1 +} ImageAcquireMode; + +int bus_image_acquire(Manager *m, sd_bus_message *message, const char *name_or_path, Image *image, ImageAcquireMode mode, const char *polkit_action, Image **ret, sd_bus_error *error); + +int bus_image_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +int bus_image_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); diff --git a/src/portable/portabled-image.c b/src/portable/portabled-image.c new file mode 100644 index 00000000..d95845b3 --- /dev/null +++ b/src/portable/portabled-image.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "portable.h" +#include "portabled-image.h" +#include "portabled.h" + +Image *manager_image_cache_get(Manager *m, const char *name_or_path) { + assert(m); + + return hashmap_get(m->image_cache, name_or_path); +} + +static int image_cache_flush(sd_event_source *s, void *userdata) { + Manager *m = userdata; + + assert(s); + assert(m); + + hashmap_clear(m->image_cache); + return 0; +} + +static int manager_image_cache_initialize(Manager *m) { + int r; + + assert(m); + + r = hashmap_ensure_allocated(&m->image_cache, &image_hash_ops); + if (r < 0) + return r; + + /* We flush the cache as soon as we are idle again */ + if (!m->image_cache_defer_event) { + r = sd_event_add_defer(m->event, &m->image_cache_defer_event, image_cache_flush, m); + if (r < 0) + return r; + + r = sd_event_source_set_priority(m->image_cache_defer_event, SD_EVENT_PRIORITY_IDLE); + if (r < 0) + return r; + } + + r = sd_event_source_set_enabled(m->image_cache_defer_event, SD_EVENT_ONESHOT); + if (r < 0) + return r; + + return 0; +} + +int manager_image_cache_add(Manager *m, Image *image) { + int r; + + assert(m); + + /* We add the specified image to the cache under two keys. + * + * 1. Always under its path + * + * 2. If the image was discovered in the search path (i.e. its discoverable boolean set) we'll also add it + * under its short name. + */ + + r = manager_image_cache_initialize(m); + if (r < 0) + return r; + + image->userdata = m; + + r = hashmap_put(m->image_cache, image->path, image); + if (r < 0) + return r; + + image_ref(image); + + if (image->discoverable) { + r = hashmap_put(m->image_cache, image->name, image); + if (r < 0) + return r; + + image_ref(image); + } + + return 0; +} + +int manager_image_cache_discover(Manager *m, Hashmap *images, sd_bus_error *error) { + Image *image; + Iterator i; + int r; + + assert(m); + + /* A wrapper around image_discover() (for finding images in search path) and portable_discover_attached() (for + * finding attached images). */ + + r = image_discover(IMAGE_PORTABLE, images); + if (r < 0) + return r; + + HASHMAP_FOREACH(image, images, i) + (void) manager_image_cache_add(m, image); + + return 0; +} diff --git a/src/portable/portabled-image.h b/src/portable/portabled-image.h new file mode 100644 index 00000000..26ce2f6b --- /dev/null +++ b/src/portable/portabled-image.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "hashmap.h" +#include "machine-image.h" +#include "portabled.h" + +Image *manager_image_cache_get(Manager *m, const char *name_or_path); + +int manager_image_cache_add(Manager *m, Image *image); + +int manager_image_cache_discover(Manager *m, Hashmap *images, sd_bus_error *error); diff --git a/src/portable/portabled-operation.c b/src/portable/portabled-operation.c new file mode 100644 index 00000000..305c96ca --- /dev/null +++ b/src/portable/portabled-operation.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "fd-util.h" +#include "portabled-operation.h" +#include "process-util.h" + +static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + Operation *o = userdata; + int r; + + assert(o); + assert(si); + + log_debug("Operating " PID_FMT " is now complete with code=%s status=%i", + o->pid, + sigchld_code_to_string(si->si_code), si->si_status); + + o->pid = 0; + + if (si->si_code != CLD_EXITED) { + r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally."); + goto fail; + } + + if (si->si_status == EXIT_SUCCESS) + r = 0; + else if (read(o->errno_fd, &r, sizeof(r)) != sizeof(r)) { /* Try to acquire error code for failed operation */ + r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child failed."); + goto fail; + } + + if (o->done) { + /* A completion routine is set for this operation, call it. */ + r = o->done(o, r, &error); + if (r < 0) { + if (!sd_bus_error_is_set(&error)) + sd_bus_error_set_errno(&error, r); + + goto fail; + } + + } else { + /* The default operation when done is to simply return an error on failure or an empty success + * message on success. */ + if (r < 0) { + sd_bus_error_set_errno(&error, r); + goto fail; + } + + r = sd_bus_reply_method_return(o->message, NULL); + if (r < 0) + log_error_errno(r, "Failed to reply to message: %m"); + } + + operation_free(o); + return 0; + +fail: + r = sd_bus_reply_method_error(o->message, &error); + if (r < 0) + log_error_errno(r, "Failed to reply to message: %m"); + + operation_free(o); + return 0; +} + +int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret) { + Operation *o; + int r; + + assert(manager); + assert(child > 1); + assert(message); + assert(errno_fd >= 0); + + o = new0(Operation, 1); + if (!o) + return -ENOMEM; + + o->extra_fd = -1; + + r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o); + if (r < 0) { + free(o); + return r; + } + + o->pid = child; + o->message = sd_bus_message_ref(message); + o->errno_fd = errno_fd; + + LIST_PREPEND(operations, manager->operations, o); + manager->n_operations++; + o->manager = manager; + + log_debug("Started new operation " PID_FMT ".", child); + + /* At this point we took ownership of both the child and the errno file descriptor! */ + + if (ret) + *ret = o; + + return 0; +} + +Operation *operation_free(Operation *o) { + if (!o) + return NULL; + + sd_event_source_unref(o->event_source); + + safe_close(o->errno_fd); + safe_close(o->extra_fd); + + if (o->pid > 1) + (void) sigkill_wait(o->pid); + + sd_bus_message_unref(o->message); + + if (o->manager) { + LIST_REMOVE(operations, o->manager->operations, o); + o->manager->n_operations--; + } + + return mfree(o); +} diff --git a/src/portable/portabled-operation.h b/src/portable/portabled-operation.h new file mode 100644 index 00000000..701f399b --- /dev/null +++ b/src/portable/portabled-operation.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" +#include "sd-event.h" + +#include "list.h" + +typedef struct Operation Operation; + +#include "portabled.h" + +#define OPERATIONS_MAX 64 + +struct Operation { + Manager *manager; + pid_t pid; + sd_bus_message *message; + int errno_fd; + int extra_fd; + sd_event_source *event_source; + int (*done)(Operation *o, int ret, sd_bus_error *error); + LIST_FIELDS(Operation, operations); +}; + +int operation_new(Manager *manager, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret); +Operation *operation_free(Operation *o); diff --git a/src/portable/portabled.c b/src/portable/portabled.c new file mode 100644 index 00000000..75b76926 --- /dev/null +++ b/src/portable/portabled.c @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "bus-polkit.h" +#include "def.h" +#include "main-func.h" +#include "portabled-bus.h" +#include "portabled-image-bus.h" +#include "portabled.h" +#include "process-util.h" +#include "signal-util.h" + +static Manager* manager_unref(Manager *m); +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref); + +static int manager_new(Manager **ret) { + _cleanup_(manager_unrefp) Manager *m = NULL; + int r; + + assert(ret); + + m = new0(Manager, 1); + if (!m) + return -ENOMEM; + + r = sd_event_default(&m->event); + if (r < 0) + return r; + + r = sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); + if (r < 0) + return r; + + r = sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); + if (r < 0) + return r; + + (void) sd_event_set_watchdog(m->event, true); + + *ret = TAKE_PTR(m); + return 0; +} + +static Manager* manager_unref(Manager *m) { + assert(m); + + hashmap_free(m->image_cache); + + sd_event_source_unref(m->image_cache_defer_event); + + bus_verify_polkit_async_registry_free(m->polkit_registry); + + sd_bus_flush_close_unref(m->bus); + sd_event_unref(m->event); + + return mfree(m); +} + +static int manager_connect_bus(Manager *m) { + int r; + + assert(m); + assert(!m->bus); + + r = sd_bus_default_system(&m->bus); + if (r < 0) + return log_error_errno(r, "Failed to connect to system bus: %m"); + + r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/portable1", "org.freedesktop.portable1.Manager", manager_vtable, m); + if (r < 0) + return log_error_errno(r, "Failed to add manager object vtable: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/portable1/image", "org.freedesktop.portable1.Image", image_vtable, bus_image_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to add image object vtable: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/portable1/image", bus_image_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to add image enumerator: %m"); + + r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.portable1", 0, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + r = sd_bus_attach_event(m->bus, m->event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + (void) sd_bus_set_exit_on_disconnect(m->bus, true); + + return 0; +} + +static int manager_startup(Manager *m) { + int r; + + assert(m); + + r = manager_connect_bus(m); + if (r < 0) + return r; + + return 0; +} + +static bool check_idle(void *userdata) { + Manager *m = userdata; + + return !m->operations; +} + +static int manager_run(Manager *m) { + assert(m); + + return bus_event_loop_with_idle( + m->event, + m->bus, + "org.freedesktop.portable1", + DEFAULT_EXIT_USEC, + check_idle, m); +} + +static int run(int argc, char *argv[]) { + _cleanup_(manager_unrefp) Manager *m = NULL; + int r; + + log_setup_service(); + + umask(0022); + + if (argc != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, -1) >= 0); + + r = manager_new(&m); + if (r < 0) + return log_error_errno(r, "Failed to allocate manager object: %m"); + + r = manager_startup(m); + if (r < 0) + return log_error_errno(r, "Failed to fully start up daemon: %m"); + + log_debug("systemd-portabled running as pid " PID_FMT, getpid_cached()); + sd_notify(false, + "READY=1\n" + "STATUS=Processing requests..."); + + r = manager_run(m); + + (void) sd_notify(false, + "STOPPING=1\n" + "STATUS=Shutting down..."); + log_debug("systemd-portabled stopped as pid " PID_FMT, getpid_cached()); + return r; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/portable/portabled.h b/src/portable/portabled.h new file mode 100644 index 00000000..00461edf --- /dev/null +++ b/src/portable/portabled.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "sd-event.h" + +#include "hashmap.h" +#include "list.h" + +typedef struct Manager Manager; + +#include "portabled-operation.h" + +struct Manager { + sd_event *event; + sd_bus *bus; + + Hashmap *polkit_registry; + + Hashmap *image_cache; + sd_event_source *image_cache_defer_event; + + LIST_HEAD(Operation, operations); + unsigned n_operations; +}; diff --git a/src/portable/profile/default/service.conf b/src/portable/profile/default/service.conf new file mode 100644 index 00000000..792be502 --- /dev/null +++ b/src/portable/profile/default/service.conf @@ -0,0 +1,32 @@ +# The "default" security profile for services, i.e. a number of useful restrictions + +[Service] +MountAPIVFS=yes +TemporaryFileSystem=/run +BindReadOnlyPaths=/run/systemd/notify +BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout +BindReadOnlyPaths=/etc/machine-id +BindReadOnlyPaths=/etc/resolv.conf +BindReadOnlyPaths=/run/dbus/system_bus_socket +DynamicUser=yes +RemoveIPC=yes +CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER \ + CAP_FSETID CAP_IPC_LOCK CAP_IPC_OWNER CAP_KILL CAP_MKNOD CAP_NET_ADMIN \ + CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_SETGID CAP_SETPCAP \ + CAP_SETUID CAP_SYS_ADMIN CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_RESOURCE +PrivateTmp=yes +PrivateDevices=yes +PrivateUsers=yes +ProtectSystem=strict +ProtectHome=yes +ProtectKernelTunables=yes +ProtectKernelModules=yes +ProtectControlGroups=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 +LockPersonality=yes +MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictNamespaces=yes +SystemCallFilter=@system-service +SystemCallErrorNumber=EPERM +SystemCallArchitectures=native diff --git a/src/portable/profile/nonetwork/service.conf b/src/portable/profile/nonetwork/service.conf new file mode 100644 index 00000000..c81cebe0 --- /dev/null +++ b/src/portable/profile/nonetwork/service.conf @@ -0,0 +1,32 @@ +# The "nonetwork" security profile for services, i.e. like "default" but without networking + +[Service] +MountAPIVFS=yes +TemporaryFileSystem=/run +BindReadOnlyPaths=/run/systemd/notify +BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout +BindReadOnlyPaths=/etc/machine-id +BindReadOnlyPaths=/run/dbus/system_bus_socket +DynamicUser=yes +RemoveIPC=yes +CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER \ + CAP_FSETID CAP_IPC_LOCK CAP_IPC_OWNER CAP_KILL CAP_MKNOD CAP_SETGID CAP_SETPCAP \ + CAP_SETUID CAP_SYS_ADMIN CAP_SYS_CHROOT CAP_SYS_NICE CAP_SYS_RESOURCE +PrivateTmp=yes +PrivateDevices=yes +PrivateUsers=yes +ProtectSystem=strict +ProtectHome=yes +ProtectKernelTunables=yes +ProtectKernelModules=yes +ProtectControlGroups=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK +LockPersonality=yes +MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictNamespaces=yes +SystemCallFilter=@system-service +SystemCallErrorNumber=EPERM +SystemCallArchitectures=native +PrivateNetwork=yes +IPAddressDeny=any diff --git a/src/portable/profile/strict/service.conf b/src/portable/profile/strict/service.conf new file mode 100644 index 00000000..d10fb5a1 --- /dev/null +++ b/src/portable/profile/strict/service.conf @@ -0,0 +1,31 @@ +# The "strict" security profile for services, all options turned on + +[Service] +MountAPIVFS=yes +TemporaryFileSystem=/run +BindReadOnlyPaths=/run/systemd/notify +BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout +BindReadOnlyPaths=/etc/machine-id +DynamicUser=yes +RemoveIPC=yes +CapabilityBoundingSet= +PrivateTmp=yes +PrivateDevices=yes +PrivateUsers=yes +ProtectSystem=strict +ProtectHome=yes +ProtectKernelTunables=yes +ProtectKernelModules=yes +ProtectControlGroups=yes +RestrictAddressFamilies=AF_UNIX +LockPersonality=yes +NoNewPrivileges=yes +MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictNamespaces=yes +SystemCallFilter=@system-service +SystemCallErrorNumber=EPERM +SystemCallArchitectures=native +PrivateNetwork=yes +IPAddressDeny=any +TasksMax=4 diff --git a/src/portable/profile/trusted/service.conf b/src/portable/profile/trusted/service.conf new file mode 100644 index 00000000..9a6af70b --- /dev/null +++ b/src/portable/profile/trusted/service.conf @@ -0,0 +1,7 @@ +# The "trusted" profile for services, i.e. no restrictions are applied + +[Service] +MountAPIVFS=yes +BindPaths=/run +BindReadOnlyPaths=/etc/machine-id +BindReadOnlyPaths=/etc/resolv.conf diff --git a/src/pstore/meson.build b/src/pstore/meson.build new file mode 100644 index 00000000..adbac24b --- /dev/null +++ b/src/pstore/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +systemd_pstore_sources = files(''' + pstore.c +'''.split()) + +if conf.get('ENABLE_PSTORE') == 1 + install_data('pstore.conf', + install_dir : pkgsysconfdir) +endif diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c new file mode 100644 index 00000000..5c812b5d --- /dev/null +++ b/src/pstore/pstore.c @@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +/* Copyright © 2019 Oracle and/or its affiliates. */ + +/* Generally speaking, the pstore contains a small number of files + * that in turn contain a small amount of data. */ +#include +#include +#include +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-journal.h" +#include "sd-login.h" +#include "sd-messages.h" + +#include "acl-util.h" +#include "alloc-util.h" +#include "capability-util.h" +#include "cgroup-util.h" +#include "compress.h" +#include "conf-parser.h" +#include "copy.h" +#include "dirent-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "io-util.h" +#include "journal-importer.h" +#include "log.h" +#include "macro.h" +#include "main-func.h" +#include "mkdir.h" +#include "parse-util.h" +#include "process-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "special.h" +#include "sort-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "user-util.h" +#include "util.h" + +/* Command line argument handling */ +typedef enum PStoreStorage { + PSTORE_STORAGE_NONE, + PSTORE_STORAGE_EXTERNAL, + PSTORE_STORAGE_JOURNAL, + _PSTORE_STORAGE_MAX, + _PSTORE_STORAGE_INVALID = -1 +} PStoreStorage; + +static const char* const pstore_storage_table[_PSTORE_STORAGE_MAX] = { + [PSTORE_STORAGE_NONE] = "none", + [PSTORE_STORAGE_EXTERNAL] = "external", + [PSTORE_STORAGE_JOURNAL] = "journal", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP(pstore_storage, PStoreStorage); +static DEFINE_CONFIG_PARSE_ENUM(config_parse_pstore_storage, pstore_storage, PStoreStorage, "Failed to parse storage setting"); + +static PStoreStorage arg_storage = PSTORE_STORAGE_EXTERNAL; + +static bool arg_unlink = true; +static const char *arg_sourcedir = "/sys/fs/pstore"; +static const char *arg_archivedir = "/var/lib/systemd/pstore"; + +static int parse_config(void) { + static const ConfigTableItem items[] = { + { "PStore", "Unlink", config_parse_bool, 0, &arg_unlink }, + { "PStore", "Storage", config_parse_pstore_storage, 0, &arg_storage }, + {} + }; + + return config_parse_many_nulstr(PKGSYSCONFDIR "/pstore.conf", + CONF_PATHS_NULSTR("systemd/pstore.conf.d"), + "PStore\0", + config_item_table_lookup, items, + CONFIG_PARSE_WARN, NULL); +} + +/* File list handling - PStoreEntry is the struct and + * and PStoreEntry is the type that contains all info + * about a pstore entry. */ +typedef struct PStoreEntry { + struct dirent dirent; + bool is_binary; + bool handled; + char *content; + size_t content_size; +} PStoreEntry; + +typedef struct PStoreList { + PStoreEntry *entries; + size_t n_entries; + size_t n_entries_allocated; +} PStoreList; + +static void pstore_entries_reset(PStoreList *list) { + for (size_t i = 0; i < list->n_entries; i++) + free(list->entries[i].content); + free(list->entries); + list->n_entries = 0; +} + +static int compare_pstore_entries(const void *_a, const void *_b) { + PStoreEntry *a = (PStoreEntry *)_a, *b = (PStoreEntry *)_b; + return strcmp(a->dirent.d_name, b->dirent.d_name); +} + +static int move_file(PStoreEntry *pe, const char *subdir) { + _cleanup_free_ char *ifd_path = NULL, *ofd_path = NULL; + _cleanup_free_ void *field = NULL; + const char *suffix, *message; + struct iovec iovec[2]; + int n_iovec = 0, r; + + if (pe->handled) + return 0; + + ifd_path = path_join(arg_sourcedir, pe->dirent.d_name); + if (!ifd_path) + return log_oom(); + + ofd_path = path_join(arg_archivedir, subdir, pe->dirent.d_name); + if (!ofd_path) + return log_oom(); + + /* Always log to the journal */ + suffix = arg_storage == PSTORE_STORAGE_EXTERNAL ? strjoina(" moved to ", ofd_path) : (char *)"."; + message = strjoina("MESSAGE=PStore ", pe->dirent.d_name, suffix); + iovec[n_iovec++] = IOVEC_MAKE_STRING(message); + + if (pe->content_size > 0) { + size_t field_size; + + field_size = strlen("FILE=") + pe->content_size; + field = malloc(field_size); + if (!field) + return log_oom(); + memcpy(stpcpy(field, "FILE="), pe->content, pe->content_size); + iovec[n_iovec++] = IOVEC_MAKE(field, field_size); + } + + r = sd_journal_sendv(iovec, n_iovec); + if (r < 0) + return log_error_errno(r, "Failed to log pstore entry: %m"); + + if (arg_storage == PSTORE_STORAGE_EXTERNAL) { + /* Move file from pstore to external storage */ + r = mkdir_parents(ofd_path, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create directory %s: %m", ofd_path); + r = copy_file_atomic(ifd_path, ofd_path, 0600, 0, 0, COPY_REPLACE); + if (r < 0) + return log_error_errno(r, "Failed to copy_file_atomic: %s to %s", ifd_path, ofd_path); + } + + /* If file copied properly, remove it from pstore */ + if (arg_unlink) + (void) unlink(ifd_path); + + pe->handled = true; + + return 0; +} + +static int write_dmesg(const char *dmesg, size_t size, const char *id) { + _cleanup_(unlink_and_freep) char *tmp_path = NULL; + _cleanup_free_ char *ofd_path = NULL; + _cleanup_close_ int ofd = -1; + ssize_t wr; + int r; + + if (size == 0) + return 0; + + assert(dmesg); + + ofd_path = path_join(arg_archivedir, id, "dmesg.txt"); + if (!ofd_path) + return log_oom(); + + ofd = open_tmpfile_linkable(ofd_path, O_CLOEXEC|O_CREAT|O_TRUNC|O_WRONLY, &tmp_path); + if (ofd < 0) + return log_error_errno(ofd, "Failed to open temporary file %s: %m", ofd_path); + wr = write(ofd, dmesg, size); + if (wr < 0) + return log_error_errno(errno, "Failed to store dmesg to %s: %m", ofd_path); + if (wr != (ssize_t)size) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Failed to store dmesg to %s. %zu bytes are lost.", ofd_path, size - wr); + r = link_tmpfile(ofd, tmp_path, ofd_path); + if (r < 0) + return log_error_errno(r, "Failed to write temporary file %s: %m", ofd_path); + tmp_path = mfree(tmp_path); + + return 0; +} + +static void process_dmesg_files(PStoreList *list) { + /* Move files, reconstruct dmesg.txt */ + _cleanup_free_ char *dmesg = NULL, *dmesg_id = NULL; + size_t dmesg_size = 0, dmesg_allocated = 0; + bool dmesg_bad = false; + PStoreEntry *pe; + + /* Handle each dmesg file: files processed in reverse + * order so as to properly reconstruct original dmesg */ + for (size_t n = list->n_entries; n > 0; n--) { + bool move_file_and_continue = false; + _cleanup_free_ char *pe_id = NULL; + char *p; + size_t plen; + + pe = &list->entries[n-1]; + + if (pe->handled) + continue; + if (!startswith(pe->dirent.d_name, "dmesg-")) + continue; + + if (endswith(pe->dirent.d_name, ".enc.z")) /* indicates a problem */ + move_file_and_continue = true; + p = strrchr(pe->dirent.d_name, '-'); + if (!p) + move_file_and_continue = true; + + if (move_file_and_continue) { + /* A dmesg file on which we do NO additional processing */ + (void) move_file(pe, NULL); + continue; + } + + /* See if this file is one of a related group of files + * in order to reconstruct dmesg */ + + /* When dmesg is written into pstore, it is done so in + * small chunks, whatever the exchange buffer size is + * with the underlying pstore backend (ie. EFI may be + * ~2KiB), which means an example pstore with approximately + * 64KB of storage may have up to roughly 32 dmesg files + * that could be related, depending upon the size of the + * original dmesg. + * + * Here we look at the dmesg filename and try to discern + * if files are part of a related group, meaning the same + * original dmesg. + * + * The two known pstore backends are EFI and ERST. These + * backends store data in the Common Platform Error + * Record, CPER, format. The dmesg- filename contains the + * CPER record id, a 64bit number (in decimal notation). + * In Linux, the record id is encoded with two digits for + * the dmesg part (chunk) number and 3 digits for the + * count number. So allowing an additional digit to + * compensate for advancing time, this code ignores the + * last six digits of the filename in determining the + * record id. + * + * For the EFI backend, the record id encodes an id in the + * upper 32 bits, and a timestamp in the lower 32-bits. + * So ignoring the least significant 6 digits has proven + * to generally identify related dmesg entries. */ +#define PSTORE_FILENAME_IGNORE 6 + + /* determine common portion of record id */ + ++p; /* move beyond dmesg- */ + plen = strlen(p); + if (plen > PSTORE_FILENAME_IGNORE) { + pe_id = memdup_suffix0(p, plen - PSTORE_FILENAME_IGNORE); + if (!pe_id) { + log_oom(); + return; + } + } else + pe_id = mfree(pe_id); + + /* Now move file from pstore to archive storage */ + move_file(pe, pe_id); + + if (dmesg_bad) + continue; + + /* If the current record id is NOT the same as the + * previous record id, then start a new dmesg.txt file */ + if (!streq_ptr(pe_id, dmesg_id)) { + /* Encountered a new dmesg group, close out old one, open new one */ + (void) write_dmesg(dmesg, dmesg_size, dmesg_id); + dmesg_size = 0; + + /* now point dmesg_id to storage of pe_id */ + free_and_replace(dmesg_id, pe_id); + } + + /* Reconstruction of dmesg is done as a useful courtesy: do not fail, but don't write garbled + * output either. */ + size_t needed = strlen(pe->dirent.d_name) + strlen(":\n") + pe->content_size + 1; + if (!GREEDY_REALLOC(dmesg, dmesg_allocated, dmesg_size + needed)) { + log_warning_errno(ENOMEM, "Failed to write dmesg file: %m"); + dmesg_bad = true; + continue; + } + + dmesg_size += sprintf(dmesg + dmesg_size, "%s:\n", pe->dirent.d_name); + if (pe->content) { + memcpy(dmesg + dmesg_size, pe->content, pe->content_size); + dmesg_size += pe->content_size; + } + + pe_id = mfree(pe_id); + } + + if (!dmesg_bad) + (void) write_dmesg(dmesg, dmesg_size, dmesg_id); +} + +static int list_files(PStoreList *list, const char *sourcepath) { + _cleanup_(closedirp) DIR *dirp = NULL; + struct dirent *de; + int r; + + dirp = opendir(sourcepath); + if (!dirp) + return log_error_errno(errno, "Failed to opendir %s: %m", sourcepath); + + FOREACH_DIRENT(de, dirp, return log_error_errno(errno, "Failed to iterate through %s: %m", sourcepath)) { + _cleanup_free_ char *ifd_path = NULL; + + ifd_path = path_join(sourcepath, de->d_name); + if (!ifd_path) + return log_oom(); + + _cleanup_free_ char *buf = NULL; + size_t buf_size; + + /* Now read contents of pstore file */ + r = read_full_file(ifd_path, &buf, &buf_size); + if (r < 0) { + log_warning_errno(r, "Failed to read file %s, skipping: %m", ifd_path); + continue; + } + + if (!GREEDY_REALLOC(list->entries, list->n_entries_allocated, list->n_entries + 1)) + return log_oom(); + + list->entries[list->n_entries++] = (PStoreEntry) { + .dirent = *de, + .content = TAKE_PTR(buf), + .content_size = buf_size, + .is_binary = true, + .handled = false, + }; + } + + return 0; +} + +static int run(int argc, char *argv[]) { + _cleanup_(pstore_entries_reset) PStoreList list = {}; + int r; + + log_setup_service(); + + if (argc == 3) { + arg_sourcedir = argv[1]; + arg_archivedir = argv[2]; + } else if (argc > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program takes zero or two arguments."); + + /* Ignore all parse errors */ + (void) parse_config(); + + log_debug("Selected storage: %s.", pstore_storage_to_string(arg_storage)); + log_debug("Selected unlink: %s.", yes_no(arg_unlink)); + + if (arg_storage == PSTORE_STORAGE_NONE) + /* Do nothing, intentionally, leaving pstore untouched */ + return 0; + + /* Obtain list of files in pstore */ + r = list_files(&list, arg_sourcedir); + if (r < 0) + return r; + + /* Handle each pstore file */ + /* Sort files lexigraphically ascending, generally needed by all */ + qsort_safe(list.entries, list.n_entries, sizeof(PStoreEntry), compare_pstore_entries); + + /* Process known file types */ + process_dmesg_files(&list); + + /* Move left over files out of pstore */ + for (size_t n = 0; n < list.n_entries; n++) + move_file(&list.entries[n], NULL); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/pstore/pstore.conf b/src/pstore/pstore.conf new file mode 100644 index 00000000..93a8b670 --- /dev/null +++ b/src/pstore/pstore.conf @@ -0,0 +1,16 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See pstore.conf(5) for details. + +[PStore] +#Storage=external +#Unlink=yes diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c new file mode 100644 index 00000000..4e83fc83 --- /dev/null +++ b/src/quotacheck/quotacheck.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "main-func.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "signal-util.h" +#include "string-util.h" +#include "util.h" + +static bool arg_skip = false; +static bool arg_force = false; + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + + if (streq(key, "quotacheck.mode")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (streq(value, "auto")) + arg_force = arg_skip = false; + else if (streq(value, "force")) + arg_force = true; + else if (streq(value, "skip")) + arg_skip = true; + else + log_warning("Invalid quotacheck.mode= parameter '%s'. Ignoring.", value); + } + +#if HAVE_SYSV_COMPAT + else if (streq(key, "forcequotacheck") && !value) { + log_warning("Please use 'quotacheck.mode=force' rather than 'forcequotacheck' on the kernel command line."); + arg_force = true; + } +#endif + + return 0; +} + +static void test_files(void) { + +#if HAVE_SYSV_COMPAT + if (access("/forcequotacheck", F_OK) >= 0) { + log_error("Please pass 'quotacheck.mode=force' on the kernel command line rather than creating /forcequotacheck on the root file system."); + arg_force = true; + } +#endif +} + +static int run(int argc, char *argv[]) { + int r; + + log_setup_service(); + + if (argc > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program takes no arguments."); + + umask(0022); + + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + test_files(); + + if (!arg_force) { + if (arg_skip) + return 0; + + if (access("/run/systemd/quotacheck", F_OK) < 0) + return 0; + } + + r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_WAIT|FORK_LOG, NULL); + if (r < 0) + return r; + if (r == 0) { + static const char * const cmdline[] = { + QUOTACHECK, + "-anug", + NULL + }; + + /* Child */ + + execv(cmdline[0], (char**) cmdline); + _exit(EXIT_FAILURE); /* Operational error */ + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/random-seed/random-seed.c b/src/random-seed/random-seed.c new file mode 100644 index 00000000..2fcbcb28 --- /dev/null +++ b/src/random-seed/random-seed.c @@ -0,0 +1,314 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#if USE_SYS_RANDOM_H +# include +#endif +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "io-util.h" +#include "log.h" +#include "main-func.h" +#include "missing_syscall.h" +#include "mkdir.h" +#include "parse-util.h" +#include "random-util.h" +#include "string-util.h" +#include "util.h" +#include "xattr-util.h" + +typedef enum CreditEntropy { + CREDIT_ENTROPY_NO_WAY, + CREDIT_ENTROPY_YES_PLEASE, + CREDIT_ENTROPY_YES_FORCED, +} CreditEntropy; + +static CreditEntropy may_credit(int seed_fd) { + _cleanup_free_ char *creditable = NULL; + const char *e; + int r; + + assert(seed_fd >= 0); + + e = getenv("SYSTEMD_RANDOM_SEED_CREDIT"); + if (!e) { + log_debug("$SYSTEMD_RANDOM_SEED_CREDIT is not set, not crediting entropy."); + return CREDIT_ENTROPY_NO_WAY; + } + if (streq(e, "force")) { + log_debug("$SYSTEMD_RANDOM_SEED_CREDIT is set to 'force', crediting entropy."); + return CREDIT_ENTROPY_YES_FORCED; + } + + r = parse_boolean(e); + if (r <= 0) { + if (r < 0) + log_warning_errno(r, "Failed to parse $SYSTEMD_RANDOM_SEED_CREDIT, not crediting entropy: %m"); + else + log_debug("Crediting entropy is turned off via $SYSTEMD_RANDOM_SEED_CREDIT, not crediting entropy."); + + return CREDIT_ENTROPY_NO_WAY; + } + + /* Determine if the file is marked as creditable */ + r = fgetxattr_malloc(seed_fd, "user.random-seed-creditable", &creditable); + if (r < 0) { + if (IN_SET(r, -ENODATA, -ENOSYS, -EOPNOTSUPP)) + log_debug_errno(r, "Seed file is not marked as creditable, not crediting."); + else + log_warning_errno(r, "Failed to read extended attribute, ignoring: %m"); + + return CREDIT_ENTROPY_NO_WAY; + } + + r = parse_boolean(creditable); + if (r <= 0) { + if (r < 0) + log_warning_errno(r, "Failed to parse user.random-seed-creditable extended attribute, ignoring: %s", creditable); + else + log_debug("Seed file is marked as not creditable, not crediting."); + + return CREDIT_ENTROPY_NO_WAY; + } + + /* Don't credit the random seed if we are in first-boot mode, because we are supposed to start from + * scratch. This is a safety precaution for cases where we people ship "golden" images with empty + * /etc but populated /var that contains a random seed. */ + if (access("/run/systemd/first-boot", F_OK) < 0) { + + if (errno != ENOENT) { + log_warning_errno(errno, "Failed to check whether we are in first-boot mode, not crediting entropy: %m"); + return CREDIT_ENTROPY_NO_WAY; + } + + /* If ENOENT all is good, we are not in first-boot mode. */ + } else { + log_debug("Not crediting entropy, since booted in first-boot mode."); + return CREDIT_ENTROPY_NO_WAY; + } + + return CREDIT_ENTROPY_YES_PLEASE; +} + +static int run(int argc, char *argv[]) { + _cleanup_close_ int seed_fd = -1, random_fd = -1; + bool read_seed_file, write_seed_file, synchronous; + _cleanup_free_ void* buf = NULL; + size_t buf_size; + struct stat st; + ssize_t k; + int r; + + log_setup_service(); + + if (argc != 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program requires one argument."); + + umask(0022); + + buf_size = random_pool_size(); + + r = mkdir_parents(RANDOM_SEED, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m"); + + /* When we load the seed we read it and write it to the device and then immediately update the saved seed with + * new data, to make sure the next boot gets seeded differently. */ + + if (streq(argv[1], "load")) { + + seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600); + if (seed_fd < 0) { + int open_rw_error = -errno; + + write_seed_file = false; + + seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (seed_fd < 0) { + bool missing = errno == ENOENT; + + log_full_errno(missing ? LOG_DEBUG : LOG_ERR, + open_rw_error, "Failed to open " RANDOM_SEED " for writing: %m"); + r = log_full_errno(missing ? LOG_DEBUG : LOG_ERR, + errno, "Failed to open " RANDOM_SEED " for reading: %m"); + return missing ? 0 : r; + } + } else + write_seed_file = true; + + random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600); + if (random_fd < 0) + return log_error_errno(errno, "Failed to open /dev/urandom: %m"); + + read_seed_file = true; + synchronous = true; /* make this invocation a synchronous barrier for random pool initialization */ + + } else if (streq(argv[1], "save")) { + + random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (random_fd < 0) + return log_error_errno(errno, "Failed to open /dev/urandom: %m"); + + seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600); + if (seed_fd < 0) + return log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m"); + + read_seed_file = false; + write_seed_file = true; + synchronous = false; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown verb '%s'.", argv[1]); + + if (fstat(seed_fd, &st) < 0) + return log_error_errno(errno, "Failed to stat() seed file " RANDOM_SEED ": %m"); + + /* If the seed file is larger than what we expect, then honour the existing size and save/restore as much as it says */ + if ((uint64_t) st.st_size > buf_size) + buf_size = MIN(st.st_size, RANDOM_POOL_SIZE_MAX); + + buf = malloc(buf_size); + if (!buf) + return log_oom(); + + if (read_seed_file) { + sd_id128_t mid; + + /* First, let's write the machine ID into /dev/urandom, not crediting entropy. Why? As an + * extra protection against "golden images" that are put together sloppily, i.e. images which + * are duplicated on multiple systems but where the random seed file is not properly + * reset. Frequently the machine ID is properly reset on those systems however (simply + * because it's easier to notice, if it isn't due to address clashes and so on, while random + * seed equivalence is generally not noticed easily), hence let's simply write the machined + * ID into the random pool too. */ + r = sd_id128_get_machine(&mid); + if (r < 0) + log_debug_errno(r, "Failed to get machine ID, ignoring: %m"); + else { + r = loop_write(random_fd, &mid, sizeof(mid), false); + if (r < 0) + log_debug_errno(r, "Failed to write machine ID to /dev/urandom, ignoring: %m"); + } + + k = loop_read(seed_fd, buf, buf_size, false); + if (k < 0) + log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m"); + else if (k == 0) + log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding."); + else { + CreditEntropy lets_credit; + + (void) lseek(seed_fd, 0, SEEK_SET); + + lets_credit = may_credit(seed_fd); + + /* Before we credit or use the entropy, let's make sure to securely drop the + * creditable xattr from the file, so that we never credit the same random seed + * again. Note that further down we'll write a new seed again, and likely mark it as + * credible again, hence this is just paranoia to close the short time window between + * the time we upload the random seed into the kernel and download the new one from + * it. */ + + if (fremovexattr(seed_fd, "user.random-seed-creditable") < 0) { + if (!IN_SET(errno, ENODATA, ENOSYS, EOPNOTSUPP)) + log_warning_errno(errno, "Failed to remove extended attribute, ignoring: %m"); + + /* Otherwise, there was no creditable flag set, which is OK. */ + } else { + r = fsync_full(seed_fd); + if (r < 0) { + log_warning_errno(r, "Failed to synchronize seed to disk, not crediting entropy: %m"); + + if (lets_credit == CREDIT_ENTROPY_YES_PLEASE) + lets_credit = CREDIT_ENTROPY_NO_WAY; + } + } + + if (IN_SET(lets_credit, CREDIT_ENTROPY_YES_PLEASE, CREDIT_ENTROPY_YES_FORCED)) { + _cleanup_free_ struct rand_pool_info *info = NULL; + + info = malloc(offsetof(struct rand_pool_info, buf) + k); + if (!info) + return log_oom(); + + info->entropy_count = k * 8; + info->buf_size = k; + memcpy(info->buf, buf, k); + + if (ioctl(random_fd, RNDADDENTROPY, info) < 0) + return log_warning_errno(errno, "Failed to credit entropy, ignoring: %m"); + } else { + r = loop_write(random_fd, buf, (size_t) k, false); + if (r < 0) + log_error_errno(r, "Failed to write seed to /dev/urandom: %m"); + } + } + } + + if (write_seed_file) { + bool getrandom_worked = false; + + /* This is just a safety measure. Given that we are root and most likely created the file + * ourselves the mode and owner should be correct anyway. */ + r = fchmod_and_chown(seed_fd, 0600, 0, 0); + if (r < 0) + return log_error_errno(r, "Failed to adjust seed file ownership and access mode."); + + /* Let's make this whole job asynchronous, i.e. let's make ourselves a barrier for + * proper initialization of the random pool. */ + k = getrandom(buf, buf_size, GRND_NONBLOCK); + if (k < 0 && errno == EAGAIN && synchronous) { + log_notice("Kernel entropy pool is not initialized yet, waiting until it is."); + k = getrandom(buf, buf_size, 0); /* retry synchronously */ + } + if (k < 0) + log_debug_errno(errno, "Failed to read random data with getrandom(), falling back to /dev/urandom: %m"); + else if ((size_t) k < buf_size) + log_debug("Short read from getrandom(), falling back to /dev/urandom: %m"); + else + getrandom_worked = true; + + if (!getrandom_worked) { + /* Retry with classic /dev/urandom */ + k = loop_read(random_fd, buf, buf_size, false); + if (k < 0) + return log_error_errno(k, "Failed to read new seed from /dev/urandom: %m"); + if (k == 0) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Got EOF while reading from /dev/urandom."); + } + + r = loop_write(seed_fd, buf, (size_t) k, false); + if (r < 0) + return log_error_errno(r, "Failed to write new random seed file: %m"); + + if (ftruncate(seed_fd, k) < 0) + return log_error_errno(r, "Failed to truncate random seed file: %m"); + + r = fsync_full(seed_fd); + if (r < 0) + return log_error_errno(r, "Failed to synchronize seed file: %m"); + + /* If we got this random seed data from getrandom() the data is suitable for crediting + * entropy later on. Let's keep that in mind by setting an extended attribute. on the file */ + if (getrandom_worked) + if (fsetxattr(seed_fd, "user.random-seed-creditable", "1", 1, 0) < 0) + log_full_errno(IN_SET(errno, ENOSYS, EOPNOTSUPP) ? LOG_DEBUG : LOG_WARNING, errno, + "Failed to mark seed file as creditable, ignoring: %m"); + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/rc-local-generator/rc-local-generator.c b/src/rc-local-generator/rc-local-generator.c new file mode 100644 index 00000000..908e6272 --- /dev/null +++ b/src/rc-local-generator/rc-local-generator.c @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "generator.h" +#include "log.h" +#include "mkdir.h" +#include "string-util.h" +#include "util.h" + +static const char *arg_dest = NULL; + +/* So you are reading this, and might wonder: why is this implemented as a generator rather than as a plain, statically + * enabled service that carries appropriate ConditionFileIsExecutable= lines? The answer is this: conditions bypass + * execution of a service's binary, but they have no influence on unit dependencies. Thus, a service that is + * conditioned out will still act as synchronization point in the dependency tree, and we'd rather not have that for + * these two legacy scripts. */ + +static int add_symlink(const char *service, const char *where) { + const char *from, *to; + + assert(service); + assert(where); + + from = strjoina(SYSTEM_DATA_UNIT_PATH "/", service); + to = strjoina(arg_dest, "/", where, ".wants/", service); + + (void) mkdir_parents_label(to, 0755); + + if (symlink(from, to) < 0) { + if (errno == EEXIST) + return 0; + + return log_error_errno(errno, "Failed to create symlink %s: %m", to); + } + + return 1; +} + +static int check_executable(const char *path) { + assert(path); + + if (access(path, X_OK) < 0) { + if (errno == ENOENT) + return log_debug_errno(errno, "%s does not exist, skipping.", path); + if (errno == EACCES) + return log_info_errno(errno, "%s is not marked executable, skipping.", path); + + return log_warning_errno(errno, "Couldn't determine if %s exists and is executable, skipping: %m", path); + } + + return 0; +} + +static int run(const char *dest, const char *dest_early, const char *dest_late) { + int r = 0, k = 0; + + assert_se(arg_dest = dest); + + if (check_executable(RC_LOCAL_SCRIPT_PATH_START) >= 0) { + log_debug("Automatically adding rc-local.service."); + + r = add_symlink("rc-local.service", "multi-user.target"); + } + + return r < 0 ? r : k; +} + +DEFINE_MAIN_GENERATOR_FUNCTION(run); diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c new file mode 100644 index 00000000..7386f705 --- /dev/null +++ b/src/remount-fs/remount-fs.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "env-util.h" +#include "exit-status.h" +#include "fstab-util.h" +#include "log.h" +#include "main-func.h" +#include "mount-setup.h" +#include "mount-util.h" +#include "path-util.h" +#include "process-util.h" +#include "signal-util.h" +#include "strv.h" +#include "util.h" + +/* Goes through /etc/fstab and remounts all API file systems, applying options that are in /etc/fstab that systemd + * might not have respected */ + +static int track_pid(Hashmap **h, const char *path, pid_t pid) { + _cleanup_free_ char *c = NULL; + int r; + + assert(h); + assert(path); + assert(pid_is_valid(pid)); + + r = hashmap_ensure_allocated(h, NULL); + if (r < 0) + return log_oom(); + + c = strdup(path); + if (!c) + return log_oom(); + + r = hashmap_put(*h, PID_TO_PTR(pid), c); + if (r < 0) + return log_oom(); + + TAKE_PTR(c); + return 0; +} + +static int do_remount(const char *path, bool force_rw, Hashmap **pids) { + pid_t pid; + int r; + + log_debug("Remounting %s...", path); + + r = safe_fork(force_rw ? "(remount-rw)" : "(remount)", + FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + /* Child */ + execv(MOUNT_PATH, + STRV_MAKE(MOUNT_PATH, + path, + "-o", + force_rw ? "remount,rw" : "remount")); + log_error_errno(errno, "Failed to execute " MOUNT_PATH ": %m"); + _exit(EXIT_FAILURE); + } + + /* Parent */ + return track_pid(pids, path, pid); +} + +static int run(int argc, char *argv[]) { + _cleanup_hashmap_free_free_ Hashmap *pids = NULL; + _cleanup_endmntent_ FILE *f = NULL; + bool has_root = false; + struct mntent* me; + int r; + + log_setup_service(); + + if (argc > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program takes no arguments."); + + umask(0022); + + f = setmntent(fstab_path(), "re"); + if (!f) { + if (errno != ENOENT) + return log_error_errno(errno, "Failed to open %s: %m", fstab_path()); + } else + while ((me = getmntent(f))) { + /* Remount the root fs, /usr, and all API VFSs */ + if (!mount_point_is_api(me->mnt_dir) && + !PATH_IN_SET(me->mnt_dir, "/", "/usr")) + continue; + + if (path_equal(me->mnt_dir, "/")) + has_root = true; + + r = do_remount(me->mnt_dir, false, &pids); + if (r < 0) + return r; + } + + if (!has_root) { + /* The $SYSTEMD_REMOUNT_ROOT_RW environment variable is set by systemd-gpt-auto-generator to tell us + * whether to remount things. We honour it only if there's no explicit line in /etc/fstab configured + * which takes precedence. */ + + r = getenv_bool("SYSTEMD_REMOUNT_ROOT_RW"); + if (r < 0 && r != -ENXIO) + log_warning_errno(r, "Failed to parse $SYSTEMD_REMOUNT_ROOT_RW, ignoring: %m"); + + if (r > 0) { + r = do_remount("/", true, &pids); + if (r < 0) + return r; + } + } + + r = 0; + while (!hashmap_isempty(pids)) { + _cleanup_free_ char *s = NULL; + siginfo_t si = {}; + + if (waitid(P_ALL, 0, &si, WEXITED) < 0) { + if (errno == EINTR) + continue; + + return log_error_errno(errno, "waitid() failed: %m"); + } + + s = hashmap_remove(pids, PID_TO_PTR(si.si_pid)); + if (s && + !is_clean_exit(si.si_code, si.si_status, EXIT_CLEAN_COMMAND, NULL)) { + if (si.si_code == CLD_EXITED) + log_error(MOUNT_PATH " for %s exited with exit status %i.", s, si.si_status); + else + log_error(MOUNT_PATH " for %s terminated by signal %s.", s, signal_to_string(si.si_status)); + + r = -ENOEXEC; + } + } + + return r; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/reply-password/reply-password.c b/src/reply-password/reply-password.c new file mode 100644 index 00000000..3a0eb5c4 --- /dev/null +++ b/src/reply-password/reply-password.c @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "main-func.h" +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "macro.h" +#include "memory-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "util.h" + +static int send_on_socket(int fd, const char *socket_name, const void *packet, size_t size) { + union sockaddr_union sa = {}; + int salen; + + assert(fd >= 0); + assert(socket_name); + assert(packet); + + salen = sockaddr_un_set_path(&sa.un, socket_name); + if (salen < 0) + return log_error_errno(salen, "Specified socket path for AF_UNIX socket invalid, refusing: %s", socket_name); + + if (sendto(fd, packet, size, MSG_NOSIGNAL, &sa.sa, salen) < 0) + return log_error_errno(errno, "Failed to send: %m"); + + return 0; +} + +static int run(int argc, char *argv[]) { + _cleanup_(erase_and_freep) char *packet = NULL; + _cleanup_close_ int fd = -1; + size_t length = 0; + int r; + + log_setup_service(); + + if (argc != 3) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong number of arguments."); + + if (streq(argv[1], "1")) { + _cleanup_(erase_and_freep) char *line = NULL; + + r = read_line(stdin, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read password: %m"); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Got EOF while reading password."); + + packet = strjoin("+", line); + if (!packet) + return log_oom(); + + length = 1 + strlen(line) + 1; + + } else if (streq(argv[1], "0")) { + packet = strdup("-"); + if (!packet) + return log_oom(); + + length = 1; + + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid first argument %s", argv[1]); + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return log_error_errno(errno, "socket() failed: %m"); + + return send_on_socket(fd, argv[2], packet, length); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/resolve/RFCs b/src/resolve/RFCs new file mode 100644 index 00000000..7190c16f --- /dev/null +++ b/src/resolve/RFCs @@ -0,0 +1,60 @@ +Y = Comprehensively Implemented, to the point appropriate for resolved +D = Comprehensively Implemented, by a dependency of resolved +! = Missing and something we might want to implement +~ = Needs no explicit support or doesn't apply +? = Is this relevant today? + = We are working on this + +Y https://tools.ietf.org/html/rfc1034 → DOMAIN NAMES - CONCEPTS AND FACILITIES +Y https://tools.ietf.org/html/rfc1035 → DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION +? https://tools.ietf.org/html/rfc1101 → DNS Encoding of Network Names and Other Types +Y https://tools.ietf.org/html/rfc1123 → Requirements for Internet Hosts — Application and Support +~ https://tools.ietf.org/html/rfc1464 → Using the Domain Name System To Store Arbitrary String Attributes +Y https://tools.ietf.org/html/rfc1536 → Common DNS Implementation Errors and Suggested Fixes +Y https://tools.ietf.org/html/rfc1876 → A Means for Expressing Location Information in the Domain Name System +Y https://tools.ietf.org/html/rfc2181 → Clarifications to the DNS Specification +Y https://tools.ietf.org/html/rfc2308 → Negative Caching of DNS Queries (DNS NCACHE) +Y https://tools.ietf.org/html/rfc2782 → A DNS RR for specifying the location of services (DNS SRV) +D https://tools.ietf.org/html/rfc3492 → Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA) +Y https://tools.ietf.org/html/rfc3596 → DNS Extensions to Support IP Version 6 +Y https://tools.ietf.org/html/rfc3597 → Handling of Unknown DNS Resource Record (RR) Types +Y https://tools.ietf.org/html/rfc4033 → DNS Security Introduction and Requirements +Y https://tools.ietf.org/html/rfc4034 → Resource Records for the DNS Security Extensions +Y https://tools.ietf.org/html/rfc4035 → Protocol Modifications for the DNS Security Extensions +! https://tools.ietf.org/html/rfc4183 → A Suggested Scheme for DNS Resolution of Networks and Gateways +Y https://tools.ietf.org/html/rfc4255 → Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints +Y https://tools.ietf.org/html/rfc4343 → Domain Name System (DNS) Case Insensitivity Clarification +~ https://tools.ietf.org/html/rfc4470 → Minimally Covering NSEC Records and DNSSEC On-line Signing +Y https://tools.ietf.org/html/rfc4501 → Domain Name System Uniform Resource Identifiers +Y https://tools.ietf.org/html/rfc4509 → Use of SHA-256 in DNSSEC Delegation Signer (DS) Resource Records (RRs) +~ https://tools.ietf.org/html/rfc4592 → The Role of Wildcards in the Domain Name System +~ https://tools.ietf.org/html/rfc4697 → Observed DNS Resolution Misbehavior +Y https://tools.ietf.org/html/rfc4795 → Link-Local Multicast Name Resolution (LLMNR) +Y https://tools.ietf.org/html/rfc5011 → Automated Updates of DNS Security (DNSSEC) Trust Anchors +Y https://tools.ietf.org/html/rfc5155 → DNS Security (DNSSEC) Hashed Authenticated Denial of Existence +Y https://tools.ietf.org/html/rfc5452 → Measures for Making DNS More Resilient against Forged Answers +Y https://tools.ietf.org/html/rfc5702 → Use of SHA-2 Algorithms with RSA in DNSKEY and RRSIG Resource Records for DNSSEC +Y https://tools.ietf.org/html/rfc5890 → Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework +Y https://tools.ietf.org/html/rfc5891 → Internationalized Domain Names in Applications (IDNA): Protocol +Y https://tools.ietf.org/html/rfc5966 → DNS Transport over TCP - Implementation Requirements +Y https://tools.ietf.org/html/rfc6303 → Locally Served DNS Zones +Y https://tools.ietf.org/html/rfc6604 → xNAME RCODE and Status Bits Clarification +Y https://tools.ietf.org/html/rfc6605 → Elliptic Curve Digital Signature Algorithm (DSA) for DNSSEC + https://tools.ietf.org/html/rfc6672 → DNAME Redirection in the DNS +! https://tools.ietf.org/html/rfc6731 → Improved Recursive DNS Server Selection for Multi-Interfaced Nodes +Y https://tools.ietf.org/html/rfc6761 → Special-Use Domain Names + https://tools.ietf.org/html/rfc6762 → Multicast DNS + https://tools.ietf.org/html/rfc6763 → DNS-Based Service Discovery +~ https://tools.ietf.org/html/rfc6781 → DNSSEC Operational Practices, Version 2 +Y https://tools.ietf.org/html/rfc6840 → Clarifications and Implementation Notes for DNS Security (DNSSEC) +Y https://tools.ietf.org/html/rfc6891 → Extension Mechanisms for DNS (EDNS(0)) +Y https://tools.ietf.org/html/rfc6944 → Applicability Statement: DNS Security (DNSSEC) DNSKEY Algorithm Implementation Status +Y https://tools.ietf.org/html/rfc6975 → Signaling Cryptographic Algorithm Understanding in DNS Security Extensions (DNSSEC) +Y https://tools.ietf.org/html/rfc7129 → Authenticated Denial of Existence in the DNS +Y https://tools.ietf.org/html/rfc7646 → Definition and Use of DNSSEC Negative Trust Anchors +~ https://tools.ietf.org/html/rfc7719 → DNS Terminology +Y https://tools.ietf.org/html/rfc8080 → Edwards-Curve Digital Security Algorithm (EdDSA) for DNSSEC + +Also relevant: + + https://www.iab.org/documents/correspondence-reports-documents/2013-2/iab-statement-dotless-domains-considered-harmful/ diff --git a/src/resolve/dns-type.c b/src/resolve/dns-type.c new file mode 100644 index 00000000..c96f60a0 --- /dev/null +++ b/src/resolve/dns-type.c @@ -0,0 +1,316 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "dns-type.h" +#include "parse-util.h" +#include "string-util.h" + +typedef const struct { + uint16_t type; + const char *name; +} dns_type; + +static const struct dns_type_name * +lookup_dns_type (register const char *str, register GPERF_LEN_TYPE len); + +#include "dns_type-from-name.h" +#include "dns_type-to-name.h" + +int dns_type_from_string(const char *s) { + const struct dns_type_name *sc; + + assert(s); + + sc = lookup_dns_type(s, strlen(s)); + if (sc) + return sc->id; + + s = startswith_no_case(s, "TYPE"); + if (s) { + unsigned x; + + if (safe_atou(s, &x) >= 0 && + x <= UINT16_MAX) + return (int) x; + } + + return _DNS_TYPE_INVALID; +} + +bool dns_type_is_pseudo(uint16_t type) { + + /* Checks whether the specified type is a "pseudo-type". What + * a "pseudo-type" precisely is, is defined only very weakly, + * but apparently entails all RR types that are not actually + * stored as RRs on the server and should hence also not be + * cached. We use this list primarily to validate NSEC type + * bitfields, and to verify what to cache. */ + + return IN_SET(type, + 0, /* A Pseudo RR type, according to RFC 2931 */ + DNS_TYPE_ANY, + DNS_TYPE_AXFR, + DNS_TYPE_IXFR, + DNS_TYPE_OPT, + DNS_TYPE_TSIG, + DNS_TYPE_TKEY + ); +} + +bool dns_class_is_pseudo(uint16_t class) { + return class == DNS_TYPE_ANY; +} + +bool dns_type_is_valid_query(uint16_t type) { + + /* The types valid as questions in packets */ + + return !IN_SET(type, + 0, + DNS_TYPE_OPT, + DNS_TYPE_TSIG, + DNS_TYPE_TKEY, + + /* RRSIG are technically valid as questions, but we refuse doing explicit queries for them, as + * they aren't really payload, but signatures for payload, and cannot be validated on their + * own. After all they are the signatures, and have no signatures of their own validating + * them. */ + DNS_TYPE_RRSIG); +} + +bool dns_type_is_zone_transer(uint16_t type) { + + /* Zone transfers, either normal or incremental */ + + return IN_SET(type, + DNS_TYPE_AXFR, + DNS_TYPE_IXFR); +} + +bool dns_type_is_valid_rr(uint16_t type) { + + /* The types valid as RR in packets (but not necessarily + * stored on servers). */ + + return !IN_SET(type, + DNS_TYPE_ANY, + DNS_TYPE_AXFR, + DNS_TYPE_IXFR); +} + +bool dns_class_is_valid_rr(uint16_t class) { + return class != DNS_CLASS_ANY; +} + +bool dns_type_may_redirect(uint16_t type) { + /* The following record types should never be redirected using + * CNAME/DNAME RRs. See + * . */ + + if (dns_type_is_pseudo(type)) + return false; + + return !IN_SET(type, + DNS_TYPE_CNAME, + DNS_TYPE_DNAME, + DNS_TYPE_NSEC3, + DNS_TYPE_NSEC, + DNS_TYPE_RRSIG, + DNS_TYPE_NXT, + DNS_TYPE_SIG, + DNS_TYPE_KEY); +} + +bool dns_type_may_wildcard(uint16_t type) { + + /* The following records may not be expanded from wildcard RRsets */ + + if (dns_type_is_pseudo(type)) + return false; + + return !IN_SET(type, + DNS_TYPE_NSEC3, + DNS_TYPE_SOA, + + /* Prohibited by https://tools.ietf.org/html/rfc4592#section-4.4 */ + DNS_TYPE_DNAME); +} + +bool dns_type_apex_only(uint16_t type) { + + /* Returns true for all RR types that may only appear signed in a zone apex */ + + return IN_SET(type, + DNS_TYPE_SOA, + DNS_TYPE_NS, /* this one can appear elsewhere, too, but not signed */ + DNS_TYPE_DNSKEY, + DNS_TYPE_NSEC3PARAM); +} + +bool dns_type_is_dnssec(uint16_t type) { + return IN_SET(type, + DNS_TYPE_DS, + DNS_TYPE_DNSKEY, + DNS_TYPE_RRSIG, + DNS_TYPE_NSEC, + DNS_TYPE_NSEC3, + DNS_TYPE_NSEC3PARAM); +} + +bool dns_type_is_obsolete(uint16_t type) { + return IN_SET(type, + /* Obsoleted by RFC 973 */ + DNS_TYPE_MD, + DNS_TYPE_MF, + DNS_TYPE_MAILA, + + /* Kinda obsoleted by RFC 2505 */ + DNS_TYPE_MB, + DNS_TYPE_MG, + DNS_TYPE_MR, + DNS_TYPE_MINFO, + DNS_TYPE_MAILB, + + /* RFC1127 kinda obsoleted this by recommending against its use */ + DNS_TYPE_WKS, + + /* Declared historical by RFC 6563 */ + DNS_TYPE_A6, + + /* Obsoleted by DNSSEC-bis */ + DNS_TYPE_NXT, + + /* RFC 1035 removed support for concepts that needed this from RFC 883 */ + DNS_TYPE_NULL); +} + +bool dns_type_needs_authentication(uint16_t type) { + + /* Returns true for all (non-obsolete) RR types where records are not useful if they aren't + * authenticated. I.e. everything that contains crypto keys. */ + + return IN_SET(type, + DNS_TYPE_CERT, + DNS_TYPE_SSHFP, + DNS_TYPE_IPSECKEY, + DNS_TYPE_DS, + DNS_TYPE_DNSKEY, + DNS_TYPE_TLSA, + DNS_TYPE_CDNSKEY, + DNS_TYPE_OPENPGPKEY, + DNS_TYPE_CAA); +} + +int dns_type_to_af(uint16_t t) { + switch (t) { + + case DNS_TYPE_A: + return AF_INET; + + case DNS_TYPE_AAAA: + return AF_INET6; + + case DNS_TYPE_ANY: + return AF_UNSPEC; + + default: + return -EINVAL; + } +} + +const char *dns_class_to_string(uint16_t class) { + + switch (class) { + + case DNS_CLASS_IN: + return "IN"; + + case DNS_CLASS_ANY: + return "ANY"; + } + + return NULL; +} + +int dns_class_from_string(const char *s) { + + if (!s) + return _DNS_CLASS_INVALID; + + if (strcaseeq(s, "IN")) + return DNS_CLASS_IN; + else if (strcaseeq(s, "ANY")) + return DNS_CLASS_ANY; + + return _DNS_CLASS_INVALID; +} + +const char* tlsa_cert_usage_to_string(uint8_t cert_usage) { + + switch (cert_usage) { + + case 0: + return "CA constraint"; + + case 1: + return "Service certificate constraint"; + + case 2: + return "Trust anchor assertion"; + + case 3: + return "Domain-issued certificate"; + + case 4 ... 254: + return "Unassigned"; + + case 255: + return "Private use"; + } + + return NULL; /* clang cannot count that we covered everything */ +} + +const char* tlsa_selector_to_string(uint8_t selector) { + switch (selector) { + + case 0: + return "Full Certificate"; + + case 1: + return "SubjectPublicKeyInfo"; + + case 2 ... 254: + return "Unassigned"; + + case 255: + return "Private use"; + } + + return NULL; +} + +const char* tlsa_matching_type_to_string(uint8_t selector) { + + switch (selector) { + + case 0: + return "No hash used"; + + case 1: + return "SHA-256"; + + case 2: + return "SHA-512"; + + case 3 ... 254: + return "Unassigned"; + + case 255: + return "Private use"; + } + + return NULL; +} diff --git a/src/resolve/dns-type.h b/src/resolve/dns-type.h new file mode 100644 index 00000000..8721536b --- /dev/null +++ b/src/resolve/dns-type.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "macro.h" + +/* DNS record types, taken from + * http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml. + */ +enum { + /* Normal records */ + DNS_TYPE_A = 0x01, + DNS_TYPE_NS, + DNS_TYPE_MD, + DNS_TYPE_MF, + DNS_TYPE_CNAME, + DNS_TYPE_SOA, + DNS_TYPE_MB, + DNS_TYPE_MG, + DNS_TYPE_MR, + DNS_TYPE_NULL, + DNS_TYPE_WKS, + DNS_TYPE_PTR, + DNS_TYPE_HINFO, + DNS_TYPE_MINFO, + DNS_TYPE_MX, + DNS_TYPE_TXT, + DNS_TYPE_RP, + DNS_TYPE_AFSDB, + DNS_TYPE_X25, + DNS_TYPE_ISDN, + DNS_TYPE_RT, + DNS_TYPE_NSAP, + DNS_TYPE_NSAP_PTR, + DNS_TYPE_SIG, + DNS_TYPE_KEY, + DNS_TYPE_PX, + DNS_TYPE_GPOS, + DNS_TYPE_AAAA, + DNS_TYPE_LOC, + DNS_TYPE_NXT, + DNS_TYPE_EID, + DNS_TYPE_NIMLOC, + DNS_TYPE_SRV, + DNS_TYPE_ATMA, + DNS_TYPE_NAPTR, + DNS_TYPE_KX, + DNS_TYPE_CERT, + DNS_TYPE_A6, + DNS_TYPE_DNAME, + DNS_TYPE_SINK, + DNS_TYPE_OPT, /* EDNS0 option */ + DNS_TYPE_APL, + DNS_TYPE_DS, + DNS_TYPE_SSHFP, + DNS_TYPE_IPSECKEY, + DNS_TYPE_RRSIG, + DNS_TYPE_NSEC, + DNS_TYPE_DNSKEY, + DNS_TYPE_DHCID, + DNS_TYPE_NSEC3, + DNS_TYPE_NSEC3PARAM, + DNS_TYPE_TLSA, + + DNS_TYPE_HIP = 0x37, + DNS_TYPE_NINFO, + DNS_TYPE_RKEY, + DNS_TYPE_TALINK, + DNS_TYPE_CDS, + DNS_TYPE_CDNSKEY, + DNS_TYPE_OPENPGPKEY, + + DNS_TYPE_SPF = 0x63, + DNS_TYPE_NID, + DNS_TYPE_L32, + DNS_TYPE_L64, + DNS_TYPE_LP, + DNS_TYPE_EUI48, + DNS_TYPE_EUI64, + + DNS_TYPE_TKEY = 0xF9, + DNS_TYPE_TSIG, + DNS_TYPE_IXFR, + DNS_TYPE_AXFR, + DNS_TYPE_MAILB, + DNS_TYPE_MAILA, + DNS_TYPE_ANY, + DNS_TYPE_URI, + DNS_TYPE_CAA, + DNS_TYPE_TA = 0x8000, + DNS_TYPE_DLV, + + _DNS_TYPE_MAX, + _DNS_TYPE_INVALID = -1 +}; + +assert_cc(DNS_TYPE_SSHFP == 44); +assert_cc(DNS_TYPE_TLSA == 52); +assert_cc(DNS_TYPE_ANY == 255); + +/* DNS record classes, see RFC 1035 */ +enum { + DNS_CLASS_IN = 0x01, + DNS_CLASS_ANY = 0xFF, + + _DNS_CLASS_MAX, + _DNS_CLASS_INVALID = -1 +}; + +#define _DNS_CLASS_STRING_MAX (sizeof "CLASS" + DECIMAL_STR_MAX(uint16_t)) +#define _DNS_TYPE_STRING_MAX (sizeof "CLASS" + DECIMAL_STR_MAX(uint16_t)) + +bool dns_type_is_pseudo(uint16_t type); +bool dns_type_is_valid_query(uint16_t type); +bool dns_type_is_valid_rr(uint16_t type); +bool dns_type_may_redirect(uint16_t type); +bool dns_type_is_dnssec(uint16_t type); +bool dns_type_is_obsolete(uint16_t type); +bool dns_type_may_wildcard(uint16_t type); +bool dns_type_apex_only(uint16_t type); +bool dns_type_needs_authentication(uint16_t type); +bool dns_type_is_zone_transer(uint16_t type); +int dns_type_to_af(uint16_t type); + +bool dns_class_is_pseudo(uint16_t class); +bool dns_class_is_valid_rr(uint16_t class); + +/* TYPE?? follows http://tools.ietf.org/html/rfc3597#section-5 */ +const char *dns_type_to_string(int type); +int dns_type_from_string(const char *s); + +const char *dns_class_to_string(uint16_t class); +int dns_class_from_string(const char *name); + +/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.2 */ +const char *tlsa_cert_usage_to_string(uint8_t cert_usage); + +/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.3 */ +const char *tlsa_selector_to_string(uint8_t selector); + +/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.4 */ +const char *tlsa_matching_type_to_string(uint8_t selector); + +/* https://tools.ietf.org/html/rfc6844#section-5.1 */ +#define CAA_FLAG_CRITICAL (1u << 7) diff --git a/src/resolve/dns_type-to-name.awk b/src/resolve/dns_type-to-name.awk new file mode 100644 index 00000000..badb1824 --- /dev/null +++ b/src/resolve/dns_type-to-name.awk @@ -0,0 +1,11 @@ +BEGIN{ + print "const char *dns_type_to_string(int type) {\n\tswitch(type) {" +} +{ + printf " case DNS_TYPE_%s: return ", $1; + sub(/_/, "-"); + printf "\"%s\";\n", $1 +} +END{ + print " default: return NULL;\n\t}\n}\n" +} diff --git a/src/resolve/generate-dns_type-gperf.py b/src/resolve/generate-dns_type-gperf.py new file mode 100755 index 00000000..d4f7b947 --- /dev/null +++ b/src/resolve/generate-dns_type-gperf.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +"""Generate %-from-name.gperf from %-list.txt +""" + +import sys + +name, prefix, input = sys.argv[1:] + +print("""\ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \\"-Wimplicit-fallthrough\\"") +#endif +%}""") +print("""\ +struct {}_name {{ const char* name; int id; }}; +%null-strings +%%""".format(name)) + +for line in open(input): + line = line.rstrip() + s = line.replace('_', '-') + print("{}, {}{}".format(s, prefix, line)) diff --git a/src/resolve/generate-dns_type-list.sed b/src/resolve/generate-dns_type-list.sed new file mode 100644 index 00000000..b7bc30f1 --- /dev/null +++ b/src/resolve/generate-dns_type-list.sed @@ -0,0 +1 @@ +s/.* DNS_TYPE_(\w+).*/\1/p diff --git a/src/resolve/meson.build b/src/resolve/meson.build new file mode 100644 index 00000000..92b67b63 --- /dev/null +++ b/src/resolve/meson.build @@ -0,0 +1,231 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +basic_dns_sources = files(''' + resolved-dns-dnssec.c + resolved-dns-dnssec.h + resolved-dns-packet.c + resolved-dns-packet.h + resolved-dns-rr.c + resolved-dns-rr.h + resolved-dns-answer.c + resolved-dns-answer.h + resolved-dns-question.c + resolved-dns-question.h + dns-type.c +'''.split()) + +dns_type_h = files('dns-type.h')[0] + +systemd_resolved_sources = files(''' + resolved.c + resolved-manager.c + resolved-manager.h + resolved-dnssd.c + resolved-dnssd.h + resolved-dnssd-bus.c + resolved-dnssd-bus.h + resolved-conf.c + resolved-conf.h + resolved-resolv-conf.c + resolved-resolv-conf.h + resolved-bus.c + resolved-bus.h + resolved-link.h + resolved-link.c + resolved-link-bus.c + resolved-link-bus.h + resolved-llmnr.h + resolved-llmnr.c + resolved-mdns.h + resolved-mdns.c + resolved-def.h + resolved-dns-query.h + resolved-dns-query.c + resolved-dns-synthesize.h + resolved-dns-synthesize.c + resolved-dns-transaction.h + resolved-dns-transaction.c + resolved-dns-scope.h + resolved-dns-scope.c + resolved-dns-server.h + resolved-dns-server.c + resolved-dns-search-domain.h + resolved-dns-search-domain.c + resolved-dns-cache.h + resolved-dns-cache.c + resolved-dns-zone.h + resolved-dns-zone.c + resolved-dns-stream.h + resolved-dns-stream.c + resolved-dns-trust-anchor.h + resolved-dns-trust-anchor.c + resolved-dns-stub.h + resolved-dns-stub.c + resolved-etc-hosts.h + resolved-etc-hosts.c + resolved-dnstls.h +'''.split()) + +resolvectl_sources = files(''' + resolvconf-compat.c + resolvconf-compat.h + resolvectl.c + resolvectl.h +'''.split()) + +############################################################ + +dns_type_list_txt = custom_target( + 'dns_type-list.txt', + input : ['generate-dns_type-list.sed', dns_type_h], + output : 'dns_type-list.txt', + command : [sed, '-n', '-r', '-f', '@INPUT0@', '@INPUT1@'], + capture : true) + +generate_dns_type_gperf = find_program('generate-dns_type-gperf.py') + +dns_type_headers = [dns_type_h] +foreach item : [['dns_type', dns_type_list_txt, 'dns_type', 'DNS_TYPE_']] + + fname = '@0@-from-name.gperf'.format(item[0]) + gperf_file = custom_target( + fname, + input : item[1], + output : fname, + command : [generate_dns_type_gperf, item[2], item[3], '@INPUT@'], + capture : true) + + fname = '@0@-from-name.h'.format(item[0]) + target1 = custom_target( + fname, + input : gperf_file, + output : fname, + command : [gperf, + '-L', 'ANSI-C', '-t', '--ignore-case', + '-N', 'lookup_@0@'.format(item[2]), + '-H', 'hash_@0@_name'.format(item[2]), + '-p', '-C', + '@INPUT@'], + capture : true) + + fname = '@0@-to-name.h'.format(item[0]) + awkscript = '@0@-to-name.awk'.format(item[0]) + target2 = custom_target( + fname, + input : [awkscript, item[1]], + output : fname, + command : [awk, '-f', '@INPUT0@', '@INPUT1@'], + capture : true) + + dns_type_headers += [target1, target2] +endforeach + +resolved_gperf_c = custom_target( + 'resolved_gperf.c', + input : 'resolved-gperf.gperf', + output : 'resolved-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + +resolved_dnssd_gperf_c = custom_target( + 'resolved_dnssd_gperf.c', + input : 'resolved-dnssd-gperf.gperf', + output : 'resolved-dnssd-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + +libsystemd_resolve_core = static_library( + 'systemd-resolve-core', + basic_dns_sources, + dns_type_headers, + include_directories : includes) + +systemd_resolved_sources += [resolved_gperf_c, resolved_dnssd_gperf_c] + +systemd_resolved_dependencies = [threads, libgpg_error, libm, libidn] +if conf.get('ENABLE_DNS_OVER_TLS') == 1 + if conf.get('DNS_OVER_TLS_USE_GNUTLS') == 1 + systemd_resolved_sources += files('resolved-dnstls-gnutls.c', + 'resolved-dnstls-gnutls.h') + systemd_resolved_dependencies += libgnutls + elif conf.get('DNS_OVER_TLS_USE_OPENSSL') == 1 + systemd_resolved_sources += files('resolved-dnstls-openssl.c', + 'resolved-dnstls-openssl.h') + systemd_resolved_dependencies += libopenssl + else + error('unknown dependency for supporting DNS-over-TLS') + endif +endif + +if conf.get('ENABLE_RESOLVE') == 1 + install_data('org.freedesktop.resolve1.conf', + install_dir : dbuspolicydir) + install_data('org.freedesktop.resolve1.service', + install_dir : dbussystemservicedir) + install_data('org.freedesktop.resolve1.policy', + install_dir : polkitpolicydir) + + resolved_conf = configure_file( + input : 'resolved.conf.in', + output : 'resolved.conf', + configuration : substs) + install_data(resolved_conf, + install_dir : pkgsysconfdir) + + install_data('resolv.conf', + install_dir : rootlibexecdir) +endif + +tests += [ + [['src/resolve/test-resolve-tables.c', + dns_type_headers, + 'src/shared/test-tables.h'], + [libsystemd_resolve_core, + libshared], + [libgcrypt, + libgpg_error, + libm], + 'ENABLE_RESOLVE'], + + [['src/resolve/test-dns-packet.c', + dns_type_headers], + [libsystemd_resolve_core, + libshared], + [libgcrypt, + libgpg_error, + libm], + 'ENABLE_RESOLVE'], + + [['src/resolve/test-resolved-etc-hosts.c', + 'src/resolve/resolved-etc-hosts.c', + 'src/resolve/resolved-etc-hosts.h'], + [libsystemd_resolve_core, + libshared], + [libgcrypt, + libgpg_error, + libm], + 'ENABLE_RESOLVE'], + + [['src/resolve/test-resolved-packet.c', + dns_type_headers], + [libsystemd_resolve_core, + libshared], + [libgcrypt, + libgpg_error, + libm], + 'ENABLE_RESOLVE'], + + [['src/resolve/test-dnssec.c', + dns_type_headers], + [libsystemd_resolve_core, + libshared], + [libgcrypt, + libgpg_error, + libm], + 'ENABLE_RESOLVE'], + + [['src/resolve/test-dnssec-complex.c', + 'src/resolve/dns-type.c', + dns_type_headers], + [], + [], + 'ENABLE_RESOLVE', 'manual'], +] diff --git a/src/resolve/org.freedesktop.resolve1.conf b/src/resolve/org.freedesktop.resolve1.conf new file mode 100644 index 00000000..25b09774 --- /dev/null +++ b/src/resolve/org.freedesktop.resolve1.conf @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/resolve/org.freedesktop.resolve1.policy b/src/resolve/org.freedesktop.resolve1.policy new file mode 100644 index 00000000..fd27327f --- /dev/null +++ b/src/resolve/org.freedesktop.resolve1.policy @@ -0,0 +1,142 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Register a DNS-SD service + Authentication is required to register a DNS-SD service + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + + Unregister a DNS-SD service + Authentication is required to unregister a DNS-SD service + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + + Set DNS servers + Authentication is required to set DNS servers. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + + Set domains + Authentication is required to set domains. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + + Set default route + Authentication is required to set default route. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + + Enable/disable LLMNR + Authentication is required to enable or disable LLMNR. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + + Enable/disable multicast DNS + Authentication is required to enable or disable multicast DNS. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + + Enable/disable DNS over TLS + Authentication is required to enable or disable DNS over TLS. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + + Enable/disable DNSSEC + Authentication is required to enable or disable DNSSEC. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + + Set DNSSEC Negative Trust Anchors + Authentication is required to set DNSSEC Negative Trust Anchors. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + + Revert name resolution settings + Authentication is required to reset name resolution settings. + + auth_admin + auth_admin + auth_admin_keep + + unix-user:systemd-resolve + + + diff --git a/src/resolve/org.freedesktop.resolve1.service b/src/resolve/org.freedesktop.resolve1.service new file mode 100644 index 00000000..2c25a612 --- /dev/null +++ b/src/resolve/org.freedesktop.resolve1.service @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.resolve1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.resolve1.service diff --git a/src/resolve/resolv.conf b/src/resolve/resolv.conf new file mode 100644 index 00000000..c3079aca --- /dev/null +++ b/src/resolve/resolv.conf @@ -0,0 +1,18 @@ +# This file belongs to man:systemd-resolved(8). Do not edit. +# +# This is a static resolv.conf file for connecting local clients to the +# internal DNS stub resolver of systemd-resolved. This file lists no search +# domains. +# +# Run "resolvectl status" to see details about the uplink DNS servers +# currently in use. +# +# Third party programs must not access this file directly, but only through the +# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way, +# replace this symlink by a static file or a different symlink. +# +# See man:systemd-resolved.service(8) for details about the supported modes of +# operation for /etc/resolv.conf. + +nameserver 127.0.0.53 +options edns0 diff --git a/src/resolve/resolvconf-compat.c b/src/resolve/resolvconf-compat.c new file mode 100644 index 00000000..8cd14711 --- /dev/null +++ b/src/resolve/resolvconf-compat.c @@ -0,0 +1,275 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "def.h" +#include "dns-domain.h" +#include "extract-word.h" +#include "fileio.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "resolvconf-compat.h" +#include "resolvectl.h" +#include "resolved-def.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" + +static int resolvconf_help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("resolvectl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%1$s -a INTERFACE < FILE\n" + "%1$s -d INTERFACE\n" + "\n" + "Register DNS server and domain configuration with systemd-resolved.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -a Register per-interface DNS server and domain data\n" + " -d Unregister per-interface DNS server and domain data\n" + " -f Ignore if specified interface does not exist\n" + " -x Send DNS traffic preferably over this interface\n" + "\n" + "This is a compatibility alias for the resolvectl(1) tool, providing native\n" + "command line compatibility with the resolvconf(8) tool of various Linux\n" + "distributions and BSD systems. Some options supported by other implementations\n" + "are not supported and are ignored: -m, -p. Various options supported by other\n" + "implementations are not supported and will cause the invocation to fail: -u,\n" + "-I, -i, -l, -R, -r, -v, -V, --enable-updates, --disable-updates,\n" + "--updates-are-enabled.\n" + "\nSee the %2$s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_nameserver(const char *string) { + int r; + + assert(string); + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + if (strv_push(&arg_set_dns, word) < 0) + return log_oom(); + + word = NULL; + } + + return 0; +} + +static int parse_search_domain(const char *string) { + int r; + + assert(string); + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&string, &word, NULL, EXTRACT_UNQUOTE); + if (r < 0) + return r; + if (r == 0) + break; + + if (strv_push(&arg_set_domain, word) < 0) + return log_oom(); + + word = NULL; + } + + return 0; +} + +int resolvconf_parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_ENABLE_UPDATES, + ARG_DISABLE_UPDATES, + ARG_UPDATES_ARE_ENABLED, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + + /* The following are specific to Debian's original resolvconf */ + { "enable-updates", no_argument, NULL, ARG_ENABLE_UPDATES }, + { "disable-updates", no_argument, NULL, ARG_DISABLE_UPDATES }, + { "updates-are-enabled", no_argument, NULL, ARG_UPDATES_ARE_ENABLED }, + {} + }; + + enum { + TYPE_REGULAR, + TYPE_PRIVATE, /* -p: Not supported, treated identically to TYPE_REGULAR */ + TYPE_EXCLUSIVE, /* -x */ + } type = TYPE_REGULAR; + + int c, r; + + assert(argc >= 0); + assert(argv); + + /* openresolv checks these environment variables */ + if (getenv("IF_EXCLUSIVE")) + type = TYPE_EXCLUSIVE; + if (getenv("IF_PRIVATE")) + type = TYPE_PRIVATE; /* not actually supported */ + + arg_mode = _MODE_INVALID; + + while ((c = getopt_long(argc, argv, "hadxpfm:uIi:l:Rr:vV", options, NULL)) >= 0) + switch(c) { + + case 'h': + return resolvconf_help(); + + case ARG_VERSION: + return version(); + + /* -a and -d is what everybody can agree on */ + case 'a': + arg_mode = MODE_SET_LINK; + break; + + case 'd': + arg_mode = MODE_REVERT_LINK; + break; + + /* The exclusive/private/force stuff is an openresolv invention, we support in some skewed way */ + case 'x': + type = TYPE_EXCLUSIVE; + break; + + case 'p': + type = TYPE_PRIVATE; /* not actually supported */ + break; + + case 'f': + arg_ifindex_permissive = true; + break; + + /* The metrics stuff is an openresolv invention we ignore (and don't really need) */ + case 'm': + log_debug("Switch -%c ignored.", c); + break; + + /* Everybody else can agree on the existence of -u but we don't support it. */ + case 'u': + + /* The following options are openresolv inventions we don't support. */ + case 'I': + case 'i': + case 'l': + case 'R': + case 'r': + case 'v': + case 'V': + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Switch -%c not supported.", c); + + /* The Debian resolvconf commands we don't support. */ + case ARG_ENABLE_UPDATES: + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Switch --enable-updates not supported."); + case ARG_DISABLE_UPDATES: + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Switch --disable-updates not supported."); + case ARG_UPDATES_ARE_ENABLED: + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Switch --updates-are-enabled not supported."); + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_mode == _MODE_INVALID) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Expected either -a or -d on the command line."); + + if (optind+1 != argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Expected interface name as argument."); + + r = ifname_mangle(argv[optind]); + if (r <= 0) + return r; + + optind++; + + if (arg_mode == MODE_SET_LINK) { + unsigned n = 0; + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *a, *l; + + r = read_line(stdin, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read from stdin: %m"); + if (r == 0) + break; + + n++; + + l = strstrip(line); + if (IN_SET(*l, '#', ';', 0)) + continue; + + a = first_word(l, "nameserver"); + if (a) { + (void) parse_nameserver(a); + continue; + } + + a = first_word(l, "domain"); + if (!a) + a = first_word(l, "search"); + if (a) { + (void) parse_search_domain(a); + continue; + } + + log_syntax(NULL, LOG_DEBUG, "stdin", n, 0, "Ignoring resolv.conf line: %s", l); + } + + if (type == TYPE_EXCLUSIVE) { + + /* If -x mode is selected, let's preferably route non-suffixed lookups to this interface. This + * somewhat matches the original -x behaviour */ + + r = strv_extend(&arg_set_domain, "~."); + if (r < 0) + return log_oom(); + + } else if (type == TYPE_PRIVATE) + log_debug("Private DNS server data not supported, ignoring."); + + if (!arg_set_dns) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "No DNS servers specified, refusing operation."); + } + + return 1; /* work to do */ +} diff --git a/src/resolve/resolvconf-compat.h b/src/resolve/resolvconf-compat.h new file mode 100644 index 00000000..872add1d --- /dev/null +++ b/src/resolve/resolvconf-compat.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int resolvconf_parse_argv(int argc, char *argv[]); diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c new file mode 100644 index 00000000..0a96a18b --- /dev/null +++ b/src/resolve/resolvectl.c @@ -0,0 +1,3261 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-bus.h" +#include "sd-netlink.h" + +#include "af-list.h" +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-util.h" +#include "dns-domain.h" +#include "escape.h" +#include "format-util.h" +#include "gcrypt-util.h" +#include "in-addr-util.h" +#include "main-func.h" +#include "missing_network.h" +#include "netlink-util.h" +#include "pager.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "resolvconf-compat.h" +#include "resolvectl.h" +#include "resolved-def.h" +#include "resolved-dns-packet.h" +#include "string-table.h" +#include "strv.h" +#include "terminal-util.h" +#include "verbs.h" + +static int arg_family = AF_UNSPEC; +static int arg_ifindex = 0; +static char *arg_ifname = NULL; +static uint16_t arg_type = 0; +static uint16_t arg_class = 0; +static bool arg_legend = true; +static uint64_t arg_flags = 0; +static PagerFlags arg_pager_flags = 0; +bool arg_ifindex_permissive = false; /* If true, don't generate an error if the specified interface index doesn't exist */ +static const char *arg_service_family = NULL; + +typedef enum RawType { + RAW_NONE, + RAW_PAYLOAD, + RAW_PACKET, +} RawType; +static RawType arg_raw = RAW_NONE; + +ExecutionMode arg_mode = MODE_RESOLVE_HOST; + +char **arg_set_dns = NULL; +char **arg_set_domain = NULL; +static const char *arg_set_llmnr = NULL; +static const char *arg_set_mdns = NULL; +static const char *arg_set_dns_over_tls = NULL; +static const char *arg_set_dnssec = NULL; +static char **arg_set_nta = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_ifname, freep); +STATIC_DESTRUCTOR_REGISTER(arg_set_dns, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_set_domain, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_set_nta, strv_freep); + +typedef enum StatusMode { + STATUS_ALL, + STATUS_DNS, + STATUS_DOMAIN, + STATUS_DEFAULT_ROUTE, + STATUS_LLMNR, + STATUS_MDNS, + STATUS_PRIVATE, + STATUS_DNSSEC, + STATUS_NTA, +} StatusMode; + +int ifname_mangle(const char *s) { + _cleanup_free_ char *iface = NULL; + const char *dot; + int ifi, r; + + assert(s); + + dot = strchr(s, '.'); + if (dot) { + log_debug("Ignoring protocol specifier '%s'.", dot + 1); + iface = strndup(s, dot - s); + + } else + iface = strdup(s); + if (!iface) + return log_oom(); + + r = parse_ifindex_or_ifname(iface, &ifi); + if (r < 0) { + if (r == -ENODEV && arg_ifindex_permissive) { + log_debug("Interface '%s' not found, but -f specified, ignoring.", iface); + return 0; /* done */ + } + + return log_error_errno(r, "Unknown interface '%s': %m", iface); + } + + if (arg_ifindex > 0 && arg_ifindex != ifi) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified multiple different interfaces. Refusing."); + + arg_ifindex = ifi; + free_and_replace(arg_ifname, iface); + + return 1; +} + +static void print_source(uint64_t flags, usec_t rtt) { + char rtt_str[FORMAT_TIMESTAMP_MAX]; + + if (!arg_legend) + return; + + if (flags == 0) + return; + + printf("\n%s-- Information acquired via", ansi_grey()); + + if (flags != 0) + printf(" protocol%s%s%s%s%s", + flags & SD_RESOLVED_DNS ? " DNS" :"", + flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "", + flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "", + flags & SD_RESOLVED_MDNS_IPV4 ? " mDNS/IPv4" : "", + flags & SD_RESOLVED_MDNS_IPV6 ? " mDNS/IPv6" : ""); + + assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100)); + + printf(" in %s.%s\n" + "%s-- Data is authenticated: %s%s\n", + rtt_str, ansi_normal(), + ansi_grey(), yes_no(flags & SD_RESOLVED_AUTHENTICATED), ansi_normal()); +} + +static void print_ifindex_comment(int printed_so_far, int ifindex) { + char ifname[IF_NAMESIZE + 1]; + + if (ifindex <= 0) + return; + + if (!format_ifname(ifindex, ifname)) + log_warning_errno(errno, "Failed to resolve interface name for index %i, ignoring: %m", ifindex); + else + printf("%*s%s-- link: %s%s", + 60 > printed_so_far ? 60 - printed_so_far : 0, " ", /* Align comment to the 60th column */ + ansi_grey(), ifname, ansi_normal()); +} + +static int resolve_host(sd_bus *bus, const char *name) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *canonical = NULL; + unsigned c = 0; + uint64_t flags; + usec_t ts; + int r; + + assert(name); + + log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname); + + r = sd_bus_message_new_method_call( + bus, + &req, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResolveHostname"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags); + if (r < 0) + return bus_log_create_error(r); + + ts = now(CLOCK_MONOTONIC); + + r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); + if (r < 0) + return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(&error, r)); + + ts = now(CLOCK_MONOTONIC) - ts; + + r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { + _cleanup_free_ char *pretty = NULL; + int ifindex, family, k; + const void *a; + size_t sz; + + assert_cc(sizeof(int) == sizeof(int32_t)); + + r = sd_bus_message_read(reply, "ii", &ifindex, &family); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_array(reply, 'y', &a, &sz); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + if (!IN_SET(family, AF_INET, AF_INET6)) { + log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown"); + continue; + } + + if (sz != FAMILY_ADDRESS_SIZE(family)) { + log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown"); + return -EINVAL; + } + + r = in_addr_ifindex_to_string(family, a, ifindex, &pretty); + if (r < 0) + return log_error_errno(r, "Failed to print address for %s: %m", name); + + k = printf("%*s%s %s%s%s", + (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ", + ansi_highlight(), pretty, ansi_normal()); + + print_ifindex_comment(k, ifindex); + fputc('\n', stdout); + + c++; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read(reply, "st", &canonical, &flags); + if (r < 0) + return bus_log_parse_error(r); + + if (!streq(name, canonical)) + printf("%*s%s (%s)\n", + (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ", + canonical); + + if (c == 0) { + log_error("%s: no addresses found", name); + return -ESRCH; + } + + print_source(flags, ts); + + return 0; +} + +static int resolve_address(sd_bus *bus, int family, const union in_addr_union *address, int ifindex) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *pretty = NULL; + uint64_t flags; + unsigned c = 0; + usec_t ts; + int r; + + assert(bus); + assert(IN_SET(family, AF_INET, AF_INET6)); + assert(address); + + if (ifindex <= 0) + ifindex = arg_ifindex; + + r = in_addr_ifindex_to_string(family, address, ifindex, &pretty); + if (r < 0) + return log_oom(); + + log_debug("Resolving %s.", pretty); + + r = sd_bus_message_new_method_call( + bus, + &req, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResolveAddress"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(req, "ii", ifindex, family); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family)); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(req, "t", arg_flags); + if (r < 0) + return bus_log_create_error(r); + + ts = now(CLOCK_MONOTONIC); + + r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); + if (r < 0) + return log_error_errno(r, "%s: resolve call failed: %s", pretty, bus_error_message(&error, r)); + + ts = now(CLOCK_MONOTONIC) - ts; + + r = sd_bus_message_enter_container(reply, 'a', "(is)"); + if (r < 0) + return bus_log_create_error(r); + + while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) { + const char *n; + int k; + + assert_cc(sizeof(int) == sizeof(int32_t)); + + r = sd_bus_message_read(reply, "is", &ifindex, &n); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return r; + + k = printf("%*s%s %s%s%s", + (int) strlen(pretty), c == 0 ? pretty : "", + c == 0 ? ":" : " ", + ansi_highlight(), n, ansi_normal()); + + print_ifindex_comment(k, ifindex); + fputc('\n', stdout); + + c++; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read(reply, "t", &flags); + if (r < 0) + return bus_log_parse_error(r); + + if (c == 0) { + log_error("%s: no names found", pretty); + return -ESRCH; + } + + print_source(flags, ts); + + return 0; +} + +static int output_rr_packet(const void *d, size_t l, int ifindex) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + int r; + + r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, DNS_PACKET_SIZE_MAX); + if (r < 0) + return log_oom(); + + p->refuse_compression = true; + + r = dns_packet_append_blob(p, d, l, NULL); + if (r < 0) + return log_oom(); + + r = dns_packet_read_rr(p, &rr, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to parse RR: %m"); + + if (arg_raw == RAW_PAYLOAD) { + void *data; + ssize_t k; + + k = dns_resource_record_payload(rr, &data); + if (k < 0) + return log_error_errno(k, "Cannot dump RR: %m"); + fwrite(data, 1, k, stdout); + } else { + const char *s; + int k; + + s = dns_resource_record_to_string(rr); + if (!s) + return log_oom(); + + k = printf("%s", s); + print_ifindex_comment(k, ifindex); + fputc('\n', stdout); + } + + return 0; +} + +static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type, bool warn_missing) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + unsigned n = 0; + uint64_t flags; + int r; + usec_t ts; + bool needs_authentication = false; + + assert(name); + + log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(arg_ifname) ? "*" : arg_ifname); + + r = sd_bus_message_new_method_call( + bus, + &req, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResolveRecord"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, class, type, arg_flags); + if (r < 0) + return bus_log_create_error(r); + + ts = now(CLOCK_MONOTONIC); + + r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); + if (r < 0) { + if (warn_missing || r != -ENXIO) + log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r)); + return r; + } + + ts = now(CLOCK_MONOTONIC) - ts; + + r = sd_bus_message_enter_container(reply, 'a', "(iqqay)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) { + uint16_t c, t; + int ifindex; + const void *d; + size_t l; + + assert_cc(sizeof(int) == sizeof(int32_t)); + + r = sd_bus_message_read(reply, "iqq", &ifindex, &c, &t); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_array(reply, 'y', &d, &l); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + if (arg_raw == RAW_PACKET) { + uint64_t u64 = htole64(l); + + fwrite(&u64, sizeof(u64), 1, stdout); + fwrite(d, 1, l, stdout); + } else { + r = output_rr_packet(d, l, ifindex); + if (r < 0) + return r; + } + + if (dns_type_needs_authentication(t)) + needs_authentication = true; + + n++; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read(reply, "t", &flags); + if (r < 0) + return bus_log_parse_error(r); + + if (n == 0) { + if (warn_missing) + log_error("%s: no records found", name); + return -ESRCH; + } + + print_source(flags, ts); + + if ((flags & SD_RESOLVED_AUTHENTICATED) == 0 && needs_authentication) { + fflush(stdout); + + fprintf(stderr, "\n%s" + "WARNING: The resources shown contain cryptographic key data which could not be\n" + " authenticated. It is not suitable to authenticate any communication.\n" + " This is usually indication that DNSSEC authentication was not enabled\n" + " or is not available for the selected protocol or DNS servers.%s\n", + ansi_highlight_red(), + ansi_normal()); + } + + return 0; +} + +static int resolve_rfc4501(sd_bus *bus, const char *name) { + uint16_t type = 0, class = 0; + const char *p, *q, *n; + int r; + + assert(bus); + assert(name); + assert(startswith(name, "dns:")); + + /* Parse RFC 4501 dns: URIs */ + + p = name + 4; + + if (p[0] == '/') { + const char *e; + + if (p[1] != '/') + goto invalid; + + e = strchr(p + 2, '/'); + if (!e) + goto invalid; + + if (e != p + 2) + log_warning("DNS authority specification not supported; ignoring specified authority."); + + p = e + 1; + } + + q = strchr(p, '?'); + if (q) { + n = strndupa(p, q - p); + q++; + + for (;;) { + const char *f; + + f = startswith_no_case(q, "class="); + if (f) { + _cleanup_free_ char *t = NULL; + const char *e; + + if (class != 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "DNS class specified twice."); + + e = strchrnul(f, ';'); + t = strndup(f, e - f); + if (!t) + return log_oom(); + + r = dns_class_from_string(t); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown DNS class %s.", t); + + class = r; + + if (*e == ';') { + q = e + 1; + continue; + } + + break; + } + + f = startswith_no_case(q, "type="); + if (f) { + _cleanup_free_ char *t = NULL; + const char *e; + + if (type != 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "DNS type specified twice."); + + e = strchrnul(f, ';'); + t = strndup(f, e - f); + if (!t) + return log_oom(); + + r = dns_type_from_string(t); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown DNS type %s.", t); + + type = r; + + if (*e == ';') { + q = e + 1; + continue; + } + + break; + } + + goto invalid; + } + } else + n = p; + + if (class == 0) + class = arg_class ?: DNS_CLASS_IN; + if (type == 0) + type = arg_type ?: DNS_TYPE_A; + + return resolve_record(bus, n, class, type, true); + +invalid: + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid DNS URI: %s", name); +} + +static int verb_query(int argc, char **argv, void *userdata) { + sd_bus *bus = userdata; + char **p; + int q, r = 0; + + if (arg_type != 0) + STRV_FOREACH(p, argv + 1) { + q = resolve_record(bus, *p, arg_class, arg_type, true); + if (q < 0) + r = q; + } + + else + STRV_FOREACH(p, argv + 1) { + if (startswith(*p, "dns:")) + q = resolve_rfc4501(bus, *p); + else { + int family, ifindex; + union in_addr_union a; + + q = in_addr_ifindex_from_string_auto(*p, &family, &a, &ifindex); + if (q >= 0) + q = resolve_address(bus, family, &a, ifindex); + else + q = resolve_host(bus, *p); + } + if (q < 0) + r = q; + } + + return r; +} + +static int resolve_service(sd_bus *bus, const char *name, const char *type, const char *domain) { + const char *canonical_name, *canonical_type, *canonical_domain; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + size_t indent, sz; + uint64_t flags; + const char *p; + unsigned c; + usec_t ts; + int r; + + assert(bus); + assert(domain); + + name = empty_to_null(name); + type = empty_to_null(type); + + if (name) + log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name, type, domain, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname); + else if (type) + log_debug("Resolving service type %s of %s (family %s, interface %s).", type, domain, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname); + else + log_debug("Resolving service type %s (family %s, interface %s).", domain, af_to_name(arg_family) ?: "*", isempty(arg_ifname) ? "*" : arg_ifname); + + r = sd_bus_message_new_method_call( + bus, + &req, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResolveService"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(req, "isssit", arg_ifindex, name, type, domain, arg_family, arg_flags); + if (r < 0) + return bus_log_create_error(r); + + ts = now(CLOCK_MONOTONIC); + + r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); + if (r < 0) + return log_error_errno(r, "Resolve call failed: %s", bus_error_message(&error, r)); + + ts = now(CLOCK_MONOTONIC) - ts; + + r = sd_bus_message_enter_container(reply, 'a', "(qqqsa(iiay)s)"); + if (r < 0) + return bus_log_parse_error(r); + + indent = + (name ? strlen(name) + 1 : 0) + + (type ? strlen(type) + 1 : 0) + + strlen(domain) + 2; + + c = 0; + while ((r = sd_bus_message_enter_container(reply, 'r', "qqqsa(iiay)s")) > 0) { + uint16_t priority, weight, port; + const char *hostname, *canonical; + + r = sd_bus_message_read(reply, "qqqs", &priority, &weight, &port, &hostname); + if (r < 0) + return bus_log_parse_error(r); + + if (name) + printf("%*s%s", (int) strlen(name), c == 0 ? name : "", c == 0 ? "/" : " "); + if (type) + printf("%*s%s", (int) strlen(type), c == 0 ? type : "", c == 0 ? "/" : " "); + + printf("%*s%s %s:%u [priority=%u, weight=%u]\n", + (int) strlen(domain), c == 0 ? domain : "", + c == 0 ? ":" : " ", + hostname, port, + priority, weight); + + r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { + _cleanup_free_ char *pretty = NULL; + int ifindex, family, k; + const void *a; + + assert_cc(sizeof(int) == sizeof(int32_t)); + + r = sd_bus_message_read(reply, "ii", &ifindex, &family); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_array(reply, 'y', &a, &sz); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + if (!IN_SET(family, AF_INET, AF_INET6)) { + log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown"); + continue; + } + + if (sz != FAMILY_ADDRESS_SIZE(family)) { + log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown"); + return -EINVAL; + } + + r = in_addr_ifindex_to_string(family, a, ifindex, &pretty); + if (r < 0) + return log_error_errno(r, "Failed to print address for %s: %m", name); + + k = printf("%*s%s", (int) indent, "", pretty); + print_ifindex_comment(k, ifindex); + fputc('\n', stdout); + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read(reply, "s", &canonical); + if (r < 0) + return bus_log_parse_error(r); + + if (!streq(hostname, canonical)) + printf("%*s(%s)\n", (int) indent, "", canonical); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + c++; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_enter_container(reply, 'a', "ay"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read_array(reply, 'y', (const void**) &p, &sz)) > 0) { + _cleanup_free_ char *escaped = NULL; + + escaped = cescape_length(p, sz); + if (!escaped) + return log_oom(); + + printf("%*s%s\n", (int) indent, "", escaped); + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read(reply, "ssst", &canonical_name, &canonical_type, &canonical_domain, &flags); + if (r < 0) + return bus_log_parse_error(r); + + canonical_name = empty_to_null(canonical_name); + canonical_type = empty_to_null(canonical_type); + + if (!streq_ptr(name, canonical_name) || + !streq_ptr(type, canonical_type) || + !streq_ptr(domain, canonical_domain)) { + + printf("%*s(", (int) indent, ""); + + if (canonical_name) + printf("%s/", canonical_name); + if (canonical_type) + printf("%s/", canonical_type); + + printf("%s)\n", canonical_domain); + } + + print_source(flags, ts); + + return 0; +} + +static int verb_service(int argc, char **argv, void *userdata) { + sd_bus *bus = userdata; + + if (argc == 2) + return resolve_service(bus, NULL, NULL, argv[1]); + else if (argc == 3) + return resolve_service(bus, NULL, argv[1], argv[2]); + else + return resolve_service(bus, argv[1], argv[2], argv[3]); +} + +static int resolve_openpgp(sd_bus *bus, const char *address) { + const char *domain, *full; + int r; + _cleanup_free_ char *hashed = NULL; + + assert(bus); + assert(address); + + domain = strrchr(address, '@'); + if (!domain) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Address does not contain '@': \"%s\"", address); + if (domain == address || domain[1] == '\0') + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Address starts or ends with '@': \"%s\"", address); + domain++; + + r = string_hashsum_sha256(address, domain - 1 - address, &hashed); + if (r < 0) + return log_error_errno(r, "Hashing failed: %m"); + + strshorten(hashed, 56); + + full = strjoina(hashed, "._openpgpkey.", domain); + log_debug("Looking up \"%s\".", full); + + r = resolve_record(bus, full, + arg_class ?: DNS_CLASS_IN, + arg_type ?: DNS_TYPE_OPENPGPKEY, false); + + if (IN_SET(r, -ENXIO, -ESRCH)) { /* NXDOMAIN or NODATA? */ + hashed = mfree(hashed); + r = string_hashsum_sha224(address, domain - 1 - address, &hashed); + if (r < 0) + return log_error_errno(r, "Hashing failed: %m"); + + full = strjoina(hashed, "._openpgpkey.", domain); + log_debug("Looking up \"%s\".", full); + + return resolve_record(bus, full, + arg_class ?: DNS_CLASS_IN, + arg_type ?: DNS_TYPE_OPENPGPKEY, true); + } + + return r; +} + +static int verb_openpgp(int argc, char **argv, void *userdata) { + sd_bus *bus = userdata; + char **p; + int q, r = 0; + + STRV_FOREACH(p, argv + 1) { + q = resolve_openpgp(bus, *p); + if (q < 0) + r = q; + } + + return r; +} + +static int resolve_tlsa(sd_bus *bus, const char *family, const char *address) { + const char *port; + uint16_t port_num = 443; + _cleanup_free_ char *full = NULL; + int r; + + assert(bus); + assert(address); + + port = strrchr(address, ':'); + if (port) { + r = parse_ip_port(port + 1, &port_num); + if (r < 0) + return log_error_errno(r, "Invalid port \"%s\".", port + 1); + + address = strndupa(address, port - address); + } + + r = asprintf(&full, "_%u._%s.%s", + port_num, + family, + address); + if (r < 0) + return log_oom(); + + log_debug("Looking up \"%s\".", full); + + return resolve_record(bus, full, + arg_class ?: DNS_CLASS_IN, + arg_type ?: DNS_TYPE_TLSA, true); +} + +static bool service_family_is_valid(const char *s) { + return STR_IN_SET(s, "tcp", "udp", "sctp"); +} + +static int verb_tlsa(int argc, char **argv, void *userdata) { + sd_bus *bus = userdata; + char **p, **args = argv + 1; + const char *family = "tcp"; + int q, r = 0; + + if (service_family_is_valid(argv[1])) { + family = argv[1]; + args++; + } + + STRV_FOREACH(p, args) { + q = resolve_tlsa(bus, family, *p); + if (q < 0) + r = q; + } + + return r; +} + +static int show_statistics(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + sd_bus *bus = userdata; + uint64_t n_current_transactions, n_total_transactions, + cache_size, n_cache_hit, n_cache_miss, + n_dnssec_secure, n_dnssec_insecure, n_dnssec_bogus, n_dnssec_indeterminate; + int r, dnssec_supported; + + assert(bus); + + r = sd_bus_get_property_trivial(bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "DNSSECSupported", + &error, + 'b', + &dnssec_supported); + if (r < 0) + return log_error_errno(r, "Failed to get DNSSEC supported state: %s", bus_error_message(&error, r)); + + printf("DNSSEC supported by current servers: %s%s%s\n\n", + ansi_highlight(), + yes_no(dnssec_supported), + ansi_normal()); + + r = sd_bus_get_property(bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "TransactionStatistics", + &error, + &reply, + "(tt)"); + if (r < 0) + return log_error_errno(r, "Failed to get transaction statistics: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "(tt)", + &n_current_transactions, + &n_total_transactions); + if (r < 0) + return bus_log_parse_error(r); + + printf("%sTransactions%s\n" + "Current Transactions: %" PRIu64 "\n" + " Total Transactions: %" PRIu64 "\n", + ansi_highlight(), + ansi_normal(), + n_current_transactions, + n_total_transactions); + + reply = sd_bus_message_unref(reply); + + r = sd_bus_get_property(bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "CacheStatistics", + &error, + &reply, + "(ttt)"); + if (r < 0) + return log_error_errno(r, "Failed to get cache statistics: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "(ttt)", + &cache_size, + &n_cache_hit, + &n_cache_miss); + if (r < 0) + return bus_log_parse_error(r); + + printf("\n%sCache%s\n" + " Current Cache Size: %" PRIu64 "\n" + " Cache Hits: %" PRIu64 "\n" + " Cache Misses: %" PRIu64 "\n", + ansi_highlight(), + ansi_normal(), + cache_size, + n_cache_hit, + n_cache_miss); + + reply = sd_bus_message_unref(reply); + + r = sd_bus_get_property(bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "DNSSECStatistics", + &error, + &reply, + "(tttt)"); + if (r < 0) + return log_error_errno(r, "Failed to get DNSSEC statistics: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "(tttt)", + &n_dnssec_secure, + &n_dnssec_insecure, + &n_dnssec_bogus, + &n_dnssec_indeterminate); + if (r < 0) + return bus_log_parse_error(r); + + printf("\n%sDNSSEC Verdicts%s\n" + " Secure: %" PRIu64 "\n" + " Insecure: %" PRIu64 "\n" + " Bogus: %" PRIu64 "\n" + " Indeterminate: %" PRIu64 "\n", + ansi_highlight(), + ansi_normal(), + n_dnssec_secure, + n_dnssec_insecure, + n_dnssec_bogus, + n_dnssec_indeterminate); + + return 0; +} + +static int reset_statistics(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + r = sd_bus_call_method(bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResetStatistics", + &error, + NULL, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to reset statistics: %s", bus_error_message(&error, r)); + + return 0; +} + +static int flush_caches(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + r = sd_bus_call_method(bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "FlushCaches", + &error, + NULL, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to flush caches: %s", bus_error_message(&error, r)); + + return 0; +} + +static int reset_server_features(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + r = sd_bus_call_method(bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResetServerFeatures", + &error, + NULL, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to reset server features: %s", bus_error_message(&error, r)); + + return 0; +} + +static int read_dns_server_one(sd_bus_message *m, bool with_ifindex, char **ret) { + _cleanup_free_ char *pretty = NULL; + int ifindex, family, r; + const void *a; + size_t sz; + + assert(m); + assert(ret); + + r = sd_bus_message_enter_container(m, 'r', with_ifindex ? "iiay" : "iay"); + if (r <= 0) + return r; + + if (with_ifindex) { + r = sd_bus_message_read(m, "i", &ifindex); + if (r < 0) + return r; + } + + r = sd_bus_message_read(m, "i", &family); + if (r < 0) + return r; + + r = sd_bus_message_read_array(m, 'y', &a, &sz); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + if (with_ifindex && ifindex != 0) { + /* only show the global ones here */ + *ret = NULL; + return 1; + } + + if (!IN_SET(family, AF_INET, AF_INET6)) { + log_debug("Unexpected family, ignoring: %i", family); + + *ret = NULL; + return 1; + } + + if (sz != FAMILY_ADDRESS_SIZE(family)) { + log_debug("Address size mismatch, ignoring."); + + *ret = NULL; + return 1; + } + + r = in_addr_to_string(family, a, &pretty); + if (r < 0) + return r; + + *ret = TAKE_PTR(pretty); + + return 1; +} + +static int map_link_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + char ***l = userdata; + int r; + + assert(bus); + assert(member); + assert(m); + assert(l); + + r = sd_bus_message_enter_container(m, 'a', "(iay)"); + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *pretty = NULL; + + r = read_dns_server_one(m, false, &pretty); + if (r < 0) + return r; + if (r == 0) + break; + + if (isempty(pretty)) + continue; + + r = strv_consume(l, TAKE_PTR(pretty)); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +static int map_link_current_dns_server(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + assert(m); + assert(userdata); + + return read_dns_server_one(m, false, userdata); +} + +static int read_domain_one(sd_bus_message *m, bool with_ifindex, char **ret) { + _cleanup_free_ char *str = NULL; + int ifindex, route_only, r; + const char *domain; + + assert(m); + assert(ret); + + if (with_ifindex) + r = sd_bus_message_read(m, "(isb)", &ifindex, &domain, &route_only); + else + r = sd_bus_message_read(m, "(sb)", &domain, &route_only); + if (r <= 0) + return r; + + if (with_ifindex && ifindex != 0) { + /* only show the global ones here */ + *ret = NULL; + return 1; + } + + if (route_only) + str = strjoin("~", domain); + else + str = strdup(domain); + if (!str) + return -ENOMEM; + + *ret = TAKE_PTR(str); + + return 1; +} + +static int map_link_domains(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + char ***l = userdata; + int r; + + assert(bus); + assert(member); + assert(m); + assert(l); + + r = sd_bus_message_enter_container(m, 'a', "(sb)"); + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *pretty = NULL; + + r = read_domain_one(m, false, &pretty); + if (r < 0) + return r; + if (r == 0) + break; + + if (isempty(pretty)) + continue; + + r = strv_consume(l, TAKE_PTR(pretty)); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +static int status_print_strv_ifindex(int ifindex, const char *ifname, char **p) { + char **i; + + printf("%sLink %i (%s)%s:", + ansi_highlight(), ifindex, ifname, ansi_normal()); + + STRV_FOREACH(i, p) + printf(" %s", *i); + + printf("\n"); + + return 0; +} + +struct link_info { + uint64_t scopes_mask; + const char *llmnr; + const char *mdns; + const char *dns_over_tls; + const char *dnssec; + char *current_dns; + char **dns; + char **domains; + char **ntas; + bool dnssec_supported; + bool default_route; +}; + +static void link_info_clear(struct link_info *p) { + free(p->current_dns); + strv_free(p->dns); + strv_free(p->domains); + strv_free(p->ntas); +} + +static int status_ifindex(sd_bus *bus, int ifindex, const char *name, StatusMode mode, bool *empty_line) { + static const struct bus_properties_map property_map[] = { + { "ScopesMask", "t", NULL, offsetof(struct link_info, scopes_mask) }, + { "DNS", "a(iay)", map_link_dns_servers, offsetof(struct link_info, dns) }, + { "CurrentDNSServer", "(iay)", map_link_current_dns_server, offsetof(struct link_info, current_dns) }, + { "Domains", "a(sb)", map_link_domains, offsetof(struct link_info, domains) }, + { "DefaultRoute", "b", NULL, offsetof(struct link_info, default_route) }, + { "LLMNR", "s", NULL, offsetof(struct link_info, llmnr) }, + { "MulticastDNS", "s", NULL, offsetof(struct link_info, mdns) }, + { "DNSOverTLS", "s", NULL, offsetof(struct link_info, dns_over_tls) }, + { "DNSSEC", "s", NULL, offsetof(struct link_info, dnssec) }, + { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct link_info, ntas) }, + { "DNSSECSupported", "b", NULL, offsetof(struct link_info, dnssec_supported) }, + {} + }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(link_info_clear) struct link_info link_info = {}; + _cleanup_free_ char *ifi = NULL, *p = NULL; + char ifname[IF_NAMESIZE + 1] = ""; + char **i; + int r; + + assert(bus); + assert(ifindex > 0); + + if (!name) { + if (!format_ifname(ifindex, ifname)) + return log_error_errno(errno, "Failed to resolve interface name for %i: %m", ifindex); + + name = ifname; + } + + if (asprintf(&ifi, "%i", ifindex) < 0) + return log_oom(); + + r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifi, &p); + if (r < 0) + return log_oom(); + + r = bus_map_all_properties(bus, + "org.freedesktop.resolve1", + p, + property_map, + BUS_MAP_BOOLEAN_AS_BOOL, + &error, + &m, + &link_info); + if (r < 0) + return log_error_errno(r, "Failed to get link data for %i: %s", ifindex, bus_error_message(&error, r)); + + (void) pager_open(arg_pager_flags); + + if (mode == STATUS_DNS) + return status_print_strv_ifindex(ifindex, name, link_info.dns); + + if (mode == STATUS_DOMAIN) + return status_print_strv_ifindex(ifindex, name, link_info.domains); + + if (mode == STATUS_NTA) + return status_print_strv_ifindex(ifindex, name, link_info.ntas); + + if (mode == STATUS_DEFAULT_ROUTE) { + printf("%sLink %i (%s)%s: %s\n", + ansi_highlight(), ifindex, name, ansi_normal(), + yes_no(link_info.default_route)); + + return 0; + } + + if (mode == STATUS_LLMNR) { + printf("%sLink %i (%s)%s: %s\n", + ansi_highlight(), ifindex, name, ansi_normal(), + strna(link_info.llmnr)); + + return 0; + } + + if (mode == STATUS_MDNS) { + printf("%sLink %i (%s)%s: %s\n", + ansi_highlight(), ifindex, name, ansi_normal(), + strna(link_info.mdns)); + + return 0; + } + + if (mode == STATUS_PRIVATE) { + printf("%sLink %i (%s)%s: %s\n", + ansi_highlight(), ifindex, name, ansi_normal(), + strna(link_info.dns_over_tls)); + + return 0; + } + + if (mode == STATUS_DNSSEC) { + printf("%sLink %i (%s)%s: %s\n", + ansi_highlight(), ifindex, name, ansi_normal(), + strna(link_info.dnssec)); + + return 0; + } + + if (empty_line && *empty_line) + fputc('\n', stdout); + + printf("%sLink %i (%s)%s\n", + ansi_highlight(), ifindex, name, ansi_normal()); + + if (link_info.scopes_mask == 0) + printf(" Current Scopes: none\n"); + else + printf(" Current Scopes:%s%s%s%s%s\n", + link_info.scopes_mask & SD_RESOLVED_DNS ? " DNS" : "", + link_info.scopes_mask & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "", + link_info.scopes_mask & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "", + link_info.scopes_mask & SD_RESOLVED_MDNS_IPV4 ? " mDNS/IPv4" : "", + link_info.scopes_mask & SD_RESOLVED_MDNS_IPV6 ? " mDNS/IPv6" : ""); + + printf("DefaultRoute setting: %s\n" + " LLMNR setting: %s\n" + "MulticastDNS setting: %s\n" + " DNSOverTLS setting: %s\n" + " DNSSEC setting: %s\n" + " DNSSEC supported: %s\n", + yes_no(link_info.default_route), + strna(link_info.llmnr), + strna(link_info.mdns), + strna(link_info.dns_over_tls), + strna(link_info.dnssec), + yes_no(link_info.dnssec_supported)); + + if (link_info.current_dns) + printf(" Current DNS Server: %s\n", link_info.current_dns); + + STRV_FOREACH(i, link_info.dns) { + printf(" %s %s\n", + i == link_info.dns ? "DNS Servers:" : " ", + *i); + } + + STRV_FOREACH(i, link_info.domains) { + printf(" %s %s\n", + i == link_info.domains ? "DNS Domain:" : " ", + *i); + } + + STRV_FOREACH(i, link_info.ntas) { + printf(" %s %s\n", + i == link_info.ntas ? "DNSSEC NTA:" : " ", + *i); + } + + if (empty_line) + *empty_line = true; + + return 0; +} + +static int map_global_dns_servers(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + char ***l = userdata; + int r; + + assert(bus); + assert(member); + assert(m); + assert(l); + + r = sd_bus_message_enter_container(m, 'a', "(iiay)"); + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *pretty = NULL; + + r = read_dns_server_one(m, true, &pretty); + if (r < 0) + return r; + if (r == 0) + break; + + if (isempty(pretty)) + continue; + + r = strv_consume(l, TAKE_PTR(pretty)); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +static int map_global_current_dns_server(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + assert(m); + assert(userdata); + + return read_dns_server_one(m, true, userdata); +} + +static int map_global_domains(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + char ***l = userdata; + int r; + + assert(bus); + assert(member); + assert(m); + assert(l); + + r = sd_bus_message_enter_container(m, 'a', "(isb)"); + if (r < 0) + return r; + + for (;;) { + _cleanup_free_ char *pretty = NULL; + + r = read_domain_one(m, true, &pretty); + if (r < 0) + return r; + if (r == 0) + break; + + if (isempty(pretty)) + continue; + + r = strv_consume(l, TAKE_PTR(pretty)); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +static int status_print_strv_global(char **p) { + char **i; + + printf("%sGlobal%s:", ansi_highlight(), ansi_normal()); + + STRV_FOREACH(i, p) + printf(" %s", *i); + + printf("\n"); + + return 0; +} + +struct global_info { + char *current_dns; + char **dns; + char **fallback_dns; + char **domains; + char **ntas; + const char *llmnr; + const char *mdns; + const char *dns_over_tls; + const char *dnssec; + bool dnssec_supported; +}; + +static void global_info_clear(struct global_info *p) { + free(p->current_dns); + strv_free(p->dns); + strv_free(p->fallback_dns); + strv_free(p->domains); + strv_free(p->ntas); +} + +static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) { + static const struct bus_properties_map property_map[] = { + { "DNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, dns) }, + { "FallbackDNS", "a(iiay)", map_global_dns_servers, offsetof(struct global_info, fallback_dns) }, + { "CurrentDNSServer", "(iiay)", map_global_current_dns_server, offsetof(struct global_info, current_dns) }, + { "Domains", "a(isb)", map_global_domains, offsetof(struct global_info, domains) }, + { "DNSSECNegativeTrustAnchors", "as", NULL, offsetof(struct global_info, ntas) }, + { "LLMNR", "s", NULL, offsetof(struct global_info, llmnr) }, + { "MulticastDNS", "s", NULL, offsetof(struct global_info, mdns) }, + { "DNSOverTLS", "s", NULL, offsetof(struct global_info, dns_over_tls) }, + { "DNSSEC", "s", NULL, offsetof(struct global_info, dnssec) }, + { "DNSSECSupported", "b", NULL, offsetof(struct global_info, dnssec_supported) }, + {} + }; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(global_info_clear) struct global_info global_info = {}; + char **i; + int r; + + assert(bus); + assert(empty_line); + + r = bus_map_all_properties(bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + property_map, + BUS_MAP_BOOLEAN_AS_BOOL, + &error, + &m, + &global_info); + if (r < 0) + return log_error_errno(r, "Failed to get global data: %s", bus_error_message(&error, r)); + + (void) pager_open(arg_pager_flags); + + if (mode == STATUS_DNS) + return status_print_strv_global(global_info.dns); + + if (mode == STATUS_DOMAIN) + return status_print_strv_global(global_info.domains); + + if (mode == STATUS_NTA) + return status_print_strv_global(global_info.ntas); + + if (mode == STATUS_LLMNR) { + printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(), + strna(global_info.llmnr)); + + return 0; + } + + if (mode == STATUS_MDNS) { + printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(), + strna(global_info.mdns)); + + return 0; + } + + if (mode == STATUS_PRIVATE) { + printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(), + strna(global_info.dns_over_tls)); + + return 0; + } + + if (mode == STATUS_DNSSEC) { + printf("%sGlobal%s: %s\n", ansi_highlight(), ansi_normal(), + strna(global_info.dnssec)); + + return 0; + } + + printf("%sGlobal%s\n", ansi_highlight(), ansi_normal()); + + printf(" LLMNR setting: %s\n" + "MulticastDNS setting: %s\n" + " DNSOverTLS setting: %s\n" + " DNSSEC setting: %s\n" + " DNSSEC supported: %s\n", + strna(global_info.llmnr), + strna(global_info.mdns), + strna(global_info.dns_over_tls), + strna(global_info.dnssec), + yes_no(global_info.dnssec_supported)); + + if (global_info.current_dns) + printf(" Current DNS Server: %s\n", global_info.current_dns); + + STRV_FOREACH(i, global_info.dns) { + printf(" %s %s\n", + i == global_info.dns ? "DNS Servers:" : " ", + *i); + } + + STRV_FOREACH(i, global_info.fallback_dns) { + printf("%s %s\n", + i == global_info.fallback_dns ? "Fallback DNS Servers:" : " ", + *i); + } + + STRV_FOREACH(i, global_info.domains) { + printf(" %s %s\n", + i == global_info.domains ? "DNS Domain:" : " ", + *i); + } + + strv_sort(global_info.ntas); + STRV_FOREACH(i, global_info.ntas) { + printf(" %s %s\n", + i == global_info.ntas ? "DNSSEC NTA:" : " ", + *i); + } + + *empty_line = true; + + return 0; +} + +static int status_all(sd_bus *bus, StatusMode mode) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + sd_netlink_message *i; + bool empty_line = false; + int r; + + assert(bus); + + r = status_global(bus, mode, &empty_line); + if (r < 0) + return r; + + r = sd_netlink_open(&rtnl); + if (r < 0) + return log_error_errno(r, "Failed to connect to netlink: %m"); + + r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0); + if (r < 0) + return rtnl_log_create_error(r); + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return rtnl_log_create_error(r); + + r = sd_netlink_call(rtnl, req, 0, &reply); + if (r < 0) + return log_error_errno(r, "Failed to enumerate links: %m"); + + r = 0; + for (i = reply; i; i = sd_netlink_message_next(i)) { + const char *name; + int ifindex, q; + uint16_t type; + + q = sd_netlink_message_get_type(i, &type); + if (q < 0) + return rtnl_log_parse_error(q); + + if (type != RTM_NEWLINK) + continue; + + q = sd_rtnl_message_link_get_ifindex(i, &ifindex); + if (q < 0) + return rtnl_log_parse_error(q); + + if (ifindex == LOOPBACK_IFINDEX) + continue; + + q = sd_netlink_message_read_string(i, IFLA_IFNAME, &name); + if (q < 0) + return rtnl_log_parse_error(q); + + q = status_ifindex(bus, ifindex, name, mode, &empty_line); + if (q < 0 && r >= 0) + r = q; + } + + return r; +} + +static int verb_status(int argc, char **argv, void *userdata) { + sd_bus *bus = userdata; + int q, r = 0; + + if (argc > 1) { + char **ifname; + bool empty_line = false; + + STRV_FOREACH(ifname, argv + 1) { + int ifindex; + + q = parse_ifindex_or_ifname(*ifname, &ifindex); + if (q < 0) { + log_error_errno(q, "Unknown interface '%s', ignoring: %m", *ifname); + continue; + } + + q = status_ifindex(bus, ifindex, NULL, STATUS_ALL, &empty_line); + if (q < 0) + r = q; + } + } else + r = status_all(bus, STATUS_ALL); + + return r; +} + +static int call_dns(sd_bus *bus, char **dns, const char *destination, const char *path, const char *interface, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL; + char **p; + int r; + + r = sd_bus_message_new_method_call( + bus, + &req, + destination, + path, + interface, + "SetLinkDNS"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(req, "i", arg_ifindex); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(req, 'a', "(iay)"); + if (r < 0) + return bus_log_create_error(r); + + /* If only argument is the empty string, then call SetLinkDNS() with an + * empty list, which will clear the list of domains for an interface. */ + if (!strv_equal(dns, STRV_MAKE(""))) + STRV_FOREACH(p, dns) { + struct in_addr_data data; + + r = in_addr_from_string_auto(*p, &data.family, &data.address); + if (r < 0) + return log_error_errno(r, "Failed to parse DNS server address: %s", *p); + + r = sd_bus_message_open_container(req, 'r', "iay"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(req, "i", data.family); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_array(req, 'y', &data.address, FAMILY_ADDRESS_SIZE(data.family)); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(req); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(req); + if (r < 0) + return bus_log_create_error(r); + + return sd_bus_call(bus, req, 0, error, NULL); +} + +static int verb_dns(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + if (argc >= 2) { + r = ifname_mangle(argv[1]); + if (r < 0) + return r; + } + + if (arg_ifindex <= 0) + return status_all(bus, STATUS_DNS); + + if (argc < 3) + return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNS, NULL); + + r = call_dns(bus, argv + 2, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + &error); + if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { + sd_bus_error_free(&error); + + r = call_dns(bus, argv + 2, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + &error); + } + if (r < 0) { + if (arg_ifindex_permissive && + sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) + return 0; + + return log_error_errno(r, "Failed to set DNS configuration: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int call_domain(sd_bus *bus, char **domain, const char *destination, const char *path, const char *interface, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL; + char **p; + int r; + + r = sd_bus_message_new_method_call( + bus, + &req, + destination, + path, + interface, + "SetLinkDomains"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(req, "i", arg_ifindex); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(req, 'a', "(sb)"); + if (r < 0) + return bus_log_create_error(r); + + /* If only argument is the empty string, then call SetLinkDomains() with an + * empty list, which will clear the list of domains for an interface. */ + if (!strv_equal(domain, STRV_MAKE(""))) + STRV_FOREACH(p, domain) { + const char *n; + + n = **p == '~' ? *p + 1 : *p; + + r = dns_name_is_valid(n); + if (r < 0) + return log_error_errno(r, "Failed to validate specified domain %s: %m", n); + if (r == 0) { + log_error("Domain not valid: %s", n); + return -EINVAL; + } + + r = sd_bus_message_append(req, "(sb)", n, **p == '~'); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(req); + if (r < 0) + return bus_log_create_error(r); + + return sd_bus_call(bus, req, 0, error, NULL); +} + +static int verb_domain(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + if (argc >= 2) { + r = ifname_mangle(argv[1]); + if (r < 0) + return r; + } + + if (arg_ifindex <= 0) + return status_all(bus, STATUS_DOMAIN); + + if (argc < 3) + return status_ifindex(bus, arg_ifindex, NULL, STATUS_DOMAIN, NULL); + + r = call_domain(bus, argv + 2, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + &error); + if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { + sd_bus_error_free(&error); + + r = call_domain(bus, argv + 2, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + &error); + } + if (r < 0) { + if (arg_ifindex_permissive && + sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) + return 0; + + return log_error_errno(r, "Failed to set domain configuration: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int verb_default_route(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, b; + + assert(bus); + + if (argc >= 2) { + r = ifname_mangle(argv[1]); + if (r < 0) + return r; + } + + if (arg_ifindex <= 0) + return status_all(bus, STATUS_DEFAULT_ROUTE); + + if (argc < 3) + return status_ifindex(bus, arg_ifindex, NULL, STATUS_DEFAULT_ROUTE, NULL); + + b = parse_boolean(argv[2]); + if (b < 0) + return log_error_errno(b, "Failed to parse boolean argument: %s", argv[2]); + + r = sd_bus_call_method( + bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "SetLinkDefaultRoute", + &error, + NULL, + "ib", arg_ifindex, b); + if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { + sd_bus_error_free(&error); + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "SetLinkDefaultRoute", + &error, + NULL, + "ib", arg_ifindex, b); + } + if (r < 0) { + if (arg_ifindex_permissive && + sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) + return 0; + + return log_error_errno(r, "Failed to set default route configuration: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int verb_llmnr(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + if (argc >= 2) { + r = ifname_mangle(argv[1]); + if (r < 0) + return r; + } + + if (arg_ifindex <= 0) + return status_all(bus, STATUS_LLMNR); + + if (argc < 3) + return status_ifindex(bus, arg_ifindex, NULL, STATUS_LLMNR, NULL); + + r = sd_bus_call_method( + bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "SetLinkLLMNR", + &error, + NULL, + "is", arg_ifindex, argv[2]); + if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { + sd_bus_error_free(&error); + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "SetLinkLLMNR", + &error, + NULL, + "is", arg_ifindex, argv[2]); + } + if (r < 0) { + if (arg_ifindex_permissive && + sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) + return 0; + + return log_error_errno(r, "Failed to set LLMNR configuration: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int verb_mdns(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + if (argc >= 2) { + r = ifname_mangle(argv[1]); + if (r < 0) + return r; + } + + if (arg_ifindex <= 0) + return status_all(bus, STATUS_MDNS); + + if (argc < 3) + return status_ifindex(bus, arg_ifindex, NULL, STATUS_MDNS, NULL); + + r = sd_bus_call_method( + bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "SetLinkMulticastDNS", + &error, + NULL, + "is", arg_ifindex, argv[2]); + if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { + sd_bus_error_free(&error); + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "SetLinkMulticastDNS", + &error, + NULL, + "is", arg_ifindex, argv[2]); + } + if (r < 0) { + if (arg_ifindex_permissive && + sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) + return 0; + + return log_error_errno(r, "Failed to set MulticastDNS configuration: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int verb_dns_over_tls(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + if (argc >= 2) { + r = ifname_mangle(argv[1]); + if (r < 0) + return r; + } + + if (arg_ifindex <= 0) + return status_all(bus, STATUS_PRIVATE); + + if (argc < 3) + return status_ifindex(bus, arg_ifindex, NULL, STATUS_PRIVATE, NULL); + + r = sd_bus_call_method( + bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "SetLinkDNSOverTLS", + &error, + NULL, + "is", arg_ifindex, argv[2]); + if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { + sd_bus_error_free(&error); + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "SetLinkDNSOverTLS", + &error, + NULL, + "is", arg_ifindex, argv[2]); + } + if (r < 0) { + if (arg_ifindex_permissive && + sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) + return 0; + + return log_error_errno(r, "Failed to set DNSOverTLS configuration: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int verb_dnssec(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + if (argc >= 2) { + r = ifname_mangle(argv[1]); + if (r < 0) + return r; + } + + if (arg_ifindex <= 0) + return status_all(bus, STATUS_DNSSEC); + + if (argc < 3) + return status_ifindex(bus, arg_ifindex, NULL, STATUS_DNSSEC, NULL); + + r = sd_bus_call_method( + bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "SetLinkDNSSEC", + &error, + NULL, + "is", arg_ifindex, argv[2]); + if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { + sd_bus_error_free(&error); + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "SetLinkDNSSEC", + &error, + NULL, + "is", arg_ifindex, argv[2]); + } + if (r < 0) { + if (arg_ifindex_permissive && + sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) + return 0; + + return log_error_errno(r, "Failed to set DNSSEC configuration: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int call_nta(sd_bus *bus, char **nta, const char *destination, const char *path, const char *interface, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL; + int r; + + r = sd_bus_message_new_method_call( + bus, + &req, + destination, + path, + interface, + "SetLinkDNSSECNegativeTrustAnchors"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(req, "i", arg_ifindex); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(req, nta); + if (r < 0) + return bus_log_create_error(r); + + return sd_bus_call(bus, req, 0, error, NULL); +} + +static int verb_nta(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + char **p; + int r; + bool clear; + + assert(bus); + + if (argc >= 2) { + r = ifname_mangle(argv[1]); + if (r < 0) + return r; + } + + if (arg_ifindex <= 0) + return status_all(bus, STATUS_NTA); + + if (argc < 3) + return status_ifindex(bus, arg_ifindex, NULL, STATUS_NTA, NULL); + + /* If only argument is the empty string, then call SetLinkDNSSECNegativeTrustAnchors() + * with an empty list, which will clear the list of domains for an interface. */ + clear = strv_equal(argv + 2, STRV_MAKE("")); + + if (!clear) + STRV_FOREACH(p, argv + 2) { + r = dns_name_is_valid(*p); + if (r < 0) + return log_error_errno(r, "Failed to validate specified domain %s: %m", *p); + if (r == 0) { + log_error("Domain not valid: %s", *p); + return -EINVAL; + } + } + + r = call_nta(bus, clear ? NULL : argv + 2, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + &error); + if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { + sd_bus_error_free(&error); + + r = call_nta(bus, clear ? NULL : argv + 2, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + &error); + } + if (r < 0) { + if (arg_ifindex_permissive && + sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) + return 0; + + return log_error_errno(r, "Failed to set DNSSEC NTA configuration: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int verb_revert_link(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + if (argc >= 2) { + r = ifname_mangle(argv[1]); + if (r < 0) + return r; + } + + if (arg_ifindex <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Interface argument required."); + + r = sd_bus_call_method( + bus, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "RevertLink", + &error, + NULL, + "i", arg_ifindex); + if (r < 0 && sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY)) { + sd_bus_error_free(&error); + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "RevertLinkDNS", + &error, + NULL, + "i", arg_ifindex); + } + if (r < 0) { + if (arg_ifindex_permissive && + sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK)) + return 0; + + return log_error_errno(r, "Failed to revert interface configuration: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static void help_protocol_types(void) { + if (arg_legend) + puts("Known protocol types:"); + puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6\nmdns\nmdns-ipv4\nmdns-ipv6"); +} + +static void help_dns_types(void) { + if (arg_legend) + puts("Known DNS RR types:"); + + DUMP_STRING_TABLE(dns_type, int, _DNS_TYPE_MAX); +} + +static void help_dns_classes(void) { + if (arg_legend) + puts("Known DNS RR classes:"); + + DUMP_STRING_TABLE(dns_class, int, _DNS_CLASS_MAX); +} + +static int compat_help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("resolvectl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n" + "%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n" + "%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n" + "%1$s [OPTIONS...] --statistics\n" + "%1$s [OPTIONS...] --reset-statistics\n" + "\n" + "%2$sResolve domain names, IPv4 and IPv6 addresses, DNS records, and services.%3$s\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " -4 Resolve IPv4 addresses\n" + " -6 Resolve IPv6 addresses\n" + " -i --interface=INTERFACE Look on interface\n" + " -p --protocol=PROTO|help Look via protocol\n" + " -t --type=TYPE|help Query RR with DNS type\n" + " -c --class=CLASS|help Query RR with DNS class\n" + " --service Resolve service (SRV)\n" + " --service-address=BOOL Resolve address for services (default: yes)\n" + " --service-txt=BOOL Resolve TXT records for services (default: yes)\n" + " --openpgp Query OpenPGP public key\n" + " --tlsa Query TLS public key\n" + " --cname=BOOL Follow CNAME redirects (default: yes)\n" + " --search=BOOL Use search domains for single-label names\n" + " (default: yes)\n" + " --raw[=payload|packet] Dump the answer as binary data\n" + " --legend=BOOL Print headers and additional info (default: yes)\n" + " --statistics Show resolver statistics\n" + " --reset-statistics Reset resolver statistics\n" + " --status Show link and server status\n" + " --flush-caches Flush all local DNS caches\n" + " --reset-server-features\n" + " Forget learnt DNS server feature levels\n" + " --set-dns=SERVER Set per-interface DNS server address\n" + " --set-domain=DOMAIN Set per-interface search domain\n" + " --set-llmnr=MODE Set per-interface LLMNR mode\n" + " --set-mdns=MODE Set per-interface MulticastDNS mode\n" + " --set-dnsovertls=MODE Set per-interface DNS-over-TLS mode\n" + " --set-dnssec=MODE Set per-interface DNSSEC mode\n" + " --set-nta=DOMAIN Set per-interface DNSSEC NTA\n" + " --revert Revert per-interface configuration\n" + "\nSee the %4$s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int native_help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("resolvectl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n" + "\n" + "%sSend control commands to the network name resolution manager, or%s\n" + "%sresolve domain names, IPv4 and IPv6 addresses, DNS records, and services.%s\n" + "\nCommands:\n" + " query HOSTNAME|ADDRESS... Resolve domain names, IPv4 and IPv6 addresses\n" + " service [[NAME] TYPE] DOMAIN Resolve service (SRV)\n" + " openpgp EMAIL@DOMAIN... Query OpenPGP public key\n" + " tlsa DOMAIN[:PORT]... Query TLS public key\n" + " status [LINK...] Show link and server status\n" + " statistics Show resolver statistics\n" + " reset-statistics Reset resolver statistics\n" + " flush-caches Flush all local DNS caches\n" + " reset-server-features Forget learnt DNS server feature levels\n" + " dns [LINK [SERVER...]] Get/set per-interface DNS server address\n" + " domain [LINK [DOMAIN...]] Get/set per-interface search domain\n" + " default-route [LINK [BOOL]] Get/set per-interface default route flag\n" + " llmnr [LINK [MODE]] Get/set per-interface LLMNR mode\n" + " mdns [LINK [MODE]] Get/set per-interface MulticastDNS mode\n" + " dnsovertls [LINK [MODE]] Get/set per-interface DNS-over-TLS mode\n" + " dnssec [LINK [MODE]] Get/set per-interface DNSSEC mode\n" + " nta [LINK [DOMAIN...]] Get/set per-interface DNSSEC NTA\n" + " revert LINK Revert per-interface configuration\n" + "\nOptions:\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " -4 Resolve IPv4 addresses\n" + " -6 Resolve IPv6 addresses\n" + " -i --interface=INTERFACE Look on interface\n" + " -p --protocol=PROTO|help Look via protocol\n" + " -t --type=TYPE|help Query RR with DNS type\n" + " -c --class=CLASS|help Query RR with DNS class\n" + " --service-address=BOOL Resolve address for services (default: yes)\n" + " --service-txt=BOOL Resolve TXT records for services (default: yes)\n" + " --cname=BOOL Follow CNAME redirects (default: yes)\n" + " --search=BOOL Use search domains for single-label names\n" + " (default: yes)\n" + " --raw[=payload|packet] Dump the answer as binary data\n" + " --legend=BOOL Print headers and additional info (default: yes)\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int verb_help(int argc, char **argv, void *userdata) { + return native_help(); +} + +static int compat_parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_LEGEND, + ARG_SERVICE, + ARG_CNAME, + ARG_SERVICE_ADDRESS, + ARG_SERVICE_TXT, + ARG_OPENPGP, + ARG_TLSA, + ARG_RAW, + ARG_SEARCH, + ARG_STATISTICS, + ARG_RESET_STATISTICS, + ARG_STATUS, + ARG_FLUSH_CACHES, + ARG_RESET_SERVER_FEATURES, + ARG_NO_PAGER, + ARG_SET_DNS, + ARG_SET_DOMAIN, + ARG_SET_LLMNR, + ARG_SET_MDNS, + ARG_SET_PRIVATE, + ARG_SET_DNSSEC, + ARG_SET_NTA, + ARG_REVERT_LINK, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "type", required_argument, NULL, 't' }, + { "class", required_argument, NULL, 'c' }, + { "legend", required_argument, NULL, ARG_LEGEND }, + { "interface", required_argument, NULL, 'i' }, + { "protocol", required_argument, NULL, 'p' }, + { "cname", required_argument, NULL, ARG_CNAME }, + { "service", no_argument, NULL, ARG_SERVICE }, + { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS }, + { "service-txt", required_argument, NULL, ARG_SERVICE_TXT }, + { "openpgp", no_argument, NULL, ARG_OPENPGP }, + { "tlsa", optional_argument, NULL, ARG_TLSA }, + { "raw", optional_argument, NULL, ARG_RAW }, + { "search", required_argument, NULL, ARG_SEARCH }, + { "statistics", no_argument, NULL, ARG_STATISTICS, }, + { "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS }, + { "status", no_argument, NULL, ARG_STATUS }, + { "flush-caches", no_argument, NULL, ARG_FLUSH_CACHES }, + { "reset-server-features", no_argument, NULL, ARG_RESET_SERVER_FEATURES }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "set-dns", required_argument, NULL, ARG_SET_DNS }, + { "set-domain", required_argument, NULL, ARG_SET_DOMAIN }, + { "set-llmnr", required_argument, NULL, ARG_SET_LLMNR }, + { "set-mdns", required_argument, NULL, ARG_SET_MDNS }, + { "set-dnsovertls", required_argument, NULL, ARG_SET_PRIVATE }, + { "set-dnssec", required_argument, NULL, ARG_SET_DNSSEC }, + { "set-nta", required_argument, NULL, ARG_SET_NTA }, + { "revert", no_argument, NULL, ARG_REVERT_LINK }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0) + switch(c) { + + case 'h': + return compat_help(); + + case ARG_VERSION: + return version(); + + case '4': + arg_family = AF_INET; + break; + + case '6': + arg_family = AF_INET6; + break; + + case 'i': + r = ifname_mangle(optarg); + if (r < 0) + return r; + break; + + case 't': + if (streq(optarg, "help")) { + help_dns_types(); + return 0; + } + + r = dns_type_from_string(optarg); + if (r < 0) { + log_error("Failed to parse RR record type %s", optarg); + return r; + } + arg_type = (uint16_t) r; + assert((int) arg_type == r); + + arg_mode = MODE_RESOLVE_RECORD; + break; + + case 'c': + if (streq(optarg, "help")) { + help_dns_classes(); + return 0; + } + + r = dns_class_from_string(optarg); + if (r < 0) { + log_error("Failed to parse RR record class %s", optarg); + return r; + } + arg_class = (uint16_t) r; + assert((int) arg_class == r); + + break; + + case ARG_LEGEND: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --legend= argument"); + + arg_legend = r; + break; + + case 'p': + if (streq(optarg, "help")) { + help_protocol_types(); + return 0; + } else if (streq(optarg, "dns")) + arg_flags |= SD_RESOLVED_DNS; + else if (streq(optarg, "llmnr")) + arg_flags |= SD_RESOLVED_LLMNR; + else if (streq(optarg, "llmnr-ipv4")) + arg_flags |= SD_RESOLVED_LLMNR_IPV4; + else if (streq(optarg, "llmnr-ipv6")) + arg_flags |= SD_RESOLVED_LLMNR_IPV6; + else if (streq(optarg, "mdns")) + arg_flags |= SD_RESOLVED_MDNS; + else if (streq(optarg, "mdns-ipv4")) + arg_flags |= SD_RESOLVED_MDNS_IPV4; + else if (streq(optarg, "mdns-ipv6")) + arg_flags |= SD_RESOLVED_MDNS_IPV6; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown protocol specifier: %s", optarg); + + break; + + case ARG_SERVICE: + arg_mode = MODE_RESOLVE_SERVICE; + break; + + case ARG_OPENPGP: + arg_mode = MODE_RESOLVE_OPENPGP; + break; + + case ARG_TLSA: + arg_mode = MODE_RESOLVE_TLSA; + if (!optarg || service_family_is_valid(optarg)) + arg_service_family = optarg; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown service family \"%s\".", optarg); + break; + + case ARG_RAW: + if (on_tty()) + return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), + "Refusing to write binary data to tty."); + + if (optarg == NULL || streq(optarg, "payload")) + arg_raw = RAW_PAYLOAD; + else if (streq(optarg, "packet")) + arg_raw = RAW_PACKET; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown --raw specifier \"%s\".", + optarg); + + arg_legend = false; + break; + + case ARG_CNAME: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --cname= argument."); + SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0); + break; + + case ARG_SERVICE_ADDRESS: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --service-address= argument."); + SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0); + break; + + case ARG_SERVICE_TXT: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --service-txt= argument."); + SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0); + break; + + case ARG_SEARCH: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --search argument."); + SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0); + break; + + case ARG_STATISTICS: + arg_mode = MODE_STATISTICS; + break; + + case ARG_RESET_STATISTICS: + arg_mode = MODE_RESET_STATISTICS; + break; + + case ARG_FLUSH_CACHES: + arg_mode = MODE_FLUSH_CACHES; + break; + + case ARG_RESET_SERVER_FEATURES: + arg_mode = MODE_RESET_SERVER_FEATURES; + break; + + case ARG_STATUS: + arg_mode = MODE_STATUS; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_SET_DNS: + r = strv_extend(&arg_set_dns, optarg); + if (r < 0) + return log_oom(); + + arg_mode = MODE_SET_LINK; + break; + + case ARG_SET_DOMAIN: + r = strv_extend(&arg_set_domain, optarg); + if (r < 0) + return log_oom(); + + arg_mode = MODE_SET_LINK; + break; + + case ARG_SET_LLMNR: + arg_set_llmnr = optarg; + arg_mode = MODE_SET_LINK; + break; + + case ARG_SET_MDNS: + arg_set_mdns = optarg; + arg_mode = MODE_SET_LINK; + break; + + case ARG_SET_PRIVATE: + arg_set_dns_over_tls = optarg; + arg_mode = MODE_SET_LINK; + break; + + case ARG_SET_DNSSEC: + arg_set_dnssec = optarg; + arg_mode = MODE_SET_LINK; + break; + + case ARG_SET_NTA: + r = strv_extend(&arg_set_nta, optarg); + if (r < 0) + return log_oom(); + + arg_mode = MODE_SET_LINK; + break; + + case ARG_REVERT_LINK: + arg_mode = MODE_REVERT_LINK; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_type == 0 && arg_class != 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--class= may only be used in conjunction with --type=."); + + if (arg_type != 0 && arg_mode == MODE_RESOLVE_SERVICE) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--service and --type= may not be combined."); + + if (arg_type != 0 && arg_class == 0) + arg_class = DNS_CLASS_IN; + + if (arg_class != 0 && arg_type == 0) + arg_type = DNS_TYPE_A; + + if (IN_SET(arg_mode, MODE_SET_LINK, MODE_REVERT_LINK)) { + + if (arg_ifindex <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnsovertls=, --set-dnssec=, --set-nta= and --revert require --interface=."); + } + + return 1 /* work to do */; +} + +static int native_parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + ARG_LEGEND, + ARG_CNAME, + ARG_SERVICE_ADDRESS, + ARG_SERVICE_TXT, + ARG_RAW, + ARG_SEARCH, + ARG_NO_PAGER, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "type", required_argument, NULL, 't' }, + { "class", required_argument, NULL, 'c' }, + { "legend", required_argument, NULL, ARG_LEGEND }, + { "interface", required_argument, NULL, 'i' }, + { "protocol", required_argument, NULL, 'p' }, + { "cname", required_argument, NULL, ARG_CNAME }, + { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS }, + { "service-txt", required_argument, NULL, ARG_SERVICE_TXT }, + { "raw", optional_argument, NULL, ARG_RAW }, + { "search", required_argument, NULL, ARG_SEARCH }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0) + switch(c) { + + case 'h': + return native_help(); + + case ARG_VERSION: + return version(); + + case '4': + arg_family = AF_INET; + break; + + case '6': + arg_family = AF_INET6; + break; + + case 'i': + r = ifname_mangle(optarg); + if (r < 0) + return r; + break; + + case 't': + if (streq(optarg, "help")) { + help_dns_types(); + return 0; + } + + r = dns_type_from_string(optarg); + if (r < 0) { + log_error("Failed to parse RR record type %s", optarg); + return r; + } + arg_type = (uint16_t) r; + assert((int) arg_type == r); + + break; + + case 'c': + if (streq(optarg, "help")) { + help_dns_classes(); + return 0; + } + + r = dns_class_from_string(optarg); + if (r < 0) { + log_error("Failed to parse RR record class %s", optarg); + return r; + } + arg_class = (uint16_t) r; + assert((int) arg_class == r); + + break; + + case ARG_LEGEND: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --legend= argument"); + + arg_legend = r; + break; + + case 'p': + if (streq(optarg, "help")) { + help_protocol_types(); + return 0; + } else if (streq(optarg, "dns")) + arg_flags |= SD_RESOLVED_DNS; + else if (streq(optarg, "llmnr")) + arg_flags |= SD_RESOLVED_LLMNR; + else if (streq(optarg, "llmnr-ipv4")) + arg_flags |= SD_RESOLVED_LLMNR_IPV4; + else if (streq(optarg, "llmnr-ipv6")) + arg_flags |= SD_RESOLVED_LLMNR_IPV6; + else if (streq(optarg, "mdns")) + arg_flags |= SD_RESOLVED_MDNS; + else if (streq(optarg, "mdns-ipv4")) + arg_flags |= SD_RESOLVED_MDNS_IPV4; + else if (streq(optarg, "mdns-ipv6")) + arg_flags |= SD_RESOLVED_MDNS_IPV6; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown protocol specifier: %s", + optarg); + + break; + + case ARG_RAW: + if (on_tty()) + return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), + "Refusing to write binary data to tty."); + + if (optarg == NULL || streq(optarg, "payload")) + arg_raw = RAW_PAYLOAD; + else if (streq(optarg, "packet")) + arg_raw = RAW_PACKET; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown --raw specifier \"%s\".", + optarg); + + arg_legend = false; + break; + + case ARG_CNAME: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --cname= argument."); + SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0); + break; + + case ARG_SERVICE_ADDRESS: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --service-address= argument."); + SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0); + break; + + case ARG_SERVICE_TXT: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --service-txt= argument."); + SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0); + break; + + case ARG_SEARCH: + r = parse_boolean(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse --search argument."); + SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0); + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_type == 0 && arg_class != 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--class= may only be used in conjunction with --type=."); + + if (arg_type != 0 && arg_class == 0) + arg_class = DNS_CLASS_IN; + + if (arg_class != 0 && arg_type == 0) + arg_type = DNS_TYPE_A; + + return 1 /* work to do */; +} + +static int native_main(int argc, char *argv[], sd_bus *bus) { + + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, verb_help }, + { "status", VERB_ANY, VERB_ANY, VERB_DEFAULT, verb_status }, + { "query", 2, VERB_ANY, 0, verb_query }, + { "service", 2, 4, 0, verb_service }, + { "openpgp", 2, VERB_ANY, 0, verb_openpgp }, + { "tlsa", 2, VERB_ANY, 0, verb_tlsa }, + { "statistics", VERB_ANY, 1, 0, show_statistics }, + { "reset-statistics", VERB_ANY, 1, 0, reset_statistics }, + { "flush-caches", VERB_ANY, 1, 0, flush_caches }, + { "reset-server-features", VERB_ANY, 1, 0, reset_server_features }, + { "dns", VERB_ANY, VERB_ANY, 0, verb_dns }, + { "domain", VERB_ANY, VERB_ANY, 0, verb_domain }, + { "default-route", VERB_ANY, 3, 0, verb_default_route }, + { "llmnr", VERB_ANY, 3, 0, verb_llmnr }, + { "mdns", VERB_ANY, 3, 0, verb_mdns }, + { "dnsovertls", VERB_ANY, 3, 0, verb_dns_over_tls }, + { "dnssec", VERB_ANY, 3, 0, verb_dnssec }, + { "nta", VERB_ANY, VERB_ANY, 0, verb_nta }, + { "revert", VERB_ANY, 2, 0, verb_revert_link }, + {} + }; + + return dispatch_verb(argc, argv, verbs, bus); +} + +static int translate(const char *verb, const char *single_arg, size_t num_args, char **args, sd_bus *bus) { + char **fake, **p; + size_t num, i; + + assert(verb); + assert(num_args == 0 || args); + + num = !!single_arg + num_args + 1; + + p = fake = newa0(char *, num + 1); + *p++ = (char *) verb; + if (single_arg) + *p++ = (char *) single_arg; + for (i = 0; i < num_args; i++) + *p++ = args[i]; + + optind = 0; + return native_main((int) num, fake, bus); +} + +static int compat_main(int argc, char *argv[], sd_bus *bus) { + int r = 0; + + switch (arg_mode) { + case MODE_RESOLVE_HOST: + case MODE_RESOLVE_RECORD: + return translate("query", NULL, argc - optind, argv + optind, bus); + + case MODE_RESOLVE_SERVICE: + return translate("service", NULL, argc - optind, argv + optind, bus); + + case MODE_RESOLVE_OPENPGP: + return translate("openpgp", NULL, argc - optind, argv + optind, bus); + + case MODE_RESOLVE_TLSA: + return translate("tlsa", arg_service_family, argc - optind, argv + optind, bus); + + case MODE_STATISTICS: + return translate("statistics", NULL, 0, NULL, bus); + + case MODE_RESET_STATISTICS: + return translate("reset-statistics", NULL, 0, NULL, bus); + + case MODE_FLUSH_CACHES: + return translate("flush-caches", NULL, 0, NULL, bus); + + case MODE_RESET_SERVER_FEATURES: + return translate("reset-server-features", NULL, 0, NULL, bus); + + case MODE_STATUS: + return translate("status", NULL, argc - optind, argv + optind, bus); + + case MODE_SET_LINK: + assert(arg_ifname); + + if (arg_set_dns) { + r = translate("dns", arg_ifname, strv_length(arg_set_dns), arg_set_dns, bus); + if (r < 0) + return r; + } + + if (arg_set_domain) { + r = translate("domain", arg_ifname, strv_length(arg_set_domain), arg_set_domain, bus); + if (r < 0) + return r; + } + + if (arg_set_nta) { + r = translate("nta", arg_ifname, strv_length(arg_set_nta), arg_set_nta, bus); + if (r < 0) + return r; + } + + if (arg_set_llmnr) { + r = translate("llmnr", arg_ifname, 1, (char **) &arg_set_llmnr, bus); + if (r < 0) + return r; + } + + if (arg_set_mdns) { + r = translate("mdns", arg_ifname, 1, (char **) &arg_set_mdns, bus); + if (r < 0) + return r; + } + + if (arg_set_dns_over_tls) { + r = translate("dnsovertls", arg_ifname, 1, (char **) &arg_set_dns_over_tls, bus); + if (r < 0) + return r; + } + + if (arg_set_dnssec) { + r = translate("dnssec", arg_ifname, 1, (char **) &arg_set_dnssec, bus); + if (r < 0) + return r; + } + + return r; + + case MODE_REVERT_LINK: + assert(arg_ifname); + + return translate("revert", arg_ifname, 0, NULL, bus); + + case _MODE_INVALID: + assert_not_reached("invalid mode"); + } + + return 0; +} + +static int run(int argc, char **argv) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + setlocale(LC_ALL, ""); + log_show_color(true); + log_parse_environment(); + log_open(); + + if (streq(program_invocation_short_name, "resolvconf")) + r = resolvconf_parse_argv(argc, argv); + else if (streq(program_invocation_short_name, "systemd-resolve")) + r = compat_parse_argv(argc, argv); + else + r = native_parse_argv(argc, argv); + if (r <= 0) + return r; + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_error_errno(r, "sd_bus_open_system: %m"); + + if (STR_IN_SET(program_invocation_short_name, "systemd-resolve", "resolvconf")) + return compat_main(argc, argv, bus); + + return native_main(argc, argv, bus); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/resolve/resolvectl.h b/src/resolve/resolvectl.h new file mode 100644 index 00000000..6b3a1f84 --- /dev/null +++ b/src/resolve/resolvectl.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +typedef enum ExecutionMode { + MODE_RESOLVE_HOST, + MODE_RESOLVE_RECORD, + MODE_RESOLVE_SERVICE, + MODE_RESOLVE_OPENPGP, + MODE_RESOLVE_TLSA, + MODE_STATISTICS, + MODE_RESET_STATISTICS, + MODE_FLUSH_CACHES, + MODE_RESET_SERVER_FEATURES, + MODE_STATUS, + MODE_SET_LINK, + MODE_REVERT_LINK, + _MODE_INVALID = -1, +} ExecutionMode; + +extern ExecutionMode arg_mode; +extern char **arg_set_dns; +extern char **arg_set_domain; +extern bool arg_ifindex_permissive; + +int ifname_mangle(const char *s); diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c new file mode 100644 index 00000000..a2712610 --- /dev/null +++ b/src/resolve/resolved-bus.c @@ -0,0 +1,1969 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "dns-domain.h" +#include "memory-util.h" +#include "missing_capability.h" +#include "resolved-bus.h" +#include "resolved-def.h" +#include "resolved-dns-synthesize.h" +#include "resolved-dnssd-bus.h" +#include "resolved-dnssd.h" +#include "resolved-link-bus.h" +#include "stdio-util.h" +#include "strv.h" +#include "user-util.h" +#include "utf8.h" + +BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_resolve_support, resolve_support, ResolveSupport); + +static int reply_query_state(DnsQuery *q) { + + switch (q->state) { + + case DNS_TRANSACTION_NO_SERVERS: + return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found"); + + case DNS_TRANSACTION_TIMEOUT: + return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out"); + + case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED: + return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed"); + + case DNS_TRANSACTION_INVALID_REPLY: + return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply"); + + case DNS_TRANSACTION_ERRNO: + return sd_bus_reply_method_errnof(q->request, q->answer_errno, "Lookup failed due to system error: %m"); + + case DNS_TRANSACTION_ABORTED: + return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted"); + + case DNS_TRANSACTION_DNSSEC_FAILED: + return sd_bus_reply_method_errorf(q->request, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s", + dnssec_result_to_string(q->answer_dnssec_result)); + + case DNS_TRANSACTION_NO_TRUST_ANCHOR: + return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known"); + + case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED: + return sd_bus_reply_method_errorf(q->request, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type"); + + case DNS_TRANSACTION_NETWORK_DOWN: + return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NETWORK_DOWN, "Network is down"); + + case DNS_TRANSACTION_NOT_FOUND: + /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we + * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */ + return sd_bus_reply_method_errorf(q->request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q)); + + case DNS_TRANSACTION_RCODE_FAILURE: { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + if (q->answer_rcode == DNS_RCODE_NXDOMAIN) + sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q)); + else { + const char *rc, *n; + char p[DECIMAL_STR_MAX(q->answer_rcode)]; + + rc = dns_rcode_to_string(q->answer_rcode); + if (!rc) { + xsprintf(p, "%i", q->answer_rcode); + rc = p; + } + + n = strjoina(_BUS_ERROR_DNS, rc); + sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", dns_query_string(q), rc); + } + + return sd_bus_reply_method_error(q->request, &error); + } + + case DNS_TRANSACTION_NULL: + case DNS_TRANSACTION_PENDING: + case DNS_TRANSACTION_VALIDATING: + case DNS_TRANSACTION_SUCCESS: + default: + assert_not_reached("Impossible state"); + } +} + +static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) { + int r; + + assert(reply); + assert(rr); + + r = sd_bus_message_open_container(reply, 'r', "iiay"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "i", ifindex); + if (r < 0) + return r; + + if (rr->key->type == DNS_TYPE_A) { + r = sd_bus_message_append(reply, "i", AF_INET); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr)); + + } else if (rr->key->type == DNS_TYPE_AAAA) { + r = sd_bus_message_append(reply, "i", AF_INET6); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr)); + } else + return -EAFNOSUPPORT; + + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return 0; +} + +static void bus_method_resolve_hostname_complete(DnsQuery *q) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *normalized = NULL; + DnsResourceRecord *rr; + unsigned added = 0; + int ifindex, r; + + assert(q); + + if (q->state != DNS_TRANSACTION_SUCCESS) { + r = reply_query_state(q); + goto finish; + } + + r = dns_query_process_cname(q); + if (r == -ELOOP) { + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); + goto finish; + } + if (r < 0) + goto finish; + if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ + return; + + r = sd_bus_message_new_method_return(q->request, &reply); + if (r < 0) + goto finish; + + r = sd_bus_message_open_container(reply, 'a', "(iiay)"); + if (r < 0) + goto finish; + + DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { + DnsQuestion *question; + + question = dns_query_question_for_protocol(q, q->answer_protocol); + + r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); + if (r < 0) + goto finish; + if (r == 0) + continue; + + r = append_address(reply, rr, ifindex); + if (r < 0) + goto finish; + + if (!canonical) + canonical = dns_resource_record_ref(rr); + + added++; + } + + if (added <= 0) { + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); + goto finish; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + goto finish; + + /* The key names are not necessarily normalized, make sure that they are when we return them to our bus + * clients. */ + r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized); + if (r < 0) + goto finish; + + /* Return the precise spelling and uppercasing and CNAME target reported by the server */ + assert(canonical); + r = sd_bus_message_append( + reply, "st", + normalized, + SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))); + if (r < 0) + goto finish; + + r = sd_bus_send(q->manager->bus, reply, NULL); + +finish: + if (r < 0) { + log_error_errno(r, "Failed to send hostname reply: %m"); + sd_bus_reply_method_errno(q->request, r, NULL); + } + + dns_query_free(q); +} + +static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) { + assert(flags); + + if (ifindex < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index"); + + if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter"); + + if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */ + *flags |= SD_RESOLVED_PROTOCOLS_ALL; + + return 0; +} + +static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname, int family, uint64_t flags) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *canonical = NULL; + union in_addr_union parsed; + int r, ff, parsed_ifindex = 0; + + /* Check if the hostname is actually already an IP address formatted as string. In that case just parse it, + * let's not attempt to look it up. */ + + r = in_addr_ifindex_from_string_auto(hostname, &ff, &parsed, &parsed_ifindex); + if (r < 0) /* not an address */ + return 0; + + if (family != AF_UNSPEC && ff != family) + return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address is not of the requested family."); + if (ifindex > 0 && parsed_ifindex > 0 && parsed_ifindex != ifindex) + return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address interface index does not match requested interface."); + + if (parsed_ifindex > 0) + ifindex = parsed_ifindex; + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(iiay)"); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'r', "iiay"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "ii", ifindex, ff); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', &parsed, FAMILY_ADDRESS_SIZE(ff)); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + /* When an IP address is specified we just return it as canonical name, in order to avoid a DNS + * look-up. However, we reformat it to make sure it's in a truly canonical form (i.e. on IPv6 the inner + * omissions are always done the same way). */ + r = in_addr_ifindex_to_string(ff, &parsed, ifindex, &canonical); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "st", canonical, + SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true)); + if (r < 0) + return r; + + return sd_bus_send(sd_bus_message_get_bus(m), reply, NULL); +} + +static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL; + Manager *m = userdata; + const char *hostname; + int family, ifindex; + uint64_t flags; + DnsQuery *q; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(int) == sizeof(int32_t)); + + r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags); + if (r < 0) + return r; + + if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); + + r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error); + if (r < 0) + return r; + + r = parse_as_address(message, ifindex, hostname, family, flags); + if (r != 0) + return r; + + r = dns_name_is_valid(hostname); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname); + + r = dns_question_new_address(&question_utf8, family, hostname, false); + if (r < 0) + return r; + + r = dns_question_new_address(&question_idna, family, hostname, true); + if (r < 0 && r != -EALREADY) + return r; + + r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, ifindex, flags); + if (r < 0) + return r; + + q->request = sd_bus_message_ref(message); + q->request_family = family; + q->complete = bus_method_resolve_hostname_complete; + q->suppress_unroutable_family = family == AF_UNSPEC; + + r = dns_query_bus_track(q, message); + if (r < 0) + goto fail; + + r = dns_query_go(q); + if (r < 0) + goto fail; + + return 1; + +fail: + dns_query_free(q); + return r; +} + +static void bus_method_resolve_address_complete(DnsQuery *q) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + DnsQuestion *question; + DnsResourceRecord *rr; + unsigned added = 0; + int ifindex, r; + + assert(q); + + if (q->state != DNS_TRANSACTION_SUCCESS) { + r = reply_query_state(q); + goto finish; + } + + r = dns_query_process_cname(q); + if (r == -ELOOP) { + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); + goto finish; + } + if (r < 0) + goto finish; + if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ + return; + + r = sd_bus_message_new_method_return(q->request, &reply); + if (r < 0) + goto finish; + + r = sd_bus_message_open_container(reply, 'a', "(is)"); + if (r < 0) + goto finish; + + question = dns_query_question_for_protocol(q, q->answer_protocol); + + DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { + _cleanup_free_ char *normalized = NULL; + + r = dns_question_matches_rr(question, rr, NULL); + if (r < 0) + goto finish; + if (r == 0) + continue; + + r = dns_name_normalize(rr->ptr.name, 0, &normalized); + if (r < 0) + goto finish; + + r = sd_bus_message_append(reply, "(is)", ifindex, normalized); + if (r < 0) + goto finish; + + added++; + } + + if (added <= 0) { + _cleanup_free_ char *ip = NULL; + + (void) in_addr_to_string(q->request_family, &q->request_address, &ip); + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, + "Address '%s' does not have any RR of requested type", strnull(ip)); + goto finish; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + goto finish; + + r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))); + if (r < 0) + goto finish; + + r = sd_bus_send(q->manager->bus, reply, NULL); + +finish: + if (r < 0) { + log_error_errno(r, "Failed to send address reply: %m"); + sd_bus_reply_method_errno(q->request, r, NULL); + } + + dns_query_free(q); +} + +static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; + Manager *m = userdata; + int family, ifindex; + uint64_t flags; + const void *d; + DnsQuery *q; + size_t sz; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(int) == sizeof(int32_t)); + + r = sd_bus_message_read(message, "ii", &ifindex, &family); + if (r < 0) + return r; + + if (!IN_SET(family, AF_INET, AF_INET6)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); + + r = sd_bus_message_read_array(message, 'y', &d, &sz); + if (r < 0) + return r; + + if (sz != FAMILY_ADDRESS_SIZE(family)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size"); + + r = sd_bus_message_read(message, "t", &flags); + if (r < 0) + return r; + + r = check_ifindex_flags(ifindex, &flags, 0, error); + if (r < 0) + return r; + + r = dns_question_new_reverse(&question, family, d); + if (r < 0) + return r; + + r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH); + if (r < 0) + return r; + + q->request = sd_bus_message_ref(message); + q->request_family = family; + memcpy(&q->request_address, d, sz); + q->complete = bus_method_resolve_address_complete; + + r = dns_query_bus_track(q, message); + if (r < 0) + goto fail; + + r = dns_query_go(q); + if (r < 0) + goto fail; + + return 1; + +fail: + dns_query_free(q); + return r; +} + +static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) { + int r; + + assert(m); + assert(rr); + + r = sd_bus_message_open_container(m, 'r', "iqqay"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "iqq", + ifindex, + rr->key->class, + rr->key->type); + if (r < 0) + return r; + + r = dns_resource_record_to_wire_format(rr, false); + if (r < 0) + return r; + + r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size); + if (r < 0) + return r; + + return sd_bus_message_close_container(m); +} + +static void bus_method_resolve_record_complete(DnsQuery *q) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + DnsResourceRecord *rr; + DnsQuestion *question; + unsigned added = 0; + int ifindex; + int r; + + assert(q); + + if (q->state != DNS_TRANSACTION_SUCCESS) { + r = reply_query_state(q); + goto finish; + } + + r = dns_query_process_cname(q); + if (r == -ELOOP) { + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); + goto finish; + } + if (r < 0) + goto finish; + if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ + return; + + r = sd_bus_message_new_method_return(q->request, &reply); + if (r < 0) + goto finish; + + r = sd_bus_message_open_container(reply, 'a', "(iqqay)"); + if (r < 0) + goto finish; + + question = dns_query_question_for_protocol(q, q->answer_protocol); + + DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { + r = dns_question_matches_rr(question, rr, NULL); + if (r < 0) + goto finish; + if (r == 0) + continue; + + r = bus_message_append_rr(reply, rr, ifindex); + if (r < 0) + goto finish; + + added++; + } + + if (added <= 0) { + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", dns_query_string(q)); + goto finish; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + goto finish; + + r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))); + if (r < 0) + goto finish; + + r = sd_bus_send(q->manager->bus, reply, NULL); + +finish: + if (r < 0) { + log_error_errno(r, "Failed to send record reply: %m"); + sd_bus_reply_method_errno(q->request, r, NULL); + } + + dns_query_free(q); +} + +static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; + Manager *m = userdata; + uint16_t class, type; + const char *name; + int r, ifindex; + uint64_t flags; + DnsQuery *q; + + assert(message); + assert(m); + + assert_cc(sizeof(int) == sizeof(int32_t)); + + r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags); + if (r < 0) + return r; + + r = dns_name_is_valid(name); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name); + + if (!dns_type_is_valid_query(type)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified resource record type %" PRIu16 " may not be used in a query.", type); + if (dns_type_is_zone_transer(type)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Zone transfers not permitted via this programming interface."); + if (dns_type_is_obsolete(type)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type); + + r = check_ifindex_flags(ifindex, &flags, 0, error); + if (r < 0) + return r; + + question = dns_question_new(1); + if (!question) + return -ENOMEM; + + key = dns_resource_key_new(class, type, name); + if (!key) + return -ENOMEM; + + r = dns_question_add(question, key); + if (r < 0) + return r; + + r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH); + if (r < 0) + return r; + + /* Let's request that the TTL is fixed up for locally cached entries, after all we return it in the wire format + * blob */ + q->clamp_ttl = true; + + q->request = sd_bus_message_ref(message); + q->complete = bus_method_resolve_record_complete; + + r = dns_query_bus_track(q, message); + if (r < 0) + goto fail; + + r = dns_query_go(q); + if (r < 0) + goto fail; + + return 1; + +fail: + dns_query_free(q); + return r; +} + +static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL; + _cleanup_free_ char *normalized = NULL; + DnsQuery *aux; + int r; + + assert(q); + assert(reply); + assert(rr); + assert(rr->key); + + if (rr->key->type != DNS_TYPE_SRV) + return 0; + + if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) { + /* First, let's see if we could find an appropriate A or AAAA + * record for the SRV record */ + LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) { + DnsResourceRecord *zz; + DnsQuestion *question; + + if (aux->state != DNS_TRANSACTION_SUCCESS) + continue; + if (aux->auxiliary_result != 0) + continue; + + question = dns_query_question_for_protocol(aux, aux->answer_protocol); + + r = dns_name_equal(dns_question_first_name(question), rr->srv.name); + if (r < 0) + return r; + if (r == 0) + continue; + + DNS_ANSWER_FOREACH(zz, aux->answer) { + + r = dns_question_matches_rr(question, zz, NULL); + if (r < 0) + return r; + if (r == 0) + continue; + + canonical = dns_resource_record_ref(zz); + break; + } + + if (canonical) + break; + } + + /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */ + if (!canonical) + return 0; + } + + r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s"); + if (r < 0) + return r; + + r = dns_name_normalize(rr->srv.name, 0, &normalized); + if (r < 0) + return r; + + r = sd_bus_message_append( + reply, + "qqqs", + rr->srv.priority, rr->srv.weight, rr->srv.port, normalized); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "(iiay)"); + if (r < 0) + return r; + + if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) { + LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) { + DnsResourceRecord *zz; + DnsQuestion *question; + int ifindex; + + if (aux->state != DNS_TRANSACTION_SUCCESS) + continue; + if (aux->auxiliary_result != 0) + continue; + + question = dns_query_question_for_protocol(aux, aux->answer_protocol); + + r = dns_name_equal(dns_question_first_name(question), rr->srv.name); + if (r < 0) + return r; + if (r == 0) + continue; + + DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) { + + r = dns_question_matches_rr(question, zz, NULL); + if (r < 0) + return r; + if (r == 0) + continue; + + r = append_address(reply, zz, ifindex); + if (r < 0) + return r; + } + } + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + if (canonical) { + normalized = mfree(normalized); + + r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized); + if (r < 0) + return r; + } + + /* Note that above we appended the hostname as encoded in the + * SRV, and here the canonical hostname this maps to. */ + r = sd_bus_message_append(reply, "s", normalized); + if (r < 0) + return r; + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return 1; +} + +static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) { + DnsTxtItem *i; + int r; + + assert(reply); + assert(rr); + assert(rr->key); + + if (rr->key->type != DNS_TYPE_TXT) + return 0; + + LIST_FOREACH(items, i, rr->txt.items) { + + if (i->length <= 0) + continue; + + r = sd_bus_message_append_array(reply, 'y', i->data, i->length); + if (r < 0) + return r; + } + + return 1; +} + +static void resolve_service_all_complete(DnsQuery *q) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL; + DnsQuestion *question; + DnsResourceRecord *rr; + unsigned added = 0; + DnsQuery *aux; + int r; + + assert(q); + + if (q->block_all_complete > 0) + return; + + if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) { + DnsQuery *bad = NULL; + bool have_success = false; + + LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) { + + switch (aux->state) { + + case DNS_TRANSACTION_PENDING: + /* If an auxiliary query is still pending, let's wait */ + return; + + case DNS_TRANSACTION_SUCCESS: + if (aux->auxiliary_result == 0) + have_success = true; + else + bad = aux; + break; + + default: + bad = aux; + break; + } + } + + if (!have_success) { + /* We can only return one error, hence pick the last error we encountered */ + + assert(bad); + + if (bad->state == DNS_TRANSACTION_SUCCESS) { + assert(bad->auxiliary_result != 0); + + if (bad->auxiliary_result == -ELOOP) { + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad)); + goto finish; + } + + r = bad->auxiliary_result; + goto finish; + } + + r = reply_query_state(bad); + goto finish; + } + } + + r = sd_bus_message_new_method_return(q->request, &reply); + if (r < 0) + goto finish; + + r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)"); + if (r < 0) + goto finish; + + question = dns_query_question_for_protocol(q, q->answer_protocol); + DNS_ANSWER_FOREACH(rr, q->answer) { + r = dns_question_matches_rr(question, rr, NULL); + if (r < 0) + goto finish; + if (r == 0) + continue; + + r = append_srv(q, reply, rr); + if (r < 0) + goto finish; + if (r == 0) /* not an SRV record */ + continue; + + if (!canonical) + canonical = dns_resource_record_ref(rr); + + added++; + } + + if (added <= 0) { + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); + goto finish; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + goto finish; + + r = sd_bus_message_open_container(reply, 'a', "ay"); + if (r < 0) + goto finish; + + DNS_ANSWER_FOREACH(rr, q->answer) { + r = dns_question_matches_rr(question, rr, NULL); + if (r < 0) + goto finish; + if (r == 0) + continue; + + r = append_txt(reply, rr); + if (r < 0) + goto finish; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + goto finish; + + assert(canonical); + r = dns_service_split(dns_resource_key_name(canonical->key), &name, &type, &domain); + if (r < 0) + goto finish; + + r = sd_bus_message_append( + reply, + "ssst", + name, type, domain, + SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))); + if (r < 0) + goto finish; + + r = sd_bus_send(q->manager->bus, reply, NULL); + +finish: + if (r < 0) { + log_error_errno(r, "Failed to send service reply: %m"); + sd_bus_reply_method_errno(q->request, r, NULL); + } + + dns_query_free(q); +} + +static void resolve_service_hostname_complete(DnsQuery *q) { + int r; + + assert(q); + assert(q->auxiliary_for); + + if (q->state != DNS_TRANSACTION_SUCCESS) { + resolve_service_all_complete(q->auxiliary_for); + return; + } + + r = dns_query_process_cname(q); + if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ + return; + + /* This auxiliary lookup is finished or failed, let's see if all are finished now. */ + q->auxiliary_result = r; + resolve_service_all_complete(q->auxiliary_for); +} + +static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) { + _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; + DnsQuery *aux; + int r; + + assert(q); + assert(rr); + assert(rr->key); + assert(rr->key->type == DNS_TYPE_SRV); + + /* OK, we found an SRV record for the service. Let's resolve + * the hostname included in it */ + + r = dns_question_new_address(&question, q->request_family, rr->srv.name, false); + if (r < 0) + return r; + + r = dns_query_new(q->manager, &aux, question, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH); + if (r < 0) + return r; + + aux->request_family = q->request_family; + aux->complete = resolve_service_hostname_complete; + + r = dns_query_make_auxiliary(aux, q); + if (r == -EAGAIN) { + /* Too many auxiliary lookups? If so, don't complain, + * let's just not add this one, we already have more + * than enough */ + + dns_query_free(aux); + return 0; + } + if (r < 0) + goto fail; + + /* Note that auxiliary queries do not track the original bus + * client, only the primary request does that. */ + + r = dns_query_go(aux); + if (r < 0) + goto fail; + + return 1; + +fail: + dns_query_free(aux); + return r; +} + +static void bus_method_resolve_service_complete(DnsQuery *q) { + bool has_root_domain = false; + DnsResourceRecord *rr; + DnsQuestion *question; + unsigned found = 0; + int ifindex, r; + + assert(q); + + if (q->state != DNS_TRANSACTION_SUCCESS) { + r = reply_query_state(q); + goto finish; + } + + r = dns_query_process_cname(q); + if (r == -ELOOP) { + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q)); + goto finish; + } + if (r < 0) + goto finish; + if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */ + return; + + question = dns_query_question_for_protocol(q, q->answer_protocol); + + DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) { + r = dns_question_matches_rr(question, rr, NULL); + if (r < 0) + goto finish; + if (r == 0) + continue; + + if (rr->key->type != DNS_TYPE_SRV) + continue; + + if (dns_name_is_root(rr->srv.name)) { + has_root_domain = true; + continue; + } + + if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) { + q->block_all_complete++; + r = resolve_service_hostname(q, rr, ifindex); + q->block_all_complete--; + + if (r < 0) + goto finish; + } + + found++; + } + + if (has_root_domain && found <= 0) { + /* If there's exactly one SRV RR and it uses + * the root domain as host name, then the + * service is explicitly not offered on the + * domain. Report this as a recognizable + * error. See RFC 2782, Section "Usage + * Rules". */ + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_query_string(q)); + goto finish; + } + + if (found <= 0) { + r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q)); + goto finish; + } + + /* Maybe we are already finished? check now... */ + resolve_service_all_complete(q); + return; + +finish: + if (r < 0) { + log_error_errno(r, "Failed to send service reply: %m"); + sd_bus_reply_method_errno(q->request, r, NULL); + } + + dns_query_free(q); +} + +static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL; + const char *name, *type, *domain; + Manager *m = userdata; + int family, ifindex; + uint64_t flags; + DnsQuery *q; + int r; + + assert(message); + assert(m); + + assert_cc(sizeof(int) == sizeof(int32_t)); + + r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags); + if (r < 0) + return r; + + if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); + + if (isempty(name)) + name = NULL; + else if (!dns_service_name_is_valid(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name); + + if (isempty(type)) + type = NULL; + else if (!dns_srv_type_is_valid(type)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type); + + r = dns_name_is_valid(domain); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain); + + if (name && !type) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type."); + + r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error); + if (r < 0) + return r; + + r = dns_question_new_service(&question_utf8, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), false); + if (r < 0) + return r; + + r = dns_question_new_service(&question_idna, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), true); + if (r < 0) + return r; + + r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags|SD_RESOLVED_NO_SEARCH); + if (r < 0) + return r; + + q->request = sd_bus_message_ref(message); + q->request_family = family; + q->complete = bus_method_resolve_service_complete; + + r = dns_query_bus_track(q, message); + if (r < 0) + goto fail; + + r = dns_query_go(q); + if (r < 0) + goto fail; + + return 1; + +fail: + dns_query_free(q); + return r; +} + +int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex) { + int r; + + assert(reply); + + if (!s) { + if (with_ifindex) + return sd_bus_message_append(reply, "(iiay)", 0, AF_UNSPEC, 0); + else + return sd_bus_message_append(reply, "(iay)", AF_UNSPEC, 0); + } + + r = sd_bus_message_open_container(reply, 'r', with_ifindex ? "iiay" : "iay"); + if (r < 0) + return r; + + if (with_ifindex) { + r = sd_bus_message_append(reply, "i", dns_server_ifindex(s)); + if (r < 0) + return r; + } + + r = sd_bus_message_append(reply, "i", s->family); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family)); + if (r < 0) + return r; + + return sd_bus_message_close_container(reply); +} + +static int bus_property_get_dns_servers( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + DnsServer *s; + Iterator i; + Link *l; + int r; + + assert(reply); + assert(m); + + r = sd_bus_message_open_container(reply, 'a', "(iiay)"); + if (r < 0) + return r; + + LIST_FOREACH(servers, s, m->dns_servers) { + r = bus_dns_server_append(reply, s, true); + if (r < 0) + return r; + } + + HASHMAP_FOREACH(l, m->links, i) + LIST_FOREACH(servers, s, l->dns_servers) { + r = bus_dns_server_append(reply, s, true); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int bus_property_get_fallback_dns_servers( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + DnsServer *s, **f = userdata; + int r; + + assert(reply); + assert(f); + + r = sd_bus_message_open_container(reply, 'a', "(iiay)"); + if (r < 0) + return r; + + LIST_FOREACH(servers, s, *f) { + r = bus_dns_server_append(reply, s, true); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int bus_property_get_current_dns_server( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + DnsServer *s; + + assert(reply); + assert(userdata); + + s = *(DnsServer **) userdata; + + return bus_dns_server_append(reply, s, true); +} + +static int bus_property_get_domains( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + DnsSearchDomain *d; + Iterator i; + Link *l; + int r; + + assert(reply); + assert(m); + + r = sd_bus_message_open_container(reply, 'a', "(isb)"); + if (r < 0) + return r; + + LIST_FOREACH(domains, d, m->search_domains) { + r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only); + if (r < 0) + return r; + } + + HASHMAP_FOREACH(l, m->links, i) { + LIST_FOREACH(domains, d, l->search_domains) { + r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only); + if (r < 0) + return r; + } + } + + return sd_bus_message_close_container(reply); +} + +static int bus_property_get_transaction_statistics( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(reply); + assert(m); + + return sd_bus_message_append(reply, "(tt)", + (uint64_t) hashmap_size(m->dns_transactions), + (uint64_t) m->n_transactions_total); +} + +static int bus_property_get_cache_statistics( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + uint64_t size = 0, hit = 0, miss = 0; + Manager *m = userdata; + DnsScope *s; + + assert(reply); + assert(m); + + LIST_FOREACH(scopes, s, m->dns_scopes) { + size += dns_cache_size(&s->cache); + hit += s->cache.n_hit; + miss += s->cache.n_miss; + } + + return sd_bus_message_append(reply, "(ttt)", size, hit, miss); +} + +static int bus_property_get_dnssec_statistics( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + + assert(reply); + assert(m); + + return sd_bus_message_append(reply, "(tttt)", + (uint64_t) m->n_dnssec_verdict[DNSSEC_SECURE], + (uint64_t) m->n_dnssec_verdict[DNSSEC_INSECURE], + (uint64_t) m->n_dnssec_verdict[DNSSEC_BOGUS], + (uint64_t) m->n_dnssec_verdict[DNSSEC_INDETERMINATE]); +} + +static int bus_property_get_ntas( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + const char *domain; + Iterator i; + int r; + + assert(reply); + assert(m); + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + SET_FOREACH(domain, m->trust_anchor.negative_by_name, i) { + r = sd_bus_message_append(reply, "s", domain); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode); +static BUS_DEFINE_PROPERTY_GET(bus_property_get_dnssec_supported, "b", Manager, manager_dnssec_supported); +static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode, "s", Manager, manager_get_dnssec_mode, dnssec_mode_to_string); +static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dns_over_tls_mode, "s", Manager, manager_get_dns_over_tls_mode, dns_over_tls_mode_to_string); + +static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + DnsScope *s; + + assert(message); + assert(m); + + LIST_FOREACH(scopes, s, m->dns_scopes) + s->cache.n_hit = s->cache.n_miss = 0; + + m->n_transactions_total = 0; + zero(m->n_dnssec_verdict); + + return sd_bus_reply_method_return(message, NULL); +} + +static int get_any_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) { + Link *l; + + assert(m); + assert(ret); + + if (ifindex <= 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index"); + + l = hashmap_get(m->links, INT_TO_PTR(ifindex)); + if (!l) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex); + + *ret = l; + return 0; +} + +static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) { + int ifindex, r; + Link *l; + + assert(m); + assert(message); + assert(handler); + + assert_cc(sizeof(int) == sizeof(int32_t)); + r = sd_bus_message_read(message, "i", &ifindex); + if (r < 0) + return r; + + r = get_any_link(m, ifindex, &l, error); + if (r < 0) + return r; + + return handler(message, l, error); +} + +static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_dns_servers, error); +} + +static int bus_method_set_link_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_domains, error); +} + +static int bus_method_set_link_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_default_route, error); +} + +static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_llmnr, error); +} + +static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_mdns, error); +} + +static int bus_method_set_link_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_dns_over_tls, error); +} + +static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_dnssec, error); +} + +static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error); +} + +static int bus_method_revert_link(sd_bus_message *message, void *userdata, sd_bus_error *error) { + return call_link_method(userdata, message, bus_link_method_revert, error); +} + +static int bus_method_get_link(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *p = NULL; + Manager *m = userdata; + int r, ifindex; + Link *l; + + assert(message); + assert(m); + + assert_cc(sizeof(int) == sizeof(int32_t)); + r = sd_bus_message_read(message, "i", &ifindex); + if (r < 0) + return r; + + r = get_any_link(m, ifindex, &l, error); + if (r < 0) + return r; + + p = link_bus_path(l); + if (!p) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", p); +} + +static int bus_method_flush_caches(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + assert(message); + assert(m); + + manager_flush_caches(m); + + return sd_bus_reply_method_return(message, NULL); +} + +static int bus_method_reset_server_features(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + assert(message); + assert(m); + + manager_reset_server_features(m); + + return sd_bus_reply_method_return(message, NULL); +} + +static int on_bus_track(sd_bus_track *t, void *userdata) { + DnssdService *s = userdata; + + assert(t); + assert(s); + + log_debug("Client of active request vanished, destroying DNS-SD service."); + dnssd_service_free(s); + + return 0; +} + +static int bus_method_register_service(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + _cleanup_(dnssd_service_freep) DnssdService *service = NULL; + _cleanup_(sd_bus_track_unrefp) sd_bus_track *bus_track = NULL; + _cleanup_free_ char *path = NULL; + _cleanup_free_ char *instance_name = NULL; + Manager *m = userdata; + DnssdService *s = NULL; + const char *name; + const char *name_template; + const char *type; + uid_t euid; + int r; + + assert(message); + assert(m); + + if (m->mdns_support != RESOLVE_SUPPORT_YES) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled"); + + service = new0(DnssdService, 1); + if (!service) + return log_oom(); + + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_euid(creds, &euid); + if (r < 0) + return r; + service->originator = euid; + + r = sd_bus_message_read(message, "sssqqq", &name, &name_template, &type, + &service->port, &service->priority, + &service->weight); + if (r < 0) + return r; + + s = hashmap_get(m->dnssd_services, name); + if (s) + return sd_bus_error_setf(error, BUS_ERROR_DNSSD_SERVICE_EXISTS, "DNS-SD service '%s' exists already", name); + + if (!dnssd_srv_type_is_valid(type)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DNS-SD service type '%s' is invalid", type); + + service->name = strdup(name); + if (!service->name) + return log_oom(); + + service->name_template = strdup(name_template); + if (!service->name_template) + return log_oom(); + + service->type = strdup(type); + if (!service->type) + return log_oom(); + + r = dnssd_render_instance_name(service, &instance_name); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "a{say}"); + if (r < 0) + return r; + + while ((r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "{say}")) > 0) { + _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL; + DnsTxtItem *last = NULL; + + txt_data = new0(DnssdTxtData, 1); + if (!txt_data) + return log_oom(); + + while ((r = sd_bus_message_enter_container(message, SD_BUS_TYPE_DICT_ENTRY, "say")) > 0) { + const char *key; + const void *value; + size_t size; + DnsTxtItem *i; + + r = sd_bus_message_read(message, "s", &key); + if (r < 0) + return r; + + if (isempty(key)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Keys in DNS-SD TXT RRs can't be empty"); + + if (!ascii_is_valid(key)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TXT key '%s' contains non-ASCII symbols", key); + + r = sd_bus_message_read_array(message, 'y', &value, &size); + if (r < 0) + return r; + + r = dnssd_txt_item_new_from_data(key, value, size, &i); + if (r < 0) + return r; + + LIST_INSERT_AFTER(items, txt_data->txt, last, i); + last = i; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (txt_data->txt) { + LIST_PREPEND(items, service->txt_data_items, txt_data); + txt_data = NULL; + } + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!service->txt_data_items) { + _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL; + + txt_data = new0(DnssdTxtData, 1); + if (!txt_data) + return log_oom(); + + r = dns_txt_item_new_empty(&txt_data->txt); + if (r < 0) + return r; + + LIST_PREPEND(items, service->txt_data_items, txt_data); + txt_data = NULL; + } + + r = sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", service->name, &path); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, CAP_SYS_ADMIN, + "org.freedesktop.resolve1.register-service", + NULL, false, UID_INVALID, + &m->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + r = hashmap_ensure_allocated(&m->dnssd_services, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(m->dnssd_services, service->name, service); + if (r < 0) + return r; + + r = sd_bus_track_new(sd_bus_message_get_bus(message), &bus_track, on_bus_track, service); + if (r < 0) + return r; + + r = sd_bus_track_add_sender(bus_track, message); + if (r < 0) + return r; + + service->manager = m; + + service = NULL; + + manager_refresh_rrs(m); + + return sd_bus_reply_method_return(message, "o", path); +} + +static int call_dnssd_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) { + _cleanup_free_ char *name = NULL; + DnssdService *s = NULL; + const char *path; + int r; + + assert(m); + assert(message); + assert(handler); + + r = sd_bus_message_read(message, "o", &path); + if (r < 0) + return r; + + r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/dnssd", &name); + if (r == 0) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DNSSD_SERVICE, "DNS-SD service with object path '%s' does not exist", path); + if (r < 0) + return r; + + s = hashmap_get(m->dnssd_services, name); + if (!s) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DNSSD_SERVICE, "DNS-SD service '%s' not known", name); + + return handler(message, s, error); +} + +static int bus_method_unregister_service(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + + assert(message); + assert(m); + + return call_dnssd_method(m, message, bus_dnssd_method_unregister, error); +} + +static const sd_bus_vtable resolve_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Manager, llmnr_support), 0), + SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Manager, mdns_support), 0), + SD_BUS_PROPERTY("DNSOverTLS", "s", bus_property_get_dns_over_tls_mode, 0, 0), + SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("FallbackDNS", "a(iiay)", bus_property_get_fallback_dns_servers, offsetof(Manager, fallback_dns_servers), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CurrentDNSServer", "(iiay)", bus_property_get_current_dns_server, offsetof(Manager, current_dns_server), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains, 0, 0), + SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0), + SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0), + SD_BUS_PROPERTY("DNSSEC", "s", bus_property_get_dnssec_mode, 0, 0), + SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0), + SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0), + SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas, 0, 0), + SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode, offsetof(Manager, dns_stub_listener_mode), 0), + + SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("FlushCaches", NULL, NULL, bus_method_flush_caches, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ResetServerFeatures", NULL, NULL, bus_method_reset_server_features, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_domains, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDefaultRoute", "ib", NULL, bus_method_set_link_default_route, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDNSOverTLS", "is", NULL, bus_method_set_link_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("RevertLink", "i", NULL, bus_method_revert_link, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_METHOD("RegisterService", "sssqqqaa{say}", "o", bus_method_register_service, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("UnregisterService", "o", NULL, bus_method_unregister_service, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END, +}; + +static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { + Manager *m = userdata; + int b, r; + + assert(message); + assert(m); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) { + log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m"); + return 0; + } + + if (b) + return 0; + + log_debug("Coming back from suspend, verifying all RRs..."); + + manager_verify_all(m); + return 0; +} + +int manager_connect_bus(Manager *m) { + int r; + + assert(m); + + if (m->bus) + return 0; + + r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-resolve"); + if (r < 0) + return log_error_errno(r, "Failed to connect to system bus: %m"); + + r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m); + if (r < 0) + return log_error_errno(r, "Failed to register object: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable, link_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to register link objects: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/link", link_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to register link enumerator: %m"); + + r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/dnssd", "org.freedesktop.resolve1.DnssdService", dnssd_vtable, dnssd_object_find, m); + if (r < 0) + return log_error_errno(r, "Failed to register dnssd objects: %m"); + + r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/dnssd", dnssd_node_enumerator, m); + if (r < 0) + return log_error_errno(r, "Failed to register dnssd enumerator: %m"); + + r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + r = sd_bus_attach_event(m->bus, m->event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + r = sd_bus_match_signal_async( + m->bus, + NULL, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "PrepareForSleep", + match_prepare_for_sleep, + NULL, + m); + if (r < 0) + log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m"); + + return 0; +} + +int _manager_send_changed(Manager *manager, const char *property, ...) { + assert(manager); + + char **l = strv_from_stdarg_alloca(property); + + int r = sd_bus_emit_properties_changed_strv( + manager->bus, + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + l); + if (r < 0) + log_notice_errno(r, "Failed to emit notification about changed property %s: %m", property); + return r; +} diff --git a/src/resolve/resolved-bus.h b/src/resolve/resolved-bus.h new file mode 100644 index 00000000..a499f76a --- /dev/null +++ b/src/resolve/resolved-bus.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "resolved-manager.h" + +int manager_connect_bus(Manager *m); +int _manager_send_changed(Manager *manager, const char *property, ...) _sentinel_; +#define manager_send_changed(manager, ...) _manager_send_changed(manager, __VA_ARGS__, NULL) +int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex); +int bus_property_get_resolve_support(sd_bus *bus, const char *path, const char *interface, + const char *property, sd_bus_message *reply, + void *userdata, sd_bus_error *error); diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c new file mode 100644 index 00000000..a46c4538 --- /dev/null +++ b/src/resolve/resolved-conf.c @@ -0,0 +1,403 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "conf-parser.h" +#include "def.h" +#include "extract-word.h" +#include "hexdecoct.h" +#include "parse-util.h" +#include "resolved-conf.h" +#include "resolved-dnssd.h" +#include "specifier.h" +#include "string-table.h" +#include "string-util.h" +#include "utf8.h" + +DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode, "Failed to parse DNS stub listener mode setting"); + +static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MAX] = { + [DNS_STUB_LISTENER_NO] = "no", + [DNS_STUB_LISTENER_UDP] = "udp", + [DNS_STUB_LISTENER_TCP] = "tcp", + [DNS_STUB_LISTENER_YES] = "yes", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES); + +static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) { + union in_addr_union address; + int family, r, ifindex = 0; + DnsServer *s; + + assert(m); + assert(word); + + r = in_addr_ifindex_from_string_auto(word, &family, &address, &ifindex); + if (r < 0) + return r; + + /* Silently filter out 0.0.0.0 and 127.0.0.53 (our own stub DNS listener) */ + if (!dns_server_address_valid(family, &address)) + return 0; + + /* Filter out duplicates */ + s = dns_server_find(manager_get_first_dns_server(m, type), family, &address, ifindex); + if (s) { + /* + * Drop the marker. This is used to find the servers + * that ceased to exist, see + * manager_mark_dns_servers() and + * manager_flush_marked_dns_servers(). + */ + dns_server_move_back_and_unmark(s); + return 0; + } + + return dns_server_new(m, NULL, type, NULL, family, &address, ifindex); +} + +int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) { + int r; + + assert(m); + assert(string); + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + r = manager_add_dns_server_by_string(m, type, word); + if (r < 0) + log_warning_errno(r, "Failed to add DNS server address '%s', ignoring: %m", word); + } + + return 0; +} + +static int manager_add_search_domain_by_string(Manager *m, const char *domain) { + DnsSearchDomain *d; + bool route_only; + int r; + + assert(m); + assert(domain); + + route_only = *domain == '~'; + if (route_only) + domain++; + + if (dns_name_is_root(domain) || streq(domain, "*")) { + route_only = true; + domain = "."; + } + + r = dns_search_domain_find(m->search_domains, domain, &d); + if (r < 0) + return r; + if (r > 0) + dns_search_domain_move_back_and_unmark(d); + else { + r = dns_search_domain_new(m, &d, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain); + if (r < 0) + return r; + } + + d->route_only = route_only; + return 0; +} + +int manager_parse_search_domains_and_warn(Manager *m, const char *string) { + int r; + + assert(m); + assert(string); + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&string, &word, NULL, EXTRACT_UNQUOTE); + if (r < 0) + return r; + if (r == 0) + break; + + r = manager_add_search_domain_by_string(m, word); + if (r < 0) + log_warning_errno(r, "Failed to add search domain '%s', ignoring: %m", word); + } + + return 0; +} + +int config_parse_dns_servers( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Manager *m = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(m); + + if (isempty(rvalue)) + /* Empty assignment means clear the list */ + dns_server_unlink_all(manager_get_first_dns_server(m, ltype)); + else { + /* Otherwise, add to the list */ + r = manager_parse_dns_server_string_and_warn(m, ltype, rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNS server string '%s'. Ignoring.", rvalue); + return 0; + } + } + + /* If we have a manual setting, then we stop reading + * /etc/resolv.conf */ + if (ltype == DNS_SERVER_SYSTEM) + m->read_resolv_conf = false; + if (ltype == DNS_SERVER_FALLBACK) + m->need_builtin_fallbacks = false; + + return 0; +} + +int config_parse_search_domains( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Manager *m = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(m); + + if (isempty(rvalue)) + /* Empty assignment means clear the list */ + dns_search_domain_unlink_all(m->search_domains); + else { + /* Otherwise, add to the list */ + r = manager_parse_search_domains_and_warn(m, rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse search domains string '%s'. Ignoring.", rvalue); + return 0; + } + } + + /* If we have a manual setting, then we stop reading + * /etc/resolv.conf */ + m->read_resolv_conf = false; + + return 0; +} + +int config_parse_dnssd_service_name(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { + static const Specifier specifier_table[] = { + { 'b', specifier_boot_id, NULL }, + { 'H', specifier_host_name, NULL }, + { 'm', specifier_machine_id, NULL }, + { 'v', specifier_kernel_release, NULL }, + {} + }; + DnssdService *s = userdata; + _cleanup_free_ char *name = NULL; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(s); + + if (isempty(rvalue)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Service instance name can't be empty. Ignoring."); + return -EINVAL; + } + + r = free_and_strdup(&s->name_template, rvalue); + if (r < 0) + return log_oom(); + + r = specifier_printf(s->name_template, specifier_table, NULL, &name); + if (r < 0) + return log_debug_errno(r, "Failed to replace specifiers: %m"); + + if (!dns_service_name_is_valid(name)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Service instance name template renders to invalid name '%s'. Ignoring.", name); + return -EINVAL; + } + + return 0; +} + +int config_parse_dnssd_service_type(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { + DnssdService *s = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(s); + + if (isempty(rvalue)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Service type can't be empty. Ignoring."); + return -EINVAL; + } + + if (!dnssd_srv_type_is_valid(rvalue)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Service type is invalid. Ignoring."); + return -EINVAL; + } + + r = free_and_strdup(&s->type, rvalue); + if (r < 0) + return log_oom(); + + return 0; +} + +int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata) { + _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL; + DnssdService *s = userdata; + DnsTxtItem *last = NULL; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(s); + + if (isempty(rvalue)) { + /* Flush out collected items */ + s->txt_data_items = dnssd_txtdata_free_all(s->txt_data_items); + return 0; + } + + txt_data = new0(DnssdTxtData, 1); + if (!txt_data) + return log_oom(); + + for (;;) { + _cleanup_free_ char *word = NULL; + _cleanup_free_ char *key = NULL; + _cleanup_free_ char *value = NULL; + _cleanup_free_ void *decoded = NULL; + size_t length = 0; + DnsTxtItem *i; + int r; + + r = extract_first_word(&rvalue, &word, NULL, + EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + + r = split_pair(word, "=", &key, &value); + if (r == -ENOMEM) + return log_oom(); + if (r == -EINVAL) + key = TAKE_PTR(word); + + if (!ascii_is_valid(key)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid syntax, ignoring: %s", key); + return -EINVAL; + } + + switch (ltype) { + + case DNS_TXT_ITEM_DATA: + if (value) { + r = unbase64mem(value, strlen(value), &decoded, &length); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, + "Invalid base64 encoding, ignoring: %s", value); + } + + r = dnssd_txt_item_new_from_data(key, decoded, length, &i); + if (r < 0) + return log_oom(); + break; + + case DNS_TXT_ITEM_TEXT: + r = dnssd_txt_item_new_from_string(key, value, &i); + if (r < 0) + return log_oom(); + break; + + default: + assert_not_reached("Unknown type of Txt config"); + } + + LIST_INSERT_AFTER(items, txt_data->txt, last, i); + last = i; + } + + if (!LIST_IS_EMPTY(txt_data->txt)) { + LIST_PREPEND(items, s->txt_data_items, txt_data); + txt_data = NULL; + } + + return 0; +} + +int manager_parse_config_file(Manager *m) { + int r; + + assert(m); + + r = config_parse_many_nulstr(PKGSYSCONFDIR "/resolved.conf", + CONF_PATHS_NULSTR("systemd/resolved.conf.d"), + "Resolve\0", + config_item_perf_lookup, resolved_gperf_lookup, + CONFIG_PARSE_WARN, m); + if (r < 0) + return r; + + if (m->need_builtin_fallbacks) { + r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_FALLBACK, DNS_SERVERS); + if (r < 0) + return r; + } + +#if ! HAVE_GCRYPT + if (m->dnssec_mode != DNSSEC_NO) { + log_warning("DNSSEC option cannot be enabled or set to allow-downgrade when systemd-resolved is built without gcrypt support. Turning off DNSSEC support."); + m->dnssec_mode = DNSSEC_NO; + } +#endif + +#if ! ENABLE_DNS_OVER_TLS + if (m->dns_over_tls_mode != DNS_OVER_TLS_NO) { + log_warning("DNS-over-TLS option cannot be enabled or set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support."); + m->dns_over_tls_mode = DNS_OVER_TLS_NO; + } +#endif + return 0; + +} diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h new file mode 100644 index 00000000..4713df58 --- /dev/null +++ b/src/resolve/resolved-conf.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" + +typedef enum DnsStubListenerMode DnsStubListenerMode; + +enum DnsStubListenerMode { + DNS_STUB_LISTENER_NO, + DNS_STUB_LISTENER_UDP, + DNS_STUB_LISTENER_TCP, + DNS_STUB_LISTENER_YES, + _DNS_STUB_LISTENER_MODE_MAX, + _DNS_STUB_LISTENER_MODE_INVALID = -1 +}; + +#include "resolved-manager.h" +#include "resolved-dns-server.h" + +int manager_parse_config_file(Manager *m); + +int manager_parse_search_domains_and_warn(Manager *m, const char *string); +int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string); + +const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, GPERF_LEN_TYPE length); +const struct ConfigPerfItem* resolved_dnssd_gperf_lookup(const char *key, GPERF_LEN_TYPE length); + +CONFIG_PARSER_PROTOTYPE(config_parse_dns_servers); +CONFIG_PARSER_PROTOTYPE(config_parse_search_domains); +CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_name); +CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_type); +CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt); + +const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_; +DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_; diff --git a/src/resolve/resolved-def.h b/src/resolve/resolved-def.h new file mode 100644 index 00000000..63c24a02 --- /dev/null +++ b/src/resolve/resolved-def.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "time-util.h" + +#define SD_RESOLVED_DNS (UINT64_C(1) << 0) +#define SD_RESOLVED_LLMNR_IPV4 (UINT64_C(1) << 1) +#define SD_RESOLVED_LLMNR_IPV6 (UINT64_C(1) << 2) +#define SD_RESOLVED_MDNS_IPV4 (UINT64_C(1) << 3) +#define SD_RESOLVED_MDNS_IPV6 (UINT64_C(1) << 4) +#define SD_RESOLVED_NO_CNAME (UINT64_C(1) << 5) +#define SD_RESOLVED_NO_TXT (UINT64_C(1) << 6) +#define SD_RESOLVED_NO_ADDRESS (UINT64_C(1) << 7) +#define SD_RESOLVED_NO_SEARCH (UINT64_C(1) << 8) +#define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9) + +#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6) +#define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6) + +#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS) + +#define SD_RESOLVED_QUERY_TIMEOUT_USEC (120 * USEC_PER_SEC) diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c new file mode 100644 index 00000000..e5693bf7 --- /dev/null +++ b/src/resolve/resolved-dns-answer.c @@ -0,0 +1,752 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "dns-domain.h" +#include "resolved-dns-answer.h" +#include "resolved-dns-dnssec.h" +#include "string-util.h" + +DnsAnswer *dns_answer_new(size_t n) { + DnsAnswer *a; + + a = malloc0(offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * n); + if (!a) + return NULL; + + a->n_ref = 1; + a->n_allocated = n; + + return a; +} + +static void dns_answer_flush(DnsAnswer *a) { + DnsResourceRecord *rr; + + if (!a) + return; + + DNS_ANSWER_FOREACH(rr, a) + dns_resource_record_unref(rr); + + a->n_rrs = 0; +} + +static DnsAnswer *dns_answer_free(DnsAnswer *a) { + assert(a); + + dns_answer_flush(a); + return mfree(a); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsAnswer, dns_answer, dns_answer_free); + +static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { + assert(rr); + + if (!a) + return -ENOSPC; + + if (a->n_rrs >= a->n_allocated) + return -ENOSPC; + + a->items[a->n_rrs++] = (DnsAnswerItem) { + .rr = dns_resource_record_ref(rr), + .ifindex = ifindex, + .flags = flags, + }; + + return 1; +} + +static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) { + DnsResourceRecord *rr; + DnsAnswerFlags flags; + int ifindex, r; + + DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, source) { + r = dns_answer_add_raw(a, rr, ifindex, flags); + if (r < 0) + return r; + } + + return 0; +} + +int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { + size_t i; + int r; + + assert(rr); + + if (!a) + return -ENOSPC; + if (a->n_ref > 1) + return -EBUSY; + + for (i = 0; i < a->n_rrs; i++) { + if (a->items[i].ifindex != ifindex) + continue; + + r = dns_resource_key_equal(a->items[i].rr->key, rr->key); + if (r < 0) + return r; + if (r == 0) + continue; + + /* There's already an RR of the same RRset in place! Let's see if the TTLs more or less + * match. We don't really care if they match precisely, but we do care whether one is 0 and + * the other is not. See RFC 2181, Section 5.2. */ + if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0)) + return -EINVAL; + + r = dns_resource_record_payload_equal(a->items[i].rr, rr); + if (r < 0) + return r; + if (r == 0) + continue; + + /* Entry already exists, keep the entry with the higher RR. */ + if (rr->ttl > a->items[i].rr->ttl) { + dns_resource_record_ref(rr); + dns_resource_record_unref(a->items[i].rr); + a->items[i].rr = rr; + } + + a->items[i].flags |= flags; + return 0; + } + + return dns_answer_add_raw(a, rr, ifindex, flags); +} + +static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) { + DnsResourceRecord *rr; + DnsAnswerFlags flags; + int ifindex, r; + + DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, b) { + r = dns_answer_add(a, rr, ifindex, flags); + if (r < 0) + return r; + } + + return 0; +} + +int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { + int r; + + assert(a); + assert(rr); + + r = dns_answer_reserve_or_clone(a, 1); + if (r < 0) + return r; + + return dns_answer_add(*a, rr, ifindex, flags); +} + +int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *soa = NULL; + + soa = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SOA, name); + if (!soa) + return -ENOMEM; + + soa->ttl = ttl; + + soa->soa.mname = strdup(name); + if (!soa->soa.mname) + return -ENOMEM; + + soa->soa.rname = strjoin("root.", name); + if (!soa->soa.rname) + return -ENOMEM; + + soa->soa.serial = 1; + soa->soa.refresh = 1; + soa->soa.retry = 1; + soa->soa.expire = 1; + soa->soa.minimum = ttl; + + return dns_answer_add(a, soa, ifindex, DNS_ANSWER_AUTHENTICATED); +} + +int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) { + DnsAnswerFlags flags = 0, i_flags; + DnsResourceRecord *i; + bool found = false; + int r; + + assert(key); + + DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) { + r = dns_resource_key_match_rr(key, i, NULL); + if (r < 0) + return r; + if (r == 0) + continue; + + if (!ret_flags) + return 1; + + if (found) + flags &= i_flags; + else { + flags = i_flags; + found = true; + } + } + + if (ret_flags) + *ret_flags = flags; + + return found; +} + +int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) { + DnsResourceRecord *i; + + DNS_ANSWER_FOREACH(i, a) { + if (IN_SET(i->key->type, DNS_TYPE_NSEC, DNS_TYPE_NSEC3)) + return true; + } + + return false; +} + +int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone) { + DnsResourceRecord *rr; + int r; + + /* Checks whether the specified answer contains at least one NSEC3 RR in the specified zone */ + + DNS_ANSWER_FOREACH(rr, answer) { + const char *p; + + if (rr->key->type != DNS_TYPE_NSEC3) + continue; + + p = dns_resource_key_name(rr->key); + r = dns_name_parent(&p); + if (r < 0) + return r; + if (r == 0) + continue; + + r = dns_name_equal(p, zone); + if (r != 0) + return r; + } + + return false; +} + +int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) { + DnsResourceRecord *rr, *soa = NULL; + DnsAnswerFlags rr_flags, soa_flags = 0; + int r; + + assert(key); + + /* For a SOA record we can never find a matching SOA record */ + if (key->type == DNS_TYPE_SOA) + return 0; + + DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) { + r = dns_resource_key_match_soa(key, rr->key); + if (r < 0) + return r; + if (r > 0) { + + if (soa) { + r = dns_name_endswith(dns_resource_key_name(rr->key), dns_resource_key_name(soa->key)); + if (r < 0) + return r; + if (r > 0) + continue; + } + + soa = rr; + soa_flags = rr_flags; + } + } + + if (!soa) + return 0; + + if (ret) + *ret = soa; + if (flags) + *flags = soa_flags; + + return 1; +} + +int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) { + DnsResourceRecord *rr; + DnsAnswerFlags rr_flags; + int r; + + assert(key); + + /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */ + if (!dns_type_may_redirect(key->type)) + return 0; + + DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) { + r = dns_resource_key_match_cname_or_dname(key, rr->key, NULL); + if (r < 0) + return r; + if (r > 0) { + if (ret) + *ret = rr; + if (flags) + *flags = rr_flags; + return 1; + } + } + + return 0; +} + +int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) { + _cleanup_(dns_answer_unrefp) DnsAnswer *k = NULL; + int r; + + assert(ret); + + if (dns_answer_size(a) <= 0) { + *ret = dns_answer_ref(b); + return 0; + } + + if (dns_answer_size(b) <= 0) { + *ret = dns_answer_ref(a); + return 0; + } + + k = dns_answer_new(a->n_rrs + b->n_rrs); + if (!k) + return -ENOMEM; + + r = dns_answer_add_raw_all(k, a); + if (r < 0) + return r; + + r = dns_answer_add_all(k, b); + if (r < 0) + return r; + + *ret = TAKE_PTR(k); + + return 0; +} + +int dns_answer_extend(DnsAnswer **a, DnsAnswer *b) { + DnsAnswer *merged; + int r; + + assert(a); + + r = dns_answer_merge(*a, b, &merged); + if (r < 0) + return r; + + dns_answer_unref(*a); + *a = merged; + + return 0; +} + +int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) { + bool found = false, other = false; + DnsResourceRecord *rr; + size_t i; + int r; + + assert(a); + assert(key); + + /* Remove all entries matching the specified key from *a */ + + DNS_ANSWER_FOREACH(rr, *a) { + r = dns_resource_key_equal(rr->key, key); + if (r < 0) + return r; + if (r > 0) + found = true; + else + other = true; + + if (found && other) + break; + } + + if (!found) + return 0; + + if (!other) { + *a = dns_answer_unref(*a); /* Return NULL for the empty answer */ + return 1; + } + + if ((*a)->n_ref > 1) { + _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL; + DnsAnswerFlags flags; + int ifindex; + + copy = dns_answer_new((*a)->n_rrs); + if (!copy) + return -ENOMEM; + + DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) { + r = dns_resource_key_equal(rr->key, key); + if (r < 0) + return r; + if (r > 0) + continue; + + r = dns_answer_add_raw(copy, rr, ifindex, flags); + if (r < 0) + return r; + } + + dns_answer_unref(*a); + *a = TAKE_PTR(copy); + + return 1; + } + + /* Only a single reference, edit in-place */ + + i = 0; + for (;;) { + if (i >= (*a)->n_rrs) + break; + + r = dns_resource_key_equal((*a)->items[i].rr->key, key); + if (r < 0) + return r; + if (r > 0) { + /* Kill this entry */ + + dns_resource_record_unref((*a)->items[i].rr); + memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1)); + (*a)->n_rrs--; + continue; + + } else + /* Keep this entry */ + i++; + } + + return 1; +} + +int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) { + bool found = false, other = false; + DnsResourceRecord *rr; + size_t i; + int r; + + assert(a); + assert(rm); + + /* Remove all entries matching the specified RR from *a */ + + DNS_ANSWER_FOREACH(rr, *a) { + r = dns_resource_record_equal(rr, rm); + if (r < 0) + return r; + if (r > 0) + found = true; + else + other = true; + + if (found && other) + break; + } + + if (!found) + return 0; + + if (!other) { + *a = dns_answer_unref(*a); /* Return NULL for the empty answer */ + return 1; + } + + if ((*a)->n_ref > 1) { + _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL; + DnsAnswerFlags flags; + int ifindex; + + copy = dns_answer_new((*a)->n_rrs); + if (!copy) + return -ENOMEM; + + DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) { + r = dns_resource_record_equal(rr, rm); + if (r < 0) + return r; + if (r > 0) + continue; + + r = dns_answer_add_raw(copy, rr, ifindex, flags); + if (r < 0) + return r; + } + + dns_answer_unref(*a); + *a = TAKE_PTR(copy); + + return 1; + } + + /* Only a single reference, edit in-place */ + + i = 0; + for (;;) { + if (i >= (*a)->n_rrs) + break; + + r = dns_resource_record_equal((*a)->items[i].rr, rm); + if (r < 0) + return r; + if (r > 0) { + /* Kill this entry */ + + dns_resource_record_unref((*a)->items[i].rr); + memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1)); + (*a)->n_rrs--; + continue; + + } else + /* Keep this entry */ + i++; + } + + return 1; +} + +int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags) { + DnsResourceRecord *rr_source; + int ifindex_source, r; + DnsAnswerFlags flags_source; + + assert(a); + assert(key); + + /* Copy all RRs matching the specified key from source into *a */ + + DNS_ANSWER_FOREACH_FULL(rr_source, ifindex_source, flags_source, source) { + + r = dns_resource_key_equal(rr_source->key, key); + if (r < 0) + return r; + if (r == 0) + continue; + + /* Make space for at least one entry */ + r = dns_answer_reserve_or_clone(a, 1); + if (r < 0) + return r; + + r = dns_answer_add(*a, rr_source, ifindex_source, flags_source|or_flags); + if (r < 0) + return r; + } + + return 0; +} + +int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags) { + int r; + + assert(to); + assert(from); + assert(key); + + r = dns_answer_copy_by_key(to, *from, key, or_flags); + if (r < 0) + return r; + + return dns_answer_remove_by_key(from, key); +} + +void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) { + DnsAnswerItem *items; + size_t i, start, end; + + if (!a) + return; + + if (a->n_rrs <= 1) + return; + + start = 0; + end = a->n_rrs-1; + + /* RFC 4795, Section 2.6 suggests we should order entries + * depending on whether the sender is a link-local address. */ + + items = newa(DnsAnswerItem, a->n_rrs); + for (i = 0; i < a->n_rrs; i++) { + + if (a->items[i].rr->key->class == DNS_CLASS_IN && + ((a->items[i].rr->key->type == DNS_TYPE_A && in_addr_is_link_local(AF_INET, (union in_addr_union*) &a->items[i].rr->a.in_addr) != prefer_link_local) || + (a->items[i].rr->key->type == DNS_TYPE_AAAA && in_addr_is_link_local(AF_INET6, (union in_addr_union*) &a->items[i].rr->aaaa.in6_addr) != prefer_link_local))) + /* Order address records that are not preferred to the end of the array */ + items[end--] = a->items[i]; + else + /* Order all other records to the beginning of the array */ + items[start++] = a->items[i]; + } + + assert(start == end+1); + memcpy(a->items, items, sizeof(DnsAnswerItem) * a->n_rrs); +} + +int dns_answer_reserve(DnsAnswer **a, size_t n_free) { + DnsAnswer *n; + + assert(a); + + if (n_free <= 0) + return 0; + + if (*a) { + size_t ns; + + if ((*a)->n_ref > 1) + return -EBUSY; + + ns = (*a)->n_rrs + n_free; + + if ((*a)->n_allocated >= ns) + return 0; + + /* Allocate more than we need */ + ns *= 2; + + n = realloc(*a, offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * ns); + if (!n) + return -ENOMEM; + + n->n_allocated = ns; + } else { + n = dns_answer_new(n_free); + if (!n) + return -ENOMEM; + } + + *a = n; + return 0; +} + +int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free) { + _cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL; + int r; + + assert(a); + + /* Tries to extend the DnsAnswer object. And if that's not + * possible, since we are not the sole owner, then allocate a + * new, appropriately sized one. Either way, after this call + * the object will only have a single reference, and has room + * for at least the specified number of RRs. */ + + r = dns_answer_reserve(a, n_free); + if (r != -EBUSY) + return r; + + assert(*a); + + n = dns_answer_new(((*a)->n_rrs + n_free) * 2); + if (!n) + return -ENOMEM; + + r = dns_answer_add_raw_all(n, *a); + if (r < 0) + return r; + + dns_answer_unref(*a); + *a = TAKE_PTR(n); + + return 0; +} + +void dns_answer_dump(DnsAnswer *answer, FILE *f) { + DnsResourceRecord *rr; + DnsAnswerFlags flags; + int ifindex; + + if (!f) + f = stdout; + + DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) { + const char *t; + + fputc('\t', f); + + t = dns_resource_record_to_string(rr); + if (!t) { + log_oom(); + continue; + } + + fputs(t, f); + + if (ifindex != 0 || flags & (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE|DNS_ANSWER_SHARED_OWNER)) + fputs("\t;", f); + + if (ifindex != 0) + printf(" ifindex=%i", ifindex); + if (flags & DNS_ANSWER_AUTHENTICATED) + fputs(" authenticated", f); + if (flags & DNS_ANSWER_CACHEABLE) + fputs(" cachable", f); + if (flags & DNS_ANSWER_SHARED_OWNER) + fputs(" shared-owner", f); + + fputc('\n', f); + } +} + +int dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) { + DnsResourceRecord *rr; + int r; + + assert(cname); + + /* Checks whether the answer contains a DNAME record that indicates that the specified CNAME record is + * synthesized from it */ + + if (cname->key->type != DNS_TYPE_CNAME) + return 0; + + DNS_ANSWER_FOREACH(rr, a) { + _cleanup_free_ char *n = NULL; + + if (rr->key->type != DNS_TYPE_DNAME) + continue; + if (rr->key->class != cname->key->class) + continue; + + r = dns_name_change_suffix(cname->cname.name, rr->dname.name, dns_resource_key_name(rr->key), &n); + if (r < 0) + return r; + if (r == 0) + continue; + + r = dns_name_equal(n, dns_resource_key_name(cname->key)); + if (r < 0) + return r; + if (r > 0) + return 1; + } + + return 0; +} diff --git a/src/resolve/resolved-dns-answer.h b/src/resolve/resolved-dns-answer.h new file mode 100644 index 00000000..47fc80e2 --- /dev/null +++ b/src/resolve/resolved-dns-answer.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct DnsAnswer DnsAnswer; +typedef struct DnsAnswerItem DnsAnswerItem; + +#include "macro.h" +#include "resolved-dns-rr.h" + +/* A simple array of resource records. We keep track of the + * originating ifindex for each RR where that makes sense, so that we + * can qualify A and AAAA RRs referring to a local link with the + * right ifindex. + * + * Note that we usually encode the empty DnsAnswer object as a simple NULL. */ + +typedef enum DnsAnswerFlags { + DNS_ANSWER_AUTHENTICATED = 1 << 0, /* Item has been authenticated */ + DNS_ANSWER_CACHEABLE = 1 << 1, /* Item is subject to caching */ + DNS_ANSWER_SHARED_OWNER = 1 << 2, /* For mDNS: RRset may be owner by multiple peers */ + DNS_ANSWER_CACHE_FLUSH = 1 << 3, /* For mDNS: sets cache-flush bit in the rrclass of response records */ + DNS_ANSWER_GOODBYE = 1 << 4, /* For mDNS: item is subject to disappear */ +} DnsAnswerFlags; + +struct DnsAnswerItem { + DnsResourceRecord *rr; + int ifindex; + DnsAnswerFlags flags; +}; + +struct DnsAnswer { + unsigned n_ref; + size_t n_rrs, n_allocated; + DnsAnswerItem items[0]; +}; + +DnsAnswer *dns_answer_new(size_t n); +DnsAnswer *dns_answer_ref(DnsAnswer *a); +DnsAnswer *dns_answer_unref(DnsAnswer *a); + +int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags); +int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags); +int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex); + +int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags); +int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a); +int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone); + +int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags); +int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags); + +int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret); +int dns_answer_extend(DnsAnswer **a, DnsAnswer *b); + +void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local); + +int dns_answer_reserve(DnsAnswer **a, size_t n_free); +int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free); + +int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key); +int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rr); + +int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags); +int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags); + +int dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname); + +static inline size_t dns_answer_size(DnsAnswer *a) { + return a ? a->n_rrs : 0; +} + +static inline bool dns_answer_isempty(DnsAnswer *a) { + return dns_answer_size(a) <= 0; +} + +void dns_answer_dump(DnsAnswer *answer, FILE *f); + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref); + +#define _DNS_ANSWER_FOREACH(q, kk, a) \ + for (size_t UNIQ_T(i, q) = ({ \ + (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \ + 0; \ + }); \ + (a) && (UNIQ_T(i, q) < (a)->n_rrs); \ + UNIQ_T(i, q)++, (kk) = (UNIQ_T(i, q) < (a)->n_rrs ? (a)->items[UNIQ_T(i, q)].rr : NULL)) + +#define DNS_ANSWER_FOREACH(kk, a) _DNS_ANSWER_FOREACH(UNIQ, kk, a) + +#define _DNS_ANSWER_FOREACH_IFINDEX(q, kk, ifi, a) \ + for (size_t UNIQ_T(i, q) = ({ \ + (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \ + (ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \ + 0; \ + }); \ + (a) && (UNIQ_T(i, q) < (a)->n_rrs); \ + UNIQ_T(i, q)++, \ + (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \ + (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0)) + +#define DNS_ANSWER_FOREACH_IFINDEX(kk, ifindex, a) _DNS_ANSWER_FOREACH_IFINDEX(UNIQ, kk, ifindex, a) + +#define _DNS_ANSWER_FOREACH_FLAGS(q, kk, fl, a) \ + for (size_t UNIQ_T(i, q) = ({ \ + (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \ + (fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \ + 0; \ + }); \ + (a) && (UNIQ_T(i, q) < (a)->n_rrs); \ + UNIQ_T(i, q)++, \ + (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \ + (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0)) + +#define DNS_ANSWER_FOREACH_FLAGS(kk, flags, a) _DNS_ANSWER_FOREACH_FLAGS(UNIQ, kk, flags, a) + +#define _DNS_ANSWER_FOREACH_FULL(q, kk, ifi, fl, a) \ + for (size_t UNIQ_T(i, q) = ({ \ + (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \ + (ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \ + (fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \ + 0; \ + }); \ + (a) && (UNIQ_T(i, q) < (a)->n_rrs); \ + UNIQ_T(i, q)++, \ + (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \ + (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0), \ + (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0)) + +#define DNS_ANSWER_FOREACH_FULL(kk, ifindex, flags, a) _DNS_ANSWER_FOREACH_FULL(UNIQ, kk, ifindex, flags, a) diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c new file mode 100644 index 00000000..946889a8 --- /dev/null +++ b/src/resolve/resolved-dns-cache.c @@ -0,0 +1,1116 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "af-list.h" +#include "alloc-util.h" +#include "dns-domain.h" +#include "format-util.h" +#include "resolved-dns-answer.h" +#include "resolved-dns-cache.h" +#include "resolved-dns-packet.h" +#include "string-util.h" + +/* Never cache more than 4K entries. RFC 1536, Section 5 suggests to + * leave DNS caches unbounded, but that's crazy. */ +#define CACHE_MAX 4096 + +/* We never keep any item longer than 2h in our cache */ +#define CACHE_TTL_MAX_USEC (2 * USEC_PER_HOUR) + +/* How long to cache strange rcodes, i.e. rcodes != SUCCESS and != NXDOMAIN (specifically: that's only SERVFAIL for + * now) */ +#define CACHE_TTL_STRANGE_RCODE_USEC (30 * USEC_PER_SEC) + +typedef enum DnsCacheItemType DnsCacheItemType; +typedef struct DnsCacheItem DnsCacheItem; + +enum DnsCacheItemType { + DNS_CACHE_POSITIVE, + DNS_CACHE_NODATA, + DNS_CACHE_NXDOMAIN, + DNS_CACHE_RCODE, /* "strange" RCODE (effective only SERVFAIL for now) */ +}; + +struct DnsCacheItem { + DnsCacheItemType type; + DnsResourceKey *key; + DnsResourceRecord *rr; + int rcode; + + usec_t until; + bool authenticated:1; + bool shared_owner:1; + + int ifindex; + int owner_family; + union in_addr_union owner_address; + + unsigned prioq_idx; + LIST_FIELDS(DnsCacheItem, by_key); +}; + +static const char *dns_cache_item_type_to_string(DnsCacheItem *item) { + assert(item); + + switch (item->type) { + + case DNS_CACHE_POSITIVE: + return "POSITIVE"; + + case DNS_CACHE_NODATA: + return "NODATA"; + + case DNS_CACHE_NXDOMAIN: + return "NXDOMAIN"; + + case DNS_CACHE_RCODE: + return dns_rcode_to_string(item->rcode); + } + + return NULL; +} + +static void dns_cache_item_free(DnsCacheItem *i) { + if (!i) + return; + + dns_resource_record_unref(i->rr); + dns_resource_key_unref(i->key); + free(i); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsCacheItem*, dns_cache_item_free); + +static void dns_cache_item_unlink_and_free(DnsCache *c, DnsCacheItem *i) { + DnsCacheItem *first; + + assert(c); + + if (!i) + return; + + first = hashmap_get(c->by_key, i->key); + LIST_REMOVE(by_key, first, i); + + if (first) + assert_se(hashmap_replace(c->by_key, first->key, first) >= 0); + else + hashmap_remove(c->by_key, i->key); + + prioq_remove(c->by_expiry, i, &i->prioq_idx); + + dns_cache_item_free(i); +} + +static bool dns_cache_remove_by_rr(DnsCache *c, DnsResourceRecord *rr) { + DnsCacheItem *first, *i; + int r; + + first = hashmap_get(c->by_key, rr->key); + LIST_FOREACH(by_key, i, first) { + r = dns_resource_record_equal(i->rr, rr); + if (r < 0) + return r; + if (r > 0) { + dns_cache_item_unlink_and_free(c, i); + return true; + } + } + + return false; +} + +static bool dns_cache_remove_by_key(DnsCache *c, DnsResourceKey *key) { + DnsCacheItem *first, *i, *n; + + assert(c); + assert(key); + + first = hashmap_remove(c->by_key, key); + if (!first) + return false; + + LIST_FOREACH_SAFE(by_key, i, n, first) { + prioq_remove(c->by_expiry, i, &i->prioq_idx); + dns_cache_item_free(i); + } + + return true; +} + +void dns_cache_flush(DnsCache *c) { + DnsResourceKey *key; + + assert(c); + + while ((key = hashmap_first_key(c->by_key))) + dns_cache_remove_by_key(c, key); + + assert(hashmap_size(c->by_key) == 0); + assert(prioq_size(c->by_expiry) == 0); + + c->by_key = hashmap_free(c->by_key); + c->by_expiry = prioq_free(c->by_expiry); +} + +static void dns_cache_make_space(DnsCache *c, unsigned add) { + assert(c); + + if (add <= 0) + return; + + /* Makes space for n new entries. Note that we actually allow + * the cache to grow beyond CACHE_MAX, but only when we shall + * add more RRs to the cache than CACHE_MAX at once. In that + * case the cache will be emptied completely otherwise. */ + + for (;;) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + DnsCacheItem *i; + + if (prioq_size(c->by_expiry) <= 0) + break; + + if (prioq_size(c->by_expiry) + add < CACHE_MAX) + break; + + i = prioq_peek(c->by_expiry); + assert(i); + + /* Take an extra reference to the key so that it + * doesn't go away in the middle of the remove call */ + key = dns_resource_key_ref(i->key); + dns_cache_remove_by_key(c, key); + } +} + +void dns_cache_prune(DnsCache *c) { + usec_t t = 0; + + assert(c); + + /* Remove all entries that are past their TTL */ + + for (;;) { + DnsCacheItem *i; + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + + i = prioq_peek(c->by_expiry); + if (!i) + break; + + if (t <= 0) + t = now(clock_boottime_or_monotonic()); + + if (i->until > t) + break; + + /* Depending whether this is an mDNS shared entry + * either remove only this one RR or the whole RRset */ + log_debug("Removing %scache entry for %s (expired "USEC_FMT"s ago)", + i->shared_owner ? "shared " : "", + dns_resource_key_to_string(i->key, key_str, sizeof key_str), + (t - i->until) / USEC_PER_SEC); + + if (i->shared_owner) + dns_cache_item_unlink_and_free(c, i); + else { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + + /* Take an extra reference to the key so that it + * doesn't go away in the middle of the remove call */ + key = dns_resource_key_ref(i->key); + dns_cache_remove_by_key(c, key); + } + } +} + +static int dns_cache_item_prioq_compare_func(const void *a, const void *b) { + const DnsCacheItem *x = a, *y = b; + + return CMP(x->until, y->until); +} + +static int dns_cache_init(DnsCache *c) { + int r; + + assert(c); + + r = prioq_ensure_allocated(&c->by_expiry, dns_cache_item_prioq_compare_func); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&c->by_key, &dns_resource_key_hash_ops); + if (r < 0) + return r; + + return r; +} + +static int dns_cache_link_item(DnsCache *c, DnsCacheItem *i) { + DnsCacheItem *first; + int r; + + assert(c); + assert(i); + + r = prioq_put(c->by_expiry, i, &i->prioq_idx); + if (r < 0) + return r; + + first = hashmap_get(c->by_key, i->key); + if (first) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL; + + /* Keep a reference to the original key, while we manipulate the list. */ + k = dns_resource_key_ref(first->key); + + /* Now, try to reduce the number of keys we keep */ + dns_resource_key_reduce(&first->key, &i->key); + + if (first->rr) + dns_resource_key_reduce(&first->rr->key, &i->key); + if (i->rr) + dns_resource_key_reduce(&i->rr->key, &i->key); + + LIST_PREPEND(by_key, first, i); + assert_se(hashmap_replace(c->by_key, first->key, first) >= 0); + } else { + r = hashmap_put(c->by_key, i->key, i); + if (r < 0) { + prioq_remove(c->by_expiry, i, &i->prioq_idx); + return r; + } + } + + return 0; +} + +static DnsCacheItem* dns_cache_get(DnsCache *c, DnsResourceRecord *rr) { + DnsCacheItem *i; + + assert(c); + assert(rr); + + LIST_FOREACH(by_key, i, hashmap_get(c->by_key, rr->key)) + if (i->rr && dns_resource_record_equal(i->rr, rr) > 0) + return i; + + return NULL; +} + +static usec_t calculate_until(DnsResourceRecord *rr, uint32_t nsec_ttl, usec_t timestamp, bool use_soa_minimum) { + uint32_t ttl; + usec_t u; + + assert(rr); + + ttl = MIN(rr->ttl, nsec_ttl); + if (rr->key->type == DNS_TYPE_SOA && use_soa_minimum) { + /* If this is a SOA RR, and it is requested, clamp to + * the SOA's minimum field. This is used when we do + * negative caching, to determine the TTL for the + * negative caching entry. See RFC 2308, Section + * 5. */ + + if (ttl > rr->soa.minimum) + ttl = rr->soa.minimum; + } + + u = ttl * USEC_PER_SEC; + if (u > CACHE_TTL_MAX_USEC) + u = CACHE_TTL_MAX_USEC; + + if (rr->expiry != USEC_INFINITY) { + usec_t left; + + /* Make use of the DNSSEC RRSIG expiry info, if we + * have it */ + + left = LESS_BY(rr->expiry, now(CLOCK_REALTIME)); + if (u > left) + u = left; + } + + return timestamp + u; +} + +static void dns_cache_item_update_positive( + DnsCache *c, + DnsCacheItem *i, + DnsResourceRecord *rr, + bool authenticated, + bool shared_owner, + usec_t timestamp, + int ifindex, + int owner_family, + const union in_addr_union *owner_address) { + + assert(c); + assert(i); + assert(rr); + assert(owner_address); + + i->type = DNS_CACHE_POSITIVE; + + if (!i->by_key_prev) + /* We are the first item in the list, we need to + * update the key used in the hashmap */ + + assert_se(hashmap_replace(c->by_key, rr->key, i) >= 0); + + dns_resource_record_ref(rr); + dns_resource_record_unref(i->rr); + i->rr = rr; + + dns_resource_key_unref(i->key); + i->key = dns_resource_key_ref(rr->key); + + i->until = calculate_until(rr, (uint32_t) -1, timestamp, false); + i->authenticated = authenticated; + i->shared_owner = shared_owner; + + i->ifindex = ifindex; + + i->owner_family = owner_family; + i->owner_address = *owner_address; + + prioq_reshuffle(c->by_expiry, i, &i->prioq_idx); +} + +static int dns_cache_put_positive( + DnsCache *c, + DnsResourceRecord *rr, + bool authenticated, + bool shared_owner, + usec_t timestamp, + int ifindex, + int owner_family, + const union in_addr_union *owner_address) { + + _cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL; + DnsCacheItem *existing; + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + int r, k; + + assert(c); + assert(rr); + assert(owner_address); + + /* Never cache pseudo RRs */ + if (dns_class_is_pseudo(rr->key->class)) + return 0; + if (dns_type_is_pseudo(rr->key->type)) + return 0; + + /* New TTL is 0? Delete this specific entry... */ + if (rr->ttl <= 0) { + k = dns_cache_remove_by_rr(c, rr); + log_debug("%s: %s", + k > 0 ? "Removed zero TTL entry from cache" : "Not caching zero TTL cache entry", + dns_resource_key_to_string(rr->key, key_str, sizeof key_str)); + return 0; + } + + /* Entry exists already? Update TTL, timestamp and owner */ + existing = dns_cache_get(c, rr); + if (existing) { + dns_cache_item_update_positive( + c, + existing, + rr, + authenticated, + shared_owner, + timestamp, + ifindex, + owner_family, + owner_address); + return 0; + } + + /* Otherwise, add the new RR */ + r = dns_cache_init(c); + if (r < 0) + return r; + + dns_cache_make_space(c, 1); + + i = new0(DnsCacheItem, 1); + if (!i) + return -ENOMEM; + + i->type = DNS_CACHE_POSITIVE; + i->key = dns_resource_key_ref(rr->key); + i->rr = dns_resource_record_ref(rr); + i->until = calculate_until(rr, (uint32_t) -1, timestamp, false); + i->authenticated = authenticated; + i->shared_owner = shared_owner; + i->ifindex = ifindex; + i->owner_family = owner_family; + i->owner_address = *owner_address; + i->prioq_idx = PRIOQ_IDX_NULL; + + r = dns_cache_link_item(c, i); + if (r < 0) + return r; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *t = NULL; + char ifname[IF_NAMESIZE + 1]; + + (void) in_addr_to_string(i->owner_family, &i->owner_address, &t); + + log_debug("Added positive %s%s cache entry for %s "USEC_FMT"s on %s/%s/%s", + i->authenticated ? "authenticated" : "unauthenticated", + i->shared_owner ? " shared" : "", + dns_resource_key_to_string(i->key, key_str, sizeof key_str), + (i->until - timestamp) / USEC_PER_SEC, + i->ifindex == 0 ? "*" : strna(format_ifname(i->ifindex, ifname)), + af_to_name_short(i->owner_family), + strna(t)); + } + + i = NULL; + return 0; +} + +static int dns_cache_put_negative( + DnsCache *c, + DnsResourceKey *key, + int rcode, + bool authenticated, + uint32_t nsec_ttl, + usec_t timestamp, + DnsResourceRecord *soa, + int owner_family, + const union in_addr_union *owner_address) { + + _cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL; + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + int r; + + assert(c); + assert(key); + assert(owner_address); + + /* Never cache pseudo RR keys. DNS_TYPE_ANY is particularly + * important to filter out as we use this as a pseudo-type for + * NXDOMAIN entries */ + if (dns_class_is_pseudo(key->class)) + return 0; + if (dns_type_is_pseudo(key->type)) + return 0; + + if (IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN)) { + if (!soa) + return 0; + + /* For negative replies, check if we have a TTL of a SOA */ + if (nsec_ttl <= 0 || soa->soa.minimum <= 0 || soa->ttl <= 0) { + log_debug("Not caching negative entry with zero SOA/NSEC/NSEC3 TTL: %s", + dns_resource_key_to_string(key, key_str, sizeof key_str)); + return 0; + } + } else if (rcode != DNS_RCODE_SERVFAIL) + return 0; + + r = dns_cache_init(c); + if (r < 0) + return r; + + dns_cache_make_space(c, 1); + + i = new0(DnsCacheItem, 1); + if (!i) + return -ENOMEM; + + i->type = + rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA : + rcode == DNS_RCODE_NXDOMAIN ? DNS_CACHE_NXDOMAIN : DNS_CACHE_RCODE; + i->until = + i->type == DNS_CACHE_RCODE ? timestamp + CACHE_TTL_STRANGE_RCODE_USEC : + calculate_until(soa, nsec_ttl, timestamp, true); + i->authenticated = authenticated; + i->owner_family = owner_family; + i->owner_address = *owner_address; + i->prioq_idx = PRIOQ_IDX_NULL; + i->rcode = rcode; + + if (i->type == DNS_CACHE_NXDOMAIN) { + /* NXDOMAIN entries should apply equally to all types, so we use ANY as + * a pseudo type for this purpose here. */ + i->key = dns_resource_key_new(key->class, DNS_TYPE_ANY, dns_resource_key_name(key)); + if (!i->key) + return -ENOMEM; + + /* Make sure to remove any previous entry for this + * specific ANY key. (For non-ANY keys the cache data + * is already cleared by the caller.) Note that we + * don't bother removing positive or NODATA cache + * items in this case, because it would either be slow + * or require explicit indexing by name */ + dns_cache_remove_by_key(c, key); + } else + i->key = dns_resource_key_ref(key); + + r = dns_cache_link_item(c, i); + if (r < 0) + return r; + + log_debug("Added %s cache entry for %s "USEC_FMT"s", + dns_cache_item_type_to_string(i), + dns_resource_key_to_string(i->key, key_str, sizeof key_str), + (i->until - timestamp) / USEC_PER_SEC); + + i = NULL; + return 0; +} + +static void dns_cache_remove_previous( + DnsCache *c, + DnsResourceKey *key, + DnsAnswer *answer) { + + DnsResourceRecord *rr; + DnsAnswerFlags flags; + + assert(c); + + /* First, if we were passed a key (i.e. on LLMNR/DNS, but + * not on mDNS), delete all matching old RRs, so that we only + * keep complete by_key in place. */ + if (key) + dns_cache_remove_by_key(c, key); + + /* Second, flush all entries matching the answer, unless this + * is an RR that is explicitly marked to be "shared" between + * peers (i.e. mDNS RRs without the flush-cache bit set). */ + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + if ((flags & DNS_ANSWER_CACHEABLE) == 0) + continue; + + if (flags & DNS_ANSWER_SHARED_OWNER) + continue; + + dns_cache_remove_by_key(c, rr->key); + } +} + +static bool rr_eligible(DnsResourceRecord *rr) { + assert(rr); + + /* When we see an NSEC/NSEC3 RR, we'll only cache it if it is from the lower zone, not the upper zone, since + * that's where the interesting bits are (with exception of DS RRs). Of course, this way we cannot derive DS + * existence from any cached NSEC/NSEC3, but that should be fine. */ + + switch (rr->key->type) { + + case DNS_TYPE_NSEC: + return !bitmap_isset(rr->nsec.types, DNS_TYPE_NS) || + bitmap_isset(rr->nsec.types, DNS_TYPE_SOA); + + case DNS_TYPE_NSEC3: + return !bitmap_isset(rr->nsec3.types, DNS_TYPE_NS) || + bitmap_isset(rr->nsec3.types, DNS_TYPE_SOA); + + default: + return true; + } +} + +int dns_cache_put( + DnsCache *c, + DnsCacheMode cache_mode, + DnsResourceKey *key, + int rcode, + DnsAnswer *answer, + bool authenticated, + uint32_t nsec_ttl, + usec_t timestamp, + int owner_family, + const union in_addr_union *owner_address) { + + DnsResourceRecord *soa = NULL, *rr; + bool weird_rcode = false; + DnsAnswerFlags flags; + unsigned cache_keys; + int r, ifindex; + + assert(c); + assert(owner_address); + + dns_cache_remove_previous(c, key, answer); + + /* We only care for positive replies and NXDOMAINs, on all other replies we will simply flush the respective + * entries, and that's it. (Well, with one further exception: since some DNS zones (akamai!) return SERVFAIL + * consistently for some lookups, and forwarders tend to propagate that we'll cache that too, but only for a + * short time.) */ + + if (IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN)) { + if (dns_answer_size(answer) <= 0) { + if (key) { + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + + log_debug("Not caching negative entry without a SOA record: %s", + dns_resource_key_to_string(key, key_str, sizeof key_str)); + } + return 0; + } + + } else { + /* Only cache SERVFAIL as "weird" rcode for now. We can add more later, should that turn out to be + * beneficial. */ + if (rcode != DNS_RCODE_SERVFAIL) + return 0; + + weird_rcode = true; + } + + cache_keys = dns_answer_size(answer); + if (key) + cache_keys++; + + /* Make some space for our new entries */ + dns_cache_make_space(c, cache_keys); + + if (timestamp <= 0) + timestamp = now(clock_boottime_or_monotonic()); + + /* Second, add in positive entries for all contained RRs */ + DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) { + if ((flags & DNS_ANSWER_CACHEABLE) == 0 || + !rr_eligible(rr)) + continue; + + r = dns_cache_put_positive( + c, + rr, + flags & DNS_ANSWER_AUTHENTICATED, + flags & DNS_ANSWER_SHARED_OWNER, + timestamp, + ifindex, + owner_family, owner_address); + if (r < 0) + goto fail; + } + + if (!key) /* mDNS doesn't know negative caching, really */ + return 0; + + /* Third, add in negative entries if the key has no RR */ + r = dns_answer_match_key(answer, key, NULL); + if (r < 0) + goto fail; + if (r > 0) + return 0; + + /* But not if it has a matching CNAME/DNAME (the negative + * caching will be done on the canonical name, not on the + * alias) */ + r = dns_answer_find_cname_or_dname(answer, key, NULL, NULL); + if (r < 0) + goto fail; + if (r > 0) + return 0; + + /* See https://tools.ietf.org/html/rfc2308, which say that a matching SOA record in the packet is used to + * enable negative caching. We apply one exception though: if we are about to cache a weird rcode we do so + * regardless of a SOA. */ + r = dns_answer_find_soa(answer, key, &soa, &flags); + if (r < 0) + goto fail; + if (r == 0 && !weird_rcode) + return 0; + if (r > 0) { + /* Refuse using the SOA data if it is unsigned, but the key is + * signed */ + if (authenticated && (flags & DNS_ANSWER_AUTHENTICATED) == 0) + return 0; + } + + if (cache_mode == DNS_CACHE_MODE_NO_NEGATIVE) { + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + log_debug("Not caching negative entry for: %s, cache mode set to no-negative", + dns_resource_key_to_string(key, key_str, sizeof key_str)); + return 0; + } + + r = dns_cache_put_negative( + c, + key, + rcode, + authenticated, + nsec_ttl, + timestamp, + soa, + owner_family, owner_address); + if (r < 0) + goto fail; + + return 0; + +fail: + /* Adding all RRs failed. Let's clean up what we already + * added, just in case */ + + if (key) + dns_cache_remove_by_key(c, key); + + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + if ((flags & DNS_ANSWER_CACHEABLE) == 0) + continue; + + dns_cache_remove_by_key(c, rr->key); + } + + return r; +} + +static DnsCacheItem *dns_cache_get_by_key_follow_cname_dname_nsec(DnsCache *c, DnsResourceKey *k) { + DnsCacheItem *i; + const char *n; + int r; + + assert(c); + assert(k); + + /* If we hit some OOM error, or suchlike, we don't care too + * much, after all this is just a cache */ + + i = hashmap_get(c->by_key, k); + if (i) + return i; + + n = dns_resource_key_name(k); + + /* Check if we have an NXDOMAIN cache item for the name, notice that we use + * the pseudo-type ANY for NXDOMAIN cache items. */ + i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_ANY, n)); + if (i && i->type == DNS_CACHE_NXDOMAIN) + return i; + + if (dns_type_may_redirect(k->type)) { + /* Check if we have a CNAME record instead */ + i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_CNAME, n)); + if (i && i->type != DNS_CACHE_NODATA) + return i; + + /* OK, let's look for cached DNAME records. */ + for (;;) { + if (isempty(n)) + return NULL; + + i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_DNAME, n)); + if (i && i->type != DNS_CACHE_NODATA) + return i; + + /* Jump one label ahead */ + r = dns_name_parent(&n); + if (r <= 0) + return NULL; + } + } + + if (k->type != DNS_TYPE_NSEC) { + /* Check if we have an NSEC record instead for the name. */ + i = hashmap_get(c->by_key, &DNS_RESOURCE_KEY_CONST(k->class, DNS_TYPE_NSEC, n)); + if (i) + return i; + } + + return NULL; +} + +int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, bool clamp_ttl, int *rcode, DnsAnswer **ret, bool *authenticated) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + unsigned n = 0; + int r; + bool nxdomain = false; + DnsCacheItem *j, *first, *nsec = NULL; + bool have_authenticated = false, have_non_authenticated = false; + usec_t current; + int found_rcode = -1; + + assert(c); + assert(key); + assert(rcode); + assert(ret); + assert(authenticated); + + if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) { + /* If we have ANY lookups we don't use the cache, so + * that the caller refreshes via the network. */ + + log_debug("Ignoring cache for ANY lookup: %s", + dns_resource_key_to_string(key, key_str, sizeof key_str)); + + c->n_miss++; + + *ret = NULL; + *rcode = DNS_RCODE_SUCCESS; + *authenticated = false; + + return 0; + } + + first = dns_cache_get_by_key_follow_cname_dname_nsec(c, key); + if (!first) { + /* If one question cannot be answered we need to refresh */ + + log_debug("Cache miss for %s", + dns_resource_key_to_string(key, key_str, sizeof key_str)); + + c->n_miss++; + + *ret = NULL; + *rcode = DNS_RCODE_SUCCESS; + *authenticated = false; + + return 0; + } + + LIST_FOREACH(by_key, j, first) { + if (j->rr) { + if (j->rr->key->type == DNS_TYPE_NSEC) + nsec = j; + + n++; + } else if (j->type == DNS_CACHE_NXDOMAIN) + nxdomain = true; + else if (j->type == DNS_CACHE_RCODE) + found_rcode = j->rcode; + + if (j->authenticated) + have_authenticated = true; + else + have_non_authenticated = true; + } + + if (found_rcode >= 0) { + log_debug("RCODE %s cache hit for %s", + dns_rcode_to_string(found_rcode), + dns_resource_key_to_string(key, key_str, sizeof(key_str))); + + *ret = NULL; + *rcode = found_rcode; + *authenticated = false; + + c->n_hit++; + return 1; + } + + if (nsec && !IN_SET(key->type, DNS_TYPE_NSEC, DNS_TYPE_DS)) { + /* Note that we won't derive information for DS RRs from an NSEC, because we only cache NSEC RRs from + * the lower-zone of a zone cut, but the DS RRs are on the upper zone. */ + + log_debug("NSEC NODATA cache hit for %s", + dns_resource_key_to_string(key, key_str, sizeof key_str)); + + /* We only found an NSEC record that matches our name. + * If it says the type doesn't exist report + * NODATA. Otherwise report a cache miss. */ + + *ret = NULL; + *rcode = DNS_RCODE_SUCCESS; + *authenticated = nsec->authenticated; + + if (!bitmap_isset(nsec->rr->nsec.types, key->type) && + !bitmap_isset(nsec->rr->nsec.types, DNS_TYPE_CNAME) && + !bitmap_isset(nsec->rr->nsec.types, DNS_TYPE_DNAME)) { + c->n_hit++; + return 1; + } + + c->n_miss++; + return 0; + } + + log_debug("%s cache hit for %s", + n > 0 ? "Positive" : + nxdomain ? "NXDOMAIN" : "NODATA", + dns_resource_key_to_string(key, key_str, sizeof key_str)); + + if (n <= 0) { + c->n_hit++; + + *ret = NULL; + *rcode = nxdomain ? DNS_RCODE_NXDOMAIN : DNS_RCODE_SUCCESS; + *authenticated = have_authenticated && !have_non_authenticated; + return 1; + } + + answer = dns_answer_new(n); + if (!answer) + return -ENOMEM; + + if (clamp_ttl) + current = now(clock_boottime_or_monotonic()); + + LIST_FOREACH(by_key, j, first) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + + if (!j->rr) + continue; + + if (clamp_ttl) { + rr = dns_resource_record_ref(j->rr); + + r = dns_resource_record_clamp_ttl(&rr, LESS_BY(j->until, current) / USEC_PER_SEC); + if (r < 0) + return r; + } + + r = dns_answer_add(answer, rr ?: j->rr, j->ifindex, j->authenticated ? DNS_ANSWER_AUTHENTICATED : 0); + if (r < 0) + return r; + } + + c->n_hit++; + + *ret = answer; + *rcode = DNS_RCODE_SUCCESS; + *authenticated = have_authenticated && !have_non_authenticated; + answer = NULL; + + return n; +} + +int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address) { + DnsCacheItem *i, *first; + bool same_owner = true; + + assert(cache); + assert(rr); + + dns_cache_prune(cache); + + /* See if there's a cache entry for the same key. If there + * isn't there's no conflict */ + first = hashmap_get(cache->by_key, rr->key); + if (!first) + return 0; + + /* See if the RR key is owned by the same owner, if so, there + * isn't a conflict either */ + LIST_FOREACH(by_key, i, first) { + if (i->owner_family != owner_family || + !in_addr_equal(owner_family, &i->owner_address, owner_address)) { + same_owner = false; + break; + } + } + if (same_owner) + return 0; + + /* See if there's the exact same RR in the cache. If yes, then + * there's no conflict. */ + if (dns_cache_get(cache, rr)) + return 0; + + /* There's a conflict */ + return 1; +} + +int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) { + unsigned ancount = 0; + Iterator iterator; + DnsCacheItem *i; + int r; + + assert(cache); + assert(p); + + HASHMAP_FOREACH(i, cache->by_key, iterator) { + DnsCacheItem *j; + + LIST_FOREACH(by_key, j, i) { + if (!j->rr) + continue; + + if (!j->shared_owner) + continue; + + r = dns_packet_append_rr(p, j->rr, 0, NULL, NULL); + if (r == -EMSGSIZE && p->protocol == DNS_PROTOCOL_MDNS) { + /* For mDNS, if we're unable to stuff all known answers into the given packet, + * allocate a new one, push the RR into that one and link it to the current one. + */ + + DNS_PACKET_HEADER(p)->ancount = htobe16(ancount); + ancount = 0; + + r = dns_packet_new_query(&p->more, p->protocol, 0, true); + if (r < 0) + return r; + + /* continue with new packet */ + p = p->more; + r = dns_packet_append_rr(p, j->rr, 0, NULL, NULL); + } + + if (r < 0) + return r; + + ancount++; + } + } + + DNS_PACKET_HEADER(p)->ancount = htobe16(ancount); + + return 0; +} + +void dns_cache_dump(DnsCache *cache, FILE *f) { + Iterator iterator; + DnsCacheItem *i; + + if (!cache) + return; + + if (!f) + f = stdout; + + HASHMAP_FOREACH(i, cache->by_key, iterator) { + DnsCacheItem *j; + + LIST_FOREACH(by_key, j, i) { + + fputc('\t', f); + + if (j->rr) { + const char *t; + t = dns_resource_record_to_string(j->rr); + if (!t) { + log_oom(); + continue; + } + + fputs(t, f); + fputc('\n', f); + } else { + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + + fputs(dns_resource_key_to_string(j->key, key_str, sizeof key_str), f); + fputs(" -- ", f); + fputs(dns_cache_item_type_to_string(j), f); + fputc('\n', f); + } + } + } +} + +bool dns_cache_is_empty(DnsCache *cache) { + if (!cache) + return true; + + return hashmap_isempty(cache->by_key); +} + +unsigned dns_cache_size(DnsCache *cache) { + if (!cache) + return 0; + + return hashmap_size(cache->by_key); +} diff --git a/src/resolve/resolved-dns-cache.h b/src/resolve/resolved-dns-cache.h new file mode 100644 index 00000000..afd7d45d --- /dev/null +++ b/src/resolve/resolved-dns-cache.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "hashmap.h" +#include "list.h" +#include "prioq.h" +#include "resolve-util.h" +#include "time-util.h" + +typedef struct DnsCache { + Hashmap *by_key; + Prioq *by_expiry; + unsigned n_hit; + unsigned n_miss; +} DnsCache; + +#include "resolved-dns-answer.h" +#include "resolved-dns-packet.h" +#include "resolved-dns-question.h" +#include "resolved-dns-rr.h" + +void dns_cache_flush(DnsCache *c); +void dns_cache_prune(DnsCache *c); + +int dns_cache_put(DnsCache *c, DnsCacheMode cache_mode, DnsResourceKey *key, int rcode, DnsAnswer *answer, bool authenticated, uint32_t nsec_ttl, usec_t timestamp, int owner_family, const union in_addr_union *owner_address); +int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, bool clamp_ttl, int *rcode, DnsAnswer **answer, bool *authenticated); + +int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address); + +void dns_cache_dump(DnsCache *cache, FILE *f); +bool dns_cache_is_empty(DnsCache *cache); + +unsigned dns_cache_size(DnsCache *cache); + +int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p); diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c new file mode 100644 index 00000000..ec9bfd7a --- /dev/null +++ b/src/resolve/resolved-dns-dnssec.c @@ -0,0 +1,2310 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "dns-domain.h" +#include "fd-util.h" +#include "fileio.h" +#include "gcrypt-util.h" +#include "hexdecoct.h" +#include "memory-util.h" +#include "resolved-dns-dnssec.h" +#include "resolved-dns-packet.h" +#include "sort-util.h" +#include "string-table.h" + +#define VERIFY_RRS_MAX 256 +#define MAX_KEY_SIZE (32*1024) + +/* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */ +#define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE) + +/* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value */ +#define NSEC3_ITERATIONS_MAX 2500 + +/* + * The DNSSEC Chain of trust: + * + * Normal RRs are protected via RRSIG RRs in combination with DNSKEY RRs, all in the same zone + * DNSKEY RRs are either protected like normal RRs, or via a DS from a zone "higher" up the tree + * DS RRs are protected like normal RRs + * + * Example chain: + * Normal RR → RRSIG/DNSKEY+ → DS → RRSIG/DNSKEY+ → DS → ... → DS → RRSIG/DNSKEY+ → DS + */ + +uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke) { + const uint8_t *p; + uint32_t sum, f; + size_t i; + + /* The algorithm from RFC 4034, Appendix B. */ + + assert(dnskey); + assert(dnskey->key->type == DNS_TYPE_DNSKEY); + + f = (uint32_t) dnskey->dnskey.flags; + + if (mask_revoke) + f &= ~DNSKEY_FLAG_REVOKE; + + sum = f + ((((uint32_t) dnskey->dnskey.protocol) << 8) + (uint32_t) dnskey->dnskey.algorithm); + + p = dnskey->dnskey.key; + + for (i = 0; i < dnskey->dnskey.key_size; i++) + sum += (i & 1) == 0 ? (uint32_t) p[i] << 8 : (uint32_t) p[i]; + + sum += (sum >> 16) & UINT32_C(0xFFFF); + + return sum & UINT32_C(0xFFFF); +} + +int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max) { + size_t c = 0; + int r; + + /* Converts the specified hostname into DNSSEC canonicalized + * form. */ + + if (buffer_max < 2) + return -ENOBUFS; + + for (;;) { + r = dns_label_unescape(&n, buffer, buffer_max, 0); + if (r < 0) + return r; + if (r == 0) + break; + + if (buffer_max < (size_t) r + 2) + return -ENOBUFS; + + /* The DNSSEC canonical form is not clear on what to + * do with dots appearing in labels, the way DNS-SD + * does it. Refuse it for now. */ + + if (memchr(buffer, '.', r)) + return -EINVAL; + + ascii_strlower_n(buffer, (size_t) r); + buffer[r] = '.'; + + buffer += r + 1; + c += r + 1; + + buffer_max -= r + 1; + } + + if (c <= 0) { + /* Not even a single label: this is the root domain name */ + + assert(buffer_max > 2); + buffer[0] = '.'; + buffer[1] = 0; + + return 1; + } + + return (int) c; +} + +#if HAVE_GCRYPT + +static int rr_compare(DnsResourceRecord * const *a, DnsResourceRecord * const *b) { + const DnsResourceRecord *x = *a, *y = *b; + size_t m; + int r; + + /* Let's order the RRs according to RFC 4034, Section 6.3 */ + + assert(x); + assert(x->wire_format); + assert(y); + assert(y->wire_format); + + m = MIN(DNS_RESOURCE_RECORD_RDATA_SIZE(x), DNS_RESOURCE_RECORD_RDATA_SIZE(y)); + + r = memcmp(DNS_RESOURCE_RECORD_RDATA(x), DNS_RESOURCE_RECORD_RDATA(y), m); + if (r != 0) + return r; + + return CMP(DNS_RESOURCE_RECORD_RDATA_SIZE(x), DNS_RESOURCE_RECORD_RDATA_SIZE(y)); +} + +static int dnssec_rsa_verify_raw( + const char *hash_algorithm, + const void *signature, size_t signature_size, + const void *data, size_t data_size, + const void *exponent, size_t exponent_size, + const void *modulus, size_t modulus_size) { + + gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL; + gcry_mpi_t n = NULL, e = NULL, s = NULL; + gcry_error_t ge; + int r; + + assert(hash_algorithm); + + ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature, signature_size, NULL); + if (ge != 0) { + r = -EIO; + goto finish; + } + + ge = gcry_mpi_scan(&e, GCRYMPI_FMT_USG, exponent, exponent_size, NULL); + if (ge != 0) { + r = -EIO; + goto finish; + } + + ge = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, modulus, modulus_size, NULL); + if (ge != 0) { + r = -EIO; + goto finish; + } + + ge = gcry_sexp_build(&signature_sexp, + NULL, + "(sig-val (rsa (s %m)))", + s); + + if (ge != 0) { + r = -EIO; + goto finish; + } + + ge = gcry_sexp_build(&data_sexp, + NULL, + "(data (flags pkcs1) (hash %s %b))", + hash_algorithm, + (int) data_size, + data); + if (ge != 0) { + r = -EIO; + goto finish; + } + + ge = gcry_sexp_build(&public_key_sexp, + NULL, + "(public-key (rsa (n %m) (e %m)))", + n, + e); + if (ge != 0) { + r = -EIO; + goto finish; + } + + ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp); + if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE) + r = 0; + else if (ge != 0) { + log_debug("RSA signature check failed: %s", gpg_strerror(ge)); + r = -EIO; + } else + r = 1; + +finish: + if (e) + gcry_mpi_release(e); + if (n) + gcry_mpi_release(n); + if (s) + gcry_mpi_release(s); + + if (public_key_sexp) + gcry_sexp_release(public_key_sexp); + if (signature_sexp) + gcry_sexp_release(signature_sexp); + if (data_sexp) + gcry_sexp_release(data_sexp); + + return r; +} + +static int dnssec_rsa_verify( + const char *hash_algorithm, + const void *hash, size_t hash_size, + DnsResourceRecord *rrsig, + DnsResourceRecord *dnskey) { + + size_t exponent_size, modulus_size; + void *exponent, *modulus; + + assert(hash_algorithm); + assert(hash); + assert(hash_size > 0); + assert(rrsig); + assert(dnskey); + + if (*(uint8_t*) dnskey->dnskey.key == 0) { + /* exponent is > 255 bytes long */ + + exponent = (uint8_t*) dnskey->dnskey.key + 3; + exponent_size = + ((size_t) (((uint8_t*) dnskey->dnskey.key)[1]) << 8) | + ((size_t) ((uint8_t*) dnskey->dnskey.key)[2]); + + if (exponent_size < 256) + return -EINVAL; + + if (3 + exponent_size >= dnskey->dnskey.key_size) + return -EINVAL; + + modulus = (uint8_t*) dnskey->dnskey.key + 3 + exponent_size; + modulus_size = dnskey->dnskey.key_size - 3 - exponent_size; + + } else { + /* exponent is <= 255 bytes long */ + + exponent = (uint8_t*) dnskey->dnskey.key + 1; + exponent_size = (size_t) ((uint8_t*) dnskey->dnskey.key)[0]; + + if (exponent_size <= 0) + return -EINVAL; + + if (1 + exponent_size >= dnskey->dnskey.key_size) + return -EINVAL; + + modulus = (uint8_t*) dnskey->dnskey.key + 1 + exponent_size; + modulus_size = dnskey->dnskey.key_size - 1 - exponent_size; + } + + return dnssec_rsa_verify_raw( + hash_algorithm, + rrsig->rrsig.signature, rrsig->rrsig.signature_size, + hash, hash_size, + exponent, exponent_size, + modulus, modulus_size); +} + +static int dnssec_ecdsa_verify_raw( + const char *hash_algorithm, + const char *curve, + const void *signature_r, size_t signature_r_size, + const void *signature_s, size_t signature_s_size, + const void *data, size_t data_size, + const void *key, size_t key_size) { + + gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL; + gcry_mpi_t q = NULL, r = NULL, s = NULL; + gcry_error_t ge; + int k; + + assert(hash_algorithm); + + ge = gcry_mpi_scan(&r, GCRYMPI_FMT_USG, signature_r, signature_r_size, NULL); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature_s, signature_s_size, NULL); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, key, key_size, NULL); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_sexp_build(&signature_sexp, + NULL, + "(sig-val (ecdsa (r %m) (s %m)))", + r, + s); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_sexp_build(&data_sexp, + NULL, + "(data (flags rfc6979) (hash %s %b))", + hash_algorithm, + (int) data_size, + data); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_sexp_build(&public_key_sexp, + NULL, + "(public-key (ecc (curve %s) (q %m)))", + curve, + q); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp); + if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE) + k = 0; + else if (ge != 0) { + log_debug("ECDSA signature check failed: %s", gpg_strerror(ge)); + k = -EIO; + } else + k = 1; +finish: + if (r) + gcry_mpi_release(r); + if (s) + gcry_mpi_release(s); + if (q) + gcry_mpi_release(q); + + if (public_key_sexp) + gcry_sexp_release(public_key_sexp); + if (signature_sexp) + gcry_sexp_release(signature_sexp); + if (data_sexp) + gcry_sexp_release(data_sexp); + + return k; +} + +static int dnssec_ecdsa_verify( + const char *hash_algorithm, + int algorithm, + const void *hash, size_t hash_size, + DnsResourceRecord *rrsig, + DnsResourceRecord *dnskey) { + + const char *curve; + size_t key_size; + uint8_t *q; + + assert(hash); + assert(hash_size); + assert(rrsig); + assert(dnskey); + + if (algorithm == DNSSEC_ALGORITHM_ECDSAP256SHA256) { + key_size = 32; + curve = "NIST P-256"; + } else if (algorithm == DNSSEC_ALGORITHM_ECDSAP384SHA384) { + key_size = 48; + curve = "NIST P-384"; + } else + return -EOPNOTSUPP; + + if (dnskey->dnskey.key_size != key_size * 2) + return -EINVAL; + + if (rrsig->rrsig.signature_size != key_size * 2) + return -EINVAL; + + q = newa(uint8_t, key_size*2 + 1); + q[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */ + memcpy(q+1, dnskey->dnskey.key, key_size*2); + + return dnssec_ecdsa_verify_raw( + hash_algorithm, + curve, + rrsig->rrsig.signature, key_size, + (uint8_t*) rrsig->rrsig.signature + key_size, key_size, + hash, hash_size, + q, key_size*2+1); +} + +#if GCRYPT_VERSION_NUMBER >= 0x010600 +static int dnssec_eddsa_verify_raw( + const char *curve, + const void *signature_r, size_t signature_r_size, + const void *signature_s, size_t signature_s_size, + const void *data, size_t data_size, + const void *key, size_t key_size) { + + gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL; + gcry_error_t ge; + int k; + + ge = gcry_sexp_build(&signature_sexp, + NULL, + "(sig-val (eddsa (r %b) (s %b)))", + (int) signature_r_size, + signature_r, + (int) signature_s_size, + signature_s); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_sexp_build(&data_sexp, + NULL, + "(data (flags eddsa) (hash-algo sha512) (value %b))", + (int) data_size, + data); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_sexp_build(&public_key_sexp, + NULL, + "(public-key (ecc (curve %s) (flags eddsa) (q %b)))", + curve, + (int) key_size, + key); + if (ge != 0) { + k = -EIO; + goto finish; + } + + ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp); + if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE) + k = 0; + else if (ge != 0) { + log_debug("EdDSA signature check failed: %s", gpg_strerror(ge)); + k = -EIO; + } else + k = 1; +finish: + if (public_key_sexp) + gcry_sexp_release(public_key_sexp); + if (signature_sexp) + gcry_sexp_release(signature_sexp); + if (data_sexp) + gcry_sexp_release(data_sexp); + + return k; +} + +static int dnssec_eddsa_verify( + int algorithm, + const void *data, size_t data_size, + DnsResourceRecord *rrsig, + DnsResourceRecord *dnskey) { + const char *curve; + size_t key_size; + + if (algorithm == DNSSEC_ALGORITHM_ED25519) { + curve = "Ed25519"; + key_size = 32; + } else + return -EOPNOTSUPP; + + if (dnskey->dnskey.key_size != key_size) + return -EINVAL; + + if (rrsig->rrsig.signature_size != key_size * 2) + return -EINVAL; + + return dnssec_eddsa_verify_raw( + curve, + rrsig->rrsig.signature, key_size, + (uint8_t*) rrsig->rrsig.signature + key_size, key_size, + data, data_size, + dnskey->dnskey.key, key_size); +} +#endif + +static void md_add_uint8(gcry_md_hd_t md, uint8_t v) { + gcry_md_write(md, &v, sizeof(v)); +} + +static void md_add_uint16(gcry_md_hd_t md, uint16_t v) { + v = htobe16(v); + gcry_md_write(md, &v, sizeof(v)); +} + +static void fwrite_uint8(FILE *fp, uint8_t v) { + fwrite(&v, sizeof(v), 1, fp); +} + +static void fwrite_uint16(FILE *fp, uint16_t v) { + v = htobe16(v); + fwrite(&v, sizeof(v), 1, fp); +} + +static void fwrite_uint32(FILE *fp, uint32_t v) { + v = htobe32(v); + fwrite(&v, sizeof(v), 1, fp); +} + +static int dnssec_rrsig_prepare(DnsResourceRecord *rrsig) { + int n_key_labels, n_signer_labels; + const char *name; + int r; + + /* Checks whether the specified RRSIG RR is somewhat valid, and initializes the .n_skip_labels_source and + * .n_skip_labels_signer fields so that we can use them later on. */ + + assert(rrsig); + assert(rrsig->key->type == DNS_TYPE_RRSIG); + + /* Check if this RRSIG RR is already prepared */ + if (rrsig->n_skip_labels_source != (unsigned) -1) + return 0; + + if (rrsig->rrsig.inception > rrsig->rrsig.expiration) + return -EINVAL; + + name = dns_resource_key_name(rrsig->key); + + n_key_labels = dns_name_count_labels(name); + if (n_key_labels < 0) + return n_key_labels; + if (rrsig->rrsig.labels > n_key_labels) + return -EINVAL; + + n_signer_labels = dns_name_count_labels(rrsig->rrsig.signer); + if (n_signer_labels < 0) + return n_signer_labels; + if (n_signer_labels > rrsig->rrsig.labels) + return -EINVAL; + + r = dns_name_skip(name, n_key_labels - n_signer_labels, &name); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + /* Check if the signer is really a suffix of us */ + r = dns_name_equal(name, rrsig->rrsig.signer); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + rrsig->n_skip_labels_source = n_key_labels - rrsig->rrsig.labels; + rrsig->n_skip_labels_signer = n_key_labels - n_signer_labels; + + return 0; +} + +static int dnssec_rrsig_expired(DnsResourceRecord *rrsig, usec_t realtime) { + usec_t expiration, inception, skew; + + assert(rrsig); + assert(rrsig->key->type == DNS_TYPE_RRSIG); + + if (realtime == USEC_INFINITY) + realtime = now(CLOCK_REALTIME); + + expiration = rrsig->rrsig.expiration * USEC_PER_SEC; + inception = rrsig->rrsig.inception * USEC_PER_SEC; + + /* Consider inverted validity intervals as expired */ + if (inception > expiration) + return true; + + /* Permit a certain amount of clock skew of 10% of the valid + * time range. This takes inspiration from unbound's + * resolver. */ + skew = (expiration - inception) / 10; + if (skew > SKEW_MAX) + skew = SKEW_MAX; + + if (inception < skew) + inception = 0; + else + inception -= skew; + + if (expiration + skew < expiration) + expiration = USEC_INFINITY; + else + expiration += skew; + + return realtime < inception || realtime > expiration; +} + +static int algorithm_to_gcrypt_md(uint8_t algorithm) { + + /* Translates a DNSSEC signature algorithm into a gcrypt + * digest identifier. + * + * Note that we implement all algorithms listed as "Must + * implement" and "Recommended to Implement" in RFC6944. We + * don't implement any algorithms that are listed as + * "Optional" or "Must Not Implement". Specifically, we do not + * implement RSAMD5, DSASHA1, DH, DSA-NSEC3-SHA1, and + * GOST-ECC. */ + + switch (algorithm) { + + case DNSSEC_ALGORITHM_RSASHA1: + case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1: + return GCRY_MD_SHA1; + + case DNSSEC_ALGORITHM_RSASHA256: + case DNSSEC_ALGORITHM_ECDSAP256SHA256: + return GCRY_MD_SHA256; + + case DNSSEC_ALGORITHM_ECDSAP384SHA384: + return GCRY_MD_SHA384; + + case DNSSEC_ALGORITHM_RSASHA512: + return GCRY_MD_SHA512; + + default: + return -EOPNOTSUPP; + } +} + +static void dnssec_fix_rrset_ttl( + DnsResourceRecord *list[], + unsigned n, + DnsResourceRecord *rrsig, + usec_t realtime) { + + unsigned k; + + assert(list); + assert(n > 0); + assert(rrsig); + + for (k = 0; k < n; k++) { + DnsResourceRecord *rr = list[k]; + + /* Pick the TTL as the minimum of the RR's TTL, the + * RR's original TTL according to the RRSIG and the + * RRSIG's own TTL, see RFC 4035, Section 5.3.3 */ + rr->ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl); + rr->expiry = rrsig->rrsig.expiration * USEC_PER_SEC; + + /* Copy over information about the signer and wildcard source of synthesis */ + rr->n_skip_labels_source = rrsig->n_skip_labels_source; + rr->n_skip_labels_signer = rrsig->n_skip_labels_signer; + } + + rrsig->expiry = rrsig->rrsig.expiration * USEC_PER_SEC; +} + +int dnssec_verify_rrset( + DnsAnswer *a, + const DnsResourceKey *key, + DnsResourceRecord *rrsig, + DnsResourceRecord *dnskey, + usec_t realtime, + DnssecResult *result) { + + uint8_t wire_format_name[DNS_WIRE_FORMAT_HOSTNAME_MAX]; + DnsResourceRecord **list, *rr; + const char *source, *name; + _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL; + int r, md_algorithm; + size_t k, n = 0; + size_t sig_size = 0; + _cleanup_free_ char *sig_data = NULL; + _cleanup_fclose_ FILE *f = NULL; + size_t hash_size; + void *hash; + bool wildcard; + + assert(key); + assert(rrsig); + assert(dnskey); + assert(result); + assert(rrsig->key->type == DNS_TYPE_RRSIG); + assert(dnskey->key->type == DNS_TYPE_DNSKEY); + + /* Verifies that the RRSet matches the specified "key" in "a", + * using the signature "rrsig" and the key "dnskey". It's + * assumed that RRSIG and DNSKEY match. */ + + r = dnssec_rrsig_prepare(rrsig); + if (r == -EINVAL) { + *result = DNSSEC_INVALID; + return r; + } + if (r < 0) + return r; + + r = dnssec_rrsig_expired(rrsig, realtime); + if (r < 0) + return r; + if (r > 0) { + *result = DNSSEC_SIGNATURE_EXPIRED; + return 0; + } + + name = dns_resource_key_name(key); + + /* Some keys may only appear signed in the zone apex, and are invalid anywhere else. (SOA, NS...) */ + if (dns_type_apex_only(rrsig->rrsig.type_covered)) { + r = dns_name_equal(rrsig->rrsig.signer, name); + if (r < 0) + return r; + if (r == 0) { + *result = DNSSEC_INVALID; + return 0; + } + } + + /* OTOH DS RRs may not appear in the zone apex, but are valid everywhere else. */ + if (rrsig->rrsig.type_covered == DNS_TYPE_DS) { + r = dns_name_equal(rrsig->rrsig.signer, name); + if (r < 0) + return r; + if (r > 0) { + *result = DNSSEC_INVALID; + return 0; + } + } + + /* Determine the "Source of Synthesis" and whether this is a wildcard RRSIG */ + r = dns_name_suffix(name, rrsig->rrsig.labels, &source); + if (r < 0) + return r; + if (r > 0 && !dns_type_may_wildcard(rrsig->rrsig.type_covered)) { + /* We refuse to validate NSEC3 or SOA RRs that are synthesized from wildcards */ + *result = DNSSEC_INVALID; + return 0; + } + if (r == 1) { + /* If we stripped a single label, then let's see if that maybe was "*". If so, we are not really + * synthesized from a wildcard, we are the wildcard itself. Treat that like a normal name. */ + r = dns_name_startswith(name, "*"); + if (r < 0) + return r; + if (r > 0) + source = name; + + wildcard = r == 0; + } else + wildcard = r > 0; + + /* Collect all relevant RRs in a single array, so that we can look at the RRset */ + list = newa(DnsResourceRecord *, dns_answer_size(a)); + + DNS_ANSWER_FOREACH(rr, a) { + r = dns_resource_key_equal(key, rr->key); + if (r < 0) + return r; + if (r == 0) + continue; + + /* We need the wire format for ordering, and digest calculation */ + r = dns_resource_record_to_wire_format(rr, true); + if (r < 0) + return r; + + list[n++] = rr; + + if (n > VERIFY_RRS_MAX) + return -E2BIG; + } + + if (n <= 0) + return -ENODATA; + + /* Bring the RRs into canonical order */ + typesafe_qsort(list, n, rr_compare); + + f = open_memstream_unlocked(&sig_data, &sig_size); + if (!f) + return -ENOMEM; + + fwrite_uint16(f, rrsig->rrsig.type_covered); + fwrite_uint8(f, rrsig->rrsig.algorithm); + fwrite_uint8(f, rrsig->rrsig.labels); + fwrite_uint32(f, rrsig->rrsig.original_ttl); + fwrite_uint32(f, rrsig->rrsig.expiration); + fwrite_uint32(f, rrsig->rrsig.inception); + fwrite_uint16(f, rrsig->rrsig.key_tag); + + r = dns_name_to_wire_format(rrsig->rrsig.signer, wire_format_name, sizeof(wire_format_name), true); + if (r < 0) + return r; + fwrite(wire_format_name, 1, r, f); + + /* Convert the source of synthesis into wire format */ + r = dns_name_to_wire_format(source, wire_format_name, sizeof(wire_format_name), true); + if (r < 0) + return r; + + for (k = 0; k < n; k++) { + size_t l; + + rr = list[k]; + + /* Hash the source of synthesis. If this is a wildcard, then prefix it with the *. label */ + if (wildcard) + fwrite((uint8_t[]) { 1, '*'}, sizeof(uint8_t), 2, f); + fwrite(wire_format_name, 1, r, f); + + fwrite_uint16(f, rr->key->type); + fwrite_uint16(f, rr->key->class); + fwrite_uint32(f, rrsig->rrsig.original_ttl); + + l = DNS_RESOURCE_RECORD_RDATA_SIZE(rr); + assert(l <= 0xFFFF); + + fwrite_uint16(f, (uint16_t) l); + fwrite(DNS_RESOURCE_RECORD_RDATA(rr), 1, l, f); + } + + r = fflush_and_check(f); + if (r < 0) + return r; + + initialize_libgcrypt(false); + + switch (rrsig->rrsig.algorithm) { +#if GCRYPT_VERSION_NUMBER >= 0x010600 + case DNSSEC_ALGORITHM_ED25519: + break; +#else + case DNSSEC_ALGORITHM_ED25519: +#endif + case DNSSEC_ALGORITHM_ED448: + *result = DNSSEC_UNSUPPORTED_ALGORITHM; + return 0; + default: + /* OK, the RRs are now in canonical order. Let's calculate the digest */ + md_algorithm = algorithm_to_gcrypt_md(rrsig->rrsig.algorithm); + if (md_algorithm == -EOPNOTSUPP) { + *result = DNSSEC_UNSUPPORTED_ALGORITHM; + return 0; + } + if (md_algorithm < 0) + return md_algorithm; + + gcry_md_open(&md, md_algorithm, 0); + if (!md) + return -EIO; + + hash_size = gcry_md_get_algo_dlen(md_algorithm); + assert(hash_size > 0); + + gcry_md_write(md, sig_data, sig_size); + + hash = gcry_md_read(md, 0); + if (!hash) + return -EIO; + } + + switch (rrsig->rrsig.algorithm) { + + case DNSSEC_ALGORITHM_RSASHA1: + case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1: + case DNSSEC_ALGORITHM_RSASHA256: + case DNSSEC_ALGORITHM_RSASHA512: + r = dnssec_rsa_verify( + gcry_md_algo_name(md_algorithm), + hash, hash_size, + rrsig, + dnskey); + break; + + case DNSSEC_ALGORITHM_ECDSAP256SHA256: + case DNSSEC_ALGORITHM_ECDSAP384SHA384: + r = dnssec_ecdsa_verify( + gcry_md_algo_name(md_algorithm), + rrsig->rrsig.algorithm, + hash, hash_size, + rrsig, + dnskey); + break; +#if GCRYPT_VERSION_NUMBER >= 0x010600 + case DNSSEC_ALGORITHM_ED25519: + r = dnssec_eddsa_verify( + rrsig->rrsig.algorithm, + sig_data, sig_size, + rrsig, + dnskey); + break; +#endif + } + if (r < 0) + return r; + + /* Now, fix the ttl, expiry, and remember the synthesizing source and the signer */ + if (r > 0) + dnssec_fix_rrset_ttl(list, n, rrsig, realtime); + + if (r == 0) + *result = DNSSEC_INVALID; + else if (wildcard) + *result = DNSSEC_VALIDATED_WILDCARD; + else + *result = DNSSEC_VALIDATED; + + return 0; +} + +int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) { + + assert(rrsig); + assert(dnskey); + + /* Checks if the specified DNSKEY RR matches the key used for + * the signature in the specified RRSIG RR */ + + if (rrsig->key->type != DNS_TYPE_RRSIG) + return -EINVAL; + + if (dnskey->key->type != DNS_TYPE_DNSKEY) + return 0; + if (dnskey->key->class != rrsig->key->class) + return 0; + if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0) + return 0; + if (!revoked_ok && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE)) + return 0; + if (dnskey->dnskey.protocol != 3) + return 0; + if (dnskey->dnskey.algorithm != rrsig->rrsig.algorithm) + return 0; + + if (dnssec_keytag(dnskey, false) != rrsig->rrsig.key_tag) + return 0; + + return dns_name_equal(dns_resource_key_name(dnskey->key), rrsig->rrsig.signer); +} + +int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) { + assert(key); + assert(rrsig); + + /* Checks if the specified RRSIG RR protects the RRSet of the specified RR key. */ + + if (rrsig->key->type != DNS_TYPE_RRSIG) + return 0; + if (rrsig->key->class != key->class) + return 0; + if (rrsig->rrsig.type_covered != key->type) + return 0; + + return dns_name_equal(dns_resource_key_name(rrsig->key), dns_resource_key_name(key)); +} + +int dnssec_verify_rrset_search( + DnsAnswer *a, + const DnsResourceKey *key, + DnsAnswer *validated_dnskeys, + usec_t realtime, + DnssecResult *result, + DnsResourceRecord **ret_rrsig) { + + bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false; + DnsResourceRecord *rrsig; + int r; + + assert(key); + assert(result); + + /* Verifies all RRs from "a" that match the key "key" against DNSKEYs in "validated_dnskeys" */ + + if (!a || a->n_rrs <= 0) + return -ENODATA; + + /* Iterate through each RRSIG RR. */ + DNS_ANSWER_FOREACH(rrsig, a) { + DnsResourceRecord *dnskey; + DnsAnswerFlags flags; + + /* Is this an RRSIG RR that applies to RRs matching our key? */ + r = dnssec_key_match_rrsig(key, rrsig); + if (r < 0) + return r; + if (r == 0) + continue; + + found_rrsig = true; + + /* Look for a matching key */ + DNS_ANSWER_FOREACH_FLAGS(dnskey, flags, validated_dnskeys) { + DnssecResult one_result; + + if ((flags & DNS_ANSWER_AUTHENTICATED) == 0) + continue; + + /* Is this a DNSKEY RR that matches they key of our RRSIG? */ + r = dnssec_rrsig_match_dnskey(rrsig, dnskey, false); + if (r < 0) + return r; + if (r == 0) + continue; + + /* Take the time here, if it isn't set yet, so + * that we do all validations with the same + * time. */ + if (realtime == USEC_INFINITY) + realtime = now(CLOCK_REALTIME); + + /* Yay, we found a matching RRSIG with a matching + * DNSKEY, awesome. Now let's verify all entries of + * the RRSet against the RRSIG and DNSKEY + * combination. */ + + r = dnssec_verify_rrset(a, key, rrsig, dnskey, realtime, &one_result); + if (r < 0) + return r; + + switch (one_result) { + + case DNSSEC_VALIDATED: + case DNSSEC_VALIDATED_WILDCARD: + /* Yay, the RR has been validated, + * return immediately, but fix up the expiry */ + if (ret_rrsig) + *ret_rrsig = rrsig; + + *result = one_result; + return 0; + + case DNSSEC_INVALID: + /* If the signature is invalid, let's try another + key and/or signature. After all they + key_tags and stuff are not unique, and + might be shared by multiple keys. */ + found_invalid = true; + continue; + + case DNSSEC_UNSUPPORTED_ALGORITHM: + /* If the key algorithm is + unsupported, try another + RRSIG/DNSKEY pair, but remember we + encountered this, so that we can + return a proper error when we + encounter nothing better. */ + found_unsupported_algorithm = true; + continue; + + case DNSSEC_SIGNATURE_EXPIRED: + /* If the signature is expired, try + another one, but remember it, so + that we can return this */ + found_expired_rrsig = true; + continue; + + default: + assert_not_reached("Unexpected DNSSEC validation result"); + } + } + } + + if (found_expired_rrsig) + *result = DNSSEC_SIGNATURE_EXPIRED; + else if (found_unsupported_algorithm) + *result = DNSSEC_UNSUPPORTED_ALGORITHM; + else if (found_invalid) + *result = DNSSEC_INVALID; + else if (found_rrsig) + *result = DNSSEC_MISSING_KEY; + else + *result = DNSSEC_NO_SIGNATURE; + + if (ret_rrsig) + *ret_rrsig = NULL; + + return 0; +} + +int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) { + DnsResourceRecord *rr; + int r; + + /* Checks whether there's at least one RRSIG in 'a' that protects RRs of the specified key */ + + DNS_ANSWER_FOREACH(rr, a) { + r = dnssec_key_match_rrsig(key, rr); + if (r < 0) + return r; + if (r > 0) + return 1; + } + + return 0; +} + +static int digest_to_gcrypt_md(uint8_t algorithm) { + + /* Translates a DNSSEC digest algorithm into a gcrypt digest identifier */ + + switch (algorithm) { + + case DNSSEC_DIGEST_SHA1: + return GCRY_MD_SHA1; + + case DNSSEC_DIGEST_SHA256: + return GCRY_MD_SHA256; + + case DNSSEC_DIGEST_SHA384: + return GCRY_MD_SHA384; + + default: + return -EOPNOTSUPP; + } +} + +int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) { + uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX]; + _cleanup_(gcry_md_closep) gcry_md_hd_t md = NULL; + size_t hash_size; + int md_algorithm, r; + void *result; + + assert(dnskey); + assert(ds); + + /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */ + + if (dnskey->key->type != DNS_TYPE_DNSKEY) + return -EINVAL; + if (ds->key->type != DNS_TYPE_DS) + return -EINVAL; + if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0) + return -EKEYREJECTED; + if (!mask_revoke && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE)) + return -EKEYREJECTED; + if (dnskey->dnskey.protocol != 3) + return -EKEYREJECTED; + + if (dnskey->dnskey.algorithm != ds->ds.algorithm) + return 0; + if (dnssec_keytag(dnskey, mask_revoke) != ds->ds.key_tag) + return 0; + + initialize_libgcrypt(false); + + md_algorithm = digest_to_gcrypt_md(ds->ds.digest_type); + if (md_algorithm < 0) + return md_algorithm; + + hash_size = gcry_md_get_algo_dlen(md_algorithm); + assert(hash_size > 0); + + if (ds->ds.digest_size != hash_size) + return 0; + + r = dns_name_to_wire_format(dns_resource_key_name(dnskey->key), wire_format, sizeof(wire_format), true); + if (r < 0) + return r; + + gcry_md_open(&md, md_algorithm, 0); + if (!md) + return -EIO; + + gcry_md_write(md, wire_format, r); + if (mask_revoke) + md_add_uint16(md, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE); + else + md_add_uint16(md, dnskey->dnskey.flags); + md_add_uint8(md, dnskey->dnskey.protocol); + md_add_uint8(md, dnskey->dnskey.algorithm); + gcry_md_write(md, dnskey->dnskey.key, dnskey->dnskey.key_size); + + result = gcry_md_read(md, 0); + if (!result) + return -EIO; + + return memcmp(result, ds->ds.digest, ds->ds.digest_size) == 0; +} + +int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) { + DnsResourceRecord *ds; + DnsAnswerFlags flags; + int r; + + assert(dnskey); + + if (dnskey->key->type != DNS_TYPE_DNSKEY) + return 0; + + DNS_ANSWER_FOREACH_FLAGS(ds, flags, validated_ds) { + + if ((flags & DNS_ANSWER_AUTHENTICATED) == 0) + continue; + + if (ds->key->type != DNS_TYPE_DS) + continue; + if (ds->key->class != dnskey->key->class) + continue; + + r = dns_name_equal(dns_resource_key_name(dnskey->key), dns_resource_key_name(ds->key)); + if (r < 0) + return r; + if (r == 0) + continue; + + r = dnssec_verify_dnskey_by_ds(dnskey, ds, false); + if (IN_SET(r, -EKEYREJECTED, -EOPNOTSUPP)) + return 0; /* The DNSKEY is revoked or otherwise invalid, or we don't support the digest algorithm */ + if (r < 0) + return r; + if (r > 0) + return 1; + } + + return 0; +} + +static int nsec3_hash_to_gcrypt_md(uint8_t algorithm) { + + /* Translates a DNSSEC NSEC3 hash algorithm into a gcrypt digest identifier */ + + switch (algorithm) { + + case NSEC3_ALGORITHM_SHA1: + return GCRY_MD_SHA1; + + default: + return -EOPNOTSUPP; + } +} + +int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) { + uint8_t wire_format[DNS_WIRE_FORMAT_HOSTNAME_MAX]; + gcry_md_hd_t md = NULL; + size_t hash_size; + int algorithm; + void *result; + unsigned k; + int r; + + assert(nsec3); + assert(name); + assert(ret); + + if (nsec3->key->type != DNS_TYPE_NSEC3) + return -EINVAL; + + if (nsec3->nsec3.iterations > NSEC3_ITERATIONS_MAX) + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Ignoring NSEC3 RR %s with excessive number of iterations.", + dns_resource_record_to_string(nsec3)); + + algorithm = nsec3_hash_to_gcrypt_md(nsec3->nsec3.algorithm); + if (algorithm < 0) + return algorithm; + + initialize_libgcrypt(false); + + hash_size = gcry_md_get_algo_dlen(algorithm); + assert(hash_size > 0); + + if (nsec3->nsec3.next_hashed_name_size != hash_size) + return -EINVAL; + + r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true); + if (r < 0) + return r; + + gcry_md_open(&md, algorithm, 0); + if (!md) + return -EIO; + + gcry_md_write(md, wire_format, r); + gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size); + + result = gcry_md_read(md, 0); + if (!result) { + r = -EIO; + goto finish; + } + + for (k = 0; k < nsec3->nsec3.iterations; k++) { + uint8_t tmp[hash_size]; + memcpy(tmp, result, hash_size); + + gcry_md_reset(md); + gcry_md_write(md, tmp, hash_size); + gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size); + + result = gcry_md_read(md, 0); + if (!result) { + r = -EIO; + goto finish; + } + } + + memcpy(ret, result, hash_size); + r = (int) hash_size; + +finish: + gcry_md_close(md); + return r; +} + +static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) { + const char *a, *b; + int r; + + assert(rr); + + if (rr->key->type != DNS_TYPE_NSEC3) + return 0; + + /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */ + if (!IN_SET(rr->nsec3.flags, 0, 1)) + return 0; + + /* Ignore NSEC3 RRs whose algorithm we don't know */ + if (nsec3_hash_to_gcrypt_md(rr->nsec3.algorithm) < 0) + return 0; + /* Ignore NSEC3 RRs with an excessive number of required iterations */ + if (rr->nsec3.iterations > NSEC3_ITERATIONS_MAX) + return 0; + + /* Ignore NSEC3 RRs generated from wildcards. If these NSEC3 RRs weren't correctly signed we can't make this + * check (since rr->n_skip_labels_source is -1), but that's OK, as we won't trust them anyway in that case. */ + if (!IN_SET(rr->n_skip_labels_source, 0, (unsigned) -1)) + return 0; + /* Ignore NSEC3 RRs that are located anywhere else than one label below the zone */ + if (!IN_SET(rr->n_skip_labels_signer, 1, (unsigned) -1)) + return 0; + + if (!nsec3) + return 1; + + /* If a second NSEC3 RR is specified, also check if they are from the same zone. */ + + if (nsec3 == rr) /* Shortcut */ + return 1; + + if (rr->key->class != nsec3->key->class) + return 0; + if (rr->nsec3.algorithm != nsec3->nsec3.algorithm) + return 0; + if (rr->nsec3.iterations != nsec3->nsec3.iterations) + return 0; + if (rr->nsec3.salt_size != nsec3->nsec3.salt_size) + return 0; + if (memcmp_safe(rr->nsec3.salt, nsec3->nsec3.salt, rr->nsec3.salt_size) != 0) + return 0; + + a = dns_resource_key_name(rr->key); + r = dns_name_parent(&a); /* strip off hash */ + if (r <= 0) + return r; + + b = dns_resource_key_name(nsec3->key); + r = dns_name_parent(&b); /* strip off hash */ + if (r <= 0) + return r; + + /* Make sure both have the same parent */ + return dns_name_equal(a, b); +} + +static int nsec3_hashed_domain_format(const uint8_t *hashed, size_t hashed_size, const char *zone, char **ret) { + _cleanup_free_ char *l = NULL; + char *j; + + assert(hashed); + assert(hashed_size > 0); + assert(zone); + assert(ret); + + l = base32hexmem(hashed, hashed_size, false); + if (!l) + return -ENOMEM; + + j = strjoin(l, ".", zone); + if (!j) + return -ENOMEM; + + *ret = j; + return (int) hashed_size; +} + +static int nsec3_hashed_domain_make(DnsResourceRecord *nsec3, const char *domain, const char *zone, char **ret) { + uint8_t hashed[DNSSEC_HASH_SIZE_MAX]; + int hashed_size; + + assert(nsec3); + assert(domain); + assert(zone); + assert(ret); + + hashed_size = dnssec_nsec3_hash(nsec3, domain, hashed); + if (hashed_size < 0) + return hashed_size; + + return nsec3_hashed_domain_format(hashed, (size_t) hashed_size, zone, ret); +} + +/* See RFC 5155, Section 8 + * First try to find a NSEC3 record that matches our query precisely, if that fails, find the closest + * enclosure. Secondly, find a proof that there is no closer enclosure and either a proof that there + * is no wildcard domain as a direct descendant of the closest enclosure, or find an NSEC3 record that + * matches the wildcard domain. + * + * Based on this we can prove either the existence of the record in @key, or NXDOMAIN or NODATA, or + * that there is no proof either way. The latter is the case if a the proof of non-existence of a given + * name uses an NSEC3 record with the opt-out bit set. Lastly, if we are given insufficient NSEC3 records + * to conclude anything we indicate this by returning NO_RR. */ +static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) { + _cleanup_free_ char *next_closer_domain = NULL, *wildcard_domain = NULL; + const char *zone, *p, *pp = NULL, *wildcard; + DnsResourceRecord *rr, *enclosure_rr, *zone_rr, *wildcard_rr = NULL; + DnsAnswerFlags flags; + int hashed_size, r; + bool a, no_closer = false, no_wildcard = false, optout = false; + + assert(key); + assert(result); + + /* First step, find the zone name and the NSEC3 parameters of the zone. + * it is sufficient to look for the longest common suffix we find with + * any NSEC3 RR in the response. Any NSEC3 record will do as all NSEC3 + * records from a given zone in a response must use the same + * parameters. */ + zone = dns_resource_key_name(key); + for (;;) { + DNS_ANSWER_FOREACH_FLAGS(zone_rr, flags, answer) { + r = nsec3_is_good(zone_rr, NULL); + if (r < 0) + return r; + if (r == 0) + continue; + + r = dns_name_equal_skip(dns_resource_key_name(zone_rr->key), 1, zone); + if (r < 0) + return r; + if (r > 0) + goto found_zone; + } + + /* Strip one label from the front */ + r = dns_name_parent(&zone); + if (r < 0) + return r; + if (r == 0) + break; + } + + *result = DNSSEC_NSEC_NO_RR; + return 0; + +found_zone: + /* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */ + p = dns_resource_key_name(key); + for (;;) { + _cleanup_free_ char *hashed_domain = NULL; + + hashed_size = nsec3_hashed_domain_make(zone_rr, p, zone, &hashed_domain); + if (hashed_size == -EOPNOTSUPP) { + *result = DNSSEC_NSEC_UNSUPPORTED_ALGORITHM; + return 0; + } + if (hashed_size < 0) + return hashed_size; + + DNS_ANSWER_FOREACH_FLAGS(enclosure_rr, flags, answer) { + + r = nsec3_is_good(enclosure_rr, zone_rr); + if (r < 0) + return r; + if (r == 0) + continue; + + if (enclosure_rr->nsec3.next_hashed_name_size != (size_t) hashed_size) + continue; + + r = dns_name_equal(dns_resource_key_name(enclosure_rr->key), hashed_domain); + if (r < 0) + return r; + if (r > 0) { + a = flags & DNS_ANSWER_AUTHENTICATED; + goto found_closest_encloser; + } + } + + /* We didn't find the closest encloser with this name, + * but let's remember this domain name, it might be + * the next closer name */ + + pp = p; + + /* Strip one label from the front */ + r = dns_name_parent(&p); + if (r < 0) + return r; + if (r == 0) + break; + } + + *result = DNSSEC_NSEC_NO_RR; + return 0; + +found_closest_encloser: + /* We found a closest encloser in 'p'; next closer is 'pp' */ + + if (!pp) { + /* We have an exact match! If we area looking for a DS RR, then we must insist that we got the NSEC3 RR + * from the parent. Otherwise the one from the child. Do so, by checking whether SOA and NS are + * appropriately set. */ + + if (key->type == DNS_TYPE_DS) { + if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA)) + return -EBADMSG; + } else { + if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) && + !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA)) + return -EBADMSG; + } + + /* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */ + if (bitmap_isset(enclosure_rr->nsec3.types, key->type)) + *result = DNSSEC_NSEC_FOUND; + else if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_CNAME)) + *result = DNSSEC_NSEC_CNAME; + else + *result = DNSSEC_NSEC_NODATA; + + if (authenticated) + *authenticated = a; + if (ttl) + *ttl = enclosure_rr->ttl; + + return 0; + } + + /* Ensure this is not a DNAME domain, see RFC5155, section 8.3. */ + if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_DNAME)) + return -EBADMSG; + + /* Ensure that this data is from the delegated domain + * (i.e. originates from the "lower" DNS server), and isn't + * just glue records (i.e. doesn't originate from the "upper" + * DNS server). */ + if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) && + !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA)) + return -EBADMSG; + + /* Prove that there is no next closer and whether or not there is a wildcard domain. */ + + wildcard = strjoina("*.", p); + r = nsec3_hashed_domain_make(enclosure_rr, wildcard, zone, &wildcard_domain); + if (r < 0) + return r; + if (r != hashed_size) + return -EBADMSG; + + r = nsec3_hashed_domain_make(enclosure_rr, pp, zone, &next_closer_domain); + if (r < 0) + return r; + if (r != hashed_size) + return -EBADMSG; + + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + _cleanup_free_ char *next_hashed_domain = NULL; + + r = nsec3_is_good(rr, zone_rr); + if (r < 0) + return r; + if (r == 0) + continue; + + r = nsec3_hashed_domain_format(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, zone, &next_hashed_domain); + if (r < 0) + return r; + + r = dns_name_between(dns_resource_key_name(rr->key), next_closer_domain, next_hashed_domain); + if (r < 0) + return r; + if (r > 0) { + if (rr->nsec3.flags & 1) + optout = true; + + a = a && (flags & DNS_ANSWER_AUTHENTICATED); + + no_closer = true; + } + + r = dns_name_equal(dns_resource_key_name(rr->key), wildcard_domain); + if (r < 0) + return r; + if (r > 0) { + a = a && (flags & DNS_ANSWER_AUTHENTICATED); + + wildcard_rr = rr; + } + + r = dns_name_between(dns_resource_key_name(rr->key), wildcard_domain, next_hashed_domain); + if (r < 0) + return r; + if (r > 0) { + if (rr->nsec3.flags & 1) + /* This only makes sense if we have a wildcard delegation, which is + * very unlikely, see RFC 4592, Section 4.2, but we cannot rely on + * this not happening, so hence cannot simply conclude NXDOMAIN as + * we would wish */ + optout = true; + + a = a && (flags & DNS_ANSWER_AUTHENTICATED); + + no_wildcard = true; + } + } + + if (wildcard_rr && no_wildcard) + return -EBADMSG; + + if (!no_closer) { + *result = DNSSEC_NSEC_NO_RR; + return 0; + } + + if (wildcard_rr) { + /* A wildcard exists that matches our query. */ + if (optout) + /* This is not specified in any RFC to the best of my knowledge, but + * if the next closer enclosure is covered by an opt-out NSEC3 RR + * it means that we cannot prove that the source of synthesis is + * correct, as there may be a closer match. */ + *result = DNSSEC_NSEC_OPTOUT; + else if (bitmap_isset(wildcard_rr->nsec3.types, key->type)) + *result = DNSSEC_NSEC_FOUND; + else if (bitmap_isset(wildcard_rr->nsec3.types, DNS_TYPE_CNAME)) + *result = DNSSEC_NSEC_CNAME; + else + *result = DNSSEC_NSEC_NODATA; + } else { + if (optout) + /* The RFC only specifies that we have to care for optout for NODATA for + * DS records. However, children of an insecure opt-out delegation should + * also be considered opt-out, rather than verified NXDOMAIN. + * Note that we do not require a proof of wildcard non-existence if the + * next closer domain is covered by an opt-out, as that would not provide + * any additional information. */ + *result = DNSSEC_NSEC_OPTOUT; + else if (no_wildcard) + *result = DNSSEC_NSEC_NXDOMAIN; + else { + *result = DNSSEC_NSEC_NO_RR; + + return 0; + } + } + + if (authenticated) + *authenticated = a; + + if (ttl) + *ttl = enclosure_rr->ttl; + + return 0; +} + +static int dnssec_nsec_wildcard_equal(DnsResourceRecord *rr, const char *name) { + char label[DNS_LABEL_MAX]; + const char *n; + int r; + + assert(rr); + assert(rr->key->type == DNS_TYPE_NSEC); + + /* Checks whether the specified RR has a name beginning in "*.", and if the rest is a suffix of our name */ + + if (rr->n_skip_labels_source != 1) + return 0; + + n = dns_resource_key_name(rr->key); + r = dns_label_unescape(&n, label, sizeof label, 0); + if (r <= 0) + return r; + if (r != 1 || label[0] != '*') + return 0; + + return dns_name_endswith(name, n); +} + +static int dnssec_nsec_in_path(DnsResourceRecord *rr, const char *name) { + const char *nn, *common_suffix; + int r; + + assert(rr); + assert(rr->key->type == DNS_TYPE_NSEC); + + /* Checks whether the specified nsec RR indicates that name is an empty non-terminal (ENT) + * + * A couple of examples: + * + * NSEC bar → waldo.foo.bar: indicates that foo.bar exists and is an ENT + * NSEC waldo.foo.bar → yyy.zzz.xoo.bar: indicates that xoo.bar and zzz.xoo.bar exist and are ENTs + * NSEC yyy.zzz.xoo.bar → bar: indicates pretty much nothing about ENTs + */ + + /* First, determine parent of next domain. */ + nn = rr->nsec.next_domain_name; + r = dns_name_parent(&nn); + if (r <= 0) + return r; + + /* If the name we just determined is not equal or child of the name we are interested in, then we can't say + * anything at all. */ + r = dns_name_endswith(nn, name); + if (r <= 0) + return r; + + /* If the name we are interested in is not a prefix of the common suffix of the NSEC RR's owner and next domain names, then we can't say anything either. */ + r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix); + if (r < 0) + return r; + + return dns_name_endswith(name, common_suffix); +} + +static int dnssec_nsec_from_parent_zone(DnsResourceRecord *rr, const char *name) { + int r; + + assert(rr); + assert(rr->key->type == DNS_TYPE_NSEC); + + /* Checks whether this NSEC originates to the parent zone or the child zone. */ + + r = dns_name_parent(&name); + if (r <= 0) + return r; + + r = dns_name_equal(name, dns_resource_key_name(rr->key)); + if (r <= 0) + return r; + + /* DNAME, and NS without SOA is an indication for a delegation. */ + if (bitmap_isset(rr->nsec.types, DNS_TYPE_DNAME)) + return 1; + + if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) && !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA)) + return 1; + + return 0; +} + +static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) { + const char *signer; + int r; + + assert(rr); + assert(rr->key->type == DNS_TYPE_NSEC); + + /* Checks whether the name is covered by this NSEC RR. This means, that the name is somewhere below the NSEC's + * signer name, and between the NSEC's two names. */ + + r = dns_resource_record_signer(rr, &signer); + if (r < 0) + return r; + + r = dns_name_endswith(name, signer); /* this NSEC isn't suitable the name is not in the signer's domain */ + if (r <= 0) + return r; + + return dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name); +} + +static int dnssec_nsec_generate_wildcard(DnsResourceRecord *rr, const char *name, char **wc) { + const char *common_suffix1, *common_suffix2, *signer; + int r, labels1, labels2; + + assert(rr); + assert(rr->key->type == DNS_TYPE_NSEC); + + /* Generates "Wildcard at the Closest Encloser" for the given name and NSEC RR. */ + + r = dns_resource_record_signer(rr, &signer); + if (r < 0) + return r; + + r = dns_name_endswith(name, signer); /* this NSEC isn't suitable the name is not in the signer's domain */ + if (r <= 0) + return r; + + r = dns_name_common_suffix(name, dns_resource_key_name(rr->key), &common_suffix1); + if (r < 0) + return r; + + r = dns_name_common_suffix(name, rr->nsec.next_domain_name, &common_suffix2); + if (r < 0) + return r; + + labels1 = dns_name_count_labels(common_suffix1); + if (labels1 < 0) + return labels1; + + labels2 = dns_name_count_labels(common_suffix2); + if (labels2 < 0) + return labels2; + + if (labels1 > labels2) + r = dns_name_concat("*", common_suffix1, 0, wc); + else + r = dns_name_concat("*", common_suffix2, 0, wc); + + if (r < 0) + return r; + + return 0; +} + +int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) { + bool have_nsec3 = false, covering_rr_authenticated = false, wildcard_rr_authenticated = false; + DnsResourceRecord *rr, *covering_rr = NULL, *wildcard_rr = NULL; + DnsAnswerFlags flags; + const char *name; + int r; + + assert(key); + assert(result); + + /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */ + + name = dns_resource_key_name(key); + + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + + if (rr->key->class != key->class) + continue; + + have_nsec3 = have_nsec3 || (rr->key->type == DNS_TYPE_NSEC3); + + if (rr->key->type != DNS_TYPE_NSEC) + continue; + + /* The following checks only make sense for NSEC RRs that are not expanded from a wildcard */ + r = dns_resource_record_is_synthetic(rr); + if (r < 0) + return r; + if (r > 0) + continue; + + /* Check if this is a direct match. If so, we have encountered a NODATA case */ + r = dns_name_equal(dns_resource_key_name(rr->key), name); + if (r < 0) + return r; + if (r == 0) { + /* If it's not a direct match, maybe it's a wild card match? */ + r = dnssec_nsec_wildcard_equal(rr, name); + if (r < 0) + return r; + } + if (r > 0) { + if (key->type == DNS_TYPE_DS) { + /* If we look for a DS RR and the server sent us the NSEC RR of the child zone + * we have a problem. For DS RRs we want the NSEC RR from the parent */ + if (bitmap_isset(rr->nsec.types, DNS_TYPE_SOA)) + continue; + } else { + /* For all RR types, ensure that if NS is set SOA is set too, so that we know + * we got the child's NSEC. */ + if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) && + !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA)) + continue; + } + + if (bitmap_isset(rr->nsec.types, key->type)) + *result = DNSSEC_NSEC_FOUND; + else if (bitmap_isset(rr->nsec.types, DNS_TYPE_CNAME)) + *result = DNSSEC_NSEC_CNAME; + else + *result = DNSSEC_NSEC_NODATA; + + if (authenticated) + *authenticated = flags & DNS_ANSWER_AUTHENTICATED; + if (ttl) + *ttl = rr->ttl; + + return 0; + } + + /* Check if the name we are looking for is an empty non-terminal within the owner or next name + * of the NSEC RR. */ + r = dnssec_nsec_in_path(rr, name); + if (r < 0) + return r; + if (r > 0) { + *result = DNSSEC_NSEC_NODATA; + + if (authenticated) + *authenticated = flags & DNS_ANSWER_AUTHENTICATED; + if (ttl) + *ttl = rr->ttl; + + return 0; + } + + /* The following two "covering" checks, are not useful if the NSEC is from the parent */ + r = dnssec_nsec_from_parent_zone(rr, name); + if (r < 0) + return r; + if (r > 0) + continue; + + /* Check if this NSEC RR proves the absence of an explicit RR under this name */ + r = dnssec_nsec_covers(rr, name); + if (r < 0) + return r; + if (r > 0 && (!covering_rr || !covering_rr_authenticated)) { + covering_rr = rr; + covering_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED; + } + } + + if (covering_rr) { + _cleanup_free_ char *wc = NULL; + r = dnssec_nsec_generate_wildcard(covering_rr, name, &wc); + if (r < 0) + return r; + + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + + if (rr->key->class != key->class) + continue; + + if (rr->key->type != DNS_TYPE_NSEC) + continue; + + /* Check if this NSEC RR proves the nonexistence of the wildcard */ + r = dnssec_nsec_covers(rr, wc); + if (r < 0) + return r; + if (r > 0 && (!wildcard_rr || !wildcard_rr_authenticated)) { + wildcard_rr = rr; + wildcard_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED; + } + } + } + + if (covering_rr && wildcard_rr) { + /* If we could prove that neither the name itself, nor the wildcard at the closest encloser exists, we + * proved the NXDOMAIN case. */ + *result = DNSSEC_NSEC_NXDOMAIN; + + if (authenticated) + *authenticated = covering_rr_authenticated && wildcard_rr_authenticated; + if (ttl) + *ttl = MIN(covering_rr->ttl, wildcard_rr->ttl); + + return 0; + } + + /* OK, this was not sufficient. Let's see if NSEC3 can help. */ + if (have_nsec3) + return dnssec_test_nsec3(answer, key, result, authenticated, ttl); + + /* No appropriate NSEC RR found, report this. */ + *result = DNSSEC_NSEC_NO_RR; + return 0; +} + +static int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const char *name, const char *zone, bool *authenticated) { + DnsResourceRecord *rr; + DnsAnswerFlags flags; + int r; + + assert(name); + assert(zone); + + /* Checks whether there's an NSEC/NSEC3 that proves that the specified 'name' is non-existing in the specified + * 'zone'. The 'zone' must be a suffix of the 'name'. */ + + DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) { + bool found = false; + + if (rr->key->type != type && type != DNS_TYPE_ANY) + continue; + + switch (rr->key->type) { + + case DNS_TYPE_NSEC: + + /* We only care for NSEC RRs from the indicated zone */ + r = dns_resource_record_is_signer(rr, zone); + if (r < 0) + return r; + if (r == 0) + continue; + + r = dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name); + if (r < 0) + return r; + + found = r > 0; + break; + + case DNS_TYPE_NSEC3: { + _cleanup_free_ char *hashed_domain = NULL, *next_hashed_domain = NULL; + + /* We only care for NSEC3 RRs from the indicated zone */ + r = dns_resource_record_is_signer(rr, zone); + if (r < 0) + return r; + if (r == 0) + continue; + + r = nsec3_is_good(rr, NULL); + if (r < 0) + return r; + if (r == 0) + break; + + /* Format the domain we are testing with the NSEC3 RR's hash function */ + r = nsec3_hashed_domain_make( + rr, + name, + zone, + &hashed_domain); + if (r < 0) + return r; + if ((size_t) r != rr->nsec3.next_hashed_name_size) + break; + + /* Format the NSEC3's next hashed name as proper domain name */ + r = nsec3_hashed_domain_format( + rr->nsec3.next_hashed_name, + rr->nsec3.next_hashed_name_size, + zone, + &next_hashed_domain); + if (r < 0) + return r; + + r = dns_name_between(dns_resource_key_name(rr->key), hashed_domain, next_hashed_domain); + if (r < 0) + return r; + + found = r > 0; + break; + } + + default: + continue; + } + + if (found) { + if (authenticated) + *authenticated = flags & DNS_ANSWER_AUTHENTICATED; + return 1; + } + } + + return 0; +} + +static int dnssec_test_positive_wildcard_nsec3( + DnsAnswer *answer, + const char *name, + const char *source, + const char *zone, + bool *authenticated) { + + const char *next_closer = NULL; + int r; + + /* Run a positive NSEC3 wildcard proof. Specifically: + * + * A proof that the "next closer" of the generating wildcard does not exist. + * + * Note a key difference between the NSEC3 and NSEC versions of the proof. NSEC RRs don't have to exist for + * empty non-transients. NSEC3 RRs however have to. This means it's sufficient to check if the next closer name + * exists for the NSEC3 RR and we are done. + * + * To prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f all we have to check is that + * c.d.e.f does not exist. */ + + for (;;) { + next_closer = name; + r = dns_name_parent(&name); + if (r <= 0) + return r; + + r = dns_name_equal(name, source); + if (r < 0) + return r; + if (r > 0) + break; + } + + return dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC3, next_closer, zone, authenticated); +} + +static int dnssec_test_positive_wildcard_nsec( + DnsAnswer *answer, + const char *name, + const char *source, + const char *zone, + bool *_authenticated) { + + bool authenticated = true; + int r; + + /* Run a positive NSEC wildcard proof. Specifically: + * + * A proof that there's neither a wildcard name nor a non-wildcard name that is a suffix of the name "name" and + * a prefix of the synthesizing source "source" in the zone "zone". + * + * See RFC 5155, Section 8.8 and RFC 4035, Section 5.3.4 + * + * Note that if we want to prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f, then we + * have to prove that none of the following exist: + * + * 1) a.b.c.d.e.f + * 2) *.b.c.d.e.f + * 3) b.c.d.e.f + * 4) *.c.d.e.f + * 5) c.d.e.f + */ + + for (;;) { + _cleanup_free_ char *wc = NULL; + bool a = false; + + /* Check if there's an NSEC or NSEC3 RR that proves that the mame we determined is really non-existing, + * i.e between the owner name and the next name of an NSEC RR. */ + r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, name, zone, &a); + if (r <= 0) + return r; + + authenticated = authenticated && a; + + /* Strip one label off */ + r = dns_name_parent(&name); + if (r <= 0) + return r; + + /* Did we reach the source of synthesis? */ + r = dns_name_equal(name, source); + if (r < 0) + return r; + if (r > 0) { + /* Successful exit */ + *_authenticated = authenticated; + return 1; + } + + /* Safety check, that the source of synthesis is still our suffix */ + r = dns_name_endswith(name, source); + if (r < 0) + return r; + if (r == 0) + return -EBADMSG; + + /* Replace the label we stripped off with an asterisk */ + wc = strjoin("*.", name); + if (!wc) + return -ENOMEM; + + /* And check if the proof holds for the asterisk name, too */ + r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, wc, zone, &a); + if (r <= 0) + return r; + + authenticated = authenticated && a; + /* In the next iteration we'll check the non-asterisk-prefixed version */ + } +} + +int dnssec_test_positive_wildcard( + DnsAnswer *answer, + const char *name, + const char *source, + const char *zone, + bool *authenticated) { + + int r; + + assert(name); + assert(source); + assert(zone); + assert(authenticated); + + r = dns_answer_contains_zone_nsec3(answer, zone); + if (r < 0) + return r; + if (r > 0) + return dnssec_test_positive_wildcard_nsec3(answer, name, source, zone, authenticated); + else + return dnssec_test_positive_wildcard_nsec(answer, name, source, zone, authenticated); +} + +#else + +int dnssec_verify_rrset( + DnsAnswer *a, + const DnsResourceKey *key, + DnsResourceRecord *rrsig, + DnsResourceRecord *dnskey, + usec_t realtime, + DnssecResult *result) { + + return -EOPNOTSUPP; +} + +int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) { + + return -EOPNOTSUPP; +} + +int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) { + + return -EOPNOTSUPP; +} + +int dnssec_verify_rrset_search( + DnsAnswer *a, + const DnsResourceKey *key, + DnsAnswer *validated_dnskeys, + usec_t realtime, + DnssecResult *result, + DnsResourceRecord **ret_rrsig) { + + return -EOPNOTSUPP; +} + +int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) { + + return -EOPNOTSUPP; +} + +int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) { + + return -EOPNOTSUPP; +} + +int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) { + + return -EOPNOTSUPP; +} + +int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) { + + return -EOPNOTSUPP; +} + +int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) { + + return -EOPNOTSUPP; +} + +int dnssec_test_positive_wildcard( + DnsAnswer *answer, + const char *name, + const char *source, + const char *zone, + bool *authenticated) { + + return -EOPNOTSUPP; +} + +#endif + +static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = { + [DNSSEC_VALIDATED] = "validated", + [DNSSEC_VALIDATED_WILDCARD] = "validated-wildcard", + [DNSSEC_INVALID] = "invalid", + [DNSSEC_SIGNATURE_EXPIRED] = "signature-expired", + [DNSSEC_UNSUPPORTED_ALGORITHM] = "unsupported-algorithm", + [DNSSEC_NO_SIGNATURE] = "no-signature", + [DNSSEC_MISSING_KEY] = "missing-key", + [DNSSEC_UNSIGNED] = "unsigned", + [DNSSEC_FAILED_AUXILIARY] = "failed-auxiliary", + [DNSSEC_NSEC_MISMATCH] = "nsec-mismatch", + [DNSSEC_INCOMPATIBLE_SERVER] = "incompatible-server", +}; +DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult); + +static const char* const dnssec_verdict_table[_DNSSEC_VERDICT_MAX] = { + [DNSSEC_SECURE] = "secure", + [DNSSEC_INSECURE] = "insecure", + [DNSSEC_BOGUS] = "bogus", + [DNSSEC_INDETERMINATE] = "indeterminate", +}; +DEFINE_STRING_TABLE_LOOKUP(dnssec_verdict, DnssecVerdict); diff --git a/src/resolve/resolved-dns-dnssec.h b/src/resolve/resolved-dns-dnssec.h new file mode 100644 index 00000000..dfee7232 --- /dev/null +++ b/src/resolve/resolved-dns-dnssec.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef enum DnssecResult DnssecResult; +typedef enum DnssecVerdict DnssecVerdict; + +#include "dns-domain.h" +#include "resolved-dns-answer.h" +#include "resolved-dns-rr.h" + +enum DnssecResult { + /* These five are returned by dnssec_verify_rrset() */ + DNSSEC_VALIDATED, + DNSSEC_VALIDATED_WILDCARD, /* Validated via a wildcard RRSIG, further NSEC/NSEC3 checks necessary */ + DNSSEC_INVALID, + DNSSEC_SIGNATURE_EXPIRED, + DNSSEC_UNSUPPORTED_ALGORITHM, + + /* These two are added by dnssec_verify_rrset_search() */ + DNSSEC_NO_SIGNATURE, + DNSSEC_MISSING_KEY, + + /* These two are added by the DnsTransaction logic */ + DNSSEC_UNSIGNED, + DNSSEC_FAILED_AUXILIARY, + DNSSEC_NSEC_MISMATCH, + DNSSEC_INCOMPATIBLE_SERVER, + + _DNSSEC_RESULT_MAX, + _DNSSEC_RESULT_INVALID = -1 +}; + +enum DnssecVerdict { + DNSSEC_SECURE, + DNSSEC_INSECURE, + DNSSEC_BOGUS, + DNSSEC_INDETERMINATE, + + _DNSSEC_VERDICT_MAX, + _DNSSEC_VERDICT_INVALID = -1 +}; + +#define DNSSEC_CANONICAL_HOSTNAME_MAX (DNS_HOSTNAME_MAX + 2) + +/* The longest digest we'll ever generate, of all digest algorithms we support */ +#define DNSSEC_HASH_SIZE_MAX (MAX(20, 32)) + +int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok); +int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig); + +int dnssec_verify_rrset(DnsAnswer *answer, const DnsResourceKey *key, DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, usec_t realtime, DnssecResult *result); +int dnssec_verify_rrset_search(DnsAnswer *answer, const DnsResourceKey *key, DnsAnswer *validated_dnskeys, usec_t realtime, DnssecResult *result, DnsResourceRecord **rrsig); + +int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke); +int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds); + +int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key); + +uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke); + +int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max); + +int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret); + +typedef enum DnssecNsecResult { + DNSSEC_NSEC_NO_RR, /* No suitable NSEC/NSEC3 RR found */ + DNSSEC_NSEC_CNAME, /* Didn't find what was asked for, but did find CNAME */ + DNSSEC_NSEC_UNSUPPORTED_ALGORITHM, + DNSSEC_NSEC_NXDOMAIN, + DNSSEC_NSEC_NODATA, + DNSSEC_NSEC_FOUND, + DNSSEC_NSEC_OPTOUT, +} DnssecNsecResult; + +int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl); + +int dnssec_test_positive_wildcard(DnsAnswer *a, const char *name, const char *source, const char *zone, bool *authenticated); + +const char* dnssec_result_to_string(DnssecResult m) _const_; +DnssecResult dnssec_result_from_string(const char *s) _pure_; + +const char* dnssec_verdict_to_string(DnssecVerdict m) _const_; +DnssecVerdict dnssec_verdict_from_string(const char *s) _pure_; diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c new file mode 100644 index 00000000..05aaa0fb --- /dev/null +++ b/src/resolve/resolved-dns-packet.c @@ -0,0 +1,2400 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if HAVE_GCRYPT +#include +#endif + +#include "alloc-util.h" +#include "dns-domain.h" +#include "memory-util.h" +#include "resolved-dns-packet.h" +#include "set.h" +#include "string-table.h" +#include "strv.h" +#include "unaligned.h" +#include "utf8.h" +#include "util.h" + +#define EDNS0_OPT_DO (1<<15) + +assert_cc(DNS_PACKET_SIZE_START > DNS_PACKET_HEADER_SIZE); + +typedef struct DnsPacketRewinder { + DnsPacket *packet; + size_t saved_rindex; +} DnsPacketRewinder; + +static void rewind_dns_packet(DnsPacketRewinder *rewinder) { + if (rewinder->packet) + dns_packet_rewind(rewinder->packet, rewinder->saved_rindex); +} + +#define INIT_REWINDER(rewinder, p) do { rewinder.packet = p; rewinder.saved_rindex = p->rindex; } while (0) +#define CANCEL_REWINDER(rewinder) do { rewinder.packet = NULL; } while (0) + +int dns_packet_new( + DnsPacket **ret, + DnsProtocol protocol, + size_t min_alloc_dsize, + size_t max_size) { + + DnsPacket *p; + size_t a; + + assert(ret); + assert(max_size >= DNS_PACKET_HEADER_SIZE); + + if (max_size > DNS_PACKET_SIZE_MAX) + max_size = DNS_PACKET_SIZE_MAX; + + /* The caller may not check what is going to be truly allocated, so do not allow to + * allocate a DNS packet bigger than DNS_PACKET_SIZE_MAX. + */ + if (min_alloc_dsize > DNS_PACKET_SIZE_MAX) + return log_error_errno(SYNTHETIC_ERRNO(EFBIG), + "Requested packet data size too big: %zu", + min_alloc_dsize); + + /* When dns_packet_new() is called with min_alloc_dsize == 0, allocate more than the + * absolute minimum (which is the dns packet header size), to avoid + * resizing immediately again after appending the first data to the packet. + */ + if (min_alloc_dsize < DNS_PACKET_HEADER_SIZE) + a = DNS_PACKET_SIZE_START; + else + a = min_alloc_dsize; + + /* round up to next page size */ + a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket)); + + /* make sure we never allocate more than useful */ + if (a > max_size) + a = max_size; + + p = malloc0(ALIGN(sizeof(DnsPacket)) + a); + if (!p) + return -ENOMEM; + + p->size = p->rindex = DNS_PACKET_HEADER_SIZE; + p->allocated = a; + p->max_size = max_size; + p->protocol = protocol; + p->opt_start = p->opt_size = (size_t) -1; + p->n_ref = 1; + + *ret = p; + + return 0; +} + +void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) { + + DnsPacketHeader *h; + + assert(p); + + h = DNS_PACKET_HEADER(p); + + switch(p->protocol) { + case DNS_PROTOCOL_LLMNR: + assert(!truncated); + + h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */, + 0 /* opcode */, + 0 /* c */, + 0 /* tc */, + 0 /* t */, + 0 /* ra */, + 0 /* ad */, + 0 /* cd */, + 0 /* rcode */)); + break; + + case DNS_PROTOCOL_MDNS: + h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */, + 0 /* opcode */, + 0 /* aa */, + truncated /* tc */, + 0 /* rd (ask for recursion) */, + 0 /* ra */, + 0 /* ad */, + 0 /* cd */, + 0 /* rcode */)); + break; + + default: + assert(!truncated); + + h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */, + 0 /* opcode */, + 0 /* aa */, + 0 /* tc */, + 1 /* rd (ask for recursion) */, + 0 /* ra */, + 0 /* ad */, + dnssec_checking_disabled /* cd */, + 0 /* rcode */)); + } +} + +int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled) { + DnsPacket *p; + int r; + + assert(ret); + + r = dns_packet_new(&p, protocol, min_alloc_dsize, DNS_PACKET_SIZE_MAX); + if (r < 0) + return r; + + /* Always set the TC bit to 0 initially. + * If there are multiple packets later, we'll update the bit shortly before sending. + */ + dns_packet_set_flags(p, dnssec_checking_disabled, false); + + *ret = p; + return 0; +} + +DnsPacket *dns_packet_ref(DnsPacket *p) { + + if (!p) + return NULL; + + assert(!p->on_stack); + + assert(p->n_ref > 0); + p->n_ref++; + return p; +} + +static void dns_packet_free(DnsPacket *p) { + char *s; + + assert(p); + + dns_question_unref(p->question); + dns_answer_unref(p->answer); + dns_resource_record_unref(p->opt); + + while ((s = hashmap_steal_first_key(p->names))) + free(s); + hashmap_free(p->names); + + free(p->_data); + + if (!p->on_stack) + free(p); +} + +DnsPacket *dns_packet_unref(DnsPacket *p) { + if (!p) + return NULL; + + assert(p->n_ref > 0); + + dns_packet_unref(p->more); + + if (p->n_ref == 1) + dns_packet_free(p); + else + p->n_ref--; + + return NULL; +} + +int dns_packet_validate(DnsPacket *p) { + assert(p); + + if (p->size < DNS_PACKET_HEADER_SIZE) + return -EBADMSG; + + if (p->size > DNS_PACKET_SIZE_MAX) + return -EBADMSG; + + return 1; +} + +int dns_packet_validate_reply(DnsPacket *p) { + int r; + + assert(p); + + r = dns_packet_validate(p); + if (r < 0) + return r; + + if (DNS_PACKET_QR(p) != 1) + return 0; + + if (DNS_PACKET_OPCODE(p) != 0) + return -EBADMSG; + + switch (p->protocol) { + + case DNS_PROTOCOL_LLMNR: + /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */ + if (DNS_PACKET_QDCOUNT(p) != 1) + return -EBADMSG; + + break; + + case DNS_PROTOCOL_MDNS: + /* RFC 6762, Section 18 */ + if (DNS_PACKET_RCODE(p) != 0) + return -EBADMSG; + + break; + + default: + break; + } + + return 1; +} + +int dns_packet_validate_query(DnsPacket *p) { + int r; + + assert(p); + + r = dns_packet_validate(p); + if (r < 0) + return r; + + if (DNS_PACKET_QR(p) != 0) + return 0; + + if (DNS_PACKET_OPCODE(p) != 0) + return -EBADMSG; + + if (DNS_PACKET_TC(p)) + return -EBADMSG; + + switch (p->protocol) { + + case DNS_PROTOCOL_LLMNR: + case DNS_PROTOCOL_DNS: + /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */ + if (DNS_PACKET_QDCOUNT(p) != 1) + return -EBADMSG; + + /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */ + if (DNS_PACKET_ANCOUNT(p) > 0) + return -EBADMSG; + + /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */ + if (DNS_PACKET_NSCOUNT(p) > 0) + return -EBADMSG; + + break; + + case DNS_PROTOCOL_MDNS: + /* RFC 6762, Section 18 */ + if (DNS_PACKET_AA(p) != 0 || + DNS_PACKET_RD(p) != 0 || + DNS_PACKET_RA(p) != 0 || + DNS_PACKET_AD(p) != 0 || + DNS_PACKET_CD(p) != 0 || + DNS_PACKET_RCODE(p) != 0) + return -EBADMSG; + + break; + + default: + break; + } + + return 1; +} + +static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) { + assert(p); + + if (p->size + add > p->allocated) { + size_t a, ms; + + a = PAGE_ALIGN((p->size + add) * 2); + + ms = dns_packet_size_max(p); + if (a > ms) + a = ms; + + if (p->size + add > a) + return -EMSGSIZE; + + if (p->_data) { + void *d; + + d = realloc(p->_data, a); + if (!d) + return -ENOMEM; + + p->_data = d; + } else { + p->_data = malloc(a); + if (!p->_data) + return -ENOMEM; + + memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size); + memzero((uint8_t*) p->_data + p->size, a - p->size); + } + + p->allocated = a; + } + + if (start) + *start = p->size; + + if (ret) + *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size; + + p->size += add; + return 0; +} + +void dns_packet_truncate(DnsPacket *p, size_t sz) { + Iterator i; + char *s; + void *n; + + assert(p); + + if (p->size <= sz) + return; + + HASHMAP_FOREACH_KEY(n, s, p->names, i) { + + if (PTR_TO_SIZE(n) < sz) + continue; + + hashmap_remove(p->names, s); + free(s); + } + + p->size = sz; +} + +int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) { + void *q; + int r; + + assert(p); + + r = dns_packet_extend(p, l, &q, start); + if (r < 0) + return r; + + memcpy_safe(q, d, l); + return 0; +} + +int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) { + void *d; + int r; + + assert(p); + + r = dns_packet_extend(p, sizeof(uint8_t), &d, start); + if (r < 0) + return r; + + ((uint8_t*) d)[0] = v; + + return 0; +} + +int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) { + void *d; + int r; + + assert(p); + + r = dns_packet_extend(p, sizeof(uint16_t), &d, start); + if (r < 0) + return r; + + unaligned_write_be16(d, v); + + return 0; +} + +int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) { + void *d; + int r; + + assert(p); + + r = dns_packet_extend(p, sizeof(uint32_t), &d, start); + if (r < 0) + return r; + + unaligned_write_be32(d, v); + + return 0; +} + +int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) { + assert(p); + assert(s); + + return dns_packet_append_raw_string(p, s, strlen(s), start); +} + +int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) { + void *d; + int r; + + assert(p); + assert(s || size == 0); + + if (size > 255) + return -E2BIG; + + r = dns_packet_extend(p, 1 + size, &d, start); + if (r < 0) + return r; + + ((uint8_t*) d)[0] = (uint8_t) size; + + memcpy_safe(((uint8_t*) d) + 1, s, size); + + return 0; +} + +int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, bool canonical_candidate, size_t *start) { + uint8_t *w; + int r; + + /* Append a label to a packet. Optionally, does this in DNSSEC + * canonical form, if this label is marked as a candidate for + * it, and the canonical form logic is enabled for the + * packet */ + + assert(p); + assert(d); + + if (l > DNS_LABEL_MAX) + return -E2BIG; + + r = dns_packet_extend(p, 1 + l, (void**) &w, start); + if (r < 0) + return r; + + *(w++) = (uint8_t) l; + + if (p->canonical_form && canonical_candidate) { + size_t i; + + /* Generate in canonical form, as defined by DNSSEC + * RFC 4034, Section 6.2, i.e. all lower-case. */ + + for (i = 0; i < l; i++) + w[i] = (uint8_t) ascii_tolower(d[i]); + } else + /* Otherwise, just copy the string unaltered. This is + * essential for DNS-SD, where the casing of labels + * matters and needs to be retained. */ + memcpy(w, d, l); + + return 0; +} + +int dns_packet_append_name( + DnsPacket *p, + const char *name, + bool allow_compression, + bool canonical_candidate, + size_t *start) { + + size_t saved_size; + int r; + + assert(p); + assert(name); + + if (p->refuse_compression) + allow_compression = false; + + saved_size = p->size; + + while (!dns_name_is_root(name)) { + const char *z = name; + char label[DNS_LABEL_MAX]; + size_t n = 0; + + if (allow_compression) + n = PTR_TO_SIZE(hashmap_get(p->names, name)); + if (n > 0) { + assert(n < p->size); + + if (n < 0x4000) { + r = dns_packet_append_uint16(p, 0xC000 | n, NULL); + if (r < 0) + goto fail; + + goto done; + } + } + + r = dns_label_unescape(&name, label, sizeof label, 0); + if (r < 0) + goto fail; + + r = dns_packet_append_label(p, label, r, canonical_candidate, &n); + if (r < 0) + goto fail; + + if (allow_compression) { + _cleanup_free_ char *s = NULL; + + s = strdup(z); + if (!s) { + r = -ENOMEM; + goto fail; + } + + r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops); + if (r < 0) + goto fail; + + r = hashmap_put(p->names, s, SIZE_TO_PTR(n)); + if (r < 0) + goto fail; + + s = NULL; + } + } + + r = dns_packet_append_uint8(p, 0, NULL); + if (r < 0) + return r; + +done: + if (start) + *start = saved_size; + + return 0; + +fail: + dns_packet_truncate(p, saved_size); + return r; +} + +int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, const DnsAnswerFlags flags, size_t *start) { + size_t saved_size; + uint16_t class; + int r; + + assert(p); + assert(k); + + saved_size = p->size; + + r = dns_packet_append_name(p, dns_resource_key_name(k), true, true, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint16(p, k->type, NULL); + if (r < 0) + goto fail; + + class = flags & DNS_ANSWER_CACHE_FLUSH ? k->class | MDNS_RR_CACHE_FLUSH : k->class; + r = dns_packet_append_uint16(p, class, NULL); + if (r < 0) + goto fail; + + if (start) + *start = saved_size; + + return 0; + +fail: + dns_packet_truncate(p, saved_size); + return r; +} + +static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, const uint8_t *types, size_t *start) { + size_t saved_size; + int r; + + assert(p); + assert(types); + assert(length > 0); + + saved_size = p->size; + + r = dns_packet_append_uint8(p, window, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, length, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, types, length, NULL); + if (r < 0) + goto fail; + + if (start) + *start = saved_size; + + return 0; +fail: + dns_packet_truncate(p, saved_size); + return r; +} + +static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) { + Iterator i; + uint8_t window = 0; + uint8_t entry = 0; + uint8_t bitmaps[32] = {}; + unsigned n; + size_t saved_size; + int r; + + assert(p); + + saved_size = p->size; + + BITMAP_FOREACH(n, types, i) { + assert(n <= 0xffff); + + if ((n >> 8) != window && bitmaps[entry / 8] != 0) { + r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL); + if (r < 0) + goto fail; + + zero(bitmaps); + } + + window = n >> 8; + entry = n & 255; + + bitmaps[entry / 8] |= 1 << (7 - (entry % 8)); + } + + if (bitmaps[entry / 8] != 0) { + r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL); + if (r < 0) + goto fail; + } + + if (start) + *start = saved_size; + + return 0; +fail: + dns_packet_truncate(p, saved_size); + return r; +} + +/* Append the OPT pseudo-RR described in RFC6891 */ +int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, int rcode, size_t *start) { + size_t saved_size; + int r; + + assert(p); + /* we must never advertise supported packet size smaller than the legacy max */ + assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX); + assert(rcode >= 0); + assert(rcode <= _DNS_RCODE_MAX); + + if (p->opt_start != (size_t) -1) + return -EBUSY; + + assert(p->opt_size == (size_t) -1); + + saved_size = p->size; + + /* empty name */ + r = dns_packet_append_uint8(p, 0, NULL); + if (r < 0) + return r; + + /* type */ + r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL); + if (r < 0) + goto fail; + + /* class: maximum udp packet that can be received */ + r = dns_packet_append_uint16(p, max_udp_size, NULL); + if (r < 0) + goto fail; + + /* extended RCODE and VERSION */ + r = dns_packet_append_uint16(p, ((uint16_t) rcode & 0x0FF0) << 4, NULL); + if (r < 0) + goto fail; + + /* flags: DNSSEC OK (DO), see RFC3225 */ + r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO : 0, NULL); + if (r < 0) + goto fail; + + /* RDLENGTH */ + if (edns0_do && !DNS_PACKET_QR(p)) { + /* If DO is on and this is not a reply, also append RFC6975 Algorithm data */ + + static const uint8_t rfc6975[] = { + + 0, 5, /* OPTION_CODE: DAU */ +#if HAVE_GCRYPT && GCRYPT_VERSION_NUMBER >= 0x010600 + 0, 7, /* LIST_LENGTH */ +#else + 0, 6, /* LIST_LENGTH */ +#endif + DNSSEC_ALGORITHM_RSASHA1, + DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1, + DNSSEC_ALGORITHM_RSASHA256, + DNSSEC_ALGORITHM_RSASHA512, + DNSSEC_ALGORITHM_ECDSAP256SHA256, + DNSSEC_ALGORITHM_ECDSAP384SHA384, +#if HAVE_GCRYPT && GCRYPT_VERSION_NUMBER >= 0x010600 + DNSSEC_ALGORITHM_ED25519, +#endif + + 0, 6, /* OPTION_CODE: DHU */ + 0, 3, /* LIST_LENGTH */ + DNSSEC_DIGEST_SHA1, + DNSSEC_DIGEST_SHA256, + DNSSEC_DIGEST_SHA384, + + 0, 7, /* OPTION_CODE: N3U */ + 0, 1, /* LIST_LENGTH */ + NSEC3_ALGORITHM_SHA1, + }; + + r = dns_packet_append_uint16(p, sizeof(rfc6975), NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rfc6975, sizeof(rfc6975), NULL); + } else + r = dns_packet_append_uint16(p, 0, NULL); + if (r < 0) + goto fail; + + DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) + 1); + + p->opt_start = saved_size; + p->opt_size = p->size - saved_size; + + if (start) + *start = saved_size; + + return 0; + +fail: + dns_packet_truncate(p, saved_size); + return r; +} + +int dns_packet_truncate_opt(DnsPacket *p) { + assert(p); + + if (p->opt_start == (size_t) -1) { + assert(p->opt_size == (size_t) -1); + return 0; + } + + assert(p->opt_size != (size_t) -1); + assert(DNS_PACKET_ARCOUNT(p) > 0); + + if (p->opt_start + p->opt_size != p->size) + return -EBUSY; + + dns_packet_truncate(p, p->opt_start); + DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) - 1); + p->opt_start = p->opt_size = (size_t) -1; + + return 1; +} + +int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start) { + + size_t saved_size, rdlength_offset, end, rdlength, rds; + uint32_t ttl; + int r; + + assert(p); + assert(rr); + + saved_size = p->size; + + r = dns_packet_append_key(p, rr->key, flags, NULL); + if (r < 0) + goto fail; + + ttl = flags & DNS_ANSWER_GOODBYE ? 0 : rr->ttl; + r = dns_packet_append_uint32(p, ttl, NULL); + if (r < 0) + goto fail; + + /* Initially we write 0 here */ + r = dns_packet_append_uint16(p, 0, &rdlength_offset); + if (r < 0) + goto fail; + + rds = p->size - saved_size; + + switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { + + case DNS_TYPE_SRV: + r = dns_packet_append_uint16(p, rr->srv.priority, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint16(p, rr->srv.weight, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint16(p, rr->srv.port, NULL); + if (r < 0) + goto fail; + + /* RFC 2782 states "Unless and until permitted by future standards + * action, name compression is not to be used for this field." */ + r = dns_packet_append_name(p, rr->srv.name, false, false, NULL); + break; + + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: + r = dns_packet_append_name(p, rr->ptr.name, true, false, NULL); + break; + + case DNS_TYPE_HINFO: + r = dns_packet_append_string(p, rr->hinfo.cpu, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_string(p, rr->hinfo.os, NULL); + break; + + case DNS_TYPE_SPF: /* exactly the same as TXT */ + case DNS_TYPE_TXT: + + if (!rr->txt.items) { + /* RFC 6763, section 6.1 suggests to generate + * single empty string for an empty array. */ + + r = dns_packet_append_raw_string(p, NULL, 0, NULL); + if (r < 0) + goto fail; + } else { + DnsTxtItem *i; + + LIST_FOREACH(items, i, rr->txt.items) { + r = dns_packet_append_raw_string(p, i->data, i->length, NULL); + if (r < 0) + goto fail; + } + } + + r = 0; + break; + + case DNS_TYPE_A: + r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL); + break; + + case DNS_TYPE_AAAA: + r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL); + break; + + case DNS_TYPE_SOA: + r = dns_packet_append_name(p, rr->soa.mname, true, false, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_name(p, rr->soa.rname, true, false, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->soa.serial, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->soa.refresh, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->soa.retry, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->soa.expire, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->soa.minimum, NULL); + break; + + case DNS_TYPE_MX: + r = dns_packet_append_uint16(p, rr->mx.priority, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_name(p, rr->mx.exchange, true, false, NULL); + break; + + case DNS_TYPE_LOC: + r = dns_packet_append_uint8(p, rr->loc.version, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->loc.size, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->loc.latitude, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->loc.longitude, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->loc.altitude, NULL); + break; + + case DNS_TYPE_DS: + r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL); + break; + + case DNS_TYPE_SSHFP: + r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL); + break; + + case DNS_TYPE_DNSKEY: + r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL); + break; + + case DNS_TYPE_RRSIG: + r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL); + break; + + case DNS_TYPE_NSEC: + r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_types(p, rr->nsec.types, NULL); + if (r < 0) + goto fail; + + break; + + case DNS_TYPE_NSEC3: + r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_types(p, rr->nsec3.types, NULL); + if (r < 0) + goto fail; + + break; + + case DNS_TYPE_TLSA: + r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL); + break; + + case DNS_TYPE_CAA: + r = dns_packet_append_uint8(p, rr->caa.flags, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_string(p, rr->caa.tag, NULL); + if (r < 0) + goto fail; + + r = dns_packet_append_blob(p, rr->caa.value, rr->caa.value_size, NULL); + break; + + case DNS_TYPE_OPT: + case DNS_TYPE_OPENPGPKEY: + case _DNS_TYPE_INVALID: /* unparseable */ + default: + + r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL); + break; + } + if (r < 0) + goto fail; + + /* Let's calculate the actual data size and update the field */ + rdlength = p->size - rdlength_offset - sizeof(uint16_t); + if (rdlength > 0xFFFF) { + r = -ENOSPC; + goto fail; + } + + end = p->size; + p->size = rdlength_offset; + r = dns_packet_append_uint16(p, rdlength, NULL); + if (r < 0) + goto fail; + p->size = end; + + if (start) + *start = saved_size; + + if (rdata_start) + *rdata_start = rds; + + return 0; + +fail: + dns_packet_truncate(p, saved_size); + return r; +} + +int dns_packet_append_question(DnsPacket *p, DnsQuestion *q) { + DnsResourceKey *key; + int r; + + assert(p); + + DNS_QUESTION_FOREACH(key, q) { + r = dns_packet_append_key(p, key, 0, NULL); + if (r < 0) + return r; + } + + return 0; +} + +int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a) { + DnsResourceRecord *rr; + DnsAnswerFlags flags; + int r; + + assert(p); + + DNS_ANSWER_FOREACH_FLAGS(rr, flags, a) { + r = dns_packet_append_rr(p, rr, flags, NULL, NULL); + if (r < 0) + return r; + } + + return 0; +} + +int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) { + assert(p); + + if (p->rindex + sz > p->size) + return -EMSGSIZE; + + if (ret) + *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex; + + if (start) + *start = p->rindex; + + p->rindex += sz; + return 0; +} + +void dns_packet_rewind(DnsPacket *p, size_t idx) { + assert(p); + assert(idx <= p->size); + assert(idx >= DNS_PACKET_HEADER_SIZE); + + p->rindex = idx; +} + +int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) { + const void *q; + int r; + + assert(p); + assert(d); + + r = dns_packet_read(p, sz, &q, start); + if (r < 0) + return r; + + memcpy(d, q, sz); + return 0; +} + +static int dns_packet_read_memdup( + DnsPacket *p, size_t size, + void **ret, size_t *ret_size, + size_t *ret_start) { + + const void *src; + size_t start; + int r; + + assert(p); + assert(ret); + + r = dns_packet_read(p, size, &src, &start); + if (r < 0) + return r; + + if (size <= 0) + *ret = NULL; + else { + void *copy; + + copy = memdup(src, size); + if (!copy) + return -ENOMEM; + + *ret = copy; + } + + if (ret_size) + *ret_size = size; + if (ret_start) + *ret_start = start; + + return 0; +} + +int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) { + const void *d; + int r; + + assert(p); + + r = dns_packet_read(p, sizeof(uint8_t), &d, start); + if (r < 0) + return r; + + *ret = ((uint8_t*) d)[0]; + return 0; +} + +int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) { + const void *d; + int r; + + assert(p); + + r = dns_packet_read(p, sizeof(uint16_t), &d, start); + if (r < 0) + return r; + + *ret = unaligned_read_be16(d); + + return 0; +} + +int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) { + const void *d; + int r; + + assert(p); + + r = dns_packet_read(p, sizeof(uint32_t), &d, start); + if (r < 0) + return r; + + *ret = unaligned_read_be32(d); + + return 0; +} + +int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) { + _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder; + const void *d; + char *t; + uint8_t c; + int r; + + assert(p); + INIT_REWINDER(rewinder, p); + + r = dns_packet_read_uint8(p, &c, NULL); + if (r < 0) + return r; + + r = dns_packet_read(p, c, &d, NULL); + if (r < 0) + return r; + + if (memchr(d, 0, c)) + return -EBADMSG; + + t = strndup(d, c); + if (!t) + return -ENOMEM; + + if (!utf8_is_valid(t)) { + free(t); + return -EBADMSG; + } + + *ret = t; + + if (start) + *start = rewinder.saved_rindex; + CANCEL_REWINDER(rewinder); + + return 0; +} + +int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) { + _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder; + uint8_t c; + int r; + + assert(p); + INIT_REWINDER(rewinder, p); + + r = dns_packet_read_uint8(p, &c, NULL); + if (r < 0) + return r; + + r = dns_packet_read(p, c, ret, NULL); + if (r < 0) + return r; + + if (size) + *size = c; + if (start) + *start = rewinder.saved_rindex; + CANCEL_REWINDER(rewinder); + + return 0; +} + +int dns_packet_read_name( + DnsPacket *p, + char **_ret, + bool allow_compression, + size_t *start) { + + _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder; + size_t after_rindex = 0, jump_barrier; + _cleanup_free_ char *ret = NULL; + size_t n = 0, allocated = 0; + bool first = true; + int r; + + assert(p); + assert(_ret); + INIT_REWINDER(rewinder, p); + jump_barrier = p->rindex; + + if (p->refuse_compression) + allow_compression = false; + + for (;;) { + uint8_t c, d; + + r = dns_packet_read_uint8(p, &c, NULL); + if (r < 0) + return r; + + if (c == 0) + /* End of name */ + break; + else if (c <= 63) { + const char *label; + + /* Literal label */ + r = dns_packet_read(p, c, (const void**) &label, NULL); + if (r < 0) + return r; + + if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) + return -ENOMEM; + + if (first) + first = false; + else + ret[n++] = '.'; + + r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX); + if (r < 0) + return r; + + n += r; + continue; + } else if (allow_compression && (c & 0xc0) == 0xc0) { + uint16_t ptr; + + /* Pointer */ + r = dns_packet_read_uint8(p, &d, NULL); + if (r < 0) + return r; + + ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d; + if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) + return -EBADMSG; + + if (after_rindex == 0) + after_rindex = p->rindex; + + /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */ + jump_barrier = ptr; + p->rindex = ptr; + } else + return -EBADMSG; + } + + if (!GREEDY_REALLOC(ret, allocated, n + 1)) + return -ENOMEM; + + ret[n] = 0; + + if (after_rindex != 0) + p->rindex= after_rindex; + + *_ret = TAKE_PTR(ret); + + if (start) + *start = rewinder.saved_rindex; + CANCEL_REWINDER(rewinder); + + return 0; +} + +static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) { + uint8_t window; + uint8_t length; + const uint8_t *bitmap; + uint8_t bit = 0; + unsigned i; + bool found = false; + _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder; + int r; + + assert(p); + assert(types); + INIT_REWINDER(rewinder, p); + + r = bitmap_ensure_allocated(types); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &window, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &length, NULL); + if (r < 0) + return r; + + if (length == 0 || length > 32) + return -EBADMSG; + + r = dns_packet_read(p, length, (const void **)&bitmap, NULL); + if (r < 0) + return r; + + for (i = 0; i < length; i++) { + uint8_t bitmask = 1 << 7; + + if (!bitmap[i]) { + found = false; + bit += 8; + continue; + } + + found = true; + + for (; bitmask; bit++, bitmask >>= 1) + if (bitmap[i] & bitmask) { + uint16_t n; + + n = (uint16_t) window << 8 | (uint16_t) bit; + + /* Ignore pseudo-types. see RFC4034 section 4.1.2 */ + if (dns_type_is_pseudo(n)) + continue; + + r = bitmap_set(*types, n); + if (r < 0) + return r; + } + } + + if (!found) + return -EBADMSG; + + if (start) + *start = rewinder.saved_rindex; + CANCEL_REWINDER(rewinder); + + return 0; +} + +static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) { + _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder; + int r; + + INIT_REWINDER(rewinder, p); + + while (p->rindex < rewinder.saved_rindex + size) { + r = dns_packet_read_type_window(p, types, NULL); + if (r < 0) + return r; + + /* don't read past end of current RR */ + if (p->rindex > rewinder.saved_rindex + size) + return -EBADMSG; + } + + if (p->rindex != rewinder.saved_rindex + size) + return -EBADMSG; + + if (start) + *start = rewinder.saved_rindex; + CANCEL_REWINDER(rewinder); + + return 0; +} + +int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start) { + _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder; + _cleanup_free_ char *name = NULL; + bool cache_flush = false; + uint16_t class, type; + DnsResourceKey *key; + int r; + + assert(p); + assert(ret); + INIT_REWINDER(rewinder, p); + + r = dns_packet_read_name(p, &name, true, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint16(p, &type, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint16(p, &class, NULL); + if (r < 0) + return r; + + if (p->protocol == DNS_PROTOCOL_MDNS) { + /* See RFC6762, Section 10.2 */ + + if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH)) { + class &= ~MDNS_RR_CACHE_FLUSH; + cache_flush = true; + } + } + + key = dns_resource_key_new_consume(class, type, name); + if (!key) + return -ENOMEM; + + name = NULL; + *ret = key; + + if (ret_cache_flush) + *ret_cache_flush = cache_flush; + if (start) + *start = rewinder.saved_rindex; + CANCEL_REWINDER(rewinder); + + return 0; +} + +static bool loc_size_ok(uint8_t size) { + uint8_t m = size >> 4, e = size & 0xF; + + return m <= 9 && e <= 9 && (m > 0 || e == 0); +} + +int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder; + size_t offset; + uint16_t rdlength; + bool cache_flush; + int r; + + assert(p); + assert(ret); + + INIT_REWINDER(rewinder, p); + + r = dns_packet_read_key(p, &key, &cache_flush, NULL); + if (r < 0) + return r; + + if (!dns_class_is_valid_rr(key->class) || !dns_type_is_valid_rr(key->type)) + return -EBADMSG; + + rr = dns_resource_record_new(key); + if (!rr) + return -ENOMEM; + + r = dns_packet_read_uint32(p, &rr->ttl, NULL); + if (r < 0) + return r; + + /* RFC 2181, Section 8, suggests to + * treat a TTL with the MSB set as a zero TTL. */ + if (rr->ttl & UINT32_C(0x80000000)) + rr->ttl = 0; + + r = dns_packet_read_uint16(p, &rdlength, NULL); + if (r < 0) + return r; + + if (p->rindex + rdlength > p->size) + return -EBADMSG; + + offset = p->rindex; + + switch (rr->key->type) { + + case DNS_TYPE_SRV: + r = dns_packet_read_uint16(p, &rr->srv.priority, NULL); + if (r < 0) + return r; + r = dns_packet_read_uint16(p, &rr->srv.weight, NULL); + if (r < 0) + return r; + r = dns_packet_read_uint16(p, &rr->srv.port, NULL); + if (r < 0) + return r; + r = dns_packet_read_name(p, &rr->srv.name, true, NULL); + break; + + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: + r = dns_packet_read_name(p, &rr->ptr.name, true, NULL); + break; + + case DNS_TYPE_HINFO: + r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL); + if (r < 0) + return r; + + r = dns_packet_read_string(p, &rr->hinfo.os, NULL); + break; + + case DNS_TYPE_SPF: /* exactly the same as TXT */ + case DNS_TYPE_TXT: + if (rdlength <= 0) { + r = dns_txt_item_new_empty(&rr->txt.items); + if (r < 0) + return r; + } else { + DnsTxtItem *last = NULL; + + while (p->rindex < offset + rdlength) { + DnsTxtItem *i; + const void *data; + size_t sz; + + r = dns_packet_read_raw_string(p, &data, &sz, NULL); + if (r < 0) + return r; + + i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */ + if (!i) + return -ENOMEM; + + memcpy(i->data, data, sz); + i->length = sz; + + LIST_INSERT_AFTER(items, rr->txt.items, last, i); + last = i; + } + } + + r = 0; + break; + + case DNS_TYPE_A: + r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL); + break; + + case DNS_TYPE_AAAA: + r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL); + break; + + case DNS_TYPE_SOA: + r = dns_packet_read_name(p, &rr->soa.mname, true, NULL); + if (r < 0) + return r; + + r = dns_packet_read_name(p, &rr->soa.rname, true, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint32(p, &rr->soa.serial, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint32(p, &rr->soa.retry, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint32(p, &rr->soa.expire, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL); + break; + + case DNS_TYPE_MX: + r = dns_packet_read_uint16(p, &rr->mx.priority, NULL); + if (r < 0) + return r; + + r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL); + break; + + case DNS_TYPE_LOC: { + uint8_t t; + size_t pos; + + r = dns_packet_read_uint8(p, &t, &pos); + if (r < 0) + return r; + + if (t == 0) { + rr->loc.version = t; + + r = dns_packet_read_uint8(p, &rr->loc.size, NULL); + if (r < 0) + return r; + + if (!loc_size_ok(rr->loc.size)) + return -EBADMSG; + + r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL); + if (r < 0) + return r; + + if (!loc_size_ok(rr->loc.horiz_pre)) + return -EBADMSG; + + r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL); + if (r < 0) + return r; + + if (!loc_size_ok(rr->loc.vert_pre)) + return -EBADMSG; + + r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL); + if (r < 0) + return r; + + break; + } else { + dns_packet_rewind(p, pos); + rr->unparseable = true; + goto unparseable; + } + } + + case DNS_TYPE_DS: + r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL); + if (r < 0) + return r; + + if (rdlength < 4) + return -EBADMSG; + + r = dns_packet_read_memdup(p, rdlength - 4, + &rr->ds.digest, &rr->ds.digest_size, + NULL); + if (r < 0) + return r; + + if (rr->ds.digest_size <= 0) + /* the accepted size depends on the algorithm, but for now + just ensure that the value is greater than zero */ + return -EBADMSG; + + break; + + case DNS_TYPE_SSHFP: + r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL); + if (r < 0) + return r; + + if (rdlength < 2) + return -EBADMSG; + + r = dns_packet_read_memdup(p, rdlength - 2, + &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size, + NULL); + + if (rr->sshfp.fingerprint_size <= 0) + /* the accepted size depends on the algorithm, but for now + just ensure that the value is greater than zero */ + return -EBADMSG; + + break; + + case DNS_TYPE_DNSKEY: + r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL); + if (r < 0) + return r; + + if (rdlength < 4) + return -EBADMSG; + + r = dns_packet_read_memdup(p, rdlength - 4, + &rr->dnskey.key, &rr->dnskey.key_size, + NULL); + + if (rr->dnskey.key_size <= 0) + /* the accepted size depends on the algorithm, but for now + just ensure that the value is greater than zero */ + return -EBADMSG; + + break; + + case DNS_TYPE_RRSIG: + r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL); + if (r < 0) + return r; + + r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL); + if (r < 0) + return r; + + if (rdlength + offset < p->rindex) + return -EBADMSG; + + r = dns_packet_read_memdup(p, offset + rdlength - p->rindex, + &rr->rrsig.signature, &rr->rrsig.signature_size, + NULL); + + if (rr->rrsig.signature_size <= 0) + /* the accepted size depends on the algorithm, but for now + just ensure that the value is greater than zero */ + return -EBADMSG; + + break; + + case DNS_TYPE_NSEC: { + + /* + * RFC6762, section 18.14 explicitly states mDNS should use name compression. + * This contradicts RFC3845, section 2.1.1 + */ + + bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS; + + r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL); + if (r < 0) + return r; + + r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL); + + /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself + * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records + * without the NSEC bit set. */ + + break; + } + case DNS_TYPE_NSEC3: { + uint8_t size; + + r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL); + if (r < 0) + return r; + + /* this may be zero */ + r = dns_packet_read_uint8(p, &size, NULL); + if (r < 0) + return r; + + r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &size, NULL); + if (r < 0) + return r; + + if (size <= 0) + return -EBADMSG; + + r = dns_packet_read_memdup(p, size, + &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, + NULL); + if (r < 0) + return r; + + r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL); + + /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */ + + break; + } + + case DNS_TYPE_TLSA: + r = dns_packet_read_uint8(p, &rr->tlsa.cert_usage, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &rr->tlsa.selector, NULL); + if (r < 0) + return r; + + r = dns_packet_read_uint8(p, &rr->tlsa.matching_type, NULL); + if (r < 0) + return r; + + if (rdlength < 3) + return -EBADMSG; + + r = dns_packet_read_memdup(p, rdlength - 3, + &rr->tlsa.data, &rr->tlsa.data_size, + NULL); + + if (rr->tlsa.data_size <= 0) + /* the accepted size depends on the algorithm, but for now + just ensure that the value is greater than zero */ + return -EBADMSG; + + break; + + case DNS_TYPE_CAA: + r = dns_packet_read_uint8(p, &rr->caa.flags, NULL); + if (r < 0) + return r; + + r = dns_packet_read_string(p, &rr->caa.tag, NULL); + if (r < 0) + return r; + + if (rdlength + offset < p->rindex) + return -EBADMSG; + + r = dns_packet_read_memdup(p, + rdlength + offset - p->rindex, + &rr->caa.value, &rr->caa.value_size, NULL); + + break; + + case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */ + case DNS_TYPE_OPENPGPKEY: + default: + unparseable: + r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL); + + break; + } + if (r < 0) + return r; + if (p->rindex != offset + rdlength) + return -EBADMSG; + + *ret = TAKE_PTR(rr); + + if (ret_cache_flush) + *ret_cache_flush = cache_flush; + if (start) + *start = rewinder.saved_rindex; + CANCEL_REWINDER(rewinder); + + return 0; +} + +static bool opt_is_good(DnsResourceRecord *rr, bool *rfc6975) { + const uint8_t* p; + bool found_dau_dhu_n3u = false; + size_t l; + + /* Checks whether the specified OPT RR is well-formed and whether it contains RFC6975 data (which is not OK in + * a reply). */ + + assert(rr); + assert(rr->key->type == DNS_TYPE_OPT); + + /* Check that the version is 0 */ + if (((rr->ttl >> 16) & UINT32_C(0xFF)) != 0) { + *rfc6975 = false; + return true; /* if it's not version 0, it's OK, but we will ignore the OPT field contents */ + } + + p = rr->opt.data; + l = rr->opt.data_size; + while (l > 0) { + uint16_t option_code, option_length; + + /* At least four bytes for OPTION-CODE and OPTION-LENGTH are required */ + if (l < 4U) + return false; + + option_code = unaligned_read_be16(p); + option_length = unaligned_read_be16(p + 2); + + if (l < option_length + 4U) + return false; + + /* RFC 6975 DAU, DHU or N3U fields found. */ + if (IN_SET(option_code, 5, 6, 7)) + found_dau_dhu_n3u = true; + + p += option_length + 4U; + l -= option_length + 4U; + } + + *rfc6975 = found_dau_dhu_n3u; + return true; +} + +static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question) { + _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; + unsigned n, i; + int r; + + n = DNS_PACKET_QDCOUNT(p); + if (n > 0) { + question = dns_question_new(n); + if (!question) + return -ENOMEM; + + _cleanup_set_free_ Set *keys = NULL; /* references to keys are kept by Question */ + + keys = set_new(&dns_resource_key_hash_ops); + if (!keys) + return log_oom(); + + r = set_reserve(keys, n * 2); /* Higher multipliers give slightly higher efficiency through + * hash collisions, but the gains quickly drop of after 2. */ + if (r < 0) + return r; + + for (i = 0; i < n; i++) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + bool cache_flush; + + r = dns_packet_read_key(p, &key, &cache_flush, NULL); + if (r < 0) + return r; + + if (cache_flush) + return -EBADMSG; + + if (!dns_type_is_valid_query(key->type)) + return -EBADMSG; + + r = set_put(keys, key); + if (r < 0) + return r; + if (r == 0) + /* Already in the Question, let's skip */ + continue; + + r = dns_question_add_raw(question, key); + if (r < 0) + return r; + } + } + + *ret_question = TAKE_PTR(question); + + return 0; +} + +static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + unsigned n, i; + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *previous = NULL; + bool bad_opt = false; + int r; + + n = DNS_PACKET_RRCOUNT(p); + if (n == 0) + return 0; + + answer = dns_answer_new(n); + if (!answer) + return -ENOMEM; + + for (i = 0; i < n; i++) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + bool cache_flush = false; + + r = dns_packet_read_rr(p, &rr, &cache_flush, NULL); + if (r < 0) + return r; + + /* Try to reduce memory usage a bit */ + if (previous) + dns_resource_key_reduce(&rr->key, &previous->key); + + if (rr->key->type == DNS_TYPE_OPT) { + bool has_rfc6975; + + if (p->opt || bad_opt) { + /* Multiple OPT RRs? if so, let's ignore all, because there's + * something wrong with the server, and if one is valid we wouldn't + * know which one. */ + log_debug("Multiple OPT RRs detected, ignoring all."); + bad_opt = true; + continue; + } + + if (!dns_name_is_root(dns_resource_key_name(rr->key))) { + /* If the OPT RR is not owned by the root domain, then it is bad, + * let's ignore it. */ + log_debug("OPT RR is not owned by root domain, ignoring."); + bad_opt = true; + continue; + } + + if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)) { + /* OPT RR is in the wrong section? Some Belkin routers do this. This + * is a hint the EDNS implementation is borked, like the Belkin one + * is, hence ignore it. */ + log_debug("OPT RR in wrong section, ignoring."); + bad_opt = true; + continue; + } + + if (!opt_is_good(rr, &has_rfc6975)) { + log_debug("Malformed OPT RR, ignoring."); + bad_opt = true; + continue; + } + + if (DNS_PACKET_QR(p)) { + /* Additional checks for responses */ + + if (!DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(rr)) { + /* If this is a reply and we don't know the EDNS version + * then something is weird... */ + log_debug("EDNS version newer that our request, bad server."); + return -EBADMSG; + } + + if (has_rfc6975) { + /* If the OPT RR contains RFC6975 algorithm data, then this + * is indication that the server just copied the OPT it got + * from us (which contained that data) back into the reply. + * If so, then it doesn't properly support EDNS, as RFC6975 + * makes it very clear that the algorithm data should only + * be contained in questions, never in replies. Crappy + * Belkin routers copy the OPT data for example, hence let's + * detect this so that we downgrade early. */ + log_debug("OPT RR contains RFC6975 data, ignoring."); + bad_opt = true; + continue; + } + } + + p->opt = dns_resource_record_ref(rr); + } else { + /* According to RFC 4795, section 2.9. only the RRs from the Answer section + * shall be cached. Hence mark only those RRs as cacheable by default, but + * not the ones from the Additional or Authority sections. */ + DnsAnswerFlags flags = + (i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0) | + (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0); + + r = dns_answer_add(answer, rr, p->ifindex, flags); + if (r < 0) + return r; + } + + /* Remember this RR, so that we potentically can merge it's ->key object with the + * next RR. Note that we only do this if we actually decided to keep the RR around. + */ + dns_resource_record_unref(previous); + previous = dns_resource_record_ref(rr); + } + + if (bad_opt) + p->opt = dns_resource_record_unref(p->opt); + + *ret_answer = TAKE_PTR(answer); + + return 0; +} + +int dns_packet_extract(DnsPacket *p) { + _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL; + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = {}; + int r; + + if (p->extracted) + return 0; + + INIT_REWINDER(rewinder, p); + dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE); + + r = dns_packet_extract_question(p, &question); + if (r < 0) + return r; + + r = dns_packet_extract_answer(p, &answer); + if (r < 0) + return r; + + p->question = TAKE_PTR(question); + p->answer = TAKE_PTR(answer); + + p->extracted = true; + + /* no CANCEL, always rewind */ + return 0; +} + +int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) { + int r; + + assert(p); + assert(key); + + /* Checks if the specified packet is a reply for the specified + * key and the specified key is the only one in the question + * section. */ + + if (DNS_PACKET_QR(p) != 1) + return 0; + + /* Let's unpack the packet, if that hasn't happened yet. */ + r = dns_packet_extract(p); + if (r < 0) + return r; + + if (!p->question) + return 0; + + if (p->question->n_keys != 1) + return 0; + + return dns_resource_key_equal(p->question->keys[0], key); +} + +static void dns_packet_hash_func(const DnsPacket *s, struct siphash *state) { + assert(s); + + siphash24_compress(&s->size, sizeof(s->size), state); + siphash24_compress(DNS_PACKET_DATA((DnsPacket*) s), s->size, state); +} + +static int dns_packet_compare_func(const DnsPacket *x, const DnsPacket *y) { + int r; + + r = CMP(x->size, y->size); + if (r != 0) + return r; + + return memcmp(DNS_PACKET_DATA((DnsPacket*) x), DNS_PACKET_DATA((DnsPacket*) y), x->size); +} + +DEFINE_HASH_OPS(dns_packet_hash_ops, DnsPacket, dns_packet_hash_func, dns_packet_compare_func); + +static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = { + [DNS_RCODE_SUCCESS] = "SUCCESS", + [DNS_RCODE_FORMERR] = "FORMERR", + [DNS_RCODE_SERVFAIL] = "SERVFAIL", + [DNS_RCODE_NXDOMAIN] = "NXDOMAIN", + [DNS_RCODE_NOTIMP] = "NOTIMP", + [DNS_RCODE_REFUSED] = "REFUSED", + [DNS_RCODE_YXDOMAIN] = "YXDOMAIN", + [DNS_RCODE_YXRRSET] = "YRRSET", + [DNS_RCODE_NXRRSET] = "NXRRSET", + [DNS_RCODE_NOTAUTH] = "NOTAUTH", + [DNS_RCODE_NOTZONE] = "NOTZONE", + [DNS_RCODE_BADVERS] = "BADVERS", + [DNS_RCODE_BADKEY] = "BADKEY", + [DNS_RCODE_BADTIME] = "BADTIME", + [DNS_RCODE_BADMODE] = "BADMODE", + [DNS_RCODE_BADNAME] = "BADNAME", + [DNS_RCODE_BADALG] = "BADALG", + [DNS_RCODE_BADTRUNC] = "BADTRUNC", + [DNS_RCODE_BADCOOKIE] = "BADCOOKIE", +}; +DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int); + +static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = { + [DNS_PROTOCOL_DNS] = "dns", + [DNS_PROTOCOL_MDNS] = "mdns", + [DNS_PROTOCOL_LLMNR] = "llmnr", +}; +DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol); diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h new file mode 100644 index 00000000..56614c4a --- /dev/null +++ b/src/resolve/resolved-dns-packet.h @@ -0,0 +1,302 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "hashmap.h" +#include "in-addr-util.h" +#include "macro.h" +#include "sparse-endian.h" + +typedef struct DnsPacketHeader DnsPacketHeader; +typedef struct DnsPacket DnsPacket; + +#include "resolved-def.h" +#include "resolved-dns-answer.h" +#include "resolved-dns-question.h" +#include "resolved-dns-rr.h" + +typedef enum DnsProtocol { + DNS_PROTOCOL_DNS, + DNS_PROTOCOL_MDNS, + DNS_PROTOCOL_LLMNR, + _DNS_PROTOCOL_MAX, + _DNS_PROTOCOL_INVALID = -1 +} DnsProtocol; + +struct DnsPacketHeader { + uint16_t id; + be16_t flags; + be16_t qdcount; + be16_t ancount; + be16_t nscount; + be16_t arcount; +}; + +#define DNS_PACKET_HEADER_SIZE sizeof(DnsPacketHeader) +#define UDP_PACKET_HEADER_SIZE (sizeof(struct iphdr) + sizeof(struct udphdr)) + +/* The various DNS protocols deviate in how large a packet can grow, + * but the TCP transport has a 16bit size field, hence that appears to + * be the absolute maximum. */ +#define DNS_PACKET_SIZE_MAX 0xFFFFu + +/* The default size to use for allocation when we don't know how large + * the packet will turn out to be. */ +#define DNS_PACKET_SIZE_START 512u + +/* RFC 1035 say 512 is the maximum, for classic unicast DNS */ +#define DNS_PACKET_UNICAST_SIZE_MAX 512u + +/* With EDNS0 we can use larger packets, default to 4096, which is what is commonly used */ +#define DNS_PACKET_UNICAST_SIZE_LARGE_MAX 4096u + +struct DnsPacket { + unsigned n_ref; + DnsProtocol protocol; + size_t size, allocated, rindex, max_size; + void *_data; /* don't access directly, use DNS_PACKET_DATA()! */ + Hashmap *names; /* For name compression */ + size_t opt_start, opt_size; + + /* Parsed data */ + DnsQuestion *question; + DnsAnswer *answer; + DnsResourceRecord *opt; + + /* Packet reception metadata */ + int ifindex; + int family, ipproto; + union in_addr_union sender, destination; + uint16_t sender_port, destination_port; + uint32_t ttl; + + /* For support of truncated packets */ + DnsPacket *more; + + bool on_stack:1; + bool extracted:1; + bool refuse_compression:1; + bool canonical_form:1; +}; + +static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) { + if (_unlikely_(!p)) + return NULL; + + if (p->_data) + return p->_data; + + return ((uint8_t*) p) + ALIGN(sizeof(DnsPacket)); +} + +#define DNS_PACKET_HEADER(p) ((DnsPacketHeader*) DNS_PACKET_DATA(p)) +#define DNS_PACKET_ID(p) DNS_PACKET_HEADER(p)->id +#define DNS_PACKET_QR(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 15) & 1) +#define DNS_PACKET_OPCODE(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 11) & 15) +#define DNS_PACKET_AA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 10) & 1) +#define DNS_PACKET_TC(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 9) & 1) +#define DNS_PACKET_RD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 8) & 1) +#define DNS_PACKET_RA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 7) & 1) +#define DNS_PACKET_AD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 5) & 1) +#define DNS_PACKET_CD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 4) & 1) + +#define DNS_PACKET_FLAG_TC (UINT16_C(1) << 9) + +static inline uint16_t DNS_PACKET_RCODE(DnsPacket *p) { + uint16_t rcode; + + if (p->opt) + rcode = (uint16_t) (p->opt->ttl >> 24); + else + rcode = 0; + + return rcode | (be16toh(DNS_PACKET_HEADER(p)->flags) & 0xF); +} + +static inline uint16_t DNS_PACKET_PAYLOAD_SIZE_MAX(DnsPacket *p) { + + /* Returns the advertised maximum size for replies, or the DNS default if there's nothing defined. */ + + if (p->ipproto == IPPROTO_TCP) /* we ignore EDNS(0) size data on TCP, like everybody else */ + return DNS_PACKET_SIZE_MAX; + + if (p->opt) + return MAX(DNS_PACKET_UNICAST_SIZE_MAX, p->opt->key->class); + + return DNS_PACKET_UNICAST_SIZE_MAX; +} + +static inline bool DNS_PACKET_DO(DnsPacket *p) { + if (!p->opt) + return false; + + return !!(p->opt->ttl & (1U << 15)); +} + +static inline bool DNS_PACKET_VERSION_SUPPORTED(DnsPacket *p) { + /* Returns true if this packet is in a version we support. Which means either non-EDNS or EDNS(0), but not EDNS + * of any newer versions */ + + if (!p->opt) + return true; + + return DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(p->opt); +} + +/* LLMNR defines some bits differently */ +#define DNS_PACKET_LLMNR_C(p) DNS_PACKET_AA(p) +#define DNS_PACKET_LLMNR_T(p) DNS_PACKET_RD(p) + +#define DNS_PACKET_QDCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->qdcount) +#define DNS_PACKET_ANCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->ancount) +#define DNS_PACKET_NSCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->nscount) +#define DNS_PACKET_ARCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->arcount) + +#define DNS_PACKET_MAKE_FLAGS(qr, opcode, aa, tc, rd, ra, ad, cd, rcode) \ + (((uint16_t) !!(qr) << 15) | \ + ((uint16_t) ((opcode) & 15) << 11) | \ + ((uint16_t) !!(aa) << 10) | /* on LLMNR: c */ \ + ((uint16_t) !!(tc) << 9) | \ + ((uint16_t) !!(rd) << 8) | /* on LLMNR: t */ \ + ((uint16_t) !!(ra) << 7) | \ + ((uint16_t) !!(ad) << 5) | \ + ((uint16_t) !!(cd) << 4) | \ + ((uint16_t) ((rcode) & 15))) + +static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket *p) { + return + (unsigned) DNS_PACKET_ANCOUNT(p) + + (unsigned) DNS_PACKET_NSCOUNT(p) + + (unsigned) DNS_PACKET_ARCOUNT(p); +} + +int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize, size_t max_size); +int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled); + +void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated); + +DnsPacket *dns_packet_ref(DnsPacket *p); +DnsPacket *dns_packet_unref(DnsPacket *p); + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsPacket*, dns_packet_unref); + +int dns_packet_validate(DnsPacket *p); +int dns_packet_validate_reply(DnsPacket *p); +int dns_packet_validate_query(DnsPacket *p); + +int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key); + +int dns_packet_append_blob(DnsPacket *p, const void *d, size_t sz, size_t *start); +int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start); +int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start); +int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start); +int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start); +int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start); +int dns_packet_append_label(DnsPacket *p, const char *s, size_t l, bool canonical_candidate, size_t *start); +int dns_packet_append_name(DnsPacket *p, const char *name, bool allow_compression, bool canonical_candidate, size_t *start); +int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *key, const DnsAnswerFlags flags, size_t *start); +int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start); +int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, int rcode, size_t *start); +int dns_packet_append_question(DnsPacket *p, DnsQuestion *q); +int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a); + +void dns_packet_truncate(DnsPacket *p, size_t sz); +int dns_packet_truncate_opt(DnsPacket *p); + +int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start); +int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start); +int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start); +int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start); +int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start); +int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start); +int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start); +int dns_packet_read_name(DnsPacket *p, char **ret, bool allow_compression, size_t *start); +int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start); +int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start); + +void dns_packet_rewind(DnsPacket *p, size_t idx); + +int dns_packet_skip_question(DnsPacket *p); +int dns_packet_extract(DnsPacket *p); + +static inline bool DNS_PACKET_SHALL_CACHE(DnsPacket *p) { + /* Never cache data originating from localhost, under the + * assumption, that it's coming from a locally DNS forwarder + * or server, that is caching on its own. */ + + return in_addr_is_localhost(p->family, &p->sender) == 0; +} + +/* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 */ +enum { + DNS_RCODE_SUCCESS = 0, + DNS_RCODE_FORMERR = 1, + DNS_RCODE_SERVFAIL = 2, + DNS_RCODE_NXDOMAIN = 3, + DNS_RCODE_NOTIMP = 4, + DNS_RCODE_REFUSED = 5, + DNS_RCODE_YXDOMAIN = 6, + DNS_RCODE_YXRRSET = 7, + DNS_RCODE_NXRRSET = 8, + DNS_RCODE_NOTAUTH = 9, + DNS_RCODE_NOTZONE = 10, + DNS_RCODE_BADVERS = 16, + DNS_RCODE_BADSIG = 16, /* duplicate value! */ + DNS_RCODE_BADKEY = 17, + DNS_RCODE_BADTIME = 18, + DNS_RCODE_BADMODE = 19, + DNS_RCODE_BADNAME = 20, + DNS_RCODE_BADALG = 21, + DNS_RCODE_BADTRUNC = 22, + DNS_RCODE_BADCOOKIE = 23, + _DNS_RCODE_MAX_DEFINED, + _DNS_RCODE_MAX = 4095 /* 4 bit rcode in the header plus 8 bit rcode in OPT, makes 12 bit */ +}; + +const char* dns_rcode_to_string(int i) _const_; +int dns_rcode_from_string(const char *s) _pure_; + +const char* dns_protocol_to_string(DnsProtocol p) _const_; +DnsProtocol dns_protocol_from_string(const char *s) _pure_; + +#define LLMNR_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 252U) }) +#define LLMNR_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03 } }) + +#define MDNS_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 251U) }) +#define MDNS_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb } }) + +extern const struct hash_ops dns_packet_hash_ops; + +static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family, bool authenticated) { + uint64_t f; + + /* Converts a protocol + family into a flags field as used in queries and responses */ + + f = authenticated ? SD_RESOLVED_AUTHENTICATED : 0; + + switch (protocol) { + case DNS_PROTOCOL_DNS: + return f|SD_RESOLVED_DNS; + + case DNS_PROTOCOL_LLMNR: + return f|(family == AF_INET6 ? SD_RESOLVED_LLMNR_IPV6 : SD_RESOLVED_LLMNR_IPV4); + + case DNS_PROTOCOL_MDNS: + return f|(family == AF_INET6 ? SD_RESOLVED_MDNS_IPV6 : SD_RESOLVED_MDNS_IPV4); + + default: + return f; + } +} + +static inline size_t dns_packet_size_max(DnsPacket *p) { + assert(p); + + /* Why not insist on a fully initialized max_size during DnsPacket construction? Well, this way it's easy to + * allocate a transient, throw-away DnsPacket on the stack by simple zero initialization, without having to + * deal with explicit field initialization. */ + + return p->max_size != 0 ? p->max_size : DNS_PACKET_SIZE_MAX; +} diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c new file mode 100644 index 00000000..4a41921c --- /dev/null +++ b/src/resolve/resolved-dns-query.c @@ -0,0 +1,1107 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "dns-domain.h" +#include "dns-type.h" +#include "hostname-util.h" +#include "local-addresses.h" +#include "resolved-dns-query.h" +#include "resolved-dns-synthesize.h" +#include "resolved-etc-hosts.h" +#include "string-util.h" + +#define CNAME_MAX 8 +#define QUERIES_MAX 2048 +#define AUXILIARY_QUERIES_MAX 64 + +static int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScope *s) { + DnsQueryCandidate *c; + + assert(ret); + assert(q); + assert(s); + + c = new0(DnsQueryCandidate, 1); + if (!c) + return -ENOMEM; + + c->query = q; + c->scope = s; + + LIST_PREPEND(candidates_by_query, q->candidates, c); + LIST_PREPEND(candidates_by_scope, s->query_candidates, c); + + *ret = c; + return 0; +} + +static void dns_query_candidate_stop(DnsQueryCandidate *c) { + DnsTransaction *t; + + assert(c); + + while ((t = set_steal_first(c->transactions))) { + set_remove(t->notify_query_candidates, c); + set_remove(t->notify_query_candidates_done, c); + dns_transaction_gc(t); + } +} + +DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) { + + if (!c) + return NULL; + + dns_query_candidate_stop(c); + + set_free(c->transactions); + dns_search_domain_unref(c->search_domain); + + if (c->query) + LIST_REMOVE(candidates_by_query, c->query->candidates, c); + + if (c->scope) + LIST_REMOVE(candidates_by_scope, c->scope->query_candidates, c); + + return mfree(c); +} + +static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) { + DnsSearchDomain *next = NULL; + + assert(c); + + if (c->search_domain && c->search_domain->linked) + next = c->search_domain->domains_next; + else + next = dns_scope_get_search_domains(c->scope); + + for (;;) { + if (!next) /* We hit the end of the list */ + return 0; + + if (!next->route_only) + break; + + /* Skip over route-only domains */ + next = next->domains_next; + } + + dns_search_domain_unref(c->search_domain); + c->search_domain = dns_search_domain_ref(next); + + return 1; +} + +static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResourceKey *key) { + DnsTransaction *t; + int r; + + assert(c); + assert(key); + + t = dns_scope_find_transaction(c->scope, key, true); + if (!t) { + r = dns_transaction_new(&t, c->scope, key); + if (r < 0) + return r; + } else { + if (set_contains(c->transactions, t)) + return 0; + } + + r = set_ensure_allocated(&c->transactions, NULL); + if (r < 0) + goto gc; + + r = set_ensure_allocated(&t->notify_query_candidates, NULL); + if (r < 0) + goto gc; + + r = set_ensure_allocated(&t->notify_query_candidates_done, NULL); + if (r < 0) + goto gc; + + r = set_put(t->notify_query_candidates, c); + if (r < 0) + goto gc; + + r = set_put(c->transactions, t); + if (r < 0) { + (void) set_remove(t->notify_query_candidates, c); + goto gc; + } + + t->clamp_ttl = c->query->clamp_ttl; + return 1; + +gc: + dns_transaction_gc(t); + return r; +} + +static int dns_query_candidate_go(DnsQueryCandidate *c) { + DnsTransaction *t; + Iterator i; + int r; + unsigned n = 0; + + assert(c); + + /* Start the transactions that are not started yet */ + SET_FOREACH(t, c->transactions, i) { + if (t->state != DNS_TRANSACTION_NULL) + continue; + + r = dns_transaction_go(t); + if (r < 0) + return r; + + n++; + } + + /* If there was nothing to start, then let's proceed immediately */ + if (n == 0) + dns_query_candidate_notify(c); + + return 0; +} + +static DnsTransactionState dns_query_candidate_state(DnsQueryCandidate *c) { + DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS; + DnsTransaction *t; + Iterator i; + + assert(c); + + if (c->error_code != 0) + return DNS_TRANSACTION_ERRNO; + + SET_FOREACH(t, c->transactions, i) { + + switch (t->state) { + + case DNS_TRANSACTION_NULL: + /* If there's a NULL transaction pending, then + * this means not all transactions where + * started yet, and we were called from within + * the stackframe that is supposed to start + * remaining transactions. In this case, + * simply claim the candidate is pending. */ + + case DNS_TRANSACTION_PENDING: + case DNS_TRANSACTION_VALIDATING: + /* If there's one transaction currently in + * VALIDATING state, then this means there's + * also one in PENDING state, hence we can + * return PENDING immediately. */ + return DNS_TRANSACTION_PENDING; + + case DNS_TRANSACTION_SUCCESS: + state = t->state; + break; + + default: + if (state != DNS_TRANSACTION_SUCCESS) + state = t->state; + + break; + } + } + + return state; +} + +static bool dns_query_candidate_is_routable(DnsQueryCandidate *c, uint16_t type) { + int family; + + assert(c); + + /* Checks whether the specified RR type matches an address family that is routable on the link(s) the scope of + * this candidate belongs to. Specifically, whether there's a routable IPv4 address on it if we query an A RR, + * or a routable IPv6 address if we query an AAAA RR. */ + + if (!c->query->suppress_unroutable_family) + return true; + + if (c->scope->protocol != DNS_PROTOCOL_DNS) + return true; + + family = dns_type_to_af(type); + if (family < 0) + return true; + + if (c->scope->link) + return link_relevant(c->scope->link, family, false); + else + return manager_routable(c->scope->manager, family); +} + +static int dns_query_candidate_setup_transactions(DnsQueryCandidate *c) { + DnsQuestion *question; + DnsResourceKey *key; + int n = 0, r; + + assert(c); + + dns_query_candidate_stop(c); + + question = dns_query_question_for_protocol(c->query, c->scope->protocol); + + /* Create one transaction per question key */ + DNS_QUESTION_FOREACH(key, question) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *new_key = NULL; + DnsResourceKey *qkey; + + if (!dns_query_candidate_is_routable(c, key->type)) + continue; + + if (c->search_domain) { + r = dns_resource_key_new_append_suffix(&new_key, key, c->search_domain->name); + if (r < 0) + goto fail; + + qkey = new_key; + } else + qkey = key; + + if (!dns_scope_good_key(c->scope, qkey)) + continue; + + r = dns_query_candidate_add_transaction(c, qkey); + if (r < 0) + goto fail; + + n++; + } + + return n; + +fail: + dns_query_candidate_stop(c); + return r; +} + +void dns_query_candidate_notify(DnsQueryCandidate *c) { + DnsTransactionState state; + int r; + + assert(c); + + state = dns_query_candidate_state(c); + + if (DNS_TRANSACTION_IS_LIVE(state)) + return; + + if (state != DNS_TRANSACTION_SUCCESS && c->search_domain) { + + r = dns_query_candidate_next_search_domain(c); + if (r < 0) + goto fail; + + if (r > 0) { + /* OK, there's another search domain to try, let's do so. */ + + r = dns_query_candidate_setup_transactions(c); + if (r < 0) + goto fail; + + if (r > 0) { + /* New transactions where queued. Start them and wait */ + + r = dns_query_candidate_go(c); + if (r < 0) + goto fail; + + return; + } + } + + } + + dns_query_ready(c->query); + return; + +fail: + log_warning_errno(r, "Failed to follow search domains: %m"); + c->error_code = r; + dns_query_ready(c->query); +} + +static void dns_query_stop(DnsQuery *q) { + DnsQueryCandidate *c; + + assert(q); + + q->timeout_event_source = sd_event_source_unref(q->timeout_event_source); + + LIST_FOREACH(candidates_by_query, c, q->candidates) + dns_query_candidate_stop(c); +} + +static void dns_query_free_candidates(DnsQuery *q) { + assert(q); + + while (q->candidates) + dns_query_candidate_free(q->candidates); +} + +static void dns_query_reset_answer(DnsQuery *q) { + assert(q); + + q->answer = dns_answer_unref(q->answer); + q->answer_rcode = 0; + q->answer_dnssec_result = _DNSSEC_RESULT_INVALID; + q->answer_errno = 0; + q->answer_authenticated = false; + q->answer_protocol = _DNS_PROTOCOL_INVALID; + q->answer_family = AF_UNSPEC; + q->answer_search_domain = dns_search_domain_unref(q->answer_search_domain); +} + +DnsQuery *dns_query_free(DnsQuery *q) { + if (!q) + return NULL; + + while (q->auxiliary_queries) + dns_query_free(q->auxiliary_queries); + + if (q->auxiliary_for) { + assert(q->auxiliary_for->n_auxiliary_queries > 0); + q->auxiliary_for->n_auxiliary_queries--; + LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q); + } + + dns_query_free_candidates(q); + + dns_question_unref(q->question_idna); + dns_question_unref(q->question_utf8); + + dns_query_reset_answer(q); + + sd_bus_message_unref(q->request); + sd_bus_track_unref(q->bus_track); + + dns_packet_unref(q->request_dns_packet); + dns_packet_unref(q->reply_dns_packet); + + if (q->request_dns_stream) { + /* Detach the stream from our query, in case something else keeps a reference to it. */ + (void) set_remove(q->request_dns_stream->queries, q); + q->request_dns_stream = dns_stream_unref(q->request_dns_stream); + } + + free(q->request_address_string); + + if (q->manager) { + LIST_REMOVE(queries, q->manager->dns_queries, q); + q->manager->n_dns_queries--; + } + + return mfree(q); +} + +int dns_query_new( + Manager *m, + DnsQuery **ret, + DnsQuestion *question_utf8, + DnsQuestion *question_idna, + int ifindex, + uint64_t flags) { + + _cleanup_(dns_query_freep) DnsQuery *q = NULL; + DnsResourceKey *key; + bool good = false; + int r; + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + + assert(m); + + if (dns_question_size(question_utf8) > 0) { + r = dns_question_is_valid_for_query(question_utf8); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + good = true; + } + + /* If the IDNA and UTF8 questions are the same, merge their references */ + r = dns_question_is_equal(question_idna, question_utf8); + if (r < 0) + return r; + if (r > 0) + question_idna = question_utf8; + else { + if (dns_question_size(question_idna) > 0) { + r = dns_question_is_valid_for_query(question_idna); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + good = true; + } + } + + if (!good) /* don't allow empty queries */ + return -EINVAL; + + if (m->n_dns_queries >= QUERIES_MAX) + return -EBUSY; + + q = new0(DnsQuery, 1); + if (!q) + return -ENOMEM; + + q->question_utf8 = dns_question_ref(question_utf8); + q->question_idna = dns_question_ref(question_idna); + q->ifindex = ifindex; + q->flags = flags; + q->answer_dnssec_result = _DNSSEC_RESULT_INVALID; + q->answer_protocol = _DNS_PROTOCOL_INVALID; + q->answer_family = AF_UNSPEC; + + /* First dump UTF8 question */ + DNS_QUESTION_FOREACH(key, question_utf8) + log_debug("Looking up RR for %s.", + dns_resource_key_to_string(key, key_str, sizeof key_str)); + + /* And then dump the IDNA question, but only what hasn't been dumped already through the UTF8 question. */ + DNS_QUESTION_FOREACH(key, question_idna) { + r = dns_question_contains(question_utf8, key); + if (r < 0) + return r; + if (r > 0) + continue; + + log_debug("Looking up IDNA RR for %s.", + dns_resource_key_to_string(key, key_str, sizeof key_str)); + } + + LIST_PREPEND(queries, m->dns_queries, q); + m->n_dns_queries++; + q->manager = m; + + if (ret) + *ret = q; + q = NULL; + + return 0; +} + +int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for) { + assert(q); + assert(auxiliary_for); + + /* Ensure that the query is not auxiliary yet, and + * nothing else is auxiliary to it either */ + assert(!q->auxiliary_for); + assert(!q->auxiliary_queries); + + /* Ensure that the unit we shall be made auxiliary for isn't + * auxiliary itself */ + assert(!auxiliary_for->auxiliary_for); + + if (auxiliary_for->n_auxiliary_queries >= AUXILIARY_QUERIES_MAX) + return -EAGAIN; + + LIST_PREPEND(auxiliary_queries, auxiliary_for->auxiliary_queries, q); + q->auxiliary_for = auxiliary_for; + + auxiliary_for->n_auxiliary_queries++; + return 0; +} + +static void dns_query_complete(DnsQuery *q, DnsTransactionState state) { + assert(q); + assert(!DNS_TRANSACTION_IS_LIVE(state)); + assert(DNS_TRANSACTION_IS_LIVE(q->state)); + + /* Note that this call might invalidate the query. Callers + * should hence not attempt to access the query or transaction + * after calling this function. */ + + q->state = state; + + dns_query_stop(q); + if (q->complete) + q->complete(q); +} + +static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) { + DnsQuery *q = userdata; + + assert(s); + assert(q); + + dns_query_complete(q, DNS_TRANSACTION_TIMEOUT); + return 0; +} + +static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) { + DnsQueryCandidate *c; + int r; + + assert(q); + assert(s); + + r = dns_query_candidate_new(&c, q, s); + if (r < 0) + return r; + + /* If this a single-label domain on DNS, we might append a suitable search domain first. */ + if ((q->flags & SD_RESOLVED_NO_SEARCH) == 0 && + dns_scope_name_needs_search_domain(s, dns_question_first_name(q->question_idna))) { + /* OK, we need a search domain now. Let's find one for this scope */ + + r = dns_query_candidate_next_search_domain(c); + if (r <= 0) /* if there's no search domain, then we won't add any transaction. */ + goto fail; + } + + r = dns_query_candidate_setup_transactions(c); + if (r < 0) + goto fail; + + return 0; + +fail: + dns_query_candidate_free(c); + return r; +} + +static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + int r; + + assert(q); + assert(state); + + /* Tries to synthesize localhost RR replies (and others) where appropriate. Note that this is done *after* the + * the normal lookup finished. The data from the network hence takes precedence over the data we + * synthesize. (But note that many scopes refuse to resolve certain domain names) */ + + if (!IN_SET(*state, + DNS_TRANSACTION_RCODE_FAILURE, + DNS_TRANSACTION_NO_SERVERS, + DNS_TRANSACTION_TIMEOUT, + DNS_TRANSACTION_ATTEMPTS_MAX_REACHED, + DNS_TRANSACTION_NETWORK_DOWN, + DNS_TRANSACTION_NOT_FOUND)) + return 0; + + r = dns_synthesize_answer( + q->manager, + q->question_utf8, + q->ifindex, + &answer); + if (r == -ENXIO) { + /* If we get ENXIO this tells us to generate NXDOMAIN unconditionally. */ + + dns_query_reset_answer(q); + q->answer_rcode = DNS_RCODE_NXDOMAIN; + q->answer_protocol = dns_synthesize_protocol(q->flags); + q->answer_family = dns_synthesize_family(q->flags); + q->answer_authenticated = true; + *state = DNS_TRANSACTION_RCODE_FAILURE; + + return 0; + } + if (r <= 0) + return r; + + dns_query_reset_answer(q); + + q->answer = TAKE_PTR(answer); + q->answer_rcode = DNS_RCODE_SUCCESS; + q->answer_protocol = dns_synthesize_protocol(q->flags); + q->answer_family = dns_synthesize_family(q->flags); + q->answer_authenticated = true; + + *state = DNS_TRANSACTION_SUCCESS; + + return 1; +} + +static int dns_query_try_etc_hosts(DnsQuery *q) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + int r; + + assert(q); + + /* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The + * data from /etc/hosts hence takes precedence over the network. */ + + r = manager_etc_hosts_lookup( + q->manager, + q->question_utf8, + &answer); + if (r <= 0) + return r; + + dns_query_reset_answer(q); + + q->answer = TAKE_PTR(answer); + q->answer_rcode = DNS_RCODE_SUCCESS; + q->answer_protocol = dns_synthesize_protocol(q->flags); + q->answer_family = dns_synthesize_family(q->flags); + q->answer_authenticated = true; + + return 1; +} + +int dns_query_go(DnsQuery *q) { + DnsScopeMatch found = DNS_SCOPE_NO; + DnsScope *s, *first = NULL; + DnsQueryCandidate *c; + int r; + + assert(q); + + if (q->state != DNS_TRANSACTION_NULL) + return 0; + + r = dns_query_try_etc_hosts(q); + if (r < 0) + return r; + if (r > 0) { + dns_query_complete(q, DNS_TRANSACTION_SUCCESS); + return 1; + } + + LIST_FOREACH(scopes, s, q->manager->dns_scopes) { + DnsScopeMatch match; + const char *name; + + name = dns_question_first_name(dns_query_question_for_protocol(q, s->protocol)); + if (!name) + continue; + + match = dns_scope_good_domain(s, q->ifindex, q->flags, name); + if (match < 0) { + log_debug("Couldn't check if '%s' matches against scope, ignoring.", name); + continue; + } + + if (match > found) { /* Does this match better? If so, remember how well it matched, and the first one + * that matches this well */ + found = match; + first = s; + } + } + + if (found == DNS_SCOPE_NO) { + DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS; + + r = dns_query_synthesize_reply(q, &state); + if (r < 0) + return r; + + dns_query_complete(q, state); + return 1; + } + + r = dns_query_add_candidate(q, first); + if (r < 0) + goto fail; + + LIST_FOREACH(scopes, s, first->scopes_next) { + DnsScopeMatch match; + const char *name; + + name = dns_question_first_name(dns_query_question_for_protocol(q, s->protocol)); + if (!name) + continue; + + match = dns_scope_good_domain(s, q->ifindex, q->flags, name); + if (match < 0) { + log_debug("Couldn't check if '%s' matches against scope, ignoring.", name); + continue; + } + + if (match < found) + continue; + + r = dns_query_add_candidate(q, s); + if (r < 0) + goto fail; + } + + dns_query_reset_answer(q); + + r = sd_event_add_time( + q->manager->event, + &q->timeout_event_source, + clock_boottime_or_monotonic(), + now(clock_boottime_or_monotonic()) + SD_RESOLVED_QUERY_TIMEOUT_USEC, + 0, on_query_timeout, q); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(q->timeout_event_source, "query-timeout"); + + q->state = DNS_TRANSACTION_PENDING; + q->block_ready++; + + /* Start the transactions */ + LIST_FOREACH(candidates_by_query, c, q->candidates) { + r = dns_query_candidate_go(c); + if (r < 0) { + q->block_ready--; + goto fail; + } + } + + q->block_ready--; + dns_query_ready(q); + + return 1; + +fail: + dns_query_stop(q); + return r; +} + +static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) { + DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS; + bool has_authenticated = false, has_non_authenticated = false; + DnssecResult dnssec_result_authenticated = _DNSSEC_RESULT_INVALID, dnssec_result_non_authenticated = _DNSSEC_RESULT_INVALID; + DnsTransaction *t; + Iterator i; + int r; + + assert(q); + + if (!c) { + r = dns_query_synthesize_reply(q, &state); + if (r < 0) + goto fail; + + dns_query_complete(q, state); + return; + } + + if (c->error_code != 0) { + /* If the candidate had an error condition of its own, start with that. */ + state = DNS_TRANSACTION_ERRNO; + q->answer = dns_answer_unref(q->answer); + q->answer_rcode = 0; + q->answer_dnssec_result = _DNSSEC_RESULT_INVALID; + q->answer_authenticated = false; + q->answer_errno = c->error_code; + } + + SET_FOREACH(t, c->transactions, i) { + + switch (t->state) { + + case DNS_TRANSACTION_SUCCESS: { + /* We found a successfully reply, merge it into the answer */ + r = dns_answer_extend(&q->answer, t->answer); + if (r < 0) + goto fail; + + q->answer_rcode = t->answer_rcode; + q->answer_errno = 0; + + if (t->answer_authenticated) { + has_authenticated = true; + dnssec_result_authenticated = t->answer_dnssec_result; + } else { + has_non_authenticated = true; + dnssec_result_non_authenticated = t->answer_dnssec_result; + } + + state = DNS_TRANSACTION_SUCCESS; + break; + } + + case DNS_TRANSACTION_NULL: + case DNS_TRANSACTION_PENDING: + case DNS_TRANSACTION_VALIDATING: + case DNS_TRANSACTION_ABORTED: + /* Ignore transactions that didn't complete */ + continue; + + default: + /* Any kind of failure? Store the data away, if there's nothing stored yet. */ + if (state == DNS_TRANSACTION_SUCCESS) + continue; + + /* If there's already an authenticated negative reply stored, then prefer that over any unauthenticated one */ + if (q->answer_authenticated && !t->answer_authenticated) + continue; + + q->answer = dns_answer_unref(q->answer); + q->answer_rcode = t->answer_rcode; + q->answer_dnssec_result = t->answer_dnssec_result; + q->answer_authenticated = t->answer_authenticated; + q->answer_errno = t->answer_errno; + + state = t->state; + break; + } + } + + if (state == DNS_TRANSACTION_SUCCESS) { + q->answer_authenticated = has_authenticated && !has_non_authenticated; + q->answer_dnssec_result = q->answer_authenticated ? dnssec_result_authenticated : dnssec_result_non_authenticated; + } + + q->answer_protocol = c->scope->protocol; + q->answer_family = c->scope->family; + + dns_search_domain_unref(q->answer_search_domain); + q->answer_search_domain = dns_search_domain_ref(c->search_domain); + + r = dns_query_synthesize_reply(q, &state); + if (r < 0) + goto fail; + + dns_query_complete(q, state); + return; + +fail: + q->answer_errno = -r; + dns_query_complete(q, DNS_TRANSACTION_ERRNO); +} + +void dns_query_ready(DnsQuery *q) { + + DnsQueryCandidate *bad = NULL, *c; + bool pending = false; + + assert(q); + assert(DNS_TRANSACTION_IS_LIVE(q->state)); + + /* Note that this call might invalidate the query. Callers + * should hence not attempt to access the query or transaction + * after calling this function, unless the block_ready + * counter was explicitly bumped before doing so. */ + + if (q->block_ready > 0) + return; + + LIST_FOREACH(candidates_by_query, c, q->candidates) { + DnsTransactionState state; + + state = dns_query_candidate_state(c); + switch (state) { + + case DNS_TRANSACTION_SUCCESS: + /* One of the candidates is successful, + * let's use it, and copy its data out */ + dns_query_accept(q, c); + return; + + case DNS_TRANSACTION_NULL: + case DNS_TRANSACTION_PENDING: + case DNS_TRANSACTION_VALIDATING: + /* One of the candidates is still going on, + * let's maybe wait for it */ + pending = true; + break; + + default: + /* Any kind of failure */ + bad = c; + break; + } + } + + if (pending) + return; + + dns_query_accept(q, bad); +} + +static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) { + _cleanup_(dns_question_unrefp) DnsQuestion *nq_idna = NULL, *nq_utf8 = NULL; + int r, k; + + assert(q); + + q->n_cname_redirects++; + if (q->n_cname_redirects > CNAME_MAX) + return -ELOOP; + + r = dns_question_cname_redirect(q->question_idna, cname, &nq_idna); + if (r < 0) + return r; + else if (r > 0) + log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q->question_idna), dns_question_first_name(nq_idna)); + + k = dns_question_is_equal(q->question_idna, q->question_utf8); + if (k < 0) + return r; + if (k > 0) { + /* Same question? Shortcut new question generation */ + nq_utf8 = dns_question_ref(nq_idna); + k = r; + } else { + k = dns_question_cname_redirect(q->question_utf8, cname, &nq_utf8); + if (k < 0) + return k; + else if (k > 0) + log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q->question_utf8), dns_question_first_name(nq_utf8)); + } + + if (r == 0 && k == 0) /* No actual cname happened? */ + return -ELOOP; + + if (q->answer_protocol == DNS_PROTOCOL_DNS) { + /* Don't permit CNAME redirects from unicast DNS to LLMNR or MulticastDNS, so that global resources + * cannot invade the local namespace. The opposite way we permit: local names may redirect to global + * ones. */ + + q->flags &= ~(SD_RESOLVED_LLMNR|SD_RESOLVED_MDNS); /* mask away the local protocols */ + } + + /* Turn off searching for the new name */ + q->flags |= SD_RESOLVED_NO_SEARCH; + + dns_question_unref(q->question_idna); + q->question_idna = TAKE_PTR(nq_idna); + + dns_question_unref(q->question_utf8); + q->question_utf8 = TAKE_PTR(nq_utf8); + + dns_query_free_candidates(q); + dns_query_reset_answer(q); + + q->state = DNS_TRANSACTION_NULL; + + return 0; +} + +int dns_query_process_cname(DnsQuery *q) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL; + DnsQuestion *question; + DnsResourceRecord *rr; + int r; + + assert(q); + + if (!IN_SET(q->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_NULL)) + return DNS_QUERY_NOMATCH; + + question = dns_query_question_for_protocol(q, q->answer_protocol); + + DNS_ANSWER_FOREACH(rr, q->answer) { + r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); + if (r < 0) + return r; + if (r > 0) + return DNS_QUERY_MATCH; /* The answer matches directly, no need to follow cnames */ + + r = dns_question_matches_cname_or_dname(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); + if (r < 0) + return r; + if (r > 0 && !cname) + cname = dns_resource_record_ref(rr); + } + + if (!cname) + return DNS_QUERY_NOMATCH; /* No match and no cname to follow */ + + if (q->flags & SD_RESOLVED_NO_CNAME) + return -ELOOP; + + if (!q->answer_authenticated) + q->previous_redirect_unauthenticated = true; + + /* OK, let's actually follow the CNAME */ + r = dns_query_cname_redirect(q, cname); + if (r < 0) + return r; + + /* Let's see if the answer can already answer the new + * redirected question */ + r = dns_query_process_cname(q); + if (r != DNS_QUERY_NOMATCH) + return r; + + /* OK, it cannot, let's begin with the new query */ + r = dns_query_go(q); + if (r < 0) + return r; + + return DNS_QUERY_RESTARTED; /* We restarted the query for a new cname */ +} + +static int on_bus_track(sd_bus_track *t, void *userdata) { + DnsQuery *q = userdata; + + assert(t); + assert(q); + + log_debug("Client of active query vanished, aborting query."); + dns_query_complete(q, DNS_TRANSACTION_ABORTED); + return 0; +} + +int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) { + int r; + + assert(q); + assert(m); + + if (!q->bus_track) { + r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, on_bus_track, q); + if (r < 0) + return r; + } + + r = sd_bus_track_add_sender(q->bus_track, m); + if (r < 0) + return r; + + return 0; +} + +DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol) { + assert(q); + + switch (protocol) { + + case DNS_PROTOCOL_DNS: + return q->question_idna; + + case DNS_PROTOCOL_MDNS: + case DNS_PROTOCOL_LLMNR: + return q->question_utf8; + + default: + return NULL; + } +} + +const char *dns_query_string(DnsQuery *q) { + const char *name; + int r; + + /* Returns a somewhat useful human-readable lookup key string for this query */ + + if (q->request_address_string) + return q->request_address_string; + + if (q->request_address_valid) { + r = in_addr_to_string(q->request_family, &q->request_address, &q->request_address_string); + if (r >= 0) + return q->request_address_string; + } + + name = dns_question_first_name(q->question_utf8); + if (name) + return name; + + return dns_question_first_name(q->question_idna); +} + +bool dns_query_fully_authenticated(DnsQuery *q) { + assert(q); + + return q->answer_authenticated && !q->previous_redirect_unauthenticated; +} diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h new file mode 100644 index 00000000..5ee946bc --- /dev/null +++ b/src/resolve/resolved-dns-query.h @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "set.h" + +typedef struct DnsQueryCandidate DnsQueryCandidate; +typedef struct DnsQuery DnsQuery; + +#include "resolved-dns-answer.h" +#include "resolved-dns-question.h" +#include "resolved-dns-stream.h" +#include "resolved-dns-search-domain.h" + +struct DnsQueryCandidate { + DnsQuery *query; + DnsScope *scope; + + DnsSearchDomain *search_domain; + + int error_code; + Set *transactions; + + LIST_FIELDS(DnsQueryCandidate, candidates_by_query); + LIST_FIELDS(DnsQueryCandidate, candidates_by_scope); +}; + +struct DnsQuery { + Manager *manager; + + /* When resolving a service, we first create a TXT+SRV query, + * and then for the hostnames we discover auxiliary A+AAAA + * queries. This pointer always points from the auxiliary + * queries back to the TXT+SRV query. */ + DnsQuery *auxiliary_for; + LIST_HEAD(DnsQuery, auxiliary_queries); + unsigned n_auxiliary_queries; + int auxiliary_result; + + /* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note that even + * on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names (in contrast to their + * domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference between these two fields is mostly + * relevant only for explicit *hostname* lookups as well as the domain suffixes of service lookups. */ + DnsQuestion *question_idna; + DnsQuestion *question_utf8; + + uint64_t flags; + int ifindex; + + /* If true, A or AAAA RR lookups will be suppressed on links with no routable address of the matching address + * family */ + bool suppress_unroutable_family; + + /* If true, the RR TTLs of the answer will be clamped by their current left validity in the cache */ + bool clamp_ttl; + + DnsTransactionState state; + unsigned n_cname_redirects; + + LIST_HEAD(DnsQueryCandidate, candidates); + sd_event_source *timeout_event_source; + + /* Discovered data */ + DnsAnswer *answer; + int answer_rcode; + DnssecResult answer_dnssec_result; + bool answer_authenticated; + DnsProtocol answer_protocol; + int answer_family; + DnsSearchDomain *answer_search_domain; + int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */ + bool previous_redirect_unauthenticated; + + /* Bus client information */ + sd_bus_message *request; + int request_family; + bool request_address_valid; + union in_addr_union request_address; + unsigned block_all_complete; + char *request_address_string; + + /* DNS stub information */ + DnsPacket *request_dns_packet; + DnsStream *request_dns_stream; + DnsPacket *reply_dns_packet; + + /* Completion callback */ + void (*complete)(DnsQuery* q); + unsigned block_ready; + + sd_bus_track *bus_track; + + LIST_FIELDS(DnsQuery, queries); + LIST_FIELDS(DnsQuery, auxiliary_queries); +}; + +enum { + DNS_QUERY_MATCH, + DNS_QUERY_NOMATCH, + DNS_QUERY_RESTARTED, +}; + +DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c); +void dns_query_candidate_notify(DnsQueryCandidate *c); + +int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question_utf8, DnsQuestion *question_idna, int family, uint64_t flags); +DnsQuery *dns_query_free(DnsQuery *q); + +int dns_query_make_auxiliary(DnsQuery *q, DnsQuery *auxiliary_for); + +int dns_query_go(DnsQuery *q); +void dns_query_ready(DnsQuery *q); + +int dns_query_process_cname(DnsQuery *q); + +int dns_query_bus_track(DnsQuery *q, sd_bus_message *m); + +DnsQuestion* dns_query_question_for_protocol(DnsQuery *q, DnsProtocol protocol); + +const char *dns_query_string(DnsQuery *q); + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free); + +bool dns_query_fully_authenticated(DnsQuery *q); diff --git a/src/resolve/resolved-dns-question.c b/src/resolve/resolved-dns-question.c new file mode 100644 index 00000000..62833efa --- /dev/null +++ b/src/resolve/resolved-dns-question.c @@ -0,0 +1,446 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "dns-domain.h" +#include "dns-type.h" +#include "resolved-dns-question.h" + +DnsQuestion *dns_question_new(size_t n) { + DnsQuestion *q; + + assert(n > 0); + + q = malloc0(offsetof(DnsQuestion, keys) + sizeof(DnsResourceKey*) * n); + if (!q) + return NULL; + + q->n_ref = 1; + q->n_allocated = n; + + return q; +} + +static DnsQuestion *dns_question_free(DnsQuestion *q) { + size_t i; + + assert(q); + + for (i = 0; i < q->n_keys; i++) + dns_resource_key_unref(q->keys[i]); + return mfree(q); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsQuestion, dns_question, dns_question_free); + +int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key) { + /* Insert without checking for duplicates. */ + + assert(key); + assert(q); + + if (q->n_keys >= q->n_allocated) + return -ENOSPC; + + q->keys[q->n_keys++] = dns_resource_key_ref(key); + return 0; +} + +int dns_question_add(DnsQuestion *q, DnsResourceKey *key) { + int r; + + assert(key); + + if (!q) + return -ENOSPC; + + for (size_t i = 0; i < q->n_keys; i++) { + r = dns_resource_key_equal(q->keys[i], key); + if (r < 0) + return r; + if (r > 0) + return 0; + } + + return dns_question_add_raw(q, key); +} + +int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) { + size_t i; + int r; + + assert(rr); + + if (!q) + return 0; + + for (i = 0; i < q->n_keys; i++) { + r = dns_resource_key_match_rr(q->keys[i], rr, search_domain); + if (r != 0) + return r; + } + + return 0; +} + +int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) { + size_t i; + int r; + + assert(rr); + + if (!q) + return 0; + + if (!IN_SET(rr->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME)) + return 0; + + for (i = 0; i < q->n_keys; i++) { + /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */ + if (!dns_type_may_redirect(q->keys[i]->type)) + return 0; + + r = dns_resource_key_match_cname_or_dname(q->keys[i], rr->key, search_domain); + if (r != 0) + return r; + } + + return 0; +} + +int dns_question_is_valid_for_query(DnsQuestion *q) { + const char *name; + size_t i; + int r; + + if (!q) + return 0; + + if (q->n_keys <= 0) + return 0; + + if (q->n_keys > 65535) + return 0; + + name = dns_resource_key_name(q->keys[0]); + if (!name) + return 0; + + /* Check that all keys in this question bear the same name */ + for (i = 0; i < q->n_keys; i++) { + assert(q->keys[i]); + + if (i > 0) { + r = dns_name_equal(dns_resource_key_name(q->keys[i]), name); + if (r <= 0) + return r; + } + + if (!dns_type_is_valid_query(q->keys[i]->type)) + return 0; + } + + return 1; +} + +int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) { + size_t j; + int r; + + assert(k); + + if (!a) + return 0; + + for (j = 0; j < a->n_keys; j++) { + r = dns_resource_key_equal(a->keys[j], k); + if (r != 0) + return r; + } + + return 0; +} + +int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) { + size_t j; + int r; + + if (a == b) + return 1; + + if (!a) + return !b || b->n_keys == 0; + if (!b) + return a->n_keys == 0; + + /* Checks if all keys in a are also contained b, and vice versa */ + + for (j = 0; j < a->n_keys; j++) { + r = dns_question_contains(b, a->keys[j]); + if (r <= 0) + return r; + } + + for (j = 0; j < b->n_keys; j++) { + r = dns_question_contains(a, b->keys[j]); + if (r <= 0) + return r; + } + + return 1; +} + +int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret) { + _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL; + DnsResourceKey *key; + bool same = true; + int r; + + assert(cname); + assert(ret); + assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME)); + + if (dns_question_size(q) <= 0) { + *ret = NULL; + return 0; + } + + DNS_QUESTION_FOREACH(key, q) { + _cleanup_free_ char *destination = NULL; + const char *d; + + if (cname->key->type == DNS_TYPE_CNAME) + d = cname->cname.name; + else { + r = dns_name_change_suffix(dns_resource_key_name(key), dns_resource_key_name(cname->key), cname->dname.name, &destination); + if (r < 0) + return r; + if (r == 0) + continue; + + d = destination; + } + + r = dns_name_equal(dns_resource_key_name(key), d); + if (r < 0) + return r; + + if (r == 0) { + same = false; + break; + } + } + + /* Fully the same, indicate we didn't do a thing */ + if (same) { + *ret = NULL; + return 0; + } + + n = dns_question_new(q->n_keys); + if (!n) + return -ENOMEM; + + /* Create a new question, and patch in the new name */ + DNS_QUESTION_FOREACH(key, q) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL; + + k = dns_resource_key_new_redirect(key, cname); + if (!k) + return -ENOMEM; + + r = dns_question_add(n, k); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(n); + + return 1; +} + +const char *dns_question_first_name(DnsQuestion *q) { + + if (!q) + return NULL; + + if (q->n_keys < 1) + return NULL; + + return dns_resource_key_name(q->keys[0]); +} + +int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna) { + _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL; + _cleanup_free_ char *buf = NULL; + int r; + + assert(ret); + assert(name); + + if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC)) + return -EAFNOSUPPORT; + + if (convert_idna) { + r = dns_name_apply_idna(name, &buf); + if (r < 0) + return r; + if (r > 0 && !streq(name, buf)) + name = buf; + else + /* We did not manage to create convert the idna name, or it's + * the same as the original name. We assume the caller already + * created an unconverted question, so let's not repeat work + * unnecessarily. */ + return -EALREADY; + } + + q = dns_question_new(family == AF_UNSPEC ? 2 : 1); + if (!q) + return -ENOMEM; + + if (family != AF_INET6) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + + key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, name); + if (!key) + return -ENOMEM; + + r = dns_question_add(q, key); + if (r < 0) + return r; + } + + if (family != AF_INET) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + + key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, name); + if (!key) + return -ENOMEM; + + r = dns_question_add(q, key); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(q); + + return 0; +} + +int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL; + _cleanup_free_ char *reverse = NULL; + int r; + + assert(ret); + assert(a); + + if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC)) + return -EAFNOSUPPORT; + + r = dns_name_reverse(family, a, &reverse); + if (r < 0) + return r; + + q = dns_question_new(1); + if (!q) + return -ENOMEM; + + key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse); + if (!key) + return -ENOMEM; + + reverse = NULL; + + r = dns_question_add(q, key); + if (r < 0) + return r; + + *ret = TAKE_PTR(q); + + return 0; +} + +int dns_question_new_service( + DnsQuestion **ret, + const char *service, + const char *type, + const char *domain, + bool with_txt, + bool convert_idna) { + + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL; + _cleanup_free_ char *buf = NULL, *joined = NULL; + const char *name; + int r; + + assert(ret); + + /* We support three modes of invocation: + * + * 1. Only a domain is specified, in which case we assume a properly encoded SRV RR name, including service + * type and possibly a service name. If specified in this way we assume it's already IDNA converted if + * that's necessary. + * + * 2. Both service type and a domain specified, in which case a normal SRV RR is assumed, without a DNS-SD + * style prefix. In this case we'll IDNA convert the domain, if that's requested. + * + * 3. All three of service name, type and domain are specified, in which case a DNS-SD service is put + * together. The service name is never IDNA converted, and the domain is if requested. + * + * It's not supported to specify a service name without a type, or no domain name. + */ + + if (!domain) + return -EINVAL; + + if (type) { + if (convert_idna) { + r = dns_name_apply_idna(domain, &buf); + if (r < 0) + return r; + if (r > 0) + domain = buf; + } + + r = dns_service_join(service, type, domain, &joined); + if (r < 0) + return r; + + name = joined; + } else { + if (service) + return -EINVAL; + + name = domain; + } + + q = dns_question_new(1 + with_txt); + if (!q) + return -ENOMEM; + + key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_SRV, name); + if (!key) + return -ENOMEM; + + r = dns_question_add(q, key); + if (r < 0) + return r; + + if (with_txt) { + dns_resource_key_unref(key); + key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_TXT, name); + if (!key) + return -ENOMEM; + + r = dns_question_add(q, key); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(q); + + return 0; +} diff --git a/src/resolve/resolved-dns-question.h b/src/resolve/resolved-dns-question.h new file mode 100644 index 00000000..0803f49b --- /dev/null +++ b/src/resolve/resolved-dns-question.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct DnsQuestion DnsQuestion; + +#include "macro.h" +#include "resolved-dns-rr.h" + +/* A simple array of resource keys */ + +struct DnsQuestion { + unsigned n_ref; + size_t n_keys, n_allocated; + DnsResourceKey* keys[0]; +}; + +DnsQuestion *dns_question_new(size_t n); +DnsQuestion *dns_question_ref(DnsQuestion *q); +DnsQuestion *dns_question_unref(DnsQuestion *q); + +int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna); +int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a); +int dns_question_new_service(DnsQuestion **ret, const char *service, const char *type, const char *domain, bool with_txt, bool convert_idna); + +int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key); +int dns_question_add(DnsQuestion *q, DnsResourceKey *key); + +int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain); +int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char* search_domain); +int dns_question_is_valid_for_query(DnsQuestion *q); +int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k); +int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b); + +int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret); + +const char *dns_question_first_name(DnsQuestion *q); + +static inline size_t dns_question_size(DnsQuestion *q) { + return q ? q->n_keys : 0; +} + +static inline bool dns_question_isempty(DnsQuestion *q) { + return dns_question_size(q) <= 0; +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuestion*, dns_question_unref); + +#define _DNS_QUESTION_FOREACH(u, key, q) \ + for (size_t UNIQ_T(i, u) = ({ \ + (key) = ((q) && (q)->n_keys > 0) ? (q)->keys[0] : NULL; \ + 0; \ + }); \ + (q) && (UNIQ_T(i, u) < (q)->n_keys); \ + UNIQ_T(i, u)++, (key) = (UNIQ_T(i, u) < (q)->n_keys ? (q)->keys[UNIQ_T(i, u)] : NULL)) + +#define DNS_QUESTION_FOREACH(key, q) _DNS_QUESTION_FOREACH(UNIQ, key, q) diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c new file mode 100644 index 00000000..6ba26a24 --- /dev/null +++ b/src/resolve/resolved-dns-rr.c @@ -0,0 +1,1820 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "dns-domain.h" +#include "dns-type.h" +#include "escape.h" +#include "hexdecoct.h" +#include "memory-util.h" +#include "resolved-dns-dnssec.h" +#include "resolved-dns-packet.h" +#include "resolved-dns-rr.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" + +DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) { + DnsResourceKey *k; + size_t l; + + assert(name); + + l = strlen(name); + k = malloc0(sizeof(DnsResourceKey) + l + 1); + if (!k) + return NULL; + + k->n_ref = 1; + k->class = class; + k->type = type; + + strcpy((char*) k + sizeof(DnsResourceKey), name); + + return k; +} + +DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname) { + int r; + + assert(key); + assert(cname); + + assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME)); + + if (cname->key->type == DNS_TYPE_CNAME) + return dns_resource_key_new(key->class, key->type, cname->cname.name); + else { + DnsResourceKey *k; + char *destination = NULL; + + r = dns_name_change_suffix(dns_resource_key_name(key), dns_resource_key_name(cname->key), cname->dname.name, &destination); + if (r < 0) + return NULL; + if (r == 0) + return dns_resource_key_ref((DnsResourceKey*) key); + + k = dns_resource_key_new_consume(key->class, key->type, destination); + if (!k) + return mfree(destination); + + return k; + } +} + +int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name) { + DnsResourceKey *new_key; + char *joined; + int r; + + assert(ret); + assert(key); + assert(name); + + if (dns_name_is_root(name)) { + *ret = dns_resource_key_ref(key); + return 0; + } + + r = dns_name_concat(dns_resource_key_name(key), name, 0, &joined); + if (r < 0) + return r; + + new_key = dns_resource_key_new_consume(key->class, key->type, joined); + if (!new_key) { + free(joined); + return -ENOMEM; + } + + *ret = new_key; + return 0; +} + +DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) { + DnsResourceKey *k; + + assert(name); + + k = new0(DnsResourceKey, 1); + if (!k) + return NULL; + + k->n_ref = 1; + k->class = class; + k->type = type; + k->_name = name; + + return k; +} + +DnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) { + + if (!k) + return NULL; + + /* Static/const keys created with DNS_RESOURCE_KEY_CONST will + * set this to -1, they should not be reffed/unreffed */ + assert(k->n_ref != (unsigned) -1); + + assert(k->n_ref > 0); + k->n_ref++; + + return k; +} + +DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) { + if (!k) + return NULL; + + assert(k->n_ref != (unsigned) -1); + assert(k->n_ref > 0); + + if (k->n_ref == 1) { + free(k->_name); + free(k); + } else + k->n_ref--; + + return NULL; +} + +const char* dns_resource_key_name(const DnsResourceKey *key) { + const char *name; + + if (!key) + return NULL; + + if (key->_name) + name = key->_name; + else + name = (char*) key + sizeof(DnsResourceKey); + + if (dns_name_is_root(name)) + return "."; + else + return name; +} + +bool dns_resource_key_is_address(const DnsResourceKey *key) { + assert(key); + + /* Check if this is an A or AAAA resource key */ + + return key->class == DNS_CLASS_IN && IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_AAAA); +} + +bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey *key) { + assert(key); + + /* Check if this is a PTR resource key used in + Service Instance Enumeration as described in RFC6763 p4.1. */ + + if (key->type != DNS_TYPE_PTR) + return false; + + return dns_name_endswith(dns_resource_key_name(key), "_tcp.local") || + dns_name_endswith(dns_resource_key_name(key), "_udp.local"); +} + +int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) { + int r; + + if (a == b) + return 1; + + r = dns_name_equal(dns_resource_key_name(a), dns_resource_key_name(b)); + if (r <= 0) + return r; + + if (a->class != b->class) + return 0; + + if (a->type != b->type) + return 0; + + return 1; +} + +int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain) { + int r; + + assert(key); + assert(rr); + + if (key == rr->key) + return 1; + + /* Checks if an rr matches the specified key. If a search + * domain is specified, it will also be checked if the key + * with the search domain suffixed might match the RR. */ + + if (rr->key->class != key->class && key->class != DNS_CLASS_ANY) + return 0; + + if (rr->key->type != key->type && key->type != DNS_TYPE_ANY) + return 0; + + r = dns_name_equal(dns_resource_key_name(rr->key), dns_resource_key_name(key)); + if (r != 0) + return r; + + if (search_domain) { + _cleanup_free_ char *joined = NULL; + + r = dns_name_concat(dns_resource_key_name(key), search_domain, 0, &joined); + if (r < 0) + return r; + + return dns_name_equal(dns_resource_key_name(rr->key), joined); + } + + return 0; +} + +int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain) { + int r; + + assert(key); + assert(cname); + + if (cname->class != key->class && key->class != DNS_CLASS_ANY) + return 0; + + if (cname->type == DNS_TYPE_CNAME) + r = dns_name_equal(dns_resource_key_name(key), dns_resource_key_name(cname)); + else if (cname->type == DNS_TYPE_DNAME) + r = dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(cname)); + else + return 0; + + if (r != 0) + return r; + + if (search_domain) { + _cleanup_free_ char *joined = NULL; + + r = dns_name_concat(dns_resource_key_name(key), search_domain, 0, &joined); + if (r < 0) + return r; + + if (cname->type == DNS_TYPE_CNAME) + return dns_name_equal(joined, dns_resource_key_name(cname)); + else if (cname->type == DNS_TYPE_DNAME) + return dns_name_endswith(joined, dns_resource_key_name(cname)); + } + + return 0; +} + +int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa) { + assert(soa); + assert(key); + + /* Checks whether 'soa' is a SOA record for the specified key. */ + + if (soa->class != key->class) + return 0; + + if (soa->type != DNS_TYPE_SOA) + return 0; + + return dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(soa)); +} + +static void dns_resource_key_hash_func(const DnsResourceKey *k, struct siphash *state) { + assert(k); + + dns_name_hash_func(dns_resource_key_name(k), state); + siphash24_compress(&k->class, sizeof(k->class), state); + siphash24_compress(&k->type, sizeof(k->type), state); +} + +static int dns_resource_key_compare_func(const DnsResourceKey *x, const DnsResourceKey *y) { + int ret; + + ret = dns_name_compare_func(dns_resource_key_name(x), dns_resource_key_name(y)); + if (ret != 0) + return ret; + + ret = CMP(x->type, y->type); + if (ret != 0) + return ret; + + ret = CMP(x->class, y->class); + if (ret != 0) + return ret; + + return 0; +} + +DEFINE_HASH_OPS(dns_resource_key_hash_ops, DnsResourceKey, dns_resource_key_hash_func, dns_resource_key_compare_func); + +char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size) { + const char *c, *t; + char *ans = buf; + + /* If we cannot convert the CLASS/TYPE into a known string, + use the format recommended by RFC 3597, Section 5. */ + + c = dns_class_to_string(key->class); + t = dns_type_to_string(key->type); + + snprintf(buf, buf_size, "%s %s%s%.0u %s%s%.0u", + dns_resource_key_name(key), + strempty(c), c ? "" : "CLASS", c ? 0 : key->class, + strempty(t), t ? "" : "TYPE", t ? 0 : key->type); + + return ans; +} + +bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b) { + assert(a); + assert(b); + + /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do + * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come + * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same + * superficial data. */ + + if (!*a) + return false; + if (!*b) + return false; + + /* We refuse merging const keys */ + if ((*a)->n_ref == (unsigned) -1) + return false; + if ((*b)->n_ref == (unsigned) -1) + return false; + + /* Already the same? */ + if (*a == *b) + return true; + + /* Are they really identical? */ + if (dns_resource_key_equal(*a, *b) <= 0) + return false; + + /* Keep the one which already has more references. */ + if ((*a)->n_ref > (*b)->n_ref) { + dns_resource_key_unref(*b); + *b = dns_resource_key_ref(*a); + } else { + dns_resource_key_unref(*a); + *a = dns_resource_key_ref(*b); + } + + return true; +} + +DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) { + DnsResourceRecord *rr; + + rr = new0(DnsResourceRecord, 1); + if (!rr) + return NULL; + + rr->n_ref = 1; + rr->key = dns_resource_key_ref(key); + rr->expiry = USEC_INFINITY; + rr->n_skip_labels_signer = rr->n_skip_labels_source = (unsigned) -1; + + return rr; +} + +DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + + key = dns_resource_key_new(class, type, name); + if (!key) + return NULL; + + return dns_resource_record_new(key); +} + +static DnsResourceRecord* dns_resource_record_free(DnsResourceRecord *rr) { + assert(rr); + + if (rr->key) { + switch(rr->key->type) { + + case DNS_TYPE_SRV: + free(rr->srv.name); + break; + + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: + free(rr->ptr.name); + break; + + case DNS_TYPE_HINFO: + free(rr->hinfo.cpu); + free(rr->hinfo.os); + break; + + case DNS_TYPE_TXT: + case DNS_TYPE_SPF: + dns_txt_item_free_all(rr->txt.items); + break; + + case DNS_TYPE_SOA: + free(rr->soa.mname); + free(rr->soa.rname); + break; + + case DNS_TYPE_MX: + free(rr->mx.exchange); + break; + + case DNS_TYPE_DS: + free(rr->ds.digest); + break; + + case DNS_TYPE_SSHFP: + free(rr->sshfp.fingerprint); + break; + + case DNS_TYPE_DNSKEY: + free(rr->dnskey.key); + break; + + case DNS_TYPE_RRSIG: + free(rr->rrsig.signer); + free(rr->rrsig.signature); + break; + + case DNS_TYPE_NSEC: + free(rr->nsec.next_domain_name); + bitmap_free(rr->nsec.types); + break; + + case DNS_TYPE_NSEC3: + free(rr->nsec3.next_hashed_name); + free(rr->nsec3.salt); + bitmap_free(rr->nsec3.types); + break; + + case DNS_TYPE_LOC: + case DNS_TYPE_A: + case DNS_TYPE_AAAA: + break; + + case DNS_TYPE_TLSA: + free(rr->tlsa.data); + break; + + case DNS_TYPE_CAA: + free(rr->caa.tag); + free(rr->caa.value); + break; + + case DNS_TYPE_OPENPGPKEY: + default: + if (!rr->unparseable) + free(rr->generic.data); + } + + if (rr->unparseable) + free(rr->generic.data); + + free(rr->wire_format); + dns_resource_key_unref(rr->key); + } + + free(rr->to_string); + return mfree(rr); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsResourceRecord, dns_resource_record, dns_resource_record_free); + +int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + _cleanup_free_ char *ptr = NULL; + int r; + + assert(ret); + assert(address); + assert(hostname); + + r = dns_name_reverse(family, address, &ptr); + if (r < 0) + return r; + + key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr); + if (!key) + return -ENOMEM; + + ptr = NULL; + + rr = dns_resource_record_new(key); + if (!rr) + return -ENOMEM; + + rr->ptr.name = strdup(hostname); + if (!rr->ptr.name) + return -ENOMEM; + + *ret = TAKE_PTR(rr); + + return 0; +} + +int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name) { + DnsResourceRecord *rr; + + assert(ret); + assert(address); + assert(family); + + if (family == AF_INET) { + + rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, name); + if (!rr) + return -ENOMEM; + + rr->a.in_addr = address->in; + + } else if (family == AF_INET6) { + + rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, name); + if (!rr) + return -ENOMEM; + + rr->aaaa.in6_addr = address->in6; + } else + return -EAFNOSUPPORT; + + *ret = rr; + + return 0; +} + +#define FIELD_EQUAL(a, b, field) \ + ((a).field ## _size == (b).field ## _size && \ + memcmp_safe((a).field, (b).field, (a).field ## _size) == 0) + +int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) { + int r; + + /* Check if a and b are the same, but don't look at their keys */ + + if (a->unparseable != b->unparseable) + return 0; + + switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) { + + case DNS_TYPE_SRV: + r = dns_name_equal(a->srv.name, b->srv.name); + if (r <= 0) + return r; + + return a->srv.priority == b->srv.priority && + a->srv.weight == b->srv.weight && + a->srv.port == b->srv.port; + + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: + return dns_name_equal(a->ptr.name, b->ptr.name); + + case DNS_TYPE_HINFO: + return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) && + strcaseeq(a->hinfo.os, b->hinfo.os); + + case DNS_TYPE_SPF: /* exactly the same as TXT */ + case DNS_TYPE_TXT: + return dns_txt_item_equal(a->txt.items, b->txt.items); + + case DNS_TYPE_A: + return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0; + + case DNS_TYPE_AAAA: + return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0; + + case DNS_TYPE_SOA: + r = dns_name_equal(a->soa.mname, b->soa.mname); + if (r <= 0) + return r; + r = dns_name_equal(a->soa.rname, b->soa.rname); + if (r <= 0) + return r; + + return a->soa.serial == b->soa.serial && + a->soa.refresh == b->soa.refresh && + a->soa.retry == b->soa.retry && + a->soa.expire == b->soa.expire && + a->soa.minimum == b->soa.minimum; + + case DNS_TYPE_MX: + if (a->mx.priority != b->mx.priority) + return 0; + + return dns_name_equal(a->mx.exchange, b->mx.exchange); + + case DNS_TYPE_LOC: + assert(a->loc.version == b->loc.version); + + return a->loc.size == b->loc.size && + a->loc.horiz_pre == b->loc.horiz_pre && + a->loc.vert_pre == b->loc.vert_pre && + a->loc.latitude == b->loc.latitude && + a->loc.longitude == b->loc.longitude && + a->loc.altitude == b->loc.altitude; + + case DNS_TYPE_DS: + return a->ds.key_tag == b->ds.key_tag && + a->ds.algorithm == b->ds.algorithm && + a->ds.digest_type == b->ds.digest_type && + FIELD_EQUAL(a->ds, b->ds, digest); + + case DNS_TYPE_SSHFP: + return a->sshfp.algorithm == b->sshfp.algorithm && + a->sshfp.fptype == b->sshfp.fptype && + FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint); + + case DNS_TYPE_DNSKEY: + return a->dnskey.flags == b->dnskey.flags && + a->dnskey.protocol == b->dnskey.protocol && + a->dnskey.algorithm == b->dnskey.algorithm && + FIELD_EQUAL(a->dnskey, b->dnskey, key); + + case DNS_TYPE_RRSIG: + /* do the fast comparisons first */ + return a->rrsig.type_covered == b->rrsig.type_covered && + a->rrsig.algorithm == b->rrsig.algorithm && + a->rrsig.labels == b->rrsig.labels && + a->rrsig.original_ttl == b->rrsig.original_ttl && + a->rrsig.expiration == b->rrsig.expiration && + a->rrsig.inception == b->rrsig.inception && + a->rrsig.key_tag == b->rrsig.key_tag && + FIELD_EQUAL(a->rrsig, b->rrsig, signature) && + dns_name_equal(a->rrsig.signer, b->rrsig.signer); + + case DNS_TYPE_NSEC: + return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) && + bitmap_equal(a->nsec.types, b->nsec.types); + + case DNS_TYPE_NSEC3: + return a->nsec3.algorithm == b->nsec3.algorithm && + a->nsec3.flags == b->nsec3.flags && + a->nsec3.iterations == b->nsec3.iterations && + FIELD_EQUAL(a->nsec3, b->nsec3, salt) && + FIELD_EQUAL(a->nsec3, b->nsec3, next_hashed_name) && + bitmap_equal(a->nsec3.types, b->nsec3.types); + + case DNS_TYPE_TLSA: + return a->tlsa.cert_usage == b->tlsa.cert_usage && + a->tlsa.selector == b->tlsa.selector && + a->tlsa.matching_type == b->tlsa.matching_type && + FIELD_EQUAL(a->tlsa, b->tlsa, data); + + case DNS_TYPE_CAA: + return a->caa.flags == b->caa.flags && + streq(a->caa.tag, b->caa.tag) && + FIELD_EQUAL(a->caa, b->caa, value); + + case DNS_TYPE_OPENPGPKEY: + default: + return FIELD_EQUAL(a->generic, b->generic, data); + } +} + +int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) { + int r; + + assert(a); + assert(b); + + if (a == b) + return 1; + + r = dns_resource_key_equal(a->key, b->key); + if (r <= 0) + return r; + + return dns_resource_record_payload_equal(a, b); +} + +static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude, + uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) { + char *s; + char NS = latitude >= 1U<<31 ? 'N' : 'S'; + char EW = longitude >= 1U<<31 ? 'E' : 'W'; + + int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude); + int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude); + double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude); + double siz = (size >> 4) * exp10((double) (size & 0xF)); + double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF)); + double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF)); + + if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm", + (lat / 60000 / 60), + (lat / 60000) % 60, + (lat % 60000) / 1000., + NS, + (lon / 60000 / 60), + (lon / 60000) % 60, + (lon % 60000) / 1000., + EW, + alt / 100., + siz / 100., + hor / 100., + ver / 100.) < 0) + return NULL; + + return s; +} + +static int format_timestamp_dns(char *buf, size_t l, time_t sec) { + struct tm tm; + + assert(buf); + assert(l > STRLEN("YYYYMMDDHHmmSS")); + + if (!gmtime_r(&sec, &tm)) + return -EINVAL; + + if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0) + return -EINVAL; + + return 0; +} + +static char *format_types(Bitmap *types) { + _cleanup_strv_free_ char **strv = NULL; + _cleanup_free_ char *str = NULL; + Iterator i; + unsigned type; + int r; + + BITMAP_FOREACH(type, types, i) { + if (dns_type_to_string(type)) { + r = strv_extend(&strv, dns_type_to_string(type)); + if (r < 0) + return NULL; + } else { + char *t; + + r = asprintf(&t, "TYPE%u", type); + if (r < 0) + return NULL; + + r = strv_consume(&strv, t); + if (r < 0) + return NULL; + } + } + + str = strv_join(strv, " "); + if (!str) + return NULL; + + return strjoin("( ", str, " )"); +} + +static char *format_txt(DnsTxtItem *first) { + DnsTxtItem *i; + size_t c = 1; + char *p, *s; + + LIST_FOREACH(items, i, first) + c += i->length * 4 + 3; + + p = s = new(char, c); + if (!s) + return NULL; + + LIST_FOREACH(items, i, first) { + size_t j; + + if (i != first) + *(p++) = ' '; + + *(p++) = '"'; + + for (j = 0; j < i->length; j++) { + if (i->data[j] < ' ' || i->data[j] == '"' || i->data[j] >= 127) { + *(p++) = '\\'; + *(p++) = '0' + (i->data[j] / 100); + *(p++) = '0' + ((i->data[j] / 10) % 10); + *(p++) = '0' + (i->data[j] % 10); + } else + *(p++) = i->data[j]; + } + + *(p++) = '"'; + } + + *p = 0; + return s; +} + +const char *dns_resource_record_to_string(DnsResourceRecord *rr) { + _cleanup_free_ char *t = NULL; + char *s, k[DNS_RESOURCE_KEY_STRING_MAX]; + int r; + + assert(rr); + + if (rr->to_string) + return rr->to_string; + + dns_resource_key_to_string(rr->key, k, sizeof(k)); + + switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { + + case DNS_TYPE_SRV: + r = asprintf(&s, "%s %u %u %u %s", + k, + rr->srv.priority, + rr->srv.weight, + rr->srv.port, + strna(rr->srv.name)); + if (r < 0) + return NULL; + break; + + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: + s = strjoin(k, " ", rr->ptr.name); + if (!s) + return NULL; + + break; + + case DNS_TYPE_HINFO: + s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os); + if (!s) + return NULL; + break; + + case DNS_TYPE_SPF: /* exactly the same as TXT */ + case DNS_TYPE_TXT: + t = format_txt(rr->txt.items); + if (!t) + return NULL; + + s = strjoin(k, " ", t); + if (!s) + return NULL; + break; + + case DNS_TYPE_A: { + _cleanup_free_ char *x = NULL; + + r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x); + if (r < 0) + return NULL; + + s = strjoin(k, " ", x); + if (!s) + return NULL; + break; + } + + case DNS_TYPE_AAAA: + r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t); + if (r < 0) + return NULL; + + s = strjoin(k, " ", t); + if (!s) + return NULL; + break; + + case DNS_TYPE_SOA: + r = asprintf(&s, "%s %s %s %u %u %u %u %u", + k, + strna(rr->soa.mname), + strna(rr->soa.rname), + rr->soa.serial, + rr->soa.refresh, + rr->soa.retry, + rr->soa.expire, + rr->soa.minimum); + if (r < 0) + return NULL; + break; + + case DNS_TYPE_MX: + r = asprintf(&s, "%s %u %s", + k, + rr->mx.priority, + rr->mx.exchange); + if (r < 0) + return NULL; + break; + + case DNS_TYPE_LOC: + assert(rr->loc.version == 0); + + t = format_location(rr->loc.latitude, + rr->loc.longitude, + rr->loc.altitude, + rr->loc.size, + rr->loc.horiz_pre, + rr->loc.vert_pre); + if (!t) + return NULL; + + s = strjoin(k, " ", t); + if (!s) + return NULL; + break; + + case DNS_TYPE_DS: + t = hexmem(rr->ds.digest, rr->ds.digest_size); + if (!t) + return NULL; + + r = asprintf(&s, "%s %u %u %u %s", + k, + rr->ds.key_tag, + rr->ds.algorithm, + rr->ds.digest_type, + t); + if (r < 0) + return NULL; + break; + + case DNS_TYPE_SSHFP: + t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size); + if (!t) + return NULL; + + r = asprintf(&s, "%s %u %u %s", + k, + rr->sshfp.algorithm, + rr->sshfp.fptype, + t); + if (r < 0) + return NULL; + break; + + case DNS_TYPE_DNSKEY: { + _cleanup_free_ char *alg = NULL; + char *ss; + uint16_t key_tag; + + key_tag = dnssec_keytag(rr, true); + + r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg); + if (r < 0) + return NULL; + + r = asprintf(&s, "%s %u %u %s", + k, + rr->dnskey.flags, + rr->dnskey.protocol, + alg); + if (r < 0) + return NULL; + + r = base64_append(&s, r, + rr->dnskey.key, rr->dnskey.key_size, + 8, columns()); + if (r < 0) + return NULL; + + r = asprintf(&ss, "%s\n" + " -- Flags:%s%s%s\n" + " -- Key tag: %u", + s, + rr->dnskey.flags & DNSKEY_FLAG_SEP ? " SEP" : "", + rr->dnskey.flags & DNSKEY_FLAG_REVOKE ? " REVOKE" : "", + rr->dnskey.flags & DNSKEY_FLAG_ZONE_KEY ? " ZONE_KEY" : "", + key_tag); + if (r < 0) + return NULL; + free(s); + s = ss; + + break; + } + + case DNS_TYPE_RRSIG: { + _cleanup_free_ char *alg = NULL; + char expiration[STRLEN("YYYYMMDDHHmmSS") + 1], inception[STRLEN("YYYYMMDDHHmmSS") + 1]; + const char *type; + + type = dns_type_to_string(rr->rrsig.type_covered); + + r = dnssec_algorithm_to_string_alloc(rr->rrsig.algorithm, &alg); + if (r < 0) + return NULL; + + r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration); + if (r < 0) + return NULL; + + r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception); + if (r < 0) + return NULL; + + /* TYPE?? follows + * http://tools.ietf.org/html/rfc3597#section-5 */ + + r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s", + k, + type ?: "TYPE", + type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered, + alg, + rr->rrsig.labels, + rr->rrsig.original_ttl, + expiration, + inception, + rr->rrsig.key_tag, + rr->rrsig.signer); + if (r < 0) + return NULL; + + r = base64_append(&s, r, + rr->rrsig.signature, rr->rrsig.signature_size, + 8, columns()); + if (r < 0) + return NULL; + + break; + } + + case DNS_TYPE_NSEC: + t = format_types(rr->nsec.types); + if (!t) + return NULL; + + r = asprintf(&s, "%s %s %s", + k, + rr->nsec.next_domain_name, + t); + if (r < 0) + return NULL; + break; + + case DNS_TYPE_NSEC3: { + _cleanup_free_ char *salt = NULL, *hash = NULL; + + if (rr->nsec3.salt_size > 0) { + salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size); + if (!salt) + return NULL; + } + + hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false); + if (!hash) + return NULL; + + t = format_types(rr->nsec3.types); + if (!t) + return NULL; + + r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s", + k, + rr->nsec3.algorithm, + rr->nsec3.flags, + rr->nsec3.iterations, + rr->nsec3.salt_size > 0 ? salt : "-", + hash, + t); + if (r < 0) + return NULL; + + break; + } + + case DNS_TYPE_TLSA: { + const char *cert_usage, *selector, *matching_type; + + cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage); + selector = tlsa_selector_to_string(rr->tlsa.selector); + matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type); + + t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size); + if (!t) + return NULL; + + r = asprintf(&s, + "%s %u %u %u %s\n" + " -- Cert. usage: %s\n" + " -- Selector: %s\n" + " -- Matching type: %s", + k, + rr->tlsa.cert_usage, + rr->tlsa.selector, + rr->tlsa.matching_type, + t, + cert_usage, + selector, + matching_type); + if (r < 0) + return NULL; + + break; + } + + case DNS_TYPE_CAA: { + _cleanup_free_ char *value; + + value = octescape(rr->caa.value, rr->caa.value_size); + if (!value) + return NULL; + + r = asprintf(&s, "%s %u %s \"%s\"%s%s%s%.0u", + k, + rr->caa.flags, + rr->caa.tag, + value, + rr->caa.flags ? "\n -- Flags:" : "", + rr->caa.flags & CAA_FLAG_CRITICAL ? " critical" : "", + rr->caa.flags & ~CAA_FLAG_CRITICAL ? " " : "", + rr->caa.flags & ~CAA_FLAG_CRITICAL); + if (r < 0) + return NULL; + + break; + } + + case DNS_TYPE_OPENPGPKEY: { + r = asprintf(&s, "%s", k); + if (r < 0) + return NULL; + + r = base64_append(&s, r, + rr->generic.data, rr->generic.data_size, + 8, columns()); + if (r < 0) + return NULL; + break; + } + + default: + t = hexmem(rr->generic.data, rr->generic.data_size); + if (!t) + return NULL; + + /* Format as documented in RFC 3597, Section 5 */ + r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t); + if (r < 0) + return NULL; + break; + } + + rr->to_string = s; + return s; +} + +ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) { + assert(rr); + assert(out); + + switch(rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { + case DNS_TYPE_SRV: + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: + case DNS_TYPE_HINFO: + case DNS_TYPE_SPF: + case DNS_TYPE_TXT: + case DNS_TYPE_A: + case DNS_TYPE_AAAA: + case DNS_TYPE_SOA: + case DNS_TYPE_MX: + case DNS_TYPE_LOC: + case DNS_TYPE_DS: + case DNS_TYPE_DNSKEY: + case DNS_TYPE_RRSIG: + case DNS_TYPE_NSEC: + case DNS_TYPE_NSEC3: + return -EINVAL; + + case DNS_TYPE_SSHFP: + *out = rr->sshfp.fingerprint; + return rr->sshfp.fingerprint_size; + + case DNS_TYPE_TLSA: + *out = rr->tlsa.data; + return rr->tlsa.data_size; + + case DNS_TYPE_OPENPGPKEY: + default: + *out = rr->generic.data; + return rr->generic.data_size; + } +} + +int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) { + + DnsPacket packet = { + .n_ref = 1, + .protocol = DNS_PROTOCOL_DNS, + .on_stack = true, + .refuse_compression = true, + .canonical_form = canonical, + }; + + size_t start, rds; + int r; + + assert(rr); + + /* Generates the RR in wire-format, optionally in the + * canonical form as discussed in the DNSSEC RFC 4034, Section + * 6.2. We allocate a throw-away DnsPacket object on the stack + * here, because we need some book-keeping for memory + * management, and can reuse the DnsPacket serializer, that + * can generate the canonical form, too, but also knows label + * compression and suchlike. */ + + if (rr->wire_format && rr->wire_format_canonical == canonical) + return 0; + + r = dns_packet_append_rr(&packet, rr, 0, &start, &rds); + if (r < 0) + return r; + + assert(start == 0); + assert(packet._data); + + free(rr->wire_format); + rr->wire_format = packet._data; + rr->wire_format_size = packet.size; + rr->wire_format_rdata_offset = rds; + rr->wire_format_canonical = canonical; + + packet._data = NULL; + dns_packet_unref(&packet); + + return 0; +} + +int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) { + const char *n; + int r; + + assert(rr); + assert(ret); + + /* Returns the RRset's signer, if it is known. */ + + if (rr->n_skip_labels_signer == (unsigned) -1) + return -ENODATA; + + n = dns_resource_key_name(rr->key); + r = dns_name_skip(n, rr->n_skip_labels_signer, &n); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + *ret = n; + return 0; +} + +int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) { + const char *n; + int r; + + assert(rr); + assert(ret); + + /* Returns the RRset's synthesizing source, if it is known. */ + + if (rr->n_skip_labels_source == (unsigned) -1) + return -ENODATA; + + n = dns_resource_key_name(rr->key); + r = dns_name_skip(n, rr->n_skip_labels_source, &n); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + + *ret = n; + return 0; +} + +int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone) { + const char *signer; + int r; + + assert(rr); + + r = dns_resource_record_signer(rr, &signer); + if (r < 0) + return r; + + return dns_name_equal(zone, signer); +} + +int dns_resource_record_is_synthetic(DnsResourceRecord *rr) { + int r; + + assert(rr); + + /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */ + + if (rr->n_skip_labels_source == (unsigned) -1) + return -ENODATA; + + if (rr->n_skip_labels_source == 0) + return 0; + + if (rr->n_skip_labels_source > 1) + return 1; + + r = dns_name_startswith(dns_resource_key_name(rr->key), "*"); + if (r < 0) + return r; + + return !r; +} + +void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *state) { + assert(rr); + + dns_resource_key_hash_func(rr->key, state); + + switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { + + case DNS_TYPE_SRV: + siphash24_compress(&rr->srv.priority, sizeof(rr->srv.priority), state); + siphash24_compress(&rr->srv.weight, sizeof(rr->srv.weight), state); + siphash24_compress(&rr->srv.port, sizeof(rr->srv.port), state); + dns_name_hash_func(rr->srv.name, state); + break; + + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: + dns_name_hash_func(rr->ptr.name, state); + break; + + case DNS_TYPE_HINFO: + string_hash_func(rr->hinfo.cpu, state); + string_hash_func(rr->hinfo.os, state); + break; + + case DNS_TYPE_TXT: + case DNS_TYPE_SPF: { + DnsTxtItem *j; + + LIST_FOREACH(items, j, rr->txt.items) { + siphash24_compress(j->data, j->length, state); + + /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab" + * followed by "". */ + siphash24_compress_byte(0, state); + } + break; + } + + case DNS_TYPE_A: + siphash24_compress(&rr->a.in_addr, sizeof(rr->a.in_addr), state); + break; + + case DNS_TYPE_AAAA: + siphash24_compress(&rr->aaaa.in6_addr, sizeof(rr->aaaa.in6_addr), state); + break; + + case DNS_TYPE_SOA: + dns_name_hash_func(rr->soa.mname, state); + dns_name_hash_func(rr->soa.rname, state); + siphash24_compress(&rr->soa.serial, sizeof(rr->soa.serial), state); + siphash24_compress(&rr->soa.refresh, sizeof(rr->soa.refresh), state); + siphash24_compress(&rr->soa.retry, sizeof(rr->soa.retry), state); + siphash24_compress(&rr->soa.expire, sizeof(rr->soa.expire), state); + siphash24_compress(&rr->soa.minimum, sizeof(rr->soa.minimum), state); + break; + + case DNS_TYPE_MX: + siphash24_compress(&rr->mx.priority, sizeof(rr->mx.priority), state); + dns_name_hash_func(rr->mx.exchange, state); + break; + + case DNS_TYPE_LOC: + siphash24_compress(&rr->loc.version, sizeof(rr->loc.version), state); + siphash24_compress(&rr->loc.size, sizeof(rr->loc.size), state); + siphash24_compress(&rr->loc.horiz_pre, sizeof(rr->loc.horiz_pre), state); + siphash24_compress(&rr->loc.vert_pre, sizeof(rr->loc.vert_pre), state); + siphash24_compress(&rr->loc.latitude, sizeof(rr->loc.latitude), state); + siphash24_compress(&rr->loc.longitude, sizeof(rr->loc.longitude), state); + siphash24_compress(&rr->loc.altitude, sizeof(rr->loc.altitude), state); + break; + + case DNS_TYPE_SSHFP: + siphash24_compress(&rr->sshfp.algorithm, sizeof(rr->sshfp.algorithm), state); + siphash24_compress(&rr->sshfp.fptype, sizeof(rr->sshfp.fptype), state); + siphash24_compress(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state); + break; + + case DNS_TYPE_DNSKEY: + siphash24_compress(&rr->dnskey.flags, sizeof(rr->dnskey.flags), state); + siphash24_compress(&rr->dnskey.protocol, sizeof(rr->dnskey.protocol), state); + siphash24_compress(&rr->dnskey.algorithm, sizeof(rr->dnskey.algorithm), state); + siphash24_compress(rr->dnskey.key, rr->dnskey.key_size, state); + break; + + case DNS_TYPE_RRSIG: + siphash24_compress(&rr->rrsig.type_covered, sizeof(rr->rrsig.type_covered), state); + siphash24_compress(&rr->rrsig.algorithm, sizeof(rr->rrsig.algorithm), state); + siphash24_compress(&rr->rrsig.labels, sizeof(rr->rrsig.labels), state); + siphash24_compress(&rr->rrsig.original_ttl, sizeof(rr->rrsig.original_ttl), state); + siphash24_compress(&rr->rrsig.expiration, sizeof(rr->rrsig.expiration), state); + siphash24_compress(&rr->rrsig.inception, sizeof(rr->rrsig.inception), state); + siphash24_compress(&rr->rrsig.key_tag, sizeof(rr->rrsig.key_tag), state); + dns_name_hash_func(rr->rrsig.signer, state); + siphash24_compress(rr->rrsig.signature, rr->rrsig.signature_size, state); + break; + + case DNS_TYPE_NSEC: + dns_name_hash_func(rr->nsec.next_domain_name, state); + /* FIXME: we leave out the type bitmap here. Hash + * would be better if we'd take it into account + * too. */ + break; + + case DNS_TYPE_DS: + siphash24_compress(&rr->ds.key_tag, sizeof(rr->ds.key_tag), state); + siphash24_compress(&rr->ds.algorithm, sizeof(rr->ds.algorithm), state); + siphash24_compress(&rr->ds.digest_type, sizeof(rr->ds.digest_type), state); + siphash24_compress(rr->ds.digest, rr->ds.digest_size, state); + break; + + case DNS_TYPE_NSEC3: + siphash24_compress(&rr->nsec3.algorithm, sizeof(rr->nsec3.algorithm), state); + siphash24_compress(&rr->nsec3.flags, sizeof(rr->nsec3.flags), state); + siphash24_compress(&rr->nsec3.iterations, sizeof(rr->nsec3.iterations), state); + siphash24_compress(rr->nsec3.salt, rr->nsec3.salt_size, state); + siphash24_compress(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state); + /* FIXME: We leave the bitmaps out */ + break; + + case DNS_TYPE_TLSA: + siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state); + siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state); + siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state); + siphash24_compress(rr->tlsa.data, rr->tlsa.data_size, state); + break; + + case DNS_TYPE_CAA: + siphash24_compress(&rr->caa.flags, sizeof(rr->caa.flags), state); + string_hash_func(rr->caa.tag, state); + siphash24_compress(rr->caa.value, rr->caa.value_size, state); + break; + + case DNS_TYPE_OPENPGPKEY: + default: + siphash24_compress(rr->generic.data, rr->generic.data_size, state); + break; + } +} + +static int dns_resource_record_compare_func(const DnsResourceRecord *x, const DnsResourceRecord *y) { + int r; + + r = dns_resource_key_compare_func(x->key, y->key); + if (r != 0) + return r; + + if (dns_resource_record_equal(x, y)) + return 0; + + /* We still use CMP() here, even though don't implement proper + * ordering, since the hashtable doesn't need ordering anyway. */ + return CMP(x, y); +} + +DEFINE_HASH_OPS(dns_resource_record_hash_ops, DnsResourceRecord, dns_resource_record_hash_func, dns_resource_record_compare_func); + +DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *copy = NULL; + DnsResourceRecord *t; + + assert(rr); + + copy = dns_resource_record_new(rr->key); + if (!copy) + return NULL; + + copy->ttl = rr->ttl; + copy->expiry = rr->expiry; + copy->n_skip_labels_signer = rr->n_skip_labels_signer; + copy->n_skip_labels_source = rr->n_skip_labels_source; + copy->unparseable = rr->unparseable; + + switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { + + case DNS_TYPE_SRV: + copy->srv.priority = rr->srv.priority; + copy->srv.weight = rr->srv.weight; + copy->srv.port = rr->srv.port; + copy->srv.name = strdup(rr->srv.name); + if (!copy->srv.name) + return NULL; + break; + + case DNS_TYPE_PTR: + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: + copy->ptr.name = strdup(rr->ptr.name); + if (!copy->ptr.name) + return NULL; + break; + + case DNS_TYPE_HINFO: + copy->hinfo.cpu = strdup(rr->hinfo.cpu); + if (!copy->hinfo.cpu) + return NULL; + + copy->hinfo.os = strdup(rr->hinfo.os); + if (!copy->hinfo.os) + return NULL; + break; + + case DNS_TYPE_TXT: + case DNS_TYPE_SPF: + copy->txt.items = dns_txt_item_copy(rr->txt.items); + if (!copy->txt.items) + return NULL; + break; + + case DNS_TYPE_A: + copy->a = rr->a; + break; + + case DNS_TYPE_AAAA: + copy->aaaa = rr->aaaa; + break; + + case DNS_TYPE_SOA: + copy->soa.mname = strdup(rr->soa.mname); + if (!copy->soa.mname) + return NULL; + copy->soa.rname = strdup(rr->soa.rname); + if (!copy->soa.rname) + return NULL; + copy->soa.serial = rr->soa.serial; + copy->soa.refresh = rr->soa.refresh; + copy->soa.retry = rr->soa.retry; + copy->soa.expire = rr->soa.expire; + copy->soa.minimum = rr->soa.minimum; + break; + + case DNS_TYPE_MX: + copy->mx.priority = rr->mx.priority; + copy->mx.exchange = strdup(rr->mx.exchange); + if (!copy->mx.exchange) + return NULL; + break; + + case DNS_TYPE_LOC: + copy->loc = rr->loc; + break; + + case DNS_TYPE_SSHFP: + copy->sshfp.algorithm = rr->sshfp.algorithm; + copy->sshfp.fptype = rr->sshfp.fptype; + copy->sshfp.fingerprint = memdup(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size); + if (!copy->sshfp.fingerprint) + return NULL; + copy->sshfp.fingerprint_size = rr->sshfp.fingerprint_size; + break; + + case DNS_TYPE_DNSKEY: + copy->dnskey.flags = rr->dnskey.flags; + copy->dnskey.protocol = rr->dnskey.protocol; + copy->dnskey.algorithm = rr->dnskey.algorithm; + copy->dnskey.key = memdup(rr->dnskey.key, rr->dnskey.key_size); + if (!copy->dnskey.key) + return NULL; + copy->dnskey.key_size = rr->dnskey.key_size; + break; + + case DNS_TYPE_RRSIG: + copy->rrsig.type_covered = rr->rrsig.type_covered; + copy->rrsig.algorithm = rr->rrsig.algorithm; + copy->rrsig.labels = rr->rrsig.labels; + copy->rrsig.original_ttl = rr->rrsig.original_ttl; + copy->rrsig.expiration = rr->rrsig.expiration; + copy->rrsig.inception = rr->rrsig.inception; + copy->rrsig.key_tag = rr->rrsig.key_tag; + copy->rrsig.signer = strdup(rr->rrsig.signer); + if (!copy->rrsig.signer) + return NULL; + copy->rrsig.signature = memdup(rr->rrsig.signature, rr->rrsig.signature_size); + if (!copy->rrsig.signature) + return NULL; + copy->rrsig.signature_size = rr->rrsig.signature_size; + break; + + case DNS_TYPE_NSEC: + copy->nsec.next_domain_name = strdup(rr->nsec.next_domain_name); + if (!copy->nsec.next_domain_name) + return NULL; + copy->nsec.types = bitmap_copy(rr->nsec.types); + if (!copy->nsec.types) + return NULL; + break; + + case DNS_TYPE_DS: + copy->ds.key_tag = rr->ds.key_tag; + copy->ds.algorithm = rr->ds.algorithm; + copy->ds.digest_type = rr->ds.digest_type; + copy->ds.digest = memdup(rr->ds.digest, rr->ds.digest_size); + if (!copy->ds.digest) + return NULL; + copy->ds.digest_size = rr->ds.digest_size; + break; + + case DNS_TYPE_NSEC3: + copy->nsec3.algorithm = rr->nsec3.algorithm; + copy->nsec3.flags = rr->nsec3.flags; + copy->nsec3.iterations = rr->nsec3.iterations; + copy->nsec3.salt = memdup(rr->nsec3.salt, rr->nsec3.salt_size); + if (!copy->nsec3.salt) + return NULL; + copy->nsec3.salt_size = rr->nsec3.salt_size; + copy->nsec3.next_hashed_name = memdup(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size); + if (!copy->nsec3.next_hashed_name_size) + return NULL; + copy->nsec3.next_hashed_name_size = rr->nsec3.next_hashed_name_size; + copy->nsec3.types = bitmap_copy(rr->nsec3.types); + if (!copy->nsec3.types) + return NULL; + break; + + case DNS_TYPE_TLSA: + copy->tlsa.cert_usage = rr->tlsa.cert_usage; + copy->tlsa.selector = rr->tlsa.selector; + copy->tlsa.matching_type = rr->tlsa.matching_type; + copy->tlsa.data = memdup(rr->tlsa.data, rr->tlsa.data_size); + if (!copy->tlsa.data) + return NULL; + copy->tlsa.data_size = rr->tlsa.data_size; + break; + + case DNS_TYPE_CAA: + copy->caa.flags = rr->caa.flags; + copy->caa.tag = strdup(rr->caa.tag); + if (!copy->caa.tag) + return NULL; + copy->caa.value = memdup(rr->caa.value, rr->caa.value_size); + if (!copy->caa.value) + return NULL; + copy->caa.value_size = rr->caa.value_size; + break; + + case DNS_TYPE_OPT: + default: + copy->generic.data = memdup(rr->generic.data, rr->generic.data_size); + if (!copy->generic.data) + return NULL; + copy->generic.data_size = rr->generic.data_size; + break; + } + + t = TAKE_PTR(copy); + + return t; +} + +int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl) { + DnsResourceRecord *old_rr, *new_rr; + uint32_t new_ttl; + + assert(rr); + old_rr = *rr; + + if (old_rr->key->type == DNS_TYPE_OPT) + return -EINVAL; + + new_ttl = MIN(old_rr->ttl, max_ttl); + if (new_ttl == old_rr->ttl) + return 0; + + if (old_rr->n_ref == 1) { + /* Patch in place */ + old_rr->ttl = new_ttl; + return 1; + } + + new_rr = dns_resource_record_copy(old_rr); + if (!new_rr) + return -ENOMEM; + + new_rr->ttl = new_ttl; + + dns_resource_record_unref(*rr); + *rr = new_rr; + + return 1; +} + +DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) { + DnsTxtItem *n; + + if (!i) + return NULL; + + n = i->items_next; + + free(i); + return dns_txt_item_free_all(n); +} + +bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b) { + + if (a == b) + return true; + + if (!a != !b) + return false; + + if (!a) + return true; + + if (a->length != b->length) + return false; + + if (memcmp(a->data, b->data, a->length) != 0) + return false; + + return dns_txt_item_equal(a->items_next, b->items_next); +} + +DnsTxtItem *dns_txt_item_copy(DnsTxtItem *first) { + DnsTxtItem *i, *copy = NULL, *end = NULL; + + LIST_FOREACH(items, i, first) { + DnsTxtItem *j; + + j = memdup(i, offsetof(DnsTxtItem, data) + i->length + 1); + if (!j) { + dns_txt_item_free_all(copy); + return NULL; + } + + LIST_INSERT_AFTER(items, copy, end, j); + end = j; + } + + return copy; +} + +int dns_txt_item_new_empty(DnsTxtItem **ret) { + DnsTxtItem *i; + + /* RFC 6763, section 6.1 suggests to treat + * empty TXT RRs as equivalent to a TXT record + * with a single empty string. */ + + i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */ + if (!i) + return -ENOMEM; + + *ret = i; + + return 0; +} + +static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = { + /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */ + [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5", + [DNSSEC_ALGORITHM_DH] = "DH", + [DNSSEC_ALGORITHM_DSA] = "DSA", + [DNSSEC_ALGORITHM_ECC] = "ECC", + [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1", + [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1", + [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1", + [DNSSEC_ALGORITHM_RSASHA256] = "RSASHA256", + [DNSSEC_ALGORITHM_RSASHA512] = "RSASHA512", + [DNSSEC_ALGORITHM_ECC_GOST] = "ECC-GOST", + [DNSSEC_ALGORITHM_ECDSAP256SHA256] = "ECDSAP256SHA256", + [DNSSEC_ALGORITHM_ECDSAP384SHA384] = "ECDSAP384SHA384", + [DNSSEC_ALGORITHM_ED25519] = "ED25519", + [DNSSEC_ALGORITHM_ED448] = "ED448", + [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT", + [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS", + [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm, int, 255); + +static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = { + /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */ + [DNSSEC_DIGEST_SHA1] = "SHA-1", + [DNSSEC_DIGEST_SHA256] = "SHA-256", + [DNSSEC_DIGEST_GOST_R_34_11_94] = "GOST_R_34.11-94", + [DNSSEC_DIGEST_SHA384] = "SHA-384", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest, int, 255); diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h new file mode 100644 index 00000000..291447f0 --- /dev/null +++ b/src/resolve/resolved-dns-rr.h @@ -0,0 +1,341 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "bitmap.h" +#include "dns-type.h" +#include "hashmap.h" +#include "in-addr-util.h" +#include "list.h" +#include "string-util.h" +#include "time-util.h" + +typedef struct DnsResourceKey DnsResourceKey; +typedef struct DnsResourceRecord DnsResourceRecord; +typedef struct DnsTxtItem DnsTxtItem; + +/* DNSKEY RR flags */ +#define DNSKEY_FLAG_SEP (UINT16_C(1) << 0) +#define DNSKEY_FLAG_REVOKE (UINT16_C(1) << 7) +#define DNSKEY_FLAG_ZONE_KEY (UINT16_C(1) << 8) + +/* mDNS RR flags */ +#define MDNS_RR_CACHE_FLUSH (UINT16_C(1) << 15) + +/* DNSSEC algorithm identifiers, see + * http://tools.ietf.org/html/rfc4034#appendix-A.1 and + * https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */ +enum { + DNSSEC_ALGORITHM_RSAMD5 = 1, + DNSSEC_ALGORITHM_DH, + DNSSEC_ALGORITHM_DSA, + DNSSEC_ALGORITHM_ECC, + DNSSEC_ALGORITHM_RSASHA1, + DNSSEC_ALGORITHM_DSA_NSEC3_SHA1, + DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1, + DNSSEC_ALGORITHM_RSASHA256 = 8, /* RFC 5702 */ + DNSSEC_ALGORITHM_RSASHA512 = 10, /* RFC 5702 */ + DNSSEC_ALGORITHM_ECC_GOST = 12, /* RFC 5933 */ + DNSSEC_ALGORITHM_ECDSAP256SHA256 = 13, /* RFC 6605 */ + DNSSEC_ALGORITHM_ECDSAP384SHA384 = 14, /* RFC 6605 */ + DNSSEC_ALGORITHM_ED25519 = 15, /* RFC 8080 */ + DNSSEC_ALGORITHM_ED448 = 16, /* RFC 8080 */ + DNSSEC_ALGORITHM_INDIRECT = 252, + DNSSEC_ALGORITHM_PRIVATEDNS, + DNSSEC_ALGORITHM_PRIVATEOID, + _DNSSEC_ALGORITHM_MAX_DEFINED +}; + +/* DNSSEC digest identifiers, see + * https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */ +enum { + DNSSEC_DIGEST_SHA1 = 1, + DNSSEC_DIGEST_SHA256 = 2, /* RFC 4509 */ + DNSSEC_DIGEST_GOST_R_34_11_94 = 3, /* RFC 5933 */ + DNSSEC_DIGEST_SHA384 = 4, /* RFC 6605 */ + _DNSSEC_DIGEST_MAX_DEFINED +}; + +/* DNSSEC NSEC3 hash algorithms, see + * https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */ +enum { + NSEC3_ALGORITHM_SHA1 = 1, + _NSEC3_ALGORITHM_MAX_DEFINED +}; + +struct DnsResourceKey { + unsigned n_ref; /* (unsigned -1) for const keys, see below */ + uint16_t class, type; + char *_name; /* don't access directly, use dns_resource_key_name()! */ +}; + +/* Creates a temporary resource key. This is only useful to quickly + * look up something, without allocating a full DnsResourceKey object + * for it. Note that it is not OK to take references to this kind of + * resource key object. */ +#define DNS_RESOURCE_KEY_CONST(c, t, n) \ + ((DnsResourceKey) { \ + .n_ref = (unsigned) -1, \ + .class = c, \ + .type = t, \ + ._name = (char*) n, \ + }) + +struct DnsTxtItem { + size_t length; + LIST_FIELDS(DnsTxtItem, items); + uint8_t data[]; +}; + +struct DnsResourceRecord { + unsigned n_ref; + DnsResourceKey *key; + + char *to_string; + + uint32_t ttl; + usec_t expiry; /* RRSIG signature expiry */ + + /* How many labels to strip to determine "signer" of the RRSIG (aka, the zone). -1 if not signed. */ + unsigned n_skip_labels_signer; + /* How many labels to strip to determine "synthesizing source" of this RR, i.e. the wildcard's immediate parent. -1 if not signed. */ + unsigned n_skip_labels_source; + + bool unparseable:1; + + bool wire_format_canonical:1; + void *wire_format; + size_t wire_format_size; + size_t wire_format_rdata_offset; + + union { + struct { + void *data; + size_t data_size; + } generic, opt; + + struct { + uint16_t priority; + uint16_t weight; + uint16_t port; + char *name; + } srv; + + struct { + char *name; + } ptr, ns, cname, dname; + + struct { + char *cpu; + char *os; + } hinfo; + + struct { + DnsTxtItem *items; + } txt, spf; + + struct { + struct in_addr in_addr; + } a; + + struct { + struct in6_addr in6_addr; + } aaaa; + + struct { + char *mname; + char *rname; + uint32_t serial; + uint32_t refresh; + uint32_t retry; + uint32_t expire; + uint32_t minimum; + } soa; + + struct { + uint16_t priority; + char *exchange; + } mx; + + /* https://tools.ietf.org/html/rfc1876 */ + struct { + uint8_t version; + uint8_t size; + uint8_t horiz_pre; + uint8_t vert_pre; + uint32_t latitude; + uint32_t longitude; + uint32_t altitude; + } loc; + + /* https://tools.ietf.org/html/rfc4255#section-3.1 */ + struct { + uint8_t algorithm; + uint8_t fptype; + void *fingerprint; + size_t fingerprint_size; + } sshfp; + + /* http://tools.ietf.org/html/rfc4034#section-2.1 */ + struct { + uint16_t flags; + uint8_t protocol; + uint8_t algorithm; + void* key; + size_t key_size; + } dnskey; + + /* http://tools.ietf.org/html/rfc4034#section-3.1 */ + struct { + uint16_t type_covered; + uint8_t algorithm; + uint8_t labels; + uint32_t original_ttl; + uint32_t expiration; + uint32_t inception; + uint16_t key_tag; + char *signer; + void *signature; + size_t signature_size; + } rrsig; + + /* https://tools.ietf.org/html/rfc4034#section-4.1 */ + struct { + char *next_domain_name; + Bitmap *types; + } nsec; + + /* https://tools.ietf.org/html/rfc4034#section-5.1 */ + struct { + uint16_t key_tag; + uint8_t algorithm; + uint8_t digest_type; + void *digest; + size_t digest_size; + } ds; + + struct { + uint8_t algorithm; + uint8_t flags; + uint16_t iterations; + void *salt; + size_t salt_size; + void *next_hashed_name; + size_t next_hashed_name_size; + Bitmap *types; + } nsec3; + + /* https://tools.ietf.org/html/draft-ietf-dane-protocol-23 */ + struct { + uint8_t cert_usage; + uint8_t selector; + uint8_t matching_type; + void *data; + size_t data_size; + } tlsa; + + /* https://tools.ietf.org/html/rfc6844 */ + struct { + uint8_t flags; + char *tag; + void *value; + size_t value_size; + } caa; + }; +}; + +static inline const void* DNS_RESOURCE_RECORD_RDATA(const DnsResourceRecord *rr) { + if (!rr) + return NULL; + + if (!rr->wire_format) + return NULL; + + assert(rr->wire_format_rdata_offset <= rr->wire_format_size); + return (uint8_t*) rr->wire_format + rr->wire_format_rdata_offset; +} + +static inline size_t DNS_RESOURCE_RECORD_RDATA_SIZE(const DnsResourceRecord *rr) { + if (!rr) + return 0; + if (!rr->wire_format) + return 0; + + assert(rr->wire_format_rdata_offset <= rr->wire_format_size); + return rr->wire_format_size - rr->wire_format_rdata_offset; +} + +static inline uint8_t DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(const DnsResourceRecord *rr) { + assert(rr); + assert(rr->key->type == DNS_TYPE_OPT); + + return ((rr->ttl >> 16) & 0xFF) == 0; +} + +DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name); +DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname); +int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name); +DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name); +DnsResourceKey* dns_resource_key_ref(DnsResourceKey *key); +DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key); +const char* dns_resource_key_name(const DnsResourceKey *key); +bool dns_resource_key_is_address(const DnsResourceKey *key); +bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey *key); +int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b); +int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain); +int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain); +int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa); + +/* _DNS_{CLASS,TYPE}_STRING_MAX include one byte for NUL, which we use for space instead below. + * DNS_HOSTNAME_MAX does not include the NUL byte, so we need to add 1. */ +#define DNS_RESOURCE_KEY_STRING_MAX (_DNS_CLASS_STRING_MAX + _DNS_TYPE_STRING_MAX + DNS_HOSTNAME_MAX + 1) + +char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size); +ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out); + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref); + +static inline bool dns_key_is_shared(const DnsResourceKey *key) { + return IN_SET(key->type, DNS_TYPE_PTR); +} + +bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b); + +DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key); +DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name); +DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr); +DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr); +int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name); +int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name); +int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b); +int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b); + +const char* dns_resource_record_to_string(DnsResourceRecord *rr); +DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr); +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref); + +int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical); + +int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret); +int dns_resource_record_source(DnsResourceRecord *rr, const char **ret); +int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone); +int dns_resource_record_is_synthetic(DnsResourceRecord *rr); + +int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl); + +DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i); +bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b); +DnsTxtItem *dns_txt_item_copy(DnsTxtItem *i); +int dns_txt_item_new_empty(DnsTxtItem **ret); + +void dns_resource_record_hash_func(const DnsResourceRecord *i, struct siphash *state); + +extern const struct hash_ops dns_resource_key_hash_ops; +extern const struct hash_ops dns_resource_record_hash_ops; + +int dnssec_algorithm_to_string_alloc(int i, char **ret); +int dnssec_algorithm_from_string(const char *s) _pure_; + +int dnssec_digest_to_string_alloc(int i, char **ret); +int dnssec_digest_from_string(const char *s) _pure_; diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c new file mode 100644 index 00000000..691f0794 --- /dev/null +++ b/src/resolve/resolved-dns-scope.c @@ -0,0 +1,1461 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "af-list.h" +#include "alloc-util.h" +#include "dns-domain.h" +#include "fd-util.h" +#include "hostname-util.h" +#include "missing_network.h" +#include "random-util.h" +#include "resolved-dnssd.h" +#include "resolved-dns-scope.h" +#include "resolved-dns-zone.h" +#include "resolved-llmnr.h" +#include "resolved-mdns.h" +#include "socket-util.h" +#include "strv.h" + +#define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC) +#define MULTICAST_RATELIMIT_BURST 1000 + +/* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */ +#define MULTICAST_RESEND_TIMEOUT_MIN_USEC (100 * USEC_PER_MSEC) +#define MULTICAST_RESEND_TIMEOUT_MAX_USEC (1 * USEC_PER_SEC) + +int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) { + DnsScope *s; + + assert(m); + assert(ret); + + s = new(DnsScope, 1); + if (!s) + return -ENOMEM; + + *s = (DnsScope) { + .manager = m, + .link = l, + .protocol = protocol, + .family = family, + .resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC, + }; + + if (protocol == DNS_PROTOCOL_DNS) { + /* Copy DNSSEC mode from the link if it is set there, + * otherwise take the manager's DNSSEC mode. Note that + * we copy this only at scope creation time, and do + * not update it from the on, even if the setting + * changes. */ + + if (l) { + s->dnssec_mode = link_get_dnssec_mode(l); + s->dns_over_tls_mode = link_get_dns_over_tls_mode(l); + } else { + s->dnssec_mode = manager_get_dnssec_mode(m); + s->dns_over_tls_mode = manager_get_dns_over_tls_mode(m); + } + + } else { + s->dnssec_mode = DNSSEC_NO; + s->dns_over_tls_mode = DNS_OVER_TLS_NO; + } + + LIST_PREPEND(scopes, m->dns_scopes, s); + + dns_scope_llmnr_membership(s, true); + dns_scope_mdns_membership(s, true); + + log_debug("New scope on link %s, protocol %s, family %s", l ? l->ifname : "*", dns_protocol_to_string(protocol), family == AF_UNSPEC ? "*" : af_to_name(family)); + + /* Enforce ratelimiting for the multicast protocols */ + s->ratelimit = (RateLimit) { MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST }; + + *ret = s; + return 0; +} + +static void dns_scope_abort_transactions(DnsScope *s) { + assert(s); + + while (s->transactions) { + DnsTransaction *t = s->transactions; + + /* Abort the transaction, but make sure it is not + * freed while we still look at it */ + + t->block_gc++; + if (DNS_TRANSACTION_IS_LIVE(t->state)) + dns_transaction_complete(t, DNS_TRANSACTION_ABORTED); + t->block_gc--; + + dns_transaction_free(t); + } +} + +DnsScope* dns_scope_free(DnsScope *s) { + if (!s) + return NULL; + + log_debug("Removing scope on link %s, protocol %s, family %s", s->link ? s->link->ifname : "*", dns_protocol_to_string(s->protocol), s->family == AF_UNSPEC ? "*" : af_to_name(s->family)); + + dns_scope_llmnr_membership(s, false); + dns_scope_mdns_membership(s, false); + dns_scope_abort_transactions(s); + + while (s->query_candidates) + dns_query_candidate_free(s->query_candidates); + + hashmap_free(s->transactions_by_key); + + ordered_hashmap_free_with_destructor(s->conflict_queue, dns_resource_record_unref); + sd_event_source_unref(s->conflict_event_source); + + sd_event_source_unref(s->announce_event_source); + + dns_cache_flush(&s->cache); + dns_zone_flush(&s->zone); + + LIST_REMOVE(scopes, s->manager->dns_scopes, s); + return mfree(s); +} + +DnsServer *dns_scope_get_dns_server(DnsScope *s) { + assert(s); + + if (s->protocol != DNS_PROTOCOL_DNS) + return NULL; + + if (s->link) + return link_get_dns_server(s->link); + else + return manager_get_dns_server(s->manager); +} + +unsigned dns_scope_get_n_dns_servers(DnsScope *s) { + unsigned n = 0; + DnsServer *i; + + assert(s); + + if (s->protocol != DNS_PROTOCOL_DNS) + return 0; + + if (s->link) + i = s->link->dns_servers; + else + i = s->manager->dns_servers; + + for (; i; i = i->servers_next) + n++; + + return n; +} + +void dns_scope_next_dns_server(DnsScope *s) { + assert(s); + + if (s->protocol != DNS_PROTOCOL_DNS) + return; + + if (s->link) + link_next_dns_server(s->link); + else + manager_next_dns_server(s->manager); +} + +void dns_scope_packet_received(DnsScope *s, usec_t rtt) { + assert(s); + + if (rtt <= s->max_rtt) + return; + + s->max_rtt = rtt; + s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC); +} + +void dns_scope_packet_lost(DnsScope *s, usec_t usec) { + assert(s); + + if (s->resend_timeout <= usec) + s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC); +} + +static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) { + union in_addr_union addr; + int ifindex = 0, r; + int family; + uint32_t mtu; + + assert(s); + assert(p); + assert(p->protocol == s->protocol); + + if (s->link) { + mtu = s->link->mtu; + ifindex = s->link->ifindex; + } else + mtu = manager_find_mtu(s->manager); + + switch (s->protocol) { + + case DNS_PROTOCOL_DNS: + assert(fd >= 0); + + if (DNS_PACKET_QDCOUNT(p) > 1) + return -EOPNOTSUPP; + + if (p->size > DNS_PACKET_UNICAST_SIZE_MAX) + return -EMSGSIZE; + + if (p->size + UDP_PACKET_HEADER_SIZE > mtu) + return -EMSGSIZE; + + r = manager_write(s->manager, fd, p); + if (r < 0) + return r; + + break; + + case DNS_PROTOCOL_LLMNR: + assert(fd < 0); + + if (DNS_PACKET_QDCOUNT(p) > 1) + return -EOPNOTSUPP; + + if (!ratelimit_below(&s->ratelimit)) + return -EBUSY; + + family = s->family; + + if (family == AF_INET) { + addr.in = LLMNR_MULTICAST_IPV4_ADDRESS; + fd = manager_llmnr_ipv4_udp_fd(s->manager); + } else if (family == AF_INET6) { + addr.in6 = LLMNR_MULTICAST_IPV6_ADDRESS; + fd = manager_llmnr_ipv6_udp_fd(s->manager); + } else + return -EAFNOSUPPORT; + if (fd < 0) + return fd; + + r = manager_send(s->manager, fd, ifindex, family, &addr, LLMNR_PORT, NULL, p); + if (r < 0) + return r; + + break; + + case DNS_PROTOCOL_MDNS: + assert(fd < 0); + + if (!ratelimit_below(&s->ratelimit)) + return -EBUSY; + + family = s->family; + + if (family == AF_INET) { + addr.in = MDNS_MULTICAST_IPV4_ADDRESS; + fd = manager_mdns_ipv4_fd(s->manager); + } else if (family == AF_INET6) { + addr.in6 = MDNS_MULTICAST_IPV6_ADDRESS; + fd = manager_mdns_ipv6_fd(s->manager); + } else + return -EAFNOSUPPORT; + if (fd < 0) + return fd; + + r = manager_send(s->manager, fd, ifindex, family, &addr, MDNS_PORT, NULL, p); + if (r < 0) + return r; + + break; + + default: + return -EAFNOSUPPORT; + } + + return 1; +} + +int dns_scope_emit_udp(DnsScope *s, int fd, DnsPacket *p) { + int r; + + assert(s); + assert(p); + assert(p->protocol == s->protocol); + assert((s->protocol == DNS_PROTOCOL_DNS) == (fd >= 0)); + + do { + /* If there are multiple linked packets, set the TC bit in all but the last of them */ + if (p->more) { + assert(p->protocol == DNS_PROTOCOL_MDNS); + dns_packet_set_flags(p, true, true); + } + + r = dns_scope_emit_one(s, fd, p); + if (r < 0) + return r; + + p = p->more; + } while (p); + + return 0; +} + +static int dns_scope_socket( + DnsScope *s, + int type, + int family, + const union in_addr_union *address, + DnsServer *server, + uint16_t port, + union sockaddr_union *ret_socket_address) { + + _cleanup_close_ int fd = -1; + union sockaddr_union sa; + socklen_t salen; + int r, ifindex; + + assert(s); + + if (server) { + assert(family == AF_UNSPEC); + assert(!address); + + ifindex = dns_server_ifindex(server); + + switch (server->family) { + case AF_INET: + sa = (union sockaddr_union) { + .in.sin_family = server->family, + .in.sin_port = htobe16(port), + .in.sin_addr = server->address.in, + }; + salen = sizeof(sa.in); + break; + case AF_INET6: + sa = (union sockaddr_union) { + .in6.sin6_family = server->family, + .in6.sin6_port = htobe16(port), + .in6.sin6_addr = server->address.in6, + .in6.sin6_scope_id = ifindex, + }; + salen = sizeof(sa.in6); + break; + default: + return -EAFNOSUPPORT; + } + } else { + assert(family != AF_UNSPEC); + assert(address); + + ifindex = s->link ? s->link->ifindex : 0; + + switch (family) { + case AF_INET: + sa = (union sockaddr_union) { + .in.sin_family = family, + .in.sin_port = htobe16(port), + .in.sin_addr = address->in, + }; + salen = sizeof(sa.in); + break; + case AF_INET6: + sa = (union sockaddr_union) { + .in6.sin6_family = family, + .in6.sin6_port = htobe16(port), + .in6.sin6_addr = address->in6, + .in6.sin6_scope_id = ifindex, + }; + salen = sizeof(sa.in6); + break; + default: + return -EAFNOSUPPORT; + } + } + + fd = socket(sa.sa.sa_family, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return -errno; + + if (type == SOCK_STREAM) { + r = setsockopt_int(fd, IPPROTO_TCP, TCP_NODELAY, true); + if (r < 0) + return r; + } + + if (s->link) { + be32_t ifindex_be = htobe32(ifindex); + + if (sa.sa.sa_family == AF_INET) { + r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)); + if (r < 0) + return -errno; + } else if (sa.sa.sa_family == AF_INET6) { + r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)); + if (r < 0) + return -errno; + } + } + + if (s->protocol == DNS_PROTOCOL_LLMNR) { + /* RFC 4795, section 2.5 requires the TTL to be set to 1 */ + + if (sa.sa.sa_family == AF_INET) { + r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true); + if (r < 0) + return r; + } else if (sa.sa.sa_family == AF_INET6) { + r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, true); + if (r < 0) + return r; + } + } + + if (type == SOCK_DGRAM) { + /* Set IP_RECVERR or IPV6_RECVERR to get ICMP error feedback. See discussion in #10345. */ + + if (sa.sa.sa_family == AF_INET) { + r = setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, true); + if (r < 0) + return r; + + r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true); + if (r < 0) + return r; + + } else if (sa.sa.sa_family == AF_INET6) { + r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVERR, true); + if (r < 0) + return r; + + r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true); + if (r < 0) + return r; + } + } + + if (ret_socket_address) + *ret_socket_address = sa; + else { + r = connect(fd, &sa.sa, salen); + if (r < 0 && errno != EINPROGRESS) + return -errno; + } + + return TAKE_FD(fd); +} + +int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port) { + return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, server, port, NULL); +} + +int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port, union sockaddr_union *ret_socket_address) { + /* If ret_socket_address is not NULL, the caller is responsible + * for calling connect() or sendmsg(). This is required by TCP + * Fast Open, to be able to send the initial SYN packet along + * with the first data packet. */ + return dns_scope_socket(s, SOCK_STREAM, family, address, server, port, ret_socket_address); +} + +static DnsScopeMatch accept_link_local_reverse_lookups(const char *domain) { + assert(domain); + + if (dns_name_endswith(domain, "254.169.in-addr.arpa") > 0) + return DNS_SCOPE_YES_BASE + 4; /* 4 labels match */ + + if (dns_name_endswith(domain, "8.e.f.ip6.arpa") > 0 || + dns_name_endswith(domain, "9.e.f.ip6.arpa") > 0 || + dns_name_endswith(domain, "a.e.f.ip6.arpa") > 0 || + dns_name_endswith(domain, "b.e.f.ip6.arpa") > 0) + return DNS_SCOPE_YES_BASE + 5; /* 5 labels match */ + + return _DNS_SCOPE_MATCH_INVALID; +} + +DnsScopeMatch dns_scope_good_domain( + DnsScope *s, + int ifindex, + uint64_t flags, + const char *domain) { + + DnsSearchDomain *d; + + /* This returns the following return values: + * + * DNS_SCOPE_NO → This scope is not suitable for lookups of this domain, at all + * DNS_SCOPE_MAYBE → This scope is suitable, but only if nothing else wants it + * DNS_SCOPE_YES_BASE+n → This scope is suitable, and 'n' suffix labels match + * + * (The idea is that the caller will only use the scopes with the longest 'n' returned. If no scopes return + * DNS_SCOPE_YES_BASE+n, then it should use those which returned DNS_SCOPE_MAYBE. It should never use those + * which returned DNS_SCOPE_NO.) + */ + + assert(s); + assert(domain); + + /* Checks if the specified domain is something to look up on + * this scope. Note that this accepts non-qualified hostnames, + * i.e. those without any search path prefixed yet. */ + + if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex)) + return DNS_SCOPE_NO; + + if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0) + return DNS_SCOPE_NO; + + /* Never resolve any loopback hostname or IP address via DNS, + * LLMNR or mDNS. Instead, always rely on synthesized RRs for + * these. */ + if (is_localhost(domain) || + dns_name_endswith(domain, "127.in-addr.arpa") > 0 || + dns_name_equal(domain, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) + return DNS_SCOPE_NO; + + /* Never respond to some of the domains listed in RFC6303 */ + if (dns_name_endswith(domain, "0.in-addr.arpa") > 0 || + dns_name_equal(domain, "255.255.255.255.in-addr.arpa") > 0 || + dns_name_equal(domain, "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) + return DNS_SCOPE_NO; + + /* Never respond to some of the domains listed in RFC6761 */ + if (dns_name_endswith(domain, "invalid") > 0) + return DNS_SCOPE_NO; + + switch (s->protocol) { + + case DNS_PROTOCOL_DNS: { + bool has_search_domains = false; + int n_best = -1; + + /* Never route things to scopes that lack DNS servers */ + if (!dns_scope_get_dns_server(s)) + return DNS_SCOPE_NO; + + /* Always honour search domains for routing queries, except if this scope lacks DNS servers. Note that + * we return DNS_SCOPE_YES here, rather than just DNS_SCOPE_MAYBE, which means other wildcard scopes + * won't be considered anymore. */ + LIST_FOREACH(domains, d, dns_scope_get_search_domains(s)) { + + if (!d->route_only && !dns_name_is_root(d->name)) + has_search_domains = true; + + if (dns_name_endswith(domain, d->name) > 0) { + int c; + + c = dns_name_count_labels(d->name); + if (c < 0) + continue; + + if (c > n_best) + n_best = c; + } + } + + /* If there's a true search domain defined for this scope, and the query is single-label, + * then let's resolve things here, prefereably. Note that LLMNR considers itself + * authoritative for single-label names too, at the same preference, see below. */ + if (has_search_domains && dns_name_is_single_label(domain)) + return DNS_SCOPE_YES_BASE + 1; + + /* Let's return the number of labels in the best matching result */ + if (n_best >= 0) { + assert(n_best <= DNS_SCOPE_YES_END - DNS_SCOPE_YES_BASE); + return DNS_SCOPE_YES_BASE + n_best; + } + + /* See if this scope is suitable as default route. */ + if (!dns_scope_is_default_route(s)) + return DNS_SCOPE_NO; + + /* Exclude link-local IP ranges */ + if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 && + dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 && + dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 && + dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 && + dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0 && + /* If networks use .local in their private setups, they are supposed to also add .local to their search + * domains, which we already checked above. Otherwise, we consider .local specific to mDNS and won't + * send such queries ordinary DNS servers. */ + dns_name_endswith(domain, "local") == 0) + return DNS_SCOPE_MAYBE; + + return DNS_SCOPE_NO; + } + + case DNS_PROTOCOL_MDNS: { + DnsScopeMatch m; + + m = accept_link_local_reverse_lookups(domain); + if (m >= 0) + return m; + + if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) || + (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0)) + return DNS_SCOPE_MAYBE; + + if ((dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */ + dns_name_equal(domain, "local") == 0 && /* but not the single-label "local" name itself */ + manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via mDNS */ + return DNS_SCOPE_YES_BASE + 1; /* Return +1, as the top-level .local domain matches, i.e. one label */ + + return DNS_SCOPE_NO; + } + + case DNS_PROTOCOL_LLMNR: { + DnsScopeMatch m; + + m = accept_link_local_reverse_lookups(domain); + if (m >= 0) + return m; + + if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) || + (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0)) + return DNS_SCOPE_MAYBE; + + if ((dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */ + !is_gateway_hostname(domain) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */ + manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */ + return DNS_SCOPE_YES_BASE + 1; /* Return +1, as we consider ourselves authoritative + * for single-label names, i.e. one label. This is + * particular relevant as it means a "." route on some + * other scope won't pull all traffic away from + * us. (If people actually want to pull traffic away + * from us they should turn off LLMNR on the + * link). Note that unicast DNS scopes with search + * domains also consider themselves authoritative for + * single-label domains, at the same preference (see + * above). */ + + return DNS_SCOPE_NO; + } + + default: + assert_not_reached("Unknown scope protocol"); + } +} + +bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key) { + int key_family; + + assert(s); + assert(key); + + /* Check if it makes sense to resolve the specified key on + * this scope. Note that this call assumes as fully qualified + * name, i.e. the search suffixes already appended. */ + + if (key->class != DNS_CLASS_IN) + return false; + + if (s->protocol == DNS_PROTOCOL_DNS) { + + /* On classic DNS, looking up non-address RRs is always + * fine. (Specifically, we want to permit looking up + * DNSKEY and DS records on the root and top-level + * domains.) */ + if (!dns_resource_key_is_address(key)) + return true; + + /* However, we refuse to look up A and AAAA RRs on the + * root and single-label domains, under the assumption + * that those should be resolved via LLMNR or search + * path only, and should not be leaked onto the + * internet. */ + return !(dns_name_is_single_label(dns_resource_key_name(key)) || + dns_name_is_root(dns_resource_key_name(key))); + } + + /* On mDNS and LLMNR, send A and AAAA queries only on the + * respective scopes */ + + key_family = dns_type_to_af(key->type); + if (key_family < 0) + return true; + + return key_family == s->family; +} + +static int dns_scope_multicast_membership(DnsScope *s, bool b, struct in_addr in, struct in6_addr in6) { + int fd; + + assert(s); + assert(s->link); + + if (s->family == AF_INET) { + struct ip_mreqn mreqn = { + .imr_multiaddr = in, + .imr_ifindex = s->link->ifindex, + }; + + if (s->protocol == DNS_PROTOCOL_LLMNR) + fd = manager_llmnr_ipv4_udp_fd(s->manager); + else + fd = manager_mdns_ipv4_fd(s->manager); + + if (fd < 0) + return fd; + + /* Always first try to drop membership before we add + * one. This is necessary on some devices, such as + * veth. */ + if (b) + (void) setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)); + + if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0) + return -errno; + + } else if (s->family == AF_INET6) { + struct ipv6_mreq mreq = { + .ipv6mr_multiaddr = in6, + .ipv6mr_interface = s->link->ifindex, + }; + + if (s->protocol == DNS_PROTOCOL_LLMNR) + fd = manager_llmnr_ipv6_udp_fd(s->manager); + else + fd = manager_mdns_ipv6_fd(s->manager); + + if (fd < 0) + return fd; + + if (b) + (void) setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); + + if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) + return -errno; + } else + return -EAFNOSUPPORT; + + return 0; +} + +int dns_scope_llmnr_membership(DnsScope *s, bool b) { + assert(s); + + if (s->protocol != DNS_PROTOCOL_LLMNR) + return 0; + + return dns_scope_multicast_membership(s, b, LLMNR_MULTICAST_IPV4_ADDRESS, LLMNR_MULTICAST_IPV6_ADDRESS); +} + +int dns_scope_mdns_membership(DnsScope *s, bool b) { + assert(s); + + if (s->protocol != DNS_PROTOCOL_MDNS) + return 0; + + return dns_scope_multicast_membership(s, b, MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_IPV6_ADDRESS); +} + +int dns_scope_make_reply_packet( + DnsScope *s, + uint16_t id, + int rcode, + DnsQuestion *q, + DnsAnswer *answer, + DnsAnswer *soa, + bool tentative, + DnsPacket **ret) { + + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + int r; + + assert(s); + assert(ret); + + if (dns_question_isempty(q) && + dns_answer_isempty(answer) && + dns_answer_isempty(soa)) + return -EINVAL; + + r = dns_packet_new(&p, s->protocol, 0, DNS_PACKET_SIZE_MAX); + if (r < 0) + return r; + + DNS_PACKET_HEADER(p)->id = id; + DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS( + 1 /* qr */, + 0 /* opcode */, + 0 /* c */, + 0 /* tc */, + tentative, + 0 /* (ra) */, + 0 /* (ad) */, + 0 /* (cd) */, + rcode)); + + r = dns_packet_append_question(p, q); + if (r < 0) + return r; + DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(q)); + + r = dns_packet_append_answer(p, answer); + if (r < 0) + return r; + DNS_PACKET_HEADER(p)->ancount = htobe16(dns_answer_size(answer)); + + r = dns_packet_append_answer(p, soa); + if (r < 0) + return r; + DNS_PACKET_HEADER(p)->arcount = htobe16(dns_answer_size(soa)); + + *ret = TAKE_PTR(p); + + return 0; +} + +static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) { + DnsResourceRecord *rr; + DnsResourceKey *key; + + assert(s); + assert(p); + + DNS_QUESTION_FOREACH(key, p->question) + dns_zone_verify_conflicts(&s->zone, key); + + DNS_ANSWER_FOREACH(rr, p->answer) + dns_zone_verify_conflicts(&s->zone, rr->key); +} + +void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL; + _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL; + DnsResourceKey *key = NULL; + bool tentative = false; + int r; + + assert(s); + assert(p); + + if (p->protocol != DNS_PROTOCOL_LLMNR) + return; + + if (p->ipproto == IPPROTO_UDP) { + /* Don't accept UDP queries directed to anything but + * the LLMNR multicast addresses. See RFC 4795, + * section 2.5. */ + + if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS)) + return; + + if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS)) + return; + } + + r = dns_packet_extract(p); + if (r < 0) { + log_debug_errno(r, "Failed to extract resource records from incoming packet: %m"); + return; + } + + if (DNS_PACKET_LLMNR_C(p)) { + /* Somebody notified us about a possible conflict */ + dns_scope_verify_conflicts(s, p); + return; + } + + assert(dns_question_size(p->question) == 1); + key = p->question->keys[0]; + + r = dns_zone_lookup(&s->zone, key, 0, &answer, &soa, &tentative); + if (r < 0) { + log_debug_errno(r, "Failed to lookup key: %m"); + return; + } + if (r == 0) + return; + + if (answer) + dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0); + + r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply); + if (r < 0) { + log_debug_errno(r, "Failed to build reply packet: %m"); + return; + } + + if (stream) { + r = dns_stream_write_packet(stream, reply); + if (r < 0) { + log_debug_errno(r, "Failed to enqueue reply packet: %m"); + return; + } + + /* Let's take an extra reference on this stream, so that it stays around after returning. The reference + * will be dangling until the stream is disconnected, and the default completion handler of the stream + * will then unref the stream and destroy it */ + if (DNS_STREAM_QUEUED(stream)) + dns_stream_ref(stream); + } else { + int fd; + + if (!ratelimit_below(&s->ratelimit)) + return; + + if (p->family == AF_INET) + fd = manager_llmnr_ipv4_udp_fd(s->manager); + else if (p->family == AF_INET6) + fd = manager_llmnr_ipv6_udp_fd(s->manager); + else { + log_debug("Unknown protocol"); + return; + } + if (fd < 0) { + log_debug_errno(fd, "Failed to get reply socket: %m"); + return; + } + + /* Note that we always immediately reply to all LLMNR + * requests, and do not wait any time, since we + * verified uniqueness for all records. Also see RFC + * 4795, Section 2.7 */ + + r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, NULL, reply); + if (r < 0) { + log_debug_errno(r, "Failed to send reply packet: %m"); + return; + } + } +} + +DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) { + DnsTransaction *t; + + assert(scope); + assert(key); + + /* Try to find an ongoing transaction that is a equal to the + * specified question */ + t = hashmap_get(scope->transactions_by_key, key); + if (!t) + return NULL; + + /* Refuse reusing transactions that completed based on cached + * data instead of a real packet, if that's requested. */ + if (!cache_ok && + IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_RCODE_FAILURE) && + t->answer_source != DNS_TRANSACTION_NETWORK) + return NULL; + + return t; +} + +static int dns_scope_make_conflict_packet( + DnsScope *s, + DnsResourceRecord *rr, + DnsPacket **ret) { + + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + int r; + + assert(s); + assert(rr); + assert(ret); + + r = dns_packet_new(&p, s->protocol, 0, DNS_PACKET_SIZE_MAX); + if (r < 0) + return r; + + DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS( + 0 /* qr */, + 0 /* opcode */, + 1 /* conflict */, + 0 /* tc */, + 0 /* t */, + 0 /* (ra) */, + 0 /* (ad) */, + 0 /* (cd) */, + 0)); + + /* For mDNS, the transaction ID should always be 0 */ + if (s->protocol != DNS_PROTOCOL_MDNS) + random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t)); + + DNS_PACKET_HEADER(p)->qdcount = htobe16(1); + DNS_PACKET_HEADER(p)->arcount = htobe16(1); + + r = dns_packet_append_key(p, rr->key, 0, NULL); + if (r < 0) + return r; + + r = dns_packet_append_rr(p, rr, 0, NULL, NULL); + if (r < 0) + return r; + + *ret = TAKE_PTR(p); + + return 0; +} + +static int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata) { + DnsScope *scope = userdata; + int r; + + assert(es); + assert(scope); + + scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source); + + for (;;) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + + key = ordered_hashmap_first_key(scope->conflict_queue); + if (!key) + break; + + rr = ordered_hashmap_remove(scope->conflict_queue, key); + assert(rr); + + r = dns_scope_make_conflict_packet(scope, rr, &p); + if (r < 0) { + log_error_errno(r, "Failed to make conflict packet: %m"); + return 0; + } + + r = dns_scope_emit_udp(scope, -1, p); + if (r < 0) + log_debug_errno(r, "Failed to send conflict packet: %m"); + } + + return 0; +} + +int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) { + usec_t jitter; + int r; + + assert(scope); + assert(rr); + + /* We don't send these queries immediately. Instead, we queue + * them, and send them after some jitter delay. */ + r = ordered_hashmap_ensure_allocated(&scope->conflict_queue, &dns_resource_key_hash_ops); + if (r < 0) { + log_oom(); + return r; + } + + /* We only place one RR per key in the conflict + * messages, not all of them. That should be enough to + * indicate where there might be a conflict */ + r = ordered_hashmap_put(scope->conflict_queue, rr->key, rr); + if (IN_SET(r, 0, -EEXIST)) + return 0; + if (r < 0) + return log_debug_errno(r, "Failed to queue conflicting RR: %m"); + + dns_resource_key_ref(rr->key); + dns_resource_record_ref(rr); + + if (scope->conflict_event_source) + return 0; + + random_bytes(&jitter, sizeof(jitter)); + jitter %= LLMNR_JITTER_INTERVAL_USEC; + + r = sd_event_add_time(scope->manager->event, + &scope->conflict_event_source, + clock_boottime_or_monotonic(), + now(clock_boottime_or_monotonic()) + jitter, + LLMNR_JITTER_INTERVAL_USEC, + on_conflict_dispatch, scope); + if (r < 0) + return log_debug_errno(r, "Failed to add conflict dispatch event: %m"); + + (void) sd_event_source_set_description(scope->conflict_event_source, "scope-conflict"); + + return 0; +} + +void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) { + DnsResourceRecord *rr; + int r; + + assert(scope); + assert(p); + + if (!IN_SET(p->protocol, DNS_PROTOCOL_LLMNR, DNS_PROTOCOL_MDNS)) + return; + + if (DNS_PACKET_RRCOUNT(p) <= 0) + return; + + if (p->protocol == DNS_PROTOCOL_LLMNR) { + if (DNS_PACKET_LLMNR_C(p) != 0) + return; + + if (DNS_PACKET_LLMNR_T(p) != 0) + return; + } + + if (manager_our_packet(scope->manager, p)) + return; + + r = dns_packet_extract(p); + if (r < 0) { + log_debug_errno(r, "Failed to extract packet: %m"); + return; + } + + log_debug("Checking for conflicts..."); + + DNS_ANSWER_FOREACH(rr, p->answer) { + /* No conflict if it is DNS-SD RR used for service enumeration. */ + if (dns_resource_key_is_dnssd_ptr(rr->key)) + continue; + + /* Check for conflicts against the local zone. If we + * found one, we won't check any further */ + r = dns_zone_check_conflicts(&scope->zone, rr); + if (r != 0) + continue; + + /* Check for conflicts against the local cache. If so, + * send out an advisory query, to inform everybody */ + r = dns_cache_check_conflicts(&scope->cache, rr, p->family, &p->sender); + if (r <= 0) + continue; + + dns_scope_notify_conflict(scope, rr); + } +} + +void dns_scope_dump(DnsScope *s, FILE *f) { + assert(s); + + if (!f) + f = stdout; + + fputs("[Scope protocol=", f); + fputs(dns_protocol_to_string(s->protocol), f); + + if (s->link) { + fputs(" interface=", f); + fputs(s->link->ifname, f); + } + + if (s->family != AF_UNSPEC) { + fputs(" family=", f); + fputs(af_to_name(s->family), f); + } + + fputs("]\n", f); + + if (!dns_zone_is_empty(&s->zone)) { + fputs("ZONE:\n", f); + dns_zone_dump(&s->zone, f); + } + + if (!dns_cache_is_empty(&s->cache)) { + fputs("CACHE:\n", f); + dns_cache_dump(&s->cache, f); + } +} + +DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) { + assert(s); + + if (s->protocol != DNS_PROTOCOL_DNS) + return NULL; + + if (s->link) + return s->link->search_domains; + + return s->manager->search_domains; +} + +bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) { + assert(s); + + if (s->protocol != DNS_PROTOCOL_DNS) + return false; + + return dns_name_is_single_label(name); +} + +bool dns_scope_network_good(DnsScope *s) { + /* Checks whether the network is in good state for lookups on this scope. For mDNS/LLMNR/Classic DNS scopes + * bound to links this is easy, as they don't even exist if the link isn't in a suitable state. For the global + * DNS scope we check whether there are any links that are up and have an address. */ + + if (s->link) + return true; + + return manager_routable(s->manager, AF_UNSPEC); +} + +int dns_scope_ifindex(DnsScope *s) { + assert(s); + + if (s->link) + return s->link->ifindex; + + return 0; +} + +static int on_announcement_timeout(sd_event_source *s, usec_t usec, void *userdata) { + DnsScope *scope = userdata; + + assert(s); + + scope->announce_event_source = sd_event_source_unref(scope->announce_event_source); + + (void) dns_scope_announce(scope, false); + return 0; +} + +int dns_scope_announce(DnsScope *scope, bool goodbye) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + _cleanup_set_free_ Set *types = NULL; + DnsTransaction *t; + DnsZoneItem *z, *i; + unsigned size = 0; + Iterator iterator; + char *service_type; + int r; + + if (!scope) + return 0; + + if (scope->protocol != DNS_PROTOCOL_MDNS) + return 0; + + /* Check if we're done with probing. */ + LIST_FOREACH(transactions_by_scope, t, scope->transactions) + if (DNS_TRANSACTION_IS_LIVE(t->state)) + return 0; + + /* Check if there're services pending conflict resolution. */ + if (manager_next_dnssd_names(scope->manager)) + return 0; /* we reach this point only if changing hostname didn't help */ + + /* Calculate answer's size. */ + HASHMAP_FOREACH(z, scope->zone.by_key, iterator) { + if (z->state != DNS_ZONE_ITEM_ESTABLISHED) + continue; + + if (z->rr->key->type == DNS_TYPE_PTR && + !dns_zone_contains_name(&scope->zone, z->rr->ptr.name)) { + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + + log_debug("Skip PTR RR <%s> since its counterparts seem to be withdrawn", dns_resource_key_to_string(z->rr->key, key_str, sizeof key_str)); + z->state = DNS_ZONE_ITEM_WITHDRAWN; + continue; + } + + /* Collect service types for _services._dns-sd._udp.local RRs in a set */ + if (!scope->announced && + dns_resource_key_is_dnssd_ptr(z->rr->key)) { + if (!set_contains(types, dns_resource_key_name(z->rr->key))) { + r = set_ensure_allocated(&types, &dns_name_hash_ops); + if (r < 0) + return log_debug_errno(r, "Failed to allocate set: %m"); + + r = set_put(types, dns_resource_key_name(z->rr->key)); + if (r < 0) + return log_debug_errno(r, "Failed to add item to set: %m"); + } + } + + LIST_FOREACH(by_key, i, z) + size++; + } + + answer = dns_answer_new(size + set_size(types)); + if (!answer) + return log_oom(); + + /* Second iteration, actually add RRs to the answer. */ + HASHMAP_FOREACH(z, scope->zone.by_key, iterator) + LIST_FOREACH (by_key, i, z) { + DnsAnswerFlags flags; + + if (i->state != DNS_ZONE_ITEM_ESTABLISHED) + continue; + + if (dns_resource_key_is_dnssd_ptr(i->rr->key)) + flags = goodbye ? DNS_ANSWER_GOODBYE : 0; + else + flags = goodbye ? (DNS_ANSWER_GOODBYE|DNS_ANSWER_CACHE_FLUSH) : DNS_ANSWER_CACHE_FLUSH; + + r = dns_answer_add(answer, i->rr, 0 , flags); + if (r < 0) + return log_debug_errno(r, "Failed to add RR to announce: %m"); + } + + /* Since all the active services are in the zone make them discoverable now. */ + SET_FOREACH(service_type, types, iterator) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr; + + rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, + "_services._dns-sd._udp.local"); + rr->ptr.name = strdup(service_type); + rr->ttl = MDNS_DEFAULT_TTL; + + r = dns_zone_put(&scope->zone, scope, rr, false); + if (r < 0) + log_warning_errno(r, "Failed to add DNS-SD PTR record to MDNS zone: %m"); + + r = dns_answer_add(answer, rr, 0 , 0); + if (r < 0) + return log_debug_errno(r, "Failed to add RR to announce: %m"); + } + + if (dns_answer_isempty(answer)) + return 0; + + r = dns_scope_make_reply_packet(scope, 0, DNS_RCODE_SUCCESS, NULL, answer, NULL, false, &p); + if (r < 0) + return log_debug_errno(r, "Failed to build reply packet: %m"); + + r = dns_scope_emit_udp(scope, -1, p); + if (r < 0) + return log_debug_errno(r, "Failed to send reply packet: %m"); + + /* In section 8.3 of RFC6762: "The Multicast DNS responder MUST send at least two unsolicited + * responses, one second apart." */ + if (!scope->announced) { + usec_t ts; + + scope->announced = true; + + assert_se(sd_event_now(scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); + ts += MDNS_ANNOUNCE_DELAY; + + r = sd_event_add_time( + scope->manager->event, + &scope->announce_event_source, + clock_boottime_or_monotonic(), + ts, + MDNS_JITTER_RANGE_USEC, + on_announcement_timeout, scope); + if (r < 0) + return log_debug_errno(r, "Failed to schedule second announcement: %m"); + + (void) sd_event_source_set_description(scope->announce_event_source, "mdns-announce"); + } + + return 0; +} + +int dns_scope_add_dnssd_services(DnsScope *scope) { + Iterator i; + DnssdService *service; + DnssdTxtData *txt_data; + int r; + + assert(scope); + + if (hashmap_size(scope->manager->dnssd_services) == 0) + return 0; + + scope->announced = false; + + HASHMAP_FOREACH(service, scope->manager->dnssd_services, i) { + service->withdrawn = false; + + r = dns_zone_put(&scope->zone, scope, service->ptr_rr, false); + if (r < 0) + log_warning_errno(r, "Failed to add PTR record to MDNS zone: %m"); + + r = dns_zone_put(&scope->zone, scope, service->srv_rr, true); + if (r < 0) + log_warning_errno(r, "Failed to add SRV record to MDNS zone: %m"); + + LIST_FOREACH(items, txt_data, service->txt_data_items) { + r = dns_zone_put(&scope->zone, scope, txt_data->rr, true); + if (r < 0) + log_warning_errno(r, "Failed to add TXT record to MDNS zone: %m"); + } + } + + return 0; +} + +int dns_scope_remove_dnssd_services(DnsScope *scope) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + Iterator i; + DnssdService *service; + DnssdTxtData *txt_data; + int r; + + assert(scope); + + key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_PTR, + "_services._dns-sd._udp.local"); + if (!key) + return log_oom(); + + r = dns_zone_remove_rrs_by_key(&scope->zone, key); + if (r < 0) + return r; + + HASHMAP_FOREACH(service, scope->manager->dnssd_services, i) { + dns_zone_remove_rr(&scope->zone, service->ptr_rr); + dns_zone_remove_rr(&scope->zone, service->srv_rr); + LIST_FOREACH(items, txt_data, service->txt_data_items) + dns_zone_remove_rr(&scope->zone, txt_data->rr); + } + + return 0; +} + +static bool dns_scope_has_route_only_domains(DnsScope *scope) { + DnsSearchDomain *domain, *first; + bool route_only = false; + + assert(scope); + assert(scope->protocol == DNS_PROTOCOL_DNS); + + /* Returns 'true' if this scope is suitable for queries to specific domains only. For that we check + * if there are any route-only domains on this interface, as a heuristic to discern VPN-style links + * from non-VPN-style links. Returns 'false' for all other cases, i.e. if the scope is intended to + * take queries to arbitrary domains, i.e. has no routing domains set. */ + + if (scope->link) + first = scope->link->search_domains; + else + first = scope->manager->search_domains; + + LIST_FOREACH(domains, domain, first) { + /* "." means "any domain", thus the interface takes any kind of traffic. Thus, we exit early + * here, as it doesn't really matter whether this link has any route-only domains or not, + * "~." really trumps everything and clearly indicates that this interface shall receive all + * traffic it can get. */ + if (dns_name_is_root(DNS_SEARCH_DOMAIN_NAME(domain))) + return false; + + if (domain->route_only) + route_only = true; + } + + return route_only; +} + +bool dns_scope_is_default_route(DnsScope *scope) { + assert(scope); + + /* Only use DNS scopes as default routes */ + if (scope->protocol != DNS_PROTOCOL_DNS) + return false; + + /* The global DNS scope is always suitable as default route */ + if (!scope->link) + return true; + + /* Honour whatever is explicitly configured. This is really the best approach, and trumps any + * automatic logic. */ + if (scope->link->default_route >= 0) + return scope->link->default_route; + + /* Otherwise check if we have any route-only domains, as a sensible heuristic: if so, let's not + * volunteer as default route. */ + return !dns_scope_has_route_only_domains(scope); +} diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h new file mode 100644 index 00000000..f4b45c4f --- /dev/null +++ b/src/resolve/resolved-dns-scope.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "list.h" + +typedef struct DnsScope DnsScope; + +#include "resolved-dns-cache.h" +#include "resolved-dns-dnssec.h" +#include "resolved-dns-packet.h" +#include "resolved-dns-query.h" +#include "resolved-dns-search-domain.h" +#include "resolved-dns-server.h" +#include "resolved-dns-stream.h" +#include "resolved-dns-zone.h" +#include "resolved-link.h" + +typedef enum DnsScopeMatch { + DNS_SCOPE_NO, + DNS_SCOPE_MAYBE, + DNS_SCOPE_YES_BASE, /* Add the number of matching labels to this */ + DNS_SCOPE_YES_END = DNS_SCOPE_YES_BASE + DNS_N_LABELS_MAX, + _DNS_SCOPE_MATCH_MAX, + _DNS_SCOPE_MATCH_INVALID = -1 +} DnsScopeMatch; + +struct DnsScope { + Manager *manager; + + DnsProtocol protocol; + int family; + + /* Copied at scope creation time from the link/manager */ + DnssecMode dnssec_mode; + DnsOverTlsMode dns_over_tls_mode; + + Link *link; + + DnsCache cache; + DnsZone zone; + + OrderedHashmap *conflict_queue; + sd_event_source *conflict_event_source; + + bool announced:1; + sd_event_source *announce_event_source; + + RateLimit ratelimit; + + usec_t resend_timeout; + usec_t max_rtt; + + LIST_HEAD(DnsQueryCandidate, query_candidates); + + /* Note that we keep track of ongoing transactions in two + * ways: once in a hashmap, indexed by the rr key, and once in + * a linked list. We use the hashmap to quickly find + * transactions we can reuse for a key. But note that there + * might be multiple transactions for the same key (because + * the zone probing can't reuse a transaction answered from + * the zone or the cache), and the hashmap only tracks the + * most recent entry. */ + Hashmap *transactions_by_key; + LIST_HEAD(DnsTransaction, transactions); + + LIST_FIELDS(DnsScope, scopes); +}; + +int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol p, int family); +DnsScope* dns_scope_free(DnsScope *s); + +void dns_scope_packet_received(DnsScope *s, usec_t rtt); +void dns_scope_packet_lost(DnsScope *s, usec_t usec); + +int dns_scope_emit_udp(DnsScope *s, int fd, DnsPacket *p); +int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *address, DnsServer *server, uint16_t port, union sockaddr_union *ret_socket_address); +int dns_scope_socket_udp(DnsScope *s, DnsServer *server, uint16_t port); + +DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain); +bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key); + +DnsServer *dns_scope_get_dns_server(DnsScope *s); +unsigned dns_scope_get_n_dns_servers(DnsScope *s); +void dns_scope_next_dns_server(DnsScope *s); + +int dns_scope_llmnr_membership(DnsScope *s, bool b); +int dns_scope_mdns_membership(DnsScope *s, bool b); + +int dns_scope_make_reply_packet(DnsScope *s, uint16_t id, int rcode, DnsQuestion *q, DnsAnswer *answer, DnsAnswer *soa, bool tentative, DnsPacket **ret); +void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p); + +DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok); + +int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr); +void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p); + +void dns_scope_dump(DnsScope *s, FILE *f); + +DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s); + +bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name); + +bool dns_scope_network_good(DnsScope *s); + +int dns_scope_ifindex(DnsScope *s); + +int dns_scope_announce(DnsScope *scope, bool goodbye); + +int dns_scope_add_dnssd_services(DnsScope *scope); +int dns_scope_remove_dnssd_services(DnsScope *scope); + +bool dns_scope_is_default_route(DnsScope *scope); diff --git a/src/resolve/resolved-dns-search-domain.c b/src/resolve/resolved-dns-search-domain.c new file mode 100644 index 00000000..21c2442c --- /dev/null +++ b/src/resolve/resolved-dns-search-domain.c @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "dns-domain.h" +#include "resolved-dns-search-domain.h" + +int dns_search_domain_new( + Manager *m, + DnsSearchDomain **ret, + DnsSearchDomainType type, + Link *l, + const char *name) { + + _cleanup_free_ char *normalized = NULL; + DnsSearchDomain *d; + int r; + + assert(m); + assert((type == DNS_SEARCH_DOMAIN_LINK) == !!l); + assert(name); + + r = dns_name_normalize(name, 0, &normalized); + if (r < 0) + return r; + + if (l) { + if (l->n_search_domains >= LINK_SEARCH_DOMAINS_MAX) + return -E2BIG; + } else { + if (m->n_search_domains >= MANAGER_SEARCH_DOMAINS_MAX) + return -E2BIG; + } + + d = new0(DnsSearchDomain, 1); + if (!d) + return -ENOMEM; + + d->n_ref = 1; + d->manager = m; + d->type = type; + d->name = TAKE_PTR(normalized); + + switch (type) { + + case DNS_SEARCH_DOMAIN_LINK: + d->link = l; + LIST_APPEND(domains, l->search_domains, d); + l->n_search_domains++; + break; + + case DNS_SERVER_SYSTEM: + LIST_APPEND(domains, m->search_domains, d); + m->n_search_domains++; + break; + + default: + assert_not_reached("Unknown search domain type"); + } + + d->linked = true; + + if (ret) + *ret = d; + + return 0; +} + +static DnsSearchDomain* dns_search_domain_free(DnsSearchDomain *d) { + assert(d); + + free(d->name); + return mfree(d); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsSearchDomain, dns_search_domain, dns_search_domain_free); + +void dns_search_domain_unlink(DnsSearchDomain *d) { + assert(d); + assert(d->manager); + + if (!d->linked) + return; + + switch (d->type) { + + case DNS_SEARCH_DOMAIN_LINK: + assert(d->link); + assert(d->link->n_search_domains > 0); + LIST_REMOVE(domains, d->link->search_domains, d); + d->link->n_search_domains--; + break; + + case DNS_SEARCH_DOMAIN_SYSTEM: + assert(d->manager->n_search_domains > 0); + LIST_REMOVE(domains, d->manager->search_domains, d); + d->manager->n_search_domains--; + break; + } + + d->linked = false; + + dns_search_domain_unref(d); +} + +void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d) { + DnsSearchDomain *tail; + + assert(d); + + if (!d->marked) + return; + + d->marked = false; + + if (!d->linked || !d->domains_next) + return; + + switch (d->type) { + + case DNS_SEARCH_DOMAIN_LINK: + assert(d->link); + LIST_FIND_TAIL(domains, d, tail); + LIST_REMOVE(domains, d->link->search_domains, d); + LIST_INSERT_AFTER(domains, d->link->search_domains, tail, d); + break; + + case DNS_SEARCH_DOMAIN_SYSTEM: + LIST_FIND_TAIL(domains, d, tail); + LIST_REMOVE(domains, d->manager->search_domains, d); + LIST_INSERT_AFTER(domains, d->manager->search_domains, tail, d); + break; + + default: + assert_not_reached("Unknown search domain type"); + } +} + +void dns_search_domain_unlink_all(DnsSearchDomain *first) { + DnsSearchDomain *next; + + if (!first) + return; + + next = first->domains_next; + dns_search_domain_unlink(first); + + dns_search_domain_unlink_all(next); +} + +void dns_search_domain_unlink_marked(DnsSearchDomain *first) { + DnsSearchDomain *next; + + if (!first) + return; + + next = first->domains_next; + + if (first->marked) + dns_search_domain_unlink(first); + + dns_search_domain_unlink_marked(next); +} + +void dns_search_domain_mark_all(DnsSearchDomain *first) { + if (!first) + return; + + first->marked = true; + dns_search_domain_mark_all(first->domains_next); +} + +int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret) { + DnsSearchDomain *d; + int r; + + assert(name); + assert(ret); + + LIST_FOREACH(domains, d, first) { + + r = dns_name_equal(name, d->name); + if (r < 0) + return r; + if (r > 0) { + *ret = d; + return 1; + } + } + + *ret = NULL; + return 0; +} diff --git a/src/resolve/resolved-dns-search-domain.h b/src/resolve/resolved-dns-search-domain.h new file mode 100644 index 00000000..d0c2914d --- /dev/null +++ b/src/resolve/resolved-dns-search-domain.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "macro.h" + +typedef struct DnsSearchDomain DnsSearchDomain; + +typedef enum DnsSearchDomainType { + DNS_SEARCH_DOMAIN_SYSTEM, + DNS_SEARCH_DOMAIN_LINK, +} DnsSearchDomainType; + +#include "resolved-link.h" +#include "resolved-manager.h" + +struct DnsSearchDomain { + Manager *manager; + + unsigned n_ref; + + DnsSearchDomainType type; + Link *link; + + char *name; + + bool marked:1; + bool route_only:1; + + bool linked:1; + LIST_FIELDS(DnsSearchDomain, domains); +}; + +int dns_search_domain_new( + Manager *m, + DnsSearchDomain **ret, + DnsSearchDomainType type, + Link *link, + const char *name); + +DnsSearchDomain* dns_search_domain_ref(DnsSearchDomain *d); +DnsSearchDomain* dns_search_domain_unref(DnsSearchDomain *d); + +void dns_search_domain_unlink(DnsSearchDomain *d); +void dns_search_domain_move_back_and_unmark(DnsSearchDomain *d); + +void dns_search_domain_unlink_all(DnsSearchDomain *first); +void dns_search_domain_unlink_marked(DnsSearchDomain *first); +void dns_search_domain_mark_all(DnsSearchDomain *first); + +int dns_search_domain_find(DnsSearchDomain *first, const char *name, DnsSearchDomain **ret); + +static inline const char* DNS_SEARCH_DOMAIN_NAME(DnsSearchDomain *d) { + return d ? d->name : NULL; +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsSearchDomain*, dns_search_domain_unref); diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c new file mode 100644 index 00000000..9f2c9731 --- /dev/null +++ b/src/resolve/resolved-dns-server.c @@ -0,0 +1,901 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "resolved-bus.h" +#include "resolved-dns-server.h" +#include "resolved-dns-stub.h" +#include "resolved-resolv-conf.h" +#include "siphash24.h" +#include "string-table.h" +#include "string-util.h" + +/* The amount of time to wait before retrying with a full feature set */ +#define DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC (6 * USEC_PER_HOUR) +#define DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC (5 * USEC_PER_MINUTE) + +/* The number of times we will attempt a certain feature set before degrading */ +#define DNS_SERVER_FEATURE_RETRY_ATTEMPTS 3 + +int dns_server_new( + Manager *m, + DnsServer **ret, + DnsServerType type, + Link *l, + int family, + const union in_addr_union *in_addr, + int ifindex) { + + DnsServer *s; + + assert(m); + assert((type == DNS_SERVER_LINK) == !!l); + assert(in_addr); + + if (!IN_SET(family, AF_INET, AF_INET6)) + return -EAFNOSUPPORT; + + if (l) { + if (l->n_dns_servers >= LINK_DNS_SERVERS_MAX) + return -E2BIG; + } else { + if (m->n_dns_servers >= MANAGER_DNS_SERVERS_MAX) + return -E2BIG; + } + + s = new(DnsServer, 1); + if (!s) + return -ENOMEM; + + *s = (DnsServer) { + .n_ref = 1, + .manager = m, + .type = type, + .family = family, + .address = *in_addr, + .ifindex = ifindex, + }; + + dns_server_reset_features(s); + + switch (type) { + + case DNS_SERVER_LINK: + s->link = l; + LIST_APPEND(servers, l->dns_servers, s); + l->n_dns_servers++; + break; + + case DNS_SERVER_SYSTEM: + LIST_APPEND(servers, m->dns_servers, s); + m->n_dns_servers++; + break; + + case DNS_SERVER_FALLBACK: + LIST_APPEND(servers, m->fallback_dns_servers, s); + m->n_dns_servers++; + break; + + default: + assert_not_reached("Unknown server type"); + } + + s->linked = true; + + /* A new DNS server that isn't fallback is added and the one + * we used so far was a fallback one? Then let's try to pick + * the new one */ + if (type != DNS_SERVER_FALLBACK && + m->current_dns_server && + m->current_dns_server->type == DNS_SERVER_FALLBACK) + manager_set_dns_server(m, NULL); + + if (ret) + *ret = s; + + return 0; +} + +static DnsServer* dns_server_free(DnsServer *s) { + assert(s); + + dns_server_unref_stream(s); + +#if ENABLE_DNS_OVER_TLS + dnstls_server_free(s); +#endif + + free(s->server_string); + return mfree(s); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsServer, dns_server, dns_server_free); + +void dns_server_unlink(DnsServer *s) { + assert(s); + assert(s->manager); + + /* This removes the specified server from the linked list of + * servers, but any server might still stay around if it has + * refs, for example from an ongoing transaction. */ + + if (!s->linked) + return; + + switch (s->type) { + + case DNS_SERVER_LINK: + assert(s->link); + assert(s->link->n_dns_servers > 0); + LIST_REMOVE(servers, s->link->dns_servers, s); + s->link->n_dns_servers--; + break; + + case DNS_SERVER_SYSTEM: + assert(s->manager->n_dns_servers > 0); + LIST_REMOVE(servers, s->manager->dns_servers, s); + s->manager->n_dns_servers--; + break; + + case DNS_SERVER_FALLBACK: + assert(s->manager->n_dns_servers > 0); + LIST_REMOVE(servers, s->manager->fallback_dns_servers, s); + s->manager->n_dns_servers--; + break; + default: + assert_not_reached("Unknown server type"); + } + + s->linked = false; + + if (s->link && s->link->current_dns_server == s) + link_set_dns_server(s->link, NULL); + + if (s->manager->current_dns_server == s) + manager_set_dns_server(s->manager, NULL); + + /* No need to keep a default stream around anymore */ + dns_server_unref_stream(s); + + dns_server_unref(s); +} + +void dns_server_move_back_and_unmark(DnsServer *s) { + DnsServer *tail; + + assert(s); + + if (!s->marked) + return; + + s->marked = false; + + if (!s->linked || !s->servers_next) + return; + + /* Move us to the end of the list, so that the order is + * strictly kept, if we are not at the end anyway. */ + + switch (s->type) { + + case DNS_SERVER_LINK: + assert(s->link); + LIST_FIND_TAIL(servers, s, tail); + LIST_REMOVE(servers, s->link->dns_servers, s); + LIST_INSERT_AFTER(servers, s->link->dns_servers, tail, s); + break; + + case DNS_SERVER_SYSTEM: + LIST_FIND_TAIL(servers, s, tail); + LIST_REMOVE(servers, s->manager->dns_servers, s); + LIST_INSERT_AFTER(servers, s->manager->dns_servers, tail, s); + break; + + case DNS_SERVER_FALLBACK: + LIST_FIND_TAIL(servers, s, tail); + LIST_REMOVE(servers, s->manager->fallback_dns_servers, s); + LIST_INSERT_AFTER(servers, s->manager->fallback_dns_servers, tail, s); + break; + + default: + assert_not_reached("Unknown server type"); + } +} + +static void dns_server_verified(DnsServer *s, DnsServerFeatureLevel level) { + assert(s); + + if (s->verified_feature_level > level) + return; + + if (s->verified_feature_level != level) { + log_debug("Verified we get a response at feature level %s from DNS server %s.", + dns_server_feature_level_to_string(level), + dns_server_string(s)); + s->verified_feature_level = level; + } + + assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &s->verified_usec) >= 0); +} + +static void dns_server_reset_counters(DnsServer *s) { + assert(s); + + s->n_failed_udp = 0; + s->n_failed_tcp = 0; + s->n_failed_tls = 0; + s->packet_truncated = false; + s->verified_usec = 0; + + /* Note that we do not reset s->packet_bad_opt and s->packet_rrsig_missing here. We reset them only when the + * grace period ends, but not when lowering the possible feature level, as a lower level feature level should + * not make RRSIGs appear or OPT appear, but rather make them disappear. If the reappear anyway, then that's + * indication for a differently broken OPT/RRSIG implementation, and we really don't want to support that + * either. + * + * This is particularly important to deal with certain Belkin routers which break OPT for certain lookups (A), + * but pass traffic through for others (AAAA). If we detect the broken behaviour on one lookup we should not + * re-enable it for another, because we cannot validate things anyway, given that the RRSIG/OPT data will be + * incomplete. */ +} + +void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, size_t size) { + assert(s); + + if (protocol == IPPROTO_UDP) { + if (s->possible_feature_level == level) + s->n_failed_udp = 0; + } else if (protocol == IPPROTO_TCP) { + if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(level)) { + if (s->possible_feature_level == level) + s->n_failed_tls = 0; + } else { + if (s->possible_feature_level == level) + s->n_failed_tcp = 0; + + /* Successful TCP connections are only useful to verify the TCP feature level. */ + level = DNS_SERVER_FEATURE_LEVEL_TCP; + } + } + + /* If the RRSIG data is missing, then we can only validate EDNS0 at max */ + if (s->packet_rrsig_missing && level >= DNS_SERVER_FEATURE_LEVEL_DO) + level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0; + + /* If the OPT RR got lost, then we can only validate UDP at max */ + if (s->packet_bad_opt && level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) + level = DNS_SERVER_FEATURE_LEVEL_EDNS0 - 1; + + /* Even if we successfully receive a reply to a request announcing support for large packets, + that does not mean we can necessarily receive large packets. */ + if (level == DNS_SERVER_FEATURE_LEVEL_LARGE) + level = DNS_SERVER_FEATURE_LEVEL_LARGE - 1; + + dns_server_verified(s, level); + + /* Remember the size of the largest UDP packet we received from a server, + we know that we can always announce support for packets with at least + this size. */ + if (protocol == IPPROTO_UDP && s->received_udp_packet_max < size) + s->received_udp_packet_max = size; +} + +void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level) { + assert(s); + assert(s->manager); + + if (s->possible_feature_level == level) { + if (protocol == IPPROTO_UDP) + s->n_failed_udp++; + else if (protocol == IPPROTO_TCP) { + if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(level)) + s->n_failed_tls++; + else + s->n_failed_tcp++; + } + } +} + +void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level) { + assert(s); + + /* Invoked whenever we get a packet with TC bit set. */ + + if (s->possible_feature_level != level) + return; + + s->packet_truncated = true; +} + +void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level) { + assert(s); + + if (level < DNS_SERVER_FEATURE_LEVEL_DO) + return; + + /* If the RRSIG RRs are missing, we have to downgrade what we previously verified */ + if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO) + s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0; + + s->packet_rrsig_missing = true; +} + +void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level) { + assert(s); + + if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0) + return; + + /* If the OPT RR got lost, we have to downgrade what we previously verified */ + if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) + s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0-1; + + s->packet_bad_opt = true; +} + +void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level) { + assert(s); + + /* Invoked whenever we got a FORMERR, SERVFAIL or NOTIMP rcode from a server and downgrading the feature level + * for the transaction made it go away. In this case we immediately downgrade to the feature level that made + * things work. */ + + if (s->verified_feature_level > level) + s->verified_feature_level = level; + + if (s->possible_feature_level > level) { + s->possible_feature_level = level; + dns_server_reset_counters(s); + } + + log_debug("Downgrading transaction feature level fixed an RCODE error, downgrading server %s too.", dns_server_string(s)); +} + +static bool dns_server_grace_period_expired(DnsServer *s) { + usec_t ts; + + assert(s); + assert(s->manager); + + if (s->verified_usec == 0) + return false; + + assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); + + if (s->verified_usec + s->features_grace_period_usec > ts) + return false; + + s->features_grace_period_usec = MIN(s->features_grace_period_usec * 2, DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC); + + return true; +} + +DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) { + DnsServerFeatureLevel best; + + assert(s); + + /* Determine the best feature level we care about. If DNSSEC mode is off there's no point in using anything + * better than EDNS0, hence don't even try. */ + if (dns_server_get_dnssec_mode(s) != DNSSEC_NO) + best = dns_server_get_dns_over_tls_mode(s) == DNS_OVER_TLS_NO ? + DNS_SERVER_FEATURE_LEVEL_LARGE : + DNS_SERVER_FEATURE_LEVEL_TLS_DO; + else + best = dns_server_get_dns_over_tls_mode(s) == DNS_OVER_TLS_NO ? + DNS_SERVER_FEATURE_LEVEL_EDNS0 : + DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN; + + /* Clamp the feature level the highest level we care about. The DNSSEC mode might have changed since the last + * time, hence let's downgrade if we are still at a higher level. */ + if (s->possible_feature_level > best) + s->possible_feature_level = best; + + if (s->possible_feature_level < best && dns_server_grace_period_expired(s)) { + + s->possible_feature_level = best; + + dns_server_reset_counters(s); + + s->packet_bad_opt = false; + s->packet_rrsig_missing = false; + + log_info("Grace period over, resuming full feature set (%s) for DNS server %s.", + dns_server_feature_level_to_string(s->possible_feature_level), + dns_server_string(s)); + + dns_server_flush_cache(s); + + } else if (s->possible_feature_level <= s->verified_feature_level) + s->possible_feature_level = s->verified_feature_level; + else { + DnsServerFeatureLevel p = s->possible_feature_level; + + if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS && + s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_TCP) { + + /* We are at the TCP (lowest) level, and we tried a couple of TCP connections, and it didn't + * work. Upgrade back to UDP again. */ + log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again..."); + s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP; + } else if (s->n_failed_tls > 0 && + DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) && dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) { + + /* We tried to connect using DNS-over-TLS, and it didn't work. Downgrade to plaintext UDP + * if we don't require DNS-over-TLS */ + + log_debug("Server doesn't support DNS-over-TLS, downgrading protocol..."); + s->possible_feature_level--; + } else if (s->packet_bad_opt && + s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0) { + + /* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to below + * EDNS0 levels. After all, some records generate different responses with and without OPT RR + * in the request. Example: + * https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */ + + log_debug("Server doesn't support EDNS(0) properly, downgrading feature level..."); + s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP; + + } else if (s->packet_rrsig_missing && + s->possible_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO) { + + /* RRSIG data was missing on a EDNS0 packet with DO bit set. This means the server doesn't + * augment responses with DNSSEC RRs. If so, let's better not ask the server for it anymore, + * after all some servers generate different replies depending if an OPT RR is in the query or + * not. */ + + log_debug("Detected server responses lack RRSIG records, downgrading feature level..."); + s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0; + + } else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS && + s->possible_feature_level >= (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) { + + /* We lost too many UDP packets in a row, and are on a feature level of UDP or higher. If the + * packets are lost, maybe the server cannot parse them, hence downgrading sounds like a good + * idea. We might downgrade all the way down to TCP this way. + * + * If strict DNSSEC mode is used we won't downgrade below DO level however, as packet loss + * might have many reasons, a broken DNSSEC implementation being only one reason. And if the + * user is strict on DNSSEC, then let's assume that DNSSEC is not the fault here. */ + + log_debug("Lost too many UDP packets, downgrading feature level..."); + s->possible_feature_level--; + + } else if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS && + s->packet_truncated && + s->possible_feature_level > (dns_server_get_dnssec_mode(s) == DNSSEC_YES ? DNS_SERVER_FEATURE_LEVEL_LARGE : DNS_SERVER_FEATURE_LEVEL_UDP)) { + + /* We got too many TCP connection failures in a row, we had at least one truncated packet, and + * are on a feature level above UDP. By downgrading things and getting rid of DNSSEC or EDNS0 + * data we hope to make the packet smaller, so that it still works via UDP given that TCP + * appears not to be a fallback. Note that if we are already at the lowest UDP level, we don't + * go further down, since that's TCP, and TCP failed too often after all. */ + + log_debug("Got too many failed TCP connection failures and truncated UDP packets, downgrading feature level..."); + s->possible_feature_level--; + } + + if (p != s->possible_feature_level) { + + /* We changed the feature level, reset the counting */ + dns_server_reset_counters(s); + + log_warning("Using degraded feature set (%s) for DNS server %s.", + dns_server_feature_level_to_string(s->possible_feature_level), + dns_server_string(s)); + } + } + + return s->possible_feature_level; +} + +int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level) { + size_t packet_size; + bool edns_do; + int r; + + assert(server); + assert(packet); + assert(packet->protocol == DNS_PROTOCOL_DNS); + + /* Fix the OPT field in the packet to match our current feature level. */ + + r = dns_packet_truncate_opt(packet); + if (r < 0) + return r; + + if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0) + return 0; + + edns_do = level >= DNS_SERVER_FEATURE_LEVEL_DO; + + if (level >= DNS_SERVER_FEATURE_LEVEL_LARGE) + packet_size = DNS_PACKET_UNICAST_SIZE_LARGE_MAX; + else + packet_size = server->received_udp_packet_max; + + return dns_packet_append_opt(packet, packet_size, edns_do, 0, NULL); +} + +int dns_server_ifindex(const DnsServer *s) { + assert(s); + + /* The link ifindex always takes precedence */ + if (s->link) + return s->link->ifindex; + + if (s->ifindex > 0) + return s->ifindex; + + return 0; +} + +const char *dns_server_string(DnsServer *server) { + assert(server); + + if (!server->server_string) + (void) in_addr_ifindex_to_string(server->family, &server->address, dns_server_ifindex(server), &server->server_string); + + return strna(server->server_string); +} + +bool dns_server_dnssec_supported(DnsServer *server) { + assert(server); + + /* Returns whether the server supports DNSSEC according to what we know about it */ + + if (server->possible_feature_level < DNS_SERVER_FEATURE_LEVEL_DO) + return false; + + if (server->packet_bad_opt) + return false; + + if (server->packet_rrsig_missing) + return false; + + /* DNSSEC servers need to support TCP properly (see RFC5966), if they don't, we assume DNSSEC is borked too */ + if (server->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS) + return false; + + return true; +} + +void dns_server_warn_downgrade(DnsServer *server) { + assert(server); + + if (server->warned_downgrade) + return; + + log_struct(LOG_NOTICE, + "MESSAGE_ID=" SD_MESSAGE_DNSSEC_DOWNGRADE_STR, + LOG_MESSAGE("Server %s does not support DNSSEC, downgrading to non-DNSSEC mode.", dns_server_string(server)), + "DNS_SERVER=%s", dns_server_string(server), + "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(server->possible_feature_level)); + + server->warned_downgrade = true; +} + +static void dns_server_hash_func(const DnsServer *s, struct siphash *state) { + assert(s); + + siphash24_compress(&s->family, sizeof(s->family), state); + siphash24_compress(&s->address, FAMILY_ADDRESS_SIZE(s->family), state); + siphash24_compress(&s->ifindex, sizeof(s->ifindex), state); +} + +static int dns_server_compare_func(const DnsServer *x, const DnsServer *y) { + int r; + + r = CMP(x->family, y->family); + if (r != 0) + return r; + + r = memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family)); + if (r != 0) + return r; + + r = CMP(x->ifindex, y->ifindex); + if (r != 0) + return r; + + return 0; +} + +DEFINE_HASH_OPS(dns_server_hash_ops, DnsServer, dns_server_hash_func, dns_server_compare_func); + +void dns_server_unlink_all(DnsServer *first) { + DnsServer *next; + + if (!first) + return; + + next = first->servers_next; + dns_server_unlink(first); + + dns_server_unlink_all(next); +} + +void dns_server_unlink_marked(DnsServer *first) { + DnsServer *next; + + if (!first) + return; + + next = first->servers_next; + + if (first->marked) + dns_server_unlink(first); + + dns_server_unlink_marked(next); +} + +void dns_server_mark_all(DnsServer *first) { + if (!first) + return; + + first->marked = true; + dns_server_mark_all(first->servers_next); +} + +DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr, int ifindex) { + DnsServer *s; + + LIST_FOREACH(servers, s, first) + if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0 && s->ifindex == ifindex) + return s; + + return NULL; +} + +DnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t) { + assert(m); + + switch (t) { + + case DNS_SERVER_SYSTEM: + return m->dns_servers; + + case DNS_SERVER_FALLBACK: + return m->fallback_dns_servers; + + default: + return NULL; + } +} + +DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) { + assert(m); + + if (m->current_dns_server == s) + return s; + + if (s) + log_debug("Switching to %s DNS server %s.", + dns_server_type_to_string(s->type), + dns_server_string(s)); + + dns_server_unref(m->current_dns_server); + m->current_dns_server = dns_server_ref(s); + + if (m->unicast_scope) + dns_cache_flush(&m->unicast_scope->cache); + + (void) manager_send_changed(m, "CurrentDNSServer"); + + return s; +} + +DnsServer *manager_get_dns_server(Manager *m) { + Link *l; + assert(m); + + /* Try to read updates resolv.conf */ + manager_read_resolv_conf(m); + + /* If no DNS server was chosen so far, pick the first one */ + if (!m->current_dns_server) + manager_set_dns_server(m, m->dns_servers); + + if (!m->current_dns_server) { + bool found = false; + Iterator i; + + /* No DNS servers configured, let's see if there are + * any on any links. If not, we use the fallback + * servers */ + + HASHMAP_FOREACH(l, m->links, i) + if (l->dns_servers) { + found = true; + break; + } + + if (!found) + manager_set_dns_server(m, m->fallback_dns_servers); + } + + return m->current_dns_server; +} + +void manager_next_dns_server(Manager *m) { + assert(m); + + /* If there's currently no DNS server set, then the next + * manager_get_dns_server() will find one */ + if (!m->current_dns_server) + return; + + /* Change to the next one, but make sure to follow the linked + * list only if the server is still linked. */ + if (m->current_dns_server->linked && m->current_dns_server->servers_next) { + manager_set_dns_server(m, m->current_dns_server->servers_next); + return; + } + + /* If there was no next one, then start from the beginning of + * the list */ + if (m->current_dns_server->type == DNS_SERVER_FALLBACK) + manager_set_dns_server(m, m->fallback_dns_servers); + else + manager_set_dns_server(m, m->dns_servers); +} + +DnssecMode dns_server_get_dnssec_mode(DnsServer *s) { + assert(s); + + if (s->link) + return link_get_dnssec_mode(s->link); + + return manager_get_dnssec_mode(s->manager); +} + +DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s) { + assert(s); + + if (s->link) + return link_get_dns_over_tls_mode(s->link); + + return manager_get_dns_over_tls_mode(s->manager); +} + +void dns_server_flush_cache(DnsServer *s) { + DnsServer *current; + DnsScope *scope; + + assert(s); + + /* Flush the cache of the scope this server belongs to */ + + current = s->link ? s->link->current_dns_server : s->manager->current_dns_server; + if (current != s) + return; + + scope = s->link ? s->link->unicast_scope : s->manager->unicast_scope; + if (!scope) + return; + + dns_cache_flush(&scope->cache); +} + +void dns_server_reset_features(DnsServer *s) { + assert(s); + + s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID; + s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST; + + s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX; + + s->packet_bad_opt = false; + s->packet_rrsig_missing = false; + + s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC; + + s->warned_downgrade = false; + + dns_server_reset_counters(s); + + /* Let's close the default stream, so that we reprobe with the new features */ + dns_server_unref_stream(s); +} + +void dns_server_reset_features_all(DnsServer *s) { + DnsServer *i; + + LIST_FOREACH(servers, i, s) + dns_server_reset_features(i); +} + +void dns_server_dump(DnsServer *s, FILE *f) { + assert(s); + + if (!f) + f = stdout; + + fputs("[Server ", f); + fputs(dns_server_string(s), f); + fputs(" type=", f); + fputs(dns_server_type_to_string(s->type), f); + + if (s->type == DNS_SERVER_LINK) { + assert(s->link); + + fputs(" interface=", f); + fputs(s->link->ifname, f); + } + + fputs("]\n", f); + + fputs("\tVerified feature level: ", f); + fputs(strna(dns_server_feature_level_to_string(s->verified_feature_level)), f); + fputc('\n', f); + + fputs("\tPossible feature level: ", f); + fputs(strna(dns_server_feature_level_to_string(s->possible_feature_level)), f); + fputc('\n', f); + + fputs("\tDNSSEC Mode: ", f); + fputs(strna(dnssec_mode_to_string(dns_server_get_dnssec_mode(s))), f); + fputc('\n', f); + + fputs("\tCan do DNSSEC: ", f); + fputs(yes_no(dns_server_dnssec_supported(s)), f); + fputc('\n', f); + + fprintf(f, + "\tMaximum UDP packet size received: %zu\n" + "\tFailed UDP attempts: %u\n" + "\tFailed TCP attempts: %u\n" + "\tSeen truncated packet: %s\n" + "\tSeen OPT RR getting lost: %s\n" + "\tSeen RRSIG RR missing: %s\n", + s->received_udp_packet_max, + s->n_failed_udp, + s->n_failed_tcp, + yes_no(s->packet_truncated), + yes_no(s->packet_bad_opt), + yes_no(s->packet_rrsig_missing)); +} + +void dns_server_unref_stream(DnsServer *s) { + DnsStream *ref; + + assert(s); + + /* Detaches the default stream of this server. Some special care needs to be taken here, as that stream and + * this server reference each other. First, take the stream out of the server. It's destructor will check if it + * is registered with us, hence let's invalidate this separately, so that it is already unregistered. */ + ref = TAKE_PTR(s->stream); + + /* And then, unref it */ + dns_stream_unref(ref); +} + +DnsScope *dns_server_scope(DnsServer *s) { + assert(s); + assert((s->type == DNS_SERVER_LINK) == !!s->link); + + if (s->link) + return s->link->unicast_scope; + + return s->manager->unicast_scope; +} + +static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = { + [DNS_SERVER_SYSTEM] = "system", + [DNS_SERVER_FALLBACK] = "fallback", + [DNS_SERVER_LINK] = "link", +}; +DEFINE_STRING_TABLE_LOOKUP(dns_server_type, DnsServerType); + +static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVEL_MAX] = { + [DNS_SERVER_FEATURE_LEVEL_TCP] = "TCP", + [DNS_SERVER_FEATURE_LEVEL_UDP] = "UDP", + [DNS_SERVER_FEATURE_LEVEL_EDNS0] = "UDP+EDNS0", + [DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN] = "TLS+EDNS0", + [DNS_SERVER_FEATURE_LEVEL_DO] = "UDP+EDNS0+DO", + [DNS_SERVER_FEATURE_LEVEL_LARGE] = "UDP+EDNS0+DO+LARGE", + [DNS_SERVER_FEATURE_LEVEL_TLS_DO] = "TLS+EDNS0+D0", +}; +DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level, DnsServerFeatureLevel); diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h new file mode 100644 index 00000000..54339355 --- /dev/null +++ b/src/resolve/resolved-dns-server.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "in-addr-util.h" + +typedef struct DnsServer DnsServer; + +typedef enum DnsServerType { + DNS_SERVER_SYSTEM, + DNS_SERVER_FALLBACK, + DNS_SERVER_LINK, + _DNS_SERVER_TYPE_MAX, + _DNS_SERVER_TYPE_INVALID = -1 +} DnsServerType; + +const char* dns_server_type_to_string(DnsServerType i) _const_; +DnsServerType dns_server_type_from_string(const char *s) _pure_; + +typedef enum DnsServerFeatureLevel { + DNS_SERVER_FEATURE_LEVEL_TCP, + DNS_SERVER_FEATURE_LEVEL_UDP, + DNS_SERVER_FEATURE_LEVEL_EDNS0, + DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN, + DNS_SERVER_FEATURE_LEVEL_DO, + DNS_SERVER_FEATURE_LEVEL_LARGE, + DNS_SERVER_FEATURE_LEVEL_TLS_DO, + _DNS_SERVER_FEATURE_LEVEL_MAX, + _DNS_SERVER_FEATURE_LEVEL_INVALID = -1 +} DnsServerFeatureLevel; + +#define DNS_SERVER_FEATURE_LEVEL_WORST 0 +#define DNS_SERVER_FEATURE_LEVEL_BEST (_DNS_SERVER_FEATURE_LEVEL_MAX - 1) +#define DNS_SERVER_FEATURE_LEVEL_IS_TLS(x) IN_SET(x, DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN, DNS_SERVER_FEATURE_LEVEL_TLS_DO) + +const char* dns_server_feature_level_to_string(int i) _const_; +int dns_server_feature_level_from_string(const char *s) _pure_; + +#include "resolved-dnstls.h" +#include "resolved-link.h" +#include "resolved-manager.h" + +struct DnsServer { + Manager *manager; + + unsigned n_ref; + + DnsServerType type; + Link *link; + + int family; + union in_addr_union address; + int ifindex; /* for IPv6 link-local DNS servers */ + + char *server_string; + + /* The long-lived stream towards this server. */ + DnsStream *stream; + +#if ENABLE_DNS_OVER_TLS + DnsTlsServerData dnstls_data; +#endif + + DnsServerFeatureLevel verified_feature_level; + DnsServerFeatureLevel possible_feature_level; + + size_t received_udp_packet_max; + + unsigned n_failed_udp; + unsigned n_failed_tcp; + unsigned n_failed_tls; + + bool packet_truncated:1; + bool packet_bad_opt:1; + bool packet_rrsig_missing:1; + + usec_t verified_usec; + usec_t features_grace_period_usec; + + /* Whether we already warned about downgrading to non-DNSSEC mode for this server */ + bool warned_downgrade:1; + + /* Used when GC'ing old DNS servers when configuration changes. */ + bool marked:1; + + /* If linked is set, then this server appears in the servers linked list */ + bool linked:1; + LIST_FIELDS(DnsServer, servers); +}; + +int dns_server_new( + Manager *m, + DnsServer **ret, + DnsServerType type, + Link *link, + int family, + const union in_addr_union *address, + int ifindex); + +DnsServer* dns_server_ref(DnsServer *s); +DnsServer* dns_server_unref(DnsServer *s); + +void dns_server_unlink(DnsServer *s); +void dns_server_move_back_and_unmark(DnsServer *s); + +void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, size_t size); +void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level); +void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level); +void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level); +void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level); +void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level); + +DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s); + +int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level); + +const char *dns_server_string(DnsServer *server); +int dns_server_ifindex(const DnsServer *s); + +bool dns_server_dnssec_supported(DnsServer *server); + +void dns_server_warn_downgrade(DnsServer *server); + +DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr, int ifindex); + +void dns_server_unlink_all(DnsServer *first); +void dns_server_unlink_marked(DnsServer *first); +void dns_server_mark_all(DnsServer *first); + +DnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t); + +DnsServer *manager_set_dns_server(Manager *m, DnsServer *s); +DnsServer *manager_get_dns_server(Manager *m); +void manager_next_dns_server(Manager *m); + +DnssecMode dns_server_get_dnssec_mode(DnsServer *s); +DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s); + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref); + +extern const struct hash_ops dns_server_hash_ops; + +void dns_server_flush_cache(DnsServer *s); + +void dns_server_reset_features(DnsServer *s); +void dns_server_reset_features_all(DnsServer *s); + +void dns_server_dump(DnsServer *s, FILE *f); + +void dns_server_unref_stream(DnsServer *s); + +DnsScope *dns_server_scope(DnsServer *s); diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c new file mode 100644 index 00000000..2a106949 --- /dev/null +++ b/src/resolve/resolved-dns-stream.c @@ -0,0 +1,600 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "io-util.h" +#include "missing_network.h" +#include "resolved-dns-stream.h" + +#define DNS_STREAM_TIMEOUT_USEC (10 * USEC_PER_SEC) +#define DNS_STREAMS_MAX 128 + +#define DNS_QUERIES_PER_STREAM 32 + +static void dns_stream_stop(DnsStream *s) { + assert(s); + + s->io_event_source = sd_event_source_unref(s->io_event_source); + s->timeout_event_source = sd_event_source_unref(s->timeout_event_source); + s->fd = safe_close(s->fd); + + /* Disconnect us from the server object if we are now not usable anymore */ + dns_stream_detach(s); +} + +static int dns_stream_update_io(DnsStream *s) { + int f = 0; + + assert(s); + + if (s->write_packet && s->n_written < sizeof(s->write_size) + s->write_packet->size) + f |= EPOLLOUT; + else if (!ordered_set_isempty(s->write_queue)) { + dns_packet_unref(s->write_packet); + s->write_packet = ordered_set_steal_first(s->write_queue); + s->write_size = htobe16(s->write_packet->size); + s->n_written = 0; + f |= EPOLLOUT; + } + + /* Let's read a packet if we haven't queued any yet. Except if we already hit a limit of parallel + * queries for this connection. */ + if ((!s->read_packet || s->n_read < sizeof(s->read_size) + s->read_packet->size) && + set_size(s->queries) < DNS_QUERIES_PER_STREAM) + f |= EPOLLIN; + +#if ENABLE_DNS_OVER_TLS + /* For handshake and clean closing purposes, TLS can override requested events */ + if (s->dnstls_events != 0) + f = s->dnstls_events; +#endif + + return sd_event_source_set_io_events(s->io_event_source, f); +} + +static int dns_stream_complete(DnsStream *s, int error) { + _cleanup_(dns_stream_unrefp) _unused_ DnsStream *ref = dns_stream_ref(s); /* Protect stream while we process it */ + + assert(s); + assert(error >= 0); + + /* Error is > 0 when the connection failed for some reason in the network stack. It's == 0 if we sent + * and received exactly one packet each (in the LLMNR client case). */ + +#if ENABLE_DNS_OVER_TLS + if (s->encrypted) { + int r; + + r = dnstls_stream_shutdown(s, error); + if (r != -EAGAIN) + dns_stream_stop(s); + } else +#endif + dns_stream_stop(s); + + dns_stream_detach(s); + + if (s->complete) + s->complete(s, error); + else /* the default action if no completion function is set is to close the stream */ + dns_stream_unref(s); + + return 0; +} + +static int dns_stream_identify(DnsStream *s) { + union { + struct cmsghdr header; /* For alignment */ + uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo)) + + EXTRA_CMSG_SPACE /* kernel appears to require extra space */]; + } control; + struct msghdr mh = {}; + struct cmsghdr *cmsg; + socklen_t sl; + int r; + + assert(s); + + if (s->identified) + return 0; + + /* Query the local side */ + s->local_salen = sizeof(s->local); + r = getsockname(s->fd, &s->local.sa, &s->local_salen); + if (r < 0) + return -errno; + if (s->local.sa.sa_family == AF_INET6 && s->ifindex <= 0) + s->ifindex = s->local.in6.sin6_scope_id; + + /* Query the remote side */ + s->peer_salen = sizeof(s->peer); + r = getpeername(s->fd, &s->peer.sa, &s->peer_salen); + if (r < 0) + return -errno; + if (s->peer.sa.sa_family == AF_INET6 && s->ifindex <= 0) + s->ifindex = s->peer.in6.sin6_scope_id; + + /* Check consistency */ + assert(s->peer.sa.sa_family == s->local.sa.sa_family); + assert(IN_SET(s->peer.sa.sa_family, AF_INET, AF_INET6)); + + /* Query connection meta information */ + sl = sizeof(control); + if (s->peer.sa.sa_family == AF_INET) { + r = getsockopt(s->fd, IPPROTO_IP, IP_PKTOPTIONS, &control, &sl); + if (r < 0) + return -errno; + } else if (s->peer.sa.sa_family == AF_INET6) { + + r = getsockopt(s->fd, IPPROTO_IPV6, IPV6_2292PKTOPTIONS, &control, &sl); + if (r < 0) + return -errno; + } else + return -EAFNOSUPPORT; + + mh.msg_control = &control; + mh.msg_controllen = sl; + + CMSG_FOREACH(cmsg, &mh) { + + if (cmsg->cmsg_level == IPPROTO_IPV6) { + assert(s->peer.sa.sa_family == AF_INET6); + + switch (cmsg->cmsg_type) { + + case IPV6_PKTINFO: { + struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg); + + if (s->ifindex <= 0) + s->ifindex = i->ipi6_ifindex; + break; + } + + case IPV6_HOPLIMIT: + s->ttl = *(int *) CMSG_DATA(cmsg); + break; + } + + } else if (cmsg->cmsg_level == IPPROTO_IP) { + assert(s->peer.sa.sa_family == AF_INET); + + switch (cmsg->cmsg_type) { + + case IP_PKTINFO: { + struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg); + + if (s->ifindex <= 0) + s->ifindex = i->ipi_ifindex; + break; + } + + case IP_TTL: + s->ttl = *(int *) CMSG_DATA(cmsg); + break; + } + } + } + + /* The Linux kernel sets the interface index to the loopback + * device if the connection came from the local host since it + * avoids the routing table in such a case. Let's unset the + * interface index in such a case. */ + if (s->ifindex == LOOPBACK_IFINDEX) + s->ifindex = 0; + + /* If we don't know the interface index still, we look for the + * first local interface with a matching address. Yuck! */ + if (s->ifindex <= 0) + s->ifindex = manager_find_ifindex(s->manager, s->local.sa.sa_family, s->local.sa.sa_family == AF_INET ? (union in_addr_union*) &s->local.in.sin_addr : (union in_addr_union*) &s->local.in6.sin6_addr); + + if (s->protocol == DNS_PROTOCOL_LLMNR && s->ifindex > 0) { + uint32_t ifindex = htobe32(s->ifindex); + + /* Make sure all packets for this connection are sent on the same interface */ + if (s->local.sa.sa_family == AF_INET) { + r = setsockopt(s->fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)); + if (r < 0) + log_debug_errno(errno, "Failed to invoke IP_UNICAST_IF: %m"); + } else if (s->local.sa.sa_family == AF_INET6) { + r = setsockopt(s->fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex)); + if (r < 0) + log_debug_errno(errno, "Failed to invoke IPV6_UNICAST_IF: %m"); + } + } + + s->identified = true; + + return 0; +} + +ssize_t dns_stream_writev(DnsStream *s, const struct iovec *iov, size_t iovcnt, int flags) { + ssize_t m; + + assert(s); + assert(iov); + +#if ENABLE_DNS_OVER_TLS + if (s->encrypted && !(flags & DNS_STREAM_WRITE_TLS_DATA)) { + ssize_t ss; + size_t i; + + m = 0; + for (i = 0; i < iovcnt; i++) { + ss = dnstls_stream_write(s, iov[i].iov_base, iov[i].iov_len); + if (ss < 0) + return ss; + + m += ss; + if (ss != (ssize_t) iov[i].iov_len) + continue; + } + } else +#endif + if (s->tfo_salen > 0) { + struct msghdr hdr = { + .msg_iov = (struct iovec*) iov, + .msg_iovlen = iovcnt, + .msg_name = &s->tfo_address.sa, + .msg_namelen = s->tfo_salen + }; + + m = sendmsg(s->fd, &hdr, MSG_FASTOPEN); + if (m < 0) { + if (errno == EOPNOTSUPP) { + s->tfo_salen = 0; + if (connect(s->fd, &s->tfo_address.sa, s->tfo_salen) < 0) + return -errno; + + return -EAGAIN; + } + if (errno == EINPROGRESS) + return -EAGAIN; + + return -errno; + } else + s->tfo_salen = 0; /* connection is made */ + } else { + m = writev(s->fd, iov, iovcnt); + if (m < 0) + return -errno; + } + + return m; +} + +static ssize_t dns_stream_read(DnsStream *s, void *buf, size_t count) { + ssize_t ss; + +#if ENABLE_DNS_OVER_TLS + if (s->encrypted) + ss = dnstls_stream_read(s, buf, count); + else +#endif + { + ss = read(s->fd, buf, count); + if (ss < 0) + return -errno; + } + + return ss; +} + +static int on_stream_timeout(sd_event_source *es, usec_t usec, void *userdata) { + DnsStream *s = userdata; + + assert(s); + + return dns_stream_complete(s, ETIMEDOUT); +} + +static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + _cleanup_(dns_stream_unrefp) DnsStream *s = dns_stream_ref(userdata); /* Protect stream while we process it */ + bool progressed = false; + int r; + + assert(s); + +#if ENABLE_DNS_OVER_TLS + if (s->encrypted) { + r = dnstls_stream_on_io(s, revents); + if (r == DNSTLS_STREAM_CLOSED) + return 0; + if (r == -EAGAIN) + return dns_stream_update_io(s); + if (r < 0) + return dns_stream_complete(s, -r); + + r = dns_stream_update_io(s); + if (r < 0) + return r; + } +#endif + + /* only identify after connecting */ + if (s->tfo_salen == 0) { + r = dns_stream_identify(s); + if (r < 0) + return dns_stream_complete(s, -r); + } + + if ((revents & EPOLLOUT) && + s->write_packet && + s->n_written < sizeof(s->write_size) + s->write_packet->size) { + + struct iovec iov[2]; + ssize_t ss; + + iov[0] = IOVEC_MAKE(&s->write_size, sizeof(s->write_size)); + iov[1] = IOVEC_MAKE(DNS_PACKET_DATA(s->write_packet), s->write_packet->size); + + IOVEC_INCREMENT(iov, 2, s->n_written); + + ss = dns_stream_writev(s, iov, 2, 0); + if (ss < 0) { + if (!IN_SET(-ss, EINTR, EAGAIN)) + return dns_stream_complete(s, -ss); + } else { + progressed = true; + s->n_written += ss; + } + + /* Are we done? If so, disable the event source for EPOLLOUT */ + if (s->n_written >= sizeof(s->write_size) + s->write_packet->size) { + r = dns_stream_update_io(s); + if (r < 0) + return dns_stream_complete(s, -r); + } + } + + if ((revents & (EPOLLIN|EPOLLHUP|EPOLLRDHUP)) && + (!s->read_packet || + s->n_read < sizeof(s->read_size) + s->read_packet->size)) { + + if (s->n_read < sizeof(s->read_size)) { + ssize_t ss; + + ss = dns_stream_read(s, (uint8_t*) &s->read_size + s->n_read, sizeof(s->read_size) - s->n_read); + if (ss < 0) { + if (!IN_SET(-ss, EINTR, EAGAIN)) + return dns_stream_complete(s, -ss); + } else if (ss == 0) + return dns_stream_complete(s, ECONNRESET); + else { + progressed = true; + s->n_read += ss; + } + } + + if (s->n_read >= sizeof(s->read_size)) { + + if (be16toh(s->read_size) < DNS_PACKET_HEADER_SIZE) + return dns_stream_complete(s, EBADMSG); + + if (s->n_read < sizeof(s->read_size) + be16toh(s->read_size)) { + ssize_t ss; + + if (!s->read_packet) { + r = dns_packet_new(&s->read_packet, s->protocol, be16toh(s->read_size), DNS_PACKET_SIZE_MAX); + if (r < 0) + return dns_stream_complete(s, -r); + + s->read_packet->size = be16toh(s->read_size); + s->read_packet->ipproto = IPPROTO_TCP; + s->read_packet->family = s->peer.sa.sa_family; + s->read_packet->ttl = s->ttl; + s->read_packet->ifindex = s->ifindex; + + if (s->read_packet->family == AF_INET) { + s->read_packet->sender.in = s->peer.in.sin_addr; + s->read_packet->sender_port = be16toh(s->peer.in.sin_port); + s->read_packet->destination.in = s->local.in.sin_addr; + s->read_packet->destination_port = be16toh(s->local.in.sin_port); + } else { + assert(s->read_packet->family == AF_INET6); + s->read_packet->sender.in6 = s->peer.in6.sin6_addr; + s->read_packet->sender_port = be16toh(s->peer.in6.sin6_port); + s->read_packet->destination.in6 = s->local.in6.sin6_addr; + s->read_packet->destination_port = be16toh(s->local.in6.sin6_port); + + if (s->read_packet->ifindex == 0) + s->read_packet->ifindex = s->peer.in6.sin6_scope_id; + if (s->read_packet->ifindex == 0) + s->read_packet->ifindex = s->local.in6.sin6_scope_id; + } + } + + ss = dns_stream_read(s, + (uint8_t*) DNS_PACKET_DATA(s->read_packet) + s->n_read - sizeof(s->read_size), + sizeof(s->read_size) + be16toh(s->read_size) - s->n_read); + if (ss < 0) { + if (!IN_SET(-ss, EINTR, EAGAIN)) + return dns_stream_complete(s, -ss); + } else if (ss == 0) + return dns_stream_complete(s, ECONNRESET); + else + s->n_read += ss; + } + + /* Are we done? If so, disable the event source for EPOLLIN */ + if (s->n_read >= sizeof(s->read_size) + be16toh(s->read_size)) { + /* If there's a packet handler + * installed, call that. Note that + * this is optional... */ + if (s->on_packet) { + r = s->on_packet(s); + if (r < 0) + return r; + } + + r = dns_stream_update_io(s); + if (r < 0) + return dns_stream_complete(s, -r); + } + } + } + + /* Call "complete" callback if finished reading and writing one packet, and there's nothing else left + * to write. */ + if (s->type == DNS_STREAM_LLMNR_SEND && + (s->write_packet && s->n_written >= sizeof(s->write_size) + s->write_packet->size) && + ordered_set_isempty(s->write_queue) && + (s->read_packet && s->n_read >= sizeof(s->read_size) + s->read_packet->size)) + return dns_stream_complete(s, 0); + + /* If we did something, let's restart the timeout event source */ + if (progressed && s->timeout_event_source) { + r = sd_event_source_set_time(s->timeout_event_source, now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC); + if (r < 0) + log_warning_errno(errno, "Couldn't restart TCP connection timeout, ignoring: %m"); + } + + return 0; +} + +static DnsStream *dns_stream_free(DnsStream *s) { + DnsPacket *p; + Iterator i; + + assert(s); + + dns_stream_stop(s); + + if (s->manager) { + LIST_REMOVE(streams, s->manager->dns_streams, s); + s->manager->n_dns_streams[s->type]--; + } + +#if ENABLE_DNS_OVER_TLS + if (s->encrypted) + dnstls_stream_free(s); +#endif + + ORDERED_SET_FOREACH(p, s->write_queue, i) + dns_packet_unref(ordered_set_remove(s->write_queue, p)); + + dns_packet_unref(s->write_packet); + dns_packet_unref(s->read_packet); + dns_server_unref(s->server); + + ordered_set_free(s->write_queue); + + return mfree(s); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsStream, dns_stream, dns_stream_free); + +int dns_stream_new( + Manager *m, + DnsStream **ret, + DnsStreamType type, + DnsProtocol protocol, + int fd, + const union sockaddr_union *tfo_address) { + + _cleanup_(dns_stream_unrefp) DnsStream *s = NULL; + int r; + + assert(m); + assert(ret); + assert(type >= 0); + assert(type < _DNS_STREAM_TYPE_MAX); + assert(protocol >= 0); + assert(protocol < _DNS_PROTOCOL_MAX); + assert(fd >= 0); + + if (m->n_dns_streams[type] > DNS_STREAMS_MAX) + return -EBUSY; + + s = new(DnsStream, 1); + if (!s) + return -ENOMEM; + + *s = (DnsStream) { + .n_ref = 1, + .fd = -1, + .protocol = protocol, + .type = type, + }; + + r = ordered_set_ensure_allocated(&s->write_queue, &dns_packet_hash_ops); + if (r < 0) + return r; + + r = sd_event_add_io(m->event, &s->io_event_source, fd, EPOLLIN, on_stream_io, s); + if (r < 0) + return r; + + (void) sd_event_source_set_description(s->io_event_source, "dns-stream-io"); + + r = sd_event_add_time( + m->event, + &s->timeout_event_source, + clock_boottime_or_monotonic(), + now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC, 0, + on_stream_timeout, s); + if (r < 0) + return r; + + (void) sd_event_source_set_description(s->timeout_event_source, "dns-stream-timeout"); + + LIST_PREPEND(streams, m->dns_streams, s); + m->n_dns_streams[type]++; + s->manager = m; + + s->fd = fd; + + if (tfo_address) { + s->tfo_address = *tfo_address; + s->tfo_salen = tfo_address->sa.sa_family == AF_INET6 ? sizeof(tfo_address->in6) : sizeof(tfo_address->in); + } + + *ret = TAKE_PTR(s); + + return 0; +} + +int dns_stream_write_packet(DnsStream *s, DnsPacket *p) { + int r; + + assert(s); + assert(p); + + r = ordered_set_put(s->write_queue, p); + if (r < 0) + return r; + + dns_packet_ref(p); + + return dns_stream_update_io(s); +} + +DnsPacket *dns_stream_take_read_packet(DnsStream *s) { + assert(s); + + if (!s->read_packet) + return NULL; + + if (s->n_read < sizeof(s->read_size)) + return NULL; + + if (s->n_read < sizeof(s->read_size) + be16toh(s->read_size)) + return NULL; + + s->n_read = 0; + return TAKE_PTR(s->read_packet); +} + +void dns_stream_detach(DnsStream *s) { + assert(s); + + if (!s->server) + return; + + if (s->server->stream != s) + return; + + dns_server_unref_stream(s->server); +} diff --git a/src/resolve/resolved-dns-stream.h b/src/resolve/resolved-dns-stream.h new file mode 100644 index 00000000..1013f6e4 --- /dev/null +++ b/src/resolve/resolved-dns-stream.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "socket-util.h" + +typedef struct DnsStream DnsStream; + +typedef enum DnsStreamType { + DNS_STREAM_LOOKUP, /* Outgoing connection to a classic DNS server */ + DNS_STREAM_LLMNR_SEND, /* Outgoing LLMNR TCP lookup */ + DNS_STREAM_LLMNR_RECV, /* Incoming LLMNR TCP lookup */ + DNS_STREAM_STUB, /* Incoming DNS stub connection */ + _DNS_STREAM_TYPE_MAX, + _DNS_STREAM_TYPE_INVALID = -1, +} DnsStreamType; + +#include "resolved-dns-packet.h" +#include "resolved-dns-transaction.h" +#include "resolved-dnstls.h" +#include "resolved-manager.h" + +#define DNS_STREAM_WRITE_TLS_DATA 1 + +/* Streams are used by three subsystems: + * + * 1. The normal transaction logic when doing a DNS or LLMNR lookup via TCP + * 2. The LLMNR logic when accepting a TCP-based lookup + * 3. The DNS stub logic when accepting a TCP-based lookup + */ + +struct DnsStream { + Manager *manager; + unsigned n_ref; + + DnsStreamType type; + DnsProtocol protocol; + + int fd; + union sockaddr_union peer; + socklen_t peer_salen; + union sockaddr_union local; + socklen_t local_salen; + int ifindex; + uint32_t ttl; + bool identified; + + /* only when using TCP fast open */ + union sockaddr_union tfo_address; + socklen_t tfo_salen; + +#if ENABLE_DNS_OVER_TLS + DnsTlsStreamData dnstls_data; + int dnstls_events; +#endif + + sd_event_source *io_event_source; + sd_event_source *timeout_event_source; + + be16_t write_size, read_size; + DnsPacket *write_packet, *read_packet; + size_t n_written, n_read; + OrderedSet *write_queue; + + int (*on_packet)(DnsStream *s); + int (*complete)(DnsStream *s, int error); + + LIST_HEAD(DnsTransaction, transactions); /* when used by the transaction logic */ + DnsServer *server; /* when used by the transaction logic */ + Set *queries; /* when used by the DNS stub logic */ + + /* used when DNS-over-TLS is enabled */ + bool encrypted:1; + + LIST_FIELDS(DnsStream, streams); +}; + +int dns_stream_new(Manager *m, DnsStream **s, DnsStreamType type, DnsProtocol protocol, int fd, const union sockaddr_union *tfo_address); +#if ENABLE_DNS_OVER_TLS +int dns_stream_connect_tls(DnsStream *s, void *tls_session); +#endif +DnsStream *dns_stream_unref(DnsStream *s); +DnsStream *dns_stream_ref(DnsStream *s); + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_unref); + +int dns_stream_write_packet(DnsStream *s, DnsPacket *p); +ssize_t dns_stream_writev(DnsStream *s, const struct iovec *iov, size_t iovcnt, int flags); + +static inline bool DNS_STREAM_QUEUED(DnsStream *s) { + assert(s); + + if (s->fd < 0) /* already stopped? */ + return false; + + return !!s->write_packet; +} + +DnsPacket *dns_stream_take_read_packet(DnsStream *s); + +void dns_stream_detach(DnsStream *s); diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c new file mode 100644 index 00000000..ce994a7e --- /dev/null +++ b/src/resolve/resolved-dns-stub.c @@ -0,0 +1,585 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "errno-util.h" +#include "fd-util.h" +#include "missing_network.h" +#include "resolved-dns-stub.h" +#include "socket-util.h" + +/* The MTU of the loopback device is 64K on Linux, advertise that as maximum datagram size, but subtract the Ethernet, + * IP and UDP header sizes */ +#define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U) + +static int manager_dns_stub_udp_fd(Manager *m); +static int manager_dns_stub_tcp_fd(Manager *m); + +static int dns_stub_make_reply_packet( + DnsPacket **p, + size_t max_size, + DnsQuestion *q, + DnsAnswer *answer, + bool *ret_truncated) { + + bool truncated = false; + DnsResourceRecord *rr; + unsigned c = 0; + int r; + + assert(p); + + /* Note that we don't bother with any additional RRs, as this is stub is for local lookups only, and hence + * roundtrips aren't expensive. */ + + if (!*p) { + r = dns_packet_new(p, DNS_PROTOCOL_DNS, 0, max_size); + if (r < 0) + return r; + + r = dns_packet_append_question(*p, q); + if (r < 0) + return r; + + DNS_PACKET_HEADER(*p)->qdcount = htobe16(dns_question_size(q)); + } + + DNS_ANSWER_FOREACH(rr, answer) { + + r = dns_question_matches_rr(q, rr, NULL); + if (r < 0) + return r; + if (r > 0) + goto add; + + r = dns_question_matches_cname_or_dname(q, rr, NULL); + if (r < 0) + return r; + if (r > 0) + goto add; + + continue; + add: + r = dns_packet_append_rr(*p, rr, 0, NULL, NULL); + if (r == -EMSGSIZE) { + truncated = true; + break; + } + if (r < 0) + return r; + + c++; + } + + if (ret_truncated) + *ret_truncated = truncated; + else if (truncated) + return -EMSGSIZE; + + DNS_PACKET_HEADER(*p)->ancount = htobe16(be16toh(DNS_PACKET_HEADER(*p)->ancount) + c); + + return 0; +} + +static int dns_stub_finish_reply_packet( + DnsPacket *p, + uint16_t id, + int rcode, + bool tc, /* set the Truncated bit? */ + bool add_opt, /* add an OPT RR to this packet? */ + bool edns0_do, /* set the EDNS0 DNSSEC OK bit? */ + bool ad) { /* set the DNSSEC authenticated data bit? */ + + int r; + + assert(p); + + if (add_opt) { + r = dns_packet_append_opt(p, ADVERTISE_DATAGRAM_SIZE_MAX, edns0_do, rcode, NULL); + if (r == -EMSGSIZE) /* Hit the size limit? then indicate truncation */ + tc = true; + else if (r < 0) + return r; + + } else { + /* If the client can't to EDNS0, don't do DO either */ + edns0_do = false; + + /* If the client didn't do EDNS, clamp the rcode to 4 bit */ + if (rcode > 0xF) + rcode = DNS_RCODE_SERVFAIL; + } + + /* Don't set the AD bit unless DO is on, too */ + if (!edns0_do) + ad = false; + + DNS_PACKET_HEADER(p)->id = id; + + DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS( + 1 /* qr */, + 0 /* opcode */, + 0 /* aa */, + tc /* tc */, + 1 /* rd */, + 1 /* ra */, + ad /* ad */, + 0 /* cd */, + rcode)); + + return 0; +} + +static int dns_stub_send(Manager *m, DnsStream *s, DnsPacket *p, DnsPacket *reply) { + int r; + + assert(m); + assert(p); + assert(reply); + + if (s) + r = dns_stream_write_packet(s, reply); + else { + int fd; + + fd = manager_dns_stub_udp_fd(m); + if (fd < 0) + return log_debug_errno(fd, "Failed to get reply socket: %m"); + + /* Note that it is essential here that we explicitly choose the source IP address for this packet. This + * is because otherwise the kernel will choose it automatically based on the routing table and will + * thus pick 127.0.0.1 rather than 127.0.0.53. */ + + r = manager_send(m, fd, LOOPBACK_IFINDEX, p->family, &p->sender, p->sender_port, &p->destination, reply); + } + if (r < 0) + return log_debug_errno(r, "Failed to send reply packet: %m"); + + return 0; +} + +static int dns_stub_send_failure(Manager *m, DnsStream *s, DnsPacket *p, int rcode, bool authenticated) { + _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL; + int r; + + assert(m); + assert(p); + + r = dns_stub_make_reply_packet(&reply, DNS_PACKET_PAYLOAD_SIZE_MAX(p), p->question, NULL, NULL); + if (r < 0) + return log_debug_errno(r, "Failed to make failure packet: %m"); + + r = dns_stub_finish_reply_packet(reply, DNS_PACKET_ID(p), rcode, false, !!p->opt, DNS_PACKET_DO(p), authenticated); + if (r < 0) + return log_debug_errno(r, "Failed to build failure packet: %m"); + + return dns_stub_send(m, s, p, reply); +} + +static void dns_stub_query_complete(DnsQuery *q) { + int r; + + assert(q); + assert(q->request_dns_packet); + + switch (q->state) { + + case DNS_TRANSACTION_SUCCESS: { + bool truncated; + + r = dns_stub_make_reply_packet(&q->reply_dns_packet, DNS_PACKET_PAYLOAD_SIZE_MAX(q->request_dns_packet), q->question_idna, q->answer, &truncated); + if (r < 0) { + log_debug_errno(r, "Failed to build reply packet: %m"); + break; + } + + if (!truncated) { + r = dns_query_process_cname(q); + if (r == -ELOOP) { + (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false); + break; + } + if (r < 0) { + log_debug_errno(r, "Failed to process CNAME: %m"); + break; + } + if (r == DNS_QUERY_RESTARTED) + return; + } + + r = dns_stub_finish_reply_packet( + q->reply_dns_packet, + DNS_PACKET_ID(q->request_dns_packet), + q->answer_rcode, + truncated, + !!q->request_dns_packet->opt, + DNS_PACKET_DO(q->request_dns_packet), + dns_query_fully_authenticated(q)); + if (r < 0) { + log_debug_errno(r, "Failed to finish reply packet: %m"); + break; + } + + (void) dns_stub_send(q->manager, q->request_dns_stream, q->request_dns_packet, q->reply_dns_packet); + break; + } + + case DNS_TRANSACTION_RCODE_FAILURE: + (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, q->answer_rcode, dns_query_fully_authenticated(q)); + break; + + case DNS_TRANSACTION_NOT_FOUND: + (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_NXDOMAIN, dns_query_fully_authenticated(q)); + break; + + case DNS_TRANSACTION_TIMEOUT: + case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED: + /* Propagate a timeout as a no packet, i.e. that the client also gets a timeout */ + break; + + case DNS_TRANSACTION_NO_SERVERS: + case DNS_TRANSACTION_INVALID_REPLY: + case DNS_TRANSACTION_ERRNO: + case DNS_TRANSACTION_ABORTED: + case DNS_TRANSACTION_DNSSEC_FAILED: + case DNS_TRANSACTION_NO_TRUST_ANCHOR: + case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED: + case DNS_TRANSACTION_NETWORK_DOWN: + (void) dns_stub_send_failure(q->manager, q->request_dns_stream, q->request_dns_packet, DNS_RCODE_SERVFAIL, false); + break; + + case DNS_TRANSACTION_NULL: + case DNS_TRANSACTION_PENDING: + case DNS_TRANSACTION_VALIDATING: + default: + assert_not_reached("Impossible state"); + } + + dns_query_free(q); +} + +static int dns_stub_stream_complete(DnsStream *s, int error) { + assert(s); + + log_debug_errno(error, "DNS TCP connection terminated, destroying queries: %m"); + + for (;;) { + DnsQuery *q; + + q = set_first(s->queries); + if (!q) + break; + + dns_query_free(q); + } + + /* This drops the implicit ref we keep around since it was allocated, as incoming stub connections + * should be kept as long as the client wants to. */ + dns_stream_unref(s); + return 0; +} + +static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) { + DnsQuery *q = NULL; + int r; + + assert(m); + assert(p); + assert(p->protocol == DNS_PROTOCOL_DNS); + + if (in_addr_is_localhost(p->family, &p->sender) <= 0 || + in_addr_is_localhost(p->family, &p->destination) <= 0) { + log_error("Got packet on unexpected IP range, refusing."); + dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false); + goto fail; + } + + r = dns_packet_extract(p); + if (r < 0) { + log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m"); + dns_stub_send_failure(m, s, p, DNS_RCODE_FORMERR, false); + goto fail; + } + + if (!DNS_PACKET_VERSION_SUPPORTED(p)) { + log_debug("Got EDNS OPT field with unsupported version number."); + dns_stub_send_failure(m, s, p, DNS_RCODE_BADVERS, false); + goto fail; + } + + if (dns_type_is_obsolete(p->question->keys[0]->type)) { + log_debug("Got message with obsolete key type, refusing."); + dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false); + goto fail; + } + + if (dns_type_is_zone_transer(p->question->keys[0]->type)) { + log_debug("Got request for zone transfer, refusing."); + dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false); + goto fail; + } + + if (!DNS_PACKET_RD(p)) { + /* If the "rd" bit is off (i.e. recursion was not requested), then refuse operation */ + log_debug("Got request with recursion disabled, refusing."); + dns_stub_send_failure(m, s, p, DNS_RCODE_REFUSED, false); + goto fail; + } + + if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) { + log_debug("Got request with DNSSEC CD bit set, refusing."); + dns_stub_send_failure(m, s, p, DNS_RCODE_NOTIMP, false); + goto fail; + } + + r = dns_query_new(m, &q, p->question, p->question, 0, SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_SEARCH); + if (r < 0) { + log_error_errno(r, "Failed to generate query object: %m"); + dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false); + goto fail; + } + + /* Request that the TTL is corrected by the cached time for this lookup, so that we return vaguely useful TTLs */ + q->clamp_ttl = true; + + q->request_dns_packet = dns_packet_ref(p); + q->request_dns_stream = dns_stream_ref(s); /* make sure the stream stays around until we can send a reply through it */ + q->complete = dns_stub_query_complete; + + if (s) { + /* Remember which queries belong to this stream, so that we can cancel them when the stream + * is disconnected early */ + + r = set_ensure_allocated(&s->queries, &trivial_hash_ops); + if (r < 0) { + log_oom(); + goto fail; + } + + if (set_put(s->queries, q) < 0) { + log_oom(); + goto fail; + } + } + + r = dns_query_go(q); + if (r < 0) { + log_error_errno(r, "Failed to start query: %m"); + dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false); + goto fail; + } + + log_debug("Processing query..."); + return; + +fail: + dns_query_free(q); +} + +static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + Manager *m = userdata; + int r; + + r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p); + if (r <= 0) + return r; + + if (dns_packet_validate_query(p) > 0) { + log_debug("Got DNS stub UDP query packet for id %u", DNS_PACKET_ID(p)); + + dns_stub_process_query(m, NULL, p); + } else + log_debug("Invalid DNS stub UDP packet, ignoring."); + + return 0; +} + +static int manager_dns_stub_udp_fd(Manager *m) { + union sockaddr_union sa = { + .in.sin_family = AF_INET, + .in.sin_port = htobe16(53), + .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB), + }; + _cleanup_close_ int fd = -1; + int r; + + if (m->dns_stub_udp_fd >= 0) + return m->dns_stub_udp_fd; + + fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return -errno; + + r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return r; + + r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true); + if (r < 0) + return r; + + r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true); + if (r < 0) + return r; + + /* Make sure no traffic from outside the local host can leak to onto this socket */ + r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX); + if (r < 0) + return r; + + if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) + return -errno; + + r = sd_event_add_io(m->event, &m->dns_stub_udp_event_source, fd, EPOLLIN, on_dns_stub_packet, m); + if (r < 0) + return r; + + (void) sd_event_source_set_description(m->dns_stub_udp_event_source, "dns-stub-udp"); + + return m->dns_stub_udp_fd = TAKE_FD(fd); +} + +static int on_dns_stub_stream_packet(DnsStream *s) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + + assert(s); + + p = dns_stream_take_read_packet(s); + assert(p); + + if (dns_packet_validate_query(p) > 0) { + log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(p)); + + dns_stub_process_query(s->manager, s, p); + } else + log_debug("Invalid DNS stub TCP packet, ignoring."); + + return 0; +} + +static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + DnsStream *stream; + Manager *m = userdata; + int cfd, r; + + cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); + if (cfd < 0) { + if (ERRNO_IS_ACCEPT_AGAIN(errno)) + return 0; + + return -errno; + } + + r = dns_stream_new(m, &stream, DNS_STREAM_STUB, DNS_PROTOCOL_DNS, cfd, NULL); + if (r < 0) { + safe_close(cfd); + return r; + } + + stream->on_packet = on_dns_stub_stream_packet; + stream->complete = dns_stub_stream_complete; + + /* We let the reference to the stream dangle here, it will be dropped later by the complete callback. */ + + return 0; +} + +static int manager_dns_stub_tcp_fd(Manager *m) { + union sockaddr_union sa = { + .in.sin_family = AF_INET, + .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB), + .in.sin_port = htobe16(53), + }; + _cleanup_close_ int fd = -1; + int r; + + if (m->dns_stub_tcp_fd >= 0) + return m->dns_stub_tcp_fd; + + fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return -errno; + + r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true); + if (r < 0) + return r; + + r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return r; + + r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true); + if (r < 0) + return r; + + r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true); + if (r < 0) + return r; + + /* Make sure no traffic from outside the local host can leak to onto this socket */ + r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX); + if (r < 0) + return r; + + if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) + return -errno; + + if (listen(fd, SOMAXCONN) < 0) + return -errno; + + r = sd_event_add_io(m->event, &m->dns_stub_tcp_event_source, fd, EPOLLIN, on_dns_stub_stream, m); + if (r < 0) + return r; + + (void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp"); + + return m->dns_stub_tcp_fd = TAKE_FD(fd); +} + +int manager_dns_stub_start(Manager *m) { + const char *t = "UDP"; + int r = 0; + + assert(m); + + if (m->dns_stub_listener_mode == DNS_STUB_LISTENER_NO) + log_debug("Not creating stub listener."); + else + log_debug("Creating stub listener using %s.", + m->dns_stub_listener_mode == DNS_STUB_LISTENER_UDP ? "UDP" : + m->dns_stub_listener_mode == DNS_STUB_LISTENER_TCP ? "TCP" : + "UDP/TCP"); + + if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP)) + r = manager_dns_stub_udp_fd(m); + + if (r >= 0 && + IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) { + t = "TCP"; + r = manager_dns_stub_tcp_fd(m); + } + + if (IN_SET(r, -EADDRINUSE, -EPERM)) { + if (r == -EADDRINUSE) + log_warning_errno(r, + "Another process is already listening on %s socket 127.0.0.53:53.\n" + "Turning off local DNS stub support.", t); + else + log_warning_errno(r, + "Failed to listen on %s socket 127.0.0.53:53: %m.\n" + "Turning off local DNS stub support.", t); + manager_dns_stub_stop(m); + } else if (r < 0) + return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t); + + return 0; +} + +void manager_dns_stub_stop(Manager *m) { + assert(m); + + m->dns_stub_udp_event_source = sd_event_source_unref(m->dns_stub_udp_event_source); + m->dns_stub_tcp_event_source = sd_event_source_unref(m->dns_stub_tcp_event_source); + + m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd); + m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd); +} diff --git a/src/resolve/resolved-dns-stub.h b/src/resolve/resolved-dns-stub.h new file mode 100644 index 00000000..f34e9db1 --- /dev/null +++ b/src/resolve/resolved-dns-stub.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "resolved-manager.h" + +void manager_dns_stub_stop(Manager *m); +int manager_dns_stub_start(Manager *m); diff --git a/src/resolve/resolved-dns-synthesize.c b/src/resolve/resolved-dns-synthesize.c new file mode 100644 index 00000000..f65116c3 --- /dev/null +++ b/src/resolve/resolved-dns-synthesize.c @@ -0,0 +1,434 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "hostname-util.h" +#include "local-addresses.h" +#include "missing_network.h" +#include "resolved-dns-synthesize.h" + +int dns_synthesize_ifindex(int ifindex) { + + /* When the caller asked for resolving on a specific + * interface, we synthesize the answer for that + * interface. However, if nothing specific was claimed and we + * only return localhost RRs, we synthesize the answer for + * localhost. */ + + if (ifindex > 0) + return ifindex; + + return LOOPBACK_IFINDEX; +} + +int dns_synthesize_family(uint64_t flags) { + + /* Picks an address family depending on set flags. This is + * purely for synthesized answers, where the family we return + * for the reply should match what was requested in the + * question, even though we are synthesizing the answer + * here. */ + + if (!(flags & SD_RESOLVED_DNS)) { + if (flags & (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_MDNS_IPV4)) + return AF_INET; + if (flags & (SD_RESOLVED_LLMNR_IPV6|SD_RESOLVED_MDNS_IPV6)) + return AF_INET6; + } + + return AF_UNSPEC; +} + +DnsProtocol dns_synthesize_protocol(uint64_t flags) { + + /* Similar as dns_synthesize_family() but does this for the + * protocol. If resolving via DNS was requested, we claim it + * was DNS. Similar, if nothing specific was + * requested. However, if only resolving via LLMNR was + * requested we return that. */ + + if (flags & SD_RESOLVED_DNS) + return DNS_PROTOCOL_DNS; + if (flags & SD_RESOLVED_LLMNR) + return DNS_PROTOCOL_LLMNR; + if (flags & SD_RESOLVED_MDNS) + return DNS_PROTOCOL_MDNS; + + return DNS_PROTOCOL_DNS; +} + +static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) { + int r; + + assert(m); + assert(key); + assert(answer); + + r = dns_answer_reserve(answer, 2); + if (r < 0) + return r; + + if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + + rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, dns_resource_key_name(key)); + if (!rr) + return -ENOMEM; + + rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK); + + r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + } + + if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + + rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, dns_resource_key_name(key)); + if (!rr) + return -ENOMEM; + + rr->aaaa.in6_addr = in6addr_loopback; + + r = dns_answer_add(*answer, rr, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + } + + return 0; +} + +static int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex, DnsAnswerFlags flags) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + + rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from); + if (!rr) + return -ENOMEM; + + rr->ptr.name = strdup(to); + if (!rr->ptr.name) + return -ENOMEM; + + return dns_answer_add(*answer, rr, ifindex, flags); +} + +static int synthesize_localhost_ptr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) { + int r; + + assert(m); + assert(key); + assert(answer); + + if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) { + r = dns_answer_reserve(answer, 1); + if (r < 0) + return r; + + r = answer_add_ptr(answer, dns_resource_key_name(key), "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + } + + return 0; +} + +static int answer_add_addresses_rr( + DnsAnswer **answer, + const char *name, + struct local_address *addresses, + unsigned n_addresses) { + + unsigned j; + int r; + + assert(answer); + assert(name); + + r = dns_answer_reserve(answer, n_addresses); + if (r < 0) + return r; + + for (j = 0; j < n_addresses; j++) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + + r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name); + if (r < 0) + return r; + + r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + } + + return 0; +} + +static int answer_add_addresses_ptr( + DnsAnswer **answer, + const char *name, + struct local_address *addresses, + unsigned n_addresses, + int af, const union in_addr_union *match) { + + bool added = false; + unsigned j; + int r; + + assert(answer); + assert(name); + + for (j = 0; j < n_addresses; j++) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + + if (af != AF_UNSPEC) { + + if (addresses[j].family != af) + continue; + + if (match && !in_addr_equal(af, match, &addresses[j].address)) + continue; + } + + r = dns_answer_reserve(answer, 1); + if (r < 0) + return r; + + r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name); + if (r < 0) + return r; + + r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + + added = true; + } + + return added; +} + +static int synthesize_system_hostname_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) { + _cleanup_free_ struct local_address *addresses = NULL; + int n = 0, af; + + assert(m); + assert(key); + assert(answer); + + af = dns_type_to_af(key->type); + if (af >= 0) { + n = local_addresses(m->rtnl, ifindex, af, &addresses); + if (n < 0) + return n; + + if (n == 0) { + struct local_address buffer[2]; + + /* If we have no local addresses then use ::1 + * and 127.0.0.2 as local ones. */ + + if (IN_SET(af, AF_INET, AF_UNSPEC)) + buffer[n++] = (struct local_address) { + .family = AF_INET, + .ifindex = dns_synthesize_ifindex(ifindex), + .address.in.s_addr = htobe32(0x7F000002), + }; + + if (IN_SET(af, AF_INET6, AF_UNSPEC)) + buffer[n++] = (struct local_address) { + .family = AF_INET6, + .ifindex = dns_synthesize_ifindex(ifindex), + .address.in6 = in6addr_loopback, + }; + + return answer_add_addresses_rr(answer, + dns_resource_key_name(key), + buffer, n); + } + } + + return answer_add_addresses_rr(answer, dns_resource_key_name(key), addresses, n); +} + +static int synthesize_system_hostname_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) { + _cleanup_free_ struct local_address *addresses = NULL; + bool added = false; + int n, r; + + assert(m); + assert(address); + assert(answer); + + if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) { + + /* Always map the IPv4 address 127.0.0.2 to the local hostname, in addition to "localhost": */ + + r = dns_answer_reserve(answer, 4); + if (r < 0) + return r; + + r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->full_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + + r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->llmnr_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + + r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->mdns_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + + r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + + return 1; + } + + n = local_addresses(m->rtnl, ifindex, af, &addresses); + if (n <= 0) + return n; + + r = answer_add_addresses_ptr(answer, m->full_hostname, addresses, n, af, address); + if (r < 0) + return r; + if (r > 0) + added = true; + + r = answer_add_addresses_ptr(answer, m->llmnr_hostname, addresses, n, af, address); + if (r < 0) + return r; + if (r > 0) + added = true; + + r = answer_add_addresses_ptr(answer, m->mdns_hostname, addresses, n, af, address); + if (r < 0) + return r; + if (r > 0) + added = true; + + return added; +} + +static int synthesize_gateway_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) { + _cleanup_free_ struct local_address *addresses = NULL; + int n = 0, af, r; + + assert(m); + assert(key); + assert(answer); + + af = dns_type_to_af(key->type); + if (af >= 0) { + n = local_gateways(m->rtnl, ifindex, af, &addresses); + if (n <= 0) + return n; /* < 0 means: error; == 0 means we have no gateway */ + } + + r = answer_add_addresses_rr(answer, dns_resource_key_name(key), addresses, n); + if (r < 0) + return r; + + return 1; /* > 0 means: we have some gateway */ +} + +static int synthesize_gateway_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) { + _cleanup_free_ struct local_address *addresses = NULL; + int n; + + assert(m); + assert(address); + assert(answer); + + n = local_gateways(m->rtnl, ifindex, af, &addresses); + if (n <= 0) + return n; + + return answer_add_addresses_ptr(answer, "_gateway", addresses, n, af, address); +} + +int dns_synthesize_answer( + Manager *m, + DnsQuestion *q, + int ifindex, + DnsAnswer **ret) { + + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + DnsResourceKey *key; + bool found = false, nxdomain = false; + int r; + + assert(m); + assert(q); + + DNS_QUESTION_FOREACH(key, q) { + union in_addr_union address; + const char *name; + int af; + + if (!IN_SET(key->class, DNS_CLASS_IN, DNS_CLASS_ANY)) + continue; + + name = dns_resource_key_name(key); + + if (is_localhost(name)) { + + r = synthesize_localhost_rr(m, key, ifindex, &answer); + if (r < 0) + return log_error_errno(r, "Failed to synthesize localhost RRs: %m"); + + } else if (manager_is_own_hostname(m, name)) { + + r = synthesize_system_hostname_rr(m, key, ifindex, &answer); + if (r < 0) + return log_error_errno(r, "Failed to synthesize system hostname RRs: %m"); + + } else if (is_gateway_hostname(name)) { + + r = synthesize_gateway_rr(m, key, ifindex, &answer); + if (r < 0) + return log_error_errno(r, "Failed to synthesize gateway RRs: %m"); + if (r == 0) { /* if we have no gateway return NXDOMAIN */ + nxdomain = true; + continue; + } + + } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) || + dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) { + + r = synthesize_localhost_ptr(m, key, ifindex, &answer); + if (r < 0) + return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m"); + + } else if (dns_name_address(name, &af, &address) > 0) { + int v, w; + + v = synthesize_system_hostname_ptr(m, af, &address, ifindex, &answer); + if (v < 0) + return log_error_errno(v, "Failed to synthesize system hostname PTR RR: %m"); + + w = synthesize_gateway_ptr(m, af, &address, ifindex, &answer); + if (w < 0) + return log_error_errno(w, "Failed to synthesize gateway hostname PTR RR: %m"); + + if (v == 0 && w == 0) /* This IP address is neither a local one nor a gateway */ + continue; + + } else + continue; + + found = true; + } + + if (found) { + + if (ret) + *ret = TAKE_PTR(answer); + + return 1; + } else if (nxdomain) + return -ENXIO; + + return 0; +} diff --git a/src/resolve/resolved-dns-synthesize.h b/src/resolve/resolved-dns-synthesize.h new file mode 100644 index 00000000..0d9d17ba --- /dev/null +++ b/src/resolve/resolved-dns-synthesize.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "resolved-dns-answer.h" +#include "resolved-dns-question.h" +#include "resolved-manager.h" + +int dns_synthesize_ifindex(int ifindex); +int dns_synthesize_family(uint64_t flags); +DnsProtocol dns_synthesize_protocol(uint64_t flags); + +int dns_synthesize_answer(Manager *m, DnsQuestion *q, int ifindex, DnsAnswer **ret); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c new file mode 100644 index 00000000..fb54d160 --- /dev/null +++ b/src/resolve/resolved-dns-transaction.c @@ -0,0 +1,3279 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-messages.h" + +#include "af-list.h" +#include "alloc-util.h" +#include "dns-domain.h" +#include "errno-list.h" +#include "errno-util.h" +#include "fd-util.h" +#include "random-util.h" +#include "resolved-dns-cache.h" +#include "resolved-dns-transaction.h" +#include "resolved-dnstls.h" +#include "resolved-llmnr.h" +#include "string-table.h" + +#define TRANSACTIONS_MAX 4096 +#define TRANSACTION_TCP_TIMEOUT_USEC (10U*USEC_PER_SEC) + +/* After how much time to repeat classic DNS requests */ +#define DNS_TIMEOUT_USEC (SD_RESOLVED_QUERY_TIMEOUT_USEC / DNS_TRANSACTION_ATTEMPTS_MAX) + +static void dns_transaction_reset_answer(DnsTransaction *t) { + assert(t); + + t->received = dns_packet_unref(t->received); + t->answer = dns_answer_unref(t->answer); + t->answer_rcode = 0; + t->answer_dnssec_result = _DNSSEC_RESULT_INVALID; + t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID; + t->answer_authenticated = false; + t->answer_nsec_ttl = (uint32_t) -1; + t->answer_errno = 0; +} + +static void dns_transaction_flush_dnssec_transactions(DnsTransaction *t) { + DnsTransaction *z; + + assert(t); + + while ((z = set_steal_first(t->dnssec_transactions))) { + set_remove(z->notify_transactions, t); + set_remove(z->notify_transactions_done, t); + dns_transaction_gc(z); + } +} + +static void dns_transaction_close_connection(DnsTransaction *t) { + assert(t); + + if (t->stream) { + /* Let's detach the stream from our transaction, in case something else keeps a reference to it. */ + LIST_REMOVE(transactions_by_stream, t->stream->transactions, t); + + /* Remove packet in case it's still in the queue */ + dns_packet_unref(ordered_set_remove(t->stream->write_queue, t->sent)); + + t->stream = dns_stream_unref(t->stream); + } + + t->dns_udp_event_source = sd_event_source_unref(t->dns_udp_event_source); + t->dns_udp_fd = safe_close(t->dns_udp_fd); +} + +static void dns_transaction_stop_timeout(DnsTransaction *t) { + assert(t); + + t->timeout_event_source = sd_event_source_unref(t->timeout_event_source); +} + +DnsTransaction* dns_transaction_free(DnsTransaction *t) { + DnsQueryCandidate *c; + DnsZoneItem *i; + DnsTransaction *z; + + if (!t) + return NULL; + + log_debug("Freeing transaction %" PRIu16 ".", t->id); + + dns_transaction_close_connection(t); + dns_transaction_stop_timeout(t); + + dns_packet_unref(t->sent); + dns_transaction_reset_answer(t); + + dns_server_unref(t->server); + + if (t->scope) { + hashmap_remove_value(t->scope->transactions_by_key, t->key, t); + LIST_REMOVE(transactions_by_scope, t->scope->transactions, t); + + if (t->id != 0) + hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id)); + } + + while ((c = set_steal_first(t->notify_query_candidates))) + set_remove(c->transactions, t); + set_free(t->notify_query_candidates); + + while ((c = set_steal_first(t->notify_query_candidates_done))) + set_remove(c->transactions, t); + set_free(t->notify_query_candidates_done); + + while ((i = set_steal_first(t->notify_zone_items))) + i->probe_transaction = NULL; + set_free(t->notify_zone_items); + + while ((i = set_steal_first(t->notify_zone_items_done))) + i->probe_transaction = NULL; + set_free(t->notify_zone_items_done); + + while ((z = set_steal_first(t->notify_transactions))) + set_remove(z->dnssec_transactions, t); + set_free(t->notify_transactions); + + while ((z = set_steal_first(t->notify_transactions_done))) + set_remove(z->dnssec_transactions, t); + set_free(t->notify_transactions_done); + + dns_transaction_flush_dnssec_transactions(t); + set_free(t->dnssec_transactions); + + dns_answer_unref(t->validated_keys); + dns_resource_key_unref(t->key); + + return mfree(t); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free); + +bool dns_transaction_gc(DnsTransaction *t) { + assert(t); + + if (t->block_gc > 0) + return true; + + if (set_isempty(t->notify_query_candidates) && + set_isempty(t->notify_query_candidates_done) && + set_isempty(t->notify_zone_items) && + set_isempty(t->notify_zone_items_done) && + set_isempty(t->notify_transactions) && + set_isempty(t->notify_transactions_done)) { + dns_transaction_free(t); + return false; + } + + return true; +} + +static uint16_t pick_new_id(Manager *m) { + uint16_t new_id; + + /* Find a fresh, unused transaction id. Note that this loop is bounded because there's a limit on the number of + * transactions, and it's much lower than the space of IDs. */ + + assert_cc(TRANSACTIONS_MAX < 0xFFFF); + + do + random_bytes(&new_id, sizeof(new_id)); + while (new_id == 0 || + hashmap_get(m->dns_transactions, UINT_TO_PTR(new_id))); + + return new_id; +} + +int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key) { + _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL; + int r; + + assert(ret); + assert(s); + assert(key); + + /* Don't allow looking up invalid or pseudo RRs */ + if (!dns_type_is_valid_query(key->type)) + return -EINVAL; + if (dns_type_is_obsolete(key->type)) + return -EOPNOTSUPP; + + /* We only support the IN class */ + if (!IN_SET(key->class, DNS_CLASS_IN, DNS_CLASS_ANY)) + return -EOPNOTSUPP; + + if (hashmap_size(s->manager->dns_transactions) >= TRANSACTIONS_MAX) + return -EBUSY; + + r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&s->transactions_by_key, &dns_resource_key_hash_ops); + if (r < 0) + return r; + + t = new0(DnsTransaction, 1); + if (!t) + return -ENOMEM; + + t->dns_udp_fd = -1; + t->answer_source = _DNS_TRANSACTION_SOURCE_INVALID; + t->answer_dnssec_result = _DNSSEC_RESULT_INVALID; + t->answer_nsec_ttl = (uint32_t) -1; + t->key = dns_resource_key_ref(key); + t->current_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID; + t->clamp_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID; + + t->id = pick_new_id(s->manager); + + r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t); + if (r < 0) { + t->id = 0; + return r; + } + + r = hashmap_replace(s->transactions_by_key, t->key, t); + if (r < 0) { + hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id)); + return r; + } + + LIST_PREPEND(transactions_by_scope, s->transactions, t); + t->scope = s; + + s->manager->n_transactions_total++; + + if (ret) + *ret = t; + + t = NULL; + + return 0; +} + +static void dns_transaction_shuffle_id(DnsTransaction *t) { + uint16_t new_id; + assert(t); + + /* Pick a new ID for this transaction. */ + + new_id = pick_new_id(t->scope->manager); + assert_se(hashmap_remove_and_put(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id), UINT_TO_PTR(new_id), t) >= 0); + + log_debug("Transaction %" PRIu16 " is now %" PRIu16 ".", t->id, new_id); + t->id = new_id; + + /* Make sure we generate a new packet with the new ID */ + t->sent = dns_packet_unref(t->sent); +} + +static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) { + _cleanup_free_ char *pretty = NULL; + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + DnsZoneItem *z; + + assert(t); + assert(p); + + if (manager_our_packet(t->scope->manager, p) != 0) + return; + + (void) in_addr_to_string(p->family, &p->sender, &pretty); + + log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s got tentative packet from %s.", + t->id, + dns_resource_key_to_string(t->key, key_str, sizeof key_str), + dns_protocol_to_string(t->scope->protocol), + t->scope->link ? t->scope->link->ifname : "*", + af_to_name_short(t->scope->family), + strnull(pretty)); + + /* RFC 4795, Section 4.1 says that the peer with the + * lexicographically smaller IP address loses */ + if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) { + log_debug("Peer has lexicographically larger IP address and thus lost in the conflict."); + return; + } + + log_debug("We have the lexicographically larger IP address and thus lost in the conflict."); + + t->block_gc++; + + while ((z = set_first(t->notify_zone_items))) { + /* First, make sure the zone item drops the reference + * to us */ + dns_zone_item_probe_stop(z); + + /* Secondly, report this as conflict, so that we might + * look for a different hostname */ + dns_zone_item_conflict(z); + } + t->block_gc--; + + dns_transaction_gc(t); +} + +void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) { + DnsQueryCandidate *c; + DnsZoneItem *z; + DnsTransaction *d; + const char *st; + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + + assert(t); + assert(!DNS_TRANSACTION_IS_LIVE(state)); + + if (state == DNS_TRANSACTION_DNSSEC_FAILED) { + dns_resource_key_to_string(t->key, key_str, sizeof key_str); + + log_struct(LOG_NOTICE, + "MESSAGE_ID=" SD_MESSAGE_DNSSEC_FAILURE_STR, + LOG_MESSAGE("DNSSEC validation failed for question %s: %s", key_str, dnssec_result_to_string(t->answer_dnssec_result)), + "DNS_TRANSACTION=%" PRIu16, t->id, + "DNS_QUESTION=%s", key_str, + "DNSSEC_RESULT=%s", dnssec_result_to_string(t->answer_dnssec_result), + "DNS_SERVER=%s", dns_server_string(t->server), + "DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(t->server->possible_feature_level)); + } + + /* Note that this call might invalidate the query. Callers + * should hence not attempt to access the query or transaction + * after calling this function. */ + + if (state == DNS_TRANSACTION_ERRNO) + st = errno_to_name(t->answer_errno); + else + st = dns_transaction_state_to_string(state); + + log_debug("Transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s).", + t->id, + dns_resource_key_to_string(t->key, key_str, sizeof key_str), + dns_protocol_to_string(t->scope->protocol), + t->scope->link ? t->scope->link->ifname : "*", + af_to_name_short(t->scope->family), + st, + t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source), + t->answer_authenticated ? "authenticated" : "unsigned"); + + t->state = state; + + dns_transaction_close_connection(t); + dns_transaction_stop_timeout(t); + + /* Notify all queries that are interested, but make sure the + * transaction isn't freed while we are still looking at it */ + t->block_gc++; + + SET_FOREACH_MOVE(c, t->notify_query_candidates_done, t->notify_query_candidates) + dns_query_candidate_notify(c); + SWAP_TWO(t->notify_query_candidates, t->notify_query_candidates_done); + + SET_FOREACH_MOVE(z, t->notify_zone_items_done, t->notify_zone_items) + dns_zone_item_notify(z); + SWAP_TWO(t->notify_zone_items, t->notify_zone_items_done); + if (t->probing && t->state == DNS_TRANSACTION_ATTEMPTS_MAX_REACHED) + (void) dns_scope_announce(t->scope, false); + + SET_FOREACH_MOVE(d, t->notify_transactions_done, t->notify_transactions) + dns_transaction_notify(d, t); + SWAP_TWO(t->notify_transactions, t->notify_transactions_done); + + t->block_gc--; + dns_transaction_gc(t); +} + +static int dns_transaction_pick_server(DnsTransaction *t) { + DnsServer *server; + + assert(t); + assert(t->scope->protocol == DNS_PROTOCOL_DNS); + + /* Pick a DNS server and a feature level for it. */ + + server = dns_scope_get_dns_server(t->scope); + if (!server) + return -ESRCH; + + /* If we changed the server invalidate the feature level clamping, as the new server might have completely + * different properties. */ + if (server != t->server) + t->clamp_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID; + + t->current_feature_level = dns_server_possible_feature_level(server); + + /* Clamp the feature level if that is requested. */ + if (t->clamp_feature_level != _DNS_SERVER_FEATURE_LEVEL_INVALID && + t->current_feature_level > t->clamp_feature_level) + t->current_feature_level = t->clamp_feature_level; + + log_debug("Using feature level %s for transaction %u.", dns_server_feature_level_to_string(t->current_feature_level), t->id); + + if (server == t->server) + return 0; + + dns_server_unref(t->server); + t->server = dns_server_ref(server); + + t->n_picked_servers ++; + + log_debug("Using DNS server %s for transaction %u.", dns_server_string(t->server), t->id); + + return 1; +} + +static void dns_transaction_retry(DnsTransaction *t, bool next_server) { + int r; + + assert(t); + + log_debug("Retrying transaction %" PRIu16 ".", t->id); + + /* Before we try again, switch to a new server. */ + if (next_server) + dns_scope_next_dns_server(t->scope); + + r = dns_transaction_go(t); + if (r < 0) { + t->answer_errno = -r; + dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); + } +} + +static int dns_transaction_maybe_restart(DnsTransaction *t) { + int r; + + assert(t); + + /* Returns > 0 if the transaction was restarted, 0 if not */ + + if (!t->server) + return 0; + + if (t->current_feature_level <= dns_server_possible_feature_level(t->server)) + return 0; + + /* The server's current feature level is lower than when we sent the original query. We learnt something from + the response or possibly an auxiliary DNSSEC response that we didn't know before. We take that as reason to + restart the whole transaction. This is a good idea to deal with servers that respond rubbish if we include + OPT RR or DO bit. One of these cases is documented here, for example: + https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html */ + + log_debug("Server feature level is now lower than when we began our transaction. Restarting with new ID."); + dns_transaction_shuffle_id(t); + + r = dns_transaction_go(t); + if (r < 0) + return r; + + return 1; +} + +static void on_transaction_stream_error(DnsTransaction *t, int error) { + assert(t); + + dns_transaction_close_connection(t); + + if (ERRNO_IS_DISCONNECT(error)) { + if (t->scope->protocol == DNS_PROTOCOL_LLMNR) { + /* If the LLMNR/TCP connection failed, the host doesn't support LLMNR, and we cannot answer the + * question on this scope. */ + dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND); + return; + } + + dns_transaction_retry(t, true); + return; + } + if (error != 0) { + t->answer_errno = error; + dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); + } +} + +static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) { + assert(t); + assert(p); + + dns_transaction_close_connection(t); + + if (dns_packet_validate_reply(p) <= 0) { + log_debug("Invalid TCP reply packet."); + dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); + return 0; + } + + dns_scope_check_conflicts(t->scope, p); + + t->block_gc++; + dns_transaction_process_reply(t, p); + t->block_gc--; + + /* If the response wasn't useful, then complete the transition + * now. After all, we are the worst feature set now with TCP + * sockets, and there's really no point in retrying. */ + if (t->state == DNS_TRANSACTION_PENDING) + dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); + else + dns_transaction_gc(t); + + return 0; +} + +static int on_stream_complete(DnsStream *s, int error) { + assert(s); + + if (ERRNO_IS_DISCONNECT(error) && s->protocol != DNS_PROTOCOL_LLMNR) { + log_debug_errno(error, "Connection failure for DNS TCP stream: %m"); + + if (s->transactions) { + DnsTransaction *t; + + t = s->transactions; + dns_server_packet_lost(t->server, IPPROTO_TCP, t->current_feature_level); + } + } + + if (error != 0) { + DnsTransaction *t, *n; + + LIST_FOREACH_SAFE(transactions_by_stream, t, n, s->transactions) + on_transaction_stream_error(t, error); + } + + return 0; +} + +static int on_stream_packet(DnsStream *s) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + DnsTransaction *t; + + assert(s); + + /* Take ownership of packet to be able to receive new packets */ + p = dns_stream_take_read_packet(s); + assert(p); + + t = hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p))); + if (t) + return dns_transaction_on_stream_packet(t, p); + + /* Ignore incorrect transaction id as an old transaction can have been canceled. */ + log_debug("Received unexpected TCP reply packet with id %" PRIu16 ", ignoring.", DNS_PACKET_ID(p)); + return 0; +} + +static uint16_t dns_port_for_feature_level(DnsServerFeatureLevel level) { + return DNS_SERVER_FEATURE_LEVEL_IS_TLS(level) ? 853 : 53; +} + +static int dns_transaction_emit_tcp(DnsTransaction *t) { + _cleanup_(dns_stream_unrefp) DnsStream *s = NULL; + _cleanup_close_ int fd = -1; + union sockaddr_union sa; + DnsStreamType type; + int r; + + assert(t); + + dns_transaction_close_connection(t); + + switch (t->scope->protocol) { + + case DNS_PROTOCOL_DNS: + r = dns_transaction_pick_server(t); + if (r < 0) + return r; + + if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type)) + return -EOPNOTSUPP; + + r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level); + if (r < 0) + return r; + + if (t->server->stream && (DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level) == t->server->stream->encrypted)) + s = dns_stream_ref(t->server->stream); + else + fd = dns_scope_socket_tcp(t->scope, AF_UNSPEC, NULL, t->server, dns_port_for_feature_level(t->current_feature_level), &sa); + + type = DNS_STREAM_LOOKUP; + break; + + case DNS_PROTOCOL_LLMNR: + /* When we already received a reply to this (but it was truncated), send to its sender address */ + if (t->received) + fd = dns_scope_socket_tcp(t->scope, t->received->family, &t->received->sender, NULL, t->received->sender_port, &sa); + else { + union in_addr_union address; + int family = AF_UNSPEC; + + /* Otherwise, try to talk to the owner of a + * the IP address, in case this is a reverse + * PTR lookup */ + + r = dns_name_address(dns_resource_key_name(t->key), &family, &address); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + if (family != t->scope->family) + return -ESRCH; + + fd = dns_scope_socket_tcp(t->scope, family, &address, NULL, LLMNR_PORT, &sa); + } + + type = DNS_STREAM_LLMNR_SEND; + break; + + default: + return -EAFNOSUPPORT; + } + + if (!s) { + if (fd < 0) + return fd; + + r = dns_stream_new(t->scope->manager, &s, type, t->scope->protocol, fd, &sa); + if (r < 0) + return r; + + fd = -1; + +#if ENABLE_DNS_OVER_TLS + if (t->scope->protocol == DNS_PROTOCOL_DNS && + DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level)) { + + assert(t->server); + r = dnstls_stream_connect_tls(s, t->server); + if (r < 0) + return r; + } +#endif + + if (t->server) { + dns_server_unref_stream(t->server); + s->server = dns_server_ref(t->server); + t->server->stream = dns_stream_ref(s); + } + + s->complete = on_stream_complete; + s->on_packet = on_stream_packet; + + /* The interface index is difficult to determine if we are + * connecting to the local host, hence fill this in right away + * instead of determining it from the socket */ + s->ifindex = dns_scope_ifindex(t->scope); + } + + t->stream = TAKE_PTR(s); + LIST_PREPEND(transactions_by_stream, t->stream->transactions, t); + + r = dns_stream_write_packet(t->stream, t->sent); + if (r < 0) { + dns_transaction_close_connection(t); + return r; + } + + dns_transaction_reset_answer(t); + + t->tried_stream = true; + + return 0; +} + +static void dns_transaction_cache_answer(DnsTransaction *t) { + assert(t); + + /* For mDNS we cache whenever we get the packet, rather than + * in each transaction. */ + if (!IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR)) + return; + + /* Caching disabled? */ + if (t->scope->manager->enable_cache == DNS_CACHE_MODE_NO) + return; + + /* We never cache if this packet is from the local host, under + * the assumption that a locally running DNS server would + * cache this anyway, and probably knows better when to flush + * the cache then we could. */ + if (!DNS_PACKET_SHALL_CACHE(t->received)) + return; + + dns_cache_put(&t->scope->cache, + t->scope->manager->enable_cache, + t->key, + t->answer_rcode, + t->answer, + t->answer_authenticated, + t->answer_nsec_ttl, + 0, + t->received->family, + &t->received->sender); +} + +static bool dns_transaction_dnssec_is_live(DnsTransaction *t) { + DnsTransaction *dt; + Iterator i; + + assert(t); + + SET_FOREACH(dt, t->dnssec_transactions, i) + if (DNS_TRANSACTION_IS_LIVE(dt->state)) + return true; + + return false; +} + +static int dns_transaction_dnssec_ready(DnsTransaction *t) { + DnsTransaction *dt; + Iterator i; + + assert(t); + + /* Checks whether the auxiliary DNSSEC transactions of our transaction have completed, or are still + * ongoing. Returns 0, if we aren't ready for the DNSSEC validation, positive if we are. */ + + SET_FOREACH(dt, t->dnssec_transactions, i) { + + switch (dt->state) { + + case DNS_TRANSACTION_NULL: + case DNS_TRANSACTION_PENDING: + case DNS_TRANSACTION_VALIDATING: + /* Still ongoing */ + return 0; + + case DNS_TRANSACTION_RCODE_FAILURE: + if (!IN_SET(dt->answer_rcode, DNS_RCODE_NXDOMAIN, DNS_RCODE_SERVFAIL)) { + log_debug("Auxiliary DNSSEC RR query failed with rcode=%s.", dns_rcode_to_string(dt->answer_rcode)); + goto fail; + } + + /* Fall-through: NXDOMAIN/SERVFAIL is good enough for us. This is because some DNS servers + * erroneously return NXDOMAIN/SERVFAIL for empty non-terminals (Akamai...) or missing DS + * records (Facebook), and we need to handle that nicely, when asking for parent SOA or similar + * RRs to make unsigned proofs. */ + + case DNS_TRANSACTION_SUCCESS: + /* All good. */ + break; + + case DNS_TRANSACTION_DNSSEC_FAILED: + /* We handle DNSSEC failures different from other errors, as we care about the DNSSEC + * validationr result */ + + log_debug("Auxiliary DNSSEC RR query failed validation: %s", dnssec_result_to_string(dt->answer_dnssec_result)); + t->answer_dnssec_result = dt->answer_dnssec_result; /* Copy error code over */ + dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED); + return 0; + + default: + log_debug("Auxiliary DNSSEC RR query failed with %s", dns_transaction_state_to_string(dt->state)); + goto fail; + } + } + + /* All is ready, we can go and validate */ + return 1; + +fail: + t->answer_dnssec_result = DNSSEC_FAILED_AUXILIARY; + dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED); + return 0; +} + +static void dns_transaction_process_dnssec(DnsTransaction *t) { + int r; + + assert(t); + + /* Are there ongoing DNSSEC transactions? If so, let's wait for them. */ + r = dns_transaction_dnssec_ready(t); + if (r < 0) + goto fail; + if (r == 0) /* We aren't ready yet (or one of our auxiliary transactions failed, and we shouldn't validate now */ + return; + + /* See if we learnt things from the additional DNSSEC transactions, that we didn't know before, and better + * restart the lookup immediately. */ + r = dns_transaction_maybe_restart(t); + if (r < 0) + goto fail; + if (r > 0) /* Transaction got restarted... */ + return; + + /* All our auxiliary DNSSEC transactions are complete now. Try + * to validate our RRset now. */ + r = dns_transaction_validate_dnssec(t); + if (r == -EBADMSG) { + dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); + return; + } + if (r < 0) + goto fail; + + if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER && + t->scope->dnssec_mode == DNSSEC_YES) { + + /* We are not in automatic downgrade mode, and the server is bad. Let's try a different server, maybe + * that works. */ + + if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) { + /* We tried fewer servers on this transaction than we know, let's try another one then */ + dns_transaction_retry(t, true); + return; + } + + /* OK, let's give up, apparently all servers we tried didn't work. */ + dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED); + return; + } + + if (!IN_SET(t->answer_dnssec_result, + _DNSSEC_RESULT_INVALID, /* No DNSSEC validation enabled */ + DNSSEC_VALIDATED, /* Answer is signed and validated successfully */ + DNSSEC_UNSIGNED, /* Answer is right-fully unsigned */ + DNSSEC_INCOMPATIBLE_SERVER)) { /* Server does not do DNSSEC (Yay, we are downgrade attack vulnerable!) */ + dns_transaction_complete(t, DNS_TRANSACTION_DNSSEC_FAILED); + return; + } + + if (t->answer_dnssec_result == DNSSEC_INCOMPATIBLE_SERVER) + dns_server_warn_downgrade(t->server); + + dns_transaction_cache_answer(t); + + if (t->answer_rcode == DNS_RCODE_SUCCESS) + dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); + else + dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE); + + return; + +fail: + t->answer_errno = -r; + dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); +} + +static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) { + int r; + + assert(t); + + /* Checks whether the answer is positive, i.e. either a direct + * answer to the question, or a CNAME/DNAME for it */ + + r = dns_answer_match_key(t->answer, t->key, flags); + if (r != 0) + return r; + + r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags); + if (r != 0) + return r; + + return false; +} + +static int dns_transaction_fix_rcode(DnsTransaction *t) { + int r; + + assert(t); + + /* Fix up the RCODE to SUCCESS if we get at least one matching RR in a response. Note that this contradicts the + * DNS RFCs a bit. Specifically, RFC 6604 Section 3 clarifies that the RCODE shall say something about a + * CNAME/DNAME chain element coming after the last chain element contained in the message, and not the first + * one included. However, it also indicates that not all DNS servers implement this correctly. Moreover, when + * using DNSSEC we usually only can prove the first element of a CNAME/DNAME chain anyway, hence let's settle + * on always processing the RCODE as referring to the immediate look-up we do, i.e. the first element of a + * CNAME/DNAME chain. This way, we uniformly handle CNAME/DNAME chains, regardless if the DNS server + * incorrectly implements RCODE, whether DNSSEC is in use, or whether the DNS server only supplied us with an + * incomplete CNAME/DNAME chain. + * + * Or in other words: if we get at least one positive reply in a message we patch NXDOMAIN to become SUCCESS, + * and then rely on the CNAME chasing logic to figure out that there's actually a CNAME error with a new + * lookup. */ + + if (t->answer_rcode != DNS_RCODE_NXDOMAIN) + return 0; + + r = dns_transaction_has_positive_answer(t, NULL); + if (r <= 0) + return r; + + t->answer_rcode = DNS_RCODE_SUCCESS; + return 0; +} + +void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { + usec_t ts; + int r; + + assert(t); + assert(p); + assert(t->scope); + assert(t->scope->manager); + + if (t->state != DNS_TRANSACTION_PENDING) + return; + + /* Note that this call might invalidate the query. Callers + * should hence not attempt to access the query or transaction + * after calling this function. */ + + log_debug("Processing incoming packet on transaction %" PRIu16" (rcode=%s).", + t->id, dns_rcode_to_string(DNS_PACKET_RCODE(p))); + + switch (t->scope->protocol) { + + case DNS_PROTOCOL_LLMNR: + /* For LLMNR we will not accept any packets from other interfaces */ + + if (p->ifindex != dns_scope_ifindex(t->scope)) + return; + + if (p->family != t->scope->family) + return; + + /* Tentative packets are not full responses but still + * useful for identifying uniqueness conflicts during + * probing. */ + if (DNS_PACKET_LLMNR_T(p)) { + dns_transaction_tentative(t, p); + return; + } + + break; + + case DNS_PROTOCOL_MDNS: + /* For mDNS we will not accept any packets from other interfaces */ + + if (p->ifindex != dns_scope_ifindex(t->scope)) + return; + + if (p->family != t->scope->family) + return; + + break; + + case DNS_PROTOCOL_DNS: + /* Note that we do not need to verify the + * addresses/port numbers of incoming traffic, as we + * invoked connect() on our UDP socket in which case + * the kernel already does the needed verification for + * us. */ + break; + + default: + assert_not_reached("Invalid DNS protocol."); + } + + if (t->received != p) { + dns_packet_unref(t->received); + t->received = dns_packet_ref(p); + } + + t->answer_source = DNS_TRANSACTION_NETWORK; + + if (p->ipproto == IPPROTO_TCP) { + if (DNS_PACKET_TC(p)) { + /* Truncated via TCP? Somebody must be fucking with us */ + dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); + return; + } + + if (DNS_PACKET_ID(p) != t->id) { + /* Not the reply to our query? Somebody must be fucking with us */ + dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); + return; + } + } + + assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); + + switch (t->scope->protocol) { + + case DNS_PROTOCOL_DNS: + assert(t->server); + + if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_FORMERR, DNS_RCODE_SERVFAIL, DNS_RCODE_NOTIMP)) { + + /* Request failed, immediately try again with reduced features */ + + if (t->current_feature_level <= DNS_SERVER_FEATURE_LEVEL_UDP) { + + /* This was already at UDP feature level? If so, it doesn't make sense to downgrade + * this transaction anymore, but let's see if it might make sense to send the request + * to a different DNS server instead. If not let's process the response, and accept the + * rcode. Note that we don't retry on TCP, since that's a suitable way to mitigate + * packet loss, but is not going to give us better rcodes should we actually have + * managed to get them already at UDP level. */ + + if (t->n_picked_servers < dns_scope_get_n_dns_servers(t->scope)) { + /* We tried fewer servers on this transaction than we know, let's try another one then */ + dns_transaction_retry(t, true); + return; + } + + /* Give up, accept the rcode */ + log_debug("Server returned error: %s", dns_rcode_to_string(DNS_PACKET_RCODE(p))); + break; + } + + /* Reduce this feature level by one and try again. */ + switch (t->current_feature_level) { + case DNS_SERVER_FEATURE_LEVEL_TLS_DO: + t->clamp_feature_level = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN; + break; + case DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN + 1: + /* Skip plain TLS when TLS is not supported */ + t->clamp_feature_level = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN - 1; + break; + default: + t->clamp_feature_level = t->current_feature_level - 1; + } + + log_debug("Server returned error %s, retrying transaction with reduced feature level %s.", + dns_rcode_to_string(DNS_PACKET_RCODE(p)), + dns_server_feature_level_to_string(t->clamp_feature_level)); + + dns_transaction_retry(t, false /* use the same server */); + return; + } + + if (DNS_PACKET_RCODE(p) == DNS_RCODE_REFUSED) { + /* This server refused our request? If so, try again, use a different server */ + log_debug("Server returned REFUSED, switching servers, and retrying."); + dns_transaction_retry(t, true /* pick a new server */); + return; + } + + if (DNS_PACKET_TC(p)) + dns_server_packet_truncated(t->server, t->current_feature_level); + + break; + + case DNS_PROTOCOL_LLMNR: + case DNS_PROTOCOL_MDNS: + dns_scope_packet_received(t->scope, ts - t->start_usec); + break; + + default: + assert_not_reached("Invalid DNS protocol."); + } + + if (DNS_PACKET_TC(p)) { + + /* Truncated packets for mDNS are not allowed. Give up immediately. */ + if (t->scope->protocol == DNS_PROTOCOL_MDNS) { + dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); + return; + } + + log_debug("Reply truncated, retrying via TCP."); + + /* Response was truncated, let's try again with good old TCP */ + r = dns_transaction_emit_tcp(t); + if (r == -ESRCH) { + /* No servers found? Damn! */ + dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS); + return; + } + if (r == -EOPNOTSUPP) { + /* Tried to ask for DNSSEC RRs, on a server that doesn't do DNSSEC */ + dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED); + return; + } + if (r < 0) { + /* On LLMNR, if we cannot connect to the host, + * we immediately give up */ + if (t->scope->protocol != DNS_PROTOCOL_DNS) + goto fail; + + /* On DNS, couldn't send? Try immediately again, with a new server */ + dns_transaction_retry(t, true); + } + + return; + } + + /* After the superficial checks, actually parse the message. */ + r = dns_packet_extract(p); + if (r < 0) { + dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); + return; + } + + if (t->server) { + /* Report that we successfully received a valid packet with a good rcode after we initially got a bad + * rcode and subsequently downgraded the protocol */ + + if (IN_SET(DNS_PACKET_RCODE(p), DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN) && + t->clamp_feature_level != _DNS_SERVER_FEATURE_LEVEL_INVALID) + dns_server_packet_rcode_downgrade(t->server, t->clamp_feature_level); + + /* Report that the OPT RR was missing */ + if (!p->opt) + dns_server_packet_bad_opt(t->server, t->current_feature_level); + + /* Report that we successfully received a packet */ + dns_server_packet_received(t->server, p->ipproto, t->current_feature_level, p->size); + } + + /* See if we know things we didn't know before that indicate we better restart the lookup immediately. */ + r = dns_transaction_maybe_restart(t); + if (r < 0) + goto fail; + if (r > 0) /* Transaction got restarted... */ + return; + + if (IN_SET(t->scope->protocol, DNS_PROTOCOL_DNS, DNS_PROTOCOL_LLMNR, DNS_PROTOCOL_MDNS)) { + + /* When dealing with protocols other than mDNS only consider responses with + * equivalent query section to the request. For mDNS this check doesn't make + * sense, because the section 6 of RFC6762 states that "Multicast DNS responses MUST NOT + * contain any questions in the Question Section". */ + if (t->scope->protocol != DNS_PROTOCOL_MDNS) { + r = dns_packet_is_reply_for(p, t->key); + if (r < 0) + goto fail; + if (r == 0) { + dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY); + return; + } + } + + /* Install the answer as answer to the transaction */ + dns_answer_unref(t->answer); + t->answer = dns_answer_ref(p->answer); + t->answer_rcode = DNS_PACKET_RCODE(p); + t->answer_dnssec_result = _DNSSEC_RESULT_INVALID; + t->answer_authenticated = false; + + r = dns_transaction_fix_rcode(t); + if (r < 0) + goto fail; + + /* Block GC while starting requests for additional DNSSEC RRs */ + t->block_gc++; + r = dns_transaction_request_dnssec_keys(t); + t->block_gc--; + + /* Maybe the transaction is ready for GC'ing now? If so, free it and return. */ + if (!dns_transaction_gc(t)) + return; + + /* Requesting additional keys might have resulted in + * this transaction to fail, since the auxiliary + * request failed for some reason. If so, we are not + * in pending state anymore, and we should exit + * quickly. */ + if (t->state != DNS_TRANSACTION_PENDING) + return; + if (r < 0) + goto fail; + if (r > 0) { + /* There are DNSSEC transactions pending now. Update the state accordingly. */ + t->state = DNS_TRANSACTION_VALIDATING; + dns_transaction_close_connection(t); + dns_transaction_stop_timeout(t); + return; + } + } + + dns_transaction_process_dnssec(t); + return; + +fail: + t->answer_errno = -r; + dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); +} + +static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + DnsTransaction *t = userdata; + int r; + + assert(t); + assert(t->scope); + + r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p); + if (ERRNO_IS_DISCONNECT(-r)) { + usec_t usec; + + /* UDP connection failures get reported via ICMP and then are possibly delivered to us on the + * next recvmsg(). Treat this like a lost packet. */ + + log_debug_errno(r, "Connection failure for DNS UDP packet: %m"); + assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0); + dns_server_packet_lost(t->server, IPPROTO_UDP, t->current_feature_level); + + dns_transaction_retry(t, true); + return 0; + } + if (r < 0) { + dns_transaction_complete(t, DNS_TRANSACTION_ERRNO); + t->answer_errno = -r; + return 0; + } + if (r == 0) + /* Spurious wakeup without any data */ + return 0; + + r = dns_packet_validate_reply(p); + if (r < 0) { + log_debug_errno(r, "Received invalid DNS packet as response, ignoring: %m"); + return 0; + } + if (r == 0) { + log_debug("Received inappropriate DNS packet as response, ignoring."); + return 0; + } + + if (DNS_PACKET_ID(p) != t->id) { + log_debug("Received packet with incorrect transaction ID, ignoring."); + return 0; + } + + dns_transaction_process_reply(t, p); + return 0; +} + +static int dns_transaction_emit_udp(DnsTransaction *t) { + int r; + + assert(t); + + if (t->scope->protocol == DNS_PROTOCOL_DNS) { + + r = dns_transaction_pick_server(t); + if (r < 0) + return r; + + if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP || DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level)) + return -EAGAIN; /* Sorry, can't do UDP, try TCP! */ + + if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(t->key->type)) + return -EOPNOTSUPP; + + if (r > 0 || t->dns_udp_fd < 0) { /* Server changed, or no connection yet. */ + int fd; + + dns_transaction_close_connection(t); + + fd = dns_scope_socket_udp(t->scope, t->server, 53); + if (fd < 0) + return fd; + + r = sd_event_add_io(t->scope->manager->event, &t->dns_udp_event_source, fd, EPOLLIN, on_dns_packet, t); + if (r < 0) { + safe_close(fd); + return r; + } + + (void) sd_event_source_set_description(t->dns_udp_event_source, "dns-transaction-udp"); + t->dns_udp_fd = fd; + } + + r = dns_server_adjust_opt(t->server, t->sent, t->current_feature_level); + if (r < 0) + return r; + } else + dns_transaction_close_connection(t); + + r = dns_scope_emit_udp(t->scope, t->dns_udp_fd, t->sent); + if (r < 0) + return r; + + dns_transaction_reset_answer(t); + + return 0; +} + +static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) { + DnsTransaction *t = userdata; + + assert(s); + assert(t); + + if (!t->initial_jitter_scheduled || t->initial_jitter_elapsed) { + /* Timeout reached? Increase the timeout for the server used */ + switch (t->scope->protocol) { + + case DNS_PROTOCOL_DNS: + assert(t->server); + dns_server_packet_lost(t->server, t->stream ? IPPROTO_TCP : IPPROTO_UDP, t->current_feature_level); + break; + + case DNS_PROTOCOL_LLMNR: + case DNS_PROTOCOL_MDNS: + dns_scope_packet_lost(t->scope, usec - t->start_usec); + break; + + default: + assert_not_reached("Invalid DNS protocol."); + } + + if (t->initial_jitter_scheduled) + t->initial_jitter_elapsed = true; + } + + log_debug("Timeout reached on transaction %" PRIu16 ".", t->id); + + dns_transaction_retry(t, true); + return 0; +} + +static usec_t transaction_get_resend_timeout(DnsTransaction *t) { + assert(t); + assert(t->scope); + + switch (t->scope->protocol) { + + case DNS_PROTOCOL_DNS: + + /* When we do TCP, grant a much longer timeout, as in this case there's no need for us to quickly + * resend, as the kernel does that anyway for us, and we really don't want to interrupt it in that + * needlessly. */ + if (t->stream) + return TRANSACTION_TCP_TIMEOUT_USEC; + + return DNS_TIMEOUT_USEC; + + case DNS_PROTOCOL_MDNS: + assert(t->n_attempts > 0); + if (t->probing) + return MDNS_PROBING_INTERVAL_USEC; + else + return (1 << (t->n_attempts - 1)) * USEC_PER_SEC; + + case DNS_PROTOCOL_LLMNR: + return t->scope->resend_timeout; + + default: + assert_not_reached("Invalid DNS protocol."); + } +} + +static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) { + int r; + + assert(t); + + dns_transaction_stop_timeout(t); + + if (!dns_scope_network_good(t->scope)) { + dns_transaction_complete(t, DNS_TRANSACTION_NETWORK_DOWN); + return 0; + } + + if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) { + dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED); + return 0; + } + + if (t->scope->protocol == DNS_PROTOCOL_LLMNR && t->tried_stream) { + /* If we already tried via a stream, then we don't + * retry on LLMNR. See RFC 4795, Section 2.7. */ + dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED); + return 0; + } + + t->n_attempts++; + t->start_usec = ts; + + dns_transaction_reset_answer(t); + dns_transaction_flush_dnssec_transactions(t); + + /* Check the trust anchor. Do so only on classic DNS, since DNSSEC does not apply otherwise. */ + if (t->scope->protocol == DNS_PROTOCOL_DNS) { + r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, t->key, &t->answer); + if (r < 0) + return r; + if (r > 0) { + t->answer_rcode = DNS_RCODE_SUCCESS; + t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR; + t->answer_authenticated = true; + dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); + return 0; + } + + if (dns_name_is_root(dns_resource_key_name(t->key)) && + t->key->type == DNS_TYPE_DS) { + + /* Hmm, this is a request for the root DS? A + * DS RR doesn't exist in the root zone, and + * if our trust anchor didn't know it either, + * this means we cannot do any DNSSEC logic + * anymore. */ + + if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) { + /* We are in downgrade mode. In this + * case, synthesize an unsigned empty + * response, so that the any lookup + * depending on this one can continue + * assuming there was no DS, and hence + * the root zone was unsigned. */ + + t->answer_rcode = DNS_RCODE_SUCCESS; + t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR; + t->answer_authenticated = false; + dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); + } else + /* If we are not in downgrade mode, + * then fail the lookup, because we + * cannot reasonably answer it. There + * might be DS RRs, but we don't know + * them, and the DNS server won't tell + * them to us (and even if it would, + * we couldn't validate and trust them. */ + dns_transaction_complete(t, DNS_TRANSACTION_NO_TRUST_ANCHOR); + + return 0; + } + } + + /* Check the zone, but only if this transaction is not used + * for probing or verifying a zone item. */ + if (set_isempty(t->notify_zone_items)) { + + r = dns_zone_lookup(&t->scope->zone, t->key, dns_scope_ifindex(t->scope), &t->answer, NULL, NULL); + if (r < 0) + return r; + if (r > 0) { + t->answer_rcode = DNS_RCODE_SUCCESS; + t->answer_source = DNS_TRANSACTION_ZONE; + t->answer_authenticated = true; + dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); + return 0; + } + } + + /* Check the cache, but only if this transaction is not used + * for probing or verifying a zone item. */ + if (set_isempty(t->notify_zone_items)) { + + /* Before trying the cache, let's make sure we figured out a + * server to use. Should this cause a change of server this + * might flush the cache. */ + (void) dns_scope_get_dns_server(t->scope); + + /* Let's then prune all outdated entries */ + dns_cache_prune(&t->scope->cache); + + r = dns_cache_lookup(&t->scope->cache, t->key, t->clamp_ttl, &t->answer_rcode, &t->answer, &t->answer_authenticated); + if (r < 0) + return r; + if (r > 0) { + t->answer_source = DNS_TRANSACTION_CACHE; + if (t->answer_rcode == DNS_RCODE_SUCCESS) + dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS); + else + dns_transaction_complete(t, DNS_TRANSACTION_RCODE_FAILURE); + return 0; + } + } + + return 1; +} + +static int dns_transaction_make_packet_mdns(DnsTransaction *t) { + + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + bool add_known_answers = false; + DnsTransaction *other; + Iterator i; + DnsResourceKey *tkey; + _cleanup_set_free_ Set *keys = NULL; + unsigned qdcount; + unsigned nscount = 0; + usec_t ts; + int r; + + assert(t); + assert(t->scope->protocol == DNS_PROTOCOL_MDNS); + + /* Discard any previously prepared packet, so we can start over and coalesce again */ + t->sent = dns_packet_unref(t->sent); + + r = dns_packet_new_query(&p, t->scope->protocol, 0, false); + if (r < 0) + return r; + + r = dns_packet_append_key(p, t->key, 0, NULL); + if (r < 0) + return r; + + qdcount = 1; + + if (dns_key_is_shared(t->key)) + add_known_answers = true; + + if (t->key->type == DNS_TYPE_ANY) { + r = set_ensure_allocated(&keys, &dns_resource_key_hash_ops); + if (r < 0) + return r; + + r = set_put(keys, t->key); + if (r < 0) + return r; + } + + /* + * For mDNS, we want to coalesce as many open queries in pending transactions into one single + * query packet on the wire as possible. To achieve that, we iterate through all pending transactions + * in our current scope, and see whether their timing constraints allow them to be sent. + */ + + assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); + + LIST_FOREACH(transactions_by_scope, other, t->scope->transactions) { + + /* Skip ourselves */ + if (other == t) + continue; + + if (other->state != DNS_TRANSACTION_PENDING) + continue; + + if (other->next_attempt_after > ts) + continue; + + if (qdcount >= UINT16_MAX) + break; + + r = dns_packet_append_key(p, other->key, 0, NULL); + + /* + * If we can't stuff more questions into the packet, just give up. + * One of the 'other' transactions will fire later and take care of the rest. + */ + if (r == -EMSGSIZE) + break; + + if (r < 0) + return r; + + r = dns_transaction_prepare(other, ts); + if (r <= 0) + continue; + + ts += transaction_get_resend_timeout(other); + + r = sd_event_add_time( + other->scope->manager->event, + &other->timeout_event_source, + clock_boottime_or_monotonic(), + ts, 0, + on_transaction_timeout, other); + if (r < 0) + return r; + + (void) sd_event_source_set_description(other->timeout_event_source, "dns-transaction-timeout"); + + other->state = DNS_TRANSACTION_PENDING; + other->next_attempt_after = ts; + + qdcount++; + + if (dns_key_is_shared(other->key)) + add_known_answers = true; + + if (other->key->type == DNS_TYPE_ANY) { + r = set_ensure_allocated(&keys, &dns_resource_key_hash_ops); + if (r < 0) + return r; + + r = set_put(keys, other->key); + if (r < 0) + return r; + } + } + + DNS_PACKET_HEADER(p)->qdcount = htobe16(qdcount); + + /* Append known answer section if we're asking for any shared record */ + if (add_known_answers) { + r = dns_cache_export_shared_to_packet(&t->scope->cache, p); + if (r < 0) + return r; + } + + SET_FOREACH(tkey, keys, i) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + bool tentative; + + r = dns_zone_lookup(&t->scope->zone, tkey, t->scope->link->ifindex, &answer, NULL, &tentative); + if (r < 0) + return r; + + r = dns_packet_append_answer(p, answer); + if (r < 0) + return r; + + nscount += dns_answer_size(answer); + } + DNS_PACKET_HEADER(p)->nscount = htobe16(nscount); + + t->sent = TAKE_PTR(p); + + return 0; +} + +static int dns_transaction_make_packet(DnsTransaction *t) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + int r; + + assert(t); + + if (t->scope->protocol == DNS_PROTOCOL_MDNS) + return dns_transaction_make_packet_mdns(t); + + if (t->sent) + return 0; + + r = dns_packet_new_query(&p, t->scope->protocol, 0, t->scope->dnssec_mode != DNSSEC_NO); + if (r < 0) + return r; + + r = dns_packet_append_key(p, t->key, 0, NULL); + if (r < 0) + return r; + + DNS_PACKET_HEADER(p)->qdcount = htobe16(1); + DNS_PACKET_HEADER(p)->id = t->id; + + t->sent = TAKE_PTR(p); + + return 0; +} + +int dns_transaction_go(DnsTransaction *t) { + usec_t ts; + int r; + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + + assert(t); + + /* Returns > 0 if the transaction is now pending, returns 0 if could be processed immediately and has finished + * now. */ + + assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0); + + r = dns_transaction_prepare(t, ts); + if (r <= 0) + return r; + + log_debug("Transaction %" PRIu16 " for <%s> scope %s on %s/%s.", + t->id, + dns_resource_key_to_string(t->key, key_str, sizeof key_str), + dns_protocol_to_string(t->scope->protocol), + t->scope->link ? t->scope->link->ifname : "*", + af_to_name_short(t->scope->family)); + + if (!t->initial_jitter_scheduled && + IN_SET(t->scope->protocol, DNS_PROTOCOL_LLMNR, DNS_PROTOCOL_MDNS)) { + usec_t jitter, accuracy; + + /* RFC 4795 Section 2.7 suggests all queries should be + * delayed by a random time from 0 to JITTER_INTERVAL. */ + + t->initial_jitter_scheduled = true; + + random_bytes(&jitter, sizeof(jitter)); + + switch (t->scope->protocol) { + + case DNS_PROTOCOL_LLMNR: + jitter %= LLMNR_JITTER_INTERVAL_USEC; + accuracy = LLMNR_JITTER_INTERVAL_USEC; + break; + + case DNS_PROTOCOL_MDNS: + jitter %= MDNS_JITTER_RANGE_USEC; + jitter += MDNS_JITTER_MIN_USEC; + accuracy = MDNS_JITTER_RANGE_USEC; + break; + default: + assert_not_reached("bad protocol"); + } + + r = sd_event_add_time( + t->scope->manager->event, + &t->timeout_event_source, + clock_boottime_or_monotonic(), + ts + jitter, accuracy, + on_transaction_timeout, t); + if (r < 0) + return r; + + (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout"); + + t->n_attempts = 0; + t->next_attempt_after = ts; + t->state = DNS_TRANSACTION_PENDING; + + log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter); + return 0; + } + + /* Otherwise, we need to ask the network */ + r = dns_transaction_make_packet(t); + if (r < 0) + return r; + + if (t->scope->protocol == DNS_PROTOCOL_LLMNR && + (dns_name_endswith(dns_resource_key_name(t->key), "in-addr.arpa") > 0 || + dns_name_endswith(dns_resource_key_name(t->key), "ip6.arpa") > 0)) { + + /* RFC 4795, Section 2.4. says reverse lookups shall + * always be made via TCP on LLMNR */ + r = dns_transaction_emit_tcp(t); + } else { + /* Try via UDP, and if that fails due to large size or lack of + * support try via TCP */ + r = dns_transaction_emit_udp(t); + if (r == -EMSGSIZE) + log_debug("Sending query via TCP since it is too large."); + else if (r == -EAGAIN) + log_debug("Sending query via TCP since UDP isn't supported."); + if (IN_SET(r, -EMSGSIZE, -EAGAIN)) + r = dns_transaction_emit_tcp(t); + } + + if (r == -ESRCH) { + /* No servers to send this to? */ + dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS); + return 0; + } + if (r == -EOPNOTSUPP) { + /* Tried to ask for DNSSEC RRs, on a server that doesn't do DNSSEC */ + dns_transaction_complete(t, DNS_TRANSACTION_RR_TYPE_UNSUPPORTED); + return 0; + } + if (t->scope->protocol == DNS_PROTOCOL_LLMNR && ERRNO_IS_DISCONNECT(-r)) { + /* On LLMNR, if we cannot connect to a host via TCP when doing reverse lookups. This means we cannot + * answer this request with this protocol. */ + dns_transaction_complete(t, DNS_TRANSACTION_NOT_FOUND); + return 0; + } + if (r < 0) { + if (t->scope->protocol != DNS_PROTOCOL_DNS) + return r; + + /* Couldn't send? Try immediately again, with a new server */ + dns_scope_next_dns_server(t->scope); + + return dns_transaction_go(t); + } + + ts += transaction_get_resend_timeout(t); + + r = sd_event_add_time( + t->scope->manager->event, + &t->timeout_event_source, + clock_boottime_or_monotonic(), + ts, 0, + on_transaction_timeout, t); + if (r < 0) + return r; + + (void) sd_event_source_set_description(t->timeout_event_source, "dns-transaction-timeout"); + + t->state = DNS_TRANSACTION_PENDING; + t->next_attempt_after = ts; + + return 1; +} + +static int dns_transaction_find_cyclic(DnsTransaction *t, DnsTransaction *aux) { + DnsTransaction *n; + Iterator i; + int r; + + assert(t); + assert(aux); + + /* Try to find cyclic dependencies between transaction objects */ + + if (t == aux) + return 1; + + SET_FOREACH(n, aux->dnssec_transactions, i) { + r = dns_transaction_find_cyclic(t, n); + if (r != 0) + return r; + } + + return 0; +} + +static int dns_transaction_add_dnssec_transaction(DnsTransaction *t, DnsResourceKey *key, DnsTransaction **ret) { + DnsTransaction *aux; + int r; + + assert(t); + assert(ret); + assert(key); + + aux = dns_scope_find_transaction(t->scope, key, true); + if (!aux) { + r = dns_transaction_new(&aux, t->scope, key); + if (r < 0) + return r; + } else { + if (set_contains(t->dnssec_transactions, aux)) { + *ret = aux; + return 0; + } + + r = dns_transaction_find_cyclic(t, aux); + if (r < 0) + return r; + if (r > 0) { + char s[DNS_RESOURCE_KEY_STRING_MAX], saux[DNS_RESOURCE_KEY_STRING_MAX]; + + return log_debug_errno(SYNTHETIC_ERRNO(ELOOP), + "Potential cyclic dependency, refusing to add transaction %" PRIu16 " (%s) as dependency for %" PRIu16 " (%s).", + aux->id, + dns_resource_key_to_string(t->key, s, sizeof s), + t->id, + dns_resource_key_to_string(aux->key, saux, sizeof saux)); + } + } + + r = set_ensure_allocated(&t->dnssec_transactions, NULL); + if (r < 0) + goto gc; + + r = set_ensure_allocated(&aux->notify_transactions, NULL); + if (r < 0) + goto gc; + + r = set_ensure_allocated(&aux->notify_transactions_done, NULL); + if (r < 0) + goto gc; + + r = set_put(t->dnssec_transactions, aux); + if (r < 0) + goto gc; + + r = set_put(aux->notify_transactions, t); + if (r < 0) { + (void) set_remove(t->dnssec_transactions, aux); + goto gc; + } + + *ret = aux; + return 1; + +gc: + dns_transaction_gc(aux); + return r; +} + +static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *key) { + _cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL; + DnsTransaction *aux; + int r; + + assert(t); + assert(key); + + /* Try to get the data from the trust anchor */ + r = dns_trust_anchor_lookup_positive(&t->scope->manager->trust_anchor, key, &a); + if (r < 0) + return r; + if (r > 0) { + r = dns_answer_extend(&t->validated_keys, a); + if (r < 0) + return r; + + return 0; + } + + /* This didn't work, ask for it via the network/cache then. */ + r = dns_transaction_add_dnssec_transaction(t, key, &aux); + if (r == -ELOOP) /* This would result in a cyclic dependency */ + return 0; + if (r < 0) + return r; + + if (aux->state == DNS_TRANSACTION_NULL) { + r = dns_transaction_go(aux); + if (r < 0) + return r; + } + + return 1; +} + +static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) { + int r; + + assert(t); + + /* Check whether the specified name is in the NTA + * database, either in the global one, or the link-local + * one. */ + + r = dns_trust_anchor_lookup_negative(&t->scope->manager->trust_anchor, name); + if (r != 0) + return r; + + if (!t->scope->link) + return 0; + + return set_contains(t->scope->link->dnssec_negative_trust_anchors, name); +} + +static int dns_transaction_has_unsigned_negative_answer(DnsTransaction *t) { + int r; + + assert(t); + + /* Checks whether the answer is negative, and lacks NSEC/NSEC3 + * RRs to prove it */ + + r = dns_transaction_has_positive_answer(t, NULL); + if (r < 0) + return r; + if (r > 0) + return false; + + /* Is this key explicitly listed as a negative trust anchor? + * If so, it's nothing we need to care about */ + r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(t->key)); + if (r < 0) + return r; + if (r > 0) + return false; + + /* The answer does not contain any RRs that match to the + * question. If so, let's see if there are any NSEC/NSEC3 RRs + * included. If not, the answer is unsigned. */ + + r = dns_answer_contains_nsec_or_nsec3(t->answer); + if (r < 0) + return r; + if (r > 0) + return false; + + return true; +} + +static int dns_transaction_is_primary_response(DnsTransaction *t, DnsResourceRecord *rr) { + int r; + + assert(t); + assert(rr); + + /* Check if the specified RR is the "primary" response, + * i.e. either matches the question precisely or is a + * CNAME/DNAME for it. */ + + r = dns_resource_key_match_rr(t->key, rr, NULL); + if (r != 0) + return r; + + return dns_resource_key_match_cname_or_dname(t->key, rr->key, NULL); +} + +static bool dns_transaction_dnssec_supported(DnsTransaction *t) { + assert(t); + + /* Checks whether our transaction's DNS server is assumed to be compatible with DNSSEC. Returns false as soon + * as we changed our mind about a server, and now believe it is incompatible with DNSSEC. */ + + if (t->scope->protocol != DNS_PROTOCOL_DNS) + return false; + + /* If we have picked no server, then we are working from the cache or some other source, and DNSSEC might well + * be supported, hence return true. */ + if (!t->server) + return true; + + /* Note that we do not check the feature level actually used for the transaction but instead the feature level + * the server is known to support currently, as the transaction feature level might be lower than what the + * server actually supports, since we might have downgraded this transaction's feature level because we got a + * SERVFAIL earlier and wanted to check whether downgrading fixes it. */ + + return dns_server_dnssec_supported(t->server); +} + +static bool dns_transaction_dnssec_supported_full(DnsTransaction *t) { + DnsTransaction *dt; + Iterator i; + + assert(t); + + /* Checks whether our transaction our any of the auxiliary transactions couldn't do DNSSEC. */ + + if (!dns_transaction_dnssec_supported(t)) + return false; + + SET_FOREACH(dt, t->dnssec_transactions, i) + if (!dns_transaction_dnssec_supported(dt)) + return false; + + return true; +} + +int dns_transaction_request_dnssec_keys(DnsTransaction *t) { + DnsResourceRecord *rr; + + int r; + + assert(t); + + /* + * Retrieve all auxiliary RRs for the answer we got, so that + * we can verify signatures or prove that RRs are rightfully + * unsigned. Specifically: + * + * - For RRSIG we get the matching DNSKEY + * - For DNSKEY we get the matching DS + * - For unsigned SOA/NS we get the matching DS + * - For unsigned CNAME/DNAME/DS we get the parent SOA RR + * - For other unsigned RRs we get the matching SOA RR + * - For SOA/NS queries with no matching response RR, and no NSEC/NSEC3, the DS RR + * - For DS queries with no matching response RRs, and no NSEC/NSEC3, the parent's SOA RR + * - For other queries with no matching response RRs, and no NSEC/NSEC3, the SOA RR + */ + + if (t->scope->dnssec_mode == DNSSEC_NO) + return 0; + if (t->answer_source != DNS_TRANSACTION_NETWORK) + return 0; /* We only need to validate stuff from the network */ + if (!dns_transaction_dnssec_supported(t)) + return 0; /* If we can't do DNSSEC anyway there's no point in getting the auxiliary RRs */ + + DNS_ANSWER_FOREACH(rr, t->answer) { + + if (dns_type_is_pseudo(rr->key->type)) + continue; + + /* If this RR is in the negative trust anchor, we don't need to validate it. */ + r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(rr->key)); + if (r < 0) + return r; + if (r > 0) + continue; + + switch (rr->key->type) { + + case DNS_TYPE_RRSIG: { + /* For each RRSIG we request the matching DNSKEY */ + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *dnskey = NULL; + + /* If this RRSIG is about a DNSKEY RR and the + * signer is the same as the owner, then we + * already have the DNSKEY, and we don't have + * to look for more. */ + if (rr->rrsig.type_covered == DNS_TYPE_DNSKEY) { + r = dns_name_equal(rr->rrsig.signer, dns_resource_key_name(rr->key)); + if (r < 0) + return r; + if (r > 0) + continue; + } + + /* If the signer is not a parent of our + * original query, then this is about an + * auxiliary RRset, but not anything we asked + * for. In this case we aren't interested, + * because we don't want to request additional + * RRs for stuff we didn't really ask for, and + * also to avoid request loops, where + * additional RRs from one transaction result + * in another transaction whose additional RRs + * point back to the original transaction, and + * we deadlock. */ + r = dns_name_endswith(dns_resource_key_name(t->key), rr->rrsig.signer); + if (r < 0) + return r; + if (r == 0) + continue; + + dnskey = dns_resource_key_new(rr->key->class, DNS_TYPE_DNSKEY, rr->rrsig.signer); + if (!dnskey) + return -ENOMEM; + + log_debug("Requesting DNSKEY to validate transaction %" PRIu16" (%s, RRSIG with key tag: %" PRIu16 ").", + t->id, dns_resource_key_name(rr->key), rr->rrsig.key_tag); + r = dns_transaction_request_dnssec_rr(t, dnskey); + if (r < 0) + return r; + break; + } + + case DNS_TYPE_DNSKEY: { + /* For each DNSKEY we request the matching DS */ + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL; + + /* If the DNSKEY we are looking at is not for + * zone we are interested in, nor any of its + * parents, we aren't interested, and don't + * request it. After all, we don't want to end + * up in request loops, and want to keep + * additional traffic down. */ + + r = dns_name_endswith(dns_resource_key_name(t->key), dns_resource_key_name(rr->key)); + if (r < 0) + return r; + if (r == 0) + continue; + + ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, dns_resource_key_name(rr->key)); + if (!ds) + return -ENOMEM; + + log_debug("Requesting DS to validate transaction %" PRIu16" (%s, DNSKEY with key tag: %" PRIu16 ").", + t->id, dns_resource_key_name(rr->key), dnssec_keytag(rr, false)); + r = dns_transaction_request_dnssec_rr(t, ds); + if (r < 0) + return r; + + break; + } + + case DNS_TYPE_SOA: + case DNS_TYPE_NS: { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *ds = NULL; + + /* For an unsigned SOA or NS, try to acquire + * the matching DS RR, as we are at a zone cut + * then, and whether a DS exists tells us + * whether the zone is signed. Do so only if + * this RR matches our original question, + * however. */ + + r = dns_resource_key_match_rr(t->key, rr, NULL); + if (r < 0) + return r; + if (r == 0) { + /* Hmm, so this SOA RR doesn't match our original question. In this case, maybe this is + * a negative reply, and we need the a SOA RR's TTL in order to cache a negative entry? + * If so, we need to validate it, too. */ + + r = dns_answer_match_key(t->answer, t->key, NULL); + if (r < 0) + return r; + if (r > 0) /* positive reply, we won't need the SOA and hence don't need to validate + * it. */ + continue; + + /* Only bother with this if the SOA/NS RR we are looking at is actually a parent of + * what we are looking for, otherwise there's no value in it for us. */ + r = dns_name_endswith(dns_resource_key_name(t->key), dns_resource_key_name(rr->key)); + if (r < 0) + return r; + if (r == 0) + continue; + } + + r = dnssec_has_rrsig(t->answer, rr->key); + if (r < 0) + return r; + if (r > 0) + continue; + + ds = dns_resource_key_new(rr->key->class, DNS_TYPE_DS, dns_resource_key_name(rr->key)); + if (!ds) + return -ENOMEM; + + log_debug("Requesting DS to validate transaction %" PRIu16 " (%s, unsigned SOA/NS RRset).", + t->id, dns_resource_key_name(rr->key)); + r = dns_transaction_request_dnssec_rr(t, ds); + if (r < 0) + return r; + + break; + } + + case DNS_TYPE_DS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL; + const char *name; + + /* CNAMEs and DNAMEs cannot be located at a + * zone apex, hence ask for the parent SOA for + * unsigned CNAME/DNAME RRs, maybe that's the + * apex. But do all that only if this is + * actually a response to our original + * question. + * + * Similar for DS RRs, which are signed when + * the parent SOA is signed. */ + + r = dns_transaction_is_primary_response(t, rr); + if (r < 0) + return r; + if (r == 0) + continue; + + r = dnssec_has_rrsig(t->answer, rr->key); + if (r < 0) + return r; + if (r > 0) + continue; + + r = dns_answer_has_dname_for_cname(t->answer, rr); + if (r < 0) + return r; + if (r > 0) + continue; + + name = dns_resource_key_name(rr->key); + r = dns_name_parent(&name); + if (r < 0) + return r; + if (r == 0) + continue; + + soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, name); + if (!soa) + return -ENOMEM; + + log_debug("Requesting parent SOA to validate transaction %" PRIu16 " (%s, unsigned CNAME/DNAME/DS RRset).", + t->id, dns_resource_key_name(rr->key)); + r = dns_transaction_request_dnssec_rr(t, soa); + if (r < 0) + return r; + + break; + } + + default: { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL; + + /* For other unsigned RRsets (including + * NSEC/NSEC3!), look for proof the zone is + * unsigned, by requesting the SOA RR of the + * zone. However, do so only if they are + * directly relevant to our original + * question. */ + + r = dns_transaction_is_primary_response(t, rr); + if (r < 0) + return r; + if (r == 0) + continue; + + r = dnssec_has_rrsig(t->answer, rr->key); + if (r < 0) + return r; + if (r > 0) + continue; + + soa = dns_resource_key_new(rr->key->class, DNS_TYPE_SOA, dns_resource_key_name(rr->key)); + if (!soa) + return -ENOMEM; + + log_debug("Requesting SOA to validate transaction %" PRIu16 " (%s, unsigned non-SOA/NS RRset <%s>).", + t->id, dns_resource_key_name(rr->key), dns_resource_record_to_string(rr)); + r = dns_transaction_request_dnssec_rr(t, soa); + if (r < 0) + return r; + break; + }} + } + + /* Above, we requested everything necessary to validate what + * we got. Now, let's request what we need to validate what we + * didn't get... */ + + r = dns_transaction_has_unsigned_negative_answer(t); + if (r < 0) + return r; + if (r > 0) { + const char *name; + uint16_t type = 0; + + name = dns_resource_key_name(t->key); + + /* If this was a SOA or NS request, then check if there's a DS RR for the same domain. Note that this + * could also be used as indication that we are not at a zone apex, but in real world setups there are + * too many broken DNS servers (Hello, incapdns.net!) where non-terminal zones return NXDOMAIN even + * though they have further children. If this was a DS request, then it's signed when the parent zone + * is signed, hence ask the parent SOA in that case. If this was any other RR then ask for the SOA RR, + * to see if that is signed. */ + + if (t->key->type == DNS_TYPE_DS) { + r = dns_name_parent(&name); + if (r > 0) { + type = DNS_TYPE_SOA; + log_debug("Requesting parent SOA (→ %s) to validate transaction %" PRIu16 " (%s, unsigned empty DS response).", + name, t->id, dns_resource_key_name(t->key)); + } else + name = NULL; + + } else if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS)) { + + type = DNS_TYPE_DS; + log_debug("Requesting DS (→ %s) to validate transaction %" PRIu16 " (%s, unsigned empty SOA/NS response).", + name, t->id, name); + + } else { + type = DNS_TYPE_SOA; + log_debug("Requesting SOA (→ %s) to validate transaction %" PRIu16 " (%s, unsigned empty non-SOA/NS/DS response).", + name, t->id, name); + } + + if (name) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *soa = NULL; + + soa = dns_resource_key_new(t->key->class, type, name); + if (!soa) + return -ENOMEM; + + r = dns_transaction_request_dnssec_rr(t, soa); + if (r < 0) + return r; + } + } + + return dns_transaction_dnssec_is_live(t); +} + +void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source) { + assert(t); + assert(source); + + /* Invoked whenever any of our auxiliary DNSSEC transactions completed its work. If the state is still PENDING, + we are still in the loop that adds further DNSSEC transactions, hence don't check if we are ready yet. If + the state is VALIDATING however, we should check if we are complete now. */ + + if (t->state == DNS_TRANSACTION_VALIDATING) + dns_transaction_process_dnssec(t); +} + +static int dns_transaction_validate_dnskey_by_ds(DnsTransaction *t) { + DnsResourceRecord *rr; + int ifindex, r; + + assert(t); + + /* Add all DNSKEY RRs from the answer that are validated by DS + * RRs from the list of validated keys to the list of + * validated keys. */ + + DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, t->answer) { + + r = dnssec_verify_dnskey_by_ds_search(rr, t->validated_keys); + if (r < 0) + return r; + if (r == 0) + continue; + + /* If so, the DNSKEY is validated too. */ + r = dns_answer_add_extend(&t->validated_keys, rr, ifindex, DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + } + + return 0; +} + +static int dns_transaction_requires_rrsig(DnsTransaction *t, DnsResourceRecord *rr) { + int r; + + assert(t); + assert(rr); + + /* Checks if the RR we are looking for must be signed with an + * RRSIG. This is used for positive responses. */ + + if (t->scope->dnssec_mode == DNSSEC_NO) + return false; + + if (dns_type_is_pseudo(rr->key->type)) + return -EINVAL; + + r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(rr->key)); + if (r < 0) + return r; + if (r > 0) + return false; + + switch (rr->key->type) { + + case DNS_TYPE_RRSIG: + /* RRSIGs are the signatures themselves, they need no signing. */ + return false; + + case DNS_TYPE_SOA: + case DNS_TYPE_NS: { + DnsTransaction *dt; + Iterator i; + + /* For SOA or NS RRs we look for a matching DS transaction */ + + SET_FOREACH(dt, t->dnssec_transactions, i) { + + if (dt->key->class != rr->key->class) + continue; + if (dt->key->type != DNS_TYPE_DS) + continue; + + r = dns_name_equal(dns_resource_key_name(dt->key), dns_resource_key_name(rr->key)); + if (r < 0) + return r; + if (r == 0) + continue; + + /* We found a DS transactions for the SOA/NS + * RRs we are looking at. If it discovered signed DS + * RRs, then we need to be signed, too. */ + + if (!dt->answer_authenticated) + return false; + + return dns_answer_match_key(dt->answer, dt->key, NULL); + } + + /* We found nothing that proves this is safe to leave + * this unauthenticated, hence ask inist on + * authentication. */ + return true; + } + + case DNS_TYPE_DS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAME: { + const char *parent = NULL; + DnsTransaction *dt; + Iterator i; + + /* + * CNAME/DNAME RRs cannot be located at a zone apex, hence look directly for the parent SOA. + * + * DS RRs are signed if the parent is signed, hence also look at the parent SOA + */ + + SET_FOREACH(dt, t->dnssec_transactions, i) { + + if (dt->key->class != rr->key->class) + continue; + if (dt->key->type != DNS_TYPE_SOA) + continue; + + if (!parent) { + parent = dns_resource_key_name(rr->key); + r = dns_name_parent(&parent); + if (r < 0) + return r; + if (r == 0) { + if (rr->key->type == DNS_TYPE_DS) + return true; + + /* A CNAME/DNAME without a parent? That's sooo weird. */ + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), + "Transaction %" PRIu16 " claims CNAME/DNAME at root. Refusing.", t->id); + } + } + + r = dns_name_equal(dns_resource_key_name(dt->key), parent); + if (r < 0) + return r; + if (r == 0) + continue; + + return t->answer_authenticated; + } + + return true; + } + + default: { + DnsTransaction *dt; + Iterator i; + + /* Any other kind of RR (including DNSKEY/NSEC/NSEC3). Let's see if our SOA lookup was authenticated */ + + SET_FOREACH(dt, t->dnssec_transactions, i) { + + if (dt->key->class != rr->key->class) + continue; + if (dt->key->type != DNS_TYPE_SOA) + continue; + + r = dns_name_equal(dns_resource_key_name(dt->key), dns_resource_key_name(rr->key)); + if (r < 0) + return r; + if (r == 0) + continue; + + /* We found the transaction that was supposed to find + * the SOA RR for us. It was successful, but found no + * RR for us. This means we are not at a zone cut. In + * this case, we require authentication if the SOA + * lookup was authenticated too. */ + return t->answer_authenticated; + } + + return true; + }} +} + +static int dns_transaction_in_private_tld(DnsTransaction *t, const DnsResourceKey *key) { + DnsTransaction *dt; + const char *tld; + Iterator i; + int r; + + /* If DNSSEC downgrade mode is on, checks whether the + * specified RR is one level below a TLD we have proven not to + * exist. In such a case we assume that this is a private + * domain, and permit it. + * + * This detects cases like the Fritz!Box router networks. Each + * Fritz!Box router serves a private "fritz.box" zone, in the + * non-existing TLD "box". Requests for the "fritz.box" domain + * are served by the router itself, while requests for the + * "box" domain will result in NXDOMAIN. + * + * Note that this logic is unable to detect cases where a + * router serves a private DNS zone directly under + * non-existing TLD. In such a case we cannot detect whether + * the TLD is supposed to exist or not, as all requests we + * make for it will be answered by the router's zone, and not + * by the root zone. */ + + assert(t); + + if (t->scope->dnssec_mode != DNSSEC_ALLOW_DOWNGRADE) + return false; /* In strict DNSSEC mode what doesn't exist, doesn't exist */ + + tld = dns_resource_key_name(key); + r = dns_name_parent(&tld); + if (r < 0) + return r; + if (r == 0) + return false; /* Already the root domain */ + + if (!dns_name_is_single_label(tld)) + return false; + + SET_FOREACH(dt, t->dnssec_transactions, i) { + + if (dt->key->class != key->class) + continue; + + r = dns_name_equal(dns_resource_key_name(dt->key), tld); + if (r < 0) + return r; + if (r == 0) + continue; + + /* We found an auxiliary lookup we did for the TLD. If + * that returned with NXDOMAIN, we know the TLD didn't + * exist, and hence this might be a private zone. */ + + return dt->answer_rcode == DNS_RCODE_NXDOMAIN; + } + + return false; +} + +static int dns_transaction_requires_nsec(DnsTransaction *t) { + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + DnsTransaction *dt; + const char *name; + uint16_t type = 0; + Iterator i; + int r; + + assert(t); + + /* Checks if we need to insist on NSEC/NSEC3 RRs for proving + * this negative reply */ + + if (t->scope->dnssec_mode == DNSSEC_NO) + return false; + + if (dns_type_is_pseudo(t->key->type)) + return -EINVAL; + + r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(t->key)); + if (r < 0) + return r; + if (r > 0) + return false; + + r = dns_transaction_in_private_tld(t, t->key); + if (r < 0) + return r; + if (r > 0) { + /* The lookup is from a TLD that is proven not to + * exist, and we are in downgrade mode, hence ignore + * that fact that we didn't get any NSEC RRs. */ + + log_info("Detected a negative query %s in a private DNS zone, permitting unsigned response.", + dns_resource_key_to_string(t->key, key_str, sizeof key_str)); + return false; + } + + name = dns_resource_key_name(t->key); + + if (t->key->type == DNS_TYPE_DS) { + + /* We got a negative reply for this DS lookup? DS RRs are signed when their parent zone is signed, + * hence check the parent SOA in this case. */ + + r = dns_name_parent(&name); + if (r < 0) + return r; + if (r == 0) + return true; + + type = DNS_TYPE_SOA; + + } else if (IN_SET(t->key->type, DNS_TYPE_SOA, DNS_TYPE_NS)) + /* We got a negative reply for this SOA/NS lookup? If so, check if there's a DS RR for this */ + type = DNS_TYPE_DS; + else + /* For all other negative replies, check for the SOA lookup */ + type = DNS_TYPE_SOA; + + /* For all other RRs we check the SOA on the same level to see + * if it's signed. */ + + SET_FOREACH(dt, t->dnssec_transactions, i) { + + if (dt->key->class != t->key->class) + continue; + if (dt->key->type != type) + continue; + + r = dns_name_equal(dns_resource_key_name(dt->key), name); + if (r < 0) + return r; + if (r == 0) + continue; + + return dt->answer_authenticated; + } + + /* If in doubt, require NSEC/NSEC3 */ + return true; +} + +static int dns_transaction_dnskey_authenticated(DnsTransaction *t, DnsResourceRecord *rr) { + DnsResourceRecord *rrsig; + bool found = false; + int r; + + /* Checks whether any of the DNSKEYs used for the RRSIGs for + * the specified RRset is authenticated (i.e. has a matching + * DS RR). */ + + r = dns_transaction_negative_trust_anchor_lookup(t, dns_resource_key_name(rr->key)); + if (r < 0) + return r; + if (r > 0) + return false; + + DNS_ANSWER_FOREACH(rrsig, t->answer) { + DnsTransaction *dt; + Iterator i; + + r = dnssec_key_match_rrsig(rr->key, rrsig); + if (r < 0) + return r; + if (r == 0) + continue; + + SET_FOREACH(dt, t->dnssec_transactions, i) { + + if (dt->key->class != rr->key->class) + continue; + + if (dt->key->type == DNS_TYPE_DNSKEY) { + + r = dns_name_equal(dns_resource_key_name(dt->key), rrsig->rrsig.signer); + if (r < 0) + return r; + if (r == 0) + continue; + + /* OK, we found an auxiliary DNSKEY + * lookup. If that lookup is + * authenticated, report this. */ + + if (dt->answer_authenticated) + return true; + + found = true; + + } else if (dt->key->type == DNS_TYPE_DS) { + + r = dns_name_equal(dns_resource_key_name(dt->key), rrsig->rrsig.signer); + if (r < 0) + return r; + if (r == 0) + continue; + + /* OK, we found an auxiliary DS + * lookup. If that lookup is + * authenticated and non-zero, we + * won! */ + + if (!dt->answer_authenticated) + return false; + + return dns_answer_match_key(dt->answer, dt->key, NULL); + } + } + } + + return found ? false : -ENXIO; +} + +static int dns_transaction_known_signed(DnsTransaction *t, DnsResourceRecord *rr) { + assert(t); + assert(rr); + + /* We know that the root domain is signed, hence if it appears + * not to be signed, there's a problem with the DNS server */ + + return rr->key->class == DNS_CLASS_IN && + dns_name_is_root(dns_resource_key_name(rr->key)); +} + +static int dns_transaction_check_revoked_trust_anchors(DnsTransaction *t) { + DnsResourceRecord *rr; + int r; + + assert(t); + + /* Maybe warn the user that we encountered a revoked DNSKEY + * for a key from our trust anchor. Note that we don't care + * whether the DNSKEY can be authenticated or not. It's + * sufficient if it is self-signed. */ + + DNS_ANSWER_FOREACH(rr, t->answer) { + r = dns_trust_anchor_check_revoked(&t->scope->manager->trust_anchor, rr, t->answer); + if (r < 0) + return r; + } + + return 0; +} + +static int dns_transaction_invalidate_revoked_keys(DnsTransaction *t) { + bool changed; + int r; + + assert(t); + + /* Removes all DNSKEY/DS objects from t->validated_keys that + * our trust anchors database considers revoked. */ + + do { + DnsResourceRecord *rr; + + changed = false; + + DNS_ANSWER_FOREACH(rr, t->validated_keys) { + r = dns_trust_anchor_is_revoked(&t->scope->manager->trust_anchor, rr); + if (r < 0) + return r; + if (r > 0) { + r = dns_answer_remove_by_rr(&t->validated_keys, rr); + if (r < 0) + return r; + + assert(r > 0); + changed = true; + break; + } + } + } while (changed); + + return 0; +} + +static int dns_transaction_copy_validated(DnsTransaction *t) { + DnsTransaction *dt; + Iterator i; + int r; + + assert(t); + + /* Copy all validated RRs from the auxiliary DNSSEC transactions into our set of validated RRs */ + + SET_FOREACH(dt, t->dnssec_transactions, i) { + + if (DNS_TRANSACTION_IS_LIVE(dt->state)) + continue; + + if (!dt->answer_authenticated) + continue; + + r = dns_answer_extend(&t->validated_keys, dt->answer); + if (r < 0) + return r; + } + + return 0; +} + +typedef enum { + DNSSEC_PHASE_DNSKEY, /* Phase #1, only validate DNSKEYs */ + DNSSEC_PHASE_NSEC, /* Phase #2, only validate NSEC+NSEC3 */ + DNSSEC_PHASE_ALL, /* Phase #3, validate everything else */ +} Phase; + +static int dnssec_validate_records( + DnsTransaction *t, + Phase phase, + bool *have_nsec, + DnsAnswer **validated) { + + DnsResourceRecord *rr; + int r; + + /* Returns negative on error, 0 if validation failed, 1 to restart validation, 2 when finished. */ + + DNS_ANSWER_FOREACH(rr, t->answer) { + DnsResourceRecord *rrsig = NULL; + DnssecResult result; + + switch (rr->key->type) { + case DNS_TYPE_RRSIG: + continue; + + case DNS_TYPE_DNSKEY: + /* We validate DNSKEYs only in the DNSKEY and ALL phases */ + if (phase == DNSSEC_PHASE_NSEC) + continue; + break; + + case DNS_TYPE_NSEC: + case DNS_TYPE_NSEC3: + *have_nsec = true; + + /* We validate NSEC/NSEC3 only in the NSEC and ALL phases */ + if (phase == DNSSEC_PHASE_DNSKEY) + continue; + break; + + default: + /* We validate all other RRs only in the ALL phases */ + if (phase != DNSSEC_PHASE_ALL) + continue; + } + + r = dnssec_verify_rrset_search(t->answer, rr->key, t->validated_keys, USEC_INFINITY, &result, &rrsig); + if (r < 0) + return r; + + log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result)); + + if (result == DNSSEC_VALIDATED) { + + if (rr->key->type == DNS_TYPE_DNSKEY) { + /* If we just validated a DNSKEY RRset, then let's add these keys to + * the set of validated keys for this transaction. */ + + r = dns_answer_copy_by_key(&t->validated_keys, t->answer, rr->key, DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + + /* Some of the DNSKEYs we just added might already have been revoked, + * remove them again in that case. */ + r = dns_transaction_invalidate_revoked_keys(t); + if (r < 0) + return r; + } + + /* Add the validated RRset to the new list of validated + * RRsets, and remove it from the unvalidated RRsets. + * We mark the RRset as authenticated and cacheable. */ + r = dns_answer_move_by_key(validated, &t->answer, rr->key, DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE); + if (r < 0) + return r; + + manager_dnssec_verdict(t->scope->manager, DNSSEC_SECURE, rr->key); + + /* Exit the loop, we dropped something from the answer, start from the beginning */ + return 1; + } + + /* If we haven't read all DNSKEYs yet a negative result of the validation is irrelevant, as + * there might be more DNSKEYs coming. Similar, if we haven't read all NSEC/NSEC3 RRs yet, + * we cannot do positive wildcard proofs yet, as those require the NSEC/NSEC3 RRs. */ + if (phase != DNSSEC_PHASE_ALL) + continue; + + if (result == DNSSEC_VALIDATED_WILDCARD) { + bool authenticated = false; + const char *source; + + /* This RRset validated, but as a wildcard. This means we need + * to prove via NSEC/NSEC3 that no matching non-wildcard RR exists. */ + + /* First step, determine the source of synthesis */ + r = dns_resource_record_source(rrsig, &source); + if (r < 0) + return r; + + r = dnssec_test_positive_wildcard(*validated, + dns_resource_key_name(rr->key), + source, + rrsig->rrsig.signer, + &authenticated); + + /* Unless the NSEC proof showed that the key really doesn't exist something is off. */ + if (r == 0) + result = DNSSEC_INVALID; + else { + r = dns_answer_move_by_key(validated, &t->answer, rr->key, + authenticated ? (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE) : 0); + if (r < 0) + return r; + + manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, rr->key); + + /* Exit the loop, we dropped something from the answer, start from the beginning */ + return 1; + } + } + + if (result == DNSSEC_NO_SIGNATURE) { + r = dns_transaction_requires_rrsig(t, rr); + if (r < 0) + return r; + if (r == 0) { + /* Data does not require signing. In that case, just copy it over, + * but remember that this is by no means authenticated. */ + r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0); + if (r < 0) + return r; + + manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key); + return 1; + } + + r = dns_transaction_known_signed(t, rr); + if (r < 0) + return r; + if (r > 0) { + /* This is an RR we know has to be signed. If it isn't this means + * the server is not attaching RRSIGs, hence complain. */ + + dns_server_packet_rrsig_missing(t->server, t->current_feature_level); + + if (t->scope->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE) { + + /* Downgrading is OK? If so, just consider the information unsigned */ + + r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0); + if (r < 0) + return r; + + manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key); + return 1; + } + + /* Otherwise, fail */ + t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER; + return 0; + } + + r = dns_transaction_in_private_tld(t, rr->key); + if (r < 0) + return r; + if (r > 0) { + char s[DNS_RESOURCE_KEY_STRING_MAX]; + + /* The data is from a TLD that is proven not to exist, and we are in downgrade + * mode, hence ignore the fact that this was not signed. */ + + log_info("Detected RRset %s is in a private DNS zone, permitting unsigned RRs.", + dns_resource_key_to_string(rr->key, s, sizeof s)); + + r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0); + if (r < 0) + return r; + + manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key); + return 1; + } + } + + if (IN_SET(result, + DNSSEC_MISSING_KEY, + DNSSEC_SIGNATURE_EXPIRED, + DNSSEC_UNSUPPORTED_ALGORITHM)) { + + r = dns_transaction_dnskey_authenticated(t, rr); + if (r < 0 && r != -ENXIO) + return r; + if (r == 0) { + /* The DNSKEY transaction was not authenticated, this means there's + * no DS for this, which means it's OK if no keys are found for this signature. */ + + r = dns_answer_move_by_key(validated, &t->answer, rr->key, 0); + if (r < 0) + return r; + + manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, rr->key); + return 1; + } + } + + r = dns_transaction_is_primary_response(t, rr); + if (r < 0) + return r; + if (r > 0) { + /* Look for a matching DNAME for this CNAME */ + r = dns_answer_has_dname_for_cname(t->answer, rr); + if (r < 0) + return r; + if (r == 0) { + /* Also look among the stuff we already validated */ + r = dns_answer_has_dname_for_cname(*validated, rr); + if (r < 0) + return r; + } + + if (r == 0) { + if (IN_SET(result, + DNSSEC_INVALID, + DNSSEC_SIGNATURE_EXPIRED, + DNSSEC_NO_SIGNATURE)) + manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, rr->key); + else /* DNSSEC_MISSING_KEY or DNSSEC_UNSUPPORTED_ALGORITHM */ + manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, rr->key); + + /* This is a primary response to our question, and it failed validation. + * That's fatal. */ + t->answer_dnssec_result = result; + return 0; + } + + /* This is a primary response, but we do have a DNAME RR + * in the RR that can replay this CNAME, hence rely on + * that, and we can remove the CNAME in favour of it. */ + } + + /* This is just some auxiliary data. Just remove the RRset and continue. */ + r = dns_answer_remove_by_key(&t->answer, rr->key); + if (r < 0) + return r; + + /* We dropped something from the answer, start from the beginning. */ + return 1; + } + + return 2; /* Finito. */ +} + +int dns_transaction_validate_dnssec(DnsTransaction *t) { + _cleanup_(dns_answer_unrefp) DnsAnswer *validated = NULL; + Phase phase; + DnsAnswerFlags flags; + int r; + char key_str[DNS_RESOURCE_KEY_STRING_MAX]; + + assert(t); + + /* We have now collected all DS and DNSKEY RRs in + * t->validated_keys, let's see which RRs we can now + * authenticate with that. */ + + if (t->scope->dnssec_mode == DNSSEC_NO) + return 0; + + /* Already validated */ + if (t->answer_dnssec_result != _DNSSEC_RESULT_INVALID) + return 0; + + /* Our own stuff needs no validation */ + if (IN_SET(t->answer_source, DNS_TRANSACTION_ZONE, DNS_TRANSACTION_TRUST_ANCHOR)) { + t->answer_dnssec_result = DNSSEC_VALIDATED; + t->answer_authenticated = true; + return 0; + } + + /* Cached stuff is not affected by validation. */ + if (t->answer_source != DNS_TRANSACTION_NETWORK) + return 0; + + if (!dns_transaction_dnssec_supported_full(t)) { + /* The server does not support DNSSEC, or doesn't augment responses with RRSIGs. */ + t->answer_dnssec_result = DNSSEC_INCOMPATIBLE_SERVER; + log_debug("Not validating response for %" PRIu16 ", used server feature level does not support DNSSEC.", t->id); + return 0; + } + + log_debug("Validating response from transaction %" PRIu16 " (%s).", + t->id, + dns_resource_key_to_string(t->key, key_str, sizeof key_str)); + + /* First, see if this response contains any revoked trust + * anchors we care about */ + r = dns_transaction_check_revoked_trust_anchors(t); + if (r < 0) + return r; + + /* Third, copy all RRs we acquired successfully from auxiliary RRs over. */ + r = dns_transaction_copy_validated(t); + if (r < 0) + return r; + + /* Second, see if there are DNSKEYs we already know a + * validated DS for. */ + r = dns_transaction_validate_dnskey_by_ds(t); + if (r < 0) + return r; + + /* Fourth, remove all DNSKEY and DS RRs again that our trust + * anchor says are revoked. After all we might have marked + * some keys revoked above, but they might still be lingering + * in our validated_keys list. */ + r = dns_transaction_invalidate_revoked_keys(t); + if (r < 0) + return r; + + phase = DNSSEC_PHASE_DNSKEY; + for (;;) { + bool have_nsec = false; + + r = dnssec_validate_records(t, phase, &have_nsec, &validated); + if (r <= 0) + return r; + + /* Try again as long as we managed to achieve something */ + if (r == 1) + continue; + + if (phase == DNSSEC_PHASE_DNSKEY && have_nsec) { + /* OK, we processed all DNSKEYs, and there are NSEC/NSEC3 RRs, look at those now. */ + phase = DNSSEC_PHASE_NSEC; + continue; + } + + if (phase != DNSSEC_PHASE_ALL) { + /* OK, we processed all DNSKEYs and NSEC/NSEC3 RRs, look at all the rest now. + * Note that in this third phase we start to remove RRs we couldn't validate. */ + phase = DNSSEC_PHASE_ALL; + continue; + } + + /* We're done */ + break; + } + + dns_answer_unref(t->answer); + t->answer = TAKE_PTR(validated); + + /* At this point the answer only contains validated + * RRsets. Now, let's see if it actually answers the question + * we asked. If so, great! If it doesn't, then see if + * NSEC/NSEC3 can prove this. */ + r = dns_transaction_has_positive_answer(t, &flags); + if (r > 0) { + /* Yes, it answers the question! */ + + if (flags & DNS_ANSWER_AUTHENTICATED) { + /* The answer is fully authenticated, yay. */ + t->answer_dnssec_result = DNSSEC_VALIDATED; + t->answer_rcode = DNS_RCODE_SUCCESS; + t->answer_authenticated = true; + } else { + /* The answer is not fully authenticated. */ + t->answer_dnssec_result = DNSSEC_UNSIGNED; + t->answer_authenticated = false; + } + + } else if (r == 0) { + DnssecNsecResult nr; + bool authenticated = false; + + /* Bummer! Let's check NSEC/NSEC3 */ + r = dnssec_nsec_test(t->answer, t->key, &nr, &authenticated, &t->answer_nsec_ttl); + if (r < 0) + return r; + + switch (nr) { + + case DNSSEC_NSEC_NXDOMAIN: + /* NSEC proves the domain doesn't exist. Very good. */ + log_debug("Proved NXDOMAIN via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str); + t->answer_dnssec_result = DNSSEC_VALIDATED; + t->answer_rcode = DNS_RCODE_NXDOMAIN; + t->answer_authenticated = authenticated; + + manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, t->key); + break; + + case DNSSEC_NSEC_NODATA: + /* NSEC proves that there's no data here, very good. */ + log_debug("Proved NODATA via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str); + t->answer_dnssec_result = DNSSEC_VALIDATED; + t->answer_rcode = DNS_RCODE_SUCCESS; + t->answer_authenticated = authenticated; + + manager_dnssec_verdict(t->scope->manager, authenticated ? DNSSEC_SECURE : DNSSEC_INSECURE, t->key); + break; + + case DNSSEC_NSEC_OPTOUT: + /* NSEC3 says the data might not be signed */ + log_debug("Data is NSEC3 opt-out via NSEC/NSEC3 for transaction %u (%s)", t->id, key_str); + t->answer_dnssec_result = DNSSEC_UNSIGNED; + t->answer_authenticated = false; + + manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, t->key); + break; + + case DNSSEC_NSEC_NO_RR: + /* No NSEC data? Bummer! */ + + r = dns_transaction_requires_nsec(t); + if (r < 0) + return r; + if (r > 0) { + t->answer_dnssec_result = DNSSEC_NO_SIGNATURE; + manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, t->key); + } else { + t->answer_dnssec_result = DNSSEC_UNSIGNED; + t->answer_authenticated = false; + manager_dnssec_verdict(t->scope->manager, DNSSEC_INSECURE, t->key); + } + + break; + + case DNSSEC_NSEC_UNSUPPORTED_ALGORITHM: + /* We don't know the NSEC3 algorithm used? */ + t->answer_dnssec_result = DNSSEC_UNSUPPORTED_ALGORITHM; + manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, t->key); + break; + + case DNSSEC_NSEC_FOUND: + case DNSSEC_NSEC_CNAME: + /* NSEC says it needs to be there, but we couldn't find it? Bummer! */ + t->answer_dnssec_result = DNSSEC_NSEC_MISMATCH; + manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, t->key); + break; + + default: + assert_not_reached("Unexpected NSEC result."); + } + } + + return 1; +} + +static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = { + [DNS_TRANSACTION_NULL] = "null", + [DNS_TRANSACTION_PENDING] = "pending", + [DNS_TRANSACTION_VALIDATING] = "validating", + [DNS_TRANSACTION_RCODE_FAILURE] = "rcode-failure", + [DNS_TRANSACTION_SUCCESS] = "success", + [DNS_TRANSACTION_NO_SERVERS] = "no-servers", + [DNS_TRANSACTION_TIMEOUT] = "timeout", + [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached", + [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply", + [DNS_TRANSACTION_ERRNO] = "errno", + [DNS_TRANSACTION_ABORTED] = "aborted", + [DNS_TRANSACTION_DNSSEC_FAILED] = "dnssec-failed", + [DNS_TRANSACTION_NO_TRUST_ANCHOR] = "no-trust-anchor", + [DNS_TRANSACTION_RR_TYPE_UNSUPPORTED] = "rr-type-unsupported", + [DNS_TRANSACTION_NETWORK_DOWN] = "network-down", + [DNS_TRANSACTION_NOT_FOUND] = "not-found", +}; +DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState); + +static const char* const dns_transaction_source_table[_DNS_TRANSACTION_SOURCE_MAX] = { + [DNS_TRANSACTION_NETWORK] = "network", + [DNS_TRANSACTION_CACHE] = "cache", + [DNS_TRANSACTION_ZONE] = "zone", + [DNS_TRANSACTION_TRUST_ANCHOR] = "trust-anchor", +}; +DEFINE_STRING_TABLE_LOOKUP(dns_transaction_source, DnsTransactionSource); diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h new file mode 100644 index 00000000..bdfcbc1a --- /dev/null +++ b/src/resolve/resolved-dns-transaction.h @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct DnsTransaction DnsTransaction; +typedef enum DnsTransactionState DnsTransactionState; +typedef enum DnsTransactionSource DnsTransactionSource; + +enum DnsTransactionState { + DNS_TRANSACTION_NULL, + DNS_TRANSACTION_PENDING, + DNS_TRANSACTION_VALIDATING, + DNS_TRANSACTION_RCODE_FAILURE, + DNS_TRANSACTION_SUCCESS, + DNS_TRANSACTION_NO_SERVERS, + DNS_TRANSACTION_TIMEOUT, + DNS_TRANSACTION_ATTEMPTS_MAX_REACHED, + DNS_TRANSACTION_INVALID_REPLY, + DNS_TRANSACTION_ERRNO, + DNS_TRANSACTION_ABORTED, + DNS_TRANSACTION_DNSSEC_FAILED, + DNS_TRANSACTION_NO_TRUST_ANCHOR, + DNS_TRANSACTION_RR_TYPE_UNSUPPORTED, + DNS_TRANSACTION_NETWORK_DOWN, + DNS_TRANSACTION_NOT_FOUND, /* like NXDOMAIN, but when LLMNR/TCP connections fail */ + _DNS_TRANSACTION_STATE_MAX, + _DNS_TRANSACTION_STATE_INVALID = -1 +}; + +#define DNS_TRANSACTION_IS_LIVE(state) IN_SET((state), DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING) + +enum DnsTransactionSource { + DNS_TRANSACTION_NETWORK, + DNS_TRANSACTION_CACHE, + DNS_TRANSACTION_ZONE, + DNS_TRANSACTION_TRUST_ANCHOR, + _DNS_TRANSACTION_SOURCE_MAX, + _DNS_TRANSACTION_SOURCE_INVALID = -1 +}; + +#include "resolved-dns-answer.h" +#include "resolved-dns-packet.h" +#include "resolved-dns-question.h" +#include "resolved-dns-scope.h" +#include "resolved-dns-server.h" +#include "resolved-dns-stream.h" + +struct DnsTransaction { + DnsScope *scope; + + DnsResourceKey *key; + + DnsTransactionState state; + + uint16_t id; + + bool tried_stream:1; + + bool initial_jitter_scheduled:1; + bool initial_jitter_elapsed:1; + + bool clamp_ttl:1; + + bool probing:1; + + DnsPacket *sent, *received; + + DnsAnswer *answer; + int answer_rcode; + DnssecResult answer_dnssec_result; + DnsTransactionSource answer_source; + uint32_t answer_nsec_ttl; + int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */ + + /* Indicates whether the primary answer is authenticated, + * i.e. whether the RRs from answer which directly match the + * question are authenticated, or, if there are none, whether + * the NODATA or NXDOMAIN case is. It says nothing about + * additional RRs listed in the answer, however they have + * their own DNS_ANSWER_AUTHORIZED FLAGS. Note that this bit + * is defined different than the AD bit in DNS packets, as + * that covers more than just the actual primary answer. */ + bool answer_authenticated; + + /* Contains DNSKEY, DS, SOA RRs we already verified and need + * to authenticate this reply */ + DnsAnswer *validated_keys; + + usec_t start_usec; + usec_t next_attempt_after; + sd_event_source *timeout_event_source; + unsigned n_attempts; + + unsigned n_picked_servers; + + /* UDP connection logic, if we need it */ + int dns_udp_fd; + sd_event_source *dns_udp_event_source; + + /* TCP connection logic, if we need it */ + DnsStream *stream; + + /* The active server */ + DnsServer *server; + + /* The features of the DNS server at time of transaction start */ + DnsServerFeatureLevel current_feature_level; + + /* If we got SERVFAIL back, we retry the lookup, using a lower feature level than we used before. */ + DnsServerFeatureLevel clamp_feature_level; + + /* Query candidates this transaction is referenced by and that + * shall be notified about this specific transaction + * completing. */ + Set *notify_query_candidates, *notify_query_candidates_done; + + /* Zone items this transaction is referenced by and that shall + * be notified about completion. */ + Set *notify_zone_items, *notify_zone_items_done; + + /* Other transactions that this transactions is referenced by + * and that shall be notified about completion. This is used + * when transactions want to validate their RRsets, but need + * another DNSKEY or DS RR to do so. */ + Set *notify_transactions, *notify_transactions_done; + + /* The opposite direction: the transactions this transaction + * created in order to request DNSKEY or DS RRs. */ + Set *dnssec_transactions; + + unsigned block_gc; + + LIST_FIELDS(DnsTransaction, transactions_by_scope); + LIST_FIELDS(DnsTransaction, transactions_by_stream); +}; + +int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key); +DnsTransaction* dns_transaction_free(DnsTransaction *t); + +bool dns_transaction_gc(DnsTransaction *t); +int dns_transaction_go(DnsTransaction *t); + +void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p); +void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state); + +void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source); +int dns_transaction_validate_dnssec(DnsTransaction *t); +int dns_transaction_request_dnssec_keys(DnsTransaction *t); + +const char* dns_transaction_state_to_string(DnsTransactionState p) _const_; +DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_; + +const char* dns_transaction_source_to_string(DnsTransactionSource p) _const_; +DnsTransactionSource dns_transaction_source_from_string(const char *s) _pure_; + +/* LLMNR Jitter interval, see RFC 4795 Section 7 */ +#define LLMNR_JITTER_INTERVAL_USEC (100 * USEC_PER_MSEC) + +/* mDNS Jitter interval, see RFC 6762 Section 5.2 */ +#define MDNS_JITTER_MIN_USEC (20 * USEC_PER_MSEC) +#define MDNS_JITTER_RANGE_USEC (100 * USEC_PER_MSEC) + +/* mDNS probing interval, see RFC 6762 Section 8.1 */ +#define MDNS_PROBING_INTERVAL_USEC (250 * USEC_PER_MSEC) + +/* Maximum attempts to send DNS requests, across all DNS servers */ +#define DNS_TRANSACTION_ATTEMPTS_MAX 24 + +/* Maximum attempts to send LLMNR requests, see RFC 4795 Section 2.7 */ +#define LLMNR_TRANSACTION_ATTEMPTS_MAX 3 + +/* Maximum attempts to send MDNS requests, see RFC 6762 Section 8.1 */ +#define MDNS_TRANSACTION_ATTEMPTS_MAX 3 + +#define TRANSACTION_ATTEMPTS_MAX(p) (((p) == DNS_PROTOCOL_LLMNR) ? \ + LLMNR_TRANSACTION_ATTEMPTS_MAX : \ + (((p) == DNS_PROTOCOL_MDNS) ? \ + MDNS_TRANSACTION_ATTEMPTS_MAX : \ + DNS_TRANSACTION_ATTEMPTS_MAX)) diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c new file mode 100644 index 00000000..92842bcf --- /dev/null +++ b/src/resolve/resolved-dns-trust-anchor.c @@ -0,0 +1,782 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "conf-files.h" +#include "def.h" +#include "dns-domain.h" +#include "fd-util.h" +#include "fileio.h" +#include "hexdecoct.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "resolved-dns-dnssec.h" +#include "resolved-dns-trust-anchor.h" +#include "set.h" +#include "sort-util.h" +#include "string-util.h" +#include "strv.h" + +static const char trust_anchor_dirs[] = CONF_PATHS_NULSTR("dnssec-trust-anchors.d"); + +/* The second DS RR from https://data.iana.org/root-anchors/root-anchors.xml, retrieved February 2017 */ +static const uint8_t root_digest2[] = + { 0xE0, 0x6D, 0x44, 0xB8, 0x0B, 0x8F, 0x1D, 0x39, 0xA9, 0x5C, 0x0B, 0x0D, 0x7C, 0x65, 0xD0, 0x84, + 0x58, 0xE8, 0x80, 0x40, 0x9B, 0xBC, 0x68, 0x34, 0x57, 0x10, 0x42, 0x37, 0xC7, 0xF8, 0xEC, 0x8D }; + +static bool dns_trust_anchor_knows_domain_positive(DnsTrustAnchor *d, const char *name) { + assert(d); + + /* Returns true if there's an entry for the specified domain + * name in our trust anchor */ + + return + hashmap_contains(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DNSKEY, name)) || + hashmap_contains(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DS, name)); +} + +static int add_root_ksk( + DnsAnswer *answer, + DnsResourceKey *key, + uint16_t key_tag, + uint8_t algorithm, + uint8_t digest_type, + const void *digest, + size_t digest_size) { + + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + int r; + + rr = dns_resource_record_new(key); + if (!rr) + return -ENOMEM; + + rr->ds.key_tag = key_tag; + rr->ds.algorithm = algorithm; + rr->ds.digest_type = digest_type; + rr->ds.digest_size = digest_size; + rr->ds.digest = memdup(digest, rr->ds.digest_size); + if (!rr->ds.digest) + return -ENOMEM; + + r = dns_answer_add(answer, rr, 0, DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + + return 0; +} + +static int dns_trust_anchor_add_builtin_positive(DnsTrustAnchor *d) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + int r; + + assert(d); + + r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops); + if (r < 0) + return r; + + /* Only add the built-in trust anchor if there's neither a DS nor a DNSKEY defined for the root domain. That + * way users have an easy way to override the root domain DS/DNSKEY data. */ + if (dns_trust_anchor_knows_domain_positive(d, ".")) + return 0; + + key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_DS, ""); + if (!key) + return -ENOMEM; + + answer = dns_answer_new(2); + if (!answer) + return -ENOMEM; + + /* Add the currently valid RRs from https://data.iana.org/root-anchors/root-anchors.xml */ + r = add_root_ksk(answer, key, 20326, DNSSEC_ALGORITHM_RSASHA256, DNSSEC_DIGEST_SHA256, root_digest2, sizeof(root_digest2)); + if (r < 0) + return r; + + r = hashmap_put(d->positive_by_key, key, answer); + if (r < 0) + return r; + + answer = NULL; + return 0; +} + +static int dns_trust_anchor_add_builtin_negative(DnsTrustAnchor *d) { + + static const char private_domains[] = + /* RFC 6761 says that .test is a special domain for + * testing and not to be installed in the root zone */ + "test\0" + + /* RFC 6761 says that these reverse IP lookup ranges + * are for private addresses, and hence should not + * show up in the root zone */ + "10.in-addr.arpa\0" + "16.172.in-addr.arpa\0" + "17.172.in-addr.arpa\0" + "18.172.in-addr.arpa\0" + "19.172.in-addr.arpa\0" + "20.172.in-addr.arpa\0" + "21.172.in-addr.arpa\0" + "22.172.in-addr.arpa\0" + "23.172.in-addr.arpa\0" + "24.172.in-addr.arpa\0" + "25.172.in-addr.arpa\0" + "26.172.in-addr.arpa\0" + "27.172.in-addr.arpa\0" + "28.172.in-addr.arpa\0" + "29.172.in-addr.arpa\0" + "30.172.in-addr.arpa\0" + "31.172.in-addr.arpa\0" + "168.192.in-addr.arpa\0" + + /* The same, but for IPv6. */ + "d.f.ip6.arpa\0" + + /* RFC 6762 reserves the .local domain for Multicast + * DNS, it hence cannot appear in the root zone. (Note + * that we by default do not route .local traffic to + * DNS anyway, except when a configured search domain + * suggests so.) */ + "local\0" + + /* These two are well known, popular private zone + * TLDs, that are blocked from delegation, according + * to: + * http://icannwiki.com/Name_Collision#NGPC_Resolution + * + * There's also ongoing work on making this official + * in an RRC: + * https://www.ietf.org/archive/id/draft-chapin-additional-reserved-tlds-02.txt */ + "home\0" + "corp\0" + + /* The following four TLDs are suggested for private + * zones in RFC 6762, Appendix G, and are hence very + * unlikely to be made official TLDs any day soon */ + "lan\0" + "intranet\0" + "internal\0" + "private\0"; + + const char *name; + int r; + + assert(d); + + /* Only add the built-in trust anchor if there's no negative + * trust anchor defined at all. This enables easy overriding + * of negative trust anchors. */ + + if (set_size(d->negative_by_name) > 0) + return 0; + + r = set_ensure_allocated(&d->negative_by_name, &dns_name_hash_ops); + if (r < 0) + return r; + + /* We add a couple of domains as default negative trust + * anchors, where it's very unlikely they will be installed in + * the root zone. If they exist they must be private, and thus + * unsigned. */ + + NULSTR_FOREACH(name, private_domains) { + + if (dns_trust_anchor_knows_domain_positive(d, name)) + continue; + + r = set_put_strdup(d->negative_by_name, name); + if (r < 0) + return r; + } + + return 0; +} + +static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, unsigned line, const char *s) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + _cleanup_free_ char *domain = NULL, *class = NULL, *type = NULL; + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + DnsAnswer *old_answer = NULL; + const char *p = s; + int r; + + assert(d); + assert(line); + + r = extract_first_word(&p, &domain, NULL, EXTRACT_UNQUOTE); + if (r < 0) + return log_warning_errno(r, "Unable to parse domain in line %s:%u: %m", path, line); + + r = dns_name_is_valid(domain); + if (r < 0) + return log_warning_errno(r, "Failed to check validity of domain name '%s', at line %s:%u, ignoring line: %m", domain, path, line); + if (r == 0) { + log_warning("Domain name %s is invalid, at line %s:%u, ignoring line.", domain, path, line); + return -EINVAL; + } + + r = extract_many_words(&p, NULL, 0, &class, &type, NULL); + if (r < 0) + return log_warning_errno(r, "Unable to parse class and type in line %s:%u: %m", path, line); + if (r != 2) { + log_warning("Missing class or type in line %s:%u", path, line); + return -EINVAL; + } + + if (!strcaseeq(class, "IN")) { + log_warning("RR class %s is not supported, ignoring line %s:%u.", class, path, line); + return -EINVAL; + } + + if (strcaseeq(type, "DS")) { + _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL; + _cleanup_free_ void *dd = NULL; + uint16_t kt; + int a, dt; + size_t l; + + r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, NULL); + if (r < 0) { + log_warning_errno(r, "Failed to parse DS parameters on line %s:%u: %m", path, line); + return -EINVAL; + } + if (r != 3) { + log_warning("Missing DS parameters on line %s:%u", path, line); + return -EINVAL; + } + + r = safe_atou16(key_tag, &kt); + if (r < 0) + return log_warning_errno(r, "Failed to parse DS key tag %s on line %s:%u: %m", key_tag, path, line); + + a = dnssec_algorithm_from_string(algorithm); + if (a < 0) { + log_warning("Failed to parse DS algorithm %s on line %s:%u", algorithm, path, line); + return -EINVAL; + } + + dt = dnssec_digest_from_string(digest_type); + if (dt < 0) { + log_warning("Failed to parse DS digest type %s on line %s:%u", digest_type, path, line); + return -EINVAL; + } + + if (isempty(p)) { + log_warning("Missing DS digest on line %s:%u", path, line); + return -EINVAL; + } + + r = unhexmem(p, strlen(p), &dd, &l); + if (r < 0) { + log_warning("Failed to parse DS digest %s on line %s:%u", p, path, line); + return -EINVAL; + } + + rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, domain); + if (!rr) + return log_oom(); + + rr->ds.key_tag = kt; + rr->ds.algorithm = a; + rr->ds.digest_type = dt; + rr->ds.digest_size = l; + rr->ds.digest = TAKE_PTR(dd); + + } else if (strcaseeq(type, "DNSKEY")) { + _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL; + _cleanup_free_ void *k = NULL; + uint16_t f; + size_t l; + int a; + + r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, NULL); + if (r < 0) + return log_warning_errno(r, "Failed to parse DNSKEY parameters on line %s:%u: %m", path, line); + if (r != 3) { + log_warning("Missing DNSKEY parameters on line %s:%u", path, line); + return -EINVAL; + } + + if (!streq(protocol, "3")) { + log_warning("DNSKEY Protocol is not 3 on line %s:%u", path, line); + return -EINVAL; + } + + r = safe_atou16(flags, &f); + if (r < 0) + return log_warning_errno(r, "Failed to parse DNSKEY flags field %s on line %s:%u", flags, path, line); + if ((f & DNSKEY_FLAG_ZONE_KEY) == 0) { + log_warning("DNSKEY lacks zone key bit set on line %s:%u", path, line); + return -EINVAL; + } + if ((f & DNSKEY_FLAG_REVOKE)) { + log_warning("DNSKEY is already revoked on line %s:%u", path, line); + return -EINVAL; + } + + a = dnssec_algorithm_from_string(algorithm); + if (a < 0) { + log_warning("Failed to parse DNSKEY algorithm %s on line %s:%u", algorithm, path, line); + return -EINVAL; + } + + if (isempty(p)) { + log_warning("Missing DNSKEY key on line %s:%u", path, line); + return -EINVAL; + } + + r = unbase64mem(p, strlen(p), &k, &l); + if (r < 0) + return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", p, path, line); + + rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, domain); + if (!rr) + return log_oom(); + + rr->dnskey.flags = f; + rr->dnskey.protocol = 3; + rr->dnskey.algorithm = a; + rr->dnskey.key_size = l; + rr->dnskey.key = TAKE_PTR(k); + + } else { + log_warning("RR type %s is not supported, ignoring line %s:%u.", type, path, line); + return -EINVAL; + } + + r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops); + if (r < 0) + return log_oom(); + + old_answer = hashmap_get(d->positive_by_key, rr->key); + answer = dns_answer_ref(old_answer); + + r = dns_answer_add_extend(&answer, rr, 0, DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return log_error_errno(r, "Failed to add trust anchor RR: %m"); + + r = hashmap_replace(d->positive_by_key, rr->key, answer); + if (r < 0) + return log_error_errno(r, "Failed to add answer to trust anchor: %m"); + + old_answer = dns_answer_unref(old_answer); + answer = NULL; + + return 0; +} + +static int dns_trust_anchor_load_negative(DnsTrustAnchor *d, const char *path, unsigned line, const char *s) { + _cleanup_free_ char *domain = NULL; + const char *p = s; + int r; + + assert(d); + assert(line); + + r = extract_first_word(&p, &domain, NULL, EXTRACT_UNQUOTE); + if (r < 0) + return log_warning_errno(r, "Unable to parse line %s:%u: %m", path, line); + + r = dns_name_is_valid(domain); + if (r < 0) + return log_warning_errno(r, "Failed to check validity of domain name '%s', at line %s:%u, ignoring line: %m", domain, path, line); + if (r == 0) { + log_warning("Domain name %s is invalid, at line %s:%u, ignoring line.", domain, path, line); + return -EINVAL; + } + + if (!isempty(p)) { + log_warning("Trailing garbage at line %s:%u, ignoring line.", path, line); + return -EINVAL; + } + + r = set_ensure_allocated(&d->negative_by_name, &dns_name_hash_ops); + if (r < 0) + return log_oom(); + + r = set_put(d->negative_by_name, domain); + if (r < 0) + return log_oom(); + if (r > 0) + domain = NULL; + + return 0; +} + +static int dns_trust_anchor_load_files( + DnsTrustAnchor *d, + const char *suffix, + int (*loader)(DnsTrustAnchor *d, const char *path, unsigned n, const char *line)) { + + _cleanup_strv_free_ char **files = NULL; + char **f; + int r; + + assert(d); + assert(suffix); + assert(loader); + + r = conf_files_list_nulstr(&files, suffix, NULL, 0, trust_anchor_dirs); + if (r < 0) + return log_error_errno(r, "Failed to enumerate %s trust anchor files: %m", suffix); + + STRV_FOREACH(f, files) { + _cleanup_fclose_ FILE *g = NULL; + unsigned n = 0; + + g = fopen(*f, "r"); + if (!g) { + if (errno == ENOENT) + continue; + + log_warning_errno(errno, "Failed to open '%s', ignoring: %m", *f); + continue; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + char *l; + + r = read_line(g, LONG_LINE_MAX, &line); + if (r < 0) { + log_warning_errno(r, "Failed to read '%s', ignoring: %m", *f); + break; + } + if (r == 0) + break; + + n++; + + l = strstrip(line); + if (isempty(l)) + continue; + + if (*l == ';') + continue; + + (void) loader(d, *f, n, l); + } + } + + return 0; +} + +static int domain_name_cmp(char * const *a, char * const *b) { + return dns_name_compare_func(*a, *b); +} + +static int dns_trust_anchor_dump(DnsTrustAnchor *d) { + DnsAnswer *a; + Iterator i; + + assert(d); + + if (hashmap_isempty(d->positive_by_key)) + log_info("No positive trust anchors defined."); + else { + log_info("Positive Trust Anchors:"); + HASHMAP_FOREACH(a, d->positive_by_key, i) { + DnsResourceRecord *rr; + + DNS_ANSWER_FOREACH(rr, a) + log_info("%s", dns_resource_record_to_string(rr)); + } + } + + if (set_isempty(d->negative_by_name)) + log_info("No negative trust anchors defined."); + else { + _cleanup_free_ char **l = NULL, *j = NULL; + + l = set_get_strv(d->negative_by_name); + if (!l) + return log_oom(); + + typesafe_qsort(l, set_size(d->negative_by_name), domain_name_cmp); + + j = strv_join(l, " "); + if (!j) + return log_oom(); + + log_info("Negative trust anchors: %s", j); + } + + return 0; +} + +int dns_trust_anchor_load(DnsTrustAnchor *d) { + int r; + + assert(d); + + /* If loading things from disk fails, we don't consider this fatal */ + (void) dns_trust_anchor_load_files(d, ".positive", dns_trust_anchor_load_positive); + (void) dns_trust_anchor_load_files(d, ".negative", dns_trust_anchor_load_negative); + + /* However, if the built-in DS fails, then we have a problem. */ + r = dns_trust_anchor_add_builtin_positive(d); + if (r < 0) + return log_error_errno(r, "Failed to add built-in positive trust anchor: %m"); + + r = dns_trust_anchor_add_builtin_negative(d); + if (r < 0) + return log_error_errno(r, "Failed to add built-in negative trust anchor: %m"); + + dns_trust_anchor_dump(d); + + return 0; +} + +void dns_trust_anchor_flush(DnsTrustAnchor *d) { + assert(d); + + d->positive_by_key = hashmap_free_with_destructor(d->positive_by_key, dns_answer_unref); + d->revoked_by_rr = set_free_with_destructor(d->revoked_by_rr, dns_resource_record_unref); + d->negative_by_name = set_free_free(d->negative_by_name); +} + +int dns_trust_anchor_lookup_positive(DnsTrustAnchor *d, const DnsResourceKey *key, DnsAnswer **ret) { + DnsAnswer *a; + + assert(d); + assert(key); + assert(ret); + + /* We only serve DS and DNSKEY RRs. */ + if (!IN_SET(key->type, DNS_TYPE_DS, DNS_TYPE_DNSKEY)) + return 0; + + a = hashmap_get(d->positive_by_key, key); + if (!a) + return 0; + + *ret = dns_answer_ref(a); + return 1; +} + +int dns_trust_anchor_lookup_negative(DnsTrustAnchor *d, const char *name) { + int r; + + assert(d); + assert(name); + + for (;;) { + /* If the domain is listed as-is in the NTA database, then that counts */ + if (set_contains(d->negative_by_name, name)) + return true; + + /* If the domain isn't listed as NTA, but is listed as positive trust anchor, then that counts. See RFC + * 7646, section 1.1 */ + if (hashmap_contains(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_DS, name))) + return false; + + if (hashmap_contains(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_IN, DNS_TYPE_KEY, name))) + return false; + + /* And now, let's look at the parent, and check that too */ + r = dns_name_parent(&name); + if (r < 0) + return r; + if (r == 0) + break; + } + + return false; +} + +static int dns_trust_anchor_revoked_put(DnsTrustAnchor *d, DnsResourceRecord *rr) { + int r; + + assert(d); + + r = set_ensure_allocated(&d->revoked_by_rr, &dns_resource_record_hash_ops); + if (r < 0) + return r; + + r = set_put(d->revoked_by_rr, rr); + if (r < 0) + return r; + if (r > 0) + dns_resource_record_ref(rr); + + return r; +} + +static int dns_trust_anchor_remove_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr) { + _cleanup_(dns_answer_unrefp) DnsAnswer *new_answer = NULL; + DnsAnswer *old_answer; + int r; + + /* Remember that this is a revoked trust anchor RR */ + r = dns_trust_anchor_revoked_put(d, rr); + if (r < 0) + return r; + + /* Remove this from the positive trust anchor */ + old_answer = hashmap_get(d->positive_by_key, rr->key); + if (!old_answer) + return 0; + + new_answer = dns_answer_ref(old_answer); + + r = dns_answer_remove_by_rr(&new_answer, rr); + if (r <= 0) + return r; + + /* We found the key! Warn the user */ + log_struct(LOG_WARNING, + "MESSAGE_ID=" SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED_STR, + LOG_MESSAGE("DNSSEC trust anchor %s has been revoked.\n" + "Please update the trust anchor, or upgrade your operating system.", + strna(dns_resource_record_to_string(rr))), + "TRUST_ANCHOR=%s", dns_resource_record_to_string(rr)); + + if (dns_answer_size(new_answer) <= 0) { + assert_se(hashmap_remove(d->positive_by_key, rr->key) == old_answer); + dns_answer_unref(old_answer); + return 1; + } + + r = hashmap_replace(d->positive_by_key, new_answer->items[0].rr->key, new_answer); + if (r < 0) + return r; + + new_answer = NULL; + dns_answer_unref(old_answer); + return 1; +} + +static int dns_trust_anchor_check_revoked_one(DnsTrustAnchor *d, DnsResourceRecord *revoked_dnskey) { + DnsAnswer *a; + int r; + + assert(d); + assert(revoked_dnskey); + assert(revoked_dnskey->key->type == DNS_TYPE_DNSKEY); + assert(revoked_dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE); + + a = hashmap_get(d->positive_by_key, revoked_dnskey->key); + if (a) { + DnsResourceRecord *anchor; + + /* First, look for the precise DNSKEY in our trust anchor database */ + + DNS_ANSWER_FOREACH(anchor, a) { + + if (anchor->dnskey.protocol != revoked_dnskey->dnskey.protocol) + continue; + + if (anchor->dnskey.algorithm != revoked_dnskey->dnskey.algorithm) + continue; + + if (anchor->dnskey.key_size != revoked_dnskey->dnskey.key_size) + continue; + + /* Note that we allow the REVOKE bit to be + * different! It will be set in the revoked + * key, but unset in our version of it */ + if (((anchor->dnskey.flags ^ revoked_dnskey->dnskey.flags) | DNSKEY_FLAG_REVOKE) != DNSKEY_FLAG_REVOKE) + continue; + + if (memcmp(anchor->dnskey.key, revoked_dnskey->dnskey.key, anchor->dnskey.key_size) != 0) + continue; + + dns_trust_anchor_remove_revoked(d, anchor); + break; + } + } + + a = hashmap_get(d->positive_by_key, &DNS_RESOURCE_KEY_CONST(revoked_dnskey->key->class, DNS_TYPE_DS, dns_resource_key_name(revoked_dnskey->key))); + if (a) { + DnsResourceRecord *anchor; + + /* Second, look for DS RRs matching this DNSKEY in our trust anchor database */ + + DNS_ANSWER_FOREACH(anchor, a) { + + /* We set mask_revoke to true here, since our + * DS fingerprint will be the one of the + * unrevoked DNSKEY, but the one we got passed + * here has the bit set. */ + r = dnssec_verify_dnskey_by_ds(revoked_dnskey, anchor, true); + if (r < 0) + return r; + if (r == 0) + continue; + + dns_trust_anchor_remove_revoked(d, anchor); + break; + } + } + + return 0; +} + +int dns_trust_anchor_check_revoked(DnsTrustAnchor *d, DnsResourceRecord *dnskey, DnsAnswer *rrs) { + DnsResourceRecord *rrsig; + int r; + + assert(d); + assert(dnskey); + + /* Looks if "dnskey" is a self-signed RR that has been revoked + * and matches one of our trust anchor entries. If so, removes + * it from the trust anchor and returns > 0. */ + + if (dnskey->key->type != DNS_TYPE_DNSKEY) + return 0; + + /* Is this DNSKEY revoked? */ + if ((dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE) == 0) + return 0; + + /* Could this be interesting to us at all? If not, + * there's no point in looking for and verifying a + * self-signed RRSIG. */ + if (!dns_trust_anchor_knows_domain_positive(d, dns_resource_key_name(dnskey->key))) + return 0; + + /* Look for a self-signed RRSIG in the other rrs belonging to this DNSKEY */ + DNS_ANSWER_FOREACH(rrsig, rrs) { + DnssecResult result; + + if (rrsig->key->type != DNS_TYPE_RRSIG) + continue; + + r = dnssec_rrsig_match_dnskey(rrsig, dnskey, true); + if (r < 0) + return r; + if (r == 0) + continue; + + r = dnssec_verify_rrset(rrs, dnskey->key, rrsig, dnskey, USEC_INFINITY, &result); + if (r < 0) + return r; + if (result != DNSSEC_VALIDATED) + continue; + + /* Bingo! This is a revoked self-signed DNSKEY. Let's + * see if this precise one exists in our trust anchor + * database, too. */ + r = dns_trust_anchor_check_revoked_one(d, dnskey); + if (r < 0) + return r; + + return 1; + } + + return 0; +} + +int dns_trust_anchor_is_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr) { + assert(d); + + if (!IN_SET(rr->key->type, DNS_TYPE_DS, DNS_TYPE_DNSKEY)) + return 0; + + return set_contains(d->revoked_by_rr, rr); +} diff --git a/src/resolve/resolved-dns-trust-anchor.h b/src/resolve/resolved-dns-trust-anchor.h new file mode 100644 index 00000000..df49777e --- /dev/null +++ b/src/resolve/resolved-dns-trust-anchor.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct DnsTrustAnchor DnsTrustAnchor; + +#include "hashmap.h" +#include "resolved-dns-answer.h" +#include "resolved-dns-rr.h" + +/* This contains a fixed database mapping domain names to DS or DNSKEY records. */ + +struct DnsTrustAnchor { + Hashmap *positive_by_key; + Set *negative_by_name; + Set *revoked_by_rr; +}; + +int dns_trust_anchor_load(DnsTrustAnchor *d); +void dns_trust_anchor_flush(DnsTrustAnchor *d); + +int dns_trust_anchor_lookup_positive(DnsTrustAnchor *d, const DnsResourceKey* key, DnsAnswer **answer); +int dns_trust_anchor_lookup_negative(DnsTrustAnchor *d, const char *name); + +int dns_trust_anchor_check_revoked(DnsTrustAnchor *d, DnsResourceRecord *dnskey, DnsAnswer *rrs); +int dns_trust_anchor_is_revoked(DnsTrustAnchor *d, DnsResourceRecord *rr); diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c new file mode 100644 index 00000000..d5cc2767 --- /dev/null +++ b/src/resolve/resolved-dns-zone.c @@ -0,0 +1,704 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "dns-domain.h" +#include "list.h" +#include "resolved-dns-packet.h" +#include "resolved-dns-zone.h" +#include "resolved-dnssd.h" +#include "string-util.h" + +/* Never allow more than 1K entries */ +#define ZONE_MAX 1024 + +void dns_zone_item_probe_stop(DnsZoneItem *i) { + DnsTransaction *t; + assert(i); + + if (!i->probe_transaction) + return; + + t = TAKE_PTR(i->probe_transaction); + + set_remove(t->notify_zone_items, i); + set_remove(t->notify_zone_items_done, i); + dns_transaction_gc(t); +} + +static void dns_zone_item_free(DnsZoneItem *i) { + if (!i) + return; + + dns_zone_item_probe_stop(i); + dns_resource_record_unref(i->rr); + + free(i); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnsZoneItem*, dns_zone_item_free); + +static void dns_zone_item_remove_and_free(DnsZone *z, DnsZoneItem *i) { + DnsZoneItem *first; + + assert(z); + + if (!i) + return; + + first = hashmap_get(z->by_key, i->rr->key); + LIST_REMOVE(by_key, first, i); + if (first) + assert_se(hashmap_replace(z->by_key, first->rr->key, first) >= 0); + else + hashmap_remove(z->by_key, i->rr->key); + + first = hashmap_get(z->by_name, dns_resource_key_name(i->rr->key)); + LIST_REMOVE(by_name, first, i); + if (first) + assert_se(hashmap_replace(z->by_name, dns_resource_key_name(first->rr->key), first) >= 0); + else + hashmap_remove(z->by_name, dns_resource_key_name(i->rr->key)); + + dns_zone_item_free(i); +} + +void dns_zone_flush(DnsZone *z) { + DnsZoneItem *i; + + assert(z); + + while ((i = hashmap_first(z->by_key))) + dns_zone_item_remove_and_free(z, i); + + assert(hashmap_size(z->by_key) == 0); + assert(hashmap_size(z->by_name) == 0); + + z->by_key = hashmap_free(z->by_key); + z->by_name = hashmap_free(z->by_name); +} + +DnsZoneItem* dns_zone_get(DnsZone *z, DnsResourceRecord *rr) { + DnsZoneItem *i; + + assert(z); + assert(rr); + + LIST_FOREACH(by_key, i, hashmap_get(z->by_key, rr->key)) + if (dns_resource_record_equal(i->rr, rr) > 0) + return i; + + return NULL; +} + +void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr) { + DnsZoneItem *i; + + assert(z); + assert(rr); + + i = dns_zone_get(z, rr); + if (i) + dns_zone_item_remove_and_free(z, i); +} + +int dns_zone_remove_rrs_by_key(DnsZone *z, DnsResourceKey *key) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL; + DnsResourceRecord *rr; + bool tentative; + int r; + + r = dns_zone_lookup(z, key, 0, &answer, &soa, &tentative); + if (r < 0) + return r; + + DNS_ANSWER_FOREACH(rr, answer) + dns_zone_remove_rr(z, rr); + + return 0; +} + +static int dns_zone_init(DnsZone *z) { + int r; + + assert(z); + + r = hashmap_ensure_allocated(&z->by_key, &dns_resource_key_hash_ops); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&z->by_name, &dns_name_hash_ops); + if (r < 0) + return r; + + return 0; +} + +static int dns_zone_link_item(DnsZone *z, DnsZoneItem *i) { + DnsZoneItem *first; + int r; + + first = hashmap_get(z->by_key, i->rr->key); + if (first) { + LIST_PREPEND(by_key, first, i); + assert_se(hashmap_replace(z->by_key, first->rr->key, first) >= 0); + } else { + r = hashmap_put(z->by_key, i->rr->key, i); + if (r < 0) + return r; + } + + first = hashmap_get(z->by_name, dns_resource_key_name(i->rr->key)); + if (first) { + LIST_PREPEND(by_name, first, i); + assert_se(hashmap_replace(z->by_name, dns_resource_key_name(first->rr->key), first) >= 0); + } else { + r = hashmap_put(z->by_name, dns_resource_key_name(i->rr->key), i); + if (r < 0) + return r; + } + + return 0; +} + +static int dns_zone_item_probe_start(DnsZoneItem *i) { + DnsTransaction *t; + int r; + + assert(i); + + if (i->probe_transaction) + return 0; + + t = dns_scope_find_transaction(i->scope, &DNS_RESOURCE_KEY_CONST(i->rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(i->rr->key)), false); + if (!t) { + _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL; + + key = dns_resource_key_new(i->rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(i->rr->key)); + if (!key) + return -ENOMEM; + + r = dns_transaction_new(&t, i->scope, key); + if (r < 0) + return r; + } + + r = set_ensure_allocated(&t->notify_zone_items, NULL); + if (r < 0) + goto gc; + + r = set_ensure_allocated(&t->notify_zone_items_done, NULL); + if (r < 0) + goto gc; + + r = set_put(t->notify_zone_items, i); + if (r < 0) + goto gc; + + i->probe_transaction = t; + t->probing = true; + + if (t->state == DNS_TRANSACTION_NULL) { + + i->block_ready++; + r = dns_transaction_go(t); + i->block_ready--; + + if (r < 0) { + dns_zone_item_probe_stop(i); + return r; + } + } + + dns_zone_item_notify(i); + return 0; + +gc: + dns_transaction_gc(t); + return r; +} + +int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) { + _cleanup_(dns_zone_item_freep) DnsZoneItem *i = NULL; + DnsZoneItem *existing; + int r; + + assert(z); + assert(s); + assert(rr); + + if (dns_class_is_pseudo(rr->key->class)) + return -EINVAL; + if (dns_type_is_pseudo(rr->key->type)) + return -EINVAL; + + existing = dns_zone_get(z, rr); + if (existing) + return 0; + + r = dns_zone_init(z); + if (r < 0) + return r; + + i = new0(DnsZoneItem, 1); + if (!i) + return -ENOMEM; + + i->scope = s; + i->rr = dns_resource_record_ref(rr); + i->probing_enabled = probe; + + r = dns_zone_link_item(z, i); + if (r < 0) + return r; + + if (probe) { + DnsZoneItem *first, *j; + bool established = false; + + /* Check if there's already an RR with the same name + * established. If so, it has been probed already, and + * we don't need to probe again. */ + + LIST_FIND_HEAD(by_name, i, first); + LIST_FOREACH(by_name, j, first) { + if (i == j) + continue; + + if (j->state == DNS_ZONE_ITEM_ESTABLISHED) + established = true; + } + + if (established) + i->state = DNS_ZONE_ITEM_ESTABLISHED; + else { + i->state = DNS_ZONE_ITEM_PROBING; + + r = dns_zone_item_probe_start(i); + if (r < 0) { + dns_zone_item_remove_and_free(z, i); + i = NULL; + return r; + } + } + } else + i->state = DNS_ZONE_ITEM_ESTABLISHED; + + i = NULL; + return 0; +} + +static int dns_zone_add_authenticated_answer(DnsAnswer *a, DnsZoneItem *i, int ifindex) { + DnsAnswerFlags flags; + + /* From RFC 6762, Section 10.2 + * "They (the rules about when to set the cache-flush bit) apply to + * startup announcements as described in Section 8.3, "Announcing", + * and to responses generated as a result of receiving query messages." + * So, set the cache-flush bit for mDNS answers except for DNS-SD + * service enumeration PTRs described in RFC 6763, Section 4.1. */ + if (i->scope->protocol == DNS_PROTOCOL_MDNS && + !dns_resource_key_is_dnssd_ptr(i->rr->key)) + flags = DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHE_FLUSH; + else + flags = DNS_ANSWER_AUTHENTICATED; + + return dns_answer_add(a, i->rr, ifindex, flags); +} + +int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, int ifindex, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL; + unsigned n_answer = 0; + DnsZoneItem *j, *first; + bool tentative = true, need_soa = false; + int r; + + /* Note that we don't actually need the ifindex for anything. However when it is passed we'll initialize the + * ifindex field in the answer with it */ + + assert(z); + assert(key); + assert(ret_answer); + + /* First iteration, count what we have */ + + if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) { + bool found = false, added = false; + int k; + + /* If this is a generic match, then we have to + * go through the list by the name and look + * for everything manually */ + + first = hashmap_get(z->by_name, dns_resource_key_name(key)); + LIST_FOREACH(by_name, j, first) { + if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) + continue; + + found = true; + + k = dns_resource_key_match_rr(key, j->rr, NULL); + if (k < 0) + return k; + if (k > 0) { + n_answer++; + added = true; + } + + } + + if (found && !added) + need_soa = true; + + } else { + bool found = false; + + /* If this is a specific match, then look for + * the right key immediately */ + + first = hashmap_get(z->by_key, key); + LIST_FOREACH(by_key, j, first) { + if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) + continue; + + found = true; + n_answer++; + } + + if (!found) { + first = hashmap_get(z->by_name, dns_resource_key_name(key)); + LIST_FOREACH(by_name, j, first) { + if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) + continue; + + need_soa = true; + break; + } + } + } + + if (n_answer <= 0 && !need_soa) + goto return_empty; + + if (n_answer > 0) { + answer = dns_answer_new(n_answer); + if (!answer) + return -ENOMEM; + } + + if (need_soa) { + soa = dns_answer_new(1); + if (!soa) + return -ENOMEM; + } + + /* Second iteration, actually add the RRs to the answers */ + if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) { + bool found = false, added = false; + int k; + + first = hashmap_get(z->by_name, dns_resource_key_name(key)); + LIST_FOREACH(by_name, j, first) { + if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) + continue; + + found = true; + + if (j->state != DNS_ZONE_ITEM_PROBING) + tentative = false; + + k = dns_resource_key_match_rr(key, j->rr, NULL); + if (k < 0) + return k; + if (k > 0) { + r = dns_zone_add_authenticated_answer(answer, j, ifindex); + if (r < 0) + return r; + + added = true; + } + } + + if (found && !added) { + r = dns_answer_add_soa(soa, dns_resource_key_name(key), LLMNR_DEFAULT_TTL, ifindex); + if (r < 0) + return r; + } + } else { + bool found = false; + + first = hashmap_get(z->by_key, key); + LIST_FOREACH(by_key, j, first) { + if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) + continue; + + found = true; + + if (j->state != DNS_ZONE_ITEM_PROBING) + tentative = false; + + r = dns_zone_add_authenticated_answer(answer, j, ifindex); + if (r < 0) + return r; + } + + if (!found) { + bool add_soa = false; + + first = hashmap_get(z->by_name, dns_resource_key_name(key)); + LIST_FOREACH(by_name, j, first) { + if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) + continue; + + if (j->state != DNS_ZONE_ITEM_PROBING) + tentative = false; + + add_soa = true; + } + + if (add_soa) { + r = dns_answer_add_soa(soa, dns_resource_key_name(key), LLMNR_DEFAULT_TTL, ifindex); + if (r < 0) + return r; + } + } + } + + /* If the caller sets ret_tentative to NULL, then use this as + * indication to not return tentative entries */ + + if (!ret_tentative && tentative) + goto return_empty; + + *ret_answer = TAKE_PTR(answer); + + if (ret_soa) + *ret_soa = TAKE_PTR(soa); + + if (ret_tentative) + *ret_tentative = tentative; + + return 1; + +return_empty: + *ret_answer = NULL; + + if (ret_soa) + *ret_soa = NULL; + + if (ret_tentative) + *ret_tentative = false; + + return 0; +} + +void dns_zone_item_conflict(DnsZoneItem *i) { + assert(i); + + if (!IN_SET(i->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_VERIFYING, DNS_ZONE_ITEM_ESTABLISHED)) + return; + + log_info("Detected conflict on %s", strna(dns_resource_record_to_string(i->rr))); + + dns_zone_item_probe_stop(i); + + /* Withdraw the conflict item */ + i->state = DNS_ZONE_ITEM_WITHDRAWN; + + dnssd_signal_conflict(i->scope->manager, dns_resource_key_name(i->rr->key)); + + /* Maybe change the hostname */ + if (manager_is_own_hostname(i->scope->manager, dns_resource_key_name(i->rr->key)) > 0) + manager_next_hostname(i->scope->manager); +} + +void dns_zone_item_notify(DnsZoneItem *i) { + assert(i); + assert(i->probe_transaction); + + if (i->block_ready > 0) + return; + + if (IN_SET(i->probe_transaction->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_VALIDATING)) + return; + + if (i->probe_transaction->state == DNS_TRANSACTION_SUCCESS) { + bool we_lost = false; + + /* The probe got a successful reply. If we so far + * weren't established we just give up. + * + * In LLMNR case if we already + * were established, and the peer has the + * lexicographically larger IP address we continue + * and defend it. */ + + if (!IN_SET(i->state, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) { + log_debug("Got a successful probe for not yet established RR, we lost."); + we_lost = true; + } else if (i->probe_transaction->scope->protocol == DNS_PROTOCOL_LLMNR) { + assert(i->probe_transaction->received); + we_lost = memcmp(&i->probe_transaction->received->sender, &i->probe_transaction->received->destination, FAMILY_ADDRESS_SIZE(i->probe_transaction->received->family)) < 0; + if (we_lost) + log_debug("Got a successful probe reply for an established RR, and we have a lexicographically larger IP address and thus lost."); + } + + if (we_lost) { + dns_zone_item_conflict(i); + return; + } + + log_debug("Got a successful probe reply, but peer has lexicographically lower IP address and thus lost."); + } + + log_debug("Record %s successfully probed.", strna(dns_resource_record_to_string(i->rr))); + + dns_zone_item_probe_stop(i); + i->state = DNS_ZONE_ITEM_ESTABLISHED; +} + +static int dns_zone_item_verify(DnsZoneItem *i) { + int r; + + assert(i); + + if (i->state != DNS_ZONE_ITEM_ESTABLISHED) + return 0; + + log_debug("Verifying RR %s", strna(dns_resource_record_to_string(i->rr))); + + i->state = DNS_ZONE_ITEM_VERIFYING; + r = dns_zone_item_probe_start(i); + if (r < 0) { + log_error_errno(r, "Failed to start probing for verifying RR: %m"); + i->state = DNS_ZONE_ITEM_ESTABLISHED; + return r; + } + + return 0; +} + +int dns_zone_check_conflicts(DnsZone *zone, DnsResourceRecord *rr) { + DnsZoneItem *i, *first; + int c = 0; + + assert(zone); + assert(rr); + + /* This checks whether a response RR we received from somebody + * else is one that we actually thought was uniquely ours. If + * so, we'll verify our RRs. */ + + /* No conflict if we don't have the name at all. */ + first = hashmap_get(zone->by_name, dns_resource_key_name(rr->key)); + if (!first) + return 0; + + /* No conflict if we have the exact same RR */ + if (dns_zone_get(zone, rr)) + return 0; + + /* No conflict if it is DNS-SD RR used for service enumeration. */ + if (dns_resource_key_is_dnssd_ptr(rr->key)) + return 0; + + /* OK, somebody else has RRs for the same name. Yuck! Let's + * start probing again */ + + LIST_FOREACH(by_name, i, first) { + if (dns_resource_record_equal(i->rr, rr)) + continue; + + dns_zone_item_verify(i); + c++; + } + + return c; +} + +int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key) { + DnsZoneItem *i, *first; + int c = 0; + + assert(zone); + + /* Somebody else notified us about a possible conflict. Let's + * verify if that's true. */ + + first = hashmap_get(zone->by_name, dns_resource_key_name(key)); + if (!first) + return 0; + + LIST_FOREACH(by_name, i, first) { + dns_zone_item_verify(i); + c++; + } + + return c; +} + +void dns_zone_verify_all(DnsZone *zone) { + DnsZoneItem *i; + Iterator iterator; + + assert(zone); + + HASHMAP_FOREACH(i, zone->by_key, iterator) { + DnsZoneItem *j; + + LIST_FOREACH(by_key, j, i) + dns_zone_item_verify(j); + } +} + +void dns_zone_dump(DnsZone *zone, FILE *f) { + Iterator iterator; + DnsZoneItem *i; + + if (!zone) + return; + + if (!f) + f = stdout; + + HASHMAP_FOREACH(i, zone->by_key, iterator) { + DnsZoneItem *j; + + LIST_FOREACH(by_key, j, i) { + const char *t; + + t = dns_resource_record_to_string(j->rr); + if (!t) { + log_oom(); + continue; + } + + fputc('\t', f); + fputs(t, f); + fputc('\n', f); + } + } +} + +bool dns_zone_is_empty(DnsZone *zone) { + if (!zone) + return true; + + return hashmap_isempty(zone->by_key); +} + +bool dns_zone_contains_name(DnsZone *z, const char *name) { + DnsZoneItem *i, *first; + + first = hashmap_get(z->by_name, name); + if (!first) + return false; + + LIST_FOREACH(by_name, i, first) { + if (!IN_SET(i->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) + continue; + + return true; + } + + return false; +} diff --git a/src/resolve/resolved-dns-zone.h b/src/resolve/resolved-dns-zone.h new file mode 100644 index 00000000..2719b218 --- /dev/null +++ b/src/resolve/resolved-dns-zone.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "hashmap.h" + +typedef struct DnsZone { + Hashmap *by_key; + Hashmap *by_name; +} DnsZone; + +typedef struct DnsZoneItem DnsZoneItem; +typedef enum DnsZoneItemState DnsZoneItemState; + +#include "resolved-dns-answer.h" +#include "resolved-dns-question.h" +#include "resolved-dns-rr.h" +#include "resolved-dns-transaction.h" + +/* RFC 4795 Section 2.8. suggests a TTL of 30s by default */ +#define LLMNR_DEFAULT_TTL (30) + +/* RFC 6762 Section 10. suggests a TTL of 120s by default */ +#define MDNS_DEFAULT_TTL (120) + +enum DnsZoneItemState { + DNS_ZONE_ITEM_PROBING, + DNS_ZONE_ITEM_ESTABLISHED, + DNS_ZONE_ITEM_VERIFYING, + DNS_ZONE_ITEM_WITHDRAWN, +}; + +struct DnsZoneItem { + DnsScope *scope; + DnsResourceRecord *rr; + + DnsZoneItemState state; + + unsigned block_ready; + + bool probing_enabled; + + LIST_FIELDS(DnsZoneItem, by_key); + LIST_FIELDS(DnsZoneItem, by_name); + + DnsTransaction *probe_transaction; +}; + +void dns_zone_flush(DnsZone *z); + +int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe); +DnsZoneItem* dns_zone_get(DnsZone *z, DnsResourceRecord *rr); +void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr); +int dns_zone_remove_rrs_by_key(DnsZone *z, DnsResourceKey *key); + +int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, int ifindex, DnsAnswer **answer, DnsAnswer **soa, bool *tentative); + +void dns_zone_item_conflict(DnsZoneItem *i); +void dns_zone_item_notify(DnsZoneItem *i); + +int dns_zone_check_conflicts(DnsZone *zone, DnsResourceRecord *rr); +int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key); + +void dns_zone_verify_all(DnsZone *zone); + +void dns_zone_item_probe_stop(DnsZoneItem *i); + +void dns_zone_dump(DnsZone *zone, FILE *f); +bool dns_zone_is_empty(DnsZone *zone); +bool dns_zone_contains_name(DnsZone *z, const char *name); diff --git a/src/resolve/resolved-dnssd-bus.c b/src/resolve/resolved-dnssd-bus.c new file mode 100644 index 00000000..f7dcb3bf --- /dev/null +++ b/src/resolve/resolved-dnssd-bus.c @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-polkit.h" +#include "missing_capability.h" +#include "resolved-dnssd-bus.h" +#include "resolved-dnssd.h" +#include "resolved-link.h" +#include "strv.h" +#include "user-util.h" + +int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_error *error) { + DnssdService *s = userdata; + DnssdTxtData *txt_data; + Manager *m; + Iterator i; + Link *l; + int r; + + assert(message); + assert(s); + + m = s->manager; + + r = bus_verify_polkit_async(message, CAP_SYS_ADMIN, + "org.freedesktop.resolve1.unregister-service", + NULL, false, s->originator, + &m->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + HASHMAP_FOREACH(l, m->links, i) { + if (l->mdns_ipv4_scope) { + r = dns_scope_announce(l->mdns_ipv4_scope, true); + if (r < 0) + log_warning_errno(r, "Failed to send goodbye messages in IPv4 scope: %m"); + + dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, s->ptr_rr); + dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, s->srv_rr); + LIST_FOREACH(items, txt_data, s->txt_data_items) + dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, txt_data->rr); + } + + if (l->mdns_ipv6_scope) { + r = dns_scope_announce(l->mdns_ipv6_scope, true); + if (r < 0) + log_warning_errno(r, "Failed to send goodbye messages in IPv6 scope: %m"); + + dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, s->ptr_rr); + dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, s->srv_rr); + LIST_FOREACH(items, txt_data, s->txt_data_items) + dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, txt_data->rr); + } + } + + dnssd_service_free(s); + + manager_refresh_rrs(m); + + return sd_bus_reply_method_return(message, NULL); +} + +const sd_bus_vtable dnssd_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_METHOD("Unregister", NULL, NULL, bus_dnssd_method_unregister, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_SIGNAL("Conflicted", NULL, 0), + + SD_BUS_VTABLE_END +}; + +int dnssd_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + _cleanup_free_ char *name = NULL; + Manager *m = userdata; + DnssdService *service; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/dnssd", &name); + if (r <= 0) + return 0; + + service = hashmap_get(m->dnssd_services, name); + if (!service) + return 0; + + *found = service; + return 1; +} + +int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + DnssdService *service; + Iterator i; + unsigned c = 0; + int r; + + assert(bus); + assert(path); + assert(m); + assert(nodes); + + l = new0(char*, hashmap_size(m->dnssd_services) + 1); + if (!l) + return -ENOMEM; + + HASHMAP_FOREACH(service, m->dnssd_services, i) { + char *p; + + r = sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", service->name, &p); + if (r < 0) + return r; + + l[c++] = p; + } + + l[c] = NULL; + *nodes = TAKE_PTR(l); + + return 1; +} diff --git a/src/resolve/resolved-dnssd-bus.h b/src/resolve/resolved-dnssd-bus.h new file mode 100644 index 00000000..9ee2ce17 --- /dev/null +++ b/src/resolve/resolved-dnssd-bus.h @@ -0,0 +1,10 @@ +#pragma once + +#include "sd-bus.h" + +extern const sd_bus_vtable dnssd_vtable[]; + +int dnssd_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); + +int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/resolve/resolved-dnssd-gperf.gperf b/src/resolve/resolved-dnssd-gperf.gperf new file mode 100644 index 00000000..2780b856 --- /dev/null +++ b/src/resolve/resolved-dnssd-gperf.gperf @@ -0,0 +1,24 @@ +%{ +#include +#include "conf-parser.h" +#include "resolved-conf.h" +#include "resolved-dnssd.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name resolved_dnssd_gperf_hash +%define lookup-function-name resolved_dnssd_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +Service.Name, config_parse_dnssd_service_name, 0, 0 +Service.Type, config_parse_dnssd_service_type, 0, 0 +Service.Port, config_parse_ip_port, 0, offsetof(DnssdService, port) +Service.Priority, config_parse_uint16, 0, offsetof(DnssdService, priority) +Service.Weight, config_parse_uint16, 0, offsetof(DnssdService, weight) +Service.TxtText, config_parse_dnssd_txt, DNS_TXT_ITEM_TEXT, 0 +Service.TxtData, config_parse_dnssd_txt, DNS_TXT_ITEM_DATA, 0 diff --git a/src/resolve/resolved-dnssd.c b/src/resolve/resolved-dnssd.c new file mode 100644 index 00000000..0e6fa1d0 --- /dev/null +++ b/src/resolve/resolved-dnssd.c @@ -0,0 +1,360 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "conf-files.h" +#include "conf-parser.h" +#include "def.h" +#include "resolved-dnssd.h" +#include "resolved-dns-rr.h" +#include "resolved-manager.h" +#include "specifier.h" +#include "strv.h" + +#define DNSSD_SERVICE_DIRS ((const char* const*) CONF_PATHS_STRV("systemd/dnssd")) + +DnssdTxtData *dnssd_txtdata_free(DnssdTxtData *txt_data) { + if (!txt_data) + return NULL; + + dns_resource_record_unref(txt_data->rr); + dns_txt_item_free_all(txt_data->txt); + + return mfree(txt_data); +} + +DnssdTxtData *dnssd_txtdata_free_all(DnssdTxtData *txt_data) { + DnssdTxtData *next; + + if (!txt_data) + return NULL; + + next = txt_data->items_next; + + dnssd_txtdata_free(txt_data); + + return dnssd_txtdata_free_all(next); +} + +DnssdService *dnssd_service_free(DnssdService *service) { + if (!service) + return NULL; + + if (service->manager) + hashmap_remove(service->manager->dnssd_services, service->name); + + dns_resource_record_unref(service->ptr_rr); + dns_resource_record_unref(service->srv_rr); + + dnssd_txtdata_free_all(service->txt_data_items); + + free(service->filename); + free(service->name); + free(service->type); + free(service->name_template); + + return mfree(service); +} + +static int dnssd_service_load(Manager *manager, const char *filename) { + _cleanup_(dnssd_service_freep) DnssdService *service = NULL; + _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL; + char *d; + const char *dropin_dirname; + int r; + + assert(manager); + assert(filename); + + service = new0(DnssdService, 1); + if (!service) + return log_oom(); + + service->filename = strdup(filename); + if (!service->filename) + return log_oom(); + + service->name = strdup(basename(filename)); + if (!service->name) + return log_oom(); + + d = endswith(service->name, ".dnssd"); + if (!d) + return -EINVAL; + + assert(streq(d, ".dnssd")); + + *d = '\0'; + + dropin_dirname = strjoina(service->name, ".dnssd.d"); + + r = config_parse_many(filename, DNSSD_SERVICE_DIRS, dropin_dirname, + "Service\0", + config_item_perf_lookup, resolved_dnssd_gperf_lookup, + false, service); + if (r < 0) + return r; + + if (!service->name_template) { + log_error("%s doesn't define service instance name", service->name); + return -EINVAL; + } + + if (!service->type) { + log_error("%s doesn't define service type", service->name); + return -EINVAL; + } + + if (LIST_IS_EMPTY(service->txt_data_items)) { + txt_data = new0(DnssdTxtData, 1); + if (!txt_data) + return log_oom(); + + r = dns_txt_item_new_empty(&txt_data->txt); + if (r < 0) + return r; + + LIST_PREPEND(items, service->txt_data_items, txt_data); + txt_data = NULL; + } + + r = hashmap_ensure_allocated(&manager->dnssd_services, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(manager->dnssd_services, service->name, service); + if (r < 0) + return r; + + service->manager = manager; + + r = dnssd_update_rrs(service); + if (r < 0) + return r; + + service = NULL; + + return 0; +} + +static int specifier_dnssd_host_name(char specifier, const void *data, const void *userdata, char **ret) { + DnssdService *s = (DnssdService *) userdata; + char *n; + + assert(s); + assert(s->manager); + assert(s->manager->llmnr_hostname); + + n = strdup(s->manager->llmnr_hostname); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; +} + +int dnssd_render_instance_name(DnssdService *s, char **ret_name) { + static const Specifier specifier_table[] = { + { 'b', specifier_boot_id, NULL }, + { 'H', specifier_dnssd_host_name, NULL }, + { 'm', specifier_machine_id, NULL }, + { 'v', specifier_kernel_release, NULL }, + {} + }; + _cleanup_free_ char *name = NULL; + int r; + + assert(s); + assert(s->name_template); + + r = specifier_printf(s->name_template, specifier_table, s, &name); + if (r < 0) + return log_debug_errno(r, "Failed to replace specifiers: %m"); + + if (!dns_service_name_is_valid(name)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Service instance name '%s' is invalid.", + name); + + *ret_name = TAKE_PTR(name); + + return 0; +} + +int dnssd_load(Manager *manager) { + _cleanup_strv_free_ char **files = NULL; + char **f; + int r; + + assert(manager); + + if (manager->mdns_support != RESOLVE_SUPPORT_YES) + return 0; + + r = conf_files_list_strv(&files, ".dnssd", NULL, 0, DNSSD_SERVICE_DIRS); + if (r < 0) + return log_error_errno(r, "Failed to enumerate .dnssd files: %m"); + + STRV_FOREACH_BACKWARDS(f, files) { + r = dnssd_service_load(manager, *f); + if (r < 0) + log_warning_errno(r, "Failed to load '%s': %m", *f);; + } + + return 0; +} + +int dnssd_update_rrs(DnssdService *s) { + _cleanup_free_ char *n = NULL; + _cleanup_free_ char *service_name = NULL; + _cleanup_free_ char *full_name = NULL; + DnssdTxtData *txt_data; + int r; + + assert(s); + assert(s->txt_data_items); + assert(s->manager); + + s->ptr_rr = dns_resource_record_unref(s->ptr_rr); + s->srv_rr = dns_resource_record_unref(s->srv_rr); + LIST_FOREACH(items, txt_data, s->txt_data_items) + txt_data->rr = dns_resource_record_unref(txt_data->rr); + + r = dnssd_render_instance_name(s, &n); + if (r < 0) + return r; + + r = dns_name_concat(s->type, "local", 0, &service_name); + if (r < 0) + return r; + r = dns_name_concat(n, service_name, 0, &full_name); + if (r < 0) + return r; + + LIST_FOREACH(items, txt_data, s->txt_data_items) { + txt_data->rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_TXT, + full_name); + if (!txt_data->rr) + goto oom; + + txt_data->rr->ttl = MDNS_DEFAULT_TTL; + txt_data->rr->txt.items = dns_txt_item_copy(txt_data->txt); + if (!txt_data->rr->txt.items) + goto oom; + } + + s->ptr_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, + service_name); + if (!s->ptr_rr) + goto oom; + + s->ptr_rr->ttl = MDNS_DEFAULT_TTL; + s->ptr_rr->ptr.name = strdup(full_name); + if (!s->ptr_rr->ptr.name) + goto oom; + + s->srv_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SRV, + full_name); + if (!s->srv_rr) + goto oom; + + s->srv_rr->ttl = MDNS_DEFAULT_TTL; + s->srv_rr->srv.priority = s->priority; + s->srv_rr->srv.weight = s->weight; + s->srv_rr->srv.port = s->port; + s->srv_rr->srv.name = strdup(s->manager->mdns_hostname); + if (!s->srv_rr->srv.name) + goto oom; + + return 0; + +oom: + LIST_FOREACH(items, txt_data, s->txt_data_items) + txt_data->rr = dns_resource_record_unref(txt_data->rr); + s->ptr_rr = dns_resource_record_unref(s->ptr_rr); + s->srv_rr = dns_resource_record_unref(s->srv_rr); + return -ENOMEM; +} + +int dnssd_txt_item_new_from_string(const char *key, const char *value, DnsTxtItem **ret_item) { + size_t length; + DnsTxtItem *i; + + length = strlen(key); + + if (!isempty(value)) + length += strlen(value) + 1; /* length of value plus '=' */ + + i = malloc0(offsetof(DnsTxtItem, data) + length + 1); /* for safety reasons we add an extra NUL byte */ + if (!i) + return -ENOMEM; + + memcpy(i->data, key, strlen(key)); + if (!isempty(value)) { + memcpy(i->data + strlen(key), "=", 1); + memcpy(i->data + strlen(key) + 1, value, strlen(value)); + } + i->length = length; + + *ret_item = TAKE_PTR(i); + + return 0; +} + +int dnssd_txt_item_new_from_data(const char *key, const void *data, const size_t size, DnsTxtItem **ret_item) { + size_t length; + DnsTxtItem *i; + + length = strlen(key); + + if (size > 0) + length += size + 1; /* size of date plus '=' */ + + i = malloc0(offsetof(DnsTxtItem, data) + length + 1); /* for safety reasons we add an extra NUL byte */ + if (!i) + return -ENOMEM; + + memcpy(i->data, key, strlen(key)); + if (size > 0) { + memcpy(i->data + strlen(key), "=", 1); + memcpy(i->data + strlen(key) + 1, data, size); + } + i->length = length; + + *ret_item = TAKE_PTR(i); + + return 0; +} + +void dnssd_signal_conflict(Manager *manager, const char *name) { + Iterator i; + DnssdService *s; + int r; + + HASHMAP_FOREACH(s, manager->dnssd_services, i) { + if (s->withdrawn) + continue; + + if (dns_name_equal(dns_resource_key_name(s->srv_rr->key), name)) { + _cleanup_free_ char *path = NULL; + + s->withdrawn = true; + + r = sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", s->name, &path); + if (r < 0) { + log_error_errno(r, "Can't get D-BUS object path: %m"); + return; + } + + r = sd_bus_emit_signal(manager->bus, + path, + "org.freedesktop.resolve1.DnssdService", + "Conflicted", + NULL); + if (r < 0) { + log_error_errno(r, "Cannot emit signal: %m"); + return; + } + + break; + } + } +} diff --git a/src/resolve/resolved-dnssd.h b/src/resolve/resolved-dnssd.h new file mode 100644 index 00000000..f2e10145 --- /dev/null +++ b/src/resolve/resolved-dnssd.h @@ -0,0 +1,59 @@ +#pragma once + +#include "list.h" + +typedef struct DnssdService DnssdService; +typedef struct DnssdTxtData DnssdTxtData; + +typedef struct Manager Manager; +typedef struct DnsResourceRecord DnsResourceRecord; +typedef struct DnsTxtItem DnsTxtItem; + +enum { + DNS_TXT_ITEM_TEXT, + DNS_TXT_ITEM_DATA +}; + +struct DnssdTxtData { + DnsResourceRecord *rr; + + LIST_HEAD(DnsTxtItem, txt); + + LIST_FIELDS(DnssdTxtData, items); +}; + +struct DnssdService { + char *filename; + char *name; + char *name_template; + char *type; + uint16_t port; + uint16_t priority; + uint16_t weight; + + DnsResourceRecord *ptr_rr; + DnsResourceRecord *srv_rr; + + /* Section 6.8 of RFC 6763 allows having service + * instances with multiple TXT resource records. */ + LIST_HEAD(DnssdTxtData, txt_data_items); + + Manager *manager; + + bool withdrawn:1; + uid_t originator; +}; + +DnssdService *dnssd_service_free(DnssdService *service); +DnssdTxtData *dnssd_txtdata_free(DnssdTxtData *txt_data); +DnssdTxtData *dnssd_txtdata_free_all(DnssdTxtData *txt_data); + +DEFINE_TRIVIAL_CLEANUP_FUNC(DnssdService*, dnssd_service_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(DnssdTxtData*, dnssd_txtdata_free); + +int dnssd_render_instance_name(DnssdService *s, char **ret_name); +int dnssd_load(Manager *manager); +int dnssd_txt_item_new_from_string(const char *key, const char *value, DnsTxtItem **ret_item); +int dnssd_txt_item_new_from_data(const char *key, const void *value, const size_t size, DnsTxtItem **ret_item); +int dnssd_update_rrs(DnssdService *s); +void dnssd_signal_conflict(Manager *manager, const char *name); diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c new file mode 100644 index 00000000..ed0a31e8 --- /dev/null +++ b/src/resolve/resolved-dnstls-gnutls.c @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if !ENABLE_DNS_OVER_TLS || !DNS_OVER_TLS_USE_GNUTLS +#error This source file requires DNS-over-TLS to be enabled and GnuTLS to be available. +#endif + +#include + +#include "resolved-dns-stream.h" +#include "resolved-dnstls.h" + +#define TLS_PROTOCOL_PRIORITY "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2" +DEFINE_TRIVIAL_CLEANUP_FUNC(gnutls_session_t, gnutls_deinit); + +static ssize_t dnstls_stream_writev(gnutls_transport_ptr_t p, const giovec_t *iov, int iovcnt) { + int r; + + assert(p); + + r = dns_stream_writev((DnsStream*) p, (const struct iovec*) iov, iovcnt, DNS_STREAM_WRITE_TLS_DATA); + if (r < 0) { + errno = -r; + return -1; + } + + return r; +} + +int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + _cleanup_(gnutls_deinitp) gnutls_session_t gs; + int r; + + assert(stream); + assert(server); + + r = gnutls_init(&gs, GNUTLS_CLIENT | GNUTLS_ENABLE_FALSE_START | GNUTLS_NONBLOCK); + if (r < 0) + return r; + + /* As DNS-over-TLS is a recent protocol, older TLS versions can be disabled */ + r = gnutls_priority_set_direct(gs, TLS_PROTOCOL_PRIORITY, NULL); + if (r < 0) + return r; + + r = gnutls_credentials_set(gs, GNUTLS_CRD_CERTIFICATE, stream->manager->dnstls_data.cert_cred); + if (r < 0) + return r; + + if (server->dnstls_data.session_data.size > 0) { + gnutls_session_set_data(gs, server->dnstls_data.session_data.data, server->dnstls_data.session_data.size); + + // Clear old session ticket + gnutls_free(server->dnstls_data.session_data.data); + server->dnstls_data.session_data.data = NULL; + server->dnstls_data.session_data.size = 0; + } + + if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { + stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS; + if (server->family == AF_INET) { + stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr; + stream->dnstls_data.validation.size = 4; + } else { + stream->dnstls_data.validation.data = server->address.in6.s6_addr; + stream->dnstls_data.validation.size = 16; + } + gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0); + } + + gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); + + gnutls_transport_set_ptr2(gs, (gnutls_transport_ptr_t) (long) stream->fd, stream); + gnutls_transport_set_vec_push_function(gs, &dnstls_stream_writev); + + stream->encrypted = true; + stream->dnstls_data.handshake = gnutls_handshake(gs); + if (stream->dnstls_data.handshake < 0 && gnutls_error_is_fatal(stream->dnstls_data.handshake)) + return -ECONNREFUSED; + + stream->dnstls_data.session = TAKE_PTR(gs); + + return 0; +} + +void dnstls_stream_free(DnsStream *stream) { + assert(stream); + assert(stream->encrypted); + + if (stream->dnstls_data.session) + gnutls_deinit(stream->dnstls_data.session); +} + +int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) { + int r; + + assert(stream); + assert(stream->encrypted); + assert(stream->dnstls_data.session); + + if (stream->dnstls_data.shutdown) { + r = gnutls_bye(stream->dnstls_data.session, GNUTLS_SHUT_RDWR); + if (r == GNUTLS_E_AGAIN) { + stream->dnstls_events = gnutls_record_get_direction(stream->dnstls_data.session) == 1 ? EPOLLOUT : EPOLLIN; + return -EAGAIN; + } else if (r < 0) + log_debug("Failed to invoke gnutls_bye: %s", gnutls_strerror(r)); + + stream->dnstls_events = 0; + stream->dnstls_data.shutdown = false; + dns_stream_unref(stream); + return DNSTLS_STREAM_CLOSED; + } else if (stream->dnstls_data.handshake < 0) { + stream->dnstls_data.handshake = gnutls_handshake(stream->dnstls_data.session); + if (stream->dnstls_data.handshake == GNUTLS_E_AGAIN) { + stream->dnstls_events = gnutls_record_get_direction(stream->dnstls_data.session) == 1 ? EPOLLOUT : EPOLLIN; + return -EAGAIN; + } else if (stream->dnstls_data.handshake < 0) { + log_debug("Failed to invoke gnutls_handshake: %s", gnutls_strerror(stream->dnstls_data.handshake)); + if (gnutls_error_is_fatal(stream->dnstls_data.handshake)) + return -ECONNREFUSED; + } + + stream->dnstls_events = 0; + } + + return 0; +} + +int dnstls_stream_shutdown(DnsStream *stream, int error) { + int r; + + assert(stream); + assert(stream->encrypted); + assert(stream->dnstls_data.session); + + /* Store TLS Ticket for faster successive TLS handshakes */ + if (stream->server && stream->server->dnstls_data.session_data.size == 0 && stream->dnstls_data.handshake == GNUTLS_E_SUCCESS) + gnutls_session_get_data2(stream->dnstls_data.session, &stream->server->dnstls_data.session_data); + + if (IN_SET(error, ETIMEDOUT, 0)) { + r = gnutls_bye(stream->dnstls_data.session, GNUTLS_SHUT_RDWR); + if (r == GNUTLS_E_AGAIN) { + if (!stream->dnstls_data.shutdown) { + stream->dnstls_data.shutdown = true; + dns_stream_ref(stream); + return -EAGAIN; + } + } else if (r < 0) + log_debug("Failed to invoke gnutls_bye: %s", gnutls_strerror(r)); + } + + return 0; +} + +ssize_t dnstls_stream_write(DnsStream *stream, const char *buf, size_t count) { + ssize_t ss; + + assert(stream); + assert(stream->encrypted); + assert(stream->dnstls_data.session); + assert(buf); + + ss = gnutls_record_send(stream->dnstls_data.session, buf, count); + if (ss < 0) + switch(ss) { + case GNUTLS_E_INTERRUPTED: + return -EINTR; + case GNUTLS_E_AGAIN: + return -EAGAIN; + default: + return log_debug_errno(SYNTHETIC_ERRNO(EPIPE), + "Failed to invoke gnutls_record_send: %s", + gnutls_strerror(ss)); + } + + return ss; +} + +ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) { + ssize_t ss; + + assert(stream); + assert(stream->encrypted); + assert(stream->dnstls_data.session); + assert(buf); + + ss = gnutls_record_recv(stream->dnstls_data.session, buf, count); + if (ss < 0) + switch(ss) { + case GNUTLS_E_INTERRUPTED: + return -EINTR; + case GNUTLS_E_AGAIN: + return -EAGAIN; + default: + return log_debug_errno(SYNTHETIC_ERRNO(EPIPE), + "Failed to invoke gnutls_record_recv: %s", + gnutls_strerror(ss)); + } + + return ss; +} + +void dnstls_server_free(DnsServer *server) { + assert(server); + + if (server->dnstls_data.session_data.data) + gnutls_free(server->dnstls_data.session_data.data); +} + +int dnstls_manager_init(Manager *manager) { + int r; + assert(manager); + + r = gnutls_certificate_allocate_credentials(&manager->dnstls_data.cert_cred); + if (r < 0) + return -ENOMEM; + + r = gnutls_certificate_set_x509_system_trust(manager->dnstls_data.cert_cred); + if (r < 0) + log_warning("Failed to load system trust store: %s", gnutls_strerror(r)); + + return 0; +} + +void dnstls_manager_free(Manager *manager) { + assert(manager); + + if (manager->dnstls_data.cert_cred) + gnutls_certificate_free_credentials(manager->dnstls_data.cert_cred); +} diff --git a/src/resolve/resolved-dnstls-gnutls.h b/src/resolve/resolved-dnstls-gnutls.h new file mode 100644 index 00000000..d4da2017 --- /dev/null +++ b/src/resolve/resolved-dnstls-gnutls.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if !ENABLE_DNS_OVER_TLS || !DNS_OVER_TLS_USE_GNUTLS +#error This source file requires DNS-over-TLS to be enabled and GnuTLS to be available. +#endif + +#include +#include + +struct DnsTlsManagerData { + gnutls_certificate_credentials_t cert_cred; +}; + +struct DnsTlsServerData { + gnutls_datum_t session_data; +}; + +struct DnsTlsStreamData { + gnutls_session_t session; + gnutls_typed_vdata_st validation; + int handshake; + bool shutdown; +}; diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c new file mode 100644 index 00000000..85e202ff --- /dev/null +++ b/src/resolve/resolved-dnstls-openssl.c @@ -0,0 +1,383 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if !ENABLE_DNS_OVER_TLS || !DNS_OVER_TLS_USE_OPENSSL +#error This source file requires DNS-over-TLS to be enabled and OpenSSL to be available. +#endif + +#include +#include + +#include "io-util.h" +#include "resolved-dns-stream.h" +#include "resolved-dnstls.h" + +DEFINE_TRIVIAL_CLEANUP_FUNC(SSL*, SSL_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(BIO*, BIO_free); + +static int dnstls_flush_write_buffer(DnsStream *stream) { + ssize_t ss; + + assert(stream); + assert(stream->encrypted); + + if (stream->dnstls_data.buffer_offset < stream->dnstls_data.write_buffer->length) { + assert(stream->dnstls_data.write_buffer->data); + + struct iovec iov[1]; + iov[0] = IOVEC_MAKE(stream->dnstls_data.write_buffer->data + stream->dnstls_data.buffer_offset, + stream->dnstls_data.write_buffer->length - stream->dnstls_data.buffer_offset); + ss = dns_stream_writev(stream, iov, 1, DNS_STREAM_WRITE_TLS_DATA); + if (ss < 0) { + if (ss == -EAGAIN) + stream->dnstls_events |= EPOLLOUT; + + return ss; + } else { + stream->dnstls_data.buffer_offset += ss; + + if (stream->dnstls_data.buffer_offset < stream->dnstls_data.write_buffer->length) { + stream->dnstls_events |= EPOLLOUT; + return -EAGAIN; + } else { + BIO_reset(SSL_get_wbio(stream->dnstls_data.ssl)); + stream->dnstls_data.buffer_offset = 0; + } + } + } + + return 0; +} + +int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + _cleanup_(BIO_freep) BIO *rb = NULL, *wb = NULL; + _cleanup_(SSL_freep) SSL *s = NULL; + int error, r; + + assert(stream); + assert(stream->manager); + assert(server); + + rb = BIO_new_socket(stream->fd, 0); + if (!rb) + return -ENOMEM; + + wb = BIO_new(BIO_s_mem()); + if (!wb) + return -ENOMEM; + + BIO_get_mem_ptr(wb, &stream->dnstls_data.write_buffer); + stream->dnstls_data.buffer_offset = 0; + + s = SSL_new(stream->manager->dnstls_data.ctx); + if (!s) + return -ENOMEM; + + SSL_set_connect_state(s); + SSL_set_session(s, server->dnstls_data.session); + SSL_set_bio(s, TAKE_PTR(rb), TAKE_PTR(wb)); + + if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { + X509_VERIFY_PARAM *v; + const unsigned char *ip; + + SSL_set_verify(s, SSL_VERIFY_PEER, NULL); + v = SSL_get0_param(s); + ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr; + if (!X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family))) + return -ECONNREFUSED; + } + + ERR_clear_error(); + stream->dnstls_data.handshake = SSL_do_handshake(s); + if (stream->dnstls_data.handshake <= 0) { + error = SSL_get_error(s, stream->dnstls_data.handshake); + if (!IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { + char errbuf[256]; + + ERR_error_string_n(error, errbuf, sizeof(errbuf)); + log_debug("Failed to invoke SSL_do_handshake: %s", errbuf); + return -ECONNREFUSED; + } + } + + stream->encrypted = true; + stream->dnstls_data.ssl = TAKE_PTR(s); + + r = dnstls_flush_write_buffer(stream); + if (r < 0 && r != -EAGAIN) { + SSL_free(TAKE_PTR(stream->dnstls_data.ssl)); + return r; + } + + return 0; +} + +void dnstls_stream_free(DnsStream *stream) { + assert(stream); + assert(stream->encrypted); + + if (stream->dnstls_data.ssl) + SSL_free(stream->dnstls_data.ssl); +} + +int dnstls_stream_on_io(DnsStream *stream, uint32_t revents) { + int error, r; + + assert(stream); + assert(stream->encrypted); + assert(stream->dnstls_data.ssl); + + /* Flush write buffer when requested by OpenSSL */ + if ((revents & EPOLLOUT) && (stream->dnstls_events & EPOLLOUT)) { + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + } + + if (stream->dnstls_data.shutdown) { + ERR_clear_error(); + r = SSL_shutdown(stream->dnstls_data.ssl); + if (r == 0) { + stream->dnstls_events = 0; + + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + + return -EAGAIN; + } else if (r < 0) { + error = SSL_get_error(stream->dnstls_data.ssl, r); + if (IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { + stream->dnstls_events = error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; + + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + + return -EAGAIN; + } else if (error == SSL_ERROR_SYSCALL) { + if (errno > 0) + log_debug_errno(errno, "Failed to invoke SSL_shutdown, ignoring: %m"); + } else { + char errbuf[256]; + + ERR_error_string_n(error, errbuf, sizeof(errbuf)); + log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf); + } + } + + stream->dnstls_events = 0; + stream->dnstls_data.shutdown = false; + + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + + dns_stream_unref(stream); + return DNSTLS_STREAM_CLOSED; + } else if (stream->dnstls_data.handshake <= 0) { + ERR_clear_error(); + stream->dnstls_data.handshake = SSL_do_handshake(stream->dnstls_data.ssl); + if (stream->dnstls_data.handshake <= 0) { + error = SSL_get_error(stream->dnstls_data.ssl, stream->dnstls_data.handshake); + if (IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { + stream->dnstls_events = error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + + return -EAGAIN; + } else { + char errbuf[256]; + + ERR_error_string_n(error, errbuf, sizeof(errbuf)); + return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED), + "Failed to invoke SSL_do_handshake: %s", + errbuf); + } + } + + stream->dnstls_events = 0; + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + } + + return 0; +} + +int dnstls_stream_shutdown(DnsStream *stream, int error) { + int ssl_error, r; + SSL_SESSION *s; + + assert(stream); + assert(stream->encrypted); + assert(stream->dnstls_data.ssl); + + if (stream->server) { + s = SSL_get1_session(stream->dnstls_data.ssl); + if (s) { + if (stream->server->dnstls_data.session) + SSL_SESSION_free(stream->server->dnstls_data.session); + + stream->server->dnstls_data.session = s; + } + } + + if (error == ETIMEDOUT) { + ERR_clear_error(); + r = SSL_shutdown(stream->dnstls_data.ssl); + if (r == 0) { + if (!stream->dnstls_data.shutdown) { + stream->dnstls_data.shutdown = true; + dns_stream_ref(stream); + } + + stream->dnstls_events = 0; + + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + + return -EAGAIN; + } else if (r < 0) { + ssl_error = SSL_get_error(stream->dnstls_data.ssl, r); + if (IN_SET(ssl_error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { + stream->dnstls_events = ssl_error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; + r = dnstls_flush_write_buffer(stream); + if (r < 0 && r != -EAGAIN) + return r; + + if (!stream->dnstls_data.shutdown) { + stream->dnstls_data.shutdown = true; + dns_stream_ref(stream); + } + return -EAGAIN; + } else if (ssl_error == SSL_ERROR_SYSCALL) { + if (errno > 0) + log_debug_errno(errno, "Failed to invoke SSL_shutdown, ignoring: %m"); + } else { + char errbuf[256]; + + ERR_error_string_n(ssl_error, errbuf, sizeof(errbuf)); + log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf); + } + } + + stream->dnstls_events = 0; + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + } + + return 0; +} + +ssize_t dnstls_stream_write(DnsStream *stream, const char *buf, size_t count) { + int error, r; + ssize_t ss; + + assert(stream); + assert(stream->encrypted); + assert(stream->dnstls_data.ssl); + assert(buf); + + ERR_clear_error(); + ss = r = SSL_write(stream->dnstls_data.ssl, buf, count); + if (r <= 0) { + error = SSL_get_error(stream->dnstls_data.ssl, r); + if (IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { + stream->dnstls_events = error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; + ss = -EAGAIN; + } else if (error == SSL_ERROR_ZERO_RETURN) { + stream->dnstls_events = 0; + ss = 0; + } else { + char errbuf[256]; + + ERR_error_string_n(error, errbuf, sizeof(errbuf)); + log_debug("Failed to invoke SSL_write: %s", errbuf); + stream->dnstls_events = 0; + ss = -EPIPE; + } + } else + stream->dnstls_events = 0; + + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + + return ss; +} + +ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) { + int error, r; + ssize_t ss; + + assert(stream); + assert(stream->encrypted); + assert(stream->dnstls_data.ssl); + assert(buf); + + ERR_clear_error(); + ss = r = SSL_read(stream->dnstls_data.ssl, buf, count); + if (r <= 0) { + error = SSL_get_error(stream->dnstls_data.ssl, r); + if (IN_SET(error, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE)) { + stream->dnstls_events = error == SSL_ERROR_WANT_READ ? EPOLLIN : EPOLLOUT; + ss = -EAGAIN; + } else if (error == SSL_ERROR_ZERO_RETURN) { + stream->dnstls_events = 0; + ss = 0; + } else { + char errbuf[256]; + + ERR_error_string_n(error, errbuf, sizeof(errbuf)); + log_debug("Failed to invoke SSL_read: %s", errbuf); + stream->dnstls_events = 0; + ss = -EPIPE; + } + } else + stream->dnstls_events = 0; + + /* flush write buffer in cache of renegotiation */ + r = dnstls_flush_write_buffer(stream); + if (r < 0) + return r; + + return ss; +} + +void dnstls_server_free(DnsServer *server) { + assert(server); + + if (server->dnstls_data.session) + SSL_SESSION_free(server->dnstls_data.session); +} + +int dnstls_manager_init(Manager *manager) { + int r; + assert(manager); + + ERR_load_crypto_strings(); + SSL_load_error_strings(); + manager->dnstls_data.ctx = SSL_CTX_new(TLS_client_method()); + + if (!manager->dnstls_data.ctx) + return -ENOMEM; + + SSL_CTX_set_min_proto_version(manager->dnstls_data.ctx, TLS1_2_VERSION); + SSL_CTX_set_options(manager->dnstls_data.ctx, SSL_OP_NO_COMPRESSION); + r = SSL_CTX_set_default_verify_paths(manager->dnstls_data.ctx); + if (r < 0) + log_warning("Failed to load system trust store: %s", ERR_error_string(ERR_get_error(), NULL)); + + return 0; +} + +void dnstls_manager_free(Manager *manager) { + assert(manager); + + if (manager->dnstls_data.ctx) + SSL_CTX_free(manager->dnstls_data.ctx); +} diff --git a/src/resolve/resolved-dnstls-openssl.h b/src/resolve/resolved-dnstls-openssl.h new file mode 100644 index 00000000..8100d2ba --- /dev/null +++ b/src/resolve/resolved-dnstls-openssl.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if !ENABLE_DNS_OVER_TLS || !DNS_OVER_TLS_USE_OPENSSL +#error This source file requires DNS-over-TLS to be enabled and OpenSSL to be available. +#endif + +#include +#include + +struct DnsTlsManagerData { + SSL_CTX *ctx; +}; + +struct DnsTlsServerData { + SSL_SESSION *session; +}; + +struct DnsTlsStreamData { + int handshake; + bool shutdown; + SSL *ssl; + BUF_MEM *write_buffer; + size_t buffer_offset; +}; diff --git a/src/resolve/resolved-dnstls.h b/src/resolve/resolved-dnstls.h new file mode 100644 index 00000000..1b912117 --- /dev/null +++ b/src/resolve/resolved-dnstls.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if ENABLE_DNS_OVER_TLS + +typedef struct DnsTlsManagerData DnsTlsManagerData; +typedef struct DnsTlsServerData DnsTlsServerData; +typedef struct DnsTlsStreamData DnsTlsStreamData; + +#if DNS_OVER_TLS_USE_GNUTLS +#include "resolved-dnstls-gnutls.h" +#elif DNS_OVER_TLS_USE_OPENSSL +#include "resolved-dnstls-openssl.h" +#else +#error Unknown dependency for supporting DNS-over-TLS +#endif + +#include "resolved-dns-stream.h" +#include "resolved-dns-transaction.h" +#include "resolved-manager.h" + +#define DNSTLS_STREAM_CLOSED 1 + +int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server); +void dnstls_stream_free(DnsStream *stream); +int dnstls_stream_on_io(DnsStream *stream, uint32_t revents); +int dnstls_stream_shutdown(DnsStream *stream, int error); +ssize_t dnstls_stream_write(DnsStream *stream, const char *buf, size_t count); +ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count); + +void dnstls_server_free(DnsServer *server); + +int dnstls_manager_init(Manager *manager); +void dnstls_manager_free(Manager *manager); + +#endif /* ENABLE_DNS_OVER_TLS */ diff --git a/src/resolve/resolved-etc-hosts.c b/src/resolve/resolved-etc-hosts.c new file mode 100644 index 00000000..6a23d2bb --- /dev/null +++ b/src/resolve/resolved-etc-hosts.c @@ -0,0 +1,381 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "fd-util.h" +#include "fileio.h" +#include "hostname-util.h" +#include "resolved-dns-synthesize.h" +#include "resolved-etc-hosts.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" + +/* Recheck /etc/hosts at most once every 2s */ +#define ETC_HOSTS_RECHECK_USEC (2*USEC_PER_SEC) + +static void etc_hosts_item_free(EtcHostsItem *item) { + strv_free(item->names); + free(item); +} + +static void etc_hosts_item_by_name_free(EtcHostsItemByName *item) { + free(item->name); + free(item->addresses); + free(item); +} + +void etc_hosts_free(EtcHosts *hosts) { + hosts->by_address = hashmap_free_with_destructor(hosts->by_address, etc_hosts_item_free); + hosts->by_name = hashmap_free_with_destructor(hosts->by_name, etc_hosts_item_by_name_free); + hosts->no_address = set_free_free(hosts->no_address); +} + +void manager_etc_hosts_flush(Manager *m) { + etc_hosts_free(&m->etc_hosts); + m->etc_hosts_mtime = USEC_INFINITY; +} + +static int parse_line(EtcHosts *hosts, unsigned nr, const char *line) { + _cleanup_free_ char *address_str = NULL; + struct in_addr_data address = {}; + bool found = false; + EtcHostsItem *item; + int r; + + assert(hosts); + assert(line); + + r = extract_first_word(&line, &address_str, NULL, EXTRACT_RELAX); + if (r < 0) + return log_error_errno(r, "/etc/hosts:%u: failed to extract address: %m", nr); + assert(r > 0); /* We already checked that the line is not empty, so it should contain *something* */ + + r = in_addr_ifindex_from_string_auto(address_str, &address.family, &address.address, NULL); + if (r < 0) { + log_warning_errno(r, "/etc/hosts:%u: address '%s' is invalid, ignoring: %m", nr, address_str); + return 0; + } + + r = in_addr_is_null(address.family, &address.address); + if (r < 0) { + log_warning_errno(r, "/etc/hosts:%u: address '%s' is invalid, ignoring: %m", nr, address_str); + return 0; + } + if (r > 0) + /* This is an 0.0.0.0 or :: item, which we assume means that we shall map the specified hostname to + * nothing. */ + item = NULL; + else { + /* If this is a normal address, then simply add entry mapping it to the specified names */ + + item = hashmap_get(hosts->by_address, &address); + if (!item) { + r = hashmap_ensure_allocated(&hosts->by_address, &in_addr_data_hash_ops); + if (r < 0) + return log_oom(); + + item = new0(EtcHostsItem, 1); + if (!item) + return log_oom(); + + item->address = address; + + r = hashmap_put(hosts->by_address, &item->address, item); + if (r < 0) { + free(item); + return log_oom(); + } + } + } + + for (;;) { + _cleanup_free_ char *name = NULL; + EtcHostsItemByName *bn; + + r = extract_first_word(&line, &name, NULL, EXTRACT_RELAX); + if (r < 0) + return log_error_errno(r, "/etc/hosts:%u: couldn't extract host name: %m", nr); + if (r == 0) + break; + + found = true; + + r = dns_name_is_valid_ldh(name); + if (r <= 0) { + log_warning_errno(r, "/etc/hosts:%u: hostname \"%s\" is not valid, ignoring.", nr, name); + continue; + } + + if (is_localhost(name)) + /* Suppress the "localhost" line that is often seen */ + continue; + + if (!item) { + /* Optimize the case where we don't need to store any addresses, by storing + * only the name in a dedicated Set instead of the hashmap */ + + r = set_ensure_allocated(&hosts->no_address, &dns_name_hash_ops); + if (r < 0) + return log_oom(); + + r = set_put(hosts->no_address, name); + if (r < 0) + return r; + + TAKE_PTR(name); + continue; + } + + r = strv_extend(&item->names, name); + if (r < 0) + return log_oom(); + + bn = hashmap_get(hosts->by_name, name); + if (!bn) { + r = hashmap_ensure_allocated(&hosts->by_name, &dns_name_hash_ops); + if (r < 0) + return log_oom(); + + bn = new0(EtcHostsItemByName, 1); + if (!bn) + return log_oom(); + + r = hashmap_put(hosts->by_name, name, bn); + if (r < 0) { + free(bn); + return log_oom(); + } + + bn->name = TAKE_PTR(name); + } + + if (!GREEDY_REALLOC(bn->addresses, bn->n_allocated, bn->n_addresses + 1)) + return log_oom(); + + bn->addresses[bn->n_addresses++] = &item->address; + } + + if (!found) + log_warning("/etc/hosts:%u: line is missing any host names", nr); + + return 0; +} + +int etc_hosts_parse(EtcHosts *hosts, FILE *f) { + _cleanup_(etc_hosts_free) EtcHosts t = {}; + unsigned nr = 0; + int r; + + for (;;) { + _cleanup_free_ char *line = NULL; + char *l; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read /etc/hosts: %m"); + if (r == 0) + break; + + nr++; + + l = strchr(line, '#'); + if (l) + *l = '\0'; + + l = strstrip(line); + if (isempty(l)) + continue; + + r = parse_line(&t, nr, l); + if (r < 0) + return r; + } + + etc_hosts_free(hosts); + *hosts = t; + t = (EtcHosts) {}; /* prevent cleanup */ + return 0; +} + +static int manager_etc_hosts_read(Manager *m) { + _cleanup_fclose_ FILE *f = NULL; + struct stat st; + usec_t ts; + int r; + + assert_se(sd_event_now(m->event, clock_boottime_or_monotonic(), &ts) >= 0); + + /* See if we checked /etc/hosts recently already */ + if (m->etc_hosts_last != USEC_INFINITY && m->etc_hosts_last + ETC_HOSTS_RECHECK_USEC > ts) + return 0; + + m->etc_hosts_last = ts; + + if (m->etc_hosts_mtime != USEC_INFINITY) { + if (stat("/etc/hosts", &st) < 0) { + if (errno != ENOENT) + return log_error_errno(errno, "Failed to stat /etc/hosts: %m"); + + manager_etc_hosts_flush(m); + return 0; + } + + /* Did the mtime change? If not, there's no point in re-reading the file. */ + if (timespec_load(&st.st_mtim) == m->etc_hosts_mtime) + return 0; + } + + f = fopen("/etc/hosts", "re"); + if (!f) { + if (errno != ENOENT) + return log_error_errno(errno, "Failed to open /etc/hosts: %m"); + + manager_etc_hosts_flush(m); + return 0; + } + + /* Take the timestamp at the beginning of processing, so that any changes made later are read on the next + * invocation */ + r = fstat(fileno(f), &st); + if (r < 0) + return log_error_errno(errno, "Failed to fstat() /etc/hosts: %m"); + + r = etc_hosts_parse(&m->etc_hosts, f); + if (r < 0) + return r; + + m->etc_hosts_mtime = timespec_load(&st.st_mtim); + m->etc_hosts_last = ts; + + return 1; +} + +int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) { + bool found_a = false, found_aaaa = false; + struct in_addr_data k = {}; + EtcHostsItemByName *bn; + DnsResourceKey *t; + const char *name; + unsigned i; + int r; + + assert(m); + assert(q); + assert(answer); + + if (!m->read_etc_hosts) + return 0; + + (void) manager_etc_hosts_read(m); + + name = dns_question_first_name(q); + if (!name) + return 0; + + r = dns_name_address(name, &k.family, &k.address); + if (r > 0) { + EtcHostsItem *item; + DnsResourceKey *found_ptr = NULL; + + item = hashmap_get(m->etc_hosts.by_address, &k); + if (!item) + return 0; + + /* We have an address in /etc/hosts that matches the queried name. Let's return successful. Actual data + * we'll only return if the request was for PTR. */ + + DNS_QUESTION_FOREACH(t, q) { + if (!IN_SET(t->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) + continue; + if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY)) + continue; + + r = dns_name_equal(dns_resource_key_name(t), name); + if (r < 0) + return r; + if (r > 0) { + found_ptr = t; + break; + } + } + + if (found_ptr) { + char **n; + + r = dns_answer_reserve(answer, strv_length(item->names)); + if (r < 0) + return r; + + STRV_FOREACH(n, item->names) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + + rr = dns_resource_record_new(found_ptr); + if (!rr) + return -ENOMEM; + + rr->ptr.name = strdup(*n); + if (!rr->ptr.name) + return -ENOMEM; + + r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + } + } + + return 1; + } + + bn = hashmap_get(m->etc_hosts.by_name, name); + if (bn) { + r = dns_answer_reserve(answer, bn->n_addresses); + if (r < 0) + return r; + } else { + /* Check if name was listed with no address. If yes, continue to return an answer. */ + if (!set_contains(m->etc_hosts.no_address, name)) + return 0; + } + + DNS_QUESTION_FOREACH(t, q) { + if (!IN_SET(t->type, DNS_TYPE_A, DNS_TYPE_AAAA, DNS_TYPE_ANY)) + continue; + if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY)) + continue; + + r = dns_name_equal(dns_resource_key_name(t), name); + if (r < 0) + return r; + if (r == 0) + continue; + + if (IN_SET(t->type, DNS_TYPE_A, DNS_TYPE_ANY)) + found_a = true; + if (IN_SET(t->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) + found_aaaa = true; + + if (found_a && found_aaaa) + break; + } + + for (i = 0; bn && i < bn->n_addresses; i++) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + + if ((!found_a && bn->addresses[i]->family == AF_INET) || + (!found_aaaa && bn->addresses[i]->family == AF_INET6)) + continue; + + r = dns_resource_record_new_address(&rr, bn->addresses[i]->family, &bn->addresses[i]->address, bn->name); + if (r < 0) + return r; + + r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED); + if (r < 0) + return r; + } + + return found_a || found_aaaa; +} diff --git a/src/resolve/resolved-etc-hosts.h b/src/resolve/resolved-etc-hosts.h new file mode 100644 index 00000000..caf32a53 --- /dev/null +++ b/src/resolve/resolved-etc-hosts.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "resolved-manager.h" +#include "resolved-dns-question.h" +#include "resolved-dns-answer.h" + +typedef struct EtcHostsItem { + struct in_addr_data address; + + char **names; +} EtcHostsItem; + +typedef struct EtcHostsItemByName { + char *name; + + struct in_addr_data **addresses; + size_t n_addresses, n_allocated; +} EtcHostsItemByName; + +int etc_hosts_parse(EtcHosts *hosts, FILE *f); +void etc_hosts_free(EtcHosts *hosts); + +void manager_etc_hosts_flush(Manager *m); +int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer); diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf new file mode 100644 index 00000000..049fe9eb --- /dev/null +++ b/src/resolve/resolved-gperf.gperf @@ -0,0 +1,29 @@ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif +#include +#include "conf-parser.h" +#include "resolved-conf.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name resolved_gperf_hash +%define lookup-function-name resolved_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0 +Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0 +Resolve.Domains, config_parse_search_domains, 0, 0 +Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support) +Resolve.MulticastDNS, config_parse_resolve_support, 0, offsetof(Manager, mdns_support) +Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode) +Resolve.DNSOverTLS, config_parse_dns_over_tls_mode, 0, offsetof(Manager, dns_over_tls_mode) +Resolve.Cache, config_parse_dns_cache_mode, DNS_CACHE_MODE_YES, offsetof(Manager, enable_cache) +Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode) +Resolve.ReadEtcHosts, config_parse_bool, 0, offsetof(Manager, read_etc_hosts) \ No newline at end of file diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c new file mode 100644 index 00000000..8bbfbaac --- /dev/null +++ b/src/resolve/resolved-link-bus.c @@ -0,0 +1,787 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-polkit.h" +#include "bus-util.h" +#include "parse-util.h" +#include "resolve-util.h" +#include "resolved-bus.h" +#include "resolved-link-bus.h" +#include "resolved-resolv-conf.h" +#include "stdio-util.h" +#include "strv.h" +#include "user-util.h" + +static BUS_DEFINE_PROPERTY_GET(property_get_dnssec_supported, "b", Link, link_dnssec_supported); +static BUS_DEFINE_PROPERTY_GET2(property_get_dnssec_mode, "s", Link, link_get_dnssec_mode, dnssec_mode_to_string); + +static int property_get_dns_over_tls_mode( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Link *l = userdata; + + assert(reply); + assert(l); + + return sd_bus_message_append(reply, "s", dns_over_tls_mode_to_string(link_get_dns_over_tls_mode(l))); +} + +static int property_get_dns( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Link *l = userdata; + DnsServer *s; + int r; + + assert(reply); + assert(l); + + r = sd_bus_message_open_container(reply, 'a', "(iay)"); + if (r < 0) + return r; + + LIST_FOREACH(servers, s, l->dns_servers) { + r = bus_dns_server_append(reply, s, false); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_current_dns_server( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + DnsServer *s; + + assert(reply); + assert(userdata); + + s = *(DnsServer **) userdata; + + return bus_dns_server_append(reply, s, false); +} + +static int property_get_domains( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Link *l = userdata; + DnsSearchDomain *d; + int r; + + assert(reply); + assert(l); + + r = sd_bus_message_open_container(reply, 'a', "(sb)"); + if (r < 0) + return r; + + LIST_FOREACH(domains, d, l->search_domains) { + r = sd_bus_message_append(reply, "(sb)", d->name, d->route_only); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_default_route( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Link *l = userdata; + + assert(reply); + assert(l); + + /* Return what is configured, if there's something configured */ + if (l->default_route >= 0) + return sd_bus_message_append(reply, "b", l->default_route); + + /* Otherwise report what is in effect */ + if (l->unicast_scope) + return sd_bus_message_append(reply, "b", dns_scope_is_default_route(l->unicast_scope)); + + return sd_bus_message_append(reply, "b", false); +} + +static int property_get_scopes_mask( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Link *l = userdata; + uint64_t mask; + + assert(reply); + assert(l); + + mask = (l->unicast_scope ? SD_RESOLVED_DNS : 0) | + (l->llmnr_ipv4_scope ? SD_RESOLVED_LLMNR_IPV4 : 0) | + (l->llmnr_ipv6_scope ? SD_RESOLVED_LLMNR_IPV6 : 0) | + (l->mdns_ipv4_scope ? SD_RESOLVED_MDNS_IPV4 : 0) | + (l->mdns_ipv6_scope ? SD_RESOLVED_MDNS_IPV6 : 0); + + return sd_bus_message_append(reply, "t", mask); +} + +static int property_get_ntas( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Link *l = userdata; + const char *name; + Iterator i; + int r; + + assert(reply); + assert(l); + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + SET_FOREACH(name, l->dnssec_negative_trust_anchors, i) { + r = sd_bus_message_append(reply, "s", name); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int verify_unmanaged_link(Link *l, sd_bus_error *error) { + assert(l); + + if (l->flags & IFF_LOOPBACK) + return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->ifname); + if (l->is_managed) + return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is managed.", l->ifname); + + return 0; +} + +int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ struct in_addr_data *dns = NULL; + size_t allocated = 0, n = 0; + Link *l = userdata; + unsigned i; + int r; + + assert(message); + assert(l); + + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(message, 'a', "(iay)"); + if (r < 0) + return r; + + for (;;) { + int family; + size_t sz; + const void *d; + + assert_cc(sizeof(int) == sizeof(int32_t)); + + r = sd_bus_message_enter_container(message, 'r', "iay"); + if (r < 0) + return r; + if (r == 0) + break; + + r = sd_bus_message_read(message, "i", &family); + if (r < 0) + return r; + + if (!IN_SET(family, AF_INET, AF_INET6)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family); + + r = sd_bus_message_read_array(message, 'y', &d, &sz); + if (r < 0) + return r; + if (sz != FAMILY_ADDRESS_SIZE(family)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size"); + + if (!dns_server_address_valid(family, d)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address"); + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + if (!GREEDY_REALLOC(dns, allocated, n+1)) + return -ENOMEM; + + dns[n].family = family; + memcpy(&dns[n].address, d, sz); + n++; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.resolve1.set-dns-servers", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + dns_server_mark_all(l->dns_servers); + + for (i = 0; i < n; i++) { + DnsServer *s; + + s = dns_server_find(l->dns_servers, dns[i].family, &dns[i].address, 0); + if (s) + dns_server_move_back_and_unmark(s); + else { + r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address, 0); + if (r < 0) + goto clear; + } + + } + + dns_server_unlink_marked(l->dns_servers); + link_allocate_scopes(l); + + (void) link_save_user(l); + (void) manager_write_resolv_conf(l->manager); + (void) manager_send_changed(l->manager, "DNS"); + + return sd_bus_reply_method_return(message, NULL); + +clear: + dns_server_unlink_all(l->dns_servers); + return r; +} + +int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + int r; + + assert(message); + assert(l); + + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(message, 'a', "(sb)"); + if (r < 0) + return r; + + for (;;) { + const char *name; + int route_only; + + r = sd_bus_message_read(message, "(sb)", &name, &route_only); + if (r < 0) + return r; + if (r == 0) + break; + + r = dns_name_is_valid(name); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name); + if (!route_only && dns_name_is_root(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain"); + } + + r = sd_bus_message_rewind(message, false); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.resolve1.set-domains", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + dns_search_domain_mark_all(l->search_domains); + + for (;;) { + DnsSearchDomain *d; + const char *name; + int route_only; + + r = sd_bus_message_read(message, "(sb)", &name, &route_only); + if (r < 0) + goto clear; + if (r == 0) + break; + + r = dns_search_domain_find(l->search_domains, name, &d); + if (r < 0) + goto clear; + + if (r > 0) + dns_search_domain_move_back_and_unmark(d); + else { + r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name); + if (r < 0) + goto clear; + } + + d->route_only = route_only; + } + + r = sd_bus_message_exit_container(message); + if (r < 0) + goto clear; + + dns_search_domain_unlink_marked(l->search_domains); + + (void) link_save_user(l); + (void) manager_write_resolv_conf(l->manager); + + return sd_bus_reply_method_return(message, NULL); + +clear: + dns_search_domain_unlink_all(l->search_domains); + return r; +} + +int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + int r, b; + + assert(message); + assert(l); + + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.resolve1.set-default-route", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + if (l->default_route != b) { + l->default_route = b; + + (void) link_save_user(l); + (void) manager_write_resolv_conf(l->manager); + } + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + ResolveSupport mode; + const char *llmnr; + int r; + + assert(message); + assert(l); + + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &llmnr); + if (r < 0) + return r; + + if (isempty(llmnr)) + mode = RESOLVE_SUPPORT_YES; + else { + mode = resolve_support_from_string(llmnr); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr); + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.resolve1.set-llmnr", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + l->llmnr_support = mode; + link_allocate_scopes(l); + link_add_rrs(l, false); + + (void) link_save_user(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + ResolveSupport mode; + const char *mdns; + int r; + + assert(message); + assert(l); + + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &mdns); + if (r < 0) + return r; + + if (isempty(mdns)) + mode = RESOLVE_SUPPORT_NO; + else { + mode = resolve_support_from_string(mdns); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns); + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.resolve1.set-mdns", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + l->mdns_support = mode; + link_allocate_scopes(l); + link_add_rrs(l, false); + + (void) link_save_user(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + const char *dns_over_tls; + DnsOverTlsMode mode; + int r; + + assert(message); + assert(l); + + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &dns_over_tls); + if (r < 0) + return r; + + if (isempty(dns_over_tls)) + mode = _DNS_OVER_TLS_MODE_INVALID; + else { + mode = dns_over_tls_mode_from_string(dns_over_tls); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSOverTLS setting: %s", dns_over_tls); + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.resolve1.set-dns-over-tls", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + link_set_dns_over_tls_mode(l, mode); + + (void) link_save_user(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + const char *dnssec; + DnssecMode mode; + int r; + + assert(message); + assert(l); + + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + + r = sd_bus_message_read(message, "s", &dnssec); + if (r < 0) + return r; + + if (isempty(dnssec)) + mode = _DNSSEC_MODE_INVALID; + else { + mode = dnssec_mode_from_string(dnssec); + if (mode < 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec); + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.resolve1.set-dnssec", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + link_set_dnssec_mode(l, mode); + + (void) link_save_user(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_set_free_free_ Set *ns = NULL; + _cleanup_strv_free_ char **ntas = NULL; + Link *l = userdata; + int r; + char **i; + + assert(message); + assert(l); + + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + + ns = set_new(&dns_name_hash_ops); + if (!ns) + return -ENOMEM; + + r = sd_bus_message_read_strv(message, &ntas); + if (r < 0) + return r; + + STRV_FOREACH(i, ntas) { + r = dns_name_is_valid(*i); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Invalid negative trust anchor domain: %s", *i); + + r = set_put_strdup(ns, *i); + if (r < 0) + return r; + } + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.resolve1.set-dnssec-negative-trust-anchors", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + set_free_free(l->dnssec_negative_trust_anchors); + l->dnssec_negative_trust_anchors = TAKE_PTR(ns); + + (void) link_save_user(l); + + return sd_bus_reply_method_return(message, NULL); +} + +int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Link *l = userdata; + int r; + + assert(message); + assert(l); + + r = verify_unmanaged_link(l, error); + if (r < 0) + return r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, + "org.freedesktop.resolve1.revert", + NULL, true, UID_INVALID, + &l->manager->polkit_registry, error); + if (r < 0) + return r; + if (r == 0) + return 1; /* Polkit will call us back */ + + link_flush_settings(l); + link_allocate_scopes(l); + link_add_rrs(l, false); + + (void) link_save_user(l); + (void) manager_write_resolv_conf(l->manager); + (void) manager_send_changed(l->manager, "DNS"); + + return sd_bus_reply_method_return(message, NULL); +} + +const sd_bus_vtable link_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0), + SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0), + SD_BUS_PROPERTY("CurrentDNSServer", "(iay)", property_get_current_dns_server, offsetof(Link, current_dns_server), 0), + SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0), + SD_BUS_PROPERTY("DefaultRoute", "b", property_get_default_route, 0, 0), + SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Link, llmnr_support), 0), + SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Link, mdns_support), 0), + SD_BUS_PROPERTY("DNSOverTLS", "s", property_get_dns_over_tls_mode, 0, 0), + SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, 0, 0), + SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0), + SD_BUS_PROPERTY("DNSSECSupported", "b", property_get_dnssec_supported, 0, 0), + + SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_domains, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDefaultRoute", "b", NULL, bus_link_method_set_default_route, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDNSOverTLS", "s", NULL, bus_link_method_set_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Revert", NULL, NULL, bus_link_method_revert, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_VTABLE_END +}; + +int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { + _cleanup_free_ char *e = NULL; + Manager *m = userdata; + int ifindex; + Link *link; + int r; + + assert(bus); + assert(path); + assert(interface); + assert(found); + assert(m); + + r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/link", &e); + if (r <= 0) + return 0; + + r = parse_ifindex(e, &ifindex); + if (r < 0) + return 0; + + link = hashmap_get(m->links, INT_TO_PTR(ifindex)); + if (!link) + return 0; + + *found = link; + return 1; +} + +char *link_bus_path(const Link *link) { + char *p, ifindex[DECIMAL_STR_MAX(link->ifindex)]; + int r; + + assert(link); + + xsprintf(ifindex, "%i", link->ifindex); + + r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifindex, &p); + if (r < 0) + return NULL; + + return p; +} + +int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { + _cleanup_strv_free_ char **l = NULL; + Manager *m = userdata; + Link *link; + Iterator i; + unsigned c = 0; + + assert(bus); + assert(path); + assert(m); + assert(nodes); + + l = new0(char*, hashmap_size(m->links) + 1); + if (!l) + return -ENOMEM; + + HASHMAP_FOREACH(link, m->links, i) { + char *p; + + p = link_bus_path(link); + if (!p) + return -ENOMEM; + + l[c++] = p; + } + + l[c] = NULL; + *nodes = TAKE_PTR(l); + + return 1; +} diff --git a/src/resolve/resolved-link-bus.h b/src/resolve/resolved-link-bus.h new file mode 100644 index 00000000..74068a47 --- /dev/null +++ b/src/resolve/resolved-link-bus.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "resolved-link.h" + +extern const sd_bus_vtable link_vtable[]; + +int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); +char *link_bus_path(const Link *link); +int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); + +int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c new file mode 100644 index 00000000..96ebb4d2 --- /dev/null +++ b/src/resolve/resolved-link.c @@ -0,0 +1,1395 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-network.h" + +#include "alloc-util.h" +#include "env-file.h" +#include "fd-util.h" +#include "fileio.h" +#include "log-link.h" +#include "mkdir.h" +#include "parse-util.h" +#include "resolved-link.h" +#include "resolved-llmnr.h" +#include "resolved-mdns.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" + +int link_new(Manager *m, Link **ret, int ifindex) { + _cleanup_(link_freep) Link *l = NULL; + int r; + + assert(m); + assert(ifindex > 0); + + r = hashmap_ensure_allocated(&m->links, NULL); + if (r < 0) + return r; + + l = new(Link, 1); + if (!l) + return -ENOMEM; + + *l = (Link) { + .ifindex = ifindex, + .default_route = -1, + .llmnr_support = RESOLVE_SUPPORT_YES, + .mdns_support = RESOLVE_SUPPORT_NO, + .dnssec_mode = _DNSSEC_MODE_INVALID, + .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID, + .operstate = IF_OPER_UNKNOWN, + }; + + if (asprintf(&l->state_file, "/run/systemd/resolve/netif/%i", ifindex) < 0) + return -ENOMEM; + + r = hashmap_put(m->links, INT_TO_PTR(ifindex), l); + if (r < 0) + return r; + + l->manager = m; + + if (ret) + *ret = l; + l = NULL; + + return 0; +} + +void link_flush_settings(Link *l) { + assert(l); + + l->default_route = -1; + l->llmnr_support = RESOLVE_SUPPORT_YES; + l->mdns_support = RESOLVE_SUPPORT_NO; + l->dnssec_mode = _DNSSEC_MODE_INVALID; + l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID; + + dns_server_unlink_all(l->dns_servers); + dns_search_domain_unlink_all(l->search_domains); + + l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors); +} + +Link *link_free(Link *l) { + if (!l) + return NULL; + + /* Send goodbye messages. */ + dns_scope_announce(l->mdns_ipv4_scope, true); + dns_scope_announce(l->mdns_ipv6_scope, true); + + link_flush_settings(l); + + while (l->addresses) + (void) link_address_free(l->addresses); + + if (l->manager) + hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex)); + + dns_scope_free(l->unicast_scope); + dns_scope_free(l->llmnr_ipv4_scope); + dns_scope_free(l->llmnr_ipv6_scope); + dns_scope_free(l->mdns_ipv4_scope); + dns_scope_free(l->mdns_ipv6_scope); + + free(l->state_file); + free(l->ifname); + + return mfree(l); +} + +void link_allocate_scopes(Link *l) { + bool unicast_relevant; + int r; + + assert(l); + + /* If a link that used to be relevant is no longer, or a link that did not use to be relevant now becomes + * relevant, let's reinit the learnt global DNS server information, since we might talk to different servers + * now, even if they have the same addresses as before. */ + + unicast_relevant = link_relevant(l, AF_UNSPEC, false); + if (unicast_relevant != l->unicast_relevant) { + l->unicast_relevant = unicast_relevant; + + dns_server_reset_features_all(l->manager->fallback_dns_servers); + dns_server_reset_features_all(l->manager->dns_servers); + + /* Also, flush the global unicast scope, to deal with split horizon setups, where talking through one + * interface reveals different DNS zones than through others. */ + if (l->manager->unicast_scope) + dns_cache_flush(&l->manager->unicast_scope->cache); + } + + /* And now, allocate all scopes that makes sense now if we didn't have them yet, and drop those which we don't + * need anymore */ + + if (unicast_relevant && l->dns_servers) { + if (!l->unicast_scope) { + dns_server_reset_features_all(l->dns_servers); + + r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC); + if (r < 0) + log_warning_errno(r, "Failed to allocate DNS scope: %m"); + } + } else + l->unicast_scope = dns_scope_free(l->unicast_scope); + + if (link_relevant(l, AF_INET, true) && + l->llmnr_support != RESOLVE_SUPPORT_NO && + l->manager->llmnr_support != RESOLVE_SUPPORT_NO) { + if (!l->llmnr_ipv4_scope) { + r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET); + if (r < 0) + log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m"); + } + } else + l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope); + + if (link_relevant(l, AF_INET6, true) && + l->llmnr_support != RESOLVE_SUPPORT_NO && + l->manager->llmnr_support != RESOLVE_SUPPORT_NO && + socket_ipv6_is_supported()) { + if (!l->llmnr_ipv6_scope) { + r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6); + if (r < 0) + log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m"); + } + } else + l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope); + + if (link_relevant(l, AF_INET, true) && + l->mdns_support != RESOLVE_SUPPORT_NO && + l->manager->mdns_support != RESOLVE_SUPPORT_NO) { + if (!l->mdns_ipv4_scope) { + r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET); + if (r < 0) + log_warning_errno(r, "Failed to allocate mDNS IPv4 scope: %m"); + } + } else + l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope); + + if (link_relevant(l, AF_INET6, true) && + l->mdns_support != RESOLVE_SUPPORT_NO && + l->manager->mdns_support != RESOLVE_SUPPORT_NO) { + if (!l->mdns_ipv6_scope) { + r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6); + if (r < 0) + log_warning_errno(r, "Failed to allocate mDNS IPv6 scope: %m"); + } + } else + l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope); +} + +void link_add_rrs(Link *l, bool force_remove) { + LinkAddress *a; + int r; + + LIST_FOREACH(addresses, a, l->addresses) + link_address_add_rrs(a, force_remove); + + if (!force_remove && + l->mdns_support == RESOLVE_SUPPORT_YES && + l->manager->mdns_support == RESOLVE_SUPPORT_YES) { + + if (l->mdns_ipv4_scope) { + r = dns_scope_add_dnssd_services(l->mdns_ipv4_scope); + if (r < 0) + log_warning_errno(r, "Failed to add IPv4 DNS-SD services: %m"); + } + + if (l->mdns_ipv6_scope) { + r = dns_scope_add_dnssd_services(l->mdns_ipv6_scope); + if (r < 0) + log_warning_errno(r, "Failed to add IPv6 DNS-SD services: %m"); + } + + } else { + + if (l->mdns_ipv4_scope) { + r = dns_scope_remove_dnssd_services(l->mdns_ipv4_scope); + if (r < 0) + log_warning_errno(r, "Failed to remove IPv4 DNS-SD services: %m"); + } + + if (l->mdns_ipv6_scope) { + r = dns_scope_remove_dnssd_services(l->mdns_ipv6_scope); + if (r < 0) + log_warning_errno(r, "Failed to remove IPv6 DNS-SD services: %m"); + } + } +} + +int link_process_rtnl(Link *l, sd_netlink_message *m) { + const char *n = NULL; + int r; + + assert(l); + assert(m); + + r = sd_rtnl_message_link_get_flags(m, &l->flags); + if (r < 0) + return r; + + (void) sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu); + (void) sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &l->operstate); + + if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0) { + r = free_and_strdup(&l->ifname, n); + if (r < 0) + return r; + } + + link_allocate_scopes(l); + link_add_rrs(l, false); + + return 0; +} + +static int link_update_dns_server_one(Link *l, const char *name) { + union in_addr_union a; + DnsServer *s; + int family, r; + + assert(l); + assert(name); + + r = in_addr_from_string_auto(name, &family, &a); + if (r < 0) + return r; + + s = dns_server_find(l->dns_servers, family, &a, 0); + if (s) { + dns_server_move_back_and_unmark(s); + return 0; + } + + return dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, 0); +} + +static int link_update_dns_servers(Link *l) { + _cleanup_strv_free_ char **nameservers = NULL; + char **nameserver; + int r; + + assert(l); + + r = sd_network_link_get_dns(l->ifindex, &nameservers); + if (r == -ENODATA) { + r = 0; + goto clear; + } + if (r < 0) + goto clear; + + dns_server_mark_all(l->dns_servers); + + STRV_FOREACH(nameserver, nameservers) { + r = link_update_dns_server_one(l, *nameserver); + if (r < 0) + goto clear; + } + + dns_server_unlink_marked(l->dns_servers); + return 0; + +clear: + dns_server_unlink_all(l->dns_servers); + return r; +} + +static int link_update_default_route(Link *l) { + int r; + + assert(l); + + r = sd_network_link_get_dns_default_route(l->ifindex); + if (r == -ENODATA) { + r = 0; + goto clear; + } + if (r < 0) + goto clear; + + l->default_route = r > 0; + return 0; + +clear: + l->default_route = -1; + return r; +} + +static int link_update_llmnr_support(Link *l) { + _cleanup_free_ char *b = NULL; + int r; + + assert(l); + + r = sd_network_link_get_llmnr(l->ifindex, &b); + if (r == -ENODATA) { + r = 0; + goto clear; + } + if (r < 0) + goto clear; + + l->llmnr_support = resolve_support_from_string(b); + if (l->llmnr_support < 0) { + r = -EINVAL; + goto clear; + } + + return 0; + +clear: + l->llmnr_support = RESOLVE_SUPPORT_YES; + return r; +} + +static int link_update_mdns_support(Link *l) { + _cleanup_free_ char *b = NULL; + int r; + + assert(l); + + r = sd_network_link_get_mdns(l->ifindex, &b); + if (r == -ENODATA) { + r = 0; + goto clear; + } + if (r < 0) + goto clear; + + l->mdns_support = resolve_support_from_string(b); + if (l->mdns_support < 0) { + r = -EINVAL; + goto clear; + } + + return 0; + +clear: + l->mdns_support = RESOLVE_SUPPORT_NO; + return r; +} + +void link_set_dns_over_tls_mode(Link *l, DnsOverTlsMode mode) { + + assert(l); + +#if ! ENABLE_DNS_OVER_TLS + if (mode != DNS_OVER_TLS_NO) + log_warning("DNS-over-TLS option for the link cannot be enabled or set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support."); + return; +#endif + + l->dns_over_tls_mode = mode; +} + +static int link_update_dns_over_tls_mode(Link *l) { + _cleanup_free_ char *b = NULL; + int r; + + assert(l); + + r = sd_network_link_get_dns_over_tls(l->ifindex, &b); + if (r == -ENODATA) { + r = 0; + goto clear; + } + if (r < 0) + goto clear; + + l->dns_over_tls_mode = dns_over_tls_mode_from_string(b); + if (l->dns_over_tls_mode < 0) { + r = -EINVAL; + goto clear; + } + + return 0; + +clear: + l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID; + return r; +} + +void link_set_dnssec_mode(Link *l, DnssecMode mode) { + + assert(l); + +#if ! HAVE_GCRYPT + if (IN_SET(mode, DNSSEC_YES, DNSSEC_ALLOW_DOWNGRADE)) + log_warning("DNSSEC option for the link cannot be enabled or set to allow-downgrade when systemd-resolved is built without gcrypt support. Turning off DNSSEC support."); + return; +#endif + + if (l->dnssec_mode == mode) + return; + + if ((l->dnssec_mode == _DNSSEC_MODE_INVALID) || + (l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) || + (l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) { + + /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the + * allow-downgrade mode to full DNSSEC mode, flush it too. */ + if (l->unicast_scope) + dns_cache_flush(&l->unicast_scope->cache); + } + + l->dnssec_mode = mode; +} + +static int link_update_dnssec_mode(Link *l) { + _cleanup_free_ char *m = NULL; + DnssecMode mode; + int r; + + assert(l); + + r = sd_network_link_get_dnssec(l->ifindex, &m); + if (r == -ENODATA) { + r = 0; + goto clear; + } + if (r < 0) + goto clear; + + mode = dnssec_mode_from_string(m); + if (mode < 0) { + r = -EINVAL; + goto clear; + } + + link_set_dnssec_mode(l, mode); + + return 0; + +clear: + l->dnssec_mode = _DNSSEC_MODE_INVALID; + return r; +} + +static int link_update_dnssec_negative_trust_anchors(Link *l) { + _cleanup_strv_free_ char **ntas = NULL; + _cleanup_set_free_free_ Set *ns = NULL; + int r; + + assert(l); + + r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas); + if (r == -ENODATA) { + r = 0; + goto clear; + } + if (r < 0) + goto clear; + + ns = set_new(&dns_name_hash_ops); + if (!ns) + return -ENOMEM; + + r = set_put_strdupv(ns, ntas); + if (r < 0) + return r; + + set_free_free(l->dnssec_negative_trust_anchors); + l->dnssec_negative_trust_anchors = TAKE_PTR(ns); + + return 0; + +clear: + l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors); + return r; +} + +static int link_update_search_domain_one(Link *l, const char *name, bool route_only) { + DnsSearchDomain *d; + int r; + + assert(l); + assert(name); + + r = dns_search_domain_find(l->search_domains, name, &d); + if (r < 0) + return r; + if (r > 0) + dns_search_domain_move_back_and_unmark(d); + else { + r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name); + if (r < 0) + return r; + } + + d->route_only = route_only; + return 0; +} + +static int link_update_search_domains(Link *l) { + _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL; + char **i; + int r, q; + + assert(l); + + r = sd_network_link_get_search_domains(l->ifindex, &sdomains); + if (r < 0 && r != -ENODATA) + goto clear; + + q = sd_network_link_get_route_domains(l->ifindex, &rdomains); + if (q < 0 && q != -ENODATA) { + r = q; + goto clear; + } + + if (r == -ENODATA && q == -ENODATA) { + /* networkd knows nothing about this interface, and that's fine. */ + r = 0; + goto clear; + } + + dns_search_domain_mark_all(l->search_domains); + + STRV_FOREACH(i, sdomains) { + r = link_update_search_domain_one(l, *i, false); + if (r < 0) + goto clear; + } + + STRV_FOREACH(i, rdomains) { + r = link_update_search_domain_one(l, *i, true); + if (r < 0) + goto clear; + } + + dns_search_domain_unlink_marked(l->search_domains); + return 0; + +clear: + dns_search_domain_unlink_all(l->search_domains); + return r; +} + +static int link_is_managed(Link *l) { + _cleanup_free_ char *state = NULL; + int r; + + assert(l); + + r = sd_network_link_get_setup_state(l->ifindex, &state); + if (r == -ENODATA) + return 0; + if (r < 0) + return r; + + return !STR_IN_SET(state, "pending", "unmanaged"); +} + +static void link_read_settings(Link *l) { + int r; + + assert(l); + + /* Read settings from networkd, except when networkd is not managing this interface. */ + + r = link_is_managed(l); + if (r < 0) { + log_link_warning_errno(l, r, "Failed to determine whether the interface is managed: %m"); + return; + } + if (r == 0) { + + /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */ + if (l->is_managed) + link_flush_settings(l); + + l->is_managed = false; + return; + } + + l->is_managed = true; + + r = link_update_dns_servers(l); + if (r < 0) + log_link_warning_errno(l, r, "Failed to read DNS servers for the interface, ignoring: %m"); + + r = link_update_llmnr_support(l); + if (r < 0) + log_link_warning_errno(l, r, "Failed to read LLMNR support for the interface, ignoring: %m"); + + r = link_update_mdns_support(l); + if (r < 0) + log_link_warning_errno(l, r, "Failed to read mDNS support for the interface, ignoring: %m"); + + r = link_update_dns_over_tls_mode(l); + if (r < 0) + log_link_warning_errno(l, r, "Failed to read DNS-over-TLS mode for the interface, ignoring: %m"); + + r = link_update_dnssec_mode(l); + if (r < 0) + log_link_warning_errno(l, r, "Failed to read DNSSEC mode for the interface, ignoring: %m"); + + r = link_update_dnssec_negative_trust_anchors(l); + if (r < 0) + log_link_warning_errno(l, r, "Failed to read DNSSEC negative trust anchors for the interface, ignoring: %m"); + + r = link_update_search_domains(l); + if (r < 0) + log_link_warning_errno(l, r, "Failed to read search domains for the interface, ignoring: %m"); + + r = link_update_default_route(l); + if (r < 0) + log_link_warning_errno(l, r, "Failed to read default route setting for the interface, proceeding anyway: %m"); +} + +int link_update(Link *l) { + int r; + + assert(l); + + link_read_settings(l); + link_load_user(l); + + if (l->llmnr_support != RESOLVE_SUPPORT_NO) { + r = manager_llmnr_start(l->manager); + if (r < 0) + return r; + } + + if (l->mdns_support != RESOLVE_SUPPORT_NO) { + r = manager_mdns_start(l->manager); + if (r < 0) + return r; + } + + link_allocate_scopes(l); + link_add_rrs(l, false); + + return 0; +} + +bool link_relevant(Link *l, int family, bool local_multicast) { + _cleanup_free_ char *state = NULL; + LinkAddress *a; + + assert(l); + + /* A link is relevant for local multicast traffic if it isn't a loopback device, has a link + * beat, can do multicast and has at least one link-local (or better) IP address. + * + * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at + * least one routable address. */ + + if (l->flags & (IFF_LOOPBACK|IFF_DORMANT)) + return false; + + if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP)) + return false; + + if (local_multicast) { + if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST) + return false; + } + + /* Check kernel operstate + * https://www.kernel.org/doc/Documentation/networking/operstates.txt */ + if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP)) + return false; + + (void) sd_network_link_get_operational_state(l->ifindex, &state); + if (state && !STR_IN_SET(state, "unknown", "degraded", "degraded-carrier", "routable")) + return false; + + LIST_FOREACH(addresses, a, l->addresses) + if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast)) + return true; + + return false; +} + +LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) { + LinkAddress *a; + + assert(l); + + LIST_FOREACH(addresses, a, l->addresses) + if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr)) + return a; + + return NULL; +} + +DnsServer* link_set_dns_server(Link *l, DnsServer *s) { + assert(l); + + if (l->current_dns_server == s) + return s; + + if (s) + log_debug("Switching to DNS server %s for interface %s.", dns_server_string(s), l->ifname); + + dns_server_unref(l->current_dns_server); + l->current_dns_server = dns_server_ref(s); + + if (l->unicast_scope) + dns_cache_flush(&l->unicast_scope->cache); + + return s; +} + +DnsServer *link_get_dns_server(Link *l) { + assert(l); + + if (!l->current_dns_server) + link_set_dns_server(l, l->dns_servers); + + return l->current_dns_server; +} + +void link_next_dns_server(Link *l) { + assert(l); + + if (!l->current_dns_server) + return; + + /* Change to the next one, but make sure to follow the linked + * list only if this server is actually still linked. */ + if (l->current_dns_server->linked && l->current_dns_server->servers_next) { + link_set_dns_server(l, l->current_dns_server->servers_next); + return; + } + + link_set_dns_server(l, l->dns_servers); +} + +DnsOverTlsMode link_get_dns_over_tls_mode(Link *l) { + assert(l); + + if (l->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID) + return l->dns_over_tls_mode; + + return manager_get_dns_over_tls_mode(l->manager); +} + +DnssecMode link_get_dnssec_mode(Link *l) { + assert(l); + + if (l->dnssec_mode != _DNSSEC_MODE_INVALID) + return l->dnssec_mode; + + return manager_get_dnssec_mode(l->manager); +} + +bool link_dnssec_supported(Link *l) { + DnsServer *server; + + assert(l); + + if (link_get_dnssec_mode(l) == DNSSEC_NO) + return false; + + server = link_get_dns_server(l); + if (server) + return dns_server_dnssec_supported(server); + + return true; +} + +int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) { + LinkAddress *a; + + assert(l); + assert(in_addr); + + a = new0(LinkAddress, 1); + if (!a) + return -ENOMEM; + + a->family = family; + a->in_addr = *in_addr; + + a->link = l; + LIST_PREPEND(addresses, l->addresses, a); + l->n_addresses++; + + if (ret) + *ret = a; + + return 0; +} + +LinkAddress *link_address_free(LinkAddress *a) { + if (!a) + return NULL; + + if (a->link) { + LIST_REMOVE(addresses, a->link->addresses, a); + + assert(a->link->n_addresses > 0); + a->link->n_addresses--; + + if (a->llmnr_address_rr) { + if (a->family == AF_INET && a->link->llmnr_ipv4_scope) + dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr); + else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope) + dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr); + } + + if (a->llmnr_ptr_rr) { + if (a->family == AF_INET && a->link->llmnr_ipv4_scope) + dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr); + else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope) + dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr); + } + + if (a->mdns_address_rr) { + if (a->family == AF_INET && a->link->mdns_ipv4_scope) + dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr); + else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope) + dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr); + } + + if (a->mdns_ptr_rr) { + if (a->family == AF_INET && a->link->mdns_ipv4_scope) + dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr); + else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope) + dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr); + } + } + + dns_resource_record_unref(a->llmnr_address_rr); + dns_resource_record_unref(a->llmnr_ptr_rr); + dns_resource_record_unref(a->mdns_address_rr); + dns_resource_record_unref(a->mdns_ptr_rr); + + return mfree(a); +} + +void link_address_add_rrs(LinkAddress *a, bool force_remove) { + int r; + + assert(a); + + if (a->family == AF_INET) { + + if (!force_remove && + link_address_relevant(a, true) && + a->link->llmnr_ipv4_scope && + a->link->llmnr_support == RESOLVE_SUPPORT_YES && + a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) { + + if (!a->link->manager->llmnr_host_ipv4_key) { + a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname); + if (!a->link->manager->llmnr_host_ipv4_key) { + r = -ENOMEM; + goto fail; + } + } + + if (!a->llmnr_address_rr) { + a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key); + if (!a->llmnr_address_rr) { + r = -ENOMEM; + goto fail; + } + + a->llmnr_address_rr->a.in_addr = a->in_addr.in; + a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL; + } + + if (!a->llmnr_ptr_rr) { + r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname); + if (r < 0) + goto fail; + + a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL; + } + + r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true); + if (r < 0) + log_warning_errno(r, "Failed to add A record to LLMNR zone: %m"); + + r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false); + if (r < 0) + log_warning_errno(r, "Failed to add IPv4 PTR record to LLMNR zone: %m"); + } else { + if (a->llmnr_address_rr) { + if (a->link->llmnr_ipv4_scope) + dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr); + a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr); + } + + if (a->llmnr_ptr_rr) { + if (a->link->llmnr_ipv4_scope) + dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr); + a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr); + } + } + + if (!force_remove && + link_address_relevant(a, true) && + a->link->mdns_ipv4_scope && + a->link->mdns_support == RESOLVE_SUPPORT_YES && + a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) { + if (!a->link->manager->mdns_host_ipv4_key) { + a->link->manager->mdns_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->mdns_hostname); + if (!a->link->manager->mdns_host_ipv4_key) { + r = -ENOMEM; + goto fail; + } + } + + if (!a->mdns_address_rr) { + a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv4_key); + if (!a->mdns_address_rr) { + r = -ENOMEM; + goto fail; + } + + a->mdns_address_rr->a.in_addr = a->in_addr.in; + a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL; + } + + if (!a->mdns_ptr_rr) { + r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname); + if (r < 0) + goto fail; + + a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL; + } + + r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_address_rr, true); + if (r < 0) + log_warning_errno(r, "Failed to add A record to MDNS zone: %m"); + + r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_ptr_rr, false); + if (r < 0) + log_warning_errno(r, "Failed to add IPv4 PTR record to MDNS zone: %m"); + } else { + if (a->mdns_address_rr) { + if (a->link->mdns_ipv4_scope) + dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr); + a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr); + } + + if (a->mdns_ptr_rr) { + if (a->link->mdns_ipv4_scope) + dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr); + a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr); + } + } + } + + if (a->family == AF_INET6) { + + if (!force_remove && + link_address_relevant(a, true) && + a->link->llmnr_ipv6_scope && + a->link->llmnr_support == RESOLVE_SUPPORT_YES && + a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) { + + if (!a->link->manager->llmnr_host_ipv6_key) { + a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname); + if (!a->link->manager->llmnr_host_ipv6_key) { + r = -ENOMEM; + goto fail; + } + } + + if (!a->llmnr_address_rr) { + a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key); + if (!a->llmnr_address_rr) { + r = -ENOMEM; + goto fail; + } + + a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6; + a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL; + } + + if (!a->llmnr_ptr_rr) { + r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname); + if (r < 0) + goto fail; + + a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL; + } + + r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true); + if (r < 0) + log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m"); + + r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false); + if (r < 0) + log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m"); + } else { + if (a->llmnr_address_rr) { + if (a->link->llmnr_ipv6_scope) + dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr); + a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr); + } + + if (a->llmnr_ptr_rr) { + if (a->link->llmnr_ipv6_scope) + dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr); + a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr); + } + } + + if (!force_remove && + link_address_relevant(a, true) && + a->link->mdns_ipv6_scope && + a->link->mdns_support == RESOLVE_SUPPORT_YES && + a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) { + + if (!a->link->manager->mdns_host_ipv6_key) { + a->link->manager->mdns_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->mdns_hostname); + if (!a->link->manager->mdns_host_ipv6_key) { + r = -ENOMEM; + goto fail; + } + } + + if (!a->mdns_address_rr) { + a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv6_key); + if (!a->mdns_address_rr) { + r = -ENOMEM; + goto fail; + } + + a->mdns_address_rr->aaaa.in6_addr = a->in_addr.in6; + a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL; + } + + if (!a->mdns_ptr_rr) { + r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname); + if (r < 0) + goto fail; + + a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL; + } + + r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_address_rr, true); + if (r < 0) + log_warning_errno(r, "Failed to add AAAA record to MDNS zone: %m"); + + r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_ptr_rr, false); + if (r < 0) + log_warning_errno(r, "Failed to add IPv6 PTR record to MDNS zone: %m"); + } else { + if (a->mdns_address_rr) { + if (a->link->mdns_ipv6_scope) + dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr); + a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr); + } + + if (a->mdns_ptr_rr) { + if (a->link->mdns_ipv6_scope) + dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr); + a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr); + } + } + } + + return; + +fail: + log_debug_errno(r, "Failed to update address RRs: %m"); +} + +int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) { + int r; + assert(a); + assert(m); + + r = sd_rtnl_message_addr_get_flags(m, &a->flags); + if (r < 0) + return r; + + sd_rtnl_message_addr_get_scope(m, &a->scope); + + link_allocate_scopes(a->link); + link_add_rrs(a->link, false); + + return 0; +} + +bool link_address_relevant(LinkAddress *a, bool local_multicast) { + assert(a); + + if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE)) + return false; + + if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK)) + return false; + + return true; +} + +static bool link_needs_save(Link *l) { + assert(l); + + /* Returns true if any of the settings where set different from the default */ + + if (l->is_managed) + return false; + + if (l->llmnr_support != RESOLVE_SUPPORT_YES || + l->mdns_support != RESOLVE_SUPPORT_NO || + l->dnssec_mode != _DNSSEC_MODE_INVALID || + l->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID) + return true; + + if (l->dns_servers || + l->search_domains) + return true; + + if (!set_isempty(l->dnssec_negative_trust_anchors)) + return true; + + if (l->default_route >= 0) + return true; + + return false; +} + +int link_save_user(Link *l) { + _cleanup_free_ char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *v; + int r; + + assert(l); + assert(l->state_file); + + if (!link_needs_save(l)) { + (void) unlink(l->state_file); + return 0; + } + + r = mkdir_parents(l->state_file, 0700); + if (r < 0) + goto fail; + + r = fopen_temporary(l->state_file, &f, &temp_path); + if (r < 0) + goto fail; + + (void) fchmod(fileno(f), 0644); + + fputs("# This is private data. Do not parse.\n", f); + + v = resolve_support_to_string(l->llmnr_support); + if (v) + fprintf(f, "LLMNR=%s\n", v); + + v = resolve_support_to_string(l->mdns_support); + if (v) + fprintf(f, "MDNS=%s\n", v); + + v = dnssec_mode_to_string(l->dnssec_mode); + if (v) + fprintf(f, "DNSSEC=%s\n", v); + + if (l->default_route >= 0) + fprintf(f, "DEFAULT_ROUTE=%s\n", yes_no(l->default_route)); + + if (l->dns_servers) { + DnsServer *server; + + fputs("SERVERS=", f); + LIST_FOREACH(servers, server, l->dns_servers) { + + if (server != l->dns_servers) + fputc(' ', f); + + v = dns_server_string(server); + if (!v) { + r = -ENOMEM; + goto fail; + } + + fputs(v, f); + } + fputc('\n', f); + } + + if (l->search_domains) { + DnsSearchDomain *domain; + + fputs("DOMAINS=", f); + LIST_FOREACH(domains, domain, l->search_domains) { + + if (domain != l->search_domains) + fputc(' ', f); + + if (domain->route_only) + fputc('~', f); + + fputs(DNS_SEARCH_DOMAIN_NAME(domain), f); + } + fputc('\n', f); + } + + if (!set_isempty(l->dnssec_negative_trust_anchors)) { + bool space = false; + Iterator i; + char *nta; + + fputs("NTAS=", f); + SET_FOREACH(nta, l->dnssec_negative_trust_anchors, i) { + + if (space) + fputc(' ', f); + + fputs(nta, f); + space = true; + } + fputc('\n', f); + } + + r = fflush_and_check(f); + if (r < 0) + goto fail; + + if (rename(temp_path, l->state_file) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + (void) unlink(l->state_file); + + if (temp_path) + (void) unlink(temp_path); + + return log_error_errno(r, "Failed to save link data %s: %m", l->state_file); +} + +int link_load_user(Link *l) { + _cleanup_free_ char + *llmnr = NULL, + *mdns = NULL, + *dnssec = NULL, + *servers = NULL, + *domains = NULL, + *ntas = NULL, + *default_route = NULL; + + ResolveSupport s; + const char *p; + int r; + + assert(l); + assert(l->state_file); + + /* Try to load only a single time */ + if (l->loaded) + return 0; + l->loaded = true; + + if (l->is_managed) + return 0; /* if the device is managed, then networkd is our configuration source, not the bus API */ + + r = parse_env_file(NULL, l->state_file, + "LLMNR", &llmnr, + "MDNS", &mdns, + "DNSSEC", &dnssec, + "SERVERS", &servers, + "DOMAINS", &domains, + "NTAS", &ntas, + "DEFAULT_ROUTE", &default_route); + if (r == -ENOENT) + return 0; + if (r < 0) + goto fail; + + link_flush_settings(l); + + /* If we can't recognize the LLMNR or MDNS setting we don't override the default */ + s = resolve_support_from_string(llmnr); + if (s >= 0) + l->llmnr_support = s; + + s = resolve_support_from_string(mdns); + if (s >= 0) + l->mdns_support = s; + + r = parse_boolean(default_route); + if (r >= 0) + l->default_route = r; + + /* If we can't recognize the DNSSEC setting, then set it to invalid, so that the daemon default is used. */ + l->dnssec_mode = dnssec_mode_from_string(dnssec); + + for (p = servers;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, 0); + if (r < 0) + goto fail; + if (r == 0) + break; + + r = link_update_dns_server_one(l, word); + if (r < 0) { + log_debug_errno(r, "Failed to load DNS server '%s', ignoring: %m", word); + continue; + } + } + + for (p = domains;;) { + _cleanup_free_ char *word = NULL; + const char *n; + bool is_route; + + r = extract_first_word(&p, &word, NULL, 0); + if (r < 0) + goto fail; + if (r == 0) + break; + + is_route = word[0] == '~'; + n = is_route ? word + 1 : word; + + r = link_update_search_domain_one(l, n, is_route); + if (r < 0) { + log_debug_errno(r, "Failed to load search domain '%s', ignoring: %m", word); + continue; + } + } + + if (ntas) { + _cleanup_set_free_free_ Set *ns = NULL; + + ns = set_new(&dns_name_hash_ops); + if (!ns) { + r = -ENOMEM; + goto fail; + } + + r = set_put_strsplit(ns, ntas, NULL, 0); + if (r < 0) + goto fail; + + l->dnssec_negative_trust_anchors = TAKE_PTR(ns); + } + + return 0; + +fail: + return log_error_errno(r, "Failed to load link data %s: %m", l->state_file); +} + +void link_remove_user(Link *l) { + assert(l); + assert(l->state_file); + + (void) unlink(l->state_file); +} diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h new file mode 100644 index 00000000..4b545a55 --- /dev/null +++ b/src/resolve/resolved-link.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "in-addr-util.h" +#include "ratelimit.h" +#include "resolve-util.h" + +typedef struct Link Link; +typedef struct LinkAddress LinkAddress; + +#include "resolved-dns-rr.h" +#include "resolved-dns-scope.h" +#include "resolved-dns-search-domain.h" +#include "resolved-dns-server.h" +#include "resolved-manager.h" + +#define LINK_SEARCH_DOMAINS_MAX 256 +#define LINK_DNS_SERVERS_MAX 256 + +struct LinkAddress { + Link *link; + + int family; + union in_addr_union in_addr; + + unsigned char flags, scope; + + DnsResourceRecord *llmnr_address_rr; + DnsResourceRecord *llmnr_ptr_rr; + DnsResourceRecord *mdns_address_rr; + DnsResourceRecord *mdns_ptr_rr; + + LIST_FIELDS(LinkAddress, addresses); +}; + +struct Link { + Manager *manager; + + int ifindex; + unsigned flags; + + LIST_HEAD(LinkAddress, addresses); + unsigned n_addresses; + + LIST_HEAD(DnsServer, dns_servers); + DnsServer *current_dns_server; + unsigned n_dns_servers; + + LIST_HEAD(DnsSearchDomain, search_domains); + unsigned n_search_domains; + + int default_route; + + ResolveSupport llmnr_support; + ResolveSupport mdns_support; + DnsOverTlsMode dns_over_tls_mode; + DnssecMode dnssec_mode; + Set *dnssec_negative_trust_anchors; + + DnsScope *unicast_scope; + DnsScope *llmnr_ipv4_scope; + DnsScope *llmnr_ipv6_scope; + DnsScope *mdns_ipv4_scope; + DnsScope *mdns_ipv6_scope; + + bool is_managed; + + char *ifname; + uint32_t mtu; + uint8_t operstate; + + bool loaded; + char *state_file; + + bool unicast_relevant; +}; + +int link_new(Manager *m, Link **ret, int ifindex); +Link *link_free(Link *l); +int link_process_rtnl(Link *l, sd_netlink_message *m); +int link_update(Link *l); +bool link_relevant(Link *l, int family, bool local_multicast); +LinkAddress* link_find_address(Link *l, int family, const union in_addr_union *in_addr); +void link_add_rrs(Link *l, bool force_remove); + +void link_flush_settings(Link *l); +void link_set_dnssec_mode(Link *l, DnssecMode mode); +void link_set_dns_over_tls_mode(Link *l, DnsOverTlsMode mode); +void link_allocate_scopes(Link *l); + +DnsServer* link_set_dns_server(Link *l, DnsServer *s); +DnsServer* link_get_dns_server(Link *l); +void link_next_dns_server(Link *l); + +DnssecMode link_get_dnssec_mode(Link *l); +bool link_dnssec_supported(Link *l); + +DnsOverTlsMode link_get_dns_over_tls_mode(Link *l); + +int link_save_user(Link *l); +int link_load_user(Link *l); +void link_remove_user(Link *l); + +int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr); +LinkAddress *link_address_free(LinkAddress *a); +int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m); +bool link_address_relevant(LinkAddress *l, bool local_multicast); +void link_address_add_rrs(LinkAddress *a, bool force_remove); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); diff --git a/src/resolve/resolved-llmnr.c b/src/resolve/resolved-llmnr.c new file mode 100644 index 00000000..61e50343 --- /dev/null +++ b/src/resolve/resolved-llmnr.c @@ -0,0 +1,450 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "errno-util.h" +#include "fd-util.h" +#include "resolved-llmnr.h" +#include "resolved-manager.h" + +void manager_llmnr_stop(Manager *m) { + assert(m); + + m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source); + m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd); + + m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source); + m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd); + + m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source); + m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd); + + m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source); + m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd); +} + +int manager_llmnr_start(Manager *m) { + int r; + + assert(m); + + if (m->llmnr_support == RESOLVE_SUPPORT_NO) + return 0; + + r = manager_llmnr_ipv4_udp_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + + r = manager_llmnr_ipv4_tcp_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + + if (socket_ipv6_is_supported()) { + r = manager_llmnr_ipv6_udp_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + + r = manager_llmnr_ipv6_tcp_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + } + + return 0; + +eaddrinuse: + log_warning("Another LLMNR responder prohibits binding the socket to the same port. Turning off LLMNR support."); + m->llmnr_support = RESOLVE_SUPPORT_NO; + manager_llmnr_stop(m); + + return 0; +} + +static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + DnsTransaction *t = NULL; + Manager *m = userdata; + DnsScope *scope; + int r; + + assert(s); + assert(fd >= 0); + assert(m); + + r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p); + if (r <= 0) + return r; + + if (manager_our_packet(m, p)) + return 0; + + scope = manager_find_scope(m, p); + if (!scope) { + log_debug("Got LLMNR UDP packet on unknown scope. Ignoring."); + return 0; + } + + if (dns_packet_validate_reply(p) > 0) { + log_debug("Got LLMNR UDP reply packet for id %u", DNS_PACKET_ID(p)); + + dns_scope_check_conflicts(scope, p); + + t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p))); + if (t) + dns_transaction_process_reply(t, p); + + } else if (dns_packet_validate_query(p) > 0) { + log_debug("Got LLMNR UDP query packet for id %u", DNS_PACKET_ID(p)); + + dns_scope_process_query(scope, NULL, p); + } else + log_debug("Invalid LLMNR UDP packet, ignoring."); + + return 0; +} + +int manager_llmnr_ipv4_udp_fd(Manager *m) { + union sockaddr_union sa = { + .in.sin_family = AF_INET, + .in.sin_port = htobe16(LLMNR_PORT), + }; + _cleanup_close_ int s = -1; + int r; + + assert(m); + + if (m->llmnr_ipv4_udp_fd >= 0) + return m->llmnr_ipv4_udp_fd; + + s = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s < 0) + return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to create socket: %m"); + + /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ + r = setsockopt_int(s, IPPROTO_IP, IP_TTL, 255); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_TTL: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_TTL, 255); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_TTL: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_LOOP, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MULTICAST_LOOP: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_PKTINFO: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_RECVTTL, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_RECVTTL: %m"); + + /* Disable Don't-Fragment bit in the IP header */ + r = setsockopt_int(s, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set IP_MTU_DISCOVER: %m"); + + /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */ + r = bind(s, &sa.sa, sizeof(sa.in)); + if (r < 0) { + if (errno != EADDRINUSE) + return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m"); + + log_warning("LLMNR-IPv4(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers."); + + /* try again with SO_REUSEADDR */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m"); + + r = bind(s, &sa.sa, sizeof(sa.in)); + if (r < 0) + return log_error_errno(errno, "LLMNR-IPv4(UDP): Failed to bind socket: %m"); + } else { + /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to set SO_REUSEADDR: %m"); + } + + r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, s, EPOLLIN, on_llmnr_packet, m); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(UDP): Failed to create event source: %m"); + + (void) sd_event_source_set_description(m->llmnr_ipv4_udp_event_source, "llmnr-ipv4-udp"); + + return m->llmnr_ipv4_udp_fd = TAKE_FD(s); +} + +int manager_llmnr_ipv6_udp_fd(Manager *m) { + union sockaddr_union sa = { + .in6.sin6_family = AF_INET6, + .in6.sin6_port = htobe16(LLMNR_PORT), + }; + _cleanup_close_ int s = -1; + int r; + + assert(m); + + if (m->llmnr_ipv6_udp_fd >= 0) + return m->llmnr_ipv6_udp_fd; + + s = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s < 0) + return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to create socket: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_UNICAST_HOPS: %m"); + + /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_HOPS: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_MULTICAST_LOOP: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_V6ONLY: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVPKTINFO: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set IPV6_RECVHOPLIMIT: %m"); + + /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */ + r = bind(s, &sa.sa, sizeof(sa.in6)); + if (r < 0) { + if (errno != EADDRINUSE) + return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m"); + + log_warning("LLMNR-IPv6(UDP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers."); + + /* try again with SO_REUSEADDR */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m"); + + r = bind(s, &sa.sa, sizeof(sa.in6)); + if (r < 0) + return log_error_errno(errno, "LLMNR-IPv6(UDP): Failed to bind socket: %m"); + } else { + /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to set SO_REUSEADDR: %m"); + } + + r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, s, EPOLLIN, on_llmnr_packet, m); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(UDP): Failed to create event source: %m"); + + (void) sd_event_source_set_description(m->llmnr_ipv6_udp_event_source, "llmnr-ipv6-udp"); + + return m->llmnr_ipv6_udp_fd = TAKE_FD(s); +} + +static int on_llmnr_stream_packet(DnsStream *s) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + DnsScope *scope; + + assert(s); + + p = dns_stream_take_read_packet(s); + assert(p); + + scope = manager_find_scope(s->manager, p); + if (!scope) + log_debug("Got LLMNR TCP packet on unknown scope. Ignoring."); + else if (dns_packet_validate_query(p) > 0) { + log_debug("Got LLMNR TCP query packet for id %u", DNS_PACKET_ID(p)); + + dns_scope_process_query(scope, s, p); + } else + log_debug("Invalid LLMNR TCP packet, ignoring."); + + dns_stream_unref(s); + return 0; +} + +static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + DnsStream *stream; + Manager *m = userdata; + int cfd, r; + + cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); + if (cfd < 0) { + if (ERRNO_IS_ACCEPT_AGAIN(errno)) + return 0; + + return -errno; + } + + r = dns_stream_new(m, &stream, DNS_STREAM_LLMNR_RECV, DNS_PROTOCOL_LLMNR, cfd, NULL); + if (r < 0) { + safe_close(cfd); + return r; + } + + stream->on_packet = on_llmnr_stream_packet; + /* We don't configure a "complete" handler here, we rely on the default handler than simply drops the + * reference to the stream, thus freeing it */ + return 0; +} + +int manager_llmnr_ipv4_tcp_fd(Manager *m) { + union sockaddr_union sa = { + .in.sin_family = AF_INET, + .in.sin_port = htobe16(LLMNR_PORT), + }; + _cleanup_close_ int s = -1; + int r; + + assert(m); + + if (m->llmnr_ipv4_tcp_fd >= 0) + return m->llmnr_ipv4_tcp_fd; + + s = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s < 0) + return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to create socket: %m"); + + /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */ + r = setsockopt_int(s, IPPROTO_IP, IP_TTL, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_TTL: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_PKTINFO: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_RECVTTL, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_RECVTTL: %m"); + + /* Disable Don't-Fragment bit in the IP header */ + r = setsockopt_int(s, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set IP_MTU_DISCOVER: %m"); + + /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */ + r = bind(s, &sa.sa, sizeof(sa.in)); + if (r < 0) { + if (errno != EADDRINUSE) + return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m"); + + log_warning("LLMNR-IPv4(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers."); + + /* try again with SO_REUSEADDR */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m"); + + r = bind(s, &sa.sa, sizeof(sa.in)); + if (r < 0) + return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to bind socket: %m"); + } else { + /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to set SO_REUSEADDR: %m"); + } + + r = listen(s, SOMAXCONN); + if (r < 0) + return log_error_errno(errno, "LLMNR-IPv4(TCP): Failed to listen the stream: %m"); + + r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, s, EPOLLIN, on_llmnr_stream, m); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv4(TCP): Failed to create event source: %m"); + + (void) sd_event_source_set_description(m->llmnr_ipv4_tcp_event_source, "llmnr-ipv4-tcp"); + + return m->llmnr_ipv4_tcp_fd = TAKE_FD(s); +} + +int manager_llmnr_ipv6_tcp_fd(Manager *m) { + union sockaddr_union sa = { + .in6.sin6_family = AF_INET6, + .in6.sin6_port = htobe16(LLMNR_PORT), + }; + _cleanup_close_ int s = -1; + int r; + + assert(m); + + if (m->llmnr_ipv6_tcp_fd >= 0) + return m->llmnr_ipv6_tcp_fd; + + s = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s < 0) + return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to create socket: %m"); + + /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */ + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_UNICAST_HOPS: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_V6ONLY: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVPKTINFO: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set IPV6_RECVHOPLIMIT: %m"); + + /* first try to bind without SO_REUSEADDR to detect another LLMNR responder */ + r = bind(s, &sa.sa, sizeof(sa.in6)); + if (r < 0) { + if (errno != EADDRINUSE) + return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m"); + + log_warning("LLMNR-IPv6(TCP): There appears to be another LLMNR responder running, or previously systemd-resolved crashed with some outstanding transfers."); + + /* try again with SO_REUSEADDR */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m"); + + r = bind(s, &sa.sa, sizeof(sa.in6)); + if (r < 0) + return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to bind socket: %m"); + } else { + /* enable SO_REUSEADDR for the case that the user really wants multiple LLMNR responders */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to set SO_REUSEADDR: %m"); + } + + r = listen(s, SOMAXCONN); + if (r < 0) + return log_error_errno(errno, "LLMNR-IPv6(TCP): Failed to listen the stream: %m"); + + r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, s, EPOLLIN, on_llmnr_stream, m); + if (r < 0) + return log_error_errno(r, "LLMNR-IPv6(TCP): Failed to create event source: %m"); + + (void) sd_event_source_set_description(m->llmnr_ipv6_tcp_event_source, "llmnr-ipv6-tcp"); + + return m->llmnr_ipv6_tcp_fd = TAKE_FD(s); +} diff --git a/src/resolve/resolved-llmnr.h b/src/resolve/resolved-llmnr.h new file mode 100644 index 00000000..a3b12cf3 --- /dev/null +++ b/src/resolve/resolved-llmnr.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "resolved-manager.h" + +#define LLMNR_PORT 5355 + +int manager_llmnr_ipv4_udp_fd(Manager *m); +int manager_llmnr_ipv6_udp_fd(Manager *m); +int manager_llmnr_ipv4_tcp_fd(Manager *m); +int manager_llmnr_ipv6_tcp_fd(Manager *m); + +void manager_llmnr_stop(Manager *m); +int manager_llmnr_start(Manager *m); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c new file mode 100644 index 00000000..2d5dbcc2 --- /dev/null +++ b/src/resolve/resolved-manager.c @@ -0,0 +1,1552 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_LIBIDN2 +#include +#endif + +#include "af-list.h" +#include "alloc-util.h" +#include "bus-polkit.h" +#include "dirent-util.h" +#include "dns-domain.h" +#include "fd-util.h" +#include "fileio.h" +#include "hostname-util.h" +#include "io-util.h" +#include "missing_network.h" +#include "netlink-util.h" +#include "network-internal.h" +#include "ordered-set.h" +#include "parse-util.h" +#include "random-util.h" +#include "resolved-bus.h" +#include "resolved-conf.h" +#include "resolved-dns-stub.h" +#include "resolved-dnssd.h" +#include "resolved-etc-hosts.h" +#include "resolved-llmnr.h" +#include "resolved-manager.h" +#include "resolved-mdns.h" +#include "resolved-resolv-conf.h" +#include "socket-util.h" +#include "string-table.h" +#include "string-util.h" +#include "utf8.h" + +#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC) + +static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { + Manager *m = userdata; + uint16_t type; + Link *l; + int ifindex, r; + + assert(rtnl); + assert(m); + assert(mm); + + r = sd_netlink_message_get_type(mm, &type); + if (r < 0) + goto fail; + + r = sd_rtnl_message_link_get_ifindex(mm, &ifindex); + if (r < 0) + goto fail; + + l = hashmap_get(m->links, INT_TO_PTR(ifindex)); + + switch (type) { + + case RTM_NEWLINK:{ + bool is_new = !l; + + if (!l) { + r = link_new(m, &l, ifindex); + if (r < 0) + goto fail; + } + + r = link_process_rtnl(l, mm); + if (r < 0) + goto fail; + + r = link_update(l); + if (r < 0) + goto fail; + + if (is_new) + log_debug("Found new link %i/%s", ifindex, l->ifname); + + break; + } + + case RTM_DELLINK: + if (l) { + log_debug("Removing link %i/%s", l->ifindex, l->ifname); + link_remove_user(l); + link_free(l); + } + + break; + } + + return 0; + +fail: + log_warning_errno(r, "Failed to process RTNL link message: %m"); + return 0; +} + +static int manager_process_address(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { + Manager *m = userdata; + union in_addr_union address; + uint16_t type; + int r, ifindex, family; + LinkAddress *a; + Link *l; + + assert(rtnl); + assert(mm); + assert(m); + + r = sd_netlink_message_get_type(mm, &type); + if (r < 0) + goto fail; + + r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex); + if (r < 0) + goto fail; + + l = hashmap_get(m->links, INT_TO_PTR(ifindex)); + if (!l) + return 0; + + r = sd_rtnl_message_addr_get_family(mm, &family); + if (r < 0) + goto fail; + + switch (family) { + + case AF_INET: + r = sd_netlink_message_read_in_addr(mm, IFA_LOCAL, &address.in); + if (r < 0) { + r = sd_netlink_message_read_in_addr(mm, IFA_ADDRESS, &address.in); + if (r < 0) + goto fail; + } + + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(mm, IFA_LOCAL, &address.in6); + if (r < 0) { + r = sd_netlink_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6); + if (r < 0) + goto fail; + } + + break; + + default: + return 0; + } + + a = link_find_address(l, family, &address); + + switch (type) { + + case RTM_NEWADDR: + + if (!a) { + r = link_address_new(l, &a, family, &address); + if (r < 0) + return r; + } + + r = link_address_update_rtnl(a, mm); + if (r < 0) + return r; + + break; + + case RTM_DELADDR: + link_address_free(a); + break; + } + + return 0; + +fail: + log_warning_errno(r, "Failed to process RTNL address message: %m"); + return 0; +} + +static int manager_rtnl_listen(Manager *m) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + sd_netlink_message *i; + int r; + + assert(m); + + /* First, subscribe to interfaces coming and going */ + r = sd_netlink_open(&m->rtnl); + if (r < 0) + return r; + + r = sd_netlink_attach_event(m->rtnl, m->event, SD_EVENT_PRIORITY_IMPORTANT); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, manager_process_link, NULL, m, "resolve-NEWLINK"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELLINK, manager_process_link, NULL, m, "resolve-DELLINK"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, manager_process_address, NULL, m, "resolve-NEWADDR"); + if (r < 0) + return r; + + r = sd_netlink_add_match(m->rtnl, NULL, RTM_DELADDR, manager_process_address, NULL, m, "resolve-DELADDR"); + if (r < 0) + return r; + + /* Then, enumerate all links */ + r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (i = reply; i; i = sd_netlink_message_next(i)) { + r = manager_process_link(m->rtnl, i, m); + if (r < 0) + return r; + } + + req = sd_netlink_message_unref(req); + reply = sd_netlink_message_unref(reply); + + /* Finally, enumerate all addresses, too */ + r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(m->rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (i = reply; i; i = sd_netlink_message_next(i)) { + r = manager_process_address(m->rtnl, i, m); + if (r < 0) + return r; + } + + return r; +} + +static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + Iterator i; + Link *l; + int r; + + assert(m); + + sd_network_monitor_flush(m->network_monitor); + + HASHMAP_FOREACH(l, m->links, i) { + r = link_update(l); + if (r < 0) + log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex); + } + + (void) manager_write_resolv_conf(m); + (void) manager_send_changed(m, "DNS"); + + return 0; +} + +static int manager_network_monitor_listen(Manager *m) { + int r, fd, events; + + assert(m); + + r = sd_network_monitor_new(&m->network_monitor, NULL); + if (r < 0) + return r; + + fd = sd_network_monitor_get_fd(m->network_monitor); + if (fd < 0) + return fd; + + events = sd_network_monitor_get_events(m->network_monitor); + if (events < 0) + return events; + + r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m); + if (r < 0) + return r; + + r = sd_event_source_set_priority(m->network_event_source, SD_EVENT_PRIORITY_IMPORTANT+5); + if (r < 0) + return r; + + (void) sd_event_source_set_description(m->network_event_source, "network-monitor"); + + return 0; +} + +static int determine_hostname(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) { + _cleanup_free_ char *h = NULL, *n = NULL; +#if HAVE_LIBIDN2 + _cleanup_free_ char *utf8 = NULL; +#elif HAVE_LIBIDN + int k; +#endif + char label[DNS_LABEL_MAX]; + const char *p, *decoded; + int r; + + assert(full_hostname); + assert(llmnr_hostname); + assert(mdns_hostname); + + /* Extract and normalize the first label of the locally configured hostname, and check it's not "localhost". */ + + r = gethostname_strict(&h); + if (r < 0) + return log_debug_errno(r, "Can't determine system hostname: %m"); + + p = h; + r = dns_label_unescape(&p, label, sizeof label, 0); + if (r < 0) + return log_error_errno(r, "Failed to unescape host name: %m"); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Couldn't find a single label in hostname."); + +#if HAVE_LIBIDN2 + r = idn2_to_unicode_8z8z(label, &utf8, 0); + if (r != IDN2_OK) + return log_error("Failed to undo IDNA: %s", idn2_strerror(r)); + assert(utf8_is_valid(utf8)); + + r = strlen(utf8); + decoded = utf8; +#elif HAVE_LIBIDN + k = dns_label_undo_idna(label, r, label, sizeof label); + if (k < 0) + return log_error_errno(k, "Failed to undo IDNA: %m"); + if (k > 0) + r = k; + + if (!utf8_is_valid(label)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "System hostname is not UTF-8 clean."); + decoded = label; +#else + decoded = label; /* no decoding */ +#endif + + r = dns_label_escape_new(decoded, r, &n); + if (r < 0) + return log_error_errno(r, "Failed to escape host name: %m"); + + if (is_localhost(n)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "System hostname is 'localhost', ignoring."); + + r = dns_name_concat(n, "local", 0, mdns_hostname); + if (r < 0) + return log_error_errno(r, "Failed to determine mDNS hostname: %m"); + + *llmnr_hostname = TAKE_PTR(n); + *full_hostname = TAKE_PTR(h); + + return 0; +} + +static const char *fallback_hostname(void) { + + /* Determine the fall back hostname. For exposing this system to the outside world, we cannot have it to be + * "localhost" even if that's the compiled in hostname. In this case, let's revert to "linux" instead. */ + + if (is_localhost(FALLBACK_HOSTNAME)) + return "linux"; + + return FALLBACK_HOSTNAME; +} + +static int make_fallback_hostnames(char **full_hostname, char **llmnr_hostname, char **mdns_hostname) { + _cleanup_free_ char *n = NULL, *m = NULL; + char label[DNS_LABEL_MAX], *h; + const char *p; + int r; + + assert(full_hostname); + assert(llmnr_hostname); + assert(mdns_hostname); + + p = fallback_hostname(); + r = dns_label_unescape(&p, label, sizeof label, 0); + if (r < 0) + return log_error_errno(r, "Failed to unescape fallback host name: %m"); + + assert(r > 0); /* The fallback hostname must have at least one label */ + + r = dns_label_escape_new(label, r, &n); + if (r < 0) + return log_error_errno(r, "Failed to escape fallback hostname: %m"); + + r = dns_name_concat(n, "local", 0, &m); + if (r < 0) + return log_error_errno(r, "Failed to concatenate mDNS hostname: %m"); + + h = strdup(fallback_hostname()); + if (!h) + return log_oom(); + + *llmnr_hostname = TAKE_PTR(n); + *mdns_hostname = TAKE_PTR(m); + + *full_hostname = h; + + return 0; +} + +static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + _cleanup_free_ char *full_hostname = NULL, *llmnr_hostname = NULL, *mdns_hostname = NULL; + Manager *m = userdata; + bool llmnr_hostname_changed; + int r; + + assert(m); + + r = determine_hostname(&full_hostname, &llmnr_hostname, &mdns_hostname); + if (r < 0) + return 0; /* ignore invalid hostnames */ + + llmnr_hostname_changed = !streq(llmnr_hostname, m->llmnr_hostname); + if (streq(full_hostname, m->full_hostname) && + !llmnr_hostname_changed && + streq(mdns_hostname, m->mdns_hostname)) + return 0; + + log_info("System hostname changed to '%s'.", full_hostname); + + free_and_replace(m->full_hostname, full_hostname); + free_and_replace(m->llmnr_hostname, llmnr_hostname); + free_and_replace(m->mdns_hostname, mdns_hostname); + + manager_refresh_rrs(m); + (void) manager_send_changed(m, "LLMNRHostname"); + + return 0; +} + +static int manager_watch_hostname(Manager *m) { + int r; + + assert(m); + + m->hostname_fd = open("/proc/sys/kernel/hostname", + O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (m->hostname_fd < 0) { + log_warning_errno(errno, "Failed to watch hostname: %m"); + return 0; + } + + r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m); + if (r < 0) { + if (r == -EPERM) + /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */ + m->hostname_fd = safe_close(m->hostname_fd); + else + return log_error_errno(r, "Failed to add hostname event source: %m"); + } + + (void) sd_event_source_set_description(m->hostname_event_source, "hostname"); + + r = determine_hostname(&m->full_hostname, &m->llmnr_hostname, &m->mdns_hostname); + if (r < 0) { + log_info("Defaulting to hostname '%s'.", fallback_hostname()); + + r = make_fallback_hostnames(&m->full_hostname, &m->llmnr_hostname, &m->mdns_hostname); + if (r < 0) + return r; + } else + log_info("Using system hostname '%s'.", m->full_hostname); + + return 0; +} + +static int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + _cleanup_free_ char *buffer = NULL; + _cleanup_fclose_ FILE *f = NULL; + Manager *m = userdata; + DnsServer *server; + size_t size = 0; + DnsScope *scope; + Iterator i; + Link *l; + + assert(s); + assert(si); + assert(m); + + f = open_memstream_unlocked(&buffer, &size); + if (!f) + return log_oom(); + + LIST_FOREACH(scopes, scope, m->dns_scopes) + dns_scope_dump(scope, f); + + LIST_FOREACH(servers, server, m->dns_servers) + dns_server_dump(server, f); + LIST_FOREACH(servers, server, m->fallback_dns_servers) + dns_server_dump(server, f); + HASHMAP_FOREACH(l, m->links, i) + LIST_FOREACH(servers, server, l->dns_servers) + dns_server_dump(server, f); + + if (fflush_and_check(f) < 0) + return log_oom(); + + log_dump(LOG_INFO, buffer); + return 0; +} + +static int manager_sigusr2(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *m = userdata; + + assert(s); + assert(si); + assert(m); + + manager_flush_caches(m); + + return 0; +} + +static int manager_sigrtmin1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *m = userdata; + + assert(s); + assert(si); + assert(m); + + manager_reset_server_features(m); + return 0; +} + +int manager_new(Manager **ret) { + _cleanup_(manager_freep) Manager *m = NULL; + int r; + + assert(ret); + + m = new(Manager, 1); + if (!m) + return -ENOMEM; + + *m = (Manager) { + .llmnr_ipv4_udp_fd = -1, + .llmnr_ipv6_udp_fd = -1, + .llmnr_ipv4_tcp_fd = -1, + .llmnr_ipv6_tcp_fd = -1, + .mdns_ipv4_fd = -1, + .mdns_ipv6_fd = -1, + .dns_stub_udp_fd = -1, + .dns_stub_tcp_fd = -1, + .hostname_fd = -1, + + .llmnr_support = RESOLVE_SUPPORT_YES, + .mdns_support = RESOLVE_SUPPORT_YES, + .dnssec_mode = DEFAULT_DNSSEC_MODE, + .dns_over_tls_mode = DEFAULT_DNS_OVER_TLS_MODE, + .enable_cache = DNS_CACHE_MODE_YES, + .dns_stub_listener_mode = DNS_STUB_LISTENER_YES, + .read_resolv_conf = true, + .need_builtin_fallbacks = true, + .etc_hosts_last = USEC_INFINITY, + .etc_hosts_mtime = USEC_INFINITY, + .read_etc_hosts = true, + }; + + r = dns_trust_anchor_load(&m->trust_anchor); + if (r < 0) + return r; + + r = manager_parse_config_file(m); + if (r < 0) + log_warning_errno(r, "Failed to parse configuration file: %m"); + +#if ENABLE_DNS_OVER_TLS + r = dnstls_manager_init(m); + if (r < 0) + return r; +#endif + + r = sd_event_default(&m->event); + if (r < 0) + return r; + + (void) sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); + (void) sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); + + (void) sd_event_set_watchdog(m->event, true); + + r = manager_watch_hostname(m); + if (r < 0) + return r; + + r = dnssd_load(m); + if (r < 0) + log_warning_errno(r, "Failed to load DNS-SD configuration files: %m"); + + r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC); + if (r < 0) + return r; + + r = manager_network_monitor_listen(m); + if (r < 0) + return r; + + r = manager_rtnl_listen(m); + if (r < 0) + return r; + + r = manager_connect_bus(m); + if (r < 0) + return r; + + (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m); + (void) sd_event_add_signal(m->event, &m->sigusr2_event_source, SIGUSR2, manager_sigusr2, m); + (void) sd_event_add_signal(m->event, &m->sigrtmin1_event_source, SIGRTMIN+1, manager_sigrtmin1, m); + + manager_cleanup_saved_user(m); + + *ret = TAKE_PTR(m); + + return 0; +} + +int manager_start(Manager *m) { + int r; + + assert(m); + + r = manager_dns_stub_start(m); + if (r < 0) + return r; + + return 0; +} + +Manager *manager_free(Manager *m) { + Link *l; + DnssdService *s; + + if (!m) + return NULL; + + dns_server_unlink_all(m->dns_servers); + dns_server_unlink_all(m->fallback_dns_servers); + dns_search_domain_unlink_all(m->search_domains); + + while ((l = hashmap_first(m->links))) + link_free(l); + + while (m->dns_queries) + dns_query_free(m->dns_queries); + + dns_scope_free(m->unicast_scope); + + /* At this point only orphaned streams should remain. All others should have been freed already by their + * owners */ + while (m->dns_streams) + dns_stream_unref(m->dns_streams); + +#if ENABLE_DNS_OVER_TLS + dnstls_manager_free(m); +#endif + + hashmap_free(m->links); + hashmap_free(m->dns_transactions); + + sd_event_source_unref(m->network_event_source); + sd_network_monitor_unref(m->network_monitor); + + sd_netlink_unref(m->rtnl); + sd_event_source_unref(m->rtnl_event_source); + + manager_llmnr_stop(m); + manager_mdns_stop(m); + manager_dns_stub_stop(m); + + bus_verify_polkit_async_registry_free(m->polkit_registry); + + sd_bus_flush_close_unref(m->bus); + + sd_event_source_unref(m->sigusr1_event_source); + sd_event_source_unref(m->sigusr2_event_source); + sd_event_source_unref(m->sigrtmin1_event_source); + + sd_event_unref(m->event); + + dns_resource_key_unref(m->llmnr_host_ipv4_key); + dns_resource_key_unref(m->llmnr_host_ipv6_key); + dns_resource_key_unref(m->mdns_host_ipv4_key); + dns_resource_key_unref(m->mdns_host_ipv6_key); + + sd_event_source_unref(m->hostname_event_source); + safe_close(m->hostname_fd); + + free(m->full_hostname); + free(m->llmnr_hostname); + free(m->mdns_hostname); + + while ((s = hashmap_first(m->dnssd_services))) + dnssd_service_free(s); + hashmap_free(m->dnssd_services); + + dns_trust_anchor_flush(&m->trust_anchor); + manager_etc_hosts_flush(m); + + return mfree(m); +} + +int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + union { + struct cmsghdr header; /* For alignment */ + uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo)) + + CMSG_SPACE(int) /* ttl/hoplimit */ + + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */]; + } control; + union sockaddr_union sa; + struct iovec iov; + struct msghdr mh = { + .msg_name = &sa.sa, + .msg_namelen = sizeof(sa), + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + struct cmsghdr *cmsg; + ssize_t ms, l; + int r; + + assert(m); + assert(fd >= 0); + assert(ret); + + ms = next_datagram_size_fd(fd); + if (ms < 0) + return ms; + + r = dns_packet_new(&p, protocol, ms, DNS_PACKET_SIZE_MAX); + if (r < 0) + return r; + + iov = IOVEC_MAKE(DNS_PACKET_DATA(p), p->allocated); + + l = recvmsg(fd, &mh, 0); + if (l < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + return -errno; + } + if (l == 0) + return 0; + + assert(!(mh.msg_flags & MSG_CTRUNC)); + assert(!(mh.msg_flags & MSG_TRUNC)); + + p->size = (size_t) l; + + p->family = sa.sa.sa_family; + p->ipproto = IPPROTO_UDP; + if (p->family == AF_INET) { + p->sender.in = sa.in.sin_addr; + p->sender_port = be16toh(sa.in.sin_port); + } else if (p->family == AF_INET6) { + p->sender.in6 = sa.in6.sin6_addr; + p->sender_port = be16toh(sa.in6.sin6_port); + p->ifindex = sa.in6.sin6_scope_id; + } else + return -EAFNOSUPPORT; + + CMSG_FOREACH(cmsg, &mh) { + + if (cmsg->cmsg_level == IPPROTO_IPV6) { + assert(p->family == AF_INET6); + + switch (cmsg->cmsg_type) { + + case IPV6_PKTINFO: { + struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg); + + if (p->ifindex <= 0) + p->ifindex = i->ipi6_ifindex; + + p->destination.in6 = i->ipi6_addr; + break; + } + + case IPV6_HOPLIMIT: + p->ttl = *(int *) CMSG_DATA(cmsg); + break; + + } + } else if (cmsg->cmsg_level == IPPROTO_IP) { + assert(p->family == AF_INET); + + switch (cmsg->cmsg_type) { + + case IP_PKTINFO: { + struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg); + + if (p->ifindex <= 0) + p->ifindex = i->ipi_ifindex; + + p->destination.in = i->ipi_addr; + break; + } + + case IP_TTL: + p->ttl = *(int *) CMSG_DATA(cmsg); + break; + } + } + } + + /* The Linux kernel sets the interface index to the loopback + * device if the packet came from the local host since it + * avoids the routing table in such a case. Let's unset the + * interface index in such a case. */ + if (p->ifindex == LOOPBACK_IFINDEX) + p->ifindex = 0; + + if (protocol != DNS_PROTOCOL_DNS) { + /* If we don't know the interface index still, we look for the + * first local interface with a matching address. Yuck! */ + if (p->ifindex <= 0) + p->ifindex = manager_find_ifindex(m, p->family, &p->destination); + } + + *ret = TAKE_PTR(p); + + return 1; +} + +static int sendmsg_loop(int fd, struct msghdr *mh, int flags) { + int r; + + assert(fd >= 0); + assert(mh); + + for (;;) { + if (sendmsg(fd, mh, flags) >= 0) + return 0; + + if (errno == EINTR) + continue; + + if (errno != EAGAIN) + return -errno; + + r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC); + if (r < 0) + return r; + if (r == 0) + return -ETIMEDOUT; + } +} + +static int write_loop(int fd, void *message, size_t length) { + int r; + + assert(fd >= 0); + assert(message); + + for (;;) { + if (write(fd, message, length) >= 0) + return 0; + + if (errno == EINTR) + continue; + + if (errno != EAGAIN) + return -errno; + + r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC); + if (r < 0) + return r; + if (r == 0) + return -ETIMEDOUT; + } +} + +int manager_write(Manager *m, int fd, DnsPacket *p) { + int r; + + log_debug("Sending %s packet with id %" PRIu16 ".", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p)); + + r = write_loop(fd, DNS_PACKET_DATA(p), p->size); + if (r < 0) + return r; + + return 0; +} + +static int manager_ipv4_send( + Manager *m, + int fd, + int ifindex, + const struct in_addr *destination, + uint16_t port, + const struct in_addr *source, + DnsPacket *p) { + union { + struct cmsghdr header; /* For alignment */ + uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))]; + } control = {}; + union sockaddr_union sa; + struct iovec iov; + struct msghdr mh = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_name = &sa.sa, + .msg_namelen = sizeof(sa.in), + }; + + assert(m); + assert(fd >= 0); + assert(destination); + assert(port > 0); + assert(p); + + iov = IOVEC_MAKE(DNS_PACKET_DATA(p), p->size); + + sa = (union sockaddr_union) { + .in.sin_family = AF_INET, + .in.sin_addr = *destination, + .in.sin_port = htobe16(port), + }; + + if (ifindex > 0) { + struct cmsghdr *cmsg; + struct in_pktinfo *pi; + + mh.msg_control = &control; + mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo)); + + cmsg = CMSG_FIRSTHDR(&mh); + cmsg->cmsg_len = mh.msg_controllen; + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_PKTINFO; + + pi = (struct in_pktinfo*) CMSG_DATA(cmsg); + pi->ipi_ifindex = ifindex; + + if (source) + pi->ipi_spec_dst = *source; + } + + return sendmsg_loop(fd, &mh, 0); +} + +static int manager_ipv6_send( + Manager *m, + int fd, + int ifindex, + const struct in6_addr *destination, + uint16_t port, + const struct in6_addr *source, + DnsPacket *p) { + + union { + struct cmsghdr header; /* For alignment */ + uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + } control = {}; + union sockaddr_union sa; + struct iovec iov; + struct msghdr mh = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_name = &sa.sa, + .msg_namelen = sizeof(sa.in6), + }; + + assert(m); + assert(fd >= 0); + assert(destination); + assert(port > 0); + assert(p); + + iov = IOVEC_MAKE(DNS_PACKET_DATA(p), p->size); + + sa = (union sockaddr_union) { + .in6.sin6_family = AF_INET6, + .in6.sin6_addr = *destination, + .in6.sin6_port = htobe16(port), + .in6.sin6_scope_id = ifindex, + }; + + if (ifindex > 0) { + struct cmsghdr *cmsg; + struct in6_pktinfo *pi; + + mh.msg_control = &control; + mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo)); + + cmsg = CMSG_FIRSTHDR(&mh); + cmsg->cmsg_len = mh.msg_controllen; + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + + pi = (struct in6_pktinfo*) CMSG_DATA(cmsg); + pi->ipi6_ifindex = ifindex; + + if (source) + pi->ipi6_addr = *source; + } + + return sendmsg_loop(fd, &mh, 0); +} + +int manager_send( + Manager *m, + int fd, + int ifindex, + int family, + const union in_addr_union *destination, + uint16_t port, + const union in_addr_union *source, + DnsPacket *p) { + + assert(m); + assert(fd >= 0); + assert(destination); + assert(port > 0); + assert(p); + + log_debug("Sending %s packet with id %" PRIu16 " on interface %i/%s.", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family)); + + if (family == AF_INET) + return manager_ipv4_send(m, fd, ifindex, &destination->in, port, source ? &source->in : NULL, p); + if (family == AF_INET6) + return manager_ipv6_send(m, fd, ifindex, &destination->in6, port, source ? &source->in6 : NULL, p); + + return -EAFNOSUPPORT; +} + +uint32_t manager_find_mtu(Manager *m) { + uint32_t mtu = 0; + Link *l; + Iterator i; + + /* If we don't know on which link a DNS packet would be + * delivered, let's find the largest MTU that works on all + * interfaces we know of */ + + HASHMAP_FOREACH(l, m->links, i) { + if (l->mtu <= 0) + continue; + + if (mtu <= 0 || l->mtu < mtu) + mtu = l->mtu; + } + + return mtu; +} + +int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) { + LinkAddress *a; + + assert(m); + + a = manager_find_link_address(m, family, in_addr); + if (a) + return a->link->ifindex; + + return 0; +} + +void manager_refresh_rrs(Manager *m) { + Iterator i; + Link *l; + DnssdService *s; + + assert(m); + + m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key); + m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key); + m->mdns_host_ipv4_key = dns_resource_key_unref(m->mdns_host_ipv4_key); + m->mdns_host_ipv6_key = dns_resource_key_unref(m->mdns_host_ipv6_key); + + if (m->mdns_support == RESOLVE_SUPPORT_YES) + HASHMAP_FOREACH(s, m->dnssd_services, i) + if (dnssd_update_rrs(s) < 0) + log_warning("Failed to refresh DNS-SD service '%s'", s->name); + + HASHMAP_FOREACH(l, m->links, i) { + link_add_rrs(l, true); + link_add_rrs(l, false); + } +} + +static int manager_next_random_name(const char *old, char **ret_new) { + const char *p; + uint64_t u, a; + char *n; + + p = strchr(old, 0); + assert(p); + + while (p > old) { + if (!strchr(DIGITS, p[-1])) + break; + + p--; + } + + if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0) + u = 1; + + /* Add a random number to the old value. This way we can avoid + * that two hosts pick the same hostname, win on IPv4 and lose + * on IPv6 (or vice versa), and pick the same hostname + * replacement hostname, ad infinitum. We still want the + * numbers to go up monotonically, hence we just add a random + * value 1..10 */ + + random_bytes(&a, sizeof(a)); + u += 1 + a % 10; + + if (asprintf(&n, "%.*s%" PRIu64, (int) (p - old), old, u) < 0) + return -ENOMEM; + + *ret_new = n; + + return 0; +} + +int manager_next_hostname(Manager *m) { + _cleanup_free_ char *h = NULL, *k = NULL; + int r; + + assert(m); + + r = manager_next_random_name(m->llmnr_hostname, &h); + if (r < 0) + return r; + + r = dns_name_concat(h, "local", 0, &k); + if (r < 0) + return r; + + log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h); + + free_and_replace(m->llmnr_hostname, h); + free_and_replace(m->mdns_hostname, k); + + manager_refresh_rrs(m); + (void) manager_send_changed(m, "LLMNRHostname"); + + return 0; +} + +LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) { + Iterator i; + Link *l; + + assert(m); + + HASHMAP_FOREACH(l, m->links, i) { + LinkAddress *a; + + a = link_find_address(l, family, in_addr); + if (a) + return a; + } + + return NULL; +} + +bool manager_our_packet(Manager *m, DnsPacket *p) { + assert(m); + assert(p); + + return !!manager_find_link_address(m, p->family, &p->sender); +} + +DnsScope* manager_find_scope(Manager *m, DnsPacket *p) { + Link *l; + + assert(m); + assert(p); + + l = hashmap_get(m->links, INT_TO_PTR(p->ifindex)); + if (!l) + return NULL; + + switch (p->protocol) { + case DNS_PROTOCOL_LLMNR: + if (p->family == AF_INET) + return l->llmnr_ipv4_scope; + else if (p->family == AF_INET6) + return l->llmnr_ipv6_scope; + + break; + + case DNS_PROTOCOL_MDNS: + if (p->family == AF_INET) + return l->mdns_ipv4_scope; + else if (p->family == AF_INET6) + return l->mdns_ipv6_scope; + + break; + + default: + break; + } + + return NULL; +} + +void manager_verify_all(Manager *m) { + DnsScope *s; + + assert(m); + + LIST_FOREACH(scopes, s, m->dns_scopes) + dns_zone_verify_all(&s->zone); +} + +int manager_is_own_hostname(Manager *m, const char *name) { + int r; + + assert(m); + assert(name); + + if (m->llmnr_hostname) { + r = dns_name_equal(name, m->llmnr_hostname); + if (r != 0) + return r; + } + + if (m->mdns_hostname) { + r = dns_name_equal(name, m->mdns_hostname); + if (r != 0) + return r; + } + + if (m->full_hostname) + return dns_name_equal(name, m->full_hostname); + + return 0; +} + +int manager_compile_dns_servers(Manager *m, OrderedSet **dns) { + DnsServer *s; + Iterator i; + Link *l; + int r; + + assert(m); + assert(dns); + + r = ordered_set_ensure_allocated(dns, &dns_server_hash_ops); + if (r < 0) + return r; + + /* First add the system-wide servers and domains */ + LIST_FOREACH(servers, s, m->dns_servers) { + r = ordered_set_put(*dns, s); + if (r == -EEXIST) + continue; + if (r < 0) + return r; + } + + /* Then, add the per-link servers */ + HASHMAP_FOREACH(l, m->links, i) { + LIST_FOREACH(servers, s, l->dns_servers) { + r = ordered_set_put(*dns, s); + if (r == -EEXIST) + continue; + if (r < 0) + return r; + } + } + + /* If we found nothing, add the fallback servers */ + if (ordered_set_isempty(*dns)) { + LIST_FOREACH(servers, s, m->fallback_dns_servers) { + r = ordered_set_put(*dns, s); + if (r == -EEXIST) + continue; + if (r < 0) + return r; + } + } + + return 0; +} + +/* filter_route is a tri-state: + * < 0: no filtering + * = 0 or false: return only domains which should be used for searching + * > 0 or true: return only domains which are for routing only + */ +int manager_compile_search_domains(Manager *m, OrderedSet **domains, int filter_route) { + DnsSearchDomain *d; + Iterator i; + Link *l; + int r; + + assert(m); + assert(domains); + + r = ordered_set_ensure_allocated(domains, &dns_name_hash_ops); + if (r < 0) + return r; + + LIST_FOREACH(domains, d, m->search_domains) { + + if (filter_route >= 0 && + d->route_only != !!filter_route) + continue; + + r = ordered_set_put(*domains, d->name); + if (r == -EEXIST) + continue; + if (r < 0) + return r; + } + + HASHMAP_FOREACH(l, m->links, i) { + + LIST_FOREACH(domains, d, l->search_domains) { + + if (filter_route >= 0 && + d->route_only != !!filter_route) + continue; + + r = ordered_set_put(*domains, d->name); + if (r == -EEXIST) + continue; + if (r < 0) + return r; + } + } + + return 0; +} + +DnssecMode manager_get_dnssec_mode(Manager *m) { + assert(m); + + if (m->dnssec_mode != _DNSSEC_MODE_INVALID) + return m->dnssec_mode; + + return DNSSEC_NO; +} + +bool manager_dnssec_supported(Manager *m) { + DnsServer *server; + Iterator i; + Link *l; + + assert(m); + + if (manager_get_dnssec_mode(m) == DNSSEC_NO) + return false; + + server = manager_get_dns_server(m); + if (server && !dns_server_dnssec_supported(server)) + return false; + + HASHMAP_FOREACH(l, m->links, i) + if (!link_dnssec_supported(l)) + return false; + + return true; +} + +DnsOverTlsMode manager_get_dns_over_tls_mode(Manager *m) { + assert(m); + + if (m->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID) + return m->dns_over_tls_mode; + + return DNS_OVER_TLS_NO; +} + +void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key) { + + assert(verdict >= 0); + assert(verdict < _DNSSEC_VERDICT_MAX); + + if (DEBUG_LOGGING) { + char s[DNS_RESOURCE_KEY_STRING_MAX]; + + log_debug("Found verdict for lookup %s: %s", + dns_resource_key_to_string(key, s, sizeof s), + dnssec_verdict_to_string(verdict)); + } + + m->n_dnssec_verdict[verdict]++; +} + +bool manager_routable(Manager *m, int family) { + Iterator i; + Link *l; + + assert(m); + + /* Returns true if the host has at least one interface with a routable address of the specified type */ + + HASHMAP_FOREACH(l, m->links, i) + if (link_relevant(l, family, false)) + return true; + + return false; +} + +void manager_flush_caches(Manager *m) { + DnsScope *scope; + + assert(m); + + LIST_FOREACH(scopes, scope, m->dns_scopes) + dns_cache_flush(&scope->cache); + + log_info("Flushed all caches."); +} + +void manager_reset_server_features(Manager *m) { + Iterator i; + Link *l; + + dns_server_reset_features_all(m->dns_servers); + dns_server_reset_features_all(m->fallback_dns_servers); + + HASHMAP_FOREACH(l, m->links, i) + dns_server_reset_features_all(l->dns_servers); + + log_info("Resetting learnt feature levels on all servers."); +} + +void manager_cleanup_saved_user(Manager *m) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r; + + assert(m); + + /* Clean up all saved per-link files in /run/systemd/resolve/netif/ that don't have a matching interface + * anymore. These files are created to persist settings pushed in by the user via the bus, so that resolved can + * be restarted without losing this data. */ + + d = opendir("/run/systemd/resolve/netif/"); + if (!d) { + if (errno == ENOENT) + return; + + log_warning_errno(errno, "Failed to open interface directory: %m"); + return; + } + + FOREACH_DIRENT_ALL(de, d, log_error_errno(errno, "Failed to read interface directory: %m")) { + _cleanup_free_ char *p = NULL; + int ifindex; + Link *l; + + if (!IN_SET(de->d_type, DT_UNKNOWN, DT_REG)) + continue; + + if (dot_or_dot_dot(de->d_name)) + continue; + + r = parse_ifindex(de->d_name, &ifindex); + if (r < 0) /* Probably some temporary file from a previous run. Delete it */ + goto rm; + + l = hashmap_get(m->links, INT_TO_PTR(ifindex)); + if (!l) /* link vanished */ + goto rm; + + if (l->is_managed) /* now managed by networkd, hence the bus settings are useless */ + goto rm; + + continue; + + rm: + p = path_join("/run/systemd/resolve/netif", de->d_name); + if (!p) { + log_oom(); + return; + } + + (void) unlink(p); + } +} + +bool manager_next_dnssd_names(Manager *m) { + Iterator i; + DnssdService *s; + bool tried = false; + int r; + + assert(m); + + HASHMAP_FOREACH(s, m->dnssd_services, i) { + _cleanup_free_ char * new_name = NULL; + + if (!s->withdrawn) + continue; + + r = manager_next_random_name(s->name_template, &new_name); + if (r < 0) { + log_warning_errno(r, "Failed to get new name for service '%s': %m", s->name); + continue; + } + + free_and_replace(s->name_template, new_name); + + s->withdrawn = false; + + tried = true; + } + + if (tried) + manager_refresh_rrs(m); + + return tried; +} diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h new file mode 100644 index 00000000..7f7d3a6b --- /dev/null +++ b/src/resolve/resolved-manager.h @@ -0,0 +1,189 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" +#include "sd-netlink.h" +#include "sd-network.h" + +#include "hashmap.h" +#include "list.h" +#include "ordered-set.h" +#include "resolve-util.h" + +typedef struct Manager Manager; + +#include "resolved-conf.h" +#include "resolved-dns-query.h" +#include "resolved-dns-search-domain.h" +#include "resolved-dns-server.h" +#include "resolved-dns-stream.h" +#include "resolved-dns-trust-anchor.h" +#include "resolved-dnstls.h" +#include "resolved-link.h" + +#define MANAGER_SEARCH_DOMAINS_MAX 256 +#define MANAGER_DNS_SERVERS_MAX 256 + +typedef struct EtcHosts { + Hashmap *by_address; + Hashmap *by_name; + Set *no_address; +} EtcHosts; + +struct Manager { + sd_event *event; + + ResolveSupport llmnr_support; + ResolveSupport mdns_support; + DnssecMode dnssec_mode; + DnsOverTlsMode dns_over_tls_mode; + DnsCacheMode enable_cache; + DnsStubListenerMode dns_stub_listener_mode; + +#if ENABLE_DNS_OVER_TLS + DnsTlsManagerData dnstls_data; +#endif + + /* Network */ + Hashmap *links; + + sd_netlink *rtnl; + sd_event_source *rtnl_event_source; + + sd_network_monitor *network_monitor; + sd_event_source *network_event_source; + + /* DNS query management */ + Hashmap *dns_transactions; + LIST_HEAD(DnsQuery, dns_queries); + unsigned n_dns_queries; + + LIST_HEAD(DnsStream, dns_streams); + unsigned n_dns_streams[_DNS_STREAM_TYPE_MAX]; + + /* Unicast dns */ + LIST_HEAD(DnsServer, dns_servers); + LIST_HEAD(DnsServer, fallback_dns_servers); + unsigned n_dns_servers; /* counts both main and fallback */ + DnsServer *current_dns_server; + + LIST_HEAD(DnsSearchDomain, search_domains); + unsigned n_search_domains; + + bool need_builtin_fallbacks:1; + + bool read_resolv_conf:1; + usec_t resolv_conf_mtime; + + DnsTrustAnchor trust_anchor; + + LIST_HEAD(DnsScope, dns_scopes); + DnsScope *unicast_scope; + + /* LLMNR */ + int llmnr_ipv4_udp_fd; + int llmnr_ipv6_udp_fd; + int llmnr_ipv4_tcp_fd; + int llmnr_ipv6_tcp_fd; + + sd_event_source *llmnr_ipv4_udp_event_source; + sd_event_source *llmnr_ipv6_udp_event_source; + sd_event_source *llmnr_ipv4_tcp_event_source; + sd_event_source *llmnr_ipv6_tcp_event_source; + + /* mDNS */ + int mdns_ipv4_fd; + int mdns_ipv6_fd; + + /* DNS-SD */ + Hashmap *dnssd_services; + + sd_event_source *mdns_ipv4_event_source; + sd_event_source *mdns_ipv6_event_source; + + /* dbus */ + sd_bus *bus; + + /* The hostname we publish on LLMNR and mDNS */ + char *full_hostname; + char *llmnr_hostname; + char *mdns_hostname; + DnsResourceKey *llmnr_host_ipv4_key; + DnsResourceKey *llmnr_host_ipv6_key; + DnsResourceKey *mdns_host_ipv4_key; + DnsResourceKey *mdns_host_ipv6_key; + + /* Watch the system hostname */ + int hostname_fd; + sd_event_source *hostname_event_source; + + sd_event_source *sigusr1_event_source; + sd_event_source *sigusr2_event_source; + sd_event_source *sigrtmin1_event_source; + + unsigned n_transactions_total; + unsigned n_dnssec_verdict[_DNSSEC_VERDICT_MAX]; + + /* Data from /etc/hosts */ + EtcHosts etc_hosts; + usec_t etc_hosts_last, etc_hosts_mtime; + bool read_etc_hosts; + + /* Local DNS stub on 127.0.0.53:53 */ + int dns_stub_udp_fd; + int dns_stub_tcp_fd; + + sd_event_source *dns_stub_udp_event_source; + sd_event_source *dns_stub_tcp_event_source; + + Hashmap *polkit_registry; +}; + +/* Manager */ + +int manager_new(Manager **ret); +Manager* manager_free(Manager *m); + +int manager_start(Manager *m); + +uint32_t manager_find_mtu(Manager *m); + +int manager_write(Manager *m, int fd, DnsPacket *p); +int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *destination, uint16_t port, const union in_addr_union *source, DnsPacket *p); +int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret); + +int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr); +LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr); + +void manager_refresh_rrs(Manager *m); +int manager_next_hostname(Manager *m); + +bool manager_our_packet(Manager *m, DnsPacket *p); +DnsScope* manager_find_scope(Manager *m, DnsPacket *p); + +void manager_verify_all(Manager *m); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); + +#define EXTRA_CMSG_SPACE 1024 + +int manager_is_own_hostname(Manager *m, const char *name); + +int manager_compile_dns_servers(Manager *m, OrderedSet **servers); +int manager_compile_search_domains(Manager *m, OrderedSet **domains, int filter_route); + +DnssecMode manager_get_dnssec_mode(Manager *m); +bool manager_dnssec_supported(Manager *m); + +DnsOverTlsMode manager_get_dns_over_tls_mode(Manager *m); + +void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key); + +bool manager_routable(Manager *m, int family); + +void manager_flush_caches(Manager *m); +void manager_reset_server_features(Manager *m); + +void manager_cleanup_saved_user(Manager *m); + +bool manager_next_dnssd_names(Manager *m); diff --git a/src/resolve/resolved-mdns.c b/src/resolve/resolved-mdns.c new file mode 100644 index 00000000..eba29789 --- /dev/null +++ b/src/resolve/resolved-mdns.c @@ -0,0 +1,482 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "resolved-manager.h" +#include "resolved-mdns.h" +#include "sort-util.h" + +#define CLEAR_CACHE_FLUSH(x) (~MDNS_RR_CACHE_FLUSH & (x)) + +void manager_mdns_stop(Manager *m) { + assert(m); + + m->mdns_ipv4_event_source = sd_event_source_unref(m->mdns_ipv4_event_source); + m->mdns_ipv4_fd = safe_close(m->mdns_ipv4_fd); + + m->mdns_ipv6_event_source = sd_event_source_unref(m->mdns_ipv6_event_source); + m->mdns_ipv6_fd = safe_close(m->mdns_ipv6_fd); +} + +int manager_mdns_start(Manager *m) { + int r; + + assert(m); + + if (m->mdns_support == RESOLVE_SUPPORT_NO) + return 0; + + r = manager_mdns_ipv4_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + + if (socket_ipv6_is_supported()) { + r = manager_mdns_ipv6_fd(m); + if (r == -EADDRINUSE) + goto eaddrinuse; + if (r < 0) + return r; + } + + return 0; + +eaddrinuse: + log_warning("Another mDNS responder prohibits binding the socket to the same port. Turning off mDNS support."); + m->mdns_support = RESOLVE_SUPPORT_NO; + manager_mdns_stop(m); + + return 0; +} + +static int mdns_rr_compare(DnsResourceRecord * const *a, DnsResourceRecord * const *b) { + DnsResourceRecord *x = *(DnsResourceRecord **) a, *y = *(DnsResourceRecord **) b; + size_t m; + int r; + + assert(x); + assert(y); + + r = CMP(CLEAR_CACHE_FLUSH(x->key->class), CLEAR_CACHE_FLUSH(y->key->class)); + if (r != 0) + return r; + + r = CMP(x->key->type, y->key->type); + if (r != 0) + return r; + + r = dns_resource_record_to_wire_format(x, false); + if (r < 0) { + log_warning_errno(r, "Can't wire-format RR: %m"); + return 0; + } + + r = dns_resource_record_to_wire_format(y, false); + if (r < 0) { + log_warning_errno(r, "Can't wire-format RR: %m"); + return 0; + } + + m = MIN(DNS_RESOURCE_RECORD_RDATA_SIZE(x), DNS_RESOURCE_RECORD_RDATA_SIZE(y)); + + r = memcmp(DNS_RESOURCE_RECORD_RDATA(x), DNS_RESOURCE_RECORD_RDATA(y), m); + if (r != 0) + return r; + + return CMP(DNS_RESOURCE_RECORD_RDATA_SIZE(x), DNS_RESOURCE_RECORD_RDATA_SIZE(y)); +} + +static int proposed_rrs_cmp(DnsResourceRecord **x, unsigned x_size, DnsResourceRecord **y, unsigned y_size) { + unsigned m; + int r; + + m = MIN(x_size, y_size); + for (unsigned i = 0; i < m; i++) { + r = mdns_rr_compare(&x[i], &y[i]); + if (r != 0) + return r; + } + + return CMP(x_size, y_size); +} + +static int mdns_packet_extract_matching_rrs(DnsPacket *p, DnsResourceKey *key, DnsResourceRecord ***ret_rrs) { + _cleanup_free_ DnsResourceRecord **list = NULL; + unsigned n = 0, size = 0; + int r; + + assert(p); + assert(key); + assert(ret_rrs); + assert_return(DNS_PACKET_NSCOUNT(p) > 0, -EINVAL); + + for (size_t i = DNS_PACKET_ANCOUNT(p); i < (DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)); i++) { + r = dns_resource_key_match_rr(key, p->answer->items[i].rr, NULL); + if (r < 0) + return r; + if (r > 0) + size++; + } + + if (size == 0) + return 0; + + list = new(DnsResourceRecord *, size); + if (!list) + return -ENOMEM; + + for (size_t i = DNS_PACKET_ANCOUNT(p); i < (DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)); i++) { + r = dns_resource_key_match_rr(key, p->answer->items[i].rr, NULL); + if (r < 0) + return r; + if (r > 0) + list[n++] = p->answer->items[i].rr; + } + assert(n == size); + typesafe_qsort(list, size, mdns_rr_compare); + + *ret_rrs = TAKE_PTR(list); + + return size; +} + +static int mdns_do_tiebreak(DnsResourceKey *key, DnsAnswer *answer, DnsPacket *p) { + _cleanup_free_ DnsResourceRecord **our = NULL, **remote = NULL; + DnsResourceRecord *rr; + size_t i = 0, size; + int r; + + size = dns_answer_size(answer); + our = new(DnsResourceRecord *, size); + if (!our) + return -ENOMEM; + + DNS_ANSWER_FOREACH(rr, answer) + our[i++] = rr; + + typesafe_qsort(our, size, mdns_rr_compare); + + r = mdns_packet_extract_matching_rrs(p, key, &remote); + if (r < 0) + return r; + + assert(r > 0); + + if (proposed_rrs_cmp(remote, r, our, size) > 0) + return 1; + + return 0; +} + +static int mdns_scope_process_query(DnsScope *s, DnsPacket *p) { + _cleanup_(dns_answer_unrefp) DnsAnswer *full_answer = NULL; + _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL; + DnsResourceKey *key = NULL; + DnsResourceRecord *rr; + bool tentative = false; + int r; + + assert(s); + assert(p); + + r = dns_packet_extract(p); + if (r < 0) + return log_debug_errno(r, "Failed to extract resource records from incoming packet: %m"); + + assert_return((dns_question_size(p->question) > 0), -EINVAL); + + DNS_QUESTION_FOREACH(key, p->question) { + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL; + + r = dns_zone_lookup(&s->zone, key, 0, &answer, &soa, &tentative); + if (r < 0) + return log_debug_errno(r, "Failed to lookup key: %m"); + + if (tentative && DNS_PACKET_NSCOUNT(p) > 0) { + /* + * A race condition detected with the probe packet from + * a remote host. + * Do simultaneous probe tiebreaking as described in + * RFC 6762, Section 8.2. In case we lost don't reply + * the question and withdraw conflicting RRs. + */ + r = mdns_do_tiebreak(key, answer, p); + if (r < 0) + return log_debug_errno(r, "Failed to do tiebreaking"); + + if (r > 0) { /* we lost */ + DNS_ANSWER_FOREACH(rr, answer) { + DnsZoneItem *i; + + i = dns_zone_get(&s->zone, rr); + if (i) + dns_zone_item_conflict(i); + } + + continue; + } + } + + r = dns_answer_extend(&full_answer, answer); + if (r < 0) + return log_debug_errno(r, "Failed to extend answer: %m"); + } + + if (dns_answer_isempty(full_answer)) + return 0; + + r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, NULL, full_answer, NULL, false, &reply); + if (r < 0) + return log_debug_errno(r, "Failed to build reply packet: %m"); + + if (!ratelimit_below(&s->ratelimit)) + return 0; + + r = dns_scope_emit_udp(s, -1, reply); + if (r < 0) + return log_debug_errno(r, "Failed to send reply packet: %m"); + + return 0; +} + +static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + Manager *m = userdata; + DnsScope *scope; + int r; + + r = manager_recv(m, fd, DNS_PROTOCOL_MDNS, &p); + if (r <= 0) + return r; + + if (manager_our_packet(m, p)) + return 0; + + scope = manager_find_scope(m, p); + if (!scope) { + log_debug("Got mDNS UDP packet on unknown scope. Ignoring."); + return 0; + } + + if (dns_packet_validate_reply(p) > 0) { + DnsResourceRecord *rr; + + log_debug("Got mDNS reply packet"); + + /* + * mDNS is different from regular DNS and LLMNR with regard to handling responses. + * While on other protocols, we can ignore every answer that doesn't match a question + * we broadcast earlier, RFC6762, section 18.1 recommends looking at and caching all + * incoming information, regardless of the DNS packet ID. + * + * Hence, extract the packet here, and try to find a transaction for answer the we got + * and complete it. Also store the new information in scope's cache. + */ + r = dns_packet_extract(p); + if (r < 0) { + log_debug("mDNS packet extraction failed."); + return 0; + } + + dns_scope_check_conflicts(scope, p); + + DNS_ANSWER_FOREACH(rr, p->answer) { + const char *name = dns_resource_key_name(rr->key); + DnsTransaction *t; + + /* If the received reply packet contains ANY record that is not .local or .in-addr.arpa, + * we assume someone's playing tricks on us and discard the packet completely. */ + if (!(dns_name_endswith(name, "in-addr.arpa") > 0 || + dns_name_endswith(name, "local") > 0)) + return 0; + + if (rr->ttl == 0) { + log_debug("Got a goodbye packet"); + /* See the section 10.1 of RFC6762 */ + rr->ttl = 1; + } + + t = dns_scope_find_transaction(scope, rr->key, false); + if (t) + dns_transaction_process_reply(t, p); + + /* Also look for the various types of ANY transactions */ + t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), false); + if (t) + dns_transaction_process_reply(t, p); + + t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, rr->key->type, dns_resource_key_name(rr->key)), false); + if (t) + dns_transaction_process_reply(t, p); + + t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), false); + if (t) + dns_transaction_process_reply(t, p); + } + + dns_cache_put(&scope->cache, scope->manager->enable_cache, NULL, DNS_PACKET_RCODE(p), p->answer, false, (uint32_t) -1, 0, p->family, &p->sender); + + } else if (dns_packet_validate_query(p) > 0) { + log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p)); + + r = mdns_scope_process_query(scope, p); + if (r < 0) { + log_debug_errno(r, "mDNS query processing failed: %m"); + return 0; + } + } else + log_debug("Invalid mDNS UDP packet."); + + return 0; +} + +int manager_mdns_ipv4_fd(Manager *m) { + union sockaddr_union sa = { + .in.sin_family = AF_INET, + .in.sin_port = htobe16(MDNS_PORT), + }; + _cleanup_close_ int s = -1; + int r; + + assert(m); + + if (m->mdns_ipv4_fd >= 0) + return m->mdns_ipv4_fd; + + s = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s < 0) + return log_error_errno(errno, "mDNS-IPv4: Failed to create socket: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_TTL, 255); + if (r < 0) + return log_error_errno(r, "mDNS-IPv4: Failed to set IP_TTL: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_TTL, 255); + if (r < 0) + return log_error_errno(r, "mDNS-IPv4: Failed to set IP_MULTICAST_TTL: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_MULTICAST_LOOP, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv4: Failed to set IP_MULTICAST_LOOP: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv4: Failed to set IP_PKTINFO: %m"); + + r = setsockopt_int(s, IPPROTO_IP, IP_RECVTTL, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv4: Failed to set IP_RECVTTL: %m"); + + /* Disable Don't-Fragment bit in the IP header */ + r = setsockopt_int(s, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT); + if (r < 0) + return log_error_errno(r, "mDNS-IPv4: Failed to set IP_MTU_DISCOVER: %m"); + + /* See the section 15.1 of RFC6762 */ + /* first try to bind without SO_REUSEADDR to detect another mDNS responder */ + r = bind(s, &sa.sa, sizeof(sa.in)); + if (r < 0) { + if (errno != EADDRINUSE) + return log_error_errno(errno, "mDNS-IPv4: Failed to bind socket: %m"); + + log_warning("mDNS-IPv4: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers."); + + /* try again with SO_REUSEADDR */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m"); + + r = bind(s, &sa.sa, sizeof(sa.in)); + if (r < 0) + return log_error_errno(errno, "mDNS-IPv4: Failed to bind socket: %m"); + } else { + /* enable SO_REUSEADDR for the case that the user really wants multiple mDNS responders */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m"); + } + + r = sd_event_add_io(m->event, &m->mdns_ipv4_event_source, s, EPOLLIN, on_mdns_packet, m); + if (r < 0) + return log_error_errno(r, "mDNS-IPv4: Failed to create event source: %m"); + + return m->mdns_ipv4_fd = TAKE_FD(s); +} + +int manager_mdns_ipv6_fd(Manager *m) { + union sockaddr_union sa = { + .in6.sin6_family = AF_INET6, + .in6.sin6_port = htobe16(MDNS_PORT), + }; + _cleanup_close_ int s = -1; + int r; + + assert(m); + + if (m->mdns_ipv6_fd >= 0) + return m->mdns_ipv6_fd; + + s = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (s < 0) + return log_error_errno(errno, "mDNS-IPv6: Failed to create socket: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255); + if (r < 0) + return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_UNICAST_HOPS: %m"); + + /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */ + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255); + if (r < 0) + return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_MULTICAST_HOPS: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_MULTICAST_LOOP: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_V6ONLY: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_RECVPKTINFO: %m"); + + r = setsockopt_int(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv6: Failed to set IPV6_RECVHOPLIMIT: %m"); + + /* See the section 15.1 of RFC6762 */ + /* first try to bind without SO_REUSEADDR to detect another mDNS responder */ + r = bind(s, &sa.sa, sizeof(sa.in6)); + if (r < 0) { + if (errno != EADDRINUSE) + return log_error_errno(errno, "mDNS-IPv6: Failed to bind socket: %m"); + + log_warning("mDNS-IPv6: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers."); + + /* try again with SO_REUSEADDR */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m"); + + r = bind(s, &sa.sa, sizeof(sa.in6)); + if (r < 0) + return log_error_errno(errno, "mDNS-IPv6: Failed to bind socket: %m"); + } else { + /* enable SO_REUSEADDR for the case that the user really wants multiple mDNS responders */ + r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return log_error_errno(r, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m"); + } + + r = sd_event_add_io(m->event, &m->mdns_ipv6_event_source, s, EPOLLIN, on_mdns_packet, m); + if (r < 0) + return log_error_errno(r, "mDNS-IPv6: Failed to create event source: %m"); + + return m->mdns_ipv6_fd = TAKE_FD(s); +} diff --git a/src/resolve/resolved-mdns.h b/src/resolve/resolved-mdns.h new file mode 100644 index 00000000..2f694786 --- /dev/null +++ b/src/resolve/resolved-mdns.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "resolved-manager.h" + +#define MDNS_PORT 5353 +#define MDNS_ANNOUNCE_DELAY (1 * USEC_PER_SEC) + +int manager_mdns_ipv4_fd(Manager *m); +int manager_mdns_ipv6_fd(Manager *m); + +void manager_mdns_stop(Manager *m); +int manager_mdns_start(Manager *m); diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c new file mode 100644 index 00000000..7b487d50 --- /dev/null +++ b/src/resolve/resolved-resolv-conf.c @@ -0,0 +1,399 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dns-domain.h" +#include "fd-util.h" +#include "fileio.h" +#include "ordered-set.h" +#include "resolved-conf.h" +#include "resolved-dns-server.h" +#include "resolved-resolv-conf.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util-label.h" + +/* A resolv.conf file containing the DNS server and domain data we learnt from uplink, i.e. the full uplink data */ +#define PRIVATE_UPLINK_RESOLV_CONF "/run/systemd/resolve/resolv.conf" + +/* A resolv.conf file containing the domain data we learnt from uplink, but our own DNS server address. */ +#define PRIVATE_STUB_RESOLV_CONF "/run/systemd/resolve/stub-resolv.conf" + +/* A static resolv.conf file containing no domains, but only our own DNS server address */ +#define PRIVATE_STATIC_RESOLV_CONF ROOTLIBEXECDIR "/resolv.conf" + +int manager_check_resolv_conf(const Manager *m) { + const char *path; + struct stat st; + int r; + + assert(m); + + /* This warns only when our stub listener is disabled and /etc/resolv.conf is a symlink to + * PRIVATE_STATIC_RESOLV_CONF or PRIVATE_STUB_RESOLV_CONF. */ + + if (m->dns_stub_listener_mode != DNS_STUB_LISTENER_NO) + return 0; + + r = stat("/etc/resolv.conf", &st); + if (r < 0) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m"); + } + + FOREACH_STRING(path, + PRIVATE_STUB_RESOLV_CONF, + PRIVATE_STATIC_RESOLV_CONF) { + + struct stat own; + + /* Is it symlinked to our own uplink file? */ + if (stat(path, &own) >= 0 && + st.st_dev == own.st_dev && + st.st_ino == own.st_ino) { + log_warning("DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to %s " + "which expects DNSStubListener= to be enabled.", path); + return -EOPNOTSUPP; + } + } + + return 0; +} + +static bool file_is_our_own(const struct stat *st) { + const char *path; + + assert(st); + + FOREACH_STRING(path, + PRIVATE_UPLINK_RESOLV_CONF, + PRIVATE_STUB_RESOLV_CONF, + PRIVATE_STATIC_RESOLV_CONF) { + + struct stat own; + + /* Is it symlinked to our own uplink file? */ + if (stat(path, &own) >= 0 && + st->st_dev == own.st_dev && + st->st_ino == own.st_ino) + return true; + } + + return false; +} + +int manager_read_resolv_conf(Manager *m) { + _cleanup_fclose_ FILE *f = NULL; + struct stat st; + unsigned n = 0; + int r; + + assert(m); + + /* Reads the system /etc/resolv.conf, if it exists and is not + * symlinked to our own resolv.conf instance */ + + if (!m->read_resolv_conf) + return 0; + + r = stat("/etc/resolv.conf", &st); + if (r < 0) { + if (errno == ENOENT) + return 0; + + r = log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m"); + goto clear; + } + + /* Have we already seen the file? */ + if (timespec_load(&st.st_mtim) == m->resolv_conf_mtime) + return 0; + + if (file_is_our_own(&st)) + return 0; + + f = fopen("/etc/resolv.conf", "re"); + if (!f) { + if (errno == ENOENT) + return 0; + + r = log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m"); + goto clear; + } + + if (fstat(fileno(f), &st) < 0) { + r = log_error_errno(errno, "Failed to stat open file: %m"); + goto clear; + } + + if (file_is_our_own(&st)) + return 0; + + dns_server_mark_all(m->dns_servers); + dns_search_domain_mark_all(m->search_domains); + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *a; + char *l; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) { + log_error_errno(r, "Failed to read /etc/resolv.conf: %m"); + goto clear; + } + if (r == 0) + break; + + n++; + + l = strstrip(line); + if (IN_SET(*l, '#', ';', 0)) + continue; + + a = first_word(l, "nameserver"); + if (a) { + r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_SYSTEM, a); + if (r < 0) + log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring.", a); + + continue; + } + + a = first_word(l, "domain"); + if (!a) /* We treat "domain" lines, and "search" lines as equivalent, and add both to our list. */ + a = first_word(l, "search"); + if (a) { + r = manager_parse_search_domains_and_warn(m, a); + if (r < 0) + log_warning_errno(r, "Failed to parse search domain string '%s', ignoring.", a); + } + + log_syntax(NULL, LOG_DEBUG, "/etc/resolv.conf", n, 0, "Ignoring resolv.conf line: %s", l); + } + + m->resolv_conf_mtime = timespec_load(&st.st_mtim); + + /* Flush out all servers and search domains that are still + * marked. Those are then ones that didn't appear in the new + * /etc/resolv.conf */ + dns_server_unlink_marked(m->dns_servers); + dns_search_domain_unlink_marked(m->search_domains); + + /* Whenever /etc/resolv.conf changes, start using the first + * DNS server of it. This is useful to deal with broken + * network managing implementations (like NetworkManager), + * that when connecting to a VPN place both the VPN DNS + * servers and the local ones in /etc/resolv.conf. Without + * resetting the DNS server to use back to the first entry we + * will continue to use the local one thus being unable to + * resolve VPN domains. */ + manager_set_dns_server(m, m->dns_servers); + + /* Unconditionally flush the cache when /etc/resolv.conf is + * modified, even if the data it contained was completely + * identical to the previous version we used. We do this + * because altering /etc/resolv.conf is typically done when + * the network configuration changes, and that should be + * enough to flush the global unicast DNS cache. */ + if (m->unicast_scope) + dns_cache_flush(&m->unicast_scope->cache); + + /* If /etc/resolv.conf changed, make sure to forget everything we learned about the DNS servers. After all we + * might now talk to a very different DNS server that just happens to have the same IP address as an old one + * (think 192.168.1.1). */ + dns_server_reset_features_all(m->dns_servers); + + return 0; + +clear: + dns_server_unlink_all(m->dns_servers); + dns_search_domain_unlink_all(m->search_domains); + return r; +} + +static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) { + DnsScope *scope; + + assert(s); + assert(f); + assert(count); + + if (!dns_server_string(s)) { + log_warning("Out of memory, or invalid DNS address. Ignoring server."); + return; + } + + /* Check if the scope this DNS server belongs to is suitable as 'default' route for lookups; resolv.conf does + * not have a syntax to express that, so it must not appear as a global name server to avoid routing unrelated + * domains to it (which is a privacy violation, will most probably fail anyway, and adds unnecessary load) */ + scope = dns_server_scope(s); + if (scope && !dns_scope_is_default_route(scope)) { + log_debug("Scope of DNS server %s has only route-only domains, not using as global name server", dns_server_string(s)); + return; + } + + if (*count == MAXNS) + fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f); + (*count)++; + + fprintf(f, "nameserver %s\n", dns_server_string(s)); +} + +static void write_resolv_conf_search( + OrderedSet *domains, + FILE *f) { + unsigned length = 0, count = 0; + Iterator i; + char *domain; + + assert(domains); + assert(f); + + fputs("search", f); + + ORDERED_SET_FOREACH(domain, domains, i) { + if (++count > MAXDNSRCH) { + fputs("\n# Too many search domains configured, remaining ones ignored.", f); + break; + } + length += strlen(domain) + 1; + if (length > 256) { + fputs("\n# Total length of all search domains is too long, remaining ones ignored.", f); + break; + } + fputc(' ', f); + fputs(domain, f); + } + + fputs("\n", f); +} + +static int write_uplink_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) { + Iterator i; + + fputs("# This file is managed by man:systemd-resolved(8). Do not edit.\n" + "#\n" + "# This is a dynamic resolv.conf file for connecting local clients directly to\n" + "# all known uplink DNS servers. This file lists all configured search domains.\n" + "#\n" + "# Third party programs must not access this file directly, but only through the\n" + "# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,\n" + "# replace this symlink by a static file or a different symlink.\n" + "#\n" + "# See man:systemd-resolved.service(8) for details about the supported modes of\n" + "# operation for /etc/resolv.conf.\n" + "\n", f); + + if (ordered_set_isempty(dns)) + fputs("# No DNS servers known.\n", f); + else { + unsigned count = 0; + DnsServer *s; + + ORDERED_SET_FOREACH(s, dns, i) + write_resolv_conf_server(s, f, &count); + } + + if (!ordered_set_isempty(domains)) + write_resolv_conf_search(domains, f); + + return fflush_and_check(f); +} + +static int write_stub_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) { + fputs_unlocked("# This file is managed by man:systemd-resolved(8). Do not edit.\n" + "#\n" + "# This is a dynamic resolv.conf file for connecting local clients to the\n" + "# internal DNS stub resolver of systemd-resolved. This file lists all\n" + "# configured search domains.\n" + "#\n" + "# Run \"resolvectl status\" to see details about the uplink DNS servers\n" + "# currently in use.\n" + "#\n" + "# Third party programs must not access this file directly, but only through the\n" + "# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,\n" + "# replace this symlink by a static file or a different symlink.\n" + "#\n" + "# See man:systemd-resolved.service(8) for details about the supported modes of\n" + "# operation for /etc/resolv.conf.\n" + "\n" + "nameserver 127.0.0.53\n" + "options edns0\n", f); + + if (!ordered_set_isempty(domains)) + write_resolv_conf_search(domains, f); + + return fflush_and_check(f); +} + +int manager_write_resolv_conf(Manager *m) { + _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL; + _cleanup_free_ char *temp_path_uplink = NULL, *temp_path_stub = NULL; + _cleanup_fclose_ FILE *f_uplink = NULL, *f_stub = NULL; + int r; + + assert(m); + + /* Read the system /etc/resolv.conf first */ + (void) manager_read_resolv_conf(m); + + /* Add the full list to a set, to filter out duplicates */ + r = manager_compile_dns_servers(m, &dns); + if (r < 0) + return log_warning_errno(r, "Failed to compile list of DNS servers: %m"); + + r = manager_compile_search_domains(m, &domains, false); + if (r < 0) + return log_warning_errno(r, "Failed to compile list of search domains: %m"); + + r = fopen_temporary_label(PRIVATE_UPLINK_RESOLV_CONF, PRIVATE_UPLINK_RESOLV_CONF, &f_uplink, &temp_path_uplink); + if (r < 0) + return log_warning_errno(r, "Failed to open private resolv.conf file for writing: %m"); + + (void) fchmod(fileno(f_uplink), 0644); + + r = fopen_temporary_label(PRIVATE_STUB_RESOLV_CONF, PRIVATE_STUB_RESOLV_CONF, &f_stub, &temp_path_stub); + if (r < 0) + return log_warning_errno(r, "Failed to open private stub-resolv.conf file for writing: %m"); + + (void) fchmod(fileno(f_stub), 0644); + + r = write_uplink_resolv_conf_contents(f_uplink, dns, domains); + if (r < 0) { + log_error_errno(r, "Failed to write private resolv.conf contents: %m"); + goto fail; + } + + if (rename(temp_path_uplink, PRIVATE_UPLINK_RESOLV_CONF) < 0) { + r = log_error_errno(errno, "Failed to move private resolv.conf file into place: %m"); + goto fail; + } + + r = write_stub_resolv_conf_contents(f_stub, dns, domains); + if (r < 0) { + log_error_errno(r, "Failed to write private stub-resolv.conf contents: %m"); + goto fail; + } + + if (rename(temp_path_stub, PRIVATE_STUB_RESOLV_CONF) < 0) { + r = log_error_errno(errno, "Failed to move private stub-resolv.conf file into place: %m"); + goto fail; + } + + return 0; + +fail: + (void) unlink(PRIVATE_UPLINK_RESOLV_CONF); + (void) unlink(temp_path_uplink); + (void) unlink(PRIVATE_STUB_RESOLV_CONF); + (void) unlink(temp_path_stub); + + return r; +} diff --git a/src/resolve/resolved-resolv-conf.h b/src/resolve/resolved-resolv-conf.h new file mode 100644 index 00000000..f69cf2a4 --- /dev/null +++ b/src/resolve/resolved-resolv-conf.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "resolved-manager.h" + +int manager_check_resolv_conf(const Manager *m); +int manager_read_resolv_conf(Manager *m); +int manager_write_resolv_conf(Manager *m); diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c new file mode 100644 index 00000000..2ca9fbdc --- /dev/null +++ b/src/resolve/resolved.c @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-event.h" + +#include "capability-util.h" +#include "daemon-util.h" +#include "main-func.h" +#include "mkdir.h" +#include "resolved-conf.h" +#include "resolved-manager.h" +#include "resolved-resolv-conf.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "user-util.h" + +static int run(int argc, char *argv[]) { + _cleanup_(notify_on_cleanup) const char *notify_stop = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + const char *user = "systemd-resolve"; + uid_t uid; + gid_t gid; + int r; + + log_setup_service(); + + if (argc != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); + + umask(0022); + + r = mac_selinux_init(); + if (r < 0) + return log_error_errno(r, "SELinux setup failed: %m"); + + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); + if (r < 0) + return log_error_errno(r, "Cannot resolve user name %s: %m", user); + + /* Always create the directory where resolv.conf will live */ + r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid, MKDIR_WARN_MODE); + if (r < 0) + return log_error_errno(r, "Could not create runtime directory: %m"); + + /* Drop privileges, but only if we have been started as root. If we are not running as root we assume most + * privileges are already dropped. */ + if (getuid() == 0) { + + /* Drop privileges, but keep three caps. Note that we drop those too, later on (see below) */ + r = drop_privileges(uid, gid, + (UINT64_C(1) << CAP_NET_RAW)| /* needed for SO_BINDTODEVICE */ + (UINT64_C(1) << CAP_NET_BIND_SERVICE)| /* needed to bind on port 53 */ + (UINT64_C(1) << CAP_SETPCAP) /* needed in order to drop the caps later */); + if (r < 0) + return log_error_errno(r, "Failed to drop privileges: %m"); + } + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGUSR1, SIGUSR2, SIGRTMIN+1, -1) >= 0); + + r = manager_new(&m); + if (r < 0) + return log_error_errno(r, "Could not create manager: %m"); + + r = manager_start(m); + if (r < 0) + return log_error_errno(r, "Failed to start manager: %m"); + + /* Write finish default resolv.conf to avoid a dangling symlink */ + (void) manager_write_resolv_conf(m); + + (void) manager_check_resolv_conf(m); + + /* Let's drop the remaining caps now */ + r = capability_bounding_set_drop(0, true); + if (r < 0) + return log_error_errno(r, "Failed to drop remaining caps: %m"); + + notify_stop = notify_start(NOTIFY_READY, NOTIFY_STOPPING); + + r = sd_event_loop(m->event); + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in new file mode 100644 index 00000000..6898c784 --- /dev/null +++ b/src/resolve/resolved.conf.in @@ -0,0 +1,24 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See resolved.conf(5) for details + +[Resolve] +#DNS= +#FallbackDNS=@DNS_SERVERS@ +#Domains= +#LLMNR=yes +#MulticastDNS=yes +#DNSSEC=@DEFAULT_DNSSEC_MODE@ +#DNSOverTLS=@DEFAULT_DNS_OVER_TLS_MODE@ +#Cache=yes +#DNSStubListener=yes +#ReadEtcHosts=yes diff --git a/src/resolve/test-dns-packet.c b/src/resolve/test-dns-packet.c new file mode 100644 index 00000000..7c6346cb --- /dev/null +++ b/src/resolve/test-dns-packet.c @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "fileio.h" +#include "glob-util.h" +#include "log.h" +#include "macro.h" +#include "resolved-dns-packet.h" +#include "resolved-dns-rr.h" +#include "path-util.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "unaligned.h" + +#define HASH_KEY SD_ID128_MAKE(d3,1e,48,90,4b,fa,4c,fe,af,9d,d5,a1,d7,2e,8a,b1) + +static void verify_rr_copy(DnsResourceRecord *rr) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *copy = NULL; + const char *a, *b; + + assert_se(copy = dns_resource_record_copy(rr)); + assert_se(dns_resource_record_equal(copy, rr) > 0); + + assert_se(a = dns_resource_record_to_string(rr)); + assert_se(b = dns_resource_record_to_string(copy)); + + assert_se(streq(a, b)); +} + +static uint64_t hash(DnsResourceRecord *rr) { + struct siphash state; + + siphash24_init(&state, HASH_KEY.bytes); + dns_resource_record_hash_func(rr, &state); + return siphash24_finalize(&state); +} + +static void test_packet_from_file(const char* filename, bool canonical) { + _cleanup_free_ char *data = NULL; + size_t data_size, packet_size, offset; + + assert_se(read_full_file(filename, &data, &data_size) >= 0); + assert_se(data); + assert_se(data_size > 8); + + log_info("============== %s %s==============", filename, canonical ? "canonical " : ""); + + for (offset = 0; offset < data_size; offset += 8 + packet_size) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL, *p2 = NULL; + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL, *rr2 = NULL; + const char *s, *s2; + uint64_t hash1, hash2; + + packet_size = unaligned_read_le64(data + offset); + assert_se(packet_size > 0); + assert_se(offset + 8 + packet_size <= data_size); + + assert_se(dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, DNS_PACKET_SIZE_MAX) >= 0); + + assert_se(dns_packet_append_blob(p, data + offset + 8, packet_size, NULL) >= 0); + assert_se(dns_packet_read_rr(p, &rr, NULL, NULL) >= 0); + + verify_rr_copy(rr); + + s = dns_resource_record_to_string(rr); + assert_se(s); + puts(s); + + hash1 = hash(rr); + + assert_se(dns_resource_record_to_wire_format(rr, canonical) >= 0); + + assert_se(dns_packet_new(&p2, DNS_PROTOCOL_DNS, 0, DNS_PACKET_SIZE_MAX) >= 0); + assert_se(dns_packet_append_blob(p2, rr->wire_format, rr->wire_format_size, NULL) >= 0); + assert_se(dns_packet_read_rr(p2, &rr2, NULL, NULL) >= 0); + + verify_rr_copy(rr); + + s2 = dns_resource_record_to_string(rr); + assert_se(s2); + assert_se(streq(s, s2)); + + hash2 = hash(rr); + assert_se(hash1 == hash2); + } +} + +int main(int argc, char **argv) { + int i, N; + _cleanup_free_ char *pkts_glob = NULL; + _cleanup_globfree_ glob_t g = {}; + char **fnames; + + log_parse_environment(); + + if (argc >= 2) { + N = argc - 1; + fnames = argv + 1; + } else { + pkts_glob = path_join(get_testdata_dir(), "test-resolve/*.pkts"); + assert_se(glob(pkts_glob, GLOB_NOSORT, NULL, &g) == 0); + N = g.gl_pathc; + fnames = g.gl_pathv; + } + + for (i = 0; i < N; i++) { + test_packet_from_file(fnames[i], false); + puts(""); + test_packet_from_file(fnames[i], true); + if (i + 1 < N) + puts(""); + } + + return EXIT_SUCCESS; +} diff --git a/src/resolve/test-dnssec-complex.c b/src/resolve/test-dnssec-complex.c new file mode 100644 index 00000000..ccd62a14 --- /dev/null +++ b/src/resolve/test-dnssec-complex.c @@ -0,0 +1,223 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-bus.h" + +#include "af-list.h" +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "dns-type.h" +#include "random-util.h" +#include "resolved-def.h" +#include "string-util.h" +#include "time-util.h" + +static void prefix_random(const char *name, char **ret) { + uint64_t i, u; + char *m = NULL; + + u = 1 + (random_u64() & 3); + + for (i = 0; i < u; i++) { + _cleanup_free_ char *b = NULL; + char *x; + + assert_se(asprintf(&b, "x%" PRIu64 "x", random_u64())); + x = strjoin(b, ".", name); + assert_se(x); + + free(m); + m = x; + } + + *ret = m; + } + +static void test_rr_lookup(sd_bus *bus, const char *name, uint16_t type, const char *result) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *m = NULL; + int r; + + /* If the name starts with a dot, we prefix one to three random labels */ + if (startswith(name, ".")) { + prefix_random(name + 1, &m); + name = m; + } + + assert_se(sd_bus_message_new_method_call( + bus, + &req, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResolveRecord") >= 0); + + assert_se(sd_bus_message_append(req, "isqqt", 0, name, DNS_CLASS_IN, type, UINT64_C(0)) >= 0); + + r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); + + if (r < 0) { + assert_se(result); + assert_se(sd_bus_error_has_name(&error, result)); + log_info("[OK] %s/%s resulted in <%s>.", name, dns_type_to_string(type), error.name); + } else { + assert_se(!result); + log_info("[OK] %s/%s succeeded.", name, dns_type_to_string(type)); + } +} + +static void test_hostname_lookup(sd_bus *bus, const char *name, int family, const char *result) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *m = NULL; + const char *af; + int r; + + af = family == AF_UNSPEC ? "AF_UNSPEC" : af_to_name(family); + + /* If the name starts with a dot, we prefix one to three random labels */ + if (startswith(name, ".")) { + prefix_random(name + 1, &m); + name = m; + } + + assert_se(sd_bus_message_new_method_call( + bus, + &req, + "org.freedesktop.resolve1", + "/org/freedesktop/resolve1", + "org.freedesktop.resolve1.Manager", + "ResolveHostname") >= 0); + + assert_se(sd_bus_message_append(req, "isit", 0, name, family, UINT64_C(0)) >= 0); + + r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply); + + if (r < 0) { + assert_se(result); + assert_se(sd_bus_error_has_name(&error, result)); + log_info("[OK] %s/%s resulted in <%s>.", name, af, error.name); + } else { + assert_se(!result); + log_info("[OK] %s/%s succeeded.", name, af); + } + +} + +int main(int argc, char* argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + + /* Note that this is a manual test as it requires: + * + * Full network access + * A DNSSEC capable DNS server + * That zones contacted are still set up as they were when I wrote this. + */ + + assert_se(sd_bus_open_system(&bus) >= 0); + + /* Normally signed */ + test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_A, NULL); + test_hostname_lookup(bus, "www.eurid.eu", AF_UNSPEC, NULL); + + test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_A, NULL); + test_hostname_lookup(bus, "sigok.verteiltesysteme.net", AF_UNSPEC, NULL); + + /* Normally signed, NODATA */ + test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); + test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); + + /* Invalid signature */ + test_rr_lookup(bus, "sigfail.verteiltesysteme.net", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED); + test_hostname_lookup(bus, "sigfail.verteiltesysteme.net", AF_INET, BUS_ERROR_DNSSEC_FAILED); + + /* Invalid signature, RSA, wildcard */ + test_rr_lookup(bus, ".wilda.rhybar.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED); + test_hostname_lookup(bus, ".wilda.rhybar.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED); + + /* Invalid signature, ECDSA, wildcard */ + test_rr_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED); + test_hostname_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED); + + /* Missing DS for DNSKEY */ + test_rr_lookup(bus, "www.dnssec-bogus.sg", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED); + test_hostname_lookup(bus, "www.dnssec-bogus.sg", AF_INET, BUS_ERROR_DNSSEC_FAILED); + + /* NXDOMAIN in NSEC domain */ + test_rr_lookup(bus, "hhh.nasa.gov", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN"); + test_hostname_lookup(bus, "hhh.nasa.gov", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN"); + test_rr_lookup(bus, "_pgpkey-https._tcp.hkps.pool.sks-keyservers.net", DNS_TYPE_SRV, _BUS_ERROR_DNS "NXDOMAIN"); + + /* wildcard, NSEC zone */ + test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_A, NULL); + test_hostname_lookup(bus, ".wilda.nsec.0skar.cz", AF_INET, NULL); + + /* wildcard, NSEC zone, NODATA */ + test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); + + /* wildcard, NSEC3 zone */ + test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_A, NULL); + test_hostname_lookup(bus, ".wilda.0skar.cz", AF_INET, NULL); + + /* wildcard, NSEC3 zone, NODATA */ + test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); + + /* wildcard, NSEC zone, CNAME */ + test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_A, NULL); + test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_UNSPEC, NULL); + test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_INET, NULL); + + /* wildcard, NSEC zone, NODATA, CNAME */ + test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); + + /* wildcard, NSEC3 zone, CNAME */ + test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_A, NULL); + test_hostname_lookup(bus, ".wild.0skar.cz", AF_UNSPEC, NULL); + test_hostname_lookup(bus, ".wild.0skar.cz", AF_INET, NULL); + + /* wildcard, NSEC3 zone, NODATA, CNAME */ + test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR); + + /* NODATA due to empty non-terminal in NSEC domain */ + test_rr_lookup(bus, "herndon.nasa.gov", DNS_TYPE_A, BUS_ERROR_NO_SUCH_RR); + test_hostname_lookup(bus, "herndon.nasa.gov", AF_UNSPEC, BUS_ERROR_NO_SUCH_RR); + test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET, BUS_ERROR_NO_SUCH_RR); + test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET6, BUS_ERROR_NO_SUCH_RR); + + /* NXDOMAIN in NSEC root zone: */ + test_rr_lookup(bus, "jasdhjas.kjkfgjhfjg", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN"); + test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN"); + test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET, _BUS_ERROR_DNS "NXDOMAIN"); + test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN"); + + /* NXDOMAIN in NSEC3 .com zone: */ + test_rr_lookup(bus, "kjkfgjhfjgsdfdsfd.com", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN"); + test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET, _BUS_ERROR_DNS "NXDOMAIN"); + test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN"); + test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN"); + + /* Unsigned A */ + test_rr_lookup(bus, "poettering.de", DNS_TYPE_A, NULL); + test_rr_lookup(bus, "poettering.de", DNS_TYPE_AAAA, NULL); + test_hostname_lookup(bus, "poettering.de", AF_UNSPEC, NULL); + test_hostname_lookup(bus, "poettering.de", AF_INET, NULL); + test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL); + +#if HAVE_LIBIDN2 || HAVE_LIBIDN + /* Unsigned A with IDNA conversion necessary */ + test_hostname_lookup(bus, "pöttering.de", AF_UNSPEC, NULL); + test_hostname_lookup(bus, "pöttering.de", AF_INET, NULL); + test_hostname_lookup(bus, "pöttering.de", AF_INET6, NULL); +#endif + + /* DNAME, pointing to NXDOMAIN */ + test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN"); + test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_RP, _BUS_ERROR_DNS "NXDOMAIN"); + test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN"); + test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET, _BUS_ERROR_DNS "NXDOMAIN"); + test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN"); + + return 0; +} diff --git a/src/resolve/test-dnssec.c b/src/resolve/test-dnssec.c new file mode 100644 index 00000000..840c4fa1 --- /dev/null +++ b/src/resolve/test-dnssec.c @@ -0,0 +1,514 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#if HAVE_GCRYPT +#include +#endif +#include +#include + +#include "alloc-util.h" +#include "resolved-dns-dnssec.h" +#include "resolved-dns-rr.h" +#include "string-util.h" +#include "hexdecoct.h" + +static void test_dnssec_canonicalize_one(const char *original, const char *canonical, int r) { + char canonicalized[DNSSEC_CANONICAL_HOSTNAME_MAX]; + + assert_se(dnssec_canonicalize(original, canonicalized, sizeof(canonicalized)) == r); + if (r < 0) + return; + + assert_se(streq(canonicalized, canonical)); +} + +static void test_dnssec_canonicalize(void) { + test_dnssec_canonicalize_one("", ".", 1); + test_dnssec_canonicalize_one(".", ".", 1); + test_dnssec_canonicalize_one("foo", "foo.", 4); + test_dnssec_canonicalize_one("foo.", "foo.", 4); + test_dnssec_canonicalize_one("FOO.", "foo.", 4); + test_dnssec_canonicalize_one("FOO.bar.", "foo.bar.", 8); + test_dnssec_canonicalize_one("FOO..bar.", NULL, -EINVAL); +} + +#if HAVE_GCRYPT + +static void test_dnssec_verify_dns_key(void) { + + static const uint8_t ds1_fprint[] = { + 0x46, 0x8B, 0xC8, 0xDD, 0xC7, 0xE8, 0x27, 0x03, 0x40, 0xBB, 0x8A, 0x1F, 0x3B, 0x2E, 0x45, 0x9D, + 0x80, 0x67, 0x14, 0x01, + }; + static const uint8_t ds2_fprint[] = { + 0x8A, 0xEE, 0x80, 0x47, 0x05, 0x5F, 0x83, 0xD1, 0x48, 0xBA, 0x8F, 0xF6, 0xDD, 0xA7, 0x60, 0xCE, + 0x94, 0xF7, 0xC7, 0x5E, 0x52, 0x4C, 0xF2, 0xE9, 0x50, 0xB9, 0x2E, 0xCB, 0xEF, 0x96, 0xB9, 0x98, + }; + static const uint8_t dnskey_blob[] = { + 0x03, 0x01, 0x00, 0x01, 0xa8, 0x12, 0xda, 0x4f, 0xd2, 0x7d, 0x54, 0x14, 0x0e, 0xcc, 0x5b, 0x5e, + 0x45, 0x9c, 0x96, 0x98, 0xc0, 0xc0, 0x85, 0x81, 0xb1, 0x47, 0x8c, 0x7d, 0xe8, 0x39, 0x50, 0xcc, + 0xc5, 0xd0, 0xf2, 0x00, 0x81, 0x67, 0x79, 0xf6, 0xcc, 0x9d, 0xad, 0x6c, 0xbb, 0x7b, 0x6f, 0x48, + 0x97, 0x15, 0x1c, 0xfd, 0x0b, 0xfe, 0xd3, 0xd7, 0x7d, 0x9f, 0x81, 0x26, 0xd3, 0xc5, 0x65, 0x49, + 0xcf, 0x46, 0x62, 0xb0, 0x55, 0x6e, 0x47, 0xc7, 0x30, 0xef, 0x51, 0xfb, 0x3e, 0xc6, 0xef, 0xde, + 0x27, 0x3f, 0xfa, 0x57, 0x2d, 0xa7, 0x1d, 0x80, 0x46, 0x9a, 0x5f, 0x14, 0xb3, 0xb0, 0x2c, 0xbe, + 0x72, 0xca, 0xdf, 0xb2, 0xff, 0x36, 0x5b, 0x4f, 0xec, 0x58, 0x8e, 0x8d, 0x01, 0xe9, 0xa9, 0xdf, + 0xb5, 0x60, 0xad, 0x52, 0x4d, 0xfc, 0xa9, 0x3e, 0x8d, 0x35, 0x95, 0xb3, 0x4e, 0x0f, 0xca, 0x45, + 0x1b, 0xf7, 0xef, 0x3a, 0x88, 0x25, 0x08, 0xc7, 0x4e, 0x06, 0xc1, 0x62, 0x1a, 0xce, 0xd8, 0x77, + 0xbd, 0x02, 0x65, 0xf8, 0x49, 0xfb, 0xce, 0xf6, 0xa8, 0x09, 0xfc, 0xde, 0xb2, 0x09, 0x9d, 0x39, + 0xf8, 0x63, 0x9c, 0x32, 0x42, 0x7c, 0xa0, 0x30, 0x86, 0x72, 0x7a, 0x4a, 0xc6, 0xd4, 0xb3, 0x2d, + 0x24, 0xef, 0x96, 0x3f, 0xc2, 0xda, 0xd3, 0xf2, 0x15, 0x6f, 0xda, 0x65, 0x4b, 0x81, 0x28, 0x68, + 0xf4, 0xfe, 0x3e, 0x71, 0x4f, 0x50, 0x96, 0x72, 0x58, 0xa1, 0x89, 0xdd, 0x01, 0x61, 0x39, 0x39, + 0xc6, 0x76, 0xa4, 0xda, 0x02, 0x70, 0x3d, 0xc0, 0xdc, 0x8d, 0x70, 0x72, 0x04, 0x90, 0x79, 0xd4, + 0xec, 0x65, 0xcf, 0x49, 0x35, 0x25, 0x3a, 0x14, 0x1a, 0x45, 0x20, 0xeb, 0x31, 0xaf, 0x92, 0xba, + 0x20, 0xd3, 0xcd, 0xa7, 0x13, 0x44, 0xdc, 0xcf, 0xf0, 0x27, 0x34, 0xb9, 0xe7, 0x24, 0x6f, 0x73, + 0xe7, 0xea, 0x77, 0x03, + }; + + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds1 = NULL, *ds2 = NULL; + + /* The two DS RRs in effect for nasa.gov on 2015-12-01. */ + ds1 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "nasa.gov"); + assert_se(ds1); + + ds1->ds.key_tag = 47857; + ds1->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256; + ds1->ds.digest_type = DNSSEC_DIGEST_SHA1; + ds1->ds.digest_size = sizeof(ds1_fprint); + ds1->ds.digest = memdup(ds1_fprint, ds1->ds.digest_size); + assert_se(ds1->ds.digest); + + log_info("DS1: %s", strna(dns_resource_record_to_string(ds1))); + + ds2 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "NASA.GOV"); + assert_se(ds2); + + ds2->ds.key_tag = 47857; + ds2->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256; + ds2->ds.digest_type = DNSSEC_DIGEST_SHA256; + ds2->ds.digest_size = sizeof(ds2_fprint); + ds2->ds.digest = memdup(ds2_fprint, ds2->ds.digest_size); + assert_se(ds2->ds.digest); + + log_info("DS2: %s", strna(dns_resource_record_to_string(ds2))); + + dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nasa.GOV"); + assert_se(dnskey); + + dnskey->dnskey.flags = 257; + dnskey->dnskey.protocol = 3; + dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256; + dnskey->dnskey.key_size = sizeof(dnskey_blob); + dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob)); + assert_se(dnskey->dnskey.key); + + log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey))); + log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false)); + + assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds1, false) > 0); + assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds2, false) > 0); +} + +static void test_dnssec_verify_rfc8080_ed25519_example1(void) { + static const uint8_t dnskey_blob[] = { + 0x97, 0x4d, 0x96, 0xa2, 0x2d, 0x22, 0x4b, 0xc0, 0x1a, 0xdb, 0x91, 0x50, 0x91, 0x47, 0x7d, + 0x44, 0xcc, 0xd9, 0x1c, 0x9a, 0x41, 0xa1, 0x14, 0x30, 0x01, 0x01, 0x17, 0xd5, 0x2c, 0x59, + 0x24, 0xe + }; + static const uint8_t ds_fprint[] = { + 0xdd, 0xa6, 0xb9, 0x69, 0xbd, 0xfb, 0x79, 0xf7, 0x1e, 0xe7, 0xb7, 0xfb, 0xdf, 0xb7, 0xdc, + 0xd7, 0xad, 0xbb, 0xd3, 0x5d, 0xdf, 0x79, 0xed, 0x3b, 0x6d, 0xd7, 0xf6, 0xe3, 0x56, 0xdd, + 0xd7, 0x47, 0xf7, 0x6f, 0x5f, 0x7a, 0xe1, 0xa6, 0xf9, 0xe5, 0xce, 0xfc, 0x7b, 0xbf, 0x5a, + 0xdf, 0x4e, 0x1b + }; + static const uint8_t signature_blob[] = { + 0xa0, 0xbf, 0x64, 0xac, 0x9b, 0xa7, 0xef, 0x17, 0xc1, 0x38, 0x85, 0x9c, 0x18, 0x78, 0xbb, + 0x99, 0xa8, 0x39, 0xfe, 0x17, 0x59, 0xac, 0xa5, 0xb0, 0xd7, 0x98, 0xcf, 0x1a, 0xb1, 0xe9, + 0x8d, 0x07, 0x91, 0x02, 0xf4, 0xdd, 0xb3, 0x36, 0x8f, 0x0f, 0xe4, 0x0b, 0xb3, 0x77, 0xf1, + 0xf0, 0x0e, 0x0c, 0xdd, 0xed, 0xb7, 0x99, 0x16, 0x7d, 0x56, 0xb6, 0xe9, 0x32, 0x78, 0x30, + 0x72, 0xba, 0x8d, 0x02 + }; + + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds = NULL, *mx = NULL, + *rrsig = NULL; + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + DnssecResult result; + + dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "example.com."); + assert_se(dnskey); + + dnskey->dnskey.flags = 257; + dnskey->dnskey.protocol = 3; + dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_ED25519; + dnskey->dnskey.key_size = sizeof(dnskey_blob); + dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob)); + assert_se(dnskey->dnskey.key); + + log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey))); + + ds = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "example.com."); + assert_se(ds); + + ds->ds.key_tag = 3613; + ds->ds.algorithm = DNSSEC_ALGORITHM_ED25519; + ds->ds.digest_type = DNSSEC_DIGEST_SHA256; + ds->ds.digest_size = sizeof(ds_fprint); + ds->ds.digest = memdup(ds_fprint, ds->ds.digest_size); + assert_se(ds->ds.digest); + + log_info("DS: %s", strna(dns_resource_record_to_string(ds))); + + mx = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_MX, "example.com."); + assert_se(mx); + + mx->mx.priority = 10; + mx->mx.exchange = strdup("mail.example.com."); + assert_se(mx->mx.exchange); + + log_info("MX: %s", strna(dns_resource_record_to_string(mx))); + + rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "example.com."); + assert_se(rrsig); + + rrsig->rrsig.type_covered = DNS_TYPE_MX; + rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_ED25519; + rrsig->rrsig.labels = 2; + rrsig->rrsig.original_ttl = 3600; + rrsig->rrsig.expiration = 1440021600; + rrsig->rrsig.inception = 1438207200; + rrsig->rrsig.key_tag = 3613; + rrsig->rrsig.signer = strdup("example.com."); + assert_se(rrsig->rrsig.signer); + rrsig->rrsig.signature_size = sizeof(signature_blob); + rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size); + assert_se(rrsig->rrsig.signature); + + log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig))); + + assert_se(dnssec_key_match_rrsig(mx->key, rrsig) > 0); + assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0); + + answer = dns_answer_new(1); + assert_se(answer); + assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0); + + assert_se(dnssec_verify_rrset(answer, mx->key, rrsig, dnskey, + rrsig->rrsig.inception * USEC_PER_SEC, &result) >= 0); +#if GCRYPT_VERSION_NUMBER >= 0x010600 + assert_se(result == DNSSEC_VALIDATED); +#else + assert_se(result == DNSSEC_UNSUPPORTED_ALGORITHM); +#endif +} + +static void test_dnssec_verify_rfc8080_ed25519_example2(void) { + static const uint8_t dnskey_blob[] = { + 0xcc, 0xf9, 0xd9, 0xfd, 0x0c, 0x04, 0x7b, 0xb4, 0xbc, 0x0b, 0x94, 0x8f, 0xcf, 0x63, 0x9f, + 0x4b, 0x94, 0x51, 0xe3, 0x40, 0x13, 0x93, 0x6f, 0xeb, 0x62, 0x71, 0x3d, 0xc4, 0x72, 0x4, + 0x8a, 0x3b + }; + static const uint8_t ds_fprint[] = { + 0xe3, 0x4d, 0x7b, 0xf3, 0x56, 0xfd, 0xdf, 0x87, 0xb7, 0xf7, 0x67, 0x5e, 0xe3, 0xdd, 0x9e, + 0x73, 0xbe, 0xda, 0x7b, 0x67, 0xb5, 0xe5, 0xde, 0xf4, 0x7f, 0xae, 0x7b, 0xe5, 0xad, 0x5c, + 0xd1, 0xb7, 0x39, 0xf5, 0xce, 0x76, 0xef, 0x97, 0x34, 0xe1, 0xe6, 0xde, 0xf3, 0x47, 0x3a, + 0xeb, 0x5e, 0x1c + }; + static const uint8_t signature_blob[] = { + 0xcd, 0x74, 0x34, 0x6e, 0x46, 0x20, 0x41, 0x31, 0x05, 0xc9, 0xf2, 0xf2, 0x8b, 0xd4, 0x28, + 0x89, 0x8e, 0x83, 0xf1, 0x97, 0x58, 0xa3, 0x8c, 0x32, 0x52, 0x15, 0x62, 0xa1, 0x86, 0x57, + 0x15, 0xd4, 0xf8, 0xd7, 0x44, 0x0f, 0x44, 0x84, 0xd0, 0x4a, 0xa2, 0x52, 0x9f, 0x34, 0x28, + 0x4a, 0x6e, 0x69, 0xa0, 0x9e, 0xe0, 0x0f, 0xb0, 0x10, 0x47, 0x43, 0xbb, 0x2a, 0xe2, 0x39, + 0x93, 0x6a, 0x5c, 0x06 + }; + + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds = NULL, *mx = NULL, + *rrsig = NULL; + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + DnssecResult result; + + dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "example.com."); + assert_se(dnskey); + + dnskey->dnskey.flags = 257; + dnskey->dnskey.protocol = 3; + dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_ED25519; + dnskey->dnskey.key_size = sizeof(dnskey_blob); + dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob)); + assert_se(dnskey->dnskey.key); + + log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey))); + + ds = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "example.com."); + assert_se(ds); + + ds->ds.key_tag = 35217; + ds->ds.algorithm = DNSSEC_ALGORITHM_ED25519; + ds->ds.digest_type = DNSSEC_DIGEST_SHA256; + ds->ds.digest_size = sizeof(ds_fprint); + ds->ds.digest = memdup(ds_fprint, ds->ds.digest_size); + assert_se(ds->ds.digest); + + log_info("DS: %s", strna(dns_resource_record_to_string(ds))); + + mx = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_MX, "example.com."); + assert_se(mx); + + mx->mx.priority = 10; + mx->mx.exchange = strdup("mail.example.com."); + assert_se(mx->mx.exchange); + + log_info("MX: %s", strna(dns_resource_record_to_string(mx))); + + rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "example.com."); + assert_se(rrsig); + + rrsig->rrsig.type_covered = DNS_TYPE_MX; + rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_ED25519; + rrsig->rrsig.labels = 2; + rrsig->rrsig.original_ttl = 3600; + rrsig->rrsig.expiration = 1440021600; + rrsig->rrsig.inception = 1438207200; + rrsig->rrsig.key_tag = 35217; + rrsig->rrsig.signer = strdup("example.com."); + assert_se(rrsig->rrsig.signer); + rrsig->rrsig.signature_size = sizeof(signature_blob); + rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size); + assert_se(rrsig->rrsig.signature); + + log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig))); + + assert_se(dnssec_key_match_rrsig(mx->key, rrsig) > 0); + assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0); + + answer = dns_answer_new(1); + assert_se(answer); + assert_se(dns_answer_add(answer, mx, 0, DNS_ANSWER_AUTHENTICATED) >= 0); + + assert_se(dnssec_verify_rrset(answer, mx->key, rrsig, dnskey, + rrsig->rrsig.inception * USEC_PER_SEC, &result) >= 0); +#if GCRYPT_VERSION_NUMBER >= 0x010600 + assert_se(result == DNSSEC_VALIDATED); +#else + assert_se(result == DNSSEC_UNSUPPORTED_ALGORITHM); +#endif +} +static void test_dnssec_verify_rrset(void) { + + static const uint8_t signature_blob[] = { + 0x7f, 0x79, 0xdd, 0x5e, 0x89, 0x79, 0x18, 0xd0, 0x34, 0x86, 0x8c, 0x72, 0x77, 0x75, 0x48, 0x4d, + 0xc3, 0x7d, 0x38, 0x04, 0xab, 0xcd, 0x9e, 0x4c, 0x82, 0xb0, 0x92, 0xca, 0xe9, 0x66, 0xe9, 0x6e, + 0x47, 0xc7, 0x68, 0x8c, 0x94, 0xf6, 0x69, 0xcb, 0x75, 0x94, 0xe6, 0x30, 0xa6, 0xfb, 0x68, 0x64, + 0x96, 0x1a, 0x84, 0xe1, 0xdc, 0x16, 0x4c, 0x83, 0x6c, 0x44, 0xf2, 0x74, 0x4d, 0x74, 0x79, 0x8f, + 0xf3, 0xf4, 0x63, 0x0d, 0xef, 0x5a, 0xe7, 0xe2, 0xfd, 0xf2, 0x2b, 0x38, 0x7c, 0x28, 0x96, 0x9d, + 0xb6, 0xcd, 0x5c, 0x3b, 0x57, 0xe2, 0x24, 0x78, 0x65, 0xd0, 0x9e, 0x77, 0x83, 0x09, 0x6c, 0xff, + 0x3d, 0x52, 0x3f, 0x6e, 0xd1, 0xed, 0x2e, 0xf9, 0xee, 0x8e, 0xa6, 0xbe, 0x9a, 0xa8, 0x87, 0x76, + 0xd8, 0x77, 0xcc, 0x96, 0xa0, 0x98, 0xa1, 0xd1, 0x68, 0x09, 0x43, 0xcf, 0x56, 0xd9, 0xd1, 0x66, + }; + + static const uint8_t dnskey_blob[] = { + 0x03, 0x01, 0x00, 0x01, 0x9b, 0x49, 0x9b, 0xc1, 0xf9, 0x9a, 0xe0, 0x4e, 0xcf, 0xcb, 0x14, 0x45, + 0x2e, 0xc9, 0xf9, 0x74, 0xa7, 0x18, 0xb5, 0xf3, 0xde, 0x39, 0x49, 0xdf, 0x63, 0x33, 0x97, 0x52, + 0xe0, 0x8e, 0xac, 0x50, 0x30, 0x8e, 0x09, 0xd5, 0x24, 0x3d, 0x26, 0xa4, 0x49, 0x37, 0x2b, 0xb0, + 0x6b, 0x1b, 0xdf, 0xde, 0x85, 0x83, 0xcb, 0x22, 0x4e, 0x60, 0x0a, 0x91, 0x1a, 0x1f, 0xc5, 0x40, + 0xb1, 0xc3, 0x15, 0xc1, 0x54, 0x77, 0x86, 0x65, 0x53, 0xec, 0x10, 0x90, 0x0c, 0x91, 0x00, 0x5e, + 0x15, 0xdc, 0x08, 0x02, 0x4c, 0x8c, 0x0d, 0xc0, 0xac, 0x6e, 0xc4, 0x3e, 0x1b, 0x80, 0x19, 0xe4, + 0xf7, 0x5f, 0x77, 0x51, 0x06, 0x87, 0x61, 0xde, 0xa2, 0x18, 0x0f, 0x40, 0x8b, 0x79, 0x72, 0xfa, + 0x8d, 0x1a, 0x44, 0x47, 0x0d, 0x8e, 0x3a, 0x2d, 0xc7, 0x39, 0xbf, 0x56, 0x28, 0x97, 0xd9, 0x20, + 0x4f, 0x00, 0x51, 0x3b, + }; + + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *a = NULL, *rrsig = NULL, *dnskey = NULL; + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + DnssecResult result; + + a = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, "nAsA.gov"); + assert_se(a); + + a->a.in_addr.s_addr = inet_addr("52.0.14.116"); + + log_info("A: %s", strna(dns_resource_record_to_string(a))); + + rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV."); + assert_se(rrsig); + + rrsig->rrsig.type_covered = DNS_TYPE_A; + rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_RSASHA256; + rrsig->rrsig.labels = 2; + rrsig->rrsig.original_ttl = 600; + rrsig->rrsig.expiration = 0x5683135c; + rrsig->rrsig.inception = 0x565b7da8; + rrsig->rrsig.key_tag = 63876; + rrsig->rrsig.signer = strdup("Nasa.Gov."); + assert_se(rrsig->rrsig.signer); + rrsig->rrsig.signature_size = sizeof(signature_blob); + rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size); + assert_se(rrsig->rrsig.signature); + + log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig))); + + dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV"); + assert_se(dnskey); + + dnskey->dnskey.flags = 256; + dnskey->dnskey.protocol = 3; + dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256; + dnskey->dnskey.key_size = sizeof(dnskey_blob); + dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob)); + assert_se(dnskey->dnskey.key); + + log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey))); + log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false)); + + assert_se(dnssec_key_match_rrsig(a->key, rrsig) > 0); + assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0); + + answer = dns_answer_new(1); + assert_se(answer); + assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED) >= 0); + + /* Validate the RR as it if was 2015-12-2 today */ + assert_se(dnssec_verify_rrset(answer, a->key, rrsig, dnskey, 1449092754*USEC_PER_SEC, &result) >= 0); + assert_se(result == DNSSEC_VALIDATED); +} + +static void test_dnssec_verify_rrset2(void) { + + static const uint8_t signature_blob[] = { + 0x48, 0x45, 0xc8, 0x8b, 0xc0, 0x14, 0x92, 0xf5, 0x15, 0xc6, 0x84, 0x9d, 0x2f, 0xe3, 0x32, 0x11, + 0x7d, 0xf1, 0xe6, 0x87, 0xb9, 0x42, 0xd3, 0x8b, 0x9e, 0xaf, 0x92, 0x31, 0x0a, 0x53, 0xad, 0x8b, + 0xa7, 0x5c, 0x83, 0x39, 0x8c, 0x28, 0xac, 0xce, 0x6e, 0x9c, 0x18, 0xe3, 0x31, 0x16, 0x6e, 0xca, + 0x38, 0x31, 0xaf, 0xd9, 0x94, 0xf1, 0x84, 0xb1, 0xdf, 0x5a, 0xc2, 0x73, 0x22, 0xf6, 0xcb, 0xa2, + 0xe7, 0x8c, 0x77, 0x0c, 0x74, 0x2f, 0xc2, 0x13, 0xb0, 0x93, 0x51, 0xa9, 0x4f, 0xae, 0x0a, 0xda, + 0x45, 0xcc, 0xfd, 0x43, 0x99, 0x36, 0x9a, 0x0d, 0x21, 0xe0, 0xeb, 0x30, 0x65, 0xd4, 0xa0, 0x27, + 0x37, 0x3b, 0xe4, 0xc1, 0xc5, 0xa1, 0x2a, 0xd1, 0x76, 0xc4, 0x7e, 0x64, 0x0e, 0x5a, 0xa6, 0x50, + 0x24, 0xd5, 0x2c, 0xcc, 0x6d, 0xe5, 0x37, 0xea, 0xbd, 0x09, 0x34, 0xed, 0x24, 0x06, 0xa1, 0x22, + }; + + static const uint8_t dnskey_blob[] = { + 0x03, 0x01, 0x00, 0x01, 0xc3, 0x7f, 0x1d, 0xd1, 0x1c, 0x97, 0xb1, 0x13, 0x34, 0x3a, 0x9a, 0xea, + 0xee, 0xd9, 0x5a, 0x11, 0x1b, 0x17, 0xc7, 0xe3, 0xd4, 0xda, 0x20, 0xbc, 0x5d, 0xba, 0x74, 0xe3, + 0x37, 0x99, 0xec, 0x25, 0xce, 0x93, 0x7f, 0xbd, 0x22, 0x73, 0x7e, 0x14, 0x71, 0xe0, 0x60, 0x07, + 0xd4, 0x39, 0x8b, 0x5e, 0xe9, 0xba, 0x25, 0xe8, 0x49, 0xe9, 0x34, 0xef, 0xfe, 0x04, 0x5c, 0xa5, + 0x27, 0xcd, 0xa9, 0xda, 0x70, 0x05, 0x21, 0xab, 0x15, 0x82, 0x24, 0xc3, 0x94, 0xf5, 0xd7, 0xb7, + 0xc4, 0x66, 0xcb, 0x32, 0x6e, 0x60, 0x2b, 0x55, 0x59, 0x28, 0x89, 0x8a, 0x72, 0xde, 0x88, 0x56, + 0x27, 0x95, 0xd9, 0xac, 0x88, 0x4f, 0x65, 0x2b, 0x68, 0xfc, 0xe6, 0x41, 0xc1, 0x1b, 0xef, 0x4e, + 0xd6, 0xc2, 0x0f, 0x64, 0x88, 0x95, 0x5e, 0xdd, 0x3a, 0x02, 0x07, 0x50, 0xa9, 0xda, 0xa4, 0x49, + 0x74, 0x62, 0xfe, 0xd7, + }; + + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *nsec = NULL, *rrsig = NULL, *dnskey = NULL; + _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL; + DnssecResult result; + + nsec = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC, "nasa.gov"); + assert_se(nsec); + + nsec->nsec.next_domain_name = strdup("3D-Printing.nasa.gov"); + assert_se(nsec->nsec.next_domain_name); + + nsec->nsec.types = bitmap_new(); + assert_se(nsec->nsec.types); + assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_A) >= 0); + assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_NS) >= 0); + assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_SOA) >= 0); + assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_MX) >= 0); + assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_TXT) >= 0); + assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_RRSIG) >= 0); + assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_NSEC) >= 0); + assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_DNSKEY) >= 0); + assert_se(bitmap_set(nsec->nsec.types, 65534) >= 0); + + log_info("NSEC: %s", strna(dns_resource_record_to_string(nsec))); + + rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV."); + assert_se(rrsig); + + rrsig->rrsig.type_covered = DNS_TYPE_NSEC; + rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_RSASHA256; + rrsig->rrsig.labels = 2; + rrsig->rrsig.original_ttl = 300; + rrsig->rrsig.expiration = 0x5689002f; + rrsig->rrsig.inception = 0x56617230; + rrsig->rrsig.key_tag = 30390; + rrsig->rrsig.signer = strdup("Nasa.Gov."); + assert_se(rrsig->rrsig.signer); + rrsig->rrsig.signature_size = sizeof(signature_blob); + rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size); + assert_se(rrsig->rrsig.signature); + + log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig))); + + dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV"); + assert_se(dnskey); + + dnskey->dnskey.flags = 256; + dnskey->dnskey.protocol = 3; + dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256; + dnskey->dnskey.key_size = sizeof(dnskey_blob); + dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob)); + assert_se(dnskey->dnskey.key); + + log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey))); + log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false)); + + assert_se(dnssec_key_match_rrsig(nsec->key, rrsig) > 0); + assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0); + + answer = dns_answer_new(1); + assert_se(answer); + assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED) >= 0); + + /* Validate the RR as it if was 2015-12-11 today */ + assert_se(dnssec_verify_rrset(answer, nsec->key, rrsig, dnskey, 1449849318*USEC_PER_SEC, &result) >= 0); + assert_se(result == DNSSEC_VALIDATED); +} + +static void test_dnssec_nsec3_hash(void) { + static const uint8_t salt[] = { 0xB0, 0x1D, 0xFA, 0xCE }; + static const uint8_t next_hashed_name[] = { 0x84, 0x10, 0x26, 0x53, 0xc9, 0xfa, 0x4d, 0x85, 0x6c, 0x97, 0x82, 0xe2, 0x8f, 0xdf, 0x2d, 0x5e, 0x87, 0x69, 0xc4, 0x52 }; + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; + uint8_t h[DNSSEC_HASH_SIZE_MAX]; + _cleanup_free_ char *b = NULL; + int k; + + /* The NSEC3 RR for eurid.eu on 2015-12-14. */ + rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC3, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM.eurid.eu."); + assert_se(rr); + + rr->nsec3.algorithm = DNSSEC_DIGEST_SHA1; + rr->nsec3.flags = 1; + rr->nsec3.iterations = 1; + rr->nsec3.salt = memdup(salt, sizeof(salt)); + assert_se(rr->nsec3.salt); + rr->nsec3.salt_size = sizeof(salt); + rr->nsec3.next_hashed_name = memdup(next_hashed_name, sizeof(next_hashed_name)); + assert_se(rr->nsec3.next_hashed_name); + rr->nsec3.next_hashed_name_size = sizeof(next_hashed_name); + + log_info("NSEC3: %s", strna(dns_resource_record_to_string(rr))); + + k = dnssec_nsec3_hash(rr, "eurid.eu", &h); + assert_se(k >= 0); + + b = base32hexmem(h, k, false); + assert_se(b); + assert_se(strcasecmp(b, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM") == 0); +} + +#endif + +int main(int argc, char *argv[]) { + + test_dnssec_canonicalize(); + +#if HAVE_GCRYPT + test_dnssec_verify_dns_key(); + test_dnssec_verify_rfc8080_ed25519_example1(); + test_dnssec_verify_rfc8080_ed25519_example2(); + test_dnssec_verify_rrset(); + test_dnssec_verify_rrset2(); + test_dnssec_nsec3_hash(); +#endif + + return 0; +} diff --git a/src/resolve/test-resolve-tables.c b/src/resolve/test-resolve-tables.c new file mode 100644 index 00000000..2230a66e --- /dev/null +++ b/src/resolve/test-resolve-tables.c @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "dns-type.h" +#include "resolved-dns-dnssec.h" +#include "resolved-dns-packet.h" +#include "test-tables.h" + +int main(int argc, char **argv) { + uint16_t i; + + test_table(dns_protocol, DNS_PROTOCOL); + test_table(dnssec_result, DNSSEC_RESULT); + test_table(dnssec_verdict, DNSSEC_VERDICT); + + test_table_sparse(dns_rcode, DNS_RCODE); + test_table_sparse(dns_type, DNS_TYPE); + + log_info("/* DNS_TYPE */"); + for (i = 0; i < _DNS_TYPE_MAX; i++) { + const char *s; + + s = dns_type_to_string(i); + assert_se(s == NULL || strlen(s) < _DNS_TYPE_STRING_MAX); + + if (s) + log_info("%-*s %s%s%s%s%s%s%s%s%s", + (int) _DNS_TYPE_STRING_MAX - 1, s, + dns_type_is_pseudo(i) ? "pseudo " : "", + dns_type_is_valid_query(i) ? "valid_query " : "", + dns_type_is_valid_rr(i) ? "is_valid_rr " : "", + dns_type_may_redirect(i) ? "may_redirect " : "", + dns_type_is_dnssec(i) ? "dnssec " : "", + dns_type_is_obsolete(i) ? "obsolete " : "", + dns_type_may_wildcard(i) ? "wildcard " : "", + dns_type_apex_only(i) ? "apex_only " : "", + dns_type_needs_authentication(i) ? "needs_authentication" : ""); + } + + log_info("/* DNS_CLASS */"); + for (i = 0; i < _DNS_CLASS_MAX; i++) { + const char *s; + + s = dns_class_to_string(i); + assert_se(s == NULL || strlen(s) < _DNS_CLASS_STRING_MAX); + + if (s) + log_info("%-*s %s%s", + (int) _DNS_CLASS_STRING_MAX - 1, s, + dns_class_is_pseudo(i) ? "is_pseudo " : "", + dns_class_is_valid_rr(i) ? "is_valid_rr " : ""); + } + + return EXIT_SUCCESS; +} diff --git a/src/resolve/test-resolved-etc-hosts.c b/src/resolve/test-resolved-etc-hosts.c new file mode 100644 index 00000000..ca359006 --- /dev/null +++ b/src/resolve/test-resolved-etc-hosts.c @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "log.h" +#include "resolved-etc-hosts.h" +#include "strv.h" +#include "tests.h" +#include "tmpfile-util.h" + +static void test_parse_etc_hosts_system(void) { + _cleanup_fclose_ FILE *f = NULL; + + log_info("/* %s */", __func__); + + f = fopen("/etc/hosts", "re"); + if (!f) { + assert_se(errno == ENOENT); + return; + } + + _cleanup_(etc_hosts_free) EtcHosts hosts = {}; + assert_se(etc_hosts_parse(&hosts, f) == 0); +} + +#define address_equal_4(_addr, _address) \ + ((_addr)->family == AF_INET && \ + !memcmp(&(_addr)->address.in, &(struct in_addr) { .s_addr = (_address) }, 4)) + +#define address_equal_6(_addr, ...) \ + ((_addr)->family == AF_INET6 && \ + !memcmp(&(_addr)->address.in6, &(struct in6_addr) { .s6_addr = __VA_ARGS__}, 16) ) + +static void test_parse_etc_hosts(void) { + _cleanup_(unlink_tempfilep) char + t[] = "/tmp/test-resolved-etc-hosts.XXXXXX"; + + log_info("/* %s */", __func__); + + int fd; + _cleanup_fclose_ FILE *f; + const char *s; + + fd = mkostemp_safe(t); + assert_se(fd >= 0); + + f = fdopen(fd, "r+"); + assert_se(f); + fputs("1.2.3.4 some.where\n" + "1.2.3.5 some.where\n" + "1.2.3.6 dash dash-dash.where-dash\n" + "1.2.3.7 bad-dash- -bad-dash -bad-dash.bad-\n" + "1.2.3.8\n" + "1.2.3.9 before.comment # within.comment\n" + "1.2.3.10 before.comment#within.comment2\n" + "1.2.3.11 before.comment# within.comment3\n" + "1.2.3.12 before.comment#\n" + "1.2.3 short.address\n" + "1.2.3.4.5 long.address\n" + "1::2::3 multi.colon\n" + + "::0 some.where some.other\n" + "0.0.0.0 black.listed\n" + "::5\t\t\t \tsome.where\tsome.other foobar.foo.foo\t\t\t\n" + " \n", f); + assert_se(fflush_and_check(f) >= 0); + rewind(f); + + _cleanup_(etc_hosts_free) EtcHosts hosts = {}; + assert_se(etc_hosts_parse(&hosts, f) == 0); + + EtcHostsItemByName *bn; + assert_se(bn = hashmap_get(hosts.by_name, "some.where")); + assert_se(bn->n_addresses == 3); + assert_se(bn->n_allocated >= 3); + assert_se(address_equal_4(bn->addresses[0], inet_addr("1.2.3.4"))); + assert_se(address_equal_4(bn->addresses[1], inet_addr("1.2.3.5"))); + assert_se(address_equal_6(bn->addresses[2], {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5})); + + assert_se(bn = hashmap_get(hosts.by_name, "dash")); + assert_se(bn->n_addresses == 1); + assert_se(bn->n_allocated >= 1); + assert_se(address_equal_4(bn->addresses[0], inet_addr("1.2.3.6"))); + + assert_se(bn = hashmap_get(hosts.by_name, "dash-dash.where-dash")); + assert_se(bn->n_addresses == 1); + assert_se(bn->n_allocated >= 1); + assert_se(address_equal_4(bn->addresses[0], inet_addr("1.2.3.6"))); + + /* See https://tools.ietf.org/html/rfc1035#section-2.3.1 */ + FOREACH_STRING(s, "bad-dash-", "-bad-dash", "-bad-dash.bad-") + assert_se(!hashmap_get(hosts.by_name, s)); + + assert_se(bn = hashmap_get(hosts.by_name, "before.comment")); + assert_se(bn->n_addresses == 4); + assert_se(bn->n_allocated >= 4); + assert_se(address_equal_4(bn->addresses[0], inet_addr("1.2.3.9"))); + assert_se(address_equal_4(bn->addresses[1], inet_addr("1.2.3.10"))); + assert_se(address_equal_4(bn->addresses[2], inet_addr("1.2.3.11"))); + assert_se(address_equal_4(bn->addresses[3], inet_addr("1.2.3.12"))); + + assert(!hashmap_get(hosts.by_name, "within.comment")); + assert(!hashmap_get(hosts.by_name, "within.comment2")); + assert(!hashmap_get(hosts.by_name, "within.comment3")); + assert(!hashmap_get(hosts.by_name, "#")); + + assert(!hashmap_get(hosts.by_name, "short.address")); + assert(!hashmap_get(hosts.by_name, "long.address")); + assert(!hashmap_get(hosts.by_name, "multi.colon")); + assert_se(!set_contains(hosts.no_address, "short.address")); + assert_se(!set_contains(hosts.no_address, "long.address")); + assert_se(!set_contains(hosts.no_address, "multi.colon")); + + assert_se(bn = hashmap_get(hosts.by_name, "some.other")); + assert_se(bn->n_addresses == 1); + assert_se(bn->n_allocated >= 1); + assert_se(address_equal_6(bn->addresses[0], {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5})); + + assert_se( set_contains(hosts.no_address, "some.where")); + assert_se( set_contains(hosts.no_address, "some.other")); + assert_se( set_contains(hosts.no_address, "black.listed")); + assert_se(!set_contains(hosts.no_address, "foobar.foo.foo")); +} + +static void test_parse_file(const char *fname) { + _cleanup_(etc_hosts_free) EtcHosts hosts = {}; + _cleanup_fclose_ FILE *f; + + log_info("/* %s(\"%s\") */", __func__, fname); + + assert_se(f = fopen(fname, "re")); + assert_se(etc_hosts_parse(&hosts, f) == 0); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + if (argc == 1) { + test_parse_etc_hosts_system(); + test_parse_etc_hosts(); + } else + test_parse_file(argv[1]); + + return 0; +} diff --git a/src/resolve/test-resolved-packet.c b/src/resolve/test-resolved-packet.c new file mode 100644 index 00000000..c9a511be --- /dev/null +++ b/src/resolve/test-resolved-packet.c @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "log.h" +#include "resolved-dns-packet.h" +#include "tests.h" + +static void test_dns_packet_new(void) { + size_t i; + _cleanup_(dns_packet_unrefp) DnsPacket *p2 = NULL; + + for (i = 0; i <= DNS_PACKET_SIZE_MAX; i++) { + _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; + + assert_se(dns_packet_new(&p, DNS_PROTOCOL_DNS, i, DNS_PACKET_SIZE_MAX) == 0); + + log_debug("dns_packet_new: %zu → %zu", i, p->allocated); + assert_se(p->allocated >= MIN(DNS_PACKET_SIZE_MAX, i)); + + if (i > DNS_PACKET_SIZE_START + 10 && i < DNS_PACKET_SIZE_MAX - 10) + i = MIN(i * 2, DNS_PACKET_SIZE_MAX - 10); + } + + assert_se(dns_packet_new(&p2, DNS_PROTOCOL_DNS, DNS_PACKET_SIZE_MAX + 1, DNS_PACKET_SIZE_MAX) == -EFBIG); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_dns_packet_new(); + + return 0; +} diff --git a/src/rfkill/rfkill.c b/src/rfkill/rfkill.c new file mode 100644 index 00000000..50198281 --- /dev/null +++ b/src/rfkill/rfkill.c @@ -0,0 +1,377 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-device.h" + +#include "alloc-util.h" +#include "device-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "io-util.h" +#include "list.h" +#include "main-func.h" +#include "mkdir.h" +#include "parse-util.h" +#include "reboot-util.h" +#include "string-table.h" +#include "string-util.h" +#include "udev-util.h" +#include "util.h" + +/* Note that any write is delayed until exit and the rfkill state will not be + * stored for rfkill indices that disappear after a change. */ +#define EXIT_USEC (5 * USEC_PER_SEC) + +typedef struct write_queue_item { + LIST_FIELDS(struct write_queue_item, queue); + int rfkill_idx; + char *file; + int state; +} write_queue_item; + +typedef struct Context { + LIST_HEAD(write_queue_item, write_queue); + int rfkill_fd; +} Context; + +static struct write_queue_item* write_queue_item_free(struct write_queue_item *item) { + if (!item) + return NULL; + + free(item->file); + return mfree(item); +} + +static const char* const rfkill_type_table[NUM_RFKILL_TYPES] = { + [RFKILL_TYPE_ALL] = "all", + [RFKILL_TYPE_WLAN] = "wlan", + [RFKILL_TYPE_BLUETOOTH] = "bluetooth", + [RFKILL_TYPE_UWB] = "uwb", + [RFKILL_TYPE_WIMAX] = "wimax", + [RFKILL_TYPE_WWAN] = "wwan", + [RFKILL_TYPE_GPS] = "gps", + [RFKILL_TYPE_FM] = "fm", + [RFKILL_TYPE_NFC] = "nfc", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(rfkill_type, int); + +static int find_device( + const struct rfkill_event *event, + sd_device **ret) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + _cleanup_free_ char *sysname = NULL; + const char *name; + int r; + + assert(event); + assert(ret); + + if (asprintf(&sysname, "rfkill%i", event->idx) < 0) + return log_oom(); + + r = sd_device_new_from_subsystem_sysname(&device, "rfkill", sysname); + if (r < 0) + return log_full_errno(IN_SET(r, -ENOENT, -ENXIO, -ENODEV) ? LOG_DEBUG : LOG_ERR, r, + "Failed to open device '%s': %m", sysname); + + r = sd_device_get_sysattr_value(device, "name", &name); + if (r < 0) + return log_device_debug_errno(device, r, "Device has no name, ignoring: %m"); + + log_device_debug(device, "Operating on rfkill device '%s'.", name); + + *ret = TAKE_PTR(device); + return 0; +} + +static int determine_state_file( + const struct rfkill_event *event, + char **ret) { + + _cleanup_(sd_device_unrefp) sd_device *d = NULL, *device = NULL; + const char *path_id, *type; + char *state_file; + int r; + + assert(event); + assert(ret); + + r = find_device(event, &d); + if (r < 0) + return r; + + r = device_wait_for_initialization(d, "rfkill", USEC_INFINITY, &device); + if (r < 0) + return r; + + assert_se(type = rfkill_type_to_string(event->type)); + + if (sd_device_get_property_value(device, "ID_PATH", &path_id) >= 0) { + _cleanup_free_ char *escaped_path_id = NULL; + + escaped_path_id = cescape(path_id); + if (!escaped_path_id) + return log_oom(); + + state_file = strjoin("/var/lib/systemd/rfkill/", escaped_path_id, ":", type); + } else + state_file = strjoin("/var/lib/systemd/rfkill/", type); + + if (!state_file) + return log_oom(); + + *ret = state_file; + return 0; +} + +static int load_state(Context *c, const struct rfkill_event *event) { + _cleanup_free_ char *state_file = NULL, *value = NULL; + struct rfkill_event we; + ssize_t l; + int b, r; + + assert(c); + assert(c->rfkill_fd >= 0); + assert(event); + + if (shall_restore_state() == 0) + return 0; + + r = determine_state_file(event, &state_file); + if (r < 0) + return r; + + r = read_one_line_file(state_file, &value); + if (IN_SET(r, -ENOENT, 0)) { + /* No state file or it's truncated? Then save the current state */ + + r = write_string_file(state_file, one_zero(event->soft), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MKDIR_0755); + if (r < 0) + return log_error_errno(r, "Failed to write state file %s: %m", state_file); + + log_debug("Saved state '%s' to %s.", one_zero(event->soft), state_file); + return 0; + } + if (r < 0) + return log_error_errno(r, "Failed to read state file %s: %m", state_file); + + b = parse_boolean(value); + if (b < 0) + return log_error_errno(b, "Failed to parse state file %s: %m", state_file); + + we = (struct rfkill_event) { + .op = RFKILL_OP_CHANGE, + .idx = event->idx, + .soft = b, + }; + + l = write(c->rfkill_fd, &we, sizeof(we)); + if (l < 0) + return log_error_errno(errno, "Failed to restore rfkill state for %i: %m", event->idx); + if (l != sizeof(we)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Couldn't write rfkill event structure, too short."); + + log_debug("Loaded state '%s' from %s.", one_zero(b), state_file); + return 0; +} + +static void save_state_queue_remove(Context *c, int idx, const char *state_file) { + struct write_queue_item *item, *tmp; + + assert(c); + + LIST_FOREACH_SAFE(queue, item, tmp, c->write_queue) { + if ((state_file && streq(item->file, state_file)) || idx == item->rfkill_idx) { + log_debug("Canceled previous save state of '%s' to %s.", one_zero(item->state), item->file); + LIST_REMOVE(queue, c->write_queue, item); + write_queue_item_free(item); + } + } +} + +static int save_state_queue(Context *c, const struct rfkill_event *event) { + _cleanup_free_ char *state_file = NULL; + struct write_queue_item *item; + int r; + + assert(c); + assert(c->rfkill_fd >= 0); + assert(event); + + r = determine_state_file(event, &state_file); + if (r < 0) + return r; + + save_state_queue_remove(c, event->idx, state_file); + + item = new0(struct write_queue_item, 1); + if (!item) + return -ENOMEM; + + item->file = TAKE_PTR(state_file); + item->rfkill_idx = event->idx; + item->state = event->soft; + + LIST_APPEND(queue, c->write_queue, item); + + return 0; +} + +static int save_state_cancel(Context *c, const struct rfkill_event *event) { + _cleanup_free_ char *state_file = NULL; + int r; + + assert(c); + assert(c->rfkill_fd >= 0); + assert(event); + + r = determine_state_file(event, &state_file); + save_state_queue_remove(c, event->idx, state_file); + if (r < 0) + return r; + + return 0; +} + +static int save_state_write_one(struct write_queue_item *item) { + int r; + + r = write_string_file(item->file, one_zero(item->state), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_MKDIR_0755); + if (r < 0) + return log_error_errno(r, "Failed to write state file %s: %m", item->file); + + log_debug("Saved state '%s' to %s.", one_zero(item->state), item->file); + return 0; +} + +static void context_save_and_clear(Context *c) { + struct write_queue_item *i; + + assert(c); + + while ((i = c->write_queue)) { + LIST_REMOVE(queue, c->write_queue, i); + (void) save_state_write_one(i); + write_queue_item_free(i); + } + + safe_close(c->rfkill_fd); +} + +static int run(int argc, char *argv[]) { + _cleanup_(context_save_and_clear) Context c = { .rfkill_fd = -1 }; + bool ready = false; + int r, n; + + if (argc > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires no arguments."); + + log_setup_service(); + + umask(0022); + + n = sd_listen_fds(false); + if (n < 0) + return log_error_errno(n, "Failed to determine whether we got any file descriptors passed: %m"); + if (n > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Got too many file descriptors."); + + if (n == 0) { + c.rfkill_fd = open("/dev/rfkill", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); + if (c.rfkill_fd < 0) { + if (errno == ENOENT) { + log_debug_errno(errno, "Missing rfkill subsystem, or no device present, exiting."); + return 0; + } + + return log_error_errno(errno, "Failed to open /dev/rfkill: %m"); + } + } else { + c.rfkill_fd = SD_LISTEN_FDS_START; + + r = fd_nonblock(c.rfkill_fd, 1); + if (r < 0) + return log_error_errno(r, "Failed to make /dev/rfkill socket non-blocking: %m"); + } + + for (;;) { + struct rfkill_event event; + const char *type; + ssize_t l; + + l = read(c.rfkill_fd, &event, sizeof(event)); + if (l < 0) { + if (errno == EAGAIN) { + + if (!ready) { + /* Notify manager that we are + * now finished with + * processing whatever was + * queued */ + (void) sd_notify(false, "READY=1"); + ready = true; + } + + /* Hang around for a bit, maybe there's more coming */ + + r = fd_wait_for_event(c.rfkill_fd, POLLIN, EXIT_USEC); + if (r == -EINTR) + continue; + if (r < 0) + return log_error_errno(r, "Failed to poll() on device: %m"); + if (r > 0) + continue; + + log_debug("All events read and idle, exiting."); + break; + } + + log_error_errno(errno, "Failed to read from /dev/rfkill: %m"); + } + + if (l != RFKILL_EVENT_SIZE_V1) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Read event structure of invalid size."); + + type = rfkill_type_to_string(event.type); + if (!type) { + log_debug("An rfkill device of unknown type %i discovered, ignoring.", event.type); + continue; + } + + switch (event.op) { + + case RFKILL_OP_ADD: + log_debug("A new rfkill device has been added with index %i and type %s.", event.idx, type); + (void) load_state(&c, &event); + break; + + case RFKILL_OP_DEL: + log_debug("An rfkill device has been removed with index %i and type %s", event.idx, type); + (void) save_state_cancel(&c, &event); + break; + + case RFKILL_OP_CHANGE: + log_debug("An rfkill device has changed state with index %i and type %s", event.idx, type); + (void) save_state_queue(&c, &event); + break; + + default: + log_debug("Unknown event %i from /dev/rfkill for index %i and type %s, ignoring.", event.op, event.idx, type); + break; + } + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/run-generator/run-generator.c b/src/run-generator/run-generator.c new file mode 100644 index 00000000..7d6c1109 --- /dev/null +++ b/src/run-generator/run-generator.c @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "generator.h" +#include "mkdir.h" +#include "proc-cmdline.h" +#include "specifier.h" +#include "strv.h" + +static const char *arg_dest = NULL; +static char **arg_commands = NULL; +static char *arg_success_action = NULL; +static char *arg_failure_action = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_commands, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_success_action, freep); +STATIC_DESTRUCTOR_REGISTER(arg_failure_action, freep); + +static int parse(const char *key, const char *value, void *data) { + int r; + + if (proc_cmdline_key_streq(key, "systemd.run")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = strv_extend(&arg_commands, value); + if (r < 0) + return log_oom(); + + } else if (proc_cmdline_key_streq(key, "systemd.run_success_action")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (free_and_strdup(&arg_success_action, value) < 0) + return log_oom(); + + } else if (proc_cmdline_key_streq(key, "systemd.run_failure_action")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + if (free_and_strdup(&arg_failure_action, value) < 0) + return log_oom(); + } + + return 0; +} + +static int generate(void) { + _cleanup_fclose_ FILE *f = NULL; + const char *p; + char **c; + int r; + + if (strv_isempty(arg_commands) && !arg_success_action) + return 0; + + p = strjoina(arg_dest, "/kernel-command-line.service"); + f = fopen(p, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", p); + + fputs("# Automatically generated by systemd-run-generator\n\n" + "[Unit]\n" + "Description=Command from Kernel Command Line\n" + "Documentation=man:systemd-run-generator(8)\n" + "SourcePath=/proc/cmdline\n", f); + + if (!streq_ptr(arg_success_action, "none")) + fprintf(f, "SuccessAction=%s\n", + arg_success_action ?: "exit"); + + if (!streq_ptr(arg_failure_action, "none")) + fprintf(f, "FailureAction=%s\n", + arg_failure_action ?: "exit"); + + fputs("\n" + "[Service]\n" + "Type=oneshot\n" + "StandardOutput=journal+console\n", f); + + STRV_FOREACH(c, arg_commands) { + _cleanup_free_ char *a = NULL; + + a = specifier_escape(*c); + if (!a) + return log_oom(); + + fprintf(f, "ExecStart=%s\n", a); + } + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", p); + + /* Let's create a a target we can link "default.target" to */ + p = strjoina(arg_dest, "/kernel-command-line.target"); + r = write_string_file( + p, + "# Automatically generated by systemd-run-generator\n\n" + "[Unit]\n" + "Description=Command from Kernel Command Line\n" + "Documentation=man:systemd-run-generator(8)\n" + "SourcePath=/proc/cmdline\n" + "Requires=kernel-command-line.service\n" + "After=kernel-command-line.service\n", + WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_NOFOLLOW); + if (r < 0) + return log_error_errno(r, "Failed to create unit file %s: %m", p); + + /* And now redirect default.target to our new target */ + p = strjoina(arg_dest, "/default.target"); + if (symlink("kernel-command-line.target", p) < 0) + return log_error_errno(errno, "Failed to link unit file kernel-command-line.target → %s: %m", p); + + return 0; +} + +static int run(const char *dest, const char *dest_early, const char *dest_late) { + int r; + + assert_se(arg_dest = dest); + + r = proc_cmdline_parse(parse, NULL, PROC_CMDLINE_RD_STRICT|PROC_CMDLINE_STRIP_RD_PREFIX); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + return generate(); +} + +DEFINE_MAIN_GENERATOR_FUNCTION(run); diff --git a/src/run/run.c b/src/run/run.c new file mode 100644 index 00000000..2b806fb6 --- /dev/null +++ b/src/run/run.c @@ -0,0 +1,1734 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-event.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-unit-util.h" +#include "bus-util.h" +#include "bus-wait-for-jobs.h" +#include "calendarspec.h" +#include "env-util.h" +#include "exit-status.h" +#include "fd-util.h" +#include "format-util.h" +#include "main-func.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "process-util.h" +#include "ptyfwd.h" +#include "signal-util.h" +#include "spawn-polkit-agent.h" +#include "strv.h" +#include "terminal-util.h" +#include "unit-def.h" +#include "unit-name.h" +#include "user-util.h" + +static bool arg_ask_password = true; +static bool arg_scope = false; +static bool arg_remain_after_exit = false; +static bool arg_no_block = false; +static bool arg_wait = false; +static const char *arg_unit = NULL; +static const char *arg_description = NULL; +static const char *arg_slice = NULL; +static bool arg_send_sighup = false; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static const char *arg_host = NULL; +static bool arg_user = false; +static const char *arg_service_type = NULL; +static const char *arg_exec_user = NULL; +static const char *arg_exec_group = NULL; +static int arg_nice = 0; +static bool arg_nice_set = false; +static char **arg_environment = NULL; +static char **arg_property = NULL; +static enum { + ARG_STDIO_NONE, /* The default, as it is for normal services, stdin connected to /dev/null, and stdout+stderr to the journal */ + ARG_STDIO_PTY, /* Interactive behaviour, requested by --pty: we allocate a pty and connect it to the TTY we are invoked from */ + ARG_STDIO_DIRECT, /* Directly pass our stdin/stdout/stderr to the activated service, useful for usage in shell pipelines, requested by --pipe */ + ARG_STDIO_AUTO, /* If --pipe and --pty are used together we use --pty when invoked on a TTY, and --pipe otherwise */ +} arg_stdio = ARG_STDIO_NONE; +static char **arg_path_property = NULL; +static char **arg_socket_property = NULL; +static char **arg_timer_property = NULL; +static bool arg_with_timer = false; +static bool arg_quiet = false; +static bool arg_aggressive_gc = false; +static char *arg_working_directory = NULL; +static bool arg_shell = false; +static char **arg_cmdline = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_environment, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_path_property, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_socket_property, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_timer_property, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_working_directory, freep); +STATIC_DESTRUCTOR_REGISTER(arg_cmdline, strv_freep); + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-run", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND [ARGUMENTS...]\n" + "\n%sRun the specified command in a transient scope or service.%s\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --no-ask-password Do not prompt for password\n" + " --user Run as user unit\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " --scope Run this as scope rather than service\n" + " -u --unit=UNIT Run under the specified unit name\n" + " -p --property=NAME=VALUE Set service or scope unit property\n" + " --description=TEXT Description for unit\n" + " --slice=SLICE Run in the specified slice\n" + " --no-block Do not wait until operation finished\n" + " -r --remain-after-exit Leave service around until explicitly stopped\n" + " --wait Wait until service stopped again\n" + " --send-sighup Send SIGHUP when terminating\n" + " --service-type=TYPE Service type\n" + " --uid=USER Run as system user\n" + " --gid=GROUP Run as system group\n" + " --nice=NICE Nice level\n" + " --working-directory=PATH Set working directory\n" + " -d --same-dir Inherit working directory from caller\n" + " -E --setenv=NAME=VALUE Set environment\n" + " -t --pty Run service on pseudo TTY as STDIN/STDOUT/\n" + " STDERR\n" + " -P --pipe Pass STDIN/STDOUT/STDERR directly to service\n" + " -q --quiet Suppress information messages during runtime\n" + " -G --collect Unload unit after it ran, even when failed\n" + " -S --shell Invoke a $SHELL interactively\n\n" + "Path options:\n" + " --path-property=NAME=VALUE Set path unit property\n\n" + "Socket options:\n" + " --socket-property=NAME=VALUE Set socket unit property\n\n" + "Timer options:\n" + " --on-active=SECONDS Run after SECONDS delay\n" + " --on-boot=SECONDS Run SECONDS after machine was booted up\n" + " --on-startup=SECONDS Run SECONDS after systemd activation\n" + " --on-unit-active=SECONDS Run SECONDS after the last activation\n" + " --on-unit-inactive=SECONDS Run SECONDS after the last deactivation\n" + " --on-calendar=SPEC Realtime timer\n" + " --on-timezone-change Run when the timezone changes\n" + " --on-clock-change Run when the realtime clock jumps\n" + " --timer-property=NAME=VALUE Set timer unit property\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +static int add_timer_property(const char *name, const char *val) { + char *p; + + assert(name); + assert(val); + + p = strjoin(name, "=", val); + if (!p) + return log_oom(); + + if (strv_consume(&arg_timer_property, p) < 0) + return log_oom(); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_USER, + ARG_SYSTEM, + ARG_SCOPE, + ARG_DESCRIPTION, + ARG_SLICE, + ARG_SEND_SIGHUP, + ARG_SERVICE_TYPE, + ARG_EXEC_USER, + ARG_EXEC_GROUP, + ARG_NICE, + ARG_ON_ACTIVE, + ARG_ON_BOOT, + ARG_ON_STARTUP, + ARG_ON_UNIT_ACTIVE, + ARG_ON_UNIT_INACTIVE, + ARG_ON_CALENDAR, + ARG_ON_TIMEZONE_CHANGE, + ARG_ON_CLOCK_CHANGE, + ARG_TIMER_PROPERTY, + ARG_PATH_PROPERTY, + ARG_SOCKET_PROPERTY, + ARG_NO_BLOCK, + ARG_NO_ASK_PASSWORD, + ARG_WAIT, + ARG_WORKING_DIRECTORY, + ARG_SHELL, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "user", no_argument, NULL, ARG_USER }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "scope", no_argument, NULL, ARG_SCOPE }, + { "unit", required_argument, NULL, 'u' }, + { "description", required_argument, NULL, ARG_DESCRIPTION }, + { "slice", required_argument, NULL, ARG_SLICE }, + { "remain-after-exit", no_argument, NULL, 'r' }, + { "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "service-type", required_argument, NULL, ARG_SERVICE_TYPE }, + { "wait", no_argument, NULL, ARG_WAIT }, + { "uid", required_argument, NULL, ARG_EXEC_USER }, + { "gid", required_argument, NULL, ARG_EXEC_GROUP }, + { "nice", required_argument, NULL, ARG_NICE }, + { "setenv", required_argument, NULL, 'E' }, + { "property", required_argument, NULL, 'p' }, + { "tty", no_argument, NULL, 't' }, /* deprecated alias */ + { "pty", no_argument, NULL, 't' }, + { "pipe", no_argument, NULL, 'P' }, + { "quiet", no_argument, NULL, 'q' }, + { "on-active", required_argument, NULL, ARG_ON_ACTIVE }, + { "on-boot", required_argument, NULL, ARG_ON_BOOT }, + { "on-startup", required_argument, NULL, ARG_ON_STARTUP }, + { "on-unit-active", required_argument, NULL, ARG_ON_UNIT_ACTIVE }, + { "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE }, + { "on-calendar", required_argument, NULL, ARG_ON_CALENDAR }, + { "on-timezone-change",no_argument, NULL, ARG_ON_TIMEZONE_CHANGE}, + { "on-clock-change", no_argument, NULL, ARG_ON_CLOCK_CHANGE }, + { "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY }, + { "path-property", required_argument, NULL, ARG_PATH_PROPERTY }, + { "socket-property", required_argument, NULL, ARG_SOCKET_PROPERTY }, + { "no-block", no_argument, NULL, ARG_NO_BLOCK }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "collect", no_argument, NULL, 'G' }, + { "working-directory", required_argument, NULL, ARG_WORKING_DIRECTORY }, + { "same-dir", no_argument, NULL, 'd' }, + { "shell", no_argument, NULL, 'S' }, + {}, + }; + + bool with_trigger = false; + int r, c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPqGdSu:", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + + case ARG_USER: + arg_user = true; + break; + + case ARG_SYSTEM: + arg_user = false; + break; + + case ARG_SCOPE: + arg_scope = true; + break; + + case 'u': + arg_unit = optarg; + break; + + case ARG_DESCRIPTION: + arg_description = optarg; + break; + + case ARG_SLICE: + arg_slice = optarg; + break; + + case ARG_SEND_SIGHUP: + arg_send_sighup = true; + break; + + case 'r': + arg_remain_after_exit = true; + break; + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case ARG_SERVICE_TYPE: + arg_service_type = optarg; + break; + + case ARG_EXEC_USER: + arg_exec_user = optarg; + break; + + case ARG_EXEC_GROUP: + arg_exec_group = optarg; + break; + + case ARG_NICE: + r = parse_nice(optarg, &arg_nice); + if (r < 0) + return log_error_errno(r, "Failed to parse nice value: %s", optarg); + + arg_nice_set = true; + break; + + case 'E': + if (strv_extend(&arg_environment, optarg) < 0) + return log_oom(); + + break; + + case 'p': + if (strv_extend(&arg_property, optarg) < 0) + return log_oom(); + + break; + + case 't': /* --pty */ + if (IN_SET(arg_stdio, ARG_STDIO_DIRECT, ARG_STDIO_AUTO)) /* if --pipe is already used, upgrade to auto mode */ + arg_stdio = ARG_STDIO_AUTO; + else + arg_stdio = ARG_STDIO_PTY; + break; + + case 'P': /* --pipe */ + if (IN_SET(arg_stdio, ARG_STDIO_PTY, ARG_STDIO_AUTO)) /* If --pty is already used, upgrade to auto mode */ + arg_stdio = ARG_STDIO_AUTO; + else + arg_stdio = ARG_STDIO_DIRECT; + break; + + case 'q': + arg_quiet = true; + break; + + case ARG_ON_ACTIVE: + r = add_timer_property("OnActiveSec", optarg); + if (r < 0) + return r; + + arg_with_timer = true; + break; + + case ARG_ON_BOOT: + r = add_timer_property("OnBootSec", optarg); + if (r < 0) + return r; + + arg_with_timer = true; + break; + + case ARG_ON_STARTUP: + r = add_timer_property("OnStartupSec", optarg); + if (r < 0) + return r; + + arg_with_timer = true; + break; + + case ARG_ON_UNIT_ACTIVE: + r = add_timer_property("OnUnitActiveSec", optarg); + if (r < 0) + return r; + + arg_with_timer = true; + break; + + case ARG_ON_UNIT_INACTIVE: + r = add_timer_property("OnUnitInactiveSec", optarg); + if (r < 0) + return r; + + arg_with_timer = true; + break; + + case ARG_ON_CALENDAR: { + _cleanup_(calendar_spec_freep) CalendarSpec *cs = NULL; + + r = calendar_spec_from_string(optarg, &cs); + if (r < 0) + return log_error_errno(r, "Failed to parse calendar event specification: %m"); + + /* Let's make sure the given calendar event is not in the past */ + r = calendar_spec_next_usec(cs, now(CLOCK_REALTIME), NULL); + if (r == -ENOENT) + /* The calendar event is in the past — let's warn about this, but install it + * anyway as is. The service manager will trigger the service right away. + * Moreover, the server side might have a different clock or timezone than we + * do, hence it should decide when or whether to run something. */ + log_warning("Specified calendar expression is in the past, proceeding anyway."); + else if (r < 0) + return log_error_errno(r, "Failed to calculate next time calendar expression elapses: %m"); + + r = add_timer_property("OnCalendar", optarg); + if (r < 0) + return r; + + arg_with_timer = true; + break; + } + + case ARG_ON_TIMEZONE_CHANGE: + r = add_timer_property("OnTimezoneChange", "yes"); + if (r < 0) + return r; + + arg_with_timer = true; + break; + + case ARG_ON_CLOCK_CHANGE: + r = add_timer_property("OnClockChange", "yes"); + if (r < 0) + return r; + + arg_with_timer = true; + break; + + case ARG_TIMER_PROPERTY: + + if (strv_extend(&arg_timer_property, optarg) < 0) + return log_oom(); + + arg_with_timer = arg_with_timer || + STARTSWITH_SET(optarg, + "OnActiveSec=", + "OnBootSec=", + "OnStartupSec=", + "OnUnitActiveSec=", + "OnUnitInactiveSec=", + "OnCalendar="); + break; + + case ARG_PATH_PROPERTY: + + if (strv_extend(&arg_path_property, optarg) < 0) + return log_oom(); + + break; + + case ARG_SOCKET_PROPERTY: + + if (strv_extend(&arg_socket_property, optarg) < 0) + return log_oom(); + + break; + + case ARG_NO_BLOCK: + arg_no_block = true; + break; + + case ARG_WAIT: + arg_wait = true; + break; + + case ARG_WORKING_DIRECTORY: + r = parse_path_argument_and_warn(optarg, true, &arg_working_directory); + if (r < 0) + return r; + + break; + + case 'd': { + _cleanup_free_ char *p = NULL; + + r = safe_getcwd(&p); + if (r < 0) + return log_error_errno(r, "Failed to get current working directory: %m"); + + if (empty_or_root(p)) + arg_working_directory = mfree(arg_working_directory); + else + free_and_replace(arg_working_directory, p); + break; + } + + case 'G': + arg_aggressive_gc = true; + break; + + case 'S': + arg_shell = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + with_trigger = !!arg_path_property || !!arg_socket_property || arg_with_timer; + + /* currently, only single trigger (path, socket, timer) unit can be created simultaneously */ + if ((int) !!arg_path_property + (int) !!arg_socket_property + (int) arg_with_timer > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Only single trigger (path, socket, timer) unit can be created."); + + if (arg_shell) { + /* If --shell is imply --pty --pipe --same-dir --service-type=exec --wait --collect, unless otherwise + * specified. */ + + if (!arg_scope) { + if (arg_stdio == ARG_STDIO_NONE) + arg_stdio = ARG_STDIO_AUTO; + + if (!arg_working_directory) { + r = safe_getcwd(&arg_working_directory); + if (r < 0) + return log_error_errno(r, "Failed to get current working directory: %m"); + } + + if (!arg_service_type) { + arg_service_type = strdup("exec"); + if (!arg_service_type) + return log_oom(); + } + + arg_wait = true; + } + + arg_aggressive_gc = true; + } + + if (arg_stdio == ARG_STDIO_AUTO) { + /* If we both --pty and --pipe are specified we'll automatically pick --pty if we are connected fully + * to a TTY and pick direct fd passing otherwise. This way, we automatically adapt to usage in a shell + * pipeline, but we are neatly interactive with tty-level isolation otherwise. */ + arg_stdio = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) ? + ARG_STDIO_PTY : + ARG_STDIO_DIRECT; + } + + if (argc > optind) { + char **l; + + if (arg_shell) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "If --shell is used, no command line is expected."); + + l = strv_copy(argv + optind); + if (!l) + return log_oom(); + + strv_free_and_replace(arg_cmdline, l); + + } else if (arg_shell) { + _cleanup_free_ char *s = NULL; + char **l; + + r = get_shell(&s); + if (r < 0) + return log_error_errno(r, "Failed to determine shell: %m"); + + l = strv_new(s); + if (!l) + return log_oom(); + + strv_free_and_replace(arg_cmdline, l); + + } else if (!arg_unit || !with_trigger) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Command line to execute required."); + + if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Execution in user context is not supported on non-local systems."); + + if (arg_scope && arg_transport != BUS_TRANSPORT_LOCAL) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Scope execution is not supported on non-local systems."); + + if (arg_scope && (arg_remain_after_exit || arg_service_type)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--remain-after-exit and --service-type= are not supported in --scope mode."); + + if (arg_stdio != ARG_STDIO_NONE && (with_trigger || arg_scope)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--pty/--pipe is not compatible in timer or --scope mode."); + + if (arg_stdio != ARG_STDIO_NONE && arg_transport == BUS_TRANSPORT_REMOTE) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--pty/--pipe is only supported when connecting to the local system or containers."); + + if (arg_stdio != ARG_STDIO_NONE && arg_no_block) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--pty/--pipe is not compatible with --no-block."); + + if (arg_scope && with_trigger) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Path, socket or timer options are not supported in --scope mode."); + + if (arg_timer_property && !arg_with_timer) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--timer-property= has no effect without any other timer options."); + + if (arg_wait) { + if (arg_no_block) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--wait may not be combined with --no-block."); + + if (with_trigger) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--wait may not be combined with path, socket or timer operations."); + + if (arg_scope) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--wait may not be combined with --scope."); + } + + return 1; +} + +static int transient_unit_set_properties(sd_bus_message *m, UnitType t, char **properties) { + int r; + + r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description); + if (r < 0) + return bus_log_create_error(r); + + if (arg_aggressive_gc) { + r = sd_bus_message_append(m, "(sv)", "CollectMode", "s", "inactive-or-failed"); + if (r < 0) + return bus_log_create_error(r); + } + + r = bus_append_unit_property_assignment_many(m, t, properties); + if (r < 0) + return r; + + return 0; +} + +static int transient_cgroup_set_properties(sd_bus_message *m) { + int r; + assert(m); + + if (!isempty(arg_slice)) { + _cleanup_free_ char *slice = NULL; + + r = unit_name_mangle_with_suffix(arg_slice, "as slice", + arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, + ".slice", &slice); + if (r < 0) + return log_error_errno(r, "Failed to mangle name '%s': %m", arg_slice); + + r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice); + if (r < 0) + return bus_log_create_error(r); + } + + return 0; +} + +static int transient_kill_set_properties(sd_bus_message *m) { + int r; + + assert(m); + + if (arg_send_sighup) { + r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup); + if (r < 0) + return bus_log_create_error(r); + } + + return 0; +} + +static int transient_service_set_properties(sd_bus_message *m, const char *pty_path) { + bool send_term = false; + int r; + + assert(m); + + r = transient_unit_set_properties(m, UNIT_SERVICE, arg_property); + if (r < 0) + return r; + + r = transient_kill_set_properties(m); + if (r < 0) + return r; + + r = transient_cgroup_set_properties(m); + if (r < 0) + return r; + + if (arg_wait || arg_stdio != ARG_STDIO_NONE) { + r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1); + if (r < 0) + return bus_log_create_error(r); + } + + if (arg_remain_after_exit) { + r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit); + if (r < 0) + return bus_log_create_error(r); + } + + if (arg_service_type) { + r = sd_bus_message_append(m, "(sv)", "Type", "s", arg_service_type); + if (r < 0) + return bus_log_create_error(r); + } + + if (arg_exec_user) { + r = sd_bus_message_append(m, "(sv)", "User", "s", arg_exec_user); + if (r < 0) + return bus_log_create_error(r); + } + + if (arg_exec_group) { + r = sd_bus_message_append(m, "(sv)", "Group", "s", arg_exec_group); + if (r < 0) + return bus_log_create_error(r); + } + + if (arg_nice_set) { + r = sd_bus_message_append(m, "(sv)", "Nice", "i", arg_nice); + if (r < 0) + return bus_log_create_error(r); + } + + if (arg_working_directory) { + r = sd_bus_message_append(m, "(sv)", "WorkingDirectory", "s", arg_working_directory); + if (r < 0) + return bus_log_create_error(r); + } + + if (pty_path) { + r = sd_bus_message_append(m, + "(sv)(sv)(sv)(sv)", + "StandardInput", "s", "tty", + "StandardOutput", "s", "tty", + "StandardError", "s", "tty", + "TTYPath", "s", pty_path); + if (r < 0) + return bus_log_create_error(r); + + send_term = true; + + } else if (arg_stdio == ARG_STDIO_DIRECT) { + r = sd_bus_message_append(m, + "(sv)(sv)(sv)", + "StandardInputFileDescriptor", "h", STDIN_FILENO, + "StandardOutputFileDescriptor", "h", STDOUT_FILENO, + "StandardErrorFileDescriptor", "h", STDERR_FILENO); + if (r < 0) + return bus_log_create_error(r); + + send_term = isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO); + } + + if (send_term) { + const char *e; + + e = getenv("TERM"); + if (e) { + char *n; + + n = strjoina("TERM=", e); + r = sd_bus_message_append(m, + "(sv)", + "Environment", "as", 1, n); + if (r < 0) + return bus_log_create_error(r); + } + } + + if (!strv_isempty(arg_environment)) { + r = sd_bus_message_open_container(m, 'r', "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", "Environment"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', "as"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, arg_environment); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + } + + /* Exec container */ + if (!strv_isempty(arg_cmdline)) { + r = sd_bus_message_open_container(m, 'r', "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", "ExecStart"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', "a(sasb)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "(sasb)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'r', "sasb"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", arg_cmdline[0]); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, arg_cmdline); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "b", false); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + } + + return 0; +} + +static int transient_scope_set_properties(sd_bus_message *m) { + int r; + + assert(m); + + r = transient_unit_set_properties(m, UNIT_SCOPE, arg_property); + if (r < 0) + return r; + + r = transient_kill_set_properties(m); + if (r < 0) + return r; + + r = transient_cgroup_set_properties(m); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid_cached()); + if (r < 0) + return bus_log_create_error(r); + + return 0; +} + +static int transient_timer_set_properties(sd_bus_message *m) { + int r; + + assert(m); + + r = transient_unit_set_properties(m, UNIT_TIMER, arg_timer_property); + if (r < 0) + return r; + + /* Automatically clean up our transient timers */ + r = sd_bus_message_append(m, "(sv)", "RemainAfterElapse", "b", false); + if (r < 0) + return bus_log_create_error(r); + + return 0; +} + +static int make_unit_name(sd_bus *bus, UnitType t, char **ret) { + const char *unique, *id; + char *p; + int r; + + assert(bus); + assert(t >= 0); + assert(t < _UNIT_TYPE_MAX); + + r = sd_bus_get_unique_name(bus, &unique); + if (r < 0) { + sd_id128_t rnd; + + /* We couldn't get the unique name, which is a pretty + * common case if we are connected to systemd + * directly. In that case, just pick a random uuid as + * name */ + + r = sd_id128_randomize(&rnd); + if (r < 0) + return log_error_errno(r, "Failed to generate random run unit name: %m"); + + if (asprintf(ret, "run-r" SD_ID128_FORMAT_STR ".%s", SD_ID128_FORMAT_VAL(rnd), unit_type_to_string(t)) < 0) + return log_oom(); + + return 0; + } + + /* We managed to get the unique name, then let's use that to + * name our transient units. */ + + id = startswith(unique, ":1."); + if (!id) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unique name %s has unexpected format.", + unique); + + p = strjoin("run-u", id, ".", unit_type_to_string(t)); + if (!p) + return log_oom(); + + *ret = p; + return 0; +} + +typedef struct RunContext { + sd_bus *bus; + sd_event *event; + PTYForward *forward; + sd_bus_slot *match; + + /* The exit data of the unit */ + char *active_state; + uint64_t inactive_exit_usec; + uint64_t inactive_enter_usec; + char *result; + uint64_t cpu_usage_nsec; + uint64_t ip_ingress_bytes; + uint64_t ip_egress_bytes; + uint64_t io_read_bytes; + uint64_t io_write_bytes; + uint32_t exit_code; + uint32_t exit_status; +} RunContext; + +static void run_context_free(RunContext *c) { + assert(c); + + c->forward = pty_forward_free(c->forward); + c->match = sd_bus_slot_unref(c->match); + c->bus = sd_bus_unref(c->bus); + c->event = sd_event_unref(c->event); + + free(c->active_state); + free(c->result); +} + +static void run_context_check_done(RunContext *c) { + bool done; + + assert(c); + + if (c->match) + done = STRPTR_IN_SET(c->active_state, "inactive", "failed"); + else + done = true; + + if (c->forward && done) /* If the service is gone, it's time to drain the output */ + done = pty_forward_drain(c->forward); + + if (done) + sd_event_exit(c->event, EXIT_SUCCESS); +} + +static int run_context_update(RunContext *c, const char *path) { + + static const struct bus_properties_map map[] = { + { "ActiveState", "s", NULL, offsetof(RunContext, active_state) }, + { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_exit_usec) }, + { "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_enter_usec) }, + { "Result", "s", NULL, offsetof(RunContext, result) }, + { "ExecMainCode", "i", NULL, offsetof(RunContext, exit_code) }, + { "ExecMainStatus", "i", NULL, offsetof(RunContext, exit_status) }, + { "CPUUsageNSec", "t", NULL, offsetof(RunContext, cpu_usage_nsec) }, + { "IPIngressBytes", "t", NULL, offsetof(RunContext, ip_ingress_bytes) }, + { "IPEgressBytes", "t", NULL, offsetof(RunContext, ip_egress_bytes) }, + { "IOReadBytes", "t", NULL, offsetof(RunContext, io_read_bytes) }, + { "IOWriteBytes", "t", NULL, offsetof(RunContext, io_write_bytes) }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + r = bus_map_all_properties(c->bus, + "org.freedesktop.systemd1", + path, + map, + BUS_MAP_STRDUP, + &error, + NULL, + c); + if (r < 0) { + sd_event_exit(c->event, EXIT_FAILURE); + return log_error_errno(r, "Failed to query unit state: %s", bus_error_message(&error, r)); + } + + run_context_check_done(c); + return 0; +} + +static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + RunContext *c = userdata; + + assert(m); + assert(c); + + return run_context_update(c, sd_bus_message_get_path(m)); +} + +static int pty_forward_handler(PTYForward *f, int rcode, void *userdata) { + RunContext *c = userdata; + + assert(f); + + if (rcode < 0) { + sd_event_exit(c->event, EXIT_FAILURE); + return log_error_errno(rcode, "Error on PTY forwarding logic: %m"); + } + + run_context_check_done(c); + return 0; +} + +static int start_transient_service( + sd_bus *bus, + int *retval) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_free_ char *service = NULL, *pty_path = NULL; + _cleanup_close_ int master = -1; + int r; + + assert(bus); + assert(retval); + + if (arg_stdio == ARG_STDIO_PTY) { + + if (arg_transport == BUS_TRANSPORT_LOCAL) { + master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (master < 0) + return log_error_errno(errno, "Failed to acquire pseudo tty: %m"); + + r = ptsname_malloc(master, &pty_path); + if (r < 0) + return log_error_errno(r, "Failed to determine tty name: %m"); + + if (unlockpt(master) < 0) + return log_error_errno(errno, "Failed to unlock tty: %m"); + + } else if (arg_transport == BUS_TRANSPORT_MACHINE) { + _cleanup_(sd_bus_unrefp) sd_bus *system_bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *pty_reply = NULL; + const char *s; + + r = sd_bus_default_system(&system_bus); + if (r < 0) + return log_error_errno(r, "Failed to connect to system bus: %m"); + + r = sd_bus_call_method(system_bus, + "org.freedesktop.machine1", + "/org/freedesktop/machine1", + "org.freedesktop.machine1.Manager", + "OpenMachinePTY", + &error, + &pty_reply, + "s", arg_host); + if (r < 0) + return log_error_errno(r, "Failed to get machine PTY: %s", bus_error_message(&error, -r)); + + r = sd_bus_message_read(pty_reply, "hs", &master, &s); + if (r < 0) + return bus_log_parse_error(r); + + master = fcntl(master, F_DUPFD_CLOEXEC, 3); + if (master < 0) + return log_error_errno(errno, "Failed to duplicate master fd: %m"); + + pty_path = strdup(s); + if (!pty_path) + return log_oom(); + } else + assert_not_reached("Can't allocate tty via ssh"); + } + + if (!arg_no_block) { + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Could not watch jobs: %m"); + } + + if (arg_unit) { + r = unit_name_mangle_with_suffix(arg_unit, "as unit", + arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, + ".service", &service); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); + } else { + r = make_unit_name(bus, UNIT_SERVICE, &service); + if (r < 0) + return r; + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); + if (r < 0) + return bus_log_create_error(r); + + /* Name and mode */ + r = sd_bus_message_append(m, "ss", service, "fail"); + if (r < 0) + return bus_log_create_error(r); + + /* Properties */ + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = transient_service_set_properties(m, pty_path); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + /* Auxiliary units */ + r = sd_bus_message_append(m, "a(sa(sv))", 0); + if (r < 0) + return bus_log_create_error(r); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r)); + + if (w) { + const char *object; + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_one(w, object, arg_quiet); + if (r < 0) + return r; + } + + if (!arg_quiet) + log_info("Running as unit: %s", service); + + if (arg_wait || arg_stdio != ARG_STDIO_NONE) { + _cleanup_(run_context_free) RunContext c = { + .cpu_usage_nsec = NSEC_INFINITY, + .ip_ingress_bytes = UINT64_MAX, + .ip_egress_bytes = UINT64_MAX, + .io_read_bytes = UINT64_MAX, + .io_write_bytes = UINT64_MAX, + .inactive_exit_usec = USEC_INFINITY, + .inactive_enter_usec = USEC_INFINITY, + }; + _cleanup_free_ char *path = NULL; + + c.bus = sd_bus_ref(bus); + + r = sd_event_default(&c.event); + if (r < 0) + return log_error_errno(r, "Failed to get event loop: %m"); + + if (master >= 0) { + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGWINCH, SIGTERM, SIGINT, -1) >= 0); + (void) sd_event_add_signal(c.event, NULL, SIGINT, NULL, NULL); + (void) sd_event_add_signal(c.event, NULL, SIGTERM, NULL, NULL); + + if (!arg_quiet) + log_info("Press ^] three times within 1s to disconnect TTY."); + + r = pty_forward_new(c.event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &c.forward); + if (r < 0) + return log_error_errno(r, "Failed to create PTY forwarder: %m"); + + pty_forward_set_handler(c.forward, pty_forward_handler, &c); + + /* Make sure to process any TTY events before we process bus events */ + (void) pty_forward_set_priority(c.forward, SD_EVENT_PRIORITY_IMPORTANT); + } + + path = unit_dbus_path_from_name(service); + if (!path) + return log_oom(); + + r = sd_bus_match_signal_async( + bus, + &c.match, + "org.freedesktop.systemd1", + path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + on_properties_changed, NULL, &c); + if (r < 0) + return log_error_errno(r, "Failed to request properties changed signal match: %m"); + + r = sd_bus_attach_event(bus, c.event, SD_EVENT_PRIORITY_NORMAL); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + r = run_context_update(&c, path); + if (r < 0) + return r; + + r = sd_event_loop(c.event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + if (c.forward) { + char last_char = 0; + + r = pty_forward_get_last_char(c.forward, &last_char); + if (r >= 0 && !arg_quiet && last_char != '\n') + fputc('\n', stdout); + } + + if (arg_wait && !arg_quiet) { + + /* Explicitly destroy the PTY forwarder, so that the PTY device is usable again, with its + * original settings (i.e. proper line breaks), so that we can show the summary in a pretty + * way. */ + c.forward = pty_forward_free(c.forward); + + if (!isempty(c.result)) + log_info("Finished with result: %s", strna(c.result)); + + if (c.exit_code == CLD_EXITED) + log_info("Main processes terminated with: code=%s/status=%i", + sigchld_code_to_string(c.exit_code), c.exit_status); + else if (c.exit_code > 0) + log_info("Main processes terminated with: code=%s/status=%s", + sigchld_code_to_string(c.exit_code), signal_to_string(c.exit_status)); + + if (timestamp_is_set(c.inactive_enter_usec) && + timestamp_is_set(c.inactive_exit_usec) && + c.inactive_enter_usec > c.inactive_exit_usec) { + char ts[FORMAT_TIMESPAN_MAX]; + log_info("Service runtime: %s", + format_timespan(ts, sizeof ts, c.inactive_enter_usec - c.inactive_exit_usec, USEC_PER_MSEC)); + } + + if (c.cpu_usage_nsec != NSEC_INFINITY) { + char ts[FORMAT_TIMESPAN_MAX]; + log_info("CPU time consumed: %s", + format_timespan(ts, sizeof ts, (c.cpu_usage_nsec + NSEC_PER_USEC - 1) / NSEC_PER_USEC, USEC_PER_MSEC)); + } + + if (c.ip_ingress_bytes != UINT64_MAX) { + char bytes[FORMAT_BYTES_MAX]; + log_info("IP traffic received: %s", format_bytes(bytes, sizeof bytes, c.ip_ingress_bytes)); + } + if (c.ip_egress_bytes != UINT64_MAX) { + char bytes[FORMAT_BYTES_MAX]; + log_info("IP traffic sent: %s", format_bytes(bytes, sizeof bytes, c.ip_egress_bytes)); + } + if (c.io_read_bytes != UINT64_MAX) { + char bytes[FORMAT_BYTES_MAX]; + log_info("IO bytes read: %s", format_bytes(bytes, sizeof bytes, c.io_read_bytes)); + } + if (c.io_write_bytes != UINT64_MAX) { + char bytes[FORMAT_BYTES_MAX]; + log_info("IO bytes written: %s", format_bytes(bytes, sizeof bytes, c.io_write_bytes)); + } + } + + /* Try to propagate the service's return value. But if the service defines + * e.g. SuccessExitStatus, honour this, and return 0 to mean "success". */ + if (streq_ptr(c.result, "success")) + *retval = 0; + else if (streq_ptr(c.result, "exit-code") && c.exit_status > 0) + *retval = c.exit_status; + else if (streq_ptr(c.result, "signal")) + *retval = EXIT_EXCEPTION; + else + *retval = EXIT_FAILURE; + } + + return 0; +} + +static int acquire_invocation_id(sd_bus *bus, sd_id128_t *ret) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const void *p; + size_t l; + int r; + + assert(bus); + assert(ret); + + r = sd_bus_get_property(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1/unit/self", + "org.freedesktop.systemd1.Unit", + "InvocationID", + &error, + &reply, + "ay"); + if (r < 0) + return log_error_errno(r, "Failed to request invocation ID for scope: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read_array(reply, 'y', &p, &l); + if (r < 0) + return bus_log_parse_error(r); + + if (l != sizeof(sd_id128_t)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid UUID size, %zu != %zu.", l, sizeof(sd_id128_t)); + + memcpy(ret, p, l); + return 0; +} + +static int start_transient_scope(sd_bus *bus) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_strv_free_ char **env = NULL, **user_env = NULL; + _cleanup_free_ char *scope = NULL; + const char *object = NULL; + sd_id128_t invocation_id; + int r; + + assert(bus); + assert(!strv_isempty(arg_cmdline)); + + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_oom(); + + if (arg_unit) { + r = unit_name_mangle_with_suffix(arg_unit, "as unit", + arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, + ".scope", &scope); + if (r < 0) + return log_error_errno(r, "Failed to mangle scope name: %m"); + } else { + r = make_unit_name(bus, UNIT_SCOPE, &scope); + if (r < 0) + return r; + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); + if (r < 0) + return bus_log_create_error(r); + + /* Name and Mode */ + r = sd_bus_message_append(m, "ss", scope, "fail"); + if (r < 0) + return bus_log_create_error(r); + + /* Properties */ + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = transient_scope_set_properties(m); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + /* Auxiliary units */ + r = sd_bus_message_append(m, "a(sa(sv))", 0); + if (r < 0) + return bus_log_create_error(r); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to start transient scope unit: %s", bus_error_message(&error, -r)); + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_one(w, object, arg_quiet); + if (r < 0) + return r; + + r = acquire_invocation_id(bus, &invocation_id); + if (r < 0) + return r; + + r = strv_extendf(&user_env, "INVOCATION_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(invocation_id)); + if (r < 0) + return log_oom(); + + if (arg_nice_set) { + if (setpriority(PRIO_PROCESS, 0, arg_nice) < 0) + return log_error_errno(errno, "Failed to set nice level: %m"); + } + + if (arg_exec_group) { + gid_t gid; + + r = get_group_creds(&arg_exec_group, &gid, 0); + if (r < 0) + return log_error_errno(r, "Failed to resolve group %s: %m", arg_exec_group); + + if (setresgid(gid, gid, gid) < 0) + return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid); + } + + if (arg_exec_user) { + const char *home, *shell; + uid_t uid; + gid_t gid; + + r = get_user_creds(&arg_exec_user, &uid, &gid, &home, &shell, USER_CREDS_CLEAN|USER_CREDS_PREFER_NSS); + if (r < 0) + return log_error_errno(r, "Failed to resolve user %s: %m", arg_exec_user); + + if (home) { + r = strv_extendf(&user_env, "HOME=%s", home); + if (r < 0) + return log_oom(); + } + + if (shell) { + r = strv_extendf(&user_env, "SHELL=%s", shell); + if (r < 0) + return log_oom(); + } + + r = strv_extendf(&user_env, "USER=%s", arg_exec_user); + if (r < 0) + return log_oom(); + + r = strv_extendf(&user_env, "LOGNAME=%s", arg_exec_user); + if (r < 0) + return log_oom(); + + if (!arg_exec_group) { + if (setresgid(gid, gid, gid) < 0) + return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid); + } + + if (setresuid(uid, uid, uid) < 0) + return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid); + } + + env = strv_env_merge(3, environ, user_env, arg_environment); + if (!env) + return log_oom(); + + if (!arg_quiet) + log_info("Running scope as unit: %s", scope); + + execvpe(arg_cmdline[0], arg_cmdline, env); + + return log_error_errno(errno, "Failed to execute: %m"); +} + +static int start_transient_trigger( + sd_bus *bus, + const char *suffix) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + _cleanup_free_ char *trigger = NULL, *service = NULL; + const char *object = NULL; + int r; + + assert(bus); + + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_oom(); + + if (arg_unit) { + switch (unit_name_to_type(arg_unit)) { + + case UNIT_SERVICE: + service = strdup(arg_unit); + if (!service) + return log_oom(); + + r = unit_name_change_suffix(service, suffix, &trigger); + if (r < 0) + return log_error_errno(r, "Failed to change unit suffix: %m"); + break; + + case UNIT_TIMER: + trigger = strdup(arg_unit); + if (!trigger) + return log_oom(); + + r = unit_name_change_suffix(trigger, ".service", &service); + if (r < 0) + return log_error_errno(r, "Failed to change unit suffix: %m"); + break; + + default: + r = unit_name_mangle_with_suffix(arg_unit, "as unit", + arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, + ".service", &service); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); + + r = unit_name_mangle_with_suffix(arg_unit, "as trigger", + arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, + suffix, &trigger); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); + + break; + } + } else { + r = make_unit_name(bus, UNIT_SERVICE, &service); + if (r < 0) + return r; + + r = unit_name_change_suffix(service, suffix, &trigger); + if (r < 0) + return log_error_errno(r, "Failed to change unit suffix: %m"); + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartTransientUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password); + if (r < 0) + return bus_log_create_error(r); + + /* Name and Mode */ + r = sd_bus_message_append(m, "ss", trigger, "fail"); + if (r < 0) + return bus_log_create_error(r); + + /* Properties */ + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + if (streq(suffix, ".path")) + r = transient_unit_set_properties(m, UNIT_PATH, arg_path_property); + else if (streq(suffix, ".socket")) + r = transient_unit_set_properties(m, UNIT_SOCKET, arg_socket_property); + else if (streq(suffix, ".timer")) + r = transient_timer_set_properties(m); + else + assert_not_reached("Invalid suffix"); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "(sa(sv))"); + if (r < 0) + return bus_log_create_error(r); + + if (!strv_isempty(arg_cmdline)) { + r = sd_bus_message_open_container(m, 'r', "sa(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", service); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = transient_service_set_properties(m, NULL); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to start transient %s unit: %s", suffix + 1, bus_error_message(&error, -r)); + + r = sd_bus_message_read(reply, "o", &object); + if (r < 0) + return bus_log_parse_error(r); + + r = bus_wait_for_jobs_one(w, object, arg_quiet); + if (r < 0) + return r; + + if (!arg_quiet) { + log_info("Running %s as unit: %s", suffix + 1, trigger); + if (!strv_isempty(arg_cmdline)) + log_info("Will run service as unit: %s", service); + } + + return 0; +} + +static int run(int argc, char* argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *description = NULL; + int r, retval = EXIT_SUCCESS; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (!strv_isempty(arg_cmdline) && arg_transport == BUS_TRANSPORT_LOCAL) { + _cleanup_free_ char *command = NULL; + + /* Patch in an absolute path */ + + r = find_binary(arg_cmdline[0], &command); + if (r < 0) + return log_error_errno(r, "Failed to find executable %s: %m", arg_cmdline[0]); + + free_and_replace(arg_cmdline[0], command); + } + + if (!arg_description) { + description = strv_join(arg_cmdline, " "); + if (!description) + return log_oom(); + + if (arg_unit && isempty(description)) { + r = free_and_strdup(&description, arg_unit); + if (r < 0) + return log_oom(); + } + + arg_description = description; + } + + /* If --wait is used connect via the bus, unconditionally, as ref/unref is not supported via the limited direct + * connection */ + if (arg_wait || arg_stdio != ARG_STDIO_NONE) + r = bus_connect_transport(arg_transport, arg_host, arg_user, &bus); + else + r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + if (arg_scope) + r = start_transient_scope(bus); + else if (arg_path_property) + r = start_transient_trigger(bus, ".path"); + else if (arg_socket_property) + r = start_transient_trigger(bus, ".socket"); + else if (arg_with_timer) + r = start_transient_trigger(bus, ".timer"); + else + r = start_transient_service(bus, &retval); + if (r < 0) + return r; + + return retval; +} + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c new file mode 100644 index 00000000..1ccb4f82 --- /dev/null +++ b/src/shared/acl-util.c @@ -0,0 +1,408 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "acl-util.h" +#include "alloc-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" +#include "util.h" + +int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) { + acl_entry_t i; + int r; + + assert(acl); + assert(entry); + + for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { + + acl_tag_t tag; + uid_t *u; + bool b; + + if (acl_get_tag_type(i, &tag) < 0) + return -errno; + + if (tag != ACL_USER) + continue; + + u = acl_get_qualifier(i); + if (!u) + return -errno; + + b = *u == uid; + acl_free(u); + + if (b) { + *entry = i; + return 1; + } + } + if (r < 0) + return -errno; + + return 0; +} + +int calc_acl_mask_if_needed(acl_t *acl_p) { + acl_entry_t i; + int r; + bool need = false; + + assert(acl_p); + + for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) { + acl_tag_t tag; + + if (acl_get_tag_type(i, &tag) < 0) + return -errno; + + if (tag == ACL_MASK) + return 0; + + if (IN_SET(tag, ACL_USER, ACL_GROUP)) + need = true; + } + if (r < 0) + return -errno; + + if (need && acl_calc_mask(acl_p) < 0) + return -errno; + + return need; +} + +int add_base_acls_if_needed(acl_t *acl_p, const char *path) { + acl_entry_t i; + int r; + bool have_user_obj = false, have_group_obj = false, have_other = false; + struct stat st; + _cleanup_(acl_freep) acl_t basic = NULL; + + assert(acl_p); + + for (r = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) { + acl_tag_t tag; + + if (acl_get_tag_type(i, &tag) < 0) + return -errno; + + if (tag == ACL_USER_OBJ) + have_user_obj = true; + else if (tag == ACL_GROUP_OBJ) + have_group_obj = true; + else if (tag == ACL_OTHER) + have_other = true; + if (have_user_obj && have_group_obj && have_other) + return 0; + } + if (r < 0) + return -errno; + + r = stat(path, &st); + if (r < 0) + return -errno; + + basic = acl_from_mode(st.st_mode); + if (!basic) + return -errno; + + for (r = acl_get_entry(basic, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(basic, ACL_NEXT_ENTRY, &i)) { + acl_tag_t tag; + acl_entry_t dst; + + if (acl_get_tag_type(i, &tag) < 0) + return -errno; + + if ((tag == ACL_USER_OBJ && have_user_obj) || + (tag == ACL_GROUP_OBJ && have_group_obj) || + (tag == ACL_OTHER && have_other)) + continue; + + r = acl_create_entry(acl_p, &dst); + if (r < 0) + return -errno; + + r = acl_copy_entry(dst, i); + if (r < 0) + return -errno; + } + if (r < 0) + return -errno; + return 0; +} + +int acl_search_groups(const char *path, char ***ret_groups) { + _cleanup_strv_free_ char **g = NULL; + _cleanup_(acl_freep) acl_t acl = NULL; + bool ret = false; + acl_entry_t entry; + int r; + + assert(path); + + acl = acl_get_file(path, ACL_TYPE_DEFAULT); + if (!acl) + return -errno; + + r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); + for (;;) { + _cleanup_(acl_free_gid_tpp) gid_t *gid = NULL; + acl_tag_t tag; + + if (r < 0) + return -errno; + if (r == 0) + break; + + if (acl_get_tag_type(entry, &tag) < 0) + return -errno; + + if (tag != ACL_GROUP) + goto next; + + gid = acl_get_qualifier(entry); + if (!gid) + return -errno; + + if (in_gid(*gid) > 0) { + if (!ret_groups) + return true; + + ret = true; + } + + if (ret_groups) { + char *name; + + name = gid_to_name(*gid); + if (!name) + return -ENOMEM; + + r = strv_consume(&g, name); + if (r < 0) + return r; + } + + next: + r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); + } + + if (ret_groups) + *ret_groups = TAKE_PTR(g); + + return ret; +} + +int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) { + _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not freed */ + _cleanup_strv_free_ char **split; + char **entry; + int r = -EINVAL; + _cleanup_(acl_freep) acl_t a_acl = NULL, d_acl = NULL; + + split = strv_split(text, ","); + if (!split) + return -ENOMEM; + + STRV_FOREACH(entry, split) { + char *p; + + p = STARTSWITH_SET(*entry, "default:", "d:"); + if (p) + r = strv_push(&d, p); + else + r = strv_push(&a, *entry); + if (r < 0) + return r; + } + + if (!strv_isempty(a)) { + _cleanup_free_ char *join; + + join = strv_join(a, ","); + if (!join) + return -ENOMEM; + + a_acl = acl_from_text(join); + if (!a_acl) + return -errno; + + if (want_mask) { + r = calc_acl_mask_if_needed(&a_acl); + if (r < 0) + return r; + } + } + + if (!strv_isempty(d)) { + _cleanup_free_ char *join; + + join = strv_join(d, ","); + if (!join) + return -ENOMEM; + + d_acl = acl_from_text(join); + if (!d_acl) + return -errno; + + if (want_mask) { + r = calc_acl_mask_if_needed(&d_acl); + if (r < 0) + return r; + } + } + + *acl_access = TAKE_PTR(a_acl); + *acl_default = TAKE_PTR(d_acl); + + return 0; +} + +static int acl_entry_equal(acl_entry_t a, acl_entry_t b) { + acl_tag_t tag_a, tag_b; + + if (acl_get_tag_type(a, &tag_a) < 0) + return -errno; + + if (acl_get_tag_type(b, &tag_b) < 0) + return -errno; + + if (tag_a != tag_b) + return false; + + switch (tag_a) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + /* can have only one of those */ + return true; + case ACL_USER: { + _cleanup_(acl_free_uid_tpp) uid_t *uid_a = NULL, *uid_b = NULL; + + uid_a = acl_get_qualifier(a); + if (!uid_a) + return -errno; + + uid_b = acl_get_qualifier(b); + if (!uid_b) + return -errno; + + return *uid_a == *uid_b; + } + case ACL_GROUP: { + _cleanup_(acl_free_gid_tpp) gid_t *gid_a = NULL, *gid_b = NULL; + + gid_a = acl_get_qualifier(a); + if (!gid_a) + return -errno; + + gid_b = acl_get_qualifier(b); + if (!gid_b) + return -errno; + + return *gid_a == *gid_b; + } + default: + assert_not_reached("Unknown acl tag type"); + } +} + +static int find_acl_entry(acl_t acl, acl_entry_t entry, acl_entry_t *out) { + acl_entry_t i; + int r; + + for (r = acl_get_entry(acl, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) { + + r = acl_entry_equal(i, entry); + if (r < 0) + return r; + if (r > 0) { + *out = i; + return 1; + } + } + if (r < 0) + return -errno; + return 0; +} + +int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) { + _cleanup_(acl_freep) acl_t old; + acl_entry_t i; + int r; + + old = acl_get_file(path, type); + if (!old) + return -errno; + + for (r = acl_get_entry(new, ACL_FIRST_ENTRY, &i); + r > 0; + r = acl_get_entry(new, ACL_NEXT_ENTRY, &i)) { + + acl_entry_t j; + + r = find_acl_entry(old, i, &j); + if (r < 0) + return r; + if (r == 0) + if (acl_create_entry(&old, &j) < 0) + return -errno; + + if (acl_copy_entry(j, i) < 0) + return -errno; + } + if (r < 0) + return -errno; + + *acl = TAKE_PTR(old); + + return 0; +} + +int add_acls_for_user(int fd, uid_t uid) { + _cleanup_(acl_freep) acl_t acl = NULL; + acl_entry_t entry; + acl_permset_t permset; + int r; + + acl = acl_get_fd(fd); + if (!acl) + return -errno; + + r = acl_find_uid(acl, uid, &entry); + if (r <= 0) { + if (acl_create_entry(&acl, &entry) < 0 || + acl_set_tag_type(entry, ACL_USER) < 0 || + acl_set_qualifier(entry, &uid) < 0) + return -errno; + } + + /* We do not recalculate the mask unconditionally here, + * so that the fchmod() mask above stays intact. */ + if (acl_get_permset(entry, &permset) < 0 || + acl_add_perm(permset, ACL_READ) < 0) + return -errno; + + r = calc_acl_mask_if_needed(&acl); + if (r < 0) + return r; + + return acl_set_fd(fd, acl); +} diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h new file mode 100644 index 00000000..10b2a3d9 --- /dev/null +++ b/src/shared/acl-util.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if HAVE_ACL + +#include +#include +#include + +#include "macro.h" + +int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry); +int calc_acl_mask_if_needed(acl_t *acl_p); +int add_base_acls_if_needed(acl_t *acl_p, const char *path); +int acl_search_groups(const char* path, char ***ret_groups); +int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask); +int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl); +int add_acls_for_user(int fd, uid_t uid); + +/* acl_free takes multiple argument types. + * Multiple cleanup functions are necessary. */ +DEFINE_TRIVIAL_CLEANUP_FUNC(acl_t, acl_free); +#define acl_free_charp acl_free +DEFINE_TRIVIAL_CLEANUP_FUNC(char*, acl_free_charp); +#define acl_free_uid_tp acl_free +DEFINE_TRIVIAL_CLEANUP_FUNC(uid_t*, acl_free_uid_tp); +#define acl_free_gid_tp acl_free +DEFINE_TRIVIAL_CLEANUP_FUNC(gid_t*, acl_free_gid_tp); + +#endif diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c new file mode 100644 index 00000000..d565ebd4 --- /dev/null +++ b/src/shared/acpi-fpdt.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "acpi-fpdt.h" +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "time-util.h" + +struct acpi_table_header { + char signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oem_id[6]; + char oem_table_id[8]; + uint32_t oem_revision; + char asl_compiler_id[4]; + uint32_t asl_compiler_revision; +}; + +enum { + ACPI_FPDT_TYPE_BOOT = 0, + ACPI_FPDT_TYPE_S3PERF = 1, +}; + +struct acpi_fpdt_header { + uint16_t type; + uint8_t length; + uint8_t revision; + uint8_t reserved[4]; + uint64_t ptr; +}; + +struct acpi_fpdt_boot_header { + char signature[4]; + uint32_t length; +}; + +enum { + ACPI_FPDT_S3PERF_RESUME_REC = 0, + ACPI_FPDT_S3PERF_SUSPEND_REC = 1, + ACPI_FPDT_BOOT_REC = 2, +}; + +struct acpi_fpdt_boot { + uint16_t type; + uint8_t length; + uint8_t revision; + uint8_t reserved[4]; + uint64_t reset_end; + uint64_t load_start; + uint64_t startup_start; + uint64_t exit_services_entry; + uint64_t exit_services_exit; +}; + +int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) { + _cleanup_free_ char *buf = NULL; + struct acpi_table_header *tbl; + size_t l = 0; + struct acpi_fpdt_header *rec; + int r; + uint64_t ptr = 0; + _cleanup_close_ int fd = -1; + struct acpi_fpdt_boot_header hbrec; + struct acpi_fpdt_boot brec; + + r = read_full_file("/sys/firmware/acpi/tables/FPDT", &buf, &l); + if (r < 0) + return r; + + if (l < sizeof(struct acpi_table_header) + sizeof(struct acpi_fpdt_header)) + return -EINVAL; + + tbl = (struct acpi_table_header *)buf; + if (l != tbl->length) + return -EINVAL; + + if (memcmp(tbl->signature, "FPDT", 4) != 0) + return -EINVAL; + + /* find Firmware Basic Boot Performance Pointer Record */ + for (rec = (struct acpi_fpdt_header *)(buf + sizeof(struct acpi_table_header)); + (char *)rec < buf + l; + rec = (struct acpi_fpdt_header *)((char *)rec + rec->length)) { + if (rec->length <= 0) + break; + if (rec->type != ACPI_FPDT_TYPE_BOOT) + continue; + if (rec->length != sizeof(struct acpi_fpdt_header)) + continue; + + ptr = rec->ptr; + break; + } + + if (ptr == 0) + return -ENODATA; + + /* read Firmware Basic Boot Performance Data Record */ + fd = open("/dev/mem", O_CLOEXEC|O_RDONLY); + if (fd < 0) + return -errno; + + l = pread(fd, &hbrec, sizeof(struct acpi_fpdt_boot_header), ptr); + if (l != sizeof(struct acpi_fpdt_boot_header)) + return -EINVAL; + + if (memcmp(hbrec.signature, "FBPT", 4) != 0) + return -EINVAL; + + if (hbrec.length < sizeof(struct acpi_fpdt_boot_header) + sizeof(struct acpi_fpdt_boot)) + return -EINVAL; + + l = pread(fd, &brec, sizeof(struct acpi_fpdt_boot), ptr + sizeof(struct acpi_fpdt_boot_header)); + if (l != sizeof(struct acpi_fpdt_boot)) + return -EINVAL; + + if (brec.length != sizeof(struct acpi_fpdt_boot)) + return -EINVAL; + + if (brec.type != ACPI_FPDT_BOOT_REC) + return -EINVAL; + + if (brec.exit_services_exit == 0) + /* Non-UEFI compatible boot. */ + return -ENODATA; + + if (brec.startup_start == 0 || brec.exit_services_exit < brec.startup_start) + return -EINVAL; + if (brec.exit_services_exit > NSEC_PER_HOUR) + return -EINVAL; + + if (loader_start) + *loader_start = brec.startup_start / 1000; + if (loader_exit) + *loader_exit = brec.exit_services_exit / 1000; + + return 0; +} diff --git a/src/shared/acpi-fpdt.h b/src/shared/acpi-fpdt.h new file mode 100644 index 00000000..8d288937 --- /dev/null +++ b/src/shared/acpi-fpdt.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit); diff --git a/src/shared/apparmor-util.c b/src/shared/apparmor-util.c new file mode 100644 index 00000000..c4a4b04d --- /dev/null +++ b/src/shared/apparmor-util.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "apparmor-util.h" +#include "fileio.h" +#include "parse-util.h" + +bool mac_apparmor_use(void) { + static int cached_use = -1; + + if (cached_use < 0) { + _cleanup_free_ char *p = NULL; + + cached_use = + read_one_line_file("/sys/module/apparmor/parameters/enabled", &p) >= 0 && + parse_boolean(p) > 0; + } + + return cached_use; +} diff --git a/src/shared/apparmor-util.h b/src/shared/apparmor-util.h new file mode 100644 index 00000000..7fbaf90d --- /dev/null +++ b/src/shared/apparmor-util.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +bool mac_apparmor_use(void); diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c new file mode 100644 index 00000000..7f6775f4 --- /dev/null +++ b/src/shared/ask-password-api.c @@ -0,0 +1,1011 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "ask-password-api.h" +#include "def.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "io-util.h" +#include "log.h" +#include "macro.h" +#include "memory-util.h" +#include "missing_syscall.h" +#include "mkdir.h" +#include "process-util.h" +#include "random-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "time-util.h" +#include "tmpfile-util.h" +#include "umask-util.h" +#include "utf8.h" + +#define KEYRING_TIMEOUT_USEC ((5 * USEC_PER_MINUTE) / 2) + +static int lookup_key(const char *keyname, key_serial_t *ret) { + key_serial_t serial; + + assert(keyname); + assert(ret); + + serial = request_key("user", keyname, NULL, 0); + if (serial == -1) + return negative_errno(); + + *ret = serial; + return 0; +} + +static int retrieve_key(key_serial_t serial, char ***ret) { + size_t nfinal, m = 100; + char **l; + _cleanup_(erase_and_freep) char *pfinal = NULL; + + assert(ret); + + for (;;) { + _cleanup_(erase_and_freep) char *p = NULL; + long n; + + p = new(char, m); + if (!p) + return -ENOMEM; + + n = keyctl(KEYCTL_READ, (unsigned long) serial, (unsigned long) p, (unsigned long) m, 0); + if (n < 0) + return -errno; + if ((size_t) n <= m) { + nfinal = (size_t) n; + pfinal = TAKE_PTR(p); + break; + } + + if (m > LONG_MAX / 2) /* overflow check */ + return -ENOMEM; + m *= 2; + } + + l = strv_parse_nulstr(pfinal, nfinal); + if (!l) + return -ENOMEM; + + *ret = l; + return 0; +} + +static int add_to_keyring(const char *keyname, AskPasswordFlags flags, char **passwords) { + _cleanup_strv_free_erase_ char **l = NULL; + _cleanup_(erase_and_freep) char *p = NULL; + key_serial_t serial; + size_t n; + int r; + + assert(keyname); + + if (!(flags & ASK_PASSWORD_PUSH_CACHE)) + return 0; + if (strv_isempty(passwords)) + return 0; + + r = lookup_key(keyname, &serial); + if (r >= 0) { + r = retrieve_key(serial, &l); + if (r < 0) + return r; + } else if (r != -ENOKEY) + return r; + + r = strv_extend_strv(&l, passwords, true); + if (r <= 0) + return r; + + r = strv_make_nulstr(l, &p, &n); + if (r < 0) + return r; + + serial = add_key("user", keyname, p, n, KEY_SPEC_USER_KEYRING); + if (serial == -1) + return -errno; + + if (keyctl(KEYCTL_SET_TIMEOUT, + (unsigned long) serial, + (unsigned long) DIV_ROUND_UP(KEYRING_TIMEOUT_USEC, USEC_PER_SEC), 0, 0) < 0) + log_debug_errno(errno, "Failed to adjust timeout: %m"); + + /* Tell everyone to check the keyring */ + (void) touch("/run/systemd/ask-password"); + + log_debug("Added key to keyring as %" PRIi32 ".", serial); + + return 1; +} + +static int add_to_keyring_and_log(const char *keyname, AskPasswordFlags flags, char **passwords) { + int r; + + assert(keyname); + + r = add_to_keyring(keyname, flags, passwords); + if (r < 0) + return log_debug_errno(r, "Failed to add password to keyring: %m"); + + return 0; +} + +static int ask_password_keyring(const char *keyname, AskPasswordFlags flags, char ***ret) { + + key_serial_t serial; + int r; + + assert(keyname); + assert(ret); + + if (!(flags & ASK_PASSWORD_ACCEPT_CACHED)) + return -EUNATCH; + + r = lookup_key(keyname, &serial); + if (ERRNO_IS_NOT_SUPPORTED(r) || r == -EPERM) /* when retrieving the distinction between "kernel or + * container manager don't support or allow this" and + * "no matching key known" doesn't matter. Note that we + * propagate EACCESS here (even if EPERM not) since + * that is used if the keyring is available but we lack + * access to the key. */ + return -ENOKEY; + if (r < 0) + return r; + + return retrieve_key(serial, ret); +} + +static int backspace_chars(int ttyfd, size_t p) { + if (ttyfd < 0) + return 0; + + _cleanup_free_ char *buf = malloc_multiply(3, p); + if (!buf) + return log_oom(); + + for (size_t i = 0; i < p; i++) + memcpy(buf + 3 * i, "\b \b", 3); + + return loop_write(ttyfd, buf, 3*p, false); +} + +static int backspace_string(int ttyfd, const char *str) { + assert(str); + + /* Backspaces through enough characters to entirely undo printing of the specified string. */ + + if (ttyfd < 0) + return 0; + + size_t m = utf8_n_codepoints(str); + if (m == (size_t) -1) + m = strlen(str); /* Not a valid UTF-8 string? If so, let's backspace the number of bytes + * output. Most likely this happened because we are not in an UTF-8 locale, + * and in that case that is the correct thing to do. And even if it's not, + * terminals tend to stop backspacing at the leftmost column, hence + * backspacing too much should be mostly OK. */ + + return backspace_chars(ttyfd, m); +} + +int ask_password_plymouth( + const char *message, + usec_t until, + AskPasswordFlags flags, + const char *flag_file, + char ***ret) { + + static const union sockaddr_union sa = PLYMOUTH_SOCKET; + _cleanup_close_ int fd = -1, notify = -1; + _cleanup_free_ char *packet = NULL; + ssize_t k; + int r, n; + struct pollfd pollfd[2] = {}; + char buffer[LINE_MAX]; + size_t p = 0; + enum { + POLL_SOCKET, + POLL_INOTIFY + }; + + assert(ret); + + if (flag_file) { + notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); + if (notify < 0) + return -errno; + + r = inotify_add_watch(notify, flag_file, IN_ATTRIB); /* for the link count */ + if (r < 0) + return -errno; + } + + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return -errno; + + r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + if (r < 0) + return -errno; + + if (flags & ASK_PASSWORD_ACCEPT_CACHED) { + packet = strdup("c"); + n = 1; + } else if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) + packet = NULL; + if (!packet) + return -ENOMEM; + + r = loop_write(fd, packet, n + 1, true); + if (r < 0) + return r; + + pollfd[POLL_SOCKET].fd = fd; + pollfd[POLL_SOCKET].events = POLLIN; + pollfd[POLL_INOTIFY].fd = notify; + pollfd[POLL_INOTIFY].events = POLLIN; + + for (;;) { + int sleep_for = -1, j; + + if (until > 0) { + usec_t y; + + y = now(CLOCK_MONOTONIC); + + if (y > until) { + r = -ETIME; + goto finish; + } + + sleep_for = (int) ((until - y) / USEC_PER_MSEC); + } + + if (flag_file && access(flag_file, F_OK) < 0) { + r = -errno; + goto finish; + } + + j = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for); + if (j < 0) { + if (errno == EINTR) + continue; + + r = -errno; + goto finish; + } else if (j == 0) { + r = -ETIME; + goto finish; + } + + if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0) + (void) flush_fd(notify); + + if (pollfd[POLL_SOCKET].revents == 0) + continue; + + k = read(fd, buffer + p, sizeof(buffer) - p); + if (k < 0) { + if (IN_SET(errno, EINTR, EAGAIN)) + continue; + + r = -errno; + goto finish; + } else if (k == 0) { + r = -EIO; + goto finish; + } + + p += k; + + if (p < 1) + continue; + + if (buffer[0] == 5) { + + if (flags & ASK_PASSWORD_ACCEPT_CACHED) { + /* Hmm, first try with cached + * passwords failed, so let's retry + * with a normal password request */ + packet = mfree(packet); + + if (asprintf(&packet, "*\002%c%s%n", (int) (strlen(message) + 1), message, &n) < 0) { + r = -ENOMEM; + goto finish; + } + + r = loop_write(fd, packet, n+1, true); + if (r < 0) + goto finish; + + flags &= ~ASK_PASSWORD_ACCEPT_CACHED; + p = 0; + continue; + } + + /* No password, because UI not shown */ + r = -ENOENT; + goto finish; + + } else if (IN_SET(buffer[0], 2, 9)) { + uint32_t size; + char **l; + + /* One or more answers */ + if (p < 5) + continue; + + memcpy(&size, buffer+1, sizeof(size)); + size = le32toh(size); + if (size + 5 > sizeof(buffer)) { + r = -EIO; + goto finish; + } + + if (p-5 < size) + continue; + + l = strv_parse_nulstr(buffer + 5, size); + if (!l) { + r = -ENOMEM; + goto finish; + } + + *ret = l; + break; + + } else { + /* Unknown packet */ + r = -EIO; + goto finish; + } + } + + r = 0; + +finish: + explicit_bzero_safe(buffer, sizeof(buffer)); + return r; +} + +int ask_password_tty( + int ttyfd, + const char *message, + const char *keyname, + usec_t until, + AskPasswordFlags flags, + const char *flag_file, + char ***ret) { + + enum { + POLL_TTY, + POLL_INOTIFY, + _POLL_MAX, + }; + + bool reset_tty = false, dirty = false, use_color = false; + _cleanup_close_ int cttyfd = -1, notify = -1; + struct termios old_termios, new_termios; + char passphrase[LINE_MAX + 1] = {}, *x; + _cleanup_strv_free_erase_ char **l = NULL; + struct pollfd pollfd[_POLL_MAX]; + size_t p = 0, codepoint = 0; + int r; + + assert(ret); + + if (flags & ASK_PASSWORD_NO_TTY) + return -EUNATCH; + + if (!message) + message = "Password:"; + + if (flag_file || ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname)) { + notify = inotify_init1(IN_CLOEXEC|IN_NONBLOCK); + if (notify < 0) + return -errno; + } + if (flag_file) { + if (inotify_add_watch(notify, flag_file, IN_ATTRIB /* for the link count */) < 0) + return -errno; + } + if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) { + r = ask_password_keyring(keyname, flags, ret); + if (r >= 0) + return 0; + else if (r != -ENOKEY) + return r; + + if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_ATTRIB /* for mtime */) < 0) + return -errno; + } + + /* If the caller didn't specify a TTY, then use the controlling tty, if we can. */ + if (ttyfd < 0) + ttyfd = cttyfd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC); + + if (ttyfd >= 0) { + if (tcgetattr(ttyfd, &old_termios) < 0) + return -errno; + + if (flags & ASK_PASSWORD_CONSOLE_COLOR) + use_color = dev_console_colors_enabled(); + else + use_color = colors_enabled(); + + if (use_color) + (void) loop_write(ttyfd, ANSI_HIGHLIGHT, STRLEN(ANSI_HIGHLIGHT), false); + + (void) loop_write(ttyfd, message, strlen(message), false); + (void) loop_write(ttyfd, " ", 1, false); + + if (use_color) + (void) loop_write(ttyfd, ANSI_NORMAL, STRLEN(ANSI_NORMAL), false); + + new_termios = old_termios; + new_termios.c_lflag &= ~(ICANON|ECHO); + new_termios.c_cc[VMIN] = 1; + new_termios.c_cc[VTIME] = 0; + + if (tcsetattr(ttyfd, TCSADRAIN, &new_termios) < 0) { + r = -errno; + goto finish; + } + + reset_tty = true; + } + + pollfd[POLL_TTY] = (struct pollfd) { + .fd = ttyfd >= 0 ? ttyfd : STDIN_FILENO, + .events = POLLIN, + }; + pollfd[POLL_INOTIFY] = (struct pollfd) { + .fd = notify, + .events = POLLIN, + }; + + for (;;) { + _cleanup_(erase_char) char c; + int sleep_for = -1, k; + ssize_t n; + + if (until > 0) { + usec_t y; + + y = now(CLOCK_MONOTONIC); + + if (y > until) { + r = -ETIME; + goto finish; + } + + sleep_for = (int) DIV_ROUND_UP(until - y, USEC_PER_MSEC); + } + + if (flag_file) + if (access(flag_file, F_OK) < 0) { + r = -errno; + goto finish; + } + + k = poll(pollfd, notify >= 0 ? 2 : 1, sleep_for); + if (k < 0) { + if (errno == EINTR) + continue; + + r = -errno; + goto finish; + } else if (k == 0) { + r = -ETIME; + goto finish; + } + + if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0 && keyname) { + (void) flush_fd(notify); + + r = ask_password_keyring(keyname, flags, ret); + if (r >= 0) { + r = 0; + goto finish; + } else if (r != -ENOKEY) + goto finish; + } + + if (pollfd[POLL_TTY].revents == 0) + continue; + + n = read(ttyfd >= 0 ? ttyfd : STDIN_FILENO, &c, 1); + if (n < 0) { + if (IN_SET(errno, EINTR, EAGAIN)) + continue; + + r = -errno; + goto finish; + + } + + /* We treat EOF, newline and NUL byte all as valid end markers */ + if (n == 0 || c == '\n' || c == 0) + break; + + if (c == 4) { /* C-d also known as EOT */ + if (ttyfd >= 0) + (void) loop_write(ttyfd, "(skipped)", 9, false); + + goto skipped; + } + + if (c == 21) { /* C-u */ + + if (!(flags & ASK_PASSWORD_SILENT)) + (void) backspace_string(ttyfd, passphrase); + + explicit_bzero_safe(passphrase, sizeof(passphrase)); + p = codepoint = 0; + + } else if (IN_SET(c, '\b', 127)) { + + if (p > 0) { + size_t q; + + if (!(flags & ASK_PASSWORD_SILENT)) + (void) backspace_chars(ttyfd, 1); + + /* Remove a full UTF-8 codepoint from the end. For that, figure out where the + * last one begins */ + q = 0; + for (;;) { + size_t z; + + z = utf8_encoded_valid_unichar(passphrase + q, (size_t) -1); + if (z == 0) { + q = (size_t) -1; /* Invalid UTF8! */ + break; + } + + if (q + z >= p) /* This one brings us over the edge */ + break; + + q += z; + } + + p = codepoint = q == (size_t) -1 ? p - 1 : q; + explicit_bzero_safe(passphrase + p, sizeof(passphrase) - p); + + } else if (!dirty && !(flags & ASK_PASSWORD_SILENT)) { + + flags |= ASK_PASSWORD_SILENT; + + /* There are two ways to enter silent mode. Either by pressing backspace as + * first key (and only as first key), or ... */ + + if (ttyfd >= 0) + (void) loop_write(ttyfd, "(no echo) ", 10, false); + + } else if (ttyfd >= 0) + (void) loop_write(ttyfd, "\a", 1, false); + + } else if (c == '\t' && !(flags & ASK_PASSWORD_SILENT)) { + + (void) backspace_string(ttyfd, passphrase); + flags |= ASK_PASSWORD_SILENT; + + /* ... or by pressing TAB at any time. */ + + if (ttyfd >= 0) + (void) loop_write(ttyfd, "(no echo) ", 10, false); + + } else if (p >= sizeof(passphrase)-1) { + + /* Reached the size limit */ + if (ttyfd >= 0) + (void) loop_write(ttyfd, "\a", 1, false); + + } else { + passphrase[p++] = c; + + if (!(flags & ASK_PASSWORD_SILENT) && ttyfd >= 0) { + /* Check if we got a complete UTF-8 character now. If so, let's output one '*'. */ + n = utf8_encoded_valid_unichar(passphrase + codepoint, (size_t) -1); + if (n >= 0) { + if (flags & ASK_PASSWORD_ECHO) + (void) loop_write(ttyfd, passphrase + codepoint, n, false); + else + (void) loop_write(ttyfd, "*", 1, false); + codepoint = p; + } + } + + dirty = true; + } + } + + x = strndup(passphrase, p); + explicit_bzero_safe(passphrase, sizeof(passphrase)); + if (!x) { + r = -ENOMEM; + goto finish; + } + + r = strv_consume(&l, x); + if (r < 0) + goto finish; + +skipped: + if (keyname) + (void) add_to_keyring_and_log(keyname, flags, l); + + *ret = TAKE_PTR(l); + r = 0; + +finish: + if (ttyfd >= 0 && reset_tty) { + (void) loop_write(ttyfd, "\n", 1, false); + (void) tcsetattr(ttyfd, TCSADRAIN, &old_termios); + } + + return r; +} + +static int create_socket(char **ret) { + _cleanup_free_ char *path = NULL; + union sockaddr_union sa = {}; + _cleanup_close_ int fd = -1; + int salen, r; + + assert(ret); + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return -errno; + + if (asprintf(&path, "/run/systemd/ask-password/sck.%" PRIx64, random_u64()) < 0) + return -ENOMEM; + + salen = sockaddr_un_set_path(&sa.un, path); + if (salen < 0) + return salen; + + RUN_WITH_UMASK(0177) { + if (bind(fd, &sa.sa, salen) < 0) + return -errno; + } + + r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return r; + + *ret = TAKE_PTR(path); + return TAKE_FD(fd); +} + +int ask_password_agent( + const char *message, + const char *icon, + const char *id, + const char *keyname, + usec_t until, + AskPasswordFlags flags, + char ***ret) { + + enum { + FD_SOCKET, + FD_SIGNAL, + FD_INOTIFY, + _FD_MAX + }; + + _cleanup_close_ int socket_fd = -1, signal_fd = -1, notify = -1, fd = -1; + char temp[] = "/run/systemd/ask-password/tmp.XXXXXX"; + char final[sizeof(temp)] = ""; + _cleanup_free_ char *socket_name = NULL; + _cleanup_strv_free_erase_ char **l = NULL; + _cleanup_fclose_ FILE *f = NULL; + struct pollfd pollfd[_FD_MAX]; + sigset_t mask, oldmask; + int r; + + assert(ret); + + if (flags & ASK_PASSWORD_NO_AGENT) + return -EUNATCH; + + assert_se(sigemptyset(&mask) >= 0); + assert_se(sigset_add_many(&mask, SIGINT, SIGTERM, -1) >= 0); + assert_se(sigprocmask(SIG_BLOCK, &mask, &oldmask) >= 0); + + (void) mkdir_p_label("/run/systemd/ask-password", 0755); + + if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && keyname) { + r = ask_password_keyring(keyname, flags, ret); + if (r >= 0) { + r = 0; + goto finish; + } else if (r != -ENOKEY) + goto finish; + + notify = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); + if (notify < 0) { + r = -errno; + goto finish; + } + if (inotify_add_watch(notify, "/run/systemd/ask-password", IN_ATTRIB /* for mtime */) < 0) { + r = -errno; + goto finish; + } + } + + fd = mkostemp_safe(temp); + if (fd < 0) { + r = fd; + goto finish; + } + + (void) fchmod(fd, 0644); + + f = fdopen(fd, "w"); + if (!f) { + r = -errno; + goto finish; + } + + fd = -1; + + signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); + if (signal_fd < 0) { + r = -errno; + goto finish; + } + + socket_fd = create_socket(&socket_name); + if (socket_fd < 0) { + r = socket_fd; + goto finish; + } + + fprintf(f, + "[Ask]\n" + "PID="PID_FMT"\n" + "Socket=%s\n" + "AcceptCached=%i\n" + "Echo=%i\n" + "NotAfter="USEC_FMT"\n", + getpid_cached(), + socket_name, + (flags & ASK_PASSWORD_ACCEPT_CACHED) ? 1 : 0, + (flags & ASK_PASSWORD_ECHO) ? 1 : 0, + until); + + if (message) + fprintf(f, "Message=%s\n", message); + + if (icon) + fprintf(f, "Icon=%s\n", icon); + + if (id) + fprintf(f, "Id=%s\n", id); + + r = fflush_and_check(f); + if (r < 0) + goto finish; + + memcpy(final, temp, sizeof(temp)); + + final[sizeof(final)-11] = 'a'; + final[sizeof(final)-10] = 's'; + final[sizeof(final)-9] = 'k'; + + if (rename(temp, final) < 0) { + r = -errno; + goto finish; + } + + zero(pollfd); + pollfd[FD_SOCKET].fd = socket_fd; + pollfd[FD_SOCKET].events = POLLIN; + pollfd[FD_SIGNAL].fd = signal_fd; + pollfd[FD_SIGNAL].events = POLLIN; + pollfd[FD_INOTIFY].fd = notify; + pollfd[FD_INOTIFY].events = POLLIN; + + for (;;) { + char passphrase[LINE_MAX+1]; + struct msghdr msghdr; + struct iovec iovec; + struct ucred *ucred; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; + } control; + ssize_t n; + int k; + usec_t t; + + t = now(CLOCK_MONOTONIC); + + if (until > 0 && until <= t) { + r = -ETIME; + goto finish; + } + + k = poll(pollfd, notify >= 0 ? _FD_MAX : _FD_MAX - 1, until > 0 ? (int) ((until-t)/USEC_PER_MSEC) : -1); + if (k < 0) { + if (errno == EINTR) + continue; + + r = -errno; + goto finish; + } + + if (k <= 0) { + r = -ETIME; + goto finish; + } + + if (pollfd[FD_SIGNAL].revents & POLLIN) { + r = -EINTR; + goto finish; + } + + if (notify >= 0 && pollfd[FD_INOTIFY].revents != 0) { + (void) flush_fd(notify); + + r = ask_password_keyring(keyname, flags, ret); + if (r >= 0) { + r = 0; + goto finish; + } else if (r != -ENOKEY) + goto finish; + } + + if (pollfd[FD_SOCKET].revents == 0) + continue; + + if (pollfd[FD_SOCKET].revents != POLLIN) { + r = -EIO; + goto finish; + } + + iovec = IOVEC_MAKE(passphrase, sizeof(passphrase)); + + zero(control); + zero(msghdr); + msghdr.msg_iov = &iovec; + msghdr.msg_iovlen = 1; + msghdr.msg_control = &control; + msghdr.msg_controllen = sizeof(control); + + n = recvmsg(socket_fd, &msghdr, 0); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + continue; + + r = -errno; + goto finish; + } + + cmsg_close_all(&msghdr); + + if (n <= 0) { + log_debug("Message too short"); + continue; + } + + if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) || + control.cmsghdr.cmsg_level != SOL_SOCKET || + control.cmsghdr.cmsg_type != SCM_CREDENTIALS || + control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) { + log_debug("Received message without credentials. Ignoring."); + continue; + } + + ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr); + if (ucred->uid != 0) { + log_debug("Got request from unprivileged user. Ignoring."); + continue; + } + + if (passphrase[0] == '+') { + /* An empty message refers to the empty password */ + if (n == 1) + l = strv_new(""); + else + l = strv_parse_nulstr(passphrase+1, n-1); + explicit_bzero_safe(passphrase, n); + if (!l) { + r = -ENOMEM; + goto finish; + } + + if (strv_isempty(l)) { + l = strv_free(l); + log_debug("Invalid packet"); + continue; + } + + break; + } + + if (passphrase[0] == '-') { + r = -ECANCELED; + goto finish; + } + + log_debug("Invalid packet"); + } + + if (keyname) + (void) add_to_keyring_and_log(keyname, flags, l); + + *ret = TAKE_PTR(l); + r = 0; + +finish: + if (socket_name) + (void) unlink(socket_name); + + (void) unlink(temp); + + if (final[0]) + (void) unlink(final); + + assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0); + return r; +} + +int ask_password_auto( + const char *message, + const char *icon, + const char *id, + const char *keyname, + usec_t until, + AskPasswordFlags flags, + char ***ret) { + + int r; + + assert(ret); + + if ((flags & ASK_PASSWORD_ACCEPT_CACHED) && + keyname && + ((flags & ASK_PASSWORD_NO_TTY) || !isatty(STDIN_FILENO)) && + (flags & ASK_PASSWORD_NO_AGENT)) { + r = ask_password_keyring(keyname, flags, ret); + if (r != -ENOKEY) + return r; + } + + if (!(flags & ASK_PASSWORD_NO_TTY) && isatty(STDIN_FILENO)) + return ask_password_tty(-1, message, keyname, until, flags, NULL, ret); + + if (!(flags & ASK_PASSWORD_NO_AGENT)) + return ask_password_agent(message, icon, id, keyname, until, flags, ret); + + return -EUNATCH; +} diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h new file mode 100644 index 00000000..528e3d01 --- /dev/null +++ b/src/shared/ask-password-api.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "time-util.h" + +typedef enum AskPasswordFlags { + ASK_PASSWORD_ACCEPT_CACHED = 1 << 0, + ASK_PASSWORD_PUSH_CACHE = 1 << 1, + ASK_PASSWORD_ECHO = 1 << 2, /* show the password literally while reading, instead of "*" */ + ASK_PASSWORD_SILENT = 1 << 3, /* do no show any password at all while reading */ + ASK_PASSWORD_NO_TTY = 1 << 4, + ASK_PASSWORD_NO_AGENT = 1 << 5, + ASK_PASSWORD_CONSOLE_COLOR = 1 << 6, /* Use color if /dev/console points to a console that supports color */ +} AskPasswordFlags; + +int ask_password_tty(int tty_fd, const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret); +int ask_password_plymouth(const char *message, usec_t until, AskPasswordFlags flags, const char *flag_file, char ***ret); +int ask_password_agent(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); +int ask_password_auto(const char *message, const char *icon, const char *id, const char *keyname, usec_t until, AskPasswordFlags flag, char ***ret); diff --git a/src/shared/barrier.c b/src/shared/barrier.c new file mode 100644 index 00000000..bb5869da --- /dev/null +++ b/src/shared/barrier.c @@ -0,0 +1,394 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "barrier.h" +#include "fd-util.h" +#include "macro.h" + +/** + * Barriers + * This barrier implementation provides a simple synchronization method based + * on file-descriptors that can safely be used between threads and processes. A + * barrier object contains 2 shared counters based on eventfd. Both processes + * can now place barriers and wait for the other end to reach a random or + * specific barrier. + * Barriers are numbered, so you can either wait for the other end to reach any + * barrier or the last barrier that you placed. This way, you can use barriers + * for one-way *and* full synchronization. Note that even-though barriers are + * numbered, these numbers are internal and recycled once both sides reached the + * same barrier (implemented as a simple signed counter). It is thus not + * possible to address barriers by their ID. + * + * Barrier-API: Both ends can place as many barriers via barrier_place() as + * they want and each pair of barriers on both sides will be implicitly linked. + * Each side can use the barrier_wait/sync_*() family of calls to wait for the + * other side to place a specific barrier. barrier_wait_next() waits until the + * other side calls barrier_place(). No links between the barriers are + * considered and this simply serves as most basic asynchronous barrier. + * barrier_sync_next() is like barrier_wait_next() and waits for the other side + * to place their next barrier via barrier_place(). However, it only waits for + * barriers that are linked to a barrier we already placed. If the other side + * already placed more barriers than we did, barrier_sync_next() returns + * immediately. + * barrier_sync() extends barrier_sync_next() and waits until the other end + * placed as many barriers via barrier_place() as we did. If they already placed + * as many as we did (or more), it returns immediately. + * + * Additionally to basic barriers, an abortion event is available. + * barrier_abort() places an abortion event that cannot be undone. An abortion + * immediately cancels all placed barriers and replaces them. Any running and + * following wait/sync call besides barrier_wait_abortion() will immediately + * return false on both sides (otherwise, they always return true). + * barrier_abort() can be called multiple times on both ends and will be a + * no-op if already called on this side. + * barrier_wait_abortion() can be used to wait for the other side to call + * barrier_abort() and is the only wait/sync call that does not return + * immediately if we aborted outself. It only returns once the other side + * called barrier_abort(). + * + * Barriers can be used for in-process and inter-process synchronization. + * However, for in-process synchronization you could just use mutexes. + * Therefore, main target is IPC and we require both sides to *not* share the FD + * table. If that's given, barriers provide target tracking: If the remote side + * exit()s, an abortion event is implicitly queued on the other side. This way, + * a sync/wait call will be woken up if the remote side crashed or exited + * unexpectedly. However, note that these abortion events are only queued if the + * barrier-queue has been drained. Therefore, it is safe to place a barrier and + * exit. The other side can safely wait on the barrier even though the exit + * queued an abortion event. Usually, the abortion event would overwrite the + * barrier, however, that's not true for exit-abortion events. Those are only + * queued if the barrier-queue is drained (thus, the receiving side has placed + * more barriers than the remote side). + */ + +/** + * barrier_create() - Initialize a barrier object + * @obj: barrier to initialize + * + * This initializes a barrier object. The caller is responsible of allocating + * the memory and keeping it valid. The memory does not have to be zeroed + * beforehand. + * Two eventfd objects are allocated for each barrier. If allocation fails, an + * error is returned. + * + * If this function fails, the barrier is reset to an invalid state so it is + * safe to call barrier_destroy() on the object regardless whether the + * initialization succeeded or not. + * + * The caller is responsible to destroy the object via barrier_destroy() before + * releasing the underlying memory. + * + * Returns: 0 on success, negative error code on failure. + */ +int barrier_create(Barrier *b) { + _cleanup_(barrier_destroyp) Barrier *staging = b; + int r; + + assert(b); + + b->me = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + if (b->me < 0) + return -errno; + + b->them = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + if (b->them < 0) + return -errno; + + r = pipe2(b->pipe, O_CLOEXEC | O_NONBLOCK); + if (r < 0) + return -errno; + + staging = NULL; + return 0; +} + +/** + * barrier_destroy() - Destroy a barrier object + * @b: barrier to destroy or NULL + * + * This destroys a barrier object that has previously been passed to + * barrier_create(). The object is released and reset to invalid + * state. Therefore, it is safe to call barrier_destroy() multiple + * times or even if barrier_create() failed. However, barrier must be + * always initialized with BARRIER_NULL. + * + * If @b is NULL, this is a no-op. + */ +void barrier_destroy(Barrier *b) { + if (!b) + return; + + b->me = safe_close(b->me); + b->them = safe_close(b->them); + safe_close_pair(b->pipe); + b->barriers = 0; +} + +/** + * barrier_set_role() - Set the local role of the barrier + * @b: barrier to operate on + * @role: role to set on the barrier + * + * This sets the roles on a barrier object. This is needed to know + * which side of the barrier you're on. Usually, the parent creates + * the barrier via barrier_create() and then calls fork() or clone(). + * Therefore, the FDs are duplicated and the child retains the same + * barrier object. + * + * Both sides need to call barrier_set_role() after fork() or clone() + * are done. If this is not done, barriers will not work correctly. + * + * Note that barriers could be supported without fork() or clone(). However, + * this is currently not needed so it hasn't been implemented. + */ +void barrier_set_role(Barrier *b, unsigned role) { + assert(b); + assert(IN_SET(role, BARRIER_PARENT, BARRIER_CHILD)); + /* make sure this is only called once */ + assert(b->pipe[0] >= 0 && b->pipe[1] >= 0); + + if (role == BARRIER_PARENT) + b->pipe[1] = safe_close(b->pipe[1]); + else { + b->pipe[0] = safe_close(b->pipe[0]); + + /* swap me/them for children */ + SWAP_TWO(b->me, b->them); + } +} + +/* places barrier; returns false if we aborted, otherwise true */ +static bool barrier_write(Barrier *b, uint64_t buf) { + ssize_t len; + + /* prevent new sync-points if we already aborted */ + if (barrier_i_aborted(b)) + return false; + + assert(b->me >= 0); + do { + len = write(b->me, &buf, sizeof(buf)); + } while (len < 0 && IN_SET(errno, EAGAIN, EINTR)); + + if (len != sizeof(buf)) + goto error; + + /* lock if we aborted */ + if (buf >= (uint64_t)BARRIER_ABORTION) { + if (barrier_they_aborted(b)) + b->barriers = BARRIER_WE_ABORTED; + else + b->barriers = BARRIER_I_ABORTED; + } else if (!barrier_is_aborted(b)) + b->barriers += buf; + + return !barrier_i_aborted(b); + +error: + /* If there is an unexpected error, we have to make this fatal. There + * is no way we can recover from sync-errors. Therefore, we close the + * pipe-ends and treat this as abortion. The other end will notice the + * pipe-close and treat it as abortion, too. */ + + safe_close_pair(b->pipe); + b->barriers = BARRIER_WE_ABORTED; + return false; +} + +/* waits for barriers; returns false if they aborted, otherwise true */ +static bool barrier_read(Barrier *b, int64_t comp) { + if (barrier_they_aborted(b)) + return false; + + while (b->barriers > comp) { + struct pollfd pfd[2] = { + { .fd = b->pipe[0] >= 0 ? b->pipe[0] : b->pipe[1], + .events = POLLHUP }, + { .fd = b->them, + .events = POLLIN }}; + uint64_t buf; + int r; + + r = poll(pfd, 2, -1); + if (r < 0 && IN_SET(errno, EAGAIN, EINTR)) + continue; + else if (r < 0) + goto error; + + if (pfd[1].revents) { + ssize_t len; + + /* events on @them signal new data for us */ + len = read(b->them, &buf, sizeof(buf)); + if (len < 0 && IN_SET(errno, EAGAIN, EINTR)) + continue; + + if (len != sizeof(buf)) + goto error; + } else if (pfd[0].revents & (POLLHUP | POLLERR | POLLNVAL)) + /* POLLHUP on the pipe tells us the other side exited. + * We treat this as implicit abortion. But we only + * handle it if there's no event on the eventfd. This + * guarantees that exit-abortions do not overwrite real + * barriers. */ + buf = BARRIER_ABORTION; + else + continue; + + /* lock if they aborted */ + if (buf >= (uint64_t)BARRIER_ABORTION) { + if (barrier_i_aborted(b)) + b->barriers = BARRIER_WE_ABORTED; + else + b->barriers = BARRIER_THEY_ABORTED; + } else if (!barrier_is_aborted(b)) + b->barriers -= buf; + } + + return !barrier_they_aborted(b); + +error: + /* If there is an unexpected error, we have to make this fatal. There + * is no way we can recover from sync-errors. Therefore, we close the + * pipe-ends and treat this as abortion. The other end will notice the + * pipe-close and treat it as abortion, too. */ + + safe_close_pair(b->pipe); + b->barriers = BARRIER_WE_ABORTED; + return false; +} + +/** + * barrier_place() - Place a new barrier + * @b: barrier object + * + * This places a new barrier on the barrier object. If either side already + * aborted, this is a no-op and returns "false". Otherwise, the barrier is + * placed and this returns "true". + * + * Returns: true if barrier was placed, false if either side aborted. + */ +bool barrier_place(Barrier *b) { + assert(b); + + if (barrier_is_aborted(b)) + return false; + + barrier_write(b, BARRIER_SINGLE); + return true; +} + +/** + * barrier_abort() - Abort the synchronization + * @b: barrier object to abort + * + * This aborts the barrier-synchronization. If barrier_abort() was already + * called on this side, this is a no-op. Otherwise, the barrier is put into the + * ABORT-state and will stay there. The other side is notified about the + * abortion. Any following attempt to place normal barriers or to wait on normal + * barriers will return immediately as "false". + * + * You can wait for the other side to call barrier_abort(), too. Use + * barrier_wait_abortion() for that. + * + * Returns: false if the other side already aborted, true otherwise. + */ +bool barrier_abort(Barrier *b) { + assert(b); + + barrier_write(b, BARRIER_ABORTION); + return !barrier_they_aborted(b); +} + +/** + * barrier_wait_next() - Wait for the next barrier of the other side + * @b: barrier to operate on + * + * This waits until the other side places its next barrier. This is independent + * of any barrier-links and just waits for any next barrier of the other side. + * + * If either side aborted, this returns false. + * + * Returns: false if either side aborted, true otherwise. + */ +bool barrier_wait_next(Barrier *b) { + assert(b); + + if (barrier_is_aborted(b)) + return false; + + barrier_read(b, b->barriers - 1); + return !barrier_is_aborted(b); +} + +/** + * barrier_wait_abortion() - Wait for the other side to abort + * @b: barrier to operate on + * + * This waits until the other side called barrier_abort(). This can be called + * regardless whether the local side already called barrier_abort() or not. + * + * If the other side has already aborted, this returns immediately. + * + * Returns: false if the local side aborted, true otherwise. + */ +bool barrier_wait_abortion(Barrier *b) { + assert(b); + + barrier_read(b, BARRIER_THEY_ABORTED); + return !barrier_i_aborted(b); +} + +/** + * barrier_sync_next() - Wait for the other side to place a next linked barrier + * @b: barrier to operate on + * + * This is like barrier_wait_next() and waits for the other side to call + * barrier_place(). However, this only waits for linked barriers. That means, if + * the other side already placed more barriers than (or as much as) we did, this + * returns immediately instead of waiting. + * + * If either side aborted, this returns false. + * + * Returns: false if either side aborted, true otherwise. + */ +bool barrier_sync_next(Barrier *b) { + assert(b); + + if (barrier_is_aborted(b)) + return false; + + barrier_read(b, MAX((int64_t)0, b->barriers - 1)); + return !barrier_is_aborted(b); +} + +/** + * barrier_sync() - Wait for the other side to place as many barriers as we did + * @b: barrier to operate on + * + * This is like barrier_sync_next() but waits for the other side to call + * barrier_place() as often as we did (in total). If they already placed as much + * as we did (or more), this returns immediately instead of waiting. + * + * If either side aborted, this returns false. + * + * Returns: false if either side aborted, true otherwise. + */ +bool barrier_sync(Barrier *b) { + assert(b); + + if (barrier_is_aborted(b)) + return false; + + barrier_read(b, 0); + return !barrier_is_aborted(b); +} diff --git a/src/shared/barrier.h b/src/shared/barrier.h new file mode 100644 index 00000000..0eb3d279 --- /dev/null +++ b/src/shared/barrier.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "macro.h" + +/* See source file for an API description. */ + +typedef struct Barrier Barrier; + +enum { + BARRIER_SINGLE = 1LL, + BARRIER_ABORTION = INT64_MAX, + + /* bias values to store state; keep @WE < @THEY < @I */ + BARRIER_BIAS = INT64_MIN, + BARRIER_WE_ABORTED = BARRIER_BIAS + 1LL, + BARRIER_THEY_ABORTED = BARRIER_BIAS + 2LL, + BARRIER_I_ABORTED = BARRIER_BIAS + 3LL, +}; + +enum { + BARRIER_PARENT, + BARRIER_CHILD, +}; + +struct Barrier { + int me; + int them; + int pipe[2]; + int64_t barriers; +}; + +#define BARRIER_NULL {-1, -1, {-1, -1}, 0} + +int barrier_create(Barrier *obj); +void barrier_destroy(Barrier *b); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Barrier*, barrier_destroy); + +void barrier_set_role(Barrier *b, unsigned role); + +bool barrier_place(Barrier *b); +bool barrier_abort(Barrier *b); + +bool barrier_wait_next(Barrier *b); +bool barrier_wait_abortion(Barrier *b); +bool barrier_sync_next(Barrier *b); +bool barrier_sync(Barrier *b); + +static inline bool barrier_i_aborted(Barrier *b) { + return IN_SET(b->barriers, BARRIER_I_ABORTED, BARRIER_WE_ABORTED); +} + +static inline bool barrier_they_aborted(Barrier *b) { + return IN_SET(b->barriers, BARRIER_THEY_ABORTED, BARRIER_WE_ABORTED); +} + +static inline bool barrier_we_aborted(Barrier *b) { + return b->barriers == BARRIER_WE_ABORTED; +} + +static inline bool barrier_is_aborted(Barrier *b) { + return IN_SET(b->barriers, + BARRIER_I_ABORTED, BARRIER_THEY_ABORTED, BARRIER_WE_ABORTED); +} + +static inline bool barrier_place_and_sync(Barrier *b) { + (void) barrier_place(b); + return barrier_sync(b); +} diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c new file mode 100644 index 00000000..657407da --- /dev/null +++ b/src/shared/base-filesystem.c @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "base-filesystem.h" +#include "fd-util.h" +#include "log.h" +#include "macro.h" +#include "nulstr-util.h" +#include "path-util.h" +#include "string-util.h" +#include "umask-util.h" +#include "user-util.h" + +typedef struct BaseFilesystem { + const char *dir; + mode_t mode; + const char *target; + const char *exists; + bool ignore_failure; +} BaseFilesystem; + +static const BaseFilesystem table[] = { + { "bin", 0, "usr/bin\0", NULL }, + { "lib", 0, "usr/lib\0", NULL }, + { "root", 0755, NULL, NULL, true }, + { "sbin", 0, "usr/sbin\0", NULL }, + { "usr", 0755, NULL, NULL }, + { "var", 0755, NULL, NULL }, + { "etc", 0755, NULL, NULL }, + { "proc", 0755, NULL, NULL, true }, + { "sys", 0755, NULL, NULL, true }, + { "dev", 0755, NULL, NULL, true }, +#if defined(__i386__) || defined(__x86_64__) + { "lib64", 0, "usr/lib/x86_64-linux-gnu\0" + "usr/lib64\0", "ld-linux-x86-64.so.2" }, +#endif +}; + +int base_filesystem_create(const char *root, uid_t uid, gid_t gid) { + _cleanup_close_ int fd = -1; + size_t i; + int r; + + fd = open(root, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); + if (fd < 0) + return log_error_errno(errno, "Failed to open root file system: %m"); + + for (i = 0; i < ELEMENTSOF(table); i ++) { + if (faccessat(fd, table[i].dir, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) + continue; + + if (table[i].target) { + const char *target = NULL, *s; + + /* check if one of the targets exists */ + NULSTR_FOREACH(s, table[i].target) { + if (faccessat(fd, s, F_OK, AT_SYMLINK_NOFOLLOW) < 0) + continue; + + /* check if a specific file exists at the target path */ + if (table[i].exists) { + _cleanup_free_ char *p = NULL; + + p = path_join(s, table[i].exists); + if (!p) + return log_oom(); + + if (faccessat(fd, p, F_OK, AT_SYMLINK_NOFOLLOW) < 0) + continue; + } + + target = s; + break; + } + + if (!target) + continue; + + if (symlinkat(target, fd, table[i].dir) < 0) { + log_full_errno(IN_SET(errno, EEXIST, EROFS) || table[i].ignore_failure ? LOG_DEBUG : LOG_ERR, errno, + "Failed to create symlink at %s/%s: %m", root, table[i].dir); + + if (IN_SET(errno, EEXIST, EROFS) || table[i].ignore_failure) + continue; + + return -errno; + } + + if (uid_is_valid(uid) || gid_is_valid(gid)) { + if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0) + return log_error_errno(errno, "Failed to chown symlink at %s/%s: %m", root, table[i].dir); + } + + continue; + } + + RUN_WITH_UMASK(0000) + r = mkdirat(fd, table[i].dir, table[i].mode); + if (r < 0) { + log_full_errno(IN_SET(errno, EEXIST, EROFS) || table[i].ignore_failure ? LOG_DEBUG : LOG_ERR, errno, + "Failed to create directory at %s/%s: %m", root, table[i].dir); + + if (IN_SET(errno, EEXIST, EROFS) || table[i].ignore_failure) + continue; + + return -errno; + } + + if (uid != UID_INVALID || gid != UID_INVALID) { + if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0) + return log_error_errno(errno, "Failed to chown directory at %s/%s: %m", root, table[i].dir); + } + } + + return 0; +} diff --git a/src/shared/base-filesystem.h b/src/shared/base-filesystem.h new file mode 100644 index 00000000..39d97081 --- /dev/null +++ b/src/shared/base-filesystem.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int base_filesystem_create(const char *root, uid_t uid, gid_t gid); diff --git a/src/shared/bitmap.c b/src/shared/bitmap.c new file mode 100644 index 00000000..2eba72dd --- /dev/null +++ b/src/shared/bitmap.c @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "bitmap.h" +#include "hashmap.h" +#include "macro.h" +#include "memory-util.h" + +/* Bitmaps are only meant to store relatively small numbers + * (corresponding to, say, an enum), so it is ok to limit + * the max entry. 64k should be plenty. */ +#define BITMAPS_MAX_ENTRY 0xffff + +/* This indicates that we reached the end of the bitmap */ +#define BITMAP_END ((unsigned) -1) + +#define BITMAP_NUM_TO_OFFSET(n) ((n) / (sizeof(uint64_t) * 8)) +#define BITMAP_NUM_TO_REM(n) ((n) % (sizeof(uint64_t) * 8)) +#define BITMAP_OFFSET_TO_NUM(offset, rem) ((offset) * sizeof(uint64_t) * 8 + (rem)) + +Bitmap *bitmap_new(void) { + return new0(Bitmap, 1); +} + +Bitmap *bitmap_copy(Bitmap *b) { + Bitmap *ret; + + ret = bitmap_new(); + if (!ret) + return NULL; + + ret->bitmaps = newdup(uint64_t, b->bitmaps, b->n_bitmaps); + if (!ret->bitmaps) + return mfree(ret); + + ret->n_bitmaps = ret->bitmaps_allocated = b->n_bitmaps; + return ret; +} + +void bitmap_free(Bitmap *b) { + if (!b) + return; + + free(b->bitmaps); + free(b); +} + +int bitmap_ensure_allocated(Bitmap **b) { + Bitmap *a; + + assert(b); + + if (*b) + return 0; + + a = bitmap_new(); + if (!a) + return -ENOMEM; + + *b = a; + + return 0; +} + +int bitmap_set(Bitmap *b, unsigned n) { + uint64_t bitmask; + unsigned offset; + + assert(b); + + /* we refuse to allocate huge bitmaps */ + if (n > BITMAPS_MAX_ENTRY) + return -ERANGE; + + offset = BITMAP_NUM_TO_OFFSET(n); + + if (offset >= b->n_bitmaps) { + if (!GREEDY_REALLOC0(b->bitmaps, b->bitmaps_allocated, offset + 1)) + return -ENOMEM; + + b->n_bitmaps = offset + 1; + } + + bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n); + + b->bitmaps[offset] |= bitmask; + + return 0; +} + +void bitmap_unset(Bitmap *b, unsigned n) { + uint64_t bitmask; + unsigned offset; + + if (!b) + return; + + offset = BITMAP_NUM_TO_OFFSET(n); + + if (offset >= b->n_bitmaps) + return; + + bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n); + + b->bitmaps[offset] &= ~bitmask; +} + +bool bitmap_isset(const Bitmap *b, unsigned n) { + uint64_t bitmask; + unsigned offset; + + if (!b) + return false; + + offset = BITMAP_NUM_TO_OFFSET(n); + + if (offset >= b->n_bitmaps) + return false; + + bitmask = UINT64_C(1) << BITMAP_NUM_TO_REM(n); + + return !!(b->bitmaps[offset] & bitmask); +} + +bool bitmap_isclear(const Bitmap *b) { + unsigned i; + + if (!b) + return true; + + for (i = 0; i < b->n_bitmaps; i++) + if (b->bitmaps[i] != 0) + return false; + + return true; +} + +void bitmap_clear(Bitmap *b) { + if (!b) + return; + + b->bitmaps = mfree(b->bitmaps); + b->n_bitmaps = 0; + b->bitmaps_allocated = 0; +} + +bool bitmap_iterate(const Bitmap *b, Iterator *i, unsigned *n) { + uint64_t bitmask; + unsigned offset, rem; + + assert(i); + assert(n); + + if (!b || i->idx == BITMAP_END) + return false; + + offset = BITMAP_NUM_TO_OFFSET(i->idx); + rem = BITMAP_NUM_TO_REM(i->idx); + bitmask = UINT64_C(1) << rem; + + for (; offset < b->n_bitmaps; offset ++) { + if (b->bitmaps[offset]) { + for (; bitmask; bitmask <<= 1, rem ++) { + if (b->bitmaps[offset] & bitmask) { + *n = BITMAP_OFFSET_TO_NUM(offset, rem); + i->idx = *n + 1; + + return true; + } + } + } + + rem = 0; + bitmask = 1; + } + + i->idx = BITMAP_END; + + return false; +} + +bool bitmap_equal(const Bitmap *a, const Bitmap *b) { + size_t common_n_bitmaps; + const Bitmap *c; + unsigned i; + + if (a == b) + return true; + + if (!a != !b) + return false; + + if (!a) + return true; + + common_n_bitmaps = MIN(a->n_bitmaps, b->n_bitmaps); + if (memcmp_safe(a->bitmaps, b->bitmaps, sizeof(uint64_t) * common_n_bitmaps) != 0) + return false; + + c = a->n_bitmaps > b->n_bitmaps ? a : b; + for (i = common_n_bitmaps; i < c->n_bitmaps; i++) + if (c->bitmaps[i] != 0) + return false; + + return true; +} diff --git a/src/shared/bitmap.h b/src/shared/bitmap.h new file mode 100644 index 00000000..f65a0505 --- /dev/null +++ b/src/shared/bitmap.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "hashmap.h" +#include "macro.h" + +typedef struct Bitmap { + uint64_t *bitmaps; + size_t n_bitmaps; + size_t bitmaps_allocated; +} Bitmap; + +Bitmap *bitmap_new(void); +Bitmap *bitmap_copy(Bitmap *b); +int bitmap_ensure_allocated(Bitmap **b); +void bitmap_free(Bitmap *b); + +int bitmap_set(Bitmap *b, unsigned n); +void bitmap_unset(Bitmap *b, unsigned n); +bool bitmap_isset(const Bitmap *b, unsigned n); +bool bitmap_isclear(const Bitmap *b); +void bitmap_clear(Bitmap *b); + +bool bitmap_iterate(const Bitmap *b, Iterator *i, unsigned *n); + +bool bitmap_equal(const Bitmap *a, const Bitmap *b); + +#define BITMAP_FOREACH(n, b, i) \ + for ((i).idx = 0; bitmap_iterate((b), &(i), (unsigned*)&(n)); ) + +DEFINE_TRIVIAL_CLEANUP_FUNC(Bitmap*, bitmap_free); + +#define _cleanup_bitmap_free_ _cleanup_(bitmap_freep) diff --git a/src/shared/blkid-util.h b/src/shared/blkid-util.h new file mode 100644 index 00000000..eb07a88b --- /dev/null +++ b/src/shared/blkid-util.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if HAVE_BLKID +# include + +# include "macro.h" + +DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe); +#endif diff --git a/src/shared/boot-timestamps.c b/src/shared/boot-timestamps.c new file mode 100644 index 00000000..4ce14603 --- /dev/null +++ b/src/shared/boot-timestamps.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "acpi-fpdt.h" +#include "boot-timestamps.h" +#include "efi-loader.h" +#include "macro.h" +#include "time-util.h" + +int boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader) { + usec_t x = 0, y = 0, a; + int r; + dual_timestamp _n; + + assert(firmware); + assert(loader); + + if (!n) { + dual_timestamp_get(&_n); + n = &_n; + } + + r = acpi_get_boot_usec(&x, &y); + if (r < 0) { + r = efi_loader_get_boot_usec(&x, &y); + if (r < 0) + return r; + } + + /* Let's convert this to timestamps where the firmware + * began/loader began working. To make this more confusing: + * since usec_t is unsigned and the kernel's monotonic clock + * begins at kernel initialization we'll actually initialize + * the monotonic timestamps here as negative of the actual + * value. */ + + firmware->monotonic = y; + loader->monotonic = y - x; + + a = n->monotonic + firmware->monotonic; + firmware->realtime = n->realtime > a ? n->realtime - a : 0; + + a = n->monotonic + loader->monotonic; + loader->realtime = n->realtime > a ? n->realtime - a : 0; + + return 0; +} diff --git a/src/shared/boot-timestamps.h b/src/shared/boot-timestamps.h new file mode 100644 index 00000000..4e648f18 --- /dev/null +++ b/src/shared/boot-timestamps.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader); diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c new file mode 100644 index 00000000..558748df --- /dev/null +++ b/src/shared/bootspec.c @@ -0,0 +1,1431 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-device.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "blkid-util.h" +#include "bootspec.h" +#include "conf-files.h" +#include "def.h" +#include "device-nodes.h" +#include "dirent-util.h" +#include "efivars.h" +#include "efi-loader.h" +#include "env-file.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "parse-util.h" +#include "path-util.h" +#include "pe-header.h" +#include "sort-util.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "unaligned.h" +#include "util.h" +#include "virt.h" + +static void boot_entry_free(BootEntry *entry) { + assert(entry); + + free(entry->id); + free(entry->path); + free(entry->root); + free(entry->title); + free(entry->show_title); + free(entry->version); + free(entry->machine_id); + free(entry->architecture); + strv_free(entry->options); + free(entry->kernel); + free(entry->efi); + strv_free(entry->initrd); + free(entry->device_tree); +} + +static int boot_entry_load( + const char *root, + const char *path, + BootEntry *entry) { + + _cleanup_(boot_entry_free) BootEntry tmp = { + .type = BOOT_ENTRY_CONF, + }; + + _cleanup_fclose_ FILE *f = NULL; + unsigned line = 1; + char *b, *c; + int r; + + assert(root); + assert(path); + assert(entry); + + c = endswith_no_case(path, ".conf"); + if (!c) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry file suffix: %s", path); + + b = basename(path); + tmp.id = strndup(b, c - b); + if (!tmp.id) + return log_oom(); + + if (!efi_loader_entry_name_valid(tmp.id)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry filename: %s", path); + + tmp.path = strdup(path); + if (!tmp.path) + return log_oom(); + + tmp.root = strdup(root); + if (!tmp.root) + return log_oom(); + + f = fopen(path, "re"); + if (!f) + return log_error_errno(errno, "Failed to open \"%s\": %m", path); + + for (;;) { + _cleanup_free_ char *buf = NULL, *field = NULL; + const char *p; + + r = read_line(f, LONG_LINE_MAX, &buf); + if (r == 0) + break; + if (r == -ENOBUFS) + return log_error_errno(r, "%s:%u: Line too long", path, line); + if (r < 0) + return log_error_errno(r, "%s:%u: Error while reading: %m", path, line); + + line++; + + if (IN_SET(*strstrip(buf), '#', '\0')) + continue; + + p = buf; + r = extract_first_word(&p, &field, " \t", 0); + if (r < 0) { + log_error_errno(r, "Failed to parse config file %s line %u: %m", path, line); + continue; + } + if (r == 0) { + log_warning("%s:%u: Bad syntax", path, line); + continue; + } + + if (streq(field, "title")) + r = free_and_strdup(&tmp.title, p); + else if (streq(field, "version")) + r = free_and_strdup(&tmp.version, p); + else if (streq(field, "machine-id")) + r = free_and_strdup(&tmp.machine_id, p); + else if (streq(field, "architecture")) + r = free_and_strdup(&tmp.architecture, p); + else if (streq(field, "options")) + r = strv_extend(&tmp.options, p); + else if (streq(field, "linux")) + r = free_and_strdup(&tmp.kernel, p); + else if (streq(field, "efi")) + r = free_and_strdup(&tmp.efi, p); + else if (streq(field, "initrd")) + r = strv_extend(&tmp.initrd, p); + else if (streq(field, "devicetree")) + r = free_and_strdup(&tmp.device_tree, p); + else { + log_notice("%s:%u: Unknown line \"%s\", ignoring.", path, line, field); + continue; + } + if (r < 0) + return log_error_errno(r, "%s:%u: Error while reading: %m", path, line); + } + + *entry = tmp; + tmp = (BootEntry) {}; + return 0; +} + +void boot_config_free(BootConfig *config) { + size_t i; + + assert(config); + + free(config->default_pattern); + free(config->timeout); + free(config->editor); + free(config->auto_entries); + free(config->auto_firmware); + free(config->console_mode); + free(config->random_seed_mode); + + free(config->entry_oneshot); + free(config->entry_default); + + for (i = 0; i < config->n_entries; i++) + boot_entry_free(config->entries + i); + free(config->entries); +} + +static int boot_loader_read_conf(const char *path, BootConfig *config) { + _cleanup_fclose_ FILE *f = NULL; + unsigned line = 1; + int r; + + assert(path); + assert(config); + + f = fopen(path, "re"); + if (!f) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open \"%s\": %m", path); + } + + for (;;) { + _cleanup_free_ char *buf = NULL, *field = NULL; + const char *p; + + r = read_line(f, LONG_LINE_MAX, &buf); + if (r == 0) + break; + if (r == -ENOBUFS) + return log_error_errno(r, "%s:%u: Line too long", path, line); + if (r < 0) + return log_error_errno(r, "%s:%u: Error while reading: %m", path, line); + + line++; + + if (IN_SET(*strstrip(buf), '#', '\0')) + continue; + + p = buf; + r = extract_first_word(&p, &field, " \t", 0); + if (r < 0) { + log_error_errno(r, "Failed to parse config file %s line %u: %m", path, line); + continue; + } + if (r == 0) { + log_warning("%s:%u: Bad syntax", path, line); + continue; + } + + if (streq(field, "default")) + r = free_and_strdup(&config->default_pattern, p); + else if (streq(field, "timeout")) + r = free_and_strdup(&config->timeout, p); + else if (streq(field, "editor")) + r = free_and_strdup(&config->editor, p); + else if (streq(field, "auto-entries")) + r = free_and_strdup(&config->auto_entries, p); + else if (streq(field, "auto-firmware")) + r = free_and_strdup(&config->auto_firmware, p); + else if (streq(field, "console-mode")) + r = free_and_strdup(&config->console_mode, p); + else if (streq(field, "random-seed-mode")) + r = free_and_strdup(&config->random_seed_mode, p); + else { + log_notice("%s:%u: Unknown line \"%s\", ignoring.", path, line, field); + continue; + } + if (r < 0) + return log_error_errno(r, "%s:%u: Error while reading: %m", path, line); + } + + return 1; +} + +static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { + return str_verscmp(a->id, b->id); +} + +static int boot_entries_find( + const char *root, + const char *dir, + BootEntry **entries, + size_t *n_entries) { + + _cleanup_strv_free_ char **files = NULL; + size_t n_allocated = *n_entries; + char **f; + int r; + + assert(root); + assert(dir); + assert(entries); + assert(n_entries); + + r = conf_files_list(&files, ".conf", NULL, 0, dir); + if (r < 0) + return log_error_errno(r, "Failed to list files in \"%s\": %m", dir); + + STRV_FOREACH(f, files) { + if (!GREEDY_REALLOC0(*entries, n_allocated, *n_entries + 1)) + return log_oom(); + + r = boot_entry_load(root, *f, *entries + *n_entries); + if (r < 0) + continue; + + (*n_entries) ++; + } + + return 0; +} + +static int boot_entry_load_unified( + const char *root, + const char *path, + const char *osrelease, + const char *cmdline, + BootEntry *ret) { + + _cleanup_free_ char *os_pretty_name = NULL, *os_id = NULL, *version_id = NULL, *build_id = NULL; + _cleanup_(boot_entry_free) BootEntry tmp = { + .type = BOOT_ENTRY_UNIFIED, + }; + _cleanup_fclose_ FILE *f = NULL; + const char *k; + int r; + + assert(root); + assert(path); + assert(osrelease); + + k = path_startswith(path, root); + if (!k) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Path is not below root: %s", path); + + f = fmemopen_unlocked((void*) osrelease, strlen(osrelease), "r"); + if (!f) + return log_error_errno(errno, "Failed to open os-release buffer: %m"); + + r = parse_env_file(f, "os-release", + "PRETTY_NAME", &os_pretty_name, + "ID", &os_id, + "VERSION_ID", &version_id, + "BUILD_ID", &build_id); + if (r < 0) + return log_error_errno(r, "Failed to parse os-release data from unified kernel image %s: %m", path); + + if (!os_pretty_name || !os_id || !(version_id || build_id)) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Missing fields in os-release data from unified kernel image %s, refusing.", path); + + tmp.id = strjoin(os_id, "-", version_id ?: build_id); + if (!tmp.id) + return log_oom(); + + if (!efi_loader_entry_name_valid(tmp.id)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry: %s", tmp.id); + + tmp.path = strdup(path); + if (!tmp.path) + return log_oom(); + + tmp.root = strdup(root); + if (!tmp.root) + return log_oom(); + + tmp.kernel = strdup(skip_leading_chars(k, "/")); + if (!tmp.kernel) + return log_oom(); + + tmp.options = strv_new(skip_leading_chars(cmdline, WHITESPACE)); + if (!tmp.options) + return log_oom(); + + delete_trailing_chars(tmp.options[0], WHITESPACE); + + tmp.title = TAKE_PTR(os_pretty_name); + + *ret = tmp; + tmp = (BootEntry) {}; + return 0; +} + +/* Maximum PE section we are willing to load (Note that sections we are not interested in may be larger, but + * the ones we do care about and we are willing to load into memory have this size limit.) */ +#define PE_SECTION_SIZE_MAX (4U*1024U*1024U) + +static int find_sections( + int fd, + char **ret_osrelease, + char **ret_cmdline) { + + _cleanup_free_ struct PeSectionHeader *sections = NULL; + _cleanup_free_ char *osrelease = NULL, *cmdline = NULL; + size_t i, n_sections; + struct DosFileHeader dos; + struct PeHeader pe; + uint64_t start; + ssize_t n; + + n = pread(fd, &dos, sizeof(dos), 0); + if (n < 0) + return log_error_errno(errno, "Failed read DOS header: %m"); + if (n != sizeof(dos)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading DOS header, refusing."); + + if (dos.Magic[0] != 'M' || dos.Magic[1] != 'Z') + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "DOS executable magic missing, refusing."); + + start = unaligned_read_le32(&dos.ExeHeader); + n = pread(fd, &pe, sizeof(pe), start); + if (n < 0) + return log_error_errno(errno, "Failed to read PE header: %m"); + if (n != sizeof(pe)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading PE header, refusing."); + + if (pe.Magic[0] != 'P' || pe.Magic[1] != 'E' || pe.Magic[2] != 0 || pe.Magic[3] != 0) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PE executable magic missing, refusing."); + + n_sections = unaligned_read_le16(&pe.FileHeader.NumberOfSections); + if (n_sections > 96) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "PE header has too many sections, refusing."); + + sections = new(struct PeSectionHeader, n_sections); + if (!sections) + return log_oom(); + + n = pread(fd, sections, + n_sections * sizeof(struct PeSectionHeader), + start + sizeof(pe) + unaligned_read_le16(&pe.FileHeader.SizeOfOptionalHeader)); + if (n < 0) + return log_error_errno(errno, "Failed to read section data: %m"); + if ((size_t) n != n_sections * sizeof(struct PeSectionHeader)) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading sections, refusing."); + + for (i = 0; i < n_sections; i++) { + _cleanup_free_ char *k = NULL; + uint32_t offset, size; + char **b; + + if (strneq((char*) sections[i].Name, ".osrel", sizeof(sections[i].Name))) + b = &osrelease; + else if (strneq((char*) sections[i].Name, ".cmdline", sizeof(sections[i].Name))) + b = &cmdline; + else + continue; + + if (*b) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Duplicate section %s, refusing.", sections[i].Name); + + offset = unaligned_read_le32(§ions[i].PointerToRawData); + size = unaligned_read_le32(§ions[i].VirtualSize); + + if (size > PE_SECTION_SIZE_MAX) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Section %s too large, refusing.", sections[i].Name); + + k = new(char, size+1); + if (!k) + return log_oom(); + + n = pread(fd, k, size, offset); + if (n < 0) + return log_error_errno(errno, "Failed to read section payload: %m"); + if ((size_t) n != size) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading section payload, refusing:"); + + /* Allow one trailing NUL byte, but nothing more. */ + if (size > 0 && memchr(k, 0, size - 1)) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Section contains embedded NUL byte: %m"); + + k[size] = 0; + *b = TAKE_PTR(k); + } + + if (!osrelease) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Image lacks .osrel section, refusing."); + + if (ret_osrelease) + *ret_osrelease = TAKE_PTR(osrelease); + if (ret_cmdline) + *ret_cmdline = TAKE_PTR(cmdline); + + return 0; +} + +static int boot_entries_find_unified( + const char *root, + const char *dir, + BootEntry **entries, + size_t *n_entries) { + + _cleanup_(closedirp) DIR *d = NULL; + size_t n_allocated = *n_entries; + struct dirent *de; + int r; + + assert(root); + assert(dir); + assert(entries); + assert(n_entries); + + d = opendir(dir); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open %s: %m", dir); + } + + FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read %s: %m", dir)) { + _cleanup_free_ char *j = NULL, *osrelease = NULL, *cmdline = NULL; + _cleanup_close_ int fd = -1; + + dirent_ensure_type(d, de); + if (!dirent_is_file(de)) + continue; + + if (!endswith_no_case(de->d_name, ".efi")) + continue; + + if (!GREEDY_REALLOC0(*entries, n_allocated, *n_entries + 1)) + return log_oom(); + + fd = openat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) { + log_warning_errno(errno, "Failed to open %s/%s, ignoring: %m", dir, de->d_name); + continue; + } + + r = fd_verify_regular(fd); + if (r < 0) { + log_warning_errno(r, "File %s/%s is not regular, ignoring: %m", dir, de->d_name); + continue; + } + + r = find_sections(fd, &osrelease, &cmdline); + if (r < 0) + continue; + + j = path_join(dir, de->d_name); + if (!j) + return log_oom(); + + r = boot_entry_load_unified(root, j, osrelease, cmdline, *entries + *n_entries); + if (r < 0) + continue; + + (*n_entries) ++; + } + + return 0; +} + +static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) { + size_t i, j; + bool non_unique = false; + + assert(entries || n_entries == 0); + assert(arr || n_entries == 0); + + for (i = 0; i < n_entries; i++) + arr[i] = false; + + for (i = 0; i < n_entries; i++) + for (j = 0; j < n_entries; j++) + if (i != j && streq(boot_entry_title(entries + i), + boot_entry_title(entries + j))) + non_unique = arr[i] = arr[j] = true; + + return non_unique; +} + +static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) { + char *s; + size_t i; + int r; + bool arr[n_entries]; + + assert(entries || n_entries == 0); + + /* Find _all_ non-unique titles */ + if (!find_nonunique(entries, n_entries, arr)) + return 0; + + /* Add version to non-unique titles */ + for (i = 0; i < n_entries; i++) + if (arr[i] && entries[i].version) { + r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].version); + if (r < 0) + return -ENOMEM; + + free_and_replace(entries[i].show_title, s); + } + + if (!find_nonunique(entries, n_entries, arr)) + return 0; + + /* Add machine-id to non-unique titles */ + for (i = 0; i < n_entries; i++) + if (arr[i] && entries[i].machine_id) { + r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].machine_id); + if (r < 0) + return -ENOMEM; + + free_and_replace(entries[i].show_title, s); + } + + if (!find_nonunique(entries, n_entries, arr)) + return 0; + + /* Add file name to non-unique titles */ + for (i = 0; i < n_entries; i++) + if (arr[i]) { + r = asprintf(&s, "%s (%s)", boot_entry_title(entries + i), entries[i].id); + if (r < 0) + return -ENOMEM; + + free_and_replace(entries[i].show_title, s); + } + + return 0; +} + +static int boot_entries_select_default(const BootConfig *config) { + int i; + + assert(config); + assert(config->entries || config->n_entries == 0); + + if (config->n_entries == 0) { + log_debug("Found no default boot entry :("); + return -1; /* -1 means "no default" */ + } + + if (config->entry_oneshot) + for (i = config->n_entries - 1; i >= 0; i--) + if (streq(config->entry_oneshot, config->entries[i].id)) { + log_debug("Found default: id \"%s\" is matched by LoaderEntryOneShot", + config->entries[i].id); + return i; + } + + if (config->entry_default) + for (i = config->n_entries - 1; i >= 0; i--) + if (streq(config->entry_default, config->entries[i].id)) { + log_debug("Found default: id \"%s\" is matched by LoaderEntryDefault", + config->entries[i].id); + return i; + } + + if (config->default_pattern) + for (i = config->n_entries - 1; i >= 0; i--) + if (fnmatch(config->default_pattern, config->entries[i].id, FNM_CASEFOLD) == 0) { + log_debug("Found default: id \"%s\" is matched by pattern \"%s\"", + config->entries[i].id, config->default_pattern); + return i; + } + + log_debug("Found default: last entry \"%s\"", config->entries[config->n_entries - 1].id); + return config->n_entries - 1; +} + +int boot_entries_load_config( + const char *esp_path, + const char *xbootldr_path, + BootConfig *config) { + + const char *p; + int r; + + assert(config); + + if (esp_path) { + p = strjoina(esp_path, "/loader/loader.conf"); + r = boot_loader_read_conf(p, config); + if (r < 0) + return r; + + p = strjoina(esp_path, "/loader/entries"); + r = boot_entries_find(esp_path, p, &config->entries, &config->n_entries); + if (r < 0) + return r; + + p = strjoina(esp_path, "/EFI/Linux/"); + r = boot_entries_find_unified(esp_path, p, &config->entries, &config->n_entries); + if (r < 0) + return r; + } + + if (xbootldr_path) { + p = strjoina(xbootldr_path, "/loader/entries"); + r = boot_entries_find(xbootldr_path, p, &config->entries, &config->n_entries); + if (r < 0) + return r; + + p = strjoina(xbootldr_path, "/EFI/Linux/"); + r = boot_entries_find_unified(xbootldr_path, p, &config->entries, &config->n_entries); + if (r < 0) + return r; + } + + typesafe_qsort(config->entries, config->n_entries, boot_entry_compare); + + r = boot_entries_uniquify(config->entries, config->n_entries); + if (r < 0) + return log_error_errno(r, "Failed to uniquify boot entries: %m"); + + if (is_efi_boot()) { + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &config->entry_oneshot); + if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) { + log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryOneShot\": %m"); + if (r == -ENOMEM) + return r; + } + + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryDefault", &config->entry_default); + if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) { + log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryDefault\": %m"); + if (r == -ENOMEM) + return r; + } + } + + config->default_entry = boot_entries_select_default(config); + return 0; +} + +int boot_entries_load_config_auto( + const char *override_esp_path, + const char *override_xbootldr_path, + BootConfig *config) { + + _cleanup_free_ char *esp_where = NULL, *xbootldr_where = NULL; + int r; + + assert(config); + + /* This function is similar to boot_entries_load_config(), however we automatically search for the + * ESP and the XBOOTLDR partition unless it is explicitly specified. Also, if the user did not pass + * an ESP or XBOOTLDR path directly, let's see if /run/boot-loader-entries/ exists. If so, let's + * read data from there, as if it was an ESP (i.e. loading both entries and loader.conf data from + * it). This allows other boot loaders to pass boot loader entry information to our tools if they + * want to. */ + + if (!override_esp_path && !override_xbootldr_path) { + if (access("/run/boot-loader-entries/", F_OK) >= 0) + return boot_entries_load_config("/run/boot-loader-entries/", NULL, config); + + if (errno != ENOENT) + return log_error_errno(errno, + "Failed to determine whether /run/boot-loader-entries/ exists: %m"); + } + + r = find_esp_and_warn(override_esp_path, false, &esp_where, NULL, NULL, NULL, NULL); + if (r < 0) /* we don't log about ENOKEY here, but propagate it, leaving it to the caller to log */ + return r; + + r = find_xbootldr_and_warn(override_xbootldr_path, false, &xbootldr_where, NULL); + if (r < 0 && r != -ENOKEY) + return r; /* It's fine if the XBOOTLDR partition doesn't exist, hence we ignore ENOKEY here */ + + return boot_entries_load_config(esp_where, xbootldr_where, config); +} + +#if ENABLE_EFI +int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) { + static const char * const title_table[] = { + /* Pretty names for a few well-known automatically discovered entries. */ + "auto-osx", "macOS", + "auto-windows", "Windows Boot Manager", + "auto-efi-shell", "EFI Shell", + "auto-efi-default", "EFI Default Loader", + "auto-reboot-to-firmware-setup", "Reboot Into Firmware Interface", + }; + + _cleanup_strv_free_ char **found_by_loader = NULL; + size_t n_allocated; + char **i; + int r; + + assert(config); + + /* Let's add the entries discovered by the boot loader to the end of our list, unless they are + * already included there. */ + + r = efi_loader_get_entries(&found_by_loader); + if (IN_SET(r, -ENOENT, -EOPNOTSUPP)) + return log_debug_errno(r, "Boot loader reported no entries."); + if (r < 0) + return log_error_errno(r, "Failed to determine entries reported by boot loader: %m"); + + n_allocated = config->n_entries; + + STRV_FOREACH(i, found_by_loader) { + _cleanup_free_ char *c = NULL, *t = NULL, *p = NULL; + char **a, **b; + + if (boot_config_has_entry(config, *i)) + continue; + + if (only_auto && !startswith(*i, "auto-")) + continue; + + c = strdup(*i); + if (!c) + return log_oom(); + + STRV_FOREACH_PAIR(a, b, (char**) title_table) + if (streq(*a, *i)) { + t = strdup(*b); + if (!t) + return log_oom(); + break; + } + + p = efi_variable_path(EFI_VENDOR_LOADER, "LoaderEntries"); + if (!p) + return log_oom(); + + if (!GREEDY_REALLOC0(config->entries, n_allocated, config->n_entries + 1)) + return log_oom(); + + config->entries[config->n_entries++] = (BootEntry) { + .type = BOOT_ENTRY_LOADER, + .id = TAKE_PTR(c), + .title = TAKE_PTR(t), + .path = TAKE_PTR(p), + }; + } + + return 0; +} +#endif + +/********************************************************************************/ + +static int verify_esp_blkid( + dev_t devid, + bool searching, + uint32_t *ret_part, + uint64_t *ret_pstart, + uint64_t *ret_psize, + sd_id128_t *ret_uuid) { + + sd_id128_t uuid = SD_ID128_NULL; + uint64_t pstart = 0, psize = 0; + uint32_t part = 0; + +#if HAVE_BLKID + _cleanup_(blkid_free_probep) blkid_probe b = NULL; + _cleanup_free_ char *node = NULL; + const char *v; + int r; + + r = device_path_make_major_minor(S_IFBLK, devid, &node); + if (r < 0) + return log_error_errno(r, "Failed to format major/minor device path: %m"); + + errno = 0; + b = blkid_new_probe_from_filename(node); + if (!b) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(ENOMEM), "Failed to open file system \"%s\": %m", node); + + blkid_probe_enable_superblocks(b, 1); + blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); + blkid_probe_enable_partitions(b, 1); + blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); + + errno = 0; + r = blkid_do_safeprobe(b); + if (r == -2) + return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" is ambiguous.", node); + else if (r == 1) + return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" does not contain a label.", node); + else if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe file system \"%s\": %m", node); + + errno = 0; + r = blkid_probe_lookup_value(b, "TYPE", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe file system type of \"%s\": %m", node); + if (!streq(v, "vfat")) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "File system \"%s\" is not FAT.", node); + + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition scheme of \"%s\": %m", node); + if (!streq(v, "gpt")) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "File system \"%s\" is not on a GPT partition table.", node); + + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: EIO, "Failed to probe partition type UUID of \"%s\": %m", node); + if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "File system \"%s\" has wrong type for an EFI System Partition (ESP).", node); + + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition entry UUID of \"%s\": %m", node); + r = sd_id128_from_string(v, &uuid); + if (r < 0) + return log_error_errno(r, "Partition \"%s\" has invalid UUID \"%s\".", node, v); + + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition number of \"%s\": %m", node); + r = safe_atou32(v, &part); + if (r < 0) + return log_error_errno(r, "Failed to parse PART_ENTRY_NUMBER field."); + + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition offset of \"%s\": %m", node); + r = safe_atou64(v, &pstart); + if (r < 0) + return log_error_errno(r, "Failed to parse PART_ENTRY_OFFSET field."); + + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition size of \"%s\": %m", node); + r = safe_atou64(v, &psize); + if (r < 0) + return log_error_errno(r, "Failed to parse PART_ENTRY_SIZE field."); +#endif + + if (ret_part) + *ret_part = part; + if (ret_pstart) + *ret_pstart = pstart; + if (ret_psize) + *ret_psize = psize; + if (ret_uuid) + *ret_uuid = uuid; + + return 0; +} + +static int verify_esp_udev( + dev_t devid, + bool searching, + uint32_t *ret_part, + uint64_t *ret_pstart, + uint64_t *ret_psize, + sd_id128_t *ret_uuid) { + + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + _cleanup_free_ char *node = NULL; + sd_id128_t uuid = SD_ID128_NULL; + uint64_t pstart = 0, psize = 0; + uint32_t part = 0; + const char *v; + int r; + + r = device_path_make_major_minor(S_IFBLK, devid, &node); + if (r < 0) + return log_error_errno(r, "Failed to format major/minor device path: %m"); + + r = sd_device_new_from_devnum(&d, 'b', devid); + if (r < 0) + return log_error_errno(r, "Failed to get device from device number: %m"); + + r = sd_device_get_property_value(d, "ID_FS_TYPE", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + if (!streq(v, "vfat")) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "File system \"%s\" is not FAT.", node ); + + r = sd_device_get_property_value(d, "ID_PART_ENTRY_SCHEME", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + if (!streq(v, "gpt")) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "File system \"%s\" is not on a GPT partition table.", node); + + r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "File system \"%s\" has wrong type for an EFI System Partition (ESP).", node); + + r = sd_device_get_property_value(d, "ID_PART_ENTRY_UUID", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + r = sd_id128_from_string(v, &uuid); + if (r < 0) + return log_error_errno(r, "Partition \"%s\" has invalid UUID \"%s\".", node, v); + + r = sd_device_get_property_value(d, "ID_PART_ENTRY_NUMBER", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + r = safe_atou32(v, &part); + if (r < 0) + return log_error_errno(r, "Failed to parse PART_ENTRY_NUMBER field."); + + r = sd_device_get_property_value(d, "ID_PART_ENTRY_OFFSET", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + r = safe_atou64(v, &pstart); + if (r < 0) + return log_error_errno(r, "Failed to parse PART_ENTRY_OFFSET field."); + + r = sd_device_get_property_value(d, "ID_PART_ENTRY_SIZE", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + r = safe_atou64(v, &psize); + if (r < 0) + return log_error_errno(r, "Failed to parse PART_ENTRY_SIZE field."); + + if (ret_part) + *ret_part = part; + if (ret_pstart) + *ret_pstart = pstart; + if (ret_psize) + *ret_psize = psize; + if (ret_uuid) + *ret_uuid = uuid; + + return 0; +} + +static int verify_fsroot_dir( + const char *path, + bool searching, + bool unprivileged_mode, + dev_t *ret_dev) { + + struct stat st, st2; + const char *t2, *trigger; + int r; + + assert(path); + assert(ret_dev); + + /* So, the ESP and XBOOTLDR partition are commonly located on an autofs mount. stat() on the + * directory won't trigger it, if it is not mounted yet. Let's hence explicitly trigger it here, + * before stat()ing */ + trigger = strjoina(path, "/trigger"); /* Filename doesn't matter... */ + (void) access(trigger, F_OK); + + if (stat(path, &st) < 0) + return log_full_errno((searching && errno == ENOENT) || + (unprivileged_mode && errno == EACCES) ? LOG_DEBUG : LOG_ERR, errno, + "Failed to determine block device node of \"%s\": %m", path); + + if (major(st.st_dev) == 0) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "Block device node of \"%s\" is invalid.", path); + + t2 = strjoina(path, "/.."); + if (stat(t2, &st2) < 0) { + if (errno != EACCES) + r = -errno; + else { + _cleanup_free_ char *parent = NULL; + + /* If going via ".." didn't work due to EACCESS, then let's determine the parent path + * directly instead. It's not as good, due to symlinks and such, but we can't do + * anything better here. */ + + parent = dirname_malloc(path); + if (!parent) + return log_oom(); + + if (stat(parent, &st2) < 0) + r = -errno; + else + r = 0; + } + + if (r < 0) + return log_full_errno(unprivileged_mode && r == -EACCES ? LOG_DEBUG : LOG_ERR, r, + "Failed to determine block device node of parent of \"%s\": %m", path); + } + + if (st.st_dev == st2.st_dev) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "Directory \"%s\" is not the root of the file system.", path); + + if (ret_dev) + *ret_dev = st.st_dev; + + return 0; +} + +static int verify_esp( + const char *p, + bool searching, + bool unprivileged_mode, + uint32_t *ret_part, + uint64_t *ret_pstart, + uint64_t *ret_psize, + sd_id128_t *ret_uuid) { + + bool relax_checks; + dev_t devid; + int r; + + assert(p); + + /* This logs about all errors, except: + * + * -ENOENT → if 'searching' is set, and the dir doesn't exist + * -EADDRNOTAVAIL → if 'searching' is set, and the dir doesn't look like an ESP + * -EACESS → if 'unprivileged_mode' is set, and we have trouble accessing the thing + */ + + relax_checks = getenv_bool("SYSTEMD_RELAX_ESP_CHECKS") > 0; + + /* Non-root user can only check the status, so if an error occurred in the following, it does not cause any + * issues. Let's also, silence the error messages. */ + + if (!relax_checks) { + struct statfs sfs; + + if (statfs(p, &sfs) < 0) + /* If we are searching for the mount point, don't generate a log message if we can't find the path */ + return log_full_errno((searching && errno == ENOENT) || + (unprivileged_mode && errno == EACCES) ? LOG_DEBUG : LOG_ERR, errno, + "Failed to check file system type of \"%s\": %m", p); + + if (!F_TYPE_EQUAL(sfs.f_type, MSDOS_SUPER_MAGIC)) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV), + "File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p); + } + + r = verify_fsroot_dir(p, searching, unprivileged_mode, &devid); + if (r < 0) + return r; + + /* In a container we don't have access to block devices, skip this part of the verification, we trust + * the container manager set everything up correctly on its own. */ + if (detect_container() > 0 || relax_checks) + goto finish; + + /* If we are unprivileged we ask udev for the metadata about the partition. If we are privileged we + * use blkid instead. Why? Because this code is called from 'bootctl' which is pretty much an + * emergency recovery tool that should also work when udev isn't up (i.e. from the emergency shell), + * however blkid can't work if we have no privileges to access block devices directly, which is why + * we use udev in that case. */ + if (unprivileged_mode) + return verify_esp_udev(devid, searching, ret_part, ret_pstart, ret_psize, ret_uuid); + else + return verify_esp_blkid(devid, searching, ret_part, ret_pstart, ret_psize, ret_uuid); + +finish: + if (ret_part) + *ret_part = 0; + if (ret_pstart) + *ret_pstart = 0; + if (ret_psize) + *ret_psize = 0; + if (ret_uuid) + *ret_uuid = SD_ID128_NULL; + + return 0; +} + +int find_esp_and_warn( + const char *path, + bool unprivileged_mode, + char **ret_path, + uint32_t *ret_part, + uint64_t *ret_pstart, + uint64_t *ret_psize, + sd_id128_t *ret_uuid) { + + int r; + + /* This logs about all errors except: + * + * -ENOKEY → when we can't find the partition + * -EACCESS → when unprivileged_mode is true, and we can't access something + */ + + if (path) { + r = verify_esp(path, false, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid); + if (r < 0) + return r; + + goto found; + } + + path = getenv("SYSTEMD_ESP_PATH"); + if (path) { + if (!path_is_valid(path) || !path_is_absolute(path)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "$SYSTEMD_ESP_PATH does not refer to absolute path, refusing to use it: %s", + path); + + /* Note: when the user explicitly configured things with an env var we won't validate the mount + * point. After all we want this to be useful for testing. */ + goto found; + } + + FOREACH_STRING(path, "/efi", "/boot", "/boot/efi") { + + r = verify_esp(path, true, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid); + if (r >= 0) + goto found; + if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */ + return r; + } + + /* No logging here */ + return -ENOKEY; + +found: + if (ret_path) { + char *c; + + c = strdup(path); + if (!c) + return log_oom(); + + *ret_path = c; + } + + return 0; +} + +static int verify_xbootldr_blkid( + dev_t devid, + bool searching, + sd_id128_t *ret_uuid) { + + sd_id128_t uuid = SD_ID128_NULL; + +#if HAVE_BLKID + _cleanup_(blkid_free_probep) blkid_probe b = NULL; + _cleanup_free_ char *node = NULL; + const char *v; + int r; + + r = device_path_make_major_minor(S_IFBLK, devid, &node); + if (r < 0) + return log_error_errno(r, "Failed to format major/minor device path: %m"); + errno = 0; + b = blkid_new_probe_from_filename(node); + if (!b) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(ENOMEM), "Failed to open file system \"%s\": %m", node); + + blkid_probe_enable_partitions(b, 1); + blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); + + errno = 0; + r = blkid_do_safeprobe(b); + if (r == -2) + return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" is ambiguous.", node); + else if (r == 1) + return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "File system \"%s\" does not contain a label.", node); + else if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe file system \"%s\": %m", node); + + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition scheme of \"%s\": %m", node); + if (streq(v, "gpt")) { + + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition type UUID of \"%s\": %m", node); + if (!streq(v, "bc13c2ff-59e6-4262-a352-b275fd6f7172")) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV), + "File system \"%s\" has wrong type for extended boot loader partition.", node); + + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition entry UUID of \"%s\": %m", node); + r = sd_id128_from_string(v, &uuid); + if (r < 0) + return log_error_errno(r, "Partition \"%s\" has invalid UUID \"%s\".", node, v); + + } else if (streq(v, "dos")) { + + errno = 0; + r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL); + if (r != 0) + return log_error_errno(errno ?: SYNTHETIC_ERRNO(EIO), "Failed to probe partition type UUID of \"%s\": %m", node); + if (!streq(v, "0xea")) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV), + "File system \"%s\" has wrong type for extended boot loader partition.", node); + + } else + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV), + "File system \"%s\" is not on a GPT or DOS partition table.", node); +#endif + + if (ret_uuid) + *ret_uuid = uuid; + + return 0; +} + +static int verify_xbootldr_udev( + dev_t devid, + bool searching, + sd_id128_t *ret_uuid) { + + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + _cleanup_free_ char *node = NULL; + sd_id128_t uuid = SD_ID128_NULL; + const char *v; + int r; + + r = device_path_make_major_minor(S_IFBLK, devid, &node); + if (r < 0) + return log_error_errno(r, "Failed to format major/minor device path: %m"); + + r = sd_device_new_from_devnum(&d, 'b', devid); + if (r < 0) + return log_error_errno(r, "Failed to get device from device number: %m"); + + r = sd_device_get_property_value(d, "ID_PART_ENTRY_SCHEME", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + + if (streq(v, "gpt")) { + + r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + if (!streq(v, "bc13c2ff-59e6-4262-a352-b275fd6f7172")) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV), + "File system \"%s\" has wrong type for extended boot loader partition.", node); + + r = sd_device_get_property_value(d, "ID_PART_ENTRY_UUID", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + r = sd_id128_from_string(v, &uuid); + if (r < 0) + return log_error_errno(r, "Partition \"%s\" has invalid UUID \"%s\".", node, v); + + } else if (streq(v, "dos")) { + + r = sd_device_get_property_value(d, "ID_PART_ENTRY_TYPE", &v); + if (r < 0) + return log_error_errno(r, "Failed to get device property: %m"); + if (!streq(v, "0xea")) + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV), + "File system \"%s\" has wrong type for extended boot loader partition.", node); + } else + return log_full_errno(searching ? LOG_DEBUG : LOG_ERR, + searching ? SYNTHETIC_ERRNO(EADDRNOTAVAIL) : SYNTHETIC_ERRNO(ENODEV), + "File system \"%s\" is not on a GPT or DOS partition table.", node); + + if (ret_uuid) + *ret_uuid = uuid; + + return 0; +} + +static int verify_xbootldr( + const char *p, + bool searching, + bool unprivileged_mode, + sd_id128_t *ret_uuid) { + + bool relax_checks; + dev_t devid; + int r; + + assert(p); + + relax_checks = getenv_bool("SYSTEMD_RELAX_XBOOTLDR_CHECKS") > 0; + + r = verify_fsroot_dir(p, searching, unprivileged_mode, &devid); + if (r < 0) + return r; + + if (detect_container() > 0 || relax_checks) + goto finish; + + if (unprivileged_mode) + return verify_xbootldr_udev(devid, searching, ret_uuid); + else + return verify_xbootldr_blkid(devid, searching, ret_uuid); + +finish: + if (ret_uuid) + *ret_uuid = SD_ID128_NULL; + + return 0; +} + +int find_xbootldr_and_warn( + const char *path, + bool unprivileged_mode, + char **ret_path, + sd_id128_t *ret_uuid) { + + int r; + + /* Similar to find_esp_and_warn(), but finds the XBOOTLDR partition. Returns the same errors. */ + + if (path) { + r = verify_xbootldr(path, false, unprivileged_mode, ret_uuid); + if (r < 0) + return r; + + goto found; + } + + path = getenv("SYSTEMD_XBOOTLDR_PATH"); + if (path) { + if (!path_is_valid(path) || !path_is_absolute(path)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "$SYSTEMD_XBOOTLDR_PATH does not refer to absolute path, refusing to use it: %s", + path); + + goto found; + } + + r = verify_xbootldr("/boot", true, unprivileged_mode, ret_uuid); + if (r >= 0) { + path = "/boot"; + goto found; + } + if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */ + return r; + + return -ENOKEY; + +found: + if (ret_path) { + char *c; + + c = strdup(path); + if (!c) + return log_oom(); + + *ret_path = c; + } + + return 0; +} diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h new file mode 100644 index 00000000..b65b76c2 --- /dev/null +++ b/src/shared/bootspec.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#pragma once + +#include +#include +#include + +#include "sd-id128.h" + +#include "string-util.h" + +typedef enum BootEntryType { + BOOT_ENTRY_CONF, /* Type #1 entries: *.conf files */ + BOOT_ENTRY_UNIFIED, /* Type #2 entries: *.efi files */ + BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI var */ + _BOOT_ENTRY_MAX, + _BOOT_ENTRY_INVALID = -1, +} BootEntryType; + +typedef struct BootEntry { + BootEntryType type; + char *id; /* This is the file basename without extension */ + char *path; /* This is the full path to the drop-in file */ + char *root; /* The root path in which the drop-in was found, i.e. to which 'kernel', 'efi' and 'initrd' are relative */ + char *title; + char *show_title; + char *version; + char *machine_id; + char *architecture; + char **options; + char *kernel; /* linux is #defined to 1, yikes! */ + char *efi; + char **initrd; + char *device_tree; +} BootEntry; + +typedef struct BootConfig { + char *default_pattern; + char *timeout; + char *editor; + char *auto_entries; + char *auto_firmware; + char *console_mode; + char *random_seed_mode; + + char *entry_oneshot; + char *entry_default; + + BootEntry *entries; + size_t n_entries; + ssize_t default_entry; +} BootConfig; + +static inline bool boot_config_has_entry(BootConfig *config, const char *id) { + size_t j; + + for (j = 0; j < config->n_entries; j++) + if (streq(config->entries[j].id, id)) + return true; + + return false; +} + +static inline BootEntry* boot_config_default_entry(BootConfig *config) { + if (config->default_entry < 0) + return NULL; + + return config->entries + config->default_entry; +} + +void boot_config_free(BootConfig *config); +int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config); +int boot_entries_load_config_auto(const char *override_esp_path, const char *override_xbootldr_path, BootConfig *config); +#if ENABLE_EFI +int boot_entries_augment_from_loader(BootConfig *config, bool only_auto); +#else +static inline int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) { + return -EOPNOTSUPP; +} +#endif + +static inline const char* boot_entry_title(const BootEntry *entry) { + return entry->show_title ?: entry->title ?: entry->id; +} + +int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid); +int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid); diff --git a/src/shared/bpf-program.c b/src/shared/bpf-program.c new file mode 100644 index 00000000..e5c9df40 --- /dev/null +++ b/src/shared/bpf-program.c @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "bpf-program.h" +#include "fd-util.h" +#include "log.h" +#include "memory-util.h" +#include "missing_syscall.h" +#include "path-util.h" + +int bpf_program_new(uint32_t prog_type, BPFProgram **ret) { + _cleanup_(bpf_program_unrefp) BPFProgram *p = NULL; + + p = new0(BPFProgram, 1); + if (!p) + return log_oom(); + + p->n_ref = 1; + p->prog_type = prog_type; + p->kernel_fd = -1; + + *ret = TAKE_PTR(p); + + return 0; +} + +static BPFProgram *bpf_program_free(BPFProgram *p) { + assert(p); + + /* Unfortunately, the kernel currently doesn't implicitly detach BPF programs from their cgroups when the last + * fd to the BPF program is closed. This has nasty side-effects since this means that abnormally terminated + * programs that attached one of their BPF programs to a cgroup will leave this programs pinned for good with + * zero chance of recovery, until the cgroup is removed. This is particularly problematic if the cgroup in + * question is the root cgroup (or any other cgroup belonging to a service that cannot be restarted during + * operation, such as dbus), as the memory for the BPF program can only be reclaimed through a reboot. To + * counter this, we track closely to which cgroup a program was attached to and will detach it on our own + * whenever we close the BPF fd. */ + (void) bpf_program_cgroup_detach(p); + + safe_close(p->kernel_fd); + free(p->instructions); + free(p->attached_path); + + return mfree(p); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(BPFProgram, bpf_program, bpf_program_free); + +int bpf_program_add_instructions(BPFProgram *p, const struct bpf_insn *instructions, size_t count) { + + assert(p); + + if (p->kernel_fd >= 0) /* don't allow modification after we uploaded things to the kernel */ + return -EBUSY; + + if (!GREEDY_REALLOC(p->instructions, p->allocated, p->n_instructions + count)) + return -ENOMEM; + + memcpy(p->instructions + p->n_instructions, instructions, sizeof(struct bpf_insn) * count); + p->n_instructions += count; + + return 0; +} + +int bpf_program_load_kernel(BPFProgram *p, char *log_buf, size_t log_size) { + union bpf_attr attr; + + assert(p); + + if (p->kernel_fd >= 0) { /* make this idempotent */ + memzero(log_buf, log_size); + return 0; + } + + attr = (union bpf_attr) { + .prog_type = p->prog_type, + .insns = PTR_TO_UINT64(p->instructions), + .insn_cnt = p->n_instructions, + .license = PTR_TO_UINT64("GPL"), + .log_buf = PTR_TO_UINT64(log_buf), + .log_level = !!log_buf, + .log_size = log_size, + }; + + p->kernel_fd = bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); + if (p->kernel_fd < 0) + return -errno; + + return 0; +} + +int bpf_program_load_from_bpf_fs(BPFProgram *p, const char *path) { + union bpf_attr attr; + + assert(p); + + if (p->kernel_fd >= 0) /* don't overwrite an assembled or loaded program */ + return -EBUSY; + + attr = (union bpf_attr) { + .pathname = PTR_TO_UINT64(path), + }; + + p->kernel_fd = bpf(BPF_OBJ_GET, &attr, sizeof(attr)); + if (p->kernel_fd < 0) + return -errno; + + return 0; +} + +int bpf_program_cgroup_attach(BPFProgram *p, int type, const char *path, uint32_t flags) { + _cleanup_free_ char *copy = NULL; + _cleanup_close_ int fd = -1; + union bpf_attr attr; + int r; + + assert(p); + assert(type >= 0); + assert(path); + + if (!IN_SET(flags, 0, BPF_F_ALLOW_OVERRIDE, BPF_F_ALLOW_MULTI)) + return -EINVAL; + + /* We need to track which cgroup the program is attached to, and we can only track one attachment, hence let's + * refuse this early. */ + if (p->attached_path) { + if (!path_equal(p->attached_path, path)) + return -EBUSY; + if (p->attached_type != type) + return -EBUSY; + if (p->attached_flags != flags) + return -EBUSY; + + /* Here's a shortcut: if we previously attached this program already, then we don't have to do so + * again. Well, with one exception: if we are in BPF_F_ALLOW_OVERRIDE mode then someone else might have + * replaced our program since the last time, hence let's reattach it again, just to be safe. In flags + * == 0 mode this is not an issue since nobody else can replace our program in that case, and in flags + * == BPF_F_ALLOW_MULTI mode any other's program would be installed in addition to ours hence ours + * would remain in effect. */ + if (flags != BPF_F_ALLOW_OVERRIDE) + return 0; + } + + /* Ensure we have a kernel object for this. */ + r = bpf_program_load_kernel(p, NULL, 0); + if (r < 0) + return r; + + copy = strdup(path); + if (!copy) + return -ENOMEM; + + fd = open(path, O_DIRECTORY|O_RDONLY|O_CLOEXEC); + if (fd < 0) + return -errno; + + attr = (union bpf_attr) { + .attach_type = type, + .target_fd = fd, + .attach_bpf_fd = p->kernel_fd, + .attach_flags = flags, + }; + + if (bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)) < 0) + return -errno; + + free_and_replace(p->attached_path, copy); + p->attached_type = type; + p->attached_flags = flags; + + return 0; +} + +int bpf_program_cgroup_detach(BPFProgram *p) { + _cleanup_close_ int fd = -1; + + assert(p); + + if (!p->attached_path) + return -EUNATCH; + + fd = open(p->attached_path, O_DIRECTORY|O_RDONLY|O_CLOEXEC); + if (fd < 0) { + if (errno != ENOENT) + return -errno; + + /* If the cgroup does not exist anymore, then we don't have to explicitly detach, it got detached + * implicitly by the removal, hence don't complain */ + + } else { + union bpf_attr attr; + + attr = (union bpf_attr) { + .attach_type = p->attached_type, + .target_fd = fd, + .attach_bpf_fd = p->kernel_fd, + }; + + if (bpf(BPF_PROG_DETACH, &attr, sizeof(attr)) < 0) + return -errno; + } + + p->attached_path = mfree(p->attached_path); + + return 0; +} + +int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags) { + union bpf_attr attr = { + .map_type = type, + .key_size = key_size, + .value_size = value_size, + .max_entries = max_entries, + .map_flags = flags, + }; + int fd; + + fd = bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); + if (fd < 0) + return -errno; + + return fd; +} + +int bpf_map_update_element(int fd, const void *key, void *value) { + + union bpf_attr attr = { + .map_fd = fd, + .key = PTR_TO_UINT64(key), + .value = PTR_TO_UINT64(value), + }; + + if (bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)) < 0) + return -errno; + + return 0; +} + +int bpf_map_lookup_element(int fd, const void *key, void *value) { + + union bpf_attr attr = { + .map_fd = fd, + .key = PTR_TO_UINT64(key), + .value = PTR_TO_UINT64(value), + }; + + if (bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)) < 0) + return -errno; + + return 0; +} diff --git a/src/shared/bpf-program.h b/src/shared/bpf-program.h new file mode 100644 index 00000000..a21589eb --- /dev/null +++ b/src/shared/bpf-program.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "list.h" +#include "macro.h" + +typedef struct BPFProgram BPFProgram; + +struct BPFProgram { + unsigned n_ref; + + int kernel_fd; + uint32_t prog_type; + + size_t n_instructions; + size_t allocated; + struct bpf_insn *instructions; + + char *attached_path; + int attached_type; + uint32_t attached_flags; +}; + +int bpf_program_new(uint32_t prog_type, BPFProgram **ret); +BPFProgram *bpf_program_unref(BPFProgram *p); +BPFProgram *bpf_program_ref(BPFProgram *p); + +int bpf_program_add_instructions(BPFProgram *p, const struct bpf_insn *insn, size_t count); +int bpf_program_load_kernel(BPFProgram *p, char *log_buf, size_t log_size); +int bpf_program_load_from_bpf_fs(BPFProgram *p, const char *path); + +int bpf_program_cgroup_attach(BPFProgram *p, int type, const char *path, uint32_t flags); +int bpf_program_cgroup_detach(BPFProgram *p); + +int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags); +int bpf_map_update_element(int fd, const void *key, void *value); +int bpf_map_lookup_element(int fd, const void *key, void *value); + +DEFINE_TRIVIAL_CLEANUP_FUNC(BPFProgram*, bpf_program_unref); diff --git a/src/shared/bus-polkit.c b/src/shared/bus-polkit.c new file mode 100644 index 00000000..0dbf3f60 --- /dev/null +++ b/src/shared/bus-polkit.c @@ -0,0 +1,416 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-internal.h" +#include "bus-message.h" +#include "bus-polkit.h" +#include "strv.h" +#include "user-util.h" + +static int check_good_user(sd_bus_message *m, uid_t good_user) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; + uid_t sender_uid; + int r; + + assert(m); + + if (good_user == UID_INVALID) + return 0; + + r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + /* Don't trust augmented credentials for authorization */ + assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM); + + r = sd_bus_creds_get_euid(creds, &sender_uid); + if (r < 0) + return r; + + return sender_uid == good_user; +} + +#if ENABLE_POLKIT +static int bus_message_append_strv_key_value( + sd_bus_message *m, + const char **l) { + + const char **k, **v; + int r; + + assert(m); + + r = sd_bus_message_open_container(m, 'a', "{ss}"); + if (r < 0) + return r; + + STRV_FOREACH_PAIR(k, v, l) { + r = sd_bus_message_append(m, "{ss}", *k, *v); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return r; + + return r; +} +#endif + +int bus_test_polkit( + sd_bus_message *call, + int capability, + const char *action, + const char **details, + uid_t good_user, + bool *_challenge, + sd_bus_error *ret_error) { + + int r; + + assert(call); + assert(action); + + /* Tests non-interactively! */ + + r = check_good_user(call, good_user); + if (r != 0) + return r; + + r = sd_bus_query_sender_privilege(call, capability); + if (r < 0) + return r; + else if (r > 0) + return 1; +#if ENABLE_POLKIT + else { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int authorized = false, challenge = false; + const char *sender; + + sender = sd_bus_message_get_sender(call); + if (!sender) + return -EBADMSG; + + r = sd_bus_message_new_method_call( + call->bus, + &request, + "org.freedesktop.PolicyKit1", + "/org/freedesktop/PolicyKit1/Authority", + "org.freedesktop.PolicyKit1.Authority", + "CheckAuthorization"); + if (r < 0) + return r; + + r = sd_bus_message_append( + request, + "(sa{sv})s", + "system-bus-name", 1, "name", "s", sender, + action); + if (r < 0) + return r; + + r = bus_message_append_strv_key_value(request, details); + if (r < 0) + return r; + + r = sd_bus_message_append(request, "us", 0, NULL); + if (r < 0) + return r; + + r = sd_bus_call(call->bus, request, 0, ret_error, &reply); + if (r < 0) { + /* Treat no PK available as access denied */ + if (sd_bus_error_has_name(ret_error, SD_BUS_ERROR_SERVICE_UNKNOWN)) { + sd_bus_error_free(ret_error); + return -EACCES; + } + + return r; + } + + r = sd_bus_message_enter_container(reply, 'r', "bba{ss}"); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "bb", &authorized, &challenge); + if (r < 0) + return r; + + if (authorized) + return 1; + + if (_challenge) { + *_challenge = challenge; + return 0; + } + } +#endif + + return -EACCES; +} + +#if ENABLE_POLKIT + +typedef struct AsyncPolkitQuery { + char *action; + char **details; + + sd_bus_message *request, *reply; + sd_bus_slot *slot; + + Hashmap *registry; + sd_event_source *defer_event_source; +} AsyncPolkitQuery; + +static void async_polkit_query_free(AsyncPolkitQuery *q) { + if (!q) + return; + + sd_bus_slot_unref(q->slot); + + if (q->registry && q->request) + hashmap_remove(q->registry, q->request); + + sd_bus_message_unref(q->request); + sd_bus_message_unref(q->reply); + + free(q->action); + strv_free(q->details); + + sd_event_source_disable_unref(q->defer_event_source); + free(q); +} + +static int async_polkit_defer(sd_event_source *s, void *userdata) { + AsyncPolkitQuery *q = userdata; + + assert(s); + + /* This is called as idle event source after we processed the async polkit reply, hopefully after the + * method call we re-enqueued has been properly processed. */ + + async_polkit_query_free(q); + return 0; +} + +static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + AsyncPolkitQuery *q = userdata; + int r; + + assert(reply); + assert(q); + + assert(q->slot); + q->slot = sd_bus_slot_unref(q->slot); + + assert(!q->reply); + q->reply = sd_bus_message_ref(reply); + + /* Now, let's dispatch the original message a second time be re-enqueing. This will then traverse the + * whole message processing again, and thus re-validating and re-retrieving the "userdata" field + * again. + * + * We install an idle event loop event to clean-up the PolicyKit request data when we are idle again, + * i.e. after the second time the message is processed is complete. */ + + assert(!q->defer_event_source); + r = sd_event_add_defer(sd_bus_get_event(sd_bus_message_get_bus(reply)), &q->defer_event_source, async_polkit_defer, q); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(q->defer_event_source, SD_EVENT_PRIORITY_IDLE); + if (r < 0) + goto fail; + + r = sd_event_source_set_enabled(q->defer_event_source, SD_EVENT_ONESHOT); + if (r < 0) + goto fail; + + r = sd_bus_message_rewind(q->request, true); + if (r < 0) + goto fail; + + r = sd_bus_enqueue_for_read(sd_bus_message_get_bus(q->request), q->request); + if (r < 0) + goto fail; + + return 1; + +fail: + log_debug_errno(r, "Processing asynchronous PolicyKit reply failed, ignoring: %m"); + (void) sd_bus_reply_method_errno(q->request, r, NULL); + async_polkit_query_free(q); + return r; +} + +#endif + +int bus_verify_polkit_async( + sd_bus_message *call, + int capability, + const char *action, + const char **details, + bool interactive, + uid_t good_user, + Hashmap **registry, + sd_bus_error *ret_error) { + +#if ENABLE_POLKIT + _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL; + AsyncPolkitQuery *q; + int c; +#endif + const char *sender; + int r; + + assert(call); + assert(action); + assert(registry); + + r = check_good_user(call, good_user); + if (r != 0) + return r; + +#if ENABLE_POLKIT + q = hashmap_get(*registry, call); + if (q) { + int authorized, challenge; + + /* This is the second invocation of this function, and there's already a response from + * polkit, let's process it */ + assert(q->reply); + + /* If the operation we want to authenticate changed between the first and the second time, + * let's not use this authentication, it might be out of date as the object and context we + * operate on might have changed. */ + if (!streq(q->action, action) || + !strv_equal(q->details, (char**) details)) + return -ESTALE; + + if (sd_bus_message_is_method_error(q->reply, NULL)) { + const sd_bus_error *e; + + e = sd_bus_message_get_error(q->reply); + + /* Treat no PK available as access denied */ + if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) || + sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER)) + return -EACCES; + + /* Copy error from polkit reply */ + sd_bus_error_copy(ret_error, e); + return -sd_bus_error_get_errno(e); + } + + r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}"); + if (r >= 0) + r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge); + if (r < 0) + return r; + + if (authorized) + return 1; + + if (challenge) + return sd_bus_error_set(ret_error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required."); + + return -EACCES; + } +#endif + + r = sd_bus_query_sender_privilege(call, capability); + if (r < 0) + return r; + else if (r > 0) + return 1; + + sender = sd_bus_message_get_sender(call); + if (!sender) + return -EBADMSG; + +#if ENABLE_POLKIT + c = sd_bus_message_get_allow_interactive_authorization(call); + if (c < 0) + return c; + if (c > 0) + interactive = true; + + r = hashmap_ensure_allocated(registry, NULL); + if (r < 0) + return r; + + r = sd_bus_message_new_method_call( + call->bus, + &pk, + "org.freedesktop.PolicyKit1", + "/org/freedesktop/PolicyKit1/Authority", + "org.freedesktop.PolicyKit1.Authority", + "CheckAuthorization"); + if (r < 0) + return r; + + r = sd_bus_message_append( + pk, + "(sa{sv})s", + "system-bus-name", 1, "name", "s", sender, + action); + if (r < 0) + return r; + + r = bus_message_append_strv_key_value(pk, details); + if (r < 0) + return r; + + r = sd_bus_message_append(pk, "us", interactive, NULL); + if (r < 0) + return r; + + q = new(AsyncPolkitQuery, 1); + if (!q) + return -ENOMEM; + + *q = (AsyncPolkitQuery) { + .request = sd_bus_message_ref(call), + }; + + q->action = strdup(action); + if (!q->action) { + async_polkit_query_free(q); + return -ENOMEM; + } + + q->details = strv_copy((char**) details); + if (!q->details) { + async_polkit_query_free(q); + return -ENOMEM; + } + + r = hashmap_put(*registry, call, q); + if (r < 0) { + async_polkit_query_free(q); + return r; + } + + q->registry = *registry; + + r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0); + if (r < 0) { + async_polkit_query_free(q); + return r; + } + + return 0; +#endif + + return -EACCES; +} + +void bus_verify_polkit_async_registry_free(Hashmap *registry) { +#if ENABLE_POLKIT + hashmap_free_with_destructor(registry, async_polkit_query_free); +#endif +} diff --git a/src/shared/bus-polkit.h b/src/shared/bus-polkit.h new file mode 100644 index 00000000..29b39230 --- /dev/null +++ b/src/shared/bus-polkit.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "hashmap.h" + +int bus_test_polkit(sd_bus_message *call, int capability, const char *action, const char **details, uid_t good_user, bool *_challenge, sd_bus_error *e); + +int bus_verify_polkit_async(sd_bus_message *call, int capability, const char *action, const char **details, bool interactive, uid_t good_user, Hashmap **registry, sd_bus_error *error); +void bus_verify_polkit_async_registry_free(Hashmap *registry); diff --git a/src/shared/bus-unit-procs.c b/src/shared/bus-unit-procs.c new file mode 100644 index 00000000..b21fe393 --- /dev/null +++ b/src/shared/bus-unit-procs.c @@ -0,0 +1,410 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-unit-procs.h" +#include "hashmap.h" +#include "list.h" +#include "locale-util.h" +#include "macro.h" +#include "path-util.h" +#include "process-util.h" +#include "sort-util.h" +#include "string-util.h" +#include "terminal-util.h" + +struct CGroupInfo { + char *cgroup_path; + bool is_const; /* If false, cgroup_path should be free()'d */ + + Hashmap *pids; /* PID → process name */ + bool done; + + struct CGroupInfo *parent; + LIST_FIELDS(struct CGroupInfo, siblings); + LIST_HEAD(struct CGroupInfo, children); + size_t n_children; +}; + +static int add_cgroup(Hashmap *cgroups, const char *path, bool is_const, struct CGroupInfo **ret) { + struct CGroupInfo *parent = NULL, *cg; + int r; + + assert(cgroups); + assert(ret); + + path = empty_to_root(path); + + cg = hashmap_get(cgroups, path); + if (cg) { + *ret = cg; + return 0; + } + + if (!empty_or_root(path)) { + const char *e, *pp; + + e = strrchr(path, '/'); + if (!e) + return -EINVAL; + + pp = strndupa(path, e - path); + + r = add_cgroup(cgroups, pp, false, &parent); + if (r < 0) + return r; + } + + cg = new0(struct CGroupInfo, 1); + if (!cg) + return -ENOMEM; + + if (is_const) + cg->cgroup_path = (char*) path; + else { + cg->cgroup_path = strdup(path); + if (!cg->cgroup_path) { + free(cg); + return -ENOMEM; + } + } + + cg->is_const = is_const; + cg->parent = parent; + + r = hashmap_put(cgroups, cg->cgroup_path, cg); + if (r < 0) { + if (!is_const) + free(cg->cgroup_path); + free(cg); + return r; + } + + if (parent) { + LIST_PREPEND(siblings, parent->children, cg); + parent->n_children++; + } + + *ret = cg; + return 1; +} + +static int add_process( + Hashmap *cgroups, + const char *path, + pid_t pid, + const char *name) { + + struct CGroupInfo *cg; + int r; + + assert(cgroups); + assert(name); + assert(pid > 0); + + r = add_cgroup(cgroups, path, true, &cg); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&cg->pids, &trivial_hash_ops); + if (r < 0) + return r; + + return hashmap_put(cg->pids, PID_TO_PTR(pid), (void*) name); +} + +static void remove_cgroup(Hashmap *cgroups, struct CGroupInfo *cg) { + assert(cgroups); + assert(cg); + + while (cg->children) + remove_cgroup(cgroups, cg->children); + + hashmap_remove(cgroups, cg->cgroup_path); + + if (!cg->is_const) + free(cg->cgroup_path); + + hashmap_free(cg->pids); + + if (cg->parent) + LIST_REMOVE(siblings, cg->parent->children, cg); + + free(cg); +} + +static int cgroup_info_compare_func(struct CGroupInfo * const *a, struct CGroupInfo * const *b) { + return strcmp((*a)->cgroup_path, (*b)->cgroup_path); +} + +static int dump_processes( + Hashmap *cgroups, + const char *cgroup_path, + const char *prefix, + unsigned n_columns, + OutputFlags flags) { + + struct CGroupInfo *cg; + int r; + + assert(prefix); + + cgroup_path = empty_to_root(cgroup_path); + + cg = hashmap_get(cgroups, cgroup_path); + if (!cg) + return 0; + + if (!hashmap_isempty(cg->pids)) { + const char *name; + size_t n = 0, i; + pid_t *pids; + void *pidp; + Iterator j; + int width; + + /* Order processes by their PID */ + pids = newa(pid_t, hashmap_size(cg->pids)); + + HASHMAP_FOREACH_KEY(name, pidp, cg->pids, j) + pids[n++] = PTR_TO_PID(pidp); + + assert(n == hashmap_size(cg->pids)); + typesafe_qsort(pids, n, pid_compare_func); + + width = DECIMAL_STR_WIDTH(pids[n-1]); + + for (i = 0; i < n; i++) { + _cleanup_free_ char *e = NULL; + const char *special; + bool more; + + name = hashmap_get(cg->pids, PID_TO_PTR(pids[i])); + assert(name); + + if (n_columns != 0) { + unsigned k; + + k = MAX(LESS_BY(n_columns, 2U + width + 1U), 20U); + + e = ellipsize(name, k, 100); + if (e) + name = e; + } + + more = i+1 < n || cg->children; + special = special_glyph(more ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT); + + fprintf(stdout, "%s%s%*"PID_PRI" %s\n", + prefix, + special, + width, pids[i], + name); + } + } + + if (cg->children) { + struct CGroupInfo **children, *child; + size_t n = 0, i; + + /* Order subcgroups by their name */ + children = newa(struct CGroupInfo*, cg->n_children); + LIST_FOREACH(siblings, child, cg->children) + children[n++] = child; + assert(n == cg->n_children); + typesafe_qsort(children, n, cgroup_info_compare_func); + + if (n_columns != 0) + n_columns = MAX(LESS_BY(n_columns, 2U), 20U); + + for (i = 0; i < n; i++) { + _cleanup_free_ char *pp = NULL; + const char *name, *special; + bool more; + + child = children[i]; + + name = strrchr(child->cgroup_path, '/'); + if (!name) + return -EINVAL; + name++; + + more = i+1 < n; + special = special_glyph(more ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT); + + fputs(prefix, stdout); + fputs(special, stdout); + fputs(name, stdout); + fputc('\n', stdout); + + special = special_glyph(more ? SPECIAL_GLYPH_TREE_VERTICAL : SPECIAL_GLYPH_TREE_SPACE); + + pp = strjoin(prefix, special); + if (!pp) + return -ENOMEM; + + r = dump_processes(cgroups, child->cgroup_path, pp, n_columns, flags); + if (r < 0) + return r; + } + } + + cg->done = true; + return 0; +} + +static int dump_extra_processes( + Hashmap *cgroups, + const char *prefix, + unsigned n_columns, + OutputFlags flags) { + + _cleanup_free_ pid_t *pids = NULL; + _cleanup_hashmap_free_ Hashmap *names = NULL; + struct CGroupInfo *cg; + size_t n_allocated = 0, n = 0, k; + Iterator i; + int width, r; + + /* Prints the extra processes, i.e. those that are in cgroups we haven't displayed yet. We show them as + * combined, sorted, linear list. */ + + HASHMAP_FOREACH(cg, cgroups, i) { + const char *name; + void *pidp; + Iterator j; + + if (cg->done) + continue; + + if (hashmap_isempty(cg->pids)) + continue; + + r = hashmap_ensure_allocated(&names, &trivial_hash_ops); + if (r < 0) + return r; + + if (!GREEDY_REALLOC(pids, n_allocated, n + hashmap_size(cg->pids))) + return -ENOMEM; + + HASHMAP_FOREACH_KEY(name, pidp, cg->pids, j) { + pids[n++] = PTR_TO_PID(pidp); + + r = hashmap_put(names, pidp, (void*) name); + if (r < 0) + return r; + } + } + + if (n == 0) + return 0; + + typesafe_qsort(pids, n, pid_compare_func); + width = DECIMAL_STR_WIDTH(pids[n-1]); + + for (k = 0; k < n; k++) { + _cleanup_free_ char *e = NULL; + const char *name; + + name = hashmap_get(names, PID_TO_PTR(pids[k])); + assert(name); + + if (n_columns != 0) { + unsigned z; + + z = MAX(LESS_BY(n_columns, 2U + width + 1U), 20U); + + e = ellipsize(name, z, 100); + if (e) + name = e; + } + + fprintf(stdout, "%s%s %*" PID_PRI " %s\n", + prefix, + special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), + width, pids[k], + name); + } + + return 0; +} + +int unit_show_processes( + sd_bus *bus, + const char *unit, + const char *cgroup_path, + const char *prefix, + unsigned n_columns, + OutputFlags flags, + sd_bus_error *error) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Hashmap *cgroups = NULL; + struct CGroupInfo *cg; + int r; + + assert(bus); + assert(unit); + + if (flags & OUTPUT_FULL_WIDTH) + n_columns = 0; + else if (n_columns <= 0) + n_columns = columns(); + + prefix = strempty(prefix); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetUnitProcesses", + error, + &reply, + "s", + unit); + if (r < 0) + return r; + + cgroups = hashmap_new(&path_hash_ops); + if (!cgroups) + return -ENOMEM; + + r = sd_bus_message_enter_container(reply, 'a', "(sus)"); + if (r < 0) + goto finish; + + for (;;) { + const char *path = NULL, *name = NULL; + uint32_t pid; + + r = sd_bus_message_read(reply, "(sus)", &path, &pid, &name); + if (r < 0) + goto finish; + if (r == 0) + break; + + r = add_process(cgroups, path, pid, name); + if (r == -ENOMEM) + goto finish; + if (r < 0) + log_warning_errno(r, "Invalid process description in GetUnitProcesses reply: cgroup=\"%s\" pid="PID_FMT" command=\"%s\", ignoring: %m", + path, pid, name); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + goto finish; + + r = dump_processes(cgroups, cgroup_path, prefix, n_columns, flags); + if (r < 0) + goto finish; + + r = dump_extra_processes(cgroups, prefix, n_columns, flags); + +finish: + while ((cg = hashmap_first(cgroups))) + remove_cgroup(cgroups, cg); + + hashmap_free(cgroups); + + return r; +} diff --git a/src/shared/bus-unit-procs.h b/src/shared/bus-unit-procs.h new file mode 100644 index 00000000..1cb5ca62 --- /dev/null +++ b/src/shared/bus-unit-procs.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "output-mode.h" + +int unit_show_processes(sd_bus *bus, const char *unit, const char *cgroup_path, const char *prefix, unsigned n_columns, OutputFlags flags, sd_bus_error *error); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c new file mode 100644 index 00000000..22a15493 --- /dev/null +++ b/src/shared/bus-unit-util.c @@ -0,0 +1,2045 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-unit-util.h" +#include "bus-util.h" +#include "cap-list.h" +#include "cgroup-setup.h" +#include "cgroup-util.h" +#include "condition.h" +#include "cpu-set-util.h" +#include "escape.h" +#include "exec-util.h" +#include "exit-status.h" +#include "hexdecoct.h" +#include "hostname-util.h" +#include "in-addr-util.h" +#include "ip-protocol-list.h" +#include "locale-util.h" +#include "log.h" +#include "missing_fs.h" +#include "mountpoint-util.h" +#include "nsflags.h" +#include "parse-util.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "securebits-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "sort-util.h" +#include "string-util.h" +#include "syslog-util.h" +#include "terminal-util.h" +#include "unit-def.h" +#include "user-util.h" +#include "utf8.h" + +int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) { + assert(message); + assert(u); + + u->machine = NULL; + + return sd_bus_message_read( + message, + "(ssssssouso)", + &u->id, + &u->description, + &u->load_state, + &u->active_state, + &u->sub_state, + &u->following, + &u->unit_path, + &u->job_id, + &u->job_type, + &u->job_path); +} + +#define DEFINE_BUS_APPEND_PARSE_PTR(bus_type, cast_type, type, parse_func) \ + static int bus_append_##parse_func( \ + sd_bus_message *m, \ + const char *field, \ + const char *eq) { \ + type val; \ + int r; \ + \ + r = parse_func(eq, &val); \ + if (r < 0) \ + return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq); \ + \ + r = sd_bus_message_append(m, "(sv)", field, \ + bus_type, (cast_type) val); \ + if (r < 0) \ + return bus_log_create_error(r); \ + \ + return 1; \ + } + +#define DEFINE_BUS_APPEND_PARSE(bus_type, parse_func) \ + static int bus_append_##parse_func( \ + sd_bus_message *m, \ + const char *field, \ + const char *eq) { \ + int r; \ + \ + r = parse_func(eq); \ + if (r < 0) \ + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse %s: %s", field, eq); \ + \ + r = sd_bus_message_append(m, "(sv)", field, \ + bus_type, (int32_t) r); \ + if (r < 0) \ + return bus_log_create_error(r); \ + \ + return 1; \ + } + +DEFINE_BUS_APPEND_PARSE("b", parse_boolean); +DEFINE_BUS_APPEND_PARSE("i", ioprio_class_from_string); +DEFINE_BUS_APPEND_PARSE("i", ip_tos_from_string); +DEFINE_BUS_APPEND_PARSE("i", log_facility_unshifted_from_string); +DEFINE_BUS_APPEND_PARSE("i", log_level_from_string); +DEFINE_BUS_APPEND_PARSE("i", parse_errno); +DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string); +DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string); +DEFINE_BUS_APPEND_PARSE("i", signal_from_string); +DEFINE_BUS_APPEND_PARSE("i", parse_ip_protocol); +DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, ioprio_parse_priority); +DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, parse_nice); +DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, safe_atoi); +DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, nsec_t, parse_nsec); +DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_blkio_weight_parse); +DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_cpu_shares_parse); +DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, cg_weight_parse); +DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, unsigned long, mount_propagation_flags_from_string); +DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, safe_atou64); +DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, mode_t, parse_mode); +DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, unsigned, safe_atou); +DEFINE_BUS_APPEND_PARSE_PTR("x", int64_t, int64_t, safe_atoi64); + +static int bus_append_string(sd_bus_message *m, const char *field, const char *eq) { + int r; + + r = sd_bus_message_append(m, "(sv)", field, "s", eq); + if (r < 0) + return bus_log_create_error(r); + + return 1; +} + +static int bus_append_strv(sd_bus_message *m, const char *field, const char *eq, ExtractFlags flags) { + const char *p; + int r; + + r = sd_bus_message_open_container(m, 'r', "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(m, 's', field); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', "as"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return bus_log_create_error(r); + + for (p = eq;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, flags); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_error_errno(r, "Invalid syntax: %s", eq); + + r = sd_bus_message_append_basic(m, 's', word); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + return 1; +} + +static int bus_append_byte_array(sd_bus_message *m, const char *field, const void *buf, size_t n) { + int r; + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', "ay"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_array(m, 'y', buf, n); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + return 1; +} + +static int bus_append_parse_sec_rename(sd_bus_message *m, const char *field, const char *eq) { + char *n; + usec_t t; + size_t l; + int r; + + r = parse_sec(eq, &t); + if (r < 0) + return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq); + + l = strlen(field); + n = newa(char, l + 2); + /* Change suffix Sec → USec */ + strcpy(mempcpy(n, field, l - 3), "USec"); + + r = sd_bus_message_append(m, "(sv)", n, "t", t); + if (r < 0) + return bus_log_create_error(r); + + return 1; +} + +static int bus_append_parse_size(sd_bus_message *m, const char *field, const char *eq, uint64_t base) { + uint64_t v; + int r; + + r = parse_size(eq, base, &v); + if (r < 0) + return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq); + + r = sd_bus_message_append(m, "(sv)", field, "t", v); + if (r < 0) + return bus_log_create_error(r); + + return 1; +} + +static int bus_append_exec_command(sd_bus_message *m, const char *field, const char *eq) { + bool explicit_path = false, done = false; + _cleanup_strv_free_ char **l = NULL, **ex_opts = NULL; + _cleanup_free_ char *path = NULL, *upgraded_name = NULL; + ExecCommandFlags flags = 0; + bool is_ex_prop = endswith(field, "Ex"); + int r; + + do { + switch (*eq) { + + case '-': + if (FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE)) + done = true; + else { + flags |= EXEC_COMMAND_IGNORE_FAILURE; + eq++; + } + break; + + case '@': + if (explicit_path) + done = true; + else { + explicit_path = true; + eq++; + } + break; + + case ':': + if (FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND)) + done = true; + else { + flags |= EXEC_COMMAND_NO_ENV_EXPAND; + eq++; + } + break; + + case '+': + if (flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC)) + done = true; + else { + flags |= EXEC_COMMAND_FULLY_PRIVILEGED; + eq++; + } + break; + + case '!': + if (flags & (EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_AMBIENT_MAGIC)) + done = true; + else if (FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID)) { + flags &= ~EXEC_COMMAND_NO_SETUID; + flags |= EXEC_COMMAND_AMBIENT_MAGIC; + eq++; + } else { + flags |= EXEC_COMMAND_NO_SETUID; + eq++; + } + break; + + default: + done = true; + break; + } + } while (!done); + + if (!is_ex_prop && (flags & (EXEC_COMMAND_NO_ENV_EXPAND|EXEC_COMMAND_FULLY_PRIVILEGED|EXEC_COMMAND_NO_SETUID|EXEC_COMMAND_AMBIENT_MAGIC))) { + /* Upgrade the ExecXYZ= property to ExecXYZEx= for convenience */ + is_ex_prop = true; + upgraded_name = strjoin(field, "Ex"); + if (!upgraded_name) + return log_oom(); + } + + if (is_ex_prop) { + r = exec_command_flags_to_strv(flags, &ex_opts); + if (r < 0) + return log_error_errno(r, "Failed to convert ExecCommandFlags to strv: %m"); + } + + if (explicit_path) { + r = extract_first_word(&eq, &path, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE); + if (r < 0) + return log_error_errno(r, "Failed to parse path: %m"); + } + + r = strv_split_extract(&l, eq, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE); + if (r < 0) + return log_error_errno(r, "Failed to parse command line: %m"); + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, upgraded_name ?: field); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', is_ex_prop ? "a(sasas)" : "a(sasb)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', is_ex_prop ? "(sasas)" : "(sasb)"); + if (r < 0) + return bus_log_create_error(r); + + if (!strv_isempty(l)) { + + r = sd_bus_message_open_container(m, 'r', is_ex_prop ? "sasas" : "sasb"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", path ?: l[0]); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, l); + if (r < 0) + return bus_log_create_error(r); + + r = is_ex_prop ? sd_bus_message_append_strv(m, ex_opts) : sd_bus_message_append(m, "b", FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE)); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + return 1; +} + +static int bus_append_ip_address_access(sd_bus_message *m, int family, const union in_addr_union *prefix, unsigned char prefixlen) { + int r; + + assert(m); + assert(prefix); + + r = sd_bus_message_open_container(m, 'r', "iayu"); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "i", family); + if (r < 0) + return r; + + r = sd_bus_message_append_array(m, 'y', prefix, FAMILY_ADDRESS_SIZE(family)); + if (r < 0) + return r; + + r = sd_bus_message_append(m, "u", prefixlen); + if (r < 0) + return r; + + return sd_bus_message_close_container(m); +} + +static int bus_append_cgroup_property(sd_bus_message *m, const char *field, const char *eq) { + int r; + + if (STR_IN_SET(field, "DevicePolicy", "Slice")) + return bus_append_string(m, field, eq); + + if (STR_IN_SET(field, "CPUAccounting", + "MemoryAccounting", + "IOAccounting", + "BlockIOAccounting", + "TasksAccounting", + "IPAccounting")) + return bus_append_parse_boolean(m, field, eq); + + if (STR_IN_SET(field, "CPUWeight", + "StartupCPUWeight", + "IOWeight", + "StartupIOWeight")) + return bus_append_cg_weight_parse(m, field, eq); + + if (STR_IN_SET(field, "CPUShares", + "StartupCPUShares")) + return bus_append_cg_cpu_shares_parse(m, field, eq); + + if (STR_IN_SET(field, "AllowedCPUs", + "AllowedMemoryNodes")) { + _cleanup_(cpu_set_reset) CPUSet cpuset = {}; + _cleanup_free_ uint8_t *array = NULL; + size_t allocated; + + r = parse_cpu_set(eq, &cpuset); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value: %s", field, eq); + + r = cpu_set_to_dbus(&cpuset, &array, &allocated); + if (r < 0) + return log_error_errno(r, "Failed to serialize CPUSet: %m"); + + return bus_append_byte_array(m, field, array, allocated); + } + + if (STR_IN_SET(field, "BlockIOWeight", + "StartupBlockIOWeight")) + return bus_append_cg_blkio_weight_parse(m, field, eq); + + if (streq(field, "DisableControllers")) + return bus_append_strv(m, "DisableControllers", eq, EXTRACT_UNQUOTE); + + if (streq(field, "Delegate")) { + r = parse_boolean(eq); + if (r < 0) + return bus_append_strv(m, "DelegateControllers", eq, EXTRACT_UNQUOTE); + + r = sd_bus_message_append(m, "(sv)", "Delegate", "b", r); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (STR_IN_SET(field, "MemoryMin", + "DefaultMemoryLow", + "DefaultMemoryMin", + "MemoryLow", + "MemoryHigh", + "MemoryMax", + "MemorySwapMax", + "MemoryLimit", + "TasksMax")) { + + if (isempty(eq) || streq(eq, "infinity")) { + r = sd_bus_message_append(m, "(sv)", field, "t", CGROUP_LIMIT_MAX); + if (r < 0) + return bus_log_create_error(r); + return 1; + } + + r = parse_permille(eq); + if (r >= 0) { + char *n; + + /* When this is a percentage we'll convert this into a relative value in the range 0…UINT32_MAX + * and pass it in the MemoryLowScale property (and related ones). This way the physical memory + * size can be determined server-side. */ + + n = strjoina(field, "Scale"); + r = sd_bus_message_append(m, "(sv)", n, "u", (uint32_t) (((uint64_t) r * UINT32_MAX) / 1000U)); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "TasksMax")) + return bus_append_safe_atou64(m, field, eq); + + return bus_append_parse_size(m, field, eq, 1024); + } + + if (streq(field, "CPUQuota")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", USEC_INFINITY); + else { + r = parse_permille_unbounded(eq); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(ERANGE), + "CPU quota too small."); + if (r < 0) + return log_error_errno(r, "CPU quota '%s' invalid.", eq); + + r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", (((uint64_t) r * USEC_PER_SEC) / 1000U)); + } + + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "CPUQuotaPeriodSec")) { + usec_t u = USEC_INFINITY; + + r = parse_sec_def_infinity(eq, &u); + if (r < 0) + return log_error_errno(r, "CPU quota period '%s' invalid.", eq); + + r = sd_bus_message_append(m, "(sv)", "CPUQuotaPeriodUSec", "t", u); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "DeviceAllow")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 0); + else { + const char *path = eq, *rwm = NULL, *e; + + e = strchr(eq, ' '); + if (e) { + path = strndupa(eq, e - eq); + rwm = e+1; + } + + r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 1, path, strempty(rwm)); + } + + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (cgroup_io_limit_type_from_string(field) >= 0 || STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", field, "a(st)", 0); + else { + const char *path, *bandwidth, *e; + uint64_t bytes; + + e = strchr(eq, ' '); + if (!e) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse %s value %s.", + field, eq); + + path = strndupa(eq, e - eq); + bandwidth = e+1; + + if (streq(bandwidth, "infinity")) + bytes = CGROUP_LIMIT_MAX; + else { + r = parse_size(bandwidth, 1000, &bytes); + if (r < 0) + return log_error_errno(r, "Failed to parse byte value %s: %m", bandwidth); + } + + r = sd_bus_message_append(m, "(sv)", field, "a(st)", 1, path, bytes); + } + + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (STR_IN_SET(field, "IODeviceWeight", + "BlockIODeviceWeight")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", field, "a(st)", 0); + else { + const char *path, *weight, *e; + uint64_t u; + + e = strchr(eq, ' '); + if (!e) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse %s value %s.", + field, eq); + + path = strndupa(eq, e - eq); + weight = e+1; + + r = safe_atou64(weight, &u); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value %s: %m", field, weight); + + r = sd_bus_message_append(m, "(sv)", field, "a(st)", 1, path, u); + } + + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "IODeviceLatencyTargetSec")) { + const char *field_usec = "IODeviceLatencyTargetUSec"; + + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", field_usec, "a(st)", USEC_INFINITY); + else { + const char *path, *target, *e; + usec_t usec; + + e = strchr(eq, ' '); + if (!e) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse %s value %s.", + field, eq); + + path = strndupa(eq, e - eq); + target = e+1; + + r = parse_sec(target, &usec); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value %s: %m", field, target); + + r = sd_bus_message_append(m, "(sv)", field_usec, "a(st)", 1, path, usec); + } + + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (STR_IN_SET(field, "IPAddressAllow", + "IPAddressDeny")) { + unsigned char prefixlen; + union in_addr_union prefix = {}; + int family; + + if (isempty(eq)) { + r = sd_bus_message_append(m, "(sv)", field, "a(iayu)", 0); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', "a(iayu)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "(iayu)"); + if (r < 0) + return bus_log_create_error(r); + + if (streq(eq, "any")) { + /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */ + + r = bus_append_ip_address_access(m, AF_INET, &prefix, 0); + if (r < 0) + return bus_log_create_error(r); + + r = bus_append_ip_address_access(m, AF_INET6, &prefix, 0); + if (r < 0) + return bus_log_create_error(r); + + } else if (is_localhost(eq)) { + /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */ + + prefix.in.s_addr = htobe32(0x7f000000); + r = bus_append_ip_address_access(m, AF_INET, &prefix, 8); + if (r < 0) + return bus_log_create_error(r); + + prefix.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT; + r = bus_append_ip_address_access(m, AF_INET6, &prefix, 128); + if (r < 0) + return r; + + } else if (streq(eq, "link-local")) { + /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */ + + prefix.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16)); + r = bus_append_ip_address_access(m, AF_INET, &prefix, 16); + if (r < 0) + return bus_log_create_error(r); + + prefix.in6 = (struct in6_addr) { + .s6_addr32[0] = htobe32(0xfe800000) + }; + r = bus_append_ip_address_access(m, AF_INET6, &prefix, 64); + if (r < 0) + return bus_log_create_error(r); + + } else if (streq(eq, "multicast")) { + /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */ + + prefix.in.s_addr = htobe32((UINT32_C(224) << 24)); + r = bus_append_ip_address_access(m, AF_INET, &prefix, 4); + if (r < 0) + return bus_log_create_error(r); + + prefix.in6 = (struct in6_addr) { + .s6_addr32[0] = htobe32(0xff000000) + }; + r = bus_append_ip_address_access(m, AF_INET6, &prefix, 8); + if (r < 0) + return bus_log_create_error(r); + + } else { + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&eq, &word, NULL, 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_error_errno(r, "Failed to parse %s: %s", field, eq); + + r = in_addr_prefix_from_string_auto(word, &family, &prefix, &prefixlen); + if (r < 0) + return log_error_errno(r, "Failed to parse IP address prefix: %s", word); + + r = bus_append_ip_address_access(m, family, &prefix, prefixlen); + if (r < 0) + return bus_log_create_error(r); + } + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (STR_IN_SET(field, "IPIngressFilterPath", + "IPEgressFilterPath")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", field, "as", 0); + else + r = sd_bus_message_append(m, "(sv)", field, "as", 1, eq); + + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + return 0; +} + +static int bus_append_automount_property(sd_bus_message *m, const char *field, const char *eq) { + if (streq(field, "Where")) + return bus_append_string(m, field, eq); + + if (streq(field, "DirectoryMode")) + return bus_append_parse_mode(m, field, eq); + + if (streq(field, "TimeoutIdleSec")) + return bus_append_parse_sec_rename(m, field, eq); + + return 0; +} + +static int bus_append_execute_property(sd_bus_message *m, const char *field, const char *eq) { + const char *suffix; + int r; + + if (STR_IN_SET(field, "User", + "Group", + "UtmpIdentifier", + "UtmpMode", + "PAMName", + "TTYPath", + "WorkingDirectory", + "RootDirectory", + "SyslogIdentifier", + "ProtectSystem", + "ProtectHome", + "SELinuxContext", + "RootImage", + "RuntimeDirectoryPreserve", + "Personality", + "KeyringMode", + "NetworkNamespacePath")) + return bus_append_string(m, field, eq); + + if (STR_IN_SET(field, "IgnoreSIGPIPE", + "TTYVHangup", + "TTYReset", + "TTYVTDisallocate", + "PrivateTmp", + "PrivateDevices", + "PrivateNetwork", + "PrivateUsers", + "PrivateMounts", + "NoNewPrivileges", + "SyslogLevelPrefix", + "MemoryDenyWriteExecute", + "RestrictRealtime", + "DynamicUser", + "RemoveIPC", + "ProtectKernelTunables", + "ProtectKernelModules", + "ProtectKernelLogs", + "ProtectControlGroups", + "MountAPIVFS", + "CPUSchedulingResetOnFork", + "LockPersonality", + "ProtectHostname", + "RestrictSUIDSGID")) + return bus_append_parse_boolean(m, field, eq); + + if (STR_IN_SET(field, "ReadWriteDirectories", + "ReadOnlyDirectories", + "InaccessibleDirectories", + "ReadWritePaths", + "ReadOnlyPaths", + "InaccessiblePaths", + "RuntimeDirectory", + "StateDirectory", + "CacheDirectory", + "LogsDirectory", + "ConfigurationDirectory", + "SupplementaryGroups", + "SystemCallArchitectures")) + return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE); + + if (STR_IN_SET(field, "SyslogLevel", + "LogLevelMax")) + return bus_append_log_level_from_string(m, field, eq); + + if (streq(field, "SyslogFacility")) + return bus_append_log_facility_unshifted_from_string(m, field, eq); + + if (streq(field, "SecureBits")) + return bus_append_secure_bits_from_string(m, field, eq); + + if (streq(field, "CPUSchedulingPolicy")) + return bus_append_sched_policy_from_string(m, field, eq); + + if (STR_IN_SET(field, "CPUSchedulingPriority", + "OOMScoreAdjust")) + return bus_append_safe_atoi(m, field, eq); + + if (streq(field, "Nice")) + return bus_append_parse_nice(m, field, eq); + + if (streq(field, "SystemCallErrorNumber")) + return bus_append_parse_errno(m, field, eq); + + if (streq(field, "IOSchedulingClass")) + return bus_append_ioprio_class_from_string(m, field, eq); + + if (streq(field, "IOSchedulingPriority")) + return bus_append_ioprio_parse_priority(m, field, eq); + + if (STR_IN_SET(field, "RuntimeDirectoryMode", + "StateDirectoryMode", + "CacheDirectoryMode", + "LogsDirectoryMode", + "ConfigurationDirectoryMode", + "UMask")) + return bus_append_parse_mode(m, field, eq); + + if (streq(field, "TimerSlackNSec")) + return bus_append_parse_nsec(m, field, eq); + + if (streq(field, "LogRateLimitIntervalSec")) + return bus_append_parse_sec_rename(m, field, eq); + + if (streq(field, "LogRateLimitBurst")) + return bus_append_safe_atou(m, field, eq); + + if (streq(field, "MountFlags")) + return bus_append_mount_propagation_flags_from_string(m, field, eq); + + if (STR_IN_SET(field, "Environment", + "UnsetEnvironment", + "PassEnvironment")) + return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE); + + if (streq(field, "EnvironmentFile")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", "EnvironmentFiles", "a(sb)", 0); + else + r = sd_bus_message_append(m, "(sv)", "EnvironmentFiles", "a(sb)", 1, + eq[0] == '-' ? eq + 1 : eq, + eq[0] == '-'); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "LogExtraFields")) { + r = sd_bus_message_open_container(m, 'r', "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(m, 's', "LogExtraFields"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', "aay"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "ay"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_array(m, 'y', eq, strlen(eq)); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (STR_IN_SET(field, "StandardInput", + "StandardOutput", + "StandardError")) { + const char *n, *appended; + + if ((n = startswith(eq, "fd:"))) { + appended = strjoina(field, "FileDescriptorName"); + r = sd_bus_message_append(m, "(sv)", appended, "s", n); + } else if ((n = startswith(eq, "file:"))) { + appended = strjoina(field, "File"); + r = sd_bus_message_append(m, "(sv)", appended, "s", n); + } else if ((n = startswith(eq, "append:"))) { + appended = strjoina(field, "FileToAppend"); + r = sd_bus_message_append(m, "(sv)", appended, "s", n); + } else + r = sd_bus_message_append(m, "(sv)", field, "s", eq); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "StandardInputText")) { + _cleanup_free_ char *unescaped = NULL; + + r = cunescape(eq, 0, &unescaped); + if (r < 0) + return log_error_errno(r, "Failed to unescape text '%s': %m", eq); + + if (!strextend(&unescaped, "\n", NULL)) + return log_oom(); + + /* Note that we don't expand specifiers here, but that should be OK, as this is a programmatic + * interface anyway */ + + return bus_append_byte_array(m, field, unescaped, strlen(unescaped)); + } + + if (streq(field, "StandardInputData")) { + _cleanup_free_ void *decoded = NULL; + size_t sz; + + r = unbase64mem(eq, (size_t) -1, &decoded, &sz); + if (r < 0) + return log_error_errno(r, "Failed to decode base64 data '%s': %m", eq); + + return bus_append_byte_array(m, field, decoded, sz); + } + + if ((suffix = startswith(field, "Limit"))) { + int rl; + + rl = rlimit_from_string(suffix); + if (rl >= 0) { + const char *sn; + struct rlimit l; + + r = rlimit_parse(rl, eq, &l); + if (r < 0) + return log_error_errno(r, "Failed to parse resource limit: %s", eq); + + r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max); + if (r < 0) + return bus_log_create_error(r); + + sn = strjoina(field, "Soft"); + r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + } + + if (STR_IN_SET(field, "AppArmorProfile", + "SmackProcessLabel")) { + int ignore = 0; + const char *s = eq; + + if (eq[0] == '-') { + ignore = 1; + s = eq + 1; + } + + r = sd_bus_message_append(m, "(sv)", field, "(bs)", ignore, s); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (STR_IN_SET(field, "CapabilityBoundingSet", + "AmbientCapabilities")) { + uint64_t sum = 0; + bool invert = false; + const char *p = eq; + + if (*p == '~') { + invert = true; + p++; + } + + r = capability_set_from_string(p, &sum); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value %s: %m", field, eq); + + sum = invert ? ~sum : sum; + + r = sd_bus_message_append(m, "(sv)", field, "t", sum); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "CPUAffinity")) { + _cleanup_(cpu_set_reset) CPUSet cpuset = {}; + _cleanup_free_ uint8_t *array = NULL; + size_t allocated; + + r = parse_cpu_set(eq, &cpuset); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value: %s", field, eq); + + r = cpu_set_to_dbus(&cpuset, &array, &allocated); + if (r < 0) + return log_error_errno(r, "Failed to serialize CPUAffinity: %m"); + + return bus_append_byte_array(m, field, array, allocated); + } + + if (streq(field, "NUMAPolicy")) { + r = mpol_from_string(eq); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value: %s", field, eq); + + r = sd_bus_message_append(m, "(sv)", field, "i", (int32_t) r); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "NUMAMask")) { + _cleanup_(cpu_set_reset) CPUSet nodes = {}; + _cleanup_free_ uint8_t *array = NULL; + size_t allocated; + + r = parse_cpu_set(eq, &nodes); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value: %s", field, eq); + + r = cpu_set_to_dbus(&nodes, &array, &allocated); + if (r < 0) + return log_error_errno(r, "Failed to serialize NUMAMask: %m"); + + return bus_append_byte_array(m, field, array, allocated); + } + + if (STR_IN_SET(field, "RestrictAddressFamilies", + "SystemCallFilter")) { + int whitelist = 1; + const char *p = eq; + + if (*p == '~') { + whitelist = 0; + p++; + } + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', "(bas)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'r', "bas"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(m, 'b', &whitelist); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return bus_log_create_error(r); + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_error_errno(r, "Invalid syntax: %s", eq); + + r = sd_bus_message_append_basic(m, 's', word); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "RestrictNamespaces")) { + bool invert = false; + unsigned long flags; + + r = parse_boolean(eq); + if (r > 0) + flags = 0; + else if (r == 0) + flags = NAMESPACE_FLAGS_ALL; + else { + if (eq[0] == '~') { + invert = true; + eq++; + } + + r = namespace_flags_from_string(eq, &flags); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value %s.", field, eq); + } + + if (invert) + flags = (~flags) & NAMESPACE_FLAGS_ALL; + + r = sd_bus_message_append(m, "(sv)", field, "t", (uint64_t) flags); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (STR_IN_SET(field, "BindPaths", + "BindReadOnlyPaths")) { + const char *p = eq; + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', "a(ssbt)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "(ssbt)"); + if (r < 0) + return bus_log_create_error(r); + + for (;;) { + _cleanup_free_ char *source = NULL, *destination = NULL; + char *s = NULL, *d = NULL; + bool ignore_enoent = false; + uint64_t flags = MS_REC; + + r = extract_first_word(&p, &source, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return log_error_errno(r, "Failed to parse argument: %m"); + if (r == 0) + break; + + s = source; + if (s[0] == '-') { + ignore_enoent = true; + s++; + } + + if (p && p[-1] == ':') { + r = extract_first_word(&p, &destination, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return log_error_errno(r, "Failed to parse argument: %m"); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Missing argument after ':': %s", + eq); + + d = destination; + + if (p && p[-1] == ':') { + _cleanup_free_ char *options = NULL; + + r = extract_first_word(&p, &options, NULL, EXTRACT_UNQUOTE); + if (r < 0) + return log_error_errno(r, "Failed to parse argument: %m"); + + if (isempty(options) || streq(options, "rbind")) + flags = MS_REC; + else if (streq(options, "norbind")) + flags = 0; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown options: %s", + eq); + } + } else + d = s; + + r = sd_bus_message_append(m, "(ssbt)", s, d, ignore_enoent, flags); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "TemporaryFileSystem")) { + const char *p = eq; + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', "a(ss)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "(ss)"); + if (r < 0) + return bus_log_create_error(r); + + for (;;) { + _cleanup_free_ char *word = NULL, *path = NULL; + const char *w; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r < 0) + return log_error_errno(r, "Failed to parse argument: %m"); + if (r == 0) + break; + + w = word; + r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + if (r < 0) + return log_error_errno(r, "Failed to parse argument: %m"); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse argument: %s", + p); + + r = sd_bus_message_append(m, "(ss)", path, w); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + return 0; +} + +static int bus_append_kill_property(sd_bus_message *m, const char *field, const char *eq) { + if (streq(field, "KillMode")) + return bus_append_string(m, field, eq); + + if (STR_IN_SET(field, "SendSIGHUP", + "SendSIGKILL")) + return bus_append_parse_boolean(m, field, eq); + + if (STR_IN_SET(field, "KillSignal", + "RestartKillSignal", + "FinalKillSignal", + "WatchdogSignal")) + return bus_append_signal_from_string(m, field, eq); + + return 0; +} + +static int bus_append_mount_property(sd_bus_message *m, const char *field, const char *eq) { + + if (STR_IN_SET(field, "What", + "Where", + "Options", + "Type")) + return bus_append_string(m, field, eq); + + if (streq(field, "TimeoutSec")) + return bus_append_parse_sec_rename(m, field, eq); + + if (streq(field, "DirectoryMode")) + return bus_append_parse_mode(m, field, eq); + + if (STR_IN_SET(field, "SloppyOptions", + "LazyUnmount", + "ForceUnmount")) + return bus_append_parse_boolean(m, field, eq); + + return 0; +} + +static int bus_append_path_property(sd_bus_message *m, const char *field, const char *eq) { + int r; + + if (streq(field, "MakeDirectory")) + return bus_append_parse_boolean(m, field, eq); + + if (streq(field, "DirectoryMode")) + return bus_append_parse_mode(m, field, eq); + + if (STR_IN_SET(field, "PathExists", + "PathExistsGlob", + "PathChanged", + "PathModified", + "DirectoryNotEmpty")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", "Paths", "a(ss)", 0); + else + r = sd_bus_message_append(m, "(sv)", "Paths", "a(ss)", 1, field, eq); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + return 0; +} + +static int bus_append_scope_property(sd_bus_message *m, const char *field, const char *eq) { + if (streq(field, "RuntimeMaxSec")) + return bus_append_parse_sec_rename(m, field, eq); + + if (streq(field, "TimeoutStopSec")) + return bus_append_parse_sec_rename(m, field, eq); + + return 0; +} + +static int bus_append_service_property(sd_bus_message *m, const char *field, const char *eq) { + int r; + + if (STR_IN_SET(field, "PIDFile", + "Type", + "Restart", + "BusName", + "NotifyAccess", + "USBFunctionDescriptors", + "USBFunctionStrings", + "OOMPolicy")) + return bus_append_string(m, field, eq); + + if (STR_IN_SET(field, "PermissionsStartOnly", + "RootDirectoryStartOnly", + "RemainAfterExit", + "GuessMainPID")) + return bus_append_parse_boolean(m, field, eq); + + if (STR_IN_SET(field, "RestartSec", + "TimeoutStartSec", + "TimeoutStopSec", + "TimeoutAbortSec", + "RuntimeMaxSec", + "WatchdogSec")) + return bus_append_parse_sec_rename(m, field, eq); + + if (streq(field, "TimeoutSec")) { + r = bus_append_parse_sec_rename(m, "TimeoutStartSec", eq); + if (r < 0) + return r; + + return bus_append_parse_sec_rename(m, "TimeoutStopSec", eq); + } + + if (streq(field, "FileDescriptorStoreMax")) + return bus_append_safe_atou(m, field, eq); + + if (STR_IN_SET(field, "ExecCondition", + "ExecStartPre", + "ExecStart", + "ExecStartPost", + "ExecConditionEx", + "ExecStartPreEx", + "ExecStartEx", + "ExecStartPostEx", + "ExecReload", + "ExecStop", + "ExecStopPost", + "ExecReloadEx", + "ExecStopEx", + "ExecStopPostEx")) + return bus_append_exec_command(m, field, eq); + + if (STR_IN_SET(field, "RestartPreventExitStatus", + "RestartForceExitStatus", + "SuccessExitStatus")) { + _cleanup_free_ int *status = NULL, *signal = NULL; + size_t n_status = 0, n_signal = 0; + const char *p; + + for (p = eq;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_error_errno(r, "Invalid syntax in %s: %s", field, eq); + + /* We need to call exit_status_from_string() first, because we want + * to parse numbers as exit statuses, not signals. */ + + r = exit_status_from_string(word); + if (r >= 0) { + assert(r >= 0 && r < 256); + + status = reallocarray(status, n_status + 1, sizeof(int)); + if (!status) + return log_oom(); + + status[n_status++] = r; + + } else if ((r = signal_from_string(word)) >= 0) { + signal = reallocarray(signal, n_signal + 1, sizeof(int)); + if (!signal) + return log_oom(); + + signal[n_signal++] = r; + + } else + /* original r from exit_status_to_string() */ + return log_error_errno(r, "Invalid status or signal %s in %s: %m", + word, field); + } + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'v', "(aiai)"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'r', "aiai"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_array(m, 'i', status, n_status * sizeof(int)); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_array(m, 'i', signal, n_signal * sizeof(int)); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + return 0; +} + +static int bus_append_socket_property(sd_bus_message *m, const char *field, const char *eq) { + int r; + + if (STR_IN_SET(field, "Accept", + "Writable", + "KeepAlive", + "NoDelay", + "FreeBind", + "Transparent", + "Broadcast", + "PassCredentials", + "PassSecurity", + "ReusePort", + "RemoveOnStop", + "SELinuxContextFromNet")) + return bus_append_parse_boolean(m, field, eq); + + if (STR_IN_SET(field, "Priority", + "IPTTL", + "Mark")) + return bus_append_safe_atoi(m, field, eq); + + if (streq(field, "IPTOS")) + return bus_append_ip_tos_from_string(m, field, eq); + + if (STR_IN_SET(field, "Backlog", + "MaxConnections", + "MaxConnectionsPerSource", + "KeepAliveProbes", + "TriggerLimitBurst")) + return bus_append_safe_atou(m, field, eq); + + if (STR_IN_SET(field, "SocketMode", + "DirectoryMode")) + return bus_append_parse_mode(m, field, eq); + + if (STR_IN_SET(field, "MessageQueueMaxMessages", + "MessageQueueMessageSize")) + return bus_append_safe_atoi64(m, field, eq); + + if (STR_IN_SET(field, "TimeoutSec", + "KeepAliveTimeSec", + "KeepAliveIntervalSec", + "DeferAcceptSec", + "TriggerLimitIntervalSec")) + return bus_append_parse_sec_rename(m, field, eq); + + if (STR_IN_SET(field, "ReceiveBuffer", + "SendBuffer", + "PipeSize")) + return bus_append_parse_size(m, field, eq, 1024); + + if (STR_IN_SET(field, "ExecStartPre", + "ExecStartPost", + "ExecReload", + "ExecStopPost")) + return bus_append_exec_command(m, field, eq); + + if (STR_IN_SET(field, "SmackLabel", + "SmackLabelIPIn", + "SmackLabelIPOut", + "TCPCongestion", + "BindToDevice", + "BindIPv6Only", + "FileDescriptorName", + "SocketUser", + "SocketGroup")) + return bus_append_string(m, field, eq); + + if (streq(field, "Symlinks")) + return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE); + + if (streq(field, "SocketProtocol")) + return bus_append_parse_ip_protocol(m, field, eq); + + if (STR_IN_SET(field, "ListenStream", + "ListenDatagram", + "ListenSequentialPacket", + "ListenNetlink", + "ListenSpecial", + "ListenMessageQueue", + "ListenFIFO", + "ListenUSBFunction")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", "Listen", "a(ss)", 0); + else + r = sd_bus_message_append(m, "(sv)", "Listen", "a(ss)", 1, field + STRLEN("Listen"), eq); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + return 0; +} +static int bus_append_timer_property(sd_bus_message *m, const char *field, const char *eq) { + int r; + + if (STR_IN_SET(field, "WakeSystem", + "RemainAfterElapse", + "Persistent", + "OnTimezoneChange", + "OnClockChange")) + return bus_append_parse_boolean(m, field, eq); + + if (STR_IN_SET(field, "AccuracySec", + "RandomizedDelaySec")) + return bus_append_parse_sec_rename(m, field, eq); + + if (STR_IN_SET(field, "OnActiveSec", + "OnBootSec", + "OnStartupSec", + "OnUnitActiveSec", + "OnUnitInactiveSec")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", "TimersMonotonic", "a(st)", 0); + else { + usec_t t; + r = parse_sec(eq, &t); + if (r < 0) + return log_error_errno(r, "Failed to parse %s=%s: %m", field, eq); + + r = sd_bus_message_append(m, "(sv)", "TimersMonotonic", "a(st)", 1, field, t); + } + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (streq(field, "OnCalendar")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", "TimersCalendar", "a(ss)", 0); + else + r = sd_bus_message_append(m, "(sv)", "TimersCalendar", "a(ss)", 1, field, eq); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + return 0; +} + +static int bus_append_unit_property(sd_bus_message *m, const char *field, const char *eq) { + ConditionType t = _CONDITION_TYPE_INVALID; + bool is_condition = false; + int r; + + if (STR_IN_SET(field, "Description", + "SourcePath", + "OnFailureJobMode", + "JobTimeoutAction", + "JobTimeoutRebootArgument", + "StartLimitAction", + "FailureAction", + "SuccessAction", + "RebootArgument", + "CollectMode")) + return bus_append_string(m, field, eq); + + if (STR_IN_SET(field, "StopWhenUnneeded", + "RefuseManualStart", + "RefuseManualStop", + "AllowIsolate", + "IgnoreOnIsolate", + "DefaultDependencies")) + return bus_append_parse_boolean(m, field, eq); + + if (STR_IN_SET(field, "JobTimeoutSec", + "JobRunningTimeoutSec", + "StartLimitIntervalSec")) + return bus_append_parse_sec_rename(m, field, eq); + + if (streq(field, "StartLimitBurst")) + return bus_append_safe_atou(m, field, eq); + + if (STR_IN_SET(field, "SuccessActionExitStatus", + "FailureActionExitStatus")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", field, "i", -1); + else { + uint8_t u; + + r = safe_atou8(eq, &u); + if (r < 0) + return log_error_errno(r, "Failed to parse %s=%s", field, eq); + + r = sd_bus_message_append(m, "(sv)", field, "i", (int) u); + } + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + if (unit_dependency_from_string(field) >= 0 || + STR_IN_SET(field, "Documentation", + "RequiresMountsFor")) + return bus_append_strv(m, field, eq, EXTRACT_UNQUOTE); + + t = condition_type_from_string(field); + if (t >= 0) + is_condition = true; + else + t = assert_type_from_string(field); + if (t >= 0) { + if (isempty(eq)) + r = sd_bus_message_append(m, "(sv)", is_condition ? "Conditions" : "Asserts", "a(sbbs)", 0); + else { + const char *p = eq; + int trigger, negate; + + trigger = *p == '|'; + if (trigger) + p++; + + negate = *p == '!'; + if (negate) + p++; + + r = sd_bus_message_append(m, "(sv)", is_condition ? "Conditions" : "Asserts", "a(sbbs)", 1, + field, trigger, negate, p); + } + if (r < 0) + return bus_log_create_error(r); + + return 1; + } + + return 0; +} + +int bus_append_unit_property_assignment(sd_bus_message *m, UnitType t, const char *assignment) { + const char *eq, *field; + int r; + + assert(m); + assert(assignment); + + eq = strchr(assignment, '='); + if (!eq) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Not an assignment: %s", assignment); + + field = strndupa(assignment, eq - assignment); + eq++; + + switch (t) { + case UNIT_SERVICE: + r = bus_append_cgroup_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_execute_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_kill_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_service_property(m, field, eq); + if (r != 0) + return r; + break; + + case UNIT_SOCKET: + r = bus_append_cgroup_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_execute_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_kill_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_socket_property(m, field, eq); + if (r != 0) + return r; + break; + + case UNIT_TIMER: + r = bus_append_timer_property(m, field, eq); + if (r != 0) + return r; + break; + + case UNIT_PATH: + r = bus_append_path_property(m, field, eq); + if (r != 0) + return r; + break; + + case UNIT_SLICE: + r = bus_append_cgroup_property(m, field, eq); + if (r != 0) + return r; + break; + + case UNIT_SCOPE: + r = bus_append_cgroup_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_kill_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_scope_property(m, field, eq); + if (r != 0) + return r; + break; + + case UNIT_MOUNT: + r = bus_append_cgroup_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_execute_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_kill_property(m, field, eq); + if (r != 0) + return r; + + r = bus_append_mount_property(m, field, eq); + if (r != 0) + return r; + + break; + + case UNIT_AUTOMOUNT: + r = bus_append_automount_property(m, field, eq); + if (r != 0) + return r; + + break; + + case UNIT_TARGET: + case UNIT_DEVICE: + case UNIT_SWAP: + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Not supported unit type"); + + default: + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid unit type"); + } + + r = bus_append_unit_property(m, field, eq); + if (r != 0) + return r; + + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown assignment: %s", assignment); +} + +int bus_append_unit_property_assignment_many(sd_bus_message *m, UnitType t, char **l) { + char **i; + int r; + + assert(m); + + STRV_FOREACH(i, l) { + r = bus_append_unit_property_assignment(m, t, *i); + if (r < 0) + return r; + } + + return 0; +} + +int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, size_t *n_changes) { + const char *type, *path, *source; + int r; + + /* changes is dereferenced when calling unit_file_dump_changes() later, + * so we have to make sure this is not NULL. */ + assert(changes); + assert(n_changes); + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) { + /* We expect only "success" changes to be sent over the bus. + Hence, reject anything negative. */ + UnitFileChangeType ch = unit_file_change_type_from_string(type); + + if (ch < 0) { + log_notice("Manager reported unknown change type \"%s\" for path \"%s\", ignoring.", type, path); + continue; + } + + r = unit_file_changes_add(changes, n_changes, ch, path, source); + if (r < 0) + return r; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + unit_file_dump_changes(0, NULL, *changes, *n_changes, quiet); + return 0; +} + +int unit_load_state(sd_bus *bus, const char *name, char **load_state) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + int r; + + path = unit_dbus_path_from_name(name); + if (!path) + return log_oom(); + + /* This function warns on it's own, because otherwise it'd be awkward to pass + * the dbus error message around. */ + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + "LoadState", + &error, + load_state); + if (r < 0) + return log_error_errno(r, "Failed to get load state of %s: %s", name, bus_error_message(&error, r)); + + return 0; +} diff --git a/src/shared/bus-unit-util.h b/src/shared/bus-unit-util.h new file mode 100644 index 00000000..a0b496f6 --- /dev/null +++ b/src/shared/bus-unit-util.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" + +#include "install.h" +#include "unit-def.h" + +typedef struct UnitInfo { + const char *machine; + const char *id; + const char *description; + const char *load_state; + const char *active_state; + const char *sub_state; + const char *following; + const char *unit_path; + uint32_t job_id; + const char *job_type; + const char *job_path; +} UnitInfo; + +int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u); + +int bus_append_unit_property_assignment(sd_bus_message *m, UnitType t, const char *assignment); +int bus_append_unit_property_assignment_many(sd_bus_message *m, UnitType t, char **l); + +int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, size_t *n_changes); + +int unit_load_state(sd_bus *bus, const char *name, char **load_state); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c new file mode 100644 index 00000000..7bab9458 --- /dev/null +++ b/src/shared/bus-util.c @@ -0,0 +1,1412 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-daemon.h" +#include "sd-event.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "bus-internal.h" +#include "bus-label.h" +#include "bus-message.h" +#include "bus-util.h" +#include "cap-list.h" +#include "cgroup-util.h" +#include "mountpoint-util.h" +#include "nsflags.h" +#include "parse-util.h" +#include "path-util.h" +#include "rlimit-util.h" +#include "socket-util.h" +#include "stdio-util.h" +#include "strv.h" +#include "user-util.h" + +static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + sd_event *e = userdata; + + assert(m); + assert(e); + + sd_bus_close(sd_bus_message_get_bus(m)); + sd_event_exit(e, 0); + + return 1; +} + +int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) { + const char *match; + const char *unique; + int r; + + assert(e); + assert(bus); + assert(name); + + /* We unregister the name here and then wait for the + * NameOwnerChanged signal for this event to arrive before we + * quit. We do this in order to make sure that any queued + * requests are still processed before we really exit. */ + + r = sd_bus_get_unique_name(bus, &unique); + if (r < 0) + return r; + + match = strjoina( + "sender='org.freedesktop.DBus'," + "type='signal'," + "interface='org.freedesktop.DBus'," + "member='NameOwnerChanged'," + "path='/org/freedesktop/DBus'," + "arg0='", name, "',", + "arg1='", unique, "',", + "arg2=''"); + + r = sd_bus_add_match_async(bus, NULL, match, name_owner_change_callback, NULL, e); + if (r < 0) + return r; + + r = sd_bus_release_name_async(bus, NULL, name, NULL, NULL); + if (r < 0) + return r; + + return 0; +} + +int bus_event_loop_with_idle( + sd_event *e, + sd_bus *bus, + const char *name, + usec_t timeout, + check_idle_t check_idle, + void *userdata) { + bool exiting = false; + int r, code; + + assert(e); + assert(bus); + assert(name); + + for (;;) { + bool idle; + + r = sd_event_get_state(e); + if (r < 0) + return r; + if (r == SD_EVENT_FINISHED) + break; + + if (check_idle) + idle = check_idle(userdata); + else + idle = true; + + r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout); + if (r < 0) + return r; + + if (r == 0 && !exiting && idle) { + + r = sd_bus_try_close(bus); + if (r == -EBUSY) + continue; + + /* Fallback for dbus1 connections: we + * unregister the name and wait for the + * response to come through for it */ + if (r == -EOPNOTSUPP) { + + /* Inform the service manager that we + * are going down, so that it will + * queue all further start requests, + * instead of assuming we are already + * running. */ + sd_notify(false, "STOPPING=1"); + + r = bus_async_unregister_and_exit(e, bus, name); + if (r < 0) + return r; + + exiting = true; + continue; + } + + if (r < 0) + return r; + + sd_event_exit(e, 0); + break; + } + } + + r = sd_event_get_exit_code(e, &code); + if (r < 0) + return r; + + return code; +} + +int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL; + int r, has_owner = 0; + + assert(c); + assert(name); + + r = sd_bus_call_method(c, + "org.freedesktop.DBus", + "/org/freedesktop/dbus", + "org.freedesktop.DBus", + "NameHasOwner", + error, + &rep, + "s", + name); + if (r < 0) + return r; + + r = sd_bus_message_read_basic(rep, 'b', &has_owner); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + return has_owner; +} + +int bus_check_peercred(sd_bus *c) { + struct ucred ucred; + int fd, r; + + assert(c); + + fd = sd_bus_get_fd(c); + if (fd < 0) + return fd; + + r = getpeercred(fd, &ucred); + if (r < 0) + return r; + + if (ucred.uid != 0 && ucred.uid != geteuid()) + return -EPERM; + + return 1; +} + +int bus_connect_system_systemd(sd_bus **_bus) { + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; + int r; + + assert(_bus); + + if (geteuid() != 0) + return sd_bus_default_system(_bus); + + /* If we are root then let's talk directly to the system + * instance, instead of going via the bus */ + + r = sd_bus_new(&bus); + if (r < 0) + return r; + + r = sd_bus_set_address(bus, "unix:path=/run/systemd/private"); + if (r < 0) + return r; + + r = sd_bus_start(bus); + if (r < 0) + return sd_bus_default_system(_bus); + + r = bus_check_peercred(bus); + if (r < 0) + return r; + + *_bus = TAKE_PTR(bus); + + return 0; +} + +int bus_connect_user_systemd(sd_bus **_bus) { + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *ee = NULL; + const char *e; + int r; + + assert(_bus); + + e = secure_getenv("XDG_RUNTIME_DIR"); + if (!e) + return sd_bus_default_user(_bus); + + ee = bus_address_escape(e); + if (!ee) + return -ENOMEM; + + r = sd_bus_new(&bus); + if (r < 0) + return r; + + bus->address = strjoin("unix:path=", ee, "/systemd/private"); + if (!bus->address) + return -ENOMEM; + + r = sd_bus_start(bus); + if (r < 0) + return sd_bus_default_user(_bus); + + r = bus_check_peercred(bus); + if (r < 0) + return r; + + *_bus = TAKE_PTR(bus); + + return 0; +} + +int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *value) { + assert(name); + + if (expected_value && !streq_ptr(expected_value, value)) + return 0; + + if (only_value) + puts(value); + else + printf("%s=%s\n", name, value); + + return 0; +} + +int bus_print_property_valuef(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) { + va_list ap; + int r; + + assert(name); + assert(fmt); + + if (expected_value) { + _cleanup_free_ char *s = NULL; + + va_start(ap, fmt); + r = vasprintf(&s, fmt, ap); + va_end(ap); + if (r < 0) + return -ENOMEM; + + if (streq_ptr(expected_value, s)) { + if (only_value) + puts(s); + else + printf("%s=%s\n", name, s); + } + + return 0; + } + + if (!only_value) + printf("%s=", name); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + puts(""); + + return 0; +} + +static int bus_print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) { + char type; + const char *contents; + int r; + + assert(name); + assert(m); + + r = sd_bus_message_peek_type(m, &type, &contents); + if (r < 0) + return r; + + switch (type) { + + case SD_BUS_TYPE_STRING: { + const char *s; + + r = sd_bus_message_read_basic(m, type, &s); + if (r < 0) + return r; + + if (all || !isempty(s)) { + bool good; + + /* This property has a single value, so we need to take + * care not to print a new line, everything else is OK. */ + good = !strchr(s, '\n'); + bus_print_property_value(name, expected_value, value, good ? s : "[unprintable]"); + } + + return 1; + } + + case SD_BUS_TYPE_BOOLEAN: { + int b; + + r = sd_bus_message_read_basic(m, type, &b); + if (r < 0) + return r; + + if (expected_value && parse_boolean(expected_value) != b) + return 1; + + bus_print_property_value(name, NULL, value, yes_no(b)); + return 1; + } + + case SD_BUS_TYPE_UINT64: { + uint64_t u; + + r = sd_bus_message_read_basic(m, type, &u); + if (r < 0) + return r; + + /* Yes, heuristics! But we can change this check + * should it turn out to not be sufficient */ + + if (endswith(name, "Timestamp") || + STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec", "TimeUSec", "RTCTimeUSec")) { + char timestamp[FORMAT_TIMESTAMP_MAX]; + const char *t; + + t = format_timestamp(timestamp, sizeof(timestamp), u); + if (t || all) + bus_print_property_value(name, expected_value, value, strempty(t)); + + } else if (strstr(name, "USec")) { + char timespan[FORMAT_TIMESPAN_MAX]; + + (void) format_timespan(timespan, sizeof(timespan), u, 0); + bus_print_property_value(name, expected_value, value, timespan); + + } else if (streq(name, "RestrictNamespaces")) { + _cleanup_free_ char *s = NULL; + const char *result; + + if ((u & NAMESPACE_FLAGS_ALL) == 0) + result = "yes"; + else if (FLAGS_SET(u, NAMESPACE_FLAGS_ALL)) + result = "no"; + else { + r = namespace_flags_to_string(u, &s); + if (r < 0) + return r; + + result = s; + } + + bus_print_property_value(name, expected_value, value, result); + + } else if (streq(name, "MountFlags")) { + const char *result; + + result = mount_propagation_flags_to_string(u); + if (!result) + return -EINVAL; + + bus_print_property_value(name, expected_value, value, result); + + } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) { + _cleanup_free_ char *s = NULL; + + r = capability_set_to_string_alloc(u, &s); + if (r < 0) + return r; + + bus_print_property_value(name, expected_value, value, s); + + } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) || + (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) || + (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) || + (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == (uint64_t) -1) || + (endswith(name, "NSec") && u == (uint64_t) -1)) + + bus_print_property_value(name, expected_value, value, "[not set]"); + + else if ((STR_IN_SET(name, "DefaultMemoryLow", "DefaultMemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) || + (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) || + (startswith(name, "Limit") && u == (uint64_t) -1) || + (startswith(name, "DefaultLimit") && u == (uint64_t) -1)) + + bus_print_property_value(name, expected_value, value, "infinity"); + else if (STR_IN_SET(name, "IPIngressBytes", "IPIngressPackets", "IPEgressBytes", "IPEgressPackets") && u == (uint64_t) -1) + bus_print_property_value(name, expected_value, value, "[no data]"); + else + bus_print_property_valuef(name, expected_value, value, "%"PRIu64, u); + + return 1; + } + + case SD_BUS_TYPE_INT64: { + int64_t i; + + r = sd_bus_message_read_basic(m, type, &i); + if (r < 0) + return r; + + bus_print_property_valuef(name, expected_value, value, "%"PRIi64, i); + return 1; + } + + case SD_BUS_TYPE_UINT32: { + uint32_t u; + + r = sd_bus_message_read_basic(m, type, &u); + if (r < 0) + return r; + + if (strstr(name, "UMask") || strstr(name, "Mode")) + bus_print_property_valuef(name, expected_value, value, "%04o", u); + + else if (streq(name, "UID")) { + if (u == UID_INVALID) + bus_print_property_value(name, expected_value, value, "[not set]"); + else + bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u); + } else if (streq(name, "GID")) { + if (u == GID_INVALID) + bus_print_property_value(name, expected_value, value, "[not set]"); + else + bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u); + } else + bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u); + + return 1; + } + + case SD_BUS_TYPE_INT32: { + int32_t i; + + r = sd_bus_message_read_basic(m, type, &i); + if (r < 0) + return r; + + bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i); + return 1; + } + + case SD_BUS_TYPE_DOUBLE: { + double d; + + r = sd_bus_message_read_basic(m, type, &d); + if (r < 0) + return r; + + bus_print_property_valuef(name, expected_value, value, "%g", d); + return 1; + } + + case SD_BUS_TYPE_ARRAY: + if (streq(contents, "s")) { + bool first = true; + const char *str; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents); + if (r < 0) + return r; + + while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) { + bool good; + + if (first && !value) + printf("%s=", name); + + /* This property has multiple space-separated values, so + * neither spaces nor newlines can be allowed in a value. */ + good = str[strcspn(str, " \n")] == '\0'; + + printf("%s%s", first ? "" : " ", good ? str : "[unprintable]"); + + first = false; + } + if (r < 0) + return r; + + if (first && all && !value) + printf("%s=", name); + if (!first || all) + puts(""); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 1; + + } else if (streq(contents, "y")) { + const uint8_t *u; + size_t n; + + r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n); + if (r < 0) + return r; + + if (all || n > 0) { + unsigned i; + + if (!value) + printf("%s=", name); + + for (i = 0; i < n; i++) + printf("%02x", u[i]); + + puts(""); + } + + return 1; + + } else if (streq(contents, "u")) { + uint32_t *u; + size_t n; + + r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n); + if (r < 0) + return r; + + if (all || n > 0) { + unsigned i; + + if (!value) + printf("%s=", name); + + for (i = 0; i < n; i++) + printf("%08x", u[i]); + + puts(""); + } + + return 1; + } + + break; + } + + return 0; +} + +int bus_message_print_all_properties( + sd_bus_message *m, + bus_message_print_t func, + char **filter, + bool value, + bool all, + Set **found_properties) { + + int r; + + assert(m); + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}"); + if (r < 0) + return r; + + while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { + _cleanup_free_ char *name_with_equal = NULL; + const char *name, *contents, *expected_value = NULL; + + r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name); + if (r < 0) + return r; + + if (found_properties) { + r = set_ensure_allocated(found_properties, &string_hash_ops); + if (r < 0) + return log_oom(); + + r = set_put(*found_properties, name); + if (r < 0 && r != -EEXIST) + return log_oom(); + } + + name_with_equal = strjoin(name, "="); + if (!name_with_equal) + return log_oom(); + + if (!filter || strv_find(filter, name) || + (expected_value = strv_find_startswith(filter, name_with_equal))) { + r = sd_bus_message_peek_type(m, NULL, &contents); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents); + if (r < 0) + return r; + + if (func) + r = func(name, expected_value, m, value, all); + if (!func || r == 0) + r = bus_print_property(name, expected_value, m, value, all); + if (r < 0) + return r; + if (r == 0) { + if (all && !expected_value) + printf("%s=[unprintable]\n", name); + /* skip what we didn't read */ + r = sd_bus_message_skip(m, contents); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + } else { + r = sd_bus_message_skip(m, "v"); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +int bus_print_all_properties( + sd_bus *bus, + const char *dest, + const char *path, + bus_message_print_t func, + char **filter, + bool value, + bool all, + Set **found_properties) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + assert(path); + + r = sd_bus_call_method(bus, + dest, + path, + "org.freedesktop.DBus.Properties", + "GetAll", + &error, + &reply, + "s", ""); + if (r < 0) + return r; + + return bus_message_print_all_properties(reply, func, filter, value, all, found_properties); +} + +int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + sd_id128_t *p = userdata; + const void *v; + size_t n; + int r; + + r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n); + if (r < 0) + return r; + + if (n == 0) + *p = SD_ID128_NULL; + else if (n == 16) + memcpy((*p).bytes, v, n); + else + return -EINVAL; + + return 0; +} + +static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) { + char type; + int r; + + r = sd_bus_message_peek_type(m, &type, NULL); + if (r < 0) + return r; + + switch (type) { + + case SD_BUS_TYPE_STRING: + case SD_BUS_TYPE_OBJECT_PATH: { + const char **p = userdata; + const char *s; + + r = sd_bus_message_read_basic(m, type, &s); + if (r < 0) + return r; + + if (isempty(s)) + s = NULL; + + if (flags & BUS_MAP_STRDUP) + return free_and_strdup((char **) userdata, s); + + *p = s; + return 0; + } + + case SD_BUS_TYPE_ARRAY: { + _cleanup_strv_free_ char **l = NULL; + char ***p = userdata; + + r = bus_message_read_strv_extend(m, &l); + if (r < 0) + return r; + + return strv_free_and_replace(*p, l); + } + + case SD_BUS_TYPE_BOOLEAN: { + int b; + + r = sd_bus_message_read_basic(m, type, &b); + if (r < 0) + return r; + + if (flags & BUS_MAP_BOOLEAN_AS_BOOL) + *(bool*) userdata = b; + else + *(int*) userdata = b; + + return 0; + } + + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: { + uint32_t u, *p = userdata; + + r = sd_bus_message_read_basic(m, type, &u); + if (r < 0) + return r; + + *p = u; + return 0; + } + + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: { + uint64_t t, *p = userdata; + + r = sd_bus_message_read_basic(m, type, &t); + if (r < 0) + return r; + + *p = t; + return 0; + } + + case SD_BUS_TYPE_DOUBLE: { + double d, *p = userdata; + + r = sd_bus_message_read_basic(m, type, &d); + if (r < 0) + return r; + + *p = d; + return 0; + }} + + return -EOPNOTSUPP; +} + +int bus_message_map_all_properties( + sd_bus_message *m, + const struct bus_properties_map *map, + unsigned flags, + sd_bus_error *error, + void *userdata) { + + int r; + + assert(m); + assert(map); + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}"); + if (r < 0) + return r; + + while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { + const struct bus_properties_map *prop; + const char *member; + const char *contents; + void *v; + unsigned i; + + r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member); + if (r < 0) + return r; + + for (i = 0, prop = NULL; map[i].member; i++) + if (streq(map[i].member, member)) { + prop = &map[i]; + break; + } + + if (prop) { + r = sd_bus_message_peek_type(m, NULL, &contents); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents); + if (r < 0) + return r; + + v = (uint8_t *)userdata + prop->offset; + if (map[i].set) + r = prop->set(sd_bus_message_get_bus(m), member, m, error, v); + else + r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + } else { + r = sd_bus_message_skip(m, "v"); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + } + if (r < 0) + return r; + + return sd_bus_message_exit_container(m); +} + +int bus_map_all_properties( + sd_bus *bus, + const char *destination, + const char *path, + const struct bus_properties_map *map, + unsigned flags, + sd_bus_error *error, + sd_bus_message **reply, + void *userdata) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + assert(bus); + assert(destination); + assert(path); + assert(map); + assert(reply || (flags & BUS_MAP_STRDUP)); + + r = sd_bus_call_method( + bus, + destination, + path, + "org.freedesktop.DBus.Properties", + "GetAll", + error, + &m, + "s", ""); + if (r < 0) + return r; + + r = bus_message_map_all_properties(m, map, flags, error, userdata); + if (r < 0) + return r; + + if (reply) + *reply = sd_bus_message_ref(m); + + return r; +} + +int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) { + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; + int r; + + assert(transport >= 0); + assert(transport < _BUS_TRANSPORT_MAX); + assert(ret); + + assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL); + assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP); + + switch (transport) { + + case BUS_TRANSPORT_LOCAL: + if (user) + r = sd_bus_default_user(&bus); + else { + if (sd_booted() <= 0) { + /* Print a friendly message when the local system is actually not running systemd as PID 1. */ + log_error("System has not been booted with systemd as init system (PID 1). Can't operate."); + + return -EHOSTDOWN; + } + r = sd_bus_default_system(&bus); + } + break; + + case BUS_TRANSPORT_REMOTE: + r = sd_bus_open_system_remote(&bus, host); + break; + + case BUS_TRANSPORT_MACHINE: + r = sd_bus_open_system_machine(&bus, host); + break; + + default: + assert_not_reached("Hmm, unknown transport type."); + } + if (r < 0) + return r; + + r = sd_bus_set_exit_on_disconnect(bus, true); + if (r < 0) + return r; + + *ret = TAKE_PTR(bus); + + return 0; +} + +int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { + int r; + + assert(transport >= 0); + assert(transport < _BUS_TRANSPORT_MAX); + assert(bus); + + assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL); + assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP); + + switch (transport) { + + case BUS_TRANSPORT_LOCAL: + if (user) + r = bus_connect_user_systemd(bus); + else { + if (sd_booted() <= 0) + /* Print a friendly message when the local system is actually not running systemd as PID 1. */ + return log_error_errno(SYNTHETIC_ERRNO(EHOSTDOWN), + "System has not been booted with systemd as init system (PID 1). Can't operate."); + r = bus_connect_system_systemd(bus); + } + break; + + case BUS_TRANSPORT_REMOTE: + r = sd_bus_open_system_remote(bus, host); + break; + + case BUS_TRANSPORT_MACHINE: + r = sd_bus_open_system_machine(bus, host); + break; + + default: + assert_not_reached("Hmm, unknown transport type."); + } + + return r; +} + +int bus_property_get_bool( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + int b = *(bool*) userdata; + + return sd_bus_message_append_basic(reply, 'b', &b); +} + +int bus_property_set_bool( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *value, + void *userdata, + sd_bus_error *error) { + + int b, r; + + r = sd_bus_message_read(value, "b", &b); + if (r < 0) + return r; + + *(bool*) userdata = b; + return 0; +} + +int bus_property_get_id128( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + sd_id128_t *id = userdata; + + if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */ + return sd_bus_message_append(reply, "ay", 0); + else + return sd_bus_message_append_array(reply, 'y', id->bytes, 16); +} + +#if __SIZEOF_SIZE_T__ != 8 +int bus_property_get_size( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + uint64_t sz = *(size_t*) userdata; + + return sd_bus_message_append_basic(reply, 't', &sz); +} +#endif + +#if __SIZEOF_LONG__ != 8 +int bus_property_get_long( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + int64_t l = *(long*) userdata; + + return sd_bus_message_append_basic(reply, 'x', &l); +} + +int bus_property_get_ulong( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + uint64_t ul = *(unsigned long*) userdata; + + return sd_bus_message_append_basic(reply, 't', &ul); +} +#endif + +/** + * bus_path_encode_unique() - encode unique object path + * @b: bus connection or NULL + * @prefix: object path prefix + * @sender_id: unique-name of client, or NULL + * @external_id: external ID to be chosen by client, or NULL + * @ret_path: storage for encoded object path pointer + * + * Whenever we provide a bus API that allows clients to create and manage + * server-side objects, we need to provide a unique name for these objects. If + * we let the server choose the name, we suffer from a race condition: If a + * client creates an object asynchronously, it cannot destroy that object until + * it received the method reply. It cannot know the name of the new object, + * thus, it cannot destroy it. Furthermore, it enforces a round-trip. + * + * Therefore, many APIs allow the client to choose the unique name for newly + * created objects. There're two problems to solve, though: + * 1) Object names are usually defined via dbus object paths, which are + * usually globally namespaced. Therefore, multiple clients must be able + * to choose unique object names without interference. + * 2) If multiple libraries share the same bus connection, they must be + * able to choose unique object names without interference. + * The first problem is solved easily by prefixing a name with the + * unique-bus-name of a connection. The server side must enforce this and + * reject any other name. The second problem is solved by providing unique + * suffixes from within sd-bus. + * + * This helper allows clients to create unique object-paths. It uses the + * template '/prefix/sender_id/external_id' and returns the new path in + * @ret_path (must be freed by the caller). + * If @sender_id is NULL, the unique-name of @b is used. If @external_id is + * NULL, this function allocates a unique suffix via @b (by requesting a new + * cookie). If both @sender_id and @external_id are given, @b can be passed as + * NULL. + * + * Returns: 0 on success, negative error code on failure. + */ +int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) { + _cleanup_free_ char *sender_label = NULL, *external_label = NULL; + char external_buf[DECIMAL_STR_MAX(uint64_t)], *p; + int r; + + assert_return(b || (sender_id && external_id), -EINVAL); + assert_return(object_path_is_valid(prefix), -EINVAL); + assert_return(ret_path, -EINVAL); + + if (!sender_id) { + r = sd_bus_get_unique_name(b, &sender_id); + if (r < 0) + return r; + } + + if (!external_id) { + xsprintf(external_buf, "%"PRIu64, ++b->cookie); + external_id = external_buf; + } + + sender_label = bus_label_escape(sender_id); + if (!sender_label) + return -ENOMEM; + + external_label = bus_label_escape(external_id); + if (!external_label) + return -ENOMEM; + + p = path_join(prefix, sender_label, external_label); + if (!p) + return -ENOMEM; + + *ret_path = p; + return 0; +} + +/** + * bus_path_decode_unique() - decode unique object path + * @path: object path to decode + * @prefix: object path prefix + * @ret_sender: output parameter for sender-id label + * @ret_external: output parameter for external-id label + * + * This does the reverse of bus_path_encode_unique() (see its description for + * details). Both trailing labels, sender-id and external-id, are unescaped and + * returned in the given output parameters (the caller must free them). + * + * Note that this function returns 0 if the path does not match the template + * (see bus_path_encode_unique()), 1 if it matched. + * + * Returns: Negative error code on failure, 0 if the given object path does not + * match the template (return parameters are set to NULL), 1 if it was + * parsed successfully (return parameters contain allocated labels). + */ +int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) { + const char *p, *q; + char *sender, *external; + + assert(object_path_is_valid(path)); + assert(object_path_is_valid(prefix)); + assert(ret_sender); + assert(ret_external); + + p = object_path_startswith(path, prefix); + if (!p) { + *ret_sender = NULL; + *ret_external = NULL; + return 0; + } + + q = strchr(p, '/'); + if (!q) { + *ret_sender = NULL; + *ret_external = NULL; + return 0; + } + + sender = bus_label_unescape_n(p, q - p); + external = bus_label_unescape(q + 1); + if (!sender || !external) { + free(sender); + free(external); + return -ENOMEM; + } + + *ret_sender = sender; + *ret_external = external; + return 1; +} + +int bus_property_get_rlimit( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + const char *is_soft; + struct rlimit *rl; + uint64_t u; + rlim_t x; + + assert(bus); + assert(reply); + assert(userdata); + + is_soft = endswith(property, "Soft"); + + rl = *(struct rlimit**) userdata; + if (rl) + x = is_soft ? rl->rlim_cur : rl->rlim_max; + else { + struct rlimit buf = {}; + const char *s, *p; + int z; + + /* Chop off "Soft" suffix */ + s = is_soft ? strndupa(property, is_soft - property) : property; + + /* Skip over any prefix, such as "Default" */ + assert_se(p = strstr(s, "Limit")); + + z = rlimit_from_string(p + 5); + assert(z >= 0); + + (void) getrlimit(z, &buf); + x = is_soft ? buf.rlim_cur : buf.rlim_max; + } + + /* rlim_t might have different sizes, let's map RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on all + * archs */ + u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x; + + return sd_bus_message_append(reply, "t", u); +} + +int bus_track_add_name_many(sd_bus_track *t, char **l) { + int r = 0; + char **i; + + assert(t); + + /* Continues adding after failure, and returns the first failure. */ + + STRV_FOREACH(i, l) { + int k; + + k = sd_bus_track_add_name(t, *i); + if (k < 0 && r >= 0) + r = k; + } + + return r; +} + +int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) { + _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; + const char *e; + int r; + + assert(ret); + + /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal + * turned on. */ + + r = sd_bus_new(&bus); + if (r < 0) + return r; + + if (description) { + r = sd_bus_set_description(bus, description); + if (r < 0) + return r; + } + + e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS"); + if (!e) + e = DEFAULT_SYSTEM_BUS_ADDRESS; + + r = sd_bus_set_address(bus, e); + if (r < 0) + return r; + + r = sd_bus_set_bus_client(bus, true); + if (r < 0) + return r; + + r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS); + if (r < 0) + return r; + + r = sd_bus_set_watch_bind(bus, true); + if (r < 0) + return r; + + r = sd_bus_set_connected_signal(bus, true); + if (r < 0) + return r; + + r = sd_bus_start(bus); + if (r < 0) + return r; + + *ret = TAKE_PTR(bus); + + return 0; +} + +int bus_reply_pair_array(sd_bus_message *m, char **l) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + char **k, **v; + int r; + + assert(m); + + /* Reply to the specified message with a message containing a dictionary put together from the + * specified strv */ + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "{ss}"); + if (r < 0) + return r; + + STRV_FOREACH_PAIR(k, v, l) { + r = sd_bus_message_append(reply, "{ss}", *k, *v); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static void bus_message_unref_wrapper(void *m) { + sd_bus_message_unref(m); +} + +const struct hash_ops bus_message_hash_ops = { + .hash = trivial_hash_func, + .compare = trivial_compare_func, + .free_value = bus_message_unref_wrapper, +}; diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h new file mode 100644 index 00000000..db245a79 --- /dev/null +++ b/src/shared/bus-util.h @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-event.h" + +#include "macro.h" +#include "set.h" +#include "string-util.h" +#include "time-util.h" + +typedef enum BusTransport { + BUS_TRANSPORT_LOCAL, + BUS_TRANSPORT_REMOTE, + BUS_TRANSPORT_MACHINE, + _BUS_TRANSPORT_MAX, + _BUS_TRANSPORT_INVALID = -1 +} BusTransport; + +typedef int (*bus_property_set_t) (sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); + +struct bus_properties_map { + const char *member; + const char *signature; + bus_property_set_t set; + size_t offset; +}; + +enum { + BUS_MAP_STRDUP = 1 << 0, /* If set, each "s" message is duplicated. Thus, each pointer needs to be freed. */ + BUS_MAP_BOOLEAN_AS_BOOL = 1 << 1, /* If set, each "b" message is written to a bool pointer. If not set, "b" is written to a int pointer. */ +}; + +int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); + +int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, unsigned flags, sd_bus_error *error, void *userdata); +int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, + unsigned flags, sd_bus_error *error, sd_bus_message **reply, void *userdata); + +int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name); + +typedef bool (*check_idle_t)(void *userdata); + +int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout, check_idle_t check_idle, void *userdata); + +int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error); + +int bus_check_peercred(sd_bus *c); + +int bus_connect_system_systemd(sd_bus **_bus); +int bus_connect_user_systemd(sd_bus **_bus); + +int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus); +int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus); + +typedef int (*bus_message_print_t) (const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all); + +int bus_print_property_value(const char *name, const char *expected_value, bool only_value, const char *value); +int bus_print_property_valuef(const char *name, const char *expected_value, bool only_value, const char *fmt, ...) _printf_(4,5); +int bus_message_print_all_properties(sd_bus_message *m, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties); +int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties); + +int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); +int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error); +int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); + +#define bus_property_get_usec ((sd_bus_property_get_t) NULL) +#define bus_property_set_usec ((sd_bus_property_set_t) NULL) + +assert_cc(sizeof(int) == sizeof(int32_t)); +#define bus_property_get_int ((sd_bus_property_get_t) NULL) + +assert_cc(sizeof(unsigned) == sizeof(uint32_t)); +#define bus_property_get_unsigned ((sd_bus_property_get_t) NULL) + +/* On 64bit machines we can use the default serializer for size_t and + * friends, otherwise we need to cast this manually */ +#if __SIZEOF_SIZE_T__ == 8 +#define bus_property_get_size ((sd_bus_property_get_t) NULL) +#else +int bus_property_get_size(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); +#endif + +#if __SIZEOF_LONG__ == 8 +#define bus_property_get_long ((sd_bus_property_get_t) NULL) +#define bus_property_get_ulong ((sd_bus_property_get_t) NULL) +#else +int bus_property_get_long(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); +int bus_property_get_ulong(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); +#endif + +/* uid_t and friends on Linux 32 bit. This means we can just use the + * default serializer for 32bit unsigned, for serializing it, and map + * it to NULL here */ +assert_cc(sizeof(uid_t) == sizeof(uint32_t)); +#define bus_property_get_uid ((sd_bus_property_get_t) NULL) + +assert_cc(sizeof(gid_t) == sizeof(uint32_t)); +#define bus_property_get_gid ((sd_bus_property_get_t) NULL) + +assert_cc(sizeof(pid_t) == sizeof(uint32_t)); +#define bus_property_get_pid ((sd_bus_property_get_t) NULL) + +assert_cc(sizeof(mode_t) == sizeof(uint32_t)); +#define bus_property_get_mode ((sd_bus_property_get_t) NULL) + +#define bus_log_parse_error(r) \ + log_error_errno(r, "Failed to parse bus message: %m") + +#define bus_log_create_error(r) \ + log_error_errno(r, "Failed to create bus message: %m") + +#define BUS_DEFINE_PROPERTY_GET_GLOBAL(function, bus_type, val) \ + int function(sd_bus *bus, \ + const char *path, \ + const char *interface, \ + const char *property, \ + sd_bus_message *reply, \ + void *userdata, \ + sd_bus_error *error) { \ + \ + assert(bus); \ + assert(reply); \ + \ + return sd_bus_message_append(reply, bus_type, val); \ + } + +#define BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, get1, get2) \ + int function(sd_bus *bus, \ + const char *path, \ + const char *interface, \ + const char *property, \ + sd_bus_message *reply, \ + void *userdata, \ + sd_bus_error *error) { \ + \ + data_type *data = userdata; \ + \ + assert(bus); \ + assert(reply); \ + assert(data); \ + \ + return sd_bus_message_append(reply, bus_type, \ + get2(get1(data))); \ + } + +#define ident(x) (x) +#define BUS_DEFINE_PROPERTY_GET(function, bus_type, data_type, get1) \ + BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, get1, ident) + +#define ref(x) (*(x)) +#define BUS_DEFINE_PROPERTY_GET_REF(function, bus_type, data_type, get) \ + BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, ref, get) + +#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \ + BUS_DEFINE_PROPERTY_GET_REF(function, "s", type, name##_to_string) + +#define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \ + SD_BUS_PROPERTY(name, "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, realtime), (flags)), \ + SD_BUS_PROPERTY(name "Monotonic", "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, monotonic), (flags)) + +int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path); +int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external); + +int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); + +int bus_track_add_name_many(sd_bus_track *t, char **l); + +int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description); +static inline int bus_open_system_watch_bind(sd_bus **ret) { + return bus_open_system_watch_bind_with_description(ret, NULL); +} + +int bus_reply_pair_array(sd_bus_message *m, char **l); + +extern const struct hash_ops bus_message_hash_ops; diff --git a/src/shared/bus-wait-for-jobs.c b/src/shared/bus-wait-for-jobs.c new file mode 100644 index 00000000..4e6b862d --- /dev/null +++ b/src/shared/bus-wait-for-jobs.c @@ -0,0 +1,337 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "bus-wait-for-jobs.h" +#include "set.h" +#include "bus-util.h" +#include "bus-internal.h" +#include "unit-def.h" +#include "escape.h" +#include "strv.h" + +typedef struct BusWaitForJobs { + sd_bus *bus; + + /* The set of jobs to wait for, as bus object paths */ + Set *jobs; + + /* The unit name and job result of the last Job message */ + char *name; + char *result; + + sd_bus_slot *slot_job_removed; + sd_bus_slot *slot_disconnected; +} BusWaitForJobs; + +static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) { + assert(m); + + log_error("Warning! D-Bus connection terminated."); + sd_bus_close(sd_bus_message_get_bus(m)); + + return 0; +} + +static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + const char *path, *unit, *result; + BusWaitForJobs *d = userdata; + uint32_t id; + char *found; + int r; + + assert(m); + assert(d); + + r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + found = set_remove(d->jobs, (char*) path); + if (!found) + return 0; + + free(found); + + (void) free_and_strdup(&d->result, empty_to_null(result)); + + (void) free_and_strdup(&d->name, empty_to_null(unit)); + + return 0; +} + +void bus_wait_for_jobs_free(BusWaitForJobs *d) { + if (!d) + return; + + set_free_free(d->jobs); + + sd_bus_slot_unref(d->slot_disconnected); + sd_bus_slot_unref(d->slot_job_removed); + + sd_bus_unref(d->bus); + + free(d->name); + free(d->result); + + free(d); +} + +int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) { + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL; + int r; + + assert(bus); + assert(ret); + + d = new(BusWaitForJobs, 1); + if (!d) + return -ENOMEM; + + *d = (BusWaitForJobs) { + .bus = sd_bus_ref(bus), + }; + + /* When we are a bus client we match by sender. Direct + * connections OTOH have no initialized sender field, and + * hence we ignore the sender then */ + r = sd_bus_match_signal_async( + bus, + &d->slot_job_removed, + bus->bus_client ? "org.freedesktop.systemd1" : NULL, + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "JobRemoved", + match_job_removed, NULL, d); + if (r < 0) + return r; + + r = sd_bus_match_signal_async( + bus, + &d->slot_disconnected, + "org.freedesktop.DBus.Local", + NULL, + "org.freedesktop.DBus.Local", + "Disconnected", + match_disconnected, NULL, d); + if (r < 0) + return r; + + *ret = TAKE_PTR(d); + + return 0; +} + +static int bus_process_wait(sd_bus *bus) { + int r; + + for (;;) { + r = sd_bus_process(bus, NULL); + if (r < 0) + return r; + if (r > 0) + return 0; + + r = sd_bus_wait(bus, (uint64_t) -1); + if (r < 0) + return r; + } +} + +static int bus_job_get_service_result(BusWaitForJobs *d, char **result) { + _cleanup_free_ char *dbus_path = NULL; + + assert(d); + assert(d->name); + assert(result); + + if (!endswith(d->name, ".service")) + return -EINVAL; + + dbus_path = unit_dbus_path_from_name(d->name); + if (!dbus_path) + return -ENOMEM; + + return sd_bus_get_property_string(d->bus, + "org.freedesktop.systemd1", + dbus_path, + "org.freedesktop.systemd1.Service", + "Result", + NULL, + result); +} + +static void log_job_error_with_service_result(const char* service, const char *result, const char* const* extra_args) { + _cleanup_free_ char *service_shell_quoted = NULL; + const char *systemctl = "systemctl", *journalctl = "journalctl"; + + static const struct { + const char *result, *explanation; + } explanations[] = { + { "resources", "of unavailable resources or another system error" }, + { "protocol", "the service did not take the steps required by its unit configuration" }, + { "timeout", "a timeout was exceeded" }, + { "exit-code", "the control process exited with error code" }, + { "signal", "a fatal signal was delivered to the control process" }, + { "core-dump", "a fatal signal was delivered causing the control process to dump core" }, + { "watchdog", "the service failed to send watchdog ping" }, + { "start-limit", "start of the service was attempted too often" } + }; + + assert(service); + + service_shell_quoted = shell_maybe_quote(service, ESCAPE_BACKSLASH); + + if (!strv_isempty((char**) extra_args)) { + _cleanup_free_ char *t; + + t = strv_join((char**) extra_args, " "); + systemctl = strjoina("systemctl ", t ? : ""); + journalctl = strjoina("journalctl ", t ? : ""); + } + + if (!isempty(result)) { + size_t i; + + for (i = 0; i < ELEMENTSOF(explanations); ++i) + if (streq(result, explanations[i].result)) + break; + + if (i < ELEMENTSOF(explanations)) { + log_error("Job for %s failed because %s.\n" + "See \"%s status %s\" and \"%s -xe\" for details.\n", + service, + explanations[i].explanation, + systemctl, + service_shell_quoted ?: "", + journalctl); + goto finish; + } + } + + log_error("Job for %s failed.\n" + "See \"%s status %s\" and \"%s -xe\" for details.\n", + service, + systemctl, + service_shell_quoted ?: "", + journalctl); + +finish: + /* For some results maybe additional explanation is required */ + if (streq_ptr(result, "start-limit")) + log_info("To force a start use \"%1$s reset-failed %2$s\"\n" + "followed by \"%1$s start %2$s\" again.", + systemctl, + service_shell_quoted ?: ""); +} + +static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const* extra_args) { + assert(d); + assert(d->name); + assert(d->result); + + if (!quiet) { + if (streq(d->result, "canceled")) + log_error("Job for %s canceled.", strna(d->name)); + else if (streq(d->result, "timeout")) + log_error("Job for %s timed out.", strna(d->name)); + else if (streq(d->result, "dependency")) + log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name)); + else if (streq(d->result, "invalid")) + log_error("%s is not active, cannot reload.", strna(d->name)); + else if (streq(d->result, "assert")) + log_error("Assertion failed on job for %s.", strna(d->name)); + else if (streq(d->result, "unsupported")) + log_error("Operation on or unit type of %s not supported on this system.", strna(d->name)); + else if (streq(d->result, "collected")) + log_error("Queued job for %s was garbage collected.", strna(d->name)); + else if (streq(d->result, "once")) + log_error("Unit %s was started already once and can't be started again.", strna(d->name)); + else if (!STR_IN_SET(d->result, "done", "skipped")) { + + if (d->name && endswith(d->name, ".service")) { + _cleanup_free_ char *result = NULL; + int q; + + q = bus_job_get_service_result(d, &result); + if (q < 0) + log_debug_errno(q, "Failed to get Result property of unit %s: %m", d->name); + + log_job_error_with_service_result(d->name, result, extra_args); + } else + log_error("Job failed. See \"journalctl -xe\" for details."); + } + } + + if (STR_IN_SET(d->result, "canceled", "collected")) + return -ECANCELED; + else if (streq(d->result, "timeout")) + return -ETIME; + else if (streq(d->result, "dependency")) + return -EIO; + else if (streq(d->result, "invalid")) + return -ENOEXEC; + else if (streq(d->result, "assert")) + return -EPROTO; + else if (streq(d->result, "unsupported")) + return -EOPNOTSUPP; + else if (streq(d->result, "once")) + return -ESTALE; + else if (STR_IN_SET(d->result, "done", "skipped")) + return 0; + + return log_debug_errno(SYNTHETIC_ERRNO(EIO), + "Unexpected job result, assuming server side newer than us: %s", d->result); +} + +int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_args) { + int r = 0; + + assert(d); + + while (!set_isempty(d->jobs)) { + int q; + + q = bus_process_wait(d->bus); + if (q < 0) + return log_error_errno(q, "Failed to wait for response: %m"); + + if (d->name && d->result) { + q = check_wait_response(d, quiet, extra_args); + /* Return the first error as it is most likely to be + * meaningful. */ + if (q < 0 && r == 0) + r = q; + + log_debug_errno(q, "Got result %s/%m for job %s", d->result, d->name); + } + + d->name = mfree(d->name); + d->result = mfree(d->result); + } + + return r; +} + +int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) { + int r; + + assert(d); + + r = set_ensure_allocated(&d->jobs, &string_hash_ops); + if (r < 0) + return r; + + return set_put_strdup(d->jobs, path); +} + +int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) { + int r; + + r = bus_wait_for_jobs_add(d, path); + if (r < 0) + return log_oom(); + + return bus_wait_for_jobs(d, quiet, NULL); +} diff --git a/src/shared/bus-wait-for-jobs.h b/src/shared/bus-wait-for-jobs.h new file mode 100644 index 00000000..8f21eb9c --- /dev/null +++ b/src/shared/bus-wait-for-jobs.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-bus.h" +#include "macro.h" + +typedef struct BusWaitForJobs BusWaitForJobs; + +int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret); +void bus_wait_for_jobs_free(BusWaitForJobs *d); +int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path); +int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_args); +int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet); + +DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free); diff --git a/src/shared/bus-wait-for-units.c b/src/shared/bus-wait-for-units.c new file mode 100644 index 00000000..78b2a604 --- /dev/null +++ b/src/shared/bus-wait-for-units.c @@ -0,0 +1,433 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-util.h" +#include "bus-wait-for-units.h" +#include "hashmap.h" +#include "string-util.h" +#include "strv.h" +#include "unit-def.h" + +typedef struct WaitForItem { + BusWaitForUnits *parent; + + BusWaitForUnitsFlags flags; + + char *bus_path; + + sd_bus_slot *slot_get_all; + sd_bus_slot *slot_properties_changed; + + bus_wait_for_units_unit_callback unit_callback; + void *userdata; + + char *active_state; + uint32_t job_id; + char *clean_result; +} WaitForItem; + +typedef struct BusWaitForUnits { + sd_bus *bus; + sd_bus_slot *slot_disconnected; + + Hashmap *items; + + bus_wait_for_units_ready_callback ready_callback; + void *userdata; + + WaitForItem *current; + + BusWaitForUnitsState state; + bool has_failed:1; +} BusWaitForUnits; + +static WaitForItem *wait_for_item_free(WaitForItem *item) { + int r; + + if (!item) + return NULL; + + if (item->parent) { + if (FLAGS_SET(item->flags, BUS_WAIT_REFFED) && item->bus_path && item->parent->bus) { + r = sd_bus_call_method_async( + item->parent->bus, + NULL, + "org.freedesktop.systemd1", + item->bus_path, + "org.freedesktop.systemd1.Unit", + "Unref", + NULL, + NULL, + NULL); + if (r < 0) + log_debug_errno(r, "Failed to drop reference to unit %s, ignoring: %m", item->bus_path); + } + + assert_se(hashmap_remove(item->parent->items, item->bus_path) == item); + + if (item->parent->current == item) + item->parent->current = NULL; + } + + sd_bus_slot_unref(item->slot_properties_changed); + sd_bus_slot_unref(item->slot_get_all); + + free(item->bus_path); + free(item->active_state); + free(item->clean_result); + + return mfree(item); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(WaitForItem*, wait_for_item_free); + +static void bus_wait_for_units_clear(BusWaitForUnits *d) { + WaitForItem *item; + + assert(d); + + d->slot_disconnected = sd_bus_slot_unref(d->slot_disconnected); + d->bus = sd_bus_unref(d->bus); + + while ((item = hashmap_first(d->items))) { + d->current = item; + + item->unit_callback(d, item->bus_path, false, item->userdata); + wait_for_item_free(item); + } + + d->items = hashmap_free(d->items); +} + +static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) { + BusWaitForUnits *d = userdata; + + assert(m); + assert(d); + + log_error("Warning! D-Bus connection terminated."); + + bus_wait_for_units_clear(d); + + if (d->ready_callback) + d->ready_callback(d, false, d->userdata); + else /* If no ready callback is specified close the connection so that the event loop exits */ + sd_bus_close(sd_bus_message_get_bus(m)); + + return 0; +} + +int bus_wait_for_units_new(sd_bus *bus, BusWaitForUnits **ret) { + _cleanup_(bus_wait_for_units_freep) BusWaitForUnits *d = NULL; + int r; + + assert(bus); + assert(ret); + + d = new(BusWaitForUnits, 1); + if (!d) + return -ENOMEM; + + *d = (BusWaitForUnits) { + .state = BUS_WAIT_SUCCESS, + .bus = sd_bus_ref(bus), + }; + + r = sd_bus_match_signal_async( + bus, + &d->slot_disconnected, + "org.freedesktop.DBus.Local", + NULL, + "org.freedesktop.DBus.Local", + "Disconnected", + match_disconnected, NULL, d); + if (r < 0) + return r; + + *ret = TAKE_PTR(d); + return 0; +} + +BusWaitForUnits* bus_wait_for_units_free(BusWaitForUnits *d) { + if (!d) + return NULL; + + bus_wait_for_units_clear(d); + sd_bus_slot_unref(d->slot_disconnected); + sd_bus_unref(d->bus); + + return mfree(d); +} + +static bool bus_wait_for_units_is_ready(BusWaitForUnits *d) { + assert(d); + + if (!d->bus) /* Disconnected? */ + return true; + + return hashmap_isempty(d->items); +} + +void bus_wait_for_units_set_ready_callback(BusWaitForUnits *d, bus_wait_for_units_ready_callback callback, void *userdata) { + assert(d); + + d->ready_callback = callback; + d->userdata = userdata; +} + +static void bus_wait_for_units_check_ready(BusWaitForUnits *d) { + assert(d); + + if (!bus_wait_for_units_is_ready(d)) + return; + + d->state = d->has_failed ? BUS_WAIT_FAILURE : BUS_WAIT_SUCCESS; + + if (d->ready_callback) + d->ready_callback(d, d->state, d->userdata); +} + +static void wait_for_item_check_ready(WaitForItem *item) { + BusWaitForUnits *d; + + assert(item); + assert_se(d = item->parent); + + if (FLAGS_SET(item->flags, BUS_WAIT_FOR_MAINTENANCE_END)) { + + if (item->clean_result && !streq(item->clean_result, "success")) + d->has_failed = true; + + if (!item->active_state || streq(item->active_state, "maintenance")) + return; + } + + if (FLAGS_SET(item->flags, BUS_WAIT_NO_JOB) && item->job_id != 0) + return; + + if (FLAGS_SET(item->flags, BUS_WAIT_FOR_INACTIVE)) { + + if (streq_ptr(item->active_state, "failed")) + d->has_failed = true; + else if (!streq_ptr(item->active_state, "inactive")) + return; + } + + if (item->unit_callback) { + d->current = item; + item->unit_callback(d, item->bus_path, true, item->userdata); + } + + wait_for_item_free(item); + + bus_wait_for_units_check_ready(d); +} + +static int property_map_job( + sd_bus *bus, + const char *member, + sd_bus_message *m, + sd_bus_error *error, + void *userdata) { + + WaitForItem *item = userdata; + const char *path; + uint32_t id; + int r; + + assert(item); + + r = sd_bus_message_read(m, "(uo)", &id, &path); + if (r < 0) + return r; + + item->job_id = id; + return 0; +} + +static int wait_for_item_parse_properties(WaitForItem *item, sd_bus_message *m) { + + static const struct bus_properties_map map[] = { + { "ActiveState", "s", NULL, offsetof(WaitForItem, active_state) }, + { "Job", "(uo)", property_map_job, 0 }, + { "CleanResult", "s", NULL, offsetof(WaitForItem, clean_result) }, + {} + }; + + int r; + + assert(item); + assert(m); + + r = bus_message_map_all_properties(m, map, BUS_MAP_STRDUP, NULL, item); + if (r < 0) + return r; + + wait_for_item_check_ready(item); + return 0; +} + +static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + WaitForItem *item = userdata; + const char *interface; + int r; + + assert(item); + + r = sd_bus_message_read(m, "s", &interface); + if (r < 0) { + log_debug_errno(r, "Failed to parse PropertiesChanged signal: %m"); + return 0; + } + + if (!streq(interface, "org.freedesktop.systemd1.Unit")) + return 0; + + r = wait_for_item_parse_properties(item, m); + if (r < 0) + log_debug_errno(r, "Failed to process PropertiesChanged signal: %m"); + + return 0; +} + +static int on_get_all_properties(sd_bus_message *m, void *userdata, sd_bus_error *error) { + WaitForItem *item = userdata; + int r; + + assert(item); + + if (sd_bus_error_is_set(error)) { + BusWaitForUnits *d = item->parent; + + d->has_failed = true; + + log_debug_errno(sd_bus_error_get_errno(error), "GetAll() failed for %s: %s", + item->bus_path, error->message); + + d->current = item; + item->unit_callback(d, item->bus_path, false, item->userdata); + wait_for_item_free(item); + + bus_wait_for_units_check_ready(d); + return 0; + } + + r = wait_for_item_parse_properties(item, m); + if (r < 0) + log_debug_errno(r, "Failed to process GetAll method reply: %m"); + + return 0; +} + +int bus_wait_for_units_add_unit( + BusWaitForUnits *d, + const char *unit, + BusWaitForUnitsFlags flags, + bus_wait_for_units_unit_callback callback, + void *userdata) { + + _cleanup_(wait_for_item_freep) WaitForItem *item = NULL; + int r; + + assert(d); + assert(unit); + + assert(flags != 0); + + r = hashmap_ensure_allocated(&d->items, &string_hash_ops); + if (r < 0) + return r; + + item = new(WaitForItem, 1); + if (!item) + return -ENOMEM; + + *item = (WaitForItem) { + .flags = flags, + .bus_path = unit_dbus_path_from_name(unit), + .unit_callback = callback, + .userdata = userdata, + .job_id = UINT32_MAX, + }; + + if (!item->bus_path) + return -ENOMEM; + + if (!FLAGS_SET(item->flags, BUS_WAIT_REFFED)) { + r = sd_bus_call_method_async( + d->bus, + NULL, + "org.freedesktop.systemd1", + item->bus_path, + "org.freedesktop.systemd1.Unit", + "Ref", + NULL, + NULL, + NULL); + if (r < 0) + return log_debug_errno(r, "Failed to add reference to unit %s: %m", unit); + + item->flags |= BUS_WAIT_REFFED; + } + + r = sd_bus_match_signal_async( + d->bus, + &item->slot_properties_changed, + "org.freedesktop.systemd1", + item->bus_path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + on_properties_changed, + NULL, + item); + if (r < 0) + return log_debug_errno(r, "Failed to request match for PropertiesChanged signal: %m"); + + r = sd_bus_call_method_async( + d->bus, + &item->slot_get_all, + "org.freedesktop.systemd1", + item->bus_path, + "org.freedesktop.DBus.Properties", + "GetAll", + on_get_all_properties, + item, + "s", FLAGS_SET(item->flags, BUS_WAIT_FOR_MAINTENANCE_END) ? NULL : "org.freedesktop.systemd1.Unit"); + if (r < 0) + return log_debug_errno(r, "Failed to request properties of unit %s: %m", unit); + + r = hashmap_put(d->items, item->bus_path, item); + if (r < 0) + return r; + + d->state = BUS_WAIT_RUNNING; + item->parent = d; + TAKE_PTR(item); + return 0; +} + +int bus_wait_for_units_run(BusWaitForUnits *d) { + int r; + + assert(d); + + while (d->state == BUS_WAIT_RUNNING) { + + r = sd_bus_process(d->bus, NULL); + if (r < 0) + return r; + if (r > 0) + continue; + + r = sd_bus_wait(d->bus, (uint64_t) -1); + if (r < 0) + return r; + } + + return d->state; +} + +BusWaitForUnitsState bus_wait_for_units_state(BusWaitForUnits *d) { + assert(d); + + return d->state; +} diff --git a/src/shared/bus-wait-for-units.h b/src/shared/bus-wait-for-units.h new file mode 100644 index 00000000..a20f3d8f --- /dev/null +++ b/src/shared/bus-wait-for-units.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "macro.h" +#include "sd-bus.h" + +typedef struct BusWaitForUnits BusWaitForUnits; + +typedef enum BusWaitForUnitsState { + BUS_WAIT_SUCCESS, /* Nothing to wait for anymore and nothing failed */ + BUS_WAIT_FAILURE, /* dito, but something failed */ + BUS_WAIT_RUNNING, /* Still something to wait for */ + _BUS_WAIT_FOR_UNITS_STATE_MAX, + _BUS_WAIT_FOR_UNITS_STATE_INVALID = -1, +} BusWaitForUnitsState; + +typedef enum BusWaitForUnitsFlags { + BUS_WAIT_FOR_MAINTENANCE_END = 1 << 0, /* Wait until the unit is no longer in maintenance state */ + BUS_WAIT_FOR_INACTIVE = 1 << 1, /* Wait until the unit is back in inactive or dead state */ + BUS_WAIT_NO_JOB = 1 << 2, /* Wait until there's no more job pending */ + BUS_WAIT_REFFED = 1 << 3, /* The unit is already reffed with RefUnit() */ +} BusWaitForUnitsFlags; + +typedef void (*bus_wait_for_units_ready_callback)(BusWaitForUnits *d, BusWaitForUnitsState state, void *userdata); +typedef void (*bus_wait_for_units_unit_callback)(BusWaitForUnits *d, const char *unit_path, bool good, void *userdata); + +int bus_wait_for_units_new(sd_bus *bus, BusWaitForUnits **ret); +BusWaitForUnits* bus_wait_for_units_free(BusWaitForUnits *d); + +BusWaitForUnitsState bus_wait_for_units_state(BusWaitForUnits *d); +void bus_wait_for_units_set_ready_callback(BusWaitForUnits *d, bus_wait_for_units_ready_callback callback, void *userdata); +int bus_wait_for_units_add_unit(BusWaitForUnits *d, const char *unit, BusWaitForUnitsFlags flags, bus_wait_for_units_unit_callback callback, void *userdata); +int bus_wait_for_units_run(BusWaitForUnits *d); + +DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForUnits*, bus_wait_for_units_free); diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c new file mode 100644 index 00000000..217ab3fb --- /dev/null +++ b/src/shared/calendarspec.c @@ -0,0 +1,1380 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "calendarspec.h" +#include "errno-util.h" +#include "fileio.h" +#include "macro.h" +#include "parse-util.h" +#include "process-util.h" +#include "sort-util.h" +#include "string-util.h" +#include "time-util.h" + +#define BITS_WEEKDAYS 127 +#define MIN_YEAR 1970 +#define MAX_YEAR 2199 + +/* An arbitrary limit on the length of the chains of components. We don't want to + * build a very long linked list, which would be slow to iterate over and might cause + * our stack to overflow. It's unlikely that legitimate uses require more than a few + * linked compenents anyway. */ +#define CALENDARSPEC_COMPONENTS_MAX 240 + +static void chain_free(CalendarComponent *c) { + CalendarComponent *n; + + while (c) { + n = c->next; + free(c); + c = n; + } +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(CalendarComponent*, chain_free); + +CalendarSpec* calendar_spec_free(CalendarSpec *c) { + + if (!c) + return NULL; + + chain_free(c->year); + chain_free(c->month); + chain_free(c->day); + chain_free(c->hour); + chain_free(c->minute); + chain_free(c->microsecond); + free(c->timezone); + + return mfree(c); +} + +static int component_compare(CalendarComponent * const *a, CalendarComponent * const *b) { + int r; + + r = CMP((*a)->start, (*b)->start); + if (r != 0) + return r; + + r = CMP((*a)->stop, (*b)->stop); + if (r != 0) + return r; + + return CMP((*a)->repeat, (*b)->repeat); +} + +static void normalize_chain(CalendarComponent **c) { + CalendarComponent **b, *i, **j, *next; + size_t n = 0, k; + + assert(c); + + for (i = *c; i; i = i->next) { + n++; + + /* + * While we're counting the chain, also normalize `stop` + * so the length of the range is a multiple of `repeat` + */ + if (i->stop > i->start && i->repeat > 0) + i->stop -= (i->stop - i->start) % i->repeat; + + } + + if (n <= 1) + return; + + j = b = newa(CalendarComponent*, n); + for (i = *c; i; i = i->next) + *(j++) = i; + + typesafe_qsort(b, n, component_compare); + + b[n-1]->next = NULL; + next = b[n-1]; + + /* Drop non-unique entries */ + for (k = n-1; k > 0; k--) { + if (component_compare(&b[k-1], &next) == 0) { + free(b[k-1]); + continue; + } + + b[k-1]->next = next; + next = b[k-1]; + } + + *c = next; +} + +static void fix_year(CalendarComponent *c) { + /* Turns 12 → 2012, 89 → 1989 */ + + while (c) { + if (c->start >= 0 && c->start < 70) + c->start += 2000; + + if (c->stop >= 0 && c->stop < 70) + c->stop += 2000; + + if (c->start >= 70 && c->start < 100) + c->start += 1900; + + if (c->stop >= 70 && c->stop < 100) + c->stop += 1900; + + c = c->next; + } +} + +int calendar_spec_normalize(CalendarSpec *c) { + assert(c); + + if (streq_ptr(c->timezone, "UTC")) { + c->utc = true; + c->timezone = mfree(c->timezone); + } + + if (c->weekdays_bits <= 0 || c->weekdays_bits >= BITS_WEEKDAYS) + c->weekdays_bits = -1; + + if (c->end_of_month && !c->day) + c->end_of_month = false; + + fix_year(c->year); + + normalize_chain(&c->year); + normalize_chain(&c->month); + normalize_chain(&c->day); + normalize_chain(&c->hour); + normalize_chain(&c->minute); + normalize_chain(&c->microsecond); + + return 0; +} + +_pure_ static bool chain_valid(CalendarComponent *c, int from, int to, bool end_of_month) { + assert(to >= from); + + if (!c) + return true; + + /* Forbid dates more than 28 days from the end of the month */ + if (end_of_month) + to -= 3; + + if (c->start < from || c->start > to) + return false; + + /* Avoid overly large values that could cause overflow */ + if (c->repeat > to - from) + return false; + + /* + * c->repeat must be short enough so at least one repetition may + * occur before the end of the interval. For dates scheduled + * relative to the end of the month, c->start and c->stop + * correspond to the Nth last day of the month. + */ + if (c->stop >= 0) { + if (c->stop < from || c ->stop > to) + return false; + + if (c->start + c->repeat > c->stop) + return false; + } else { + if (end_of_month && c->start - c->repeat < from) + return false; + + if (!end_of_month && c->start + c->repeat > to) + return false; + } + + if (c->next) + return chain_valid(c->next, from, to, end_of_month); + + return true; +} + +_pure_ bool calendar_spec_valid(CalendarSpec *c) { + assert(c); + + if (c->weekdays_bits > BITS_WEEKDAYS) + return false; + + if (!chain_valid(c->year, MIN_YEAR, MAX_YEAR, false)) + return false; + + if (!chain_valid(c->month, 1, 12, false)) + return false; + + if (!chain_valid(c->day, 1, 31, c->end_of_month)) + return false; + + if (!chain_valid(c->hour, 0, 23, false)) + return false; + + if (!chain_valid(c->minute, 0, 59, false)) + return false; + + if (!chain_valid(c->microsecond, 0, 60*USEC_PER_SEC-1, false)) + return false; + + return true; +} + +static void format_weekdays(FILE *f, const CalendarSpec *c) { + static const char *const days[] = { + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun" + }; + + int l, x; + bool need_comma = false; + + assert(f); + assert(c); + assert(c->weekdays_bits > 0 && c->weekdays_bits <= BITS_WEEKDAYS); + + for (x = 0, l = -1; x < (int) ELEMENTSOF(days); x++) { + + if (c->weekdays_bits & (1 << x)) { + + if (l < 0) { + if (need_comma) + fputc(',', f); + else + need_comma = true; + + fputs(days[x], f); + l = x; + } + + } else if (l >= 0) { + + if (x > l + 1) { + fputs(x > l + 2 ? ".." : ",", f); + fputs(days[x-1], f); + } + + l = -1; + } + } + + if (l >= 0 && x > l + 1) { + fputs(x > l + 2 ? ".." : ",", f); + fputs(days[x-1], f); + } +} + +static void format_chain(FILE *f, int space, const CalendarComponent *c, bool usec) { + int d = usec ? (int) USEC_PER_SEC : 1; + + assert(f); + + if (!c) { + fputc('*', f); + return; + } + + if (usec && c->start == 0 && c->repeat == USEC_PER_SEC && !c->next) { + fputc('*', f); + return; + } + + assert(c->start >= 0); + + fprintf(f, "%0*i", space, c->start / d); + if (c->start % d > 0) + fprintf(f, ".%06i", c->start % d); + + if (c->stop > 0) + fprintf(f, "..%0*i", space, c->stop / d); + if (c->stop % d > 0) + fprintf(f, ".%06i", c->stop % d); + + if (c->repeat > 0 && !(c->stop > 0 && c->repeat == d)) + fprintf(f, "/%i", c->repeat / d); + if (c->repeat % d > 0) + fprintf(f, ".%06i", c->repeat % d); + + if (c->next) { + fputc(',', f); + format_chain(f, space, c->next, usec); + } +} + +int calendar_spec_to_string(const CalendarSpec *c, char **p) { + char *buf = NULL; + size_t sz = 0; + FILE *f; + int r; + + assert(c); + assert(p); + + f = open_memstream_unlocked(&buf, &sz); + if (!f) + return -ENOMEM; + + if (c->weekdays_bits > 0 && c->weekdays_bits <= BITS_WEEKDAYS) { + format_weekdays(f, c); + fputc(' ', f); + } + + format_chain(f, 4, c->year, false); + fputc('-', f); + format_chain(f, 2, c->month, false); + fputc(c->end_of_month ? '~' : '-', f); + format_chain(f, 2, c->day, false); + fputc(' ', f); + format_chain(f, 2, c->hour, false); + fputc(':', f); + format_chain(f, 2, c->minute, false); + fputc(':', f); + format_chain(f, 2, c->microsecond, true); + + if (c->utc) + fputs(" UTC", f); + else if (c->timezone != NULL) { + fputc(' ', f); + fputs(c->timezone, f); + } else if (IN_SET(c->dst, 0, 1)) { + + /* If daylight saving is explicitly on or off, let's show the used timezone. */ + + tzset(); + + if (!isempty(tzname[c->dst])) { + fputc(' ', f); + fputs(tzname[c->dst], f); + } + } + + r = fflush_and_check(f); + if (r < 0) { + free(buf); + fclose(f); + return r; + } + + fclose(f); + + *p = buf; + return 0; +} + +static int parse_weekdays(const char **p, CalendarSpec *c) { + static const struct { + const char *name; + const int nr; + } day_nr[] = { + { "Monday", 0 }, + { "Mon", 0 }, + { "Tuesday", 1 }, + { "Tue", 1 }, + { "Wednesday", 2 }, + { "Wed", 2 }, + { "Thursday", 3 }, + { "Thu", 3 }, + { "Friday", 4 }, + { "Fri", 4 }, + { "Saturday", 5 }, + { "Sat", 5 }, + { "Sunday", 6 }, + { "Sun", 6 } + }; + + int l = -1; + bool first = true; + + assert(p); + assert(*p); + assert(c); + + for (;;) { + size_t i; + + for (i = 0; i < ELEMENTSOF(day_nr); i++) { + size_t skip; + + if (!startswith_no_case(*p, day_nr[i].name)) + continue; + + skip = strlen(day_nr[i].name); + + if (!IN_SET((*p)[skip], 0, '-', '.', ',', ' ')) + return -EINVAL; + + c->weekdays_bits |= 1 << day_nr[i].nr; + + if (l >= 0) { + int j; + + if (l > day_nr[i].nr) + return -EINVAL; + + for (j = l + 1; j < day_nr[i].nr; j++) + c->weekdays_bits |= 1 << j; + } + + *p += skip; + break; + } + + /* Couldn't find this prefix, so let's assume the + weekday was not specified and let's continue with + the date */ + if (i >= ELEMENTSOF(day_nr)) + return first ? 0 : -EINVAL; + + /* We reached the end of the string */ + if (**p == 0) + return 0; + + /* We reached the end of the weekday spec part */ + if (**p == ' ') { + *p += strspn(*p, " "); + return 0; + } + + if (**p == '.') { + if (l >= 0) + return -EINVAL; + + if ((*p)[1] != '.') + return -EINVAL; + + l = day_nr[i].nr; + *p += 2; + + /* Support ranges with "-" for backwards compatibility */ + } else if (**p == '-') { + if (l >= 0) + return -EINVAL; + + l = day_nr[i].nr; + *p += 1; + + } else if (**p == ',') { + l = -1; + *p += 1; + } + + /* Allow a trailing comma but not an open range */ + if (IN_SET(**p, 0, ' ')) { + *p += strspn(*p, " "); + return l < 0 ? 0 : -EINVAL; + } + + first = false; + } +} + +static int parse_one_number(const char *p, const char **e, unsigned long *ret) { + char *ee = NULL; + unsigned long value; + + errno = 0; + value = strtoul(p, &ee, 10); + if (errno > 0) + return -errno; + if (ee == p) + return -EINVAL; + + *ret = value; + *e = ee; + return 0; +} + +static int parse_component_decimal(const char **p, bool usec, int *res) { + unsigned long value; + const char *e = NULL; + int r; + + if (!isdigit(**p)) + return -EINVAL; + + r = parse_one_number(*p, &e, &value); + if (r < 0) + return r; + + if (usec) { + if (value * USEC_PER_SEC / USEC_PER_SEC != value) + return -ERANGE; + + value *= USEC_PER_SEC; + + /* One "." is a decimal point, but ".." is a range separator */ + if (e[0] == '.' && e[1] != '.') { + unsigned add; + + e++; + r = parse_fractional_part_u(&e, 6, &add); + if (r < 0) + return r; + + if (add + value < value) + return -ERANGE; + value += add; + } + } + + if (value > INT_MAX) + return -ERANGE; + + *p = e; + *res = value; + + return 0; +} + +static int const_chain(int value, CalendarComponent **c) { + CalendarComponent *cc = NULL; + + assert(c); + + cc = new(CalendarComponent, 1); + if (!cc) + return -ENOMEM; + + *cc = (CalendarComponent) { + .start = value, + .stop = -1, + .repeat = 0, + .next = *c, + }; + + *c = cc; + + return 0; +} + +static int calendarspec_from_time_t(CalendarSpec *c, time_t time) { + _cleanup_(chain_freep) CalendarComponent + *year = NULL, *month = NULL, *day = NULL, + *hour = NULL, *minute = NULL, *us = NULL; + struct tm tm; + int r; + + if (!gmtime_r(&time, &tm)) + return -ERANGE; + + if (tm.tm_year > INT_MAX - 1900) + return -ERANGE; + + r = const_chain(tm.tm_year + 1900, &year); + if (r < 0) + return r; + + r = const_chain(tm.tm_mon + 1, &month); + if (r < 0) + return r; + + r = const_chain(tm.tm_mday, &day); + if (r < 0) + return r; + + r = const_chain(tm.tm_hour, &hour); + if (r < 0) + return r; + + r = const_chain(tm.tm_min, &minute); + if (r < 0) + return r; + + r = const_chain(tm.tm_sec * USEC_PER_SEC, &us); + if (r < 0) + return r; + + c->utc = true; + c->year = TAKE_PTR(year); + c->month = TAKE_PTR(month); + c->day = TAKE_PTR(day); + c->hour = TAKE_PTR(hour); + c->minute = TAKE_PTR(minute); + c->microsecond = TAKE_PTR(us); + return 0; +} + +static int prepend_component(const char **p, bool usec, unsigned nesting, CalendarComponent **c) { + int r, start, stop = -1, repeat = 0; + CalendarComponent *cc; + const char *e = *p; + + assert(p); + assert(c); + + if (nesting > CALENDARSPEC_COMPONENTS_MAX) + return -ENOBUFS; + + r = parse_component_decimal(&e, usec, &start); + if (r < 0) + return r; + + if (e[0] == '.' && e[1] == '.') { + e += 2; + r = parse_component_decimal(&e, usec, &stop); + if (r < 0) + return r; + + repeat = usec ? USEC_PER_SEC : 1; + } + + if (*e == '/') { + e++; + r = parse_component_decimal(&e, usec, &repeat); + if (r < 0) + return r; + + if (repeat == 0) + return -ERANGE; + } + + if (!IN_SET(*e, 0, ' ', ',', '-', '~', ':')) + return -EINVAL; + + cc = new(CalendarComponent, 1); + if (!cc) + return -ENOMEM; + + *cc = (CalendarComponent) { + .start = start, + .stop = stop, + .repeat = repeat, + .next = *c, + }; + + *p = e; + *c = cc; + + if (*e ==',') { + *p += 1; + return prepend_component(p, usec, nesting + 1, c); + } + + return 0; +} + +static int parse_chain(const char **p, bool usec, CalendarComponent **c) { + _cleanup_(chain_freep) CalendarComponent *cc = NULL; + const char *t; + int r; + + assert(p); + assert(c); + + t = *p; + + if (t[0] == '*') { + if (usec) { + r = const_chain(0, c); + if (r < 0) + return r; + (*c)->repeat = USEC_PER_SEC; + } else + *c = NULL; + + *p = t + 1; + return 0; + } + + r = prepend_component(&t, usec, 0, &cc); + if (r < 0) + return r; + + *p = t; + *c = TAKE_PTR(cc); + return 0; +} + +static int parse_date(const char **p, CalendarSpec *c) { + _cleanup_(chain_freep) CalendarComponent *first = NULL, *second = NULL, *third = NULL; + const char *t; + int r; + + assert(p); + assert(*p); + assert(c); + + t = *p; + + if (*t == 0) + return 0; + + /* @TIMESTAMP — UNIX time in seconds since the epoch */ + if (*t == '@') { + unsigned long value; + time_t time; + + r = parse_one_number(t + 1, &t, &value); + if (r < 0) + return r; + + time = value; + if ((unsigned long) time != value) + return -ERANGE; + + r = calendarspec_from_time_t(c, time); + if (r < 0) + return r; + + *p = t; + return 1; /* finito, don't parse H:M:S after that */ + } + + r = parse_chain(&t, false, &first); + if (r < 0) + return r; + + /* Already the end? A ':' as separator? In that case this was a time, not a date */ + if (IN_SET(*t, 0, ':')) + return 0; + + if (*t == '~') + c->end_of_month = true; + else if (*t != '-') + return -EINVAL; + + t++; + r = parse_chain(&t, false, &second); + if (r < 0) + return r; + + /* Got two parts, hence it's month and day */ + if (IN_SET(*t, 0, ' ')) { + *p = t + strspn(t, " "); + c->month = TAKE_PTR(first); + c->day = TAKE_PTR(second); + return 0; + } else if (c->end_of_month) + return -EINVAL; + + if (*t == '~') + c->end_of_month = true; + else if (*t != '-') + return -EINVAL; + + t++; + r = parse_chain(&t, false, &third); + if (r < 0) + return r; + + if (!IN_SET(*t, 0, ' ')) + return -EINVAL; + + /* Got three parts, hence it is year, month and day */ + *p = t + strspn(t, " "); + c->year = TAKE_PTR(first); + c->month = TAKE_PTR(second); + c->day = TAKE_PTR(third); + return 0; +} + +static int parse_calendar_time(const char **p, CalendarSpec *c) { + _cleanup_(chain_freep) CalendarComponent *h = NULL, *m = NULL, *s = NULL; + const char *t; + int r; + + assert(p); + assert(*p); + assert(c); + + t = *p; + + /* If no time is specified at all, then this means 00:00:00 */ + if (*t == 0) + goto null_hour; + + r = parse_chain(&t, false, &h); + if (r < 0) + return r; + + if (*t != ':') + return -EINVAL; + + t++; + r = parse_chain(&t, false, &m); + if (r < 0) + return r; + + /* Already at the end? Then it's hours and minutes, and seconds are 0 */ + if (*t == 0) + goto null_second; + + if (*t != ':') + return -EINVAL; + + t++; + r = parse_chain(&t, true, &s); + if (r < 0) + return r; + + /* At the end? Then it's hours, minutes and seconds */ + if (*t == 0) + goto finish; + + return -EINVAL; + +null_hour: + r = const_chain(0, &h); + if (r < 0) + return r; + + r = const_chain(0, &m); + if (r < 0) + return r; + +null_second: + r = const_chain(0, &s); + if (r < 0) + return r; + +finish: + *p = t; + c->hour = TAKE_PTR(h); + c->minute = TAKE_PTR(m); + c->microsecond = TAKE_PTR(s); + + return 0; +} + +int calendar_spec_from_string(const char *p, CalendarSpec **spec) { + const char *utc; + _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL; + _cleanup_free_ char *p_tmp = NULL; + int r; + + assert(p); + + c = new(CalendarSpec, 1); + if (!c) + return -ENOMEM; + + *c = (CalendarSpec) { + .dst = -1, + .timezone = NULL, + }; + + utc = endswith_no_case(p, " UTC"); + if (utc) { + c->utc = true; + p = p_tmp = strndup(p, utc - p); + if (!p) + return -ENOMEM; + } else { + const char *e = NULL; + int j; + + tzset(); + + /* Check if the local timezone was specified? */ + for (j = 0; j <= 1; j++) { + if (isempty(tzname[j])) + continue; + + e = endswith_no_case(p, tzname[j]); + if (!e) + continue; + if (e == p) + continue; + if (e[-1] != ' ') + continue; + + break; + } + + /* Found one of the two timezones specified? */ + if (IN_SET(j, 0, 1)) { + p = p_tmp = strndup(p, e - p - 1); + if (!p) + return -ENOMEM; + + c->dst = j; + } else { + const char *last_space; + + last_space = strrchr(p, ' '); + if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG)) { + c->timezone = strdup(last_space + 1); + if (!c->timezone) + return -ENOMEM; + + p = p_tmp = strndup(p, last_space - p); + if (!p) + return -ENOMEM; + } + } + } + + if (isempty(p)) + return -EINVAL; + + if (strcaseeq(p, "minutely")) { + r = const_chain(0, &c->microsecond); + if (r < 0) + return r; + + } else if (strcaseeq(p, "hourly")) { + r = const_chain(0, &c->minute); + if (r < 0) + return r; + r = const_chain(0, &c->microsecond); + if (r < 0) + return r; + + } else if (strcaseeq(p, "daily")) { + r = const_chain(0, &c->hour); + if (r < 0) + return r; + r = const_chain(0, &c->minute); + if (r < 0) + return r; + r = const_chain(0, &c->microsecond); + if (r < 0) + return r; + + } else if (strcaseeq(p, "monthly")) { + r = const_chain(1, &c->day); + if (r < 0) + return r; + r = const_chain(0, &c->hour); + if (r < 0) + return r; + r = const_chain(0, &c->minute); + if (r < 0) + return r; + r = const_chain(0, &c->microsecond); + if (r < 0) + return r; + + } else if (strcaseeq(p, "annually") || + strcaseeq(p, "yearly") || + strcaseeq(p, "anually") /* backwards compatibility */ ) { + + r = const_chain(1, &c->month); + if (r < 0) + return r; + r = const_chain(1, &c->day); + if (r < 0) + return r; + r = const_chain(0, &c->hour); + if (r < 0) + return r; + r = const_chain(0, &c->minute); + if (r < 0) + return r; + r = const_chain(0, &c->microsecond); + if (r < 0) + return r; + + } else if (strcaseeq(p, "weekly")) { + + c->weekdays_bits = 1; + + r = const_chain(0, &c->hour); + if (r < 0) + return r; + r = const_chain(0, &c->minute); + if (r < 0) + return r; + r = const_chain(0, &c->microsecond); + if (r < 0) + return r; + + } else if (strcaseeq(p, "quarterly")) { + + r = const_chain(1, &c->month); + if (r < 0) + return r; + r = const_chain(4, &c->month); + if (r < 0) + return r; + r = const_chain(7, &c->month); + if (r < 0) + return r; + r = const_chain(10, &c->month); + if (r < 0) + return r; + r = const_chain(1, &c->day); + if (r < 0) + return r; + r = const_chain(0, &c->hour); + if (r < 0) + return r; + r = const_chain(0, &c->minute); + if (r < 0) + return r; + r = const_chain(0, &c->microsecond); + if (r < 0) + return r; + + } else if (strcaseeq(p, "biannually") || + strcaseeq(p, "bi-annually") || + strcaseeq(p, "semiannually") || + strcaseeq(p, "semi-annually")) { + + r = const_chain(1, &c->month); + if (r < 0) + return r; + r = const_chain(7, &c->month); + if (r < 0) + return r; + r = const_chain(1, &c->day); + if (r < 0) + return r; + r = const_chain(0, &c->hour); + if (r < 0) + return r; + r = const_chain(0, &c->minute); + if (r < 0) + return r; + r = const_chain(0, &c->microsecond); + if (r < 0) + return r; + + } else { + r = parse_weekdays(&p, c); + if (r < 0) + return r; + + r = parse_date(&p, c); + if (r < 0) + return r; + + if (r == 0) { + r = parse_calendar_time(&p, c); + if (r < 0) + return r; + } + + if (*p != 0) + return -EINVAL; + } + + r = calendar_spec_normalize(c); + if (r < 0) + return r; + + if (!calendar_spec_valid(c)) + return -EINVAL; + + if (spec) + *spec = TAKE_PTR(c); + return 0; +} + +static int find_end_of_month(struct tm *tm, bool utc, int day) { + struct tm t = *tm; + + t.tm_mon++; + t.tm_mday = 1 - day; + + if (mktime_or_timegm(&t, utc) < 0 || + t.tm_mon != tm->tm_mon) + return -1; + + return t.tm_mday; +} + +static int find_matching_component(const CalendarSpec *spec, const CalendarComponent *c, + struct tm *tm, int *val) { + const CalendarComponent *p = c; + int start, stop, d = -1; + bool d_set = false; + int r; + + assert(val); + + if (!c) + return 0; + + while (c) { + start = c->start; + stop = c->stop; + + if (spec->end_of_month && p == spec->day) { + start = find_end_of_month(tm, spec->utc, start); + stop = find_end_of_month(tm, spec->utc, stop); + + if (stop > 0) + SWAP_TWO(start, stop); + } + + if (start >= *val) { + + if (!d_set || start < d) { + d = start; + d_set = true; + } + + } else if (c->repeat > 0) { + int k; + + k = start + c->repeat * DIV_ROUND_UP(*val - start, c->repeat); + + if ((!d_set || k < d) && (stop < 0 || k <= stop)) { + d = k; + d_set = true; + } + } + + c = c->next; + } + + if (!d_set) + return -ENOENT; + + r = *val != d; + *val = d; + return r; +} + +static int tm_within_bounds(struct tm *tm, bool utc) { + struct tm t; + assert(tm); + + /* + * Set an upper bound on the year so impossible dates like "*-02-31" + * don't cause find_next() to loop forever. tm_year contains years + * since 1900, so adjust it accordingly. + */ + if (tm->tm_year + 1900 > MAX_YEAR) + return -ERANGE; + + t = *tm; + if (mktime_or_timegm(&t, utc) < 0) + return negative_errno(); + + /* Did any normalization take place? If so, it was out of bounds before */ + bool good = t.tm_year == tm->tm_year && + t.tm_mon == tm->tm_mon && + t.tm_mday == tm->tm_mday && + t.tm_hour == tm->tm_hour && + t.tm_min == tm->tm_min && + t.tm_sec == tm->tm_sec; + if (!good) + *tm = t; + return good; +} + +static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) { + struct tm t; + int k; + + if (weekdays_bits < 0 || weekdays_bits >= BITS_WEEKDAYS) + return true; + + t = *tm; + if (mktime_or_timegm(&t, utc) < 0) + return false; + + k = t.tm_wday == 0 ? 6 : t.tm_wday - 1; + return (weekdays_bits & (1 << k)); +} + +static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { + struct tm c; + int tm_usec; + int r; + + /* Returns -ENOENT if the expression is not going to elapse anymore */ + + assert(spec); + assert(tm); + + c = *tm; + tm_usec = *usec; + + for (;;) { + /* Normalize the current date */ + (void) mktime_or_timegm(&c, spec->utc); + c.tm_isdst = spec->dst; + + c.tm_year += 1900; + r = find_matching_component(spec, spec->year, &c, &c.tm_year); + c.tm_year -= 1900; + + if (r > 0) { + c.tm_mon = 0; + c.tm_mday = 1; + c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; + } + if (r < 0) + return r; + if (tm_within_bounds(&c, spec->utc) <= 0) + return -ENOENT; + + c.tm_mon += 1; + r = find_matching_component(spec, spec->month, &c, &c.tm_mon); + c.tm_mon -= 1; + + if (r > 0) { + c.tm_mday = 1; + c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; + } + if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) { + c.tm_year++; + c.tm_mon = 0; + c.tm_mday = 1; + c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; + continue; + } + if (r == 0) + continue; + + r = find_matching_component(spec, spec->day, &c, &c.tm_mday); + if (r > 0) + c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; + if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) { + c.tm_mon++; + c.tm_mday = 1; + c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; + continue; + } + if (r == 0) + continue; + + if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) { + c.tm_mday++; + c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; + continue; + } + + r = find_matching_component(spec, spec->hour, &c, &c.tm_hour); + if (r > 0) + c.tm_min = c.tm_sec = tm_usec = 0; + if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) { + c.tm_mday++; + c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; + continue; + } + if (r == 0) + /* The next hour we set might be missing if there + * are time zone changes. Let's try again starting at + * normalized time. */ + continue; + + r = find_matching_component(spec, spec->minute, &c, &c.tm_min); + if (r > 0) + c.tm_sec = tm_usec = 0; + if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) { + c.tm_hour++; + c.tm_min = c.tm_sec = tm_usec = 0; + continue; + } + if (r == 0) + continue; + + c.tm_sec = c.tm_sec * USEC_PER_SEC + tm_usec; + r = find_matching_component(spec, spec->microsecond, &c, &c.tm_sec); + tm_usec = c.tm_sec % USEC_PER_SEC; + c.tm_sec /= USEC_PER_SEC; + + if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) { + c.tm_min++; + c.tm_sec = tm_usec = 0; + continue; + } + if (r == 0) + continue; + + *tm = c; + *usec = tm_usec; + return 0; + } +} + +static int calendar_spec_next_usec_impl(const CalendarSpec *spec, usec_t usec, usec_t *ret_next) { + struct tm tm; + time_t t; + int r; + usec_t tm_usec; + + assert(spec); + + if (usec > USEC_TIMESTAMP_FORMATTABLE_MAX) + return -EINVAL; + + usec++; + t = (time_t) (usec / USEC_PER_SEC); + assert_se(localtime_or_gmtime_r(&t, &tm, spec->utc)); + tm_usec = usec % USEC_PER_SEC; + + r = find_next(spec, &tm, &tm_usec); + if (r < 0) + return r; + + t = mktime_or_timegm(&tm, spec->utc); + if (t < 0) + return -EINVAL; + + if (ret_next) + *ret_next = (usec_t) t * USEC_PER_SEC + tm_usec; + + return 0; +} + +typedef struct SpecNextResult { + usec_t next; + int return_value; +} SpecNextResult; + +int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *ret_next) { + SpecNextResult *shared, tmp; + int r; + + assert(spec); + + if (isempty(spec->timezone)) + return calendar_spec_next_usec_impl(spec, usec, ret_next); + + shared = mmap(NULL, sizeof *shared, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); + if (shared == MAP_FAILED) + return negative_errno(); + + r = safe_fork("(sd-calendar)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT, NULL); + if (r < 0) { + (void) munmap(shared, sizeof *shared); + return r; + } + if (r == 0) { + char *colon_tz; + + /* tzset(3) says $TZ should be prefixed with ":" if we reference timezone files */ + colon_tz = strjoina(":", spec->timezone); + + if (setenv("TZ", colon_tz, 1) != 0) { + shared->return_value = negative_errno(); + _exit(EXIT_FAILURE); + } + + tzset(); + + shared->return_value = calendar_spec_next_usec_impl(spec, usec, &shared->next); + + _exit(EXIT_SUCCESS); + } + + tmp = *shared; + if (munmap(shared, sizeof *shared) < 0) + return negative_errno(); + + if (tmp.return_value == 0 && ret_next) + *ret_next = tmp.next; + + return tmp.return_value; +} diff --git a/src/shared/calendarspec.h b/src/shared/calendarspec.h new file mode 100644 index 00000000..3bf8a39e --- /dev/null +++ b/src/shared/calendarspec.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/* A structure for specifying (possibly repetitive) points in calendar + * time, a la cron */ + +#include + +#include "time-util.h" +#include "util.h" + +typedef struct CalendarComponent { + int start; + int stop; + int repeat; + + struct CalendarComponent *next; +} CalendarComponent; + +typedef struct CalendarSpec { + int weekdays_bits; + bool end_of_month; + bool utc; + int dst; + char *timezone; + + CalendarComponent *year; + CalendarComponent *month; + CalendarComponent *day; + + CalendarComponent *hour; + CalendarComponent *minute; + CalendarComponent *microsecond; +} CalendarSpec; + +CalendarSpec* calendar_spec_free(CalendarSpec *c); + +int calendar_spec_normalize(CalendarSpec *spec); +bool calendar_spec_valid(CalendarSpec *spec); + +int calendar_spec_to_string(const CalendarSpec *spec, char **p); +int calendar_spec_from_string(const char *p, CalendarSpec **spec); + +int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next); + +DEFINE_TRIVIAL_CLEANUP_FUNC(CalendarSpec*, calendar_spec_free); diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c new file mode 100644 index 00000000..e8398cbd --- /dev/null +++ b/src/shared/cgroup-setup.c @@ -0,0 +1,859 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "cgroup-setup.h" +#include "cgroup-util.h" +#include "errno-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "stdio-util.h" +#include "string-util.h" +#include "fs-util.h" +#include "mkdir.h" +#include "process-util.h" +#include "fileio.h" +#include "user-util.h" +#include "fd-util.h" + +bool cg_is_unified_wanted(void) { + static thread_local int wanted = -1; + bool b; + const bool is_default = DEFAULT_HIERARCHY == CGROUP_UNIFIED_ALL; + _cleanup_free_ char *c = NULL; + int r; + + /* If we have a cached value, return that. */ + if (wanted >= 0) + return wanted; + + /* If the hierarchy is already mounted, then follow whatever was chosen for it. */ + r = cg_unified_cached(true); + if (r >= 0) + return (wanted = r >= CGROUP_UNIFIED_ALL); + + /* If we were explicitly passed systemd.unified_cgroup_hierarchy, respect that. */ + r = proc_cmdline_get_bool("systemd.unified_cgroup_hierarchy", &b); + if (r > 0) + return (wanted = b); + + /* If we passed cgroup_no_v1=all with no other instructions, it seems highly unlikely that we want to + * use hybrid or legacy hierarchy. */ + r = proc_cmdline_get_key("cgroup_no_v1", 0, &c); + if (r > 0 && streq_ptr(c, "all")) + return (wanted = true); + + return (wanted = is_default); +} + +bool cg_is_legacy_wanted(void) { + static thread_local int wanted = -1; + + /* If we have a cached value, return that. */ + if (wanted >= 0) + return wanted; + + /* Check if we have cgroup v2 already mounted. */ + if (cg_unified_cached(true) == CGROUP_UNIFIED_ALL) + return (wanted = false); + + /* Otherwise, assume that at least partial legacy is wanted, + * since cgroup v2 should already be mounted at this point. */ + return (wanted = true); +} + +bool cg_is_hybrid_wanted(void) { + static thread_local int wanted = -1; + int r; + bool b; + const bool is_default = DEFAULT_HIERARCHY >= CGROUP_UNIFIED_SYSTEMD; + /* We default to true if the default is "hybrid", obviously, but also when the default is "unified", + * because if we get called, it means that unified hierarchy was not mounted. */ + + /* If we have a cached value, return that. */ + if (wanted >= 0) + return wanted; + + /* If the hierarchy is already mounted, then follow whatever was chosen for it. */ + if (cg_unified_cached(true) == CGROUP_UNIFIED_ALL) + return (wanted = false); + + /* Otherwise, let's see what the kernel command line has to say. Since checking is expensive, cache + * a non-error result. */ + r = proc_cmdline_get_bool("systemd.legacy_systemd_cgroup_controller", &b); + + /* The meaning of the kernel option is reversed wrt. to the return value of this function, hence the + * negation. */ + return (wanted = r > 0 ? !b : is_default); +} + +int cg_weight_parse(const char *s, uint64_t *ret) { + uint64_t u; + int r; + + if (isempty(s)) { + *ret = CGROUP_WEIGHT_INVALID; + return 0; + } + + r = safe_atou64(s, &u); + if (r < 0) + return r; + + if (u < CGROUP_WEIGHT_MIN || u > CGROUP_WEIGHT_MAX) + return -ERANGE; + + *ret = u; + return 0; +} + +int cg_cpu_shares_parse(const char *s, uint64_t *ret) { + uint64_t u; + int r; + + if (isempty(s)) { + *ret = CGROUP_CPU_SHARES_INVALID; + return 0; + } + + r = safe_atou64(s, &u); + if (r < 0) + return r; + + if (u < CGROUP_CPU_SHARES_MIN || u > CGROUP_CPU_SHARES_MAX) + return -ERANGE; + + *ret = u; + return 0; +} + +int cg_blkio_weight_parse(const char *s, uint64_t *ret) { + uint64_t u; + int r; + + if (isempty(s)) { + *ret = CGROUP_BLKIO_WEIGHT_INVALID; + return 0; + } + + r = safe_atou64(s, &u); + if (r < 0) + return r; + + if (u < CGROUP_BLKIO_WEIGHT_MIN || u > CGROUP_BLKIO_WEIGHT_MAX) + return -ERANGE; + + *ret = u; + return 0; +} + +static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { + assert(path); + assert(sb); + assert(ftwbuf); + + if (typeflag != FTW_DP) + return 0; + + if (ftwbuf->level < 1) + return 0; + + (void) rmdir(path); + return 0; +} + +int cg_trim(const char *controller, const char *path, bool delete_root) { + _cleanup_free_ char *fs = NULL; + int r = 0, q; + + assert(path); + + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + errno = 0; + if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0) { + if (errno == ENOENT) + r = 0; + else + r = errno_or_else(EIO); + } + + if (delete_root) { + if (rmdir(fs) < 0 && errno != ENOENT) + return -errno; + } + + q = cg_hybrid_unified(); + if (q < 0) + return q; + if (q > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { + q = cg_trim(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, delete_root); + if (q < 0) + log_warning_errno(q, "Failed to trim compat systemd cgroup %s: %m", path); + } + + return r; +} + +/* Create a cgroup in the hierarchy of controller. + * Returns 0 if the group already existed, 1 on success, negative otherwise. + */ +int cg_create(const char *controller, const char *path) { + _cleanup_free_ char *fs = NULL; + int r; + + r = cg_get_path_and_check(controller, path, NULL, &fs); + if (r < 0) + return r; + + r = mkdir_parents(fs, 0755); + if (r < 0) + return r; + + r = mkdir_errno_wrapper(fs, 0755); + if (r == -EEXIST) + return 0; + if (r < 0) + return r; + + r = cg_hybrid_unified(); + if (r < 0) + return r; + + if (r > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { + r = cg_create(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path); + if (r < 0) + log_warning_errno(r, "Failed to create compat systemd cgroup %s: %m", path); + } + + return 1; +} + +int cg_create_and_attach(const char *controller, const char *path, pid_t pid) { + int r, q; + + assert(pid >= 0); + + r = cg_create(controller, path); + if (r < 0) + return r; + + q = cg_attach(controller, path, pid); + if (q < 0) + return q; + + /* This does not remove the cgroup on failure */ + return r; +} + +int cg_attach(const char *controller, const char *path, pid_t pid) { + _cleanup_free_ char *fs = NULL; + char c[DECIMAL_STR_MAX(pid_t) + 2]; + int r; + + assert(path); + assert(pid >= 0); + + r = cg_get_path_and_check(controller, path, "cgroup.procs", &fs); + if (r < 0) + return r; + + if (pid == 0) + pid = getpid_cached(); + + xsprintf(c, PID_FMT "\n", pid); + + r = write_string_file(fs, c, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return r; + + r = cg_hybrid_unified(); + if (r < 0) + return r; + + if (r > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { + r = cg_attach(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, pid); + if (r < 0) + log_warning_errno(r, "Failed to attach "PID_FMT" to compat systemd cgroup %s: %m", pid, path); + } + + return 0; +} + +int cg_attach_fallback(const char *controller, const char *path, pid_t pid) { + int r; + + assert(controller); + assert(path); + assert(pid >= 0); + + r = cg_attach(controller, path, pid); + if (r < 0) { + char prefix[strlen(path) + 1]; + + /* This didn't work? Then let's try all prefixes of + * the destination */ + + PATH_FOREACH_PREFIX(prefix, path) { + int q; + + q = cg_attach(controller, prefix, pid); + if (q >= 0) + return q; + } + } + + return r; +} + +int cg_set_access( + const char *controller, + const char *path, + uid_t uid, + gid_t gid) { + + struct Attribute { + const char *name; + bool fatal; + }; + + /* cgroup v1, aka legacy/non-unified */ + static const struct Attribute legacy_attributes[] = { + { "cgroup.procs", true }, + { "tasks", false }, + { "cgroup.clone_children", false }, + {}, + }; + + /* cgroup v2, aka unified */ + static const struct Attribute unified_attributes[] = { + { "cgroup.procs", true }, + { "cgroup.subtree_control", true }, + { "cgroup.threads", false }, + {}, + }; + + static const struct Attribute* const attributes[] = { + [false] = legacy_attributes, + [true] = unified_attributes, + }; + + _cleanup_free_ char *fs = NULL; + const struct Attribute *i; + int r, unified; + + assert(path); + + if (uid == UID_INVALID && gid == GID_INVALID) + return 0; + + unified = cg_unified_controller(controller); + if (unified < 0) + return unified; + + /* Configure access to the cgroup itself */ + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + r = chmod_and_chown(fs, 0755, uid, gid); + if (r < 0) + return r; + + /* Configure access to the cgroup's attributes */ + for (i = attributes[unified]; i->name; i++) { + fs = mfree(fs); + + r = cg_get_path(controller, path, i->name, &fs); + if (r < 0) + return r; + + r = chmod_and_chown(fs, 0644, uid, gid); + if (r < 0) { + if (i->fatal) + return r; + + log_debug_errno(r, "Failed to set access on cgroup %s, ignoring: %m", fs); + } + } + + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { + r = cg_hybrid_unified(); + if (r < 0) + return r; + if (r > 0) { + /* Always propagate access mode from unified to legacy controller */ + r = cg_set_access(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, uid, gid); + if (r < 0) + log_debug_errno(r, "Failed to set access on compatibility systemd cgroup %s, ignoring: %m", path); + } + } + + return 0; +} + +int cg_migrate( + const char *cfrom, + const char *pfrom, + const char *cto, + const char *pto, + CGroupFlags flags) { + + bool done = false; + _cleanup_set_free_ Set *s = NULL; + int r, ret = 0; + pid_t my_pid; + + assert(cfrom); + assert(pfrom); + assert(cto); + assert(pto); + + s = set_new(NULL); + if (!s) + return -ENOMEM; + + my_pid = getpid_cached(); + + do { + _cleanup_fclose_ FILE *f = NULL; + pid_t pid = 0; + done = true; + + r = cg_enumerate_processes(cfrom, pfrom, &f); + if (r < 0) { + if (ret >= 0 && r != -ENOENT) + return r; + + return ret; + } + + while ((r = cg_read_pid(f, &pid)) > 0) { + + /* This might do weird stuff if we aren't a + * single-threaded program. However, we + * luckily know we are not */ + if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid) + continue; + + if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid)) + continue; + + /* Ignore kernel threads. Since they can only + * exist in the root cgroup, we only check for + * them there. */ + if (cfrom && + empty_or_root(pfrom) && + is_kernel_thread(pid) > 0) + continue; + + r = cg_attach(cto, pto, pid); + if (r < 0) { + if (ret >= 0 && r != -ESRCH) + ret = r; + } else if (ret == 0) + ret = 1; + + done = false; + + r = set_put(s, PID_TO_PTR(pid)); + if (r < 0) { + if (ret >= 0) + return r; + + return ret; + } + } + + if (r < 0) { + if (ret >= 0) + return r; + + return ret; + } + } while (!done); + + return ret; +} + +int cg_migrate_recursive( + const char *cfrom, + const char *pfrom, + const char *cto, + const char *pto, + CGroupFlags flags) { + + _cleanup_closedir_ DIR *d = NULL; + int r, ret = 0; + char *fn; + + assert(cfrom); + assert(pfrom); + assert(cto); + assert(pto); + + ret = cg_migrate(cfrom, pfrom, cto, pto, flags); + + r = cg_enumerate_subgroups(cfrom, pfrom, &d); + if (r < 0) { + if (ret >= 0 && r != -ENOENT) + return r; + + return ret; + } + + while ((r = cg_read_subgroup(d, &fn)) > 0) { + _cleanup_free_ char *p = NULL; + + p = path_join(empty_to_root(pfrom), fn); + free(fn); + if (!p) + return -ENOMEM; + + r = cg_migrate_recursive(cfrom, p, cto, pto, flags); + if (r != 0 && ret >= 0) + ret = r; + } + + if (r < 0 && ret >= 0) + ret = r; + + if (flags & CGROUP_REMOVE) { + r = cg_rmdir(cfrom, pfrom); + if (r < 0 && ret >= 0 && !IN_SET(r, -ENOENT, -EBUSY)) + return r; + } + + return ret; +} + +int cg_migrate_recursive_fallback( + const char *cfrom, + const char *pfrom, + const char *cto, + const char *pto, + CGroupFlags flags) { + + int r; + + assert(cfrom); + assert(pfrom); + assert(cto); + assert(pto); + + r = cg_migrate_recursive(cfrom, pfrom, cto, pto, flags); + if (r < 0) { + char prefix[strlen(pto) + 1]; + + /* This didn't work? Then let's try all prefixes of the destination */ + + PATH_FOREACH_PREFIX(prefix, pto) { + int q; + + q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, flags); + if (q >= 0) + return q; + } + } + + return r; +} + +int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path) { + CGroupController c; + CGroupMask done; + bool created; + int r; + + /* This one will create a cgroup in our private tree, but also + * duplicate it in the trees specified in mask, and remove it + * in all others. + * + * Returns 0 if the group already existed in the systemd hierarchy, + * 1 on success, negative otherwise. + */ + + /* First create the cgroup in our own hierarchy. */ + r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path); + if (r < 0) + return r; + created = r; + + /* If we are in the unified hierarchy, we are done now */ + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) + return created; + + supported &= CGROUP_MASK_V1; + mask = CGROUP_MASK_EXTEND_JOINED(mask); + done = 0; + + /* Otherwise, do the same in the other hierarchies */ + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { + CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); + const char *n; + + if (!FLAGS_SET(supported, bit)) + continue; + + if (FLAGS_SET(done, bit)) + continue; + + n = cgroup_controller_to_string(c); + if (FLAGS_SET(mask, bit)) + (void) cg_create(n, path); + else + (void) cg_trim(n, path, true); + + done |= CGROUP_MASK_EXTEND_JOINED(bit); + } + + return created; +} + +int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_migrate_callback_t path_callback, void *userdata) { + CGroupController c; + CGroupMask done; + int r; + + r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid); + if (r < 0) + return r; + + r = cg_all_unified(); + if (r < 0) + return r; + if (r > 0) + return 0; + + supported &= CGROUP_MASK_V1; + done = 0; + + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { + CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); + const char *p = NULL; + + if (!FLAGS_SET(supported, bit)) + continue; + + if (FLAGS_SET(done, bit)) + continue; + + if (path_callback) + p = path_callback(bit, userdata); + if (!p) + p = path; + + (void) cg_attach_fallback(cgroup_controller_to_string(c), p, pid); + done |= CGROUP_MASK_EXTEND_JOINED(bit); + } + + return 0; +} + +int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids, cg_migrate_callback_t path_callback, void *userdata) { + Iterator i; + void *pidp; + int r = 0; + + SET_FOREACH(pidp, pids, i) { + pid_t pid = PTR_TO_PID(pidp); + int q; + + q = cg_attach_everywhere(supported, path, pid, path_callback, userdata); + if (q < 0 && r >= 0) + r = q; + } + + return r; +} + +int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) { + CGroupController c; + CGroupMask done; + int r = 0, q; + + if (!path_equal(from, to)) { + r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, CGROUP_REMOVE); + if (r < 0) + return r; + } + + q = cg_all_unified(); + if (q < 0) + return q; + if (q > 0) + return r; + + supported &= CGROUP_MASK_V1; + done = 0; + + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { + CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); + const char *p = NULL; + + if (!FLAGS_SET(supported, bit)) + continue; + + if (FLAGS_SET(done, bit)) + continue; + + if (to_callback) + p = to_callback(bit, userdata); + if (!p) + p = to; + + (void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, 0); + done |= CGROUP_MASK_EXTEND_JOINED(bit); + } + + return r; +} + +int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root) { + CGroupController c; + CGroupMask done; + int r, q; + + r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root); + if (r < 0) + return r; + + q = cg_all_unified(); + if (q < 0) + return q; + if (q > 0) + return r; + + supported &= CGROUP_MASK_V1; + done = 0; + + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { + CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); + + if (!FLAGS_SET(supported, bit)) + continue; + + if (FLAGS_SET(done, bit)) + continue; + + (void) cg_trim(cgroup_controller_to_string(c), path, delete_root); + done |= CGROUP_MASK_EXTEND_JOINED(bit); + } + + return r; +} + +int cg_enable_everywhere( + CGroupMask supported, + CGroupMask mask, + const char *p, + CGroupMask *ret_result_mask) { + + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *fs = NULL; + CGroupController c; + CGroupMask ret = 0; + int r; + + assert(p); + + if (supported == 0) { + if (ret_result_mask) + *ret_result_mask = 0; + return 0; + } + + r = cg_all_unified(); + if (r < 0) + return r; + if (r == 0) { + /* On the legacy hierarchy there's no concept of "enabling" controllers in cgroups defined. Let's claim + * complete success right away. (If you wonder why we return the full mask here, rather than zero: the + * caller tends to use the returned mask later on to compare if all controllers where properly joined, + * and if not requeues realization. This use is the primary purpose of the return value, hence let's + * minimize surprises here and reduce triggers for re-realization by always saying we fully + * succeeded.) */ + if (ret_result_mask) + *ret_result_mask = mask & supported & CGROUP_MASK_V2; /* If you wonder why we mask this with + * CGROUP_MASK_V2: The 'supported' mask + * might contain pure-V1 or BPF + * controllers, and we never want to + * claim that we could enable those with + * cgroup.subtree_control */ + return 0; + } + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, p, "cgroup.subtree_control", &fs); + if (r < 0) + return r; + + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) { + CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c); + const char *n; + + if (!FLAGS_SET(CGROUP_MASK_V2, bit)) + continue; + + if (!FLAGS_SET(supported, bit)) + continue; + + n = cgroup_controller_to_string(c); + { + char s[1 + strlen(n) + 1]; + + s[0] = FLAGS_SET(mask, bit) ? '+' : '-'; + strcpy(s + 1, n); + + if (!f) { + f = fopen(fs, "we"); + if (!f) + return log_debug_errno(errno, "Failed to open cgroup.subtree_control file of %s: %m", p); + } + + r = write_string_stream(f, s, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) { + log_debug_errno(r, "Failed to %s controller %s for %s (%s): %m", + FLAGS_SET(mask, bit) ? "enable" : "disable", n, p, fs); + clearerr(f); + + /* If we can't turn off a controller, leave it on in the reported resulting mask. This + * happens for example when we attempt to turn off a controller up in the tree that is + * used down in the tree. */ + if (!FLAGS_SET(mask, bit) && r == -EBUSY) /* You might wonder why we check for EBUSY + * only here, and not follow the same logic + * for other errors such as EINVAL or + * EOPNOTSUPP or anything else. That's + * because EBUSY indicates that the + * controllers is currently enabled and + * cannot be disabled because something down + * the hierarchy is still using it. Any other + * error most likely means something like "I + * never heard of this controller" or + * similar. In the former case it's hence + * safe to assume the controller is still on + * after the failed operation, while in the + * latter case it's safer to assume the + * controller is unknown and hence certainly + * not enabled. */ + ret |= bit; + } else { + /* Otherwise, if we managed to turn on a controller, set the bit reflecting that. */ + if (FLAGS_SET(mask, bit)) + ret |= bit; + } + } + } + + /* Let's return the precise set of controllers now enabled for the cgroup. */ + if (ret_result_mask) + *ret_result_mask = ret; + + return 0; +} diff --git a/src/shared/cgroup-setup.h b/src/shared/cgroup-setup.h new file mode 100644 index 00000000..6e9b6857 --- /dev/null +++ b/src/shared/cgroup-setup.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "cgroup-util.h" + +bool cg_is_unified_wanted(void); +bool cg_is_legacy_wanted(void); +bool cg_is_hybrid_wanted(void); + +int cg_weight_parse(const char *s, uint64_t *ret); +int cg_cpu_shares_parse(const char *s, uint64_t *ret); +int cg_blkio_weight_parse(const char *s, uint64_t *ret); + +int cg_trim(const char *controller, const char *path, bool delete_root); + +int cg_create(const char *controller, const char *path); +int cg_attach(const char *controller, const char *path, pid_t pid); +int cg_attach_fallback(const char *controller, const char *path, pid_t pid); +int cg_create_and_attach(const char *controller, const char *path, pid_t pid); + +int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags); +int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags); +int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags); + +int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path); +int cg_attach_everywhere(CGroupMask supported, const char *path, pid_t pid, cg_migrate_callback_t callback, void *userdata); +int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids, cg_migrate_callback_t callback, void *userdata); +int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to, cg_migrate_callback_t callback, void *userdata); +int cg_trim_everywhere(CGroupMask supported, const char *path, bool delete_root); +int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p, CGroupMask *ret_result_mask); diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c new file mode 100644 index 00000000..208d27df --- /dev/null +++ b/src/shared/cgroup-show.c @@ -0,0 +1,400 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "cgroup-show.h" +#include "cgroup-util.h" +#include "env-file.h" +#include "fd-util.h" +#include "format-util.h" +#include "locale-util.h" +#include "macro.h" +#include "output-mode.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "sort-util.h" +#include "string-util.h" +#include "terminal-util.h" +#include "unit-name.h" +#include "xattr-util.h" + +static void show_pid_array( + pid_t pids[], + unsigned n_pids, + const char *prefix, + size_t n_columns, + bool extra, + bool more, + OutputFlags flags) { + + unsigned i, j, pid_width; + + if (n_pids == 0) + return; + + typesafe_qsort(pids, n_pids, pid_compare_func); + + /* Filter duplicates */ + for (j = 0, i = 1; i < n_pids; i++) { + if (pids[i] == pids[j]) + continue; + pids[++j] = pids[i]; + } + n_pids = j + 1; + pid_width = DECIMAL_STR_WIDTH(pids[j]); + + if (flags & OUTPUT_FULL_WIDTH) + n_columns = SIZE_MAX; + else { + if (n_columns > pid_width + 3) /* something like "├─1114784 " */ + n_columns -= pid_width + 3; + else + n_columns = 20; + } + for (i = 0; i < n_pids; i++) { + _cleanup_free_ char *t = NULL; + + (void) get_process_cmdline(pids[i], n_columns, + PROCESS_CMDLINE_COMM_FALLBACK | PROCESS_CMDLINE_USE_LOCALE, + &t); + + if (extra) + printf("%s%s ", prefix, special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET)); + else + printf("%s%s", prefix, special_glyph(((more || i < n_pids-1) ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT))); + + printf("%s%*"PID_PRI" %s%s\n", ansi_grey(), pid_width, pids[i], strna(t), ansi_normal()); + } +} + +static int show_cgroup_one_by_path( + const char *path, + const char *prefix, + size_t n_columns, + bool more, + OutputFlags flags) { + + char *fn; + _cleanup_fclose_ FILE *f = NULL; + size_t n = 0, n_allocated = 0; + _cleanup_free_ pid_t *pids = NULL; + _cleanup_free_ char *p = NULL; + pid_t pid; + int r; + + r = cg_mangle_path(path, &p); + if (r < 0) + return r; + + fn = strjoina(p, "/cgroup.procs"); + f = fopen(fn, "re"); + if (!f) + return -errno; + + while ((r = cg_read_pid(f, &pid)) > 0) { + + if (!(flags & OUTPUT_KERNEL_THREADS) && is_kernel_thread(pid) > 0) + continue; + + if (!GREEDY_REALLOC(pids, n_allocated, n + 1)) + return -ENOMEM; + + assert(n < n_allocated); + pids[n++] = pid; + } + + if (r < 0) + return r; + + show_pid_array(pids, n, prefix, n_columns, false, more, flags); + + return 0; +} + +static int show_cgroup_name( + const char *path, + const char *prefix, + const char *glyph) { + + _cleanup_free_ char *b = NULL; + bool delegate = false; + int r; + + r = getxattr_malloc(path, "trusted.delegate", &b, false); + if (r < 0) { + if (r != -ENODATA) + log_debug_errno(r, "Failed to read trusted.delegate extended attribute: %m"); + } else { + r = parse_boolean(b); + if (r < 0) + log_debug_errno(r, "Failed to parse trusted.delegate extended attribute boolean value: %m"); + else + delegate = r > 0; + + b = mfree(b); + } + + b = strdup(basename(path)); + if (!b) + return -ENOMEM; + + printf("%s%s%s%s%s %s%s%s\n", + prefix, glyph, + delegate ? ansi_underline() : "", + cg_unescape(b), + delegate ? ansi_normal() : "", + delegate ? ansi_highlight() : "", + delegate ? special_glyph(SPECIAL_GLYPH_ELLIPSIS) : "", + delegate ? ansi_normal() : ""); + return 0; +} + +int show_cgroup_by_path( + const char *path, + const char *prefix, + size_t n_columns, + OutputFlags flags) { + + _cleanup_free_ char *fn = NULL, *p1 = NULL, *last = NULL, *p2 = NULL; + _cleanup_closedir_ DIR *d = NULL; + bool shown_pids = false; + char *gn = NULL; + int r; + + assert(path); + + if (n_columns <= 0) + n_columns = columns(); + + prefix = strempty(prefix); + + r = cg_mangle_path(path, &fn); + if (r < 0) + return r; + + d = opendir(fn); + if (!d) + return -errno; + + while ((r = cg_read_subgroup(d, &gn)) > 0) { + _cleanup_free_ char *k = NULL; + + k = path_join(fn, gn); + free(gn); + if (!k) + return -ENOMEM; + + if (!(flags & OUTPUT_SHOW_ALL) && cg_is_empty_recursive(NULL, k) > 0) + continue; + + if (!shown_pids) { + show_cgroup_one_by_path(path, prefix, n_columns, true, flags); + shown_pids = true; + } + + if (last) { + r = show_cgroup_name(last, prefix, special_glyph(SPECIAL_GLYPH_TREE_BRANCH)); + if (r < 0) + return r; + + if (!p1) { + p1 = strjoin(prefix, special_glyph(SPECIAL_GLYPH_TREE_VERTICAL)); + if (!p1) + return -ENOMEM; + } + + show_cgroup_by_path(last, p1, n_columns-2, flags); + free(last); + } + + last = TAKE_PTR(k); + } + + if (r < 0) + return r; + + if (!shown_pids) + show_cgroup_one_by_path(path, prefix, n_columns, !!last, flags); + + if (last) { + r = show_cgroup_name(last, prefix, special_glyph(SPECIAL_GLYPH_TREE_RIGHT)); + if (r < 0) + return r; + + if (!p2) { + p2 = strjoin(prefix, " "); + if (!p2) + return -ENOMEM; + } + + show_cgroup_by_path(last, p2, n_columns-2, flags); + } + + return 0; +} + +int show_cgroup(const char *controller, + const char *path, + const char *prefix, + size_t n_columns, + OutputFlags flags) { + _cleanup_free_ char *p = NULL; + int r; + + assert(path); + + r = cg_get_path(controller, path, NULL, &p); + if (r < 0) + return r; + + return show_cgroup_by_path(p, prefix, n_columns, flags); +} + +static int show_extra_pids( + const char *controller, + const char *path, + const char *prefix, + size_t n_columns, + const pid_t pids[], + unsigned n_pids, + OutputFlags flags) { + + _cleanup_free_ pid_t *copy = NULL; + unsigned i, j; + int r; + + assert(path); + + if (n_pids <= 0) + return 0; + + if (n_columns <= 0) + n_columns = columns(); + + prefix = strempty(prefix); + + copy = new(pid_t, n_pids); + if (!copy) + return -ENOMEM; + + for (i = 0, j = 0; i < n_pids; i++) { + _cleanup_free_ char *k = NULL; + + r = cg_pid_get_path(controller, pids[i], &k); + if (r < 0) + return r; + + if (path_startswith(k, path)) + continue; + + copy[j++] = pids[i]; + } + + show_pid_array(copy, j, prefix, n_columns, true, false, flags); + + return 0; +} + +int show_cgroup_and_extra( + const char *controller, + const char *path, + const char *prefix, + size_t n_columns, + const pid_t extra_pids[], + unsigned n_extra_pids, + OutputFlags flags) { + + int r; + + assert(path); + + r = show_cgroup(controller, path, prefix, n_columns, flags); + if (r < 0) + return r; + + return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids, flags); +} + +int show_cgroup_get_unit_path_and_warn( + sd_bus *bus, + const char *unit, + char **ret) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + int r; + + path = unit_dbus_path_from_name(unit); + if (!path) + return log_oom(); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + path, + unit_dbus_interface_from_name(unit), + "ControlGroup", + &error, + ret); + if (r < 0) + return log_error_errno(r, "Failed to query unit control group path: %s", + bus_error_message(&error, r)); + + return 0; +} + +int show_cgroup_get_path_and_warn( + const char *machine, + const char *prefix, + char **ret) { + + int r; + _cleanup_free_ char *root = NULL; + + if (machine) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *unit = NULL; + const char *m; + + m = strjoina("/run/systemd/machines/", machine); + r = parse_env_file(NULL, m, "SCOPE", &unit); + if (r < 0) + return log_error_errno(r, "Failed to load machine data: %m"); + + r = bus_connect_transport_systemd(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + r = show_cgroup_get_unit_path_and_warn(bus, unit, &root); + if (r < 0) + return r; + } else { + r = cg_get_root_path(&root); + if (r == -ENOMEDIUM) + return log_error_errno(r, "Failed to get root control group path.\n" + "No cgroup filesystem mounted on /sys/fs/cgroup"); + else if (r < 0) + return log_error_errno(r, "Failed to get root control group path: %m"); + } + + if (prefix) { + char *t; + + t = strjoin(root, prefix); + if (!t) + return log_oom(); + + *ret = t; + } else + *ret = TAKE_PTR(root); + + return 0; +} diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h new file mode 100644 index 00000000..dfb26f82 --- /dev/null +++ b/src/shared/cgroup-show.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-bus.h" + +#include "logs-show.h" +#include "output-mode.h" + +int show_cgroup_by_path(const char *path, const char *prefix, size_t n_columns, OutputFlags flags); +int show_cgroup(const char *controller, const char *path, const char *prefix, size_t n_columns, OutputFlags flags); + +int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, size_t n_columns, const pid_t extra_pids[], unsigned n_extra_pids, OutputFlags flags); + +int show_cgroup_get_unit_path_and_warn( + sd_bus *bus, + const char *unit, + char **ret); +int show_cgroup_get_path_and_warn( + const char *machine, + const char *prefix, + char **ret); diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c new file mode 100644 index 00000000..e4cd2d30 --- /dev/null +++ b/src/shared/clean-ipc.c @@ -0,0 +1,451 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clean-ipc.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "log.h" +#include "macro.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" + +static bool match_uid_gid(uid_t subject_uid, gid_t subject_gid, uid_t delete_uid, gid_t delete_gid) { + + if (uid_is_valid(delete_uid) && subject_uid == delete_uid) + return true; + + if (gid_is_valid(delete_gid) && subject_gid == delete_gid) + return true; + + return false; +} + +static int clean_sysvipc_shm(uid_t delete_uid, gid_t delete_gid, bool rm) { + _cleanup_fclose_ FILE *f = NULL; + bool first = true; + int ret = 0, r; + + f = fopen("/proc/sysvipc/shm", "re"); + if (!f) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to open /proc/sysvipc/shm: %m"); + } + + for (;;) { + _cleanup_free_ char *line = NULL; + unsigned n_attached; + pid_t cpid, lpid; + uid_t uid, cuid; + gid_t gid, cgid; + int shmid; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_warning_errno(errno, "Failed to read /proc/sysvipc/shm: %m"); + if (r == 0) + break; + + if (first) { + first = false; + continue; + } + + if (sscanf(line, "%*i %i %*o %*u " PID_FMT " " PID_FMT " %u " UID_FMT " " GID_FMT " " UID_FMT " " GID_FMT, + &shmid, &cpid, &lpid, &n_attached, &uid, &gid, &cuid, &cgid) != 8) + continue; + + if (n_attached > 0) + continue; + + if (!match_uid_gid(uid, gid, delete_uid, delete_gid)) + continue; + + if (!rm) + return 1; + + if (shmctl(shmid, IPC_RMID, NULL) < 0) { + + /* Ignore entries that are already deleted */ + if (IN_SET(errno, EIDRM, EINVAL)) + continue; + + ret = log_warning_errno(errno, + "Failed to remove SysV shared memory segment %i: %m", + shmid); + } else { + log_debug("Removed SysV shared memory segment %i.", shmid); + if (ret == 0) + ret = 1; + } + } + + return ret; +} + +static int clean_sysvipc_sem(uid_t delete_uid, gid_t delete_gid, bool rm) { + _cleanup_fclose_ FILE *f = NULL; + bool first = true; + int ret = 0, r; + + f = fopen("/proc/sysvipc/sem", "re"); + if (!f) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to open /proc/sysvipc/sem: %m"); + } + + for (;;) { + _cleanup_free_ char *line = NULL; + uid_t uid, cuid; + gid_t gid, cgid; + int semid; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_warning_errno(r, "Failed to read /proc/sysvipc/sem: %m"); + if (r == 0) + break; + + if (first) { + first = false; + continue; + } + + if (sscanf(line, "%*i %i %*o %*u " UID_FMT " " GID_FMT " " UID_FMT " " GID_FMT, + &semid, &uid, &gid, &cuid, &cgid) != 5) + continue; + + if (!match_uid_gid(uid, gid, delete_uid, delete_gid)) + continue; + + if (!rm) + return 1; + + if (semctl(semid, 0, IPC_RMID) < 0) { + + /* Ignore entries that are already deleted */ + if (IN_SET(errno, EIDRM, EINVAL)) + continue; + + ret = log_warning_errno(errno, + "Failed to remove SysV semaphores object %i: %m", + semid); + } else { + log_debug("Removed SysV semaphore %i.", semid); + if (ret == 0) + ret = 1; + } + } + + return ret; +} + +static int clean_sysvipc_msg(uid_t delete_uid, gid_t delete_gid, bool rm) { + _cleanup_fclose_ FILE *f = NULL; + bool first = true; + int ret = 0, r; + + f = fopen("/proc/sysvipc/msg", "re"); + if (!f) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to open /proc/sysvipc/msg: %m"); + } + + for (;;) { + _cleanup_free_ char *line = NULL; + uid_t uid, cuid; + gid_t gid, cgid; + pid_t cpid, lpid; + int msgid; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_warning_errno(r, "Failed to read /proc/sysvipc/msg: %m"); + if (r == 0) + break; + + if (first) { + first = false; + continue; + } + + if (sscanf(line, "%*i %i %*o %*u %*u " PID_FMT " " PID_FMT " " UID_FMT " " GID_FMT " " UID_FMT " " GID_FMT, + &msgid, &cpid, &lpid, &uid, &gid, &cuid, &cgid) != 7) + continue; + + if (!match_uid_gid(uid, gid, delete_uid, delete_gid)) + continue; + + if (!rm) + return 1; + + if (msgctl(msgid, IPC_RMID, NULL) < 0) { + + /* Ignore entries that are already deleted */ + if (IN_SET(errno, EIDRM, EINVAL)) + continue; + + ret = log_warning_errno(errno, + "Failed to remove SysV message queue %i: %m", + msgid); + } else { + log_debug("Removed SysV message queue %i.", msgid); + if (ret == 0) + ret = 1; + } + } + + return ret; +} + +static int clean_posix_shm_internal(DIR *dir, uid_t uid, gid_t gid, bool rm) { + struct dirent *de; + int ret = 0, r; + + assert(dir); + + FOREACH_DIRENT_ALL(de, dir, goto fail) { + struct stat st; + + if (dot_or_dot_dot(de->d_name)) + continue; + + if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { + if (errno == ENOENT) + continue; + + ret = log_warning_errno(errno, "Failed to stat() POSIX shared memory segment %s: %m", de->d_name); + continue; + } + + if (S_ISDIR(st.st_mode)) { + _cleanup_closedir_ DIR *kid; + + kid = xopendirat(dirfd(dir), de->d_name, O_NOFOLLOW|O_NOATIME); + if (!kid) { + if (errno != ENOENT) + ret = log_warning_errno(errno, "Failed to enter shared memory directory %s: %m", de->d_name); + } else { + r = clean_posix_shm_internal(kid, uid, gid, rm); + if (r < 0) + ret = r; + } + + if (!match_uid_gid(st.st_uid, st.st_gid, uid, gid)) + continue; + + if (!rm) + return 1; + + if (unlinkat(dirfd(dir), de->d_name, AT_REMOVEDIR) < 0) { + + if (errno == ENOENT) + continue; + + ret = log_warning_errno(errno, "Failed to remove POSIX shared memory directory %s: %m", de->d_name); + } else { + log_debug("Removed POSIX shared memory directory %s", de->d_name); + if (ret == 0) + ret = 1; + } + } else { + + if (!match_uid_gid(st.st_uid, st.st_gid, uid, gid)) + continue; + + if (!rm) + return 1; + + if (unlinkat(dirfd(dir), de->d_name, 0) < 0) { + + if (errno == ENOENT) + continue; + + ret = log_warning_errno(errno, "Failed to remove POSIX shared memory segment %s: %m", de->d_name); + } else { + log_debug("Removed POSIX shared memory segment %s", de->d_name); + if (ret == 0) + ret = 1; + } + } + } + + return ret; + +fail: + return log_warning_errno(errno, "Failed to read /dev/shm: %m"); +} + +static int clean_posix_shm(uid_t uid, gid_t gid, bool rm) { + _cleanup_closedir_ DIR *dir = NULL; + + dir = opendir("/dev/shm"); + if (!dir) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to open /dev/shm: %m"); + } + + return clean_posix_shm_internal(dir, uid, gid, rm); +} + +static int clean_posix_mq(uid_t uid, gid_t gid, bool rm) { + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *de; + int ret = 0; + + dir = opendir("/dev/mqueue"); + if (!dir) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to open /dev/mqueue: %m"); + } + + FOREACH_DIRENT_ALL(de, dir, goto fail) { + struct stat st; + char fn[1+strlen(de->d_name)+1]; + + if (dot_or_dot_dot(de->d_name)) + continue; + + if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { + if (errno == ENOENT) + continue; + + ret = log_warning_errno(errno, + "Failed to stat() MQ segment %s: %m", + de->d_name); + continue; + } + + if (!match_uid_gid(st.st_uid, st.st_gid, uid, gid)) + continue; + + if (!rm) + return 1; + + fn[0] = '/'; + strcpy(fn+1, de->d_name); + + if (mq_unlink(fn) < 0) { + if (errno == ENOENT) + continue; + + ret = log_warning_errno(errno, + "Failed to unlink POSIX message queue %s: %m", + fn); + } else { + log_debug("Removed POSIX message queue %s", fn); + if (ret == 0) + ret = 1; + } + } + + return ret; + +fail: + return log_warning_errno(errno, "Failed to read /dev/mqueue: %m"); +} + +int clean_ipc_internal(uid_t uid, gid_t gid, bool rm) { + int ret = 0, r; + + /* If 'rm' is true, clean all IPC objects owned by either the specified UID or the specified GID. Return the + * last error encountered or == 0 if no matching IPC objects have been found or > 0 if matching IPC objects + * have been found and have been removed. + * + * If 'rm' is false, just search for IPC objects owned by either the specified UID or the specified GID. In + * this case we return < 0 on error, > 0 if we found a matching object, == 0 if we didn't. + * + * As special rule: if UID/GID is specified as root we'll silently not clean up things, and always claim that + * there are IPC objects for it. */ + + if (uid == 0) { + if (!rm) + return 1; + + uid = UID_INVALID; + } + if (gid == 0) { + if (!rm) + return 1; + + gid = GID_INVALID; + } + + /* Anything to do? */ + if (!uid_is_valid(uid) && !gid_is_valid(gid)) + return 0; + + r = clean_sysvipc_shm(uid, gid, rm); + if (r != 0) { + if (!rm) + return r; + if (ret == 0) + ret = r; + } + + r = clean_sysvipc_sem(uid, gid, rm); + if (r != 0) { + if (!rm) + return r; + if (ret == 0) + ret = r; + } + + r = clean_sysvipc_msg(uid, gid, rm); + if (r != 0) { + if (!rm) + return r; + if (ret == 0) + ret = r; + } + + r = clean_posix_shm(uid, gid, rm); + if (r != 0) { + if (!rm) + return r; + if (ret == 0) + ret = r; + } + + r = clean_posix_mq(uid, gid, rm); + if (r != 0) { + if (!rm) + return r; + if (ret == 0) + ret = r; + } + + return ret; +} + +int clean_ipc_by_uid(uid_t uid) { + return clean_ipc_internal(uid, GID_INVALID, true); +} + +int clean_ipc_by_gid(gid_t gid) { + return clean_ipc_internal(UID_INVALID, gid, true); +} diff --git a/src/shared/clean-ipc.h b/src/shared/clean-ipc.h new file mode 100644 index 00000000..eaff47d4 --- /dev/null +++ b/src/shared/clean-ipc.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "user-util.h" + +int clean_ipc_internal(uid_t uid, gid_t gid, bool rm); + +/* Remove all IPC objects owned by the specified UID or GID */ +int clean_ipc_by_uid(uid_t uid); +int clean_ipc_by_gid(gid_t gid); + +/* Check if any IPC object owned by the specified UID or GID exists, returns > 0 if so, == 0 if not */ +static inline int search_ipc(uid_t uid, gid_t gid) { + return clean_ipc_internal(uid, gid, false); +} diff --git a/src/shared/clock-util.c b/src/shared/clock-util.c new file mode 100644 index 00000000..32cce1e1 --- /dev/null +++ b/src/shared/clock-util.c @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "clock-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "macro.h" +#include "string-util.h" + +int clock_get_hwclock(struct tm *tm) { + _cleanup_close_ int fd = -1; + + assert(tm); + + fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC); + if (fd < 0) + return -errno; + + /* This leaves the timezone fields of struct tm + * uninitialized! */ + if (ioctl(fd, RTC_RD_TIME, tm) < 0) + return -errno; + + /* We don't know daylight saving, so we reset this in order not + * to confuse mktime(). */ + tm->tm_isdst = -1; + + return 0; +} + +int clock_set_hwclock(const struct tm *tm) { + _cleanup_close_ int fd = -1; + + assert(tm); + + fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC); + if (fd < 0) + return -errno; + + if (ioctl(fd, RTC_SET_TIME, tm) < 0) + return -errno; + + return 0; +} + +int clock_is_localtime(const char* adjtime_path) { + _cleanup_fclose_ FILE *f; + int r; + + if (!adjtime_path) + adjtime_path = "/etc/adjtime"; + + /* + * The third line of adjtime is "UTC" or "LOCAL" or nothing. + * # /etc/adjtime + * 0.0 0 0 + * 0 + * UTC + */ + f = fopen(adjtime_path, "re"); + if (f) { + _cleanup_free_ char *line = NULL; + unsigned i; + + for (i = 0; i < 2; i++) { /* skip the first two lines */ + r = read_line(f, LONG_LINE_MAX, NULL); + if (r < 0) + return r; + if (r == 0) + return false; /* less than three lines → default to UTC */ + } + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + return false; /* less than three lines → default to UTC */ + + return streq(line, "LOCAL"); + + } else if (errno != ENOENT) + return -errno; + + /* adjtime not present → default to UTC */ + return false; +} + +int clock_set_timezone(int *min) { + const struct timeval *tv_null = NULL; + struct timespec ts; + struct tm tm; + int minutesdelta; + struct timezone tz; + + assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); + assert_se(localtime_r(&ts.tv_sec, &tm)); + minutesdelta = tm.tm_gmtoff / 60; + + tz.tz_minuteswest = -minutesdelta; + tz.tz_dsttime = 0; /* DST_NONE */ + + /* + * If the RTC does not run in UTC but in local time, the very first + * call to settimeofday() will set the kernel's timezone and will warp the + * system clock, so that it runs in UTC instead of the local time we + * have read from the RTC. + */ + if (settimeofday(tv_null, &tz) < 0) + return negative_errno(); + + if (min) + *min = minutesdelta; + return 0; +} + +int clock_reset_timewarp(void) { + const struct timeval *tv_null = NULL; + struct timezone tz; + + tz.tz_minuteswest = 0; + tz.tz_dsttime = 0; /* DST_NONE */ + + /* + * The very first call to settimeofday() does time warp magic. Do a + * dummy call here, so the time warping is sealed and all later calls + * behave as expected. + */ + if (settimeofday(tv_null, &tz) < 0) + return -errno; + + return 0; +} + +#define TIME_EPOCH_USEC ((usec_t) TIME_EPOCH * USEC_PER_SEC) + +int clock_apply_epoch(void) { + struct timespec ts; + + if (now(CLOCK_REALTIME) >= TIME_EPOCH_USEC) + return 0; + + if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, TIME_EPOCH_USEC)) < 0) + return -errno; + + return 1; +} diff --git a/src/shared/clock-util.h b/src/shared/clock-util.h new file mode 100644 index 00000000..b9db54ea --- /dev/null +++ b/src/shared/clock-util.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int clock_is_localtime(const char* adjtime_path); +int clock_set_timezone(int *min); +int clock_reset_timewarp(void); +int clock_get_hwclock(struct tm *tm); +int clock_set_hwclock(const struct tm *tm); +int clock_apply_epoch(void); diff --git a/src/shared/condition.c b/src/shared/condition.c new file mode 100644 index 00000000..9f4c7fe3 --- /dev/null +++ b/src/shared/condition.c @@ -0,0 +1,905 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "apparmor-util.h" +#include "architecture.h" +#include "audit-util.h" +#include "cap-list.h" +#include "cgroup-util.h" +#include "condition.h" +#include "cpu-set-util.h" +#include "efi-loader.h" +#include "env-file.h" +#include "extract-word.h" +#include "fd-util.h" +#include "fileio.h" +#include "glob-util.h" +#include "hostname-util.h" +#include "ima-util.h" +#include "limits-util.h" +#include "list.h" +#include "macro.h" +#include "mountpoint-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "selinux-util.h" +#include "smack-util.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "tomoyo-util.h" +#include "user-util.h" +#include "util.h" +#include "virt.h" + +Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) { + Condition *c; + + assert(type >= 0); + assert(type < _CONDITION_TYPE_MAX); + assert((!parameter) == (type == CONDITION_NULL)); + + c = new(Condition, 1); + if (!c) + return NULL; + + *c = (Condition) { + .type = type, + .trigger = trigger, + .negate = negate, + }; + + if (parameter) { + c->parameter = strdup(parameter); + if (!c->parameter) + return mfree(c); + } + + return c; +} + +void condition_free(Condition *c) { + assert(c); + + free(c->parameter); + free(c); +} + +Condition* condition_free_list_type(Condition *head, ConditionType type) { + Condition *c, *n; + + LIST_FOREACH_SAFE(conditions, c, n, head) + if (type < 0 || c->type == type) { + LIST_REMOVE(conditions, head, c); + condition_free(c); + } + + assert(type >= 0 || !head); + return head; +} + +static int condition_test_kernel_command_line(Condition *c) { + _cleanup_free_ char *line = NULL; + const char *p; + bool equal; + int r; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_KERNEL_COMMAND_LINE); + + r = proc_cmdline(&line); + if (r < 0) + return r; + + equal = strchr(c->parameter, '='); + + for (p = line;;) { + _cleanup_free_ char *word = NULL; + bool found; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX); + if (r < 0) + return r; + if (r == 0) + break; + + if (equal) + found = streq(word, c->parameter); + else { + const char *f; + + f = startswith(word, c->parameter); + found = f && IN_SET(*f, 0, '='); + } + + if (found) + return true; + } + + return false; +} + +typedef enum { + /* Listed in order of checking. Note that some comparators are prefixes of others, hence the longest + * should be listed first. */ + ORDER_LOWER_OR_EQUAL, + ORDER_GREATER_OR_EQUAL, + ORDER_LOWER, + ORDER_GREATER, + ORDER_EQUAL, + ORDER_UNEQUAL, + _ORDER_MAX, + _ORDER_INVALID = -1 +} OrderOperator; + +static OrderOperator parse_order(const char **s) { + + static const char *const prefix[_ORDER_MAX] = { + [ORDER_LOWER_OR_EQUAL] = "<=", + [ORDER_GREATER_OR_EQUAL] = ">=", + [ORDER_LOWER] = "<", + [ORDER_GREATER] = ">", + [ORDER_EQUAL] = "=", + [ORDER_UNEQUAL] = "!=", + }; + + OrderOperator i; + + for (i = 0; i < _ORDER_MAX; i++) { + const char *e; + + e = startswith(*s, prefix[i]); + if (e) { + *s = e; + return i; + } + } + + return _ORDER_INVALID; +} + +static bool test_order(int k, OrderOperator p) { + + switch (p) { + + case ORDER_LOWER: + return k < 0; + + case ORDER_LOWER_OR_EQUAL: + return k <= 0; + + case ORDER_EQUAL: + return k == 0; + + case ORDER_UNEQUAL: + return k != 0; + + case ORDER_GREATER_OR_EQUAL: + return k >= 0; + + case ORDER_GREATER: + return k > 0; + + default: + assert_not_reached("unknown order"); + + } +} + +static int condition_test_kernel_version(Condition *c) { + OrderOperator order; + struct utsname u; + const char *p; + bool first = true; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_KERNEL_VERSION); + + assert_se(uname(&u) >= 0); + + p = c->parameter; + + for (;;) { + _cleanup_free_ char *word = NULL; + const char *s; + int r; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r < 0) + return log_debug_errno(r, "Failed to parse condition string \"%s\": %m", p); + if (r == 0) + break; + + s = strstrip(word); + order = parse_order(&s); + if (order >= 0) { + s += strspn(s, WHITESPACE); + if (isempty(s)) { + if (first) { + /* For backwards compatibility, allow whitespace between the operator and + * value, without quoting, but only in the first expression. */ + word = mfree(word); + r = extract_first_word(&p, &word, NULL, 0); + if (r < 0) + return log_debug_errno(r, "Failed to parse condition string \"%s\": %m", p); + if (r == 0) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unexpected end of expression: %s", p); + s = word; + } else + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Unexpected end of expression: %s", p); + } + + r = test_order(str_verscmp(u.release, s), order); + } else + /* No prefix? Then treat as glob string */ + r = fnmatch(s, u.release, 0) == 0; + + if (r == 0) + return false; + + first = false; + } + + return true; +} + +static int condition_test_memory(Condition *c) { + OrderOperator order; + uint64_t m, k; + const char *p; + int r; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_MEMORY); + + m = physical_memory(); + + p = c->parameter; + order = parse_order(&p); + if (order < 0) + order = ORDER_GREATER_OR_EQUAL; /* default to >= check, if nothing is specified. */ + + r = safe_atou64(p, &k); + if (r < 0) + return log_debug_errno(r, "Failed to parse size: %m"); + + return test_order(CMP(m, k), order); +} + +static int condition_test_cpus(Condition *c) { + OrderOperator order; + const char *p; + unsigned k; + int r, n; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_CPUS); + + n = cpus_in_affinity_mask(); + if (n < 0) + return log_debug_errno(n, "Failed to determine CPUs in affinity mask: %m"); + + p = c->parameter; + order = parse_order(&p); + if (order < 0) + order = ORDER_GREATER_OR_EQUAL; /* default to >= check, if nothing is specified. */ + + r = safe_atou(p, &k); + if (r < 0) + return log_debug_errno(r, "Failed to parse number of CPUs: %m"); + + return test_order(CMP((unsigned) n, k), order); +} + +static int condition_test_user(Condition *c) { + uid_t id; + int r; + _cleanup_free_ char *username = NULL; + const char *u; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_USER); + + r = parse_uid(c->parameter, &id); + if (r >= 0) + return id == getuid() || id == geteuid(); + + if (streq("@system", c->parameter)) + return uid_is_system(getuid()) || uid_is_system(geteuid()); + + username = getusername_malloc(); + if (!username) + return -ENOMEM; + + if (streq(username, c->parameter)) + return 1; + + if (getpid_cached() == 1) + return streq(c->parameter, "root"); + + u = c->parameter; + r = get_user_creds(&u, &id, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); + if (r < 0) + return 0; + + return id == getuid() || id == geteuid(); +} + +static int condition_test_control_group_controller(Condition *c) { + int r; + CGroupMask system_mask, wanted_mask = 0; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_CONTROL_GROUP_CONTROLLER); + + r = cg_mask_supported(&system_mask); + if (r < 0) + return log_debug_errno(r, "Failed to determine supported controllers: %m"); + + r = cg_mask_from_string(c->parameter, &wanted_mask); + if (r < 0 || wanted_mask <= 0) { + /* This won't catch the case that we have an unknown controller + * mixed in with valid ones -- these are only assessed on the + * validity of the valid controllers found. */ + log_debug("Failed to parse cgroup string: %s", c->parameter); + return 1; + } + + return FLAGS_SET(system_mask, wanted_mask); +} + +static int condition_test_group(Condition *c) { + gid_t id; + int r; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_GROUP); + + r = parse_gid(c->parameter, &id); + if (r >= 0) + return in_gid(id); + + /* Avoid any NSS lookups if we are PID1 */ + if (getpid_cached() == 1) + return streq(c->parameter, "root"); + + return in_group(c->parameter) > 0; +} + +static int condition_test_virtualization(Condition *c) { + int b, v; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_VIRTUALIZATION); + + if (streq(c->parameter, "private-users")) + return running_in_userns(); + + v = detect_virtualization(); + if (v < 0) + return v; + + /* First, compare with yes/no */ + b = parse_boolean(c->parameter); + if (b >= 0) + return b == !!v; + + /* Then, compare categorization */ + if (streq(c->parameter, "vm")) + return VIRTUALIZATION_IS_VM(v); + + if (streq(c->parameter, "container")) + return VIRTUALIZATION_IS_CONTAINER(v); + + /* Finally compare id */ + return v != VIRTUALIZATION_NONE && streq(c->parameter, virtualization_to_string(v)); +} + +static int condition_test_architecture(Condition *c) { + int a, b; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_ARCHITECTURE); + + a = uname_architecture(); + if (a < 0) + return a; + + if (streq(c->parameter, "native")) + b = native_architecture(); + else { + b = architecture_from_string(c->parameter); + if (b < 0) /* unknown architecture? Then it's definitely not ours */ + return false; + } + + return a == b; +} + +static int condition_test_host(Condition *c) { + _cleanup_free_ char *h = NULL; + sd_id128_t x, y; + int r; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_HOST); + + if (sd_id128_from_string(c->parameter, &x) >= 0) { + + r = sd_id128_get_machine(&y); + if (r < 0) + return r; + + return sd_id128_equal(x, y); + } + + h = gethostname_malloc(); + if (!h) + return -ENOMEM; + + return fnmatch(c->parameter, h, FNM_CASEFOLD) == 0; +} + +static int condition_test_ac_power(Condition *c) { + int r; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_AC_POWER); + + r = parse_boolean(c->parameter); + if (r < 0) + return r; + + return (on_ac_power() != 0) == !!r; +} + +static int condition_test_security(Condition *c) { + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_SECURITY); + + if (streq(c->parameter, "selinux")) + return mac_selinux_use(); + if (streq(c->parameter, "smack")) + return mac_smack_use(); + if (streq(c->parameter, "apparmor")) + return mac_apparmor_use(); + if (streq(c->parameter, "audit")) + return use_audit(); + if (streq(c->parameter, "ima")) + return use_ima(); + if (streq(c->parameter, "tomoyo")) + return mac_tomoyo_use(); + if (streq(c->parameter, "uefi-secureboot")) + return is_efi_secure_boot(); + + return false; +} + +static int condition_test_capability(Condition *c) { + unsigned long long capabilities = (unsigned long long) -1; + _cleanup_fclose_ FILE *f = NULL; + int value, r; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_CAPABILITY); + + /* If it's an invalid capability, we don't have it */ + value = capability_from_name(c->parameter); + if (value < 0) + return -EINVAL; + + /* If it's a valid capability we default to assume + * that we have it */ + + f = fopen("/proc/self/status", "re"); + if (!f) + return -errno; + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *p; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + p = startswith(line, "CapBnd:"); + if (p) { + if (sscanf(line+7, "%llx", &capabilities) != 1) + return -EIO; + + break; + } + } + + return !!(capabilities & (1ULL << value)); +} + +static int condition_test_needs_update(Condition *c) { + const char *p; + struct stat usr, other; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_NEEDS_UPDATE); + + /* If the file system is read-only we shouldn't suggest an update */ + if (path_is_read_only_fs(c->parameter) > 0) + return false; + + /* Any other failure means we should allow the condition to be true, + * so that we rather invoke too many update tools than too + * few. */ + + if (!path_is_absolute(c->parameter)) + return true; + + p = strjoina(c->parameter, "/.updated"); + if (lstat(p, &other) < 0) + return true; + + if (lstat("/usr/", &usr) < 0) + return true; + + /* + * First, compare seconds as they are always accurate... + */ + if (usr.st_mtim.tv_sec != other.st_mtim.tv_sec) + return usr.st_mtim.tv_sec > other.st_mtim.tv_sec; + + /* + * ...then compare nanoseconds. + * + * A false positive is only possible when /usr's nanoseconds > 0 + * (otherwise /usr cannot be strictly newer than the target file) + * AND the target file's nanoseconds == 0 + * (otherwise the filesystem supports nsec timestamps, see stat(2)). + */ + if (usr.st_mtim.tv_nsec > 0 && other.st_mtim.tv_nsec == 0) { + _cleanup_free_ char *timestamp_str = NULL; + uint64_t timestamp; + int r; + + r = parse_env_file(NULL, p, "TIMESTAMP_NSEC", ×tamp_str); + if (r < 0) { + log_error_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p); + return true; + } else if (r == 0) { + log_debug("No data in timestamp file '%s', using mtime", p); + return true; + } + + r = safe_atou64(timestamp_str, ×tamp); + if (r < 0) { + log_error_errno(r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", timestamp_str, p); + return true; + } + + timespec_store(&other.st_mtim, timestamp); + } + + return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec; +} + +static int condition_test_first_boot(Condition *c) { + int r; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_FIRST_BOOT); + + r = parse_boolean(c->parameter); + if (r < 0) + return r; + + return (access("/run/systemd/first-boot", F_OK) >= 0) == !!r; +} + +static int condition_test_path_exists(Condition *c) { + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_PATH_EXISTS); + + return access(c->parameter, F_OK) >= 0; +} + +static int condition_test_path_exists_glob(Condition *c) { + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_PATH_EXISTS_GLOB); + + return glob_exists(c->parameter) > 0; +} + +static int condition_test_path_is_directory(Condition *c) { + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_PATH_IS_DIRECTORY); + + return is_dir(c->parameter, true) > 0; +} + +static int condition_test_path_is_symbolic_link(Condition *c) { + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_PATH_IS_SYMBOLIC_LINK); + + return is_symlink(c->parameter) > 0; +} + +static int condition_test_path_is_mount_point(Condition *c) { + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_PATH_IS_MOUNT_POINT); + + return path_is_mount_point(c->parameter, NULL, AT_SYMLINK_FOLLOW) > 0; +} + +static int condition_test_path_is_read_write(Condition *c) { + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_PATH_IS_READ_WRITE); + + return path_is_read_only_fs(c->parameter) <= 0; +} + +static int condition_test_directory_not_empty(Condition *c) { + int r; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_DIRECTORY_NOT_EMPTY); + + r = dir_is_empty(c->parameter); + return r <= 0 && r != -ENOENT; +} + +static int condition_test_file_not_empty(Condition *c) { + struct stat st; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_FILE_NOT_EMPTY); + + return (stat(c->parameter, &st) >= 0 && + S_ISREG(st.st_mode) && + st.st_size > 0); +} + +static int condition_test_file_is_executable(Condition *c) { + struct stat st; + + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_FILE_IS_EXECUTABLE); + + return (stat(c->parameter, &st) >= 0 && + S_ISREG(st.st_mode) && + (st.st_mode & 0111)); +} + +static int condition_test_null(Condition *c) { + assert(c); + assert(c->type == CONDITION_NULL); + + /* Note that during parsing we already evaluate the string and + * store it in c->negate */ + return true; +} + +int condition_test(Condition *c) { + + static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c) = { + [CONDITION_PATH_EXISTS] = condition_test_path_exists, + [CONDITION_PATH_EXISTS_GLOB] = condition_test_path_exists_glob, + [CONDITION_PATH_IS_DIRECTORY] = condition_test_path_is_directory, + [CONDITION_PATH_IS_SYMBOLIC_LINK] = condition_test_path_is_symbolic_link, + [CONDITION_PATH_IS_MOUNT_POINT] = condition_test_path_is_mount_point, + [CONDITION_PATH_IS_READ_WRITE] = condition_test_path_is_read_write, + [CONDITION_DIRECTORY_NOT_EMPTY] = condition_test_directory_not_empty, + [CONDITION_FILE_NOT_EMPTY] = condition_test_file_not_empty, + [CONDITION_FILE_IS_EXECUTABLE] = condition_test_file_is_executable, + [CONDITION_KERNEL_COMMAND_LINE] = condition_test_kernel_command_line, + [CONDITION_KERNEL_VERSION] = condition_test_kernel_version, + [CONDITION_VIRTUALIZATION] = condition_test_virtualization, + [CONDITION_SECURITY] = condition_test_security, + [CONDITION_CAPABILITY] = condition_test_capability, + [CONDITION_HOST] = condition_test_host, + [CONDITION_AC_POWER] = condition_test_ac_power, + [CONDITION_ARCHITECTURE] = condition_test_architecture, + [CONDITION_NEEDS_UPDATE] = condition_test_needs_update, + [CONDITION_FIRST_BOOT] = condition_test_first_boot, + [CONDITION_USER] = condition_test_user, + [CONDITION_GROUP] = condition_test_group, + [CONDITION_CONTROL_GROUP_CONTROLLER] = condition_test_control_group_controller, + [CONDITION_NULL] = condition_test_null, + [CONDITION_CPUS] = condition_test_cpus, + [CONDITION_MEMORY] = condition_test_memory, + }; + + int r, b; + + assert(c); + assert(c->type >= 0); + assert(c->type < _CONDITION_TYPE_MAX); + + r = condition_tests[c->type](c); + if (r < 0) { + c->result = CONDITION_ERROR; + return r; + } + + b = (r > 0) == !c->negate; + c->result = b ? CONDITION_SUCCEEDED : CONDITION_FAILED; + return b; +} + +bool condition_test_list(Condition *first, const char *(*to_string)(ConditionType t), condition_test_logger_t logger, void *userdata) { + Condition *c; + int triggered = -1; + + assert(!!logger == !!to_string); + + /* If the condition list is empty, then it is true */ + if (!first) + return true; + + /* Otherwise, if all of the non-trigger conditions apply and + * if any of the trigger conditions apply (unless there are + * none) we return true */ + LIST_FOREACH(conditions, c, first) { + int r; + + r = condition_test(c); + + if (logger) { + const char *p = c->type == CONDITION_NULL ? "true" : c->parameter; + assert(p); + + if (r < 0) + logger(userdata, LOG_WARNING, r, PROJECT_FILE, __LINE__, __func__, + "Couldn't determine result for %s=%s%s%s, assuming failed: %m", + to_string(c->type), + c->trigger ? "|" : "", + c->negate ? "!" : "", + p); + else + logger(userdata, LOG_DEBUG, 0, PROJECT_FILE, __LINE__, __func__, + "%s=%s%s%s %s.", + to_string(c->type), + c->trigger ? "|" : "", + c->negate ? "!" : "", + p, + condition_result_to_string(c->result)); + } + + if (!c->trigger && r <= 0) + return false; + + if (c->trigger && triggered <= 0) + triggered = r > 0; + } + + return triggered != 0; +} + +void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) { + assert(c); + assert(f); + + prefix = strempty(prefix); + + fprintf(f, + "%s\t%s: %s%s%s %s\n", + prefix, + to_string(c->type), + c->trigger ? "|" : "", + c->negate ? "!" : "", + c->parameter, + condition_result_to_string(c->result)); +} + +void condition_dump_list(Condition *first, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)) { + Condition *c; + + LIST_FOREACH(conditions, c, first) + condition_dump(c, f, prefix, to_string); +} + +static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { + [CONDITION_ARCHITECTURE] = "ConditionArchitecture", + [CONDITION_VIRTUALIZATION] = "ConditionVirtualization", + [CONDITION_HOST] = "ConditionHost", + [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine", + [CONDITION_KERNEL_VERSION] = "ConditionKernelVersion", + [CONDITION_SECURITY] = "ConditionSecurity", + [CONDITION_CAPABILITY] = "ConditionCapability", + [CONDITION_AC_POWER] = "ConditionACPower", + [CONDITION_NEEDS_UPDATE] = "ConditionNeedsUpdate", + [CONDITION_FIRST_BOOT] = "ConditionFirstBoot", + [CONDITION_PATH_EXISTS] = "ConditionPathExists", + [CONDITION_PATH_EXISTS_GLOB] = "ConditionPathExistsGlob", + [CONDITION_PATH_IS_DIRECTORY] = "ConditionPathIsDirectory", + [CONDITION_PATH_IS_SYMBOLIC_LINK] = "ConditionPathIsSymbolicLink", + [CONDITION_PATH_IS_MOUNT_POINT] = "ConditionPathIsMountPoint", + [CONDITION_PATH_IS_READ_WRITE] = "ConditionPathIsReadWrite", + [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty", + [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty", + [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable", + [CONDITION_USER] = "ConditionUser", + [CONDITION_GROUP] = "ConditionGroup", + [CONDITION_CONTROL_GROUP_CONTROLLER] = "ConditionControlGroupController", + [CONDITION_NULL] = "ConditionNull", + [CONDITION_CPUS] = "ConditionCPUs", + [CONDITION_MEMORY] = "ConditionMemory", +}; + +DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType); + +static const char* const assert_type_table[_CONDITION_TYPE_MAX] = { + [CONDITION_ARCHITECTURE] = "AssertArchitecture", + [CONDITION_VIRTUALIZATION] = "AssertVirtualization", + [CONDITION_HOST] = "AssertHost", + [CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine", + [CONDITION_KERNEL_VERSION] = "AssertKernelVersion", + [CONDITION_SECURITY] = "AssertSecurity", + [CONDITION_CAPABILITY] = "AssertCapability", + [CONDITION_AC_POWER] = "AssertACPower", + [CONDITION_NEEDS_UPDATE] = "AssertNeedsUpdate", + [CONDITION_FIRST_BOOT] = "AssertFirstBoot", + [CONDITION_PATH_EXISTS] = "AssertPathExists", + [CONDITION_PATH_EXISTS_GLOB] = "AssertPathExistsGlob", + [CONDITION_PATH_IS_DIRECTORY] = "AssertPathIsDirectory", + [CONDITION_PATH_IS_SYMBOLIC_LINK] = "AssertPathIsSymbolicLink", + [CONDITION_PATH_IS_MOUNT_POINT] = "AssertPathIsMountPoint", + [CONDITION_PATH_IS_READ_WRITE] = "AssertPathIsReadWrite", + [CONDITION_DIRECTORY_NOT_EMPTY] = "AssertDirectoryNotEmpty", + [CONDITION_FILE_NOT_EMPTY] = "AssertFileNotEmpty", + [CONDITION_FILE_IS_EXECUTABLE] = "AssertFileIsExecutable", + [CONDITION_USER] = "AssertUser", + [CONDITION_GROUP] = "AssertGroup", + [CONDITION_CONTROL_GROUP_CONTROLLER] = "AssertControlGroupController", + [CONDITION_NULL] = "AssertNull", + [CONDITION_CPUS] = "AssertCPUs", + [CONDITION_MEMORY] = "AssertMemory", +}; + +DEFINE_STRING_TABLE_LOOKUP(assert_type, ConditionType); + +static const char* const condition_result_table[_CONDITION_RESULT_MAX] = { + [CONDITION_UNTESTED] = "untested", + [CONDITION_SUCCEEDED] = "succeeded", + [CONDITION_FAILED] = "failed", + [CONDITION_ERROR] = "error", +}; + +DEFINE_STRING_TABLE_LOOKUP(condition_result, ConditionResult); diff --git a/src/shared/condition.h b/src/shared/condition.h new file mode 100644 index 00000000..84322e74 --- /dev/null +++ b/src/shared/condition.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "list.h" +#include "macro.h" + +typedef enum ConditionType { + CONDITION_ARCHITECTURE, + CONDITION_VIRTUALIZATION, + CONDITION_HOST, + CONDITION_KERNEL_COMMAND_LINE, + CONDITION_KERNEL_VERSION, + CONDITION_SECURITY, + CONDITION_CAPABILITY, + CONDITION_AC_POWER, + CONDITION_MEMORY, + CONDITION_CPUS, + + CONDITION_NEEDS_UPDATE, + CONDITION_FIRST_BOOT, + + CONDITION_PATH_EXISTS, + CONDITION_PATH_EXISTS_GLOB, + CONDITION_PATH_IS_DIRECTORY, + CONDITION_PATH_IS_SYMBOLIC_LINK, + CONDITION_PATH_IS_MOUNT_POINT, + CONDITION_PATH_IS_READ_WRITE, + CONDITION_DIRECTORY_NOT_EMPTY, + CONDITION_FILE_NOT_EMPTY, + CONDITION_FILE_IS_EXECUTABLE, + + CONDITION_NULL, + + CONDITION_USER, + CONDITION_GROUP, + + CONDITION_CONTROL_GROUP_CONTROLLER, + + _CONDITION_TYPE_MAX, + _CONDITION_TYPE_INVALID = -1 +} ConditionType; + +typedef enum ConditionResult { + CONDITION_UNTESTED, + CONDITION_SUCCEEDED, + CONDITION_FAILED, + CONDITION_ERROR, + _CONDITION_RESULT_MAX, + _CONDITION_RESULT_INVALID = -1 +} ConditionResult; + +typedef struct Condition { + ConditionType type:8; + + bool trigger:1; + bool negate:1; + + ConditionResult result:6; + + char *parameter; + + LIST_FIELDS(struct Condition, conditions); +} Condition; + +Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate); +void condition_free(Condition *c); +Condition* condition_free_list_type(Condition *first, ConditionType type); +static inline Condition* condition_free_list(Condition *first) { + return condition_free_list_type(first, _CONDITION_TYPE_INVALID); +} + +int condition_test(Condition *c); +typedef int (*condition_test_logger_t)(void *userdata, int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(7, 8); +bool condition_test_list(Condition *first, const char *(*to_string)(ConditionType t), condition_test_logger_t logger, void *userdata); + +void condition_dump(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)); +void condition_dump_list(Condition *c, FILE *f, const char *prefix, const char *(*to_string)(ConditionType t)); + +const char* condition_type_to_string(ConditionType t) _const_; +ConditionType condition_type_from_string(const char *s) _pure_; + +const char* assert_type_to_string(ConditionType t) _const_; +ConditionType assert_type_from_string(const char *s) _pure_; + +const char* condition_result_to_string(ConditionResult r) _const_; +ConditionResult condition_result_from_string(const char *s) _pure_; + +static inline bool condition_takes_path(ConditionType t) { + return IN_SET(t, + CONDITION_PATH_EXISTS, + CONDITION_PATH_EXISTS_GLOB, + CONDITION_PATH_IS_DIRECTORY, + CONDITION_PATH_IS_SYMBOLIC_LINK, + CONDITION_PATH_IS_MOUNT_POINT, + CONDITION_PATH_IS_READ_WRITE, + CONDITION_DIRECTORY_NOT_EMPTY, + CONDITION_FILE_NOT_EMPTY, + CONDITION_FILE_IS_EXECUTABLE, + CONDITION_NEEDS_UPDATE); +} diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c new file mode 100644 index 00000000..3269d830 --- /dev/null +++ b/src/shared/conf-parser.c @@ -0,0 +1,1117 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "conf-files.h" +#include "conf-parser.h" +#include "def.h" +#include "extract-word.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "log.h" +#include "macro.h" +#include "missing_network.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" +#include "syslog-util.h" +#include "time-util.h" +#include "utf8.h" + +int config_item_table_lookup( + const void *table, + const char *section, + const char *lvalue, + ConfigParserCallback *func, + int *ltype, + void **data, + void *userdata) { + + const ConfigTableItem *t; + + assert(table); + assert(lvalue); + assert(func); + assert(ltype); + assert(data); + + for (t = table; t->lvalue; t++) { + + if (!streq(lvalue, t->lvalue)) + continue; + + if (!streq_ptr(section, t->section)) + continue; + + *func = t->parse; + *ltype = t->ltype; + *data = t->data; + return 1; + } + + return 0; +} + +int config_item_perf_lookup( + const void *table, + const char *section, + const char *lvalue, + ConfigParserCallback *func, + int *ltype, + void **data, + void *userdata) { + + ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table; + const ConfigPerfItem *p; + + assert(table); + assert(lvalue); + assert(func); + assert(ltype); + assert(data); + + if (section) { + const char *key; + + key = strjoina(section, ".", lvalue); + p = lookup(key, strlen(key)); + } else + p = lookup(lvalue, strlen(lvalue)); + if (!p) + return 0; + + *func = p->parse; + *ltype = p->ltype; + *data = (uint8_t*) userdata + p->offset; + return 1; +} + +/* Run the user supplied parser for an assignment */ +static int next_assignment( + const char *unit, + const char *filename, + unsigned line, + ConfigItemLookup lookup, + const void *table, + const char *section, + unsigned section_line, + const char *lvalue, + const char *rvalue, + ConfigParseFlags flags, + void *userdata) { + + ConfigParserCallback func = NULL; + int ltype = 0; + void *data = NULL; + int r; + + assert(filename); + assert(line > 0); + assert(lookup); + assert(lvalue); + assert(rvalue); + + r = lookup(table, section, lvalue, &func, <ype, &data, userdata); + if (r < 0) + return r; + if (r > 0) { + if (func) + return func(unit, filename, line, section, section_line, + lvalue, ltype, rvalue, data, userdata); + + return 0; + } + + /* Warn about unknown non-extension fields. */ + if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(lvalue, "X-")) + log_syntax(unit, LOG_WARNING, filename, line, 0, + "Unknown key name '%s' in section '%s', ignoring.", lvalue, section); + + return 0; +} + +/* Parse a single logical line */ +static int parse_line( + const char* unit, + const char *filename, + unsigned line, + const char *sections, + ConfigItemLookup lookup, + const void *table, + ConfigParseFlags flags, + char **section, + unsigned *section_line, + bool *section_ignored, + char *l, + void *userdata) { + + char *e, *include; + + assert(filename); + assert(line > 0); + assert(lookup); + assert(l); + + l = strstrip(l); + if (!*l) + return 0; + + if (*l == '\n') + return 0; + + include = first_word(l, ".include"); + if (include) { + _cleanup_free_ char *fn = NULL; + + /* .includes are a bad idea, we only support them here + * for historical reasons. They create cyclic include + * problems and make it difficult to detect + * configuration file changes with an easy + * stat(). Better approaches, such as .d/ drop-in + * snippets exist. + * + * Support for them should be eventually removed. */ + + if (!(flags & CONFIG_PARSE_ALLOW_INCLUDE)) { + log_syntax(unit, LOG_ERR, filename, line, 0, ".include not allowed here. Ignoring."); + return 0; + } + + log_syntax(unit, LOG_WARNING, filename, line, 0, + ".include directives are deprecated, and support for them will be removed in a future version of systemd. " + "Please use drop-in files instead."); + + fn = file_in_same_dir(filename, strstrip(include)); + if (!fn) + return -ENOMEM; + + return config_parse(unit, fn, NULL, sections, lookup, table, flags, userdata); + } + + if (!utf8_is_valid(l)) + return log_syntax_invalid_utf8(unit, LOG_WARNING, filename, line, l); + + if (*l == '[') { + size_t k; + char *n; + + k = strlen(l); + assert(k > 0); + + if (l[k-1] != ']') { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid section header '%s'", l); + return -EBADMSG; + } + + n = strndup(l+1, k-2); + if (!n) + return -ENOMEM; + + if (sections && !nulstr_contains(sections, n)) { + + if (!(flags & CONFIG_PARSE_RELAXED) && !startswith(n, "X-")) + log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown section '%s'. Ignoring.", n); + + free(n); + *section = mfree(*section); + *section_line = 0; + *section_ignored = true; + } else { + free_and_replace(*section, n); + *section_line = line; + *section_ignored = false; + } + + return 0; + } + + if (sections && !*section) { + if (!(flags & CONFIG_PARSE_RELAXED) && !*section_ignored) + log_syntax(unit, LOG_WARNING, filename, line, 0, "Assignment outside of section. Ignoring."); + + return 0; + } + + e = strchr(l, '='); + if (!e) + return log_syntax(unit, LOG_WARNING, filename, line, 0, + "Missing '=', ignoring line."); + if (e == l) + return log_syntax(unit, LOG_WARNING, filename, line, 0, + "Missing key name before '=', ignoring line."); + + *e = 0; + e++; + + return next_assignment(unit, + filename, + line, + lookup, + table, + *section, + *section_line, + strstrip(l), + strstrip(e), + flags, + userdata); +} + +/* Go through the file and parse each line */ +int config_parse(const char *unit, + const char *filename, + FILE *f, + const char *sections, + ConfigItemLookup lookup, + const void *table, + ConfigParseFlags flags, + void *userdata) { + + _cleanup_free_ char *section = NULL, *continuation = NULL; + _cleanup_fclose_ FILE *ours = NULL; + unsigned line = 0, section_line = 0; + bool section_ignored = false; + int r; + + assert(filename); + assert(lookup); + + if (!f) { + f = ours = fopen(filename, "re"); + if (!f) { + /* Only log on request, except for ENOENT, + * since we return 0 to the caller. */ + if ((flags & CONFIG_PARSE_WARN) || errno == ENOENT) + log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, + "Failed to open configuration file '%s': %m", filename); + return errno == ENOENT ? 0 : -errno; + } + } + + fd_warn_permissions(filename, fileno(f)); + + for (;;) { + _cleanup_free_ char *buf = NULL; + bool escaped = false; + char *l, *p, *e; + + r = read_line(f, LONG_LINE_MAX, &buf); + if (r == 0) + break; + if (r == -ENOBUFS) { + if (flags & CONFIG_PARSE_WARN) + log_error_errno(r, "%s:%u: Line too long", filename, line); + + return r; + } + if (r < 0) { + if (CONFIG_PARSE_WARN) + log_error_errno(r, "%s:%u: Error while reading configuration file: %m", filename, line); + + return r; + } + + l = skip_leading_chars(buf, WHITESPACE); + if (*l != '\0' && strchr(COMMENTS, *l)) + continue; + + l = buf; + if (!(flags & CONFIG_PARSE_REFUSE_BOM)) { + char *q; + + q = startswith(buf, UTF8_BYTE_ORDER_MARK); + if (q) { + l = q; + flags |= CONFIG_PARSE_REFUSE_BOM; + } + } + + if (continuation) { + if (strlen(continuation) + strlen(l) > LONG_LINE_MAX) { + if (flags & CONFIG_PARSE_WARN) + log_error("%s:%u: Continuation line too long", filename, line); + return -ENOBUFS; + } + + if (!strextend(&continuation, l, NULL)) { + if (flags & CONFIG_PARSE_WARN) + log_oom(); + return -ENOMEM; + } + + p = continuation; + } else + p = l; + + for (e = p; *e; e++) { + if (escaped) + escaped = false; + else if (*e == '\\') + escaped = true; + } + + if (escaped) { + *(e-1) = ' '; + + if (!continuation) { + continuation = strdup(l); + if (!continuation) { + if (flags & CONFIG_PARSE_WARN) + log_oom(); + return -ENOMEM; + } + } + + continue; + } + + r = parse_line(unit, + filename, + ++line, + sections, + lookup, + table, + flags, + §ion, + §ion_line, + §ion_ignored, + p, + userdata); + if (r < 0) { + if (flags & CONFIG_PARSE_WARN) + log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line); + return r; + } + + continuation = mfree(continuation); + } + + if (continuation) { + r = parse_line(unit, + filename, + ++line, + sections, + lookup, + table, + flags, + §ion, + §ion_line, + §ion_ignored, + continuation, + userdata); + if (r < 0) { + if (flags & CONFIG_PARSE_WARN) + log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line); + return r; + } + } + + return 0; +} + +static int config_parse_many_files( + const char *conf_file, + char **files, + const char *sections, + ConfigItemLookup lookup, + const void *table, + ConfigParseFlags flags, + void *userdata) { + + char **fn; + int r; + + if (conf_file) { + r = config_parse(NULL, conf_file, NULL, sections, lookup, table, flags, userdata); + if (r < 0) + return r; + } + + STRV_FOREACH(fn, files) { + r = config_parse(NULL, *fn, NULL, sections, lookup, table, flags, userdata); + if (r < 0) + return r; + } + + return 0; +} + +/* Parse each config file in the directories specified as nulstr. */ +int config_parse_many_nulstr( + const char *conf_file, + const char *conf_file_dirs, + const char *sections, + ConfigItemLookup lookup, + const void *table, + ConfigParseFlags flags, + void *userdata) { + + _cleanup_strv_free_ char **files = NULL; + int r; + + r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs); + if (r < 0) + return r; + + return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata); +} + +/* Parse each config file in the directories specified as strv. */ +int config_parse_many( + const char *conf_file, + const char* const* conf_file_dirs, + const char *dropin_dirname, + const char *sections, + ConfigItemLookup lookup, + const void *table, + ConfigParseFlags flags, + void *userdata) { + + _cleanup_strv_free_ char **dropin_dirs = NULL; + _cleanup_strv_free_ char **files = NULL; + const char *suffix; + int r; + + suffix = strjoina("/", dropin_dirname); + r = strv_extend_strv_concat(&dropin_dirs, (char**) conf_file_dirs, suffix); + if (r < 0) + return r; + + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char* const*) dropin_dirs); + if (r < 0) + return r; + + return config_parse_many_files(conf_file, files, sections, lookup, table, flags, userdata); +} + +#define DEFINE_PARSER(type, vartype, conv_func) \ + DEFINE_CONFIG_PARSE_PTR(config_parse_##type, conv_func, vartype, "Failed to parse " #type " value") + +DEFINE_PARSER(int, int, safe_atoi); +DEFINE_PARSER(long, long, safe_atoli); +DEFINE_PARSER(uint8, uint8_t, safe_atou8); +DEFINE_PARSER(uint16, uint16_t, safe_atou16); +DEFINE_PARSER(uint32, uint32_t, safe_atou32); +DEFINE_PARSER(uint64, uint64_t, safe_atou64); +DEFINE_PARSER(unsigned, unsigned, safe_atou); +DEFINE_PARSER(double, double, safe_atod); +DEFINE_PARSER(nsec, nsec_t, parse_nsec); +DEFINE_PARSER(sec, usec_t, parse_sec); +DEFINE_PARSER(sec_def_infinity, usec_t, parse_sec_def_infinity); +DEFINE_PARSER(mode, mode_t, parse_mode); + +int config_parse_iec_size(const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + size_t *sz = data; + uint64_t v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_size(rvalue, 1024, &v); + if (r >= 0 && (uint64_t) (size_t) v != v) + r = -ERANGE; + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue); + return 0; + } + + *sz = (size_t) v; + return 0; +} + +int config_parse_si_size( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + size_t *sz = data; + uint64_t v; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_size(rvalue, 1000, &v); + if (r >= 0 && (uint64_t) (size_t) v != v) + r = -ERANGE; + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value '%s', ignoring: %m", rvalue); + return 0; + } + + *sz = (size_t) v; + return 0; +} + +int config_parse_iec_uint64( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint64_t *bytes = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_size(rvalue, 1024, bytes); + if (r < 0) + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue); + + return 0; +} + +int config_parse_bool(const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int k; + bool *b = data; + bool fatal = ltype; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + k = parse_boolean(rvalue); + if (k < 0) { + log_syntax(unit, LOG_ERR, filename, line, k, + "Failed to parse boolean value%s: %s", + fatal ? "" : ", ignoring", rvalue); + return fatal ? -ENOEXEC : 0; + } + + *b = k; + return 0; +} + +int config_parse_tristate( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int k, *t = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* A tristate is pretty much a boolean, except that it can + * also take the special value -1, indicating "uninitialized", + * much like NULL is for a pointer type. */ + + k = parse_boolean(rvalue); + if (k < 0) { + log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue); + return 0; + } + + *t = !!k; + return 0; +} + +int config_parse_string( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char **s = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (free_and_strdup(s, empty_to_null(rvalue)) < 0) + return log_oom(); + + return 0; +} + +int config_parse_path( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + _cleanup_free_ char *n = NULL; + bool fatal = ltype; + char **s = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) + goto finalize; + + n = strdup(rvalue); + if (!n) + return log_oom(); + + r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE | (fatal ? PATH_CHECK_FATAL : 0), unit, filename, line, lvalue); + if (r < 0) + return fatal ? -ENOEXEC : 0; + +finalize: + return free_and_replace(*s, n); +} + +int config_parse_strv( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char ***sv = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + *sv = strv_free(*sv); + return 0; + } + + for (;;) { + char *word = NULL; + + r = extract_first_word(&rvalue, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); + break; + } + + r = strv_consume(sv, word); + if (r < 0) + return log_oom(); + } + + return 0; +} + +int config_parse_warn_compat( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Disabled reason = ltype; + + switch(reason) { + + case DISABLED_CONFIGURATION: + log_syntax(unit, LOG_DEBUG, filename, line, 0, + "Support for option %s= has been disabled at compile time and it is ignored", lvalue); + break; + + case DISABLED_LEGACY: + log_syntax(unit, LOG_INFO, filename, line, 0, + "Support for option %s= has been removed and it is ignored", lvalue); + break; + + case DISABLED_EXPERIMENTAL: + log_syntax(unit, LOG_INFO, filename, line, 0, + "Support for option %s= has not yet been enabled and it is ignored", lvalue); + break; + } + + return 0; +} + +int config_parse_log_facility( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int *o = data, x; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + x = log_facility_unshifted_from_string(rvalue); + if (x < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log facility, ignoring: %s", rvalue); + return 0; + } + + *o = (x << 3) | LOG_PRI(*o); + + return 0; +} + +int config_parse_log_level( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int *o = data, x; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + x = log_level_from_string(rvalue); + if (x < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse log level, ignoring: %s", rvalue); + return 0; + } + + if (*o < 0) /* if it wasn't initialized so far, assume zero facility */ + *o = x; + else + *o = (*o & LOG_FACMASK) | x; + + return 0; +} + +int config_parse_signal( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int *sig = data, r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(sig); + + r = signal_from_string(rvalue); + if (r <= 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue); + return 0; + } + + *sig = r; + return 0; +} + +int config_parse_personality( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + unsigned long *personality = data, p; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(personality); + + if (isempty(rvalue)) + p = PERSONALITY_INVALID; + else { + p = personality_from_string(rvalue); + if (p == PERSONALITY_INVALID) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue); + return 0; + } + } + + *personality = p; + return 0; +} + +int config_parse_ifname( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + char **s = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + *s = mfree(*s); + return 0; + } + + if (!ifname_valid(rvalue)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue); + return 0; + } + + r = free_and_strdup(s, rvalue); + if (r < 0) + return log_oom(); + + return 0; +} + +int config_parse_ip_port( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint16_t *s = data; + uint16_t port; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + *s = 0; + return 0; + } + + r = parse_ip_port(rvalue, &port); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse port '%s'.", rvalue); + return 0; + } + + *s = port; + + return 0; +} + +int config_parse_mtu( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint32_t *mtu = data; + int r; + + assert(rvalue); + assert(mtu); + + r = parse_mtu(ltype, rvalue, mtu); + if (r == -ERANGE) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Maximum transfer unit (MTU) value out of range. Permitted range is %" PRIu32 "…%" PRIu32 ", ignoring: %s", + (uint32_t) (ltype == AF_INET6 ? IPV6_MIN_MTU : IPV4_MIN_MTU), (uint32_t) UINT32_MAX, + rvalue); + return 0; + } + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse MTU value '%s', ignoring: %m", rvalue); + return 0; + } + + return 0; +} + +int config_parse_rlimit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + struct rlimit **rl = data, d = {}; + int r; + + assert(rvalue); + assert(rl); + + r = rlimit_parse(ltype, rvalue, &d); + if (r == -EILSEQ) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Soft resource limit chosen higher than hard limit, ignoring: %s", rvalue); + return 0; + } + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); + return 0; + } + + if (rl[ltype]) + *rl[ltype] = d; + else { + rl[ltype] = newdup(struct rlimit, &d, 1); + if (!rl[ltype]) + return log_oom(); + } + + return 0; +} + +int config_parse_permille(const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + unsigned *permille = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(permille); + + r = parse_permille(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse permille value, ignoring: %s", rvalue); + return 0; + } + + *permille = (unsigned) r; + + return 0; +} diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h new file mode 100644 index 00000000..04c68b18 --- /dev/null +++ b/src/shared/conf-parser.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "log.h" +#include "macro.h" + +/* An abstract parser for simple, line based, shallow configuration files consisting of variable assignments only. */ + +typedef enum ConfigParseFlags { + CONFIG_PARSE_RELAXED = 1 << 0, + CONFIG_PARSE_ALLOW_INCLUDE = 1 << 1, + CONFIG_PARSE_WARN = 1 << 2, + CONFIG_PARSE_REFUSE_BOM = 1 << 3, +} ConfigParseFlags; + +/* Argument list for parsers of specific configuration settings. */ +#define CONFIG_PARSER_ARGUMENTS \ + const char *unit, \ + const char *filename, \ + unsigned line, \ + const char *section, \ + unsigned section_line, \ + const char *lvalue, \ + int ltype, \ + const char *rvalue, \ + void *data, \ + void *userdata + +/* Prototype for a parser for a specific configuration setting */ +typedef int (*ConfigParserCallback)(CONFIG_PARSER_ARGUMENTS); + +/* A macro declaring the a function prototype, following the typedef above, simply because it's so cumbersomely long + * otherwise. (And current emacs gets irritatingly slow when editing files that contain lots of very long function + * prototypes on the same screen…) */ +#define CONFIG_PARSER_PROTOTYPE(name) int name(CONFIG_PARSER_ARGUMENTS) + +/* Wraps information for parsing a specific configuration variable, to + * be stored in a simple array */ +typedef struct ConfigTableItem { + const char *section; /* Section */ + const char *lvalue; /* Name of the variable */ + ConfigParserCallback parse; /* Function that is called to parse the variable's value */ + int ltype; /* Distinguish different variables passed to the same callback */ + void *data; /* Where to store the variable's data */ +} ConfigTableItem; + +/* Wraps information for parsing a specific configuration variable, to + * be stored in a gperf perfect hashtable */ +typedef struct ConfigPerfItem { + const char *section_and_lvalue; /* Section + "." + name of the variable */ + ConfigParserCallback parse; /* Function that is called to parse the variable's value */ + int ltype; /* Distinguish different variables passed to the same callback */ + size_t offset; /* Offset where to store data, from the beginning of userdata */ +} ConfigPerfItem; + +/* Prototype for a low-level gperf lookup function */ +typedef const ConfigPerfItem* (*ConfigPerfItemLookup)(const char *section_and_lvalue, unsigned length); + +/* Prototype for a generic high-level lookup function */ +typedef int (*ConfigItemLookup)( + const void *table, + const char *section, + const char *lvalue, + ConfigParserCallback *func, + int *ltype, + void **data, + void *userdata); + +/* Linear table search implementation of ConfigItemLookup, based on + * ConfigTableItem arrays */ +int config_item_table_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata); + +/* gperf implementation of ConfigItemLookup, based on gperf + * ConfigPerfItem tables */ +int config_item_perf_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata); + +int config_parse( + const char *unit, + const char *filename, + FILE *f, + const char *sections, /* nulstr */ + ConfigItemLookup lookup, + const void *table, + ConfigParseFlags flags, + void *userdata); + +int config_parse_many_nulstr( + const char *conf_file, /* possibly NULL */ + const char *conf_file_dirs, /* nulstr */ + const char *sections, /* nulstr */ + ConfigItemLookup lookup, + const void *table, + ConfigParseFlags flags, + void *userdata); + +int config_parse_many( + const char *conf_file, /* possibly NULL */ + const char* const* conf_file_dirs, + const char *dropin_dirname, + const char *sections, /* nulstr */ + ConfigItemLookup lookup, + const void *table, + ConfigParseFlags flags, + void *userdata); + +CONFIG_PARSER_PROTOTYPE(config_parse_int); +CONFIG_PARSER_PROTOTYPE(config_parse_unsigned); +CONFIG_PARSER_PROTOTYPE(config_parse_long); +CONFIG_PARSER_PROTOTYPE(config_parse_uint8); +CONFIG_PARSER_PROTOTYPE(config_parse_uint16); +CONFIG_PARSER_PROTOTYPE(config_parse_uint32); +CONFIG_PARSER_PROTOTYPE(config_parse_uint64); +CONFIG_PARSER_PROTOTYPE(config_parse_double); +CONFIG_PARSER_PROTOTYPE(config_parse_iec_size); +CONFIG_PARSER_PROTOTYPE(config_parse_si_size); +CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64); +CONFIG_PARSER_PROTOTYPE(config_parse_bool); +CONFIG_PARSER_PROTOTYPE(config_parse_tristate); +CONFIG_PARSER_PROTOTYPE(config_parse_string); +CONFIG_PARSER_PROTOTYPE(config_parse_path); +CONFIG_PARSER_PROTOTYPE(config_parse_strv); +CONFIG_PARSER_PROTOTYPE(config_parse_sec); +CONFIG_PARSER_PROTOTYPE(config_parse_sec_def_infinity); +CONFIG_PARSER_PROTOTYPE(config_parse_sec_def_unset); +CONFIG_PARSER_PROTOTYPE(config_parse_nsec); +CONFIG_PARSER_PROTOTYPE(config_parse_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_warn_compat); +CONFIG_PARSER_PROTOTYPE(config_parse_log_facility); +CONFIG_PARSER_PROTOTYPE(config_parse_log_level); +CONFIG_PARSER_PROTOTYPE(config_parse_signal); +CONFIG_PARSER_PROTOTYPE(config_parse_personality); +CONFIG_PARSER_PROTOTYPE(config_parse_permille); +CONFIG_PARSER_PROTOTYPE(config_parse_ifname); +CONFIG_PARSER_PROTOTYPE(config_parse_ip_port); +CONFIG_PARSER_PROTOTYPE(config_parse_mtu); +CONFIG_PARSER_PROTOTYPE(config_parse_rlimit); + +typedef enum Disabled { + DISABLED_CONFIGURATION, + DISABLED_LEGACY, + DISABLED_EXPERIMENTAL, +} Disabled; + +#define DEFINE_CONFIG_PARSE(function, parser, msg) \ + CONFIG_PARSER_PROTOTYPE(function) { \ + int *i = data, r; \ + \ + assert(filename); \ + assert(lvalue); \ + assert(rvalue); \ + assert(data); \ + \ + r = parser(rvalue); \ + if (r < 0) { \ + log_syntax(unit, LOG_ERR, filename, line, r, \ + msg ", ignoring: %s", rvalue); \ + return 0; \ + } \ + \ + *i = r; \ + return 0; \ + } + +#define DEFINE_CONFIG_PARSE_PTR(function, parser, type, msg) \ + CONFIG_PARSER_PROTOTYPE(function) { \ + type *i = data; \ + int r; \ + \ + assert(filename); \ + assert(lvalue); \ + assert(rvalue); \ + assert(data); \ + \ + r = parser(rvalue, i); \ + if (r < 0) \ + log_syntax(unit, LOG_ERR, filename, line, r, \ + msg ", ignoring: %s", rvalue); \ + \ + return 0; \ + } + +#define DEFINE_CONFIG_PARSE_ENUM(function, name, type, msg) \ + CONFIG_PARSER_PROTOTYPE(function) { \ + type *i = data, x; \ + \ + assert(filename); \ + assert(lvalue); \ + assert(rvalue); \ + assert(data); \ + \ + x = name##_from_string(rvalue); \ + if (x < 0) { \ + log_syntax(unit, LOG_ERR, filename, line, 0, \ + msg ", ignoring: %s", rvalue); \ + return 0; \ + } \ + \ + *i = x; \ + return 0; \ + } + +#define DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(function, name, type, default_value, msg) \ + CONFIG_PARSER_PROTOTYPE(function) { \ + type *i = data, x; \ + \ + assert(filename); \ + assert(lvalue); \ + assert(rvalue); \ + assert(data); \ + \ + if (isempty(rvalue)) { \ + *i = default_value; \ + return 0; \ + } \ + \ + x = name##_from_string(rvalue); \ + if (x < 0) { \ + log_syntax(unit, LOG_ERR, filename, line, 0, \ + msg ", ignoring: %s", rvalue); \ + return 0; \ + } \ + \ + *i = x; \ + return 0; \ + } + +#define DEFINE_CONFIG_PARSE_ENUMV(function, name, type, invalid, msg) \ + CONFIG_PARSER_PROTOTYPE(function) { \ + type **enums = data, x, *ys; \ + _cleanup_free_ type *xs = NULL; \ + const char *word, *state; \ + size_t l, i = 0; \ + \ + assert(filename); \ + assert(lvalue); \ + assert(rvalue); \ + assert(data); \ + \ + xs = new0(type, 1); \ + if (!xs) \ + return -ENOMEM; \ + \ + *xs = invalid; \ + \ + FOREACH_WORD(word, l, rvalue, state) { \ + _cleanup_free_ char *en = NULL; \ + type *new_xs; \ + \ + en = strndup(word, l); \ + if (!en) \ + return -ENOMEM; \ + \ + if ((x = name##_from_string(en)) < 0) { \ + log_syntax(unit, LOG_ERR, filename, line, 0, \ + msg ", ignoring: %s", en); \ + continue; \ + } \ + \ + for (ys = xs; x != invalid && *ys != invalid; ys++) { \ + if (*ys == x) { \ + log_syntax(unit, LOG_NOTICE, filename, \ + line, 0, \ + "Duplicate entry, ignoring: %s", \ + en); \ + x = invalid; \ + } \ + } \ + \ + if (x == invalid) \ + continue; \ + \ + *(xs + i) = x; \ + new_xs = realloc(xs, (++i + 1) * sizeof(type)); \ + if (new_xs) \ + xs = new_xs; \ + else \ + return -ENOMEM; \ + \ + *(xs + i) = invalid; \ + } \ + \ + free_and_replace(*enums, xs); \ + return 0; \ + } diff --git a/src/shared/cpu-set-util.c b/src/shared/cpu-set-util.c new file mode 100644 index 00000000..219314ef --- /dev/null +++ b/src/shared/cpu-set-util.c @@ -0,0 +1,382 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "cpu-set-util.h" +#include "dirent-util.h" +#include "errno-util.h" +#include "extract-word.h" +#include "fd-util.h" +#include "log.h" +#include "macro.h" +#include "memory-util.h" +#include "missing_syscall.h" +#include "parse-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "string-table.h" +#include "strv.h" +#include "util.h" + +char* cpu_set_to_string(const CPUSet *a) { + _cleanup_free_ char *str = NULL; + size_t allocated = 0, len = 0; + int i, r; + + for (i = 0; (size_t) i < a->allocated * 8; i++) { + if (!CPU_ISSET_S(i, a->allocated, a->set)) + continue; + + if (!GREEDY_REALLOC(str, allocated, len + 1 + DECIMAL_STR_MAX(int))) + return NULL; + + r = sprintf(str + len, len > 0 ? " %d" : "%d", i); + assert_se(r > 0); + len += r; + } + + return TAKE_PTR(str) ?: strdup(""); +} + +char *cpu_set_to_range_string(const CPUSet *set) { + unsigned range_start = 0, range_end; + _cleanup_free_ char *str = NULL; + size_t allocated = 0, len = 0; + bool in_range = false; + int r; + + for (unsigned i = 0; i < set->allocated * 8; i++) + if (CPU_ISSET_S(i, set->allocated, set->set)) { + if (in_range) + range_end++; + else { + range_start = range_end = i; + in_range = true; + } + } else if (in_range) { + in_range = false; + + if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(unsigned))) + return NULL; + + if (range_end > range_start) + r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); + else + r = sprintf(str + len, len > 0 ? " %d" : "%d", range_start); + assert_se(r > 0); + len += r; + } + + if (in_range) { + if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(int))) + return NULL; + + if (range_end > range_start) + r = sprintf(str + len, len > 0 ? " %d-%d" : "%d-%d", range_start, range_end); + else + r = sprintf(str + len, len > 0 ? " %d" : "%d", range_start); + assert_se(r > 0); + } + + return TAKE_PTR(str) ?: strdup(""); +} + +int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) { + size_t need; + + assert(cpu_set); + + need = CPU_ALLOC_SIZE(ncpus); + if (need > cpu_set->allocated) { + cpu_set_t *t; + + t = realloc(cpu_set->set, need); + if (!t) + return -ENOMEM; + + memzero((uint8_t*) t + cpu_set->allocated, need - cpu_set->allocated); + + cpu_set->set = t; + cpu_set->allocated = need; + } + + return 0; +} + +static int cpu_set_add(CPUSet *cpu_set, unsigned cpu) { + int r; + + if (cpu >= 8192) + /* As of kernel 5.1, CONFIG_NR_CPUS can be set to 8192 on PowerPC */ + return -ERANGE; + + r = cpu_set_realloc(cpu_set, cpu + 1); + if (r < 0) + return r; + + CPU_SET_S(cpu, cpu_set->allocated, cpu_set->set); + return 0; +} + +int cpu_set_add_all(CPUSet *a, const CPUSet *b) { + int r; + + /* Do this backwards, so if we fail, we fail before changing anything. */ + for (unsigned cpu_p1 = b->allocated * 8; cpu_p1 > 0; cpu_p1--) + if (CPU_ISSET_S(cpu_p1 - 1, b->allocated, b->set)) { + r = cpu_set_add(a, cpu_p1 - 1); + if (r < 0) + return r; + } + + return 0; +} + +int parse_cpu_set_full( + const char *rvalue, + CPUSet *cpu_set, + bool warn, + const char *unit, + const char *filename, + unsigned line, + const char *lvalue) { + + _cleanup_(cpu_set_reset) CPUSet c = {}; + const char *p = rvalue; + + assert(p); + + for (;;) { + _cleanup_free_ char *word = NULL; + unsigned cpu_lower, cpu_upper; + int r; + + r = extract_first_word(&p, &word, WHITESPACE ",", EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return warn ? log_oom() : -ENOMEM; + if (r < 0) + return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Invalid value for %s: %s", lvalue, rvalue) : r; + if (r == 0) + break; + + r = parse_range(word, &cpu_lower, &cpu_upper); + if (r < 0) + return warn ? log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse CPU affinity '%s'", word) : r; + + if (cpu_lower > cpu_upper) { + if (warn) + log_syntax(unit, LOG_WARNING, filename, line, 0, "Range '%s' is invalid, %u > %u, ignoring.", + word, cpu_lower, cpu_upper); + + /* Make sure something is allocated, to distinguish this from the empty case */ + r = cpu_set_realloc(&c, 1); + if (r < 0) + return r; + } + + for (unsigned cpu_p1 = MIN(cpu_upper, UINT_MAX-1) + 1; cpu_p1 > cpu_lower; cpu_p1--) { + r = cpu_set_add(&c, cpu_p1 - 1); + if (r < 0) + return warn ? log_syntax(unit, LOG_ERR, filename, line, r, + "Cannot add CPU %u to set: %m", cpu_p1 - 1) : r; + } + } + + /* On success, transfer ownership to the output variable */ + *cpu_set = c; + c = (CPUSet) {}; + + return 0; +} + +int parse_cpu_set_extend( + const char *rvalue, + CPUSet *old, + bool warn, + const char *unit, + const char *filename, + unsigned line, + const char *lvalue) { + + _cleanup_(cpu_set_reset) CPUSet cpuset = {}; + int r; + + r = parse_cpu_set_full(rvalue, &cpuset, true, unit, filename, line, lvalue); + if (r < 0) + return r; + + if (!cpuset.set) { + /* An empty assignment resets the CPU list */ + cpu_set_reset(old); + return 0; + } + + if (!old->set) { + *old = cpuset; + cpuset = (CPUSet) {}; + return 0; + } + + return cpu_set_add_all(old, &cpuset); +} + +int cpus_in_affinity_mask(void) { + size_t n = 16; + int r; + + for (;;) { + cpu_set_t *c; + + c = CPU_ALLOC(n); + if (!c) + return -ENOMEM; + + if (sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0) { + int k; + + k = CPU_COUNT_S(CPU_ALLOC_SIZE(n), c); + CPU_FREE(c); + + if (k <= 0) + return -EINVAL; + + return k; + } + + r = -errno; + CPU_FREE(c); + + if (r != -EINVAL) + return r; + if (n > SIZE_MAX/2) + return -ENOMEM; + n *= 2; + } +} + +int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated) { + uint8_t *out; + + assert(set); + assert(ret); + + out = new0(uint8_t, set->allocated); + if (!out) + return -ENOMEM; + + for (unsigned cpu = 0; cpu < set->allocated * 8; cpu++) + if (CPU_ISSET_S(cpu, set->allocated, set->set)) + out[cpu / 8] |= 1u << (cpu % 8); + + *ret = out; + *allocated = set->allocated; + return 0; +} + +int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set) { + _cleanup_(cpu_set_reset) CPUSet s = {}; + int r; + + assert(bits); + assert(set); + + for (unsigned cpu = size * 8; cpu > 0; cpu--) + if (bits[(cpu - 1) / 8] & (1u << ((cpu - 1) % 8))) { + r = cpu_set_add(&s, cpu - 1); + if (r < 0) + return r; + } + + *set = s; + s = (CPUSet) {}; + return 0; +} + +bool numa_policy_is_valid(const NUMAPolicy *policy) { + assert(policy); + + if (!mpol_is_valid(numa_policy_get_type(policy))) + return false; + + if (!policy->nodes.set && + !IN_SET(numa_policy_get_type(policy), MPOL_DEFAULT, MPOL_LOCAL, MPOL_PREFERRED)) + return false; + + if (policy->nodes.set && + numa_policy_get_type(policy) == MPOL_PREFERRED && + CPU_COUNT_S(policy->nodes.allocated, policy->nodes.set) != 1) + return false; + + return true; +} + +static int numa_policy_to_mempolicy(const NUMAPolicy *policy, unsigned long *ret_maxnode, unsigned long **ret_nodes) { + unsigned node, bits = 0, ulong_bits; + _cleanup_free_ unsigned long *out = NULL; + + assert(policy); + assert(ret_maxnode); + assert(ret_nodes); + + if (IN_SET(numa_policy_get_type(policy), MPOL_DEFAULT, MPOL_LOCAL) || + (numa_policy_get_type(policy) == MPOL_PREFERRED && !policy->nodes.set)) { + *ret_nodes = NULL; + *ret_maxnode = 0; + return 0; + } + + bits = policy->nodes.allocated * 8; + ulong_bits = sizeof(unsigned long) * 8; + + out = new0(unsigned long, DIV_ROUND_UP(policy->nodes.allocated, sizeof(unsigned long))); + if (!out) + return -ENOMEM; + + /* We don't make any assumptions about internal type libc is using to store NUMA node mask. + Hence we need to convert the node mask to the representation expected by set_mempolicy() */ + for (node = 0; node < bits; node++) + if (CPU_ISSET_S(node, policy->nodes.allocated, policy->nodes.set)) + out[node / ulong_bits] |= 1ul << (node % ulong_bits); + + *ret_nodes = TAKE_PTR(out); + *ret_maxnode = bits + 1; + return 0; +} + +int apply_numa_policy(const NUMAPolicy *policy) { + int r; + _cleanup_free_ unsigned long *nodes = NULL; + unsigned long maxnode; + + assert(policy); + + if (get_mempolicy(NULL, NULL, 0, 0, 0) < 0 && errno == ENOSYS) + return -EOPNOTSUPP; + + if (!numa_policy_is_valid(policy)) + return -EINVAL; + + r = numa_policy_to_mempolicy(policy, &maxnode, &nodes); + if (r < 0) + return r; + + r = set_mempolicy(numa_policy_get_type(policy), nodes, maxnode); + if (r < 0) + return -errno; + + return 0; +} + +static const char* const mpol_table[] = { + [MPOL_DEFAULT] = "default", + [MPOL_PREFERRED] = "preferred", + [MPOL_BIND] = "bind", + [MPOL_INTERLEAVE] = "interleave", + [MPOL_LOCAL] = "local", +}; + +DEFINE_STRING_TABLE_LOOKUP(mpol, int); diff --git a/src/shared/cpu-set-util.h b/src/shared/cpu-set-util.h new file mode 100644 index 00000000..27812dfd --- /dev/null +++ b/src/shared/cpu-set-util.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" +#include "missing_syscall.h" + +/* This wraps the libc interface with a variable to keep the allocated size. */ +typedef struct CPUSet { + cpu_set_t *set; + size_t allocated; /* in bytes */ +} CPUSet; + +static inline void cpu_set_reset(CPUSet *a) { + assert((a->allocated > 0) == !!a->set); + if (a->set) + CPU_FREE(a->set); + *a = (CPUSet) {}; +} + +int cpu_set_add_all(CPUSet *a, const CPUSet *b); + +char* cpu_set_to_string(const CPUSet *a); +char *cpu_set_to_range_string(const CPUSet *a); +int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus); + +int parse_cpu_set_full( + const char *rvalue, + CPUSet *cpu_set, + bool warn, + const char *unit, + const char *filename, unsigned line, + const char *lvalue); +int parse_cpu_set_extend( + const char *rvalue, + CPUSet *old, + bool warn, + const char *unit, + const char *filename, + unsigned line, + const char *lvalue); + +static inline int parse_cpu_set(const char *rvalue, CPUSet *cpu_set){ + return parse_cpu_set_full(rvalue, cpu_set, false, NULL, NULL, 0, NULL); +} + +int cpu_set_to_dbus(const CPUSet *set, uint8_t **ret, size_t *allocated); +int cpu_set_from_dbus(const uint8_t *bits, size_t size, CPUSet *set); + +int cpus_in_affinity_mask(void); + +static inline bool mpol_is_valid(int t) { + return t >= MPOL_DEFAULT && t <= MPOL_LOCAL; +} + +typedef struct NUMAPolicy { + /* Always use numa_policy_get_type() to read the value */ + int type; + CPUSet nodes; +} NUMAPolicy; + +bool numa_policy_is_valid(const NUMAPolicy *p); + +static inline int numa_policy_get_type(const NUMAPolicy *p) { + return p->type < 0 ? (p->nodes.set ? MPOL_PREFERRED : -1) : p->type; +} + +static inline void numa_policy_reset(NUMAPolicy *p) { + assert(p); + cpu_set_reset(&p->nodes); + p->type = -1; +} + +int apply_numa_policy(const NUMAPolicy *policy); + +const char* mpol_to_string(int i) _const_; +int mpol_from_string(const char *s) _pure_; diff --git a/src/shared/crypt-util.c b/src/shared/crypt-util.c new file mode 100644 index 00000000..20bdc548 --- /dev/null +++ b/src/shared/crypt-util.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if HAVE_LIBCRYPTSETUP +#include "crypt-util.h" +#include "log.h" + +void cryptsetup_log_glue(int level, const char *msg, void *usrptr) { + switch (level) { + case CRYPT_LOG_NORMAL: + level = LOG_NOTICE; + break; + case CRYPT_LOG_ERROR: + level = LOG_ERR; + break; + case CRYPT_LOG_VERBOSE: + level = LOG_INFO; + break; + case CRYPT_LOG_DEBUG: + level = LOG_DEBUG; + break; + default: + log_error("Unknown libcryptsetup log level: %d", level); + level = LOG_ERR; + } + + log_full(level, "%s", msg); +} +#endif diff --git a/src/shared/crypt-util.h b/src/shared/crypt-util.h new file mode 100644 index 00000000..c25b1159 --- /dev/null +++ b/src/shared/crypt-util.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#if HAVE_LIBCRYPTSETUP +#include + +#include "macro.h" + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct crypt_device *, crypt_free); + +void cryptsetup_log_glue(int level, const char *msg, void *usrptr); +#endif diff --git a/src/shared/daemon-util.h b/src/shared/daemon-util.h new file mode 100644 index 00000000..5e9eca1d --- /dev/null +++ b/src/shared/daemon-util.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-daemon.h" + +#define NOTIFY_READY "READY=1\n" "STATUS=Processing requests..." +#define NOTIFY_STOPPING "STOPPING=1\n" "STATUS=Shutting down..." + +static inline const char *notify_start(const char *start, const char *stop) { + if (start) + (void) sd_notify(false, start); + + return stop; +} + +/* This is intended to be used with _cleanup_ attribute. */ +static inline void notify_on_cleanup(const char **p) { + if (p) + (void) sd_notify(false, *p); +} diff --git a/src/shared/dev-setup.c b/src/shared/dev-setup.c new file mode 100644 index 00000000..071ff7b3 --- /dev/null +++ b/src/shared/dev-setup.c @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "dev-setup.h" +#include "label.h" +#include "log.h" +#include "nulstr-util.h" +#include "path-util.h" +#include "umask-util.h" +#include "user-util.h" + +int dev_setup(const char *prefix, uid_t uid, gid_t gid) { + static const char symlinks[] = + "-/proc/kcore\0" "/dev/core\0" + "/proc/self/fd\0" "/dev/fd\0" + "/proc/self/fd/0\0" "/dev/stdin\0" + "/proc/self/fd/1\0" "/dev/stdout\0" + "/proc/self/fd/2\0" "/dev/stderr\0"; + + const char *j, *k; + int r; + + NULSTR_FOREACH_PAIR(j, k, symlinks) { + _cleanup_free_ char *link_name = NULL; + const char *n; + + if (j[0] == '-') { + j++; + + if (access(j, F_OK) < 0) + continue; + } + + if (prefix) { + link_name = path_join(prefix, k); + if (!link_name) + return -ENOMEM; + + n = link_name; + } else + n = k; + + r = symlink_label(j, n); + if (r < 0) + log_debug_errno(r, "Failed to symlink %s to %s: %m", j, n); + + if (uid != UID_INVALID || gid != GID_INVALID) + if (lchown(n, uid, gid) < 0) + log_debug_errno(errno, "Failed to chown %s: %m", n); + } + + return 0; +} + +int make_inaccessible_nodes(const char *root, uid_t uid, gid_t gid) { + static const struct { + const char *name; + mode_t mode; + } table[] = { + { "/run/systemd", S_IFDIR | 0755 }, + { "/run/systemd/inaccessible", S_IFDIR | 0000 }, + { "/run/systemd/inaccessible/reg", S_IFREG | 0000 }, + { "/run/systemd/inaccessible/dir", S_IFDIR | 0000 }, + { "/run/systemd/inaccessible/fifo", S_IFIFO | 0000 }, + { "/run/systemd/inaccessible/sock", S_IFSOCK | 0000 }, + + /* The following two are likely to fail if we lack the privs for it (for example in an userns + * environment, if CAP_SYS_MKNOD is missing, or if a device node policy prohibit major/minor of 0 + * device nodes to be created). But that's entirely fine. Consumers of these files should carry + * fallback to use a different node then, for example /run/systemd/inaccessible/sock, which is close + * enough in behaviour and semantics for most uses. */ + { "/run/systemd/inaccessible/chr", S_IFCHR | 0000 }, + { "/run/systemd/inaccessible/blk", S_IFBLK | 0000 }, + }; + + _cleanup_umask_ mode_t u; + size_t i; + int r; + + u = umask(0000); + + /* Set up inaccessible (and empty) file nodes of all types. This are used to as mount sources for over-mounting + * ("masking") file nodes that shall become inaccessible and empty for specific containers or services. We try + * to lock down these nodes as much as we can, but otherwise try to match them as closely as possible with the + * underlying file, i.e. in the best case we offer the same node type as the underlying node. */ + + for (i = 0; i < ELEMENTSOF(table); i++) { + _cleanup_free_ char *path = NULL; + + path = path_join(root, table[i].name); + if (!path) + return log_oom(); + + if (S_ISDIR(table[i].mode)) + r = mkdir(path, table[i].mode & 07777); + else + r = mknod(path, table[i].mode, makedev(0, 0)); + if (r < 0) { + if (errno != EEXIST) + log_debug_errno(errno, "Failed to create '%s', ignoring: %m", path); + continue; + } + + if (uid != UID_INVALID || gid != GID_INVALID) { + if (lchown(path, uid, gid) < 0) + log_debug_errno(errno, "Failed to chown '%s': %m", path); + } + } + + return 0; +} diff --git a/src/shared/dev-setup.h b/src/shared/dev-setup.h new file mode 100644 index 00000000..72b90ec4 --- /dev/null +++ b/src/shared/dev-setup.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int dev_setup(const char *prefix, uid_t uid, gid_t gid); + +int make_inaccessible_nodes(const char *root, uid_t uid, gid_t gid); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c new file mode 100644 index 00000000..934e0fe8 --- /dev/null +++ b/src/shared/dissect-image.c @@ -0,0 +1,1523 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-device.h" +#include "sd-id128.h" + +#include "architecture.h" +#include "ask-password-api.h" +#include "blkid-util.h" +#include "blockdev-util.h" +#include "copy.h" +#include "crypt-util.h" +#include "def.h" +#include "device-nodes.h" +#include "device-util.h" +#include "dissect-image.h" +#include "dm-util.h" +#include "env-file.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "gpt.h" +#include "hexdecoct.h" +#include "hostname-util.h" +#include "id128-util.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "nulstr-util.h" +#include "os-util.h" +#include "path-util.h" +#include "process-util.h" +#include "raw-clone.h" +#include "signal-util.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "udev-util.h" +#include "user-util.h" +#include "xattr-util.h" + +int probe_filesystem(const char *node, char **ret_fstype) { + /* Try to find device content type and return it in *ret_fstype. If nothing is found, + * 0/NULL will be returned. -EUCLEAN will be returned for ambiguous results, and an + * different error otherwise. */ + +#if HAVE_BLKID + _cleanup_(blkid_free_probep) blkid_probe b = NULL; + const char *fstype; + int r; + + errno = 0; + b = blkid_new_probe_from_filename(node); + if (!b) + return errno_or_else(ENOMEM); + + blkid_probe_enable_superblocks(b, 1); + blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE); + + errno = 0; + r = blkid_do_safeprobe(b); + if (r == 1) { + log_debug("No type detected on partition %s", node); + goto not_found; + } + if (r == -2) { + log_debug("Results ambiguous for partition %s", node); + return -EUCLEAN; + } + if (r != 0) + return errno_or_else(EIO); + + (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); + + if (fstype) { + char *t; + + t = strdup(fstype); + if (!t) + return -ENOMEM; + + *ret_fstype = t; + return 1; + } + +not_found: + *ret_fstype = NULL; + return 0; +#else + return -EOPNOTSUPP; +#endif +} + +#if HAVE_BLKID +/* Detect RPMB and Boot partitions, which are not listed by blkid. + * See https://github.com/systemd/systemd/issues/5806. */ +static bool device_is_mmc_special_partition(sd_device *d) { + const char *sysname; + + assert(d); + + if (sd_device_get_sysname(d, &sysname) < 0) + return false; + + return startswith(sysname, "mmcblk") && + (endswith(sysname, "rpmb") || endswith(sysname, "boot0") || endswith(sysname, "boot1")); +} + +static bool device_is_block(sd_device *d) { + const char *ss; + + assert(d); + + if (sd_device_get_subsystem(d, &ss) < 0) + return false; + + return streq(ss, "block"); +} + +static int enumerator_for_parent(sd_device *d, sd_device_enumerator **ret) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + int r; + + assert(d); + assert(ret); + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_parent(e, d); + if (r < 0) + return r; + + *ret = TAKE_PTR(e); + return 0; +} + +/* how many times to wait for the device nodes to appear */ +#define N_DEVICE_NODE_LIST_ATTEMPTS 10 + +static int wait_for_partitions_to_appear( + int fd, + sd_device *d, + unsigned num_partitions, + DissectImageFlags flags, + sd_device_enumerator **ret_enumerator) { + + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *q; + unsigned n; + int r; + + assert(fd >= 0); + assert(d); + assert(ret_enumerator); + + r = enumerator_for_parent(d, &e); + if (r < 0) + return r; + + /* Count the partitions enumerated by the kernel */ + n = 0; + FOREACH_DEVICE(e, q) { + if (sd_device_get_devnum(q, NULL) < 0) + continue; + if (!device_is_block(q)) + continue; + if (device_is_mmc_special_partition(q)) + continue; + + if (!FLAGS_SET(flags, DISSECT_IMAGE_NO_UDEV)) { + r = device_wait_for_initialization(q, "block", USEC_INFINITY, NULL); + if (r < 0) + return r; + } + + n++; + } + + if (n == num_partitions + 1) { + *ret_enumerator = TAKE_PTR(e); + return 0; /* success! */ + } + if (n > num_partitions + 1) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), + "blkid and kernel partition lists do not match."); + + /* The kernel has probed fewer partitions than blkid? Maybe the kernel prober is still running or it + * got EBUSY because udev already opened the device. Let's reprobe the device, which is a synchronous + * call that waits until probing is complete. */ + + for (unsigned j = 0; ; j++) { + if (j++ > 20) + return -EBUSY; + + if (ioctl(fd, BLKRRPART, 0) >= 0) + break; + r = -errno; + if (r == -EINVAL) { + struct loop_info64 info; + + /* If we are running on a loop device that has partition scanning off, return + * an explicit recognizable error about this, so that callers can generate a + * proper message explaining the situation. */ + + if (ioctl(fd, LOOP_GET_STATUS64, &info) >= 0 && (info.lo_flags & LO_FLAGS_PARTSCAN) == 0) { + log_debug("Device is a loop device and partition scanning is off!"); + return -EPROTONOSUPPORT; + } + } + if (r != -EBUSY) + return r; + + /* If something else has the device open, such as an udev rule, the ioctl will return + * EBUSY. Since there's no way to wait until it isn't busy anymore, let's just wait a bit, + * and try again. + * + * This is really something they should fix in the kernel! */ + (void) usleep(50 * USEC_PER_MSEC); + + } + + return -EAGAIN; /* no success yet, try again */ +} + +static int loop_wait_for_partitions_to_appear( + int fd, + sd_device *d, + unsigned num_partitions, + DissectImageFlags flags, + sd_device_enumerator **ret_enumerator) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + int r; + + assert(fd >= 0); + assert(d); + assert(ret_enumerator); + + log_debug("Waiting for device (parent + %d partitions) to appear...", num_partitions); + + if (!FLAGS_SET(flags, DISSECT_IMAGE_NO_UDEV)) { + r = device_wait_for_initialization(d, "block", USEC_INFINITY, &device); + if (r < 0) + return r; + } else + device = sd_device_ref(d); + + for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) { + r = wait_for_partitions_to_appear(fd, device, num_partitions, flags, ret_enumerator); + if (r != -EAGAIN) + return r; + } + + return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), + "Kernel partitions dit not appear within %d attempts", + N_DEVICE_NODE_LIST_ATTEMPTS); +} + +#endif + +int dissect_image( + int fd, + const void *root_hash, + size_t root_hash_size, + DissectImageFlags flags, + DissectedImage **ret) { + +#if HAVE_BLKID + sd_id128_t root_uuid = SD_ID128_NULL, verity_uuid = SD_ID128_NULL; + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + bool is_gpt, is_mbr, generic_rw, multiple_generic = false; + _cleanup_(sd_device_unrefp) sd_device *d = NULL; + _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; + _cleanup_(blkid_free_probep) blkid_probe b = NULL; + _cleanup_free_ char *generic_node = NULL; + sd_id128_t generic_uuid = SD_ID128_NULL; + const char *pttype = NULL; + blkid_partlist pl; + int r, generic_nr; + struct stat st; + sd_device *q; + unsigned i; + + assert(fd >= 0); + assert(ret); + assert(root_hash || root_hash_size == 0); + + /* Probes a disk image, and returns information about what it found in *ret. + * + * Returns -ENOPKG if no suitable partition table or file system could be found. + * Returns -EADDRNOTAVAIL if a root hash was specified but no matching root/verity partitions found. */ + + if (root_hash) { + /* If a root hash is supplied, then we use the root partition that has a UUID that match the first + * 128bit of the root hash. And we use the verity partition that has a UUID that match the final + * 128bit. */ + + if (root_hash_size < sizeof(sd_id128_t)) + return -EINVAL; + + memcpy(&root_uuid, root_hash, sizeof(sd_id128_t)); + memcpy(&verity_uuid, (const uint8_t*) root_hash + root_hash_size - sizeof(sd_id128_t), sizeof(sd_id128_t)); + + if (sd_id128_is_null(root_uuid)) + return -EINVAL; + if (sd_id128_is_null(verity_uuid)) + return -EINVAL; + } + + if (fstat(fd, &st) < 0) + return -errno; + + if (!S_ISBLK(st.st_mode)) + return -ENOTBLK; + + b = blkid_new_probe(); + if (!b) + return -ENOMEM; + + errno = 0; + r = blkid_probe_set_device(b, fd, 0, 0); + if (r != 0) + return errno_or_else(ENOMEM); + + if ((flags & DISSECT_IMAGE_GPT_ONLY) == 0) { + /* Look for file system superblocks, unless we only shall look for GPT partition tables */ + blkid_probe_enable_superblocks(b, 1); + blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE|BLKID_SUBLKS_USAGE); + } + + blkid_probe_enable_partitions(b, 1); + blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); + + errno = 0; + r = blkid_do_safeprobe(b); + if (IN_SET(r, -2, 1)) + return log_debug_errno(SYNTHETIC_ERRNO(ENOPKG), "Failed to identify any partition table."); + if (r != 0) + return errno_or_else(EIO); + + m = new0(DissectedImage, 1); + if (!m) + return -ENOMEM; + + r = sd_device_new_from_devnum(&d, 'b', st.st_rdev); + if (r < 0) + return r; + + if (!(flags & DISSECT_IMAGE_GPT_ONLY) && + (flags & DISSECT_IMAGE_REQUIRE_ROOT)) { + const char *usage = NULL; + + (void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL); + if (STRPTR_IN_SET(usage, "filesystem", "crypto")) { + _cleanup_free_ char *t = NULL, *n = NULL; + const char *fstype = NULL; + + /* OK, we have found a file system, that's our root partition then. */ + (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL); + + if (fstype) { + t = strdup(fstype); + if (!t) + return -ENOMEM; + } + + r = device_path_make_major_minor(st.st_mode, st.st_rdev, &n); + if (r < 0) + return r; + + m->partitions[PARTITION_ROOT] = (DissectedPartition) { + .found = true, + .rw = true, + .partno = -1, + .architecture = _ARCHITECTURE_INVALID, + .fstype = TAKE_PTR(t), + .node = TAKE_PTR(n), + }; + + m->encrypted = streq_ptr(fstype, "crypto_LUKS"); + + r = loop_wait_for_partitions_to_appear(fd, d, 0, flags, &e); + if (r < 0) + return r; + + *ret = TAKE_PTR(m); + + return 0; + } + } + + (void) blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); + if (!pttype) + return -ENOPKG; + + is_gpt = streq_ptr(pttype, "gpt"); + is_mbr = streq_ptr(pttype, "dos"); + + if (!is_gpt && ((flags & DISSECT_IMAGE_GPT_ONLY) || !is_mbr)) + return -ENOPKG; + + errno = 0; + pl = blkid_probe_get_partitions(b); + if (!pl) + return errno_or_else(ENOMEM); + + r = loop_wait_for_partitions_to_appear(fd, d, blkid_partlist_numof_partitions(pl), flags, &e); + if (r < 0) + return r; + + FOREACH_DEVICE(e, q) { + unsigned long long pflags; + blkid_partition pp; + const char *node; + dev_t qn; + int nr; + + r = sd_device_get_devnum(q, &qn); + if (r < 0) + continue; + + if (st.st_rdev == qn) + continue; + + if (!device_is_block(q)) + continue; + + if (device_is_mmc_special_partition(q)) + continue; + + r = sd_device_get_devname(q, &node); + if (r < 0) + continue; + + pp = blkid_partlist_devno_to_partition(pl, qn); + if (!pp) + continue; + + pflags = blkid_partition_get_flags(pp); + + nr = blkid_partition_get_partno(pp); + if (nr < 0) + continue; + + if (is_gpt) { + int designator = _PARTITION_DESIGNATOR_INVALID, architecture = _ARCHITECTURE_INVALID; + const char *stype, *sid, *fstype = NULL; + sd_id128_t type_id, id; + bool rw = true; + + sid = blkid_partition_get_uuid(pp); + if (!sid) + continue; + if (sd_id128_from_string(sid, &id) < 0) + continue; + + stype = blkid_partition_get_type_string(pp); + if (!stype) + continue; + if (sd_id128_from_string(stype, &type_id) < 0) + continue; + + if (sd_id128_equal(type_id, GPT_HOME)) { + + if (pflags & GPT_FLAG_NO_AUTO) + continue; + + designator = PARTITION_HOME; + rw = !(pflags & GPT_FLAG_READ_ONLY); + } else if (sd_id128_equal(type_id, GPT_SRV)) { + + if (pflags & GPT_FLAG_NO_AUTO) + continue; + + designator = PARTITION_SRV; + rw = !(pflags & GPT_FLAG_READ_ONLY); + } else if (sd_id128_equal(type_id, GPT_ESP)) { + + /* Note that we don't check the GPT_FLAG_NO_AUTO flag for the ESP, as it is not defined + * there. We instead check the GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as recommended by the + * UEFI spec (See "12.3.3 Number and Location of System Partitions"). */ + + if (pflags & GPT_FLAG_NO_BLOCK_IO_PROTOCOL) + continue; + + designator = PARTITION_ESP; + fstype = "vfat"; + + } else if (sd_id128_equal(type_id, GPT_XBOOTLDR)) { + + if (pflags & GPT_FLAG_NO_AUTO) + continue; + + designator = PARTITION_XBOOTLDR; + rw = !(pflags & GPT_FLAG_READ_ONLY); + } +#ifdef GPT_ROOT_NATIVE + else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) { + + if (pflags & GPT_FLAG_NO_AUTO) + continue; + + /* If a root ID is specified, ignore everything but the root id */ + if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id)) + continue; + + designator = PARTITION_ROOT; + architecture = native_architecture(); + rw = !(pflags & GPT_FLAG_READ_ONLY); + } else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE_VERITY)) { + + if (pflags & GPT_FLAG_NO_AUTO) + continue; + + m->can_verity = true; + + /* Ignore verity unless a root hash is specified */ + if (sd_id128_is_null(verity_uuid) || !sd_id128_equal(verity_uuid, id)) + continue; + + designator = PARTITION_ROOT_VERITY; + fstype = "DM_verity_hash"; + architecture = native_architecture(); + rw = false; + } +#endif +#ifdef GPT_ROOT_SECONDARY + else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY)) { + + if (pflags & GPT_FLAG_NO_AUTO) + continue; + + /* If a root ID is specified, ignore everything but the root id */ + if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id)) + continue; + + designator = PARTITION_ROOT_SECONDARY; + architecture = SECONDARY_ARCHITECTURE; + rw = !(pflags & GPT_FLAG_READ_ONLY); + } else if (sd_id128_equal(type_id, GPT_ROOT_SECONDARY_VERITY)) { + + if (pflags & GPT_FLAG_NO_AUTO) + continue; + + m->can_verity = true; + + /* Ignore verity unless root has is specified */ + if (sd_id128_is_null(verity_uuid) || !sd_id128_equal(verity_uuid, id)) + continue; + + designator = PARTITION_ROOT_SECONDARY_VERITY; + fstype = "DM_verity_hash"; + architecture = SECONDARY_ARCHITECTURE; + rw = false; + } +#endif + else if (sd_id128_equal(type_id, GPT_SWAP)) { + + if (pflags & GPT_FLAG_NO_AUTO) + continue; + + designator = PARTITION_SWAP; + fstype = "swap"; + } else if (sd_id128_equal(type_id, GPT_LINUX_GENERIC)) { + + if (pflags & GPT_FLAG_NO_AUTO) + continue; + + if (generic_node) + multiple_generic = true; + else { + generic_nr = nr; + generic_rw = !(pflags & GPT_FLAG_READ_ONLY); + generic_uuid = id; + generic_node = strdup(node); + if (!generic_node) + return -ENOMEM; + } + } + + if (designator != _PARTITION_DESIGNATOR_INVALID) { + _cleanup_free_ char *t = NULL, *n = NULL; + + /* First one wins */ + if (m->partitions[designator].found) + continue; + + if (fstype) { + t = strdup(fstype); + if (!t) + return -ENOMEM; + } + + n = strdup(node); + if (!n) + return -ENOMEM; + + m->partitions[designator] = (DissectedPartition) { + .found = true, + .partno = nr, + .rw = rw, + .architecture = architecture, + .node = TAKE_PTR(n), + .fstype = TAKE_PTR(t), + .uuid = id, + }; + } + + } else if (is_mbr) { + + switch (blkid_partition_get_type(pp)) { + + case 0x83: /* Linux partition */ + + if (pflags != 0x80) /* Bootable flag */ + continue; + + if (generic_node) + multiple_generic = true; + else { + generic_nr = nr; + generic_rw = true; + generic_node = strdup(node); + if (!generic_node) + return -ENOMEM; + } + + break; + + case 0xEA: { /* Boot Loader Spec extended $BOOT partition */ + _cleanup_free_ char *n = NULL; + sd_id128_t id = SD_ID128_NULL; + const char *sid; + + /* First one wins */ + if (m->partitions[PARTITION_XBOOTLDR].found) + continue; + + sid = blkid_partition_get_uuid(pp); + if (sid) + (void) sd_id128_from_string(sid, &id); + + n = strdup(node); + if (!n) + return -ENOMEM; + + m->partitions[PARTITION_XBOOTLDR] = (DissectedPartition) { + .found = true, + .partno = nr, + .rw = true, + .architecture = _ARCHITECTURE_INVALID, + .node = TAKE_PTR(n), + .uuid = id, + }; + + break; + }} + } + } + + if (!m->partitions[PARTITION_ROOT].found) { + /* No root partition found? Then let's see if ther's one for the secondary architecture. And if not + * either, then check if there's a single generic one, and use that. */ + + if (m->partitions[PARTITION_ROOT_VERITY].found) + return -EADDRNOTAVAIL; + + if (m->partitions[PARTITION_ROOT_SECONDARY].found) { + m->partitions[PARTITION_ROOT] = m->partitions[PARTITION_ROOT_SECONDARY]; + zero(m->partitions[PARTITION_ROOT_SECONDARY]); + + m->partitions[PARTITION_ROOT_VERITY] = m->partitions[PARTITION_ROOT_SECONDARY_VERITY]; + zero(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]); + + } else if (flags & DISSECT_IMAGE_REQUIRE_ROOT) { + + /* If the root has was set, then we won't fallback to a generic node, because the root hash + * decides */ + if (root_hash) + return -EADDRNOTAVAIL; + + /* If we didn't find a generic node, then we can't fix this up either */ + if (!generic_node) + return -ENXIO; + + /* If we didn't find a properly marked root partition, but we did find a single suitable + * generic Linux partition, then use this as root partition, if the caller asked for it. */ + if (multiple_generic) + return -ENOTUNIQ; + + m->partitions[PARTITION_ROOT] = (DissectedPartition) { + .found = true, + .rw = generic_rw, + .partno = generic_nr, + .architecture = _ARCHITECTURE_INVALID, + .node = TAKE_PTR(generic_node), + .uuid = generic_uuid, + }; + } + } + + if (root_hash) { + if (!m->partitions[PARTITION_ROOT_VERITY].found || !m->partitions[PARTITION_ROOT].found) + return -EADDRNOTAVAIL; + + /* If we found the primary root with the hash, then we definitely want to suppress any secondary root + * (which would be weird, after all the root hash should only be assigned to one pair of + * partitions... */ + m->partitions[PARTITION_ROOT_SECONDARY].found = false; + m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false; + + /* If we found a verity setup, then the root partition is necessarily read-only. */ + m->partitions[PARTITION_ROOT].rw = false; + + m->verity = true; + } + + blkid_free_probe(b); + b = NULL; + + /* Fill in file system types if we don't know them yet. */ + for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { + DissectedPartition *p = m->partitions + i; + + if (!p->found) + continue; + + if (!p->fstype && p->node) { + r = probe_filesystem(p->node, &p->fstype); + if (r < 0 && r != -EUCLEAN) + return r; + } + + if (streq_ptr(p->fstype, "crypto_LUKS")) + m->encrypted = true; + + if (p->fstype && fstype_is_ro(p->fstype)) + p->rw = false; + } + + *ret = TAKE_PTR(m); + + return 0; +#else + return -EOPNOTSUPP; +#endif +} + +DissectedImage* dissected_image_unref(DissectedImage *m) { + unsigned i; + + if (!m) + return NULL; + + for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { + free(m->partitions[i].fstype); + free(m->partitions[i].node); + free(m->partitions[i].decrypted_fstype); + free(m->partitions[i].decrypted_node); + } + + free(m->hostname); + strv_free(m->machine_info); + strv_free(m->os_release); + + return mfree(m); +} + +static int is_loop_device(const char *path) { + char s[SYS_BLOCK_PATH_MAX("/../loop/")]; + struct stat st; + + assert(path); + + if (stat(path, &st) < 0) + return -errno; + + if (!S_ISBLK(st.st_mode)) + return -ENOTBLK; + + xsprintf_sys_block_path(s, "/loop/", st.st_dev); + if (access(s, F_OK) < 0) { + if (errno != ENOENT) + return -errno; + + /* The device itself isn't a loop device, but maybe it's a partition and its parent is? */ + xsprintf_sys_block_path(s, "/../loop/", st.st_dev); + if (access(s, F_OK) < 0) + return errno == ENOENT ? false : -errno; + } + + return true; +} + +static int mount_partition( + DissectedPartition *m, + const char *where, + const char *directory, + uid_t uid_shift, + DissectImageFlags flags) { + + _cleanup_free_ char *chased = NULL, *options = NULL; + const char *p, *node, *fstype; + bool rw; + int r; + + assert(m); + assert(where); + + node = m->decrypted_node ?: m->node; + fstype = m->decrypted_fstype ?: m->fstype; + + if (!m->found || !node || !fstype) + return 0; + + /* Stacked encryption? Yuck */ + if (streq_ptr(fstype, "crypto_LUKS")) + return -ELOOP; + + rw = m->rw && !(flags & DISSECT_IMAGE_READ_ONLY); + + if (directory) { + r = chase_symlinks(directory, where, CHASE_PREFIX_ROOT, &chased, NULL); + if (r < 0) + return r; + + p = chased; + } else + p = where; + + /* If requested, turn on discard support. */ + if (fstype_can_discard(fstype) && + ((flags & DISSECT_IMAGE_DISCARD) || + ((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node)))) { + options = strdup("discard"); + if (!options) + return -ENOMEM; + } + + if (uid_is_valid(uid_shift) && uid_shift != 0 && fstype_can_uid_gid(fstype)) { + _cleanup_free_ char *uid_option = NULL; + + if (asprintf(&uid_option, "uid=" UID_FMT ",gid=" GID_FMT, uid_shift, (gid_t) uid_shift) < 0) + return -ENOMEM; + + if (!strextend_with_separator(&options, ",", uid_option, NULL)) + return -ENOMEM; + } + + r = mount_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options); + if (r < 0) + return r; + + return 1; +} + +int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift, DissectImageFlags flags) { + int r, boot_mounted; + + assert(m); + assert(where); + + if (!m->partitions[PARTITION_ROOT].found) + return -ENXIO; + + if ((flags & DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY) == 0) { + r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, uid_shift, flags); + if (r < 0) + return r; + + if (flags & DISSECT_IMAGE_VALIDATE_OS) { + r = path_is_os_tree(where); + if (r < 0) + return r; + if (r == 0) + return -EMEDIUMTYPE; + } + } + + if (flags & DISSECT_IMAGE_MOUNT_ROOT_ONLY) + return 0; + + r = mount_partition(m->partitions + PARTITION_HOME, where, "/home", uid_shift, flags); + if (r < 0) + return r; + + r = mount_partition(m->partitions + PARTITION_SRV, where, "/srv", uid_shift, flags); + if (r < 0) + return r; + + boot_mounted = mount_partition(m->partitions + PARTITION_XBOOTLDR, where, "/boot", uid_shift, flags); + if (boot_mounted < 0) + return boot_mounted; + + if (m->partitions[PARTITION_ESP].found) { + /* Mount the ESP to /efi if it exists. If it doesn't exist, use /boot instead, but only if it + * exists and is empty, and we didn't already mount the XBOOTLDR partition into it. */ + + r = chase_symlinks("/efi", where, CHASE_PREFIX_ROOT, NULL, NULL); + if (r >= 0) { + r = mount_partition(m->partitions + PARTITION_ESP, where, "/efi", uid_shift, flags); + if (r < 0) + return r; + + } else if (boot_mounted <= 0) { + _cleanup_free_ char *p = NULL; + + r = chase_symlinks("/boot", where, CHASE_PREFIX_ROOT, &p, NULL); + if (r >= 0 && dir_is_empty(p) > 0) { + r = mount_partition(m->partitions + PARTITION_ESP, where, "/boot", uid_shift, flags); + if (r < 0) + return r; + } + } + } + + return 0; +} + +#if HAVE_LIBCRYPTSETUP +typedef struct DecryptedPartition { + struct crypt_device *device; + char *name; + bool relinquished; +} DecryptedPartition; + +struct DecryptedImage { + DecryptedPartition *decrypted; + size_t n_decrypted; + size_t n_allocated; +}; +#endif + +DecryptedImage* decrypted_image_unref(DecryptedImage* d) { +#if HAVE_LIBCRYPTSETUP + size_t i; + int r; + + if (!d) + return NULL; + + for (i = 0; i < d->n_decrypted; i++) { + DecryptedPartition *p = d->decrypted + i; + + if (p->device && p->name && !p->relinquished) { + r = crypt_deactivate(p->device, p->name); + if (r < 0) + log_debug_errno(r, "Failed to deactivate encrypted partition %s", p->name); + } + + if (p->device) + crypt_free(p->device); + free(p->name); + } + + free(d); +#endif + return NULL; +} + +#if HAVE_LIBCRYPTSETUP + +static int make_dm_name_and_node(const void *original_node, const char *suffix, char **ret_name, char **ret_node) { + _cleanup_free_ char *name = NULL, *node = NULL; + const char *base; + + assert(original_node); + assert(suffix); + assert(ret_name); + assert(ret_node); + + base = strrchr(original_node, '/'); + if (!base) + return -EINVAL; + base++; + if (isempty(base)) + return -EINVAL; + + name = strjoin(base, suffix); + if (!name) + return -ENOMEM; + if (!filename_is_valid(name)) + return -EINVAL; + + node = path_join(crypt_get_dir(), name); + if (!node) + return -ENOMEM; + + *ret_name = TAKE_PTR(name); + *ret_node = TAKE_PTR(node); + + return 0; +} + +static int decrypt_partition( + DissectedPartition *m, + const char *passphrase, + DissectImageFlags flags, + DecryptedImage *d) { + + _cleanup_free_ char *node = NULL, *name = NULL; + _cleanup_(crypt_freep) struct crypt_device *cd = NULL; + int r; + + assert(m); + assert(d); + + if (!m->found || !m->node || !m->fstype) + return 0; + + if (!streq(m->fstype, "crypto_LUKS")) + return 0; + + if (!passphrase) + return -ENOKEY; + + r = make_dm_name_and_node(m->node, "-decrypted", &name, &node); + if (r < 0) + return r; + + if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1)) + return -ENOMEM; + + r = crypt_init(&cd, m->node); + if (r < 0) + return log_debug_errno(r, "Failed to initialize dm-crypt: %m"); + + r = crypt_load(cd, CRYPT_LUKS, NULL); + if (r < 0) + return log_debug_errno(r, "Failed to load LUKS metadata: %m"); + + r = crypt_activate_by_passphrase(cd, name, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), + ((flags & DISSECT_IMAGE_READ_ONLY) ? CRYPT_ACTIVATE_READONLY : 0) | + ((flags & DISSECT_IMAGE_DISCARD_ON_CRYPTO) ? CRYPT_ACTIVATE_ALLOW_DISCARDS : 0)); + if (r < 0) { + log_debug_errno(r, "Failed to activate LUKS device: %m"); + return r == -EPERM ? -EKEYREJECTED : r; + } + + d->decrypted[d->n_decrypted].name = TAKE_PTR(name); + d->decrypted[d->n_decrypted].device = TAKE_PTR(cd); + d->n_decrypted++; + + m->decrypted_node = TAKE_PTR(node); + + return 0; +} + +static int verity_partition( + DissectedPartition *m, + DissectedPartition *v, + const void *root_hash, + size_t root_hash_size, + DissectImageFlags flags, + DecryptedImage *d) { + + _cleanup_free_ char *node = NULL, *name = NULL; + _cleanup_(crypt_freep) struct crypt_device *cd = NULL; + int r; + + assert(m); + assert(v); + + if (!root_hash) + return 0; + + if (!m->found || !m->node || !m->fstype) + return 0; + if (!v->found || !v->node || !v->fstype) + return 0; + + if (!streq(v->fstype, "DM_verity_hash")) + return 0; + + r = make_dm_name_and_node(m->node, "-verity", &name, &node); + if (r < 0) + return r; + + if (!GREEDY_REALLOC0(d->decrypted, d->n_allocated, d->n_decrypted + 1)) + return -ENOMEM; + + r = crypt_init(&cd, v->node); + if (r < 0) + return r; + + r = crypt_load(cd, CRYPT_VERITY, NULL); + if (r < 0) + return r; + + r = crypt_set_data_device(cd, m->node); + if (r < 0) + return r; + + r = crypt_activate_by_volume_key(cd, name, root_hash, root_hash_size, CRYPT_ACTIVATE_READONLY); + if (r < 0) + return r; + + d->decrypted[d->n_decrypted].name = TAKE_PTR(name); + d->decrypted[d->n_decrypted].device = TAKE_PTR(cd); + d->n_decrypted++; + + m->decrypted_node = TAKE_PTR(node); + + return 0; +} +#endif + +int dissected_image_decrypt( + DissectedImage *m, + const char *passphrase, + const void *root_hash, + size_t root_hash_size, + DissectImageFlags flags, + DecryptedImage **ret) { + +#if HAVE_LIBCRYPTSETUP + _cleanup_(decrypted_image_unrefp) DecryptedImage *d = NULL; + unsigned i; + int r; +#endif + + assert(m); + assert(root_hash || root_hash_size == 0); + + /* Returns: + * + * = 0 → There was nothing to decrypt + * > 0 → Decrypted successfully + * -ENOKEY → There's something to decrypt but no key was supplied + * -EKEYREJECTED → Passed key was not correct + */ + + if (root_hash && root_hash_size < sizeof(sd_id128_t)) + return -EINVAL; + + if (!m->encrypted && !m->verity) { + *ret = NULL; + return 0; + } + +#if HAVE_LIBCRYPTSETUP + d = new0(DecryptedImage, 1); + if (!d) + return -ENOMEM; + + for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { + DissectedPartition *p = m->partitions + i; + int k; + + if (!p->found) + continue; + + r = decrypt_partition(p, passphrase, flags, d); + if (r < 0) + return r; + + k = PARTITION_VERITY_OF(i); + if (k >= 0) { + r = verity_partition(p, m->partitions + k, root_hash, root_hash_size, flags, d); + if (r < 0) + return r; + } + + if (!p->decrypted_fstype && p->decrypted_node) { + r = probe_filesystem(p->decrypted_node, &p->decrypted_fstype); + if (r < 0 && r != -EUCLEAN) + return r; + } + } + + *ret = TAKE_PTR(d); + + return 1; +#else + return -EOPNOTSUPP; +#endif +} + +int dissected_image_decrypt_interactively( + DissectedImage *m, + const char *passphrase, + const void *root_hash, + size_t root_hash_size, + DissectImageFlags flags, + DecryptedImage **ret) { + + _cleanup_strv_free_erase_ char **z = NULL; + int n = 3, r; + + if (passphrase) + n--; + + for (;;) { + r = dissected_image_decrypt(m, passphrase, root_hash, root_hash_size, flags, ret); + if (r >= 0) + return r; + if (r == -EKEYREJECTED) + log_error_errno(r, "Incorrect passphrase, try again!"); + else if (r != -ENOKEY) + return log_error_errno(r, "Failed to decrypt image: %m"); + + if (--n < 0) + return log_error_errno(SYNTHETIC_ERRNO(EKEYREJECTED), + "Too many retries."); + + z = strv_free(z); + + r = ask_password_auto("Please enter image passphrase:", NULL, "dissect", "dissect", USEC_INFINITY, 0, &z); + if (r < 0) + return log_error_errno(r, "Failed to query for passphrase: %m"); + + passphrase = z[0]; + } +} + +int decrypted_image_relinquish(DecryptedImage *d) { + +#if HAVE_LIBCRYPTSETUP + size_t i; + int r; +#endif + + assert(d); + + /* Turns on automatic removal after the last use ended for all DM devices of this image, and sets a boolean so + * that we don't clean it up ourselves either anymore */ + +#if HAVE_LIBCRYPTSETUP + for (i = 0; i < d->n_decrypted; i++) { + DecryptedPartition *p = d->decrypted + i; + + if (p->relinquished) + continue; + + r = dm_deferred_remove(p->name); + if (r < 0) + return log_debug_errno(r, "Failed to mark %s for auto-removal: %m", p->name); + + p->relinquished = true; + } +#endif + + return 0; +} + +int root_hash_load(const char *image, void **ret, size_t *ret_size) { + _cleanup_free_ char *text = NULL; + _cleanup_free_ void *k = NULL; + size_t l; + int r; + + assert(image); + assert(ret); + assert(ret_size); + + if (is_device_path(image)) { + /* If we are asked to load the root hash for a device node, exit early */ + *ret = NULL; + *ret_size = 0; + return 0; + } + + r = getxattr_malloc(image, "user.verity.roothash", &text, true); + if (r < 0) { + char *fn, *e, *n; + + if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT)) + return r; + + fn = newa(char, strlen(image) + STRLEN(".roothash") + 1); + n = stpcpy(fn, image); + e = endswith(fn, ".raw"); + if (e) + n = e; + + strcpy(n, ".roothash"); + + r = read_one_line_file(fn, &text); + if (r == -ENOENT) { + *ret = NULL; + *ret_size = 0; + return 0; + } + if (r < 0) + return r; + } + + r = unhexmem(text, strlen(text), &k, &l); + if (r < 0) + return r; + if (l < sizeof(sd_id128_t)) + return -EINVAL; + + *ret = TAKE_PTR(k); + *ret_size = l; + + return 1; +} + +int dissected_image_acquire_metadata(DissectedImage *m) { + + enum { + META_HOSTNAME, + META_MACHINE_ID, + META_MACHINE_INFO, + META_OS_RELEASE, + _META_MAX, + }; + + static const char *const paths[_META_MAX] = { + [META_HOSTNAME] = "/etc/hostname\0", + [META_MACHINE_ID] = "/etc/machine-id\0", + [META_MACHINE_INFO] = "/etc/machine-info\0", + [META_OS_RELEASE] = "/etc/os-release\0/usr/lib/os-release\0", + }; + + _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL; + _cleanup_(rmdir_and_freep) char *t = NULL; + _cleanup_(sigkill_waitp) pid_t child = 0; + sd_id128_t machine_id = SD_ID128_NULL; + _cleanup_free_ char *hostname = NULL; + unsigned n_meta_initialized = 0, k; + int fds[2 * _META_MAX], r; + + BLOCK_SIGNALS(SIGCHLD); + + assert(m); + + for (; n_meta_initialized < _META_MAX; n_meta_initialized ++) + if (pipe2(fds + 2*n_meta_initialized, O_CLOEXEC) < 0) { + r = -errno; + goto finish; + } + + r = mkdtemp_malloc("/tmp/dissect-XXXXXX", &t); + if (r < 0) + goto finish; + + r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &child); + if (r < 0) + goto finish; + if (r == 0) { + r = dissected_image_mount(m, t, UID_INVALID, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_VALIDATE_OS); + if (r < 0) { + log_debug_errno(r, "Failed to mount dissected image: %m"); + _exit(EXIT_FAILURE); + } + + for (k = 0; k < _META_MAX; k++) { + _cleanup_close_ int fd = -1; + const char *p; + + fds[2*k] = safe_close(fds[2*k]); + + NULSTR_FOREACH(p, paths[k]) { + fd = chase_symlinks_and_open(p, t, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL); + if (fd >= 0) + break; + } + if (fd < 0) { + log_debug_errno(fd, "Failed to read %s file of image, ignoring: %m", paths[k]); + continue; + } + + r = copy_bytes(fd, fds[2*k+1], (uint64_t) -1, 0); + if (r < 0) + _exit(EXIT_FAILURE); + + fds[2*k+1] = safe_close(fds[2*k+1]); + } + + _exit(EXIT_SUCCESS); + } + + for (k = 0; k < _META_MAX; k++) { + _cleanup_fclose_ FILE *f = NULL; + + fds[2*k+1] = safe_close(fds[2*k+1]); + + f = fdopen(fds[2*k], "r"); + if (!f) { + r = -errno; + goto finish; + } + + fds[2*k] = -1; + + switch (k) { + + case META_HOSTNAME: + r = read_etc_hostname_stream(f, &hostname); + if (r < 0) + log_debug_errno(r, "Failed to read /etc/hostname: %m"); + + break; + + case META_MACHINE_ID: { + _cleanup_free_ char *line = NULL; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + log_debug_errno(r, "Failed to read /etc/machine-id: %m"); + else if (r == 33) { + r = sd_id128_from_string(line, &machine_id); + if (r < 0) + log_debug_errno(r, "Image contains invalid /etc/machine-id: %s", line); + } else if (r == 0) + log_debug("/etc/machine-id file is empty."); + else + log_debug("/etc/machine-id has unexpected length %i.", r); + + break; + } + + case META_MACHINE_INFO: + r = load_env_file_pairs(f, "machine-info", &machine_info); + if (r < 0) + log_debug_errno(r, "Failed to read /etc/machine-info: %m"); + + break; + + case META_OS_RELEASE: + r = load_env_file_pairs(f, "os-release", &os_release); + if (r < 0) + log_debug_errno(r, "Failed to read OS release file: %m"); + + break; + } + } + + r = wait_for_terminate_and_check("(sd-dissect)", child, 0); + child = 0; + if (r < 0) + goto finish; + if (r != EXIT_SUCCESS) + return -EPROTO; + + free_and_replace(m->hostname, hostname); + m->machine_id = machine_id; + strv_free_and_replace(m->machine_info, machine_info); + strv_free_and_replace(m->os_release, os_release); + +finish: + for (k = 0; k < n_meta_initialized; k++) + safe_close_pair(fds + 2*k); + + return r; +} + +int dissect_image_and_warn( + int fd, + const char *name, + const void *root_hash, + size_t root_hash_size, + DissectImageFlags flags, + DissectedImage **ret) { + + _cleanup_free_ char *buffer = NULL; + int r; + + if (!name) { + r = fd_get_path(fd, &buffer); + if (r < 0) + return r; + + name = buffer; + } + + r = dissect_image(fd, root_hash, root_hash_size, flags, ret); + + switch (r) { + + case -EOPNOTSUPP: + return log_error_errno(r, "Dissecting images is not supported, compiled without blkid support."); + + case -ENOPKG: + return log_error_errno(r, "Couldn't identify a suitable partition table or file system in '%s'.", name); + + case -EADDRNOTAVAIL: + return log_error_errno(r, "No root partition for specified root hash found in '%s'.", name); + + case -ENOTUNIQ: + return log_error_errno(r, "Multiple suitable root partitions found in image '%s'.", name); + + case -ENXIO: + return log_error_errno(r, "No suitable root partition found in image '%s'.", name); + + case -EPROTONOSUPPORT: + return log_error_errno(r, "Device '%s' is loopback block device with partition scanning turned off, please turn it on.", name); + + default: + if (r < 0) + return log_error_errno(r, "Failed to dissect image '%s': %m", name); + + return r; + } +} + +static const char *const partition_designator_table[] = { + [PARTITION_ROOT] = "root", + [PARTITION_ROOT_SECONDARY] = "root-secondary", + [PARTITION_HOME] = "home", + [PARTITION_SRV] = "srv", + [PARTITION_ESP] = "esp", + [PARTITION_XBOOTLDR] = "xbootldr", + [PARTITION_SWAP] = "swap", + [PARTITION_ROOT_VERITY] = "root-verity", + [PARTITION_ROOT_SECONDARY_VERITY] = "root-secondary-verity", +}; + +DEFINE_STRING_TABLE_LOOKUP(partition_designator, int); diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h new file mode 100644 index 00000000..40b8035a --- /dev/null +++ b/src/shared/dissect-image.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-id128.h" + +#include "macro.h" + +typedef struct DissectedImage DissectedImage; +typedef struct DissectedPartition DissectedPartition; +typedef struct DecryptedImage DecryptedImage; + +struct DissectedPartition { + bool found:1; + bool rw:1; + int partno; /* -1 if there was no partition and the images contains a file system directly */ + int architecture; /* Intended architecture: either native, secondary or unset (-1). */ + sd_id128_t uuid; /* Partition entry UUID as reported by the GPT */ + char *fstype; + char *node; + char *decrypted_node; + char *decrypted_fstype; +}; + +enum { + PARTITION_ROOT, + PARTITION_ROOT_SECONDARY, /* Secondary architecture */ + PARTITION_HOME, + PARTITION_SRV, + PARTITION_ESP, + PARTITION_XBOOTLDR, + PARTITION_SWAP, + PARTITION_ROOT_VERITY, /* verity data for the PARTITION_ROOT partition */ + PARTITION_ROOT_SECONDARY_VERITY, /* verity data for the PARTITION_ROOT_SECONDARY partition */ + _PARTITION_DESIGNATOR_MAX, + _PARTITION_DESIGNATOR_INVALID = -1 +}; + +static inline int PARTITION_VERITY_OF(int p) { + if (p == PARTITION_ROOT) + return PARTITION_ROOT_VERITY; + if (p == PARTITION_ROOT_SECONDARY) + return PARTITION_ROOT_SECONDARY_VERITY; + return _PARTITION_DESIGNATOR_INVALID; +} + +typedef enum DissectImageFlags { + DISSECT_IMAGE_READ_ONLY = 1 << 0, + DISSECT_IMAGE_DISCARD_ON_LOOP = 1 << 1, /* Turn on "discard" if on a loop device and file system supports it */ + DISSECT_IMAGE_DISCARD = 1 << 2, /* Turn on "discard" if file system supports it, on all block devices */ + DISSECT_IMAGE_DISCARD_ON_CRYPTO = 1 << 3, /* Turn on "discard" also on crypto devices */ + DISSECT_IMAGE_DISCARD_ANY = DISSECT_IMAGE_DISCARD_ON_LOOP | + DISSECT_IMAGE_DISCARD | + DISSECT_IMAGE_DISCARD_ON_CRYPTO, + DISSECT_IMAGE_GPT_ONLY = 1 << 4, /* Only recognize images with GPT partition tables */ + DISSECT_IMAGE_REQUIRE_ROOT = 1 << 5, /* Don't accept disks without root partition */ + DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root partition */ + DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only non-root partitions */ + DISSECT_IMAGE_VALIDATE_OS = 1 << 8, /* Refuse mounting images that aren't identifiable as OS images */ + DISSECT_IMAGE_NO_UDEV = 1 << 9, /* Don't wait for udev initializing things */ +} DissectImageFlags; + +struct DissectedImage { + bool encrypted:1; + bool verity:1; /* verity available and usable */ + bool can_verity:1; /* verity available, but not necessarily used */ + + DissectedPartition partitions[_PARTITION_DESIGNATOR_MAX]; + + char *hostname; + sd_id128_t machine_id; + char **machine_info; + char **os_release; +}; + +int probe_filesystem(const char *node, char **ret_fstype); +int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret); +int dissect_image_and_warn(int fd, const char *name, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret); + +DissectedImage* dissected_image_unref(DissectedImage *m); +DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref); + +int dissected_image_decrypt(DissectedImage *m, const char *passphrase, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DecryptedImage **ret); +int dissected_image_decrypt_interactively(DissectedImage *m, const char *passphrase, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DecryptedImage **ret); +int dissected_image_mount(DissectedImage *m, const char *dest, uid_t uid_shift, DissectImageFlags flags); + +int dissected_image_acquire_metadata(DissectedImage *m); + +DecryptedImage* decrypted_image_unref(DecryptedImage *p); +DEFINE_TRIVIAL_CLEANUP_FUNC(DecryptedImage*, decrypted_image_unref); +int decrypted_image_relinquish(DecryptedImage *d); + +const char* partition_designator_to_string(int i) _const_; +int partition_designator_from_string(const char *name) _pure_; + +int root_hash_load(const char *image, void **ret, size_t *ret_size); diff --git a/src/shared/dm-util.c b/src/shared/dm-util.c new file mode 100644 index 00000000..d817e5b0 --- /dev/null +++ b/src/shared/dm-util.c @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "dm-util.h" +#include "fd-util.h" +#include "string-util.h" + +int dm_deferred_remove(const char *name) { + + struct dm_ioctl dm = { + .version = { + DM_VERSION_MAJOR, + DM_VERSION_MINOR, + DM_VERSION_PATCHLEVEL + }, + .data_size = sizeof(dm), + .flags = DM_DEFERRED_REMOVE, + }; + + _cleanup_close_ int fd = -1; + + assert(name); + + /* Unfortunately, libcryptsetup doesn't provide a proper API for this, hence call the ioctl() + * directly. */ + + if (strlen(name) >= sizeof(dm.name)) + return -ENODEV; /* A device with a name longer than this cannot possibly exist */ + + fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC); + if (fd < 0) + return -errno; + + strncpy_exact(dm.name, name, sizeof(dm.name)); + + if (ioctl(fd, DM_DEV_REMOVE, &dm)) + return -errno; + + return 0; +} diff --git a/src/shared/dm-util.h b/src/shared/dm-util.h new file mode 100644 index 00000000..6c78bfe7 --- /dev/null +++ b/src/shared/dm-util.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int dm_deferred_remove(const char *name); diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c new file mode 100644 index 00000000..b8126653 --- /dev/null +++ b/src/shared/dns-domain.c @@ -0,0 +1,1374 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#if HAVE_LIBIDN2 +# include +#elif HAVE_LIBIDN +# include +# include +#endif + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dns-domain.h" +#include "hashmap.h" +#include "hexdecoct.h" +#include "hostname-util.h" +#include "in-addr-util.h" +#include "macro.h" +#include "parse-util.h" +#include "string-util.h" +#include "strv.h" +#include "utf8.h" + +int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags flags) { + const char *n; + char *d, last_char = 0; + int r = 0; + + assert(name); + assert(*name); + + n = *name; + d = dest; + + for (;;) { + if (IN_SET(*n, 0, '.')) { + if (FLAGS_SET(flags, DNS_LABEL_LDH) && last_char == '-') + /* Trailing dash */ + return -EINVAL; + + if (*n == '.') + n++; + break; + } + + if (r >= DNS_LABEL_MAX) + return -EINVAL; + + if (sz <= 0) + return -ENOBUFS; + + if (*n == '\\') { + /* Escaped character */ + if (FLAGS_SET(flags, DNS_LABEL_NO_ESCAPES)) + return -EINVAL; + + n++; + + if (*n == 0) + /* Ending NUL */ + return -EINVAL; + + else if (IN_SET(*n, '\\', '.')) { + /* Escaped backslash or dot */ + + if (FLAGS_SET(flags, DNS_LABEL_LDH)) + return -EINVAL; + + last_char = *n; + if (d) + *(d++) = *n; + sz--; + r++; + n++; + + } else if (n[0] >= '0' && n[0] <= '9') { + unsigned k; + + /* Escaped literal ASCII character */ + + if (!(n[1] >= '0' && n[1] <= '9') || + !(n[2] >= '0' && n[2] <= '9')) + return -EINVAL; + + k = ((unsigned) (n[0] - '0') * 100) + + ((unsigned) (n[1] - '0') * 10) + + ((unsigned) (n[2] - '0')); + + /* Don't allow anything that doesn't + * fit in 8bit. Note that we do allow + * control characters, as some servers + * (e.g. cloudflare) are happy to + * generate labels with them + * inside. */ + if (k > 255) + return -EINVAL; + + if (FLAGS_SET(flags, DNS_LABEL_LDH) && + !valid_ldh_char((char) k)) + return -EINVAL; + + last_char = (char) k; + if (d) + *(d++) = (char) k; + sz--; + r++; + + n += 3; + } else + return -EINVAL; + + } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) { + + /* Normal character */ + + if (FLAGS_SET(flags, DNS_LABEL_LDH)) { + if (!valid_ldh_char(*n)) + return -EINVAL; + if (r == 0 && *n == '-') + /* Leading dash */ + return -EINVAL; + } + + last_char = *n; + if (d) + *(d++) = *n; + sz--; + r++; + n++; + } else + return -EINVAL; + } + + /* Empty label that is not at the end? */ + if (r == 0 && *n) + return -EINVAL; + + /* More than one trailing dot? */ + if (*n == '.') + return -EINVAL; + + if (sz >= 1 && d) + *d = 0; + + *name = n; + return r; +} + +/* @label_terminal: terminal character of a label, updated to point to the terminal character of + * the previous label (always skipping one dot) or to NULL if there are no more + * labels. */ +int dns_label_unescape_suffix(const char *name, const char **label_terminal, char *dest, size_t sz) { + const char *terminal; + int r; + + assert(name); + assert(label_terminal); + assert(dest); + + /* no more labels */ + if (!*label_terminal) { + if (sz >= 1) + *dest = 0; + + return 0; + } + + terminal = *label_terminal; + assert(IN_SET(*terminal, 0, '.')); + + /* Skip current terminal character (and accept domain names ending it ".") */ + if (*terminal == 0) + terminal--; + if (terminal >= name && *terminal == '.') + terminal--; + + /* Point name to the last label, and terminal to the preceding terminal symbol (or make it a NULL pointer) */ + for (;;) { + if (terminal < name) { + /* Reached the first label, so indicate that there are no more */ + terminal = NULL; + break; + } + + /* Find the start of the last label */ + if (*terminal == '.') { + const char *y; + unsigned slashes = 0; + + for (y = terminal - 1; y >= name && *y == '\\'; y--) + slashes++; + + if (slashes % 2 == 0) { + /* The '.' was not escaped */ + name = terminal + 1; + break; + } else { + terminal = y; + continue; + } + } + + terminal--; + } + + r = dns_label_unescape(&name, dest, sz, 0); + if (r < 0) + return r; + + *label_terminal = terminal; + + return r; +} + +int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) { + char *q; + + /* DNS labels must be between 1 and 63 characters long. A + * zero-length label does not exist. See RFC 2182, Section + * 11. */ + + if (l <= 0 || l > DNS_LABEL_MAX) + return -EINVAL; + if (sz < 1) + return -ENOBUFS; + + assert(p); + assert(dest); + + q = dest; + while (l > 0) { + + if (IN_SET(*p, '.', '\\')) { + + /* Dot or backslash */ + + if (sz < 3) + return -ENOBUFS; + + *(q++) = '\\'; + *(q++) = *p; + + sz -= 2; + + } else if (IN_SET(*p, '_', '-') || + (*p >= '0' && *p <= '9') || + (*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z')) { + + /* Proper character */ + + if (sz < 2) + return -ENOBUFS; + + *(q++) = *p; + sz -= 1; + + } else { + + /* Everything else */ + + if (sz < 5) + return -ENOBUFS; + + *(q++) = '\\'; + *(q++) = '0' + (char) ((uint8_t) *p / 100); + *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10); + *(q++) = '0' + (char) ((uint8_t) *p % 10); + + sz -= 4; + } + + p++; + l--; + } + + *q = 0; + return (int) (q - dest); +} + +int dns_label_escape_new(const char *p, size_t l, char **ret) { + _cleanup_free_ char *s = NULL; + int r; + + assert(p); + assert(ret); + + if (l <= 0 || l > DNS_LABEL_MAX) + return -EINVAL; + + s = new(char, DNS_LABEL_ESCAPED_MAX); + if (!s) + return -ENOMEM; + + r = dns_label_escape(p, l, s, DNS_LABEL_ESCAPED_MAX); + if (r < 0) + return r; + + *ret = TAKE_PTR(s); + + return r; +} + +#if HAVE_LIBIDN +int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) { + _cleanup_free_ uint32_t *input = NULL; + size_t input_size, l; + const char *p; + bool contains_8bit = false; + char buffer[DNS_LABEL_MAX+1]; + + assert(encoded); + assert(decoded); + + /* Converts an U-label into an A-label */ + + if (encoded_size <= 0) + return -EINVAL; + + for (p = encoded; p < encoded + encoded_size; p++) + if ((uint8_t) *p > 127) + contains_8bit = true; + + if (!contains_8bit) { + if (encoded_size > DNS_LABEL_MAX) + return -EINVAL; + + return 0; + } + + input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size); + if (!input) + return -ENOMEM; + + if (idna_to_ascii_4i(input, input_size, buffer, 0) != 0) + return -EINVAL; + + l = strlen(buffer); + + /* Verify that the result is not longer than one DNS label. */ + if (l <= 0 || l > DNS_LABEL_MAX) + return -EINVAL; + if (l > decoded_max) + return -ENOBUFS; + + memcpy(decoded, buffer, l); + + /* If there's room, append a trailing NUL byte, but only then */ + if (decoded_max > l) + decoded[l] = 0; + + return (int) l; +} + +int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) { + size_t input_size, output_size; + _cleanup_free_ uint32_t *input = NULL; + _cleanup_free_ char *result = NULL; + uint32_t *output = NULL; + size_t w; + + /* To be invoked after unescaping. Converts an A-label into an U-label. */ + + assert(encoded); + assert(decoded); + + if (encoded_size <= 0 || encoded_size > DNS_LABEL_MAX) + return -EINVAL; + + if (!memory_startswith(encoded, encoded_size, IDNA_ACE_PREFIX)) + return 0; + + input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size); + if (!input) + return -ENOMEM; + + output_size = input_size; + output = newa(uint32_t, output_size); + + idna_to_unicode_44i(input, input_size, output, &output_size, 0); + + result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w); + if (!result) + return -ENOMEM; + if (w <= 0) + return -EINVAL; + if (w > decoded_max) + return -ENOBUFS; + + memcpy(decoded, result, w); + + /* Append trailing NUL byte if there's space, but only then. */ + if (decoded_max > w) + decoded[w] = 0; + + return w; +} +#endif + +int dns_name_concat(const char *a, const char *b, DNSLabelFlags flags, char **_ret) { + _cleanup_free_ char *ret = NULL; + size_t n = 0, allocated = 0; + const char *p; + bool first = true; + int r; + + if (a) + p = a; + else if (b) + p = TAKE_PTR(b); + else + goto finish; + + for (;;) { + char label[DNS_LABEL_MAX]; + + r = dns_label_unescape(&p, label, sizeof label, flags); + if (r < 0) + return r; + if (r == 0) { + if (*p != 0) + return -EINVAL; + + if (b) { + /* Now continue with the second string, if there is one */ + p = TAKE_PTR(b); + continue; + } + + break; + } + + if (_ret) { + if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) + return -ENOMEM; + + r = dns_label_escape(label, r, ret + n + !first, DNS_LABEL_ESCAPED_MAX); + if (r < 0) + return r; + + if (!first) + ret[n] = '.'; + } else { + char escaped[DNS_LABEL_ESCAPED_MAX]; + + r = dns_label_escape(label, r, escaped, sizeof(escaped)); + if (r < 0) + return r; + } + + if (!first) + n++; + else + first = false; + + n += r; + } + +finish: + if (n > DNS_HOSTNAME_MAX) + return -EINVAL; + + if (_ret) { + if (n == 0) { + /* Nothing appended? If so, generate at least a single dot, to indicate the DNS root domain */ + if (!GREEDY_REALLOC(ret, allocated, 2)) + return -ENOMEM; + + ret[n++] = '.'; + } else { + if (!GREEDY_REALLOC(ret, allocated, n + 1)) + return -ENOMEM; + } + + ret[n] = 0; + *_ret = TAKE_PTR(ret); + } + + return 0; +} + +void dns_name_hash_func(const char *p, struct siphash *state) { + int r; + + assert(p); + + for (;;) { + char label[DNS_LABEL_MAX+1]; + + r = dns_label_unescape(&p, label, sizeof label, 0); + if (r < 0) + break; + if (r == 0) + break; + + ascii_strlower_n(label, r); + siphash24_compress(label, r, state); + siphash24_compress_byte(0, state); /* make sure foobar and foo.bar result in different hashes */ + } + + /* enforce that all names are terminated by the empty label */ + string_hash_func("", state); +} + +int dns_name_compare_func(const char *a, const char *b) { + const char *x, *y; + int r, q; + + assert(a); + assert(b); + + x = a + strlen(a); + y = b + strlen(b); + + for (;;) { + char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX]; + + if (x == NULL && y == NULL) + return 0; + + r = dns_label_unescape_suffix(a, &x, la, sizeof(la)); + q = dns_label_unescape_suffix(b, &y, lb, sizeof(lb)); + if (r < 0 || q < 0) + return CMP(r, q); + + r = ascii_strcasecmp_nn(la, r, lb, q); + if (r != 0) + return r; + } +} + +DEFINE_HASH_OPS(dns_name_hash_ops, char, dns_name_hash_func, dns_name_compare_func); + +int dns_name_equal(const char *x, const char *y) { + int r, q; + + assert(x); + assert(y); + + for (;;) { + char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX]; + + r = dns_label_unescape(&x, la, sizeof la, 0); + if (r < 0) + return r; + + q = dns_label_unescape(&y, lb, sizeof lb, 0); + if (q < 0) + return q; + + if (r != q) + return false; + if (r == 0) + return true; + + if (ascii_strcasecmp_n(la, lb, r) != 0) + return false; + } +} + +int dns_name_endswith(const char *name, const char *suffix) { + const char *n, *s, *saved_n = NULL; + int r, q; + + assert(name); + assert(suffix); + + n = name; + s = suffix; + + for (;;) { + char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX]; + + r = dns_label_unescape(&n, ln, sizeof ln, 0); + if (r < 0) + return r; + + if (!saved_n) + saved_n = n; + + q = dns_label_unescape(&s, ls, sizeof ls, 0); + if (q < 0) + return q; + + if (r == 0 && q == 0) + return true; + if (r == 0 && saved_n == n) + return false; + + if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) { + + /* Not the same, let's jump back, and try with the next label again */ + s = suffix; + n = TAKE_PTR(saved_n); + } + } +} + +int dns_name_startswith(const char *name, const char *prefix) { + const char *n, *p; + int r, q; + + assert(name); + assert(prefix); + + n = name; + p = prefix; + + for (;;) { + char ln[DNS_LABEL_MAX], lp[DNS_LABEL_MAX]; + + r = dns_label_unescape(&p, lp, sizeof lp, 0); + if (r < 0) + return r; + if (r == 0) + return true; + + q = dns_label_unescape(&n, ln, sizeof ln, 0); + if (q < 0) + return q; + + if (r != q) + return false; + if (ascii_strcasecmp_n(ln, lp, r) != 0) + return false; + } +} + +int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret) { + const char *n, *s, *saved_before = NULL, *saved_after = NULL, *prefix; + int r, q; + + assert(name); + assert(old_suffix); + assert(new_suffix); + assert(ret); + + n = name; + s = old_suffix; + + for (;;) { + char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX]; + + if (!saved_before) + saved_before = n; + + r = dns_label_unescape(&n, ln, sizeof ln, 0); + if (r < 0) + return r; + + if (!saved_after) + saved_after = n; + + q = dns_label_unescape(&s, ls, sizeof ls, 0); + if (q < 0) + return q; + + if (r == 0 && q == 0) + break; + if (r == 0 && saved_after == n) { + *ret = NULL; /* doesn't match */ + return 0; + } + + if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) { + + /* Not the same, let's jump back, and try with the next label again */ + s = old_suffix; + n = TAKE_PTR(saved_after); + saved_before = NULL; + } + } + + /* Found it! Now generate the new name */ + prefix = strndupa(name, saved_before - name); + + r = dns_name_concat(prefix, new_suffix, 0, ret); + if (r < 0) + return r; + + return 1; +} + +int dns_name_between(const char *a, const char *b, const char *c) { + /* Determine if b is strictly greater than a and strictly smaller than c. + We consider the order of names to be circular, so that if a is + strictly greater than c, we consider b to be between them if it is + either greater than a or smaller than c. This is how the canonical + DNS name order used in NSEC records work. */ + + if (dns_name_compare_func(a, c) < 0) + /* + a and c are properly ordered: + a<---b--->c + */ + return dns_name_compare_func(a, b) < 0 && + dns_name_compare_func(b, c) < 0; + else + /* + a and c are equal or 'reversed': + <--b--c a-----> + or: + <-----c a--b--> + */ + return dns_name_compare_func(b, c) < 0 || + dns_name_compare_func(a, b) < 0; +} + +int dns_name_reverse(int family, const union in_addr_union *a, char **ret) { + const uint8_t *p; + int r; + + assert(a); + assert(ret); + + p = (const uint8_t*) a; + + if (family == AF_INET) + r = asprintf(ret, "%u.%u.%u.%u.in-addr.arpa", p[3], p[2], p[1], p[0]); + else if (family == AF_INET6) + r = asprintf(ret, "%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.ip6.arpa", + hexchar(p[15] & 0xF), hexchar(p[15] >> 4), hexchar(p[14] & 0xF), hexchar(p[14] >> 4), + hexchar(p[13] & 0xF), hexchar(p[13] >> 4), hexchar(p[12] & 0xF), hexchar(p[12] >> 4), + hexchar(p[11] & 0xF), hexchar(p[11] >> 4), hexchar(p[10] & 0xF), hexchar(p[10] >> 4), + hexchar(p[ 9] & 0xF), hexchar(p[ 9] >> 4), hexchar(p[ 8] & 0xF), hexchar(p[ 8] >> 4), + hexchar(p[ 7] & 0xF), hexchar(p[ 7] >> 4), hexchar(p[ 6] & 0xF), hexchar(p[ 6] >> 4), + hexchar(p[ 5] & 0xF), hexchar(p[ 5] >> 4), hexchar(p[ 4] & 0xF), hexchar(p[ 4] >> 4), + hexchar(p[ 3] & 0xF), hexchar(p[ 3] >> 4), hexchar(p[ 2] & 0xF), hexchar(p[ 2] >> 4), + hexchar(p[ 1] & 0xF), hexchar(p[ 1] >> 4), hexchar(p[ 0] & 0xF), hexchar(p[ 0] >> 4)); + else + return -EAFNOSUPPORT; + if (r < 0) + return -ENOMEM; + + return 0; +} + +int dns_name_address(const char *p, int *family, union in_addr_union *address) { + int r; + + assert(p); + assert(family); + assert(address); + + r = dns_name_endswith(p, "in-addr.arpa"); + if (r < 0) + return r; + if (r > 0) { + uint8_t a[4]; + unsigned i; + + for (i = 0; i < ELEMENTSOF(a); i++) { + char label[DNS_LABEL_MAX+1]; + + r = dns_label_unescape(&p, label, sizeof label, 0); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + if (r > 3) + return -EINVAL; + + r = safe_atou8(label, &a[i]); + if (r < 0) + return r; + } + + r = dns_name_equal(p, "in-addr.arpa"); + if (r <= 0) + return r; + + *family = AF_INET; + address->in.s_addr = htobe32(((uint32_t) a[3] << 24) | + ((uint32_t) a[2] << 16) | + ((uint32_t) a[1] << 8) | + (uint32_t) a[0]); + + return 1; + } + + r = dns_name_endswith(p, "ip6.arpa"); + if (r < 0) + return r; + if (r > 0) { + struct in6_addr a; + unsigned i; + + for (i = 0; i < ELEMENTSOF(a.s6_addr); i++) { + char label[DNS_LABEL_MAX+1]; + int x, y; + + r = dns_label_unescape(&p, label, sizeof label, 0); + if (r <= 0) + return r; + if (r != 1) + return -EINVAL; + x = unhexchar(label[0]); + if (x < 0) + return -EINVAL; + + r = dns_label_unescape(&p, label, sizeof label, 0); + if (r <= 0) + return r; + if (r != 1) + return -EINVAL; + y = unhexchar(label[0]); + if (y < 0) + return -EINVAL; + + a.s6_addr[ELEMENTSOF(a.s6_addr) - i - 1] = (uint8_t) y << 4 | (uint8_t) x; + } + + r = dns_name_equal(p, "ip6.arpa"); + if (r <= 0) + return r; + + *family = AF_INET6; + address->in6 = a; + return 1; + } + + return 0; +} + +bool dns_name_is_root(const char *name) { + + assert(name); + + /* There are exactly two ways to encode the root domain name: + * as empty string, or with a single dot. */ + + return STR_IN_SET(name, "", "."); +} + +bool dns_name_is_single_label(const char *name) { + int r; + + assert(name); + + r = dns_name_parent(&name); + if (r <= 0) + return false; + + return dns_name_is_root(name); +} + +/* Encode a domain name according to RFC 1035 Section 3.1, without compression */ +int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, bool canonical) { + uint8_t *label_length, *out; + int r; + + assert(domain); + assert(buffer); + + out = buffer; + + do { + /* Reserve a byte for label length */ + if (len <= 0) + return -ENOBUFS; + len--; + label_length = out; + out++; + + /* Convert and copy a single label. Note that + * dns_label_unescape() returns 0 when it hits the end + * of the domain name, which we rely on here to encode + * the trailing NUL byte. */ + r = dns_label_unescape(&domain, (char *) out, len, 0); + if (r < 0) + return r; + + /* Optionally, output the name in DNSSEC canonical + * format, as described in RFC 4034, section 6.2. Or + * in other words: in lower-case. */ + if (canonical) + ascii_strlower_n((char*) out, (size_t) r); + + /* Fill label length, move forward */ + *label_length = r; + out += r; + len -= r; + + } while (r != 0); + + /* Verify the maximum size of the encoded name. The trailing + * dot + NUL byte account are included this time, hence + * compare against DNS_HOSTNAME_MAX + 2 (which is 255) this + * time. */ + if (out - buffer > DNS_HOSTNAME_MAX + 2) + return -EINVAL; + + return out - buffer; +} + +static bool srv_type_label_is_valid(const char *label, size_t n) { + size_t k; + + assert(label); + + if (n < 2) /* Label needs to be at least 2 chars long */ + return false; + + if (label[0] != '_') /* First label char needs to be underscore */ + return false; + + /* Second char must be a letter */ + if (!(label[1] >= 'A' && label[1] <= 'Z') && + !(label[1] >= 'a' && label[1] <= 'z')) + return false; + + /* Third and further chars must be alphanumeric or a hyphen */ + for (k = 2; k < n; k++) { + if (!(label[k] >= 'A' && label[k] <= 'Z') && + !(label[k] >= 'a' && label[k] <= 'z') && + !(label[k] >= '0' && label[k] <= '9') && + label[k] != '-') + return false; + } + + return true; +} + +bool dns_srv_type_is_valid(const char *name) { + unsigned c = 0; + int r; + + if (!name) + return false; + + for (;;) { + char label[DNS_LABEL_MAX]; + + /* This more or less implements RFC 6335, Section 5.1 */ + + r = dns_label_unescape(&name, label, sizeof label, 0); + if (r < 0) + return false; + if (r == 0) + break; + + if (c >= 2) + return false; + + if (!srv_type_label_is_valid(label, r)) + return false; + + c++; + } + + return c == 2; /* exactly two labels */ +} + +bool dnssd_srv_type_is_valid(const char *name) { + return dns_srv_type_is_valid(name) && + ((dns_name_endswith(name, "_tcp") > 0) || + (dns_name_endswith(name, "_udp") > 0)); /* Specific to DNS-SD. RFC 6763, Section 7 */ +} + +bool dns_service_name_is_valid(const char *name) { + size_t l; + + /* This more or less implements RFC 6763, Section 4.1.1 */ + + if (!name) + return false; + + if (!utf8_is_valid(name)) + return false; + + if (string_has_cc(name, NULL)) + return false; + + l = strlen(name); + if (l <= 0) + return false; + if (l > 63) + return false; + + return true; +} + +int dns_service_join(const char *name, const char *type, const char *domain, char **ret) { + char escaped[DNS_LABEL_ESCAPED_MAX]; + _cleanup_free_ char *n = NULL; + int r; + + assert(type); + assert(domain); + assert(ret); + + if (!dns_srv_type_is_valid(type)) + return -EINVAL; + + if (!name) + return dns_name_concat(type, domain, 0, ret); + + if (!dns_service_name_is_valid(name)) + return -EINVAL; + + r = dns_label_escape(name, strlen(name), escaped, sizeof(escaped)); + if (r < 0) + return r; + + r = dns_name_concat(type, domain, 0, &n); + if (r < 0) + return r; + + return dns_name_concat(escaped, n, 0, ret); +} + +static bool dns_service_name_label_is_valid(const char *label, size_t n) { + char *s; + + assert(label); + + if (memchr(label, 0, n)) + return false; + + s = strndupa(label, n); + return dns_service_name_is_valid(s); +} + +int dns_service_split(const char *joined, char **_name, char **_type, char **_domain) { + _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL; + const char *p = joined, *q = NULL, *d = NULL; + char a[DNS_LABEL_MAX], b[DNS_LABEL_MAX], c[DNS_LABEL_MAX]; + int an, bn, cn, r; + unsigned x = 0; + + assert(joined); + + /* Get first label from the full name */ + an = dns_label_unescape(&p, a, sizeof(a), 0); + if (an < 0) + return an; + + if (an > 0) { + x++; + + /* If there was a first label, try to get the second one */ + bn = dns_label_unescape(&p, b, sizeof(b), 0); + if (bn < 0) + return bn; + + if (bn > 0) { + x++; + + /* If there was a second label, try to get the third one */ + q = p; + cn = dns_label_unescape(&p, c, sizeof(c), 0); + if (cn < 0) + return cn; + + if (cn > 0) + x++; + } else + cn = 0; + } else + an = 0; + + if (x >= 2 && srv_type_label_is_valid(b, bn)) { + + if (x >= 3 && srv_type_label_is_valid(c, cn)) { + + if (dns_service_name_label_is_valid(a, an)) { + /* OK, got . . . */ + + name = strndup(a, an); + if (!name) + return -ENOMEM; + + type = strjoin(b, ".", c); + if (!type) + return -ENOMEM; + + d = p; + goto finish; + } + + } else if (srv_type_label_is_valid(a, an)) { + + /* OK, got . . */ + + name = NULL; + + type = strjoin(a, ".", b); + if (!type) + return -ENOMEM; + + d = q; + goto finish; + } + } + + name = NULL; + type = NULL; + d = joined; + +finish: + r = dns_name_normalize(d, 0, &domain); + if (r < 0) + return r; + + if (_domain) + *_domain = TAKE_PTR(domain); + + if (_type) + *_type = TAKE_PTR(type); + + if (_name) + *_name = TAKE_PTR(name); + + return 0; +} + +static int dns_name_build_suffix_table(const char *name, const char *table[]) { + const char *p; + unsigned n = 0; + int r; + + assert(name); + assert(table); + + p = name; + for (;;) { + if (n > DNS_N_LABELS_MAX) + return -EINVAL; + + table[n] = p; + r = dns_name_parent(&p); + if (r < 0) + return r; + if (r == 0) + break; + + n++; + } + + return (int) n; +} + +int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) { + const char* labels[DNS_N_LABELS_MAX+1]; + int n; + + assert(name); + assert(ret); + + n = dns_name_build_suffix_table(name, labels); + if (n < 0) + return n; + + if ((unsigned) n < n_labels) + return -EINVAL; + + *ret = labels[n - n_labels]; + return (int) (n - n_labels); +} + +int dns_name_skip(const char *a, unsigned n_labels, const char **ret) { + int r; + + assert(a); + assert(ret); + + for (; n_labels > 0; n_labels--) { + r = dns_name_parent(&a); + if (r < 0) + return r; + if (r == 0) { + *ret = ""; + return 0; + } + } + + *ret = a; + return 1; +} + +int dns_name_count_labels(const char *name) { + unsigned n = 0; + const char *p; + int r; + + assert(name); + + p = name; + for (;;) { + r = dns_name_parent(&p); + if (r < 0) + return r; + if (r == 0) + break; + + if (n >= DNS_N_LABELS_MAX) + return -EINVAL; + + n++; + } + + return (int) n; +} + +int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b) { + int r; + + assert(a); + assert(b); + + r = dns_name_skip(a, n_labels, &a); + if (r <= 0) + return r; + + return dns_name_equal(a, b); +} + +int dns_name_common_suffix(const char *a, const char *b, const char **ret) { + const char *a_labels[DNS_N_LABELS_MAX+1], *b_labels[DNS_N_LABELS_MAX+1]; + int n = 0, m = 0, k = 0, r, q; + + assert(a); + assert(b); + assert(ret); + + /* Determines the common suffix of domain names a and b */ + + n = dns_name_build_suffix_table(a, a_labels); + if (n < 0) + return n; + + m = dns_name_build_suffix_table(b, b_labels); + if (m < 0) + return m; + + for (;;) { + char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX]; + const char *x, *y; + + if (k >= n || k >= m) { + *ret = a_labels[n - k]; + return 0; + } + + x = a_labels[n - 1 - k]; + r = dns_label_unescape(&x, la, sizeof la, 0); + if (r < 0) + return r; + + y = b_labels[m - 1 - k]; + q = dns_label_unescape(&y, lb, sizeof lb, 0); + if (q < 0) + return q; + + if (r != q || ascii_strcasecmp_n(la, lb, r) != 0) { + *ret = a_labels[n - k]; + return 0; + } + + k++; + } +} + +int dns_name_apply_idna(const char *name, char **ret) { + /* Return negative on error, 0 if not implemented, positive on success. */ + +#if HAVE_LIBIDN2 + int r; + _cleanup_free_ char *t = NULL; + + assert(name); + assert(ret); + + r = idn2_lookup_u8((uint8_t*) name, (uint8_t**) &t, + IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL); + log_debug("idn2_lookup_u8: %s → %s", name, t); + if (r == IDN2_OK) { + if (!startswith(name, "xn--")) { + _cleanup_free_ char *s = NULL; + + r = idn2_to_unicode_8z8z(t, &s, 0); + if (r != IDN2_OK) { + log_debug("idn2_to_unicode_8z8z(\"%s\") failed: %d/%s", + t, r, idn2_strerror(r)); + return 0; + } + + if (!streq_ptr(name, s)) { + log_debug("idn2 roundtrip failed: \"%s\" → \"%s\" → \"%s\", ignoring.", + name, t, s); + return 0; + } + } + + *ret = TAKE_PTR(t); + + return 1; /* *ret has been written */ + } + + log_debug("idn2_lookup_u8(\"%s\") failed: %d/%s", name, r, idn2_strerror(r)); + if (r == IDN2_2HYPHEN) + /* The name has two hyphens — forbidden by IDNA2008 in some cases */ + return 0; + if (IN_SET(r, IDN2_TOO_BIG_DOMAIN, IDN2_TOO_BIG_LABEL)) + return -ENOSPC; + return -EINVAL; +#elif HAVE_LIBIDN + _cleanup_free_ char *buf = NULL; + size_t n = 0, allocated = 0; + bool first = true; + int r, q; + + assert(name); + assert(ret); + + for (;;) { + char label[DNS_LABEL_MAX]; + + r = dns_label_unescape(&name, label, sizeof label, 0); + if (r < 0) + return r; + if (r == 0) + break; + + q = dns_label_apply_idna(label, r, label, sizeof label); + if (q < 0) + return q; + if (q > 0) + r = q; + + if (!GREEDY_REALLOC(buf, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) + return -ENOMEM; + + r = dns_label_escape(label, r, buf + n + !first, DNS_LABEL_ESCAPED_MAX); + if (r < 0) + return r; + + if (first) + first = false; + else + buf[n++] = '.'; + + n += r; + } + + if (n > DNS_HOSTNAME_MAX) + return -EINVAL; + + if (!GREEDY_REALLOC(buf, allocated, n + 1)) + return -ENOMEM; + + buf[n] = 0; + *ret = TAKE_PTR(buf); + + return 1; +#else + return 0; +#endif +} + +int dns_name_is_valid_or_address(const char *name) { + /* Returns > 0 if the specified name is either a valid IP address formatted as string or a valid DNS name */ + + if (isempty(name)) + return 0; + + if (in_addr_from_string_auto(name, NULL, NULL) >= 0) + return 1; + + return dns_name_is_valid(name); +} diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h new file mode 100644 index 00000000..6ed512c6 --- /dev/null +++ b/src/shared/dns-domain.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "hashmap.h" +#include "in-addr-util.h" + +/* Length of a single label, with all escaping removed, excluding any trailing dot or NUL byte */ +#define DNS_LABEL_MAX 63 + +/* Worst case length of a single label, with all escaping applied and room for a trailing NUL byte. */ +#define DNS_LABEL_ESCAPED_MAX (DNS_LABEL_MAX*4+1) + +/* Maximum length of a full hostname, consisting of a series of unescaped labels, and no trailing dot or NUL byte */ +#define DNS_HOSTNAME_MAX 253 + +/* Maximum length of a full hostname, on the wire, including the final NUL byte */ +#define DNS_WIRE_FORMAT_HOSTNAME_MAX 255 + +/* Maximum number of labels per valid hostname */ +#define DNS_N_LABELS_MAX 127 + +typedef enum DNSLabelFlags { + DNS_LABEL_LDH = 1 << 0, /* Follow the "LDH" rule — only letters, digits, and internal hyphens. */ + DNS_LABEL_NO_ESCAPES = 1 << 1, /* Do not treat backslashes specially */ +} DNSLabelFlags; + +int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags flags); +int dns_label_unescape_suffix(const char *name, const char **label_end, char *dest, size_t sz); +int dns_label_escape(const char *p, size_t l, char *dest, size_t sz); +int dns_label_escape_new(const char *p, size_t l, char **ret); + +static inline int dns_name_parent(const char **name) { + return dns_label_unescape(name, NULL, DNS_LABEL_MAX, 0); +} + +#if HAVE_LIBIDN +int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max); +int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max); +#endif + +int dns_name_concat(const char *a, const char *b, DNSLabelFlags flags, char **ret); + +static inline int dns_name_normalize(const char *s, DNSLabelFlags flags, char **ret) { + /* dns_name_concat() normalizes as a side-effect */ + return dns_name_concat(s, NULL, flags, ret); +} + +static inline int dns_name_is_valid(const char *s) { + int r; + + /* dns_name_normalize() verifies as a side effect */ + r = dns_name_normalize(s, 0, NULL); + if (r == -EINVAL) + return 0; + if (r < 0) + return r; + return 1; +} + +static inline int dns_name_is_valid_ldh(const char *s) { + int r; + + r = dns_name_concat(s, NULL, DNS_LABEL_LDH|DNS_LABEL_NO_ESCAPES, NULL); + if (r == -EINVAL) + return 0; + if (r < 0) + return r; + return 1; +} + +void dns_name_hash_func(const char *s, struct siphash *state); +int dns_name_compare_func(const char *a, const char *b); +extern const struct hash_ops dns_name_hash_ops; + +int dns_name_between(const char *a, const char *b, const char *c); +int dns_name_equal(const char *x, const char *y); +int dns_name_endswith(const char *name, const char *suffix); +int dns_name_startswith(const char *name, const char *prefix); + +int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret); + +int dns_name_reverse(int family, const union in_addr_union *a, char **ret); +int dns_name_address(const char *p, int *family, union in_addr_union *a); + +bool dns_name_is_root(const char *name); +bool dns_name_is_single_label(const char *name); + +int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, bool canonical); + +bool dns_srv_type_is_valid(const char *name); +bool dnssd_srv_type_is_valid(const char *name); +bool dns_service_name_is_valid(const char *name); + +int dns_service_join(const char *name, const char *type, const char *domain, char **ret); +int dns_service_split(const char *joined, char **name, char **type, char **domain); + +int dns_name_suffix(const char *name, unsigned n_labels, const char **ret); +int dns_name_count_labels(const char *name); + +int dns_name_skip(const char *a, unsigned n_labels, const char **ret); +int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b); + +int dns_name_common_suffix(const char *a, const char *b, const char **ret); + +int dns_name_apply_idna(const char *name, char **ret); + +int dns_name_is_valid_or_address(const char *name); diff --git a/src/shared/dropin.c b/src/shared/dropin.c new file mode 100644 index 00000000..96cd08aa --- /dev/null +++ b/src/shared/dropin.c @@ -0,0 +1,275 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "conf-files.h" +#include "dirent-util.h" +#include "dropin.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio-label.h" +#include "fs-util.h" +#include "hashmap.h" +#include "log.h" +#include "macro.h" +#include "mkdir.h" +#include "path-util.h" +#include "set.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" + +int drop_in_file(const char *dir, const char *unit, unsigned level, + const char *name, char **ret_p, char **ret_q) { + + char prefix[DECIMAL_STR_MAX(unsigned)]; + _cleanup_free_ char *b = NULL, *p = NULL, *q = NULL; + + assert(unit); + assert(name); + assert(ret_p); + assert(ret_q); + + sprintf(prefix, "%u", level); + + b = xescape(name, "/."); + if (!b) + return -ENOMEM; + + if (!filename_is_valid(b)) + return -EINVAL; + + p = strjoin(dir, "/", unit, ".d"); + q = strjoin(p, "/", prefix, "-", b, ".conf"); + if (!p || !q) + return -ENOMEM; + + *ret_p = TAKE_PTR(p); + *ret_q = TAKE_PTR(q); + return 0; +} + +int write_drop_in(const char *dir, const char *unit, unsigned level, + const char *name, const char *data) { + + _cleanup_free_ char *p = NULL, *q = NULL; + int r; + + assert(dir); + assert(unit); + assert(name); + assert(data); + + r = drop_in_file(dir, unit, level, name, &p, &q); + if (r < 0) + return r; + + (void) mkdir_p(p, 0755); + return write_string_file_atomic_label(q, data); +} + +int write_drop_in_format(const char *dir, const char *unit, unsigned level, + const char *name, const char *format, ...) { + _cleanup_free_ char *p = NULL; + va_list ap; + int r; + + assert(dir); + assert(unit); + assert(name); + assert(format); + + va_start(ap, format); + r = vasprintf(&p, format, ap); + va_end(ap); + + if (r < 0) + return -ENOMEM; + + return write_drop_in(dir, unit, level, name, p); +} + +static int unit_file_add_dir( + const char *original_root, + const char *path, + char ***dirs) { + + _cleanup_free_ char *chased = NULL; + int r; + + assert(path); + + /* This adds [original_root]/path to dirs, if it exists. */ + + r = chase_symlinks(path, original_root, 0, &chased, NULL); + if (r == -ENOENT) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */ + return 0; + if (r == -ENAMETOOLONG) { + /* Also, ignore -ENAMETOOLONG but log about it. After all, users are not even able to create the + * drop-in dir in such case. This mostly happens for device units with an overly long /sys path. */ + log_debug_errno(r, "Path '%s' too long, couldn't canonicalize, ignoring.", path); + return 0; + } + if (r < 0) + return log_warning_errno(r, "Failed to canonicalize path '%s': %m", path); + + if (strv_consume(dirs, TAKE_PTR(chased)) < 0) + return log_oom(); + + return 0; +} + +static int unit_file_find_dirs( + const char *original_root, + Set *unit_path_cache, + const char *unit_path, + const char *name, + const char *suffix, + char ***dirs) { + + _cleanup_free_ char *prefix = NULL, *instance = NULL, *built = NULL; + bool is_instance, chopped; + const char *dash; + UnitType type; + char *path; + size_t n; + int r; + + assert(unit_path); + assert(name); + assert(suffix); + + path = strjoina(unit_path, "/", name, suffix); + if (!unit_path_cache || set_get(unit_path_cache, path)) { + r = unit_file_add_dir(original_root, path, dirs); + if (r < 0) + return r; + } + + is_instance = unit_name_is_valid(name, UNIT_NAME_INSTANCE); + if (is_instance) { /* Also try the template dir */ + _cleanup_free_ char *template = NULL; + + r = unit_name_template(name, &template); + if (r < 0) + return log_error_errno(r, "Failed to generate template from unit name: %m"); + + r = unit_file_find_dirs(original_root, unit_path_cache, unit_path, template, suffix, dirs); + if (r < 0) + return r; + } + + /* Return early for top level drop-ins. */ + if (unit_type_from_string(name) >= 0) + return 0; + + /* Let's see if there's a "-" prefix for this unit name. If so, let's invoke ourselves for it. This will then + * recursively do the same for all our prefixes. i.e. this means given "foo-bar-waldo.service" we'll also + * search "foo-bar-.service" and "foo-.service". + * + * Note the order in which we do it: we traverse up adding drop-ins on each step. This means the more specific + * drop-ins may override the more generic drop-ins, which is the intended behaviour. */ + + r = unit_name_to_prefix(name, &prefix); + if (r < 0) + return log_error_errno(r, "Failed to derive unit name prefix from unit name: %m"); + + chopped = false; + for (;;) { + dash = strrchr(prefix, '-'); + if (!dash) /* No dash? if so we are done */ + return 0; + + n = (size_t) (dash - prefix); + if (n == 0) /* Leading dash? If so, we are done */ + return 0; + + if (prefix[n+1] != 0 || chopped) { + prefix[n+1] = 0; + break; + } + + /* Trailing dash? If so, chop it off and try again, but not more than once. */ + prefix[n] = 0; + chopped = true; + } + + if (!unit_prefix_is_valid(prefix)) + return 0; + + type = unit_name_to_type(name); + if (type < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to to derive unit type from unit name: %s", + name); + + if (is_instance) { + r = unit_name_to_instance(name, &instance); + if (r < 0) + return log_error_errno(r, "Failed to derive unit name instance from unit name: %m"); + } + + r = unit_name_build_from_type(prefix, instance, type, &built); + if (r < 0) + return log_error_errno(r, "Failed to build prefix unit name: %m"); + + return unit_file_find_dirs(original_root, unit_path_cache, unit_path, built, suffix, dirs); +} + +int unit_file_find_dropin_paths( + const char *original_root, + char **lookup_path, + Set *unit_path_cache, + const char *dir_suffix, + const char *file_suffix, + const Set *names, + char ***ret) { + + _cleanup_strv_free_ char **dirs = NULL; + char *name, **p; + Iterator i; + int r; + + assert(ret); + + /* All the names in the unit are of the same type so just grab one. */ + name = (char*) set_first(names); + if (name) { + UnitType type = _UNIT_TYPE_INVALID; + + type = unit_name_to_type(name); + if (type < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to to derive unit type from unit name: %s", + name); + + /* Special top level drop in for ".". Add this first as it's the most generic + * and should be able to be overridden by more specific drop-ins. */ + STRV_FOREACH(p, lookup_path) + (void) unit_file_find_dirs(original_root, + unit_path_cache, + *p, + unit_type_to_string(type), + dir_suffix, + &dirs); + } + + SET_FOREACH(name, names, i) + STRV_FOREACH(p, lookup_path) + (void) unit_file_find_dirs(original_root, unit_path_cache, *p, name, dir_suffix, &dirs); + + if (strv_isempty(dirs)) { + *ret = NULL; + return 0; + } + + r = conf_files_list_strv(ret, file_suffix, NULL, 0, (const char**) dirs); + if (r < 0) + return log_warning_errno(r, "Failed to create the list of configuration files: %m"); + + return 1; +} diff --git a/src/shared/dropin.h b/src/shared/dropin.h new file mode 100644 index 00000000..89a2ab10 --- /dev/null +++ b/src/shared/dropin.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "hashmap.h" +#include "macro.h" +#include "set.h" +#include "unit-name.h" + +int drop_in_file(const char *dir, const char *unit, unsigned level, + const char *name, char **_p, char **_q); + +int write_drop_in(const char *dir, const char *unit, unsigned level, + const char *name, const char *data); + +int write_drop_in_format(const char *dir, const char *unit, unsigned level, + const char *name, const char *format, ...) _printf_(5, 6); + +int unit_file_find_dropin_paths( + const char *original_root, + char **lookup_path, + Set *unit_path_cache, + const char *dir_suffix, + const char *file_suffix, + const Set *names, + char ***paths); diff --git a/src/shared/efi-loader.c b/src/shared/efi-loader.c new file mode 100644 index 00000000..4f6dff79 --- /dev/null +++ b/src/shared/efi-loader.c @@ -0,0 +1,699 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "dirent-util.h" +#include "efi-loader.h" +#include "efivars.h" +#include "fd-util.h" +#include "io-util.h" +#include "parse-util.h" +#include "sort-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "utf8.h" +#include "virt.h" + +#if ENABLE_EFI + +#define LOAD_OPTION_ACTIVE 0x00000001 +#define MEDIA_DEVICE_PATH 0x04 +#define MEDIA_HARDDRIVE_DP 0x01 +#define MEDIA_FILEPATH_DP 0x04 +#define SIGNATURE_TYPE_GUID 0x02 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 +#define END_DEVICE_PATH_TYPE 0x7f +#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 + +#define boot_option__contents { \ + uint32_t attr; \ + uint16_t path_len; \ + uint16_t title[]; \ + } + +struct boot_option boot_option__contents; +struct boot_option__packed boot_option__contents _packed_; +assert_cc(offsetof(struct boot_option, title) == offsetof(struct boot_option__packed, title)); +/* sizeof(struct boot_option) != sizeof(struct boot_option__packed), so + * the *size* of the structure should not be used anywhere below. */ + +struct drive_path { + uint32_t part_nr; + uint64_t part_start; + uint64_t part_size; + char signature[16]; + uint8_t mbr_type; + uint8_t signature_type; +} _packed_; + +#define device_path__contents { \ + uint8_t type; \ + uint8_t sub_type; \ + uint16_t length; \ + union { \ + uint16_t path[0]; \ + struct drive_path drive; \ + }; \ + } + +struct device_path device_path__contents; +struct device_path__packed device_path__contents _packed_; +assert_cc(sizeof(struct device_path) == sizeof(struct device_path__packed)); + + +int efi_reboot_to_firmware_supported(void) { + _cleanup_free_ void *v = NULL; + uint64_t b; + size_t s; + int r; + + if (!is_efi_boot()) + return -EOPNOTSUPP; + + r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", NULL, &v, &s); + if (r == -ENOENT) /* variable doesn't exist? it's not supported then */ + return -EOPNOTSUPP; + if (r < 0) + return r; + if (s != sizeof(uint64_t)) + return -EINVAL; + + b = *(uint64_t*) v; + if (!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) + return -EOPNOTSUPP; /* bit unset? it's not supported then */ + + return 0; +} + +static int get_os_indications(uint64_t *os_indication) { + _cleanup_free_ void *v = NULL; + size_t s; + int r; + + /* Let's verify general support first */ + r = efi_reboot_to_firmware_supported(); + if (r < 0) + return r; + + r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s); + if (r == -ENOENT) { + /* Some firmware implementations that do support OsIndications and report that with + * OsIndicationsSupported will remove the OsIndications variable when it is unset. Let's pretend it's 0 + * then, to hide this implementation detail. Note that this call will return -ENOENT then only if the + * support for OsIndications is missing entirely, as determined by efi_reboot_to_firmware_supported() + * above. */ + *os_indication = 0; + return 0; + } else if (r < 0) + return r; + else if (s != sizeof(uint64_t)) + return -EINVAL; + + *os_indication = *(uint64_t *)v; + return 0; +} + +int efi_get_reboot_to_firmware(void) { + int r; + uint64_t b; + + r = get_os_indications(&b); + if (r < 0) + return r; + + return !!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI); +} + +int efi_set_reboot_to_firmware(bool value) { + int r; + uint64_t b, b_new; + + r = get_os_indications(&b); + if (r < 0) + return r; + + if (value) + b_new = b | EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + else + b_new = b & ~EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + + /* Avoid writing to efi vars store if we can due to firmware bugs. */ + if (b != b_new) + return efi_set_variable(EFI_VENDOR_GLOBAL, "OsIndications", &b_new, sizeof(uint64_t)); + + return 0; +} + +static ssize_t utf16_size(const uint16_t *s, size_t buf_len_bytes) { + size_t l = 0; + + /* Returns the size of the string in bytes without the terminating two zero bytes */ + + if (buf_len_bytes % sizeof(uint16_t) != 0) + return -EINVAL; + + while (l < buf_len_bytes / sizeof(uint16_t)) { + if (s[l] == 0) + return (l + 1) * sizeof(uint16_t); + l++; + } + + return -EINVAL; /* The terminator was not found */ +} + +struct guid { + uint32_t u1; + uint16_t u2; + uint16_t u3; + uint8_t u4[8]; +} _packed_; + +static void efi_guid_to_id128(const void *guid, sd_id128_t *id128) { + uint32_t u1; + uint16_t u2, u3; + const struct guid *uuid = guid; + + memcpy(&u1, &uuid->u1, sizeof(uint32_t)); + id128->bytes[0] = (u1 >> 24) & 0xff; + id128->bytes[1] = (u1 >> 16) & 0xff; + id128->bytes[2] = (u1 >> 8) & 0xff; + id128->bytes[3] = u1 & 0xff; + memcpy(&u2, &uuid->u2, sizeof(uint16_t)); + id128->bytes[4] = (u2 >> 8) & 0xff; + id128->bytes[5] = u2 & 0xff; + memcpy(&u3, &uuid->u3, sizeof(uint16_t)); + id128->bytes[6] = (u3 >> 8) & 0xff; + id128->bytes[7] = u3 & 0xff; + memcpy(&id128->bytes[8], uuid->u4, sizeof(uuid->u4)); +} + +int efi_get_boot_option( + uint16_t id, + char **title, + sd_id128_t *part_uuid, + char **path, + bool *active) { + + char boot_id[9]; + _cleanup_free_ uint8_t *buf = NULL; + size_t l; + struct boot_option *header; + ssize_t title_size; + _cleanup_free_ char *s = NULL, *p = NULL; + sd_id128_t p_uuid = SD_ID128_NULL; + int r; + + if (!is_efi_boot()) + return -EOPNOTSUPP; + + xsprintf(boot_id, "Boot%04X", id); + r = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, (void **)&buf, &l); + if (r < 0) + return r; + if (l < offsetof(struct boot_option, title)) + return -ENOENT; + + header = (struct boot_option *)buf; + title_size = utf16_size(header->title, l - offsetof(struct boot_option, title)); + if (title_size < 0) + return title_size; + + if (title) { + s = utf16_to_utf8(header->title, title_size); + if (!s) + return -ENOMEM; + } + + if (header->path_len > 0) { + uint8_t *dbuf; + size_t dnext, doff; + + doff = offsetof(struct boot_option, title) + title_size; + dbuf = buf + doff; + if (header->path_len > l - doff) + return -EINVAL; + + dnext = 0; + while (dnext < header->path_len) { + struct device_path *dpath; + + dpath = (struct device_path *)(dbuf + dnext); + if (dpath->length < 4) + break; + + /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */ + if (dpath->type == END_DEVICE_PATH_TYPE && dpath->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE) + break; + + dnext += dpath->length; + + /* Type 0x04 – Media Device Path */ + if (dpath->type != MEDIA_DEVICE_PATH) + continue; + + /* Sub-Type 1 – Hard Drive */ + if (dpath->sub_type == MEDIA_HARDDRIVE_DP) { + /* 0x02 – GUID Partition Table */ + if (dpath->drive.mbr_type != MBR_TYPE_EFI_PARTITION_TABLE_HEADER) + continue; + + /* 0x02 – GUID signature */ + if (dpath->drive.signature_type != SIGNATURE_TYPE_GUID) + continue; + + if (part_uuid) + efi_guid_to_id128(dpath->drive.signature, &p_uuid); + continue; + } + + /* Sub-Type 4 – File Path */ + if (dpath->sub_type == MEDIA_FILEPATH_DP && !p && path) { + p = utf16_to_utf8(dpath->path, dpath->length-4); + if (!p) + return -ENOMEM; + + efi_tilt_backslashes(p); + continue; + } + } + } + + if (title) + *title = TAKE_PTR(s); + if (part_uuid) + *part_uuid = p_uuid; + if (path) + *path = TAKE_PTR(p); + if (active) + *active = header->attr & LOAD_OPTION_ACTIVE; + + return 0; +} + +static void to_utf16(uint16_t *dest, const char *src) { + int i; + + for (i = 0; src[i] != '\0'; i++) + dest[i] = src[i]; + dest[i] = '\0'; +} + +static void id128_to_efi_guid(sd_id128_t id, void *guid) { + struct guid uuid = { + .u1 = id.bytes[0] << 24 | id.bytes[1] << 16 | id.bytes[2] << 8 | id.bytes[3], + .u2 = id.bytes[4] << 8 | id.bytes[5], + .u3 = id.bytes[6] << 8 | id.bytes[7], + }; + memcpy(uuid.u4, id.bytes+8, sizeof(uuid.u4)); + memcpy(guid, &uuid, sizeof(uuid)); +} + +static uint16_t *tilt_slashes(uint16_t *s) { + uint16_t *p; + + for (p = s; *p; p++) + if (*p == '/') + *p = '\\'; + + return s; +} + +int efi_add_boot_option( + uint16_t id, + const char *title, + uint32_t part, + uint64_t pstart, + uint64_t psize, + sd_id128_t part_uuid, + const char *path) { + + size_t size, title_len, path_len; + _cleanup_free_ char *buf = NULL; + struct boot_option *option; + struct device_path *devicep; + char boot_id[9]; + + if (!is_efi_boot()) + return -EOPNOTSUPP; + + title_len = (strlen(title)+1) * 2; + path_len = (strlen(path)+1) * 2; + + buf = malloc0(offsetof(struct boot_option, title) + title_len + + sizeof(struct drive_path) + + sizeof(struct device_path) + path_len); + if (!buf) + return -ENOMEM; + + /* header */ + option = (struct boot_option *)buf; + option->attr = LOAD_OPTION_ACTIVE; + option->path_len = offsetof(struct device_path, drive) + sizeof(struct drive_path) + + offsetof(struct device_path, path) + path_len + + offsetof(struct device_path, path); + to_utf16(option->title, title); + size = offsetof(struct boot_option, title) + title_len; + + /* partition info */ + devicep = (struct device_path *)(buf + size); + devicep->type = MEDIA_DEVICE_PATH; + devicep->sub_type = MEDIA_HARDDRIVE_DP; + devicep->length = offsetof(struct device_path, drive) + sizeof(struct drive_path); + memcpy(&devicep->drive.part_nr, &part, sizeof(uint32_t)); + memcpy(&devicep->drive.part_start, &pstart, sizeof(uint64_t)); + memcpy(&devicep->drive.part_size, &psize, sizeof(uint64_t)); + id128_to_efi_guid(part_uuid, devicep->drive.signature); + devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; + devicep->drive.signature_type = SIGNATURE_TYPE_GUID; + size += devicep->length; + + /* path to loader */ + devicep = (struct device_path *)(buf + size); + devicep->type = MEDIA_DEVICE_PATH; + devicep->sub_type = MEDIA_FILEPATH_DP; + devicep->length = offsetof(struct device_path, path) + path_len; + to_utf16(devicep->path, path); + tilt_slashes(devicep->path); + size += devicep->length; + + /* end of path */ + devicep = (struct device_path *)(buf + size); + devicep->type = END_DEVICE_PATH_TYPE; + devicep->sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE; + devicep->length = offsetof(struct device_path, path); + size += devicep->length; + + xsprintf(boot_id, "Boot%04X", id); + return efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, buf, size); +} + +int efi_remove_boot_option(uint16_t id) { + char boot_id[9]; + + if (!is_efi_boot()) + return -EOPNOTSUPP; + + xsprintf(boot_id, "Boot%04X", id); + return efi_set_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, 0); +} + +int efi_get_boot_order(uint16_t **order) { + _cleanup_free_ void *buf = NULL; + size_t l; + int r; + + if (!is_efi_boot()) + return -EOPNOTSUPP; + + r = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", NULL, &buf, &l); + if (r < 0) + return r; + + if (l <= 0) + return -ENOENT; + + if (l % sizeof(uint16_t) > 0 || + l / sizeof(uint16_t) > INT_MAX) + return -EINVAL; + + *order = TAKE_PTR(buf); + return (int) (l / sizeof(uint16_t)); +} + +int efi_set_boot_order(uint16_t *order, size_t n) { + + if (!is_efi_boot()) + return -EOPNOTSUPP; + + return efi_set_variable(EFI_VENDOR_GLOBAL, "BootOrder", order, n * sizeof(uint16_t)); +} + +static int boot_id_hex(const char s[static 4]) { + int id = 0, i; + + assert(s); + + for (i = 0; i < 4; i++) + if (s[i] >= '0' && s[i] <= '9') + id |= (s[i] - '0') << (3 - i) * 4; + else if (s[i] >= 'A' && s[i] <= 'F') + id |= (s[i] - 'A' + 10) << (3 - i) * 4; + else + return -EINVAL; + + return id; +} + +static int cmp_uint16(const uint16_t *a, const uint16_t *b) { + return CMP(*a, *b); +} + +int efi_get_boot_options(uint16_t **options) { + _cleanup_closedir_ DIR *dir = NULL; + _cleanup_free_ uint16_t *list = NULL; + struct dirent *de; + size_t alloc = 0; + int count = 0; + + assert(options); + + if (!is_efi_boot()) + return -EOPNOTSUPP; + + dir = opendir("/sys/firmware/efi/efivars/"); + if (!dir) + return -errno; + + FOREACH_DIRENT(de, dir, return -errno) { + int id; + + if (strncmp(de->d_name, "Boot", 4) != 0) + continue; + + if (strlen(de->d_name) != 45) + continue; + + if (strcmp(de->d_name + 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0) + continue; + + id = boot_id_hex(de->d_name + 4); + if (id < 0) + continue; + + if (!GREEDY_REALLOC(list, alloc, count + 1)) + return -ENOMEM; + + list[count++] = id; + } + + typesafe_qsort(list, count, cmp_uint16); + + *options = TAKE_PTR(list); + + return count; +} + +static int read_usec(sd_id128_t vendor, const char *name, usec_t *u) { + _cleanup_free_ char *j = NULL; + int r; + uint64_t x = 0; + + assert(name); + assert(u); + + r = efi_get_variable_string(EFI_VENDOR_LOADER, name, &j); + if (r < 0) + return r; + + r = safe_atou64(j, &x); + if (r < 0) + return r; + + *u = x; + return 0; +} + +int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) { + uint64_t x, y; + int r; + + assert(firmware); + assert(loader); + + if (!is_efi_boot()) + return -EOPNOTSUPP; + + r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeInitUSec", &x); + if (r < 0) + return r; + + r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeExecUSec", &y); + if (r < 0) + return r; + + if (y == 0 || y < x) + return -EIO; + + if (y > USEC_PER_HOUR) + return -EIO; + + *firmware = x; + *loader = y; + + return 0; +} + +int efi_loader_get_device_part_uuid(sd_id128_t *u) { + _cleanup_free_ char *p = NULL; + int r, parsed[16]; + + if (!is_efi_boot()) + return -EOPNOTSUPP; + + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderDevicePartUUID", &p); + if (r < 0) + return r; + + if (sscanf(p, SD_ID128_UUID_FORMAT_STR, + &parsed[0], &parsed[1], &parsed[2], &parsed[3], + &parsed[4], &parsed[5], &parsed[6], &parsed[7], + &parsed[8], &parsed[9], &parsed[10], &parsed[11], + &parsed[12], &parsed[13], &parsed[14], &parsed[15]) != 16) + return -EIO; + + if (u) { + unsigned i; + + for (i = 0; i < ELEMENTSOF(parsed); i++) + u->bytes[i] = parsed[i]; + } + + return 0; +} + +int efi_loader_get_entries(char ***ret) { + _cleanup_free_ char16_t *entries = NULL; + _cleanup_strv_free_ char **l = NULL; + size_t size, i, start; + int r; + + assert(ret); + + if (!is_efi_boot()) + return -EOPNOTSUPP; + + r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntries", NULL, (void**) &entries, &size); + if (r < 0) + return r; + + /* The variable contains a series of individually NUL terminated UTF-16 strings. */ + + for (i = 0, start = 0;; i++) { + _cleanup_free_ char *decoded = NULL; + bool end; + + /* Is this the end of the variable's data? */ + end = i * sizeof(char16_t) >= size; + + /* Are we in the middle of a string? (i.e. not at the end of the variable, nor at a NUL terminator?) If + * so, let's go to the next entry. */ + if (!end && entries[i] != 0) + continue; + + /* We reached the end of a string, let's decode it into UTF-8 */ + decoded = utf16_to_utf8(entries + start, (i - start) * sizeof(char16_t)); + if (!decoded) + return -ENOMEM; + + if (efi_loader_entry_name_valid(decoded)) { + r = strv_consume(&l, TAKE_PTR(decoded)); + if (r < 0) + return r; + } else + log_debug("Ignoring invalid loader entry '%s'.", decoded); + + /* We reached the end of the variable */ + if (end) + break; + + /* Continue after the NUL byte */ + start = i + 1; + } + + *ret = TAKE_PTR(l); + return 0; +} + +int efi_loader_get_features(uint64_t *ret) { + _cleanup_free_ void *v = NULL; + size_t s; + int r; + + if (!is_efi_boot()) { + *ret = 0; + return 0; + } + + r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderFeatures", NULL, &v, &s); + if (r == -ENOENT) { + _cleanup_free_ char *info = NULL; + + /* The new (v240+) LoaderFeatures variable is not supported, let's see if it's systemd-boot at all */ + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderInfo", &info); + if (r < 0) { + if (r != -ENOENT) + return r; + + /* Variable not set, definitely means not systemd-boot */ + + } else if (first_word(info, "systemd-boot")) { + + /* An older systemd-boot version. Let's hardcode the feature set, since it was pretty + * static in all its versions. */ + + *ret = EFI_LOADER_FEATURE_CONFIG_TIMEOUT | + EFI_LOADER_FEATURE_ENTRY_DEFAULT | + EFI_LOADER_FEATURE_ENTRY_ONESHOT; + + return 0; + } + + /* No features supported */ + *ret = 0; + return 0; + } + if (r < 0) + return r; + + if (s != sizeof(uint64_t)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "LoaderFeatures EFI variable doesn't have the right size."); + + memcpy(ret, v, sizeof(uint64_t)); + return 0; +} + +#endif + +bool efi_loader_entry_name_valid(const char *s) { + if (isempty(s)) + return false; + + if (strlen(s) > FILENAME_MAX) /* Make sure entry names fit in filenames */ + return false; + + return in_charset(s, ALPHANUMERICAL "+-_."); +} + +char *efi_tilt_backslashes(char *s) { + char *p; + + for (p = s; *p; p++) + if (*p == '\\') + *p = '/'; + + return s; +} diff --git a/src/shared/efi-loader.h b/src/shared/efi-loader.h new file mode 100644 index 00000000..96208d25 --- /dev/null +++ b/src/shared/efi-loader.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "efivars.h" + +#if ENABLE_EFI + +int efi_reboot_to_firmware_supported(void); +int efi_get_reboot_to_firmware(void); +int efi_set_reboot_to_firmware(bool value); + +int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *part_uuid, char **path, bool *active); +int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path); +int efi_remove_boot_option(uint16_t id); +int efi_get_boot_order(uint16_t **order); +int efi_set_boot_order(uint16_t *order, size_t n); +int efi_get_boot_options(uint16_t **options); + +int efi_loader_get_device_part_uuid(sd_id128_t *u); +int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader); + +int efi_loader_get_entries(char ***ret); + +int efi_loader_get_features(uint64_t *ret); + +#else + +static inline int efi_reboot_to_firmware_supported(void) { + return -EOPNOTSUPP; +} + +static inline int efi_get_reboot_to_firmware(void) { + return -EOPNOTSUPP; +} + +static inline int efi_set_reboot_to_firmware(bool value) { + return -EOPNOTSUPP; +} + +static inline int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *part_uuid, char **path, bool *active) { + return -EOPNOTSUPP; +} + +static inline int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path) { + return -EOPNOTSUPP; +} + +static inline int efi_remove_boot_option(uint16_t id) { + return -EOPNOTSUPP; +} + +static inline int efi_get_boot_order(uint16_t **order) { + return -EOPNOTSUPP; +} + +static inline int efi_set_boot_order(uint16_t *order, size_t n) { + return -EOPNOTSUPP; +} + +static inline int efi_get_boot_options(uint16_t **options) { + return -EOPNOTSUPP; +} + +static inline int efi_loader_get_device_part_uuid(sd_id128_t *u) { + return -EOPNOTSUPP; +} + +static inline int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) { + return -EOPNOTSUPP; +} + +static inline int efi_loader_get_entries(char ***ret) { + return -EOPNOTSUPP; +} + +static inline int efi_loader_get_features(uint64_t *ret) { + return -EOPNOTSUPP; +} + +#endif + +bool efi_loader_entry_name_valid(const char *s); + +char *efi_tilt_backslashes(char *s); diff --git a/src/shared/enable-mempool.c b/src/shared/enable-mempool.c new file mode 100644 index 00000000..a571b43f --- /dev/null +++ b/src/shared/enable-mempool.c @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "mempool.h" + +const bool mempool_use_allowed = true; diff --git a/src/shared/env-file-label.c b/src/shared/env-file-label.c new file mode 100644 index 00000000..add68d22 --- /dev/null +++ b/src/shared/env-file-label.c @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "env-file-label.h" +#include "env-file.h" +#include "selinux-util.h" + +int write_env_file_label(const char *fname, char **l) { + int r; + + r = mac_selinux_create_file_prepare(fname, S_IFREG); + if (r < 0) + return r; + + r = write_env_file(fname, l); + + mac_selinux_create_file_clear(); + + return r; +} diff --git a/src/shared/env-file-label.h b/src/shared/env-file-label.h new file mode 100644 index 00000000..158fc4ec --- /dev/null +++ b/src/shared/env-file-label.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/* These functions are split out of fileio.h (and not for example just flags to the functions they wrap) in order to + * optimize linking: This way, -lselinux is needed only for the callers of these functions that need selinux, but not + * for all */ + +int write_env_file_label(const char *fname, char **l); diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c new file mode 100644 index 00000000..3119b2b9 --- /dev/null +++ b/src/shared/ethtool-util.c @@ -0,0 +1,948 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "conf-parser.h" +#include "ethtool-util.h" +#include "extract-word.h" +#include "log.h" +#include "memory-util.h" +#include "socket-util.h" +#include "string-table.h" +#include "strxcpyx.h" + +static const char* const duplex_table[_DUP_MAX] = { + [DUP_FULL] = "full", + [DUP_HALF] = "half" +}; + +DEFINE_STRING_TABLE_LOOKUP(duplex, Duplex); +DEFINE_CONFIG_PARSE_ENUM(config_parse_duplex, duplex, Duplex, "Failed to parse duplex setting"); + +static const char* const wol_table[_WOL_MAX] = { + [WOL_PHY] = "phy", + [WOL_UCAST] = "unicast", + [WOL_MCAST] = "multicast", + [WOL_BCAST] = "broadcast", + [WOL_ARP] = "arp", + [WOL_MAGIC] = "magic", + [WOL_MAGICSECURE] = "secureon", + [WOL_OFF] = "off", +}; + +DEFINE_STRING_TABLE_LOOKUP(wol, WakeOnLan); +DEFINE_CONFIG_PARSE_ENUM(config_parse_wol, wol, WakeOnLan, "Failed to parse WakeOnLan setting"); + +static const char* const port_table[] = { + [NET_DEV_PORT_TP] = "tp", + [NET_DEV_PORT_AUI] = "aui", + [NET_DEV_PORT_MII] = "mii", + [NET_DEV_PORT_FIBRE] = "fibre", + [NET_DEV_PORT_BNC] = "bnc", +}; + +DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort); +DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse Port setting"); + +static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = { + [NET_DEV_FEAT_GSO] = "tx-generic-segmentation", + [NET_DEV_FEAT_GRO] = "rx-gro", + [NET_DEV_FEAT_LRO] = "rx-lro", + [NET_DEV_FEAT_TSO] = "tx-tcp-segmentation", + [NET_DEV_FEAT_TSO6] = "tx-tcp6-segmentation", +}; + +static const char* const ethtool_link_mode_bit_table[] = { + [ETHTOOL_LINK_MODE_10baseT_Half_BIT] = "10baset-half", + [ETHTOOL_LINK_MODE_10baseT_Full_BIT] = "10baset-full", + [ETHTOOL_LINK_MODE_100baseT_Half_BIT] = "100baset-half", + [ETHTOOL_LINK_MODE_100baseT_Full_BIT] = "100baset-full", + [ETHTOOL_LINK_MODE_1000baseT_Half_BIT] = "1000baset-half", + [ETHTOOL_LINK_MODE_1000baseT_Full_BIT] = "1000baset-full", + [ETHTOOL_LINK_MODE_Autoneg_BIT] = "autonegotiation", + [ETHTOOL_LINK_MODE_TP_BIT] = "tp", + [ETHTOOL_LINK_MODE_AUI_BIT] = "aui", + [ETHTOOL_LINK_MODE_MII_BIT] = "mii", + [ETHTOOL_LINK_MODE_FIBRE_BIT] = "fibre", + [ETHTOOL_LINK_MODE_BNC_BIT] = "bnc", + [ETHTOOL_LINK_MODE_10000baseT_Full_BIT] = "10000baset-full", + [ETHTOOL_LINK_MODE_Pause_BIT] = "pause", + [ETHTOOL_LINK_MODE_Asym_Pause_BIT] = "asym-pause", + [ETHTOOL_LINK_MODE_2500baseX_Full_BIT] = "2500basex-full", + [ETHTOOL_LINK_MODE_Backplane_BIT] = "backplane", + [ETHTOOL_LINK_MODE_1000baseKX_Full_BIT] = "1000basekx-full", + [ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT] = "10000basekx4-full", + [ETHTOOL_LINK_MODE_10000baseKR_Full_BIT] = "10000basekr-full", + [ETHTOOL_LINK_MODE_10000baseR_FEC_BIT] = "10000baser-fec", + [ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT] = "20000basemld2-full", + [ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT] = "20000basekr2-full", + [ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT] = "40000basekr4-full", + [ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT] = "40000basecr4-full", + [ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT] = "40000basesr4-full", + [ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT] = "40000baselr4-full", + [ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT] = "56000basekr4-full", + [ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT] = "56000basecr4-full", + [ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT] = "56000basesr4-full", + [ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT] = "56000baselr4-full", + [ETHTOOL_LINK_MODE_25000baseCR_Full_BIT] = "25000basecr-full", + [ETHTOOL_LINK_MODE_25000baseKR_Full_BIT] = "25000basekr-full", + [ETHTOOL_LINK_MODE_25000baseSR_Full_BIT] = "25000basesr-full", + [ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT] = "50000basecr2-full", + [ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT] = "50000basekr2-full", + [ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT] = "100000basekr4-full", + [ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT] = "100000basesr4-full", + [ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT] = "100000basecr4-full", + [ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT] = "100000baselr4-er4-full", + [ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT] = "50000basesr2-full", + [ETHTOOL_LINK_MODE_1000baseX_Full_BIT] = "1000basex-full", + [ETHTOOL_LINK_MODE_10000baseCR_Full_BIT] = "10000basecr-full", + [ETHTOOL_LINK_MODE_10000baseSR_Full_BIT] = "10000basesr-full", + [ETHTOOL_LINK_MODE_10000baseLR_Full_BIT] = "10000baselr-full", + [ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT] = "10000baselrm-full", + [ETHTOOL_LINK_MODE_10000baseER_Full_BIT] = "10000baseer-full", + [ETHTOOL_LINK_MODE_2500baseT_Full_BIT] = "2500baset-full", + [ETHTOOL_LINK_MODE_5000baseT_Full_BIT] = "5000baset-full", + [ETHTOOL_LINK_MODE_FEC_NONE_BIT] = "fec-none", + [ETHTOOL_LINK_MODE_FEC_RS_BIT] = "fec-rs", + [ETHTOOL_LINK_MODE_FEC_BASER_BIT] = "fec-baser", + [ETHTOOL_LINK_MODE_50000baseKR_Full_BIT] = "50000basekr_full", + [ETHTOOL_LINK_MODE_50000baseSR_Full_BIT] = "50000basesr_full", + [ETHTOOL_LINK_MODE_50000baseCR_Full_BIT] = "50000basecr_full", + [ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT] = "50000baselr_er_fr_full", + [ETHTOOL_LINK_MODE_50000baseDR_Full_BIT] = "50000basedr_full", + [ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT] = "100000basekr2_full", + [ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT] = "100000basesr2_full", + [ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT] = "100000basecr2_full", + [ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT] = "100000baselr2_er2_fr2_full", + [ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT] = "100000basedr2_full", + [ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT] = "200000basekr4_full", + [ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT] = "200000basesr4_full", + [ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT] = "200000basecr4_full", + [ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT] = "200000baselr4_er4_fr4_full", + [ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT] = "200000basedr4_full", +}; +/* Make sure the array is large enough to fit all bits */ +assert_cc((ELEMENTSOF(ethtool_link_mode_bit_table)-1) / 32 < N_ADVERTISE); + +DEFINE_STRING_TABLE_LOOKUP(ethtool_link_mode_bit, enum ethtool_link_mode_bit_indices); + +static int ethtool_connect_or_warn(int *ret, bool warn) { + int fd; + + assert_return(ret, -EINVAL); + + fd = socket_ioctl_fd(); + if (fd < 0) + return log_full_errno(warn ? LOG_WARNING: LOG_DEBUG, fd, + "ethtool: could not create control socket: %m"); + + *ret = fd; + + return 0; +} + +int ethtool_get_driver(int *fd, const char *ifname, char **ret) { + struct ethtool_drvinfo ecmd = { + .cmd = ETHTOOL_GDRVINFO + }; + struct ifreq ifr = { + .ifr_data = (void*) &ecmd + }; + char *d; + int r; + + if (*fd < 0) { + r = ethtool_connect_or_warn(fd, true); + if (r < 0) + return r; + } + + strscpy(ifr.ifr_name, IFNAMSIZ, ifname); + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + + d = strdup(ecmd.driver); + if (!d) + return -ENOMEM; + + *ret = d; + return 0; +} + +int ethtool_get_link_info(int *fd, const char *ifname, + int *ret_autonegotiation, size_t *ret_speed, + Duplex *ret_duplex, NetDevPort *ret_port) { + struct ethtool_cmd ecmd = { + .cmd = ETHTOOL_GSET, + }; + struct ifreq ifr = { + .ifr_data = (void*) &ecmd, + }; + int r; + + if (*fd < 0) { + r = ethtool_connect_or_warn(fd, false); + if (r < 0) + return r; + } + + strscpy(ifr.ifr_name, IFNAMSIZ, ifname); + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + + if (ret_autonegotiation) + *ret_autonegotiation = ecmd.autoneg; + + if (ret_speed) { + uint32_t speed; + + speed = ethtool_cmd_speed(&ecmd); + *ret_speed = speed == (uint32_t) SPEED_UNKNOWN ? + SIZE_MAX : (size_t) speed * 1000 * 1000; + } + + if (ret_duplex) + *ret_duplex = ecmd.duplex; + + if (ret_port) + *ret_port = ecmd.port; + + return 0; +} + +int ethtool_set_speed(int *fd, const char *ifname, unsigned speed, Duplex duplex) { + struct ethtool_cmd ecmd = { + .cmd = ETHTOOL_GSET + }; + struct ifreq ifr = { + .ifr_data = (void*) &ecmd + }; + bool need_update = false; + int r; + + if (speed == 0 && duplex == _DUP_INVALID) + return 0; + + if (*fd < 0) { + r = ethtool_connect_or_warn(fd, true); + if (r < 0) + return r; + } + + strscpy(ifr.ifr_name, IFNAMSIZ, ifname); + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + + if (ethtool_cmd_speed(&ecmd) != speed) { + ethtool_cmd_speed_set(&ecmd, speed); + need_update = true; + } + + switch (duplex) { + case DUP_HALF: + if (ecmd.duplex != DUPLEX_HALF) { + ecmd.duplex = DUPLEX_HALF; + need_update = true; + } + break; + case DUP_FULL: + if (ecmd.duplex != DUPLEX_FULL) { + ecmd.duplex = DUPLEX_FULL; + need_update = true; + } + break; + default: + break; + } + + if (need_update) { + ecmd.cmd = ETHTOOL_SSET; + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + } + + return 0; +} + +int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol) { + struct ethtool_wolinfo ecmd = { + .cmd = ETHTOOL_GWOL + }; + struct ifreq ifr = { + .ifr_data = (void*) &ecmd + }; + bool need_update = false; + int r; + + if (wol == _WOL_INVALID) + return 0; + + if (*fd < 0) { + r = ethtool_connect_or_warn(fd, true); + if (r < 0) + return r; + } + + strscpy(ifr.ifr_name, IFNAMSIZ, ifname); + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + + switch (wol) { + case WOL_PHY: + if (ecmd.wolopts != WAKE_PHY) { + ecmd.wolopts = WAKE_PHY; + need_update = true; + } + break; + case WOL_UCAST: + if (ecmd.wolopts != WAKE_UCAST) { + ecmd.wolopts = WAKE_UCAST; + need_update = true; + } + break; + case WOL_MCAST: + if (ecmd.wolopts != WAKE_MCAST) { + ecmd.wolopts = WAKE_MCAST; + need_update = true; + } + break; + case WOL_BCAST: + if (ecmd.wolopts != WAKE_BCAST) { + ecmd.wolopts = WAKE_BCAST; + need_update = true; + } + break; + case WOL_ARP: + if (ecmd.wolopts != WAKE_ARP) { + ecmd.wolopts = WAKE_ARP; + need_update = true; + } + break; + case WOL_MAGIC: + if (ecmd.wolopts != WAKE_MAGIC) { + ecmd.wolopts = WAKE_MAGIC; + need_update = true; + } + break; + case WOL_MAGICSECURE: + if (ecmd.wolopts != WAKE_MAGICSECURE) { + ecmd.wolopts = WAKE_MAGICSECURE; + need_update = true; + } + break; + case WOL_OFF: + if (ecmd.wolopts != 0) { + ecmd.wolopts = 0; + need_update = true; + } + break; + default: + break; + } + + if (need_update) { + ecmd.cmd = ETHTOOL_SWOL; + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + } + + return 0; +} + +int ethtool_set_nic_buffer_size(int *fd, const char *ifname, netdev_ring_param *ring) { + struct ethtool_ringparam ecmd = { + .cmd = ETHTOOL_GRINGPARAM + }; + struct ifreq ifr = { + .ifr_data = (void*) &ecmd + }; + bool need_update = false; + int r; + + if (*fd < 0) { + r = ethtool_connect_or_warn(fd, true); + if (r < 0) + return r; + } + + strscpy(ifr.ifr_name, IFNAMSIZ, ifname); + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + + if (ring->rx_pending_set) { + if (ecmd.rx_pending != ring->rx_pending) { + ecmd.rx_pending = ring->rx_pending; + need_update = true; + } + } + + if (ring->tx_pending_set) { + if (ecmd.tx_pending != ring->tx_pending) { + ecmd.tx_pending = ring->tx_pending; + need_update = true; + } + } + + if (need_update) { + ecmd.cmd = ETHTOOL_SRINGPARAM; + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + } + + return 0; +} + +static int get_stringset(int fd, struct ifreq *ifr, int stringset_id, struct ethtool_gstrings **gstrings) { + _cleanup_free_ struct ethtool_gstrings *strings = NULL; + struct { + struct ethtool_sset_info info; + uint32_t space; + } buffer = { + .info = { + .cmd = ETHTOOL_GSSET_INFO, + .sset_mask = UINT64_C(1) << stringset_id, + }, + }; + unsigned len; + int r; + + ifr->ifr_data = (void *) &buffer.info; + + r = ioctl(fd, SIOCETHTOOL, ifr); + if (r < 0) + return -errno; + + if (!buffer.info.sset_mask) + return -EINVAL; + + len = buffer.info.data[0]; + + strings = malloc0(sizeof(struct ethtool_gstrings) + len * ETH_GSTRING_LEN); + if (!strings) + return -ENOMEM; + + strings->cmd = ETHTOOL_GSTRINGS; + strings->string_set = stringset_id; + strings->len = len; + + ifr->ifr_data = (void *) strings; + + r = ioctl(fd, SIOCETHTOOL, ifr); + if (r < 0) + return -errno; + + *gstrings = TAKE_PTR(strings); + + return 0; +} + +static int find_feature_index(struct ethtool_gstrings *strings, const char *feature) { + unsigned i; + + for (i = 0; i < strings->len; i++) { + if (streq((char *) &strings->data[i * ETH_GSTRING_LEN], feature)) + return i; + } + + return -ENODATA; +} + +int ethtool_set_features(int *fd, const char *ifname, int *features) { + _cleanup_free_ struct ethtool_gstrings *strings = NULL; + struct ethtool_sfeatures *sfeatures; + int block, bit, i, r; + struct ifreq ifr = {}; + + if (*fd < 0) { + r = ethtool_connect_or_warn(fd, true); + if (r < 0) + return r; + } + + strscpy(ifr.ifr_name, IFNAMSIZ, ifname); + + r = get_stringset(*fd, &ifr, ETH_SS_FEATURES, &strings); + if (r < 0) + return log_warning_errno(r, "ethtool: could not get ethtool features for %s", ifname); + + sfeatures = alloca0(sizeof(struct ethtool_sfeatures) + DIV_ROUND_UP(strings->len, 32U) * sizeof(sfeatures->features[0])); + sfeatures->cmd = ETHTOOL_SFEATURES; + sfeatures->size = DIV_ROUND_UP(strings->len, 32U); + + for (i = 0; i < _NET_DEV_FEAT_MAX; i++) { + + if (features[i] != -1) { + + r = find_feature_index(strings, netdev_feature_table[i]); + if (r < 0) { + log_warning_errno(r, "ethtool: could not find feature: %s", netdev_feature_table[i]); + continue; + } + + block = r / 32; + bit = r % 32; + + sfeatures->features[block].valid |= 1 << bit; + + if (features[i]) + sfeatures->features[block].requested |= 1 << bit; + else + sfeatures->features[block].requested &= ~(1 << bit); + } + } + + ifr.ifr_data = (void *) sfeatures; + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return log_warning_errno(r, "ethtool: could not set ethtool features for %s", ifname); + + return 0; +} + +static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_usettings **g) { + struct ecmd { + struct ethtool_link_settings req; + __u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; + } ecmd = { + .req.cmd = ETHTOOL_GLINKSETTINGS, + }; + struct ethtool_link_usettings *u; + unsigned offset; + int r; + + /* The interaction user/kernel via the new API requires a small ETHTOOL_GLINKSETTINGS + handshake first to agree on the length of the link mode bitmaps. If kernel doesn't + agree with user, it returns the bitmap length it is expecting from user as a negative + length (and cmd field is 0). When kernel and user agree, kernel returns valid info in + all fields (ie. link mode length > 0 and cmd is ETHTOOL_GLINKSETTINGS). Based on + https://github.com/torvalds/linux/commit/3f1ac7a700d039c61d8d8b99f28d605d489a60cf + */ + + ifr->ifr_data = (void *) &ecmd; + + r = ioctl(fd, SIOCETHTOOL, ifr); + if (r < 0) + return -errno; + + if (ecmd.req.link_mode_masks_nwords >= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) + return -EOPNOTSUPP; + + ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords; + + ifr->ifr_data = (void *) &ecmd; + + r = ioctl(fd, SIOCETHTOOL, ifr); + if (r < 0) + return -errno; + + if (ecmd.req.link_mode_masks_nwords <= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) + return -EOPNOTSUPP; + + u = new(struct ethtool_link_usettings, 1); + if (!u) + return -ENOMEM; + + *u = (struct ethtool_link_usettings) { + .base = ecmd.req, + }; + + offset = 0; + memcpy(u->link_modes.supported, &ecmd.link_mode_data[offset], 4 * ecmd.req.link_mode_masks_nwords); + + offset += ecmd.req.link_mode_masks_nwords; + memcpy(u->link_modes.advertising, &ecmd.link_mode_data[offset], 4 * ecmd.req.link_mode_masks_nwords); + + offset += ecmd.req.link_mode_masks_nwords; + memcpy(u->link_modes.lp_advertising, &ecmd.link_mode_data[offset], 4 * ecmd.req.link_mode_masks_nwords); + + *g = u; + + return 0; +} + +static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **u) { + struct ethtool_link_usettings *e; + struct ethtool_cmd ecmd = { + .cmd = ETHTOOL_GSET, + }; + int r; + + ifr->ifr_data = (void *) &ecmd; + + r = ioctl(fd, SIOCETHTOOL, ifr); + if (r < 0) + return -errno; + + e = new(struct ethtool_link_usettings, 1); + if (!e) + return -ENOMEM; + + *e = (struct ethtool_link_usettings) { + .base.cmd = ETHTOOL_GSET, + .base.link_mode_masks_nwords = 1, + .base.speed = ethtool_cmd_speed(&ecmd), + .base.duplex = ecmd.duplex, + .base.port = ecmd.port, + .base.phy_address = ecmd.phy_address, + .base.autoneg = ecmd.autoneg, + .base.mdio_support = ecmd.mdio_support, + + .link_modes.supported[0] = ecmd.supported, + .link_modes.advertising[0] = ecmd.advertising, + .link_modes.lp_advertising[0] = ecmd.lp_advertising, + }; + + *u = e; + + return 0; +} + +static int set_slinksettings(int fd, struct ifreq *ifr, const struct ethtool_link_usettings *u) { + struct { + struct ethtool_link_settings req; + __u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; + } ecmd = {}; + unsigned offset; + int r; + + if (u->base.cmd != ETHTOOL_GLINKSETTINGS || u->base.link_mode_masks_nwords <= 0) + return -EINVAL; + + ecmd.req = u->base; + ecmd.req.cmd = ETHTOOL_SLINKSETTINGS; + offset = 0; + memcpy(&ecmd.link_mode_data[offset], u->link_modes.supported, 4 * ecmd.req.link_mode_masks_nwords); + + offset += ecmd.req.link_mode_masks_nwords; + memcpy(&ecmd.link_mode_data[offset], u->link_modes.advertising, 4 * ecmd.req.link_mode_masks_nwords); + + offset += ecmd.req.link_mode_masks_nwords; + memcpy(&ecmd.link_mode_data[offset], u->link_modes.lp_advertising, 4 * ecmd.req.link_mode_masks_nwords); + + ifr->ifr_data = (void *) &ecmd; + + r = ioctl(fd, SIOCETHTOOL, ifr); + if (r < 0) + return -errno; + + return 0; +} + +static int set_sset(int fd, struct ifreq *ifr, const struct ethtool_link_usettings *u) { + struct ethtool_cmd ecmd = { + .cmd = ETHTOOL_SSET, + }; + int r; + + if (u->base.cmd != ETHTOOL_GSET || u->base.link_mode_masks_nwords <= 0) + return -EINVAL; + + ecmd.supported = u->link_modes.supported[0]; + ecmd.advertising = u->link_modes.advertising[0]; + ecmd.lp_advertising = u->link_modes.lp_advertising[0]; + + ethtool_cmd_speed_set(&ecmd, u->base.speed); + + ecmd.duplex = u->base.duplex; + ecmd.port = u->base.port; + ecmd.phy_address = u->base.phy_address; + ecmd.autoneg = u->base.autoneg; + ecmd.mdio_support = u->base.mdio_support; + ecmd.eth_tp_mdix = u->base.eth_tp_mdix; + ecmd.eth_tp_mdix_ctrl = u->base.eth_tp_mdix_ctrl; + + ifr->ifr_data = (void *) &ecmd; + + r = ioctl(fd, SIOCETHTOOL, ifr); + if (r < 0) + return -errno; + + return 0; +} + +/* If autonegotiation is disabled, the speed and duplex represent the fixed link + * mode and are writable if the driver supports multiple link modes. If it is + * enabled then they are read-only. If the link is up they represent the negotiated + * link mode; if the link is down, the speed is 0, %SPEED_UNKNOWN or the highest + * enabled speed and @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode. + */ +int ethtool_set_glinksettings( + int *fd, + const char *ifname, + int autonegotiation, + uint32_t advertise[static N_ADVERTISE], + size_t speed, + Duplex duplex, + NetDevPort port) { + _cleanup_free_ struct ethtool_link_usettings *u = NULL; + struct ifreq ifr = {}; + int r; + + assert(advertise); + + if (autonegotiation != AUTONEG_DISABLE && memeqzero(advertise, sizeof(uint32_t) * N_ADVERTISE)) { + log_info("ethtool: autonegotiation is unset or enabled, the speed and duplex are not writable."); + return 0; + } + + if (*fd < 0) { + r = ethtool_connect_or_warn(fd, true); + if (r < 0) + return r; + } + + strscpy(ifr.ifr_name, IFNAMSIZ, ifname); + + r = get_glinksettings(*fd, &ifr, &u); + if (r < 0) { + r = get_gset(*fd, &ifr, &u); + if (r < 0) + return log_warning_errno(r, "ethtool: Cannot get device settings for %s : %m", ifname); + } + + if (speed > 0) + u->base.speed = DIV_ROUND_UP(speed, 1000000); + + if (duplex != _DUP_INVALID) + u->base.duplex = duplex; + + if (port != _NET_DEV_PORT_INVALID) + u->base.port = port; + + if (autonegotiation >= 0) + u->base.autoneg = autonegotiation; + + if (!memeqzero(advertise, sizeof(uint32_t) * N_ADVERTISE)) { + u->base.autoneg = AUTONEG_ENABLE; + memcpy(&u->link_modes.advertising, advertise, sizeof(uint32_t) * N_ADVERTISE); + memzero((uint8_t*) &u->link_modes.advertising + sizeof(uint32_t) * N_ADVERTISE, + ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES - sizeof(uint32_t) * N_ADVERTISE); + } + + if (u->base.cmd == ETHTOOL_GLINKSETTINGS) + r = set_slinksettings(*fd, &ifr, u); + else + r = set_sset(*fd, &ifr, u); + if (r < 0) + return log_warning_errno(r, "ethtool: Cannot set device settings for %s: %m", ifname); + + return r; +} + +int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels) { + struct ethtool_channels ecmd = { + .cmd = ETHTOOL_GCHANNELS + }; + struct ifreq ifr = { + .ifr_data = (void*) &ecmd + }; + + bool need_update = false; + int r; + + if (*fd < 0) { + r = ethtool_connect_or_warn(fd, true); + if (r < 0) + return r; + } + + strscpy(ifr.ifr_name, IFNAMSIZ, ifname); + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + + if (channels->rx_count_set && ecmd.rx_count != channels->rx_count) { + ecmd.rx_count = channels->rx_count; + need_update = true; + } + + if (channels->tx_count_set && ecmd.tx_count != channels->tx_count) { + ecmd.tx_count = channels->tx_count; + need_update = true; + } + + if (channels->other_count_set && ecmd.other_count != channels->other_count) { + ecmd.other_count = channels->other_count; + need_update = true; + } + + if (channels->combined_count_set && ecmd.combined_count != channels->combined_count) { + ecmd.combined_count = channels->combined_count; + need_update = true; + } + + if (need_update) { + ecmd.cmd = ETHTOOL_SCHANNELS; + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) + return -errno; + } + + return 0; +} + +int config_parse_channel(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + netdev_channels *channels = data; + uint32_t k; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou32(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse channel value, ignoring: %s", rvalue); + return 0; + } + + if (k < 1) { + log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid %s value, ignoring: %s", lvalue, rvalue); + return 0; + } + + if (streq(lvalue, "RxChannels")) { + channels->rx_count = k; + channels->rx_count_set = true; + } else if (streq(lvalue, "TxChannels")) { + channels->tx_count = k; + channels->tx_count_set = true; + } else if (streq(lvalue, "OtherChannels")) { + channels->other_count = k; + channels->other_count_set = true; + } else if (streq(lvalue, "CombinedChannels")) { + channels->combined_count = k; + channels->combined_count_set = true; + } + + return 0; +} + +int config_parse_advertise(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + uint32_t *advertise = data; + const char *p; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + /* Empty string resets the value. */ + memzero(advertise, sizeof(uint32_t) * N_ADVERTISE); + return 0; + } + + for (p = rvalue;;) { + _cleanup_free_ char *w = NULL; + enum ethtool_link_mode_bit_indices mode; + + r = extract_first_word(&p, &w, NULL, 0); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to split advertise modes '%s', ignoring: %m", rvalue); + break; + } + if (r == 0) + break; + + mode = ethtool_link_mode_bit_from_string(w); + /* We reuse the kernel provided enum which does not contain negative value. So, the cast + * below is mandatory. Otherwise, the check below always passes and access an invalid address. */ + if ((int) mode < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse advertise mode, ignoring: %s", w); + continue; + } + + advertise[mode / 32] |= 1UL << (mode % 32); + } + + return 0; +} + +int config_parse_nic_buffer_size(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + netdev_ring_param *ring = data; + uint32_t k; + int r; + + assert(filename); + assert(section); + assert(lvalue); + assert(rvalue); + assert(data); + + r = safe_atou32(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse interface buffer value, ignoring: %s", rvalue); + return 0; + } + + if (k < 1) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid %s value, ignoring: %s", lvalue, rvalue); + return 0; + } + + if (streq(lvalue, "RxBufferSize")) { + ring->rx_pending = k; + ring->rx_pending_set = true; + } else if (streq(lvalue, "TxBufferSize")) { + ring->tx_pending = k; + ring->tx_pending_set = true; + } + + return 0; +} diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h new file mode 100644 index 00000000..d408bcd9 --- /dev/null +++ b/src/shared/ethtool-util.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "conf-parser.h" + +#define N_ADVERTISE 3 + +/* we can't use DUPLEX_ prefix, as it + * clashes with */ +typedef enum Duplex { + DUP_HALF = DUPLEX_HALF, + DUP_FULL = DUPLEX_FULL, + _DUP_MAX, + _DUP_INVALID = -1 +} Duplex; + +typedef enum WakeOnLan { + WOL_PHY, + WOL_UCAST, + WOL_MCAST, + WOL_BCAST, + WOL_ARP, + WOL_MAGIC, + WOL_MAGICSECURE, + WOL_OFF, + _WOL_MAX, + _WOL_INVALID = -1 +} WakeOnLan; + +typedef enum NetDevFeature { + NET_DEV_FEAT_GSO, + NET_DEV_FEAT_GRO, + NET_DEV_FEAT_LRO, + NET_DEV_FEAT_TSO, + NET_DEV_FEAT_TSO6, + _NET_DEV_FEAT_MAX, + _NET_DEV_FEAT_INVALID = -1 +} NetDevFeature; + +typedef enum NetDevPort { + NET_DEV_PORT_TP = PORT_TP, + NET_DEV_PORT_AUI = PORT_AUI, + NET_DEV_PORT_MII = PORT_MII, + NET_DEV_PORT_FIBRE = PORT_FIBRE, + NET_DEV_PORT_BNC = PORT_BNC, + NET_DEV_PORT_DA = PORT_DA, + NET_DEV_PORT_NONE = PORT_NONE, + NET_DEV_PORT_OTHER = PORT_OTHER, + _NET_DEV_PORT_MAX, + _NET_DEV_PORT_INVALID = -1 +} NetDevPort; + +#define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32 (SCHAR_MAX) +#define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES (4 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32) + +/* layout of the struct passed from/to userland */ +struct ethtool_link_usettings { + struct ethtool_link_settings base; + + struct { + uint32_t supported[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; + uint32_t advertising[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; + uint32_t lp_advertising[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; + } link_modes; +}; + +typedef struct netdev_channels { + uint32_t rx_count; + uint32_t tx_count; + uint32_t other_count; + uint32_t combined_count; + + bool rx_count_set; + bool tx_count_set; + bool other_count_set; + bool combined_count_set; +} netdev_channels; + +typedef struct netdev_ring_param { + uint32_t rx_pending; + uint32_t tx_pending; + + bool rx_pending_set; + bool tx_pending_set; +} netdev_ring_param; + +int ethtool_get_driver(int *fd, const char *ifname, char **ret); +int ethtool_get_link_info(int *fd, const char *ifname, + int *ret_autonegotiation, size_t *ret_speed, + Duplex *ret_duplex, NetDevPort *ret_port); +int ethtool_set_speed(int *fd, const char *ifname, unsigned speed, Duplex duplex); +int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol); +int ethtool_set_nic_buffer_size(int *fd, const char *ifname, netdev_ring_param *ring); +int ethtool_set_features(int *fd, const char *ifname, int *features); +int ethtool_set_glinksettings(int *fd, const char *ifname, + int autonegotiation, uint32_t advertise[static N_ADVERTISE], + size_t speed, Duplex duplex, NetDevPort port); +int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels); + +const char *duplex_to_string(Duplex d) _const_; +Duplex duplex_from_string(const char *d) _pure_; + +const char *wol_to_string(WakeOnLan wol) _const_; +WakeOnLan wol_from_string(const char *wol) _pure_; + +const char *port_to_string(NetDevPort port) _const_; +NetDevPort port_from_string(const char *port) _pure_; + +const char *ethtool_link_mode_bit_to_string(enum ethtool_link_mode_bit_indices val) _const_; +enum ethtool_link_mode_bit_indices ethtool_link_mode_bit_from_string(const char *str) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_duplex); +CONFIG_PARSER_PROTOTYPE(config_parse_wol); +CONFIG_PARSER_PROTOTYPE(config_parse_port); +CONFIG_PARSER_PROTOTYPE(config_parse_channel); +CONFIG_PARSER_PROTOTYPE(config_parse_advertise); +CONFIG_PARSER_PROTOTYPE(config_parse_nic_buffer_size); diff --git a/src/shared/exec-util.c b/src/shared/exec-util.c new file mode 100644 index 00000000..8fb936dc --- /dev/null +++ b/src/shared/exec-util.c @@ -0,0 +1,446 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "conf-files.h" +#include "env-file.h" +#include "env-util.h" +#include "exec-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "hashmap.h" +#include "macro.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "serialize.h" +#include "set.h" +#include "signal-util.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "util.h" + +/* Put this test here for a lack of better place */ +assert_cc(EAGAIN == EWOULDBLOCK); + +static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) { + + pid_t _pid; + int r; + + if (null_or_empty_path(path)) { + log_debug("%s is empty (a mask).", path); + return 0; + } + + r = safe_fork("(direxec)", FORK_DEATHSIG|FORK_LOG, &_pid); + if (r < 0) + return r; + if (r == 0) { + char *_argv[2]; + + if (stdout_fd >= 0) { + r = rearrange_stdio(STDIN_FILENO, stdout_fd, STDERR_FILENO); + if (r < 0) + _exit(EXIT_FAILURE); + } + + (void) rlimit_nofile_safe(); + + if (!argv) { + _argv[0] = (char*) path; + _argv[1] = NULL; + argv = _argv; + } else + argv[0] = (char*) path; + + execv(path, argv); + log_error_errno(errno, "Failed to execute %s: %m", path); + _exit(EXIT_FAILURE); + } + + *pid = _pid; + return 1; +} + +static int do_execute( + char **directories, + usec_t timeout, + gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX], + void* const callback_args[_STDOUT_CONSUME_MAX], + int output_fd, + char *argv[], + char *envp[], + ExecDirFlags flags) { + + _cleanup_hashmap_free_free_ Hashmap *pids = NULL; + _cleanup_strv_free_ char **paths = NULL; + char **path, **e; + int r; + bool parallel_execution; + + /* We fork this all off from a child process so that we can somewhat cleanly make + * use of SIGALRM to set a time limit. + * + * We attempt to perform parallel execution if configured by the user, however + * if `callbacks` is nonnull, execution must be serial. + */ + parallel_execution = FLAGS_SET(flags, EXEC_DIR_PARALLEL) && !callbacks; + + r = conf_files_list_strv(&paths, NULL, NULL, CONF_FILES_EXECUTABLE|CONF_FILES_REGULAR|CONF_FILES_FILTER_MASKED, (const char* const*) directories); + if (r < 0) + return log_error_errno(r, "Failed to enumerate executables: %m"); + + if (parallel_execution) { + pids = hashmap_new(NULL); + if (!pids) + return log_oom(); + } + + /* Abort execution of this process after the timeout. We simply rely on SIGALRM as + * default action terminating the process, and turn on alarm(). */ + + if (timeout != USEC_INFINITY) + alarm(DIV_ROUND_UP(timeout, USEC_PER_SEC)); + + STRV_FOREACH(e, envp) + if (putenv(*e) != 0) + return log_error_errno(errno, "Failed to set environment variable: %m"); + + STRV_FOREACH(path, paths) { + _cleanup_free_ char *t = NULL; + _cleanup_close_ int fd = -1; + pid_t pid; + + t = strdup(*path); + if (!t) + return log_oom(); + + if (callbacks) { + fd = open_serialization_fd(basename(*path)); + if (fd < 0) + return log_error_errno(fd, "Failed to open serialization file: %m"); + } + + r = do_spawn(t, argv, fd, &pid); + if (r <= 0) + continue; + + if (parallel_execution) { + r = hashmap_put(pids, PID_TO_PTR(pid), t); + if (r < 0) + return log_oom(); + t = NULL; + } else { + r = wait_for_terminate_and_check(t, pid, WAIT_LOG); + if (FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS)) { + if (r < 0) + continue; + } else if (r > 0) + return r; + + if (callbacks) { + if (lseek(fd, 0, SEEK_SET) < 0) + return log_error_errno(errno, "Failed to seek on serialization fd: %m"); + + r = callbacks[STDOUT_GENERATE](fd, callback_args[STDOUT_GENERATE]); + fd = -1; + if (r < 0) + return log_error_errno(r, "Failed to process output from %s: %m", *path); + } + } + } + + if (callbacks) { + r = callbacks[STDOUT_COLLECT](output_fd, callback_args[STDOUT_COLLECT]); + if (r < 0) + return log_error_errno(r, "Callback two failed: %m"); + } + + while (!hashmap_isempty(pids)) { + _cleanup_free_ char *t = NULL; + pid_t pid; + + pid = PTR_TO_PID(hashmap_first_key(pids)); + assert(pid > 0); + + t = hashmap_remove(pids, PID_TO_PTR(pid)); + assert(t); + + r = wait_for_terminate_and_check(t, pid, WAIT_LOG); + if (!FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS) && r > 0) + return r; + } + + return 0; +} + +int execute_directories( + const char* const* directories, + usec_t timeout, + gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX], + void* const callback_args[_STDOUT_CONSUME_MAX], + char *argv[], + char *envp[], + ExecDirFlags flags) { + + char **dirs = (char**) directories; + _cleanup_close_ int fd = -1; + char *name; + int r; + pid_t executor_pid; + + assert(!strv_isempty(dirs)); + + name = basename(dirs[0]); + assert(!isempty(name)); + + if (callbacks) { + assert(callback_args); + assert(callbacks[STDOUT_GENERATE]); + assert(callbacks[STDOUT_COLLECT]); + assert(callbacks[STDOUT_CONSUME]); + + fd = open_serialization_fd(name); + if (fd < 0) + return log_error_errno(fd, "Failed to open serialization file: %m"); + } + + /* Executes all binaries in the directories serially or in parallel and waits for + * them to finish. Optionally a timeout is applied. If a file with the same name + * exists in more than one directory, the earliest one wins. */ + + r = safe_fork("(sd-executor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &executor_pid); + if (r < 0) + return r; + if (r == 0) { + r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv, envp, flags); + _exit(r < 0 ? EXIT_FAILURE : r); + } + + r = wait_for_terminate_and_check("(sd-executor)", executor_pid, 0); + if (r < 0) + return r; + if (!FLAGS_SET(flags, EXEC_DIR_IGNORE_ERRORS) && r > 0) + return r; + + if (!callbacks) + return 0; + + if (lseek(fd, 0, SEEK_SET) < 0) + return log_error_errno(errno, "Failed to rewind serialization fd: %m"); + + r = callbacks[STDOUT_CONSUME](fd, callback_args[STDOUT_CONSUME]); + fd = -1; + if (r < 0) + return log_error_errno(r, "Failed to parse returned data: %m"); + return 0; +} + +static int gather_environment_generate(int fd, void *arg) { + char ***env = arg, **x, **y; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_strv_free_ char **new = NULL; + int r; + + /* Read a series of VAR=value assignments from fd, use them to update the list of + * variables in env. Also update the exported environment. + * + * fd is always consumed, even on error. + */ + + assert(env); + + f = fdopen(fd, "r"); + if (!f) { + safe_close(fd); + return -errno; + } + + r = load_env_file_pairs(f, NULL, &new); + if (r < 0) + return r; + + STRV_FOREACH_PAIR(x, y, new) { + char *p; + + if (!env_name_is_valid(*x)) { + log_warning("Invalid variable assignment \"%s=...\", ignoring.", *x); + continue; + } + + p = strjoin(*x, "=", *y); + if (!p) + return -ENOMEM; + + r = strv_env_replace(env, p); + if (r < 0) + return r; + + if (setenv(*x, *y, true) < 0) + return -errno; + } + + return r; +} + +static int gather_environment_collect(int fd, void *arg) { + _cleanup_fclose_ FILE *f = NULL; + char ***env = arg; + int r; + + /* Write out a series of env=cescape(VAR=value) assignments to fd. */ + + assert(env); + + f = fdopen(fd, "w"); + if (!f) { + safe_close(fd); + return -errno; + } + + r = serialize_strv(f, "env", *env); + if (r < 0) + return r; + + r = fflush_and_check(f); + if (r < 0) + return r; + + return 0; +} + +static int gather_environment_consume(int fd, void *arg) { + _cleanup_fclose_ FILE *f = NULL; + char ***env = arg; + int r = 0; + + /* Read a series of env=cescape(VAR=value) assignments from fd into env. */ + + assert(env); + + f = fdopen(fd, "r"); + if (!f) { + safe_close(fd); + return -errno; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *v; + int k; + + k = read_line(f, LONG_LINE_MAX, &line); + if (k < 0) + return k; + if (k == 0) + break; + + v = startswith(line, "env="); + if (!v) { + log_debug("Serialization line \"%s\" unexpectedly didn't start with \"env=\".", line); + if (r == 0) + r = -EINVAL; + + continue; + } + + k = deserialize_environment(v, env); + if (k < 0) { + log_debug_errno(k, "Invalid serialization line \"%s\": %m", line); + + if (r == 0) + r = k; + } + } + + return r; +} + +int exec_command_flags_from_strv(char **ex_opts, ExecCommandFlags *flags) { + ExecCommandFlags ex_flag, ret_flags = 0; + char **opt; + + assert(flags); + + STRV_FOREACH(opt, ex_opts) { + ex_flag = exec_command_flags_from_string(*opt); + if (ex_flag >= 0) + ret_flags |= ex_flag; + else + return -EINVAL; + } + + *flags = ret_flags; + + return 0; +} + +int exec_command_flags_to_strv(ExecCommandFlags flags, char ***ex_opts) { + _cleanup_strv_free_ char **ret_opts = NULL; + ExecCommandFlags it = flags; + const char *str; + int i, r; + + assert(ex_opts); + + for (i = 0; it != 0; it &= ~(1 << i), i++) { + if (FLAGS_SET(flags, (1 << i))) { + str = exec_command_flags_to_string(1 << i); + if (!str) + return -EINVAL; + + r = strv_extend(&ret_opts, str); + if (r < 0) + return r; + } + } + + *ex_opts = TAKE_PTR(ret_opts); + + return 0; +} + +const gather_stdout_callback_t gather_environment[] = { + gather_environment_generate, + gather_environment_collect, + gather_environment_consume, +}; + +static const char* const exec_command_strings[] = { + "ignore-failure", /* EXEC_COMMAND_IGNORE_FAILURE */ + "privileged", /* EXEC_COMMAND_FULLY_PRIVILEGED */ + "no-setuid", /* EXEC_COMMAND_NO_SETUID */ + "ambient", /* EXEC_COMMAND_AMBIENT_MAGIC */ + "no-env-expand", /* EXEC_COMMAND_NO_ENV_EXPAND */ +}; + +const char* exec_command_flags_to_string(ExecCommandFlags i) { + size_t idx; + + for (idx = 0; idx < ELEMENTSOF(exec_command_strings); idx++) + if (i == (1 << idx)) + return exec_command_strings[idx]; + + return NULL; +} + +ExecCommandFlags exec_command_flags_from_string(const char *s) { + ssize_t idx; + + idx = string_table_lookup(exec_command_strings, ELEMENTSOF(exec_command_strings), s); + + if (idx < 0) + return _EXEC_COMMAND_FLAGS_INVALID; + else + return 1 << idx; +} diff --git a/src/shared/exec-util.h b/src/shared/exec-util.h new file mode 100644 index 00000000..9fe90125 --- /dev/null +++ b/src/shared/exec-util.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "time-util.h" + +typedef int (*gather_stdout_callback_t) (int fd, void *arg); + +enum { + STDOUT_GENERATE, /* from generators to helper process */ + STDOUT_COLLECT, /* from helper process to main process */ + STDOUT_CONSUME, /* process data in main process */ + _STDOUT_CONSUME_MAX, +}; + +typedef enum { + EXEC_DIR_NONE = 0, /* No execdir flags */ + EXEC_DIR_PARALLEL = 1 << 0, /* Execute scripts in parallel, if possible */ + EXEC_DIR_IGNORE_ERRORS = 1 << 1, /* Ignore non-zero exit status of scripts */ +} ExecDirFlags; + +typedef enum ExecCommandFlags { + EXEC_COMMAND_IGNORE_FAILURE = 1 << 0, + EXEC_COMMAND_FULLY_PRIVILEGED = 1 << 1, + EXEC_COMMAND_NO_SETUID = 1 << 2, + EXEC_COMMAND_AMBIENT_MAGIC = 1 << 3, + EXEC_COMMAND_NO_ENV_EXPAND = 1 << 4, + _EXEC_COMMAND_FLAGS_INVALID = -1, +} ExecCommandFlags; + +int execute_directories( + const char* const* directories, + usec_t timeout, + gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX], + void* const callback_args[_STDOUT_CONSUME_MAX], + char *argv[], + char *envp[], + ExecDirFlags flags); + +int exec_command_flags_from_strv(char **ex_opts, ExecCommandFlags *flags); +int exec_command_flags_to_strv(ExecCommandFlags flags, char ***ex_opts); + +extern const gather_stdout_callback_t gather_environment[_STDOUT_CONSUME_MAX]; + +const char* exec_command_flags_to_string(ExecCommandFlags i); +ExecCommandFlags exec_command_flags_from_string(const char *s); diff --git a/src/shared/exit-status.c b/src/shared/exit-status.c new file mode 100644 index 00000000..82b1422b --- /dev/null +++ b/src/shared/exit-status.c @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "exit-status.h" +#include "macro.h" +#include "parse-util.h" +#include "set.h" +#include "string-util.h" + +const ExitStatusMapping exit_status_mappings[256] = { + /* Exit status ranges: + * + * 0…1 │ ISO C, EXIT_SUCCESS + EXIT_FAILURE + * 2…7 │ LSB exit codes for init scripts + * 8…63 │ (Currently unmapped) + * 64…78 │ BSD defined exit codes + * 79…199 │ (Currently unmapped) + * 200…242 │ systemd's private error codes (might be extended to 254 in future development) + * 243…254 │ (Currently unmapped, but see above) + * + * 255 │ EXIT_EXCEPTION (We use this to propagate exit-by-signal events. It's frequently used by others apps (like bash) + * │ to indicate exit reason that cannot really be expressed in a single exit status value — such as a propagated + * │ signal or such, and we follow that logic here.) + */ + + [EXIT_SUCCESS] = { "SUCCESS", EXIT_STATUS_LIBC }, + [EXIT_FAILURE] = { "FAILURE", EXIT_STATUS_LIBC }, + + [EXIT_CHDIR] = { "CHDIR", EXIT_STATUS_SYSTEMD }, + [EXIT_NICE] = { "NICE", EXIT_STATUS_SYSTEMD }, + [EXIT_FDS] = { "FDS", EXIT_STATUS_SYSTEMD }, + [EXIT_EXEC] = { "EXEC", EXIT_STATUS_SYSTEMD }, + [EXIT_MEMORY] = { "MEMORY", EXIT_STATUS_SYSTEMD }, + [EXIT_LIMITS] = { "LIMITS", EXIT_STATUS_SYSTEMD }, + [EXIT_OOM_ADJUST] = { "OOM_ADJUST", EXIT_STATUS_SYSTEMD }, + [EXIT_SIGNAL_MASK] = { "SIGNAL_MASK", EXIT_STATUS_SYSTEMD }, + [EXIT_STDIN] = { "STDIN", EXIT_STATUS_SYSTEMD }, + [EXIT_STDOUT] = { "STDOUT", EXIT_STATUS_SYSTEMD }, + [EXIT_CHROOT] = { "CHROOT", EXIT_STATUS_SYSTEMD }, + [EXIT_IOPRIO] = { "IOPRIO", EXIT_STATUS_SYSTEMD }, + [EXIT_TIMERSLACK] = { "TIMERSLACK", EXIT_STATUS_SYSTEMD }, + [EXIT_SECUREBITS] = { "SECUREBITS", EXIT_STATUS_SYSTEMD }, + [EXIT_SETSCHEDULER] = { "SETSCHEDULER", EXIT_STATUS_SYSTEMD }, + [EXIT_CPUAFFINITY] = { "CPUAFFINITY", EXIT_STATUS_SYSTEMD }, + [EXIT_GROUP] = { "GROUP", EXIT_STATUS_SYSTEMD }, + [EXIT_USER] = { "USER", EXIT_STATUS_SYSTEMD }, + [EXIT_CAPABILITIES] = { "CAPABILITIES", EXIT_STATUS_SYSTEMD }, + [EXIT_CGROUP] = { "CGROUP", EXIT_STATUS_SYSTEMD }, + [EXIT_SETSID] = { "SETSID", EXIT_STATUS_SYSTEMD }, + [EXIT_CONFIRM] = { "CONFIRM", EXIT_STATUS_SYSTEMD }, + [EXIT_STDERR] = { "STDERR", EXIT_STATUS_SYSTEMD }, + [EXIT_PAM] = { "PAM", EXIT_STATUS_SYSTEMD }, + [EXIT_NETWORK] = { "NETWORK", EXIT_STATUS_SYSTEMD }, + [EXIT_NAMESPACE] = { "NAMESPACE", EXIT_STATUS_SYSTEMD }, + [EXIT_NO_NEW_PRIVILEGES] = { "NO_NEW_PRIVILEGES", EXIT_STATUS_SYSTEMD }, + [EXIT_SECCOMP] = { "SECCOMP", EXIT_STATUS_SYSTEMD }, + [EXIT_SELINUX_CONTEXT] = { "SELINUX_CONTEXT", EXIT_STATUS_SYSTEMD }, + [EXIT_PERSONALITY] = { "PERSONALITY", EXIT_STATUS_SYSTEMD }, + [EXIT_APPARMOR_PROFILE] = { "APPARMOR", EXIT_STATUS_SYSTEMD }, + [EXIT_ADDRESS_FAMILIES] = { "ADDRESS_FAMILIES", EXIT_STATUS_SYSTEMD }, + [EXIT_RUNTIME_DIRECTORY] = { "RUNTIME_DIRECTORY", EXIT_STATUS_SYSTEMD }, + [EXIT_CHOWN] = { "CHOWN", EXIT_STATUS_SYSTEMD }, + [EXIT_SMACK_PROCESS_LABEL] = { "SMACK_PROCESS_LABEL", EXIT_STATUS_SYSTEMD }, + [EXIT_KEYRING] = { "KEYRING", EXIT_STATUS_SYSTEMD }, + [EXIT_STATE_DIRECTORY] = { "STATE_DIRECTORY", EXIT_STATUS_SYSTEMD }, + [EXIT_CACHE_DIRECTORY] = { "CACHE_DIRECTORY", EXIT_STATUS_SYSTEMD }, + [EXIT_LOGS_DIRECTORY] = { "LOGS_DIRECTORY", EXIT_STATUS_SYSTEMD }, + [EXIT_CONFIGURATION_DIRECTORY] = { "CONFIGURATION_DIRECTORY", EXIT_STATUS_SYSTEMD }, + [EXIT_NUMA_POLICY] = { "NUMA_POLICY", EXIT_STATUS_SYSTEMD }, + [EXIT_EXCEPTION] = { "EXCEPTION", EXIT_STATUS_SYSTEMD }, + + [EXIT_INVALIDARGUMENT] = { "INVALIDARGUMENT", EXIT_STATUS_LSB }, + [EXIT_NOTIMPLEMENTED] = { "NOTIMPLEMENTED", EXIT_STATUS_LSB }, + [EXIT_NOPERMISSION] = { "NOPERMISSION", EXIT_STATUS_LSB }, + [EXIT_NOTINSTALLED] = { "NOTINSTALLED", EXIT_STATUS_LSB }, + [EXIT_NOTCONFIGURED] = { "NOTCONFIGURED", EXIT_STATUS_LSB }, + [EXIT_NOTRUNNING] = { "NOTRUNNING", EXIT_STATUS_LSB }, + + [EX_USAGE] = { "USAGE", EXIT_STATUS_BSD }, + [EX_DATAERR] = { "DATAERR", EXIT_STATUS_BSD }, + [EX_NOINPUT] = { "NOINPUT", EXIT_STATUS_BSD }, + [EX_NOUSER] = { "NOUSER", EXIT_STATUS_BSD }, + [EX_NOHOST] = { "NOHOST", EXIT_STATUS_BSD }, + [EX_UNAVAILABLE] = { "UNAVAILABLE", EXIT_STATUS_BSD }, + [EX_SOFTWARE] = { "SOFTWARE", EXIT_STATUS_BSD }, + [EX_OSERR] = { "OSERR", EXIT_STATUS_BSD }, + [EX_OSFILE] = { "OSFILE", EXIT_STATUS_BSD }, + [EX_CANTCREAT] = { "CANTCREAT", EXIT_STATUS_BSD }, + [EX_IOERR] = { "IOERR", EXIT_STATUS_BSD }, + [EX_TEMPFAIL] = { "TEMPFAIL", EXIT_STATUS_BSD }, + [EX_PROTOCOL] = { "PROTOCOL", EXIT_STATUS_BSD }, + [EX_NOPERM] = { "NOPERM", EXIT_STATUS_BSD }, + [EX_CONFIG] = { "CONFIG", EXIT_STATUS_BSD }, +}; + +const char* exit_status_to_string(int code, ExitStatusClass class) { + if (code < 0 || (size_t) code >= ELEMENTSOF(exit_status_mappings)) + return NULL; + return class & exit_status_mappings[code].class ? exit_status_mappings[code].name : NULL; +} + +const char* exit_status_class(int code) { + if (code < 0 || (size_t) code >= ELEMENTSOF(exit_status_mappings)) + return NULL; + + switch (exit_status_mappings[code].class) { + case EXIT_STATUS_LIBC: + return "libc"; + case EXIT_STATUS_SYSTEMD: + return "systemd"; + case EXIT_STATUS_LSB: + return "LSB"; + case EXIT_STATUS_BSD: + return "BSD"; + default: return NULL; + } +} + +int exit_status_from_string(const char *s) { + uint8_t val; + int r; + + for (size_t i = 0; i < ELEMENTSOF(exit_status_mappings); i++) + if (streq_ptr(s, exit_status_mappings[i].name)) + return i; + + r = safe_atou8(s, &val); + if (r < 0) + return r; + + return val; +} + +bool is_clean_exit(int code, int status, ExitClean clean, const ExitStatusSet *success_status) { + if (code == CLD_EXITED) + return status == 0 || + (success_status && + bitmap_isset(&success_status->status, status)); + + /* If a daemon does not implement handlers for some of the signals, we do not consider this an + unclean shutdown */ + if (code == CLD_KILLED) + return + (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) || + (success_status && + bitmap_isset(&success_status->signal, status)); + + return false; +} + +void exit_status_set_free(ExitStatusSet *x) { + assert(x); + + bitmap_clear(&x->status); + bitmap_clear(&x->signal); +} + +bool exit_status_set_is_empty(const ExitStatusSet *x) { + if (!x) + return true; + + return bitmap_isclear(&x->status) && bitmap_isclear(&x->signal); +} + +bool exit_status_set_test(const ExitStatusSet *x, int code, int status) { + if (code == CLD_EXITED && bitmap_isset(&x->status, status)) + return true; + + if (IN_SET(code, CLD_KILLED, CLD_DUMPED) && bitmap_isset(&x->signal, status)) + return true; + + return false; +} diff --git a/src/shared/exit-status.h b/src/shared/exit-status.h new file mode 100644 index 00000000..9ea147c8 --- /dev/null +++ b/src/shared/exit-status.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "bitmap.h" +#include "hashmap.h" +#include "macro.h" + +/* This defines pretty names for the LSB 'start' verb exit codes. Note that they shouldn't be confused with + * the LSB 'status' verb exit codes which are defined very differently. For details see: + * + * https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html + */ + +enum { + /* EXIT_SUCCESS defined by libc */ + /* EXIT_FAILURE defined by libc */ + EXIT_INVALIDARGUMENT = 2, + EXIT_NOTIMPLEMENTED = 3, + EXIT_NOPERMISSION = 4, + EXIT_NOTINSTALLED = 5, + EXIT_NOTCONFIGURED = 6, + EXIT_NOTRUNNING = 7, + + /* BSD's sysexits.h defines a couple EX_xyz exit codes in the range 64 … 78 */ + + /* The LSB suggests that error codes >= 200 are "reserved". We use them here under the assumption + * that they hence are unused by init scripts. */ + EXIT_CHDIR = 200, + EXIT_NICE, + EXIT_FDS, + EXIT_EXEC, + EXIT_MEMORY, + EXIT_LIMITS, + EXIT_OOM_ADJUST, + EXIT_SIGNAL_MASK, + EXIT_STDIN, + EXIT_STDOUT, + EXIT_CHROOT, /* 210 */ + EXIT_IOPRIO, + EXIT_TIMERSLACK, + EXIT_SECUREBITS, + EXIT_SETSCHEDULER, + EXIT_CPUAFFINITY, + EXIT_GROUP, + EXIT_USER, + EXIT_CAPABILITIES, + EXIT_CGROUP, + EXIT_SETSID, /* 220 */ + EXIT_CONFIRM, + EXIT_STDERR, + _EXIT_RESERVED, /* used to be tcpwrap, don't reuse! */ + EXIT_PAM, + EXIT_NETWORK, + EXIT_NAMESPACE, + EXIT_NO_NEW_PRIVILEGES, + EXIT_SECCOMP, + EXIT_SELINUX_CONTEXT, + EXIT_PERSONALITY, /* 230 */ + EXIT_APPARMOR_PROFILE, + EXIT_ADDRESS_FAMILIES, + EXIT_RUNTIME_DIRECTORY, + _EXIT_RESERVED2, /* used to be used by kdbus, don't reuse */ + EXIT_CHOWN, + EXIT_SMACK_PROCESS_LABEL, + EXIT_KEYRING, + EXIT_STATE_DIRECTORY, + EXIT_CACHE_DIRECTORY, + EXIT_LOGS_DIRECTORY, /* 240 */ + EXIT_CONFIGURATION_DIRECTORY, + EXIT_NUMA_POLICY, + + EXIT_EXCEPTION = 255, /* Whenever we want to propagate an abnormal/signal exit, in line with bash */ +}; + +typedef enum ExitStatusClass { + EXIT_STATUS_LIBC = 1 << 0, /* libc EXIT_STATUS/EXIT_FAILURE */ + EXIT_STATUS_SYSTEMD = 1 << 1, /* systemd's own exit codes */ + EXIT_STATUS_LSB = 1 << 2, /* LSB exit codes */ + EXIT_STATUS_BSD = 1 << 3, /* BSD (EX_xyz) exit codes */ + EXIT_STATUS_FULL = EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD | EXIT_STATUS_LSB | EXIT_STATUS_BSD, +} ExitStatusClass; + +typedef struct ExitStatusSet { + Bitmap status; + Bitmap signal; +} ExitStatusSet; + +const char* exit_status_to_string(int code, ExitStatusClass class) _const_; +const char* exit_status_class(int code) _const_; +int exit_status_from_string(const char *s) _pure_; + +typedef struct ExitStatusMapping { + const char *name; + ExitStatusClass class; +} ExitStatusMapping; + +extern const ExitStatusMapping exit_status_mappings[256]; + +typedef enum ExitClean { + EXIT_CLEAN_DAEMON, + EXIT_CLEAN_COMMAND, +} ExitClean; + +bool is_clean_exit(int code, int status, ExitClean clean, const ExitStatusSet *success_status); + +void exit_status_set_free(ExitStatusSet *x); +bool exit_status_set_is_empty(const ExitStatusSet *x); +bool exit_status_set_test(const ExitStatusSet *x, int code, int status); diff --git a/src/shared/fdset.c b/src/shared/fdset.c new file mode 100644 index 00000000..89d118a3 --- /dev/null +++ b/src/shared/fdset.c @@ -0,0 +1,254 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fdset.h" +#include "log.h" +#include "macro.h" +#include "parse-util.h" +#include "path-util.h" +#include "set.h" + +#define MAKE_SET(s) ((Set*) s) +#define MAKE_FDSET(s) ((FDSet*) s) + +FDSet *fdset_new(void) { + return MAKE_FDSET(set_new(NULL)); +} + +int fdset_new_array(FDSet **ret, const int *fds, size_t n_fds) { + size_t i; + FDSet *s; + int r; + + assert(ret); + + s = fdset_new(); + if (!s) + return -ENOMEM; + + for (i = 0; i < n_fds; i++) { + + r = fdset_put(s, fds[i]); + if (r < 0) { + set_free(MAKE_SET(s)); + return r; + } + } + + *ret = s; + return 0; +} + +void fdset_close(FDSet *s) { + void *p; + + while ((p = set_steal_first(MAKE_SET(s)))) { + /* Valgrind's fd might have ended up in this set here, due to fdset_new_fill(). We'll ignore + * all failures here, so that the EBADFD that valgrind will return us on close() doesn't + * influence us */ + + /* When reloading duplicates of the private bus connection fds and suchlike are closed here, + * which has no effect at all, since they are only duplicates. So don't be surprised about + * these log messages. */ + + log_debug("Closing set fd %i", PTR_TO_FD(p)); + (void) close_nointr(PTR_TO_FD(p)); + } +} + +FDSet* fdset_free(FDSet *s) { + fdset_close(s); + set_free(MAKE_SET(s)); + return NULL; +} + +int fdset_put(FDSet *s, int fd) { + assert(s); + assert(fd >= 0); + + return set_put(MAKE_SET(s), FD_TO_PTR(fd)); +} + +int fdset_put_dup(FDSet *s, int fd) { + int copy, r; + + assert(s); + assert(fd >= 0); + + copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (copy < 0) + return -errno; + + r = fdset_put(s, copy); + if (r < 0) { + safe_close(copy); + return r; + } + + return copy; +} + +bool fdset_contains(FDSet *s, int fd) { + assert(s); + assert(fd >= 0); + + return !!set_get(MAKE_SET(s), FD_TO_PTR(fd)); +} + +int fdset_remove(FDSet *s, int fd) { + assert(s); + assert(fd >= 0); + + return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT; +} + +int fdset_new_fill(FDSet **_s) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r = 0; + FDSet *s; + + assert(_s); + + /* Creates an fdset and fills in all currently open file + * descriptors. */ + + d = opendir("/proc/self/fd"); + if (!d) + return -errno; + + s = fdset_new(); + if (!s) { + r = -ENOMEM; + goto finish; + } + + FOREACH_DIRENT(de, d, return -errno) { + int fd = -1; + + r = safe_atoi(de->d_name, &fd); + if (r < 0) + goto finish; + + if (fd < 3) + continue; + + if (fd == dirfd(d)) + continue; + + r = fdset_put(s, fd); + if (r < 0) + goto finish; + } + + r = 0; + *_s = TAKE_PTR(s); + +finish: + /* We won't close the fds here! */ + if (s) + set_free(MAKE_SET(s)); + + return r; +} + +int fdset_cloexec(FDSet *fds, bool b) { + Iterator i; + void *p; + int r; + + assert(fds); + + SET_FOREACH(p, MAKE_SET(fds), i) { + r = fd_cloexec(PTR_TO_FD(p), b); + if (r < 0) + return r; + } + + return 0; +} + +int fdset_new_listen_fds(FDSet **_s, bool unset) { + int n, fd, r; + FDSet *s; + + assert(_s); + + /* Creates an fdset and fills in all passed file descriptors */ + + s = fdset_new(); + if (!s) { + r = -ENOMEM; + goto fail; + } + + n = sd_listen_fds(unset); + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { + r = fdset_put(s, fd); + if (r < 0) + goto fail; + } + + *_s = s; + return 0; + +fail: + if (s) + set_free(MAKE_SET(s)); + + return r; +} + +int fdset_close_others(FDSet *fds) { + void *e; + Iterator i; + int *a = NULL; + size_t j = 0, m; + + m = fdset_size(fds); + + if (m > 0) { + a = newa(int, m); + SET_FOREACH(e, MAKE_SET(fds), i) + a[j++] = PTR_TO_FD(e); + } + + assert(j == m); + + return close_all_fds(a, j); +} + +unsigned fdset_size(FDSet *fds) { + return set_size(MAKE_SET(fds)); +} + +bool fdset_isempty(FDSet *fds) { + return set_isempty(MAKE_SET(fds)); +} + +int fdset_iterate(FDSet *s, Iterator *i) { + void *p; + + if (!set_iterate(MAKE_SET(s), i, &p)) + return -ENOENT; + + return PTR_TO_FD(p); +} + +int fdset_steal_first(FDSet *fds) { + void *p; + + p = set_steal_first(MAKE_SET(fds)); + if (!p) + return -ENOENT; + + return PTR_TO_FD(p); +} diff --git a/src/shared/fdset.h b/src/shared/fdset.h new file mode 100644 index 00000000..bdf13770 --- /dev/null +++ b/src/shared/fdset.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "hashmap.h" +#include "macro.h" +#include "set.h" + +typedef struct FDSet FDSet; + +FDSet* fdset_new(void); +FDSet* fdset_free(FDSet *s); + +int fdset_put(FDSet *s, int fd); +int fdset_put_dup(FDSet *s, int fd); + +bool fdset_contains(FDSet *s, int fd); +int fdset_remove(FDSet *s, int fd); + +int fdset_new_array(FDSet **ret, const int *fds, size_t n_fds); +int fdset_new_fill(FDSet **ret); +int fdset_new_listen_fds(FDSet **ret, bool unset); + +int fdset_cloexec(FDSet *fds, bool b); + +int fdset_close_others(FDSet *fds); + +unsigned fdset_size(FDSet *fds); +bool fdset_isempty(FDSet *fds); + +int fdset_iterate(FDSet *s, Iterator *i); + +int fdset_steal_first(FDSet *fds); + +void fdset_close(FDSet *fds); + +#define FDSET_FOREACH(fd, fds, i) \ + for ((i) = ITERATOR_FIRST, (fd) = fdset_iterate((fds), &(i)); (fd) >= 0; (fd) = fdset_iterate((fds), &(i))) + +DEFINE_TRIVIAL_CLEANUP_FUNC(FDSet*, fdset_free); +#define _cleanup_fdset_free_ _cleanup_(fdset_freep) diff --git a/src/shared/fileio-label.c b/src/shared/fileio-label.c new file mode 100644 index 00000000..49ab2972 --- /dev/null +++ b/src/shared/fileio-label.c @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "fileio-label.h" +#include "fileio.h" +#include "selinux-util.h" + +int write_string_file_atomic_label_ts(const char *fn, const char *line, struct timespec *ts) { + int r; + + r = mac_selinux_create_file_prepare(fn, S_IFREG); + if (r < 0) + return r; + + r = write_string_file_ts(fn, line, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC, ts); + + mac_selinux_create_file_clear(); + + return r; +} + +int create_shutdown_run_nologin_or_warn(void) { + int r; + + /* This is used twice: once in systemd-user-sessions.service, in order to block logins when we actually go + * down, and once in systemd-logind.service when shutdowns are scheduled, and logins are to be turned off a bit + * in advance. We use the same wording of the message in both cases. */ + + r = write_string_file_atomic_label("/run/nologin", + "System is going down. Unprivileged users are not permitted to log in anymore. " + "For technical details, see pam_nologin(8)."); + if (r < 0) + return log_error_errno(r, "Failed to create /run/nologin: %m"); + + return 0; +} diff --git a/src/shared/fileio-label.h b/src/shared/fileio-label.h new file mode 100644 index 00000000..8f88955d --- /dev/null +++ b/src/shared/fileio-label.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +/* These functions are split out of fileio.h (and not for example just flags to the functions they wrap) in order to + * optimize linking: This way, -lselinux is needed only for the callers of these functions that need selinux, but not + * for all */ + +int write_string_file_atomic_label_ts(const char *fn, const char *line, struct timespec *ts); +static inline int write_string_file_atomic_label(const char *fn, const char *line) { + return write_string_file_atomic_label_ts(fn, line, NULL); +} + +int create_shutdown_run_nologin_or_warn(void); diff --git a/src/shared/firewall-util.c b/src/shared/firewall-util.c new file mode 100644 index 00000000..4d4d615b --- /dev/null +++ b/src/shared/firewall-util.c @@ -0,0 +1,350 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +/* Temporary work-around for broken glibc vs. linux kernel header definitions + * This is already fixed upstream, remove this when distributions have updated. + */ +#define _NET_IF_H 1 + +#include +#include +#include +#include +#include +#include +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "firewall-util.h" +#include "in-addr-util.h" +#include "macro.h" +#include "socket-util.h" + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct xtc_handle*, iptc_free); + +static int entry_fill_basics( + struct ipt_entry *entry, + int protocol, + const char *in_interface, + const union in_addr_union *source, + unsigned source_prefixlen, + const char *out_interface, + const union in_addr_union *destination, + unsigned destination_prefixlen) { + + assert(entry); + + if (out_interface && !ifname_valid(out_interface)) + return -EINVAL; + if (in_interface && !ifname_valid(in_interface)) + return -EINVAL; + + entry->ip.proto = protocol; + + if (in_interface) { + size_t l; + + l = strlen(in_interface); + assert(l < sizeof entry->ip.iniface); + assert(l < sizeof entry->ip.iniface_mask); + + strcpy(entry->ip.iniface, in_interface); + memset(entry->ip.iniface_mask, 0xFF, l + 1); + } + if (source) { + entry->ip.src = source->in; + in4_addr_prefixlen_to_netmask(&entry->ip.smsk, source_prefixlen); + } + + if (out_interface) { + size_t l = strlen(out_interface); + assert(l < sizeof entry->ip.outiface); + assert(l < sizeof entry->ip.outiface_mask); + + strcpy(entry->ip.outiface, out_interface); + memset(entry->ip.outiface_mask, 0xFF, l + 1); + } + if (destination) { + entry->ip.dst = destination->in; + in4_addr_prefixlen_to_netmask(&entry->ip.dmsk, destination_prefixlen); + } + + return 0; +} + +int fw_add_masquerade( + bool add, + int af, + int protocol, + const union in_addr_union *source, + unsigned source_prefixlen, + const char *out_interface, + const union in_addr_union *destination, + unsigned destination_prefixlen) { + + static const xt_chainlabel chain = "POSTROUTING"; + _cleanup_(iptc_freep) struct xtc_handle *h = NULL; + struct ipt_entry *entry, *mask; + struct ipt_entry_target *t; + size_t sz; + struct nf_nat_ipv4_multi_range_compat *mr; + int r; + + if (af != AF_INET) + return -EOPNOTSUPP; + + if (!IN_SET(protocol, 0, IPPROTO_TCP, IPPROTO_UDP)) + return -EOPNOTSUPP; + + h = iptc_init("nat"); + if (!h) + return -errno; + + sz = XT_ALIGN(sizeof(struct ipt_entry)) + + XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)); + + /* Put together the entry we want to add or remove */ + entry = alloca0(sz); + entry->next_offset = sz; + entry->target_offset = XT_ALIGN(sizeof(struct ipt_entry)); + r = entry_fill_basics(entry, protocol, NULL, source, source_prefixlen, out_interface, destination, destination_prefixlen); + if (r < 0) + return r; + + /* Fill in target part */ + t = ipt_get_target(entry); + t->u.target_size = + XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)); + strncpy(t->u.user.name, "MASQUERADE", sizeof(t->u.user.name)); + mr = (struct nf_nat_ipv4_multi_range_compat*) t->data; + mr->rangesize = 1; + + /* Create a search mask entry */ + mask = alloca(sz); + memset(mask, 0xFF, sz); + + if (add) { + if (iptc_check_entry(chain, entry, (unsigned char*) mask, h)) + return 0; + if (errno != ENOENT) /* if other error than not existing yet, fail */ + return -errno; + + if (!iptc_insert_entry(chain, entry, 0, h)) + return -errno; + } else { + if (!iptc_delete_entry(chain, entry, (unsigned char*) mask, h)) { + if (errno == ENOENT) /* if it's already gone, all is good! */ + return 0; + + return -errno; + } + } + + if (!iptc_commit(h)) + return -errno; + + return 0; +} + +int fw_add_local_dnat( + bool add, + int af, + int protocol, + const char *in_interface, + const union in_addr_union *source, + unsigned source_prefixlen, + const union in_addr_union *destination, + unsigned destination_prefixlen, + uint16_t local_port, + const union in_addr_union *remote, + uint16_t remote_port, + const union in_addr_union *previous_remote) { + + static const xt_chainlabel chain_pre = "PREROUTING", chain_output = "OUTPUT"; + _cleanup_(iptc_freep) struct xtc_handle *h = NULL; + struct ipt_entry *entry, *mask; + struct ipt_entry_target *t; + struct ipt_entry_match *m; + struct xt_addrtype_info_v1 *at; + struct nf_nat_ipv4_multi_range_compat *mr; + size_t sz, msz; + int r; + + assert(add || !previous_remote); + + if (af != AF_INET) + return -EOPNOTSUPP; + + if (!IN_SET(protocol, IPPROTO_TCP, IPPROTO_UDP)) + return -EOPNOTSUPP; + + if (local_port <= 0) + return -EINVAL; + + if (remote_port <= 0) + return -EINVAL; + + h = iptc_init("nat"); + if (!h) + return -errno; + + sz = XT_ALIGN(sizeof(struct ipt_entry)) + + XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_addrtype_info_v1)) + + XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)); + + if (protocol == IPPROTO_TCP) + msz = XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_tcp)); + else + msz = XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_udp)); + + sz += msz; + + /* Fill in basic part */ + entry = alloca0(sz); + entry->next_offset = sz; + entry->target_offset = + XT_ALIGN(sizeof(struct ipt_entry)) + + XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_addrtype_info_v1)) + + msz; + r = entry_fill_basics(entry, protocol, in_interface, source, source_prefixlen, NULL, destination, destination_prefixlen); + if (r < 0) + return r; + + /* Fill in first match */ + m = (struct ipt_entry_match*) ((uint8_t*) entry + XT_ALIGN(sizeof(struct ipt_entry))); + m->u.match_size = msz; + if (protocol == IPPROTO_TCP) { + struct xt_tcp *tcp; + + strncpy(m->u.user.name, "tcp", sizeof(m->u.user.name)); + tcp = (struct xt_tcp*) m->data; + tcp->dpts[0] = tcp->dpts[1] = local_port; + tcp->spts[0] = 0; + tcp->spts[1] = 0xFFFF; + + } else { + struct xt_udp *udp; + + strncpy(m->u.user.name, "udp", sizeof(m->u.user.name)); + udp = (struct xt_udp*) m->data; + udp->dpts[0] = udp->dpts[1] = local_port; + udp->spts[0] = 0; + udp->spts[1] = 0xFFFF; + } + + /* Fill in second match */ + m = (struct ipt_entry_match*) ((uint8_t*) entry + XT_ALIGN(sizeof(struct ipt_entry)) + msz); + m->u.match_size = + XT_ALIGN(sizeof(struct ipt_entry_match)) + + XT_ALIGN(sizeof(struct xt_addrtype_info_v1)); + strncpy(m->u.user.name, "addrtype", sizeof(m->u.user.name)); + m->u.user.revision = 1; + at = (struct xt_addrtype_info_v1*) m->data; + at->dest = XT_ADDRTYPE_LOCAL; + + /* Fill in target part */ + t = ipt_get_target(entry); + t->u.target_size = + XT_ALIGN(sizeof(struct ipt_entry_target)) + + XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)); + strncpy(t->u.user.name, "DNAT", sizeof(t->u.user.name)); + mr = (struct nf_nat_ipv4_multi_range_compat*) t->data; + mr->rangesize = 1; + mr->range[0].flags = NF_NAT_RANGE_PROTO_SPECIFIED|NF_NAT_RANGE_MAP_IPS; + mr->range[0].min_ip = mr->range[0].max_ip = remote->in.s_addr; + if (protocol == IPPROTO_TCP) + mr->range[0].min.tcp.port = mr->range[0].max.tcp.port = htobe16(remote_port); + else + mr->range[0].min.udp.port = mr->range[0].max.udp.port = htobe16(remote_port); + + mask = alloca0(sz); + memset(mask, 0xFF, sz); + + if (add) { + /* Add the PREROUTING rule, if it is missing so far */ + if (!iptc_check_entry(chain_pre, entry, (unsigned char*) mask, h)) { + if (errno != ENOENT) + return -EINVAL; + + if (!iptc_insert_entry(chain_pre, entry, 0, h)) + return -errno; + } + + /* If a previous remote is set, remove its entry */ + if (previous_remote && previous_remote->in.s_addr != remote->in.s_addr) { + mr->range[0].min_ip = mr->range[0].max_ip = previous_remote->in.s_addr; + + if (!iptc_delete_entry(chain_pre, entry, (unsigned char*) mask, h)) { + if (errno != ENOENT) + return -errno; + } + + mr->range[0].min_ip = mr->range[0].max_ip = remote->in.s_addr; + } + + /* Add the OUTPUT rule, if it is missing so far */ + if (!in_interface) { + + /* Don't apply onto loopback addresses */ + if (!destination) { + entry->ip.dst.s_addr = htobe32(0x7F000000); + entry->ip.dmsk.s_addr = htobe32(0xFF000000); + entry->ip.invflags = IPT_INV_DSTIP; + } + + if (!iptc_check_entry(chain_output, entry, (unsigned char*) mask, h)) { + if (errno != ENOENT) + return -errno; + + if (!iptc_insert_entry(chain_output, entry, 0, h)) + return -errno; + } + + /* If a previous remote is set, remove its entry */ + if (previous_remote && previous_remote->in.s_addr != remote->in.s_addr) { + mr->range[0].min_ip = mr->range[0].max_ip = previous_remote->in.s_addr; + + if (!iptc_delete_entry(chain_output, entry, (unsigned char*) mask, h)) { + if (errno != ENOENT) + return -errno; + } + } + } + } else { + if (!iptc_delete_entry(chain_pre, entry, (unsigned char*) mask, h)) { + if (errno != ENOENT) + return -errno; + } + + if (!in_interface) { + if (!destination) { + entry->ip.dst.s_addr = htobe32(0x7F000000); + entry->ip.dmsk.s_addr = htobe32(0xFF000000); + entry->ip.invflags = IPT_INV_DSTIP; + } + + if (!iptc_delete_entry(chain_output, entry, (unsigned char*) mask, h)) { + if (errno != ENOENT) + return -errno; + } + } + } + + if (!iptc_commit(h)) + return -errno; + + return 0; +} diff --git a/src/shared/firewall-util.h b/src/shared/firewall-util.h new file mode 100644 index 00000000..4fc71dad --- /dev/null +++ b/src/shared/firewall-util.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "in-addr-util.h" + +#if HAVE_LIBIPTC + +int fw_add_masquerade( + bool add, + int af, + int protocol, + const union in_addr_union *source, + unsigned source_prefixlen, + const char *out_interface, + const union in_addr_union *destination, + unsigned destination_prefixlen); + +int fw_add_local_dnat( + bool add, + int af, + int protocol, + const char *in_interface, + const union in_addr_union *source, + unsigned source_prefixlen, + const union in_addr_union *destination, + unsigned destination_prefixlen, + uint16_t local_port, + const union in_addr_union *remote, + uint16_t remote_port, + const union in_addr_union *previous_remote); + +#else + +static inline int fw_add_masquerade( + bool add, + int af, + int protocol, + const union in_addr_union *source, + unsigned source_prefixlen, + const char *out_interface, + const union in_addr_union *destination, + unsigned destination_prefixlen) { + return -EOPNOTSUPP; +} + +static inline int fw_add_local_dnat( + bool add, + int af, + int protocol, + const char *in_interface, + const union in_addr_union *source, + unsigned source_prefixlen, + const union in_addr_union *destination, + unsigned destination_prefixlen, + uint16_t local_port, + const union in_addr_union *remote, + uint16_t remote_port, + const union in_addr_union *previous_remote) { + return -EOPNOTSUPP; +} + +#endif diff --git a/src/shared/format-table.c b/src/shared/format-table.c new file mode 100644 index 00000000..4617ae8b --- /dev/null +++ b/src/shared/format-table.c @@ -0,0 +1,2090 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-table.h" +#include "format-util.h" +#include "gunicode.h" +#include "in-addr-util.h" +#include "memory-util.h" +#include "pager.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "sort-util.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "terminal-util.h" +#include "time-util.h" +#include "utf8.h" +#include "util.h" + +#define DEFAULT_WEIGHT 100 + +/* + A few notes on implementation details: + + - TableCell is a 'fake' structure, it's just used as data type to pass references to specific cell positions in the + table. It can be easily converted to an index number and back. + + - TableData is where the actual data is stored: it encapsulates the data and formatting for a specific cell. It's + 'pseudo-immutable' and ref-counted. When a cell's data's formatting is to be changed, we duplicate the object if the + ref-counting is larger than 1. Note that TableData and its ref-counting is mostly not visible to the outside. The + outside only sees Table and TableCell. + + - The Table object stores a simple one-dimensional array of references to TableData objects, one row after the + previous one. + + - There's no special concept of a "row" or "column" in the table, and no special concept of the "header" row. It's all + derived from the cell index: we know how many cells are to be stored in a row, and can determine the rest from + that. The first row is always the header row. If header display is turned off we simply skip outputting the first + row. Also, when sorting rows we always leave the first row where it is, as the header shouldn't move. + + - Note because there's no row and no column object some properties that might be appropriate as row/column properties + are exposed as cell properties instead. For example, the "weight" of a column (which is used to determine where to + add/remove space preferable when expanding/compressing tables horizontally) is actually made the "weight" of a + cell. Given that we usually need it per-column though we will calculate the average across every cell of the column + instead. + + - To make things easy, when cells are added without any explicit configured formatting, then we'll copy the formatting + from the same cell in the previous cell. This is particularly useful for the "weight" of the cell (see above), as + this means setting the weight of the cells of the header row will nicely propagate to all cells in the other rows. +*/ + +typedef struct TableData { + unsigned n_ref; + TableDataType type; + + size_t minimum_width; /* minimum width for the column */ + size_t maximum_width; /* maximum width for the column */ + unsigned weight; /* the horizontal weight for this column, in case the table is expanded/compressed */ + unsigned ellipsize_percent; /* 0 … 100, where to place the ellipsis when compression is needed */ + unsigned align_percent; /* 0 … 100, where to pad with spaces when expanding is needed. 0: left-aligned, 100: right-aligned */ + + bool uppercase; /* Uppercase string on display */ + + const char *color; /* ANSI color string to use for this cell. When written to terminal should not move cursor. Will automatically be reset after the cell */ + char *url; /* A URL to use for a clickable hyperlink */ + char *formatted; /* A cached textual representation of the cell data, before ellipsation/alignment */ + + union { + uint8_t data[0]; /* data is generic array */ + bool boolean; + usec_t timestamp; + usec_t timespan; + uint64_t size; + char string[0]; + int int_val; + int8_t int8; + int16_t int16; + int32_t int32; + int64_t int64; + unsigned uint_val; + uint8_t uint8; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + int percent; /* we use 'int' as datatype for percent values in order to match the result of parse_percent() */ + int ifindex; + union in_addr_union address; + /* … add more here as we start supporting more cell data types … */ + }; +} TableData; + +static size_t TABLE_CELL_TO_INDEX(TableCell *cell) { + size_t i; + + assert(cell); + + i = PTR_TO_SIZE(cell); + assert(i > 0); + + return i-1; +} + +static TableCell* TABLE_INDEX_TO_CELL(size_t index) { + assert(index != (size_t) -1); + return SIZE_TO_PTR(index + 1); +} + +struct Table { + size_t n_columns; + size_t n_cells; + + bool header; /* Whether to show the header row? */ + size_t width; /* If != (size_t) -1 the width to format this table in */ + + TableData **data; + size_t n_allocated; + + size_t *display_map; /* List of columns to show (by their index). It's fine if columns are listed multiple times or not at all */ + size_t n_display_map; + + size_t *sort_map; /* The columns to order rows by, in order of preference. */ + size_t n_sort_map; + + bool *reverse_map; + + char *empty_string; +}; + +Table *table_new_raw(size_t n_columns) { + _cleanup_(table_unrefp) Table *t = NULL; + + assert(n_columns > 0); + + t = new(Table, 1); + if (!t) + return NULL; + + *t = (struct Table) { + .n_columns = n_columns, + .header = true, + .width = (size_t) -1, + }; + + return TAKE_PTR(t); +} + +Table *table_new_internal(const char *first_header, ...) { + _cleanup_(table_unrefp) Table *t = NULL; + size_t n_columns = 1; + const char *h; + va_list ap; + int r; + + assert(first_header); + + va_start(ap, first_header); + for (;;) { + h = va_arg(ap, const char*); + if (!h) + break; + + n_columns++; + } + va_end(ap); + + t = table_new_raw(n_columns); + if (!t) + return NULL; + + va_start(ap, first_header); + for (h = first_header; h; h = va_arg(ap, const char*)) { + TableCell *cell; + + r = table_add_cell(t, &cell, TABLE_STRING, h); + if (r < 0) { + va_end(ap); + return NULL; + } + + /* Make the table header uppercase */ + r = table_set_uppercase(t, cell, true); + if (r < 0) { + va_end(ap); + return NULL; + } + } + va_end(ap); + + assert(t->n_columns == t->n_cells); + return TAKE_PTR(t); +} + +static TableData *table_data_free(TableData *d) { + assert(d); + + free(d->formatted); + free(d->url); + + return mfree(d); +} + +DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(TableData, table_data, table_data_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(TableData*, table_data_unref); + +Table *table_unref(Table *t) { + size_t i; + + if (!t) + return NULL; + + for (i = 0; i < t->n_cells; i++) + table_data_unref(t->data[i]); + + free(t->data); + free(t->display_map); + free(t->sort_map); + free(t->reverse_map); + free(t->empty_string); + + return mfree(t); +} + +static size_t table_data_size(TableDataType type, const void *data) { + + switch (type) { + + case TABLE_EMPTY: + return 0; + + case TABLE_STRING: + return strlen(data) + 1; + + case TABLE_BOOLEAN: + return sizeof(bool); + + case TABLE_TIMESTAMP: + case TABLE_TIMESTAMP_UTC: + case TABLE_TIMESTAMP_RELATIVE: + case TABLE_TIMESPAN: + case TABLE_TIMESPAN_MSEC: + return sizeof(usec_t); + + case TABLE_SIZE: + case TABLE_INT64: + case TABLE_UINT64: + case TABLE_BPS: + return sizeof(uint64_t); + + case TABLE_INT32: + case TABLE_UINT32: + return sizeof(uint32_t); + + case TABLE_INT16: + case TABLE_UINT16: + return sizeof(uint16_t); + + case TABLE_INT8: + case TABLE_UINT8: + return sizeof(uint8_t); + + case TABLE_INT: + case TABLE_UINT: + case TABLE_PERCENT: + case TABLE_IFINDEX: + return sizeof(int); + + case TABLE_IN_ADDR: + return sizeof(struct in_addr); + + case TABLE_IN6_ADDR: + return sizeof(struct in6_addr); + + default: + assert_not_reached("Uh? Unexpected cell type"); + } +} + +static bool table_data_matches( + TableData *d, + TableDataType type, + const void *data, + size_t minimum_width, + size_t maximum_width, + unsigned weight, + unsigned align_percent, + unsigned ellipsize_percent) { + + size_t k, l; + assert(d); + + if (d->type != type) + return false; + + if (d->minimum_width != minimum_width) + return false; + + if (d->maximum_width != maximum_width) + return false; + + if (d->weight != weight) + return false; + + if (d->align_percent != align_percent) + return false; + + if (d->ellipsize_percent != ellipsize_percent) + return false; + + /* If a color/url/uppercase flag is set, refuse to merge */ + if (d->color) + return false; + if (d->url) + return false; + if (d->uppercase) + return false; + + k = table_data_size(type, data); + l = table_data_size(d->type, d->data); + + if (k != l) + return false; + + return memcmp_safe(data, d->data, l) == 0; +} + +static TableData *table_data_new( + TableDataType type, + const void *data, + size_t minimum_width, + size_t maximum_width, + unsigned weight, + unsigned align_percent, + unsigned ellipsize_percent) { + + size_t data_size; + TableData *d; + + data_size = table_data_size(type, data); + + d = malloc0(offsetof(TableData, data) + data_size); + if (!d) + return NULL; + + d->n_ref = 1; + d->type = type; + d->minimum_width = minimum_width; + d->maximum_width = maximum_width; + d->weight = weight; + d->align_percent = align_percent; + d->ellipsize_percent = ellipsize_percent; + memcpy_safe(d->data, data, data_size); + + return d; +} + +int table_add_cell_full( + Table *t, + TableCell **ret_cell, + TableDataType type, + const void *data, + size_t minimum_width, + size_t maximum_width, + unsigned weight, + unsigned align_percent, + unsigned ellipsize_percent) { + + _cleanup_(table_data_unrefp) TableData *d = NULL; + TableData *p; + + assert(t); + assert(type >= 0); + assert(type < _TABLE_DATA_TYPE_MAX); + + /* Special rule: patch NULL data fields to the empty field */ + if (!data) + type = TABLE_EMPTY; + + /* Determine the cell adjacent to the current one, but one row up */ + if (t->n_cells >= t->n_columns) + assert_se(p = t->data[t->n_cells - t->n_columns]); + else + p = NULL; + + /* If formatting parameters are left unspecified, copy from the previous row */ + if (minimum_width == (size_t) -1) + minimum_width = p ? p->minimum_width : 1; + + if (weight == (unsigned) -1) + weight = p ? p->weight : DEFAULT_WEIGHT; + + if (align_percent == (unsigned) -1) + align_percent = p ? p->align_percent : 0; + + if (ellipsize_percent == (unsigned) -1) + ellipsize_percent = p ? p->ellipsize_percent : 100; + + assert(align_percent <= 100); + assert(ellipsize_percent <= 100); + + /* Small optimization: Pretty often adjacent cells in two subsequent lines have the same data and + * formatting. Let's see if we can reuse the cell data and ref it once more. */ + + if (p && table_data_matches(p, type, data, minimum_width, maximum_width, weight, align_percent, ellipsize_percent)) + d = table_data_ref(p); + else { + d = table_data_new(type, data, minimum_width, maximum_width, weight, align_percent, ellipsize_percent); + if (!d) + return -ENOMEM; + } + + if (!GREEDY_REALLOC(t->data, t->n_allocated, MAX(t->n_cells + 1, t->n_columns))) + return -ENOMEM; + + if (ret_cell) + *ret_cell = TABLE_INDEX_TO_CELL(t->n_cells); + + t->data[t->n_cells++] = TAKE_PTR(d); + + return 0; +} + +int table_add_cell_stringf(Table *t, TableCell **ret_cell, const char *format, ...) { + _cleanup_free_ char *buffer = NULL; + va_list ap; + int r; + + va_start(ap, format); + r = vasprintf(&buffer, format, ap); + va_end(ap); + if (r < 0) + return -ENOMEM; + + return table_add_cell(t, ret_cell, TABLE_STRING, buffer); +} + +int table_fill_empty(Table *t, size_t until_column) { + int r; + + assert(t); + + /* Fill the rest of the current line with empty cells until we reach the specified column. Will add + * at least one cell. Pass 0 in order to fill a line to the end or insert an empty line. */ + + if (until_column >= t->n_columns) + return -EINVAL; + + do { + r = table_add_cell(t, NULL, TABLE_EMPTY, NULL); + if (r < 0) + return r; + + } while ((t->n_cells % t->n_columns) != until_column); + + return 0; +} + +int table_dup_cell(Table *t, TableCell *cell) { + size_t i; + + assert(t); + + /* Add the data of the specified cell a second time as a new cell to the end. */ + + i = TABLE_CELL_TO_INDEX(cell); + if (i >= t->n_cells) + return -ENXIO; + + if (!GREEDY_REALLOC(t->data, t->n_allocated, MAX(t->n_cells + 1, t->n_columns))) + return -ENOMEM; + + t->data[t->n_cells++] = table_data_ref(t->data[i]); + return 0; +} + +static int table_dedup_cell(Table *t, TableCell *cell) { + _cleanup_free_ char *curl = NULL; + TableData *nd, *od; + size_t i; + + assert(t); + + /* Helper call that ensures the specified cell's data object has a ref count of 1, which we can use before + * changing a cell's formatting without effecting every other cell's formatting that shares the same data */ + + i = TABLE_CELL_TO_INDEX(cell); + if (i >= t->n_cells) + return -ENXIO; + + assert_se(od = t->data[i]); + if (od->n_ref == 1) + return 0; + + assert(od->n_ref > 1); + + if (od->url) { + curl = strdup(od->url); + if (!curl) + return -ENOMEM; + } + + nd = table_data_new( + od->type, + od->data, + od->minimum_width, + od->maximum_width, + od->weight, + od->align_percent, + od->ellipsize_percent); + if (!nd) + return -ENOMEM; + + nd->color = od->color; + nd->url = TAKE_PTR(curl); + nd->uppercase = od->uppercase; + + table_data_unref(od); + t->data[i] = nd; + + assert(nd->n_ref == 1); + + return 1; +} + +static TableData *table_get_data(Table *t, TableCell *cell) { + size_t i; + + assert(t); + assert(cell); + + /* Get the data object of the specified cell, or NULL if it doesn't exist */ + + i = TABLE_CELL_TO_INDEX(cell); + if (i >= t->n_cells) + return NULL; + + assert(t->data[i]); + assert(t->data[i]->n_ref > 0); + + return t->data[i]; +} + +int table_set_minimum_width(Table *t, TableCell *cell, size_t minimum_width) { + int r; + + assert(t); + assert(cell); + + if (minimum_width == (size_t) -1) + minimum_width = 1; + + r = table_dedup_cell(t, cell); + if (r < 0) + return r; + + table_get_data(t, cell)->minimum_width = minimum_width; + return 0; +} + +int table_set_maximum_width(Table *t, TableCell *cell, size_t maximum_width) { + int r; + + assert(t); + assert(cell); + + r = table_dedup_cell(t, cell); + if (r < 0) + return r; + + table_get_data(t, cell)->maximum_width = maximum_width; + return 0; +} + +int table_set_weight(Table *t, TableCell *cell, unsigned weight) { + int r; + + assert(t); + assert(cell); + + if (weight == (unsigned) -1) + weight = DEFAULT_WEIGHT; + + r = table_dedup_cell(t, cell); + if (r < 0) + return r; + + table_get_data(t, cell)->weight = weight; + return 0; +} + +int table_set_align_percent(Table *t, TableCell *cell, unsigned percent) { + int r; + + assert(t); + assert(cell); + + if (percent == (unsigned) -1) + percent = 0; + + assert(percent <= 100); + + r = table_dedup_cell(t, cell); + if (r < 0) + return r; + + table_get_data(t, cell)->align_percent = percent; + return 0; +} + +int table_set_ellipsize_percent(Table *t, TableCell *cell, unsigned percent) { + int r; + + assert(t); + assert(cell); + + if (percent == (unsigned) -1) + percent = 100; + + assert(percent <= 100); + + r = table_dedup_cell(t, cell); + if (r < 0) + return r; + + table_get_data(t, cell)->ellipsize_percent = percent; + return 0; +} + +int table_set_color(Table *t, TableCell *cell, const char *color) { + int r; + + assert(t); + assert(cell); + + r = table_dedup_cell(t, cell); + if (r < 0) + return r; + + table_get_data(t, cell)->color = empty_to_null(color); + return 0; +} + +int table_set_url(Table *t, TableCell *cell, const char *url) { + _cleanup_free_ char *copy = NULL; + int r; + + assert(t); + assert(cell); + + if (url) { + copy = strdup(url); + if (!copy) + return -ENOMEM; + } + + r = table_dedup_cell(t, cell); + if (r < 0) + return r; + + return free_and_replace(table_get_data(t, cell)->url, copy); +} + +int table_set_uppercase(Table *t, TableCell *cell, bool b) { + TableData *d; + int r; + + assert(t); + assert(cell); + + r = table_dedup_cell(t, cell); + if (r < 0) + return r; + + assert_se(d = table_get_data(t, cell)); + + if (d->uppercase == b) + return 0; + + d->formatted = mfree(d->formatted); + d->uppercase = b; + return 1; +} + +int table_update(Table *t, TableCell *cell, TableDataType type, const void *data) { + _cleanup_free_ char *curl = NULL; + TableData *nd, *od; + size_t i; + + assert(t); + assert(cell); + + i = TABLE_CELL_TO_INDEX(cell); + if (i >= t->n_cells) + return -ENXIO; + + assert_se(od = t->data[i]); + + if (od->url) { + curl = strdup(od->url); + if (!curl) + return -ENOMEM; + } + + nd = table_data_new( + type, + data, + od->minimum_width, + od->maximum_width, + od->weight, + od->align_percent, + od->ellipsize_percent); + if (!nd) + return -ENOMEM; + + nd->color = od->color; + nd->url = TAKE_PTR(curl); + nd->uppercase = od->uppercase; + + table_data_unref(od); + t->data[i] = nd; + + return 0; +} + +int table_add_many_internal(Table *t, TableDataType first_type, ...) { + TableDataType type; + va_list ap; + TableCell *last_cell = NULL; + int r; + + assert(t); + assert(first_type >= 0); + assert(first_type < _TABLE_DATA_TYPE_MAX); + + type = first_type; + + va_start(ap, first_type); + for (;;) { + const void *data; + union { + uint64_t size; + usec_t usec; + int int_val; + int8_t int8; + int16_t int16; + int32_t int32; + int64_t int64; + unsigned uint_val; + uint8_t uint8; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + int percent; + int ifindex; + bool b; + union in_addr_union address; + } buffer; + + switch (type) { + + case TABLE_EMPTY: + data = NULL; + break; + + case TABLE_STRING: + data = va_arg(ap, const char *); + break; + + case TABLE_BOOLEAN: + buffer.b = va_arg(ap, int); + data = &buffer.b; + break; + + case TABLE_TIMESTAMP: + case TABLE_TIMESTAMP_UTC: + case TABLE_TIMESTAMP_RELATIVE: + case TABLE_TIMESPAN: + case TABLE_TIMESPAN_MSEC: + buffer.usec = va_arg(ap, usec_t); + data = &buffer.usec; + break; + + case TABLE_SIZE: + case TABLE_BPS: + buffer.size = va_arg(ap, uint64_t); + data = &buffer.size; + break; + + case TABLE_INT: + buffer.int_val = va_arg(ap, int); + data = &buffer.int_val; + break; + + case TABLE_INT8: { + int x = va_arg(ap, int); + assert(x >= INT8_MIN && x <= INT8_MAX); + + buffer.int8 = x; + data = &buffer.int8; + break; + } + + case TABLE_INT16: { + int x = va_arg(ap, int); + assert(x >= INT16_MIN && x <= INT16_MAX); + + buffer.int16 = x; + data = &buffer.int16; + break; + } + + case TABLE_INT32: + buffer.int32 = va_arg(ap, int32_t); + data = &buffer.int32; + break; + + case TABLE_INT64: + buffer.int64 = va_arg(ap, int64_t); + data = &buffer.int64; + break; + + case TABLE_UINT: + buffer.uint_val = va_arg(ap, unsigned); + data = &buffer.uint_val; + break; + + case TABLE_UINT8: { + unsigned x = va_arg(ap, unsigned); + assert(x <= UINT8_MAX); + + buffer.uint8 = x; + data = &buffer.uint8; + break; + } + + case TABLE_UINT16: { + unsigned x = va_arg(ap, unsigned); + assert(x <= UINT16_MAX); + + buffer.uint16 = x; + data = &buffer.uint16; + break; + } + + case TABLE_UINT32: + buffer.uint32 = va_arg(ap, uint32_t); + data = &buffer.uint32; + break; + + case TABLE_UINT64: + buffer.uint64 = va_arg(ap, uint64_t); + data = &buffer.uint64; + break; + + case TABLE_PERCENT: + buffer.percent = va_arg(ap, int); + data = &buffer.percent; + break; + + case TABLE_IFINDEX: + buffer.ifindex = va_arg(ap, int); + data = &buffer.ifindex; + break; + + case TABLE_IN_ADDR: + buffer.address = *va_arg(ap, union in_addr_union *); + data = &buffer.address.in; + break; + + case TABLE_IN6_ADDR: + buffer.address = *va_arg(ap, union in_addr_union *); + data = &buffer.address.in6; + break; + + case TABLE_SET_MINIMUM_WIDTH: { + size_t w = va_arg(ap, size_t); + + r = table_set_minimum_width(t, last_cell, w); + break; + } + + case TABLE_SET_MAXIMUM_WIDTH: { + size_t w = va_arg(ap, size_t); + r = table_set_maximum_width(t, last_cell, w); + break; + } + + case TABLE_SET_WEIGHT: { + unsigned w = va_arg(ap, unsigned); + r = table_set_weight(t, last_cell, w); + break; + } + + case TABLE_SET_ALIGN_PERCENT: { + unsigned p = va_arg(ap, unsigned); + r = table_set_align_percent(t, last_cell, p); + break; + } + + case TABLE_SET_ELLIPSIZE_PERCENT: { + unsigned p = va_arg(ap, unsigned); + r = table_set_ellipsize_percent(t, last_cell, p); + break; + } + + case TABLE_SET_COLOR: { + const char *c = va_arg(ap, const char*); + r = table_set_color(t, last_cell, c); + break; + } + + case TABLE_SET_URL: { + const char *u = va_arg(ap, const char*); + r = table_set_url(t, last_cell, u); + break; + } + + case TABLE_SET_UPPERCASE: { + int u = va_arg(ap, int); + r = table_set_uppercase(t, last_cell, u); + break; + } + + case _TABLE_DATA_TYPE_MAX: + /* Used as end marker */ + va_end(ap); + return 0; + + default: + assert_not_reached("Uh? Unexpected data type."); + } + + if (type < _TABLE_DATA_TYPE_MAX) + r = table_add_cell(t, &last_cell, type, data); + + if (r < 0) { + va_end(ap); + return r; + } + + type = va_arg(ap, TableDataType); + } +} + +void table_set_header(Table *t, bool b) { + assert(t); + + t->header = b; +} + +void table_set_width(Table *t, size_t width) { + assert(t); + + t->width = width; +} + +int table_set_empty_string(Table *t, const char *empty) { + assert(t); + + return free_and_strdup(&t->empty_string, empty); +} + +int table_set_display(Table *t, size_t first_column, ...) { + size_t allocated, column; + va_list ap; + + assert(t); + + allocated = t->n_display_map; + column = first_column; + + va_start(ap, first_column); + for (;;) { + assert(column < t->n_columns); + + if (!GREEDY_REALLOC(t->display_map, allocated, MAX(t->n_columns, t->n_display_map+1))) { + va_end(ap); + return -ENOMEM; + } + + t->display_map[t->n_display_map++] = column; + + column = va_arg(ap, size_t); + if (column == (size_t) -1) + break; + + } + va_end(ap); + + return 0; +} + +int table_set_sort(Table *t, size_t first_column, ...) { + size_t allocated, column; + va_list ap; + + assert(t); + + allocated = t->n_sort_map; + column = first_column; + + va_start(ap, first_column); + for (;;) { + assert(column < t->n_columns); + + if (!GREEDY_REALLOC(t->sort_map, allocated, MAX(t->n_columns, t->n_sort_map+1))) { + va_end(ap); + return -ENOMEM; + } + + t->sort_map[t->n_sort_map++] = column; + + column = va_arg(ap, size_t); + if (column == (size_t) -1) + break; + } + va_end(ap); + + return 0; +} + +static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t index_b) { + assert(a); + assert(b); + + if (a->type == b->type) { + + /* We only define ordering for cells of the same data type. If cells with different data types are + * compared we follow the order the cells were originally added in */ + + switch (a->type) { + + case TABLE_STRING: + return strcmp(a->string, b->string); + + case TABLE_BOOLEAN: + if (!a->boolean && b->boolean) + return -1; + if (a->boolean && !b->boolean) + return 1; + return 0; + + case TABLE_TIMESTAMP: + case TABLE_TIMESTAMP_UTC: + case TABLE_TIMESTAMP_RELATIVE: + return CMP(a->timestamp, b->timestamp); + + case TABLE_TIMESPAN: + case TABLE_TIMESPAN_MSEC: + return CMP(a->timespan, b->timespan); + + case TABLE_SIZE: + case TABLE_BPS: + return CMP(a->size, b->size); + + case TABLE_INT: + return CMP(a->int_val, b->int_val); + + case TABLE_INT8: + return CMP(a->int8, b->int8); + + case TABLE_INT16: + return CMP(a->int16, b->int16); + + case TABLE_INT32: + return CMP(a->int32, b->int32); + + case TABLE_INT64: + return CMP(a->int64, b->int64); + + case TABLE_UINT: + return CMP(a->uint_val, b->uint_val); + + case TABLE_UINT8: + return CMP(a->uint8, b->uint8); + + case TABLE_UINT16: + return CMP(a->uint16, b->uint16); + + case TABLE_UINT32: + return CMP(a->uint32, b->uint32); + + case TABLE_UINT64: + return CMP(a->uint64, b->uint64); + + case TABLE_PERCENT: + return CMP(a->percent, b->percent); + + case TABLE_IFINDEX: + return CMP(a->ifindex, b->ifindex); + + case TABLE_IN_ADDR: + return CMP(a->address.in.s_addr, b->address.in.s_addr); + + case TABLE_IN6_ADDR: + return memcmp(&a->address.in6, &b->address.in6, FAMILY_ADDRESS_SIZE(AF_INET6)); + + default: + ; + } + } + + /* Generic fallback using the original order in which the cells where added. */ + return CMP(index_a, index_b); +} + +static int table_data_compare(const size_t *a, const size_t *b, Table *t) { + size_t i; + int r; + + assert(t); + assert(t->sort_map); + + /* Make sure the header stays at the beginning */ + if (*a < t->n_columns && *b < t->n_columns) + return 0; + if (*a < t->n_columns) + return -1; + if (*b < t->n_columns) + return 1; + + /* Order other lines by the sorting map */ + for (i = 0; i < t->n_sort_map; i++) { + TableData *d, *dd; + + d = t->data[*a + t->sort_map[i]]; + dd = t->data[*b + t->sort_map[i]]; + + r = cell_data_compare(d, *a, dd, *b); + if (r != 0) + return t->reverse_map && t->reverse_map[t->sort_map[i]] ? -r : r; + } + + /* Order identical lines by the order there were originally added in */ + return CMP(*a, *b); +} + +static const char *table_data_format(Table *t, TableData *d) { + assert(d); + + if (d->formatted) + return d->formatted; + + switch (d->type) { + case TABLE_EMPTY: + return strempty(t->empty_string); + + case TABLE_STRING: + if (d->uppercase) { + char *p, *q; + + d->formatted = new(char, strlen(d->string) + 1); + if (!d->formatted) + return NULL; + + for (p = d->string, q = d->formatted; *p; p++, q++) + *q = (char) toupper((unsigned char) *p); + *q = 0; + + return d->formatted; + } + + return d->string; + + case TABLE_BOOLEAN: + return yes_no(d->boolean); + + case TABLE_TIMESTAMP: + case TABLE_TIMESTAMP_UTC: + case TABLE_TIMESTAMP_RELATIVE: { + _cleanup_free_ char *p; + char *ret; + + p = new(char, FORMAT_TIMESTAMP_MAX); + if (!p) + return NULL; + + if (d->type == TABLE_TIMESTAMP) + ret = format_timestamp(p, FORMAT_TIMESTAMP_MAX, d->timestamp); + else if (d->type == TABLE_TIMESTAMP_UTC) + ret = format_timestamp_utc(p, FORMAT_TIMESTAMP_MAX, d->timestamp); + else + ret = format_timestamp_relative(p, FORMAT_TIMESTAMP_MAX, d->timestamp); + if (!ret) + return "n/a"; + + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_TIMESPAN: + case TABLE_TIMESPAN_MSEC: { + _cleanup_free_ char *p; + + p = new(char, FORMAT_TIMESPAN_MAX); + if (!p) + return NULL; + + if (!format_timespan(p, FORMAT_TIMESPAN_MAX, d->timespan, + d->type == TABLE_TIMESPAN ? 0 : USEC_PER_MSEC)) + return "n/a"; + + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_SIZE: { + _cleanup_free_ char *p; + + p = new(char, FORMAT_BYTES_MAX); + if (!p) + return NULL; + + if (!format_bytes(p, FORMAT_BYTES_MAX, d->size)) + return "n/a"; + + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_BPS: { + _cleanup_free_ char *p; + size_t n; + + p = new(char, FORMAT_BYTES_MAX+2); + if (!p) + return NULL; + + if (!format_bytes_full(p, FORMAT_BYTES_MAX, d->size, 0)) + return "n/a"; + + n = strlen(p); + strscpy(p + n, FORMAT_BYTES_MAX + 2 - n, "bps"); + + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_INT: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->int_val) + 1); + if (!p) + return NULL; + + sprintf(p, "%i", d->int_val); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_INT8: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->int8) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIi8, d->int8); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_INT16: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->int16) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIi16, d->int16); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_INT32: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->int32) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIi32, d->int32); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_INT64: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->int64) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIi64, d->int64); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_UINT: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->uint_val) + 1); + if (!p) + return NULL; + + sprintf(p, "%u", d->uint_val); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_UINT8: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->uint8) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIu8, d->uint8); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_UINT16: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->uint16) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIu16, d->uint16); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_UINT32: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->uint32) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIu32, d->uint32); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_UINT64: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->uint64) + 1); + if (!p) + return NULL; + + sprintf(p, "%" PRIu64, d->uint64); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_PERCENT: { + _cleanup_free_ char *p; + + p = new(char, DECIMAL_STR_WIDTH(d->percent) + 2); + if (!p) + return NULL; + + sprintf(p, "%i%%" , d->percent); + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_IFINDEX: { + _cleanup_free_ char *p = NULL; + char name[IF_NAMESIZE + 1]; + + if (format_ifname(d->ifindex, name)) { + p = strdup(name); + if (!p) + return NULL; + } else { + if (asprintf(&p, "%i" , d->ifindex) < 0) + return NULL; + } + + d->formatted = TAKE_PTR(p); + break; + } + + case TABLE_IN_ADDR: + case TABLE_IN6_ADDR: { + _cleanup_free_ char *p = NULL; + + if (in_addr_to_string(d->type == TABLE_IN_ADDR ? AF_INET : AF_INET6, + &d->address, &p) < 0) + return NULL; + + d->formatted = TAKE_PTR(p); + break; + } + + default: + assert_not_reached("Unexpected type?"); + } + + return d->formatted; +} + +static int table_data_requested_width(Table *table, TableData *d, size_t *ret) { + const char *t; + size_t l; + + t = table_data_format(table, d); + if (!t) + return -ENOMEM; + + l = utf8_console_width(t); + if (l == (size_t) -1) + return -EINVAL; + + if (d->maximum_width != (size_t) -1 && l > d->maximum_width) + l = d->maximum_width; + + if (l < d->minimum_width) + l = d->minimum_width; + + *ret = l; + return 0; +} + +static char *align_string_mem(const char *str, const char *url, size_t new_length, unsigned percent) { + size_t w = 0, space, lspace, old_length, clickable_length; + _cleanup_free_ char *clickable = NULL; + const char *p; + char *ret; + size_t i; + int r; + + /* As with ellipsize_mem(), 'old_length' is a byte size while 'new_length' is a width in character cells */ + + assert(str); + assert(percent <= 100); + + old_length = strlen(str); + + if (url) { + r = terminal_urlify(url, str, &clickable); + if (r < 0) + return NULL; + + clickable_length = strlen(clickable); + } else + clickable_length = old_length; + + /* Determine current width on screen */ + p = str; + while (p < str + old_length) { + char32_t c; + + if (utf8_encoded_to_unichar(p, &c) < 0) { + p++, w++; /* count invalid chars as 1 */ + continue; + } + + p = utf8_next_char(p); + w += unichar_iswide(c) ? 2 : 1; + } + + /* Already wider than the target, if so, don't do anything */ + if (w >= new_length) + return clickable ? TAKE_PTR(clickable) : strdup(str); + + /* How much spaces shall we add? An how much on the left side? */ + space = new_length - w; + lspace = space * percent / 100U; + + ret = new(char, space + clickable_length + 1); + if (!ret) + return NULL; + + for (i = 0; i < lspace; i++) + ret[i] = ' '; + memcpy(ret + lspace, clickable ?: str, clickable_length); + for (i = lspace + clickable_length; i < space + clickable_length; i++) + ret[i] = ' '; + + ret[space + clickable_length] = 0; + return ret; +} + +static const char* table_data_color(TableData *d) { + assert(d); + + if (d->color) + return d->color; + + /* Let's implicitly color all "empty" cells in grey, in case an "empty_string" is set that is not empty */ + if (d->type == TABLE_EMPTY) + return ansi_grey(); + + return NULL; +} + +int table_print(Table *t, FILE *f) { + size_t n_rows, *minimum_width, *maximum_width, display_columns, *requested_width, + i, j, table_minimum_width, table_maximum_width, table_requested_width, table_effective_width, + *width; + _cleanup_free_ size_t *sorted = NULL; + uint64_t *column_weight, weight_sum; + int r; + + assert(t); + + if (!f) + f = stdout; + + /* Ensure we have no incomplete rows */ + assert(t->n_cells % t->n_columns == 0); + + n_rows = t->n_cells / t->n_columns; + assert(n_rows > 0); /* at least the header row must be complete */ + + if (t->sort_map) { + /* If sorting is requested, let's calculate an index table we use to lookup the actual index to display with. */ + + sorted = new(size_t, n_rows); + if (!sorted) + return -ENOMEM; + + for (i = 0; i < n_rows; i++) + sorted[i] = i * t->n_columns; + + typesafe_qsort_r(sorted, n_rows, table_data_compare, t); + } + + if (t->display_map) + display_columns = t->n_display_map; + else + display_columns = t->n_columns; + + assert(display_columns > 0); + + minimum_width = newa(size_t, display_columns); + maximum_width = newa(size_t, display_columns); + requested_width = newa(size_t, display_columns); + width = newa(size_t, display_columns); + column_weight = newa0(uint64_t, display_columns); + + for (j = 0; j < display_columns; j++) { + minimum_width[j] = 1; + maximum_width[j] = (size_t) -1; + requested_width[j] = (size_t) -1; + } + + /* First pass: determine column sizes */ + for (i = t->header ? 0 : 1; i < n_rows; i++) { + TableData **row; + + /* Note that we don't care about ordering at this time, as we just want to determine column sizes, + * hence we don't care for sorted[] during the first pass. */ + row = t->data + i * t->n_columns; + + for (j = 0; j < display_columns; j++) { + TableData *d; + size_t req; + + assert_se(d = row[t->display_map ? t->display_map[j] : j]); + + r = table_data_requested_width(t, d, &req); + if (r < 0) + return r; + + /* Determine the biggest width that any cell in this column would like to have */ + if (requested_width[j] == (size_t) -1 || + requested_width[j] < req) + requested_width[j] = req; + + /* Determine the minimum width any cell in this column needs */ + if (minimum_width[j] < d->minimum_width) + minimum_width[j] = d->minimum_width; + + /* Determine the maximum width any cell in this column needs */ + if (d->maximum_width != (size_t) -1 && + (maximum_width[j] == (size_t) -1 || + maximum_width[j] > d->maximum_width)) + maximum_width[j] = d->maximum_width; + + /* Determine the full columns weight */ + column_weight[j] += d->weight; + } + } + + /* One space between each column */ + table_requested_width = table_minimum_width = table_maximum_width = display_columns - 1; + + /* Calculate the total weight for all columns, plus the minimum, maximum and requested width for the table. */ + weight_sum = 0; + for (j = 0; j < display_columns; j++) { + weight_sum += column_weight[j]; + + table_minimum_width += minimum_width[j]; + + if (maximum_width[j] == (size_t) -1) + table_maximum_width = (size_t) -1; + else + table_maximum_width += maximum_width[j]; + + table_requested_width += requested_width[j]; + } + + /* Calculate effective table width */ + if (t->width != (size_t) -1) + table_effective_width = t->width; + else if (pager_have() || !isatty(STDOUT_FILENO)) + table_effective_width = table_requested_width; + else + table_effective_width = MIN(table_requested_width, columns()); + + if (table_maximum_width != (size_t) -1 && table_effective_width > table_maximum_width) + table_effective_width = table_maximum_width; + + if (table_effective_width < table_minimum_width) + table_effective_width = table_minimum_width; + + if (table_effective_width >= table_requested_width) { + size_t extra; + + /* We have extra room, let's distribute it among columns according to their weights. We first provide + * each column with what it asked for and the distribute the rest. */ + + extra = table_effective_width - table_requested_width; + + for (j = 0; j < display_columns; j++) { + size_t delta; + + if (weight_sum == 0) + width[j] = requested_width[j] + extra / (display_columns - j); /* Avoid division by zero */ + else + width[j] = requested_width[j] + (extra * column_weight[j]) / weight_sum; + + if (maximum_width[j] != (size_t) -1 && width[j] > maximum_width[j]) + width[j] = maximum_width[j]; + + if (width[j] < minimum_width[j]) + width[j] = minimum_width[j]; + + assert(width[j] >= requested_width[j]); + delta = width[j] - requested_width[j]; + + /* Subtract what we just added from the rest */ + if (extra > delta) + extra -= delta; + else + extra = 0; + + assert(weight_sum >= column_weight[j]); + weight_sum -= column_weight[j]; + } + + } else { + /* We need to compress the table, columns can't get what they asked for. We first provide each column + * with the minimum they need, and then distribute anything left. */ + bool finalize = false; + size_t extra; + + extra = table_effective_width - table_minimum_width; + + for (j = 0; j < display_columns; j++) + width[j] = (size_t) -1; + + for (;;) { + bool restart = false; + + for (j = 0; j < display_columns; j++) { + size_t delta, w; + + /* Did this column already get something assigned? If so, let's skip to the next */ + if (width[j] != (size_t) -1) + continue; + + if (weight_sum == 0) + w = minimum_width[j] + extra / (display_columns - j); /* avoid division by zero */ + else + w = minimum_width[j] + (extra * column_weight[j]) / weight_sum; + + if (w >= requested_width[j]) { + /* Never give more than requested. If we hit a column like this, there's more + * space to allocate to other columns which means we need to restart the + * iteration. However, if we hit a column like this, let's assign it the space + * it wanted for good early.*/ + + w = requested_width[j]; + restart = true; + + } else if (!finalize) + continue; + + width[j] = w; + + assert(w >= minimum_width[j]); + delta = w - minimum_width[j]; + + assert(delta <= extra); + extra -= delta; + + assert(weight_sum >= column_weight[j]); + weight_sum -= column_weight[j]; + + if (restart && !finalize) + break; + } + + if (finalize) + break; + + if (!restart) + finalize = true; + } + } + + /* Second pass: show output */ + for (i = t->header ? 0 : 1; i < n_rows; i++) { + TableData **row; + + if (sorted) + row = t->data + sorted[i]; + else + row = t->data + i * t->n_columns; + + for (j = 0; j < display_columns; j++) { + _cleanup_free_ char *buffer = NULL; + const char *field; + TableData *d; + size_t l; + + assert_se(d = row[t->display_map ? t->display_map[j] : j]); + + field = table_data_format(t, d); + if (!field) + return -ENOMEM; + + l = utf8_console_width(field); + if (l > width[j]) { + /* Field is wider than allocated space. Let's ellipsize */ + + buffer = ellipsize(field, width[j], d->ellipsize_percent); + if (!buffer) + return -ENOMEM; + + field = buffer; + + } else if (l < width[j]) { + /* Field is shorter than allocated space. Let's align with spaces */ + + buffer = align_string_mem(field, d->url, width[j], d->align_percent); + if (!buffer) + return -ENOMEM; + + field = buffer; + } + + if (l >= width[j] && d->url) { + _cleanup_free_ char *clickable = NULL; + + r = terminal_urlify(d->url, field, &clickable); + if (r < 0) + return r; + + free_and_replace(buffer, clickable); + field = buffer; + } + + if (row == t->data) /* underline header line fully, including the column separator */ + fputs(ansi_underline(), f); + + if (j > 0) + fputc(' ', f); /* column separator */ + + if (table_data_color(d) && colors_enabled()) { + if (row == t->data) /* first undo header underliner */ + fputs(ANSI_NORMAL, f); + + fputs(table_data_color(d), f); + } + + fputs(field, f); + + if (colors_enabled() && (table_data_color(d) || row == t->data)) + fputs(ANSI_NORMAL, f); + } + + fputc('\n', f); + } + + return fflush_and_check(f); +} + +int table_format(Table *t, char **ret) { + _cleanup_fclose_ FILE *f = NULL; + char *buf = NULL; + size_t sz = 0; + int r; + + f = open_memstream_unlocked(&buf, &sz); + if (!f) + return -ENOMEM; + + r = table_print(t, f); + if (r < 0) + return r; + + f = safe_fclose(f); + + *ret = buf; + + return 0; +} + +size_t table_get_rows(Table *t) { + if (!t) + return 0; + + assert(t->n_columns > 0); + return t->n_cells / t->n_columns; +} + +size_t table_get_columns(Table *t) { + if (!t) + return 0; + + assert(t->n_columns > 0); + return t->n_columns; +} + +int table_set_reverse(Table *t, size_t column, bool b) { + assert(t); + assert(column < t->n_columns); + + if (!t->reverse_map) { + if (!b) + return 0; + + t->reverse_map = new0(bool, t->n_columns); + if (!t->reverse_map) + return -ENOMEM; + } + + t->reverse_map[column] = b; + return 0; +} + +TableCell *table_get_cell(Table *t, size_t row, size_t column) { + size_t i; + + assert(t); + + if (column >= t->n_columns) + return NULL; + + i = row * t->n_columns + column; + if (i >= t->n_cells) + return NULL; + + return TABLE_INDEX_TO_CELL(i); +} + +const void *table_get(Table *t, TableCell *cell) { + TableData *d; + + assert(t); + + d = table_get_data(t, cell); + if (!d) + return NULL; + + return d->data; +} + +const void* table_get_at(Table *t, size_t row, size_t column) { + TableCell *cell; + + cell = table_get_cell(t, row, column); + if (!cell) + return NULL; + + return table_get(t, cell); +} + +static int table_data_to_json(TableData *d, JsonVariant **ret) { + + switch (d->type) { + + case TABLE_EMPTY: + return json_variant_new_null(ret); + + case TABLE_STRING: + return json_variant_new_string(ret, d->string); + + case TABLE_BOOLEAN: + return json_variant_new_boolean(ret, d->boolean); + + case TABLE_TIMESTAMP: + case TABLE_TIMESTAMP_UTC: + case TABLE_TIMESTAMP_RELATIVE: + if (d->timestamp == USEC_INFINITY) + return json_variant_new_null(ret); + + return json_variant_new_unsigned(ret, d->timestamp); + + case TABLE_TIMESPAN: + case TABLE_TIMESPAN_MSEC: + if (d->timespan == USEC_INFINITY) + return json_variant_new_null(ret); + + return json_variant_new_unsigned(ret, d->timespan); + + case TABLE_SIZE: + case TABLE_BPS: + if (d->size == (size_t) -1) + return json_variant_new_null(ret); + + return json_variant_new_unsigned(ret, d->size); + + case TABLE_INT: + return json_variant_new_integer(ret, d->int_val); + + case TABLE_INT8: + return json_variant_new_integer(ret, d->int8); + + case TABLE_INT16: + return json_variant_new_integer(ret, d->int16); + + case TABLE_INT32: + return json_variant_new_integer(ret, d->int32); + + case TABLE_INT64: + return json_variant_new_integer(ret, d->int64); + + case TABLE_UINT: + return json_variant_new_unsigned(ret, d->uint_val); + + case TABLE_UINT8: + return json_variant_new_unsigned(ret, d->uint8); + + case TABLE_UINT16: + return json_variant_new_unsigned(ret, d->uint16); + + case TABLE_UINT32: + return json_variant_new_unsigned(ret, d->uint32); + + case TABLE_UINT64: + return json_variant_new_unsigned(ret, d->uint64); + + case TABLE_PERCENT: + return json_variant_new_integer(ret, d->percent); + + case TABLE_IFINDEX: + return json_variant_new_integer(ret, d->ifindex); + + case TABLE_IN_ADDR: + return json_variant_new_array_bytes(ret, &d->address, FAMILY_ADDRESS_SIZE(AF_INET)); + + case TABLE_IN6_ADDR: + return json_variant_new_array_bytes(ret, &d->address, FAMILY_ADDRESS_SIZE(AF_INET6)); + + default: + return -EINVAL; + } +} + +int table_to_json(Table *t, JsonVariant **ret) { + JsonVariant **rows = NULL, **elements = NULL; + _cleanup_free_ size_t *sorted = NULL; + size_t n_rows, i, j, display_columns; + int r; + + assert(t); + + /* Ensure we have no incomplete rows */ + assert(t->n_cells % t->n_columns == 0); + + n_rows = t->n_cells / t->n_columns; + assert(n_rows > 0); /* at least the header row must be complete */ + + if (t->sort_map) { + /* If sorting is requested, let's calculate an index table we use to lookup the actual index to display with. */ + + sorted = new(size_t, n_rows); + if (!sorted) { + r = -ENOMEM; + goto finish; + } + + for (i = 0; i < n_rows; i++) + sorted[i] = i * t->n_columns; + + typesafe_qsort_r(sorted, n_rows, table_data_compare, t); + } + + if (t->display_map) + display_columns = t->n_display_map; + else + display_columns = t->n_columns; + assert(display_columns > 0); + + elements = new0(JsonVariant*, display_columns * 2); + if (!elements) { + r = -ENOMEM; + goto finish; + } + + for (j = 0; j < display_columns; j++) { + TableData *d; + + assert_se(d = t->data[t->display_map ? t->display_map[j] : j]); + + r = table_data_to_json(d, elements + j*2); + if (r < 0) + goto finish; + } + + rows = new0(JsonVariant*, n_rows-1); + if (!rows) { + r = -ENOMEM; + goto finish; + } + + for (i = 1; i < n_rows; i++) { + TableData **row; + + if (sorted) + row = t->data + sorted[i]; + else + row = t->data + i * t->n_columns; + + for (j = 0; j < display_columns; j++) { + TableData *d; + size_t k; + + assert_se(d = row[t->display_map ? t->display_map[j] : j]); + + k = j*2+1; + elements[k] = json_variant_unref(elements[k]); + + r = table_data_to_json(d, elements + k); + if (r < 0) + goto finish; + } + + r = json_variant_new_object(rows + i - 1, elements, display_columns * 2); + if (r < 0) + goto finish; + } + + r = json_variant_new_array(ret, rows, n_rows - 1); + +finish: + if (rows) { + json_variant_unref_many(rows, n_rows-1); + free(rows); + } + + if (elements) { + json_variant_unref_many(elements, display_columns*2); + free(elements); + } + + return r; +} + +int table_print_json(Table *t, FILE *f, JsonFormatFlags flags) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + int r; + + assert(t); + + if (!f) + f = stdout; + + r = table_to_json(t, &v); + if (r < 0) + return r; + + json_variant_dump(v, flags, f, NULL); + + return fflush_and_check(f); +} diff --git a/src/shared/format-table.h b/src/shared/format-table.h new file mode 100644 index 00000000..80f319d0 --- /dev/null +++ b/src/shared/format-table.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "json.h" +#include "macro.h" + +typedef enum TableDataType { + TABLE_EMPTY, + TABLE_STRING, + TABLE_BOOLEAN, + TABLE_TIMESTAMP, + TABLE_TIMESTAMP_UTC, + TABLE_TIMESTAMP_RELATIVE, + TABLE_TIMESPAN, + TABLE_TIMESPAN_MSEC, + TABLE_SIZE, + TABLE_BPS, + TABLE_INT, + TABLE_INT8, + TABLE_INT16, + TABLE_INT32, + TABLE_INT64, + TABLE_UINT, + TABLE_UINT8, + TABLE_UINT16, + TABLE_UINT32, + TABLE_UINT64, + TABLE_PERCENT, + TABLE_IFINDEX, + TABLE_IN_ADDR, /* Takes a union in_addr_union (or a struct in_addr) */ + TABLE_IN6_ADDR, /* Takes a union in_addr_union (or a struct in6_addr) */ + _TABLE_DATA_TYPE_MAX, + + /* The following are not really data types, but commands for table_add_cell_many() to make changes to + * a cell just added. */ + TABLE_SET_MINIMUM_WIDTH, + TABLE_SET_MAXIMUM_WIDTH, + TABLE_SET_WEIGHT, + TABLE_SET_ALIGN_PERCENT, + TABLE_SET_ELLIPSIZE_PERCENT, + TABLE_SET_COLOR, + TABLE_SET_URL, + TABLE_SET_UPPERCASE, + + _TABLE_DATA_TYPE_INVALID = -1, +} TableDataType; + +/* PIDs are just 32bit signed integers on Linux */ +#define TABLE_PID TABLE_INT32 +assert_cc(sizeof(pid_t) == sizeof(int32_t)); + +/* UIDs/GIDs are just 32bit unsigned integers on Linux */ +#define TABLE_UID TABLE_UINT32 +#define TABLE_GID TABLE_UINT32 +assert_cc(sizeof(uid_t) == sizeof(uint32_t)); +assert_cc(sizeof(gid_t) == sizeof(uint32_t)); + +typedef struct Table Table; +typedef struct TableCell TableCell; + +Table *table_new_internal(const char *first_header, ...) _sentinel_; +#define table_new(...) table_new_internal(__VA_ARGS__, NULL) +Table *table_new_raw(size_t n_columns); +Table *table_unref(Table *t); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Table*, table_unref); + +int table_add_cell_full(Table *t, TableCell **ret_cell, TableDataType type, const void *data, size_t minimum_width, size_t maximum_width, unsigned weight, unsigned align_percent, unsigned ellipsize_percent); +static inline int table_add_cell(Table *t, TableCell **ret_cell, TableDataType type, const void *data) { + return table_add_cell_full(t, ret_cell, type, data, (size_t) -1, (size_t) -1, (unsigned) -1, (unsigned) -1, (unsigned) -1); +} +int table_add_cell_stringf(Table *t, TableCell **ret_cell, const char *format, ...) _printf_(3, 4); + +int table_fill_empty(Table *t, size_t until_column); + +int table_dup_cell(Table *t, TableCell *cell); + +int table_set_minimum_width(Table *t, TableCell *cell, size_t minimum_width); +int table_set_maximum_width(Table *t, TableCell *cell, size_t maximum_width); +int table_set_weight(Table *t, TableCell *cell, unsigned weight); +int table_set_align_percent(Table *t, TableCell *cell, unsigned percent); +int table_set_ellipsize_percent(Table *t, TableCell *cell, unsigned percent); +int table_set_color(Table *t, TableCell *cell, const char *color); +int table_set_url(Table *t, TableCell *cell, const char *url); +int table_set_uppercase(Table *t, TableCell *cell, bool b); + +int table_update(Table *t, TableCell *cell, TableDataType type, const void *data); + +int table_add_many_internal(Table *t, TableDataType first_type, ...); +#define table_add_many(t, ...) table_add_many_internal(t, __VA_ARGS__, _TABLE_DATA_TYPE_MAX) + +void table_set_header(Table *table, bool b); +void table_set_width(Table *t, size_t width); +int table_set_empty_string(Table *t, const char *empty); +int table_set_display(Table *t, size_t first_column, ...); +int table_set_sort(Table *t, size_t first_column, ...); +int table_set_reverse(Table *t, size_t column, bool b); + +int table_print(Table *t, FILE *f); +int table_format(Table *t, char **ret); + +static inline TableCell* TABLE_HEADER_CELL(size_t i) { + return SIZE_TO_PTR(i + 1); +} + +size_t table_get_rows(Table *t); +size_t table_get_columns(Table *t); + +TableCell *table_get_cell(Table *t, size_t row, size_t column); + +const void *table_get(Table *t, TableCell *cell); +const void *table_get_at(Table *t, size_t row, size_t column); + +int table_to_json(Table *t, JsonVariant **ret); +int table_print_json(Table *t, FILE *f, JsonFormatFlags json_flags); diff --git a/src/shared/fsck-util.h b/src/shared/fsck-util.h new file mode 100644 index 00000000..78ec18dd --- /dev/null +++ b/src/shared/fsck-util.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/* exit codes as defined in fsck(8) */ +enum { + FSCK_SUCCESS = 0, + FSCK_ERROR_CORRECTED = 1 << 0, + FSCK_SYSTEM_SHOULD_REBOOT = 1 << 1, + FSCK_ERRORS_LEFT_UNCORRECTED = 1 << 2, + FSCK_OPERATIONAL_ERROR = 1 << 3, + FSCK_USAGE_OR_SYNTAX_ERROR = 1 << 4, + FSCK_USER_CANCELLED = 1 << 5, + FSCK_SHARED_LIB_ERROR = 1 << 7, +}; diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c new file mode 100644 index 00000000..86a57e6b --- /dev/null +++ b/src/shared/fstab-util.c @@ -0,0 +1,262 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "device-nodes.h" +#include "fstab-util.h" +#include "macro.h" +#include "mount-util.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "string-util.h" +#include "strv.h" + +int fstab_has_fstype(const char *fstype) { + _cleanup_endmntent_ FILE *f = NULL; + struct mntent *m; + + f = setmntent(fstab_path(), "re"); + if (!f) + return errno == ENOENT ? false : -errno; + + for (;;) { + errno = 0; + m = getmntent(f); + if (!m) + return errno != 0 ? -errno : false; + + if (streq(m->mnt_type, fstype)) + return true; + } + return false; +} + +int fstab_is_mount_point(const char *mount) { + _cleanup_endmntent_ FILE *f = NULL; + struct mntent *m; + + f = setmntent(fstab_path(), "re"); + if (!f) + return errno == ENOENT ? false : -errno; + + for (;;) { + errno = 0; + m = getmntent(f); + if (!m) + return errno != 0 ? -errno : false; + + if (path_equal(m->mnt_dir, mount)) + return true; + } + return false; +} + +int fstab_filter_options(const char *opts, const char *names, + const char **namefound, char **value, char **filtered) { + const char *name, *n = NULL, *x; + _cleanup_strv_free_ char **stor = NULL; + _cleanup_free_ char *v = NULL, **strv = NULL; + + assert(names && *names); + + if (!opts) + goto answer; + + /* If !value and !filtered, this function is not allowed to fail. */ + + if (!filtered) { + const char *word, *state; + size_t l; + + FOREACH_WORD_SEPARATOR(word, l, opts, ",", state) + NULSTR_FOREACH(name, names) { + if (l < strlen(name)) + continue; + if (!strneq(word, name, strlen(name))) + continue; + + /* we know that the string is NUL + * terminated, so *x is valid */ + x = word + strlen(name); + if (IN_SET(*x, '\0', '=', ',')) { + n = name; + if (value) { + free(v); + if (IN_SET(*x, '\0', ',')) + v = NULL; + else { + assert(*x == '='); + x++; + v = strndup(x, l - strlen(name) - 1); + if (!v) + return -ENOMEM; + } + } + } + } + } else { + char **t, **s; + + stor = strv_split(opts, ","); + if (!stor) + return -ENOMEM; + strv = memdup(stor, sizeof(char*) * (strv_length(stor) + 1)); + if (!strv) + return -ENOMEM; + + for (s = t = strv; *s; s++) { + NULSTR_FOREACH(name, names) { + x = startswith(*s, name); + if (x && IN_SET(*x, '\0', '=')) + goto found; + } + + *t = *s; + t++; + continue; + found: + /* Keep the last occurrence found */ + n = name; + if (value) { + free(v); + if (*x == '\0') + v = NULL; + else { + assert(*x == '='); + x++; + v = strdup(x); + if (!v) + return -ENOMEM; + } + } + } + *t = NULL; + } + +answer: + if (namefound) + *namefound = n; + if (filtered) { + char *f; + + f = strv_join(strv, ","); + if (!f) + return -ENOMEM; + + *filtered = f; + } + if (value) + *value = TAKE_PTR(v); + + return !!n; +} + +int fstab_extract_values(const char *opts, const char *name, char ***values) { + _cleanup_strv_free_ char **optsv = NULL, **res = NULL; + char **s; + + assert(opts); + assert(name); + assert(values); + + optsv = strv_split(opts, ","); + if (!optsv) + return -ENOMEM; + + STRV_FOREACH(s, optsv) { + char *arg; + int r; + + arg = startswith(*s, name); + if (!arg || *arg != '=') + continue; + r = strv_extend(&res, arg + 1); + if (r < 0) + return r; + } + + *values = TAKE_PTR(res); + + return !!*values; +} + +int fstab_find_pri(const char *options, int *ret) { + _cleanup_free_ char *opt = NULL; + int r, pri; + + assert(ret); + + r = fstab_filter_options(options, "pri\0", NULL, &opt, NULL); + if (r < 0) + return r; + if (r == 0 || !opt) + return 0; + + r = safe_atoi(opt, &pri); + if (r < 0) + return r; + + *ret = pri; + return 1; +} + +static char *unquote(const char *s, const char* quotes) { + size_t l; + assert(s); + + /* This is rather stupid, simply removes the heading and + * trailing quotes if there is one. Doesn't care about + * escaping or anything. + * + * DON'T USE THIS FOR NEW CODE ANYMORE! */ + + l = strlen(s); + if (l < 2) + return strdup(s); + + if (strchr(quotes, s[0]) && s[l-1] == s[0]) + return strndup(s+1, l-2); + + return strdup(s); +} + +static char *tag_to_udev_node(const char *tagvalue, const char *by) { + _cleanup_free_ char *t = NULL, *u = NULL; + size_t enc_len; + + u = unquote(tagvalue, QUOTES); + if (!u) + return NULL; + + enc_len = strlen(u) * 4 + 1; + t = new(char, enc_len); + if (!t) + return NULL; + + if (encode_devnode_name(u, t, enc_len) < 0) + return NULL; + + return strjoin("/dev/disk/by-", by, "/", t); +} + +char *fstab_node_to_udev_node(const char *p) { + assert(p); + + if (startswith(p, "LABEL=")) + return tag_to_udev_node(p+6, "label"); + + if (startswith(p, "UUID=")) + return tag_to_udev_node(p+5, "uuid"); + + if (startswith(p, "PARTUUID=")) + return tag_to_udev_node(p+9, "partuuid"); + + if (startswith(p, "PARTLABEL=")) + return tag_to_udev_node(p+10, "partlabel"); + + return strdup(p); +} diff --git a/src/shared/fstab-util.h b/src/shared/fstab-util.h new file mode 100644 index 00000000..f575ed0b --- /dev/null +++ b/src/shared/fstab-util.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "macro.h" + +int fstab_is_mount_point(const char *mount); +int fstab_has_fstype(const char *fstype); + +int fstab_filter_options(const char *opts, const char *names, const char **namefound, char **value, char **filtered); + +int fstab_extract_values(const char *opts, const char *name, char ***values); + +static inline bool fstab_test_option(const char *opts, const char *names) { + return !!fstab_filter_options(opts, names, NULL, NULL, NULL); +} + +int fstab_find_pri(const char *options, int *ret); + +static inline bool fstab_test_yes_no_option(const char *opts, const char *yes_no) { + const char *opt; + + /* If first name given is last, return 1. + * If second name given is last or neither is found, return 0. */ + + assert_se(fstab_filter_options(opts, yes_no, &opt, NULL, NULL) >= 0); + + return opt == yes_no; +} + +char *fstab_node_to_udev_node(const char *p); + +static inline const char* fstab_path(void) { + return secure_getenv("SYSTEMD_FSTAB") ?: "/etc/fstab"; +} diff --git a/src/shared/generate-ip-protocol-list.sh b/src/shared/generate-ip-protocol-list.sh new file mode 100755 index 00000000..3f919794 --- /dev/null +++ b/src/shared/generate-ip-protocol-list.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu + +$1 -dM -include netinet/in.h - +#include + +#include "alloc-util.h" +#include "dropin.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "fstab-util.h" +#include "generator.h" +#include "log.h" +#include "macro.h" +#include "mkdir.h" +#include "path-util.h" +#include "special.h" +#include "specifier.h" +#include "string-util.h" +#include "time-util.h" +#include "unit-name.h" +#include "util.h" + +int generator_open_unit_file( + const char *dest, + const char *source, + const char *name, + FILE **file) { + + const char *unit; + FILE *f; + int r; + + unit = prefix_roota(dest, name); + + r = fopen_unlocked(unit, "wxe", &f); + if (r < 0) { + if (source && r == -EEXIST) + return log_error_errno(r, + "Failed to create unit file %s, as it already exists. Duplicate entry in %s?", + unit, source); + else + return log_error_errno(r, + "Failed to create unit file %s: %m", + unit); + } + + fprintf(f, + "# Automatically generated by %s\n\n", + program_invocation_short_name); + + *file = f; + return 0; +} + +int generator_add_symlink(const char *dir, const char *dst, const char *dep_type, const char *src) { + /* Adds a symlink from ./ to (if src is absolute) + * or ../ (otherwise). */ + + const char *from, *to; + + from = path_is_absolute(src) ? src : strjoina("../", src); + to = strjoina(dir, "/", dst, ".", dep_type, "/", basename(src)); + + mkdir_parents_label(to, 0755); + if (symlink(from, to) < 0) + if (errno != EEXIST) + return log_error_errno(errno, "Failed to create symlink \"%s\": %m", to); + + return 0; +} + +static int write_fsck_sysroot_service(const char *dir, const char *what) { + _cleanup_free_ char *device = NULL, *escaped = NULL, *escaped2 = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *unit; + int r; + + escaped = specifier_escape(what); + if (!escaped) + return log_oom(); + + escaped2 = cescape(escaped); + if (!escaped2) + return log_oom(); + + unit = strjoina(dir, "/"SPECIAL_FSCK_ROOT_SERVICE); + log_debug("Creating %s", unit); + + r = unit_name_from_path(what, ".device", &device); + if (r < 0) + return log_error_errno(r, "Failed to convert device \"%s\" to unit name: %m", what); + + f = fopen(unit, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", unit); + + fprintf(f, + "# Automatically generated by %1$s\n\n" + "[Unit]\n" + "Description=File System Check on %2$s\n" + "Documentation=man:systemd-fsck-root.service(8)\n" + "DefaultDependencies=no\n" + "BindsTo=%3$s\n" + "Conflicts=shutdown.target\n" + "After=initrd-root-device.target local-fs-pre.target %3$s\n" + "Before=shutdown.target\n" + "\n" + "[Service]\n" + "Type=oneshot\n" + "RemainAfterExit=yes\n" + "ExecStart=" SYSTEMD_FSCK_PATH " %4$s\n" + "TimeoutSec=0\n", + program_invocation_short_name, + escaped, + device, + escaped2); + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", unit); + + return 0; +} + +int generator_write_fsck_deps( + FILE *f, + const char *dir, + const char *what, + const char *where, + const char *fstype) { + + int r; + + assert(f); + assert(dir); + assert(what); + assert(where); + + if (!is_device_path(what)) { + log_warning("Checking was requested for \"%s\", but it is not a device.", what); + return 0; + } + + if (!isempty(fstype) && !streq(fstype, "auto")) { + r = fsck_exists(fstype); + if (r < 0) + log_warning_errno(r, "Checking was requested for %s, but couldn't detect if fsck.%s may be used, proceeding: %m", what, fstype); + else if (r == 0) { + /* treat missing check as essentially OK */ + log_debug("Checking was requested for %s, but fsck.%s does not exist.", what, fstype); + return 0; + } + } + + if (path_equal(where, "/")) { + const char *lnk; + + lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/" SPECIAL_FSCK_ROOT_SERVICE); + + (void) mkdir_parents(lnk, 0755); + if (symlink(SYSTEM_DATA_UNIT_PATH "/" SPECIAL_FSCK_ROOT_SERVICE, lnk) < 0) + return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); + + } else { + _cleanup_free_ char *_fsck = NULL; + const char *fsck, *dep; + + if (in_initrd() && path_equal(where, "/sysroot")) { + r = write_fsck_sysroot_service(dir, what); + if (r < 0) + return r; + + fsck = SPECIAL_FSCK_ROOT_SERVICE; + dep = "Requires"; + } else { + /* When this is /usr, then let's add a Wants= dependency, otherwise a Requires= + * dependency. Why? We can't possibly unmount /usr during shutdown, but if we have a + * Requires= from /usr onto a fsck@.service unit and that unit is shut down, then + * we'd have to unmount /usr too. */ + + dep = !in_initrd() && path_equal(where, "/usr") ? "Wants" : "Requires"; + + r = unit_name_from_path_instance("systemd-fsck", what, ".service", &_fsck); + if (r < 0) + return log_error_errno(r, "Failed to create fsck service name: %m"); + + fsck = _fsck; + } + + fprintf(f, + "%1$s=%2$s\n" + "After=%2$s\n", + dep, fsck); + } + + return 0; +} + +int generator_write_timeouts( + const char *dir, + const char *what, + const char *where, + const char *opts, + char **filtered) { + + /* Configure how long we wait for a device that backs a mount point or a + * swap partition to show up. This is useful to support endless device timeouts + * for devices that show up only after user input, like crypto devices. */ + + _cleanup_free_ char *node = NULL, *unit = NULL, *timeout = NULL; + usec_t u; + int r; + + r = fstab_filter_options(opts, "comment=systemd.device-timeout\0" + "x-systemd.device-timeout\0", + NULL, &timeout, filtered); + if (r <= 0) + return r; + + r = parse_sec_fix_0(timeout, &u); + if (r < 0) { + log_warning("Failed to parse timeout for %s, ignoring: %s", where, timeout); + return 0; + } + + node = fstab_node_to_udev_node(what); + if (!node) + return log_oom(); + if (!is_device_path(node)) { + log_warning("x-systemd.device-timeout ignored for %s", what); + return 0; + } + + r = unit_name_from_path(node, ".device", &unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit name from path: %m"); + + return write_drop_in_format(dir, unit, 50, "device-timeout", + "# Automatically generated by %s\n" + "# from supplied options \"%s\"\n\n" + "[Unit]\n" + "JobRunningTimeoutSec=%s", + program_invocation_short_name, + opts, + timeout); +} + +int generator_write_device_deps( + const char *dir, + const char *what, + const char *where, + const char *opts) { + + /* fstab records that specify _netdev option should apply the network + * ordering on the actual device depending on network connection. If we + * are not mounting real device (NFS, CIFS), we rely on _netdev effect + * on the mount unit itself. */ + + _cleanup_free_ char *node = NULL, *unit = NULL; + int r; + + if (!fstab_test_option(opts, "_netdev\0")) + return 0; + + node = fstab_node_to_udev_node(what); + if (!node) + return log_oom(); + + /* Nothing to apply dependencies to. */ + if (!is_device_path(node)) + return 0; + + r = unit_name_from_path(node, ".device", &unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", + node); + + /* See mount_add_default_dependencies for explanation why we create such + * dependencies. */ + return write_drop_in_format(dir, unit, 50, "netdev-dependencies", + "# Automatically generated by %s\n\n" + "[Unit]\n" + "After=" SPECIAL_NETWORK_ONLINE_TARGET " " SPECIAL_NETWORK_TARGET "\n" + "Wants=" SPECIAL_NETWORK_ONLINE_TARGET "\n", + program_invocation_short_name); +} + +int generator_write_initrd_root_device_deps(const char *dir, const char *what) { + _cleanup_free_ char *unit = NULL; + int r; + + r = unit_name_from_path(what, ".device", &unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", + what); + + return write_drop_in_format(dir, SPECIAL_INITRD_ROOT_DEVICE_TARGET, 50, "root-device", + "# Automatically generated by %s\n\n" + "[Unit]\n" + "Requires=%s\n" + "After=%s", + program_invocation_short_name, + unit, + unit); +} + +int generator_hook_up_mkswap( + const char *dir, + const char *what) { + + _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *unit_file; + int r; + + node = fstab_node_to_udev_node(what); + if (!node) + return log_oom(); + + /* Nothing to work on. */ + if (!is_device_path(node)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot format something that is not a device node: %s", + node); + + r = unit_name_from_path_instance("systemd-mkswap", node, ".service", &unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m", + node); + + unit_file = prefix_roota(dir, unit); + log_debug("Creating %s", unit_file); + + escaped = cescape(node); + if (!escaped) + return log_oom(); + + r = unit_name_from_path(what, ".swap", &where_unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", + what); + + f = fopen(unit_file, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", + unit_file); + + fprintf(f, + "# Automatically generated by %s\n\n" + "[Unit]\n" + "Description=Make Swap on %%f\n" + "Documentation=man:systemd-mkswap@.service(8)\n" + "DefaultDependencies=no\n" + "BindsTo=%%i.device\n" + "Conflicts=shutdown.target\n" + "After=%%i.device\n" + "Before=shutdown.target %s\n" + "\n" + "[Service]\n" + "Type=oneshot\n" + "RemainAfterExit=yes\n" + "ExecStart="SYSTEMD_MAKEFS_PATH " swap %s\n" + "TimeoutSec=0\n", + program_invocation_short_name, + where_unit, + escaped); + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", unit_file); + + return generator_add_symlink(dir, where_unit, "requires", unit); +} + +int generator_hook_up_mkfs( + const char *dir, + const char *what, + const char *where, + const char *type) { + + _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *unit_file; + int r; + + node = fstab_node_to_udev_node(what); + if (!node) + return log_oom(); + + /* Nothing to work on. */ + if (!is_device_path(node)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot format something that is not a device node: %s", + node); + + if (!type || streq(type, "auto")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot format partition %s, filesystem type is not specified", + node); + + r = unit_name_from_path_instance("systemd-makefs", node, ".service", &unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m", + node); + + unit_file = prefix_roota(dir, unit); + log_debug("Creating %s", unit_file); + + escaped = cescape(node); + if (!escaped) + return log_oom(); + + r = unit_name_from_path(where, ".mount", &where_unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", + where); + + f = fopen(unit_file, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", + unit_file); + + fprintf(f, + "# Automatically generated by %s\n\n" + "[Unit]\n" + "Description=Make File System on %%f\n" + "Documentation=man:systemd-makefs@.service(8)\n" + "DefaultDependencies=no\n" + "BindsTo=%%i.device\n" + "Conflicts=shutdown.target\n" + "After=%%i.device\n" + /* fsck might or might not be used, so let's be safe and order + * ourselves before both systemd-fsck@.service and the mount unit. */ + "Before=shutdown.target systemd-fsck@%%i.service %s\n" + "\n" + "[Service]\n" + "Type=oneshot\n" + "RemainAfterExit=yes\n" + "ExecStart="SYSTEMD_MAKEFS_PATH " %s %s\n" + "TimeoutSec=0\n", + program_invocation_short_name, + where_unit, + type, + escaped); + // XXX: what about local-fs-pre.target? + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit file %s: %m", unit_file); + + return generator_add_symlink(dir, where_unit, "requires", unit); +} + +int generator_hook_up_growfs( + const char *dir, + const char *where, + const char *target) { + + _cleanup_free_ char *unit = NULL, *escaped = NULL, *where_unit = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *unit_file; + int r; + + escaped = cescape(where); + if (!escaped) + return log_oom(); + + r = unit_name_from_path_instance("systemd-growfs", where, ".service", &unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m", + where); + + r = unit_name_from_path(where, ".mount", &where_unit); + if (r < 0) + return log_error_errno(r, "Failed to make unit name from path \"%s\": %m", + where); + + unit_file = prefix_roota(dir, unit); + log_debug("Creating %s", unit_file); + + f = fopen(unit_file, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", + unit_file); + + fprintf(f, + "# Automatically generated by %s\n\n" + "[Unit]\n" + "Description=Grow File System on %%f\n" + "Documentation=man:systemd-growfs@.service(8)\n" + "DefaultDependencies=no\n" + "BindsTo=%%i.mount\n" + "Conflicts=shutdown.target\n" + "After=%%i.mount\n" + "Before=shutdown.target %s\n", + program_invocation_short_name, + target); + + if (empty_or_root(where)) /* Make sure the root fs is actually writable before we resize it */ + fprintf(f, + "After=systemd-remount-fs.service\n"); + + fprintf(f, + "\n" + "[Service]\n" + "Type=oneshot\n" + "RemainAfterExit=yes\n" + "ExecStart="SYSTEMD_GROWFS_PATH " %s\n" + "TimeoutSec=0\n", + escaped); + + return generator_add_symlink(dir, where_unit, "wants", unit); +} + +int generator_enable_remount_fs_service(const char *dir) { + /* Pull in systemd-remount-fs.service */ + return generator_add_symlink(dir, SPECIAL_LOCAL_FS_TARGET, "wants", + SYSTEM_DATA_UNIT_PATH "/" SPECIAL_REMOUNT_FS_SERVICE); +} + +void log_setup_generator(void) { + log_set_prohibit_ipc(true); + log_setup_service(); +} diff --git a/src/shared/generator.h b/src/shared/generator.h new file mode 100644 index 00000000..fa002a91 --- /dev/null +++ b/src/shared/generator.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "main-func.h" + +int generator_open_unit_file( + const char *dest, + const char *source, + const char *name, + FILE **file); + +int generator_add_symlink(const char *dir, const char *dst, const char *dep_type, const char *src); + +int generator_write_fsck_deps( + FILE *f, + const char *dir, + const char *what, + const char *where, + const char *type); + +int generator_write_timeouts( + const char *dir, + const char *what, + const char *where, + const char *opts, + char **filtered); + +int generator_write_device_deps( + const char *dir, + const char *what, + const char *where, + const char *opts); + +int generator_write_initrd_root_device_deps( + const char *dir, + const char *what); + +int generator_hook_up_mkswap( + const char *dir, + const char *what); +int generator_hook_up_mkfs( + const char *dir, + const char *what, + const char *where, + const char *type); +int generator_hook_up_growfs( + const char *dir, + const char *where, + const char *target); + +int generator_enable_remount_fs_service(const char *dir); + +void log_setup_generator(void); + +/* Similar to DEFINE_MAIN_FUNCTION, but initializes logging and assigns positional arguments. */ +#define DEFINE_MAIN_GENERATOR_FUNCTION(impl) \ + _DEFINE_MAIN_FUNCTION( \ + ({ \ + log_setup_generator(); \ + if (argc > 1 && argc != 4) \ + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), \ + "This program takes zero or three arguments."); \ + }), \ + impl(argc > 1 ? argv[1] : "/tmp", \ + argc > 1 ? argv[2] : "/tmp", \ + argc > 1 ? argv[3] : "/tmp"), \ + r < 0 ? EXIT_FAILURE : EXIT_SUCCESS) diff --git a/src/shared/gpt.h b/src/shared/gpt.h new file mode 100644 index 00000000..31e01bd5 --- /dev/null +++ b/src/shared/gpt.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-id128.h" + +/* We only support root disk discovery for x86, x86-64, Itanium and ARM for + * now, since EFI for anything else doesn't really exist, and we only + * care for root partitions on the same disk as the EFI ESP. */ + +#define GPT_ROOT_X86 SD_ID128_MAKE(44,47,95,40,f2,97,41,b2,9a,f7,d1,31,d5,f0,45,8a) +#define GPT_ROOT_X86_64 SD_ID128_MAKE(4f,68,bc,e3,e8,cd,4d,b1,96,e7,fb,ca,f9,84,b7,09) +#define GPT_ROOT_ARM SD_ID128_MAKE(69,da,d7,10,2c,e4,4e,3c,b1,6c,21,a1,d4,9a,be,d3) +#define GPT_ROOT_ARM_64 SD_ID128_MAKE(b9,21,b0,45,1d,f0,41,c3,af,44,4c,6f,28,0d,3f,ae) +#define GPT_ROOT_IA64 SD_ID128_MAKE(99,3d,8d,3d,f8,0e,42,25,85,5a,9d,af,8e,d7,ea,97) +#define GPT_ESP SD_ID128_MAKE(c1,2a,73,28,f8,1f,11,d2,ba,4b,00,a0,c9,3e,c9,3b) +#define GPT_XBOOTLDR SD_ID128_MAKE(bc,13,c2,ff,59,e6,42,62,a3,52,b2,75,fd,6f,71,72) +#define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f) +#define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15) +#define GPT_SRV SD_ID128_MAKE(3b,8f,84,25,20,e0,4f,3b,90,7f,1a,25,a7,6f,98,e8) + +/* Verity partitions for the root partitions above (we only define them for the root partitions, because only they are + * are commonly read-only and hence suitable for verity). */ +#define GPT_ROOT_X86_VERITY SD_ID128_MAKE(d1,3c,5d,3b,b5,d1,42,2a,b2,9f,94,54,fd,c8,9d,76) +#define GPT_ROOT_X86_64_VERITY SD_ID128_MAKE(2c,73,57,ed,eb,d2,46,d9,ae,c1,23,d4,37,ec,2b,f5) +#define GPT_ROOT_ARM_VERITY SD_ID128_MAKE(73,86,cd,f2,20,3c,47,a9,a4,98,f2,ec,ce,45,a2,d6) +#define GPT_ROOT_ARM_64_VERITY SD_ID128_MAKE(df,33,00,ce,d6,9f,4c,92,97,8c,9b,fb,0f,38,d8,20) +#define GPT_ROOT_IA64_VERITY SD_ID128_MAKE(86,ed,10,d5,b6,07,45,bb,89,57,d3,50,f2,3d,05,71) + +#if defined(__x86_64__) +# define GPT_ROOT_NATIVE GPT_ROOT_X86_64 +# define GPT_ROOT_SECONDARY GPT_ROOT_X86 +# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_X86_64_VERITY +# define GPT_ROOT_SECONDARY_VERITY GPT_ROOT_X86_VERITY +#elif defined(__i386__) +# define GPT_ROOT_NATIVE GPT_ROOT_X86 +# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_X86_VERITY +#endif + +#if defined(__ia64__) +# define GPT_ROOT_NATIVE GPT_ROOT_IA64 +# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_IA64_VERITY +#endif + +#if defined(__aarch64__) && (__BYTE_ORDER != __BIG_ENDIAN) +# define GPT_ROOT_NATIVE GPT_ROOT_ARM_64 +# define GPT_ROOT_SECONDARY GPT_ROOT_ARM +# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_ARM_64_VERITY +# define GPT_ROOT_SECONDARY_VERITY GPT_ROOT_ARM_VERITY +#elif defined(__arm__) && (__BYTE_ORDER != __BIG_ENDIAN) +# define GPT_ROOT_NATIVE GPT_ROOT_ARM +# define GPT_ROOT_NATIVE_VERITY GPT_ROOT_ARM_VERITY +#endif + +#define GPT_FLAG_NO_BLOCK_IO_PROTOCOL (1ULL << 1) + +/* Flags we recognize on the root, swap, home and srv partitions when + * doing auto-discovery. These happen to be identical to what + * Microsoft defines for its own Basic Data Partitions, but that's + * just because we saw no point in defining any other values here. */ +#define GPT_FLAG_READ_ONLY (1ULL << 60) +#define GPT_FLAG_NO_AUTO (1ULL << 63) + +#define GPT_LINUX_GENERIC SD_ID128_MAKE(0f,c6,3d,af,84,83,47,72,8e,79,3d,69,d8,47,7d,e4) diff --git a/src/shared/id128-print.c b/src/shared/id128-print.c new file mode 100644 index 00000000..356f4105 --- /dev/null +++ b/src/shared/id128-print.c @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "id128-print.h" +#include "log.h" +#include "pretty-print.h" +#include "terminal-util.h" + +int id128_pretty_print(sd_id128_t id, Id128PrettyPrintMode mode) { + _cleanup_free_ char *man_link = NULL, *mod_link = NULL; + const char *on, *off; + unsigned i; + + assert(mode >= 0); + assert(mode < _ID128_PRETTY_PRINT_MODE_MAX); + + if (mode == ID128_PRINT_ID128) { + printf(SD_ID128_FORMAT_STR "\n", + SD_ID128_FORMAT_VAL(id)); + return 0; + } else if (mode == ID128_PRINT_UUID) { + printf(SD_ID128_UUID_FORMAT_STR "\n", + SD_ID128_FORMAT_VAL(id)); + return 0; + } + + on = ansi_highlight(); + off = ansi_normal(); + + if (terminal_urlify("man:systemd-id128(1)", "systemd-id128(1)", &man_link) < 0) + return log_oom(); + + if (terminal_urlify("https://docs.python.org/3/library/uuid.html", "uuid", &mod_link) < 0) + return log_oom(); + + printf("As string:\n" + "%s" SD_ID128_FORMAT_STR "%s\n\n" + "As UUID:\n" + "%s" SD_ID128_UUID_FORMAT_STR "%s\n\n" + "As %s macro:\n" + "%s#define XYZ SD_ID128_MAKE(", + on, SD_ID128_FORMAT_VAL(id), off, + on, SD_ID128_FORMAT_VAL(id), off, + man_link, + on); + for (i = 0; i < 16; i++) + printf("%02x%s", id.bytes[i], i != 15 ? "," : ""); + printf(")%s\n\n", off); + + printf("As Python constant:\n" + ">>> import %s\n" + ">>> %sXYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')%s\n", + mod_link, + on, SD_ID128_FORMAT_VAL(id), off); + + return 0; +} + +int id128_print_new(Id128PrettyPrintMode mode) { + sd_id128_t id; + int r; + + r = sd_id128_randomize(&id); + if (r < 0) + return log_error_errno(r, "Failed to generate ID: %m"); + + return id128_pretty_print(id, mode); +} diff --git a/src/shared/id128-print.h b/src/shared/id128-print.h new file mode 100644 index 00000000..1dc5b6aa --- /dev/null +++ b/src/shared/id128-print.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#pragma once + +#include + +#include "sd-id128.h" + +typedef enum Id128PrettyPrintMode { + ID128_PRINT_ID128, + ID128_PRINT_UUID, + ID128_PRINT_PRETTY, + _ID128_PRETTY_PRINT_MODE_MAX, + _ID128_PRETTY_PRINT_MODE_INVALID = -1 +} Id128PrettyPrintMode; + +int id128_pretty_print(sd_id128_t id, Id128PrettyPrintMode mode); +int id128_print_new(Id128PrettyPrintMode mode); diff --git a/src/shared/ima-util.c b/src/shared/ima-util.c new file mode 100644 index 00000000..0d4ce3ca --- /dev/null +++ b/src/shared/ima-util.c @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "ima-util.h" + +static int use_ima_cached = -1; + +bool use_ima(void) { + + if (use_ima_cached < 0) + use_ima_cached = access("/sys/kernel/security/ima/", F_OK) >= 0; + + return use_ima_cached; +} diff --git a/src/shared/ima-util.h b/src/shared/ima-util.h new file mode 100644 index 00000000..8f20741c --- /dev/null +++ b/src/shared/ima-util.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +bool use_ima(void); diff --git a/src/shared/import-util.c b/src/shared/import-util.c new file mode 100644 index 00000000..f7770e7d --- /dev/null +++ b/src/shared/import-util.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "import-util.h" +#include "log.h" +#include "macro.h" +#include "nulstr-util.h" +#include "path-util.h" +#include "string-table.h" +#include "string-util.h" + +int import_url_last_component(const char *url, char **ret) { + const char *e, *p; + char *s; + + e = strchrnul(url, '?'); + + while (e > url && e[-1] == '/') + e--; + + p = e; + while (p > url && p[-1] != '/') + p--; + + if (e <= p) + return -EINVAL; + + s = strndup(p, e - p); + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +int import_url_change_last_component(const char *url, const char *suffix, char **ret) { + const char *e; + char *s; + + assert(url); + assert(ret); + + e = strchrnul(url, '?'); + + while (e > url && e[-1] == '/') + e--; + + while (e > url && e[-1] != '/') + e--; + + if (e <= url) + return -EINVAL; + + s = new(char, (e - url) + strlen(suffix) + 1); + if (!s) + return -ENOMEM; + + strcpy(mempcpy(s, url, e - url), suffix); + *ret = s; + return 0; +} + +static const char* const import_verify_table[_IMPORT_VERIFY_MAX] = { + [IMPORT_VERIFY_NO] = "no", + [IMPORT_VERIFY_CHECKSUM] = "checksum", + [IMPORT_VERIFY_SIGNATURE] = "signature", +}; + +DEFINE_STRING_TABLE_LOOKUP(import_verify, ImportVerify); + +int tar_strip_suffixes(const char *name, char **ret) { + const char *e; + char *s; + + e = endswith(name, ".tar"); + if (!e) + e = endswith(name, ".tar.xz"); + if (!e) + e = endswith(name, ".tar.gz"); + if (!e) + e = endswith(name, ".tar.bz2"); + if (!e) + e = endswith(name, ".tgz"); + if (!e) + e = strchr(name, 0); + + if (e <= name) + return -EINVAL; + + s = strndup(name, e - name); + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +int raw_strip_suffixes(const char *p, char **ret) { + + static const char suffixes[] = + ".xz\0" + ".gz\0" + ".bz2\0" + ".raw\0" + ".qcow2\0" + ".img\0" + ".bin\0"; + + _cleanup_free_ char *q = NULL; + + q = strdup(p); + if (!q) + return -ENOMEM; + + for (;;) { + const char *sfx; + bool changed = false; + + NULSTR_FOREACH(sfx, suffixes) { + char *e; + + e = endswith(q, sfx); + if (e) { + *e = 0; + changed = true; + } + } + + if (!changed) + break; + } + + *ret = TAKE_PTR(q); + + return 0; +} + +int import_assign_pool_quota_and_warn(const char *path) { + int r; + + r = btrfs_subvol_auto_qgroup("/var/lib/machines", 0, true); + if (r == -ENOTTY) { + log_debug_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines, as directory is not on btrfs or not a subvolume. Ignoring."); + return 0; + } + if (r < 0) + return log_error_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines: %m"); + if (r > 0) + log_info("Set up default quota hierarchy for /var/lib/machines."); + + r = btrfs_subvol_auto_qgroup(path, 0, true); + if (r == -ENOTTY) { + log_debug_errno(r, "Failed to set up quota hierarchy for %s, as directory is not on btrfs or not a subvolume. Ignoring.", path); + return 0; + } + if (r < 0) + return log_error_errno(r, "Failed to set up default quota hierarchy for %s: %m", path); + if (r > 0) + log_debug("Set up default quota hierarchy for %s.", path); + + return 0; +} diff --git a/src/shared/import-util.h b/src/shared/import-util.h new file mode 100644 index 00000000..0f2a5170 --- /dev/null +++ b/src/shared/import-util.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +typedef enum ImportVerify { + IMPORT_VERIFY_NO, + IMPORT_VERIFY_CHECKSUM, + IMPORT_VERIFY_SIGNATURE, + _IMPORT_VERIFY_MAX, + _IMPORT_VERIFY_INVALID = -1, +} ImportVerify; + +int import_url_last_component(const char *url, char **ret); +int import_url_change_last_component(const char *url, const char *suffix, char **ret); + +const char* import_verify_to_string(ImportVerify v) _const_; +ImportVerify import_verify_from_string(const char *s) _pure_; + +int tar_strip_suffixes(const char *name, char **ret); +int raw_strip_suffixes(const char *name, char **ret); + +int import_assign_pool_quota_and_warn(const char *path); diff --git a/src/shared/initreq.h b/src/shared/initreq.h new file mode 100644 index 00000000..1d7ff81d --- /dev/null +++ b/src/shared/initreq.h @@ -0,0 +1,73 @@ +/* + * initreq.h Interface to talk to init through /dev/initctl. + * + * Copyright (C) 1995-2004 Miquel van Smoorenburg + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * Version: @(#)initreq.h 1.28 31-Mar-2004 MvS + */ + +#pragma once + +#include + +#if defined(__FreeBSD_kernel__) +# define INIT_FIFO "/etc/.initctl" +#else +# define INIT_FIFO "/dev/initctl" +#endif + +#define INIT_MAGIC 0x03091969 +#define INIT_CMD_START 0 +#define INIT_CMD_RUNLVL 1 +#define INIT_CMD_POWERFAIL 2 +#define INIT_CMD_POWERFAILNOW 3 +#define INIT_CMD_POWEROK 4 +#define INIT_CMD_BSD 5 +#define INIT_CMD_SETENV 6 +#define INIT_CMD_UNSETENV 7 + +#define INIT_CMD_CHANGECONS 12345 + +#ifdef MAXHOSTNAMELEN +# define INITRQ_HLEN MAXHOSTNAMELEN +#else +# define INITRQ_HLEN 64 +#endif + +/* + * This is what BSD 4.4 uses when talking to init. + * Linux doesn't use this right now. + */ +struct init_request_bsd { + char gen_id[8]; /* Beats me.. telnetd uses "fe" */ + char tty_id[16]; /* Tty name minus /dev/tty */ + char host[INITRQ_HLEN]; /* Hostname */ + char term_type[16]; /* Terminal type */ + int signal; /* Signal to send */ + int pid; /* Process to send to */ + char exec_name[128]; /* Program to execute */ + char reserved[128]; /* For future expansion. */ +}; + +/* + * Because of legacy interfaces, "runlevel" and "sleeptime" + * aren't in a separate struct in the union. + * + * The weird sizes are because init expects the whole + * struct to be 384 bytes. + */ +struct init_request { + int magic; /* Magic number */ + int cmd; /* What kind of request */ + int runlevel; /* Runlevel to change to */ + int sleeptime; /* Time between TERM and KILL */ + union { + struct init_request_bsd bsd; + char data[368]; + } i; +}; diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c new file mode 100644 index 00000000..2061384a --- /dev/null +++ b/src/shared/install-printf.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "format-util.h" +#include "install-printf.h" +#include "install.h" +#include "macro.h" +#include "specifier.h" +#include "string-util.h" +#include "unit-name.h" +#include "user-util.h" + +static int specifier_prefix_and_instance(char specifier, const void *data, const void *userdata, char **ret) { + const UnitFileInstallInfo *i = userdata; + _cleanup_free_ char *prefix = NULL; + int r; + + assert(i); + + r = unit_name_to_prefix_and_instance(i->name, &prefix); + if (r < 0) + return r; + + if (endswith(prefix, "@") && i->default_instance) { + char *ans; + + ans = strjoin(prefix, i->default_instance); + if (!ans) + return -ENOMEM; + *ret = ans; + } else + *ret = TAKE_PTR(prefix); + + return 0; +} + +static int specifier_name(char specifier, const void *data, const void *userdata, char **ret) { + const UnitFileInstallInfo *i = userdata; + char *ans; + + assert(i); + + if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE) && i->default_instance) + return unit_name_replace_instance(i->name, i->default_instance, ret); + + ans = strdup(i->name); + if (!ans) + return -ENOMEM; + *ret = ans; + return 0; +} + +static int specifier_prefix(char specifier, const void *data, const void *userdata, char **ret) { + const UnitFileInstallInfo *i = userdata; + + assert(i); + + return unit_name_to_prefix(i->name, ret); +} + +static int specifier_instance(char specifier, const void *data, const void *userdata, char **ret) { + const UnitFileInstallInfo *i = userdata; + char *instance; + int r; + + assert(i); + + r = unit_name_to_instance(i->name, &instance); + if (r < 0) + return r; + + if (isempty(instance)) { + r = free_and_strdup(&instance, strempty(i->default_instance)); + if (r < 0) + return r; + } + + *ret = instance; + return 0; +} + +static int specifier_last_component(char specifier, const void *data, const void *userdata, char **ret) { + _cleanup_free_ char *prefix = NULL; + char *dash; + int r; + + r = specifier_prefix(specifier, data, userdata, &prefix); + if (r < 0) + return r; + + dash = strrchr(prefix, '-'); + if (dash) { + dash = strdup(dash + 1); + if (!dash) + return -ENOMEM; + *ret = dash; + } else + *ret = TAKE_PTR(prefix); + + return 0; +} + +int install_full_printf(const UnitFileInstallInfo *i, const char *format, char **ret) { + /* This is similar to unit_full_printf() but does not support + * anything path-related. + * + * %n: the full id of the unit (foo@bar.waldo) + * %N: the id of the unit without the suffix (foo@bar) + * %p: the prefix (foo) + * %i: the instance (bar) + + * %U the UID of the running user + * %u the username of running user + * %m the machine ID of the running system + * %H the host name of the running system + * %b the boot ID of the running system + * %v `uname -r` of the running system + */ + + const Specifier table[] = { + { 'n', specifier_name, NULL }, + { 'N', specifier_prefix_and_instance, NULL }, + { 'p', specifier_prefix, NULL }, + { 'i', specifier_instance, NULL }, + { 'j', specifier_last_component, NULL }, + + { 'g', specifier_group_name, NULL }, + { 'G', specifier_group_id, NULL }, + { 'U', specifier_user_id, NULL }, + { 'u', specifier_user_name, NULL }, + + { 'm', specifier_machine_id, NULL }, + { 'H', specifier_host_name, NULL }, + { 'b', specifier_boot_id, NULL }, + { 'v', specifier_kernel_release, NULL }, + {} + }; + + assert(i); + assert(format); + assert(ret); + + return specifier_printf(format, table, i, ret); +} diff --git a/src/shared/install-printf.h b/src/shared/install-printf.h new file mode 100644 index 00000000..fa8ea7ef --- /dev/null +++ b/src/shared/install-printf.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "install.h" + +int install_full_printf(const UnitFileInstallInfo *i, const char *format, char **ret); diff --git a/src/shared/install.c b/src/shared/install.c new file mode 100644 index 00000000..e72ff187 --- /dev/null +++ b/src/shared/install.c @@ -0,0 +1,3367 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "conf-files.h" +#include "conf-parser.h" +#include "def.h" +#include "dirent-util.h" +#include "extract-word.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hashmap.h" +#include "install-printf.h" +#include "install.h" +#include "locale-util.h" +#include "log.h" +#include "macro.h" +#include "mkdir.h" +#include "path-lookup.h" +#include "path-util.h" +#include "rm-rf.h" +#include "set.h" +#include "special.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "unit-file.h" + +#define UNIT_FILE_FOLLOW_SYMLINK_MAX 64 + +typedef enum SearchFlags { + SEARCH_LOAD = 1 << 0, + SEARCH_FOLLOW_CONFIG_SYMLINKS = 1 << 1, + SEARCH_DROPIN = 1 << 2, +} SearchFlags; + +typedef struct { + OrderedHashmap *will_process; + OrderedHashmap *have_processed; +} InstallContext; + +typedef enum { + PRESET_UNKNOWN, + PRESET_ENABLE, + PRESET_DISABLE, +} PresetAction; + +typedef struct { + char *pattern; + PresetAction action; + char **instances; +} PresetRule; + +typedef struct { + PresetRule *rules; + size_t n_rules; +} Presets; + +static bool unit_file_install_info_has_rules(const UnitFileInstallInfo *i) { + assert(i); + + return !strv_isempty(i->aliases) || + !strv_isempty(i->wanted_by) || + !strv_isempty(i->required_by); +} + +static bool unit_file_install_info_has_also(const UnitFileInstallInfo *i) { + assert(i); + + return !strv_isempty(i->also); +} + +static void presets_freep(Presets *p) { + size_t i; + + if (!p) + return; + + for (i = 0; i < p->n_rules; i++) { + free(p->rules[i].pattern); + strv_free(p->rules[i].instances); + } + + free(p->rules); + p->n_rules = 0; +} + +static const char *const unit_file_type_table[_UNIT_FILE_TYPE_MAX] = { + [UNIT_FILE_TYPE_REGULAR] = "regular", + [UNIT_FILE_TYPE_SYMLINK] = "symlink", + [UNIT_FILE_TYPE_MASKED] = "masked", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(unit_file_type, UnitFileType); + +static int in_search_path(const LookupPaths *p, const char *path) { + _cleanup_free_ char *parent = NULL; + char **i; + + assert(path); + + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; + + STRV_FOREACH(i, p->search_path) + if (path_equal(parent, *i)) + return true; + + return false; +} + +static const char* skip_root(const LookupPaths *p, const char *path) { + char *e; + + assert(p); + assert(path); + + if (!p->root_dir) + return path; + + e = path_startswith(path, p->root_dir); + if (!e) + return NULL; + + /* Make sure the returned path starts with a slash */ + if (e[0] != '/') { + if (e == path || e[-1] != '/') + return NULL; + + e--; + } + + return e; +} + +static int path_is_generator(const LookupPaths *p, const char *path) { + _cleanup_free_ char *parent = NULL; + + assert(p); + assert(path); + + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; + + return path_equal_ptr(parent, p->generator) || + path_equal_ptr(parent, p->generator_early) || + path_equal_ptr(parent, p->generator_late); +} + +static int path_is_transient(const LookupPaths *p, const char *path) { + _cleanup_free_ char *parent = NULL; + + assert(p); + assert(path); + + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; + + return path_equal_ptr(parent, p->transient); +} + +static int path_is_control(const LookupPaths *p, const char *path) { + _cleanup_free_ char *parent = NULL; + + assert(p); + assert(path); + + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; + + return path_equal_ptr(parent, p->persistent_control) || + path_equal_ptr(parent, p->runtime_control); +} + +static int path_is_config(const LookupPaths *p, const char *path, bool check_parent) { + _cleanup_free_ char *parent = NULL; + + assert(p); + assert(path); + + /* Note that we do *not* have generic checks for /etc or /run in place, since with + * them we couldn't discern configuration from transient or generated units */ + + if (check_parent) { + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; + + path = parent; + } + + return path_equal_ptr(path, p->persistent_config) || + path_equal_ptr(path, p->runtime_config); +} + +static int path_is_runtime(const LookupPaths *p, const char *path, bool check_parent) { + _cleanup_free_ char *parent = NULL; + const char *rpath; + + assert(p); + assert(path); + + /* Everything in /run is considered runtime. On top of that we also add + * explicit checks for the various runtime directories, as safety net. */ + + rpath = skip_root(p, path); + if (rpath && path_startswith(rpath, "/run")) + return true; + + if (check_parent) { + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; + + path = parent; + } + + return path_equal_ptr(path, p->runtime_config) || + path_equal_ptr(path, p->generator) || + path_equal_ptr(path, p->generator_early) || + path_equal_ptr(path, p->generator_late) || + path_equal_ptr(path, p->transient) || + path_equal_ptr(path, p->runtime_control); +} + +static int path_is_vendor(const LookupPaths *p, const char *path) { + const char *rpath; + + assert(p); + assert(path); + + rpath = skip_root(p, path); + if (!rpath) + return 0; + + if (path_startswith(rpath, "/usr")) + return true; + +#if HAVE_SPLIT_USR + if (path_startswith(rpath, "/lib")) + return true; +#endif + + return path_equal(rpath, SYSTEM_DATA_UNIT_PATH); +} + +int unit_file_changes_add( + UnitFileChange **changes, + size_t *n_changes, + UnitFileChangeType type, + const char *path, + const char *source) { + + _cleanup_free_ char *p = NULL, *s = NULL; + UnitFileChange *c; + + assert(path); + assert(!changes == !n_changes); + + if (!changes) + return 0; + + c = reallocarray(*changes, *n_changes + 1, sizeof(UnitFileChange)); + if (!c) + return -ENOMEM; + *changes = c; + + p = strdup(path); + if (source) + s = strdup(source); + + if (!p || (source && !s)) + return -ENOMEM; + + path_simplify(p, false); + if (s) + path_simplify(s, false); + + c[*n_changes] = (UnitFileChange) { type, p, s }; + p = s = NULL; + (*n_changes) ++; + return 0; +} + +void unit_file_changes_free(UnitFileChange *changes, size_t n_changes) { + size_t i; + + assert(changes || n_changes == 0); + + for (i = 0; i < n_changes; i++) { + free(changes[i].path); + free(changes[i].source); + } + + free(changes); +} + +void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, size_t n_changes, bool quiet) { + size_t i; + bool logged = false; + + assert(changes || n_changes == 0); + /* If verb is not specified, errors are not allowed! */ + assert(verb || r >= 0); + + for (i = 0; i < n_changes; i++) { + assert(verb || changes[i].type >= 0); + + switch(changes[i].type) { + case UNIT_FILE_SYMLINK: + if (!quiet) + log_info("Created symlink %s %s %s.", + changes[i].path, + special_glyph(SPECIAL_GLYPH_ARROW), + changes[i].source); + break; + case UNIT_FILE_UNLINK: + if (!quiet) + log_info("Removed %s.", changes[i].path); + break; + case UNIT_FILE_IS_MASKED: + if (!quiet) + log_info("Unit %s is masked, ignoring.", changes[i].path); + break; + case UNIT_FILE_IS_DANGLING: + if (!quiet) + log_info("Unit %s is an alias to a unit that is not present, ignoring.", + changes[i].path); + break; + case -EEXIST: + if (changes[i].source) + log_error_errno(changes[i].type, + "Failed to %s unit, file %s already exists and is a symlink to %s.", + verb, changes[i].path, changes[i].source); + else + log_error_errno(changes[i].type, + "Failed to %s unit, file %s already exists.", + verb, changes[i].path); + logged = true; + break; + case -ERFKILL: + log_error_errno(changes[i].type, "Failed to %s unit, unit %s is masked.", + verb, changes[i].path); + logged = true; + break; + case -EADDRNOTAVAIL: + log_error_errno(changes[i].type, "Failed to %s unit, unit %s is transient or generated.", + verb, changes[i].path); + logged = true; + break; + case -EUCLEAN: + log_error_errno(changes[i].type, + "Failed to %s unit, \"%s\" is not a valid unit name.", + verb, changes[i].path); + logged = true; + break; + case -ELOOP: + log_error_errno(changes[i].type, "Failed to %s unit, refusing to operate on linked unit file %s", + verb, changes[i].path); + logged = true; + break; + + case -ENOENT: + log_error_errno(changes[i].type, "Failed to %s unit, unit %s does not exist.", verb, changes[i].path); + logged = true; + break; + + default: + assert(changes[i].type < 0); + log_error_errno(changes[i].type, "Failed to %s unit, file %s: %m.", + verb, changes[i].path); + logged = true; + } + } + + if (r < 0 && !logged) + log_error_errno(r, "Failed to %s: %m.", verb); +} + +/** + * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem. + * wc should be the full path in the host file system. + */ +static bool chroot_symlinks_same(const char *root, const char *wd, const char *a, const char *b) { + assert(path_is_absolute(wd)); + + /* This will give incorrect results if the paths are relative and go outside + * of the chroot. False negatives are possible. */ + + if (!root) + root = "/"; + + a = strjoina(path_is_absolute(a) ? root : wd, "/", a); + b = strjoina(path_is_absolute(b) ? root : wd, "/", b); + return path_equal_or_files_same(a, b, 0); +} + +static int create_symlink( + const LookupPaths *paths, + const char *old_path, + const char *new_path, + bool force, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_free_ char *dest = NULL, *dirname = NULL; + const char *rp; + int r; + + assert(old_path); + assert(new_path); + + rp = skip_root(paths, old_path); + if (rp) + old_path = rp; + + /* Actually create a symlink, and remember that we did. Is + * smart enough to check if there's already a valid symlink in + * place. + * + * Returns 1 if a symlink was created or already exists and points to + * the right place, or negative on error. + */ + + mkdir_parents_label(new_path, 0755); + + if (symlink(old_path, new_path) >= 0) { + unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); + return 1; + } + + if (errno != EEXIST) { + unit_file_changes_add(changes, n_changes, -errno, new_path, NULL); + return -errno; + } + + r = readlink_malloc(new_path, &dest); + if (r < 0) { + /* translate EINVAL (non-symlink exists) to EEXIST */ + if (r == -EINVAL) + r = -EEXIST; + + unit_file_changes_add(changes, n_changes, r, new_path, NULL); + return r; + } + + dirname = dirname_malloc(new_path); + if (!dirname) + return -ENOMEM; + + if (chroot_symlinks_same(paths->root_dir, dirname, dest, old_path)) { + log_debug("Symlink %s → %s already exists", new_path, dest); + return 1; + } + + if (!force) { + unit_file_changes_add(changes, n_changes, -EEXIST, new_path, dest); + return -EEXIST; + } + + r = symlink_atomic(old_path, new_path); + if (r < 0) { + unit_file_changes_add(changes, n_changes, r, new_path, NULL); + return r; + } + + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, new_path, NULL); + unit_file_changes_add(changes, n_changes, UNIT_FILE_SYMLINK, new_path, old_path); + + return 1; +} + +static int mark_symlink_for_removal( + Set **remove_symlinks_to, + const char *p) { + + char *n; + int r; + + assert(p); + + r = set_ensure_allocated(remove_symlinks_to, &path_hash_ops); + if (r < 0) + return r; + + n = strdup(p); + if (!n) + return -ENOMEM; + + path_simplify(n, false); + + r = set_consume(*remove_symlinks_to, n); + if (r == -EEXIST) + return 0; + if (r < 0) + return r; + + return 1; +} + +static int remove_marked_symlinks_fd( + Set *remove_symlinks_to, + int fd, + const char *path, + const char *config_path, + const LookupPaths *lp, + bool dry_run, + bool *restart, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r = 0; + + assert(remove_symlinks_to); + assert(fd >= 0); + assert(path); + assert(config_path); + assert(lp); + assert(restart); + + d = fdopendir(fd); + if (!d) { + safe_close(fd); + return -errno; + } + + rewinddir(d); + + FOREACH_DIRENT(de, d, return -errno) { + + dirent_ensure_type(d, de); + + if (de->d_type == DT_DIR) { + _cleanup_free_ char *p = NULL; + int nfd, q; + + nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); + if (nfd < 0) { + if (errno == ENOENT) + continue; + + if (r == 0) + r = -errno; + continue; + } + + p = path_make_absolute(de->d_name, path); + if (!p) { + safe_close(nfd); + return -ENOMEM; + } + + /* This will close nfd, regardless whether it succeeds or not */ + q = remove_marked_symlinks_fd(remove_symlinks_to, nfd, p, config_path, lp, dry_run, restart, changes, n_changes); + if (q < 0 && r == 0) + r = q; + + } else if (de->d_type == DT_LNK) { + _cleanup_free_ char *p = NULL, *dest = NULL; + const char *rp; + bool found; + int q; + + if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) + continue; + + p = path_make_absolute(de->d_name, path); + if (!p) + return -ENOMEM; + path_simplify(p, false); + + q = readlink_malloc(p, &dest); + if (q == -ENOENT) + continue; + if (q < 0) { + if (r == 0) + r = q; + continue; + } + + /* We remove all links pointing to a file or path that is marked, as well as all files sharing + * the same name as a file that is marked. */ + + found = set_contains(remove_symlinks_to, dest) || + set_contains(remove_symlinks_to, basename(dest)) || + set_contains(remove_symlinks_to, de->d_name); + + if (!found) + continue; + + if (!dry_run) { + if (unlinkat(fd, de->d_name, 0) < 0 && errno != ENOENT) { + if (r == 0) + r = -errno; + unit_file_changes_add(changes, n_changes, -errno, p, NULL); + continue; + } + + (void) rmdir_parents(p, config_path); + } + + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, p, NULL); + + /* Now, remember the full path (but with the root prefix removed) of + * the symlink we just removed, and remove any symlinks to it, too. */ + + rp = skip_root(lp, p); + q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: p); + if (q < 0) + return q; + if (q > 0 && !dry_run) + *restart = true; + } + } + + return r; +} + +static int remove_marked_symlinks( + Set *remove_symlinks_to, + const char *config_path, + const LookupPaths *lp, + bool dry_run, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_close_ int fd = -1; + bool restart; + int r = 0; + + assert(config_path); + assert(lp); + + if (set_size(remove_symlinks_to) <= 0) + return 0; + + fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC); + if (fd < 0) + return errno == ENOENT ? 0 : -errno; + + do { + int q, cfd; + restart = false; + + cfd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (cfd < 0) + return -errno; + + /* This takes possession of cfd and closes it */ + q = remove_marked_symlinks_fd(remove_symlinks_to, cfd, config_path, config_path, lp, dry_run, &restart, changes, n_changes); + if (r == 0) + r = q; + } while (restart); + + return r; +} + +static int is_symlink_with_known_name(const UnitFileInstallInfo *i, const char *name) { + int r; + + if (streq(name, i->name)) + return true; + + if (strv_contains(i->aliases, name)) + return true; + + /* Look for template symlink matching DefaultInstance */ + if (i->default_instance && unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) { + _cleanup_free_ char *s = NULL; + + r = unit_name_replace_instance(i->name, i->default_instance, &s); + if (r < 0) { + if (r != -EINVAL) + return r; + + } else if (streq(name, s)) + return true; + } + + return false; +} + +static int find_symlinks_fd( + const char *root_dir, + const UnitFileInstallInfo *i, + bool match_aliases, + bool ignore_same_name, + int fd, + const char *path, + const char *config_path, + bool *same_name_link) { + + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r = 0; + + assert(i); + assert(fd >= 0); + assert(path); + assert(config_path); + assert(same_name_link); + + d = fdopendir(fd); + if (!d) { + safe_close(fd); + return -errno; + } + + FOREACH_DIRENT(de, d, return -errno) { + + dirent_ensure_type(d, de); + + if (de->d_type == DT_DIR) { + _cleanup_free_ char *p = NULL; + int nfd, q; + + nfd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); + if (nfd < 0) { + if (errno == ENOENT) + continue; + + if (r == 0) + r = -errno; + continue; + } + + p = path_make_absolute(de->d_name, path); + if (!p) { + safe_close(nfd); + return -ENOMEM; + } + + /* This will close nfd, regardless whether it succeeds or not */ + q = find_symlinks_fd(root_dir, i, match_aliases, ignore_same_name, nfd, + p, config_path, same_name_link); + if (q > 0) + return 1; + if (r == 0) + r = q; + + } else if (de->d_type == DT_LNK) { + _cleanup_free_ char *p = NULL, *dest = NULL; + bool found_path = false, found_dest, b = false; + int q; + + /* Acquire symlink name */ + p = path_make_absolute(de->d_name, path); + if (!p) + return -ENOMEM; + + /* Acquire symlink destination */ + q = readlink_malloc(p, &dest); + if (q == -ENOENT) + continue; + if (q < 0) { + if (r == 0) + r = q; + continue; + } + + /* Make absolute */ + if (!path_is_absolute(dest)) { + char *x; + + x = path_join(root_dir, dest); + if (!x) + return -ENOMEM; + + free_and_replace(dest, x); + } + + assert(unit_name_is_valid(i->name, UNIT_NAME_ANY)); + if (!ignore_same_name) + /* Check if the symlink itself matches what we are looking for. + * + * If ignore_same_name is specified, we are in one of the directories which + * have lower priority than the unit file, and even if a file or symlink with + * this name was found, we should ignore it. */ + found_path = streq(de->d_name, i->name); + + /* Check if what the symlink points to matches what we are looking for */ + found_dest = streq(basename(dest), i->name); + + if (found_path && found_dest) { + _cleanup_free_ char *t = NULL; + + /* Filter out same name links in the main + * config path */ + t = path_make_absolute(i->name, config_path); + if (!t) + return -ENOMEM; + + b = path_equal(t, p); + } + + if (b) + *same_name_link = true; + else if (found_path || found_dest) { + if (!match_aliases) + return 1; + + /* Check if symlink name is in the set of names used by [Install] */ + q = is_symlink_with_known_name(i, de->d_name); + if (q < 0) + return q; + if (q > 0) + return 1; + } + } + } + + return r; +} + +static int find_symlinks( + const char *root_dir, + const UnitFileInstallInfo *i, + bool match_name, + bool ignore_same_name, + const char *config_path, + bool *same_name_link) { + + int fd; + + assert(i); + assert(config_path); + assert(same_name_link); + + fd = open(config_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC); + if (fd < 0) { + if (IN_SET(errno, ENOENT, ENOTDIR, EACCES)) + return 0; + return -errno; + } + + /* This takes possession of fd and closes it */ + return find_symlinks_fd(root_dir, i, match_name, ignore_same_name, fd, + config_path, config_path, same_name_link); +} + +static int find_symlinks_in_scope( + UnitFileScope scope, + const LookupPaths *paths, + const UnitFileInstallInfo *i, + bool match_name, + UnitFileState *state) { + + bool same_name_link_runtime = false, same_name_link_config = false; + bool enabled_in_runtime = false, enabled_at_all = false; + bool ignore_same_name = false; + char **p; + int r; + + assert(paths); + assert(i); + + /* As we iterate over the list of search paths in paths->search_path, we may encounter "same name" + * symlinks. The ones which are "below" (i.e. have lower priority) than the unit file itself are + * effectively masked, so we should ignore them. */ + + STRV_FOREACH(p, paths->search_path) { + bool same_name_link = false; + + r = find_symlinks(paths->root_dir, i, match_name, ignore_same_name, *p, &same_name_link); + if (r < 0) + return r; + if (r > 0) { + /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */ + + if (path_equal_ptr(*p, paths->persistent_config)) { + /* This is the best outcome, let's return it immediately. */ + *state = UNIT_FILE_ENABLED; + return 1; + } + + /* look for global enablement of user units */ + if (scope == UNIT_FILE_USER && path_is_user_config_dir(*p)) { + *state = UNIT_FILE_ENABLED; + return 1; + } + + r = path_is_runtime(paths, *p, false); + if (r < 0) + return r; + if (r > 0) + enabled_in_runtime = true; + else + enabled_at_all = true; + + } else if (same_name_link) { + if (path_equal_ptr(*p, paths->persistent_config)) + same_name_link_config = true; + else { + r = path_is_runtime(paths, *p, false); + if (r < 0) + return r; + if (r > 0) + same_name_link_runtime = true; + } + } + + /* Check if next iteration will be "below" the unit file (either a regular file + * or a symlink), and hence should be ignored */ + if (!ignore_same_name && path_startswith(i->path, *p)) + ignore_same_name = true; + } + + if (enabled_in_runtime) { + *state = UNIT_FILE_ENABLED_RUNTIME; + return 1; + } + + /* Here's a special rule: if the unit we are looking for is an instance, and it symlinked in the search path + * outside of runtime and configuration directory, then we consider it statically enabled. Note we do that only + * for instance, not for regular names, as those are merely aliases, while instances explicitly instantiate + * something, and hence are a much stronger concept. */ + if (enabled_at_all && unit_name_is_valid(i->name, UNIT_NAME_INSTANCE)) { + *state = UNIT_FILE_STATIC; + return 1; + } + + /* Hmm, we didn't find it, but maybe we found the same name + * link? */ + if (same_name_link_config) { + *state = UNIT_FILE_LINKED; + return 1; + } + if (same_name_link_runtime) { + *state = UNIT_FILE_LINKED_RUNTIME; + return 1; + } + + return 0; +} + +static void install_info_free(UnitFileInstallInfo *i) { + + if (!i) + return; + + free(i->name); + free(i->path); + strv_free(i->aliases); + strv_free(i->wanted_by); + strv_free(i->required_by); + strv_free(i->also); + free(i->default_instance); + free(i->symlink_target); + free(i); +} + +static void install_context_done(InstallContext *c) { + assert(c); + + c->will_process = ordered_hashmap_free_with_destructor(c->will_process, install_info_free); + c->have_processed = ordered_hashmap_free_with_destructor(c->have_processed, install_info_free); +} + +static UnitFileInstallInfo *install_info_find(InstallContext *c, const char *name) { + UnitFileInstallInfo *i; + + i = ordered_hashmap_get(c->have_processed, name); + if (i) + return i; + + return ordered_hashmap_get(c->will_process, name); +} + +static int install_info_may_process( + const UnitFileInstallInfo *i, + const LookupPaths *paths, + UnitFileChange **changes, + size_t *n_changes) { + assert(i); + assert(paths); + + /* Checks whether the loaded unit file is one we should process, or is masked, + * transient or generated and thus not subject to enable/disable operations. */ + + if (i->type == UNIT_FILE_TYPE_MASKED) { + unit_file_changes_add(changes, n_changes, -ERFKILL, i->path, NULL); + return -ERFKILL; + } + if (path_is_generator(paths, i->path) || + path_is_transient(paths, i->path)) { + unit_file_changes_add(changes, n_changes, -EADDRNOTAVAIL, i->path, NULL); + return -EADDRNOTAVAIL; + } + + return 0; +} + +/** + * Adds a new UnitFileInstallInfo entry under name in the InstallContext.will_process + * hashmap, or retrieves the existing one if already present. + * + * Returns negative on error, 0 if the unit was already known, 1 otherwise. + */ +static int install_info_add( + InstallContext *c, + const char *name, + const char *path, + bool auxiliary, + UnitFileInstallInfo **ret) { + + UnitFileInstallInfo *i = NULL; + int r; + + assert(c); + assert(name || path); + + if (!name) + name = basename(path); + + if (!unit_name_is_valid(name, UNIT_NAME_ANY)) + return -EINVAL; + + i = install_info_find(c, name); + if (i) { + i->auxiliary = i->auxiliary && auxiliary; + + if (ret) + *ret = i; + return 0; + } + + r = ordered_hashmap_ensure_allocated(&c->will_process, &string_hash_ops); + if (r < 0) + return r; + + i = new(UnitFileInstallInfo, 1); + if (!i) + return -ENOMEM; + + *i = (UnitFileInstallInfo) { + .type = _UNIT_FILE_TYPE_INVALID, + .auxiliary = auxiliary, + }; + + i->name = strdup(name); + if (!i->name) { + r = -ENOMEM; + goto fail; + } + + if (path) { + i->path = strdup(path); + if (!i->path) { + r = -ENOMEM; + goto fail; + } + } + + r = ordered_hashmap_put(c->will_process, i->name, i); + if (r < 0) + goto fail; + + if (ret) + *ret = i; + + return 1; + +fail: + install_info_free(i); + return r; +} + +static int config_parse_alias( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + UnitType type; + + assert(unit); + assert(filename); + assert(lvalue); + assert(rvalue); + + type = unit_name_to_type(unit); + if (!unit_type_may_alias(type)) + return log_syntax(unit, LOG_WARNING, filename, line, 0, + "Alias= is not allowed for %s units, ignoring.", + unit_type_to_string(type)); + + return config_parse_strv(unit, filename, line, section, section_line, + lvalue, ltype, rvalue, data, userdata); +} + +static int config_parse_also( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + UnitFileInstallInfo *info = userdata, *alsoinfo = NULL; + InstallContext *c = data; + int r; + + assert(unit); + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *word = NULL, *printed = NULL; + + r = extract_first_word(&rvalue, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + r = install_full_printf(info, word, &printed); + if (r < 0) + return r; + + if (!unit_name_is_valid(printed, UNIT_NAME_ANY)) + return -EINVAL; + + r = install_info_add(c, printed, NULL, true, &alsoinfo); + if (r < 0) + return r; + + r = strv_push(&info->also, printed); + if (r < 0) + return r; + + printed = NULL; + } + + return 0; +} + +static int config_parse_default_instance( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + UnitFileInstallInfo *i = data; + _cleanup_free_ char *printed = NULL; + int r; + + assert(unit); + assert(filename); + assert(lvalue); + assert(rvalue); + + if (unit_name_is_valid(unit, UNIT_NAME_INSTANCE)) + /* When enabling an instance, we might be using a template unit file, + * but we should ignore DefaultInstance silently. */ + return 0; + if (!unit_name_is_valid(unit, UNIT_NAME_TEMPLATE)) + return log_syntax(unit, LOG_WARNING, filename, line, 0, + "DefaultInstance= only makes sense for template units, ignoring."); + + r = install_full_printf(i, rvalue, &printed); + if (r < 0) + return r; + + if (isempty(printed)) { + i->default_instance = mfree(i->default_instance); + return 0; + } + + if (!unit_instance_is_valid(printed)) + return log_syntax(unit, LOG_WARNING, filename, line, SYNTHETIC_ERRNO(EINVAL), + "Invalid DefaultInstance= value \"%s\".", printed); + + return free_and_replace(i->default_instance, printed); +} + +static int unit_file_load( + InstallContext *c, + UnitFileInstallInfo *info, + const char *path, + const char *root_dir, + SearchFlags flags) { + + const ConfigTableItem items[] = { + { "Install", "Alias", config_parse_alias, 0, &info->aliases }, + { "Install", "WantedBy", config_parse_strv, 0, &info->wanted_by }, + { "Install", "RequiredBy", config_parse_strv, 0, &info->required_by }, + { "Install", "DefaultInstance", config_parse_default_instance, 0, info }, + { "Install", "Also", config_parse_also, 0, c }, + {} + }; + + UnitType type; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_close_ int fd = -1; + struct stat st; + int r; + + assert(info); + assert(path); + + if (!(flags & SEARCH_DROPIN)) { + /* Loading or checking for the main unit file… */ + + type = unit_name_to_type(info->name); + if (type < 0) + return -EINVAL; + if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) && !unit_type_may_template(type)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unit type %s cannot be templated.", unit_type_to_string(type)); + + if (!(flags & SEARCH_LOAD)) { + r = lstat(path, &st); + if (r < 0) + return -errno; + + if (null_or_empty(&st)) + info->type = UNIT_FILE_TYPE_MASKED; + else if (S_ISREG(st.st_mode)) + info->type = UNIT_FILE_TYPE_REGULAR; + else if (S_ISLNK(st.st_mode)) + return -ELOOP; + else if (S_ISDIR(st.st_mode)) + return -EISDIR; + else + return -ENOTTY; + + return 0; + } + + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + } else { + /* Operating on a drop-in file. If we aren't supposed to load the unit file drop-ins don't matter, let's hence shortcut this. */ + + if (!(flags & SEARCH_LOAD)) + return 0; + + fd = chase_symlinks_and_open(path, root_dir, 0, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL); + if (fd < 0) + return fd; + } + + if (fstat(fd, &st) < 0) + return -errno; + + if (null_or_empty(&st)) { + if ((flags & SEARCH_DROPIN) == 0) + info->type = UNIT_FILE_TYPE_MASKED; + + return 0; + } + + r = stat_verify_regular(&st); + if (r < 0) + return r; + + f = fdopen(fd, "r"); + if (!f) + return -errno; + fd = -1; + + /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */ + assert(c); + + r = config_parse(info->name, path, f, + NULL, + config_item_table_lookup, items, + CONFIG_PARSE_RELAXED|CONFIG_PARSE_ALLOW_INCLUDE, info); + if (r < 0) + return log_debug_errno(r, "Failed to parse %s: %m", info->name); + + if ((flags & SEARCH_DROPIN) == 0) + info->type = UNIT_FILE_TYPE_REGULAR; + + return + (int) strv_length(info->aliases) + + (int) strv_length(info->wanted_by) + + (int) strv_length(info->required_by); +} + +static int unit_file_load_or_readlink( + InstallContext *c, + UnitFileInstallInfo *info, + const char *path, + const char *root_dir, + SearchFlags flags) { + + _cleanup_free_ char *target = NULL; + int r; + + r = unit_file_load(c, info, path, root_dir, flags); + if (r != -ELOOP || (flags & SEARCH_DROPIN)) + return r; + + /* This is a symlink, let's read it. */ + + r = readlink_malloc(path, &target); + if (r < 0) + return r; + + if (path_equal(target, "/dev/null")) + info->type = UNIT_FILE_TYPE_MASKED; + else { + const char *bn; + UnitType a, b; + + bn = basename(target); + + if (unit_name_is_valid(info->name, UNIT_NAME_PLAIN)) { + + if (!unit_name_is_valid(bn, UNIT_NAME_PLAIN)) + return -EINVAL; + + } else if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) { + + if (!unit_name_is_valid(bn, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) + return -EINVAL; + + } else if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE)) { + + if (!unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) + return -EINVAL; + } else + return -EINVAL; + + /* Enforce that the symlink destination does not + * change the unit file type. */ + + a = unit_name_to_type(info->name); + b = unit_name_to_type(bn); + if (a < 0 || b < 0 || a != b) + return -EINVAL; + + if (path_is_absolute(target)) + /* This is an absolute path, prefix the root so that we always deal with fully qualified paths */ + info->symlink_target = path_join(root_dir, target); + else + /* This is a relative path, take it relative to the dir the symlink is located in. */ + info->symlink_target = file_in_same_dir(path, target); + if (!info->symlink_target) + return -ENOMEM; + + info->type = UNIT_FILE_TYPE_SYMLINK; + } + + return 0; +} + +static int unit_file_search( + InstallContext *c, + UnitFileInstallInfo *info, + const LookupPaths *paths, + SearchFlags flags) { + + const char *dropin_dir_name = NULL, *dropin_template_dir_name = NULL; + _cleanup_strv_free_ char **dirs = NULL, **files = NULL; + _cleanup_free_ char *template = NULL; + bool found_unit = false; + int r, result; + char **p; + + assert(info); + assert(paths); + + /* Was this unit already loaded? */ + if (info->type != _UNIT_FILE_TYPE_INVALID) + return 0; + + if (info->path) + return unit_file_load_or_readlink(c, info, info->path, paths->root_dir, flags); + + assert(info->name); + + if (unit_name_is_valid(info->name, UNIT_NAME_INSTANCE)) { + r = unit_name_template(info->name, &template); + if (r < 0) + return r; + } + + STRV_FOREACH(p, paths->search_path) { + _cleanup_free_ char *path = NULL; + + path = path_join(*p, info->name); + if (!path) + return -ENOMEM; + + r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags); + if (r >= 0) { + info->path = TAKE_PTR(path); + result = r; + found_unit = true; + break; + } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES)) + return r; + } + + if (!found_unit && template) { + + /* Unit file doesn't exist, however instance + * enablement was requested. We will check if it is + * possible to load template unit file. */ + + STRV_FOREACH(p, paths->search_path) { + _cleanup_free_ char *path = NULL; + + path = path_join(*p, template); + if (!path) + return -ENOMEM; + + r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags); + if (r >= 0) { + info->path = TAKE_PTR(path); + result = r; + found_unit = true; + break; + } else if (!IN_SET(r, -ENOENT, -ENOTDIR, -EACCES)) + return r; + } + } + + if (!found_unit) + return log_debug_errno(SYNTHETIC_ERRNO(ENOENT), + "Cannot find unit %s%s%s.", + info->name, template ? " or " : "", strempty(template)); + + if (info->type == UNIT_FILE_TYPE_MASKED) + return result; + + /* Search for drop-in directories */ + + dropin_dir_name = strjoina(info->name, ".d"); + STRV_FOREACH(p, paths->search_path) { + char *path; + + path = path_join(*p, dropin_dir_name); + if (!path) + return -ENOMEM; + + r = strv_consume(&dirs, path); + if (r < 0) + return r; + } + + if (template) { + dropin_template_dir_name = strjoina(template, ".d"); + STRV_FOREACH(p, paths->search_path) { + char *path; + + path = path_join(*p, dropin_template_dir_name); + if (!path) + return -ENOMEM; + + r = strv_consume(&dirs, path); + if (r < 0) + return r; + } + } + + /* Load drop-in conf files */ + + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) dirs); + if (r < 0) + return log_debug_errno(r, "Failed to get list of conf files: %m"); + + STRV_FOREACH(p, files) { + r = unit_file_load_or_readlink(c, info, *p, paths->root_dir, flags | SEARCH_DROPIN); + if (r < 0) + return log_debug_errno(r, "Failed to load conf file %s: %m", *p); + } + + return result; +} + +static int install_info_follow( + InstallContext *c, + UnitFileInstallInfo *i, + const char *root_dir, + SearchFlags flags, + bool ignore_different_name) { + + assert(c); + assert(i); + + if (i->type != UNIT_FILE_TYPE_SYMLINK) + return -EINVAL; + if (!i->symlink_target) + return -EINVAL; + + /* If the basename doesn't match, the caller should add a + * complete new entry for this. */ + + if (!ignore_different_name && !streq(basename(i->symlink_target), i->name)) + return -EXDEV; + + free_and_replace(i->path, i->symlink_target); + i->type = _UNIT_FILE_TYPE_INVALID; + + return unit_file_load_or_readlink(c, i, i->path, root_dir, flags); +} + +/** + * Search for the unit file. If the unit name is a symlink, follow the symlink to the + * target, maybe more than once. Propagate the instance name if present. + */ +static int install_info_traverse( + UnitFileScope scope, + InstallContext *c, + const LookupPaths *paths, + UnitFileInstallInfo *start, + SearchFlags flags, + UnitFileInstallInfo **ret) { + + UnitFileInstallInfo *i; + unsigned k = 0; + int r; + + assert(paths); + assert(start); + assert(c); + + r = unit_file_search(c, start, paths, flags); + if (r < 0) + return r; + + i = start; + while (i->type == UNIT_FILE_TYPE_SYMLINK) { + /* Follow the symlink */ + + if (++k > UNIT_FILE_FOLLOW_SYMLINK_MAX) + return -ELOOP; + + if (!(flags & SEARCH_FOLLOW_CONFIG_SYMLINKS)) { + r = path_is_config(paths, i->path, true); + if (r < 0) + return r; + if (r > 0) + return -ELOOP; + } + + r = install_info_follow(c, i, paths->root_dir, flags, false); + if (r == -EXDEV) { + _cleanup_free_ char *buffer = NULL; + const char *bn; + + /* Target has a different name, create a new + * install info object for that, and continue + * with that. */ + + bn = basename(i->symlink_target); + + if (unit_name_is_valid(i->name, UNIT_NAME_INSTANCE) && + unit_name_is_valid(bn, UNIT_NAME_TEMPLATE)) { + + _cleanup_free_ char *instance = NULL; + + r = unit_name_to_instance(i->name, &instance); + if (r < 0) + return r; + + r = unit_name_replace_instance(bn, instance, &buffer); + if (r < 0) + return r; + + if (streq(buffer, i->name)) { + + /* We filled in the instance, and the target stayed the same? If so, then let's + * honour the link as it is. */ + + r = install_info_follow(c, i, paths->root_dir, flags, true); + if (r < 0) + return r; + + continue; + } + + bn = buffer; + } + + r = install_info_add(c, bn, NULL, false, &i); + if (r < 0) + return r; + + /* Try again, with the new target we found. */ + r = unit_file_search(c, i, paths, flags); + if (r == -ENOENT) + /* Translate error code to highlight this specific case */ + return -ENOLINK; + } + + if (r < 0) + return r; + } + + if (ret) + *ret = i; + + return 0; +} + +/** + * Call install_info_add() with name_or_path as the path (if name_or_path starts with "/") + * or the name (otherwise). root_dir is prepended to the path. + */ +static int install_info_add_auto( + InstallContext *c, + const LookupPaths *paths, + const char *name_or_path, + UnitFileInstallInfo **ret) { + + assert(c); + assert(name_or_path); + + if (path_is_absolute(name_or_path)) { + const char *pp; + + pp = prefix_roota(paths->root_dir, name_or_path); + + return install_info_add(c, NULL, pp, false, ret); + } else + return install_info_add(c, name_or_path, NULL, false, ret); +} + +static int install_info_discover( + UnitFileScope scope, + InstallContext *c, + const LookupPaths *paths, + const char *name, + SearchFlags flags, + UnitFileInstallInfo **ret, + UnitFileChange **changes, + size_t *n_changes) { + + UnitFileInstallInfo *i; + int r; + + assert(c); + assert(paths); + assert(name); + + r = install_info_add_auto(c, paths, name, &i); + if (r >= 0) + r = install_info_traverse(scope, c, paths, i, flags, ret); + + if (r < 0) + unit_file_changes_add(changes, n_changes, r, name, NULL); + return r; +} + +static int install_info_discover_and_check( + UnitFileScope scope, + InstallContext *c, + const LookupPaths *paths, + const char *name, + SearchFlags flags, + UnitFileInstallInfo **ret, + UnitFileChange **changes, + size_t *n_changes) { + + int r; + + r = install_info_discover(scope, c, paths, name, flags, ret, changes, n_changes); + if (r < 0) + return r; + + return install_info_may_process(ret ? *ret : NULL, paths, changes, n_changes); +} + +static int install_info_symlink_alias( + UnitFileInstallInfo *i, + const LookupPaths *paths, + const char *config_path, + bool force, + UnitFileChange **changes, + size_t *n_changes) { + + char **s; + int r = 0, q; + + assert(i); + assert(paths); + assert(config_path); + + STRV_FOREACH(s, i->aliases) { + _cleanup_free_ char *alias_path = NULL, *dst = NULL; + + q = install_full_printf(i, *s, &dst); + if (q < 0) + return q; + + alias_path = path_make_absolute(dst, config_path); + if (!alias_path) + return -ENOMEM; + + q = create_symlink(paths, i->path, alias_path, force, changes, n_changes); + if (r == 0) + r = q; + } + + return r; +} + +static int install_info_symlink_wants( + UnitFileInstallInfo *i, + const LookupPaths *paths, + const char *config_path, + char **list, + const char *suffix, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_free_ char *buf = NULL; + const char *n; + char **s; + int r = 0, q; + + assert(i); + assert(paths); + assert(config_path); + + if (strv_isempty(list)) + return 0; + + if (unit_name_is_valid(i->name, UNIT_NAME_TEMPLATE)) { + UnitFileInstallInfo instance = { + .type = _UNIT_FILE_TYPE_INVALID, + }; + _cleanup_free_ char *path = NULL; + + /* If this is a template, and we have no instance, don't do anything */ + if (!i->default_instance) + return 1; + + r = unit_name_replace_instance(i->name, i->default_instance, &buf); + if (r < 0) + return r; + + instance.name = buf; + r = unit_file_search(NULL, &instance, paths, SEARCH_FOLLOW_CONFIG_SYMLINKS); + if (r < 0) + return r; + + path = TAKE_PTR(instance.path); + + if (instance.type == UNIT_FILE_TYPE_MASKED) { + unit_file_changes_add(changes, n_changes, -ERFKILL, path, NULL); + return -ERFKILL; + } + + n = buf; + } else + n = i->name; + + STRV_FOREACH(s, list) { + _cleanup_free_ char *path = NULL, *dst = NULL; + + q = install_full_printf(i, *s, &dst); + if (q < 0) + return q; + + if (!unit_name_is_valid(dst, UNIT_NAME_ANY)) { + unit_file_changes_add(changes, n_changes, -EUCLEAN, dst, NULL); + r = -EUCLEAN; + continue; + } + + path = strjoin(config_path, "/", dst, suffix, n); + if (!path) + return -ENOMEM; + + q = create_symlink(paths, i->path, path, true, changes, n_changes); + if (r == 0) + r = q; + } + + return r; +} + +static int install_info_symlink_link( + UnitFileInstallInfo *i, + const LookupPaths *paths, + const char *config_path, + bool force, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_free_ char *path = NULL; + int r; + + assert(i); + assert(paths); + assert(config_path); + assert(i->path); + + r = in_search_path(paths, i->path); + if (r < 0) + return r; + if (r > 0) + return 0; + + path = path_join(config_path, i->name); + if (!path) + return -ENOMEM; + + return create_symlink(paths, i->path, path, force, changes, n_changes); +} + +static int install_info_apply( + UnitFileInstallInfo *i, + const LookupPaths *paths, + const char *config_path, + bool force, + UnitFileChange **changes, + size_t *n_changes) { + + int r, q; + + assert(i); + assert(paths); + assert(config_path); + + if (i->type != UNIT_FILE_TYPE_REGULAR) + return 0; + + r = install_info_symlink_alias(i, paths, config_path, force, changes, n_changes); + + q = install_info_symlink_wants(i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes); + if (r == 0) + r = q; + + q = install_info_symlink_wants(i, paths, config_path, i->required_by, ".requires/", changes, n_changes); + if (r == 0) + r = q; + + q = install_info_symlink_link(i, paths, config_path, force, changes, n_changes); + /* Do not count links to the unit file towards the "carries_install_info" count */ + if (r == 0 && q < 0) + r = q; + + return r; +} + +static int install_context_apply( + UnitFileScope scope, + InstallContext *c, + const LookupPaths *paths, + const char *config_path, + bool force, + SearchFlags flags, + UnitFileChange **changes, + size_t *n_changes) { + + UnitFileInstallInfo *i; + int r; + + assert(c); + assert(paths); + assert(config_path); + + if (ordered_hashmap_isempty(c->will_process)) + return 0; + + r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops); + if (r < 0) + return r; + + r = 0; + while ((i = ordered_hashmap_first(c->will_process))) { + int q; + + q = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name); + if (q < 0) + return q; + + q = install_info_traverse(scope, c, paths, i, flags, NULL); + if (q < 0) { + unit_file_changes_add(changes, n_changes, q, i->name, NULL); + return q; + } + + /* We can attempt to process a masked unit when a different unit + * that we were processing specifies it in Also=. */ + if (i->type == UNIT_FILE_TYPE_MASKED) { + unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path, NULL); + if (r >= 0) + /* Assume that something *could* have been enabled here, + * avoid "empty [Install] section" warning. */ + r += 1; + continue; + } + + if (i->type != UNIT_FILE_TYPE_REGULAR) + continue; + + q = install_info_apply(i, paths, config_path, force, changes, n_changes); + if (r >= 0) { + if (q < 0) + r = q; + else + r += q; + } + } + + return r; +} + +static int install_context_mark_for_removal( + UnitFileScope scope, + InstallContext *c, + const LookupPaths *paths, + Set **remove_symlinks_to, + const char *config_path, + UnitFileChange **changes, + size_t *n_changes) { + + UnitFileInstallInfo *i; + int r; + + assert(c); + assert(paths); + assert(config_path); + + /* Marks all items for removal */ + + if (ordered_hashmap_isempty(c->will_process)) + return 0; + + r = ordered_hashmap_ensure_allocated(&c->have_processed, &string_hash_ops); + if (r < 0) + return r; + + while ((i = ordered_hashmap_first(c->will_process))) { + + r = ordered_hashmap_move_one(c->have_processed, c->will_process, i->name); + if (r < 0) + return r; + + r = install_info_traverse(scope, c, paths, i, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL); + if (r == -ENOLINK) { + log_debug_errno(r, "Name %s leads to a dangling symlink, removing name.", i->name); + unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_DANGLING, i->path ?: i->name, NULL); + } else if (r == -ENOENT) { + + if (i->auxiliary) /* some unit specified in Also= or similar is missing */ + log_debug_errno(r, "Auxiliary unit of %s not found, removing name.", i->name); + else { + log_debug_errno(r, "Unit %s not found, removing name.", i->name); + unit_file_changes_add(changes, n_changes, r, i->path ?: i->name, NULL); + } + + } else if (r < 0) { + log_debug_errno(r, "Failed to find unit %s, removing name: %m", i->name); + unit_file_changes_add(changes, n_changes, r, i->path ?: i->name, NULL); + } else if (i->type == UNIT_FILE_TYPE_MASKED) { + log_debug("Unit file %s is masked, ignoring.", i->name); + unit_file_changes_add(changes, n_changes, UNIT_FILE_IS_MASKED, i->path ?: i->name, NULL); + continue; + } else if (i->type != UNIT_FILE_TYPE_REGULAR) { + log_debug("Unit %s has type %s, ignoring.", i->name, unit_file_type_to_string(i->type) ?: "invalid"); + continue; + } + + r = mark_symlink_for_removal(remove_symlinks_to, i->name); + if (r < 0) + return r; + } + + return 0; +} + +int unit_file_mask( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + const char *config_path; + char **i; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + if (!config_path) + return -ENXIO; + + STRV_FOREACH(i, files) { + _cleanup_free_ char *path = NULL; + int q; + + if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) { + if (r == 0) + r = -EINVAL; + continue; + } + + path = path_make_absolute(*i, config_path); + if (!path) + return -ENOMEM; + + q = create_symlink(&paths, "/dev/null", path, !!(flags & UNIT_FILE_FORCE), changes, n_changes); + if (q < 0 && r >= 0) + r = q; + } + + return r; +} + +int unit_file_unmask( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; + _cleanup_strv_free_ char **todo = NULL; + size_t n_todo = 0, n_allocated = 0; + const char *config_path; + char **i; + bool dry_run; + int r, q; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + if (!config_path) + return -ENXIO; + + dry_run = !!(flags & UNIT_FILE_DRY_RUN); + + STRV_FOREACH(i, files) { + _cleanup_free_ char *path = NULL; + + if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) + return -EINVAL; + + path = path_make_absolute(*i, config_path); + if (!path) + return -ENOMEM; + + r = null_or_empty_path(path); + if (r == -ENOENT) + continue; + if (r < 0) + return r; + if (r == 0) + continue; + + if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) + return -ENOMEM; + + todo[n_todo] = strdup(*i); + if (!todo[n_todo]) + return -ENOMEM; + + n_todo++; + } + + strv_uniq(todo); + + r = 0; + STRV_FOREACH(i, todo) { + _cleanup_free_ char *path = NULL; + const char *rp; + + path = path_make_absolute(*i, config_path); + if (!path) + return -ENOMEM; + + if (!dry_run && unlink(path) < 0) { + if (errno != ENOENT) { + if (r >= 0) + r = -errno; + unit_file_changes_add(changes, n_changes, -errno, path, NULL); + } + + continue; + } + + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); + + rp = skip_root(&paths, path); + q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path); + if (q < 0) + return q; + } + + q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes); + if (r >= 0) + r = q; + + return r; +} + +int unit_file_link( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_strv_free_ char **todo = NULL; + size_t n_todo = 0, n_allocated = 0; + const char *config_path; + char **i; + int r, q; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + if (!config_path) + return -ENXIO; + + STRV_FOREACH(i, files) { + _cleanup_free_ char *full = NULL; + struct stat st; + char *fn; + + if (!path_is_absolute(*i)) + return -EINVAL; + + fn = basename(*i); + if (!unit_name_is_valid(fn, UNIT_NAME_ANY)) + return -EINVAL; + + full = path_join(paths.root_dir, *i); + if (!full) + return -ENOMEM; + + if (lstat(full, &st) < 0) + return -errno; + r = stat_verify_regular(&st); + if (r < 0) + return r; + + q = in_search_path(&paths, *i); + if (q < 0) + return q; + if (q > 0) + continue; + + if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) + return -ENOMEM; + + todo[n_todo] = strdup(*i); + if (!todo[n_todo]) + return -ENOMEM; + + n_todo++; + } + + strv_uniq(todo); + + r = 0; + STRV_FOREACH(i, todo) { + _cleanup_free_ char *new_path = NULL; + + new_path = path_make_absolute(basename(*i), config_path); + if (!new_path) + return -ENOMEM; + + q = create_symlink(&paths, *i, new_path, !!(flags & UNIT_FILE_FORCE), changes, n_changes); + if (q < 0 && r >= 0) + r = q; + } + + return r; +} + +static int path_shall_revert(const LookupPaths *paths, const char *path) { + int r; + + assert(paths); + assert(path); + + /* Checks whether the path is one where the drop-in directories shall be removed. */ + + r = path_is_config(paths, path, true); + if (r != 0) + return r; + + r = path_is_control(paths, path); + if (r != 0) + return r; + + return path_is_transient(paths, path); +} + +int unit_file_revert( + UnitFileScope scope, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_strv_free_ char **todo = NULL; + size_t n_todo = 0, n_allocated = 0; + char **i; + int r, q; + + /* Puts a unit file back into vendor state. This means: + * + * a) we remove all drop-in snippets added by the user ("config"), add to transient units ("transient"), and + * added via "systemctl set-property" ("control"), but not if the drop-in is generated ("generated"). + * + * c) if there's a vendor unit file (i.e. one in /usr) we remove any configured overriding unit files (i.e. in + * "config", but not in "transient" or "control" or even "generated"). + * + * We remove all that in both the runtime and the persistent directories, if that applies. + */ + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + STRV_FOREACH(i, files) { + bool has_vendor = false; + char **p; + + if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) + return -EINVAL; + + STRV_FOREACH(p, paths.search_path) { + _cleanup_free_ char *path = NULL, *dropin = NULL; + struct stat st; + + path = path_make_absolute(*i, *p); + if (!path) + return -ENOMEM; + + r = lstat(path, &st); + if (r < 0) { + if (errno != ENOENT) + return -errno; + } else if (S_ISREG(st.st_mode)) { + /* Check if there's a vendor version */ + r = path_is_vendor(&paths, path); + if (r < 0) + return r; + if (r > 0) + has_vendor = true; + } + + dropin = strjoin(path, ".d"); + if (!dropin) + return -ENOMEM; + + r = lstat(dropin, &st); + if (r < 0) { + if (errno != ENOENT) + return -errno; + } else if (S_ISDIR(st.st_mode)) { + /* Remove the drop-ins */ + r = path_shall_revert(&paths, dropin); + if (r < 0) + return r; + if (r > 0) { + if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) + return -ENOMEM; + + todo[n_todo++] = TAKE_PTR(dropin); + } + } + } + + if (!has_vendor) + continue; + + /* OK, there's a vendor version, hence drop all configuration versions */ + STRV_FOREACH(p, paths.search_path) { + _cleanup_free_ char *path = NULL; + struct stat st; + + path = path_make_absolute(*i, *p); + if (!path) + return -ENOMEM; + + r = lstat(path, &st); + if (r < 0) { + if (errno != ENOENT) + return -errno; + } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { + r = path_is_config(&paths, path, true); + if (r < 0) + return r; + if (r > 0) { + if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) + return -ENOMEM; + + todo[n_todo++] = TAKE_PTR(path); + } + } + } + } + + strv_uniq(todo); + + r = 0; + STRV_FOREACH(i, todo) { + _cleanup_strv_free_ char **fs = NULL; + const char *rp; + char **j; + + (void) get_files_in_directory(*i, &fs); + + q = rm_rf(*i, REMOVE_ROOT|REMOVE_PHYSICAL); + if (q < 0 && q != -ENOENT && r >= 0) { + r = q; + continue; + } + + STRV_FOREACH(j, fs) { + _cleanup_free_ char *t = NULL; + + t = path_join(*i, *j); + if (!t) + return -ENOMEM; + + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, t, NULL); + } + + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, *i, NULL); + + rp = skip_root(&paths, *i); + q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: *i); + if (q < 0) + return q; + } + + q = remove_marked_symlinks(remove_symlinks_to, paths.runtime_config, &paths, false, changes, n_changes); + if (r >= 0) + r = q; + + q = remove_marked_symlinks(remove_symlinks_to, paths.persistent_config, &paths, false, changes, n_changes); + if (r >= 0) + r = q; + + return r; +} + +int unit_file_add_dependency( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + const char *target, + UnitDependency dep, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(install_context_done) InstallContext c = {}; + UnitFileInstallInfo *i, *target_info; + const char *config_path; + char **f; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + assert(target); + + if (!IN_SET(dep, UNIT_WANTS, UNIT_REQUIRES)) + return -EINVAL; + + if (!unit_name_is_valid(target, UNIT_NAME_ANY)) + return -EINVAL; + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + if (!config_path) + return -ENXIO; + + r = install_info_discover_and_check(scope, &c, &paths, target, SEARCH_FOLLOW_CONFIG_SYMLINKS, + &target_info, changes, n_changes); + if (r < 0) + return r; + + assert(target_info->type == UNIT_FILE_TYPE_REGULAR); + + STRV_FOREACH(f, files) { + char ***l; + + r = install_info_discover_and_check(scope, &c, &paths, *f, SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); + if (r < 0) + return r; + + assert(i->type == UNIT_FILE_TYPE_REGULAR); + + /* We didn't actually load anything from the unit + * file, but instead just add in our new symlink to + * create. */ + + if (dep == UNIT_WANTS) + l = &i->wanted_by; + else + l = &i->required_by; + + strv_free(*l); + *l = strv_new(target_info->name); + if (!*l) + return -ENOMEM; + } + + return install_context_apply(scope, &c, &paths, config_path, !!(flags & UNIT_FILE_FORCE), SEARCH_FOLLOW_CONFIG_SYMLINKS, changes, n_changes); +} + +int unit_file_enable( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(install_context_done) InstallContext c = {}; + const char *config_path; + UnitFileInstallInfo *i; + char **f; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + if (!config_path) + return -ENXIO; + + STRV_FOREACH(f, files) { + r = install_info_discover_and_check(scope, &c, &paths, *f, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); + if (r < 0) + return r; + + assert(i->type == UNIT_FILE_TYPE_REGULAR); + } + + /* This will return the number of symlink rules that were + supposed to be created, not the ones actually created. This + is useful to determine whether the passed files had any + installation data at all. */ + + return install_context_apply(scope, &c, &paths, config_path, !!(flags & UNIT_FILE_FORCE), SEARCH_LOAD, changes, n_changes); +} + +int unit_file_disable( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(install_context_done) InstallContext c = {}; + _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; + const char *config_path; + char **i; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + if (!config_path) + return -ENXIO; + + STRV_FOREACH(i, files) { + if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) + return -EINVAL; + + r = install_info_add(&c, *i, NULL, false, NULL); + if (r < 0) + return r; + } + + r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, changes, n_changes); + if (r < 0) + return r; + + return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, !!(flags & UNIT_FILE_DRY_RUN), changes, n_changes); +} + +int unit_file_reenable( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes) { + + char **n; + int r; + size_t l, i; + + /* First, we invoke the disable command with only the basename... */ + l = strv_length(files); + n = newa(char*, l+1); + for (i = 0; i < l; i++) + n[i] = basename(files[i]); + n[i] = NULL; + + r = unit_file_disable(scope, flags, root_dir, n, changes, n_changes); + if (r < 0) + return r; + + /* But the enable command with the full name */ + return unit_file_enable(scope, flags, root_dir, files, changes, n_changes); +} + +int unit_file_set_default( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + const char *name, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(install_context_done) InstallContext c = {}; + UnitFileInstallInfo *i; + const char *new_path; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + assert(name); + + if (unit_name_to_type(name) != UNIT_TARGET) /* this also validates the name */ + return -EINVAL; + if (streq(name, SPECIAL_DEFAULT_TARGET)) + return -EINVAL; + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + r = install_info_discover_and_check(scope, &c, &paths, name, 0, &i, changes, n_changes); + if (r < 0) + return r; + + new_path = strjoina(paths.persistent_config, "/" SPECIAL_DEFAULT_TARGET); + return create_symlink(&paths, i->path, new_path, !!(flags & UNIT_FILE_FORCE), changes, n_changes); +} + +int unit_file_get_default( + UnitFileScope scope, + const char *root_dir, + char **name) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(install_context_done) InstallContext c = {}; + UnitFileInstallInfo *i; + char *n; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + assert(name); + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + r = install_info_discover(scope, &c, &paths, SPECIAL_DEFAULT_TARGET, SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, NULL, NULL); + if (r < 0) + return r; + r = install_info_may_process(i, &paths, NULL, 0); + if (r < 0) + return r; + + n = strdup(i->name); + if (!n) + return -ENOMEM; + + *name = n; + return 0; +} + +int unit_file_lookup_state( + UnitFileScope scope, + const LookupPaths *paths, + const char *name, + UnitFileState *ret) { + + _cleanup_(install_context_done) InstallContext c = {}; + UnitFileInstallInfo *i; + UnitFileState state; + int r; + + assert(paths); + assert(name); + + if (!unit_name_is_valid(name, UNIT_NAME_ANY)) + return -EINVAL; + + r = install_info_discover(scope, &c, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, NULL, NULL); + if (r < 0) + return log_debug_errno(r, "Failed to discover unit %s: %m", name); + + assert(IN_SET(i->type, UNIT_FILE_TYPE_REGULAR, UNIT_FILE_TYPE_MASKED)); + log_debug("Found unit %s at %s (%s)", name, strna(i->path), + i->type == UNIT_FILE_TYPE_REGULAR ? "regular file" : "mask"); + + /* Shortcut things, if the caller just wants to know if this unit exists. */ + if (!ret) + return 0; + + switch (i->type) { + + case UNIT_FILE_TYPE_MASKED: + r = path_is_runtime(paths, i->path, true); + if (r < 0) + return r; + + state = r > 0 ? UNIT_FILE_MASKED_RUNTIME : UNIT_FILE_MASKED; + break; + + case UNIT_FILE_TYPE_REGULAR: + r = path_is_generator(paths, i->path); + if (r < 0) + return r; + if (r > 0) { + state = UNIT_FILE_GENERATED; + break; + } + + r = path_is_transient(paths, i->path); + if (r < 0) + return r; + if (r > 0) { + state = UNIT_FILE_TRANSIENT; + break; + } + + /* Check if any of the Alias= symlinks have been created. + * We ignore other aliases, and only check those that would + * be created by systemctl enable for this unit. */ + r = find_symlinks_in_scope(scope, paths, i, true, &state); + if (r < 0) + return r; + if (r > 0) + break; + + /* Check if the file is known under other names. If it is, + * it might be in use. Report that as UNIT_FILE_INDIRECT. */ + r = find_symlinks_in_scope(scope, paths, i, false, &state); + if (r < 0) + return r; + if (r > 0) + state = UNIT_FILE_INDIRECT; + else { + if (unit_file_install_info_has_rules(i)) + state = UNIT_FILE_DISABLED; + else if (unit_file_install_info_has_also(i)) + state = UNIT_FILE_INDIRECT; + else + state = UNIT_FILE_STATIC; + } + + break; + + default: + assert_not_reached("Unexpected unit file type."); + } + + *ret = state; + return 0; +} + +int unit_file_get_state( + UnitFileScope scope, + const char *root_dir, + const char *name, + UnitFileState *ret) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + assert(name); + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + return unit_file_lookup_state(scope, &paths, name, ret); +} + +int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *name) { + _cleanup_(install_context_done) InstallContext c = {}; + int r; + + assert(paths); + assert(name); + + if (!unit_name_is_valid(name, UNIT_NAME_ANY)) + return -EINVAL; + + r = install_info_discover(scope, &c, paths, name, 0, NULL, NULL, NULL); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + return 1; +} + +static int split_pattern_into_name_and_instances(const char *pattern, char **out_unit_name, char ***out_instances) { + _cleanup_strv_free_ char **instances = NULL; + _cleanup_free_ char *unit_name = NULL; + int r; + + assert(pattern); + assert(out_instances); + assert(out_unit_name); + + r = extract_first_word(&pattern, &unit_name, NULL, EXTRACT_RETAIN_ESCAPE); + if (r < 0) + return r; + + /* We handle the instances logic when unit name is extracted */ + if (pattern) { + /* We only create instances when a rule of templated unit + * is seen. A rule like enable foo@.service a b c will + * result in an array of (a, b, c) as instance names */ + if (!unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) + return -EINVAL; + + instances = strv_split(pattern, WHITESPACE); + if (!instances) + return -ENOMEM; + + *out_instances = TAKE_PTR(instances); + } + + *out_unit_name = TAKE_PTR(unit_name); + + return 0; +} + +static int presets_find_config(UnitFileScope scope, const char *root_dir, char ***files) { + static const char* const system_dirs[] = {CONF_PATHS("systemd/system-preset"), NULL}; + static const char* const user_dirs[] = {CONF_PATHS_USR("systemd/user-preset"), NULL}; + const char* const* dirs; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + + if (scope == UNIT_FILE_SYSTEM) + dirs = system_dirs; + else if (IN_SET(scope, UNIT_FILE_GLOBAL, UNIT_FILE_USER)) + dirs = user_dirs; + else + assert_not_reached("Invalid unit file scope"); + + return conf_files_list_strv(files, ".preset", root_dir, 0, dirs); +} + +static int read_presets(UnitFileScope scope, const char *root_dir, Presets *presets) { + _cleanup_(presets_freep) Presets ps = {}; + size_t n_allocated = 0; + _cleanup_strv_free_ char **files = NULL; + char **p; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + assert(presets); + + r = presets_find_config(scope, root_dir, &files); + if (r < 0) + return r; + + STRV_FOREACH(p, files) { + _cleanup_fclose_ FILE *f; + int n = 0; + + f = fopen(*p, "re"); + if (!f) { + if (errno == ENOENT) + continue; + + return -errno; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + PresetRule rule = {}; + const char *parameter; + char *l; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return r; + if (r == 0) + break; + + l = strstrip(line); + n++; + + if (isempty(l)) + continue; + if (strchr(COMMENTS, *l)) + continue; + + parameter = first_word(l, "enable"); + if (parameter) { + char *unit_name; + char **instances = NULL; + + /* Unit_name will remain the same as parameter when no instances are specified */ + r = split_pattern_into_name_and_instances(parameter, &unit_name, &instances); + if (r < 0) { + log_syntax(NULL, LOG_WARNING, *p, n, r, "Couldn't parse line '%s'. Ignoring.", line); + continue; + } + + rule = (PresetRule) { + .pattern = unit_name, + .action = PRESET_ENABLE, + .instances = instances, + }; + } + + parameter = first_word(l, "disable"); + if (parameter) { + char *pattern; + + pattern = strdup(parameter); + if (!pattern) + return -ENOMEM; + + rule = (PresetRule) { + .pattern = pattern, + .action = PRESET_DISABLE, + }; + } + + if (rule.action) { + if (!GREEDY_REALLOC(ps.rules, n_allocated, ps.n_rules + 1)) + return -ENOMEM; + + ps.rules[ps.n_rules++] = rule; + continue; + } + + log_syntax(NULL, LOG_WARNING, *p, n, 0, "Couldn't parse line '%s'. Ignoring.", line); + } + } + + *presets = ps; + ps = (Presets){}; + + return 0; +} + +static int pattern_match_multiple_instances( + const PresetRule rule, + const char *unit_name, + char ***ret) { + + _cleanup_free_ char *templated_name = NULL; + int r; + + /* If no ret is needed or the rule itself does not have instances + * initialized, we return not matching */ + if (!ret || !rule.instances) + return 0; + + r = unit_name_template(unit_name, &templated_name); + if (r < 0) + return r; + if (!streq(rule.pattern, templated_name)) + return 0; + + /* Compose a list of specified instances when unit name is a template */ + if (unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { + _cleanup_free_ char *prefix = NULL; + _cleanup_strv_free_ char **out_strv = NULL; + char **iter; + + r = unit_name_to_prefix(unit_name, &prefix); + if (r < 0) + return r; + + STRV_FOREACH(iter, rule.instances) { + _cleanup_free_ char *name = NULL; + r = unit_name_build(prefix, *iter, ".service", &name); + if (r < 0) + return r; + r = strv_extend(&out_strv, name); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(out_strv); + return 1; + } else { + /* We now know the input unit name is an instance name */ + _cleanup_free_ char *instance_name = NULL; + + r = unit_name_to_instance(unit_name, &instance_name); + if (r < 0) + return r; + + if (strv_find(rule.instances, instance_name)) + return 1; + } + return 0; +} + +static int query_presets(const char *name, const Presets presets, char ***instance_name_list) { + PresetAction action = PRESET_UNKNOWN; + size_t i; + char **s; + if (!unit_name_is_valid(name, UNIT_NAME_ANY)) + return -EINVAL; + + for (i = 0; i < presets.n_rules; i++) + if (pattern_match_multiple_instances(presets.rules[i], name, instance_name_list) > 0 || + fnmatch(presets.rules[i].pattern, name, FNM_NOESCAPE) == 0) { + action = presets.rules[i].action; + break; + } + + switch (action) { + case PRESET_UNKNOWN: + log_debug("Preset files don't specify rule for %s. Enabling.", name); + return 1; + case PRESET_ENABLE: + if (instance_name_list && *instance_name_list) + STRV_FOREACH(s, *instance_name_list) + log_debug("Preset files say enable %s.", *s); + else + log_debug("Preset files say enable %s.", name); + return 1; + case PRESET_DISABLE: + log_debug("Preset files say disable %s.", name); + return 0; + default: + assert_not_reached("invalid preset action"); + } +} + +int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name) { + _cleanup_(presets_freep) Presets presets = {}; + int r; + + r = read_presets(scope, root_dir, &presets); + if (r < 0) + return r; + + return query_presets(name, presets, NULL); +} + +static int execute_preset( + UnitFileScope scope, + InstallContext *plus, + InstallContext *minus, + const LookupPaths *paths, + const char *config_path, + char **files, + UnitFilePresetMode mode, + bool force, + UnitFileChange **changes, + size_t *n_changes) { + + int r; + + assert(plus); + assert(minus); + assert(paths); + assert(config_path); + + if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) { + _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; + + r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, changes, n_changes); + if (r < 0) + return r; + + r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes); + } else + r = 0; + + if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) { + int q; + + /* Returns number of symlinks that where supposed to be installed. */ + q = install_context_apply(scope, plus, paths, config_path, force, SEARCH_LOAD, changes, n_changes); + if (r >= 0) { + if (q < 0) + r = q; + else + r += q; + } + } + + return r; +} + +static int preset_prepare_one( + UnitFileScope scope, + InstallContext *plus, + InstallContext *minus, + LookupPaths *paths, + const char *name, + Presets presets, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_(install_context_done) InstallContext tmp = {}; + _cleanup_strv_free_ char **instance_name_list = NULL; + UnitFileInstallInfo *i; + int r; + + if (install_info_find(plus, name) || install_info_find(minus, name)) + return 0; + + r = install_info_discover(scope, &tmp, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); + if (r < 0) + return r; + if (!streq(name, i->name)) { + log_debug("Skipping %s because it is an alias for %s.", name, i->name); + return 0; + } + + r = query_presets(name, presets, &instance_name_list); + if (r < 0) + return r; + + if (r > 0) { + if (instance_name_list) { + char **s; + STRV_FOREACH(s, instance_name_list) { + r = install_info_discover_and_check(scope, plus, paths, *s, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); + if (r < 0) + return r; + } + } else { + r = install_info_discover_and_check(scope, plus, paths, name, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); + if (r < 0) + return r; + } + + } else + r = install_info_discover(scope, minus, paths, name, SEARCH_FOLLOW_CONFIG_SYMLINKS, + &i, changes, n_changes); + + return r; +} + +int unit_file_preset( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFilePresetMode mode, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_(install_context_done) InstallContext plus = {}, minus = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(presets_freep) Presets presets = {}; + const char *config_path; + char **i; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + assert(mode < _UNIT_FILE_PRESET_MAX); + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + if (!config_path) + return -ENXIO; + + r = read_presets(scope, root_dir, &presets); + if (r < 0) + return r; + + STRV_FOREACH(i, files) { + r = preset_prepare_one(scope, &plus, &minus, &paths, *i, presets, changes, n_changes); + if (r < 0) + return r; + } + + return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes); +} + +int unit_file_preset_all( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + UnitFilePresetMode mode, + UnitFileChange **changes, + size_t *n_changes) { + + _cleanup_(install_context_done) InstallContext plus = {}, minus = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(presets_freep) Presets presets = {}; + const char *config_path = NULL; + char **i; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + assert(mode < _UNIT_FILE_PRESET_MAX); + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; + if (!config_path) + return -ENXIO; + + r = read_presets(scope, root_dir, &presets); + if (r < 0) + return r; + + STRV_FOREACH(i, paths.search_path) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + + d = opendir(*i); + if (!d) { + if (errno == ENOENT) + continue; + + return -errno; + } + + FOREACH_DIRENT(de, d, return -errno) { + + if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) + continue; + + dirent_ensure_type(d, de); + + if (!IN_SET(de->d_type, DT_LNK, DT_REG)) + continue; + + /* we don't pass changes[] in, because we want to handle errors on our own */ + r = preset_prepare_one(scope, &plus, &minus, &paths, de->d_name, presets, NULL, 0); + if (r == -ERFKILL) + r = unit_file_changes_add(changes, n_changes, + UNIT_FILE_IS_MASKED, de->d_name, NULL); + else if (r == -ENOLINK) + r = unit_file_changes_add(changes, n_changes, + UNIT_FILE_IS_DANGLING, de->d_name, NULL); + else if (r == -EADDRNOTAVAIL) /* Ignore generated/transient units when applying preset */ + continue; + if (r < 0) + return r; + } + } + + return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes); +} + +static void unit_file_list_free_one(UnitFileList *f) { + if (!f) + return; + + free(f->path); + free(f); +} + +Hashmap* unit_file_list_free(Hashmap *h) { + return hashmap_free_with_destructor(h, unit_file_list_free_one); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(UnitFileList*, unit_file_list_free_one); + +int unit_file_get_list( + UnitFileScope scope, + const char *root_dir, + Hashmap *h, + char **states, + char **patterns) { + + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + char **i; + int r; + + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + assert(h); + + r = lookup_paths_init(&paths, scope, 0, root_dir); + if (r < 0) + return r; + + STRV_FOREACH(i, paths.search_path) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + + d = opendir(*i); + if (!d) { + if (errno == ENOENT) + continue; + if (IN_SET(errno, ENOTDIR, EACCES)) { + log_debug_errno(errno, "Failed to open \"%s\": %m", *i); + continue; + } + + return -errno; + } + + FOREACH_DIRENT(de, d, return -errno) { + _cleanup_(unit_file_list_free_onep) UnitFileList *f = NULL; + + if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) + continue; + + if (!strv_fnmatch_or_empty(patterns, de->d_name, FNM_NOESCAPE)) + continue; + + if (hashmap_get(h, de->d_name)) + continue; + + dirent_ensure_type(d, de); + + if (!IN_SET(de->d_type, DT_LNK, DT_REG)) + continue; + + f = new0(UnitFileList, 1); + if (!f) + return -ENOMEM; + + f->path = path_make_absolute(de->d_name, *i); + if (!f->path) + return -ENOMEM; + + r = unit_file_lookup_state(scope, &paths, de->d_name, &f->state); + if (r < 0) + f->state = UNIT_FILE_BAD; + + if (!strv_isempty(states) && + !strv_contains(states, unit_file_state_to_string(f->state))) + continue; + + r = hashmap_put(h, basename(f->path), f); + if (r < 0) + return r; + + f = NULL; /* prevent cleanup */ + } + } + + return 0; +} + +static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = { + [UNIT_FILE_ENABLED] = "enabled", + [UNIT_FILE_ENABLED_RUNTIME] = "enabled-runtime", + [UNIT_FILE_LINKED] = "linked", + [UNIT_FILE_LINKED_RUNTIME] = "linked-runtime", + [UNIT_FILE_MASKED] = "masked", + [UNIT_FILE_MASKED_RUNTIME] = "masked-runtime", + [UNIT_FILE_STATIC] = "static", + [UNIT_FILE_DISABLED] = "disabled", + [UNIT_FILE_INDIRECT] = "indirect", + [UNIT_FILE_GENERATED] = "generated", + [UNIT_FILE_TRANSIENT] = "transient", + [UNIT_FILE_BAD] = "bad", +}; + +DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState); + +static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = { + [UNIT_FILE_SYMLINK] = "symlink", + [UNIT_FILE_UNLINK] = "unlink", + [UNIT_FILE_IS_MASKED] = "masked", + [UNIT_FILE_IS_DANGLING] = "dangling", +}; + +DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType); + +static const char* const unit_file_preset_mode_table[_UNIT_FILE_PRESET_MAX] = { + [UNIT_FILE_PRESET_FULL] = "full", + [UNIT_FILE_PRESET_ENABLE_ONLY] = "enable-only", + [UNIT_FILE_PRESET_DISABLE_ONLY] = "disable-only", +}; + +DEFINE_STRING_TABLE_LOOKUP(unit_file_preset_mode, UnitFilePresetMode); diff --git a/src/shared/install.h b/src/shared/install.h new file mode 100644 index 00000000..b2ad9c4a --- /dev/null +++ b/src/shared/install.h @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef enum UnitFilePresetMode UnitFilePresetMode; +typedef enum UnitFileChangeType UnitFileChangeType; +typedef enum UnitFileFlags UnitFileFlags; +typedef enum UnitFileType UnitFileType; +typedef struct UnitFileChange UnitFileChange; +typedef struct UnitFileList UnitFileList; +typedef struct UnitFileInstallInfo UnitFileInstallInfo; + +#include + +#include "hashmap.h" +#include "macro.h" +#include "path-lookup.h" +#include "strv.h" +#include "unit-name.h" + +enum UnitFilePresetMode { + UNIT_FILE_PRESET_FULL, + UNIT_FILE_PRESET_ENABLE_ONLY, + UNIT_FILE_PRESET_DISABLE_ONLY, + _UNIT_FILE_PRESET_MAX, + _UNIT_FILE_PRESET_INVALID = -1 +}; + +enum UnitFileChangeType { + UNIT_FILE_SYMLINK, + UNIT_FILE_UNLINK, + UNIT_FILE_IS_MASKED, + UNIT_FILE_IS_DANGLING, + _UNIT_FILE_CHANGE_TYPE_MAX, + _UNIT_FILE_CHANGE_TYPE_INVALID = INT_MIN +}; + +enum UnitFileFlags { + UNIT_FILE_RUNTIME = 1 << 0, + UNIT_FILE_FORCE = 1 << 1, + UNIT_FILE_DRY_RUN = 1 << 2, +}; + +/* type can either one of the UnitFileChangeTypes listed above, or a negative error. + * If source is specified, it should be the contents of the path symlink. + * In case of an error, source should be the existing symlink contents or NULL + */ +struct UnitFileChange { + int type; /* UnitFileChangeType or bust */ + char *path; + char *source; +}; + +static inline bool unit_file_changes_have_modification(const UnitFileChange* changes, size_t n_changes) { + size_t i; + for (i = 0; i < n_changes; i++) + if (IN_SET(changes[i].type, UNIT_FILE_SYMLINK, UNIT_FILE_UNLINK)) + return true; + return false; +} + +struct UnitFileList { + char *path; + UnitFileState state; +}; + +enum UnitFileType { + UNIT_FILE_TYPE_REGULAR, + UNIT_FILE_TYPE_SYMLINK, + UNIT_FILE_TYPE_MASKED, + _UNIT_FILE_TYPE_MAX, + _UNIT_FILE_TYPE_INVALID = -1, +}; + +struct UnitFileInstallInfo { + char *name; + char *path; + + char **aliases; + char **wanted_by; + char **required_by; + char **also; + + char *default_instance; + char *symlink_target; + + UnitFileType type; + bool auxiliary; +}; + +int unit_file_enable( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes); +int unit_file_disable( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes); +int unit_file_reenable( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes); +int unit_file_preset( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFilePresetMode mode, + UnitFileChange **changes, + size_t *n_changes); +int unit_file_preset_all( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + UnitFilePresetMode mode, + UnitFileChange **changes, + size_t *n_changes); +int unit_file_mask( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes); +int unit_file_unmask( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes); +int unit_file_link( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes); +int unit_file_revert( + UnitFileScope scope, + const char *root_dir, + char **files, + UnitFileChange **changes, + size_t *n_changes); +int unit_file_set_default( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + const char *file, + UnitFileChange **changes, + size_t *n_changes); +int unit_file_get_default( + UnitFileScope scope, + const char *root_dir, + char **name); +int unit_file_add_dependency( + UnitFileScope scope, + UnitFileFlags flags, + const char *root_dir, + char **files, + const char *target, + UnitDependency dep, + UnitFileChange **changes, + size_t *n_changes); + +int unit_file_lookup_state( + UnitFileScope scope, + const LookupPaths *paths, + const char *name, + UnitFileState *ret); + +int unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename, UnitFileState *ret); +int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *name); + +int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h, char **states, char **patterns); +Hashmap* unit_file_list_free(Hashmap *h); + +int unit_file_changes_add(UnitFileChange **changes, size_t *n_changes, UnitFileChangeType type, const char *path, const char *source); +void unit_file_changes_free(UnitFileChange *changes, size_t n_changes); +void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, size_t n_changes, bool quiet); + +int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name); + +const char *unit_file_state_to_string(UnitFileState s) _const_; +UnitFileState unit_file_state_from_string(const char *s) _pure_; +/* from_string conversion is unreliable because of the overlap between -EPERM and -1 for error. */ + +const char *unit_file_change_type_to_string(UnitFileChangeType s) _const_; +UnitFileChangeType unit_file_change_type_from_string(const char *s) _pure_; + +const char *unit_file_preset_mode_to_string(UnitFilePresetMode m) _const_; +UnitFilePresetMode unit_file_preset_mode_from_string(const char *s) _pure_; diff --git a/src/shared/ip-protocol-list.c b/src/shared/ip-protocol-list.c new file mode 100644 index 00000000..aa675ea1 --- /dev/null +++ b/src/shared/ip-protocol-list.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "ip-protocol-list.h" +#include "macro.h" +#include "parse-util.h" +#include "string-util.h" + +static const struct ip_protocol_name* lookup_ip_protocol(register const char *str, register GPERF_LEN_TYPE len); + +#include "ip-protocol-from-name.h" +#include "ip-protocol-to-name.h" + +const char *ip_protocol_to_name(int id) { + + if (id < 0) + return NULL; + + if ((size_t) id >= ELEMENTSOF(ip_protocol_names)) + return NULL; + + return ip_protocol_names[id]; +} + +int ip_protocol_from_name(const char *name) { + const struct ip_protocol_name *sc; + + assert(name); + + sc = lookup_ip_protocol(name, strlen(name)); + if (!sc) + return -EINVAL; + + return sc->id; +} + +int parse_ip_protocol(const char *s) { + _cleanup_free_ char *str = NULL; + int i, r; + + assert(s); + + if (isempty(s)) + return IPPROTO_IP; + + /* Do not use strdupa() here, as the input string may come from * + * command line or config files. */ + str = strdup(s); + if (!str) + return -ENOMEM; + + i = ip_protocol_from_name(ascii_strlower(str)); + if (i >= 0) + return i; + + r = safe_atoi(str, &i); + if (r < 0) + return r; + + if (!ip_protocol_to_name(i)) + return -EINVAL; + + return i; +} diff --git a/src/shared/ip-protocol-list.h b/src/shared/ip-protocol-list.h new file mode 100644 index 00000000..5c949696 --- /dev/null +++ b/src/shared/ip-protocol-list.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +const char *ip_protocol_to_name(int id); +int ip_protocol_from_name(const char *name); +int parse_ip_protocol(const char *s); diff --git a/src/shared/ip-protocol-to-name.awk b/src/shared/ip-protocol-to-name.awk new file mode 100644 index 00000000..824f811f --- /dev/null +++ b/src/shared/ip-protocol-to-name.awk @@ -0,0 +1,9 @@ +BEGIN{ + print "static const char* const ip_protocol_names[] = { " +} +!/HOPOPTS/ { + printf " [IPPROTO_%s] = \"%s\",\n", $1, tolower($1) +} +END{ + print "};" +} diff --git a/src/shared/journal-importer.c b/src/shared/journal-importer.c new file mode 100644 index 00000000..7c4fc702 --- /dev/null +++ b/src/shared/journal-importer.c @@ -0,0 +1,473 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "errno-util.h" +#include "escape.h" +#include "fd-util.h" +#include "io-util.h" +#include "journal-file.h" +#include "journal-importer.h" +#include "journal-util.h" +#include "parse-util.h" +#include "string-util.h" +#include "unaligned.h" + +enum { + IMPORTER_STATE_LINE = 0, /* waiting to read, or reading line */ + IMPORTER_STATE_DATA_START, /* reading binary data header */ + IMPORTER_STATE_DATA, /* reading binary data */ + IMPORTER_STATE_DATA_FINISH, /* expecting newline */ + IMPORTER_STATE_EOF, /* done */ +}; + +void journal_importer_cleanup(JournalImporter *imp) { + if (imp->fd >= 0 && !imp->passive_fd) { + log_debug("Closing %s (fd=%d)", imp->name ?: "importer", imp->fd); + safe_close(imp->fd); + } + + free(imp->name); + free(imp->buf); + iovw_free_contents(&imp->iovw, false); +} + +static char* realloc_buffer(JournalImporter *imp, size_t size) { + char *b, *old = imp->buf; + + b = GREEDY_REALLOC(imp->buf, imp->size, size); + if (!b) + return NULL; + + iovw_rebase(&imp->iovw, old, imp->buf); + + return b; +} + +static int get_line(JournalImporter *imp, char **line, size_t *size) { + ssize_t n; + char *c = NULL; + + assert(imp); + assert(imp->state == IMPORTER_STATE_LINE); + assert(imp->offset <= imp->filled); + assert(imp->filled <= imp->size); + assert(!imp->buf || imp->size > 0); + assert(imp->fd >= 0); + + for (;;) { + if (imp->buf) { + size_t start = MAX(imp->scanned, imp->offset); + + c = memchr(imp->buf + start, '\n', + imp->filled - start); + if (c) + break; + } + + imp->scanned = imp->filled; + if (imp->scanned >= DATA_SIZE_MAX) + return log_error_errno(SYNTHETIC_ERRNO(ENOBUFS), + "Entry is bigger than %u bytes.", + DATA_SIZE_MAX); + + if (imp->passive_fd) + /* we have to wait for some data to come to us */ + return -EAGAIN; + + /* We know that imp->filled is at most DATA_SIZE_MAX, so if + we reallocate it, we'll increase the size at least a bit. */ + assert_cc(DATA_SIZE_MAX < ENTRY_SIZE_MAX); + if (imp->size - imp->filled < LINE_CHUNK && + !realloc_buffer(imp, MIN(imp->filled + LINE_CHUNK, ENTRY_SIZE_MAX))) + return log_oom(); + + assert(imp->buf); + assert(imp->size - imp->filled >= LINE_CHUNK || + imp->size == ENTRY_SIZE_MAX); + + n = read(imp->fd, + imp->buf + imp->filled, + imp->size - imp->filled); + if (n < 0) { + if (errno != EAGAIN) + log_error_errno(errno, "read(%d, ..., %zu): %m", + imp->fd, + imp->size - imp->filled); + return -errno; + } else if (n == 0) + return 0; + + imp->filled += n; + } + + *line = imp->buf + imp->offset; + *size = c + 1 - imp->buf - imp->offset; + imp->offset += *size; + + return 1; +} + +static int fill_fixed_size(JournalImporter *imp, void **data, size_t size) { + + assert(imp); + assert(IN_SET(imp->state, IMPORTER_STATE_DATA_START, IMPORTER_STATE_DATA, IMPORTER_STATE_DATA_FINISH)); + assert(size <= DATA_SIZE_MAX); + assert(imp->offset <= imp->filled); + assert(imp->filled <= imp->size); + assert(imp->buf || imp->size == 0); + assert(!imp->buf || imp->size > 0); + assert(imp->fd >= 0); + assert(data); + + while (imp->filled - imp->offset < size) { + int n; + + if (imp->passive_fd) + /* we have to wait for some data to come to us */ + return -EAGAIN; + + if (!realloc_buffer(imp, imp->offset + size)) + return log_oom(); + + n = read(imp->fd, imp->buf + imp->filled, + imp->size - imp->filled); + if (n < 0) { + if (errno != EAGAIN) + log_error_errno(errno, "read(%d, ..., %zu): %m", imp->fd, + imp->size - imp->filled); + return -errno; + } else if (n == 0) + return 0; + + imp->filled += n; + } + + *data = imp->buf + imp->offset; + imp->offset += size; + + return 1; +} + +static int get_data_size(JournalImporter *imp) { + int r; + void *data; + + assert(imp); + assert(imp->state == IMPORTER_STATE_DATA_START); + assert(imp->data_size == 0); + + r = fill_fixed_size(imp, &data, sizeof(uint64_t)); + if (r <= 0) + return r; + + imp->data_size = unaligned_read_le64(data); + if (imp->data_size > DATA_SIZE_MAX) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Stream declares field with size %zu > DATA_SIZE_MAX = %u", + imp->data_size, DATA_SIZE_MAX); + if (imp->data_size == 0) + log_warning("Binary field with zero length"); + + return 1; +} + +static int get_data_data(JournalImporter *imp, void **data) { + int r; + + assert(imp); + assert(data); + assert(imp->state == IMPORTER_STATE_DATA); + + r = fill_fixed_size(imp, data, imp->data_size); + if (r <= 0) + return r; + + return 1; +} + +static int get_data_newline(JournalImporter *imp) { + int r; + char *data; + + assert(imp); + assert(imp->state == IMPORTER_STATE_DATA_FINISH); + + r = fill_fixed_size(imp, (void**) &data, 1); + if (r <= 0) + return r; + + assert(data); + if (*data != '\n') { + char buf[4]; + int l; + + l = cescape_char(*data, buf); + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Expected newline, got '%.*s'", l, buf); + } + + return 1; +} + +static int process_special_field(JournalImporter *imp, char *line) { + const char *value; + char buf[CELLESCAPE_DEFAULT_LENGTH]; + int r; + + assert(line); + + value = startswith(line, "__CURSOR="); + if (value) + /* ignore __CURSOR */ + return 1; + + value = startswith(line, "__REALTIME_TIMESTAMP="); + if (value) { + uint64_t x; + + r = safe_atou64(value, &x); + if (r < 0) + return log_warning_errno(r, "Failed to parse __REALTIME_TIMESTAMP '%s': %m", + cellescape(buf, sizeof buf, value)); + else if (!VALID_REALTIME(x)) { + log_warning("__REALTIME_TIMESTAMP out of range, ignoring: %"PRIu64, x); + return -ERANGE; + } + + imp->ts.realtime = x; + return 1; + } + + value = startswith(line, "__MONOTONIC_TIMESTAMP="); + if (value) { + uint64_t x; + + r = safe_atou64(value, &x); + if (r < 0) + return log_warning_errno(r, "Failed to parse __MONOTONIC_TIMESTAMP '%s': %m", + cellescape(buf, sizeof buf, value)); + else if (!VALID_MONOTONIC(x)) { + log_warning("__MONOTONIC_TIMESTAMP out of range, ignoring: %"PRIu64, x); + return -ERANGE; + } + + imp->ts.monotonic = x; + return 1; + } + + /* Just a single underline, but it needs special treatment too. */ + value = startswith(line, "_BOOT_ID="); + if (value) { + r = sd_id128_from_string(value, &imp->boot_id); + if (r < 0) + return log_warning_errno(r, "Failed to parse _BOOT_ID '%s': %m", + cellescape(buf, sizeof buf, value)); + + /* store the field in the usual fashion too */ + return 0; + } + + value = startswith(line, "__"); + if (value) { + log_notice("Unknown dunder line __%s, ignoring.", cellescape(buf, sizeof buf, value)); + return 1; + } + + /* no dunder */ + return 0; +} + +int journal_importer_process_data(JournalImporter *imp) { + int r; + + switch(imp->state) { + case IMPORTER_STATE_LINE: { + char *line, *sep; + size_t n = 0; + + assert(imp->data_size == 0); + + r = get_line(imp, &line, &n); + if (r < 0) + return r; + if (r == 0) { + imp->state = IMPORTER_STATE_EOF; + return 0; + } + assert(n > 0); + assert(line[n-1] == '\n'); + + if (n == 1) { + log_trace("Received empty line, event is ready"); + return 1; + } + + /* MESSAGE=xxx\n + or + COREDUMP\n + LLLLLLLL0011223344...\n + */ + sep = memchr(line, '=', n); + if (sep) { + /* chomp newline */ + n--; + + if (!journal_field_valid(line, sep - line, true)) { + char buf[64], *t; + + t = strndupa(line, sep - line); + log_debug("Ignoring invalid field: \"%s\"", + cellescape(buf, sizeof buf, t)); + + return 0; + } + + line[n] = '\0'; + r = process_special_field(imp, line); + if (r != 0) + return r < 0 ? r : 0; + + r = iovw_put(&imp->iovw, line, n); + if (r < 0) + return r; + } else { + /* replace \n with = */ + line[n-1] = '='; + + imp->field_len = n; + imp->state = IMPORTER_STATE_DATA_START; + + /* we cannot put the field in iovec until we have all data */ + } + + log_trace("Received: %.*s (%s)", (int) n, line, sep ? "text" : "binary"); + + return 0; /* continue */ + } + + case IMPORTER_STATE_DATA_START: + assert(imp->data_size == 0); + + r = get_data_size(imp); + // log_debug("get_data_size() -> %d", r); + if (r < 0) + return r; + if (r == 0) { + imp->state = IMPORTER_STATE_EOF; + return 0; + } + + imp->state = imp->data_size > 0 ? + IMPORTER_STATE_DATA : IMPORTER_STATE_DATA_FINISH; + + return 0; /* continue */ + + case IMPORTER_STATE_DATA: { + void *data; + char *field; + + assert(imp->data_size > 0); + + r = get_data_data(imp, &data); + // log_debug("get_data_data() -> %d", r); + if (r < 0) + return r; + if (r == 0) { + imp->state = IMPORTER_STATE_EOF; + return 0; + } + + assert(data); + + field = (char*) data - sizeof(uint64_t) - imp->field_len; + memmove(field + sizeof(uint64_t), field, imp->field_len); + + r = iovw_put(&imp->iovw, field + sizeof(uint64_t), imp->field_len + imp->data_size); + if (r < 0) + return r; + + imp->state = IMPORTER_STATE_DATA_FINISH; + + return 0; /* continue */ + } + + case IMPORTER_STATE_DATA_FINISH: + r = get_data_newline(imp); + // log_debug("get_data_newline() -> %d", r); + if (r < 0) + return r; + if (r == 0) { + imp->state = IMPORTER_STATE_EOF; + return 0; + } + + imp->data_size = 0; + imp->state = IMPORTER_STATE_LINE; + + return 0; /* continue */ + default: + assert_not_reached("wtf?"); + } +} + +int journal_importer_push_data(JournalImporter *imp, const char *data, size_t size) { + assert(imp); + assert(imp->state != IMPORTER_STATE_EOF); + + if (!realloc_buffer(imp, imp->filled + size)) + return log_error_errno(SYNTHETIC_ERRNO(ENOMEM), + "Failed to store received data of size %zu " + "(in addition to existing %zu bytes with %zu filled): %s", + size, imp->size, imp->filled, + strerror_safe(ENOMEM)); + + memcpy(imp->buf + imp->filled, data, size); + imp->filled += size; + + return 0; +} + +void journal_importer_drop_iovw(JournalImporter *imp) { + size_t remain, target; + + /* This function drops processed data that along with the iovw that points at it */ + + iovw_free_contents(&imp->iovw, false); + + /* possibly reset buffer position */ + remain = imp->filled - imp->offset; + + if (remain == 0) /* no brainer */ + imp->offset = imp->scanned = imp->filled = 0; + else if (imp->offset > imp->size - imp->filled && + imp->offset > remain) { + memcpy(imp->buf, imp->buf + imp->offset, remain); + imp->offset = imp->scanned = 0; + imp->filled = remain; + } + + target = imp->size; + while (target > 16 * LINE_CHUNK && imp->filled < target / 2) + target /= 2; + if (target < imp->size) { + char *tmp; + + tmp = realloc(imp->buf, target); + if (!tmp) + log_warning("Failed to reallocate buffer to (smaller) size %zu", + target); + else { + log_debug("Reallocated buffer from %zu to %zu bytes", + imp->size, target); + imp->buf = tmp; + imp->size = target; + } + } +} + +bool journal_importer_eof(const JournalImporter *imp) { + return imp->state == IMPORTER_STATE_EOF; +} diff --git a/src/shared/journal-importer.h b/src/shared/journal-importer.h new file mode 100644 index 00000000..b2e3c817 --- /dev/null +++ b/src/shared/journal-importer.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#pragma once + +#include +#include +#include + +#include "io-util.h" +#include "sd-id128.h" +#include "time-util.h" + +/* Make sure not to make this smaller than the maximum coredump size. + * See JOURNAL_SIZE_MAX in coredump.c */ +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#define ENTRY_SIZE_MAX (1024*1024*770u) +#define DATA_SIZE_MAX (1024*1024*768u) +#else +#define ENTRY_SIZE_MAX (1024*1024*13u) +#define DATA_SIZE_MAX (1024*1024*11u) +#endif +#define LINE_CHUNK 8*1024u + +/* The maximum number of fields in an entry */ +#define ENTRY_FIELD_COUNT_MAX 1024 + +typedef struct JournalImporter { + int fd; + bool passive_fd; + char *name; + + char *buf; + size_t size; /* total size of the buffer */ + size_t offset; /* offset to the beginning of live data in the buffer */ + size_t scanned; /* number of bytes since the beginning of data without a newline */ + size_t filled; /* total number of bytes in the buffer */ + + size_t field_len; /* used for binary fields: the field name length */ + size_t data_size; /* and the size of the binary data chunk being processed */ + + struct iovec_wrapper iovw; + + int state; + dual_timestamp ts; + sd_id128_t boot_id; +} JournalImporter; + +#define JOURNAL_IMPORTER_INIT(_fd) { .fd = (_fd), .iovw = {} } +#define JOURNAL_IMPORTER_MAKE(_fd) (JournalImporter) JOURNAL_IMPORTER_INIT(_fd) + +void journal_importer_cleanup(JournalImporter *); +int journal_importer_process_data(JournalImporter *); +int journal_importer_push_data(JournalImporter *, const char *data, size_t size); +void journal_importer_drop_iovw(JournalImporter *); +bool journal_importer_eof(const JournalImporter *); + +static inline size_t journal_importer_bytes_remaining(const JournalImporter *imp) { + return imp->filled; +} diff --git a/src/shared/journal-util.c b/src/shared/journal-util.c new file mode 100644 index 00000000..2f672c29 --- /dev/null +++ b/src/shared/journal-util.c @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "acl-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "journal-internal.h" +#include "journal-util.h" +#include "log.h" +#include "strv.h" +#include "user-util.h" + +static int access_check_var_log_journal(sd_journal *j, bool want_other_users) { +#if HAVE_ACL + _cleanup_strv_free_ char **g = NULL; + const char* dir; +#endif + int r; + + assert(j); + + /* If we are root, we should have access, don't warn. */ + if (getuid() == 0) + return 0; + + /* If we are in the 'systemd-journal' group, we should have + * access too. */ + r = in_group("systemd-journal"); + if (r < 0) + return log_error_errno(r, "Failed to check if we are in the 'systemd-journal' group: %m"); + if (r > 0) + return 0; + +#if HAVE_ACL + if (laccess("/run/log/journal", F_OK) >= 0) + dir = "/run/log/journal"; + else + dir = "/var/log/journal"; + + /* If we are in any of the groups listed in the journal ACLs, + * then all is good, too. Let's enumerate all groups from the + * default ACL of the directory, which generally should allow + * access to most journal files too. */ + r = acl_search_groups(dir, &g); + if (r < 0) + return log_error_errno(r, "Failed to search journal ACL: %m"); + if (r > 0) + return 0; + + /* Print a pretty list, if there were ACLs set. */ + if (!strv_isempty(g)) { + _cleanup_free_ char *s = NULL; + + /* There are groups in the ACL, let's list them */ + r = strv_extend(&g, "systemd-journal"); + if (r < 0) + return log_oom(); + + strv_sort(g); + strv_uniq(g); + + s = strv_join(g, "', '"); + if (!s) + return log_oom(); + + log_notice("Hint: You are currently not seeing messages from %s.\n" + " Users in groups '%s' can see all messages.\n" + " Pass -q to turn off this notice.", + want_other_users ? "other users and the system" : "the system", + s); + return 1; + } +#endif + + /* If no ACLs were found, print a short version of the message. */ + log_notice("Hint: You are currently not seeing messages from %s.\n" + " Users in the 'systemd-journal' group can see all messages. Pass -q to\n" + " turn off this notice.", + want_other_users ? "other users and the system" : "the system"); + + return 1; +} + +int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_users) { + Iterator it; + void *code; + char *path; + int r = 0; + + assert(j); + + if (hashmap_isempty(j->errors)) { + if (ordered_hashmap_isempty(j->files) && !quiet) + log_notice("No journal files were found."); + + return 0; + } + + if (hashmap_contains(j->errors, INT_TO_PTR(-EACCES))) { + if (!quiet) + (void) access_check_var_log_journal(j, want_other_users); + + if (ordered_hashmap_isempty(j->files)) + r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions."); + } + + HASHMAP_FOREACH_KEY(path, code, j->errors, it) { + int err; + + err = abs(PTR_TO_INT(code)); + + switch (err) { + case EACCES: + continue; + + case ENODATA: + log_warning_errno(err, "Journal file %s is truncated, ignoring file.", path); + break; + + case EPROTONOSUPPORT: + log_warning_errno(err, "Journal file %1$s uses an unsupported feature, ignoring file.\n" + "Use SYSTEMD_LOG_LEVEL=debug journalctl --file=%1$s to see the details.", + path); + break; + + case EBADMSG: + log_warning_errno(err, "Journal file %s corrupted, ignoring file.", path); + break; + + default: + log_warning_errno(err, "An error was encountered while opening journal file or directory %s, ignoring file: %m", path); + break; + } + } + + return r; +} + +bool journal_field_valid(const char *p, size_t l, bool allow_protected) { + const char *a; + + /* We kinda enforce POSIX syntax recommendations for + environment variables here, but make a couple of additional + requirements. + + http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */ + + if (l == (size_t) -1) + l = strlen(p); + + /* No empty field names */ + if (l <= 0) + return false; + + /* Don't allow names longer than 64 chars */ + if (l > 64) + return false; + + /* Variables starting with an underscore are protected */ + if (!allow_protected && p[0] == '_') + return false; + + /* Don't allow digits as first character */ + if (p[0] >= '0' && p[0] <= '9') + return false; + + /* Only allow A-Z0-9 and '_' */ + for (a = p; a < p + l; a++) + if ((*a < 'A' || *a > 'Z') && + (*a < '0' || *a > '9') && + *a != '_') + return false; + + return true; +} diff --git a/src/shared/journal-util.h b/src/shared/journal-util.h new file mode 100644 index 00000000..da86434a --- /dev/null +++ b/src/shared/journal-util.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-journal.h" + +bool journal_field_valid(const char *p, size_t l, bool allow_protected); + +int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_users); diff --git a/src/shared/json-internal.h b/src/shared/json-internal.h new file mode 100644 index 00000000..bf158bff --- /dev/null +++ b/src/shared/json-internal.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#pragma once + +#include "json.h" + +/* This header should include all prototypes only the JSON parser itself and + * its tests need access to. Normal code consuming the JSON parser should not + * interface with this. */ + +typedef union JsonValue { + /* Encodes a simple value. On x86-64 this structure is 16 bytes wide (as long double is 128bit). */ + bool boolean; + long double real; + intmax_t integer; + uintmax_t unsig; +} JsonValue; + +/* Let's protect us against accidental structure size changes on our most relevant arch */ +#ifdef __x86_64__ +assert_cc(sizeof(JsonValue) == 16U); +#endif + +#define JSON_VALUE_NULL ((JsonValue) {}) + +/* We use fake JsonVariant objects for some special values, in order to avoid memory allocations for them. Note that + * effectively this means that there are multiple ways to encode the same objects: via these magic values or as + * properly allocated JsonVariant. We convert between both on-the-fly as necessary. */ +#define JSON_VARIANT_MAGIC_TRUE ((JsonVariant*) 1) +#define JSON_VARIANT_MAGIC_FALSE ((JsonVariant*) 2) +#define JSON_VARIANT_MAGIC_NULL ((JsonVariant*) 3) +#define JSON_VARIANT_MAGIC_ZERO_INTEGER ((JsonVariant*) 4) +#define JSON_VARIANT_MAGIC_ZERO_UNSIGNED ((JsonVariant*) 5) +#define JSON_VARIANT_MAGIC_ZERO_REAL ((JsonVariant*) 6) +#define JSON_VARIANT_MAGIC_EMPTY_STRING ((JsonVariant*) 7) +#define JSON_VARIANT_MAGIC_EMPTY_ARRAY ((JsonVariant*) 8) +#define JSON_VARIANT_MAGIC_EMPTY_OBJECT ((JsonVariant*) 9) +#define _JSON_VARIANT_MAGIC_MAX ((JsonVariant*) 10) + +/* This is only safe as long as we don't define more than 4K magic pointers, i.e. the page size of the simplest + * architectures we support. That's because we rely on the fact that malloc() will never allocate from the first memory + * page, as it is a faulting page for catching NULL pointer dereferences. */ +assert_cc((uintptr_t) _JSON_VARIANT_MAGIC_MAX < 4096U); + +enum { /* JSON tokens */ + JSON_TOKEN_END, + JSON_TOKEN_COLON, + JSON_TOKEN_COMMA, + JSON_TOKEN_OBJECT_OPEN, + JSON_TOKEN_OBJECT_CLOSE, + JSON_TOKEN_ARRAY_OPEN, + JSON_TOKEN_ARRAY_CLOSE, + JSON_TOKEN_STRING, + JSON_TOKEN_REAL, + JSON_TOKEN_INTEGER, + JSON_TOKEN_UNSIGNED, + JSON_TOKEN_BOOLEAN, + JSON_TOKEN_NULL, + _JSON_TOKEN_MAX, + _JSON_TOKEN_INVALID = -1, +}; + +int json_tokenize(const char **p, char **ret_string, JsonValue *ret_value, unsigned *ret_line, unsigned *ret_column, void **state, unsigned *line, unsigned *column); diff --git a/src/shared/json.c b/src/shared/json.c new file mode 100644 index 00000000..7393c100 --- /dev/null +++ b/src/shared/json.c @@ -0,0 +1,3463 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "sd-messages.h" + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "float.h" +#include "hexdecoct.h" +#include "json-internal.h" +#include "json.h" +#include "macro.h" +#include "memory-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "utf8.h" + +/* Refuse putting together variants with a larger depth than 4K by default (as a protection against overflowing stacks + * if code processes JSON objects recursively. Note that we store the depth in an uint16_t, hence make sure this + * remains under 2^16. + * The value was 16k, but it was discovered to be too high on llvm/x86-64. See also the issue #10738. */ +#define DEPTH_MAX (4U*1024U) +assert_cc(DEPTH_MAX <= UINT16_MAX); + +typedef struct JsonSource { + /* When we parse from a file or similar, encodes the filename, to indicate the source of a json variant */ + size_t n_ref; + unsigned max_line; + unsigned max_column; + char name[]; +} JsonSource; + +/* On x86-64 this whole structure should have a size of 6 * 64 bit = 48 bytes */ +struct JsonVariant { + union { + /* We either maintain a reference counter for this variant itself, or we are embedded into an + * array/object, in which case only that surrounding object is ref-counted. (If 'embedded' is false, + * see below.) */ + size_t n_ref; + + /* If this JsonVariant is part of an array/object, then this field points to the surrounding + * JSON_VARIANT_ARRAY/JSON_VARIANT_OBJECT object. (If 'embedded' is true, see below.) */ + JsonVariant *parent; + }; + + /* If this was parsed from some file or buffer, this stores where from, as well as the source line/column */ + JsonSource *source; + unsigned line, column; + + JsonVariantType type:5; + + /* A marker whether this variant is embedded into in array/object or not. If true, the 'parent' pointer above + * is valid. If false, the 'n_ref' field above is valid instead. */ + bool is_embedded:1; + + /* In some conditions (for example, if this object is part of an array of strings or objects), we don't store + * any data inline, but instead simply reference an external object and act as surrogate of it. In that case + * this bool is set, and the external object is referenced through the .reference field below. */ + bool is_reference:1; + + /* While comparing two arrays, we use this for marking what we already have seen */ + bool is_marked:1; + + /* The current 'depth' of the JsonVariant, i.e. how many levels of member variants this has */ + uint16_t depth; + + union { + /* For simple types we store the value in-line. */ + JsonValue value; + + /* For objects and arrays we store the number of elements immediately following */ + size_t n_elements; + + /* If is_reference as indicated above is set, this is where the reference object is actually stored. */ + JsonVariant *reference; + + /* Strings are placed immediately after the structure. Note that when this is a JsonVariant embedded + * into an array we might encode strings up to INLINE_STRING_LENGTH characters directly inside the + * element, while longer strings are stored as references. When this object is not embedded into an + * array, but stand-alone we allocate the right size for the whole structure, i.e. the array might be + * much larger than INLINE_STRING_LENGTH. + * + * Note that because we want to allocate arrays of the JsonVariant structure we specify [0] here, + * rather than the prettier []. If we wouldn't, then this char array would have undefined size, and so + * would the union and then the struct this is included in. And of structures with undefined size we + * can't allocate arrays (at least not easily). */ + char string[0]; + }; +}; + +/* Inside string arrays we have a series of JasonVariant structures one after the other. In this case, strings longer + * than INLINE_STRING_MAX are stored as references, and all shorter ones inline. (This means — on x86-64 — strings up + * to 15 chars are stored within the array elements, and all others in separate allocations) */ +#define INLINE_STRING_MAX (sizeof(JsonVariant) - offsetof(JsonVariant, string) - 1U) + +/* Let's make sure this structure isn't increased in size accidentally. This check is only for our most relevant arch + * (x86-64). */ +#ifdef __x86_64__ +assert_cc(sizeof(JsonVariant) == 48U); +assert_cc(INLINE_STRING_MAX == 15U); +#endif + +static JsonSource* json_source_new(const char *name) { + JsonSource *s; + + assert(name); + + s = malloc(offsetof(JsonSource, name) + strlen(name) + 1); + if (!s) + return NULL; + + *s = (JsonSource) { + .n_ref = 1, + }; + strcpy(s->name, name); + + return s; +} + +DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(JsonSource, json_source, mfree); + +static bool json_source_equal(JsonSource *a, JsonSource *b) { + if (a == b) + return true; + + if (!a || !b) + return false; + + return streq(a->name, b->name); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(JsonSource*, json_source_unref); + +/* There are four kind of JsonVariant* pointers: + * + * 1. NULL + * 2. A 'regular' one, i.e. pointing to malloc() memory + * 3. A 'magic' one, i.e. one of the special JSON_VARIANT_MAGIC_XYZ values, that encode a few very basic values directly in the pointer. + * 4. A 'const string' one, i.e. a pointer to a const string. + * + * The four kinds of pointers can be discerned like this: + * + * Detecting #1 is easy, just compare with NULL. Detecting #3 is similarly easy: all magic pointers are below + * _JSON_VARIANT_MAGIC_MAX (which is pretty low, within the first memory page, which is special on Linux and other + * OSes, as it is a faulting page). In order to discern #2 and #4 we check the lowest bit. If it's off it's #2, + * otherwise #4. This makes use of the fact that malloc() will return "maximum aligned" memory, which definitely + * means the pointer is even. This means we can use the uneven pointers to reference static strings, as long as we + * make sure that all static strings used like this are aligned to 2 (or higher), and that we mask the bit on + * access. The JSON_VARIANT_STRING_CONST() macro encodes strings as JsonVariant* pointers, with the bit set. */ + +static bool json_variant_is_magic(const JsonVariant *v) { + if (!v) + return false; + + return v < _JSON_VARIANT_MAGIC_MAX; +} + +static bool json_variant_is_const_string(const JsonVariant *v) { + + if (v < _JSON_VARIANT_MAGIC_MAX) + return false; + + /* A proper JsonVariant is aligned to whatever malloc() aligns things too, which is definitely not uneven. We + * hence use all uneven pointers as indicators for const strings. */ + + return (((uintptr_t) v) & 1) != 0; +} + +static bool json_variant_is_regular(const JsonVariant *v) { + + if (v < _JSON_VARIANT_MAGIC_MAX) + return false; + + return (((uintptr_t) v) & 1) == 0; +} + +static JsonVariant *json_variant_dereference(JsonVariant *v) { + + /* Recursively dereference variants that are references to other variants */ + + if (!v) + return NULL; + + if (!json_variant_is_regular(v)) + return v; + + if (!v->is_reference) + return v; + + return json_variant_dereference(v->reference); +} + +static uint16_t json_variant_depth(JsonVariant *v) { + + v = json_variant_dereference(v); + if (!v) + return 0; + + if (!json_variant_is_regular(v)) + return 0; + + return v->depth; +} + +static JsonVariant *json_variant_normalize(JsonVariant *v) { + + /* Converts json variants to their normalized form, i.e. fully dereferenced and wherever possible converted to + * the "magic" version if there is one */ + + if (!v) + return NULL; + + v = json_variant_dereference(v); + + switch (json_variant_type(v)) { + + case JSON_VARIANT_BOOLEAN: + return json_variant_boolean(v) ? JSON_VARIANT_MAGIC_TRUE : JSON_VARIANT_MAGIC_FALSE; + + case JSON_VARIANT_NULL: + return JSON_VARIANT_MAGIC_NULL; + + case JSON_VARIANT_INTEGER: + return json_variant_integer(v) == 0 ? JSON_VARIANT_MAGIC_ZERO_INTEGER : v; + + case JSON_VARIANT_UNSIGNED: + return json_variant_unsigned(v) == 0 ? JSON_VARIANT_MAGIC_ZERO_UNSIGNED : v; + + case JSON_VARIANT_REAL: +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + return json_variant_real(v) == 0.0 ? JSON_VARIANT_MAGIC_ZERO_REAL : v; +#pragma GCC diagnostic pop + + case JSON_VARIANT_STRING: + return isempty(json_variant_string(v)) ? JSON_VARIANT_MAGIC_EMPTY_STRING : v; + + case JSON_VARIANT_ARRAY: + return json_variant_elements(v) == 0 ? JSON_VARIANT_MAGIC_EMPTY_ARRAY : v; + + case JSON_VARIANT_OBJECT: + return json_variant_elements(v) == 0 ? JSON_VARIANT_MAGIC_EMPTY_OBJECT : v; + + default: + return v; + } +} + +static JsonVariant *json_variant_conservative_normalize(JsonVariant *v) { + + /* Much like json_variant_normalize(), but won't simplify if the variant has a source/line location attached to + * it, in order not to lose context */ + + if (!v) + return NULL; + + if (!json_variant_is_regular(v)) + return v; + + if (v->source || v->line > 0 || v->column > 0) + return v; + + return json_variant_normalize(v); +} + +static int json_variant_new(JsonVariant **ret, JsonVariantType type, size_t space) { + JsonVariant *v; + + assert_return(ret, -EINVAL); + + v = malloc0(MAX(sizeof(JsonVariant), + offsetof(JsonVariant, value) + space)); + if (!v) + return -ENOMEM; + + v->n_ref = 1; + v->type = type; + + *ret = v; + return 0; +} + +int json_variant_new_integer(JsonVariant **ret, intmax_t i) { + JsonVariant *v; + int r; + + assert_return(ret, -EINVAL); + + if (i == 0) { + *ret = JSON_VARIANT_MAGIC_ZERO_INTEGER; + return 0; + } + + r = json_variant_new(&v, JSON_VARIANT_INTEGER, sizeof(i)); + if (r < 0) + return r; + + v->value.integer = i; + *ret = v; + + return 0; +} + +int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u) { + JsonVariant *v; + int r; + + assert_return(ret, -EINVAL); + if (u == 0) { + *ret = JSON_VARIANT_MAGIC_ZERO_UNSIGNED; + return 0; + } + + r = json_variant_new(&v, JSON_VARIANT_UNSIGNED, sizeof(u)); + if (r < 0) + return r; + + v->value.unsig = u; + *ret = v; + + return 0; +} + +int json_variant_new_real(JsonVariant **ret, long double d) { + JsonVariant *v; + int r; + + assert_return(ret, -EINVAL); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + if (d == 0.0) { +#pragma GCC diagnostic pop + *ret = JSON_VARIANT_MAGIC_ZERO_REAL; + return 0; + } + + r = json_variant_new(&v, JSON_VARIANT_REAL, sizeof(d)); + if (r < 0) + return r; + + v->value.real = d; + *ret = v; + + return 0; +} + +int json_variant_new_boolean(JsonVariant **ret, bool b) { + assert_return(ret, -EINVAL); + + if (b) + *ret = JSON_VARIANT_MAGIC_TRUE; + else + *ret = JSON_VARIANT_MAGIC_FALSE; + + return 0; +} + +int json_variant_new_null(JsonVariant **ret) { + assert_return(ret, -EINVAL); + + *ret = JSON_VARIANT_MAGIC_NULL; + return 0; +} + +int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n) { + JsonVariant *v; + int r; + + assert_return(ret, -EINVAL); + if (!s) { + assert_return(IN_SET(n, 0, (size_t) -1), -EINVAL); + return json_variant_new_null(ret); + } + if (n == (size_t) -1) /* determine length automatically */ + n = strlen(s); + else if (memchr(s, 0, n)) /* don't allow embedded NUL, as we can't express that in JSON */ + return -EINVAL; + if (n == 0) { + *ret = JSON_VARIANT_MAGIC_EMPTY_STRING; + return 0; + } + + r = json_variant_new(&v, JSON_VARIANT_STRING, n + 1); + if (r < 0) + return r; + + memcpy(v->string, s, n); + v->string[n] = 0; + + *ret = v; + return 0; +} + +static void json_variant_set(JsonVariant *a, JsonVariant *b) { + assert(a); + + b = json_variant_dereference(b); + if (!b) { + a->type = JSON_VARIANT_NULL; + return; + } + + a->type = json_variant_type(b); + switch (a->type) { + + case JSON_VARIANT_INTEGER: + a->value.integer = json_variant_integer(b); + break; + + case JSON_VARIANT_UNSIGNED: + a->value.unsig = json_variant_unsigned(b); + break; + + case JSON_VARIANT_REAL: + a->value.real = json_variant_real(b); + break; + + case JSON_VARIANT_BOOLEAN: + a->value.boolean = json_variant_boolean(b); + break; + + case JSON_VARIANT_STRING: { + const char *s; + + assert_se(s = json_variant_string(b)); + + /* Short strings we can store inline */ + if (strnlen(s, INLINE_STRING_MAX+1) <= INLINE_STRING_MAX) { + strcpy(a->string, s); + break; + } + + /* For longer strings, use a reference… */ + _fallthrough_; + } + + case JSON_VARIANT_ARRAY: + case JSON_VARIANT_OBJECT: + a->is_reference = true; + a->reference = json_variant_ref(json_variant_conservative_normalize(b)); + break; + + case JSON_VARIANT_NULL: + break; + + default: + assert_not_reached("Unexpected variant type"); + } +} + +static void json_variant_copy_source(JsonVariant *v, JsonVariant *from) { + assert(v); + assert(from); + + if (!json_variant_is_regular(from)) + return; + + v->line = from->line; + v->column = from->column; + v->source = json_source_ref(from->source); +} + +int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + + assert_return(ret, -EINVAL); + if (n == 0) { + *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY; + return 0; + } + assert_return(array, -EINVAL); + + v = new(JsonVariant, n + 1); + if (!v) + return -ENOMEM; + + *v = (JsonVariant) { + .n_ref = 1, + .type = JSON_VARIANT_ARRAY, + }; + + for (v->n_elements = 0; v->n_elements < n; v->n_elements++) { + JsonVariant *w = v + 1 + v->n_elements, + *c = array[v->n_elements]; + uint16_t d; + + d = json_variant_depth(c); + if (d >= DEPTH_MAX) /* Refuse too deep nesting */ + return -ELNRNG; + if (d >= v->depth) + v->depth = d + 1; + + *w = (JsonVariant) { + .is_embedded = true, + .parent = v, + }; + + json_variant_set(w, c); + json_variant_copy_source(w, c); + } + + *ret = TAKE_PTR(v); + return 0; +} + +int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n) { + JsonVariant *v; + size_t i; + + assert_return(ret, -EINVAL); + if (n == 0) { + *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY; + return 0; + } + assert_return(p, -EINVAL); + + v = new(JsonVariant, n + 1); + if (!v) + return -ENOMEM; + + *v = (JsonVariant) { + .n_ref = 1, + .type = JSON_VARIANT_ARRAY, + .n_elements = n, + .depth = 1, + }; + + for (i = 0; i < n; i++) { + JsonVariant *w = v + 1 + i; + + *w = (JsonVariant) { + .is_embedded = true, + .parent = v, + .type = JSON_VARIANT_UNSIGNED, + .value.unsig = ((const uint8_t*) p)[i], + }; + } + + *ret = v; + return 0; +} + +int json_variant_new_array_strv(JsonVariant **ret, char **l) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + size_t n; + int r; + + assert(ret); + + n = strv_length(l); + if (n == 0) { + *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY; + return 0; + } + + v = new(JsonVariant, n + 1); + if (!v) + return -ENOMEM; + + *v = (JsonVariant) { + .n_ref = 1, + .type = JSON_VARIANT_ARRAY, + .depth = 1, + }; + + for (v->n_elements = 0; v->n_elements < n; v->n_elements++) { + JsonVariant *w = v + 1 + v->n_elements; + size_t k; + + *w = (JsonVariant) { + .is_embedded = true, + .parent = v, + .type = JSON_VARIANT_STRING, + }; + + k = strlen(l[v->n_elements]); + + if (k > INLINE_STRING_MAX) { + /* If string is too long, store it as reference. */ + + r = json_variant_new_string(&w->reference, l[v->n_elements]); + if (r < 0) + return r; + + w->is_reference = true; + } else + memcpy(w->string, l[v->n_elements], k+1); + } + + *ret = TAKE_PTR(v); + return 0; +} + +int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + + assert_return(ret, -EINVAL); + if (n == 0) { + *ret = JSON_VARIANT_MAGIC_EMPTY_OBJECT; + return 0; + } + assert_return(array, -EINVAL); + assert_return(n % 2 == 0, -EINVAL); + + v = new(JsonVariant, n + 1); + if (!v) + return -ENOMEM; + + *v = (JsonVariant) { + .n_ref = 1, + .type = JSON_VARIANT_OBJECT, + }; + + for (v->n_elements = 0; v->n_elements < n; v->n_elements++) { + JsonVariant *w = v + 1 + v->n_elements, + *c = array[v->n_elements]; + uint16_t d; + + if ((v->n_elements & 1) == 0 && + !json_variant_is_string(c)) + return -EINVAL; /* Every second one needs to be a string, as it is the key name */ + + d = json_variant_depth(c); + if (d >= DEPTH_MAX) /* Refuse too deep nesting */ + return -ELNRNG; + if (d >= v->depth) + v->depth = d + 1; + + *w = (JsonVariant) { + .is_embedded = true, + .parent = v, + }; + + json_variant_set(w, c); + json_variant_copy_source(w, c); + } + + *ret = TAKE_PTR(v); + return 0; +} + +static void json_variant_free_inner(JsonVariant *v) { + assert(v); + + if (!json_variant_is_regular(v)) + return; + + json_source_unref(v->source); + + if (v->is_reference) { + json_variant_unref(v->reference); + return; + } + + if (IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT)) { + size_t i; + + for (i = 0; i < v->n_elements; i++) + json_variant_free_inner(v + 1 + i); + } +} + +JsonVariant *json_variant_ref(JsonVariant *v) { + if (!v) + return NULL; + if (!json_variant_is_regular(v)) + return v; + + if (v->is_embedded) + json_variant_ref(v->parent); /* ref the compounding variant instead */ + else { + assert(v->n_ref > 0); + v->n_ref++; + } + + return v; +} + +JsonVariant *json_variant_unref(JsonVariant *v) { + if (!v) + return NULL; + if (!json_variant_is_regular(v)) + return NULL; + + if (v->is_embedded) + json_variant_unref(v->parent); + else { + assert(v->n_ref > 0); + v->n_ref--; + + if (v->n_ref == 0) { + json_variant_free_inner(v); + free(v); + } + } + + return NULL; +} + +void json_variant_unref_many(JsonVariant **array, size_t n) { + size_t i; + + assert(array || n == 0); + + for (i = 0; i < n; i++) + json_variant_unref(array[i]); +} + +const char *json_variant_string(JsonVariant *v) { + if (!v) + return NULL; + if (v == JSON_VARIANT_MAGIC_EMPTY_STRING) + return ""; + if (json_variant_is_magic(v)) + goto mismatch; + if (json_variant_is_const_string(v)) { + uintptr_t p = (uintptr_t) v; + + assert((p & 1) != 0); + return (const char*) (p ^ 1U); + } + + if (v->is_reference) + return json_variant_string(v->reference); + if (v->type != JSON_VARIANT_STRING) + goto mismatch; + + return v->string; + +mismatch: + log_debug("Non-string JSON variant requested as string, returning NULL."); + return NULL; +} + +bool json_variant_boolean(JsonVariant *v) { + if (!v) + goto mismatch; + if (v == JSON_VARIANT_MAGIC_TRUE) + return true; + if (v == JSON_VARIANT_MAGIC_FALSE) + return false; + if (!json_variant_is_regular(v)) + goto mismatch; + if (v->type != JSON_VARIANT_BOOLEAN) + goto mismatch; + if (v->is_reference) + return json_variant_boolean(v->reference); + + return v->value.boolean; + +mismatch: + log_debug("Non-boolean JSON variant requested as boolean, returning false."); + return false; +} + +intmax_t json_variant_integer(JsonVariant *v) { + if (!v) + goto mismatch; + if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER || + v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || + v == JSON_VARIANT_MAGIC_ZERO_REAL) + return 0; + if (!json_variant_is_regular(v)) + goto mismatch; + if (v->is_reference) + return json_variant_integer(v->reference); + + switch (v->type) { + + case JSON_VARIANT_INTEGER: + return v->value.integer; + + case JSON_VARIANT_UNSIGNED: + if (v->value.unsig <= INTMAX_MAX) + return (intmax_t) v->value.unsig; + + log_debug("Unsigned integer %ju requested as signed integer and out of range, returning 0.", v->value.unsig); + return 0; + + case JSON_VARIANT_REAL: { + intmax_t converted; + + converted = (intmax_t) v->value.real; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + if ((long double) converted == v->value.real) +#pragma GCC diagnostic pop + return converted; + + log_debug("Real %Lg requested as integer, and cannot be converted losslessly, returning 0.", v->value.real); + return 0; + } + + default: + break; + } + +mismatch: + log_debug("Non-integer JSON variant requested as integer, returning 0."); + return 0; +} + +uintmax_t json_variant_unsigned(JsonVariant *v) { + if (!v) + goto mismatch; + if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER || + v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || + v == JSON_VARIANT_MAGIC_ZERO_REAL) + return 0; + if (!json_variant_is_regular(v)) + goto mismatch; + if (v->is_reference) + return json_variant_integer(v->reference); + + switch (v->type) { + + case JSON_VARIANT_INTEGER: + if (v->value.integer >= 0) + return (uintmax_t) v->value.integer; + + log_debug("Signed integer %ju requested as unsigned integer and out of range, returning 0.", v->value.integer); + return 0; + + case JSON_VARIANT_UNSIGNED: + return v->value.unsig; + + case JSON_VARIANT_REAL: { + uintmax_t converted; + + converted = (uintmax_t) v->value.real; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + if ((long double) converted == v->value.real) +#pragma GCC diagnostic pop + return converted; + + log_debug("Real %Lg requested as unsigned integer, and cannot be converted losslessly, returning 0.", v->value.real); + return 0; + } + + default: + break; + } + +mismatch: + log_debug("Non-integer JSON variant requested as unsigned, returning 0."); + return 0; +} + +long double json_variant_real(JsonVariant *v) { + if (!v) + return 0.0; + if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER || + v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || + v == JSON_VARIANT_MAGIC_ZERO_REAL) + return 0.0; + if (!json_variant_is_regular(v)) + goto mismatch; + if (v->is_reference) + return json_variant_real(v->reference); + + switch (v->type) { + + case JSON_VARIANT_REAL: + return v->value.real; + + case JSON_VARIANT_INTEGER: { + long double converted; + + converted = (long double) v->value.integer; + + if ((intmax_t) converted == v->value.integer) + return converted; + + log_debug("Signed integer %ji requested as real, and cannot be converted losslessly, returning 0.", v->value.integer); + return 0.0; + } + + case JSON_VARIANT_UNSIGNED: { + long double converted; + + converted = (long double) v->value.unsig; + + if ((uintmax_t) converted == v->value.unsig) + return converted; + + log_debug("Unsigned integer %ju requested as real, and cannot be converted losslessly, returning 0.", v->value.unsig); + return 0.0; + } + + default: + break; + } + +mismatch: + log_debug("Non-integer JSON variant requested as integer, returning 0."); + return 0.0; +} + +bool json_variant_is_negative(JsonVariant *v) { + if (!v) + goto mismatch; + if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER || + v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || + v == JSON_VARIANT_MAGIC_ZERO_REAL) + return false; + if (!json_variant_is_regular(v)) + goto mismatch; + if (v->is_reference) + return json_variant_is_negative(v->reference); + + /* This function is useful as checking whether numbers are negative is pretty complex since we have three types + * of numbers. And some JSON code (OCI for example) uses negative numbers to mark "not defined" numeric + * values. */ + + switch (v->type) { + + case JSON_VARIANT_REAL: + return v->value.real < 0; + + case JSON_VARIANT_INTEGER: + return v->value.integer < 0; + + case JSON_VARIANT_UNSIGNED: + return false; + + default: + break; + } + +mismatch: + log_debug("Non-integer JSON variant tested for negativity, returning false."); + return false; +} + +JsonVariantType json_variant_type(JsonVariant *v) { + + if (!v) + return _JSON_VARIANT_TYPE_INVALID; + + if (json_variant_is_const_string(v)) + return JSON_VARIANT_STRING; + + if (v == JSON_VARIANT_MAGIC_TRUE || v == JSON_VARIANT_MAGIC_FALSE) + return JSON_VARIANT_BOOLEAN; + + if (v == JSON_VARIANT_MAGIC_NULL) + return JSON_VARIANT_NULL; + + if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER) + return JSON_VARIANT_INTEGER; + + if (v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED) + return JSON_VARIANT_UNSIGNED; + + if (v == JSON_VARIANT_MAGIC_ZERO_REAL) + return JSON_VARIANT_REAL; + + if (v == JSON_VARIANT_MAGIC_EMPTY_STRING) + return JSON_VARIANT_STRING; + + if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY) + return JSON_VARIANT_ARRAY; + + if (v == JSON_VARIANT_MAGIC_EMPTY_OBJECT) + return JSON_VARIANT_OBJECT; + + return v->type; +} + +bool json_variant_has_type(JsonVariant *v, JsonVariantType type) { + JsonVariantType rt; + + v = json_variant_dereference(v); + if (!v) + return false; + + rt = json_variant_type(v); + if (rt == type) + return true; + + /* If it's a const string, then it only can be a string, and if it is not, it's not */ + if (json_variant_is_const_string(v)) + return false; + + /* All three magic zeroes qualify as integer, unsigned and as real */ + if ((v == JSON_VARIANT_MAGIC_ZERO_INTEGER || v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || v == JSON_VARIANT_MAGIC_ZERO_REAL) && + IN_SET(type, JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL, JSON_VARIANT_NUMBER)) + return true; + + /* All other magic variant types are only equal to themselves */ + if (json_variant_is_magic(v)) + return false; + + /* Handle the "number" pseudo type */ + if (type == JSON_VARIANT_NUMBER) + return IN_SET(rt, JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL); + + /* Integer conversions are OK in many cases */ + if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_UNSIGNED) + return v->value.integer >= 0; + if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_INTEGER) + return v->value.unsig <= INTMAX_MAX; + + /* Any integer that can be converted lossley to a real and back may also be considered a real */ + if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_REAL) + return (intmax_t) (long double) v->value.integer == v->value.integer; + if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_REAL) + return (uintmax_t) (long double) v->value.unsig == v->value.unsig; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + /* Any real that can be converted losslessly to an integer and back may also be considered an integer */ + if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_INTEGER) + return (long double) (intmax_t) v->value.real == v->value.real; + if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_UNSIGNED) + return (long double) (uintmax_t) v->value.real == v->value.real; +#pragma GCC diagnostic pop + + return false; +} + +size_t json_variant_elements(JsonVariant *v) { + if (!v) + return 0; + if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY || + v == JSON_VARIANT_MAGIC_EMPTY_OBJECT) + return 0; + if (!json_variant_is_regular(v)) + goto mismatch; + if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT)) + goto mismatch; + if (v->is_reference) + return json_variant_elements(v->reference); + + return v->n_elements; + +mismatch: + log_debug("Number of elements in non-array/non-object JSON variant requested, returning 0."); + return 0; +} + +JsonVariant *json_variant_by_index(JsonVariant *v, size_t idx) { + if (!v) + return NULL; + if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY || + v == JSON_VARIANT_MAGIC_EMPTY_OBJECT) + return NULL; + if (!json_variant_is_regular(v)) + goto mismatch; + if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT)) + goto mismatch; + if (v->is_reference) + return json_variant_by_index(v->reference, idx); + if (idx >= v->n_elements) + return NULL; + + return json_variant_conservative_normalize(v + 1 + idx); + +mismatch: + log_debug("Element in non-array/non-object JSON variant requested by index, returning NULL."); + return NULL; +} + +JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key) { + size_t i; + + if (!v) + goto not_found; + if (!key) + goto not_found; + if (v == JSON_VARIANT_MAGIC_EMPTY_OBJECT) + goto not_found; + if (!json_variant_is_regular(v)) + goto mismatch; + if (v->type != JSON_VARIANT_OBJECT) + goto mismatch; + if (v->is_reference) + return json_variant_by_key(v->reference, key); + + for (i = 0; i < v->n_elements; i += 2) { + JsonVariant *p; + + p = json_variant_dereference(v + 1 + i); + + if (!json_variant_has_type(p, JSON_VARIANT_STRING)) + continue; + + if (streq(json_variant_string(p), key)) { + + if (ret_key) + *ret_key = json_variant_conservative_normalize(v + 1 + i); + + return json_variant_conservative_normalize(v + 1 + i + 1); + } + } + +not_found: + if (ret_key) + *ret_key = NULL; + + return NULL; + +mismatch: + log_debug("Element in non-object JSON variant requested by key, returning NULL."); + if (ret_key) + *ret_key = NULL; + + return NULL; +} + +JsonVariant *json_variant_by_key(JsonVariant *v, const char *key) { + return json_variant_by_key_full(v, key, NULL); +} + +bool json_variant_equal(JsonVariant *a, JsonVariant *b) { + JsonVariantType t; + + a = json_variant_normalize(a); + b = json_variant_normalize(b); + + if (a == b) + return true; + + t = json_variant_type(a); + if (!json_variant_has_type(b, t)) + return false; + + switch (t) { + + case JSON_VARIANT_STRING: + return streq(json_variant_string(a), json_variant_string(b)); + + case JSON_VARIANT_INTEGER: + return json_variant_integer(a) == json_variant_integer(b); + + case JSON_VARIANT_UNSIGNED: + return json_variant_unsigned(a) == json_variant_unsigned(b); + + case JSON_VARIANT_REAL: +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + return json_variant_real(a) == json_variant_real(b); +#pragma GCC diagnostic pop + + case JSON_VARIANT_BOOLEAN: + return json_variant_boolean(a) == json_variant_boolean(b); + + case JSON_VARIANT_NULL: + return true; + + case JSON_VARIANT_ARRAY: { + size_t i, n; + + n = json_variant_elements(a); + if (n != json_variant_elements(b)) + return false; + + for (i = 0; i < n; i++) { + if (!json_variant_equal(json_variant_by_index(a, i), json_variant_by_index(b, i))) + return false; + } + + return true; + } + + case JSON_VARIANT_OBJECT: { + size_t i, n; + + n = json_variant_elements(a); + if (n != json_variant_elements(b)) + return false; + + /* Iterate through all keys in 'a' */ + for (i = 0; i < n; i += 2) { + bool found = false; + size_t j; + + /* Match them against all keys in 'b' */ + for (j = 0; j < n; j += 2) { + JsonVariant *key_b; + + key_b = json_variant_by_index(b, j); + + /* During the first iteration unmark everything */ + if (i == 0) + key_b->is_marked = false; + else if (key_b->is_marked) /* In later iterations if we already marked something, don't bother with it again */ + continue; + + if (found) + continue; + + if (json_variant_equal(json_variant_by_index(a, i), key_b) && + json_variant_equal(json_variant_by_index(a, i+1), json_variant_by_index(b, j+1))) { + /* Key and values match! */ + key_b->is_marked = found = true; + + /* In the first iteration we continue the inner loop since we want to mark + * everything, otherwise exit the loop quickly after we found what we were + * looking for. */ + if (i != 0) + break; + } + } + + if (!found) + return false; + } + + return true; + } + + default: + assert_not_reached("Unknown variant type."); + } +} + +int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column) { + assert_return(v, -EINVAL); + + if (ret_source) + *ret_source = json_variant_is_regular(v) && v->source ? v->source->name : NULL; + + if (ret_line) + *ret_line = json_variant_is_regular(v) ? v->line : 0; + + if (ret_column) + *ret_column = json_variant_is_regular(v) ? v->column : 0; + + return 0; +} + +static int print_source(FILE *f, JsonVariant *v, JsonFormatFlags flags, bool whitespace) { + size_t w, k; + + if (!FLAGS_SET(flags, JSON_FORMAT_SOURCE|JSON_FORMAT_PRETTY)) + return 0; + + if (!json_variant_is_regular(v)) + return 0; + + if (!v->source && v->line == 0 && v->column == 0) + return 0; + + /* The max width we need to format the line numbers for this source file */ + w = (v->source && v->source->max_line > 0) ? + DECIMAL_STR_WIDTH(v->source->max_line) : + DECIMAL_STR_MAX(unsigned)-1; + k = (v->source && v->source->max_column > 0) ? + DECIMAL_STR_WIDTH(v->source->max_column) : + DECIMAL_STR_MAX(unsigned) -1; + + if (whitespace) { + size_t i, n; + + n = 1 + (v->source ? strlen(v->source->name) : 0) + + ((v->source && (v->line > 0 || v->column > 0)) ? 1 : 0) + + (v->line > 0 ? w : 0) + + (((v->source || v->line > 0) && v->column > 0) ? 1 : 0) + + (v->column > 0 ? k : 0) + + 2; + + for (i = 0; i < n; i++) + fputc(' ', f); + } else { + fputc('[', f); + + if (v->source) + fputs(v->source->name, f); + if (v->source && (v->line > 0 || v->column > 0)) + fputc(':', f); + if (v->line > 0) + fprintf(f, "%*u", (int) w, v->line); + if ((v->source || v->line > 0) || v->column > 0) + fputc(':', f); + if (v->column > 0) + fprintf(f, "%*u", (int) k, v->column); + + fputc(']', f); + fputc(' ', f); + } + + return 0; +} + +static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const char *prefix) { + int r; + + assert(f); + assert(v); + + switch (json_variant_type(v)) { + + case JSON_VARIANT_REAL: { + locale_t loc; + + loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0); + if (loc == (locale_t) 0) + return -errno; + + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_HIGHLIGHT_BLUE, f); + + fprintf(f, "%.*Le", DECIMAL_DIG, json_variant_real(v)); + + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_NORMAL, f); + + freelocale(loc); + break; + } + + case JSON_VARIANT_INTEGER: + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_HIGHLIGHT_BLUE, f); + + fprintf(f, "%" PRIdMAX, json_variant_integer(v)); + + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_NORMAL, f); + break; + + case JSON_VARIANT_UNSIGNED: + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_HIGHLIGHT_BLUE, f); + + fprintf(f, "%" PRIuMAX, json_variant_unsigned(v)); + + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_NORMAL, f); + break; + + case JSON_VARIANT_BOOLEAN: + + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_HIGHLIGHT, f); + + if (json_variant_boolean(v)) + fputs("true", f); + else + fputs("false", f); + + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_NORMAL, f); + + break; + + case JSON_VARIANT_NULL: + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_HIGHLIGHT, f); + + fputs("null", f); + + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_NORMAL, f); + break; + + case JSON_VARIANT_STRING: { + const char *q; + + fputc('"', f); + + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_GREEN, f); + + for (q = json_variant_string(v); *q; q++) { + + switch (*q) { + + case '"': + fputs("\\\"", f); + break; + + case '\\': + fputs("\\\\", f); + break; + + case '\b': + fputs("\\b", f); + break; + + case '\f': + fputs("\\f", f); + break; + + case '\n': + fputs("\\n", f); + break; + + case '\r': + fputs("\\r", f); + break; + + case '\t': + fputs("\\t", f); + break; + + default: + if ((signed char) *q >= 0 && *q < ' ') + fprintf(f, "\\u%04x", *q); + else + fputc(*q, f); + break; + } + } + + if (flags & JSON_FORMAT_COLOR) + fputs(ANSI_NORMAL, f); + + fputc('"', f); + break; + } + + case JSON_VARIANT_ARRAY: { + size_t i, n; + + n = json_variant_elements(v); + + if (n == 0) + fputs("[]", f); + else { + _cleanup_free_ char *joined = NULL; + const char *prefix2; + + if (flags & JSON_FORMAT_PRETTY) { + joined = strjoin(strempty(prefix), "\t"); + if (!joined) + return -ENOMEM; + + prefix2 = joined; + fputs("[\n", f); + } else { + prefix2 = strempty(prefix); + fputc('[', f); + } + + for (i = 0; i < n; i++) { + JsonVariant *e; + + assert_se(e = json_variant_by_index(v, i)); + + if (i > 0) { + if (flags & JSON_FORMAT_PRETTY) + fputs(",\n", f); + else + fputc(',', f); + } + + if (flags & JSON_FORMAT_PRETTY) { + print_source(f, e, flags, false); + fputs(prefix2, f); + } + + r = json_format(f, e, flags, prefix2); + if (r < 0) + return r; + } + + if (flags & JSON_FORMAT_PRETTY) { + fputc('\n', f); + print_source(f, v, flags, true); + fputs(strempty(prefix), f); + } + + fputc(']', f); + } + break; + } + + case JSON_VARIANT_OBJECT: { + size_t i, n; + + n = json_variant_elements(v); + + if (n == 0) + fputs("{}", f); + else { + _cleanup_free_ char *joined = NULL; + const char *prefix2; + + if (flags & JSON_FORMAT_PRETTY) { + joined = strjoin(strempty(prefix), "\t"); + if (!joined) + return -ENOMEM; + + prefix2 = joined; + fputs("{\n", f); + } else { + prefix2 = strempty(prefix); + fputc('{', f); + } + + for (i = 0; i < n; i += 2) { + JsonVariant *e; + + e = json_variant_by_index(v, i); + + if (i > 0) { + if (flags & JSON_FORMAT_PRETTY) + fputs(",\n", f); + else + fputc(',', f); + } + + if (flags & JSON_FORMAT_PRETTY) { + print_source(f, e, flags, false); + fputs(prefix2, f); + } + + r = json_format(f, e, flags, prefix2); + if (r < 0) + return r; + + fputs(flags & JSON_FORMAT_PRETTY ? " : " : ":", f); + + r = json_format(f, json_variant_by_index(v, i+1), flags, prefix2); + if (r < 0) + return r; + } + + if (flags & JSON_FORMAT_PRETTY) { + fputc('\n', f); + print_source(f, v, flags, true); + fputs(strempty(prefix), f); + } + + fputc('}', f); + } + break; + } + + default: + assert_not_reached("Unexpected variant type."); + } + + return 0; +} + +int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) { + _cleanup_free_ char *s = NULL; + size_t sz = 0; + int r; + + /* Returns the length of the generated string (without the terminating NUL), + * or negative on error. */ + + assert_return(v, -EINVAL); + assert_return(ret, -EINVAL); + + { + _cleanup_fclose_ FILE *f = NULL; + + f = open_memstream_unlocked(&s, &sz); + if (!f) + return -ENOMEM; + + json_variant_dump(v, flags, f, NULL); + + /* Add terminating 0, so that the output buffer is a valid string. */ + fputc('\0', f); + + r = fflush_and_check(f); + } + if (r < 0) + return r; + + assert(s); + *ret = TAKE_PTR(s); + assert(sz > 0); + return (int) sz - 1; +} + +void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix) { + if (!v) + return; + + if (!f) + f = stdout; + + print_source(f, v, flags, false); + + if (((flags & (JSON_FORMAT_COLOR_AUTO|JSON_FORMAT_COLOR)) == JSON_FORMAT_COLOR_AUTO) && colors_enabled()) + flags |= JSON_FORMAT_COLOR; + + if (flags & JSON_FORMAT_SSE) + fputs("data: ", f); + if (flags & JSON_FORMAT_SEQ) + fputc('\x1e', f); /* ASCII Record Separator */ + + json_format(f, v, flags, prefix); + + if (flags & (JSON_FORMAT_PRETTY|JSON_FORMAT_SEQ|JSON_FORMAT_SSE|JSON_FORMAT_NEWLINE)) + fputc('\n', f); + if (flags & JSON_FORMAT_SSE) + fputc('\n', f); /* In case of SSE add a second newline */ +} + +static int json_variant_copy(JsonVariant **nv, JsonVariant *v) { + JsonVariantType t; + JsonVariant *c; + JsonValue value; + const void *source; + size_t k; + + assert(nv); + assert(v); + + /* Let's copy the simple types literally, and the larger types by references */ + t = json_variant_type(v); + switch (t) { + case JSON_VARIANT_INTEGER: + k = sizeof(intmax_t); + value.integer = json_variant_integer(v); + source = &value; + break; + + case JSON_VARIANT_UNSIGNED: + k = sizeof(uintmax_t); + value.unsig = json_variant_unsigned(v); + source = &value; + break; + + case JSON_VARIANT_REAL: + k = sizeof(long double); + value.real = json_variant_real(v); + source = &value; + break; + + case JSON_VARIANT_BOOLEAN: + k = sizeof(bool); + value.boolean = json_variant_boolean(v); + source = &value; + break; + + case JSON_VARIANT_NULL: + k = 0; + source = NULL; + break; + + case JSON_VARIANT_STRING: + source = json_variant_string(v); + k = strnlen(source, INLINE_STRING_MAX + 1); + if (k <= INLINE_STRING_MAX) { + k ++; + break; + } + + _fallthrough_; + + default: + /* Everything else copy by reference */ + + c = malloc0(MAX(sizeof(JsonVariant), + offsetof(JsonVariant, reference) + sizeof(JsonVariant*))); + if (!c) + return -ENOMEM; + + c->n_ref = 1; + c->type = t; + c->is_reference = true; + c->reference = json_variant_ref(json_variant_normalize(v)); + + *nv = c; + return 0; + } + + c = malloc0(MAX(sizeof(JsonVariant), + offsetof(JsonVariant, value) + k)); + if (!c) + return -ENOMEM; + + c->n_ref = 1; + c->type = t; + + memcpy_safe(&c->value, source, k); + + *nv = c; + return 0; +} + +static bool json_single_ref(JsonVariant *v) { + + /* Checks whether the caller is the single owner of the object, i.e. can get away with changing it */ + + if (!json_variant_is_regular(v)) + return false; + + if (v->is_embedded) + return json_single_ref(v->parent); + + assert(v->n_ref > 0); + return v->n_ref == 1; +} + +static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned line, unsigned column) { + JsonVariant *w; + int r; + + assert(v); + + /* Patch in source and line/column number. Tries to do this in-place if the caller is the sole referencer of + * the object. If not, allocates a new object, possibly a surrogate for the original one */ + + if (!*v) + return 0; + + if (source && line > source->max_line) + source->max_line = line; + if (source && column > source->max_column) + source->max_column = column; + + if (!json_variant_is_regular(*v)) { + + if (!source && line == 0 && column == 0) + return 0; + + } else { + if (json_source_equal((*v)->source, source) && + (*v)->line == line && + (*v)->column == column) + return 0; + + if (json_single_ref(*v)) { /* Sole reference? */ + json_source_unref((*v)->source); + (*v)->source = json_source_ref(source); + (*v)->line = line; + (*v)->column = column; + return 1; + } + } + + r = json_variant_copy(&w, *v); + if (r < 0) + return r; + + assert(json_variant_is_regular(w)); + assert(!w->is_embedded); + assert(w->n_ref == 1); + assert(!w->source); + + w->source = json_source_ref(source); + w->line = line; + w->column = column; + + json_variant_unref(*v); + *v = w; + + return 1; +} + +static void inc_lines_columns(unsigned *line, unsigned *column, const char *s, size_t n) { + assert(line); + assert(column); + assert(s || n == 0); + + while (n > 0) { + if (*s == '\n') { + (*line)++; + *column = 1; + } else if ((signed char) *s >= 0 && *s < 127) /* Process ASCII chars quickly */ + (*column)++; + else { + int w; + + w = utf8_encoded_valid_unichar(s, n); + if (w < 0) /* count invalid unichars as normal characters */ + w = 1; + else if ((size_t) w > n) /* never read more than the specified number of characters */ + w = (int) n; + + (*column)++; + + s += w; + n -= w; + continue; + } + + s++; + n--; + } +} + +static int unhex_ucs2(const char *c, uint16_t *ret) { + int aa, bb, cc, dd; + uint16_t x; + + assert(c); + assert(ret); + + aa = unhexchar(c[0]); + if (aa < 0) + return -EINVAL; + + bb = unhexchar(c[1]); + if (bb < 0) + return -EINVAL; + + cc = unhexchar(c[2]); + if (cc < 0) + return -EINVAL; + + dd = unhexchar(c[3]); + if (dd < 0) + return -EINVAL; + + x = ((uint16_t) aa << 12) | + ((uint16_t) bb << 8) | + ((uint16_t) cc << 4) | + ((uint16_t) dd); + + if (x <= 0) + return -EINVAL; + + *ret = x; + + return 0; +} + +static int json_parse_string(const char **p, char **ret) { + _cleanup_free_ char *s = NULL; + size_t n = 0, allocated = 0; + const char *c; + + assert(p); + assert(*p); + assert(ret); + + c = *p; + + if (*c != '"') + return -EINVAL; + + c++; + + for (;;) { + int len; + + /* Check for EOF */ + if (*c == 0) + return -EINVAL; + + /* Check for control characters 0x00..0x1f */ + if (*c > 0 && *c < ' ') + return -EINVAL; + + /* Check for control character 0x7f */ + if (*c == 0x7f) + return -EINVAL; + + if (*c == '"') { + if (!s) { + s = strdup(""); + if (!s) + return -ENOMEM; + } else + s[n] = 0; + + *p = c + 1; + + *ret = TAKE_PTR(s); + return JSON_TOKEN_STRING; + } + + if (*c == '\\') { + char ch = 0; + c++; + + if (*c == 0) + return -EINVAL; + + if (IN_SET(*c, '"', '\\', '/')) + ch = *c; + else if (*c == 'b') + ch = '\b'; + else if (*c == 'f') + ch = '\f'; + else if (*c == 'n') + ch = '\n'; + else if (*c == 'r') + ch = '\r'; + else if (*c == 't') + ch = '\t'; + else if (*c == 'u') { + char16_t x; + int r; + + r = unhex_ucs2(c + 1, &x); + if (r < 0) + return r; + + c += 5; + + if (!GREEDY_REALLOC(s, allocated, n + 5)) + return -ENOMEM; + + if (!utf16_is_surrogate(x)) + n += utf8_encode_unichar(s + n, (char32_t) x); + else if (utf16_is_trailing_surrogate(x)) + return -EINVAL; + else { + char16_t y; + + if (c[0] != '\\' || c[1] != 'u') + return -EINVAL; + + r = unhex_ucs2(c + 2, &y); + if (r < 0) + return r; + + c += 6; + + if (!utf16_is_trailing_surrogate(y)) + return -EINVAL; + + n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y)); + } + + continue; + } else + return -EINVAL; + + if (!GREEDY_REALLOC(s, allocated, n + 2)) + return -ENOMEM; + + s[n++] = ch; + c ++; + continue; + } + + len = utf8_encoded_valid_unichar(c, (size_t) -1); + if (len < 0) + return len; + + if (!GREEDY_REALLOC(s, allocated, n + len + 1)) + return -ENOMEM; + + memcpy(s + n, c, len); + n += len; + c += len; + } +} + +static int json_parse_number(const char **p, JsonValue *ret) { + bool negative = false, exponent_negative = false, is_real = false; + long double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0; + intmax_t i = 0; + uintmax_t u = 0; + const char *c; + + assert(p); + assert(*p); + assert(ret); + + c = *p; + + if (*c == '-') { + negative = true; + c++; + } + + if (*c == '0') + c++; + else { + if (!strchr("123456789", *c) || *c == 0) + return -EINVAL; + + do { + if (!is_real) { + if (negative) { + + if (i < INTMAX_MIN / 10) /* overflow */ + is_real = true; + else { + intmax_t t = 10 * i; + + if (t < INTMAX_MIN + (*c - '0')) /* overflow */ + is_real = true; + else + i = t - (*c - '0'); + } + } else { + if (u > UINTMAX_MAX / 10) /* overflow */ + is_real = true; + else { + uintmax_t t = 10 * u; + + if (t > UINTMAX_MAX - (*c - '0')) /* overflow */ + is_real = true; + else + u = t + (*c - '0'); + } + } + } + + x = 10.0 * x + (*c - '0'); + + c++; + } while (strchr("0123456789", *c) && *c != 0); + } + + if (*c == '.') { + is_real = true; + c++; + + if (!strchr("0123456789", *c) || *c == 0) + return -EINVAL; + + do { + y = 10.0 * y + (*c - '0'); + shift = 10.0 * shift; + c++; + } while (strchr("0123456789", *c) && *c != 0); + } + + if (IN_SET(*c, 'e', 'E')) { + is_real = true; + c++; + + if (*c == '-') { + exponent_negative = true; + c++; + } else if (*c == '+') + c++; + + if (!strchr("0123456789", *c) || *c == 0) + return -EINVAL; + + do { + exponent = 10.0 * exponent + (*c - '0'); + c++; + } while (strchr("0123456789", *c) && *c != 0); + } + + *p = c; + + if (is_real) { + ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10l((exponent_negative ? -1.0 : 1.0) * exponent); + return JSON_TOKEN_REAL; + } else if (negative) { + ret->integer = i; + return JSON_TOKEN_INTEGER; + } else { + ret->unsig = u; + return JSON_TOKEN_UNSIGNED; + } +} + +int json_tokenize( + const char **p, + char **ret_string, + JsonValue *ret_value, + unsigned *ret_line, /* 'ret_line' returns the line at the beginning of this token */ + unsigned *ret_column, + void **state, + unsigned *line, /* 'line' is used as a line state, it always reflect the line we are at after the token was read */ + unsigned *column) { + + unsigned start_line, start_column; + const char *start, *c; + size_t n; + int t, r; + + enum { + STATE_NULL, + STATE_VALUE, + STATE_VALUE_POST, + }; + + assert(p); + assert(*p); + assert(ret_string); + assert(ret_value); + assert(ret_line); + assert(ret_column); + assert(line); + assert(column); + assert(state); + + t = PTR_TO_INT(*state); + if (t == STATE_NULL) { + *line = 1; + *column = 1; + t = STATE_VALUE; + } + + /* Skip over the whitespace */ + n = strspn(*p, WHITESPACE); + inc_lines_columns(line, column, *p, n); + c = *p + n; + + /* Remember where we started processing this token */ + start = c; + start_line = *line; + start_column = *column; + + if (*c == 0) { + *ret_string = NULL; + *ret_value = JSON_VALUE_NULL; + r = JSON_TOKEN_END; + goto finish; + } + + switch (t) { + + case STATE_VALUE: + + if (*c == '{') { + c++; + *state = INT_TO_PTR(STATE_VALUE); + r = JSON_TOKEN_OBJECT_OPEN; + goto null_return; + + } else if (*c == '}') { + c++; + *state = INT_TO_PTR(STATE_VALUE_POST); + r = JSON_TOKEN_OBJECT_CLOSE; + goto null_return; + + } else if (*c == '[') { + c++; + *state = INT_TO_PTR(STATE_VALUE); + r = JSON_TOKEN_ARRAY_OPEN; + goto null_return; + + } else if (*c == ']') { + c++; + *state = INT_TO_PTR(STATE_VALUE_POST); + r = JSON_TOKEN_ARRAY_CLOSE; + goto null_return; + + } else if (*c == '"') { + + r = json_parse_string(&c, ret_string); + if (r < 0) + return r; + + *ret_value = JSON_VALUE_NULL; + *state = INT_TO_PTR(STATE_VALUE_POST); + goto finish; + + } else if (strchr("-0123456789", *c)) { + + r = json_parse_number(&c, ret_value); + if (r < 0) + return r; + + *ret_string = NULL; + *state = INT_TO_PTR(STATE_VALUE_POST); + goto finish; + + } else if (startswith(c, "true")) { + *ret_string = NULL; + ret_value->boolean = true; + c += 4; + *state = INT_TO_PTR(STATE_VALUE_POST); + r = JSON_TOKEN_BOOLEAN; + goto finish; + + } else if (startswith(c, "false")) { + *ret_string = NULL; + ret_value->boolean = false; + c += 5; + *state = INT_TO_PTR(STATE_VALUE_POST); + r = JSON_TOKEN_BOOLEAN; + goto finish; + + } else if (startswith(c, "null")) { + *ret_string = NULL; + *ret_value = JSON_VALUE_NULL; + c += 4; + *state = INT_TO_PTR(STATE_VALUE_POST); + r = JSON_TOKEN_NULL; + goto finish; + + } + + return -EINVAL; + + case STATE_VALUE_POST: + + if (*c == ':') { + c++; + *state = INT_TO_PTR(STATE_VALUE); + r = JSON_TOKEN_COLON; + goto null_return; + + } else if (*c == ',') { + c++; + *state = INT_TO_PTR(STATE_VALUE); + r = JSON_TOKEN_COMMA; + goto null_return; + + } else if (*c == '}') { + c++; + *state = INT_TO_PTR(STATE_VALUE_POST); + r = JSON_TOKEN_OBJECT_CLOSE; + goto null_return; + + } else if (*c == ']') { + c++; + *state = INT_TO_PTR(STATE_VALUE_POST); + r = JSON_TOKEN_ARRAY_CLOSE; + goto null_return; + } + + return -EINVAL; + + default: + assert_not_reached("Unexpected tokenizer state"); + } + +null_return: + *ret_string = NULL; + *ret_value = JSON_VALUE_NULL; + +finish: + inc_lines_columns(line, column, start, c - start); + *p = c; + + *ret_line = start_line; + *ret_column = start_column; + + return r; +} + +typedef enum JsonExpect { + /* The following values are used by json_parse() */ + EXPECT_TOPLEVEL, + EXPECT_END, + EXPECT_OBJECT_FIRST_KEY, + EXPECT_OBJECT_NEXT_KEY, + EXPECT_OBJECT_COLON, + EXPECT_OBJECT_VALUE, + EXPECT_OBJECT_COMMA, + EXPECT_ARRAY_FIRST_ELEMENT, + EXPECT_ARRAY_NEXT_ELEMENT, + EXPECT_ARRAY_COMMA, + + /* And these are used by json_build() */ + EXPECT_ARRAY_ELEMENT, + EXPECT_OBJECT_KEY, +} JsonExpect; + +typedef struct JsonStack { + JsonExpect expect; + JsonVariant **elements; + size_t n_elements, n_elements_allocated; + unsigned line_before; + unsigned column_before; + size_t n_suppress; /* When building: if > 0, suppress this many subsequent elements. If == (size_t) -1, suppress all subsequent elements */ +} JsonStack; + +static void json_stack_release(JsonStack *s) { + assert(s); + + json_variant_unref_many(s->elements, s->n_elements); + s->elements = mfree(s->elements); +} + +static int json_parse_internal( + const char **input, + JsonSource *source, + JsonVariant **ret, + unsigned *line, + unsigned *column, + bool continue_end) { + + size_t n_stack = 1, n_stack_allocated = 0, i; + unsigned line_buffer = 0, column_buffer = 0; + void *tokenizer_state = NULL; + JsonStack *stack = NULL; + const char *p; + int r; + + assert_return(input, -EINVAL); + assert_return(ret, -EINVAL); + + p = *input; + + if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack)) + return -ENOMEM; + + stack[0] = (JsonStack) { + .expect = EXPECT_TOPLEVEL, + }; + + if (!line) + line = &line_buffer; + if (!column) + column = &column_buffer; + + for (;;) { + _cleanup_(json_variant_unrefp) JsonVariant *add = NULL; + _cleanup_free_ char *string = NULL; + unsigned line_token, column_token; + JsonStack *current; + JsonValue value; + int token; + + assert(n_stack > 0); + current = stack + n_stack - 1; + + if (continue_end && current->expect == EXPECT_END) + goto done; + + token = json_tokenize(&p, &string, &value, &line_token, &column_token, &tokenizer_state, line, column); + if (token < 0) { + r = token; + goto finish; + } + + switch (token) { + + case JSON_TOKEN_END: + if (current->expect != EXPECT_END) { + r = -EINVAL; + goto finish; + } + + assert(current->n_elements == 1); + assert(n_stack == 1); + goto done; + + case JSON_TOKEN_COLON: + + if (current->expect != EXPECT_OBJECT_COLON) { + r = -EINVAL; + goto finish; + } + + current->expect = EXPECT_OBJECT_VALUE; + break; + + case JSON_TOKEN_COMMA: + + if (current->expect == EXPECT_OBJECT_COMMA) + current->expect = EXPECT_OBJECT_NEXT_KEY; + else if (current->expect == EXPECT_ARRAY_COMMA) + current->expect = EXPECT_ARRAY_NEXT_ELEMENT; + else { + r = -EINVAL; + goto finish; + } + + break; + + case JSON_TOKEN_OBJECT_OPEN: + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) { + r = -ENOMEM; + goto finish; + } + current = stack + n_stack - 1; + + /* Prepare the expect for when we return from the child */ + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_COMMA; + else { + assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)); + current->expect = EXPECT_ARRAY_COMMA; + } + + stack[n_stack++] = (JsonStack) { + .expect = EXPECT_OBJECT_FIRST_KEY, + .line_before = line_token, + .column_before = column_token, + }; + + current = stack + n_stack - 1; + break; + + case JSON_TOKEN_OBJECT_CLOSE: + if (!IN_SET(current->expect, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_COMMA)) { + r = -EINVAL; + goto finish; + } + + assert(n_stack > 1); + + r = json_variant_new_object(&add, current->elements, current->n_elements); + if (r < 0) + goto finish; + + line_token = current->line_before; + column_token = current->column_before; + + json_stack_release(current); + n_stack--, current--; + + break; + + case JSON_TOKEN_ARRAY_OPEN: + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) { + r = -ENOMEM; + goto finish; + } + current = stack + n_stack - 1; + + /* Prepare the expect for when we return from the child */ + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_COMMA; + else { + assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)); + current->expect = EXPECT_ARRAY_COMMA; + } + + stack[n_stack++] = (JsonStack) { + .expect = EXPECT_ARRAY_FIRST_ELEMENT, + .line_before = line_token, + .column_before = column_token, + }; + + break; + + case JSON_TOKEN_ARRAY_CLOSE: + if (!IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_COMMA)) { + r = -EINVAL; + goto finish; + } + + assert(n_stack > 1); + + r = json_variant_new_array(&add, current->elements, current->n_elements); + if (r < 0) + goto finish; + + line_token = current->line_before; + column_token = current->column_before; + + json_stack_release(current); + n_stack--, current--; + break; + + case JSON_TOKEN_STRING: + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_NEXT_KEY, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + r = json_variant_new_string(&add, string); + if (r < 0) + goto finish; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (IN_SET(current->expect, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_NEXT_KEY)) + current->expect = EXPECT_OBJECT_COLON; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_COMMA; + else { + assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)); + current->expect = EXPECT_ARRAY_COMMA; + } + + break; + + case JSON_TOKEN_REAL: + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + r = json_variant_new_real(&add, value.real); + if (r < 0) + goto finish; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_COMMA; + else { + assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)); + current->expect = EXPECT_ARRAY_COMMA; + } + + break; + + case JSON_TOKEN_INTEGER: + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + r = json_variant_new_integer(&add, value.integer); + if (r < 0) + goto finish; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_COMMA; + else { + assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)); + current->expect = EXPECT_ARRAY_COMMA; + } + + break; + + case JSON_TOKEN_UNSIGNED: + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + r = json_variant_new_unsigned(&add, value.unsig); + if (r < 0) + goto finish; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_COMMA; + else { + assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)); + current->expect = EXPECT_ARRAY_COMMA; + } + + break; + + case JSON_TOKEN_BOOLEAN: + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + r = json_variant_new_boolean(&add, value.boolean); + if (r < 0) + goto finish; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_COMMA; + else { + assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)); + current->expect = EXPECT_ARRAY_COMMA; + } + + break; + + case JSON_TOKEN_NULL: + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + r = json_variant_new_null(&add); + if (r < 0) + goto finish; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_COMMA; + else { + assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)); + current->expect = EXPECT_ARRAY_COMMA; + } + + break; + + default: + assert_not_reached("Unexpected token"); + } + + if (add) { + (void) json_variant_set_source(&add, source, line_token, column_token); + + if (!GREEDY_REALLOC(current->elements, current->n_elements_allocated, current->n_elements + 1)) { + r = -ENOMEM; + goto finish; + } + + current->elements[current->n_elements++] = TAKE_PTR(add); + } + } + +done: + assert(n_stack == 1); + assert(stack[0].n_elements == 1); + + *ret = json_variant_ref(stack[0].elements[0]); + *input = p; + r = 0; + +finish: + for (i = 0; i < n_stack; i++) + json_stack_release(stack + i); + + free(stack); + + return r; +} + +int json_parse(const char *input, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) { + return json_parse_internal(&input, NULL, ret, ret_line, ret_column, false); +} + +int json_parse_continue(const char **p, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) { + return json_parse_internal(p, NULL, ret, ret_line, ret_column, true); +} + +int json_parse_file(FILE *f, const char *path, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) { + _cleanup_(json_source_unrefp) JsonSource *source = NULL; + _cleanup_free_ char *text = NULL; + const char *p; + int r; + + if (f) + r = read_full_stream(f, &text, NULL); + else if (path) + r = read_full_file(path, &text, NULL); + else + return -EINVAL; + if (r < 0) + return r; + + if (path) { + source = json_source_new(path); + if (!source) + return -ENOMEM; + } + + p = text; + return json_parse_internal(&p, source, ret, ret_line, ret_column, false); +} + +int json_buildv(JsonVariant **ret, va_list ap) { + JsonStack *stack = NULL; + size_t n_stack = 1, n_stack_allocated = 0, i; + int r; + + assert_return(ret, -EINVAL); + + if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack)) + return -ENOMEM; + + stack[0] = (JsonStack) { + .expect = EXPECT_TOPLEVEL, + }; + + for (;;) { + _cleanup_(json_variant_unrefp) JsonVariant *add = NULL; + size_t n_subtract = 0; /* how much to subtract from current->n_suppress, i.e. how many elements would + * have been added to the current variant */ + JsonStack *current; + int command; + + assert(n_stack > 0); + current = stack + n_stack - 1; + + if (current->expect == EXPECT_END) + goto done; + + command = va_arg(ap, int); + + switch (command) { + + case _JSON_BUILD_STRING: { + const char *p; + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + p = va_arg(ap, const char *); + + if (current->n_suppress == 0) { + r = json_variant_new_string(&add, p); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + } + + case _JSON_BUILD_INTEGER: { + intmax_t j; + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + j = va_arg(ap, intmax_t); + + if (current->n_suppress == 0) { + r = json_variant_new_integer(&add, j); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + } + + case _JSON_BUILD_UNSIGNED: { + uintmax_t j; + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + j = va_arg(ap, uintmax_t); + + if (current->n_suppress == 0) { + r = json_variant_new_unsigned(&add, j); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + } + + case _JSON_BUILD_REAL: { + long double d; + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + d = va_arg(ap, long double); + + if (current->n_suppress == 0) { + r = json_variant_new_real(&add, d); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + } + + case _JSON_BUILD_BOOLEAN: { + bool b; + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + b = va_arg(ap, int); + + if (current->n_suppress == 0) { + r = json_variant_new_boolean(&add, b); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + } + + case _JSON_BUILD_NULL: + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + if (current->n_suppress == 0) { + r = json_variant_new_null(&add); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + + case _JSON_BUILD_VARIANT: + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + /* Note that we don't care for current->n_suppress here, after all the variant is already + * allocated anyway... */ + add = va_arg(ap, JsonVariant*); + if (!add) + add = JSON_VARIANT_MAGIC_NULL; + else + json_variant_ref(add); + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + + case _JSON_BUILD_LITERAL: { + const char *l; + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + l = va_arg(ap, const char *); + + if (l) { + /* Note that we don't care for current->n_suppress here, we should generate parsing + * errors even in suppressed object properties */ + + r = json_parse(l, &add, NULL, NULL); + if (r < 0) + goto finish; + } else + add = JSON_VARIANT_MAGIC_NULL; + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + } + + case _JSON_BUILD_ARRAY_BEGIN: + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) { + r = -ENOMEM; + goto finish; + } + current = stack + n_stack - 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + stack[n_stack++] = (JsonStack) { + .expect = EXPECT_ARRAY_ELEMENT, + .n_suppress = current->n_suppress != 0 ? (size_t) -1 : 0, /* if we shall suppress the + * new array, then we should + * also suppress all array + * members */ + }; + + break; + + case _JSON_BUILD_ARRAY_END: + if (current->expect != EXPECT_ARRAY_ELEMENT) { + r = -EINVAL; + goto finish; + } + + assert(n_stack > 1); + + if (current->n_suppress == 0) { + r = json_variant_new_array(&add, current->elements, current->n_elements); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + json_stack_release(current); + n_stack--, current--; + + break; + + case _JSON_BUILD_STRV: { + char **l; + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + l = va_arg(ap, char **); + + if (current->n_suppress == 0) { + r = json_variant_new_array_strv(&add, l); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + } + + case _JSON_BUILD_OBJECT_BEGIN: + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) { + r = -ENOMEM; + goto finish; + } + current = stack + n_stack - 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + stack[n_stack++] = (JsonStack) { + .expect = EXPECT_OBJECT_KEY, + .n_suppress = current->n_suppress != 0 ? (size_t) -1 : 0, /* if we shall suppress the + * new object, then we should + * also suppress all object + * members */ + }; + + break; + + case _JSON_BUILD_OBJECT_END: + + if (current->expect != EXPECT_OBJECT_KEY) { + r = -EINVAL; + goto finish; + } + + assert(n_stack > 1); + + if (current->n_suppress == 0) { + r = json_variant_new_object(&add, current->elements, current->n_elements); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + json_stack_release(current); + n_stack--, current--; + + break; + + case _JSON_BUILD_PAIR: { + const char *n; + + if (current->expect != EXPECT_OBJECT_KEY) { + r = -EINVAL; + goto finish; + } + + n = va_arg(ap, const char *); + + if (current->n_suppress == 0) { + r = json_variant_new_string(&add, n); + if (r < 0) + goto finish; + } + + n_subtract = 1; + + current->expect = EXPECT_OBJECT_VALUE; + break; + } + + case _JSON_BUILD_PAIR_CONDITION: { + const char *n; + bool b; + + if (current->expect != EXPECT_OBJECT_KEY) { + r = -EINVAL; + goto finish; + } + + b = va_arg(ap, int); + n = va_arg(ap, const char *); + + if (b && current->n_suppress == 0) { + r = json_variant_new_string(&add, n); + if (r < 0) + goto finish; + } + + n_subtract = 1; /* we generated one item */ + + if (!b && current->n_suppress != (size_t) -1) + current->n_suppress += 2; /* Suppress this one and the next item */ + + current->expect = EXPECT_OBJECT_VALUE; + break; + }} + + /* If a variant was generated, add it to our current variant, but only if we are not supposed to suppress additions */ + if (add && current->n_suppress == 0) { + if (!GREEDY_REALLOC(current->elements, current->n_elements_allocated, current->n_elements + 1)) { + r = -ENOMEM; + goto finish; + } + + current->elements[current->n_elements++] = TAKE_PTR(add); + } + + /* If we are supposed to suppress items, let's subtract how many items where generated from that + * counter. Except if the counter is (size_t) -1, i.e. we shall suppress an infinite number of elements + * on this stack level */ + if (current->n_suppress != (size_t) -1) { + if (current->n_suppress <= n_subtract) /* Saturated */ + current->n_suppress = 0; + else + current->n_suppress -= n_subtract; + } + } + +done: + assert(n_stack == 1); + assert(stack[0].n_elements == 1); + + *ret = json_variant_ref(stack[0].elements[0]); + r = 0; + +finish: + for (i = 0; i < n_stack; i++) + json_stack_release(stack + i); + + free(stack); + + return r; +} + +int json_build(JsonVariant **ret, ...) { + va_list ap; + int r; + + va_start(ap, ret); + r = json_buildv(ret, ap); + va_end(ap); + + return r; +} + +int json_log_internal( + JsonVariant *variant, + int level, + int error, + const char *file, + int line, + const char *func, + const char *format, ...) { + + PROTECT_ERRNO; + + unsigned source_line, source_column; + char buffer[LINE_MAX]; + const char *source; + va_list ap; + int r; + + errno = ERRNO_VALUE(error); + + va_start(ap, format); + (void) vsnprintf(buffer, sizeof buffer, format, ap); + va_end(ap); + + if (variant) { + r = json_variant_get_source(variant, &source, &source_line, &source_column); + if (r < 0) + return r; + } else { + source = NULL; + source_line = 0; + source_column = 0; + } + + if (source && source_line > 0 && source_column > 0) + return log_struct_internal( + LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level), + error, + file, line, func, + "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR, + "CONFIG_FILE=%s", source, + "CONFIG_LINE=%u", source_line, + "CONFIG_COLUMN=%u", source_column, + LOG_MESSAGE("%s:%u:%u: %s", source, source_line, source_column, buffer), + NULL); + else + return log_struct_internal( + LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level), + error, + file, line, func, + "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR, + LOG_MESSAGE("%s", buffer), + NULL); +} + +int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata) { + const JsonDispatch *p; + size_t i, n, m; + int r, done = 0; + bool *found; + + if (!json_variant_is_object(v)) { + json_log(v, flags, 0, "JSON variant is not an object."); + + if (flags & JSON_PERMISSIVE) + return 0; + + return -EINVAL; + } + + for (p = table, m = 0; p->name; p++) + m++; + + found = newa0(bool, m); + + n = json_variant_elements(v); + for (i = 0; i < n; i += 2) { + JsonVariant *key, *value; + + assert_se(key = json_variant_by_index(v, i)); + assert_se(value = json_variant_by_index(v, i+1)); + + for (p = table; p->name; p++) + if (p->name == (const char*) -1 || + streq_ptr(json_variant_string(key), p->name)) + break; + + if (p->name) { /* Found a matching entry! :-) */ + JsonDispatchFlags merged_flags; + + merged_flags = flags | p->flags; + + if (p->type != _JSON_VARIANT_TYPE_INVALID && + !json_variant_has_type(value, p->type)) { + + json_log(value, merged_flags, 0, + "Object field '%s' has wrong type %s, expected %s.", json_variant_string(key), + json_variant_type_to_string(json_variant_type(value)), json_variant_type_to_string(p->type)); + + if (merged_flags & JSON_PERMISSIVE) + continue; + + return -EINVAL; + } + + if (found[p-table]) { + json_log(value, merged_flags, 0, "Duplicate object field '%s'.", json_variant_string(key)); + + if (merged_flags & JSON_PERMISSIVE) + continue; + + return -ENOTUNIQ; + } + + found[p-table] = true; + + if (p->callback) { + r = p->callback(json_variant_string(key), value, merged_flags, (uint8_t*) userdata + p->offset); + if (r < 0) { + if (merged_flags & JSON_PERMISSIVE) + continue; + + return r; + } + } + + done ++; + + } else { /* Didn't find a matching entry! :-( */ + + if (bad) { + r = bad(json_variant_string(key), value, flags, userdata); + if (r < 0) { + if (flags & JSON_PERMISSIVE) + continue; + + return r; + } else + done ++; + + } else { + json_log(value, flags, 0, "Unexpected object field '%s'.", json_variant_string(key)); + + if (flags & JSON_PERMISSIVE) + continue; + + return -EADDRNOTAVAIL; + } + } + } + + for (p = table; p->name; p++) { + JsonDispatchFlags merged_flags = p->flags | flags; + + if ((merged_flags & JSON_MANDATORY) && !found[p-table]) { + json_log(v, merged_flags, 0, "Missing object field '%s'.", p->name); + + if ((merged_flags & JSON_PERMISSIVE)) + continue; + + return -ENXIO; + } + } + + return done; +} + +int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { + bool *b = userdata; + + assert(variant); + assert(b); + + if (!json_variant_is_boolean(variant)) + return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a boolean.", strna(name)); + + *b = json_variant_boolean(variant); + return 0; +} + +int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { + int *b = userdata; + + assert(variant); + assert(b); + + if (!json_variant_is_boolean(variant)) + return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a boolean.", strna(name)); + + *b = json_variant_boolean(variant); + return 0; +} + +int json_dispatch_integer(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { + intmax_t *i = userdata; + + assert(variant); + assert(i); + + if (!json_variant_is_integer(variant)) + return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name)); + + *i = json_variant_integer(variant); + return 0; +} + +int json_dispatch_unsigned(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { + uintmax_t *u = userdata; + + assert(variant); + assert(u); + + if (!json_variant_is_unsigned(variant)) + return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an unsigned integer.", strna(name)); + + *u = json_variant_unsigned(variant); + return 0; +} + +int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { + uint32_t *u = userdata; + + assert(variant); + assert(u); + + if (!json_variant_is_unsigned(variant)) + return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an unsigned integer.", strna(name)); + + if (json_variant_unsigned(variant) > UINT32_MAX) + return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds.", strna(name)); + + *u = (uint32_t) json_variant_unsigned(variant); + return 0; +} + +int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { + int32_t *i = userdata; + + assert(variant); + assert(i); + + if (!json_variant_is_integer(variant)) + return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name)); + + if (json_variant_integer(variant) < INT32_MIN || json_variant_integer(variant) > INT32_MAX) + return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds.", strna(name)); + + *i = (int32_t) json_variant_integer(variant); + return 0; +} + +int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { + char **s = userdata; + int r; + + assert(variant); + assert(s); + + if (json_variant_is_null(variant)) { + *s = mfree(*s); + return 0; + } + + if (!json_variant_is_string(variant)) + return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name)); + + r = free_and_strdup(s, json_variant_string(variant)); + if (r < 0) + return json_log(variant, flags, r, "Failed to allocate string: %m"); + + return 0; +} + +int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { + _cleanup_strv_free_ char **l = NULL; + char ***s = userdata; + JsonVariant *e; + int r; + + assert(variant); + assert(s); + + if (json_variant_is_null(variant)) { + *s = strv_free(*s); + return 0; + } + + if (!json_variant_is_array(variant)) + return json_log(variant, SYNTHETIC_ERRNO(EINVAL), flags, "JSON field '%s' is not an array.", strna(name)); + + JSON_VARIANT_ARRAY_FOREACH(e, variant) { + if (!json_variant_is_string(e)) + return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), "JSON array element is not a string."); + + r = strv_extend(&l, json_variant_string(e)); + if (r < 0) + return json_log(e, flags, r, "Failed to append array element: %m"); + } + + strv_free_and_replace(*s, l); + return 0; +} + +int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { + JsonVariant **p = userdata; + + assert(variant); + assert(p); + + json_variant_unref(*p); + *p = json_variant_ref(variant); + + return 0; +} + +static const char* const json_variant_type_table[_JSON_VARIANT_TYPE_MAX] = { + [JSON_VARIANT_STRING] = "string", + [JSON_VARIANT_INTEGER] = "integer", + [JSON_VARIANT_UNSIGNED] = "unsigned", + [JSON_VARIANT_REAL] = "real", + [JSON_VARIANT_NUMBER] = "number", + [JSON_VARIANT_BOOLEAN] = "boolean", + [JSON_VARIANT_ARRAY] = "array", + [JSON_VARIANT_OBJECT] = "object", + [JSON_VARIANT_NULL] = "null", +}; + +DEFINE_STRING_TABLE_LOOKUP(json_variant_type, JsonVariantType); diff --git a/src/shared/json.h b/src/shared/json.h new file mode 100644 index 00000000..1f9c620e --- /dev/null +++ b/src/shared/json.h @@ -0,0 +1,288 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "macro.h" +#include "string-util.h" +#include "log.h" + +/* + In case you wonder why we have our own JSON implementation, here are a couple of reasons why this implementation has + benefits over various other implementations: + + - We need support for 64bit signed and unsigned integers, i.e. the full 64,5bit range of -9223372036854775808…18446744073709551615 + - All our variants are immutable after creation + - Special values such as true, false, zero, null, empty strings, empty array, empty objects require zero dynamic memory + - Progressive parsing + - Our integer/real type implicitly converts, but only if that's safe and loss-lessly possible + - There's a "builder" for putting together objects easily in varargs function calls + - There's a "dispatcher" for mapping objects to C data structures + - Every variant optionally carries parsing location information, which simplifies debugging and parse log error generation + - Formatter has color, line, column support + + Limitations: + - Doesn't allow embedded NUL in strings + - Can't store integers outside of the -9223372036854775808…18446744073709551615 range (it will use 'long double' for + values outside this range, which is lossy) + - Can't store negative zero (will be treated identical to positive zero, and not retained across serialization) + - Can't store non-integer numbers that can't be stored in "long double" losslessly + - Allows creation and parsing of objects with duplicate keys. The "dispatcher" will refuse them however. This means + we can parse and pass around such objects, but will carefully refuse them when we convert them into our own data. + + (These limitations should be pretty much in line with those of other JSON implementations, in fact might be less + limiting in most cases even.) +*/ + +typedef struct JsonVariant JsonVariant; + +typedef enum JsonVariantType { + JSON_VARIANT_STRING, + JSON_VARIANT_INTEGER, + JSON_VARIANT_UNSIGNED, + JSON_VARIANT_REAL, + JSON_VARIANT_NUMBER, /* This a pseudo-type: we can never create variants of this type, but we use it as wildcard check for the above three types */ + JSON_VARIANT_BOOLEAN, + JSON_VARIANT_ARRAY, + JSON_VARIANT_OBJECT, + JSON_VARIANT_NULL, + _JSON_VARIANT_TYPE_MAX, + _JSON_VARIANT_TYPE_INVALID = -1 +} JsonVariantType; + +int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n); +int json_variant_new_integer(JsonVariant **ret, intmax_t i); +int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u); +int json_variant_new_real(JsonVariant **ret, long double d); +int json_variant_new_boolean(JsonVariant **ret, bool b); +int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n); +int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n); +int json_variant_new_array_strv(JsonVariant **ret, char **l); +int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n); +int json_variant_new_null(JsonVariant **ret); + +static inline int json_variant_new_string(JsonVariant **ret, const char *s) { + return json_variant_new_stringn(ret, s, (size_t) -1); +} + +JsonVariant *json_variant_ref(JsonVariant *v); +JsonVariant *json_variant_unref(JsonVariant *v); +void json_variant_unref_many(JsonVariant **array, size_t n); + +DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref); + +const char *json_variant_string(JsonVariant *v); +intmax_t json_variant_integer(JsonVariant *v); +uintmax_t json_variant_unsigned(JsonVariant *v); +long double json_variant_real(JsonVariant *v); +bool json_variant_boolean(JsonVariant *v); + +JsonVariantType json_variant_type(JsonVariant *v); +bool json_variant_has_type(JsonVariant *v, JsonVariantType type); + +static inline bool json_variant_is_string(JsonVariant *v) { + return json_variant_has_type(v, JSON_VARIANT_STRING); +} + +static inline bool json_variant_is_integer(JsonVariant *v) { + return json_variant_has_type(v, JSON_VARIANT_INTEGER); +} + +static inline bool json_variant_is_unsigned(JsonVariant *v) { + return json_variant_has_type(v, JSON_VARIANT_UNSIGNED); +} + +static inline bool json_variant_is_real(JsonVariant *v) { + return json_variant_has_type(v, JSON_VARIANT_REAL); +} + +static inline bool json_variant_is_number(JsonVariant *v) { + return json_variant_has_type(v, JSON_VARIANT_NUMBER); +} + +static inline bool json_variant_is_boolean(JsonVariant *v) { + return json_variant_has_type(v, JSON_VARIANT_BOOLEAN); +} + +static inline bool json_variant_is_array(JsonVariant *v) { + return json_variant_has_type(v, JSON_VARIANT_ARRAY); +} + +static inline bool json_variant_is_object(JsonVariant *v) { + return json_variant_has_type(v, JSON_VARIANT_OBJECT); +} + +static inline bool json_variant_is_null(JsonVariant *v) { + return json_variant_has_type(v, JSON_VARIANT_NULL); +} + +bool json_variant_is_negative(JsonVariant *v); + +size_t json_variant_elements(JsonVariant *v); +JsonVariant *json_variant_by_index(JsonVariant *v, size_t index); +JsonVariant *json_variant_by_key(JsonVariant *v, const char *key); +JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key); + +bool json_variant_equal(JsonVariant *a, JsonVariant *b); + +struct json_variant_foreach_state { + JsonVariant *variant; + size_t idx; +}; + +#define JSON_VARIANT_ARRAY_FOREACH(i, v) \ + for (struct json_variant_foreach_state _state = { (v), 0 }; \ + json_variant_is_array(_state.variant) && \ + _state.idx < json_variant_elements(_state.variant) && \ + ({ i = json_variant_by_index(_state.variant, _state.idx); \ + true; }); \ + _state.idx++) + +#define JSON_VARIANT_OBJECT_FOREACH(k, e, v) \ + for (struct json_variant_foreach_state _state = { (v), 0 }; \ + json_variant_is_object(_state.variant) && \ + _state.idx < json_variant_elements(_state.variant) && \ + ({ k = json_variant_string(json_variant_by_index(_state.variant, _state.idx)); \ + e = json_variant_by_index(_state.variant, _state.idx + 1); \ + true; }); \ + _state.idx += 2) + +int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column); + +typedef enum JsonFormatFlags { + JSON_FORMAT_NEWLINE = 1 << 0, /* suffix with newline */ + JSON_FORMAT_PRETTY = 1 << 1, /* add internal whitespace to appeal to human readers */ + JSON_FORMAT_COLOR = 1 << 2, /* insert ANSI color sequences */ + JSON_FORMAT_COLOR_AUTO = 1 << 3, /* insert ANSI color sequences if colors_enabled() says so */ + JSON_FORMAT_SOURCE = 1 << 4, /* prefix with source filename/line/column */ + JSON_FORMAT_SSE = 1 << 5, /* prefix/suffix with W3C server-sent events */ + JSON_FORMAT_SEQ = 1 << 6, /* prefix/suffix with RFC 7464 application/json-seq */ +} JsonFormatFlags; + +int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret); +void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix); + +int json_parse(const char *string, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column); +int json_parse_continue(const char **p, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column); +int json_parse_file(FILE *f, const char *path, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column); + +enum { + _JSON_BUILD_STRING, + _JSON_BUILD_INTEGER, + _JSON_BUILD_UNSIGNED, + _JSON_BUILD_REAL, + _JSON_BUILD_BOOLEAN, + _JSON_BUILD_ARRAY_BEGIN, + _JSON_BUILD_ARRAY_END, + _JSON_BUILD_OBJECT_BEGIN, + _JSON_BUILD_OBJECT_END, + _JSON_BUILD_PAIR, + _JSON_BUILD_PAIR_CONDITION, + _JSON_BUILD_NULL, + _JSON_BUILD_VARIANT, + _JSON_BUILD_LITERAL, + _JSON_BUILD_STRV, + _JSON_BUILD_MAX, +}; + +#define JSON_BUILD_STRING(s) _JSON_BUILD_STRING, ({ const char *_x = s; _x; }) +#define JSON_BUILD_INTEGER(i) _JSON_BUILD_INTEGER, ({ intmax_t _x = i; _x; }) +#define JSON_BUILD_UNSIGNED(u) _JSON_BUILD_UNSIGNED, ({ uintmax_t _x = u; _x; }) +#define JSON_BUILD_REAL(d) _JSON_BUILD_REAL, ({ long double _x = d; _x; }) +#define JSON_BUILD_BOOLEAN(b) _JSON_BUILD_BOOLEAN, ({ bool _x = b; _x; }) +#define JSON_BUILD_ARRAY(...) _JSON_BUILD_ARRAY_BEGIN, __VA_ARGS__, _JSON_BUILD_ARRAY_END +#define JSON_BUILD_OBJECT(...) _JSON_BUILD_OBJECT_BEGIN, __VA_ARGS__, _JSON_BUILD_OBJECT_END +#define JSON_BUILD_PAIR(n, ...) _JSON_BUILD_PAIR, ({ const char *_x = n; _x; }), __VA_ARGS__ +#define JSON_BUILD_PAIR_CONDITION(c, n, ...) _JSON_BUILD_PAIR_CONDITION, ({ bool _x = c; _x; }), ({ const char *_x = n; _x; }), __VA_ARGS__ +#define JSON_BUILD_NULL _JSON_BUILD_NULL +#define JSON_BUILD_VARIANT(v) _JSON_BUILD_VARIANT, ({ JsonVariant *_x = v; _x; }) +#define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, ({ const char *_x = l; _x; }) +#define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, ({ char **_x = l; _x; }) + +int json_build(JsonVariant **ret, ...); +int json_buildv(JsonVariant **ret, va_list ap); + +/* A bitmask of flags used by the dispatch logic. Note that this is a combined bit mask, that is generated from the bit + * mask originally passed into json_dispatch(), the individual bitmask associated with the static JsonDispatch callout + * entry, as well the bitmask specified for json_log() calls */ +typedef enum JsonDispatchFlags { + /* The following three may be set in JsonDispatch's .flags field or the json_dispatch() flags parameter */ + JSON_PERMISSIVE = 1 << 0, /* Shall parsing errors be considered fatal for this property? */ + JSON_MANDATORY = 1 << 1, /* Should existence of this property be mandatory? */ + JSON_LOG = 1 << 2, /* Should the parser log about errors? */ + + /* The following two may be passed into log_json() in addition to the three above */ + JSON_DEBUG = 1 << 3, /* Indicates that this log message is a debug message */ + JSON_WARNING = 1 << 4, /* Indicates that this log message is a warning message */ +} JsonDispatchFlags; + +typedef int (*JsonDispatchCallback)(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); + +typedef struct JsonDispatch { + const char *name; + JsonVariantType type; + JsonDispatchCallback callback; + size_t offset; + JsonDispatchFlags flags; +} JsonDispatch; + +int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata); + +int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); +int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); +int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); +int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); +int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); +int json_dispatch_integer(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); +int json_dispatch_unsigned(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); +int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); +int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); + +assert_cc(sizeof(uintmax_t) == sizeof(uint64_t)); +#define json_dispatch_uint64 json_dispatch_unsigned + +assert_cc(sizeof(intmax_t) == sizeof(int64_t)); +#define json_dispatch_int64 json_dispatch_integer + +static inline int json_dispatch_level(JsonDispatchFlags flags) { + + /* Did the user request no logging? If so, then never log higher than LOG_DEBUG. Also, if this is marked as + * debug message, then also log at debug level. */ + + if (!(flags & JSON_LOG) || + (flags & JSON_DEBUG)) + return LOG_DEBUG; + + /* Are we invoked in permissive mode, or is this explicitly marked as warning message? Then this should be + * printed at LOG_WARNING */ + if (flags & (JSON_PERMISSIVE|JSON_WARNING)) + return LOG_WARNING; + + /* Otherwise it's an error. */ + return LOG_ERR; +} + +int json_log_internal(JsonVariant *variant, int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(7, 8); + +#define json_log(variant, flags, error, ...) \ + ({ \ + int _level = json_dispatch_level(flags), _e = (error); \ + (log_get_max_level() >= LOG_PRI(_level)) \ + ? json_log_internal(variant, _level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ + : -ERRNO_VALUE(_e); \ + }) + +#define JSON_VARIANT_STRING_CONST(x) _JSON_VARIANT_STRING_CONST(UNIQ, (x)) + +#define _JSON_VARIANT_STRING_CONST(xq, x) \ + ({ \ + _align_(2) static const char UNIQ_T(json_string_const, xq)[] = (x); \ + assert((((uintptr_t) UNIQ_T(json_string_const, xq)) & 1) == 0); \ + (JsonVariant*) ((uintptr_t) UNIQ_T(json_string_const, xq) + 1); \ + }) + +const char *json_variant_type_to_string(JsonVariantType t); +JsonVariantType json_variant_type_from_string(const char *s); diff --git a/src/shared/libmount-util.h b/src/shared/libmount-util.h new file mode 100644 index 00000000..7c3b855d --- /dev/null +++ b/src/shared/libmount-util.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +/* This needs to be after sys/mount.h */ +#include + +#include "macro.h" + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter); + +static inline int libmount_parse( + const char *path, + FILE *source, + struct libmnt_table **ret_table, + struct libmnt_iter **ret_iter) { + + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; + int r; + + /* Older libmount seems to require this. */ + assert(!source || path); + + table = mnt_new_table(); + iter = mnt_new_iter(MNT_ITER_FORWARD); + if (!table || !iter) + return -ENOMEM; + + /* If source or path are specified, we use on the functions which ignore utab. + * Only if both are empty, we use mnt_table_parse_mtab(). */ + + if (source) + r = mnt_table_parse_stream(table, source, path); + else if (path) + r = mnt_table_parse_file(table, path); + else + r = mnt_table_parse_mtab(table, NULL); + if (r < 0) + return r; + + *ret_table = TAKE_PTR(table); + *ret_iter = TAKE_PTR(iter); + return 0; +} diff --git a/src/shared/libshared.sym b/src/shared/libshared.sym new file mode 100644 index 00000000..6a7495ad --- /dev/null +++ b/src/shared/libshared.sym @@ -0,0 +1,3 @@ +SD_SHARED { + global: *; +}; diff --git a/src/shared/linux/README b/src/shared/linux/README new file mode 100644 index 00000000..46d55476 --- /dev/null +++ b/src/shared/linux/README @@ -0,0 +1,8 @@ +The files in this directory are copied from kernel-5.2, and the following modifications are applied: +- auto_dev-ioctl.h: set AUTOFS_DEV_IOCTL_VERSION_MINOR to 0 +- auto_dev-ioctl.h: define AUTOFS_IOCTL if not defined +- bpf_insn.h: This is imported from samples/bpf/bpf_insn.h +- bpf_insn.h: BPF_JMP_A() macro is also imported from include/linux/filter.h +- dm-ioctl.h: set DM_VERSION_MINOR to 27 +- ethtool.h: define __KERNEL_DIV_ROUND_UP if not defined +- ethtool.h: add casts in ethtool_cmd_speed() diff --git a/src/shared/linux/auto_dev-ioctl.h b/src/shared/linux/auto_dev-ioctl.h new file mode 100644 index 00000000..261546c6 --- /dev/null +++ b/src/shared/linux/auto_dev-ioctl.h @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +/* + * Copyright 2008 Red Hat, Inc. All rights reserved. + * Copyright 2008 Ian Kent + * + * This file is part of the Linux kernel and is made available under + * the terms of the GNU General Public License, version 2, or at your + * option, any later version, incorporated herein by reference. + */ + +#ifndef _UAPI_LINUX_AUTO_DEV_IOCTL_H +#define _UAPI_LINUX_AUTO_DEV_IOCTL_H + +#include +#include + +#define AUTOFS_DEVICE_NAME "autofs" + +#define AUTOFS_DEV_IOCTL_VERSION_MAJOR 1 +#define AUTOFS_DEV_IOCTL_VERSION_MINOR 0 + +#define AUTOFS_DEV_IOCTL_SIZE sizeof(struct autofs_dev_ioctl) + +/* + * An ioctl interface for autofs mount point control. + */ + +struct args_protover { + __u32 version; +}; + +struct args_protosubver { + __u32 sub_version; +}; + +struct args_openmount { + __u32 devid; +}; + +struct args_ready { + __u32 token; +}; + +struct args_fail { + __u32 token; + __s32 status; +}; + +struct args_setpipefd { + __s32 pipefd; +}; + +struct args_timeout { + __u64 timeout; +}; + +struct args_requester { + __u32 uid; + __u32 gid; +}; + +struct args_expire { + __u32 how; +}; + +struct args_askumount { + __u32 may_umount; +}; + +struct args_ismountpoint { + union { + struct args_in { + __u32 type; + } in; + struct args_out { + __u32 devid; + __u32 magic; + } out; + }; +}; + +/* + * All the ioctls use this structure. + * When sending a path size must account for the total length + * of the chunk of memory otherwise is is the size of the + * structure. + */ + +struct autofs_dev_ioctl { + __u32 ver_major; + __u32 ver_minor; + __u32 size; /* total size of data passed in + * including this struct */ + __s32 ioctlfd; /* automount command fd */ + + /* Command parameters */ + + union { + struct args_protover protover; + struct args_protosubver protosubver; + struct args_openmount openmount; + struct args_ready ready; + struct args_fail fail; + struct args_setpipefd setpipefd; + struct args_timeout timeout; + struct args_requester requester; + struct args_expire expire; + struct args_askumount askumount; + struct args_ismountpoint ismountpoint; + }; + + char path[0]; +}; + +static inline void init_autofs_dev_ioctl(struct autofs_dev_ioctl *in) +{ + memset(in, 0, AUTOFS_DEV_IOCTL_SIZE); + in->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR; + in->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR; + in->size = AUTOFS_DEV_IOCTL_SIZE; + in->ioctlfd = -1; +} + +enum { + /* Get various version info */ + AUTOFS_DEV_IOCTL_VERSION_CMD = 0x71, + AUTOFS_DEV_IOCTL_PROTOVER_CMD, + AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD, + + /* Open mount ioctl fd */ + AUTOFS_DEV_IOCTL_OPENMOUNT_CMD, + + /* Close mount ioctl fd */ + AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD, + + /* Mount/expire status returns */ + AUTOFS_DEV_IOCTL_READY_CMD, + AUTOFS_DEV_IOCTL_FAIL_CMD, + + /* Activate/deactivate autofs mount */ + AUTOFS_DEV_IOCTL_SETPIPEFD_CMD, + AUTOFS_DEV_IOCTL_CATATONIC_CMD, + + /* Expiry timeout */ + AUTOFS_DEV_IOCTL_TIMEOUT_CMD, + + /* Get mount last requesting uid and gid */ + AUTOFS_DEV_IOCTL_REQUESTER_CMD, + + /* Check for eligible expire candidates */ + AUTOFS_DEV_IOCTL_EXPIRE_CMD, + + /* Request busy status */ + AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD, + + /* Check if path is a mountpoint */ + AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD, +}; + +#ifndef AUTOFS_IOCTL +#define AUTOFS_IOCTL 0x93 +#endif + +#define AUTOFS_DEV_IOCTL_VERSION \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_VERSION_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_PROTOVER \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_PROTOVER_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_PROTOSUBVER \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_OPENMOUNT \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_OPENMOUNT_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_CLOSEMOUNT \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_READY \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_READY_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_FAIL \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_FAIL_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_SETPIPEFD \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_SETPIPEFD_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_CATATONIC \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_CATATONIC_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_TIMEOUT \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_TIMEOUT_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_REQUESTER \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_REQUESTER_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_EXPIRE \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_EXPIRE_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_ASKUMOUNT \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD, struct autofs_dev_ioctl) + +#define AUTOFS_DEV_IOCTL_ISMOUNTPOINT \ + _IOWR(AUTOFS_IOCTL, \ + AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD, struct autofs_dev_ioctl) + +#endif /* _UAPI_LINUX_AUTO_DEV_IOCTL_H */ diff --git a/src/shared/linux/bpf.h b/src/shared/linux/bpf.h new file mode 100644 index 00000000..359fc370 --- /dev/null +++ b/src/shared/linux/bpf.h @@ -0,0 +1,3057 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#ifndef _UAPI__LINUX_BPF_H__ +#define _UAPI__LINUX_BPF_H__ + +#include +#include + +/* Extended instruction set based on top of classic BPF */ + +/* instruction classes */ +#define BPF_ALU64 0x07 /* alu mode in double word width */ + +/* ld/ldx fields */ +#define BPF_DW 0x18 /* double word (64-bit) */ +#define BPF_XADD 0xc0 /* exclusive add */ + +/* alu/jmp fields */ +#define BPF_MOV 0xb0 /* mov reg to reg */ +#define BPF_ARSH 0xc0 /* sign extending arithmetic shift right */ + +/* change endianness of a register */ +#define BPF_END 0xd0 /* flags for endianness conversion: */ +#define BPF_TO_LE 0x00 /* convert to little-endian */ +#define BPF_TO_BE 0x08 /* convert to big-endian */ +#define BPF_FROM_LE BPF_TO_LE +#define BPF_FROM_BE BPF_TO_BE + +/* jmp encodings */ +#define BPF_JNE 0x50 /* jump != */ +#define BPF_JLT 0xa0 /* LT is unsigned, '<' */ +#define BPF_JLE 0xb0 /* LE is unsigned, '<=' */ +#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */ +#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */ +#define BPF_JSLT 0xc0 /* SLT is signed, '<' */ +#define BPF_JSLE 0xd0 /* SLE is signed, '<=' */ +#define BPF_CALL 0x80 /* function call */ +#define BPF_EXIT 0x90 /* function return */ + +/* Register numbers */ +enum { + BPF_REG_0 = 0, + BPF_REG_1, + BPF_REG_2, + BPF_REG_3, + BPF_REG_4, + BPF_REG_5, + BPF_REG_6, + BPF_REG_7, + BPF_REG_8, + BPF_REG_9, + BPF_REG_10, + __MAX_BPF_REG, +}; + +/* BPF has 10 general purpose 64-bit registers and stack frame. */ +#define MAX_BPF_REG __MAX_BPF_REG + +struct bpf_insn { + __u8 code; /* opcode */ + __u8 dst_reg:4; /* dest register */ + __u8 src_reg:4; /* source register */ + __s16 off; /* signed offset */ + __s32 imm; /* signed immediate constant */ +}; + +/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */ +struct bpf_lpm_trie_key { + __u32 prefixlen; /* up to 32 for AF_INET, 128 for AF_INET6 */ + __u8 data[0]; /* Arbitrary size */ +}; + +struct bpf_cgroup_storage_key { + __u64 cgroup_inode_id; /* cgroup inode id */ + __u32 attach_type; /* program attach type */ +}; + +/* BPF syscall commands, see bpf(2) man-page for details. */ +enum bpf_cmd { + BPF_MAP_CREATE, + BPF_MAP_LOOKUP_ELEM, + BPF_MAP_UPDATE_ELEM, + BPF_MAP_DELETE_ELEM, + BPF_MAP_GET_NEXT_KEY, + BPF_PROG_LOAD, + BPF_OBJ_PIN, + BPF_OBJ_GET, + BPF_PROG_ATTACH, + BPF_PROG_DETACH, + BPF_PROG_TEST_RUN, + BPF_PROG_GET_NEXT_ID, + BPF_MAP_GET_NEXT_ID, + BPF_PROG_GET_FD_BY_ID, + BPF_MAP_GET_FD_BY_ID, + BPF_OBJ_GET_INFO_BY_FD, + BPF_PROG_QUERY, + BPF_RAW_TRACEPOINT_OPEN, + BPF_BTF_LOAD, + BPF_BTF_GET_FD_BY_ID, + BPF_TASK_FD_QUERY, + BPF_MAP_LOOKUP_AND_DELETE_ELEM, +}; + +enum bpf_map_type { + BPF_MAP_TYPE_UNSPEC, + BPF_MAP_TYPE_HASH, + BPF_MAP_TYPE_ARRAY, + BPF_MAP_TYPE_PROG_ARRAY, + BPF_MAP_TYPE_PERF_EVENT_ARRAY, + BPF_MAP_TYPE_PERCPU_HASH, + BPF_MAP_TYPE_PERCPU_ARRAY, + BPF_MAP_TYPE_STACK_TRACE, + BPF_MAP_TYPE_CGROUP_ARRAY, + BPF_MAP_TYPE_LRU_HASH, + BPF_MAP_TYPE_LRU_PERCPU_HASH, + BPF_MAP_TYPE_LPM_TRIE, + BPF_MAP_TYPE_ARRAY_OF_MAPS, + BPF_MAP_TYPE_HASH_OF_MAPS, + BPF_MAP_TYPE_DEVMAP, + BPF_MAP_TYPE_SOCKMAP, + BPF_MAP_TYPE_CPUMAP, + BPF_MAP_TYPE_XSKMAP, + BPF_MAP_TYPE_SOCKHASH, + BPF_MAP_TYPE_CGROUP_STORAGE, + BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, + BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE, + BPF_MAP_TYPE_QUEUE, + BPF_MAP_TYPE_STACK, +}; + +/* Note that tracing related programs such as + * BPF_PROG_TYPE_{KPROBE,TRACEPOINT,PERF_EVENT,RAW_TRACEPOINT} + * are not subject to a stable API since kernel internal data + * structures can change from release to release and may + * therefore break existing tracing BPF programs. Tracing BPF + * programs correspond to /a/ specific kernel which is to be + * analyzed, and not /a/ specific kernel /and/ all future ones. + */ +enum bpf_prog_type { + BPF_PROG_TYPE_UNSPEC, + BPF_PROG_TYPE_SOCKET_FILTER, + BPF_PROG_TYPE_KPROBE, + BPF_PROG_TYPE_SCHED_CLS, + BPF_PROG_TYPE_SCHED_ACT, + BPF_PROG_TYPE_TRACEPOINT, + BPF_PROG_TYPE_XDP, + BPF_PROG_TYPE_PERF_EVENT, + BPF_PROG_TYPE_CGROUP_SKB, + BPF_PROG_TYPE_CGROUP_SOCK, + BPF_PROG_TYPE_LWT_IN, + BPF_PROG_TYPE_LWT_OUT, + BPF_PROG_TYPE_LWT_XMIT, + BPF_PROG_TYPE_SOCK_OPS, + BPF_PROG_TYPE_SK_SKB, + BPF_PROG_TYPE_CGROUP_DEVICE, + BPF_PROG_TYPE_SK_MSG, + BPF_PROG_TYPE_RAW_TRACEPOINT, + BPF_PROG_TYPE_CGROUP_SOCK_ADDR, + BPF_PROG_TYPE_LWT_SEG6LOCAL, + BPF_PROG_TYPE_LIRC_MODE2, + BPF_PROG_TYPE_SK_REUSEPORT, + BPF_PROG_TYPE_FLOW_DISSECTOR, +}; + +enum bpf_attach_type { + BPF_CGROUP_INET_INGRESS, + BPF_CGROUP_INET_EGRESS, + BPF_CGROUP_INET_SOCK_CREATE, + BPF_CGROUP_SOCK_OPS, + BPF_SK_SKB_STREAM_PARSER, + BPF_SK_SKB_STREAM_VERDICT, + BPF_CGROUP_DEVICE, + BPF_SK_MSG_VERDICT, + BPF_CGROUP_INET4_BIND, + BPF_CGROUP_INET6_BIND, + BPF_CGROUP_INET4_CONNECT, + BPF_CGROUP_INET6_CONNECT, + BPF_CGROUP_INET4_POST_BIND, + BPF_CGROUP_INET6_POST_BIND, + BPF_CGROUP_UDP4_SENDMSG, + BPF_CGROUP_UDP6_SENDMSG, + BPF_LIRC_MODE2, + BPF_FLOW_DISSECTOR, + __MAX_BPF_ATTACH_TYPE +}; + +#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE + +/* cgroup-bpf attach flags used in BPF_PROG_ATTACH command + * + * NONE(default): No further bpf programs allowed in the subtree. + * + * BPF_F_ALLOW_OVERRIDE: If a sub-cgroup installs some bpf program, + * the program in this cgroup yields to sub-cgroup program. + * + * BPF_F_ALLOW_MULTI: If a sub-cgroup installs some bpf program, + * that cgroup program gets run in addition to the program in this cgroup. + * + * Only one program is allowed to be attached to a cgroup with + * NONE or BPF_F_ALLOW_OVERRIDE flag. + * Attaching another program on top of NONE or BPF_F_ALLOW_OVERRIDE will + * release old program and attach the new one. Attach flags has to match. + * + * Multiple programs are allowed to be attached to a cgroup with + * BPF_F_ALLOW_MULTI flag. They are executed in FIFO order + * (those that were attached first, run first) + * The programs of sub-cgroup are executed first, then programs of + * this cgroup and then programs of parent cgroup. + * When children program makes decision (like picking TCP CA or sock bind) + * parent program has a chance to override it. + * + * A cgroup with MULTI or OVERRIDE flag allows any attach flags in sub-cgroups. + * A cgroup with NONE doesn't allow any programs in sub-cgroups. + * Ex1: + * cgrp1 (MULTI progs A, B) -> + * cgrp2 (OVERRIDE prog C) -> + * cgrp3 (MULTI prog D) -> + * cgrp4 (OVERRIDE prog E) -> + * cgrp5 (NONE prog F) + * the event in cgrp5 triggers execution of F,D,A,B in that order. + * if prog F is detached, the execution is E,D,A,B + * if prog F and D are detached, the execution is E,A,B + * if prog F, E and D are detached, the execution is C,A,B + * + * All eligible programs are executed regardless of return code from + * earlier programs. + */ +#define BPF_F_ALLOW_OVERRIDE (1U << 0) +#define BPF_F_ALLOW_MULTI (1U << 1) + +/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the + * verifier will perform strict alignment checking as if the kernel + * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set, + * and NET_IP_ALIGN defined to 2. + */ +#define BPF_F_STRICT_ALIGNMENT (1U << 0) + +/* If BPF_F_ANY_ALIGNMENT is used in BPF_PROF_LOAD command, the + * verifier will allow any alignment whatsoever. On platforms + * with strict alignment requirements for loads ands stores (such + * as sparc and mips) the verifier validates that all loads and + * stores provably follow this requirement. This flag turns that + * checking and enforcement off. + * + * It is mostly used for testing when we want to validate the + * context and memory access aspects of the verifier, but because + * of an unaligned access the alignment check would trigger before + * the one we are interested in. + */ +#define BPF_F_ANY_ALIGNMENT (1U << 1) + +/* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ +#define BPF_PSEUDO_MAP_FD 1 + +/* when bpf_call->src_reg == BPF_PSEUDO_CALL, bpf_call->imm == pc-relative + * offset to another bpf function + */ +#define BPF_PSEUDO_CALL 1 + +/* flags for BPF_MAP_UPDATE_ELEM command */ +#define BPF_ANY 0 /* create new element or update existing */ +#define BPF_NOEXIST 1 /* create new element if it didn't exist */ +#define BPF_EXIST 2 /* update existing element */ + +/* flags for BPF_MAP_CREATE command */ +#define BPF_F_NO_PREALLOC (1U << 0) +/* Instead of having one common LRU list in the + * BPF_MAP_TYPE_LRU_[PERCPU_]HASH map, use a percpu LRU list + * which can scale and perform better. + * Note, the LRU nodes (including free nodes) cannot be moved + * across different LRU lists. + */ +#define BPF_F_NO_COMMON_LRU (1U << 1) +/* Specify numa node during map creation */ +#define BPF_F_NUMA_NODE (1U << 2) + +#define BPF_OBJ_NAME_LEN 16U + +/* Flags for accessing BPF object */ +#define BPF_F_RDONLY (1U << 3) +#define BPF_F_WRONLY (1U << 4) + +/* Flag for stack_map, store build_id+offset instead of pointer */ +#define BPF_F_STACK_BUILD_ID (1U << 5) + +/* Zero-initialize hash function seed. This should only be used for testing. */ +#define BPF_F_ZERO_SEED (1U << 6) + +/* flags for BPF_PROG_QUERY */ +#define BPF_F_QUERY_EFFECTIVE (1U << 0) + +enum bpf_stack_build_id_status { + /* user space need an empty entry to identify end of a trace */ + BPF_STACK_BUILD_ID_EMPTY = 0, + /* with valid build_id and offset */ + BPF_STACK_BUILD_ID_VALID = 1, + /* couldn't get build_id, fallback to ip */ + BPF_STACK_BUILD_ID_IP = 2, +}; + +#define BPF_BUILD_ID_SIZE 20 +struct bpf_stack_build_id { + __s32 status; + unsigned char build_id[BPF_BUILD_ID_SIZE]; + union { + __u64 offset; + __u64 ip; + }; +}; + +union bpf_attr { + struct { /* anonymous struct used by BPF_MAP_CREATE command */ + __u32 map_type; /* one of enum bpf_map_type */ + __u32 key_size; /* size of key in bytes */ + __u32 value_size; /* size of value in bytes */ + __u32 max_entries; /* max number of entries in a map */ + __u32 map_flags; /* BPF_MAP_CREATE related + * flags defined above. + */ + __u32 inner_map_fd; /* fd pointing to the inner map */ + __u32 numa_node; /* numa node (effective only if + * BPF_F_NUMA_NODE is set). + */ + char map_name[BPF_OBJ_NAME_LEN]; + __u32 map_ifindex; /* ifindex of netdev to create on */ + __u32 btf_fd; /* fd pointing to a BTF type data */ + __u32 btf_key_type_id; /* BTF type_id of the key */ + __u32 btf_value_type_id; /* BTF type_id of the value */ + }; + + struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ + __u32 map_fd; + __aligned_u64 key; + union { + __aligned_u64 value; + __aligned_u64 next_key; + }; + __u64 flags; + }; + + struct { /* anonymous struct used by BPF_PROG_LOAD command */ + __u32 prog_type; /* one of enum bpf_prog_type */ + __u32 insn_cnt; + __aligned_u64 insns; + __aligned_u64 license; + __u32 log_level; /* verbosity level of verifier */ + __u32 log_size; /* size of user buffer */ + __aligned_u64 log_buf; /* user supplied buffer */ + __u32 kern_version; /* not used */ + __u32 prog_flags; + char prog_name[BPF_OBJ_NAME_LEN]; + __u32 prog_ifindex; /* ifindex of netdev to prep for */ + /* For some prog types expected attach type must be known at + * load time to verify attach type specific parts of prog + * (context accesses, allowed helpers, etc). + */ + __u32 expected_attach_type; + __u32 prog_btf_fd; /* fd pointing to BTF type data */ + __u32 func_info_rec_size; /* userspace bpf_func_info size */ + __aligned_u64 func_info; /* func info */ + __u32 func_info_cnt; /* number of bpf_func_info records */ + __u32 line_info_rec_size; /* userspace bpf_line_info size */ + __aligned_u64 line_info; /* line info */ + __u32 line_info_cnt; /* number of bpf_line_info records */ + }; + + struct { /* anonymous struct used by BPF_OBJ_* commands */ + __aligned_u64 pathname; + __u32 bpf_fd; + __u32 file_flags; + }; + + struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */ + __u32 target_fd; /* container object to attach to */ + __u32 attach_bpf_fd; /* eBPF program to attach */ + __u32 attach_type; + __u32 attach_flags; + }; + + struct { /* anonymous struct used by BPF_PROG_TEST_RUN command */ + __u32 prog_fd; + __u32 retval; + __u32 data_size_in; /* input: len of data_in */ + __u32 data_size_out; /* input/output: len of data_out + * returns ENOSPC if data_out + * is too small. + */ + __aligned_u64 data_in; + __aligned_u64 data_out; + __u32 repeat; + __u32 duration; + } test; + + struct { /* anonymous struct used by BPF_*_GET_*_ID */ + union { + __u32 start_id; + __u32 prog_id; + __u32 map_id; + __u32 btf_id; + }; + __u32 next_id; + __u32 open_flags; + }; + + struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */ + __u32 bpf_fd; + __u32 info_len; + __aligned_u64 info; + } info; + + struct { /* anonymous struct used by BPF_PROG_QUERY command */ + __u32 target_fd; /* container object to query */ + __u32 attach_type; + __u32 query_flags; + __u32 attach_flags; + __aligned_u64 prog_ids; + __u32 prog_cnt; + } query; + + struct { + __u64 name; + __u32 prog_fd; + } raw_tracepoint; + + struct { /* anonymous struct for BPF_BTF_LOAD */ + __aligned_u64 btf; + __aligned_u64 btf_log_buf; + __u32 btf_size; + __u32 btf_log_size; + __u32 btf_log_level; + }; + + struct { + __u32 pid; /* input: pid */ + __u32 fd; /* input: fd */ + __u32 flags; /* input: flags */ + __u32 buf_len; /* input/output: buf len */ + __aligned_u64 buf; /* input/output: + * tp_name for tracepoint + * symbol for kprobe + * filename for uprobe + */ + __u32 prog_id; /* output: prod_id */ + __u32 fd_type; /* output: BPF_FD_TYPE_* */ + __u64 probe_offset; /* output: probe_offset */ + __u64 probe_addr; /* output: probe_addr */ + } task_fd_query; +} __attribute__((aligned(8))); + +/* The description below is an attempt at providing documentation to eBPF + * developers about the multiple available eBPF helper functions. It can be + * parsed and used to produce a manual page. The workflow is the following, + * and requires the rst2man utility: + * + * $ ./scripts/bpf_helpers_doc.py \ + * --filename include/uapi/linux/bpf.h > /tmp/bpf-helpers.rst + * $ rst2man /tmp/bpf-helpers.rst > /tmp/bpf-helpers.7 + * $ man /tmp/bpf-helpers.7 + * + * Note that in order to produce this external documentation, some RST + * formatting is used in the descriptions to get "bold" and "italics" in + * manual pages. Also note that the few trailing white spaces are + * intentional, removing them would break paragraphs for rst2man. + * + * Start of BPF helper function descriptions: + * + * void *bpf_map_lookup_elem(struct bpf_map *map, const void *key) + * Description + * Perform a lookup in *map* for an entry associated to *key*. + * Return + * Map value associated to *key*, or **NULL** if no entry was + * found. + * + * int bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags) + * Description + * Add or update the value of the entry associated to *key* in + * *map* with *value*. *flags* is one of: + * + * **BPF_NOEXIST** + * The entry for *key* must not exist in the map. + * **BPF_EXIST** + * The entry for *key* must already exist in the map. + * **BPF_ANY** + * No condition on the existence of the entry for *key*. + * + * Flag value **BPF_NOEXIST** cannot be used for maps of types + * **BPF_MAP_TYPE_ARRAY** or **BPF_MAP_TYPE_PERCPU_ARRAY** (all + * elements always exist), the helper would return an error. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_map_delete_elem(struct bpf_map *map, const void *key) + * Description + * Delete entry with *key* from *map*. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags) + * Description + * Push an element *value* in *map*. *flags* is one of: + * + * **BPF_EXIST** + * If the queue/stack is full, the oldest element is removed to + * make room for this. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_probe_read(void *dst, u32 size, const void *src) + * Description + * For tracing programs, safely attempt to read *size* bytes from + * address *src* and store the data in *dst*. + * Return + * 0 on success, or a negative error in case of failure. + * + * u64 bpf_ktime_get_ns(void) + * Description + * Return the time elapsed since system boot, in nanoseconds. + * Return + * Current *ktime*. + * + * int bpf_trace_printk(const char *fmt, u32 fmt_size, ...) + * Description + * This helper is a "printk()-like" facility for debugging. It + * prints a message defined by format *fmt* (of size *fmt_size*) + * to file *\/sys/kernel/debug/tracing/trace* from DebugFS, if + * available. It can take up to three additional **u64** + * arguments (as an eBPF helpers, the total number of arguments is + * limited to five). + * + * Each time the helper is called, it appends a line to the trace. + * The format of the trace is customizable, and the exact output + * one will get depends on the options set in + * *\/sys/kernel/debug/tracing/trace_options* (see also the + * *README* file under the same directory). However, it usually + * defaults to something like: + * + * :: + * + * telnet-470 [001] .N.. 419421.045894: 0x00000001: + * + * In the above: + * + * * ``telnet`` is the name of the current task. + * * ``470`` is the PID of the current task. + * * ``001`` is the CPU number on which the task is + * running. + * * In ``.N..``, each character refers to a set of + * options (whether irqs are enabled, scheduling + * options, whether hard/softirqs are running, level of + * preempt_disabled respectively). **N** means that + * **TIF_NEED_RESCHED** and **PREEMPT_NEED_RESCHED** + * are set. + * * ``419421.045894`` is a timestamp. + * * ``0x00000001`` is a fake value used by BPF for the + * instruction pointer register. + * * ```` is the message formatted with + * *fmt*. + * + * The conversion specifiers supported by *fmt* are similar, but + * more limited than for printk(). They are **%d**, **%i**, + * **%u**, **%x**, **%ld**, **%li**, **%lu**, **%lx**, **%lld**, + * **%lli**, **%llu**, **%llx**, **%p**, **%s**. No modifier (size + * of field, padding with zeroes, etc.) is available, and the + * helper will return **-EINVAL** (but print nothing) if it + * encounters an unknown specifier. + * + * Also, note that **bpf_trace_printk**\ () is slow, and should + * only be used for debugging purposes. For this reason, a notice + * bloc (spanning several lines) is printed to kernel logs and + * states that the helper should not be used "for production use" + * the first time this helper is used (or more precisely, when + * **trace_printk**\ () buffers are allocated). For passing values + * to user space, perf events should be preferred. + * Return + * The number of bytes written to the buffer, or a negative error + * in case of failure. + * + * u32 bpf_get_prandom_u32(void) + * Description + * Get a pseudo-random number. + * + * From a security point of view, this helper uses its own + * pseudo-random internal state, and cannot be used to infer the + * seed of other random functions in the kernel. However, it is + * essential to note that the generator used by the helper is not + * cryptographically secure. + * Return + * A random 32-bit unsigned value. + * + * u32 bpf_get_smp_processor_id(void) + * Description + * Get the SMP (symmetric multiprocessing) processor id. Note that + * all programs run with preemption disabled, which means that the + * SMP processor id is stable during all the execution of the + * program. + * Return + * The SMP id of the processor running the program. + * + * int bpf_skb_store_bytes(struct sk_buff *skb, u32 offset, const void *from, u32 len, u64 flags) + * Description + * Store *len* bytes from address *from* into the packet + * associated to *skb*, at *offset*. *flags* are a combination of + * **BPF_F_RECOMPUTE_CSUM** (automatically recompute the + * checksum for the packet after storing the bytes) and + * **BPF_F_INVALIDATE_HASH** (set *skb*\ **->hash**, *skb*\ + * **->swhash** and *skb*\ **->l4hash** to 0). + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_l3_csum_replace(struct sk_buff *skb, u32 offset, u64 from, u64 to, u64 size) + * Description + * Recompute the layer 3 (e.g. IP) checksum for the packet + * associated to *skb*. Computation is incremental, so the helper + * must know the former value of the header field that was + * modified (*from*), the new value of this field (*to*), and the + * number of bytes (2 or 4) for this field, stored in *size*. + * Alternatively, it is possible to store the difference between + * the previous and the new values of the header field in *to*, by + * setting *from* and *size* to 0. For both methods, *offset* + * indicates the location of the IP checksum within the packet. + * + * This helper works in combination with **bpf_csum_diff**\ (), + * which does not update the checksum in-place, but offers more + * flexibility and can handle sizes larger than 2 or 4 for the + * checksum to update. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_l4_csum_replace(struct sk_buff *skb, u32 offset, u64 from, u64 to, u64 flags) + * Description + * Recompute the layer 4 (e.g. TCP, UDP or ICMP) checksum for the + * packet associated to *skb*. Computation is incremental, so the + * helper must know the former value of the header field that was + * modified (*from*), the new value of this field (*to*), and the + * number of bytes (2 or 4) for this field, stored on the lowest + * four bits of *flags*. Alternatively, it is possible to store + * the difference between the previous and the new values of the + * header field in *to*, by setting *from* and the four lowest + * bits of *flags* to 0. For both methods, *offset* indicates the + * location of the IP checksum within the packet. In addition to + * the size of the field, *flags* can be added (bitwise OR) actual + * flags. With **BPF_F_MARK_MANGLED_0**, a null checksum is left + * untouched (unless **BPF_F_MARK_ENFORCE** is added as well), and + * for updates resulting in a null checksum the value is set to + * **CSUM_MANGLED_0** instead. Flag **BPF_F_PSEUDO_HDR** indicates + * the checksum is to be computed against a pseudo-header. + * + * This helper works in combination with **bpf_csum_diff**\ (), + * which does not update the checksum in-place, but offers more + * flexibility and can handle sizes larger than 2 or 4 for the + * checksum to update. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_tail_call(void *ctx, struct bpf_map *prog_array_map, u32 index) + * Description + * This special helper is used to trigger a "tail call", or in + * other words, to jump into another eBPF program. The same stack + * frame is used (but values on stack and in registers for the + * caller are not accessible to the callee). This mechanism allows + * for program chaining, either for raising the maximum number of + * available eBPF instructions, or to execute given programs in + * conditional blocks. For security reasons, there is an upper + * limit to the number of successive tail calls that can be + * performed. + * + * Upon call of this helper, the program attempts to jump into a + * program referenced at index *index* in *prog_array_map*, a + * special map of type **BPF_MAP_TYPE_PROG_ARRAY**, and passes + * *ctx*, a pointer to the context. + * + * If the call succeeds, the kernel immediately runs the first + * instruction of the new program. This is not a function call, + * and it never returns to the previous program. If the call + * fails, then the helper has no effect, and the caller continues + * to run its subsequent instructions. A call can fail if the + * destination program for the jump does not exist (i.e. *index* + * is superior to the number of entries in *prog_array_map*), or + * if the maximum number of tail calls has been reached for this + * chain of programs. This limit is defined in the kernel by the + * macro **MAX_TAIL_CALL_CNT** (not accessible to user space), + * which is currently set to 32. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_clone_redirect(struct sk_buff *skb, u32 ifindex, u64 flags) + * Description + * Clone and redirect the packet associated to *skb* to another + * net device of index *ifindex*. Both ingress and egress + * interfaces can be used for redirection. The **BPF_F_INGRESS** + * value in *flags* is used to make the distinction (ingress path + * is selected if the flag is present, egress path otherwise). + * This is the only flag supported for now. + * + * In comparison with **bpf_redirect**\ () helper, + * **bpf_clone_redirect**\ () has the associated cost of + * duplicating the packet buffer, but this can be executed out of + * the eBPF program. Conversely, **bpf_redirect**\ () is more + * efficient, but it is handled through an action code where the + * redirection happens only after the eBPF program has returned. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * u64 bpf_get_current_pid_tgid(void) + * Return + * A 64-bit integer containing the current tgid and pid, and + * created as such: + * *current_task*\ **->tgid << 32 \|** + * *current_task*\ **->pid**. + * + * u64 bpf_get_current_uid_gid(void) + * Return + * A 64-bit integer containing the current GID and UID, and + * created as such: *current_gid* **<< 32 \|** *current_uid*. + * + * int bpf_get_current_comm(char *buf, u32 size_of_buf) + * Description + * Copy the **comm** attribute of the current task into *buf* of + * *size_of_buf*. The **comm** attribute contains the name of + * the executable (excluding the path) for the current task. The + * *size_of_buf* must be strictly positive. On success, the + * helper makes sure that the *buf* is NUL-terminated. On failure, + * it is filled with zeroes. + * Return + * 0 on success, or a negative error in case of failure. + * + * u32 bpf_get_cgroup_classid(struct sk_buff *skb) + * Description + * Retrieve the classid for the current task, i.e. for the net_cls + * cgroup to which *skb* belongs. + * + * This helper can be used on TC egress path, but not on ingress. + * + * The net_cls cgroup provides an interface to tag network packets + * based on a user-provided identifier for all traffic coming from + * the tasks belonging to the related cgroup. See also the related + * kernel documentation, available from the Linux sources in file + * *Documentation/cgroup-v1/net_cls.txt*. + * + * The Linux kernel has two versions for cgroups: there are + * cgroups v1 and cgroups v2. Both are available to users, who can + * use a mixture of them, but note that the net_cls cgroup is for + * cgroup v1 only. This makes it incompatible with BPF programs + * run on cgroups, which is a cgroup-v2-only feature (a socket can + * only hold data for one version of cgroups at a time). + * + * This helper is only available is the kernel was compiled with + * the **CONFIG_CGROUP_NET_CLASSID** configuration option set to + * "**y**" or to "**m**". + * Return + * The classid, or 0 for the default unconfigured classid. + * + * int bpf_skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci) + * Description + * Push a *vlan_tci* (VLAN tag control information) of protocol + * *vlan_proto* to the packet associated to *skb*, then update + * the checksum. Note that if *vlan_proto* is different from + * **ETH_P_8021Q** and **ETH_P_8021AD**, it is considered to + * be **ETH_P_8021Q**. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_skb_vlan_pop(struct sk_buff *skb) + * Description + * Pop a VLAN header from the packet associated to *skb*. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_skb_get_tunnel_key(struct sk_buff *skb, struct bpf_tunnel_key *key, u32 size, u64 flags) + * Description + * Get tunnel metadata. This helper takes a pointer *key* to an + * empty **struct bpf_tunnel_key** of **size**, that will be + * filled with tunnel metadata for the packet associated to *skb*. + * The *flags* can be set to **BPF_F_TUNINFO_IPV6**, which + * indicates that the tunnel is based on IPv6 protocol instead of + * IPv4. + * + * The **struct bpf_tunnel_key** is an object that generalizes the + * principal parameters used by various tunneling protocols into a + * single struct. This way, it can be used to easily make a + * decision based on the contents of the encapsulation header, + * "summarized" in this struct. In particular, it holds the IP + * address of the remote end (IPv4 or IPv6, depending on the case) + * in *key*\ **->remote_ipv4** or *key*\ **->remote_ipv6**. Also, + * this struct exposes the *key*\ **->tunnel_id**, which is + * generally mapped to a VNI (Virtual Network Identifier), making + * it programmable together with the **bpf_skb_set_tunnel_key**\ + * () helper. + * + * Let's imagine that the following code is part of a program + * attached to the TC ingress interface, on one end of a GRE + * tunnel, and is supposed to filter out all messages coming from + * remote ends with IPv4 address other than 10.0.0.1: + * + * :: + * + * int ret; + * struct bpf_tunnel_key key = {}; + * + * ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); + * if (ret < 0) + * return TC_ACT_SHOT; // drop packet + * + * if (key.remote_ipv4 != 0x0a000001) + * return TC_ACT_SHOT; // drop packet + * + * return TC_ACT_OK; // accept packet + * + * This interface can also be used with all encapsulation devices + * that can operate in "collect metadata" mode: instead of having + * one network device per specific configuration, the "collect + * metadata" mode only requires a single device where the + * configuration can be extracted from this helper. + * + * This can be used together with various tunnels such as VXLan, + * Geneve, GRE or IP in IP (IPIP). + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_skb_set_tunnel_key(struct sk_buff *skb, struct bpf_tunnel_key *key, u32 size, u64 flags) + * Description + * Populate tunnel metadata for packet associated to *skb.* The + * tunnel metadata is set to the contents of *key*, of *size*. The + * *flags* can be set to a combination of the following values: + * + * **BPF_F_TUNINFO_IPV6** + * Indicate that the tunnel is based on IPv6 protocol + * instead of IPv4. + * **BPF_F_ZERO_CSUM_TX** + * For IPv4 packets, add a flag to tunnel metadata + * indicating that checksum computation should be skipped + * and checksum set to zeroes. + * **BPF_F_DONT_FRAGMENT** + * Add a flag to tunnel metadata indicating that the + * packet should not be fragmented. + * **BPF_F_SEQ_NUMBER** + * Add a flag to tunnel metadata indicating that a + * sequence number should be added to tunnel header before + * sending the packet. This flag was added for GRE + * encapsulation, but might be used with other protocols + * as well in the future. + * + * Here is a typical usage on the transmit path: + * + * :: + * + * struct bpf_tunnel_key key; + * populate key ... + * bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 0); + * bpf_clone_redirect(skb, vxlan_dev_ifindex, 0); + * + * See also the description of the **bpf_skb_get_tunnel_key**\ () + * helper for additional information. + * Return + * 0 on success, or a negative error in case of failure. + * + * u64 bpf_perf_event_read(struct bpf_map *map, u64 flags) + * Description + * Read the value of a perf event counter. This helper relies on a + * *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. The nature of + * the perf event counter is selected when *map* is updated with + * perf event file descriptors. The *map* is an array whose size + * is the number of available CPUs, and each cell contains a value + * relative to one CPU. The value to retrieve is indicated by + * *flags*, that contains the index of the CPU to look up, masked + * with **BPF_F_INDEX_MASK**. Alternatively, *flags* can be set to + * **BPF_F_CURRENT_CPU** to indicate that the value for the + * current CPU should be retrieved. + * + * Note that before Linux 4.13, only hardware perf event can be + * retrieved. + * + * Also, be aware that the newer helper + * **bpf_perf_event_read_value**\ () is recommended over + * **bpf_perf_event_read**\ () in general. The latter has some ABI + * quirks where error and counter value are used as a return code + * (which is wrong to do since ranges may overlap). This issue is + * fixed with **bpf_perf_event_read_value**\ (), which at the same + * time provides more features over the **bpf_perf_event_read**\ + * () interface. Please refer to the description of + * **bpf_perf_event_read_value**\ () for details. + * Return + * The value of the perf event counter read from the map, or a + * negative error code in case of failure. + * + * int bpf_redirect(u32 ifindex, u64 flags) + * Description + * Redirect the packet to another net device of index *ifindex*. + * This helper is somewhat similar to **bpf_clone_redirect**\ + * (), except that the packet is not cloned, which provides + * increased performance. + * + * Except for XDP, both ingress and egress interfaces can be used + * for redirection. The **BPF_F_INGRESS** value in *flags* is used + * to make the distinction (ingress path is selected if the flag + * is present, egress path otherwise). Currently, XDP only + * supports redirection to the egress interface, and accepts no + * flag at all. + * + * The same effect can be attained with the more generic + * **bpf_redirect_map**\ (), which requires specific maps to be + * used but offers better performance. + * Return + * For XDP, the helper returns **XDP_REDIRECT** on success or + * **XDP_ABORTED** on error. For other program types, the values + * are **TC_ACT_REDIRECT** on success or **TC_ACT_SHOT** on + * error. + * + * u32 bpf_get_route_realm(struct sk_buff *skb) + * Description + * Retrieve the realm or the route, that is to say the + * **tclassid** field of the destination for the *skb*. The + * identifier retrieved is a user-provided tag, similar to the + * one used with the net_cls cgroup (see description for + * **bpf_get_cgroup_classid**\ () helper), but here this tag is + * held by a route (a destination entry), not by a task. + * + * Retrieving this identifier works with the clsact TC egress hook + * (see also **tc-bpf(8)**), or alternatively on conventional + * classful egress qdiscs, but not on TC ingress path. In case of + * clsact TC egress hook, this has the advantage that, internally, + * the destination entry has not been dropped yet in the transmit + * path. Therefore, the destination entry does not need to be + * artificially held via **netif_keep_dst**\ () for a classful + * qdisc until the *skb* is freed. + * + * This helper is available only if the kernel was compiled with + * **CONFIG_IP_ROUTE_CLASSID** configuration option. + * Return + * The realm of the route for the packet associated to *skb*, or 0 + * if none was found. + * + * int bpf_perf_event_output(struct pt_reg *ctx, struct bpf_map *map, u64 flags, void *data, u64 size) + * Description + * Write raw *data* blob into a special BPF perf event held by + * *map* of type **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. This perf + * event must have the following attributes: **PERF_SAMPLE_RAW** + * as **sample_type**, **PERF_TYPE_SOFTWARE** as **type**, and + * **PERF_COUNT_SW_BPF_OUTPUT** as **config**. + * + * The *flags* are used to indicate the index in *map* for which + * the value must be put, masked with **BPF_F_INDEX_MASK**. + * Alternatively, *flags* can be set to **BPF_F_CURRENT_CPU** + * to indicate that the index of the current CPU core should be + * used. + * + * The value to write, of *size*, is passed through eBPF stack and + * pointed by *data*. + * + * The context of the program *ctx* needs also be passed to the + * helper. + * + * On user space, a program willing to read the values needs to + * call **perf_event_open**\ () on the perf event (either for + * one or for all CPUs) and to store the file descriptor into the + * *map*. This must be done before the eBPF program can send data + * into it. An example is available in file + * *samples/bpf/trace_output_user.c* in the Linux kernel source + * tree (the eBPF program counterpart is in + * *samples/bpf/trace_output_kern.c*). + * + * **bpf_perf_event_output**\ () achieves better performance + * than **bpf_trace_printk**\ () for sharing data with user + * space, and is much better suitable for streaming data from eBPF + * programs. + * + * Note that this helper is not restricted to tracing use cases + * and can be used with programs attached to TC or XDP as well, + * where it allows for passing data to user space listeners. Data + * can be: + * + * * Only custom structs, + * * Only the packet payload, or + * * A combination of both. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_skb_load_bytes(const struct sk_buff *skb, u32 offset, void *to, u32 len) + * Description + * This helper was provided as an easy way to load data from a + * packet. It can be used to load *len* bytes from *offset* from + * the packet associated to *skb*, into the buffer pointed by + * *to*. + * + * Since Linux 4.7, usage of this helper has mostly been replaced + * by "direct packet access", enabling packet data to be + * manipulated with *skb*\ **->data** and *skb*\ **->data_end** + * pointing respectively to the first byte of packet data and to + * the byte after the last byte of packet data. However, it + * remains useful if one wishes to read large quantities of data + * at once from a packet into the eBPF stack. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_get_stackid(struct pt_reg *ctx, struct bpf_map *map, u64 flags) + * Description + * Walk a user or a kernel stack and return its id. To achieve + * this, the helper needs *ctx*, which is a pointer to the context + * on which the tracing program is executed, and a pointer to a + * *map* of type **BPF_MAP_TYPE_STACK_TRACE**. + * + * The last argument, *flags*, holds the number of stack frames to + * skip (from 0 to 255), masked with + * **BPF_F_SKIP_FIELD_MASK**. The next bits can be used to set + * a combination of the following flags: + * + * **BPF_F_USER_STACK** + * Collect a user space stack instead of a kernel stack. + * **BPF_F_FAST_STACK_CMP** + * Compare stacks by hash only. + * **BPF_F_REUSE_STACKID** + * If two different stacks hash into the same *stackid*, + * discard the old one. + * + * The stack id retrieved is a 32 bit long integer handle which + * can be further combined with other data (including other stack + * ids) and used as a key into maps. This can be useful for + * generating a variety of graphs (such as flame graphs or off-cpu + * graphs). + * + * For walking a stack, this helper is an improvement over + * **bpf_probe_read**\ (), which can be used with unrolled loops + * but is not efficient and consumes a lot of eBPF instructions. + * Instead, **bpf_get_stackid**\ () can collect up to + * **PERF_MAX_STACK_DEPTH** both kernel and user frames. Note that + * this limit can be controlled with the **sysctl** program, and + * that it should be manually increased in order to profile long + * user stacks (such as stacks for Java programs). To do so, use: + * + * :: + * + * # sysctl kernel.perf_event_max_stack= + * Return + * The positive or null stack id on success, or a negative error + * in case of failure. + * + * s64 bpf_csum_diff(__be32 *from, u32 from_size, __be32 *to, u32 to_size, __wsum seed) + * Description + * Compute a checksum difference, from the raw buffer pointed by + * *from*, of length *from_size* (that must be a multiple of 4), + * towards the raw buffer pointed by *to*, of size *to_size* + * (same remark). An optional *seed* can be added to the value + * (this can be cascaded, the seed may come from a previous call + * to the helper). + * + * This is flexible enough to be used in several ways: + * + * * With *from_size* == 0, *to_size* > 0 and *seed* set to + * checksum, it can be used when pushing new data. + * * With *from_size* > 0, *to_size* == 0 and *seed* set to + * checksum, it can be used when removing data from a packet. + * * With *from_size* > 0, *to_size* > 0 and *seed* set to 0, it + * can be used to compute a diff. Note that *from_size* and + * *to_size* do not need to be equal. + * + * This helper can be used in combination with + * **bpf_l3_csum_replace**\ () and **bpf_l4_csum_replace**\ (), to + * which one can feed in the difference computed with + * **bpf_csum_diff**\ (). + * Return + * The checksum result, or a negative error code in case of + * failure. + * + * int bpf_skb_get_tunnel_opt(struct sk_buff *skb, u8 *opt, u32 size) + * Description + * Retrieve tunnel options metadata for the packet associated to + * *skb*, and store the raw tunnel option data to the buffer *opt* + * of *size*. + * + * This helper can be used with encapsulation devices that can + * operate in "collect metadata" mode (please refer to the related + * note in the description of **bpf_skb_get_tunnel_key**\ () for + * more details). A particular example where this can be used is + * in combination with the Geneve encapsulation protocol, where it + * allows for pushing (with **bpf_skb_get_tunnel_opt**\ () helper) + * and retrieving arbitrary TLVs (Type-Length-Value headers) from + * the eBPF program. This allows for full customization of these + * headers. + * Return + * The size of the option data retrieved. + * + * int bpf_skb_set_tunnel_opt(struct sk_buff *skb, u8 *opt, u32 size) + * Description + * Set tunnel options metadata for the packet associated to *skb* + * to the option data contained in the raw buffer *opt* of *size*. + * + * See also the description of the **bpf_skb_get_tunnel_opt**\ () + * helper for additional information. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_skb_change_proto(struct sk_buff *skb, __be16 proto, u64 flags) + * Description + * Change the protocol of the *skb* to *proto*. Currently + * supported are transition from IPv4 to IPv6, and from IPv6 to + * IPv4. The helper takes care of the groundwork for the + * transition, including resizing the socket buffer. The eBPF + * program is expected to fill the new headers, if any, via + * **skb_store_bytes**\ () and to recompute the checksums with + * **bpf_l3_csum_replace**\ () and **bpf_l4_csum_replace**\ + * (). The main case for this helper is to perform NAT64 + * operations out of an eBPF program. + * + * Internally, the GSO type is marked as dodgy so that headers are + * checked and segments are recalculated by the GSO/GRO engine. + * The size for GSO target is adapted as well. + * + * All values for *flags* are reserved for future usage, and must + * be left at zero. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_skb_change_type(struct sk_buff *skb, u32 type) + * Description + * Change the packet type for the packet associated to *skb*. This + * comes down to setting *skb*\ **->pkt_type** to *type*, except + * the eBPF program does not have a write access to *skb*\ + * **->pkt_type** beside this helper. Using a helper here allows + * for graceful handling of errors. + * + * The major use case is to change incoming *skb*s to + * **PACKET_HOST** in a programmatic way instead of having to + * recirculate via **redirect**\ (..., **BPF_F_INGRESS**), for + * example. + * + * Note that *type* only allows certain values. At this time, they + * are: + * + * **PACKET_HOST** + * Packet is for us. + * **PACKET_BROADCAST** + * Send packet to all. + * **PACKET_MULTICAST** + * Send packet to group. + * **PACKET_OTHERHOST** + * Send packet to someone else. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_skb_under_cgroup(struct sk_buff *skb, struct bpf_map *map, u32 index) + * Description + * Check whether *skb* is a descendant of the cgroup2 held by + * *map* of type **BPF_MAP_TYPE_CGROUP_ARRAY**, at *index*. + * Return + * The return value depends on the result of the test, and can be: + * + * * 0, if the *skb* failed the cgroup2 descendant test. + * * 1, if the *skb* succeeded the cgroup2 descendant test. + * * A negative error code, if an error occurred. + * + * u32 bpf_get_hash_recalc(struct sk_buff *skb) + * Description + * Retrieve the hash of the packet, *skb*\ **->hash**. If it is + * not set, in particular if the hash was cleared due to mangling, + * recompute this hash. Later accesses to the hash can be done + * directly with *skb*\ **->hash**. + * + * Calling **bpf_set_hash_invalid**\ (), changing a packet + * prototype with **bpf_skb_change_proto**\ (), or calling + * **bpf_skb_store_bytes**\ () with the + * **BPF_F_INVALIDATE_HASH** are actions susceptible to clear + * the hash and to trigger a new computation for the next call to + * **bpf_get_hash_recalc**\ (). + * Return + * The 32-bit hash. + * + * u64 bpf_get_current_task(void) + * Return + * A pointer to the current task struct. + * + * int bpf_probe_write_user(void *dst, const void *src, u32 len) + * Description + * Attempt in a safe way to write *len* bytes from the buffer + * *src* to *dst* in memory. It only works for threads that are in + * user context, and *dst* must be a valid user space address. + * + * This helper should not be used to implement any kind of + * security mechanism because of TOC-TOU attacks, but rather to + * debug, divert, and manipulate execution of semi-cooperative + * processes. + * + * Keep in mind that this feature is meant for experiments, and it + * has a risk of crashing the system and running programs. + * Therefore, when an eBPF program using this helper is attached, + * a warning including PID and process name is printed to kernel + * logs. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_current_task_under_cgroup(struct bpf_map *map, u32 index) + * Description + * Check whether the probe is being run is the context of a given + * subset of the cgroup2 hierarchy. The cgroup2 to test is held by + * *map* of type **BPF_MAP_TYPE_CGROUP_ARRAY**, at *index*. + * Return + * The return value depends on the result of the test, and can be: + * + * * 0, if the *skb* task belongs to the cgroup2. + * * 1, if the *skb* task does not belong to the cgroup2. + * * A negative error code, if an error occurred. + * + * int bpf_skb_change_tail(struct sk_buff *skb, u32 len, u64 flags) + * Description + * Resize (trim or grow) the packet associated to *skb* to the + * new *len*. The *flags* are reserved for future usage, and must + * be left at zero. + * + * The basic idea is that the helper performs the needed work to + * change the size of the packet, then the eBPF program rewrites + * the rest via helpers like **bpf_skb_store_bytes**\ (), + * **bpf_l3_csum_replace**\ (), **bpf_l3_csum_replace**\ () + * and others. This helper is a slow path utility intended for + * replies with control messages. And because it is targeted for + * slow path, the helper itself can afford to be slow: it + * implicitly linearizes, unclones and drops offloads from the + * *skb*. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_skb_pull_data(struct sk_buff *skb, u32 len) + * Description + * Pull in non-linear data in case the *skb* is non-linear and not + * all of *len* are part of the linear section. Make *len* bytes + * from *skb* readable and writable. If a zero value is passed for + * *len*, then the whole length of the *skb* is pulled. + * + * This helper is only needed for reading and writing with direct + * packet access. + * + * For direct packet access, testing that offsets to access + * are within packet boundaries (test on *skb*\ **->data_end**) is + * susceptible to fail if offsets are invalid, or if the requested + * data is in non-linear parts of the *skb*. On failure the + * program can just bail out, or in the case of a non-linear + * buffer, use a helper to make the data available. The + * **bpf_skb_load_bytes**\ () helper is a first solution to access + * the data. Another one consists in using **bpf_skb_pull_data** + * to pull in once the non-linear parts, then retesting and + * eventually access the data. + * + * At the same time, this also makes sure the *skb* is uncloned, + * which is a necessary condition for direct write. As this needs + * to be an invariant for the write part only, the verifier + * detects writes and adds a prologue that is calling + * **bpf_skb_pull_data()** to effectively unclone the *skb* from + * the very beginning in case it is indeed cloned. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * s64 bpf_csum_update(struct sk_buff *skb, __wsum csum) + * Description + * Add the checksum *csum* into *skb*\ **->csum** in case the + * driver has supplied a checksum for the entire packet into that + * field. Return an error otherwise. This helper is intended to be + * used in combination with **bpf_csum_diff**\ (), in particular + * when the checksum needs to be updated after data has been + * written into the packet through direct packet access. + * Return + * The checksum on success, or a negative error code in case of + * failure. + * + * void bpf_set_hash_invalid(struct sk_buff *skb) + * Description + * Invalidate the current *skb*\ **->hash**. It can be used after + * mangling on headers through direct packet access, in order to + * indicate that the hash is outdated and to trigger a + * recalculation the next time the kernel tries to access this + * hash or when the **bpf_get_hash_recalc**\ () helper is called. + * + * int bpf_get_numa_node_id(void) + * Description + * Return the id of the current NUMA node. The primary use case + * for this helper is the selection of sockets for the local NUMA + * node, when the program is attached to sockets using the + * **SO_ATTACH_REUSEPORT_EBPF** option (see also **socket(7)**), + * but the helper is also available to other eBPF program types, + * similarly to **bpf_get_smp_processor_id**\ (). + * Return + * The id of current NUMA node. + * + * int bpf_skb_change_head(struct sk_buff *skb, u32 len, u64 flags) + * Description + * Grows headroom of packet associated to *skb* and adjusts the + * offset of the MAC header accordingly, adding *len* bytes of + * space. It automatically extends and reallocates memory as + * required. + * + * This helper can be used on a layer 3 *skb* to push a MAC header + * for redirection into a layer 2 device. + * + * All values for *flags* are reserved for future usage, and must + * be left at zero. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_xdp_adjust_head(struct xdp_buff *xdp_md, int delta) + * Description + * Adjust (move) *xdp_md*\ **->data** by *delta* bytes. Note that + * it is possible to use a negative value for *delta*. This helper + * can be used to prepare the packet for pushing or popping + * headers. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_probe_read_str(void *dst, int size, const void *unsafe_ptr) + * Description + * Copy a NUL terminated string from an unsafe address + * *unsafe_ptr* to *dst*. The *size* should include the + * terminating NUL byte. In case the string length is smaller than + * *size*, the target is not padded with further NUL bytes. If the + * string length is larger than *size*, just *size*-1 bytes are + * copied and the last byte is set to NUL. + * + * On success, the length of the copied string is returned. This + * makes this helper useful in tracing programs for reading + * strings, and more importantly to get its length at runtime. See + * the following snippet: + * + * :: + * + * SEC("kprobe/sys_open") + * void bpf_sys_open(struct pt_regs *ctx) + * { + * char buf[PATHLEN]; // PATHLEN is defined to 256 + * int res = bpf_probe_read_str(buf, sizeof(buf), + * ctx->di); + * + * // Consume buf, for example push it to + * // userspace via bpf_perf_event_output(); we + * // can use res (the string length) as event + * // size, after checking its boundaries. + * } + * + * In comparison, using **bpf_probe_read()** helper here instead + * to read the string would require to estimate the length at + * compile time, and would often result in copying more memory + * than necessary. + * + * Another useful use case is when parsing individual process + * arguments or individual environment variables navigating + * *current*\ **->mm->arg_start** and *current*\ + * **->mm->env_start**: using this helper and the return value, + * one can quickly iterate at the right offset of the memory area. + * Return + * On success, the strictly positive length of the string, + * including the trailing NUL character. On error, a negative + * value. + * + * u64 bpf_get_socket_cookie(struct sk_buff *skb) + * Description + * If the **struct sk_buff** pointed by *skb* has a known socket, + * retrieve the cookie (generated by the kernel) of this socket. + * If no cookie has been set yet, generate a new cookie. Once + * generated, the socket cookie remains stable for the life of the + * socket. This helper can be useful for monitoring per socket + * networking traffic statistics as it provides a unique socket + * identifier per namespace. + * Return + * A 8-byte long non-decreasing number on success, or 0 if the + * socket field is missing inside *skb*. + * + * u64 bpf_get_socket_cookie(struct bpf_sock_addr *ctx) + * Description + * Equivalent to bpf_get_socket_cookie() helper that accepts + * *skb*, but gets socket from **struct bpf_sock_addr** contex. + * Return + * A 8-byte long non-decreasing number. + * + * u64 bpf_get_socket_cookie(struct bpf_sock_ops *ctx) + * Description + * Equivalent to bpf_get_socket_cookie() helper that accepts + * *skb*, but gets socket from **struct bpf_sock_ops** contex. + * Return + * A 8-byte long non-decreasing number. + * + * u32 bpf_get_socket_uid(struct sk_buff *skb) + * Return + * The owner UID of the socket associated to *skb*. If the socket + * is **NULL**, or if it is not a full socket (i.e. if it is a + * time-wait or a request socket instead), **overflowuid** value + * is returned (note that **overflowuid** might also be the actual + * UID value for the socket). + * + * u32 bpf_set_hash(struct sk_buff *skb, u32 hash) + * Description + * Set the full hash for *skb* (set the field *skb*\ **->hash**) + * to value *hash*. + * Return + * 0 + * + * int bpf_setsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, char *optval, int optlen) + * Description + * Emulate a call to **setsockopt()** on the socket associated to + * *bpf_socket*, which must be a full socket. The *level* at + * which the option resides and the name *optname* of the option + * must be specified, see **setsockopt(2)** for more information. + * The option value of length *optlen* is pointed by *optval*. + * + * This helper actually implements a subset of **setsockopt()**. + * It supports the following *level*\ s: + * + * * **SOL_SOCKET**, which supports the following *optname*\ s: + * **SO_RCVBUF**, **SO_SNDBUF**, **SO_MAX_PACING_RATE**, + * **SO_PRIORITY**, **SO_RCVLOWAT**, **SO_MARK**. + * * **IPPROTO_TCP**, which supports the following *optname*\ s: + * **TCP_CONGESTION**, **TCP_BPF_IW**, + * **TCP_BPF_SNDCWND_CLAMP**. + * * **IPPROTO_IP**, which supports *optname* **IP_TOS**. + * * **IPPROTO_IPV6**, which supports *optname* **IPV6_TCLASS**. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_skb_adjust_room(struct sk_buff *skb, s32 len_diff, u32 mode, u64 flags) + * Description + * Grow or shrink the room for data in the packet associated to + * *skb* by *len_diff*, and according to the selected *mode*. + * + * There is a single supported mode at this time: + * + * * **BPF_ADJ_ROOM_NET**: Adjust room at the network layer + * (room space is added or removed below the layer 3 header). + * + * All values for *flags* are reserved for future usage, and must + * be left at zero. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_redirect_map(struct bpf_map *map, u32 key, u64 flags) + * Description + * Redirect the packet to the endpoint referenced by *map* at + * index *key*. Depending on its type, this *map* can contain + * references to net devices (for forwarding packets through other + * ports), or to CPUs (for redirecting XDP frames to another CPU; + * but this is only implemented for native XDP (with driver + * support) as of this writing). + * + * All values for *flags* are reserved for future usage, and must + * be left at zero. + * + * When used to redirect packets to net devices, this helper + * provides a high performance increase over **bpf_redirect**\ (). + * This is due to various implementation details of the underlying + * mechanisms, one of which is the fact that **bpf_redirect_map**\ + * () tries to send packet as a "bulk" to the device. + * Return + * **XDP_REDIRECT** on success, or **XDP_ABORTED** on error. + * + * int bpf_sk_redirect_map(struct bpf_map *map, u32 key, u64 flags) + * Description + * Redirect the packet to the socket referenced by *map* (of type + * **BPF_MAP_TYPE_SOCKMAP**) at index *key*. Both ingress and + * egress interfaces can be used for redirection. The + * **BPF_F_INGRESS** value in *flags* is used to make the + * distinction (ingress path is selected if the flag is present, + * egress path otherwise). This is the only flag supported for now. + * Return + * **SK_PASS** on success, or **SK_DROP** on error. + * + * int bpf_sock_map_update(struct bpf_sock_ops *skops, struct bpf_map *map, void *key, u64 flags) + * Description + * Add an entry to, or update a *map* referencing sockets. The + * *skops* is used as a new value for the entry associated to + * *key*. *flags* is one of: + * + * **BPF_NOEXIST** + * The entry for *key* must not exist in the map. + * **BPF_EXIST** + * The entry for *key* must already exist in the map. + * **BPF_ANY** + * No condition on the existence of the entry for *key*. + * + * If the *map* has eBPF programs (parser and verdict), those will + * be inherited by the socket being added. If the socket is + * already attached to eBPF programs, this results in an error. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_xdp_adjust_meta(struct xdp_buff *xdp_md, int delta) + * Description + * Adjust the address pointed by *xdp_md*\ **->data_meta** by + * *delta* (which can be positive or negative). Note that this + * operation modifies the address stored in *xdp_md*\ **->data**, + * so the latter must be loaded only after the helper has been + * called. + * + * The use of *xdp_md*\ **->data_meta** is optional and programs + * are not required to use it. The rationale is that when the + * packet is processed with XDP (e.g. as DoS filter), it is + * possible to push further meta data along with it before passing + * to the stack, and to give the guarantee that an ingress eBPF + * program attached as a TC classifier on the same device can pick + * this up for further post-processing. Since TC works with socket + * buffers, it remains possible to set from XDP the **mark** or + * **priority** pointers, or other pointers for the socket buffer. + * Having this scratch space generic and programmable allows for + * more flexibility as the user is free to store whatever meta + * data they need. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_perf_event_read_value(struct bpf_map *map, u64 flags, struct bpf_perf_event_value *buf, u32 buf_size) + * Description + * Read the value of a perf event counter, and store it into *buf* + * of size *buf_size*. This helper relies on a *map* of type + * **BPF_MAP_TYPE_PERF_EVENT_ARRAY**. The nature of the perf event + * counter is selected when *map* is updated with perf event file + * descriptors. The *map* is an array whose size is the number of + * available CPUs, and each cell contains a value relative to one + * CPU. The value to retrieve is indicated by *flags*, that + * contains the index of the CPU to look up, masked with + * **BPF_F_INDEX_MASK**. Alternatively, *flags* can be set to + * **BPF_F_CURRENT_CPU** to indicate that the value for the + * current CPU should be retrieved. + * + * This helper behaves in a way close to + * **bpf_perf_event_read**\ () helper, save that instead of + * just returning the value observed, it fills the *buf* + * structure. This allows for additional data to be retrieved: in + * particular, the enabled and running times (in *buf*\ + * **->enabled** and *buf*\ **->running**, respectively) are + * copied. In general, **bpf_perf_event_read_value**\ () is + * recommended over **bpf_perf_event_read**\ (), which has some + * ABI issues and provides fewer functionalities. + * + * These values are interesting, because hardware PMU (Performance + * Monitoring Unit) counters are limited resources. When there are + * more PMU based perf events opened than available counters, + * kernel will multiplex these events so each event gets certain + * percentage (but not all) of the PMU time. In case that + * multiplexing happens, the number of samples or counter value + * will not reflect the case compared to when no multiplexing + * occurs. This makes comparison between different runs difficult. + * Typically, the counter value should be normalized before + * comparing to other experiments. The usual normalization is done + * as follows. + * + * :: + * + * normalized_counter = counter * t_enabled / t_running + * + * Where t_enabled is the time enabled for event and t_running is + * the time running for event since last normalization. The + * enabled and running times are accumulated since the perf event + * open. To achieve scaling factor between two invocations of an + * eBPF program, users can can use CPU id as the key (which is + * typical for perf array usage model) to remember the previous + * value and do the calculation inside the eBPF program. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_perf_prog_read_value(struct bpf_perf_event_data *ctx, struct bpf_perf_event_value *buf, u32 buf_size) + * Description + * For en eBPF program attached to a perf event, retrieve the + * value of the event counter associated to *ctx* and store it in + * the structure pointed by *buf* and of size *buf_size*. Enabled + * and running times are also stored in the structure (see + * description of helper **bpf_perf_event_read_value**\ () for + * more details). + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_getsockopt(struct bpf_sock_ops *bpf_socket, int level, int optname, char *optval, int optlen) + * Description + * Emulate a call to **getsockopt()** on the socket associated to + * *bpf_socket*, which must be a full socket. The *level* at + * which the option resides and the name *optname* of the option + * must be specified, see **getsockopt(2)** for more information. + * The retrieved value is stored in the structure pointed by + * *opval* and of length *optlen*. + * + * This helper actually implements a subset of **getsockopt()**. + * It supports the following *level*\ s: + * + * * **IPPROTO_TCP**, which supports *optname* + * **TCP_CONGESTION**. + * * **IPPROTO_IP**, which supports *optname* **IP_TOS**. + * * **IPPROTO_IPV6**, which supports *optname* **IPV6_TCLASS**. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_override_return(struct pt_reg *regs, u64 rc) + * Description + * Used for error injection, this helper uses kprobes to override + * the return value of the probed function, and to set it to *rc*. + * The first argument is the context *regs* on which the kprobe + * works. + * + * This helper works by setting setting the PC (program counter) + * to an override function which is run in place of the original + * probed function. This means the probed function is not run at + * all. The replacement function just returns with the required + * value. + * + * This helper has security implications, and thus is subject to + * restrictions. It is only available if the kernel was compiled + * with the **CONFIG_BPF_KPROBE_OVERRIDE** configuration + * option, and in this case it only works on functions tagged with + * **ALLOW_ERROR_INJECTION** in the kernel code. + * + * Also, the helper is only available for the architectures having + * the CONFIG_FUNCTION_ERROR_INJECTION option. As of this writing, + * x86 architecture is the only one to support this feature. + * Return + * 0 + * + * int bpf_sock_ops_cb_flags_set(struct bpf_sock_ops *bpf_sock, int argval) + * Description + * Attempt to set the value of the **bpf_sock_ops_cb_flags** field + * for the full TCP socket associated to *bpf_sock_ops* to + * *argval*. + * + * The primary use of this field is to determine if there should + * be calls to eBPF programs of type + * **BPF_PROG_TYPE_SOCK_OPS** at various points in the TCP + * code. A program of the same type can change its value, per + * connection and as necessary, when the connection is + * established. This field is directly accessible for reading, but + * this helper must be used for updates in order to return an + * error if an eBPF program tries to set a callback that is not + * supported in the current kernel. + * + * The supported callback values that *argval* can combine are: + * + * * **BPF_SOCK_OPS_RTO_CB_FLAG** (retransmission time out) + * * **BPF_SOCK_OPS_RETRANS_CB_FLAG** (retransmission) + * * **BPF_SOCK_OPS_STATE_CB_FLAG** (TCP state change) + * + * Here are some examples of where one could call such eBPF + * program: + * + * * When RTO fires. + * * When a packet is retransmitted. + * * When the connection terminates. + * * When a packet is sent. + * * When a packet is received. + * Return + * Code **-EINVAL** if the socket is not a full TCP socket; + * otherwise, a positive number containing the bits that could not + * be set is returned (which comes down to 0 if all bits were set + * as required). + * + * int bpf_msg_redirect_map(struct sk_msg_buff *msg, struct bpf_map *map, u32 key, u64 flags) + * Description + * This helper is used in programs implementing policies at the + * socket level. If the message *msg* is allowed to pass (i.e. if + * the verdict eBPF program returns **SK_PASS**), redirect it to + * the socket referenced by *map* (of type + * **BPF_MAP_TYPE_SOCKMAP**) at index *key*. Both ingress and + * egress interfaces can be used for redirection. The + * **BPF_F_INGRESS** value in *flags* is used to make the + * distinction (ingress path is selected if the flag is present, + * egress path otherwise). This is the only flag supported for now. + * Return + * **SK_PASS** on success, or **SK_DROP** on error. + * + * int bpf_msg_apply_bytes(struct sk_msg_buff *msg, u32 bytes) + * Description + * For socket policies, apply the verdict of the eBPF program to + * the next *bytes* (number of bytes) of message *msg*. + * + * For example, this helper can be used in the following cases: + * + * * A single **sendmsg**\ () or **sendfile**\ () system call + * contains multiple logical messages that the eBPF program is + * supposed to read and for which it should apply a verdict. + * * An eBPF program only cares to read the first *bytes* of a + * *msg*. If the message has a large payload, then setting up + * and calling the eBPF program repeatedly for all bytes, even + * though the verdict is already known, would create unnecessary + * overhead. + * + * When called from within an eBPF program, the helper sets a + * counter internal to the BPF infrastructure, that is used to + * apply the last verdict to the next *bytes*. If *bytes* is + * smaller than the current data being processed from a + * **sendmsg**\ () or **sendfile**\ () system call, the first + * *bytes* will be sent and the eBPF program will be re-run with + * the pointer for start of data pointing to byte number *bytes* + * **+ 1**. If *bytes* is larger than the current data being + * processed, then the eBPF verdict will be applied to multiple + * **sendmsg**\ () or **sendfile**\ () calls until *bytes* are + * consumed. + * + * Note that if a socket closes with the internal counter holding + * a non-zero value, this is not a problem because data is not + * being buffered for *bytes* and is sent as it is received. + * Return + * 0 + * + * int bpf_msg_cork_bytes(struct sk_msg_buff *msg, u32 bytes) + * Description + * For socket policies, prevent the execution of the verdict eBPF + * program for message *msg* until *bytes* (byte number) have been + * accumulated. + * + * This can be used when one needs a specific number of bytes + * before a verdict can be assigned, even if the data spans + * multiple **sendmsg**\ () or **sendfile**\ () calls. The extreme + * case would be a user calling **sendmsg**\ () repeatedly with + * 1-byte long message segments. Obviously, this is bad for + * performance, but it is still valid. If the eBPF program needs + * *bytes* bytes to validate a header, this helper can be used to + * prevent the eBPF program to be called again until *bytes* have + * been accumulated. + * Return + * 0 + * + * int bpf_msg_pull_data(struct sk_msg_buff *msg, u32 start, u32 end, u64 flags) + * Description + * For socket policies, pull in non-linear data from user space + * for *msg* and set pointers *msg*\ **->data** and *msg*\ + * **->data_end** to *start* and *end* bytes offsets into *msg*, + * respectively. + * + * If a program of type **BPF_PROG_TYPE_SK_MSG** is run on a + * *msg* it can only parse data that the (**data**, **data_end**) + * pointers have already consumed. For **sendmsg**\ () hooks this + * is likely the first scatterlist element. But for calls relying + * on the **sendpage** handler (e.g. **sendfile**\ ()) this will + * be the range (**0**, **0**) because the data is shared with + * user space and by default the objective is to avoid allowing + * user space to modify data while (or after) eBPF verdict is + * being decided. This helper can be used to pull in data and to + * set the start and end pointer to given values. Data will be + * copied if necessary (i.e. if data was not linear and if start + * and end pointers do not point to the same chunk). + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * + * All values for *flags* are reserved for future usage, and must + * be left at zero. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_bind(struct bpf_sock_addr *ctx, struct sockaddr *addr, int addr_len) + * Description + * Bind the socket associated to *ctx* to the address pointed by + * *addr*, of length *addr_len*. This allows for making outgoing + * connection from the desired IP address, which can be useful for + * example when all processes inside a cgroup should use one + * single IP address on a host that has multiple IP configured. + * + * This helper works for IPv4 and IPv6, TCP and UDP sockets. The + * domain (*addr*\ **->sa_family**) must be **AF_INET** (or + * **AF_INET6**). Looking for a free port to bind to can be + * expensive, therefore binding to port is not permitted by the + * helper: *addr*\ **->sin_port** (or **sin6_port**, respectively) + * must be set to zero. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_xdp_adjust_tail(struct xdp_buff *xdp_md, int delta) + * Description + * Adjust (move) *xdp_md*\ **->data_end** by *delta* bytes. It is + * only possible to shrink the packet as of this writing, + * therefore *delta* must be a negative integer. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_skb_get_xfrm_state(struct sk_buff *skb, u32 index, struct bpf_xfrm_state *xfrm_state, u32 size, u64 flags) + * Description + * Retrieve the XFRM state (IP transform framework, see also + * **ip-xfrm(8)**) at *index* in XFRM "security path" for *skb*. + * + * The retrieved value is stored in the **struct bpf_xfrm_state** + * pointed by *xfrm_state* and of length *size*. + * + * All values for *flags* are reserved for future usage, and must + * be left at zero. + * + * This helper is available only if the kernel was compiled with + * **CONFIG_XFRM** configuration option. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_get_stack(struct pt_regs *regs, void *buf, u32 size, u64 flags) + * Description + * Return a user or a kernel stack in bpf program provided buffer. + * To achieve this, the helper needs *ctx*, which is a pointer + * to the context on which the tracing program is executed. + * To store the stacktrace, the bpf program provides *buf* with + * a nonnegative *size*. + * + * The last argument, *flags*, holds the number of stack frames to + * skip (from 0 to 255), masked with + * **BPF_F_SKIP_FIELD_MASK**. The next bits can be used to set + * the following flags: + * + * **BPF_F_USER_STACK** + * Collect a user space stack instead of a kernel stack. + * **BPF_F_USER_BUILD_ID** + * Collect buildid+offset instead of ips for user stack, + * only valid if **BPF_F_USER_STACK** is also specified. + * + * **bpf_get_stack**\ () can collect up to + * **PERF_MAX_STACK_DEPTH** both kernel and user frames, subject + * to sufficient large buffer size. Note that + * this limit can be controlled with the **sysctl** program, and + * that it should be manually increased in order to profile long + * user stacks (such as stacks for Java programs). To do so, use: + * + * :: + * + * # sysctl kernel.perf_event_max_stack= + * Return + * A non-negative value equal to or less than *size* on success, + * or a negative error in case of failure. + * + * int bpf_skb_load_bytes_relative(const struct sk_buff *skb, u32 offset, void *to, u32 len, u32 start_header) + * Description + * This helper is similar to **bpf_skb_load_bytes**\ () in that + * it provides an easy way to load *len* bytes from *offset* + * from the packet associated to *skb*, into the buffer pointed + * by *to*. The difference to **bpf_skb_load_bytes**\ () is that + * a fifth argument *start_header* exists in order to select a + * base offset to start from. *start_header* can be one of: + * + * **BPF_HDR_START_MAC** + * Base offset to load data from is *skb*'s mac header. + * **BPF_HDR_START_NET** + * Base offset to load data from is *skb*'s network header. + * + * In general, "direct packet access" is the preferred method to + * access packet data, however, this helper is in particular useful + * in socket filters where *skb*\ **->data** does not always point + * to the start of the mac header and where "direct packet access" + * is not available. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_fib_lookup(void *ctx, struct bpf_fib_lookup *params, int plen, u32 flags) + * Description + * Do FIB lookup in kernel tables using parameters in *params*. + * If lookup is successful and result shows packet is to be + * forwarded, the neighbor tables are searched for the nexthop. + * If successful (ie., FIB lookup shows forwarding and nexthop + * is resolved), the nexthop address is returned in ipv4_dst + * or ipv6_dst based on family, smac is set to mac address of + * egress device, dmac is set to nexthop mac address, rt_metric + * is set to metric from route (IPv4/IPv6 only), and ifindex + * is set to the device index of the nexthop from the FIB lookup. + * + * *plen* argument is the size of the passed in struct. + * *flags* argument can be a combination of one or more of the + * following values: + * + * **BPF_FIB_LOOKUP_DIRECT** + * Do a direct table lookup vs full lookup using FIB + * rules. + * **BPF_FIB_LOOKUP_OUTPUT** + * Perform lookup from an egress perspective (default is + * ingress). + * + * *ctx* is either **struct xdp_md** for XDP programs or + * **struct sk_buff** tc cls_act programs. + * Return + * * < 0 if any input argument is invalid + * * 0 on success (packet is forwarded, nexthop neighbor exists) + * * > 0 one of **BPF_FIB_LKUP_RET_** codes explaining why the + * packet is not forwarded or needs assist from full stack + * + * int bpf_sock_hash_update(struct bpf_sock_ops_kern *skops, struct bpf_map *map, void *key, u64 flags) + * Description + * Add an entry to, or update a sockhash *map* referencing sockets. + * The *skops* is used as a new value for the entry associated to + * *key*. *flags* is one of: + * + * **BPF_NOEXIST** + * The entry for *key* must not exist in the map. + * **BPF_EXIST** + * The entry for *key* must already exist in the map. + * **BPF_ANY** + * No condition on the existence of the entry for *key*. + * + * If the *map* has eBPF programs (parser and verdict), those will + * be inherited by the socket being added. If the socket is + * already attached to eBPF programs, this results in an error. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_msg_redirect_hash(struct sk_msg_buff *msg, struct bpf_map *map, void *key, u64 flags) + * Description + * This helper is used in programs implementing policies at the + * socket level. If the message *msg* is allowed to pass (i.e. if + * the verdict eBPF program returns **SK_PASS**), redirect it to + * the socket referenced by *map* (of type + * **BPF_MAP_TYPE_SOCKHASH**) using hash *key*. Both ingress and + * egress interfaces can be used for redirection. The + * **BPF_F_INGRESS** value in *flags* is used to make the + * distinction (ingress path is selected if the flag is present, + * egress path otherwise). This is the only flag supported for now. + * Return + * **SK_PASS** on success, or **SK_DROP** on error. + * + * int bpf_sk_redirect_hash(struct sk_buff *skb, struct bpf_map *map, void *key, u64 flags) + * Description + * This helper is used in programs implementing policies at the + * skb socket level. If the sk_buff *skb* is allowed to pass (i.e. + * if the verdeict eBPF program returns **SK_PASS**), redirect it + * to the socket referenced by *map* (of type + * **BPF_MAP_TYPE_SOCKHASH**) using hash *key*. Both ingress and + * egress interfaces can be used for redirection. The + * **BPF_F_INGRESS** value in *flags* is used to make the + * distinction (ingress path is selected if the flag is present, + * egress otherwise). This is the only flag supported for now. + * Return + * **SK_PASS** on success, or **SK_DROP** on error. + * + * int bpf_lwt_push_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len) + * Description + * Encapsulate the packet associated to *skb* within a Layer 3 + * protocol header. This header is provided in the buffer at + * address *hdr*, with *len* its size in bytes. *type* indicates + * the protocol of the header and can be one of: + * + * **BPF_LWT_ENCAP_SEG6** + * IPv6 encapsulation with Segment Routing Header + * (**struct ipv6_sr_hdr**). *hdr* only contains the SRH, + * the IPv6 header is computed by the kernel. + * **BPF_LWT_ENCAP_SEG6_INLINE** + * Only works if *skb* contains an IPv6 packet. Insert a + * Segment Routing Header (**struct ipv6_sr_hdr**) inside + * the IPv6 header. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_lwt_seg6_store_bytes(struct sk_buff *skb, u32 offset, const void *from, u32 len) + * Description + * Store *len* bytes from address *from* into the packet + * associated to *skb*, at *offset*. Only the flags, tag and TLVs + * inside the outermost IPv6 Segment Routing Header can be + * modified through this helper. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_lwt_seg6_adjust_srh(struct sk_buff *skb, u32 offset, s32 delta) + * Description + * Adjust the size allocated to TLVs in the outermost IPv6 + * Segment Routing Header contained in the packet associated to + * *skb*, at position *offset* by *delta* bytes. Only offsets + * after the segments are accepted. *delta* can be as well + * positive (growing) as negative (shrinking). + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_lwt_seg6_action(struct sk_buff *skb, u32 action, void *param, u32 param_len) + * Description + * Apply an IPv6 Segment Routing action of type *action* to the + * packet associated to *skb*. Each action takes a parameter + * contained at address *param*, and of length *param_len* bytes. + * *action* can be one of: + * + * **SEG6_LOCAL_ACTION_END_X** + * End.X action: Endpoint with Layer-3 cross-connect. + * Type of *param*: **struct in6_addr**. + * **SEG6_LOCAL_ACTION_END_T** + * End.T action: Endpoint with specific IPv6 table lookup. + * Type of *param*: **int**. + * **SEG6_LOCAL_ACTION_END_B6** + * End.B6 action: Endpoint bound to an SRv6 policy. + * Type of param: **struct ipv6_sr_hdr**. + * **SEG6_LOCAL_ACTION_END_B6_ENCAP** + * End.B6.Encap action: Endpoint bound to an SRv6 + * encapsulation policy. + * Type of param: **struct ipv6_sr_hdr**. + * + * A call to this helper is susceptible to change the underlaying + * packet buffer. Therefore, at load time, all checks on pointers + * previously done by the verifier are invalidated and must be + * performed again, if the helper is used in combination with + * direct packet access. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_rc_keydown(void *ctx, u32 protocol, u64 scancode, u32 toggle) + * Description + * This helper is used in programs implementing IR decoding, to + * report a successfully decoded key press with *scancode*, + * *toggle* value in the given *protocol*. The scancode will be + * translated to a keycode using the rc keymap, and reported as + * an input key down event. After a period a key up event is + * generated. This period can be extended by calling either + * **bpf_rc_keydown**\ () again with the same values, or calling + * **bpf_rc_repeat**\ (). + * + * Some protocols include a toggle bit, in case the button was + * released and pressed again between consecutive scancodes. + * + * The *ctx* should point to the lirc sample as passed into + * the program. + * + * The *protocol* is the decoded protocol number (see + * **enum rc_proto** for some predefined values). + * + * This helper is only available is the kernel was compiled with + * the **CONFIG_BPF_LIRC_MODE2** configuration option set to + * "**y**". + * Return + * 0 + * + * int bpf_rc_repeat(void *ctx) + * Description + * This helper is used in programs implementing IR decoding, to + * report a successfully decoded repeat key message. This delays + * the generation of a key up event for previously generated + * key down event. + * + * Some IR protocols like NEC have a special IR message for + * repeating last button, for when a button is held down. + * + * The *ctx* should point to the lirc sample as passed into + * the program. + * + * This helper is only available is the kernel was compiled with + * the **CONFIG_BPF_LIRC_MODE2** configuration option set to + * "**y**". + * Return + * 0 + * + * uint64_t bpf_skb_cgroup_id(struct sk_buff *skb) + * Description + * Return the cgroup v2 id of the socket associated with the *skb*. + * This is roughly similar to the **bpf_get_cgroup_classid**\ () + * helper for cgroup v1 by providing a tag resp. identifier that + * can be matched on or used for map lookups e.g. to implement + * policy. The cgroup v2 id of a given path in the hierarchy is + * exposed in user space through the f_handle API in order to get + * to the same 64-bit id. + * + * This helper can be used on TC egress path, but not on ingress, + * and is available only if the kernel was compiled with the + * **CONFIG_SOCK_CGROUP_DATA** configuration option. + * Return + * The id is returned or 0 in case the id could not be retrieved. + * + * u64 bpf_skb_ancestor_cgroup_id(struct sk_buff *skb, int ancestor_level) + * Description + * Return id of cgroup v2 that is ancestor of cgroup associated + * with the *skb* at the *ancestor_level*. The root cgroup is at + * *ancestor_level* zero and each step down the hierarchy + * increments the level. If *ancestor_level* == level of cgroup + * associated with *skb*, then return value will be same as that + * of **bpf_skb_cgroup_id**\ (). + * + * The helper is useful to implement policies based on cgroups + * that are upper in hierarchy than immediate cgroup associated + * with *skb*. + * + * The format of returned id and helper limitations are same as in + * **bpf_skb_cgroup_id**\ (). + * Return + * The id is returned or 0 in case the id could not be retrieved. + * + * u64 bpf_get_current_cgroup_id(void) + * Return + * A 64-bit integer containing the current cgroup id based + * on the cgroup within which the current task is running. + * + * void* get_local_storage(void *map, u64 flags) + * Description + * Get the pointer to the local storage area. + * The type and the size of the local storage is defined + * by the *map* argument. + * The *flags* meaning is specific for each map type, + * and has to be 0 for cgroup local storage. + * + * Depending on the BPF program type, a local storage area + * can be shared between multiple instances of the BPF program, + * running simultaneously. + * + * A user should care about the synchronization by himself. + * For example, by using the **BPF_STX_XADD** instruction to alter + * the shared data. + * Return + * A pointer to the local storage area. + * + * int bpf_sk_select_reuseport(struct sk_reuseport_md *reuse, struct bpf_map *map, void *key, u64 flags) + * Description + * Select a **SO_REUSEPORT** socket from a + * **BPF_MAP_TYPE_REUSEPORT_ARRAY** *map*. + * It checks the selected socket is matching the incoming + * request in the socket buffer. + * Return + * 0 on success, or a negative error in case of failure. + * + * struct bpf_sock *bpf_sk_lookup_tcp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) + * Description + * Look for TCP socket matching *tuple*, optionally in a child + * network namespace *netns*. The return value must be checked, + * and if non-**NULL**, released via **bpf_sk_release**\ (). + * + * The *ctx* should point to the context of the program, such as + * the skb or socket (depending on the hook in use). This is used + * to determine the base network namespace for the lookup. + * + * *tuple_size* must be one of: + * + * **sizeof**\ (*tuple*\ **->ipv4**) + * Look for an IPv4 socket. + * **sizeof**\ (*tuple*\ **->ipv6**) + * Look for an IPv6 socket. + * + * If the *netns* is a negative signed 32-bit integer, then the + * socket lookup table in the netns associated with the *ctx* will + * will be used. For the TC hooks, this is the netns of the device + * in the skb. For socket hooks, this is the netns of the socket. + * If *netns* is any other signed 32-bit value greater than or + * equal to zero then it specifies the ID of the netns relative to + * the netns associated with the *ctx*. *netns* values beyond the + * range of 32-bit integers are reserved for future use. + * + * All values for *flags* are reserved for future usage, and must + * be left at zero. + * + * This helper is available only if the kernel was compiled with + * **CONFIG_NET** configuration option. + * Return + * Pointer to **struct bpf_sock**, or **NULL** in case of failure. + * For sockets with reuseport option, the **struct bpf_sock** + * result is from **reuse->socks**\ [] using the hash of the tuple. + * + * struct bpf_sock *bpf_sk_lookup_udp(void *ctx, struct bpf_sock_tuple *tuple, u32 tuple_size, u64 netns, u64 flags) + * Description + * Look for UDP socket matching *tuple*, optionally in a child + * network namespace *netns*. The return value must be checked, + * and if non-**NULL**, released via **bpf_sk_release**\ (). + * + * The *ctx* should point to the context of the program, such as + * the skb or socket (depending on the hook in use). This is used + * to determine the base network namespace for the lookup. + * + * *tuple_size* must be one of: + * + * **sizeof**\ (*tuple*\ **->ipv4**) + * Look for an IPv4 socket. + * **sizeof**\ (*tuple*\ **->ipv6**) + * Look for an IPv6 socket. + * + * If the *netns* is a negative signed 32-bit integer, then the + * socket lookup table in the netns associated with the *ctx* will + * will be used. For the TC hooks, this is the netns of the device + * in the skb. For socket hooks, this is the netns of the socket. + * If *netns* is any other signed 32-bit value greater than or + * equal to zero then it specifies the ID of the netns relative to + * the netns associated with the *ctx*. *netns* values beyond the + * range of 32-bit integers are reserved for future use. + * + * All values for *flags* are reserved for future usage, and must + * be left at zero. + * + * This helper is available only if the kernel was compiled with + * **CONFIG_NET** configuration option. + * Return + * Pointer to **struct bpf_sock**, or **NULL** in case of failure. + * For sockets with reuseport option, the **struct bpf_sock** + * result is from **reuse->socks**\ [] using the hash of the tuple. + * + * int bpf_sk_release(struct bpf_sock *sock) + * Description + * Release the reference held by *sock*. *sock* must be a + * non-**NULL** pointer that was returned from + * **bpf_sk_lookup_xxx**\ (). + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_map_pop_elem(struct bpf_map *map, void *value) + * Description + * Pop an element from *map*. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_map_peek_elem(struct bpf_map *map, void *value) + * Description + * Get an element from *map* without removing it. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_msg_push_data(struct sk_buff *skb, u32 start, u32 len, u64 flags) + * Description + * For socket policies, insert *len* bytes into *msg* at offset + * *start*. + * + * If a program of type **BPF_PROG_TYPE_SK_MSG** is run on a + * *msg* it may want to insert metadata or options into the *msg*. + * This can later be read and used by any of the lower layer BPF + * hooks. + * + * This helper may fail if under memory pressure (a malloc + * fails) in these cases BPF programs will get an appropriate + * error and BPF programs will need to handle them. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_msg_pop_data(struct sk_msg_buff *msg, u32 start, u32 pop, u64 flags) + * Description + * Will remove *pop* bytes from a *msg* starting at byte *start*. + * This may result in **ENOMEM** errors under certain situations if + * an allocation and copy are required due to a full ring buffer. + * However, the helper will try to avoid doing the allocation + * if possible. Other errors can occur if input parameters are + * invalid either due to *start* byte not being valid part of *msg* + * payload and/or *pop* value being to large. + * Return + * 0 on success, or a negative error in case of failure. + * + * int bpf_rc_pointer_rel(void *ctx, s32 rel_x, s32 rel_y) + * Description + * This helper is used in programs implementing IR decoding, to + * report a successfully decoded pointer movement. + * + * The *ctx* should point to the lirc sample as passed into + * the program. + * + * This helper is only available is the kernel was compiled with + * the **CONFIG_BPF_LIRC_MODE2** configuration option set to + * "**y**". + * Return + * 0 + */ +#define __BPF_FUNC_MAPPER(FN) \ + FN(unspec), \ + FN(map_lookup_elem), \ + FN(map_update_elem), \ + FN(map_delete_elem), \ + FN(probe_read), \ + FN(ktime_get_ns), \ + FN(trace_printk), \ + FN(get_prandom_u32), \ + FN(get_smp_processor_id), \ + FN(skb_store_bytes), \ + FN(l3_csum_replace), \ + FN(l4_csum_replace), \ + FN(tail_call), \ + FN(clone_redirect), \ + FN(get_current_pid_tgid), \ + FN(get_current_uid_gid), \ + FN(get_current_comm), \ + FN(get_cgroup_classid), \ + FN(skb_vlan_push), \ + FN(skb_vlan_pop), \ + FN(skb_get_tunnel_key), \ + FN(skb_set_tunnel_key), \ + FN(perf_event_read), \ + FN(redirect), \ + FN(get_route_realm), \ + FN(perf_event_output), \ + FN(skb_load_bytes), \ + FN(get_stackid), \ + FN(csum_diff), \ + FN(skb_get_tunnel_opt), \ + FN(skb_set_tunnel_opt), \ + FN(skb_change_proto), \ + FN(skb_change_type), \ + FN(skb_under_cgroup), \ + FN(get_hash_recalc), \ + FN(get_current_task), \ + FN(probe_write_user), \ + FN(current_task_under_cgroup), \ + FN(skb_change_tail), \ + FN(skb_pull_data), \ + FN(csum_update), \ + FN(set_hash_invalid), \ + FN(get_numa_node_id), \ + FN(skb_change_head), \ + FN(xdp_adjust_head), \ + FN(probe_read_str), \ + FN(get_socket_cookie), \ + FN(get_socket_uid), \ + FN(set_hash), \ + FN(setsockopt), \ + FN(skb_adjust_room), \ + FN(redirect_map), \ + FN(sk_redirect_map), \ + FN(sock_map_update), \ + FN(xdp_adjust_meta), \ + FN(perf_event_read_value), \ + FN(perf_prog_read_value), \ + FN(getsockopt), \ + FN(override_return), \ + FN(sock_ops_cb_flags_set), \ + FN(msg_redirect_map), \ + FN(msg_apply_bytes), \ + FN(msg_cork_bytes), \ + FN(msg_pull_data), \ + FN(bind), \ + FN(xdp_adjust_tail), \ + FN(skb_get_xfrm_state), \ + FN(get_stack), \ + FN(skb_load_bytes_relative), \ + FN(fib_lookup), \ + FN(sock_hash_update), \ + FN(msg_redirect_hash), \ + FN(sk_redirect_hash), \ + FN(lwt_push_encap), \ + FN(lwt_seg6_store_bytes), \ + FN(lwt_seg6_adjust_srh), \ + FN(lwt_seg6_action), \ + FN(rc_repeat), \ + FN(rc_keydown), \ + FN(skb_cgroup_id), \ + FN(get_current_cgroup_id), \ + FN(get_local_storage), \ + FN(sk_select_reuseport), \ + FN(skb_ancestor_cgroup_id), \ + FN(sk_lookup_tcp), \ + FN(sk_lookup_udp), \ + FN(sk_release), \ + FN(map_push_elem), \ + FN(map_pop_elem), \ + FN(map_peek_elem), \ + FN(msg_push_data), \ + FN(msg_pop_data), \ + FN(rc_pointer_rel), + +/* integer value in 'imm' field of BPF_CALL instruction selects which helper + * function eBPF program intends to call + */ +#define __BPF_ENUM_FN(x) BPF_FUNC_ ## x +enum bpf_func_id { + __BPF_FUNC_MAPPER(__BPF_ENUM_FN) + __BPF_FUNC_MAX_ID, +}; +#undef __BPF_ENUM_FN + +/* All flags used by eBPF helper functions, placed here. */ + +/* BPF_FUNC_skb_store_bytes flags. */ +#define BPF_F_RECOMPUTE_CSUM (1ULL << 0) +#define BPF_F_INVALIDATE_HASH (1ULL << 1) + +/* BPF_FUNC_l3_csum_replace and BPF_FUNC_l4_csum_replace flags. + * First 4 bits are for passing the header field size. + */ +#define BPF_F_HDR_FIELD_MASK 0xfULL + +/* BPF_FUNC_l4_csum_replace flags. */ +#define BPF_F_PSEUDO_HDR (1ULL << 4) +#define BPF_F_MARK_MANGLED_0 (1ULL << 5) +#define BPF_F_MARK_ENFORCE (1ULL << 6) + +/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */ +#define BPF_F_INGRESS (1ULL << 0) + +/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */ +#define BPF_F_TUNINFO_IPV6 (1ULL << 0) + +/* flags for both BPF_FUNC_get_stackid and BPF_FUNC_get_stack. */ +#define BPF_F_SKIP_FIELD_MASK 0xffULL +#define BPF_F_USER_STACK (1ULL << 8) +/* flags used by BPF_FUNC_get_stackid only. */ +#define BPF_F_FAST_STACK_CMP (1ULL << 9) +#define BPF_F_REUSE_STACKID (1ULL << 10) +/* flags used by BPF_FUNC_get_stack only. */ +#define BPF_F_USER_BUILD_ID (1ULL << 11) + +/* BPF_FUNC_skb_set_tunnel_key flags. */ +#define BPF_F_ZERO_CSUM_TX (1ULL << 1) +#define BPF_F_DONT_FRAGMENT (1ULL << 2) +#define BPF_F_SEQ_NUMBER (1ULL << 3) + +/* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and + * BPF_FUNC_perf_event_read_value flags. + */ +#define BPF_F_INDEX_MASK 0xffffffffULL +#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK +/* BPF_FUNC_perf_event_output for sk_buff input context. */ +#define BPF_F_CTXLEN_MASK (0xfffffULL << 32) + +/* Current network namespace */ +#define BPF_F_CURRENT_NETNS (-1L) + +/* Mode for BPF_FUNC_skb_adjust_room helper. */ +enum bpf_adj_room_mode { + BPF_ADJ_ROOM_NET, +}; + +/* Mode for BPF_FUNC_skb_load_bytes_relative helper. */ +enum bpf_hdr_start_off { + BPF_HDR_START_MAC, + BPF_HDR_START_NET, +}; + +/* Encapsulation type for BPF_FUNC_lwt_push_encap helper. */ +enum bpf_lwt_encap_mode { + BPF_LWT_ENCAP_SEG6, + BPF_LWT_ENCAP_SEG6_INLINE +}; + +#define __bpf_md_ptr(type, name) \ +union { \ + type name; \ + __u64 :64; \ +} __attribute__((aligned(8))) + +/* user accessible mirror of in-kernel sk_buff. + * new fields can only be added to the end of this structure + */ +struct __sk_buff { + __u32 len; + __u32 pkt_type; + __u32 mark; + __u32 queue_mapping; + __u32 protocol; + __u32 vlan_present; + __u32 vlan_tci; + __u32 vlan_proto; + __u32 priority; + __u32 ingress_ifindex; + __u32 ifindex; + __u32 tc_index; + __u32 cb[5]; + __u32 hash; + __u32 tc_classid; + __u32 data; + __u32 data_end; + __u32 napi_id; + + /* Accessed by BPF_PROG_TYPE_sk_skb types from here to ... */ + __u32 family; + __u32 remote_ip4; /* Stored in network byte order */ + __u32 local_ip4; /* Stored in network byte order */ + __u32 remote_ip6[4]; /* Stored in network byte order */ + __u32 local_ip6[4]; /* Stored in network byte order */ + __u32 remote_port; /* Stored in network byte order */ + __u32 local_port; /* stored in host byte order */ + /* ... here. */ + + __u32 data_meta; + __bpf_md_ptr(struct bpf_flow_keys *, flow_keys); + __u64 tstamp; + __u32 wire_len; +}; + +struct bpf_tunnel_key { + __u32 tunnel_id; + union { + __u32 remote_ipv4; + __u32 remote_ipv6[4]; + }; + __u8 tunnel_tos; + __u8 tunnel_ttl; + __u16 tunnel_ext; /* Padding, future use. */ + __u32 tunnel_label; +}; + +/* user accessible mirror of in-kernel xfrm_state. + * new fields can only be added to the end of this structure + */ +struct bpf_xfrm_state { + __u32 reqid; + __u32 spi; /* Stored in network byte order */ + __u16 family; + __u16 ext; /* Padding, future use. */ + union { + __u32 remote_ipv4; /* Stored in network byte order */ + __u32 remote_ipv6[4]; /* Stored in network byte order */ + }; +}; + +/* Generic BPF return codes which all BPF program types may support. + * The values are binary compatible with their TC_ACT_* counter-part to + * provide backwards compatibility with existing SCHED_CLS and SCHED_ACT + * programs. + * + * XDP is handled seprately, see XDP_*. + */ +enum bpf_ret_code { + BPF_OK = 0, + /* 1 reserved */ + BPF_DROP = 2, + /* 3-6 reserved */ + BPF_REDIRECT = 7, + /* >127 are reserved for prog type specific return codes */ +}; + +struct bpf_sock { + __u32 bound_dev_if; + __u32 family; + __u32 type; + __u32 protocol; + __u32 mark; + __u32 priority; + __u32 src_ip4; /* Allows 1,2,4-byte read. + * Stored in network byte order. + */ + __u32 src_ip6[4]; /* Allows 1,2,4-byte read. + * Stored in network byte order. + */ + __u32 src_port; /* Allows 4-byte read. + * Stored in host byte order + */ +}; + +struct bpf_sock_tuple { + union { + struct { + __be32 saddr; + __be32 daddr; + __be16 sport; + __be16 dport; + } ipv4; + struct { + __be32 saddr[4]; + __be32 daddr[4]; + __be16 sport; + __be16 dport; + } ipv6; + }; +}; + +#define XDP_PACKET_HEADROOM 256 + +/* User return codes for XDP prog type. + * A valid XDP program must return one of these defined values. All other + * return codes are reserved for future use. Unknown return codes will + * result in packet drops and a warning via bpf_warn_invalid_xdp_action(). + */ +enum xdp_action { + XDP_ABORTED = 0, + XDP_DROP, + XDP_PASS, + XDP_TX, + XDP_REDIRECT, +}; + +/* user accessible metadata for XDP packet hook + * new fields must be added to the end of this structure + */ +struct xdp_md { + __u32 data; + __u32 data_end; + __u32 data_meta; + /* Below access go through struct xdp_rxq_info */ + __u32 ingress_ifindex; /* rxq->dev->ifindex */ + __u32 rx_queue_index; /* rxq->queue_index */ +}; + +enum sk_action { + SK_DROP = 0, + SK_PASS, +}; + +/* user accessible metadata for SK_MSG packet hook, new fields must + * be added to the end of this structure + */ +struct sk_msg_md { + __bpf_md_ptr(void *, data); + __bpf_md_ptr(void *, data_end); + + __u32 family; + __u32 remote_ip4; /* Stored in network byte order */ + __u32 local_ip4; /* Stored in network byte order */ + __u32 remote_ip6[4]; /* Stored in network byte order */ + __u32 local_ip6[4]; /* Stored in network byte order */ + __u32 remote_port; /* Stored in network byte order */ + __u32 local_port; /* stored in host byte order */ + __u32 size; /* Total size of sk_msg */ +}; + +struct sk_reuseport_md { + /* + * Start of directly accessible data. It begins from + * the tcp/udp header. + */ + __bpf_md_ptr(void *, data); + /* End of directly accessible data */ + __bpf_md_ptr(void *, data_end); + /* + * Total length of packet (starting from the tcp/udp header). + * Note that the directly accessible bytes (data_end - data) + * could be less than this "len". Those bytes could be + * indirectly read by a helper "bpf_skb_load_bytes()". + */ + __u32 len; + /* + * Eth protocol in the mac header (network byte order). e.g. + * ETH_P_IP(0x0800) and ETH_P_IPV6(0x86DD) + */ + __u32 eth_protocol; + __u32 ip_protocol; /* IP protocol. e.g. IPPROTO_TCP, IPPROTO_UDP */ + __u32 bind_inany; /* Is sock bound to an INANY address? */ + __u32 hash; /* A hash of the packet 4 tuples */ +}; + +#define BPF_TAG_SIZE 8 + +struct bpf_prog_info { + __u32 type; + __u32 id; + __u8 tag[BPF_TAG_SIZE]; + __u32 jited_prog_len; + __u32 xlated_prog_len; + __aligned_u64 jited_prog_insns; + __aligned_u64 xlated_prog_insns; + __u64 load_time; /* ns since boottime */ + __u32 created_by_uid; + __u32 nr_map_ids; + __aligned_u64 map_ids; + char name[BPF_OBJ_NAME_LEN]; + __u32 ifindex; + __u32 gpl_compatible:1; + __u64 netns_dev; + __u64 netns_ino; + __u32 nr_jited_ksyms; + __u32 nr_jited_func_lens; + __aligned_u64 jited_ksyms; + __aligned_u64 jited_func_lens; + __u32 btf_id; + __u32 func_info_rec_size; + __aligned_u64 func_info; + __u32 nr_func_info; + __u32 nr_line_info; + __aligned_u64 line_info; + __aligned_u64 jited_line_info; + __u32 nr_jited_line_info; + __u32 line_info_rec_size; + __u32 jited_line_info_rec_size; + __u32 nr_prog_tags; + __aligned_u64 prog_tags; +} __attribute__((aligned(8))); + +struct bpf_map_info { + __u32 type; + __u32 id; + __u32 key_size; + __u32 value_size; + __u32 max_entries; + __u32 map_flags; + char name[BPF_OBJ_NAME_LEN]; + __u32 ifindex; + __u32 :32; + __u64 netns_dev; + __u64 netns_ino; + __u32 btf_id; + __u32 btf_key_type_id; + __u32 btf_value_type_id; +} __attribute__((aligned(8))); + +struct bpf_btf_info { + __aligned_u64 btf; + __u32 btf_size; + __u32 id; +} __attribute__((aligned(8))); + +/* User bpf_sock_addr struct to access socket fields and sockaddr struct passed + * by user and intended to be used by socket (e.g. to bind to, depends on + * attach attach type). + */ +struct bpf_sock_addr { + __u32 user_family; /* Allows 4-byte read, but no write. */ + __u32 user_ip4; /* Allows 1,2,4-byte read and 4-byte write. + * Stored in network byte order. + */ + __u32 user_ip6[4]; /* Allows 1,2,4-byte read an 4-byte write. + * Stored in network byte order. + */ + __u32 user_port; /* Allows 4-byte read and write. + * Stored in network byte order + */ + __u32 family; /* Allows 4-byte read, but no write */ + __u32 type; /* Allows 4-byte read, but no write */ + __u32 protocol; /* Allows 4-byte read, but no write */ + __u32 msg_src_ip4; /* Allows 1,2,4-byte read an 4-byte write. + * Stored in network byte order. + */ + __u32 msg_src_ip6[4]; /* Allows 1,2,4-byte read an 4-byte write. + * Stored in network byte order. + */ +}; + +/* User bpf_sock_ops struct to access socket values and specify request ops + * and their replies. + * Some of this fields are in network (bigendian) byte order and may need + * to be converted before use (bpf_ntohl() defined in samples/bpf/bpf_endian.h). + * New fields can only be added at the end of this structure + */ +struct bpf_sock_ops { + __u32 op; + union { + __u32 args[4]; /* Optionally passed to bpf program */ + __u32 reply; /* Returned by bpf program */ + __u32 replylong[4]; /* Optionally returned by bpf prog */ + }; + __u32 family; + __u32 remote_ip4; /* Stored in network byte order */ + __u32 local_ip4; /* Stored in network byte order */ + __u32 remote_ip6[4]; /* Stored in network byte order */ + __u32 local_ip6[4]; /* Stored in network byte order */ + __u32 remote_port; /* Stored in network byte order */ + __u32 local_port; /* stored in host byte order */ + __u32 is_fullsock; /* Some TCP fields are only valid if + * there is a full socket. If not, the + * fields read as zero. + */ + __u32 snd_cwnd; + __u32 srtt_us; /* Averaged RTT << 3 in usecs */ + __u32 bpf_sock_ops_cb_flags; /* flags defined in uapi/linux/tcp.h */ + __u32 state; + __u32 rtt_min; + __u32 snd_ssthresh; + __u32 rcv_nxt; + __u32 snd_nxt; + __u32 snd_una; + __u32 mss_cache; + __u32 ecn_flags; + __u32 rate_delivered; + __u32 rate_interval_us; + __u32 packets_out; + __u32 retrans_out; + __u32 total_retrans; + __u32 segs_in; + __u32 data_segs_in; + __u32 segs_out; + __u32 data_segs_out; + __u32 lost_out; + __u32 sacked_out; + __u32 sk_txhash; + __u64 bytes_received; + __u64 bytes_acked; +}; + +/* Definitions for bpf_sock_ops_cb_flags */ +#define BPF_SOCK_OPS_RTO_CB_FLAG (1<<0) +#define BPF_SOCK_OPS_RETRANS_CB_FLAG (1<<1) +#define BPF_SOCK_OPS_STATE_CB_FLAG (1<<2) +#define BPF_SOCK_OPS_ALL_CB_FLAGS 0x7 /* Mask of all currently + * supported cb flags + */ + +/* List of known BPF sock_ops operators. + * New entries can only be added at the end + */ +enum { + BPF_SOCK_OPS_VOID, + BPF_SOCK_OPS_TIMEOUT_INIT, /* Should return SYN-RTO value to use or + * -1 if default value should be used + */ + BPF_SOCK_OPS_RWND_INIT, /* Should return initial advertized + * window (in packets) or -1 if default + * value should be used + */ + BPF_SOCK_OPS_TCP_CONNECT_CB, /* Calls BPF program right before an + * active connection is initialized + */ + BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB, /* Calls BPF program when an + * active connection is + * established + */ + BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB, /* Calls BPF program when a + * passive connection is + * established + */ + BPF_SOCK_OPS_NEEDS_ECN, /* If connection's congestion control + * needs ECN + */ + BPF_SOCK_OPS_BASE_RTT, /* Get base RTT. The correct value is + * based on the path and may be + * dependent on the congestion control + * algorithm. In general it indicates + * a congestion threshold. RTTs above + * this indicate congestion + */ + BPF_SOCK_OPS_RTO_CB, /* Called when an RTO has triggered. + * Arg1: value of icsk_retransmits + * Arg2: value of icsk_rto + * Arg3: whether RTO has expired + */ + BPF_SOCK_OPS_RETRANS_CB, /* Called when skb is retransmitted. + * Arg1: sequence number of 1st byte + * Arg2: # segments + * Arg3: return value of + * tcp_transmit_skb (0 => success) + */ + BPF_SOCK_OPS_STATE_CB, /* Called when TCP changes state. + * Arg1: old_state + * Arg2: new_state + */ + BPF_SOCK_OPS_TCP_LISTEN_CB, /* Called on listen(2), right after + * socket transition to LISTEN state. + */ +}; + +/* List of TCP states. There is a build check in net/ipv4/tcp.c to detect + * changes between the TCP and BPF versions. Ideally this should never happen. + * If it does, we need to add code to convert them before calling + * the BPF sock_ops function. + */ +enum { + BPF_TCP_ESTABLISHED = 1, + BPF_TCP_SYN_SENT, + BPF_TCP_SYN_RECV, + BPF_TCP_FIN_WAIT1, + BPF_TCP_FIN_WAIT2, + BPF_TCP_TIME_WAIT, + BPF_TCP_CLOSE, + BPF_TCP_CLOSE_WAIT, + BPF_TCP_LAST_ACK, + BPF_TCP_LISTEN, + BPF_TCP_CLOSING, /* Now a valid state */ + BPF_TCP_NEW_SYN_RECV, + + BPF_TCP_MAX_STATES /* Leave at the end! */ +}; + +#define TCP_BPF_IW 1001 /* Set TCP initial congestion window */ +#define TCP_BPF_SNDCWND_CLAMP 1002 /* Set sndcwnd_clamp */ + +struct bpf_perf_event_value { + __u64 counter; + __u64 enabled; + __u64 running; +}; + +#define BPF_DEVCG_ACC_MKNOD (1ULL << 0) +#define BPF_DEVCG_ACC_READ (1ULL << 1) +#define BPF_DEVCG_ACC_WRITE (1ULL << 2) + +#define BPF_DEVCG_DEV_BLOCK (1ULL << 0) +#define BPF_DEVCG_DEV_CHAR (1ULL << 1) + +struct bpf_cgroup_dev_ctx { + /* access_type encoded as (BPF_DEVCG_ACC_* << 16) | BPF_DEVCG_DEV_* */ + __u32 access_type; + __u32 major; + __u32 minor; +}; + +struct bpf_raw_tracepoint_args { + __u64 args[0]; +}; + +/* DIRECT: Skip the FIB rules and go to FIB table associated with device + * OUTPUT: Do lookup from egress perspective; default is ingress + */ +#define BPF_FIB_LOOKUP_DIRECT BIT(0) +#define BPF_FIB_LOOKUP_OUTPUT BIT(1) + +enum { + BPF_FIB_LKUP_RET_SUCCESS, /* lookup successful */ + BPF_FIB_LKUP_RET_BLACKHOLE, /* dest is blackholed; can be dropped */ + BPF_FIB_LKUP_RET_UNREACHABLE, /* dest is unreachable; can be dropped */ + BPF_FIB_LKUP_RET_PROHIBIT, /* dest not allowed; can be dropped */ + BPF_FIB_LKUP_RET_NOT_FWDED, /* packet is not forwarded */ + BPF_FIB_LKUP_RET_FWD_DISABLED, /* fwding is not enabled on ingress */ + BPF_FIB_LKUP_RET_UNSUPP_LWT, /* fwd requires encapsulation */ + BPF_FIB_LKUP_RET_NO_NEIGH, /* no neighbor entry for nh */ + BPF_FIB_LKUP_RET_FRAG_NEEDED, /* fragmentation required to fwd */ +}; + +struct bpf_fib_lookup { + /* input: network family for lookup (AF_INET, AF_INET6) + * output: network family of egress nexthop + */ + __u8 family; + + /* set if lookup is to consider L4 data - e.g., FIB rules */ + __u8 l4_protocol; + __be16 sport; + __be16 dport; + + /* total length of packet from network header - used for MTU check */ + __u16 tot_len; + + /* input: L3 device index for lookup + * output: device index from FIB lookup + */ + __u32 ifindex; + + union { + /* inputs to lookup */ + __u8 tos; /* AF_INET */ + __be32 flowinfo; /* AF_INET6, flow_label + priority */ + + /* output: metric of fib result (IPv4/IPv6 only) */ + __u32 rt_metric; + }; + + union { + __be32 ipv4_src; + __u32 ipv6_src[4]; /* in6_addr; network order */ + }; + + /* input to bpf_fib_lookup, ipv{4,6}_dst is destination address in + * network header. output: bpf_fib_lookup sets to gateway address + * if FIB lookup returns gateway route + */ + union { + __be32 ipv4_dst; + __u32 ipv6_dst[4]; /* in6_addr; network order */ + }; + + /* output */ + __be16 h_vlan_proto; + __be16 h_vlan_TCI; + __u8 smac[6]; /* ETH_ALEN */ + __u8 dmac[6]; /* ETH_ALEN */ +}; + +enum bpf_task_fd_type { + BPF_FD_TYPE_RAW_TRACEPOINT, /* tp name */ + BPF_FD_TYPE_TRACEPOINT, /* tp name */ + BPF_FD_TYPE_KPROBE, /* (symbol + offset) or addr */ + BPF_FD_TYPE_KRETPROBE, /* (symbol + offset) or addr */ + BPF_FD_TYPE_UPROBE, /* filename + offset */ + BPF_FD_TYPE_URETPROBE, /* filename + offset */ +}; + +struct bpf_flow_keys { + __u16 nhoff; + __u16 thoff; + __u16 addr_proto; /* ETH_P_* of valid addrs */ + __u8 is_frag; + __u8 is_first_frag; + __u8 is_encap; + __u8 ip_proto; + __be16 n_proto; + __be16 sport; + __be16 dport; + union { + struct { + __be32 ipv4_src; + __be32 ipv4_dst; + }; + struct { + __u32 ipv6_src[4]; /* in6_addr; network order */ + __u32 ipv6_dst[4]; /* in6_addr; network order */ + }; + }; +}; + +struct bpf_func_info { + __u32 insn_off; + __u32 type_id; +}; + +#define BPF_LINE_INFO_LINE_NUM(line_col) ((line_col) >> 10) +#define BPF_LINE_INFO_LINE_COL(line_col) ((line_col) & 0x3ff) + +struct bpf_line_info { + __u32 insn_off; + __u32 file_name_off; + __u32 line_off; + __u32 line_col; +}; + +#endif /* _UAPI__LINUX_BPF_H__ */ diff --git a/src/shared/linux/bpf_common.h b/src/shared/linux/bpf_common.h new file mode 100644 index 00000000..ee97668b --- /dev/null +++ b/src/shared/linux/bpf_common.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI__LINUX_BPF_COMMON_H__ +#define _UAPI__LINUX_BPF_COMMON_H__ + +/* Instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 /* 32-bit */ +#define BPF_H 0x08 /* 16-bit */ +#define BPF_B 0x10 /* 8-bit */ +/* eBPF BPF_DW 0x18 64-bit */ +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_MOD 0x90 +#define BPF_XOR 0xa0 + +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +#ifndef BPF_MAXINSNS +#define BPF_MAXINSNS 4096 +#endif + +#endif /* _UAPI__LINUX_BPF_COMMON_H__ */ diff --git a/src/shared/linux/bpf_insn.h b/src/shared/linux/bpf_insn.h new file mode 100644 index 00000000..d8d9fb22 --- /dev/null +++ b/src/shared/linux/bpf_insn.h @@ -0,0 +1,225 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* eBPF instruction mini library */ +#ifndef __BPF_INSN_H +#define __BPF_INSN_H + +struct bpf_insn; + +/* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */ + +#define BPF_ALU64_REG(OP, DST, SRC) \ + ((struct bpf_insn) { \ + .code = BPF_ALU64 | BPF_OP(OP) | BPF_X, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = 0, \ + .imm = 0 }) + +#define BPF_ALU32_REG(OP, DST, SRC) \ + ((struct bpf_insn) { \ + .code = BPF_ALU | BPF_OP(OP) | BPF_X, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = 0, \ + .imm = 0 }) + +/* ALU ops on immediates, bpf_add|sub|...: dst_reg += imm32 */ + +#define BPF_ALU64_IMM(OP, DST, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = 0, \ + .imm = IMM }) + +#define BPF_ALU32_IMM(OP, DST, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_ALU | BPF_OP(OP) | BPF_K, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = 0, \ + .imm = IMM }) + +/* Short form of mov, dst_reg = src_reg */ + +#define BPF_MOV64_REG(DST, SRC) \ + ((struct bpf_insn) { \ + .code = BPF_ALU64 | BPF_MOV | BPF_X, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = 0, \ + .imm = 0 }) + +#define BPF_MOV32_REG(DST, SRC) \ + ((struct bpf_insn) { \ + .code = BPF_ALU | BPF_MOV | BPF_X, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = 0, \ + .imm = 0 }) + +/* Short form of mov, dst_reg = imm32 */ + +#define BPF_MOV64_IMM(DST, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_ALU64 | BPF_MOV | BPF_K, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = 0, \ + .imm = IMM }) + +#define BPF_MOV32_IMM(DST, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_ALU | BPF_MOV | BPF_K, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = 0, \ + .imm = IMM }) + +/* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */ +#define BPF_LD_IMM64(DST, IMM) \ + BPF_LD_IMM64_RAW(DST, 0, IMM) + +#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_LD | BPF_DW | BPF_IMM, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = 0, \ + .imm = (__u32) (IMM) }), \ + ((struct bpf_insn) { \ + .code = 0, /* zero is reserved opcode */ \ + .dst_reg = 0, \ + .src_reg = 0, \ + .off = 0, \ + .imm = ((__u64) (IMM)) >> 32 }) + +#ifndef BPF_PSEUDO_MAP_FD +# define BPF_PSEUDO_MAP_FD 1 +#endif + +/* pseudo BPF_LD_IMM64 insn used to refer to process-local map_fd */ +#define BPF_LD_MAP_FD(DST, MAP_FD) \ + BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD) + + +/* Direct packet access, R0 = *(uint *) (skb->data + imm32) */ + +#define BPF_LD_ABS(SIZE, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS, \ + .dst_reg = 0, \ + .src_reg = 0, \ + .off = 0, \ + .imm = IMM }) + +/* Memory load, dst_reg = *(uint *) (src_reg + off16) */ + +#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \ + ((struct bpf_insn) { \ + .code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = OFF, \ + .imm = 0 }) + +/* Memory store, *(uint *) (dst_reg + off16) = src_reg */ + +#define BPF_STX_MEM(SIZE, DST, SRC, OFF) \ + ((struct bpf_insn) { \ + .code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = OFF, \ + .imm = 0 }) + +/* Atomic memory add, *(uint *)(dst_reg + off16) += src_reg */ + +#define BPF_STX_XADD(SIZE, DST, SRC, OFF) \ + ((struct bpf_insn) { \ + .code = BPF_STX | BPF_SIZE(SIZE) | BPF_XADD, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = OFF, \ + .imm = 0 }) + +/* Memory store, *(uint *) (dst_reg + off16) = imm32 */ + +#define BPF_ST_MEM(SIZE, DST, OFF, IMM) \ + ((struct bpf_insn) { \ + .code = BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = OFF, \ + .imm = IMM }) + +/* Conditional jumps against registers, if (dst_reg 'op' src_reg) goto pc + off16 */ + +#define BPF_JMP_REG(OP, DST, SRC, OFF) \ + ((struct bpf_insn) { \ + .code = BPF_JMP | BPF_OP(OP) | BPF_X, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = OFF, \ + .imm = 0 }) + +/* Like BPF_JMP_REG, but with 32-bit wide operands for comparison. */ + +#define BPF_JMP32_REG(OP, DST, SRC, OFF) \ + ((struct bpf_insn) { \ + .code = BPF_JMP32 | BPF_OP(OP) | BPF_X, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = OFF, \ + .imm = 0 }) + +/* Conditional jumps against immediates, if (dst_reg 'op' imm32) goto pc + off16 */ + +#define BPF_JMP_IMM(OP, DST, IMM, OFF) \ + ((struct bpf_insn) { \ + .code = BPF_JMP | BPF_OP(OP) | BPF_K, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = OFF, \ + .imm = IMM }) + +/* Like BPF_JMP_IMM, but with 32-bit wide operands for comparison. */ + +#define BPF_JMP32_IMM(OP, DST, IMM, OFF) \ + ((struct bpf_insn) { \ + .code = BPF_JMP32 | BPF_OP(OP) | BPF_K, \ + .dst_reg = DST, \ + .src_reg = 0, \ + .off = OFF, \ + .imm = IMM }) + +#define BPF_JMP_A(OFF) \ + ((struct bpf_insn) { \ + .code = BPF_JMP | BPF_JA, \ + .dst_reg = 0, \ + .src_reg = 0, \ + .off = OFF, \ + .imm = 0 }) + +/* Raw code statement block */ + +#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \ + ((struct bpf_insn) { \ + .code = CODE, \ + .dst_reg = DST, \ + .src_reg = SRC, \ + .off = OFF, \ + .imm = IMM }) + +/* Program exit */ + +#define BPF_EXIT_INSN() \ + ((struct bpf_insn) { \ + .code = BPF_JMP | BPF_EXIT, \ + .dst_reg = 0, \ + .src_reg = 0, \ + .off = 0, \ + .imm = 0 }) + +#endif diff --git a/src/shared/linux/dm-ioctl.h b/src/shared/linux/dm-ioctl.h new file mode 100644 index 00000000..b3aeec70 --- /dev/null +++ b/src/shared/linux/dm-ioctl.h @@ -0,0 +1,363 @@ +/* SPDX-License-Identifier: LGPL-2.0+ WITH Linux-syscall-note */ +/* + * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited. + * Copyright (C) 2004 - 2009 Red Hat, Inc. All rights reserved. + * + * This file is released under the LGPL. + */ + +#ifndef _LINUX_DM_IOCTL_V4_H +#define _LINUX_DM_IOCTL_V4_H + +#include + +#define DM_DIR "mapper" /* Slashes not supported */ +#define DM_CONTROL_NODE "control" +#define DM_MAX_TYPE_NAME 16 +#define DM_NAME_LEN 128 +#define DM_UUID_LEN 129 + +/* + * A traditional ioctl interface for the device mapper. + * + * Each device can have two tables associated with it, an + * 'active' table which is the one currently used by io passing + * through the device, and an 'inactive' one which is a table + * that is being prepared as a replacement for the 'active' one. + * + * DM_VERSION: + * Just get the version information for the ioctl interface. + * + * DM_REMOVE_ALL: + * Remove all dm devices, destroy all tables. Only really used + * for debug. + * + * DM_LIST_DEVICES: + * Get a list of all the dm device names. + * + * DM_DEV_CREATE: + * Create a new device, neither the 'active' or 'inactive' table + * slots will be filled. The device will be in suspended state + * after creation, however any io to the device will get errored + * since it will be out-of-bounds. + * + * DM_DEV_REMOVE: + * Remove a device, destroy any tables. + * + * DM_DEV_RENAME: + * Rename a device or set its uuid if none was previously supplied. + * + * DM_SUSPEND: + * This performs both suspend and resume, depending which flag is + * passed in. + * Suspend: This command will not return until all pending io to + * the device has completed. Further io will be deferred until + * the device is resumed. + * Resume: It is no longer an error to issue this command on an + * unsuspended device. If a table is present in the 'inactive' + * slot, it will be moved to the active slot, then the old table + * from the active slot will be _destroyed_. Finally the device + * is resumed. + * + * DM_DEV_STATUS: + * Retrieves the status for the table in the 'active' slot. + * + * DM_DEV_WAIT: + * Wait for a significant event to occur to the device. This + * could either be caused by an event triggered by one of the + * targets of the table in the 'active' slot, or a table change. + * + * DM_TABLE_LOAD: + * Load a table into the 'inactive' slot for the device. The + * device does _not_ need to be suspended prior to this command. + * + * DM_TABLE_CLEAR: + * Destroy any table in the 'inactive' slot (ie. abort). + * + * DM_TABLE_DEPS: + * Return a set of device dependencies for the 'active' table. + * + * DM_TABLE_STATUS: + * Return the targets status for the 'active' table. + * + * DM_TARGET_MSG: + * Pass a message string to the target at a specific offset of a device. + * + * DM_DEV_SET_GEOMETRY: + * Set the geometry of a device by passing in a string in this format: + * + * "cylinders heads sectors_per_track start_sector" + * + * Beware that CHS geometry is nearly obsolete and only provided + * for compatibility with dm devices that can be booted by a PC + * BIOS. See struct hd_geometry for range limits. Also note that + * the geometry is erased if the device size changes. + */ + +/* + * All ioctl arguments consist of a single chunk of memory, with + * this structure at the start. If a uuid is specified any + * lookup (eg. for a DM_INFO) will be done on that, *not* the + * name. + */ +struct dm_ioctl { + /* + * The version number is made up of three parts: + * major - no backward or forward compatibility, + * minor - only backwards compatible, + * patch - both backwards and forwards compatible. + * + * All clients of the ioctl interface should fill in the + * version number of the interface that they were + * compiled with. + * + * All recognised ioctl commands (ie. those that don't + * return -ENOTTY) fill out this field, even if the + * command failed. + */ + __u32 version[3]; /* in/out */ + __u32 data_size; /* total size of data passed in + * including this struct */ + + __u32 data_start; /* offset to start of data + * relative to start of this struct */ + + __u32 target_count; /* in/out */ + __s32 open_count; /* out */ + __u32 flags; /* in/out */ + + /* + * event_nr holds either the event number (input and output) or the + * udev cookie value (input only). + * The DM_DEV_WAIT ioctl takes an event number as input. + * The DM_SUSPEND, DM_DEV_REMOVE and DM_DEV_RENAME ioctls + * use the field as a cookie to return in the DM_COOKIE + * variable with the uevents they issue. + * For output, the ioctls return the event number, not the cookie. + */ + __u32 event_nr; /* in/out */ + __u32 padding; + + __u64 dev; /* in/out */ + + char name[DM_NAME_LEN]; /* device name */ + char uuid[DM_UUID_LEN]; /* unique identifier for + * the block device */ + char data[7]; /* padding or data */ +}; + +/* + * Used to specify tables. These structures appear after the + * dm_ioctl. + */ +struct dm_target_spec { + __u64 sector_start; + __u64 length; + __s32 status; /* used when reading from kernel only */ + + /* + * Location of the next dm_target_spec. + * - When specifying targets on a DM_TABLE_LOAD command, this value is + * the number of bytes from the start of the "current" dm_target_spec + * to the start of the "next" dm_target_spec. + * - When retrieving targets on a DM_TABLE_STATUS command, this value + * is the number of bytes from the start of the first dm_target_spec + * (that follows the dm_ioctl struct) to the start of the "next" + * dm_target_spec. + */ + __u32 next; + + char target_type[DM_MAX_TYPE_NAME]; + + /* + * Parameter string starts immediately after this object. + * Be careful to add padding after string to ensure correct + * alignment of subsequent dm_target_spec. + */ +}; + +/* + * Used to retrieve the target dependencies. + */ +struct dm_target_deps { + __u32 count; /* Array size */ + __u32 padding; /* unused */ + __u64 dev[0]; /* out */ +}; + +/* + * Used to get a list of all dm devices. + */ +struct dm_name_list { + __u64 dev; + __u32 next; /* offset to the next record from + the _start_ of this */ + char name[0]; +}; + +/* + * Used to retrieve the target versions + */ +struct dm_target_versions { + __u32 next; + __u32 version[3]; + + char name[0]; +}; + +/* + * Used to pass message to a target + */ +struct dm_target_msg { + __u64 sector; /* Device sector */ + + char message[0]; +}; + +/* + * If you change this make sure you make the corresponding change + * to dm-ioctl.c:lookup_ioctl() + */ +enum { + /* Top level cmds */ + DM_VERSION_CMD = 0, + DM_REMOVE_ALL_CMD, + DM_LIST_DEVICES_CMD, + + /* device level cmds */ + DM_DEV_CREATE_CMD, + DM_DEV_REMOVE_CMD, + DM_DEV_RENAME_CMD, + DM_DEV_SUSPEND_CMD, + DM_DEV_STATUS_CMD, + DM_DEV_WAIT_CMD, + + /* Table level cmds */ + DM_TABLE_LOAD_CMD, + DM_TABLE_CLEAR_CMD, + DM_TABLE_DEPS_CMD, + DM_TABLE_STATUS_CMD, + + /* Added later */ + DM_LIST_VERSIONS_CMD, + DM_TARGET_MSG_CMD, + DM_DEV_SET_GEOMETRY_CMD, + DM_DEV_ARM_POLL_CMD, +}; + +#define DM_IOCTL 0xfd + +#define DM_VERSION _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl) +#define DM_REMOVE_ALL _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl) +#define DM_LIST_DEVICES _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl) + +#define DM_DEV_CREATE _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl) +#define DM_DEV_REMOVE _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl) +#define DM_DEV_RENAME _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl) +#define DM_DEV_SUSPEND _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl) +#define DM_DEV_STATUS _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl) +#define DM_DEV_WAIT _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl) +#define DM_DEV_ARM_POLL _IOWR(DM_IOCTL, DM_DEV_ARM_POLL_CMD, struct dm_ioctl) + +#define DM_TABLE_LOAD _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl) +#define DM_TABLE_CLEAR _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl) +#define DM_TABLE_DEPS _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl) +#define DM_TABLE_STATUS _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl) + +#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl) + +#define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) +#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) + +#define DM_VERSION_MAJOR 4 +#define DM_VERSION_MINOR 27 +#define DM_VERSION_PATCHLEVEL 0 +#define DM_VERSION_EXTRA "-ioctl (2019-01-18)" + +/* Status bits */ +#define DM_READONLY_FLAG (1 << 0) /* In/Out */ +#define DM_SUSPEND_FLAG (1 << 1) /* In/Out */ +#define DM_PERSISTENT_DEV_FLAG (1 << 3) /* In */ + +/* + * Flag passed into ioctl STATUS command to get table information + * rather than current status. + */ +#define DM_STATUS_TABLE_FLAG (1 << 4) /* In */ + +/* + * Flags that indicate whether a table is present in either of + * the two table slots that a device has. + */ +#define DM_ACTIVE_PRESENT_FLAG (1 << 5) /* Out */ +#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */ + +/* + * Indicates that the buffer passed in wasn't big enough for the + * results. + */ +#define DM_BUFFER_FULL_FLAG (1 << 8) /* Out */ + +/* + * This flag is now ignored. + */ +#define DM_SKIP_BDGET_FLAG (1 << 9) /* In */ + +/* + * Set this to avoid attempting to freeze any filesystem when suspending. + */ +#define DM_SKIP_LOCKFS_FLAG (1 << 10) /* In */ + +/* + * Set this to suspend without flushing queued ios. + * Also disables flushing uncommitted changes in the thin target before + * generating statistics for DM_TABLE_STATUS and DM_DEV_WAIT. + */ +#define DM_NOFLUSH_FLAG (1 << 11) /* In */ + +/* + * If set, any table information returned will relate to the inactive + * table instead of the live one. Always check DM_INACTIVE_PRESENT_FLAG + * is set before using the data returned. + */ +#define DM_QUERY_INACTIVE_TABLE_FLAG (1 << 12) /* In */ + +/* + * If set, a uevent was generated for which the caller may need to wait. + */ +#define DM_UEVENT_GENERATED_FLAG (1 << 13) /* Out */ + +/* + * If set, rename changes the uuid not the name. Only permitted + * if no uuid was previously supplied: an existing uuid cannot be changed. + */ +#define DM_UUID_FLAG (1 << 14) /* In */ + +/* + * If set, all buffers are wiped after use. Use when sending + * or requesting sensitive data such as an encryption key. + */ +#define DM_SECURE_DATA_FLAG (1 << 15) /* In */ + +/* + * If set, a message generated output data. + */ +#define DM_DATA_OUT_FLAG (1 << 16) /* Out */ + +/* + * If set with DM_DEV_REMOVE or DM_REMOVE_ALL this indicates that if + * the device cannot be removed immediately because it is still in use + * it should instead be scheduled for removal when it gets closed. + * + * On return from DM_DEV_REMOVE, DM_DEV_STATUS or other ioctls, this + * flag indicates that the device is scheduled to be removed when it + * gets closed. + */ +#define DM_DEFERRED_REMOVE (1 << 17) /* In/Out */ + +/* + * If set, the device is suspended internally. + */ +#define DM_INTERNAL_SUSPEND_FLAG (1 << 18) /* Out */ + +#endif /* _LINUX_DM_IOCTL_H */ diff --git a/src/shared/linux/ethtool.h b/src/shared/linux/ethtool.h new file mode 100644 index 00000000..acf346be --- /dev/null +++ b/src/shared/linux/ethtool.h @@ -0,0 +1,1871 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * ethtool.h: Defines for Linux ethtool. + * + * Copyright (C) 1998 David S. Miller (davem@redhat.com) + * Copyright 2001 Jeff Garzik + * Portions Copyright 2001 Sun Microsystems (thockin@sun.com) + * Portions Copyright 2002 Intel (eli.kupermann@intel.com, + * christopher.leech@intel.com, + * scott.feldman@intel.com) + * Portions Copyright (C) Sun Microsystems 2008 + */ + +#ifndef _UAPI_LINUX_ETHTOOL_H +#define _UAPI_LINUX_ETHTOOL_H + +#include +#include +#include + +#ifndef __KERNEL__ +#include /* for INT_MAX */ +#endif + +#ifndef __KERNEL_DIV_ROUND_UP +#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +#endif + +/* All structures exposed to userland should be defined such that they + * have the same layout for 32-bit and 64-bit userland. + */ + +/** + * struct ethtool_cmd - DEPRECATED, link control and status + * This structure is DEPRECATED, please use struct ethtool_link_settings. + * @cmd: Command number = %ETHTOOL_GSET or %ETHTOOL_SSET + * @supported: Bitmask of %SUPPORTED_* flags for the link modes, + * physical connectors and other link features for which the + * interface supports autonegotiation or auto-detection. + * Read-only. + * @advertising: Bitmask of %ADVERTISED_* flags for the link modes, + * physical connectors and other link features that are + * advertised through autonegotiation or enabled for + * auto-detection. + * @speed: Low bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN + * @duplex: Duplex mode; one of %DUPLEX_* + * @port: Physical connector type; one of %PORT_* + * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not + * applicable. For clause 45 PHYs this is the PRTAD. + * @transceiver: Historically used to distinguish different possible + * PHY types, but not in a consistent way. Deprecated. + * @autoneg: Enable/disable autonegotiation and auto-detection; + * either %AUTONEG_DISABLE or %AUTONEG_ENABLE + * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO + * protocols supported by the interface; 0 if unknown. + * Read-only. + * @maxtxpkt: Historically used to report TX IRQ coalescing; now + * obsoleted by &struct ethtool_coalesce. Read-only; deprecated. + * @maxrxpkt: Historically used to report RX IRQ coalescing; now + * obsoleted by &struct ethtool_coalesce. Read-only; deprecated. + * @speed_hi: High bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN + * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of + * %ETH_TP_MDI_*. If the status is unknown or not applicable, the + * value will be %ETH_TP_MDI_INVALID. Read-only. + * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of + * %ETH_TP_MDI_*. If MDI(-X) control is not implemented, reads + * yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected. + * When written successfully, the link should be renegotiated if + * necessary. + * @lp_advertising: Bitmask of %ADVERTISED_* flags for the link modes + * and other link features that the link partner advertised + * through autonegotiation; 0 if unknown or not applicable. + * Read-only. + * + * The link speed in Mbps is split between @speed and @speed_hi. Use + * the ethtool_cmd_speed() and ethtool_cmd_speed_set() functions to + * access it. + * + * If autonegotiation is disabled, the speed and @duplex represent the + * fixed link mode and are writable if the driver supports multiple + * link modes. If it is enabled then they are read-only; if the link + * is up they represent the negotiated link mode; if the link is down, + * the speed is 0, %SPEED_UNKNOWN or the highest enabled speed and + * @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode. + * + * Some hardware interfaces may have multiple PHYs and/or physical + * connectors fitted or do not allow the driver to detect which are + * fitted. For these interfaces @port and/or @phy_address may be + * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE. + * Otherwise, attempts to write different values may be ignored or + * rejected. + * + * Users should assume that all fields not marked read-only are + * writable and subject to validation by the driver. They should use + * %ETHTOOL_GSET to get the current values before making specific + * changes and then applying them with %ETHTOOL_SSET. + * + * Deprecated fields should be ignored by both users and drivers. + */ +struct ethtool_cmd { + __u32 cmd; + __u32 supported; + __u32 advertising; + __u16 speed; + __u8 duplex; + __u8 port; + __u8 phy_address; + __u8 transceiver; + __u8 autoneg; + __u8 mdio_support; + __u32 maxtxpkt; + __u32 maxrxpkt; + __u16 speed_hi; + __u8 eth_tp_mdix; + __u8 eth_tp_mdix_ctrl; + __u32 lp_advertising; + __u32 reserved[2]; +}; + +static inline void ethtool_cmd_speed_set(struct ethtool_cmd *ep, + __u32 speed) +{ + ep->speed = (__u16)(speed & 0xFFFF); + ep->speed_hi = (__u16)(speed >> 16); +} + +static inline __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep) +{ + return ((__u32) ep->speed_hi << 16) | (__u32) ep->speed; +} + +/* Device supports clause 22 register access to PHY or peripherals + * using the interface defined in . This should not be + * set if there are known to be no such peripherals present or if + * the driver only emulates clause 22 registers for compatibility. + */ +#define ETH_MDIO_SUPPORTS_C22 1 + +/* Device supports clause 45 register access to PHY or peripherals + * using the interface defined in and . + * This should not be set if there are known to be no such peripherals + * present. + */ +#define ETH_MDIO_SUPPORTS_C45 2 + +#define ETHTOOL_FWVERS_LEN 32 +#define ETHTOOL_BUSINFO_LEN 32 +#define ETHTOOL_EROMVERS_LEN 32 + +/** + * struct ethtool_drvinfo - general driver and device information + * @cmd: Command number = %ETHTOOL_GDRVINFO + * @driver: Driver short name. This should normally match the name + * in its bus driver structure (e.g. pci_driver::name). Must + * not be an empty string. + * @version: Driver version string; may be an empty string + * @fw_version: Firmware version string; may be an empty string + * @erom_version: Expansion ROM version string; may be an empty string + * @bus_info: Device bus address. This should match the dev_name() + * string for the underlying bus device, if there is one. May be + * an empty string. + * @n_priv_flags: Number of flags valid for %ETHTOOL_GPFLAGS and + * %ETHTOOL_SPFLAGS commands; also the number of strings in the + * %ETH_SS_PRIV_FLAGS set + * @n_stats: Number of u64 statistics returned by the %ETHTOOL_GSTATS + * command; also the number of strings in the %ETH_SS_STATS set + * @testinfo_len: Number of results returned by the %ETHTOOL_TEST + * command; also the number of strings in the %ETH_SS_TEST set + * @eedump_len: Size of EEPROM accessible through the %ETHTOOL_GEEPROM + * and %ETHTOOL_SEEPROM commands, in bytes + * @regdump_len: Size of register dump returned by the %ETHTOOL_GREGS + * command, in bytes + * + * Users can use the %ETHTOOL_GSSET_INFO command to get the number of + * strings in any string set (from Linux 2.6.34). + * + * Drivers should set at most @driver, @version, @fw_version and + * @bus_info in their get_drvinfo() implementation. The ethtool + * core fills in the other fields using other driver operations. + */ +struct ethtool_drvinfo { + __u32 cmd; + char driver[32]; + char version[32]; + char fw_version[ETHTOOL_FWVERS_LEN]; + char bus_info[ETHTOOL_BUSINFO_LEN]; + char erom_version[ETHTOOL_EROMVERS_LEN]; + char reserved2[12]; + __u32 n_priv_flags; + __u32 n_stats; + __u32 testinfo_len; + __u32 eedump_len; + __u32 regdump_len; +}; + +#define SOPASS_MAX 6 + +/** + * struct ethtool_wolinfo - Wake-On-Lan configuration + * @cmd: Command number = %ETHTOOL_GWOL or %ETHTOOL_SWOL + * @supported: Bitmask of %WAKE_* flags for supported Wake-On-Lan modes. + * Read-only. + * @wolopts: Bitmask of %WAKE_* flags for enabled Wake-On-Lan modes. + * @sopass: SecureOn(tm) password; meaningful only if %WAKE_MAGICSECURE + * is set in @wolopts. + */ +struct ethtool_wolinfo { + __u32 cmd; + __u32 supported; + __u32 wolopts; + __u8 sopass[SOPASS_MAX]; +}; + +/* for passing single values */ +struct ethtool_value { + __u32 cmd; + __u32 data; +}; + +#define PFC_STORM_PREVENTION_AUTO 0xffff +#define PFC_STORM_PREVENTION_DISABLE 0 + +enum tunable_id { + ETHTOOL_ID_UNSPEC, + ETHTOOL_RX_COPYBREAK, + ETHTOOL_TX_COPYBREAK, + ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */ + /* + * Add your fresh new tunable attribute above and remember to update + * tunable_strings[] in net/core/ethtool.c + */ + __ETHTOOL_TUNABLE_COUNT, +}; + +enum tunable_type_id { + ETHTOOL_TUNABLE_UNSPEC, + ETHTOOL_TUNABLE_U8, + ETHTOOL_TUNABLE_U16, + ETHTOOL_TUNABLE_U32, + ETHTOOL_TUNABLE_U64, + ETHTOOL_TUNABLE_STRING, + ETHTOOL_TUNABLE_S8, + ETHTOOL_TUNABLE_S16, + ETHTOOL_TUNABLE_S32, + ETHTOOL_TUNABLE_S64, +}; + +struct ethtool_tunable { + __u32 cmd; + __u32 id; + __u32 type_id; + __u32 len; + void *data[0]; +}; + +#define DOWNSHIFT_DEV_DEFAULT_COUNT 0xff +#define DOWNSHIFT_DEV_DISABLE 0 + +/* Time in msecs after which link is reported as down + * 0 = lowest time supported by the PHY + * 0xff = off, link down detection according to standard + */ +#define ETHTOOL_PHY_FAST_LINK_DOWN_ON 0 +#define ETHTOOL_PHY_FAST_LINK_DOWN_OFF 0xff + +enum phy_tunable_id { + ETHTOOL_PHY_ID_UNSPEC, + ETHTOOL_PHY_DOWNSHIFT, + ETHTOOL_PHY_FAST_LINK_DOWN, + /* + * Add your fresh new phy tunable attribute above and remember to update + * phy_tunable_strings[] in net/core/ethtool.c + */ + __ETHTOOL_PHY_TUNABLE_COUNT, +}; + +/** + * struct ethtool_regs - hardware register dump + * @cmd: Command number = %ETHTOOL_GREGS + * @version: Dump format version. This is driver-specific and may + * distinguish different chips/revisions. Drivers must use new + * version numbers whenever the dump format changes in an + * incompatible way. + * @len: On entry, the real length of @data. On return, the number of + * bytes used. + * @data: Buffer for the register dump + * + * Users should use %ETHTOOL_GDRVINFO to find the maximum length of + * a register dump for the interface. They must allocate the buffer + * immediately following this structure. + */ +struct ethtool_regs { + __u32 cmd; + __u32 version; + __u32 len; + __u8 data[0]; +}; + +/** + * struct ethtool_eeprom - EEPROM dump + * @cmd: Command number = %ETHTOOL_GEEPROM, %ETHTOOL_GMODULEEEPROM or + * %ETHTOOL_SEEPROM + * @magic: A 'magic cookie' value to guard against accidental changes. + * The value passed in to %ETHTOOL_SEEPROM must match the value + * returned by %ETHTOOL_GEEPROM for the same device. This is + * unused when @cmd is %ETHTOOL_GMODULEEEPROM. + * @offset: Offset within the EEPROM to begin reading/writing, in bytes + * @len: On entry, number of bytes to read/write. On successful + * return, number of bytes actually read/written. In case of + * error, this may indicate at what point the error occurred. + * @data: Buffer to read/write from + * + * Users may use %ETHTOOL_GDRVINFO or %ETHTOOL_GMODULEINFO to find + * the length of an on-board or module EEPROM, respectively. They + * must allocate the buffer immediately following this structure. + */ +struct ethtool_eeprom { + __u32 cmd; + __u32 magic; + __u32 offset; + __u32 len; + __u8 data[0]; +}; + +/** + * struct ethtool_eee - Energy Efficient Ethernet information + * @cmd: ETHTOOL_{G,S}EEE + * @supported: Mask of %SUPPORTED_* flags for the speed/duplex combinations + * for which there is EEE support. + * @advertised: Mask of %ADVERTISED_* flags for the speed/duplex combinations + * advertised as eee capable. + * @lp_advertised: Mask of %ADVERTISED_* flags for the speed/duplex + * combinations advertised by the link partner as eee capable. + * @eee_active: Result of the eee auto negotiation. + * @eee_enabled: EEE configured mode (enabled/disabled). + * @tx_lpi_enabled: Whether the interface should assert its tx lpi, given + * that eee was negotiated. + * @tx_lpi_timer: Time in microseconds the interface delays prior to asserting + * its tx lpi (after reaching 'idle' state). Effective only when eee + * was negotiated and tx_lpi_enabled was set. + */ +struct ethtool_eee { + __u32 cmd; + __u32 supported; + __u32 advertised; + __u32 lp_advertised; + __u32 eee_active; + __u32 eee_enabled; + __u32 tx_lpi_enabled; + __u32 tx_lpi_timer; + __u32 reserved[2]; +}; + +/** + * struct ethtool_modinfo - plugin module eeprom information + * @cmd: %ETHTOOL_GMODULEINFO + * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx + * @eeprom_len: Length of the eeprom + * + * This structure is used to return the information to + * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM. + * The type code indicates the eeprom data format + */ +struct ethtool_modinfo { + __u32 cmd; + __u32 type; + __u32 eeprom_len; + __u32 reserved[8]; +}; + +/** + * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates + * @cmd: ETHTOOL_{G,S}COALESCE + * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after + * a packet arrives. + * @rx_max_coalesced_frames: Maximum number of packets to receive + * before an RX interrupt. + * @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that + * this value applies while an IRQ is being serviced by the host. + * @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames, + * except that this value applies while an IRQ is being serviced + * by the host. + * @tx_coalesce_usecs: How many usecs to delay a TX interrupt after + * a packet is sent. + * @tx_max_coalesced_frames: Maximum number of packets to be sent + * before a TX interrupt. + * @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that + * this value applies while an IRQ is being serviced by the host. + * @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames, + * except that this value applies while an IRQ is being serviced + * by the host. + * @stats_block_coalesce_usecs: How many usecs to delay in-memory + * statistics block updates. Some drivers do not have an + * in-memory statistic block, and in such cases this value is + * ignored. This value must not be zero. + * @use_adaptive_rx_coalesce: Enable adaptive RX coalescing. + * @use_adaptive_tx_coalesce: Enable adaptive TX coalescing. + * @pkt_rate_low: Threshold for low packet rate (packets per second). + * @rx_coalesce_usecs_low: How many usecs to delay an RX interrupt after + * a packet arrives, when the packet rate is below @pkt_rate_low. + * @rx_max_coalesced_frames_low: Maximum number of packets to be received + * before an RX interrupt, when the packet rate is below @pkt_rate_low. + * @tx_coalesce_usecs_low: How many usecs to delay a TX interrupt after + * a packet is sent, when the packet rate is below @pkt_rate_low. + * @tx_max_coalesced_frames_low: Maximum nuumber of packets to be sent before + * a TX interrupt, when the packet rate is below @pkt_rate_low. + * @pkt_rate_high: Threshold for high packet rate (packets per second). + * @rx_coalesce_usecs_high: How many usecs to delay an RX interrupt after + * a packet arrives, when the packet rate is above @pkt_rate_high. + * @rx_max_coalesced_frames_high: Maximum number of packets to be received + * before an RX interrupt, when the packet rate is above @pkt_rate_high. + * @tx_coalesce_usecs_high: How many usecs to delay a TX interrupt after + * a packet is sent, when the packet rate is above @pkt_rate_high. + * @tx_max_coalesced_frames_high: Maximum number of packets to be sent before + * a TX interrupt, when the packet rate is above @pkt_rate_high. + * @rate_sample_interval: How often to do adaptive coalescing packet rate + * sampling, measured in seconds. Must not be zero. + * + * Each pair of (usecs, max_frames) fields specifies that interrupts + * should be coalesced until + * (usecs > 0 && time_since_first_completion >= usecs) || + * (max_frames > 0 && completed_frames >= max_frames) + * + * It is illegal to set both usecs and max_frames to zero as this + * would cause interrupts to never be generated. To disable + * coalescing, set usecs = 0 and max_frames = 1. + * + * Some implementations ignore the value of max_frames and use the + * condition time_since_first_completion >= usecs + * + * This is deprecated. Drivers for hardware that does not support + * counting completions should validate that max_frames == !rx_usecs. + * + * Adaptive RX/TX coalescing is an algorithm implemented by some + * drivers to improve latency under low packet rates and improve + * throughput under high packet rates. Some drivers only implement + * one of RX or TX adaptive coalescing. Anything not implemented by + * the driver causes these values to be silently ignored. + * + * When the packet rate is below @pkt_rate_high but above + * @pkt_rate_low (both measured in packets per second) the + * normal {rx,tx}_* coalescing parameters are used. + */ +struct ethtool_coalesce { + __u32 cmd; + __u32 rx_coalesce_usecs; + __u32 rx_max_coalesced_frames; + __u32 rx_coalesce_usecs_irq; + __u32 rx_max_coalesced_frames_irq; + __u32 tx_coalesce_usecs; + __u32 tx_max_coalesced_frames; + __u32 tx_coalesce_usecs_irq; + __u32 tx_max_coalesced_frames_irq; + __u32 stats_block_coalesce_usecs; + __u32 use_adaptive_rx_coalesce; + __u32 use_adaptive_tx_coalesce; + __u32 pkt_rate_low; + __u32 rx_coalesce_usecs_low; + __u32 rx_max_coalesced_frames_low; + __u32 tx_coalesce_usecs_low; + __u32 tx_max_coalesced_frames_low; + __u32 pkt_rate_high; + __u32 rx_coalesce_usecs_high; + __u32 rx_max_coalesced_frames_high; + __u32 tx_coalesce_usecs_high; + __u32 tx_max_coalesced_frames_high; + __u32 rate_sample_interval; +}; + +/** + * struct ethtool_ringparam - RX/TX ring parameters + * @cmd: Command number = %ETHTOOL_GRINGPARAM or %ETHTOOL_SRINGPARAM + * @rx_max_pending: Maximum supported number of pending entries per + * RX ring. Read-only. + * @rx_mini_max_pending: Maximum supported number of pending entries + * per RX mini ring. Read-only. + * @rx_jumbo_max_pending: Maximum supported number of pending entries + * per RX jumbo ring. Read-only. + * @tx_max_pending: Maximum supported number of pending entries per + * TX ring. Read-only. + * @rx_pending: Current maximum number of pending entries per RX ring + * @rx_mini_pending: Current maximum number of pending entries per RX + * mini ring + * @rx_jumbo_pending: Current maximum number of pending entries per RX + * jumbo ring + * @tx_pending: Current maximum supported number of pending entries + * per TX ring + * + * If the interface does not have separate RX mini and/or jumbo rings, + * @rx_mini_max_pending and/or @rx_jumbo_max_pending will be 0. + * + * There may also be driver-dependent minimum values for the number + * of entries per ring. + */ +struct ethtool_ringparam { + __u32 cmd; + __u32 rx_max_pending; + __u32 rx_mini_max_pending; + __u32 rx_jumbo_max_pending; + __u32 tx_max_pending; + __u32 rx_pending; + __u32 rx_mini_pending; + __u32 rx_jumbo_pending; + __u32 tx_pending; +}; + +/** + * struct ethtool_channels - configuring number of network channel + * @cmd: ETHTOOL_{G,S}CHANNELS + * @max_rx: Read only. Maximum number of receive channel the driver support. + * @max_tx: Read only. Maximum number of transmit channel the driver support. + * @max_other: Read only. Maximum number of other channel the driver support. + * @max_combined: Read only. Maximum number of combined channel the driver + * support. Set of queues RX, TX or other. + * @rx_count: Valid values are in the range 1 to the max_rx. + * @tx_count: Valid values are in the range 1 to the max_tx. + * @other_count: Valid values are in the range 1 to the max_other. + * @combined_count: Valid values are in the range 1 to the max_combined. + * + * This can be used to configure RX, TX and other channels. + */ + +struct ethtool_channels { + __u32 cmd; + __u32 max_rx; + __u32 max_tx; + __u32 max_other; + __u32 max_combined; + __u32 rx_count; + __u32 tx_count; + __u32 other_count; + __u32 combined_count; +}; + +/** + * struct ethtool_pauseparam - Ethernet pause (flow control) parameters + * @cmd: Command number = %ETHTOOL_GPAUSEPARAM or %ETHTOOL_SPAUSEPARAM + * @autoneg: Flag to enable autonegotiation of pause frame use + * @rx_pause: Flag to enable reception of pause frames + * @tx_pause: Flag to enable transmission of pause frames + * + * Drivers should reject a non-zero setting of @autoneg when + * autoneogotiation is disabled (or not supported) for the link. + * + * If the link is autonegotiated, drivers should use + * mii_advertise_flowctrl() or similar code to set the advertised + * pause frame capabilities based on the @rx_pause and @tx_pause flags, + * even if @autoneg is zero. They should also allow the advertised + * pause frame capabilities to be controlled directly through the + * advertising field of &struct ethtool_cmd. + * + * If @autoneg is non-zero, the MAC is configured to send and/or + * receive pause frames according to the result of autonegotiation. + * Otherwise, it is configured directly based on the @rx_pause and + * @tx_pause flags. + */ +struct ethtool_pauseparam { + __u32 cmd; + __u32 autoneg; + __u32 rx_pause; + __u32 tx_pause; +}; + +#define ETH_GSTRING_LEN 32 + +/** + * enum ethtool_stringset - string set ID + * @ETH_SS_TEST: Self-test result names, for use with %ETHTOOL_TEST + * @ETH_SS_STATS: Statistic names, for use with %ETHTOOL_GSTATS + * @ETH_SS_PRIV_FLAGS: Driver private flag names, for use with + * %ETHTOOL_GPFLAGS and %ETHTOOL_SPFLAGS + * @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE; + * now deprecated + * @ETH_SS_FEATURES: Device feature names + * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names + * @ETH_SS_PHY_STATS: Statistic names, for use with %ETHTOOL_GPHYSTATS + * @ETH_SS_PHY_TUNABLES: PHY tunable names + */ +enum ethtool_stringset { + ETH_SS_TEST = 0, + ETH_SS_STATS, + ETH_SS_PRIV_FLAGS, + ETH_SS_NTUPLE_FILTERS, + ETH_SS_FEATURES, + ETH_SS_RSS_HASH_FUNCS, + ETH_SS_TUNABLES, + ETH_SS_PHY_STATS, + ETH_SS_PHY_TUNABLES, +}; + +/** + * struct ethtool_gstrings - string set for data tagging + * @cmd: Command number = %ETHTOOL_GSTRINGS + * @string_set: String set ID; one of &enum ethtool_stringset + * @len: On return, the number of strings in the string set + * @data: Buffer for strings. Each string is null-padded to a size of + * %ETH_GSTRING_LEN. + * + * Users must use %ETHTOOL_GSSET_INFO to find the number of strings in + * the string set. They must allocate a buffer of the appropriate + * size immediately following this structure. + */ +struct ethtool_gstrings { + __u32 cmd; + __u32 string_set; + __u32 len; + __u8 data[0]; +}; + +/** + * struct ethtool_sset_info - string set information + * @cmd: Command number = %ETHTOOL_GSSET_INFO + * @sset_mask: On entry, a bitmask of string sets to query, with bits + * numbered according to &enum ethtool_stringset. On return, a + * bitmask of those string sets queried that are supported. + * @data: Buffer for string set sizes. On return, this contains the + * size of each string set that was queried and supported, in + * order of ID. + * + * Example: The user passes in @sset_mask = 0x7 (sets 0, 1, 2) and on + * return @sset_mask == 0x6 (sets 1, 2). Then @data[0] contains the + * size of set 1 and @data[1] contains the size of set 2. + * + * Users must allocate a buffer of the appropriate size (4 * number of + * sets queried) immediately following this structure. + */ +struct ethtool_sset_info { + __u32 cmd; + __u32 reserved; + __u64 sset_mask; + __u32 data[0]; +}; + +/** + * enum ethtool_test_flags - flags definition of ethtool_test + * @ETH_TEST_FL_OFFLINE: if set perform online and offline tests, otherwise + * only online tests. + * @ETH_TEST_FL_FAILED: Driver set this flag if test fails. + * @ETH_TEST_FL_EXTERNAL_LB: Application request to perform external loopback + * test. + * @ETH_TEST_FL_EXTERNAL_LB_DONE: Driver performed the external loopback test + */ + +enum ethtool_test_flags { + ETH_TEST_FL_OFFLINE = (1 << 0), + ETH_TEST_FL_FAILED = (1 << 1), + ETH_TEST_FL_EXTERNAL_LB = (1 << 2), + ETH_TEST_FL_EXTERNAL_LB_DONE = (1 << 3), +}; + +/** + * struct ethtool_test - device self-test invocation + * @cmd: Command number = %ETHTOOL_TEST + * @flags: A bitmask of flags from &enum ethtool_test_flags. Some + * flags may be set by the user on entry; others may be set by + * the driver on return. + * @len: On return, the number of test results + * @data: Array of test results + * + * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the + * number of test results that will be returned. They must allocate a + * buffer of the appropriate size (8 * number of results) immediately + * following this structure. + */ +struct ethtool_test { + __u32 cmd; + __u32 flags; + __u32 reserved; + __u32 len; + __u64 data[0]; +}; + +/** + * struct ethtool_stats - device-specific statistics + * @cmd: Command number = %ETHTOOL_GSTATS + * @n_stats: On return, the number of statistics + * @data: Array of statistics + * + * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the + * number of statistics that will be returned. They must allocate a + * buffer of the appropriate size (8 * number of statistics) + * immediately following this structure. + */ +struct ethtool_stats { + __u32 cmd; + __u32 n_stats; + __u64 data[0]; +}; + +/** + * struct ethtool_perm_addr - permanent hardware address + * @cmd: Command number = %ETHTOOL_GPERMADDR + * @size: On entry, the size of the buffer. On return, the size of the + * address. The command fails if the buffer is too small. + * @data: Buffer for the address + * + * Users must allocate the buffer immediately following this structure. + * A buffer size of %MAX_ADDR_LEN should be sufficient for any address + * type. + */ +struct ethtool_perm_addr { + __u32 cmd; + __u32 size; + __u8 data[0]; +}; + +/* boolean flags controlling per-interface behavior characteristics. + * When reading, the flag indicates whether or not a certain behavior + * is enabled/present. When writing, the flag indicates whether + * or not the driver should turn on (set) or off (clear) a behavior. + * + * Some behaviors may read-only (unconditionally absent or present). + * If such is the case, return EINVAL in the set-flags operation if the + * flag differs from the read-only value. + */ +enum ethtool_flags { + ETH_FLAG_TXVLAN = (1 << 7), /* TX VLAN offload enabled */ + ETH_FLAG_RXVLAN = (1 << 8), /* RX VLAN offload enabled */ + ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ + ETH_FLAG_NTUPLE = (1 << 27), /* N-tuple filters enabled */ + ETH_FLAG_RXHASH = (1 << 28), +}; + +/* The following structures are for supporting RX network flow + * classification and RX n-tuple configuration. Note, all multibyte + * fields, e.g., ip4src, ip4dst, psrc, pdst, spi, etc. are expected to + * be in network byte order. + */ + +/** + * struct ethtool_tcpip4_spec - flow specification for TCP/IPv4 etc. + * @ip4src: Source host + * @ip4dst: Destination host + * @psrc: Source port + * @pdst: Destination port + * @tos: Type-of-service + * + * This can be used to specify a TCP/IPv4, UDP/IPv4 or SCTP/IPv4 flow. + */ +struct ethtool_tcpip4_spec { + __be32 ip4src; + __be32 ip4dst; + __be16 psrc; + __be16 pdst; + __u8 tos; +}; + +/** + * struct ethtool_ah_espip4_spec - flow specification for IPsec/IPv4 + * @ip4src: Source host + * @ip4dst: Destination host + * @spi: Security parameters index + * @tos: Type-of-service + * + * This can be used to specify an IPsec transport or tunnel over IPv4. + */ +struct ethtool_ah_espip4_spec { + __be32 ip4src; + __be32 ip4dst; + __be32 spi; + __u8 tos; +}; + +#define ETH_RX_NFC_IP4 1 + +/** + * struct ethtool_usrip4_spec - general flow specification for IPv4 + * @ip4src: Source host + * @ip4dst: Destination host + * @l4_4_bytes: First 4 bytes of transport (layer 4) header + * @tos: Type-of-service + * @ip_ver: Value must be %ETH_RX_NFC_IP4; mask must be 0 + * @proto: Transport protocol number; mask must be 0 + */ +struct ethtool_usrip4_spec { + __be32 ip4src; + __be32 ip4dst; + __be32 l4_4_bytes; + __u8 tos; + __u8 ip_ver; + __u8 proto; +}; + +/** + * struct ethtool_tcpip6_spec - flow specification for TCP/IPv6 etc. + * @ip6src: Source host + * @ip6dst: Destination host + * @psrc: Source port + * @pdst: Destination port + * @tclass: Traffic Class + * + * This can be used to specify a TCP/IPv6, UDP/IPv6 or SCTP/IPv6 flow. + */ +struct ethtool_tcpip6_spec { + __be32 ip6src[4]; + __be32 ip6dst[4]; + __be16 psrc; + __be16 pdst; + __u8 tclass; +}; + +/** + * struct ethtool_ah_espip6_spec - flow specification for IPsec/IPv6 + * @ip6src: Source host + * @ip6dst: Destination host + * @spi: Security parameters index + * @tclass: Traffic Class + * + * This can be used to specify an IPsec transport or tunnel over IPv6. + */ +struct ethtool_ah_espip6_spec { + __be32 ip6src[4]; + __be32 ip6dst[4]; + __be32 spi; + __u8 tclass; +}; + +/** + * struct ethtool_usrip6_spec - general flow specification for IPv6 + * @ip6src: Source host + * @ip6dst: Destination host + * @l4_4_bytes: First 4 bytes of transport (layer 4) header + * @tclass: Traffic Class + * @l4_proto: Transport protocol number (nexthdr after any Extension Headers) + */ +struct ethtool_usrip6_spec { + __be32 ip6src[4]; + __be32 ip6dst[4]; + __be32 l4_4_bytes; + __u8 tclass; + __u8 l4_proto; +}; + +union ethtool_flow_union { + struct ethtool_tcpip4_spec tcp_ip4_spec; + struct ethtool_tcpip4_spec udp_ip4_spec; + struct ethtool_tcpip4_spec sctp_ip4_spec; + struct ethtool_ah_espip4_spec ah_ip4_spec; + struct ethtool_ah_espip4_spec esp_ip4_spec; + struct ethtool_usrip4_spec usr_ip4_spec; + struct ethtool_tcpip6_spec tcp_ip6_spec; + struct ethtool_tcpip6_spec udp_ip6_spec; + struct ethtool_tcpip6_spec sctp_ip6_spec; + struct ethtool_ah_espip6_spec ah_ip6_spec; + struct ethtool_ah_espip6_spec esp_ip6_spec; + struct ethtool_usrip6_spec usr_ip6_spec; + struct ethhdr ether_spec; + __u8 hdata[52]; +}; + +/** + * struct ethtool_flow_ext - additional RX flow fields + * @h_dest: destination MAC address + * @vlan_etype: VLAN EtherType + * @vlan_tci: VLAN tag control information + * @data: user defined data + * + * Note, @vlan_etype, @vlan_tci, and @data are only valid if %FLOW_EXT + * is set in &struct ethtool_rx_flow_spec @flow_type. + * @h_dest is valid if %FLOW_MAC_EXT is set. + */ +struct ethtool_flow_ext { + __u8 padding[2]; + unsigned char h_dest[ETH_ALEN]; + __be16 vlan_etype; + __be16 vlan_tci; + __be32 data[2]; +}; + +/** + * struct ethtool_rx_flow_spec - classification rule for RX flows + * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW + * @h_u: Flow fields to match (dependent on @flow_type) + * @h_ext: Additional fields to match + * @m_u: Masks for flow field bits to be matched + * @m_ext: Masks for additional field bits to be matched + * Note, all additional fields must be ignored unless @flow_type + * includes the %FLOW_EXT or %FLOW_MAC_EXT flag + * (see &struct ethtool_flow_ext description). + * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC + * if packets should be discarded, or %RX_CLS_FLOW_WAKE if the + * packets should be used for Wake-on-LAN with %WAKE_FILTER + * @location: Location of rule in the table. Locations must be + * numbered such that a flow matching multiple rules will be + * classified according to the first (lowest numbered) rule. + */ +struct ethtool_rx_flow_spec { + __u32 flow_type; + union ethtool_flow_union h_u; + struct ethtool_flow_ext h_ext; + union ethtool_flow_union m_u; + struct ethtool_flow_ext m_ext; + __u64 ring_cookie; + __u32 location; +}; + +/* How rings are laid out when accessing virtual functions or + * offloaded queues is device specific. To allow users to do flow + * steering and specify these queues the ring cookie is partitioned + * into a 32bit queue index with an 8 bit virtual function id. + * This also leaves the 3bytes for further specifiers. It is possible + * future devices may support more than 256 virtual functions if + * devices start supporting PCIe w/ARI. However at the moment I + * do not know of any devices that support this so I do not reserve + * space for this at this time. If a future patch consumes the next + * byte it should be aware of this possibility. + */ +#define ETHTOOL_RX_FLOW_SPEC_RING 0x00000000FFFFFFFFLL +#define ETHTOOL_RX_FLOW_SPEC_RING_VF 0x000000FF00000000LL +#define ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF 32 +static inline __u64 ethtool_get_flow_spec_ring(__u64 ring_cookie) +{ + return ETHTOOL_RX_FLOW_SPEC_RING & ring_cookie; +} + +static inline __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie) +{ + return (ETHTOOL_RX_FLOW_SPEC_RING_VF & ring_cookie) >> + ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF; +} + +/** + * struct ethtool_rxnfc - command to get or set RX flow classification rules + * @cmd: Specific command number - %ETHTOOL_GRXFH, %ETHTOOL_SRXFH, + * %ETHTOOL_GRXRINGS, %ETHTOOL_GRXCLSRLCNT, %ETHTOOL_GRXCLSRULE, + * %ETHTOOL_GRXCLSRLALL, %ETHTOOL_SRXCLSRLDEL or %ETHTOOL_SRXCLSRLINS + * @flow_type: Type of flow to be affected, e.g. %TCP_V4_FLOW + * @data: Command-dependent value + * @fs: Flow classification rule + * @rss_context: RSS context to be affected + * @rule_cnt: Number of rules to be affected + * @rule_locs: Array of used rule locations + * + * For %ETHTOOL_GRXFH and %ETHTOOL_SRXFH, @data is a bitmask indicating + * the fields included in the flow hash, e.g. %RXH_IP_SRC. The following + * structure fields must not be used, except that if @flow_type includes + * the %FLOW_RSS flag, then @rss_context determines which RSS context to + * act on. + * + * For %ETHTOOL_GRXRINGS, @data is set to the number of RX rings/queues + * on return. + * + * For %ETHTOOL_GRXCLSRLCNT, @rule_cnt is set to the number of defined + * rules on return. If @data is non-zero on return then it is the + * size of the rule table, plus the flag %RX_CLS_LOC_SPECIAL if the + * driver supports any special location values. If that flag is not + * set in @data then special location values should not be used. + * + * For %ETHTOOL_GRXCLSRULE, @fs.@location specifies the location of an + * existing rule on entry and @fs contains the rule on return; if + * @fs.@flow_type includes the %FLOW_RSS flag, then @rss_context is + * filled with the RSS context ID associated with the rule. + * + * For %ETHTOOL_GRXCLSRLALL, @rule_cnt specifies the array size of the + * user buffer for @rule_locs on entry. On return, @data is the size + * of the rule table, @rule_cnt is the number of defined rules, and + * @rule_locs contains the locations of the defined rules. Drivers + * must use the second parameter to get_rxnfc() instead of @rule_locs. + * + * For %ETHTOOL_SRXCLSRLINS, @fs specifies the rule to add or update. + * @fs.@location either specifies the location to use or is a special + * location value with %RX_CLS_LOC_SPECIAL flag set. On return, + * @fs.@location is the actual rule location. If @fs.@flow_type + * includes the %FLOW_RSS flag, @rss_context is the RSS context ID to + * use for flow spreading traffic which matches this rule. The value + * from the rxfh indirection table will be added to @fs.@ring_cookie + * to choose which ring to deliver to. + * + * For %ETHTOOL_SRXCLSRLDEL, @fs.@location specifies the location of an + * existing rule on entry. + * + * A driver supporting the special location values for + * %ETHTOOL_SRXCLSRLINS may add the rule at any suitable unused + * location, and may remove a rule at a later location (lower + * priority) that matches exactly the same set of flows. The special + * values are %RX_CLS_LOC_ANY, selecting any location; + * %RX_CLS_LOC_FIRST, selecting the first suitable location (maximum + * priority); and %RX_CLS_LOC_LAST, selecting the last suitable + * location (minimum priority). Additional special values may be + * defined in future and drivers must return -%EINVAL for any + * unrecognised value. + */ +struct ethtool_rxnfc { + __u32 cmd; + __u32 flow_type; + __u64 data; + struct ethtool_rx_flow_spec fs; + union { + __u32 rule_cnt; + __u32 rss_context; + }; + __u32 rule_locs[0]; +}; + + +/** + * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection + * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR + * @size: On entry, the array size of the user buffer, which may be zero. + * On return from %ETHTOOL_GRXFHINDIR, the array size of the hardware + * indirection table. + * @ring_index: RX ring/queue index for each hash value + * + * For %ETHTOOL_GRXFHINDIR, a @size of zero means that only the size + * should be returned. For %ETHTOOL_SRXFHINDIR, a @size of zero means + * the table should be reset to default values. This last feature + * is not supported by the original implementations. + */ +struct ethtool_rxfh_indir { + __u32 cmd; + __u32 size; + __u32 ring_index[0]; +}; + +/** + * struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key. + * @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH + * @rss_context: RSS context identifier. Context 0 is the default for normal + * traffic; other contexts can be referenced as the destination for RX flow + * classification rules. %ETH_RXFH_CONTEXT_ALLOC is used with command + * %ETHTOOL_SRSSH to allocate a new RSS context; on return this field will + * contain the ID of the newly allocated context. + * @indir_size: On entry, the array size of the user buffer for the + * indirection table, which may be zero, or (for %ETHTOOL_SRSSH), + * %ETH_RXFH_INDIR_NO_CHANGE. On return from %ETHTOOL_GRSSH, + * the array size of the hardware indirection table. + * @key_size: On entry, the array size of the user buffer for the hash key, + * which may be zero. On return from %ETHTOOL_GRSSH, the size of the + * hardware hash key. + * @hfunc: Defines the current RSS hash function used by HW (or to be set to). + * Valid values are one of the %ETH_RSS_HASH_*. + * @rsvd: Reserved for future extensions. + * @rss_config: RX ring/queue index for each hash value i.e., indirection table + * of @indir_size __u32 elements, followed by hash key of @key_size + * bytes. + * + * For %ETHTOOL_GRSSH, a @indir_size and key_size of zero means that only the + * size should be returned. For %ETHTOOL_SRSSH, an @indir_size of + * %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested + * and a @indir_size of zero means the indir table should be reset to default + * values (if @rss_context == 0) or that the RSS context should be deleted. + * An hfunc of zero means that hash function setting is not requested. + */ +struct ethtool_rxfh { + __u32 cmd; + __u32 rss_context; + __u32 indir_size; + __u32 key_size; + __u8 hfunc; + __u8 rsvd8[3]; + __u32 rsvd32; + __u32 rss_config[0]; +}; +#define ETH_RXFH_CONTEXT_ALLOC 0xffffffff +#define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff + +/** + * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter + * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW + * @h_u: Flow field values to match (dependent on @flow_type) + * @m_u: Masks for flow field value bits to be ignored + * @vlan_tag: VLAN tag to match + * @vlan_tag_mask: Mask for VLAN tag bits to be ignored + * @data: Driver-dependent data to match + * @data_mask: Mask for driver-dependent data bits to be ignored + * @action: RX ring/queue index to deliver to (non-negative) or other action + * (negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP) + * + * For flow types %TCP_V4_FLOW, %UDP_V4_FLOW and %SCTP_V4_FLOW, where + * a field value and mask are both zero this is treated as if all mask + * bits are set i.e. the field is ignored. + */ +struct ethtool_rx_ntuple_flow_spec { + __u32 flow_type; + union { + struct ethtool_tcpip4_spec tcp_ip4_spec; + struct ethtool_tcpip4_spec udp_ip4_spec; + struct ethtool_tcpip4_spec sctp_ip4_spec; + struct ethtool_ah_espip4_spec ah_ip4_spec; + struct ethtool_ah_espip4_spec esp_ip4_spec; + struct ethtool_usrip4_spec usr_ip4_spec; + struct ethhdr ether_spec; + __u8 hdata[72]; + } h_u, m_u; + + __u16 vlan_tag; + __u16 vlan_tag_mask; + __u64 data; + __u64 data_mask; + + __s32 action; +#define ETHTOOL_RXNTUPLE_ACTION_DROP (-1) /* drop packet */ +#define ETHTOOL_RXNTUPLE_ACTION_CLEAR (-2) /* clear filter */ +}; + +/** + * struct ethtool_rx_ntuple - command to set or clear RX flow filter + * @cmd: Command number - %ETHTOOL_SRXNTUPLE + * @fs: Flow filter specification + */ +struct ethtool_rx_ntuple { + __u32 cmd; + struct ethtool_rx_ntuple_flow_spec fs; +}; + +#define ETHTOOL_FLASH_MAX_FILENAME 128 +enum ethtool_flash_op_type { + ETHTOOL_FLASH_ALL_REGIONS = 0, +}; + +/* for passing firmware flashing related parameters */ +struct ethtool_flash { + __u32 cmd; + __u32 region; + char data[ETHTOOL_FLASH_MAX_FILENAME]; +}; + +/** + * struct ethtool_dump - used for retrieving, setting device dump + * @cmd: Command number - %ETHTOOL_GET_DUMP_FLAG, %ETHTOOL_GET_DUMP_DATA, or + * %ETHTOOL_SET_DUMP + * @version: FW version of the dump, filled in by driver + * @flag: driver dependent flag for dump setting, filled in by driver during + * get and filled in by ethtool for set operation. + * flag must be initialized by macro ETH_FW_DUMP_DISABLE value when + * firmware dump is disabled. + * @len: length of dump data, used as the length of the user buffer on entry to + * %ETHTOOL_GET_DUMP_DATA and this is returned as dump length by driver + * for %ETHTOOL_GET_DUMP_FLAG command + * @data: data collected for get dump data operation + */ +struct ethtool_dump { + __u32 cmd; + __u32 version; + __u32 flag; + __u32 len; + __u8 data[0]; +}; + +#define ETH_FW_DUMP_DISABLE 0 + +/* for returning and changing feature sets */ + +/** + * struct ethtool_get_features_block - block with state of 32 features + * @available: mask of changeable features + * @requested: mask of features requested to be enabled if possible + * @active: mask of currently enabled features + * @never_changed: mask of features not changeable for any device + */ +struct ethtool_get_features_block { + __u32 available; + __u32 requested; + __u32 active; + __u32 never_changed; +}; + +/** + * struct ethtool_gfeatures - command to get state of device's features + * @cmd: command number = %ETHTOOL_GFEATURES + * @size: On entry, the number of elements in the features[] array; + * on return, the number of elements in features[] needed to hold + * all features + * @features: state of features + */ +struct ethtool_gfeatures { + __u32 cmd; + __u32 size; + struct ethtool_get_features_block features[0]; +}; + +/** + * struct ethtool_set_features_block - block with request for 32 features + * @valid: mask of features to be changed + * @requested: values of features to be changed + */ +struct ethtool_set_features_block { + __u32 valid; + __u32 requested; +}; + +/** + * struct ethtool_sfeatures - command to request change in device's features + * @cmd: command number = %ETHTOOL_SFEATURES + * @size: array size of the features[] array + * @features: feature change masks + */ +struct ethtool_sfeatures { + __u32 cmd; + __u32 size; + struct ethtool_set_features_block features[0]; +}; + +/** + * struct ethtool_ts_info - holds a device's timestamping and PHC association + * @cmd: command number = %ETHTOOL_GET_TS_INFO + * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags + * @phc_index: device index of the associated PHC, or -1 if there is none + * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values + * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values + * + * The bits in the 'tx_types' and 'rx_filters' fields correspond to + * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values, + * respectively. For example, if the device supports HWTSTAMP_TX_ON, + * then (1 << HWTSTAMP_TX_ON) in 'tx_types' will be set. + * + * Drivers should only report the filters they actually support without + * upscaling in the SIOCSHWTSTAMP ioctl. If the SIOCSHWSTAMP request for + * HWTSTAMP_FILTER_V1_SYNC is supported by HWTSTAMP_FILTER_V1_EVENT, then the + * driver should only report HWTSTAMP_FILTER_V1_EVENT in this op. + */ +struct ethtool_ts_info { + __u32 cmd; + __u32 so_timestamping; + __s32 phc_index; + __u32 tx_types; + __u32 tx_reserved[3]; + __u32 rx_filters; + __u32 rx_reserved[3]; +}; + +/* + * %ETHTOOL_SFEATURES changes features present in features[].valid to the + * values of corresponding bits in features[].requested. Bits in .requested + * not set in .valid or not changeable are ignored. + * + * Returns %EINVAL when .valid contains undefined or never-changeable bits + * or size is not equal to required number of features words (32-bit blocks). + * Returns >= 0 if request was completed; bits set in the value mean: + * %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not + * changeable (not present in %ETHTOOL_GFEATURES' features[].available) + * those bits were ignored. + * %ETHTOOL_F_WISH - some or all changes requested were recorded but the + * resulting state of bits masked by .valid is not equal to .requested. + * Probably there are other device-specific constraints on some features + * in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered + * here as though ignored bits were cleared. + * %ETHTOOL_F_COMPAT - some or all changes requested were made by calling + * compatibility functions. Requested offload state cannot be properly + * managed by kernel. + * + * Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of + * bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands + * for ETH_SS_FEATURES string set. First entry in the table corresponds to least + * significant bit in features[0] fields. Empty strings mark undefined features. + */ +enum ethtool_sfeatures_retval_bits { + ETHTOOL_F_UNSUPPORTED__BIT, + ETHTOOL_F_WISH__BIT, + ETHTOOL_F_COMPAT__BIT, +}; + +#define ETHTOOL_F_UNSUPPORTED (1 << ETHTOOL_F_UNSUPPORTED__BIT) +#define ETHTOOL_F_WISH (1 << ETHTOOL_F_WISH__BIT) +#define ETHTOOL_F_COMPAT (1 << ETHTOOL_F_COMPAT__BIT) + +#define MAX_NUM_QUEUE 4096 + +/** + * struct ethtool_per_queue_op - apply sub command to the queues in mask. + * @cmd: ETHTOOL_PERQUEUE + * @sub_command: the sub command which apply to each queues + * @queue_mask: Bitmap of the queues which sub command apply to + * @data: A complete command structure following for each of the queues addressed + */ +struct ethtool_per_queue_op { + __u32 cmd; + __u32 sub_command; + __u32 queue_mask[__KERNEL_DIV_ROUND_UP(MAX_NUM_QUEUE, 32)]; + char data[]; +}; + +/** + * struct ethtool_fecparam - Ethernet forward error correction(fec) parameters + * @cmd: Command number = %ETHTOOL_GFECPARAM or %ETHTOOL_SFECPARAM + * @active_fec: FEC mode which is active on porte + * @fec: Bitmask of supported/configured FEC modes + * @rsvd: Reserved for future extensions. i.e FEC bypass feature. + * + * Drivers should reject a non-zero setting of @autoneg when + * autoneogotiation is disabled (or not supported) for the link. + * + */ +struct ethtool_fecparam { + __u32 cmd; + /* bitmask of FEC modes */ + __u32 active_fec; + __u32 fec; + __u32 reserved; +}; + +/** + * enum ethtool_fec_config_bits - flags definition of ethtool_fec_configuration + * @ETHTOOL_FEC_NONE: FEC mode configuration is not supported + * @ETHTOOL_FEC_AUTO: Default/Best FEC mode provided by driver + * @ETHTOOL_FEC_OFF: No FEC Mode + * @ETHTOOL_FEC_RS: Reed-Solomon Forward Error Detection mode + * @ETHTOOL_FEC_BASER: Base-R/Reed-Solomon Forward Error Detection mode + */ +enum ethtool_fec_config_bits { + ETHTOOL_FEC_NONE_BIT, + ETHTOOL_FEC_AUTO_BIT, + ETHTOOL_FEC_OFF_BIT, + ETHTOOL_FEC_RS_BIT, + ETHTOOL_FEC_BASER_BIT, +}; + +#define ETHTOOL_FEC_NONE (1 << ETHTOOL_FEC_NONE_BIT) +#define ETHTOOL_FEC_AUTO (1 << ETHTOOL_FEC_AUTO_BIT) +#define ETHTOOL_FEC_OFF (1 << ETHTOOL_FEC_OFF_BIT) +#define ETHTOOL_FEC_RS (1 << ETHTOOL_FEC_RS_BIT) +#define ETHTOOL_FEC_BASER (1 << ETHTOOL_FEC_BASER_BIT) + +/* CMDs currently supported */ +#define ETHTOOL_GSET 0x00000001 /* DEPRECATED, Get settings. + * Please use ETHTOOL_GLINKSETTINGS + */ +#define ETHTOOL_SSET 0x00000002 /* DEPRECATED, Set settings. + * Please use ETHTOOL_SLINKSETTINGS + */ +#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ +#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers. */ +#define ETHTOOL_GWOL 0x00000005 /* Get wake-on-lan options. */ +#define ETHTOOL_SWOL 0x00000006 /* Set wake-on-lan options. */ +#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ +#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level. */ +#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation. */ +/* Get link status for host, i.e. whether the interface *and* the + * physical port (if there is one) are up (ethtool_value). */ +#define ETHTOOL_GLINK 0x0000000a +#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ +#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data. */ +#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ +#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ +#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ +#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters. */ +#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ +#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ +#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ +#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ +#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ +#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ +#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable + * (ethtool_value) */ +#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable + * (ethtool_value). */ +#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test. */ +#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ +#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ +#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ +#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ +#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ +#define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */ +#define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */ +#define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */ +#define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */ +#define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */ +#define ETHTOOL_GFLAGS 0x00000025 /* Get flags bitmap(ethtool_value) */ +#define ETHTOOL_SFLAGS 0x00000026 /* Set flags bitmap(ethtool_value) */ +#define ETHTOOL_GPFLAGS 0x00000027 /* Get driver-private flags bitmap */ +#define ETHTOOL_SPFLAGS 0x00000028 /* Set driver-private flags bitmap */ + +#define ETHTOOL_GRXFH 0x00000029 /* Get RX flow hash configuration */ +#define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */ +#define ETHTOOL_GGRO 0x0000002b /* Get GRO enable (ethtool_value) */ +#define ETHTOOL_SGRO 0x0000002c /* Set GRO enable (ethtool_value) */ +#define ETHTOOL_GRXRINGS 0x0000002d /* Get RX rings available for LB */ +#define ETHTOOL_GRXCLSRLCNT 0x0000002e /* Get RX class rule count */ +#define ETHTOOL_GRXCLSRULE 0x0000002f /* Get RX classification rule */ +#define ETHTOOL_GRXCLSRLALL 0x00000030 /* Get all RX classification rule */ +#define ETHTOOL_SRXCLSRLDEL 0x00000031 /* Delete RX classification rule */ +#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */ +#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */ +#define ETHTOOL_RESET 0x00000034 /* Reset hardware */ +#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */ +#define ETHTOOL_GRXNTUPLE 0x00000036 /* deprecated */ +#define ETHTOOL_GSSET_INFO 0x00000037 /* Get string set info */ +#define ETHTOOL_GRXFHINDIR 0x00000038 /* Get RX flow hash indir'n table */ +#define ETHTOOL_SRXFHINDIR 0x00000039 /* Set RX flow hash indir'n table */ + +#define ETHTOOL_GFEATURES 0x0000003a /* Get device offload settings */ +#define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */ +#define ETHTOOL_GCHANNELS 0x0000003c /* Get no of channels */ +#define ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */ +#define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */ +#define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */ +#define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */ +#define ETHTOOL_GET_TS_INFO 0x00000041 /* Get time stamping and PHC info */ +#define ETHTOOL_GMODULEINFO 0x00000042 /* Get plug-in module information */ +#define ETHTOOL_GMODULEEEPROM 0x00000043 /* Get plug-in module eeprom */ +#define ETHTOOL_GEEE 0x00000044 /* Get EEE settings */ +#define ETHTOOL_SEEE 0x00000045 /* Set EEE settings */ + +#define ETHTOOL_GRSSH 0x00000046 /* Get RX flow hash configuration */ +#define ETHTOOL_SRSSH 0x00000047 /* Set RX flow hash configuration */ +#define ETHTOOL_GTUNABLE 0x00000048 /* Get tunable configuration */ +#define ETHTOOL_STUNABLE 0x00000049 /* Set tunable configuration */ +#define ETHTOOL_GPHYSTATS 0x0000004a /* get PHY-specific statistics */ + +#define ETHTOOL_PERQUEUE 0x0000004b /* Set per queue options */ + +#define ETHTOOL_GLINKSETTINGS 0x0000004c /* Get ethtool_link_settings */ +#define ETHTOOL_SLINKSETTINGS 0x0000004d /* Set ethtool_link_settings */ +#define ETHTOOL_PHY_GTUNABLE 0x0000004e /* Get PHY tunable configuration */ +#define ETHTOOL_PHY_STUNABLE 0x0000004f /* Set PHY tunable configuration */ +#define ETHTOOL_GFECPARAM 0x00000050 /* Get FEC settings */ +#define ETHTOOL_SFECPARAM 0x00000051 /* Set FEC settings */ + +/* compatibility with older code */ +#define SPARC_ETH_GSET ETHTOOL_GSET +#define SPARC_ETH_SSET ETHTOOL_SSET + +/* Link mode bit indices */ +enum ethtool_link_mode_bit_indices { + ETHTOOL_LINK_MODE_10baseT_Half_BIT = 0, + ETHTOOL_LINK_MODE_10baseT_Full_BIT = 1, + ETHTOOL_LINK_MODE_100baseT_Half_BIT = 2, + ETHTOOL_LINK_MODE_100baseT_Full_BIT = 3, + ETHTOOL_LINK_MODE_1000baseT_Half_BIT = 4, + ETHTOOL_LINK_MODE_1000baseT_Full_BIT = 5, + ETHTOOL_LINK_MODE_Autoneg_BIT = 6, + ETHTOOL_LINK_MODE_TP_BIT = 7, + ETHTOOL_LINK_MODE_AUI_BIT = 8, + ETHTOOL_LINK_MODE_MII_BIT = 9, + ETHTOOL_LINK_MODE_FIBRE_BIT = 10, + ETHTOOL_LINK_MODE_BNC_BIT = 11, + ETHTOOL_LINK_MODE_10000baseT_Full_BIT = 12, + ETHTOOL_LINK_MODE_Pause_BIT = 13, + ETHTOOL_LINK_MODE_Asym_Pause_BIT = 14, + ETHTOOL_LINK_MODE_2500baseX_Full_BIT = 15, + ETHTOOL_LINK_MODE_Backplane_BIT = 16, + ETHTOOL_LINK_MODE_1000baseKX_Full_BIT = 17, + ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT = 18, + ETHTOOL_LINK_MODE_10000baseKR_Full_BIT = 19, + ETHTOOL_LINK_MODE_10000baseR_FEC_BIT = 20, + ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT = 21, + ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT = 22, + ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT = 23, + ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT = 24, + ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT = 25, + ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT = 26, + ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT = 27, + ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT = 28, + ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT = 29, + ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT = 30, + ETHTOOL_LINK_MODE_25000baseCR_Full_BIT = 31, + + /* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit + * 31. Please do NOT define any SUPPORTED_* or ADVERTISED_* + * macro for bits > 31. The only way to use indices > 31 is to + * use the new ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. + */ + + ETHTOOL_LINK_MODE_25000baseKR_Full_BIT = 32, + ETHTOOL_LINK_MODE_25000baseSR_Full_BIT = 33, + ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT = 34, + ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT = 35, + ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT = 36, + ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT = 37, + ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT = 38, + ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT = 39, + ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT = 40, + ETHTOOL_LINK_MODE_1000baseX_Full_BIT = 41, + ETHTOOL_LINK_MODE_10000baseCR_Full_BIT = 42, + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT = 43, + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT = 44, + ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT = 45, + ETHTOOL_LINK_MODE_10000baseER_Full_BIT = 46, + ETHTOOL_LINK_MODE_2500baseT_Full_BIT = 47, + ETHTOOL_LINK_MODE_5000baseT_Full_BIT = 48, + + ETHTOOL_LINK_MODE_FEC_NONE_BIT = 49, + ETHTOOL_LINK_MODE_FEC_RS_BIT = 50, + ETHTOOL_LINK_MODE_FEC_BASER_BIT = 51, + ETHTOOL_LINK_MODE_50000baseKR_Full_BIT = 52, + ETHTOOL_LINK_MODE_50000baseSR_Full_BIT = 53, + ETHTOOL_LINK_MODE_50000baseCR_Full_BIT = 54, + ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT = 55, + ETHTOOL_LINK_MODE_50000baseDR_Full_BIT = 56, + ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT = 57, + ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT = 58, + ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT = 59, + ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT = 60, + ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT = 61, + ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT = 62, + ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT = 63, + ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT = 64, + ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT = 65, + ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT = 66, + + /* must be last entry */ + __ETHTOOL_LINK_MODE_MASK_NBITS +}; + +#define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name) \ + (1UL << (ETHTOOL_LINK_MODE_ ## base_name ## _BIT)) + +/* DEPRECATED macros. Please migrate to + * ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. Please do NOT + * define any new SUPPORTED_* macro for bits > 31. + */ +#define SUPPORTED_10baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half) +#define SUPPORTED_10baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Full) +#define SUPPORTED_100baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Half) +#define SUPPORTED_100baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Full) +#define SUPPORTED_1000baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Half) +#define SUPPORTED_1000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Full) +#define SUPPORTED_Autoneg __ETHTOOL_LINK_MODE_LEGACY_MASK(Autoneg) +#define SUPPORTED_TP __ETHTOOL_LINK_MODE_LEGACY_MASK(TP) +#define SUPPORTED_AUI __ETHTOOL_LINK_MODE_LEGACY_MASK(AUI) +#define SUPPORTED_MII __ETHTOOL_LINK_MODE_LEGACY_MASK(MII) +#define SUPPORTED_FIBRE __ETHTOOL_LINK_MODE_LEGACY_MASK(FIBRE) +#define SUPPORTED_BNC __ETHTOOL_LINK_MODE_LEGACY_MASK(BNC) +#define SUPPORTED_10000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseT_Full) +#define SUPPORTED_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Pause) +#define SUPPORTED_Asym_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Asym_Pause) +#define SUPPORTED_2500baseX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(2500baseX_Full) +#define SUPPORTED_Backplane __ETHTOOL_LINK_MODE_LEGACY_MASK(Backplane) +#define SUPPORTED_1000baseKX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseKX_Full) +#define SUPPORTED_10000baseKX4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKX4_Full) +#define SUPPORTED_10000baseKR_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKR_Full) +#define SUPPORTED_10000baseR_FEC __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseR_FEC) +#define SUPPORTED_20000baseMLD2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseMLD2_Full) +#define SUPPORTED_20000baseKR2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseKR2_Full) +#define SUPPORTED_40000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseKR4_Full) +#define SUPPORTED_40000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseCR4_Full) +#define SUPPORTED_40000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseSR4_Full) +#define SUPPORTED_40000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseLR4_Full) +#define SUPPORTED_56000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseKR4_Full) +#define SUPPORTED_56000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseCR4_Full) +#define SUPPORTED_56000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseSR4_Full) +#define SUPPORTED_56000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseLR4_Full) +/* Please do not define any new SUPPORTED_* macro for bits > 31, see + * notice above. + */ + +/* + * DEPRECATED macros. Please migrate to + * ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. Please do NOT + * define any new ADERTISE_* macro for bits > 31. + */ +#define ADVERTISED_10baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half) +#define ADVERTISED_10baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Full) +#define ADVERTISED_100baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Half) +#define ADVERTISED_100baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Full) +#define ADVERTISED_1000baseT_Half __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Half) +#define ADVERTISED_1000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Full) +#define ADVERTISED_Autoneg __ETHTOOL_LINK_MODE_LEGACY_MASK(Autoneg) +#define ADVERTISED_TP __ETHTOOL_LINK_MODE_LEGACY_MASK(TP) +#define ADVERTISED_AUI __ETHTOOL_LINK_MODE_LEGACY_MASK(AUI) +#define ADVERTISED_MII __ETHTOOL_LINK_MODE_LEGACY_MASK(MII) +#define ADVERTISED_FIBRE __ETHTOOL_LINK_MODE_LEGACY_MASK(FIBRE) +#define ADVERTISED_BNC __ETHTOOL_LINK_MODE_LEGACY_MASK(BNC) +#define ADVERTISED_10000baseT_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseT_Full) +#define ADVERTISED_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Pause) +#define ADVERTISED_Asym_Pause __ETHTOOL_LINK_MODE_LEGACY_MASK(Asym_Pause) +#define ADVERTISED_2500baseX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(2500baseX_Full) +#define ADVERTISED_Backplane __ETHTOOL_LINK_MODE_LEGACY_MASK(Backplane) +#define ADVERTISED_1000baseKX_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseKX_Full) +#define ADVERTISED_10000baseKX4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKX4_Full) +#define ADVERTISED_10000baseKR_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKR_Full) +#define ADVERTISED_10000baseR_FEC __ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseR_FEC) +#define ADVERTISED_20000baseMLD2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseMLD2_Full) +#define ADVERTISED_20000baseKR2_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseKR2_Full) +#define ADVERTISED_40000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseKR4_Full) +#define ADVERTISED_40000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseCR4_Full) +#define ADVERTISED_40000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseSR4_Full) +#define ADVERTISED_40000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseLR4_Full) +#define ADVERTISED_56000baseKR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseKR4_Full) +#define ADVERTISED_56000baseCR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseCR4_Full) +#define ADVERTISED_56000baseSR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseSR4_Full) +#define ADVERTISED_56000baseLR4_Full __ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseLR4_Full) +/* Please do not define any new ADVERTISED_* macro for bits > 31, see + * notice above. + */ + +/* The following are all involved in forcing a particular link + * mode for the device for setting things. When getting the + * devices settings, these indicate the current mode and whether + * it was forced up into this mode or autonegotiated. + */ + +/* The forced speed, in units of 1Mb. All values 0 to INT_MAX are legal. + * Update drivers/net/phy/phy.c:phy_speed_to_str() and + * drivers/net/bonding/bond_3ad.c:__get_link_speed() when adding new values. + */ +#define SPEED_10 10 +#define SPEED_100 100 +#define SPEED_1000 1000 +#define SPEED_2500 2500 +#define SPEED_5000 5000 +#define SPEED_10000 10000 +#define SPEED_14000 14000 +#define SPEED_20000 20000 +#define SPEED_25000 25000 +#define SPEED_40000 40000 +#define SPEED_50000 50000 +#define SPEED_56000 56000 +#define SPEED_100000 100000 +#define SPEED_200000 200000 + +#define SPEED_UNKNOWN -1 + +static inline int ethtool_validate_speed(__u32 speed) +{ + return speed <= INT_MAX || speed == (__u32)SPEED_UNKNOWN; +} + +/* Duplex, half or full. */ +#define DUPLEX_HALF 0x00 +#define DUPLEX_FULL 0x01 +#define DUPLEX_UNKNOWN 0xff + +static inline int ethtool_validate_duplex(__u8 duplex) +{ + switch (duplex) { + case DUPLEX_HALF: + case DUPLEX_FULL: + case DUPLEX_UNKNOWN: + return 1; + } + + return 0; +} + +/* Which connector port. */ +#define PORT_TP 0x00 +#define PORT_AUI 0x01 +#define PORT_MII 0x02 +#define PORT_FIBRE 0x03 +#define PORT_BNC 0x04 +#define PORT_DA 0x05 +#define PORT_NONE 0xef +#define PORT_OTHER 0xff + +/* Which transceiver to use. */ +#define XCVR_INTERNAL 0x00 /* PHY and MAC are in the same package */ +#define XCVR_EXTERNAL 0x01 /* PHY and MAC are in different packages */ +#define XCVR_DUMMY1 0x02 +#define XCVR_DUMMY2 0x03 +#define XCVR_DUMMY3 0x04 + +/* Enable or disable autonegotiation. */ +#define AUTONEG_DISABLE 0x00 +#define AUTONEG_ENABLE 0x01 + +/* MDI or MDI-X status/control - if MDI/MDI_X/AUTO is set then + * the driver is required to renegotiate link + */ +#define ETH_TP_MDI_INVALID 0x00 /* status: unknown; control: unsupported */ +#define ETH_TP_MDI 0x01 /* status: MDI; control: force MDI */ +#define ETH_TP_MDI_X 0x02 /* status: MDI-X; control: force MDI-X */ +#define ETH_TP_MDI_AUTO 0x03 /* control: auto-select */ + +/* Wake-On-Lan options. */ +#define WAKE_PHY (1 << 0) +#define WAKE_UCAST (1 << 1) +#define WAKE_MCAST (1 << 2) +#define WAKE_BCAST (1 << 3) +#define WAKE_ARP (1 << 4) +#define WAKE_MAGIC (1 << 5) +#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ +#define WAKE_FILTER (1 << 7) + +/* L2-L4 network traffic flow types */ +#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */ +#define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */ +#define SCTP_V4_FLOW 0x03 /* hash or spec (sctp_ip4_spec) */ +#define AH_ESP_V4_FLOW 0x04 /* hash only */ +#define TCP_V6_FLOW 0x05 /* hash or spec (tcp_ip6_spec; nfc only) */ +#define UDP_V6_FLOW 0x06 /* hash or spec (udp_ip6_spec; nfc only) */ +#define SCTP_V6_FLOW 0x07 /* hash or spec (sctp_ip6_spec; nfc only) */ +#define AH_ESP_V6_FLOW 0x08 /* hash only */ +#define AH_V4_FLOW 0x09 /* hash or spec (ah_ip4_spec) */ +#define ESP_V4_FLOW 0x0a /* hash or spec (esp_ip4_spec) */ +#define AH_V6_FLOW 0x0b /* hash or spec (ah_ip6_spec; nfc only) */ +#define ESP_V6_FLOW 0x0c /* hash or spec (esp_ip6_spec; nfc only) */ +#define IPV4_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */ +#define IP_USER_FLOW IPV4_USER_FLOW +#define IPV6_USER_FLOW 0x0e /* spec only (usr_ip6_spec; nfc only) */ +#define IPV4_FLOW 0x10 /* hash only */ +#define IPV6_FLOW 0x11 /* hash only */ +#define ETHER_FLOW 0x12 /* spec only (ether_spec) */ +/* Flag to enable additional fields in struct ethtool_rx_flow_spec */ +#define FLOW_EXT 0x80000000 +#define FLOW_MAC_EXT 0x40000000 +/* Flag to enable RSS spreading of traffic matching rule (nfc only) */ +#define FLOW_RSS 0x20000000 + +/* L3-L4 network traffic flow hash options */ +#define RXH_L2DA (1 << 1) +#define RXH_VLAN (1 << 2) +#define RXH_L3_PROTO (1 << 3) +#define RXH_IP_SRC (1 << 4) +#define RXH_IP_DST (1 << 5) +#define RXH_L4_B_0_1 (1 << 6) /* src port in case of TCP/UDP/SCTP */ +#define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */ +#define RXH_DISCARD (1 << 31) + +#define RX_CLS_FLOW_DISC 0xffffffffffffffffULL +#define RX_CLS_FLOW_WAKE 0xfffffffffffffffeULL + +/* Special RX classification rule insert location values */ +#define RX_CLS_LOC_SPECIAL 0x80000000 /* flag */ +#define RX_CLS_LOC_ANY 0xffffffff +#define RX_CLS_LOC_FIRST 0xfffffffe +#define RX_CLS_LOC_LAST 0xfffffffd + +/* EEPROM Standards for plug in modules */ +#define ETH_MODULE_SFF_8079 0x1 +#define ETH_MODULE_SFF_8079_LEN 256 +#define ETH_MODULE_SFF_8472 0x2 +#define ETH_MODULE_SFF_8472_LEN 512 +#define ETH_MODULE_SFF_8636 0x3 +#define ETH_MODULE_SFF_8636_LEN 256 +#define ETH_MODULE_SFF_8436 0x4 +#define ETH_MODULE_SFF_8436_LEN 256 + +#define ETH_MODULE_SFF_8636_MAX_LEN 640 +#define ETH_MODULE_SFF_8436_MAX_LEN 640 + +/* Reset flags */ +/* The reset() operation must clear the flags for the components which + * were actually reset. On successful return, the flags indicate the + * components which were not reset, either because they do not exist + * in the hardware or because they cannot be reset independently. The + * driver must never reset any components that were not requested. + */ +enum ethtool_reset_flags { + /* These flags represent components dedicated to the interface + * the command is addressed to. Shift any flag left by + * ETH_RESET_SHARED_SHIFT to reset a shared component of the + * same type. + */ + ETH_RESET_MGMT = 1 << 0, /* Management processor */ + ETH_RESET_IRQ = 1 << 1, /* Interrupt requester */ + ETH_RESET_DMA = 1 << 2, /* DMA engine */ + ETH_RESET_FILTER = 1 << 3, /* Filtering/flow direction */ + ETH_RESET_OFFLOAD = 1 << 4, /* Protocol offload */ + ETH_RESET_MAC = 1 << 5, /* Media access controller */ + ETH_RESET_PHY = 1 << 6, /* Transceiver/PHY */ + ETH_RESET_RAM = 1 << 7, /* RAM shared between + * multiple components */ + ETH_RESET_AP = 1 << 8, /* Application processor */ + + ETH_RESET_DEDICATED = 0x0000ffff, /* All components dedicated to + * this interface */ + ETH_RESET_ALL = 0xffffffff, /* All components used by this + * interface, even if shared */ +}; +#define ETH_RESET_SHARED_SHIFT 16 + + +/** + * struct ethtool_link_settings - link control and status + * + * IMPORTANT, Backward compatibility notice: When implementing new + * user-space tools, please first try %ETHTOOL_GLINKSETTINGS, and + * if it succeeds use %ETHTOOL_SLINKSETTINGS to change link + * settings; do not use %ETHTOOL_SSET if %ETHTOOL_GLINKSETTINGS + * succeeded: stick to %ETHTOOL_GLINKSETTINGS/%SLINKSETTINGS in + * that case. Conversely, if %ETHTOOL_GLINKSETTINGS fails, use + * %ETHTOOL_GSET to query and %ETHTOOL_SSET to change link + * settings; do not use %ETHTOOL_SLINKSETTINGS if + * %ETHTOOL_GLINKSETTINGS failed: stick to + * %ETHTOOL_GSET/%ETHTOOL_SSET in that case. + * + * @cmd: Command number = %ETHTOOL_GLINKSETTINGS or %ETHTOOL_SLINKSETTINGS + * @speed: Link speed (Mbps) + * @duplex: Duplex mode; one of %DUPLEX_* + * @port: Physical connector type; one of %PORT_* + * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not + * applicable. For clause 45 PHYs this is the PRTAD. + * @autoneg: Enable/disable autonegotiation and auto-detection; + * either %AUTONEG_DISABLE or %AUTONEG_ENABLE + * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO + * protocols supported by the interface; 0 if unknown. + * Read-only. + * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of + * %ETH_TP_MDI_*. If the status is unknown or not applicable, the + * value will be %ETH_TP_MDI_INVALID. Read-only. + * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of + * %ETH_TP_MDI_*. If MDI(-X) control is not implemented, reads + * yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected. + * When written successfully, the link should be renegotiated if + * necessary. + * @link_mode_masks_nwords: Number of 32-bit words for each of the + * supported, advertising, lp_advertising link mode bitmaps. For + * %ETHTOOL_GLINKSETTINGS: on entry, number of words passed by user + * (>= 0); on return, if handshake in progress, negative if + * request size unsupported by kernel: absolute value indicates + * kernel expected size and all the other fields but cmd + * are 0; otherwise (handshake completed), strictly positive + * to indicate size used by kernel and cmd field stays + * %ETHTOOL_GLINKSETTINGS, all other fields populated by driver. For + * %ETHTOOL_SLINKSETTINGS: must be valid on entry, ie. a positive + * value returned previously by %ETHTOOL_GLINKSETTINGS, otherwise + * refused. For drivers: ignore this field (use kernel's + * __ETHTOOL_LINK_MODE_MASK_NBITS instead), any change to it will + * be overwritten by kernel. + * @supported: Bitmap with each bit meaning given by + * %ethtool_link_mode_bit_indices for the link modes, physical + * connectors and other link features for which the interface + * supports autonegotiation or auto-detection. Read-only. + * @advertising: Bitmap with each bit meaning given by + * %ethtool_link_mode_bit_indices for the link modes, physical + * connectors and other link features that are advertised through + * autonegotiation or enabled for auto-detection. + * @lp_advertising: Bitmap with each bit meaning given by + * %ethtool_link_mode_bit_indices for the link modes, and other + * link features that the link partner advertised through + * autonegotiation; 0 if unknown or not applicable. Read-only. + * @transceiver: Used to distinguish different possible PHY types, + * reported consistently by PHYLIB. Read-only. + * + * If autonegotiation is disabled, the speed and @duplex represent the + * fixed link mode and are writable if the driver supports multiple + * link modes. If it is enabled then they are read-only; if the link + * is up they represent the negotiated link mode; if the link is down, + * the speed is 0, %SPEED_UNKNOWN or the highest enabled speed and + * @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode. + * + * Some hardware interfaces may have multiple PHYs and/or physical + * connectors fitted or do not allow the driver to detect which are + * fitted. For these interfaces @port and/or @phy_address may be + * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE. + * Otherwise, attempts to write different values may be ignored or + * rejected. + * + * Deprecated %ethtool_cmd fields transceiver, maxtxpkt and maxrxpkt + * are not available in %ethtool_link_settings. These fields will be + * always set to zero in %ETHTOOL_GSET reply and %ETHTOOL_SSET will + * fail if any of them is set to non-zero value. + * + * Users should assume that all fields not marked read-only are + * writable and subject to validation by the driver. They should use + * %ETHTOOL_GLINKSETTINGS to get the current values before making specific + * changes and then applying them with %ETHTOOL_SLINKSETTINGS. + * + * Drivers that implement %get_link_ksettings and/or + * %set_link_ksettings should ignore the @cmd + * and @link_mode_masks_nwords fields (any change to them overwritten + * by kernel), and rely only on kernel's internal + * %__ETHTOOL_LINK_MODE_MASK_NBITS and + * %ethtool_link_mode_mask_t. Drivers that implement + * %set_link_ksettings() should validate all fields other than @cmd + * and @link_mode_masks_nwords that are not described as read-only or + * deprecated, and must ignore all fields described as read-only. + */ +struct ethtool_link_settings { + __u32 cmd; + __u32 speed; + __u8 duplex; + __u8 port; + __u8 phy_address; + __u8 autoneg; + __u8 mdio_support; + __u8 eth_tp_mdix; + __u8 eth_tp_mdix_ctrl; + __s8 link_mode_masks_nwords; + __u8 transceiver; + __u8 reserved1[3]; + __u32 reserved[7]; + __u32 link_mode_masks[0]; + /* layout of link_mode_masks fields: + * __u32 map_supported[link_mode_masks_nwords]; + * __u32 map_advertising[link_mode_masks_nwords]; + * __u32 map_lp_advertising[link_mode_masks_nwords]; + */ +}; +#endif /* _UAPI_LINUX_ETHTOOL_H */ diff --git a/src/shared/linux/nl80211.h b/src/shared/linux/nl80211.h new file mode 100644 index 00000000..beee59c8 --- /dev/null +++ b/src/shared/linux/nl80211.h @@ -0,0 +1,6552 @@ +#ifndef __LINUX_NL80211_H +#define __LINUX_NL80211_H +/* + * 802.11 netlink interface public header + * + * Copyright 2006-2010 Johannes Berg + * Copyright 2008 Michael Wu + * Copyright 2008 Luis Carlos Cobo + * Copyright 2008 Michael Buesch + * Copyright 2008, 2009 Luis R. Rodriguez + * Copyright 2008 Jouni Malinen + * Copyright 2008 Colin McCabe + * Copyright 2015-2017 Intel Deutschland GmbH + * Copyright (C) 2018-2019 Intel Corporation + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* + * This header file defines the userspace API to the wireless stack. Please + * be careful not to break things - i.e. don't move anything around or so + * unless you can demonstrate that it breaks neither API nor ABI. + * + * Additions to the API should be accompanied by actual implementations in + * an upstream driver, so that example implementations exist in case there + * are ever concerns about the precise semantics of the API or changes are + * needed, and to ensure that code for dead (no longer implemented) API + * can actually be identified and removed. + * Nonetheless, semantics should also be documented carefully in this file. + */ + +#include + +#define NL80211_GENL_NAME "nl80211" + +#define NL80211_MULTICAST_GROUP_CONFIG "config" +#define NL80211_MULTICAST_GROUP_SCAN "scan" +#define NL80211_MULTICAST_GROUP_REG "regulatory" +#define NL80211_MULTICAST_GROUP_MLME "mlme" +#define NL80211_MULTICAST_GROUP_VENDOR "vendor" +#define NL80211_MULTICAST_GROUP_NAN "nan" +#define NL80211_MULTICAST_GROUP_TESTMODE "testmode" + +#define NL80211_EDMG_BW_CONFIG_MIN 4 +#define NL80211_EDMG_BW_CONFIG_MAX 15 +#define NL80211_EDMG_CHANNELS_MIN 1 +#define NL80211_EDMG_CHANNELS_MAX 0x3c /* 0b00111100 */ + +/** + * DOC: Station handling + * + * Stations are added per interface, but a special case exists with VLAN + * interfaces. When a station is bound to an AP interface, it may be moved + * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN). + * The station is still assumed to belong to the AP interface it was added + * to. + * + * Station handling varies per interface type and depending on the driver's + * capabilities. + * + * For drivers supporting TDLS with external setup (WIPHY_FLAG_SUPPORTS_TDLS + * and WIPHY_FLAG_TDLS_EXTERNAL_SETUP), the station lifetime is as follows: + * - a setup station entry is added, not yet authorized, without any rate + * or capability information, this just exists to avoid race conditions + * - when the TDLS setup is done, a single NL80211_CMD_SET_STATION is valid + * to add rate and capability information to the station and at the same + * time mark it authorized. + * - %NL80211_TDLS_ENABLE_LINK is then used + * - after this, the only valid operation is to remove it by tearing down + * the TDLS link (%NL80211_TDLS_DISABLE_LINK) + * + * TODO: need more info for other interface types + */ + +/** + * DOC: Frame transmission/registration support + * + * Frame transmission and registration support exists to allow userspace + * management entities such as wpa_supplicant react to management frames + * that are not being handled by the kernel. This includes, for example, + * certain classes of action frames that cannot be handled in the kernel + * for various reasons. + * + * Frame registration is done on a per-interface basis and registrations + * cannot be removed other than by closing the socket. It is possible to + * specify a registration filter to register, for example, only for a + * certain type of action frame. In particular with action frames, those + * that userspace registers for will not be returned as unhandled by the + * driver, so that the registered application has to take responsibility + * for doing that. + * + * The type of frame that can be registered for is also dependent on the + * driver and interface type. The frame types are advertised in wiphy + * attributes so applications know what to expect. + * + * NOTE: When an interface changes type while registrations are active, + * these registrations are ignored until the interface type is + * changed again. This means that changing the interface type can + * lead to a situation that couldn't otherwise be produced, but + * any such registrations will be dormant in the sense that they + * will not be serviced, i.e. they will not receive any frames. + * + * Frame transmission allows userspace to send for example the required + * responses to action frames. It is subject to some sanity checking, + * but many frames can be transmitted. When a frame was transmitted, its + * status is indicated to the sending socket. + * + * For more technical details, see the corresponding command descriptions + * below. + */ + +/** + * DOC: Virtual interface / concurrency capabilities + * + * Some devices are able to operate with virtual MACs, they can have + * more than one virtual interface. The capability handling for this + * is a bit complex though, as there may be a number of restrictions + * on the types of concurrency that are supported. + * + * To start with, each device supports the interface types listed in + * the %NL80211_ATTR_SUPPORTED_IFTYPES attribute, but by listing the + * types there no concurrency is implied. + * + * Once concurrency is desired, more attributes must be observed: + * To start with, since some interface types are purely managed in + * software, like the AP-VLAN type in mac80211 for example, there's + * an additional list of these, they can be added at any time and + * are only restricted by some semantic restrictions (e.g. AP-VLAN + * cannot be added without a corresponding AP interface). This list + * is exported in the %NL80211_ATTR_SOFTWARE_IFTYPES attribute. + * + * Further, the list of supported combinations is exported. This is + * in the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute. Basically, + * it exports a list of "groups", and at any point in time the + * interfaces that are currently active must fall into any one of + * the advertised groups. Within each group, there are restrictions + * on the number of interfaces of different types that are supported + * and also the number of different channels, along with potentially + * some other restrictions. See &enum nl80211_if_combination_attrs. + * + * All together, these attributes define the concurrency of virtual + * interfaces that a given device supports. + */ + +/** + * DOC: packet coalesce support + * + * In most cases, host that receives IPv4 and IPv6 multicast/broadcast + * packets does not do anything with these packets. Therefore the + * reception of these unwanted packets causes unnecessary processing + * and power consumption. + * + * Packet coalesce feature helps to reduce number of received interrupts + * to host by buffering these packets in firmware/hardware for some + * predefined time. Received interrupt will be generated when one of the + * following events occur. + * a) Expiration of hardware timer whose expiration time is set to maximum + * coalescing delay of matching coalesce rule. + * b) Coalescing buffer in hardware reaches it's limit. + * c) Packet doesn't match any of the configured coalesce rules. + * + * User needs to configure following parameters for creating a coalesce + * rule. + * a) Maximum coalescing delay + * b) List of packet patterns which needs to be matched + * c) Condition for coalescence. pattern 'match' or 'no match' + * Multiple such rules can be created. + */ + +/** + * DOC: WPA/WPA2 EAPOL handshake offload + * + * By setting @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK flag drivers + * can indicate they support offloading EAPOL handshakes for WPA/WPA2 + * preshared key authentication. In %NL80211_CMD_CONNECT the preshared + * key should be specified using %NL80211_ATTR_PMK. Drivers supporting + * this offload may reject the %NL80211_CMD_CONNECT when no preshared + * key material is provided, for example when that driver does not + * support setting the temporal keys through %CMD_NEW_KEY. + * + * Similarly @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X flag can be + * set by drivers indicating offload support of the PTK/GTK EAPOL + * handshakes during 802.1X authentication. In order to use the offload + * the %NL80211_CMD_CONNECT should have %NL80211_ATTR_WANT_1X_4WAY_HS + * attribute flag. Drivers supporting this offload may reject the + * %NL80211_CMD_CONNECT when the attribute flag is not present. + * + * For 802.1X the PMK or PMK-R0 are set by providing %NL80211_ATTR_PMK + * using %NL80211_CMD_SET_PMK. For offloaded FT support also + * %NL80211_ATTR_PMKR0_NAME must be provided. + */ + +/** + * DOC: FILS shared key authentication offload + * + * FILS shared key authentication offload can be advertized by drivers by + * setting @NL80211_EXT_FEATURE_FILS_SK_OFFLOAD flag. The drivers that support + * FILS shared key authentication offload should be able to construct the + * authentication and association frames for FILS shared key authentication and + * eventually do a key derivation as per IEEE 802.11ai. The below additional + * parameters should be given to driver in %NL80211_CMD_CONNECT and/or in + * %NL80211_CMD_UPDATE_CONNECT_PARAMS. + * %NL80211_ATTR_FILS_ERP_USERNAME - used to construct keyname_nai + * %NL80211_ATTR_FILS_ERP_REALM - used to construct keyname_nai + * %NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM - used to construct erp message + * %NL80211_ATTR_FILS_ERP_RRK - used to generate the rIK and rMSK + * rIK should be used to generate an authentication tag on the ERP message and + * rMSK should be used to derive a PMKSA. + * rIK, rMSK should be generated and keyname_nai, sequence number should be used + * as specified in IETF RFC 6696. + * + * When FILS shared key authentication is completed, driver needs to provide the + * below additional parameters to userspace, which can be either after setting + * up a connection or after roaming. + * %NL80211_ATTR_FILS_KEK - used for key renewal + * %NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM - used in further EAP-RP exchanges + * %NL80211_ATTR_PMKID - used to identify the PMKSA used/generated + * %Nl80211_ATTR_PMK - used to update PMKSA cache in userspace + * The PMKSA can be maintained in userspace persistently so that it can be used + * later after reboots or wifi turn off/on also. + * + * %NL80211_ATTR_FILS_CACHE_ID is the cache identifier advertized by a FILS + * capable AP supporting PMK caching. It specifies the scope within which the + * PMKSAs are cached in an ESS. %NL80211_CMD_SET_PMKSA and + * %NL80211_CMD_DEL_PMKSA are enhanced to allow support for PMKSA caching based + * on FILS cache identifier. Additionally %NL80211_ATTR_PMK is used with + * %NL80211_SET_PMKSA to specify the PMK corresponding to a PMKSA for driver to + * use in a FILS shared key connection with PMKSA caching. + */ + +/** + * DOC: SAE authentication offload + * + * By setting @NL80211_EXT_FEATURE_SAE_OFFLOAD flag drivers can indicate they + * support offloading SAE authentication for WPA3-Personal networks. In + * %NL80211_CMD_CONNECT the password for SAE should be specified using + * %NL80211_ATTR_SAE_PASSWORD. + */ + +/** + * enum nl80211_commands - supported nl80211 commands + * + * @NL80211_CMD_UNSPEC: unspecified command to catch errors + * + * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request + * to get a list of all present wiphys. + * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or + * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the + * attributes determining the channel width; this is used for setting + * monitor mode channel), %NL80211_ATTR_WIPHY_RETRY_SHORT, + * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. + * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL + * instead, the support here is for backward compatibility only. + * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request + * or rename notification. Has attributes %NL80211_ATTR_WIPHY and + * %NL80211_ATTR_WIPHY_NAME. + * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes + * %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME. + * + * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration; + * either a dump request for all interfaces or a specific get with a + * single %NL80211_ATTR_IFINDEX is supported. + * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE. + * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response + * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX, + * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also + * be sent from userspace to request creation of a new virtual interface, + * then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and + * %NL80211_ATTR_IFNAME. + * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from + * userspace to request deletion of a virtual interface, then requires + * attribute %NL80211_ATTR_IFINDEX. + * + * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified + * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. + * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, + * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. + * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, + * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, + * and %NL80211_ATTR_KEY_SEQ attributes. + * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX + * or %NL80211_ATTR_MAC. + * + * @NL80211_CMD_GET_BEACON: (not used) + * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface + * using the %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL + * attributes. For drivers that generate the beacon and probe responses + * internally, the following attributes must be provided: %NL80211_ATTR_IE, + * %NL80211_ATTR_IE_PROBE_RESP and %NL80211_ATTR_IE_ASSOC_RESP. + * @NL80211_CMD_START_AP: Start AP operation on an AP interface, parameters + * are like for %NL80211_CMD_SET_BEACON, and additionally parameters that + * do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL, + * %NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID, + * %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE, + * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, + * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, + * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_INACTIVITY_TIMEOUT, + * %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS. + * The channel to use can be set on the interface or be given using the + * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width. + * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP + * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface + * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP + * + * @NL80211_CMD_GET_STATION: Get station attributes for station identified by + * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_SET_STATION: Set station attributes for station identified by + * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the + * the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC + * or, if no MAC address given, all stations, on the interface identified + * by %NL80211_ATTR_IFINDEX. %NL80211_ATTR_MGMT_SUBTYPE and + * %NL80211_ATTR_REASON_CODE can optionally be used to specify which type + * of disconnection indication should be sent to the station + * (Deauthentication or Disassociation frame and reason code for that + * frame). + * + * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to + * destination %NL80211_ATTR_MAC on the interface identified by + * %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to + * destination %NL80211_ATTR_MAC on the interface identified by + * %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_NEW_MPATH: Create a new mesh path for the destination given by + * %NL80211_ATTR_MAC via %NL80211_ATTR_MPATH_NEXT_HOP. + * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by + * %NL80211_ATTR_MAC. + * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the + * the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC + * or, if no MAC address given, all mesh paths, on the interface identified + * by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by + * %NL80211_ATTR_IFINDEX. + * + * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set + * regulatory domain. If %NL80211_ATTR_WIPHY is specified and the device + * has a private regulatory domain, it will be returned. Otherwise, the + * global regdomain will be returned. + * A device will have a private regulatory domain if it uses the + * regulatory_hint() API. Even when a private regdomain is used the channel + * information will still be mended according to further hints from + * the regulatory core to help with compliance. A dump version of this API + * is now available which will returns the global regdomain as well as + * all private regdomains of present wiphys (for those that have it). + * If a wiphy is self-managed (%NL80211_ATTR_WIPHY_SELF_MANAGED_REG), then + * its private regdomain is the only valid one for it. The regulatory + * core is not used to help with compliance in this case. + * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command + * after being queried by the kernel. CRDA replies by sending a regulatory + * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our + * current alpha2 if it found a match. It also provides + * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each + * regulatory rule is a nested set of attributes given by + * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and + * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by + * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and + * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP. + * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain + * to the specified ISO/IEC 3166-1 alpha2 country code. The core will + * store this as a valid request and then query userspace for it. + * + * @NL80211_CMD_GET_MESH_CONFIG: Get mesh networking properties for the + * interface identified by %NL80211_ATTR_IFINDEX + * + * @NL80211_CMD_SET_MESH_CONFIG: Set mesh networking properties for the + * interface identified by %NL80211_ATTR_IFINDEX + * + * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The + * interface is identified with %NL80211_ATTR_IFINDEX and the management + * frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be + * added to the end of the specified management frame is specified with + * %NL80211_ATTR_IE. If the command succeeds, the requested data will be + * added to all specified management frames generated by + * kernel/firmware/driver. + * Note: This command has been removed and it is only reserved at this + * point to avoid re-using existing command number. The functionality this + * command was planned for has been provided with cleaner design with the + * option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN, + * NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE, + * NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE. + * + * @NL80211_CMD_GET_SCAN: get scan results + * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters + * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the + * probe requests at CCK rate or not. %NL80211_ATTR_BSSID can be used to + * specify a BSSID to scan for; if not included, the wildcard BSSID will + * be used. + * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to + * NL80211_CMD_GET_SCAN and on the "scan" multicast group) + * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, + * partial scan results may be available + * + * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain + * intervals and certain number of cycles, as specified by + * %NL80211_ATTR_SCHED_SCAN_PLANS. If %NL80211_ATTR_SCHED_SCAN_PLANS is + * not specified and only %NL80211_ATTR_SCHED_SCAN_INTERVAL is specified, + * scheduled scan will run in an infinite loop with the specified interval. + * These attributes are mutually exculsive, + * i.e. NL80211_ATTR_SCHED_SCAN_INTERVAL must not be passed if + * NL80211_ATTR_SCHED_SCAN_PLANS is defined. + * If for some reason scheduled scan is aborted by the driver, all scan + * plans are canceled (including scan plans that did not start yet). + * Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) + * are passed, they are used in the probe requests. For + * broadcast, a broadcast SSID must be passed (ie. an empty + * string). If no SSID is passed, no probe requests are sent and + * a passive scan is performed. %NL80211_ATTR_SCAN_FREQUENCIES, + * if passed, define which channels should be scanned; if not + * passed, all channels allowed for the current regulatory domain + * are used. Extra IEs can also be passed from the userspace by + * using the %NL80211_ATTR_IE attribute. The first cycle of the + * scheduled scan can be delayed by %NL80211_ATTR_SCHED_SCAN_DELAY + * is supplied. If the device supports multiple concurrent scheduled + * scans, it will allow such when the caller provides the flag attribute + * %NL80211_ATTR_SCHED_SCAN_MULTI to indicate user-space support for it. + * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan. Returns -ENOENT if + * scheduled scan is not running. The caller may assume that as soon + * as the call returns, it is safe to start a new scheduled scan again. + * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan + * results available. + * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has + * stopped. The driver may issue this event at any time during a + * scheduled scan. One reason for stopping the scan is if the hardware + * does not support starting an association or a normal scan while running + * a scheduled scan. This event is also sent when the + * %NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface + * is brought down while a scheduled scan was running. + * + * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation + * or noise level + * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to + * NL80211_CMD_GET_SURVEY and on the "scan" multicast group) + * + * @NL80211_CMD_SET_PMKSA: Add a PMKSA cache entry using %NL80211_ATTR_MAC + * (for the BSSID), %NL80211_ATTR_PMKID, and optionally %NL80211_ATTR_PMK + * (PMK is used for PTKSA derivation in case of FILS shared key offload) or + * using %NL80211_ATTR_SSID, %NL80211_ATTR_FILS_CACHE_ID, + * %NL80211_ATTR_PMKID, and %NL80211_ATTR_PMK in case of FILS + * authentication where %NL80211_ATTR_FILS_CACHE_ID is the identifier + * advertized by a FILS capable AP identifying the scope of PMKSA in an + * ESS. + * @NL80211_CMD_DEL_PMKSA: Delete a PMKSA cache entry, using %NL80211_ATTR_MAC + * (for the BSSID) and %NL80211_ATTR_PMKID or using %NL80211_ATTR_SSID, + * %NL80211_ATTR_FILS_CACHE_ID, and %NL80211_ATTR_PMKID in case of FILS + * authentication. + * @NL80211_CMD_FLUSH_PMKSA: Flush all PMKSA cache entries. + * + * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain + * has been changed and provides details of the request information + * that caused the change such as who initiated the regulatory request + * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx + * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if + * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or + * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain + * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is + * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on + * to (%NL80211_ATTR_REG_ALPHA2). + * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon + * has been found while world roaming thus enabling active scan or + * any mode of operation that initiates TX (beacons) on a channel + * where we would not have been able to do either before. As an example + * if you are world roaming (regulatory domain set to world or if your + * driver is using a custom world roaming regulatory domain) and while + * doing a passive scan on the 5 GHz band you find an AP there (if not + * on a DFS channel) you will now be able to actively scan for that AP + * or use AP mode on your card on that same channel. Note that this will + * never be used for channels 1-11 on the 2 GHz band as they are always + * enabled world wide. This beacon hint is only sent if your device had + * either disabled active scanning or beaconing on a channel. We send to + * userspace the wiphy on which we removed a restriction from + * (%NL80211_ATTR_WIPHY) and the channel on which this occurred + * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER) + * the beacon hint was processed. + * + * @NL80211_CMD_AUTHENTICATE: authentication request and notification. + * This command is used both as a command (request to authenticate) and + * as an event on the "mlme" multicast group indicating completion of the + * authentication process. + * When used as a command, %NL80211_ATTR_IFINDEX is used to identify the + * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and + * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify + * the SSID (mainly for association, but is included in authentication + * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used + * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE + * is used to specify the authentication type. %NL80211_ATTR_IE is used to + * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) + * to be added to the frame. + * When used as an event, this reports reception of an Authentication + * frame in station and IBSS modes when the local MLME processed the + * frame, i.e., it was for the local STA and was received in correct + * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the + * MLME SAP interface (kernel providing MLME, userspace SME). The + * included %NL80211_ATTR_FRAME attribute contains the management frame + * (including both the header and frame body, but not FCS). This event is + * also used to indicate if the authentication attempt timed out. In that + * case the %NL80211_ATTR_FRAME attribute is replaced with a + * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which + * pending authentication timed out). + * @NL80211_CMD_ASSOCIATE: association request and notification; like + * NL80211_CMD_AUTHENTICATE but for Association and Reassociation + * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, + * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives). The + * %NL80211_ATTR_PREV_BSSID attribute is used to specify whether the + * request is for the initial association to an ESS (that attribute not + * included) or for reassociation within the ESS (that attribute is + * included). + * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like + * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to + * MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication + * primitives). + * @NL80211_CMD_DISASSOCIATE: disassociation request and notification; like + * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to + * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives). + * + * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael + * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the + * event includes %NL80211_ATTR_MAC to describe the source MAC address of + * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key + * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and + * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this + * event matches with MLME-MICHAELMICFAILURE.indication() primitive + * + * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a + * FREQ attribute (for the initial frequency if no peer can be found) + * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those + * should be fixed rather than automatically determined. Can only be + * executed on a network interface that is UP, and fixed BSSID/FREQ + * may be rejected. Another optional parameter is the beacon interval, + * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not + * given defaults to 100 TU (102.4ms). + * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is + * determined by the network interface. + * + * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute + * to identify the device, and the TESTDATA blob attribute to pass through + * to the driver. + * + * @NL80211_CMD_CONNECT: connection request and notification; this command + * requests to connect to a specified network but without separating + * auth and assoc steps. For this, you need to specify the SSID in a + * %NL80211_ATTR_SSID attribute, and can optionally specify the association + * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, + * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, + * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, + * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, + * %NL80211_ATTR_CONTROL_PORT_OVER_NL80211, %NL80211_ATTR_MAC_HINT, and + * %NL80211_ATTR_WIPHY_FREQ_HINT. + * If included, %NL80211_ATTR_MAC and %NL80211_ATTR_WIPHY_FREQ are + * restrictions on BSS selection, i.e., they effectively prevent roaming + * within the ESS. %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT + * can be included to provide a recommendation of the initial BSS while + * allowing the driver to roam to other BSSes within the ESS and also to + * ignore this recommendation if the indicated BSS is not ideal. Only one + * set of BSSID,frequency parameters is used (i.e., either the enforcing + * %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict + * %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT). + * %NL80211_ATTR_PREV_BSSID can be used to request a reassociation within + * the ESS in case the device is already associated and an association with + * a different BSS is desired. + * Background scan period can optionally be + * specified in %NL80211_ATTR_BG_SCAN_PERIOD, + * if not specified default background scan configuration + * in driver is used and if period value is 0, bg scan will be disabled. + * This attribute is ignored if driver does not support roam scan. + * It is also sent as an event, with the BSSID and response IEs when the + * connection is established or failed to be established. This can be + * determined by the %NL80211_ATTR_STATUS_CODE attribute (0 = success, + * non-zero = failure). If %NL80211_ATTR_TIMED_OUT is included in the + * event, the connection attempt failed due to not being able to initiate + * authentication/association or not receiving a response from the AP. + * Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as + * well to remain backwards compatible. + * When establishing a security association, drivers that support 4 way + * handshake offload should send %NL80211_CMD_PORT_AUTHORIZED event when + * the 4 way handshake is completed successfully. + * @NL80211_CMD_ROAM: Notification indicating the card/driver roamed by itself. + * When a security association was established with the new AP (e.g. if + * the FT protocol was used for roaming or the driver completed the 4 way + * handshake), this event should be followed by an + * %NL80211_CMD_PORT_AUTHORIZED event. + * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify + * userspace that a connection was dropped by the AP or due to other + * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and + * %NL80211_ATTR_REASON_CODE attributes are used. + * + * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices + * associated with this wiphy must be down and will follow. + * + * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified + * channel for the specified amount of time. This can be used to do + * off-channel operations like transmit a Public Action frame and wait for + * a response while being associated to an AP on another channel. + * %NL80211_ATTR_IFINDEX is used to specify which interface (and thus + * radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the + * frequency for the operation. + * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds + * to remain on the channel. This command is also used as an event to + * notify when the requested duration starts (it may take a while for the + * driver to schedule this time due to other concurrent needs for the + * radio). + * When called, this operation returns a cookie (%NL80211_ATTR_COOKIE) + * that will be included with any events pertaining to this request; + * the cookie is also used to cancel the request. + * @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a + * pending remain-on-channel duration if the desired operation has been + * completed prior to expiration of the originally requested duration. + * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the + * radio. The %NL80211_ATTR_COOKIE attribute must be given as well to + * uniquely identify the request. + * This command is also used as an event to notify when a requested + * remain-on-channel duration has expired. + * + * @NL80211_CMD_SET_TX_BITRATE_MASK: Set the mask of rates to be used in TX + * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface + * and @NL80211_ATTR_TX_RATES the set of allowed rates. + * + * @NL80211_CMD_REGISTER_FRAME: Register for receiving certain mgmt frames + * (via @NL80211_CMD_FRAME) for processing in userspace. This command + * requires an interface index, a frame type attribute (optional for + * backward compatibility reasons, if not given assumes action frames) + * and a match attribute containing the first few bytes of the frame + * that should match, e.g. a single byte for only a category match or + * four bytes for vendor frames including the OUI. The registration + * cannot be dropped, but is removed automatically when the netlink + * socket is closed. Multiple registrations can be made. + * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for + * backward compatibility + * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This + * command is used both as a request to transmit a management frame and + * as an event indicating reception of a frame that was not processed in + * kernel code, but is for us (i.e., which may need to be processed in a + * user space application). %NL80211_ATTR_FRAME is used to specify the + * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ is used + * to indicate on which channel the frame is to be transmitted or was + * received. If this channel is not the current channel (remain-on-channel + * or the operational channel) the device will switch to the given channel + * and transmit the frame, optionally waiting for a response for the time + * specified using %NL80211_ATTR_DURATION. When called, this operation + * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the + * TX status event pertaining to the TX request. + * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the + * management frames at CCK rate or not in 2GHz band. + * %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA + * counters which will be updated to the current value. This attribute + * is used during CSA period. + * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this + * command may be used with the corresponding cookie to cancel the wait + * time if it is known that it is no longer necessary. This command is + * also sent as an event whenever the driver has completed the off-channel + * wait time. + * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility. + * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame + * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies + * the TX command and %NL80211_ATTR_FRAME includes the contents of the + * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged + * the frame. + * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for + * backward compatibility. + * + * @NL80211_CMD_SET_POWER_SAVE: Set powersave, using %NL80211_ATTR_PS_STATE + * @NL80211_CMD_GET_POWER_SAVE: Get powersave status in %NL80211_ATTR_PS_STATE + * + * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command + * is used to configure connection quality monitoring notification trigger + * levels. + * @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This + * command is used as an event to indicate the that a trigger level was + * reached. + * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ + * and the attributes determining channel width) the given interface + * (identifed by %NL80211_ATTR_IFINDEX) shall operate on. + * In case multiple channels are supported by the device, the mechanism + * with which it switches channels is implementation-defined. + * When a monitor interface is given, it can only switch channel while + * no other interfaces are operating to avoid disturbing the operation + * of any other interfaces, and other interfaces will again take + * precedence when they are used. + * + * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. + * + * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if this AP should perform + * multicast to unicast conversion. When enabled, all multicast packets + * with ethertype ARP, IPv4 or IPv6 (possibly within an 802.1Q header) + * will be sent out to each station once with the destination (multicast) + * MAC address replaced by the station's MAC address. Note that this may + * break certain expectations of the receiver, e.g. the ability to drop + * unicast IP packets encapsulated in multicast L2 frames, or the ability + * to not send destination unreachable messages in such cases. + * This can only be toggled per BSS. Configure this on an interface of + * type %NL80211_IFTYPE_AP. It applies to all its VLAN interfaces + * (%NL80211_IFTYPE_AP_VLAN), except for those in 4addr (WDS) mode. + * If %NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED is not present with this + * command, the feature is disabled. + * + * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial + * mesh config parameters may be given. + * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the + * network is determined by the network interface. + * + * @NL80211_CMD_UNPROT_DEAUTHENTICATE: Unprotected deauthentication frame + * notification. This event is used to indicate that an unprotected + * deauthentication frame was dropped when MFP is in use. + * @NL80211_CMD_UNPROT_DISASSOCIATE: Unprotected disassociation frame + * notification. This event is used to indicate that an unprotected + * disassociation frame was dropped when MFP is in use. + * + * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a + * beacon or probe response from a compatible mesh peer. This is only + * sent while no station information (sta_info) exists for the new peer + * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH, + * @NL80211_MESH_SETUP_USERSPACE_AMPE, or + * @NL80211_MESH_SETUP_USERSPACE_MPM is set. On reception of this + * notification, userspace may decide to create a new station + * (@NL80211_CMD_NEW_STATION). To stop this notification from + * reoccurring, the userspace authentication daemon may want to create the + * new station with the AUTHENTICATED flag unset and maybe change it later + * depending on the authentication result. + * + * @NL80211_CMD_GET_WOWLAN: get Wake-on-Wireless-LAN (WoWLAN) settings. + * @NL80211_CMD_SET_WOWLAN: set Wake-on-Wireless-LAN (WoWLAN) settings. + * Since wireless is more complex than wired ethernet, it supports + * various triggers. These triggers can be configured through this + * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For + * more background information, see + * http://wireless.kernel.org/en/users/Documentation/WoWLAN. + * The @NL80211_CMD_SET_WOWLAN command can also be used as a notification + * from the driver reporting the wakeup reason. In this case, the + * @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason + * for the wakeup, if it was caused by wireless. If it is not present + * in the wakeup notification, the wireless device didn't cause the + * wakeup but reports that it was woken up. + * + * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver + * the necessary information for supporting GTK rekey offload. This + * feature is typically used during WoWLAN. The configuration data + * is contained in %NL80211_ATTR_REKEY_DATA (which is nested and + * contains the data in sub-attributes). After rekeying happened, + * this command may also be sent by the driver as an MLME event to + * inform userspace of the new replay counter. + * + * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace + * of PMKSA caching dandidates. + * + * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup). + * In addition, this can be used as an event to request userspace to take + * actions on TDLS links (set up a new link or tear down an existing one). + * In such events, %NL80211_ATTR_TDLS_OPERATION indicates the requested + * operation, %NL80211_ATTR_MAC contains the peer MAC address, and + * %NL80211_ATTR_REASON_CODE the reason code to be used (only with + * %NL80211_TDLS_TEARDOWN). + * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. The + * %NL80211_ATTR_TDLS_ACTION attribute determines the type of frame to be + * sent. Public Action codes (802.11-2012 8.1.5.1) will be sent as + * 802.11 management frames, while TDLS action codes (802.11-2012 + * 8.5.13.1) will be encapsulated and sent as data frames. The currently + * supported Public Action code is %WLAN_PUB_ACTION_TDLS_DISCOVER_RES + * and the currently supported TDLS actions codes are given in + * &enum ieee80211_tdls_actioncode. + * + * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP + * (or GO) interface (i.e. hostapd) to ask for unexpected frames to + * implement sending deauth to stations that send unexpected class 3 + * frames. Also used as the event sent by the kernel when such a frame + * is received. + * For the event, the %NL80211_ATTR_MAC attribute carries the TA and + * other attributes like the interface index are present. + * If used as the command it must have an interface index and you can + * only unsubscribe from the event by closing the socket. Subscription + * is also for %NL80211_CMD_UNEXPECTED_4ADDR_FRAME events. + * + * @NL80211_CMD_UNEXPECTED_4ADDR_FRAME: Sent as an event indicating that the + * associated station identified by %NL80211_ATTR_MAC sent a 4addr frame + * and wasn't already in a 4-addr VLAN. The event will be sent similarly + * to the %NL80211_CMD_UNEXPECTED_FRAME event, to the same listener. + * + * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface + * by sending a null data frame to it and reporting when the frame is + * acknowleged. This is used to allow timing out inactive clients. Uses + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a + * direct reply with an %NL80211_ATTR_COOKIE that is later used to match + * up the event with the request. The event includes the same data and + * has %NL80211_ATTR_ACK set if the frame was ACKed. + * + * @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from + * other BSSes when any interfaces are in AP mode. This helps implement + * OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME + * messages. Note that per PHY only one application may register. + * + * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether + * No Acknowledgement Policy should be applied. + * + * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels + * independently of the userspace SME, send this event indicating + * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the + * attributes determining channel width. This indication may also be + * sent when a remotely-initiated switch (e.g., when a STA receives a CSA + * from the remote AP) is completed; + * + * @NL80211_CMD_CH_SWITCH_STARTED_NOTIFY: Notify that a channel switch + * has been started on an interface, regardless of the initiator + * (ie. whether it was requested from a remote device or + * initiated on our own). It indicates that + * %NL80211_ATTR_IFINDEX will be on %NL80211_ATTR_WIPHY_FREQ + * after %NL80211_ATTR_CH_SWITCH_COUNT TBTT's. The userspace may + * decide to react to this indication by requesting other + * interfaces to change channel as well. + * + * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. It must have been created with + * %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the + * P2P Device can be used for P2P operations, e.g. remain-on-channel and + * public action frame TX. + * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. + * + * @NL80211_CMD_CONN_FAILED: connection request to an AP failed; used to + * notify userspace that AP has rejected the connection request from a + * station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON + * is used for this. + * + * @NL80211_CMD_SET_MCAST_RATE: Change the rate used to send multicast frames + * for IBSS or MESH vif. + * + * @NL80211_CMD_SET_MAC_ACL: sets ACL for MAC address based access control. + * This is to be used with the drivers advertising the support of MAC + * address based access control. List of MAC addresses is passed in + * %NL80211_ATTR_MAC_ADDRS and ACL policy is passed in + * %NL80211_ATTR_ACL_POLICY. Driver will enable ACL with this list, if it + * is not already done. The new list will replace any existing list. Driver + * will clear its ACL when the list of MAC addresses passed is empty. This + * command is used in AP/P2P GO mode. Driver has to make sure to clear its + * ACL list during %NL80211_CMD_STOP_AP. + * + * @NL80211_CMD_RADAR_DETECT: Start a Channel availability check (CAC). Once + * a radar is detected or the channel availability scan (CAC) has finished + * or was aborted, or a radar was detected, usermode will be notified with + * this event. This command is also used to notify userspace about radars + * while operating on this channel. + * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the + * event. + * + * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features, + * i.e. features for the nl80211 protocol rather than device features. + * Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap. + * + * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition + * Information Element to the WLAN driver + * + * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver + * to the supplicant. This will carry the target AP's MAC address along + * with the relevant Information Elements. This event is used to report + * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE). + * + * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running + * a critical protocol that needs more reliability in the connection to + * complete. + * + * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can + * return back to normal. + * + * @NL80211_CMD_GET_COALESCE: Get currently supported coalesce rules. + * @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules. + * + * @NL80211_CMD_CHANNEL_SWITCH: Perform a channel switch by announcing the + * the new channel information (Channel Switch Announcement - CSA) + * in the beacon for some time (as defined in the + * %NL80211_ATTR_CH_SWITCH_COUNT parameter) and then change to the + * new channel. Userspace provides the new channel information (using + * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel + * width). %NL80211_ATTR_CH_SWITCH_BLOCK_TX may be supplied to inform + * other station that transmission must be blocked until the channel + * switch is complete. + * + * @NL80211_CMD_VENDOR: Vendor-specified command/event. The command is specified + * by the %NL80211_ATTR_VENDOR_ID attribute and a sub-command in + * %NL80211_ATTR_VENDOR_SUBCMD. Parameter(s) can be transported in + * %NL80211_ATTR_VENDOR_DATA. + * For feature advertisement, the %NL80211_ATTR_VENDOR_DATA attribute is + * used in the wiphy data as a nested attribute containing descriptions + * (&struct nl80211_vendor_cmd_info) of the supported vendor commands. + * This may also be sent as an event with the same attributes. + * + * @NL80211_CMD_SET_QOS_MAP: Set Interworking QoS mapping for IP DSCP values. + * The QoS mapping information is included in %NL80211_ATTR_QOS_MAP. If + * that attribute is not included, QoS mapping is disabled. Since this + * QoS mapping is relevant for IP packets, it is only valid during an + * association. This is cleared on disassociation and AP restart. + * + * @NL80211_CMD_ADD_TX_TS: Ask the kernel to add a traffic stream for the given + * %NL80211_ATTR_TSID and %NL80211_ATTR_MAC with %NL80211_ATTR_USER_PRIO + * and %NL80211_ATTR_ADMITTED_TIME parameters. + * Note that the action frame handshake with the AP shall be handled by + * userspace via the normal management RX/TX framework, this only sets + * up the TX TS in the driver/device. + * If the admitted time attribute is not added then the request just checks + * if a subsequent setup could be successful, the intent is to use this to + * avoid setting up a session with the AP when local restrictions would + * make that impossible. However, the subsequent "real" setup may still + * fail even if the check was successful. + * @NL80211_CMD_DEL_TX_TS: Remove an existing TS with the %NL80211_ATTR_TSID + * and %NL80211_ATTR_MAC parameters. It isn't necessary to call this + * before removing a station entry entirely, or before disassociating + * or similar, cleanup will happen in the driver/device in this case. + * + * @NL80211_CMD_GET_MPP: Get mesh path attributes for mesh proxy path to + * destination %NL80211_ATTR_MAC on the interface identified by + * %NL80211_ATTR_IFINDEX. + * + * @NL80211_CMD_JOIN_OCB: Join the OCB network. The center frequency and + * bandwidth of a channel must be given. + * @NL80211_CMD_LEAVE_OCB: Leave the OCB network -- no special arguments, the + * network is determined by the network interface. + * + * @NL80211_CMD_TDLS_CHANNEL_SWITCH: Start channel-switching with a TDLS peer, + * identified by the %NL80211_ATTR_MAC parameter. A target channel is + * provided via %NL80211_ATTR_WIPHY_FREQ and other attributes determining + * channel width/type. The target operating class is given via + * %NL80211_ATTR_OPER_CLASS. + * The driver is responsible for continually initiating channel-switching + * operations and returning to the base channel for communication with the + * AP. + * @NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH: Stop channel-switching with a TDLS + * peer given by %NL80211_ATTR_MAC. Both peers must be on the base channel + * when this command completes. + * + * @NL80211_CMD_WIPHY_REG_CHANGE: Similar to %NL80211_CMD_REG_CHANGE, but used + * as an event to indicate changes for devices with wiphy-specific regdom + * management. + * + * @NL80211_CMD_ABORT_SCAN: Stop an ongoing scan. Returns -ENOENT if a scan is + * not running. The driver indicates the status of the scan through + * cfg80211_scan_done(). + * + * @NL80211_CMD_START_NAN: Start NAN operation, identified by its + * %NL80211_ATTR_WDEV interface. This interface must have been + * previously created with %NL80211_CMD_NEW_INTERFACE. After it + * has been started, the NAN interface will create or join a + * cluster. This command must have a valid + * %NL80211_ATTR_NAN_MASTER_PREF attribute and optional + * %NL80211_ATTR_BANDS attributes. If %NL80211_ATTR_BANDS is + * omitted or set to 0, it means don't-care and the device will + * decide what to use. After this command NAN functions can be + * added. + * @NL80211_CMD_STOP_NAN: Stop the NAN operation, identified by + * its %NL80211_ATTR_WDEV interface. + * @NL80211_CMD_ADD_NAN_FUNCTION: Add a NAN function. The function is defined + * with %NL80211_ATTR_NAN_FUNC nested attribute. When called, this + * operation returns the strictly positive and unique instance id + * (%NL80211_ATTR_NAN_FUNC_INST_ID) and a cookie (%NL80211_ATTR_COOKIE) + * of the function upon success. + * Since instance ID's can be re-used, this cookie is the right + * way to identify the function. This will avoid races when a termination + * event is handled by the user space after it has already added a new + * function that got the same instance id from the kernel as the one + * which just terminated. + * This cookie may be used in NAN events even before the command + * returns, so userspace shouldn't process NAN events until it processes + * the response to this command. + * Look at %NL80211_ATTR_SOCKET_OWNER as well. + * @NL80211_CMD_DEL_NAN_FUNCTION: Delete a NAN function by cookie. + * This command is also used as a notification sent when a NAN function is + * terminated. This will contain a %NL80211_ATTR_NAN_FUNC_INST_ID + * and %NL80211_ATTR_COOKIE attributes. + * @NL80211_CMD_CHANGE_NAN_CONFIG: Change current NAN + * configuration. NAN must be operational (%NL80211_CMD_START_NAN + * was executed). It must contain at least one of the following + * attributes: %NL80211_ATTR_NAN_MASTER_PREF, + * %NL80211_ATTR_BANDS. If %NL80211_ATTR_BANDS is omitted, the + * current configuration is not changed. If it is present but + * set to zero, the configuration is changed to don't-care + * (i.e. the device can decide what to do). + * @NL80211_CMD_NAN_FUNC_MATCH: Notification sent when a match is reported. + * This will contain a %NL80211_ATTR_NAN_MATCH nested attribute and + * %NL80211_ATTR_COOKIE. + * + * @NL80211_CMD_UPDATE_CONNECT_PARAMS: Update one or more connect parameters + * for subsequent roaming cases if the driver or firmware uses internal + * BSS selection. This command can be issued only while connected and it + * does not result in a change for the current association. Currently, + * only the %NL80211_ATTR_IE data is used and updated with this command. + * + * @NL80211_CMD_SET_PMK: For offloaded 4-Way handshake, set the PMK or PMK-R0 + * for the given authenticator address (specified with %NL80211_ATTR_MAC). + * When %NL80211_ATTR_PMKR0_NAME is set, %NL80211_ATTR_PMK specifies the + * PMK-R0, otherwise it specifies the PMK. + * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously + * configured PMK for the authenticator address identified by + * %NL80211_ATTR_MAC. + * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates that the 4 way + * handshake was completed successfully by the driver. The BSSID is + * specified with %NL80211_ATTR_MAC. Drivers that support 4 way handshake + * offload should send this event after indicating 802.11 association with + * %NL80211_CMD_CONNECT or %NL80211_CMD_ROAM. If the 4 way handshake failed + * %NL80211_CMD_DISCONNECT should be indicated instead. + * + * @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request + * and RX notification. This command is used both as a request to transmit + * a control port frame and as a notification that a control port frame + * has been received. %NL80211_ATTR_FRAME is used to specify the + * frame contents. The frame is the raw EAPoL data, without ethernet or + * 802.11 headers. + * When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, + * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added + * indicating the protocol type of the received frame; whether the frame + * was received unencrypted and the MAC address of the peer respectively. + * + * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. + * + * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host + * drivers that do not define separate commands for authentication and + * association, but rely on user space for the authentication to happen. + * This interface acts both as the event request (driver to user space) + * to trigger the authentication and command response (userspace to + * driver) to indicate the authentication status. + * + * User space uses the %NL80211_CMD_CONNECT command to the host driver to + * trigger a connection. The host driver selects a BSS and further uses + * this interface to offload only the authentication part to the user + * space. Authentication frames are passed between the driver and user + * space through the %NL80211_CMD_FRAME interface. Host driver proceeds + * further with the association after getting successful authentication + * status. User space indicates the authentication status through + * %NL80211_ATTR_STATUS_CODE attribute in %NL80211_CMD_EXTERNAL_AUTH + * command interface. + * + * Host driver reports this status on an authentication failure to the + * user space through the connect result as the user space would have + * initiated the connection through the connect request. + * + * @NL80211_CMD_STA_OPMODE_CHANGED: An event that notify station's + * ht opmode or vht opmode changes using any of %NL80211_ATTR_SMPS_MODE, + * %NL80211_ATTR_CHANNEL_WIDTH,%NL80211_ATTR_NSS attributes with its + * address(specified in %NL80211_ATTR_MAC). + * + * @NL80211_CMD_GET_FTM_RESPONDER_STATS: Retrieve FTM responder statistics, in + * the %NL80211_ATTR_FTM_RESPONDER_STATS attribute. + * + * @NL80211_CMD_PEER_MEASUREMENT_START: start a (set of) peer measurement(s) + * with the given parameters, which are encapsulated in the nested + * %NL80211_ATTR_PEER_MEASUREMENTS attribute. Optionally, MAC address + * randomization may be enabled and configured by specifying the + * %NL80211_ATTR_MAC and %NL80211_ATTR_MAC_MASK attributes. + * If a timeout is requested, use the %NL80211_ATTR_TIMEOUT attribute. + * A u64 cookie for further %NL80211_ATTR_COOKIE use is is returned in + * the netlink extended ack message. + * + * To cancel a measurement, close the socket that requested it. + * + * Measurement results are reported to the socket that requested the + * measurement using @NL80211_CMD_PEER_MEASUREMENT_RESULT when they + * become available, so applications must ensure a large enough socket + * buffer size. + * + * Depending on driver support it may or may not be possible to start + * multiple concurrent measurements. + * @NL80211_CMD_PEER_MEASUREMENT_RESULT: This command number is used for the + * result notification from the driver to the requesting socket. + * @NL80211_CMD_PEER_MEASUREMENT_COMPLETE: Notification only, indicating that + * the measurement completed, using the measurement cookie + * (%NL80211_ATTR_COOKIE). + * + * @NL80211_CMD_NOTIFY_RADAR: Notify the kernel that a radar signal was + * detected and reported by a neighboring device on the channel + * indicated by %NL80211_ATTR_WIPHY_FREQ and other attributes + * determining the width and type. + * + * @NL80211_CMD_UPDATE_OWE_INFO: This interface allows the host driver to + * offload OWE processing to user space. This intends to support + * OWE AKM by the host drivers that implement SME but rely + * on the user space for the cryptographic/DH IE processing in AP mode. + * + * @NL80211_CMD_PROBE_MESH_LINK: The requirement for mesh link metric + * refreshing, is that from one mesh point we be able to send some data + * frames to other mesh points which are not currently selected as a + * primary traffic path, but which are only 1 hop away. The absence of + * the primary path to the chosen node makes it necessary to apply some + * form of marking on a chosen packet stream so that the packets can be + * properly steered to the selected node for testing, and not by the + * regular mesh path lookup. Further, the packets must be of type data + * so that the rate control (often embedded in firmware) is used for + * rate selection. + * + * Here attribute %NL80211_ATTR_MAC is used to specify connected mesh + * peer MAC address and %NL80211_ATTR_FRAME is used to specify the frame + * content. The frame is ethernet data. + * + * @NL80211_CMD_MAX: highest used command number + * @__NL80211_CMD_AFTER_LAST: internal use + */ +enum nl80211_commands { +/* don't change the order or add anything between, this is ABI! */ + NL80211_CMD_UNSPEC, + + NL80211_CMD_GET_WIPHY, /* can dump */ + NL80211_CMD_SET_WIPHY, + NL80211_CMD_NEW_WIPHY, + NL80211_CMD_DEL_WIPHY, + + NL80211_CMD_GET_INTERFACE, /* can dump */ + NL80211_CMD_SET_INTERFACE, + NL80211_CMD_NEW_INTERFACE, + NL80211_CMD_DEL_INTERFACE, + + NL80211_CMD_GET_KEY, + NL80211_CMD_SET_KEY, + NL80211_CMD_NEW_KEY, + NL80211_CMD_DEL_KEY, + + NL80211_CMD_GET_BEACON, + NL80211_CMD_SET_BEACON, + NL80211_CMD_START_AP, + NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP, + NL80211_CMD_STOP_AP, + NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP, + + NL80211_CMD_GET_STATION, + NL80211_CMD_SET_STATION, + NL80211_CMD_NEW_STATION, + NL80211_CMD_DEL_STATION, + + NL80211_CMD_GET_MPATH, + NL80211_CMD_SET_MPATH, + NL80211_CMD_NEW_MPATH, + NL80211_CMD_DEL_MPATH, + + NL80211_CMD_SET_BSS, + + NL80211_CMD_SET_REG, + NL80211_CMD_REQ_SET_REG, + + NL80211_CMD_GET_MESH_CONFIG, + NL80211_CMD_SET_MESH_CONFIG, + + NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */, + + NL80211_CMD_GET_REG, + + NL80211_CMD_GET_SCAN, + NL80211_CMD_TRIGGER_SCAN, + NL80211_CMD_NEW_SCAN_RESULTS, + NL80211_CMD_SCAN_ABORTED, + + NL80211_CMD_REG_CHANGE, + + NL80211_CMD_AUTHENTICATE, + NL80211_CMD_ASSOCIATE, + NL80211_CMD_DEAUTHENTICATE, + NL80211_CMD_DISASSOCIATE, + + NL80211_CMD_MICHAEL_MIC_FAILURE, + + NL80211_CMD_REG_BEACON_HINT, + + NL80211_CMD_JOIN_IBSS, + NL80211_CMD_LEAVE_IBSS, + + NL80211_CMD_TESTMODE, + + NL80211_CMD_CONNECT, + NL80211_CMD_ROAM, + NL80211_CMD_DISCONNECT, + + NL80211_CMD_SET_WIPHY_NETNS, + + NL80211_CMD_GET_SURVEY, + NL80211_CMD_NEW_SURVEY_RESULTS, + + NL80211_CMD_SET_PMKSA, + NL80211_CMD_DEL_PMKSA, + NL80211_CMD_FLUSH_PMKSA, + + NL80211_CMD_REMAIN_ON_CHANNEL, + NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, + + NL80211_CMD_SET_TX_BITRATE_MASK, + + NL80211_CMD_REGISTER_FRAME, + NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME, + NL80211_CMD_FRAME, + NL80211_CMD_ACTION = NL80211_CMD_FRAME, + NL80211_CMD_FRAME_TX_STATUS, + NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS, + + NL80211_CMD_SET_POWER_SAVE, + NL80211_CMD_GET_POWER_SAVE, + + NL80211_CMD_SET_CQM, + NL80211_CMD_NOTIFY_CQM, + + NL80211_CMD_SET_CHANNEL, + NL80211_CMD_SET_WDS_PEER, + + NL80211_CMD_FRAME_WAIT_CANCEL, + + NL80211_CMD_JOIN_MESH, + NL80211_CMD_LEAVE_MESH, + + NL80211_CMD_UNPROT_DEAUTHENTICATE, + NL80211_CMD_UNPROT_DISASSOCIATE, + + NL80211_CMD_NEW_PEER_CANDIDATE, + + NL80211_CMD_GET_WOWLAN, + NL80211_CMD_SET_WOWLAN, + + NL80211_CMD_START_SCHED_SCAN, + NL80211_CMD_STOP_SCHED_SCAN, + NL80211_CMD_SCHED_SCAN_RESULTS, + NL80211_CMD_SCHED_SCAN_STOPPED, + + NL80211_CMD_SET_REKEY_OFFLOAD, + + NL80211_CMD_PMKSA_CANDIDATE, + + NL80211_CMD_TDLS_OPER, + NL80211_CMD_TDLS_MGMT, + + NL80211_CMD_UNEXPECTED_FRAME, + + NL80211_CMD_PROBE_CLIENT, + + NL80211_CMD_REGISTER_BEACONS, + + NL80211_CMD_UNEXPECTED_4ADDR_FRAME, + + NL80211_CMD_SET_NOACK_MAP, + + NL80211_CMD_CH_SWITCH_NOTIFY, + + NL80211_CMD_START_P2P_DEVICE, + NL80211_CMD_STOP_P2P_DEVICE, + + NL80211_CMD_CONN_FAILED, + + NL80211_CMD_SET_MCAST_RATE, + + NL80211_CMD_SET_MAC_ACL, + + NL80211_CMD_RADAR_DETECT, + + NL80211_CMD_GET_PROTOCOL_FEATURES, + + NL80211_CMD_UPDATE_FT_IES, + NL80211_CMD_FT_EVENT, + + NL80211_CMD_CRIT_PROTOCOL_START, + NL80211_CMD_CRIT_PROTOCOL_STOP, + + NL80211_CMD_GET_COALESCE, + NL80211_CMD_SET_COALESCE, + + NL80211_CMD_CHANNEL_SWITCH, + + NL80211_CMD_VENDOR, + + NL80211_CMD_SET_QOS_MAP, + + NL80211_CMD_ADD_TX_TS, + NL80211_CMD_DEL_TX_TS, + + NL80211_CMD_GET_MPP, + + NL80211_CMD_JOIN_OCB, + NL80211_CMD_LEAVE_OCB, + + NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, + + NL80211_CMD_TDLS_CHANNEL_SWITCH, + NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH, + + NL80211_CMD_WIPHY_REG_CHANGE, + + NL80211_CMD_ABORT_SCAN, + + NL80211_CMD_START_NAN, + NL80211_CMD_STOP_NAN, + NL80211_CMD_ADD_NAN_FUNCTION, + NL80211_CMD_DEL_NAN_FUNCTION, + NL80211_CMD_CHANGE_NAN_CONFIG, + NL80211_CMD_NAN_MATCH, + + NL80211_CMD_SET_MULTICAST_TO_UNICAST, + + NL80211_CMD_UPDATE_CONNECT_PARAMS, + + NL80211_CMD_SET_PMK, + NL80211_CMD_DEL_PMK, + + NL80211_CMD_PORT_AUTHORIZED, + + NL80211_CMD_RELOAD_REGDB, + + NL80211_CMD_EXTERNAL_AUTH, + + NL80211_CMD_STA_OPMODE_CHANGED, + + NL80211_CMD_CONTROL_PORT_FRAME, + + NL80211_CMD_GET_FTM_RESPONDER_STATS, + + NL80211_CMD_PEER_MEASUREMENT_START, + NL80211_CMD_PEER_MEASUREMENT_RESULT, + NL80211_CMD_PEER_MEASUREMENT_COMPLETE, + + NL80211_CMD_NOTIFY_RADAR, + + NL80211_CMD_UPDATE_OWE_INFO, + + NL80211_CMD_PROBE_MESH_LINK, + + /* add new commands above here */ + + /* used to define NL80211_CMD_MAX below */ + __NL80211_CMD_AFTER_LAST, + NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1 +}; + +/* + * Allow user space programs to use #ifdef on new commands by defining them + * here + */ +#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS +#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE +#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE +#define NL80211_CMD_AUTHENTICATE NL80211_CMD_AUTHENTICATE +#define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE +#define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE +#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE +#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT + +#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS + +/* source-level API compatibility */ +#define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG +#define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG +#define NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE NL80211_MESH_SETUP_IE + +/** + * enum nl80211_attrs - nl80211 netlink attributes + * + * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors + * + * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf. + * /sys/class/ieee80211//index + * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) + * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters + * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz, + * defines the channel together with the (deprecated) + * %NL80211_ATTR_WIPHY_CHANNEL_TYPE attribute or the attributes + * %NL80211_ATTR_CHANNEL_WIDTH and if needed %NL80211_ATTR_CENTER_FREQ1 + * and %NL80211_ATTR_CENTER_FREQ2 + * @NL80211_ATTR_CHANNEL_WIDTH: u32 attribute containing one of the values + * of &enum nl80211_chan_width, describing the channel width. See the + * documentation of the enum for more information. + * @NL80211_ATTR_CENTER_FREQ1: Center frequency of the first part of the + * channel, used for anything but 20 MHz bandwidth + * @NL80211_ATTR_CENTER_FREQ2: Center frequency of the second part of the + * channel, used only for 80+80 MHz bandwidth + * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ + * if HT20 or HT40 are to be used (i.e., HT disabled if not included): + * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including + * this attribute) + * NL80211_CHAN_HT20 = HT20 only + * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel + * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel + * This attribute is now deprecated. + * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is + * less than or equal to the RTS threshold; allowed range: 1..255; + * dot11ShortRetryLimit; u8 + * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is + * greater than the RTS threshold; allowed range: 1..255; + * dot11ShortLongLimit; u8 + * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum + * length in octets for frames; allowed range: 256..8000, disable + * fragmentation with (u32)-1; dot11FragmentationThreshold; u32 + * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length + * larger than or equal to this use RTS/CTS handshake); allowed range: + * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32 + * @NL80211_ATTR_WIPHY_COVERAGE_CLASS: Coverage Class as defined by IEEE 802.11 + * section 7.3.2.9; dot11CoverageClass; u8 + * + * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on + * @NL80211_ATTR_IFNAME: network interface name + * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype + * + * @NL80211_ATTR_WDEV: wireless device identifier, used for pseudo-devices + * that don't have a netdev (u64) + * + * @NL80211_ATTR_MAC: MAC address (various uses) + * + * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of + * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC + * keys + * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3) + * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 + * section 7.3.2.25.1, e.g. 0x000FAC04) + * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and + * CCMP keys, each six bytes in little endian + * @NL80211_ATTR_KEY_DEFAULT: Flag attribute indicating the key is default key + * @NL80211_ATTR_KEY_DEFAULT_MGMT: Flag attribute indicating the key is the + * default management key + * @NL80211_ATTR_CIPHER_SUITES_PAIRWISE: For crypto settings for connect or + * other commands, indicates which pairwise cipher suites are used + * @NL80211_ATTR_CIPHER_SUITE_GROUP: For crypto settings for connect or + * other commands, indicates which group cipher suite is used + * + * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU + * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing + * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE + * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE + * + * @NL80211_ATTR_STA_AID: Association ID for the station (u16) + * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of + * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2) + * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by + * IEEE 802.11 7.3.1.6 (u16). + * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported + * rates as defined by IEEE 802.11 7.3.2.2 but without the length + * restriction (at most %NL80211_MAX_SUPP_RATES). + * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station + * to, or the AP interface the station was originally added to to. + * @NL80211_ATTR_STA_INFO: information about a station, part of station info + * given for %NL80211_CMD_GET_STATION, nested attribute containing + * info as possible, see &enum nl80211_sta_info. + * + * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands, + * consisting of a nested array. + * + * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). + * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link + * (see &enum nl80211_plink_action). + * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. + * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path + * info given for %NL80211_CMD_GET_MPATH, nested attribute described at + * &enum nl80211_mpath_info. + * + * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of + * &enum nl80211_mntr_flags. + * + * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the + * current regulatory domain should be set to or is already set to. + * For example, 'CR', for Costa Rica. This attribute is used by the kernel + * to query the CRDA to retrieve one regulatory domain. This attribute can + * also be used by userspace to query the kernel for the currently set + * regulatory domain. We chose an alpha2 as that is also used by the + * IEEE-802.11 country information element to identify a country. + * Users can also simply ask the wireless core to set regulatory domain + * to a specific alpha2. + * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory + * rules. + * + * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1) + * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled + * (u8, 0 or 1) + * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled + * (u8, 0 or 1) + * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic + * rates in format defined by IEEE 802.11 7.3.2.2 but without the length + * restriction (at most %NL80211_MAX_SUPP_RATES). + * + * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * + * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all + * supported interface types, each a flag attribute with the number + * of the interface mode. + * + * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for + * %NL80211_CMD_SET_MGMT_EXTRA_IE. + * + * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with + * %NL80211_CMD_SET_MGMT_EXTRA_IE). + * + * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with + * a single scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: number of SSIDs you can + * scan with a single scheduled scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements + * that can be added to a scan request + * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information + * elements that can be added to a scheduled scan request + * @NL80211_ATTR_MAX_MATCH_SETS: maximum number of sets that can be + * used with @NL80211_ATTR_SCHED_SCAN_MATCH, a wiphy attribute. + * + * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) + * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive + * scanning and include a zero-length SSID (wildcard) for wildcard scan + * @NL80211_ATTR_BSS: scan result BSS + * + * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain + * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_* + * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently + * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*) + * + * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies + * an array of command numbers (i.e. a mapping index to command number) + * that the driver for the given wiphy supports. + * + * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header + * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and + * NL80211_CMD_ASSOCIATE events + * @NL80211_ATTR_SSID: SSID (binary attribute, 0..32 octets) + * @NL80211_ATTR_AUTH_TYPE: AuthenticationType, see &enum nl80211_auth_type, + * represented as a u32 + * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and + * %NL80211_CMD_DISASSOCIATE, u16 + * + * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as + * a u32 + * + * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change + * due to considerations from a beacon hint. This attribute reflects + * the state of the channel _before_ the beacon hint processing. This + * attributes consists of a nested attribute containing + * NL80211_FREQUENCY_ATTR_* + * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change + * due to considerations from a beacon hint. This attribute reflects + * the state of the channel _after_ the beacon hint processing. This + * attributes consists of a nested attribute containing + * NL80211_FREQUENCY_ATTR_* + * + * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported + * cipher suites + * + * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look + * for other networks on different channels + * + * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this + * is used, e.g., with %NL80211_CMD_AUTHENTICATE event + * + * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is + * used for the association (&enum nl80211_mfp, represented as a u32); + * this attribute can be used with %NL80211_CMD_ASSOCIATE and + * %NL80211_CMD_CONNECT requests. %NL80211_MFP_OPTIONAL is not allowed for + * %NL80211_CMD_ASSOCIATE since user space SME is expected and hence, it + * must have decided whether to use management frame protection or not. + * Setting %NL80211_MFP_OPTIONAL with a %NL80211_CMD_CONNECT request will + * let the driver (or the firmware) decide whether to use MFP or not. + * + * @NL80211_ATTR_STA_FLAGS2: Attribute containing a + * &struct nl80211_sta_flag_update. + * + * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls + * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in + * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE + * request, the driver will assume that the port is unauthorized until + * authorized by user space. Otherwise, port is marked authorized by + * default in station mode. + * @NL80211_ATTR_CONTROL_PORT_ETHERTYPE: A 16-bit value indicating the + * ethertype that will be used for key negotiation. It can be + * specified with the associate and connect commands. If it is not + * specified, the value defaults to 0x888E (PAE, 802.1X). This + * attribute is also used as a flag in the wiphy information to + * indicate that protocols other than PAE are supported. + * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with + * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom + * ethertype frames used for key negotiation must not be encrypted. + * @NL80211_ATTR_CONTROL_PORT_OVER_NL80211: A flag indicating whether control + * port frames (e.g. of type given in %NL80211_ATTR_CONTROL_PORT_ETHERTYPE) + * will be sent directly to the network interface or sent via the NL80211 + * socket. If this attribute is missing, then legacy behavior of sending + * control port frames directly to the network interface is used. If the + * flag is included, then control port frames are sent over NL80211 instead + * using %CMD_CONTROL_PORT_FRAME. If control port routing over NL80211 is + * to be used then userspace must also use the %NL80211_ATTR_SOCKET_OWNER + * flag. + * + * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. + * We recommend using nested, driver-specific attributes within this. + * + * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT + * event was due to the AP disconnecting the station, and not due to + * a local disconnect request. + * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT + * event (u16) + * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating + * that protected APs should be used. This is also used with NEW_BEACON to + * indicate that the BSS is to use protection. + * + * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT, ASSOCIATE, and NEW_BEACON + * to indicate which unicast key ciphers will be used with the connection + * (an array of u32). + * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which group key cipher will be used with the connection (a + * u32). + * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which WPA version(s) the AP we want to associate with is using + * (a u32 with flags from &enum nl80211_wpa_versions). + * @NL80211_ATTR_AKM_SUITES: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which key management algorithm(s) to use (an array of u32). + * This attribute is also sent in response to @NL80211_CMD_GET_WIPHY, + * indicating the supported AKM suites, intended for specific drivers which + * implement SME and have constraints on which AKMs are supported and also + * the cases where an AKM support is offloaded to the driver/firmware. + * If there is no such notification from the driver, user space should + * assume the driver supports all the AKM suites. + * + * @NL80211_ATTR_REQ_IE: (Re)association request information elements as + * sent out by the card, for ROAM and successful CONNECT events. + * @NL80211_ATTR_RESP_IE: (Re)association response information elements as + * sent by peer, for ROAM and successful CONNECT events. + * + * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used in ASSOCIATE and CONNECT + * commands to specify a request to reassociate within an ESS, i.e., to use + * Reassociate Request frame (with the value of this attribute in the + * Current AP address field) instead of Association Request frame which is + * used for the initial association to an ESS. + * + * @NL80211_ATTR_KEY: key information in a nested attribute with + * %NL80211_KEY_* sub-attributes + * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect() + * and join_ibss(), key information is in a nested attribute each + * with %NL80211_KEY_* sub-attributes + * + * @NL80211_ATTR_PID: Process ID of a network namespace. + * + * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for + * dumps. This number increases whenever the object list being + * dumped changes, and as such userspace can verify that it has + * obtained a complete and consistent snapshot by verifying that + * all dump messages contain the same generation number. If it + * changed then the list changed and the dump should be repeated + * completely from scratch. + * + * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface + * + * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of + * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute + * containing info as possible, see &enum survey_info. + * + * @NL80211_ATTR_PMKID: PMK material for PMKSA caching. + * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can + * cache, a wiphy attribute. + * + * @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32. + * @NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION: Device attribute that + * specifies the maximum duration that can be requested with the + * remain-on-channel operation, in milliseconds, u32. + * + * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects. + * + * @NL80211_ATTR_TX_RATES: Nested set of attributes + * (enum nl80211_tx_rate_attributes) describing TX rates per band. The + * enum nl80211_band value is used as the index (nla_type() of the nested + * data. If a band is not included, it will be configured to allow all + * rates based on negotiated supported rates information. This attribute + * is used with %NL80211_CMD_SET_TX_BITRATE_MASK and with starting AP, + * and joining mesh networks (not IBSS yet). In the later case, it must + * specify just a single bitrate, which is to be used for the beacon. + * The driver must also specify support for this with the extended + * features NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, + * NL80211_EXT_FEATURE_BEACON_RATE_HT and + * NL80211_EXT_FEATURE_BEACON_RATE_VHT. + * + * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain + * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. + * @NL80211_ATTR_FRAME_TYPE: A u16 indicating the frame type/subtype for the + * @NL80211_CMD_REGISTER_FRAME command. + * @NL80211_ATTR_TX_FRAME_TYPES: wiphy capability attribute, which is a + * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing + * information about which frame types can be transmitted with + * %NL80211_CMD_FRAME. + * @NL80211_ATTR_RX_FRAME_TYPES: wiphy capability attribute, which is a + * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing + * information about which frame types can be registered for RX. + * + * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was + * acknowledged by the recipient. + * + * @NL80211_ATTR_PS_STATE: powersave state, using &enum nl80211_ps_state values. + * + * @NL80211_ATTR_CQM: connection quality monitor configuration in a + * nested attribute with %NL80211_ATTR_CQM_* sub-attributes. + * + * @NL80211_ATTR_LOCAL_STATE_CHANGE: Flag attribute to indicate that a command + * is requesting a local authentication/association state change without + * invoking actual management frame exchange. This can be used with + * NL80211_CMD_AUTHENTICATE, NL80211_CMD_DEAUTHENTICATE, + * NL80211_CMD_DISASSOCIATE. + * + * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations + * connected to this BSS. + * + * @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See + * &enum nl80211_tx_power_setting for possible values. + * @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units. + * This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING + * for non-automatic settings. + * + * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly + * means support for per-station GTKs. + * + * @NL80211_ATTR_WIPHY_ANTENNA_TX: Bitmap of allowed antennas for transmitting. + * This can be used to mask out antennas which are not attached or should + * not be used for transmitting. If an antenna is not selected in this + * bitmap the hardware is not allowed to transmit on this antenna. + * + * Each bit represents one antenna, starting with antenna 1 at the first + * bit. Depending on which antennas are selected in the bitmap, 802.11n + * drivers can derive which chainmasks to use (if all antennas belonging to + * a particular chain are disabled this chain should be disabled) and if + * a chain has diversity antennas wether diversity should be used or not. + * HT capabilities (STBC, TX Beamforming, Antenna selection) can be + * derived from the available chains after applying the antenna mask. + * Non-802.11n drivers can derive wether to use diversity or not. + * Drivers may reject configurations or RX/TX mask combinations they cannot + * support by returning -EINVAL. + * + * @NL80211_ATTR_WIPHY_ANTENNA_RX: Bitmap of allowed antennas for receiving. + * This can be used to mask out antennas which are not attached or should + * not be used for receiving. If an antenna is not selected in this bitmap + * the hardware should not be configured to receive on this antenna. + * For a more detailed description see @NL80211_ATTR_WIPHY_ANTENNA_TX. + * + * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: Bitmap of antennas which are available + * for configuration as TX antennas via the above parameters. + * + * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX: Bitmap of antennas which are available + * for configuration as RX antennas via the above parameters. + * + * @NL80211_ATTR_MCAST_RATE: Multicast tx rate (in 100 kbps) for IBSS + * + * @NL80211_ATTR_OFFCHANNEL_TX_OK: For management frame TX, the frame may be + * transmitted on another channel when the channel given doesn't match + * the current channel. If the current channel doesn't match and this + * flag isn't set, the frame will be rejected. This is also used as an + * nl80211 capability flag. + * + * @NL80211_ATTR_BSS_HT_OPMODE: HT operation mode (u16) + * + * @NL80211_ATTR_KEY_DEFAULT_TYPES: A nested attribute containing flags + * attributes, specifying what a key should be set as default as. + * See &enum nl80211_key_default_types. + * + * @NL80211_ATTR_MESH_SETUP: Optional mesh setup parameters. These cannot be + * changed once the mesh is active. + * @NL80211_ATTR_MESH_CONFIG: Mesh configuration parameters, a nested attribute + * containing attributes from &enum nl80211_meshconf_params. + * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver + * allows auth frames in a mesh to be passed to userspace for processing via + * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. + * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as defined in + * &enum nl80211_plink_state. Used when userspace is driving the peer link + * management state machine. @NL80211_MESH_SETUP_USERSPACE_AMPE or + * @NL80211_MESH_SETUP_USERSPACE_MPM must be enabled. + * + * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy + * capabilities, the supported WoWLAN triggers + * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to + * indicate which WoW triggers should be enabled. This is also + * used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN + * triggers. + * + * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan + * cycles, in msecs. + * + * @NL80211_ATTR_SCHED_SCAN_MATCH: Nested attribute with one or more + * sets of attributes to match during scheduled scans. Only BSSs + * that match any of the sets will be reported. These are + * pass-thru filter rules. + * For a match to succeed, the BSS must match all attributes of a + * set. Since not every hardware supports matching all types of + * attributes, there is no guarantee that the reported BSSs are + * fully complying with the match sets and userspace needs to be + * able to ignore them by itself. + * Thus, the implementation is somewhat hardware-dependent, but + * this is only an optimization and the userspace application + * needs to handle all the non-filtered results anyway. + * If the match attributes don't make sense when combined with + * the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID + * is included in the probe request, but the match attributes + * will never let it go through), -EINVAL may be returned. + * If omitted, no filtering is done. + * + * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported + * interface combinations. In each nested item, it contains attributes + * defined in &enum nl80211_if_combination_attrs. + * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like + * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that + * are managed in software: interfaces of these types aren't subject to + * any restrictions in their number or combinations. + * + * @NL80211_ATTR_REKEY_DATA: nested attribute containing the information + * necessary for GTK rekeying in the device, see &enum nl80211_rekey_data. + * + * @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan, + * nested array attribute containing an entry for each band, with the entry + * being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but + * without the length restriction (at most %NL80211_MAX_SUPP_RATES). + * + * @NL80211_ATTR_HIDDEN_SSID: indicates whether SSID is to be hidden from Beacon + * and Probe Response (when response to wildcard Probe Request); see + * &enum nl80211_hidden_ssid, represented as a u32 + * + * @NL80211_ATTR_IE_PROBE_RESP: Information element(s) for Probe Response frame. + * This is used with %NL80211_CMD_NEW_BEACON and %NL80211_CMD_SET_BEACON to + * provide extra IEs (e.g., WPS/P2P IE) into Probe Response frames when the + * driver (or firmware) replies to Probe Request frames. + * @NL80211_ATTR_IE_ASSOC_RESP: Information element(s) for (Re)Association + * Response frames. This is used with %NL80211_CMD_NEW_BEACON and + * %NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into + * (Re)Association Response frames when the driver (or firmware) replies to + * (Re)Association Request frames. + * + * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration + * of the station, see &enum nl80211_sta_wme_attr. + * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working + * as AP. + * + * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of + * roaming to another AP in the same ESS if the signal lever is low. + * + * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching + * candidate information, see &enum nl80211_pmksa_candidate_attr. + * + * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not + * for management frames transmission. In order to avoid p2p probe/action + * frames are being transmitted at CCK rate in 2GHz band, the user space + * applications use this attribute. + * This attribute is used with %NL80211_CMD_TRIGGER_SCAN and + * %NL80211_CMD_FRAME commands. + * + * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup + * request, link setup confirm, link teardown, etc.). Values are + * described in the TDLS (802.11z) specification. + * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a + * TDLS conversation between two devices. + * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see + * &enum nl80211_tdls_operation, represented as a u8. + * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate + * as a TDLS peer sta. + * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown + * procedures should be performed by sending TDLS packets via + * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be + * used for asking the driver to perform a TDLS operation. + * + * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices + * that have AP support to indicate that they have the AP SME integrated + * with support for the features listed in this attribute, see + * &enum nl80211_ap_sme_features. + * + * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells + * the driver to not wait for an acknowledgement. Note that due to this, + * it will also not give a status callback nor return a cookie. This is + * mostly useful for probe responses to save airtime. + * + * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from + * &enum nl80211_feature_flags and is advertised in wiphy information. + * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe + * requests while operating in AP-mode. + * This attribute holds a bitmap of the supported protocols for + * offloading (see &enum nl80211_probe_resp_offload_support_attr). + * + * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire + * probe-response frame. The DA field in the 802.11 header is zero-ed out, + * to be filled by the FW. + * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable + * this feature. Currently, only supported in mac80211 drivers. + * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the + * ATTR_HT_CAPABILITY to which attention should be paid. + * Currently, only mac80211 NICs support this feature. + * The values that may be configured are: + * MCS rates, MAX-AMSDU, HT-20-40 and HT_CAP_SGI_40 + * AMPDU density and AMPDU factor. + * All values are treated as suggestions and may be ignored + * by the driver as required. The actual values may be seen in + * the station debugfs ht_caps file. + * + * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country + * abides to when initiating radiation on DFS channels. A country maps + * to one DFS region. + * + * @NL80211_ATTR_NOACK_MAP: This u16 bitmap contains the No Ack Policy of + * up to 16 TIDs. + * + * @NL80211_ATTR_INACTIVITY_TIMEOUT: timeout value in seconds, this can be + * used by the drivers which has MLME in firmware and does not have support + * to report per station tx/rx activity to free up the station entry from + * the list. This needs to be used when the driver advertises the + * capability to timeout the stations. + * + * @NL80211_ATTR_RX_SIGNAL_DBM: signal strength in dBm (as a 32-bit int); + * this attribute is (depending on the driver capabilities) added to + * received frames indicated with %NL80211_CMD_FRAME. + * + * @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds + * or 0 to disable background scan. + * + * @NL80211_ATTR_USER_REG_HINT_TYPE: type of regulatory hint passed from + * userspace. If unset it is assumed the hint comes directly from + * a user. If set code could specify exactly what type of source + * was used to provide the hint. For the different types of + * allowed user regulatory hints see nl80211_user_reg_hint_type. + * + * @NL80211_ATTR_CONN_FAILED_REASON: The reason for which AP has rejected + * the connection request from a station. nl80211_connect_failed_reason + * enum has different reasons of connection failure. + * + * @NL80211_ATTR_AUTH_DATA: Fields and elements in Authentication frames. + * This contains the authentication frame body (non-IE and IE data), + * excluding the Authentication algorithm number, i.e., starting at the + * Authentication transaction sequence number field. It is used with + * authentication algorithms that need special fields to be added into + * the frames (SAE and FILS). Currently, only the SAE cases use the + * initial two fields (Authentication transaction sequence number and + * Status code). However, those fields are included in the attribute data + * for all authentication algorithms to keep the attribute definition + * consistent. + * + * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * + * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32) + * + * @NL80211_ATTR_P2P_CTWINDOW: P2P GO Client Traffic Window (u8), used with + * the START_AP and SET_BSS commands + * @NL80211_ATTR_P2P_OPPPS: P2P GO opportunistic PS (u8), used with the + * START_AP and SET_BSS commands. This can have the values 0 or 1; + * if not given in START_AP 0 is assumed, if not given in SET_BSS + * no change is made. + * + * @NL80211_ATTR_LOCAL_MESH_POWER_MODE: local mesh STA link-specific power mode + * defined in &enum nl80211_mesh_power_mode. + * + * @NL80211_ATTR_ACL_POLICY: ACL policy, see &enum nl80211_acl_policy, + * carried in a u32 attribute + * + * @NL80211_ATTR_MAC_ADDRS: Array of nested MAC addresses, used for + * MAC ACL. + * + * @NL80211_ATTR_MAC_ACL_MAX: u32 attribute to advertise the maximum + * number of MAC addresses that a device can support for MAC + * ACL. + * + * @NL80211_ATTR_RADAR_EVENT: Type of radar event for notification to userspace, + * contains a value of enum nl80211_radar_event (u32). + * + * @NL80211_ATTR_EXT_CAPA: 802.11 extended capabilities that the kernel driver + * has and handles. The format is the same as the IE contents. See + * 802.11-2012 8.4.2.29 for more information. + * @NL80211_ATTR_EXT_CAPA_MASK: Extended capabilities that the kernel driver + * has set in the %NL80211_ATTR_EXT_CAPA value, for multibit fields. + * + * @NL80211_ATTR_STA_CAPABILITY: Station capabilities (u16) are advertised to + * the driver, e.g., to enable TDLS power save (PU-APSD). + * + * @NL80211_ATTR_STA_EXT_CAPABILITY: Station extended capabilities are + * advertised to the driver, e.g., to enable TDLS off channel operations + * and PU-APSD. + * + * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see + * &enum nl80211_protocol_features, the attribute is a u32. + * + * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports + * receiving the data for a single wiphy split across multiple + * messages, given with wiphy dump message + * + * @NL80211_ATTR_MDID: Mobility Domain Identifier + * + * @NL80211_ATTR_IE_RIC: Resource Information Container Information + * Element + * + * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased + * reliability, see &enum nl80211_crit_proto_id (u16). + * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which + * the connection should have increased reliability (u16). + * + * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16). + * This is similar to @NL80211_ATTR_STA_AID but with a difference of being + * allowed to be used with the first @NL80211_CMD_SET_STATION command to + * update a TDLS peer STA entry. + * + * @NL80211_ATTR_COALESCE_RULE: Coalesce rule information. + * + * @NL80211_ATTR_CH_SWITCH_COUNT: u32 attribute specifying the number of TBTT's + * until the channel switch event. + * @NL80211_ATTR_CH_SWITCH_BLOCK_TX: flag attribute specifying that transmission + * must be blocked on the current channel (before the channel switch + * operation). + * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information + * for the time while performing a channel switch. + * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel + * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). + * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel + * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP). + * + * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. + * As specified in the &enum nl80211_rxmgmt_flags. + * + * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels. + * + * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported + * supported operating classes. + * + * @NL80211_ATTR_HANDLE_DFS: A flag indicating whether user space + * controls DFS operation in IBSS mode. If the flag is included in + * %NL80211_CMD_JOIN_IBSS request, the driver will allow use of DFS + * channels and reports radar events to userspace. Userspace is required + * to react to radar events, e.g. initiate a channel switch or leave the + * IBSS network. + * + * @NL80211_ATTR_SUPPORT_5_MHZ: A flag indicating that the device supports + * 5 MHz channel bandwidth. + * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports + * 10 MHz channel bandwidth. + * + * @NL80211_ATTR_OPMODE_NOTIF: Operating mode field from Operating Mode + * Notification Element based on association request when used with + * %NL80211_CMD_NEW_STATION or %NL80211_CMD_SET_STATION (only when + * %NL80211_FEATURE_FULL_AP_CLIENT_STATE is supported, or with TDLS); + * u8 attribute. + * + * @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if + * %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet) + * @NL80211_ATTR_VENDOR_SUBCMD: vendor sub-command + * @NL80211_ATTR_VENDOR_DATA: data for the vendor command, if any; this + * attribute is also used for vendor command feature advertisement + * @NL80211_ATTR_VENDOR_EVENTS: used for event list advertising in the wiphy + * info, containing a nested array of possible events + * + * @NL80211_ATTR_QOS_MAP: IP DSCP mapping for Interworking QoS mapping. This + * data is in the format defined for the payload of the QoS Map Set element + * in IEEE Std 802.11-2012, 8.4.2.97. + * + * @NL80211_ATTR_MAC_HINT: MAC address recommendation as initial BSS + * @NL80211_ATTR_WIPHY_FREQ_HINT: frequency of the recommended initial BSS + * + * @NL80211_ATTR_MAX_AP_ASSOC_STA: Device attribute that indicates how many + * associated stations are supported in AP mode (including P2P GO); u32. + * Since drivers may not have a fixed limit on the maximum number (e.g., + * other concurrent operations may affect this), drivers are allowed to + * advertise values that cannot always be met. In such cases, an attempt + * to add a new station entry with @NL80211_CMD_NEW_STATION may fail. + * + * @NL80211_ATTR_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which + * should be updated when the frame is transmitted. + * @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum + * supported number of csa counters. + * + * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32. + * As specified in the &enum nl80211_tdls_peer_capability. + * + * @NL80211_ATTR_SOCKET_OWNER: Flag attribute, if set during interface + * creation then the new interface will be owned by the netlink socket + * that created it and will be destroyed when the socket is closed. + * If set during scheduled scan start then the new scan req will be + * owned by the netlink socket that created it and the scheduled scan will + * be stopped when the socket is closed. + * If set during configuration of regulatory indoor operation then the + * regulatory indoor configuration would be owned by the netlink socket + * that configured the indoor setting, and the indoor operation would be + * cleared when the socket is closed. + * If set during NAN interface creation, the interface will be destroyed + * if the socket is closed just like any other interface. Moreover, NAN + * notifications will be sent in unicast to that socket. Without this + * attribute, the notifications will be sent to the %NL80211_MCGRP_NAN + * multicast group. + * If set during %NL80211_CMD_ASSOCIATE or %NL80211_CMD_CONNECT the + * station will deauthenticate when the socket is closed. + * If set during %NL80211_CMD_JOIN_IBSS the IBSS will be automatically + * torn down when the socket is closed. + * If set during %NL80211_CMD_JOIN_MESH the mesh setup will be + * automatically torn down when the socket is closed. + * If set during %NL80211_CMD_START_AP the AP will be automatically + * disabled when the socket is closed. + * + * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is + * the TDLS link initiator. + * + * @NL80211_ATTR_USE_RRM: flag for indicating whether the current connection + * shall support Radio Resource Measurements (11k). This attribute can be + * used with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests. + * User space applications are expected to use this flag only if the + * underlying device supports these minimal RRM features: + * %NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES, + * %NL80211_FEATURE_QUIET, + * Or, if global RRM is supported, see: + * %NL80211_EXT_FEATURE_RRM + * If this flag is used, driver must add the Power Capabilities IE to the + * association request. In addition, it must also set the RRM capability + * flag in the association request's Capability Info field. + * + * @NL80211_ATTR_WIPHY_DYN_ACK: flag attribute used to enable ACK timeout + * estimation algorithm (dynack). In order to activate dynack + * %NL80211_FEATURE_ACKTO_ESTIMATION feature flag must be set by lower + * drivers to indicate dynack capability. Dynack is automatically disabled + * setting valid value for coverage class. + * + * @NL80211_ATTR_TSID: a TSID value (u8 attribute) + * @NL80211_ATTR_USER_PRIO: user priority value (u8 attribute) + * @NL80211_ATTR_ADMITTED_TIME: admitted time in units of 32 microseconds + * (per second) (u16 attribute) + * + * @NL80211_ATTR_SMPS_MODE: SMPS mode to use (ap mode). see + * &enum nl80211_smps_mode. + * + * @NL80211_ATTR_OPER_CLASS: operating class + * + * @NL80211_ATTR_MAC_MASK: MAC address mask + * + * @NL80211_ATTR_WIPHY_SELF_MANAGED_REG: flag attribute indicating this device + * is self-managing its regulatory information and any regulatory domain + * obtained from it is coming from the device's wiphy and not the global + * cfg80211 regdomain. + * + * @NL80211_ATTR_EXT_FEATURES: extended feature flags contained in a byte + * array. The feature flags are identified by their bit index (see &enum + * nl80211_ext_feature_index). The bit index is ordered starting at the + * least-significant bit of the first byte in the array, ie. bit index 0 + * is located at bit 0 of byte 0. bit index 25 would be located at bit 1 + * of byte 3 (u8 array). + * + * @NL80211_ATTR_SURVEY_RADIO_STATS: Request overall radio statistics to be + * returned along with other survey data. If set, @NL80211_CMD_GET_SURVEY + * may return a survey entry without a channel indicating global radio + * statistics (only some values are valid and make sense.) + * For devices that don't return such an entry even then, the information + * should be contained in the result as the sum of the respective counters + * over all channels. + * + * @NL80211_ATTR_SCHED_SCAN_DELAY: delay before the first cycle of a + * scheduled scan is started. Or the delay before a WoWLAN + * net-detect scan is started, counting from the moment the + * system is suspended. This value is a u32, in seconds. + + * @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device + * is operating in an indoor environment. + * + * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS: maximum number of scan plans for + * scheduled scan supported by the device (u32), a wiphy attribute. + * @NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL: maximum interval (in seconds) for + * a scan plan (u32), a wiphy attribute. + * @NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS: maximum number of iterations in + * a scan plan (u32), a wiphy attribute. + * @NL80211_ATTR_SCHED_SCAN_PLANS: a list of scan plans for scheduled scan. + * Each scan plan defines the number of scan iterations and the interval + * between scans. The last scan plan will always run infinitely, + * thus it must not specify the number of iterations, only the interval + * between scans. The scan plans are executed sequentially. + * Each scan plan is a nested attribute of &enum nl80211_sched_scan_plan. + * @NL80211_ATTR_PBSS: flag attribute. If set it means operate + * in a PBSS. Specified in %NL80211_CMD_CONNECT to request + * connecting to a PCP, and in %NL80211_CMD_START_AP to start + * a PCP instead of AP. Relevant for DMG networks only. + * @NL80211_ATTR_BSS_SELECT: nested attribute for driver supporting the + * BSS selection feature. When used with %NL80211_CMD_GET_WIPHY it contains + * attributes according &enum nl80211_bss_select_attr to indicate what + * BSS selection behaviours are supported. When used with %NL80211_CMD_CONNECT + * it contains the behaviour-specific attribute containing the parameters for + * BSS selection to be done by driver and/or firmware. + * + * @NL80211_ATTR_STA_SUPPORT_P2P_PS: whether P2P PS mechanism supported + * or not. u8, one of the values of &enum nl80211_sta_p2p_ps_status + * + * @NL80211_ATTR_PAD: attribute used for padding for 64-bit alignment + * + * @NL80211_ATTR_IFTYPE_EXT_CAPA: Nested attribute of the following attributes: + * %NL80211_ATTR_IFTYPE, %NL80211_ATTR_EXT_CAPA, + * %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per + * interface type. + * + * @NL80211_ATTR_MU_MIMO_GROUP_DATA: array of 24 bytes that defines a MU-MIMO + * groupID for monitor mode. + * The first 8 bytes are a mask that defines the membership in each + * group (there are 64 groups, group 0 and 63 are reserved), + * each bit represents a group and set to 1 for being a member in + * that group and 0 for not being a member. + * The remaining 16 bytes define the position in each group: 2 bits for + * each group. + * (smaller group numbers represented on most significant bits and bigger + * group numbers on least significant bits.) + * This attribute is used only if all interfaces are in monitor mode. + * Set this attribute in order to monitor packets using the given MU-MIMO + * groupID data. + * to turn off that feature set all the bits of the groupID to zero. + * @NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR: mac address for the sniffer to follow + * when using MU-MIMO air sniffer. + * to turn that feature off set an invalid mac address + * (e.g. FF:FF:FF:FF:FF:FF) + * + * @NL80211_ATTR_SCAN_START_TIME_TSF: The time at which the scan was actually + * started (u64). The time is the TSF of the BSS the interface that + * requested the scan is connected to (if available, otherwise this + * attribute must not be included). + * @NL80211_ATTR_SCAN_START_TIME_TSF_BSSID: The BSS according to which + * %NL80211_ATTR_SCAN_START_TIME_TSF is set. + * @NL80211_ATTR_MEASUREMENT_DURATION: measurement duration in TUs (u16). If + * %NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY is not set, this is the + * maximum measurement duration allowed. This attribute is used with + * measurement requests. It can also be used with %NL80211_CMD_TRIGGER_SCAN + * if the scan is used for beacon report radio measurement. + * @NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY: flag attribute that indicates + * that the duration specified with %NL80211_ATTR_MEASUREMENT_DURATION is + * mandatory. If this flag is not set, the duration is the maximum duration + * and the actual measurement duration may be shorter. + * + * @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is + * used to pull the stored data for mesh peer in power save state. + * + * @NL80211_ATTR_NAN_MASTER_PREF: the master preference to be used by + * %NL80211_CMD_START_NAN and optionally with + * %NL80211_CMD_CHANGE_NAN_CONFIG. Its type is u8 and it can't be 0. + * Also, values 1 and 255 are reserved for certification purposes and + * should not be used during a normal device operation. + * @NL80211_ATTR_BANDS: operating bands configuration. This is a u32 + * bitmask of BIT(NL80211_BAND_*) as described in %enum + * nl80211_band. For instance, for NL80211_BAND_2GHZ, bit 0 + * would be set. This attribute is used with + * %NL80211_CMD_START_NAN and %NL80211_CMD_CHANGE_NAN_CONFIG, and + * it is optional. If no bands are set, it means don't-care and + * the device will decide what to use. + * @NL80211_ATTR_NAN_FUNC: a function that can be added to NAN. See + * &enum nl80211_nan_func_attributes for description of this nested + * attribute. + * @NL80211_ATTR_NAN_MATCH: used to report a match. This is a nested attribute. + * See &enum nl80211_nan_match_attributes. + * @NL80211_ATTR_FILS_KEK: KEK for FILS (Re)Association Request/Response frame + * protection. + * @NL80211_ATTR_FILS_NONCES: Nonces (part of AAD) for FILS (Re)Association + * Request/Response frame protection. This attribute contains the 16 octet + * STA Nonce followed by 16 octets of AP Nonce. + * + * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Indicates whether or not multicast + * packets should be send out as unicast to all stations (flag attribute). + * + * @NL80211_ATTR_BSSID: The BSSID of the AP. Note that %NL80211_ATTR_MAC is also + * used in various commands/events for specifying the BSSID. + * + * @NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI: Relative RSSI threshold by which + * other BSSs has to be better or slightly worse than the current + * connected BSS so that they get reported to user space. + * This will give an opportunity to userspace to consider connecting to + * other matching BSSs which have better or slightly worse RSSI than + * the current connected BSS by using an offloaded operation to avoid + * unnecessary wakeups. + * + * @NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST: When present the RSSI level for BSSs in + * the specified band is to be adjusted before doing + * %NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI based comparison to figure out + * better BSSs. The attribute value is a packed structure + * value as specified by &struct nl80211_bss_select_rssi_adjust. + * + * @NL80211_ATTR_TIMEOUT_REASON: The reason for which an operation timed out. + * u32 attribute with an &enum nl80211_timeout_reason value. This is used, + * e.g., with %NL80211_CMD_CONNECT event. + * + * @NL80211_ATTR_FILS_ERP_USERNAME: EAP Re-authentication Protocol (ERP) + * username part of NAI used to refer keys rRK and rIK. This is used with + * %NL80211_CMD_CONNECT. + * + * @NL80211_ATTR_FILS_ERP_REALM: EAP Re-authentication Protocol (ERP) realm part + * of NAI specifying the domain name of the ER server. This is used with + * %NL80211_CMD_CONNECT. + * + * @NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM: Unsigned 16-bit ERP next sequence number + * to use in ERP messages. This is used in generating the FILS wrapped data + * for FILS authentication and is used with %NL80211_CMD_CONNECT. + * + * @NL80211_ATTR_FILS_ERP_RRK: ERP re-authentication Root Key (rRK) for the + * NAI specified by %NL80211_ATTR_FILS_ERP_USERNAME and + * %NL80211_ATTR_FILS_ERP_REALM. This is used for generating rIK and rMSK + * from successful FILS authentication and is used with + * %NL80211_CMD_CONNECT. + * + * @NL80211_ATTR_FILS_CACHE_ID: A 2-octet identifier advertized by a FILS AP + * identifying the scope of PMKSAs. This is used with + * @NL80211_CMD_SET_PMKSA and @NL80211_CMD_DEL_PMKSA. + * + * @NL80211_ATTR_PMK: attribute for passing PMK key material. Used with + * %NL80211_CMD_SET_PMKSA for the PMKSA identified by %NL80211_ATTR_PMKID. + * For %NL80211_CMD_CONNECT it is used to provide PSK for offloading 4-way + * handshake for WPA/WPA2-PSK networks. For 802.1X authentication it is + * used with %NL80211_CMD_SET_PMK. For offloaded FT support this attribute + * specifies the PMK-R0 if NL80211_ATTR_PMKR0_NAME is included as well. + * + * @NL80211_ATTR_SCHED_SCAN_MULTI: flag attribute which user-space shall use to + * indicate that it supports multiple active scheduled scan requests. + * @NL80211_ATTR_SCHED_SCAN_MAX_REQS: indicates maximum number of scheduled + * scan request that may be active for the device (u32). + * + * @NL80211_ATTR_WANT_1X_4WAY_HS: flag attribute which user-space can include + * in %NL80211_CMD_CONNECT to indicate that for 802.1X authentication it + * wants to use the supported offload of the 4-way handshake. + * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT. + * @NL80211_ATTR_PORT_AUTHORIZED: (reserved) + * + * @NL80211_ATTR_EXTERNAL_AUTH_ACTION: Identify the requested external + * authentication operation (u32 attribute with an + * &enum nl80211_external_auth_action value). This is used with the + * %NL80211_CMD_EXTERNAL_AUTH request event. + * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user + * space supports external authentication. This attribute shall be used + * with %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP request. The driver + * may offload authentication processing to user space if this capability + * is indicated in the respective requests from the user space. + * + * @NL80211_ATTR_NSS: Station's New/updated RX_NSS value notified using this + * u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED. + * + * @NL80211_ATTR_TXQ_STATS: TXQ statistics (nested attribute, see &enum + * nl80211_txq_stats) + * @NL80211_ATTR_TXQ_LIMIT: Total packet limit for the TXQ queues for this phy. + * The smaller of this and the memory limit is enforced. + * @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory memory limit (in bytes) for the + * TXQ queues for this phy. The smaller of this and the packet limit is + * enforced. + * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes + * a flow is assigned on each round of the DRR scheduler. + * @NL80211_ATTR_HE_CAPABILITY: HE Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION). Can be set + * only if %NL80211_STA_FLAG_WME is set. + * + * @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include + * in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing + * measurement (FTM) responder functionality and containing parameters as + * possible, see &enum nl80211_ftm_responder_attr + * + * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder + * statistics, see &enum nl80211_ftm_responder_stats. + * + * @NL80211_ATTR_TIMEOUT: Timeout for the given operation in milliseconds (u32), + * if the attribute is not given no timeout is requested. Note that 0 is an + * invalid value. + * + * @NL80211_ATTR_PEER_MEASUREMENTS: peer measurements request (and result) + * data, uses nested attributes specified in + * &enum nl80211_peer_measurement_attrs. + * This is also used for capability advertisement in the wiphy information, + * with the appropriate sub-attributes. + * + * @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime + * scheduler. + * + * @NL80211_ATTR_STA_TX_POWER_SETTING: Transmit power setting type (u8) for + * station associated with the AP. See &enum nl80211_tx_power_setting for + * possible values. + * @NL80211_ATTR_STA_TX_POWER: Transmit power level (s16) in dBm units. This + * allows to set Tx power for a station. If this attribute is not included, + * the default per-interface tx power setting will be overriding. Driver + * should be picking up the lowest tx power, either tx power per-interface + * or per-station. + * + * @NL80211_ATTR_SAE_PASSWORD: attribute for passing SAE password material. It + * is used with %NL80211_CMD_CONNECT to provide password for offloading + * SAE authentication for WPA3-Personal networks. + * + * @NL80211_ATTR_TWT_RESPONDER: Enable target wait time responder support. + * + * @NL80211_ATTR_HE_OBSS_PD: nested attribute for OBSS Packet Detection + * functionality. + * + * @NL80211_ATTR_WIPHY_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz + * channel(s) that are allowed to be used for EDMG transmissions. + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251. (u8 attribute) + * @NL80211_ATTR_WIPHY_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes + * the allowed channel bandwidth configurations. (u8 attribute) + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13. + * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use + */ +enum nl80211_attrs { +/* don't change the order or add anything between, this is ABI! */ + NL80211_ATTR_UNSPEC, + + NL80211_ATTR_WIPHY, + NL80211_ATTR_WIPHY_NAME, + + NL80211_ATTR_IFINDEX, + NL80211_ATTR_IFNAME, + NL80211_ATTR_IFTYPE, + + NL80211_ATTR_MAC, + + NL80211_ATTR_KEY_DATA, + NL80211_ATTR_KEY_IDX, + NL80211_ATTR_KEY_CIPHER, + NL80211_ATTR_KEY_SEQ, + NL80211_ATTR_KEY_DEFAULT, + + NL80211_ATTR_BEACON_INTERVAL, + NL80211_ATTR_DTIM_PERIOD, + NL80211_ATTR_BEACON_HEAD, + NL80211_ATTR_BEACON_TAIL, + + NL80211_ATTR_STA_AID, + NL80211_ATTR_STA_FLAGS, + NL80211_ATTR_STA_LISTEN_INTERVAL, + NL80211_ATTR_STA_SUPPORTED_RATES, + NL80211_ATTR_STA_VLAN, + NL80211_ATTR_STA_INFO, + + NL80211_ATTR_WIPHY_BANDS, + + NL80211_ATTR_MNTR_FLAGS, + + NL80211_ATTR_MESH_ID, + NL80211_ATTR_STA_PLINK_ACTION, + NL80211_ATTR_MPATH_NEXT_HOP, + NL80211_ATTR_MPATH_INFO, + + NL80211_ATTR_BSS_CTS_PROT, + NL80211_ATTR_BSS_SHORT_PREAMBLE, + NL80211_ATTR_BSS_SHORT_SLOT_TIME, + + NL80211_ATTR_HT_CAPABILITY, + + NL80211_ATTR_SUPPORTED_IFTYPES, + + NL80211_ATTR_REG_ALPHA2, + NL80211_ATTR_REG_RULES, + + NL80211_ATTR_MESH_CONFIG, + + NL80211_ATTR_BSS_BASIC_RATES, + + NL80211_ATTR_WIPHY_TXQ_PARAMS, + NL80211_ATTR_WIPHY_FREQ, + NL80211_ATTR_WIPHY_CHANNEL_TYPE, + + NL80211_ATTR_KEY_DEFAULT_MGMT, + + NL80211_ATTR_MGMT_SUBTYPE, + NL80211_ATTR_IE, + + NL80211_ATTR_MAX_NUM_SCAN_SSIDS, + + NL80211_ATTR_SCAN_FREQUENCIES, + NL80211_ATTR_SCAN_SSIDS, + NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */ + NL80211_ATTR_BSS, + + NL80211_ATTR_REG_INITIATOR, + NL80211_ATTR_REG_TYPE, + + NL80211_ATTR_SUPPORTED_COMMANDS, + + NL80211_ATTR_FRAME, + NL80211_ATTR_SSID, + NL80211_ATTR_AUTH_TYPE, + NL80211_ATTR_REASON_CODE, + + NL80211_ATTR_KEY_TYPE, + + NL80211_ATTR_MAX_SCAN_IE_LEN, + NL80211_ATTR_CIPHER_SUITES, + + NL80211_ATTR_FREQ_BEFORE, + NL80211_ATTR_FREQ_AFTER, + + NL80211_ATTR_FREQ_FIXED, + + + NL80211_ATTR_WIPHY_RETRY_SHORT, + NL80211_ATTR_WIPHY_RETRY_LONG, + NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + NL80211_ATTR_WIPHY_RTS_THRESHOLD, + + NL80211_ATTR_TIMED_OUT, + + NL80211_ATTR_USE_MFP, + + NL80211_ATTR_STA_FLAGS2, + + NL80211_ATTR_CONTROL_PORT, + + NL80211_ATTR_TESTDATA, + + NL80211_ATTR_PRIVACY, + + NL80211_ATTR_DISCONNECTED_BY_AP, + NL80211_ATTR_STATUS_CODE, + + NL80211_ATTR_CIPHER_SUITES_PAIRWISE, + NL80211_ATTR_CIPHER_SUITE_GROUP, + NL80211_ATTR_WPA_VERSIONS, + NL80211_ATTR_AKM_SUITES, + + NL80211_ATTR_REQ_IE, + NL80211_ATTR_RESP_IE, + + NL80211_ATTR_PREV_BSSID, + + NL80211_ATTR_KEY, + NL80211_ATTR_KEYS, + + NL80211_ATTR_PID, + + NL80211_ATTR_4ADDR, + + NL80211_ATTR_SURVEY_INFO, + + NL80211_ATTR_PMKID, + NL80211_ATTR_MAX_NUM_PMKIDS, + + NL80211_ATTR_DURATION, + + NL80211_ATTR_COOKIE, + + NL80211_ATTR_WIPHY_COVERAGE_CLASS, + + NL80211_ATTR_TX_RATES, + + NL80211_ATTR_FRAME_MATCH, + + NL80211_ATTR_ACK, + + NL80211_ATTR_PS_STATE, + + NL80211_ATTR_CQM, + + NL80211_ATTR_LOCAL_STATE_CHANGE, + + NL80211_ATTR_AP_ISOLATE, + + NL80211_ATTR_WIPHY_TX_POWER_SETTING, + NL80211_ATTR_WIPHY_TX_POWER_LEVEL, + + NL80211_ATTR_TX_FRAME_TYPES, + NL80211_ATTR_RX_FRAME_TYPES, + NL80211_ATTR_FRAME_TYPE, + + NL80211_ATTR_CONTROL_PORT_ETHERTYPE, + NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, + + NL80211_ATTR_SUPPORT_IBSS_RSN, + + NL80211_ATTR_WIPHY_ANTENNA_TX, + NL80211_ATTR_WIPHY_ANTENNA_RX, + + NL80211_ATTR_MCAST_RATE, + + NL80211_ATTR_OFFCHANNEL_TX_OK, + + NL80211_ATTR_BSS_HT_OPMODE, + + NL80211_ATTR_KEY_DEFAULT_TYPES, + + NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, + + NL80211_ATTR_MESH_SETUP, + + NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, + NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, + + NL80211_ATTR_SUPPORT_MESH_AUTH, + NL80211_ATTR_STA_PLINK_STATE, + + NL80211_ATTR_WOWLAN_TRIGGERS, + NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, + + NL80211_ATTR_SCHED_SCAN_INTERVAL, + + NL80211_ATTR_INTERFACE_COMBINATIONS, + NL80211_ATTR_SOFTWARE_IFTYPES, + + NL80211_ATTR_REKEY_DATA, + + NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, + NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, + + NL80211_ATTR_SCAN_SUPP_RATES, + + NL80211_ATTR_HIDDEN_SSID, + + NL80211_ATTR_IE_PROBE_RESP, + NL80211_ATTR_IE_ASSOC_RESP, + + NL80211_ATTR_STA_WME, + NL80211_ATTR_SUPPORT_AP_UAPSD, + + NL80211_ATTR_ROAM_SUPPORT, + + NL80211_ATTR_SCHED_SCAN_MATCH, + NL80211_ATTR_MAX_MATCH_SETS, + + NL80211_ATTR_PMKSA_CANDIDATE, + + NL80211_ATTR_TX_NO_CCK_RATE, + + NL80211_ATTR_TDLS_ACTION, + NL80211_ATTR_TDLS_DIALOG_TOKEN, + NL80211_ATTR_TDLS_OPERATION, + NL80211_ATTR_TDLS_SUPPORT, + NL80211_ATTR_TDLS_EXTERNAL_SETUP, + + NL80211_ATTR_DEVICE_AP_SME, + + NL80211_ATTR_DONT_WAIT_FOR_ACK, + + NL80211_ATTR_FEATURE_FLAGS, + + NL80211_ATTR_PROBE_RESP_OFFLOAD, + + NL80211_ATTR_PROBE_RESP, + + NL80211_ATTR_DFS_REGION, + + NL80211_ATTR_DISABLE_HT, + NL80211_ATTR_HT_CAPABILITY_MASK, + + NL80211_ATTR_NOACK_MAP, + + NL80211_ATTR_INACTIVITY_TIMEOUT, + + NL80211_ATTR_RX_SIGNAL_DBM, + + NL80211_ATTR_BG_SCAN_PERIOD, + + NL80211_ATTR_WDEV, + + NL80211_ATTR_USER_REG_HINT_TYPE, + + NL80211_ATTR_CONN_FAILED_REASON, + + NL80211_ATTR_AUTH_DATA, + + NL80211_ATTR_VHT_CAPABILITY, + + NL80211_ATTR_SCAN_FLAGS, + + NL80211_ATTR_CHANNEL_WIDTH, + NL80211_ATTR_CENTER_FREQ1, + NL80211_ATTR_CENTER_FREQ2, + + NL80211_ATTR_P2P_CTWINDOW, + NL80211_ATTR_P2P_OPPPS, + + NL80211_ATTR_LOCAL_MESH_POWER_MODE, + + NL80211_ATTR_ACL_POLICY, + + NL80211_ATTR_MAC_ADDRS, + + NL80211_ATTR_MAC_ACL_MAX, + + NL80211_ATTR_RADAR_EVENT, + + NL80211_ATTR_EXT_CAPA, + NL80211_ATTR_EXT_CAPA_MASK, + + NL80211_ATTR_STA_CAPABILITY, + NL80211_ATTR_STA_EXT_CAPABILITY, + + NL80211_ATTR_PROTOCOL_FEATURES, + NL80211_ATTR_SPLIT_WIPHY_DUMP, + + NL80211_ATTR_DISABLE_VHT, + NL80211_ATTR_VHT_CAPABILITY_MASK, + + NL80211_ATTR_MDID, + NL80211_ATTR_IE_RIC, + + NL80211_ATTR_CRIT_PROT_ID, + NL80211_ATTR_MAX_CRIT_PROT_DURATION, + + NL80211_ATTR_PEER_AID, + + NL80211_ATTR_COALESCE_RULE, + + NL80211_ATTR_CH_SWITCH_COUNT, + NL80211_ATTR_CH_SWITCH_BLOCK_TX, + NL80211_ATTR_CSA_IES, + NL80211_ATTR_CSA_C_OFF_BEACON, + NL80211_ATTR_CSA_C_OFF_PRESP, + + NL80211_ATTR_RXMGMT_FLAGS, + + NL80211_ATTR_STA_SUPPORTED_CHANNELS, + + NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES, + + NL80211_ATTR_HANDLE_DFS, + + NL80211_ATTR_SUPPORT_5_MHZ, + NL80211_ATTR_SUPPORT_10_MHZ, + + NL80211_ATTR_OPMODE_NOTIF, + + NL80211_ATTR_VENDOR_ID, + NL80211_ATTR_VENDOR_SUBCMD, + NL80211_ATTR_VENDOR_DATA, + NL80211_ATTR_VENDOR_EVENTS, + + NL80211_ATTR_QOS_MAP, + + NL80211_ATTR_MAC_HINT, + NL80211_ATTR_WIPHY_FREQ_HINT, + + NL80211_ATTR_MAX_AP_ASSOC_STA, + + NL80211_ATTR_TDLS_PEER_CAPABILITY, + + NL80211_ATTR_SOCKET_OWNER, + + NL80211_ATTR_CSA_C_OFFSETS_TX, + NL80211_ATTR_MAX_CSA_COUNTERS, + + NL80211_ATTR_TDLS_INITIATOR, + + NL80211_ATTR_USE_RRM, + + NL80211_ATTR_WIPHY_DYN_ACK, + + NL80211_ATTR_TSID, + NL80211_ATTR_USER_PRIO, + NL80211_ATTR_ADMITTED_TIME, + + NL80211_ATTR_SMPS_MODE, + + NL80211_ATTR_OPER_CLASS, + + NL80211_ATTR_MAC_MASK, + + NL80211_ATTR_WIPHY_SELF_MANAGED_REG, + + NL80211_ATTR_EXT_FEATURES, + + NL80211_ATTR_SURVEY_RADIO_STATS, + + NL80211_ATTR_NETNS_FD, + + NL80211_ATTR_SCHED_SCAN_DELAY, + + NL80211_ATTR_REG_INDOOR, + + NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS, + NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL, + NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS, + NL80211_ATTR_SCHED_SCAN_PLANS, + + NL80211_ATTR_PBSS, + + NL80211_ATTR_BSS_SELECT, + + NL80211_ATTR_STA_SUPPORT_P2P_PS, + + NL80211_ATTR_PAD, + + NL80211_ATTR_IFTYPE_EXT_CAPA, + + NL80211_ATTR_MU_MIMO_GROUP_DATA, + NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR, + + NL80211_ATTR_SCAN_START_TIME_TSF, + NL80211_ATTR_SCAN_START_TIME_TSF_BSSID, + NL80211_ATTR_MEASUREMENT_DURATION, + NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY, + + NL80211_ATTR_MESH_PEER_AID, + + NL80211_ATTR_NAN_MASTER_PREF, + NL80211_ATTR_BANDS, + NL80211_ATTR_NAN_FUNC, + NL80211_ATTR_NAN_MATCH, + + NL80211_ATTR_FILS_KEK, + NL80211_ATTR_FILS_NONCES, + + NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED, + + NL80211_ATTR_BSSID, + + NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI, + NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST, + + NL80211_ATTR_TIMEOUT_REASON, + + NL80211_ATTR_FILS_ERP_USERNAME, + NL80211_ATTR_FILS_ERP_REALM, + NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM, + NL80211_ATTR_FILS_ERP_RRK, + NL80211_ATTR_FILS_CACHE_ID, + + NL80211_ATTR_PMK, + + NL80211_ATTR_SCHED_SCAN_MULTI, + NL80211_ATTR_SCHED_SCAN_MAX_REQS, + + NL80211_ATTR_WANT_1X_4WAY_HS, + NL80211_ATTR_PMKR0_NAME, + NL80211_ATTR_PORT_AUTHORIZED, + + NL80211_ATTR_EXTERNAL_AUTH_ACTION, + NL80211_ATTR_EXTERNAL_AUTH_SUPPORT, + + NL80211_ATTR_NSS, + NL80211_ATTR_ACK_SIGNAL, + + NL80211_ATTR_CONTROL_PORT_OVER_NL80211, + + NL80211_ATTR_TXQ_STATS, + NL80211_ATTR_TXQ_LIMIT, + NL80211_ATTR_TXQ_MEMORY_LIMIT, + NL80211_ATTR_TXQ_QUANTUM, + + NL80211_ATTR_HE_CAPABILITY, + + NL80211_ATTR_FTM_RESPONDER, + + NL80211_ATTR_FTM_RESPONDER_STATS, + + NL80211_ATTR_TIMEOUT, + + NL80211_ATTR_PEER_MEASUREMENTS, + + NL80211_ATTR_AIRTIME_WEIGHT, + NL80211_ATTR_STA_TX_POWER_SETTING, + NL80211_ATTR_STA_TX_POWER, + + NL80211_ATTR_SAE_PASSWORD, + + NL80211_ATTR_TWT_RESPONDER, + + NL80211_ATTR_HE_OBSS_PD, + + NL80211_ATTR_WIPHY_EDMG_CHANNELS, + NL80211_ATTR_WIPHY_EDMG_BW_CONFIG, + + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, + NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST, + NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 +}; + +/* source-level API compatibility */ +#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION +#define NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG +#define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER +#define NL80211_ATTR_SAE_DATA NL80211_ATTR_AUTH_DATA + +/* + * Allow user space programs to use #ifdef on new attributes by defining them + * here + */ +#define NL80211_CMD_CONNECT NL80211_CMD_CONNECT +#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY +#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES +#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS +#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ +#define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE +#define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE +#define NL80211_ATTR_IE NL80211_ATTR_IE +#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR +#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE +#define NL80211_ATTR_FRAME NL80211_ATTR_FRAME +#define NL80211_ATTR_SSID NL80211_ATTR_SSID +#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE +#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE +#define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE +#define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP +#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS +#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES +#define NL80211_ATTR_KEY NL80211_ATTR_KEY +#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS +#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS + +#define NL80211_WIPHY_NAME_MAXLEN 64 + +#define NL80211_MAX_SUPP_RATES 32 +#define NL80211_MAX_SUPP_HT_RATES 77 +#define NL80211_MAX_SUPP_REG_RULES 128 +#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 +#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 +#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 +#define NL80211_HT_CAPABILITY_LEN 26 +#define NL80211_VHT_CAPABILITY_LEN 12 +#define NL80211_HE_MIN_CAPABILITY_LEN 16 +#define NL80211_HE_MAX_CAPABILITY_LEN 54 +#define NL80211_MAX_NR_CIPHER_SUITES 5 +#define NL80211_MAX_NR_AKM_SUITES 2 + +#define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10 + +/* default RSSI threshold for scan results if none specified. */ +#define NL80211_SCAN_RSSI_THOLD_OFF -300 + +#define NL80211_CQM_TXE_MAX_INTVL 1800 + +/** + * enum nl80211_iftype - (virtual) interface types + * + * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides + * @NL80211_IFTYPE_ADHOC: independent BSS member + * @NL80211_IFTYPE_STATION: managed BSS member + * @NL80211_IFTYPE_AP: access point + * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points; VLAN interfaces + * are a bit special in that they must always be tied to a pre-existing + * AP type interface. + * @NL80211_IFTYPE_WDS: wireless distribution interface + * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames + * @NL80211_IFTYPE_MESH_POINT: mesh point + * @NL80211_IFTYPE_P2P_CLIENT: P2P client + * @NL80211_IFTYPE_P2P_GO: P2P group owner + * @NL80211_IFTYPE_P2P_DEVICE: P2P device interface type, this is not a netdev + * and therefore can't be created in the normal ways, use the + * %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE + * commands to create and destroy one + * @NL80211_IF_TYPE_OCB: Outside Context of a BSS + * This mode corresponds to the MIB variable dot11OCBActivated=true + * @NL80211_IFTYPE_NAN: NAN device interface type (not a netdev) + * @NL80211_IFTYPE_MAX: highest interface type number currently defined + * @NUM_NL80211_IFTYPES: number of defined interface types + * + * These values are used with the %NL80211_ATTR_IFTYPE + * to set the type of an interface. + * + */ +enum nl80211_iftype { + NL80211_IFTYPE_UNSPECIFIED, + NL80211_IFTYPE_ADHOC, + NL80211_IFTYPE_STATION, + NL80211_IFTYPE_AP, + NL80211_IFTYPE_AP_VLAN, + NL80211_IFTYPE_WDS, + NL80211_IFTYPE_MONITOR, + NL80211_IFTYPE_MESH_POINT, + NL80211_IFTYPE_P2P_CLIENT, + NL80211_IFTYPE_P2P_GO, + NL80211_IFTYPE_P2P_DEVICE, + NL80211_IFTYPE_OCB, + NL80211_IFTYPE_NAN, + + /* keep last */ + NUM_NL80211_IFTYPES, + NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1 +}; + +/** + * enum nl80211_sta_flags - station flags + * + * Station flags. When a station is added to an AP interface, it is + * assumed to be already associated (and hence authenticated.) + * + * @__NL80211_STA_FLAG_INVALID: attribute number 0 is reserved + * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) + * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames + * with short barker preamble + * @NL80211_STA_FLAG_WME: station is WME/QoS capable + * @NL80211_STA_FLAG_MFP: station uses management frame protection + * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated + * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer -- this flag should + * only be used in managed mode (even in the flags mask). Note that the + * flag can't be changed, it is only valid while adding a station, and + * attempts to change it will silently be ignored (rather than rejected + * as errors.) + * @NL80211_STA_FLAG_ASSOCIATED: station is associated; used with drivers + * that support %NL80211_FEATURE_FULL_AP_CLIENT_STATE to transition a + * previously added station into associated state + * @NL80211_STA_FLAG_MAX: highest station flag number currently defined + * @__NL80211_STA_FLAG_AFTER_LAST: internal use + */ +enum nl80211_sta_flags { + __NL80211_STA_FLAG_INVALID, + NL80211_STA_FLAG_AUTHORIZED, + NL80211_STA_FLAG_SHORT_PREAMBLE, + NL80211_STA_FLAG_WME, + NL80211_STA_FLAG_MFP, + NL80211_STA_FLAG_AUTHENTICATED, + NL80211_STA_FLAG_TDLS_PEER, + NL80211_STA_FLAG_ASSOCIATED, + + /* keep last */ + __NL80211_STA_FLAG_AFTER_LAST, + NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 +}; + +/** + * enum nl80211_sta_p2p_ps_status - station support of P2P PS + * + * @NL80211_P2P_PS_UNSUPPORTED: station doesn't support P2P PS mechanism + * @@NL80211_P2P_PS_SUPPORTED: station supports P2P PS mechanism + * @NUM_NL80211_P2P_PS_STATUS: number of values + */ +enum nl80211_sta_p2p_ps_status { + NL80211_P2P_PS_UNSUPPORTED = 0, + NL80211_P2P_PS_SUPPORTED, + + NUM_NL80211_P2P_PS_STATUS, +}; + +#define NL80211_STA_FLAG_MAX_OLD_API NL80211_STA_FLAG_TDLS_PEER + +/** + * struct nl80211_sta_flag_update - station flags mask/set + * @mask: mask of station flags to set + * @set: which values to set them to + * + * Both mask and set contain bits as per &enum nl80211_sta_flags. + */ +struct nl80211_sta_flag_update { + __u32 mask; + __u32 set; +} __attribute__((packed)); + +/** + * enum nl80211_he_gi - HE guard interval + * @NL80211_RATE_INFO_HE_GI_0_8: 0.8 usec + * @NL80211_RATE_INFO_HE_GI_1_6: 1.6 usec + * @NL80211_RATE_INFO_HE_GI_3_2: 3.2 usec + */ +enum nl80211_he_gi { + NL80211_RATE_INFO_HE_GI_0_8, + NL80211_RATE_INFO_HE_GI_1_6, + NL80211_RATE_INFO_HE_GI_3_2, +}; + +/** + * enum nl80211_he_ru_alloc - HE RU allocation values + * @NL80211_RATE_INFO_HE_RU_ALLOC_26: 26-tone RU allocation + * @NL80211_RATE_INFO_HE_RU_ALLOC_52: 52-tone RU allocation + * @NL80211_RATE_INFO_HE_RU_ALLOC_106: 106-tone RU allocation + * @NL80211_RATE_INFO_HE_RU_ALLOC_242: 242-tone RU allocation + * @NL80211_RATE_INFO_HE_RU_ALLOC_484: 484-tone RU allocation + * @NL80211_RATE_INFO_HE_RU_ALLOC_996: 996-tone RU allocation + * @NL80211_RATE_INFO_HE_RU_ALLOC_2x996: 2x996-tone RU allocation + */ +enum nl80211_he_ru_alloc { + NL80211_RATE_INFO_HE_RU_ALLOC_26, + NL80211_RATE_INFO_HE_RU_ALLOC_52, + NL80211_RATE_INFO_HE_RU_ALLOC_106, + NL80211_RATE_INFO_HE_RU_ALLOC_242, + NL80211_RATE_INFO_HE_RU_ALLOC_484, + NL80211_RATE_INFO_HE_RU_ALLOC_996, + NL80211_RATE_INFO_HE_RU_ALLOC_2x996, +}; + +/** + * enum nl80211_rate_info - bitrate information + * + * These attribute types are used with %NL80211_STA_INFO_TXRATE + * when getting information about the bitrate of a station. + * There are 2 attributes for bitrate, a legacy one that represents + * a 16-bit value, and new one that represents a 32-bit value. + * If the rate value fits into 16 bit, both attributes are reported + * with the same value. If the rate is too high to fit into 16 bits + * (>6.5535Gbps) only 32-bit attribute is included. + * User space tools encouraged to use the 32-bit attribute and fall + * back to the 16-bit one for compatibility with older kernels. + * + * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved + * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) + * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) + * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 MHz dualchannel bitrate + * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval + * @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s) + * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined + * @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8) + * @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8) + * @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate + * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: unused - 80+80 is treated the + * same as 160 for purposes of the bitrates + * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate + * @NL80211_RATE_INFO_10_MHZ_WIDTH: 10 MHz width - note that this is + * a legacy rate and will be reported as the actual bitrate, i.e. + * half the base (20 MHz) rate + * @NL80211_RATE_INFO_5_MHZ_WIDTH: 5 MHz width - note that this is + * a legacy rate and will be reported as the actual bitrate, i.e. + * a quarter of the base (20 MHz) rate + * @NL80211_RATE_INFO_HE_MCS: HE MCS index (u8, 0-11) + * @NL80211_RATE_INFO_HE_NSS: HE NSS value (u8, 1-8) + * @NL80211_RATE_INFO_HE_GI: HE guard interval identifier + * (u8, see &enum nl80211_he_gi) + * @NL80211_RATE_INFO_HE_DCM: HE DCM value (u8, 0/1) + * @NL80211_RATE_INFO_RU_ALLOC: HE RU allocation, if not present then + * non-OFDMA was used (u8, see &enum nl80211_he_ru_alloc) + * @__NL80211_RATE_INFO_AFTER_LAST: internal use + */ +enum nl80211_rate_info { + __NL80211_RATE_INFO_INVALID, + NL80211_RATE_INFO_BITRATE, + NL80211_RATE_INFO_MCS, + NL80211_RATE_INFO_40_MHZ_WIDTH, + NL80211_RATE_INFO_SHORT_GI, + NL80211_RATE_INFO_BITRATE32, + NL80211_RATE_INFO_VHT_MCS, + NL80211_RATE_INFO_VHT_NSS, + NL80211_RATE_INFO_80_MHZ_WIDTH, + NL80211_RATE_INFO_80P80_MHZ_WIDTH, + NL80211_RATE_INFO_160_MHZ_WIDTH, + NL80211_RATE_INFO_10_MHZ_WIDTH, + NL80211_RATE_INFO_5_MHZ_WIDTH, + NL80211_RATE_INFO_HE_MCS, + NL80211_RATE_INFO_HE_NSS, + NL80211_RATE_INFO_HE_GI, + NL80211_RATE_INFO_HE_DCM, + NL80211_RATE_INFO_HE_RU_ALLOC, + + /* keep last */ + __NL80211_RATE_INFO_AFTER_LAST, + NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 +}; + +/** + * enum nl80211_sta_bss_param - BSS information collected by STA + * + * These attribute types are used with %NL80211_STA_INFO_BSS_PARAM + * when getting information about the bitrate of a station. + * + * @__NL80211_STA_BSS_PARAM_INVALID: attribute number 0 is reserved + * @NL80211_STA_BSS_PARAM_CTS_PROT: whether CTS protection is enabled (flag) + * @NL80211_STA_BSS_PARAM_SHORT_PREAMBLE: whether short preamble is enabled + * (flag) + * @NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME: whether short slot time is enabled + * (flag) + * @NL80211_STA_BSS_PARAM_DTIM_PERIOD: DTIM period for beaconing (u8) + * @NL80211_STA_BSS_PARAM_BEACON_INTERVAL: Beacon interval (u16) + * @NL80211_STA_BSS_PARAM_MAX: highest sta_bss_param number currently defined + * @__NL80211_STA_BSS_PARAM_AFTER_LAST: internal use + */ +enum nl80211_sta_bss_param { + __NL80211_STA_BSS_PARAM_INVALID, + NL80211_STA_BSS_PARAM_CTS_PROT, + NL80211_STA_BSS_PARAM_SHORT_PREAMBLE, + NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME, + NL80211_STA_BSS_PARAM_DTIM_PERIOD, + NL80211_STA_BSS_PARAM_BEACON_INTERVAL, + + /* keep last */ + __NL80211_STA_BSS_PARAM_AFTER_LAST, + NL80211_STA_BSS_PARAM_MAX = __NL80211_STA_BSS_PARAM_AFTER_LAST - 1 +}; + +/** + * enum nl80211_sta_info - station information + * + * These attribute types are used with %NL80211_ATTR_STA_INFO + * when getting information about a station. + * + * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved + * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) + * @NL80211_STA_INFO_RX_BYTES: total received bytes (MPDU length) + * (u32, from this station) + * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (MPDU length) + * (u32, to this station) + * @NL80211_STA_INFO_RX_BYTES64: total received bytes (MPDU length) + * (u64, from this station) + * @NL80211_STA_INFO_TX_BYTES64: total transmitted bytes (MPDU length) + * (u64, to this station) + * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute + * containing info as possible, see &enum nl80211_rate_info + * @NL80211_STA_INFO_RX_PACKETS: total received packet (MSDUs and MMPDUs) + * (u32, from this station) + * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (MSDUs and MMPDUs) + * (u32, to this station) + * @NL80211_STA_INFO_TX_RETRIES: total retries (MPDUs) (u32, to this station) + * @NL80211_STA_INFO_TX_FAILED: total failed packets (MPDUs) + * (u32, to this station) + * @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm) + * @NL80211_STA_INFO_LLID: the station's mesh LLID + * @NL80211_STA_INFO_PLID: the station's mesh PLID + * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station + * (see %enum nl80211_plink_state) + * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested + * attribute, like NL80211_STA_INFO_TX_BITRATE. + * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute + * containing info as possible, see &enum nl80211_sta_bss_param + * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected + * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. + * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32) + * @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64) + * @NL80211_STA_INFO_LOCAL_PM: local mesh STA link-specific power mode + * @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode + * @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards + * non-peer STA + * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU + * Contains a nested array of signal strength attributes (u8, dBm) + * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average + * Same format as NL80211_STA_INFO_CHAIN_SIGNAL. + * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the + * 802.11 header (u32, kbps) + * @NL80211_STA_INFO_RX_DROP_MISC: RX packets dropped for unspecified reasons + * (u64) + * @NL80211_STA_INFO_BEACON_RX: number of beacons received from this peer (u64) + * @NL80211_STA_INFO_BEACON_SIGNAL_AVG: signal strength average + * for beacons only (u8, dBm) + * @NL80211_STA_INFO_TID_STATS: per-TID statistics (see &enum nl80211_tid_stats) + * This is a nested attribute where each the inner attribute number is the + * TID+1 and the special TID 16 (i.e. value 17) is used for non-QoS frames; + * each one of those is again nested with &enum nl80211_tid_stats + * attributes carrying the actual values. + * @NL80211_STA_INFO_RX_DURATION: aggregate PPDU duration for all frames + * received from the station (u64, usec) + * @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment + * @NL80211_STA_INFO_ACK_SIGNAL: signal strength of the last ACK frame(u8, dBm) + * @NL80211_STA_INFO_ACK_SIGNAL_AVG: avg signal strength of ACK frames (s8, dBm) + * @NL80211_STA_INFO_RX_MPDUS: total number of received packets (MPDUs) + * (u32, from this station) + * @NL80211_STA_INFO_FCS_ERROR_COUNT: total number of packets (MPDUs) received + * with an FCS error (u32, from this station). This count may not include + * some packets with an FCS error due to TA corruption. Hence this counter + * might not be fully accurate. + * @NL80211_STA_INFO_CONNECTED_TO_GATE: set to true if STA has a path to a + * mesh gate (u8, 0 or 1) + * @NL80211_STA_INFO_TX_DURATION: aggregate PPDU duration for all frames + * sent to the station (u64, usec) + * @NL80211_STA_INFO_AIRTIME_WEIGHT: current airtime weight for station (u16) + * @NL80211_STA_INFO_AIRTIME_LINK_METRIC: airtime link metric for mesh station + * @NL80211_STA_INFO_ASSOC_AT_BOOTTIME: Timestamp (CLOCK_BOOTTIME, nanoseconds) + * of STA's association + * @__NL80211_STA_INFO_AFTER_LAST: internal + * @NL80211_STA_INFO_MAX: highest possible station info attribute + */ +enum nl80211_sta_info { + __NL80211_STA_INFO_INVALID, + NL80211_STA_INFO_INACTIVE_TIME, + NL80211_STA_INFO_RX_BYTES, + NL80211_STA_INFO_TX_BYTES, + NL80211_STA_INFO_LLID, + NL80211_STA_INFO_PLID, + NL80211_STA_INFO_PLINK_STATE, + NL80211_STA_INFO_SIGNAL, + NL80211_STA_INFO_TX_BITRATE, + NL80211_STA_INFO_RX_PACKETS, + NL80211_STA_INFO_TX_PACKETS, + NL80211_STA_INFO_TX_RETRIES, + NL80211_STA_INFO_TX_FAILED, + NL80211_STA_INFO_SIGNAL_AVG, + NL80211_STA_INFO_RX_BITRATE, + NL80211_STA_INFO_BSS_PARAM, + NL80211_STA_INFO_CONNECTED_TIME, + NL80211_STA_INFO_STA_FLAGS, + NL80211_STA_INFO_BEACON_LOSS, + NL80211_STA_INFO_T_OFFSET, + NL80211_STA_INFO_LOCAL_PM, + NL80211_STA_INFO_PEER_PM, + NL80211_STA_INFO_NONPEER_PM, + NL80211_STA_INFO_RX_BYTES64, + NL80211_STA_INFO_TX_BYTES64, + NL80211_STA_INFO_CHAIN_SIGNAL, + NL80211_STA_INFO_CHAIN_SIGNAL_AVG, + NL80211_STA_INFO_EXPECTED_THROUGHPUT, + NL80211_STA_INFO_RX_DROP_MISC, + NL80211_STA_INFO_BEACON_RX, + NL80211_STA_INFO_BEACON_SIGNAL_AVG, + NL80211_STA_INFO_TID_STATS, + NL80211_STA_INFO_RX_DURATION, + NL80211_STA_INFO_PAD, + NL80211_STA_INFO_ACK_SIGNAL, + NL80211_STA_INFO_ACK_SIGNAL_AVG, + NL80211_STA_INFO_RX_MPDUS, + NL80211_STA_INFO_FCS_ERROR_COUNT, + NL80211_STA_INFO_CONNECTED_TO_GATE, + NL80211_STA_INFO_TX_DURATION, + NL80211_STA_INFO_AIRTIME_WEIGHT, + NL80211_STA_INFO_AIRTIME_LINK_METRIC, + NL80211_STA_INFO_ASSOC_AT_BOOTTIME, + + /* keep last */ + __NL80211_STA_INFO_AFTER_LAST, + NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1 +}; + +/* we renamed this - stay compatible */ +#define NL80211_STA_INFO_DATA_ACK_SIGNAL_AVG NL80211_STA_INFO_ACK_SIGNAL_AVG + + +/** + * enum nl80211_tid_stats - per TID statistics attributes + * @__NL80211_TID_STATS_INVALID: attribute number 0 is reserved + * @NL80211_TID_STATS_RX_MSDU: number of MSDUs received (u64) + * @NL80211_TID_STATS_TX_MSDU: number of MSDUs transmitted (or + * attempted to transmit; u64) + * @NL80211_TID_STATS_TX_MSDU_RETRIES: number of retries for + * transmitted MSDUs (not counting the first attempt; u64) + * @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted + * MSDUs (u64) + * @NL80211_TID_STATS_PAD: attribute used for padding for 64-bit alignment + * @NL80211_TID_STATS_TXQ_STATS: TXQ stats (nested attribute) + * @NUM_NL80211_TID_STATS: number of attributes here + * @NL80211_TID_STATS_MAX: highest numbered attribute here + */ +enum nl80211_tid_stats { + __NL80211_TID_STATS_INVALID, + NL80211_TID_STATS_RX_MSDU, + NL80211_TID_STATS_TX_MSDU, + NL80211_TID_STATS_TX_MSDU_RETRIES, + NL80211_TID_STATS_TX_MSDU_FAILED, + NL80211_TID_STATS_PAD, + NL80211_TID_STATS_TXQ_STATS, + + /* keep last */ + NUM_NL80211_TID_STATS, + NL80211_TID_STATS_MAX = NUM_NL80211_TID_STATS - 1 +}; + +/** + * enum nl80211_txq_stats - per TXQ statistics attributes + * @__NL80211_TXQ_STATS_INVALID: attribute number 0 is reserved + * @NUM_NL80211_TXQ_STATS: number of attributes here + * @NL80211_TXQ_STATS_BACKLOG_BYTES: number of bytes currently backlogged + * @NL80211_TXQ_STATS_BACKLOG_PACKETS: number of packets currently + * backlogged + * @NL80211_TXQ_STATS_FLOWS: total number of new flows seen + * @NL80211_TXQ_STATS_DROPS: total number of packet drops + * @NL80211_TXQ_STATS_ECN_MARKS: total number of packet ECN marks + * @NL80211_TXQ_STATS_OVERLIMIT: number of drops due to queue space overflow + * @NL80211_TXQ_STATS_OVERMEMORY: number of drops due to memory limit overflow + * (only for per-phy stats) + * @NL80211_TXQ_STATS_COLLISIONS: number of hash collisions + * @NL80211_TXQ_STATS_TX_BYTES: total number of bytes dequeued from TXQ + * @NL80211_TXQ_STATS_TX_PACKETS: total number of packets dequeued from TXQ + * @NL80211_TXQ_STATS_MAX_FLOWS: number of flow buckets for PHY + * @NL80211_TXQ_STATS_MAX: highest numbered attribute here + */ +enum nl80211_txq_stats { + __NL80211_TXQ_STATS_INVALID, + NL80211_TXQ_STATS_BACKLOG_BYTES, + NL80211_TXQ_STATS_BACKLOG_PACKETS, + NL80211_TXQ_STATS_FLOWS, + NL80211_TXQ_STATS_DROPS, + NL80211_TXQ_STATS_ECN_MARKS, + NL80211_TXQ_STATS_OVERLIMIT, + NL80211_TXQ_STATS_OVERMEMORY, + NL80211_TXQ_STATS_COLLISIONS, + NL80211_TXQ_STATS_TX_BYTES, + NL80211_TXQ_STATS_TX_PACKETS, + NL80211_TXQ_STATS_MAX_FLOWS, + + /* keep last */ + NUM_NL80211_TXQ_STATS, + NL80211_TXQ_STATS_MAX = NUM_NL80211_TXQ_STATS - 1 +}; + +/** + * enum nl80211_mpath_flags - nl80211 mesh path flags + * + * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active + * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running + * @NL80211_MPATH_FLAG_SN_VALID: the mesh path contains a valid SN + * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set + * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded + */ +enum nl80211_mpath_flags { + NL80211_MPATH_FLAG_ACTIVE = 1<<0, + NL80211_MPATH_FLAG_RESOLVING = 1<<1, + NL80211_MPATH_FLAG_SN_VALID = 1<<2, + NL80211_MPATH_FLAG_FIXED = 1<<3, + NL80211_MPATH_FLAG_RESOLVED = 1<<4, +}; + +/** + * enum nl80211_mpath_info - mesh path information + * + * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting + * information about a mesh path. + * + * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved + * @NL80211_MPATH_INFO_FRAME_QLEN: number of queued frames for this destination + * @NL80211_MPATH_INFO_SN: destination sequence number + * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path + * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now + * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in + * &enum nl80211_mpath_flags; + * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec + * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries + * @NL80211_MPATH_INFO_HOP_COUNT: hop count to destination + * @NL80211_MPATH_INFO_PATH_CHANGE: total number of path changes to destination + * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number + * currently defined + * @__NL80211_MPATH_INFO_AFTER_LAST: internal use + */ +enum nl80211_mpath_info { + __NL80211_MPATH_INFO_INVALID, + NL80211_MPATH_INFO_FRAME_QLEN, + NL80211_MPATH_INFO_SN, + NL80211_MPATH_INFO_METRIC, + NL80211_MPATH_INFO_EXPTIME, + NL80211_MPATH_INFO_FLAGS, + NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, + NL80211_MPATH_INFO_DISCOVERY_RETRIES, + NL80211_MPATH_INFO_HOP_COUNT, + NL80211_MPATH_INFO_PATH_CHANGE, + + /* keep last */ + __NL80211_MPATH_INFO_AFTER_LAST, + NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 +}; + +/** + * enum nl80211_band_iftype_attr - Interface type data attributes + * + * @__NL80211_BAND_IFTYPE_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_BAND_IFTYPE_ATTR_IFTYPES: nested attribute containing a flag attribute + * for each interface type that supports the band data + * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC: HE MAC capabilities as in HE + * capabilities IE + * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY: HE PHY capabilities as in HE + * capabilities IE + * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET: HE supported NSS/MCS as in HE + * capabilities IE + * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE: HE PPE thresholds information as + * defined in HE capabilities IE + * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band HE capability attribute currently + * defined + * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use + */ +enum nl80211_band_iftype_attr { + __NL80211_BAND_IFTYPE_ATTR_INVALID, + + NL80211_BAND_IFTYPE_ATTR_IFTYPES, + NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC, + NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, + NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, + NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, + + /* keep last */ + __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, + NL80211_BAND_IFTYPE_ATTR_MAX = __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_band_attr - band attributes + * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band, + * an array of nested frequency attributes + * @NL80211_BAND_ATTR_RATES: supported bitrates in this band, + * an array of nested bitrate attributes + * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as + * defined in 802.11n + * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE + * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n + * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n + * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as + * defined in 802.11ac + * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE + * @NL80211_BAND_ATTR_IFTYPE_DATA: nested array attribute, with each entry using + * attributes from &enum nl80211_band_iftype_attr + * @NL80211_BAND_ATTR_EDMG_CHANNELS: bitmap that indicates the 2.16 GHz + * channel(s) that are allowed to be used for EDMG transmissions. + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251. + * @NL80211_BAND_ATTR_EDMG_BW_CONFIG: Channel BW Configuration subfield encodes + * the allowed channel bandwidth configurations. + * Defined by IEEE P802.11ay/D4.0 section 9.4.2.251, Table 13. + * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined + * @__NL80211_BAND_ATTR_AFTER_LAST: internal use + */ +enum nl80211_band_attr { + __NL80211_BAND_ATTR_INVALID, + NL80211_BAND_ATTR_FREQS, + NL80211_BAND_ATTR_RATES, + + NL80211_BAND_ATTR_HT_MCS_SET, + NL80211_BAND_ATTR_HT_CAPA, + NL80211_BAND_ATTR_HT_AMPDU_FACTOR, + NL80211_BAND_ATTR_HT_AMPDU_DENSITY, + + NL80211_BAND_ATTR_VHT_MCS_SET, + NL80211_BAND_ATTR_VHT_CAPA, + NL80211_BAND_ATTR_IFTYPE_DATA, + + NL80211_BAND_ATTR_EDMG_CHANNELS, + NL80211_BAND_ATTR_EDMG_BW_CONFIG, + + /* keep last */ + __NL80211_BAND_ATTR_AFTER_LAST, + NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 +}; + +#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA + +/** + * enum nl80211_wmm_rule - regulatory wmm rule + * + * @__NL80211_WMMR_INVALID: attribute number 0 is reserved + * @NL80211_WMMR_CW_MIN: Minimum contention window slot. + * @NL80211_WMMR_CW_MAX: Maximum contention window slot. + * @NL80211_WMMR_AIFSN: Arbitration Inter Frame Space. + * @NL80211_WMMR_TXOP: Maximum allowed tx operation time. + * @nl80211_WMMR_MAX: highest possible wmm rule. + * @__NL80211_WMMR_LAST: Internal use. + */ +enum nl80211_wmm_rule { + __NL80211_WMMR_INVALID, + NL80211_WMMR_CW_MIN, + NL80211_WMMR_CW_MAX, + NL80211_WMMR_AIFSN, + NL80211_WMMR_TXOP, + + /* keep last */ + __NL80211_WMMR_LAST, + NL80211_WMMR_MAX = __NL80211_WMMR_LAST - 1 +}; + +/** + * enum nl80211_frequency_attr - frequency attributes + * @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz + * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current + * regulatory domain. + * @NL80211_FREQUENCY_ATTR_NO_IR: no mechanisms that initiate radiation + * are permitted on this channel, this includes sending probe + * requests, or modes of operation that require beaconing. + * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm + * (100 * dBm). + * @NL80211_FREQUENCY_ATTR_DFS_STATE: current state for DFS + * (enum nl80211_dfs_state) + * @NL80211_FREQUENCY_ATTR_DFS_TIME: time in miliseconds for how long + * this channel is in this DFS state. + * @NL80211_FREQUENCY_ATTR_NO_HT40_MINUS: HT40- isn't possible with this + * channel as the control channel + * @NL80211_FREQUENCY_ATTR_NO_HT40_PLUS: HT40+ isn't possible with this + * channel as the control channel + * @NL80211_FREQUENCY_ATTR_NO_80MHZ: any 80 MHz channel using this channel + * as the primary or any of the secondary channels isn't possible, + * this includes 80+80 channels + * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel + * using this channel as the primary or any of the secondary channels + * isn't possible + * @NL80211_FREQUENCY_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. + * @NL80211_FREQUENCY_ATTR_INDOOR_ONLY: Only indoor use is permitted on this + * channel. A channel that has the INDOOR_ONLY attribute can only be + * used when there is a clear assessment that the device is operating in + * an indoor surroundings, i.e., it is connected to AC power (and not + * through portable DC inverters) or is under the control of a master + * that is acting as an AP and is connected to AC power. + * @NL80211_FREQUENCY_ATTR_IR_CONCURRENT: IR operation is allowed on this + * channel if it's connected concurrently to a BSS on the same channel on + * the 2 GHz band or to a channel in the same UNII band (on the 5 GHz + * band), and IEEE80211_CHAN_RADAR is not set. Instantiating a GO or TDLS + * off-channel on a channel that has the IR_CONCURRENT attribute set can be + * done when there is a clear assessment that the device is operating under + * the guidance of an authorized master, i.e., setting up a GO or TDLS + * off-channel while the device is also connected to an AP with DFS and + * radar detection on the UNII band (it is up to user-space, i.e., + * wpa_supplicant to perform the required verifications). Using this + * attribute for IR is disallowed for master interfaces (IBSS, AP). + * @NL80211_FREQUENCY_ATTR_NO_20MHZ: 20 MHz operation is not allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_NO_10MHZ: 10 MHz operation is not allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_WMM: this channel has wmm limitations. + * This is a nested attribute that contains the wmm limitation per AC. + * (see &enum nl80211_wmm_rule) + * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number + * currently defined + * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use + * + * See https://apps.fcc.gov/eas/comments/GetPublishedDocument.html?id=327&tn=528122 + * for more information on the FCC description of the relaxations allowed + * by NL80211_FREQUENCY_ATTR_INDOOR_ONLY and + * NL80211_FREQUENCY_ATTR_IR_CONCURRENT. + */ +enum nl80211_frequency_attr { + __NL80211_FREQUENCY_ATTR_INVALID, + NL80211_FREQUENCY_ATTR_FREQ, + NL80211_FREQUENCY_ATTR_DISABLED, + NL80211_FREQUENCY_ATTR_NO_IR, + __NL80211_FREQUENCY_ATTR_NO_IBSS, + NL80211_FREQUENCY_ATTR_RADAR, + NL80211_FREQUENCY_ATTR_MAX_TX_POWER, + NL80211_FREQUENCY_ATTR_DFS_STATE, + NL80211_FREQUENCY_ATTR_DFS_TIME, + NL80211_FREQUENCY_ATTR_NO_HT40_MINUS, + NL80211_FREQUENCY_ATTR_NO_HT40_PLUS, + NL80211_FREQUENCY_ATTR_NO_80MHZ, + NL80211_FREQUENCY_ATTR_NO_160MHZ, + NL80211_FREQUENCY_ATTR_DFS_CAC_TIME, + NL80211_FREQUENCY_ATTR_INDOOR_ONLY, + NL80211_FREQUENCY_ATTR_IR_CONCURRENT, + NL80211_FREQUENCY_ATTR_NO_20MHZ, + NL80211_FREQUENCY_ATTR_NO_10MHZ, + NL80211_FREQUENCY_ATTR_WMM, + + /* keep last */ + __NL80211_FREQUENCY_ATTR_AFTER_LAST, + NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1 +}; + +#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER +#define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN NL80211_FREQUENCY_ATTR_NO_IR +#define NL80211_FREQUENCY_ATTR_NO_IBSS NL80211_FREQUENCY_ATTR_NO_IR +#define NL80211_FREQUENCY_ATTR_NO_IR NL80211_FREQUENCY_ATTR_NO_IR +#define NL80211_FREQUENCY_ATTR_GO_CONCURRENT \ + NL80211_FREQUENCY_ATTR_IR_CONCURRENT + +/** + * enum nl80211_bitrate_attr - bitrate attributes + * @__NL80211_BITRATE_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps + * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported + * in 2.4 GHz band. + * @NL80211_BITRATE_ATTR_MAX: highest bitrate attribute number + * currently defined + * @__NL80211_BITRATE_ATTR_AFTER_LAST: internal use + */ +enum nl80211_bitrate_attr { + __NL80211_BITRATE_ATTR_INVALID, + NL80211_BITRATE_ATTR_RATE, + NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE, + + /* keep last */ + __NL80211_BITRATE_ATTR_AFTER_LAST, + NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_initiator - Indicates the initiator of a reg domain request + * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world + * regulatory domain. + * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the + * regulatory domain. + * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the + * wireless core it thinks its knows the regulatory domain we should be in. + * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an + * 802.11 country information element with regulatory information it + * thinks we should consider. cfg80211 only processes the country + * code from the IE, and relies on the regulatory domain information + * structure passed by userspace (CRDA) from our wireless-regdb. + * If a channel is enabled but the country code indicates it should + * be disabled we disable the channel and re-enable it upon disassociation. + */ +enum nl80211_reg_initiator { + NL80211_REGDOM_SET_BY_CORE, + NL80211_REGDOM_SET_BY_USER, + NL80211_REGDOM_SET_BY_DRIVER, + NL80211_REGDOM_SET_BY_COUNTRY_IE, +}; + +/** + * enum nl80211_reg_type - specifies the type of regulatory domain + * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains + * to a specific country. When this is set you can count on the + * ISO / IEC 3166 alpha2 country code being valid. + * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory + * domain. + * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom + * driver specific world regulatory domain. These do not apply system-wide + * and are only applicable to the individual devices which have requested + * them to be applied. + * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product + * of an intersection between two regulatory domains -- the previously + * set regulatory domain on the system and the last accepted regulatory + * domain request to be processed. + */ +enum nl80211_reg_type { + NL80211_REGDOM_TYPE_COUNTRY, + NL80211_REGDOM_TYPE_WORLD, + NL80211_REGDOM_TYPE_CUSTOM_WORLD, + NL80211_REGDOM_TYPE_INTERSECTION, +}; + +/** + * enum nl80211_reg_rule_attr - regulatory rule attributes + * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional + * considerations for a given frequency range. These are the + * &enum nl80211_reg_rule_flags. + * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory + * rule in KHz. This is not a center of frequency but an actual regulatory + * band edge. + * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule + * in KHz. This is not a center a frequency but an actual regulatory + * band edge. + * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this + * frequency range, in KHz. + * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain + * for a given frequency range. The value is in mBi (100 * dBi). + * If you don't have one then don't send this. + * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for + * a given frequency range. The value is in mBm (100 * dBm). + * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. + * If not present or 0 default CAC time will be used. + * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number + * currently defined + * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use + */ +enum nl80211_reg_rule_attr { + __NL80211_REG_RULE_ATTR_INVALID, + NL80211_ATTR_REG_RULE_FLAGS, + + NL80211_ATTR_FREQ_RANGE_START, + NL80211_ATTR_FREQ_RANGE_END, + NL80211_ATTR_FREQ_RANGE_MAX_BW, + + NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, + NL80211_ATTR_POWER_RULE_MAX_EIRP, + + NL80211_ATTR_DFS_CAC_TIME, + + /* keep last */ + __NL80211_REG_RULE_ATTR_AFTER_LAST, + NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_sched_scan_match_attr - scheduled scan match attributes + * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching, + * only report BSS with matching SSID. + * (This cannot be used together with BSSID.) + * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a + * BSS in scan results. Filtering is turned off if not specified. Note that + * if this attribute is in a match set of its own, then it is treated as + * the default value for all matchsets with an SSID, rather than being a + * matchset of its own without an RSSI filter. This is due to problems with + * how this API was implemented in the past. Also, due to the same problem, + * the only way to create a matchset with only an RSSI filter (with this + * attribute) is if there's only a single matchset with the RSSI attribute. + * @NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI: Flag indicating whether + * %NL80211_SCHED_SCAN_MATCH_ATTR_RSSI to be used as absolute RSSI or + * relative to current bss's RSSI. + * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST: When present the RSSI level for + * BSS-es in the specified band is to be adjusted before doing + * RSSI-based BSS selection. The attribute value is a packed structure + * value as specified by &struct nl80211_bss_select_rssi_adjust. + * @NL80211_SCHED_SCAN_MATCH_ATTR_BSSID: BSSID to be used for matching + * (this cannot be used together with SSID). + * @NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI: Nested attribute that carries the + * band specific minimum rssi thresholds for the bands defined in + * enum nl80211_band. The minimum rssi threshold value(s32) specific to a + * band shall be encapsulated in attribute with type value equals to one + * of the NL80211_BAND_* defined in enum nl80211_band. For example, the + * minimum rssi threshold value for 2.4GHZ band shall be encapsulated + * within an attribute of type NL80211_BAND_2GHZ. And one or more of such + * attributes will be nested within this attribute. + * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter + * attribute number currently defined + * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use + */ +enum nl80211_sched_scan_match_attr { + __NL80211_SCHED_SCAN_MATCH_ATTR_INVALID, + + NL80211_SCHED_SCAN_MATCH_ATTR_SSID, + NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, + NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI, + NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST, + NL80211_SCHED_SCAN_MATCH_ATTR_BSSID, + NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI, + + /* keep last */ + __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST, + NL80211_SCHED_SCAN_MATCH_ATTR_MAX = + __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1 +}; + +/* only for backward compatibility */ +#define NL80211_ATTR_SCHED_SCAN_MATCH_SSID NL80211_SCHED_SCAN_MATCH_ATTR_SSID + +/** + * enum nl80211_reg_rule_flags - regulatory rule flags + * + * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed + * @NL80211_RRF_NO_CCK: CCK modulation not allowed + * @NL80211_RRF_NO_INDOOR: indoor operation not allowed + * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed + * @NL80211_RRF_DFS: DFS support is required to be used + * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links + * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links + * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed, + * this includes probe requests or modes of operation that require + * beaconing. + * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated + * base on contiguous rules and wider channels will be allowed to cross + * multiple contiguous/overlapping frequency ranges. + * @NL80211_RRF_IR_CONCURRENT: See %NL80211_FREQUENCY_ATTR_IR_CONCURRENT + * @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation + * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation + * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed + * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed + */ +enum nl80211_reg_rule_flags { + NL80211_RRF_NO_OFDM = 1<<0, + NL80211_RRF_NO_CCK = 1<<1, + NL80211_RRF_NO_INDOOR = 1<<2, + NL80211_RRF_NO_OUTDOOR = 1<<3, + NL80211_RRF_DFS = 1<<4, + NL80211_RRF_PTP_ONLY = 1<<5, + NL80211_RRF_PTMP_ONLY = 1<<6, + NL80211_RRF_NO_IR = 1<<7, + __NL80211_RRF_NO_IBSS = 1<<8, + NL80211_RRF_AUTO_BW = 1<<11, + NL80211_RRF_IR_CONCURRENT = 1<<12, + NL80211_RRF_NO_HT40MINUS = 1<<13, + NL80211_RRF_NO_HT40PLUS = 1<<14, + NL80211_RRF_NO_80MHZ = 1<<15, + NL80211_RRF_NO_160MHZ = 1<<16, +}; + +#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR +#define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS |\ + NL80211_RRF_NO_HT40PLUS) +#define NL80211_RRF_GO_CONCURRENT NL80211_RRF_IR_CONCURRENT + +/* For backport compatibility with older userspace */ +#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS) + +/** + * enum nl80211_dfs_regions - regulatory DFS regions + * + * @NL80211_DFS_UNSET: Country has no DFS master region specified + * @NL80211_DFS_FCC: Country follows DFS master rules from FCC + * @NL80211_DFS_ETSI: Country follows DFS master rules from ETSI + * @NL80211_DFS_JP: Country follows DFS master rules from JP/MKK/Telec + */ +enum nl80211_dfs_regions { + NL80211_DFS_UNSET = 0, + NL80211_DFS_FCC = 1, + NL80211_DFS_ETSI = 2, + NL80211_DFS_JP = 3, +}; + +/** + * enum nl80211_user_reg_hint_type - type of user regulatory hint + * + * @NL80211_USER_REG_HINT_USER: a user sent the hint. This is always + * assumed if the attribute is not set. + * @NL80211_USER_REG_HINT_CELL_BASE: the hint comes from a cellular + * base station. Device drivers that have been tested to work + * properly to support this type of hint can enable these hints + * by setting the NL80211_FEATURE_CELL_BASE_REG_HINTS feature + * capability on the struct wiphy. The wireless core will + * ignore all cell base station hints until at least one device + * present has been registered with the wireless core that + * has listed NL80211_FEATURE_CELL_BASE_REG_HINTS as a + * supported feature. + * @NL80211_USER_REG_HINT_INDOOR: a user sent an hint indicating that the + * platform is operating in an indoor environment. + */ +enum nl80211_user_reg_hint_type { + NL80211_USER_REG_HINT_USER = 0, + NL80211_USER_REG_HINT_CELL_BASE = 1, + NL80211_USER_REG_HINT_INDOOR = 2, +}; + +/** + * enum nl80211_survey_info - survey information + * + * These attribute types are used with %NL80211_ATTR_SURVEY_INFO + * when getting information about a survey. + * + * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved + * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel + * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) + * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used + * @NL80211_SURVEY_INFO_TIME: amount of time (in ms) that the radio + * was turned on (on channel or globally) + * @NL80211_SURVEY_INFO_TIME_BUSY: amount of the time the primary + * channel was sensed busy (either due to activity or energy detect) + * @NL80211_SURVEY_INFO_TIME_EXT_BUSY: amount of time the extension + * channel was sensed busy + * @NL80211_SURVEY_INFO_TIME_RX: amount of time the radio spent + * receiving data (on channel or globally) + * @NL80211_SURVEY_INFO_TIME_TX: amount of time the radio spent + * transmitting data (on channel or globally) + * @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan + * (on this channel or globally) + * @NL80211_SURVEY_INFO_PAD: attribute used for padding for 64-bit alignment + * @NL80211_SURVEY_INFO_TIME_BSS_RX: amount of time the radio spent + * receiving frames destined to the local BSS + * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number + * currently defined + * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use + */ +enum nl80211_survey_info { + __NL80211_SURVEY_INFO_INVALID, + NL80211_SURVEY_INFO_FREQUENCY, + NL80211_SURVEY_INFO_NOISE, + NL80211_SURVEY_INFO_IN_USE, + NL80211_SURVEY_INFO_TIME, + NL80211_SURVEY_INFO_TIME_BUSY, + NL80211_SURVEY_INFO_TIME_EXT_BUSY, + NL80211_SURVEY_INFO_TIME_RX, + NL80211_SURVEY_INFO_TIME_TX, + NL80211_SURVEY_INFO_TIME_SCAN, + NL80211_SURVEY_INFO_PAD, + NL80211_SURVEY_INFO_TIME_BSS_RX, + + /* keep last */ + __NL80211_SURVEY_INFO_AFTER_LAST, + NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1 +}; + +/* keep old names for compatibility */ +#define NL80211_SURVEY_INFO_CHANNEL_TIME NL80211_SURVEY_INFO_TIME +#define NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY NL80211_SURVEY_INFO_TIME_BUSY +#define NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY NL80211_SURVEY_INFO_TIME_EXT_BUSY +#define NL80211_SURVEY_INFO_CHANNEL_TIME_RX NL80211_SURVEY_INFO_TIME_RX +#define NL80211_SURVEY_INFO_CHANNEL_TIME_TX NL80211_SURVEY_INFO_TIME_TX + +/** + * enum nl80211_mntr_flags - monitor configuration flags + * + * Monitor configuration flags. + * + * @__NL80211_MNTR_FLAG_INVALID: reserved + * + * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS + * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP + * @NL80211_MNTR_FLAG_CONTROL: pass control frames + * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering + * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing. + * overrides all other flags. + * @NL80211_MNTR_FLAG_ACTIVE: use the configured MAC address + * and ACK incoming unicast packets. + * + * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use + * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag + */ +enum nl80211_mntr_flags { + __NL80211_MNTR_FLAG_INVALID, + NL80211_MNTR_FLAG_FCSFAIL, + NL80211_MNTR_FLAG_PLCPFAIL, + NL80211_MNTR_FLAG_CONTROL, + NL80211_MNTR_FLAG_OTHER_BSS, + NL80211_MNTR_FLAG_COOK_FRAMES, + NL80211_MNTR_FLAG_ACTIVE, + + /* keep last */ + __NL80211_MNTR_FLAG_AFTER_LAST, + NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 +}; + +/** + * enum nl80211_mesh_power_mode - mesh power save modes + * + * @NL80211_MESH_POWER_UNKNOWN: The mesh power mode of the mesh STA is + * not known or has not been set yet. + * @NL80211_MESH_POWER_ACTIVE: Active mesh power mode. The mesh STA is + * in Awake state all the time. + * @NL80211_MESH_POWER_LIGHT_SLEEP: Light sleep mode. The mesh STA will + * alternate between Active and Doze states, but will wake up for + * neighbor's beacons. + * @NL80211_MESH_POWER_DEEP_SLEEP: Deep sleep mode. The mesh STA will + * alternate between Active and Doze states, but may not wake up + * for neighbor's beacons. + * + * @__NL80211_MESH_POWER_AFTER_LAST - internal use + * @NL80211_MESH_POWER_MAX - highest possible power save level + */ + +enum nl80211_mesh_power_mode { + NL80211_MESH_POWER_UNKNOWN, + NL80211_MESH_POWER_ACTIVE, + NL80211_MESH_POWER_LIGHT_SLEEP, + NL80211_MESH_POWER_DEEP_SLEEP, + + __NL80211_MESH_POWER_AFTER_LAST, + NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1 +}; + +/** + * enum nl80211_meshconf_params - mesh configuration parameters + * + * Mesh configuration parameters. These can be changed while the mesh is + * active. + * + * @__NL80211_MESHCONF_INVALID: internal use + * + * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in + * millisecond units, used by the Peer Link Open message + * + * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the initial confirm timeout, in + * millisecond units, used by the peer link management to close a peer link + * + * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in + * millisecond units + * + * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed + * on this mesh interface + * + * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link + * open retries that can be sent to establish a new peer link instance in a + * mesh + * + * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh + * point. + * + * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically open + * peer links when we detect compatible mesh peers. Disabled if + * @NL80211_MESH_SETUP_USERSPACE_MPM or @NL80211_MESH_SETUP_USERSPACE_AMPE are + * set. + * + * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames + * containing a PREQ that an MP can send to a particular destination (path + * target) + * + * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths + * (in milliseconds) + * + * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait + * until giving up on a path discovery (in milliseconds) + * + * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh + * points receiving a PREQ shall consider the forwarding information from + * the root to be valid. (TU = time unit) + * + * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in + * TUs) during which an MP can send only one action frame containing a PREQ + * reference element + * + * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs) + * that it takes for an HWMP information element to propagate across the + * mesh + * + * @NL80211_MESHCONF_HWMP_ROOTMODE: whether root mode is enabled or not + * + * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a + * source mesh point for path selection elements. + * + * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between + * root announcements are transmitted. + * + * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has + * access to a broader network beyond the MBSS. This is done via Root + * Announcement frames. + * + * @NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: The minimum interval of time (in + * TUs) during which a mesh STA can send only one Action frame containing a + * PERR element. + * + * @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding + * or forwarding entity (default is TRUE - forwarding entity) + * + * @NL80211_MESHCONF_RSSI_THRESHOLD: RSSI threshold in dBm. This specifies the + * threshold for average signal strength of candidate station to establish + * a peer link. + * + * @NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: maximum number of neighbors + * to synchronize to for 11s default synchronization method + * (see 11C.12.2.2) + * + * @NL80211_MESHCONF_HT_OPMODE: set mesh HT protection mode. + * + * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute + * + * @NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT: The time (in TUs) for + * which mesh STAs receiving a proactive PREQ shall consider the forwarding + * information to the root mesh STA to be valid. + * + * @NL80211_MESHCONF_HWMP_ROOT_INTERVAL: The interval of time (in TUs) between + * proactive PREQs are transmitted. + * + * @NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL: The minimum interval of time + * (in TUs) during which a mesh STA can send only one Action frame + * containing a PREQ element for root path confirmation. + * + * @NL80211_MESHCONF_POWER_MODE: Default mesh power mode for new peer links. + * type &enum nl80211_mesh_power_mode (u32) + * + * @NL80211_MESHCONF_AWAKE_WINDOW: awake window duration (in TUs) + * + * @NL80211_MESHCONF_PLINK_TIMEOUT: If no tx activity is seen from a STA we've + * established peering with for longer than this time (in seconds), then + * remove it from the STA's list of peers. You may set this to 0 to disable + * the removal of the STA. Default is 30 minutes. + * + * @NL80211_MESHCONF_CONNECTED_TO_GATE: If set to true then this mesh STA + * will advertise that it is connected to a gate in the mesh formation + * field. If left unset then the mesh formation field will only + * advertise such if there is an active root mesh path. + * + * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use + */ +enum nl80211_meshconf_params { + __NL80211_MESHCONF_INVALID, + NL80211_MESHCONF_RETRY_TIMEOUT, + NL80211_MESHCONF_CONFIRM_TIMEOUT, + NL80211_MESHCONF_HOLDING_TIMEOUT, + NL80211_MESHCONF_MAX_PEER_LINKS, + NL80211_MESHCONF_MAX_RETRIES, + NL80211_MESHCONF_TTL, + NL80211_MESHCONF_AUTO_OPEN_PLINKS, + NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, + NL80211_MESHCONF_PATH_REFRESH_TIME, + NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, + NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, + NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, + NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, + NL80211_MESHCONF_HWMP_ROOTMODE, + NL80211_MESHCONF_ELEMENT_TTL, + NL80211_MESHCONF_HWMP_RANN_INTERVAL, + NL80211_MESHCONF_GATE_ANNOUNCEMENTS, + NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, + NL80211_MESHCONF_FORWARDING, + NL80211_MESHCONF_RSSI_THRESHOLD, + NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, + NL80211_MESHCONF_HT_OPMODE, + NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, + NL80211_MESHCONF_HWMP_ROOT_INTERVAL, + NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, + NL80211_MESHCONF_POWER_MODE, + NL80211_MESHCONF_AWAKE_WINDOW, + NL80211_MESHCONF_PLINK_TIMEOUT, + NL80211_MESHCONF_CONNECTED_TO_GATE, + + /* keep last */ + __NL80211_MESHCONF_ATTR_AFTER_LAST, + NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_mesh_setup_params - mesh setup parameters + * + * Mesh setup parameters. These are used to start/join a mesh and cannot be + * changed while the mesh is active. + * + * @__NL80211_MESH_SETUP_INVALID: Internal use + * + * @NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL: Enable this option to use a + * vendor specific path selection algorithm or disable it to use the + * default HWMP. + * + * @NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC: Enable this option to use a + * vendor specific path metric or disable it to use the default Airtime + * metric. + * + * @NL80211_MESH_SETUP_IE: Information elements for this mesh, for instance, a + * robust security network ie, or a vendor specific information element + * that vendors will use to identify the path selection methods and + * metrics in use. + * + * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication + * daemon will be authenticating mesh candidates. + * + * @NL80211_MESH_SETUP_USERSPACE_AMPE: Enable this option if an authentication + * daemon will be securing peer link frames. AMPE is a secured version of + * Mesh Peering Management (MPM) and is implemented with the assistance of + * a userspace daemon. When this flag is set, the kernel will send peer + * management frames to a userspace daemon that will implement AMPE + * functionality (security capabilities selection, key confirmation, and + * key management). When the flag is unset (default), the kernel can + * autonomously complete (unsecured) mesh peering without the need of a + * userspace daemon. + * + * @NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC: Enable this option to use a + * vendor specific synchronization method or disable it to use the default + * neighbor offset synchronization + * + * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will + * implement an MPM which handles peer allocation and state. + * + * @NL80211_MESH_SETUP_AUTH_PROTOCOL: Inform the kernel of the authentication + * method (u8, as defined in IEEE 8.4.2.100.6, e.g. 0x1 for SAE). + * Default is no authentication method required. + * + * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number + * + * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use + */ +enum nl80211_mesh_setup_params { + __NL80211_MESH_SETUP_INVALID, + NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL, + NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC, + NL80211_MESH_SETUP_IE, + NL80211_MESH_SETUP_USERSPACE_AUTH, + NL80211_MESH_SETUP_USERSPACE_AMPE, + NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC, + NL80211_MESH_SETUP_USERSPACE_MPM, + NL80211_MESH_SETUP_AUTH_PROTOCOL, + + /* keep last */ + __NL80211_MESH_SETUP_ATTR_AFTER_LAST, + NL80211_MESH_SETUP_ATTR_MAX = __NL80211_MESH_SETUP_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_txq_attr - TX queue parameter attributes + * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved + * @NL80211_TXQ_ATTR_AC: AC identifier (NL80211_AC_*) + * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning + * disabled + * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form + * 2^n-1 in the range 1..32767] + * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form + * 2^n-1 in the range 1..32767] + * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255] + * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal + * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number + */ +enum nl80211_txq_attr { + __NL80211_TXQ_ATTR_INVALID, + NL80211_TXQ_ATTR_AC, + NL80211_TXQ_ATTR_TXOP, + NL80211_TXQ_ATTR_CWMIN, + NL80211_TXQ_ATTR_CWMAX, + NL80211_TXQ_ATTR_AIFS, + + /* keep last */ + __NL80211_TXQ_ATTR_AFTER_LAST, + NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 +}; + +enum nl80211_ac { + NL80211_AC_VO, + NL80211_AC_VI, + NL80211_AC_BE, + NL80211_AC_BK, + NL80211_NUM_ACS +}; + +/* backward compat */ +#define NL80211_TXQ_ATTR_QUEUE NL80211_TXQ_ATTR_AC +#define NL80211_TXQ_Q_VO NL80211_AC_VO +#define NL80211_TXQ_Q_VI NL80211_AC_VI +#define NL80211_TXQ_Q_BE NL80211_AC_BE +#define NL80211_TXQ_Q_BK NL80211_AC_BK + +/** + * enum nl80211_channel_type - channel type + * @NL80211_CHAN_NO_HT: 20 MHz, non-HT channel + * @NL80211_CHAN_HT20: 20 MHz HT channel + * @NL80211_CHAN_HT40MINUS: HT40 channel, secondary channel + * below the control channel + * @NL80211_CHAN_HT40PLUS: HT40 channel, secondary channel + * above the control channel + */ +enum nl80211_channel_type { + NL80211_CHAN_NO_HT, + NL80211_CHAN_HT20, + NL80211_CHAN_HT40MINUS, + NL80211_CHAN_HT40PLUS +}; + +/** + * enum nl80211_key_mode - Key mode + * + * @NL80211_KEY_RX_TX: (Default) + * Key can be used for Rx and Tx immediately + * + * The following modes can only be selected for unicast keys and when the + * driver supports @NL80211_EXT_FEATURE_EXT_KEY_ID: + * + * @NL80211_KEY_NO_TX: Only allowed in combination with @NL80211_CMD_NEW_KEY: + * Unicast key can only be used for Rx, Tx not allowed, yet + * @NL80211_KEY_SET_TX: Only allowed in combination with @NL80211_CMD_SET_KEY: + * The unicast key identified by idx and mac is cleared for Tx and becomes + * the preferred Tx key for the station. + */ +enum nl80211_key_mode { + NL80211_KEY_RX_TX, + NL80211_KEY_NO_TX, + NL80211_KEY_SET_TX +}; + +/** + * enum nl80211_chan_width - channel width definitions + * + * These values are used with the %NL80211_ATTR_CHANNEL_WIDTH + * attribute. + * + * @NL80211_CHAN_WIDTH_20_NOHT: 20 MHz, non-HT channel + * @NL80211_CHAN_WIDTH_20: 20 MHz HT channel + * @NL80211_CHAN_WIDTH_40: 40 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_80: 80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_80P80: 80+80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well + * @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel + * @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel + */ +enum nl80211_chan_width { + NL80211_CHAN_WIDTH_20_NOHT, + NL80211_CHAN_WIDTH_20, + NL80211_CHAN_WIDTH_40, + NL80211_CHAN_WIDTH_80, + NL80211_CHAN_WIDTH_80P80, + NL80211_CHAN_WIDTH_160, + NL80211_CHAN_WIDTH_5, + NL80211_CHAN_WIDTH_10, +}; + +/** + * enum nl80211_bss_scan_width - control channel width for a BSS + * + * These values are used with the %NL80211_BSS_CHAN_WIDTH attribute. + * + * @NL80211_BSS_CHAN_WIDTH_20: control channel is 20 MHz wide or compatible + * @NL80211_BSS_CHAN_WIDTH_10: control channel is 10 MHz wide + * @NL80211_BSS_CHAN_WIDTH_5: control channel is 5 MHz wide + */ +enum nl80211_bss_scan_width { + NL80211_BSS_CHAN_WIDTH_20, + NL80211_BSS_CHAN_WIDTH_10, + NL80211_BSS_CHAN_WIDTH_5, +}; + +/** + * enum nl80211_bss - netlink attributes for a BSS + * + * @__NL80211_BSS_INVALID: invalid + * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets) + * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) + * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) + * (if @NL80211_BSS_PRESP_DATA is present then this is known to be + * from a probe response, otherwise it may be from the same beacon + * that the NL80211_BSS_BEACON_TSF will be from) + * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) + * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16) + * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the + * raw information elements from the probe response/beacon (bin); + * if the %NL80211_BSS_BEACON_IES attribute is present and the data is + * different then the IEs here are from a Probe Response frame; otherwise + * they are from a Beacon frame. + * However, if the driver does not indicate the source of the IEs, these + * IEs may be from either frame subtype. + * If present, the @NL80211_BSS_PRESP_DATA attribute indicates that the + * data here is known to be from a probe response, without any heuristics. + * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon + * in mBm (100 * dBm) (s32) + * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon + * in unspecified units, scaled to 0..100 (u8) + * @NL80211_BSS_STATUS: status, if this BSS is "used" + * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms + * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information + * elements from a Beacon frame (bin); not present if no Beacon frame has + * yet been received + * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel + * (u32, enum nl80211_bss_scan_width) + * @NL80211_BSS_BEACON_TSF: TSF of the last received beacon (u64) + * (not present if no beacon frame has been received yet) + * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and + * @NL80211_BSS_TSF is known to be from a probe response (flag attribute) + * @NL80211_BSS_LAST_SEEN_BOOTTIME: CLOCK_BOOTTIME timestamp when this entry + * was last updated by a received frame. The value is expected to be + * accurate to about 10ms. (u64, nanoseconds) + * @NL80211_BSS_PAD: attribute used for padding for 64-bit alignment + * @NL80211_BSS_PARENT_TSF: the time at the start of reception of the first + * octet of the timestamp field of the last beacon/probe received for + * this BSS. The time is the TSF of the BSS specified by + * @NL80211_BSS_PARENT_BSSID. (u64). + * @NL80211_BSS_PARENT_BSSID: the BSS according to which @NL80211_BSS_PARENT_TSF + * is set. + * @NL80211_BSS_CHAIN_SIGNAL: per-chain signal strength of last BSS update. + * Contains a nested array of signal strength attributes (u8, dBm), + * using the nesting index as the antenna number. + * @__NL80211_BSS_AFTER_LAST: internal + * @NL80211_BSS_MAX: highest BSS attribute + */ +enum nl80211_bss { + __NL80211_BSS_INVALID, + NL80211_BSS_BSSID, + NL80211_BSS_FREQUENCY, + NL80211_BSS_TSF, + NL80211_BSS_BEACON_INTERVAL, + NL80211_BSS_CAPABILITY, + NL80211_BSS_INFORMATION_ELEMENTS, + NL80211_BSS_SIGNAL_MBM, + NL80211_BSS_SIGNAL_UNSPEC, + NL80211_BSS_STATUS, + NL80211_BSS_SEEN_MS_AGO, + NL80211_BSS_BEACON_IES, + NL80211_BSS_CHAN_WIDTH, + NL80211_BSS_BEACON_TSF, + NL80211_BSS_PRESP_DATA, + NL80211_BSS_LAST_SEEN_BOOTTIME, + NL80211_BSS_PAD, + NL80211_BSS_PARENT_TSF, + NL80211_BSS_PARENT_BSSID, + NL80211_BSS_CHAIN_SIGNAL, + + /* keep last */ + __NL80211_BSS_AFTER_LAST, + NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1 +}; + +/** + * enum nl80211_bss_status - BSS "status" + * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS. + * Note that this is no longer used since cfg80211 no longer + * keeps track of whether or not authentication was done with + * a given BSS. + * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS. + * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS. + * + * The BSS status is a BSS attribute in scan dumps, which + * indicates the status the interface has wrt. this BSS. + */ +enum nl80211_bss_status { + NL80211_BSS_STATUS_AUTHENTICATED, + NL80211_BSS_STATUS_ASSOCIATED, + NL80211_BSS_STATUS_IBSS_JOINED, +}; + +/** + * enum nl80211_auth_type - AuthenticationType + * + * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication + * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only) + * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r) + * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP) + * @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals + * @NL80211_AUTHTYPE_FILS_SK: Fast Initial Link Setup shared key + * @NL80211_AUTHTYPE_FILS_SK_PFS: Fast Initial Link Setup shared key with PFS + * @NL80211_AUTHTYPE_FILS_PK: Fast Initial Link Setup public key + * @__NL80211_AUTHTYPE_NUM: internal + * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm + * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by + * trying multiple times); this is invalid in netlink -- leave out + * the attribute for this on CONNECT commands. + */ +enum nl80211_auth_type { + NL80211_AUTHTYPE_OPEN_SYSTEM, + NL80211_AUTHTYPE_SHARED_KEY, + NL80211_AUTHTYPE_FT, + NL80211_AUTHTYPE_NETWORK_EAP, + NL80211_AUTHTYPE_SAE, + NL80211_AUTHTYPE_FILS_SK, + NL80211_AUTHTYPE_FILS_SK_PFS, + NL80211_AUTHTYPE_FILS_PK, + + /* keep last */ + __NL80211_AUTHTYPE_NUM, + NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1, + NL80211_AUTHTYPE_AUTOMATIC +}; + +/** + * enum nl80211_key_type - Key Type + * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key + * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key + * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS) + * @NUM_NL80211_KEYTYPES: number of defined key types + */ +enum nl80211_key_type { + NL80211_KEYTYPE_GROUP, + NL80211_KEYTYPE_PAIRWISE, + NL80211_KEYTYPE_PEERKEY, + + NUM_NL80211_KEYTYPES +}; + +/** + * enum nl80211_mfp - Management frame protection state + * @NL80211_MFP_NO: Management frame protection not used + * @NL80211_MFP_REQUIRED: Management frame protection required + * @NL80211_MFP_OPTIONAL: Management frame protection is optional + */ +enum nl80211_mfp { + NL80211_MFP_NO, + NL80211_MFP_REQUIRED, + NL80211_MFP_OPTIONAL, +}; + +enum nl80211_wpa_versions { + NL80211_WPA_VERSION_1 = 1 << 0, + NL80211_WPA_VERSION_2 = 1 << 1, + NL80211_WPA_VERSION_3 = 1 << 2, +}; + +/** + * enum nl80211_key_default_types - key default types + * @__NL80211_KEY_DEFAULT_TYPE_INVALID: invalid + * @NL80211_KEY_DEFAULT_TYPE_UNICAST: key should be used as default + * unicast key + * @NL80211_KEY_DEFAULT_TYPE_MULTICAST: key should be used as default + * multicast key + * @NUM_NL80211_KEY_DEFAULT_TYPES: number of default types + */ +enum nl80211_key_default_types { + __NL80211_KEY_DEFAULT_TYPE_INVALID, + NL80211_KEY_DEFAULT_TYPE_UNICAST, + NL80211_KEY_DEFAULT_TYPE_MULTICAST, + + NUM_NL80211_KEY_DEFAULT_TYPES +}; + +/** + * enum nl80211_key_attributes - key attributes + * @__NL80211_KEY_INVALID: invalid + * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of + * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC + * keys + * @NL80211_KEY_IDX: key ID (u8, 0-3) + * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 + * section 7.3.2.25.1, e.g. 0x000FAC04) + * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and + * CCMP keys, each six bytes in little endian + * @NL80211_KEY_DEFAULT: flag indicating default key + * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key + * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not + * specified the default depends on whether a MAC address was + * given with the command using the key or not (u32) + * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags + * attributes, specifying what a key should be set as default as. + * See &enum nl80211_key_default_types. + * @NL80211_KEY_MODE: the mode from enum nl80211_key_mode. + * Defaults to @NL80211_KEY_RX_TX. + * + * @__NL80211_KEY_AFTER_LAST: internal + * @NL80211_KEY_MAX: highest key attribute + */ +enum nl80211_key_attributes { + __NL80211_KEY_INVALID, + NL80211_KEY_DATA, + NL80211_KEY_IDX, + NL80211_KEY_CIPHER, + NL80211_KEY_SEQ, + NL80211_KEY_DEFAULT, + NL80211_KEY_DEFAULT_MGMT, + NL80211_KEY_TYPE, + NL80211_KEY_DEFAULT_TYPES, + NL80211_KEY_MODE, + + /* keep last */ + __NL80211_KEY_AFTER_LAST, + NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1 +}; + +/** + * enum nl80211_tx_rate_attributes - TX rate set attributes + * @__NL80211_TXRATE_INVALID: invalid + * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection + * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with + * 1 = 500 kbps) but without the IE length restriction (at most + * %NL80211_MAX_SUPP_RATES in a single array). + * @NL80211_TXRATE_HT: HT (MCS) rates allowed for TX rate selection + * in an array of MCS numbers. + * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection, + * see &struct nl80211_txrate_vht + * @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi + * @__NL80211_TXRATE_AFTER_LAST: internal + * @NL80211_TXRATE_MAX: highest TX rate attribute + */ +enum nl80211_tx_rate_attributes { + __NL80211_TXRATE_INVALID, + NL80211_TXRATE_LEGACY, + NL80211_TXRATE_HT, + NL80211_TXRATE_VHT, + NL80211_TXRATE_GI, + + /* keep last */ + __NL80211_TXRATE_AFTER_LAST, + NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1 +}; + +#define NL80211_TXRATE_MCS NL80211_TXRATE_HT +#define NL80211_VHT_NSS_MAX 8 + +/** + * struct nl80211_txrate_vht - VHT MCS/NSS txrate bitmap + * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.) + */ +struct nl80211_txrate_vht { + __u16 mcs[NL80211_VHT_NSS_MAX]; +}; + +enum nl80211_txrate_gi { + NL80211_TXRATE_DEFAULT_GI, + NL80211_TXRATE_FORCE_SGI, + NL80211_TXRATE_FORCE_LGI, +}; + +/** + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) + * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz) + * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace + * since newer kernel versions may support more bands + */ +enum nl80211_band { + NL80211_BAND_2GHZ, + NL80211_BAND_5GHZ, + NL80211_BAND_60GHZ, + NL80211_BAND_6GHZ, + + NUM_NL80211_BANDS, +}; + +/** + * enum nl80211_ps_state - powersave state + * @NL80211_PS_DISABLED: powersave is disabled + * @NL80211_PS_ENABLED: powersave is enabled + */ +enum nl80211_ps_state { + NL80211_PS_DISABLED, + NL80211_PS_ENABLED, +}; + +/** + * enum nl80211_attr_cqm - connection quality monitor attributes + * @__NL80211_ATTR_CQM_INVALID: invalid + * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies + * the threshold for the RSSI level at which an event will be sent. Zero + * to disable. Alternatively, if %NL80211_EXT_FEATURE_CQM_RSSI_LIST is + * set, multiple values can be supplied as a low-to-high sorted array of + * threshold values in dBm. Events will be sent when the RSSI value + * crosses any of the thresholds. + * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies + * the minimum amount the RSSI level must change after an event before a + * new event may be issued (to reduce effects of RSSI oscillation). + * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event + * @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many + * consecutive packets were not acknowledged by the peer + * @NL80211_ATTR_CQM_TXE_RATE: TX error rate in %. Minimum % of TX failures + * during the given %NL80211_ATTR_CQM_TXE_INTVL before an + * %NL80211_CMD_NOTIFY_CQM with reported %NL80211_ATTR_CQM_TXE_RATE and + * %NL80211_ATTR_CQM_TXE_PKTS is generated. + * @NL80211_ATTR_CQM_TXE_PKTS: number of attempted packets in a given + * %NL80211_ATTR_CQM_TXE_INTVL before %NL80211_ATTR_CQM_TXE_RATE is + * checked. + * @NL80211_ATTR_CQM_TXE_INTVL: interval in seconds. Specifies the periodic + * interval in which %NL80211_ATTR_CQM_TXE_PKTS and + * %NL80211_ATTR_CQM_TXE_RATE must be satisfied before generating an + * %NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting. + * @NL80211_ATTR_CQM_BEACON_LOSS_EVENT: flag attribute that's set in a beacon + * loss event + * @NL80211_ATTR_CQM_RSSI_LEVEL: the RSSI value in dBm that triggered the + * RSSI threshold event. + * @__NL80211_ATTR_CQM_AFTER_LAST: internal + * @NL80211_ATTR_CQM_MAX: highest key attribute + */ +enum nl80211_attr_cqm { + __NL80211_ATTR_CQM_INVALID, + NL80211_ATTR_CQM_RSSI_THOLD, + NL80211_ATTR_CQM_RSSI_HYST, + NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, + NL80211_ATTR_CQM_PKT_LOSS_EVENT, + NL80211_ATTR_CQM_TXE_RATE, + NL80211_ATTR_CQM_TXE_PKTS, + NL80211_ATTR_CQM_TXE_INTVL, + NL80211_ATTR_CQM_BEACON_LOSS_EVENT, + NL80211_ATTR_CQM_RSSI_LEVEL, + + /* keep last */ + __NL80211_ATTR_CQM_AFTER_LAST, + NL80211_ATTR_CQM_MAX = __NL80211_ATTR_CQM_AFTER_LAST - 1 +}; + +/** + * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event + * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: The RSSI level is lower than the + * configured threshold + * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the + * configured threshold + * @NL80211_CQM_RSSI_BEACON_LOSS_EVENT: (reserved, never sent) + */ +enum nl80211_cqm_rssi_threshold_event { + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, + NL80211_CQM_RSSI_BEACON_LOSS_EVENT, +}; + + +/** + * enum nl80211_tx_power_setting - TX power adjustment + * @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power + * @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter + * @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter + */ +enum nl80211_tx_power_setting { + NL80211_TX_POWER_AUTOMATIC, + NL80211_TX_POWER_LIMITED, + NL80211_TX_POWER_FIXED, +}; + +/** + * enum nl80211_packet_pattern_attr - packet pattern attribute + * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute + * @NL80211_PKTPAT_PATTERN: the pattern, values where the mask has + * a zero bit are ignored + * @NL80211_PKTPAT_MASK: pattern mask, must be long enough to have + * a bit for each byte in the pattern. The lowest-order bit corresponds + * to the first byte of the pattern, but the bytes of the pattern are + * in a little-endian-like format, i.e. the 9th byte of the pattern + * corresponds to the lowest-order bit in the second byte of the mask. + * For example: The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where + * xx indicates "don't care") would be represented by a pattern of + * twelve zero bytes, and a mask of "0xed,0x01". + * Note that the pattern matching is done as though frames were not + * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked + * first (including SNAP header unpacking) and then matched. + * @NL80211_PKTPAT_OFFSET: packet offset, pattern is matched after + * these fixed number of bytes of received packet + * @NUM_NL80211_PKTPAT: number of attributes + * @MAX_NL80211_PKTPAT: max attribute number + */ +enum nl80211_packet_pattern_attr { + __NL80211_PKTPAT_INVALID, + NL80211_PKTPAT_MASK, + NL80211_PKTPAT_PATTERN, + NL80211_PKTPAT_OFFSET, + + NUM_NL80211_PKTPAT, + MAX_NL80211_PKTPAT = NUM_NL80211_PKTPAT - 1, +}; + +/** + * struct nl80211_pattern_support - packet pattern support information + * @max_patterns: maximum number of patterns supported + * @min_pattern_len: minimum length of each pattern + * @max_pattern_len: maximum length of each pattern + * @max_pkt_offset: maximum Rx packet offset + * + * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when + * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED or in + * %NL80211_ATTR_COALESCE_RULE_PKT_PATTERN when that is part of + * %NL80211_ATTR_COALESCE_RULE in the capability information given + * by the kernel to userspace. + */ +struct nl80211_pattern_support { + __u32 max_patterns; + __u32 min_pattern_len; + __u32 max_pattern_len; + __u32 max_pkt_offset; +} __attribute__((packed)); + +/* only for backward compatibility */ +#define __NL80211_WOWLAN_PKTPAT_INVALID __NL80211_PKTPAT_INVALID +#define NL80211_WOWLAN_PKTPAT_MASK NL80211_PKTPAT_MASK +#define NL80211_WOWLAN_PKTPAT_PATTERN NL80211_PKTPAT_PATTERN +#define NL80211_WOWLAN_PKTPAT_OFFSET NL80211_PKTPAT_OFFSET +#define NUM_NL80211_WOWLAN_PKTPAT NUM_NL80211_PKTPAT +#define MAX_NL80211_WOWLAN_PKTPAT MAX_NL80211_PKTPAT +#define nl80211_wowlan_pattern_support nl80211_pattern_support + +/** + * enum nl80211_wowlan_triggers - WoWLAN trigger definitions + * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes + * @NL80211_WOWLAN_TRIG_ANY: wake up on any activity, do not really put + * the chip into a special state -- works best with chips that have + * support for low-power operation already (flag) + * Note that this mode is incompatible with all of the others, if + * any others are even supported by the device. + * @NL80211_WOWLAN_TRIG_DISCONNECT: wake up on disconnect, the way disconnect + * is detected is implementation-specific (flag) + * @NL80211_WOWLAN_TRIG_MAGIC_PKT: wake up on magic packet (6x 0xff, followed + * by 16 repetitions of MAC addr, anywhere in payload) (flag) + * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns + * which are passed in an array of nested attributes, each nested attribute + * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern. + * Each pattern defines a wakeup packet. Packet offset is associated with + * each pattern which is used while matching the pattern. The matching is + * done on the MSDU, i.e. as though the packet was an 802.3 packet, so the + * pattern matching is done after the packet is converted to the MSDU. + * + * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute + * carrying a &struct nl80211_pattern_support. + * + * When reporting wakeup. it is a u32 attribute containing the 0-based + * index of the pattern that caused the wakeup, in the patterns passed + * to the kernel when configuring. + * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be + * used when setting, used only to indicate that GTK rekeying is supported + * by the device (flag) + * @NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: wake up on GTK rekey failure (if + * done by the device) (flag) + * @NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: wake up on EAP Identity Request + * packet (flag) + * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag) + * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released + * (on devices that have rfkill in the device) (flag) + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211: For wakeup reporting only, contains + * the 802.11 packet that caused the wakeup, e.g. a deauth frame. The frame + * may be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN + * attribute contains the original length. + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN: Original length of the 802.11 + * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 + * attribute if the packet was truncated somewhere. + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023: For wakeup reporting only, contains the + * 802.11 packet that caused the wakeup, e.g. a magic packet. The frame may + * be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN attribute + * contains the original length. + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: Original length of the 802.3 + * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 + * attribute if the packet was truncated somewhere. + * @NL80211_WOWLAN_TRIG_TCP_CONNECTION: TCP connection wake, see DOC section + * "TCP connection wakeup" for more details. This is a nested attribute + * containing the exact information for establishing and keeping alive + * the TCP connection. + * @NL80211_WOWLAN_TRIG_TCP_WAKEUP_MATCH: For wakeup reporting only, the + * wakeup packet was received on the TCP connection + * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST: For wakeup reporting only, the + * TCP connection was lost or failed to be established + * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS: For wakeup reporting only, + * the TCP connection ran out of tokens to use for data to send to the + * service + * @NL80211_WOWLAN_TRIG_NET_DETECT: wake up when a configured network + * is detected. This is a nested attribute that contains the + * same attributes used with @NL80211_CMD_START_SCHED_SCAN. It + * specifies how the scan is performed (e.g. the interval, the + * channels to scan and the initial delay) as well as the scan + * results that will trigger a wake (i.e. the matchsets). This + * attribute is also sent in a response to + * @NL80211_CMD_GET_WIPHY, indicating the number of match sets + * supported by the driver (u32). + * @NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS: nested attribute + * containing an array with information about what triggered the + * wake up. If no elements are present in the array, it means + * that the information is not available. If more than one + * element is present, it means that more than one match + * occurred. + * Each element in the array is a nested attribute that contains + * one optional %NL80211_ATTR_SSID attribute and one optional + * %NL80211_ATTR_SCAN_FREQUENCIES attribute. At least one of + * these attributes must be present. If + * %NL80211_ATTR_SCAN_FREQUENCIES contains more than one + * frequency, it means that the match occurred in more than one + * channel. + * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers + * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number + * + * These nested attributes are used to configure the wakeup triggers and + * to report the wakeup reason(s). + */ +enum nl80211_wowlan_triggers { + __NL80211_WOWLAN_TRIG_INVALID, + NL80211_WOWLAN_TRIG_ANY, + NL80211_WOWLAN_TRIG_DISCONNECT, + NL80211_WOWLAN_TRIG_MAGIC_PKT, + NL80211_WOWLAN_TRIG_PKT_PATTERN, + NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED, + NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE, + NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST, + NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE, + NL80211_WOWLAN_TRIG_RFKILL_RELEASE, + NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211, + NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN, + NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023, + NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN, + NL80211_WOWLAN_TRIG_TCP_CONNECTION, + NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH, + NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST, + NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS, + NL80211_WOWLAN_TRIG_NET_DETECT, + NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS, + + /* keep last */ + NUM_NL80211_WOWLAN_TRIG, + MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1 +}; + +/** + * DOC: TCP connection wakeup + * + * Some devices can establish a TCP connection in order to be woken up by a + * packet coming in from outside their network segment, or behind NAT. If + * configured, the device will establish a TCP connection to the given + * service, and periodically send data to that service. The first data + * packet is usually transmitted after SYN/ACK, also ACKing the SYN/ACK. + * The data packets can optionally include a (little endian) sequence + * number (in the TCP payload!) that is generated by the device, and, also + * optionally, a token from a list of tokens. This serves as a keep-alive + * with the service, and for NATed connections, etc. + * + * During this keep-alive period, the server doesn't send any data to the + * client. When receiving data, it is compared against the wakeup pattern + * (and mask) and if it matches, the host is woken up. Similarly, if the + * connection breaks or cannot be established to start with, the host is + * also woken up. + * + * Developer's note: ARP offload is required for this, otherwise TCP + * response packets might not go through correctly. + */ + +/** + * struct nl80211_wowlan_tcp_data_seq - WoWLAN TCP data sequence + * @start: starting value + * @offset: offset of sequence number in packet + * @len: length of the sequence value to write, 1 through 4 + * + * Note: don't confuse with the TCP sequence number(s), this is for the + * keepalive packet payload. The actual value is written into the packet + * in little endian. + */ +struct nl80211_wowlan_tcp_data_seq { + __u32 start, offset, len; +}; + +/** + * struct nl80211_wowlan_tcp_data_token - WoWLAN TCP data token config + * @offset: offset of token in packet + * @len: length of each token + * @token_stream: stream of data to be used for the tokens, the length must + * be a multiple of @len for this to make sense + */ +struct nl80211_wowlan_tcp_data_token { + __u32 offset, len; + __u8 token_stream[]; +}; + +/** + * struct nl80211_wowlan_tcp_data_token_feature - data token features + * @min_len: minimum token length + * @max_len: maximum token length + * @bufsize: total available token buffer size (max size of @token_stream) + */ +struct nl80211_wowlan_tcp_data_token_feature { + __u32 min_len, max_len, bufsize; +}; + +/** + * enum nl80211_wowlan_tcp_attrs - WoWLAN TCP connection parameters + * @__NL80211_WOWLAN_TCP_INVALID: invalid number for nested attributes + * @NL80211_WOWLAN_TCP_SRC_IPV4: source IPv4 address (in network byte order) + * @NL80211_WOWLAN_TCP_DST_IPV4: destination IPv4 address + * (in network byte order) + * @NL80211_WOWLAN_TCP_DST_MAC: destination MAC address, this is given because + * route lookup when configured might be invalid by the time we suspend, + * and doing a route lookup when suspending is no longer possible as it + * might require ARP querying. + * @NL80211_WOWLAN_TCP_SRC_PORT: source port (u16); optional, if not given a + * socket and port will be allocated + * @NL80211_WOWLAN_TCP_DST_PORT: destination port (u16) + * @NL80211_WOWLAN_TCP_DATA_PAYLOAD: data packet payload, at least one byte. + * For feature advertising, a u32 attribute holding the maximum length + * of the data payload. + * @NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ: data packet sequence configuration + * (if desired), a &struct nl80211_wowlan_tcp_data_seq. For feature + * advertising it is just a flag + * @NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN: data packet token configuration, + * see &struct nl80211_wowlan_tcp_data_token and for advertising see + * &struct nl80211_wowlan_tcp_data_token_feature. + * @NL80211_WOWLAN_TCP_DATA_INTERVAL: data interval in seconds, maximum + * interval in feature advertising (u32) + * @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a + * u32 attribute holding the maximum length + * @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for + * feature advertising. The mask works like @NL80211_PKTPAT_MASK + * but on the TCP payload only. + * @NUM_NL80211_WOWLAN_TCP: number of TCP attributes + * @MAX_NL80211_WOWLAN_TCP: highest attribute number + */ +enum nl80211_wowlan_tcp_attrs { + __NL80211_WOWLAN_TCP_INVALID, + NL80211_WOWLAN_TCP_SRC_IPV4, + NL80211_WOWLAN_TCP_DST_IPV4, + NL80211_WOWLAN_TCP_DST_MAC, + NL80211_WOWLAN_TCP_SRC_PORT, + NL80211_WOWLAN_TCP_DST_PORT, + NL80211_WOWLAN_TCP_DATA_PAYLOAD, + NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ, + NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN, + NL80211_WOWLAN_TCP_DATA_INTERVAL, + NL80211_WOWLAN_TCP_WAKE_PAYLOAD, + NL80211_WOWLAN_TCP_WAKE_MASK, + + /* keep last */ + NUM_NL80211_WOWLAN_TCP, + MAX_NL80211_WOWLAN_TCP = NUM_NL80211_WOWLAN_TCP - 1 +}; + +/** + * struct nl80211_coalesce_rule_support - coalesce rule support information + * @max_rules: maximum number of rules supported + * @pat: packet pattern support information + * @max_delay: maximum supported coalescing delay in msecs + * + * This struct is carried in %NL80211_ATTR_COALESCE_RULE in the + * capability information given by the kernel to userspace. + */ +struct nl80211_coalesce_rule_support { + __u32 max_rules; + struct nl80211_pattern_support pat; + __u32 max_delay; +} __attribute__((packed)); + +/** + * enum nl80211_attr_coalesce_rule - coalesce rule attribute + * @__NL80211_COALESCE_RULE_INVALID: invalid number for nested attribute + * @NL80211_ATTR_COALESCE_RULE_DELAY: delay in msecs used for packet coalescing + * @NL80211_ATTR_COALESCE_RULE_CONDITION: condition for packet coalescence, + * see &enum nl80211_coalesce_condition. + * @NL80211_ATTR_COALESCE_RULE_PKT_PATTERN: packet offset, pattern is matched + * after these fixed number of bytes of received packet + * @NUM_NL80211_ATTR_COALESCE_RULE: number of attributes + * @NL80211_ATTR_COALESCE_RULE_MAX: max attribute number + */ +enum nl80211_attr_coalesce_rule { + __NL80211_COALESCE_RULE_INVALID, + NL80211_ATTR_COALESCE_RULE_DELAY, + NL80211_ATTR_COALESCE_RULE_CONDITION, + NL80211_ATTR_COALESCE_RULE_PKT_PATTERN, + + /* keep last */ + NUM_NL80211_ATTR_COALESCE_RULE, + NL80211_ATTR_COALESCE_RULE_MAX = NUM_NL80211_ATTR_COALESCE_RULE - 1 +}; + +/** + * enum nl80211_coalesce_condition - coalesce rule conditions + * @NL80211_COALESCE_CONDITION_MATCH: coalaesce Rx packets when patterns + * in a rule are matched. + * @NL80211_COALESCE_CONDITION_NO_MATCH: coalesce Rx packets when patterns + * in a rule are not matched. + */ +enum nl80211_coalesce_condition { + NL80211_COALESCE_CONDITION_MATCH, + NL80211_COALESCE_CONDITION_NO_MATCH +}; + +/** + * enum nl80211_iface_limit_attrs - limit attributes + * @NL80211_IFACE_LIMIT_UNSPEC: (reserved) + * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that + * can be chosen from this set of interface types (u32) + * @NL80211_IFACE_LIMIT_TYPES: nested attribute containing a + * flag attribute for each interface type in this set + * @NUM_NL80211_IFACE_LIMIT: number of attributes + * @MAX_NL80211_IFACE_LIMIT: highest attribute number + */ +enum nl80211_iface_limit_attrs { + NL80211_IFACE_LIMIT_UNSPEC, + NL80211_IFACE_LIMIT_MAX, + NL80211_IFACE_LIMIT_TYPES, + + /* keep last */ + NUM_NL80211_IFACE_LIMIT, + MAX_NL80211_IFACE_LIMIT = NUM_NL80211_IFACE_LIMIT - 1 +}; + +/** + * enum nl80211_if_combination_attrs -- interface combination attributes + * + * @NL80211_IFACE_COMB_UNSPEC: (reserved) + * @NL80211_IFACE_COMB_LIMITS: Nested attributes containing the limits + * for given interface types, see &enum nl80211_iface_limit_attrs. + * @NL80211_IFACE_COMB_MAXNUM: u32 attribute giving the total number of + * interfaces that can be created in this group. This number doesn't + * apply to interfaces purely managed in software, which are listed + * in a separate attribute %NL80211_ATTR_INTERFACES_SOFTWARE. + * @NL80211_IFACE_COMB_STA_AP_BI_MATCH: flag attribute specifying that + * beacon intervals within this group must be all the same even for + * infrastructure and AP/GO combinations, i.e. the GO(s) must adopt + * the infrastructure network's beacon interval. + * @NL80211_IFACE_COMB_NUM_CHANNELS: u32 attribute specifying how many + * different channels may be used within this group. + * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap + * of supported channel widths for radar detection. + * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap + * of supported regulatory regions for radar detection. + * @NL80211_IFACE_COMB_BI_MIN_GCD: u32 attribute specifying the minimum GCD of + * different beacon intervals supported by all the interface combinations + * in this group (if not present, all beacon intervals be identical). + * @NUM_NL80211_IFACE_COMB: number of attributes + * @MAX_NL80211_IFACE_COMB: highest attribute number + * + * Examples: + * limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2 + * => allows an AP and a STA that must match BIs + * + * numbers = [ #{AP, P2P-GO} <= 8 ], BI min gcd, channels = 1, max = 8, + * => allows 8 of AP/GO that can have BI gcd >= min gcd + * + * numbers = [ #{STA} <= 2 ], channels = 2, max = 2 + * => allows two STAs on different channels + * + * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4 + * => allows a STA plus three P2P interfaces + * + * The list of these four possibilities could completely be contained + * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate + * that any of these groups must match. + * + * "Combinations" of just a single interface will not be listed here, + * a single interface of any valid interface type is assumed to always + * be possible by itself. This means that implicitly, for each valid + * interface type, the following group always exists: + * numbers = [ #{} <= 1 ], channels = 1, max = 1 + */ +enum nl80211_if_combination_attrs { + NL80211_IFACE_COMB_UNSPEC, + NL80211_IFACE_COMB_LIMITS, + NL80211_IFACE_COMB_MAXNUM, + NL80211_IFACE_COMB_STA_AP_BI_MATCH, + NL80211_IFACE_COMB_NUM_CHANNELS, + NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, + NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, + NL80211_IFACE_COMB_BI_MIN_GCD, + + /* keep last */ + NUM_NL80211_IFACE_COMB, + MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1 +}; + + +/** + * enum nl80211_plink_state - state of a mesh peer link finite state machine + * + * @NL80211_PLINK_LISTEN: initial state, considered the implicit + * state of non existent mesh peer links + * @NL80211_PLINK_OPN_SNT: mesh plink open frame has been sent to + * this mesh peer + * @NL80211_PLINK_OPN_RCVD: mesh plink open frame has been received + * from this mesh peer + * @NL80211_PLINK_CNF_RCVD: mesh plink confirm frame has been + * received from this mesh peer + * @NL80211_PLINK_ESTAB: mesh peer link is established + * @NL80211_PLINK_HOLDING: mesh peer link is being closed or cancelled + * @NL80211_PLINK_BLOCKED: all frames transmitted from this mesh + * plink are discarded + * @NUM_NL80211_PLINK_STATES: number of peer link states + * @MAX_NL80211_PLINK_STATES: highest numerical value of plink states + */ +enum nl80211_plink_state { + NL80211_PLINK_LISTEN, + NL80211_PLINK_OPN_SNT, + NL80211_PLINK_OPN_RCVD, + NL80211_PLINK_CNF_RCVD, + NL80211_PLINK_ESTAB, + NL80211_PLINK_HOLDING, + NL80211_PLINK_BLOCKED, + + /* keep last */ + NUM_NL80211_PLINK_STATES, + MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 +}; + +/** + * enum nl80211_plink_action - actions to perform in mesh peers + * + * @NL80211_PLINK_ACTION_NO_ACTION: perform no action + * @NL80211_PLINK_ACTION_OPEN: start mesh peer link establishment + * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer + * @NUM_NL80211_PLINK_ACTIONS: number of possible actions + */ +enum plink_actions { + NL80211_PLINK_ACTION_NO_ACTION, + NL80211_PLINK_ACTION_OPEN, + NL80211_PLINK_ACTION_BLOCK, + + NUM_NL80211_PLINK_ACTIONS, +}; + + +#define NL80211_KCK_LEN 16 +#define NL80211_KEK_LEN 16 +#define NL80211_REPLAY_CTR_LEN 8 + +/** + * enum nl80211_rekey_data - attributes for GTK rekey offload + * @__NL80211_REKEY_DATA_INVALID: invalid number for nested attributes + * @NL80211_REKEY_DATA_KEK: key encryption key (binary) + * @NL80211_REKEY_DATA_KCK: key confirmation key (binary) + * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary) + * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal) + * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal) + */ +enum nl80211_rekey_data { + __NL80211_REKEY_DATA_INVALID, + NL80211_REKEY_DATA_KEK, + NL80211_REKEY_DATA_KCK, + NL80211_REKEY_DATA_REPLAY_CTR, + + /* keep last */ + NUM_NL80211_REKEY_DATA, + MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 1 +}; + +/** + * enum nl80211_hidden_ssid - values for %NL80211_ATTR_HIDDEN_SSID + * @NL80211_HIDDEN_SSID_NOT_IN_USE: do not hide SSID (i.e., broadcast it in + * Beacon frames) + * @NL80211_HIDDEN_SSID_ZERO_LEN: hide SSID by using zero-length SSID element + * in Beacon frames + * @NL80211_HIDDEN_SSID_ZERO_CONTENTS: hide SSID by using correct length of SSID + * element in Beacon frames but zero out each byte in the SSID + */ +enum nl80211_hidden_ssid { + NL80211_HIDDEN_SSID_NOT_IN_USE, + NL80211_HIDDEN_SSID_ZERO_LEN, + NL80211_HIDDEN_SSID_ZERO_CONTENTS +}; + +/** + * enum nl80211_sta_wme_attr - station WME attributes + * @__NL80211_STA_WME_INVALID: invalid number for nested attribute + * @NL80211_STA_WME_UAPSD_QUEUES: bitmap of uapsd queues. the format + * is the same as the AC bitmap in the QoS info field. + * @NL80211_STA_WME_MAX_SP: max service period. the format is the same + * as the MAX_SP field in the QoS info field (but already shifted down). + * @__NL80211_STA_WME_AFTER_LAST: internal + * @NL80211_STA_WME_MAX: highest station WME attribute + */ +enum nl80211_sta_wme_attr { + __NL80211_STA_WME_INVALID, + NL80211_STA_WME_UAPSD_QUEUES, + NL80211_STA_WME_MAX_SP, + + /* keep last */ + __NL80211_STA_WME_AFTER_LAST, + NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1 +}; + +/** + * enum nl80211_pmksa_candidate_attr - attributes for PMKSA caching candidates + * @__NL80211_PMKSA_CANDIDATE_INVALID: invalid number for nested attributes + * @NL80211_PMKSA_CANDIDATE_INDEX: candidate index (u32; the smaller, the higher + * priority) + * @NL80211_PMKSA_CANDIDATE_BSSID: candidate BSSID (6 octets) + * @NL80211_PMKSA_CANDIDATE_PREAUTH: RSN pre-authentication supported (flag) + * @NUM_NL80211_PMKSA_CANDIDATE: number of PMKSA caching candidate attributes + * (internal) + * @MAX_NL80211_PMKSA_CANDIDATE: highest PMKSA caching candidate attribute + * (internal) + */ +enum nl80211_pmksa_candidate_attr { + __NL80211_PMKSA_CANDIDATE_INVALID, + NL80211_PMKSA_CANDIDATE_INDEX, + NL80211_PMKSA_CANDIDATE_BSSID, + NL80211_PMKSA_CANDIDATE_PREAUTH, + + /* keep last */ + NUM_NL80211_PMKSA_CANDIDATE, + MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1 +}; + +/** + * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION + * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request + * @NL80211_TDLS_SETUP: Setup TDLS link + * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established + * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link + * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link + */ +enum nl80211_tdls_operation { + NL80211_TDLS_DISCOVERY_REQ, + NL80211_TDLS_SETUP, + NL80211_TDLS_TEARDOWN, + NL80211_TDLS_ENABLE_LINK, + NL80211_TDLS_DISABLE_LINK, +}; + +/* + * enum nl80211_ap_sme_features - device-integrated AP features + * Reserved for future use, no bits are defined in + * NL80211_ATTR_DEVICE_AP_SME yet. +enum nl80211_ap_sme_features { +}; + */ + +/** + * enum nl80211_feature_flags - device/driver features + * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back + * TX status to the socket error queue when requested with the + * socket option. + * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates. + * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up + * the connected inactive stations in AP mode. + * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested + * to work properly to suppport receiving regulatory hints from + * cellular base stations. + * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only + * here to reserve the value for API/ABI compatibility) + * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of + * equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station + * mode + * @NL80211_FEATURE_LOW_PRIORITY_SCAN: This driver supports low priority scan + * @NL80211_FEATURE_SCAN_FLUSH: Scan flush is supported + * @NL80211_FEATURE_AP_SCAN: Support scanning using an AP vif + * @NL80211_FEATURE_VIF_TXPOWER: The driver supports per-vif TX power setting + * @NL80211_FEATURE_NEED_OBSS_SCAN: The driver expects userspace to perform + * OBSS scans and generate 20/40 BSS coex reports. This flag is used only + * for drivers implementing the CONNECT API, for AUTH/ASSOC it is implied. + * @NL80211_FEATURE_P2P_GO_CTWIN: P2P GO implementation supports CT Window + * setting + * @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic + * powersave + * @NL80211_FEATURE_FULL_AP_CLIENT_STATE: The driver supports full state + * transitions for AP clients. Without this flag (and if the driver + * doesn't have the AP SME in the device) the driver supports adding + * stations only when they're associated and adds them in associated + * state (to later be transitioned into authorized), with this flag + * they should be added before even sending the authentication reply + * and then transitioned into authenticated, associated and authorized + * states using station flags. + * Note that even for drivers that support this, the default is to add + * stations in authenticated/associated state, so to add unauthenticated + * stations the authenticated/associated bits have to be set in the mask. + * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits + * (HT40, VHT 80/160 MHz) if this flag is set + * @NL80211_FEATURE_USERSPACE_MPM: This driver supports a userspace Mesh + * Peering Management entity which may be implemented by registering for + * beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is + * still generated by the driver. + * @NL80211_FEATURE_ACTIVE_MONITOR: This driver supports an active monitor + * interface. An active monitor interface behaves like a normal monitor + * interface, but gets added to the driver. It ensures that incoming + * unicast packets directed at the configured interface address get ACKed. + * @NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE: This driver supports dynamic + * channel bandwidth change (e.g., HT 20 <-> 40 MHz channel) during the + * lifetime of a BSS. + * @NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES: This device adds a DS Parameter + * Set IE to probe requests. + * @NL80211_FEATURE_WFA_TPC_IE_IN_PROBES: This device adds a WFA TPC Report IE + * to probe requests. + * @NL80211_FEATURE_QUIET: This device, in client mode, supports Quiet Period + * requests sent to it by an AP. + * @NL80211_FEATURE_TX_POWER_INSERTION: This device is capable of inserting the + * current tx power value into the TPC Report IE in the spectrum + * management TPC Report action frame, and in the Radio Measurement Link + * Measurement Report action frame. + * @NL80211_FEATURE_ACKTO_ESTIMATION: This driver supports dynamic ACK timeout + * estimation (dynack). %NL80211_ATTR_WIPHY_DYN_ACK flag attribute is used + * to enable dynack. + * @NL80211_FEATURE_STATIC_SMPS: Device supports static spatial + * multiplexing powersave, ie. can turn off all but one chain + * even on HT connections that should be using more chains. + * @NL80211_FEATURE_DYNAMIC_SMPS: Device supports dynamic spatial + * multiplexing powersave, ie. can turn off all but one chain + * and then wake the rest up as required after, for example, + * rts/cts handshake. + * @NL80211_FEATURE_SUPPORTS_WMM_ADMISSION: the device supports setting up WMM + * TSPEC sessions (TID aka TSID 0-7) with the %NL80211_CMD_ADD_TX_TS + * command. Standard IEEE 802.11 TSPEC setup is not yet supported, it + * needs to be able to handle Block-Ack agreements and other things. + * @NL80211_FEATURE_MAC_ON_CREATE: Device supports configuring + * the vif's MAC address upon creation. + * See 'macaddr' field in the vif_params (cfg80211.h). + * @NL80211_FEATURE_TDLS_CHANNEL_SWITCH: Driver supports channel switching when + * operating as a TDLS peer. + * @NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR: This device/driver supports using a + * random MAC address during scan (if the device is unassociated); the + * %NL80211_SCAN_FLAG_RANDOM_ADDR flag may be set for scans and the MAC + * address mask/value will be used. + * @NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR: This device/driver supports + * using a random MAC address for every scan iteration during scheduled + * scan (while not associated), the %NL80211_SCAN_FLAG_RANDOM_ADDR may + * be set for scheduled scan and the MAC address mask/value will be used. + * @NL80211_FEATURE_ND_RANDOM_MAC_ADDR: This device/driver supports using a + * random MAC address for every scan iteration during "net detect", i.e. + * scan in unassociated WoWLAN, the %NL80211_SCAN_FLAG_RANDOM_ADDR may + * be set for scheduled scan and the MAC address mask/value will be used. + */ +enum nl80211_feature_flags { + NL80211_FEATURE_SK_TX_STATUS = 1 << 0, + NL80211_FEATURE_HT_IBSS = 1 << 1, + NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, + NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3, + NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4, + NL80211_FEATURE_SAE = 1 << 5, + NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6, + NL80211_FEATURE_SCAN_FLUSH = 1 << 7, + NL80211_FEATURE_AP_SCAN = 1 << 8, + NL80211_FEATURE_VIF_TXPOWER = 1 << 9, + NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10, + NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11, + NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12, + /* bit 13 is reserved */ + NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14, + NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15, + NL80211_FEATURE_USERSPACE_MPM = 1 << 16, + NL80211_FEATURE_ACTIVE_MONITOR = 1 << 17, + NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE = 1 << 18, + NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES = 1 << 19, + NL80211_FEATURE_WFA_TPC_IE_IN_PROBES = 1 << 20, + NL80211_FEATURE_QUIET = 1 << 21, + NL80211_FEATURE_TX_POWER_INSERTION = 1 << 22, + NL80211_FEATURE_ACKTO_ESTIMATION = 1 << 23, + NL80211_FEATURE_STATIC_SMPS = 1 << 24, + NL80211_FEATURE_DYNAMIC_SMPS = 1 << 25, + NL80211_FEATURE_SUPPORTS_WMM_ADMISSION = 1 << 26, + NL80211_FEATURE_MAC_ON_CREATE = 1 << 27, + NL80211_FEATURE_TDLS_CHANNEL_SWITCH = 1 << 28, + NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR = 1 << 29, + NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR = 1 << 30, + NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 1U << 31, +}; + +/** + * enum nl80211_ext_feature_index - bit index of extended features. + * @NL80211_EXT_FEATURE_VHT_IBSS: This driver supports IBSS with VHT datarates. + * @NL80211_EXT_FEATURE_RRM: This driver supports RRM. When featured, user can + * can request to use RRM (see %NL80211_ATTR_USE_RRM) with + * %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set + * the ASSOC_REQ_USE_RRM flag in the association request even if + * NL80211_FEATURE_QUIET is not advertized. + * @NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER: This device supports MU-MIMO air + * sniffer which means that it can be configured to hear packets from + * certain groups which can be configured by the + * %NL80211_ATTR_MU_MIMO_GROUP_DATA attribute, + * or can be configured to follow a station by configuring the + * %NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR attribute. + * @NL80211_EXT_FEATURE_SCAN_START_TIME: This driver includes the actual + * time the scan started in scan results event. The time is the TSF of + * the BSS that the interface that requested the scan is connected to + * (if available). + * @NL80211_EXT_FEATURE_BSS_PARENT_TSF: Per BSS, this driver reports the + * time the last beacon/probe was received. The time is the TSF of the + * BSS that the interface that requested the scan is connected to + * (if available). + * @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of + * channel dwell time. + * @NL80211_EXT_FEATURE_BEACON_RATE_LEGACY: Driver supports beacon rate + * configuration (AP/mesh), supporting a legacy (non HT/VHT) rate. + * @NL80211_EXT_FEATURE_BEACON_RATE_HT: Driver supports beacon rate + * configuration (AP/mesh) with HT rates. + * @NL80211_EXT_FEATURE_BEACON_RATE_VHT: Driver supports beacon rate + * configuration (AP/mesh) with VHT rates. + * @NL80211_EXT_FEATURE_FILS_STA: This driver supports Fast Initial Link Setup + * with user space SME (NL80211_CMD_AUTHENTICATE) in station mode. + * @NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA: This driver supports randomized TA + * in @NL80211_CMD_FRAME while not associated. + * @NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED: This driver supports + * randomized TA in @NL80211_CMD_FRAME while associated. + * @NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI: The driver supports sched_scan + * for reporting BSSs with better RSSI than the current connected BSS + * (%NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI). + * @NL80211_EXT_FEATURE_CQM_RSSI_LIST: With this driver the + * %NL80211_ATTR_CQM_RSSI_THOLD attribute accepts a list of zero or more + * RSSI threshold values to monitor rather than exactly one threshold. + * @NL80211_EXT_FEATURE_FILS_SK_OFFLOAD: Driver SME supports FILS shared key + * authentication with %NL80211_CMD_CONNECT. + * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK: Device wants to do 4-way + * handshake with PSK in station mode (PSK is passed as part of the connect + * and associate commands), doing it in the host might not be supported. + * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X: Device wants to do doing 4-way + * handshake with 802.1X in station mode (will pass EAP frames to the host + * and accept the set_pmk/del_pmk commands), doing it in the host might not + * be supported. + * @NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME: Driver is capable of overriding + * the max channel attribute in the FILS request params IE with the + * actual dwell time. + * @NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP: Driver accepts broadcast probe + * response + * @NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE: Driver supports sending + * the first probe request in each channel at rate of at least 5.5Mbps. + * @NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION: Driver supports + * probe request tx deferral and suppression + * @NL80211_EXT_FEATURE_MFP_OPTIONAL: Driver supports the %NL80211_MFP_OPTIONAL + * value in %NL80211_ATTR_USE_MFP. + * @NL80211_EXT_FEATURE_LOW_SPAN_SCAN: Driver supports low span scan. + * @NL80211_EXT_FEATURE_LOW_POWER_SCAN: Driver supports low power scan. + * @NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN: Driver supports high accuracy scan. + * @NL80211_EXT_FEATURE_DFS_OFFLOAD: HW/driver will offload DFS actions. + * Device or driver will do all DFS-related actions by itself, + * informing user-space about CAC progress, radar detection event, + * channel change triggered by radar detection event. + * No need to start CAC from user-space, no need to react to + * "radar detected" event. + * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211: Driver supports sending and + * receiving control port frames over nl80211 instead of the netdevice. + * @NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT: This driver/device supports + * (average) ACK signal strength reporting. + * @NL80211_EXT_FEATURE_TXQS: Driver supports FQ-CoDel-enabled intermediate + * TXQs. + * @NL80211_EXT_FEATURE_SCAN_RANDOM_SN: Driver/device supports randomizing the + * SN in probe request frames if requested by %NL80211_SCAN_FLAG_RANDOM_SN. + * @NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT: Driver/device can omit all data + * except for supported rates from the probe request content if requested + * by the %NL80211_SCAN_FLAG_MIN_PREQ_CONTENT flag. + * @NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER: Driver supports enabling fine + * timing measurement responder role. + * + * @NL80211_EXT_FEATURE_CAN_REPLACE_PTK0: Driver/device confirm that they are + * able to rekey an in-use key correctly. Userspace must not rekey PTK keys + * if this flag is not set. Ignoring this can leak clear text packets and/or + * freeze the connection. + * @NL80211_EXT_FEATURE_EXT_KEY_ID: Driver supports "Extended Key ID for + * Individually Addressed Frames" from IEEE802.11-2016. + * + * @NL80211_EXT_FEATURE_AIRTIME_FAIRNESS: Driver supports getting airtime + * fairness for transmitted packets and has enabled airtime fairness + * scheduling. + * + * @NL80211_EXT_FEATURE_AP_PMKSA_CACHING: Driver/device supports PMKSA caching + * (set/del PMKSA operations) in AP mode. + * + * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Driver supports + * filtering of sched scan results using band specific RSSI thresholds. + * + * @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power + * to a station. + * + * @NL80211_EXT_FEATURE_SAE_OFFLOAD: Device wants to do SAE authentication in + * station mode (SAE password is passed as part of the connect command). + * + * @NUM_NL80211_EXT_FEATURES: number of extended features. + * @MAX_NL80211_EXT_FEATURES: highest extended feature index. + */ +enum nl80211_ext_feature_index { + NL80211_EXT_FEATURE_VHT_IBSS, + NL80211_EXT_FEATURE_RRM, + NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER, + NL80211_EXT_FEATURE_SCAN_START_TIME, + NL80211_EXT_FEATURE_BSS_PARENT_TSF, + NL80211_EXT_FEATURE_SET_SCAN_DWELL, + NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, + NL80211_EXT_FEATURE_BEACON_RATE_HT, + NL80211_EXT_FEATURE_BEACON_RATE_VHT, + NL80211_EXT_FEATURE_FILS_STA, + NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA, + NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED, + NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI, + NL80211_EXT_FEATURE_CQM_RSSI_LIST, + NL80211_EXT_FEATURE_FILS_SK_OFFLOAD, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X, + NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME, + NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP, + NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE, + NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION, + NL80211_EXT_FEATURE_MFP_OPTIONAL, + NL80211_EXT_FEATURE_LOW_SPAN_SCAN, + NL80211_EXT_FEATURE_LOW_POWER_SCAN, + NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN, + NL80211_EXT_FEATURE_DFS_OFFLOAD, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211, + NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT, + /* we renamed this - stay compatible */ + NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT = NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT, + NL80211_EXT_FEATURE_TXQS, + NL80211_EXT_FEATURE_SCAN_RANDOM_SN, + NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT, + NL80211_EXT_FEATURE_CAN_REPLACE_PTK0, + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER, + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS, + NL80211_EXT_FEATURE_AP_PMKSA_CACHING, + NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD, + NL80211_EXT_FEATURE_EXT_KEY_ID, + NL80211_EXT_FEATURE_STA_TX_PWR, + NL80211_EXT_FEATURE_SAE_OFFLOAD, + + /* add new features before the definition below */ + NUM_NL80211_EXT_FEATURES, + MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1 +}; + +/** + * enum nl80211_probe_resp_offload_support_attr - optional supported + * protocols for probe-response offloading by the driver/FW. + * To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute. + * Each enum value represents a bit in the bitmap of supported + * protocols. Typically a subset of probe-requests belonging to a + * supported protocol will be excluded from offload and uploaded + * to the host. + * + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: Support for WPS ver. 1 + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: Support for WPS ver. 2 + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: Support for P2P + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: Support for 802.11u + */ +enum nl80211_probe_resp_offload_support_attr { + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS = 1<<0, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 = 1<<1, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P = 1<<2, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 1<<3, +}; + +/** + * enum nl80211_connect_failed_reason - connection request failed reasons + * @NL80211_CONN_FAIL_MAX_CLIENTS: Maximum number of clients that can be + * handled by the AP is reached. + * @NL80211_CONN_FAIL_BLOCKED_CLIENT: Connection request is rejected due to ACL. + */ +enum nl80211_connect_failed_reason { + NL80211_CONN_FAIL_MAX_CLIENTS, + NL80211_CONN_FAIL_BLOCKED_CLIENT, +}; + +/** + * enum nl80211_timeout_reason - timeout reasons + * + * @NL80211_TIMEOUT_UNSPECIFIED: Timeout reason unspecified. + * @NL80211_TIMEOUT_SCAN: Scan (AP discovery) timed out. + * @NL80211_TIMEOUT_AUTH: Authentication timed out. + * @NL80211_TIMEOUT_ASSOC: Association timed out. + */ +enum nl80211_timeout_reason { + NL80211_TIMEOUT_UNSPECIFIED, + NL80211_TIMEOUT_SCAN, + NL80211_TIMEOUT_AUTH, + NL80211_TIMEOUT_ASSOC, +}; + +/** + * enum nl80211_scan_flags - scan request control flags + * + * Scan request control flags are used to control the handling + * of NL80211_CMD_TRIGGER_SCAN and NL80211_CMD_START_SCHED_SCAN + * requests. + * + * NL80211_SCAN_FLAG_LOW_SPAN, NL80211_SCAN_FLAG_LOW_POWER, and + * NL80211_SCAN_FLAG_HIGH_ACCURACY flags are exclusive of each other, i.e., only + * one of them can be used in the request. + * + * @NL80211_SCAN_FLAG_LOW_PRIORITY: scan request has low priority + * @NL80211_SCAN_FLAG_FLUSH: flush cache before scanning + * @NL80211_SCAN_FLAG_AP: force a scan even if the interface is configured + * as AP and the beaconing has already been configured. This attribute is + * dangerous because will destroy stations performance as a lot of frames + * will be lost while scanning off-channel, therefore it must be used only + * when really needed + * @NL80211_SCAN_FLAG_RANDOM_ADDR: use a random MAC address for this scan (or + * for scheduled scan: a different one for every scan iteration). When the + * flag is set, depending on device capabilities the @NL80211_ATTR_MAC and + * @NL80211_ATTR_MAC_MASK attributes may also be given in which case only + * the masked bits will be preserved from the MAC address and the remainder + * randomised. If the attributes are not given full randomisation (46 bits, + * locally administered 1, multicast 0) is assumed. + * This flag must not be requested when the feature isn't supported, check + * the nl80211 feature flags for the device. + * @NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME: fill the dwell time in the FILS + * request parameters IE in the probe request + * @NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP: accept broadcast probe responses + * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE: send probe request frames at + * rate of at least 5.5M. In case non OCE AP is discovered in the channel, + * only the first probe req in the channel will be sent in high rate. + * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION: allow probe request + * tx deferral (dot11FILSProbeDelay shall be set to 15ms) + * and suppression (if it has received a broadcast Probe Response frame, + * Beacon frame or FILS Discovery frame from an AP that the STA considers + * a suitable candidate for (re-)association - suitable in terms of + * SSID and/or RSSI. + * @NL80211_SCAN_FLAG_LOW_SPAN: Span corresponds to the total time taken to + * accomplish the scan. Thus, this flag intends the driver to perform the + * scan request with lesser span/duration. It is specific to the driver + * implementations on how this is accomplished. Scan accuracy may get + * impacted with this flag. + * @NL80211_SCAN_FLAG_LOW_POWER: This flag intends the scan attempts to consume + * optimal possible power. Drivers can resort to their specific means to + * optimize the power. Scan accuracy may get impacted with this flag. + * @NL80211_SCAN_FLAG_HIGH_ACCURACY: Accuracy here intends to the extent of scan + * results obtained. Thus HIGH_ACCURACY scan flag aims to get maximum + * possible scan results. This flag hints the driver to use the best + * possible scan configuration to improve the accuracy in scanning. + * Latency and power use may get impacted with this flag. + * @NL80211_SCAN_FLAG_RANDOM_SN: randomize the sequence number in probe + * request frames from this scan to avoid correlation/tracking being + * possible. + * @NL80211_SCAN_FLAG_MIN_PREQ_CONTENT: minimize probe request content to + * only have supported rates and no additional capabilities (unless + * added by userspace explicitly.) + */ +enum nl80211_scan_flags { + NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, + NL80211_SCAN_FLAG_FLUSH = 1<<1, + NL80211_SCAN_FLAG_AP = 1<<2, + NL80211_SCAN_FLAG_RANDOM_ADDR = 1<<3, + NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME = 1<<4, + NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP = 1<<5, + NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE = 1<<6, + NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 1<<7, + NL80211_SCAN_FLAG_LOW_SPAN = 1<<8, + NL80211_SCAN_FLAG_LOW_POWER = 1<<9, + NL80211_SCAN_FLAG_HIGH_ACCURACY = 1<<10, + NL80211_SCAN_FLAG_RANDOM_SN = 1<<11, + NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1<<12, +}; + +/** + * enum nl80211_acl_policy - access control policy + * + * Access control policy is applied on a MAC list set by + * %NL80211_CMD_START_AP and %NL80211_CMD_SET_MAC_ACL, to + * be used with %NL80211_ATTR_ACL_POLICY. + * + * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are + * listed in ACL, i.e. allow all the stations which are not listed + * in ACL to authenticate. + * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow the stations which are listed + * in ACL, i.e. deny all the stations which are not listed in ACL. + */ +enum nl80211_acl_policy { + NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED, + NL80211_ACL_POLICY_DENY_UNLESS_LISTED, +}; + +/** + * enum nl80211_smps_mode - SMPS mode + * + * Requested SMPS mode (for AP mode) + * + * @NL80211_SMPS_OFF: SMPS off (use all antennas). + * @NL80211_SMPS_STATIC: static SMPS (use a single antenna) + * @NL80211_SMPS_DYNAMIC: dynamic smps (start with a single antenna and + * turn on other antennas after CTS/RTS). + */ +enum nl80211_smps_mode { + NL80211_SMPS_OFF, + NL80211_SMPS_STATIC, + NL80211_SMPS_DYNAMIC, + + __NL80211_SMPS_AFTER_LAST, + NL80211_SMPS_MAX = __NL80211_SMPS_AFTER_LAST - 1 +}; + +/** + * enum nl80211_radar_event - type of radar event for DFS operation + * + * Type of event to be used with NL80211_ATTR_RADAR_EVENT to inform userspace + * about detected radars or success of the channel available check (CAC) + * + * @NL80211_RADAR_DETECTED: A radar pattern has been detected. The channel is + * now unusable. + * @NL80211_RADAR_CAC_FINISHED: Channel Availability Check has been finished, + * the channel is now available. + * @NL80211_RADAR_CAC_ABORTED: Channel Availability Check has been aborted, no + * change to the channel status. + * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is + * over, channel becomes usable. + * @NL80211_RADAR_PRE_CAC_EXPIRED: Channel Availability Check done on this + * non-operating channel is expired and no longer valid. New CAC must + * be done on this channel before starting the operation. This is not + * applicable for ETSI dfs domain where pre-CAC is valid for ever. + * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started, + * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled. + */ +enum nl80211_radar_event { + NL80211_RADAR_DETECTED, + NL80211_RADAR_CAC_FINISHED, + NL80211_RADAR_CAC_ABORTED, + NL80211_RADAR_NOP_FINISHED, + NL80211_RADAR_PRE_CAC_EXPIRED, + NL80211_RADAR_CAC_STARTED, +}; + +/** + * enum nl80211_dfs_state - DFS states for channels + * + * Channel states used by the DFS code. + * + * @NL80211_DFS_USABLE: The channel can be used, but channel availability + * check (CAC) must be performed before using it for AP or IBSS. + * @NL80211_DFS_UNAVAILABLE: A radar has been detected on this channel, it + * is therefore marked as not available. + * @NL80211_DFS_AVAILABLE: The channel has been CAC checked and is available. + */ +enum nl80211_dfs_state { + NL80211_DFS_USABLE, + NL80211_DFS_UNAVAILABLE, + NL80211_DFS_AVAILABLE, +}; + +/** + * enum enum nl80211_protocol_features - nl80211 protocol features + * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting + * wiphy dumps (if requested by the application with the attribute + * %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the + * wiphy dump by %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFINDEX or + * %NL80211_ATTR_WDEV. + */ +enum nl80211_protocol_features { + NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0, +}; + +/** + * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers + * + * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified. + * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol. + * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol. + * @NL80211_CRIT_PROTO_APIPA: APIPA protocol. + * @NUM_NL80211_CRIT_PROTO: must be kept last. + */ +enum nl80211_crit_proto_id { + NL80211_CRIT_PROTO_UNSPEC, + NL80211_CRIT_PROTO_DHCP, + NL80211_CRIT_PROTO_EAPOL, + NL80211_CRIT_PROTO_APIPA, + /* add other protocols before this one */ + NUM_NL80211_CRIT_PROTO +}; + +/* maximum duration for critical protocol measures */ +#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */ + +/** + * enum nl80211_rxmgmt_flags - flags for received management frame. + * + * Used by cfg80211_rx_mgmt() + * + * @NL80211_RXMGMT_FLAG_ANSWERED: frame was answered by device/driver. + * @NL80211_RXMGMT_FLAG_EXTERNAL_AUTH: Host driver intends to offload + * the authentication. Exclusively defined for host drivers that + * advertises the SME functionality but would like the userspace + * to handle certain authentication algorithms (e.g. SAE). + */ +enum nl80211_rxmgmt_flags { + NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0, + NL80211_RXMGMT_FLAG_EXTERNAL_AUTH = 1 << 1, +}; + +/* + * If this flag is unset, the lower 24 bits are an OUI, if set + * a Linux nl80211 vendor ID is used (no such IDs are allocated + * yet, so that's not valid so far) + */ +#define NL80211_VENDOR_ID_IS_LINUX 0x80000000 + +/** + * struct nl80211_vendor_cmd_info - vendor command data + * @vendor_id: If the %NL80211_VENDOR_ID_IS_LINUX flag is clear, then the + * value is a 24-bit OUI; if it is set then a separately allocated ID + * may be used, but no such IDs are allocated yet. New IDs should be + * added to this file when needed. + * @subcmd: sub-command ID for the command + */ +struct nl80211_vendor_cmd_info { + __u32 vendor_id; + __u32 subcmd; +}; + +/** + * enum nl80211_tdls_peer_capability - TDLS peer flags. + * + * Used by tdls_mgmt() to determine which conditional elements need + * to be added to TDLS Setup frames. + * + * @NL80211_TDLS_PEER_HT: TDLS peer is HT capable. + * @NL80211_TDLS_PEER_VHT: TDLS peer is VHT capable. + * @NL80211_TDLS_PEER_WMM: TDLS peer is WMM capable. + */ +enum nl80211_tdls_peer_capability { + NL80211_TDLS_PEER_HT = 1<<0, + NL80211_TDLS_PEER_VHT = 1<<1, + NL80211_TDLS_PEER_WMM = 1<<2, +}; + +/** + * enum nl80211_sched_scan_plan - scanning plan for scheduled scan + * @__NL80211_SCHED_SCAN_PLAN_INVALID: attribute number 0 is reserved + * @NL80211_SCHED_SCAN_PLAN_INTERVAL: interval between scan iterations. In + * seconds (u32). + * @NL80211_SCHED_SCAN_PLAN_ITERATIONS: number of scan iterations in this + * scan plan (u32). The last scan plan must not specify this attribute + * because it will run infinitely. A value of zero is invalid as it will + * make the scan plan meaningless. + * @NL80211_SCHED_SCAN_PLAN_MAX: highest scheduled scan plan attribute number + * currently defined + * @__NL80211_SCHED_SCAN_PLAN_AFTER_LAST: internal use + */ +enum nl80211_sched_scan_plan { + __NL80211_SCHED_SCAN_PLAN_INVALID, + NL80211_SCHED_SCAN_PLAN_INTERVAL, + NL80211_SCHED_SCAN_PLAN_ITERATIONS, + + /* keep last */ + __NL80211_SCHED_SCAN_PLAN_AFTER_LAST, + NL80211_SCHED_SCAN_PLAN_MAX = + __NL80211_SCHED_SCAN_PLAN_AFTER_LAST - 1 +}; + +/** + * struct nl80211_bss_select_rssi_adjust - RSSI adjustment parameters. + * + * @band: band of BSS that must match for RSSI value adjustment. The value + * of this field is according to &enum nl80211_band. + * @delta: value used to adjust the RSSI value of matching BSS in dB. + */ +struct nl80211_bss_select_rssi_adjust { + __u8 band; + __s8 delta; +} __attribute__((packed)); + +/** + * enum nl80211_bss_select_attr - attributes for bss selection. + * + * @__NL80211_BSS_SELECT_ATTR_INVALID: reserved. + * @NL80211_BSS_SELECT_ATTR_RSSI: Flag indicating only RSSI-based BSS selection + * is requested. + * @NL80211_BSS_SELECT_ATTR_BAND_PREF: attribute indicating BSS + * selection should be done such that the specified band is preferred. + * When there are multiple BSS-es in the preferred band, the driver + * shall use RSSI-based BSS selection as a second step. The value of + * this attribute is according to &enum nl80211_band (u32). + * @NL80211_BSS_SELECT_ATTR_RSSI_ADJUST: When present the RSSI level for + * BSS-es in the specified band is to be adjusted before doing + * RSSI-based BSS selection. The attribute value is a packed structure + * value as specified by &struct nl80211_bss_select_rssi_adjust. + * @NL80211_BSS_SELECT_ATTR_MAX: highest bss select attribute number. + * @__NL80211_BSS_SELECT_ATTR_AFTER_LAST: internal use. + * + * One and only one of these attributes are found within %NL80211_ATTR_BSS_SELECT + * for %NL80211_CMD_CONNECT. It specifies the required BSS selection behaviour + * which the driver shall use. + */ +enum nl80211_bss_select_attr { + __NL80211_BSS_SELECT_ATTR_INVALID, + NL80211_BSS_SELECT_ATTR_RSSI, + NL80211_BSS_SELECT_ATTR_BAND_PREF, + NL80211_BSS_SELECT_ATTR_RSSI_ADJUST, + + /* keep last */ + __NL80211_BSS_SELECT_ATTR_AFTER_LAST, + NL80211_BSS_SELECT_ATTR_MAX = __NL80211_BSS_SELECT_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_nan_function_type - NAN function type + * + * Defines the function type of a NAN function + * + * @NL80211_NAN_FUNC_PUBLISH: function is publish + * @NL80211_NAN_FUNC_SUBSCRIBE: function is subscribe + * @NL80211_NAN_FUNC_FOLLOW_UP: function is follow-up + */ +enum nl80211_nan_function_type { + NL80211_NAN_FUNC_PUBLISH, + NL80211_NAN_FUNC_SUBSCRIBE, + NL80211_NAN_FUNC_FOLLOW_UP, + + /* keep last */ + __NL80211_NAN_FUNC_TYPE_AFTER_LAST, + NL80211_NAN_FUNC_MAX_TYPE = __NL80211_NAN_FUNC_TYPE_AFTER_LAST - 1, +}; + +/** + * enum nl80211_nan_publish_type - NAN publish tx type + * + * Defines how to send publish Service Discovery Frames + * + * @NL80211_NAN_SOLICITED_PUBLISH: publish function is solicited + * @NL80211_NAN_UNSOLICITED_PUBLISH: publish function is unsolicited + */ +enum nl80211_nan_publish_type { + NL80211_NAN_SOLICITED_PUBLISH = 1 << 0, + NL80211_NAN_UNSOLICITED_PUBLISH = 1 << 1, +}; + +/** + * enum nl80211_nan_func_term_reason - NAN functions termination reason + * + * Defines termination reasons of a NAN function + * + * @NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST: requested by user + * @NL80211_NAN_FUNC_TERM_REASON_TTL_EXPIRED: timeout + * @NL80211_NAN_FUNC_TERM_REASON_ERROR: errored + */ +enum nl80211_nan_func_term_reason { + NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST, + NL80211_NAN_FUNC_TERM_REASON_TTL_EXPIRED, + NL80211_NAN_FUNC_TERM_REASON_ERROR, +}; + +#define NL80211_NAN_FUNC_SERVICE_ID_LEN 6 +#define NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN 0xff +#define NL80211_NAN_FUNC_SRF_MAX_LEN 0xff + +/** + * enum nl80211_nan_func_attributes - NAN function attributes + * @__NL80211_NAN_FUNC_INVALID: invalid + * @NL80211_NAN_FUNC_TYPE: &enum nl80211_nan_function_type (u8). + * @NL80211_NAN_FUNC_SERVICE_ID: 6 bytes of the service ID hash as + * specified in NAN spec. This is a binary attribute. + * @NL80211_NAN_FUNC_PUBLISH_TYPE: relevant if the function's type is + * publish. Defines the transmission type for the publish Service Discovery + * Frame, see &enum nl80211_nan_publish_type. Its type is u8. + * @NL80211_NAN_FUNC_PUBLISH_BCAST: relevant if the function is a solicited + * publish. Should the solicited publish Service Discovery Frame be sent to + * the NAN Broadcast address. This is a flag. + * @NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE: relevant if the function's type is + * subscribe. Is the subscribe active. This is a flag. + * @NL80211_NAN_FUNC_FOLLOW_UP_ID: relevant if the function's type is follow up. + * The instance ID for the follow up Service Discovery Frame. This is u8. + * @NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID: relevant if the function's type + * is follow up. This is a u8. + * The requestor instance ID for the follow up Service Discovery Frame. + * @NL80211_NAN_FUNC_FOLLOW_UP_DEST: the MAC address of the recipient of the + * follow up Service Discovery Frame. This is a binary attribute. + * @NL80211_NAN_FUNC_CLOSE_RANGE: is this function limited for devices in a + * close range. The range itself (RSSI) is defined by the device. + * This is a flag. + * @NL80211_NAN_FUNC_TTL: strictly positive number of DWs this function should + * stay active. If not present infinite TTL is assumed. This is a u32. + * @NL80211_NAN_FUNC_SERVICE_INFO: array of bytes describing the service + * specific info. This is a binary attribute. + * @NL80211_NAN_FUNC_SRF: Service Receive Filter. This is a nested attribute. + * See &enum nl80211_nan_srf_attributes. + * @NL80211_NAN_FUNC_RX_MATCH_FILTER: Receive Matching filter. This is a nested + * attribute. It is a list of binary values. + * @NL80211_NAN_FUNC_TX_MATCH_FILTER: Transmit Matching filter. This is a + * nested attribute. It is a list of binary values. + * @NL80211_NAN_FUNC_INSTANCE_ID: The instance ID of the function. + * Its type is u8 and it cannot be 0. + * @NL80211_NAN_FUNC_TERM_REASON: NAN function termination reason. + * See &enum nl80211_nan_func_term_reason. + * + * @NUM_NL80211_NAN_FUNC_ATTR: internal + * @NL80211_NAN_FUNC_ATTR_MAX: highest NAN function attribute + */ +enum nl80211_nan_func_attributes { + __NL80211_NAN_FUNC_INVALID, + NL80211_NAN_FUNC_TYPE, + NL80211_NAN_FUNC_SERVICE_ID, + NL80211_NAN_FUNC_PUBLISH_TYPE, + NL80211_NAN_FUNC_PUBLISH_BCAST, + NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE, + NL80211_NAN_FUNC_FOLLOW_UP_ID, + NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID, + NL80211_NAN_FUNC_FOLLOW_UP_DEST, + NL80211_NAN_FUNC_CLOSE_RANGE, + NL80211_NAN_FUNC_TTL, + NL80211_NAN_FUNC_SERVICE_INFO, + NL80211_NAN_FUNC_SRF, + NL80211_NAN_FUNC_RX_MATCH_FILTER, + NL80211_NAN_FUNC_TX_MATCH_FILTER, + NL80211_NAN_FUNC_INSTANCE_ID, + NL80211_NAN_FUNC_TERM_REASON, + + /* keep last */ + NUM_NL80211_NAN_FUNC_ATTR, + NL80211_NAN_FUNC_ATTR_MAX = NUM_NL80211_NAN_FUNC_ATTR - 1 +}; + +/** + * enum nl80211_nan_srf_attributes - NAN Service Response filter attributes + * @__NL80211_NAN_SRF_INVALID: invalid + * @NL80211_NAN_SRF_INCLUDE: present if the include bit of the SRF set. + * This is a flag. + * @NL80211_NAN_SRF_BF: Bloom Filter. Present if and only if + * %NL80211_NAN_SRF_MAC_ADDRS isn't present. This attribute is binary. + * @NL80211_NAN_SRF_BF_IDX: index of the Bloom Filter. Mandatory if + * %NL80211_NAN_SRF_BF is present. This is a u8. + * @NL80211_NAN_SRF_MAC_ADDRS: list of MAC addresses for the SRF. Present if + * and only if %NL80211_NAN_SRF_BF isn't present. This is a nested + * attribute. Each nested attribute is a MAC address. + * @NUM_NL80211_NAN_SRF_ATTR: internal + * @NL80211_NAN_SRF_ATTR_MAX: highest NAN SRF attribute + */ +enum nl80211_nan_srf_attributes { + __NL80211_NAN_SRF_INVALID, + NL80211_NAN_SRF_INCLUDE, + NL80211_NAN_SRF_BF, + NL80211_NAN_SRF_BF_IDX, + NL80211_NAN_SRF_MAC_ADDRS, + + /* keep last */ + NUM_NL80211_NAN_SRF_ATTR, + NL80211_NAN_SRF_ATTR_MAX = NUM_NL80211_NAN_SRF_ATTR - 1, +}; + +/** + * enum nl80211_nan_match_attributes - NAN match attributes + * @__NL80211_NAN_MATCH_INVALID: invalid + * @NL80211_NAN_MATCH_FUNC_LOCAL: the local function that had the + * match. This is a nested attribute. + * See &enum nl80211_nan_func_attributes. + * @NL80211_NAN_MATCH_FUNC_PEER: the peer function + * that caused the match. This is a nested attribute. + * See &enum nl80211_nan_func_attributes. + * + * @NUM_NL80211_NAN_MATCH_ATTR: internal + * @NL80211_NAN_MATCH_ATTR_MAX: highest NAN match attribute + */ +enum nl80211_nan_match_attributes { + __NL80211_NAN_MATCH_INVALID, + NL80211_NAN_MATCH_FUNC_LOCAL, + NL80211_NAN_MATCH_FUNC_PEER, + + /* keep last */ + NUM_NL80211_NAN_MATCH_ATTR, + NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1 +}; + +/** + * nl80211_external_auth_action - Action to perform with external + * authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION. + * @NL80211_EXTERNAL_AUTH_START: Start the authentication. + * @NL80211_EXTERNAL_AUTH_ABORT: Abort the ongoing authentication. + */ +enum nl80211_external_auth_action { + NL80211_EXTERNAL_AUTH_START, + NL80211_EXTERNAL_AUTH_ABORT, +}; + +/** + * enum nl80211_ftm_responder_attributes - fine timing measurement + * responder attributes + * @__NL80211_FTM_RESP_ATTR_INVALID: Invalid + * @NL80211_FTM_RESP_ATTR_ENABLED: FTM responder is enabled + * @NL80211_FTM_RESP_ATTR_LCI: The content of Measurement Report Element + * (9.4.2.22 in 802.11-2016) with type 8 - LCI (9.4.2.22.10), + * i.e. starting with the measurement token + * @NL80211_FTM_RESP_ATTR_CIVIC: The content of Measurement Report Element + * (9.4.2.22 in 802.11-2016) with type 11 - Civic (Section 9.4.2.22.13), + * i.e. starting with the measurement token + * @__NL80211_FTM_RESP_ATTR_LAST: Internal + * @NL80211_FTM_RESP_ATTR_MAX: highest FTM responder attribute. + */ +enum nl80211_ftm_responder_attributes { + __NL80211_FTM_RESP_ATTR_INVALID, + + NL80211_FTM_RESP_ATTR_ENABLED, + NL80211_FTM_RESP_ATTR_LCI, + NL80211_FTM_RESP_ATTR_CIVICLOC, + + /* keep last */ + __NL80211_FTM_RESP_ATTR_LAST, + NL80211_FTM_RESP_ATTR_MAX = __NL80211_FTM_RESP_ATTR_LAST - 1, +}; + +/* + * enum nl80211_ftm_responder_stats - FTM responder statistics + * + * These attribute types are used with %NL80211_ATTR_FTM_RESPONDER_STATS + * when getting FTM responder statistics. + * + * @__NL80211_FTM_STATS_INVALID: attribute number 0 is reserved + * @NL80211_FTM_STATS_SUCCESS_NUM: number of FTM sessions in which all frames + * were ssfully answered (u32) + * @NL80211_FTM_STATS_PARTIAL_NUM: number of FTM sessions in which part of the + * frames were successfully answered (u32) + * @NL80211_FTM_STATS_FAILED_NUM: number of failed FTM sessions (u32) + * @NL80211_FTM_STATS_ASAP_NUM: number of ASAP sessions (u32) + * @NL80211_FTM_STATS_NON_ASAP_NUM: number of non-ASAP sessions (u32) + * @NL80211_FTM_STATS_TOTAL_DURATION_MSEC: total sessions durations - gives an + * indication of how much time the responder was busy (u64, msec) + * @NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM: number of unknown FTM triggers - + * triggers from initiators that didn't finish successfully the negotiation + * phase with the responder (u32) + * @NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM: number of FTM reschedule requests + * - initiator asks for a new scheduling although it already has scheduled + * FTM slot (u32) + * @NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM: number of FTM triggers out of + * scheduled window (u32) + * @NL80211_FTM_STATS_PAD: used for padding, ignore + * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal + * @NL80211_FTM_STATS_MAX: highest possible FTM responder stats attribute + */ +enum nl80211_ftm_responder_stats { + __NL80211_FTM_STATS_INVALID, + NL80211_FTM_STATS_SUCCESS_NUM, + NL80211_FTM_STATS_PARTIAL_NUM, + NL80211_FTM_STATS_FAILED_NUM, + NL80211_FTM_STATS_ASAP_NUM, + NL80211_FTM_STATS_NON_ASAP_NUM, + NL80211_FTM_STATS_TOTAL_DURATION_MSEC, + NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM, + NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM, + NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM, + NL80211_FTM_STATS_PAD, + + /* keep last */ + __NL80211_FTM_STATS_AFTER_LAST, + NL80211_FTM_STATS_MAX = __NL80211_FTM_STATS_AFTER_LAST - 1 +}; + +/** + * enum nl80211_preamble - frame preamble types + * @NL80211_PREAMBLE_LEGACY: legacy (HR/DSSS, OFDM, ERP PHY) preamble + * @NL80211_PREAMBLE_HT: HT preamble + * @NL80211_PREAMBLE_VHT: VHT preamble + * @NL80211_PREAMBLE_DMG: DMG preamble + */ +enum nl80211_preamble { + NL80211_PREAMBLE_LEGACY, + NL80211_PREAMBLE_HT, + NL80211_PREAMBLE_VHT, + NL80211_PREAMBLE_DMG, +}; + +/** + * enum nl80211_peer_measurement_type - peer measurement types + * @NL80211_PMSR_TYPE_INVALID: invalid/unused, needed as we use + * these numbers also for attributes + * + * @NL80211_PMSR_TYPE_FTM: flight time measurement + * + * @NUM_NL80211_PMSR_TYPES: internal + * @NL80211_PMSR_TYPE_MAX: highest type number + */ +enum nl80211_peer_measurement_type { + NL80211_PMSR_TYPE_INVALID, + + NL80211_PMSR_TYPE_FTM, + + NUM_NL80211_PMSR_TYPES, + NL80211_PMSR_TYPE_MAX = NUM_NL80211_PMSR_TYPES - 1 +}; + +/** + * enum nl80211_peer_measurement_status - peer measurement status + * @NL80211_PMSR_STATUS_SUCCESS: measurement completed successfully + * @NL80211_PMSR_STATUS_REFUSED: measurement was locally refused + * @NL80211_PMSR_STATUS_TIMEOUT: measurement timed out + * @NL80211_PMSR_STATUS_FAILURE: measurement failed, a type-dependent + * reason may be available in the response data + */ +enum nl80211_peer_measurement_status { + NL80211_PMSR_STATUS_SUCCESS, + NL80211_PMSR_STATUS_REFUSED, + NL80211_PMSR_STATUS_TIMEOUT, + NL80211_PMSR_STATUS_FAILURE, +}; + +/** + * enum nl80211_peer_measurement_req - peer measurement request attributes + * @__NL80211_PMSR_REQ_ATTR_INVALID: invalid + * + * @NL80211_PMSR_REQ_ATTR_DATA: This is a nested attribute with measurement + * type-specific request data inside. The attributes used are from the + * enums named nl80211_peer_measurement__req. + * @NL80211_PMSR_REQ_ATTR_GET_AP_TSF: include AP TSF timestamp, if supported + * (flag attribute) + * + * @NUM_NL80211_PMSR_REQ_ATTRS: internal + * @NL80211_PMSR_REQ_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_req { + __NL80211_PMSR_REQ_ATTR_INVALID, + + NL80211_PMSR_REQ_ATTR_DATA, + NL80211_PMSR_REQ_ATTR_GET_AP_TSF, + + /* keep last */ + NUM_NL80211_PMSR_REQ_ATTRS, + NL80211_PMSR_REQ_ATTR_MAX = NUM_NL80211_PMSR_REQ_ATTRS - 1 +}; + +/** + * enum nl80211_peer_measurement_resp - peer measurement response attributes + * @__NL80211_PMSR_RESP_ATTR_INVALID: invalid + * + * @NL80211_PMSR_RESP_ATTR_DATA: This is a nested attribute with measurement + * type-specific results inside. The attributes used are from the enums + * named nl80211_peer_measurement__resp. + * @NL80211_PMSR_RESP_ATTR_STATUS: u32 value with the measurement status + * (using values from &enum nl80211_peer_measurement_status.) + * @NL80211_PMSR_RESP_ATTR_HOST_TIME: host time (%CLOCK_BOOTTIME) when the + * result was measured; this value is not expected to be accurate to + * more than 20ms. (u64, nanoseconds) + * @NL80211_PMSR_RESP_ATTR_AP_TSF: TSF of the AP that the interface + * doing the measurement is connected to when the result was measured. + * This shall be accurately reported if supported and requested + * (u64, usec) + * @NL80211_PMSR_RESP_ATTR_FINAL: If results are sent to the host partially + * (*e.g. with FTM per-burst data) this flag will be cleared on all but + * the last result; if all results are combined it's set on the single + * result. + * @NL80211_PMSR_RESP_ATTR_PAD: padding for 64-bit attributes, ignore + * + * @NUM_NL80211_PMSR_RESP_ATTRS: internal + * @NL80211_PMSR_RESP_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_resp { + __NL80211_PMSR_RESP_ATTR_INVALID, + + NL80211_PMSR_RESP_ATTR_DATA, + NL80211_PMSR_RESP_ATTR_STATUS, + NL80211_PMSR_RESP_ATTR_HOST_TIME, + NL80211_PMSR_RESP_ATTR_AP_TSF, + NL80211_PMSR_RESP_ATTR_FINAL, + NL80211_PMSR_RESP_ATTR_PAD, + + /* keep last */ + NUM_NL80211_PMSR_RESP_ATTRS, + NL80211_PMSR_RESP_ATTR_MAX = NUM_NL80211_PMSR_RESP_ATTRS - 1 +}; + +/** + * enum nl80211_peer_measurement_peer_attrs - peer attributes for measurement + * @__NL80211_PMSR_PEER_ATTR_INVALID: invalid + * + * @NL80211_PMSR_PEER_ATTR_ADDR: peer's MAC address + * @NL80211_PMSR_PEER_ATTR_CHAN: channel definition, nested, using top-level + * attributes like %NL80211_ATTR_WIPHY_FREQ etc. + * @NL80211_PMSR_PEER_ATTR_REQ: This is a nested attribute indexed by + * measurement type, with attributes from the + * &enum nl80211_peer_measurement_req inside. + * @NL80211_PMSR_PEER_ATTR_RESP: This is a nested attribute indexed by + * measurement type, with attributes from the + * &enum nl80211_peer_measurement_resp inside. + * + * @NUM_NL80211_PMSR_PEER_ATTRS: internal + * @NL80211_PMSR_PEER_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_peer_attrs { + __NL80211_PMSR_PEER_ATTR_INVALID, + + NL80211_PMSR_PEER_ATTR_ADDR, + NL80211_PMSR_PEER_ATTR_CHAN, + NL80211_PMSR_PEER_ATTR_REQ, + NL80211_PMSR_PEER_ATTR_RESP, + + /* keep last */ + NUM_NL80211_PMSR_PEER_ATTRS, + NL80211_PMSR_PEER_ATTR_MAX = NUM_NL80211_PMSR_PEER_ATTRS - 1, +}; + +/** + * enum nl80211_peer_measurement_attrs - peer measurement attributes + * @__NL80211_PMSR_ATTR_INVALID: invalid + * + * @NL80211_PMSR_ATTR_MAX_PEERS: u32 attribute used for capability + * advertisement only, indicates the maximum number of peers + * measurements can be done with in a single request + * @NL80211_PMSR_ATTR_REPORT_AP_TSF: flag attribute in capability + * indicating that the connected AP's TSF can be reported in + * measurement results + * @NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR: flag attribute in capability + * indicating that MAC address randomization is supported. + * @NL80211_PMSR_ATTR_TYPE_CAPA: capabilities reported by the device, + * this contains a nesting indexed by measurement type, and + * type-specific capabilities inside, which are from the enums + * named nl80211_peer_measurement__capa. + * @NL80211_PMSR_ATTR_PEERS: nested attribute, the nesting index is + * meaningless, just a list of peers to measure with, with the + * sub-attributes taken from + * &enum nl80211_peer_measurement_peer_attrs. + * + * @NUM_NL80211_PMSR_ATTR: internal + * @NL80211_PMSR_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_attrs { + __NL80211_PMSR_ATTR_INVALID, + + NL80211_PMSR_ATTR_MAX_PEERS, + NL80211_PMSR_ATTR_REPORT_AP_TSF, + NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR, + NL80211_PMSR_ATTR_TYPE_CAPA, + NL80211_PMSR_ATTR_PEERS, + + /* keep last */ + NUM_NL80211_PMSR_ATTR, + NL80211_PMSR_ATTR_MAX = NUM_NL80211_PMSR_ATTR - 1 +}; + +/** + * enum nl80211_peer_measurement_ftm_capa - FTM capabilities + * @__NL80211_PMSR_FTM_CAPA_ATTR_INVALID: invalid + * + * @NL80211_PMSR_FTM_CAPA_ATTR_ASAP: flag attribute indicating ASAP mode + * is supported + * @NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP: flag attribute indicating non-ASAP + * mode is supported + * @NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI: flag attribute indicating if LCI + * data can be requested during the measurement + * @NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC: flag attribute indicating if civic + * location data can be requested during the measurement + * @NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES: u32 bitmap attribute of bits + * from &enum nl80211_preamble. + * @NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS: bitmap of values from + * &enum nl80211_chan_width indicating the supported channel + * bandwidths for FTM. Note that a higher channel bandwidth may be + * configured to allow for other measurements types with different + * bandwidth requirement in the same measurement. + * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT: u32 attribute indicating + * the maximum bursts exponent that can be used (if not present anything + * is valid) + * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST: u32 attribute indicating + * the maximum FTMs per burst (if not present anything is valid) + * + * @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal + * @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_ftm_capa { + __NL80211_PMSR_FTM_CAPA_ATTR_INVALID, + + NL80211_PMSR_FTM_CAPA_ATTR_ASAP, + NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP, + NL80211_PMSR_FTM_CAPA_ATTR_REQ_LCI, + NL80211_PMSR_FTM_CAPA_ATTR_REQ_CIVICLOC, + NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES, + NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS, + NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT, + NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST, + + /* keep last */ + NUM_NL80211_PMSR_FTM_CAPA_ATTR, + NL80211_PMSR_FTM_CAPA_ATTR_MAX = NUM_NL80211_PMSR_FTM_CAPA_ATTR - 1 +}; + +/** + * enum nl80211_peer_measurement_ftm_req - FTM request attributes + * @__NL80211_PMSR_FTM_REQ_ATTR_INVALID: invalid + * + * @NL80211_PMSR_FTM_REQ_ATTR_ASAP: ASAP mode requested (flag) + * @NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE: preamble type (see + * &enum nl80211_preamble), optional for DMG (u32) + * @NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP: number of bursts exponent as in + * 802.11-2016 9.4.2.168 "Fine Timing Measurement Parameters element" + * (u8, 0-15, optional with default 15 i.e. "no preference") + * @NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD: interval between bursts in units + * of 100ms (u16, optional with default 0) + * @NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION: burst duration, as in 802.11-2016 + * Table 9-257 "Burst Duration field encoding" (u8, 0-15, optional with + * default 15 i.e. "no preference") + * @NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST: number of successful FTM frames + * requested per burst + * (u8, 0-31, optional with default 0 i.e. "no preference") + * @NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES: number of FTMR frame retries + * (u8, default 3) + * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI: request LCI data (flag) + * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC: request civic location data + * (flag) + * + * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal + * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_ftm_req { + __NL80211_PMSR_FTM_REQ_ATTR_INVALID, + + NL80211_PMSR_FTM_REQ_ATTR_ASAP, + NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE, + NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP, + NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD, + NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION, + NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST, + NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES, + NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI, + NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC, + + /* keep last */ + NUM_NL80211_PMSR_FTM_REQ_ATTR, + NL80211_PMSR_FTM_REQ_ATTR_MAX = NUM_NL80211_PMSR_FTM_REQ_ATTR - 1 +}; + +/** + * enum nl80211_peer_measurement_ftm_failure_reasons - FTM failure reasons + * @NL80211_PMSR_FTM_FAILURE_UNSPECIFIED: unspecified failure, not used + * @NL80211_PMSR_FTM_FAILURE_NO_RESPONSE: no response from the FTM responder + * @NL80211_PMSR_FTM_FAILURE_REJECTED: FTM responder rejected measurement + * @NL80211_PMSR_FTM_FAILURE_WRONG_CHANNEL: we already know the peer is + * on a different channel, so can't measure (if we didn't know, we'd + * try and get no response) + * @NL80211_PMSR_FTM_FAILURE_PEER_NOT_CAPABLE: peer can't actually do FTM + * @NL80211_PMSR_FTM_FAILURE_INVALID_TIMESTAMP: invalid T1/T4 timestamps + * received + * @NL80211_PMSR_FTM_FAILURE_PEER_BUSY: peer reports busy, you may retry + * later (see %NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME) + * @NL80211_PMSR_FTM_FAILURE_BAD_CHANGED_PARAMS: parameters were changed + * by the peer and are no longer supported + */ +enum nl80211_peer_measurement_ftm_failure_reasons { + NL80211_PMSR_FTM_FAILURE_UNSPECIFIED, + NL80211_PMSR_FTM_FAILURE_NO_RESPONSE, + NL80211_PMSR_FTM_FAILURE_REJECTED, + NL80211_PMSR_FTM_FAILURE_WRONG_CHANNEL, + NL80211_PMSR_FTM_FAILURE_PEER_NOT_CAPABLE, + NL80211_PMSR_FTM_FAILURE_INVALID_TIMESTAMP, + NL80211_PMSR_FTM_FAILURE_PEER_BUSY, + NL80211_PMSR_FTM_FAILURE_BAD_CHANGED_PARAMS, +}; + +/** + * enum nl80211_peer_measurement_ftm_resp - FTM response attributes + * @__NL80211_PMSR_FTM_RESP_ATTR_INVALID: invalid + * + * @NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON: FTM-specific failure reason + * (u32, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX: optional, if bursts are reported + * as separate results then it will be the burst index 0...(N-1) and + * the top level will indicate partial results (u32) + * @NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS: number of FTM Request frames + * transmitted (u32, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES: number of FTM Request frames + * that were acknowleged (u32, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME: retry time received from the + * busy peer (u32, seconds) + * @NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP: actual number of bursts exponent + * used by the responder (similar to request, u8) + * @NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION: actual burst duration used by + * the responder (similar to request, u8) + * @NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST: actual FTMs per burst used + * by the responder (similar to request, u8) + * @NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG: average RSSI across all FTM action + * frames (optional, s32, 1/2 dBm) + * @NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD: RSSI spread across all FTM action + * frames (optional, s32, 1/2 dBm) + * @NL80211_PMSR_FTM_RESP_ATTR_TX_RATE: bitrate we used for the response to the + * FTM action frame (optional, nested, using &enum nl80211_rate_info + * attributes) + * @NL80211_PMSR_FTM_RESP_ATTR_RX_RATE: bitrate the responder used for the FTM + * action frame (optional, nested, using &enum nl80211_rate_info attrs) + * @NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG: average RTT (s64, picoseconds, optional + * but one of RTT/DIST must be present) + * @NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE: RTT variance (u64, ps^2, note that + * standard deviation is the square root of variance, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD: RTT spread (u64, picoseconds, + * optional) + * @NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG: average distance (s64, mm, optional + * but one of RTT/DIST must be present) + * @NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE: distance variance (u64, mm^2, note + * that standard deviation is the square root of variance, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD: distance spread (u64, mm, optional) + * @NL80211_PMSR_FTM_RESP_ATTR_LCI: LCI data from peer (binary, optional); + * this is the contents of the Measurement Report Element (802.11-2016 + * 9.4.2.22.1) starting with the Measurement Token, with Measurement + * Type 8. + * @NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC: civic location data from peer + * (binary, optional); + * this is the contents of the Measurement Report Element (802.11-2016 + * 9.4.2.22.1) starting with the Measurement Token, with Measurement + * Type 11. + * @NL80211_PMSR_FTM_RESP_ATTR_PAD: ignore, for u64/s64 padding only + * + * @NUM_NL80211_PMSR_FTM_RESP_ATTR: internal + * @NL80211_PMSR_FTM_RESP_ATTR_MAX: highest attribute number + */ +enum nl80211_peer_measurement_ftm_resp { + __NL80211_PMSR_FTM_RESP_ATTR_INVALID, + + NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON, + NL80211_PMSR_FTM_RESP_ATTR_BURST_INDEX, + NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS, + NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES, + NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME, + NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP, + NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION, + NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST, + NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG, + NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD, + NL80211_PMSR_FTM_RESP_ATTR_TX_RATE, + NL80211_PMSR_FTM_RESP_ATTR_RX_RATE, + NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG, + NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE, + NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD, + NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG, + NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE, + NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD, + NL80211_PMSR_FTM_RESP_ATTR_LCI, + NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC, + NL80211_PMSR_FTM_RESP_ATTR_PAD, + + /* keep last */ + NUM_NL80211_PMSR_FTM_RESP_ATTR, + NL80211_PMSR_FTM_RESP_ATTR_MAX = NUM_NL80211_PMSR_FTM_RESP_ATTR - 1 +}; + +/** + * enum nl80211_obss_pd_attributes - OBSS packet detection attributes + * @__NL80211_HE_OBSS_PD_ATTR_INVALID: Invalid + * + * @NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET: the OBSS PD minimum tx power offset. + * @NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET: the OBSS PD maximum tx power offset. + * + * @__NL80211_HE_OBSS_PD_ATTR_LAST: Internal + * @NL80211_HE_OBSS_PD_ATTR_MAX: highest OBSS PD attribute. + */ +enum nl80211_obss_pd_attributes { + __NL80211_HE_OBSS_PD_ATTR_INVALID, + + NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, + NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET, + + /* keep last */ + __NL80211_HE_OBSS_PD_ATTR_LAST, + NL80211_HE_OBSS_PD_ATTR_MAX = __NL80211_HE_OBSS_PD_ATTR_LAST - 1, +}; + + +#endif /* __LINUX_NL80211_H */ diff --git a/src/shared/local-addresses.c b/src/shared/local-addresses.c new file mode 100644 index 00000000..2f3d6756 --- /dev/null +++ b/src/shared/local-addresses.c @@ -0,0 +1,260 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "local-addresses.h" +#include "macro.h" +#include "netlink-util.h" +#include "sort-util.h" + +static int address_compare(const struct local_address *a, const struct local_address *b) { + int r; + + /* Order lowest scope first, IPv4 before IPv6, lowest interface index first */ + + if (a->family == AF_INET && b->family == AF_INET6) + return -1; + if (a->family == AF_INET6 && b->family == AF_INET) + return 1; + + r = CMP(a->scope, b->scope); + if (r != 0) + return r; + + r = CMP(a->metric, b->metric); + if (r != 0) + return r; + + r = CMP(a->ifindex, b->ifindex); + if (r != 0) + return r; + + return memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family)); +} + +int local_addresses(sd_netlink *context, int ifindex, int af, struct local_address **ret) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_free_ struct local_address *list = NULL; + size_t n_list = 0, n_allocated = 0; + sd_netlink_message *m; + int r; + + assert(ret); + + if (context) + rtnl = sd_netlink_ref(context); + else { + r = sd_netlink_open(&rtnl); + if (r < 0) + return r; + } + + r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, af); + if (r < 0) + return r; + + r = sd_netlink_call(rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (m = reply; m; m = sd_netlink_message_next(m)) { + struct local_address *a; + unsigned char flags; + uint16_t type; + int ifi, family; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + return r; + + r = sd_netlink_message_get_type(m, &type); + if (r < 0) + return r; + if (type != RTM_NEWADDR) + continue; + + r = sd_rtnl_message_addr_get_ifindex(m, &ifi); + if (r < 0) + return r; + if (ifindex > 0 && ifi != ifindex) + continue; + + r = sd_rtnl_message_addr_get_family(m, &family); + if (r < 0) + return r; + if (af != AF_UNSPEC && af != family) + continue; + + r = sd_rtnl_message_addr_get_flags(m, &flags); + if (r < 0) + return r; + if (flags & IFA_F_DEPRECATED) + continue; + + if (!GREEDY_REALLOC0(list, n_allocated, n_list+1)) + return -ENOMEM; + + a = list + n_list; + + r = sd_rtnl_message_addr_get_scope(m, &a->scope); + if (r < 0) + return r; + + if (ifindex == 0 && IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE)) + continue; + + switch (family) { + + case AF_INET: + r = sd_netlink_message_read_in_addr(m, IFA_LOCAL, &a->address.in); + if (r < 0) { + r = sd_netlink_message_read_in_addr(m, IFA_ADDRESS, &a->address.in); + if (r < 0) + continue; + } + break; + + case AF_INET6: + r = sd_netlink_message_read_in6_addr(m, IFA_LOCAL, &a->address.in6); + if (r < 0) { + r = sd_netlink_message_read_in6_addr(m, IFA_ADDRESS, &a->address.in6); + if (r < 0) + continue; + } + break; + + default: + continue; + } + + a->ifindex = ifi; + a->family = family; + + n_list++; + }; + + typesafe_qsort(list, n_list, address_compare); + + *ret = TAKE_PTR(list); + + return (int) n_list; +} + +int local_gateways(sd_netlink *context, int ifindex, int af, struct local_address **ret) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; + _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; + _cleanup_free_ struct local_address *list = NULL; + sd_netlink_message *m = NULL; + size_t n_list = 0, n_allocated = 0; + int r; + + assert(ret); + + if (context) + rtnl = sd_netlink_ref(context); + else { + r = sd_netlink_open(&rtnl); + if (r < 0) + return r; + } + + r = sd_rtnl_message_new_route(rtnl, &req, RTM_GETROUTE, af, RTPROT_UNSPEC); + if (r < 0) + return r; + + r = sd_netlink_message_request_dump(req, true); + if (r < 0) + return r; + + r = sd_netlink_call(rtnl, req, 0, &reply); + if (r < 0) + return r; + + for (m = reply; m; m = sd_netlink_message_next(m)) { + struct local_address *a; + uint16_t type; + unsigned char dst_len, src_len, table; + uint32_t ifi; + int family; + + r = sd_netlink_message_get_errno(m); + if (r < 0) + return r; + + r = sd_netlink_message_get_type(m, &type); + if (r < 0) + return r; + if (type != RTM_NEWROUTE) + continue; + + /* We only care for default routes */ + r = sd_rtnl_message_route_get_dst_prefixlen(m, &dst_len); + if (r < 0) + return r; + if (dst_len != 0) + continue; + + r = sd_rtnl_message_route_get_src_prefixlen(m, &src_len); + if (r < 0) + return r; + if (src_len != 0) + continue; + + r = sd_rtnl_message_route_get_table(m, &table); + if (r < 0) + return r; + if (table != RT_TABLE_MAIN) + continue; + + r = sd_netlink_message_read_u32(m, RTA_OIF, &ifi); + if (r == -ENODATA) /* Not all routes have an RTA_OIF attribute (for example nexthop ones) */ + continue; + if (r < 0) + return r; + if (ifindex > 0 && (int) ifi != ifindex) + continue; + + r = sd_rtnl_message_route_get_family(m, &family); + if (r < 0) + return r; + if (af != AF_UNSPEC && af != family) + continue; + + if (!GREEDY_REALLOC0(list, n_allocated, n_list + 1)) + return -ENOMEM; + + a = list + n_list; + + switch (family) { + case AF_INET: + r = sd_netlink_message_read_in_addr(m, RTA_GATEWAY, &a->address.in); + if (r < 0) + continue; + + break; + case AF_INET6: + r = sd_netlink_message_read_in6_addr(m, RTA_GATEWAY, &a->address.in6); + if (r < 0) + continue; + + break; + default: + continue; + } + + sd_netlink_message_read_u32(m, RTA_PRIORITY, &a->metric); + + a->ifindex = ifi; + a->family = family; + + n_list++; + } + + typesafe_qsort(list, n_list, address_compare); + + *ret = TAKE_PTR(list); + + return (int) n_list; +} diff --git a/src/shared/local-addresses.h b/src/shared/local-addresses.h new file mode 100644 index 00000000..e88c5e5d --- /dev/null +++ b/src/shared/local-addresses.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-netlink.h" + +#include "in-addr-util.h" + +struct local_address { + int family, ifindex; + unsigned char scope; + uint32_t metric; + union in_addr_union address; +}; + +int local_addresses(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret); + +int local_gateways(sd_netlink *rtnl, int ifindex, int af, struct local_address **ret); diff --git a/src/shared/lockfile-util.c b/src/shared/lockfile-util.c new file mode 100644 index 00000000..260c2088 --- /dev/null +++ b/src/shared/lockfile-util.c @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "lockfile-util.h" +#include "macro.h" +#include "missing_fcntl.h" +#include "path-util.h" + +int make_lock_file(const char *p, int operation, LockFile *ret) { + _cleanup_close_ int fd = -1; + _cleanup_free_ char *t = NULL; + int r; + + /* + * We use UNPOSIX locks if they are available. They have nice + * semantics, and are mostly compatible with NFS. However, + * they are only available on new kernels. When we detect we + * are running on an older kernel, then we fall back to good + * old BSD locks. They also have nice semantics, but are + * slightly problematic on NFS, where they are upgraded to + * POSIX locks, even though locally they are orthogonal to + * POSIX locks. + */ + + t = strdup(p); + if (!t) + return -ENOMEM; + + for (;;) { + struct flock fl = { + .l_type = (operation & ~LOCK_NB) == LOCK_EX ? F_WRLCK : F_RDLCK, + .l_whence = SEEK_SET, + }; + struct stat st; + + fd = open(p, O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY, 0600); + if (fd < 0) + return -errno; + + r = fcntl(fd, (operation & LOCK_NB) ? F_OFD_SETLK : F_OFD_SETLKW, &fl); + if (r < 0) { + + /* If the kernel is too old, use good old BSD locks */ + if (errno == EINVAL) + r = flock(fd, operation); + + if (r < 0) + return errno == EAGAIN ? -EBUSY : -errno; + } + + /* If we acquired the lock, let's check if the file + * still exists in the file system. If not, then the + * previous exclusive owner removed it and then closed + * it. In such a case our acquired lock is worthless, + * hence try again. */ + + r = fstat(fd, &st); + if (r < 0) + return -errno; + if (st.st_nlink > 0) + break; + + fd = safe_close(fd); + } + + ret->path = t; + ret->fd = fd; + ret->operation = operation; + + fd = -1; + t = NULL; + + return r; +} + +int make_lock_file_for(const char *p, int operation, LockFile *ret) { + const char *fn; + char *t; + + assert(p); + assert(ret); + + fn = basename(p); + if (!filename_is_valid(fn)) + return -EINVAL; + + t = newa(char, strlen(p) + 2 + 4 + 1); + stpcpy(stpcpy(stpcpy(mempcpy(t, p, fn - p), ".#"), fn), ".lck"); + + return make_lock_file(t, operation, ret); +} + +void release_lock_file(LockFile *f) { + int r; + + if (!f) + return; + + if (f->path) { + + /* If we are the exclusive owner we can safely delete + * the lock file itself. If we are not the exclusive + * owner, we can try becoming it. */ + + if (f->fd >= 0 && + (f->operation & ~LOCK_NB) == LOCK_SH) { + static const struct flock fl = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, + }; + + r = fcntl(f->fd, F_OFD_SETLK, &fl); + if (r < 0 && errno == EINVAL) + r = flock(f->fd, LOCK_EX|LOCK_NB); + + if (r >= 0) + f->operation = LOCK_EX|LOCK_NB; + } + + if ((f->operation & ~LOCK_NB) == LOCK_EX) + unlink_noerrno(f->path); + + f->path = mfree(f->path); + } + + f->fd = safe_close(f->fd); + f->operation = 0; +} diff --git a/src/shared/lockfile-util.h b/src/shared/lockfile-util.h new file mode 100644 index 00000000..e0eef34c --- /dev/null +++ b/src/shared/lockfile-util.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef struct LockFile { + char *path; + int fd; + int operation; +} LockFile; + +int make_lock_file(const char *p, int operation, LockFile *ret); +int make_lock_file_for(const char *p, int operation, LockFile *ret); +void release_lock_file(LockFile *f); + +#define LOCK_FILE_INIT { .fd = -1, .path = NULL } diff --git a/src/shared/log-link.h b/src/shared/log-link.h new file mode 100644 index 00000000..2d038026 --- /dev/null +++ b/src/shared/log-link.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "log.h" + +/* + * The following macros append INTERFACE= to the message. + * The macros require a struct named 'Link' which contains 'char *ifname': + * + * typedef struct Link { + * char *ifname; + * } Link; + * + * See, network/networkd-link.h for example. + */ + +#define log_link_full(link, level, error, ...) \ + ({ \ + const Link *_l = (link); \ + (_l && _l->ifname) ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \ + log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \ + }) \ + +#define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__) +#define log_link_info(link, ...) log_link_full(link, LOG_INFO, 0, ##__VA_ARGS__) +#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, 0, ##__VA_ARGS__) +#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, 0, ##__VA_ARGS__) +#define log_link_error(link, ...) log_link_full(link, LOG_ERR, 0, ##__VA_ARGS__) + +#define log_link_debug_errno(link, error, ...) log_link_full(link, LOG_DEBUG, error, ##__VA_ARGS__) +#define log_link_info_errno(link, error, ...) log_link_full(link, LOG_INFO, error, ##__VA_ARGS__) +#define log_link_notice_errno(link, error, ...) log_link_full(link, LOG_NOTICE, error, ##__VA_ARGS__) +#define log_link_warning_errno(link, error, ...) log_link_full(link, LOG_WARNING, error, ##__VA_ARGS__) +#define log_link_error_errno(link, error, ...) log_link_full(link, LOG_ERR, error, ##__VA_ARGS__) + +#define LOG_LINK_MESSAGE(link, fmt, ...) "MESSAGE=%s: " fmt, (link)->ifname, ##__VA_ARGS__ +#define LOG_LINK_INTERFACE(link) "INTERFACE=%s", (link)->ifname diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c new file mode 100644 index 00000000..95b2e337 --- /dev/null +++ b/src/shared/logs-show.c @@ -0,0 +1,1501 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-id128.h" +#include "sd-journal.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "hashmap.h" +#include "hostname-util.h" +#include "io-util.h" +#include "journal-internal.h" +#include "json.h" +#include "log.h" +#include "logs-show.h" +#include "macro.h" +#include "namespace-util.h" +#include "output-mode.h" +#include "parse-util.h" +#include "process-util.h" +#include "pretty-print.h" +#include "sparse-endian.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "time-util.h" +#include "utf8.h" +#include "util.h" + +/* up to three lines (each up to 100 characters) or 300 characters, whichever is less */ +#define PRINT_LINE_THRESHOLD 3 +#define PRINT_CHAR_THRESHOLD 300 + +#define JSON_THRESHOLD 4096U + +static int print_catalog(FILE *f, sd_journal *j) { + int r; + _cleanup_free_ char *t = NULL, *z = NULL; + + r = sd_journal_get_catalog(j, &t); + if (r < 0) + return r; + + z = strreplace(strstrip(t), "\n", "\n-- "); + if (!z) + return log_oom(); + + fputs("-- ", f); + fputs(z, f); + fputc('\n', f); + + return 0; +} + +static int parse_field(const void *data, size_t length, const char *field, size_t field_len, char **target, size_t *target_len) { + size_t nl; + char *buf; + + assert(data); + assert(field); + assert(target); + + if (length < field_len) + return 0; + + if (memcmp(data, field, field_len)) + return 0; + + nl = length - field_len; + + buf = newdup_suffix0(char, (const char*) data + field_len, nl); + if (!buf) + return log_oom(); + + free(*target); + *target = buf; + + if (target_len) + *target_len = nl; + + return 1; +} + +typedef struct ParseFieldVec { + const char *field; + size_t field_len; + char **target; + size_t *target_len; +} ParseFieldVec; + +#define PARSE_FIELD_VEC_ENTRY(_field, _target, _target_len) \ + { .field = _field, .field_len = strlen(_field), .target = _target, .target_len = _target_len } + +static int parse_fieldv(const void *data, size_t length, const ParseFieldVec *fields, unsigned n_fields) { + unsigned i; + + for (i = 0; i < n_fields; i++) { + const ParseFieldVec *f = &fields[i]; + int r; + + r = parse_field(data, length, f->field, f->field_len, f->target, f->target_len); + if (r < 0) + return r; + else if (r > 0) + break; + } + + return 0; +} + +static int field_set_test(Set *fields, const char *name, size_t n) { + char *s = NULL; + + if (!fields) + return 1; + + s = strndupa(name, n); + if (!s) + return log_oom(); + + return set_get(fields, s) ? 1 : 0; +} + +static bool shall_print(const char *p, size_t l, OutputFlags flags) { + assert(p); + + if (flags & OUTPUT_SHOW_ALL) + return true; + + if (l >= PRINT_CHAR_THRESHOLD) + return false; + + if (!utf8_is_printable(p, l)) + return false; + + return true; +} + +static bool print_multiline( + FILE *f, + unsigned prefix, + unsigned n_columns, + OutputFlags flags, + int priority, + bool audit, + const char* message, + size_t message_len, + size_t highlight[2]) { + + const char *color_on = "", *color_off = "", *highlight_on = ""; + const char *pos, *end; + bool ellipsized = false; + int line = 0; + + if (flags & OUTPUT_COLOR) { + get_log_colors(priority, &color_on, &color_off, &highlight_on); + + if (audit && strempty(color_on)) { + color_on = ANSI_BLUE; + color_off = ANSI_NORMAL; + } + } + + /* A special case: make sure that we print a newline when + the message is empty. */ + if (message_len == 0) + fputs("\n", f); + + for (pos = message; + pos < message + message_len; + pos = end + 1, line++) { + bool continuation = line > 0; + bool tail_line; + int len; + for (end = pos; end < message + message_len && *end != '\n'; end++) + ; + len = end - pos; + assert(len >= 0); + + /* We need to figure out when we are showing not-last line, *and* + * will skip subsequent lines. In that case, we will put the dots + * at the end of the line, instead of putting dots in the middle + * or not at all. + */ + tail_line = + line + 1 == PRINT_LINE_THRESHOLD || + end + 1 >= message + PRINT_CHAR_THRESHOLD; + + if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) || + (prefix + len + 1 < n_columns && !tail_line)) { + if (highlight && + (size_t) (pos - message) <= highlight[0] && + highlight[0] < (size_t) len) { + + fprintf(f, "%*s%s%.*s", + continuation * prefix, "", + color_on, (int) highlight[0], pos); + fprintf(f, "%s%.*s", + highlight_on, + (int) (MIN((size_t) len, highlight[1]) - highlight[0]), + pos + highlight[0]); + if ((size_t) len > highlight[1]) + fprintf(f, "%s%.*s", + color_on, + (int) (len - highlight[1]), + pos + highlight[1]); + fprintf(f, "%s\n", color_off); + + } else + fprintf(f, "%*s%s%.*s%s\n", + continuation * prefix, "", + color_on, len, pos, color_off); + continue; + } + + /* Beyond this point, ellipsization will happen. */ + ellipsized = true; + + if (prefix < n_columns && n_columns - prefix >= 3) { + if (n_columns - prefix > (unsigned) len + 3) + fprintf(f, "%*s%s%.*s...%s\n", + continuation * prefix, "", + color_on, len, pos, color_off); + else { + _cleanup_free_ char *e; + + e = ellipsize_mem(pos, len, n_columns - prefix, + tail_line ? 100 : 90); + if (!e) + fprintf(f, "%*s%s%.*s%s\n", + continuation * prefix, "", + color_on, len, pos, color_off); + else + fprintf(f, "%*s%s%s%s\n", + continuation * prefix, "", + color_on, e, color_off); + } + } else + fputs("...\n", f); + + if (tail_line) + break; + } + + return ellipsized; +} + +static int output_timestamp_monotonic(FILE *f, sd_journal *j, const char *monotonic) { + sd_id128_t boot_id; + uint64_t t; + int r; + + assert(f); + assert(j); + + r = -ENXIO; + if (monotonic) + r = safe_atou64(monotonic, &t); + if (r < 0) + r = sd_journal_get_monotonic_usec(j, &t, &boot_id); + if (r < 0) + return log_error_errno(r, "Failed to get monotonic timestamp: %m"); + + fprintf(f, "[%5"PRI_USEC".%06"PRI_USEC"]", t / USEC_PER_SEC, t % USEC_PER_SEC); + return 1 + 5 + 1 + 6 + 1; +} + +static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, OutputFlags flags, const char *realtime) { + char buf[MAX(FORMAT_TIMESTAMP_MAX, 64)]; + struct tm *(*gettime_r)(const time_t *, struct tm *); + struct tm tm; + uint64_t x; + time_t t; + int r; + + assert(f); + assert(j); + + if (realtime) + r = safe_atou64(realtime, &x); + if (!realtime || r < 0 || !VALID_REALTIME(x)) + r = sd_journal_get_realtime_usec(j, &x); + if (r < 0) + return log_error_errno(r, "Failed to get realtime timestamp: %m"); + + if (IN_SET(mode, OUTPUT_SHORT_FULL, OUTPUT_WITH_UNIT)) { + const char *k; + + if (flags & OUTPUT_UTC) + k = format_timestamp_utc(buf, sizeof(buf), x); + else + k = format_timestamp(buf, sizeof(buf), x); + if (!k) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to format timestamp: %" PRIu64, x); + + } else { + char usec[7]; + + gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r; + t = (time_t) (x / USEC_PER_SEC); + + switch (mode) { + + case OUTPUT_SHORT_UNIX: + xsprintf(buf, "%10"PRI_TIME".%06"PRIu64, t, x % USEC_PER_SEC); + break; + + case OUTPUT_SHORT_ISO: + if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm)) <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to format ISO time"); + break; + + case OUTPUT_SHORT_ISO_PRECISE: + /* No usec in strftime, so we leave space and copy over */ + if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S.xxxxxx%z", gettime_r(&t, &tm)) <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to format ISO-precise time"); + xsprintf(usec, "%06"PRI_USEC, x % USEC_PER_SEC); + memcpy(buf + 20, usec, 6); + break; + + case OUTPUT_SHORT: + case OUTPUT_SHORT_PRECISE: + + if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm)) <= 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to format syslog time"); + + if (mode == OUTPUT_SHORT_PRECISE) { + size_t k; + + assert(sizeof(buf) > strlen(buf)); + k = sizeof(buf) - strlen(buf); + + r = snprintf(buf + strlen(buf), k, ".%06"PRIu64, x % USEC_PER_SEC); + if (r <= 0 || (size_t) r >= k) /* too long? */ + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to format precise time"); + } + break; + + default: + assert_not_reached("Unknown time format"); + } + } + + fputs(buf, f); + return (int) strlen(buf); +} + +static int output_short( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags, + Set *output_fields, + const size_t highlight[2]) { + + int r; + const void *data; + size_t length; + size_t n = 0; + _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL, *transport = NULL, *config_file = NULL, *unit = NULL, *user_unit = NULL; + size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0, transport_len = 0, config_file_len = 0, unit_len = 0, user_unit_len = 0; + int p = LOG_INFO; + bool ellipsized = false, audit; + const ParseFieldVec fields[] = { + PARSE_FIELD_VEC_ENTRY("_PID=", &pid, &pid_len), + PARSE_FIELD_VEC_ENTRY("_COMM=", &comm, &comm_len), + PARSE_FIELD_VEC_ENTRY("MESSAGE=", &message, &message_len), + PARSE_FIELD_VEC_ENTRY("PRIORITY=", &priority, &priority_len), + PARSE_FIELD_VEC_ENTRY("_TRANSPORT=", &transport, &transport_len), + PARSE_FIELD_VEC_ENTRY("_HOSTNAME=", &hostname, &hostname_len), + PARSE_FIELD_VEC_ENTRY("SYSLOG_PID=", &fake_pid, &fake_pid_len), + PARSE_FIELD_VEC_ENTRY("SYSLOG_IDENTIFIER=", &identifier, &identifier_len), + PARSE_FIELD_VEC_ENTRY("_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len), + PARSE_FIELD_VEC_ENTRY("_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len), + PARSE_FIELD_VEC_ENTRY("CONFIG_FILE=", &config_file, &config_file_len), + PARSE_FIELD_VEC_ENTRY("_SYSTEMD_UNIT=", &unit, &unit_len), + PARSE_FIELD_VEC_ENTRY("_SYSTEMD_USER_UNIT=", &user_unit, &user_unit_len), + }; + size_t highlight_shifted[] = {highlight ? highlight[0] : 0, highlight ? highlight[1] : 0}; + + assert(f); + assert(j); + + /* Set the threshold to one bigger than the actual print + * threshold, so that if the line is actually longer than what + * we're willing to print, ellipsization will occur. This way + * we won't output a misleading line without any indication of + * truncation. + */ + sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1); + + JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { + r = parse_fieldv(data, length, fields, ELEMENTSOF(fields)); + if (r < 0) + return r; + } + if (r == -EBADMSG) { + log_debug_errno(r, "Skipping message we can't read: %m"); + return 0; + } + if (r < 0) + return log_error_errno(r, "Failed to get journal fields: %m"); + + if (!message) { + log_debug("Skipping message without MESSAGE= field."); + return 0; + } + + if (!(flags & OUTPUT_SHOW_ALL)) + strip_tab_ansi(&message, &message_len, highlight_shifted); + + if (priority_len == 1 && *priority >= '0' && *priority <= '7') + p = *priority - '0'; + + audit = streq_ptr(transport, "audit"); + + if (mode == OUTPUT_SHORT_MONOTONIC) + r = output_timestamp_monotonic(f, j, monotonic); + else + r = output_timestamp_realtime(f, j, mode, flags, realtime); + if (r < 0) + return r; + n += r; + + if (flags & OUTPUT_NO_HOSTNAME) { + /* Suppress display of the hostname if this is requested. */ + hostname = mfree(hostname); + hostname_len = 0; + } + + if (hostname && shall_print(hostname, hostname_len, flags)) { + fprintf(f, " %.*s", (int) hostname_len, hostname); + n += hostname_len + 1; + } + + if (mode == OUTPUT_WITH_UNIT && ((unit && shall_print(unit, unit_len, flags)) || + (user_unit && shall_print(user_unit, user_unit_len, flags)))) { + if (unit) { + fprintf(f, " %.*s", (int) unit_len, unit); + n += unit_len + 1; + } + if (user_unit) { + if (unit) + fprintf(f, "/%.*s", (int) user_unit_len, user_unit); + else + fprintf(f, " %.*s", (int) user_unit_len, user_unit); + n += unit_len + 1; + } + } else if (identifier && shall_print(identifier, identifier_len, flags)) { + fprintf(f, " %.*s", (int) identifier_len, identifier); + n += identifier_len + 1; + } else if (comm && shall_print(comm, comm_len, flags)) { + fprintf(f, " %.*s", (int) comm_len, comm); + n += comm_len + 1; + } else + fputs(" unknown", f); + + if (pid && shall_print(pid, pid_len, flags)) { + fprintf(f, "[%.*s]", (int) pid_len, pid); + n += pid_len + 2; + } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) { + fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid); + n += fake_pid_len + 2; + } + + if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) { + char bytes[FORMAT_BYTES_MAX]; + fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); + } else { + fputs(": ", f); + + /* URLify config_file string in message, if the message starts with it. + * Skip URLification if the highlighted pattern overlaps. */ + if (config_file && + message_len >= config_file_len && + memcmp(message, config_file, config_file_len) == 0 && + IN_SET(message[config_file_len], ':', ' ', '\0') && + (!highlight || highlight_shifted[0] == 0 || highlight_shifted[0] > config_file_len)) { + + _cleanup_free_ char *t = NULL, *urlified = NULL; + + t = strndup(config_file, config_file_len); + if (t && terminal_urlify_path(t, NULL, &urlified) >= 0) { + size_t shift = strlen(urlified) - config_file_len; + char *joined; + + joined = strjoin(urlified, message + config_file_len); + if (joined) { + free_and_replace(message, joined); + message_len += shift; + if (highlight) { + highlight_shifted[0] += shift; + highlight_shifted[1] += shift; + } + } + } + } + + ellipsized |= + print_multiline(f, n + 2, n_columns, flags, p, audit, + message, message_len, + highlight_shifted); + } + + if (flags & OUTPUT_CATALOG) + print_catalog(f, j); + + return ellipsized; +} + +static int output_verbose( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags, + Set *output_fields, + const size_t highlight[2]) { + + const void *data; + size_t length; + _cleanup_free_ char *cursor = NULL; + uint64_t realtime = 0; + char ts[FORMAT_TIMESTAMP_MAX + 7]; + const char *timestamp; + int r; + + assert(f); + assert(j); + + sd_journal_set_data_threshold(j, 0); + + r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length); + if (r == -ENOENT) + log_debug("Source realtime timestamp not found"); + else if (r < 0) + return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get source realtime timestamp: %m"); + else { + _cleanup_free_ char *value = NULL; + + r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", + STRLEN("_SOURCE_REALTIME_TIMESTAMP="), &value, + NULL); + if (r < 0) + return r; + assert(r > 0); + + r = safe_atou64(value, &realtime); + if (r < 0) + log_debug_errno(r, "Failed to parse realtime timestamp: %m"); + } + + if (r < 0) { + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) + return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get realtime timestamp: %m"); + } + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0) + return log_error_errno(r, "Failed to get cursor: %m"); + + timestamp = flags & OUTPUT_UTC ? format_timestamp_us_utc(ts, sizeof ts, realtime) + : format_timestamp_us(ts, sizeof ts, realtime); + fprintf(f, "%s [%s]\n", + timestamp ?: "(no timestamp)", + cursor); + + JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { + const char *c, *p; + int fieldlen; + const char *on = "", *off = ""; + _cleanup_free_ char *urlified = NULL; + size_t valuelen; + + c = memchr(data, '=', length); + if (!c) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid field."); + fieldlen = c - (const char*) data; + + r = field_set_test(output_fields, data, fieldlen); + if (r < 0) + return r; + if (r == 0) + continue; + + valuelen = length - 1 - fieldlen; + + if ((flags & OUTPUT_COLOR) && (p = startswith(data, "MESSAGE="))) { + on = ANSI_HIGHLIGHT; + off = ANSI_NORMAL; + } else if ((p = startswith(data, "CONFIG_FILE="))) { + if (terminal_urlify_path(p, NULL, &urlified) >= 0) { + p = urlified; + valuelen = strlen(urlified); + } + } else + p = c + 1; + + if ((flags & OUTPUT_SHOW_ALL) || + (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH) + && utf8_is_printable(data, length))) { + fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data); + print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, false, + p, valuelen, + NULL); + fputs(off, f); + } else { + char bytes[FORMAT_BYTES_MAX]; + + fprintf(f, " %s%.*s=[%s blob data]%s\n", + on, + (int) (c - (const char*) data), + (const char*) data, + format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1), + off); + } + } + + if (r < 0) + return r; + + if (flags & OUTPUT_CATALOG) + print_catalog(f, j); + + return 0; +} + +static int output_export( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags, + Set *output_fields, + const size_t highlight[2]) { + + sd_id128_t boot_id; + char sid[33]; + int r; + usec_t realtime, monotonic; + _cleanup_free_ char *cursor = NULL; + const void *data; + size_t length; + + assert(j); + + sd_journal_set_data_threshold(j, 0); + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) + return log_error_errno(r, "Failed to get realtime timestamp: %m"); + + r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); + if (r < 0) + return log_error_errno(r, "Failed to get monotonic timestamp: %m"); + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0) + return log_error_errno(r, "Failed to get cursor: %m"); + + fprintf(f, + "__CURSOR=%s\n" + "__REALTIME_TIMESTAMP="USEC_FMT"\n" + "__MONOTONIC_TIMESTAMP="USEC_FMT"\n" + "_BOOT_ID=%s\n", + cursor, + realtime, + monotonic, + sd_id128_to_string(boot_id, sid)); + + JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { + const char *c; + + /* We already printed the boot id from the data in the header, hence let's suppress it here */ + if (memory_startswith(data, length, "_BOOT_ID=")) + continue; + + c = memchr(data, '=', length); + if (!c) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid field."); + + r = field_set_test(output_fields, data, c - (const char *) data); + if (r < 0) + return r; + if (!r) + continue; + + if (utf8_is_printable_newline(data, length, false)) + fwrite(data, length, 1, f); + else { + uint64_t le64; + + fwrite(data, c - (const char*) data, 1, f); + fputc('\n', f); + le64 = htole64(length - (c - (const char*) data) - 1); + fwrite(&le64, sizeof(le64), 1, f); + fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f); + } + + fputc('\n', f); + } + if (r == -EBADMSG) { + log_debug_errno(r, "Skipping message we can't read: %m"); + return 0; + } + + if (r < 0) + return r; + + fputc('\n', f); + + return 0; +} + +void json_escape( + FILE *f, + const char* p, + size_t l, + OutputFlags flags) { + + assert(f); + assert(p); + + if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD) + fputs("null", f); + + else if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(p, l)) { + bool not_first = false; + + fputs("[ ", f); + + while (l > 0) { + if (not_first) + fprintf(f, ", %u", (uint8_t) *p); + else { + not_first = true; + fprintf(f, "%u", (uint8_t) *p); + } + + p++; + l--; + } + + fputs(" ]", f); + } else { + fputc('"', f); + + while (l > 0) { + if (IN_SET(*p, '"', '\\')) { + fputc('\\', f); + fputc(*p, f); + } else if (*p == '\n') + fputs("\\n", f); + else if ((uint8_t) *p < ' ') + fprintf(f, "\\u%04x", (uint8_t) *p); + else + fputc(*p, f); + + p++; + l--; + } + + fputc('"', f); + } +} + +struct json_data { + JsonVariant* name; + size_t n_values; + JsonVariant* values[]; +}; + +static int update_json_data( + Hashmap *h, + OutputFlags flags, + const char *name, + const void *value, + size_t size) { + + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + struct json_data *d; + int r; + + if (!(flags & OUTPUT_SHOW_ALL) && strlen(name) + 1 + size >= JSON_THRESHOLD) + r = json_variant_new_null(&v); + else if (utf8_is_printable(value, size)) + r = json_variant_new_stringn(&v, value, size); + else + r = json_variant_new_array_bytes(&v, value, size); + if (r < 0) + return log_error_errno(r, "Failed to allocate JSON data: %m"); + + d = hashmap_get(h, name); + if (d) { + struct json_data *w; + + w = realloc(d, offsetof(struct json_data, values) + sizeof(JsonVariant*) * (d->n_values + 1)); + if (!w) + return log_oom(); + + d = w; + assert_se(hashmap_update(h, json_variant_string(d->name), d) >= 0); + } else { + _cleanup_(json_variant_unrefp) JsonVariant *n = NULL; + + r = json_variant_new_string(&n, name); + if (r < 0) + return log_error_errno(r, "Failed to allocate JSON name variant: %m"); + + d = malloc0(offsetof(struct json_data, values) + sizeof(JsonVariant*)); + if (!d) + return log_oom(); + + r = hashmap_put(h, json_variant_string(n), d); + if (r < 0) { + free(d); + return log_error_errno(r, "Failed to insert JSON name into hashmap: %m"); + } + + d->name = TAKE_PTR(n); + } + + d->values[d->n_values++] = TAKE_PTR(v); + return 0; +} + +static int update_json_data_split( + Hashmap *h, + OutputFlags flags, + Set *output_fields, + const void *data, + size_t size) { + + const char *eq; + char *name; + + assert(h); + assert(data || size == 0); + + if (memory_startswith(data, size, "_BOOT_ID=")) + return 0; + + eq = memchr(data, '=', MIN(size, JSON_THRESHOLD)); + if (!eq) + return 0; + + if (eq == data) + return 0; + + name = strndupa(data, eq - (const char*) data); + if (output_fields && !set_get(output_fields, name)) + return 0; + + return update_json_data(h, flags, name, eq + 1, size - (eq - (const char*) data) - 1); +} + +static int output_json( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags, + Set *output_fields, + const size_t highlight[2]) { + + char sid[SD_ID128_STRING_MAX], usecbuf[DECIMAL_STR_MAX(usec_t)]; + _cleanup_(json_variant_unrefp) JsonVariant *object = NULL; + _cleanup_free_ char *cursor = NULL; + uint64_t realtime, monotonic; + JsonVariant **array = NULL; + struct json_data *d; + sd_id128_t boot_id; + Hashmap *h = NULL; + size_t n = 0; + Iterator i; + int r; + + assert(j); + + (void) sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD); + + r = sd_journal_get_realtime_usec(j, &realtime); + if (r < 0) + return log_error_errno(r, "Failed to get realtime timestamp: %m"); + + r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id); + if (r < 0) + return log_error_errno(r, "Failed to get monotonic timestamp: %m"); + + r = sd_journal_get_cursor(j, &cursor); + if (r < 0) + return log_error_errno(r, "Failed to get cursor: %m"); + + h = hashmap_new(&string_hash_ops); + if (!h) + return log_oom(); + + r = update_json_data(h, flags, "__CURSOR", cursor, strlen(cursor)); + if (r < 0) + goto finish; + + xsprintf(usecbuf, USEC_FMT, realtime); + r = update_json_data(h, flags, "__REALTIME_TIMESTAMP", usecbuf, strlen(usecbuf)); + if (r < 0) + goto finish; + + xsprintf(usecbuf, USEC_FMT, monotonic); + r = update_json_data(h, flags, "__MONOTONIC_TIMESTAMP", usecbuf, strlen(usecbuf)); + if (r < 0) + goto finish; + + sd_id128_to_string(boot_id, sid); + r = update_json_data(h, flags, "_BOOT_ID", sid, strlen(sid)); + if (r < 0) + goto finish; + + for (;;) { + const void *data; + size_t size; + + r = sd_journal_enumerate_data(j, &data, &size); + if (r == -EBADMSG) { + log_debug_errno(r, "Skipping message we can't read: %m"); + r = 0; + goto finish; + } + if (r < 0) { + log_error_errno(r, "Failed to read journal: %m"); + goto finish; + } + if (r == 0) + break; + + r = update_json_data_split(h, flags, output_fields, data, size); + if (r < 0) + goto finish; + } + + array = new(JsonVariant*, hashmap_size(h)*2); + if (!array) { + r = log_oom(); + goto finish; + } + + HASHMAP_FOREACH(d, h, i) { + assert(d->n_values > 0); + + array[n++] = json_variant_ref(d->name); + + if (d->n_values == 1) + array[n++] = json_variant_ref(d->values[0]); + else { + _cleanup_(json_variant_unrefp) JsonVariant *q = NULL; + + r = json_variant_new_array(&q, d->values, d->n_values); + if (r < 0) { + log_error_errno(r, "Failed to create JSON array: %m"); + goto finish; + } + + array[n++] = TAKE_PTR(q); + } + } + + r = json_variant_new_object(&object, array, n); + if (r < 0) { + log_error_errno(r, "Failed to allocate JSON object: %m"); + goto finish; + } + + json_variant_dump(object, + output_mode_to_json_format_flags(mode) | + (FLAGS_SET(flags, OUTPUT_COLOR) ? JSON_FORMAT_COLOR : 0), + f, NULL); + + r = 0; + +finish: + while ((d = hashmap_steal_first(h))) { + size_t k; + + json_variant_unref(d->name); + for (k = 0; k < d->n_values; k++) + json_variant_unref(d->values[k]); + + free(d); + } + + hashmap_free(h); + + json_variant_unref_many(array, n); + free(array); + + return r; +} + +static int output_cat( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags, + Set *output_fields, + const size_t highlight[2]) { + + const void *data; + size_t l; + int r; + const char *highlight_on = "", *highlight_off = ""; + + assert(j); + assert(f); + + if (flags & OUTPUT_COLOR) { + highlight_on = ANSI_HIGHLIGHT_RED; + highlight_off = ANSI_NORMAL; + } + + sd_journal_set_data_threshold(j, 0); + + r = sd_journal_get_data(j, "MESSAGE", &data, &l); + if (r == -EBADMSG) { + log_debug_errno(r, "Skipping message we can't read: %m"); + return 0; + } + if (r < 0) { + /* An entry without MESSAGE=? */ + if (r == -ENOENT) + return 0; + + return log_error_errno(r, "Failed to get data: %m"); + } + + assert(l >= 8); + + if (highlight && (flags & OUTPUT_COLOR)) { + assert(highlight[0] <= highlight[1]); + assert(highlight[1] <= l - 8); + + fwrite((const char*) data + 8, 1, highlight[0], f); + fwrite(highlight_on, 1, strlen(highlight_on), f); + fwrite((const char*) data + 8 + highlight[0], 1, highlight[1] - highlight[0], f); + fwrite(highlight_off, 1, strlen(highlight_off), f); + fwrite((const char*) data + 8 + highlight[1], 1, l - 8 - highlight[1], f); + } else + fwrite((const char*) data + 8, 1, l - 8, f); + fputc('\n', f); + + return 0; +} + +static int (*output_funcs[_OUTPUT_MODE_MAX])( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags, + Set *output_fields, + const size_t highlight[2]) = { + + [OUTPUT_SHORT] = output_short, + [OUTPUT_SHORT_ISO] = output_short, + [OUTPUT_SHORT_ISO_PRECISE] = output_short, + [OUTPUT_SHORT_PRECISE] = output_short, + [OUTPUT_SHORT_MONOTONIC] = output_short, + [OUTPUT_SHORT_UNIX] = output_short, + [OUTPUT_SHORT_FULL] = output_short, + [OUTPUT_VERBOSE] = output_verbose, + [OUTPUT_EXPORT] = output_export, + [OUTPUT_JSON] = output_json, + [OUTPUT_JSON_PRETTY] = output_json, + [OUTPUT_JSON_SSE] = output_json, + [OUTPUT_JSON_SEQ] = output_json, + [OUTPUT_CAT] = output_cat, + [OUTPUT_WITH_UNIT] = output_short, +}; + +int show_journal_entry( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags, + char **output_fields, + const size_t highlight[2], + bool *ellipsized) { + + int ret; + _cleanup_set_free_free_ Set *fields = NULL; + assert(mode >= 0); + assert(mode < _OUTPUT_MODE_MAX); + + if (n_columns <= 0) + n_columns = columns(); + + if (output_fields) { + fields = set_new(&string_hash_ops); + if (!fields) + return log_oom(); + + ret = set_put_strdupv(fields, output_fields); + if (ret < 0) + return ret; + } + + ret = output_funcs[mode](f, j, mode, n_columns, flags, fields, highlight); + + if (ellipsized && ret > 0) + *ellipsized = true; + + return ret; +} + +static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) { + assert(f); + assert(flags); + + if (!(*flags & OUTPUT_BEGIN_NEWLINE)) + return 0; + + /* Print a beginning new line if that's request, but only once + * on the first line we print. */ + + fputc('\n', f); + *flags &= ~OUTPUT_BEGIN_NEWLINE; + return 0; +} + +int show_journal( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + OutputFlags flags, + bool *ellipsized) { + + int r; + unsigned line = 0; + bool need_seek = false; + int warn_cutoff = flags & OUTPUT_WARN_CUTOFF; + + assert(j); + assert(mode >= 0); + assert(mode < _OUTPUT_MODE_MAX); + + if (how_many == (unsigned) -1) + need_seek = true; + else { + /* Seek to end */ + r = sd_journal_seek_tail(j); + if (r < 0) + return log_error_errno(r, "Failed to seek to tail: %m"); + + r = sd_journal_previous_skip(j, how_many); + if (r < 0) + return log_error_errno(r, "Failed to skip previous: %m"); + } + + for (;;) { + for (;;) { + usec_t usec; + + if (need_seek) { + r = sd_journal_next(j); + if (r < 0) + return log_error_errno(r, "Failed to iterate through journal: %m"); + } + + if (r == 0) + break; + + need_seek = true; + + if (not_before > 0) { + r = sd_journal_get_monotonic_usec(j, &usec, NULL); + + /* -ESTALE is returned if the + timestamp is not from this boot */ + if (r == -ESTALE) + continue; + else if (r < 0) + return log_error_errno(r, "Failed to get journal time: %m"); + + if (usec < not_before) + continue; + } + + line++; + maybe_print_begin_newline(f, &flags); + + r = show_journal_entry(f, j, mode, n_columns, flags, NULL, NULL, ellipsized); + if (r < 0) + return r; + } + + if (warn_cutoff && line < how_many && not_before > 0) { + sd_id128_t boot_id; + usec_t cutoff = 0; + + /* Check whether the cutoff line is too early */ + + r = sd_id128_get_boot(&boot_id); + if (r < 0) + return log_error_errno(r, "Failed to get boot id: %m"); + + r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL); + if (r < 0) + return log_error_errno(r, "Failed to get journal cutoff time: %m"); + + if (r > 0 && not_before < cutoff) { + maybe_print_begin_newline(f, &flags); + fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n"); + } + + warn_cutoff = false; + } + + if (!(flags & OUTPUT_FOLLOW)) + break; + + r = sd_journal_wait(j, USEC_INFINITY); + if (r < 0) + return log_error_errno(r, "Failed to wait for journal: %m"); + + } + + return 0; +} + +int add_matches_for_unit(sd_journal *j, const char *unit) { + const char *m1, *m2, *m3, *m4; + int r; + + assert(j); + assert(unit); + + m1 = strjoina("_SYSTEMD_UNIT=", unit); + m2 = strjoina("COREDUMP_UNIT=", unit); + m3 = strjoina("UNIT=", unit); + m4 = strjoina("OBJECT_SYSTEMD_UNIT=", unit); + + (void)( + /* Look for messages from the service itself */ + (r = sd_journal_add_match(j, m1, 0)) || + + /* Look for coredumps of the service */ + (r = sd_journal_add_disjunction(j)) || + (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) || + (r = sd_journal_add_match(j, "_UID=0", 0)) || + (r = sd_journal_add_match(j, m2, 0)) || + + /* Look for messages from PID 1 about this service */ + (r = sd_journal_add_disjunction(j)) || + (r = sd_journal_add_match(j, "_PID=1", 0)) || + (r = sd_journal_add_match(j, m3, 0)) || + + /* Look for messages from authorized daemons about this service */ + (r = sd_journal_add_disjunction(j)) || + (r = sd_journal_add_match(j, "_UID=0", 0)) || + (r = sd_journal_add_match(j, m4, 0)) + ); + + if (r == 0 && endswith(unit, ".slice")) { + const char *m5; + + m5 = strjoina("_SYSTEMD_SLICE=", unit); + + /* Show all messages belonging to a slice */ + (void)( + (r = sd_journal_add_disjunction(j)) || + (r = sd_journal_add_match(j, m5, 0)) + ); + } + + return r; +} + +int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) { + int r; + char *m1, *m2, *m3, *m4; + char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)]; + + assert(j); + assert(unit); + + m1 = strjoina("_SYSTEMD_USER_UNIT=", unit); + m2 = strjoina("USER_UNIT=", unit); + m3 = strjoina("COREDUMP_USER_UNIT=", unit); + m4 = strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit); + sprintf(muid, "_UID="UID_FMT, uid); + + (void) ( + /* Look for messages from the user service itself */ + (r = sd_journal_add_match(j, m1, 0)) || + (r = sd_journal_add_match(j, muid, 0)) || + + /* Look for messages from systemd about this service */ + (r = sd_journal_add_disjunction(j)) || + (r = sd_journal_add_match(j, m2, 0)) || + (r = sd_journal_add_match(j, muid, 0)) || + + /* Look for coredumps of the service */ + (r = sd_journal_add_disjunction(j)) || + (r = sd_journal_add_match(j, m3, 0)) || + (r = sd_journal_add_match(j, muid, 0)) || + (r = sd_journal_add_match(j, "_UID=0", 0)) || + + /* Look for messages from authorized daemons about this service */ + (r = sd_journal_add_disjunction(j)) || + (r = sd_journal_add_match(j, m4, 0)) || + (r = sd_journal_add_match(j, muid, 0)) || + (r = sd_journal_add_match(j, "_UID=0", 0)) + ); + + if (r == 0 && endswith(unit, ".slice")) { + const char *m5; + + m5 = strjoina("_SYSTEMD_SLICE=", unit); + + /* Show all messages belonging to a slice */ + (void)( + (r = sd_journal_add_disjunction(j)) || + (r = sd_journal_add_match(j, m5, 0)) || + (r = sd_journal_add_match(j, muid, 0)) + ); + } + + return r; +} + +static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1; + pid_t pid, child; + char buf[37]; + ssize_t k; + int r; + + assert(machine); + assert(boot_id); + + if (!machine_name_is_valid(machine)) + return -EINVAL; + + r = container_get_leader(machine, &pid); + if (r < 0) + return r; + + r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, NULL, &rootfd); + if (r < 0) + return r; + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0) + return -errno; + + r = namespace_fork("(sd-bootidns)", "(sd-bootid)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG, + pidnsfd, mntnsfd, -1, -1, rootfd, &child); + if (r < 0) + return r; + if (r == 0) { + int fd; + + pair[0] = safe_close(pair[0]); + + fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + _exit(EXIT_FAILURE); + + r = loop_read_exact(fd, buf, 36, false); + safe_close(fd); + if (r < 0) + _exit(EXIT_FAILURE); + + k = send(pair[1], buf, 36, MSG_NOSIGNAL); + if (k != 36) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + r = wait_for_terminate_and_check("(sd-bootidns)", child, 0); + if (r < 0) + return r; + if (r != EXIT_SUCCESS) + return -EIO; + + k = recv(pair[0], buf, 36, 0); + if (k != 36) + return -EIO; + + buf[36] = 0; + r = sd_id128_from_string(buf, boot_id); + if (r < 0) + return r; + + return 0; +} + +int add_match_this_boot(sd_journal *j, const char *machine) { + char match[9+32+1] = "_BOOT_ID="; + sd_id128_t boot_id; + int r; + + assert(j); + + if (machine) { + r = get_boot_id_for_machine(machine, &boot_id); + if (r < 0) + return log_error_errno(r, "Failed to get boot id of container %s: %m", machine); + } else { + r = sd_id128_get_boot(&boot_id); + if (r < 0) + return log_error_errno(r, "Failed to get boot id: %m"); + } + + sd_id128_to_string(boot_id, match + 9); + r = sd_journal_add_match(j, match, strlen(match)); + if (r < 0) + return log_error_errno(r, "Failed to add match: %m"); + + r = sd_journal_add_conjunction(j); + if (r < 0) + return log_error_errno(r, "Failed to add conjunction: %m"); + + return 0; +} + +int show_journal_by_unit( + FILE *f, + const char *unit, + OutputMode mode, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + uid_t uid, + OutputFlags flags, + int journal_open_flags, + bool system_unit, + bool *ellipsized) { + + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + int r; + + assert(mode >= 0); + assert(mode < _OUTPUT_MODE_MAX); + assert(unit); + + if (how_many <= 0) + return 0; + + r = sd_journal_open(&j, journal_open_flags); + if (r < 0) + return log_error_errno(r, "Failed to open journal: %m"); + + r = add_match_this_boot(j, NULL); + if (r < 0) + return r; + + if (system_unit) + r = add_matches_for_unit(j, unit); + else + r = add_matches_for_user_unit(j, unit, uid); + if (r < 0) + return log_error_errno(r, "Failed to add unit matches: %m"); + + if (DEBUG_LOGGING) { + _cleanup_free_ char *filter; + + filter = journal_make_match_string(j); + if (!filter) + return log_oom(); + + log_debug("Journal filter: %s", filter); + } + + return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized); +} diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h new file mode 100644 index 00000000..1e0c4ea1 --- /dev/null +++ b/src/shared/logs-show.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include +#include + +#include "sd-journal.h" + +#include "macro.h" +#include "output-mode.h" +#include "time-util.h" +#include "util.h" + +int show_journal_entry( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + OutputFlags flags, + char **output_fields, + const size_t highlight[2], + bool *ellipsized); +int show_journal( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + OutputFlags flags, + bool *ellipsized); + +int add_match_this_boot(sd_journal *j, const char *machine); + +int add_matches_for_unit( + sd_journal *j, + const char *unit); + +int add_matches_for_user_unit( + sd_journal *j, + const char *unit, + uid_t uid); + +int show_journal_by_unit( + FILE *f, + const char *unit, + OutputMode mode, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + uid_t uid, + OutputFlags flags, + int journal_open_flags, + bool system_unit, + bool *ellipsized); + +void json_escape( + FILE *f, + const char* p, + size_t l, + OutputFlags flags); diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c new file mode 100644 index 00000000..559d7f81 --- /dev/null +++ b/src/shared/loop-util.c @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "loop-util.h" +#include "stat-util.h" + +int loop_device_make(int fd, int open_flags, LoopDevice **ret) { + const struct loop_info64 info = { + .lo_flags = LO_FLAGS_AUTOCLEAR|LO_FLAGS_PARTSCAN|(open_flags == O_RDONLY ? LO_FLAGS_READ_ONLY : 0), + }; + + _cleanup_close_ int control = -1, loop = -1; + _cleanup_free_ char *loopdev = NULL; + unsigned n_attempts = 0; + struct stat st; + LoopDevice *d; + int nr, r; + + assert(fd >= 0); + assert(ret); + assert(IN_SET(open_flags, O_RDWR, O_RDONLY)); + + if (fstat(fd, &st) < 0) + return -errno; + + if (S_ISBLK(st.st_mode)) { + int copy; + + /* If this is already a block device, store a copy of the fd as it is */ + + copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (copy < 0) + return -errno; + + d = new0(LoopDevice, 1); + if (!d) + return -ENOMEM; + + *d = (LoopDevice) { + .fd = copy, + .nr = -1, + .relinquished = true, /* It's not allocated by us, don't destroy it when this object is freed */ + }; + + *ret = d; + return d->fd; + } + + r = stat_verify_regular(&st); + if (r < 0) + return r; + + control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); + if (control < 0) + return -errno; + + /* Loop around LOOP_CTL_GET_FREE, since at the moment we attempt to open the returned device it might + * be gone already, taken by somebody else racing against us. */ + for (;;) { + nr = ioctl(control, LOOP_CTL_GET_FREE); + if (nr < 0) + return -errno; + + if (asprintf(&loopdev, "/dev/loop%i", nr) < 0) + return -ENOMEM; + + loop = open(loopdev, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|open_flags); + if (loop < 0) + return -errno; + if (ioctl(loop, LOOP_SET_FD, fd) < 0) { + if (errno != EBUSY) + return -errno; + + if (++n_attempts >= 64) /* Give up eventually */ + return -EBUSY; + } else + break; + + loopdev = mfree(loopdev); + loop = safe_close(loop); + } + + if (ioctl(loop, LOOP_SET_STATUS64, &info) < 0) + return -errno; + + d = new(LoopDevice, 1); + if (!d) + return -ENOMEM; + + *d = (LoopDevice) { + .fd = TAKE_FD(loop), + .node = TAKE_PTR(loopdev), + .nr = nr, + }; + + *ret = d; + return d->fd; +} + +int loop_device_make_by_path(const char *path, int open_flags, LoopDevice **ret) { + _cleanup_close_ int fd = -1; + + assert(path); + assert(ret); + assert(IN_SET(open_flags, O_RDWR, O_RDONLY)); + + fd = open(path, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|open_flags); + if (fd < 0) + return -errno; + + return loop_device_make(fd, open_flags, ret); +} + +LoopDevice* loop_device_unref(LoopDevice *d) { + if (!d) + return NULL; + + if (d->fd >= 0) { + + if (d->nr >= 0 && !d->relinquished) { + if (ioctl(d->fd, LOOP_CLR_FD) < 0) + log_debug_errno(errno, "Failed to clear loop device: %m"); + + } + + safe_close(d->fd); + } + + if (d->nr >= 0 && !d->relinquished) { + _cleanup_close_ int control = -1; + + control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); + if (control < 0) + log_debug_errno(errno, "Failed to open loop control device: %m"); + else { + if (ioctl(control, LOOP_CTL_REMOVE, d->nr) < 0) + log_debug_errno(errno, "Failed to remove loop device: %m"); + } + } + + free(d->node); + return mfree(d); +} + +void loop_device_relinquish(LoopDevice *d) { + assert(d); + + /* Don't attempt to clean up the loop device anymore from this point on. Leave the clean-ing up to the kernel + * itself, using the loop device "auto-clear" logic we already turned on when creating the device. */ + + d->relinquished = true; +} diff --git a/src/shared/loop-util.h b/src/shared/loop-util.h new file mode 100644 index 00000000..d78466c5 --- /dev/null +++ b/src/shared/loop-util.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "macro.h" + +typedef struct LoopDevice LoopDevice; + +/* Some helpers for setting up loopback block devices */ + +struct LoopDevice { + int fd; + int nr; + char *node; + bool relinquished; +}; + +int loop_device_make(int fd, int open_flags, LoopDevice **ret); +int loop_device_make_by_path(const char *path, int open_flags, LoopDevice **ret); + +LoopDevice* loop_device_unref(LoopDevice *d); +DEFINE_TRIVIAL_CLEANUP_FUNC(LoopDevice*, loop_device_unref); + +void loop_device_relinquish(LoopDevice *d); diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c new file mode 100644 index 00000000..a11803e7 --- /dev/null +++ b/src/shared/machine-image.c @@ -0,0 +1,1273 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "chattr-util.h" +#include "copy.h" +#include "dirent-util.h" +#include "dissect-image.h" +#include "env-file.h" +#include "env-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "hostname-util.h" +#include "id128-util.h" +#include "lockfile-util.h" +#include "log.h" +#include "loop-util.h" +#include "machine-image.h" +#include "macro.h" +#include "mkdir.h" +#include "nulstr-util.h" +#include "os-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "utf8.h" +#include "xattr-util.h" + +static const char* const image_search_path[_IMAGE_CLASS_MAX] = { + [IMAGE_MACHINE] = "/etc/machines\0" /* only place symlinks here */ + "/run/machines\0" /* and here too */ + "/var/lib/machines\0" /* the main place for images */ + "/var/lib/container\0" /* legacy */ + "/usr/local/lib/machines\0" + "/usr/lib/machines\0", + + [IMAGE_PORTABLE] = "/etc/portables\0" /* only place symlinks here */ + "/run/portables\0" /* and here too */ + "/var/lib/portables\0" /* the main place for images */ + "/usr/local/lib/portables\0" + "/usr/lib/portables\0", +}; + +static Image *image_free(Image *i) { + assert(i); + + free(i->name); + free(i->path); + + free(i->hostname); + strv_free(i->machine_info); + strv_free(i->os_release); + + return mfree(i); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(Image, image, image_free); +DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(image_hash_ops, char, string_hash_func, string_compare_func, + Image, image_unref); + +static char **image_settings_path(Image *image) { + _cleanup_strv_free_ char **l = NULL; + const char *fn, *s; + unsigned i = 0; + + assert(image); + + l = new0(char*, 4); + if (!l) + return NULL; + + fn = strjoina(image->name, ".nspawn"); + + FOREACH_STRING(s, "/etc/systemd/nspawn", "/run/systemd/nspawn") { + l[i] = path_join(s, fn); + if (!l[i]) + return NULL; + + i++; + } + + l[i] = file_in_same_dir(image->path, fn); + if (!l[i]) + return NULL; + + return TAKE_PTR(l); +} + +static char *image_roothash_path(Image *image) { + const char *fn; + + assert(image); + + fn = strjoina(image->name, ".roothash"); + + return file_in_same_dir(image->path, fn); +} + +static int image_new( + ImageType t, + const char *pretty, + const char *path, + const char *filename, + bool read_only, + usec_t crtime, + usec_t mtime, + Image **ret) { + + _cleanup_(image_unrefp) Image *i = NULL; + + assert(t >= 0); + assert(t < _IMAGE_TYPE_MAX); + assert(pretty); + assert(filename); + assert(ret); + + i = new0(Image, 1); + if (!i) + return -ENOMEM; + + i->n_ref = 1; + i->type = t; + i->read_only = read_only; + i->crtime = crtime; + i->mtime = mtime; + i->usage = i->usage_exclusive = (uint64_t) -1; + i->limit = i->limit_exclusive = (uint64_t) -1; + + i->name = strdup(pretty); + if (!i->name) + return -ENOMEM; + + i->path = path_join(path, filename); + if (!i->path) + return -ENOMEM; + + path_simplify(i->path, false); + + *ret = TAKE_PTR(i); + + return 0; +} + +static int extract_pretty(const char *path, const char *suffix, char **ret) { + _cleanup_free_ char *name = NULL; + const char *p; + size_t n; + + assert(path); + assert(ret); + + p = last_path_component(path); + n = strcspn(p, "/"); + + name = strndup(p, n); + if (!name) + return -ENOMEM; + + if (suffix) { + char *e; + + e = endswith(name, suffix); + if (!e) + return -EINVAL; + + *e = 0; + } + + if (!image_name_is_valid(name)) + return -EINVAL; + + *ret = TAKE_PTR(name); + return 0; +} + +static int image_make( + const char *pretty, + int dfd, + const char *path, + const char *filename, + const struct stat *st, + Image **ret) { + + _cleanup_free_ char *pretty_buffer = NULL, *parent = NULL; + struct stat stbuf; + bool read_only; + int r; + + assert(dfd >= 0 || dfd == AT_FDCWD); + assert(path || dfd == AT_FDCWD); + assert(filename); + + /* We explicitly *do* follow symlinks here, since we want to allow symlinking trees, raw files and block + * devices into /var/lib/machines/, and treat them normally. + * + * This function returns -ENOENT if we can't find the image after all, and -EMEDIUMTYPE if it's not a file we + * recognize. */ + + if (!st) { + if (fstatat(dfd, filename, &stbuf, 0) < 0) + return -errno; + + st = &stbuf; + } + + if (!path) { + if (dfd == AT_FDCWD) + (void) safe_getcwd(&parent); + else + (void) fd_get_path(dfd, &parent); + } + + read_only = + (path && path_startswith(path, "/usr")) || + (faccessat(dfd, filename, W_OK, AT_EACCESS) < 0 && errno == EROFS); + + if (S_ISDIR(st->st_mode)) { + _cleanup_close_ int fd = -1; + unsigned file_attr = 0; + + if (!ret) + return 0; + + if (!pretty) { + r = extract_pretty(filename, NULL, &pretty_buffer); + if (r < 0) + return r; + + pretty = pretty_buffer; + } + + fd = openat(dfd, filename, O_CLOEXEC|O_NOCTTY|O_DIRECTORY); + if (fd < 0) + return -errno; + + /* btrfs subvolumes have inode 256 */ + if (st->st_ino == 256) { + + r = btrfs_is_filesystem(fd); + if (r < 0) + return r; + if (r) { + BtrfsSubvolInfo info; + + /* It's a btrfs subvolume */ + + r = btrfs_subvol_get_info_fd(fd, 0, &info); + if (r < 0) + return r; + + r = image_new(IMAGE_SUBVOLUME, + pretty, + path, + filename, + info.read_only || read_only, + info.otime, + 0, + ret); + if (r < 0) + return r; + + if (btrfs_quota_scan_ongoing(fd) == 0) { + BtrfsQuotaInfo quota; + + r = btrfs_subvol_get_subtree_quota_fd(fd, 0, "a); + if (r >= 0) { + (*ret)->usage = quota.referenced; + (*ret)->usage_exclusive = quota.exclusive; + + (*ret)->limit = quota.referenced_max; + (*ret)->limit_exclusive = quota.exclusive_max; + } + } + + return 0; + } + } + + /* If the IMMUTABLE bit is set, we consider the + * directory read-only. Since the ioctl is not + * supported everywhere we ignore failures. */ + (void) read_attr_fd(fd, &file_attr); + + /* It's just a normal directory. */ + r = image_new(IMAGE_DIRECTORY, + pretty, + path, + filename, + read_only || (file_attr & FS_IMMUTABLE_FL), + 0, + 0, + ret); + if (r < 0) + return r; + + return 0; + + } else if (S_ISREG(st->st_mode) && endswith(filename, ".raw")) { + usec_t crtime = 0; + + /* It's a RAW disk image */ + + if (!ret) + return 0; + + (void) fd_getcrtime_at(dfd, filename, &crtime, 0); + + if (!pretty) { + r = extract_pretty(filename, ".raw", &pretty_buffer); + if (r < 0) + return r; + + pretty = pretty_buffer; + } + + r = image_new(IMAGE_RAW, + pretty, + path, + filename, + !(st->st_mode & 0222) || read_only, + crtime, + timespec_load(&st->st_mtim), + ret); + if (r < 0) + return r; + + (*ret)->usage = (*ret)->usage_exclusive = st->st_blocks * 512; + (*ret)->limit = (*ret)->limit_exclusive = st->st_size; + + return 0; + + } else if (S_ISBLK(st->st_mode)) { + _cleanup_close_ int block_fd = -1; + uint64_t size = UINT64_MAX; + + /* A block device */ + + if (!ret) + return 0; + + if (!pretty) { + r = extract_pretty(filename, NULL, &pretty_buffer); + if (r < 0) + return r; + + pretty = pretty_buffer; + } + + block_fd = openat(dfd, filename, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); + if (block_fd < 0) + log_debug_errno(errno, "Failed to open block device %s/%s, ignoring: %m", path ?: strnull(parent), filename); + else { + /* Refresh stat data after opening the node */ + if (fstat(block_fd, &stbuf) < 0) + return -errno; + st = &stbuf; + + if (!S_ISBLK(st->st_mode)) /* Verify that what we opened is actually what we think it is */ + return -ENOTTY; + + if (!read_only) { + int state = 0; + + if (ioctl(block_fd, BLKROGET, &state) < 0) + log_debug_errno(errno, "Failed to issue BLKROGET on device %s/%s, ignoring: %m", path ?: strnull(parent), filename); + else if (state) + read_only = true; + } + + if (ioctl(block_fd, BLKGETSIZE64, &size) < 0) + log_debug_errno(errno, "Failed to issue BLKGETSIZE64 on device %s/%s, ignoring: %m", path ?: strnull(parent), filename); + + block_fd = safe_close(block_fd); + } + + r = image_new(IMAGE_BLOCK, + pretty, + path, + filename, + !(st->st_mode & 0222) || read_only, + 0, + 0, + ret); + if (r < 0) + return r; + + if (!IN_SET(size, 0, UINT64_MAX)) + (*ret)->usage = (*ret)->usage_exclusive = (*ret)->limit = (*ret)->limit_exclusive = size; + + return 0; + } + + return -EMEDIUMTYPE; +} + +int image_find(ImageClass class, const char *name, Image **ret) { + const char *path; + int r; + + assert(class >= 0); + assert(class < _IMAGE_CLASS_MAX); + assert(name); + + /* There are no images with invalid names */ + if (!image_name_is_valid(name)) + return -ENOENT; + + NULSTR_FOREACH(path, image_search_path[class]) { + _cleanup_closedir_ DIR *d = NULL; + struct stat st; + + d = opendir(path); + if (!d) { + if (errno == ENOENT) + continue; + + return -errno; + } + + /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people to + * symlink block devices into the search path */ + if (fstatat(dirfd(d), name, &st, 0) < 0) { + _cleanup_free_ char *raw = NULL; + + if (errno != ENOENT) + return -errno; + + raw = strjoin(name, ".raw"); + if (!raw) + return -ENOMEM; + + if (fstatat(dirfd(d), raw, &st, 0) < 0) { + + if (errno == ENOENT) + continue; + + return -errno; + } + + if (!S_ISREG(st.st_mode)) + continue; + + r = image_make(name, dirfd(d), path, raw, &st, ret); + + } else { + if (!S_ISDIR(st.st_mode) && !S_ISBLK(st.st_mode)) + continue; + + r = image_make(name, dirfd(d), path, name, &st, ret); + } + if (IN_SET(r, -ENOENT, -EMEDIUMTYPE)) + continue; + if (r < 0) + return r; + + if (ret) + (*ret)->discoverable = true; + + return 1; + } + + if (class == IMAGE_MACHINE && streq(name, ".host")) { + r = image_make(".host", AT_FDCWD, NULL, "/", NULL, ret); + if (r < 0) + return r; + + if (ret) + (*ret)->discoverable = true; + + return r; + } + + return -ENOENT; +}; + +int image_from_path(const char *path, Image **ret) { + + /* Note that we don't set the 'discoverable' field of the returned object, because we don't check here whether + * the image is in the image search path. And if it is we don't know if the path we used is actually not + * overridden by another, different image earlier in the search path */ + + if (path_equal(path, "/")) + return image_make(".host", AT_FDCWD, NULL, "/", NULL, ret); + + return image_make(NULL, AT_FDCWD, NULL, path, NULL, ret); +} + +int image_find_harder(ImageClass class, const char *name_or_path, Image **ret) { + if (image_name_is_valid(name_or_path)) + return image_find(class, name_or_path, ret); + + return image_from_path(name_or_path, ret); +} + +int image_discover(ImageClass class, Hashmap *h) { + const char *path; + int r; + + assert(class >= 0); + assert(class < _IMAGE_CLASS_MAX); + assert(h); + + NULSTR_FOREACH(path, image_search_path[class]) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + + d = opendir(path); + if (!d) { + if (errno == ENOENT) + continue; + + return -errno; + } + + FOREACH_DIRENT_ALL(de, d, return -errno) { + _cleanup_(image_unrefp) Image *image = NULL; + _cleanup_free_ char *truncated = NULL; + const char *pretty; + struct stat st; + + if (dot_or_dot_dot(de->d_name)) + continue; + + /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people + * to symlink block devices into the search path */ + if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) { + if (errno == ENOENT) + continue; + + return -errno; + } + + if (S_ISREG(st.st_mode)) { + const char *e; + + e = endswith(de->d_name, ".raw"); + if (!e) + continue; + + truncated = strndup(de->d_name, e - de->d_name); + if (!truncated) + return -ENOMEM; + + pretty = truncated; + } else if (S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) + pretty = de->d_name; + else + continue; + + if (!image_name_is_valid(pretty)) + continue; + + if (hashmap_contains(h, pretty)) + continue; + + r = image_make(pretty, dirfd(d), path, de->d_name, &st, &image); + if (IN_SET(r, -ENOENT, -EMEDIUMTYPE)) + continue; + if (r < 0) + return r; + + image->discoverable = true; + + r = hashmap_put(h, image->name, image); + if (r < 0) + return r; + + image = NULL; + } + } + + if (class == IMAGE_MACHINE && !hashmap_contains(h, ".host")) { + _cleanup_(image_unrefp) Image *image = NULL; + + r = image_make(".host", AT_FDCWD, NULL, "/", NULL, &image); + if (r < 0) + return r; + + image->discoverable = true; + + r = hashmap_put(h, image->name, image); + if (r < 0) + return r; + + image = NULL; + } + + return 0; +} + +int image_remove(Image *i) { + _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; + _cleanup_strv_free_ char **settings = NULL; + _cleanup_free_ char *roothash = NULL; + char **j; + int r; + + assert(i); + + if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i)) + return -EROFS; + + settings = image_settings_path(i); + if (!settings) + return -ENOMEM; + + roothash = image_roothash_path(i); + if (!roothash) + return -ENOMEM; + + /* Make sure we don't interfere with a running nspawn */ + r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock); + if (r < 0) + return r; + + switch (i->type) { + + case IMAGE_SUBVOLUME: + + /* Let's unlink first, maybe it is a symlink? If that works we are happy. Otherwise, let's get out the + * big guns */ + if (unlink(i->path) < 0) { + r = btrfs_subvol_remove(i->path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); + if (r < 0) + return r; + } + + break; + + case IMAGE_DIRECTORY: + /* Allow deletion of read-only directories */ + (void) chattr_path(i->path, 0, FS_IMMUTABLE_FL, NULL); + r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); + if (r < 0) + return r; + + break; + + case IMAGE_BLOCK: + + /* If this is inside of /dev, then it's a real block device, hence let's not touch the device node + * itself (but let's remove the stuff stored alongside it). If it's anywhere else, let's try to unlink + * the thing (it's most likely a symlink after all). */ + + if (path_startswith(i->path, "/dev")) + break; + + _fallthrough_; + case IMAGE_RAW: + if (unlink(i->path) < 0) + return -errno; + break; + + default: + return -EOPNOTSUPP; + } + + STRV_FOREACH(j, settings) { + if (unlink(*j) < 0 && errno != ENOENT) + log_debug_errno(errno, "Failed to unlink %s, ignoring: %m", *j); + } + + if (unlink(roothash) < 0 && errno != ENOENT) + log_debug_errno(errno, "Failed to unlink %s, ignoring: %m", roothash); + + return 0; +} + +static int rename_auxiliary_file(const char *path, const char *new_name, const char *suffix) { + _cleanup_free_ char *rs = NULL; + const char *fn; + + fn = strjoina(new_name, suffix); + + rs = file_in_same_dir(path, fn); + if (!rs) + return -ENOMEM; + + return rename_noreplace(AT_FDCWD, path, AT_FDCWD, rs); +} + +int image_rename(Image *i, const char *new_name) { + _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT, name_lock = LOCK_FILE_INIT; + _cleanup_free_ char *new_path = NULL, *nn = NULL, *roothash = NULL; + _cleanup_strv_free_ char **settings = NULL; + unsigned file_attr = 0; + char **j; + int r; + + assert(i); + + if (!image_name_is_valid(new_name)) + return -EINVAL; + + if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i)) + return -EROFS; + + settings = image_settings_path(i); + if (!settings) + return -ENOMEM; + + roothash = image_roothash_path(i); + if (!roothash) + return -ENOMEM; + + /* Make sure we don't interfere with a running nspawn */ + r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock); + if (r < 0) + return r; + + /* Make sure nobody takes the new name, between the time we + * checked it is currently unused in all search paths, and the + * time we take possession of it */ + r = image_name_lock(new_name, LOCK_EX|LOCK_NB, &name_lock); + if (r < 0) + return r; + + r = image_find(IMAGE_MACHINE, new_name, NULL); + if (r >= 0) + return -EEXIST; + if (r != -ENOENT) + return r; + + switch (i->type) { + + case IMAGE_DIRECTORY: + /* Turn of the immutable bit while we rename the image, so that we can rename it */ + (void) read_attr_path(i->path, &file_attr); + + if (file_attr & FS_IMMUTABLE_FL) + (void) chattr_path(i->path, 0, FS_IMMUTABLE_FL, NULL); + + _fallthrough_; + case IMAGE_SUBVOLUME: + new_path = file_in_same_dir(i->path, new_name); + break; + + case IMAGE_BLOCK: + + /* Refuse renaming raw block devices in /dev, the names are picked by udev after all. */ + if (path_startswith(i->path, "/dev")) + return -EROFS; + + new_path = file_in_same_dir(i->path, new_name); + break; + + case IMAGE_RAW: { + const char *fn; + + fn = strjoina(new_name, ".raw"); + new_path = file_in_same_dir(i->path, fn); + break; + } + + default: + return -EOPNOTSUPP; + } + + if (!new_path) + return -ENOMEM; + + nn = strdup(new_name); + if (!nn) + return -ENOMEM; + + r = rename_noreplace(AT_FDCWD, i->path, AT_FDCWD, new_path); + if (r < 0) + return r; + + /* Restore the immutable bit, if it was set before */ + if (file_attr & FS_IMMUTABLE_FL) + (void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL, NULL); + + free_and_replace(i->path, new_path); + free_and_replace(i->name, nn); + + STRV_FOREACH(j, settings) { + r = rename_auxiliary_file(*j, new_name, ".nspawn"); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to rename settings file %s, ignoring: %m", *j); + } + + r = rename_auxiliary_file(roothash, new_name, ".roothash"); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to rename roothash file %s, ignoring: %m", roothash); + + return 0; +} + +static int clone_auxiliary_file(const char *path, const char *new_name, const char *suffix) { + _cleanup_free_ char *rs = NULL; + const char *fn; + + fn = strjoina(new_name, suffix); + + rs = file_in_same_dir(path, fn); + if (!rs) + return -ENOMEM; + + return copy_file_atomic(path, rs, 0664, 0, 0, COPY_REFLINK); +} + +int image_clone(Image *i, const char *new_name, bool read_only) { + _cleanup_(release_lock_file) LockFile name_lock = LOCK_FILE_INIT; + _cleanup_strv_free_ char **settings = NULL; + _cleanup_free_ char *roothash = NULL; + const char *new_path; + char **j; + int r; + + assert(i); + + if (!image_name_is_valid(new_name)) + return -EINVAL; + + settings = image_settings_path(i); + if (!settings) + return -ENOMEM; + + roothash = image_roothash_path(i); + if (!roothash) + return -ENOMEM; + + /* Make sure nobody takes the new name, between the time we + * checked it is currently unused in all search paths, and the + * time we take possession of it */ + r = image_name_lock(new_name, LOCK_EX|LOCK_NB, &name_lock); + if (r < 0) + return r; + + r = image_find(IMAGE_MACHINE, new_name, NULL); + if (r >= 0) + return -EEXIST; + if (r != -ENOENT) + return r; + + switch (i->type) { + + case IMAGE_SUBVOLUME: + case IMAGE_DIRECTORY: + /* If we can we'll always try to create a new btrfs subvolume here, even if the source is a plain + * directory. */ + + new_path = strjoina("/var/lib/machines/", new_name); + + r = btrfs_subvol_snapshot(i->path, new_path, + (read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) | + BTRFS_SNAPSHOT_FALLBACK_COPY | + BTRFS_SNAPSHOT_FALLBACK_DIRECTORY | + BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE | + BTRFS_SNAPSHOT_RECURSIVE | + BTRFS_SNAPSHOT_QUOTA); + if (r >= 0) + /* Enable "subtree" quotas for the copy, if we didn't copy any quota from the source. */ + (void) btrfs_subvol_auto_qgroup(new_path, 0, true); + + break; + + case IMAGE_RAW: + new_path = strjoina("/var/lib/machines/", new_name, ".raw"); + + r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644, FS_NOCOW_FL, FS_NOCOW_FL, COPY_REFLINK|COPY_CRTIME); + break; + + case IMAGE_BLOCK: + default: + return -EOPNOTSUPP; + } + + if (r < 0) + return r; + + STRV_FOREACH(j, settings) { + r = clone_auxiliary_file(*j, new_name, ".nspawn"); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to clone settings %s, ignoring: %m", *j); + } + + r = clone_auxiliary_file(roothash, new_name, ".roothash"); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to clone root hash file %s, ignoring: %m", roothash); + + return 0; +} + +int image_read_only(Image *i, bool b) { + _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; + int r; + + assert(i); + + if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i)) + return -EROFS; + + /* Make sure we don't interfere with a running nspawn */ + r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock); + if (r < 0) + return r; + + switch (i->type) { + + case IMAGE_SUBVOLUME: + + /* Note that we set the flag only on the top-level + * subvolume of the image. */ + + r = btrfs_subvol_set_read_only(i->path, b); + if (r < 0) + return r; + + break; + + case IMAGE_DIRECTORY: + /* For simple directory trees we cannot use the access + mode of the top-level directory, since it has an + effect on the container itself. However, we can + use the "immutable" flag, to at least make the + top-level directory read-only. It's not as good as + a read-only subvolume, but at least something, and + we can read the value back. */ + + r = chattr_path(i->path, b ? FS_IMMUTABLE_FL : 0, FS_IMMUTABLE_FL, NULL); + if (r < 0) + return r; + + break; + + case IMAGE_RAW: { + struct stat st; + + if (stat(i->path, &st) < 0) + return -errno; + + if (chmod(i->path, (st.st_mode & 0444) | (b ? 0000 : 0200)) < 0) + return -errno; + + /* If the images is now read-only, it's a good time to + * defrag it, given that no write patterns will + * fragment it again. */ + if (b) + (void) btrfs_defrag(i->path); + break; + } + + case IMAGE_BLOCK: { + _cleanup_close_ int fd = -1; + struct stat st; + int state = b; + + fd = open(i->path, O_CLOEXEC|O_RDONLY|O_NONBLOCK|O_NOCTTY); + if (fd < 0) + return -errno; + + if (fstat(fd, &st) < 0) + return -errno; + if (!S_ISBLK(st.st_mode)) + return -ENOTTY; + + if (ioctl(fd, BLKROSET, &state) < 0) + return -errno; + + break; + } + + default: + return -EOPNOTSUPP; + } + + return 0; +} + +int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local) { + _cleanup_free_ char *p = NULL; + LockFile t = LOCK_FILE_INIT; + struct stat st; + bool exclusive; + int r; + + assert(path); + assert(global); + assert(local); + + /* Locks an image path. This actually creates two locks: one "local" one, next to the image path + * itself, which might be shared via NFS. And another "global" one, in /run, that uses the + * device/inode number. This has the benefit that we can even lock a tree that is a mount point, + * correctly. */ + + if (!path_is_absolute(path)) + return -EINVAL; + + switch (operation & (LOCK_SH|LOCK_EX)) { + case LOCK_SH: + exclusive = false; + break; + case LOCK_EX: + exclusive = true; + break; + default: + return -EINVAL; + } + + if (getenv_bool("SYSTEMD_NSPAWN_LOCK") == 0) { + *local = *global = (LockFile) LOCK_FILE_INIT; + return 0; + } + + /* Prohibit taking exclusive locks on the host image. We can't allow this, since we ourselves are + * running off it after all, and we don't want any images to manipulate the host image. We make an + * exception for shared locks however: we allow those (and make them NOPs since there's no point in + * taking them if there can't be exclusive locks). Strictly speaking these are questionable as well, + * since it means changes made to the host might propagate to the container as they happen (and a + * shared lock kinda suggests that no changes happen at all while it is in place), but it's too + * useful not to allow read-only containers off the host root, hence let's support this, and trust + * the user to do the right thing with this. */ + if (path_equal(path, "/")) { + if (exclusive) + return -EBUSY; + + *local = *global = (LockFile) LOCK_FILE_INIT; + return 0; + } + + if (stat(path, &st) >= 0) { + if (S_ISBLK(st.st_mode)) + r = asprintf(&p, "/run/systemd/nspawn/locks/block-%u:%u", major(st.st_rdev), minor(st.st_rdev)); + else if (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode)) + r = asprintf(&p, "/run/systemd/nspawn/locks/inode-%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino); + else + return -ENOTTY; + + if (r < 0) + return -ENOMEM; + } + + /* For block devices we don't need the "local" lock, as the major/minor lock above should be + * sufficient, since block devices are host local anyway. */ + if (!path_startswith(path, "/dev/")) { + r = make_lock_file_for(path, operation, &t); + if (r < 0) { + if (!exclusive && r == -EROFS) + log_debug_errno(r, "Failed to create shared lock for '%s', ignoring: %m", path); + else + return r; + } + } + + if (p) { + (void) mkdir_p("/run/systemd/nspawn/locks", 0700); + + r = make_lock_file(p, operation, global); + if (r < 0) { + release_lock_file(&t); + return r; + } + } else + *global = (LockFile) LOCK_FILE_INIT; + + *local = t; + return 0; +} + +int image_set_limit(Image *i, uint64_t referenced_max) { + assert(i); + + if (IMAGE_IS_VENDOR(i) || IMAGE_IS_HOST(i)) + return -EROFS; + + if (i->type != IMAGE_SUBVOLUME) + return -EOPNOTSUPP; + + /* We set the quota both for the subvolume as well as for the + * subtree. The latter is mostly for historical reasons, since + * we didn't use to have a concept of subtree quota, and hence + * only modified the subvolume quota. */ + + (void) btrfs_qgroup_set_limit(i->path, 0, referenced_max); + (void) btrfs_subvol_auto_qgroup(i->path, 0, true); + return btrfs_subvol_set_subtree_quota_limit(i->path, 0, referenced_max); +} + +int image_read_metadata(Image *i) { + _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; + int r; + + assert(i); + + r = image_path_lock(i->path, LOCK_SH|LOCK_NB, &global_lock, &local_lock); + if (r < 0) + return r; + + switch (i->type) { + + case IMAGE_SUBVOLUME: + case IMAGE_DIRECTORY: { + _cleanup_strv_free_ char **machine_info = NULL, **os_release = NULL; + sd_id128_t machine_id = SD_ID128_NULL; + _cleanup_free_ char *hostname = NULL; + _cleanup_free_ char *path = NULL; + + r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to chase /etc/hostname in image %s: %m", i->name); + else if (r >= 0) { + r = read_etc_hostname(path, &hostname); + if (r < 0) + log_debug_errno(errno, "Failed to read /etc/hostname of image %s: %m", i->name); + } + + path = mfree(path); + + r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to chase /etc/machine-id in image %s: %m", i->name); + else if (r >= 0) { + _cleanup_close_ int fd = -1; + + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + log_debug_errno(errno, "Failed to open %s: %m", path); + else { + r = id128_read_fd(fd, ID128_PLAIN, &machine_id); + if (r < 0) + log_debug_errno(r, "Image %s contains invalid machine ID.", i->name); + } + } + + path = mfree(path); + + r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL); + if (r < 0 && r != -ENOENT) + log_debug_errno(r, "Failed to chase /etc/machine-info in image %s: %m", i->name); + else if (r >= 0) { + r = load_env_file_pairs(NULL, path, &machine_info); + if (r < 0) + log_debug_errno(r, "Failed to parse machine-info data of %s: %m", i->name); + } + + r = load_os_release_pairs(i->path, &os_release); + if (r < 0) + log_debug_errno(r, "Failed to read os-release in image, ignoring: %m"); + + free_and_replace(i->hostname, hostname); + i->machine_id = machine_id; + strv_free_and_replace(i->machine_info, machine_info); + strv_free_and_replace(i->os_release, os_release); + + break; + } + + case IMAGE_RAW: + case IMAGE_BLOCK: { + _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; + _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; + + r = loop_device_make_by_path(i->path, O_RDONLY, &d); + if (r < 0) + return r; + + r = dissect_image(d->fd, NULL, 0, DISSECT_IMAGE_REQUIRE_ROOT, &m); + if (r < 0) + return r; + + r = dissected_image_acquire_metadata(m); + if (r < 0) + return r; + + free_and_replace(i->hostname, m->hostname); + i->machine_id = m->machine_id; + strv_free_and_replace(i->machine_info, m->machine_info); + strv_free_and_replace(i->os_release, m->os_release); + + break; + } + + default: + return -EOPNOTSUPP; + } + + i->metadata_valid = true; + + return 0; +} + +int image_name_lock(const char *name, int operation, LockFile *ret) { + assert(name); + assert(ret); + + /* Locks an image name, regardless of the precise path used. */ + + if (!image_name_is_valid(name)) + return -EINVAL; + + if (getenv_bool("SYSTEMD_NSPAWN_LOCK") == 0) { + *ret = (LockFile) LOCK_FILE_INIT; + return 0; + } + + if (streq(name, ".host")) + return -EBUSY; + + const char *p = strjoina("/run/systemd/nspawn/locks/name-", name); + (void) mkdir_p("/run/systemd/nspawn/locks", 0700); + return make_lock_file(p, operation, ret); +} + +bool image_name_is_valid(const char *s) { + if (!filename_is_valid(s)) + return false; + + if (string_has_cc(s, NULL)) + return false; + + if (!utf8_is_valid(s)) + return false; + + /* Temporary files for atomically creating new files */ + if (startswith(s, ".#")) + return false; + + return true; +} + +bool image_in_search_path(ImageClass class, const char *image) { + const char *path; + + assert(image); + + NULSTR_FOREACH(path, image_search_path[class]) { + const char *p; + size_t k; + + p = path_startswith(image, path); + if (!p) + continue; + + /* Make sure there's a filename following */ + k = strcspn(p, "/"); + if (k == 0) + continue; + + p += k; + + /* Accept trailing slashes */ + if (p[strspn(p, "/")] == 0) + return true; + + } + + return false; +} + +static const char* const image_type_table[_IMAGE_TYPE_MAX] = { + [IMAGE_DIRECTORY] = "directory", + [IMAGE_SUBVOLUME] = "subvolume", + [IMAGE_RAW] = "raw", + [IMAGE_BLOCK] = "block", +}; + +DEFINE_STRING_TABLE_LOOKUP(image_type, ImageType); diff --git a/src/shared/machine-image.h b/src/shared/machine-image.h new file mode 100644 index 00000000..9fd45899 --- /dev/null +++ b/src/shared/machine-image.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "sd-id128.h" + +#include "hashmap.h" +#include "lockfile-util.h" +#include "macro.h" +#include "path-util.h" +#include "string-util.h" +#include "time-util.h" + +typedef enum ImageClass { + IMAGE_MACHINE, + IMAGE_PORTABLE, + _IMAGE_CLASS_MAX, + _IMAGE_CLASS_INVALID = -1 +} ImageClass; + +typedef enum ImageType { + IMAGE_DIRECTORY, + IMAGE_SUBVOLUME, + IMAGE_RAW, + IMAGE_BLOCK, + _IMAGE_TYPE_MAX, + _IMAGE_TYPE_INVALID = -1 +} ImageType; + +typedef struct Image { + unsigned n_ref; + + ImageType type; + char *name; + char *path; + bool read_only; + + usec_t crtime; + usec_t mtime; + + uint64_t usage; + uint64_t usage_exclusive; + uint64_t limit; + uint64_t limit_exclusive; + + char *hostname; + sd_id128_t machine_id; + char **machine_info; + char **os_release; + + bool metadata_valid:1; + bool discoverable:1; /* true if we know for sure that image_find() would find the image given just the short name */ + + void *userdata; +} Image; + +Image *image_unref(Image *i); +Image *image_ref(Image *i); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Image*, image_unref); + +int image_find(ImageClass class, const char *name, Image **ret); +int image_from_path(const char *path, Image **ret); +int image_find_harder(ImageClass class, const char *name_or_path, Image **ret); +int image_discover(ImageClass class, Hashmap *map); + +int image_remove(Image *i); +int image_rename(Image *i, const char *new_name); +int image_clone(Image *i, const char *new_name, bool read_only); +int image_read_only(Image *i, bool b); + +const char* image_type_to_string(ImageType t) _const_; +ImageType image_type_from_string(const char *s) _pure_; + +bool image_name_is_valid(const char *s) _pure_; + +int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local); +int image_name_lock(const char *name, int operation, LockFile *ret); + +int image_set_limit(Image *i, uint64_t referenced_max); + +int image_read_metadata(Image *i); + +bool image_in_search_path(ImageClass class, const char *image); + +static inline bool IMAGE_IS_HIDDEN(const struct Image *i) { + assert(i); + + return i->name && i->name[0] == '.'; +} + +static inline bool IMAGE_IS_VENDOR(const struct Image *i) { + assert(i); + + return i->path && path_startswith(i->path, "/usr"); +} + +static inline bool IMAGE_IS_HOST(const struct Image *i) { + assert(i); + + if (i->name && streq(i->name, ".host")) + return true; + + if (i->path && path_equal(i->path, "/")) + return true; + + return false; +} + +extern const struct hash_ops image_hash_ops; diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c new file mode 100644 index 00000000..7e331283 --- /dev/null +++ b/src/shared/machine-pool.c @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "btrfs-util.h" +#include "label.h" +#include "machine-pool.h" +#include "missing_magic.h" +#include "stat-util.h" + +static int check_btrfs(void) { + struct statfs sfs; + + if (statfs("/var/lib/machines", &sfs) < 0) { + if (errno != ENOENT) + return -errno; + + if (statfs("/var/lib", &sfs) < 0) + return -errno; + } + + return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC); +} + +int setup_machine_directory(sd_bus_error *error) { + int r; + + r = check_btrfs(); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to determine whether /var/lib/machines is located on btrfs: %m"); + if (r == 0) + return 0; + + (void) btrfs_subvol_make_label("/var/lib/machines"); + + r = btrfs_quota_enable("/var/lib/machines", true); + if (r < 0) + log_warning_errno(r, "Failed to enable quota for /var/lib/machines, ignoring: %m"); + + r = btrfs_subvol_auto_qgroup("/var/lib/machines", 0, true); + if (r < 0) + log_warning_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines, ignoring: %m"); + + return 1; +} diff --git a/src/shared/machine-pool.h b/src/shared/machine-pool.h new file mode 100644 index 00000000..6f59a18f --- /dev/null +++ b/src/shared/machine-pool.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" + +int setup_machine_directory(sd_bus_error *error); diff --git a/src/shared/main-func.h b/src/shared/main-func.h new file mode 100644 index 00000000..6c26cb9f --- /dev/null +++ b/src/shared/main-func.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "pager.h" +#include "selinux-util.h" +#include "spawn-ask-password-agent.h" +#include "spawn-polkit-agent.h" +#include "static-destruct.h" +#include "util.h" + +#define _DEFINE_MAIN_FUNCTION(intro, impl, ret) \ + int main(int argc, char *argv[]) { \ + int r; \ + save_argc_argv(argc, argv); \ + intro; \ + r = impl; \ + ask_password_agent_close(); \ + polkit_agent_close(); \ + pager_close(); \ + mac_selinux_finish(); \ + static_destruct(); \ + return ret; \ + } + +/* Negative return values from impl are mapped to EXIT_FAILURE, and + * everything else means success! */ +#define DEFINE_MAIN_FUNCTION(impl) \ + _DEFINE_MAIN_FUNCTION(,impl(argc, argv), r < 0 ? EXIT_FAILURE : EXIT_SUCCESS) + +/* Zero is mapped to EXIT_SUCCESS, negative values are mapped to EXIT_FAILURE, + * and positive values are propagated. + * Note: "true" means failure! */ +#define DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(impl) \ + _DEFINE_MAIN_FUNCTION(,impl(argc, argv), r < 0 ? EXIT_FAILURE : r) diff --git a/src/shared/meson.build b/src/shared/meson.build new file mode 100644 index 00000000..063d1577 --- /dev/null +++ b/src/shared/meson.build @@ -0,0 +1,308 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +shared_sources = files(''' + acl-util.h + acpi-fpdt.c + acpi-fpdt.h + apparmor-util.c + apparmor-util.h + ask-password-api.c + ask-password-api.h + barrier.c + barrier.h + base-filesystem.c + base-filesystem.h + bitmap.c + bitmap.h + blkid-util.h + boot-timestamps.c + boot-timestamps.h + bootspec.c + bootspec.h + bpf-program.c + bpf-program.h + bus-unit-procs.c + bus-unit-procs.h + bus-unit-util.c + bus-unit-util.h + bus-util.c + bus-util.h + bus-polkit.c + bus-polkit.h + bus-wait-for-jobs.c + bus-wait-for-jobs.h + bus-wait-for-units.c + bus-wait-for-units.h + calendarspec.c + calendarspec.h + cgroup-setup.c + cgroup-setup.h + cgroup-show.c + cgroup-show.h + clean-ipc.c + clean-ipc.h + clock-util.c + clock-util.h + condition.c + condition.h + conf-parser.c + conf-parser.h + cpu-set-util.c + cpu-set-util.h + crypt-util.c + crypt-util.h + daemon-util.h + dev-setup.c + dev-setup.h + dissect-image.c + dissect-image.h + dm-util.c + dm-util.h + dns-domain.c + dns-domain.h + dropin.c + dropin.h + efi-loader.c + efi-loader.h + enable-mempool.c + env-file-label.c + env-file-label.h + ethtool-util.c + ethtool-util.h + exec-util.c + exec-util.h + exit-status.c + exit-status.h + fdset.c + fdset.h + fileio-label.c + fileio-label.h + firewall-util.h + format-table.c + format-table.h + fsck-util.h + fstab-util.c + fstab-util.h + generator.c + generator.h + gpt.h + id128-print.c + id128-print.h + ima-util.c + ima-util.h + import-util.c + import-util.h + initreq.h + install-printf.c + install-printf.h + install.c + install.h + ip-protocol-list.c + ip-protocol-list.h + journal-importer.c + journal-importer.h + journal-util.c + journal-util.h + json-internal.h + json.c + json.h + libmount-util.h + linux/auto_dev-ioctl.h + linux/bpf.h + linux/bpf_common.h + linux/bpf_insn.h + linux/dm-ioctl.h + linux/ethtool.h + local-addresses.c + local-addresses.h + lockfile-util.c + lockfile-util.h + log-link.h + logs-show.c + logs-show.h + loop-util.c + loop-util.h + machine-image.c + machine-image.h + machine-pool.c + machine-pool.h + main-func.h + module-util.h + mount-util.c + mount-util.h + nscd-flush.c + nscd-flush.h + nsflags.c + nsflags.h + os-util.c + os-util.h + output-mode.c + output-mode.h + pager.c + pager.h + path-lookup.c + path-lookup.h + pe-header.h + pretty-print.c + pretty-print.h + ptyfwd.c + ptyfwd.h + reboot-util.c + reboot-util.h + resolve-util.c + resolve-util.h + seccomp-util.h + securebits-util.c + securebits-util.h + serialize.c + serialize.h + sleep-config.c + sleep-config.h + spawn-ask-password-agent.c + spawn-ask-password-agent.h + spawn-polkit-agent.c + spawn-polkit-agent.h + specifier.c + specifier.h + switch-root.c + switch-root.h + sysctl-util.c + sysctl-util.h + tmpfile-util-label.c + tmpfile-util-label.h + tomoyo-util.c + tomoyo-util.h + udev-util.c + udev-util.h + uid-range.c + uid-range.h + unit-file.c + unit-file.h + utmp-wtmp.h + varlink.c + varlink.h + verbs.c + verbs.h + vlan-util.c + vlan-util.h + volatile-util.c + volatile-util.h + watchdog.c + watchdog.h + web-util.c + web-util.h + wifi-util.c + wifi-util.h + xml.c + xml.h +'''.split()) + +if get_option('tests') != 'false' + shared_sources += files('tests.c', 'tests.h') +endif + +test_tables_h = files('test-tables.h') +shared_sources += test_tables_h + +if conf.get('HAVE_ACL') == 1 + shared_sources += files('acl-util.c') +endif + +if conf.get('ENABLE_UTMP') == 1 + shared_sources += files('utmp-wtmp.c') +endif + +if conf.get('HAVE_SECCOMP') == 1 + shared_sources += files('seccomp-util.c') +endif + +if conf.get('HAVE_LIBIPTC') == 1 + shared_sources += files('firewall-util.c') +endif + +if conf.get('HAVE_KMOD') == 1 + shared_sources += files('module-util.c') +endif + +generate_ip_protocol_list = find_program('generate-ip-protocol-list.sh') +ip_protocol_list_txt = custom_target( + 'ip-protocol-list.txt', + output : 'ip-protocol-list.txt', + command : [generate_ip_protocol_list, cpp], + capture : true) + +fname = 'ip-protocol-from-name.gperf' +gperf_file = custom_target( + fname, + input : ip_protocol_list_txt, + output : fname, + command : [generate_gperfs, 'ip_protocol', 'IPPROTO_', '@INPUT@'], + capture : true) + +fname = 'ip-protocol-from-name.h' +target1 = custom_target( + fname, + input : gperf_file, + output : fname, + command : [gperf, + '-L', 'ANSI-C', '-t', '--ignore-case', + '-N', 'lookup_ip_protocol', + '-H', 'hash_ip_protocol_name', + '-p', '-C', + '@INPUT@'], + capture : true) + +fname = 'ip-protocol-to-name.h' +awkscript = 'ip-protocol-to-name.awk' +target2 = custom_target( + fname, + input : [awkscript, ip_protocol_list_txt], + output : fname, + command : [awk, '-f', '@INPUT0@', '@INPUT1@'], + capture : true) + +shared_generated_gperf_headers = [target1, target2] +shared_sources += shared_generated_gperf_headers + +libshared_name = 'systemd-shared-@0@'.format(meson.project_version()) + +libshared_deps = [threads, + libacl, + libblkid, + libcap, + libcryptsetup, + libgcrypt, + libidn, + libiptc, + libkmod, + liblz4, + libmount, + librt, + libseccomp, + libselinux, + libxz] + +libshared_sym_path = '@0@/libshared.sym'.format(meson.current_source_dir()) + +libshared_static = static_library( + libshared_name, + shared_sources, + include_directories : includes, + dependencies : libshared_deps, + c_args : ['-fvisibility=default']) + +libshared = shared_library( + libshared_name, + libudev_sources, + include_directories : includes, + link_args : ['-shared', + '-Wl,--version-script=' + libshared_sym_path], + link_whole : [libshared_static, + libbasic, + libbasic_gcrypt, + libsystemd_static, + libjournal_client], + c_args : ['-fvisibility=default'], + dependencies : libshared_deps, + install : true, + install_dir : rootlibexecdir) diff --git a/src/shared/module-util.c b/src/shared/module-util.c new file mode 100644 index 00000000..75c8ba2b --- /dev/null +++ b/src/shared/module-util.c @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "module-util.h" + +int module_load_and_warn(struct kmod_ctx *ctx, const char *module, bool verbose) { + const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST; + struct kmod_list *itr; + _cleanup_(kmod_module_unref_listp) struct kmod_list *modlist = NULL; + int r = 0; + + /* verbose==true means we should log at non-debug level if we + * fail to find or load the module. */ + + log_debug("Loading module: %s", module); + + r = kmod_module_new_from_lookup(ctx, module, &modlist); + if (r < 0) + return log_full_errno(verbose ? LOG_ERR : LOG_DEBUG, r, + "Failed to lookup module alias '%s': %m", module); + + if (!modlist) { + log_full_errno(verbose ? LOG_ERR : LOG_DEBUG, r, + "Failed to find module '%s'", module); + return -ENOENT; + } + + kmod_list_foreach(itr, modlist) { + _cleanup_(kmod_module_unrefp) struct kmod_module *mod = NULL; + int state, err; + + mod = kmod_module_get_module(itr); + state = kmod_module_get_initstate(mod); + + switch (state) { + case KMOD_MODULE_BUILTIN: + log_full(verbose ? LOG_INFO : LOG_DEBUG, + "Module '%s' is built in", kmod_module_get_name(mod)); + break; + + case KMOD_MODULE_LIVE: + log_debug("Module '%s' is already loaded", kmod_module_get_name(mod)); + break; + + default: + err = kmod_module_probe_insert_module(mod, probe_flags, + NULL, NULL, NULL, NULL); + if (err == 0) + log_full(verbose ? LOG_INFO : LOG_DEBUG, + "Inserted module '%s'", kmod_module_get_name(mod)); + else if (err == KMOD_PROBE_APPLY_BLACKLIST) + log_full(verbose ? LOG_INFO : LOG_DEBUG, + "Module '%s' is blacklisted", kmod_module_get_name(mod)); + else { + assert(err < 0); + + log_full_errno(!verbose ? LOG_DEBUG : + err == -ENODEV ? LOG_NOTICE : + err == -ENOENT ? LOG_WARNING : + LOG_ERR, + err, + "Failed to insert module '%s': %m", + kmod_module_get_name(mod)); + if (!IN_SET(err, -ENODEV, -ENOENT)) + r = err; + } + } + } + + return r; +} diff --git a/src/shared/module-util.h b/src/shared/module-util.h new file mode 100644 index 00000000..c386c5b4 --- /dev/null +++ b/src/shared/module-util.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_ctx*, kmod_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_module*, kmod_module_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(struct kmod_list*, kmod_module_unref_list); + +int module_load_and_warn(struct kmod_ctx *ctx, const char *module, bool verbose); diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c new file mode 100644 index 00000000..d316e81a --- /dev/null +++ b/src/shared/mount-util.c @@ -0,0 +1,559 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "extract-word.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hashmap.h" +#include "libmount-util.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "set.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" + +int umount_recursive(const char *prefix, int flags) { + int n = 0, r; + bool again; + + /* Try to umount everything recursively below a + * directory. Also, take care of stacked mounts, and keep + * unmounting them until they are gone. */ + + do { + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; + + again = false; + + r = libmount_parse("/proc/self/mountinfo", NULL, &table, &iter); + if (r < 0) + return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m"); + + for (;;) { + struct libmnt_fs *fs; + const char *path; + + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) + break; + if (r < 0) + return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m"); + + path = mnt_fs_get_target(fs); + if (!path) + continue; + + if (!path_startswith(path, prefix)) + continue; + + if (umount2(path, flags) < 0) { + r = log_debug_errno(errno, "Failed to umount %s: %m", path); + continue; + } + + log_debug("Successfully unmounted %s", path); + + again = true; + n++; + + break; + } + + } while (again); + + return n; +} + +/* Get the mount flags for the mountpoint at "path" from "table" */ +static int get_mount_flags(const char *path, unsigned long *flags, struct libmnt_table *table) { + struct statvfs buf = {}; + struct libmnt_fs *fs = NULL; + const char *opts = NULL; + int r = 0; + + fs = mnt_table_find_target(table, path, MNT_ITER_FORWARD); + if (!fs) { + log_warning("Could not find '%s' in mount table", path); + goto fallback; + } + + opts = mnt_fs_get_vfs_options(fs); + r = mnt_optstr_get_flags(opts, flags, mnt_get_builtin_optmap(MNT_LINUX_MAP)); + if (r != 0) { + log_warning_errno(r, "Could not get flags for '%s': %m", path); + goto fallback; + } + + /* relatime is default and trying to set it in an unprivileged container causes EPERM */ + *flags &= ~MS_RELATIME; + return 0; + +fallback: + if (statvfs(path, &buf) < 0) + return -errno; + + *flags = buf.f_flag; + return 0; +} + +/* Use this function only if you do not have direct access to /proc/self/mountinfo but the caller can open it + * for you. This is the case when /proc is masked or not mounted. Otherwise, use bind_remount_recursive. */ +int bind_remount_recursive_with_mountinfo( + const char *prefix, + unsigned long new_flags, + unsigned long flags_mask, + char **blacklist, + FILE *proc_self_mountinfo) { + + _cleanup_set_free_free_ Set *done = NULL; + _cleanup_free_ char *cleaned = NULL; + int r; + + assert(proc_self_mountinfo); + + /* Recursively remount a directory (and all its submounts) read-only or read-write. If the directory is already + * mounted, we reuse the mount and simply mark it MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write + * operation). If it isn't we first make it one. Afterwards we apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to + * all submounts we can access, too. When mounts are stacked on the same mount point we only care for each + * individual "top-level" mount on each point, as we cannot influence/access the underlying mounts anyway. We + * do not have any effect on future submounts that might get propagated, they migt be writable. This includes + * future submounts that have been triggered via autofs. + * + * If the "blacklist" parameter is specified it may contain a list of subtrees to exclude from the + * remount operation. Note that we'll ignore the blacklist for the top-level path. */ + + cleaned = strdup(prefix); + if (!cleaned) + return -ENOMEM; + + path_simplify(cleaned, false); + + done = set_new(&path_hash_ops); + if (!done) + return -ENOMEM; + + for (;;) { + _cleanup_set_free_free_ Set *todo = NULL; + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; + bool top_autofs = false; + char *x; + unsigned long orig_flags; + + todo = set_new(&path_hash_ops); + if (!todo) + return -ENOMEM; + + rewind(proc_self_mountinfo); + + r = libmount_parse("/proc/self/mountinfo", proc_self_mountinfo, &table, &iter); + if (r < 0) + return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m"); + + for (;;) { + struct libmnt_fs *fs; + const char *path, *type; + + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) + break; + if (r < 0) + return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m"); + + path = mnt_fs_get_target(fs); + type = mnt_fs_get_fstype(fs); + if (!path || !type) + continue; + + if (!path_startswith(path, cleaned)) + continue; + + /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount + * we shall operate on. */ + if (!path_equal(path, cleaned)) { + bool blacklisted = false; + char **i; + + STRV_FOREACH(i, blacklist) { + if (path_equal(*i, cleaned)) + continue; + + if (!path_startswith(*i, cleaned)) + continue; + + if (path_startswith(path, *i)) { + blacklisted = true; + log_debug("Not remounting %s blacklisted by %s, called for %s", + path, *i, cleaned); + break; + } + } + if (blacklisted) + continue; + } + + /* Let's ignore autofs mounts. If they aren't + * triggered yet, we want to avoid triggering + * them, as we don't make any guarantees for + * future submounts anyway. If they are + * already triggered, then we will find + * another entry for this. */ + if (streq(type, "autofs")) { + top_autofs = top_autofs || path_equal(path, cleaned); + continue; + } + + if (!set_contains(done, path)) { + r = set_put_strdup(todo, path); + if (r < 0) + return r; + } + } + + /* If we have no submounts to process anymore and if + * the root is either already done, or an autofs, we + * are done */ + if (set_isempty(todo) && + (top_autofs || set_contains(done, cleaned))) + return 0; + + if (!set_contains(done, cleaned) && + !set_contains(todo, cleaned)) { + /* The prefix directory itself is not yet a mount, make it one. */ + if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0) + return -errno; + + orig_flags = 0; + (void) get_mount_flags(cleaned, &orig_flags, table); + orig_flags &= ~MS_RDONLY; + + if (mount(NULL, cleaned, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL) < 0) + return -errno; + + log_debug("Made top-level directory %s a mount point.", prefix); + + r = set_put_strdup(done, cleaned); + if (r < 0) + return r; + } + + while ((x = set_steal_first(todo))) { + + r = set_consume(done, x); + if (IN_SET(r, 0, -EEXIST)) + continue; + if (r < 0) + return r; + + /* Deal with mount points that are obstructed by a later mount */ + r = path_is_mount_point(x, NULL, 0); + if (IN_SET(r, 0, -ENOENT)) + continue; + if (IN_SET(r, -EACCES, -EPERM)) { + /* Even if root user invoke this, submounts under private FUSE or NFS mount points + * may not be acceessed. E.g., + * + * $ bindfs --no-allow-other ~/mnt/mnt ~/mnt/mnt + * $ bindfs --no-allow-other ~/mnt ~/mnt + * + * Then, root user cannot access the mount point ~/mnt/mnt. + * In such cases, the submounts are ignored, as we have no way to manage them. */ + log_debug_errno(r, "Failed to determine '%s' is mount point or not, ignoring: %m", x); + continue; + } + if (r < 0) + return r; + + /* Try to reuse the original flag set */ + orig_flags = 0; + (void) get_mount_flags(x, &orig_flags, table); + orig_flags &= ~MS_RDONLY; + + if (mount(NULL, x, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL) < 0) + return -errno; + + log_debug("Remounted %s read-only.", x); + } + } +} + +int bind_remount_recursive(const char *prefix, unsigned long new_flags, unsigned long flags_mask, char **blacklist) { + _cleanup_fclose_ FILE *proc_self_mountinfo = NULL; + int r; + + r = fopen_unlocked("/proc/self/mountinfo", "re", &proc_self_mountinfo); + if (r < 0) + return r; + + return bind_remount_recursive_with_mountinfo(prefix, new_flags, flags_mask, blacklist, proc_self_mountinfo); +} + +int mount_move_root(const char *path) { + assert(path); + + if (chdir(path) < 0) + return -errno; + + if (mount(path, "/", NULL, MS_MOVE, NULL) < 0) + return -errno; + + if (chroot(".") < 0) + return -errno; + + if (chdir("/") < 0) + return -errno; + + return 0; +} + +int repeat_unmount(const char *path, int flags) { + bool done = false; + + assert(path); + + /* If there are multiple mounts on a mount point, this + * removes them all */ + + for (;;) { + if (umount2(path, flags) < 0) { + + if (errno == EINVAL) + return done; + + return -errno; + } + + done = true; + } +} + +const char* mode_to_inaccessible_node(mode_t mode) { + /* This function maps a node type to a corresponding inaccessible file node. These nodes are created during + * early boot by PID 1. In some cases we lacked the privs to create the character and block devices (maybe + * because we run in an userns environment, or miss CAP_SYS_MKNOD, or run with a devices policy that excludes + * device nodes with major and minor of 0), but that's fine, in that case we use an AF_UNIX file node instead, + * which is not the same, but close enough for most uses. And most importantly, the kernel allows bind mounts + * from socket nodes to any non-directory file nodes, and that's the most important thing that matters. */ + + switch(mode & S_IFMT) { + case S_IFREG: + return "/run/systemd/inaccessible/reg"; + + case S_IFDIR: + return "/run/systemd/inaccessible/dir"; + + case S_IFCHR: + if (access("/run/systemd/inaccessible/chr", F_OK) == 0) + return "/run/systemd/inaccessible/chr"; + return "/run/systemd/inaccessible/sock"; + + case S_IFBLK: + if (access("/run/systemd/inaccessible/blk", F_OK) == 0) + return "/run/systemd/inaccessible/blk"; + return "/run/systemd/inaccessible/sock"; + + case S_IFIFO: + return "/run/systemd/inaccessible/fifo"; + + case S_IFSOCK: + return "/run/systemd/inaccessible/sock"; + } + return NULL; +} + +#define FLAG(name) (flags & name ? STRINGIFY(name) "|" : "") +static char* mount_flags_to_string(long unsigned flags) { + char *x; + _cleanup_free_ char *y = NULL; + long unsigned overflow; + + overflow = flags & ~(MS_RDONLY | + MS_NOSUID | + MS_NODEV | + MS_NOEXEC | + MS_SYNCHRONOUS | + MS_REMOUNT | + MS_MANDLOCK | + MS_DIRSYNC | + MS_NOATIME | + MS_NODIRATIME | + MS_BIND | + MS_MOVE | + MS_REC | + MS_SILENT | + MS_POSIXACL | + MS_UNBINDABLE | + MS_PRIVATE | + MS_SLAVE | + MS_SHARED | + MS_RELATIME | + MS_KERNMOUNT | + MS_I_VERSION | + MS_STRICTATIME | + MS_LAZYTIME); + + if (flags == 0 || overflow != 0) + if (asprintf(&y, "%lx", overflow) < 0) + return NULL; + + x = strjoin(FLAG(MS_RDONLY), + FLAG(MS_NOSUID), + FLAG(MS_NODEV), + FLAG(MS_NOEXEC), + FLAG(MS_SYNCHRONOUS), + FLAG(MS_REMOUNT), + FLAG(MS_MANDLOCK), + FLAG(MS_DIRSYNC), + FLAG(MS_NOATIME), + FLAG(MS_NODIRATIME), + FLAG(MS_BIND), + FLAG(MS_MOVE), + FLAG(MS_REC), + FLAG(MS_SILENT), + FLAG(MS_POSIXACL), + FLAG(MS_UNBINDABLE), + FLAG(MS_PRIVATE), + FLAG(MS_SLAVE), + FLAG(MS_SHARED), + FLAG(MS_RELATIME), + FLAG(MS_KERNMOUNT), + FLAG(MS_I_VERSION), + FLAG(MS_STRICTATIME), + FLAG(MS_LAZYTIME), + y); + if (!x) + return NULL; + if (!y) + x[strlen(x) - 1] = '\0'; /* truncate the last | */ + return x; +} + +int mount_verbose( + int error_log_level, + const char *what, + const char *where, + const char *type, + unsigned long flags, + const char *options) { + + _cleanup_free_ char *fl = NULL, *o = NULL; + unsigned long f; + int r; + + r = mount_option_mangle(options, flags, &f, &o); + if (r < 0) + return log_full_errno(error_log_level, r, + "Failed to mangle mount options %s: %m", + strempty(options)); + + fl = mount_flags_to_string(f); + + if ((f & MS_REMOUNT) && !what && !type) + log_debug("Remounting %s (%s \"%s\")...", + where, strnull(fl), strempty(o)); + else if (!what && !type) + log_debug("Mounting %s (%s \"%s\")...", + where, strnull(fl), strempty(o)); + else if ((f & MS_BIND) && !type) + log_debug("Bind-mounting %s on %s (%s \"%s\")...", + what, where, strnull(fl), strempty(o)); + else if (f & MS_MOVE) + log_debug("Moving mount %s → %s (%s \"%s\")...", + what, where, strnull(fl), strempty(o)); + else + log_debug("Mounting %s on %s (%s \"%s\")...", + strna(type), where, strnull(fl), strempty(o)); + if (mount(what, where, type, f, o) < 0) + return log_full_errno(error_log_level, errno, + "Failed to mount %s (type %s) on %s (%s \"%s\"): %m", + strna(what), strna(type), where, strnull(fl), strempty(o)); + return 0; +} + +int umount_verbose(const char *what) { + log_debug("Umounting %s...", what); + if (umount(what) < 0) + return log_error_errno(errno, "Failed to unmount %s: %m", what); + return 0; +} + +int mount_option_mangle( + const char *options, + unsigned long mount_flags, + unsigned long *ret_mount_flags, + char **ret_remaining_options) { + + const struct libmnt_optmap *map; + _cleanup_free_ char *ret = NULL; + const char *p; + int r; + + /* This extracts mount flags from the mount options, and store + * non-mount-flag options to '*ret_remaining_options'. + * E.g., + * "rw,nosuid,nodev,relatime,size=1630748k,mode=700,uid=1000,gid=1000" + * is split to MS_NOSUID|MS_NODEV|MS_RELATIME and + * "size=1630748k,mode=700,uid=1000,gid=1000". + * See more examples in test-mount-utils.c. + * + * Note that if 'options' does not contain any non-mount-flag options, + * then '*ret_remaining_options' is set to NULL instead of empty string. + * Note that this does not check validity of options stored in + * '*ret_remaining_options'. + * Note that if 'options' is NULL, then this just copies 'mount_flags' + * to '*ret_mount_flags'. */ + + assert(ret_mount_flags); + assert(ret_remaining_options); + + map = mnt_get_builtin_optmap(MNT_LINUX_MAP); + if (!map) + return -EINVAL; + + p = options; + for (;;) { + _cleanup_free_ char *word = NULL; + const struct libmnt_optmap *ent; + + r = extract_first_word(&p, &word, ",", EXTRACT_UNQUOTE); + if (r < 0) + return r; + if (r == 0) + break; + + for (ent = map; ent->name; ent++) { + /* All entries in MNT_LINUX_MAP do not take any argument. + * Thus, ent->name does not contain "=" or "[=]". */ + if (!streq(word, ent->name)) + continue; + + if (!(ent->mask & MNT_INVERT)) + mount_flags |= ent->id; + else if (mount_flags & ent->id) + mount_flags ^= ent->id; + + break; + } + + /* If 'word' is not a mount flag, then store it in '*ret_remaining_options'. */ + if (!ent->name && !strextend_with_separator(&ret, ",", word, NULL)) + return -ENOMEM; + } + + *ret_mount_flags = mount_flags; + *ret_remaining_options = TAKE_PTR(ret); + + return 0; +} diff --git a/src/shared/mount-util.h b/src/shared/mount-util.h new file mode 100644 index 00000000..8649fca3 --- /dev/null +++ b/src/shared/mount-util.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "macro.h" + +int repeat_unmount(const char *path, int flags); +int umount_recursive(const char *target, int flags); +int bind_remount_recursive(const char *prefix, unsigned long new_flags, unsigned long flags_mask, char **blacklist); +int bind_remount_recursive_with_mountinfo(const char *prefix, unsigned long new_flags, unsigned long flags_mask, char **blacklist, FILE *proc_self_mountinfo); + +int mount_move_root(const char *path); + +DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent); +#define _cleanup_endmntent_ _cleanup_(endmntentp) + +int mount_verbose( + int error_log_level, + const char *what, + const char *where, + const char *type, + unsigned long flags, + const char *options); +int umount_verbose(const char *where); + +int mount_option_mangle( + const char *options, + unsigned long mount_flags, + unsigned long *ret_mount_flags, + char **ret_remaining_options); + +const char* mode_to_inaccessible_node(mode_t mode); diff --git a/src/shared/nscd-flush.c b/src/shared/nscd-flush.c new file mode 100644 index 00000000..33a06a01 --- /dev/null +++ b/src/shared/nscd-flush.c @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#include + +#include "fd-util.h" +#include "io-util.h" +#include "nscd-flush.h" +#include "socket-util.h" +#include "strv.h" +#include "time-util.h" + +#define NSCD_FLUSH_CACHE_TIMEOUT_USEC (5*USEC_PER_SEC) + +struct nscdInvalidateRequest { + int32_t version; + int32_t type; /* in glibc this is an enum. We don't replicate this here 1:1. Also, wtf, how unportable is that + * even? */ + int32_t key_len; + char dbname[]; +}; + +static const union sockaddr_union nscd_sa = { + .un.sun_family = AF_UNIX, + .un.sun_path = "/run/nscd/socket", +}; + +static int nscd_flush_cache_one(const char *database, usec_t end) { + size_t req_size, has_written = 0, has_read = 0, l; + struct nscdInvalidateRequest *req; + _cleanup_close_ int fd = -1; + int32_t resp; + int events; + + assert(database); + + l = strlen(database); + req_size = offsetof(struct nscdInvalidateRequest, dbname) + l + 1; + + req = alloca(req_size); + *req = (struct nscdInvalidateRequest) { + .version = 2, + .type = 10, + .key_len = l + 1, + }; + + strcpy(req->dbname, database); + + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return log_debug_errno(errno, "Failed to allocate nscd socket: %m"); + + /* Note: connect() returns EINPROGRESS if O_NONBLOCK is set and establishing a connection takes time. The + * kernel lets us know this way that the connection is now being established, and we should watch with poll() + * to learn when it is fully established. That said, AF_UNIX on Linux never triggers this IRL (connect() is + * always instant on AF_UNIX), hence handling this is mostly just an exercise in defensive, protocol-agnostic + * programming. + * + * connect() returns EAGAIN if the socket's backlog limit has been reached. When we see this we give up right + * away, after all this entire function here is written in a defensive style so that a non-responding nscd + * doesn't stall us for good. (Even if we wanted to handle this better: the Linux kernel doesn't really have a + * nice way to connect() to a server synchronously with a time limit that would also cover dealing with the + * backlog limit. After all SO_RCVTIMEO and SR_SNDTIMEO don't apply to connect(), and alarm() is frickin' ugly + * and not really reasonably usable from threads-aware code.) */ + if (connect(fd, &nscd_sa.sa, SOCKADDR_UN_LEN(nscd_sa.un)) < 0) { + if (errno == EAGAIN) + return log_debug_errno(errno, "nscd is overloaded (backlog limit reached) and refuses to take further connections: %m"); + if (errno != EINPROGRESS) + return log_debug_errno(errno, "Failed to connect to nscd socket: %m"); + + /* Continue in case of EINPROGRESS, but don't bother with send() or recv() until being notified that + * establishing the connection is complete. */ + events = 0; + } else + events = POLLIN|POLLOUT; /* Let's assume initially that we can write and read to the fd, to suppress + * one poll() invocation */ + for (;;) { + usec_t p; + + if (events & POLLOUT) { + ssize_t m; + + assert(has_written < req_size); + + m = send(fd, (uint8_t*) req + has_written, req_size - has_written, MSG_NOSIGNAL); + if (m < 0) { + if (errno != EAGAIN) /* Note that EAGAIN is returned by the kernel whenever it can't + * take the data right now, and that includes if the connect() is + * asynchronous and we saw EINPROGRESS on it, and it hasn't + * completed yet. */ + return log_debug_errno(errno, "Failed to write to nscd socket: %m"); + } else + has_written += m; + } + + if (events & (POLLIN|POLLERR|POLLHUP)) { + ssize_t m; + + if (has_read >= sizeof(resp)) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Response from nscd longer than expected: %m"); + + m = recv(fd, (uint8_t*) &resp + has_read, sizeof(resp) - has_read, 0); + if (m < 0) { + if (errno != EAGAIN) + return log_debug_errno(errno, "Failed to read from nscd socket: %m"); + } else if (m == 0) { /* EOF */ + if (has_read == 0 && has_written >= req_size) /* Older nscd immediately terminated the + * connection, accept that as OK */ + return 1; + + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "nscd prematurely ended connection."); + } else + has_read += m; + } + + if (has_written >= req_size && has_read >= sizeof(resp)) { /* done? */ + if (resp < 0) + return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "nscd sent us a negative error number: %i", resp); + if (resp > 0) + return log_debug_errno(resp, "nscd return failure code on invalidating '%s'.", database); + return 1; + } + + p = now(CLOCK_MONOTONIC); + if (p >= end) + return -ETIMEDOUT; + + events = fd_wait_for_event(fd, POLLIN | (has_written < req_size ? POLLOUT : 0), end - p); + if (events < 0) + return events; + } +} + +int nscd_flush_cache(char **databases) { + usec_t end; + int r = 0; + char **i; + + /* Tries to invalidate the specified database in nscd. We do this carefully, with a 5s time-out, so that we + * don't block indefinitely on another service. */ + + end = usec_add(now(CLOCK_MONOTONIC), NSCD_FLUSH_CACHE_TIMEOUT_USEC); + + STRV_FOREACH(i, databases) { + int k; + + k = nscd_flush_cache_one(*i, end); + if (k < 0 && r >= 0) + r = k; + } + + return r; +} diff --git a/src/shared/nscd-flush.h b/src/shared/nscd-flush.h new file mode 100644 index 00000000..22774bf4 --- /dev/null +++ b/src/shared/nscd-flush.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int nscd_flush_cache(char **databases); diff --git a/src/shared/nsflags.c b/src/shared/nsflags.c new file mode 100644 index 00000000..8cc2d087 --- /dev/null +++ b/src/shared/nsflags.c @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "extract-word.h" +#include "nsflags.h" +#include "string-util.h" + +const struct namespace_flag_map namespace_flag_map[] = { + { CLONE_NEWCGROUP, "cgroup" }, + { CLONE_NEWIPC, "ipc" }, + { CLONE_NEWNET, "net" }, + /* So, the mount namespace flag is called CLONE_NEWNS for historical reasons. Let's expose it here under a more + * explanatory name: "mnt". This is in-line with how the kernel exposes namespaces in /proc/$PID/ns. */ + { CLONE_NEWNS, "mnt" }, + { CLONE_NEWPID, "pid" }, + { CLONE_NEWUSER, "user" }, + { CLONE_NEWUTS, "uts" }, + {} +}; + +int namespace_flags_from_string(const char *name, unsigned long *ret) { + unsigned long flags = 0; + int r; + + assert_se(ret); + + for (;;) { + _cleanup_free_ char *word = NULL; + unsigned long f = 0; + unsigned i; + + r = extract_first_word(&name, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + for (i = 0; namespace_flag_map[i].name; i++) + if (streq(word, namespace_flag_map[i].name)) { + f = namespace_flag_map[i].flag; + break; + } + + if (f == 0) + return -EINVAL; + + flags |= f; + } + + *ret = flags; + return 0; +} + +int namespace_flags_to_string(unsigned long flags, char **ret) { + _cleanup_free_ char *s = NULL; + unsigned i; + + for (i = 0; namespace_flag_map[i].name; i++) { + if ((flags & namespace_flag_map[i].flag) != namespace_flag_map[i].flag) + continue; + + if (!strextend_with_separator(&s, " ", namespace_flag_map[i].name, NULL)) + return -ENOMEM; + } + + if (!s) { + s = strdup(""); + if (!s) + return -ENOMEM; + } + + *ret = TAKE_PTR(s); + + return 0; +} diff --git a/src/shared/nsflags.h b/src/shared/nsflags.h new file mode 100644 index 00000000..0aeb0bc8 --- /dev/null +++ b/src/shared/nsflags.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "missing_sched.h" + +/* The combination of all namespace flags defined by the kernel. The right type for this isn't clear. setns() and + * unshare() expect these flags to be passed as (signed) "int", while clone() wants them as "unsigned long". The latter + * is definitely more appropriate for a flags parameter, and also the larger type of the two, hence let's stick to that + * here. */ +#define NAMESPACE_FLAGS_ALL \ + ((unsigned long) (CLONE_NEWCGROUP| \ + CLONE_NEWIPC| \ + CLONE_NEWNET| \ + CLONE_NEWNS| \ + CLONE_NEWPID| \ + CLONE_NEWUSER| \ + CLONE_NEWUTS)) + +#define NAMESPACE_FLAGS_INITIAL ((unsigned long) -1) + +int namespace_flags_from_string(const char *name, unsigned long *ret); +int namespace_flags_to_string(unsigned long flags, char **ret); + +struct namespace_flag_map { + unsigned long flag; + const char *name; +}; + +extern const struct namespace_flag_map namespace_flag_map[]; diff --git a/src/shared/os-util.c b/src/shared/os-util.c new file mode 100644 index 00000000..b2af8535 --- /dev/null +++ b/src/shared/os-util.c @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "env-file.h" +#include "fd-util.h" +#include "fs-util.h" +#include "macro.h" +#include "os-util.h" +#include "string-util.h" +#include "strv.h" + +int path_is_os_tree(const char *path) { + int r; + + assert(path); + + /* Does the path exist at all? If not, generate an error immediately. This is useful so that a missing root dir + * always results in -ENOENT, and we can properly distinguish the case where the whole root doesn't exist from + * the case where just the os-release file is missing. */ + if (laccess(path, F_OK) < 0) + return -errno; + + /* We use {/etc|/usr/lib}/os-release as flag file if something is an OS */ + r = open_os_release(path, NULL, NULL); + if (r == -ENOENT) /* We got nothing */ + return 0; + if (r < 0) + return r; + + return 1; +} + +int open_os_release(const char *root, char **ret_path, int *ret_fd) { + _cleanup_free_ char *q = NULL; + const char *p; + int r, fd; + + FOREACH_STRING(p, "/etc/os-release", "/usr/lib/os-release") { + r = chase_symlinks(p, root, CHASE_PREFIX_ROOT, + ret_path ? &q : NULL, + ret_fd ? &fd : NULL); + if (r != -ENOENT) + break; + } + if (r < 0) + return r; + + if (ret_fd) { + int real_fd; + + /* Convert the O_PATH fd into a proper, readable one */ + real_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY); + safe_close(fd); + if (real_fd < 0) + return real_fd; + + *ret_fd = real_fd; + } + + if (ret_path) + *ret_path = TAKE_PTR(q); + + return 0; +} + +int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) { + _cleanup_free_ char *p = NULL; + _cleanup_close_ int fd = -1; + FILE *f; + int r; + + if (!ret_file) + return open_os_release(root, ret_path, NULL); + + r = open_os_release(root, ret_path ? &p : NULL, &fd); + if (r < 0) + return r; + + f = fdopen(fd, "r"); + if (!f) + return -errno; + fd = -1; + + *ret_file = f; + + if (ret_path) + *ret_path = TAKE_PTR(p); + + return 0; +} + +int parse_os_release(const char *root, ...) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *p = NULL; + va_list ap; + int r; + + r = fopen_os_release(root, &p, &f); + if (r < 0) + return r; + + va_start(ap, root); + r = parse_env_filev(f, p, ap); + va_end(ap); + + return r; +} + +int load_os_release_pairs(const char *root, char ***ret) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *p = NULL; + int r; + + r = fopen_os_release(root, &p, &f); + if (r < 0) + return r; + + return load_env_file_pairs(f, p, ret); +} diff --git a/src/shared/os-util.h b/src/shared/os-util.h new file mode 100644 index 00000000..27ec7ac8 --- /dev/null +++ b/src/shared/os-util.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int path_is_os_tree(const char *path); + +int open_os_release(const char *root, char **ret_path, int *ret_fd); +int fopen_os_release(const char *root, char **ret_path, FILE **ret_file); + +int parse_os_release(const char *root, ...) _sentinel_; +int load_os_release_pairs(const char *root, char ***ret); diff --git a/src/shared/output-mode.c b/src/shared/output-mode.c new file mode 100644 index 00000000..107b3455 --- /dev/null +++ b/src/shared/output-mode.c @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "output-mode.h" +#include "string-table.h" + +JsonFormatFlags output_mode_to_json_format_flags(OutputMode m) { + + switch (m) { + + case OUTPUT_JSON_SSE: + return JSON_FORMAT_SSE; + + case OUTPUT_JSON_SEQ: + return JSON_FORMAT_SEQ; + + case OUTPUT_JSON_PRETTY: + return JSON_FORMAT_PRETTY; + + default: + return JSON_FORMAT_NEWLINE; + } +} + +static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { + [OUTPUT_SHORT] = "short", + [OUTPUT_SHORT_FULL] = "short-full", + [OUTPUT_SHORT_ISO] = "short-iso", + [OUTPUT_SHORT_ISO_PRECISE] = "short-iso-precise", + [OUTPUT_SHORT_PRECISE] = "short-precise", + [OUTPUT_SHORT_MONOTONIC] = "short-monotonic", + [OUTPUT_SHORT_UNIX] = "short-unix", + [OUTPUT_VERBOSE] = "verbose", + [OUTPUT_EXPORT] = "export", + [OUTPUT_JSON] = "json", + [OUTPUT_JSON_PRETTY] = "json-pretty", + [OUTPUT_JSON_SSE] = "json-sse", + [OUTPUT_JSON_SEQ] = "json-seq", + [OUTPUT_CAT] = "cat", + [OUTPUT_WITH_UNIT] = "with-unit", +}; + +DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode); diff --git a/src/shared/output-mode.h b/src/shared/output-mode.h new file mode 100644 index 00000000..00b60320 --- /dev/null +++ b/src/shared/output-mode.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "json.h" +#include "macro.h" + +typedef enum OutputMode { + OUTPUT_SHORT, + OUTPUT_SHORT_FULL, + OUTPUT_SHORT_ISO, + OUTPUT_SHORT_ISO_PRECISE, + OUTPUT_SHORT_PRECISE, + OUTPUT_SHORT_MONOTONIC, + OUTPUT_SHORT_UNIX, + OUTPUT_VERBOSE, + OUTPUT_EXPORT, + OUTPUT_JSON, + OUTPUT_JSON_PRETTY, + OUTPUT_JSON_SSE, + OUTPUT_JSON_SEQ, + OUTPUT_CAT, + OUTPUT_WITH_UNIT, + _OUTPUT_MODE_MAX, + _OUTPUT_MODE_INVALID = -1 +} OutputMode; + +static inline bool OUTPUT_MODE_IS_JSON(OutputMode m) { + return IN_SET(m, OUTPUT_JSON, OUTPUT_JSON_PRETTY, OUTPUT_JSON_SSE, OUTPUT_JSON_SEQ); +} + +/* The output flags definitions are shared by the logs and process tree output. Some apply to both, some only to the + * logs output, others only to the process tree output. */ + +typedef enum OutputFlags { + OUTPUT_SHOW_ALL = 1 << 0, + OUTPUT_FOLLOW = 1 << 1, + OUTPUT_WARN_CUTOFF = 1 << 2, + OUTPUT_FULL_WIDTH = 1 << 3, + OUTPUT_COLOR = 1 << 4, + OUTPUT_CATALOG = 1 << 5, + OUTPUT_BEGIN_NEWLINE = 1 << 6, + OUTPUT_UTC = 1 << 7, + OUTPUT_KERNEL_THREADS = 1 << 8, + OUTPUT_NO_HOSTNAME = 1 << 9, +} OutputFlags; + +JsonFormatFlags output_mode_to_json_format_flags(OutputMode m); + +const char* output_mode_to_string(OutputMode m) _const_; +OutputMode output_mode_from_string(const char *s) _pure_; diff --git a/src/shared/pager.c b/src/shared/pager.c new file mode 100644 index 00000000..1fe9db17 --- /dev/null +++ b/src/shared/pager.c @@ -0,0 +1,293 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "copy.h" +#include "fd-util.h" +#include "fileio.h" +#include "io-util.h" +#include "locale-util.h" +#include "log.h" +#include "macro.h" +#include "pager.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "signal-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "util.h" + +static pid_t pager_pid = 0; + +static int stored_stdout = -1; +static int stored_stderr = -1; +static bool stdout_redirected = false; +static bool stderr_redirected = false; + +_noreturn_ static void pager_fallback(void) { + int r; + + r = copy_bytes(STDIN_FILENO, STDOUT_FILENO, (uint64_t) -1, 0); + if (r < 0) { + log_error_errno(r, "Internal pager failed: %m"); + _exit(EXIT_FAILURE); + } + + _exit(EXIT_SUCCESS); +} + +static int no_quit_on_interrupt(int exe_name_fd, const char *less_opts) { + _cleanup_fclose_ FILE *file = NULL; + _cleanup_free_ char *line = NULL; + int r; + + assert(exe_name_fd >= 0); + assert(less_opts); + + /* This takes ownership of exe_name_fd */ + file = fdopen(exe_name_fd, "r"); + if (!file) { + safe_close(exe_name_fd); + return log_error_errno(errno, "Failed to create FILE object: %m"); + } + + /* Find the last line */ + for (;;) { + _cleanup_free_ char *t = NULL; + + r = read_line(file, LONG_LINE_MAX, &t); + if (r < 0) + return log_error_errno(r, "Failed to read from socket: %m"); + if (r == 0) + break; + + free_and_replace(line, t); + } + + /* We only treat "less" specially. + * Return true whenever option K is *not* set. */ + r = streq_ptr(line, "less") && !strchr(less_opts, 'K'); + + log_debug("Pager executable is \"%s\", options \"%s\", quit_on_interrupt: %s", + strnull(line), less_opts, yes_no(!r)); + return r; +} + +int pager_open(PagerFlags flags) { + _cleanup_close_pair_ int fd[2] = { -1, -1 }, exe_name_pipe[2] = { -1, -1 }; + _cleanup_strv_free_ char **pager_args = NULL; + const char *pager, *less_opts; + int r; + + if (flags & PAGER_DISABLE) + return 0; + + if (pager_pid > 0) + return 1; + + if (terminal_is_dumb()) + return 0; + + if (!is_main_thread()) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Pager invoked from wrong thread."); + + pager = getenv("SYSTEMD_PAGER"); + if (!pager) + pager = getenv("PAGER"); + + if (pager) { + pager_args = strv_split(pager, WHITESPACE); + if (!pager_args) + return log_oom(); + + /* If the pager is explicitly turned off, honour it */ + if (strv_isempty(pager_args) || strv_equal(pager_args, STRV_MAKE("cat"))) + return 0; + } + + /* Determine and cache number of columns/lines before we spawn the pager so that we get the value from the + * actual tty */ + (void) columns(); + (void) lines(); + + if (pipe2(fd, O_CLOEXEC) < 0) + return log_error_errno(errno, "Failed to create pager pipe: %m"); + + /* This is a pipe to feed the name of the executed pager binary into the parent */ + if (pipe2(exe_name_pipe, O_CLOEXEC) < 0) + return log_error_errno(errno, "Failed to create exe_name pipe: %m"); + + /* Initialize a good set of less options */ + less_opts = getenv("SYSTEMD_LESS"); + if (!less_opts) + less_opts = "FRSXMK"; + if (flags & PAGER_JUMP_TO_END) + less_opts = strjoina(less_opts, " +G"); + + r = safe_fork("(pager)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pager_pid); + if (r < 0) + return r; + if (r == 0) { + const char *less_charset, *exe; + + /* In the child start the pager */ + + if (dup2(fd[0], STDIN_FILENO) < 0) { + log_error_errno(errno, "Failed to duplicate file descriptor to STDIN: %m"); + _exit(EXIT_FAILURE); + } + + safe_close_pair(fd); + + if (setenv("LESS", less_opts, 1) < 0) { + log_error_errno(errno, "Failed to set environment variable LESS: %m"); + _exit(EXIT_FAILURE); + } + + /* Initialize a good charset for less. This is + * particularly important if we output UTF-8 + * characters. */ + less_charset = getenv("SYSTEMD_LESSCHARSET"); + if (!less_charset && is_locale_utf8()) + less_charset = "utf-8"; + if (less_charset && + setenv("LESSCHARSET", less_charset, 1) < 0) { + log_error_errno(errno, "Failed to set environment variable LESSCHARSET: %m"); + _exit(EXIT_FAILURE); + } + + if (pager_args) { + r = loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false); + if (r < 0) { + log_error_errno(r, "Failed to write pager name to socket: %m"); + _exit(EXIT_FAILURE); + } + + execvp(pager_args[0], pager_args); + log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, + "Failed to execute '%s', using fallback pagers: %m", pager_args[0]); + } + + /* Debian's alternatives command for pagers is + * called 'pager'. Note that we do not call + * sensible-pagers here, since that is just a + * shell script that implements a logic that + * is similar to this one anyway, but is + * Debian-specific. */ + FOREACH_STRING(exe, "pager", "less", "more") { + r = loop_write(exe_name_pipe[1], exe, strlen(exe) + 1, false); + if (r < 0) { + log_error_errno(r, "Failed to write pager name to socket: %m"); + _exit(EXIT_FAILURE); + } + execlp(exe, exe, NULL); + log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, + "Failed to execute '%s', using next fallback pager: %m", exe); + } + + r = loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in)") + 1, false); + if (r < 0) { + log_error_errno(r, "Failed to write pager name to socket: %m"); + _exit(EXIT_FAILURE); + } + /* Close pipe to signal the parent to start sending data */ + safe_close_pair(exe_name_pipe); + pager_fallback(); + /* not reached */ + } + + /* Return in the parent */ + stored_stdout = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 3); + if (dup2(fd[1], STDOUT_FILENO) < 0) { + stored_stdout = safe_close(stored_stdout); + return log_error_errno(errno, "Failed to duplicate pager pipe: %m"); + } + stdout_redirected = true; + + stored_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3); + if (dup2(fd[1], STDERR_FILENO) < 0) { + stored_stderr = safe_close(stored_stderr); + return log_error_errno(errno, "Failed to duplicate pager pipe: %m"); + } + stderr_redirected = true; + + exe_name_pipe[1] = safe_close(exe_name_pipe[1]); + + r = no_quit_on_interrupt(TAKE_FD(exe_name_pipe[0]), less_opts); + if (r < 0) + return r; + if (r > 0) + (void) ignore_signals(SIGINT, -1); + + return 1; +} + +void pager_close(void) { + + if (pager_pid <= 0) + return; + + /* Inform pager that we are done */ + (void) fflush(stdout); + if (stdout_redirected) + if (stored_stdout < 0 || dup2(stored_stdout, STDOUT_FILENO) < 0) + (void) close(STDOUT_FILENO); + stored_stdout = safe_close(stored_stdout); + (void) fflush(stderr); + if (stderr_redirected) + if (stored_stderr < 0 || dup2(stored_stderr, STDERR_FILENO) < 0) + (void) close(STDERR_FILENO); + stored_stderr = safe_close(stored_stderr); + stdout_redirected = stderr_redirected = false; + + (void) kill(pager_pid, SIGCONT); + (void) wait_for_terminate(pager_pid, NULL); + pager_pid = 0; +} + +bool pager_have(void) { + return pager_pid > 0; +} + +int show_man_page(const char *desc, bool null_stdio) { + const char *args[4] = { "man", NULL, NULL, NULL }; + char *e = NULL; + pid_t pid; + size_t k; + int r; + + k = strlen(desc); + + if (desc[k-1] == ')') + e = strrchr(desc, '('); + + if (e) { + char *page = NULL, *section = NULL; + + page = strndupa(desc, e - desc); + section = strndupa(e + 1, desc + k - e - 2); + + args[1] = section; + args[2] = page; + } else + args[1] = desc; + + r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + /* Child */ + execvp(args[0], (char**) args); + log_error_errno(errno, "Failed to execute man: %m"); + _exit(EXIT_FAILURE); + } + + return wait_for_terminate_and_check(NULL, pid, 0); +} diff --git a/src/shared/pager.h b/src/shared/pager.h new file mode 100644 index 00000000..8299e238 --- /dev/null +++ b/src/shared/pager.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +typedef enum PagerFlags { + PAGER_DISABLE = 1 << 0, + PAGER_JUMP_TO_END = 1 << 1, +} PagerFlags; + +int pager_open(PagerFlags flags); +void pager_close(void); +bool pager_have(void) _pure_; + +int show_man_page(const char *page, bool null_stdio); diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c new file mode 100644 index 00000000..5b162097 --- /dev/null +++ b/src/shared/path-lookup.c @@ -0,0 +1,839 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fs-util.h" +#include "install.h" +#include "log.h" +#include "macro.h" +#include "mkdir.h" +#include "path-lookup.h" +#include "path-util.h" +#include "rm-rf.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "user-util.h" +#include "util.h" + +int xdg_user_runtime_dir(char **ret, const char *suffix) { + const char *e; + char *j; + + assert(ret); + assert(suffix); + + e = getenv("XDG_RUNTIME_DIR"); + if (!e) + return -ENXIO; + + j = strjoin(e, suffix); + if (!j) + return -ENOMEM; + + *ret = j; + return 0; +} + +int xdg_user_config_dir(char **ret, const char *suffix) { + const char *e; + char *j; + int r; + + assert(ret); + + e = getenv("XDG_CONFIG_HOME"); + if (e) + j = strjoin(e, suffix); + else { + _cleanup_free_ char *home = NULL; + + r = get_home_dir(&home); + if (r < 0) + return r; + + j = strjoin(home, "/.config", suffix); + } + + if (!j) + return -ENOMEM; + + *ret = j; + return 0; +} + +int xdg_user_data_dir(char **ret, const char *suffix) { + const char *e; + char *j; + int r; + + assert(ret); + assert(suffix); + + /* We don't treat /etc/xdg/systemd here as the spec + * suggests because we assume that is a link to + * /etc/systemd/ anyway. */ + + e = getenv("XDG_DATA_HOME"); + if (e) + j = strjoin(e, suffix); + else { + _cleanup_free_ char *home = NULL; + + r = get_home_dir(&home); + if (r < 0) + return r; + + j = strjoin(home, "/.local/share", suffix); + } + if (!j) + return -ENOMEM; + + *ret = j; + return 1; +} + +static const char* const user_data_unit_paths[] = { + "/usr/local/lib/systemd/user", + "/usr/local/share/systemd/user", + USER_DATA_UNIT_PATH, + "/usr/lib/systemd/user", + "/usr/share/systemd/user", + NULL +}; + +static const char* const user_config_unit_paths[] = { + USER_CONFIG_UNIT_PATH, + "/etc/systemd/user", + NULL +}; + +int xdg_user_dirs(char ***ret_config_dirs, char ***ret_data_dirs) { + /* Implement the mechanisms defined in + * + * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html + * + * We look in both the config and the data dirs because we + * want to encourage that distributors ship their unit files + * as data, and allow overriding as configuration. + */ + const char *e; + _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL; + + e = getenv("XDG_CONFIG_DIRS"); + if (e) { + config_dirs = strv_split(e, ":"); + if (!config_dirs) + return -ENOMEM; + } + + e = getenv("XDG_DATA_DIRS"); + if (e) + data_dirs = strv_split(e, ":"); + else + data_dirs = strv_new("/usr/local/share", + "/usr/share"); + if (!data_dirs) + return -ENOMEM; + + *ret_config_dirs = TAKE_PTR(config_dirs); + *ret_data_dirs = TAKE_PTR(data_dirs); + + return 0; +} + +static char** user_dirs( + const char *persistent_config, + const char *runtime_config, + const char *global_persistent_config, + const char *global_runtime_config, + const char *generator, + const char *generator_early, + const char *generator_late, + const char *transient, + const char *persistent_control, + const char *runtime_control) { + + _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL; + _cleanup_free_ char *data_home = NULL; + _cleanup_strv_free_ char **res = NULL; + int r; + + r = xdg_user_dirs(&config_dirs, &data_dirs); + if (r < 0) + return NULL; + + r = xdg_user_data_dir(&data_home, "/systemd/user"); + if (r < 0 && r != -ENXIO) + return NULL; + + /* Now merge everything we found. */ + if (strv_extend(&res, persistent_control) < 0) + return NULL; + + if (strv_extend(&res, runtime_control) < 0) + return NULL; + + if (strv_extend(&res, transient) < 0) + return NULL; + + if (strv_extend(&res, generator_early) < 0) + return NULL; + + if (strv_extend_strv_concat(&res, config_dirs, "/systemd/user") < 0) + return NULL; + + if (strv_extend(&res, persistent_config) < 0) + return NULL; + + /* global config has lower priority than the user config of the same type */ + if (strv_extend(&res, global_persistent_config) < 0) + return NULL; + + if (strv_extend_strv(&res, (char**) user_config_unit_paths, false) < 0) + return NULL; + + if (strv_extend(&res, runtime_config) < 0) + return NULL; + + if (strv_extend(&res, global_runtime_config) < 0) + return NULL; + + if (strv_extend(&res, generator) < 0) + return NULL; + + if (strv_extend(&res, data_home) < 0) + return NULL; + + if (strv_extend_strv_concat(&res, data_dirs, "/systemd/user") < 0) + return NULL; + + if (strv_extend_strv(&res, (char**) user_data_unit_paths, false) < 0) + return NULL; + + if (strv_extend(&res, generator_late) < 0) + return NULL; + + if (path_strv_make_absolute_cwd(res) < 0) + return NULL; + + return TAKE_PTR(res); +} + +bool path_is_user_data_dir(const char *path) { + assert(path); + + return strv_contains((char**) user_data_unit_paths, path); +} + +bool path_is_user_config_dir(const char *path) { + assert(path); + + return strv_contains((char**) user_config_unit_paths, path); +} + +static int acquire_generator_dirs( + UnitFileScope scope, + const char *tempdir, + char **generator, + char **generator_early, + char **generator_late) { + + _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL; + const char *prefix; + + assert(generator); + assert(generator_early); + assert(generator_late); + assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER, UNIT_FILE_GLOBAL)); + + if (scope == UNIT_FILE_GLOBAL) + return -EOPNOTSUPP; + + if (tempdir) + prefix = tempdir; + else if (scope == UNIT_FILE_SYSTEM) + prefix = "/run/systemd"; + else { + /* UNIT_FILE_USER */ + const char *e; + + e = getenv("XDG_RUNTIME_DIR"); + if (!e) + return -ENXIO; + + prefix = strjoina(e, "/systemd"); + } + + x = path_join(prefix, "generator"); + if (!x) + return -ENOMEM; + + y = path_join(prefix, "generator.early"); + if (!y) + return -ENOMEM; + + z = path_join(prefix, "generator.late"); + if (!z) + return -ENOMEM; + + *generator = TAKE_PTR(x); + *generator_early = TAKE_PTR(y); + *generator_late = TAKE_PTR(z); + + return 0; +} + +static int acquire_transient_dir( + UnitFileScope scope, + const char *tempdir, + char **ret) { + + char *transient; + + assert(ret); + assert(IN_SET(scope, UNIT_FILE_SYSTEM, UNIT_FILE_USER, UNIT_FILE_GLOBAL)); + + if (scope == UNIT_FILE_GLOBAL) + return -EOPNOTSUPP; + + if (tempdir) + transient = path_join(tempdir, "transient"); + else if (scope == UNIT_FILE_SYSTEM) + transient = strdup("/run/systemd/transient"); + else + return xdg_user_runtime_dir(ret, "/systemd/transient"); + + if (!transient) + return -ENOMEM; + *ret = transient; + return 0; +} + +static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **runtime) { + _cleanup_free_ char *a = NULL, *b = NULL; + int r; + + assert(persistent); + assert(runtime); + + switch (scope) { + + case UNIT_FILE_SYSTEM: + a = strdup(SYSTEM_CONFIG_UNIT_PATH); + b = strdup("/run/systemd/system"); + break; + + case UNIT_FILE_GLOBAL: + a = strdup(USER_CONFIG_UNIT_PATH); + b = strdup("/run/systemd/user"); + break; + + case UNIT_FILE_USER: + r = xdg_user_config_dir(&a, "/systemd/user"); + if (r < 0 && r != -ENXIO) + return r; + + r = xdg_user_runtime_dir(runtime, "/systemd/user"); + if (r < 0) { + if (r != -ENXIO) + return r; + + /* If XDG_RUNTIME_DIR is not set, don't consider that fatal, simply initialize the runtime + * directory to NULL */ + *runtime = NULL; + } + + *persistent = TAKE_PTR(a); + + return 0; + + default: + assert_not_reached("Hmm, unexpected scope value."); + } + + if (!a || !b) + return -ENOMEM; + + *persistent = TAKE_PTR(a); + *runtime = TAKE_PTR(b); + + return 0; +} + +static int acquire_control_dirs(UnitFileScope scope, char **persistent, char **runtime) { + _cleanup_free_ char *a = NULL; + int r; + + assert(persistent); + assert(runtime); + + switch (scope) { + + case UNIT_FILE_SYSTEM: { + _cleanup_free_ char *b = NULL; + + a = strdup("/etc/systemd/system.control"); + if (!a) + return -ENOMEM; + + b = strdup("/run/systemd/system.control"); + if (!b) + return -ENOMEM; + + *runtime = TAKE_PTR(b); + + break; + } + + case UNIT_FILE_USER: + r = xdg_user_config_dir(&a, "/systemd/user.control"); + if (r < 0 && r != -ENXIO) + return r; + + r = xdg_user_runtime_dir(runtime, "/systemd/user.control"); + if (r < 0) { + if (r != -ENXIO) + return r; + + /* If XDG_RUNTIME_DIR is not set, don't consider this fatal, simply initialize the directory to + * NULL */ + *runtime = NULL; + } + + break; + + case UNIT_FILE_GLOBAL: + return -EOPNOTSUPP; + + default: + assert_not_reached("Hmm, unexpected scope value."); + } + + *persistent = TAKE_PTR(a); + + return 0; +} + +static int acquire_attached_dirs( + UnitFileScope scope, + char **ret_persistent, + char **ret_runtime) { + + _cleanup_free_ char *a = NULL, *b = NULL; + + assert(ret_persistent); + assert(ret_runtime); + + /* Portable services are not available to regular users for now. */ + if (scope != UNIT_FILE_SYSTEM) + return -EOPNOTSUPP; + + a = strdup("/etc/systemd/system.attached"); + if (!a) + return -ENOMEM; + + b = strdup("/run/systemd/system.attached"); + if (!b) + return -ENOMEM; + + *ret_persistent = TAKE_PTR(a); + *ret_runtime = TAKE_PTR(b); + + return 0; +} + +static int patch_root_prefix(char **p, const char *root_dir) { + char *c; + + assert(p); + + if (!*p) + return 0; + + c = path_join(root_dir, *p); + if (!c) + return -ENOMEM; + + free_and_replace(*p, c); + return 0; +} + +static int patch_root_prefix_strv(char **l, const char *root_dir) { + char **i; + int r; + + if (!root_dir) + return 0; + + STRV_FOREACH(i, l) { + r = patch_root_prefix(i, root_dir); + if (r < 0) + return r; + } + + return 0; +} + +int lookup_paths_init( + LookupPaths *p, + UnitFileScope scope, + LookupPathsFlags flags, + const char *root_dir) { + + _cleanup_(rmdir_and_freep) char *tempdir = NULL; + _cleanup_free_ char + *root = NULL, + *persistent_config = NULL, *runtime_config = NULL, + *global_persistent_config = NULL, *global_runtime_config = NULL, + *generator = NULL, *generator_early = NULL, *generator_late = NULL, + *transient = NULL, + *persistent_control = NULL, *runtime_control = NULL, + *persistent_attached = NULL, *runtime_attached = NULL; + bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */ + _cleanup_strv_free_ char **paths = NULL; + const char *e; + int r; + + assert(p); + assert(scope >= 0); + assert(scope < _UNIT_FILE_SCOPE_MAX); + +#if HAVE_SPLIT_USR + flags |= LOOKUP_PATHS_SPLIT_USR; +#endif + + if (!empty_or_root(root_dir)) { + if (scope == UNIT_FILE_USER) + return -EINVAL; + + r = is_dir(root_dir, true); + if (r < 0) + return r; + if (r == 0) + return -ENOTDIR; + + root = strdup(root_dir); + if (!root) + return -ENOMEM; + } + + if (flags & LOOKUP_PATHS_TEMPORARY_GENERATED) { + r = mkdtemp_malloc("/tmp/systemd-temporary-XXXXXX", &tempdir); + if (r < 0) + return log_debug_errno(r, "Failed to create temporary directory: %m"); + } + + /* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_config to NULL */ + r = acquire_config_dirs(scope, &persistent_config, &runtime_config); + if (r < 0) + return r; + + if (scope == UNIT_FILE_USER) { + r = acquire_config_dirs(UNIT_FILE_GLOBAL, &global_persistent_config, &global_runtime_config); + if (r < 0) + return r; + } + + if ((flags & LOOKUP_PATHS_EXCLUDE_GENERATED) == 0) { + /* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */ + r = acquire_generator_dirs(scope, tempdir, + &generator, &generator_early, &generator_late); + if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENXIO)) + return r; + } + + /* Note: if XDG_RUNTIME_DIR is not set, this will fail completely with ENXIO */ + r = acquire_transient_dir(scope, tempdir, &transient); + if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENXIO)) + return r; + + /* Note: when XDG_RUNTIME_DIR is not set this will not return -ENXIO, but simply set runtime_control to NULL */ + r = acquire_control_dirs(scope, &persistent_control, &runtime_control); + if (r < 0 && r != -EOPNOTSUPP) + return r; + + r = acquire_attached_dirs(scope, &persistent_attached, &runtime_attached); + if (r < 0 && r != -EOPNOTSUPP) + return r; + + /* First priority is whatever has been passed to us via env vars */ + e = getenv("SYSTEMD_UNIT_PATH"); + if (e) { + const char *k; + + k = endswith(e, ":"); + if (k) { + e = strndupa(e, k - e); + append = true; + } + + /* FIXME: empty components in other places should be rejected. */ + + r = path_split_and_make_absolute(e, &paths); + if (r < 0) + return r; + } + + if (!paths || append) { + /* Let's figure something out. */ + + _cleanup_strv_free_ char **add = NULL; + + /* For the user units we include share/ in the search + * path in order to comply with the XDG basedir spec. + * For the system stuff we avoid such nonsense. OTOH + * we include /lib in the search path for the system + * stuff but avoid it for user stuff. */ + + switch (scope) { + + case UNIT_FILE_SYSTEM: + add = strv_new( + /* If you modify this you also want to modify + * systemdsystemunitpath= in systemd.pc.in! */ + STRV_IFNOTNULL(persistent_control), + STRV_IFNOTNULL(runtime_control), + STRV_IFNOTNULL(transient), + STRV_IFNOTNULL(generator_early), + persistent_config, + SYSTEM_CONFIG_UNIT_PATH, + "/etc/systemd/system", + STRV_IFNOTNULL(persistent_attached), + runtime_config, + "/run/systemd/system", + STRV_IFNOTNULL(runtime_attached), + STRV_IFNOTNULL(generator), + "/usr/local/lib/systemd/system", + SYSTEM_DATA_UNIT_PATH, + "/usr/lib/systemd/system", + STRV_IFNOTNULL(flags & LOOKUP_PATHS_SPLIT_USR ? "/lib/systemd/system" : NULL), + STRV_IFNOTNULL(generator_late)); + break; + + case UNIT_FILE_GLOBAL: + add = strv_new( + /* If you modify this you also want to modify + * systemduserunitpath= in systemd.pc.in, and + * the arrays in user_dirs() above! */ + STRV_IFNOTNULL(persistent_control), + STRV_IFNOTNULL(runtime_control), + STRV_IFNOTNULL(transient), + STRV_IFNOTNULL(generator_early), + persistent_config, + USER_CONFIG_UNIT_PATH, + "/etc/systemd/user", + runtime_config, + "/run/systemd/user", + STRV_IFNOTNULL(generator), + "/usr/local/share/systemd/user", + "/usr/share/systemd/user", + "/usr/local/lib/systemd/user", + USER_DATA_UNIT_PATH, + "/usr/lib/systemd/user", + STRV_IFNOTNULL(generator_late)); + break; + + case UNIT_FILE_USER: + add = user_dirs(persistent_config, runtime_config, + global_persistent_config, global_runtime_config, + generator, generator_early, generator_late, + transient, + persistent_control, runtime_control); + break; + + default: + assert_not_reached("Hmm, unexpected scope?"); + } + + if (!add) + return -ENOMEM; + + if (paths) { + r = strv_extend_strv(&paths, add, true); + if (r < 0) + return r; + } else + /* Small optimization: if paths is NULL (and it usually is), we can simply assign 'add' to it, + * and don't have to copy anything */ + paths = TAKE_PTR(add); + } + + r = patch_root_prefix(&persistent_config, root); + if (r < 0) + return r; + r = patch_root_prefix(&runtime_config, root); + if (r < 0) + return r; + + r = patch_root_prefix(&generator, root); + if (r < 0) + return r; + r = patch_root_prefix(&generator_early, root); + if (r < 0) + return r; + r = patch_root_prefix(&generator_late, root); + if (r < 0) + return r; + + r = patch_root_prefix(&transient, root); + if (r < 0) + return r; + + r = patch_root_prefix(&persistent_control, root); + if (r < 0) + return r; + r = patch_root_prefix(&runtime_control, root); + if (r < 0) + return r; + + r = patch_root_prefix(&persistent_attached, root); + if (r < 0) + return r; + r = patch_root_prefix(&runtime_attached, root); + if (r < 0) + return r; + + r = patch_root_prefix_strv(paths, root); + if (r < 0) + return -ENOMEM; + + *p = (LookupPaths) { + .search_path = strv_uniq(TAKE_PTR(paths)), + + .persistent_config = TAKE_PTR(persistent_config), + .runtime_config = TAKE_PTR(runtime_config), + + .generator = TAKE_PTR(generator), + .generator_early = TAKE_PTR(generator_early), + .generator_late = TAKE_PTR(generator_late), + + .transient = TAKE_PTR(transient), + + .persistent_control = TAKE_PTR(persistent_control), + .runtime_control = TAKE_PTR(runtime_control), + + .persistent_attached = TAKE_PTR(persistent_attached), + .runtime_attached = TAKE_PTR(runtime_attached), + + .root_dir = TAKE_PTR(root), + .temporary_dir = TAKE_PTR(tempdir), + }; + + return 0; +} + +void lookup_paths_free(LookupPaths *p) { + if (!p) + return; + + p->search_path = strv_free(p->search_path); + + p->persistent_config = mfree(p->persistent_config); + p->runtime_config = mfree(p->runtime_config); + + p->persistent_attached = mfree(p->persistent_attached); + p->runtime_attached = mfree(p->runtime_attached); + + p->generator = mfree(p->generator); + p->generator_early = mfree(p->generator_early); + p->generator_late = mfree(p->generator_late); + + p->transient = mfree(p->transient); + + p->persistent_control = mfree(p->persistent_control); + p->runtime_control = mfree(p->runtime_control); + + p->root_dir = mfree(p->root_dir); + p->temporary_dir = mfree(p->temporary_dir); +} + +void lookup_paths_log(LookupPaths *p) { + assert(p); + + if (strv_isempty(p->search_path)) { + log_debug("Ignoring unit files."); + p->search_path = strv_free(p->search_path); + } else { + _cleanup_free_ char *t; + + t = strv_join(p->search_path, "\n\t"); + log_debug("Looking for unit files in (higher priority first):\n\t%s", strna(t)); + } +} + +int lookup_paths_mkdir_generator(LookupPaths *p) { + int r, q; + + assert(p); + + if (!p->generator || !p->generator_early || !p->generator_late) + return -EINVAL; + + r = mkdir_p_label(p->generator, 0755); + + q = mkdir_p_label(p->generator_early, 0755); + if (q < 0 && r >= 0) + r = q; + + q = mkdir_p_label(p->generator_late, 0755); + if (q < 0 && r >= 0) + r = q; + + return r; +} + +void lookup_paths_trim_generator(LookupPaths *p) { + assert(p); + + /* Trim empty dirs */ + + if (p->generator) + (void) rmdir(p->generator); + if (p->generator_early) + (void) rmdir(p->generator_early); + if (p->generator_late) + (void) rmdir(p->generator_late); +} + +void lookup_paths_flush_generator(LookupPaths *p) { + assert(p); + + /* Flush the generated unit files in full */ + + if (p->generator) + (void) rm_rf(p->generator, REMOVE_ROOT|REMOVE_PHYSICAL); + if (p->generator_early) + (void) rm_rf(p->generator_early, REMOVE_ROOT|REMOVE_PHYSICAL); + if (p->generator_late) + (void) rm_rf(p->generator_late, REMOVE_ROOT|REMOVE_PHYSICAL); + + if (p->temporary_dir) + (void) rm_rf(p->temporary_dir, REMOVE_ROOT|REMOVE_PHYSICAL); +} + +char **generator_binary_paths(UnitFileScope scope) { + + switch (scope) { + + case UNIT_FILE_SYSTEM: + return strv_new("/run/systemd/system-generators", + "/etc/systemd/system-generators", + "/usr/local/lib/systemd/system-generators", + SYSTEM_GENERATOR_PATH); + + case UNIT_FILE_GLOBAL: + case UNIT_FILE_USER: + return strv_new("/run/systemd/user-generators", + "/etc/systemd/user-generators", + "/usr/local/lib/systemd/user-generators", + USER_GENERATOR_PATH); + + default: + assert_not_reached("Hmm, unexpected scope."); + } +} diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h new file mode 100644 index 00000000..f0762d24 --- /dev/null +++ b/src/shared/path-lookup.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +typedef struct LookupPaths LookupPaths; + +#include "unit-file.h" +#include "macro.h" + +typedef enum LookupPathsFlags { + LOOKUP_PATHS_EXCLUDE_GENERATED = 1 << 0, + LOOKUP_PATHS_TEMPORARY_GENERATED = 1 << 1, + LOOKUP_PATHS_SPLIT_USR = 1 << 2, +} LookupPathsFlags; + +struct LookupPaths { + /* Where we look for unit files. This includes the individual special paths below, but also any vendor + * supplied, static unit file paths. */ + char **search_path; + + /* Where we shall create or remove our installation symlinks, aka "configuration", and where the user/admin + * shall place his own unit files. */ + char *persistent_config; + char *runtime_config; + + /* Where units from a portable service image shall be placed. */ + char *persistent_attached; + char *runtime_attached; + + /* Where to place generated unit files (i.e. those a "generator" tool generated). Note the special semantics of + * this directory: the generators are flushed each time a "systemctl daemon-reload" is issued. The user should + * not alter these directories directly. */ + char *generator; + char *generator_early; + char *generator_late; + + /* Where to place transient unit files (i.e. those created dynamically via the bus API). Note the special + * semantics of this directory: all units created transiently have their unit files removed as the transient + * unit is unloaded. The user should not alter this directory directly. */ + char *transient; + + /* Where the snippets created by "systemctl set-property" are placed. Note that for transient units, the + * snippets are placed in the transient directory though (see above). The user should not alter this directory + * directly. */ + char *persistent_control; + char *runtime_control; + + /* The root directory prepended to all items above, or NULL */ + char *root_dir; + + /* A temporary directory when running in test mode, to be nuked */ + char *temporary_dir; +}; + +int lookup_paths_init(LookupPaths *p, UnitFileScope scope, LookupPathsFlags flags, const char *root_dir); + +int xdg_user_dirs(char ***ret_config_dirs, char ***ret_data_dirs); +int xdg_user_runtime_dir(char **ret, const char *suffix); +int xdg_user_config_dir(char **ret, const char *suffix); +int xdg_user_data_dir(char **ret, const char *suffix); + +bool path_is_user_data_dir(const char *path); +bool path_is_user_config_dir(const char *path); + +void lookup_paths_log(LookupPaths *p); + +int lookup_paths_mkdir_generator(LookupPaths *p); +void lookup_paths_trim_generator(LookupPaths *p); +void lookup_paths_flush_generator(LookupPaths *p); + +void lookup_paths_free(LookupPaths *p); + +char **generator_binary_paths(UnitFileScope scope); diff --git a/src/shared/pe-header.h b/src/shared/pe-header.h new file mode 100644 index 00000000..a3629175 --- /dev/null +++ b/src/shared/pe-header.h @@ -0,0 +1,59 @@ +#pragma once + +#include + +#include "macro.h" +#include "sparse-endian.h" + +struct DosFileHeader { + uint8_t Magic[2]; + le16_t LastSize; + le16_t nBlocks; + le16_t nReloc; + le16_t HdrSize; + le16_t MinAlloc; + le16_t MaxAlloc; + le16_t ss; + le16_t sp; + le16_t Checksum; + le16_t ip; + le16_t cs; + le16_t RelocPos; + le16_t nOverlay; + le16_t reserved[4]; + le16_t OEMId; + le16_t OEMInfo; + le16_t reserved2[10]; + le32_t ExeHeader; +} _packed_; + +#define PE_HEADER_MACHINE_I386 0x014cU +#define PE_HEADER_MACHINE_X64 0x8664U + +struct PeFileHeader { + le16_t Machine; + le16_t NumberOfSections; + le32_t TimeDateStamp; + le32_t PointerToSymbolTable; + le32_t NumberOfSymbols; + le16_t SizeOfOptionalHeader; + le16_t Characteristics; +} _packed_; + +struct PeHeader { + uint8_t Magic[4]; + struct PeFileHeader FileHeader; +} _packed_; + +struct PeSectionHeader { + uint8_t Name[8]; + le32_t VirtualSize; + le32_t VirtualAddress; + le32_t SizeOfRawData; + le32_t PointerToRawData; + le32_t PointerToRelocations; + le32_t PointerToLinenumbers; + le16_t NumberOfRelocations; + le16_t NumberOfLinenumbers; + le32_t Characteristics; + } _packed_; diff --git a/src/shared/pretty-print.c b/src/shared/pretty-print.c new file mode 100644 index 00000000..5772918c --- /dev/null +++ b/src/shared/pretty-print.c @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "conf-files.h" +#include "def.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "pager.h" +#include "path-util.h" +#include "pretty-print.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "util.h" + +static bool urlify_enabled(void) { + static int cached_urlify_enabled = -1; + + /* Unfortunately 'less' doesn't support links like this yet 😭, hence let's disable this as long as there's a + * pager in effect. Let's drop this check as soon as less got fixed a and enough time passed so that it's safe + * to assume that a link-enabled 'less' version has hit most installations. */ + + if (cached_urlify_enabled < 0) { + int val; + + val = getenv_bool("SYSTEMD_URLIFY"); + if (val >= 0) + cached_urlify_enabled = val; + else + cached_urlify_enabled = colors_enabled() && !pager_have(); + } + + return cached_urlify_enabled; +} + +int terminal_urlify(const char *url, const char *text, char **ret) { + char *n; + + assert(url); + + /* Takes an URL and a pretty string and formats it as clickable link for the terminal. See + * https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda for details. */ + + if (isempty(text)) + text = url; + + if (urlify_enabled()) + n = strjoin("\x1B]8;;", url, "\a", text, "\x1B]8;;\a"); + else + n = strdup(text); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; +} + +int file_url_from_path(const char *path, char **ret) { + _cleanup_free_ char *absolute = NULL; + struct utsname u; + char *url = NULL; + int r; + + if (uname(&u) < 0) + return -errno; + + if (!path_is_absolute(path)) { + r = path_make_absolute_cwd(path, &absolute); + if (r < 0) + return r; + + path = absolute; + } + + /* As suggested by https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda, let's include the local + * hostname here. Note that we don't use gethostname_malloc() or gethostname_strict() since we are interested + * in the raw string the kernel has set, whatever it may be, under the assumption that terminals are not overly + * careful with validating the strings either. */ + + url = strjoin("file://", u.nodename, path); + if (!url) + return -ENOMEM; + + *ret = url; + return 0; +} + +int terminal_urlify_path(const char *path, const char *text, char **ret) { + _cleanup_free_ char *url = NULL; + int r; + + assert(path); + + /* Much like terminal_urlify() above, but takes a file system path as input + * and turns it into a proper file:// URL first. */ + + if (isempty(path)) + return -EINVAL; + + if (isempty(text)) + text = path; + + if (!urlify_enabled()) { + char *n; + + n = strdup(text); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; + } + + r = file_url_from_path(path, &url); + if (r < 0) + return r; + + return terminal_urlify(url, text, ret); +} + +int terminal_urlify_man(const char *page, const char *section, char **ret) { + const char *url, *text; + + url = strjoina("man:", page, "(", section, ")"); + text = strjoina(page, "(", section, ") man page"); + + return terminal_urlify(url, text, ret); +} + +static int cat_file(const char *filename, bool newline) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *urlified = NULL; + int r; + + f = fopen(filename, "re"); + if (!f) + return -errno; + + r = terminal_urlify_path(filename, NULL, &urlified); + if (r < 0) + return r; + + printf("%s%s# %s%s\n", + newline ? "\n" : "", + ansi_highlight_blue(), + urlified, + ansi_normal()); + fflush(stdout); + + for (;;) { + _cleanup_free_ char *line = NULL; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_error_errno(r, "Failed to read \"%s\": %m", filename); + if (r == 0) + break; + + puts(line); + } + + return 0; +} + +int cat_files(const char *file, char **dropins, CatFlags flags) { + char **path; + int r; + + if (file) { + r = cat_file(file, false); + if (r == -ENOENT && (flags & CAT_FLAGS_MAIN_FILE_OPTIONAL)) + printf("%s# config file %s not found%s\n", + ansi_highlight_magenta(), + file, + ansi_normal()); + else if (r < 0) + return log_warning_errno(r, "Failed to cat %s: %m", file); + } + + STRV_FOREACH(path, dropins) { + r = cat_file(*path, file || path != dropins); + if (r < 0) + return log_warning_errno(r, "Failed to cat %s: %m", *path); + } + + return 0; +} + +void print_separator(void) { + + /* Outputs a separator line that resolves to whitespace when copied from the terminal. We do that by outputting + * one line filled with spaces with ANSI underline set, followed by a second (empty) line. */ + + if (underline_enabled()) { + size_t i, c; + + c = columns(); + + flockfile(stdout); + fputs_unlocked(ANSI_UNDERLINE, stdout); + + for (i = 0; i < c; i++) + fputc_unlocked(' ', stdout); + + fputs_unlocked(ANSI_NORMAL "\n\n", stdout); + funlockfile(stdout); + } else + fputs("\n\n", stdout); +} + +static int guess_type(const char **name, char ***prefixes, bool *is_collection, const char **extension) { + /* Try to figure out if name is like tmpfiles.d/ or systemd/system-presets/, + * i.e. a collection of directories without a main config file. */ + + _cleanup_free_ char *n = NULL; + bool usr = false, run = false, coll = false; + const char *ext = ".conf"; + /* This is static so that the array doesn't get deallocated when we exit the function */ + static const char* const std_prefixes[] = { CONF_PATHS(""), NULL }; + static const char* const usr_prefixes[] = { CONF_PATHS_USR(""), NULL }; + static const char* const run_prefixes[] = { "/run/", NULL }; + + if (path_equal(*name, "environment.d")) + /* Special case: we need to include /etc/environment in the search path, even + * though the whole concept is called environment.d. */ + *name = "environment"; + + n = strdup(*name); + if (!n) + return log_oom(); + + delete_trailing_chars(n, "/"); + + if (endswith(n, ".d")) + coll = true; + + if (path_equal(n, "environment")) + usr = true; + + if (path_equal(n, "udev/hwdb.d")) + ext = ".hwdb"; + + if (path_equal(n, "udev/rules.d")) + ext = ".rules"; + + if (path_equal(n, "kernel/install.d")) + ext = ".install"; + + if (path_equal(n, "systemd/ntp-units.d")) { + coll = true; + ext = ".list"; + } + + if (path_equal(n, "systemd/relabel-extra.d")) { + coll = run = true; + ext = ".relabel"; + } + + if (PATH_IN_SET(n, "systemd/system-preset", "systemd/user-preset")) { + coll = true; + ext = ".preset"; + } + + if (path_equal(n, "systemd/user-preset")) + usr = true; + + *prefixes = (char**) (usr ? usr_prefixes : run ? run_prefixes : std_prefixes); + *is_collection = coll; + *extension = ext; + return 0; +} + +int conf_files_cat(const char *root, const char *name) { + _cleanup_strv_free_ char **dirs = NULL, **files = NULL; + _cleanup_free_ char *path = NULL; + char **prefixes, **prefix; + bool is_collection; + const char *extension; + char **t; + int r; + + r = guess_type(&name, &prefixes, &is_collection, &extension); + if (r < 0) + return r; + + STRV_FOREACH(prefix, prefixes) { + assert(endswith(*prefix, "/")); + r = strv_extendf(&dirs, "%s%s%s", *prefix, name, + is_collection ? "" : ".d"); + if (r < 0) + return log_error_errno(r, "Failed to build directory list: %m"); + } + + r = conf_files_list_strv(&files, extension, root, 0, (const char* const*) dirs); + if (r < 0) + return log_error_errno(r, "Failed to query file list: %m"); + + if (!is_collection) { + path = path_join(root, "/etc", name); + if (!path) + return log_oom(); + } + + if (DEBUG_LOGGING) { + log_debug("Looking for configuration in:"); + if (path) + log_debug(" %s", path); + STRV_FOREACH(t, dirs) + log_debug(" %s/*%s", *t, extension); + } + + /* show */ + return cat_files(path, files, CAT_FLAGS_MAIN_FILE_OPTIONAL); +} diff --git a/src/shared/pretty-print.h b/src/shared/pretty-print.h new file mode 100644 index 00000000..12ab9acf --- /dev/null +++ b/src/shared/pretty-print.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +void print_separator(void); + +int file_url_from_path(const char *path, char **ret); + +int terminal_urlify(const char *url, const char *text, char **ret); +int terminal_urlify_path(const char *path, const char *text, char **ret); +int terminal_urlify_man(const char *page, const char *section, char **ret); + +typedef enum CatFlags { + CAT_FLAGS_MAIN_FILE_OPTIONAL = 1 << 0, +} CatFlags; + +int cat_files(const char *file, char **dropins, CatFlags flags); +int conf_files_cat(const char *root, const char *name); diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c new file mode 100644 index 00000000..fe17b378 --- /dev/null +++ b/src/shared/ptyfwd.c @@ -0,0 +1,631 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-event.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "log.h" +#include "macro.h" +#include "ptyfwd.h" +#include "terminal-util.h" +#include "time-util.h" + +struct PTYForward { + sd_event *event; + + int master; + + PTYForwardFlags flags; + + sd_event_source *stdin_event_source; + sd_event_source *stdout_event_source; + sd_event_source *master_event_source; + + sd_event_source *sigwinch_event_source; + + struct termios saved_stdin_attr; + struct termios saved_stdout_attr; + + bool saved_stdin:1; + bool saved_stdout:1; + + bool stdin_readable:1; + bool stdin_hangup:1; + bool stdout_writable:1; + bool stdout_hangup:1; + bool master_readable:1; + bool master_writable:1; + bool master_hangup:1; + + bool read_from_master:1; + + bool done:1; + bool drain:1; + + bool last_char_set:1; + char last_char; + + char in_buffer[LINE_MAX], out_buffer[LINE_MAX]; + size_t in_buffer_full, out_buffer_full; + + usec_t escape_timestamp; + unsigned escape_counter; + + PTYForwardHandler handler; + void *userdata; +}; + +#define ESCAPE_USEC (1*USEC_PER_SEC) + +static void pty_forward_disconnect(PTYForward *f) { + + if (f) { + f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); + f->stdout_event_source = sd_event_source_unref(f->stdout_event_source); + + f->master_event_source = sd_event_source_unref(f->master_event_source); + f->sigwinch_event_source = sd_event_source_unref(f->sigwinch_event_source); + f->event = sd_event_unref(f->event); + + if (f->saved_stdout) + tcsetattr(STDOUT_FILENO, TCSANOW, &f->saved_stdout_attr); + if (f->saved_stdin) + tcsetattr(STDIN_FILENO, TCSANOW, &f->saved_stdin_attr); + + f->saved_stdout = f->saved_stdin = false; + } + + /* STDIN/STDOUT should not be nonblocking normally, so let's unconditionally reset it */ + (void) fd_nonblock(STDIN_FILENO, false); + (void) fd_nonblock(STDOUT_FILENO, false); +} + +static int pty_forward_done(PTYForward *f, int rcode) { + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + assert(f); + + if (f->done) + return 0; + + e = sd_event_ref(f->event); + + f->done = true; + pty_forward_disconnect(f); + + if (f->handler) + return f->handler(f, rcode, f->userdata); + else + return sd_event_exit(e, rcode < 0 ? EXIT_FAILURE : rcode); +} + +static bool look_for_escape(PTYForward *f, const char *buffer, size_t n) { + const char *p; + + assert(f); + assert(buffer); + assert(n > 0); + + for (p = buffer; p < buffer + n; p++) { + + /* Check for ^] */ + if (*p == 0x1D) { + usec_t nw = now(CLOCK_MONOTONIC); + + if (f->escape_counter == 0 || nw > f->escape_timestamp + ESCAPE_USEC) { + f->escape_timestamp = nw; + f->escape_counter = 1; + } else { + (f->escape_counter)++; + + if (f->escape_counter >= 3) + return true; + } + } else { + f->escape_timestamp = 0; + f->escape_counter = 0; + } + } + + return false; +} + +static bool ignore_vhangup(PTYForward *f) { + assert(f); + + if (f->flags & PTY_FORWARD_IGNORE_VHANGUP) + return true; + + if ((f->flags & PTY_FORWARD_IGNORE_INITIAL_VHANGUP) && !f->read_from_master) + return true; + + return false; +} + +static bool drained(PTYForward *f) { + int q = 0; + + assert(f); + + if (f->out_buffer_full > 0) + return false; + + if (f->master_readable) + return false; + + if (ioctl(f->master, TIOCINQ, &q) < 0) + log_debug_errno(errno, "TIOCINQ failed on master: %m"); + else if (q > 0) + return false; + + if (ioctl(f->master, TIOCOUTQ, &q) < 0) + log_debug_errno(errno, "TIOCOUTQ failed on master: %m"); + else if (q > 0) + return false; + + return true; +} + +static int shovel(PTYForward *f) { + ssize_t k; + + assert(f); + + while ((f->stdin_readable && f->in_buffer_full <= 0) || + (f->master_writable && f->in_buffer_full > 0) || + (f->master_readable && f->out_buffer_full <= 0) || + (f->stdout_writable && f->out_buffer_full > 0)) { + + if (f->stdin_readable && f->in_buffer_full < LINE_MAX) { + + k = read(STDIN_FILENO, f->in_buffer + f->in_buffer_full, LINE_MAX - f->in_buffer_full); + if (k < 0) { + + if (errno == EAGAIN) + f->stdin_readable = false; + else if (IN_SET(errno, EIO, EPIPE, ECONNRESET)) { + f->stdin_readable = false; + f->stdin_hangup = true; + + f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); + } else { + log_error_errno(errno, "read(): %m"); + return pty_forward_done(f, -errno); + } + } else if (k == 0) { + /* EOF on stdin */ + f->stdin_readable = false; + f->stdin_hangup = true; + + f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); + } else { + /* Check if ^] has been pressed three times within one second. If we get this we quite + * immediately. */ + if (look_for_escape(f, f->in_buffer + f->in_buffer_full, k)) + return pty_forward_done(f, -ECANCELED); + + f->in_buffer_full += (size_t) k; + } + } + + if (f->master_writable && f->in_buffer_full > 0) { + + k = write(f->master, f->in_buffer, f->in_buffer_full); + if (k < 0) { + + if (IN_SET(errno, EAGAIN, EIO)) + f->master_writable = false; + else if (IN_SET(errno, EPIPE, ECONNRESET)) { + f->master_writable = f->master_readable = false; + f->master_hangup = true; + + f->master_event_source = sd_event_source_unref(f->master_event_source); + } else { + log_error_errno(errno, "write(): %m"); + return pty_forward_done(f, -errno); + } + } else { + assert(f->in_buffer_full >= (size_t) k); + memmove(f->in_buffer, f->in_buffer + k, f->in_buffer_full - k); + f->in_buffer_full -= k; + } + } + + if (f->master_readable && f->out_buffer_full < LINE_MAX) { + + k = read(f->master, f->out_buffer + f->out_buffer_full, LINE_MAX - f->out_buffer_full); + if (k < 0) { + + /* Note that EIO on the master device + * might be caused by vhangup() or + * temporary closing of everything on + * the other side, we treat it like + * EAGAIN here and try again, unless + * ignore_vhangup is off. */ + + if (errno == EAGAIN || (errno == EIO && ignore_vhangup(f))) + f->master_readable = false; + else if (IN_SET(errno, EPIPE, ECONNRESET, EIO)) { + f->master_readable = f->master_writable = false; + f->master_hangup = true; + + f->master_event_source = sd_event_source_unref(f->master_event_source); + } else { + log_error_errno(errno, "read(): %m"); + return pty_forward_done(f, -errno); + } + } else { + f->read_from_master = true; + f->out_buffer_full += (size_t) k; + } + } + + if (f->stdout_writable && f->out_buffer_full > 0) { + + k = write(STDOUT_FILENO, f->out_buffer, f->out_buffer_full); + if (k < 0) { + + if (errno == EAGAIN) + f->stdout_writable = false; + else if (IN_SET(errno, EIO, EPIPE, ECONNRESET)) { + f->stdout_writable = false; + f->stdout_hangup = true; + f->stdout_event_source = sd_event_source_unref(f->stdout_event_source); + } else { + log_error_errno(errno, "write(): %m"); + return pty_forward_done(f, -errno); + } + + } else { + + if (k > 0) { + f->last_char = f->out_buffer[k-1]; + f->last_char_set = true; + } + + assert(f->out_buffer_full >= (size_t) k); + memmove(f->out_buffer, f->out_buffer + k, f->out_buffer_full - k); + f->out_buffer_full -= k; + } + } + } + + if (f->stdin_hangup || f->stdout_hangup || f->master_hangup) { + /* Exit the loop if any side hung up and if there's + * nothing more to write or nothing we could write. */ + + if ((f->out_buffer_full <= 0 || f->stdout_hangup) && + (f->in_buffer_full <= 0 || f->master_hangup)) + return pty_forward_done(f, 0); + } + + /* If we were asked to drain, and there's nothing more to handle from the master, then call the callback + * too. */ + if (f->drain && drained(f)) + return pty_forward_done(f, 0); + + return 0; +} + +static int on_master_event(sd_event_source *e, int fd, uint32_t revents, void *userdata) { + PTYForward *f = userdata; + + assert(f); + assert(e); + assert(e == f->master_event_source); + assert(fd >= 0); + assert(fd == f->master); + + if (revents & (EPOLLIN|EPOLLHUP)) + f->master_readable = true; + + if (revents & (EPOLLOUT|EPOLLHUP)) + f->master_writable = true; + + return shovel(f); +} + +static int on_stdin_event(sd_event_source *e, int fd, uint32_t revents, void *userdata) { + PTYForward *f = userdata; + + assert(f); + assert(e); + assert(e == f->stdin_event_source); + assert(fd >= 0); + assert(fd == STDIN_FILENO); + + if (revents & (EPOLLIN|EPOLLHUP)) + f->stdin_readable = true; + + return shovel(f); +} + +static int on_stdout_event(sd_event_source *e, int fd, uint32_t revents, void *userdata) { + PTYForward *f = userdata; + + assert(f); + assert(e); + assert(e == f->stdout_event_source); + assert(fd >= 0); + assert(fd == STDOUT_FILENO); + + if (revents & (EPOLLOUT|EPOLLHUP)) + f->stdout_writable = true; + + return shovel(f); +} + +static int on_sigwinch_event(sd_event_source *e, const struct signalfd_siginfo *si, void *userdata) { + PTYForward *f = userdata; + struct winsize ws; + + assert(f); + assert(e); + assert(e == f->sigwinch_event_source); + + /* The window size changed, let's forward that. */ + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0) + (void) ioctl(f->master, TIOCSWINSZ, &ws); + + return 0; +} + +int pty_forward_new( + sd_event *event, + int master, + PTYForwardFlags flags, + PTYForward **ret) { + + _cleanup_(pty_forward_freep) PTYForward *f = NULL; + struct winsize ws; + int r; + + f = new(PTYForward, 1); + if (!f) + return -ENOMEM; + + *f = (struct PTYForward) { + .flags = flags, + .master = -1, + }; + + if (event) + f->event = sd_event_ref(event); + else { + r = sd_event_default(&f->event); + if (r < 0) + return r; + } + + if (!(flags & PTY_FORWARD_READ_ONLY)) { + r = fd_nonblock(STDIN_FILENO, true); + if (r < 0) + return r; + + r = fd_nonblock(STDOUT_FILENO, true); + if (r < 0) + return r; + } + + r = fd_nonblock(master, true); + if (r < 0) + return r; + + f->master = master; + + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) { + /* If we can't get the resolution from the output fd, then use our internal, regular width/height, + * i.e. something derived from $COLUMNS and $LINES if set. */ + + ws = (struct winsize) { + .ws_row = lines(), + .ws_col = columns(), + }; + } + + (void) ioctl(master, TIOCSWINSZ, &ws); + + if (!(flags & PTY_FORWARD_READ_ONLY)) { + if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) { + struct termios raw_stdin_attr; + + f->saved_stdin = true; + + raw_stdin_attr = f->saved_stdin_attr; + cfmakeraw(&raw_stdin_attr); + raw_stdin_attr.c_oflag = f->saved_stdin_attr.c_oflag; + tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin_attr); + } + + if (tcgetattr(STDOUT_FILENO, &f->saved_stdout_attr) >= 0) { + struct termios raw_stdout_attr; + + f->saved_stdout = true; + + raw_stdout_attr = f->saved_stdout_attr; + cfmakeraw(&raw_stdout_attr); + raw_stdout_attr.c_iflag = f->saved_stdout_attr.c_iflag; + raw_stdout_attr.c_lflag = f->saved_stdout_attr.c_lflag; + tcsetattr(STDOUT_FILENO, TCSANOW, &raw_stdout_attr); + } + + r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f); + if (r < 0 && r != -EPERM) + return r; + + if (r >= 0) + (void) sd_event_source_set_description(f->stdin_event_source, "ptyfwd-stdin"); + } + + r = sd_event_add_io(f->event, &f->stdout_event_source, STDOUT_FILENO, EPOLLOUT|EPOLLET, on_stdout_event, f); + if (r == -EPERM) + /* stdout without epoll support. Likely redirected to regular file. */ + f->stdout_writable = true; + else if (r < 0) + return r; + else + (void) sd_event_source_set_description(f->stdout_event_source, "ptyfwd-stdout"); + + r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f); + if (r < 0) + return r; + + (void) sd_event_source_set_description(f->master_event_source, "ptyfwd-master"); + + r = sd_event_add_signal(f->event, &f->sigwinch_event_source, SIGWINCH, on_sigwinch_event, f); + if (r < 0) + return r; + + (void) sd_event_source_set_description(f->sigwinch_event_source, "ptyfwd-sigwinch"); + + *ret = TAKE_PTR(f); + + return 0; +} + +PTYForward *pty_forward_free(PTYForward *f) { + pty_forward_disconnect(f); + return mfree(f); +} + +int pty_forward_get_last_char(PTYForward *f, char *ch) { + assert(f); + assert(ch); + + if (!f->last_char_set) + return -ENXIO; + + *ch = f->last_char; + return 0; +} + +int pty_forward_set_ignore_vhangup(PTYForward *f, bool b) { + int r; + + assert(f); + + if (!!(f->flags & PTY_FORWARD_IGNORE_VHANGUP) == b) + return 0; + + SET_FLAG(f->flags, PTY_FORWARD_IGNORE_VHANGUP, b); + + if (!ignore_vhangup(f)) { + + /* We shall now react to vhangup()s? Let's check + * immediately if we might be in one */ + + f->master_readable = true; + r = shovel(f); + if (r < 0) + return r; + } + + return 0; +} + +bool pty_forward_get_ignore_vhangup(PTYForward *f) { + assert(f); + + return !!(f->flags & PTY_FORWARD_IGNORE_VHANGUP); +} + +bool pty_forward_is_done(PTYForward *f) { + assert(f); + + return f->done; +} + +void pty_forward_set_handler(PTYForward *f, PTYForwardHandler cb, void *userdata) { + assert(f); + + f->handler = cb; + f->userdata = userdata; +} + +bool pty_forward_drain(PTYForward *f) { + assert(f); + + /* Starts draining the forwarder. Specifically: + * + * - Returns true if there are no unprocessed bytes from the pty, false otherwise + * + * - Makes sure the handler function is called the next time the number of unprocessed bytes hits zero + */ + + f->drain = true; + return drained(f); +} + +int pty_forward_set_priority(PTYForward *f, int64_t priority) { + int r; + assert(f); + + r = sd_event_source_set_priority(f->stdin_event_source, priority); + if (r < 0) + return r; + + r = sd_event_source_set_priority(f->stdout_event_source, priority); + if (r < 0) + return r; + + r = sd_event_source_set_priority(f->master_event_source, priority); + if (r < 0) + return r; + + r = sd_event_source_set_priority(f->sigwinch_event_source, priority); + if (r < 0) + return r; + + return 0; +} + +int pty_forward_set_width_height(PTYForward *f, unsigned width, unsigned height) { + struct winsize ws; + + assert(f); + + if (width == (unsigned) -1 && height == (unsigned) -1) + return 0; /* noop */ + + if (width != (unsigned) -1 && + (width == 0 || width > USHRT_MAX)) + return -ERANGE; + + if (height != (unsigned) -1 && + (height == 0 || height > USHRT_MAX)) + return -ERANGE; + + if (width == (unsigned) -1 || height == (unsigned) -1) { + if (ioctl(f->master, TIOCGWINSZ, &ws) < 0) + return -errno; + + if (width != (unsigned) -1) + ws.ws_col = width; + if (height != (unsigned) -1) + ws.ws_row = height; + } else + ws = (struct winsize) { + .ws_row = height, + .ws_col = width, + }; + + if (ioctl(f->master, TIOCSWINSZ, &ws) < 0) + return -errno; + + /* Make sure we ignore SIGWINCH window size events from now on */ + f->sigwinch_event_source = sd_event_source_unref(f->sigwinch_event_source); + + return 0; +} diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h new file mode 100644 index 00000000..887d3cba --- /dev/null +++ b/src/shared/ptyfwd.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-event.h" + +#include "macro.h" + +typedef struct PTYForward PTYForward; + +typedef enum PTYForwardFlags { + PTY_FORWARD_READ_ONLY = 1, + + /* Continue reading after hangup? */ + PTY_FORWARD_IGNORE_VHANGUP = 2, + + /* Continue reading after hangup but only if we never read anything else? */ + PTY_FORWARD_IGNORE_INITIAL_VHANGUP = 4, +} PTYForwardFlags; + +typedef int (*PTYForwardHandler)(PTYForward *f, int rcode, void *userdata); + +int pty_forward_new(sd_event *event, int master, PTYForwardFlags flags, PTYForward **f); +PTYForward *pty_forward_free(PTYForward *f); + +int pty_forward_get_last_char(PTYForward *f, char *ch); + +int pty_forward_set_ignore_vhangup(PTYForward *f, bool ignore_vhangup); +bool pty_forward_get_ignore_vhangup(PTYForward *f); + +bool pty_forward_is_done(PTYForward *f); + +void pty_forward_set_handler(PTYForward *f, PTYForwardHandler handler, void *userdata); + +bool pty_forward_drain(PTYForward *f); + +int pty_forward_set_priority(PTYForward *f, int64_t priority); + +int pty_forward_set_width_height(PTYForward *f, unsigned width, unsigned height); + +DEFINE_TRIVIAL_CLEANUP_FUNC(PTYForward*, pty_forward_free); diff --git a/src/shared/reboot-util.c b/src/shared/reboot-util.c new file mode 100644 index 00000000..5d762991 --- /dev/null +++ b/src/shared/reboot-util.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "fileio.h" +#include "log.h" +#include "proc-cmdline.h" +#include "raw-reboot.h" +#include "reboot-util.h" +#include "string-util.h" +#include "umask-util.h" +#include "virt.h" + +int update_reboot_parameter_and_warn(const char *parameter, bool keep) { + int r; + + if (isempty(parameter)) { + if (keep) + return 0; + + if (unlink("/run/systemd/reboot-param") < 0) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m"); + } + + return 0; + } + + RUN_WITH_UMASK(0022) { + r = write_string_file("/run/systemd/reboot-param", parameter, + WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); + if (r < 0) + return log_warning_errno(r, "Failed to write reboot parameter file: %m"); + } + + return 0; +} + +int read_reboot_parameter(char **parameter) { + int r; + + assert(parameter); + + r = read_one_line_file("/run/systemd/reboot-param", parameter); + if (r < 0 && r != -ENOENT) + return log_debug_errno(r, "Failed to read /run/systemd/reboot-param: %m"); + + return 0; +} + +int reboot_with_parameter(RebootFlags flags) { + int r; + + /* Reboots the system with a parameter that is read from /run/systemd/reboot-param. Returns 0 if REBOOT_DRY_RUN + * was set and the actual reboot operation was hence skipped. If REBOOT_FALLBACK is set and the reboot with + * parameter doesn't work out a fallback to classic reboot() is attempted. If REBOOT_FALLBACK is not set, 0 is + * returned instead, which should be considered indication for the caller to fall back to reboot() on its own, + * or somehow else deal with this. If REBOOT_LOG is specified will log about what it is going to do, as well as + * all errors. */ + + if (detect_container() == 0) { + _cleanup_free_ char *parameter = NULL; + + r = read_one_line_file("/run/systemd/reboot-param", ¶meter); + if (r < 0 && r != -ENOENT) + log_full_errno(flags & REBOOT_LOG ? LOG_WARNING : LOG_DEBUG, r, + "Failed to read reboot parameter file, ignoring: %m"); + + if (!isempty(parameter)) { + + log_full(flags & REBOOT_LOG ? LOG_INFO : LOG_DEBUG, + "Rebooting with argument '%s'.", parameter); + + if (flags & REBOOT_DRY_RUN) + return 0; + + (void) raw_reboot(LINUX_REBOOT_CMD_RESTART2, parameter); + + log_full_errno(flags & REBOOT_LOG ? LOG_WARNING : LOG_DEBUG, errno, + "Failed to reboot with parameter, retrying without: %m"); + } + } + + if (!(flags & REBOOT_FALLBACK)) + return 0; + + log_full(flags & REBOOT_LOG ? LOG_INFO : LOG_DEBUG, "Rebooting."); + + if (flags & REBOOT_DRY_RUN) + return 0; + + (void) reboot(RB_AUTOBOOT); + + return log_full_errno(flags & REBOOT_LOG ? LOG_ERR : LOG_DEBUG, errno, "Failed to reboot: %m"); +} + +int shall_restore_state(void) { + bool ret; + int r; + + r = proc_cmdline_get_bool("systemd.restore_state", &ret); + if (r < 0) + return r; + + return r > 0 ? ret : true; +} diff --git a/src/shared/reboot-util.h b/src/shared/reboot-util.h new file mode 100644 index 00000000..5aeb3482 --- /dev/null +++ b/src/shared/reboot-util.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +int update_reboot_parameter_and_warn(const char *parameter, bool keep); + +typedef enum RebootFlags { + REBOOT_LOG = 1 << 0, /* log about what we are going to do and all errors */ + REBOOT_DRY_RUN = 1 << 1, /* return 0 right before actually doing the reboot */ + REBOOT_FALLBACK = 1 << 2, /* fallback to plain reboot() if argument-based reboot doesn't work, isn't configured or doesn't apply otherwise */ +} RebootFlags; + +int read_reboot_parameter(char **parameter); +int reboot_with_parameter(RebootFlags flags); + +int shall_restore_state(void); diff --git a/src/shared/resolve-util.c b/src/shared/resolve-util.c new file mode 100644 index 00000000..615cb6d8 --- /dev/null +++ b/src/shared/resolve-util.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "conf-parser.h" +#include "resolve-util.h" +#include "string-table.h" + +DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_support, resolve_support, ResolveSupport, "Failed to parse resolve support setting"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_dnssec_mode, dnssec_mode, DnssecMode, "Failed to parse DNSSEC mode setting"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_over_tls_mode, dns_over_tls_mode, DnsOverTlsMode, "Failed to parse DNS-over-TLS mode setting"); + +static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = { + [RESOLVE_SUPPORT_NO] = "no", + [RESOLVE_SUPPORT_YES] = "yes", + [RESOLVE_SUPPORT_RESOLVE] = "resolve", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(resolve_support, ResolveSupport, RESOLVE_SUPPORT_YES); + +static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = { + [DNSSEC_NO] = "no", + [DNSSEC_ALLOW_DOWNGRADE] = "allow-downgrade", + [DNSSEC_YES] = "yes", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dnssec_mode, DnssecMode, DNSSEC_YES); + +static const char* const dns_over_tls_mode_table[_DNS_OVER_TLS_MODE_MAX] = { + [DNS_OVER_TLS_NO] = "no", + [DNS_OVER_TLS_OPPORTUNISTIC] = "opportunistic", + [DNS_OVER_TLS_YES] = "yes", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_over_tls_mode, DnsOverTlsMode, DNS_OVER_TLS_YES); + +bool dns_server_address_valid(int family, const union in_addr_union *sa) { + + /* Refuses the 0 IP addresses as well as 127.0.0.53 (which is our own DNS stub) */ + + if (in_addr_is_null(family, sa)) + return false; + + if (family == AF_INET && sa->in.s_addr == htobe32(INADDR_DNS_STUB)) + return false; + + return true; +} + +DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_cache_mode, dns_cache_mode, DnsCacheMode, "Failed to parse DNS cache mode setting") + +static const char* const dns_cache_mode_table[_DNS_CACHE_MODE_MAX] = { + [DNS_CACHE_MODE_YES] = "yes", + [DNS_CACHE_MODE_NO] = "no", + [DNS_CACHE_MODE_NO_NEGATIVE] = "no-negative", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_cache_mode, DnsCacheMode, DNS_CACHE_MODE_YES); diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h new file mode 100644 index 00000000..acf1f3da --- /dev/null +++ b/src/shared/resolve-util.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "in-addr-util.h" +#include "macro.h" + +/* 127.0.0.53 in native endian */ +#define INADDR_DNS_STUB ((in_addr_t) 0x7f000035U) + +typedef enum DnsCacheMode DnsCacheMode; + +enum DnsCacheMode { + DNS_CACHE_MODE_NO, + DNS_CACHE_MODE_YES, + DNS_CACHE_MODE_NO_NEGATIVE, + _DNS_CACHE_MODE_MAX, + _DNS_CACHE_MODE_INVALID = 1 +}; + +typedef enum ResolveSupport ResolveSupport; +typedef enum DnssecMode DnssecMode; +typedef enum DnsOverTlsMode DnsOverTlsMode; + +enum ResolveSupport { + RESOLVE_SUPPORT_NO, + RESOLVE_SUPPORT_YES, + RESOLVE_SUPPORT_RESOLVE, + _RESOLVE_SUPPORT_MAX, + _RESOLVE_SUPPORT_INVALID = -1 +}; + +enum DnssecMode { + /* No DNSSEC validation is done */ + DNSSEC_NO, + + /* Validate locally, if the server knows DO, but if not, + * don't. Don't trust the AD bit. If the server doesn't do + * DNSSEC properly, downgrade to non-DNSSEC operation. Of + * course, we then are vulnerable to a downgrade attack, but + * that's life and what is configured. */ + DNSSEC_ALLOW_DOWNGRADE, + + /* Insist on DNSSEC server support, and rather fail than downgrading. */ + DNSSEC_YES, + + _DNSSEC_MODE_MAX, + _DNSSEC_MODE_INVALID = -1 +}; + +enum DnsOverTlsMode { + /* No connection is made for DNS-over-TLS */ + DNS_OVER_TLS_NO, + + /* Try to connect using DNS-over-TLS, but if connection fails, + * fallback to using an unencrypted connection */ + DNS_OVER_TLS_OPPORTUNISTIC, + + /* Enforce DNS-over-TLS and require valid server certificates */ + DNS_OVER_TLS_YES, + + _DNS_OVER_TLS_MODE_MAX, + _DNS_OVER_TLS_MODE_INVALID = -1 +}; + +CONFIG_PARSER_PROTOTYPE(config_parse_resolve_support); +CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_dns_over_tls_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_dns_cache_mode); + +const char* resolve_support_to_string(ResolveSupport p) _const_; +ResolveSupport resolve_support_from_string(const char *s) _pure_; + +const char* dnssec_mode_to_string(DnssecMode p) _const_; +DnssecMode dnssec_mode_from_string(const char *s) _pure_; + +const char* dns_over_tls_mode_to_string(DnsOverTlsMode p) _const_; +DnsOverTlsMode dns_over_tls_mode_from_string(const char *s) _pure_; + +bool dns_server_address_valid(int family, const union in_addr_union *sa); + +const char* dns_cache_mode_to_string(DnsCacheMode p) _const_; +DnsCacheMode dns_cache_mode_from_string(const char *s) _pure_; diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c new file mode 100644 index 00000000..6d42b2d5 --- /dev/null +++ b/src/shared/seccomp-util.c @@ -0,0 +1,2062 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "af-list.h" +#include "alloc-util.h" +#include "errno-list.h" +#include "macro.h" +#include "nsflags.h" +#include "nulstr-util.h" +#include "process-util.h" +#include "seccomp-util.h" +#include "set.h" +#include "string-util.h" +#include "strv.h" + +const uint32_t seccomp_local_archs[] = { + + /* Note: always list the native arch we are compiled as last, so that users can blacklist seccomp(), but our own calls to it still succeed */ + +#if defined(__x86_64__) && defined(__ILP32__) + SCMP_ARCH_X86, + SCMP_ARCH_X86_64, + SCMP_ARCH_X32, /* native */ +#elif defined(__x86_64__) && !defined(__ILP32__) + SCMP_ARCH_X86, + SCMP_ARCH_X32, + SCMP_ARCH_X86_64, /* native */ +#elif defined(__i386__) + SCMP_ARCH_X86, +#elif defined(__aarch64__) + SCMP_ARCH_ARM, + SCMP_ARCH_AARCH64, /* native */ +#elif defined(__arm__) + SCMP_ARCH_ARM, +#elif defined(__mips__) && __BYTE_ORDER == __BIG_ENDIAN && _MIPS_SIM == _MIPS_SIM_ABI32 + SCMP_ARCH_MIPSEL, + SCMP_ARCH_MIPS, /* native */ +#elif defined(__mips__) && __BYTE_ORDER == __LITTLE_ENDIAN && _MIPS_SIM == _MIPS_SIM_ABI32 + SCMP_ARCH_MIPS, + SCMP_ARCH_MIPSEL, /* native */ +#elif defined(__mips__) && __BYTE_ORDER == __BIG_ENDIAN && _MIPS_SIM == _MIPS_SIM_ABI64 + SCMP_ARCH_MIPSEL, + SCMP_ARCH_MIPS, + SCMP_ARCH_MIPSEL64N32, + SCMP_ARCH_MIPS64N32, + SCMP_ARCH_MIPSEL64, + SCMP_ARCH_MIPS64, /* native */ +#elif defined(__mips__) && __BYTE_ORDER == __LITTLE_ENDIAN && _MIPS_SIM == _MIPS_SIM_ABI64 + SCMP_ARCH_MIPS, + SCMP_ARCH_MIPSEL, + SCMP_ARCH_MIPS64N32, + SCMP_ARCH_MIPSEL64N32, + SCMP_ARCH_MIPS64, + SCMP_ARCH_MIPSEL64, /* native */ +#elif defined(__mips__) && __BYTE_ORDER == __BIG_ENDIAN && _MIPS_SIM == _MIPS_SIM_NABI32 + SCMP_ARCH_MIPSEL, + SCMP_ARCH_MIPS, + SCMP_ARCH_MIPSEL64, + SCMP_ARCH_MIPS64, + SCMP_ARCH_MIPSEL64N32, + SCMP_ARCH_MIPS64N32, /* native */ +#elif defined(__mips__) && __BYTE_ORDER == __LITTLE_ENDIAN && _MIPS_SIM == _MIPS_SIM_NABI32 + SCMP_ARCH_MIPS, + SCMP_ARCH_MIPSEL, + SCMP_ARCH_MIPS64, + SCMP_ARCH_MIPSEL64, + SCMP_ARCH_MIPS64N32, + SCMP_ARCH_MIPSEL64N32, /* native */ +#elif defined(__powerpc64__) && __BYTE_ORDER == __BIG_ENDIAN + SCMP_ARCH_PPC, + SCMP_ARCH_PPC64LE, + SCMP_ARCH_PPC64, /* native */ +#elif defined(__powerpc64__) && __BYTE_ORDER == __LITTLE_ENDIAN + SCMP_ARCH_PPC, + SCMP_ARCH_PPC64, + SCMP_ARCH_PPC64LE, /* native */ +#elif defined(__powerpc__) + SCMP_ARCH_PPC, +#elif defined(__s390x__) + SCMP_ARCH_S390, + SCMP_ARCH_S390X, /* native */ +#elif defined(__s390__) + SCMP_ARCH_S390, +#endif + (uint32_t) -1 + }; + +const char* seccomp_arch_to_string(uint32_t c) { + /* Maintain order used in . + * + * Names used here should be the same as those used for ConditionArchitecture=, + * except for "subarchitectures" like x32. */ + + switch(c) { + case SCMP_ARCH_NATIVE: + return "native"; + case SCMP_ARCH_X86: + return "x86"; + case SCMP_ARCH_X86_64: + return "x86-64"; + case SCMP_ARCH_X32: + return "x32"; + case SCMP_ARCH_ARM: + return "arm"; + case SCMP_ARCH_AARCH64: + return "arm64"; + case SCMP_ARCH_MIPS: + return "mips"; + case SCMP_ARCH_MIPS64: + return "mips64"; + case SCMP_ARCH_MIPS64N32: + return "mips64-n32"; + case SCMP_ARCH_MIPSEL: + return "mips-le"; + case SCMP_ARCH_MIPSEL64: + return "mips64-le"; + case SCMP_ARCH_MIPSEL64N32: + return "mips64-le-n32"; + case SCMP_ARCH_PPC: + return "ppc"; + case SCMP_ARCH_PPC64: + return "ppc64"; + case SCMP_ARCH_PPC64LE: + return "ppc64-le"; + case SCMP_ARCH_S390: + return "s390"; + case SCMP_ARCH_S390X: + return "s390x"; + default: + return NULL; + } +} + +int seccomp_arch_from_string(const char *n, uint32_t *ret) { + if (!n) + return -EINVAL; + + assert(ret); + + if (streq(n, "native")) + *ret = SCMP_ARCH_NATIVE; + else if (streq(n, "x86")) + *ret = SCMP_ARCH_X86; + else if (streq(n, "x86-64")) + *ret = SCMP_ARCH_X86_64; + else if (streq(n, "x32")) + *ret = SCMP_ARCH_X32; + else if (streq(n, "arm")) + *ret = SCMP_ARCH_ARM; + else if (streq(n, "arm64")) + *ret = SCMP_ARCH_AARCH64; + else if (streq(n, "mips")) + *ret = SCMP_ARCH_MIPS; + else if (streq(n, "mips64")) + *ret = SCMP_ARCH_MIPS64; + else if (streq(n, "mips64-n32")) + *ret = SCMP_ARCH_MIPS64N32; + else if (streq(n, "mips-le")) + *ret = SCMP_ARCH_MIPSEL; + else if (streq(n, "mips64-le")) + *ret = SCMP_ARCH_MIPSEL64; + else if (streq(n, "mips64-le-n32")) + *ret = SCMP_ARCH_MIPSEL64N32; + else if (streq(n, "ppc")) + *ret = SCMP_ARCH_PPC; + else if (streq(n, "ppc64")) + *ret = SCMP_ARCH_PPC64; + else if (streq(n, "ppc64-le")) + *ret = SCMP_ARCH_PPC64LE; + else if (streq(n, "s390")) + *ret = SCMP_ARCH_S390; + else if (streq(n, "s390x")) + *ret = SCMP_ARCH_S390X; + else + return -EINVAL; + + return 0; +} + +int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_action) { + scmp_filter_ctx seccomp; + int r; + + /* Much like seccomp_init(), but initializes the filter for one specific architecture only, without affecting + * any others. Also, turns off the NNP fiddling. */ + + seccomp = seccomp_init(default_action); + if (!seccomp) + return -ENOMEM; + + if (arch != SCMP_ARCH_NATIVE && + arch != seccomp_arch_native()) { + + r = seccomp_arch_remove(seccomp, seccomp_arch_native()); + if (r < 0) + goto finish; + + r = seccomp_arch_add(seccomp, arch); + if (r < 0) + goto finish; + + assert(seccomp_arch_exist(seccomp, arch) >= 0); + assert(seccomp_arch_exist(seccomp, SCMP_ARCH_NATIVE) == -EEXIST); + assert(seccomp_arch_exist(seccomp, seccomp_arch_native()) == -EEXIST); + } else { + assert(seccomp_arch_exist(seccomp, SCMP_ARCH_NATIVE) >= 0); + assert(seccomp_arch_exist(seccomp, seccomp_arch_native()) >= 0); + } + + r = seccomp_attr_set(seccomp, SCMP_FLTATR_ACT_BADARCH, SCMP_ACT_ALLOW); + if (r < 0) + goto finish; + + r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); + if (r < 0) + goto finish; + + *ret = seccomp; + return 0; + +finish: + seccomp_release(seccomp); + return r; +} + +static bool is_basic_seccomp_available(void) { + return prctl(PR_GET_SECCOMP, 0, 0, 0, 0) >= 0; +} + +static bool is_seccomp_filter_available(void) { + return prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0) < 0 && + errno == EFAULT; +} + +bool is_seccomp_available(void) { + static int cached_enabled = -1; + + if (cached_enabled < 0) + cached_enabled = + is_basic_seccomp_available() && + is_seccomp_filter_available(); + + return cached_enabled; +} + +const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { + [SYSCALL_FILTER_SET_DEFAULT] = { + .name = "@default", + .help = "System calls that are always permitted", + .value = + "clock_getres\0" + "clock_getres_time64\0" + "clock_gettime\0" + "clock_gettime64\0" + "clock_nanosleep\0" + "clock_nanosleep_time64\0" + "execve\0" + "exit\0" + "exit_group\0" + "futex\0" + "futex_time64\0" + "get_robust_list\0" + "get_thread_area\0" + "getegid\0" + "getegid32\0" + "geteuid\0" + "geteuid32\0" + "getgid\0" + "getgid32\0" + "getgroups\0" + "getgroups32\0" + "getpgid\0" + "getpgrp\0" + "getpid\0" + "getppid\0" + "getresgid\0" + "getresgid32\0" + "getresuid\0" + "getresuid32\0" + "getrlimit\0" /* make sure processes can query stack size and such */ + "getsid\0" + "gettid\0" + "gettimeofday\0" + "getuid\0" + "getuid32\0" + "membarrier\0" + "nanosleep\0" + "pause\0" + "prlimit64\0" + "restart_syscall\0" + "rseq\0" + "rt_sigreturn\0" + "sched_yield\0" + "set_robust_list\0" + "set_thread_area\0" + "set_tid_address\0" + "set_tls\0" + "sigreturn\0" + "time\0" + "ugetrlimit\0" + }, + [SYSCALL_FILTER_SET_AIO] = { + .name = "@aio", + .help = "Asynchronous IO", + .value = + "io_cancel\0" + "io_destroy\0" + "io_getevents\0" + "io_pgetevents\0" + "io_pgetevents_time64\0" + "io_setup\0" + "io_submit\0" + "io_uring_enter\0" + "io_uring_register\0" + "io_uring_setup\0" + }, + [SYSCALL_FILTER_SET_BASIC_IO] = { + .name = "@basic-io", + .help = "Basic IO", + .value = + "_llseek\0" + "close\0" + "dup\0" + "dup2\0" + "dup3\0" + "lseek\0" + "pread64\0" + "preadv\0" + "preadv2\0" + "pwrite64\0" + "pwritev\0" + "pwritev2\0" + "read\0" + "readv\0" + "write\0" + "writev\0" + }, + [SYSCALL_FILTER_SET_CHOWN] = { + .name = "@chown", + .help = "Change ownership of files and directories", + .value = + "chown\0" + "chown32\0" + "fchown\0" + "fchown32\0" + "fchownat\0" + "lchown\0" + "lchown32\0" + }, + [SYSCALL_FILTER_SET_CLOCK] = { + .name = "@clock", + .help = "Change the system time", + .value = + "adjtimex\0" + "clock_adjtime\0" + "clock_adjtime64\0" + "clock_settime\0" + "clock_settime64\0" + "settimeofday\0" + "stime\0" + }, + [SYSCALL_FILTER_SET_CPU_EMULATION] = { + .name = "@cpu-emulation", + .help = "System calls for CPU emulation functionality", + .value = + "modify_ldt\0" + "subpage_prot\0" + "switch_endian\0" + "vm86\0" + "vm86old\0" + }, + [SYSCALL_FILTER_SET_DEBUG] = { + .name = "@debug", + .help = "Debugging, performance monitoring and tracing functionality", + .value = + "lookup_dcookie\0" + "perf_event_open\0" + "ptrace\0" + "rtas\0" +#ifdef __NR_s390_runtime_instr + "s390_runtime_instr\0" +#endif + "sys_debug_setcontext\0" + }, + [SYSCALL_FILTER_SET_FILE_SYSTEM] = { + .name = "@file-system", + .help = "File system operations", + .value = + "access\0" + "chdir\0" + "chmod\0" + "close\0" + "creat\0" + "faccessat\0" + "fallocate\0" + "fchdir\0" + "fchmod\0" + "fchmodat\0" + "fcntl\0" + "fcntl64\0" + "fgetxattr\0" + "flistxattr\0" + "fremovexattr\0" + "fsetxattr\0" + "fstat\0" + "fstat64\0" + "fstatat64\0" + "fstatfs\0" + "fstatfs64\0" + "ftruncate\0" + "ftruncate64\0" + "futimesat\0" + "getcwd\0" + "getdents\0" + "getdents64\0" + "getxattr\0" + "inotify_add_watch\0" + "inotify_init\0" + "inotify_init1\0" + "inotify_rm_watch\0" + "lgetxattr\0" + "link\0" + "linkat\0" + "listxattr\0" + "llistxattr\0" + "lremovexattr\0" + "lsetxattr\0" + "lstat\0" + "lstat64\0" + "mkdir\0" + "mkdirat\0" + "mknod\0" + "mknodat\0" + "mmap\0" + "mmap2\0" + "munmap\0" + "newfstatat\0" + "oldfstat\0" + "oldlstat\0" + "oldstat\0" + "open\0" + "openat\0" + "readlink\0" + "readlinkat\0" + "removexattr\0" + "rename\0" + "renameat\0" + "renameat2\0" + "rmdir\0" + "setxattr\0" + "stat\0" + "stat64\0" + "statfs\0" + "statfs64\0" +#ifdef __NR_statx + "statx\0" +#endif + "symlink\0" + "symlinkat\0" + "truncate\0" + "truncate64\0" + "unlink\0" + "unlinkat\0" + "utime\0" + "utimensat\0" + "utimensat_time64\0" + "utimes\0" + }, + [SYSCALL_FILTER_SET_IO_EVENT] = { + .name = "@io-event", + .help = "Event loop system calls", + .value = + "_newselect\0" + "epoll_create\0" + "epoll_create1\0" + "epoll_ctl\0" + "epoll_ctl_old\0" + "epoll_pwait\0" + "epoll_wait\0" + "epoll_wait_old\0" + "eventfd\0" + "eventfd2\0" + "poll\0" + "ppoll\0" + "ppoll_time64\0" + "pselect6\0" + "pselect6_time64\0" + "select\0" + }, + [SYSCALL_FILTER_SET_IPC] = { + .name = "@ipc", + .help = "SysV IPC, POSIX Message Queues or other IPC", + .value = + "ipc\0" + "memfd_create\0" + "mq_getsetattr\0" + "mq_notify\0" + "mq_open\0" + "mq_timedreceive\0" + "mq_timedreceive_time64\0" + "mq_timedsend\0" + "mq_timedsend_time64\0" + "mq_unlink\0" + "msgctl\0" + "msgget\0" + "msgrcv\0" + "msgsnd\0" + "pipe\0" + "pipe2\0" + "process_vm_readv\0" + "process_vm_writev\0" + "semctl\0" + "semget\0" + "semop\0" + "semtimedop\0" + "semtimedop_time64\0" + "shmat\0" + "shmctl\0" + "shmdt\0" + "shmget\0" + }, + [SYSCALL_FILTER_SET_KEYRING] = { + .name = "@keyring", + .help = "Kernel keyring access", + .value = + "add_key\0" + "keyctl\0" + "request_key\0" + }, + [SYSCALL_FILTER_SET_MEMLOCK] = { + .name = "@memlock", + .help = "Memory locking control", + .value = + "mlock\0" + "mlock2\0" + "mlockall\0" + "munlock\0" + "munlockall\0" + }, + [SYSCALL_FILTER_SET_MODULE] = { + .name = "@module", + .help = "Loading and unloading of kernel modules", + .value = + "delete_module\0" + "finit_module\0" + "init_module\0" + }, + [SYSCALL_FILTER_SET_MOUNT] = { + .name = "@mount", + .help = "Mounting and unmounting of file systems", + .value = + "chroot\0" + "fsconfig\0" + "fsmount\0" + "fsopen\0" + "fspick\0" + "mount\0" + "move_mount\0" + "open_tree\0" + "pivot_root\0" + "umount\0" + "umount2\0" + }, + [SYSCALL_FILTER_SET_NETWORK_IO] = { + .name = "@network-io", + .help = "Network or Unix socket IO, should not be needed if not network facing", + .value = + "accept\0" + "accept4\0" + "bind\0" + "connect\0" + "getpeername\0" + "getsockname\0" + "getsockopt\0" + "listen\0" + "recv\0" + "recvfrom\0" + "recvmmsg\0" + "recvmmsg_time64\0" + "recvmsg\0" + "send\0" + "sendmmsg\0" + "sendmsg\0" + "sendto\0" + "setsockopt\0" + "shutdown\0" + "socket\0" + "socketcall\0" + "socketpair\0" + }, + [SYSCALL_FILTER_SET_OBSOLETE] = { + /* some unknown even to libseccomp */ + .name = "@obsolete", + .help = "Unusual, obsolete or unimplemented system calls", + .value = + "_sysctl\0" + "afs_syscall\0" + "bdflush\0" + "break\0" + "create_module\0" + "ftime\0" + "get_kernel_syms\0" + "getpmsg\0" + "gtty\0" + "idle\0" + "lock\0" + "mpx\0" + "prof\0" + "profil\0" + "putpmsg\0" + "query_module\0" + "security\0" + "sgetmask\0" + "ssetmask\0" + "stty\0" + "sysfs\0" + "tuxcall\0" + "ulimit\0" + "uselib\0" + "ustat\0" + "vserver\0" + }, + [SYSCALL_FILTER_SET_PKEY] = { + .name = "@pkey", + .help = "System calls used for memory protection keys", + .value = + "pkey_alloc\0" + "pkey_free\0" + "pkey_mprotect\0" + }, + [SYSCALL_FILTER_SET_PRIVILEGED] = { + .name = "@privileged", + .help = "All system calls which need super-user capabilities", + .value = + "@chown\0" + "@clock\0" + "@module\0" + "@raw-io\0" + "@reboot\0" + "@swap\0" + "_sysctl\0" + "acct\0" + "bpf\0" + "capset\0" + "chroot\0" + "fanotify_init\0" + "fanotify_mark\0" + "nfsservctl\0" + "open_by_handle_at\0" + "pivot_root\0" + "quotactl\0" + "setdomainname\0" + "setfsuid\0" + "setfsuid32\0" + "setgroups\0" + "setgroups32\0" + "sethostname\0" + "setresuid\0" + "setresuid32\0" + "setreuid\0" + "setreuid32\0" + "setuid\0" /* We list the explicit system calls here, as @setuid also includes setgid() which is not necessarily privileged */ + "setuid32\0" + "vhangup\0" + }, + [SYSCALL_FILTER_SET_PROCESS] = { + .name = "@process", + .help = "Process control, execution, namespaceing operations", + .value = + "arch_prctl\0" + "capget\0" /* Able to query arbitrary processes */ + "clone\0" + "clone3\0" + "execveat\0" + "fork\0" + "getrusage\0" + "kill\0" + "pidfd_open\0" + "pidfd_send_signal\0" + "prctl\0" + "rt_sigqueueinfo\0" + "rt_tgsigqueueinfo\0" + "setns\0" + "swapcontext\0" /* Some archs e.g. powerpc32 are using it to do userspace context switches */ + "tgkill\0" + "times\0" + "tkill\0" + "unshare\0" + "vfork\0" + "wait4\0" + "waitid\0" + "waitpid\0" + }, + [SYSCALL_FILTER_SET_RAW_IO] = { + .name = "@raw-io", + .help = "Raw I/O port access", + .value = + "ioperm\0" + "iopl\0" + "pciconfig_iobase\0" + "pciconfig_read\0" + "pciconfig_write\0" +#ifdef __NR_s390_pci_mmio_read + "s390_pci_mmio_read\0" +#endif +#ifdef __NR_s390_pci_mmio_write + "s390_pci_mmio_write\0" +#endif + }, + [SYSCALL_FILTER_SET_REBOOT] = { + .name = "@reboot", + .help = "Reboot and reboot preparation/kexec", + .value = + "kexec_file_load\0" + "kexec_load\0" + "reboot\0" + }, + [SYSCALL_FILTER_SET_RESOURCES] = { + .name = "@resources", + .help = "Alter resource settings", + .value = + "ioprio_set\0" + "mbind\0" + "migrate_pages\0" + "move_pages\0" + "nice\0" + "sched_setaffinity\0" + "sched_setattr\0" + "sched_setparam\0" + "sched_setscheduler\0" + "set_mempolicy\0" + "setpriority\0" + "setrlimit\0" + }, + [SYSCALL_FILTER_SET_SETUID] = { + .name = "@setuid", + .help = "Operations for changing user/group credentials", + .value = + "setgid\0" + "setgid32\0" + "setgroups\0" + "setgroups32\0" + "setregid\0" + "setregid32\0" + "setresgid\0" + "setresgid32\0" + "setresuid\0" + "setresuid32\0" + "setreuid\0" + "setreuid32\0" + "setuid\0" + "setuid32\0" + }, + [SYSCALL_FILTER_SET_SIGNAL] = { + .name = "@signal", + .help = "Process signal handling", + .value = + "rt_sigaction\0" + "rt_sigpending\0" + "rt_sigprocmask\0" + "rt_sigsuspend\0" + "rt_sigtimedwait\0" + "rt_sigtimedwait_time64\0" + "sigaction\0" + "sigaltstack\0" + "signal\0" + "signalfd\0" + "signalfd4\0" + "sigpending\0" + "sigprocmask\0" + "sigsuspend\0" + }, + [SYSCALL_FILTER_SET_SWAP] = { + .name = "@swap", + .help = "Enable/disable swap devices", + .value = + "swapoff\0" + "swapon\0" + }, + [SYSCALL_FILTER_SET_SYNC] = { + .name = "@sync", + .help = "Synchronize files and memory to storage", + .value = + "fdatasync\0" + "fsync\0" + "msync\0" + "sync\0" + "sync_file_range\0" + "sync_file_range2\0" + "syncfs\0" + }, + [SYSCALL_FILTER_SET_SYSTEM_SERVICE] = { + .name = "@system-service", + .help = "General system service operations", + .value = + "@aio\0" + "@basic-io\0" + "@chown\0" + "@default\0" + "@file-system\0" + "@io-event\0" + "@ipc\0" + "@keyring\0" + "@memlock\0" + "@network-io\0" + "@process\0" + "@resources\0" + "@setuid\0" + "@signal\0" + "@sync\0" + "@timer\0" + "brk\0" + "capget\0" + "capset\0" + "copy_file_range\0" + "fadvise64\0" + "fadvise64_64\0" + "flock\0" + "get_mempolicy\0" + "getcpu\0" + "getpriority\0" + "getrandom\0" + "ioctl\0" + "ioprio_get\0" + "kcmp\0" + "madvise\0" + "mprotect\0" + "mremap\0" + "name_to_handle_at\0" + "oldolduname\0" + "olduname\0" + "personality\0" + "readahead\0" + "readdir\0" + "remap_file_pages\0" + "sched_get_priority_max\0" + "sched_get_priority_min\0" + "sched_getaffinity\0" + "sched_getattr\0" + "sched_getparam\0" + "sched_getscheduler\0" + "sched_rr_get_interval\0" + "sched_rr_get_interval_time64\0" + "sched_yield\0" + "sendfile\0" + "sendfile64\0" + "setfsgid\0" + "setfsgid32\0" + "setfsuid\0" + "setfsuid32\0" + "setpgid\0" + "setsid\0" + "splice\0" + "sysinfo\0" + "tee\0" + "umask\0" + "uname\0" + "userfaultfd\0" + "vmsplice\0" + }, + [SYSCALL_FILTER_SET_TIMER] = { + .name = "@timer", + .help = "Schedule operations by time", + .value = + "alarm\0" + "getitimer\0" + "setitimer\0" + "timer_create\0" + "timer_delete\0" + "timer_getoverrun\0" + "timer_gettime\0" + "timer_gettime64\0" + "timer_settime\0" + "timer_settime64\0" + "timerfd_create\0" + "timerfd_gettime\0" + "timerfd_gettime64\0" + "timerfd_settime\0" + "timerfd_settime64\0" + "times\0" + }, +}; + +const SyscallFilterSet *syscall_filter_set_find(const char *name) { + unsigned i; + + if (isempty(name) || name[0] != '@') + return NULL; + + for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) + if (streq(syscall_filter_sets[i].name, name)) + return syscall_filter_sets + i; + + return NULL; +} + +static int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action, char **exclude, bool log_missing); + +int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, uint32_t action, char **exclude, bool log_missing) { + assert(seccomp); + assert(name); + + if (strv_contains(exclude, name)) + return 0; + + if (name[0] == '@') { + const SyscallFilterSet *other; + + other = syscall_filter_set_find(name); + if (!other) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Filter set %s is not known!", + name); + + return seccomp_add_syscall_filter_set(seccomp, other, action, exclude, log_missing); + + } else { + int id, r; + + id = seccomp_syscall_resolve_name(name); + if (id == __NR_SCMP_ERROR) { + if (log_missing) + log_debug("System call %s is not known, ignoring.", name); + return 0; + } + + r = seccomp_rule_add_exact(seccomp, action, id, 0); + if (r < 0) { + /* If the system call is not known on this architecture, then that's fine, let's ignore it */ + bool ignore = r == -EDOM; + + if (!ignore || log_missing) + log_debug_errno(r, "Failed to add rule for system call %s() / %d%s: %m", + name, id, ignore ? ", ignoring" : ""); + if (!ignore) + return r; + } + + return 0; + } +} + +static int seccomp_add_syscall_filter_set( + scmp_filter_ctx seccomp, + const SyscallFilterSet *set, + uint32_t action, + char **exclude, + bool log_missing) { + + const char *sys; + int r; + + assert(seccomp); + assert(set); + + NULSTR_FOREACH(sys, set->value) { + r = seccomp_add_syscall_filter_item(seccomp, sys, action, exclude, log_missing); + if (r < 0) + return r; + } + + return 0; +} + +int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action, bool log_missing) { + uint32_t arch; + int r; + + assert(set); + + /* The one-stop solution: allocate a seccomp object, add the specified filter to it, and apply it. Once for + * each local arch. */ + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + + log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); + + r = seccomp_init_for_arch(&seccomp, arch, default_action); + if (r < 0) + return r; + + r = seccomp_add_syscall_filter_set(seccomp, set, action, NULL, log_missing); + if (r < 0) + return log_debug_errno(r, "Failed to add filter set: %m"); + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to install filter set for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action, bool log_missing) { + uint32_t arch; + int r; + + /* Similar to seccomp_load_syscall_filter_set(), but takes a raw Set* of syscalls, instead of a + * SyscallFilterSet* table. */ + + if (hashmap_isempty(set) && default_action == SCMP_ACT_ALLOW) + return 0; + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + Iterator i; + void *syscall_id, *val; + + log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); + + r = seccomp_init_for_arch(&seccomp, arch, default_action); + if (r < 0) + return r; + + HASHMAP_FOREACH_KEY(val, syscall_id, set, i) { + uint32_t a = action; + int id = PTR_TO_INT(syscall_id) - 1; + int error = PTR_TO_INT(val); + + if (action != SCMP_ACT_ALLOW && error >= 0) + a = SCMP_ACT_ERRNO(error); + + r = seccomp_rule_add_exact(seccomp, a, id, 0); + if (r < 0) { + /* If the system call is not known on this architecture, then that's fine, let's ignore it */ + _cleanup_free_ char *n = NULL; + bool ignore; + + n = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, id); + ignore = r == -EDOM; + if (!ignore || log_missing) + log_debug_errno(r, "Failed to add rule for system call %s() / %d%s: %m", + strna(n), id, ignore ? ", ignoring" : ""); + if (!ignore) + return r; + } + } + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to install filter set for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +int seccomp_parse_syscall_filter( + const char *name, + int errno_num, + Hashmap *filter, + SeccompParseFlags flags, + const char *unit, + const char *filename, + unsigned line) { + + int r; + + assert(name); + assert(filter); + + if (name[0] == '@') { + const SyscallFilterSet *set; + const char *i; + + set = syscall_filter_set_find(name); + if (!set) { + if (!(flags & SECCOMP_PARSE_PERMISSIVE)) + return -EINVAL; + + log_syntax(unit, flags & SECCOMP_PARSE_LOG ? LOG_WARNING : LOG_DEBUG, filename, line, 0, + "Unknown system call group, ignoring: %s", name); + return 0; + } + + NULSTR_FOREACH(i, set->value) { + /* Call ourselves again, for the group to parse. Note that we downgrade logging here (i.e. take + * away the SECCOMP_PARSE_LOG flag) since any issues in the group table are our own problem, + * not a problem in user configuration data and we shouldn't pretend otherwise by complaining + * about them. */ + r = seccomp_parse_syscall_filter(i, errno_num, filter, flags &~ SECCOMP_PARSE_LOG, unit, filename, line); + if (r < 0) + return r; + } + } else { + int id; + + id = seccomp_syscall_resolve_name(name); + if (id == __NR_SCMP_ERROR) { + if (!(flags & SECCOMP_PARSE_PERMISSIVE)) + return -EINVAL; + + log_syntax(unit, flags & SECCOMP_PARSE_LOG ? LOG_WARNING : LOG_DEBUG, filename, line, 0, + "Failed to parse system call, ignoring: %s", name); + return 0; + } + + /* If we previously wanted to forbid a syscall and now + * we want to allow it, then remove it from the list. */ + if (!(flags & SECCOMP_PARSE_INVERT) == !!(flags & SECCOMP_PARSE_WHITELIST)) { + r = hashmap_put(filter, INT_TO_PTR(id + 1), INT_TO_PTR(errno_num)); + if (r < 0) + switch (r) { + case -ENOMEM: + return flags & SECCOMP_PARSE_LOG ? log_oom() : -ENOMEM; + case -EEXIST: + assert_se(hashmap_update(filter, INT_TO_PTR(id + 1), INT_TO_PTR(errno_num)) == 0); + break; + default: + return r; + } + } else + (void) hashmap_remove(filter, INT_TO_PTR(id + 1)); + } + + return 0; +} + +int seccomp_restrict_namespaces(unsigned long retain) { + uint32_t arch; + int r; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *s = NULL; + + (void) namespace_flags_to_string(retain, &s); + log_debug("Restricting namespace to: %s.", strna(s)); + } + + /* NOOP? */ + if ((retain & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL) + return 0; + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + unsigned i; + + log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); + if (r < 0) + return r; + + if ((retain & NAMESPACE_FLAGS_ALL) == 0) + /* If every single kind of namespace shall be prohibited, then let's block the whole setns() syscall + * altogether. */ + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(setns), + 0); + else + /* Otherwise, block only the invocations with the appropriate flags in the loop below, but also the + * special invocation with a zero flags argument, right here. */ + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(setns), + 1, + SCMP_A1(SCMP_CMP_EQ, 0)); + if (r < 0) { + log_debug_errno(r, "Failed to add setns() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + + for (i = 0; namespace_flag_map[i].name; i++) { + unsigned long f; + + f = namespace_flag_map[i].flag; + if ((retain & f) == f) { + log_debug("Permitting %s.", namespace_flag_map[i].name); + continue; + } + + log_debug("Blocking %s.", namespace_flag_map[i].name); + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(unshare), + 1, + SCMP_A0(SCMP_CMP_MASKED_EQ, f, f)); + if (r < 0) { + log_debug_errno(r, "Failed to add unshare() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + break; + } + + /* On s390/s390x the first two parameters to clone are switched */ + if (!IN_SET(arch, SCMP_ARCH_S390, SCMP_ARCH_S390X)) + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(clone), + 1, + SCMP_A0(SCMP_CMP_MASKED_EQ, f, f)); + else + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(clone), + 1, + SCMP_A1(SCMP_CMP_MASKED_EQ, f, f)); + if (r < 0) { + log_debug_errno(r, "Failed to add clone() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + break; + } + + if ((retain & NAMESPACE_FLAGS_ALL) != 0) { + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(setns), + 1, + SCMP_A1(SCMP_CMP_MASKED_EQ, f, f)); + if (r < 0) { + log_debug_errno(r, "Failed to add setns() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + break; + } + } + } + if (r < 0) + continue; + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to install namespace restriction rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +int seccomp_protect_sysctl(void) { + uint32_t arch; + int r; + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + + log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); + + if (IN_SET(arch, SCMP_ARCH_X32, SCMP_ARCH_AARCH64)) + /* No _sysctl syscall */ + continue; + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); + if (r < 0) + return r; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(_sysctl), + 0); + if (r < 0) { + log_debug_errno(r, "Failed to add _sysctl() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to install sysctl protection rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +int seccomp_protect_syslog(void) { + uint32_t arch; + int r; + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); + if (r < 0) + return r; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(syslog), + 0); + + if (r < 0) { + log_debug_errno(r, "Failed to add syslog() rule for architecture %s, skipping %m", seccomp_arch_to_string(arch)); + continue; + } + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to install syslog protection rules for architecture %s, skipping %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +int seccomp_restrict_address_families(Set *address_families, bool whitelist) { + uint32_t arch; + int r; + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + bool supported; + Iterator i; + + log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); + + switch (arch) { + + case SCMP_ARCH_X86_64: + case SCMP_ARCH_X32: + case SCMP_ARCH_ARM: + case SCMP_ARCH_AARCH64: + case SCMP_ARCH_PPC: + case SCMP_ARCH_PPC64: + case SCMP_ARCH_PPC64LE: + case SCMP_ARCH_MIPSEL64N32: + case SCMP_ARCH_MIPS64N32: + case SCMP_ARCH_MIPSEL64: + case SCMP_ARCH_MIPS64: + /* These we know we support (i.e. are the ones that do not use socketcall()) */ + supported = true; + break; + + case SCMP_ARCH_S390: + case SCMP_ARCH_S390X: + case SCMP_ARCH_X86: + case SCMP_ARCH_MIPSEL: + case SCMP_ARCH_MIPS: + default: + /* These we either know we don't support (i.e. are the ones that do use socketcall()), or we + * don't know */ + supported = false; + break; + } + + if (!supported) + continue; + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); + if (r < 0) + return r; + + if (whitelist) { + int af, first = 0, last = 0; + void *afp; + + /* If this is a whitelist, we first block the address families that are out of range and then + * everything that is not in the set. First, we find the lowest and highest address family in + * the set. */ + + SET_FOREACH(afp, address_families, i) { + af = PTR_TO_INT(afp); + + if (af <= 0 || af >= af_max()) + continue; + + if (first == 0 || af < first) + first = af; + + if (last == 0 || af > last) + last = af; + } + + assert((first == 0) == (last == 0)); + + if (first == 0) { + + /* No entries in the valid range, block everything */ + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EAFNOSUPPORT), + SCMP_SYS(socket), + 0); + if (r < 0) { + log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + + } else { + + /* Block everything below the first entry */ + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EAFNOSUPPORT), + SCMP_SYS(socket), + 1, + SCMP_A0(SCMP_CMP_LT, first)); + if (r < 0) { + log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + + /* Block everything above the last entry */ + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EAFNOSUPPORT), + SCMP_SYS(socket), + 1, + SCMP_A0(SCMP_CMP_GT, last)); + if (r < 0) { + log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + + /* Block everything between the first and last entry */ + for (af = 1; af < af_max(); af++) { + + if (set_contains(address_families, INT_TO_PTR(af))) + continue; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EAFNOSUPPORT), + SCMP_SYS(socket), + 1, + SCMP_A0(SCMP_CMP_EQ, af)); + if (r < 0) + break; + } + if (r < 0) { + log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + } + + } else { + void *af; + + /* If this is a blacklist, then generate one rule for + * each address family that are then combined in OR + * checks. */ + + SET_FOREACH(af, address_families, i) { + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EAFNOSUPPORT), + SCMP_SYS(socket), + 1, + SCMP_A0(SCMP_CMP_EQ, PTR_TO_INT(af))); + if (r < 0) + break; + } + if (r < 0) { + log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + } + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to install socket family rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +int seccomp_restrict_realtime(void) { + static const int permitted_policies[] = { + SCHED_OTHER, + SCHED_BATCH, + SCHED_IDLE, + }; + + int r, max_policy = 0; + uint32_t arch; + unsigned i; + + /* Determine the highest policy constant we want to allow */ + for (i = 0; i < ELEMENTSOF(permitted_policies); i++) + if (permitted_policies[i] > max_policy) + max_policy = permitted_policies[i]; + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + int p; + + log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); + if (r < 0) + return r; + + /* Go through all policies with lower values than that, and block them -- unless they appear in the + * whitelist. */ + for (p = 0; p < max_policy; p++) { + bool good = false; + + /* Check if this is in the whitelist. */ + for (i = 0; i < ELEMENTSOF(permitted_policies); i++) + if (permitted_policies[i] == p) { + good = true; + break; + } + + if (good) + continue; + + /* Deny this policy */ + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(sched_setscheduler), + 1, + SCMP_A1(SCMP_CMP_EQ, p)); + if (r < 0) { + log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + } + + /* Blacklist all other policies, i.e. the ones with higher values. Note that all comparisons are + * unsigned here, hence no need no check for < 0 values. */ + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(sched_setscheduler), + 1, + SCMP_A1(SCMP_CMP_GT, max_policy)); + if (r < 0) { + log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to install realtime protection rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +static int add_seccomp_syscall_filter(scmp_filter_ctx seccomp, + uint32_t arch, + int nr, + unsigned arg_cnt, + const struct scmp_arg_cmp arg) { + int r; + + r = seccomp_rule_add_exact(seccomp, SCMP_ACT_ERRNO(EPERM), nr, arg_cnt, arg); + if (r < 0) { + _cleanup_free_ char *n = NULL; + + n = seccomp_syscall_resolve_num_arch(arch, nr); + log_debug_errno(r, "Failed to add %s() rule for architecture %s, skipping: %m", + strna(n), + seccomp_arch_to_string(arch)); + } + + return r; +} + +/* For known architectures, check that syscalls are indeed defined or not. */ +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) +assert_cc(SCMP_SYS(shmget) > 0); +assert_cc(SCMP_SYS(shmat) > 0); +assert_cc(SCMP_SYS(shmdt) > 0); +#endif + +int seccomp_memory_deny_write_execute(void) { + uint32_t arch; + int r; + int loaded = 0; + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + int filter_syscall = 0, block_syscall = 0, shmat_syscall = 0; + + log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); + + switch (arch) { + + /* Note that on some architectures shmat() isn't available, and the call is multiplexed through ipc(). + * We ignore that here, which means there's still a way to get writable/executable + * memory, if an IPC key is mapped like this. That's a pity, but no total loss. */ + + case SCMP_ARCH_X86: + case SCMP_ARCH_S390: + filter_syscall = SCMP_SYS(mmap2); + block_syscall = SCMP_SYS(mmap); + /* shmat multiplexed, see above */ + break; + + case SCMP_ARCH_PPC: + case SCMP_ARCH_PPC64: + case SCMP_ARCH_PPC64LE: + case SCMP_ARCH_S390X: + filter_syscall = SCMP_SYS(mmap); + /* shmat multiplexed, see above */ + break; + + case SCMP_ARCH_ARM: + filter_syscall = SCMP_SYS(mmap2); /* arm has only mmap2 */ + shmat_syscall = SCMP_SYS(shmat); + break; + + case SCMP_ARCH_X86_64: + case SCMP_ARCH_X32: + case SCMP_ARCH_AARCH64: + filter_syscall = SCMP_SYS(mmap); /* amd64, x32 and arm64 have only mmap */ + shmat_syscall = SCMP_SYS(shmat); + break; + + /* Please add more definitions here, if you port systemd to other architectures! */ + +#if !defined(__i386__) && !defined(__x86_64__) && !defined(__powerpc__) && !defined(__powerpc64__) && !defined(__arm__) && !defined(__aarch64__) && !defined(__s390__) && !defined(__s390x__) +#warning "Consider adding the right mmap() syscall definitions here!" +#endif + } + + /* Can't filter mmap() on this arch, then skip it */ + if (filter_syscall == 0) + continue; + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); + if (r < 0) + return r; + + r = add_seccomp_syscall_filter(seccomp, arch, filter_syscall, + 1, + SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC|PROT_WRITE, PROT_EXEC|PROT_WRITE)); + if (r < 0) + continue; + + if (block_syscall != 0) { + r = add_seccomp_syscall_filter(seccomp, arch, block_syscall, 0, (const struct scmp_arg_cmp){} ); + if (r < 0) + continue; + } + + r = add_seccomp_syscall_filter(seccomp, arch, SCMP_SYS(mprotect), + 1, + SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC)); + if (r < 0) + continue; + +#ifdef __NR_pkey_mprotect + r = add_seccomp_syscall_filter(seccomp, arch, SCMP_SYS(pkey_mprotect), + 1, + SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC)); + if (r < 0) + continue; +#endif + + if (shmat_syscall > 0) { + r = add_seccomp_syscall_filter(seccomp, arch, shmat_syscall, + 1, + SCMP_A2(SCMP_CMP_MASKED_EQ, SHM_EXEC, SHM_EXEC)); + if (r < 0) + continue; + } + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to install MemoryDenyWriteExecute= rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + loaded++; + } + + if (loaded == 0) + log_debug_errno(r, "Failed to install any seccomp rules for MemoryDenyWriteExecute="); + + return loaded; +} + +int seccomp_restrict_archs(Set *archs) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + Iterator i; + void *id; + int r; + + /* This installs a filter with no rules, but that restricts the system call architectures to the specified + * list. + * + * There are some qualifications. However the most important use is to stop processes from bypassing + * system call restrictions, in case they used a broader (multiplexing) syscall which is only available + * in a non-native architecture. There are no holes in this use case, at least so far. */ + + /* Note libseccomp includes our "native" (current) architecture in the filter by default. + * We do not remove it. For example, our callers expect to be able to call execve() afterwards + * to run a program with the restrictions applied. */ + seccomp = seccomp_init(SCMP_ACT_ALLOW); + if (!seccomp) + return -ENOMEM; + + SET_FOREACH(id, archs, i) { + r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1); + if (r < 0 && r != -EEXIST) + return r; + } + + /* The vdso for x32 assumes that x86-64 syscalls are available. Let's allow them, since x32 + * x32 syscalls should basically match x86-64 for everything except the pointer type. + * The important thing is that you can block the old 32-bit x86 syscalls. + * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=850047 */ + + if (seccomp_arch_native() == SCMP_ARCH_X32 || + set_contains(archs, UINT32_TO_PTR(SCMP_ARCH_X32 + 1))) { + + r = seccomp_arch_add(seccomp, SCMP_ARCH_X86_64); + if (r < 0 && r != -EEXIST) + return r; + } + + r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); + if (r < 0) + return r; + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to restrict system call architectures, skipping: %m"); + + return 0; +} + +int parse_syscall_archs(char **l, Set **archs) { + _cleanup_set_free_ Set *_archs; + char **s; + int r; + + assert(l); + assert(archs); + + r = set_ensure_allocated(&_archs, NULL); + if (r < 0) + return r; + + STRV_FOREACH(s, l) { + uint32_t a; + + r = seccomp_arch_from_string(*s, &a); + if (r < 0) + return -EINVAL; + + r = set_put(_archs, UINT32_TO_PTR(a + 1)); + if (r < 0) + return -ENOMEM; + } + + *archs = TAKE_PTR(_archs); + + return 0; +} + +int seccomp_filter_set_add(Hashmap *filter, bool add, const SyscallFilterSet *set) { + const char *i; + int r; + + assert(set); + + NULSTR_FOREACH(i, set->value) { + + if (i[0] == '@') { + const SyscallFilterSet *more; + + more = syscall_filter_set_find(i); + if (!more) + return -ENXIO; + + r = seccomp_filter_set_add(filter, add, more); + if (r < 0) + return r; + } else { + int id; + + id = seccomp_syscall_resolve_name(i); + if (id == __NR_SCMP_ERROR) { + log_debug("Couldn't resolve system call, ignoring: %s", i); + continue; + } + + if (add) { + r = hashmap_put(filter, INT_TO_PTR(id + 1), INT_TO_PTR(-1)); + if (r < 0) + return r; + } else + (void) hashmap_remove(filter, INT_TO_PTR(id + 1)); + } + } + + return 0; +} + +int seccomp_lock_personality(unsigned long personality) { + uint32_t arch; + int r; + + if (personality >= PERSONALITY_INVALID) + return -EINVAL; + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); + if (r < 0) + return r; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(personality), + 1, + SCMP_A0(SCMP_CMP_NE, personality)); + if (r < 0) { + log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to enable personality lock for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +int seccomp_protect_hostname(void) { + uint32_t arch; + int r; + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); + if (r < 0) + return r; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(sethostname), + 0); + if (r < 0) { + log_debug_errno(r, "Failed to add sethostname() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(setdomainname), + 0); + if (r < 0) { + log_debug_errno(r, "Failed to add setdomainname() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + continue; + } + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to apply hostname restrictions for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) { + /* Checks the mode_t parameter of the following system calls: + * + * → chmod() + fchmod() + fchmodat() + * → open() + creat() + openat() + * → mkdir() + mkdirat() + * → mknod() + mknodat() + * + * Returns error if *everything* failed, and 0 otherwise. + */ + int r = 0; + bool any = false; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(chmod), + 1, + SCMP_A1(SCMP_CMP_MASKED_EQ, m, m)); + if (r < 0) + log_debug_errno(r, "Failed to add filter for chmod: %m"); + else + any = true; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(fchmod), + 1, + SCMP_A1(SCMP_CMP_MASKED_EQ, m, m)); + if (r < 0) + log_debug_errno(r, "Failed to add filter for fchmod: %m"); + else + any = true; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(fchmodat), + 1, + SCMP_A2(SCMP_CMP_MASKED_EQ, m, m)); + if (r < 0) + log_debug_errno(r, "Failed to add filter for fchmodat: %m"); + else + any = true; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(mkdir), + 1, + SCMP_A1(SCMP_CMP_MASKED_EQ, m, m)); + if (r < 0) + log_debug_errno(r, "Failed to add filter for mkdir: %m"); + else + any = true; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(mkdirat), + 1, + SCMP_A2(SCMP_CMP_MASKED_EQ, m, m)); + if (r < 0) + log_debug_errno(r, "Failed to add filter for mkdirat: %m"); + else + any = true; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(mknod), + 1, + SCMP_A1(SCMP_CMP_MASKED_EQ, m, m)); + if (r < 0) + log_debug_errno(r, "Failed to add filter for mknod: %m"); + else + any = true; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(mknodat), + 1, + SCMP_A2(SCMP_CMP_MASKED_EQ, m, m)); + if (r < 0) + log_debug_errno(r, "Failed to add filter for mknodat: %m"); + else + any = true; + +#if SCMP_SYS(open) > 0 + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(open), + 2, + SCMP_A1(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT), + SCMP_A2(SCMP_CMP_MASKED_EQ, m, m)); + if (r < 0) + log_debug_errno(r, "Failed to add filter for open: %m"); + else + any = true; +#endif + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(openat), + 2, + SCMP_A2(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT), + SCMP_A3(SCMP_CMP_MASKED_EQ, m, m)); + if (r < 0) + log_debug_errno(r, "Failed to add filter for openat: %m"); + else + any = true; + + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), + SCMP_SYS(creat), + 1, + SCMP_A1(SCMP_CMP_MASKED_EQ, m, m)); + if (r < 0) + log_debug_errno(r, "Failed to add filter for creat: %m"); + else + any = true; + + return any ? 0 : r; +} + +int seccomp_restrict_suid_sgid(void) { + uint32_t arch; + int r, k; + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; + + r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW); + if (r < 0) + return r; + + r = seccomp_restrict_sxid(seccomp, S_ISUID); + if (r < 0) + log_debug_errno(r, "Failed to add suid rule for architecture %s, ignoring: %m", seccomp_arch_to_string(arch)); + + k = seccomp_restrict_sxid(seccomp, S_ISGID); + if (k < 0) + log_debug_errno(r, "Failed to add sgid rule for architecture %s, ignoring: %m", seccomp_arch_to_string(arch)); + + if (r < 0 && k < 0) + continue; + + r = seccomp_load(seccomp); + if (ERRNO_IS_SECCOMP_FATAL(r)) + return r; + if (r < 0) + log_debug_errno(r, "Failed to apply suid/sgid restrictions for architecture %s, skipping: %m", seccomp_arch_to_string(arch)); + } + + return 0; +} + +uint32_t scmp_act_kill_process(void) { + + /* Returns SCMP_ACT_KILL_PROCESS if it's supported, and SCMP_ACT_KILL_THREAD otherwise. We never + * actually want to use SCMP_ACT_KILL_THREAD as its semantics are nuts (killing arbitrary threads of + * a program is just a bad idea), but on old kernels/old libseccomp it is all we have, and at least + * for single-threaded apps does the right thing. */ + +#ifdef SCMP_ACT_KILL_PROCESS + if (seccomp_api_get() >= 3) + return SCMP_ACT_KILL_PROCESS; +#endif + + return SCMP_ACT_KILL; /* same as SCMP_ACT_KILL_THREAD */ +} diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h new file mode 100644 index 00000000..0b48e74a --- /dev/null +++ b/src/shared/seccomp-util.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include +#include + +#include "set.h" + +const char* seccomp_arch_to_string(uint32_t c); +int seccomp_arch_from_string(const char *n, uint32_t *ret); + +int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_action); + +bool is_seccomp_available(void); + +typedef struct SyscallFilterSet { + const char *name; + const char *help; + const char *value; +} SyscallFilterSet; + +enum { + /* Please leave DEFAULT first, but sort the rest alphabetically */ + SYSCALL_FILTER_SET_DEFAULT, + SYSCALL_FILTER_SET_AIO, + SYSCALL_FILTER_SET_BASIC_IO, + SYSCALL_FILTER_SET_CHOWN, + SYSCALL_FILTER_SET_CLOCK, + SYSCALL_FILTER_SET_CPU_EMULATION, + SYSCALL_FILTER_SET_DEBUG, + SYSCALL_FILTER_SET_FILE_SYSTEM, + SYSCALL_FILTER_SET_IO_EVENT, + SYSCALL_FILTER_SET_IPC, + SYSCALL_FILTER_SET_KEYRING, + SYSCALL_FILTER_SET_MEMLOCK, + SYSCALL_FILTER_SET_MODULE, + SYSCALL_FILTER_SET_MOUNT, + SYSCALL_FILTER_SET_NETWORK_IO, + SYSCALL_FILTER_SET_OBSOLETE, + SYSCALL_FILTER_SET_PKEY, + SYSCALL_FILTER_SET_PRIVILEGED, + SYSCALL_FILTER_SET_PROCESS, + SYSCALL_FILTER_SET_RAW_IO, + SYSCALL_FILTER_SET_REBOOT, + SYSCALL_FILTER_SET_RESOURCES, + SYSCALL_FILTER_SET_SETUID, + SYSCALL_FILTER_SET_SIGNAL, + SYSCALL_FILTER_SET_SWAP, + SYSCALL_FILTER_SET_SYNC, + SYSCALL_FILTER_SET_SYSTEM_SERVICE, + SYSCALL_FILTER_SET_TIMER, + _SYSCALL_FILTER_SET_MAX +}; + +extern const SyscallFilterSet syscall_filter_sets[]; + +const SyscallFilterSet *syscall_filter_set_find(const char *name); + +int seccomp_filter_set_add(Hashmap *s, bool b, const SyscallFilterSet *set); + +int seccomp_add_syscall_filter_item(scmp_filter_ctx *ctx, const char *name, uint32_t action, char **exclude, bool log_missing); + +int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action, bool log_missing); +int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action, bool log_missing); + +typedef enum SeccompParseFlags { + SECCOMP_PARSE_INVERT = 1 << 0, + SECCOMP_PARSE_WHITELIST = 1 << 1, + SECCOMP_PARSE_LOG = 1 << 2, + SECCOMP_PARSE_PERMISSIVE = 1 << 3, +} SeccompParseFlags; + +int seccomp_parse_syscall_filter( + const char *name, + int errno_num, + Hashmap *filter, + SeccompParseFlags flags, + const char *unit, + const char *filename, unsigned line); + +int seccomp_restrict_archs(Set *archs); +int seccomp_restrict_namespaces(unsigned long retain); +int seccomp_protect_sysctl(void); +int seccomp_protect_syslog(void); +int seccomp_restrict_address_families(Set *address_families, bool whitelist); +int seccomp_restrict_realtime(void); +int seccomp_memory_deny_write_execute(void); +int seccomp_lock_personality(unsigned long personality); +int seccomp_protect_hostname(void); +int seccomp_restrict_suid_sgid(void); + +extern const uint32_t seccomp_local_archs[]; + +#define SECCOMP_FOREACH_LOCAL_ARCH(arch) \ + for (unsigned _i = ({ (arch) = seccomp_local_archs[0]; 0; }); \ + seccomp_local_archs[_i] != (uint32_t) -1; \ + (arch) = seccomp_local_archs[++_i]) + +/* EACCES: does not have the CAP_SYS_ADMIN or no_new_privs == 1 + * ENOMEM: out of memory, failed to allocate space for a libseccomp structure, or would exceed a defined constant + * EFAULT: addresses passed as args (by libseccomp) are invalid */ +#define ERRNO_IS_SECCOMP_FATAL(r) \ + IN_SET(abs(r), EPERM, EACCES, ENOMEM, EFAULT) + +DEFINE_TRIVIAL_CLEANUP_FUNC(scmp_filter_ctx, seccomp_release); + +int parse_syscall_archs(char **l, Set **archs); + +uint32_t scmp_act_kill_process(void); diff --git a/src/shared/securebits-util.c b/src/shared/securebits-util.c new file mode 100644 index 00000000..b2abaf4f --- /dev/null +++ b/src/shared/securebits-util.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "extract-word.h" +#include "securebits-util.h" +#include "string-util.h" + +int secure_bits_to_string_alloc(int i, char **s) { + _cleanup_free_ char *str = NULL; + size_t len; + int r; + + assert(s); + + r = asprintf(&str, "%s%s%s%s%s%s", + (i & (1 << SECURE_KEEP_CAPS)) ? "keep-caps " : "", + (i & (1 << SECURE_KEEP_CAPS_LOCKED)) ? "keep-caps-locked " : "", + (i & (1 << SECURE_NO_SETUID_FIXUP)) ? "no-setuid-fixup " : "", + (i & (1 << SECURE_NO_SETUID_FIXUP_LOCKED)) ? "no-setuid-fixup-locked " : "", + (i & (1 << SECURE_NOROOT)) ? "noroot " : "", + (i & (1 << SECURE_NOROOT_LOCKED)) ? "noroot-locked " : ""); + if (r < 0) + return -ENOMEM; + + len = strlen(str); + if (len != 0) + str[len - 1] = '\0'; + + *s = TAKE_PTR(str); + + return 0; +} + +int secure_bits_from_string(const char *s) { + int secure_bits = 0; + const char *p; + int r; + + for (p = s;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + if (r == -ENOMEM) + return r; + if (r <= 0) + break; + + if (streq(word, "keep-caps")) + secure_bits |= 1 << SECURE_KEEP_CAPS; + else if (streq(word, "keep-caps-locked")) + secure_bits |= 1 << SECURE_KEEP_CAPS_LOCKED; + else if (streq(word, "no-setuid-fixup")) + secure_bits |= 1 << SECURE_NO_SETUID_FIXUP; + else if (streq(word, "no-setuid-fixup-locked")) + secure_bits |= 1 << SECURE_NO_SETUID_FIXUP_LOCKED; + else if (streq(word, "noroot")) + secure_bits |= 1 << SECURE_NOROOT; + else if (streq(word, "noroot-locked")) + secure_bits |= 1 << SECURE_NOROOT_LOCKED; + } + + return secure_bits; +} diff --git a/src/shared/securebits-util.h b/src/shared/securebits-util.h new file mode 100644 index 00000000..b5ec6ee0 --- /dev/null +++ b/src/shared/securebits-util.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "missing_securebits.h" + +int secure_bits_to_string_alloc(int i, char **s); +int secure_bits_from_string(const char *s); + +static inline bool secure_bits_is_valid(int i) { + return ((SECURE_ALL_BITS | SECURE_ALL_LOCKS) & i) == i; +} + +static inline int secure_bits_to_string_alloc_with_check(int n, char **s) { + if (!secure_bits_is_valid(n)) + return -EINVAL; + + return secure_bits_to_string_alloc(n, s); +} diff --git a/src/shared/serialize.c b/src/shared/serialize.c new file mode 100644 index 00000000..00b70a77 --- /dev/null +++ b/src/shared/serialize.c @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "env-util.h" +#include "escape.h" +#include "fileio.h" +#include "missing_mman.h" +#include "missing_syscall.h" +#include "parse-util.h" +#include "process-util.h" +#include "serialize.h" +#include "strv.h" +#include "tmpfile-util.h" + +int serialize_item(FILE *f, const char *key, const char *value) { + assert(f); + assert(key); + + if (!value) + return 0; + + /* Make sure that anything we serialize we can also read back again with read_line() with a maximum line size + * of LONG_LINE_MAX. This is a safety net only. All code calling us should filter this out earlier anyway. */ + if (strlen(key) + 1 + strlen(value) + 1 > LONG_LINE_MAX) { + log_warning("Attempted to serialize overly long item '%s', refusing.", key); + return -EINVAL; + } + + fputs(key, f); + fputc('=', f); + fputs(value, f); + fputc('\n', f); + + return 1; +} + +int serialize_item_escaped(FILE *f, const char *key, const char *value) { + _cleanup_free_ char *c = NULL; + + assert(f); + assert(key); + + if (!value) + return 0; + + c = cescape(value); + if (!c) + return log_oom(); + + return serialize_item(f, key, c); +} + +int serialize_item_format(FILE *f, const char *key, const char *format, ...) { + char buf[LONG_LINE_MAX]; + va_list ap; + int k; + + assert(f); + assert(key); + assert(format); + + va_start(ap, format); + k = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + if (k < 0 || (size_t) k >= sizeof(buf) || strlen(key) + 1 + k + 1 > LONG_LINE_MAX) { + log_warning("Attempted to serialize overly long item '%s', refusing.", key); + return -EINVAL; + } + + fputs(key, f); + fputc('=', f); + fputs(buf, f); + fputc('\n', f); + + return 1; +} + +int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd) { + int copy; + + assert(f); + assert(key); + + if (fd < 0) + return 0; + + copy = fdset_put_dup(fds, fd); + if (copy < 0) + return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m"); + + return serialize_item_format(f, key, "%i", copy); +} + +int serialize_usec(FILE *f, const char *key, usec_t usec) { + assert(f); + assert(key); + + if (usec == USEC_INFINITY) + return 0; + + return serialize_item_format(f, key, USEC_FMT, usec); +} + +int serialize_dual_timestamp(FILE *f, const char *name, const dual_timestamp *t) { + assert(f); + assert(name); + assert(t); + + if (!dual_timestamp_is_set(t)) + return 0; + + return serialize_item_format(f, name, USEC_FMT " " USEC_FMT, t->realtime, t->monotonic); +} + +int serialize_strv(FILE *f, const char *key, char **l) { + int ret = 0, r; + char **i; + + /* Returns the first error, or positive if anything was serialized, 0 otherwise. */ + + STRV_FOREACH(i, l) { + r = serialize_item_escaped(f, key, *i); + if ((ret >= 0 && r < 0) || + (ret == 0 && r > 0)) + ret = r; + } + + return ret; +} + +int deserialize_usec(const char *value, usec_t *ret) { + int r; + + assert(value); + + r = safe_atou64(value, ret); + if (r < 0) + return log_debug_errno(r, "Failed to parse usec value \"%s\": %m", value); + + return 0; +} + +int deserialize_dual_timestamp(const char *value, dual_timestamp *t) { + uint64_t a, b; + int r, pos; + + assert(value); + assert(t); + + pos = strspn(value, WHITESPACE); + if (value[pos] == '-') + return -EINVAL; + pos += strspn(value + pos, DIGITS); + pos += strspn(value + pos, WHITESPACE); + if (value[pos] == '-') + return -EINVAL; + + r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos); + if (r != 2) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse dual timestamp value \"%s\".", + value); + + if (value[pos] != '\0') + /* trailing garbage */ + return -EINVAL; + + t->realtime = a; + t->monotonic = b; + + return 0; +} + +int deserialize_environment(const char *value, char ***list) { + _cleanup_free_ char *unescaped = NULL; + int r; + + assert(value); + assert(list); + + /* Changes the *environment strv inline. */ + + r = cunescape(value, 0, &unescaped); + if (r < 0) + return log_error_errno(r, "Failed to unescape: %m"); + + r = strv_env_replace(list, unescaped); + if (r < 0) + return log_error_errno(r, "Failed to append environment variable: %m"); + + unescaped = NULL; /* now part of 'list' */ + return 0; +} + +int open_serialization_fd(const char *ident) { + int fd; + + fd = memfd_create(ident, MFD_CLOEXEC); + if (fd < 0) { + const char *path; + + path = getpid_cached() == 1 ? "/run/systemd" : "/tmp"; + fd = open_tmpfile_unlinkable(path, O_RDWR|O_CLOEXEC); + if (fd < 0) + return fd; + + log_debug("Serializing %s to %s.", ident, path); + } else + log_debug("Serializing %s to memfd.", ident); + + return fd; +} diff --git a/src/shared/serialize.h b/src/shared/serialize.h new file mode 100644 index 00000000..9e61c825 --- /dev/null +++ b/src/shared/serialize.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "fdset.h" +#include "macro.h" +#include "string-util.h" +#include "time-util.h" + +int serialize_item(FILE *f, const char *key, const char *value); +int serialize_item_escaped(FILE *f, const char *key, const char *value); +int serialize_item_format(FILE *f, const char *key, const char *value, ...) _printf_(3,4); +int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd); +int serialize_usec(FILE *f, const char *key, usec_t usec); +int serialize_dual_timestamp(FILE *f, const char *key, const dual_timestamp *t); +int serialize_strv(FILE *f, const char *key, char **l); + +static inline int serialize_bool(FILE *f, const char *key, bool b) { + return serialize_item(f, key, yes_no(b)); +} + +int deserialize_usec(const char *value, usec_t *timestamp); +int deserialize_dual_timestamp(const char *value, dual_timestamp *t); +int deserialize_environment(const char *value, char ***environment); + +int open_serialization_fd(const char *ident); diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c new file mode 100644 index 00000000..754a63c2 --- /dev/null +++ b/src/shared/sleep-config.c @@ -0,0 +1,638 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2018 Dell Inc. +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "btrfs-util.h" +#include "conf-parser.h" +#include "def.h" +#include "env-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "macro.h" +#include "parse-util.h" +#include "path-util.h" +#include "sleep-config.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" + +int parse_sleep_config(SleepConfig **ret_sleep_config) { + _cleanup_(free_sleep_configp) SleepConfig *sc; + int allow_suspend = -1, allow_hibernate = -1, + allow_s2h = -1, allow_hybrid_sleep = -1; + + sc = new0(SleepConfig, 1); + if (!sc) + return log_oom(); + + const ConfigTableItem items[] = { + { "Sleep", "AllowSuspend", config_parse_tristate, 0, &allow_suspend }, + { "Sleep", "AllowHibernation", config_parse_tristate, 0, &allow_hibernate }, + { "Sleep", "AllowSuspendThenHibernate", config_parse_tristate, 0, &allow_s2h }, + { "Sleep", "AllowHybridSleep", config_parse_tristate, 0, &allow_hybrid_sleep }, + + { "Sleep", "SuspendMode", config_parse_strv, 0, &sc->suspend_modes }, + { "Sleep", "SuspendState", config_parse_strv, 0, &sc->suspend_states }, + { "Sleep", "HibernateMode", config_parse_strv, 0, &sc->hibernate_modes }, + { "Sleep", "HibernateState", config_parse_strv, 0, &sc->hibernate_states }, + { "Sleep", "HybridSleepMode", config_parse_strv, 0, &sc->hybrid_modes }, + { "Sleep", "HybridSleepState", config_parse_strv, 0, &sc->hybrid_states }, + + { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &sc->hibernate_delay_sec}, + {} + }; + + (void) config_parse_many_nulstr(PKGSYSCONFDIR "/sleep.conf", + CONF_PATHS_NULSTR("systemd/sleep.conf.d"), + "Sleep\0", config_item_table_lookup, items, + CONFIG_PARSE_WARN, NULL); + + /* use default values unless set */ + sc->allow_suspend = allow_suspend != 0; + sc->allow_hibernate = allow_hibernate != 0; + sc->allow_hybrid_sleep = allow_hybrid_sleep >= 0 ? allow_hybrid_sleep + : (allow_suspend != 0 && allow_hibernate != 0); + sc->allow_s2h = allow_s2h >= 0 ? allow_s2h + : (allow_suspend != 0 && allow_hibernate != 0); + + if (!sc->suspend_states) + sc->suspend_states = strv_new("mem", "standby", "freeze"); + if (!sc->hibernate_modes) + sc->hibernate_modes = strv_new("platform", "shutdown"); + if (!sc->hibernate_states) + sc->hibernate_states = strv_new("disk"); + if (!sc->hybrid_modes) + sc->hybrid_modes = strv_new("suspend", "platform", "shutdown"); + if (!sc->hybrid_states) + sc->hybrid_states = strv_new("disk"); + if (sc->hibernate_delay_sec == 0) + sc->hibernate_delay_sec = 2 * USEC_PER_HOUR; + + /* ensure values set for all required fields */ + if (!sc->suspend_states || !sc->hibernate_modes + || !sc->hibernate_states || !sc->hybrid_modes || !sc->hybrid_states) + return log_oom(); + + *ret_sleep_config = TAKE_PTR(sc); + + return 0; +} + +int can_sleep_state(char **types) { + char **type; + int r; + _cleanup_free_ char *p = NULL; + + if (strv_isempty(types)) + return true; + + /* If /sys is read-only we cannot sleep */ + if (access("/sys/power/state", W_OK) < 0) + return false; + + r = read_one_line_file("/sys/power/state", &p); + if (r < 0) + return false; + + STRV_FOREACH(type, types) { + const char *word, *state; + size_t l, k; + + k = strlen(*type); + FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) + if (l == k && memcmp(word, *type, l) == 0) + return true; + } + + return false; +} + +int can_sleep_disk(char **types) { + char **type; + int r; + _cleanup_free_ char *p = NULL; + + if (strv_isempty(types)) + return true; + + /* If /sys is read-only we cannot sleep */ + if (access("/sys/power/disk", W_OK) < 0) { + log_debug_errno(errno, "/sys/power/disk is not writable: %m"); + return false; + } + + r = read_one_line_file("/sys/power/disk", &p); + if (r < 0) { + log_debug_errno(r, "Couldn't read /sys/power/disk: %m"); + return false; + } + + STRV_FOREACH(type, types) { + const char *word, *state; + size_t l, k; + + k = strlen(*type); + FOREACH_WORD_SEPARATOR(word, l, p, WHITESPACE, state) { + if (l == k && memcmp(word, *type, l) == 0) + return true; + + if (l == k + 2 && + word[0] == '[' && + memcmp(word + 1, *type, l - 2) == 0 && + word[l-1] == ']') + return true; + } + } + + return false; +} + +#define HIBERNATION_SWAP_THRESHOLD 0.98 + +SwapEntry* swap_entry_free(SwapEntry *se) { + if (!se) + return NULL; + + free(se->device); + free(se->type); + + return mfree(se); +} + +HibernateLocation* hibernate_location_free(HibernateLocation *hl) { + if (!hl) + return NULL; + + swap_entry_free(hl->swap); + free(hl->resume); + + return mfree(hl); +} + +static int swap_device_to_major_minor(const SwapEntry *swap, char **ret) { + _cleanup_free_ char *major_minor = NULL; + _cleanup_close_ int fd = -1; + struct stat sb; + dev_t swap_dev; + int r; + + assert(swap); + assert(swap->device); + assert(swap->type); + + fd = open(swap->device, O_RDONLY | O_CLOEXEC | O_NONBLOCK); + if (fd < 0) + return log_debug_errno(errno, "Unable to open '%s': %m", swap->device); + + r = fstat(fd, &sb); + if (r < 0) + return log_debug_errno(errno, "Unable to stat %s: %m", swap->device); + + swap_dev = streq(swap->type, "partition") ? sb.st_rdev : sb.st_dev; + if (asprintf(&major_minor, "%u:%u", major(swap_dev), minor(swap_dev)) < 0) + return log_oom(); + + *ret = TAKE_PTR(major_minor); + + return 0; +} + +static int calculate_swap_file_offset(const SwapEntry *swap, uint64_t *ret_offset) { + _cleanup_close_ int fd = -1; + _cleanup_free_ struct fiemap *fiemap = NULL; + struct stat sb; + int r, btrfs; + + assert(swap); + assert(swap->device); + assert(streq(swap->type, "file")); + + fd = open(swap->device, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return log_error_errno(errno, "Failed to open %s: %m", swap->device); + + if (fstat(fd, &sb) < 0) + return log_error_errno(errno, "Failed to stat %s: %m", swap->device); + + btrfs = btrfs_is_filesystem(fd); + if (btrfs < 0) + return log_error_errno(btrfs, "Error checking %s for Btrfs filesystem: %m", swap->device); + else if (btrfs > 0) { + log_debug("Detection of swap file offset on Btrfs is not supported: %s; skipping", swap->device); + *ret_offset = 0; + return 0; + } + + r = read_fiemap(fd, &fiemap); + if (r < 0) + return log_debug_errno(r, "Unable to read extent map for '%s': %m", swap->device); + + *ret_offset = fiemap->fm_extents[0].fe_physical / page_size(); + + return 0; +} + +static int read_resume_files(char **ret_resume, uint64_t *ret_resume_offset) { + _cleanup_free_ char *resume = NULL, *resume_offset_str = NULL; + uint64_t resume_offset = 0; + int r; + + r = read_one_line_file("/sys/power/resume", &resume); + if (r < 0) + return log_debug_errno(r, "Error reading /sys/power/resume: %m"); + + r = read_one_line_file("/sys/power/resume_offset", &resume_offset_str); + if (r == -ENOENT) + log_debug("Kernel does not support resume_offset; swap file offset detection will be skipped."); + else if (r < 0) + return log_debug_errno(r, "Error reading /sys/power/resume_offset: %m"); + else { + r = safe_atou64(resume_offset_str, &resume_offset); + if (r < 0) + return log_error_errno(r, "Failed to parse value in /sys/power/resume_offset \"%s\": %m", resume_offset_str); + } + + if (resume_offset > 0 && streq(resume, "0:0")) { + log_debug("Found offset in /sys/power/resume_offset: %" PRIu64 "; no device id found in /sys/power/resume; ignoring resume_offset", + resume_offset); + resume_offset = 0; + } + + *ret_resume = TAKE_PTR(resume); + *ret_resume_offset = resume_offset; + + return 0; +} + +static bool location_is_resume_device(const HibernateLocation *location, const char *sys_resume, const uint64_t sys_offset) { + assert(location); + assert(location->resume); + assert(sys_resume); + + return streq(sys_resume, location->resume) && sys_offset == location->resume_offset; +} + +/* + * Attempt to find the hibernation location by parsing /proc/swaps, /sys/power/resume, and + * /sys/power/resume_offset. + * + * Returns: + * 1 - HibernateLocation matches values found in /sys/power/resume & /sys/power/resume_offset + * 0 - HibernateLocation is highest priority swap with most remaining space; no valid values exist in /sys/power/resume & /sys/power/resume_offset + * negative value in the case of error + */ +int find_hibernate_location(HibernateLocation **ret_hibernate_location) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_(hibernate_location_freep) HibernateLocation *hibernate_location = NULL; + _cleanup_free_ char *sys_resume = NULL; + uint64_t sys_offset = 0; + unsigned i; + int r; + + /* read the /sys/power/resume & /sys/power/resume_offset values */ + r = read_resume_files(&sys_resume, &sys_offset); + if (r < 0) + return r; + + f = fopen("/proc/swaps", "re"); + if (!f) { + log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, + "Failed to open /proc/swaps: %m"); + return negative_errno(); + } + + (void) fscanf(f, "%*s %*s %*s %*s %*s\n"); + for (i = 1;; i++) { + _cleanup_(swap_entry_freep) SwapEntry *swap = NULL; + uint64_t swap_offset = 0; + int k; + + swap = new0(SwapEntry, 1); + if (!swap) + return log_oom(); + + k = fscanf(f, + "%ms " /* device/file */ + "%ms " /* type of swap */ + "%" PRIu64 /* swap size */ + "%" PRIu64 /* used */ + "%i\n", /* priority */ + &swap->device, &swap->type, &swap->size, &swap->used, &swap->priority); + if (k == EOF) + break; + if (k != 5) { + log_warning("Failed to parse /proc/swaps:%u", i); + continue; + } + + if (streq(swap->type, "file")) { + if (endswith(swap->device, "\\040(deleted)")) { + log_warning("Ignoring deleted swap file '%s'.", swap->device); + continue; + } + + r = calculate_swap_file_offset(swap, &swap_offset); + if (r < 0) + return r; + } else if (streq(swap->type, "partition")) { + const char *fn; + + fn = path_startswith(swap->device, "/dev/"); + if (fn && startswith(fn, "zram")) { + log_debug("Ignoring compressed RAM swap device '%s'.", swap->device); + continue; + } + } else { + log_debug("Swap type %s is unsupported for hibernation: %s; skipping", swap->type, swap->device); + continue; + } + + /* prefer resume device or highest priority swap with most remaining space */ + if (!hibernate_location || swap->priority > hibernate_location->swap->priority + || ((swap->priority == hibernate_location->swap->priority) + && (swap->size - swap->used) > (hibernate_location->swap->size - hibernate_location->swap->used))) { + + _cleanup_free_ char *swap_device_id = NULL; + r = swap_device_to_major_minor(swap, &swap_device_id); + if (r < 0) + return r; + + hibernate_location = hibernate_location_free(hibernate_location); + hibernate_location = new(HibernateLocation, 1); + if (!hibernate_location) + return log_oom(); + + *hibernate_location = (HibernateLocation) { + .resume = TAKE_PTR(swap_device_id), + .resume_offset = swap_offset, + .swap = TAKE_PTR(swap), + }; + + /* if the swap is the resume device, stop looping swaps */ + if (location_is_resume_device(hibernate_location, sys_resume, sys_offset)) + break; + } + } + + if (!hibernate_location) + return log_debug_errno(SYNTHETIC_ERRNO(ENOSYS), "No swap partitions or files were found"); + + if (!streq(sys_resume, "0:0") && !location_is_resume_device(hibernate_location, sys_resume, sys_offset)) + return log_warning_errno(SYNTHETIC_ERRNO(ENOSYS), "/sys/power/resume and /sys/power/resume_offset has no matching entry in /proc/swaps; Hibernation will fail: resume=%s, resume_offset=%" PRIu64, + sys_resume, sys_offset); + + log_debug("Hibernation will attempt to use swap entry with path: %s, device: %s, offset: %" PRIu64 ", priority: %i", + hibernate_location->swap->device, hibernate_location->resume, hibernate_location->resume_offset, hibernate_location->swap->priority); + + *ret_hibernate_location = TAKE_PTR(hibernate_location); + + if (location_is_resume_device(*ret_hibernate_location, sys_resume, sys_offset)) + return 1; + + return 0; +} + +static bool enough_swap_for_hibernation(void) { + _cleanup_free_ char *active = NULL; + _cleanup_(hibernate_location_freep) HibernateLocation *hibernate_location = NULL; + unsigned long long act = 0; + int r; + + if (getenv_bool("SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK") > 0) + return true; + + r = find_hibernate_location(&hibernate_location); + if (r < 0) + return false; + + r = get_proc_field("/proc/meminfo", "Active(anon)", WHITESPACE, &active); + if (r < 0) { + log_debug_errno(r, "Failed to retrieve Active(anon) from /proc/meminfo: %m"); + return false; + } + + r = safe_atollu(active, &act); + if (r < 0) { + log_debug_errno(r, "Failed to parse Active(anon) from /proc/meminfo: %s: %m", active); + return false; + } + + r = act <= (hibernate_location->swap->size - hibernate_location->swap->used) * HIBERNATION_SWAP_THRESHOLD; + log_debug("%s swap for hibernation, Active(anon)=%llu kB, size=%" PRIu64 " kB, used=%" PRIu64 " kB, threshold=%.2g%%", + r ? "Enough" : "Not enough", act, hibernate_location->swap->size, hibernate_location->swap->used, 100*HIBERNATION_SWAP_THRESHOLD); + + return r; +} + +int read_fiemap(int fd, struct fiemap **ret) { + _cleanup_free_ struct fiemap *fiemap = NULL, *result_fiemap = NULL; + struct stat statinfo; + uint32_t result_extents = 0; + uint64_t fiemap_start = 0, fiemap_length; + const size_t n_extra = DIV_ROUND_UP(sizeof(struct fiemap), sizeof(struct fiemap_extent)); + size_t fiemap_allocated = n_extra, result_fiemap_allocated = n_extra; + + if (fstat(fd, &statinfo) < 0) + return log_debug_errno(errno, "Cannot determine file size: %m"); + if (!S_ISREG(statinfo.st_mode)) + return -ENOTTY; + fiemap_length = statinfo.st_size; + + /* Zero this out in case we run on a file with no extents */ + fiemap = calloc(n_extra, sizeof(struct fiemap_extent)); + if (!fiemap) + return -ENOMEM; + + result_fiemap = malloc_multiply(n_extra, sizeof(struct fiemap_extent)); + if (!result_fiemap) + return -ENOMEM; + + /* XFS filesystem has incorrect implementation of fiemap ioctl and + * returns extents for only one block-group at a time, so we need + * to handle it manually, starting the next fiemap call from the end + * of the last extent + */ + while (fiemap_start < fiemap_length) { + *fiemap = (struct fiemap) { + .fm_start = fiemap_start, + .fm_length = fiemap_length, + .fm_flags = FIEMAP_FLAG_SYNC, + }; + + /* Find out how many extents there are */ + if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) + return log_debug_errno(errno, "Failed to read extents: %m"); + + /* Nothing to process */ + if (fiemap->fm_mapped_extents == 0) + break; + + /* Resize fiemap to allow us to read in the extents, result fiemap has to hold all + * the extents for the whole file. Add space for the initial struct fiemap. */ + if (!greedy_realloc0((void**) &fiemap, &fiemap_allocated, + n_extra + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent))) + return -ENOMEM; + + fiemap->fm_extent_count = fiemap->fm_mapped_extents; + fiemap->fm_mapped_extents = 0; + + if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) + return log_debug_errno(errno, "Failed to read extents: %m"); + + /* Resize result_fiemap to allow us to copy in the extents */ + if (!greedy_realloc((void**) &result_fiemap, &result_fiemap_allocated, + n_extra + result_extents + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent))) + return -ENOMEM; + + memcpy(result_fiemap->fm_extents + result_extents, + fiemap->fm_extents, + sizeof(struct fiemap_extent) * fiemap->fm_mapped_extents); + + result_extents += fiemap->fm_mapped_extents; + + /* Highly unlikely that it is zero */ + if (_likely_(fiemap->fm_mapped_extents > 0)) { + uint32_t i = fiemap->fm_mapped_extents - 1; + + fiemap_start = fiemap->fm_extents[i].fe_logical + + fiemap->fm_extents[i].fe_length; + + if (fiemap->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST) + break; + } + } + + memcpy(result_fiemap, fiemap, sizeof(struct fiemap)); + result_fiemap->fm_mapped_extents = result_extents; + *ret = TAKE_PTR(result_fiemap); + return 0; +} + +static int can_sleep_internal(const char *verb, bool check_allowed, const SleepConfig *sleep_config); + +static bool can_s2h(const SleepConfig *sleep_config) { + const char *p; + int r; + + if (!clock_supported(CLOCK_BOOTTIME_ALARM)) { + log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, + "CLOCK_BOOTTIME_ALARM is not supported"); + return false; + } + + FOREACH_STRING(p, "suspend", "hibernate") { + r = can_sleep_internal(p, false, sleep_config); + if (IN_SET(r, 0, -ENOSPC, -EADV)) { + log_debug("Unable to %s system.", p); + return false; + } + if (r < 0) + return log_debug_errno(r, "Failed to check if %s is possible: %m", p); + } + + return true; +} + +static int can_sleep_internal(const char *verb, bool check_allowed, const SleepConfig *sleep_config) { + bool allow; + char **modes = NULL, **states = NULL; + int r; + + assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")); + + r = sleep_settings(verb, sleep_config, &allow, &modes, &states); + if (r < 0) + return false; + + if (check_allowed && !allow) { + log_debug("Sleep mode \"%s\" is disabled by configuration.", verb); + return false; + } + + if (streq(verb, "suspend-then-hibernate")) + return can_s2h(sleep_config); + + if (!can_sleep_state(states) || !can_sleep_disk(modes)) + return false; + + if (streq(verb, "suspend")) + return true; + + if (!enough_swap_for_hibernation()) + return -ENOSPC; + + return true; +} + +int can_sleep(const char *verb) { + _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL; + int r; + + r = parse_sleep_config(&sleep_config); + if (r < 0) + return r; + + return can_sleep_internal(verb, true, sleep_config); +} + +int sleep_settings(const char *verb, const SleepConfig *sleep_config, bool *ret_allow, char ***ret_modes, char ***ret_states) { + + assert(verb); + assert(sleep_config); + assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")); + + if (streq(verb, "suspend")) { + *ret_allow = sleep_config->allow_suspend; + *ret_modes = sleep_config->suspend_modes; + *ret_states = sleep_config->suspend_states; + } else if (streq(verb, "hibernate")) { + *ret_allow = sleep_config->allow_hibernate; + *ret_modes = sleep_config->hibernate_modes; + *ret_states = sleep_config->hibernate_states; + } else if (streq(verb, "hybrid-sleep")) { + *ret_allow = sleep_config->allow_hybrid_sleep; + *ret_modes = sleep_config->hybrid_modes; + *ret_states = sleep_config->hybrid_states; + } else if (streq(verb, "suspend-then-hibernate")) { + *ret_allow = sleep_config->allow_s2h; + *ret_modes = *ret_states = NULL; + } + + /* suspend modes empty by default */ + if ((!ret_modes && !streq(verb, "suspend")) || !ret_states) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No modes or states set for %s; Check sleep.conf", verb); + + return 0; +} + +void free_sleep_config(SleepConfig *sc) { + if (!sc) + return; + + strv_free(sc->suspend_modes); + strv_free(sc->suspend_states); + + strv_free(sc->hibernate_modes); + strv_free(sc->hibernate_states); + + strv_free(sc->hybrid_modes); + strv_free(sc->hybrid_states); + + free(sc); +} diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h new file mode 100644 index 00000000..3d82ee8e --- /dev/null +++ b/src/shared/sleep-config.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include "time-util.h" + +typedef struct SleepConfig { + bool allow_suspend; /* AllowSuspend */ + bool allow_hibernate; /* AllowHibernation */ + bool allow_s2h; /* AllowSuspendThenHibernate */ + bool allow_hybrid_sleep; /* AllowHybridSleep */ + + char **suspend_modes; /* SuspendMode */ + char **suspend_states; /* SuspendState */ + char **hibernate_modes; /* HibernateMode */ + char **hibernate_states; /* HibernateState */ + char **hybrid_modes; /* HybridSleepMode */ + char **hybrid_states; /* HybridSleepState */ + + usec_t hibernate_delay_sec; /* HibernateDelaySec */ +} SleepConfig; + +void free_sleep_config(SleepConfig *sc); +DEFINE_TRIVIAL_CLEANUP_FUNC(SleepConfig*, free_sleep_config); + +/* entry in /proc/swaps */ +typedef struct SwapEntry { + char *device; + char *type; + uint64_t size; + uint64_t used; + int priority; +} SwapEntry; + +SwapEntry* swap_entry_free(SwapEntry *se); +DEFINE_TRIVIAL_CLEANUP_FUNC(SwapEntry*, swap_entry_free); + +/* + * represents values for /sys/power/resume & /sys/power/resume_offset + * and the matching /proc/swap entry. + */ +typedef struct HibernateLocation { + char *resume; + uint64_t resume_offset; + SwapEntry *swap; +} HibernateLocation; + +HibernateLocation* hibernate_location_free(HibernateLocation *hl); +DEFINE_TRIVIAL_CLEANUP_FUNC(HibernateLocation*, hibernate_location_free); + +int sleep_settings(const char *verb, const SleepConfig *sleep_config, bool *ret_allow, char ***ret_modes, char ***ret_states); + +int read_fiemap(int fd, struct fiemap **ret); +int parse_sleep_config(SleepConfig **sleep_config); +int find_hibernate_location(HibernateLocation **ret_hibernate_location); + +int can_sleep(const char *verb); +int can_sleep_disk(char **types); +int can_sleep_state(char **types); diff --git a/src/shared/spawn-ask-password-agent.c b/src/shared/spawn-ask-password-agent.c new file mode 100644 index 00000000..ddaebf0f --- /dev/null +++ b/src/shared/spawn-ask-password-agent.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "log.h" +#include "process-util.h" +#include "spawn-ask-password-agent.h" +#include "util.h" + +static pid_t agent_pid = 0; + +int ask_password_agent_open(void) { + int r; + + if (agent_pid > 0) + return 0; + + /* We check STDIN here, not STDOUT, since this is about input, + * not output */ + if (!isatty(STDIN_FILENO)) + return 0; + + if (!is_main_thread()) + return -EPERM; + + r = fork_agent("(sd-askpwagent)", + NULL, 0, + &agent_pid, + SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, + SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, "--watch", NULL); + if (r < 0) + return log_error_errno(r, "Failed to fork TTY ask password agent: %m"); + + return 1; +} + +void ask_password_agent_close(void) { + + if (agent_pid <= 0) + return; + + /* Inform agent that we are done */ + (void) kill_and_sigcont(agent_pid, SIGTERM); + (void) wait_for_terminate(agent_pid, NULL); + agent_pid = 0; +} + +int ask_password_agent_open_if_enabled(BusTransport transport, bool ask_password) { + + /* Open the ask password agent as a child process if necessary */ + + if (transport != BUS_TRANSPORT_LOCAL) + return 0; + + if (!ask_password) + return 0; + + return ask_password_agent_open(); +} diff --git a/src/shared/spawn-ask-password-agent.h b/src/shared/spawn-ask-password-agent.h new file mode 100644 index 00000000..97b12fe2 --- /dev/null +++ b/src/shared/spawn-ask-password-agent.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "bus-util.h" + +int ask_password_agent_open(void); +void ask_password_agent_close(void); + +int ask_password_agent_open_if_enabled(BusTransport transport, bool ask_password); diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c new file mode 100644 index 00000000..4d6c0cae --- /dev/null +++ b/src/shared/spawn-polkit-agent.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "fd-util.h" +#include "io-util.h" +#include "log.h" +#include "macro.h" +#include "process-util.h" +#include "spawn-polkit-agent.h" +#include "stdio-util.h" +#include "time-util.h" +#include "util.h" + +#if ENABLE_POLKIT +static pid_t agent_pid = 0; + +int polkit_agent_open(void) { + char notify_fd[DECIMAL_STR_MAX(int) + 1]; + int pipe_fd[2], r; + + if (agent_pid > 0) + return 0; + + /* Clients that run as root don't need to activate/query polkit */ + if (geteuid() == 0) + return 0; + + /* We check STDIN here, not STDOUT, since this is about input, not output */ + if (!isatty(STDIN_FILENO)) + return 0; + + if (!is_main_thread()) + return -EPERM; + + if (pipe2(pipe_fd, 0) < 0) + return -errno; + + xsprintf(notify_fd, "%i", pipe_fd[1]); + + r = fork_agent("(polkit-agent)", + &pipe_fd[1], 1, + &agent_pid, + POLKIT_AGENT_BINARY_PATH, + POLKIT_AGENT_BINARY_PATH, "--notify-fd", notify_fd, "--fallback", NULL); + + /* Close the writing side, because that's the one for the agent */ + safe_close(pipe_fd[1]); + + if (r < 0) + log_error_errno(r, "Failed to fork TTY ask password agent: %m"); + else + /* Wait until the agent closes the fd */ + fd_wait_for_event(pipe_fd[0], POLLHUP, USEC_INFINITY); + + safe_close(pipe_fd[0]); + + return r; +} + +void polkit_agent_close(void) { + + if (agent_pid <= 0) + return; + + /* Inform agent that we are done */ + (void) kill_and_sigcont(agent_pid, SIGTERM); + (void) wait_for_terminate(agent_pid, NULL); + agent_pid = 0; +} + +#else + +int polkit_agent_open(void) { + return 0; +} + +void polkit_agent_close(void) { +} + +#endif + +int polkit_agent_open_if_enabled(BusTransport transport, bool ask_password) { + + /* Open the polkit agent as a child process if necessary */ + + if (transport != BUS_TRANSPORT_LOCAL) + return 0; + + if (!ask_password) + return 0; + + return polkit_agent_open(); +} diff --git a/src/shared/spawn-polkit-agent.h b/src/shared/spawn-polkit-agent.h new file mode 100644 index 00000000..56b01759 --- /dev/null +++ b/src/shared/spawn-polkit-agent.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "bus-util.h" + +int polkit_agent_open(void); +void polkit_agent_close(void); + +int polkit_agent_open_if_enabled(BusTransport transport, bool ask_password); diff --git a/src/shared/specifier.c b/src/shared/specifier.c new file mode 100644 index 00000000..b036ff67 --- /dev/null +++ b/src/shared/specifier.c @@ -0,0 +1,299 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "hostname-util.h" +#include "macro.h" +#include "specifier.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" + +/* + * Generic infrastructure for replacing %x style specifiers in + * strings. Will call a callback for each replacement. + */ + +/* Any ASCII character or digit: our pool of potential specifiers, + * and "%" used for escaping. */ +#define POSSIBLE_SPECIFIERS ALPHANUMERICAL "%" + +int specifier_printf(const char *text, const Specifier table[], const void *userdata, char **_ret) { + size_t l, allocated = 0; + _cleanup_free_ char *ret = NULL; + char *t; + const char *f; + bool percent = false; + int r; + + assert(text); + assert(table); + + l = strlen(text); + if (!GREEDY_REALLOC(ret, allocated, l + 1)) + return -ENOMEM; + t = ret; + + for (f = text; *f; f++, l--) + if (percent) { + if (*f == '%') + *(t++) = '%'; + else { + const Specifier *i; + + for (i = table; i->specifier; i++) + if (i->specifier == *f) + break; + + if (i->lookup) { + _cleanup_free_ char *w = NULL; + size_t k, j; + + r = i->lookup(i->specifier, i->data, userdata, &w); + if (r < 0) + return r; + + j = t - ret; + k = strlen(w); + + if (!GREEDY_REALLOC(ret, allocated, j + k + l + 1)) + return -ENOMEM; + memcpy(ret + j, w, k); + t = ret + j + k; + } else if (strchr(POSSIBLE_SPECIFIERS, *f)) + /* Oops, an unknown specifier. */ + return -EBADSLT; + else { + *(t++) = '%'; + *(t++) = *f; + } + } + + percent = false; + } else if (*f == '%') + percent = true; + else + *(t++) = *f; + + /* If string ended with a stray %, also end with % */ + if (percent) + *(t++) = '%'; + *(t++) = 0; + + /* Try to deallocate unused bytes, but don't sweat it too much */ + if ((size_t)(t - ret) < allocated) { + t = realloc(ret, t - ret); + if (t) + ret = t; + } + + *_ret = TAKE_PTR(ret); + return 0; +} + +/* Generic handler for simple string replacements */ + +int specifier_string(char specifier, const void *data, const void *userdata, char **ret) { + char *n; + + n = strdup(strempty(data)); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; +} + +int specifier_machine_id(char specifier, const void *data, const void *userdata, char **ret) { + sd_id128_t id; + char *n; + int r; + + r = sd_id128_get_machine(&id); + if (r < 0) + return r; + + n = new(char, 33); + if (!n) + return -ENOMEM; + + *ret = sd_id128_to_string(id, n); + return 0; +} + +int specifier_boot_id(char specifier, const void *data, const void *userdata, char **ret) { + sd_id128_t id; + char *n; + int r; + + r = sd_id128_get_boot(&id); + if (r < 0) + return r; + + n = new(char, 33); + if (!n) + return -ENOMEM; + + *ret = sd_id128_to_string(id, n); + return 0; +} + +int specifier_host_name(char specifier, const void *data, const void *userdata, char **ret) { + char *n; + + n = gethostname_malloc(); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; +} + +int specifier_kernel_release(char specifier, const void *data, const void *userdata, char **ret) { + struct utsname uts; + char *n; + int r; + + r = uname(&uts); + if (r < 0) + return -errno; + + n = strdup(uts.release); + if (!n) + return -ENOMEM; + + *ret = n; + return 0; +} + +int specifier_group_name(char specifier, const void *data, const void *userdata, char **ret) { + char *t; + + t = gid_to_name(getgid()); + if (!t) + return -ENOMEM; + + *ret = t; + return 0; +} + +int specifier_group_id(char specifier, const void *data, const void *userdata, char **ret) { + if (asprintf(ret, UID_FMT, getgid()) < 0) + return -ENOMEM; + + return 0; +} + +int specifier_user_name(char specifier, const void *data, const void *userdata, char **ret) { + char *t; + + /* If we are UID 0 (root), this will not result in NSS, otherwise it might. This is good, as we want to be able + * to run this in PID 1, where our user ID is 0, but where NSS lookups are not allowed. + + * We don't use getusername_malloc() here, because we don't want to look at $USER, to remain consistent with + * specifer_user_id() below. + */ + + t = uid_to_name(getuid()); + if (!t) + return -ENOMEM; + + *ret = t; + return 0; +} + +int specifier_user_id(char specifier, const void *data, const void *userdata, char **ret) { + + if (asprintf(ret, UID_FMT, getuid()) < 0) + return -ENOMEM; + + return 0; +} + +int specifier_user_home(char specifier, const void *data, const void *userdata, char **ret) { + + /* On PID 1 (which runs as root) this will not result in NSS, + * which is good. See above */ + + return get_home_dir(ret); +} + +int specifier_user_shell(char specifier, const void *data, const void *userdata, char **ret) { + + /* On PID 1 (which runs as root) this will not result in NSS, + * which is good. See above */ + + return get_shell(ret); +} + +int specifier_tmp_dir(char specifier, const void *data, const void *userdata, char **ret) { + const char *p; + char *copy; + int r; + + r = tmp_dir(&p); + if (r < 0) + return r; + + copy = strdup(p); + if (!copy) + return -ENOMEM; + + *ret = copy; + return 0; +} + +int specifier_var_tmp_dir(char specifier, const void *data, const void *userdata, char **ret) { + const char *p; + char *copy; + int r; + + r = var_tmp_dir(&p); + if (r < 0) + return r; + + copy = strdup(p); + if (!copy) + return -ENOMEM; + + *ret = copy; + return 0; +} + +int specifier_escape_strv(char **l, char ***ret) { + char **z, **p, **q; + + assert(ret); + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + z = new(char*, strv_length(l)+1); + if (!z) + return -ENOMEM; + + for (p = l, q = z; *p; p++, q++) { + + *q = specifier_escape(*p); + if (!*q) { + strv_free(z); + return -ENOMEM; + } + } + + *q = NULL; + *ret = z; + + return 0; +} diff --git a/src/shared/specifier.h b/src/shared/specifier.h new file mode 100644 index 00000000..d0221ef7 --- /dev/null +++ b/src/shared/specifier.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "string-util.h" + +typedef int (*SpecifierCallback)(char specifier, const void *data, const void *userdata, char **ret); + +typedef struct Specifier { + const char specifier; + const SpecifierCallback lookup; + const void *data; +} Specifier; + +int specifier_printf(const char *text, const Specifier table[], const void *userdata, char **ret); + +int specifier_string(char specifier, const void *data, const void *userdata, char **ret); + +int specifier_machine_id(char specifier, const void *data, const void *userdata, char **ret); +int specifier_boot_id(char specifier, const void *data, const void *userdata, char **ret); +int specifier_host_name(char specifier, const void *data, const void *userdata, char **ret); +int specifier_kernel_release(char specifier, const void *data, const void *userdata, char **ret); + +int specifier_group_name(char specifier, const void *data, const void *userdata, char **ret); +int specifier_group_id(char specifier, const void *data, const void *userdata, char **ret); +int specifier_user_name(char specifier, const void *data, const void *userdata, char **ret); +int specifier_user_id(char specifier, const void *data, const void *userdata, char **ret); +int specifier_user_home(char specifier, const void *data, const void *userdata, char **ret); +int specifier_user_shell(char specifier, const void *data, const void *userdata, char **ret); + +int specifier_tmp_dir(char specifier, const void *data, const void *userdata, char **ret); +int specifier_var_tmp_dir(char specifier, const void *data, const void *userdata, char **ret); + +static inline char* specifier_escape(const char *string) { + return strreplace(string, "%", "%%"); +} + +int specifier_escape_strv(char **l, char ***ret); diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c new file mode 100644 index 00000000..bd89cb4e --- /dev/null +++ b/src/shared/switch-root.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "base-filesystem.h" +#include "fd-util.h" +#include "fs-util.h" +#include "log.h" +#include "missing_syscall.h" +#include "mkdir.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "switch-root.h" +#include "user-util.h" +#include "util.h" + +int switch_root(const char *new_root, + const char *old_root_after, /* path below the new root, where to place the old root after the transition */ + bool unmount_old_root, + unsigned long mount_flags) { /* MS_MOVE or MS_BIND */ + + _cleanup_free_ char *resolved_old_root_after = NULL; + _cleanup_close_ int old_root_fd = -1; + bool old_root_remove; + const char *i; + int r; + + assert(new_root); + assert(old_root_after); + + if (path_equal(new_root, "/")) + return 0; + + /* Check if we shall remove the contents of the old root */ + old_root_remove = in_initrd(); + if (old_root_remove) { + old_root_fd = open("/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY|O_DIRECTORY); + if (old_root_fd < 0) + return log_error_errno(errno, "Failed to open root directory: %m"); + } + + /* Determine where we shall place the old root after the transition */ + r = chase_symlinks(old_root_after, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &resolved_old_root_after, NULL); + if (r < 0) + return log_error_errno(r, "Failed to resolve %s/%s: %m", new_root, old_root_after); + if (r == 0) /* Doesn't exist yet. Let's create it */ + (void) mkdir_p_label(resolved_old_root_after, 0755); + + /* Work-around for kernel design: the kernel refuses MS_MOVE if any file systems are mounted MS_SHARED. Hence + * remount them MS_PRIVATE here as a work-around. + * + * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */ + if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0) + return log_error_errno(errno, "Failed to set \"/\" mount propagation to private: %m"); + + FOREACH_STRING(i, "/sys", "/dev", "/run", "/proc") { + _cleanup_free_ char *chased = NULL; + + r = chase_symlinks(i, new_root, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &chased, NULL); + if (r < 0) + return log_error_errno(r, "Failed to resolve %s/%s: %m", new_root, i); + if (r > 0) { + /* Already exists. Let's see if it is a mount point already. */ + r = path_is_mount_point(chased, NULL, 0); + if (r < 0) + return log_error_errno(r, "Failed to determine whether %s is a mount point: %m", chased); + if (r > 0) /* If it is already mounted, then do nothing */ + continue; + } else + /* Doesn't exist yet? */ + (void) mkdir_p_label(chased, 0755); + + if (mount(i, chased, NULL, mount_flags, NULL) < 0) + return log_error_errno(errno, "Failed to mount %s to %s: %m", i, chased); + } + + /* Do not fail if base_filesystem_create() fails. Not all switch roots are like base_filesystem_create() wants + * them to look like. They might even boot, if they are RO and don't have the FS layout. Just ignore the error + * and switch_root() nevertheless. */ + (void) base_filesystem_create(new_root, UID_INVALID, GID_INVALID); + + if (chdir(new_root) < 0) + return log_error_errno(errno, "Failed to change directory to %s: %m", new_root); + + /* We first try a pivot_root() so that we can umount the old root dir. In many cases (i.e. where rootfs is /), + * that's not possible however, and hence we simply overmount root */ + if (pivot_root(new_root, resolved_old_root_after) >= 0) { + + /* Immediately get rid of the old root, if detach_oldroot is set. + * Since we are running off it we need to do this lazily. */ + if (unmount_old_root) { + r = umount_recursive(old_root_after, MNT_DETACH); + if (r < 0) + log_warning_errno(r, "Failed to unmount old root directory tree, ignoring: %m"); + } + + } else if (mount(new_root, "/", NULL, MS_MOVE, NULL) < 0) + return log_error_errno(errno, "Failed to move %s to /: %m", new_root); + + if (chroot(".") < 0) + return log_error_errno(errno, "Failed to change root: %m"); + + if (chdir("/") < 0) + return log_error_errno(errno, "Failed to change directory: %m"); + + if (old_root_fd >= 0) { + struct stat rb; + + if (fstat(old_root_fd, &rb) < 0) + log_warning_errno(errno, "Failed to stat old root directory, leaving: %m"); + else + (void) rm_rf_children(TAKE_FD(old_root_fd), 0, &rb); /* takes possession of the dir fd, even on failure */ + } + + return 0; +} diff --git a/src/shared/switch-root.h b/src/shared/switch-root.h new file mode 100644 index 00000000..f4d48cb4 --- /dev/null +++ b/src/shared/switch-root.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot, unsigned long mountflags); diff --git a/src/shared/sysctl-util.c b/src/shared/sysctl-util.c new file mode 100644 index 00000000..8543dbd2 --- /dev/null +++ b/src/shared/sysctl-util.c @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "macro.h" +#include "path-util.h" +#include "string-util.h" +#include "sysctl-util.h" + +char *sysctl_normalize(char *s) { + char *n; + + n = strpbrk(s, "/."); + + /* If the first separator is a slash, the path is + * assumed to be normalized and slashes remain slashes + * and dots remains dots. */ + + if (n && *n == '.') + /* Dots become slashes and slashes become dots. Fun. */ + do { + if (*n == '.') + *n = '/'; + else + *n = '.'; + + n = strpbrk(n + 1, "/."); + } while (n); + + path_simplify(s, true); + + /* Kill the leading slash, but keep the first character of the string in the same place. */ + if (*s == '/' && *(s+1)) + memmove(s, s+1, strlen(s)); + + return s; +} + +int sysctl_write(const char *property, const char *value) { + char *p; + _cleanup_close_ int fd = -1; + + assert(property); + assert(value); + + log_debug("Setting '%s' to '%.*s'.", property, (int) strcspn(value, NEWLINE), value); + + p = strjoina("/proc/sys/", property); + fd = open(p, O_WRONLY|O_CLOEXEC); + if (fd < 0) + return -errno; + + if (!endswith(value, "\n")) + value = strjoina(value, "\n"); + + if (write(fd, value, strlen(value)) < 0) + return -errno; + + return 0; +} + +int sysctl_writef(const char *property, const char *format, ...) { + _cleanup_free_ char *v = NULL; + va_list ap; + int r; + + va_start(ap, format); + r = vasprintf(&v, format, ap); + va_end(ap); + + if (r < 0) + return -ENOMEM; + + return sysctl_write(property, v); +} + +int sysctl_write_ip_property(int af, const char *ifname, const char *property, const char *value) { + const char *p; + + assert(IN_SET(af, AF_INET, AF_INET6)); + assert(property); + assert(value); + + p = strjoina("/proc/sys/net/ipv", af == AF_INET ? "4" : "6", + ifname ? "/conf/" : "", strempty(ifname), + property[0] == '/' ? "" : "/", property); + + log_debug("Setting '%s' to '%s'", p, value); + + return write_string_file(p, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); +} + +int sysctl_read(const char *property, char **content) { + char *p; + + assert(property); + assert(content); + + p = strjoina("/proc/sys/", property); + return read_full_file(p, content, NULL); +} + +int sysctl_read_ip_property(int af, const char *ifname, const char *property, char **ret) { + _cleanup_free_ char *value = NULL; + const char *p; + int r; + + assert(IN_SET(af, AF_INET, AF_INET6)); + assert(property); + + p = strjoina("/proc/sys/net/ipv", af == AF_INET ? "4" : "6", + ifname ? "/conf/" : "", strempty(ifname), + property[0] == '/' ? "" : "/", property); + + r = read_one_line_file(p, &value); + if (r < 0) + return r; + + if (ret) + *ret = TAKE_PTR(value); + + return r; +} diff --git a/src/shared/sysctl-util.h b/src/shared/sysctl-util.h new file mode 100644 index 00000000..cb30a977 --- /dev/null +++ b/src/shared/sysctl-util.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "macro.h" +#include "stdio-util.h" +#include "util.h" + +char *sysctl_normalize(char *s); +int sysctl_read(const char *property, char **value); +int sysctl_write(const char *property, const char *value); +int sysctl_writef(const char *propery, const char *format, ...) _printf_(2, 3); + +int sysctl_read_ip_property(int af, const char *ifname, const char *property, char **ret); +int sysctl_write_ip_property(int af, const char *ifname, const char *property, const char *value); +static inline int sysctl_write_ip_property_boolean(int af, const char *ifname, const char *property, bool value) { + return sysctl_write_ip_property(af, ifname, property, one_zero(value)); +} + +#define DEFINE_SYSCTL_WRITE_IP_PROPERTY(name, type, format) \ + static inline int sysctl_write_ip_property_##name(int af, const char *ifname, const char *property, type value) { \ + char buf[DECIMAL_STR_MAX(type)]; \ + xsprintf(buf, format, value); \ + return sysctl_write_ip_property(af, ifname, property, buf); \ + } + +DEFINE_SYSCTL_WRITE_IP_PROPERTY(int, int, "%i"); +DEFINE_SYSCTL_WRITE_IP_PROPERTY(uint32, uint32_t, "%" PRIu32); diff --git a/src/shared/test-tables.h b/src/shared/test-tables.h new file mode 100644 index 00000000..4eeda3b1 --- /dev/null +++ b/src/shared/test-tables.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +typedef const char* (*lookup_t)(int); +typedef int (*reverse_t)(const char*); + +static inline void _test_table(const char *name, + lookup_t lookup, + reverse_t reverse, + int size, + bool sparse) { + int i, boring = 0; + + for (i = -1; i < size + 1; i++) { + const char* val = lookup(i); + int rev; + + if (val) { + rev = reverse(val); + boring = 0; + } else { + rev = reverse("--no-such--value----"); + boring += i >= 0; + } + + if (boring < 1 || i == size) + printf("%s: %d → %s → %d\n", name, i, val, rev); + else if (boring == 1) + printf("%*s ...\n", (int) strlen(name), ""); + + assert_se(!(i >= 0 && i < size ? + sparse ? rev != i && rev != -1 : val == NULL || rev != i : + val != NULL || rev != -1)); + } +} + +#define test_table(lower, upper) \ + _test_table(STRINGIFY(lower), lower##_to_string, lower##_from_string, _##upper##_MAX, false) + +#define test_table_sparse(lower, upper) \ + _test_table(STRINGIFY(lower), lower##_to_string, lower##_from_string, _##upper##_MAX, true) diff --git a/src/shared/tests.c b/src/shared/tests.c new file mode 100644 index 00000000..96b5b805 --- /dev/null +++ b/src/shared/tests.c @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include + +/* When we include libgen.h because we need dirname() we immediately + * undefine basename() since libgen.h defines it as a macro to the POSIX + * version which is really broken. We prefer GNU basename(). */ +#include +#undef basename + +#include "alloc-util.h" +#include "cgroup-setup.h" +#include "cgroup-util.h" +#include "env-file.h" +#include "env-util.h" +#include "fs-util.h" +#include "log.h" +#include "path-util.h" +#include "random-util.h" +#include "strv.h" +#include "tests.h" + +char* setup_fake_runtime_dir(void) { + char t[] = "/tmp/fake-xdg-runtime-XXXXXX", *p; + + assert_se(mkdtemp(t)); + assert_se(setenv("XDG_RUNTIME_DIR", t, 1) >= 0); + assert_se(p = strdup(t)); + + return p; +} + +static void load_testdata_env(void) { + static bool called = false; + _cleanup_free_ char *s = NULL; + _cleanup_free_ char *envpath = NULL; + _cleanup_strv_free_ char **pairs = NULL; + char **k, **v; + + if (called) + return; + called = true; + + assert_se(readlink_and_make_absolute("/proc/self/exe", &s) >= 0); + dirname(s); + + envpath = path_join(s, "systemd-runtest.env"); + if (load_env_file_pairs(NULL, envpath, &pairs) < 0) + return; + + STRV_FOREACH_PAIR(k, v, pairs) + setenv(*k, *v, 0); +} + +const char* get_testdata_dir(void) { + const char *env; + + load_testdata_env(); + + /* if the env var is set, use that */ + env = getenv("SYSTEMD_TEST_DATA"); + if (!env) + env = SYSTEMD_TEST_DATA; + if (access(env, F_OK) < 0) { + fprintf(stderr, "ERROR: $SYSTEMD_TEST_DATA directory [%s] does not exist\n", env); + exit(EXIT_FAILURE); + } + + return env; +} + +const char* get_catalog_dir(void) { + const char *env; + + load_testdata_env(); + + /* if the env var is set, use that */ + env = getenv("SYSTEMD_CATALOG_DIR"); + if (!env) + env = SYSTEMD_CATALOG_DIR; + if (access(env, F_OK) < 0) { + fprintf(stderr, "ERROR: $SYSTEMD_CATALOG_DIR directory [%s] does not exist\n", env); + exit(EXIT_FAILURE); + } + return env; +} + +bool slow_tests_enabled(void) { + int r; + + r = getenv_bool("SYSTEMD_SLOW_TESTS"); + if (r >= 0) + return r; + + if (r != -ENXIO) + log_warning_errno(r, "Cannot parse $SYSTEMD_SLOW_TESTS, ignoring."); + return SYSTEMD_SLOW_TESTS_DEFAULT; +} + +void test_setup_logging(int level) { + log_set_max_level(level); + log_parse_environment(); + log_open(); +} + +int log_tests_skipped(const char *message) { + log_notice("%s: %s, skipping tests.", + program_invocation_short_name, message); + return EXIT_TEST_SKIP; +} + +int log_tests_skipped_errno(int r, const char *message) { + log_notice_errno(r, "%s: %s, skipping tests: %m", + program_invocation_short_name, message); + return EXIT_TEST_SKIP; +} + +bool have_namespaces(void) { + siginfo_t si = {}; + pid_t pid; + + /* Checks whether namespaces are available. In some cases they aren't. We do this by calling unshare(), and we + * do so in a child process in order not to affect our own process. */ + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + /* child */ + if (unshare(CLONE_NEWNS) < 0) + _exit(EXIT_FAILURE); + + if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + assert_se(waitid(P_PID, pid, &si, WEXITED) >= 0); + assert_se(si.si_code == CLD_EXITED); + + if (si.si_status == EXIT_SUCCESS) + return true; + + if (si.si_status == EXIT_FAILURE) + return false; + + assert_not_reached("unexpected exit code"); +} + +bool can_memlock(void) { + /* Let's see if we can mlock() a larger blob of memory. BPF programs are charged against + * RLIMIT_MEMLOCK, hence let's first make sure we can lock memory at all, and skip the test if we + * cannot. Why not check RLIMIT_MEMLOCK explicitly? Because in container environments the + * RLIMIT_MEMLOCK value we see might not match the RLIMIT_MEMLOCK value actually in effect. */ + + void *p = mmap(NULL, CAN_MEMLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0); + if (p == MAP_FAILED) + return false; + + bool b = mlock(p, CAN_MEMLOCK_SIZE) >= 0; + if (b) + assert_se(munlock(p, CAN_MEMLOCK_SIZE) >= 0); + + assert_se(munmap(p, CAN_MEMLOCK_SIZE) >= 0); + return b; +} + +int enter_cgroup_subroot(char **ret_cgroup) { + _cleanup_free_ char *cgroup_root = NULL, *cgroup_subroot = NULL; + CGroupMask supported; + int r; + + r = cg_pid_get_path(NULL, 0, &cgroup_root); + if (r == -ENOMEDIUM) + return log_warning_errno(r, "cg_pid_get_path(NULL, 0, ...) failed: %m"); + assert(r >= 0); + + assert_se(asprintf(&cgroup_subroot, "%s/%" PRIx64, cgroup_root, random_u64()) >= 0); + assert_se(cg_mask_supported(&supported) >= 0); + + /* If this fails, then we don't mind as the later cgroup operations will fail too, and it's fine if + * we handle any errors at that point. */ + + r = cg_create_everywhere(supported, _CGROUP_MASK_ALL, cgroup_subroot); + if (r < 0) + return r; + + r = cg_attach_everywhere(supported, cgroup_subroot, 0, NULL, NULL); + if (r < 0) + return r; + + if (ret_cgroup) + *ret_cgroup = TAKE_PTR(cgroup_subroot); + return 0; +} diff --git a/src/shared/tests.h b/src/shared/tests.h new file mode 100644 index 00000000..5a6fd53f --- /dev/null +++ b/src/shared/tests.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-daemon.h" + +#include "macro.h" + +static inline bool manager_errno_skip_test(int r) { + return IN_SET(abs(r), + EPERM, + EACCES, + EADDRINUSE, + EHOSTDOWN, + ENOENT, + ENOMEDIUM /* cannot determine cgroup */ + ); +} + +char* setup_fake_runtime_dir(void); +int enter_cgroup_subroot(char **ret_cgroup); +const char* get_testdata_dir(void); +const char* get_catalog_dir(void); +bool slow_tests_enabled(void); +void test_setup_logging(int level); +int log_tests_skipped(const char *message); +int log_tests_skipped_errno(int r, const char *message); + +bool have_namespaces(void); + +/* We use the small but non-trivial limit here */ +#define CAN_MEMLOCK_SIZE (512 * 1024U) +bool can_memlock(void); + +#define TEST_REQ_RUNNING_SYSTEMD(x) \ + if (sd_booted() > 0) { \ + x; \ + } else { \ + printf("systemd not booted skipping '%s'\n", #x); \ + } diff --git a/src/shared/tmpfile-util-label.c b/src/shared/tmpfile-util-label.c new file mode 100644 index 00000000..c12d7c13 --- /dev/null +++ b/src/shared/tmpfile-util-label.c @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "selinux-util.h" +#include "tmpfile-util-label.h" +#include "tmpfile-util.h" + +int fopen_temporary_label( + const char *target, + const char *path, + FILE **f, + char **temp_path) { + + int r; + + r = mac_selinux_create_file_prepare(target, S_IFREG); + if (r < 0) + return r; + + r = fopen_temporary(path, f, temp_path); + + mac_selinux_create_file_clear(); + + return r; +} diff --git a/src/shared/tmpfile-util-label.h b/src/shared/tmpfile-util-label.h new file mode 100644 index 00000000..97a87516 --- /dev/null +++ b/src/shared/tmpfile-util-label.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +/* These functions are split out of tmpfile-util.h (and not for example just flags to the functions they wrap) in order + * to optimize linking: This way, -lselinux is needed only for the callers of these functions that need selinux, but + * not for all */ + +int fopen_temporary_label(const char *target, const char *path, FILE **f, char **temp_path); diff --git a/src/shared/tomoyo-util.c b/src/shared/tomoyo-util.c new file mode 100644 index 00000000..75c24d80 --- /dev/null +++ b/src/shared/tomoyo-util.c @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "tomoyo-util.h" + +bool mac_tomoyo_use(void) { + static int cached_use = -1; + + if (cached_use < 0) + cached_use = (access("/sys/kernel/security/tomoyo/version", + F_OK) == 0); + + return cached_use; +} diff --git a/src/shared/tomoyo-util.h b/src/shared/tomoyo-util.h new file mode 100644 index 00000000..06e82278 --- /dev/null +++ b/src/shared/tomoyo-util.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +bool mac_tomoyo_use(void); diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c new file mode 100644 index 00000000..ea96f5b4 --- /dev/null +++ b/src/shared/udev-util.c @@ -0,0 +1,218 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "device-util.h" +#include "env-file.h" +#include "log.h" +#include "parse-util.h" +#include "string-table.h" +#include "string-util.h" +#include "udev-util.h" + +static const char* const resolve_name_timing_table[_RESOLVE_NAME_TIMING_MAX] = { + [RESOLVE_NAME_NEVER] = "never", + [RESOLVE_NAME_LATE] = "late", + [RESOLVE_NAME_EARLY] = "early", +}; + +DEFINE_STRING_TABLE_LOOKUP(resolve_name_timing, ResolveNameTiming); + +int udev_parse_config_full( + unsigned *ret_children_max, + usec_t *ret_exec_delay_usec, + usec_t *ret_event_timeout_usec, + ResolveNameTiming *ret_resolve_name_timing) { + + _cleanup_free_ char *log_val = NULL, *children_max = NULL, *exec_delay = NULL, *event_timeout = NULL, *resolve_names = NULL; + int r; + + r = parse_env_file(NULL, "/etc/udev/udev.conf", + "udev_log", &log_val, + "children_max", &children_max, + "exec_delay", &exec_delay, + "event_timeout", &event_timeout, + "resolve_names", &resolve_names); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + if (log_val) { + const char *log; + size_t n; + + /* unquote */ + n = strlen(log_val); + if (n >= 2 && + ((log_val[0] == '"' && log_val[n-1] == '"') || + (log_val[0] == '\'' && log_val[n-1] == '\''))) { + log_val[n - 1] = '\0'; + log = log_val + 1; + } else + log = log_val; + + /* we set the udev log level here explicitly, this is supposed + * to regulate the code in libudev/ and udev/. */ + r = log_set_max_level_from_string_realm(LOG_REALM_UDEV, log); + if (r < 0) + log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, + "failed to set udev log level '%s', ignoring: %m", log); + } + + if (ret_children_max && children_max) { + r = safe_atou(children_max, ret_children_max); + if (r < 0) + log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, + "failed to set parse children_max=%s, ignoring: %m", children_max); + } + + if (ret_exec_delay_usec && exec_delay) { + r = parse_sec(exec_delay, ret_exec_delay_usec); + if (r < 0) + log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, + "failed to set parse exec_delay=%s, ignoring: %m", exec_delay); + } + + if (ret_event_timeout_usec && event_timeout) { + r = parse_sec(event_timeout, ret_event_timeout_usec); + if (r < 0) + log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, + "failed to set parse event_timeout=%s, ignoring: %m", event_timeout); + } + + if (ret_resolve_name_timing && resolve_names) { + ResolveNameTiming t; + + t = resolve_name_timing_from_string(resolve_names); + if (t < 0) + log_syntax(NULL, LOG_WARNING, "/etc/udev/udev.conf", 0, r, + "failed to set parse resolve_names=%s, ignoring.", resolve_names); + else + *ret_resolve_name_timing = t; + } + + return 0; +} + +struct DeviceMonitorData { + const char *sysname; + sd_device *device; +}; + +static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, void *userdata) { + struct DeviceMonitorData *data = userdata; + const char *sysname; + + assert(device); + assert(data); + assert(data->sysname); + assert(!data->device); + + if (sd_device_get_sysname(device, &sysname) >= 0 && streq(sysname, data->sysname)) { + data->device = sd_device_ref(device); + return sd_event_exit(sd_device_monitor_get_event(monitor), 0); + } + + return 0; +} + +static int device_timeout_handler(sd_event_source *s, uint64_t usec, void *userdata) { + return sd_event_exit(sd_event_source_get_event(s), -ETIMEDOUT); +} + +int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout, sd_device **ret) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL; + _cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + struct DeviceMonitorData data = {}; + int r; + + assert(device); + + if (sd_device_get_is_initialized(device) > 0) { + if (ret) + *ret = sd_device_ref(device); + return 0; + } + + assert_se(sd_device_get_sysname(device, &data.sysname) >= 0); + + /* Wait until the device is initialized, so that we can get access to the ID_PATH property */ + + r = sd_event_new(&event); + if (r < 0) + return log_error_errno(r, "Failed to get default event: %m"); + + r = sd_device_monitor_new(&monitor); + if (r < 0) + return log_error_errno(r, "Failed to acquire monitor: %m"); + + if (!subsystem) { + r = sd_device_get_subsystem(device, &subsystem); + if (r < 0 && r != -ENOENT) + return log_device_error_errno(device, r, "Failed to get subsystem: %m"); + } + + if (subsystem) { + r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, subsystem, NULL); + if (r < 0) + return log_error_errno(r, "Failed to add %s subsystem match to monitor: %m", subsystem); + } + + r = sd_device_monitor_attach_event(monitor, event); + if (r < 0) + return log_error_errno(r, "Failed to attach event to device monitor: %m"); + + r = sd_device_monitor_start(monitor, device_monitor_handler, &data); + if (r < 0) + return log_error_errno(r, "Failed to start device monitor: %m"); + + if (timeout != USEC_INFINITY) { + r = sd_event_add_time(event, &timeout_source, + CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + timeout, 0, + device_timeout_handler, NULL); + if (r < 0) + return log_error_errno(r, "Failed to add timeout event source: %m"); + } + + /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized + * yet. */ + if (sd_device_get_is_initialized(device) > 0) { + if (ret) + *ret = sd_device_ref(device); + return 0; + } + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to wait for device to be initialized: %m"); + + if (ret) + *ret = TAKE_PTR(data.device); + return 0; +} + +int device_is_renaming(sd_device *dev) { + int r; + + assert(dev); + + r = sd_device_get_property_value(dev, "ID_RENAMING", NULL); + if (r < 0 && r != -ENOENT) + return r; + + return r >= 0; +} + +bool device_for_action(sd_device *dev, DeviceAction action) { + DeviceAction a; + + assert(dev); + + if (device_get_action(dev, &a) < 0) + return false; + + return a == action; +} diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h new file mode 100644 index 00000000..f62c4c56 --- /dev/null +++ b/src/shared/udev-util.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-device.h" + +#include "device-private.h" +#include "time-util.h" + +typedef enum ResolveNameTiming { + RESOLVE_NAME_NEVER, + RESOLVE_NAME_LATE, + RESOLVE_NAME_EARLY, + _RESOLVE_NAME_TIMING_MAX, + _RESOLVE_NAME_TIMING_INVALID = -1, +} ResolveNameTiming; + +ResolveNameTiming resolve_name_timing_from_string(const char *s) _pure_; +const char *resolve_name_timing_to_string(ResolveNameTiming i) _const_; + +int udev_parse_config_full( + unsigned *ret_children_max, + usec_t *ret_exec_delay_usec, + usec_t *ret_event_timeout_usec, + ResolveNameTiming *ret_resolve_name_timing); + +static inline int udev_parse_config(void) { + return udev_parse_config_full(NULL, NULL, NULL, NULL); +} + +int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout, sd_device **ret); +int device_is_renaming(sd_device *dev); +bool device_for_action(sd_device *dev, DeviceAction action); diff --git a/src/shared/uid-range.c b/src/shared/uid-range.c new file mode 100644 index 00000000..7cb7d8a4 --- /dev/null +++ b/src/shared/uid-range.c @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "macro.h" +#include "sort-util.h" +#include "uid-range.h" +#include "user-util.h" + +static bool uid_range_intersect(UidRange *range, uid_t start, uid_t nr) { + assert(range); + + return range->start <= start + nr && + range->start + range->nr >= start; +} + +static void uid_range_coalesce(UidRange **p, unsigned *n) { + unsigned i, j; + + assert(p); + assert(n); + + for (i = 0; i < *n; i++) { + for (j = i + 1; j < *n; j++) { + UidRange *x = (*p)+i, *y = (*p)+j; + + if (uid_range_intersect(x, y->start, y->nr)) { + uid_t begin, end; + + begin = MIN(x->start, y->start); + end = MAX(x->start + x->nr, y->start + y->nr); + + x->start = begin; + x->nr = end - begin; + + if (*n > j+1) + memmove(y, y+1, sizeof(UidRange) * (*n - j -1)); + + (*n)--; + j--; + } + } + } +} + +static int uid_range_compare(const UidRange *a, const UidRange *b) { + int r; + + r = CMP(a->start, b->start); + if (r != 0) + return r; + + return CMP(a->nr, b->nr); +} + +int uid_range_add(UidRange **p, unsigned *n, uid_t start, uid_t nr) { + bool found = false; + UidRange *x; + unsigned i; + + assert(p); + assert(n); + + if (nr <= 0) + return 0; + + for (i = 0; i < *n; i++) { + x = (*p) + i; + if (uid_range_intersect(x, start, nr)) { + found = true; + break; + } + } + + if (found) { + uid_t begin, end; + + begin = MIN(x->start, start); + end = MAX(x->start + x->nr, start + nr); + + x->start = begin; + x->nr = end - begin; + } else { + UidRange *t; + + t = reallocarray(*p, *n + 1, sizeof(UidRange)); + if (!t) + return -ENOMEM; + + *p = t; + x = t + ((*n) ++); + + x->start = start; + x->nr = nr; + } + + typesafe_qsort(*p, *n, uid_range_compare); + uid_range_coalesce(p, n); + + return *n; +} + +int uid_range_add_str(UidRange **p, unsigned *n, const char *s) { + uid_t start, nr; + const char *t; + int r; + + assert(p); + assert(n); + assert(s); + + t = strchr(s, '-'); + if (t) { + char *b; + uid_t end; + + b = strndupa(s, t - s); + r = parse_uid(b, &start); + if (r < 0) + return r; + + r = parse_uid(t+1, &end); + if (r < 0) + return r; + + if (end < start) + return -EINVAL; + + nr = end - start + 1; + } else { + r = parse_uid(s, &start); + if (r < 0) + return r; + + nr = 1; + } + + return uid_range_add(p, n, start, nr); +} + +int uid_range_next_lower(const UidRange *p, unsigned n, uid_t *uid) { + uid_t closest = UID_INVALID, candidate; + unsigned i; + + assert(p); + assert(uid); + + candidate = *uid - 1; + + for (i = 0; i < n; i++) { + uid_t begin, end; + + begin = p[i].start; + end = p[i].start + p[i].nr - 1; + + if (candidate >= begin && candidate <= end) { + *uid = candidate; + return 1; + } + + if (end < candidate) + closest = end; + } + + if (closest == UID_INVALID) + return -EBUSY; + + *uid = closest; + return 1; +} + +bool uid_range_contains(const UidRange *p, unsigned n, uid_t uid) { + unsigned i; + + assert(p); + assert(uid); + + for (i = 0; i < n; i++) + if (uid >= p[i].start && uid < p[i].start + p[i].nr) + return true; + + return false; +} diff --git a/src/shared/uid-range.h b/src/shared/uid-range.h new file mode 100644 index 00000000..49ba3828 --- /dev/null +++ b/src/shared/uid-range.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +typedef struct UidRange { + uid_t start, nr; +} UidRange; + +int uid_range_add(UidRange **p, unsigned *n, uid_t start, uid_t nr); +int uid_range_add_str(UidRange **p, unsigned *n, const char *s); + +int uid_range_next_lower(const UidRange *p, unsigned n, uid_t *uid); +bool uid_range_contains(const UidRange *p, unsigned n, uid_t uid); diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c new file mode 100644 index 00000000..28cd3c86 --- /dev/null +++ b/src/shared/unit-file.c @@ -0,0 +1,559 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "dirent-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "macro.h" +#include "path-lookup.h" +#include "set.h" +#include "special.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "unit-file.h" + +bool unit_type_may_alias(UnitType type) { + return IN_SET(type, + UNIT_SERVICE, + UNIT_SOCKET, + UNIT_TARGET, + UNIT_DEVICE, + UNIT_TIMER, + UNIT_PATH); +} + +bool unit_type_may_template(UnitType type) { + return IN_SET(type, + UNIT_SERVICE, + UNIT_SOCKET, + UNIT_TARGET, + UNIT_TIMER, + UNIT_PATH); +} + +int unit_validate_alias_symlink_and_warn(const char *filename, const char *target) { + const char *src, *dst; + _cleanup_free_ char *src_instance = NULL, *dst_instance = NULL; + UnitType src_unit_type, dst_unit_type; + int src_name_type, dst_name_type; + + /* Check if the *alias* symlink is valid. This applies to symlinks like + * /etc/systemd/system/dbus.service → dbus-broker.service, but not to .wants or .requires symlinks + * and such. Neither does this apply to symlinks which *link* units, i.e. symlinks to outside of the + * unit lookup path. + * + * -EINVAL is returned if the something is wrong with the source filename or the source unit type is + * not allowed to symlink, + * -EXDEV if the target filename is not a valid unit name or doesn't match the source. + */ + + src = basename(filename); + dst = basename(target); + + /* src checks */ + + src_name_type = unit_name_to_instance(src, &src_instance); + if (src_name_type < 0) + return log_notice_errno(src_name_type, + "%s: not a valid unit name \"%s\": %m", filename, src); + + src_unit_type = unit_name_to_type(src); + assert(src_unit_type >= 0); /* unit_name_to_instance() checked the suffix already */ + + if (!unit_type_may_alias(src_unit_type)) + return log_notice_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: symlinks are not allowed for units of this type, rejecting.", + filename); + + if (src_name_type != UNIT_NAME_PLAIN && + !unit_type_may_template(src_unit_type)) + return log_notice_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: templates not allowed for %s units, rejecting.", + filename, unit_type_to_string(src_unit_type)); + + /* dst checks */ + + dst_name_type = unit_name_to_instance(dst, &dst_instance); + if (dst_name_type < 0) + return log_notice_errno(dst_name_type == -EINVAL ? SYNTHETIC_ERRNO(EXDEV) : dst_name_type, + "%s points to \"%s\" which is not a valid unit name: %m", + filename, dst); + + if (!(dst_name_type == src_name_type || + (src_name_type == UNIT_NAME_INSTANCE && dst_name_type == UNIT_NAME_TEMPLATE))) + return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), + "%s: symlink target name type \"%s\" does not match source, rejecting.", + filename, dst); + + if (dst_name_type == UNIT_NAME_INSTANCE) { + assert(src_instance); + assert(dst_instance); + if (!streq(src_instance, dst_instance)) + return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), + "%s: unit symlink target \"%s\" instance name doesn't match, rejecting.", + filename, dst); + } + + dst_unit_type = unit_name_to_type(dst); + if (dst_unit_type != src_unit_type) + return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), + "%s: symlink target \"%s\" has incompatible suffix, rejecting.", + filename, dst); + + return 0; +} + +#define FOLLOW_MAX 8 + +static int unit_ids_map_get( + Hashmap *unit_ids_map, + const char *unit_name, + const char **ret_fragment_path) { + + /* Resolve recursively until we hit an absolute path, i.e. a non-aliased unit. + * + * We distinguish the case where unit_name was not found in the hashmap at all, and the case where + * some symlink was broken. + * + * If a symlink target points to an instance name, then we also check for the template. */ + + const char *id = NULL; + int r; + + for (unsigned n = 0; n < FOLLOW_MAX; n++) { + const char *t = hashmap_get(unit_ids_map, id ?: unit_name); + if (!t) { + _cleanup_free_ char *template = NULL; + + if (!id) + return -ENOENT; + + r = unit_name_template(id, &template); + if (r == -EINVAL) + return -ENXIO; /* we failed to find the symlink target */ + if (r < 0) + return log_error_errno(r, "Failed to determine template name for %s: %m", id); + + t = hashmap_get(unit_ids_map, template); + if (!t) + return -ENXIO; + + /* We successfully switched from instanced name to a template, let's continue */ + } + + if (path_is_absolute(t)) { + if (ret_fragment_path) + *ret_fragment_path = t; + return 0; + } + + id = t; + } + + return -ELOOP; +} + +static bool lookup_paths_mtime_exclude(const LookupPaths *lp, const char *path) { + /* Paths that are under our exclusive control. Users shall not alter those directly. */ + + return streq_ptr(path, lp->generator) || + streq_ptr(path, lp->generator_early) || + streq_ptr(path, lp->generator_late) || + streq_ptr(path, lp->transient) || + streq_ptr(path, lp->persistent_control) || + streq_ptr(path, lp->runtime_control); +} + +static bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime) { + char **dir; + + STRV_FOREACH(dir, (char**) lp->search_path) { + struct stat st; + + if (lookup_paths_mtime_exclude(lp, *dir)) + continue; + + /* Determine the latest lookup path modification time */ + if (stat(*dir, &st) < 0) { + if (errno == ENOENT) + continue; + + log_debug_errno(errno, "Failed to stat %s, ignoring: %m", *dir); + continue; + } + + if (timespec_load(&st.st_mtim) > mtime) { + log_debug_errno(errno, "Unit dir %s has changed, need to update cache.", *dir); + return false; + } + } + + return true; +} + +int unit_file_build_name_map( + const LookupPaths *lp, + usec_t *cache_mtime, + Hashmap **ret_unit_ids_map, + Hashmap **ret_unit_names_map, + Set **ret_path_cache) { + + /* Build two mappings: any name → main unit (i.e. the end result of symlink resolution), unit name → + * all aliases (i.e. the entry for a given key is a a list of all names which point to this key). The + * key is included in the value iff we saw a file or symlink with that name. In other words, if we + * have a key, but it is not present in the value for itself, there was an alias pointing to it, but + * the unit itself is not loadable. + * + * At the same, build a cache of paths where to find units. + */ + + _cleanup_hashmap_free_ Hashmap *ids = NULL, *names = NULL; + _cleanup_set_free_free_ Set *paths = NULL; + char **dir; + int r; + usec_t mtime = 0; + + /* Before doing anything, check if the mtime that was passed is still valid. If + * yes, do nothing. If *cache_time == 0, always build the cache. */ + if (cache_mtime && *cache_mtime > 0 && lookup_paths_mtime_good(lp, *cache_mtime)) + return 0; + + if (ret_path_cache) { + paths = set_new(&path_hash_ops); + if (!paths) + return log_oom(); + } + + STRV_FOREACH(dir, (char**) lp->search_path) { + struct dirent *de; + _cleanup_closedir_ DIR *d = NULL; + struct stat st; + + d = opendir(*dir); + if (!d) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to open \"%s\", ignoring: %m", *dir); + continue; + } + + /* Determine the latest lookup path modification time */ + if (fstat(dirfd(d), &st) < 0) + return log_error_errno(errno, "Failed to fstat %s: %m", *dir); + + if (!lookup_paths_mtime_exclude(lp, *dir)) + mtime = MAX(mtime, timespec_load(&st.st_mtim)); + + FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { + char *filename; + _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; + const char *suffix, *dst = NULL; + bool valid_unit_name; + + valid_unit_name = unit_name_is_valid(de->d_name, UNIT_NAME_ANY); + + /* We only care about valid units and dirs with certain suffixes, let's ignore the + * rest. */ + if (!valid_unit_name && + !ENDSWITH_SET(de->d_name, ".wants", ".requires", ".d")) + continue; + + filename = path_join(*dir, de->d_name); + if (!filename) + return log_oom(); + + if (ret_path_cache) { + r = set_consume(paths, filename); + if (r < 0) + return log_oom(); + /* We will still use filename below. This is safe because we know the set + * holds a reference. */ + } else + _filename_free = filename; /* Make sure we free the filename. */ + + if (!valid_unit_name) + continue; + assert_se(suffix = strrchr(de->d_name, '.')); + + /* search_path is ordered by priority (highest first). If the name is already mapped + * to something (incl. itself), it means that we have already seen it, and we should + * ignore it here. */ + if (hashmap_contains(ids, de->d_name)) + continue; + + dirent_ensure_type(d, de); + if (de->d_type == DT_LNK) { + /* We don't explicitly check for alias loops here. unit_ids_map_get() which + * limits the number of hops should be used to access the map. */ + + _cleanup_free_ char *target = NULL, *target_abs = NULL; + + r = readlinkat_malloc(dirfd(d), de->d_name, &target); + if (r < 0) { + log_warning_errno(r, "Failed to read symlink %s/%s, ignoring: %m", + *dir, de->d_name); + continue; + } + + if (!path_is_absolute(target)) { + target_abs = path_join(*dir, target); + if (!target_abs) + return log_oom(); + + free_and_replace(target, target_abs); + } + + /* Get rid of "." and ".." components in target path */ + r = chase_symlinks(target, lp->root_dir, CHASE_NOFOLLOW | CHASE_NONEXISTENT, &simplified, NULL); + if (r < 0) { + log_warning_errno(r, "Failed to resolve symlink %s pointing to %s, ignoring: %m", + filename, target); + continue; + } + + /* Check if the symlink goes outside of our search path. + * If yes, it's a linked unit file or mask, and we don't care about the target name. + * Let's just store the link destination directly. + * If not, let's verify that it's a good symlink. */ + char *tail = path_startswith_strv(simplified, lp->search_path); + if (tail) { + bool self_alias; + + dst = basename(simplified); + self_alias = streq(dst, de->d_name); + + if (is_path(tail)) + log_full(self_alias ? LOG_DEBUG : LOG_WARNING, + "Suspicious symlink %s→%s, treating as alias.", + filename, simplified); + + r = unit_validate_alias_symlink_and_warn(filename, simplified); + if (r < 0) + continue; + + if (self_alias) { + /* A self-alias that has no effect */ + log_debug("%s: self-alias: %s/%s → %s, ignoring.", + __func__, *dir, de->d_name, dst); + continue; + } + + log_debug("%s: alias: %s/%s → %s", __func__, *dir, de->d_name, dst); + } else { + dst = simplified; + + log_debug("%s: linked unit file: %s/%s → %s", __func__, *dir, de->d_name, dst); + } + + } else { + dst = filename; + log_debug("%s: normal unit file: %s", __func__, dst); + } + + r = hashmap_put_strdup(&ids, de->d_name, dst); + if (r < 0) + return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", + de->d_name, dst); + } + } + + /* Let's also put the names in the reverse db. */ + Iterator it; + const char *dummy, *src; + HASHMAP_FOREACH_KEY(dummy, src, ids, it) { + const char *dst; + + r = unit_ids_map_get(ids, src, &dst); + if (r < 0) + continue; + + if (null_or_empty_path(dst) != 0) + continue; + + /* Do not treat instance symlinks that point to the template as aliases */ + if (unit_name_is_valid(basename(dst), UNIT_NAME_TEMPLATE) && + unit_name_is_valid(src, UNIT_NAME_INSTANCE)) + continue; + + r = string_strv_hashmap_put(&names, basename(dst), src); + if (r < 0) + return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", + basename(dst), src); + } + + if (cache_mtime) + *cache_mtime = mtime; + *ret_unit_ids_map = TAKE_PTR(ids); + *ret_unit_names_map = TAKE_PTR(names); + if (ret_path_cache) + *ret_path_cache = TAKE_PTR(paths); + + return 1; +} + +int unit_file_find_fragment( + Hashmap *unit_ids_map, + Hashmap *unit_name_map, + const char *unit_name, + const char **ret_fragment_path, + Set **ret_names) { + + const char *fragment = NULL; + _cleanup_free_ char *template = NULL, *instance = NULL; + _cleanup_set_free_free_ Set *names = NULL; + char **t, **nnn; + int r, name_type; + + /* Finds a fragment path, and returns the set of names: + * if we have …/foo.service and …/foo-alias.service→foo.service, + * and …/foo@.service and …/foo-alias@.service→foo@.service, + * and …/foo@inst.service, + * this should return: + * foo.service → …/foo.service, {foo.service, foo-alias.service}, + * foo-alias.service → …/foo.service, {foo.service, foo-alias.service}, + * foo@.service → …/foo@.service, {foo@.service, foo-alias@.service}, + * foo-alias@.service → …/foo@.service, {foo@.service, foo-alias@.service}, + * foo@bar.service → …/foo@.service, {foo@bar.service, foo-alias@bar.service}, + * foo-alias@bar.service → …/foo@.service, {foo@bar.service, foo-alias@bar.service}, + * foo-alias@inst.service → …/foo@inst.service, {foo@inst.service, foo-alias@inst.service}. + */ + + name_type = unit_name_to_instance(unit_name, &instance); + if (name_type < 0) + return name_type; + + names = set_new(&string_hash_ops); + if (!names) + return -ENOMEM; + + /* The unit always has its own name if it's not a template. */ + if (IN_SET(name_type, UNIT_NAME_PLAIN, UNIT_NAME_INSTANCE)) { + r = set_put_strdup(names, unit_name); + if (r < 0) + return r; + } + + /* First try to load fragment under the original name */ + r = unit_ids_map_get(unit_ids_map, unit_name, &fragment); + if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) + return log_debug_errno(r, "Cannot load unit %s: %m", unit_name); + + if (fragment) { + /* Add any aliases of the original name to the set of names */ + nnn = hashmap_get(unit_name_map, basename(fragment)); + STRV_FOREACH(t, nnn) { + if (name_type == UNIT_NAME_INSTANCE && unit_name_is_valid(*t, UNIT_NAME_TEMPLATE)) { + char *inst; + + r = unit_name_replace_instance(*t, instance, &inst); + if (r < 0) + return log_debug_errno(r, "Cannot build instance name %s+%s: %m", *t, instance); + + if (!streq(unit_name, inst)) + log_debug("%s: %s has alias %s", __func__, unit_name, inst); + + log_info("%s: %s+%s → %s", __func__, *t, instance, inst); + r = set_consume(names, inst); + } else { + if (!streq(unit_name, *t)) + log_debug("%s: %s has alias %s", __func__, unit_name, *t); + + r = set_put_strdup(names, *t); + } + if (r < 0) + return r; + } + } + + if (!fragment && name_type == UNIT_NAME_INSTANCE) { + /* Look for a fragment under the template name */ + + r = unit_name_template(unit_name, &template); + if (r < 0) + return log_error_errno(r, "Failed to determine template name: %m"); + + r = unit_ids_map_get(unit_ids_map, template, &fragment); + if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) + return log_debug_errno(r, "Cannot load template %s: %m", template); + + if (fragment) { + /* Add any aliases of the original name to the set of names */ + nnn = hashmap_get(unit_name_map, basename(fragment)); + STRV_FOREACH(t, nnn) { + _cleanup_free_ char *inst = NULL; + const char *inst_fragment = NULL; + + r = unit_name_replace_instance(*t, instance, &inst); + if (r < 0) + return log_debug_errno(r, "Cannot build instance name %s+%s: %m", template, instance); + + /* Exclude any aliases that point in some other direction. */ + r = unit_ids_map_get(unit_ids_map, inst, &inst_fragment); + if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) + return log_debug_errno(r, "Cannot find instance fragment %s: %m", inst); + + if (inst_fragment && + !streq(basename(inst_fragment), basename(fragment))) { + log_debug("Instance %s has fragment %s and is not an alias of %s.", + inst, inst_fragment, unit_name); + continue; + } + + if (!streq(unit_name, inst)) + log_debug("%s: %s has alias %s", __func__, unit_name, inst); + r = set_consume(names, TAKE_PTR(inst)); + if (r < 0) + return r; + } + } + } + + *ret_fragment_path = fragment; + *ret_names = TAKE_PTR(names); + + // FIXME: if instance, consider any unit names with different template name + return 0; +} + +static const char * const rlmap[] = { + "emergency", SPECIAL_EMERGENCY_TARGET, + "-b", SPECIAL_EMERGENCY_TARGET, + "rescue", SPECIAL_RESCUE_TARGET, + "single", SPECIAL_RESCUE_TARGET, + "-s", SPECIAL_RESCUE_TARGET, + "s", SPECIAL_RESCUE_TARGET, + "S", SPECIAL_RESCUE_TARGET, + "1", SPECIAL_RESCUE_TARGET, + "2", SPECIAL_MULTI_USER_TARGET, + "3", SPECIAL_MULTI_USER_TARGET, + "4", SPECIAL_MULTI_USER_TARGET, + "5", SPECIAL_GRAPHICAL_TARGET, + NULL +}; + +static const char * const rlmap_initrd[] = { + "emergency", SPECIAL_EMERGENCY_TARGET, + "rescue", SPECIAL_RESCUE_TARGET, + NULL +}; + +const char* runlevel_to_target(const char *word) { + const char * const *rlmap_ptr; + size_t i; + + if (!word) + return NULL; + + if (in_initrd()) { + word = startswith(word, "rd."); + if (!word) + return NULL; + } + + rlmap_ptr = in_initrd() ? rlmap_initrd : rlmap; + + for (i = 0; rlmap_ptr[i]; i += 2) + if (streq(word, rlmap_ptr[i])) + return rlmap_ptr[i+1]; + + return NULL; +} diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h new file mode 100644 index 00000000..98ba677f --- /dev/null +++ b/src/shared/unit-file.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "hashmap.h" +#include "time-util.h" +#include "unit-name.h" + +typedef enum UnitFileState UnitFileState; +typedef enum UnitFileScope UnitFileScope; +typedef struct LookupPaths LookupPaths; + +enum UnitFileState { + UNIT_FILE_ENABLED, + UNIT_FILE_ENABLED_RUNTIME, + UNIT_FILE_LINKED, + UNIT_FILE_LINKED_RUNTIME, + UNIT_FILE_MASKED, + UNIT_FILE_MASKED_RUNTIME, + UNIT_FILE_STATIC, + UNIT_FILE_DISABLED, + UNIT_FILE_INDIRECT, + UNIT_FILE_GENERATED, + UNIT_FILE_TRANSIENT, + UNIT_FILE_BAD, + _UNIT_FILE_STATE_MAX, + _UNIT_FILE_STATE_INVALID = -1 +}; + +enum UnitFileScope { + UNIT_FILE_SYSTEM, + UNIT_FILE_GLOBAL, + UNIT_FILE_USER, + _UNIT_FILE_SCOPE_MAX, + _UNIT_FILE_SCOPE_INVALID = -1 +}; + +bool unit_type_may_alias(UnitType type) _const_; +bool unit_type_may_template(UnitType type) _const_; + +int unit_validate_alias_symlink_and_warn(const char *filename, const char *target); + +int unit_file_build_name_map( + const LookupPaths *lp, + usec_t *ret_time, + Hashmap **ret_unit_ids_map, + Hashmap **ret_unit_names_map, + Set **ret_path_cache); + +int unit_file_find_fragment( + Hashmap *unit_ids_map, + Hashmap *unit_name_map, + const char *unit_name, + const char **ret_fragment_path, + Set **names); + +const char* runlevel_to_target(const char *rl); diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c new file mode 100644 index 00000000..fa4f32f3 --- /dev/null +++ b/src/shared/utmp-wtmp.c @@ -0,0 +1,424 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "hostname-util.h" +#include "macro.h" +#include "memory-util.h" +#include "path-util.h" +#include "string-util.h" +#include "terminal-util.h" +#include "time-util.h" +#include "user-util.h" +#include "utmp-wtmp.h" + +int utmp_get_runlevel(int *runlevel, int *previous) { + struct utmpx *found, lookup = { .ut_type = RUN_LVL }; + int r; + const char *e; + + assert(runlevel); + + /* If these values are set in the environment this takes + * precedence. Presumably, sysvinit does this to work around a + * race condition that would otherwise exist where we'd always + * go to disk and hence might read runlevel data that might be + * very new and does not apply to the current script being + * executed. */ + + e = getenv("RUNLEVEL"); + if (e && e[0] > 0) { + *runlevel = e[0]; + + if (previous) { + /* $PREVLEVEL seems to be an Upstart thing */ + + e = getenv("PREVLEVEL"); + if (e && e[0] > 0) + *previous = e[0]; + else + *previous = 0; + } + + return 0; + } + + if (utmpxname(_PATH_UTMPX) < 0) + return -errno; + + setutxent(); + + found = getutxid(&lookup); + if (!found) + r = -errno; + else { + int a, b; + + a = found->ut_pid & 0xFF; + b = (found->ut_pid >> 8) & 0xFF; + + *runlevel = a; + if (previous) + *previous = b; + + r = 0; + } + + endutxent(); + + return r; +} + +static void init_timestamp(struct utmpx *store, usec_t t) { + assert(store); + + if (t <= 0) + t = now(CLOCK_REALTIME); + + store->ut_tv.tv_sec = t / USEC_PER_SEC; + store->ut_tv.tv_usec = t % USEC_PER_SEC; +} + +static void init_entry(struct utmpx *store, usec_t t) { + struct utsname uts = {}; + + assert(store); + + init_timestamp(store, t); + + if (uname(&uts) >= 0) + strncpy(store->ut_host, uts.release, sizeof(store->ut_host)); + + strncpy(store->ut_line, "~", sizeof(store->ut_line)); /* or ~~ ? */ + strncpy(store->ut_id, "~~", sizeof(store->ut_id)); +} + +static int write_entry_utmp(const struct utmpx *store) { + int r; + + assert(store); + + /* utmp is similar to wtmp, but there is only one entry for + * each entry type resp. user; i.e. basically a key/value + * table. */ + + if (utmpxname(_PATH_UTMPX) < 0) + return -errno; + + setutxent(); + + if (!pututxline(store)) + r = -errno; + else + r = 0; + + endutxent(); + + return r; +} + +static int write_entry_wtmp(const struct utmpx *store) { + assert(store); + + /* wtmp is a simple append-only file where each entry is + simply appended to the end; i.e. basically a log. */ + + errno = 0; + updwtmpx(_PATH_WTMPX, store); + return -errno; +} + +static int write_utmp_wtmp(const struct utmpx *store_utmp, const struct utmpx *store_wtmp) { + int r, s; + + r = write_entry_utmp(store_utmp); + s = write_entry_wtmp(store_wtmp); + + if (r >= 0) + r = s; + + /* If utmp/wtmp have been disabled, that's a good thing, hence + * ignore the errors */ + if (r == -ENOENT) + r = 0; + + return r; +} + +static int write_entry_both(const struct utmpx *store) { + return write_utmp_wtmp(store, store); +} + +int utmp_put_shutdown(void) { + struct utmpx store = {}; + + init_entry(&store, 0); + + store.ut_type = RUN_LVL; + strncpy(store.ut_user, "shutdown", sizeof(store.ut_user)); + + return write_entry_both(&store); +} + +int utmp_put_reboot(usec_t t) { + struct utmpx store = {}; + + init_entry(&store, t); + + store.ut_type = BOOT_TIME; + strncpy(store.ut_user, "reboot", sizeof(store.ut_user)); + + return write_entry_both(&store); +} + +static void copy_suffix(char *buf, size_t buf_size, const char *src) { + size_t l; + + l = strlen(src); + if (l < buf_size) + strncpy(buf, src, buf_size); + else + memcpy(buf, src + l - buf_size, buf_size); +} + +int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user) { + struct utmpx store = { + .ut_type = INIT_PROCESS, + .ut_pid = pid, + .ut_session = sid, + }; + int r; + + assert(id); + + init_timestamp(&store, 0); + + /* Copy the whole string if it fits, or just the suffix without the terminating NUL. */ + copy_suffix(store.ut_id, sizeof(store.ut_id), id); + + if (line) + strncpy_exact(store.ut_line, line, sizeof(store.ut_line)); + + r = write_entry_both(&store); + if (r < 0) + return r; + + if (IN_SET(ut_type, LOGIN_PROCESS, USER_PROCESS)) { + store.ut_type = LOGIN_PROCESS; + r = write_entry_both(&store); + if (r < 0) + return r; + } + + if (ut_type == USER_PROCESS) { + store.ut_type = USER_PROCESS; + strncpy(store.ut_user, user, sizeof(store.ut_user)-1); + r = write_entry_both(&store); + if (r < 0) + return r; + } + + return 0; +} + +int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) { + struct utmpx lookup = { + .ut_type = INIT_PROCESS /* looks for DEAD_PROCESS, LOGIN_PROCESS, USER_PROCESS, too */ + }, store, store_wtmp, *found; + + assert(id); + + setutxent(); + + /* Copy the whole string if it fits, or just the suffix without the terminating NUL. */ + copy_suffix(store.ut_id, sizeof(store.ut_id), id); + + found = getutxid(&lookup); + if (!found) + return 0; + + if (found->ut_pid != pid) + return 0; + + memcpy(&store, found, sizeof(store)); + store.ut_type = DEAD_PROCESS; + store.ut_exit.e_termination = code; + store.ut_exit.e_exit = status; + + zero(store.ut_user); + zero(store.ut_host); + zero(store.ut_tv); + + memcpy(&store_wtmp, &store, sizeof(store_wtmp)); + /* wtmp wants the current time */ + init_timestamp(&store_wtmp, 0); + + return write_utmp_wtmp(&store, &store_wtmp); +} + +int utmp_put_runlevel(int runlevel, int previous) { + struct utmpx store = {}; + int r; + + assert(runlevel > 0); + + if (previous <= 0) { + /* Find the old runlevel automatically */ + + r = utmp_get_runlevel(&previous, NULL); + if (r < 0) { + if (r != -ESRCH) + return r; + + previous = 0; + } + } + + if (previous == runlevel) + return 0; + + init_entry(&store, 0); + + store.ut_type = RUN_LVL; + store.ut_pid = (runlevel & 0xFF) | ((previous & 0xFF) << 8); + strncpy(store.ut_user, "runlevel", sizeof(store.ut_user)); + + return write_entry_both(&store); +} + +#define TIMEOUT_MSEC 50 + +static int write_to_terminal(const char *tty, const char *message) { + _cleanup_close_ int fd = -1; + const char *p; + size_t left; + usec_t end; + + assert(tty); + assert(message); + + fd = open(tty, O_WRONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC); + if (fd < 0 || !isatty(fd)) + return -errno; + + p = message; + left = strlen(message); + + end = now(CLOCK_MONOTONIC) + TIMEOUT_MSEC*USEC_PER_MSEC; + + while (left > 0) { + ssize_t n; + struct pollfd pollfd = { + .fd = fd, + .events = POLLOUT, + }; + usec_t t; + int k; + + t = now(CLOCK_MONOTONIC); + + if (t >= end) + return -ETIME; + + k = poll(&pollfd, 1, (end - t) / USEC_PER_MSEC); + if (k < 0) + return -errno; + + if (k == 0) + return -ETIME; + + n = write(fd, p, left); + if (n < 0) { + if (errno == EAGAIN) + continue; + + return -errno; + } + + assert((size_t) n <= left); + + p += n; + left -= n; + } + + return 0; +} + +int utmp_wall( + const char *message, + const char *username, + const char *origin_tty, + bool (*match_tty)(const char *tty, void *userdata), + void *userdata) { + + _cleanup_free_ char *text = NULL, *hn = NULL, *un = NULL, *stdin_tty = NULL; + char date[FORMAT_TIMESTAMP_MAX]; + struct utmpx *u; + int r; + + hn = gethostname_malloc(); + if (!hn) + return -ENOMEM; + if (!username) { + un = getlogname_malloc(); + if (!un) + return -ENOMEM; + } + + if (!origin_tty) { + getttyname_harder(STDIN_FILENO, &stdin_tty); + origin_tty = stdin_tty; + } + + if (asprintf(&text, + "\a\r\n" + "Broadcast message from %s@%s%s%s (%s):\r\n\r\n" + "%s\r\n\r\n", + un ?: username, hn, + origin_tty ? " on " : "", strempty(origin_tty), + format_timestamp(date, sizeof(date), now(CLOCK_REALTIME)), + message) < 0) + return -ENOMEM; + + setutxent(); + + r = 0; + + while ((u = getutxent())) { + _cleanup_free_ char *buf = NULL; + const char *path; + int q; + + if (u->ut_type != USER_PROCESS || u->ut_user[0] == 0) + continue; + + /* this access is fine, because STRLEN("/dev/") << 32 (UT_LINESIZE) */ + if (path_startswith(u->ut_line, "/dev/")) + path = u->ut_line; + else { + if (asprintf(&buf, "/dev/%.*s", (int) sizeof(u->ut_line), u->ut_line) < 0) + return -ENOMEM; + + path = buf; + } + + if (!match_tty || match_tty(path, userdata)) { + q = write_to_terminal(path, text); + if (q < 0) + r = q; + } + } + + return r; +} diff --git a/src/shared/utmp-wtmp.h b/src/shared/utmp-wtmp.h new file mode 100644 index 00000000..9e433cf7 --- /dev/null +++ b/src/shared/utmp-wtmp.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "time-util.h" +#include "util.h" + +#if ENABLE_UTMP +int utmp_get_runlevel(int *runlevel, int *previous); + +int utmp_put_shutdown(void); +int utmp_put_reboot(usec_t timestamp); +int utmp_put_runlevel(int runlevel, int previous); + +int utmp_put_dead_process(const char *id, pid_t pid, int code, int status); +int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user); + +int utmp_wall( + const char *message, + const char *username, + const char *origin_tty, + bool (*match_tty)(const char *tty, void *userdata), + void *userdata); + +#else /* ENABLE_UTMP */ + +static inline int utmp_get_runlevel(int *runlevel, int *previous) { + return -ESRCH; +} +static inline int utmp_put_shutdown(void) { + return 0; +} +static inline int utmp_put_reboot(usec_t timestamp) { + return 0; +} +static inline int utmp_put_runlevel(int runlevel, int previous) { + return 0; +} +static inline int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) { + return 0; +} +static inline int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line, int ut_type, const char *user) { + return 0; +} +static inline int utmp_wall( + const char *message, + const char *username, + const char *origin_tty, + bool (*match_tty)(const char *tty, void *userdata), + void *userdata) { + return 0; +} + +#endif /* ENABLE_UTMP */ diff --git a/src/shared/varlink.c b/src/shared/varlink.c new file mode 100644 index 00000000..ee4fb9e8 --- /dev/null +++ b/src/shared/varlink.c @@ -0,0 +1,2459 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "hashmap.h" +#include "list.h" +#include "process-util.h" +#include "set.h" +#include "socket-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "umask-util.h" +#include "user-util.h" +#include "varlink.h" + +#define VARLINK_DEFAULT_CONNECTIONS_MAX 4096U +#define VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX 1024U + +#define VARLINK_DEFAULT_TIMEOUT_USEC (45U*USEC_PER_SEC) +#define VARLINK_BUFFER_MAX (16U*1024U*1024U) +#define VARLINK_READ_SIZE (64U*1024U) + +typedef enum VarlinkState { + /* Client side states */ + VARLINK_IDLE_CLIENT, + VARLINK_AWAITING_REPLY, + VARLINK_AWAITING_REPLY_MORE, + VARLINK_CALLING, + VARLINK_CALLED, + VARLINK_PROCESSING_REPLY, + + /* Server side states */ + VARLINK_IDLE_SERVER, + VARLINK_PROCESSING_METHOD, + VARLINK_PROCESSING_METHOD_MORE, + VARLINK_PROCESSING_METHOD_ONEWAY, + VARLINK_PROCESSED_METHOD, + VARLINK_PENDING_METHOD, + VARLINK_PENDING_METHOD_MORE, + + /* Common states (only during shutdown) */ + VARLINK_PENDING_DISCONNECT, + VARLINK_PENDING_TIMEOUT, + VARLINK_PROCESSING_DISCONNECT, + VARLINK_PROCESSING_TIMEOUT, + VARLINK_PROCESSING_FAILURE, + VARLINK_DISCONNECTED, + + _VARLINK_STATE_MAX, + _VARLINK_STATE_INVALID = -1 +} VarlinkState; + +/* Tests whether we are not yet disconnected. Note that this is true during all states where the connection + * is still good for something, and false only when it's dead for good. This means: when we are + * asynchronously connecting to a peer and the connect() is still pending, then this will return 'true', as + * the connection is still good, and we are likely to be able to properly operate on it soon. */ +#define VARLINK_STATE_IS_ALIVE(state) \ + IN_SET(state, \ + VARLINK_IDLE_CLIENT, \ + VARLINK_AWAITING_REPLY, \ + VARLINK_AWAITING_REPLY_MORE, \ + VARLINK_CALLING, \ + VARLINK_CALLED, \ + VARLINK_PROCESSING_REPLY, \ + VARLINK_IDLE_SERVER, \ + VARLINK_PROCESSING_METHOD, \ + VARLINK_PROCESSING_METHOD_MORE, \ + VARLINK_PROCESSING_METHOD_ONEWAY, \ + VARLINK_PROCESSED_METHOD, \ + VARLINK_PENDING_METHOD, \ + VARLINK_PENDING_METHOD_MORE) + +struct Varlink { + unsigned n_ref; + + VarlinkServer *server; + + VarlinkState state; + bool connecting; /* This boolean indicates whether the socket fd we are operating on is currently + * processing an asynchronous connect(). In that state we watch the socket for + * EPOLLOUT, but we refrain from calling read() or write() on the socket as that + * will trigger ENOTCONN. Note that this boolean is kept separate from the + * VarlinkState above on purpose: while the connect() is still not complete we + * already want to allow queuing of messages and similar. Thus it's nice to keep + * these two state concepts separate: the VarlinkState encodes what our own view of + * the connection is, i.e. whether we think it's a server, a client, and has + * something queued already, while 'connecting' tells us a detail about the + * transport used below, that should have no effect on how we otherwise accept and + * process operations from the user. + * + * Or to say this differently: VARLINK_STATE_IS_ALIVE(state) tells you whether the + * connection is good to use, even if it might not be fully connected + * yet. connecting=true then informs you that actually we are still connecting, and + * the connection is actually not established yet and thus any requests you enqueue + * now will still work fine but will be queued only, not sent yet, but that + * shouldn't stop you from using the connection, since eventually whatever you queue + * *will* be sent. + * + * Or to say this even differently: 'state' is a high-level ("application layer" + * high, if you so will) state, while 'conecting' is a low-level ("transport layer" + * low, if you so will) state, and while they are not entirely unrelated and + * sometimes propagate effects to each other they are only asynchronously connected + * at most. */ + unsigned n_pending; + + int fd; + + char *input_buffer; /* valid data starts at input_buffer_index, ends at input_buffer_index+input_buffer_size */ + size_t input_buffer_allocated; + size_t input_buffer_index; + size_t input_buffer_size; + size_t input_buffer_unscanned; + + char *output_buffer; /* valid data starts at output_buffer_index, ends at output_buffer_index+output_buffer_size */ + size_t output_buffer_allocated; + size_t output_buffer_index; + size_t output_buffer_size; + + VarlinkReply reply_callback; + + JsonVariant *current; + JsonVariant *reply; + + struct ucred ucred; + bool ucred_acquired:1; + + bool write_disconnected:1; + bool read_disconnected:1; + bool prefer_read_write:1; + bool got_pollhup:1; + + usec_t timestamp; + usec_t timeout; + + void *userdata; + char *description; + + sd_event *event; + sd_event_source *io_event_source; + sd_event_source *time_event_source; + sd_event_source *quit_event_source; + sd_event_source *defer_event_source; +}; + +typedef struct VarlinkServerSocket VarlinkServerSocket; + +struct VarlinkServerSocket { + VarlinkServer *server; + + int fd; + char *address; + + sd_event_source *event_source; + + LIST_FIELDS(VarlinkServerSocket, sockets); +}; + +struct VarlinkServer { + unsigned n_ref; + VarlinkServerFlags flags; + + LIST_HEAD(VarlinkServerSocket, sockets); + + Hashmap *methods; + VarlinkConnect connect_callback; + + sd_event *event; + int64_t event_priority; + + unsigned n_connections; + Hashmap *by_uid; + + void *userdata; + char *description; + + unsigned connections_max; + unsigned connections_per_uid_max; +}; + +static const char* const varlink_state_table[_VARLINK_STATE_MAX] = { + [VARLINK_IDLE_CLIENT] = "idle-client", + [VARLINK_AWAITING_REPLY] = "awaiting-reply", + [VARLINK_AWAITING_REPLY_MORE] = "awaiting-reply-more", + [VARLINK_CALLING] = "calling", + [VARLINK_CALLED] = "called", + [VARLINK_PROCESSING_REPLY] = "processing-reply", + [VARLINK_IDLE_SERVER] = "idle-server", + [VARLINK_PROCESSING_METHOD] = "processing-method", + [VARLINK_PROCESSING_METHOD_MORE] = "processing-method-more", + [VARLINK_PROCESSING_METHOD_ONEWAY] = "processing-method-oneway", + [VARLINK_PROCESSED_METHOD] = "processed-method", + [VARLINK_PENDING_METHOD] = "pending-method", + [VARLINK_PENDING_METHOD_MORE] = "pending-method-more", + [VARLINK_PENDING_DISCONNECT] = "pending-disconnect", + [VARLINK_PENDING_TIMEOUT] = "pending-timeout", + [VARLINK_PROCESSING_DISCONNECT] = "processing-disconnect", + [VARLINK_PROCESSING_TIMEOUT] = "processing-timeout", + [VARLINK_PROCESSING_FAILURE] = "processing-failure", + [VARLINK_DISCONNECTED] = "disconnected", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(varlink_state, VarlinkState); + +#define varlink_log_errno(v, error, fmt, ...) \ + log_debug_errno(error, "%s: " fmt, varlink_description(v), ##__VA_ARGS__) + +#define varlink_log(v, fmt, ...) \ + log_debug("%s: " fmt, varlink_description(v), ##__VA_ARGS__) + +#define varlink_server_log_errno(s, error, fmt, ...) \ + log_debug_errno(error, "%s: " fmt, varlink_server_description(s), ##__VA_ARGS__) + +#define varlink_server_log(s, fmt, ...) \ + log_debug("%s: " fmt, varlink_server_description(s), ##__VA_ARGS__) + +static inline const char *varlink_description(Varlink *v) { + return strna(v ? v->description : NULL); +} + +static inline const char *varlink_server_description(VarlinkServer *s) { + return strna(s ? s->description : NULL); +} + +static void varlink_set_state(Varlink *v, VarlinkState state) { + assert(v); + assert(state >= 0 && state < _VARLINK_STATE_MAX); + + if (v->state < 0) + varlink_log(v, "varlink: setting state %s", + varlink_state_to_string(state)); + else + varlink_log(v, "varlink: changing state %s → %s", + varlink_state_to_string(v->state), + varlink_state_to_string(state)); + + v->state = state; +} + +static int varlink_new(Varlink **ret) { + Varlink *v; + + assert(ret); + + v = new(Varlink, 1); + if (!v) + return -ENOMEM; + + *v = (Varlink) { + .n_ref = 1, + .fd = -1, + + .state = _VARLINK_STATE_INVALID, + + .ucred.uid = UID_INVALID, + .ucred.gid = GID_INVALID, + + .timestamp = USEC_INFINITY, + .timeout = VARLINK_DEFAULT_TIMEOUT_USEC + }; + + *ret = v; + return 0; +} + +int varlink_connect_address(Varlink **ret, const char *address) { + _cleanup_(varlink_unrefp) Varlink *v = NULL; + union sockaddr_union sockaddr; + int r; + + assert_return(ret, -EINVAL); + assert_return(address, -EINVAL); + + r = sockaddr_un_set_path(&sockaddr.un, address); + if (r < 0) + return r; + + r = varlink_new(&v); + if (r < 0) + return r; + + v->fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (v->fd < 0) + return -errno; + + v->fd = fd_move_above_stdio(v->fd); + + if (connect(v->fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0) { + if (!IN_SET(errno, EAGAIN, EINPROGRESS)) + return -errno; + + v->connecting = true; /* We are asynchronously connecting, i.e. the connect() is being + * processed in the background. As long as that's the case the socket + * is in a special state: it's there, we can poll it for EPOLLOUT, but + * if we attempt to write() to it before we see EPOLLOUT we'll get + * ENOTCONN (and not EAGAIN, like we would for a normal connected + * socket that isn't writable at the moment). Since ENOTCONN on write() + * hence can mean two different things (i.e. connection not complete + * yet vs. already disconnected again), we store as a boolean whether + * we are still in connect(). */ + } + + varlink_set_state(v, VARLINK_IDLE_CLIENT); + + *ret = TAKE_PTR(v); + return r; +} + +int varlink_connect_fd(Varlink **ret, int fd) { + Varlink *v; + int r; + + assert_return(ret, -EINVAL); + assert_return(fd >= 0, -EBADF); + + r = fd_nonblock(fd, true); + if (r < 0) + return r; + + r = varlink_new(&v); + if (r < 0) + return r; + + v->fd = fd; + varlink_set_state(v, VARLINK_IDLE_CLIENT); + + /* Note that if this function is called we assume the passed socket (if it is one) is already + * properly connected, i.e. any asynchronous connect() done on it already completed. Because of that + * we'll not set the 'connecting' boolean here, i.e. we don't need to avoid write()ing to the socket + * until the connection is fully set up. Behaviour here is hence a bit different from + * varlink_connect_address() above, as there we do handle asynchronous connections ourselves and + * avoid doing write() on it before we saw EPOLLOUT for the first time. */ + + *ret = v; + return 0; +} + +static void varlink_detach_event_sources(Varlink *v) { + assert(v); + + v->io_event_source = sd_event_source_disable_unref(v->io_event_source); + v->time_event_source = sd_event_source_disable_unref(v->time_event_source); + v->quit_event_source = sd_event_source_disable_unref(v->quit_event_source); + v->defer_event_source = sd_event_source_disable_unref(v->defer_event_source); +} + +static void varlink_clear(Varlink *v) { + assert(v); + + varlink_detach_event_sources(v); + + v->fd = safe_close(v->fd); + + v->input_buffer = mfree(v->input_buffer); + v->output_buffer = mfree(v->output_buffer); + + v->current = json_variant_unref(v->current); + v->reply = json_variant_unref(v->reply); + + v->event = sd_event_unref(v->event); +} + +static Varlink* varlink_destroy(Varlink *v) { + if (!v) + return NULL; + + /* If this is called the server object must already been unreffed here. Why that? because when we + * linked up the varlink connection with the server object we took one ref in each direction */ + assert(!v->server); + + varlink_clear(v); + + free(v->description); + return mfree(v); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(Varlink, varlink, varlink_destroy); + +static int varlink_test_disconnect(Varlink *v) { + assert(v); + + /* Tests whether we the the connection has been terminated. We are careful to not stop processing it + * prematurely, since we want to handle half-open connections as well as possible and want to flush + * out and read data before we close down if we can. */ + + /* Already disconnected? */ + if (!VARLINK_STATE_IS_ALIVE(v->state)) + return 0; + + /* Wait until connection setup is complete, i.e. until asynchronous connect() completes */ + if (v->connecting) + return 0; + + /* Still something to write and we can write? Stay around */ + if (v->output_buffer_size > 0 && !v->write_disconnected) + return 0; + + /* Both sides gone already? Then there's no need to stick around */ + if (v->read_disconnected && v->write_disconnected) + goto disconnect; + + /* If we are waiting for incoming data but the read side is shut down, disconnect. */ + if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING, VARLINK_IDLE_SERVER) && v->read_disconnected) + goto disconnect; + + /* Similar, if are a client that hasn't written anything yet but the write side is dead, also + * disconnect. We also explicitly check for POLLHUP here since we likely won't notice the write side + * being down if we never wrote anything. */ + if (IN_SET(v->state, VARLINK_IDLE_CLIENT) && (v->write_disconnected || v->got_pollhup)) + goto disconnect; + + return 0; + +disconnect: + varlink_set_state(v, VARLINK_PENDING_DISCONNECT); + return 1; +} + +static int varlink_write(Varlink *v) { + ssize_t n; + + assert(v); + + if (!VARLINK_STATE_IS_ALIVE(v->state)) + return 0; + if (v->connecting) /* Writing while we are still wait for a non-blocking connect() to complete will + * result in ENOTCONN, hence exit early here */ + return 0; + if (v->output_buffer_size == 0) + return 0; + if (v->write_disconnected) + return 0; + + assert(v->fd >= 0); + + /* We generally prefer recv()/send() (mostly because of MSG_NOSIGNAL) but also want to be compatible + * with non-socket IO, hence fall back automatically */ + if (!v->prefer_read_write) { + n = send(v->fd, v->output_buffer + v->output_buffer_index, v->output_buffer_size, MSG_DONTWAIT|MSG_NOSIGNAL); + if (n < 0 && errno == ENOTSOCK) + v->prefer_read_write = true; + } + if (v->prefer_read_write) + n = write(v->fd, v->output_buffer + v->output_buffer_index, v->output_buffer_size); + if (n < 0) { + if (errno == EAGAIN) + return 0; + + if (ERRNO_IS_DISCONNECT(errno)) { + /* If we get informed about a disconnect on write, then let's remember that, but not + * act on it just yet. Let's wait for read() to report the issue first. */ + v->write_disconnected = true; + return 1; + } + + return -errno; + } + + v->output_buffer_size -= n; + + if (v->output_buffer_size == 0) + v->output_buffer_index = 0; + else + v->output_buffer_index += n; + + v->timestamp = now(CLOCK_MONOTONIC); + return 1; +} + +static int varlink_read(Varlink *v) { + size_t rs; + ssize_t n; + + assert(v); + + if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING, VARLINK_IDLE_SERVER)) + return 0; + if (v->connecting) /* read() on a socket while we are in connect() will fail with EINVAL, hence exit early here */ + return 0; + if (v->current) + return 0; + if (v->input_buffer_unscanned > 0) + return 0; + if (v->read_disconnected) + return 0; + + if (v->input_buffer_size >= VARLINK_BUFFER_MAX) + return -ENOBUFS; + + assert(v->fd >= 0); + + if (v->input_buffer_allocated <= v->input_buffer_index + v->input_buffer_size) { + size_t add; + + add = MIN(VARLINK_BUFFER_MAX - v->input_buffer_size, VARLINK_READ_SIZE); + + if (v->input_buffer_index == 0) { + + if (!GREEDY_REALLOC(v->input_buffer, v->input_buffer_allocated, v->input_buffer_size + add)) + return -ENOMEM; + + } else { + char *b; + + b = new(char, v->input_buffer_size + add); + if (!b) + return -ENOMEM; + + memcpy(b, v->input_buffer + v->input_buffer_index, v->input_buffer_size); + + free_and_replace(v->input_buffer, b); + + v->input_buffer_allocated = v->input_buffer_size + add; + v->input_buffer_index = 0; + } + } + + rs = v->input_buffer_allocated - (v->input_buffer_index + v->input_buffer_size); + + if (!v->prefer_read_write) { + n = recv(v->fd, v->input_buffer + v->input_buffer_index + v->input_buffer_size, rs, MSG_DONTWAIT); + if (n < 0 && errno == ENOTSOCK) + v->prefer_read_write = true; + } + if (v->prefer_read_write) + n = read(v->fd, v->input_buffer + v->input_buffer_index + v->input_buffer_size, rs); + if (n < 0) { + if (errno == EAGAIN) + return 0; + + if (ERRNO_IS_DISCONNECT(errno)) { + v->read_disconnected = true; + return 1; + } + + return -errno; + } + if (n == 0) { /* EOF */ + v->read_disconnected = true; + return 1; + } + + v->input_buffer_size += n; + v->input_buffer_unscanned += n; + + return 1; +} + +static int varlink_parse_message(Varlink *v) { + const char *e, *begin; + size_t sz; + int r; + + assert(v); + + if (v->current) + return 0; + if (v->input_buffer_unscanned <= 0) + return 0; + + assert(v->input_buffer_unscanned <= v->input_buffer_size); + assert(v->input_buffer_index + v->input_buffer_size <= v->input_buffer_allocated); + + begin = v->input_buffer + v->input_buffer_index; + + e = memchr(begin + v->input_buffer_size - v->input_buffer_unscanned, 0, v->input_buffer_unscanned); + if (!e) { + v->input_buffer_unscanned = 0; + return 0; + } + + sz = e - begin + 1; + + varlink_log(v, "New incoming message: %s", begin); + + r = json_parse(begin, &v->current, NULL, NULL); + if (r < 0) + return r; + + v->input_buffer_size -= sz; + + if (v->input_buffer_size == 0) + v->input_buffer_index = 0; + else + v->input_buffer_index += sz; + + v->input_buffer_unscanned = v->input_buffer_size; + return 1; +} + +static int varlink_test_timeout(Varlink *v) { + assert(v); + + if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING)) + return 0; + if (v->timeout == USEC_INFINITY) + return 0; + + if (now(CLOCK_MONOTONIC) < usec_add(v->timestamp, v->timeout)) + return 0; + + varlink_set_state(v, VARLINK_PENDING_TIMEOUT); + + return 1; +} + +static int varlink_dispatch_local_error(Varlink *v, const char *error) { + int r; + + assert(v); + assert(error); + + if (!v->reply_callback) + return 0; + + r = v->reply_callback(v, NULL, error, VARLINK_REPLY_ERROR|VARLINK_REPLY_LOCAL, v->userdata); + if (r < 0) + log_debug_errno(r, "Reply callback returned error, ignoring: %m"); + + return 1; +} + +static int varlink_dispatch_timeout(Varlink *v) { + assert(v); + + if (v->state != VARLINK_PENDING_TIMEOUT) + return 0; + + varlink_set_state(v, VARLINK_PROCESSING_TIMEOUT); + varlink_dispatch_local_error(v, VARLINK_ERROR_TIMEOUT); + varlink_close(v); + + return 1; +} + +static int varlink_dispatch_disconnect(Varlink *v) { + assert(v); + + if (v->state != VARLINK_PENDING_DISCONNECT) + return 0; + + varlink_set_state(v, VARLINK_PROCESSING_DISCONNECT); + varlink_dispatch_local_error(v, VARLINK_ERROR_DISCONNECTED); + varlink_close(v); + + return 1; +} + +static int varlink_sanitize_parameters(JsonVariant **v) { + assert(v); + + /* Varlink always wants a parameters list, hence make one if the caller doesn't want any */ + if (!*v) + return json_variant_new_object(v, NULL, 0); + else if (!json_variant_is_object(*v)) + return -EINVAL; + + return 0; +} + +static int varlink_dispatch_reply(Varlink *v) { + _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL; + VarlinkReplyFlags flags = 0; + const char *error = NULL; + JsonVariant *e; + const char *k; + int r; + + assert(v); + + if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING)) + return 0; + if (!v->current) + return 0; + + assert(v->n_pending > 0); + + if (!json_variant_is_object(v->current)) + goto invalid; + + JSON_VARIANT_OBJECT_FOREACH(k, e, v->current) { + + if (streq(k, "error")) { + if (error) + goto invalid; + if (!json_variant_is_string(e)) + goto invalid; + + error = json_variant_string(e); + flags |= VARLINK_REPLY_ERROR; + + } else if (streq(k, "parameters")) { + if (parameters) + goto invalid; + if (!json_variant_is_object(e)) + goto invalid; + + parameters = json_variant_ref(e); + + } else if (streq(k, "continues")) { + if (FLAGS_SET(flags, VARLINK_REPLY_CONTINUES)) + goto invalid; + + if (!json_variant_is_boolean(e)) + goto invalid; + + if (json_variant_boolean(e)) + flags |= VARLINK_REPLY_CONTINUES; + } else + goto invalid; + } + + /* Replies with 'continue' set are only OK if we set 'more' when the method call was initiated */ + if (v->state != VARLINK_AWAITING_REPLY_MORE && FLAGS_SET(flags, VARLINK_REPLY_CONTINUES)) + goto invalid; + + /* An error is final */ + if (error && FLAGS_SET(flags, VARLINK_REPLY_CONTINUES)) + goto invalid; + + r = varlink_sanitize_parameters(¶meters); + if (r < 0) + goto invalid; + + if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE)) { + varlink_set_state(v, VARLINK_PROCESSING_REPLY); + + if (v->reply_callback) { + r = v->reply_callback(v, parameters, error, flags, v->userdata); + if (r < 0) + log_debug_errno(r, "Reply callback returned error, ignoring: %m"); + } + + v->current = json_variant_unref(v->current); + + if (v->state == VARLINK_PROCESSING_REPLY) { + + assert(v->n_pending > 0); + + if (!FLAGS_SET(flags, VARLINK_REPLY_CONTINUES)) + v->n_pending--; + + varlink_set_state(v, + FLAGS_SET(flags, VARLINK_REPLY_CONTINUES) ? VARLINK_AWAITING_REPLY_MORE : + v->n_pending == 0 ? VARLINK_IDLE_CLIENT : VARLINK_AWAITING_REPLY); + } + } else { + assert(v->state == VARLINK_CALLING); + varlink_set_state(v, VARLINK_CALLED); + } + + return 1; + +invalid: + varlink_set_state(v, VARLINK_PROCESSING_FAILURE); + varlink_dispatch_local_error(v, VARLINK_ERROR_PROTOCOL); + varlink_close(v); + + return 1; +} + +static int varlink_dispatch_method(Varlink *v) { + _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL; + VarlinkMethodFlags flags = 0; + const char *method = NULL, *error; + JsonVariant *e; + VarlinkMethod callback; + const char *k; + int r; + + assert(v); + + if (v->state != VARLINK_IDLE_SERVER) + return 0; + if (!v->current) + return 0; + + if (!json_variant_is_object(v->current)) + goto invalid; + + JSON_VARIANT_OBJECT_FOREACH(k, e, v->current) { + + if (streq(k, "method")) { + if (method) + goto invalid; + if (!json_variant_is_string(e)) + goto invalid; + + method = json_variant_string(e); + + } else if (streq(k, "parameters")) { + if (parameters) + goto invalid; + if (!json_variant_is_object(e)) + goto invalid; + + parameters = json_variant_ref(e); + + } else if (streq(k, "oneway")) { + + if ((flags & (VARLINK_METHOD_ONEWAY|VARLINK_METHOD_MORE)) != 0) + goto invalid; + + if (!json_variant_is_boolean(e)) + goto invalid; + + if (json_variant_boolean(e)) + flags |= VARLINK_METHOD_ONEWAY; + + } else if (streq(k, "more")) { + + if ((flags & (VARLINK_METHOD_ONEWAY|VARLINK_METHOD_MORE)) != 0) + goto invalid; + + if (!json_variant_is_boolean(e)) + goto invalid; + + if (json_variant_boolean(e)) + flags |= VARLINK_METHOD_MORE; + + } else + goto invalid; + } + + if (!method) + goto invalid; + + r = varlink_sanitize_parameters(¶meters); + if (r < 0) + goto fail; + + varlink_set_state(v, (flags & VARLINK_METHOD_MORE) ? VARLINK_PROCESSING_METHOD_MORE : + (flags & VARLINK_METHOD_ONEWAY) ? VARLINK_PROCESSING_METHOD_ONEWAY : + VARLINK_PROCESSING_METHOD); + + assert(v->server); + + if (STR_IN_SET(method, "org.varlink.service.GetInfo", "org.varlink.service.GetInterface")) { + /* For now, we don't implement a single of varlink's own methods */ + callback = NULL; + error = VARLINK_ERROR_METHOD_NOT_IMPLEMENTED; + } else if (startswith(method, "org.varlink.service.")) { + callback = NULL; + error = VARLINK_ERROR_METHOD_NOT_FOUND; + } else { + callback = hashmap_get(v->server->methods, method); + error = VARLINK_ERROR_METHOD_NOT_FOUND; + } + + if (callback) { + r = callback(v, parameters, flags, v->userdata); + if (r < 0) { + log_debug_errno(r, "Callback for %s returned error: %m", method); + + /* We got an error back from the callback. Propagate it to the client if the method call remains unanswered. */ + if (!FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) { + r = varlink_errorb(v, VARLINK_ERROR_SYSTEM, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("errno", JSON_BUILD_INTEGER(-r)))); + if (r < 0) + return r; + } + } + } else if (!FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) { + assert(error); + + r = varlink_errorb(v, error, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)))); + if (r < 0) + return r; + } + + switch (v->state) { + + case VARLINK_PROCESSED_METHOD: /* Method call is fully processed */ + case VARLINK_PROCESSING_METHOD_ONEWAY: /* ditto */ + v->current = json_variant_unref(v->current); + varlink_set_state(v, VARLINK_IDLE_SERVER); + break; + + case VARLINK_PROCESSING_METHOD: /* Method call wasn't replied to, will be replied to later */ + varlink_set_state(v, VARLINK_PENDING_METHOD); + break; + + case VARLINK_PROCESSING_METHOD_MORE: /* No reply for a "more" message was sent, more to come */ + varlink_set_state(v, VARLINK_PENDING_METHOD_MORE); + break; + + default: + assert_not_reached("Unexpected state"); + + } + + return r; + +invalid: + r = -EINVAL; + +fail: + varlink_set_state(v, VARLINK_PROCESSING_FAILURE); + varlink_dispatch_local_error(v, VARLINK_ERROR_PROTOCOL); + varlink_close(v); + + return r; +} + +int varlink_process(Varlink *v) { + int r; + + assert_return(v, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + + varlink_ref(v); + + r = varlink_write(v); + if (r != 0) + goto finish; + + r = varlink_dispatch_reply(v); + if (r != 0) + goto finish; + + r = varlink_dispatch_method(v); + if (r != 0) + goto finish; + + r = varlink_parse_message(v); + if (r != 0) + goto finish; + + r = varlink_read(v); + if (r != 0) + goto finish; + + r = varlink_test_disconnect(v); + if (r != 0) + goto finish; + + r = varlink_dispatch_disconnect(v); + if (r != 0) + goto finish; + + r = varlink_test_timeout(v); + if (r != 0) + goto finish; + + r = varlink_dispatch_timeout(v); + if (r != 0) + goto finish; + +finish: + if (r >= 0 && v->defer_event_source) { + int q; + + /* If we did some processing, make sure we are called again soon */ + q = sd_event_source_set_enabled(v->defer_event_source, r > 0 ? SD_EVENT_ON : SD_EVENT_OFF); + if (q < 0) + r = q; + } + + if (r < 0) { + if (VARLINK_STATE_IS_ALIVE(v->state)) + /* Initiate disconnection */ + varlink_set_state(v, VARLINK_PENDING_DISCONNECT); + else + /* We failed while disconnecting, in that case close right away */ + varlink_close(v); + } + + varlink_unref(v); + return r; +} + +static void handle_revents(Varlink *v, int revents) { + assert(v); + + if (v->connecting) { + /* If we have seen POLLOUT or POLLHUP on a socket we are asynchronously waiting a connect() + * to complete on, we know we are ready. We don't read the connection error here though, + * we'll get the error on the next read() or write(). */ + if ((revents & (POLLOUT|POLLHUP)) == 0) + return; + + varlink_log(v, "Anynchronous connection completed."); + v->connecting = false; + } else { + /* Note that we don't care much about POLLIN/POLLOUT here, we'll just try reading and writing + * what we can. However, we do care about POLLHUP to detect connection termination even if we + * momentarily don't want to read nor write anything. */ + + if (!FLAGS_SET(revents, POLLHUP)) + return; + + varlink_log(v, "Got POLLHUP from socket."); + v->got_pollhup = true; + } +} + +int varlink_wait(Varlink *v, usec_t timeout) { + struct timespec ts; + struct pollfd pfd; + int r, fd, events; + usec_t t; + + assert_return(v, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + + r = varlink_get_timeout(v, &t); + if (r < 0) + return r; + if (t != USEC_INFINITY) { + usec_t n; + + n = now(CLOCK_MONOTONIC); + if (t < n) + t = 0; + else + t = usec_sub_unsigned(t, n); + } + + if (timeout != USEC_INFINITY && + (t == USEC_INFINITY || timeout < t)) + t = timeout; + + fd = varlink_get_fd(v); + if (fd < 0) + return fd; + + events = varlink_get_events(v); + if (events < 0) + return events; + + pfd = (struct pollfd) { + .fd = fd, + .events = events, + }; + + r = ppoll(&pfd, 1, + t == USEC_INFINITY ? NULL : timespec_store(&ts, t), + NULL); + if (r < 0) + return -errno; + + handle_revents(v, pfd.revents); + + return r > 0 ? 1 : 0; +} + +int varlink_get_fd(Varlink *v) { + + assert_return(v, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + if (v->fd < 0) + return -EBADF; + + return v->fd; +} + +int varlink_get_events(Varlink *v) { + int ret = 0; + + assert_return(v, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + + if (v->connecting) /* When processing an asynchronous connect(), we only wait for EPOLLOUT, which + * tells us that the connection is now complete. Before that we should neither + * write() or read() from the fd. */ + return EPOLLOUT; + + if (!v->read_disconnected && + IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING, VARLINK_IDLE_SERVER) && + !v->current && + v->input_buffer_unscanned <= 0) + ret |= EPOLLIN; + + if (!v->write_disconnected && + v->output_buffer_size > 0) + ret |= EPOLLOUT; + + return ret; +} + +int varlink_get_timeout(Varlink *v, usec_t *ret) { + assert_return(v, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + + if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING) && + v->timeout != USEC_INFINITY) { + if (ret) + *ret = usec_add(v->timestamp, v->timeout); + return 1; + } else { + if (ret) + *ret = USEC_INFINITY; + return 0; + } +} + +int varlink_flush(Varlink *v) { + int ret = 0, r; + + assert_return(v, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + + for (;;) { + struct pollfd pfd; + + if (v->output_buffer_size == 0) + break; + if (v->write_disconnected) + return -ECONNRESET; + + r = varlink_write(v); + if (r < 0) + return r; + if (r > 0) { + ret = 1; + continue; + } + + pfd = (struct pollfd) { + .fd = v->fd, + .events = POLLOUT, + }; + + if (poll(&pfd, 1, -1) < 0) + return -errno; + + handle_revents(v, pfd.revents); + } + + return ret; +} + +static void varlink_detach_server(Varlink *v) { + assert(v); + + if (!v->server) + return; + + if (v->server->by_uid && + v->ucred_acquired && + uid_is_valid(v->ucred.uid)) { + unsigned c; + + c = PTR_TO_UINT(hashmap_get(v->server->by_uid, UID_TO_PTR(v->ucred.uid))); + assert(c > 0); + + if (c == 1) + (void) hashmap_remove(v->server->by_uid, UID_TO_PTR(v->ucred.uid)); + else + (void) hashmap_replace(v->server->by_uid, UID_TO_PTR(v->ucred.uid), UINT_TO_PTR(c - 1)); + } + + assert(v->server->n_connections > 0); + v->server->n_connections--; + + /* If this is a connection associated to a server, then let's disconnect the server and the + * connection from each other. This drops the dangling reference that connect_callback() set up. */ + v->server = varlink_server_unref(v->server); + varlink_unref(v); +} + +int varlink_close(Varlink *v) { + + assert_return(v, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return 0; + + varlink_set_state(v, VARLINK_DISCONNECTED); + + /* Let's take a reference first, since varlink_detach_server() might drop the final (dangling) ref + * which would destroy us before we can call varlink_clear() */ + varlink_ref(v); + varlink_detach_server(v); + varlink_clear(v); + varlink_unref(v); + + return 1; +} + +Varlink* varlink_flush_close_unref(Varlink *v) { + + if (!v) + return NULL; + + (void) varlink_flush(v); + (void) varlink_close(v); + + return varlink_unref(v); +} + +static int varlink_enqueue_json(Varlink *v, JsonVariant *m) { + _cleanup_free_ char *text = NULL; + int r; + + assert(v); + assert(m); + + r = json_variant_format(m, 0, &text); + if (r < 0) + return r; + assert(text[r] == '\0'); + + if (v->output_buffer_size + r + 1 > VARLINK_BUFFER_MAX) + return -ENOBUFS; + + varlink_log(v, "Sending message: %s", text); + + if (v->output_buffer_size == 0) { + + free_and_replace(v->output_buffer, text); + + v->output_buffer_size = v->output_buffer_allocated = r + 1; + v->output_buffer_index = 0; + + } else if (v->output_buffer_index == 0) { + + if (!GREEDY_REALLOC(v->output_buffer, v->output_buffer_allocated, v->output_buffer_size + r + 1)) + return -ENOMEM; + + memcpy(v->output_buffer + v->output_buffer_size, text, r + 1); + v->output_buffer_size += r + 1; + + } else { + char *n; + const size_t new_size = v->output_buffer_size + r + 1; + + n = new(char, new_size); + if (!n) + return -ENOMEM; + + memcpy(mempcpy(n, v->output_buffer + v->output_buffer_index, v->output_buffer_size), text, r + 1); + + free_and_replace(v->output_buffer, n); + v->output_buffer_allocated = v->output_buffer_size = new_size; + v->output_buffer_index = 0; + } + + return 0; +} + +int varlink_send(Varlink *v, const char *method, JsonVariant *parameters) { + _cleanup_(json_variant_unrefp) JsonVariant *m = NULL; + int r; + + assert_return(v, -EINVAL); + assert_return(method, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + + /* We allow enqueuing multiple method calls at once! */ + if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY)) + return -EBUSY; + + r = varlink_sanitize_parameters(¶meters); + if (r < 0) + return r; + + r = json_build(&m, JSON_BUILD_OBJECT( + JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)), + JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)), + JSON_BUILD_PAIR("oneway", JSON_BUILD_BOOLEAN(true)))); + if (r < 0) + return r; + + r = varlink_enqueue_json(v, m); + if (r < 0) + return r; + + /* No state change here, this is one-way only after all */ + v->timestamp = now(CLOCK_MONOTONIC); + return 0; +} + +int varlink_sendb(Varlink *v, const char *method, ...) { + _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL; + va_list ap; + int r; + + assert_return(v, -EINVAL); + + va_start(ap, method); + r = json_buildv(¶meters, ap); + va_end(ap); + + if (r < 0) + return r; + + return varlink_send(v, method, parameters); +} + +int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters) { + _cleanup_(json_variant_unrefp) JsonVariant *m = NULL; + int r; + + assert_return(v, -EINVAL); + assert_return(method, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + + /* We allow enqueing multiple method calls at once! */ + if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY)) + return -EBUSY; + + r = varlink_sanitize_parameters(¶meters); + if (r < 0) + return r; + + r = json_build(&m, JSON_BUILD_OBJECT( + JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)), + JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)))); + if (r < 0) + return r; + + r = varlink_enqueue_json(v, m); + if (r < 0) + return r; + + varlink_set_state(v, VARLINK_AWAITING_REPLY); + v->n_pending++; + v->timestamp = now(CLOCK_MONOTONIC); + + return 0; +} + +int varlink_invokeb(Varlink *v, const char *method, ...) { + _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL; + va_list ap; + int r; + + assert_return(v, -EINVAL); + + va_start(ap, method); + r = json_buildv(¶meters, ap); + va_end(ap); + + if (r < 0) + return r; + + return varlink_invoke(v, method, parameters); +} + +int varlink_observe(Varlink *v, const char *method, JsonVariant *parameters) { + _cleanup_(json_variant_unrefp) JsonVariant *m = NULL; + int r; + + assert_return(v, -EINVAL); + assert_return(method, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + /* Note that we don't allow enqueuing multiple method calls when we are in more/continues mode! We + * thus insist on an idle client here. */ + if (v->state != VARLINK_IDLE_CLIENT) + return -EBUSY; + + r = varlink_sanitize_parameters(¶meters); + if (r < 0) + return r; + + r = json_build(&m, JSON_BUILD_OBJECT( + JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)), + JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)), + JSON_BUILD_PAIR("more", JSON_BUILD_BOOLEAN(true)))); + if (r < 0) + return r; + + r = varlink_enqueue_json(v, m); + if (r < 0) + return r; + + + varlink_set_state(v, VARLINK_AWAITING_REPLY_MORE); + v->n_pending++; + v->timestamp = now(CLOCK_MONOTONIC); + + return 0; +} + +int varlink_observeb(Varlink *v, const char *method, ...) { + _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL; + va_list ap; + int r; + + assert_return(v, -EINVAL); + + va_start(ap, method); + r = json_buildv(¶meters, ap); + va_end(ap); + + if (r < 0) + return r; + + return varlink_observe(v, method, parameters); +} + +int varlink_call( + Varlink *v, + const char *method, + JsonVariant *parameters, + JsonVariant **ret_parameters, + const char **ret_error_id, + VarlinkReplyFlags *ret_flags) { + + _cleanup_(json_variant_unrefp) JsonVariant *m = NULL; + int r; + + assert_return(v, -EINVAL); + assert_return(method, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + if (!IN_SET(v->state, VARLINK_IDLE_CLIENT)) + return -EBUSY; + + assert(v->n_pending == 0); /* n_pending can't be > 0 if we are in VARLINK_IDLE_CLIENT state */ + + r = varlink_sanitize_parameters(¶meters); + if (r < 0) + return r; + + r = json_build(&m, JSON_BUILD_OBJECT( + JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)), + JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)))); + if (r < 0) + return r; + + r = varlink_enqueue_json(v, m); + if (r < 0) + return r; + + varlink_set_state(v, VARLINK_CALLING); + v->n_pending++; + v->timestamp = now(CLOCK_MONOTONIC); + + while (v->state == VARLINK_CALLING) { + + r = varlink_process(v); + if (r < 0) + return r; + if (r > 0) + continue; + + r = varlink_wait(v, USEC_INFINITY); + if (r < 0) + return r; + } + + switch (v->state) { + + case VARLINK_CALLED: + assert(v->current); + + json_variant_unref(v->reply); + v->reply = TAKE_PTR(v->current); + + varlink_set_state(v, VARLINK_IDLE_CLIENT); + assert(v->n_pending == 1); + v->n_pending--; + + if (ret_parameters) + *ret_parameters = json_variant_by_key(v->reply, "parameters"); + if (ret_error_id) + *ret_error_id = json_variant_string(json_variant_by_key(v->reply, "error")); + if (ret_flags) + *ret_flags = 0; + + return 1; + + case VARLINK_PENDING_DISCONNECT: + case VARLINK_DISCONNECTED: + return -ECONNRESET; + + case VARLINK_PENDING_TIMEOUT: + return -ETIME; + + default: + assert_not_reached("Unexpected state after method call."); + } +} + +int varlink_callb( + Varlink *v, + const char *method, + JsonVariant **ret_parameters, + const char **ret_error_id, + VarlinkReplyFlags *ret_flags, ...) { + + _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL; + va_list ap; + int r; + + assert_return(v, -EINVAL); + + va_start(ap, ret_flags); + r = json_buildv(¶meters, ap); + va_end(ap); + + if (r < 0) + return r; + + return varlink_call(v, method, parameters, ret_parameters, ret_error_id, ret_flags); +} + +int varlink_reply(Varlink *v, JsonVariant *parameters) { + _cleanup_(json_variant_unrefp) JsonVariant *m = NULL; + int r; + + assert_return(v, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + if (!IN_SET(v->state, + VARLINK_PROCESSING_METHOD, VARLINK_PROCESSING_METHOD_MORE, + VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE)) + return -EBUSY; + + r = varlink_sanitize_parameters(¶meters); + if (r < 0) + return r; + + r = json_build(&m, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)))); + if (r < 0) + return r; + + r = varlink_enqueue_json(v, m); + if (r < 0) + return r; + + if (IN_SET(v->state, VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE)) { + /* We just replied to a method call that was let hanging for a while (i.e. we were outside of + * the varlink_dispatch_method() stack frame), which means with this reply we are ready to + * process further messages. */ + v->current = json_variant_unref(v->current); + varlink_set_state(v, VARLINK_IDLE_SERVER); + } else + /* We replied to a method call from within the varlink_dispatch_method() stack frame), which + * means we should it handle the rest of the state engine. */ + varlink_set_state(v, VARLINK_PROCESSED_METHOD); + + return 1; +} + +int varlink_replyb(Varlink *v, ...) { + _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL; + va_list ap; + int r; + + assert_return(v, -EINVAL); + + va_start(ap, v); + r = json_buildv(¶meters, ap); + va_end(ap); + + if (r < 0) + return r; + + return varlink_reply(v, parameters); +} + +int varlink_error(Varlink *v, const char *error_id, JsonVariant *parameters) { + _cleanup_(json_variant_unrefp) JsonVariant *m = NULL; + int r; + + assert_return(v, -EINVAL); + assert_return(error_id, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + if (!IN_SET(v->state, + VARLINK_PROCESSING_METHOD, VARLINK_PROCESSING_METHOD_MORE, + VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE)) + return -EBUSY; + + r = varlink_sanitize_parameters(¶meters); + if (r < 0) + return r; + + r = json_build(&m, JSON_BUILD_OBJECT( + JSON_BUILD_PAIR("error", JSON_BUILD_STRING(error_id)), + JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)))); + if (r < 0) + return r; + + r = varlink_enqueue_json(v, m); + if (r < 0) + return r; + + if (IN_SET(v->state, VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE)) { + v->current = json_variant_unref(v->current); + varlink_set_state(v, VARLINK_IDLE_SERVER); + } else + varlink_set_state(v, VARLINK_PROCESSED_METHOD); + + return 1; +} + +int varlink_errorb(Varlink *v, const char *error_id, ...) { + _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL; + va_list ap; + int r; + + assert_return(v, -EINVAL); + assert_return(error_id, -EINVAL); + + va_start(ap, error_id); + r = json_buildv(¶meters, ap); + va_end(ap); + + if (r < 0) + return r; + + return varlink_error(v, error_id, parameters); +} + +int varlink_error_invalid_parameter(Varlink *v, JsonVariant *parameters) { + + assert_return(v, -EINVAL); + assert_return(parameters, -EINVAL); + + /* We expect to be called in one of two ways: the 'parameters' argument is a string variant in which + * case it is the parameter key name that is invalid. Or the 'parameters' argument is an object + * variant in which case we'll pull out the first key. The latter mode is useful in functions that + * don't expect any arguments. */ + + if (json_variant_is_string(parameters)) + return varlink_error(v, VARLINK_ERROR_INVALID_PARAMETER, parameters); + + if (json_variant_is_object(parameters) && + json_variant_elements(parameters) > 0) + return varlink_error(v, VARLINK_ERROR_INVALID_PARAMETER, + json_variant_by_index(parameters, 0)); + + return -EINVAL; +} + +int varlink_notify(Varlink *v, JsonVariant *parameters) { + _cleanup_(json_variant_unrefp) JsonVariant *m = NULL; + int r; + + assert_return(v, -EINVAL); + + if (v->state == VARLINK_DISCONNECTED) + return -ENOTCONN; + if (!IN_SET(v->state, VARLINK_PROCESSING_METHOD_MORE, VARLINK_PENDING_METHOD_MORE)) + return -EBUSY; + + r = varlink_sanitize_parameters(¶meters); + if (r < 0) + return r; + + r = json_build(&m, JSON_BUILD_OBJECT( + JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)), + JSON_BUILD_PAIR("continues", JSON_BUILD_BOOLEAN(true)))); + if (r < 0) + return r; + + r = varlink_enqueue_json(v, m); + if (r < 0) + return r; + + /* No state change, as more is coming */ + return 1; +} + +int varlink_notifyb(Varlink *v, ...) { + _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL; + va_list ap; + int r; + + assert_return(v, -EINVAL); + + va_start(ap, v); + r = json_buildv(¶meters, ap); + va_end(ap); + + if (r < 0) + return r; + + return varlink_notify(v, parameters); +} + +int varlink_bind_reply(Varlink *v, VarlinkReply callback) { + assert_return(v, -EINVAL); + + if (callback && v->reply_callback && callback != v->reply_callback) + return -EBUSY; + + v->reply_callback = callback; + + return 0; +} + +void* varlink_set_userdata(Varlink *v, void *userdata) { + void *old; + + assert_return(v, NULL); + + old = v->userdata; + v->userdata = userdata; + + return old; +} + +void* varlink_get_userdata(Varlink *v) { + assert_return(v, NULL); + + return v->userdata; +} + +static int varlink_acquire_ucred(Varlink *v) { + int r; + + assert(v); + + if (v->ucred_acquired) + return 0; + + r = getpeercred(v->fd, &v->ucred); + if (r < 0) + return r; + + v->ucred_acquired = true; + return 0; +} + +int varlink_get_peer_uid(Varlink *v, uid_t *ret) { + int r; + + assert_return(v, -EINVAL); + assert_return(ret, -EINVAL); + + r = varlink_acquire_ucred(v); + if (r < 0) + return r; + + if (!uid_is_valid(v->ucred.uid)) + return -ENODATA; + + *ret = v->ucred.uid; + return 0; +} + +int varlink_get_peer_pid(Varlink *v, pid_t *ret) { + int r; + + assert_return(v, -EINVAL); + assert_return(ret, -EINVAL); + + r = varlink_acquire_ucred(v); + if (r < 0) + return r; + + if (!pid_is_valid(v->ucred.pid)) + return -ENODATA; + + *ret = v->ucred.pid; + return 0; +} + +int varlink_set_relative_timeout(Varlink *v, usec_t timeout) { + assert_return(v, -EINVAL); + assert_return(timeout > 0, -EINVAL); + + v->timeout = timeout; + return 0; +} + +VarlinkServer *varlink_get_server(Varlink *v) { + assert_return(v, NULL); + + return v->server; +} + +int varlink_set_description(Varlink *v, const char *description) { + assert_return(v, -EINVAL); + + return free_and_strdup(&v->description, description); +} + +static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Varlink *v = userdata; + + assert(s); + assert(v); + + handle_revents(v, revents); + (void) varlink_process(v); + + return 1; +} + +static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) { + Varlink *v = userdata; + + assert(s); + assert(v); + + (void) varlink_process(v); + return 1; +} + +static int defer_callback(sd_event_source *s, void *userdata) { + Varlink *v = userdata; + + assert(s); + assert(v); + + (void) varlink_process(v); + return 1; +} + +static int prepare_callback(sd_event_source *s, void *userdata) { + Varlink *v = userdata; + int r, e; + usec_t until; + bool have_timeout; + + assert(s); + assert(v); + + e = varlink_get_events(v); + if (e < 0) + return e; + + r = sd_event_source_set_io_events(v->io_event_source, e); + if (r < 0) + return r; + + r = varlink_get_timeout(v, &until); + if (r < 0) + return r; + have_timeout = r > 0; + + if (have_timeout) { + r = sd_event_source_set_time(v->time_event_source, until); + if (r < 0) + return r; + } + + r = sd_event_source_set_enabled(v->time_event_source, have_timeout ? SD_EVENT_ON : SD_EVENT_OFF); + if (r < 0) + return r; + + return 1; +} + +static int quit_callback(sd_event_source *event, void *userdata) { + Varlink *v = userdata; + + assert(event); + assert(v); + + varlink_flush(v); + varlink_close(v); + + return 1; +} + +int varlink_attach_event(Varlink *v, sd_event *e, int64_t priority) { + int r; + + assert_return(v, -EINVAL); + assert_return(!v->event, -EBUSY); + + if (e) + v->event = sd_event_ref(e); + else { + r = sd_event_default(&v->event); + if (r < 0) + return r; + } + + r = sd_event_add_time(v->event, &v->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, v); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(v->time_event_source, priority); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(v->time_event_source, "varlink-time"); + + r = sd_event_add_exit(v->event, &v->quit_event_source, quit_callback, v); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(v->quit_event_source, priority); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(v->quit_event_source, "varlink-quit"); + + r = sd_event_add_io(v->event, &v->io_event_source, v->fd, 0, io_callback, v); + if (r < 0) + goto fail; + + r = sd_event_source_set_prepare(v->io_event_source, prepare_callback); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(v->io_event_source, priority); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(v->io_event_source, "varlink-io"); + + r = sd_event_add_defer(v->event, &v->defer_event_source, defer_callback, v); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(v->defer_event_source, priority); + if (r < 0) + goto fail; + + (void) sd_event_source_set_description(v->defer_event_source, "varlink-defer"); + + return 0; + +fail: + varlink_detach_event(v); + return r; +} + +void varlink_detach_event(Varlink *v) { + if (!v) + return; + + varlink_detach_event_sources(v); + + v->event = sd_event_unref(v->event); +} + +sd_event *varlink_get_event(Varlink *v) { + assert_return(v, NULL); + + return v->event; +} + +int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags) { + VarlinkServer *s; + + assert_return(ret, -EINVAL); + assert_return((flags & ~_VARLINK_SERVER_FLAGS_ALL) == 0, -EINVAL); + + s = new(VarlinkServer, 1); + if (!s) + return -ENOMEM; + + *s = (VarlinkServer) { + .n_ref = 1, + .flags = flags, + .connections_max = varlink_server_connections_max(NULL), + .connections_per_uid_max = varlink_server_connections_per_uid_max(NULL), + }; + + *ret = s; + return 0; +} + +static VarlinkServer* varlink_server_destroy(VarlinkServer *s) { + char *m; + + if (!s) + return NULL; + + varlink_server_shutdown(s); + + while ((m = hashmap_steal_first_key(s->methods))) + free(m); + + hashmap_free(s->methods); + hashmap_free(s->by_uid); + + sd_event_unref(s->event); + + free(s->description); + + return mfree(s); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(VarlinkServer, varlink_server, varlink_server_destroy); + +static int validate_connection(VarlinkServer *server, const struct ucred *ucred) { + int allowed = -1; + + assert(server); + assert(ucred); + + if (FLAGS_SET(server->flags, VARLINK_SERVER_ROOT_ONLY)) + allowed = ucred->uid == 0; + + if (FLAGS_SET(server->flags, VARLINK_SERVER_MYSELF_ONLY)) + allowed = allowed > 0 || ucred->uid == getuid(); + + if (allowed == 0) { /* Allow access when it is explicitly allowed or when neither + * VARLINK_SERVER_ROOT_ONLY nor VARLINK_SERVER_MYSELF_ONLY are specified. */ + varlink_server_log(server, "Unprivileged client attempted connection, refusing."); + return 0; + } + + if (server->n_connections >= server->connections_max) { + varlink_server_log(server, "Connection limit of %u reached, refusing.", server->connections_max); + return 0; + } + + if (FLAGS_SET(server->flags, VARLINK_SERVER_ACCOUNT_UID)) { + unsigned c; + + if (!uid_is_valid(ucred->uid)) { + varlink_server_log(server, "Client with invalid UID attempted connection, refusing."); + return 0; + } + + c = PTR_TO_UINT(hashmap_get(server->by_uid, UID_TO_PTR(ucred->uid))); + if (c >= server->connections_per_uid_max) { + varlink_server_log(server, "Per-UID connection limit of %u reached, refusing.", + server->connections_per_uid_max); + return 0; + } + } + + return 1; +} + +static int count_connection(VarlinkServer *server, struct ucred *ucred) { + unsigned c; + int r; + + assert(server); + assert(ucred); + + server->n_connections++; + + if (FLAGS_SET(server->flags, VARLINK_SERVER_ACCOUNT_UID)) { + r = hashmap_ensure_allocated(&server->by_uid, NULL); + if (r < 0) + return log_debug_errno(r, "Failed to allocate UID hash table: %m"); + + c = PTR_TO_UINT(hashmap_get(server->by_uid, UID_TO_PTR(ucred->uid))); + + varlink_server_log(server, "Connections of user " UID_FMT ": %u (of %u max)", + ucred->uid, c, server->connections_per_uid_max); + + r = hashmap_replace(server->by_uid, UID_TO_PTR(ucred->uid), UINT_TO_PTR(c + 1)); + if (r < 0) + return log_debug_errno(r, "Failed to increment counter in UID hash table: %m"); + } + + return 0; +} + +int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret) { + _cleanup_(varlink_unrefp) Varlink *v = NULL; + bool ucred_acquired; + struct ucred ucred; + int r; + + assert_return(server, -EINVAL); + assert_return(fd >= 0, -EBADF); + + if ((server->flags & (VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_ACCOUNT_UID)) != 0) { + r = getpeercred(fd, &ucred); + if (r < 0) + return varlink_server_log_errno(server, r, "Failed to acquire peer credentials of incoming socket, refusing: %m"); + + ucred_acquired = true; + + r = validate_connection(server, &ucred); + if (r < 0) + return r; + if (r == 0) + return -EPERM; + } else + ucred_acquired = false; + + r = varlink_new(&v); + if (r < 0) + return varlink_server_log_errno(server, r, "Failed to allocate connection object: %m"); + + r = count_connection(server, &ucred); + if (r < 0) + return r; + + v->fd = fd; + v->userdata = server->userdata; + if (ucred_acquired) { + v->ucred = ucred; + v->ucred_acquired = true; + } + + (void) asprintf(&v->description, "%s-%i", server->description ?: "varlink", v->fd); + + /* Link up the server and the connection, and take reference in both directions. Note that the + * reference on the connection is left dangling. It will be dropped when the connection is closed, + * which happens in varlink_close(), including in the event loop quit callback. */ + v->server = varlink_server_ref(server); + varlink_ref(v); + + varlink_set_state(v, VARLINK_IDLE_SERVER); + + if (server->event) { + r = varlink_attach_event(v, server->event, server->event_priority); + if (r < 0) { + varlink_log_errno(v, r, "Failed to attach new connection: %m"); + v->fd = -1; /* take the fd out of the connection again */ + varlink_close(v); + return r; + } + } + + if (ret) + *ret = v; + + return 0; +} + +static int connect_callback(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + VarlinkServerSocket *ss = userdata; + _cleanup_close_ int cfd = -1; + Varlink *v = NULL; + int r; + + assert(source); + assert(ss); + + varlink_server_log(ss->server, "New incoming connection."); + + cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); + if (cfd < 0) { + if (ERRNO_IS_ACCEPT_AGAIN(errno)) + return 0; + + return varlink_server_log_errno(ss->server, errno, "Failed to accept incoming socket: %m"); + } + + r = varlink_server_add_connection(ss->server, cfd, &v); + if (r < 0) + return 0; + + TAKE_FD(cfd); + + if (ss->server->connect_callback) { + r = ss->server->connect_callback(ss->server, v, ss->server->userdata); + if (r < 0) { + varlink_log_errno(v, r, "Connection callback returned error, disconnecting client: %m"); + varlink_close(v); + return 0; + } + } + + return 0; +} + +int varlink_server_listen_fd(VarlinkServer *s, int fd) { + _cleanup_free_ VarlinkServerSocket *ss = NULL; + int r; + + assert_return(s, -EINVAL); + assert_return(fd >= 0, -EBADF); + + r = fd_nonblock(fd, true); + if (r < 0) + return r; + + ss = new(VarlinkServerSocket, 1); + if (!ss) + return -ENOMEM; + + *ss = (VarlinkServerSocket) { + .server = s, + .fd = fd, + }; + + if (s->event) { + _cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL; + + r = sd_event_add_io(s->event, &es, fd, EPOLLIN, connect_callback, ss); + if (r < 0) + return r; + + r = sd_event_source_set_priority(ss->event_source, s->event_priority); + if (r < 0) + return r; + } + + LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss)); + return 0; +} + +int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t m) { + union sockaddr_union sockaddr; + _cleanup_close_ int fd = -1; + int r; + + assert_return(s, -EINVAL); + assert_return(address, -EINVAL); + assert_return((m & ~0777) == 0, -EINVAL); + + r = sockaddr_un_set_path(&sockaddr.un, address); + if (r < 0) + return r; + + fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + if (fd < 0) + return -errno; + + fd = fd_move_above_stdio(fd); + + (void) sockaddr_un_unlink(&sockaddr.un); + + RUN_WITH_UMASK(~m & 0777) + if (bind(fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0) + return -errno; + + if (listen(fd, SOMAXCONN) < 0) + return -errno; + + r = varlink_server_listen_fd(s, fd); + if (r < 0) + return r; + + TAKE_FD(fd); + return 0; +} + +void* varlink_server_set_userdata(VarlinkServer *s, void *userdata) { + void *ret; + + assert_return(s, NULL); + + ret = s->userdata; + s->userdata = userdata; + + return ret; +} + +void* varlink_server_get_userdata(VarlinkServer *s) { + assert_return(s, NULL); + + return s->userdata; +} + +static VarlinkServerSocket* varlink_server_socket_destroy(VarlinkServerSocket *ss) { + if (!ss) + return NULL; + + if (ss->server) + LIST_REMOVE(sockets, ss->server->sockets, ss); + + sd_event_source_disable_unref(ss->event_source); + + free(ss->address); + safe_close(ss->fd); + + return mfree(ss); +} + +int varlink_server_shutdown(VarlinkServer *s) { + assert_return(s, -EINVAL); + + while (s->sockets) + varlink_server_socket_destroy(s->sockets); + + return 0; +} + +int varlink_server_attach_event(VarlinkServer *s, sd_event *e, int64_t priority) { + VarlinkServerSocket *ss; + int r; + + assert_return(s, -EINVAL); + assert_return(!s->event, -EBUSY); + + if (e) + s->event = sd_event_ref(e); + else { + r = sd_event_default(&s->event); + if (r < 0) + return r; + } + + LIST_FOREACH(sockets, ss, s->sockets) { + assert(!ss->event_source); + + r = sd_event_add_io(s->event, &ss->event_source, ss->fd, EPOLLIN, connect_callback, ss); + if (r < 0) + goto fail; + + r = sd_event_source_set_priority(ss->event_source, priority); + if (r < 0) + goto fail; + } + + s->event_priority = priority; + return 0; + +fail: + varlink_server_detach_event(s); + return r; +} + +int varlink_server_detach_event(VarlinkServer *s) { + VarlinkServerSocket *ss; + + assert_return(s, -EINVAL); + + LIST_FOREACH(sockets, ss, s->sockets) { + + if (!ss->event_source) + continue; + + (void) sd_event_source_set_enabled(ss->event_source, SD_EVENT_OFF); + ss->event_source = sd_event_source_unref(ss->event_source); + } + + sd_event_unref(s->event); + return 0; +} + +sd_event *varlink_server_get_event(VarlinkServer *s) { + assert_return(s, NULL); + + return s->event; +} + +int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback) { + char *m; + int r; + + assert_return(s, -EINVAL); + assert_return(method, -EINVAL); + assert_return(callback, -EINVAL); + + if (startswith(method, "org.varlink.service.")) + return -EEXIST; + + r = hashmap_ensure_allocated(&s->methods, &string_hash_ops); + if (r < 0) + return r; + + m = strdup(method); + if (!m) + return -ENOMEM; + + r = hashmap_put(s->methods, m, callback); + if (r < 0) { + free(m); + return r; + } + + return 0; +} + +int varlink_server_bind_method_many_internal(VarlinkServer *s, ...) { + va_list ap; + int r = 0; + + assert_return(s, -EINVAL); + + va_start(ap, s); + for (;;) { + VarlinkMethod callback; + const char *method; + + method = va_arg(ap, const char *); + if (!method) + break; + + callback = va_arg(ap, VarlinkMethod); + + r = varlink_server_bind_method(s, method, callback); + if (r < 0) + break; + } + va_end(ap); + + return r; +} + +int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect callback) { + assert_return(s, -EINVAL); + + if (callback && s->connect_callback && callback != s->connect_callback) + return -EBUSY; + + s->connect_callback = callback; + return 0; +} + +unsigned varlink_server_connections_max(VarlinkServer *s) { + int dts; + + /* If a server is specified, return the setting for that server, otherwise the default value */ + if (s) + return s->connections_max; + + dts = getdtablesize(); + assert_se(dts > 0); + + /* Make sure we never use up more than ¾th of RLIMIT_NOFILE for IPC */ + if (VARLINK_DEFAULT_CONNECTIONS_MAX > (unsigned) dts / 4 * 3) + return dts / 4 * 3; + + return VARLINK_DEFAULT_CONNECTIONS_MAX; +} + +unsigned varlink_server_connections_per_uid_max(VarlinkServer *s) { + unsigned m; + + if (s) + return s->connections_per_uid_max; + + /* Make sure to never use up more than ¾th of available connections for a single user */ + m = varlink_server_connections_max(NULL); + if (VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX > m) + return m / 4 * 3; + + return VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX; +} + +int varlink_server_set_connections_per_uid_max(VarlinkServer *s, unsigned m) { + assert_return(s, -EINVAL); + assert_return(m > 0, -EINVAL); + + s->connections_per_uid_max = m; + return 0; +} + +int varlink_server_set_connections_max(VarlinkServer *s, unsigned m) { + assert_return(s, -EINVAL); + assert_return(m > 0, -EINVAL); + + s->connections_max = m; + return 0; +} + +int varlink_server_set_description(VarlinkServer *s, const char *description) { + assert_return(s, -EINVAL); + + return free_and_strdup(&s->description, description); +} diff --git a/src/shared/varlink.h b/src/shared/varlink.h new file mode 100644 index 00000000..02088020 --- /dev/null +++ b/src/shared/varlink.h @@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-event.h" + +#include "json.h" +#include "time-util.h" + +/* A minimal Varlink implementation. We only implement the minimal, obvious bits here though. No validation, + * no introspection, no name service, just the stuff actually needed. + * + * You might wonder why we aren't using libvarlink here? Varlink is a very simple protocol, which allows us + * to write our own implementation relatively easily. However, the main reasons are these: + * + * • We want to use our own JSON subsystem, with all the benefits that brings (i.e. accurate unsigned+signed + * 64bit integers, full fuzzing, logging during parsing and so on). If we'd want to use that with + * libvarlink we'd have to serialize and deserialize all the time from its own representation which is + * inefficient and nasty. + * + * • We want integration into sd-event, but also synchronous event-loop-less operation + * + * • We need proper per-UID accounting and access control, since we want to allow communication between + * unprivileged clients and privileged servers. + * + * • And of course, we don't want the name service and introspection stuff for now (though that might + * change). + */ + +typedef struct Varlink Varlink; +typedef struct VarlinkServer VarlinkServer; + +typedef enum VarlinkReplyFlags { + VARLINK_REPLY_ERROR = 1 << 0, + VARLINK_REPLY_CONTINUES = 1 << 1, + VARLINK_REPLY_LOCAL = 1 << 2, +} VarlinkReplyFlags; + +typedef enum VarlinkMethodFlags { + VARLINK_METHOD_ONEWAY = 1 << 0, + VARLINK_METHOD_MORE = 2 << 1, +} VarlinkMethodFlags; + +typedef enum VarlinkServerFlags { + VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */ + VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */ + VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */ + + _VARLINK_SERVER_FLAGS_ALL = (1 << 3) - 1, +} VarlinkServerFlags; + +typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata); +typedef int (*VarlinkReply)(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata); +typedef int (*VarlinkConnect)(VarlinkServer *server, Varlink *link, void *userdata); + +int varlink_connect_address(Varlink **ret, const char *address); +int varlink_connect_fd(Varlink **ret, int fd); + +Varlink* varlink_ref(Varlink *link); +Varlink* varlink_unref(Varlink *v); + +int varlink_get_fd(Varlink *v); +int varlink_get_events(Varlink *v); +int varlink_get_timeout(Varlink *v, usec_t *ret); + +int varlink_attach_event(Varlink *v, sd_event *e, int64_t priority); +void varlink_detach_event(Varlink *v); +sd_event *varlink_get_event(Varlink *v); + +int varlink_process(Varlink *v); +int varlink_wait(Varlink *v, usec_t timeout); + +int varlink_flush(Varlink *v); +int varlink_close(Varlink *v); + +Varlink* varlink_flush_close_unref(Varlink *v); + +/* Enqueue method call, not expecting a reply */ +int varlink_send(Varlink *v, const char *method, JsonVariant *parameters); +int varlink_sendb(Varlink *v, const char *method, ...); + +/* Send method call and wait for reply */ +int varlink_call(Varlink *v, const char *method, JsonVariant *parameters, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags); +int varlink_callb(Varlink *v, const char *method, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags, ...); + +/* Enqueue method call, expect a reply, which is eventually delivered to the reply callback */ +int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters); +int varlink_invokeb(Varlink *v, const char *method, ...); + +/* Enqueue method call, expect a reply now, and possibly more later, which are all delivered to the reply callback */ +int varlink_observe(Varlink *v, const char *method, JsonVariant *parameters); +int varlink_observeb(Varlink *v, const char *method, ...); + +/* Enqueue a final reply */ +int varlink_reply(Varlink *v, JsonVariant *parameters); +int varlink_replyb(Varlink *v, ...); + +/* Enqueue a (final) error */ +int varlink_error(Varlink *v, const char *error_id, JsonVariant *parameters); +int varlink_errorb(Varlink *v, const char *error_id, ...); +int varlink_error_invalid_parameter(Varlink *v, JsonVariant *parameters); + +/* Enqueue a "more" reply */ +int varlink_notify(Varlink *v, JsonVariant *parameters); +int varlink_notifyb(Varlink *v, ...); + +/* Bind a disconnect, reply or timeout callback */ +int varlink_bind_reply(Varlink *v, VarlinkReply reply); + +void* varlink_set_userdata(Varlink *v, void *userdata); +void* varlink_get_userdata(Varlink *v); + +int varlink_get_peer_uid(Varlink *v, uid_t *ret); +int varlink_get_peer_pid(Varlink *v, pid_t *ret); + +int varlink_set_relative_timeout(Varlink *v, usec_t usec); + +VarlinkServer* varlink_get_server(Varlink *v); + +int varlink_set_description(Varlink *v, const char *d); + +/* Create a varlink server */ +int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags); +VarlinkServer *varlink_server_ref(VarlinkServer *s); +VarlinkServer *varlink_server_unref(VarlinkServer *s); + +/* Add addresses or fds to listen on */ +int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t mode); +int varlink_server_listen_fd(VarlinkServer *s, int fd); +int varlink_server_add_connection(VarlinkServer *s, int fd, Varlink **ret); + +/* Bind callbacks */ +int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback); +int varlink_server_bind_method_many_internal(VarlinkServer *s, ...); +#define varlink_server_bind_method_many(s, ...) varlink_server_bind_method_many_internal(s, __VA_ARGS__, NULL) +int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect connect); + +void* varlink_server_set_userdata(VarlinkServer *s, void *userdata); +void* varlink_server_get_userdata(VarlinkServer *s); + +int varlink_server_attach_event(VarlinkServer *v, sd_event *e, int64_t priority); +int varlink_server_detach_event(VarlinkServer *v); +sd_event *varlink_server_get_event(VarlinkServer *v); + +int varlink_server_shutdown(VarlinkServer *server); + +unsigned varlink_server_connections_max(VarlinkServer *s); +unsigned varlink_server_connections_per_uid_max(VarlinkServer *s); + +int varlink_server_set_connections_per_uid_max(VarlinkServer *s, unsigned m); +int varlink_server_set_connections_max(VarlinkServer *s, unsigned m); + +int varlink_server_set_description(VarlinkServer *s, const char *description); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_flush_close_unref); +DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServer *, varlink_server_unref); + +#define VARLINK_ERROR_DISCONNECTED "io.systemd.Disconnected" +#define VARLINK_ERROR_TIMEOUT "io.systemd.TimedOut" +#define VARLINK_ERROR_PROTOCOL "io.systemd.Protocol" +#define VARLINK_ERROR_SYSTEM "io.systemd.System" + +#define VARLINK_ERROR_INTERFACE_NOT_FOUND "org.varlink.service.InterfaceNotFound" +#define VARLINK_ERROR_METHOD_NOT_FOUND "org.varlink.service.MethodNotFound" +#define VARLINK_ERROR_METHOD_NOT_IMPLEMENTED "org.varlink.service.MethodNotImplemented" +#define VARLINK_ERROR_INVALID_PARAMETER "org.varlink.service.InvalidParameter" diff --git a/src/shared/verbs.c b/src/shared/verbs.c new file mode 100644 index 00000000..1d23ed48 --- /dev/null +++ b/src/shared/verbs.c @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "env-util.h" +#include "log.h" +#include "macro.h" +#include "process-util.h" +#include "string-util.h" +#include "verbs.h" +#include "virt.h" + +/* Wraps running_in_chroot() which is used in various places, but also adds an environment variable check so external + * processes can reliably force this on. + */ +bool running_in_chroot_or_offline(void) { + int r; + + /* Added to support use cases like rpm-ostree, where from %post scripts we only want to execute "preset", but + * not "start"/"restart" for example. + * + * See docs/ENVIRONMENT.md for docs. + */ + r = getenv_bool("SYSTEMD_OFFLINE"); + if (r < 0 && r != -ENXIO) + log_debug_errno(r, "Failed to parse $SYSTEMD_OFFLINE: %m"); + else if (r >= 0) + return r > 0; + + /* We've had this condition check for a long time which basically checks for legacy chroot case like Fedora's + * "mock", which is used for package builds. We don't want to try to start systemd services there, since + * without --new-chroot we don't even have systemd running, and even if we did, adding a concept of background + * daemons to builds would be an enormous change, requiring considering things like how the journal output is + * handled, etc. And there's really not a use case today for a build talking to a service. + * + * Note this call itself also looks for a different variable SYSTEMD_IGNORE_CHROOT=1. + */ + r = running_in_chroot(); + if (r < 0) + log_debug_errno(r, "running_in_chroot(): %m"); + + return r > 0; +} + +int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) { + const Verb *verb; + const char *name; + unsigned i; + int left; + + assert(verbs); + assert(verbs[0].dispatch); + assert(argc >= 0); + assert(argv); + assert(argc >= optind); + + left = argc - optind; + argv += optind; + optind = 0; + name = argv[0]; + + for (i = 0;; i++) { + bool found; + + /* At the end of the list? */ + if (!verbs[i].dispatch) { + if (name) + log_error("Unknown operation %s.", name); + else + log_error("Requires operation parameter."); + return -EINVAL; + } + + if (name) + found = streq(name, verbs[i].verb); + else + found = verbs[i].flags & VERB_DEFAULT; + + if (found) { + verb = &verbs[i]; + break; + } + } + + assert(verb); + + if (!name) + left = 1; + + if (verb->min_args != VERB_ANY && + (unsigned) left < verb->min_args) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too few arguments."); + + if (verb->max_args != VERB_ANY && + (unsigned) left > verb->max_args) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many arguments."); + + if ((verb->flags & VERB_ONLINE_ONLY) && running_in_chroot_or_offline()) { + if (name) + log_info("Running in chroot, ignoring request: %s", name); + else + log_info("Running in chroot, ignoring request."); + return 0; + } + + if (name) + return verb->dispatch(left, argv, userdata); + else { + char* fake[2] = { + (char*) verb->verb, + NULL + }; + + return verb->dispatch(1, fake, userdata); + } +} diff --git a/src/shared/verbs.h b/src/shared/verbs.h new file mode 100644 index 00000000..c5fe6cc7 --- /dev/null +++ b/src/shared/verbs.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#define VERB_ANY ((unsigned) -1) + +typedef enum VerbFlags { + VERB_DEFAULT = 1 << 0, + VERB_ONLINE_ONLY = 1 << 1, +} VerbFlags; + +typedef struct { + const char *verb; + unsigned min_args, max_args; + VerbFlags flags; + int (* const dispatch)(int argc, char *argv[], void *userdata); +} Verb; + +bool running_in_chroot_or_offline(void); + +int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata); diff --git a/src/shared/vlan-util.c b/src/shared/vlan-util.c new file mode 100644 index 00000000..a4b42df8 --- /dev/null +++ b/src/shared/vlan-util.c @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "conf-parser.h" +#include "parse-util.h" +#include "string-util.h" +#include "vlan-util.h" + +int parse_vlanid(const char *p, uint16_t *ret) { + uint16_t id; + int r; + + assert(p); + assert(ret); + + r = safe_atou16(p, &id); + if (r < 0) + return r; + if (!vlanid_is_valid(id)) + return -ERANGE; + + *ret = id; + return 0; +} + +int parse_vid_range(const char *p, uint16_t *vid, uint16_t *vid_end) { + unsigned lower, upper; + int r; + + r = parse_range(p, &lower, &upper); + if (r < 0) + return r; + + if (lower > VLANID_MAX || upper > VLANID_MAX || lower > upper) + return -EINVAL; + + *vid = lower; + *vid_end = upper; + return 0; +} + +int config_parse_default_port_vlanid( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + uint16_t *id = data; + + assert(lvalue); + assert(rvalue); + assert(data); + + if (streq(rvalue, "none")) { + *id = 0; + return 0; + } + + return config_parse_vlanid(unit, filename, line, section, section_line, + lvalue, ltype, rvalue, data, userdata); +} + +int config_parse_vlanid( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint16_t *id = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + r = parse_vlanid(rvalue, id); + if (r == -ERANGE) { + log_syntax(unit, LOG_ERR, filename, line, r, "VLAN identifier outside of valid range 0…4094, ignoring: %s", rvalue); + return 0; + } + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VLAN identifier value, ignoring: %s", rvalue); + return 0; + } + + return 0; +} diff --git a/src/shared/vlan-util.h b/src/shared/vlan-util.h new file mode 100644 index 00000000..c55adee3 --- /dev/null +++ b/src/shared/vlan-util.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include +#include + +#include "conf-parser.h" + +#define VLANID_MAX 4094 +#define VLANID_INVALID UINT16_MAX + +/* Note that we permit VLAN Id 0 here, as that is apparently OK by the Linux kernel */ +static inline bool vlanid_is_valid(uint16_t id) { + return id <= VLANID_MAX; +} + +int parse_vlanid(const char *p, uint16_t *ret); +int parse_vid_range(const char *p, uint16_t *vid, uint16_t *vid_end); + +CONFIG_PARSER_PROTOTYPE(config_parse_default_port_vlanid); +CONFIG_PARSER_PROTOTYPE(config_parse_vlanid); diff --git a/src/shared/volatile-util.c b/src/shared/volatile-util.c new file mode 100644 index 00000000..5ca6ab33 --- /dev/null +++ b/src/shared/volatile-util.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "macro.h" +#include "parse-util.h" +#include "proc-cmdline.h" +#include "string-table.h" +#include "string-util.h" +#include "volatile-util.h" + +int query_volatile_mode(VolatileMode *ret) { + _cleanup_free_ char *mode = NULL; + int r; + + r = proc_cmdline_get_key("systemd.volatile", PROC_CMDLINE_VALUE_OPTIONAL, &mode); + if (r < 0) + return r; + if (r == 0) { + *ret = VOLATILE_NO; + return 0; + } + + if (mode) { + VolatileMode m; + + m = volatile_mode_from_string(mode); + if (m < 0) + return -EINVAL; + + *ret = m; + } else + *ret = VOLATILE_YES; + + return 1; +} + +static const char* const volatile_mode_table[_VOLATILE_MODE_MAX] = { + [VOLATILE_NO] = "no", + [VOLATILE_YES] = "yes", + [VOLATILE_STATE] = "state", + [VOLATILE_OVERLAY] = "overlay", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(volatile_mode, VolatileMode, VOLATILE_YES); diff --git a/src/shared/volatile-util.h b/src/shared/volatile-util.h new file mode 100644 index 00000000..2d31bb11 --- /dev/null +++ b/src/shared/volatile-util.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +typedef enum VolatileMode { + VOLATILE_NO, + VOLATILE_YES, + VOLATILE_STATE, + VOLATILE_OVERLAY, + _VOLATILE_MODE_MAX, + _VOLATILE_MODE_INVALID = -1 +} VolatileMode; + +VolatileMode volatile_mode_from_string(const char *s); +const char* volatile_mode_to_string(VolatileMode m); + +int query_volatile_mode(VolatileMode *ret); diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c new file mode 100644 index 00000000..98fefb39 --- /dev/null +++ b/src/shared/watchdog.c @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "fd-util.h" +#include "log.h" +#include "string-util.h" +#include "time-util.h" +#include "watchdog.h" + +static int watchdog_fd = -1; +static char *watchdog_device = NULL; +static usec_t watchdog_timeout = USEC_INFINITY; + +static int update_timeout(void) { + int r; + + if (watchdog_fd < 0) + return 0; + + if (watchdog_timeout == USEC_INFINITY) + return 0; + else if (watchdog_timeout == 0) { + int flags; + + flags = WDIOS_DISABLECARD; + r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags); + if (r < 0) + return log_warning_errno(errno, "Failed to disable hardware watchdog: %m"); + } else { + int sec, flags; + char buf[FORMAT_TIMESPAN_MAX]; + + sec = (int) DIV_ROUND_UP(watchdog_timeout, USEC_PER_SEC); + r = ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec); + if (r < 0) + return log_warning_errno(errno, "Failed to set timeout to %is: %m", sec); + + watchdog_timeout = (usec_t) sec * USEC_PER_SEC; + log_info("Set hardware watchdog to %s.", format_timespan(buf, sizeof(buf), watchdog_timeout, 0)); + + flags = WDIOS_ENABLECARD; + r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags); + if (r < 0) { + /* ENOTTY means the watchdog is always enabled so we're fine */ + log_full(errno == ENOTTY ? LOG_DEBUG : LOG_WARNING, + "Failed to enable hardware watchdog: %m"); + if (errno != ENOTTY) + return -errno; + } + + r = ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0); + if (r < 0) + return log_warning_errno(errno, "Failed to ping hardware watchdog: %m"); + } + + return 0; +} + +static int open_watchdog(void) { + struct watchdog_info ident; + + if (watchdog_fd >= 0) + return 0; + + watchdog_fd = open(watchdog_device ?: "/dev/watchdog", + O_WRONLY|O_CLOEXEC); + if (watchdog_fd < 0) + return -errno; + + if (ioctl(watchdog_fd, WDIOC_GETSUPPORT, &ident) >= 0) + log_info("Hardware watchdog '%s', version %x", + ident.identity, + ident.firmware_version); + + return update_timeout(); +} + +int watchdog_set_device(char *path) { + int r; + + r = free_and_strdup(&watchdog_device, path); + if (r < 0) + return r; + + if (r > 0) /* watchdog_device changed */ + watchdog_fd = safe_close(watchdog_fd); + + return r; +} + +int watchdog_set_timeout(usec_t *usec) { + int r; + + watchdog_timeout = *usec; + + /* If we didn't open the watchdog yet and didn't get any + * explicit timeout value set, don't do anything */ + if (watchdog_fd < 0 && watchdog_timeout == USEC_INFINITY) + return 0; + + if (watchdog_fd < 0) + r = open_watchdog(); + else + r = update_timeout(); + + *usec = watchdog_timeout; + + return r; +} + +int watchdog_ping(void) { + int r; + + if (watchdog_fd < 0) { + r = open_watchdog(); + if (r < 0) + return r; + } + + r = ioctl(watchdog_fd, WDIOC_KEEPALIVE, 0); + if (r < 0) + return log_warning_errno(errno, "Failed to ping hardware watchdog: %m"); + + return 0; +} + +void watchdog_close(bool disarm) { + int r; + + if (watchdog_fd < 0) + return; + + if (disarm) { + int flags; + + /* Explicitly disarm it */ + flags = WDIOS_DISABLECARD; + r = ioctl(watchdog_fd, WDIOC_SETOPTIONS, &flags); + if (r < 0) + log_warning_errno(errno, "Failed to disable hardware watchdog: %m"); + + /* To be sure, use magic close logic, too */ + for (;;) { + static const char v = 'V'; + + if (write(watchdog_fd, &v, 1) > 0) + break; + + if (errno != EINTR) { + log_error_errno(errno, "Failed to disarm watchdog timer: %m"); + break; + } + } + } + + watchdog_fd = safe_close(watchdog_fd); +} diff --git a/src/shared/watchdog.h b/src/shared/watchdog.h new file mode 100644 index 00000000..a345e4ba --- /dev/null +++ b/src/shared/watchdog.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "time-util.h" +#include "util.h" + +int watchdog_set_device(char *path); +int watchdog_set_timeout(usec_t *usec); +int watchdog_ping(void); +void watchdog_close(bool disarm); + +static inline void watchdog_free_device(void) { + (void) watchdog_set_device(NULL); +} diff --git a/src/shared/web-util.c b/src/shared/web-util.c new file mode 100644 index 00000000..edf650d2 --- /dev/null +++ b/src/shared/web-util.c @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "string-util.h" +#include "strv.h" +#include "utf8.h" +#include "web-util.h" + +bool http_etag_is_valid(const char *etag) { + if (isempty(etag)) + return false; + + if (!endswith(etag, "\"")) + return false; + + if (!STARTSWITH_SET(etag, "\"", "W/\"")) + return false; + + return true; +} + +bool http_url_is_valid(const char *url) { + const char *p; + + if (isempty(url)) + return false; + + p = STARTSWITH_SET(url, "http://", "https://"); + if (!p) + return false; + + if (isempty(p)) + return false; + + return ascii_is_valid(p); +} + +bool documentation_url_is_valid(const char *url) { + const char *p; + + if (isempty(url)) + return false; + + if (http_url_is_valid(url)) + return true; + + p = STARTSWITH_SET(url, "file:/", "info:", "man:"); + if (isempty(p)) + return false; + + return ascii_is_valid(p); +} diff --git a/src/shared/web-util.h b/src/shared/web-util.h new file mode 100644 index 00000000..c9e67e5c --- /dev/null +++ b/src/shared/web-util.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +bool http_url_is_valid(const char *url) _pure_; + +bool documentation_url_is_valid(const char *url) _pure_; + +bool http_etag_is_valid(const char *etag); diff --git a/src/shared/wifi-util.c b/src/shared/wifi-util.c new file mode 100644 index 00000000..2717db65 --- /dev/null +++ b/src/shared/wifi-util.c @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-bus.h" + +#include "log.h" +#include "netlink-util.h" +#include "wifi-util.h" + +int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftype, char **ssid) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL; + sd_genl_family family; + int r; + + r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_INTERFACE, &m); + if (r < 0) + return log_debug_errno(r, "Failed to create generic netlink message: %m"); + + r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, ifindex); + if (r < 0) + return log_debug_errno(r, "Could not append NL80211_ATTR_IFINDEX attribute: %m"); + + r = sd_netlink_call(genl, m, 0, &reply); + if (r < 0) + return log_debug_errno(r, "Failed to request information about wifi interface %d: %m", ifindex); + if (!reply) + return 0; + + r = sd_netlink_message_get_errno(reply); + if (r < 0) + return log_debug_errno(r, "Failed to get information about wifi interface %d: %m", ifindex); + + r = sd_genl_message_get_family(genl, reply, &family); + if (r < 0) + return log_debug_errno(r, "Failed to determine genl family: %m"); + if (family != SD_GENL_NL80211) { + log_debug("Received message of unexpected genl family %u, ignoring.", family); + return 0; + } + + if (iftype) { + uint32_t t; + + r = sd_netlink_message_read_u32(reply, NL80211_ATTR_IFTYPE, &t); + if (r < 0) + return log_debug_errno(r, "Failed to get NL80211_ATTR_IFTYPE attribute: %m"); + *iftype = t; + } + + if (ssid) { + r = sd_netlink_message_read_string_strdup(reply, NL80211_ATTR_SSID, ssid); + if (r < 0 && r != -ENODATA) + return log_debug_errno(r, "Failed to get NL80211_ATTR_SSID attribute: %m"); + } + + return r == -ENODATA ? 0 : 1; +} + +int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL; + sd_genl_family family; + int r; + + r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_STATION, &m); + if (r < 0) + return log_debug_errno(r, "Failed to create generic netlink message: %m"); + + r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); + if (r < 0) + return log_debug_errno(r, "Failed to set dump flag: %m"); + + r = sd_netlink_message_append_u32(m, NL80211_ATTR_IFINDEX, ifindex); + if (r < 0) + return log_debug_errno(r, "Could not append NL80211_ATTR_IFINDEX attribute: %m"); + + r = sd_netlink_call(genl, m, 0, &reply); + if (r < 0) + return log_debug_errno(r, "Failed to request information about wifi station: %m"); + if (!reply) + return 0; + + r = sd_netlink_message_get_errno(reply); + if (r < 0) + return log_debug_errno(r, "Failed to get information about wifi station: %m"); + + r = sd_genl_message_get_family(genl, reply, &family); + if (r < 0) + return log_debug_errno(r, "Failed to determine genl family: %m"); + if (family != SD_GENL_NL80211) { + log_debug("Received message of unexpected genl family %u, ignoring.", family); + return 0; + } + + r = sd_netlink_message_read_ether_addr(reply, NL80211_ATTR_MAC, bssid); + if (r < 0 && r != -ENODATA) + return log_debug_errno(r, "Failed to get NL80211_ATTR_MAC attribute: %m"); + + return r == -ENODATA ? 0 : 1; +} diff --git a/src/shared/wifi-util.h b/src/shared/wifi-util.h new file mode 100644 index 00000000..c7553faf --- /dev/null +++ b/src/shared/wifi-util.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#pragma once + +#include + +#include "netlink-util.h" + +int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftype, char **ssid); +int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid); diff --git a/src/shared/xml.c b/src/shared/xml.c new file mode 100644 index 00000000..78ac42f0 --- /dev/null +++ b/src/shared/xml.c @@ -0,0 +1,237 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "macro.h" +#include "string-util.h" +#include "xml.h" + +enum { + STATE_NULL, + STATE_TEXT, + STATE_TAG, + STATE_ATTRIBUTE, +}; + +static void inc_lines(unsigned *line, const char *s, size_t n) { + const char *p = s; + + if (!line) + return; + + for (;;) { + const char *f; + + f = memchr(p, '\n', n); + if (!f) + return; + + n -= (f - p) + 1; + p = f + 1; + (*line)++; + } +} + +/* We don't actually do real XML here. We only read a simplistic + * subset, that is a bit less strict that XML and lacks all the more + * complex features, like entities, or namespaces. However, we do + * support some HTML5-like simplifications */ + +int xml_tokenize(const char **p, char **name, void **state, unsigned *line) { + const char *c, *e, *b; + char *ret; + int t; + + assert(p); + assert(*p); + assert(name); + assert(state); + + t = PTR_TO_INT(*state); + c = *p; + + if (t == STATE_NULL) { + if (line) + *line = 1; + t = STATE_TEXT; + } + + for (;;) { + if (*c == 0) + return XML_END; + + switch (t) { + + case STATE_TEXT: { + int x; + + e = strchrnul(c, '<'); + if (e > c) { + /* More text... */ + ret = strndup(c, e - c); + if (!ret) + return -ENOMEM; + + inc_lines(line, c, e - c); + + *name = ret; + *p = e; + *state = INT_TO_PTR(STATE_TEXT); + + return XML_TEXT; + } + + assert(*e == '<'); + b = c + 1; + + if (startswith(b, "!--")) { + /* A comment */ + e = strstr(b + 3, "-->"); + if (!e) + return -EINVAL; + + inc_lines(line, b, e + 3 - b); + + c = e + 3; + continue; + } + + if (*b == '?') { + /* Processing instruction */ + + e = strstr(b + 1, "?>"); + if (!e) + return -EINVAL; + + inc_lines(line, b, e + 2 - b); + + c = e + 2; + continue; + } + + if (*b == '!') { + /* DTD */ + + e = strchr(b + 1, '>'); + if (!e) + return -EINVAL; + + inc_lines(line, b, e + 1 - b); + + c = e + 1; + continue; + } + + if (*b == '/') { + /* A closing tag */ + x = XML_TAG_CLOSE; + b++; + } else + x = XML_TAG_OPEN; + + e = strpbrk(b, WHITESPACE "/>"); + if (!e) + return -EINVAL; + + ret = strndup(b, e - b); + if (!ret) + return -ENOMEM; + + *name = ret; + *p = e; + *state = INT_TO_PTR(STATE_TAG); + + return x; + } + + case STATE_TAG: + + b = c + strspn(c, WHITESPACE); + if (*b == 0) + return -EINVAL; + + inc_lines(line, c, b - c); + + e = b + strcspn(b, WHITESPACE "=/>"); + if (e > b) { + /* An attribute */ + + ret = strndup(b, e - b); + if (!ret) + return -ENOMEM; + + *name = ret; + *p = e; + *state = INT_TO_PTR(STATE_ATTRIBUTE); + + return XML_ATTRIBUTE_NAME; + } + + if (startswith(b, "/>")) { + /* An empty tag */ + + *name = NULL; /* For empty tags we return a NULL name, the caller must be prepared for that */ + *p = b + 2; + *state = INT_TO_PTR(STATE_TEXT); + + return XML_TAG_CLOSE_EMPTY; + } + + if (*b != '>') + return -EINVAL; + + c = b + 1; + t = STATE_TEXT; + continue; + + case STATE_ATTRIBUTE: + + if (*c == '=') { + c++; + + if (IN_SET(*c, '\'', '"')) { + /* Tag with a quoted value */ + + e = strchr(c+1, *c); + if (!e) + return -EINVAL; + + inc_lines(line, c, e - c); + + ret = strndup(c+1, e - c - 1); + if (!ret) + return -ENOMEM; + + *name = ret; + *p = e + 1; + *state = INT_TO_PTR(STATE_TAG); + + return XML_ATTRIBUTE_VALUE; + + } + + /* Tag with a value without quotes */ + + b = strpbrk(c, WHITESPACE ">"); + if (!b) + b = c; + + ret = strndup(c, b - c); + if (!ret) + return -ENOMEM; + + *name = ret; + *p = b; + *state = INT_TO_PTR(STATE_TAG); + return XML_ATTRIBUTE_VALUE; + } + + t = STATE_TAG; + continue; + } + + } + + assert_not_reached("Bad state"); +} diff --git a/src/shared/xml.h b/src/shared/xml.h new file mode 100644 index 00000000..8da2ff5f --- /dev/null +++ b/src/shared/xml.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +enum { + XML_END, + XML_TEXT, + XML_TAG_OPEN, + XML_TAG_CLOSE, + XML_TAG_CLOSE_EMPTY, + XML_ATTRIBUTE_NAME, + XML_ATTRIBUTE_VALUE, +}; + +int xml_tokenize(const char **p, char **name, void **state, unsigned *line); diff --git a/src/shutdown/meson.build b/src/shutdown/meson.build new file mode 100644 index 00000000..ebf0bed2 --- /dev/null +++ b/src/shutdown/meson.build @@ -0,0 +1,5 @@ +systemd_shutdown_sources = files(''' + shutdown.c + umount.c + umount.h +'''.split()) diff --git a/src/shutdown/shutdown.c b/src/shutdown/shutdown.c new file mode 100644 index 00000000..15e6c179 --- /dev/null +++ b/src/shutdown/shutdown.c @@ -0,0 +1,590 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2010 ProFUSION embedded systems +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "async.h" +#include "cgroup-setup.h" +#include "cgroup-util.h" +#include "def.h" +#include "exec-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "killall.h" +#include "log.h" +#include "parse-util.h" +#include "process-util.h" +#include "reboot-util.h" +#include "rlimit-util.h" +#include "signal-util.h" +#include "string-util.h" +#include "switch-root.h" +#include "sysctl-util.h" +#include "terminal-util.h" +#include "umount.h" +#include "util.h" +#include "virt.h" +#include "watchdog.h" + +#define SYNC_PROGRESS_ATTEMPTS 3 +#define SYNC_TIMEOUT_USEC (10*USEC_PER_SEC) + +static char* arg_verb; +static uint8_t arg_exit_code; +static usec_t arg_timeout = DEFAULT_TIMEOUT_USEC; + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_LOG_LEVEL = 0x100, + ARG_LOG_TARGET, + ARG_LOG_COLOR, + ARG_LOG_LOCATION, + ARG_EXIT_CODE, + ARG_TIMEOUT, + }; + + static const struct option options[] = { + { "log-level", required_argument, NULL, ARG_LOG_LEVEL }, + { "log-target", required_argument, NULL, ARG_LOG_TARGET }, + { "log-color", optional_argument, NULL, ARG_LOG_COLOR }, + { "log-location", optional_argument, NULL, ARG_LOG_LOCATION }, + { "exit-code", required_argument, NULL, ARG_EXIT_CODE }, + { "timeout", required_argument, NULL, ARG_TIMEOUT }, + {} + }; + + int c, r; + + assert(argc >= 1); + assert(argv); + + /* "-" prevents getopt from permuting argv[] and moving the verb away + * from argv[1]. Our interface to initrd promises it'll be there. */ + while ((c = getopt_long(argc, argv, "-", options, NULL)) >= 0) + switch (c) { + + case ARG_LOG_LEVEL: + r = log_set_max_level_from_string(optarg); + if (r < 0) + log_error_errno(r, "Failed to parse log level %s, ignoring: %m", optarg); + + break; + + case ARG_LOG_TARGET: + r = log_set_target_from_string(optarg); + if (r < 0) + log_error_errno(r, "Failed to parse log target %s, ignoring: %m", optarg); + + break; + + case ARG_LOG_COLOR: + + if (optarg) { + r = log_show_color_from_string(optarg); + if (r < 0) + log_error_errno(r, "Failed to parse log color setting %s, ignoring: %m", optarg); + } else + log_show_color(true); + + break; + + case ARG_LOG_LOCATION: + if (optarg) { + r = log_show_location_from_string(optarg); + if (r < 0) + log_error_errno(r, "Failed to parse log location setting %s, ignoring: %m", optarg); + } else + log_show_location(true); + + break; + + case ARG_EXIT_CODE: + r = safe_atou8(optarg, &arg_exit_code); + if (r < 0) + log_error_errno(r, "Failed to parse exit code %s, ignoring: %m", optarg); + + break; + + case ARG_TIMEOUT: + r = parse_sec(optarg, &arg_timeout); + if (r < 0) + log_error_errno(r, "Failed to parse shutdown timeout %s, ignoring: %m", optarg); + + break; + + case '\001': + if (!arg_verb) + arg_verb = optarg; + else + log_error("Excess arguments, ignoring"); + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option code."); + } + + if (!arg_verb) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Verb argument missing."); + + return 0; +} + +static int switch_root_initramfs(void) { + if (mount("/run/initramfs", "/run/initramfs", NULL, MS_BIND, NULL) < 0) + return log_error_errno(errno, "Failed to mount bind /run/initramfs on /run/initramfs: %m"); + + if (mount(NULL, "/run/initramfs", NULL, MS_PRIVATE, NULL) < 0) + return log_error_errno(errno, "Failed to make /run/initramfs private mount: %m"); + + /* switch_root with MS_BIND, because there might still be processes lurking around, which have open file descriptors. + * /run/initramfs/shutdown will take care of these. + * Also do not detach the old root, because /run/initramfs/shutdown needs to access it. + */ + return switch_root("/run/initramfs", "/oldroot", false, MS_BIND); +} + +/* Read the following fields from /proc/meminfo: + * + * NFS_Unstable + * Writeback + * Dirty + * + * Return true if the sum of these fields is greater than the previous + * value input. For all other issues, report the failure and indicate that + * the sync is not making progress. + */ +static int sync_making_progress(unsigned long long *prev_dirty) { + _cleanup_fclose_ FILE *f = NULL; + unsigned long long val = 0; + int ret; + + f = fopen("/proc/meminfo", "re"); + if (!f) + return log_warning_errno(errno, "Failed to open /proc/meminfo: %m"); + + for (;;) { + _cleanup_free_ char *line = NULL; + unsigned long long ull = 0; + int q; + + q = read_line(f, LONG_LINE_MAX, &line); + if (q < 0) + return log_warning_errno(q, "Failed to parse /proc/meminfo: %m"); + if (q == 0) + break; + + if (!first_word(line, "NFS_Unstable:") && !first_word(line, "Writeback:") && !first_word(line, "Dirty:")) + continue; + + errno = 0; + if (sscanf(line, "%*s %llu %*s", &ull) != 1) { + if (errno != 0) + log_warning_errno(errno, "Failed to parse /proc/meminfo: %m"); + else + log_warning("Failed to parse /proc/meminfo"); + + return false; + } + + val += ull; + } + + ret = *prev_dirty > val; + *prev_dirty = val; + return ret; +} + +static void sync_with_progress(void) { + unsigned long long dirty = ULLONG_MAX; + unsigned checks; + pid_t pid; + int r; + + BLOCK_SIGNALS(SIGCHLD); + + /* Due to the possibility of the sync operation hanging, we fork a child process and monitor the progress. If + * the timeout lapses, the assumption is that that particular sync stalled. */ + + r = asynchronous_sync(&pid); + if (r < 0) { + log_error_errno(r, "Failed to fork sync(): %m"); + return; + } + + log_info("Syncing filesystems and block devices."); + + /* Start monitoring the sync operation. If more than + * SYNC_PROGRESS_ATTEMPTS lapse without progress being made, + * we assume that the sync is stalled */ + for (checks = 0; checks < SYNC_PROGRESS_ATTEMPTS; checks++) { + r = wait_for_terminate_with_timeout(pid, SYNC_TIMEOUT_USEC); + if (r == 0) + /* Sync finished without error. + * (The sync itself does not return an error code) */ + return; + else if (r == -ETIMEDOUT) { + /* Reset the check counter if the "Dirty" value is + * decreasing */ + if (sync_making_progress(&dirty) > 0) + checks = 0; + } else { + log_error_errno(r, "Failed to sync filesystems and block devices: %m"); + return; + } + } + + /* Only reached in the event of a timeout. We should issue a kill + * to the stray process. */ + log_error("Syncing filesystems and block devices - timed out, issuing SIGKILL to PID "PID_FMT".", pid); + (void) kill(pid, SIGKILL); +} + +static int read_current_sysctl_printk_log_level(void) { + _cleanup_free_ char *sysctl_printk_vals = NULL, *sysctl_printk_curr = NULL; + int current_lvl; + const char *p; + int r; + + r = sysctl_read("kernel/printk", &sysctl_printk_vals); + if (r < 0) + return log_debug_errno(r, "Cannot read sysctl kernel.printk: %m"); + + p = sysctl_printk_vals; + r = extract_first_word(&p, &sysctl_printk_curr, NULL, 0); + if (r < 0) + return log_debug_errno(r, "Failed to split out kernel printk priority: %m"); + if (r == 0) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Short read while reading kernel.printk sysctl"); + + r = safe_atoi(sysctl_printk_curr, ¤t_lvl); + if (r < 0) + return log_debug_errno(r, "Failed to parse kernel.printk sysctl: %s", sysctl_printk_vals); + + return current_lvl; +} + +static void bump_sysctl_printk_log_level(int min_level) { + int current_lvl, r; + + /* Set the logging level to be able to see messages with log level smaller or equal to min_level */ + + current_lvl = read_current_sysctl_printk_log_level(); + if (current_lvl < 0 || current_lvl >= min_level + 1) + return; + + r = sysctl_writef("kernel/printk", "%i", min_level + 1); + if (r < 0) + log_debug_errno(r, "Failed to bump kernel.printk to %i: %m", min_level + 1); +} + +int main(int argc, char *argv[]) { + bool need_umount, need_swapoff, need_loop_detach, need_dm_detach, in_container, use_watchdog = false, can_initrd; + _cleanup_free_ char *cgroup = NULL; + char *arguments[3], *watchdog_device; + int cmd, r, umount_log_level = LOG_INFO; + static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL}; + + /* The log target defaults to console, but the original systemd process will pass its log target in through a + * command line argument, which will override this default. Also, ensure we'll never log to the journal or + * syslog, as these logging daemons are either already dead or will die very soon. */ + + log_set_target(LOG_TARGET_CONSOLE); + log_set_prohibit_ipc(true); + log_parse_environment(); + + r = parse_argv(argc, argv); + if (r < 0) + goto error; + + log_open(); + + umask(0022); + + if (getpid_cached() != 1) { + log_error("Not executed by init (PID 1)."); + r = -EPERM; + goto error; + } + + if (streq(arg_verb, "reboot")) + cmd = RB_AUTOBOOT; + else if (streq(arg_verb, "poweroff")) + cmd = RB_POWER_OFF; + else if (streq(arg_verb, "halt")) + cmd = RB_HALT_SYSTEM; + else if (streq(arg_verb, "kexec")) + cmd = LINUX_REBOOT_CMD_KEXEC; + else if (streq(arg_verb, "exit")) + cmd = 0; /* ignored, just checking that arg_verb is valid */ + else { + log_error("Unknown action '%s'.", arg_verb); + r = -EINVAL; + goto error; + } + + (void) cg_get_root_path(&cgroup); + in_container = detect_container() > 0; + + /* If the logging messages are going to KMSG, and if we are not running from a container, then try to + * update the sysctl kernel.printk current value in order to see "info" messages; This current log + * level is not updated if already big enough. + */ + if (!in_container && + IN_SET(log_get_target(), + LOG_TARGET_AUTO, + LOG_TARGET_JOURNAL_OR_KMSG, + LOG_TARGET_SYSLOG_OR_KMSG, + LOG_TARGET_KMSG)) + bump_sysctl_printk_log_level(LOG_WARNING); + + use_watchdog = getenv("WATCHDOG_USEC"); + watchdog_device = getenv("WATCHDOG_DEVICE"); + if (watchdog_device) { + r = watchdog_set_device(watchdog_device); + if (r < 0) + log_warning_errno(r, "Failed to set watchdog device to %s, ignoring: %m", + watchdog_device); + } + + /* Lock us into memory */ + (void) mlockall(MCL_CURRENT|MCL_FUTURE); + + /* Synchronize everything that is not written to disk yet at this point already. This is a good idea so that + * slow IO is processed here already and the final process killing spree is not impacted by processes + * desperately trying to sync IO to disk within their timeout. Do not remove this sync, data corruption will + * result. */ + if (!in_container) + sync_with_progress(); + + disable_coredumps(); + + log_info("Sending SIGTERM to remaining processes..."); + broadcast_signal(SIGTERM, true, true, arg_timeout); + + log_info("Sending SIGKILL to remaining processes..."); + broadcast_signal(SIGKILL, true, false, arg_timeout); + + need_umount = !in_container; + need_swapoff = !in_container; + need_loop_detach = !in_container; + need_dm_detach = !in_container; + can_initrd = !in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0; + + /* Unmount all mountpoints, swaps, and loopback devices */ + for (;;) { + bool changed = false; + + if (use_watchdog) + (void) watchdog_ping(); + + /* Let's trim the cgroup tree on each iteration so + that we leave an empty cgroup tree around, so that + container managers get a nice notify event when we + are down */ + if (cgroup) + (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false); + + if (need_umount) { + log_info("Unmounting file systems."); + r = umount_all(&changed, umount_log_level); + if (r == 0) { + need_umount = false; + log_info("All filesystems unmounted."); + } else if (r > 0) + log_info("Not all file systems unmounted, %d left.", r); + else + log_error_errno(r, "Failed to unmount file systems: %m"); + } + + if (need_swapoff) { + log_info("Deactivating swaps."); + r = swapoff_all(&changed); + if (r == 0) { + need_swapoff = false; + log_info("All swaps deactivated."); + } else if (r > 0) + log_info("Not all swaps deactivated, %d left.", r); + else + log_error_errno(r, "Failed to deactivate swaps: %m"); + } + + if (need_loop_detach) { + log_info("Detaching loop devices."); + r = loopback_detach_all(&changed, umount_log_level); + if (r == 0) { + need_loop_detach = false; + log_info("All loop devices detached."); + } else if (r > 0) + log_info("Not all loop devices detached, %d left.", r); + else + log_error_errno(r, "Failed to detach loop devices: %m"); + } + + if (need_dm_detach) { + log_info("Detaching DM devices."); + r = dm_detach_all(&changed, umount_log_level); + if (r == 0) { + need_dm_detach = false; + log_info("All DM devices detached."); + } else if (r > 0) + log_info("Not all DM devices detached, %d left.", r); + else + log_error_errno(r, "Failed to detach DM devices: %m"); + } + + if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) { + log_info("All filesystems, swaps, loop devices and DM devices detached."); + /* Yay, done */ + break; + } + + if (!changed && umount_log_level == LOG_INFO && !can_initrd) { + /* There are things we cannot get rid of. Loop one more time + * with LOG_ERR to inform the user. Note that we don't need + * to do this if there is a initrd to switch to, because that + * one is likely to get rid of the remounting mounts. If not, + * it will log about them. */ + umount_log_level = LOG_ERR; + continue; + } + + /* If in this iteration we didn't manage to + * unmount/deactivate anything, we simply give up */ + if (!changed) { + log_info("Cannot finalize remaining%s%s%s%s continuing.", + need_umount ? " file systems," : "", + need_swapoff ? " swap devices," : "", + need_loop_detach ? " loop devices," : "", + need_dm_detach ? " DM devices," : ""); + break; + } + + log_debug("Couldn't finalize remaining %s%s%s%s trying again.", + need_umount ? " file systems," : "", + need_swapoff ? " swap devices," : "", + need_loop_detach ? " loop devices," : "", + need_dm_detach ? " DM devices," : ""); + } + + /* We're done with the watchdog. */ + watchdog_free_device(); + + arguments[0] = NULL; + arguments[1] = arg_verb; + arguments[2] = NULL; + (void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + + (void) rlimit_nofile_safe(); + + if (can_initrd) { + r = switch_root_initramfs(); + if (r >= 0) { + argv[0] = (char*) "/shutdown"; + + (void) setsid(); + (void) make_console_stdio(); + + log_info("Successfully changed into root pivot.\n" + "Returning to initrd..."); + + execv("/shutdown", argv); + log_error_errno(errno, "Failed to execute shutdown binary: %m"); + } else + log_error_errno(r, "Failed to switch root to \"/run/initramfs\": %m"); + } + + if (need_umount || need_swapoff || need_loop_detach || need_dm_detach) + log_error("Failed to finalize %s%s%s%s ignoring", + need_umount ? " file systems," : "", + need_swapoff ? " swap devices," : "", + need_loop_detach ? " loop devices," : "", + need_dm_detach ? " DM devices," : ""); + + /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be + * sync'ed explicitly in advance. So let's do this here, but not needlessly slow down containers. Note that we + * sync'ed things already once above, but we did some more work since then which might have caused IO, hence + * let's do it once more. Do not remove this sync, data corruption will result. */ + if (!in_container) + sync_with_progress(); + + if (streq(arg_verb, "exit")) { + if (in_container) + return arg_exit_code; + + cmd = RB_POWER_OFF; /* We cannot exit() on the host, fallback on another method. */ + } + + switch (cmd) { + + case LINUX_REBOOT_CMD_KEXEC: + + if (!in_container) { + /* We cheat and exec kexec to avoid doing all its work */ + log_info("Rebooting with kexec."); + + r = safe_fork("(sd-kexec)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, NULL); + if (r == 0) { + const char * const args[] = { + KEXEC, "-e", NULL + }; + + /* Child */ + + execv(args[0], (char * const *) args); + _exit(EXIT_FAILURE); + } + + /* If we are still running, then the kexec can't have worked, let's fall through */ + } + + cmd = RB_AUTOBOOT; + _fallthrough_; + + case RB_AUTOBOOT: + (void) reboot_with_parameter(REBOOT_LOG); + log_info("Rebooting."); + break; + + case RB_POWER_OFF: + log_info("Powering off."); + break; + + case RB_HALT_SYSTEM: + log_info("Halting system."); + break; + + default: + assert_not_reached("Unknown magic"); + } + + (void) reboot(cmd); + if (errno == EPERM && in_container) { + /* If we are in a container, and we lacked + * CAP_SYS_BOOT just exit, this will kill our + * container for good. */ + log_info("Exiting container."); + return EXIT_SUCCESS; + } + + r = log_error_errno(errno, "Failed to invoke reboot(): %m"); + + error: + log_emergency_errno(r, "Critical error while doing system shutdown: %m"); + freeze(); +} diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c new file mode 100644 index 00000000..e006b4a2 --- /dev/null +++ b/src/shutdown/umount.c @@ -0,0 +1,691 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2010 ProFUSION embedded systems +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-device.h" + +#include "alloc-util.h" +#include "blockdev-util.h" +#include "def.h" +#include "device-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fstab-util.h" +#include "libmount-util.h" +#include "mount-setup.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "path-util.h" +#include "process-util.h" +#include "signal-util.h" +#include "string-util.h" +#include "strv.h" +#include "umount.h" +#include "util.h" +#include "virt.h" + +static void mount_point_free(MountPoint **head, MountPoint *m) { + assert(head); + assert(m); + + LIST_REMOVE(mount_point, *head, m); + + free(m->path); + free(m->remount_options); + free(m); +} + +void mount_points_list_free(MountPoint **head) { + assert(head); + + while (*head) + mount_point_free(head, *head); +} + +int mount_points_list_get(const char *mountinfo, MountPoint **head) { + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; + int r; + + assert(head); + + r = libmount_parse(mountinfo, NULL, &table, &iter); + if (r < 0) + return log_error_errno(r, "Failed to parse %s: %m", mountinfo ?: "/proc/self/mountinfo"); + + for (;;) { + struct libmnt_fs *fs; + const char *path, *fstype; + _cleanup_free_ char *options = NULL; + unsigned long remount_flags = 0u; + _cleanup_free_ char *remount_options = NULL; + bool try_remount_ro; + _cleanup_free_ MountPoint *m = NULL; + + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) + break; + if (r < 0) + return log_error_errno(r, "Failed to get next entry from %s: %m", mountinfo ?: "/proc/self/mountinfo"); + + path = mnt_fs_get_target(fs); + if (!path) + continue; + + fstype = mnt_fs_get_fstype(fs); + + /* Combine the generic VFS options with the FS-specific + * options. Duplicates are not a problem here, because the only + * options that should come up twice are typically ro/rw, which + * are turned into MS_RDONLY or the inversion of it. + * + * Even if there are duplicates later in mount_option_mangle() + * they shouldn't hurt anyways as they override each other. + */ + if (!strextend_with_separator(&options, ",", + mnt_fs_get_vfs_options(fs), + NULL)) + return log_oom(); + if (!strextend_with_separator(&options, ",", + mnt_fs_get_fs_options(fs), + NULL)) + return log_oom(); + + /* Ignore mount points we can't unmount because they + * are API or because we are keeping them open (like + * /dev/console). Also, ignore all mounts below API + * file systems, since they are likely virtual too, + * and hence not worth spending time on. Also, in + * unprivileged containers we might lack the rights to + * unmount these things, hence don't bother. */ + if (mount_point_is_api(path) || + mount_point_ignore(path) || + PATH_STARTSWITH_SET(path, "/dev", "/sys", "/proc")) + continue; + + /* If we are in a container, don't attempt to + * read-only mount anything as that brings no real + * benefits, but might confuse the host, as we remount + * the superblock here, not the bind mount. + * + * If the filesystem is a network fs, also skip the + * remount. It brings no value (we cannot leave + * a "dirty fs") and could hang if the network is down. + * Note that umount2() is more careful and will not + * hang because of the network being down. */ + try_remount_ro = detect_container() <= 0 && + !fstype_is_network(fstype) && + !fstype_is_api_vfs(fstype) && + !fstype_is_ro(fstype) && + !fstab_test_yes_no_option(options, "ro\0rw\0"); + + if (try_remount_ro) { + /* mount(2) states that mount flags and options need to be exactly the same + * as they were when the filesystem was mounted, except for the desired + * changes. So we reconstruct both here and adjust them for the later + * remount call too. */ + + r = mnt_fs_get_propagation(fs, &remount_flags); + if (r < 0) { + log_warning_errno(r, "mnt_fs_get_propagation() failed for %s, ignoring: %m", path); + continue; + } + + r = mount_option_mangle(options, remount_flags, &remount_flags, &remount_options); + if (r < 0) { + log_warning_errno(r, "mount_option_mangle failed for %s, ignoring: %m", path); + continue; + } + + /* MS_BIND is special. If it is provided it will only make the mount-point + * read-only. If left out, the super block itself is remounted, which we want. */ + remount_flags = (remount_flags|MS_REMOUNT|MS_RDONLY) & ~MS_BIND; + } + + m = new0(MountPoint, 1); + if (!m) + return log_oom(); + + m->path = strdup(path); + if (!m->path) + return log_oom(); + + m->remount_options = TAKE_PTR(remount_options); + m->remount_flags = remount_flags; + m->try_remount_ro = try_remount_ro; + + LIST_PREPEND(mount_point, *head, TAKE_PTR(m)); + } + + return 0; +} + +int swap_list_get(const char *swaps, MountPoint **head) { + _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL; + int r; + + assert(head); + + t = mnt_new_table(); + i = mnt_new_iter(MNT_ITER_FORWARD); + if (!t || !i) + return log_oom(); + + r = mnt_table_parse_swaps(t, swaps); + if (r == -ENOENT) /* no /proc/swaps is fine */ + return 0; + if (r < 0) + return log_error_errno(r, "Failed to parse %s: %m", swaps ?: "/proc/swaps"); + + for (;;) { + struct libmnt_fs *fs; + _cleanup_free_ MountPoint *swap = NULL; + const char *source; + + r = mnt_table_next_fs(t, i, &fs); + if (r == 1) + break; + if (r < 0) + return log_error_errno(r, "Failed to get next entry from %s: %m", swaps ?: "/proc/swaps"); + + source = mnt_fs_get_source(fs); + if (!source) + continue; + + swap = new0(MountPoint, 1); + if (!swap) + return log_oom(); + + swap->path = strdup(source); + if (!swap->path) + return log_oom(); + + LIST_PREPEND(mount_point, *head, TAKE_PTR(swap)); + } + + return 0; +} + +static int loopback_list_get(MountPoint **head) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *d; + int r; + + assert(head); + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_subsystem(e, "block", true); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_sysname(e, "loop*"); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_sysattr(e, "loop/backing_file", NULL, true); + if (r < 0) + return r; + + FOREACH_DEVICE(e, d) { + _cleanup_free_ char *p = NULL; + const char *dn; + MountPoint *lb; + + if (sd_device_get_devname(d, &dn) < 0) + continue; + + p = strdup(dn); + if (!p) + return -ENOMEM; + + lb = new(MountPoint, 1); + if (!lb) + return -ENOMEM; + + *lb = (MountPoint) { + .path = TAKE_PTR(p), + }; + + LIST_PREPEND(mount_point, *head, lb); + } + + return 0; +} + +static int dm_list_get(MountPoint **head) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *d; + int r; + + assert(head); + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_subsystem(e, "block", true); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_sysname(e, "dm-*"); + if (r < 0) + return r; + + FOREACH_DEVICE(e, d) { + _cleanup_free_ char *p = NULL; + const char *dn; + MountPoint *m; + dev_t devnum; + + if (sd_device_get_devnum(d, &devnum) < 0 || + sd_device_get_devname(d, &dn) < 0) + continue; + + p = strdup(dn); + if (!p) + return -ENOMEM; + + m = new(MountPoint, 1); + if (!m) + return -ENOMEM; + + *m = (MountPoint) { + .path = TAKE_PTR(p), + .devnum = devnum, + }; + + LIST_PREPEND(mount_point, *head, m); + } + + return 0; +} + +static int delete_loopback(const char *device) { + _cleanup_close_ int fd = -1; + int r; + + assert(device); + + fd = open(device, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return errno == ENOENT ? 0 : -errno; + + r = ioctl(fd, LOOP_CLR_FD, 0); + if (r >= 0) + return 1; + + /* ENXIO: not bound, so no error */ + if (errno == ENXIO) + return 0; + + return -errno; +} + +static int delete_dm(dev_t devnum) { + + struct dm_ioctl dm = { + .version = { + DM_VERSION_MAJOR, + DM_VERSION_MINOR, + DM_VERSION_PATCHLEVEL + }, + .data_size = sizeof(dm), + .dev = devnum, + }; + + _cleanup_close_ int fd = -1; + + assert(major(devnum) != 0); + + fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC); + if (fd < 0) + return -errno; + + if (ioctl(fd, DM_DEV_REMOVE, &dm) < 0) + return -errno; + + return 0; +} + +static bool nonunmountable_path(const char *path) { + return path_equal(path, "/") +#if ! HAVE_SPLIT_USR + || path_equal(path, "/usr") +#endif + || path_startswith(path, "/run/initramfs"); +} + +static int remount_with_timeout(MountPoint *m, int umount_log_level) { + pid_t pid; + int r; + + BLOCK_SIGNALS(SIGCHLD); + + assert(m); + + /* Due to the possibility of a remount operation hanging, we + * fork a child process and set a timeout. If the timeout + * lapses, the assumption is that that particular remount + * failed. */ + r = safe_fork("(sd-remount)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + log_info("Remounting '%s' read-only in with options '%s'.", m->path, m->remount_options); + + /* Start the mount operation here in the child */ + r = mount(NULL, m->path, NULL, m->remount_flags, m->remount_options); + if (r < 0) + log_full_errno(umount_log_level, errno, "Failed to remount '%s' read-only: %m", m->path); + + _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); + } + + r = wait_for_terminate_with_timeout(pid, DEFAULT_TIMEOUT_USEC); + if (r == -ETIMEDOUT) { + log_error_errno(r, "Remounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pid); + (void) kill(pid, SIGKILL); + } else if (r == -EPROTO) + log_debug_errno(r, "Remounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid); + else if (r < 0) + log_error_errno(r, "Remounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pid); + + return r; +} + +static int umount_with_timeout(MountPoint *m, int umount_log_level) { + pid_t pid; + int r; + + BLOCK_SIGNALS(SIGCHLD); + + assert(m); + + /* Due to the possibility of a umount operation hanging, we + * fork a child process and set a timeout. If the timeout + * lapses, the assumption is that that particular umount + * failed. */ + r = safe_fork("(sd-umount)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + log_info("Unmounting '%s'.", m->path); + + /* Start the mount operation here in the child Using MNT_FORCE + * causes some filesystems (e.g. FUSE and NFS and other network + * filesystems) to abort any pending requests and return -EIO + * rather than blocking indefinitely. If the filesysten is + * "busy", this may allow processes to die, thus making the + * filesystem less busy so the unmount might succeed (rather + * then return EBUSY).*/ + r = umount2(m->path, MNT_FORCE); + if (r < 0) + log_full_errno(umount_log_level, errno, "Failed to unmount %s: %m", m->path); + + _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); + } + + r = wait_for_terminate_with_timeout(pid, DEFAULT_TIMEOUT_USEC); + if (r == -ETIMEDOUT) { + log_error_errno(r, "Unmounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pid); + (void) kill(pid, SIGKILL); + } else if (r == -EPROTO) + log_debug_errno(r, "Unmounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid); + else if (r < 0) + log_error_errno(r, "Unmounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pid); + + return r; +} + +/* This includes remounting readonly, which changes the kernel mount options. + * Therefore the list passed to this function is invalidated, and should not be reused. */ +static int mount_points_list_umount(MountPoint **head, bool *changed, int umount_log_level) { + MountPoint *m; + int n_failed = 0; + + assert(head); + assert(changed); + + LIST_FOREACH(mount_point, m, *head) { + if (m->try_remount_ro) { + /* We always try to remount directories + * read-only first, before we go on and umount + * them. + * + * Mount points can be stacked. If a mount + * point is stacked below / or /usr, we + * cannot umount or remount it directly, + * since there is no way to refer to the + * underlying mount. There's nothing we can do + * about it for the general case, but we can + * do something about it if it is aliased + * somewhere else via a bind mount. If we + * explicitly remount the super block of that + * alias read-only we hence should be + * relatively safe regarding keeping a dirty fs + * we cannot otherwise see. + * + * Since the remount can hang in the instance of + * remote filesystems, we remount asynchronously + * and skip the subsequent umount if it fails. */ + if (remount_with_timeout(m, umount_log_level) < 0) { + /* Remount failed, but try unmounting anyway, + * unless this is a mount point we want to skip. */ + if (nonunmountable_path(m->path)) { + n_failed++; + continue; + } + } + } + + /* Skip / and /usr since we cannot unmount that + * anyway, since we are running from it. They have + * already been remounted ro. */ + if (nonunmountable_path(m->path)) + continue; + + /* Trying to umount */ + if (umount_with_timeout(m, umount_log_level) < 0) + n_failed++; + else + *changed = true; + } + + return n_failed; +} + +static int swap_points_list_off(MountPoint **head, bool *changed) { + MountPoint *m, *n; + int n_failed = 0; + + assert(head); + assert(changed); + + LIST_FOREACH_SAFE(mount_point, m, n, *head) { + log_info("Deactivating swap %s.", m->path); + if (swapoff(m->path) < 0) { + log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path); + n_failed++; + continue; + } + + *changed = true; + mount_point_free(head, m); + } + + return n_failed; +} + +static int loopback_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) { + MountPoint *m, *n; + int n_failed = 0, k; + struct stat root_st; + + assert(head); + assert(changed); + + k = lstat("/", &root_st); + + LIST_FOREACH_SAFE(mount_point, m, n, *head) { + int r; + struct stat loopback_st; + + if (k >= 0 && + major(root_st.st_dev) != 0 && + lstat(m->path, &loopback_st) >= 0 && + root_st.st_dev == loopback_st.st_rdev) { + n_failed++; + continue; + } + + log_info("Detaching loopback %s.", m->path); + r = delete_loopback(m->path); + if (r < 0) { + log_full_errno(umount_log_level, r, "Could not detach loopback %s: %m", m->path); + n_failed++; + continue; + } + if (r > 0) + *changed = true; + + mount_point_free(head, m); + } + + return n_failed; +} + +static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) { + MountPoint *m, *n; + int n_failed = 0, r; + dev_t rootdev; + + assert(head); + assert(changed); + + r = get_block_device("/", &rootdev); + if (r <= 0) + rootdev = 0; + + LIST_FOREACH_SAFE(mount_point, m, n, *head) { + + if (major(rootdev) != 0 && rootdev == m->devnum) { + n_failed ++; + continue; + } + + log_info("Detaching DM %s (%u:%u).", m->path, major(m->devnum), minor(m->devnum)); + r = delete_dm(m->devnum); + if (r < 0) { + log_full_errno(umount_log_level, r, "Could not detach DM %s: %m", m->path); + n_failed++; + continue; + } + + *changed = true; + mount_point_free(head, m); + } + + return n_failed; +} + +static int umount_all_once(bool *changed, int umount_log_level) { + _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head); + int r; + + assert(changed); + + LIST_HEAD_INIT(mp_list_head); + r = mount_points_list_get(NULL, &mp_list_head); + if (r < 0) + return r; + + return mount_points_list_umount(&mp_list_head, changed, umount_log_level); +} + +int umount_all(bool *changed, int umount_log_level) { + bool umount_changed; + int r; + + assert(changed); + + /* Retry umount, until nothing can be umounted anymore. Mounts are + * processed in order, newest first. The retries are needed when + * an old mount has been moved, to a path inside a newer mount. */ + do { + umount_changed = false; + + r = umount_all_once(&umount_changed, umount_log_level); + if (umount_changed) + *changed = true; + } while (umount_changed); + + return r; +} + +int swapoff_all(bool *changed) { + _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, swap_list_head); + int r; + + assert(changed); + + LIST_HEAD_INIT(swap_list_head); + + r = swap_list_get(NULL, &swap_list_head); + if (r < 0) + return r; + + return swap_points_list_off(&swap_list_head, changed); +} + +int loopback_detach_all(bool *changed, int umount_log_level) { + _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, loopback_list_head); + int r; + + assert(changed); + + LIST_HEAD_INIT(loopback_list_head); + + r = loopback_list_get(&loopback_list_head); + if (r < 0) + return r; + + return loopback_points_list_detach(&loopback_list_head, changed, umount_log_level); +} + +int dm_detach_all(bool *changed, int umount_log_level) { + _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, dm_list_head); + int r; + + assert(changed); + + LIST_HEAD_INIT(dm_list_head); + + r = dm_list_get(&dm_list_head); + if (r < 0) + return r; + + return dm_points_list_detach(&dm_list_head, changed, umount_log_level); +} diff --git a/src/shutdown/umount.h b/src/shutdown/umount.h new file mode 100644 index 00000000..6f2b24d1 --- /dev/null +++ b/src/shutdown/umount.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +/*** + Copyright © 2010 ProFUSION embedded systems +***/ + +#include "list.h" + +int umount_all(bool *changed, int umount_log_level); + +int swapoff_all(bool *changed); + +int loopback_detach_all(bool *changed, int umount_log_level); + +int dm_detach_all(bool *changed, int umount_log_level); + +/* This is exported just for testing */ +typedef struct MountPoint { + char *path; + char *remount_options; + unsigned long remount_flags; + bool try_remount_ro; + dev_t devnum; + LIST_FIELDS(struct MountPoint, mount_point); +} MountPoint; + +int mount_points_list_get(const char *mountinfo, MountPoint **head); +void mount_points_list_free(MountPoint **head); +int swap_list_get(const char *swaps, MountPoint **head); diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c new file mode 100644 index 00000000..89b80367 --- /dev/null +++ b/src/sleep/sleep.c @@ -0,0 +1,352 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2010-2017 Canonical + Copyright © 2018 Dell Inc. +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-messages.h" + +#include "btrfs-util.h" +#include "def.h" +#include "exec-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "fileio.h" +#include "log.h" +#include "main-func.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "sleep-config.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "util.h" + +static char* arg_verb = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_verb, freep); + +static int write_hibernate_location_info(const HibernateLocation *hibernate_location) { + char offset_str[DECIMAL_STR_MAX(uint64_t)]; + int r; + + assert(hibernate_location); + assert(hibernate_location->swap); + assert(hibernate_location->resume); + + r = write_string_file("/sys/power/resume", hibernate_location->resume, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return log_debug_errno(r, "Failed to write partition device to /sys/power/resume for '%s': '%s': %m", + hibernate_location->swap->device, hibernate_location->resume); + + log_debug("Wrote resume= value for %s to /sys/power/resume: %s", hibernate_location->swap->device, hibernate_location->resume); + + /* if it's a swap partition, we're done */ + if (streq(hibernate_location->swap->type, "partition")) + return r; + + if (!streq(hibernate_location->swap->type, "file")) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid hibernate type: %s", hibernate_location->swap->type); + + /* Only available in 4.17+ */ + if (hibernate_location->resume_offset > 0 && access("/sys/power/resume_offset", W_OK) < 0) { + if (errno == ENOENT) { + log_debug("Kernel too old, can't configure resume_offset for %s, ignoring: %" PRIu64, + hibernate_location->swap->device, hibernate_location->resume_offset); + return 0; + } + + return log_debug_errno(errno, "/sys/power/resume_offset not writeable: %m"); + } + + xsprintf(offset_str, "%" PRIu64, hibernate_location->resume_offset); + r = write_string_file("/sys/power/resume_offset", offset_str, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return log_debug_errno(r, "Failed to write swap file offset to /sys/power/resume_offset for '%s': '%s': %m", + hibernate_location->swap->device, offset_str); + + log_debug("Wrote resume_offset= value for %s to /sys/power/resume_offset: %s", hibernate_location->swap->device, offset_str); + + return 0; +} + +static int write_mode(char **modes) { + int r = 0; + char **mode; + + STRV_FOREACH(mode, modes) { + int k; + + k = write_string_file("/sys/power/disk", *mode, WRITE_STRING_FILE_DISABLE_BUFFER); + if (k >= 0) + return 0; + + log_debug_errno(k, "Failed to write '%s' to /sys/power/disk: %m", *mode); + if (r >= 0) + r = k; + } + + return r; +} + +static int write_state(FILE **f, char **states) { + char **state; + int r = 0; + + STRV_FOREACH(state, states) { + int k; + + k = write_string_stream(*f, *state, WRITE_STRING_FILE_DISABLE_BUFFER); + if (k >= 0) + return 0; + log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m", *state); + if (r >= 0) + r = k; + + fclose(*f); + *f = fopen("/sys/power/state", "we"); + if (!*f) + return -errno; + } + + return r; +} + +static int execute(char **modes, char **states) { + char *arguments[] = { + NULL, + (char*) "pre", + arg_verb, + NULL + }; + static const char* const dirs[] = { + SYSTEM_SLEEP_PATH, + NULL + }; + + _cleanup_fclose_ FILE *f = NULL; + _cleanup_(hibernate_location_freep) HibernateLocation *hibernate_location = NULL; + int r; + + /* This file is opened first, so that if we hit an error, + * we can abort before modifying any state. */ + f = fopen("/sys/power/state", "we"); + if (!f) + return log_error_errno(errno, "Failed to open /sys/power/state: %m"); + + setvbuf(f, NULL, _IONBF, 0); + + /* Configure the hibernation mode */ + if (!strv_isempty(modes)) { + r = find_hibernate_location(&hibernate_location); + if (r < 0) + return r; + else if (r == 0) { + r = write_hibernate_location_info(hibernate_location); + if (r < 0) + return log_error_errno(r, "Failed to prepare for hibernation: %m"); + } + + r = write_mode(modes); + if (r < 0) + return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");; + } + + (void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR, + LOG_MESSAGE("Suspending system..."), + "SLEEP=%s", arg_verb); + + r = write_state(&f, states); + if (r < 0) + log_struct_errno(LOG_ERR, r, + "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR, + LOG_MESSAGE("Failed to suspend system. System resumed again: %m"), + "SLEEP=%s", arg_verb); + else + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_SLEEP_STOP_STR, + LOG_MESSAGE("System resumed."), + "SLEEP=%s", arg_verb); + + arguments[1] = (char*) "post"; + (void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + + return r; +} + +static int execute_s2h(const SleepConfig *sleep_config) { + _cleanup_close_ int tfd = -1; + char buf[FORMAT_TIMESPAN_MAX]; + struct itimerspec ts = {}; + struct pollfd fds; + int r; + + assert(sleep_config); + + tfd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK|TFD_CLOEXEC); + if (tfd < 0) + return log_error_errno(errno, "Error creating timerfd: %m"); + + log_debug("Set timerfd wake alarm for %s", + format_timespan(buf, sizeof(buf), sleep_config->hibernate_delay_sec, USEC_PER_SEC)); + + timespec_store(&ts.it_value, sleep_config->hibernate_delay_sec); + + r = timerfd_settime(tfd, 0, &ts, NULL); + if (r < 0) + return log_error_errno(errno, "Error setting hibernate timer: %m"); + + r = execute(sleep_config->suspend_modes, sleep_config->suspend_states); + if (r < 0) + return r; + + fds = (struct pollfd) { + .fd = tfd, + .events = POLLIN, + }; + r = poll(&fds, 1, 0); + if (r < 0) + return log_error_errno(errno, "Error polling timerfd: %m"); + + tfd = safe_close(tfd); + + if (!FLAGS_SET(fds.revents, POLLIN)) /* We woke up before the alarm time, we are done. */ + return 0; + + /* If woken up after alarm time, hibernate */ + log_debug("Attempting to hibernate after waking from %s timer", + format_timespan(buf, sizeof(buf), sleep_config->hibernate_delay_sec, USEC_PER_SEC)); + + r = execute(sleep_config->hibernate_modes, sleep_config->hibernate_states); + if (r < 0) { + log_notice("Couldn't hibernate, will try to suspend again."); + r = execute(sleep_config->suspend_modes, sleep_config->suspend_states); + if (r < 0) { + log_notice("Could neither hibernate nor suspend again, giving up."); + return r; + } + } + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-suspend.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s COMMAND\n\n" + "Suspend the system, hibernate the system, or both.\n\n" + " -h --help Show this help and exit\n" + " --version Print version string and exit\n" + "\nCommands:\n" + " suspend Suspend the system\n" + " hibernate Hibernate the system\n" + " hybrid-sleep Both hibernate and suspend the system\n" + " suspend-then-hibernate Initially suspend and then hibernate\n" + " the system after a fixed period of time\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_VERSION = 0x100, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + switch(c) { + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (argc - optind != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Usage: %s COMMAND", + program_invocation_short_name); + + arg_verb = strdup(argv[optind]); + if (!arg_verb) + return log_oom(); + + if (!STR_IN_SET(arg_verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown command '%s'.", arg_verb); + + return 1 /* work to do */; +} + +static int run(int argc, char *argv[]) { + bool allow; + char **modes = NULL, **states = NULL; + _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL; + int r; + + log_setup_service(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = parse_sleep_config(&sleep_config); + if (r < 0) + return r; + + r = sleep_settings(arg_verb, sleep_config, &allow, &modes, &states); + if (r < 0) + return r; + + if (!allow) + return log_error_errno(SYNTHETIC_ERRNO(EACCES), + "Sleep mode \"%s\" is disabled by configuration, refusing.", + arg_verb); + + if (streq(arg_verb, "suspend-then-hibernate")) + return execute_s2h(sleep_config); + else + return execute(modes, states); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/sleep/sleep.conf b/src/sleep/sleep.conf new file mode 100644 index 00000000..dc2ed37f --- /dev/null +++ b/src/sleep/sleep.conf @@ -0,0 +1,25 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See systemd-sleep.conf(5) for details + +[Sleep] +#AllowSuspend=yes +#AllowHibernation=yes +#AllowSuspendThenHibernate=yes +#AllowHybridSleep=yes +#SuspendMode= +#SuspendState=mem standby freeze +#HibernateMode=platform shutdown +#HibernateState=disk +#HybridSleepMode=suspend platform shutdown +#HybridSleepState=disk +#HibernateDelaySec=180min diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c new file mode 100644 index 00000000..2fb9c854 --- /dev/null +++ b/src/socket-proxy/socket-proxyd.c @@ -0,0 +1,664 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-event.h" +#include "sd-resolve.h" + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "log.h" +#include "main-func.h" +#include "parse-util.h" +#include "path-util.h" +#include "pretty-print.h" +#include "resolve-private.h" +#include "set.h" +#include "socket-util.h" +#include "string-util.h" +#include "util.h" + +#define BUFFER_SIZE (256 * 1024) + +static unsigned arg_connections_max = 256; +static const char *arg_remote_host = NULL; + +typedef struct Context { + sd_event *event; + sd_resolve *resolve; + + Set *listen; + Set *connections; +} Context; + +typedef struct Connection { + Context *context; + + int server_fd, client_fd; + int server_to_client_buffer[2]; /* a pipe */ + int client_to_server_buffer[2]; /* a pipe */ + + size_t server_to_client_buffer_full, client_to_server_buffer_full; + size_t server_to_client_buffer_size, client_to_server_buffer_size; + + sd_event_source *server_event_source, *client_event_source; + + sd_resolve_query *resolve_query; +} Connection; + +static void connection_free(Connection *c) { + assert(c); + + if (c->context) + set_remove(c->context->connections, c); + + sd_event_source_unref(c->server_event_source); + sd_event_source_unref(c->client_event_source); + + safe_close(c->server_fd); + safe_close(c->client_fd); + + safe_close_pair(c->server_to_client_buffer); + safe_close_pair(c->client_to_server_buffer); + + sd_resolve_query_unref(c->resolve_query); + + free(c); +} + +static void context_clear(Context *context) { + assert(context); + + set_free_with_destructor(context->listen, sd_event_source_unref); + set_free_with_destructor(context->connections, connection_free); + + sd_event_unref(context->event); + sd_resolve_unref(context->resolve); +} + +static int connection_create_pipes(Connection *c, int buffer[static 2], size_t *sz) { + int r; + + assert(c); + assert(buffer); + assert(sz); + + if (buffer[0] >= 0) + return 0; + + r = pipe2(buffer, O_CLOEXEC|O_NONBLOCK); + if (r < 0) + return log_error_errno(errno, "Failed to allocate pipe buffer: %m"); + + (void) fcntl(buffer[0], F_SETPIPE_SZ, BUFFER_SIZE); + + r = fcntl(buffer[0], F_GETPIPE_SZ); + if (r < 0) + return log_error_errno(errno, "Failed to get pipe buffer size: %m"); + + assert(r > 0); + *sz = r; + + return 0; +} + +static int connection_shovel( + Connection *c, + int *from, int buffer[2], int *to, + size_t *full, size_t *sz, + sd_event_source **from_source, sd_event_source **to_source) { + + bool shoveled; + + assert(c); + assert(from); + assert(buffer); + assert(buffer[0] >= 0); + assert(buffer[1] >= 0); + assert(to); + assert(full); + assert(sz); + assert(from_source); + assert(to_source); + + do { + ssize_t z; + + shoveled = false; + + if (*full < *sz && *from >= 0 && *to >= 0) { + z = splice(*from, NULL, buffer[1], NULL, *sz - *full, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); + if (z > 0) { + *full += z; + shoveled = true; + } else if (z == 0 || ERRNO_IS_DISCONNECT(errno)) { + *from_source = sd_event_source_unref(*from_source); + *from = safe_close(*from); + } else if (!IN_SET(errno, EAGAIN, EINTR)) + return log_error_errno(errno, "Failed to splice: %m"); + } + + if (*full > 0 && *to >= 0) { + z = splice(buffer[0], NULL, *to, NULL, *full, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); + if (z > 0) { + *full -= z; + shoveled = true; + } else if (z == 0 || ERRNO_IS_DISCONNECT(errno)) { + *to_source = sd_event_source_unref(*to_source); + *to = safe_close(*to); + } else if (!IN_SET(errno, EAGAIN, EINTR)) + return log_error_errno(errno, "Failed to splice: %m"); + } + } while (shoveled); + + return 0; +} + +static int connection_enable_event_sources(Connection *c); + +static int traffic_cb(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Connection *c = userdata; + int r; + + assert(s); + assert(fd >= 0); + assert(c); + + r = connection_shovel(c, + &c->server_fd, c->server_to_client_buffer, &c->client_fd, + &c->server_to_client_buffer_full, &c->server_to_client_buffer_size, + &c->server_event_source, &c->client_event_source); + if (r < 0) + goto quit; + + r = connection_shovel(c, + &c->client_fd, c->client_to_server_buffer, &c->server_fd, + &c->client_to_server_buffer_full, &c->client_to_server_buffer_size, + &c->client_event_source, &c->server_event_source); + if (r < 0) + goto quit; + + /* EOF on both sides? */ + if (c->server_fd == -1 && c->client_fd == -1) + goto quit; + + /* Server closed, and all data written to client? */ + if (c->server_fd == -1 && c->server_to_client_buffer_full <= 0) + goto quit; + + /* Client closed, and all data written to server? */ + if (c->client_fd == -1 && c->client_to_server_buffer_full <= 0) + goto quit; + + r = connection_enable_event_sources(c); + if (r < 0) + goto quit; + + return 1; + +quit: + connection_free(c); + return 0; /* ignore errors, continue serving */ +} + +static int connection_enable_event_sources(Connection *c) { + uint32_t a = 0, b = 0; + int r; + + assert(c); + + if (c->server_to_client_buffer_full > 0) + b |= EPOLLOUT; + if (c->server_to_client_buffer_full < c->server_to_client_buffer_size) + a |= EPOLLIN; + + if (c->client_to_server_buffer_full > 0) + a |= EPOLLOUT; + if (c->client_to_server_buffer_full < c->client_to_server_buffer_size) + b |= EPOLLIN; + + if (c->server_event_source) + r = sd_event_source_set_io_events(c->server_event_source, a); + else if (c->server_fd >= 0) + r = sd_event_add_io(c->context->event, &c->server_event_source, c->server_fd, a, traffic_cb, c); + else + r = 0; + + if (r < 0) + return log_error_errno(r, "Failed to set up server event source: %m"); + + if (c->client_event_source) + r = sd_event_source_set_io_events(c->client_event_source, b); + else if (c->client_fd >= 0) + r = sd_event_add_io(c->context->event, &c->client_event_source, c->client_fd, b, traffic_cb, c); + else + r = 0; + + if (r < 0) + return log_error_errno(r, "Failed to set up client event source: %m"); + + return 0; +} + +static int connection_complete(Connection *c) { + int r; + + assert(c); + + r = connection_create_pipes(c, c->server_to_client_buffer, &c->server_to_client_buffer_size); + if (r < 0) + goto fail; + + r = connection_create_pipes(c, c->client_to_server_buffer, &c->client_to_server_buffer_size); + if (r < 0) + goto fail; + + r = connection_enable_event_sources(c); + if (r < 0) + goto fail; + + return 0; + +fail: + connection_free(c); + return 0; /* ignore errors, continue serving */ +} + +static int connect_cb(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Connection *c = userdata; + socklen_t solen; + int error, r; + + assert(s); + assert(fd >= 0); + assert(c); + + solen = sizeof(error); + r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &solen); + if (r < 0) { + log_error_errno(errno, "Failed to issue SO_ERROR: %m"); + goto fail; + } + + if (error != 0) { + log_error_errno(error, "Failed to connect to remote host: %m"); + goto fail; + } + + c->client_event_source = sd_event_source_unref(c->client_event_source); + + return connection_complete(c); + +fail: + connection_free(c); + return 0; /* ignore errors, continue serving */ +} + +static int connection_start(Connection *c, struct sockaddr *sa, socklen_t salen) { + int r; + + assert(c); + assert(sa); + assert(salen); + + c->client_fd = socket(sa->sa_family, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); + if (c->client_fd < 0) { + log_error_errno(errno, "Failed to get remote socket: %m"); + goto fail; + } + + r = connect(c->client_fd, sa, salen); + if (r < 0) { + if (errno == EINPROGRESS) { + r = sd_event_add_io(c->context->event, &c->client_event_source, c->client_fd, EPOLLOUT, connect_cb, c); + if (r < 0) { + log_error_errno(r, "Failed to add connection socket: %m"); + goto fail; + } + + r = sd_event_source_set_enabled(c->client_event_source, SD_EVENT_ONESHOT); + if (r < 0) { + log_error_errno(r, "Failed to enable oneshot event source: %m"); + goto fail; + } + } else { + log_error_errno(errno, "Failed to connect to remote host: %m"); + goto fail; + } + } else { + r = connection_complete(c); + if (r < 0) + goto fail; + } + + return 0; + +fail: + connection_free(c); + return 0; /* ignore errors, continue serving */ +} + +static int resolve_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, Connection *c) { + assert(q); + assert(c); + + if (ret != 0) { + log_error("Failed to resolve host: %s", gai_strerror(ret)); + goto fail; + } + + c->resolve_query = sd_resolve_query_unref(c->resolve_query); + + return connection_start(c, ai->ai_addr, ai->ai_addrlen); + +fail: + connection_free(c); + return 0; /* ignore errors, continue serving */ +} + +static int resolve_remote(Connection *c) { + + static const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_ADDRCONFIG + }; + + union sockaddr_union sa = {}; + const char *node, *service; + int r; + + if (IN_SET(arg_remote_host[0], '/', '@')) { + int salen; + + salen = sockaddr_un_set_path(&sa.un, arg_remote_host); + if (salen < 0) { + log_error_errno(salen, "Specified address doesn't fit in an AF_UNIX address, refusing: %m"); + goto fail; + } + + return connection_start(c, &sa.sa, salen); + } + + service = strrchr(arg_remote_host, ':'); + if (service) { + node = strndupa(arg_remote_host, service - arg_remote_host); + service++; + } else { + node = arg_remote_host; + service = "80"; + } + + log_debug("Looking up address info for %s:%s", node, service); + r = resolve_getaddrinfo(c->context->resolve, &c->resolve_query, node, service, &hints, resolve_handler, NULL, c); + if (r < 0) { + log_error_errno(r, "Failed to resolve remote host: %m"); + goto fail; + } + + return 0; + +fail: + connection_free(c); + return 0; /* ignore errors, continue serving */ +} + +static int add_connection_socket(Context *context, int fd) { + Connection *c; + int r; + + assert(context); + assert(fd >= 0); + + if (set_size(context->connections) > arg_connections_max) { + log_warning("Hit connection limit, refusing connection."); + safe_close(fd); + return 0; + } + + r = set_ensure_allocated(&context->connections, NULL); + if (r < 0) { + log_oom(); + return 0; + } + + c = new0(Connection, 1); + if (!c) { + log_oom(); + return 0; + } + + c->context = context; + c->server_fd = fd; + c->client_fd = -1; + c->server_to_client_buffer[0] = c->server_to_client_buffer[1] = -1; + c->client_to_server_buffer[0] = c->client_to_server_buffer[1] = -1; + + r = set_put(context->connections, c); + if (r < 0) { + free(c); + log_oom(); + return 0; + } + + return resolve_remote(c); +} + +static int accept_cb(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_free_ char *peer = NULL; + Context *context = userdata; + int nfd = -1, r; + + assert(s); + assert(fd >= 0); + assert(revents & EPOLLIN); + assert(context); + + nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); + if (nfd < 0) { + if (!ERRNO_IS_ACCEPT_AGAIN(errno)) + log_warning_errno(errno, "Failed to accept() socket: %m"); + } else { + (void) getpeername_pretty(nfd, true, &peer); + log_debug("New connection from %s", strna(peer)); + + r = add_connection_socket(context, nfd); + if (r < 0) { + log_error_errno(r, "Failed to accept connection, ignoring: %m"); + safe_close(fd); + } + } + + r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT); + if (r < 0) { + log_error_errno(r, "Error while re-enabling listener with ONESHOT: %m"); + sd_event_exit(context->event, r); + return r; + } + + return 1; +} + +static int add_listen_socket(Context *context, int fd) { + sd_event_source *source; + int r; + + assert(context); + assert(fd >= 0); + + r = set_ensure_allocated(&context->listen, NULL); + if (r < 0) { + log_oom(); + return r; + } + + r = sd_is_socket(fd, 0, SOCK_STREAM, 1); + if (r < 0) + return log_error_errno(r, "Failed to determine socket type: %m"); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Passed in socket is not a stream socket."); + + r = fd_nonblock(fd, true); + if (r < 0) + return log_error_errno(r, "Failed to mark file descriptor non-blocking: %m"); + + r = sd_event_add_io(context->event, &source, fd, EPOLLIN, accept_cb, context); + if (r < 0) + return log_error_errno(r, "Failed to add event source: %m"); + + r = set_put(context->listen, source); + if (r < 0) { + log_error_errno(r, "Failed to add source to set: %m"); + sd_event_source_unref(source); + return r; + } + + /* Set the watcher to oneshot in case other processes are also + * watching to accept(). */ + r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT); + if (r < 0) + return log_error_errno(r, "Failed to enable oneshot mode: %m"); + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-socket-proxyd", "8", &link); + if (r < 0) + return log_oom(); + + printf("%1$s [HOST:PORT]\n" + "%1$s [SOCKET]\n\n" + "Bidirectionally proxy local sockets to another (possibly remote) socket.\n\n" + " -c --connections-max= Set the maximum number of connections to be accepted\n" + " -h --help Show this help\n" + " --version Show package version\n" + "\nSee the %2$s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_IGNORE_ENV + }; + + static const struct option options[] = { + { "connections-max", required_argument, NULL, 'c' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "c:h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case 'c': + r = safe_atou(optarg, &arg_connections_max); + if (r < 0) { + log_error("Failed to parse --connections-max= argument: %s", optarg); + return r; + } + + if (arg_connections_max < 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Connection limit is too low."); + + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind >= argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Not enough parameters."); + + if (argc != optind+1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many parameters."); + + arg_remote_host = argv[optind]; + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(context_clear) Context context = {}; + int r, n, fd; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = sd_event_default(&context.event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + r = sd_resolve_default(&context.resolve); + if (r < 0) + return log_error_errno(r, "Failed to allocate resolver: %m"); + + r = sd_resolve_attach_event(context.resolve, context.event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach resolver: %m"); + + sd_event_set_watchdog(context.event, true); + + r = sd_listen_fds(1); + if (r < 0) + return log_error_errno(r, "Failed to receive sockets from parent."); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Didn't get any sockets passed in."); + + n = r; + + for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) { + r = add_listen_socket(&context, fd); + if (r < 0) + return r; + } + + r = sd_event_loop(context.event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/stdio-bridge/stdio-bridge.c b/src/stdio-bridge/stdio-bridge.c new file mode 100644 index 00000000..52b9ce45 --- /dev/null +++ b/src/stdio-bridge/stdio-bridge.c @@ -0,0 +1,257 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "build.h" +#include "bus-internal.h" +#include "bus-util.h" +#include "errno-util.h" +#include "log.h" +#include "main-func.h" +#include "util.h" + +#define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket" + +static const char *arg_bus_path = DEFAULT_BUS_PATH; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; + +static int help(void) { + + printf("%s [OPTIONS...]\n\n" + "STDIO or socket-activatable proxy to a given DBus endpoint.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " -p --bus-path=PATH Path to the kernel bus (default: %s)\n" + " -M --machine=MACHINE Name of machine to connect to\n", + program_invocation_short_name, DEFAULT_BUS_PATH); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_MACHINE, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "bus-path", required_argument, NULL, 'p' }, + { "machine", required_argument, NULL, 'M' }, + {}, + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hp:M:", options, NULL)) >= 0) { + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case 'p': + arg_bus_path = optarg; + break; + + case 'M': + arg_bus_path = optarg; + arg_transport = BUS_TRANSPORT_MACHINE; + break; + + case '?': + return -EINVAL; + + default: + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown option code %c", c); + } + } + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *a = NULL, *b = NULL; + sd_id128_t server_id; + bool is_unix; + int r, in_fd, out_fd; + + log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = sd_listen_fds(0); + if (r == 0) { + in_fd = STDIN_FILENO; + out_fd = STDOUT_FILENO; + } else if (r == 1) { + in_fd = SD_LISTEN_FDS_START; + out_fd = SD_LISTEN_FDS_START; + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Illegal number of file descriptors passed."); + + is_unix = + sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 && + sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0; + + r = sd_bus_new(&a); + if (r < 0) + return log_error_errno(r, "Failed to allocate bus: %m"); + + if (arg_transport == BUS_TRANSPORT_MACHINE) + r = bus_set_address_system_machine(a, arg_bus_path); + else + r = sd_bus_set_address(a, arg_bus_path); + if (r < 0) + return log_error_errno(r, "Failed to set address to connect to: %m"); + + r = sd_bus_negotiate_fds(a, is_unix); + if (r < 0) + return log_error_errno(r, "Failed to set FD negotiation: %m"); + + r = sd_bus_start(a); + if (r < 0) + return log_error_errno(r, "Failed to start bus client: %m"); + + r = sd_bus_get_bus_id(a, &server_id); + if (r < 0) + return log_error_errno(r, "Failed to get server ID: %m"); + + r = sd_bus_new(&b); + if (r < 0) + return log_error_errno(r, "Failed to allocate bus: %m"); + + r = sd_bus_set_fd(b, in_fd, out_fd); + if (r < 0) + return log_error_errno(r, "Failed to set fds: %m"); + + r = sd_bus_set_server(b, 1, server_id); + if (r < 0) + return log_error_errno(r, "Failed to set server mode: %m"); + + r = sd_bus_negotiate_fds(b, is_unix); + if (r < 0) + return log_error_errno(r, "Failed to set FD negotiation: %m"); + + r = sd_bus_set_anonymous(b, true); + if (r < 0) + return log_error_errno(r, "Failed to set anonymous authentication: %m"); + + r = sd_bus_start(b); + if (r < 0) + return log_error_errno(r, "Failed to start bus client: %m"); + + for (;;) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int events_a, events_b, fd; + uint64_t timeout_a, timeout_b, t; + struct timespec _ts, *ts; + + r = sd_bus_process(a, &m); + if (r < 0) + return log_error_errno(r, "Failed to process bus a: %m"); + + if (m) { + r = sd_bus_send(b, m, NULL); + if (r < 0) + return log_error_errno(r, "Failed to send message: %m"); + } + + if (r > 0) + continue; + + r = sd_bus_process(b, &m); + if (r < 0) { + /* treat 'connection reset by peer' as clean exit condition */ + if (ERRNO_IS_DISCONNECT(r)) + return 0; + + return log_error_errno(r, "Failed to process bus: %m"); + } + + if (m) { + r = sd_bus_send(a, m, NULL); + if (r < 0) + return log_error_errno(r, "Failed to send message: %m"); + } + + if (r > 0) + continue; + + fd = sd_bus_get_fd(a); + if (fd < 0) + return log_error_errno(fd, "Failed to get fd: %m"); + + events_a = sd_bus_get_events(a); + if (events_a < 0) + return log_error_errno(events_a, "Failed to get events mask: %m"); + + r = sd_bus_get_timeout(a, &timeout_a); + if (r < 0) + return log_error_errno(r, "Failed to get timeout: %m"); + + events_b = sd_bus_get_events(b); + if (events_b < 0) + return log_error_errno(events_b, "Failed to get events mask: %m"); + + r = sd_bus_get_timeout(b, &timeout_b); + if (r < 0) + return log_error_errno(r, "Failed to get timeout: %m"); + + t = timeout_a; + if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a)) + t = timeout_b; + + if (t == (uint64_t) -1) + ts = NULL; + else { + usec_t nw; + + nw = now(CLOCK_MONOTONIC); + if (t > nw) + t -= nw; + else + t = 0; + + ts = timespec_store(&_ts, t); + } + + { + struct pollfd p[3] = { + {.fd = fd, .events = events_a }, + {.fd = STDIN_FILENO, .events = events_b & POLLIN }, + {.fd = STDOUT_FILENO, .events = events_b & POLLOUT }, + }; + + r = ppoll(p, ELEMENTSOF(p), ts, NULL); + } + if (r < 0) + return log_error_errno(errno, "ppoll() failed: %m"); + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/sulogin-shell/sulogin-shell.c b/src/sulogin-shell/sulogin-shell.c new file mode 100644 index 00000000..6d65efbb --- /dev/null +++ b/src/sulogin-shell/sulogin-shell.c @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2017 Felipe Sateler +***/ + +#include +#include + +#include "bus-util.h" +#include "bus-error.h" +#include "def.h" +#include "env-util.h" +#include "log.h" +#include "process-util.h" +#include "sd-bus.h" +#include "signal-util.h" + +static int reload_manager(sd_bus *bus) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + log_info("Reloading system manager configuration"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Reload"); + if (r < 0) + return bus_log_create_error(r); + + /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which + * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have + * their timeout, and for everything else there's the same time budget in place. */ + + r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r)); + + return 0; +} + +static int start_default_target(sd_bus *bus) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + log_info("Starting default target"); + + /* Start these units only if we can replace base.target with it */ + r = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + &error, + NULL, + "ss", "default.target", "isolate"); + + if (r < 0) + return log_error_errno(r, "Failed to start default target: %s", bus_error_message(&error, r)); + + return 0; +} + +static int fork_wait(const char* const cmdline[]) { + pid_t pid; + int r; + + r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + /* Child */ + execv(cmdline[0], (char**) cmdline); + log_error_errno(errno, "Failed to execute %s: %m", cmdline[0]); + _exit(EXIT_FAILURE); /* Operational error */ + } + + return wait_for_terminate_and_check(cmdline[0], pid, WAIT_LOG_ABNORMAL); +} + +static void print_mode(const char* mode) { + printf("You are in %s mode. After logging in, type \"journalctl -xb\" to view\n" + "system logs, \"systemctl reboot\" to reboot, \"systemctl default\" or \"exit\"\n" + "to boot into default mode.\n", mode); + fflush(stdout); +} + +int main(int argc, char *argv[]) { + const char* sulogin_cmdline[] = { + SULOGIN, + NULL, /* --force */ + NULL + }; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + log_setup_service(); + + print_mode(argc > 1 ? argv[1] : ""); + + if (getenv_bool("SYSTEMD_SULOGIN_FORCE") > 0) + /* allows passwordless logins if root account is locked. */ + sulogin_cmdline[1] = "--force"; + + (void) fork_wait(sulogin_cmdline); + + r = bus_connect_system_systemd(&bus); + if (r < 0) { + log_warning_errno(r, "Failed to get D-Bus connection: %m"); + r = 0; + } else { + (void) reload_manager(bus); + + r = start_default_target(bus); + } + + return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c new file mode 100644 index 00000000..80742b9e --- /dev/null +++ b/src/sysctl/sysctl.c @@ -0,0 +1,368 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "conf-files.h" +#include "def.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "hashmap.h" +#include "log.h" +#include "main-func.h" +#include "pager.h" +#include "path-util.h" +#include "pretty-print.h" +#include "string-util.h" +#include "strv.h" +#include "sysctl-util.h" + +static char **arg_prefixes = NULL; +static bool arg_cat_config = false; +static PagerFlags arg_pager_flags = 0; + +STATIC_DESTRUCTOR_REGISTER(arg_prefixes, strv_freep); + +typedef struct Option { + char *key; + char *value; + bool ignore_failure; +} Option; + +static Option *option_free(Option *o) { + if (!o) + return NULL; + + free(o->key); + free(o->value); + + return mfree(o); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Option*, option_free); +DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(option_hash_ops, char, string_hash_func, string_compare_func, Option, option_free); + +static Option *option_new( + const char *key, + const char *value, + bool ignore_failure) { + + _cleanup_(option_freep) Option *o = NULL; + + assert(key); + assert(value); + + o = new(Option, 1); + if (!o) + return NULL; + + *o = (Option) { + .key = strdup(key), + .value = strdup(value), + .ignore_failure = ignore_failure, + }; + + if (!o->key || !o->value) + return NULL; + + return TAKE_PTR(o); +} + +static int apply_all(OrderedHashmap *sysctl_options) { + Option *option; + Iterator i; + int r = 0; + + ORDERED_HASHMAP_FOREACH(option, sysctl_options, i) { + int k; + + k = sysctl_write(option->key, option->value); + if (k < 0) { + /* If the sysctl is not available in the kernel or we are running with reduced + * privileges and cannot write it, then log about the issue, and proceed without + * failing. (EROFS is treated as a permission problem here, since that's how + * container managers usually protected their sysctls.) In all other cases log an + * error and make the tool fail. */ + + if (option->ignore_failure || k == -EROFS || ERRNO_IS_PRIVILEGE(k)) + log_debug_errno(k, "Couldn't write '%s' to '%s', ignoring: %m", option->value, option->key); + else if (k == -ENOENT) + log_info_errno(k, "Couldn't write '%s' to '%s', ignoring: %m", option->value, option->key); + else { + log_error_errno(k, "Couldn't write '%s' to '%s': %m", option->value, option->key); + if (r == 0) + r = k; + } + } + } + + return r; +} + +static bool test_prefix(const char *p) { + char **i; + + if (strv_isempty(arg_prefixes)) + return true; + + STRV_FOREACH(i, arg_prefixes) { + const char *t; + + t = path_startswith(*i, "/proc/sys/"); + if (!t) + t = *i; + if (path_startswith(p, t)) + return true; + } + + return false; +} + +static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ignore_enoent) { + _cleanup_fclose_ FILE *f = NULL; + unsigned c = 0; + int r; + + assert(path); + + r = search_and_fopen(path, "re", NULL, (const char**) CONF_PATHS_STRV("sysctl.d"), &f); + if (r < 0) { + if (ignore_enoent && r == -ENOENT) + return 0; + + return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path); + } + + log_debug("Parsing %s", path); + for (;;) { + _cleanup_(option_freep) Option *new_option = NULL; + _cleanup_free_ char *l = NULL; + bool ignore_failure; + Option *existing; + char *p, *value; + int k; + + k = read_line(f, LONG_LINE_MAX, &l); + if (k == 0) + break; + if (k < 0) + return log_error_errno(k, "Failed to read file '%s', ignoring: %m", path); + + c++; + + p = strstrip(l); + + if (isempty(p)) + continue; + if (strchr(COMMENTS "\n", *p)) + continue; + + value = strchr(p, '='); + if (!value) { + log_syntax(NULL, LOG_WARNING, path, c, 0, "Line is not an assignment, ignoring: %s", p); + if (r == 0) + r = -EINVAL; + continue; + } + + *value = 0; + value++; + + p = strstrip(p); + ignore_failure = p[0] == '-'; + if (ignore_failure) + p++; + + p = sysctl_normalize(p); + value = strstrip(value); + + if (!test_prefix(p)) + continue; + + existing = ordered_hashmap_get(sysctl_options, p); + if (existing) { + if (streq(value, existing->value)) { + existing->ignore_failure = existing->ignore_failure || ignore_failure; + continue; + } + + log_debug("Overwriting earlier assignment of %s at '%s:%u'.", p, path, c); + option_free(ordered_hashmap_remove(sysctl_options, p)); + } + + new_option = option_new(p, value, ignore_failure); + if (!new_option) + return log_oom(); + + k = ordered_hashmap_put(sysctl_options, new_option->key, new_option); + if (k < 0) + return log_error_errno(k, "Failed to add sysctl variable %s to hashmap: %m", p); + + TAKE_PTR(new_option); + } + + return r; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-sysctl.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" + "Applies kernel sysctl settings.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --cat-config Show configuration files\n" + " --prefix=PATH Only apply rules with the specified prefix\n" + " --no-pager Do not pipe output into a pager\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_CAT_CONFIG, + ARG_PREFIX, + ARG_NO_PAGER, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, + { "prefix", required_argument, NULL, ARG_PREFIX }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_CAT_CONFIG: + arg_cat_config = true; + break; + + case ARG_PREFIX: { + char *p; + + /* We used to require people to specify absolute paths + * in /proc/sys in the past. This is kinda useless, but + * we need to keep compatibility. We now support any + * sysctl name available. */ + sysctl_normalize(optarg); + + if (path_startswith(optarg, "/proc/sys")) + p = strdup(optarg); + else + p = path_join("/proc/sys", optarg); + if (!p) + return log_oom(); + + if (strv_consume(&arg_prefixes, p) < 0) + return log_oom(); + + break; + } + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_cat_config && argc > optind) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Positional arguments are not allowed with --cat-config"); + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(ordered_hashmap_freep) OrderedHashmap *sysctl_options = NULL; + int r, k; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + log_setup_service(); + + umask(0022); + + sysctl_options = ordered_hashmap_new(&option_hash_ops); + if (!sysctl_options) + return log_oom(); + + if (argc > optind) { + int i; + + r = 0; + + for (i = optind; i < argc; i++) { + k = parse_file(sysctl_options, argv[i], false); + if (k < 0 && r == 0) + r = k; + } + } else { + _cleanup_strv_free_ char **files = NULL; + char **f; + + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char**) CONF_PATHS_STRV("sysctl.d")); + if (r < 0) + return log_error_errno(r, "Failed to enumerate sysctl.d files: %m"); + + if (arg_cat_config) { + (void) pager_open(arg_pager_flags); + + return cat_files(NULL, files, 0); + } + + STRV_FOREACH(f, files) { + k = parse_file(sysctl_options, *f, true); + if (k < 0 && r == 0) + r = k; + } + } + + k = apply_all(sysctl_options); + if (k < 0 && r == 0) + r = k; + + return r; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/system-update-generator/system-update-generator.c b/src/system-update-generator/system-update-generator.c new file mode 100644 index 00000000..666affca --- /dev/null +++ b/src/system-update-generator/system-update-generator.c @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "fs-util.h" +#include "generator.h" +#include "log.h" +#include "proc-cmdline.h" +#include "special.h" +#include "string-util.h" +#include "unit-file.h" +#include "util.h" + +/* + * Implements the logic described in systemd.offline-updates(7). + */ + +static const char *arg_dest = NULL; + +static int generate_symlink(void) { + const char *p = NULL; + + if (laccess("/system-update", F_OK) < 0) { + if (errno == ENOENT) + return 0; + + log_error_errno(errno, "Failed to check for system update: %m"); + return -EINVAL; + } + + p = strjoina(arg_dest, "/" SPECIAL_DEFAULT_TARGET); + if (symlink(SYSTEM_DATA_UNIT_PATH "/system-update.target", p) < 0) + return log_error_errno(errno, "Failed to create symlink %s: %m", p); + + return 1; +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + assert(key); + + /* Check if a run level is specified on the kernel command line. The + * command line has higher priority than any on-disk configuration, so + * it'll make any symlink we create moot. + */ + + if (streq(key, "systemd.unit") && !proc_cmdline_value_missing(key, value)) + log_warning("Offline system update overridden by kernel command line systemd.unit= setting"); + else if (!value && runlevel_to_target(key)) + log_warning("Offline system update overridden by runlevel \"%s\" on the kernel command line", key); + + return 0; +} + +static int run(const char *dest, const char *dest_early, const char *dest_late) { + int r; + + assert_se(arg_dest = dest_early); + + r = generate_symlink(); + if (r <= 0) + return r; + + /* We parse the command line only to emit warnings. */ + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + return 0; +} + +DEFINE_MAIN_GENERATOR_FUNCTION(run); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c new file mode 100644 index 00000000..3e4fc461 --- /dev/null +++ b/src/systemctl/systemctl.c @@ -0,0 +1,9510 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-daemon.h" +#include "sd-event.h" +#include "sd-login.h" + +#include "alloc-util.h" +#include "bootspec.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-message.h" +#include "bus-unit-procs.h" +#include "bus-unit-util.h" +#include "bus-util.h" +#include "bus-wait-for-jobs.h" +#include "bus-wait-for-units.h" +#include "cgroup-show.h" +#include "cgroup-util.h" +#include "copy.h" +#include "cpu-set-util.h" +#include "dirent-util.h" +#include "dropin.h" +#include "efi-loader.h" +#include "efivars.h" +#include "env-util.h" +#include "escape.h" +#include "exec-util.h" +#include "exit-status.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "glob-util.h" +#include "hexdecoct.h" +#include "hostname-util.h" +#include "in-addr-util.h" +#include "initreq.h" +#include "install.h" +#include "io-util.h" +#include "journal-util.h" +#include "list.h" +#include "locale-util.h" +#include "log.h" +#include "logs-show.h" +#include "macro.h" +#include "main-func.h" +#include "memory-util.h" +#include "mkdir.h" +#include "pager.h" +#include "parse-util.h" +#include "path-lookup.h" +#include "path-util.h" +#include "pretty-print.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "reboot-util.h" +#include "rlimit-util.h" +#include "set.h" +#include "sigbus.h" +#include "signal-util.h" +#include "socket-util.h" +#include "sort-util.h" +#include "spawn-ask-password-agent.h" +#include "spawn-polkit-agent.h" +#include "special.h" +#include "stat-util.h" +#include "string-table.h" +#include "strv.h" +#include "sysv-compat.h" +#include "terminal-util.h" +#include "tmpfile-util.h" +#include "unit-def.h" +#include "unit-file.h" +#include "unit-name.h" +#include "user-util.h" +#include "utf8.h" +#include "utmp-wtmp.h" +#include "verbs.h" +#include "virt.h" + +static char **arg_types = NULL; +static char **arg_states = NULL; +static char **arg_properties = NULL; +static bool arg_all = false; +static enum dependency { + DEPENDENCY_FORWARD, + DEPENDENCY_REVERSE, + DEPENDENCY_AFTER, + DEPENDENCY_BEFORE, + _DEPENDENCY_MAX +} arg_dependency = DEPENDENCY_FORWARD; +static const char *arg_job_mode = "replace"; +static UnitFileScope arg_scope = UNIT_FILE_SYSTEM; +static bool arg_wait = false; +static bool arg_no_block = false; +static bool arg_no_legend = false; +static PagerFlags arg_pager_flags = 0; +static bool arg_no_wtmp = false; +static bool arg_no_sync = false; +static bool arg_no_wall = false; +static bool arg_no_reload = false; +static bool arg_value = false; +static bool arg_show_types = false; +static bool arg_ignore_inhibitors = false; +static bool arg_dry_run = false; +static bool arg_quiet = false; +static bool arg_full = false; +static bool arg_recursive = false; +static bool arg_show_transaction = false; +static int arg_force = 0; +static bool arg_ask_password = false; +static bool arg_runtime = false; +static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL; +static char **arg_wall = NULL; +static const char *arg_kill_who = NULL; +static int arg_signal = SIGTERM; +static char *arg_root = NULL; +static usec_t arg_when = 0; +static enum action { + ACTION_SYSTEMCTL, + ACTION_HALT, + ACTION_POWEROFF, + ACTION_REBOOT, + ACTION_KEXEC, + ACTION_EXIT, + ACTION_SUSPEND, + ACTION_HIBERNATE, + ACTION_HYBRID_SLEEP, + ACTION_SUSPEND_THEN_HIBERNATE, + ACTION_RUNLEVEL2, + ACTION_RUNLEVEL3, + ACTION_RUNLEVEL4, + ACTION_RUNLEVEL5, + ACTION_RESCUE, + ACTION_EMERGENCY, + ACTION_DEFAULT, + ACTION_RELOAD, + ACTION_REEXEC, + ACTION_RUNLEVEL, + ACTION_CANCEL_SHUTDOWN, + _ACTION_MAX, + _ACTION_INVALID = -1 +} arg_action = ACTION_SYSTEMCTL; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static const char *arg_host = NULL; +static unsigned arg_lines = 10; +static OutputMode arg_output = OUTPUT_SHORT; +static bool arg_plain = false; +static bool arg_firmware_setup = false; +static usec_t arg_boot_loader_menu = USEC_INFINITY; +static const char *arg_boot_loader_entry = NULL; +static bool arg_now = false; +static bool arg_jobs_before = false; +static bool arg_jobs_after = false; +static char **arg_clean_what = NULL; + +/* This is a global cache that will be constructed on first use. */ +static Hashmap *cached_id_map = NULL; +static Hashmap *cached_name_map = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_root, freep); +STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep); +STATIC_DESTRUCTOR_REGISTER(cached_id_map, hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(cached_name_map, hashmap_freep); + +static int daemon_reload(int argc, char *argv[], void* userdata); +static int trivial_method(int argc, char *argv[], void *userdata); +static int halt_now(enum action a); +static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state); + +static bool original_stdout_is_tty; + +typedef enum BusFocus { + BUS_FULL, /* The full bus indicated via --system or --user */ + BUS_MANAGER, /* The manager itself, possibly directly, possibly via the bus */ + _BUS_FOCUS_MAX +} BusFocus; + +static sd_bus *buses[_BUS_FOCUS_MAX] = {}; + +static UnitFileFlags args_to_flags(void) { + return (arg_runtime ? UNIT_FILE_RUNTIME : 0) | + (arg_force ? UNIT_FILE_FORCE : 0); +} + +static int acquire_bus(BusFocus focus, sd_bus **ret) { + int r; + + assert(focus < _BUS_FOCUS_MAX); + assert(ret); + + /* We only go directly to the manager, if we are using a local transport */ + if (arg_transport != BUS_TRANSPORT_LOCAL) + focus = BUS_FULL; + + if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0) + focus = BUS_FULL; + + if (!buses[focus]) { + bool user; + + user = arg_scope != UNIT_FILE_SYSTEM; + + if (focus == BUS_MANAGER) + r = bus_connect_transport_systemd(arg_transport, arg_host, user, &buses[focus]); + else + r = bus_connect_transport(arg_transport, arg_host, user, &buses[focus]); + if (r < 0) + return log_error_errno(r, "Failed to connect to bus: %m"); + + (void) sd_bus_set_allow_interactive_authorization(buses[focus], arg_ask_password); + } + + *ret = buses[focus]; + return 0; +} + +static void release_busses(void) { + BusFocus w; + + for (w = 0; w < _BUS_FOCUS_MAX; w++) + buses[w] = sd_bus_flush_close_unref(buses[w]); +} + +static void ask_password_agent_open_maybe(void) { + /* Open the password agent as a child process if necessary */ + + if (arg_dry_run) + return; + + if (arg_scope != UNIT_FILE_SYSTEM) + return; + + ask_password_agent_open_if_enabled(arg_transport, arg_ask_password); +} + +static void polkit_agent_open_maybe(void) { + /* Open the polkit agent as a child process if necessary */ + + if (arg_scope != UNIT_FILE_SYSTEM) + return; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); +} + +static OutputFlags get_output_flags(void) { + return + arg_all * OUTPUT_SHOW_ALL | + (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH | + colors_enabled() * OUTPUT_COLOR | + !arg_quiet * OUTPUT_WARN_CUTOFF; +} + +static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) { + assert(error); + + if (!sd_bus_error_is_set(error)) + return r; + + if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) || + sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) || + sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) || + sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE)) + return EXIT_NOPERMISSION; + + if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT)) + return EXIT_NOTINSTALLED; + + if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) || + sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED)) + return EXIT_NOTIMPLEMENTED; + + if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) + return EXIT_NOTCONFIGURED; + + if (r != 0) + return r; + + return EXIT_FAILURE; +} + +static bool install_client_side(void) { + /* Decides when to execute enable/disable/... operations + * client-side rather than server-side. */ + + if (running_in_chroot_or_offline()) + return true; + + if (sd_booted() <= 0) + return true; + + if (!isempty(arg_root)) + return true; + + if (arg_scope == UNIT_FILE_GLOBAL) + return true; + + /* Unsupported environment variable, mostly for debugging purposes */ + if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0) + return true; + + return false; +} + +static int compare_unit_info(const UnitInfo *a, const UnitInfo *b) { + const char *d1, *d2; + int r; + + /* First, order by machine */ + if (!a->machine && b->machine) + return -1; + if (a->machine && !b->machine) + return 1; + if (a->machine && b->machine) { + r = strcasecmp(a->machine, b->machine); + if (r != 0) + return r; + } + + /* Second, order by unit type */ + d1 = strrchr(a->id, '.'); + d2 = strrchr(b->id, '.'); + if (d1 && d2) { + r = strcasecmp(d1, d2); + if (r != 0) + return r; + } + + /* Third, order by name */ + return strcasecmp(a->id, b->id); +} + +static const char* unit_type_suffix(const char *name) { + const char *dot; + + dot = strrchr(name, '.'); + if (!dot) + return ""; + + return dot + 1; +} + +static bool output_show_unit(const UnitInfo *u, char **patterns) { + assert(u); + + if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE)) + return false; + + if (arg_types && !strv_find(arg_types, unit_type_suffix(u->id))) + return false; + + if (arg_all) + return true; + + /* Note that '--all' is not purely a state filter, but also a + * filter that hides units that "follow" other units (which is + * used for device units that appear under different names). */ + if (!isempty(u->following)) + return false; + + if (!strv_isempty(arg_states)) + return true; + + /* By default show all units except the ones in inactive + * state and with no pending job */ + if (u->job_id > 0) + return true; + + if (streq(u->active_state, "inactive")) + return false; + + return true; +} + +static int output_units_list(const UnitInfo *unit_infos, unsigned c) { + unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len, max_desc_len; + const UnitInfo *u; + unsigned n_shown = 0; + int job_count = 0; + bool full = arg_full || FLAGS_SET(arg_pager_flags, PAGER_DISABLE); + + max_id_len = STRLEN("UNIT"); + load_len = STRLEN("LOAD"); + active_len = STRLEN("ACTIVE"); + sub_len = STRLEN("SUB"); + job_len = STRLEN("JOB"); + max_desc_len = STRLEN("DESCRIPTION"); + + for (u = unit_infos; u < unit_infos + c; u++) { + max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0)); + load_len = MAX(load_len, strlen(u->load_state)); + active_len = MAX(active_len, strlen(u->active_state)); + sub_len = MAX(sub_len, strlen(u->sub_state)); + max_desc_len = MAX(max_desc_len, strlen(u->description)); + + if (u->job_id != 0) { + job_len = MAX(job_len, strlen(u->job_type)); + job_count++; + } + + if (!arg_no_legend && + (streq(u->active_state, "failed") || + STR_IN_SET(u->load_state, "error", "not-found", "bad-setting", "masked"))) + circle_len = 2; + } + + if (!arg_full && original_stdout_is_tty) { + unsigned basic_len; + + id_len = MIN(max_id_len, 25u); /* as much as it needs, but at most 25 for now */ + basic_len = circle_len + 1 + id_len + 1 + load_len + 1 + active_len + 1 + sub_len + 1; + + if (job_count) + basic_len += job_len + 1; + + if (basic_len < (unsigned) columns()) { + unsigned extra_len, incr; + extra_len = columns() - basic_len; + + /* Either UNIT already got 25, or is fully satisfied. + * Grant up to 25 to DESC now. */ + incr = MIN(extra_len, 25u); + desc_len = incr; + extra_len -= incr; + + /* Of the remainder give as much as the ID needs to the ID, and give the rest to the + * description but not more than it needs. */ + if (extra_len > 0) { + incr = MIN(max_id_len - id_len, extra_len); + id_len += incr; + desc_len += MIN(extra_len - incr, max_desc_len - desc_len); + } + } else + desc_len = 0; + } else { + id_len = max_id_len; + desc_len = max_desc_len; + } + + for (u = unit_infos; u < unit_infos + c; u++) { + _cleanup_free_ char *e = NULL, *j = NULL; + const char *on_underline = "", *off_underline = ""; + const char *on_loaded = "", *off_loaded = ""; + const char *on_active = "", *off_active = ""; + const char *on_circle = "", *off_circle = ""; + const char *id; + bool circle = false, underline = false; + + if (!n_shown && !arg_no_legend) { + + if (circle_len > 0) + fputs(" ", stdout); + + printf("%s%-*s %-*s %-*s %-*s ", + ansi_underline(), + id_len, "UNIT", + load_len, "LOAD", + active_len, "ACTIVE", + sub_len, "SUB"); + + if (job_count) + printf("%-*s ", job_len, "JOB"); + + printf("%-*.*s%s\n", + desc_len, + full ? -1 : (int) desc_len, + "DESCRIPTION", + ansi_normal()); + } + + n_shown++; + + if (u + 1 < unit_infos + c && + !streq(unit_type_suffix(u->id), unit_type_suffix((u + 1)->id))) { + on_underline = ansi_underline(); + off_underline = ansi_normal(); + underline = true; + } + + if (STR_IN_SET(u->load_state, "error", "not-found", "bad-setting", "masked") && !arg_plain) { + on_circle = ansi_highlight_yellow(); + off_circle = ansi_normal(); + circle = true; + on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); + off_loaded = underline ? on_underline : ansi_normal(); + } else if (streq(u->active_state, "failed") && !arg_plain) { + on_circle = ansi_highlight_red(); + off_circle = ansi_normal(); + circle = true; + on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); + off_active = underline ? on_underline : ansi_normal(); + } + + if (u->machine) { + j = strjoin(u->machine, ":", u->id); + if (!j) + return log_oom(); + + id = j; + } else + id = u->id; + + if (arg_full) { + e = ellipsize(id, id_len, 33); + if (!e) + return log_oom(); + + id = e; + } + + if (circle_len > 0) + printf("%s%s%s ", on_circle, circle ? special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE) : " ", off_circle); + + printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s", + on_underline, + on_active, id_len, id, off_active, + on_loaded, load_len, u->load_state, off_loaded, + on_active, active_len, u->active_state, + sub_len, u->sub_state, off_active, + job_count ? job_len + 1 : 0, u->job_id ? u->job_type : ""); + + printf("%-*.*s%s\n", + desc_len, + full ? -1 : (int) desc_len, + u->description, + off_underline); + } + + if (!arg_no_legend) { + const char *on, *off; + + if (n_shown) { + puts("\n" + "LOAD = Reflects whether the unit definition was properly loaded.\n" + "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n" + "SUB = The low-level unit activation state, values depend on unit type."); + puts(job_count ? "JOB = Pending job for the unit.\n" : ""); + on = ansi_highlight(); + off = ansi_normal(); + } else { + on = ansi_highlight_red(); + off = ansi_normal(); + } + + if (arg_all || strv_contains(arg_states, "inactive")) + printf("%s%u loaded units listed.%s\n" + "To show all installed unit files use 'systemctl list-unit-files'.\n", + on, n_shown, off); + else if (!arg_states) + printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n" + "To show all installed unit files use 'systemctl list-unit-files'.\n", + on, n_shown, off); + else + printf("%u loaded units listed.\n", n_shown); + } + + return 0; +} + +static int get_unit_list( + sd_bus *bus, + const char *machine, + char **patterns, + UnitInfo **unit_infos, + int c, + sd_bus_message **_reply) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + size_t size = c; + int r; + UnitInfo u; + bool fallback = false; + + assert(bus); + assert(unit_infos); + assert(_reply); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListUnitsByPatterns"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, arg_states); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, patterns); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0 && (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD) || + sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED))) { + /* Fallback to legacy ListUnitsFiltered method */ + fallback = true; + log_debug_errno(r, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error, r)); + m = sd_bus_message_unref(m); + sd_bus_error_free(&error); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListUnitsFiltered"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, arg_states); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + } + if (r < 0) + return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = bus_parse_unit_info(reply, &u)) > 0) { + u.machine = machine; + + if (!output_show_unit(&u, fallback ? patterns : NULL)) + continue; + + if (!GREEDY_REALLOC(*unit_infos, size, c+1)) + return log_oom(); + + (*unit_infos)[c++] = u; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + *_reply = TAKE_PTR(reply); + + return c; +} + +static void message_set_freep(Set **set) { + set_free_with_destructor(*set, sd_bus_message_unref); +} + +static int get_unit_list_recursive( + sd_bus *bus, + char **patterns, + UnitInfo **_unit_infos, + Set **_replies, + char ***_machines) { + + _cleanup_free_ UnitInfo *unit_infos = NULL; + _cleanup_(message_set_freep) Set *replies; + sd_bus_message *reply; + int c, r; + + assert(bus); + assert(_replies); + assert(_unit_infos); + assert(_machines); + + replies = set_new(NULL); + if (!replies) + return log_oom(); + + c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply); + if (c < 0) + return c; + + r = set_put(replies, reply); + if (r < 0) { + sd_bus_message_unref(reply); + return log_oom(); + } + + if (arg_recursive) { + _cleanup_strv_free_ char **machines = NULL; + char **i; + + r = sd_get_machine_names(&machines); + if (r < 0) + return log_error_errno(r, "Failed to get machine names: %m"); + + STRV_FOREACH(i, machines) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL; + int k; + + r = sd_bus_open_system_machine(&container, *i); + if (r < 0) { + log_warning_errno(r, "Failed to connect to container %s, ignoring: %m", *i); + continue; + } + + k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply); + if (k < 0) + return k; + + c = k; + + r = set_put(replies, reply); + if (r < 0) { + sd_bus_message_unref(reply); + return log_oom(); + } + } + + *_machines = TAKE_PTR(machines); + } else + *_machines = NULL; + + *_unit_infos = TAKE_PTR(unit_infos); + *_replies = TAKE_PTR(replies); + + return c; +} + +static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret, bool *ret_expanded) { + _cleanup_strv_free_ char **mangled = NULL, **globs = NULL; + char **name; + int r, i; + + assert(bus); + assert(ret); + + STRV_FOREACH(name, names) { + char *t; + UnitNameMangle options = UNIT_NAME_MANGLE_GLOB | (arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN); + + r = unit_name_mangle_with_suffix(*name, NULL, options, suffix ?: ".service", &t); + if (r < 0) + return log_error_errno(r, "Failed to mangle name: %m"); + + if (string_is_glob(t)) + r = strv_consume(&globs, t); + else + r = strv_consume(&mangled, t); + if (r < 0) + return log_oom(); + } + + /* Query the manager only if any of the names are a glob, since + * this is fairly expensive */ + bool expanded = !strv_isempty(globs); + if (expanded) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ UnitInfo *unit_infos = NULL; + size_t allocated, n; + + r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply); + if (r < 0) + return r; + + n = strv_length(mangled); + allocated = n + 1; + + for (i = 0; i < r; i++) { + if (!GREEDY_REALLOC(mangled, allocated, n+2)) + return log_oom(); + + mangled[n] = strdup(unit_infos[i].id); + if (!mangled[n]) + return log_oom(); + + mangled[++n] = NULL; + } + } + + if (ret_expanded) + *ret_expanded = expanded; + + *ret = TAKE_PTR(mangled); + return 0; +} + +static int list_units(int argc, char *argv[], void *userdata) { + _cleanup_free_ UnitInfo *unit_infos = NULL; + _cleanup_(message_set_freep) Set *replies = NULL; + _cleanup_strv_free_ char **machines = NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + (void) pager_open(arg_pager_flags); + + r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); + if (r < 0) + return r; + + typesafe_qsort(unit_infos, r, compare_unit_info); + return output_units_list(unit_infos, r); +} + +static int get_triggered_units( + sd_bus *bus, + const char* path, + char*** ret) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + assert(path); + assert(ret); + + r = sd_bus_get_property_strv( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + "Triggers", + &error, + ret); + if (r < 0) + return log_error_errno(r, "Failed to determine triggers: %s", bus_error_message(&error, r)); + + return 0; +} + +static int get_listening( + sd_bus *bus, + const char* unit_path, + char*** listening) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *type, *path; + int r, n = 0; + + r = sd_bus_get_property( + bus, + "org.freedesktop.systemd1", + unit_path, + "org.freedesktop.systemd1.Socket", + "Listen", + &error, + &reply, + "a(ss)"); + if (r < 0) + return log_error_errno(r, "Failed to get list of listening sockets: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) { + + r = strv_extend(listening, type); + if (r < 0) + return log_oom(); + + r = strv_extend(listening, path); + if (r < 0) + return log_oom(); + + n++; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return n; +} + +struct socket_info { + const char *machine; + const char* id; + + char* type; + char* path; + + /* Note: triggered is a list here, although it almost certainly + * will always be one unit. Nevertheless, dbus API allows for multiple + * values, so let's follow that. */ + char** triggered; + + /* The strv above is shared. free is set only in the first one. */ + bool own_triggered; +}; + +static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) { + int r; + + assert(a); + assert(b); + + if (!a->machine && b->machine) + return -1; + if (a->machine && !b->machine) + return 1; + if (a->machine && b->machine) { + r = strcasecmp(a->machine, b->machine); + if (r != 0) + return r; + } + + r = strcmp(a->path, b->path); + if (r == 0) + r = strcmp(a->type, b->type); + + return r; +} + +static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) { + struct socket_info *s; + unsigned pathlen = STRLEN("LISTEN"), + typelen = STRLEN("TYPE") * arg_show_types, + socklen = STRLEN("UNIT"), + servlen = STRLEN("ACTIVATES"); + const char *on, *off; + + for (s = socket_infos; s < socket_infos + cs; s++) { + unsigned tmp = 0; + char **a; + + socklen = MAX(socklen, strlen(s->id)); + if (arg_show_types) + typelen = MAX(typelen, strlen(s->type)); + pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0)); + + STRV_FOREACH(a, s->triggered) + tmp += strlen(*a) + 2*(a != s->triggered); + servlen = MAX(servlen, tmp); + } + + if (cs) { + if (!arg_no_legend) + printf("%-*s %-*.*s%-*s %s\n", + pathlen, "LISTEN", + typelen + arg_show_types, typelen + arg_show_types, "TYPE ", + socklen, "UNIT", + "ACTIVATES"); + + for (s = socket_infos; s < socket_infos + cs; s++) { + _cleanup_free_ char *j = NULL; + const char *path; + char **a; + + if (s->machine) { + j = strjoin(s->machine, ":", s->path); + if (!j) + return log_oom(); + path = j; + } else + path = s->path; + + if (arg_show_types) + printf("%-*s %-*s %-*s", + pathlen, path, typelen, s->type, socklen, s->id); + else + printf("%-*s %-*s", + pathlen, path, socklen, s->id); + STRV_FOREACH(a, s->triggered) + printf("%s %s", + a == s->triggered ? "" : ",", *a); + printf("\n"); + } + + on = ansi_highlight(); + off = ansi_normal(); + if (!arg_no_legend) + printf("\n"); + } else { + on = ansi_highlight_red(); + off = ansi_normal(); + } + + if (!arg_no_legend) { + printf("%s%u sockets listed.%s\n", on, cs, off); + if (!arg_all) + printf("Pass --all to see loaded but inactive sockets, too.\n"); + } + + return 0; +} + +static int list_sockets(int argc, char *argv[], void *userdata) { + _cleanup_(message_set_freep) Set *replies = NULL; + _cleanup_strv_free_ char **machines = NULL; + _cleanup_strv_free_ char **sockets_with_suffix = NULL; + _cleanup_free_ UnitInfo *unit_infos = NULL; + _cleanup_free_ struct socket_info *socket_infos = NULL; + const UnitInfo *u; + struct socket_info *s; + unsigned cs = 0; + size_t size = 0; + int r = 0, n; + sd_bus *bus; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + (void) pager_open(arg_pager_flags); + + r = expand_names(bus, strv_skip(argv, 1), ".socket", &sockets_with_suffix, NULL); + if (r < 0) + return r; + + if (argc == 1 || sockets_with_suffix) { + n = get_unit_list_recursive(bus, sockets_with_suffix, &unit_infos, &replies, &machines); + if (n < 0) + return n; + + for (u = unit_infos; u < unit_infos + n; u++) { + _cleanup_strv_free_ char **listening = NULL, **triggered = NULL; + int i, c; + + if (!endswith(u->id, ".socket")) + continue; + + r = get_triggered_units(bus, u->unit_path, &triggered); + if (r < 0) + goto cleanup; + + c = get_listening(bus, u->unit_path, &listening); + if (c < 0) { + r = c; + goto cleanup; + } + + if (!GREEDY_REALLOC(socket_infos, size, cs + c)) { + r = log_oom(); + goto cleanup; + } + + for (i = 0; i < c; i++) + socket_infos[cs + i] = (struct socket_info) { + .machine = u->machine, + .id = u->id, + .type = listening[i*2], + .path = listening[i*2 + 1], + .triggered = triggered, + .own_triggered = i==0, + }; + + /* from this point on we will cleanup those socket_infos */ + cs += c; + free(listening); + listening = triggered = NULL; /* avoid cleanup */ + } + + typesafe_qsort(socket_infos, cs, socket_info_compare); + } + + output_sockets_list(socket_infos, cs); + + cleanup: + assert(cs == 0 || socket_infos); + for (s = socket_infos; s < socket_infos + cs; s++) { + free(s->type); + free(s->path); + if (s->own_triggered) + strv_free(s->triggered); + } + + return r; +} + +static int get_next_elapse( + sd_bus *bus, + const char *path, + dual_timestamp *next) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + dual_timestamp t; + int r; + + assert(bus); + assert(path); + assert(next); + + r = sd_bus_get_property_trivial( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Timer", + "NextElapseUSecMonotonic", + &error, + 't', + &t.monotonic); + if (r < 0) + return log_error_errno(r, "Failed to get next elapse time: %s", bus_error_message(&error, r)); + + r = sd_bus_get_property_trivial( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Timer", + "NextElapseUSecRealtime", + &error, + 't', + &t.realtime); + if (r < 0) + return log_error_errno(r, "Failed to get next elapse time: %s", bus_error_message(&error, r)); + + *next = t; + return 0; +} + +static int get_last_trigger( + sd_bus *bus, + const char *path, + usec_t *last) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + assert(path); + assert(last); + + r = sd_bus_get_property_trivial( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Timer", + "LastTriggerUSec", + &error, + 't', + last); + if (r < 0) + return log_error_errno(r, "Failed to get last trigger time: %s", bus_error_message(&error, r)); + + return 0; +} + +struct timer_info { + const char* machine; + const char* id; + usec_t next_elapse; + usec_t last_trigger; + char** triggered; +}; + +static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) { + int r; + + assert(a); + assert(b); + + if (!a->machine && b->machine) + return -1; + if (a->machine && !b->machine) + return 1; + if (a->machine && b->machine) { + r = strcasecmp(a->machine, b->machine); + if (r != 0) + return r; + } + + r = CMP(a->next_elapse, b->next_elapse); + if (r != 0) + return r; + + return strcmp(a->id, b->id); +} + +static int output_timers_list(struct timer_info *timer_infos, unsigned n) { + struct timer_info *t; + unsigned + nextlen = STRLEN("NEXT"), + leftlen = STRLEN("LEFT"), + lastlen = STRLEN("LAST"), + passedlen = STRLEN("PASSED"), + unitlen = STRLEN("UNIT"), + activatelen = STRLEN("ACTIVATES"); + + const char *on, *off; + + assert(timer_infos || n == 0); + + for (t = timer_infos; t < timer_infos + n; t++) { + unsigned ul = 0; + char **a; + + if (t->next_elapse > 0) { + char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = ""; + + format_timestamp(tstamp, sizeof(tstamp), t->next_elapse); + nextlen = MAX(nextlen, strlen(tstamp) + 1); + + format_timestamp_relative(trel, sizeof(trel), t->next_elapse); + leftlen = MAX(leftlen, strlen(trel)); + } + + if (t->last_trigger > 0) { + char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = ""; + + format_timestamp(tstamp, sizeof(tstamp), t->last_trigger); + lastlen = MAX(lastlen, strlen(tstamp) + 1); + + format_timestamp_relative(trel, sizeof(trel), t->last_trigger); + passedlen = MAX(passedlen, strlen(trel)); + } + + unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0)); + + STRV_FOREACH(a, t->triggered) + ul += strlen(*a) + 2*(a != t->triggered); + + activatelen = MAX(activatelen, ul); + } + + if (n > 0) { + if (!arg_no_legend) + printf("%-*s %-*s %-*s %-*s %-*s %s\n", + nextlen, "NEXT", + leftlen, "LEFT", + lastlen, "LAST", + passedlen, "PASSED", + unitlen, "UNIT", + "ACTIVATES"); + + for (t = timer_infos; t < timer_infos + n; t++) { + _cleanup_free_ char *j = NULL; + const char *unit; + char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a"; + char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a"; + char **a; + + format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse); + format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse); + + format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger); + format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger); + + if (t->machine) { + j = strjoin(t->machine, ":", t->id); + if (!j) + return log_oom(); + unit = j; + } else + unit = t->id; + + printf("%-*s %-*s %-*s %-*s %-*s", + nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit); + + STRV_FOREACH(a, t->triggered) + printf("%s %s", + a == t->triggered ? "" : ",", *a); + printf("\n"); + } + + on = ansi_highlight(); + off = ansi_normal(); + if (!arg_no_legend) + printf("\n"); + } else { + on = ansi_highlight_red(); + off = ansi_normal(); + } + + if (!arg_no_legend) { + printf("%s%u timers listed.%s\n", on, n, off); + if (!arg_all) + printf("Pass --all to see loaded but inactive timers, too.\n"); + } + + return 0; +} + +static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) { + usec_t next_elapse; + + assert(nw); + assert(next); + + if (timestamp_is_set(next->monotonic)) { + usec_t converted; + + if (next->monotonic > nw->monotonic) + converted = nw->realtime + (next->monotonic - nw->monotonic); + else + converted = nw->realtime - (nw->monotonic - next->monotonic); + + if (timestamp_is_set(next->realtime)) + next_elapse = MIN(converted, next->realtime); + else + next_elapse = converted; + + } else + next_elapse = next->realtime; + + return next_elapse; +} + +static int list_timers(int argc, char *argv[], void *userdata) { + _cleanup_(message_set_freep) Set *replies = NULL; + _cleanup_strv_free_ char **machines = NULL; + _cleanup_strv_free_ char **timers_with_suffix = NULL; + _cleanup_free_ struct timer_info *timer_infos = NULL; + _cleanup_free_ UnitInfo *unit_infos = NULL; + struct timer_info *t; + const UnitInfo *u; + size_t size = 0; + int n, c = 0; + dual_timestamp nw; + sd_bus *bus; + int r = 0; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + (void) pager_open(arg_pager_flags); + + r = expand_names(bus, strv_skip(argv, 1), ".timer", &timers_with_suffix, NULL); + if (r < 0) + return r; + + if (argc == 1 || timers_with_suffix) { + n = get_unit_list_recursive(bus, timers_with_suffix, &unit_infos, &replies, &machines); + if (n < 0) + return n; + + dual_timestamp_get(&nw); + + for (u = unit_infos; u < unit_infos + n; u++) { + _cleanup_strv_free_ char **triggered = NULL; + dual_timestamp next = DUAL_TIMESTAMP_NULL; + usec_t m, last = 0; + + if (!endswith(u->id, ".timer")) + continue; + + r = get_triggered_units(bus, u->unit_path, &triggered); + if (r < 0) + goto cleanup; + + r = get_next_elapse(bus, u->unit_path, &next); + if (r < 0) + goto cleanup; + + get_last_trigger(bus, u->unit_path, &last); + + if (!GREEDY_REALLOC(timer_infos, size, c+1)) { + r = log_oom(); + goto cleanup; + } + + m = calc_next_elapse(&nw, &next); + + timer_infos[c++] = (struct timer_info) { + .machine = u->machine, + .id = u->id, + .next_elapse = m, + .last_trigger = last, + .triggered = TAKE_PTR(triggered), + }; + } + + typesafe_qsort(timer_infos, c, timer_info_compare); + } + + output_timers_list(timer_infos, c); + + cleanup: + for (t = timer_infos; t < timer_infos + c; t++) + strv_free(t->triggered); + + return r; +} + +static int compare_unit_file_list(const UnitFileList *a, const UnitFileList *b) { + const char *d1, *d2; + + d1 = strrchr(a->path, '.'); + d2 = strrchr(b->path, '.'); + + if (d1 && d2) { + int r; + + r = strcasecmp(d1, d2); + if (r != 0) + return r; + } + + return strcasecmp(basename(a->path), basename(b->path)); +} + +static bool output_show_unit_file(const UnitFileList *u, char **states, char **patterns) { + assert(u); + + if (!strv_fnmatch_or_empty(patterns, basename(u->path), FNM_NOESCAPE)) + return false; + + if (!strv_isempty(arg_types)) { + const char *dot; + + dot = strrchr(u->path, '.'); + if (!dot) + return false; + + if (!strv_find(arg_types, dot+1)) + return false; + } + + if (!strv_isempty(states) && + !strv_find(states, unit_file_state_to_string(u->state))) + return false; + + return true; +} + +static void output_unit_file_list(const UnitFileList *units, unsigned c) { + unsigned max_id_len, id_cols, state_cols; + const UnitFileList *u; + + max_id_len = STRLEN("UNIT FILE"); + state_cols = STRLEN("STATE"); + + for (u = units; u < units + c; u++) { + max_id_len = MAX(max_id_len, strlen(basename(u->path))); + state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state))); + } + + if (!arg_full) { + unsigned basic_cols; + + id_cols = MIN(max_id_len, 25u); + basic_cols = 1 + id_cols + state_cols; + if (basic_cols < (unsigned) columns()) + id_cols += MIN(columns() - basic_cols, max_id_len - id_cols); + } else + id_cols = max_id_len; + + if (!arg_no_legend && c > 0) + printf("%s%-*s %-*s%s\n", + ansi_underline(), + id_cols, "UNIT FILE", + state_cols, "STATE", + ansi_normal()); + + for (u = units; u < units + c; u++) { + const char *on_underline = NULL, *on_color = NULL, *off = NULL, *id; + _cleanup_free_ char *e = NULL; + bool underline; + + underline = u + 1 < units + c && + !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path)); + + if (underline) + on_underline = ansi_underline(); + + if (IN_SET(u->state, + UNIT_FILE_MASKED, + UNIT_FILE_MASKED_RUNTIME, + UNIT_FILE_DISABLED, + UNIT_FILE_BAD)) + on_color = underline ? ansi_highlight_red_underline() : ansi_highlight_red(); + else if (u->state == UNIT_FILE_ENABLED) + on_color = underline ? ansi_highlight_green_underline() : ansi_highlight_green(); + + if (on_underline || on_color) + off = ansi_normal(); + + id = basename(u->path); + + e = arg_full ? NULL : ellipsize(id, id_cols, 33); + + printf("%s%-*s %s%-*s%s\n", + strempty(on_underline), + id_cols, e ? e : id, + strempty(on_color), state_cols, unit_file_state_to_string(u->state), strempty(off)); + } + + if (!arg_no_legend) + printf("\n%u unit files listed.\n", c); +} + +static int list_unit_files(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ UnitFileList *units = NULL; + UnitFileList *unit; + size_t size = 0; + unsigned c = 0; + const char *state; + char *path; + int r; + bool fallback = false; + + if (install_client_side()) { + Hashmap *h; + UnitFileList *u; + Iterator i; + unsigned n_units; + + h = hashmap_new(&string_hash_ops); + if (!h) + return log_oom(); + + r = unit_file_get_list(arg_scope, arg_root, h, arg_states, strv_skip(argv, 1)); + if (r < 0) { + unit_file_list_free(h); + return log_error_errno(r, "Failed to get unit file list: %m"); + } + + n_units = hashmap_size(h); + + units = new(UnitFileList, n_units ?: 1); /* avoid malloc(0) */ + if (!units) { + unit_file_list_free(h); + return log_oom(); + } + + HASHMAP_FOREACH(u, h, i) { + if (!output_show_unit_file(u, NULL, NULL)) + continue; + + units[c++] = *u; + free(u); + } + + assert(c <= n_units); + hashmap_free(h); + + r = 0; + } else { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListUnitFilesByPatterns"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, arg_states); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) { + /* Fallback to legacy ListUnitFiles method */ + fallback = true; + log_debug_errno(r, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error, r)); + m = sd_bus_message_unref(m); + sd_bus_error_free(&error); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListUnitFiles"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + } + if (r < 0) + return log_error_errno(r, "Failed to list unit files: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) { + + if (!GREEDY_REALLOC(units, size, c + 1)) + return log_oom(); + + units[c] = (struct UnitFileList) { + path, + unit_file_state_from_string(state) + }; + + if (output_show_unit_file(&units[c], + fallback ? arg_states : NULL, + fallback ? strv_skip(argv, 1) : NULL)) + c++; + + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + } + + (void) pager_open(arg_pager_flags); + + typesafe_qsort(units, c, compare_unit_file_list); + output_unit_file_list(units, c); + + if (install_client_side()) + for (unit = units; unit < units + c; unit++) + free(unit->path); + + return 0; +} + +static int list_dependencies_print(const char *name, int level, unsigned branches, bool last) { + _cleanup_free_ char *n = NULL; + size_t max_len = MAX(columns(),20u); + size_t len = 0; + int i; + + if (!arg_plain) { + + for (i = level - 1; i >= 0; i--) { + len += 2; + if (len > max_len - 3 && !arg_full) { + printf("%s...\n",max_len % 2 ? "" : " "); + return 0; + } + printf("%s", special_glyph(branches & (1 << i) ? SPECIAL_GLYPH_TREE_VERTICAL : SPECIAL_GLYPH_TREE_SPACE)); + } + len += 2; + + if (len > max_len - 3 && !arg_full) { + printf("%s...\n",max_len % 2 ? "" : " "); + return 0; + } + + printf("%s", special_glyph(last ? SPECIAL_GLYPH_TREE_RIGHT : SPECIAL_GLYPH_TREE_BRANCH)); + } + + if (arg_full) { + printf("%s\n", name); + return 0; + } + + n = ellipsize(name, max_len-len, 100); + if (!n) + return log_oom(); + + printf("%s\n", n); + return 0; +} + +static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) { + struct DependencyStatusInfo { + char **dep[5]; + } info = {}; + + static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = { + [DEPENDENCY_FORWARD] = { + { "Requires", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, + { "Requisite", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) }, + { "Wants", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) }, + { "ConsistsOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) }, + { "BindsTo", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) }, + {} + }, + [DEPENDENCY_REVERSE] = { + { "RequiredBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, + { "RequisiteOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) }, + { "WantedBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) }, + { "PartOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) }, + { "BoundBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) }, + {} + }, + [DEPENDENCY_AFTER] = { + { "After", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, + {} + }, + [DEPENDENCY_BEFORE] = { + { "Before", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, + {} + }, + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_strv_free_ char **ret = NULL; + _cleanup_free_ char *dbus_path = NULL; + int i, r; + + assert(bus); + assert(name); + assert(deps); + + dbus_path = unit_dbus_path_from_name(name); + if (!dbus_path) + return log_oom(); + + r = bus_map_all_properties(bus, + "org.freedesktop.systemd1", + dbus_path, + map[arg_dependency], + BUS_MAP_STRDUP, + &error, + NULL, + &info); + if (r < 0) + return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r)); + + if (IN_SET(arg_dependency, DEPENDENCY_AFTER, DEPENDENCY_BEFORE)) { + *deps = info.dep[0]; + return 0; + } + + for (i = 0; i < 5; i++) { + r = strv_extend_strv(&ret, info.dep[i], true); + if (r < 0) + return log_oom(); + info.dep[i] = strv_free(info.dep[i]); + } + + *deps = TAKE_PTR(ret); + + return 0; +} + +static int list_dependencies_compare(char * const *a, char * const *b) { + if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET) + return 1; + if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET) + return -1; + + return strcasecmp(*a, *b); +} + +static int list_dependencies_one( + sd_bus *bus, + const char *name, + int level, + char ***units, + unsigned branches) { + + _cleanup_strv_free_ char **deps = NULL; + char **c; + int r = 0; + + assert(bus); + assert(name); + assert(units); + + r = strv_extend(units, name); + if (r < 0) + return log_oom(); + + r = list_dependencies_get_dependencies(bus, name, &deps); + if (r < 0) + return r; + + typesafe_qsort(deps, strv_length(deps), list_dependencies_compare); + + STRV_FOREACH(c, deps) { + if (strv_contains(*units, *c)) { + if (!arg_plain) { + printf(" "); + r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1); + if (r < 0) + return r; + } + continue; + } + + if (arg_plain) + printf(" "); + else { + UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID; + const char *on; + + (void) get_state_one_unit(bus, *c, &active_state); + + switch (active_state) { + case UNIT_ACTIVE: + case UNIT_RELOADING: + case UNIT_ACTIVATING: + on = ansi_highlight_green(); + break; + + case UNIT_INACTIVE: + case UNIT_DEACTIVATING: + on = ansi_normal(); + break; + + default: + on = ansi_highlight_red(); + break; + } + + printf("%s%s%s ", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), ansi_normal()); + } + + r = list_dependencies_print(*c, level, branches, c[1] == NULL); + if (r < 0) + return r; + + if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) { + r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1)); + if (r < 0) + return r; + } + } + + if (!arg_plain) + strv_remove(*units, name); + + return 0; +} + +static int list_dependencies(int argc, char *argv[], void *userdata) { + _cleanup_strv_free_ char **units = NULL; + _cleanup_free_ char *unit = NULL; + const char *u; + sd_bus *bus; + int r; + + if (argv[1]) { + r = unit_name_mangle(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, &unit); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); + + u = unit; + } else + u = SPECIAL_DEFAULT_TARGET; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + (void) pager_open(arg_pager_flags); + + puts(u); + + return list_dependencies_one(bus, u, 0, &units, 0); +} + +struct machine_info { + bool is_host; + char *name; + char *state; + char *control_group; + uint32_t n_failed_units; + uint32_t n_jobs; + usec_t timestamp; +}; + +static const struct bus_properties_map machine_info_property_map[] = { + { "SystemState", "s", NULL, offsetof(struct machine_info, state) }, + { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) }, + { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) }, + { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) }, + { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) }, + {} +}; + +static void machine_info_clear(struct machine_info *info) { + assert(info); + + free(info->name); + free(info->state); + free(info->control_group); + zero(*info); +} + +static void free_machines_list(struct machine_info *machine_infos, int n) { + int i; + + if (!machine_infos) + return; + + for (i = 0; i < n; i++) + machine_info_clear(&machine_infos[i]); + + free(machine_infos); +} + +static int compare_machine_info(const struct machine_info *a, const struct machine_info *b) { + int r; + + r = CMP(b->is_host, a->is_host); + if (r != 0) + return r; + + return strcasecmp(a->name, b->name); +} + +static int get_machine_properties(sd_bus *bus, struct machine_info *mi) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL; + int r; + + assert(mi); + + if (!bus) { + r = sd_bus_open_system_machine(&container, mi->name); + if (r < 0) + return r; + + bus = container; + } + + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + machine_info_property_map, + BUS_MAP_STRDUP, + NULL, + NULL, + mi); + if (r < 0) + return r; + + return 0; +} + +static bool output_show_machine(const char *name, char **patterns) { + return strv_fnmatch_or_empty(patterns, name, FNM_NOESCAPE); +} + +static int get_machine_list( + sd_bus *bus, + struct machine_info **_machine_infos, + char **patterns) { + + struct machine_info *machine_infos = NULL; + _cleanup_strv_free_ char **m = NULL; + _cleanup_free_ char *hn = NULL; + size_t sz = 0; + char **i; + int c = 0, r; + + hn = gethostname_malloc(); + if (!hn) + return log_oom(); + + if (output_show_machine(hn, patterns)) { + if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) + return log_oom(); + + machine_infos[c].is_host = true; + machine_infos[c].name = TAKE_PTR(hn); + + (void) get_machine_properties(bus, &machine_infos[c]); + c++; + } + + r = sd_get_machine_names(&m); + if (r < 0) + return log_error_errno(r, "Failed to get machine list: %m"); + + STRV_FOREACH(i, m) { + _cleanup_free_ char *class = NULL; + + if (!output_show_machine(*i, patterns)) + continue; + + sd_machine_get_class(*i, &class); + if (!streq_ptr(class, "container")) + continue; + + if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) { + free_machines_list(machine_infos, c); + return log_oom(); + } + + machine_infos[c].is_host = false; + machine_infos[c].name = strdup(*i); + if (!machine_infos[c].name) { + free_machines_list(machine_infos, c); + return log_oom(); + } + + (void) get_machine_properties(NULL, &machine_infos[c]); + c++; + } + + *_machine_infos = machine_infos; + return c; +} + +static void output_machines_list(struct machine_info *machine_infos, unsigned n) { + struct machine_info *m; + unsigned + circle_len = 0, + namelen = STRLEN("NAME"), + statelen = STRLEN("STATE"), + failedlen = STRLEN("FAILED"), + jobslen = STRLEN("JOBS"); + bool state_missing = false; + + assert(machine_infos || n == 0); + + for (m = machine_infos; m < machine_infos + n; m++) { + namelen = MAX(namelen, + strlen(m->name) + (m->is_host ? STRLEN(" (host)") : 0)); + statelen = MAX(statelen, strlen_ptr(m->state)); + failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units)); + jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs)); + + if (!arg_plain && m->state && !streq(m->state, "running")) + circle_len = 2; + } + + if (!arg_no_legend) { + if (circle_len > 0) + fputs(" ", stdout); + + printf("%-*s %-*s %-*s %-*s\n", + namelen, "NAME", + statelen, "STATE", + failedlen, "FAILED", + jobslen, "JOBS"); + } + + for (m = machine_infos; m < machine_infos + n; m++) { + const char *on_state = "", *off_state = ""; + const char *on_failed = "", *off_failed = ""; + bool circle = false; + + if (streq_ptr(m->state, "degraded")) { + on_state = ansi_highlight_red(); + off_state = ansi_normal(); + circle = true; + } else if (!streq_ptr(m->state, "running")) { + on_state = ansi_highlight_yellow(); + off_state = ansi_normal(); + circle = true; + } + + if (m->n_failed_units > 0) { + on_failed = ansi_highlight_red(); + off_failed = ansi_normal(); + } else + on_failed = off_failed = ""; + + if (circle_len > 0) + printf("%s%s%s ", on_state, circle ? special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE) : " ", off_state); + + if (!m->state) + state_missing = true; + + if (m->is_host) + printf("%-*s (host) %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n", + (int) (namelen - strlen(" (host)")), + strna(m->name), + on_state, statelen, strna(m->state), off_state, + on_failed, failedlen, m->n_failed_units, off_failed, + jobslen, m->n_jobs); + else + printf("%-*s %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n", + namelen, strna(m->name), + on_state, statelen, strna(m->state), off_state, + on_failed, failedlen, m->n_failed_units, off_failed, + jobslen, m->n_jobs); + } + + if (!arg_no_legend) { + printf("\n"); + if (state_missing && geteuid() != 0) + printf("Notice: some information only available to privileged users was not shown.\n"); + printf("%u machines listed.\n", n); + } +} + +static int list_machines(int argc, char *argv[], void *userdata) { + struct machine_info *machine_infos = NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = get_machine_list(bus, &machine_infos, strv_skip(argv, 1)); + if (r < 0) + return r; + + (void) pager_open(arg_pager_flags); + + typesafe_qsort(machine_infos, r, compare_machine_info); + output_machines_list(machine_infos, r); + free_machines_list(machine_infos, r); + + return 0; +} + +static int get_default(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ char *_path = NULL; + const char *path; + int r; + + if (install_client_side()) { + r = unit_file_get_default(arg_scope, arg_root, &_path); + if (r < 0) + return log_error_errno(r, "Failed to get default target: %m"); + path = _path; + + r = 0; + } else { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetDefaultTarget", + &error, + &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to get default target: %s", bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "s", &path); + if (r < 0) + return bus_log_parse_error(r); + } + + if (path) + printf("%s\n", path); + + return 0; +} + +static int set_default(int argc, char *argv[], void *userdata) { + _cleanup_free_ char *unit = NULL; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + int r; + + assert(argc >= 2); + assert(argv); + + r = unit_name_mangle_with_suffix(argv[1], "set-default", + arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, + ".target", &unit); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); + + if (install_client_side()) { + r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes); + unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet); + + if (r > 0) + r = 0; + } else { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + sd_bus *bus; + + polkit_agent_open_maybe(); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SetDefaultTarget", + &error, + &reply, + "sb", unit, 1); + if (r < 0) + return log_error_errno(r, "Failed to set default target: %s", bus_error_message(&error, r)); + + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes); + if (r < 0) + goto finish; + + /* Try to reload if enabled */ + if (!arg_no_reload) + r = daemon_reload(argc, argv, userdata); + else + r = 0; + } + +finish: + unit_file_changes_free(changes, n_changes); + + return r; +} + +static int output_waiting_jobs(sd_bus *bus, uint32_t id, const char *method, const char *prefix) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *name, *type; + uint32_t other_id; + int r; + + assert(bus); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + method, + &error, + &reply, + "u", id); + if (r < 0) + return log_debug_errno(r, "Failed to get waiting jobs for job %" PRIu32, id); + + r = sd_bus_message_enter_container(reply, 'a', "(usssoo)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "(usssoo)", &other_id, &name, &type, NULL, NULL, NULL)) > 0) + printf("%s %u (%s/%s)\n", prefix, other_id, name, type); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return 0; +} + +struct job_info { + uint32_t id; + const char *name, *type, *state; +}; + +static void output_jobs_list(sd_bus *bus, const struct job_info* jobs, unsigned n, bool skipped) { + unsigned id_len, unit_len, type_len, state_len; + const struct job_info *j; + const char *on, *off; + bool shorten = false; + + assert(n == 0 || jobs); + + if (n == 0) { + if (!arg_no_legend) { + on = ansi_highlight_green(); + off = ansi_normal(); + + printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off); + } + return; + } + + (void) pager_open(arg_pager_flags); + + id_len = STRLEN("JOB"); + unit_len = STRLEN("UNIT"); + type_len = STRLEN("TYPE"); + state_len = STRLEN("STATE"); + + for (j = jobs; j < jobs + n; j++) { + uint32_t id = j->id; + assert(j->name && j->type && j->state); + + id_len = MAX(id_len, DECIMAL_STR_WIDTH(id)); + unit_len = MAX(unit_len, strlen(j->name)); + type_len = MAX(type_len, strlen(j->type)); + state_len = MAX(state_len, strlen(j->state)); + } + + if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) { + unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3); + shorten = true; + } + + if (!arg_no_legend) + printf("%*s %-*s %-*s %-*s\n", + id_len, "JOB", + unit_len, "UNIT", + type_len, "TYPE", + state_len, "STATE"); + + for (j = jobs; j < jobs + n; j++) { + _cleanup_free_ char *e = NULL; + + if (streq(j->state, "running")) { + on = ansi_highlight(); + off = ansi_normal(); + } else + on = off = ""; + + e = shorten ? ellipsize(j->name, unit_len, 33) : NULL; + printf("%*u %s%-*s%s %-*s %s%-*s%s\n", + id_len, j->id, + on, unit_len, e ? e : j->name, off, + type_len, j->type, + on, state_len, j->state, off); + + if (arg_jobs_after) + output_waiting_jobs(bus, j->id, "GetJobAfter", "\twaiting for job"); + if (arg_jobs_before) + output_waiting_jobs(bus, j->id, "GetJobBefore", "\tblocking job"); + } + + if (!arg_no_legend) { + on = ansi_highlight(); + off = ansi_normal(); + + printf("\n%s%u jobs listed%s.\n", on, n, off); + } +} + +static bool output_show_job(struct job_info *job, char **patterns) { + return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE); +} + +static int list_jobs(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ struct job_info *jobs = NULL; + const char *name, *type, *state; + bool skipped = false; + size_t size = 0; + unsigned c = 0; + sd_bus *bus; + uint32_t id; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListJobs", + &error, + &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to list jobs: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, 'a', "(usssoo)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, NULL, NULL)) > 0) { + struct job_info job = { id, name, type, state }; + + if (!output_show_job(&job, strv_skip(argv, 1))) { + skipped = true; + continue; + } + + if (!GREEDY_REALLOC(jobs, size, c + 1)) + return log_oom(); + + jobs[c++] = job; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + (void) pager_open(arg_pager_flags); + + output_jobs_list(bus, jobs, c, skipped); + return 0; +} + +static int cancel_job(int argc, char *argv[], void *userdata) { + sd_bus *bus; + char **name; + int r = 0; + + if (argc <= 1) + return trivial_method(argc, argv, userdata); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + STRV_FOREACH(name, strv_skip(argv, 1)) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + uint32_t id; + int q; + + q = safe_atou32(*name, &id); + if (q < 0) + return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name); + + q = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "CancelJob", + &error, + NULL, + "u", id); + if (q < 0) { + log_error_errno(q, "Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q)); + if (r == 0) + r = q; + } + } + + return r; +} + +static int need_daemon_reload(sd_bus *bus, const char *unit) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *path; + int b, r; + + /* We ignore all errors here, since this is used to show a + * warning only */ + + /* We don't use unit_dbus_path_from_name() directly since we + * don't want to load the unit if it isn't loaded. */ + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetUnit", + NULL, + &reply, + "s", unit); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "o", &path); + if (r < 0) + return r; + + r = sd_bus_get_property_trivial( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + "NeedDaemonReload", + NULL, + 'b', &b); + if (r < 0) + return r; + + return b; +} + +static void warn_unit_file_changed(const char *name) { + assert(name); + + log_warning("%sWarning:%s The unit file, source configuration file or drop-ins of %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.", + ansi_highlight_red(), + ansi_normal(), + name, + arg_scope == UNIT_FILE_SYSTEM ? "" : " --user"); +} + +static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **ret_unit_path) { + char **p; + + assert(lp); + assert(unit_name); + + STRV_FOREACH(p, lp->search_path) { + _cleanup_free_ char *path = NULL, *lpath = NULL; + int r; + + path = path_join(*p, unit_name); + if (!path) + return log_oom(); + + r = chase_symlinks(path, arg_root, 0, &lpath, NULL); + if (r == -ENOENT) + continue; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) + return log_error_errno(r, "Failed to access path \"%s\": %m", path); + + if (ret_unit_path) + *ret_unit_path = TAKE_PTR(lpath); + + return 1; + } + + if (ret_unit_path) + *ret_unit_path = NULL; + + return 0; +} + +static int unit_find_template_path( + const char *unit_name, + LookupPaths *lp, + char **ret_fragment_path, + char **ret_template) { + + _cleanup_free_ char *t = NULL, *f = NULL; + int r; + + /* Returns 1 if a fragment was found, 0 if not found, negative on error. */ + + r = unit_file_find_path(lp, unit_name, &f); + if (r < 0) + return r; + if (r > 0) { + if (ret_fragment_path) + *ret_fragment_path = TAKE_PTR(f); + if (ret_template) + *ret_template = NULL; + return r; /* found a real unit */ + } + + r = unit_name_template(unit_name, &t); + if (r == -EINVAL) { + if (ret_fragment_path) + *ret_fragment_path = NULL; + if (ret_template) + *ret_template = NULL; + + return 0; /* not a template, does not exist */ + } + if (r < 0) + return log_error_errno(r, "Failed to determine template name: %m"); + + r = unit_file_find_path(lp, t, ret_fragment_path); + if (r < 0) + return r; + + if (ret_template) + *ret_template = r > 0 ? TAKE_PTR(t) : NULL; + + return r; +} + +static int unit_find_paths( + sd_bus *bus, + const char *unit_name, + LookupPaths *lp, + bool force_client_side, + char **ret_fragment_path, + char ***ret_dropin_paths) { + + _cleanup_strv_free_ char **dropins = NULL; + _cleanup_free_ char *path = NULL; + int r; + + /** + * Finds where the unit is defined on disk. Returns 0 if the unit is not found. Returns 1 if it is + * found, and sets: + * - the path to the unit in *ret_frament_path, if it exists on disk, + * - and a strv of existing drop-ins in *ret_dropin_paths, if the arg is not NULL and any dropins + * were found. + * + * Returns -ERFKILL if the unit is masked, and -EKEYREJECTED if the unit file could not be loaded for + * some reason (the latter only applies if we are going through the service manager). + */ + + assert(unit_name); + assert(ret_fragment_path); + assert(lp); + + /* Go via the bus to acquire the path, unless we are explicitly told not to, or when the unit name is a template */ + if (!force_client_side && + !install_client_side() && + !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *load_state = NULL, *dbus_path = NULL; + + dbus_path = unit_dbus_path_from_name(unit_name); + if (!dbus_path) + return log_oom(); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + dbus_path, + "org.freedesktop.systemd1.Unit", + "LoadState", + &error, + &load_state); + if (r < 0) + return log_error_errno(r, "Failed to get LoadState: %s", bus_error_message(&error, r)); + + if (streq(load_state, "masked")) + return -ERFKILL; + if (streq(load_state, "not-found")) { + r = 0; + goto not_found; + } + if (!STR_IN_SET(load_state, "loaded", "bad-setting")) + return -EKEYREJECTED; + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + dbus_path, + "org.freedesktop.systemd1.Unit", + "FragmentPath", + &error, + &path); + if (r < 0) + return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r)); + + if (ret_dropin_paths) { + r = sd_bus_get_property_strv( + bus, + "org.freedesktop.systemd1", + dbus_path, + "org.freedesktop.systemd1.Unit", + "DropInPaths", + &error, + &dropins); + if (r < 0) + return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r)); + } + } else { + const char *_path; + _cleanup_set_free_free_ Set *names = NULL; + + if (!cached_name_map) { + r = unit_file_build_name_map(lp, NULL, &cached_id_map, &cached_name_map, NULL); + if (r < 0) + return r; + } + + r = unit_file_find_fragment(cached_id_map, cached_name_map, unit_name, &_path, &names); + if (r < 0) + return r; + + if (_path) { + path = strdup(_path); + if (!path) + return log_oom(); + } + + if (ret_dropin_paths) { + r = unit_file_find_dropin_paths(arg_root, lp->search_path, NULL, + ".d", ".conf", + names, &dropins); + if (r < 0) + return r; + } + } + + if (isempty(path)) { + *ret_fragment_path = NULL; + r = 0; + } else { + *ret_fragment_path = TAKE_PTR(path); + r = 1; + } + + if (ret_dropin_paths) { + if (!strv_isempty(dropins)) { + *ret_dropin_paths = TAKE_PTR(dropins); + r = 1; + } else + *ret_dropin_paths = NULL; + } + + not_found: + if (r == 0 && !arg_force) + log_error("No files found for %s.", unit_name); + + return r; +} + +static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *buf = NULL, *dbus_path = NULL; + UnitActiveState state; + int r; + + assert(name); + assert(active_state); + + dbus_path = unit_dbus_path_from_name(name); + if (!dbus_path) + return log_oom(); + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + dbus_path, + "org.freedesktop.systemd1.Unit", + "ActiveState", + &error, + &buf); + if (r < 0) + return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r)); + + state = unit_active_state_from_string(buf); + if (state < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid unit state '%s' for: %s", buf, name); + + *active_state = state; + return 0; +} + +static int unit_is_masked(sd_bus *bus, LookupPaths *lp, const char *name) { + _cleanup_free_ char *load_state = NULL; + int r; + + if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) { + _cleanup_free_ char *path = NULL; + + /* A template cannot be loaded, but it can be still masked, so + * we need to use a different method. */ + + r = unit_file_find_path(lp, name, &path); + if (r < 0) + return r; + if (r == 0) + return false; + return null_or_empty_path(path); + } + + r = unit_load_state(bus, name, &load_state); + if (r < 0) + return r; + + return streq(load_state, "masked"); +} + +static int check_triggering_units(sd_bus *bus, const char *name) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *n = NULL, *dbus_path = NULL, *load_state = NULL; + _cleanup_strv_free_ char **triggered_by = NULL; + bool print_warning_label = true; + UnitActiveState active_state; + char **i; + int r; + + r = unit_name_mangle(name, 0, &n); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); + + r = unit_load_state(bus, name, &load_state); + if (r < 0) + return r; + + if (streq(load_state, "masked")) + return 0; + + dbus_path = unit_dbus_path_from_name(n); + if (!dbus_path) + return log_oom(); + + r = sd_bus_get_property_strv( + bus, + "org.freedesktop.systemd1", + dbus_path, + "org.freedesktop.systemd1.Unit", + "TriggeredBy", + &error, + &triggered_by); + if (r < 0) + return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r)); + + STRV_FOREACH(i, triggered_by) { + r = get_state_one_unit(bus, *i, &active_state); + if (r < 0) + return r; + + if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING)) + continue; + + if (print_warning_label) { + log_warning("Warning: Stopping %s, but it can still be activated by:", n); + print_warning_label = false; + } + + log_warning(" %s", *i); + } + + return 0; +} + +static const struct { + const char *verb; /* systemctl verb */ + const char *method; /* Name of the specific D-Bus method */ + const char *job_type; /* Job type when passing to the generic EnqueueUnitJob() method */ +} unit_actions[] = { + { "start", "StartUnit", "start" }, + { "stop", "StopUnit", "stop" }, + { "condstop", "StopUnit", "stop" }, /* legacy alias */ + { "reload", "ReloadUnit", "reload" }, + { "restart", "RestartUnit", "restart" }, + { "try-restart", "TryRestartUnit", "try-restart" }, + { "condrestart", "TryRestartUnit", "try-restart" }, /* legacy alias */ + { "reload-or-restart", "ReloadOrRestartUnit", "reload-or-restart" }, + { "try-reload-or-restart", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, + { "reload-or-try-restart", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */ + { "condreload", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */ + { "force-reload", "ReloadOrTryRestartUnit", "reload-or-try-restart" }, /* legacy alias */ +}; + +static const char *verb_to_method(const char *verb) { + size_t i; + + for (i = 0; i < ELEMENTSOF(unit_actions); i++) + if (streq_ptr(unit_actions[i].verb, verb)) + return unit_actions[i].method; + + return "StartUnit"; +} + +static const char *verb_to_job_type(const char *verb) { + size_t i; + + for (i = 0; i < ELEMENTSOF(unit_actions); i++) + if (streq_ptr(unit_actions[i].verb, verb)) + return unit_actions[i].job_type; + + return "start"; +} + +static int start_unit_one( + sd_bus *bus, + const char *method, /* When using classic per-job bus methods */ + const char *job_type, /* When using new-style EnqueueUnitJob() */ + const char *name, + const char *mode, + sd_bus_error *error, + BusWaitForJobs *w, + BusWaitForUnits *wu) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *path; + bool done = false; + int r; + + assert(method); + assert(name); + assert(mode); + assert(error); + + log_debug("%s dbus call org.freedesktop.systemd1.Manager %s(%s, %s)", + arg_dry_run ? "Would execute" : "Executing", + method, name, mode); + + if (arg_dry_run) + return 0; + + if (arg_show_transaction) { + _cleanup_(sd_bus_error_free) sd_bus_error enqueue_error = SD_BUS_ERROR_NULL; + + /* Use the new, fancy EnqueueUnitJob() API if the user wants us to print the transaction */ + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "EnqueueUnitJob", + &enqueue_error, + &reply, + "sss", + name, job_type, mode); + if (r < 0) { + if (!sd_bus_error_has_name(&enqueue_error, SD_BUS_ERROR_UNKNOWN_METHOD)) { + (void) sd_bus_error_move(error, &enqueue_error); + goto fail; + } + + /* Hmm, the API is not yet available. Let's use the classic API instead (see below). */ + log_notice("--show-transaction not supported by this service manager, proceeding without."); + } else { + const char *u, *jt; + uint32_t id; + + r = sd_bus_message_read(reply, "uosos", &id, &path, &u, NULL, &jt); + if (r < 0) + return bus_log_parse_error(r); + + log_info("Enqueued anchor job %" PRIu32 " %s/%s.", id, u, jt); + + r = sd_bus_message_enter_container(reply, 'a', "(uosos)"); + if (r < 0) + return bus_log_parse_error(r); + for (;;) { + r = sd_bus_message_read(reply, "(uosos)", &id, NULL, &u, NULL, &jt); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + log_info("Enqueued auxiliary job %" PRIu32 " %s/%s.", id, u, jt); + } + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + done = true; + } + } + + if (!done) { + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + method, + error, + &reply, + "ss", name, mode); + if (r < 0) + goto fail; + + r = sd_bus_message_read(reply, "o", &path); + if (r < 0) + return bus_log_parse_error(r); + } + + if (need_daemon_reload(bus, name) > 0) + warn_unit_file_changed(name); + + if (w) { + log_debug("Adding %s to the set", path); + r = bus_wait_for_jobs_add(w, path); + if (r < 0) + return log_error_errno(r, "Failed to watch job for %s: %m", name); + } + + if (wu) { + r = bus_wait_for_units_add_unit(wu, name, BUS_WAIT_FOR_INACTIVE|BUS_WAIT_NO_JOB, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to watch unit %s: %m", name); + } + + return 0; + +fail: + /* There's always a fallback possible for legacy actions. */ + if (arg_action != ACTION_SYSTEMCTL) + return r; + + log_error_errno(r, "Failed to %s %s: %s", job_type, name, bus_error_message(error, r)); + + if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) && + !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED) && + !sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE)) + log_error("See %s logs and 'systemctl%s status%s %s' for details.", + arg_scope == UNIT_FILE_SYSTEM ? "system" : "user", + arg_scope == UNIT_FILE_SYSTEM ? "" : " --user", + name[0] == '-' ? " --" : "", + name); + + return r; +} + +static const struct { + const char *target; + const char *verb; + const char *mode; +} action_table[_ACTION_MAX] = { + [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" }, + [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" }, + [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" }, + [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" }, + [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" }, + [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" }, + [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" }, + [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" }, + [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" }, + [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" }, + [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" }, + [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" }, + [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" }, + [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" }, + [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" }, + [ACTION_SUSPEND_THEN_HIBERNATE] = { SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET, "suspend-then-hibernate", "replace-irreversibly" }, +}; + +static enum action verb_to_action(const char *verb) { + enum action i; + + for (i = 0; i < _ACTION_MAX; i++) + if (streq_ptr(action_table[i].verb, verb)) + return i; + + return _ACTION_INVALID; +} + +static const char** make_extra_args(const char *extra_args[static 4]) { + size_t n = 0; + + assert(extra_args); + + if (arg_scope != UNIT_FILE_SYSTEM) + extra_args[n++] = "--user"; + + if (arg_transport == BUS_TRANSPORT_REMOTE) { + extra_args[n++] = "-H"; + extra_args[n++] = arg_host; + } else if (arg_transport == BUS_TRANSPORT_MACHINE) { + extra_args[n++] = "-M"; + extra_args[n++] = arg_host; + } else + assert(arg_transport == BUS_TRANSPORT_LOCAL); + + extra_args[n] = NULL; + return extra_args; +} + +static int start_unit(int argc, char *argv[], void *userdata) { + _cleanup_(bus_wait_for_units_freep) BusWaitForUnits *wu = NULL; + _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; + const char *method, *job_type, *mode, *one_name, *suffix = NULL; + _cleanup_free_ char **stopped_units = NULL; /* Do not use _cleanup_strv_free_ */ + _cleanup_strv_free_ char **names = NULL; + int r, ret = EXIT_SUCCESS; + sd_bus *bus; + char **name; + + if (arg_wait && !STR_IN_SET(argv[0], "start", "restart")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--wait may only be used with the 'start' or 'restart' commands."); + + /* we cannot do sender tracking on the private bus, so we need the full + * one for RefUnit to implement --wait */ + r = acquire_bus(arg_wait ? BUS_FULL : BUS_MANAGER, &bus); + if (r < 0) + return r; + + ask_password_agent_open_maybe(); + polkit_agent_open_maybe(); + + if (arg_action == ACTION_SYSTEMCTL) { + enum action action; + + action = verb_to_action(argv[0]); + + if (action != _ACTION_INVALID) { + /* A command in style "systemctl reboot", "systemctl poweroff", … */ + method = "StartUnit"; + job_type = "start"; + mode = action_table[action].mode; + one_name = action_table[action].target; + } else { + if (streq(argv[0], "isolate")) { + /* A "systemctl isolate …" command */ + method = "StartUnit"; + job_type = "start"; + mode = "isolate"; + suffix = ".target"; + } else { + /* A command in style of "systemctl start …", "sysemctl stop …" and so on */ + method = verb_to_method(argv[0]); + job_type = verb_to_job_type(argv[0]); + mode = arg_job_mode; + } + one_name = NULL; + } + } else { + /* A SysV legacy command such as "halt", "reboot", "poweroff", … */ + assert(arg_action >= 0 && arg_action < _ACTION_MAX); + assert(action_table[arg_action].target); + assert(action_table[arg_action].mode); + + method = "StartUnit"; + job_type = "start"; + mode = action_table[arg_action].mode; + one_name = action_table[arg_action].target; + } + + if (one_name) { + names = strv_new(one_name); + if (!names) + return log_oom(); + } else { + bool expanded; + + r = expand_names(bus, strv_skip(argv, 1), suffix, &names, &expanded); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + + if (!arg_all && expanded && streq(job_type, "start") && !arg_quiet) { + log_warning("Warning: %ssystemctl start called with a glob pattern.%s", + ansi_highlight_red(), + ansi_normal()); + log_notice("Hint: unit globs expand to loaded units, so start will usually have no effect.\n" + " Passing --all will also load units which are pulled in by other units.\n" + " See systemctl(1) for more details."); + } + } + + if (!arg_no_block) { + r = bus_wait_for_jobs_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Could not watch jobs: %m"); + } + + if (arg_wait) { + r = sd_bus_call_method_async( + bus, + NULL, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Subscribe", + NULL, NULL, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to enable subscription: %m"); + + r = bus_wait_for_units_new(bus, &wu); + if (r < 0) + return log_error_errno(r, "Failed to allocate unit watch context: %m"); + } + + STRV_FOREACH(name, names) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + r = start_unit_one(bus, method, job_type, *name, mode, &error, w, wu); + if (ret == EXIT_SUCCESS && r < 0) + ret = translate_bus_error_to_exit_status(r, &error); + + if (r >= 0 && streq(method, "StopUnit")) { + r = strv_push(&stopped_units, *name); + if (r < 0) + return log_oom(); + } + } + + if (!arg_no_block) { + const char* extra_args[4]; + + r = bus_wait_for_jobs(w, arg_quiet, make_extra_args(extra_args)); + if (r < 0) + return r; + + /* When stopping units, warn if they can still be triggered by + * another active unit (socket, path, timer) */ + if (!arg_quiet) + STRV_FOREACH(name, stopped_units) + (void) check_triggering_units(bus, *name); + } + + if (arg_wait) { + r = bus_wait_for_units_run(wu); + if (r < 0) + return log_error_errno(r, "Failed to wait for units: %m"); + if (r == BUS_WAIT_FAILURE && ret == EXIT_SUCCESS) + ret = EXIT_FAILURE; + } + + return ret; +} + +#if ENABLE_LOGIND +static int logind_set_wall_message(void) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + _cleanup_free_ char *m = NULL; + int r; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + m = strv_join(arg_wall, " "); + if (!m) + return log_oom(); + + log_debug("%s wall message \"%s\".", arg_dry_run ? "Would set" : "Setting", m); + if (arg_dry_run) + return 0; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetWallMessage", + &error, + NULL, + "sb", + m, + !arg_no_wall); + + if (r < 0) + return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r)); + return 0; +} +#endif + +/* Ask systemd-logind, which might grant access to unprivileged users through polkit */ +static int logind_reboot(enum action a) { +#if ENABLE_LOGIND + static const struct { + const char *method; + const char *description; + } actions[_ACTION_MAX] = { + [ACTION_POWEROFF] = { "PowerOff", "power off system" }, + [ACTION_REBOOT] = { "Reboot", "reboot system" }, + [ACTION_HALT] = { "Halt", "halt system" }, + [ACTION_SUSPEND] = { "Suspend", "suspend system" }, + [ACTION_HIBERNATE] = { "Hibernate", "hibernate system" }, + [ACTION_HYBRID_SLEEP] = { "HybridSleep", "put system into hybrid sleep" }, + [ACTION_SUSPEND_THEN_HIBERNATE] = { "SuspendThenHibernate", "suspend system, hibernate later" }, + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + int r; + + if (a < 0 || a >= _ACTION_MAX || !actions[a].method) + return -EINVAL; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + (void) logind_set_wall_message(); + + log_debug("%s org.freedesktop.login1.Manager %s dbus call.", arg_dry_run ? "Would execute" : "Executing", actions[a].method); + + if (arg_dry_run) + return 0; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + actions[a].method, + &error, + NULL, + "b", arg_ask_password); + if (r < 0) + return log_error_errno(r, "Failed to %s via logind: %s", actions[a].description, bus_error_message(&error, r)); + + return 0; +#else + return -ENOSYS; +#endif +} + +static int logind_check_inhibitors(enum action a) { +#if ENABLE_LOGIND + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_strv_free_ char **sessions = NULL; + const char *what, *who, *why, *mode; + uint32_t uid, pid; + sd_bus *bus; + unsigned c = 0; + char **s; + int r; + + if (arg_ignore_inhibitors || arg_force > 0) + return 0; + + if (arg_when > 0) + return 0; + + if (geteuid() == 0) + return 0; + + if (!on_tty()) + return 0; + + if (arg_transport != BUS_TRANSPORT_LOCAL) + return 0; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ListInhibitors", + NULL, + &reply, + NULL); + if (r < 0) + /* If logind is not around, then there are no inhibitors... */ + return 0; + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) { + _cleanup_free_ char *comm = NULL, *user = NULL; + _cleanup_strv_free_ char **sv = NULL; + + if (!streq(mode, "block")) + continue; + + sv = strv_split(what, ":"); + if (!sv) + return log_oom(); + + if (!pid_is_valid((pid_t) pid)) + return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Invalid PID "PID_FMT".", (pid_t) pid); + + if (!strv_contains(sv, + IN_SET(a, + ACTION_HALT, + ACTION_POWEROFF, + ACTION_REBOOT, + ACTION_KEXEC) ? "shutdown" : "sleep")) + continue; + + get_process_comm(pid, &comm); + user = uid_to_name(uid); + + log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".", + who, (pid_t) pid, strna(comm), strna(user), why); + + c++; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + /* Check for current sessions */ + sd_get_sessions(&sessions); + STRV_FOREACH(s, sessions) { + _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL; + + if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid()) + continue; + + if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user")) + continue; + + if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "wayland", "tty", "mir")) + continue; + + sd_session_get_tty(*s, &tty); + sd_session_get_seat(*s, &seat); + sd_session_get_service(*s, &service); + user = uid_to_name(uid); + + log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty); + c++; + } + + if (c <= 0) + return 0; + + log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.", + action_table[a].verb); + + return -EPERM; +#else + return 0; +#endif +} + +static int prepare_firmware_setup(void) { + + if (!arg_firmware_setup) + return 0; + +#if ENABLE_LOGIND + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetRebootToFirmwareSetup", + &error, + NULL, + "b", true); + if (r < 0) + return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r)); + + return 0; +#else + return log_error_errno(SYNTHETIC_ERRNO(ENOSYS), + "Booting into firmware setup not supported."); +#endif +} + +static int prepare_boot_loader_menu(void) { + + if (arg_boot_loader_menu == USEC_INFINITY) + return 0; + +#if ENABLE_LOGIND + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetRebootToBootLoaderMenu", + &error, + NULL, + "t", arg_boot_loader_menu); + if (r < 0) + return log_error_errno(r, "Cannot indicate to boot loader to enter boot loader entry menu: %s", bus_error_message(&error, r)); + + return 0; +#else + return log_error_errno(SYNTHETIC_ERRNO(ENOSYS), + "Booting into boot loader menu not supported."); +#endif +} + +static int prepare_boot_loader_entry(void) { + + if (!arg_boot_loader_entry) + return 0; + +#if ENABLE_LOGIND + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetRebootToBootLoaderEntry", + &error, + NULL, + "s", arg_boot_loader_entry); + if (r < 0) + return log_error_errno(r, "Cannot set boot into loader entry '%s': %s", arg_boot_loader_entry, bus_error_message(&error, r)); + + return 0; +#else + return log_error_errno(SYNTHETIC_ERRNO(ENOSYS), + "Booting into boot loader entry not supported."); +#endif +} + +static int load_kexec_kernel(void) { + _cleanup_(boot_config_free) BootConfig config = {}; + _cleanup_free_ char *kernel = NULL, *initrd = NULL, *options = NULL; + const BootEntry *e; + pid_t pid; + int r; + + if (kexec_loaded()) { + log_debug("Kexec kernel already loaded."); + return 0; + } + + if (access(KEXEC, X_OK) < 0) + return log_error_errno(errno, KEXEC" is not available: %m"); + + r = boot_entries_load_config_auto(NULL, NULL, &config); + if (r == -ENOKEY) + /* The call doesn't log about ENOKEY, let's do so here. */ + return log_error_errno(r, + "No kexec kernel loaded and autodetection failed.\n%s", + is_efi_boot() + ? "Cannot automatically load kernel: ESP partition mount point not found." + : "Automatic loading works only on systems booted with EFI."); + if (r < 0) + return r; + + e = boot_config_default_entry(&config); + if (!e) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), + "No boot loader entry suitable as default, refusing to guess."); + + log_debug("Found default boot loader entry in file \"%s\"", e->path); + + if (!e->kernel) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Boot entry does not refer to Linux kernel, which is not supported currently."); + if (strv_length(e->initrd) > 1) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Boot entry specifies multiple initrds, which is not supported currently."); + + kernel = path_join(e->root, e->kernel); + if (!kernel) + return log_oom(); + + if (!strv_isempty(e->initrd)) { + initrd = path_join(e->root, e->initrd[0]); + if (!initrd) + return log_oom(); + } + + options = strv_join(e->options, " "); + if (!options) + return log_oom(); + + log_full(arg_quiet ? LOG_DEBUG : LOG_INFO, + "%s "KEXEC" --load \"%s\" --append \"%s\"%s%s%s", + arg_dry_run ? "Would run" : "Running", + kernel, + options, + initrd ? " --initrd \"" : NULL, strempty(initrd), initrd ? "\"" : ""); + if (arg_dry_run) + return 0; + + r = safe_fork("(kexec)", FORK_WAIT|FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + const char* const args[] = { + KEXEC, + "--load", kernel, + "--append", options, + initrd ? "--initrd" : NULL, initrd, + NULL + }; + + /* Child */ + execv(args[0], (char * const *) args); + _exit(EXIT_FAILURE); + } + + return 0; +} + +static int set_exit_code(uint8_t code) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SetExitCode", + &error, + NULL, + "y", code); + if (r < 0) + return log_error_errno(r, "Failed to set exit code: %s", bus_error_message(&error, r)); + + return 0; +} + +static int start_special(int argc, char *argv[], void *userdata) { + enum action a; + int r; + bool termination_action; /* an action that terminates the manager, + * can be performed also by signal. */ + + assert(argv); + + a = verb_to_action(argv[0]); + + r = logind_check_inhibitors(a); + if (r < 0) + return r; + + if (arg_force >= 2) { + r = must_be_root(); + if (r < 0) + return r; + } + + r = prepare_firmware_setup(); + if (r < 0) + return r; + + r = prepare_boot_loader_menu(); + if (r < 0) + return r; + + r = prepare_boot_loader_entry(); + if (r < 0) + return r; + + if (a == ACTION_REBOOT && argc > 1) { + r = update_reboot_parameter_and_warn(argv[1], false); + if (r < 0) + return r; + + } else if (a == ACTION_KEXEC) { + r = load_kexec_kernel(); + if (r < 0 && arg_force >= 1) + log_notice("Failed to load kexec kernel, continuing without."); + else if (r < 0) + return r; + + } else if (a == ACTION_EXIT && argc > 1) { + uint8_t code; + + /* If the exit code is not given on the command line, + * don't reset it to zero: just keep it as it might + * have been set previously. */ + + r = safe_atou8(argv[1], &code); + if (r < 0) + return log_error_errno(r, "Invalid exit code."); + + r = set_exit_code(code); + if (r < 0) + return r; + } + + termination_action = IN_SET(a, + ACTION_HALT, + ACTION_POWEROFF, + ACTION_REBOOT); + if (termination_action && arg_force >= 2) + return halt_now(a); + + if (arg_force >= 1 && + (termination_action || IN_SET(a, ACTION_KEXEC, ACTION_EXIT))) + r = trivial_method(argc, argv, userdata); + else { + /* First try logind, to allow authentication with polkit */ + if (IN_SET(a, + ACTION_POWEROFF, + ACTION_REBOOT, + ACTION_HALT, + ACTION_SUSPEND, + ACTION_HIBERNATE, + ACTION_HYBRID_SLEEP, + ACTION_SUSPEND_THEN_HIBERNATE)) { + + r = logind_reboot(a); + if (r >= 0) + return r; + if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) + /* requested operation is not supported or already in progress */ + return r; + + /* On all other errors, try low-level operation. In order to minimize the difference between + * operation with and without logind, we explicitly enable non-blocking mode for this, as + * logind's shutdown operations are always non-blocking. */ + + arg_no_block = true; + + } else if (IN_SET(a, ACTION_EXIT, ACTION_KEXEC)) + /* Since exit/kexec are so close in behaviour to power-off/reboot, let's also make them + * asynchronous, in order to not confuse the user needlessly with unexpected behaviour. */ + arg_no_block = true; + + r = start_unit(argc, argv, userdata); + } + + if (termination_action && arg_force < 2 && + IN_SET(r, -ENOENT, -ETIMEDOUT)) + log_notice("It is possible to perform action directly, see discussion of --force --force in man:systemctl(1)."); + + return r; +} + +static int start_system_special(int argc, char *argv[], void *userdata) { + /* Like start_special above, but raises an error when running in user mode */ + + if (arg_scope != UNIT_FILE_SYSTEM) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Bad action for %s mode.", + arg_scope == UNIT_FILE_GLOBAL ? "--global" : "--user"); + + return start_special(argc, argv, userdata); +} + +static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) { + _cleanup_strv_free_ char **names = NULL; + UnitActiveState active_state; + sd_bus *bus; + char **name; + int r, i; + bool found = false; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = expand_names(bus, args, NULL, &names, NULL); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + + STRV_FOREACH(name, names) { + r = get_state_one_unit(bus, *name, &active_state); + if (r < 0) + return r; + + if (!arg_quiet) + puts(unit_active_state_to_string(active_state)); + + for (i = 0; i < nb_states; ++i) + if (good_states[i] == active_state) + found = true; + } + + /* use the given return code for the case that we won't find + * any unit which matches the list */ + return found ? 0 : code; +} + +static int check_unit_active(int argc, char *argv[], void *userdata) { + static const UnitActiveState states[] = { + UNIT_ACTIVE, + UNIT_RELOADING, + }; + + /* According to LSB: 3, "program is not running" */ + return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING, states, ELEMENTSOF(states), strv_skip(argv, 1)); +} + +static int check_unit_failed(int argc, char *argv[], void *userdata) { + static const UnitActiveState states[] = { + UNIT_FAILED, + }; + + return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS, states, ELEMENTSOF(states), strv_skip(argv, 1)); +} + +static int kill_unit(int argc, char *argv[], void *userdata) { + _cleanup_strv_free_ char **names = NULL; + char *kill_who = NULL, **name; + sd_bus *bus; + int r, q; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + if (!arg_kill_who) + arg_kill_who = "all"; + + /* --fail was specified */ + if (streq(arg_job_mode, "fail")) + kill_who = strjoina(arg_kill_who, "-fail"); + + r = expand_names(bus, strv_skip(argv, 1), NULL, &names, NULL); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + + STRV_FOREACH(name, names) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + q = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "KillUnit", + &error, + NULL, + "ssi", *name, kill_who ? kill_who : arg_kill_who, arg_signal); + if (q < 0) { + log_error_errno(q, "Failed to kill unit %s: %s", *name, bus_error_message(&error, q)); + if (r == 0) + r = q; + } + } + + return r; +} + +static int clean_unit(int argc, char *argv[], void *userdata) { + _cleanup_(bus_wait_for_units_freep) BusWaitForUnits *w = NULL; + _cleanup_strv_free_ char **names = NULL; + int r, ret = EXIT_SUCCESS; + char **name; + sd_bus *bus; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + if (!arg_clean_what) { + arg_clean_what = strv_new("cache", "runtime"); + if (!arg_clean_what) + return log_oom(); + } + + r = expand_names(bus, strv_skip(argv, 1), NULL, &names, NULL); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + + if (!arg_no_block) { + r = bus_wait_for_units_new(bus, &w); + if (r < 0) + return log_error_errno(r, "Failed to allocate unit waiter: %m"); + } + + STRV_FOREACH(name, names) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + if (w) { + /* If we shall wait for the cleaning to complete, let's add a ref on the unit first */ + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "RefUnit", + &error, + NULL, + "s", *name); + if (r < 0) { + log_error_errno(r, "Failed to add reference to unit %s: %s", *name, bus_error_message(&error, r)); + if (ret == EXIT_SUCCESS) + ret = r; + continue; + } + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "CleanUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", *name); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, arg_clean_what); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) { + log_error_errno(r, "Failed to clean unit %s: %s", *name, bus_error_message(&error, r)); + if (ret == EXIT_SUCCESS) { + ret = r; + continue; + } + } + + if (w) { + r = bus_wait_for_units_add_unit(w, *name, BUS_WAIT_REFFED|BUS_WAIT_FOR_MAINTENANCE_END, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to watch unit %s: %m", *name); + } + } + + r = bus_wait_for_units_run(w); + if (r < 0) + return log_error_errno(r, "Failed to wait for units: %m"); + if (r == BUS_WAIT_FAILURE) + ret = EXIT_FAILURE; + + return ret; +} + +typedef struct ExecStatusInfo { + char *name; + + char *path; + char **argv; + + bool ignore; + + usec_t start_timestamp; + usec_t exit_timestamp; + pid_t pid; + int code; + int status; + + ExecCommandFlags flags; + + LIST_FIELDS(struct ExecStatusInfo, exec); +} ExecStatusInfo; + +static void exec_status_info_free(ExecStatusInfo *i) { + assert(i); + + free(i->name); + free(i->path); + strv_free(i->argv); + free(i); +} + +static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i, bool is_ex_prop) { + _cleanup_strv_free_ char **ex_opts = NULL; + uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic; + const char *path; + uint32_t pid; + int32_t code, status; + int ignore, r; + + assert(m); + assert(i); + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, is_ex_prop ? "sasasttttuii" : "sasbttttuii"); + if (r < 0) + return bus_log_parse_error(r); + else if (r == 0) + return 0; + + r = sd_bus_message_read(m, "s", &path); + if (r < 0) + return bus_log_parse_error(r); + + i->path = strdup(path); + if (!i->path) + return log_oom(); + + r = sd_bus_message_read_strv(m, &i->argv); + if (r < 0) + return bus_log_parse_error(r); + + r = is_ex_prop ? sd_bus_message_read_strv(m, &ex_opts) : sd_bus_message_read(m, "b", &ignore); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read(m, + "ttttuii", + &start_timestamp, &start_timestamp_monotonic, + &exit_timestamp, &exit_timestamp_monotonic, + &pid, + &code, &status); + if (r < 0) + return bus_log_parse_error(r); + + if (is_ex_prop) { + r = exec_command_flags_from_strv(ex_opts, &i->flags); + if (r < 0) + return log_error_errno(r, "Failed to convert strv to ExecCommandFlags: %m"); + + i->ignore = FLAGS_SET(i->flags, EXEC_COMMAND_IGNORE_FAILURE); + } else + i->ignore = ignore; + + i->start_timestamp = (usec_t) start_timestamp; + i->exit_timestamp = (usec_t) exit_timestamp; + i->pid = (pid_t) pid; + i->code = code; + i->status = status; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; +} + +typedef struct UnitCondition { + char *name; + char *param; + bool trigger; + bool negate; + int tristate; + + LIST_FIELDS(struct UnitCondition, conditions); +} UnitCondition; + +static void unit_condition_free(UnitCondition *c) { + if (!c) + return; + + free(c->name); + free(c->param); + free(c); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition*, unit_condition_free); + +typedef struct UnitStatusInfo { + const char *id; + const char *load_state; + const char *active_state; + const char *sub_state; + const char *unit_file_state; + const char *unit_file_preset; + + const char *description; + const char *following; + + char **documentation; + + const char *fragment_path; + const char *source_path; + const char *control_group; + + char **dropin_paths; + + char **triggered_by; + char **triggers; + + const char *load_error; + const char *result; + + usec_t inactive_exit_timestamp; + usec_t inactive_exit_timestamp_monotonic; + usec_t active_enter_timestamp; + usec_t active_exit_timestamp; + usec_t inactive_enter_timestamp; + + bool need_daemon_reload; + bool transient; + + /* Service */ + pid_t main_pid; + pid_t control_pid; + const char *status_text; + const char *pid_file; + bool running:1; + int status_errno; + + usec_t start_timestamp; + usec_t exit_timestamp; + + int exit_code, exit_status; + + usec_t condition_timestamp; + bool condition_result; + LIST_HEAD(UnitCondition, conditions); + + usec_t assert_timestamp; + bool assert_result; + bool failed_assert_trigger; + bool failed_assert_negate; + const char *failed_assert; + const char *failed_assert_parameter; + usec_t next_elapse_real; + usec_t next_elapse_monotonic; + + /* Socket */ + unsigned n_accepted; + unsigned n_connections; + unsigned n_refused; + bool accept; + + /* Pairs of type, path */ + char **listen; + + /* Device */ + const char *sysfs_path; + + /* Mount, Automount */ + const char *where; + + /* Swap */ + const char *what; + + /* CGroup */ + uint64_t memory_current; + uint64_t memory_min; + uint64_t memory_low; + uint64_t memory_high; + uint64_t memory_max; + uint64_t memory_swap_max; + uint64_t memory_limit; + uint64_t cpu_usage_nsec; + uint64_t tasks_current; + uint64_t tasks_max; + uint64_t ip_ingress_bytes; + uint64_t ip_egress_bytes; + uint64_t io_read_bytes; + uint64_t io_write_bytes; + + uint64_t default_memory_min; + uint64_t default_memory_low; + + LIST_HEAD(ExecStatusInfo, exec); +} UnitStatusInfo; + +static void unit_status_info_free(UnitStatusInfo *info) { + ExecStatusInfo *p; + UnitCondition *c; + + strv_free(info->documentation); + strv_free(info->dropin_paths); + strv_free(info->triggered_by); + strv_free(info->triggers); + strv_free(info->listen); + + while ((c = info->conditions)) { + LIST_REMOVE(conditions, info->conditions, c); + unit_condition_free(c); + } + + while ((p = info->exec)) { + LIST_REMOVE(exec, info->exec, p); + exec_status_info_free(p); + } +} + +static void format_active_state(const char *active_state, const char **active_on, const char **active_off) { + if (streq_ptr(active_state, "failed")) { + *active_on = ansi_highlight_red(); + *active_off = ansi_normal(); + } else if (STRPTR_IN_SET(active_state, "active", "reloading")) { + *active_on = ansi_highlight_green(); + *active_off = ansi_normal(); + } else + *active_on = *active_off = ""; +} + +static void print_status_info( + sd_bus *bus, + UnitStatusInfo *i, + bool *ellipsized) { + + char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX]; + const char *s1, *s2, *active_on, *active_off, *on, *off, *ss; + _cleanup_free_ char *formatted_path = NULL; + ExecStatusInfo *p; + usec_t timestamp; + const char *path; + char **t, **t2; + int r; + + assert(i); + + /* This shows pretty information about a unit. See + * print_property() for a low-level property printer */ + + format_active_state(i->active_state, &active_on, &active_off); + + printf("%s%s%s %s", active_on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), active_off, strna(i->id)); + + if (i->description && !streq_ptr(i->id, i->description)) + printf(" - %s", i->description); + + printf("\n"); + + if (i->following) + printf(" Follow: unit currently follows state of %s\n", i->following); + + if (STRPTR_IN_SET(i->load_state, "error", "not-found", "bad-setting")) { + on = ansi_highlight_red(); + off = ansi_normal(); + } else + on = off = ""; + + path = i->source_path ?: i->fragment_path; + if (path && terminal_urlify_path(path, NULL, &formatted_path) >= 0) + path = formatted_path; + + if (!isempty(i->load_error)) + printf(" Loaded: %s%s%s (Reason: %s)\n", + on, strna(i->load_state), off, i->load_error); + else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset) && + !STR_IN_SET(i->unit_file_state, "generated", "transient")) + printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n", + on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset); + else if (path && !isempty(i->unit_file_state)) + printf(" Loaded: %s%s%s (%s; %s)\n", + on, strna(i->load_state), off, path, i->unit_file_state); + else if (path) + printf(" Loaded: %s%s%s (%s)\n", + on, strna(i->load_state), off, path); + else + printf(" Loaded: %s%s%s\n", + on, strna(i->load_state), off); + + if (i->transient) + printf(" Transient: yes\n"); + + if (!strv_isempty(i->dropin_paths)) { + _cleanup_free_ char *dir = NULL; + bool last = false; + char ** dropin; + + STRV_FOREACH(dropin, i->dropin_paths) { + _cleanup_free_ char *dropin_formatted = NULL; + const char *df; + + if (!dir || last) { + printf(dir ? " " : + " Drop-In: "); + + dir = mfree(dir); + + dir = dirname_malloc(*dropin); + if (!dir) { + log_oom(); + return; + } + + printf("%s\n" + " %s", dir, + special_glyph(SPECIAL_GLYPH_TREE_RIGHT)); + } + + last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir)); + + if (terminal_urlify_path(*dropin, basename(*dropin), &dropin_formatted) >= 0) + df = dropin_formatted; + else + df = *dropin; + + printf("%s%s", df, last ? "\n" : ", "); + } + } + + ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state; + if (ss) + printf(" Active: %s%s (%s)%s", + active_on, strna(i->active_state), ss, active_off); + else + printf(" Active: %s%s%s", + active_on, strna(i->active_state), active_off); + + if (!isempty(i->result) && !streq(i->result, "success")) + printf(" (Result: %s)", i->result); + + timestamp = STRPTR_IN_SET(i->active_state, "active", "reloading") ? i->active_enter_timestamp : + STRPTR_IN_SET(i->active_state, "inactive", "failed") ? i->inactive_enter_timestamp : + STRPTR_IN_SET(i->active_state, "activating") ? i->inactive_exit_timestamp : + i->active_exit_timestamp; + + s1 = format_timestamp_relative(since1, sizeof(since1), timestamp); + s2 = format_timestamp(since2, sizeof(since2), timestamp); + + if (s1) + printf(" since %s; %s\n", s2, s1); + else if (s2) + printf(" since %s\n", s2); + else + printf("\n"); + + STRV_FOREACH(t, i->triggered_by) { + UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID; + + (void) get_state_one_unit(bus, *t, &state); + format_active_state(unit_active_state_to_string(state), &on, &off); + + printf("%s %s%s%s %s\n", + t == i->triggered_by ? "TriggeredBy:" : " ", + on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, + *t); + } + + if (endswith(i->id, ".timer")) { + char tstamp1[FORMAT_TIMESTAMP_RELATIVE_MAX], + tstamp2[FORMAT_TIMESTAMP_MAX]; + const char *next_rel_time, *next_time; + dual_timestamp nw, next = {i->next_elapse_real, + i->next_elapse_monotonic}; + usec_t next_elapse; + + printf(" Trigger: "); + + dual_timestamp_get(&nw); + next_elapse = calc_next_elapse(&nw, &next); + next_rel_time = format_timestamp_relative(tstamp1, sizeof tstamp1, next_elapse); + next_time = format_timestamp(tstamp2, sizeof tstamp2, next_elapse); + + if (next_time && next_rel_time) + printf("%s; %s\n", next_time, next_rel_time); + else + printf("n/a\n"); + } + + STRV_FOREACH(t, i->triggers) { + UnitActiveState state = _UNIT_ACTIVE_STATE_INVALID; + + (void) get_state_one_unit(bus, *t, &state); + format_active_state(unit_active_state_to_string(state), &on, &off); + + printf("%s %s%s%s %s\n", + t == i->triggers ? " Triggers:" : " ", + on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, + *t); + } + + if (!i->condition_result && i->condition_timestamp > 0) { + UnitCondition *c; + int n = 0; + + s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp); + s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp); + + printf(" Condition: start %scondition failed%s at %s%s%s\n", + ansi_highlight_yellow(), ansi_normal(), + s2, s1 ? "; " : "", strempty(s1)); + + LIST_FOREACH(conditions, c, i->conditions) + if (c->tristate < 0) + n++; + + LIST_FOREACH(conditions, c, i->conditions) + if (c->tristate < 0) + printf(" %s %s=%s%s%s was not met\n", + --n ? special_glyph(SPECIAL_GLYPH_TREE_BRANCH) : special_glyph(SPECIAL_GLYPH_TREE_RIGHT), + c->name, + c->trigger ? "|" : "", + c->negate ? "!" : "", + c->param); + } + + if (!i->assert_result && i->assert_timestamp > 0) { + s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp); + s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp); + + printf(" Assert: start %sassertion failed%s at %s%s%s\n", + ansi_highlight_red(), ansi_normal(), + s2, s1 ? "; " : "", strempty(s1)); + if (i->failed_assert_trigger) + printf(" none of the trigger assertions were met\n"); + else if (i->failed_assert) + printf(" %s=%s%s was not met\n", + i->failed_assert, + i->failed_assert_negate ? "!" : "", + i->failed_assert_parameter); + } + + if (i->sysfs_path) + printf(" Device: %s\n", i->sysfs_path); + if (i->where) + printf(" Where: %s\n", i->where); + if (i->what) + printf(" What: %s\n", i->what); + + STRV_FOREACH(t, i->documentation) { + _cleanup_free_ char *formatted = NULL; + const char *q; + + if (terminal_urlify(*t, NULL, &formatted) >= 0) + q = formatted; + else + q = *t; + + printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", q); + } + + STRV_FOREACH_PAIR(t, t2, i->listen) + printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t); + + if (i->accept) { + printf(" Accepted: %u; Connected: %u;", i->n_accepted, i->n_connections); + if (i->n_refused) + printf(" Refused: %u", i->n_refused); + printf("\n"); + } + + LIST_FOREACH(exec, p, i->exec) { + _cleanup_free_ char *argv = NULL; + bool good; + + /* Only show exited processes here */ + if (p->code == 0) + continue; + + /* Don't print ExecXYZEx= properties here since it will appear as a + * duplicate of the non-Ex= variant. */ + if (endswith(p->name, "Ex")) + continue; + + argv = strv_join(p->argv, " "); + printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv)); + + good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL); + if (!good) { + on = ansi_highlight_red(); + off = ansi_normal(); + } else + on = off = ""; + + printf("%s(code=%s, ", on, sigchld_code_to_string(p->code)); + + if (p->code == CLD_EXITED) { + const char *c; + + printf("status=%i", p->status); + + c = exit_status_to_string(p->status, EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD); + if (c) + printf("/%s", c); + + } else + printf("signal=%s", signal_to_string(p->status)); + + printf(")%s\n", off); + + if (i->main_pid == p->pid && + i->start_timestamp == p->start_timestamp && + i->exit_timestamp == p->start_timestamp) + /* Let's not show this twice */ + i->main_pid = 0; + + if (p->pid == i->control_pid) + i->control_pid = 0; + } + + if (i->main_pid > 0 || i->control_pid > 0) { + if (i->main_pid > 0) { + printf(" Main PID: "PID_FMT, i->main_pid); + + if (i->running) { + + if (arg_transport == BUS_TRANSPORT_LOCAL) { + _cleanup_free_ char *comm = NULL; + + (void) get_process_comm(i->main_pid, &comm); + if (comm) + printf(" (%s)", comm); + } + + } else if (i->exit_code > 0) { + printf(" (code=%s, ", sigchld_code_to_string(i->exit_code)); + + if (i->exit_code == CLD_EXITED) { + const char *c; + + printf("status=%i", i->exit_status); + + c = exit_status_to_string(i->exit_status, + EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD); + if (c) + printf("/%s", c); + + } else + printf("signal=%s", signal_to_string(i->exit_status)); + printf(")"); + } + } + + if (i->control_pid > 0) { + _cleanup_free_ char *c = NULL; + + if (i->main_pid > 0) + fputs("; Control PID: ", stdout); + else + fputs("Cntrl PID: ", stdout); /* if first in column, abbreviated so it fits alignment */ + + printf(PID_FMT, i->control_pid); + + if (arg_transport == BUS_TRANSPORT_LOCAL) { + (void) get_process_comm(i->control_pid, &c); + if (c) + printf(" (%s)", c); + } + } + + printf("\n"); + } + + if (i->status_text) + printf(" Status: \"%s\"\n", i->status_text); + if (i->status_errno > 0) + printf(" Error: %i (%s)\n", i->status_errno, strerror_safe(i->status_errno)); + + if (i->ip_ingress_bytes != (uint64_t) -1 && i->ip_egress_bytes != (uint64_t) -1) { + char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX]; + + printf(" IP: %s in, %s out\n", + format_bytes(buf_in, sizeof(buf_in), i->ip_ingress_bytes), + format_bytes(buf_out, sizeof(buf_out), i->ip_egress_bytes)); + } + + if (i->io_read_bytes != UINT64_MAX && i->io_write_bytes != UINT64_MAX) { + char buf_in[FORMAT_BYTES_MAX], buf_out[FORMAT_BYTES_MAX]; + + printf(" IO: %s read, %s written\n", + format_bytes(buf_in, sizeof(buf_in), i->io_read_bytes), + format_bytes(buf_out, sizeof(buf_out), i->io_write_bytes)); + } + + if (i->tasks_current != (uint64_t) -1) { + printf(" Tasks: %" PRIu64, i->tasks_current); + + if (i->tasks_max != (uint64_t) -1) + printf(" (limit: %" PRIu64 ")\n", i->tasks_max); + else + printf("\n"); + } + + if (i->memory_current != (uint64_t) -1) { + char buf[FORMAT_BYTES_MAX]; + + printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current)); + + if (i->memory_min > 0 || i->memory_low > 0 || + i->memory_high != CGROUP_LIMIT_MAX || i->memory_max != CGROUP_LIMIT_MAX || + i->memory_swap_max != CGROUP_LIMIT_MAX || + i->memory_limit != CGROUP_LIMIT_MAX) { + const char *prefix = ""; + + printf(" ("); + if (i->memory_min > 0) { + printf("%smin: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_min)); + prefix = " "; + } + if (i->memory_low > 0) { + printf("%slow: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_low)); + prefix = " "; + } + if (i->memory_high != CGROUP_LIMIT_MAX) { + printf("%shigh: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_high)); + prefix = " "; + } + if (i->memory_max != CGROUP_LIMIT_MAX) { + printf("%smax: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_max)); + prefix = " "; + } + if (i->memory_swap_max != CGROUP_LIMIT_MAX) { + printf("%sswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_swap_max)); + prefix = " "; + } + if (i->memory_limit != CGROUP_LIMIT_MAX) { + printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit)); + prefix = " "; + } + printf(")"); + } + printf("\n"); + } + + if (i->cpu_usage_nsec != (uint64_t) -1) { + char buf[FORMAT_TIMESPAN_MAX]; + printf(" CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC)); + } + + if (i->control_group) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + static const char prefix[] = " "; + unsigned c; + + printf(" CGroup: %s\n", i->control_group); + + c = columns(); + if (c > sizeof(prefix) - 1) + c -= sizeof(prefix) - 1; + else + c = 0; + + r = unit_show_processes(bus, i->id, i->control_group, prefix, c, get_output_flags(), &error); + if (r == -EBADR) { + unsigned k = 0; + pid_t extra[2]; + + /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */ + + if (i->main_pid > 0) + extra[k++] = i->main_pid; + + if (i->control_pid > 0) + extra[k++] = i->control_pid; + + show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, extra, k, get_output_flags()); + } else if (r < 0) + log_warning_errno(r, "Failed to dump process list for '%s', ignoring: %s", + i->id, bus_error_message(&error, r)); + } + + if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) + show_journal_by_unit( + stdout, + i->id, + arg_output, + 0, + i->inactive_exit_timestamp_monotonic, + arg_lines, + getuid(), + get_output_flags() | OUTPUT_BEGIN_NEWLINE, + SD_JOURNAL_LOCAL_ONLY, + arg_scope == UNIT_FILE_SYSTEM, + ellipsized); + + if (i->need_daemon_reload) + warn_unit_file_changed(i->id); +} + +static void show_unit_help(UnitStatusInfo *i) { + char **p; + + assert(i); + + if (!i->documentation) { + log_info("Documentation for %s not known.", i->id); + return; + } + + STRV_FOREACH(p, i->documentation) + if (startswith(*p, "man:")) + show_man_page(*p + 4, false); + else + log_info("Can't show: %s", *p); +} + +static int map_main_pid(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + UnitStatusInfo *i = userdata; + uint32_t u; + int r; + + r = sd_bus_message_read(m, "u", &u); + if (r < 0) + return r; + + i->main_pid = (pid_t) u; + i->running = u > 0; + + return 0; +} + +static int map_load_error(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + const char *message, **p = userdata; + int r; + + r = sd_bus_message_read(m, "(ss)", NULL, &message); + if (r < 0) + return r; + + if (!isempty(message)) + *p = message; + + return 0; +} + +static int map_listen(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + const char *type, *path; + char ***p = userdata; + int r; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) { + + r = strv_extend(p, type); + if (r < 0) + return r; + + r = strv_extend(p, path); + if (r < 0) + return r; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +static int map_conditions(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + UnitStatusInfo *i = userdata; + const char *cond, *param; + int trigger, negate; + int32_t state; + int r; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) { + _cleanup_(unit_condition_freep) UnitCondition *c = NULL; + + c = new(UnitCondition, 1); + if (!c) + return -ENOMEM; + + *c = (UnitCondition) { + .name = strdup(cond), + .param = strdup(param), + .trigger = trigger, + .negate = negate, + .tristate = state, + }; + + if (!c->name || !c->param) + return -ENOMEM; + + LIST_PREPEND(conditions, i->conditions, TAKE_PTR(c)); + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +static int map_asserts(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + UnitStatusInfo *i = userdata; + const char *cond, *param; + int trigger, negate; + int32_t state; + int r; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)"); + if (r < 0) + return r; + + while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) { + if (state < 0 && (!trigger || !i->failed_assert)) { + i->failed_assert = cond; + i->failed_assert_trigger = trigger; + i->failed_assert_negate = negate; + i->failed_assert_parameter = param; + } + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + _cleanup_free_ ExecStatusInfo *info = NULL; + ExecStatusInfo *last; + UnitStatusInfo *i = userdata; + bool is_ex_prop = endswith(member, "Ex"); + int r; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, is_ex_prop ? "(sasasttttuii)" : "(sasbttttuii)"); + if (r < 0) + return r; + + info = new0(ExecStatusInfo, 1); + if (!info) + return -ENOMEM; + + LIST_FIND_TAIL(exec, i->exec, last); + + while ((r = exec_status_info_deserialize(m, info, is_ex_prop)) > 0) { + + info->name = strdup(member); + if (!info->name) + return -ENOMEM; + + LIST_INSERT_AFTER(exec, i->exec, last, info); + last = info; + + info = new0(ExecStatusInfo, 1); + if (!info) + return -ENOMEM; + } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +} + +static int print_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) { + char bus_type; + const char *contents; + int r; + + assert(name); + assert(m); + + /* This is a low-level property printer, see + * print_status_info() for the nicer output */ + + r = sd_bus_message_peek_type(m, &bus_type, &contents); + if (r < 0) + return r; + + switch (bus_type) { + + case SD_BUS_TYPE_INT32: + if (endswith(name, "ActionExitStatus")) { + int32_t i; + + r = sd_bus_message_read_basic(m, bus_type, &i); + if (r < 0) + return r; + + if (i >= 0 && i <= 255) + bus_print_property_valuef(name, expected_value, value, "%"PRIi32, i); + else if (all) + bus_print_property_value(name, expected_value, value, "[not set]"); + + return 1; + } else if (streq(name, "NUMAPolicy")) { + int32_t i; + + r = sd_bus_message_read_basic(m, bus_type, &i); + if (r < 0) + return r; + + bus_print_property_valuef(name, expected_value, value, "%s", strna(mpol_to_string(i))); + + return 1; + } + break; + + case SD_BUS_TYPE_STRUCT: + + if (contents[0] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) { + uint32_t u; + + r = sd_bus_message_read(m, "(uo)", &u, NULL); + if (r < 0) + return bus_log_parse_error(r); + + if (u > 0) + bus_print_property_valuef(name, expected_value, value, "%"PRIu32, u); + else if (all) + bus_print_property_value(name, expected_value, value, ""); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "Unit")) { + const char *s; + + r = sd_bus_message_read(m, "(so)", &s, NULL); + if (r < 0) + return bus_log_parse_error(r); + + if (all || !isempty(s)) + bus_print_property_value(name, expected_value, value, s); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) { + const char *a = NULL, *b = NULL; + + r = sd_bus_message_read(m, "(ss)", &a, &b); + if (r < 0) + return bus_log_parse_error(r); + + if (!isempty(a) || !isempty(b)) + bus_print_property_valuef(name, expected_value, value, "%s \"%s\"", strempty(a), strempty(b)); + else if (all) + bus_print_property_value(name, expected_value, value, ""); + + return 1; + + } else if (STR_IN_SET(name, "SystemCallFilter", "RestrictAddressFamilies")) { + _cleanup_strv_free_ char **l = NULL; + int whitelist; + + r = sd_bus_message_enter_container(m, 'r', "bas"); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read(m, "b", &whitelist); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_strv(m, &l); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + if (all || whitelist || !strv_isempty(l)) { + bool first = true; + char **i; + + if (!value) { + fputs(name, stdout); + fputc('=', stdout); + } + + if (!whitelist) + fputc('~', stdout); + + STRV_FOREACH(i, l) { + if (first) + first = false; + else + fputc(' ', stdout); + + fputs(*i, stdout); + } + fputc('\n', stdout); + } + + return 1; + + } else if (STR_IN_SET(name, "SELinuxContext", "AppArmorProfile", "SmackProcessLabel")) { + int ignore; + const char *s; + + r = sd_bus_message_read(m, "(bs)", &ignore, &s); + if (r < 0) + return bus_log_parse_error(r); + + if (!isempty(s)) + bus_print_property_valuef(name, expected_value, value, "%s%s", ignore ? "-" : "", s); + else if (all) + bus_print_property_value(name, expected_value, value, ""); + + return 1; + + } else if (endswith(name, "ExitStatus") && streq(contents, "aiai")) { + const int32_t *status, *signal; + size_t n_status, n_signal, i; + + r = sd_bus_message_enter_container(m, 'r', "aiai"); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_array(m, 'i', (const void **) &status, &n_status); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_array(m, 'i', (const void **) &signal, &n_signal); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + n_status /= sizeof(int32_t); + n_signal /= sizeof(int32_t); + + if (all || n_status > 0 || n_signal > 0) { + bool first = true; + + if (!value) { + fputs(name, stdout); + fputc('=', stdout); + } + + for (i = 0; i < n_status; i++) { + if (first) + first = false; + else + fputc(' ', stdout); + + printf("%"PRIi32, status[i]); + } + + for (i = 0; i < n_signal; i++) { + const char *str; + + str = signal_to_string((int) signal[i]); + + if (first) + first = false; + else + fputc(' ', stdout); + + if (str) + fputs(str, stdout); + else + printf("%"PRIi32, status[i]); + } + + fputc('\n', stdout); + } + return 1; + } + + break; + + case SD_BUS_TYPE_ARRAY: + + if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) { + const char *path; + int ignore; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0) + bus_print_property_valuef(name, expected_value, value, "%s (ignore_errors=%s)", path, yes_no(ignore)); + + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) { + const char *type, *path; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) + bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) { + const char *type, *path; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) + bus_print_property_valuef(name, expected_value, value, "%s (%s)", path, type); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersMonotonic")) { + const char *base; + uint64_t v, next_elapse; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(stt)", &base, &v, &next_elapse)) > 0) { + char timespan1[FORMAT_TIMESPAN_MAX] = "n/a", timespan2[FORMAT_TIMESPAN_MAX] = "n/a"; + + (void) format_timespan(timespan1, sizeof timespan1, v, 0); + (void) format_timespan(timespan2, sizeof timespan2, next_elapse, 0); + + bus_print_property_valuef(name, expected_value, value, + "{ %s=%s ; next_elapse=%s }", base, timespan1, timespan2); + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "TimersCalendar")) { + const char *base, *spec; + uint64_t next_elapse; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sst)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(sst)", &base, &spec, &next_elapse)) > 0) { + char timestamp[FORMAT_TIMESTAMP_MAX] = "n/a"; + + (void) format_timestamp(timestamp, sizeof(timestamp), next_elapse); + bus_print_property_valuef(name, expected_value, value, + "{ %s=%s ; next_elapse=%s }", base, spec, timestamp); + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) { + ExecStatusInfo info = {}; + bool is_ex_prop = endswith(name, "Ex"); + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, is_ex_prop ? "(sasasttttuii)" : "(sasbttttuii)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = exec_status_info_deserialize(m, &info, is_ex_prop)) > 0) { + char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX]; + _cleanup_strv_free_ char **optv = NULL; + _cleanup_free_ char *tt, *o = NULL; + + tt = strv_join(info.argv, " "); + + if (is_ex_prop) { + r = exec_command_flags_to_strv(info.flags, &optv); + if (r < 0) + return log_error_errno(r, "Failed to convert ExecCommandFlags to strv: %m"); + + o = strv_join(optv, " "); + + bus_print_property_valuef(name, expected_value, value, + "{ path=%s ; argv[]=%s ; flags=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }", + strna(info.path), + strna(tt), + strna(o), + strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)), + strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)), + info.pid, + sigchld_code_to_string(info.code), + info.status, + info.code == CLD_EXITED ? "" : "/", + strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status))); + } else + bus_print_property_valuef(name, expected_value, value, + "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }", + strna(info.path), + strna(tt), + yes_no(info.ignore), + strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)), + strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)), + info.pid, + sigchld_code_to_string(info.code), + info.status, + info.code == CLD_EXITED ? "" : "/", + strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status))); + + free(info.path); + strv_free(info.argv); + zero(info); + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) { + const char *path, *rwm; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0) + bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path), strna(rwm)); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && + STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) { + const char *path; + uint64_t weight; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0) + bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), weight); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && + (cgroup_io_limit_type_from_string(name) >= 0 || + STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) { + const char *path; + uint64_t bandwidth; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0) + bus_print_property_valuef(name, expected_value, value, "%s %"PRIu64, strna(path), bandwidth); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_STRUCT_BEGIN && + streq(name, "IODeviceLatencyTargetUSec")) { + char ts[FORMAT_TIMESPAN_MAX]; + const char *path; + uint64_t target; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(st)", &path, &target)) > 0) + bus_print_property_valuef(name, expected_value, value, "%s %s", strna(path), + format_timespan(ts, sizeof(ts), target, 1)); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + return 1; + + } else if (contents[0] == SD_BUS_TYPE_BYTE && streq(name, "StandardInputData")) { + _cleanup_free_ char *h = NULL; + const void *p; + size_t sz; + ssize_t n; + + r = sd_bus_message_read_array(m, 'y', &p, &sz); + if (r < 0) + return bus_log_parse_error(r); + + n = base64mem(p, sz, &h); + if (n < 0) + return log_oom(); + + bus_print_property_value(name, expected_value, value, h); + + return 1; + + } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) { + _cleanup_free_ char *addresses = NULL; + + r = sd_bus_message_enter_container(m, 'a', "(iayu)"); + if (r < 0) + return bus_log_parse_error(r); + + for (;;) { + _cleanup_free_ char *str = NULL; + uint32_t prefixlen; + int32_t family; + const void *ap; + size_t an; + + r = sd_bus_message_enter_container(m, 'r', "iayu"); + if (r < 0) + return bus_log_parse_error(r); + if (r == 0) + break; + + r = sd_bus_message_read(m, "i", &family); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read_array(m, 'y', &ap, &an); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_read(m, "u", &prefixlen); + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + if (!IN_SET(family, AF_INET, AF_INET6)) + continue; + + if (an != FAMILY_ADDRESS_SIZE(family)) + continue; + + if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8) + continue; + + if (in_addr_prefix_to_string(family, (union in_addr_union *) ap, prefixlen, &str) < 0) + continue; + + if (!strextend_with_separator(&addresses, " ", str, NULL)) + return log_oom(); + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + if (all || !isempty(addresses)) + bus_print_property_value(name, expected_value, value, strempty(addresses)); + + return 1; + + } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) { + _cleanup_free_ char *paths = NULL; + const char *source, *dest; + int ignore_enoent; + uint64_t rbind; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssbt)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(ssbt)", &source, &dest, &ignore_enoent, &rbind)) > 0) { + _cleanup_free_ char *str = NULL; + + if (isempty(source)) + continue; + + if (asprintf(&str, "%s%s%s%s%s", + ignore_enoent ? "-" : "", + source, + isempty(dest) ? "" : ":", + strempty(dest), + rbind == MS_REC ? ":rbind" : "") < 0) + return log_oom(); + + if (!strextend_with_separator(&paths, " ", str, NULL)) + return log_oom(); + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + if (all || !isempty(paths)) + bus_print_property_value(name, expected_value, value, strempty(paths)); + + return 1; + + } else if (streq(name, "TemporaryFileSystem")) { + _cleanup_free_ char *paths = NULL; + const char *target, *option; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(m, "(ss)", &target, &option)) > 0) { + _cleanup_free_ char *str = NULL; + + if (isempty(target)) + continue; + + if (asprintf(&str, "%s%s%s", target, isempty(option) ? "" : ":", strempty(option)) < 0) + return log_oom(); + + if (!strextend_with_separator(&paths, " ", str, NULL)) + return log_oom(); + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + if (all || !isempty(paths)) + bus_print_property_value(name, expected_value, value, strempty(paths)); + + return 1; + + } else if (streq(name, "LogExtraFields")) { + _cleanup_free_ char *fields = NULL; + const void *p; + size_t sz; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "ay"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read_array(m, 'y', &p, &sz)) > 0) { + _cleanup_free_ char *str = NULL; + const char *eq; + + if (memchr(p, 0, sz)) + continue; + + eq = memchr(p, '=', sz); + if (!eq) + continue; + + if (!journal_field_valid(p, eq - (const char*) p, false)) + continue; + + str = malloc(sz + 1); + if (!str) + return log_oom(); + + memcpy(str, p, sz); + str[sz] = '\0'; + + if (!utf8_is_valid(str)) + continue; + + if (!strextend_with_separator(&fields, " ", str, NULL)) + return log_oom(); + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(m); + if (r < 0) + return bus_log_parse_error(r); + + if (all || !isempty(fields)) + bus_print_property_value(name, expected_value, value, strempty(fields)); + + return 1; + } else if (contents[0] == SD_BUS_TYPE_BYTE && STR_IN_SET(name, "CPUAffinity", "NUMAMask", "AllowedCPUs", "AllowedMemoryNodes", "EffectiveCPUs", "EffectiveMemoryNodes")) { + _cleanup_free_ char *affinity = NULL; + _cleanup_(cpu_set_reset) CPUSet set = {}; + const void *a; + size_t n; + + r = sd_bus_message_read_array(m, 'y', &a, &n); + if (r < 0) + return bus_log_parse_error(r); + + r = cpu_set_from_dbus(a, n, &set); + if (r < 0) + return log_error_errno(r, "Failed to deserialize %s: %m", name); + + affinity = cpu_set_to_range_string(&set); + if (!affinity) + return log_oom(); + + bus_print_property_value(name, expected_value, value, affinity); + + return 1; + } + + break; + } + + return 0; +} + +typedef enum SystemctlShowMode{ + SYSTEMCTL_SHOW_PROPERTIES, + SYSTEMCTL_SHOW_STATUS, + SYSTEMCTL_SHOW_HELP, + _SYSTEMCTL_SHOW_MODE_MAX, + _SYSTEMCTL_SHOW_MODE_INVALID = -1, +} SystemctlShowMode; + +static const char* const systemctl_show_mode_table[_SYSTEMCTL_SHOW_MODE_MAX] = { + [SYSTEMCTL_SHOW_PROPERTIES] = "show", + [SYSTEMCTL_SHOW_STATUS] = "status", + [SYSTEMCTL_SHOW_HELP] = "help", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(systemctl_show_mode, SystemctlShowMode); + +static int show_one( + sd_bus *bus, + const char *path, + const char *unit, + SystemctlShowMode show_mode, + bool *new_line, + bool *ellipsized) { + + static const struct bus_properties_map property_map[] = { + { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) }, + { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) }, + { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) }, + {} + }, status_map[] = { + { "Id", "s", NULL, offsetof(UnitStatusInfo, id) }, + { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) }, + { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) }, + { "SubState", "s", NULL, offsetof(UnitStatusInfo, sub_state) }, + { "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) }, + { "UnitFilePreset", "s", NULL, offsetof(UnitStatusInfo, unit_file_preset) }, + { "Description", "s", NULL, offsetof(UnitStatusInfo, description) }, + { "Following", "s", NULL, offsetof(UnitStatusInfo, following) }, + { "Documentation", "as", NULL, offsetof(UnitStatusInfo, documentation) }, + { "FragmentPath", "s", NULL, offsetof(UnitStatusInfo, fragment_path) }, + { "SourcePath", "s", NULL, offsetof(UnitStatusInfo, source_path) }, + { "ControlGroup", "s", NULL, offsetof(UnitStatusInfo, control_group) }, + { "DropInPaths", "as", NULL, offsetof(UnitStatusInfo, dropin_paths) }, + { "LoadError", "(ss)", map_load_error, offsetof(UnitStatusInfo, load_error) }, + { "Result", "s", NULL, offsetof(UnitStatusInfo, result) }, + { "TriggeredBy", "as", NULL, offsetof(UnitStatusInfo, triggered_by) }, + { "Triggers", "as", NULL, offsetof(UnitStatusInfo, triggers) }, + { "InactiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp) }, + { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(UnitStatusInfo, inactive_exit_timestamp_monotonic) }, + { "ActiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_enter_timestamp) }, + { "ActiveExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, active_exit_timestamp) }, + { "InactiveEnterTimestamp", "t", NULL, offsetof(UnitStatusInfo, inactive_enter_timestamp) }, + { "NeedDaemonReload", "b", NULL, offsetof(UnitStatusInfo, need_daemon_reload) }, + { "Transient", "b", NULL, offsetof(UnitStatusInfo, transient) }, + { "ExecMainPID", "u", NULL, offsetof(UnitStatusInfo, main_pid) }, + { "MainPID", "u", map_main_pid, 0 }, + { "ControlPID", "u", NULL, offsetof(UnitStatusInfo, control_pid) }, + { "StatusText", "s", NULL, offsetof(UnitStatusInfo, status_text) }, + { "PIDFile", "s", NULL, offsetof(UnitStatusInfo, pid_file) }, + { "StatusErrno", "i", NULL, offsetof(UnitStatusInfo, status_errno) }, + { "ExecMainStartTimestamp", "t", NULL, offsetof(UnitStatusInfo, start_timestamp) }, + { "ExecMainExitTimestamp", "t", NULL, offsetof(UnitStatusInfo, exit_timestamp) }, + { "ExecMainCode", "i", NULL, offsetof(UnitStatusInfo, exit_code) }, + { "ExecMainStatus", "i", NULL, offsetof(UnitStatusInfo, exit_status) }, + { "ConditionTimestamp", "t", NULL, offsetof(UnitStatusInfo, condition_timestamp) }, + { "ConditionResult", "b", NULL, offsetof(UnitStatusInfo, condition_result) }, + { "Conditions", "a(sbbsi)", map_conditions, 0 }, + { "AssertTimestamp", "t", NULL, offsetof(UnitStatusInfo, assert_timestamp) }, + { "AssertResult", "b", NULL, offsetof(UnitStatusInfo, assert_result) }, + { "Asserts", "a(sbbsi)", map_asserts, 0 }, + { "NextElapseUSecRealtime", "t", NULL, offsetof(UnitStatusInfo, next_elapse_real) }, + { "NextElapseUSecMonotonic", "t", NULL, offsetof(UnitStatusInfo, next_elapse_monotonic) }, + { "NAccepted", "u", NULL, offsetof(UnitStatusInfo, n_accepted) }, + { "NConnections", "u", NULL, offsetof(UnitStatusInfo, n_connections) }, + { "NRefused", "u", NULL, offsetof(UnitStatusInfo, n_refused) }, + { "Accept", "b", NULL, offsetof(UnitStatusInfo, accept) }, + { "Listen", "a(ss)", map_listen, offsetof(UnitStatusInfo, listen) }, + { "SysFSPath", "s", NULL, offsetof(UnitStatusInfo, sysfs_path) }, + { "Where", "s", NULL, offsetof(UnitStatusInfo, where) }, + { "What", "s", NULL, offsetof(UnitStatusInfo, what) }, + { "MemoryCurrent", "t", NULL, offsetof(UnitStatusInfo, memory_current) }, + { "DefaultMemoryMin", "t", NULL, offsetof(UnitStatusInfo, default_memory_min) }, + { "DefaultMemoryLow", "t", NULL, offsetof(UnitStatusInfo, default_memory_low) }, + { "MemoryMin", "t", NULL, offsetof(UnitStatusInfo, memory_min) }, + { "MemoryLow", "t", NULL, offsetof(UnitStatusInfo, memory_low) }, + { "MemoryHigh", "t", NULL, offsetof(UnitStatusInfo, memory_high) }, + { "MemoryMax", "t", NULL, offsetof(UnitStatusInfo, memory_max) }, + { "MemorySwapMax", "t", NULL, offsetof(UnitStatusInfo, memory_swap_max) }, + { "MemoryLimit", "t", NULL, offsetof(UnitStatusInfo, memory_limit) }, + { "CPUUsageNSec", "t", NULL, offsetof(UnitStatusInfo, cpu_usage_nsec) }, + { "TasksCurrent", "t", NULL, offsetof(UnitStatusInfo, tasks_current) }, + { "TasksMax", "t", NULL, offsetof(UnitStatusInfo, tasks_max) }, + { "IPIngressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_ingress_bytes) }, + { "IPEgressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_egress_bytes) }, + { "IOReadBytes", "t", NULL, offsetof(UnitStatusInfo, io_read_bytes) }, + { "IOWriteBytes", "t", NULL, offsetof(UnitStatusInfo, io_write_bytes) }, + { "ExecCondition", "a(sasbttttuii)", map_exec, 0 }, + { "ExecConditionEx", "a(sasasttttuii)", map_exec, 0 }, + { "ExecStartPre", "a(sasbttttuii)", map_exec, 0 }, + { "ExecStartPreEx", "a(sasasttttuii)", map_exec, 0 }, + { "ExecStart", "a(sasbttttuii)", map_exec, 0 }, + { "ExecStartEx", "a(sasasttttuii)", map_exec, 0 }, + { "ExecStartPost", "a(sasbttttuii)", map_exec, 0 }, + { "ExecStartPostEx", "a(sasasttttuii)", map_exec, 0 }, + { "ExecReload", "a(sasbttttuii)", map_exec, 0 }, + { "ExecReloadEx", "a(sasasttttuii)", map_exec, 0 }, + { "ExecStopPre", "a(sasbttttuii)", map_exec, 0 }, + { "ExecStop", "a(sasbttttuii)", map_exec, 0 }, + { "ExecStopEx", "a(sasasttttuii)", map_exec, 0 }, + { "ExecStopPost", "a(sasbttttuii)", map_exec, 0 }, + { "ExecStopPostEx", "a(sasasttttuii)", map_exec, 0 }, + {} + }; + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_set_free_ Set *found_properties = NULL; + _cleanup_(unit_status_info_free) UnitStatusInfo info = { + .memory_current = (uint64_t) -1, + .memory_high = CGROUP_LIMIT_MAX, + .memory_max = CGROUP_LIMIT_MAX, + .memory_swap_max = CGROUP_LIMIT_MAX, + .memory_limit = (uint64_t) -1, + .cpu_usage_nsec = (uint64_t) -1, + .tasks_current = (uint64_t) -1, + .tasks_max = (uint64_t) -1, + .ip_ingress_bytes = (uint64_t) -1, + .ip_egress_bytes = (uint64_t) -1, + .io_read_bytes = UINT64_MAX, + .io_write_bytes = UINT64_MAX, + }; + char **pp; + int r; + + assert(path); + assert(new_line); + + log_debug("Showing one %s", path); + + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + path, + show_mode == SYSTEMCTL_SHOW_STATUS ? status_map : property_map, + BUS_MAP_BOOLEAN_AS_BOOL, + &error, + &reply, + &info); + if (r < 0) + return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r)); + + if (unit && streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) { + log_full(show_mode == SYSTEMCTL_SHOW_STATUS ? LOG_ERR : LOG_DEBUG, + "Unit %s could not be found.", unit); + + if (show_mode == SYSTEMCTL_SHOW_STATUS) + return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN; + else if (show_mode == SYSTEMCTL_SHOW_HELP) + return -ENOENT; + } + + if (*new_line) + printf("\n"); + + *new_line = true; + + if (show_mode == SYSTEMCTL_SHOW_STATUS) { + print_status_info(bus, &info, ellipsized); + + if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading")) + return EXIT_PROGRAM_NOT_RUNNING; + + return EXIT_PROGRAM_RUNNING_OR_SERVICE_OK; + + } else if (show_mode == SYSTEMCTL_SHOW_HELP) { + show_unit_help(&info); + return 0; + } + + r = sd_bus_message_rewind(reply, true); + if (r < 0) + return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r)); + + r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_value, arg_all, &found_properties); + if (r < 0) + return bus_log_parse_error(r); + + STRV_FOREACH(pp, arg_properties) + if (!set_contains(found_properties, *pp)) + log_debug("Property %s does not exist.", *pp); + + return 0; +} + +static int get_unit_dbus_path_by_pid( + sd_bus *bus, + uint32_t pid, + char **unit) { + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + char *u; + int r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetUnitByPID", + &error, + &reply, + "u", pid); + if (r < 0) + return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "o", &u); + if (r < 0) + return bus_log_parse_error(r); + + u = strdup(u); + if (!u) + return log_oom(); + + *unit = u; + return 0; +} + +static int show_all( + sd_bus *bus, + bool *new_line, + bool *ellipsized) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_free_ UnitInfo *unit_infos = NULL; + const UnitInfo *u; + unsigned c; + int r, ret = 0; + + r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply); + if (r < 0) + return r; + + (void) pager_open(arg_pager_flags); + + c = (unsigned) r; + + typesafe_qsort(unit_infos, c, compare_unit_info); + + for (u = unit_infos; u < unit_infos + c; u++) { + _cleanup_free_ char *p = NULL; + + p = unit_dbus_path_from_name(u->id); + if (!p) + return log_oom(); + + r = show_one(bus, p, u->id, SYSTEMCTL_SHOW_STATUS, new_line, ellipsized); + if (r < 0) + return r; + else if (r > 0 && ret == 0) + ret = r; + } + + return ret; +} + +static int show_system_status(sd_bus *bus) { + char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX]; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(machine_info_clear) struct machine_info mi = {}; + _cleanup_free_ char *hn = NULL; + const char *on, *off; + int r; + + hn = gethostname_malloc(); + if (!hn) + return log_oom(); + + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + machine_info_property_map, + BUS_MAP_STRDUP, + &error, + NULL, + &mi); + if (r < 0) + return log_error_errno(r, "Failed to read server status: %s", bus_error_message(&error, r)); + + if (streq_ptr(mi.state, "degraded")) { + on = ansi_highlight_red(); + off = ansi_normal(); + } else if (streq_ptr(mi.state, "running")) { + on = ansi_highlight_green(); + off = ansi_normal(); + } else { + on = ansi_highlight_yellow(); + off = ansi_normal(); + } + + printf("%s%s%s %s\n", on, special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE), off, arg_host ? arg_host : hn); + + printf(" State: %s%s%s\n", + on, strna(mi.state), off); + + printf(" Jobs: %" PRIu32 " queued\n", mi.n_jobs); + printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units); + + printf(" Since: %s; %s\n", + format_timestamp(since2, sizeof(since2), mi.timestamp), + format_timestamp_relative(since1, sizeof(since1), mi.timestamp)); + + printf(" CGroup: %s\n", mi.control_group ?: "/"); + if (IN_SET(arg_transport, + BUS_TRANSPORT_LOCAL, + BUS_TRANSPORT_MACHINE)) { + static const char prefix[] = " "; + unsigned c; + + c = columns(); + if (c > sizeof(prefix) - 1) + c -= sizeof(prefix) - 1; + else + c = 0; + + show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, get_output_flags()); + } + + return 0; +} + +static int show(int argc, char *argv[], void *userdata) { + bool new_line = false, ellipsized = false; + SystemctlShowMode show_mode; + int r, ret = 0; + sd_bus *bus; + + assert(argv); + + show_mode = systemctl_show_mode_from_string(argv[0]); + if (show_mode < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid argument."); + + if (show_mode == SYSTEMCTL_SHOW_HELP && argc <= 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This command expects one or more unit names. Did you mean --help?"); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + (void) pager_open(arg_pager_flags); + + /* If no argument is specified inspect the manager itself */ + if (show_mode == SYSTEMCTL_SHOW_PROPERTIES && argc <= 1) + return show_one(bus, "/org/freedesktop/systemd1", NULL, show_mode, &new_line, &ellipsized); + + if (show_mode == SYSTEMCTL_SHOW_STATUS && argc <= 1) { + + show_system_status(bus); + new_line = true; + + if (arg_all) + ret = show_all(bus, &new_line, &ellipsized); + } else { + _cleanup_free_ char **patterns = NULL; + char **name; + + STRV_FOREACH(name, strv_skip(argv, 1)) { + _cleanup_free_ char *path = NULL, *unit = NULL; + uint32_t id; + + if (safe_atou32(*name, &id) < 0) { + if (strv_push(&patterns, *name) < 0) + return log_oom(); + + continue; + } else if (show_mode == SYSTEMCTL_SHOW_PROPERTIES) { + /* Interpret as job id */ + if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0) + return log_oom(); + + } else { + /* Interpret as PID */ + r = get_unit_dbus_path_by_pid(bus, id, &path); + if (r < 0) { + ret = r; + continue; + } + + r = unit_name_from_dbus_path(path, &unit); + if (r < 0) + return log_oom(); + } + + r = show_one(bus, path, unit, show_mode, &new_line, &ellipsized); + if (r < 0) + return r; + else if (r > 0 && ret == 0) + ret = r; + } + + if (!strv_isempty(patterns)) { + _cleanup_strv_free_ char **names = NULL; + + r = expand_names(bus, patterns, NULL, &names, NULL); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + + STRV_FOREACH(name, names) { + _cleanup_free_ char *path; + + path = unit_dbus_path_from_name(*name); + if (!path) + return log_oom(); + + r = show_one(bus, path, *name, show_mode, &new_line, &ellipsized); + if (r < 0) + return r; + if (r > 0 && ret == 0) + ret = r; + } + } + } + + if (ellipsized && !arg_quiet) + printf("Hint: Some lines were ellipsized, use -l to show in full.\n"); + + return ret; +} + +static int cat(int argc, char *argv[], void *userdata) { + _cleanup_(lookup_paths_free) LookupPaths lp = {}; + _cleanup_strv_free_ char **names = NULL; + char **name; + sd_bus *bus; + bool first = true; + int r, rc = 0; + + /* Include all units by default — i.e. continue as if the --all + * option was used */ + if (strv_isempty(arg_states)) + arg_all = true; + + if (arg_transport != BUS_TRANSPORT_LOCAL) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot remotely cat units."); + + r = lookup_paths_init(&lp, arg_scope, 0, arg_root); + if (r < 0) + return log_error_errno(r, "Failed to determine unit paths: %m"); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = expand_names(bus, strv_skip(argv, 1), NULL, &names, NULL); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + + (void) pager_open(arg_pager_flags); + + STRV_FOREACH(name, names) { + _cleanup_free_ char *fragment_path = NULL; + _cleanup_strv_free_ char **dropin_paths = NULL; + + r = unit_find_paths(bus, *name, &lp, false, &fragment_path, &dropin_paths); + if (r == -ERFKILL) { + printf("%s# Unit %s is masked%s.\n", + ansi_highlight_magenta(), + *name, + ansi_normal()); + continue; + } + if (r == -EKEYREJECTED) { + printf("%s# Unit %s could not be loaded.%s\n", + ansi_highlight_magenta(), + *name, + ansi_normal()); + continue; + } + if (r < 0) + return r; + if (r == 0) { + /* Skip units which have no on-disk counterpart, but + * propagate the error to the user */ + rc = -ENOENT; + continue; + } + + if (first) + first = false; + else + puts(""); + + if (need_daemon_reload(bus, *name) > 0) /* ignore errors (<0), this is informational output */ + fprintf(stderr, + "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n" + "%s# This output shows the current version of the unit's original fragment and drop-in files.\n" + "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n" + "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n", + ansi_highlight_red(), + *name, + ansi_highlight_red(), + ansi_highlight_red(), + ansi_highlight_red(), + arg_scope == UNIT_FILE_SYSTEM ? "" : " --user", + ansi_normal()); + + r = cat_files(fragment_path, dropin_paths, 0); + if (r < 0) + return r; + } + + return rc; +} + +static int set_property(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *n = NULL; + UnitType t; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SetUnitProperties"); + if (r < 0) + return bus_log_create_error(r); + + r = unit_name_mangle(argv[1], arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, &n); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); + + t = unit_name_to_type(n); + if (t < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid unit type: %s", n); + + r = sd_bus_message_append(m, "sb", n, arg_runtime); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)"); + if (r < 0) + return bus_log_create_error(r); + + r = bus_append_unit_property_assignment_many(m, t, strv_skip(argv, 2)); + if (r < 0) + return r; + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to set unit properties on %s: %s", n, bus_error_message(&error, r)); + + return 0; +} + +static int daemon_reload(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + const char *method; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + switch (arg_action) { + + case ACTION_RELOAD: + method = "Reload"; + break; + + case ACTION_REEXEC: + method = "Reexecute"; + break; + + case ACTION_SYSTEMCTL: + method = streq(argv[0], "daemon-reexec") ? "Reexecute" : + /* "daemon-reload" */ "Reload"; + break; + + default: + assert_not_reached("Unexpected action"); + } + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + method); + if (r < 0) + return bus_log_create_error(r); + + /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which + * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have + * their timeout, and for everything else there's the same time budget in place. */ + + r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL); + + /* On reexecution, we expect a disconnect, not a reply */ + if (IN_SET(r, -ETIMEDOUT, -ECONNRESET) && streq(method, "Reexecute")) + r = 0; + + if (r < 0 && arg_action == ACTION_SYSTEMCTL) + return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r)); + + /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the + * old ways of doing things, hence don't log any error in that case here. */ + + return r < 0 ? r : 0; +} + +static int trivial_method(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *method; + sd_bus *bus; + int r; + + if (arg_dry_run) + return 0; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + method = + streq(argv[0], "clear-jobs") || + streq(argv[0], "cancel") ? "ClearJobs" : + streq(argv[0], "reset-failed") ? "ResetFailed" : + streq(argv[0], "halt") ? "Halt" : + streq(argv[0], "reboot") ? "Reboot" : + streq(argv[0], "kexec") ? "KExec" : + streq(argv[0], "exit") ? "Exit" : + /* poweroff */ "PowerOff"; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + method, + &error, + NULL, + NULL); + if (r < 0 && arg_action == ACTION_SYSTEMCTL) + return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r)); + + /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the + * old ways of doing things, hence don't log any error in that case here. */ + + return r < 0 ? r : 0; +} + +static int reset_failed(int argc, char *argv[], void *userdata) { + _cleanup_strv_free_ char **names = NULL; + sd_bus *bus; + char **name; + int r, q; + + if (argc <= 1) + return trivial_method(argc, argv, userdata); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + r = expand_names(bus, strv_skip(argv, 1), NULL, &names, NULL); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + + STRV_FOREACH(name, names) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + + q = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ResetFailedUnit", + &error, + NULL, + "s", *name); + if (q < 0) { + log_error_errno(q, "Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q)); + if (r == 0) + r = q; + } + } + + return r; +} + +static int print_variable(const char *s) { + const char *sep; + _cleanup_free_ char *esc = NULL; + + sep = strchr(s, '='); + if (!sep) + return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), + "Invalid environment block"); + + esc = shell_maybe_quote(sep + 1, ESCAPE_POSIX); + if (!esc) + return log_oom(); + + printf("%.*s=%s\n", (int)(sep-s), s, esc); + return 0; +} + +static int show_environment(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *text; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + (void) pager_open(arg_pager_flags); + + r = sd_bus_get_property( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Environment", + &error, + &reply, + "as"); + if (r < 0) + return log_error_errno(r, "Failed to get environment: %s", bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0) { + r = print_variable(text); + if (r < 0) + return r; + } + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return 0; +} + +static int switch_root(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *cmdline_init = NULL; + const char *root, *init; + sd_bus *bus; + int r; + + if (arg_transport != BUS_TRANSPORT_LOCAL) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot switch root remotely."); + + if (argc < 2 || argc > 3) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong number of arguments."); + + root = argv[1]; + + if (argc >= 3) + init = argv[2]; + else { + r = proc_cmdline_get_key("init", 0, &cmdline_init); + if (r < 0) + log_debug_errno(r, "Failed to parse /proc/cmdline: %m"); + + init = cmdline_init; + } + + init = empty_to_null(init); + if (init) { + const char *root_systemd_path = NULL, *root_init_path = NULL; + + root_systemd_path = prefix_roota(root, "/" SYSTEMD_BINARY_PATH); + root_init_path = prefix_roota(root, init); + + /* If the passed init is actually the same as the + * systemd binary, then let's suppress it. */ + if (files_same(root_init_path, root_systemd_path, 0) > 0) + init = NULL; + } + + /* Instruct PID1 to exclude us from its killing spree applied during the transition. Otherwise we + * would exit with a failure status even though the switch to the new root has succeed. */ + assert(saved_argv); + assert(saved_argv[0]); + saved_argv[0][0] = '@'; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + /* If we are slow to exit after the root switch, the new systemd instance + * will send us a signal to terminate. Just ignore it and exit normally. + * This way the unit does not end up as failed. + */ + r = ignore_signals(SIGTERM, -1); + if (r < 0) + log_warning_errno(r, "Failed to change disposition of SIGTERM to ignore: %m"); + + log_debug("Switching root - root: %s; init: %s", root, strna(init)); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SwitchRoot", + &error, + NULL, + "ss", root, init); + if (r < 0) { + (void) default_signals(SIGTERM, -1); + + return log_error_errno(r, "Failed to switch root: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int log_level(int argc, char *argv[], void *userdata) { + sd_bus *bus; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + if (argc == 1) { + _cleanup_free_ char *level = NULL; + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LogLevel", + &error, + &level); + if (r < 0) + return log_error_errno(r, "Failed to get log level: %s", bus_error_message(&error, r)); + + puts(level); + + } else { + assert(argc == 2); + + r = sd_bus_set_property( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LogLevel", + &error, + "s", + argv[1]); + if (r < 0) + return log_error_errno(r, "Failed to set log level: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int log_target(int argc, char *argv[], void *userdata) { + sd_bus *bus; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + if (argc == 1) { + _cleanup_free_ char *target = NULL; + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LogTarget", + &error, + &target); + if (r < 0) + return log_error_errno(r, "Failed to get log target: %s", bus_error_message(&error, r)); + + puts(target); + + } else { + assert(argc == 2); + + r = sd_bus_set_property( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "LogTarget", + &error, + "s", + argv[1]); + if (r < 0) + return log_error_errno(r, "Failed to set log target: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int service_watchdogs(int argc, char *argv[], void *userdata) { + sd_bus *bus; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int b, r; + + assert(argv); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + if (argc == 1) { + /* get ServiceWatchdogs */ + r = sd_bus_get_property_trivial( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ServiceWatchdogs", + &error, + 'b', + &b); + if (r < 0) + return log_error_errno(r, "Failed to get service-watchdog state: %s", bus_error_message(&error, r)); + + printf("%s\n", yes_no(!!b)); + + } else { + /* set ServiceWatchdogs */ + assert(argc == 2); + + b = parse_boolean(argv[1]); + if (b < 0) + return log_error_errno(b, "Failed to parse service-watchdogs argument: %m"); + + r = sd_bus_set_property( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ServiceWatchdogs", + &error, + "b", + b); + if (r < 0) + return log_error_errno(r, "Failed to set service-watchdog state: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int set_environment(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + const char *method; + sd_bus *bus; + int r; + + assert(argc > 1); + assert(argv); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + method = streq(argv[0], "set-environment") + ? "SetEnvironment" + : "UnsetEnvironment"; + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + method); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to set environment: %s", bus_error_message(&error, r)); + + return 0; +} + +static int import_environment(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SetEnvironment"); + if (r < 0) + return bus_log_create_error(r); + + if (argc < 2) + r = sd_bus_message_append_strv(m, environ); + else { + char **a, **b; + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return bus_log_create_error(r); + + STRV_FOREACH(a, strv_skip(argv, 1)) { + + if (!env_name_is_valid(*a)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid environment variable name: %s", *a); + + STRV_FOREACH(b, environ) { + const char *eq; + + eq = startswith(*b, *a); + if (eq && *eq == '=') { + + r = sd_bus_message_append(m, "s", *b); + if (r < 0) + return bus_log_create_error(r); + + break; + } + } + } + + r = sd_bus_message_close_container(m); + } + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to import environment: %s", bus_error_message(&error, r)); + + return 0; +} + +static int enable_sysv_units(const char *verb, char **args) { + int r = 0; + +#if HAVE_SYSV_COMPAT + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + unsigned f = 0; + + /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */ + + if (arg_scope != UNIT_FILE_SYSTEM) + return 0; + + if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0) + return 0; + + if (!STR_IN_SET(verb, + "enable", + "disable", + "is-enabled")) + return 0; + + r = lookup_paths_init(&paths, arg_scope, LOOKUP_PATHS_EXCLUDE_GENERATED, arg_root); + if (r < 0) + return r; + + r = 0; + while (args[f]) { + + const char *argv[] = { + ROOTLIBEXECDIR "/systemd-sysv-install", + NULL, /* --root= */ + NULL, /* verb */ + NULL, /* service */ + NULL, + }; + + _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL, *v = NULL; + bool found_native = false, found_sysv; + const char *name; + unsigned c = 1; + pid_t pid; + int j; + + name = args[f++]; + + if (!endswith(name, ".service")) + continue; + + if (path_is_absolute(name)) + continue; + + j = unit_file_exists(arg_scope, &paths, name); + if (j < 0 && !IN_SET(j, -ELOOP, -ERFKILL, -EADDRNOTAVAIL)) + return log_error_errno(j, "Failed to lookup unit file state: %m"); + found_native = j != 0; + + /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled, + * prefer the native unit */ + if (found_native && streq(verb, "is-enabled")) + continue; + + p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name); + if (!p) + return log_oom(); + + p[strlen(p) - STRLEN(".service")] = 0; + found_sysv = access(p, F_OK) >= 0; + if (!found_sysv) + continue; + + if (!arg_quiet) { + if (found_native) + log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]); + else + log_info("%s is not a native service, redirecting to systemd-sysv-install.", name); + } + + if (!isempty(arg_root)) { + q = strjoin("--root=", arg_root); + if (!q) + return log_oom(); + + argv[c++] = q; + } + + /* Let's copy the verb, since it's still pointing directly into the original argv[] array we + * got passed, but safe_fork() is likely going to rewrite that for the new child */ + v = strdup(verb); + if (!v) + return log_oom(); + + argv[c++] = v; + argv[c++] = basename(p); + argv[c] = NULL; + + l = strv_join((char**)argv, " "); + if (!l) + return log_oom(); + + if (!arg_quiet) + log_info("Executing: %s", l); + + j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (j < 0) + return j; + if (j == 0) { + /* Child */ + execv(argv[0], (char**) argv); + log_error_errno(errno, "Failed to execute %s: %m", argv[0]); + _exit(EXIT_FAILURE); + } + + j = wait_for_terminate_and_check("sysv-install", pid, WAIT_LOG_ABNORMAL); + if (j < 0) + return j; + if (streq(verb, "is-enabled")) { + if (j == EXIT_SUCCESS) { + if (!arg_quiet) + puts("enabled"); + r = 1; + } else { + if (!arg_quiet) + puts("disabled"); + } + + } else if (j != EXIT_SUCCESS) + return -EBADE; /* We don't warn here, under the assumption the script already showed an explanation */ + + if (found_native) + continue; + + /* Remove this entry, so that we don't try enabling it as native unit */ + assert(f > 0); + f--; + assert(args[f] == name); + strv_remove(args + f, name); + } + +#endif + return r; +} + +static int mangle_names(const char *operation, char **original_names, char ***mangled_names) { + char **i, **l, **name; + int r; + + l = i = new(char*, strv_length(original_names) + 1); + if (!l) + return log_oom(); + + STRV_FOREACH(name, original_names) { + + /* When enabling units qualified path names are OK, + * too, hence allow them explicitly. */ + + if (is_path(*name)) { + *i = strdup(*name); + if (!*i) { + strv_free(l); + return log_oom(); + } + } else { + r = unit_name_mangle_with_suffix(*name, operation, + arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, + ".service", i); + if (r < 0) { + *i = NULL; + strv_free(l); + return log_error_errno(r, "Failed to mangle unit name: %m"); + } + } + + i++; + } + + *i = NULL; + *mangled_names = l; + + return 0; +} + +static int normalize_filenames(char **names) { + char **u; + int r; + + STRV_FOREACH(u, names) + if (!path_is_absolute(*u)) { + char* normalized_path; + + if (!isempty(arg_root)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Non-absolute paths are not allowed when --root is used: %s", + *u); + + if (!strchr(*u,'/')) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Link argument does contain at least one directory separator: %s", + *u); + + r = path_make_absolute_cwd(*u, &normalized_path); + if (r < 0) + return r; + + free_and_replace(*u, normalized_path); + } + + return 0; +} + +static int normalize_names(char **names, bool warn_if_path) { + char **u; + bool was_path = false; + + STRV_FOREACH(u, names) { + int r; + + if (!is_path(*u)) + continue; + + r = free_and_strdup(u, basename(*u)); + if (r < 0) + return log_error_errno(r, "Failed to normalize unit file path: %m"); + + was_path = true; + } + + if (warn_if_path && was_path) + log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name."); + + return 0; +} + +static int unit_exists(LookupPaths *lp, const char *unit) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_free_ char *path = NULL; + static const struct bus_properties_map property_map[] = { + { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) }, + { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state)}, + {}, + }; + UnitStatusInfo info = {}; + sd_bus *bus; + int r; + + if (unit_name_is_valid(unit, UNIT_NAME_TEMPLATE)) + return unit_find_template_path(unit, lp, NULL, NULL); + + path = unit_dbus_path_from_name(unit); + if (!path) + return log_oom(); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = bus_map_all_properties(bus, "org.freedesktop.systemd1", path, property_map, 0, &error, &m, &info); + if (r < 0) + return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r)); + + return !streq_ptr(info.load_state, "not-found") || !streq_ptr(info.active_state, "inactive"); +} + +static int enable_unit(int argc, char *argv[], void *userdata) { + _cleanup_strv_free_ char **names = NULL; + const char *verb = argv[0]; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + int carries_install_info = -1; + bool ignore_carries_install_info = arg_quiet; + int r; + + if (!argv[1]) + return 0; + + r = mangle_names("to enable", strv_skip(argv, 1), &names); + if (r < 0) + return r; + + r = enable_sysv_units(verb, names); + if (r < 0) + return r; + + /* If the operation was fully executed by the SysV compat, let's finish early */ + if (strv_isempty(names)) { + if (arg_no_reload || install_client_side()) + return 0; + return daemon_reload(argc, argv, userdata); + } + + if (streq(verb, "disable")) { + r = normalize_names(names, true); + if (r < 0) + return r; + } + + if (streq(verb, "link")) { + r = normalize_filenames(names); + if (r < 0) + return r; + } + + if (install_client_side()) { + UnitFileFlags flags; + + flags = args_to_flags(); + if (streq(verb, "enable")) { + r = unit_file_enable(arg_scope, flags, arg_root, names, &changes, &n_changes); + carries_install_info = r; + } else if (streq(verb, "disable")) + r = unit_file_disable(arg_scope, flags, arg_root, names, &changes, &n_changes); + else if (streq(verb, "reenable")) { + r = unit_file_reenable(arg_scope, flags, arg_root, names, &changes, &n_changes); + carries_install_info = r; + } else if (streq(verb, "link")) + r = unit_file_link(arg_scope, flags, arg_root, names, &changes, &n_changes); + else if (streq(verb, "preset")) { + r = unit_file_preset(arg_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes); + } else if (streq(verb, "mask")) + r = unit_file_mask(arg_scope, flags, arg_root, names, &changes, &n_changes); + else if (streq(verb, "unmask")) + r = unit_file_unmask(arg_scope, flags, arg_root, names, &changes, &n_changes); + else if (streq(verb, "revert")) + r = unit_file_revert(arg_scope, arg_root, names, &changes, &n_changes); + else + assert_not_reached("Unknown verb"); + + unit_file_dump_changes(r, verb, changes, n_changes, arg_quiet); + if (r < 0) + goto finish; + r = 0; + } else { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + bool expect_carries_install_info = false; + bool send_runtime = true, send_force = true, send_preset_mode = false; + const char *method; + sd_bus *bus; + + if (STR_IN_SET(verb, "mask", "unmask")) { + char **name; + _cleanup_(lookup_paths_free) LookupPaths lp = {}; + + r = lookup_paths_init(&lp, arg_scope, 0, arg_root); + if (r < 0) + return r; + + STRV_FOREACH(name, names) { + r = unit_exists(&lp, *name); + if (r < 0) + return r; + if (r == 0) + log_notice("Unit %s does not exist, proceeding anyway.", *name); + } + } + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + if (streq(verb, "enable")) { + method = "EnableUnitFiles"; + expect_carries_install_info = true; + } else if (streq(verb, "disable")) { + method = "DisableUnitFiles"; + send_force = false; + } else if (streq(verb, "reenable")) { + method = "ReenableUnitFiles"; + expect_carries_install_info = true; + } else if (streq(verb, "link")) + method = "LinkUnitFiles"; + else if (streq(verb, "preset")) { + + if (arg_preset_mode != UNIT_FILE_PRESET_FULL) { + method = "PresetUnitFilesWithMode"; + send_preset_mode = true; + } else + method = "PresetUnitFiles"; + + expect_carries_install_info = true; + ignore_carries_install_info = true; + } else if (streq(verb, "mask")) + method = "MaskUnitFiles"; + else if (streq(verb, "unmask")) { + method = "UnmaskUnitFiles"; + send_force = false; + } else if (streq(verb, "revert")) { + method = "RevertUnitFiles"; + send_runtime = send_force = false; + } else + assert_not_reached("Unknown verb"); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + method); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, names); + if (r < 0) + return bus_log_create_error(r); + + if (send_preset_mode) { + r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode)); + if (r < 0) + return bus_log_create_error(r); + } + + if (send_runtime) { + r = sd_bus_message_append(m, "b", arg_runtime); + if (r < 0) + return bus_log_create_error(r); + } + + if (send_force) { + r = sd_bus_message_append(m, "b", arg_force); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to %s unit: %s", verb, bus_error_message(&error, r)); + + if (expect_carries_install_info) { + r = sd_bus_message_read(reply, "b", &carries_install_info); + if (r < 0) + return bus_log_parse_error(r); + } + + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes); + if (r < 0) + goto finish; + + /* Try to reload if enabled */ + if (!arg_no_reload) + r = daemon_reload(argc, argv, userdata); + else + r = 0; + } + + if (carries_install_info == 0 && !ignore_carries_install_info) + log_notice("The unit files have no installation config (WantedBy=, RequiredBy=, Also=,\n" + "Alias= settings in the [Install] section, and DefaultInstance= for template\n" + "units). This means they are not meant to be enabled using systemctl.\n" + " \n" /* trick: the space is needed so that the line does not get stripped from output */ + "Possible reasons for having this kind of units are:\n" + "%1$s A unit may be statically enabled by being symlinked from another unit's\n" + " .wants/ or .requires/ directory.\n" + "%1$s A unit's purpose may be to act as a helper for some other unit which has\n" + " a requirement dependency on it.\n" + "%1$s A unit may be started when needed via activation (socket, path, timer,\n" + " D-Bus, udev, scripted systemctl call, ...).\n" + "%1$s In case of template units, the unit is meant to be enabled with some\n" + " instance name specified.", + special_glyph(SPECIAL_GLYPH_BULLET)); + + if (arg_now && STR_IN_SET(argv[0], "enable", "disable", "mask")) { + sd_bus *bus; + size_t len, i; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + goto finish; + + len = strv_length(names); + { + char *new_args[len + 2]; + + new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop"); + for (i = 0; i < len; i++) + new_args[i + 1] = basename(names[i]); + new_args[i + 1] = NULL; + + r = start_unit(len + 1, new_args, userdata); + } + } + +finish: + unit_file_changes_free(changes, n_changes); + + return r; +} + +static int add_dependency(int argc, char *argv[], void *userdata) { + _cleanup_strv_free_ char **names = NULL; + _cleanup_free_ char *target = NULL; + const char *verb = argv[0]; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + UnitDependency dep; + int r = 0; + + if (!argv[1]) + return 0; + + r = unit_name_mangle_with_suffix(argv[1], "as target", + arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN, + ".target", &target); + if (r < 0) + return log_error_errno(r, "Failed to mangle unit name: %m"); + + r = mangle_names("as dependency", strv_skip(argv, 2), &names); + if (r < 0) + return r; + + if (streq(verb, "add-wants")) + dep = UNIT_WANTS; + else if (streq(verb, "add-requires")) + dep = UNIT_REQUIRES; + else + assert_not_reached("Unknown verb"); + + if (install_client_side()) { + r = unit_file_add_dependency(arg_scope, args_to_flags(), arg_root, names, target, dep, &changes, &n_changes); + unit_file_dump_changes(r, "add dependency on", changes, n_changes, arg_quiet); + + if (r > 0) + r = 0; + } else { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + r = sd_bus_message_new_method_call( + bus, + &m, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "AddDependencyUnitFiles"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, names); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0) + return log_error_errno(r, "Failed to add dependency: %s", bus_error_message(&error, r)); + + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes); + if (r < 0) + goto finish; + + if (arg_no_reload) { + r = 0; + goto finish; + } + + r = daemon_reload(argc, argv, userdata); + } + +finish: + unit_file_changes_free(changes, n_changes); + + return r; +} + +static int preset_all(int argc, char *argv[], void *userdata) { + UnitFileChange *changes = NULL; + size_t n_changes = 0; + int r; + + if (install_client_side()) { + r = unit_file_preset_all(arg_scope, args_to_flags(), arg_root, arg_preset_mode, &changes, &n_changes); + unit_file_dump_changes(r, "preset", changes, n_changes, arg_quiet); + + if (r > 0) + r = 0; + } else { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + sd_bus *bus; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + polkit_agent_open_maybe(); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "PresetAllUnitFiles", + &error, + &reply, + "sbb", + unit_file_preset_mode_to_string(arg_preset_mode), + arg_runtime, + arg_force); + if (r < 0) + return log_error_errno(r, "Failed to preset all units: %s", bus_error_message(&error, r)); + + r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes); + if (r < 0) + goto finish; + + if (arg_no_reload) { + r = 0; + goto finish; + } + + r = daemon_reload(argc, argv, userdata); + } + +finish: + unit_file_changes_free(changes, n_changes); + + return r; +} + +static int show_installation_targets_client_side(const char *name) { + UnitFileChange *changes = NULL; + size_t n_changes = 0, i; + UnitFileFlags flags; + char **p; + int r; + + p = STRV_MAKE(name); + flags = UNIT_FILE_DRY_RUN | + (arg_runtime ? UNIT_FILE_RUNTIME : 0); + + r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes); + if (r < 0) + return log_error_errno(r, "Failed to get file links for %s: %m", name); + + for (i = 0; i < n_changes; i++) + if (changes[i].type == UNIT_FILE_UNLINK) + printf(" %s\n", changes[i].path); + + return 0; +} + +static int show_installation_targets(sd_bus *bus, const char *name) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + const char *link; + int r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetUnitFileLinks", + &error, + &reply, + "sb", name, arg_runtime); + if (r < 0) + return log_error_errno(r, "Failed to get unit file links for %s: %s", name, bus_error_message(&error, r)); + + r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s"); + if (r < 0) + return bus_log_parse_error(r); + + while ((r = sd_bus_message_read(reply, "s", &link)) > 0) + printf(" %s\n", link); + + if (r < 0) + return bus_log_parse_error(r); + + r = sd_bus_message_exit_container(reply); + if (r < 0) + return bus_log_parse_error(r); + + return 0; +} + +static int unit_is_enabled(int argc, char *argv[], void *userdata) { + _cleanup_strv_free_ char **names = NULL; + bool enabled; + char **name; + int r; + + r = mangle_names("to check", strv_skip(argv, 1), &names); + if (r < 0) + return r; + + r = enable_sysv_units(argv[0], names); + if (r < 0) + return r; + + enabled = r > 0; + + if (install_client_side()) { + STRV_FOREACH(name, names) { + UnitFileState state; + + r = unit_file_get_state(arg_scope, arg_root, *name, &state); + if (r < 0) + return log_error_errno(r, "Failed to get unit file state for %s: %m", *name); + + if (IN_SET(state, + UNIT_FILE_ENABLED, + UNIT_FILE_ENABLED_RUNTIME, + UNIT_FILE_STATIC, + UNIT_FILE_INDIRECT, + UNIT_FILE_GENERATED)) + enabled = true; + + if (!arg_quiet) { + puts(unit_file_state_to_string(state)); + if (arg_full) { + r = show_installation_targets_client_side(*name); + if (r < 0) + return r; + } + } + } + + r = 0; + } else { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + STRV_FOREACH(name, names) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *s; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetUnitFileState", + &error, + &reply, + "s", *name); + if (r < 0) + return log_error_errno(r, "Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "s", &s); + if (r < 0) + return bus_log_parse_error(r); + + if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect", "generated")) + enabled = true; + + if (!arg_quiet) { + puts(s); + if (arg_full) { + r = show_installation_targets(bus, *name); + if (r < 0) + return r; + } + } + } + } + + return enabled ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static int match_startup_finished(sd_bus_message *m, void *userdata, sd_bus_error *error) { + char **state = userdata; + int r; + + assert(state); + + r = sd_bus_get_property_string( + sd_bus_message_get_bus(m), + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SystemState", + NULL, + state); + + sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), r); + return 0; +} + +static int is_system_running(int argc, char *argv[], void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot_startup_finished = NULL; + _cleanup_(sd_event_unrefp) sd_event* event = NULL; + _cleanup_free_ char *state = NULL; + sd_bus *bus; + int r; + + if (running_in_chroot() > 0 || (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted())) { + if (!arg_quiet) + puts("offline"); + return EXIT_FAILURE; + } + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + if (arg_wait) { + r = sd_event_default(&event); + if (r >= 0) + r = sd_bus_attach_event(bus, event, 0); + if (r >= 0) + r = sd_bus_match_signal_async( + bus, + &slot_startup_finished, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartupFinished", + match_startup_finished, NULL, &state); + if (r < 0) { + log_warning_errno(r, "Failed to request match for StartupFinished: %m"); + arg_wait = false; + } + } + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SystemState", + &error, + &state); + if (r < 0) { + log_warning_errno(r, "Failed to query system state: %s", bus_error_message(&error, r)); + + if (!arg_quiet) + puts("unknown"); + return EXIT_FAILURE; + } + + if (arg_wait && STR_IN_SET(state, "initializing", "starting")) { + r = sd_event_loop(event); + if (r < 0) { + log_warning_errno(r, "Failed to get property from event loop: %m"); + if (!arg_quiet) + puts("unknown"); + return EXIT_FAILURE; + } + } + + if (!arg_quiet) + puts(state); + + return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) { + _cleanup_free_ char *t = NULL; + int r; + + assert(new_path); + assert(original_path); + assert(ret_tmp_fn); + + r = tempfn_random(new_path, NULL, &t); + if (r < 0) + return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path); + + r = mkdir_parents(new_path, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path); + + r = copy_file(original_path, t, 0, 0644, 0, 0, COPY_REFLINK); + if (r == -ENOENT) { + + r = touch(t); + if (r < 0) + return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t); + + } else if (r < 0) + return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", new_path); + + *ret_tmp_fn = TAKE_PTR(t); + + return 0; +} + +static int get_file_to_edit( + const LookupPaths *paths, + const char *name, + char **ret_path) { + + _cleanup_free_ char *path = NULL, *run = NULL; + + assert(name); + assert(ret_path); + + path = path_join(paths->persistent_config, name); + if (!path) + return log_oom(); + + if (arg_runtime) { + run = path_join(paths->runtime_config, name); + if (!run) + return log_oom(); + } + + if (arg_runtime) { + if (access(path, F_OK) >= 0) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", + run, path); + + *ret_path = TAKE_PTR(run); + } else + *ret_path = TAKE_PTR(path); + + return 0; +} + +static int unit_file_create_new( + const LookupPaths *paths, + const char *unit_name, + const char *suffix, + char **ret_new_path, + char **ret_tmp_path) { + + _cleanup_free_ char *new_path = NULL, *tmp_path = NULL; + const char *ending; + int r; + + assert(unit_name); + assert(ret_new_path); + assert(ret_tmp_path); + + ending = strjoina(unit_name, suffix); + r = get_file_to_edit(paths, ending, &new_path); + if (r < 0) + return r; + + r = create_edit_temp_file(new_path, new_path, &tmp_path); + if (r < 0) + return r; + + *ret_new_path = TAKE_PTR(new_path); + *ret_tmp_path = TAKE_PTR(tmp_path); + + return 0; +} + +static int unit_file_create_copy( + const LookupPaths *paths, + const char *unit_name, + const char *fragment_path, + char **ret_new_path, + char **ret_tmp_path) { + + _cleanup_free_ char *new_path = NULL, *tmp_path = NULL; + int r; + + assert(fragment_path); + assert(unit_name); + assert(ret_new_path); + assert(ret_tmp_path); + + r = get_file_to_edit(paths, unit_name, &new_path); + if (r < 0) + return r; + + if (!path_equal(fragment_path, new_path) && access(new_path, F_OK) >= 0) { + char response; + + r = ask_char(&response, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", new_path, fragment_path); + if (r < 0) + return r; + if (response != 'y') + return log_warning_errno(SYNTHETIC_ERRNO(EKEYREJECTED), "%s skipped.", unit_name); + } + + r = create_edit_temp_file(new_path, fragment_path, &tmp_path); + if (r < 0) + return r; + + *ret_new_path = TAKE_PTR(new_path); + *ret_tmp_path = TAKE_PTR(tmp_path); + + return 0; +} + +static int run_editor(char **paths) { + int r; + + assert(paths); + + r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT, NULL); + if (r < 0) + return r; + if (r == 0) { + char **editor_args = NULL, **tmp_path, **original_path; + size_t n_editor_args = 0, i = 1, argc; + const char **args, *editor, *p; + + argc = strv_length(paths)/2 + 1; + + /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL + * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present, + * we try to execute well known editors + */ + editor = getenv("SYSTEMD_EDITOR"); + if (!editor) + editor = getenv("EDITOR"); + if (!editor) + editor = getenv("VISUAL"); + + if (!isempty(editor)) { + editor_args = strv_split(editor, WHITESPACE); + if (!editor_args) { + (void) log_oom(); + _exit(EXIT_FAILURE); + } + n_editor_args = strv_length(editor_args); + argc += n_editor_args - 1; + } + + args = newa(const char*, argc + 1); + + if (n_editor_args > 0) { + args[0] = editor_args[0]; + for (; i < n_editor_args; i++) + args[i] = editor_args[i]; + } + + STRV_FOREACH_PAIR(original_path, tmp_path, paths) + args[i++] = *tmp_path; + args[i] = NULL; + + if (n_editor_args > 0) + execvp(args[0], (char* const*) args); + + FOREACH_STRING(p, "editor", "nano", "vim", "vi") { + args[0] = p; + execvp(p, (char* const*) args); + /* We do not fail if the editor doesn't exist + * because we want to try each one of them before + * failing. + */ + if (errno != ENOENT) { + log_error_errno(errno, "Failed to execute %s: %m", editor); + _exit(EXIT_FAILURE); + } + } + + log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL."); + _exit(EXIT_FAILURE); + } + + return 0; +} + +static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { + _cleanup_(lookup_paths_free) LookupPaths lp = {}; + char **name; + int r; + + assert(names); + assert(paths); + + r = lookup_paths_init(&lp, arg_scope, 0, arg_root); + if (r < 0) + return r; + + STRV_FOREACH(name, names) { + _cleanup_free_ char *path = NULL, *new_path = NULL, *tmp_path = NULL, *tmp_name = NULL; + const char *unit_name; + + r = unit_find_paths(bus, *name, &lp, false, &path, NULL); + if (r == -EKEYREJECTED) { + /* If loading of the unit failed server side complete, then the server won't tell us the unit + * file path. In that case, find the file client side. */ + log_debug_errno(r, "Unit '%s' was not loaded correctly, retrying client-side.", *name); + r = unit_find_paths(bus, *name, &lp, true, &path, NULL); + } + if (r == -ERFKILL) + return log_error_errno(r, "Unit '%s' masked, cannot edit.", *name); + if (r < 0) + return r; + + if (r == 0) { + assert(!path); + + if (!arg_force) { + log_info("Run 'systemctl edit%s --force --full %s' to create a new unit.", + arg_scope == UNIT_FILE_GLOBAL ? " --global" : + arg_scope == UNIT_FILE_USER ? " --user" : "", + *name); + return -ENOENT; + } + + /* Create a new unit from scratch */ + unit_name = *name; + r = unit_file_create_new(&lp, unit_name, + arg_full ? NULL : ".d/override.conf", + &new_path, &tmp_path); + } else { + assert(path); + + unit_name = basename(path); + /* We follow unit aliases, but we need to propagate the instance */ + if (unit_name_is_valid(*name, UNIT_NAME_INSTANCE) && + unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { + _cleanup_free_ char *instance = NULL; + + r = unit_name_to_instance(*name, &instance); + if (r < 0) + return r; + + r = unit_name_replace_instance(unit_name, instance, &tmp_name); + if (r < 0) + return r; + + unit_name = tmp_name; + } + + if (arg_full) + r = unit_file_create_copy(&lp, unit_name, path, &new_path, &tmp_path); + else + r = unit_file_create_new(&lp, unit_name, ".d/override.conf", &new_path, &tmp_path); + } + if (r < 0) + return r; + + r = strv_push_pair(paths, new_path, tmp_path); + if (r < 0) + return log_oom(); + + new_path = tmp_path = NULL; + } + + return 0; +} + +static int edit(int argc, char *argv[], void *userdata) { + _cleanup_(lookup_paths_free) LookupPaths lp = {}; + _cleanup_strv_free_ char **names = NULL; + _cleanup_strv_free_ char **paths = NULL; + char **original, **tmp; + sd_bus *bus; + int r; + + if (!on_tty()) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit units if not on a tty."); + + if (arg_transport != BUS_TRANSPORT_LOCAL) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit units remotely."); + + r = lookup_paths_init(&lp, arg_scope, 0, arg_root); + if (r < 0) + return log_error_errno(r, "Failed to determine unit paths: %m"); + + r = acquire_bus(BUS_MANAGER, &bus); + if (r < 0) + return r; + + r = expand_names(bus, strv_skip(argv, 1), NULL, &names, NULL); + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + + STRV_FOREACH(tmp, names) { + r = unit_is_masked(bus, &lp, *tmp); + if (r < 0) + return r; + if (r > 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit %s: unit is masked.", *tmp); + } + + r = find_paths_to_edit(bus, names, &paths); + if (r < 0) + return r; + + if (strv_isempty(paths)) + return -ENOENT; + + r = run_editor(paths); + if (r < 0) + goto end; + + STRV_FOREACH_PAIR(original, tmp, paths) { + /* If the temporary file is empty we ignore it. + * This allows the user to cancel the modification. + */ + if (null_or_empty_path(*tmp)) { + log_warning("Editing \"%s\" canceled: temporary file is empty.", *original); + continue; + } + + r = rename(*tmp, *original); + if (r < 0) { + r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original); + goto end; + } + } + + r = 0; + + if (!arg_no_reload && !install_client_side()) + r = daemon_reload(argc, argv, userdata); + +end: + STRV_FOREACH_PAIR(original, tmp, paths) { + (void) unlink(*tmp); + + /* Removing empty dropin dirs */ + if (!arg_full) { + _cleanup_free_ char *dir; + + dir = dirname_malloc(*original); + if (!dir) + return log_oom(); + + /* no need to check if the dir is empty, rmdir + * does nothing if it is not the case. + */ + (void) rmdir(dir); + } + } + + return r; +} + +static int systemctl_help(void) { + _cleanup_free_ char *link = NULL; + int r; + + (void) pager_open(arg_pager_flags); + + r = terminal_urlify_man("systemctl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%1$s [OPTIONS...] COMMAND ...\n\n" + "%5$sQuery or send control commands to the system manager.%6$s\n" + "\n%3$sUnit Commands:%4$s\n" + " list-units [PATTERN...] List units currently in memory\n" + " list-sockets [PATTERN...] List socket units currently in memory,\n" + " ordered by address\n" + " list-timers [PATTERN...] List timer units currently in memory,\n" + " ordered by next elapse\n" + " start UNIT... Start (activate) one or more units\n" + " stop UNIT... Stop (deactivate) one or more units\n" + " reload UNIT... Reload one or more units\n" + " restart UNIT... Start or restart one or more units\n" + " try-restart UNIT... Restart one or more units if active\n" + " reload-or-restart UNIT... Reload one or more units if possible,\n" + " otherwise start or restart\n" + " try-reload-or-restart UNIT... If active, reload one or more units,\n" + " if supported, otherwise restart\n" + " isolate UNIT Start one unit and stop all others\n" + " kill UNIT... Send signal to processes of a unit\n" + " clean UNIT... Clean runtime, cache, state, logs or\n" + " configuration of unit\n" + " is-active PATTERN... Check whether units are active\n" + " is-failed PATTERN... Check whether units are failed\n" + " status [PATTERN...|PID...] Show runtime status of one or more units\n" + " show [PATTERN...|JOB...] Show properties of one or more\n" + " units/jobs or the manager\n" + " cat PATTERN... Show files and drop-ins of specified units\n" + " set-property UNIT PROPERTY=VALUE... Sets one or more properties of a unit\n" + " help PATTERN...|PID... Show manual for one or more units\n" + " reset-failed [PATTERN...] Reset failed state for all, one, or more\n" + " units\n" + " list-dependencies [UNIT] Recursively show units which are required\n" + " or wanted by this unit or by which this\n" + " unit is required or wanted" + "\n%3$sUnit File Commands:%4$s\n" + " list-unit-files [PATTERN...] List installed unit files\n" + " enable [UNIT...|PATH...] Enable one or more unit files\n" + " disable UNIT... Disable one or more unit files\n" + " reenable UNIT... Reenable one or more unit files\n" + " preset UNIT... Enable/disable one or more unit files\n" + " based on preset configuration\n" + " preset-all Enable/disable all unit files based on\n" + " preset configuration\n" + " is-enabled UNIT... Check whether unit files are enabled\n" + " mask UNIT... Mask one or more units\n" + " unmask UNIT... Unmask one or more units\n" + " link PATH... Link one or more units files into\n" + " the search path\n" + " revert UNIT... Revert one or more unit files to vendor\n" + " version\n" + " add-wants TARGET UNIT... Add 'Wants' dependency for the target\n" + " on specified one or more units\n" + " add-requires TARGET UNIT... Add 'Requires' dependency for the target\n" + " on specified one or more units\n" + " edit UNIT... Edit one or more unit files\n" + " get-default Get the name of the default target\n" + " set-default TARGET Set the default target\n" + "\n%3$sMachine Commands:%4$s\n" + " list-machines [PATTERN...] List local containers and host\n" + "\n%3$sJob Commands:%4$s\n" + " list-jobs [PATTERN...] List jobs\n" + " cancel [JOB...] Cancel all, one, or more jobs\n" + "\n%3$sEnvironment Commands:%4$s\n" + " show-environment Dump environment\n" + " set-environment VARIABLE=VALUE... Set one or more environment variables\n" + " unset-environment VARIABLE... Unset one or more environment variables\n" + " import-environment [VARIABLE...] Import all or some environment variables\n" + "\n%3$sManager State Commands:%4$s\n" + " daemon-reload Reload systemd manager configuration\n" + " daemon-reexec Reexecute systemd manager\n" + " log-level [LEVEL] Get/set logging threshold for manager\n" + " log-target [TARGET] Get/set logging target for manager\n" + " service-watchdogs [BOOL] Get/set service watchdog state\n" + "\n%3$sSystem Commands:%4$s\n" + " is-system-running Check whether system is fully running\n" + " default Enter system default mode\n" + " rescue Enter system rescue mode\n" + " emergency Enter system emergency mode\n" + " halt Shut down and halt the system\n" + " poweroff Shut down and power-off the system\n" + " reboot [ARG] Shut down and reboot the system\n" + " kexec Shut down and reboot the system with kexec\n" + " exit [EXIT_CODE] Request user instance or container exit\n" + " switch-root ROOT [INIT] Change to a different root file system\n" + " suspend Suspend the system\n" + " hibernate Hibernate the system\n" + " hybrid-sleep Hibernate and suspend the system\n" + " suspend-then-hibernate Suspend the system, wake after a period of\n" + " time, and hibernate" + "\n%3$sOptions:%4$s\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --system Connect to system manager\n" + " --user Connect to user service manager\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on a local container\n" + " -t --type=TYPE List units of a particular type\n" + " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n" + " --failed Shorcut for --state=failed\n" + " -p --property=NAME Show only properties by this name\n" + " -a --all Show all properties/all units currently in memory,\n" + " including dead/empty ones. To list all units installed\n" + " on the system, use 'list-unit-files' instead.\n" + " -l --full Don't ellipsize unit names on output\n" + " -r --recursive Show unit list of host and local containers\n" + " --reverse Show reverse dependencies with 'list-dependencies'\n" + " --job-mode=MODE Specify how to deal with already queued jobs, when\n" + " queueing a new job\n" + " -T --show-transaction When enqueuing a unit job, show full transaction\n" + " --show-types When showing sockets, explicitly show their type\n" + " --value When showing properties, only print the value\n" + " -i --ignore-inhibitors When shutting down or sleeping, ignore inhibitors\n" + " --kill-who=WHO Whom to send signal to\n" + " -s --signal=SIGNAL Which signal to send\n" + " --what=RESOURCES Which types of resources to remove\n" + " --now Start or stop unit after enabling or disabling it\n" + " --dry-run Only print what would be done\n" + " Currently supported by verbs: halt, poweroff, reboot,\n" + " kexec, suspend, hibernate, suspend-then-hibernate,\n" + " hybrid-sleep, default, rescue, emergency, and exit.\n" + " -q --quiet Suppress output\n" + " --wait For (re)start, wait until service stopped again\n" + " For is-system-running, wait until startup is completed\n" + " --no-block Do not wait until operation finished\n" + " --no-wall Don't send wall message before halt/power-off/reboot\n" + " --no-reload Don't reload daemon after en-/dis-abling unit files\n" + " --no-legend Do not print a legend (column headers and hints)\n" + " --no-pager Do not pipe output into a pager\n" + " --no-ask-password Do not ask for system passwords\n" + " --global Enable/disable/mask unit files globally\n" + " --runtime Enable/disable/mask unit files temporarily until next\n" + " reboot\n" + " -f --force When enabling unit files, override existing symlinks\n" + " When shutting down, execute action immediately\n" + " --preset-mode= Apply only enable, only disable, or all presets\n" + " --root=PATH Enable/disable/mask unit files in the specified root\n" + " directory\n" + " -n --lines=INTEGER Number of journal entries to show\n" + " -o --output=STRING Change journal output mode (short, short-precise,\n" + " short-iso, short-iso-precise, short-full,\n" + " short-monotonic, short-unix,\n" + " verbose, export, json, json-pretty, json-sse, cat)\n" + " --firmware-setup Tell the firmware to show the setup menu on next boot\n" + " --boot-loader-menu=TIME\n" + " Boot into boot loader menu on next boot\n" + " --boot-loader-entry=NAME\n" + " Boot into a specific boot loader entry on next boot\n" + " --plain Print unit dependencies as a list instead of a tree\n" + "\nSee the %2$s for details.\n" + , program_invocation_short_name + , link + , ansi_underline(), ansi_normal() + , ansi_highlight(), ansi_normal() + ); + + return 0; +} + +static int halt_help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("halt", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]%s\n" + "\n%s%s the system.%s\n" + "\nOptions:\n" + " --help Show this help\n" + " --halt Halt the machine\n" + " -p --poweroff Switch off the machine\n" + " --reboot Reboot the machine\n" + " -f --force Force immediate halt/power-off/reboot\n" + " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n" + " -d --no-wtmp Don't write wtmp record\n" + " --no-wall Don't send wall message before halt/power-off/reboot\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , arg_action == ACTION_REBOOT ? " [ARG]" : "" + , ansi_highlight() + , arg_action == ACTION_REBOOT ? "Reboot" : + arg_action == ACTION_POWEROFF ? "Power off" : + "Halt" + , ansi_normal() + , link + ); + + return 0; +} + +static int shutdown_help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("shutdown", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [TIME] [WALL...]\n" + "\n%sShut down the system.%s\n" + "\nOptions:\n" + " --help Show this help\n" + " -H --halt Halt the machine\n" + " -P --poweroff Power-off the machine\n" + " -r --reboot Reboot the machine\n" + " -h Equivalent to --poweroff, overridden by --halt\n" + " -k Don't halt/power-off/reboot, just send warnings\n" + " --no-wall Don't send wall message before halt/power-off/reboot\n" + " -c Cancel a pending shutdown\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +static int telinit_help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("telinit", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND\n\n" + "%sSend control commands to the init daemon.%s\n" + "\nCommands:\n" + " 0 Power-off the machine\n" + " 6 Reboot the machine\n" + " 2, 3, 4, 5 Start runlevelX.target unit\n" + " 1, s, S Enter rescue mode\n" + " q, Q Reload init daemon configuration\n" + " u, U Reexecute init daemon\n" + "\nOptions:\n" + " --help Show this help\n" + " --no-wall Don't send wall message before halt/power-off/reboot\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +static int runlevel_help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("runlevel", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n" + "\n%sPrints the previous and current runlevel of the init system.%s\n" + "\nOptions:\n" + " --help Show this help\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight(), ansi_normal() + , link + ); + + return 0; +} + +static void help_types(void) { + if (!arg_no_legend) + puts("Available unit types:"); + + DUMP_STRING_TABLE(unit_type, UnitType, _UNIT_TYPE_MAX); +} + +static void help_states(void) { + if (!arg_no_legend) + puts("Available unit load states:"); + DUMP_STRING_TABLE(unit_load_state, UnitLoadState, _UNIT_LOAD_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable unit active states:"); + DUMP_STRING_TABLE(unit_active_state, UnitActiveState, _UNIT_ACTIVE_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable unit file states:"); + DUMP_STRING_TABLE(unit_file_state, UnitFileState, _UNIT_FILE_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable automount unit substates:"); + DUMP_STRING_TABLE(automount_state, AutomountState, _AUTOMOUNT_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable device unit substates:"); + DUMP_STRING_TABLE(device_state, DeviceState, _DEVICE_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable mount unit substates:"); + DUMP_STRING_TABLE(mount_state, MountState, _MOUNT_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable path unit substates:"); + DUMP_STRING_TABLE(path_state, PathState, _PATH_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable scope unit substates:"); + DUMP_STRING_TABLE(scope_state, ScopeState, _SCOPE_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable service unit substates:"); + DUMP_STRING_TABLE(service_state, ServiceState, _SERVICE_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable slice unit substates:"); + DUMP_STRING_TABLE(slice_state, SliceState, _SLICE_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable socket unit substates:"); + DUMP_STRING_TABLE(socket_state, SocketState, _SOCKET_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable swap unit substates:"); + DUMP_STRING_TABLE(swap_state, SwapState, _SWAP_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable target unit substates:"); + DUMP_STRING_TABLE(target_state, TargetState, _TARGET_STATE_MAX); + + if (!arg_no_legend) + puts("\nAvailable timer unit substates:"); + DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX); +} + +static int help_boot_loader_entry(void) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_strv_free_ char **l = NULL; + sd_bus *bus; + char **i; + int r; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + r = sd_bus_get_property_strv( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "BootLoaderEntries", + &error, + &l); + if (r < 0) + return log_error_errno(r, "Failed to enumerate boot loader entries: %s", bus_error_message(&error, r)); + + if (strv_isempty(l)) + return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "No boot loader entries discovered."); + + STRV_FOREACH(i, l) + puts(*i); + + return 0; +} + +static int systemctl_parse_argv(int argc, char *argv[]) { + enum { + ARG_FAIL = 0x100, + ARG_REVERSE, + ARG_AFTER, + ARG_BEFORE, + ARG_DRY_RUN, + ARG_SHOW_TYPES, + ARG_IRREVERSIBLE, + ARG_IGNORE_DEPENDENCIES, + ARG_VALUE, + ARG_VERSION, + ARG_USER, + ARG_SYSTEM, + ARG_GLOBAL, + ARG_NO_BLOCK, + ARG_NO_LEGEND, + ARG_NO_PAGER, + ARG_NO_WALL, + ARG_ROOT, + ARG_NO_RELOAD, + ARG_KILL_WHO, + ARG_NO_ASK_PASSWORD, + ARG_FAILED, + ARG_RUNTIME, + ARG_PLAIN, + ARG_STATE, + ARG_JOB_MODE, + ARG_PRESET_MODE, + ARG_FIRMWARE_SETUP, + ARG_BOOT_LOADER_MENU, + ARG_BOOT_LOADER_ENTRY, + ARG_NOW, + ARG_MESSAGE, + ARG_WAIT, + ARG_WHAT, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "type", required_argument, NULL, 't' }, + { "property", required_argument, NULL, 'p' }, + { "all", no_argument, NULL, 'a' }, + { "reverse", no_argument, NULL, ARG_REVERSE }, + { "after", no_argument, NULL, ARG_AFTER }, + { "before", no_argument, NULL, ARG_BEFORE }, + { "show-types", no_argument, NULL, ARG_SHOW_TYPES }, + { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */ + { "full", no_argument, NULL, 'l' }, + { "job-mode", required_argument, NULL, ARG_JOB_MODE }, + { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */ + { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */ + { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */ + { "ignore-inhibitors", no_argument, NULL, 'i' }, + { "value", no_argument, NULL, ARG_VALUE }, + { "user", no_argument, NULL, ARG_USER }, + { "system", no_argument, NULL, ARG_SYSTEM }, + { "global", no_argument, NULL, ARG_GLOBAL }, + { "wait", no_argument, NULL, ARG_WAIT }, + { "no-block", no_argument, NULL, ARG_NO_BLOCK }, + { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-wall", no_argument, NULL, ARG_NO_WALL }, + { "dry-run", no_argument, NULL, ARG_DRY_RUN }, + { "quiet", no_argument, NULL, 'q' }, + { "root", required_argument, NULL, ARG_ROOT }, + { "force", no_argument, NULL, 'f' }, + { "no-reload", no_argument, NULL, ARG_NO_RELOAD }, + { "kill-who", required_argument, NULL, ARG_KILL_WHO }, + { "signal", required_argument, NULL, 's' }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "runtime", no_argument, NULL, ARG_RUNTIME }, + { "lines", required_argument, NULL, 'n' }, + { "output", required_argument, NULL, 'o' }, + { "plain", no_argument, NULL, ARG_PLAIN }, + { "state", required_argument, NULL, ARG_STATE }, + { "recursive", no_argument, NULL, 'r' }, + { "preset-mode", required_argument, NULL, ARG_PRESET_MODE }, + { "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP }, + { "boot-loader-menu", required_argument, NULL, ARG_BOOT_LOADER_MENU }, + { "boot-loader-entry", required_argument, NULL, ARG_BOOT_LOADER_ENTRY }, + { "now", no_argument, NULL, ARG_NOW }, + { "message", required_argument, NULL, ARG_MESSAGE }, + { "show-transaction", no_argument, NULL, 'T' }, + { "what", required_argument, NULL, ARG_WHAT }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */ + arg_ask_password = true; + + while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:iTr.::", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return systemctl_help(); + + case ARG_VERSION: + return version(); + + case 't': { + const char *p; + + if (isempty(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--type= requires arguments."); + + for (p = optarg;;) { + _cleanup_free_ char *type = NULL; + + r = extract_first_word(&p, &type, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse type: %s", optarg); + if (r == 0) + break; + + if (streq(type, "help")) { + help_types(); + return 0; + } + + if (unit_type_from_string(type) >= 0) { + if (strv_consume(&arg_types, TAKE_PTR(type)) < 0) + return log_oom(); + continue; + } + + /* It's much nicer to use --state= for + * load states, but let's support this + * in --types= too for compatibility + * with old versions */ + if (unit_load_state_from_string(type) >= 0) { + if (strv_consume(&arg_states, TAKE_PTR(type)) < 0) + return log_oom(); + continue; + } + + log_error("Unknown unit type or load state '%s'.", type); + return log_info_errno(SYNTHETIC_ERRNO(EINVAL), + "Use -t help to see a list of allowed values."); + } + + break; + } + + case 'p': + /* Make sure that if the empty property list was specified, we won't show any + properties. */ + if (isempty(optarg) && !arg_properties) { + arg_properties = new0(char*, 1); + if (!arg_properties) + return log_oom(); + } else { + const char *p; + + for (p = optarg;;) { + _cleanup_free_ char *prop = NULL; + + r = extract_first_word(&p, &prop, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse property: %s", optarg); + if (r == 0) + break; + + if (strv_consume(&arg_properties, TAKE_PTR(prop)) < 0) + return log_oom(); + } + } + + /* If the user asked for a particular + * property, show it to him, even if it is + * empty. */ + arg_all = true; + + break; + + case 'a': + arg_all = true; + break; + + case ARG_REVERSE: + arg_dependency = DEPENDENCY_REVERSE; + break; + + case ARG_AFTER: + arg_dependency = DEPENDENCY_AFTER; + arg_jobs_after = true; + break; + + case ARG_BEFORE: + arg_dependency = DEPENDENCY_BEFORE; + arg_jobs_before = true; + break; + + case ARG_SHOW_TYPES: + arg_show_types = true; + break; + + case ARG_VALUE: + arg_value = true; + break; + + case ARG_JOB_MODE: + arg_job_mode = optarg; + break; + + case ARG_FAIL: + arg_job_mode = "fail"; + break; + + case ARG_IRREVERSIBLE: + arg_job_mode = "replace-irreversibly"; + break; + + case ARG_IGNORE_DEPENDENCIES: + arg_job_mode = "ignore-dependencies"; + break; + + case ARG_USER: + arg_scope = UNIT_FILE_USER; + break; + + case ARG_SYSTEM: + arg_scope = UNIT_FILE_SYSTEM; + break; + + case ARG_GLOBAL: + arg_scope = UNIT_FILE_GLOBAL; + break; + + case ARG_WAIT: + arg_wait = true; + break; + + case ARG_NO_BLOCK: + arg_no_block = true; + break; + + case ARG_NO_LEGEND: + arg_no_legend = true; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_NO_WALL: + arg_no_wall = true; + break; + + case ARG_ROOT: + r = parse_path_argument_and_warn(optarg, false, &arg_root); + if (r < 0) + return r; + break; + + case 'l': + arg_full = true; + break; + + case ARG_FAILED: + if (strv_extend(&arg_states, "failed") < 0) + return log_oom(); + + break; + + case ARG_DRY_RUN: + arg_dry_run = true; + break; + + case 'q': + arg_quiet = true; + break; + + case 'f': + arg_force++; + break; + + case ARG_NO_RELOAD: + arg_no_reload = true; + break; + + case ARG_KILL_WHO: + arg_kill_who = optarg; + break; + + case 's': + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(signal, int, _NSIG); + return 0; + } + + arg_signal = signal_from_string(optarg); + if (arg_signal < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse signal string %s.", + optarg); + break; + + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case ARG_RUNTIME: + arg_runtime = true; + break; + + case 'n': + if (safe_atou(optarg, &arg_lines) < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse lines '%s'", + optarg); + break; + + case 'o': + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX); + return 0; + } + + arg_output = output_mode_from_string(optarg); + if (arg_output < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown output '%s'.", + optarg); + break; + + case 'i': + arg_ignore_inhibitors = true; + break; + + case ARG_PLAIN: + arg_plain = true; + break; + + case ARG_FIRMWARE_SETUP: + arg_firmware_setup = true; + break; + + case ARG_BOOT_LOADER_MENU: + + r = parse_sec(optarg, &arg_boot_loader_menu); + if (r < 0) + return log_error_errno(r, "Failed to parse --boot-loader-menu= argument '%s': %m", optarg); + + break; + + case ARG_BOOT_LOADER_ENTRY: + + if (streq(optarg, "help")) { /* Yes, this means, "help" is not a valid boot loader entry name we can deal with */ + r = help_boot_loader_entry(); + if (r < 0) + return r; + + return 0; + } + + arg_boot_loader_entry = empty_to_null(optarg); + break; + + case ARG_STATE: { + const char *p; + + if (isempty(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--state= requires arguments."); + + for (p = optarg;;) { + _cleanup_free_ char *s = NULL; + + r = extract_first_word(&p, &s, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse state: %s", optarg); + if (r == 0) + break; + + if (streq(s, "help")) { + help_states(); + return 0; + } + + if (strv_consume(&arg_states, TAKE_PTR(s)) < 0) + return log_oom(); + } + break; + } + + case 'r': + if (geteuid() != 0) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "--recursive requires root privileges."); + + arg_recursive = true; + break; + + case ARG_PRESET_MODE: + if (streq(optarg, "help")) { + DUMP_STRING_TABLE(unit_file_preset_mode, UnitFilePresetMode, _UNIT_FILE_PRESET_MAX); + return 0; + } + + arg_preset_mode = unit_file_preset_mode_from_string(optarg); + if (arg_preset_mode < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse preset mode: %s.", optarg); + + break; + + case ARG_NOW: + arg_now = true; + break; + + case ARG_MESSAGE: + if (strv_extend(&arg_wall, optarg) < 0) + return log_oom(); + break; + + case 'T': + arg_show_transaction = true; + break; + + case ARG_WHAT: { + const char *p; + + if (isempty(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--what= requires arguments."); + + for (p = optarg;;) { + _cleanup_free_ char *k = NULL; + + r = extract_first_word(&p, &k, ",", 0); + if (r < 0) + return log_error_errno(r, "Failed to parse directory type: %s", optarg); + if (r == 0) + break; + + if (streq(k, "help")) { + puts("runtime\n" + "state\n" + "cache\n" + "logs\n" + "configuration"); + return 0; + } + + r = strv_consume(&arg_clean_what, TAKE_PTR(k)); + if (r < 0) + return log_oom(); + } + + break; + } + + case '.': + /* Output an error mimicking getopt, and print a hint afterwards */ + log_error("%s: invalid option -- '.'", program_invocation_name); + log_notice("Hint: to specify units starting with a dash, use \"--\":\n" + " %s [OPTIONS...] COMMAND -- -.%s ...", + program_invocation_name, optarg ?: "mount"); + _fallthrough_; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot access user instance remotely."); + + if (arg_wait && arg_no_block) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--wait may not be combined with --no-block."); + + return 1; +} + +static int halt_parse_argv(int argc, char *argv[]) { + enum { + ARG_HELP = 0x100, + ARG_HALT, + ARG_REBOOT, + ARG_NO_WALL + }; + + static const struct option options[] = { + { "help", no_argument, NULL, ARG_HELP }, + { "halt", no_argument, NULL, ARG_HALT }, + { "poweroff", no_argument, NULL, 'p' }, + { "reboot", no_argument, NULL, ARG_REBOOT }, + { "force", no_argument, NULL, 'f' }, + { "wtmp-only", no_argument, NULL, 'w' }, + { "no-wtmp", no_argument, NULL, 'd' }, + { "no-sync", no_argument, NULL, 'n' }, + { "no-wall", no_argument, NULL, ARG_NO_WALL }, + {} + }; + + int c, r, runlevel; + + assert(argc >= 0); + assert(argv); + + if (utmp_get_runlevel(&runlevel, NULL) >= 0) + if (IN_SET(runlevel, '0', '6')) + arg_force = 2; + + while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) + switch (c) { + + case ARG_HELP: + return halt_help(); + + case ARG_HALT: + arg_action = ACTION_HALT; + break; + + case 'p': + if (arg_action != ACTION_REBOOT) + arg_action = ACTION_POWEROFF; + break; + + case ARG_REBOOT: + arg_action = ACTION_REBOOT; + break; + + case 'f': + arg_force = 2; + break; + + case 'w': + arg_dry_run = true; + break; + + case 'd': + arg_no_wtmp = true; + break; + + case 'n': + arg_no_sync = true; + break; + + case ARG_NO_WALL: + arg_no_wall = true; + break; + + case 'i': + case 'h': + /* Compatibility nops */ + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) { + r = update_reboot_parameter_and_warn(argc == optind + 1 ? argv[optind] : NULL, false); + if (r < 0) + return r; + } else if (optind < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many arguments."); + + return 1; +} + +static int shutdown_parse_argv(int argc, char *argv[]) { + enum { + ARG_HELP = 0x100, + ARG_NO_WALL + }; + + static const struct option options[] = { + { "help", no_argument, NULL, ARG_HELP }, + { "halt", no_argument, NULL, 'H' }, + { "poweroff", no_argument, NULL, 'P' }, + { "reboot", no_argument, NULL, 'r' }, + { "kexec", no_argument, NULL, 'K' }, /* not documented extension */ + { "no-wall", no_argument, NULL, ARG_NO_WALL }, + {} + }; + + char **wall = NULL; + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "HPrhkKat:fFc", options, NULL)) >= 0) + switch (c) { + + case ARG_HELP: + return shutdown_help(); + + case 'H': + arg_action = ACTION_HALT; + break; + + case 'P': + arg_action = ACTION_POWEROFF; + break; + + case 'r': + if (kexec_loaded()) + arg_action = ACTION_KEXEC; + else + arg_action = ACTION_REBOOT; + break; + + case 'K': + arg_action = ACTION_KEXEC; + break; + + case 'h': + if (arg_action != ACTION_HALT) + arg_action = ACTION_POWEROFF; + break; + + case 'k': + arg_dry_run = true; + break; + + case ARG_NO_WALL: + arg_no_wall = true; + break; + + case 'a': + case 't': /* Note that we also ignore any passed argument to -t, not just the -t itself */ + case 'f': + case 'F': + /* Compatibility nops */ + break; + + case 'c': + arg_action = ACTION_CANCEL_SHUTDOWN; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) { + r = parse_shutdown_time_spec(argv[optind], &arg_when); + if (r < 0) { + log_error("Failed to parse time specification: %s", argv[optind]); + return r; + } + } else + arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE; + + if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN) + /* No time argument for shutdown cancel */ + wall = argv + optind; + else if (argc > optind + 1) + /* We skip the time argument */ + wall = argv + optind + 1; + + if (wall) { + arg_wall = strv_copy(wall); + if (!arg_wall) + return log_oom(); + } + + optind = argc; + + return 1; +} + +static int telinit_parse_argv(int argc, char *argv[]) { + enum { + ARG_HELP = 0x100, + ARG_NO_WALL + }; + + static const struct option options[] = { + { "help", no_argument, NULL, ARG_HELP }, + { "no-wall", no_argument, NULL, ARG_NO_WALL }, + {} + }; + + static const struct { + char from; + enum action to; + } table[] = { + { '0', ACTION_POWEROFF }, + { '6', ACTION_REBOOT }, + { '1', ACTION_RESCUE }, + { '2', ACTION_RUNLEVEL2 }, + { '3', ACTION_RUNLEVEL3 }, + { '4', ACTION_RUNLEVEL4 }, + { '5', ACTION_RUNLEVEL5 }, + { 's', ACTION_RESCUE }, + { 'S', ACTION_RESCUE }, + { 'q', ACTION_RELOAD }, + { 'Q', ACTION_RELOAD }, + { 'u', ACTION_REEXEC }, + { 'U', ACTION_REEXEC } + }; + + unsigned i; + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) + switch (c) { + + case ARG_HELP: + return telinit_help(); + + case ARG_NO_WALL: + arg_no_wall = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind >= argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: required argument missing.", + program_invocation_short_name); + + if (optind + 1 < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many arguments."); + + if (strlen(argv[optind]) != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Expected single character argument."); + + for (i = 0; i < ELEMENTSOF(table); i++) + if (table[i].from == argv[optind][0]) + break; + + if (i >= ELEMENTSOF(table)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown command '%s'.", argv[optind]); + + arg_action = table[i].to; + + optind++; + + return 1; +} + +static int runlevel_parse_argv(int argc, char *argv[]) { + enum { + ARG_HELP = 0x100, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, ARG_HELP }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) + switch (c) { + + case ARG_HELP: + return runlevel_help(); + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many arguments."); + + return 1; +} + +static int parse_argv(int argc, char *argv[]) { + assert(argc >= 0); + assert(argv); + + if (program_invocation_short_name) { + + if (strstr(program_invocation_short_name, "halt")) { + arg_action = ACTION_HALT; + return halt_parse_argv(argc, argv); + + } else if (strstr(program_invocation_short_name, "poweroff")) { + arg_action = ACTION_POWEROFF; + return halt_parse_argv(argc, argv); + + } else if (strstr(program_invocation_short_name, "reboot")) { + if (kexec_loaded()) + arg_action = ACTION_KEXEC; + else + arg_action = ACTION_REBOOT; + return halt_parse_argv(argc, argv); + + } else if (strstr(program_invocation_short_name, "shutdown")) { + arg_action = ACTION_POWEROFF; + return shutdown_parse_argv(argc, argv); + + } else if (strstr(program_invocation_short_name, "init")) { + + /* Matches invocations as "init" as well as "telinit", which are synonymous when run as PID != + * 1 on SysV. + * + * On SysV "telinit" was the official command to communicate with PID 1, but "init" would + * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still, + * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence, for + * us if you invoke "init" you get "systemd", but it will execve() "systemctl" immediately with + * argv[] unmodified if PID is != 1. If you invoke "telinit" you directly get "systemctl". In + * both cases we shall do the same thing, which is why we do strstr(p_i_s_n, "init") here, as a + * quick way to match both. + * + * Also see redirect_telinit() in src/core/main.c. */ + + if (sd_booted() > 0) { + arg_action = _ACTION_INVALID; + return telinit_parse_argv(argc, argv); + } else { + /* Hmm, so some other init system is running, we need to forward this request to + * it. For now we simply guess that it is Upstart. */ + + (void) rlimit_nofile_safe(); + execv(TELINIT, argv); + + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Couldn't find an alternative telinit implementation to spawn."); + } + + } else if (strstr(program_invocation_short_name, "runlevel")) { + arg_action = ACTION_RUNLEVEL; + return runlevel_parse_argv(argc, argv); + } + } + + arg_action = ACTION_SYSTEMCTL; + return systemctl_parse_argv(argc, argv); +} + +#if HAVE_SYSV_COMPAT +_pure_ static int action_to_runlevel(void) { + static const char table[_ACTION_MAX] = { + [ACTION_HALT] = '0', + [ACTION_POWEROFF] = '0', + [ACTION_REBOOT] = '6', + [ACTION_RUNLEVEL2] = '2', + [ACTION_RUNLEVEL3] = '3', + [ACTION_RUNLEVEL4] = '4', + [ACTION_RUNLEVEL5] = '5', + [ACTION_RESCUE] = '1' + }; + + assert(arg_action >= 0 && arg_action < _ACTION_MAX); + return table[arg_action]; +} +#endif + +static int systemctl_main(int argc, char *argv[]) { + static const Verb verbs[] = { + { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, list_units }, + { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files }, + { "list-sockets", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_sockets }, + { "list-timers", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_timers }, + { "list-jobs", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_jobs }, + { "list-machines", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, list_machines }, + { "clear-jobs", VERB_ANY, 1, VERB_ONLINE_ONLY, trivial_method }, + { "cancel", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, cancel_job }, + { "start", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, + { "stop", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, + { "condstop", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with ALTLinux */ + { "reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, + { "restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, + { "try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, + { "reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, + { "reload-or-try-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with old systemctl <= 228 */ + { "try-reload-or-restart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, + { "force-reload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with SysV */ + { "condreload", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with ALTLinux */ + { "condrestart", 2, VERB_ANY, VERB_ONLINE_ONLY, start_unit }, /* For compatibility with RH */ + { "isolate", 2, 2, VERB_ONLINE_ONLY, start_unit }, + { "kill", 2, VERB_ANY, VERB_ONLINE_ONLY, kill_unit }, + { "clean", 2, VERB_ANY, VERB_ONLINE_ONLY, clean_unit }, + { "is-active", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_active }, + { "check", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_active }, /* deprecated alias of is-active */ + { "is-failed", 2, VERB_ANY, VERB_ONLINE_ONLY, check_unit_failed }, + { "show", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show }, + { "cat", 2, VERB_ANY, VERB_ONLINE_ONLY, cat }, + { "status", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show }, + { "help", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, show }, + { "daemon-reload", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload }, + { "daemon-reexec", VERB_ANY, 1, VERB_ONLINE_ONLY, daemon_reload }, + { "log-level", VERB_ANY, 2, 0, log_level }, + { "log-target", VERB_ANY, 2, 0, log_target }, + { "service-watchdogs", VERB_ANY, 2, 0, service_watchdogs }, + { "show-environment", VERB_ANY, 1, VERB_ONLINE_ONLY, show_environment }, + { "set-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment }, + { "unset-environment", 2, VERB_ANY, VERB_ONLINE_ONLY, set_environment }, + { "import-environment", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, import_environment }, + { "halt", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, + { "poweroff", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, + { "reboot", VERB_ANY, 2, VERB_ONLINE_ONLY, start_system_special }, + { "kexec", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, + { "suspend", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, + { "hibernate", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, + { "hybrid-sleep", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, + { "suspend-then-hibernate",VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, + { "default", VERB_ANY, 1, VERB_ONLINE_ONLY, start_special }, + { "rescue", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, + { "emergency", VERB_ANY, 1, VERB_ONLINE_ONLY, start_system_special }, + { "exit", VERB_ANY, 2, VERB_ONLINE_ONLY, start_special }, + { "reset-failed", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, reset_failed }, + { "enable", 2, VERB_ANY, 0, enable_unit }, + { "disable", 2, VERB_ANY, 0, enable_unit }, + { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled }, + { "reenable", 2, VERB_ANY, 0, enable_unit }, + { "preset", 2, VERB_ANY, 0, enable_unit }, + { "preset-all", VERB_ANY, 1, 0, preset_all }, + { "mask", 2, VERB_ANY, 0, enable_unit }, + { "unmask", 2, VERB_ANY, 0, enable_unit }, + { "link", 2, VERB_ANY, 0, enable_unit }, + { "revert", 2, VERB_ANY, 0, enable_unit }, + { "switch-root", 2, VERB_ANY, VERB_ONLINE_ONLY, switch_root }, + { "list-dependencies", VERB_ANY, 2, VERB_ONLINE_ONLY, list_dependencies }, + { "set-default", 2, 2, 0, set_default }, + { "get-default", VERB_ANY, 1, 0, get_default }, + { "set-property", 3, VERB_ANY, VERB_ONLINE_ONLY, set_property }, + { "is-system-running", VERB_ANY, 1, 0, is_system_running }, + { "add-wants", 3, VERB_ANY, 0, add_dependency }, + { "add-requires", 3, VERB_ANY, 0, add_dependency }, + { "edit", 2, VERB_ANY, VERB_ONLINE_ONLY, edit }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static int reload_with_fallback(void) { + /* First, try systemd via D-Bus. */ + if (daemon_reload(0, NULL, NULL) >= 0) + return 0; + + /* Nothing else worked, so let's try signals */ + assert(IN_SET(arg_action, ACTION_RELOAD, ACTION_REEXEC)); + + if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) + return log_error_errno(errno, "kill() failed: %m"); + + return 0; +} + +static int start_with_fallback(void) { + /* First, try systemd via D-Bus. */ + if (start_unit(0, NULL, NULL) == 0) + return 0; + +#if HAVE_SYSV_COMPAT + /* Nothing else worked, so let's try /dev/initctl */ + if (talk_initctl(action_to_runlevel()) > 0) + return 0; +#endif + + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Failed to talk to init daemon."); +} + +static int halt_now(enum action a) { + /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be + * synced explicitly in advance. */ + if (!arg_no_sync && !arg_dry_run) + (void) sync(); + + /* Make sure C-A-D is handled by the kernel from this point on... */ + if (!arg_dry_run) + (void) reboot(RB_ENABLE_CAD); + + switch (a) { + + case ACTION_HALT: + if (!arg_quiet) + log_info("Halting."); + if (arg_dry_run) + return 0; + (void) reboot(RB_HALT_SYSTEM); + return -errno; + + case ACTION_POWEROFF: + if (!arg_quiet) + log_info("Powering off."); + if (arg_dry_run) + return 0; + (void) reboot(RB_POWER_OFF); + return -errno; + + case ACTION_KEXEC: + case ACTION_REBOOT: + return reboot_with_parameter(REBOOT_FALLBACK | + (arg_quiet ? 0 : REBOOT_LOG) | + (arg_dry_run ? REBOOT_DRY_RUN : 0)); + + default: + assert_not_reached("Unknown action."); + } +} + +static int logind_schedule_shutdown(void) { + +#if ENABLE_LOGIND + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + char date[FORMAT_TIMESTAMP_MAX]; + const char *action; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + switch (arg_action) { + case ACTION_HALT: + action = "halt"; + break; + case ACTION_POWEROFF: + action = "poweroff"; + break; + case ACTION_KEXEC: + action = "kexec"; + break; + case ACTION_EXIT: + action = "exit"; + break; + case ACTION_REBOOT: + default: + action = "reboot"; + break; + } + + if (arg_dry_run) + action = strjoina("dry-", action); + + (void) logind_set_wall_message(); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ScheduleShutdown", + &error, + NULL, + "st", + action, + arg_when); + if (r < 0) + return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r)); + + if (!arg_quiet) + log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when)); + return 0; +#else + return log_error_errno(SYNTHETIC_ERRNO(ENOSYS), + "Cannot schedule shutdown without logind support, proceeding with immediate shutdown."); +#endif +} + +static int halt_main(void) { + int r; + + r = logind_check_inhibitors(arg_action); + if (r < 0) + return r; + + /* Delayed shutdown requested, and was successful */ + if (arg_when > 0 && logind_schedule_shutdown() == 0) + return 0; + /* no delay, or logind failed or is not at all available */ + + if (geteuid() != 0) { + if (arg_dry_run || arg_force > 0) { + (void) must_be_root(); + return -EPERM; + } + + /* Try logind if we are a normal user and no special + * mode applies. Maybe polkit allows us to shutdown + * the machine. */ + if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT, ACTION_HALT)) { + r = logind_reboot(arg_action); + if (r >= 0) + return r; + if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS)) + /* requested operation is not + * supported on the local system or + * already in progress */ + return r; + /* on all other errors, try low-level operation */ + } + } + + /* In order to minimize the difference between operation with and + * without logind, we explicitly enable non-blocking mode for this, + * as logind's shutdown operations are always non-blocking. */ + arg_no_block = true; + + if (!arg_dry_run && !arg_force) + return start_with_fallback(); + + assert(geteuid() == 0); + + if (!arg_no_wtmp) { + if (sd_booted() > 0) + log_debug("Not writing utmp record, assuming that systemd-update-utmp is used."); + else { + r = utmp_put_shutdown(); + if (r < 0) + log_warning_errno(r, "Failed to write utmp record: %m"); + } + } + + if (arg_dry_run) + return 0; + + r = halt_now(arg_action); + return log_error_errno(r, "Failed to reboot: %m"); +} + +static int runlevel_main(void) { + int r, runlevel, previous; + + r = utmp_get_runlevel(&runlevel, &previous); + if (r < 0) { + puts("unknown"); + return r; + } + + printf("%c %c\n", + previous <= 0 ? 'N' : previous, + runlevel <= 0 ? 'N' : runlevel); + + return 0; +} + +static int logind_cancel_shutdown(void) { +#if ENABLE_LOGIND + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus; + int r; + + r = acquire_bus(BUS_FULL, &bus); + if (r < 0) + return r; + + (void) logind_set_wall_message(); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "CancelScheduledShutdown", + &error, + NULL, NULL); + if (r < 0) + return log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r)); + + return 0; +#else + return log_error_errno(SYNTHETIC_ERRNO(ENOSYS), + "Not compiled with logind support, cannot cancel scheduled shutdowns."); +#endif +} + +static int run(int argc, char *argv[]) { + int r; + + setlocale(LC_ALL, ""); + log_parse_environment(); + log_open(); + + /* The journal merging logic potentially needs a lot of fds. */ + (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); + + sigbus_install(); + + /* Explicitly not on_tty() to avoid setting cached value. + * This becomes relevant for piping output which might be + * ellipsized. */ + original_stdout_is_tty = isatty(STDOUT_FILENO); + + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + + if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) { + if (!arg_quiet) + log_info("Running in chroot, ignoring request."); + r = 0; + goto finish; + } + + /* systemctl_main() will print an error message for the bus + * connection, but only if it needs to */ + + switch (arg_action) { + + case ACTION_SYSTEMCTL: + r = systemctl_main(argc, argv); + break; + + /* Legacy command aliases set arg_action. They provide some fallbacks, + * e.g. to tell sysvinit to reboot after you have installed systemd + * binaries. */ + + case ACTION_HALT: + case ACTION_POWEROFF: + case ACTION_REBOOT: + case ACTION_KEXEC: + r = halt_main(); + break; + + case ACTION_RUNLEVEL2: + case ACTION_RUNLEVEL3: + case ACTION_RUNLEVEL4: + case ACTION_RUNLEVEL5: + case ACTION_RESCUE: + r = start_with_fallback(); + break; + + case ACTION_RELOAD: + case ACTION_REEXEC: + r = reload_with_fallback(); + break; + + case ACTION_CANCEL_SHUTDOWN: + r = logind_cancel_shutdown(); + break; + + case ACTION_RUNLEVEL: + r = runlevel_main(); + break; + + case ACTION_EXIT: + case ACTION_SUSPEND: + case ACTION_HIBERNATE: + case ACTION_HYBRID_SLEEP: + case ACTION_SUSPEND_THEN_HIBERNATE: + case ACTION_EMERGENCY: + case ACTION_DEFAULT: + /* systemctl verbs with no equivalent in the legacy commands. + * These cannot appear in arg_action. Fall through. */ + + case _ACTION_INVALID: + default: + assert_not_reached("Unknown action"); + } + +finish: + release_busses(); + + /* Note that we return r here, not 0, so that we can implement the LSB-like return codes */ + return r; +} + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/systemctl/systemd-sysv-install.SKELETON b/src/systemctl/systemd-sysv-install.SKELETON new file mode 100755 index 00000000..8c16cf99 --- /dev/null +++ b/src/systemctl/systemd-sysv-install.SKELETON @@ -0,0 +1,49 @@ +#!/bin/sh +# This script is called by "systemctl enable/disable" when the given unit is a +# SysV init.d script. It needs to call the distribution's mechanism for +# enabling/disabling those, such as chkconfig, update-rc.d, or similar. This +# can optionally take a --root argument for enabling a SysV init script +# in a chroot or similar. +set -e + +usage() { + echo "Usage: $0 [--root=path] enable|disable|is-enabled " >&2 + exit 1 +} + +unset ROOT + +# parse options +eval set -- "$(getopt -o r: --long root: -- "$@")" +while true; do + case "$1" in + -r|--root) + ROOT="$2" + shift 2 ;; + --) shift ; break ;; + *) usage ;; + esac +done + +NAME="$2" +[ -n "$NAME" ] || usage + +case "$1" in + enable) + # call the command to enable SysV init script $NAME here + # (consider optional $ROOT) + echo "IMPLEMENT ME: enabling SysV init.d script $NAME" + ;; + disable) + # call the command to disable SysV init script $NAME here + # (consider optional $ROOT) + echo "IMPLEMENT ME: disabling SysV init.d script $NAME" + ;; + is-enabled) + # exit with 0 if $NAME is enabled, non-zero if it is disabled + # (consider optional $ROOT) + echo "IMPLEMENT ME: checking SysV init.d script $NAME" + ;; + *) + usage ;; +esac diff --git a/src/systemctl/sysv-compat.c b/src/systemctl/sysv-compat.c new file mode 100644 index 00000000..0283daad --- /dev/null +++ b/src/systemctl/sysv-compat.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "fd-util.h" +#include "initreq.h" +#include "io-util.h" +#include "parse-util.h" +#include "strv.h" +#include "sysv-compat.h" + +#if HAVE_SYSV_COMPAT +int talk_initctl(char rl) { + struct init_request request; + _cleanup_close_ int fd = -1; + const char *p; + int r; + + /* Try to switch to the specified SysV runlevel. Returns == 0 if the operation does not apply on this + * system, and > 0 on success. */ + + if (rl == 0) + return 0; + + FOREACH_STRING(p, "/run/initctl", "/dev/initctl") { + fd = open(p, O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); + if (fd >= 0 || errno != ENOENT) + break; + } + if (fd < 0) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open initctl fifo: %m"); + } + + request = (struct init_request) { + .magic = INIT_MAGIC, + .sleeptime = 0, + .cmd = INIT_CMD_RUNLVL, + .runlevel = rl, + }; + + r = loop_write(fd, &request, sizeof(request), false); + if (r < 0) + return log_error_errno(r, "Failed to write to %s: %m", p); + + return 1; +} +#endif + +int parse_shutdown_time_spec(const char *t, usec_t *ret) { + assert(t); + assert(ret); + + if (streq(t, "now")) + *ret = 0; + else if (!strchr(t, ':')) { + uint64_t u; + + if (safe_atou64(t, &u) < 0) + return -EINVAL; + + *ret = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u; + } else { + char *e = NULL; + long hour, minute; + struct tm tm = {}; + time_t s; + usec_t n; + + errno = 0; + hour = strtol(t, &e, 10); + if (errno > 0 || *e != ':' || hour < 0 || hour > 23) + return -EINVAL; + + minute = strtol(e+1, &e, 10); + if (errno > 0 || *e != 0 || minute < 0 || minute > 59) + return -EINVAL; + + n = now(CLOCK_REALTIME); + s = (time_t) (n / USEC_PER_SEC); + + assert_se(localtime_r(&s, &tm)); + + tm.tm_hour = (int) hour; + tm.tm_min = (int) minute; + tm.tm_sec = 0; + + s = mktime(&tm); + assert(s >= 0); + + *ret = (usec_t) s * USEC_PER_SEC; + + while (*ret <= n) + *ret += USEC_PER_DAY; + } + + return 0; +} diff --git a/src/systemctl/sysv-compat.h b/src/systemctl/sysv-compat.h new file mode 100644 index 00000000..e7991921 --- /dev/null +++ b/src/systemctl/sysv-compat.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "time-util.h" + +#if HAVE_SYSV_COMPAT +int talk_initctl(char runlevel); +#endif + +int parse_shutdown_time_spec(const char *t, usec_t *ret); + +/* The init script exit codes for the LSB 'status' verb. (This is different from the 'start' verb, whose exit + codes are defined in exit-status.h.) + + 0 program is running or service is OK + 1 program is dead and /var/run pid file exists + 2 program is dead and /var/lock lock file exists + 3 program is not running + 4 program or service status is unknown + 5-99 reserved for future LSB use + 100-149 reserved for distribution use + 150-199 reserved for application use + 200-254 reserved + + https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html +*/ +enum { + EXIT_PROGRAM_RUNNING_OR_SERVICE_OK = 0, + EXIT_PROGRAM_DEAD_AND_PID_EXISTS = 1, + EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS = 2, + EXIT_PROGRAM_NOT_RUNNING = 3, + EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN = 4, +}; diff --git a/src/systemd/_sd-common.h b/src/systemd/_sd-common.h new file mode 100644 index 00000000..b3ee7bbc --- /dev/null +++ b/src/systemd/_sd-common.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdcommonhfoo +#define foosdcommonhfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +/* This is a private header; never even think of including this directly! */ + +#if defined(__INCLUDE_LEVEL__) && __INCLUDE_LEVEL__ <= 1 +# error "Do not include _sd-common.h directly; it is a private header." +#endif + +typedef void (*_sd_destroy_t)(void *userdata); + +#ifndef _sd_printf_ +# if __GNUC__ >= 4 +# define _sd_printf_(a,b) __attribute__((__format__(printf, a, b))) +# else +# define _sd_printf_(a,b) +# endif +#endif + +#ifndef _sd_sentinel_ +# define _sd_sentinel_ __attribute__((__sentinel__)) +#endif + +#ifndef _sd_packed_ +# define _sd_packed_ __attribute__((__packed__)) +#endif + +#ifndef _sd_pure_ +# define _sd_pure_ __attribute__((__pure__)) +#endif + +#ifndef _SD_STRINGIFY +# define _SD_XSTRINGIFY(x) #x +# define _SD_STRINGIFY(x) _SD_XSTRINGIFY(x) +#endif + +#ifndef _SD_BEGIN_DECLARATIONS +# ifdef __cplusplus +# define _SD_BEGIN_DECLARATIONS \ + extern "C" { \ + struct _sd_useless_struct_to_allow_trailing_semicolon_ +# else +# define _SD_BEGIN_DECLARATIONS \ + struct _sd_useless_struct_to_allow_trailing_semicolon_ +# endif +#endif + +#ifndef _SD_END_DECLARATIONS +# ifdef __cplusplus +# define _SD_END_DECLARATIONS \ + } \ + struct _sd_useless_cpp_struct_to_allow_trailing_semicolon_ +# else +# define _SD_END_DECLARATIONS \ + struct _sd_useless_struct_to_allow_trailing_semicolon_ +# endif +#endif + +#ifndef _SD_ARRAY_STATIC +# if __STDC_VERSION__ >= 199901L +# define _SD_ARRAY_STATIC static +# else +# define _SD_ARRAY_STATIC +# endif +#endif + +#define _SD_DEFINE_POINTER_CLEANUP_FUNC(type, func) \ + static __inline__ void func##p(type **p) { \ + if (*p) \ + func(*p); \ + } \ + struct _sd_useless_struct_to_allow_trailing_semicolon_ + +#endif diff --git a/src/systemd/meson.build b/src/systemd/meson.build new file mode 100644 index 00000000..05196554 --- /dev/null +++ b/src/systemd/meson.build @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +_systemd_headers = ''' + sd-bus.h + sd-bus-protocol.h + sd-bus-vtable.h + sd-daemon.h + sd-device.h + sd-event.h + sd-hwdb.h + sd-id128.h + sd-journal.h + sd-login.h + sd-messages.h +'''.split() + +# https://github.com/mesonbuild/meson/issues/1633 +systemd_headers = files(_systemd_headers) + +_not_installed_headers = ''' + sd-dhcp6-client.h + sd-dhcp6-lease.h + sd-dhcp-client.h + sd-dhcp-lease.h + sd-dhcp-option.h + sd-dhcp-server.h + sd-ipv4acd.h + sd-ipv4ll.h + sd-lldp.h + sd-ndisc.h + sd-netlink.h + sd-network.h + sd-path.h + sd-radv.h + sd-resolve.h + sd-utf8.h +'''.split() + +install_headers( + systemd_headers, + '_sd-common.h', + subdir : 'systemd') + + +############################################################ + +opts = [['c'], + ['c', '-ansi'], + ['c', '-std=iso9899:1990'], + ['c', '-std=iso9899:2011']] + +if cc.has_argument('-std=iso9899:2017') + opts += [['c', '-std=iso9899:2017']] +endif + +if add_languages('cpp', required : false) + opts += [['c++'], + ['c++', '-std=c++98'], + ['c++', '-std=c++11']] + if cc.has_argument('-std=c++14') + opts += [['c++', '-std=c++14']] + endif + if cc.has_argument('-std=c++17') + opts += [['c++', '-std=c++17']] + endif +endif + +foreach header : _systemd_headers + _not_installed_headers + ['../libudev/libudev.h'] + foreach opt : opts + name = ''.join(['cc-', header.split('/')[-1], ':'] + opt) + if want_tests != 'false' + test(name, + check_compilation_sh, + args : cc.cmd_array() + ['-c', '-x'] + opt + + ['-Werror', '-include', + join_paths(meson.current_source_dir(), header)]) + endif + endforeach +endforeach diff --git a/src/systemd/sd-bus-protocol.h b/src/systemd/sd-bus-protocol.h new file mode 100644 index 00000000..a3f4e743 --- /dev/null +++ b/src/systemd/sd-bus-protocol.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdbusprotocolhfoo +#define foosdbusprotocolhfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +/* Types of message */ + +enum { + _SD_BUS_MESSAGE_TYPE_INVALID = 0, + SD_BUS_MESSAGE_METHOD_CALL, + SD_BUS_MESSAGE_METHOD_RETURN, + SD_BUS_MESSAGE_METHOD_ERROR, + SD_BUS_MESSAGE_SIGNAL, + _SD_BUS_MESSAGE_TYPE_MAX +}; + +/* Primitive types */ + +enum { + _SD_BUS_TYPE_INVALID = 0, + SD_BUS_TYPE_BYTE = 'y', + SD_BUS_TYPE_BOOLEAN = 'b', + SD_BUS_TYPE_INT16 = 'n', + SD_BUS_TYPE_UINT16 = 'q', + SD_BUS_TYPE_INT32 = 'i', + SD_BUS_TYPE_UINT32 = 'u', + SD_BUS_TYPE_INT64 = 'x', + SD_BUS_TYPE_UINT64 = 't', + SD_BUS_TYPE_DOUBLE = 'd', + SD_BUS_TYPE_STRING = 's', + SD_BUS_TYPE_OBJECT_PATH = 'o', + SD_BUS_TYPE_SIGNATURE = 'g', + SD_BUS_TYPE_UNIX_FD = 'h', + SD_BUS_TYPE_ARRAY = 'a', + SD_BUS_TYPE_VARIANT = 'v', + SD_BUS_TYPE_STRUCT = 'r', /* not actually used in signatures */ + SD_BUS_TYPE_STRUCT_BEGIN = '(', + SD_BUS_TYPE_STRUCT_END = ')', + SD_BUS_TYPE_DICT_ENTRY = 'e', /* not actually used in signatures */ + SD_BUS_TYPE_DICT_ENTRY_BEGIN = '{', + SD_BUS_TYPE_DICT_ENTRY_END = '}' +}; + +/* Well-known errors. Note that this is only a sanitized subset of the + * errors that the reference implementation generates. */ + +#define SD_BUS_ERROR_FAILED "org.freedesktop.DBus.Error.Failed" +#define SD_BUS_ERROR_NO_MEMORY "org.freedesktop.DBus.Error.NoMemory" +#define SD_BUS_ERROR_SERVICE_UNKNOWN "org.freedesktop.DBus.Error.ServiceUnknown" +#define SD_BUS_ERROR_NAME_HAS_NO_OWNER "org.freedesktop.DBus.Error.NameHasNoOwner" +#define SD_BUS_ERROR_NO_REPLY "org.freedesktop.DBus.Error.NoReply" +#define SD_BUS_ERROR_IO_ERROR "org.freedesktop.DBus.Error.IOError" +#define SD_BUS_ERROR_BAD_ADDRESS "org.freedesktop.DBus.Error.BadAddress" +#define SD_BUS_ERROR_NOT_SUPPORTED "org.freedesktop.DBus.Error.NotSupported" +#define SD_BUS_ERROR_LIMITS_EXCEEDED "org.freedesktop.DBus.Error.LimitsExceeded" +#define SD_BUS_ERROR_ACCESS_DENIED "org.freedesktop.DBus.Error.AccessDenied" +#define SD_BUS_ERROR_AUTH_FAILED "org.freedesktop.DBus.Error.AuthFailed" +#define SD_BUS_ERROR_NO_SERVER "org.freedesktop.DBus.Error.NoServer" +#define SD_BUS_ERROR_TIMEOUT "org.freedesktop.DBus.Error.Timeout" +#define SD_BUS_ERROR_NO_NETWORK "org.freedesktop.DBus.Error.NoNetwork" +#define SD_BUS_ERROR_ADDRESS_IN_USE "org.freedesktop.DBus.Error.AddressInUse" +#define SD_BUS_ERROR_DISCONNECTED "org.freedesktop.DBus.Error.Disconnected" +#define SD_BUS_ERROR_INVALID_ARGS "org.freedesktop.DBus.Error.InvalidArgs" +#define SD_BUS_ERROR_FILE_NOT_FOUND "org.freedesktop.DBus.Error.FileNotFound" +#define SD_BUS_ERROR_FILE_EXISTS "org.freedesktop.DBus.Error.FileExists" +#define SD_BUS_ERROR_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod" +#define SD_BUS_ERROR_UNKNOWN_OBJECT "org.freedesktop.DBus.Error.UnknownObject" +#define SD_BUS_ERROR_UNKNOWN_INTERFACE "org.freedesktop.DBus.Error.UnknownInterface" +#define SD_BUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty" +#define SD_BUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly" +#define SD_BUS_ERROR_UNIX_PROCESS_ID_UNKNOWN "org.freedesktop.DBus.Error.UnixProcessIdUnknown" +#define SD_BUS_ERROR_INVALID_SIGNATURE "org.freedesktop.DBus.Error.InvalidSignature" +#define SD_BUS_ERROR_INCONSISTENT_MESSAGE "org.freedesktop.DBus.Error.InconsistentMessage" +#define SD_BUS_ERROR_MATCH_RULE_NOT_FOUND "org.freedesktop.DBus.Error.MatchRuleNotFound" +#define SD_BUS_ERROR_MATCH_RULE_INVALID "org.freedesktop.DBus.Error.MatchRuleInvalid" +#define SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED \ + "org.freedesktop.DBus.Error.InteractiveAuthorizationRequired" + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h new file mode 100644 index 00000000..0f43554d --- /dev/null +++ b/src/systemd/sd-bus-vtable.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdbusvtablehfoo +#define foosdbusvtablehfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_bus_vtable sd_bus_vtable; + +#include "sd-bus.h" + +enum { + _SD_BUS_VTABLE_START = '<', + _SD_BUS_VTABLE_END = '>', + _SD_BUS_VTABLE_METHOD = 'M', + _SD_BUS_VTABLE_SIGNAL = 'S', + _SD_BUS_VTABLE_PROPERTY = 'P', + _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W' +}; + +enum { + SD_BUS_VTABLE_DEPRECATED = 1ULL << 0, + SD_BUS_VTABLE_HIDDEN = 1ULL << 1, + SD_BUS_VTABLE_UNPRIVILEGED = 1ULL << 2, + SD_BUS_VTABLE_METHOD_NO_REPLY = 1ULL << 3, + SD_BUS_VTABLE_PROPERTY_CONST = 1ULL << 4, + SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE = 1ULL << 5, + SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION = 1ULL << 6, + SD_BUS_VTABLE_PROPERTY_EXPLICIT = 1ULL << 7, + _SD_BUS_VTABLE_CAPABILITY_MASK = 0xFFFFULL << 40 +}; + +#define SD_BUS_VTABLE_CAPABILITY(x) ((uint64_t) (((x)+1) & 0xFFFF) << 40) + +enum { + _SD_BUS_VTABLE_PARAM_NAMES = 1 << 0, +}; + +extern const unsigned sd_bus_object_vtable_format; + +/* Note: unused areas in the sd_bus_vtable[] array must be initialized to 0. The structure contains an embedded + * union, and the compiler is NOT required to initialize the unused areas of the union when the rest of the + * structure is initialized. Normally the array is defined as read-only data, in which case the linker places + * it in the BSS section, which is always fully initialized, so this is not a concern. But if the array is + * created on the stack or on the heap, care must be taken to initialize the unused areas, for examply by + * first memsetting the whole region to zero before filling the data in. */ + +struct sd_bus_vtable { + /* Please do not initialize this structure directly, use the + * macros below instead */ + + uint8_t type:8; + uint64_t flags:56; + union { + struct { + size_t element_size; + uint64_t features; + const unsigned *vtable_format_reference; + } start; + struct { + const char *member; + const char *signature; + const char *result; + sd_bus_message_handler_t handler; + size_t offset; + const char *names; + } method; + struct { + const char *member; + const char *signature; + const char *names; + } signal; + struct { + const char *member; + const char *signature; + sd_bus_property_get_t get; + sd_bus_property_set_t set; + size_t offset; + } property; + } x; +}; + +#define SD_BUS_VTABLE_START(_flags) \ + { \ + .type = _SD_BUS_VTABLE_START, \ + .flags = _flags, \ + .x = { \ + .start = { \ + .element_size = sizeof(sd_bus_vtable), \ + .features = _SD_BUS_VTABLE_PARAM_NAMES, \ + .vtable_format_reference = &sd_bus_object_vtable_format, \ + }, \ + }, \ + } + +/* helper macro to format method and signal parameters, one at a time */ +#define SD_BUS_PARAM(x) #x "\0" + +#define SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, _in_names, _result, _out_names, _handler, _offset, _flags) \ + { \ + .type = _SD_BUS_VTABLE_METHOD, \ + .flags = _flags, \ + .x = { \ + .method = { \ + .member = _member, \ + .signature = _signature, \ + .result = _result, \ + .handler = _handler, \ + .offset = _offset, \ + .names = _in_names _out_names, \ + }, \ + }, \ + } +#define SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, _offset, _flags) \ + SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, "", _result, "", _handler, _offset, _flags) +#define SD_BUS_METHOD_WITH_NAMES(_member, _signature, _in_names, _result, _out_names, _handler, _flags) \ + SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, _in_names, _result, _out_names, _handler, 0, _flags) +#define SD_BUS_METHOD(_member, _signature, _result, _handler, _flags) \ + SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, "", _result, "", _handler, 0, _flags) + +#define SD_BUS_SIGNAL_WITH_NAMES(_member, _signature, _out_names, _flags) \ + { \ + .type = _SD_BUS_VTABLE_SIGNAL, \ + .flags = _flags, \ + .x = { \ + .signal = { \ + .member = _member, \ + .signature = _signature, \ + .names = _out_names, \ + }, \ + }, \ + } +#define SD_BUS_SIGNAL(_member, _signature, _flags) \ + SD_BUS_SIGNAL_WITH_NAMES(_member, _signature, "", _flags) + +#define SD_BUS_PROPERTY(_member, _signature, _get, _offset, _flags) \ + { \ + .type = _SD_BUS_VTABLE_PROPERTY, \ + .flags = _flags, \ + .x = { \ + .property = { \ + .member = _member, \ + .signature = _signature, \ + .get = _get, \ + .set = NULL, \ + .offset = _offset, \ + }, \ + }, \ + } + +#define SD_BUS_WRITABLE_PROPERTY(_member, _signature, _get, _set, _offset, _flags) \ + { \ + .type = _SD_BUS_VTABLE_WRITABLE_PROPERTY, \ + .flags = _flags, \ + .x = { \ + .property = { \ + .member = _member, \ + .signature = _signature, \ + .get = _get, \ + .set = _set, \ + .offset = _offset, \ + }, \ + }, \ + } + +#define SD_BUS_VTABLE_END \ + { \ + .type = _SD_BUS_VTABLE_END, \ + .flags = 0, \ + .x = { { 0 } }, \ + } + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h new file mode 100644 index 00000000..84ceb62d --- /dev/null +++ b/src/systemd/sd-bus.h @@ -0,0 +1,512 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdbushfoo +#define foosdbushfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include + +#include "sd-event.h" +#include "sd-id128.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +#define SD_BUS_DEFAULT ((sd_bus *) 1) +#define SD_BUS_DEFAULT_USER ((sd_bus *) 2) +#define SD_BUS_DEFAULT_SYSTEM ((sd_bus *) 3) + +/* https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-signature */ +#define SD_BUS_MAXIMUM_SIGNATURE_LENGTH 255 + +/* https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names */ +#define SD_BUS_MAXIMUM_NAME_LENGTH 255 + +/* Types */ + +typedef struct sd_bus sd_bus; +typedef struct sd_bus_message sd_bus_message; +typedef struct sd_bus_slot sd_bus_slot; +typedef struct sd_bus_creds sd_bus_creds; +typedef struct sd_bus_track sd_bus_track; + +typedef struct { + const char *name; + const char *message; + int _need_free; +} sd_bus_error; + +typedef struct { + const char* name; + int code; +} sd_bus_error_map; + +/* Flags */ + +enum { + SD_BUS_CREDS_PID = 1ULL << 0, + SD_BUS_CREDS_TID = 1ULL << 1, + SD_BUS_CREDS_PPID = 1ULL << 2, + SD_BUS_CREDS_UID = 1ULL << 3, + SD_BUS_CREDS_EUID = 1ULL << 4, + SD_BUS_CREDS_SUID = 1ULL << 5, + SD_BUS_CREDS_FSUID = 1ULL << 6, + SD_BUS_CREDS_GID = 1ULL << 7, + SD_BUS_CREDS_EGID = 1ULL << 8, + SD_BUS_CREDS_SGID = 1ULL << 9, + SD_BUS_CREDS_FSGID = 1ULL << 10, + SD_BUS_CREDS_SUPPLEMENTARY_GIDS = 1ULL << 11, + SD_BUS_CREDS_COMM = 1ULL << 12, + SD_BUS_CREDS_TID_COMM = 1ULL << 13, + SD_BUS_CREDS_EXE = 1ULL << 14, + SD_BUS_CREDS_CMDLINE = 1ULL << 15, + SD_BUS_CREDS_CGROUP = 1ULL << 16, + SD_BUS_CREDS_UNIT = 1ULL << 17, + SD_BUS_CREDS_SLICE = 1ULL << 18, + SD_BUS_CREDS_USER_UNIT = 1ULL << 19, + SD_BUS_CREDS_USER_SLICE = 1ULL << 20, + SD_BUS_CREDS_SESSION = 1ULL << 21, + SD_BUS_CREDS_OWNER_UID = 1ULL << 22, + SD_BUS_CREDS_EFFECTIVE_CAPS = 1ULL << 23, + SD_BUS_CREDS_PERMITTED_CAPS = 1ULL << 24, + SD_BUS_CREDS_INHERITABLE_CAPS = 1ULL << 25, + SD_BUS_CREDS_BOUNDING_CAPS = 1ULL << 26, + SD_BUS_CREDS_SELINUX_CONTEXT = 1ULL << 27, + SD_BUS_CREDS_AUDIT_SESSION_ID = 1ULL << 28, + SD_BUS_CREDS_AUDIT_LOGIN_UID = 1ULL << 29, + SD_BUS_CREDS_TTY = 1ULL << 30, + SD_BUS_CREDS_UNIQUE_NAME = 1ULL << 31, + SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 32, + SD_BUS_CREDS_DESCRIPTION = 1ULL << 33, + SD_BUS_CREDS_AUGMENT = 1ULL << 63, /* special flag, if on sd-bus will augment creds struct, in a potentially race-full way. */ + _SD_BUS_CREDS_ALL = (1ULL << 34) -1 +}; + +enum { + SD_BUS_NAME_REPLACE_EXISTING = 1ULL << 0, + SD_BUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1, + SD_BUS_NAME_QUEUE = 1ULL << 2 +}; + +/* Callbacks */ + +typedef int (*sd_bus_message_handler_t)(sd_bus_message *m, void *userdata, sd_bus_error *ret_error); +typedef int (*sd_bus_property_get_t) (sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); +typedef int (*sd_bus_property_set_t) (sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *ret_error); +typedef int (*sd_bus_object_find_t) (sd_bus *bus, const char *path, const char *interface, void *userdata, void **ret_found, sd_bus_error *ret_error); +typedef int (*sd_bus_node_enumerator_t) (sd_bus *bus, const char *prefix, void *userdata, char ***ret_nodes, sd_bus_error *ret_error); +typedef int (*sd_bus_track_handler_t) (sd_bus_track *track, void *userdata); +typedef _sd_destroy_t sd_bus_destroy_t; + +#include "sd-bus-protocol.h" +#include "sd-bus-vtable.h" + +/* Connections */ + +int sd_bus_default(sd_bus **ret); +int sd_bus_default_user(sd_bus **ret); +int sd_bus_default_system(sd_bus **ret); + +int sd_bus_open(sd_bus **ret); +int sd_bus_open_with_description(sd_bus **ret, const char *description); +int sd_bus_open_user(sd_bus **ret); +int sd_bus_open_user_with_description(sd_bus **ret, const char *description); +int sd_bus_open_system(sd_bus **ret); +int sd_bus_open_system_with_description(sd_bus **ret, const char *description); +int sd_bus_open_system_remote(sd_bus **ret, const char *host); +int sd_bus_open_system_machine(sd_bus **ret, const char *machine); + +int sd_bus_new(sd_bus **ret); + +int sd_bus_set_address(sd_bus *bus, const char *address); +int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd); +int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]); +int sd_bus_get_address(sd_bus *bus, const char **address); +int sd_bus_set_bus_client(sd_bus *bus, int b); +int sd_bus_is_bus_client(sd_bus *bus); +int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t bus_id); +int sd_bus_is_server(sd_bus *bus); +int sd_bus_set_anonymous(sd_bus *bus, int b); +int sd_bus_is_anonymous(sd_bus *bus); +int sd_bus_set_trusted(sd_bus *bus, int b); +int sd_bus_is_trusted(sd_bus *bus); +int sd_bus_set_monitor(sd_bus *bus, int b); +int sd_bus_is_monitor(sd_bus *bus); +int sd_bus_set_description(sd_bus *bus, const char *description); +int sd_bus_get_description(sd_bus *bus, const char **description); +int sd_bus_negotiate_creds(sd_bus *bus, int b, uint64_t creds_mask); +int sd_bus_negotiate_timestamp(sd_bus *bus, int b); +int sd_bus_negotiate_fds(sd_bus *bus, int b); +int sd_bus_can_send(sd_bus *bus, char type); +int sd_bus_get_creds_mask(sd_bus *bus, uint64_t *creds_mask); +int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b); +int sd_bus_get_allow_interactive_authorization(sd_bus *bus); +int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b); +int sd_bus_get_exit_on_disconnect(sd_bus *bus); +int sd_bus_set_close_on_exit(sd_bus *bus, int b); +int sd_bus_get_close_on_exit(sd_bus *bus); +int sd_bus_set_watch_bind(sd_bus *bus, int b); +int sd_bus_get_watch_bind(sd_bus *bus); +int sd_bus_set_connected_signal(sd_bus *bus, int b); +int sd_bus_get_connected_signal(sd_bus *bus); +int sd_bus_set_sender(sd_bus *bus, const char *sender); +int sd_bus_get_sender(sd_bus *bus, const char **ret); + +int sd_bus_start(sd_bus *bus); + +int sd_bus_try_close(sd_bus *bus); +void sd_bus_close(sd_bus *bus); + +sd_bus *sd_bus_ref(sd_bus *bus); +sd_bus *sd_bus_unref(sd_bus *bus); +sd_bus *sd_bus_close_unref(sd_bus *bus); +sd_bus *sd_bus_flush_close_unref(sd_bus *bus); + +void sd_bus_default_flush_close(void); + +int sd_bus_is_open(sd_bus *bus); +int sd_bus_is_ready(sd_bus *bus); + +int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id); +int sd_bus_get_scope(sd_bus *bus, const char **scope); +int sd_bus_get_tid(sd_bus *bus, pid_t *tid); +int sd_bus_get_owner_creds(sd_bus *bus, uint64_t creds_mask, sd_bus_creds **ret); + +int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie); +int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie); +int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply); +int sd_bus_call_async(sd_bus *bus, sd_bus_slot **slot, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec); + +int sd_bus_get_fd(sd_bus *bus); +int sd_bus_get_events(sd_bus *bus); +int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec); +int sd_bus_process(sd_bus *bus, sd_bus_message **r); +int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r); +int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec); +int sd_bus_flush(sd_bus *bus); + +sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus); +sd_bus_message* sd_bus_get_current_message(sd_bus *bus); +sd_bus_message_handler_t sd_bus_get_current_handler(sd_bus *bus); +void* sd_bus_get_current_userdata(sd_bus *bus); + +int sd_bus_attach_event(sd_bus *bus, sd_event *e, int priority); +int sd_bus_detach_event(sd_bus *bus); +sd_event *sd_bus_get_event(sd_bus *bus); + +int sd_bus_get_n_queued_read(sd_bus *bus, uint64_t *ret); +int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret); + +int sd_bus_set_method_call_timeout(sd_bus *bus, uint64_t usec); +int sd_bus_get_method_call_timeout(sd_bus *bus, uint64_t *ret); + +int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_add_match_async(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata); +int sd_bus_add_object(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_add_fallback(sd_bus *bus, sd_bus_slot **slot, const char *prefix, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata); +int sd_bus_add_fallback_vtable(sd_bus *bus, sd_bus_slot **slot, const char *prefix, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata); +int sd_bus_add_node_enumerator(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_node_enumerator_t callback, void *userdata); +int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path); + +/* Slot object */ + +sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot); +sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot); + +sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot); +void *sd_bus_slot_get_userdata(sd_bus_slot *slot); +void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata); +int sd_bus_slot_set_description(sd_bus_slot *slot, const char *description); +int sd_bus_slot_get_description(sd_bus_slot *slot, const char **description); +int sd_bus_slot_get_floating(sd_bus_slot *slot); +int sd_bus_slot_set_floating(sd_bus_slot *slot, int b); +int sd_bus_slot_set_destroy_callback(sd_bus_slot *s, sd_bus_destroy_t callback); +int sd_bus_slot_get_destroy_callback(sd_bus_slot *s, sd_bus_destroy_t *callback); + +sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot); +sd_bus_message_handler_t sd_bus_slot_get_current_handler(sd_bus_slot *slot); +void *sd_bus_slot_get_current_userdata(sd_bus_slot *slot); + +/* Message object */ + +int sd_bus_message_new(sd_bus *bus, sd_bus_message **m, uint8_t type); +int sd_bus_message_new_signal(sd_bus *bus, sd_bus_message **m, const char *path, const char *interface, const char *member); +int sd_bus_message_new_method_call(sd_bus *bus, sd_bus_message **m, const char *destination, const char *path, const char *interface, const char *member); +int sd_bus_message_new_method_return(sd_bus_message *call, sd_bus_message **m); +int sd_bus_message_new_method_error(sd_bus_message *call, sd_bus_message **m, const sd_bus_error *e); +int sd_bus_message_new_method_errorf(sd_bus_message *call, sd_bus_message **m, const char *name, const char *format, ...) _sd_printf_(4, 5); +int sd_bus_message_new_method_errno(sd_bus_message *call, sd_bus_message **m, int error, const sd_bus_error *e); +int sd_bus_message_new_method_errnof(sd_bus_message *call, sd_bus_message **m, int error, const char *format, ...) _sd_printf_(4, 5); + +sd_bus_message* sd_bus_message_ref(sd_bus_message *m); +sd_bus_message* sd_bus_message_unref(sd_bus_message *m); + +int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t timeout_usec); + +int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type); +int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie); +int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie); +int sd_bus_message_get_priority(sd_bus_message *m, int64_t *priority); + +int sd_bus_message_get_expect_reply(sd_bus_message *m); +int sd_bus_message_get_auto_start(sd_bus_message *m); +int sd_bus_message_get_allow_interactive_authorization(sd_bus_message *m); + +const char *sd_bus_message_get_signature(sd_bus_message *m, int complete); +const char *sd_bus_message_get_path(sd_bus_message *m); +const char *sd_bus_message_get_interface(sd_bus_message *m); +const char *sd_bus_message_get_member(sd_bus_message *m); +const char *sd_bus_message_get_destination(sd_bus_message *m); +const char *sd_bus_message_get_sender(sd_bus_message *m); +const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m); +int sd_bus_message_get_errno(sd_bus_message *m); + +int sd_bus_message_get_monotonic_usec(sd_bus_message *m, uint64_t *usec); +int sd_bus_message_get_realtime_usec(sd_bus_message *m, uint64_t *usec); +int sd_bus_message_get_seqnum(sd_bus_message *m, uint64_t* seqnum); + +sd_bus* sd_bus_message_get_bus(sd_bus_message *m); +sd_bus_creds *sd_bus_message_get_creds(sd_bus_message *m); /* do not unref the result */ + +int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member); +int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface, const char *member); +int sd_bus_message_is_method_error(sd_bus_message *m, const char *name); +int sd_bus_message_is_empty(sd_bus_message *m); +int sd_bus_message_has_signature(sd_bus_message *m, const char *signature); + +int sd_bus_message_set_expect_reply(sd_bus_message *m, int b); +int sd_bus_message_set_auto_start(sd_bus_message *m, int b); +int sd_bus_message_set_allow_interactive_authorization(sd_bus_message *m, int b); + +int sd_bus_message_set_destination(sd_bus_message *m, const char *destination); +int sd_bus_message_set_sender(sd_bus_message *m, const char *sender); +int sd_bus_message_set_priority(sd_bus_message *m, int64_t priority); + +int sd_bus_message_append(sd_bus_message *m, const char *types, ...); +int sd_bus_message_appendv(sd_bus_message *m, const char *types, va_list ap); +int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p); +int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size); +int sd_bus_message_append_array_space(sd_bus_message *m, char type, size_t size, void **ptr); +int sd_bus_message_append_array_iovec(sd_bus_message *m, char type, const struct iovec *iov, unsigned n); +int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, int memfd, uint64_t offset, uint64_t size); +int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s); +int sd_bus_message_append_string_iovec(sd_bus_message *m, const struct iovec *iov, unsigned n); +int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd, uint64_t offset, uint64_t size); +int sd_bus_message_append_strv(sd_bus_message *m, char **l); +int sd_bus_message_open_container(sd_bus_message *m, char type, const char *contents); +int sd_bus_message_close_container(sd_bus_message *m); +int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all); + +int sd_bus_message_read(sd_bus_message *m, const char *types, ...); +int sd_bus_message_readv(sd_bus_message *m, const char *types, va_list ap); +int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p); +int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, size_t *size); +int sd_bus_message_read_strv(sd_bus_message *m, char ***l); /* free the result! */ +int sd_bus_message_skip(sd_bus_message *m, const char *types); +int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *contents); +int sd_bus_message_exit_container(sd_bus_message *m); +int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents); +int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents); +int sd_bus_message_at_end(sd_bus_message *m, int complete); +int sd_bus_message_rewind(sd_bus_message *m, int complete); + +/* Bus management */ + +int sd_bus_get_unique_name(sd_bus *bus, const char **unique); +int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags); +int sd_bus_request_name_async(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_release_name(sd_bus *bus, const char *name); +int sd_bus_release_name_async(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable); /* free the results */ +int sd_bus_get_name_creds(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds); /* unref the result! */ +int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine); + +/* Convenience calls */ + +int sd_bus_call_method(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *types, ...); +int sd_bus_call_method_async(sd_bus *bus, sd_bus_slot **slot, const char *destination, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata, const char *types, ...); +int sd_bus_get_property(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, sd_bus_message **reply, const char *type); +int sd_bus_get_property_trivial(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char type, void *ret_ptr); +int sd_bus_get_property_string(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char **ret); /* free the result! */ +int sd_bus_get_property_strv(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, char ***ret); /* free the result! */ +int sd_bus_set_property(sd_bus *bus, const char *destination, const char *path, const char *interface, const char *member, sd_bus_error *ret_error, const char *type, ...); + +int sd_bus_reply_method_return(sd_bus_message *call, const char *types, ...); +int sd_bus_reply_method_error(sd_bus_message *call, const sd_bus_error *e); +int sd_bus_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) _sd_printf_(3, 4); +int sd_bus_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *e); +int sd_bus_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) _sd_printf_(3, 4); + +int sd_bus_emit_signal(sd_bus *bus, const char *path, const char *interface, const char *member, const char *types, ...); + +int sd_bus_emit_properties_changed_strv(sd_bus *bus, const char *path, const char *interface, char **names); +int sd_bus_emit_properties_changed(sd_bus *bus, const char *path, const char *interface, const char *name, ...) _sd_sentinel_; + +int sd_bus_emit_object_added(sd_bus *bus, const char *path); +int sd_bus_emit_object_removed(sd_bus *bus, const char *path); +int sd_bus_emit_interfaces_added_strv(sd_bus *bus, const char *path, char **interfaces); +int sd_bus_emit_interfaces_added(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_; +int sd_bus_emit_interfaces_removed_strv(sd_bus *bus, const char *path, char **interfaces); +int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const char *interface, ...) _sd_sentinel_; + +int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds); +int sd_bus_query_sender_privilege(sd_bus_message *call, int capability); + +int sd_bus_match_signal(sd_bus *bus, sd_bus_slot **ret, const char *sender, const char *path, const char *interface, const char *member, sd_bus_message_handler_t callback, void *userdata); +int sd_bus_match_signal_async(sd_bus *bus, sd_bus_slot **ret, const char *sender, const char *path, const char *interface, const char *member, sd_bus_message_handler_t match_callback, sd_bus_message_handler_t add_callback, void *userdata); + +/* Credential handling */ + +int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t creds_mask); +sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c); +sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c); +uint64_t sd_bus_creds_get_mask(const sd_bus_creds *c); +uint64_t sd_bus_creds_get_augmented_mask(const sd_bus_creds *c); + +int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid); +int sd_bus_creds_get_ppid(sd_bus_creds *c, pid_t *ppid); +int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid); +int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid); +int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid); +int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid); +int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid); +int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid); +int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid); +int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid); +int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid); +int sd_bus_creds_get_supplementary_gids(sd_bus_creds *c, const gid_t **gids); +int sd_bus_creds_get_comm(sd_bus_creds *c, const char **comm); +int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **comm); +int sd_bus_creds_get_exe(sd_bus_creds *c, const char **exe); +int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline); +int sd_bus_creds_get_cgroup(sd_bus_creds *c, const char **cgroup); +int sd_bus_creds_get_unit(sd_bus_creds *c, const char **unit); +int sd_bus_creds_get_slice(sd_bus_creds *c, const char **slice); +int sd_bus_creds_get_user_unit(sd_bus_creds *c, const char **unit); +int sd_bus_creds_get_user_slice(sd_bus_creds *c, const char **slice); +int sd_bus_creds_get_session(sd_bus_creds *c, const char **session); +int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid); +int sd_bus_creds_has_effective_cap(sd_bus_creds *c, int capability); +int sd_bus_creds_has_permitted_cap(sd_bus_creds *c, int capability); +int sd_bus_creds_has_inheritable_cap(sd_bus_creds *c, int capability); +int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability); +int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **context); +int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid); +int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *loginuid); +int sd_bus_creds_get_tty(sd_bus_creds *c, const char **tty); +int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **name); +int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***names); +int sd_bus_creds_get_description(sd_bus_creds *c, const char **name); + +/* Error structures */ + +#define SD_BUS_ERROR_MAKE_CONST(name, message) ((const sd_bus_error) {(name), (message), 0}) +#define SD_BUS_ERROR_NULL SD_BUS_ERROR_MAKE_CONST(NULL, NULL) + +void sd_bus_error_free(sd_bus_error *e); +int sd_bus_error_set(sd_bus_error *e, const char *name, const char *message); +int sd_bus_error_setf(sd_bus_error *e, const char *name, const char *format, ...) _sd_printf_(3, 4); +int sd_bus_error_set_const(sd_bus_error *e, const char *name, const char *message); +int sd_bus_error_set_errno(sd_bus_error *e, int error); +int sd_bus_error_set_errnof(sd_bus_error *e, int error, const char *format, ...) _sd_printf_(3, 4); +int sd_bus_error_set_errnofv(sd_bus_error *e, int error, const char *format, va_list ap) _sd_printf_(3,0); +int sd_bus_error_get_errno(const sd_bus_error *e); +int sd_bus_error_copy(sd_bus_error *dest, const sd_bus_error *e); +int sd_bus_error_move(sd_bus_error *dest, sd_bus_error *e); +int sd_bus_error_is_set(const sd_bus_error *e); +int sd_bus_error_has_name(const sd_bus_error *e, const char *name); + +#define SD_BUS_ERROR_MAP(_name, _code) \ + { \ + .name = _name, \ + .code = _code, \ + } +#define SD_BUS_ERROR_MAP_END \ + { \ + .name = NULL, \ + .code = - 'x', \ + } + +int sd_bus_error_add_map(const sd_bus_error_map *map); + +/* Auxiliary macros */ + +#define SD_BUS_MESSAGE_APPEND_ID128(x) 16, \ + (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], \ + (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], \ + (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], \ + (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15] + +#define SD_BUS_MESSAGE_READ_ID128(x) 16, \ + &(x).bytes[0], &(x).bytes[1], &(x).bytes[2], &(x).bytes[3], \ + &(x).bytes[4], &(x).bytes[5], &(x).bytes[6], &(x).bytes[7], \ + &(x).bytes[8], &(x).bytes[9], &(x).bytes[10], &(x).bytes[11], \ + &(x).bytes[12], &(x).bytes[13], &(x).bytes[14], &(x).bytes[15] + +/* Label escaping */ + +int sd_bus_path_encode(const char *prefix, const char *external_id, char **ret_path); +int sd_bus_path_encode_many(char **out, const char *path_template, ...); +int sd_bus_path_decode(const char *path, const char *prefix, char **ret_external_id); +int sd_bus_path_decode_many(const char *path, const char *path_template, ...); + +/* Tracking peers */ + +int sd_bus_track_new(sd_bus *bus, sd_bus_track **track, sd_bus_track_handler_t handler, void *userdata); +sd_bus_track* sd_bus_track_ref(sd_bus_track *track); +sd_bus_track* sd_bus_track_unref(sd_bus_track *track); + +sd_bus* sd_bus_track_get_bus(sd_bus_track *track); +void *sd_bus_track_get_userdata(sd_bus_track *track); +void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata); + +int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m); +int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m); +int sd_bus_track_add_name(sd_bus_track *track, const char *name); +int sd_bus_track_remove_name(sd_bus_track *track, const char *name); + +int sd_bus_track_set_recursive(sd_bus_track *track, int b); +int sd_bus_track_get_recursive(sd_bus_track *track); + +unsigned sd_bus_track_count(sd_bus_track *track); +int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m); +int sd_bus_track_count_name(sd_bus_track *track, const char *name); + +const char* sd_bus_track_contains(sd_bus_track *track, const char *name); +const char* sd_bus_track_first(sd_bus_track *track); +const char* sd_bus_track_next(sd_bus_track *track); + +int sd_bus_track_set_destroy_callback(sd_bus_track *s, sd_bus_destroy_t callback); +int sd_bus_track_get_destroy_callback(sd_bus_track *s, sd_bus_destroy_t *ret); + +/* Define helpers so that __attribute__((cleanup(sd_bus_unrefp))) and similar may be used. */ +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_close_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus, sd_bus_flush_close_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_slot, sd_bus_slot_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_message, sd_bus_message_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_creds, sd_bus_creds_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_bus_track, sd_bus_track_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h new file mode 100644 index 00000000..62b0f723 --- /dev/null +++ b/src/systemd/sd-daemon.h @@ -0,0 +1,320 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddaemonhfoo +#define foosddaemonhfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +/* + The following functionality is provided: + + - Support for logging with log levels on stderr + - File descriptor passing for socket-based activation + - Daemon startup and status notification + - Detection of systemd boots + + See sd-daemon(3) for more information. +*/ + +/* + Log levels for usage on stderr: + + fprintf(stderr, SD_NOTICE "Hello World!\n"); + + This is similar to printk() usage in the kernel. +*/ +#define SD_EMERG "<0>" /* system is unusable */ +#define SD_ALERT "<1>" /* action must be taken immediately */ +#define SD_CRIT "<2>" /* critical conditions */ +#define SD_ERR "<3>" /* error conditions */ +#define SD_WARNING "<4>" /* warning conditions */ +#define SD_NOTICE "<5>" /* normal but significant condition */ +#define SD_INFO "<6>" /* informational */ +#define SD_DEBUG "<7>" /* debug-level messages */ + +/* The first passed file descriptor is fd 3 */ +#define SD_LISTEN_FDS_START 3 + +/* + Returns how many file descriptors have been passed, or a negative + errno code on failure. Optionally, removes the $LISTEN_FDS and + $LISTEN_PID file descriptors from the environment (recommended, but + problematic in threaded environments). If r is the return value of + this function you'll find the file descriptors passed as fds + SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative + errno style error code on failure. This function call ensures that + the FD_CLOEXEC flag is set for the passed file descriptors, to make + sure they are not passed on to child processes. If FD_CLOEXEC shall + not be set, the caller needs to unset it after this call for all file + descriptors that are used. + + See sd_listen_fds(3) for more information. +*/ +int sd_listen_fds(int unset_environment); + +int sd_listen_fds_with_names(int unset_environment, char ***names); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is a FIFO in the file system stored under the + specified path, 0 otherwise. If path is NULL a path name check will + not be done and the call only verifies if the file descriptor + refers to a FIFO. Returns a negative errno style error code on + failure. + + See sd_is_fifo(3) for more information. +*/ +int sd_is_fifo(int fd, const char *path); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is a special character device on the file + system stored under the specified path, 0 otherwise. + If path is NULL a path name check will not be done and the call + only verifies if the file descriptor refers to a special character. + Returns a negative errno style error code on failure. + + See sd_is_special(3) for more information. +*/ +int sd_is_special(int fd, const char *path); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is a socket of the specified family (AF_INET, + ...) and type (SOCK_DGRAM, SOCK_STREAM, ...), 0 otherwise. If + family is 0 a socket family check will not be done. If type is 0 a + socket type check will not be done and the call only verifies if + the file descriptor refers to a socket. If listening is > 0 it is + verified that the socket is in listening mode. (i.e. listen() has + been called) If listening is == 0 it is verified that the socket is + not in listening mode. If listening is < 0 no listening mode check + is done. Returns a negative errno style error code on failure. + + See sd_is_socket(3) for more information. +*/ +int sd_is_socket(int fd, int family, int type, int listening); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is an Internet socket, of the specified family + (either AF_INET or AF_INET6) and the specified type (SOCK_DGRAM, + SOCK_STREAM, ...), 0 otherwise. If version is 0 a protocol version + check is not done. If type is 0 a socket type check will not be + done. If port is 0 a socket port check will not be done. The + listening flag is used the same way as in sd_is_socket(). Returns a + negative errno style error code on failure. + + See sd_is_socket_inet(3) for more information. +*/ +int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if the + file descriptor is an Internet socket of the specified type + (SOCK_DGRAM, SOCK_STREAM, ...), and if the address of the socket is + the same as the address specified by addr. The listening flag is used + the same way as in sd_is_socket(). Returns a negative errno style + error code on failure. + + See sd_is_socket_sockaddr(3) for more information. +*/ +int sd_is_socket_sockaddr(int fd, int type, const struct sockaddr* addr, unsigned addr_len, int listening); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is an AF_UNIX socket of the specified type + (SOCK_DGRAM, SOCK_STREAM, ...) and path, 0 otherwise. If type is 0 + a socket type check will not be done. If path is NULL a socket path + check will not be done. For normal AF_UNIX sockets set length to + 0. For abstract namespace sockets set length to the length of the + socket name (including the initial 0 byte), and pass the full + socket path in path (including the initial 0 byte). The listening + flag is used the same way as in sd_is_socket(). Returns a negative + errno style error code on failure. + + See sd_is_socket_unix(3) for more information. +*/ +int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length); + +/* + Helper call for identifying a passed file descriptor. Returns 1 if + the file descriptor is a POSIX Message Queue of the specified name, + 0 otherwise. If path is NULL a message queue name check is not + done. Returns a negative errno style error code on failure. + + See sd_is_mq(3) for more information. +*/ +int sd_is_mq(int fd, const char *path); + +/* + Informs systemd about changed daemon state. This takes a number of + newline separated environment-style variable assignments in a + string. The following variables are known: + + MAINPID=... The main PID of a daemon, in case systemd did not + fork off the process itself. Example: "MAINPID=4711" + + READY=1 Tells systemd that daemon startup or daemon reload + is finished (only relevant for services of Type=notify). + The passed argument is a boolean "1" or "0". Since there + is little value in signaling non-readiness the only + value daemons should send is "READY=1". + + RELOADING=1 Tell systemd that the daemon began reloading its + configuration. When the configuration has been + reloaded completely, READY=1 should be sent to inform + systemd about this. + + STOPPING=1 Tells systemd that the daemon is about to go down. + + STATUS=... Passes a single-line status string back to systemd + that describes the daemon state. This is free-form + and can be used for various purposes: general state + feedback, fsck-like programs could pass completion + percentages and failing programs could pass a human + readable error message. Example: "STATUS=Completed + 66% of file system check..." + + ERRNO=... If a daemon fails, the errno-style error code, + formatted as string. Example: "ERRNO=2" for ENOENT. + + BUSERROR=... If a daemon fails, the D-Bus error-style error + code. Example: "BUSERROR=org.freedesktop.DBus.Error.TimedOut" + + WATCHDOG=1 Tells systemd to update the watchdog timestamp. + Services using this feature should do this in + regular intervals. A watchdog framework can use the + timestamps to detect failed services. Also see + sd_watchdog_enabled() below. + + WATCHDOG_USEC=... + Reset watchdog_usec value during runtime. + To reset watchdog_usec value, start the service again. + Example: "WATCHDOG_USEC=20000000" + + FDSTORE=1 Store the file descriptors passed along with the + message in the per-service file descriptor store, + and pass them to the main process again on next + invocation. This variable is only supported with + sd_pid_notify_with_fds(). + + FDSTOREREMOVE=1 + Remove one or more file descriptors from the file + descriptor store, identified by the name specified + in FDNAME=, see below. + + FDNAME= A name to assign to new file descriptors stored in the + file descriptor store, or the name of the file descriptors + to remove in case of FDSTOREREMOVE=1. + + Daemons can choose to send additional variables. However, it is + recommended to prefix variable names not listed above with X_. + + Returns a negative errno-style error code on failure. Returns > 0 + if systemd could be notified, 0 if it couldn't possibly because + systemd is not running. + + Example: When a daemon finished starting up, it could issue this + call to notify systemd about it: + + sd_notify(0, "READY=1"); + + See sd_notifyf() for more complete examples. + + See sd_notify(3) for more information. +*/ +int sd_notify(int unset_environment, const char *state); + +/* + Similar to sd_notify() but takes a format string. + + Example 1: A daemon could send the following after initialization: + + sd_notifyf(0, "READY=1\n" + "STATUS=Processing requests...\n" + "MAINPID=%lu", + (unsigned long) getpid()); + + Example 2: A daemon could send the following shortly before + exiting, on failure: + + sd_notifyf(0, "STATUS=Failed to start up: %s\n" + "ERRNO=%i", + strerror(errno), + errno); + + See sd_notifyf(3) for more information. +*/ +int sd_notifyf(int unset_environment, const char *format, ...) _sd_printf_(2,3); + +/* + Similar to sd_notify(), but send the message on behalf of another + process, if the appropriate permissions are available. +*/ +int sd_pid_notify(pid_t pid, int unset_environment, const char *state); + +/* + Similar to sd_notifyf(), but send the message on behalf of another + process, if the appropriate permissions are available. +*/ +int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...) _sd_printf_(3,4); + +/* + Similar to sd_pid_notify(), but also passes the specified fd array + to the service manager for storage. This is particularly useful for + FDSTORE=1 messages. +*/ +int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds); + +/* + Returns > 0 if the system was booted with systemd. Returns < 0 on + error. Returns 0 if the system was not booted with systemd. Note + that all of the functions above handle non-systemd boots just + fine. You should NOT protect them with a call to this function. Also + note that this function checks whether the system, not the user + session is controlled by systemd. However the functions above work + for both user and system services. + + See sd_booted(3) for more information. +*/ +int sd_booted(void); + +/* + Returns > 0 if the service manager expects watchdog keep-alive + events to be sent regularly via sd_notify(0, "WATCHDOG=1"). Returns + 0 if it does not expect this. If the usec argument is non-NULL + returns the watchdog timeout in µs after which the service manager + will act on a process that has not sent a watchdog keep alive + message. This function is useful to implement services that + recognize automatically if they are being run under supervision of + systemd with WatchdogSec= set. It is recommended for clients to + generate keep-alive pings via sd_notify(0, "WATCHDOG=1") every half + of the returned time. + + See sd_watchdog_enabled(3) for more information. +*/ +int sd_watchdog_enabled(int unset_environment, uint64_t *usec); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h new file mode 100644 index 00000000..3c5c88c5 --- /dev/null +++ b/src/systemd/sd-device.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddevicehfoo +#define foosddevicehfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "sd-event.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_device sd_device; +typedef struct sd_device_enumerator sd_device_enumerator; +typedef struct sd_device_monitor sd_device_monitor; + +/* callback */ + +typedef int (*sd_device_monitor_handler_t)(sd_device_monitor *m, sd_device *device, void *userdata); + +/* device */ + +sd_device *sd_device_ref(sd_device *device); +sd_device *sd_device_unref(sd_device *device); + +int sd_device_new_from_syspath(sd_device **ret, const char *syspath); +int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum); +int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname); +int sd_device_new_from_device_id(sd_device **ret, const char *id); + +int sd_device_get_parent(sd_device *child, sd_device **ret); +int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret); + +int sd_device_get_syspath(sd_device *device, const char **ret); +int sd_device_get_subsystem(sd_device *device, const char **ret); +int sd_device_get_devtype(sd_device *device, const char **ret); +int sd_device_get_devnum(sd_device *device, dev_t *devnum); +int sd_device_get_ifindex(sd_device *device, int *ifindex); +int sd_device_get_driver(sd_device *device, const char **ret); +int sd_device_get_devpath(sd_device *device, const char **ret); +int sd_device_get_devname(sd_device *device, const char **ret); +int sd_device_get_sysname(sd_device *device, const char **ret); +int sd_device_get_sysnum(sd_device *device, const char **ret); + +int sd_device_get_is_initialized(sd_device *device); +int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec); + +const char *sd_device_get_tag_first(sd_device *device); +const char *sd_device_get_tag_next(sd_device *device); +const char *sd_device_get_devlink_first(sd_device *device); +const char *sd_device_get_devlink_next(sd_device *device); +const char *sd_device_get_property_first(sd_device *device, const char **value); +const char *sd_device_get_property_next(sd_device *device, const char **value); +const char *sd_device_get_sysattr_first(sd_device *device); +const char *sd_device_get_sysattr_next(sd_device *device); + +int sd_device_has_tag(sd_device *device, const char *tag); +int sd_device_get_property_value(sd_device *device, const char *key, const char **value); +int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value); + +int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *value); + +/* device enumerator */ + +int sd_device_enumerator_new(sd_device_enumerator **ret); +sd_device_enumerator *sd_device_enumerator_ref(sd_device_enumerator *enumerator); +sd_device_enumerator *sd_device_enumerator_unref(sd_device_enumerator *enumerator); + +sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator); +sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *enumerator); +sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerator *enumerator); +sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumerator); + +int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match); +int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumerator, const char *sysattr, const char *value, int match); +int sd_device_enumerator_add_match_property(sd_device_enumerator *enumerator, const char *property, const char *value); +int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname); +int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag); +int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent); +int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator); + +/* device monitor */ + +int sd_device_monitor_new(sd_device_monitor **ret); +sd_device_monitor *sd_device_monitor_ref(sd_device_monitor *m); +sd_device_monitor *sd_device_monitor_unref(sd_device_monitor *m); + +int sd_device_monitor_set_receive_buffer_size(sd_device_monitor *m, size_t size); +int sd_device_monitor_attach_event(sd_device_monitor *m, sd_event *event); +int sd_device_monitor_detach_event(sd_device_monitor *m); +sd_event *sd_device_monitor_get_event(sd_device_monitor *m); +sd_event_source *sd_device_monitor_get_event_source(sd_device_monitor *m); +int sd_device_monitor_start(sd_device_monitor *m, sd_device_monitor_handler_t callback, void *userdata); +int sd_device_monitor_stop(sd_device_monitor *m); + +int sd_device_monitor_filter_add_match_subsystem_devtype(sd_device_monitor *m, const char *subsystem, const char *devtype); +int sd_device_monitor_filter_add_match_tag(sd_device_monitor *m, const char *tag); +int sd_device_monitor_filter_update(sd_device_monitor *m); +int sd_device_monitor_filter_remove(sd_device_monitor *m); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_device, sd_device_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_device_enumerator, sd_device_enumerator_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_device_monitor, sd_device_monitor_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h new file mode 100644 index 00000000..f97e35b6 --- /dev/null +++ b/src/systemd/sd-dhcp-client.h @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddhcpclienthfoo +#define foosddhcpclienthfoo + +/*** + Copyright © 2013 Intel Corporation. All rights reserved. + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include + +#include "sd-dhcp-lease.h" +#include "sd-dhcp-option.h" +#include "sd-event.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +enum { + SD_DHCP_CLIENT_EVENT_STOP = 0, + SD_DHCP_CLIENT_EVENT_IP_ACQUIRE = 1, + SD_DHCP_CLIENT_EVENT_IP_CHANGE = 2, + SD_DHCP_CLIENT_EVENT_EXPIRED = 3, + SD_DHCP_CLIENT_EVENT_RENEW = 4, + SD_DHCP_CLIENT_EVENT_SELECTING = 5, +}; + +enum { + SD_DHCP_OPTION_PAD = 0, + SD_DHCP_OPTION_SUBNET_MASK = 1, + SD_DHCP_OPTION_TIME_OFFSET = 2, + SD_DHCP_OPTION_ROUTER = 3, + SD_DHCP_OPTION_DOMAIN_NAME_SERVER = 6, + SD_DHCP_OPTION_HOST_NAME = 12, + SD_DHCP_OPTION_BOOT_FILE_SIZE = 13, + SD_DHCP_OPTION_DOMAIN_NAME = 15, + SD_DHCP_OPTION_ROOT_PATH = 17, + SD_DHCP_OPTION_ENABLE_IP_FORWARDING = 19, + SD_DHCP_OPTION_ENABLE_IP_FORWARDING_NL = 20, + SD_DHCP_OPTION_POLICY_FILTER = 21, + SD_DHCP_OPTION_INTERFACE_MDR = 22, + SD_DHCP_OPTION_INTERFACE_TTL = 23, + SD_DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24, + SD_DHCP_OPTION_INTERFACE_MTU = 26, + SD_DHCP_OPTION_BROADCAST = 28, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_ROUTER_DISCOVER = 31, + SD_DHCP_OPTION_STATIC_ROUTE = 33, + SD_DHCP_OPTION_NTP_SERVER = 42, + SD_DHCP_OPTION_VENDOR_SPECIFIC = 43, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_NETBIOS_NAMESERVER = 44, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_NETBIOS_NODETYPE = 46, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_NETBIOS_SCOPE = 47, + SD_DHCP_OPTION_REQUESTED_IP_ADDRESS = 50, + SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51, + SD_DHCP_OPTION_OVERLOAD = 52, + SD_DHCP_OPTION_MESSAGE_TYPE = 53, + SD_DHCP_OPTION_SERVER_IDENTIFIER = 54, + SD_DHCP_OPTION_PARAMETER_REQUEST_LIST = 55, + SD_DHCP_OPTION_ERROR_MESSAGE = 56, + SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57, + SD_DHCP_OPTION_RENEWAL_T1_TIME = 58, + SD_DHCP_OPTION_REBINDING_T2_TIME = 59, + SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60, + SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61, + SD_DHCP_OPTION_USER_CLASS = 77, + SD_DHCP_OPTION_FQDN = 81, + SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100, + SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101, + SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119, + SD_DHCP_OPTION_SIP_SERVER = 120, + SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121, + SD_DHCP_OPTION_PRIVATE_BASE = 224, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE = 249, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY = 252, + SD_DHCP_OPTION_PRIVATE_LAST = 254, + SD_DHCP_OPTION_END = 255, +}; + +typedef struct sd_dhcp_client sd_dhcp_client; + +typedef int (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata); +int sd_dhcp_client_set_callback( + sd_dhcp_client *client, + sd_dhcp_client_callback_t cb, + void *userdata); + +int sd_dhcp_client_set_request_option( + sd_dhcp_client *client, + uint8_t option); +int sd_dhcp_client_set_request_address( + sd_dhcp_client *client, + const struct in_addr *last_address); +int sd_dhcp_client_set_request_broadcast( + sd_dhcp_client *client, + int broadcast); +int sd_dhcp_client_set_ifindex( + sd_dhcp_client *client, + int interface_index); +int sd_dhcp_client_set_mac( + sd_dhcp_client *client, + const uint8_t *addr, + size_t addr_len, + uint16_t arp_type); +int sd_dhcp_client_set_client_id( + sd_dhcp_client *client, + uint8_t type, + const uint8_t *data, + size_t data_len); +int sd_dhcp_client_set_iaid_duid( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid, + uint16_t duid_type, + const void *duid, + size_t duid_len); +int sd_dhcp_client_set_iaid_duid_llt( + sd_dhcp_client *client, + bool iaid_set, + uint32_t iaid, + uint64_t llt_time); +int sd_dhcp_client_set_duid( + sd_dhcp_client *client, + uint16_t duid_type, + const void *duid, + size_t duid_len); +int sd_dhcp_client_set_duid_llt( + sd_dhcp_client *client, + uint64_t llt_time); +int sd_dhcp_client_get_client_id( + sd_dhcp_client *client, + uint8_t *type, + const uint8_t **data, + size_t *data_len); +int sd_dhcp_client_set_mtu( + sd_dhcp_client *client, + uint32_t mtu); +int sd_dhcp_client_set_max_attempts( + sd_dhcp_client *client, + uint64_t attempt); +int sd_dhcp_client_set_client_port( + sd_dhcp_client *client, + uint16_t port); +int sd_dhcp_client_set_hostname( + sd_dhcp_client *client, + const char *hostname); +int sd_dhcp_client_set_vendor_class_identifier( + sd_dhcp_client *client, + const char *vci); +int sd_dhcp_client_set_user_class( + sd_dhcp_client *client, + const char* const *user_class); +int sd_dhcp_client_get_lease( + sd_dhcp_client *client, + sd_dhcp_lease **ret); +int sd_dhcp_client_set_service_type( + sd_dhcp_client *client, + int type); + +int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v); + +int sd_dhcp_client_stop(sd_dhcp_client *client); +int sd_dhcp_client_start(sd_dhcp_client *client); +int sd_dhcp_client_send_release(sd_dhcp_client *client); +int sd_dhcp_client_send_renew(sd_dhcp_client *client); + +sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client); +sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client); + +/* NOTE: anonymize parameter is used to initialize PRL memory with different + * options when using RFC7844 Anonymity Profiles */ +int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize); + +int sd_dhcp_client_attach_event( + sd_dhcp_client *client, + sd_event *event, + int64_t priority); +int sd_dhcp_client_detach_event(sd_dhcp_client *client); +sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_client, sd_dhcp_client_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-dhcp-lease.h b/src/systemd/sd-dhcp-lease.h new file mode 100644 index 00000000..b80d607f --- /dev/null +++ b/src/systemd/sd-dhcp-lease.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddhcpleasehfoo +#define foosddhcpleasehfoo + +/*** + Copyright © 2013 Intel Corporation. All rights reserved. + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_dhcp_lease sd_dhcp_lease; +typedef struct sd_dhcp_route sd_dhcp_route; + +sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease); +sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease); + +int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr); +int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime); +int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1); +int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2); +int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr); +int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr); +int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr); +int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr); +int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr); +int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr); +int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr); +int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr); +int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu); +int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); +int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains); +int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname); +int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path); +int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes); +int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len); +int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len); +int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone); + +int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination); +int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length); +int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway); +int sd_dhcp_route_get_option(sd_dhcp_route *route); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-dhcp-option.h b/src/systemd/sd-dhcp-option.h new file mode 100644 index 00000000..45dbd279 --- /dev/null +++ b/src/systemd/sd-dhcp-option.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddhcpoptionhfoo +#define foosddhcpoptionhfoo + +/*** + Copyright © 2013 Intel Corporation. All rights reserved. + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_dhcp_option sd_dhcp_option; + +int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret); +sd_dhcp_option *sd_dhcp_option_ref(sd_dhcp_option *ra); +sd_dhcp_option *sd_dhcp_option_unref(sd_dhcp_option *ra); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_option, sd_dhcp_option_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h new file mode 100644 index 00000000..5950506c --- /dev/null +++ b/src/systemd/sd-dhcp-server.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddhcpserverhfoo +#define foosddhcpserverhfoo + +/*** + Copyright © 2013 Intel Corporation. All rights reserved. + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include "sd-dhcp-option.h" +#include "sd-event.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_dhcp_server sd_dhcp_server; + +int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex); + +sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server); +sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server); + +int sd_dhcp_server_attach_event(sd_dhcp_server *client, sd_event *event, int64_t priority); +int sd_dhcp_server_detach_event(sd_dhcp_server *client); +sd_event *sd_dhcp_server_get_event(sd_dhcp_server *client); + +int sd_dhcp_server_is_running(sd_dhcp_server *server); + +int sd_dhcp_server_start(sd_dhcp_server *server); +int sd_dhcp_server_stop(sd_dhcp_server *server); + +int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *address, unsigned char prefixlen, uint32_t offset, uint32_t size); + +int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone); +int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n); +int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n); +int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n); +int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled); + +int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v); + +int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t); +int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t); + +int sd_dhcp_server_forcerenew(sd_dhcp_server *server); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_server, sd_dhcp_server_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h new file mode 100644 index 00000000..be34d43e --- /dev/null +++ b/src/systemd/sd-dhcp6-client.h @@ -0,0 +1,158 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddhcp6clienthfoo +#define foosddhcp6clienthfoo + +/*** + Copyright © 2014 Intel Corporation. All rights reserved. + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "sd-dhcp6-lease.h" +#include "sd-event.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +enum { + SD_DHCP6_CLIENT_EVENT_STOP = 0, + SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE = 10, + SD_DHCP6_CLIENT_EVENT_RETRANS_MAX = 11, + SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE = 12, + SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST = 13, +}; + +enum { + SD_DHCP6_OPTION_CLIENTID = 1, + SD_DHCP6_OPTION_SERVERID = 2, + SD_DHCP6_OPTION_IA_NA = 3, + SD_DHCP6_OPTION_IA_TA = 4, + SD_DHCP6_OPTION_IAADDR = 5, + SD_DHCP6_OPTION_ORO = 6, + SD_DHCP6_OPTION_PREFERENCE = 7, + SD_DHCP6_OPTION_ELAPSED_TIME = 8, + SD_DHCP6_OPTION_RELAY_MSG = 9, + /* option code 10 is unassigned */ + SD_DHCP6_OPTION_AUTH = 11, + SD_DHCP6_OPTION_UNICAST = 12, + SD_DHCP6_OPTION_STATUS_CODE = 13, + SD_DHCP6_OPTION_RAPID_COMMIT = 14, + SD_DHCP6_OPTION_USER_CLASS = 15, + SD_DHCP6_OPTION_VENDOR_CLASS = 16, + SD_DHCP6_OPTION_VENDOR_OPTS = 17, + SD_DHCP6_OPTION_INTERFACE_ID = 18, + SD_DHCP6_OPTION_RECONF_MSG = 19, + SD_DHCP6_OPTION_RECONF_ACCEPT = 20, + + SD_DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */ + SD_DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */ + SD_DHCP6_OPTION_IA_PD = 25, /* RFC 3633, prefix delegation */ + SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, prefix delegation */ + + SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */ + SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME = 32, /* RFC 8415, sec. 21.23 */ + + /* option code 35 is unassigned */ + + SD_DHCP6_OPTION_FQDN = 39, /* RFC 4704 */ + + SD_DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */ + + /* option codes 89-142 are unassigned */ + /* option codes 144-65535 are unassigned */ +}; + +typedef struct sd_dhcp6_client sd_dhcp6_client; + +typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, void *userdata); +int sd_dhcp6_client_set_callback( + sd_dhcp6_client *client, + sd_dhcp6_client_callback_t cb, + void *userdata); + +int sd_dhcp6_client_set_ifindex( + sd_dhcp6_client *client, + int interface_index); +int sd_dhcp6_client_set_local_address( + sd_dhcp6_client *client, + const struct in6_addr *local_address); +int sd_dhcp6_client_set_mac( + sd_dhcp6_client *client, + const uint8_t *addr, + size_t addr_len, + uint16_t arp_type); +int sd_dhcp6_client_set_duid( + sd_dhcp6_client *client, + uint16_t duid_type, + const void *duid, + size_t duid_len); +int sd_dhcp6_client_set_duid_llt( + sd_dhcp6_client *client, + uint64_t llt_time); +int sd_dhcp6_client_set_iaid( + sd_dhcp6_client *client, + uint32_t iaid); +int sd_dhcp6_client_set_fqdn( + sd_dhcp6_client *client, + const char *fqdn); +int sd_dhcp6_client_set_information_request( + sd_dhcp6_client *client, + int enabled); +int sd_dhcp6_client_get_information_request( + sd_dhcp6_client *client, + int *enabled); +int sd_dhcp6_client_set_request_option( + sd_dhcp6_client *client, + uint16_t option); +int sd_dhcp6_client_set_prefix_delegation_hint( + sd_dhcp6_client *client, + uint8_t prefixlen, + const struct in6_addr *pd_address); +int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, + int *delegation); +int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, + int delegation); +int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client, + int *request); +int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client, + int request); +int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transaction_id); + +int sd_dhcp6_client_get_lease( + sd_dhcp6_client *client, + sd_dhcp6_lease **ret); + +int sd_dhcp6_client_stop(sd_dhcp6_client *client); +int sd_dhcp6_client_start(sd_dhcp6_client *client); +int sd_dhcp6_client_is_running(sd_dhcp6_client *client); +int sd_dhcp6_client_attach_event( + sd_dhcp6_client *client, + sd_event *event, + int64_t priority); +int sd_dhcp6_client_detach_event(sd_dhcp6_client *client); +sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client); +sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client); +sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client); +int sd_dhcp6_client_new(sd_dhcp6_client **ret); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_client, sd_dhcp6_client_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-dhcp6-lease.h b/src/systemd/sd-dhcp6-lease.h new file mode 100644 index 00000000..33a32a6d --- /dev/null +++ b/src/systemd/sd-dhcp6-lease.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddhcp6leasehfoo +#define foosddhcp6leasehfoo + +/*** + Copyright © 2014-2015 Intel Corporation. All rights reserved. + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_dhcp6_lease sd_dhcp6_lease; + +void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease); +int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, + struct in6_addr *addr, + uint32_t *lifetime_preferred, + uint32_t *lifetime_valid); +void sd_dhcp6_lease_reset_pd_prefix_iter(sd_dhcp6_lease *lease); +int sd_dhcp6_lease_get_pd(sd_dhcp6_lease *lease, struct in6_addr *prefix, + uint8_t *prefix_len, + uint32_t *lifetime_preferred, + uint32_t *lifetime_valid); + +int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs); +int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains); +int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, + struct in6_addr **addrs); +int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn); + +sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease); +sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_lease, sd_dhcp6_lease_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h new file mode 100644 index 00000000..b14c9269 --- /dev/null +++ b/src/systemd/sd-event.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdeventhfoo +#define foosdeventhfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include +#include +#include + +#include "_sd-common.h" + +/* + Why is this better than pure epoll? + + - Supports event source prioritization + - Scales better with a large number of time events because it does not require one timerfd each + - Automatically tries to coalesce timer events system-wide + - Handles signals, child PIDs, inotify events + - Supports systemd-style automatic watchdog event generation +*/ + +_SD_BEGIN_DECLARATIONS; + +#define SD_EVENT_DEFAULT ((sd_event *) 1) + +typedef struct sd_event sd_event; +typedef struct sd_event_source sd_event_source; + +enum { + SD_EVENT_OFF = 0, + SD_EVENT_ON = 1, + SD_EVENT_ONESHOT = -1 +}; + +enum { + SD_EVENT_INITIAL, + SD_EVENT_ARMED, + SD_EVENT_PENDING, + SD_EVENT_RUNNING, + SD_EVENT_EXITING, + SD_EVENT_FINISHED, + SD_EVENT_PREPARING +}; + +enum { + /* And everything in-between and outside is good too */ + SD_EVENT_PRIORITY_IMPORTANT = -100, + SD_EVENT_PRIORITY_NORMAL = 0, + SD_EVENT_PRIORITY_IDLE = 100 +}; + +typedef int (*sd_event_handler_t)(sd_event_source *s, void *userdata); +typedef int (*sd_event_io_handler_t)(sd_event_source *s, int fd, uint32_t revents, void *userdata); +typedef int (*sd_event_time_handler_t)(sd_event_source *s, uint64_t usec, void *userdata); +typedef int (*sd_event_signal_handler_t)(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata); +#if defined _GNU_SOURCE || (defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 199309L) +typedef int (*sd_event_child_handler_t)(sd_event_source *s, const siginfo_t *si, void *userdata); +#else +typedef void* sd_event_child_handler_t; +#endif +typedef int (*sd_event_inotify_handler_t)(sd_event_source *s, const struct inotify_event *event, void *userdata); +typedef _sd_destroy_t sd_event_destroy_t; + +int sd_event_default(sd_event **e); + +int sd_event_new(sd_event **e); +sd_event* sd_event_ref(sd_event *e); +sd_event* sd_event_unref(sd_event *e); + +int sd_event_add_io(sd_event *e, sd_event_source **s, int fd, uint32_t events, sd_event_io_handler_t callback, void *userdata); +int sd_event_add_time(sd_event *e, sd_event_source **s, clockid_t clock, uint64_t usec, uint64_t accuracy, sd_event_time_handler_t callback, void *userdata); +int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_signal_handler_t callback, void *userdata); +int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata); +int sd_event_add_inotify(sd_event *e, sd_event_source **s, const char *path, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata); +int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); +int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); +int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); + +int sd_event_prepare(sd_event *e); +int sd_event_wait(sd_event *e, uint64_t usec); +int sd_event_dispatch(sd_event *e); +int sd_event_run(sd_event *e, uint64_t usec); +int sd_event_loop(sd_event *e); +int sd_event_exit(sd_event *e, int code); + +int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec); + +int sd_event_get_fd(sd_event *e); +int sd_event_get_state(sd_event *e); +int sd_event_get_tid(sd_event *e, pid_t *tid); +int sd_event_get_exit_code(sd_event *e, int *code); +int sd_event_set_watchdog(sd_event *e, int b); +int sd_event_get_watchdog(sd_event *e); +int sd_event_get_iteration(sd_event *e, uint64_t *ret); + +sd_event_source* sd_event_source_ref(sd_event_source *s); +sd_event_source* sd_event_source_unref(sd_event_source *s); +sd_event_source* sd_event_source_disable_unref(sd_event_source *s); + +sd_event *sd_event_source_get_event(sd_event_source *s); +void* sd_event_source_get_userdata(sd_event_source *s); +void* sd_event_source_set_userdata(sd_event_source *s, void *userdata); + +int sd_event_source_set_description(sd_event_source *s, const char *description); +int sd_event_source_get_description(sd_event_source *s, const char **description); +int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback); +int sd_event_source_get_pending(sd_event_source *s); +int sd_event_source_get_priority(sd_event_source *s, int64_t *priority); +int sd_event_source_set_priority(sd_event_source *s, int64_t priority); +int sd_event_source_get_enabled(sd_event_source *s, int *enabled); +int sd_event_source_set_enabled(sd_event_source *s, int enabled); +int sd_event_source_get_io_fd(sd_event_source *s); +int sd_event_source_set_io_fd(sd_event_source *s, int fd); +int sd_event_source_get_io_fd_own(sd_event_source *s); +int sd_event_source_set_io_fd_own(sd_event_source *s, int own); +int sd_event_source_get_io_events(sd_event_source *s, uint32_t* events); +int sd_event_source_set_io_events(sd_event_source *s, uint32_t events); +int sd_event_source_get_io_revents(sd_event_source *s, uint32_t* revents); +int sd_event_source_get_time(sd_event_source *s, uint64_t *usec); +int sd_event_source_set_time(sd_event_source *s, uint64_t usec); +int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *usec); +int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec); +int sd_event_source_get_time_clock(sd_event_source *s, clockid_t *clock); +int sd_event_source_get_signal(sd_event_source *s); +int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid); +int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret); +int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback); +int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret); +int sd_event_source_get_floating(sd_event_source *s); +int sd_event_source_set_floating(sd_event_source *s, int b); + +/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */ +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_disable_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-hwdb.h b/src/systemd/sd-hwdb.h new file mode 100644 index 00000000..2b0cd7f5 --- /dev/null +++ b/src/systemd/sd-hwdb.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdhwdbhfoo +#define foosdhwdbhfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_hwdb sd_hwdb; + +sd_hwdb *sd_hwdb_ref(sd_hwdb *hwdb); +sd_hwdb *sd_hwdb_unref(sd_hwdb *hwdb); + +int sd_hwdb_new(sd_hwdb **ret); + +int sd_hwdb_get(sd_hwdb *hwdb, const char *modalias, const char *key, const char **value); + +int sd_hwdb_seek(sd_hwdb *hwdb, const char *modalias); +int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value); + +/* the inverse condition avoids ambiguity of dangling 'else' after the macro */ +#define SD_HWDB_FOREACH_PROPERTY(hwdb, modalias, key, value) \ + if (sd_hwdb_seek(hwdb, modalias) < 0) { } \ + else while (sd_hwdb_enumerate(hwdb, &(key), &(value)) > 0) + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_hwdb, sd_hwdb_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-id128.h b/src/systemd/sd-id128.h new file mode 100644 index 00000000..9b00b76e --- /dev/null +++ b/src/systemd/sd-id128.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdid128hfoo +#define foosdid128hfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +/* 128-bit ID APIs. See sd-id128(3) for more information. */ + +typedef union sd_id128 sd_id128_t; + +union sd_id128 { + uint8_t bytes[16]; + uint64_t qwords[2]; +}; + +#define SD_ID128_STRING_MAX 33 + +char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]); +int sd_id128_from_string(const char *s, sd_id128_t *ret); + +int sd_id128_randomize(sd_id128_t *ret); + +int sd_id128_get_machine(sd_id128_t *ret); +int sd_id128_get_boot(sd_id128_t *ret); +int sd_id128_get_invocation(sd_id128_t *ret); + +int sd_id128_get_machine_app_specific(sd_id128_t app_id, sd_id128_t *ret); +int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret); + +#define SD_ID128_ARRAY(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ + { .bytes = { 0x##v0, 0x##v1, 0x##v2, 0x##v3, 0x##v4, 0x##v5, 0x##v6, 0x##v7, \ + 0x##v8, 0x##v9, 0x##v10, 0x##v11, 0x##v12, 0x##v13, 0x##v14, 0x##v15 }} + +#define SD_ID128_MAKE(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) \ + ((const sd_id128_t) SD_ID128_ARRAY(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)) + +/* Note that SD_ID128_FORMAT_VAL will evaluate the passed argument 16 + * times. It is hence not a good idea to call this macro with an + * expensive function as parameter or an expression with side + * effects */ + +#define SD_ID128_FORMAT_STR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" +#define SD_ID128_FORMAT_VAL(x) (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15] + +/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format */ +#define SD_ID128_UUID_FORMAT_STR "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" + +#define SD_ID128_CONST_STR(x) \ + ((const char[SD_ID128_STRING_MAX]) { \ + ((x).bytes[0] >> 4) >= 10 ? 'a' + ((x).bytes[0] >> 4) - 10 : '0' + ((x).bytes[0] >> 4), \ + ((x).bytes[0] & 15) >= 10 ? 'a' + ((x).bytes[0] & 15) - 10 : '0' + ((x).bytes[0] & 15), \ + ((x).bytes[1] >> 4) >= 10 ? 'a' + ((x).bytes[1] >> 4) - 10 : '0' + ((x).bytes[1] >> 4), \ + ((x).bytes[1] & 15) >= 10 ? 'a' + ((x).bytes[1] & 15) - 10 : '0' + ((x).bytes[1] & 15), \ + ((x).bytes[2] >> 4) >= 10 ? 'a' + ((x).bytes[2] >> 4) - 10 : '0' + ((x).bytes[2] >> 4), \ + ((x).bytes[2] & 15) >= 10 ? 'a' + ((x).bytes[2] & 15) - 10 : '0' + ((x).bytes[2] & 15), \ + ((x).bytes[3] >> 4) >= 10 ? 'a' + ((x).bytes[3] >> 4) - 10 : '0' + ((x).bytes[3] >> 4), \ + ((x).bytes[3] & 15) >= 10 ? 'a' + ((x).bytes[3] & 15) - 10 : '0' + ((x).bytes[3] & 15), \ + ((x).bytes[4] >> 4) >= 10 ? 'a' + ((x).bytes[4] >> 4) - 10 : '0' + ((x).bytes[4] >> 4), \ + ((x).bytes[4] & 15) >= 10 ? 'a' + ((x).bytes[4] & 15) - 10 : '0' + ((x).bytes[4] & 15), \ + ((x).bytes[5] >> 4) >= 10 ? 'a' + ((x).bytes[5] >> 4) - 10 : '0' + ((x).bytes[5] >> 4), \ + ((x).bytes[5] & 15) >= 10 ? 'a' + ((x).bytes[5] & 15) - 10 : '0' + ((x).bytes[5] & 15), \ + ((x).bytes[6] >> 4) >= 10 ? 'a' + ((x).bytes[6] >> 4) - 10 : '0' + ((x).bytes[6] >> 4), \ + ((x).bytes[6] & 15) >= 10 ? 'a' + ((x).bytes[6] & 15) - 10 : '0' + ((x).bytes[6] & 15), \ + ((x).bytes[7] >> 4) >= 10 ? 'a' + ((x).bytes[7] >> 4) - 10 : '0' + ((x).bytes[7] >> 4), \ + ((x).bytes[7] & 15) >= 10 ? 'a' + ((x).bytes[7] & 15) - 10 : '0' + ((x).bytes[7] & 15), \ + ((x).bytes[8] >> 4) >= 10 ? 'a' + ((x).bytes[8] >> 4) - 10 : '0' + ((x).bytes[8] >> 4), \ + ((x).bytes[8] & 15) >= 10 ? 'a' + ((x).bytes[8] & 15) - 10 : '0' + ((x).bytes[8] & 15), \ + ((x).bytes[9] >> 4) >= 10 ? 'a' + ((x).bytes[9] >> 4) - 10 : '0' + ((x).bytes[9] >> 4), \ + ((x).bytes[9] & 15) >= 10 ? 'a' + ((x).bytes[9] & 15) - 10 : '0' + ((x).bytes[9] & 15), \ + ((x).bytes[10] >> 4) >= 10 ? 'a' + ((x).bytes[10] >> 4) - 10 : '0' + ((x).bytes[10] >> 4), \ + ((x).bytes[10] & 15) >= 10 ? 'a' + ((x).bytes[10] & 15) - 10 : '0' + ((x).bytes[10] & 15), \ + ((x).bytes[11] >> 4) >= 10 ? 'a' + ((x).bytes[11] >> 4) - 10 : '0' + ((x).bytes[11] >> 4), \ + ((x).bytes[11] & 15) >= 10 ? 'a' + ((x).bytes[11] & 15) - 10 : '0' + ((x).bytes[11] & 15), \ + ((x).bytes[12] >> 4) >= 10 ? 'a' + ((x).bytes[12] >> 4) - 10 : '0' + ((x).bytes[12] >> 4), \ + ((x).bytes[12] & 15) >= 10 ? 'a' + ((x).bytes[12] & 15) - 10 : '0' + ((x).bytes[12] & 15), \ + ((x).bytes[13] >> 4) >= 10 ? 'a' + ((x).bytes[13] >> 4) - 10 : '0' + ((x).bytes[13] >> 4), \ + ((x).bytes[13] & 15) >= 10 ? 'a' + ((x).bytes[13] & 15) - 10 : '0' + ((x).bytes[13] & 15), \ + ((x).bytes[14] >> 4) >= 10 ? 'a' + ((x).bytes[14] >> 4) - 10 : '0' + ((x).bytes[14] >> 4), \ + ((x).bytes[14] & 15) >= 10 ? 'a' + ((x).bytes[14] & 15) - 10 : '0' + ((x).bytes[14] & 15), \ + ((x).bytes[15] >> 4) >= 10 ? 'a' + ((x).bytes[15] >> 4) - 10 : '0' + ((x).bytes[15] >> 4), \ + ((x).bytes[15] & 15) >= 10 ? 'a' + ((x).bytes[15] & 15) - 10 : '0' + ((x).bytes[15] & 15), \ + 0 }) + +#define SD_ID128_MAKE_STR(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \ + #a #b #c #d #e #f #g #h #i #j #k #l #m #n #o #p + +_sd_pure_ static __inline__ int sd_id128_equal(sd_id128_t a, sd_id128_t b) { + return memcmp(&a, &b, 16) == 0; +} + +_sd_pure_ static __inline__ int sd_id128_is_null(sd_id128_t a) { + return a.qwords[0] == 0 && a.qwords[1] == 0; +} + +_sd_pure_ static __inline__ int sd_id128_is_allf(sd_id128_t a) { + return a.qwords[0] == UINT64_C(0xFFFFFFFFFFFFFFFF) && a.qwords[1] == UINT64_C(0xFFFFFFFFFFFFFFFF); +} + +#define SD_ID128_NULL ((const sd_id128_t) { .qwords = { 0, 0 }}) +#define SD_ID128_ALLF ((const sd_id128_t) { .qwords = { UINT64_C(0xFFFFFFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF) }}) + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-ipv4acd.h b/src/systemd/sd-ipv4acd.h new file mode 100644 index 00000000..ebf723fc --- /dev/null +++ b/src/systemd/sd-ipv4acd.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdipv4acdfoo +#define foosdipv4acdfoo + +/*** + Copyright © 2014 Axis Communications AB. All rights reserved. + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "sd-event.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +enum { + SD_IPV4ACD_EVENT_STOP = 0, + SD_IPV4ACD_EVENT_BIND = 1, + SD_IPV4ACD_EVENT_CONFLICT = 2, +}; + +typedef struct sd_ipv4acd sd_ipv4acd; +typedef void (*sd_ipv4acd_callback_t)(sd_ipv4acd *acd, int event, void *userdata); + +int sd_ipv4acd_detach_event(sd_ipv4acd *acd); +int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority); +int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address); +int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata); +int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr); +int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int interface_index); +int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address); +int sd_ipv4acd_is_running(sd_ipv4acd *acd); +int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts); +int sd_ipv4acd_stop(sd_ipv4acd *acd); +sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *acd); +sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd); +int sd_ipv4acd_new(sd_ipv4acd **ret); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4acd, sd_ipv4acd_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-ipv4ll.h b/src/systemd/sd-ipv4ll.h new file mode 100644 index 00000000..71bd4cfe --- /dev/null +++ b/src/systemd/sd-ipv4ll.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdipv4llfoo +#define foosdipv4llfoo + +/*** + Copyright © 2014 Axis Communications AB. All rights reserved. + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include "sd-event.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +enum { + SD_IPV4LL_EVENT_STOP = 0, + SD_IPV4LL_EVENT_BIND = 1, + SD_IPV4LL_EVENT_CONFLICT = 2, +}; + +typedef struct sd_ipv4ll sd_ipv4ll; +typedef void (*sd_ipv4ll_callback_t)(sd_ipv4ll *ll, int event, void *userdata); + +int sd_ipv4ll_detach_event(sd_ipv4ll *ll); +int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority); +int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address); +int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata); +int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr); +int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int interface_index); +int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address); +int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed); +int sd_ipv4ll_is_running(sd_ipv4ll *ll); +int sd_ipv4ll_restart(sd_ipv4ll *ll); +int sd_ipv4ll_start(sd_ipv4ll *ll); +int sd_ipv4ll_stop(sd_ipv4ll *ll); +sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll); +sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll); +int sd_ipv4ll_new(sd_ipv4ll **ret); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4ll, sd_ipv4ll_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h new file mode 100644 index 00000000..b4bf3b91 --- /dev/null +++ b/src/systemd/sd-journal.h @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdjournalhfoo +#define foosdjournalhfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include + +#include "sd-id128.h" + +#include "_sd-common.h" + +/* Journal APIs. See sd-journal(3) for more information. */ + +_SD_BEGIN_DECLARATIONS; + +/* Write to daemon */ +int sd_journal_print(int priority, const char *format, ...) _sd_printf_(2, 3); +int sd_journal_printv(int priority, const char *format, va_list ap) _sd_printf_(2, 0); +int sd_journal_send(const char *format, ...) _sd_printf_(1, 0) _sd_sentinel_; +int sd_journal_sendv(const struct iovec *iov, int n); +int sd_journal_perror(const char *message); + +/* Used by the macros below. You probably don't want to call this directly. */ +int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) _sd_printf_(5, 6); +int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) _sd_printf_(5, 0); +int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) _sd_printf_(4, 0) _sd_sentinel_; +int sd_journal_sendv_with_location(const char *file, const char *line, const char *func, const struct iovec *iov, int n); +int sd_journal_perror_with_location(const char *file, const char *line, const char *func, const char *message); + +/* implicitly add code location to messages sent, if this is enabled */ +#ifndef SD_JOURNAL_SUPPRESS_LOCATION + +#define sd_journal_print(priority, ...) sd_journal_print_with_location(priority, "CODE_FILE=" __FILE__, "CODE_LINE=" _SD_STRINGIFY(__LINE__), __func__, __VA_ARGS__) +#define sd_journal_printv(priority, format, ap) sd_journal_printv_with_location(priority, "CODE_FILE=" __FILE__, "CODE_LINE=" _SD_STRINGIFY(__LINE__), __func__, format, ap) +#define sd_journal_send(...) sd_journal_send_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _SD_STRINGIFY(__LINE__), __func__, __VA_ARGS__) +#define sd_journal_sendv(iovec, n) sd_journal_sendv_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _SD_STRINGIFY(__LINE__), __func__, iovec, n) +#define sd_journal_perror(message) sd_journal_perror_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _SD_STRINGIFY(__LINE__), __func__, message) + +#endif + +int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix); + +/* Browse journal stream */ + +typedef struct sd_journal sd_journal; + +/* Open flags */ +enum { + SD_JOURNAL_LOCAL_ONLY = 1 << 0, + SD_JOURNAL_RUNTIME_ONLY = 1 << 1, + SD_JOURNAL_SYSTEM = 1 << 2, + SD_JOURNAL_CURRENT_USER = 1 << 3, + SD_JOURNAL_OS_ROOT = 1 << 4, + + SD_JOURNAL_SYSTEM_ONLY = SD_JOURNAL_SYSTEM /* deprecated name */ +}; + +/* Wakeup event types */ +enum { + SD_JOURNAL_NOP, + SD_JOURNAL_APPEND, + SD_JOURNAL_INVALIDATE +}; + +int sd_journal_open(sd_journal **ret, int flags); +int sd_journal_open_directory(sd_journal **ret, const char *path, int flags); +int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags); +int sd_journal_open_files(sd_journal **ret, const char **paths, int flags); +int sd_journal_open_files_fd(sd_journal **ret, int fds[], unsigned n_fds, int flags); +int sd_journal_open_container(sd_journal **ret, const char *machine, int flags); /* deprecated */ +void sd_journal_close(sd_journal *j); + +int sd_journal_previous(sd_journal *j); +int sd_journal_next(sd_journal *j); + +int sd_journal_previous_skip(sd_journal *j, uint64_t skip); +int sd_journal_next_skip(sd_journal *j, uint64_t skip); + +int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret); +int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id); + +int sd_journal_set_data_threshold(sd_journal *j, size_t sz); +int sd_journal_get_data_threshold(sd_journal *j, size_t *sz); + +int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l); +int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l); +void sd_journal_restart_data(sd_journal *j); + +int sd_journal_add_match(sd_journal *j, const void *data, size_t size); +int sd_journal_add_disjunction(sd_journal *j); +int sd_journal_add_conjunction(sd_journal *j); +void sd_journal_flush_matches(sd_journal *j); + +int sd_journal_seek_head(sd_journal *j); +int sd_journal_seek_tail(sd_journal *j); +int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec); +int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec); +int sd_journal_seek_cursor(sd_journal *j, const char *cursor); + +int sd_journal_get_cursor(sd_journal *j, char **cursor); +int sd_journal_test_cursor(sd_journal *j, const char *cursor); + +int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to); +int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, const sd_id128_t boot_id, uint64_t *from, uint64_t *to); + +int sd_journal_get_usage(sd_journal *j, uint64_t *bytes); + +int sd_journal_query_unique(sd_journal *j, const char *field); +int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l); +void sd_journal_restart_unique(sd_journal *j); + +int sd_journal_enumerate_fields(sd_journal *j, const char **field); +void sd_journal_restart_fields(sd_journal *j); + +int sd_journal_get_fd(sd_journal *j); +int sd_journal_get_events(sd_journal *j); +int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec); +int sd_journal_process(sd_journal *j); +int sd_journal_wait(sd_journal *j, uint64_t timeout_usec); +int sd_journal_reliable_fd(sd_journal *j); + +int sd_journal_get_catalog(sd_journal *j, char **text); +int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **text); + +int sd_journal_has_runtime_files(sd_journal *j); +int sd_journal_has_persistent_files(sd_journal *j); + +/* The inverse condition avoids ambiguity of dangling 'else' after the macro */ +#define SD_JOURNAL_FOREACH(j) \ + if (sd_journal_seek_head(j) < 0) { } \ + else while (sd_journal_next(j) > 0) + +/* The inverse condition avoids ambiguity of dangling 'else' after the macro */ +#define SD_JOURNAL_FOREACH_BACKWARDS(j) \ + if (sd_journal_seek_tail(j) < 0) { } \ + else while (sd_journal_previous(j) > 0) + +/* Iterate through the data fields of the current journal entry */ +#define SD_JOURNAL_FOREACH_DATA(j, data, l) \ + for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; ) + +/* Iterate through the all known values of a specific field */ +#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \ + for (sd_journal_restart_unique(j); sd_journal_enumerate_unique((j), &(data), &(l)) > 0; ) + +/* Iterate through all known field names */ +#define SD_JOURNAL_FOREACH_FIELD(j, field) \ + for (sd_journal_restart_fields(j); sd_journal_enumerate_fields((j), &(field)) > 0; ) + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_journal, sd_journal_close); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-lldp.h b/src/systemd/sd-lldp.h new file mode 100644 index 00000000..bf3afadc --- /dev/null +++ b/src/systemd/sd-lldp.h @@ -0,0 +1,190 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdlldphfoo +#define foosdlldphfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include + +#include "sd-event.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +/* IEEE 802.1AB-2009 Clause 8: TLV Types */ +enum { + SD_LLDP_TYPE_END = 0, + SD_LLDP_TYPE_CHASSIS_ID = 1, + SD_LLDP_TYPE_PORT_ID = 2, + SD_LLDP_TYPE_TTL = 3, + SD_LLDP_TYPE_PORT_DESCRIPTION = 4, + SD_LLDP_TYPE_SYSTEM_NAME = 5, + SD_LLDP_TYPE_SYSTEM_DESCRIPTION = 6, + SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7, + SD_LLDP_TYPE_MGMT_ADDRESS = 8, + SD_LLDP_TYPE_PRIVATE = 127, +}; + +/* IEEE 802.1AB-2009 Clause 8.5.2: Chassis subtypes */ +enum { + SD_LLDP_CHASSIS_SUBTYPE_RESERVED = 0, + SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT = 1, + SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS = 2, + SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT = 3, + SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS = 4, + SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS = 5, + SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME = 6, + SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED = 7, +}; + +/* IEEE 802.1AB-2009 Clause 8.5.3: Port subtype */ +enum { + SD_LLDP_PORT_SUBTYPE_RESERVED = 0, + SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1, + SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT = 2, + SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS = 3, + SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS = 4, + SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME = 5, + SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6, + SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7, +}; + +/* IEEE 802.1AB-2009 Clause 8.5.8: System capabilities */ +enum { + SD_LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0, + SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1, + SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE = 1 << 2, + SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP = 1 << 3, + SD_LLDP_SYSTEM_CAPABILITIES_ROUTER = 1 << 4, + SD_LLDP_SYSTEM_CAPABILITIES_PHONE = 1 << 5, + SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS = 1 << 6, + SD_LLDP_SYSTEM_CAPABILITIES_STATION = 1 << 7, + SD_LLDP_SYSTEM_CAPABILITIES_CVLAN = 1 << 8, + SD_LLDP_SYSTEM_CAPABILITIES_SVLAN = 1 << 9, + SD_LLDP_SYSTEM_CAPABILITIES_TPMR = 1 << 10, +}; + +#define SD_LLDP_SYSTEM_CAPABILITIES_ALL ((uint16_t) -1) + +#define SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS \ + ((uint16_t) \ + (SD_LLDP_SYSTEM_CAPABILITIES_REPEATER| \ + SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE| \ + SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP| \ + SD_LLDP_SYSTEM_CAPABILITIES_ROUTER| \ + SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS| \ + SD_LLDP_SYSTEM_CAPABILITIES_CVLAN| \ + SD_LLDP_SYSTEM_CAPABILITIES_SVLAN| \ + SD_LLDP_SYSTEM_CAPABILITIES_TPMR)) + +#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 } +#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f } + +/* IEEE 802.1AB-2009 Annex E */ +enum { + SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1, + SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2, + SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME = 3, + SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY = 4, + SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST = 5, + SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID = 6, + SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION = 7, +}; + +/* IEEE 802.1AB-2009 Annex F */ +enum { + SD_LLDP_OUI_802_3_SUBTYPE_MAC_PHY_CONFIG_STATUS = 1, + SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI = 2, + SD_LLDP_OUI_802_3_SUBTYPE_LINK_AGGREGATION = 3, + SD_LLDP_OUI_802_3_SUBTYPE_MAXIMUM_FRAME_SIZE = 4, +}; + +typedef struct sd_lldp sd_lldp; +typedef struct sd_lldp_neighbor sd_lldp_neighbor; + +typedef enum sd_lldp_event { + SD_LLDP_EVENT_ADDED, + SD_LLDP_EVENT_REMOVED, + SD_LLDP_EVENT_UPDATED, + SD_LLDP_EVENT_REFRESHED, + _SD_LLDP_EVENT_MAX, + _SD_LLDP_EVENT_INVALID = -1, +} sd_lldp_event; + +typedef void (*sd_lldp_callback_t)(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata); + +int sd_lldp_new(sd_lldp **ret); +sd_lldp* sd_lldp_ref(sd_lldp *lldp); +sd_lldp* sd_lldp_unref(sd_lldp *lldp); + +int sd_lldp_start(sd_lldp *lldp); +int sd_lldp_stop(sd_lldp *lldp); + +int sd_lldp_attach_event(sd_lldp *lldp, sd_event *event, int64_t priority); +int sd_lldp_detach_event(sd_lldp *lldp); +sd_event *sd_lldp_get_event(sd_lldp *lldp); + +int sd_lldp_set_callback(sd_lldp *lldp, sd_lldp_callback_t cb, void *userdata); +int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex); + +/* Controls how much and what to store in the neighbors database */ +int sd_lldp_set_neighbors_max(sd_lldp *lldp, uint64_t n); +int sd_lldp_match_capabilities(sd_lldp *lldp, uint16_t mask); +int sd_lldp_set_filter_address(sd_lldp *lldp, const struct ether_addr *address); + +int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***neighbors); + +int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size); +sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n); +sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n); + +/* Access to LLDP frame metadata */ +int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address); +int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address); +int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret); +int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size); + +/* High-level, direct, parsed out field access. These fields exist at most once, hence may be queried directly. */ +int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size); +int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size); +int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec); +int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret); +int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret); +int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret); + +/* Low-level, iterative TLV access. This is for evertyhing else, it iteratively goes through all available TLVs + * (including the ones covered with the calls above), and allows multiple TLVs for the same fields. */ +int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n); +int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n); +int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type); +int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type); +int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype); +int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype); +int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp, sd_lldp_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_lldp_neighbor, sd_lldp_neighbor_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-login.h b/src/systemd/sd-login.h new file mode 100644 index 00000000..50be5433 --- /dev/null +++ b/src/systemd/sd-login.h @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdloginhfoo +#define foosdloginhfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include "_sd-common.h" + +/* + * A few points: + * + * Instead of returning an empty string array or empty uid array, we + * may return NULL. + * + * Free the data the library returns with libc free(). String arrays + * are NULL terminated, and you need to free the array itself, in + * addition to the strings contained. + * + * We return error codes as negative errno, kernel-style. On success, we + * return 0 or positive. + * + * These functions access data in /proc, /sys/fs/cgroup, and /run. All + * of these are virtual file systems; therefore, accesses are + * relatively cheap. + * + * See sd-login(3) for more information. + */ + +_SD_BEGIN_DECLARATIONS; + +/* Get session from PID. Note that 'shared' processes of a user are + * not attached to a session, but only attached to a user. This will + * return an error for system processes and 'shared' processes of a + * user. */ +int sd_pid_get_session(pid_t pid, char **session); + +/* Get UID of the owner of the session of the PID (or in case the + * process is a 'shared' user process, the UID of that user is + * returned). This will not return the UID of the process, but rather + * the UID of the owner of the cgroup that the process is in. This will + * return an error for system processes. */ +int sd_pid_get_owner_uid(pid_t pid, uid_t *uid); + +/* Get systemd non-slice unit (i.e. service) name from PID, for system + * services. This will return an error for non-service processes. */ +int sd_pid_get_unit(pid_t pid, char **unit); + +/* Get systemd non-slice unit (i.e. service) name from PID, for user + * services. This will return an error for non-user-service + * processes. */ +int sd_pid_get_user_unit(pid_t pid, char **unit); + +/* Get slice name from PID. */ +int sd_pid_get_slice(pid_t pid, char **slice); + +/* Get user slice name from PID. */ +int sd_pid_get_user_slice(pid_t pid, char **slice); + +/* Get machine name from PID, for processes assigned to a VM or + * container. This will return an error for non-machine processes. */ +int sd_pid_get_machine_name(pid_t pid, char **machine); + +/* Get the control group from a PID, relative to the root of the + * hierarchy. */ +int sd_pid_get_cgroup(pid_t pid, char **cgroup); + +/* Similar to sd_pid_get_session(), but retrieves data about the peer + * of a connected AF_UNIX socket */ +int sd_peer_get_session(int fd, char **session); + +/* Similar to sd_pid_get_owner_uid(), but retrieves data about the peer of + * a connected AF_UNIX socket */ +int sd_peer_get_owner_uid(int fd, uid_t *uid); + +/* Similar to sd_pid_get_unit(), but retrieves data about the peer of + * a connected AF_UNIX socket */ +int sd_peer_get_unit(int fd, char **unit); + +/* Similar to sd_pid_get_user_unit(), but retrieves data about the peer of + * a connected AF_UNIX socket */ +int sd_peer_get_user_unit(int fd, char **unit); + +/* Similar to sd_pid_get_slice(), but retrieves data about the peer of + * a connected AF_UNIX socket */ +int sd_peer_get_slice(int fd, char **slice); + +/* Similar to sd_pid_get_user_slice(), but retrieves data about the peer of + * a connected AF_UNIX socket */ +int sd_peer_get_user_slice(int fd, char **slice); + +/* Similar to sd_pid_get_machine_name(), but retrieves data about the + * peer of a connected AF_UNIX socket */ +int sd_peer_get_machine_name(int fd, char **machine); + +/* Similar to sd_pid_get_cgroup(), but retrieves data about the peer + * of a connected AF_UNIX socket. */ +int sd_peer_get_cgroup(pid_t pid, char **cgroup); + +/* Get state from UID. Possible states: offline, lingering, online, active, closing */ +int sd_uid_get_state(uid_t uid, char **state); + +/* Return primary session of user, if there is any */ +int sd_uid_get_display(uid_t uid, char **session); + +/* Return 1 if UID has session on seat. If require_active is true, this will + * look for active sessions only. */ +int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat); + +/* Return sessions of user. If require_active is true, this will look for + * active sessions only. Returns the number of sessions. + * If sessions is NULL, this will just return the number of sessions. */ +int sd_uid_get_sessions(uid_t uid, int require_active, char ***sessions); + +/* Return seats of user is on. If require_active is true, this will look for + * active seats only. Returns the number of seats. + * If seats is NULL, this will just return the number of seats. */ +int sd_uid_get_seats(uid_t uid, int require_active, char ***seats); + +/* Return 1 if the session is active. */ +int sd_session_is_active(const char *session); + +/* Return 1 if the session is remote. */ +int sd_session_is_remote(const char *session); + +/* Get state from session. Possible states: online, active, closing. + * This function is a more generic version of sd_session_is_active(). */ +int sd_session_get_state(const char *session, char **state); + +/* Determine user ID of session */ +int sd_session_get_uid(const char *session, uid_t *uid); + +/* Determine seat of session */ +int sd_session_get_seat(const char *session, char **seat); + +/* Determine the (PAM) service name this session was registered by. */ +int sd_session_get_service(const char *session, char **service); + +/* Determine the type of this session, i.e. one of "tty", "x11", "wayland", "mir" or "unspecified". */ +int sd_session_get_type(const char *session, char **type); + +/* Determine the class of this session, i.e. one of "user", "greeter" or "lock-screen". */ +int sd_session_get_class(const char *session, char **clazz); + +/* Determine the desktop brand of this session, i.e. something like "GNOME", "KDE" or "systemd-console". */ +int sd_session_get_desktop(const char *session, char **desktop); + +/* Determine the X11 display of this session. */ +int sd_session_get_display(const char *session, char **display); + +/* Determine the remote host of this session. */ +int sd_session_get_remote_host(const char *session, char **remote_host); + +/* Determine the remote user of this session (if provided by PAM). */ +int sd_session_get_remote_user(const char *session, char **remote_user); + +/* Determine the TTY of this session. */ +int sd_session_get_tty(const char *session, char **display); + +/* Determine the VT number of this session. */ +int sd_session_get_vt(const char *session, unsigned *vtnr); + +/* Return active session and user of seat */ +int sd_seat_get_active(const char *seat, char **session, uid_t *uid); + +/* Return sessions and users on seat. Returns number of sessions. + * If sessions is NULL, this returns only the number of sessions. */ +int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids); + +/* Return whether the seat is multi-session capable */ +int sd_seat_can_multi_session(const char *seat); + +/* Return whether the seat is TTY capable, i.e. suitable for showing console UIs */ +int sd_seat_can_tty(const char *seat); + +/* Return whether the seat is graphics capable, i.e. suitable for showing graphical UIs */ +int sd_seat_can_graphical(const char *seat); + +/* Return the class of machine */ +int sd_machine_get_class(const char *machine, char **clazz); + +/* Return the list if host-side network interface indices of a machine */ +int sd_machine_get_ifindices(const char *machine, int **ifindices); + +/* Get all seats, store in *seats. Returns the number of seats. If + * seats is NULL, this only returns the number of seats. */ +int sd_get_seats(char ***seats); + +/* Get all sessions, store in *sessions. Returns the number of + * sessions. If sessions is NULL, this only returns the number of sessions. */ +int sd_get_sessions(char ***sessions); + +/* Get all logged in users, store in *users. Returns the number of + * users. If users is NULL, this only returns the number of users. */ +int sd_get_uids(uid_t **users); + +/* Get all running virtual machines/containers */ +int sd_get_machine_names(char ***machines); + +/* Monitor object */ +typedef struct sd_login_monitor sd_login_monitor; + +/* Create a new monitor. Category must be NULL, "seat", "session", + * "uid", or "machine" to get monitor events for the specific category + * (or all). */ +int sd_login_monitor_new(const char *category, sd_login_monitor** ret); + +/* Destroys the passed monitor. Returns NULL. */ +sd_login_monitor* sd_login_monitor_unref(sd_login_monitor *m); + +/* Flushes the monitor */ +int sd_login_monitor_flush(sd_login_monitor *m); + +/* Get FD from monitor */ +int sd_login_monitor_get_fd(sd_login_monitor *m); + +/* Get poll() mask to monitor */ +int sd_login_monitor_get_events(sd_login_monitor *m); + +/* Get timeout for poll(), as usec value relative to CLOCK_MONOTONIC's epoch */ +int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_login_monitor, sd_login_monitor_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h new file mode 100644 index 00000000..e8d26ab7 --- /dev/null +++ b/src/systemd/sd-messages.h @@ -0,0 +1,163 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdmessageshfoo +#define foosdmessageshfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "sd-id128.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +/* Hey! If you add a new message here, you *must* also update the message catalog with an appropriate explanation */ + +/* And if you add a new ID here, make sure to generate a random one with "systemd-id128 new". Do not use any other IDs, + * and do not count them up manually. */ + +#define SD_MESSAGE_JOURNAL_START SD_ID128_MAKE(f7,73,79,a8,49,0b,40,8b,be,5f,69,40,50,5a,77,7b) +#define SD_MESSAGE_JOURNAL_START_STR SD_ID128_MAKE_STR(f7,73,79,a8,49,0b,40,8b,be,5f,69,40,50,5a,77,7b) +#define SD_MESSAGE_JOURNAL_STOP SD_ID128_MAKE(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b) +#define SD_MESSAGE_JOURNAL_STOP_STR SD_ID128_MAKE_STR(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b) +#define SD_MESSAGE_JOURNAL_DROPPED SD_ID128_MAKE(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e) +#define SD_MESSAGE_JOURNAL_DROPPED_STR SD_ID128_MAKE_STR(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e) +#define SD_MESSAGE_JOURNAL_MISSED SD_ID128_MAKE(e9,bf,28,e6,e8,34,48,1b,b6,f4,8f,54,8a,d1,36,06) +#define SD_MESSAGE_JOURNAL_MISSED_STR SD_ID128_MAKE_STR(e9,bf,28,e6,e8,34,48,1b,b6,f4,8f,54,8a,d1,36,06) +#define SD_MESSAGE_JOURNAL_USAGE SD_ID128_MAKE(ec,38,7f,57,7b,84,4b,8f,a9,48,f3,3c,ad,9a,75,e6) +#define SD_MESSAGE_JOURNAL_USAGE_STR SD_ID128_MAKE_STR(ec,38,7f,57,7b,84,4b,8f,a9,48,f3,3c,ad,9a,75,e6) + +#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) +#define SD_MESSAGE_COREDUMP_STR SD_ID128_MAKE_STR(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) +#define SD_MESSAGE_TRUNCATED_CORE SD_ID128_MAKE(5a,ad,d8,e9,54,dc,4b,1a,8c,95,4d,63,fd,9e,11,37) +#define SD_MESSAGE_TRUNCATED_CORE_STR SD_ID128_MAKE_STR(5a,ad,d8,e9,54,dc,4b,1a,8c,95,4d,63,fd,9e,11,37) +#define SD_MESSAGE_BACKTRACE SD_ID128_MAKE(1f,4e,0a,44,a8,86,49,93,9a,ae,a3,4f,c6,da,8c,95) +#define SD_MESSAGE_BACKTRACE_STR SD_ID128_MAKE_STR(1f,4e,0a,44,a8,86,49,93,9a,ae,a3,4f,c6,da,8c,95) + +#define SD_MESSAGE_SESSION_START SD_ID128_MAKE(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66) +#define SD_MESSAGE_SESSION_START_STR SD_ID128_MAKE_STR(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66) +#define SD_MESSAGE_SESSION_STOP SD_ID128_MAKE(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a) +#define SD_MESSAGE_SESSION_STOP_STR SD_ID128_MAKE_STR(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a) +#define SD_MESSAGE_SEAT_START SD_ID128_MAKE(fc,be,fc,5d,a2,3d,42,80,93,f9,7c,82,a9,29,0f,7b) +#define SD_MESSAGE_SEAT_START_STR SD_ID128_MAKE_STR(fc,be,fc,5d,a2,3d,42,80,93,f9,7c,82,a9,29,0f,7b) +#define SD_MESSAGE_SEAT_STOP SD_ID128_MAKE(e7,85,2b,fe,46,78,4e,d0,ac,cd,e0,4b,c8,64,c2,d5) +#define SD_MESSAGE_SEAT_STOP_STR SD_ID128_MAKE_STR(e7,85,2b,fe,46,78,4e,d0,ac,cd,e0,4b,c8,64,c2,d5) +#define SD_MESSAGE_MACHINE_START SD_ID128_MAKE(24,d8,d4,45,25,73,40,24,96,06,83,81,a6,31,2d,f2) +#define SD_MESSAGE_MACHINE_START_STR SD_ID128_MAKE_STR(24,d8,d4,45,25,73,40,24,96,06,83,81,a6,31,2d,f2) +#define SD_MESSAGE_MACHINE_STOP SD_ID128_MAKE(58,43,2b,d3,ba,ce,47,7c,b5,14,b5,63,81,b8,a7,58) +#define SD_MESSAGE_MACHINE_STOP_STR SD_ID128_MAKE_STR(58,43,2b,d3,ba,ce,47,7c,b5,14,b5,63,81,b8,a7,58) + +#define SD_MESSAGE_TIME_CHANGE SD_ID128_MAKE(c7,a7,87,07,9b,35,4e,aa,a9,e7,7b,37,18,93,cd,27) +#define SD_MESSAGE_TIME_CHANGE_STR SD_ID128_MAKE_STR(c7,a7,87,07,9b,35,4e,aa,a9,e7,7b,37,18,93,cd,27) +#define SD_MESSAGE_TIMEZONE_CHANGE SD_ID128_MAKE(45,f8,2f,4a,ef,7a,4b,bf,94,2c,e8,61,d1,f2,09,90) +#define SD_MESSAGE_TIMEZONE_CHANGE_STR SD_ID128_MAKE_STR(45,f8,2f,4a,ef,7a,4b,bf,94,2c,e8,61,d1,f2,09,90) + +#define SD_MESSAGE_TAINTED SD_ID128_MAKE(50,87,6a,9d,b0,0f,4c,40,bd,e1,a2,ad,38,1c,3a,1b) +#define SD_MESSAGE_TAINTED_STR SD_ID128_MAKE_STR(50,87,6a,9d,b0,0f,4c,40,bd,e1,a2,ad,38,1c,3a,1b) +#define SD_MESSAGE_STARTUP_FINISHED SD_ID128_MAKE(b0,7a,24,9c,d0,24,41,4a,82,dd,00,cd,18,13,78,ff) +#define SD_MESSAGE_STARTUP_FINISHED_STR SD_ID128_MAKE_STR(b0,7a,24,9c,d0,24,41,4a,82,dd,00,cd,18,13,78,ff) +#define SD_MESSAGE_USER_STARTUP_FINISHED \ + SD_ID128_MAKE(ee,d0,0a,68,ff,d8,4e,31,88,21,05,fd,97,3a,bd,d1) +#define SD_MESSAGE_USER_STARTUP_FINISHED_STR \ + SD_ID128_MAKE_STR(ee,d0,0a,68,ff,d8,4e,31,88,21,05,fd,97,3a,bd,d1) + +#define SD_MESSAGE_SLEEP_START SD_ID128_MAKE(6b,bd,95,ee,97,79,41,e4,97,c4,8b,e2,7c,25,41,28) +#define SD_MESSAGE_SLEEP_START_STR SD_ID128_MAKE_STR(6b,bd,95,ee,97,79,41,e4,97,c4,8b,e2,7c,25,41,28) +#define SD_MESSAGE_SLEEP_STOP SD_ID128_MAKE(88,11,e6,df,2a,8e,40,f5,8a,94,ce,a2,6f,8e,bf,14) +#define SD_MESSAGE_SLEEP_STOP_STR SD_ID128_MAKE_STR(88,11,e6,df,2a,8e,40,f5,8a,94,ce,a2,6f,8e,bf,14) + +#define SD_MESSAGE_SHUTDOWN SD_ID128_MAKE(98,26,88,66,d1,d5,4a,49,9c,4e,98,92,1d,93,bc,40) +#define SD_MESSAGE_SHUTDOWN_STR SD_ID128_MAKE_STR(98,26,88,66,d1,d5,4a,49,9c,4e,98,92,1d,93,bc,40) + +/* The messages below are actually about jobs, not really about units, the macros are misleadingly named. Moreover + * SD_MESSAGE_UNIT_FAILED is not actually about a failing unit but about a failed start job. A job either finishes with + * SD_MESSAGE_UNIT_STARTED or with SD_MESSAGE_UNIT_FAILED hence. */ +#define SD_MESSAGE_UNIT_STARTING SD_ID128_MAKE(7d,49,58,e8,42,da,4a,75,8f,6c,1c,dc,7b,36,dc,c5) +#define SD_MESSAGE_UNIT_STARTING_STR SD_ID128_MAKE_STR(7d,49,58,e8,42,da,4a,75,8f,6c,1c,dc,7b,36,dc,c5) +#define SD_MESSAGE_UNIT_STARTED SD_ID128_MAKE(39,f5,34,79,d3,a0,45,ac,8e,11,78,62,48,23,1f,bf) +#define SD_MESSAGE_UNIT_STARTED_STR SD_ID128_MAKE_STR(39,f5,34,79,d3,a0,45,ac,8e,11,78,62,48,23,1f,bf) +#define SD_MESSAGE_UNIT_FAILED SD_ID128_MAKE(be,02,cf,68,55,d2,42,8b,a4,0d,f7,e9,d0,22,f0,3d) +#define SD_MESSAGE_UNIT_FAILED_STR SD_ID128_MAKE_STR(be,02,cf,68,55,d2,42,8b,a4,0d,f7,e9,d0,22,f0,3d) +#define SD_MESSAGE_UNIT_STOPPING SD_ID128_MAKE(de,5b,42,6a,63,be,47,a7,b6,ac,3e,aa,c8,2e,2f,6f) +#define SD_MESSAGE_UNIT_STOPPING_STR SD_ID128_MAKE_STR(de,5b,42,6a,63,be,47,a7,b6,ac,3e,aa,c8,2e,2f,6f) +#define SD_MESSAGE_UNIT_STOPPED SD_ID128_MAKE(9d,1a,aa,27,d6,01,40,bd,96,36,54,38,aa,d2,02,86) +#define SD_MESSAGE_UNIT_STOPPED_STR SD_ID128_MAKE_STR(9d,1a,aa,27,d6,01,40,bd,96,36,54,38,aa,d2,02,86) +#define SD_MESSAGE_UNIT_RELOADING SD_ID128_MAKE(d3,4d,03,7f,ff,18,47,e6,ae,66,9a,37,0e,69,47,25) +#define SD_MESSAGE_UNIT_RELOADING_STR SD_ID128_MAKE_STR(d3,4d,03,7f,ff,18,47,e6,ae,66,9a,37,0e,69,47,25) +#define SD_MESSAGE_UNIT_RELOADED SD_ID128_MAKE(7b,05,eb,c6,68,38,42,22,ba,a8,88,11,79,cf,da,54) +#define SD_MESSAGE_UNIT_RELOADED_STR SD_ID128_MAKE_STR(7b,05,eb,c6,68,38,42,22,ba,a8,88,11,79,cf,da,54) + +#define SD_MESSAGE_UNIT_RESTART_SCHEDULED SD_ID128_MAKE(5e,b0,34,94,b6,58,48,70,a5,36,b3,37,29,08,09,b3) +#define SD_MESSAGE_UNIT_RESTART_SCHEDULED_STR \ + SD_ID128_MAKE_STR(5e,b0,34,94,b6,58,48,70,a5,36,b3,37,29,08,09,b3) + +#define SD_MESSAGE_UNIT_RESOURCES SD_ID128_MAKE(ae,8f,7b,86,6b,03,47,b9,af,31,fe,1c,80,b1,27,c0) +#define SD_MESSAGE_UNIT_RESOURCES_STR SD_ID128_MAKE_STR(ae,8f,7b,86,6b,03,47,b9,af,31,fe,1c,80,b1,27,c0) + +#define SD_MESSAGE_UNIT_SUCCESS SD_ID128_MAKE(7a,d2,d1,89,f7,e9,4e,70,a3,8c,78,13,54,91,24,48) +#define SD_MESSAGE_UNIT_SUCCESS_STR SD_ID128_MAKE_STR(7a,d2,d1,89,f7,e9,4e,70,a3,8c,78,13,54,91,24,48) +#define SD_MESSAGE_UNIT_SKIPPED SD_ID128_MAKE(0e,42,84,a0,ca,ca,4b,fc,81,c0,bb,67,86,97,26,73) +#define SD_MESSAGE_UNIT_SKIPPED_STR SD_ID128_MAKE_STR(0e,42,84,a0,ca,ca,4b,fc,81,c0,bb,67,86,97,26,73) +#define SD_MESSAGE_UNIT_FAILURE_RESULT SD_ID128_MAKE(d9,b3,73,ed,55,a6,4f,eb,82,42,e0,2d,be,79,a4,9c) +#define SD_MESSAGE_UNIT_FAILURE_RESULT_STR \ + SD_ID128_MAKE_STR(d9,b3,73,ed,55,a6,4f,eb,82,42,e0,2d,be,79,a4,9c) + +#define SD_MESSAGE_SPAWN_FAILED SD_ID128_MAKE(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7) +#define SD_MESSAGE_SPAWN_FAILED_STR SD_ID128_MAKE_STR(64,12,57,65,1c,1b,4e,c9,a8,62,4d,7a,40,a9,e1,e7) + +#define SD_MESSAGE_UNIT_PROCESS_EXIT SD_ID128_MAKE(98,e3,22,20,3f,7a,4e,d2,90,d0,9f,e0,3c,09,fe,15) +#define SD_MESSAGE_UNIT_PROCESS_EXIT_STR SD_ID128_MAKE_STR(98,e3,22,20,3f,7a,4e,d2,90,d0,9f,e0,3c,09,fe,15) + +#define SD_MESSAGE_FORWARD_SYSLOG_MISSED SD_ID128_MAKE(00,27,22,9c,a0,64,41,81,a7,6c,4e,92,45,8a,fa,2e) +#define SD_MESSAGE_FORWARD_SYSLOG_MISSED_STR \ + SD_ID128_MAKE_STR(00,27,22,9c,a0,64,41,81,a7,6c,4e,92,45,8a,fa,2e) + +#define SD_MESSAGE_OVERMOUNTING SD_ID128_MAKE(1d,ee,03,69,c7,fc,47,36,b7,09,9b,38,ec,b4,6e,e7) +#define SD_MESSAGE_OVERMOUNTING_STR SD_ID128_MAKE_STR(1d,ee,03,69,c7,fc,47,36,b7,09,9b,38,ec,b4,6e,e7) + +#define SD_MESSAGE_UNIT_OUT_OF_MEMORY SD_ID128_MAKE(fe,6f,aa,94,e7,77,46,63,a0,da,52,71,78,91,d8,ef) +#define SD_MESSAGE_UNIT_OUT_OF_MEMORY_STR SD_ID128_MAKE_STR(fe,6f,aa,94,e7,77,46,63,a0,da,52,71,78,91,d8,ef) + +#define SD_MESSAGE_LID_OPENED SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,6f) +#define SD_MESSAGE_LID_OPENED_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,6f) +#define SD_MESSAGE_LID_CLOSED SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,70) +#define SD_MESSAGE_LID_CLOSED_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,70) +#define SD_MESSAGE_SYSTEM_DOCKED SD_ID128_MAKE(f5,f4,16,b8,62,07,4b,28,92,7a,48,c3,ba,7d,51,ff) +#define SD_MESSAGE_SYSTEM_DOCKED_STR SD_ID128_MAKE_STR(f5,f4,16,b8,62,07,4b,28,92,7a,48,c3,ba,7d,51,ff) +#define SD_MESSAGE_SYSTEM_UNDOCKED SD_ID128_MAKE(51,e1,71,bd,58,52,48,56,81,10,14,4c,51,7c,ca,53) +#define SD_MESSAGE_SYSTEM_UNDOCKED_STR SD_ID128_MAKE_STR(51,e1,71,bd,58,52,48,56,81,10,14,4c,51,7c,ca,53) +#define SD_MESSAGE_POWER_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) +#define SD_MESSAGE_POWER_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,71) +#define SD_MESSAGE_SUSPEND_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72) +#define SD_MESSAGE_SUSPEND_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,72) +#define SD_MESSAGE_HIBERNATE_KEY SD_ID128_MAKE(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,73) +#define SD_MESSAGE_HIBERNATE_KEY_STR SD_ID128_MAKE_STR(b7,2e,a4,a2,88,15,45,a0,b5,0e,20,0e,55,b9,b0,73) + +#define SD_MESSAGE_INVALID_CONFIGURATION SD_ID128_MAKE(c7,72,d2,4e,9a,88,4c,be,b9,ea,12,62,5c,30,6c,01) +#define SD_MESSAGE_INVALID_CONFIGURATION_STR \ + SD_ID128_MAKE_STR(c7,72,d2,4e,9a,88,4c,be,b9,ea,12,62,5c,30,6c,01) + +#define SD_MESSAGE_DNSSEC_FAILURE SD_ID128_MAKE(16,75,d7,f1,72,17,40,98,b1,10,8b,f8,c7,dc,8f,5d) +#define SD_MESSAGE_DNSSEC_FAILURE_STR SD_ID128_MAKE_STR(16,75,d7,f1,72,17,40,98,b1,10,8b,f8,c7,dc,8f,5d) +#define SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED \ + SD_ID128_MAKE(4d,44,08,cf,d0,d1,44,85,91,84,d1,e6,5d,7c,8a,65) +#define SD_MESSAGE_DNSSEC_TRUST_ANCHOR_REVOKED_STR \ + SD_ID128_MAKE_STR(4d,44,08,cf,d0,d1,44,85,91,84,d1,e6,5d,7c,8a,65) +#define SD_MESSAGE_DNSSEC_DOWNGRADE SD_ID128_MAKE(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57) +#define SD_MESSAGE_DNSSEC_DOWNGRADE_STR SD_ID128_MAKE_STR(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57) + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-ndisc.h b/src/systemd/sd-ndisc.h new file mode 100644 index 00000000..d1bee343 --- /dev/null +++ b/src/systemd/sd-ndisc.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdndiscfoo +#define foosdndiscfoo + +/*** + Copyright © 2014 Intel Corporation. All rights reserved. + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include + +#include "sd-event.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +/* Neightbor Discovery Options, RFC 4861, Section 4.6 and + * https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-5 */ +enum { + SD_NDISC_OPTION_SOURCE_LL_ADDRESS = 1, + SD_NDISC_OPTION_TARGET_LL_ADDRESS = 2, + SD_NDISC_OPTION_PREFIX_INFORMATION = 3, + SD_NDISC_OPTION_MTU = 5, + SD_NDISC_OPTION_ROUTE_INFORMATION = 24, + SD_NDISC_OPTION_RDNSS = 25, + SD_NDISC_OPTION_FLAGS_EXTENSION = 26, + SD_NDISC_OPTION_DNSSL = 31, + SD_NDISC_OPTION_CAPTIVE_PORTAL = 37, +}; + +/* Route preference, RFC 4191, Section 2.1 */ +enum { + SD_NDISC_PREFERENCE_LOW = 3U, + SD_NDISC_PREFERENCE_MEDIUM = 0U, + SD_NDISC_PREFERENCE_HIGH = 1U, +}; + +typedef struct sd_ndisc sd_ndisc; +typedef struct sd_ndisc_router sd_ndisc_router; + +typedef enum sd_ndisc_event { + SD_NDISC_EVENT_TIMEOUT, + SD_NDISC_EVENT_ROUTER, + _SD_NDISC_EVENT_MAX, + _SD_NDISC_EVENT_INVALID = -1, +} sd_ndisc_event; + +typedef void (*sd_ndisc_callback_t)(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata); + +int sd_ndisc_new(sd_ndisc **ret); +sd_ndisc *sd_ndisc_ref(sd_ndisc *nd); +sd_ndisc *sd_ndisc_unref(sd_ndisc *nd); + +int sd_ndisc_start(sd_ndisc *nd); +int sd_ndisc_stop(sd_ndisc *nd); + +int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority); +int sd_ndisc_detach_event(sd_ndisc *nd); +sd_event *sd_ndisc_get_event(sd_ndisc *nd); + +int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t cb, void *userdata); +int sd_ndisc_set_ifindex(sd_ndisc *nd, int interface_index); +int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr); + +int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *ret); +int sd_ndisc_get_hop_limit(sd_ndisc *nd, uint8_t *ret); + +int sd_ndisc_router_from_raw(sd_ndisc_router **ret, const void *raw, size_t raw_size); +sd_ndisc_router *sd_ndisc_router_ref(sd_ndisc_router *rt); +sd_ndisc_router *sd_ndisc_router_unref(sd_ndisc_router *rt); + +int sd_ndisc_router_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr); +int sd_ndisc_router_get_timestamp(sd_ndisc_router *rt, clockid_t clock, uint64_t *ret); +int sd_ndisc_router_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size); + +int sd_ndisc_router_get_hop_limit(sd_ndisc_router *rt, uint8_t *ret); +int sd_ndisc_router_get_flags(sd_ndisc_router *rt, uint64_t *ret_flags); +int sd_ndisc_router_get_preference(sd_ndisc_router *rt, unsigned *ret); +int sd_ndisc_router_get_lifetime(sd_ndisc_router *rt, uint16_t *ret_lifetime); +int sd_ndisc_router_get_mtu(sd_ndisc_router *rt, uint32_t *ret); + +/* Generic option access */ +int sd_ndisc_router_option_rewind(sd_ndisc_router *rt); +int sd_ndisc_router_option_next(sd_ndisc_router *rt); +int sd_ndisc_router_option_get_type(sd_ndisc_router *rt, uint8_t *ret); +int sd_ndisc_router_option_is_type(sd_ndisc_router *rt, uint8_t type); +int sd_ndisc_router_option_get_raw(sd_ndisc_router *rt, const void **ret, size_t *size); + +/* Specific option access: SD_NDISC_OPTION_PREFIX_INFORMATION */ +int sd_ndisc_router_prefix_get_valid_lifetime(sd_ndisc_router *rt, uint32_t *ret); +int sd_ndisc_router_prefix_get_preferred_lifetime(sd_ndisc_router *rt, uint32_t *ret); +int sd_ndisc_router_prefix_get_flags(sd_ndisc_router *rt, uint8_t *ret); +int sd_ndisc_router_prefix_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr); +int sd_ndisc_router_prefix_get_prefixlen(sd_ndisc_router *rt, unsigned *prefixlen); + +/* Specific option access: SD_NDISC_OPTION_ROUTE_INFORMATION */ +int sd_ndisc_router_route_get_lifetime(sd_ndisc_router *rt, uint32_t *ret); +int sd_ndisc_router_route_get_address(sd_ndisc_router *rt, struct in6_addr *ret_addr); +int sd_ndisc_router_route_get_prefixlen(sd_ndisc_router *rt, unsigned *prefixlen); +int sd_ndisc_router_route_get_preference(sd_ndisc_router *rt, unsigned *ret); + +/* Specific option access: SD_NDISC_OPTION_RDNSS */ +int sd_ndisc_router_rdnss_get_addresses(sd_ndisc_router *rt, const struct in6_addr **ret); +int sd_ndisc_router_rdnss_get_lifetime(sd_ndisc_router *rt, uint32_t *ret); + +/* Specific option access: SD_NDISC_OPTION_DNSSL */ +int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret); +int sd_ndisc_router_dnssl_get_lifetime(sd_ndisc_router *rt, uint32_t *ret); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc, sd_ndisc_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc_router, sd_ndisc_router_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-netlink.h b/src/systemd/sd-netlink.h new file mode 100644 index 00000000..b34befeb --- /dev/null +++ b/src/systemd/sd-netlink.h @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdnetlinkhfoo +#define foosdnetlinkhfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include +#include + +#include "sd-event.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_netlink sd_netlink; +typedef struct sd_genl_socket sd_genl_socket; +typedef struct sd_netlink_message sd_netlink_message; +typedef struct sd_netlink_slot sd_netlink_slot; + +typedef enum sd_gen_family { + SD_GENL_ERROR, + SD_GENL_DONE, + SD_GENL_ID_CTRL, + SD_GENL_WIREGUARD, + SD_GENL_FOU, + SD_GENL_L2TP, + SD_GENL_MACSEC, + SD_GENL_NL80211, +} sd_genl_family; + +/* callback */ + +typedef int (*sd_netlink_message_handler_t)(sd_netlink *nl, sd_netlink_message *m, void *userdata); +typedef _sd_destroy_t sd_netlink_destroy_t; + +/* bus */ +int sd_netlink_new_from_netlink(sd_netlink **nl, int fd); +int sd_netlink_open(sd_netlink **nl); +int sd_netlink_open_fd(sd_netlink **nl, int fd); +int sd_netlink_inc_rcvbuf(sd_netlink *nl, const size_t size); + +sd_netlink *sd_netlink_ref(sd_netlink *nl); +sd_netlink *sd_netlink_unref(sd_netlink *nl); + +int sd_netlink_send(sd_netlink *nl, sd_netlink_message *message, uint32_t *serial); +int sd_netlink_call_async(sd_netlink *nl, sd_netlink_slot **ret_slot, sd_netlink_message *message, + sd_netlink_message_handler_t callback, sd_netlink_destroy_t destoy_callback, + void *userdata, uint64_t usec, const char *description); +int sd_netlink_call(sd_netlink *nl, sd_netlink_message *message, uint64_t timeout, + sd_netlink_message **reply); + +int sd_netlink_get_events(const sd_netlink *nl); +int sd_netlink_get_timeout(const sd_netlink *nl, uint64_t *timeout); +int sd_netlink_process(sd_netlink *nl, sd_netlink_message **ret); +int sd_netlink_wait(sd_netlink *nl, uint64_t timeout); + +int sd_netlink_add_match(sd_netlink *nl, sd_netlink_slot **ret_slot, uint16_t match, + sd_netlink_message_handler_t callback, + sd_netlink_destroy_t destroy_callback, + void *userdata, const char *description); + +int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int64_t priority); +int sd_netlink_detach_event(sd_netlink *nl); + +int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data); +int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type); +int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data); +int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data); +int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data); +int sd_netlink_message_append_u64(sd_netlink_message *m, unsigned short type, uint64_t data); +int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len); +int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data); +int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data); +int sd_netlink_message_append_sockaddr_in(sd_netlink_message *m, unsigned short type, const struct sockaddr_in *data); +int sd_netlink_message_append_sockaddr_in6(sd_netlink_message *m, unsigned short type, const struct sockaddr_in6 *data); +int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data); +int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info); + +int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type); +int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned short type, const char *key); +int sd_netlink_message_close_container(sd_netlink_message *m); + +int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data); +int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data); +int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data); +int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data); +int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data); +int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data); +int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short type, struct ether_addr *data); +int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info); +int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data); +int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data); +int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type); +int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type); +int sd_netlink_message_exit_container(sd_netlink_message *m); + +int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type); +int sd_netlink_message_cancel_array(sd_netlink_message *m); + +int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl); + +sd_netlink_message *sd_netlink_message_next(sd_netlink_message *m); + +sd_netlink_message *sd_netlink_message_ref(sd_netlink_message *m); +sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m); + +int sd_netlink_message_request_dump(sd_netlink_message *m, int dump); +int sd_netlink_message_is_error(const sd_netlink_message *m); +int sd_netlink_message_get_errno(const sd_netlink_message *m); +int sd_netlink_message_get_type(const sd_netlink_message *m, uint16_t *type); +int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags); +int sd_netlink_message_is_broadcast(const sd_netlink_message *m); + +/* rtnl */ + +int sd_rtnl_message_new_link(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index); +int sd_rtnl_message_new_addr_update(sd_netlink *nl, sd_netlink_message **ret, int index, int family); +int sd_rtnl_message_new_addr(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int family); +int sd_rtnl_message_new_route(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type, int rtm_family, unsigned char rtm_protocol); +int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int nda_family); + +int sd_rtnl_message_get_family(const sd_netlink_message *m, int *family); + +int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen); +int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope); +int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags); +int sd_rtnl_message_addr_get_family(const sd_netlink_message *m, int *family); +int sd_rtnl_message_addr_get_prefixlen(const sd_netlink_message *m, unsigned char *prefixlen); +int sd_rtnl_message_addr_get_scope(const sd_netlink_message *m, unsigned char *scope); +int sd_rtnl_message_addr_get_flags(const sd_netlink_message *m, unsigned char *flags); +int sd_rtnl_message_addr_get_ifindex(const sd_netlink_message *m, int *ifindex); + +int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change); +int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type); +int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family); +int sd_rtnl_message_link_get_ifindex(const sd_netlink_message *m, int *ifindex); +int sd_rtnl_message_link_get_flags(const sd_netlink_message *m, unsigned *flags); +int sd_rtnl_message_link_get_type(const sd_netlink_message *m, unsigned short *type); + +int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen); +int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen); +int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope); +int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags); +int sd_rtnl_message_route_set_table(sd_netlink_message *m, unsigned char table); +int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type); +int sd_rtnl_message_route_get_flags(const sd_netlink_message *m, unsigned *flags); +int sd_rtnl_message_route_get_family(const sd_netlink_message *m, int *family); +int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family); +int sd_rtnl_message_route_get_protocol(const sd_netlink_message *m, unsigned char *protocol); +int sd_rtnl_message_route_get_scope(const sd_netlink_message *m, unsigned char *scope); +int sd_rtnl_message_route_get_tos(const sd_netlink_message *m, unsigned char *tos); +int sd_rtnl_message_route_get_table(const sd_netlink_message *m, unsigned char *table); +int sd_rtnl_message_route_get_dst_prefixlen(const sd_netlink_message *m, unsigned char *dst_len); +int sd_rtnl_message_route_get_src_prefixlen(const sd_netlink_message *m, unsigned char *src_len); +int sd_rtnl_message_route_get_type(const sd_netlink_message *m, unsigned char *type); + +int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nhmsg_type, int nh_family, unsigned char nh_protocol); + +int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags); +int sd_rtnl_message_nexthop_set_family(sd_netlink_message *m, uint8_t family); +int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *family); + +int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags); +int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state); +int sd_rtnl_message_neigh_get_family(const sd_netlink_message *m, int *family); +int sd_rtnl_message_neigh_get_ifindex(const sd_netlink_message *m, int *family); +int sd_rtnl_message_neigh_get_state(const sd_netlink_message *m, uint16_t *state); +int sd_rtnl_message_neigh_get_flags(const sd_netlink_message *m, uint8_t *flags); + +int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family); +int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen); +int sd_rtnl_message_addrlabel_get_prefixlen(const sd_netlink_message *m, unsigned char *prefixlen); + +int sd_rtnl_message_new_routing_policy_rule(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifal_family); +int sd_rtnl_message_routing_policy_rule_set_tos(sd_netlink_message *m, unsigned char tos); +int sd_rtnl_message_routing_policy_rule_get_tos(const sd_netlink_message *m, unsigned char *tos); +int sd_rtnl_message_routing_policy_rule_set_table(sd_netlink_message *m, unsigned char table); +int sd_rtnl_message_routing_policy_rule_get_table(const sd_netlink_message *m, unsigned char *table); +int sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(sd_netlink_message *m, unsigned char len); +int sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(const sd_netlink_message *m, unsigned char *len); +int sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(sd_netlink_message *m, unsigned char len); +int sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(const sd_netlink_message *m, unsigned char *len); +int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type); +int sd_rtnl_message_routing_policy_rule_get_rtm_type(const sd_netlink_message *m, unsigned char *type); +int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, unsigned flags); +int sd_rtnl_message_routing_policy_rule_get_flags(const sd_netlink_message *m, unsigned *flags); + +int sd_rtnl_message_new_qdisc(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int tcm_family, int tcm_ifindex); +int sd_rtnl_message_set_qdisc_parent(sd_netlink_message *m, uint32_t parent); +int sd_rtnl_message_set_qdisc_handle(sd_netlink_message *m, uint32_t handle); + +/* genl */ +int sd_genl_socket_open(sd_netlink **nl); +int sd_genl_message_new(sd_netlink *nl, sd_genl_family family, uint8_t cmd, sd_netlink_message **m); +int sd_genl_message_get_family(const sd_netlink *nl, const sd_netlink_message *m, sd_genl_family *family); + +/* slot */ +sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *nl); +sd_netlink_slot *sd_netlink_slot_unref(sd_netlink_slot *nl); + +sd_netlink *sd_netlink_slot_get_netlink(sd_netlink_slot *slot); +void *sd_netlink_slot_get_userdata(sd_netlink_slot *slot); +void *sd_netlink_slot_set_userdata(sd_netlink_slot *slot, void *userdata); +int sd_netlink_slot_get_destroy_callback(const sd_netlink_slot *slot, sd_netlink_destroy_t *callback); +int sd_netlink_slot_set_destroy_callback(sd_netlink_slot *slot, sd_netlink_destroy_t callback); +int sd_netlink_slot_get_floating(const sd_netlink_slot *slot); +int sd_netlink_slot_set_floating(sd_netlink_slot *slot, int b); +int sd_netlink_slot_get_description(const sd_netlink_slot *slot, const char **description); +int sd_netlink_slot_set_description(sd_netlink_slot *slot, const char *description); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_message, sd_netlink_message_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink_slot, sd_netlink_slot_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h new file mode 100644 index 00000000..d0b43227 --- /dev/null +++ b/src/systemd/sd-network.h @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdnetworkhfoo +#define foosdnetworkhfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include + +#include "_sd-common.h" + +/* + * A few points: + * + * Instead of returning an empty string array or empty integer array, we + * may return NULL. + * + * Free the data the library returns with libc free(). String arrays + * are NULL terminated, and you need to free the array itself in + * addition to the strings contained. + * + * We return error codes as negative errno, kernel-style. On success, we + * return 0 or positive. + * + * These functions access data in /run. This is a virtual file system; + * therefore, accesses are relatively cheap. + * + * See sd-network(3) for more information. + */ + +_SD_BEGIN_DECLARATIONS; + +/* Get overall operational state + * Possible states: down, up, dormant, carrier, degraded, routable + * Possible return codes: + * -ENODATA: networkd is not aware of any links + */ +int sd_network_get_operational_state(char **state); +int sd_network_get_carrier_state(char **state); +int sd_network_get_address_state(char **state); + +/* Get DNS entries for all links. These are string representations of + * IP addresses */ +int sd_network_get_dns(char ***dns); + +/* Get NTP entries for all links. These are domain names or string + * representations of IP addresses */ +int sd_network_get_ntp(char ***ntp); + +/* Get the search domains for all links. */ +int sd_network_get_search_domains(char ***domains); + +/* Get the search domains for all links. */ +int sd_network_get_route_domains(char ***domains); + +/* Get setup state from ifindex. + * Possible states: + * pending: udev is still processing the link, we don't yet know if we will manage it + * failed: networkd failed to manage the link + * configuring: in the process of retrieving configuration or configuring the link + * configured: link configured successfully + * unmanaged: networkd is not handling the link + * linger: the link is gone, but has not yet been dropped by networkd + * Possible return codes: + * -ENODATA: networkd is not aware of the link + */ +int sd_network_link_get_setup_state(int ifindex, char **state); + +/* Get operational state from ifindex. + * Possible states: + * off: the device is powered down + * no-carrier: the device is powered up, but it does not yet have a carrier + * dormant: the device has a carrier, but is not yet ready for normal traffic + * carrier: the link has a carrier + * degraded: the link has carrier and addresses valid on the local link configured + * routable: the link has carrier and routable address configured + * Possible return codes: + * -ENODATA: networkd is not aware of the link + */ +int sd_network_link_get_operational_state(int ifindex, char **state); +int sd_network_link_get_required_operstate_for_online(int ifindex, char **state); +int sd_network_link_get_carrier_state(int ifindex, char **state); +int sd_network_link_get_address_state(int ifindex, char **state); + +/* Indicates whether the network is relevant to being online. + * Possible return codes: + * 0: the connection is not required + * 1: the connection is required to consider the system online + * <0: networkd is not aware of the link + */ +int sd_network_link_get_required_for_online(int ifindex); + +/* Get path to .network file applied to link */ +int sd_network_link_get_network_file(int ifindex, char **filename); + +/* Get DNS entries for a given link. These are string representations of + * IP addresses */ +int sd_network_link_get_dns(int ifindex, char ***ret); + +/* Get DHCP4 address for a given link. This is string representations of + * IPv4 address */ +int sd_network_link_get_dhcp4_address(int ifindex, char **ret); + +/* Get NTP entries for a given link. These are domain names or string + * representations of IP addresses */ +int sd_network_link_get_ntp(int ifindex, char ***ret); + +/* Indicates whether or not LLMNR should be enabled for the link + * Possible levels of support: yes, no, resolve + * Possible return codes: + * -ENODATA: networkd is not aware of the link + */ +int sd_network_link_get_llmnr(int ifindex, char **llmnr); + +/* Indicates whether or not MulticastDNS should be enabled for the + * link. + * Possible levels of support: yes, no, resolve + * Possible return codes: + * -ENODATA: networkd is not aware of the link + */ +int sd_network_link_get_mdns(int ifindex, char **mdns); + +/* Indicates whether or not DNS-over-TLS should be enabled for the + * link. + * Possible levels of support: yes, no, opportunistic + * Possible return codes: + * -ENODATA: networkd is not aware of the link + */ +int sd_network_link_get_dns_over_tls(int ifindex, char **dns_over_tls); + +/* Indicates whether or not DNSSEC should be enabled for the link + * Possible levels of support: yes, no, allow-downgrade + * Possible return codes: + * -ENODATA: networkd is not aware of the link + */ +int sd_network_link_get_dnssec(int ifindex, char **dnssec); + +/* Returns the list of per-interface DNSSEC negative trust anchors + * Possible return codes: + * -ENODATA: networkd is not aware of the link, or has no such data + */ +int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta); + +/* Get the search DNS domain names for a given link. */ +int sd_network_link_get_search_domains(int ifindex, char ***domains); + +/* Get the route DNS domain names for a given link. */ +int sd_network_link_get_route_domains(int ifindex, char ***domains); + +/* Get the sip servers for a given link. */ +int sd_network_link_get_sip_servers(int ifindex, char ***sip); + +/* Get whether this link shall be used as 'default route' for DNS queries */ +int sd_network_link_get_dns_default_route(int ifindex); + +/* Get the carrier interface indexes to which current link is bound to. */ +int sd_network_link_get_carrier_bound_to(int ifindex, int **ifindexes); + +/* Get the CARRIERS that are bound to current link. */ +int sd_network_link_get_carrier_bound_by(int ifindex, int **ifindexes); + +/* Get the timezone that was learnt on a specific link. */ +int sd_network_link_get_timezone(int ifindex, char **timezone); + +/* Monitor object */ +typedef struct sd_network_monitor sd_network_monitor; + +/* Create a new monitor. Category must be NULL, "links" or "leases". */ +int sd_network_monitor_new(sd_network_monitor **ret, const char *category); + +/* Destroys the passed monitor. Returns NULL. */ +sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m); + +/* Flushes the monitor */ +int sd_network_monitor_flush(sd_network_monitor *m); + +/* Get FD from monitor */ +int sd_network_monitor_get_fd(sd_network_monitor *m); + +/* Get poll() mask to monitor */ +int sd_network_monitor_get_events(sd_network_monitor *m); + +/* Get timeout for poll(), as usec value relative to CLOCK_MONOTONIC's epoch */ +int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_network_monitor, sd_network_monitor_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-path.h b/src/systemd/sd-path.h new file mode 100644 index 00000000..16379876 --- /dev/null +++ b/src/systemd/sd-path.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdpathhfoo +#define foosdpathhfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +enum { + /* Temporary files */ + SD_PATH_TEMPORARY, + SD_PATH_TEMPORARY_LARGE, + + /* Vendor supplied data */ + SD_PATH_SYSTEM_BINARIES, + SD_PATH_SYSTEM_INCLUDE, + SD_PATH_SYSTEM_LIBRARY_PRIVATE, + SD_PATH_SYSTEM_LIBRARY_ARCH, + SD_PATH_SYSTEM_SHARED, + SD_PATH_SYSTEM_CONFIGURATION_FACTORY, + SD_PATH_SYSTEM_STATE_FACTORY, + + /* System configuration, runtime, state, ... */ + SD_PATH_SYSTEM_CONFIGURATION, + SD_PATH_SYSTEM_RUNTIME, + SD_PATH_SYSTEM_RUNTIME_LOGS, + SD_PATH_SYSTEM_STATE_PRIVATE, + SD_PATH_SYSTEM_STATE_LOGS, + SD_PATH_SYSTEM_STATE_CACHE, + SD_PATH_SYSTEM_STATE_SPOOL, + + /* Vendor supplied data */ + SD_PATH_USER_BINARIES, + SD_PATH_USER_LIBRARY_PRIVATE, + SD_PATH_USER_LIBRARY_ARCH, + SD_PATH_USER_SHARED, + + /* User configuration, state, runtime ... */ + SD_PATH_USER_CONFIGURATION, /* takes both actual configuration (like /etc) and state (like /var/lib) */ + SD_PATH_USER_RUNTIME, + SD_PATH_USER_STATE_CACHE, + + /* User resources */ + SD_PATH_USER, /* $HOME itself */ + SD_PATH_USER_DOCUMENTS, + SD_PATH_USER_MUSIC, + SD_PATH_USER_PICTURES, + SD_PATH_USER_VIDEOS, + SD_PATH_USER_DOWNLOAD, + SD_PATH_USER_PUBLIC, + SD_PATH_USER_TEMPLATES, + SD_PATH_USER_DESKTOP, + + /* Search paths */ + SD_PATH_SEARCH_BINARIES, + SD_PATH_SEARCH_BINARIES_DEFAULT, + SD_PATH_SEARCH_LIBRARY_PRIVATE, + SD_PATH_SEARCH_LIBRARY_ARCH, + SD_PATH_SEARCH_SHARED, + SD_PATH_SEARCH_CONFIGURATION_FACTORY, + SD_PATH_SEARCH_STATE_FACTORY, + SD_PATH_SEARCH_CONFIGURATION, + + _SD_PATH_MAX, +}; + +int sd_path_home(uint64_t type, const char *suffix, char **path); +int sd_path_search(uint64_t type, const char *suffix, char ***paths); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h new file mode 100644 index 00000000..f0852319 --- /dev/null +++ b/src/systemd/sd-radv.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdradvfoo +#define foosdradvfoo + +/*** + Copyright © 2017 Intel Corporation. All rights reserved. + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include +#include +#include +#include + +#include "_sd-common.h" +#include "sd-event.h" +#include "sd-ndisc.h" + +_SD_BEGIN_DECLARATIONS; + +#define SD_RADV_DEFAULT_MIN_TIMEOUT_USEC (200*USEC_PER_SEC) +#define SD_RADV_DEFAULT_MAX_TIMEOUT_USEC (600*USEC_PER_SEC) + +#define SD_RADV_DEFAULT_DNS_LIFETIME_USEC (3*SD_RADV_DEFAULT_MAX_TIMEOUT_USEC) + +typedef struct sd_radv sd_radv; +typedef struct sd_radv_prefix sd_radv_prefix; +typedef struct sd_radv_route_prefix sd_radv_route_prefix; + +/* Router Advertisement */ +int sd_radv_new(sd_radv **ret); +sd_radv *sd_radv_ref(sd_radv *ra); +sd_radv *sd_radv_unref(sd_radv *ra); + +int sd_radv_attach_event(sd_radv *ra, sd_event *event, int64_t priority); +int sd_radv_detach_event(sd_radv *nd); +sd_event *sd_radv_get_event(sd_radv *ra); + +int sd_radv_start(sd_radv *ra); +int sd_radv_stop(sd_radv *ra); + +int sd_radv_set_ifindex(sd_radv *ra, int interface_index); +int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr); +int sd_radv_set_mtu(sd_radv *ra, uint32_t mtu); +int sd_radv_set_hop_limit(sd_radv *ra, uint8_t hop_limit); +int sd_radv_set_router_lifetime(sd_radv *ra, uint32_t router_lifetime); +int sd_radv_set_managed_information(sd_radv *ra, int managed); +int sd_radv_set_other_information(sd_radv *ra, int other); +int sd_radv_set_preference(sd_radv *ra, unsigned preference); +int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic); +int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int dynamic); +sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra, const struct in6_addr *prefix, + unsigned char prefixlen); +int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime, + const struct in6_addr *dns, size_t n_dns); +int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime, char **search_list); + +/* Advertised prefixes */ +int sd_radv_prefix_new(sd_radv_prefix **ret); +sd_radv_prefix *sd_radv_prefix_ref(sd_radv_prefix *ra); +sd_radv_prefix *sd_radv_prefix_unref(sd_radv_prefix *ra); + +int sd_radv_prefix_set_prefix(sd_radv_prefix *p, const struct in6_addr *in6_addr, + unsigned char prefixlen); +int sd_radv_prefix_set_onlink(sd_radv_prefix *p, int onlink); +int sd_radv_prefix_set_address_autoconfiguration(sd_radv_prefix *p, + int address_autoconfiguration); +int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix *p, + uint32_t valid_lifetime); +int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p, + uint32_t preferred_lifetime); + +int sd_radv_route_prefix_new(sd_radv_route_prefix **ret); +sd_radv_route_prefix *sd_radv_route_prefix_ref(sd_radv_route_prefix *ra); +sd_radv_route_prefix *sd_radv_route_prefix_unref(sd_radv_route_prefix *ra); + +int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, unsigned char prefixlen); +int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint32_t valid_lifetime); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv, sd_radv_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_prefix, sd_radv_prefix_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_route_prefix, sd_radv_route_prefix_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-resolve.h b/src/systemd/sd-resolve.h new file mode 100644 index 00000000..d78e8db2 --- /dev/null +++ b/src/systemd/sd-resolve.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdresolvehfoo +#define foosdresolvehfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +/* 'struct addrinfo' needs _GNU_SOURCE */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +#include +#include +#include +#include + +#include "sd-event.h" + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +/* An opaque sd-resolve session structure */ +typedef struct sd_resolve sd_resolve; + +/* An opaque sd-resolve query structure */ +typedef struct sd_resolve_query sd_resolve_query; + +/* A callback on completion */ +typedef int (*sd_resolve_getaddrinfo_handler_t)(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata); +typedef int (*sd_resolve_getnameinfo_handler_t)(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata); +typedef _sd_destroy_t sd_resolve_destroy_t; + +enum { + SD_RESOLVE_GET_HOST = 1 << 0, + SD_RESOLVE_GET_SERVICE = 1 << 1, + SD_RESOLVE_GET_BOTH = SD_RESOLVE_GET_HOST | SD_RESOLVE_GET_SERVICE, +}; + +int sd_resolve_default(sd_resolve **ret); + +/* Allocate a new sd-resolve session. */ +int sd_resolve_new(sd_resolve **ret); + +/* Free a sd-resolve session. This destroys all attached + * sd_resolve_query objects automatically. */ +sd_resolve* sd_resolve_unref(sd_resolve *resolve); +sd_resolve* sd_resolve_ref(sd_resolve *resolve); + +/* Return the UNIX file descriptor to poll() for events on. Use this + * function to integrate sd-resolve with your custom main loop. */ +int sd_resolve_get_fd(sd_resolve *resolve); + +/* Return the poll() events (a combination of flags like POLLIN, + * POLLOUT, ...) to check for. */ +int sd_resolve_get_events(sd_resolve *resolve); + +/* Return the poll() timeout to pass. Returns (uint64_t) -1 as + * timeout if no timeout is needed. */ +int sd_resolve_get_timeout(sd_resolve *resolve, uint64_t *timeout_usec); + +/* Process pending responses. After this function is called, you can + * get the next completed query object(s) using + * sd_resolve_get_next(). */ +int sd_resolve_process(sd_resolve *resolve); + +/* Wait for a resolve event to complete. */ +int sd_resolve_wait(sd_resolve *resolve, uint64_t timeout_usec); + +int sd_resolve_get_tid(sd_resolve *resolve, pid_t *tid); + +int sd_resolve_attach_event(sd_resolve *resolve, sd_event *e, int64_t priority); +int sd_resolve_detach_event(sd_resolve *resolve); +sd_event *sd_resolve_get_event(sd_resolve *resolve); + +/* Issue a name-to-address query on the specified session. The + * arguments are compatible with those of libc's + * getaddrinfo(3). The function returns a new query object. When the + * query is completed, you may retrieve the results using + * sd_resolve_getaddrinfo_done(). */ +int sd_resolve_getaddrinfo(sd_resolve *resolve, sd_resolve_query **q, const char *node, const char *service, const struct addrinfo *hints, sd_resolve_getaddrinfo_handler_t callback, void *userdata); + +/* Issue an address-to-name query on the specified session. The + * arguments are compatible with those of libc's + * getnameinfo(3). The function returns a new query object. When the + * query is completed, you may retrieve the results using + * sd_resolve_getnameinfo_done(). Set gethost (resp. getserv) to non-zero + * if you want to query the hostname (resp. the service name). */ +int sd_resolve_getnameinfo(sd_resolve *resolve, sd_resolve_query **q, const struct sockaddr *sa, socklen_t salen, int flags, uint64_t get, sd_resolve_getnameinfo_handler_t callback, void *userdata); + +sd_resolve_query *sd_resolve_query_ref(sd_resolve_query *q); +sd_resolve_query *sd_resolve_query_unref(sd_resolve_query *q); + +/* Returns non-zero when the query operation specified by q has been completed. */ +int sd_resolve_query_is_done(sd_resolve_query *q); + +void *sd_resolve_query_get_userdata(sd_resolve_query *q); +void *sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata); +int sd_resolve_query_get_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t *destroy_callback); +int sd_resolve_query_set_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t destroy_callback); +int sd_resolve_query_get_floating(sd_resolve_query *q); +int sd_resolve_query_set_floating(sd_resolve_query *q, int b); + +sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_resolve, sd_resolve_unref); +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_resolve_query, sd_resolve_query_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/sd-utf8.h b/src/systemd/sd-utf8.h new file mode 100644 index 00000000..151b423d --- /dev/null +++ b/src/systemd/sd-utf8.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosdutf8hfoo +#define foosdutf8hfoo + +/*** + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +_sd_pure_ const char *sd_utf8_is_valid(const char *s); +_sd_pure_ const char *sd_ascii_is_valid(const char *s); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c new file mode 100644 index 00000000..08a2df70 --- /dev/null +++ b/src/sysusers/sysusers.c @@ -0,0 +1,1943 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "conf-files.h" +#include "copy.h" +#include "def.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "main-func.h" +#include "pager.h" +#include "path-util.h" +#include "pretty-print.h" +#include "set.h" +#include "selinux-util.h" +#include "smack-util.h" +#include "specifier.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util-label.h" +#include "uid-range.h" +#include "user-util.h" +#include "utf8.h" +#include "util.h" + +typedef enum ItemType { + ADD_USER = 'u', + ADD_GROUP = 'g', + ADD_MEMBER = 'm', + ADD_RANGE = 'r', +} ItemType; + +typedef struct Item { + ItemType type; + + char *name; + char *uid_path; + char *gid_path; + char *description; + char *home; + char *shell; + + gid_t gid; + uid_t uid; + + bool gid_set:1; + + /* When set the group with the specified gid must exist + * and the check if a uid clashes with the gid is skipped. + */ + bool id_set_strict:1; + + bool uid_set:1; + + bool todo_user:1; + bool todo_group:1; +} Item; + +static char *arg_root = NULL; +static bool arg_cat_config = false; +static const char *arg_replace = NULL; +static bool arg_inline = false; +static PagerFlags arg_pager_flags = 0; + +static OrderedHashmap *users = NULL, *groups = NULL; +static OrderedHashmap *todo_uids = NULL, *todo_gids = NULL; +static OrderedHashmap *members = NULL; + +static Hashmap *database_by_uid = NULL, *database_by_username = NULL; +static Hashmap *database_by_gid = NULL, *database_by_groupname = NULL; +static Set *database_users = NULL, *database_groups = NULL; + +static uid_t search_uid = UID_INVALID; +static UidRange *uid_range = NULL; +static unsigned n_uid_range = 0; + +STATIC_DESTRUCTOR_REGISTER(groups, ordered_hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(users, ordered_hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(members, ordered_hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(todo_uids, ordered_hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(todo_gids, ordered_hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(database_by_uid, hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(database_by_username, hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(database_users, set_free_freep); +STATIC_DESTRUCTOR_REGISTER(database_by_gid, hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(database_by_groupname, hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(database_groups, set_free_freep); +STATIC_DESTRUCTOR_REGISTER(uid_range, freep); +STATIC_DESTRUCTOR_REGISTER(arg_root, freep); + +static int load_user_database(void) { + _cleanup_fclose_ FILE *f = NULL; + const char *passwd_path; + struct passwd *pw; + int r; + + passwd_path = prefix_roota(arg_root, "/etc/passwd"); + f = fopen(passwd_path, "re"); + if (!f) + return errno == ENOENT ? 0 : -errno; + + r = hashmap_ensure_allocated(&database_by_username, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&database_by_uid, NULL); + if (r < 0) + return r; + + r = set_ensure_allocated(&database_users, NULL); + if (r < 0) + return r; + + while ((r = fgetpwent_sane(f, &pw)) > 0) { + char *n; + int k, q; + + n = strdup(pw->pw_name); + if (!n) + return -ENOMEM; + + k = set_put(database_users, n); + if (k < 0) { + free(n); + return k; + } + + k = hashmap_put(database_by_username, n, UID_TO_PTR(pw->pw_uid)); + if (k < 0 && k != -EEXIST) + return k; + + q = hashmap_put(database_by_uid, UID_TO_PTR(pw->pw_uid), n); + if (q < 0 && q != -EEXIST) + return q; + } + return r; +} + +static int load_group_database(void) { + _cleanup_fclose_ FILE *f = NULL; + const char *group_path; + struct group *gr; + int r; + + group_path = prefix_roota(arg_root, "/etc/group"); + f = fopen(group_path, "re"); + if (!f) + return errno == ENOENT ? 0 : -errno; + + r = hashmap_ensure_allocated(&database_by_groupname, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_ensure_allocated(&database_by_gid, NULL); + if (r < 0) + return r; + + r = set_ensure_allocated(&database_groups, NULL); + if (r < 0) + return r; + + while ((r = fgetgrent_sane(f, &gr)) > 0) { + char *n; + int k, q; + + n = strdup(gr->gr_name); + if (!n) + return -ENOMEM; + + k = set_put(database_groups, n); + if (k < 0) { + free(n); + return k; + } + + k = hashmap_put(database_by_groupname, n, GID_TO_PTR(gr->gr_gid)); + if (k < 0 && k != -EEXIST) + return k; + + q = hashmap_put(database_by_gid, GID_TO_PTR(gr->gr_gid), n); + if (q < 0 && q != -EEXIST) + return q; + } + return r; +} + +static int make_backup(const char *target, const char *x) { + _cleanup_close_ int src = -1; + _cleanup_fclose_ FILE *dst = NULL; + _cleanup_free_ char *temp = NULL; + char *backup; + struct timespec ts[2]; + struct stat st; + int r; + + src = open(x, O_RDONLY|O_CLOEXEC|O_NOCTTY); + if (src < 0) { + if (errno == ENOENT) /* No backup necessary... */ + return 0; + + return -errno; + } + + if (fstat(src, &st) < 0) + return -errno; + + r = fopen_temporary_label(target, x, &dst, &temp); + if (r < 0) + return r; + + r = copy_bytes(src, fileno(dst), (uint64_t) -1, COPY_REFLINK); + if (r < 0) + goto fail; + + /* Don't fail on chmod() or chown(). If it stays owned by us + * and/or unreadable by others, then it isn't too bad... */ + + backup = strjoina(x, "-"); + + /* Copy over the access mask */ + r = fchmod_and_chown(fileno(dst), st.st_mode & 07777, st.st_uid, st.st_gid); + if (r < 0) + log_warning_errno(r, "Failed to change access mode or ownership of %s: %m", backup); + + ts[0] = st.st_atim; + ts[1] = st.st_mtim; + if (futimens(fileno(dst), ts) < 0) + log_warning_errno(errno, "Failed to fix access and modification time of %s: %m", backup); + + r = fflush_sync_and_check(dst); + if (r < 0) + goto fail; + + if (rename(temp, backup) < 0) { + r = -errno; + goto fail; + } + + return 0; + +fail: + (void) unlink(temp); + return r; +} + +static int putgrent_with_members(const struct group *gr, FILE *group) { + char **a; + + assert(gr); + assert(group); + + a = ordered_hashmap_get(members, gr->gr_name); + if (a) { + _cleanup_strv_free_ char **l = NULL; + bool added = false; + char **i; + + l = strv_copy(gr->gr_mem); + if (!l) + return -ENOMEM; + + STRV_FOREACH(i, a) { + if (strv_find(l, *i)) + continue; + + if (strv_extend(&l, *i) < 0) + return -ENOMEM; + + added = true; + } + + if (added) { + struct group t; + int r; + + strv_uniq(l); + strv_sort(l); + + t = *gr; + t.gr_mem = l; + + r = putgrent_sane(&t, group); + return r < 0 ? r : 1; + } + } + + return putgrent_sane(gr, group); +} + +#if ENABLE_GSHADOW +static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) { + char **a; + + assert(sg); + assert(gshadow); + + a = ordered_hashmap_get(members, sg->sg_namp); + if (a) { + _cleanup_strv_free_ char **l = NULL; + bool added = false; + char **i; + + l = strv_copy(sg->sg_mem); + if (!l) + return -ENOMEM; + + STRV_FOREACH(i, a) { + if (strv_find(l, *i)) + continue; + + if (strv_extend(&l, *i) < 0) + return -ENOMEM; + + added = true; + } + + if (added) { + struct sgrp t; + int r; + + strv_uniq(l); + strv_sort(l); + + t = *sg; + t.sg_mem = l; + + r = putsgent_sane(&t, gshadow); + return r < 0 ? r : 1; + } + } + + return putsgent_sane(sg, gshadow); +} +#endif + +static int sync_rights(FILE *from, FILE *to) { + struct stat st; + + if (fstat(fileno(from), &st) < 0) + return -errno; + + return fchmod_and_chown(fileno(to), st.st_mode & 07777, st.st_uid, st.st_gid); +} + +static int rename_and_apply_smack(const char *temp_path, const char *dest_path) { + int r = 0; + if (rename(temp_path, dest_path) < 0) + return -errno; + +#ifdef SMACK_RUN_LABEL + r = mac_smack_apply(dest_path, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL); + if (r < 0) + return r; +#endif + return r; +} + +static const char* default_shell(uid_t uid) { + return uid == 0 ? "/bin/sh" : NOLOGIN; +} + +static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char **tmpfile_path) { + _cleanup_fclose_ FILE *original = NULL, *passwd = NULL; + _cleanup_(unlink_and_freep) char *passwd_tmp = NULL; + struct passwd *pw = NULL; + Iterator iterator; + Item *i; + int r; + + if (ordered_hashmap_size(todo_uids) == 0) + return 0; + + r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp); + if (r < 0) + return r; + + original = fopen(passwd_path, "re"); + if (original) { + + r = sync_rights(original, passwd); + if (r < 0) + return r; + + while ((r = fgetpwent_sane(original, &pw)) > 0) { + + i = ordered_hashmap_get(users, pw->pw_name); + if (i && i->todo_user) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "%s: User \"%s\" already exists.", + passwd_path, pw->pw_name); + + if (ordered_hashmap_contains(todo_uids, UID_TO_PTR(pw->pw_uid))) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "%s: Detected collision for UID " UID_FMT ".", + passwd_path, pw->pw_uid); + + /* Make sure we keep the NIS entries (if any) at the end. */ + if (IN_SET(pw->pw_name[0], '+', '-')) + break; + + r = putpwent_sane(pw, passwd); + if (r < 0) + return r; + } + if (r < 0) + return r; + + } else { + if (errno != ENOENT) + return -errno; + if (fchmod(fileno(passwd), 0644) < 0) + return -errno; + } + + ORDERED_HASHMAP_FOREACH(i, todo_uids, iterator) { + struct passwd n = { + .pw_name = i->name, + .pw_uid = i->uid, + .pw_gid = i->gid, + .pw_gecos = i->description, + + /* "x" means the password is stored in the shadow file */ + .pw_passwd = (char*) "x", + + /* We default to the root directory as home */ + .pw_dir = i->home ?: (char*) "/", + + /* Initialize the shell to nologin, with one exception: + * for root we patch in something special */ + .pw_shell = i->shell ?: (char*) default_shell(i->uid), + }; + + r = putpwent_sane(&n, passwd); + if (r < 0) + return r; + } + + /* Append the remaining NIS entries if any */ + while (pw) { + r = putpwent_sane(pw, passwd); + if (r < 0) + return r; + + r = fgetpwent_sane(original, &pw); + if (r < 0) + return r; + if (r == 0) + break; + } + + r = fflush_and_check(passwd); + if (r < 0) + return r; + + *tmpfile = TAKE_PTR(passwd); + *tmpfile_path = TAKE_PTR(passwd_tmp); + + return 0; +} + +static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char **tmpfile_path) { + _cleanup_fclose_ FILE *original = NULL, *shadow = NULL; + _cleanup_(unlink_and_freep) char *shadow_tmp = NULL; + struct spwd *sp = NULL; + Iterator iterator; + long lstchg; + Item *i; + int r; + + if (ordered_hashmap_size(todo_uids) == 0) + return 0; + + r = fopen_temporary_label("/etc/shadow", shadow_path, &shadow, &shadow_tmp); + if (r < 0) + return r; + + lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY); + + original = fopen(shadow_path, "re"); + if (original) { + + r = sync_rights(original, shadow); + if (r < 0) + return r; + + while ((r = fgetspent_sane(original, &sp)) > 0) { + + i = ordered_hashmap_get(users, sp->sp_namp); + if (i && i->todo_user) { + /* we will update the existing entry */ + sp->sp_lstchg = lstchg; + + /* only the /etc/shadow stage is left, so we can + * safely remove the item from the todo set */ + i->todo_user = false; + ordered_hashmap_remove(todo_uids, UID_TO_PTR(i->uid)); + } + + /* Make sure we keep the NIS entries (if any) at the end. */ + if (IN_SET(sp->sp_namp[0], '+', '-')) + break; + + r = putspent_sane(sp, shadow); + if (r < 0) + return r; + } + if (r < 0) + return r; + + } else { + if (errno != ENOENT) + return -errno; + if (fchmod(fileno(shadow), 0000) < 0) + return -errno; + } + + ORDERED_HASHMAP_FOREACH(i, todo_uids, iterator) { + struct spwd n = { + .sp_namp = i->name, + .sp_pwdp = (char*) "!!", /* lock this password, and make it invalid */ + .sp_lstchg = lstchg, + .sp_min = -1, + .sp_max = -1, + .sp_warn = -1, + .sp_inact = -1, + .sp_expire = -1, + .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */ + }; + + r = putspent_sane(&n, shadow); + if (r < 0) + return r; + } + + /* Append the remaining NIS entries if any */ + while (sp) { + r = putspent_sane(sp, shadow); + if (r < 0) + return r; + + r = fgetspent_sane(original, &sp); + if (r < 0) + return r; + if (r == 0) + break; + } + if (!IN_SET(errno, 0, ENOENT)) + return -errno; + + r = fflush_sync_and_check(shadow); + if (r < 0) + return r; + + *tmpfile = TAKE_PTR(shadow); + *tmpfile_path = TAKE_PTR(shadow_tmp); + + return 0; +} + +static int write_temporary_group(const char *group_path, FILE **tmpfile, char **tmpfile_path) { + _cleanup_fclose_ FILE *original = NULL, *group = NULL; + _cleanup_(unlink_and_freep) char *group_tmp = NULL; + bool group_changed = false; + struct group *gr = NULL; + Iterator iterator; + Item *i; + int r; + + if (ordered_hashmap_size(todo_gids) == 0 && ordered_hashmap_size(members) == 0) + return 0; + + r = fopen_temporary_label("/etc/group", group_path, &group, &group_tmp); + if (r < 0) + return r; + + original = fopen(group_path, "re"); + if (original) { + + r = sync_rights(original, group); + if (r < 0) + return r; + + while ((r = fgetgrent_sane(original, &gr)) > 0) { + /* Safety checks against name and GID collisions. Normally, + * this should be unnecessary, but given that we look at the + * entries anyway here, let's make an extra verification + * step that we don't generate duplicate entries. */ + + i = ordered_hashmap_get(groups, gr->gr_name); + if (i && i->todo_group) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "%s: Group \"%s\" already exists.", + group_path, gr->gr_name); + + if (ordered_hashmap_contains(todo_gids, GID_TO_PTR(gr->gr_gid))) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "%s: Detected collision for GID " GID_FMT ".", + group_path, gr->gr_gid); + + /* Make sure we keep the NIS entries (if any) at the end. */ + if (IN_SET(gr->gr_name[0], '+', '-')) + break; + + r = putgrent_with_members(gr, group); + if (r < 0) + return r; + if (r > 0) + group_changed = true; + } + if (r < 0) + return r; + + } else { + if (errno != ENOENT) + return -errno; + if (fchmod(fileno(group), 0644) < 0) + return -errno; + } + + ORDERED_HASHMAP_FOREACH(i, todo_gids, iterator) { + struct group n = { + .gr_name = i->name, + .gr_gid = i->gid, + .gr_passwd = (char*) "x", + }; + + r = putgrent_with_members(&n, group); + if (r < 0) + return r; + + group_changed = true; + } + + /* Append the remaining NIS entries if any */ + while (gr) { + r = putgrent_sane(gr, group); + if (r < 0) + return r; + + r = fgetgrent_sane(original, &gr); + if (r < 0) + return r; + if (r == 0) + break; + } + + r = fflush_sync_and_check(group); + if (r < 0) + return r; + + if (group_changed) { + *tmpfile = TAKE_PTR(group); + *tmpfile_path = TAKE_PTR(group_tmp); + } + return 0; +} + +static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, char **tmpfile_path) { +#if ENABLE_GSHADOW + _cleanup_fclose_ FILE *original = NULL, *gshadow = NULL; + _cleanup_(unlink_and_freep) char *gshadow_tmp = NULL; + bool group_changed = false; + Iterator iterator; + Item *i; + int r; + + if (ordered_hashmap_size(todo_gids) == 0 && ordered_hashmap_size(members) == 0) + return 0; + + r = fopen_temporary_label("/etc/gshadow", gshadow_path, &gshadow, &gshadow_tmp); + if (r < 0) + return r; + + original = fopen(gshadow_path, "re"); + if (original) { + struct sgrp *sg; + + r = sync_rights(original, gshadow); + if (r < 0) + return r; + + while ((r = fgetsgent_sane(original, &sg)) > 0) { + + i = ordered_hashmap_get(groups, sg->sg_namp); + if (i && i->todo_group) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "%s: Group \"%s\" already exists.", + gshadow_path, sg->sg_namp); + + r = putsgent_with_members(sg, gshadow); + if (r < 0) + return r; + if (r > 0) + group_changed = true; + } + if (r < 0) + return r; + + } else { + if (errno != ENOENT) + return -errno; + if (fchmod(fileno(gshadow), 0000) < 0) + return -errno; + } + + ORDERED_HASHMAP_FOREACH(i, todo_gids, iterator) { + struct sgrp n = { + .sg_namp = i->name, + .sg_passwd = (char*) "!!", + }; + + r = putsgent_with_members(&n, gshadow); + if (r < 0) + return r; + + group_changed = true; + } + + r = fflush_sync_and_check(gshadow); + if (r < 0) + return r; + + if (group_changed) { + *tmpfile = TAKE_PTR(gshadow); + *tmpfile_path = TAKE_PTR(gshadow_tmp); + } + return 0; +#else + return 0; +#endif +} + +static int write_files(void) { + _cleanup_fclose_ FILE *passwd = NULL, *group = NULL, *shadow = NULL, *gshadow = NULL; + _cleanup_(unlink_and_freep) char *passwd_tmp = NULL, *group_tmp = NULL, *shadow_tmp = NULL, *gshadow_tmp = NULL; + const char *passwd_path = NULL, *group_path = NULL, *shadow_path = NULL, *gshadow_path = NULL; + int r; + + passwd_path = prefix_roota(arg_root, "/etc/passwd"); + shadow_path = prefix_roota(arg_root, "/etc/shadow"); + group_path = prefix_roota(arg_root, "/etc/group"); + gshadow_path = prefix_roota(arg_root, "/etc/gshadow"); + + r = write_temporary_group(group_path, &group, &group_tmp); + if (r < 0) + return r; + + r = write_temporary_gshadow(gshadow_path, &gshadow, &gshadow_tmp); + if (r < 0) + return r; + + r = write_temporary_passwd(passwd_path, &passwd, &passwd_tmp); + if (r < 0) + return r; + + r = write_temporary_shadow(shadow_path, &shadow, &shadow_tmp); + if (r < 0) + return r; + + /* Make a backup of the old files */ + if (group) { + r = make_backup("/etc/group", group_path); + if (r < 0) + return r; + } + if (gshadow) { + r = make_backup("/etc/gshadow", gshadow_path); + if (r < 0) + return r; + } + + if (passwd) { + r = make_backup("/etc/passwd", passwd_path); + if (r < 0) + return r; + } + if (shadow) { + r = make_backup("/etc/shadow", shadow_path); + if (r < 0) + return r; + } + + /* And make the new files count */ + if (group) { + r = rename_and_apply_smack(group_tmp, group_path); + if (r < 0) + return r; + + group_tmp = mfree(group_tmp); + } + if (gshadow) { + r = rename_and_apply_smack(gshadow_tmp, gshadow_path); + if (r < 0) + return r; + + gshadow_tmp = mfree(gshadow_tmp); + } + + if (passwd) { + r = rename_and_apply_smack(passwd_tmp, passwd_path); + if (r < 0) + return r; + + passwd_tmp = mfree(passwd_tmp); + } + if (shadow) { + r = rename_and_apply_smack(shadow_tmp, shadow_path); + if (r < 0) + return r; + + shadow_tmp = mfree(shadow_tmp); + } + + return 0; +} + +static int uid_is_ok(uid_t uid, const char *name, bool check_with_gid) { + struct passwd *p; + struct group *g; + const char *n; + Item *i; + + /* Let's see if we already have assigned the UID a second time */ + if (ordered_hashmap_get(todo_uids, UID_TO_PTR(uid))) + return 0; + + /* Try to avoid using uids that are already used by a group + * that doesn't have the same name as our new user. */ + if (check_with_gid) { + i = ordered_hashmap_get(todo_gids, GID_TO_PTR(uid)); + if (i && !streq(i->name, name)) + return 0; + } + + /* Let's check the files directly */ + if (hashmap_contains(database_by_uid, UID_TO_PTR(uid))) + return 0; + + if (check_with_gid) { + n = hashmap_get(database_by_gid, GID_TO_PTR(uid)); + if (n && !streq(n, name)) + return 0; + } + + /* Let's also check via NSS, to avoid UID clashes over LDAP and such, just in case */ + if (!arg_root) { + errno = 0; + p = getpwuid(uid); + if (p) + return 0; + if (!IN_SET(errno, 0, ENOENT)) + return -errno; + + if (check_with_gid) { + errno = 0; + g = getgrgid((gid_t) uid); + if (g) { + if (!streq(g->gr_name, name)) + return 0; + } else if (!IN_SET(errno, 0, ENOENT)) + return -errno; + } + } + + return 1; +} + +static int root_stat(const char *p, struct stat *st) { + const char *fix; + + fix = prefix_roota(arg_root, p); + if (stat(fix, st) < 0) + return -errno; + + return 0; +} + +static int read_id_from_file(Item *i, uid_t *_uid, gid_t *_gid) { + struct stat st; + bool found_uid = false, found_gid = false; + uid_t uid = 0; + gid_t gid = 0; + + assert(i); + + /* First, try to get the gid directly */ + if (_gid && i->gid_path && root_stat(i->gid_path, &st) >= 0) { + gid = st.st_gid; + found_gid = true; + } + + /* Then, try to get the uid directly */ + if ((_uid || (_gid && !found_gid)) + && i->uid_path + && root_stat(i->uid_path, &st) >= 0) { + + uid = st.st_uid; + found_uid = true; + + /* If we need the gid, but had no success yet, also derive it from the uid path */ + if (_gid && !found_gid) { + gid = st.st_gid; + found_gid = true; + } + } + + /* If that didn't work yet, then let's reuse the gid as uid */ + if (_uid && !found_uid && i->gid_path) { + + if (found_gid) { + uid = (uid_t) gid; + found_uid = true; + } else if (root_stat(i->gid_path, &st) >= 0) { + uid = (uid_t) st.st_gid; + found_uid = true; + } + } + + if (_uid) { + if (!found_uid) + return 0; + + *_uid = uid; + } + + if (_gid) { + if (!found_gid) + return 0; + + *_gid = gid; + } + + return 1; +} + +static int add_user(Item *i) { + void *z; + int r; + + assert(i); + + /* Check the database directly */ + z = hashmap_get(database_by_username, i->name); + if (z) { + log_debug("User %s already exists.", i->name); + i->uid = PTR_TO_UID(z); + i->uid_set = true; + return 0; + } + + if (!arg_root) { + struct passwd *p; + + /* Also check NSS */ + errno = 0; + p = getpwnam(i->name); + if (p) { + log_debug("User %s already exists.", i->name); + i->uid = p->pw_uid; + i->uid_set = true; + + r = free_and_strdup(&i->description, p->pw_gecos); + if (r < 0) + return log_oom(); + + return 0; + } + if (!IN_SET(errno, 0, ENOENT)) + return log_error_errno(errno, "Failed to check if user %s already exists: %m", i->name); + } + + /* Try to use the suggested numeric uid */ + if (i->uid_set) { + r = uid_is_ok(i->uid, i->name, !i->id_set_strict); + if (r < 0) + return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid); + if (r == 0) { + log_debug("Suggested user ID " UID_FMT " for %s already used.", i->uid, i->name); + i->uid_set = false; + } + } + + /* If that didn't work, try to read it from the specified path */ + if (!i->uid_set) { + uid_t c; + + if (read_id_from_file(i, &c, NULL) > 0) { + + if (c <= 0 || !uid_range_contains(uid_range, n_uid_range, c)) + log_debug("User ID " UID_FMT " of file not suitable for %s.", c, i->name); + else { + r = uid_is_ok(c, i->name, true); + if (r < 0) + return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid); + else if (r > 0) { + i->uid = c; + i->uid_set = true; + } else + log_debug("User ID " UID_FMT " of file for %s is already used.", c, i->name); + } + } + } + + /* Otherwise, try to reuse the group ID */ + if (!i->uid_set && i->gid_set) { + r = uid_is_ok((uid_t) i->gid, i->name, true); + if (r < 0) + return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid); + if (r > 0) { + i->uid = (uid_t) i->gid; + i->uid_set = true; + } + } + + /* And if that didn't work either, let's try to find a free one */ + if (!i->uid_set) { + for (;;) { + r = uid_range_next_lower(uid_range, n_uid_range, &search_uid); + if (r < 0) + return log_error_errno(r, "No free user ID available for %s.", i->name); + + r = uid_is_ok(search_uid, i->name, true); + if (r < 0) + return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid); + else if (r > 0) + break; + } + + i->uid_set = true; + i->uid = search_uid; + } + + r = ordered_hashmap_ensure_allocated(&todo_uids, NULL); + if (r < 0) + return log_oom(); + + r = ordered_hashmap_put(todo_uids, UID_TO_PTR(i->uid), i); + if (r < 0) + return log_oom(); + + i->todo_user = true; + log_info("Creating user %s (%s) with uid " UID_FMT " and gid " GID_FMT ".", i->name, strna(i->description), i->uid, i->gid); + + return 0; +} + +static int gid_is_ok(gid_t gid) { + struct group *g; + struct passwd *p; + + if (ordered_hashmap_get(todo_gids, GID_TO_PTR(gid))) + return 0; + + /* Avoid reusing gids that are already used by a different user */ + if (ordered_hashmap_get(todo_uids, UID_TO_PTR(gid))) + return 0; + + if (hashmap_contains(database_by_gid, GID_TO_PTR(gid))) + return 0; + + if (hashmap_contains(database_by_uid, UID_TO_PTR(gid))) + return 0; + + if (!arg_root) { + errno = 0; + g = getgrgid(gid); + if (g) + return 0; + if (!IN_SET(errno, 0, ENOENT)) + return -errno; + + errno = 0; + p = getpwuid((uid_t) gid); + if (p) + return 0; + if (!IN_SET(errno, 0, ENOENT)) + return -errno; + } + + return 1; +} + +static int add_group(Item *i) { + void *z; + int r; + + assert(i); + + /* Check the database directly */ + z = hashmap_get(database_by_groupname, i->name); + if (z) { + log_debug("Group %s already exists.", i->name); + i->gid = PTR_TO_GID(z); + i->gid_set = true; + return 0; + } + + /* Also check NSS */ + if (!arg_root) { + struct group *g; + + errno = 0; + g = getgrnam(i->name); + if (g) { + log_debug("Group %s already exists.", i->name); + i->gid = g->gr_gid; + i->gid_set = true; + return 0; + } + if (!IN_SET(errno, 0, ENOENT)) + return log_error_errno(errno, "Failed to check if group %s already exists: %m", i->name); + } + + /* Try to use the suggested numeric gid */ + if (i->gid_set) { + r = gid_is_ok(i->gid); + if (r < 0) + return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid); + if (i->id_set_strict) { + /* If we require the gid to already exist we can return here: + * r > 0: means the gid does not exist -> fail + * r == 0: means the gid exists -> nothing more to do. + */ + if (r > 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to create %s: please create GID %d", + i->name, i->gid); + if (r == 0) + return 0; + } + if (r == 0) { + log_debug("Suggested group ID " GID_FMT " for %s already used.", i->gid, i->name); + i->gid_set = false; + } + } + + /* Try to reuse the numeric uid, if there's one */ + if (!i->gid_set && i->uid_set) { + r = gid_is_ok((gid_t) i->uid); + if (r < 0) + return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid); + if (r > 0) { + i->gid = (gid_t) i->uid; + i->gid_set = true; + } + } + + /* If that didn't work, try to read it from the specified path */ + if (!i->gid_set) { + gid_t c; + + if (read_id_from_file(i, NULL, &c) > 0) { + + if (c <= 0 || !uid_range_contains(uid_range, n_uid_range, c)) + log_debug("Group ID " GID_FMT " of file not suitable for %s.", c, i->name); + else { + r = gid_is_ok(c); + if (r < 0) + return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid); + else if (r > 0) { + i->gid = c; + i->gid_set = true; + } else + log_debug("Group ID " GID_FMT " of file for %s already used.", c, i->name); + } + } + } + + /* And if that didn't work either, let's try to find a free one */ + if (!i->gid_set) { + for (;;) { + /* We look for new GIDs in the UID pool! */ + r = uid_range_next_lower(uid_range, n_uid_range, &search_uid); + if (r < 0) + return log_error_errno(r, "No free group ID available for %s.", i->name); + + r = gid_is_ok(search_uid); + if (r < 0) + return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid); + else if (r > 0) + break; + } + + i->gid_set = true; + i->gid = search_uid; + } + + r = ordered_hashmap_ensure_allocated(&todo_gids, NULL); + if (r < 0) + return log_oom(); + + r = ordered_hashmap_put(todo_gids, GID_TO_PTR(i->gid), i); + if (r < 0) + return log_oom(); + + i->todo_group = true; + log_info("Creating group %s with gid " GID_FMT ".", i->name, i->gid); + + return 0; +} + +static int process_item(Item *i) { + int r; + + assert(i); + + switch (i->type) { + + case ADD_USER: { + Item *j; + + j = ordered_hashmap_get(groups, i->name); + if (j && j->todo_group) { + /* When the group with the same name is already in queue, + * use the information about the group and do not create + * duplicated group entry. */ + i->gid_set = j->gid_set; + i->gid = j->gid; + i->id_set_strict = true; + } else { + r = add_group(i); + if (r < 0) + return r; + } + + return add_user(i); + } + + case ADD_GROUP: + return add_group(i); + + default: + assert_not_reached("Unknown item type"); + } +} + +static Item* item_free(Item *i) { + if (!i) + return NULL; + + free(i->name); + free(i->uid_path); + free(i->gid_path); + free(i->description); + free(i->home); + free(i->shell); + return mfree(i); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Item*, item_free); +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_hash_ops, char, string_hash_func, string_compare_func, Item, item_free); + +static int add_implicit(void) { + char *g, **l; + Iterator iterator; + int r; + + /* Implicitly create additional users and groups, if they were listed in "m" lines */ + ORDERED_HASHMAP_FOREACH_KEY(l, g, members, iterator) { + char **m; + + STRV_FOREACH(m, l) + if (!ordered_hashmap_get(users, *m)) { + _cleanup_(item_freep) Item *j = NULL; + + r = ordered_hashmap_ensure_allocated(&users, &item_hash_ops); + if (r < 0) + return log_oom(); + + j = new0(Item, 1); + if (!j) + return log_oom(); + + j->type = ADD_USER; + j->name = strdup(*m); + if (!j->name) + return log_oom(); + + r = ordered_hashmap_put(users, j->name, j); + if (r < 0) + return log_oom(); + + log_debug("Adding implicit user '%s' due to m line", j->name); + j = NULL; + } + + if (!(ordered_hashmap_get(users, g) || + ordered_hashmap_get(groups, g))) { + _cleanup_(item_freep) Item *j = NULL; + + r = ordered_hashmap_ensure_allocated(&groups, &item_hash_ops); + if (r < 0) + return log_oom(); + + j = new0(Item, 1); + if (!j) + return log_oom(); + + j->type = ADD_GROUP; + j->name = strdup(g); + if (!j->name) + return log_oom(); + + r = ordered_hashmap_put(groups, j->name, j); + if (r < 0) + return log_oom(); + + log_debug("Adding implicit group '%s' due to m line", j->name); + j = NULL; + } + } + + return 0; +} + +static bool item_equal(Item *a, Item *b) { + assert(a); + assert(b); + + if (a->type != b->type) + return false; + + if (!streq_ptr(a->name, b->name)) + return false; + + if (!streq_ptr(a->uid_path, b->uid_path)) + return false; + + if (!streq_ptr(a->gid_path, b->gid_path)) + return false; + + if (!streq_ptr(a->description, b->description)) + return false; + + if (a->uid_set != b->uid_set) + return false; + + if (a->uid_set && a->uid != b->uid) + return false; + + if (a->gid_set != b->gid_set) + return false; + + if (a->gid_set && a->gid != b->gid) + return false; + + if (!streq_ptr(a->home, b->home)) + return false; + + if (!streq_ptr(a->shell, b->shell)) + return false; + + return true; +} + +static int parse_line(const char *fname, unsigned line, const char *buffer) { + + static const Specifier specifier_table[] = { + { 'm', specifier_machine_id, NULL }, + { 'b', specifier_boot_id, NULL }, + { 'H', specifier_host_name, NULL }, + { 'v', specifier_kernel_release, NULL }, + { 'T', specifier_tmp_dir, NULL }, + { 'V', specifier_var_tmp_dir, NULL }, + {} + }; + + _cleanup_free_ char *action = NULL, + *name = NULL, *resolved_name = NULL, + *id = NULL, *resolved_id = NULL, + *description = NULL, *resolved_description = NULL, + *home = NULL, *resolved_home = NULL, + *shell = NULL, *resolved_shell = NULL; + _cleanup_(item_freep) Item *i = NULL; + Item *existing; + OrderedHashmap *h; + int r; + const char *p; + + assert(fname); + assert(line >= 1); + assert(buffer); + + /* Parse columns */ + p = buffer; + r = extract_many_words(&p, NULL, EXTRACT_UNQUOTE, + &action, &name, &id, &description, &home, &shell, NULL); + if (r < 0) + return log_error_errno(r, "[%s:%u] Syntax error.", fname, line); + if (r < 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Missing action and name columns.", fname, line); + if (!isempty(p)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Trailing garbage.", fname, line); + + /* Verify action */ + if (strlen(action) != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Unknown modifier '%s'", fname, line, action); + + if (!IN_SET(action[0], ADD_USER, ADD_GROUP, ADD_MEMBER, ADD_RANGE)) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "[%s:%u] Unknown command type '%c'.", fname, line, action[0]); + + /* Verify name */ + if (empty_or_dash(name)) + name = mfree(name); + + if (name) { + r = specifier_printf(name, specifier_table, NULL, &resolved_name); + if (r < 0) + log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, name); + + if (!valid_user_group_name(resolved_name)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] '%s' is not a valid user or group name.", + fname, line, resolved_name); + } + + /* Verify id */ + if (empty_or_dash(id)) + id = mfree(id); + + if (id) { + r = specifier_printf(id, specifier_table, NULL, &resolved_id); + if (r < 0) + return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", + fname, line, name); + } + + /* Verify description */ + if (empty_or_dash(description)) + description = mfree(description); + + if (description) { + r = specifier_printf(description, specifier_table, NULL, &resolved_description); + if (r < 0) + return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", + fname, line, description); + + if (!valid_gecos(resolved_description)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] '%s' is not a valid GECOS field.", + fname, line, resolved_description); + } + + /* Verify home */ + if (empty_or_dash(home)) + home = mfree(home); + + if (home) { + r = specifier_printf(home, specifier_table, NULL, &resolved_home); + if (r < 0) + return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", + fname, line, home); + + if (!valid_home(resolved_home)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] '%s' is not a valid home directory field.", + fname, line, resolved_home); + } + + /* Verify shell */ + if (empty_or_dash(shell)) + shell = mfree(shell); + + if (shell) { + r = specifier_printf(shell, specifier_table, NULL, &resolved_shell); + if (r < 0) + return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", + fname, line, shell); + + if (!valid_shell(resolved_shell)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] '%s' is not a valid login shell field.", + fname, line, resolved_shell); + } + + switch (action[0]) { + + case ADD_RANGE: + if (resolved_name) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Lines of type 'r' don't take a name field.", + fname, line); + + if (!resolved_id) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Lines of type 'r' require a ID range in the third field.", + fname, line); + + if (description || home || shell) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Lines of type '%c' don't take a %s field.", + fname, line, action[0], + description ? "GECOS" : home ? "home directory" : "login shell"); + + r = uid_range_add_str(&uid_range, &n_uid_range, resolved_id); + if (r < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Invalid UID range %s.", fname, line, resolved_id); + + return 0; + + case ADD_MEMBER: { + /* Try to extend an existing member or group item */ + if (!name) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Lines of type 'm' require a user name in the second field.", + fname, line); + + if (!resolved_id) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Lines of type 'm' require a group name in the third field.", + fname, line); + + if (!valid_user_group_name(resolved_id)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] '%s' is not a valid user or group name.", + fname, line, resolved_id); + + if (description || home || shell) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Lines of type '%c' don't take a %s field.", + fname, line, action[0], + description ? "GECOS" : home ? "home directory" : "login shell"); + + r = string_strv_ordered_hashmap_put(&members, resolved_id, resolved_name); + if (r < 0) + return log_error_errno(r, "Failed to store mapping for %s: %m", resolved_id); + + return 0; + } + + case ADD_USER: + if (!name) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Lines of type 'u' require a user name in the second field.", + fname, line); + + r = ordered_hashmap_ensure_allocated(&users, &item_hash_ops); + if (r < 0) + return log_oom(); + + i = new0(Item, 1); + if (!i) + return log_oom(); + + if (resolved_id) { + if (path_is_absolute(resolved_id)) { + i->uid_path = TAKE_PTR(resolved_id); + path_simplify(i->uid_path, false); + } else { + _cleanup_free_ char *uid = NULL, *gid = NULL; + if (split_pair(resolved_id, ":", &uid, &gid) == 0) { + r = parse_gid(gid, &i->gid); + if (r < 0) + return log_error_errno(r, "Failed to parse GID: '%s': %m", id); + i->gid_set = true; + i->id_set_strict = true; + free_and_replace(resolved_id, uid); + } + if (!streq(resolved_id, "-")) { + r = parse_uid(resolved_id, &i->uid); + if (r < 0) + return log_error_errno(r, "Failed to parse UID: '%s': %m", id); + i->uid_set = true; + } + } + } + + i->description = TAKE_PTR(resolved_description); + i->home = TAKE_PTR(resolved_home); + i->shell = TAKE_PTR(resolved_shell); + + h = users; + break; + + case ADD_GROUP: + if (!name) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Lines of type 'g' require a user name in the second field.", + fname, line); + + if (description || home || shell) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] Lines of type '%c' don't take a %s field.", + fname, line, action[0], + description ? "GECOS" : home ? "home directory" : "login shell"); + + r = ordered_hashmap_ensure_allocated(&groups, &item_hash_ops); + if (r < 0) + return log_oom(); + + i = new0(Item, 1); + if (!i) + return log_oom(); + + if (resolved_id) { + if (path_is_absolute(resolved_id)) { + i->gid_path = TAKE_PTR(resolved_id); + path_simplify(i->gid_path, false); + } else { + r = parse_gid(resolved_id, &i->gid); + if (r < 0) + return log_error_errno(r, "Failed to parse GID: '%s': %m", id); + + i->gid_set = true; + } + } + + h = groups; + break; + + default: + return -EBADMSG; + } + + i->type = action[0]; + i->name = TAKE_PTR(resolved_name); + + existing = ordered_hashmap_get(h, i->name); + if (existing) { + /* Two identical items are fine */ + if (!item_equal(existing, i)) + log_warning("Two or more conflicting lines for %s configured, ignoring.", i->name); + + return 0; + } + + r = ordered_hashmap_put(h, i->name, i); + if (r < 0) + return log_oom(); + + i = NULL; + return 0; +} + +static int read_config_file(const char *fn, bool ignore_enoent) { + _cleanup_fclose_ FILE *rf = NULL; + FILE *f = NULL; + unsigned v = 0; + int r = 0; + + assert(fn); + + if (streq(fn, "-")) + f = stdin; + else { + r = search_and_fopen(fn, "re", arg_root, (const char**) CONF_PATHS_STRV("sysusers.d"), &rf); + if (r < 0) { + if (ignore_enoent && r == -ENOENT) + return 0; + + return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn); + } + + f = rf; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + char *l; + int k; + + k = read_line(f, LONG_LINE_MAX, &line); + if (k < 0) + return log_error_errno(k, "Failed to read '%s': %m", fn); + if (k == 0) + break; + + v++; + + l = strstrip(line); + if (IN_SET(*l, 0, '#')) + continue; + + k = parse_line(fn, v, l); + if (k < 0 && r == 0) + r = k; + } + + if (ferror(f)) { + log_error_errno(errno, "Failed to read from file %s: %m", fn); + if (r == 0) + r = -EIO; + } + + return r; +} + +static int cat_config(void) { + _cleanup_strv_free_ char **files = NULL; + int r; + + r = conf_files_list_with_replacement(arg_root, CONF_PATHS_STRV("sysusers.d"), arg_replace, &files, NULL); + if (r < 0) + return r; + + (void) pager_open(arg_pager_flags); + + return cat_files(NULL, files, 0); +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-sysusers.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" + "Creates system user accounts.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --cat-config Show configuration files\n" + " --root=PATH Operate on an alternate filesystem root\n" + " --replace=PATH Treat arguments as replacement for PATH\n" + " --inline Treat arguments as configuration lines\n" + " --no-pager Do not pipe output into a pager\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_CAT_CONFIG, + ARG_ROOT, + ARG_REPLACE, + ARG_INLINE, + ARG_NO_PAGER, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, + { "root", required_argument, NULL, ARG_ROOT }, + { "replace", required_argument, NULL, ARG_REPLACE }, + { "inline", no_argument, NULL, ARG_INLINE }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_CAT_CONFIG: + arg_cat_config = true; + break; + + case ARG_ROOT: + r = parse_path_argument_and_warn(optarg, true, &arg_root); + if (r < 0) + return r; + break; + + case ARG_REPLACE: + if (!path_is_absolute(optarg) || + !endswith(optarg, ".conf")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "The argument to --replace= must an absolute path to a config file"); + + arg_replace = optarg; + break; + + case ARG_INLINE: + arg_inline = true; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_replace && arg_cat_config) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --replace= is not supported with --cat-config"); + + if (arg_replace && optind >= argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "When --replace= is given, some configuration items must be specified"); + + return 1; +} + +static int parse_arguments(char **args) { + char **arg; + unsigned pos = 1; + int r; + + STRV_FOREACH(arg, args) { + if (arg_inline) + /* Use (argument):n, where n==1 for the first positional arg */ + r = parse_line("(argument)", pos, *arg); + else + r = read_config_file(*arg, false); + if (r < 0) + return r; + + pos++; + } + + return 0; +} + +static int read_config_files(char **args) { + _cleanup_strv_free_ char **files = NULL; + _cleanup_free_ char *p = NULL; + char **f; + int r; + + r = conf_files_list_with_replacement(arg_root, CONF_PATHS_STRV("sysusers.d"), arg_replace, &files, &p); + if (r < 0) + return r; + + STRV_FOREACH(f, files) + if (p && path_equal(*f, p)) { + log_debug("Parsing arguments at position \"%s\"…", *f); + + r = parse_arguments(args); + if (r < 0) + return r; + } else { + log_debug("Reading config file \"%s\"…", *f); + + /* Just warn, ignore result otherwise */ + (void) read_config_file(*f, true); + } + + return 0; +} + +static int run(int argc, char *argv[]) { + _cleanup_close_ int lock = -1; + Iterator iterator; + Item *i; + int r; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + log_setup_service(); + + if (arg_cat_config) + return cat_config(); + + umask(0022); + + r = mac_selinux_init(); + if (r < 0) + return log_error_errno(r, "SELinux setup failed: %m"); + + /* If command line arguments are specified along with --replace, read all + * configuration files and insert the positional arguments at the specified + * place. Otherwise, if command line arguments are specified, execute just + * them, and finally, without --replace= or any positional arguments, just + * read configuration and execute it. + */ + if (arg_replace || optind >= argc) + r = read_config_files(argv + optind); + else + r = parse_arguments(argv + optind); + if (r < 0) + return r; + + /* Let's tell nss-systemd not to synthesize the "root" and "nobody" entries for it, so that our detection + * whether the names or UID/GID area already used otherwise doesn't get confused. After all, even though + * nss-systemd synthesizes these users/groups, they should still appear in /etc/passwd and /etc/group, as the + * synthesizing logic is merely supposed to be fallback for cases where we run with a completely unpopulated + * /etc. */ + if (setenv("SYSTEMD_NSS_BYPASS_SYNTHETIC", "1", 1) < 0) + return log_error_errno(errno, "Failed to set SYSTEMD_NSS_BYPASS_SYNTHETIC environment variable: %m"); + + if (!uid_range) { + /* Default to default range of 1..SYSTEM_UID_MAX */ + r = uid_range_add(&uid_range, &n_uid_range, 1, SYSTEM_UID_MAX); + if (r < 0) + return log_oom(); + } + + r = add_implicit(); + if (r < 0) + return r; + + lock = take_etc_passwd_lock(arg_root); + if (lock < 0) + return log_error_errno(lock, "Failed to take /etc/passwd lock: %m"); + + r = load_user_database(); + if (r < 0) + return log_error_errno(r, "Failed to load user database: %m"); + + r = load_group_database(); + if (r < 0) + return log_error_errno(r, "Failed to read group database: %m"); + + ORDERED_HASHMAP_FOREACH(i, groups, iterator) + (void) process_item(i); + + ORDERED_HASHMAP_FOREACH(i, users, iterator) + (void) process_item(i); + + r = write_files(); + if (r < 0) + return log_error_errno(r, "Failed to write files: %m"); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c new file mode 100644 index 00000000..5df57438 --- /dev/null +++ b/src/sysv-generator/sysv-generator.c @@ -0,0 +1,956 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "dirent-util.h" +#include "exit-status.h" +#include "fd-util.h" +#include "fileio.h" +#include "generator.h" +#include "hashmap.h" +#include "hexdecoct.h" +#include "install.h" +#include "log.h" +#include "main-func.h" +#include "mkdir.h" +#include "path-lookup.h" +#include "path-util.h" +#include "set.h" +#include "special.h" +#include "specifier.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "unit-name.h" +#include "util.h" + +static const struct { + const char *path; + const char *target; +} rcnd_table[] = { + /* Standard SysV runlevels for start-up */ + { "rc1.d", SPECIAL_RESCUE_TARGET }, + { "rc2.d", SPECIAL_MULTI_USER_TARGET }, + { "rc3.d", SPECIAL_MULTI_USER_TARGET }, + { "rc4.d", SPECIAL_MULTI_USER_TARGET }, + { "rc5.d", SPECIAL_GRAPHICAL_TARGET }, + + /* We ignore the SysV runlevels for shutdown here, as SysV services get default dependencies anyway, and that + * means they are shut down anyway at system power off if running. */ +}; + +static const char *arg_dest = NULL; + +typedef struct SysvStub { + char *name; + char *path; + char *description; + int sysv_start_priority; + char *pid_file; + char **before; + char **after; + char **wants; + char **wanted_by; + bool has_lsb; + bool reload; + bool loaded; +} SysvStub; + +static void free_sysvstub(SysvStub *s) { + if (!s) + return; + + free(s->name); + free(s->path); + free(s->description); + free(s->pid_file); + strv_free(s->before); + strv_free(s->after); + strv_free(s->wants); + strv_free(s->wanted_by); + free(s); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(SysvStub*, free_sysvstub); + +static void free_sysvstub_hashmapp(Hashmap **h) { + hashmap_free_with_destructor(*h, free_sysvstub); +} + +static int add_alias(const char *service, const char *alias) { + const char *link; + int r; + + assert(service); + assert(alias); + + link = prefix_roota(arg_dest, alias); + + r = symlink(service, link); + if (r < 0) { + if (errno == EEXIST) + return 0; + + return -errno; + } + + return 1; +} + +static int generate_unit_file(SysvStub *s) { + _cleanup_free_ char *path_escaped = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *unit; + char **p; + int r; + + assert(s); + + if (!s->loaded) + return 0; + + path_escaped = specifier_escape(s->path); + if (!path_escaped) + return log_oom(); + + unit = prefix_roota(arg_dest, s->name); + + /* We might already have a symlink with the same name from a Provides:, + * or from backup files like /etc/init.d/foo.bak. Real scripts always win, + * so remove an existing link */ + if (is_symlink(unit) > 0) { + log_warning("Overwriting existing symlink %s with real service.", unit); + (void) unlink(unit); + } + + f = fopen(unit, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", unit); + + fprintf(f, + "# Automatically generated by systemd-sysv-generator\n\n" + "[Unit]\n" + "Documentation=man:systemd-sysv-generator(8)\n" + "SourcePath=%s\n", + path_escaped); + + if (s->description) { + _cleanup_free_ char *t; + + t = specifier_escape(s->description); + if (!t) + return log_oom(); + + fprintf(f, "Description=%s\n", t); + } + + STRV_FOREACH(p, s->before) + fprintf(f, "Before=%s\n", *p); + STRV_FOREACH(p, s->after) + fprintf(f, "After=%s\n", *p); + STRV_FOREACH(p, s->wants) + fprintf(f, "Wants=%s\n", *p); + + fprintf(f, + "\n[Service]\n" + "Type=forking\n" + "Restart=no\n" + "TimeoutSec=5min\n" + "IgnoreSIGPIPE=no\n" + "KillMode=process\n" + "GuessMainPID=no\n" + "RemainAfterExit=%s\n", + yes_no(!s->pid_file)); + + if (s->pid_file) { + _cleanup_free_ char *t; + + t = specifier_escape(s->pid_file); + if (!t) + return log_oom(); + + fprintf(f, "PIDFile=%s\n", t); + } + + /* Consider two special LSB exit codes a clean exit */ + if (s->has_lsb) + fprintf(f, + "SuccessExitStatus=%i %i\n", + EXIT_NOTINSTALLED, + EXIT_NOTCONFIGURED); + + fprintf(f, + "ExecStart=%s start\n" + "ExecStop=%s stop\n", + path_escaped, path_escaped); + + if (s->reload) + fprintf(f, "ExecReload=%s reload\n", path_escaped); + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write unit %s: %m", unit); + + STRV_FOREACH(p, s->wanted_by) + (void) generator_add_symlink(arg_dest, *p, "wants", s->name); + + return 1; +} + +static bool usage_contains_reload(const char *line) { + return (strcasestr(line, "{reload|") || + strcasestr(line, "{reload}") || + strcasestr(line, "{reload\"") || + strcasestr(line, "|reload|") || + strcasestr(line, "|reload}") || + strcasestr(line, "|reload\"")); +} + +static char *sysv_translate_name(const char *name) { + _cleanup_free_ char *c = NULL; + char *res; + + c = strdup(name); + if (!c) + return NULL; + + res = endswith(c, ".sh"); + if (res) + *res = 0; + + if (unit_name_mangle(c, 0, &res) < 0) + return NULL; + + return res; +} + +static int sysv_translate_facility(SysvStub *s, unsigned line, const char *name, char **ret) { + + /* We silently ignore the $ prefix here. According to the LSB + * spec it simply indicates whether something is a + * standardized name or a distribution-specific one. Since we + * just follow what already exists and do not introduce new + * uses or names we don't care who introduced a new name. */ + + static const char * const table[] = { + /* LSB defined facilities */ + "local_fs", NULL, + "network", SPECIAL_NETWORK_ONLINE_TARGET, + "named", SPECIAL_NSS_LOOKUP_TARGET, + "portmap", SPECIAL_RPCBIND_TARGET, + "remote_fs", SPECIAL_REMOTE_FS_TARGET, + "syslog", NULL, + "time", SPECIAL_TIME_SYNC_TARGET, + }; + + const char *filename; + char *filename_no_sh, *e, *m; + const char *n; + unsigned i; + int r; + + assert(name); + assert(s); + assert(ret); + + filename = basename(s->path); + + n = *name == '$' ? name + 1 : name; + + for (i = 0; i < ELEMENTSOF(table); i += 2) { + if (!streq(table[i], n)) + continue; + + if (!table[i+1]) { + *ret = NULL; + return 0; + } + + m = strdup(table[i+1]); + if (!m) + return log_oom(); + + *ret = m; + return 1; + } + + /* If we don't know this name, fallback heuristics to figure + * out whether something is a target or a service alias. */ + + /* Facilities starting with $ are most likely targets */ + if (*name == '$') { + r = unit_name_build(n, NULL, ".target", ret); + if (r < 0) + return log_error_errno(r, "[%s:%u] Could not build name for facility %s: %m", s->path, line, name); + + return 1; + } + + /* Strip ".sh" suffix from file name for comparison */ + filename_no_sh = strdupa(filename); + e = endswith(filename_no_sh, ".sh"); + if (e) { + *e = '\0'; + filename = filename_no_sh; + } + + /* Names equaling the file name of the services are redundant */ + if (streq_ptr(n, filename)) { + *ret = NULL; + return 0; + } + + /* Everything else we assume to be normal service names */ + m = sysv_translate_name(n); + if (!m) + return log_oom(); + + *ret = m; + return 1; +} + +static int handle_provides(SysvStub *s, unsigned line, const char *full_text, const char *text) { + int r; + + assert(s); + assert(full_text); + assert(text); + + for (;;) { + _cleanup_free_ char *word = NULL, *m = NULL; + + r = extract_first_word(&text, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX); + if (r < 0) + return log_error_errno(r, "[%s:%u] Failed to parse word from provides string: %m", s->path, line); + if (r == 0) + break; + + r = sysv_translate_facility(s, line, word, &m); + if (r <= 0) /* continue on error */ + continue; + + switch (unit_name_to_type(m)) { + + case UNIT_SERVICE: + log_debug("Adding Provides: alias '%s' for '%s'", m, s->name); + r = add_alias(s->name, m); + if (r < 0) + log_warning_errno(r, "[%s:%u] Failed to add LSB Provides name %s, ignoring: %m", s->path, line, m); + break; + + case UNIT_TARGET: + + /* NB: SysV targets which are provided by a + * service are pulled in by the services, as + * an indication that the generic service is + * now available. This is strictly one-way. + * The targets do NOT pull in SysV services! */ + + r = strv_extend(&s->before, m); + if (r < 0) + return log_oom(); + + r = strv_extend(&s->wants, m); + if (r < 0) + return log_oom(); + + if (streq(m, SPECIAL_NETWORK_ONLINE_TARGET)) { + r = strv_extend(&s->before, SPECIAL_NETWORK_TARGET); + if (r < 0) + return log_oom(); + r = strv_extend(&s->wants, SPECIAL_NETWORK_TARGET); + if (r < 0) + return log_oom(); + } + + break; + + case _UNIT_TYPE_INVALID: + log_warning("Unit name '%s' is invalid", m); + break; + + default: + log_warning("Unknown unit type for unit '%s'", m); + } + } + + return 0; +} + +static int handle_dependencies(SysvStub *s, unsigned line, const char *full_text, const char *text) { + int r; + + assert(s); + assert(full_text); + assert(text); + + for (;;) { + _cleanup_free_ char *word = NULL, *m = NULL; + bool is_before; + + r = extract_first_word(&text, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX); + if (r < 0) + return log_error_errno(r, "[%s:%u] Failed to parse word from provides string: %m", s->path, line); + if (r == 0) + break; + + r = sysv_translate_facility(s, line, word, &m); + if (r <= 0) /* continue on error */ + continue; + + is_before = startswith_no_case(full_text, "X-Start-Before:"); + + if (streq(m, SPECIAL_NETWORK_ONLINE_TARGET) && !is_before) { + /* the network-online target is special, as it needs to be actively pulled in */ + r = strv_extend(&s->after, m); + if (r < 0) + return log_oom(); + + r = strv_extend(&s->wants, m); + } else + r = strv_extend(is_before ? &s->before : &s->after, m); + if (r < 0) + return log_oom(); + } + + return 0; +} + +static int load_sysv(SysvStub *s) { + _cleanup_fclose_ FILE *f; + unsigned line = 0; + int r; + enum { + NORMAL, + DESCRIPTION, + LSB, + LSB_DESCRIPTION, + USAGE_CONTINUATION + } state = NORMAL; + _cleanup_free_ char *short_description = NULL, *long_description = NULL, *chkconfig_description = NULL; + char *description; + bool supports_reload = false; + + assert(s); + + f = fopen(s->path, "re"); + if (!f) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open %s: %m", s->path); + } + + log_debug("Loading SysV script %s", s->path); + + for (;;) { + _cleanup_free_ char *l = NULL; + char *t; + + r = read_line(f, LONG_LINE_MAX, &l); + if (r < 0) + return log_error_errno(r, "Failed to read configuration file '%s': %m", s->path); + if (r == 0) + break; + + line++; + + t = strstrip(l); + if (*t != '#') { + /* Try to figure out whether this init script supports + * the reload operation. This heuristic looks for + * "Usage" lines which include the reload option. */ + if (state == USAGE_CONTINUATION || + (state == NORMAL && strcasestr(t, "usage"))) { + if (usage_contains_reload(t)) { + supports_reload = true; + state = NORMAL; + } else if (t[strlen(t)-1] == '\\') + state = USAGE_CONTINUATION; + else + state = NORMAL; + } + + continue; + } + + if (state == NORMAL && streq(t, "### BEGIN INIT INFO")) { + state = LSB; + s->has_lsb = true; + continue; + } + + if (IN_SET(state, LSB_DESCRIPTION, LSB) && streq(t, "### END INIT INFO")) { + state = NORMAL; + continue; + } + + t++; + t += strspn(t, WHITESPACE); + + if (state == NORMAL) { + + /* Try to parse Red Hat style description */ + + if (startswith_no_case(t, "description:")) { + + size_t k; + const char *j; + + k = strlen(t); + if (k > 0 && t[k-1] == '\\') { + state = DESCRIPTION; + t[k-1] = 0; + } + + j = empty_to_null(strstrip(t+12)); + + r = free_and_strdup(&chkconfig_description, j); + if (r < 0) + return log_oom(); + + } else if (startswith_no_case(t, "pidfile:")) { + const char *fn; + + state = NORMAL; + + fn = strstrip(t+8); + if (!path_is_absolute(fn)) { + log_error("[%s:%u] PID file not absolute. Ignoring.", s->path, line); + continue; + } + + r = free_and_strdup(&s->pid_file, fn); + if (r < 0) + return log_oom(); + } + + } else if (state == DESCRIPTION) { + + /* Try to parse Red Hat style description + * continuation */ + + size_t k; + char *j; + + k = strlen(t); + if (k > 0 && t[k-1] == '\\') + t[k-1] = 0; + else + state = NORMAL; + + j = strstrip(t); + if (!isempty(j)) { + char *d = NULL; + + if (chkconfig_description) + d = strjoin(chkconfig_description, " ", j); + else + d = strdup(j); + if (!d) + return log_oom(); + + free(chkconfig_description); + chkconfig_description = d; + } + + } else if (IN_SET(state, LSB, LSB_DESCRIPTION)) { + + if (startswith_no_case(t, "Provides:")) { + state = LSB; + + r = handle_provides(s, line, t, t + 9); + if (r < 0) + return r; + + } else if (startswith_no_case(t, "Required-Start:") || + startswith_no_case(t, "Should-Start:") || + startswith_no_case(t, "X-Start-Before:") || + startswith_no_case(t, "X-Start-After:")) { + + state = LSB; + + r = handle_dependencies(s, line, t, strchr(t, ':') + 1); + if (r < 0) + return r; + + } else if (startswith_no_case(t, "Description:")) { + const char *j; + + state = LSB_DESCRIPTION; + + j = empty_to_null(strstrip(t+12)); + + r = free_and_strdup(&long_description, j); + if (r < 0) + return log_oom(); + + } else if (startswith_no_case(t, "Short-Description:")) { + const char *j; + + state = LSB; + + j = empty_to_null(strstrip(t+18)); + + r = free_and_strdup(&short_description, j); + if (r < 0) + return log_oom(); + + } else if (state == LSB_DESCRIPTION) { + + if (startswith(l, "#\t") || startswith(l, "# ")) { + const char *j; + + j = strstrip(t); + if (!isempty(j)) { + char *d = NULL; + + if (long_description) + d = strjoin(long_description, " ", t); + else + d = strdup(j); + if (!d) + return log_oom(); + + free(long_description); + long_description = d; + } + + } else + state = LSB; + } + } + } + + s->reload = supports_reload; + + /* We use the long description only if + * no short description is set. */ + + if (short_description) + description = short_description; + else if (chkconfig_description) + description = chkconfig_description; + else if (long_description) + description = long_description; + else + description = NULL; + + if (description) { + char *d; + + d = strjoin(s->has_lsb ? "LSB: " : "SYSV: ", description); + if (!d) + return log_oom(); + + s->description = d; + } + + s->loaded = true; + return 0; +} + +static int fix_order(SysvStub *s, Hashmap *all_services) { + SysvStub *other; + Iterator j; + int r; + + assert(s); + + if (!s->loaded) + return 0; + + if (s->sysv_start_priority < 0) + return 0; + + HASHMAP_FOREACH(other, all_services, j) { + if (s == other) + continue; + + if (!other->loaded) + continue; + + if (other->sysv_start_priority < 0) + continue; + + /* If both units have modern headers we don't care + * about the priorities */ + if (s->has_lsb && other->has_lsb) + continue; + + if (other->sysv_start_priority < s->sysv_start_priority) { + r = strv_extend(&s->after, other->name); + if (r < 0) + return log_oom(); + + } else if (other->sysv_start_priority > s->sysv_start_priority) { + r = strv_extend(&s->before, other->name); + if (r < 0) + return log_oom(); + } else + continue; + + /* FIXME: Maybe we should compare the name here lexicographically? */ + } + + return 0; +} + +static int acquire_search_path(const char *def, const char *envvar, char ***ret) { + _cleanup_strv_free_ char **l = NULL; + const char *e; + int r; + + assert(def); + assert(envvar); + + e = getenv(envvar); + if (e) { + r = path_split_and_make_absolute(e, &l); + if (r < 0) + return log_error_errno(r, "Failed to make $%s search path absolute: %m", envvar); + } + + if (strv_isempty(l)) { + strv_free(l); + + l = strv_new(def); + if (!l) + return log_oom(); + } + + if (!path_strv_resolve_uniq(l, NULL)) + return log_oom(); + + *ret = TAKE_PTR(l); + + return 0; +} + +static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) { + _cleanup_strv_free_ char **sysvinit_path = NULL; + char **path; + int r; + + assert(lp); + + r = acquire_search_path(SYSTEM_SYSVINIT_PATH, "SYSTEMD_SYSVINIT_PATH", &sysvinit_path); + if (r < 0) + return r; + + STRV_FOREACH(path, sysvinit_path) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + + d = opendir(*path); + if (!d) { + if (errno != ENOENT) + log_warning_errno(errno, "Opening %s failed, ignoring: %m", *path); + continue; + } + + FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", *path)) { + _cleanup_free_ char *fpath = NULL, *name = NULL; + _cleanup_(free_sysvstubp) SysvStub *service = NULL; + struct stat st; + + if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) { + log_warning_errno(errno, "stat() failed on %s/%s, ignoring: %m", *path, de->d_name); + continue; + } + + if (!(st.st_mode & S_IXUSR)) + continue; + + if (!S_ISREG(st.st_mode)) + continue; + + name = sysv_translate_name(de->d_name); + if (!name) + return log_oom(); + + if (hashmap_contains(all_services, name)) + continue; + + r = unit_file_exists(UNIT_FILE_SYSTEM, lp, name); + if (r < 0 && !IN_SET(r, -ELOOP, -ERFKILL, -EADDRNOTAVAIL)) { + log_debug_errno(r, "Failed to detect whether %s exists, skipping: %m", name); + continue; + } else if (r != 0) { + log_debug("Native unit for %s already exists, skipping.", name); + continue; + } + + fpath = path_join(*path, de->d_name); + if (!fpath) + return log_oom(); + + service = new0(SysvStub, 1); + if (!service) + return log_oom(); + + service->sysv_start_priority = -1; + service->name = TAKE_PTR(name); + service->path = TAKE_PTR(fpath); + + r = hashmap_put(all_services, service->name, service); + if (r < 0) + return log_oom(); + + service = NULL; + } + } + + return 0; +} + +static int set_dependencies_from_rcnd(const LookupPaths *lp, Hashmap *all_services) { + Set *runlevel_services[ELEMENTSOF(rcnd_table)] = {}; + _cleanup_strv_free_ char **sysvrcnd_path = NULL; + SysvStub *service; + unsigned i; + Iterator j; + char **p; + int r; + + assert(lp); + + r = acquire_search_path(SYSTEM_SYSVRCND_PATH, "SYSTEMD_SYSVRCND_PATH", &sysvrcnd_path); + if (r < 0) + return r; + + STRV_FOREACH(p, sysvrcnd_path) { + for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) { + + _cleanup_closedir_ DIR *d = NULL; + _cleanup_free_ char *path = NULL; + struct dirent *de; + + path = path_join(*p, rcnd_table[i].path); + if (!path) { + r = log_oom(); + goto finish; + } + + d = opendir(path); + if (!d) { + if (errno != ENOENT) + log_warning_errno(errno, "Opening %s failed, ignoring: %m", path); + + continue; + } + + FOREACH_DIRENT(de, d, log_error_errno(errno, "Failed to enumerate directory %s, ignoring: %m", path)) { + _cleanup_free_ char *name = NULL, *fpath = NULL; + int a, b; + + if (de->d_name[0] != 'S') + continue; + + if (strlen(de->d_name) < 4) + continue; + + a = undecchar(de->d_name[1]); + b = undecchar(de->d_name[2]); + + if (a < 0 || b < 0) + continue; + + fpath = path_join(*p, de->d_name); + if (!fpath) { + r = log_oom(); + goto finish; + } + + name = sysv_translate_name(de->d_name + 3); + if (!name) { + r = log_oom(); + goto finish; + } + + service = hashmap_get(all_services, name); + if (!service) { + log_debug("Ignoring %s symlink in %s, not generating %s.", de->d_name, rcnd_table[i].path, name); + continue; + } + + service->sysv_start_priority = MAX(a*10 + b, service->sysv_start_priority); + + r = set_ensure_allocated(&runlevel_services[i], NULL); + if (r < 0) { + log_oom(); + goto finish; + } + + r = set_put(runlevel_services[i], service); + if (r < 0) { + log_oom(); + goto finish; + } + } + } + } + + for (i = 0; i < ELEMENTSOF(rcnd_table); i ++) + SET_FOREACH(service, runlevel_services[i], j) { + r = strv_extend(&service->before, rcnd_table[i].target); + if (r < 0) { + log_oom(); + goto finish; + } + r = strv_extend(&service->wanted_by, rcnd_table[i].target); + if (r < 0) { + log_oom(); + goto finish; + } + } + + r = 0; + +finish: + for (i = 0; i < ELEMENTSOF(rcnd_table); i++) + set_free(runlevel_services[i]); + + return r; +} + +static int run(const char *dest, const char *dest_early, const char *dest_late) { + _cleanup_(free_sysvstub_hashmapp) Hashmap *all_services = NULL; + _cleanup_(lookup_paths_free) LookupPaths lp = {}; + SysvStub *service; + Iterator j; + int r; + + assert_se(arg_dest = dest_late); + + r = lookup_paths_init(&lp, UNIT_FILE_SYSTEM, LOOKUP_PATHS_EXCLUDE_GENERATED, NULL); + if (r < 0) + return log_error_errno(r, "Failed to find lookup paths: %m"); + + all_services = hashmap_new(&string_hash_ops); + if (!all_services) + return log_oom(); + + r = enumerate_sysv(&lp, all_services); + if (r < 0) + return r; + + r = set_dependencies_from_rcnd(&lp, all_services); + if (r < 0) + return r; + + HASHMAP_FOREACH(service, all_services, j) + (void) load_sysv(service); + + HASHMAP_FOREACH(service, all_services, j) { + (void) fix_order(service, all_services); + (void) generate_unit_file(service); + } + + return 0; +} + +DEFINE_MAIN_GENERATOR_FUNCTION(run); diff --git a/src/test/generate-sym-test.py b/src/test/generate-sym-test.py new file mode 100755 index 00000000..4d358b8e --- /dev/null +++ b/src/test/generate-sym-test.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import sys, re + +print('#include ') +for header in sys.argv[2:]: + print('#include "{}"'.format(header.split('/')[-1])) + +print(''' +const void* symbols[] = {''') + +for line in open(sys.argv[1]): + match = re.search('^ +([a-zA-Z0-9_]+);', line) + if match: + s = match.group(1) + if s == 'sd_bus_object_vtable_format': + print(' &{},'.format(s)) + else: + print(' {},'.format(s)) + +print('''}; + +int main(void) { + unsigned i; + for (i = 0; i < sizeof(symbols)/sizeof(void*); i++) + printf("%p\\n", symbols[i]); + return 0; +}''') diff --git a/src/test/meson.build b/src/test/meson.build new file mode 100644 index 00000000..dd844f02 --- /dev/null +++ b/src/test/meson.build @@ -0,0 +1,1131 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +awkscript = 'test-hashmap-ordered.awk' +test_hashmap_ordered_c = custom_target( + 'test-hashmap-ordered.c', + input : [awkscript, 'test-hashmap-plain.c'], + output : 'test-hashmap-ordered.c', + command : [awk, '-f', '@INPUT0@', '@INPUT1@'], + capture : true, + build_by_default : want_tests != 'false') + +test_include_dir = include_directories('.') + +path = run_command('sh', ['-c', 'echo "$PATH"']).stdout().strip() +test_env = environment() +test_env.set('SYSTEMD_KBD_MODEL_MAP', kbd_model_map) +test_env.set('SYSTEMD_LANGUAGE_FALLBACK_MAP', language_fallback_map) +test_env.set('PATH', '@0@:@1@'.format(meson.build_root(), path)) + +############################################################ + +generate_sym_test_py = find_program('generate-sym-test.py') + +test_libsystemd_sym_c = custom_target( + 'test-libsystemd-sym.c', + input : [libsystemd_sym_path] + systemd_headers, + output : 'test-libsystemd-sym.c', + command : [generate_sym_test_py, libsystemd_sym_path] + systemd_headers, + capture : true, + build_by_default : want_tests != 'false') + +test_libudev_sym_c = custom_target( + 'test-libudev-sym.c', + input : [libudev_sym_path, libudev_h_path], + output : 'test-libudev-sym.c', + command : [generate_sym_test_py, '@INPUT0@', '@INPUT1@'], + capture : true, + build_by_default : want_tests != 'false') + +test_dlopen_c = files('test-dlopen.c') + +############################################################ + +test_systemd_tmpfiles_py = find_program('test-systemd-tmpfiles.py') + +############################################################ + +tests += [ + [['src/test/test-device-nodes.c'], + [], + []], + + [['src/test/test-engine.c'], + [libcore, + libudev, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid]], + + [['src/test/test-emergency-action.c'], + [libcore, + libshared], + []], + + [['src/test/test-chown-rec.c'], + [libcore, + libshared], + []], + + [['src/test/test-job-type.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid]], + + [['src/test/test-ns.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid], + '', 'manual'], + + [['src/test/test-nscd-flush.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid], + '', 'manual'], + + [['src/test/test-loopback.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid]], + + [['src/test/test-hostname.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid], + '', 'unsafe'], + + [['src/test/test-dns-domain.c'], + [libcore, + libshared, + libsystemd_network], + []], + + [['src/test/test-boot-timestamps.c'], + [], + [], + 'ENABLE_EFI'], + + [['src/test/test-unit-file.c'], + [], + []], + + [['src/test/test-unit-name.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid]], + + [['src/test/test-load-fragment.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid]], + + [['src/test/test-serialize.c'], + [], + []], + + [['src/test/test-utf8.c'], + [], + []], + + [['src/test/test-dev-setup.c'], + [], + []], + + [['src/test/test-capability.c'], + [], + [libcap]], + + [['src/test/test-async.c'], + [], + [], + '', 'timeout=120'], + + [['src/test/test-locale-util.c'], + [], + []], + + [['src/test/test-copy.c'], + [], + []], + + [['src/test/test-static-destruct.c'], + [], + []], + + [['src/test/test-sigbus.c'], + [], + []], + + [['src/test/test-condition.c'], + [], + []], + + [['src/test/test-fdset.c'], + [], + []], + + [['src/test/test-fstab-util.c'], + [], + []], + + [['src/test/test-random-util.c'], + [], + []], + + [['src/test/test-format-table.c'], + [], + []], + + [['src/test/test-format-util.c'], + [], + []], + + [['src/test/test-ratelimit.c'], + [], + []], + + [['src/test/test-util.c'], + [], + []], + + [['src/test/test-json.c'], + [], + []], + + [['src/test/test-libmount.c'], + [], + [threads, + libmount]], + + [['src/test/test-mount-util.c'], + [], + []], + + [['src/test/test-mountpoint-util.c'], + [], + []], + + [['src/test/test-exec-util.c'], + [], + []], + + [['src/test/test-hexdecoct.c'], + [], + []], + + [['src/test/test-alloc-util.c'], + [], + []], + + [['src/test/test-xattr-util.c'], + [], + []], + + [['src/test/test-io-util.c'], + [], + []], + + [['src/test/test-glob-util.c'], + [], + []], + + [['src/test/test-fs-util.c'], + [], + []], + + [['src/test/test-umask-util.c'], + [], + []], + + [['src/test/test-proc-cmdline.c'], + [], + []], + + [['src/test/test-fd-util.c'], + [], + []], + + [['src/test/test-web-util.c'], + [], + []], + + [['src/test/test-cpu-set-util.c'], + [], + []], + + [['src/test/test-stat-util.c'], + [], + []], + + [['src/test/test-os-util.c'], + [], + []], + + [['src/test/test-escape.c'], + [], + []], + + [['src/test/test-exit-status.c'], + [], + []], + + [['src/test/test-specifier.c'], + [], + []], + + [['src/test/test-string-util.c'], + [], + []], + + [['src/test/test-extract-word.c'], + [], + []], + + [['src/test/test-parse-util.c'], + [], + []], + + [['src/test/test-sysctl-util.c'], + [], + []], + + [['src/test/test-user-util.c'], + [], + []], + + [['src/test/test-hostname-util.c'], + [], + []], + + [['src/test/test-process-util.c'], + [], + []], + + [['src/test/test-terminal-util.c'], + [], + []], + + [['src/test/test-path-lookup.c'], + [], + []], + + [['src/test/test-pretty-print.c'], + [], + []], + + [['src/test/test-uid-range.c'], + [], + []], + + [['src/test/test-cap-list.c', + generated_gperf_headers], + [], + [libcap]], + + [['src/test/test-socket-util.c'], + [], + []], + + [['src/test/test-in-addr-util.c'], + [], + []], + + [['src/test/test-barrier.c'], + [], + []], + + [['src/test/test-tmpfiles.c'], + [], + []], + + [['src/test/test-namespace.c'], + [libcore, + libshared], + [threads, + libblkid]], + + [['src/test/test-verbs.c'], + [], + []], + + [['src/test/test-install-root.c'], + [], + []], + + [['src/test/test-acl-util.c'], + [], + [], + 'HAVE_ACL'], + + [['src/test/test-seccomp.c'], + [], + [libseccomp], + 'HAVE_SECCOMP'], + + [['src/test/test-rlimit-util.c'], + [], + []], + + [['src/test/test-ask-password-api.c'], + [], + [], + '', 'manual'], + + [['src/test/test-dissect-image.c'], + [], + [libblkid], + '', 'manual'], + + [['src/test/test-signal-util.c'], + [], + []], + + [['src/test/test-selinux.c'], + [], + []], + + [['src/test/test-sizeof.c'], + [libbasic], + []], + + [['src/test/test-bpf-devices.c'], + [libcore, + libshared], + [libmount, + threads, + librt, + libseccomp, + libselinux, + libblkid]], + + [['src/test/test-bpf-firewall.c'], + [libcore, + libshared], + [libmount, + threads, + librt, + libseccomp, + libselinux, + libblkid]], + + [['src/test/test-watch-pid.c'], + [libcore, + libshared], + [libmount, + threads, + librt, + libseccomp, + libselinux, + libblkid]], + + [['src/test/test-hashmap.c', + 'src/test/test-hashmap-plain.c', + test_hashmap_ordered_c], + [], + [], + '', 'timeout=90'], + + [['src/test/test-set.c'], + [], + []], + + [['src/test/test-ordered-set.c'], + [], + []], + + [['src/test/test-set-disable-mempool.c'], + [], + [threads]], + + [['src/test/test-bitmap.c'], + [], + []], + + [['src/test/test-xml.c'], + [], + []], + + [['src/test/test-list.c'], + [], + []], + + [['src/test/test-procfs-util.c'], + [], + []], + + [['src/test/test-unaligned.c'], + [], + []], + + [['src/test/test-tables.c', + 'src/shared/test-tables.h', + 'src/journal/journald-server.c', + 'src/journal/journald-server.h'], + [libcore, + libjournal_core, + libudev_core, + libudev_static, + libsystemd_network, + libshared], + [threads, + libseccomp, + libmount, + libxz, + liblz4, + libblkid], + '', '', [], libudev_core_includes], + + [['src/test/test-prioq.c'], + [], + []], + + [['src/test/test-fileio.c'], + [], + []], + + [['src/test/test-time-util.c'], + [], + []], + + [['src/test/test-clock.c'], + [], + []], + + [['src/test/test-architecture.c'], + [], + []], + + [['src/test/test-log.c'], + [], + []], + + [['src/test/test-ipcrm.c'], + [], + [], + '', 'unsafe'], + + [['src/test/test-btrfs.c'], + [], + [], + '', 'manual'], + + + [['src/test/test-firewall-util.c'], + [libshared], + [], + 'HAVE_LIBIPTC'], + + [['src/test/test-netlink-manual.c'], + [], + [libkmod], + 'HAVE_KMOD', 'manual'], + + [['src/test/test-ellipsize.c'], + [], + []], + + [['src/test/test-date.c'], + [], + []], + + [['src/test/test-sleep.c'], + [], + []], + + [['src/test/test-replace-var.c'], + [], + []], + + [['src/test/test-calendarspec.c'], + [], + []], + + [['src/test/test-strip-tab-ansi.c'], + [], + []], + + [['src/test/test-daemon.c'], + [], + []], + + [['src/test/test-cgroup.c'], + [], + [], + '', 'manual'], + + [['src/test/test-cgroup-cpu.c'], + [libcore, + libshared], + []], + + [['src/test/test-cgroup-unit-default.c'], + [libcore, + libshared], + []], + + [['src/test/test-cgroup-mask.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid]], + + [['src/test/test-varlink.c'], + [], + [threads]], + + [['src/test/test-cgroup-util.c'], + [], + []], + + [['src/test/test-cgroup-setup.c'], + [], + []], + + [['src/test/test-env-file.c'], + [], + []], + + [['src/test/test-env-util.c'], + [], + []], + + [['src/test/test-strbuf.c'], + [], + []], + + [['src/test/test-strv.c'], + [], + []], + + [['src/test/test-path-util.c'], + [], + []], + + [['src/test/test-chase-symlinks.c'], + [], + [], + '', 'manual'], + + [['src/test/test-path.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid]], + + [['src/test/test-execute.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid], + '', 'timeout=360'], + + [['src/test/test-siphash24.c'], + [], + []], + + [['src/test/test-strxcpyx.c'], + [], + []], + + [['src/test/test-install.c'], + [libcore, + libshared], + [], + '', 'manual'], + + [['src/test/test-watchdog.c'], + [], + []], + + [['src/test/test-sched-prio.c'], + [libcore, + libshared], + [threads, + librt, + libseccomp, + libselinux, + libmount, + libblkid]], + + [['src/test/test-conf-files.c'], + [], + []], + + [['src/test/test-conf-parser.c'], + [], + []], + + [['src/test/test-af-list.c', + generated_gperf_headers], + [], + []], + + [['src/test/test-arphrd-list.c', + generated_gperf_headers], + [], + []], + + [['src/test/test-ip-protocol-list.c', + shared_generated_gperf_headers], + [], + []], + + [['src/test/test-journal-importer.c'], + [], + []], + + [['src/test/test-libudev.c'], + [libshared], + []], + + [['src/test/test-udev.c'], + [libudev_core, + libudev_static, + libsystemd_network, + libshared], + [threads, + librt, + libblkid, + libkmod, + libacl], + '', 'manual', '-DLOG_REALM=LOG_REALM_UDEV'], + + [['src/test/test-id128.c'], + [], + []], + + [['src/test/test-hash.c'], + [], + []], + + [['src/test/test-gcrypt-util.c'], + [], + [], + 'HAVE_GCRYPT'], + + [['src/test/test-nss.c'], + [], + [libdl], + 'ENABLE_NSS', 'manual'], + + [['src/test/test-umount.c', + 'src/shutdown/umount.c', + 'src/shutdown/umount.h'], + [libcore_shared, + libshared], + [libmount]], + + [['src/test/test-bus-util.c'], + [], + []], + + [['src/test/test-sd-hwdb.c'], + [], + []], + + [['src/test/test-local-addresses.c'], + [], + []], +] + +############################################################ + +# define some tests here, because the link_with deps were not defined earlier + +tests += [ + [['src/journal/test-journal.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4]], + + [['src/journal/test-journal-send.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4]], + + [['src/journal/test-journal-syslog.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4, + libselinux]], + + [['src/journal/test-journal-match.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4]], + + [['src/journal/test-journal-enum.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4], + '', 'timeout=360'], + + [['src/journal/test-journal-stream.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4]], + + [['src/journal/test-journal-flush.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4]], + + [['src/journal/test-journal-init.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4]], + + [['src/journal/test-journal-config.c'], + [libjournal_core, + libshared], + [libxz, + liblz4, + libselinux]], + + [['src/journal/test-journal-verify.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4]], + + [['src/journal/test-journal-interleaving.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4]], + + [['src/journal/test-mmap-cache.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4]], + + [['src/journal/test-catalog.c'], + [libjournal_core, + libshared], + [threads, + libxz, + liblz4]], + + [['src/journal/test-compress.c'], + [libjournal_core, + libshared], + [liblz4, + libxz]], + + [['src/journal/test-compress-benchmark.c'], + [libjournal_core, + libshared], + [liblz4, + libxz], + '', 'timeout=90'], + + [['src/journal/test-audit-type.c'], + [libjournal_core, + libshared], + [liblz4, + libxz]], +] + +############################################################ + +tests += [ + [['src/libsystemd/sd-bus/test-bus-address.c'], + [], + [threads]], + + [['src/libsystemd/sd-bus/test-bus-marshal.c'], + [], + [threads, + libglib, + libgobject, + libgio, + libdbus]], + + [['src/libsystemd/sd-bus/test-bus-signature.c'], + [], + [threads]], + + [['src/libsystemd/sd-bus/test-bus-queue-ref-cycle.c'], + [], + [threads]], + + [['src/libsystemd/sd-bus/test-bus-watch-bind.c'], + [], + [threads], '', 'timeout=120'], + + [['src/libsystemd/sd-bus/test-bus-chat.c'], + [], + [threads]], + + [['src/libsystemd/sd-bus/test-bus-cleanup.c'], + [], + [threads, + libseccomp]], + + [['src/libsystemd/sd-bus/test-bus-error.c'], + [libshared_static, + libsystemd_static], + []], + + [['src/libsystemd/sd-bus/test-bus-track.c'], + [], + [libseccomp]], + + [['src/libsystemd/sd-bus/test-bus-server.c'], + [], + [threads]], + + [['src/libsystemd/sd-bus/test-bus-objects.c'], + [], + [threads]], + + [['src/libsystemd/sd-bus/test-bus-vtable.c', + 'src/libsystemd/sd-bus/test-vtable-data.h'], + [], + []], + + [['src/libsystemd/sd-bus/test-bus-gvariant.c'], + [], + [libglib, + libgobject, + libgio]], + + [['src/libsystemd/sd-bus/test-bus-creds.c'], + [], + []], + + [['src/libsystemd/sd-bus/test-bus-match.c'], + [], + []], + + [['src/libsystemd/sd-bus/test-bus-benchmark.c'], + [], + [threads], + '', 'manual'], + + [['src/libsystemd/sd-bus/test-bus-introspect.c', + 'src/libsystemd/sd-bus/test-vtable-data.h'], + [], + []], + + [['src/libsystemd/sd-event/test-event.c'], + [], + []], + + [['src/libsystemd/sd-netlink/test-netlink.c'], + [], + []], + + [['src/libsystemd/sd-resolve/test-resolve.c'], + [], + [threads], + '', 'timeout=120'], + + [['src/libsystemd/sd-login/test-login.c'], + [], + []], + + [['src/libsystemd/sd-device/test-sd-device.c'], + [], + []], + + [['src/libsystemd/sd-device/test-sd-device-thread.c'], + [libbasic, + libshared_static, + libsystemd], + [threads]], + + [['src/libsystemd/sd-device/test-udev-device-thread.c'], + [libbasic, + libshared_static, + libudev], + [threads]], + + [['src/libsystemd/sd-device/test-sd-device-monitor.c'], + [], + []], + +] + +# test-bus-vtable-cc.cc is a symlink and symlinks get lost in containers on FuzzBuzz. +# The issue has been reported to the developers of FuzzBuzz and hopefully will be fixed soon. +# In the meantime, let's just skip the symlink there. +if cxx_cmd != '' and not want_fuzzbuzz + tests += [ + [['src/libsystemd/sd-bus/test-bus-vtable-cc.cc'], + [], + []] + ] +endif + +############################################################ + +tests += [ + [['src/libsystemd-network/test-dhcp-option.c', + 'src/libsystemd-network/dhcp-protocol.h', + 'src/libsystemd-network/dhcp-internal.h'], + [libshared, + libsystemd_network], + []], + + [['src/libsystemd-network/test-sd-dhcp-lease.c', + 'src/libsystemd-network/dhcp-lease-internal.h'], + [libshared, + libsystemd_network], + []], + + [['src/libsystemd-network/test-dhcp-client.c', + 'src/libsystemd-network/dhcp-protocol.h', + 'src/libsystemd-network/dhcp-internal.h', + 'src/systemd/sd-dhcp-client.h'], + [libshared, + libsystemd_network], + []], + + [['src/libsystemd-network/test-dhcp-server.c'], + [libshared, + libsystemd_network], + []], + + [['src/libsystemd-network/test-ipv4ll.c', + 'src/libsystemd-network/arp-util.h', + 'src/systemd/sd-ipv4ll.h'], + [libshared, + libsystemd_network], + []], + + [['src/libsystemd-network/test-ipv4ll-manual.c', + 'src/systemd/sd-ipv4ll.h'], + [libshared, + libsystemd_network], + [], + '', 'manual'], + + [['src/libsystemd-network/test-acd.c', + 'src/systemd/sd-ipv4acd.h'], + [libshared, + libsystemd_network], + [], + '', 'manual'], + + [['src/libsystemd-network/test-ndisc-rs.c', + 'src/libsystemd-network/dhcp-identifier.h', + 'src/libsystemd-network/dhcp-identifier.c', + 'src/libsystemd-network/icmp6-util.h', + 'src/systemd/sd-dhcp6-client.h', + 'src/systemd/sd-ndisc.h'], + [libshared, + libsystemd_network], + []], + + [['src/libsystemd-network/test-ndisc-ra.c', + 'src/libsystemd-network/icmp6-util.h', + 'src/systemd/sd-ndisc.h'], + [libshared, + libsystemd_network], + []], + + [['src/libsystemd-network/test-dhcp6-client.c', + 'src/libsystemd-network/dhcp-identifier.h', + 'src/libsystemd-network/dhcp-identifier.c', + 'src/libsystemd-network/dhcp6-internal.h', + 'src/systemd/sd-dhcp6-client.h'], + [libshared, + libsystemd_network], + []], + + [['src/libsystemd-network/test-lldp.c'], + [libshared, + libsystemd_network], + []], +] + +############################################################ + +tests += [ + [['src/login/test-login-shared.c'], + [], + []], + + [['src/login/test-inhibit.c'], + [], + [], + '', 'manual'], + + [['src/login/test-login-tables.c'], + [liblogind_core, + libshared], + [threads]], +] diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c new file mode 100644 index 00000000..df879747 --- /dev/null +++ b/src/test/test-acl-util.c @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "acl-util.h" +#include "fd-util.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "user-util.h" + +static void test_add_acls_for_user(void) { + char fn[] = "/tmp/test-empty.XXXXXX"; + _cleanup_close_ int fd = -1; + char *cmd; + uid_t uid; + int r; + + fd = mkostemp_safe(fn); + assert_se(fd >= 0); + + /* Use the mode that user journal files use */ + assert_se(fchmod(fd, 0640) == 0); + + cmd = strjoina("ls -l ", fn); + assert_se(system(cmd) == 0); + + cmd = strjoina("getfacl -p ", fn); + assert_se(system(cmd) == 0); + + if (getuid() == 0) { + const char *nobody = NOBODY_USER_NAME; + r = get_user_creds(&nobody, &uid, NULL, NULL, NULL, 0); + if (r < 0) + uid = 0; + } else + uid = getuid(); + + r = add_acls_for_user(fd, uid); + assert_se(r >= 0); + + cmd = strjoina("ls -l ", fn); + assert_se(system(cmd) == 0); + + cmd = strjoina("getfacl -p ", fn); + assert_se(system(cmd) == 0); + + /* set the acls again */ + + r = add_acls_for_user(fd, uid); + assert_se(r >= 0); + + cmd = strjoina("ls -l ", fn); + assert_se(system(cmd) == 0); + + cmd = strjoina("getfacl -p ", fn); + assert_se(system(cmd) == 0); + + unlink(fn); +} + +int main(int argc, char **argv) { + test_add_acls_for_user(); + + return 0; +} diff --git a/src/test/test-af-list.c b/src/test/test-af-list.c new file mode 100644 index 00000000..884372e6 --- /dev/null +++ b/src/test/test-af-list.c @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "macro.h" +#include "string-util.h" +#include "util.h" + +_unused_ +static const struct af_name* lookup_af(register const char *str, register GPERF_LEN_TYPE len); + +#include "af-from-name.h" +#include "af-list.h" +#include "af-to-name.h" + +int main(int argc, const char *argv[]) { + + unsigned i; + + for (i = 0; i < ELEMENTSOF(af_names); i++) { + if (af_names[i]) { + assert_se(streq(af_to_name(i), af_names[i])); + assert_se(af_from_name(af_names[i]) == (int) i); + } + } + + assert_se(af_to_name(af_max()) == NULL); + assert_se(af_to_name(-1) == NULL); + assert_se(af_from_name("huddlduddl") == -EINVAL); + assert_se(af_from_name("") == -EINVAL); + + return 0; +} diff --git a/src/test/test-alloc-util.c b/src/test/test-alloc-util.c new file mode 100644 index 00000000..758b7532 --- /dev/null +++ b/src/test/test-alloc-util.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "macro.h" +#include "memory-util.h" +#include "random-util.h" +#include "tests.h" + +static void test_alloca(void) { + static const uint8_t zero[997] = { }; + char *t; + + t = alloca_align(17, 512); + assert_se(!((uintptr_t)t & 0xff)); + memzero(t, 17); + + t = alloca0_align(997, 1024); + assert_se(!((uintptr_t)t & 0x1ff)); + assert_se(!memcmp(t, zero, 997)); +} + +static void test_GREEDY_REALLOC(void) { + _cleanup_free_ int *a = NULL, *b = NULL; + size_t n_allocated = 0, i, j; + + /* Give valgrind a chance to verify our realloc() operations */ + + for (i = 0; i < 20480; i++) { + assert_se(GREEDY_REALLOC(a, n_allocated, i + 1)); + assert_se(n_allocated >= i + 1); + assert_se(malloc_usable_size(a) >= (i + 1) * sizeof(int)); + a[i] = (int) i; + assert_se(GREEDY_REALLOC(a, n_allocated, i / 2)); + assert_se(n_allocated >= i / 2); + assert_se(malloc_usable_size(a) >= (i / 2) * sizeof(int)); + } + + for (j = 0; j < i / 2; j++) + assert_se(a[j] == (int) j); + + for (i = 30, n_allocated = 0; i < 20480; i += 7) { + assert_se(GREEDY_REALLOC(b, n_allocated, i + 1)); + assert_se(n_allocated >= i + 1); + assert_se(malloc_usable_size(b) >= (i + 1) * sizeof(int)); + b[i] = (int) i; + assert_se(GREEDY_REALLOC(b, n_allocated, i / 2)); + assert_se(n_allocated >= i / 2); + assert_se(malloc_usable_size(b) >= (i / 2) * sizeof(int)); + } + + for (j = 30; j < i / 2; j += 7) + assert_se(b[j] == (int) j); +} + +static void test_memdup_multiply_and_greedy_realloc(void) { + static const int org[] = { 1, 2, 3 }; + _cleanup_free_ int *dup; + int *p; + size_t i, allocated = 3; + + dup = memdup_suffix0_multiply(org, sizeof(int), 3); + assert_se(dup); + assert_se(dup[0] == 1); + assert_se(dup[1] == 2); + assert_se(dup[2] == 3); + assert_se(((uint8_t*) dup)[sizeof(int) * 3] == 0); + free(dup); + + dup = memdup_multiply(org, sizeof(int), 3); + assert_se(dup); + assert_se(dup[0] == 1); + assert_se(dup[1] == 2); + assert_se(dup[2] == 3); + + p = dup; + assert_se(greedy_realloc0((void**) &dup, &allocated, 2, sizeof(int)) == p); + + p = (int *) greedy_realloc0((void**) &dup, &allocated, 10, sizeof(int)); + assert_se(p == dup); + assert_se(allocated >= 10); + assert_se(p[0] == 1); + assert_se(p[1] == 2); + assert_se(p[2] == 3); + for (i = 3; i < allocated; i++) + assert_se(p[i] == 0); +} + +static void test_bool_assign(void) { + bool b, c, *cp = &c, d, e, f, g, h; + + b = 123; + *cp = -11; + d = 0xF & 0xFF; + e = b & d; + f = 0x0; + g = cp; /* cast from pointer */ + h = NULL; /* cast from pointer */ + + assert(b); + assert(c); + assert(d); + assert(e); + assert(!f); + assert(g); + assert(!h); +} + +static int cleanup_counter = 0; + +static void cleanup1(void *a) { + log_info("%s(%p)", __func__, a); + assert_se(++cleanup_counter == *(int*) a); +} +static void cleanup2(void *a) { + log_info("%s(%p)", __func__, a); + assert_se(++cleanup_counter == *(int*) a); +} +static void cleanup3(void *a) { + log_info("%s(%p)", __func__, a); + assert_se(++cleanup_counter == *(int*) a); +} + +static void test_cleanup_order(void) { + _cleanup_(cleanup1) int x1 = 4, x2 = 3; + _cleanup_(cleanup3) int z = 2; + _cleanup_(cleanup2) int y = 1; + log_debug("x1: %p", &x1); + log_debug("x2: %p", &x2); + log_debug("y: %p", &y); + log_debug("z: %p", &z); +} + +static void test_auto_erase_memory(void) { + _cleanup_(erase_and_freep) uint8_t *p1, *p2; + + assert_se(p1 = new(uint8_t, 1024)); + assert_se(p2 = new(uint8_t, 1024)); + + assert_se(genuine_random_bytes(p1, 1024, RANDOM_BLOCK) == 0); + + /* before we exit the scope, do something with this data, so that the compiler won't optimize this away */ + memcpy(p2, p1, 1024); + for (size_t i = 0; i < 1024; i++) + assert_se(p1[i] == p2[i]); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_alloca(); + test_GREEDY_REALLOC(); + test_memdup_multiply_and_greedy_realloc(); + test_bool_assign(); + test_cleanup_order(); + test_auto_erase_memory(); + + return 0; +} diff --git a/src/test/test-architecture.c b/src/test/test-architecture.c new file mode 100644 index 00000000..8c43bfc7 --- /dev/null +++ b/src/test/test-architecture.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "architecture.h" +#include "log.h" +#include "tests.h" +#include "util.h" +#include "virt.h" + +int main(int argc, char *argv[]) { + int a, v; + const char *p; + + test_setup_logging(LOG_INFO); + + assert_se(architecture_from_string("") < 0); + assert_se(architecture_from_string(NULL) < 0); + assert_se(architecture_from_string("hoge") < 0); + assert_se(architecture_to_string(-1) == NULL); + assert_se(architecture_from_string(architecture_to_string(0)) == 0); + assert_se(architecture_from_string(architecture_to_string(1)) == 1); + + v = detect_virtualization(); + if (IN_SET(v, -EPERM, -EACCES)) + return log_tests_skipped("Cannot detect virtualization"); + + assert_se(v >= 0); + + log_info("virtualization=%s id=%s", + VIRTUALIZATION_IS_CONTAINER(v) ? "container" : + VIRTUALIZATION_IS_VM(v) ? "vm" : "n/a", + virtualization_to_string(v)); + + a = uname_architecture(); + assert_se(a >= 0); + + p = architecture_to_string(a); + assert_se(p); + log_info("uname architecture=%s", p); + assert_se(architecture_from_string(p) == a); + + a = native_architecture(); + assert_se(a >= 0); + + p = architecture_to_string(a); + assert_se(p); + log_info("native architecture=%s", p); + assert_se(architecture_from_string(p) == a); + + log_info("primary library architecture=" LIB_ARCH_TUPLE); + + return 0; +} diff --git a/src/test/test-arphrd-list.c b/src/test/test-arphrd-list.c new file mode 100644 index 00000000..d7352b54 --- /dev/null +++ b/src/test/test-arphrd-list.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "string-util.h" +#include "tests.h" + +#include "arphrd-list.h" + +int main(int argc, const char *argv[]) { + test_setup_logging(LOG_INFO); + + for (int i = 0; i <= ARPHRD_VOID + 1; i++) { + const char *name; + + name = arphrd_to_name(i); + if (name) { + log_info("%i: %s", i, name); + + assert_se(arphrd_from_name(name) == i); + } + } + + assert_se(arphrd_to_name(ARPHRD_VOID + 1) == NULL); + assert_se(arphrd_from_name("huddlduddl") == -EINVAL); + assert_se(arphrd_from_name("") == -EINVAL); + + return 0; +} diff --git a/src/test/test-ask-password-api.c b/src/test/test-ask-password-api.c new file mode 100644 index 00000000..fa91869c --- /dev/null +++ b/src/test/test-ask-password-api.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "ask-password-api.h" +#include "log.h" +#include "strv.h" + +static void ask_password(void) { + int r; + _cleanup_strv_free_ char **ret = NULL; + + r = ask_password_tty(-1, "hello?", "da key", 0, 0, NULL, &ret); + assert(r >= 0); + assert(strv_length(ret) == 1); + + log_info("Got %s", *ret); +} + +int main(int argc, char **argv) { + log_parse_environment(); + + ask_password(); + return EXIT_SUCCESS; +} diff --git a/src/test/test-async.c b/src/test/test-async.c new file mode 100644 index 00000000..7d8accc2 --- /dev/null +++ b/src/test/test-async.c @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "async.h" +#include "macro.h" +#include "tmpfile-util.h" +#include "util.h" + +static bool test_async = false; + +static void *async_func(void *arg) { + test_async = true; + + return NULL; +} + +int main(int argc, char *argv[]) { + int fd; + char name[] = "/tmp/test-asynchronous_close.XXXXXX"; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + asynchronous_close(fd); + + assert_se(asynchronous_job(async_func, NULL) >= 0); + + assert_se(asynchronous_sync(NULL) >= 0); + + sleep(1); + + assert_se(fcntl(fd, F_GETFD) == -1); + assert_se(test_async); + + (void) unlink(name); + + return 0; +} diff --git a/src/test/test-barrier.c b/src/test/test-barrier.c new file mode 100644 index 00000000..10417f66 --- /dev/null +++ b/src/test/test-barrier.c @@ -0,0 +1,464 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +/* + * IPC barrier tests + * These tests verify the correct behavior of the IPC Barrier implementation. + * Note that the tests use alarm-timers to verify dead-locks and timeouts. These + * might not work on slow machines where 20ms are too short to perform specific + * operations (though, very unlikely). In case that turns out true, we have to + * increase it at the slightly cost of lengthen test-duration on other machines. + */ + +#include +#include +#include +#include + +#include "barrier.h" +#include "util.h" +#include "tests.h" +#include "virt.h" +#include "time-util.h" + +/* 20ms to test deadlocks; All timings use multiples of this constant as + * alarm/sleep timers. If this timeout is too small for slow machines to perform + * the requested operations, we have to increase it. On an i7 this works fine + * with 1ms base-time, so 20ms should be just fine for everyone. */ +#define BASE_TIME (20 * USEC_PER_MSEC) + +static void set_alarm(usec_t usecs) { + struct itimerval v = { }; + + timeval_store(&v.it_value, usecs); + assert_se(setitimer(ITIMER_REAL, &v, NULL) >= 0); +} + +static void sleep_for(usec_t usecs) { + /* stupid usleep() might fail if >1000000 */ + assert_se(usecs < USEC_PER_SEC); + usleep(usecs); +} + +#define TEST_BARRIER(_FUNCTION, _CHILD_CODE, _WAIT_CHILD, _PARENT_CODE, _WAIT_PARENT) \ + static void _FUNCTION(void) { \ + Barrier b = BARRIER_NULL; \ + pid_t pid1, pid2; \ + \ + assert_se(barrier_create(&b) >= 0); \ + assert_se(b.me > 0); \ + assert_se(b.them > 0); \ + assert_se(b.pipe[0] > 0); \ + assert_se(b.pipe[1] > 0); \ + \ + pid1 = fork(); \ + assert_se(pid1 >= 0); \ + if (pid1 == 0) { \ + barrier_set_role(&b, BARRIER_CHILD); \ + { _CHILD_CODE; } \ + exit(42); \ + } \ + \ + pid2 = fork(); \ + assert_se(pid2 >= 0); \ + if (pid2 == 0) { \ + barrier_set_role(&b, BARRIER_PARENT); \ + { _PARENT_CODE; } \ + exit(42); \ + } \ + \ + barrier_destroy(&b); \ + set_alarm(999999); \ + { _WAIT_CHILD; } \ + { _WAIT_PARENT; } \ + set_alarm(0); \ + } + +#define TEST_BARRIER_WAIT_SUCCESS(_pid) \ + ({ \ + int pidr, status; \ + pidr = waitpid(_pid, &status, 0); \ + assert_se(pidr == _pid); \ + assert_se(WIFEXITED(status)); \ + assert_se(WEXITSTATUS(status) == 42); \ + }) + +#define TEST_BARRIER_WAIT_ALARM(_pid) \ + ({ \ + int pidr, status; \ + pidr = waitpid(_pid, &status, 0); \ + assert_se(pidr == _pid); \ + assert_se(WIFSIGNALED(status)); \ + assert_se(WTERMSIG(status) == SIGALRM); \ + }) + +/* + * Test basic sync points + * This places a barrier in both processes and waits synchronously for them. + * The timeout makes sure the sync works as expected. The sleep_for() on one side + * makes sure the exit of the parent does not overwrite previous barriers. Due + * to the sleep_for(), we know that the parent already exited, thus there's a + * pending HUP on the pipe. However, the barrier_sync() prefers reads on the + * eventfd, thus we can safely wait on the barrier. + */ +TEST_BARRIER(test_barrier_sync, + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_place(&b)); + sleep_for(BASE_TIME * 2); + assert_se(barrier_sync(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_place(&b)); + assert_se(barrier_sync(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test wait_next() + * This places a barrier in the parent and syncs on it. The child sleeps while + * the parent places the barrier and then waits for a barrier. The wait will + * succeed as the child hasn't read the parent's barrier, yet. The following + * barrier and sync synchronize the exit. + */ +TEST_BARRIER(test_barrier_wait_next, + ({ + sleep_for(BASE_TIME); + set_alarm(BASE_TIME * 10); + assert_se(barrier_wait_next(&b)); + assert_se(barrier_place(&b)); + assert_se(barrier_sync(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + set_alarm(BASE_TIME * 4); + assert_se(barrier_place(&b)); + assert_se(barrier_sync(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test wait_next() multiple times + * This places two barriers in the parent and waits for the child to exit. The + * child sleeps 20ms so both barriers _should_ be in place. It then waits for + * the parent to place the next barrier twice. The first call will fetch both + * barriers and return. However, the second call will stall as the parent does + * not place a 3rd barrier (the sleep caught two barriers). wait_next() is does + * not look at barrier-links so this stall is expected. Thus this test times + * out. + */ +TEST_BARRIER(test_barrier_wait_next_twice, + ({ + sleep_for(BASE_TIME); + set_alarm(BASE_TIME); + assert_se(barrier_wait_next(&b)); + assert_se(barrier_wait_next(&b)); + assert_se(0); + }), + TEST_BARRIER_WAIT_ALARM(pid1), + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_place(&b)); + assert_se(barrier_place(&b)); + sleep_for(BASE_TIME * 4); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test wait_next() with local barriers + * This is the same as test_barrier_wait_next_twice, but places local barriers + * between both waits. This does not have any effect on the wait so it times out + * like the other test. + */ +TEST_BARRIER(test_barrier_wait_next_twice_local, + ({ + sleep_for(BASE_TIME); + set_alarm(BASE_TIME); + assert_se(barrier_wait_next(&b)); + assert_se(barrier_place(&b)); + assert_se(barrier_place(&b)); + assert_se(barrier_wait_next(&b)); + assert_se(0); + }), + TEST_BARRIER_WAIT_ALARM(pid1), + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_place(&b)); + assert_se(barrier_place(&b)); + sleep_for(BASE_TIME * 4); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test wait_next() with sync_next() + * This is again the same as test_barrier_wait_next_twice but uses a + * synced wait as the second wait. This works just fine because the local state + * has no barriers placed, therefore, the remote is always in sync. + */ +TEST_BARRIER(test_barrier_wait_next_twice_sync, + ({ + sleep_for(BASE_TIME); + set_alarm(BASE_TIME); + assert_se(barrier_wait_next(&b)); + assert_se(barrier_sync_next(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_place(&b)); + assert_se(barrier_place(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test wait_next() with sync_next() and local barriers + * This is again the same as test_barrier_wait_next_twice_local but uses a + * synced wait as the second wait. This works just fine because the local state + * is in sync with the remote. + */ +TEST_BARRIER(test_barrier_wait_next_twice_local_sync, + ({ + sleep_for(BASE_TIME); + set_alarm(BASE_TIME); + assert_se(barrier_wait_next(&b)); + assert_se(barrier_place(&b)); + assert_se(barrier_place(&b)); + assert_se(barrier_sync_next(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_place(&b)); + assert_se(barrier_place(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test sync_next() and sync() + * This tests sync_*() synchronizations and makes sure they work fine if the + * local state is behind the remote state. + */ +TEST_BARRIER(test_barrier_sync_next, + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_sync_next(&b)); + assert_se(barrier_sync(&b)); + assert_se(barrier_place(&b)); + assert_se(barrier_place(&b)); + assert_se(barrier_sync_next(&b)); + assert_se(barrier_sync_next(&b)); + assert_se(barrier_sync(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + set_alarm(BASE_TIME * 10); + sleep_for(BASE_TIME); + assert_se(barrier_place(&b)); + assert_se(barrier_place(&b)); + assert_se(barrier_sync(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test sync_next() and sync() with local barriers + * This tests timeouts if sync_*() is used if local barriers are placed but the + * remote didn't place any. + */ +TEST_BARRIER(test_barrier_sync_next_local, + ({ + set_alarm(BASE_TIME); + assert_se(barrier_place(&b)); + assert_se(barrier_sync_next(&b)); + assert_se(0); + }), + TEST_BARRIER_WAIT_ALARM(pid1), + ({ + sleep_for(BASE_TIME * 2); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test sync_next() and sync() with local barriers and abortion + * This is the same as test_barrier_sync_next_local but aborts the sync in the + * parent. Therefore, the sync_next() succeeds just fine due to the abortion. + */ +TEST_BARRIER(test_barrier_sync_next_local_abort, + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_place(&b)); + assert_se(!barrier_sync_next(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + assert_se(barrier_abort(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test matched wait_abortion() + * This runs wait_abortion() with remote abortion. + */ +TEST_BARRIER(test_barrier_wait_abortion, + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_wait_abortion(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + assert_se(barrier_abort(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test unmatched wait_abortion() + * This runs wait_abortion() without any remote abortion going on. It thus must + * timeout. + */ +TEST_BARRIER(test_barrier_wait_abortion_unmatched, + ({ + set_alarm(BASE_TIME); + assert_se(barrier_wait_abortion(&b)); + assert_se(0); + }), + TEST_BARRIER_WAIT_ALARM(pid1), + ({ + sleep_for(BASE_TIME * 2); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test matched wait_abortion() with local abortion + * This runs wait_abortion() with local and remote abortion. + */ +TEST_BARRIER(test_barrier_wait_abortion_local, + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_abort(&b)); + assert_se(!barrier_wait_abortion(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + assert_se(barrier_abort(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test unmatched wait_abortion() with local abortion + * This runs wait_abortion() with only local abortion. This must time out. + */ +TEST_BARRIER(test_barrier_wait_abortion_local_unmatched, + ({ + set_alarm(BASE_TIME); + assert_se(barrier_abort(&b)); + assert_se(!barrier_wait_abortion(&b)); + assert_se(0); + }), + TEST_BARRIER_WAIT_ALARM(pid1), + ({ + sleep_for(BASE_TIME * 2); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test child exit + * Place barrier and sync with the child. The child only exits()s, which should + * cause an implicit abortion and wake the parent. + */ +TEST_BARRIER(test_barrier_exit, + ({ + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + set_alarm(BASE_TIME * 10); + assert_se(barrier_place(&b)); + assert_se(!barrier_sync(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +/* + * Test child exit with sleep + * Same as test_barrier_exit but verifies the test really works due to the + * child-exit. We add a usleep() which triggers the alarm in the parent and + * causes the test to time out. + */ +TEST_BARRIER(test_barrier_no_exit, + ({ + sleep_for(BASE_TIME * 2); + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + set_alarm(BASE_TIME); + assert_se(barrier_place(&b)); + assert_se(!barrier_sync(&b)); + }), + TEST_BARRIER_WAIT_ALARM(pid2)); + +/* + * Test pending exit against sync + * The parent places a barrier *and* exits. The 20ms wait in the child + * guarantees both are pending. However, our logic prefers pending barriers over + * pending exit-abortions (unlike normal abortions), thus the wait_next() must + * succeed, same for the sync_next() as our local barrier-count is smaller than + * the remote. Once we place a barrier our count is equal, so the sync still + * succeeds. Only if we place one more barrier, we're ahead of the remote, thus + * we will fail due to HUP on the pipe. + */ +TEST_BARRIER(test_barrier_pending_exit, + ({ + set_alarm(BASE_TIME * 4); + sleep_for(BASE_TIME * 2); + assert_se(barrier_wait_next(&b)); + assert_se(barrier_sync_next(&b)); + assert_se(barrier_place(&b)); + assert_se(barrier_sync_next(&b)); + assert_se(barrier_place(&b)); + assert_se(!barrier_sync_next(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid1), + ({ + assert_se(barrier_place(&b)); + }), + TEST_BARRIER_WAIT_SUCCESS(pid2)); + +int main(int argc, char *argv[]) { + int v; + test_setup_logging(LOG_INFO); + + if (!slow_tests_enabled()) + return log_tests_skipped("slow tests are disabled"); + + /* + * This test uses real-time alarms and sleeps to test for CPU races + * explicitly. This is highly fragile if your system is under load. We + * already increased the BASE_TIME value to make the tests more robust, + * but that just makes the test take significantly longer. Given the recent + * issues when running the test in a virtualized environments, limit it + * to bare metal machines only, to minimize false-positives in CIs. + */ + v = detect_virtualization(); + if (IN_SET(v, -EPERM, -EACCES)) + return log_tests_skipped("Cannot detect virtualization"); + + if (v != VIRTUALIZATION_NONE) + return log_tests_skipped("This test requires a baremetal machine"); + + test_barrier_sync(); + test_barrier_wait_next(); + test_barrier_wait_next_twice(); + test_barrier_wait_next_twice_sync(); + test_barrier_wait_next_twice_local(); + test_barrier_wait_next_twice_local_sync(); + test_barrier_sync_next(); + test_barrier_sync_next_local(); + test_barrier_sync_next_local_abort(); + test_barrier_wait_abortion(); + test_barrier_wait_abortion_unmatched(); + test_barrier_wait_abortion_local(); + test_barrier_wait_abortion_local_unmatched(); + test_barrier_exit(); + test_barrier_no_exit(); + test_barrier_pending_exit(); + + return 0; +} diff --git a/src/test/test-bitmap.c b/src/test/test-bitmap.c new file mode 100644 index 00000000..f73d36e2 --- /dev/null +++ b/src/test/test-bitmap.c @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bitmap.h" + +int main(int argc, const char *argv[]) { + _cleanup_bitmap_free_ Bitmap *b = NULL, *b2 = NULL; + Iterator it; + unsigned n = (unsigned) -1, i = 0; + + b = bitmap_new(); + assert_se(b); + + assert_se(bitmap_ensure_allocated(&b) == 0); + bitmap_free(b); + b = NULL; + assert_se(bitmap_ensure_allocated(&b) == 0); + + assert_se(bitmap_isset(b, 0) == false); + assert_se(bitmap_isset(b, 1) == false); + assert_se(bitmap_isset(b, 256) == false); + assert_se(bitmap_isclear(b) == true); + + assert_se(bitmap_set(b, 0) == 0); + assert_se(bitmap_isset(b, 0) == true); + assert_se(bitmap_isclear(b) == false); + bitmap_unset(b, 0); + assert_se(bitmap_isset(b, 0) == false); + assert_se(bitmap_isclear(b) == true); + + assert_se(bitmap_set(b, 1) == 0); + assert_se(bitmap_isset(b, 1) == true); + assert_se(bitmap_isclear(b) == false); + bitmap_unset(b, 1); + assert_se(bitmap_isset(b, 1) == false); + assert_se(bitmap_isclear(b) == true); + + assert_se(bitmap_set(b, 256) == 0); + assert_se(bitmap_isset(b, 256) == true); + assert_se(bitmap_isclear(b) == false); + bitmap_unset(b, 256); + assert_se(bitmap_isset(b, 256) == false); + assert_se(bitmap_isclear(b) == true); + + assert_se(bitmap_set(b, 32) == 0); + bitmap_unset(b, 0); + assert_se(bitmap_isset(b, 32) == true); + bitmap_unset(b, 32); + + BITMAP_FOREACH(n, NULL, it) + assert_not_reached("NULL bitmap"); + + assert_se(bitmap_set(b, 0) == 0); + assert_se(bitmap_set(b, 1) == 0); + assert_se(bitmap_set(b, 256) == 0); + + BITMAP_FOREACH(n, b, it) { + assert_se(n == i); + if (i == 0) + i = 1; + else if (i == 1) + i = 256; + else if (i == 256) + i = (unsigned) -1; + } + + assert_se(i == (unsigned) -1); + + i = 0; + + BITMAP_FOREACH(n, b, it) { + assert_se(n == i); + if (i == 0) + i = 1; + else if (i == 1) + i = 256; + else if (i == 256) + i = (unsigned) -1; + } + + assert_se(i == (unsigned) -1); + + b2 = bitmap_copy(b); + assert_se(b2); + assert_se(bitmap_equal(b, b2) == true); + assert_se(bitmap_equal(b, b) == true); + assert_se(bitmap_equal(b, NULL) == false); + assert_se(bitmap_equal(NULL, b) == false); + assert_se(bitmap_equal(NULL, NULL) == true); + + bitmap_clear(b); + assert_se(bitmap_isclear(b) == true); + assert_se(bitmap_equal(b, b2) == false); + bitmap_free(b2); + b2 = NULL; + + assert_se(bitmap_set(b, (unsigned) -1) == -ERANGE); + + bitmap_free(b); + b = NULL; + assert_se(bitmap_ensure_allocated(&b) == 0); + assert_se(bitmap_ensure_allocated(&b2) == 0); + + assert_se(bitmap_equal(b, b2)); + assert_se(bitmap_set(b, 0) == 0); + bitmap_unset(b, 0); + assert_se(bitmap_equal(b, b2)); + + assert_se(bitmap_set(b, 1) == 0); + bitmap_clear(b); + assert_se(bitmap_equal(b, b2)); + + assert_se(bitmap_set(b, 0) == 0); + assert_se(bitmap_set(b2, 0) == 0); + assert_se(bitmap_equal(b, b2)); + + return 0; +} diff --git a/src/test/test-boot-timestamps.c b/src/test/test-boot-timestamps.c new file mode 100644 index 00000000..3c7f7a98 --- /dev/null +++ b/src/test/test-boot-timestamps.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "acpi-fpdt.h" +#include "boot-timestamps.h" +#include "efi-loader.h" +#include "log.h" +#include "tests.h" +#include "util.h" + +static int test_acpi_fpdt(void) { + char ts_start[FORMAT_TIMESPAN_MAX], ts_exit[FORMAT_TIMESPAN_MAX], ts_span[FORMAT_TIMESPAN_MAX]; + usec_t loader_start, loader_exit; + int r; + + r = acpi_get_boot_usec(&loader_start, &loader_exit); + if (r < 0) { + bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -ENODATA; + + log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read ACPI FPDT: %m"); + return ok ? 0 : r; + } + + log_info("ACPI FPDT: loader start=%s exit=%s duration=%s", + format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC), + format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC), + format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC)); + return 1; +} + +static int test_efi_loader(void) { + char ts_start[FORMAT_TIMESPAN_MAX], ts_exit[FORMAT_TIMESPAN_MAX], ts_span[FORMAT_TIMESPAN_MAX]; + usec_t loader_start, loader_exit; + int r; + + r = efi_loader_get_boot_usec(&loader_start, &loader_exit); + if (r < 0) { + bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -EOPNOTSUPP; + + log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read EFI loader data: %m"); + return ok ? 0 : r; + } + + log_info("EFI Loader: start=%s exit=%s duration=%s", + format_timespan(ts_start, sizeof(ts_start), loader_start, USEC_PER_MSEC), + format_timespan(ts_exit, sizeof(ts_exit), loader_exit, USEC_PER_MSEC), + format_timespan(ts_span, sizeof(ts_span), loader_exit - loader_start, USEC_PER_MSEC)); + return 1; +} + +static int test_boot_timestamps(void) { + char s[MAX(FORMAT_TIMESPAN_MAX, FORMAT_TIMESTAMP_MAX)]; + dual_timestamp fw, l, k; + int r; + + dual_timestamp_from_monotonic(&k, 0); + + r = boot_timestamps(NULL, &fw, &l); + if (r < 0) { + bool ok = r == -ENOENT || (getuid() != 0 && r == -EACCES) || r == -EOPNOTSUPP; + + log_full_errno(ok ? LOG_DEBUG : LOG_ERR, r, "Failed to read variables: %m"); + return ok ? 0 : r; + } + + log_info("Firmware began %s before kernel.", format_timespan(s, sizeof(s), fw.monotonic, 0)); + log_info("Loader began %s before kernel.", format_timespan(s, sizeof(s), l.monotonic, 0)); + log_info("Firmware began %s.", format_timestamp(s, sizeof(s), fw.realtime)); + log_info("Loader began %s.", format_timestamp(s, sizeof(s), l.realtime)); + log_info("Kernel began %s.", format_timestamp(s, sizeof(s), k.realtime)); + return 1; +} + +int main(int argc, char* argv[]) { + int p, q, r; + + test_setup_logging(LOG_DEBUG); + + p = test_acpi_fpdt(); + assert(p >= 0); + q = test_efi_loader(); + assert(q >= 0); + r = test_boot_timestamps(); + assert(r >= 0); + + if (p == 0 && q == 0 && r == 0) + return log_tests_skipped("access to firmware variables not possible"); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-bpf-devices.c b/src/test/test-bpf-devices.c new file mode 100644 index 00000000..1322af48 --- /dev/null +++ b/src/test/test-bpf-devices.c @@ -0,0 +1,306 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "bpf-devices.h" +#include "bpf-program.h" +#include "cgroup-setup.h" +#include "errno-list.h" +#include "fd-util.h" +#include "fs-util.h" +#include "path-util.h" +#include "tests.h" + +static void test_policy_closed(const char *cgroup_path, BPFProgram **installed_prog) { + _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL; + unsigned wrong = 0; + int r; + + log_info("/* %s */", __func__); + + r = bpf_devices_cgroup_init(&prog, CGROUP_DEVICE_POLICY_CLOSED, true); + assert_se(r >= 0); + + r = bpf_devices_whitelist_static(prog, cgroup_path); + assert_se(r >= 0); + + r = bpf_devices_apply_policy(prog, CGROUP_DEVICE_POLICY_CLOSED, true, cgroup_path, installed_prog); + assert_se(r >= 0); + + const char *s; + FOREACH_STRING(s, "/dev/null", + "/dev/zero", + "/dev/full", + "/dev/random", + "/dev/urandom", + "/dev/tty", + "/dev/ptmx") { + _cleanup_close_ int fd, fd2; + + fd = open(s, O_CLOEXEC|O_RDONLY|O_NOCTTY); + log_debug("open(%s, \"r\") = %d/%s", s, fd, fd < 0 ? errno_to_name(errno) : "-"); + wrong += fd < 0 && errno == EPERM; + /* We ignore errors other than EPERM, e.g. ENOENT or ENXIO */ + + fd2 = open(s, O_CLOEXEC|O_WRONLY|O_NOCTTY); + log_debug("open(%s, \"w\") = %d/%s", s, fd2, fd2 < 0 ? errno_to_name(errno) : "-"); + wrong += fd2 < 0 && errno == EPERM; + } + assert_se(wrong == 0); +} + +static void test_policy_strict(const char *cgroup_path, BPFProgram **installed_prog) { + _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL; + unsigned wrong = 0; + int r; + + log_info("/* %s */", __func__); + + r = bpf_devices_cgroup_init(&prog, CGROUP_DEVICE_POLICY_STRICT, true); + assert_se(r >= 0); + + r = bpf_devices_whitelist_device(prog, cgroup_path, "/dev/null", "rw"); + assert_se(r >= 0); + + r = bpf_devices_whitelist_device(prog, cgroup_path, "/dev/random", "r"); + assert_se(r >= 0); + + r = bpf_devices_whitelist_device(prog, cgroup_path, "/dev/zero", "w"); + assert_se(r >= 0); + + r = bpf_devices_apply_policy(prog, CGROUP_DEVICE_POLICY_STRICT, true, cgroup_path, installed_prog); + assert_se(r >= 0); + + { + _cleanup_close_ int fd, fd2; + const char *s = "/dev/null"; + + fd = open(s, O_CLOEXEC|O_RDONLY|O_NOCTTY); + log_debug("open(%s, \"r\") = %d/%s", s, fd, fd < 0 ? errno_to_name(errno) : "-"); + wrong += fd < 0; + + fd2 = open(s, O_CLOEXEC|O_WRONLY|O_NOCTTY); + log_debug("open(%s, \"w\") = %d/%s", s, fd2, fd2 < 0 ? errno_to_name(errno) : "-"); + wrong += fd2 < 0; + } + + { + _cleanup_close_ int fd, fd2; + const char *s = "/dev/random"; + + fd = open(s, O_CLOEXEC|O_RDONLY|O_NOCTTY); + log_debug("open(%s, \"r\") = %d/%s", s, fd, fd < 0 ? errno_to_name(errno) : "-"); + wrong += fd < 0; + + fd2 = open(s, O_CLOEXEC|O_WRONLY|O_NOCTTY); + log_debug("open(%s, \"w\") = %d/%s", s, fd2, fd2 < 0 ? errno_to_name(errno) : "-"); + wrong += fd2 >= 0; + } + + { + _cleanup_close_ int fd, fd2; + const char *s = "/dev/zero"; + + fd = open(s, O_CLOEXEC|O_RDONLY|O_NOCTTY); + log_debug("open(%s, \"r\") = %d/%s", s, fd, fd < 0 ? errno_to_name(errno) : "-"); + wrong += fd >= 0; + + fd2 = open(s, O_CLOEXEC|O_WRONLY|O_NOCTTY); + log_debug("open(%s, \"w\") = %d/%s", s, fd2, fd2 < 0 ? errno_to_name(errno) : "-"); + wrong += fd2 < 0; + } + + { + _cleanup_close_ int fd, fd2; + const char *s = "/dev/full"; + + fd = open(s, O_CLOEXEC|O_RDONLY|O_NOCTTY); + log_debug("open(%s, \"r\") = %d/%s", s, fd, fd < 0 ? errno_to_name(errno) : "-"); + wrong += fd >= 0; + + fd2 = open(s, O_CLOEXEC|O_WRONLY|O_NOCTTY); + log_debug("open(%s, \"w\") = %d/%s", s, fd2, fd2 < 0 ? errno_to_name(errno) : "-"); + wrong += fd2 >= 0; + } + + assert_se(wrong == 0); +} + +static void test_policy_whitelist_major(const char *pattern, const char *cgroup_path, BPFProgram **installed_prog) { + _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL; + unsigned wrong = 0; + int r; + + log_info("/* %s(%s) */", __func__, pattern); + + r = bpf_devices_cgroup_init(&prog, CGROUP_DEVICE_POLICY_STRICT, true); + assert_se(r >= 0); + + r = bpf_devices_whitelist_major(prog, cgroup_path, pattern, 'c', "rw"); + assert_se(r >= 0); + + r = bpf_devices_apply_policy(prog, CGROUP_DEVICE_POLICY_STRICT, true, cgroup_path, installed_prog); + assert_se(r >= 0); + + /* /dev/null, /dev/full have major==1, /dev/tty has major==5 */ + { + _cleanup_close_ int fd, fd2; + const char *s = "/dev/null"; + + fd = open(s, O_CLOEXEC|O_RDONLY|O_NOCTTY); + log_debug("open(%s, \"r\") = %d/%s", s, fd, fd < 0 ? errno_to_name(errno) : "-"); + wrong += fd < 0; + + fd2 = open(s, O_CLOEXEC|O_WRONLY|O_NOCTTY); + log_debug("open(%s, \"w\") = %d/%s", s, fd2, fd2 < 0 ? errno_to_name(errno) : "-"); + wrong += fd2 < 0; + } + + { + _cleanup_close_ int fd, fd2; + const char *s = "/dev/full"; + + fd = open(s, O_CLOEXEC|O_RDONLY|O_NOCTTY); + log_debug("open(%s, \"r\") = %d/%s", s, fd, fd < 0 ? errno_to_name(errno) : "-"); + wrong += fd < 0; + + fd2 = open(s, O_CLOEXEC|O_WRONLY|O_NOCTTY); + log_debug("open(%s, \"w\") = %d/%s", s, fd2, fd2 < 0 ? errno_to_name(errno) : "-"); + wrong += fd2 < 0; + } + + { + _cleanup_close_ int fd, fd2; + const char *s = "/dev/tty"; + + fd = open(s, O_CLOEXEC|O_RDONLY|O_NOCTTY); + log_debug("open(%s, \"r\") = %d/%s", s, fd, fd < 0 ? errno_to_name(errno) : "-"); + wrong += fd >= 0; + + fd2 = open(s, O_CLOEXEC|O_WRONLY|O_NOCTTY); + log_debug("open(%s, \"w\") = %d/%s", s, fd2, fd2 < 0 ? errno_to_name(errno) : "-"); + wrong += fd2 >= 0; + } + + assert_se(wrong == 0); +} + +static void test_policy_whitelist_major_star(char type, const char *cgroup_path, BPFProgram **installed_prog) { + _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL; + unsigned wrong = 0; + int r; + + log_info("/* %s(type=%c) */", __func__, type); + + r = bpf_devices_cgroup_init(&prog, CGROUP_DEVICE_POLICY_STRICT, true); + assert_se(r >= 0); + + r = bpf_devices_whitelist_major(prog, cgroup_path, "*", type, "rw"); + assert_se(r >= 0); + + r = bpf_devices_apply_policy(prog, CGROUP_DEVICE_POLICY_STRICT, true, cgroup_path, installed_prog); + assert_se(r >= 0); + + { + _cleanup_close_ int fd; + const char *s = "/dev/null"; + + fd = open(s, O_CLOEXEC|O_RDWR|O_NOCTTY); + log_debug("open(%s, \"r\") = %d/%s", s, fd, fd < 0 ? errno_to_name(errno) : "-"); + if (type == 'c') + wrong += fd < 0; + else + wrong += fd >= 0; + } + + assert_se(wrong == 0); +} + +static void test_policy_empty(bool add_mismatched, const char *cgroup_path, BPFProgram **installed_prog) { + _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL; + unsigned wrong = 0; + int r; + + log_info("/* %s(add_mismatched=%s) */", __func__, yes_no(add_mismatched)); + + r = bpf_devices_cgroup_init(&prog, CGROUP_DEVICE_POLICY_STRICT, add_mismatched); + assert_se(r >= 0); + + if (add_mismatched) { + r = bpf_devices_whitelist_major(prog, cgroup_path, "foobarxxx", 'c', "rw"); + assert_se(r < 0); + } + + r = bpf_devices_apply_policy(prog, CGROUP_DEVICE_POLICY_STRICT, false, cgroup_path, installed_prog); + assert_se(r >= 0); + + { + _cleanup_close_ int fd; + const char *s = "/dev/null"; + + fd = open(s, O_CLOEXEC|O_RDWR|O_NOCTTY); + log_debug("open(%s, \"r\") = %d/%s", s, fd, fd < 0 ? errno_to_name(errno) : "-"); + wrong += fd >= 0; + } + + assert_se(wrong == 0); +} + + +int main(int argc, char *argv[]) { + _cleanup_free_ char *cgroup = NULL, *parent = NULL; + _cleanup_(rmdir_and_freep) char *controller_path = NULL; + CGroupMask supported; + struct rlimit rl; + int r; + + test_setup_logging(LOG_DEBUG); + + assert_se(getrlimit(RLIMIT_MEMLOCK, &rl) >= 0); + rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, CAN_MEMLOCK_SIZE); + (void) setrlimit(RLIMIT_MEMLOCK, &rl); + + r = cg_all_unified(); + if (r <= 0) + return log_tests_skipped("We don't seem to be running with unified cgroup hierarchy"); + + if (!can_memlock()) + return log_tests_skipped("Can't use mlock()"); + + r = enter_cgroup_subroot(&cgroup); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + r = bpf_devices_supported(); + if (!r) + return log_tests_skipped("BPF device filter not supported"); + assert_se(r == 1); + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, cgroup, NULL, &controller_path); + assert_se(r >= 0); + + _cleanup_(bpf_program_unrefp) BPFProgram *prog = NULL; + + test_policy_closed(cgroup, &prog); + test_policy_strict(cgroup, &prog); + + test_policy_whitelist_major("mem", cgroup, &prog); + test_policy_whitelist_major("1", cgroup, &prog); + + test_policy_whitelist_major_star('c', cgroup, &prog); + test_policy_whitelist_major_star('b', cgroup, &prog); + + test_policy_empty(false, cgroup, &prog); + test_policy_empty(true, cgroup, &prog); + + assert_se(parent = dirname_malloc(cgroup)); + + assert_se(cg_mask_supported(&supported) >= 0); + r = cg_attach_everywhere(supported, parent, 0, NULL, NULL); + assert_se(r >= 0); + + return 0; +} diff --git a/src/test/test-bpf-firewall.c b/src/test/test-bpf-firewall.c new file mode 100644 index 00000000..fbaa349b --- /dev/null +++ b/src/test/test-bpf-firewall.c @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "bpf-firewall.h" +#include "bpf-program.h" +#include "load-fragment.h" +#include "manager.h" +#include "rm-rf.h" +#include "service.h" +#include "tests.h" +#include "unit.h" +#include "virt.h" + +int main(int argc, char *argv[]) { + const struct bpf_insn exit_insn[] = { + BPF_MOV64_IMM(BPF_REG_0, 0), /* drop */ + BPF_EXIT_INSN() + }; + + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + CGroupContext *cc = NULL; + _cleanup_(bpf_program_unrefp) BPFProgram *p = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + Unit *u; + char log_buf[65535]; + struct rlimit rl; + int r; + union bpf_attr attr; + bool test_custom_filter = false; + const char *test_prog = "/sys/fs/bpf/test-dropper"; + + test_setup_logging(LOG_DEBUG); + + if (detect_container() > 0) + return log_tests_skipped("test-bpf-firewall fails inside LXC and Docker containers: https://github.com/systemd/systemd/issues/9666"); + + assert_se(getrlimit(RLIMIT_MEMLOCK, &rl) >= 0); + rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, CAN_MEMLOCK_SIZE); + (void) setrlimit(RLIMIT_MEMLOCK, &rl); + + if (!can_memlock()) + return log_tests_skipped("Can't use mlock()"); + + r = enter_cgroup_subroot(NULL); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + assert_se(set_unit_path(get_testdata_dir()) >= 0); + assert_se(runtime_dir = setup_fake_runtime_dir()); + + r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &p); + assert(r == 0); + + r = bpf_program_add_instructions(p, exit_insn, ELEMENTSOF(exit_insn)); + assert(r == 0); + + if (getuid() != 0) + return log_tests_skipped("not running as root"); + + r = bpf_firewall_supported(); + if (r == BPF_FIREWALL_UNSUPPORTED) + return log_tests_skipped("BPF firewalling not supported"); + assert_se(r > 0); + + if (r == BPF_FIREWALL_SUPPORTED_WITH_MULTI) { + log_notice("BPF firewalling with BPF_F_ALLOW_MULTI supported. Yay!"); + test_custom_filter = true; + } else + log_notice("BPF firewalling (though without BPF_F_ALLOW_MULTI) supported. Good."); + + r = bpf_program_load_kernel(p, log_buf, ELEMENTSOF(log_buf)); + assert(r >= 0); + + if (test_custom_filter) { + attr = (union bpf_attr) { + .pathname = PTR_TO_UINT64(test_prog), + .bpf_fd = p->kernel_fd, + .file_flags = 0, + }; + + (void) unlink(test_prog); + + r = bpf(BPF_OBJ_PIN, &attr, sizeof(attr)); + if (r < 0) { + log_warning_errno(errno, "BPF object pinning failed, will not run custom filter test: %m"); + test_custom_filter = false; + } + } + + p = bpf_program_unref(p); + + /* The simple tests succeeded. Now let's try full unit-based use-case. */ + + assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0); + assert_se(manager_startup(m, NULL, NULL) >= 0); + + assert_se(u = unit_new(m, sizeof(Service))); + assert_se(unit_add_name(u, "foo.service") == 0); + assert_se(cc = unit_get_cgroup_context(u)); + u->perpetual = true; + + cc->ip_accounting = true; + + assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "10.0.1.0/24", &cc->ip_address_allow, NULL) == 0); + assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "127.0.0.2", &cc->ip_address_allow, NULL) == 0); + assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.3", &cc->ip_address_deny, NULL) == 0); + assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "10.0.3.2/24", &cc->ip_address_deny, NULL) == 0); + assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.1/25", &cc->ip_address_deny, NULL) == 0); + assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.4", &cc->ip_address_deny, NULL) == 0); + + assert(cc->ip_address_allow); + assert(cc->ip_address_allow->items_next); + assert(!cc->ip_address_allow->items_next->items_next); + + /* The deny list is defined redundantly, let's ensure it got properly reduced */ + assert(cc->ip_address_deny); + assert(cc->ip_address_deny->items_next); + assert(!cc->ip_address_deny->items_next->items_next); + + assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "/bin/ping -c 1 127.0.0.2 -W 5", SERVICE(u)->exec_command, u) == 0); + assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "/bin/ping -c 1 127.0.0.3 -W 5", SERVICE(u)->exec_command, u) == 0); + + assert_se(SERVICE(u)->exec_command[SERVICE_EXEC_START]); + assert_se(SERVICE(u)->exec_command[SERVICE_EXEC_START]->command_next); + assert_se(!SERVICE(u)->exec_command[SERVICE_EXEC_START]->command_next->command_next); + + SERVICE(u)->type = SERVICE_ONESHOT; + u->load_state = UNIT_LOADED; + + unit_dump(u, stdout, NULL); + + r = bpf_firewall_compile(u); + if (IN_SET(r, -ENOTTY, -ENOSYS, -EPERM)) + return log_tests_skipped("Kernel doesn't support the necessary bpf bits (masked out via seccomp?)"); + assert_se(r >= 0); + + assert(u->ip_bpf_ingress); + assert(u->ip_bpf_egress); + + r = bpf_program_load_kernel(u->ip_bpf_ingress, log_buf, ELEMENTSOF(log_buf)); + + log_notice("log:"); + log_notice("-------"); + log_notice("%s", log_buf); + log_notice("-------"); + + assert(r >= 0); + + r = bpf_program_load_kernel(u->ip_bpf_egress, log_buf, ELEMENTSOF(log_buf)); + + log_notice("log:"); + log_notice("-------"); + log_notice("%s", log_buf); + log_notice("-------"); + + assert(r >= 0); + + assert_se(unit_start(u) >= 0); + + while (!IN_SET(SERVICE(u)->state, SERVICE_DEAD, SERVICE_FAILED)) + assert_se(sd_event_run(m->event, UINT64_MAX) >= 0); + + assert_se(SERVICE(u)->exec_command[SERVICE_EXEC_START]->exec_status.code == CLD_EXITED && + SERVICE(u)->exec_command[SERVICE_EXEC_START]->exec_status.status == EXIT_SUCCESS); + + assert_se(SERVICE(u)->exec_command[SERVICE_EXEC_START]->command_next->exec_status.code != CLD_EXITED || + SERVICE(u)->exec_command[SERVICE_EXEC_START]->command_next->exec_status.status != EXIT_SUCCESS); + + if (test_custom_filter) { + assert_se(u = unit_new(m, sizeof(Service))); + assert_se(unit_add_name(u, "custom-filter.service") == 0); + assert_se(cc = unit_get_cgroup_context(u)); + u->perpetual = true; + + cc->ip_accounting = true; + + assert_se(config_parse_ip_filter_bpf_progs(u->id, "filename", 1, "Service", 1, "IPIngressFilterPath", 0, test_prog, &cc->ip_filters_ingress, u) == 0); + assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "-/bin/ping -c 1 127.0.0.1 -W 5", SERVICE(u)->exec_command, u) == 0); + + SERVICE(u)->type = SERVICE_ONESHOT; + u->load_state = UNIT_LOADED; + + assert_se(unit_start(u) >= 0); + + while (!IN_SET(SERVICE(u)->state, SERVICE_DEAD, SERVICE_FAILED)) + assert_se(sd_event_run(m->event, UINT64_MAX) >= 0); + + assert_se(SERVICE(u)->exec_command[SERVICE_EXEC_START]->exec_status.code != CLD_EXITED || + SERVICE(u)->exec_command[SERVICE_EXEC_START]->exec_status.status != EXIT_SUCCESS); + + (void) unlink(test_prog); + assert_se(SERVICE(u)->state == SERVICE_DEAD); + } + + return 0; +} diff --git a/src/test/test-btrfs.c b/src/test/test-btrfs.c new file mode 100644 index 00000000..5bd0e345 --- /dev/null +++ b/src/test/test-btrfs.c @@ -0,0 +1,181 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "btrfs-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "log.h" +#include "string-util.h" +#include "util.h" + +int main(int argc, char *argv[]) { + BtrfsQuotaInfo quota; + int r, fd; + + fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (fd < 0) + log_error_errno(errno, "Failed to open root directory: %m"); + else { + char ts[FORMAT_TIMESTAMP_MAX], bs[FORMAT_BYTES_MAX]; + BtrfsSubvolInfo info; + + r = btrfs_subvol_get_info_fd(fd, 0, &info); + if (r < 0) + log_error_errno(r, "Failed to get subvolume info: %m"); + else { + log_info("otime: %s", format_timestamp(ts, sizeof(ts), info.otime)); + log_info("read-only (search): %s", yes_no(info.read_only)); + } + + r = btrfs_qgroup_get_quota_fd(fd, 0, "a); + if (r < 0) + log_error_errno(r, "Failed to get quota info: %m"); + else { + log_info("referenced: %s", strna(format_bytes(bs, sizeof(bs), quota.referenced))); + log_info("exclusive: %s", strna(format_bytes(bs, sizeof(bs), quota.exclusive))); + log_info("referenced_max: %s", strna(format_bytes(bs, sizeof(bs), quota.referenced_max))); + log_info("exclusive_max: %s", strna(format_bytes(bs, sizeof(bs), quota.exclusive_max))); + } + + r = btrfs_subvol_get_read_only_fd(fd); + if (r < 0) + log_error_errno(r, "Failed to get read only flag: %m"); + else + log_info("read-only (ioctl): %s", yes_no(r)); + + safe_close(fd); + } + + r = btrfs_subvol_make("/xxxtest"); + if (r < 0) + log_error_errno(r, "Failed to make subvolume: %m"); + + r = write_string_file("/xxxtest/afile", "ljsadhfljasdkfhlkjdsfha", WRITE_STRING_FILE_CREATE); + if (r < 0) + log_error_errno(r, "Failed to write file: %m"); + + r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest2", 0); + if (r < 0) + log_error_errno(r, "Failed to make snapshot: %m"); + + r = btrfs_subvol_snapshot("/xxxtest", "/xxxtest3", BTRFS_SNAPSHOT_READ_ONLY); + if (r < 0) + log_error_errno(r, "Failed to make snapshot: %m"); + + r = btrfs_subvol_remove("/xxxtest", BTRFS_REMOVE_QUOTA); + if (r < 0) + log_error_errno(r, "Failed to remove subvolume: %m"); + + r = btrfs_subvol_remove("/xxxtest2", BTRFS_REMOVE_QUOTA); + if (r < 0) + log_error_errno(r, "Failed to remove subvolume: %m"); + + r = btrfs_subvol_remove("/xxxtest3", BTRFS_REMOVE_QUOTA); + if (r < 0) + log_error_errno(r, "Failed to remove subvolume: %m"); + + r = btrfs_subvol_snapshot("/etc", "/etc2", BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_FALLBACK_COPY); + if (r < 0) + log_error_errno(r, "Failed to make snapshot: %m"); + + r = btrfs_subvol_remove("/etc2", BTRFS_REMOVE_QUOTA); + if (r < 0) + log_error_errno(r, "Failed to remove subvolume: %m"); + + r = btrfs_subvol_make("/xxxrectest"); + if (r < 0) + log_error_errno(r, "Failed to make subvolume: %m"); + + r = btrfs_subvol_make("/xxxrectest/xxxrectest2"); + if (r < 0) + log_error_errno(r, "Failed to make subvolume: %m"); + + r = btrfs_subvol_make("/xxxrectest/xxxrectest3"); + if (r < 0) + log_error_errno(r, "Failed to make subvolume: %m"); + + r = btrfs_subvol_make("/xxxrectest/xxxrectest3/sub"); + if (r < 0) + log_error_errno(r, "Failed to make subvolume: %m"); + + if (mkdir("/xxxrectest/dir", 0755) < 0) + log_error_errno(errno, "Failed to make directory: %m"); + + r = btrfs_subvol_make("/xxxrectest/dir/xxxrectest4"); + if (r < 0) + log_error_errno(r, "Failed to make subvolume: %m"); + + if (mkdir("/xxxrectest/dir/xxxrectest4/dir", 0755) < 0) + log_error_errno(errno, "Failed to make directory: %m"); + + r = btrfs_subvol_make("/xxxrectest/dir/xxxrectest4/dir/xxxrectest5"); + if (r < 0) + log_error_errno(r, "Failed to make subvolume: %m"); + + if (mkdir("/xxxrectest/mnt", 0755) < 0) + log_error_errno(errno, "Failed to make directory: %m"); + + r = btrfs_subvol_snapshot("/xxxrectest", "/xxxrectest2", BTRFS_SNAPSHOT_RECURSIVE); + if (r < 0) + log_error_errno(r, "Failed to snapshot subvolume: %m"); + + r = btrfs_subvol_remove("/xxxrectest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE); + if (r < 0) + log_error_errno(r, "Failed to recursively remove subvolume: %m"); + + r = btrfs_subvol_remove("/xxxrectest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE); + if (r < 0) + log_error_errno(r, "Failed to recursively remove subvolume: %m"); + + r = btrfs_subvol_make("/xxxquotatest"); + if (r < 0) + log_error_errno(r, "Failed to make subvolume: %m"); + + r = btrfs_subvol_auto_qgroup("/xxxquotatest", 0, true); + if (r < 0) + log_error_errno(r, "Failed to set up auto qgroup: %m"); + + r = btrfs_subvol_make("/xxxquotatest/beneath"); + if (r < 0) + log_error_errno(r, "Failed to make subvolume: %m"); + + r = btrfs_subvol_auto_qgroup("/xxxquotatest/beneath", 0, false); + if (r < 0) + log_error_errno(r, "Failed to set up auto qgroup: %m"); + + r = btrfs_qgroup_set_limit("/xxxquotatest/beneath", 0, 4ULL * 1024 * 1024 * 1024); + if (r < 0) + log_error_errno(r, "Failed to set up quota limit: %m"); + + r = btrfs_subvol_set_subtree_quota_limit("/xxxquotatest", 0, 5ULL * 1024 * 1024 * 1024); + if (r < 0) + log_error_errno(r, "Failed to set up quota limit: %m"); + + r = btrfs_subvol_snapshot("/xxxquotatest", "/xxxquotatest2", BTRFS_SNAPSHOT_RECURSIVE|BTRFS_SNAPSHOT_QUOTA); + if (r < 0) + log_error_errno(r, "Failed to setup snapshot: %m"); + + r = btrfs_qgroup_get_quota("/xxxquotatest2/beneath", 0, "a); + if (r < 0) + log_error_errno(r, "Failed to query quota: %m"); + + assert_se(quota.referenced_max == 4ULL * 1024 * 1024 * 1024); + + r = btrfs_subvol_get_subtree_quota("/xxxquotatest2", 0, "a); + if (r < 0) + log_error_errno(r, "Failed to query quota: %m"); + + assert_se(quota.referenced_max == 5ULL * 1024 * 1024 * 1024); + + r = btrfs_subvol_remove("/xxxquotatest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE); + if (r < 0) + log_error_errno(r, "Failed remove subvolume: %m"); + + r = btrfs_subvol_remove("/xxxquotatest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE); + if (r < 0) + log_error_errno(r, "Failed remove subvolume: %m"); + + return 0; +} diff --git a/src/test/test-bus-util.c b/src/test/test-bus-util.c new file mode 100644 index 00000000..a536608c --- /dev/null +++ b/src/test/test-bus-util.c @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "bus-util.h" +#include "log.h" +#include "tests.h" + +static int callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + return 1; +} + +static void destroy_callback(void *userdata) { + int *n_called = userdata; + + (*n_called) ++; +} + +static void test_destroy_callback(void) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + sd_bus_slot *slot = NULL; + sd_bus_destroy_t t; + + int r, n_called = 0; + + log_info("/* %s */", __func__); + + r = bus_open_system_watch_bind_with_description(&bus, "test-bus"); + if (r < 0) { + log_error_errno(r, "Failed to connect to bus: %m"); + return; + } + + r = sd_bus_request_name_async(bus, &slot, "org.freedesktop.systemd.test-bus-util", 0, callback, &n_called); + assert(r == 1); + + assert_se(sd_bus_slot_get_destroy_callback(slot, NULL) == 0); + assert_se(sd_bus_slot_get_destroy_callback(slot, &t) == 0); + + assert_se(sd_bus_slot_set_destroy_callback(slot, destroy_callback) == 0); + assert_se(sd_bus_slot_get_destroy_callback(slot, NULL) == 1); + assert_se(sd_bus_slot_get_destroy_callback(slot, &t) == 1); + assert_se(t == destroy_callback); + + /* Force cleanup so we can look at n_called */ + assert(n_called == 0); + sd_bus_slot_unref(slot); + assert(n_called == 1); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_destroy_callback(); + + return 0; +} diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c new file mode 100644 index 00000000..9c2be7f4 --- /dev/null +++ b/src/test/test-calendarspec.c @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "calendarspec.h" +#include "errno-util.h" +#include "string-util.h" +#include "util.h" + +static void test_one(const char *input, const char *output) { + CalendarSpec *c; + _cleanup_free_ char *p = NULL, *q = NULL; + usec_t u; + char buf[FORMAT_TIMESTAMP_MAX]; + int r; + + assert_se(calendar_spec_from_string(input, &c) >= 0); + + assert_se(calendar_spec_to_string(c, &p) >= 0); + printf("\"%s\" → \"%s\"\n", input, p); + + assert_se(streq(p, output)); + + u = now(CLOCK_REALTIME); + r = calendar_spec_next_usec(c, u, &u); + printf("Next: %s\n", r < 0 ? strerror_safe(r) : format_timestamp(buf, sizeof(buf), u)); + calendar_spec_free(c); + + assert_se(calendar_spec_from_string(p, &c) >= 0); + assert_se(calendar_spec_to_string(c, &q) >= 0); + calendar_spec_free(c); + + assert_se(streq(q, p)); +} + +static void test_next(const char *input, const char *new_tz, usec_t after, usec_t expect) { + CalendarSpec *c; + usec_t u; + char *old_tz; + char buf[FORMAT_TIMESTAMP_MAX]; + int r; + + old_tz = getenv("TZ"); + if (old_tz) + old_tz = strdupa(old_tz); + + if (new_tz) { + char *colon_tz; + + colon_tz = strjoina(":", new_tz); + assert_se(setenv("TZ", colon_tz, 1) >= 0); + } else + assert_se(unsetenv("TZ") >= 0); + tzset(); + + assert_se(calendar_spec_from_string(input, &c) >= 0); + + printf("\"%s\"\n", input); + + u = after; + r = calendar_spec_next_usec(c, after, &u); + printf("At: %s\n", r < 0 ? strerror_safe(r) : format_timestamp_us(buf, sizeof buf, u)); + if (expect != (usec_t)-1) + assert_se(r >= 0 && u == expect); + else + assert(r == -ENOENT); + + calendar_spec_free(c); + + if (old_tz) + assert_se(setenv("TZ", old_tz, 1) >= 0); + else + assert_se(unsetenv("TZ") >= 0); + tzset(); +} + +static void test_timestamp(void) { + char buf[FORMAT_TIMESTAMP_MAX]; + _cleanup_free_ char *t = NULL; + CalendarSpec *c; + usec_t x, y; + + /* Ensure that a timestamp is also a valid calendar specification. Convert forth and back */ + + x = now(CLOCK_REALTIME); + + assert_se(format_timestamp_us(buf, sizeof(buf), x)); + printf("%s\n", buf); + assert_se(calendar_spec_from_string(buf, &c) >= 0); + assert_se(calendar_spec_to_string(c, &t) >= 0); + calendar_spec_free(c); + printf("%s\n", t); + + assert_se(parse_timestamp(t, &y) >= 0); + assert_se(y == x); +} + +static void test_hourly_bug_4031(void) { + CalendarSpec *c; + usec_t n, u, w; + char buf[FORMAT_TIMESTAMP_MAX], zaf[FORMAT_TIMESTAMP_MAX]; + int r; + + assert_se(calendar_spec_from_string("hourly", &c) >= 0); + n = now(CLOCK_REALTIME); + assert_se((r = calendar_spec_next_usec(c, n, &u)) >= 0); + + printf("Now: %s (%"PRIu64")\n", format_timestamp_us(buf, sizeof buf, n), n); + printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_us(buf, sizeof buf, u), u); + + assert_se((r = calendar_spec_next_usec(c, u, &w)) >= 0); + printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_us(zaf, sizeof zaf, w), w); + + assert_se(n < u); + assert_se(u <= n + USEC_PER_HOUR); + assert_se(u < w); + assert_se(w <= u + USEC_PER_HOUR); + + calendar_spec_free(c); +} + +int main(int argc, char* argv[]) { + CalendarSpec *c; + + test_one("Sat,Thu,Mon-Wed,Sat-Sun", "Mon..Thu,Sat,Sun *-*-* 00:00:00"); + test_one("Sat,Thu,Mon..Wed,Sat..Sun", "Mon..Thu,Sat,Sun *-*-* 00:00:00"); + test_one("Mon,Sun 12-*-* 2,1:23", "Mon,Sun 2012-*-* 01,02:23:00"); + test_one("Wed *-1", "Wed *-*-01 00:00:00"); + test_one("Wed-Wed,Wed *-1", "Wed *-*-01 00:00:00"); + test_one("Wed..Wed,Wed *-1", "Wed *-*-01 00:00:00"); + test_one("Wed, 17:48", "Wed *-*-* 17:48:00"); + test_one("Wednesday,", "Wed *-*-* 00:00:00"); + test_one("Wed-Sat,Tue 12-10-15 1:2:3", "Tue..Sat 2012-10-15 01:02:03"); + test_one("Wed..Sat,Tue 12-10-15 1:2:3", "Tue..Sat 2012-10-15 01:02:03"); + test_one("*-*-7 0:0:0", "*-*-07 00:00:00"); + test_one("10-15", "*-10-15 00:00:00"); + test_one("monday *-12-* 17:00", "Mon *-12-* 17:00:00"); + test_one("Mon,Fri *-*-3,1,2 *:30:45", "Mon,Fri *-*-01,02,03 *:30:45"); + test_one("12,14,13,12:20,10,30", "*-*-* 12,13,14:10,20,30:00"); + test_one("mon,fri *-1/2-1,3 *:30:45", "Mon,Fri *-01/2-01,03 *:30:45"); + test_one("03-05 08:05:40", "*-03-05 08:05:40"); + test_one("08:05:40", "*-*-* 08:05:40"); + test_one("05:40", "*-*-* 05:40:00"); + test_one("Sat,Sun 12-05 08:05:40", "Sat,Sun *-12-05 08:05:40"); + test_one("Sat,Sun 08:05:40", "Sat,Sun *-*-* 08:05:40"); + test_one("2003-03-05 05:40", "2003-03-05 05:40:00"); + test_one("2003-03-05", "2003-03-05 00:00:00"); + test_one("03-05", "*-03-05 00:00:00"); + test_one("hourly", "*-*-* *:00:00"); + test_one("daily", "*-*-* 00:00:00"); + test_one("monthly", "*-*-01 00:00:00"); + test_one("weekly", "Mon *-*-* 00:00:00"); + test_one("minutely", "*-*-* *:*:00"); + test_one("quarterly", "*-01,04,07,10-01 00:00:00"); + test_one("semi-annually", "*-01,07-01 00:00:00"); + test_one("annually", "*-01-01 00:00:00"); + test_one("*:2/3", "*-*-* *:02/3:00"); + test_one("2015-10-25 01:00:00 uTc", "2015-10-25 01:00:00 UTC"); + test_one("2015-10-25 01:00:00 Asia/Vladivostok", "2015-10-25 01:00:00 Asia/Vladivostok"); + test_one("weekly Pacific/Auckland", "Mon *-*-* 00:00:00 Pacific/Auckland"); + test_one("2016-03-27 03:17:00.4200005", "2016-03-27 03:17:00.420001"); + test_one("2016-03-27 03:17:00/0.42", "2016-03-27 03:17:00/0.420000"); + test_one("9..11,13:00,30", "*-*-* 09..11,13:00,30:00"); + test_one("1..3-1..3 1..3:1..3", "*-01..03-01..03 01..03:01..03:00"); + test_one("00:00:1.125..2.125", "*-*-* 00:00:01.125000..02.125000"); + test_one("00:00:1.0..3.8", "*-*-* 00:00:01..03"); + test_one("00:00:01..03", "*-*-* 00:00:01..03"); + test_one("00:00:01/2,02..03", "*-*-* 00:00:01/2,02..03"); + test_one("*-*~1 Utc", "*-*~01 00:00:00 UTC"); + test_one("*-*~05,3 ", "*-*~03,05 00:00:00"); + test_one("*-*~* 00:00:00", "*-*-* 00:00:00"); + test_one("Monday", "Mon *-*-* 00:00:00"); + test_one("Monday *-*-*", "Mon *-*-* 00:00:00"); + test_one("*-*-*", "*-*-* 00:00:00"); + test_one("*:*:*", "*-*-* *:*:*"); + test_one("*:*", "*-*-* *:*:00"); + test_one("12:*", "*-*-* 12:*:00"); + test_one("*:30", "*-*-* *:30:00"); + test_one("93..00-*-*", "1993..2000-*-* 00:00:00"); + test_one("00..07-*-*", "2000..2007-*-* 00:00:00"); + test_one("*:20..39/5", "*-*-* *:20..35/5:00"); + test_one("00:00:20..40/1", "*-*-* 00:00:20..40"); + test_one("*~03/1,03..05", "*-*~03/1,03..05 00:00:00"); + /* UNIX timestamps are always UTC */ + test_one("@1493187147", "2017-04-26 06:12:27 UTC"); + test_one("@1493187147 UTC", "2017-04-26 06:12:27 UTC"); + test_one("@0", "1970-01-01 00:00:00 UTC"); + test_one("@0 UTC", "1970-01-01 00:00:00 UTC"); + + test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000); + test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000); + test_next("2016-03-27 03:17:00", "EET", 12345, -1); + test_next("2016-03-27 03:17:00 UTC", NULL, 12345, 1459048620000000); + test_next("2016-03-27 03:17:00 UTC", "", 12345, 1459048620000000); + test_next("2016-03-27 03:17:00 UTC", "CET", 12345, 1459048620000000); + test_next("2016-03-27 03:17:00 UTC", "EET", 12345, 1459048620000000); + test_next("2016-03-27 03:17:00.420000001 UTC", "EET", 12345, 1459048620420000); + test_next("2016-03-27 03:17:00.4200005 UTC", "EET", 12345, 1459048620420001); + test_next("2015-11-13 09:11:23.42", "EET", 12345, 1447398683420000); + test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683420000, 1447398685190000); + test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683419999, 1447398683420000); + test_next("Sun 16:00:00", "CET", 1456041600123456, 1456066800000000); + test_next("*-04-31", "", 12345, -1); + test_next("2016-02~01 UTC", "", 12345, 1456704000000000); + test_next("Mon 2017-05~01..07 UTC", "", 12345, 1496016000000000); + test_next("Mon 2017-05~07/1 UTC", "", 12345, 1496016000000000); + test_next("2017-08-06 9,11,13,15,17:00 UTC", "", 1502029800000000, 1502031600000000); + test_next("2017-08-06 9..17/2:00 UTC", "", 1502029800000000, 1502031600000000); + test_next("2016-12-* 3..21/6:00 UTC", "", 1482613200000001, 1482634800000000); + test_next("2017-09-24 03:30:00 Pacific/Auckland", "", 12345, 1506177000000000); + // Due to daylight saving time - 2017-09-24 02:30:00 does not exist + test_next("2017-09-24 02:30:00 Pacific/Auckland", "", 12345, -1); + test_next("2017-04-02 02:30:00 Pacific/Auckland", "", 12345, 1491053400000000); + // Confirm that even though it's a time change here (backward) 02:30 happens only once + test_next("2017-04-02 02:30:00 Pacific/Auckland", "", 1491053400000000, -1); + test_next("2017-04-02 03:30:00 Pacific/Auckland", "", 12345, 1491060600000000); + // Confirm that timezones in the Spec work regardless of current timezone + test_next("2017-09-09 20:42:00 Pacific/Auckland", "", 12345, 1504946520000000); + test_next("2017-09-09 20:42:00 Pacific/Auckland", "EET", 12345, 1504946520000000); + + assert_se(calendar_spec_from_string("test", &c) < 0); + assert_se(calendar_spec_from_string(" utc", &c) < 0); + assert_se(calendar_spec_from_string(" ", &c) < 0); + assert_se(calendar_spec_from_string("", &c) < 0); + assert_se(calendar_spec_from_string("7", &c) < 0); + assert_se(calendar_spec_from_string("121212:1:2", &c) < 0); + assert_se(calendar_spec_from_string("2000-03-05.23 00:00:00", &c) < 0); + assert_se(calendar_spec_from_string("2000-03-05 00:00.1:00", &c) < 0); + assert_se(calendar_spec_from_string("00:00:00/0.00000001", &c) < 0); + assert_se(calendar_spec_from_string("00:00:00.0..00.9", &c) < 0); + assert_se(calendar_spec_from_string("2016~11-22", &c) < 0); + assert_se(calendar_spec_from_string("*-*~5/5", &c) < 0); + assert_se(calendar_spec_from_string("Monday.. 12:00", &c) < 0); + assert_se(calendar_spec_from_string("Monday..", &c) < 0); + assert_se(calendar_spec_from_string("-00:+00/-5", &c) < 0); + assert_se(calendar_spec_from_string("00:+00/-5", &c) < 0); + assert_se(calendar_spec_from_string("2016- 11- 24 12: 30: 00", &c) < 0); + assert_se(calendar_spec_from_string("*~29", &c) < 0); + assert_se(calendar_spec_from_string("*~16..31", &c) < 0); + assert_se(calendar_spec_from_string("12..1/2-*", &c) < 0); + assert_se(calendar_spec_from_string("*:05..05", &c) < 0); + assert_se(calendar_spec_from_string("*:05..10/6", &c) < 0); + assert_se(calendar_spec_from_string("20/4:00", &c) < 0); + assert_se(calendar_spec_from_string("00:00/60", &c) < 0); + assert_se(calendar_spec_from_string("00:00:2300", &c) < 0); + assert_se(calendar_spec_from_string("00:00:18446744073709551615", &c) < 0); + assert_se(calendar_spec_from_string("@88588582097858858", &c) == -ERANGE); + + test_timestamp(); + test_hourly_bug_4031(); + + return 0; +} diff --git a/src/test/test-cap-list.c b/src/test/test-cap-list.c new file mode 100644 index 00000000..563b9969 --- /dev/null +++ b/src/test/test-cap-list.c @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "cap-list.h" +#include "capability-util.h" +#include "parse-util.h" +#include "string-util.h" +#include "util.h" + +/* verify the capability parser */ +static void test_cap_list(void) { + int i; + + assert_se(!capability_to_name(-1)); + assert_se(!capability_to_name(capability_list_length())); + + for (i = 0; i < capability_list_length(); i++) { + const char *n; + + assert_se(n = capability_to_name(i)); + assert_se(capability_from_name(n) == i); + printf("%s = %i\n", n, i); + } + + assert_se(capability_from_name("asdfbsd") == -EINVAL); + assert_se(capability_from_name("CAP_AUDIT_READ") == CAP_AUDIT_READ); + assert_se(capability_from_name("cap_audit_read") == CAP_AUDIT_READ); + assert_se(capability_from_name("cAp_aUdIt_rEAd") == CAP_AUDIT_READ); + assert_se(capability_from_name("0") == 0); + assert_se(capability_from_name("15") == 15); + assert_se(capability_from_name("-1") == -EINVAL); + + for (i = 0; i < capability_list_length(); i++) { + _cleanup_cap_free_charp_ char *a = NULL; + const char *b; + unsigned u; + + assert_se(a = cap_to_name(i)); + + /* quit the loop as soon as libcap starts returning + * numeric ids, formatted as strings */ + if (safe_atou(a, &u) >= 0) + break; + + assert_se(b = capability_to_name(i)); + + printf("%s vs. %s\n", a, b); + + assert_se(strcasecmp(a, b) == 0); + } +} + +static void test_capability_set_one(uint64_t c, const char *t) { + _cleanup_free_ char *t1 = NULL; + uint64_t c1, c_masked = c & ((UINT64_C(1) << capability_list_length()) - 1); + + assert_se(capability_set_to_string_alloc(c, &t1) == 0); + assert_se(streq(t1, t)); + + assert_se(capability_set_from_string(t1, &c1) == 0); + assert_se(c1 == c_masked); + + free(t1); + assert_se(t1 = strjoin("'cap_chown cap_dac_override' \"cap_setgid cap_setuid\"", t, + " hogehoge foobar 12345 3.14 -3 ", t)); + assert_se(capability_set_from_string(t1, &c1) == 0); + assert_se(c1 == c_masked); +} + +static void test_capability_set(void) { + uint64_t c; + + assert_se(capability_set_from_string(NULL, &c) == 0); + assert_se(c == 0); + + assert_se(capability_set_from_string("", &c) == 0); + assert_se(c == 0); + + assert_se(capability_set_from_string("0", &c) == 0); + assert_se(c == UINT64_C(1)); + + assert_se(capability_set_from_string("1", &c) == 0); + assert_se(c == UINT64_C(1) << 1); + + assert_se(capability_set_from_string("0 1 2 3", &c) == 0); + assert_se(c == (UINT64_C(1) << 4) - 1); + + test_capability_set_one(0, ""); + test_capability_set_one( + UINT64_C(1) << CAP_DAC_OVERRIDE, + "cap_dac_override"); + test_capability_set_one( + UINT64_C(1) << CAP_DAC_OVERRIDE | + UINT64_C(1) << capability_list_length(), + "cap_dac_override"); + test_capability_set_one( + UINT64_C(1) << capability_list_length(), ""); + test_capability_set_one( + UINT64_C(1) << CAP_CHOWN | + UINT64_C(1) << CAP_DAC_OVERRIDE | + UINT64_C(1) << CAP_DAC_READ_SEARCH | + UINT64_C(1) << CAP_FOWNER | + UINT64_C(1) << CAP_SETGID | + UINT64_C(1) << CAP_SETUID | + UINT64_C(1) << CAP_SYS_PTRACE | + UINT64_C(1) << CAP_SYS_ADMIN | + UINT64_C(1) << CAP_AUDIT_CONTROL | + UINT64_C(1) << CAP_MAC_OVERRIDE | + UINT64_C(1) << CAP_SYSLOG | + UINT64_C(1) << (capability_list_length() + 1), + "cap_chown cap_dac_override cap_dac_read_search cap_fowner " + "cap_setgid cap_setuid cap_sys_ptrace cap_sys_admin " + "cap_audit_control cap_mac_override cap_syslog"); +} + +int main(int argc, char *argv[]) { + test_cap_list(); + test_capability_set(); + + return 0; +} diff --git a/src/test/test-capability.c b/src/test/test-capability.c new file mode 100644 index 00000000..295136e1 --- /dev/null +++ b/src/test/test-capability.c @@ -0,0 +1,265 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "capability-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "macro.h" +#include "missing_prctl.h" +#include "parse-util.h" +#include "string-util.h" +#include "tests.h" + +static uid_t test_uid = -1; +static gid_t test_gid = -1; + +#if HAS_FEATURE_ADDRESS_SANITIZER +/* Keep CAP_SYS_PTRACE when running under Address Sanitizer */ +static const uint64_t test_flags = UINT64_C(1) << CAP_SYS_PTRACE; +#else +/* We keep CAP_DAC_OVERRIDE to avoid errors with gcov when doing test coverage */ +static const uint64_t test_flags = UINT64_C(1) << CAP_DAC_OVERRIDE; +#endif + +/* verify cap_last_cap() against /proc/sys/kernel/cap_last_cap */ +static void test_last_cap_file(void) { + _cleanup_free_ char *content = NULL; + unsigned long val = 0; + int r; + + r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content); + assert_se(r >= 0); + + r = safe_atolu(content, &val); + assert_se(r >= 0); + assert_se(val != 0); + assert_se(val == cap_last_cap()); +} + +/* verify cap_last_cap() against syscall probing */ +static void test_last_cap_probe(void) { + unsigned long p = (unsigned long)CAP_LAST_CAP; + + if (prctl(PR_CAPBSET_READ, p) < 0) { + for (p--; p > 0; p --) + if (prctl(PR_CAPBSET_READ, p) >= 0) + break; + } else { + for (;; p++) + if (prctl(PR_CAPBSET_READ, p+1) < 0) + break; + } + + assert_se(p != 0); + assert_se(p == cap_last_cap()); +} + +static void fork_test(void (*test_func)(void)) { + pid_t pid = 0; + + pid = fork(); + assert_se(pid >= 0); + if (pid == 0) { + test_func(); + exit(EXIT_SUCCESS); + } else if (pid > 0) { + int status; + + assert_se(waitpid(pid, &status, 0) > 0); + assert_se(WIFEXITED(status) && WEXITSTATUS(status) == 0); + } +} + +static void show_capabilities(void) { + cap_t caps; + char *text; + + caps = cap_get_proc(); + assert_se(caps); + + text = cap_to_text(caps, NULL); + assert_se(text); + + log_info("Capabilities:%s", text); + cap_free(caps); + cap_free(text); +} + +static int setup_tests(bool *run_ambient) { + struct passwd *nobody; + int r; + + nobody = getpwnam(NOBODY_USER_NAME); + if (!nobody) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Could not find nobody user: %m"); + + test_uid = nobody->pw_uid; + test_gid = nobody->pw_gid; + + *run_ambient = false; + + r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); + + /* There's support for PR_CAP_AMBIENT if the prctl() call + * succeeded or error code was something else than EINVAL. The + * EINVAL check should be good enough to rule out false + * positives. */ + + if (r >= 0 || errno != EINVAL) + *run_ambient = true; + + return 0; +} + +static void test_drop_privileges_keep_net_raw(void) { + int sock; + + sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); + assert_se(sock >= 0); + safe_close(sock); + + assert_se(drop_privileges(test_uid, test_gid, test_flags | (1ULL << CAP_NET_RAW)) >= 0); + assert_se(getuid() == test_uid); + assert_se(getgid() == test_gid); + show_capabilities(); + + sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); + assert_se(sock >= 0); + safe_close(sock); +} + +static void test_drop_privileges_dontkeep_net_raw(void) { + int sock; + + sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); + assert_se(sock >= 0); + safe_close(sock); + + assert_se(drop_privileges(test_uid, test_gid, test_flags) >= 0); + assert_se(getuid() == test_uid); + assert_se(getgid() == test_gid); + show_capabilities(); + + sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP); + assert_se(sock < 0); +} + +static void test_drop_privileges_fail(void) { + assert_se(drop_privileges(test_uid, test_gid, test_flags) >= 0); + assert_se(getuid() == test_uid); + assert_se(getgid() == test_gid); + + assert_se(drop_privileges(test_uid, test_gid, test_flags) < 0); + assert_se(drop_privileges(0, 0, test_flags) < 0); +} + +static void test_drop_privileges(void) { + fork_test(test_drop_privileges_keep_net_raw); + fork_test(test_drop_privileges_dontkeep_net_raw); + fork_test(test_drop_privileges_fail); +} + +static void test_have_effective_cap(void) { + assert_se(have_effective_cap(CAP_KILL)); + assert_se(have_effective_cap(CAP_CHOWN)); + + assert_se(drop_privileges(test_uid, test_gid, test_flags | (1ULL << CAP_KILL)) >= 0); + assert_se(getuid() == test_uid); + assert_se(getgid() == test_gid); + + assert_se(have_effective_cap(CAP_KILL)); + assert_se(!have_effective_cap(CAP_CHOWN)); +} + +static void test_update_inherited_set(void) { + cap_t caps; + uint64_t set = 0; + cap_flag_value_t fv; + + caps = cap_get_proc(); + assert_se(caps); + + set = (UINT64_C(1) << CAP_CHOWN); + + assert_se(!capability_update_inherited_set(caps, set)); + assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv)); + assert(fv == CAP_SET); + + cap_free(caps); +} + +static void test_set_ambient_caps(void) { + cap_t caps; + uint64_t set = 0; + cap_flag_value_t fv; + + assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 0); + + set = (UINT64_C(1) << CAP_CHOWN); + + assert_se(!capability_ambient_set_apply(set, true)); + + caps = cap_get_proc(); + assert_se(!cap_get_flag(caps, CAP_CHOWN, CAP_INHERITABLE, &fv)); + assert(fv == CAP_SET); + cap_free(caps); + + assert_se(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) == 1); +} + +static void test_ensure_cap_64bit(void) { + _cleanup_free_ char *content = NULL; + unsigned long p = 0; + int r; + + r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content); + if (r == -ENOENT) /* kernel pre 3.2 */ + return; + assert_se(r >= 0); + + assert_se(safe_atolu(content, &p) >= 0); + + /* If caps don't fit into 64bit anymore, we have a problem, fail the test. */ + assert_se(p <= 63); + + /* Also check for the header definition */ + assert_se(CAP_LAST_CAP <= 63); +} + +int main(int argc, char *argv[]) { + bool run_ambient; + + test_setup_logging(LOG_INFO); + + test_ensure_cap_64bit(); + + test_last_cap_file(); + test_last_cap_probe(); + + log_info("have ambient caps: %s", yes_no(ambient_capabilities_supported())); + + if (getuid() != 0) + return log_tests_skipped("not running as root"); + + if (setup_tests(&run_ambient) < 0) + return log_tests_skipped("setup failed"); + + show_capabilities(); + + test_drop_privileges(); + test_update_inherited_set(); + + fork_test(test_have_effective_cap); + + if (run_ambient) + fork_test(test_set_ambient_caps); + + return 0; +} diff --git a/src/test/test-cgroup-cpu.c b/src/test/test-cgroup-cpu.c new file mode 100644 index 00000000..a445acc9 --- /dev/null +++ b/src/test/test-cgroup-cpu.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "cgroup.h" +#include "log.h" + +static void test_cgroup_cpu_adjust_period(void) { + log_info("/* %s */", __func__); + + /* Period 1ms, quota 40% -> Period 2.5ms */ + assert_se(2500 == cgroup_cpu_adjust_period(USEC_PER_MSEC, 400 * USEC_PER_MSEC, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 10ms, quota 10% -> keep. */ + assert_se(10 * USEC_PER_MSEC == cgroup_cpu_adjust_period(10 * USEC_PER_MSEC, 100 * USEC_PER_MSEC, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 1ms, quota 1000% -> keep. */ + assert_se(USEC_PER_MSEC == cgroup_cpu_adjust_period(USEC_PER_MSEC, 10000 * USEC_PER_MSEC, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 100ms, quota 30% -> keep. */ + assert_se(100 * USEC_PER_MSEC == cgroup_cpu_adjust_period(100 * USEC_PER_MSEC, 300 * USEC_PER_MSEC, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 5s, quota 40% -> adjust to 1s. */ + assert_se(USEC_PER_SEC == cgroup_cpu_adjust_period(5 * USEC_PER_SEC, 400 * USEC_PER_MSEC, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 2s, quota 250% -> adjust to 1s. */ + assert_se(USEC_PER_SEC == cgroup_cpu_adjust_period(2 * USEC_PER_SEC, 2500 * USEC_PER_MSEC, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 10us, quota 5,000,000% -> adjust to 1ms. */ + assert_se(USEC_PER_MSEC == cgroup_cpu_adjust_period(10, 50000000 * USEC_PER_MSEC, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 10ms, quota 50,000% -> keep. */ + assert_se(10 * USEC_PER_MSEC == cgroup_cpu_adjust_period(10 * USEC_PER_MSEC, 500000 * USEC_PER_MSEC, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 10ms, quota 1% -> adjust to 100ms. */ + assert_se(100 * USEC_PER_MSEC == cgroup_cpu_adjust_period(10 * USEC_PER_MSEC, 10 * USEC_PER_MSEC, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 10ms, quota .001% -> adjust to 1s. */ + assert_se(1 * USEC_PER_SEC == cgroup_cpu_adjust_period(10 * USEC_PER_MSEC, 10, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 0ms, quota 200% -> adjust to 1ms. */ + assert_se(1 * USEC_PER_MSEC == cgroup_cpu_adjust_period(0, 2 * USEC_PER_SEC, USEC_PER_MSEC, USEC_PER_SEC)); + /* Period 0ms, quota 40% -> adjust to 2.5ms. */ + assert_se(2500 == cgroup_cpu_adjust_period(0, 400 * USEC_PER_MSEC, USEC_PER_MSEC, USEC_PER_SEC)); +} + +int main(int argc, char *argv[]) { + test_cgroup_cpu_adjust_period(); + return 0; +} diff --git a/src/test/test-cgroup-mask.c b/src/test/test-cgroup-mask.c new file mode 100644 index 00000000..02c8549b --- /dev/null +++ b/src/test/test-cgroup-mask.c @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "cgroup.h" +#include "cgroup-util.h" +#include "macro.h" +#include "manager.h" +#include "rm-rf.h" +#include "string-util.h" +#include "tests.h" +#include "unit.h" + +#define ASSERT_CGROUP_MASK(got, expected) \ + log_cgroup_mask(got, expected); \ + assert_se(got == expected) + +#define ASSERT_CGROUP_MASK_JOINED(got, expected) ASSERT_CGROUP_MASK(got, CGROUP_MASK_EXTEND_JOINED(expected)) + +static void log_cgroup_mask(CGroupMask got, CGroupMask expected) { + _cleanup_free_ char *e_store = NULL, *g_store = NULL; + + assert_se(cg_mask_to_string(expected, &e_store) >= 0); + log_info("Expected mask: %s\n", e_store); + assert_se(cg_mask_to_string(got, &g_store) >= 0); + log_info("Got mask: %s\n", g_store); +} + +static int test_cgroup_mask(void) { + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + Unit *son, *daughter, *parent, *root, *grandchild, *parent_deep, *nomem_parent, *nomem_leaf; + int r; + CGroupMask cpu_accounting_mask = get_cpu_accounting_mask(); + + r = enter_cgroup_subroot(NULL); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + /* Prepare the manager. */ + assert_se(set_unit_path(get_testdata_dir()) >= 0); + assert_se(runtime_dir = setup_fake_runtime_dir()); + r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m); + if (IN_SET(r, -EPERM, -EACCES)) { + log_error_errno(r, "manager_new: %m"); + return log_tests_skipped("cannot create manager"); + } + + assert_se(r >= 0); + + /* Turn off all kinds of default accouning, so that we can + * verify the masks resulting of our configuration and nothing + * else. */ + m->default_cpu_accounting = + m->default_memory_accounting = + m->default_blockio_accounting = + m->default_io_accounting = + m->default_tasks_accounting = false; + m->default_tasks_max = TASKS_MAX_UNSET; + + assert_se(manager_startup(m, NULL, NULL) >= 0); + + /* Load units and verify hierarchy. */ + assert_se(manager_load_startable_unit_or_warn(m, "parent.slice", NULL, &parent) >= 0); + assert_se(manager_load_startable_unit_or_warn(m, "son.service", NULL, &son) >= 0); + assert_se(manager_load_startable_unit_or_warn(m, "daughter.service", NULL, &daughter) >= 0); + assert_se(manager_load_startable_unit_or_warn(m, "grandchild.service", NULL, &grandchild) >= 0); + assert_se(manager_load_startable_unit_or_warn(m, "parent-deep.slice", NULL, &parent_deep) >= 0); + assert_se(manager_load_startable_unit_or_warn(m, "nomem.slice", NULL, &nomem_parent) >= 0); + assert_se(manager_load_startable_unit_or_warn(m, "nomemleaf.service", NULL, &nomem_leaf) >= 0); + assert_se(UNIT_DEREF(son->slice) == parent); + assert_se(UNIT_DEREF(daughter->slice) == parent); + assert_se(UNIT_DEREF(parent_deep->slice) == parent); + assert_se(UNIT_DEREF(grandchild->slice) == parent_deep); + assert_se(UNIT_DEREF(nomem_leaf->slice) == nomem_parent); + root = UNIT_DEREF(parent->slice); + assert_se(UNIT_DEREF(nomem_parent->slice) == root); + + /* Verify per-unit cgroups settings. */ + ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(son), CGROUP_MASK_CPU); + ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(daughter), cpu_accounting_mask); + ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(grandchild), 0); + ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(parent_deep), CGROUP_MASK_MEMORY); + ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO)); + ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(nomem_parent), 0); + ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO)); + ASSERT_CGROUP_MASK_JOINED(unit_get_own_mask(root), 0); + + /* Verify aggregation of member masks */ + ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(son), 0); + ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(daughter), 0); + ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(grandchild), 0); + ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent_deep), 0); + ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(parent), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY)); + ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO)); + ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(nomem_leaf), 0); + ASSERT_CGROUP_MASK_JOINED(unit_get_members_mask(root), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); + + /* Verify aggregation of sibling masks. */ + ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(son), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY)); + ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(daughter), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY)); + ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(grandchild), 0); + ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent_deep), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY)); + ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(parent), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); + ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_parent), (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); + ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO)); + ASSERT_CGROUP_MASK_JOINED(unit_get_siblings_mask(root), (CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY)); + + /* Verify aggregation of target masks. */ + ASSERT_CGROUP_MASK(unit_get_target_mask(son), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported)); + ASSERT_CGROUP_MASK(unit_get_target_mask(daughter), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported)); + ASSERT_CGROUP_MASK(unit_get_target_mask(grandchild), 0); + ASSERT_CGROUP_MASK(unit_get_target_mask(parent_deep), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_MEMORY) & m->cgroup_supported)); + ASSERT_CGROUP_MASK(unit_get_target_mask(parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); + ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_parent), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT | CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported)); + ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_leaf), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported)); + ASSERT_CGROUP_MASK(unit_get_target_mask(root), (CGROUP_MASK_EXTEND_JOINED(CGROUP_MASK_CPU | cpu_accounting_mask | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); + + return 0; +} + +static void test_cg_mask_to_string_one(CGroupMask mask, const char *t) { + _cleanup_free_ char *b = NULL; + + assert_se(cg_mask_to_string(mask, &b) >= 0); + assert_se(streq_ptr(b, t)); +} + +static void test_cg_mask_to_string(void) { + test_cg_mask_to_string_one(0, NULL); + test_cg_mask_to_string_one(_CGROUP_MASK_ALL, "cpu cpuacct cpuset io blkio memory devices pids bpf-firewall bpf-devices"); + test_cg_mask_to_string_one(CGROUP_MASK_CPU, "cpu"); + test_cg_mask_to_string_one(CGROUP_MASK_CPUACCT, "cpuacct"); + test_cg_mask_to_string_one(CGROUP_MASK_CPUSET, "cpuset"); + test_cg_mask_to_string_one(CGROUP_MASK_IO, "io"); + test_cg_mask_to_string_one(CGROUP_MASK_BLKIO, "blkio"); + test_cg_mask_to_string_one(CGROUP_MASK_MEMORY, "memory"); + test_cg_mask_to_string_one(CGROUP_MASK_DEVICES, "devices"); + test_cg_mask_to_string_one(CGROUP_MASK_PIDS, "pids"); + test_cg_mask_to_string_one(CGROUP_MASK_CPU|CGROUP_MASK_CPUACCT, "cpu cpuacct"); + test_cg_mask_to_string_one(CGROUP_MASK_CPU|CGROUP_MASK_PIDS, "cpu pids"); + test_cg_mask_to_string_one(CGROUP_MASK_CPUACCT|CGROUP_MASK_PIDS, "cpuacct pids"); + test_cg_mask_to_string_one(CGROUP_MASK_DEVICES|CGROUP_MASK_PIDS, "devices pids"); + test_cg_mask_to_string_one(CGROUP_MASK_IO|CGROUP_MASK_BLKIO, "io blkio"); +} + +int main(int argc, char* argv[]) { + int rc = EXIT_SUCCESS; + + test_setup_logging(LOG_DEBUG); + + test_cg_mask_to_string(); + TEST_REQ_RUNNING_SYSTEMD(rc = test_cgroup_mask()); + + return rc; +} diff --git a/src/test/test-cgroup-setup.c b/src/test/test-cgroup-setup.c new file mode 100644 index 00000000..330631a9 --- /dev/null +++ b/src/test/test-cgroup-setup.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "build.h" +#include "cgroup-setup.h" +#include "log.h" +#include "proc-cmdline.h" +#include "string-util.h" +#include "tests.h" + +static void test_is_wanted_print(bool header) { + _cleanup_free_ char *cmdline = NULL; + + log_info("-- %s --", __func__); + assert_se(proc_cmdline(&cmdline) >= 0); + log_info("cmdline: %s", cmdline); + if (header) { + log_info(_CGROUP_HIERARCHY_); + (void) system("findmnt -n /sys/fs/cgroup"); + } + + log_info("is_unified_wanted() → %s", yes_no(cg_is_unified_wanted())); + log_info("is_hybrid_wanted() → %s", yes_no(cg_is_hybrid_wanted())); + log_info("is_legacy_wanted() → %s", yes_no(cg_is_legacy_wanted())); + log_info(" "); +} + +static void test_is_wanted(void) { + assert_se(setenv("SYSTEMD_PROC_CMDLINE", + "systemd.unified_cgroup_hierarchy", 1) >= 0); + test_is_wanted_print(false); + + assert_se(setenv("SYSTEMD_PROC_CMDLINE", + "systemd.unified_cgroup_hierarchy=0", 1) >= 0); + test_is_wanted_print(false); + + assert_se(setenv("SYSTEMD_PROC_CMDLINE", + "systemd.unified_cgroup_hierarchy=0 " + "systemd.legacy_systemd_cgroup_controller", 1) >= 0); + test_is_wanted_print(false); + + assert_se(setenv("SYSTEMD_PROC_CMDLINE", + "systemd.unified_cgroup_hierarchy=0 " + "systemd.legacy_systemd_cgroup_controller=0", 1) >= 0); + test_is_wanted_print(false); + + /* cgroup_no_v1=all implies unified cgroup hierarchy, unless otherwise + * explicitly specified. */ + assert_se(setenv("SYSTEMD_PROC_CMDLINE", + "cgroup_no_v1=all", 1) >= 0); + test_is_wanted_print(false); + + assert_se(setenv("SYSTEMD_PROC_CMDLINE", + "cgroup_no_v1=all " + "systemd.unified_cgroup_hierarchy=0", 1) >= 0); + test_is_wanted_print(false); +} + +int main(void) { + test_setup_logging(LOG_DEBUG); + + test_is_wanted_print(true); + test_is_wanted_print(false); /* run twice to test caching */ + test_is_wanted(); + + return 0; +} diff --git a/src/test/test-cgroup-unit-default.c b/src/test/test-cgroup-unit-default.c new file mode 100644 index 00000000..1286f11e --- /dev/null +++ b/src/test/test-cgroup-unit-default.c @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "cgroup.h" +#include "manager.h" +#include "rm-rf.h" +#include "tests.h" +#include "unit.h" + +static int test_default_memory_low(void) { + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + Unit *root, *dml, + *dml_passthrough, *dml_passthrough_empty, *dml_passthrough_set_dml, *dml_passthrough_set_ml, + *dml_override, *dml_override_empty, + *dml_discard, *dml_discard_empty, *dml_discard_set_ml; + uint64_t dml_tree_default; + int r; + + r = enter_cgroup_subroot(NULL); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + assert_se(set_unit_path(get_testdata_dir()) >= 0); + assert_se(runtime_dir = setup_fake_runtime_dir()); + r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m); + if (IN_SET(r, -EPERM, -EACCES)) { + log_error_errno(r, "manager_new: %m"); + return log_tests_skipped("cannot create manager"); + } + + assert_se(r >= 0); + assert_se(manager_startup(m, NULL, NULL) >= 0); + + /* dml.slice has DefaultMemoryLow=50. Beyond that, individual subhierarchies look like this: + * + * 1. dml-passthrough.slice sets MemoryLow=100. This should not affect its children, as only + * DefaultMemoryLow is propagated, not MemoryLow. As such, all leaf services should end up with + * memory.low as 50, inherited from dml.slice, *except* for dml-passthrough-set-ml.service, which + * should have the value of 0, as it has MemoryLow explicitly set. + * + * ┌───────────┐ + * │ dml.slice │ + * └─────┬─────┘ + * MemoryLow=100 + * ┌───────────┴───────────┐ + * │ dml-passthrough.slice │ + * └───────────┬───────────┘ + * ┌───────────────────────────────────┼───────────────────────────────────┐ + * no new settings DefaultMemoryLow=15 MemoryLow=0 + * ┌───────────────┴───────────────┐ ┌────────────────┴────────────────┐ ┌───────────────┴────────────────┐ + * │ dml-passthrough-empty.service │ │ dml-passthrough-set-dml.service │ │ dml-passthrough-set-ml.service │ + * └───────────────────────────────┘ └─────────────────────────────────┘ └────────────────────────────────┘ + * + * 2. dml-override.slice sets DefaultMemoryLow=10. As such, dml-override-empty.service should also + * end up with a memory.low of 10. dml-override.slice should still have a memory.low of 50. + * + * ┌───────────┐ + * │ dml.slice │ + * └─────┬─────┘ + * DefaultMemoryLow=10 + * ┌─────────┴──────────┐ + * │ dml-override.slice │ + * └─────────┬──────────┘ + * no new settings + * ┌─────────────┴──────────────┐ + * │ dml-override-empty.service │ + * └────────────────────────────┘ + * + * 3. dml-discard.slice sets DefaultMemoryLow= with no rvalue. As such, + * dml-discard-empty.service should end up with a value of 0. + * dml-discard-explicit-ml.service sets MemoryLow=70, and as such should have that override the + * reset DefaultMemoryLow value. dml-discard.slice should still have an eventual memory.low of 50. + * + * ┌───────────┐ + * │ dml.slice │ + * └─────┬─────┘ + * DefaultMemoryLow= + * ┌─────────┴─────────┐ + * │ dml-discard.slice │ + * └─────────┬─────────┘ + * ┌──────────────┴───────────────┐ + * no new settings MemoryLow=15 + * ┌─────────────┴─────────────┐ ┌─────────────┴──────────────┐ + * │ dml-discard-empty.service │ │ dml-discard-set-ml.service │ + * └───────────────────────────┘ └────────────────────────────┘ + */ + assert_se(manager_load_startable_unit_or_warn(m, "dml.slice", NULL, &dml) >= 0); + + assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough.slice", NULL, &dml_passthrough) >= 0); + assert_se(UNIT_DEREF(dml_passthrough->slice) == dml); + assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-empty.service", NULL, &dml_passthrough_empty) >= 0); + assert_se(UNIT_DEREF(dml_passthrough_empty->slice) == dml_passthrough); + assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-set-dml.service", NULL, &dml_passthrough_set_dml) >= 0); + assert_se(UNIT_DEREF(dml_passthrough_set_dml->slice) == dml_passthrough); + assert_se(manager_load_startable_unit_or_warn(m, "dml-passthrough-set-ml.service", NULL, &dml_passthrough_set_ml) >= 0); + assert_se(UNIT_DEREF(dml_passthrough_set_ml->slice) == dml_passthrough); + + assert_se(manager_load_startable_unit_or_warn(m, "dml-override.slice", NULL, &dml_override) >= 0); + assert_se(UNIT_DEREF(dml_override->slice) == dml); + assert_se(manager_load_startable_unit_or_warn(m, "dml-override-empty.service", NULL, &dml_override_empty) >= 0); + assert_se(UNIT_DEREF(dml_override_empty->slice) == dml_override); + + assert_se(manager_load_startable_unit_or_warn(m, "dml-discard.slice", NULL, &dml_discard) >= 0); + assert_se(UNIT_DEREF(dml_discard->slice) == dml); + assert_se(manager_load_startable_unit_or_warn(m, "dml-discard-empty.service", NULL, &dml_discard_empty) >= 0); + assert_se(UNIT_DEREF(dml_discard_empty->slice) == dml_discard); + assert_se(manager_load_startable_unit_or_warn(m, "dml-discard-set-ml.service", NULL, &dml_discard_set_ml) >= 0); + assert_se(UNIT_DEREF(dml_discard_set_ml->slice) == dml_discard); + + root = UNIT_DEREF(dml->slice); + assert_se(!UNIT_ISSET(root->slice)); + + assert_se(unit_get_ancestor_memory_low(root) == CGROUP_LIMIT_MIN); + + assert_se(unit_get_ancestor_memory_low(dml) == CGROUP_LIMIT_MIN); + dml_tree_default = unit_get_cgroup_context(dml)->default_memory_low; + assert_se(dml_tree_default == 50); + + assert_se(unit_get_ancestor_memory_low(dml_passthrough) == 100); + assert_se(unit_get_ancestor_memory_low(dml_passthrough_empty) == dml_tree_default); + assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_dml) == 50); + assert_se(unit_get_ancestor_memory_low(dml_passthrough_set_ml) == 0); + + assert_se(unit_get_ancestor_memory_low(dml_override) == dml_tree_default); + assert_se(unit_get_ancestor_memory_low(dml_override_empty) == 10); + + assert_se(unit_get_ancestor_memory_low(dml_discard) == dml_tree_default); + assert_se(unit_get_ancestor_memory_low(dml_discard_empty) == CGROUP_LIMIT_MIN); + assert_se(unit_get_ancestor_memory_low(dml_discard_set_ml) == 15); + + return 0; +} + +int main(int argc, char* argv[]) { + int rc = EXIT_SUCCESS; + + test_setup_logging(LOG_DEBUG); + + TEST_REQ_RUNNING_SYSTEMD(rc = test_default_memory_low()); + + return rc; +} diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c new file mode 100644 index 00000000..83b5156c --- /dev/null +++ b/src/test/test-cgroup-util.c @@ -0,0 +1,434 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "build.h" +#include "cgroup-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "parse-util.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "special.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "user-util.h" +#include "util.h" + +static void check_p_d_u(const char *path, int code, const char *result) { + _cleanup_free_ char *unit = NULL; + int r; + + r = cg_path_decode_unit(path, &unit); + printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code); + assert_se(r == code); + assert_se(streq_ptr(unit, result)); +} + +static void test_path_decode_unit(void) { + check_p_d_u("getty@tty2.service", 0, "getty@tty2.service"); + check_p_d_u("getty@tty2.service/", 0, "getty@tty2.service"); + check_p_d_u("getty@tty2.service/xxx", 0, "getty@tty2.service"); + check_p_d_u("getty@.service/", -ENXIO, NULL); + check_p_d_u("getty@.service", -ENXIO, NULL); + check_p_d_u("getty.service", 0, "getty.service"); + check_p_d_u("getty", -ENXIO, NULL); + check_p_d_u("getty/waldo", -ENXIO, NULL); + check_p_d_u("_cpu.service", 0, "cpu.service"); +} + +static void check_p_g_u(const char *path, int code, const char *result) { + _cleanup_free_ char *unit = NULL; + int r; + + r = cg_path_get_unit(path, &unit); + printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code); + assert_se(r == code); + assert_se(streq_ptr(unit, result)); +} + +static void test_path_get_unit(void) { + check_p_g_u("/system.slice/foobar.service/sdfdsaf", 0, "foobar.service"); + check_p_g_u("/system.slice/getty@tty5.service", 0, "getty@tty5.service"); + check_p_g_u("/system.slice/getty@tty5.service/aaa/bbb", 0, "getty@tty5.service"); + check_p_g_u("/system.slice/getty@tty5.service/", 0, "getty@tty5.service"); + check_p_g_u("/system.slice/getty@tty6.service/tty5", 0, "getty@tty6.service"); + check_p_g_u("sadfdsafsda", -ENXIO, NULL); + check_p_g_u("/system.slice/getty####@tty6.service/xxx", -ENXIO, NULL); + check_p_g_u("/system.slice/system-waldo.slice/foobar.service/sdfdsaf", 0, "foobar.service"); + check_p_g_u("/system.slice/system-waldo.slice/_cpu.service/sdfdsaf", 0, "cpu.service"); + check_p_g_u("/user.slice/user-1000.slice/user@1000.service/server.service", 0, "user@1000.service"); + check_p_g_u("/user.slice/user-1000.slice/user@.service/server.service", -ENXIO, NULL); +} + +static void check_p_g_u_u(const char *path, int code, const char *result) { + _cleanup_free_ char *unit = NULL; + int r; + + r = cg_path_get_user_unit(path, &unit); + printf("%s: %s → %s %d expected %s %d\n", __func__, path, unit, r, result, code); + assert_se(r == code); + assert_se(streq_ptr(unit, result)); +} + +static void test_path_get_user_unit(void) { + check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "foobar.service"); + check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo.slice/foobar.service", 0, "foobar.service"); + check_p_g_u_u("/user.slice/user-1002.slice/session-2.scope/foobar.service/waldo", 0, "foobar.service"); + check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar.service/waldo/uuuux", 0, "foobar.service"); + check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/waldo/waldo/uuuux", -ENXIO, NULL); + check_p_g_u_u("/user.slice/user-1000.slice/session-2.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service"); + check_p_g_u_u("/session-2.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service"); + check_p_g_u_u("/xyz.slice/xyz-waldo.slice/session-77.scope/foobar@pie.service/pa/po", 0, "foobar@pie.service"); + check_p_g_u_u("/meh.service", -ENXIO, NULL); + check_p_g_u_u("/session-3.scope/_cpu.service", 0, "cpu.service"); + check_p_g_u_u("/user.slice/user-1000.slice/user@1000.service/server.service", 0, "server.service"); + check_p_g_u_u("/user.slice/user-1000.slice/user@1000.service/foobar.slice/foobar@pie.service", 0, "foobar@pie.service"); + check_p_g_u_u("/user.slice/user-1000.slice/user@.service/server.service", -ENXIO, NULL); +} + +static void check_p_g_s(const char *path, int code, const char *result) { + _cleanup_free_ char *s = NULL; + + assert_se(cg_path_get_session(path, &s) == code); + assert_se(streq_ptr(s, result)); +} + +static void test_path_get_session(void) { + check_p_g_s("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, "2"); + check_p_g_s("/session-3.scope", 0, "3"); + check_p_g_s("/session-.scope", -ENXIO, NULL); + check_p_g_s("", -ENXIO, NULL); +} + +static void check_p_g_o_u(const char *path, int code, uid_t result) { + uid_t uid = 0; + + assert_se(cg_path_get_owner_uid(path, &uid) == code); + assert_se(uid == result); +} + +static void test_path_get_owner_uid(void) { + check_p_g_o_u("/user.slice/user-1000.slice/session-2.scope/foobar.service", 0, 1000); + check_p_g_o_u("/user.slice/user-1006.slice", 0, 1006); + check_p_g_o_u("", -ENXIO, 0); +} + +static void check_p_g_slice(const char *path, int code, const char *result) { + _cleanup_free_ char *s = NULL; + + assert_se(cg_path_get_slice(path, &s) == code); + assert_se(streq_ptr(s, result)); +} + +static void test_path_get_slice(void) { + check_p_g_slice("/user.slice", 0, "user.slice"); + check_p_g_slice("/foobar", 0, SPECIAL_ROOT_SLICE); + check_p_g_slice("/user.slice/user-waldo.slice", 0, "user-waldo.slice"); + check_p_g_slice("", 0, SPECIAL_ROOT_SLICE); + check_p_g_slice("foobar", 0, SPECIAL_ROOT_SLICE); + check_p_g_slice("foobar.slice", 0, "foobar.slice"); + check_p_g_slice("foo.slice/foo-bar.slice/waldo.service", 0, "foo-bar.slice"); +} + +static void check_p_g_u_slice(const char *path, int code, const char *result) { + _cleanup_free_ char *s = NULL; + + assert_se(cg_path_get_user_slice(path, &s) == code); + assert_se(streq_ptr(s, result)); +} + +static void test_path_get_user_slice(void) { + check_p_g_u_slice("/user.slice", -ENXIO, NULL); + check_p_g_u_slice("/foobar", -ENXIO, NULL); + check_p_g_u_slice("/user.slice/user-waldo.slice", -ENXIO, NULL); + check_p_g_u_slice("", -ENXIO, NULL); + check_p_g_u_slice("foobar", -ENXIO, NULL); + check_p_g_u_slice("foobar.slice", -ENXIO, NULL); + check_p_g_u_slice("foo.slice/foo-bar.slice/waldo.service", -ENXIO, NULL); + + check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service", 0, SPECIAL_ROOT_SLICE); + check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/", 0, SPECIAL_ROOT_SLICE); + check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service///", 0, SPECIAL_ROOT_SLICE); + check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/waldo.service", 0, SPECIAL_ROOT_SLICE); + check_p_g_u_slice("foo.slice/foo-bar.slice/user@1000.service/piep.slice/foo.service", 0, "piep.slice"); + check_p_g_u_slice("/foo.slice//foo-bar.slice/user@1000.service/piep.slice//piep-pap.slice//foo.service", 0, "piep-pap.slice"); +} + +static void test_get_paths(void) { + _cleanup_free_ char *a = NULL; + + assert_se(cg_get_root_path(&a) >= 0); + log_info("Root = %s", a); +} + +static void test_proc(void) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int r; + + d = opendir("/proc"); + assert_se(d); + + FOREACH_DIRENT(de, d, break) { + _cleanup_free_ char *path = NULL, *path_shifted = NULL, *session = NULL, *unit = NULL, *user_unit = NULL, *machine = NULL, *slice = NULL; + pid_t pid; + uid_t uid = UID_INVALID; + + if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN)) + continue; + + r = parse_pid(de->d_name, &pid); + if (r < 0) + continue; + + if (is_kernel_thread(pid)) + continue; + + cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &path); + cg_pid_get_path_shifted(pid, NULL, &path_shifted); + cg_pid_get_owner_uid(pid, &uid); + cg_pid_get_session(pid, &session); + cg_pid_get_unit(pid, &unit); + cg_pid_get_user_unit(pid, &user_unit); + cg_pid_get_machine_name(pid, &machine); + cg_pid_get_slice(pid, &slice); + + printf(PID_FMT"\t%s\t%s\t"UID_FMT"\t%s\t%s\t%s\t%s\t%s\n", + pid, + path, + path_shifted, + uid, + session, + unit, + user_unit, + machine, + slice); + } +} + +static void test_escape_one(const char *s, const char *r) { + _cleanup_free_ char *b; + + b = cg_escape(s); + assert_se(b); + assert_se(streq(b, r)); + + assert_se(streq(cg_unescape(b), s)); +} + +static void test_escape(void) { + test_escape_one("foobar", "foobar"); + test_escape_one(".foobar", "_.foobar"); + test_escape_one("foobar.service", "foobar.service"); + test_escape_one("cgroup.service", "_cgroup.service"); + test_escape_one("tasks", "_tasks"); + if (access("/sys/fs/cgroup/cpu", F_OK) == 0) + test_escape_one("cpu.service", "_cpu.service"); + test_escape_one("_foobar", "__foobar"); + test_escape_one("", "_"); + test_escape_one("_", "__"); + test_escape_one(".", "_."); +} + +static void test_controller_is_valid(void) { + assert_se(cg_controller_is_valid("foobar")); + assert_se(cg_controller_is_valid("foo_bar")); + assert_se(cg_controller_is_valid("name=foo")); + assert_se(!cg_controller_is_valid("")); + assert_se(!cg_controller_is_valid("name=")); + assert_se(!cg_controller_is_valid("=")); + assert_se(!cg_controller_is_valid("cpu,cpuacct")); + assert_se(!cg_controller_is_valid("_")); + assert_se(!cg_controller_is_valid("_foobar")); + assert_se(!cg_controller_is_valid("tatü")); +} + +static void test_slice_to_path_one(const char *unit, const char *path, int error) { + _cleanup_free_ char *ret = NULL; + int r; + + log_info("unit: %s", unit); + + r = cg_slice_to_path(unit, &ret); + log_info("actual: %s / %d", strnull(ret), r); + log_info("expect: %s / %d", strnull(path), error); + assert_se(r == error); + assert_se(streq_ptr(ret, path)); +} + +static void test_slice_to_path(void) { + test_slice_to_path_one("foobar.slice", "foobar.slice", 0); + test_slice_to_path_one("foobar-waldo.slice", "foobar.slice/foobar-waldo.slice", 0); + test_slice_to_path_one("foobar-waldo.service", NULL, -EINVAL); + test_slice_to_path_one(SPECIAL_ROOT_SLICE, "", 0); + test_slice_to_path_one("--.slice", NULL, -EINVAL); + test_slice_to_path_one("-", NULL, -EINVAL); + test_slice_to_path_one("-foo-.slice", NULL, -EINVAL); + test_slice_to_path_one("-foo.slice", NULL, -EINVAL); + test_slice_to_path_one("foo-.slice", NULL, -EINVAL); + test_slice_to_path_one("foo--bar.slice", NULL, -EINVAL); + test_slice_to_path_one("foo.slice/foo--bar.slice", NULL, -EINVAL); + test_slice_to_path_one("a-b.slice", "a.slice/a-b.slice", 0); + test_slice_to_path_one("a-b-c-d-e.slice", "a.slice/a-b.slice/a-b-c.slice/a-b-c-d.slice/a-b-c-d-e.slice", 0); + + test_slice_to_path_one("foobar@.slice", NULL, -EINVAL); + test_slice_to_path_one("foobar@waldo.slice", NULL, -EINVAL); + test_slice_to_path_one("foobar@waldo.service", NULL, -EINVAL); + test_slice_to_path_one("-foo@-.slice", NULL, -EINVAL); + test_slice_to_path_one("-foo@.slice", NULL, -EINVAL); + test_slice_to_path_one("foo@-.slice", NULL, -EINVAL); + test_slice_to_path_one("foo@@bar.slice", NULL, -EINVAL); + test_slice_to_path_one("foo.slice/foo@@bar.slice", NULL, -EINVAL); +} + +static void test_shift_path_one(const char *raw, const char *root, const char *shifted) { + const char *s = NULL; + + assert_se(cg_shift_path(raw, root, &s) >= 0); + assert_se(streq(s, shifted)); +} + +static void test_shift_path(void) { + + test_shift_path_one("/foobar/waldo", "/", "/foobar/waldo"); + test_shift_path_one("/foobar/waldo", "", "/foobar/waldo"); + test_shift_path_one("/foobar/waldo", "/foobar", "/waldo"); + test_shift_path_one("/foobar/waldo", "/hogehoge", "/foobar/waldo"); +} + +static void test_mask_supported(void) { + + CGroupMask m; + CGroupController c; + + assert_se(cg_mask_supported(&m) >= 0); + + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) + printf("'%s' is supported: %s\n", cgroup_controller_to_string(c), yes_no(m & CGROUP_CONTROLLER_TO_MASK(c))); +} + +static void test_is_cgroup_fs(void) { + struct statfs sfs; + assert_se(statfs("/sys/fs/cgroup", &sfs) == 0); + if (is_temporary_fs(&sfs)) + assert_se(statfs("/sys/fs/cgroup/systemd", &sfs) == 0); + assert_se(is_cgroup_fs(&sfs)); +} + +static void test_fd_is_cgroup_fs(void) { + int fd; + + fd = open("/sys/fs/cgroup", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); + assert_se(fd >= 0); + if (fd_is_temporary_fs(fd)) { + fd = safe_close(fd); + fd = open("/sys/fs/cgroup/systemd", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); + assert_se(fd >= 0); + } + assert_se(fd_is_cgroup_fs(fd)); + fd = safe_close(fd); +} + +static void test_cg_tests(void) { + int all, hybrid, systemd, r; + + r = cg_unified(); + if (r == -ENOMEDIUM) { + log_notice_errno(r, "Skipping cg hierarchy tests: %m"); + return; + } + assert_se(r >= 0); + + all = cg_all_unified(); + assert_se(IN_SET(all, 0, 1)); + + hybrid = cg_hybrid_unified(); + assert_se(IN_SET(hybrid, 0, 1)); + + systemd = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + assert_se(IN_SET(systemd, 0, 1)); + + if (all) { + assert_se(systemd); + assert_se(!hybrid); + + } else if (hybrid) { + assert_se(systemd); + assert_se(!all); + + } else + assert_se(!systemd); +} + +static void test_cg_get_keyed_attribute(void) { + _cleanup_free_ char *val = NULL; + char *vals3[3] = {}, *vals3a[3] = {}; + int i, r; + + r = cg_get_keyed_attribute("cpu", "/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val); + if (r == -ENOMEDIUM) { + log_info_errno(r, "Skipping most of %s, /sys/fs/cgroup not accessible: %m", __func__); + return; + } + + assert_se(r == -ENOENT); + assert_se(val == NULL); + + if (access("/sys/fs/cgroup/init.scope/cpu.stat", R_OK) < 0) { + log_info_errno(errno, "Skipping most of %s, /init.scope/cpu.stat not accessible: %m", __func__); + return; + } + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("no_such_attr"), &val) == -ENXIO); + assert_se(val == NULL); + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec"), &val) == 0); + log_info("cpu /init.scope cpu.stat [usage_usec] → \"%s\"", val); + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "no_such_attr"), vals3) == -ENXIO); + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", STRV_MAKE("usage_usec", "usage_usec"), vals3) == -ENXIO); + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", + STRV_MAKE("usage_usec", "user_usec", "system_usec"), vals3) == 0); + log_info("cpu /init.scope cpu.stat [usage_usec user_usec system_usec] → \"%s\", \"%s\", \"%s\"", + vals3[0], vals3[1], vals3[2]); + + assert_se(cg_get_keyed_attribute("cpu", "/init.scope", "cpu.stat", + STRV_MAKE("system_usec", "user_usec", "usage_usec"), vals3a) == 0); + log_info("cpu /init.scope cpu.stat [system_usec user_usec usage_usec] → \"%s\", \"%s\", \"%s\"", + vals3a[0], vals3a[1], vals3a[2]); + + for (i = 0; i < 3; i++) { + free(vals3[i]); + free(vals3a[i]); + } +} + +int main(void) { + test_setup_logging(LOG_DEBUG); + + test_path_decode_unit(); + test_path_get_unit(); + test_path_get_user_unit(); + test_path_get_session(); + test_path_get_owner_uid(); + test_path_get_slice(); + test_path_get_user_slice(); + TEST_REQ_RUNNING_SYSTEMD(test_get_paths()); + test_proc(); + TEST_REQ_RUNNING_SYSTEMD(test_escape()); + test_controller_is_valid(); + test_slice_to_path(); + test_shift_path(); + TEST_REQ_RUNNING_SYSTEMD(test_mask_supported()); + TEST_REQ_RUNNING_SYSTEMD(test_is_cgroup_fs()); + TEST_REQ_RUNNING_SYSTEMD(test_fd_is_cgroup_fs()); + test_cg_tests(); + test_cg_get_keyed_attribute(); + + return 0; +} diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c new file mode 100644 index 00000000..f16cb291 --- /dev/null +++ b/src/test/test-cgroup.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "cgroup-setup.h" +#include "cgroup-util.h" +#include "path-util.h" +#include "process-util.h" +#include "string-util.h" +#include "util.h" + +int main(int argc, char *argv[]) { + char *path; + char *c, *p; + + assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0); + assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0); + assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0); + assert_se(cg_create(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-c") == 0); + assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0) == 0); + + assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path) == 0); + assert_se(streq(path, "/test-b")); + free(path); + + assert_se(cg_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) == 0); + + assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path) == 0); + assert_se(path_equal(path, "/test-a")); + free(path); + + assert_se(cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", 0) == 0); + + assert_se(cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, getpid_cached(), &path) == 0); + assert_se(path_equal(path, "/test-b/test-d")); + free(path); + + assert_se(cg_get_path(SYSTEMD_CGROUP_CONTROLLER, "/test-b/test-d", NULL, &path) == 0); + assert_se(path_equal(path, "/sys/fs/cgroup/systemd/test-b/test-d")); + free(path); + + assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0); + assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0); + assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0); + assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0); + + assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, 0, NULL, NULL, NULL) == 0); + assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, 0, NULL, NULL, NULL) > 0); + + assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) > 0); + + assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0); + assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0); + + assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, 0, NULL, NULL, NULL) > 0); + assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, 0, NULL, NULL, NULL) == 0); + + cg_trim(SYSTEMD_CGROUP_CONTROLLER, "/", false); + + assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, "/test-b") < 0); + assert_se(cg_rmdir(SYSTEMD_CGROUP_CONTROLLER, "/test-a") >= 0); + + assert_se(cg_split_spec("foobar:/", &c, &p) == 0); + assert_se(streq(c, "foobar")); + assert_se(streq(p, "/")); + free(c); + free(p); + + assert_se(cg_split_spec("foobar:", &c, &p) < 0); + assert_se(cg_split_spec("foobar:asdfd", &c, &p) < 0); + assert_se(cg_split_spec(":///", &c, &p) < 0); + assert_se(cg_split_spec(":", &c, &p) < 0); + assert_se(cg_split_spec("", &c, &p) < 0); + assert_se(cg_split_spec("fo/obar:/", &c, &p) < 0); + + assert_se(cg_split_spec("/", &c, &p) >= 0); + assert_se(c == NULL); + assert_se(streq(p, "/")); + free(p); + + assert_se(cg_split_spec("foo", &c, &p) >= 0); + assert_se(streq(c, "foo")); + assert_se(p == NULL); + free(c); + + return 0; +} diff --git a/src/test/test-chase-symlinks.c b/src/test/test-chase-symlinks.c new file mode 100644 index 00000000..0b7dd876 --- /dev/null +++ b/src/test/test-chase-symlinks.c @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#include + +#include "fd-util.h" +#include "fs-util.h" +#include "log.h" +#include "main-func.h" + +static char *arg_root = NULL; +static int arg_flags = 0; +static bool arg_open = false; + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_ROOT = 0x1000, + ARG_OPEN, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "root", required_argument, NULL, ARG_ROOT }, + { "open", no_argument, NULL, ARG_OPEN }, + + { "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT }, + { "nonexistent", no_argument, NULL, CHASE_NONEXISTENT }, + { "no_autofs", no_argument, NULL, CHASE_NO_AUTOFS }, + { "safe", no_argument, NULL, CHASE_SAFE }, + { "trail-slash", no_argument, NULL, CHASE_TRAIL_SLASH }, + { "step", no_argument, NULL, CHASE_STEP }, + { "nofollow", no_argument, NULL, CHASE_NOFOLLOW }, + { "warn", no_argument, NULL, CHASE_WARN }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) + switch (c) { + + case 'h': + printf("Syntax:\n" + " %s [OPTION...] path...\n" + "Options:\n" + , argv[0]); + for (size_t i = 0; i < ELEMENTSOF(options) - 1; i++) + printf(" --%s\n", options[i].name); + return 0; + + case ARG_ROOT: + arg_root = optarg; + break; + + case ARG_OPEN: + arg_open = true; + break; + + case CHASE_PREFIX_ROOT: + case CHASE_NONEXISTENT: + case CHASE_NO_AUTOFS: + case CHASE_SAFE: + case CHASE_TRAIL_SLASH: + case CHASE_STEP: + case CHASE_NOFOLLOW: + case CHASE_WARN: + arg_flags |= c; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind == argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "At least one argument is required."); + + return 1; +} + +static int run(int argc, char **argv) { + int r; + + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + for (int i = optind; i < argc; i++) { + _cleanup_free_ char *p = NULL; + _cleanup_close_ int fd = -1; + + printf("%s ", argv[i]); + fflush(stdout); + + r = chase_symlinks(argv[i], arg_root, arg_flags, &p, arg_open ? &fd : NULL); + if (r < 0) + log_error_errno(r, "failed: %m"); + else { + log_info("→ %s", p); + if (arg_open) + assert(fd >= 0); + else + assert(fd == -1); + } + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/test/test-chown-rec.c b/src/test/test-chown-rec.c new file mode 100644 index 00000000..aa11bd27 --- /dev/null +++ b/src/test/test-chown-rec.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "chown-recursive.h" +#include "log.h" +#include "rm-rf.h" +#include "string-util.h" +#include "tests.h" +#include "tmpfile-util.h" + +static const uint8_t acl[] = { + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x07, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x20, 0x00, 0x05, 0x00, + 0xff, 0xff, 0xff, 0xff, +}; + +static const uint8_t default_acl[] = { + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x07, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x20, 0x00, 0x05, 0x00, + 0xff, 0xff, 0xff, 0xff, +}; + +static bool has_xattr(const char *p) { + char buffer[sizeof(acl) * 4]; + + if (lgetxattr(p, "system.posix_acl_access", buffer, sizeof(buffer)) < 0) { + if (IN_SET(errno, EOPNOTSUPP, ENOTTY, ENODATA, ENOSYS)) + return false; + } + + return true; +} + +static void test_chown_recursive(void) { + _cleanup_(rm_rf_physical_and_freep) char *t = NULL; + struct stat st; + const char *p; + const uid_t uid = getuid(); + const gid_t gid = getgid(); + + umask(022); + assert_se(mkdtemp_malloc(NULL, &t) >= 0); + + p = strjoina(t, "/dir"); + assert_se(mkdir(p, 0777) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISDIR(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == uid); + assert_se(st.st_gid == gid); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/symlink"); + assert_se(symlink("../../", p) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISLNK(st.st_mode)); + assert_se((st.st_mode & 07777) == 0777); + assert_se(st.st_uid == uid); + assert_se(st.st_gid == gid); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/reg"); + assert_se(mknod(p, S_IFREG|0777, 0) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISREG(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == uid); + assert_se(st.st_gid == gid); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/sock"); + assert_se(mknod(p, S_IFSOCK|0777, 0) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISSOCK(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == uid); + assert_se(st.st_gid == gid); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/fifo"); + assert_se(mknod(p, S_IFIFO|0777, 0) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISFIFO(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == uid); + assert_se(st.st_gid == gid); + assert_se(!has_xattr(p)); + + /* We now apply an xattr to the dir, and check it again */ + p = strjoina(t, "/dir"); + assert_se(setxattr(p, "system.posix_acl_access", acl, sizeof(acl), 0) >= 0); + assert_se(setxattr(p, "system.posix_acl_default", default_acl, sizeof(default_acl), 0) >= 0); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISDIR(st.st_mode)); + assert_se((st.st_mode & 07777) == 0775); /* acl change changed the mode too */ + assert_se(st.st_uid == uid); + assert_se(st.st_gid == gid); + assert_se(has_xattr(p)); + + assert_se(path_chown_recursive(t, 1, 2, 07777) >= 0); + + p = strjoina(t, "/dir"); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISDIR(st.st_mode)); + assert_se((st.st_mode & 07777) == 0775); + assert_se(st.st_uid == 1); + assert_se(st.st_gid == 2); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/symlink"); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISLNK(st.st_mode)); + assert_se((st.st_mode & 07777) == 0777); + assert_se(st.st_uid == 1); + assert_se(st.st_gid == 2); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/reg"); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISREG(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == 1); + assert_se(st.st_gid == 2); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/sock"); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISSOCK(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == 1); + assert_se(st.st_gid == 2); + assert_se(!has_xattr(p)); + + p = strjoina(t, "/dir/fifo"); + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISFIFO(st.st_mode)); + assert_se((st.st_mode & 07777) == 0755); + assert_se(st.st_uid == 1); + assert_se(st.st_gid == 2); + assert_se(!has_xattr(p)); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + if (geteuid() != 0) + return log_tests_skipped("not running as root"); + + test_chown_recursive(); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-clock.c b/src/test/test-clock.c new file mode 100644 index 00000000..018e679b --- /dev/null +++ b/src/test/test-clock.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2016 Canonical Ltd. +***/ + +#include +#include + +#include "clock-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "log.h" +#include "macro.h" +#include "tmpfile-util.h" + +static void test_clock_is_localtime(void) { + _cleanup_(unlink_tempfilep) char adjtime[] = "/tmp/test-adjtime.XXXXXX"; + _cleanup_fclose_ FILE* f = NULL; + + static const struct scenario { + const char* contents; + int expected_result; + } scenarios[] = { + /* adjtime configures UTC */ + {"0.0 0 0\n0\nUTC\n", 0}, + /* adjtime configures local time */ + {"0.0 0 0\n0\nLOCAL\n", 1}, + /* no final EOL */ + {"0.0 0 0\n0\nUTC", 0}, + {"0.0 0 0\n0\nLOCAL", 1}, + /* empty value -> defaults to UTC */ + {"0.0 0 0\n0\n", 0}, + /* unknown value -> defaults to UTC */ + {"0.0 0 0\n0\nFOO\n", 0}, + /* no third line */ + {"0.0 0 0", 0}, + {"0.0 0 0\n", 0}, + {"0.0 0 0\n0", 0}, + }; + + /* without an adjtime file we default to UTC */ + assert_se(clock_is_localtime("/nonexisting/adjtime") == 0); + + assert_se(fmkostemp_safe(adjtime, "w", &f) == 0); + log_info("adjtime test file: %s", adjtime); + + for (size_t i = 0; i < ELEMENTSOF(scenarios); ++i) { + log_info("scenario #%zu:, expected result %i", i, scenarios[i].expected_result); + log_info("%s", scenarios[i].contents); + rewind(f); + ftruncate(fileno(f), 0); + assert_se(write_string_stream(f, scenarios[i].contents, WRITE_STRING_FILE_AVOID_NEWLINE) == 0); + assert_se(clock_is_localtime(adjtime) == scenarios[i].expected_result); + } +} + +/* Test with the real /etc/adjtime */ +static void test_clock_is_localtime_system(void) { + int r; + r = clock_is_localtime(NULL); + + if (access("/etc/adjtime", F_OK) == 0) { + log_info("/etc/adjtime exists, clock_is_localtime() == %i", r); + /* if /etc/adjtime exists we expect some answer, no error or + * crash */ + assert_se(IN_SET(r, 0, 1)); + } else + /* default is UTC if there is no /etc/adjtime */ + assert_se(r == 0); +} + +int main(int argc, char *argv[]) { + test_clock_is_localtime(); + test_clock_is_localtime_system(); + + return 0; +} diff --git a/src/test/test-condition.c b/src/test/test-condition.c new file mode 100644 index 00000000..28b5b780 --- /dev/null +++ b/src/test/test-condition.c @@ -0,0 +1,842 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "apparmor-util.h" +#include "architecture.h" +#include "audit-util.h" +#include "cgroup-util.h" +#include "condition.h" +#include "cpu-set-util.h" +#include "efi-loader.h" +#include "hostname-util.h" +#include "id128-util.h" +#include "ima-util.h" +#include "limits-util.h" +#include "log.h" +#include "macro.h" +#include "nulstr-util.h" +#include "process-util.h" +#include "selinux-util.h" +#include "set.h" +#include "smack-util.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "tomoyo-util.h" +#include "user-util.h" +#include "virt.h" + +static void test_condition_test_path(void) { + Condition *condition; + + condition = condition_new(CONDITION_PATH_EXISTS, "/bin/sh", false, false); + assert_se(condition); + assert_se(condition_test(condition)); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_EXISTS, "/bin/s?", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_EXISTS_GLOB, "/bin/s?", false, true); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_EXISTS, "/thiscertainlywontexist", false, true); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_IS_DIRECTORY, "/bin", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_DIRECTORY_NOT_EMPTY, "/bin", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_FILE_NOT_EMPTY, "/bin/sh", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/bin/sh", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_FILE_IS_EXECUTABLE, "/etc/passwd", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/proc", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_IS_MOUNT_POINT, "/bin", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_IS_READ_WRITE, "/tmp", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_PATH_IS_SYMBOLIC_LINK, "/dev/stdout", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); +} + +static void test_condition_test_control_group_controller(void) { + Condition *condition; + CGroupMask system_mask; + CGroupController controller; + _cleanup_free_ char *controller_name = NULL; + int r; + + r = cg_unified(); + if (r < 0) { + log_notice_errno(r, "Skipping ConditionControlGroupController tests: %m"); + return; + } + + /* Invalid controllers are ignored */ + condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, "thisisnotarealcontroller", false, true); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + assert_se(cg_mask_supported(&system_mask) >= 0); + + /* Individual valid controllers one by one */ + for (controller = 0; controller < _CGROUP_CONTROLLER_MAX; controller++) { + const char *local_controller_name = cgroup_controller_to_string(controller); + log_info("chosen controller is '%s'", local_controller_name); + if (system_mask & CGROUP_CONTROLLER_TO_MASK(controller)) { + log_info("this controller is available"); + condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + } else { + log_info("this controller is unavailable"); + condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, local_controller_name, false, true); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + } + } + + /* Multiple valid controllers at the same time */ + assert_se(cg_mask_to_string(system_mask, &controller_name) >= 0); + + condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_CONTROL_GROUP_CONTROLLER, strempty(controller_name), false, true); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); +} + +static void test_condition_test_ac_power(void) { + Condition *condition; + + condition = condition_new(CONDITION_AC_POWER, "true", false, false); + assert_se(condition); + assert_se(condition_test(condition) == on_ac_power()); + condition_free(condition); + + condition = condition_new(CONDITION_AC_POWER, "false", false, false); + assert_se(condition); + assert_se(condition_test(condition) != on_ac_power()); + condition_free(condition); + + condition = condition_new(CONDITION_AC_POWER, "false", false, true); + assert_se(condition); + assert_se(condition_test(condition) == on_ac_power()); + condition_free(condition); +} + +static void test_condition_test_host(void) { + _cleanup_free_ char *hostname = NULL; + char sid[SD_ID128_STRING_MAX]; + Condition *condition; + sd_id128_t id; + int r; + + r = sd_id128_get_machine(&id); + assert_se(r >= 0); + assert_se(sd_id128_to_string(id, sid)); + + condition = condition_new(CONDITION_HOST, sid, false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_HOST, "garbage value jjjjjjjjjjjjjj", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_HOST, sid, false, true); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + hostname = gethostname_malloc(); + assert_se(hostname); + + /* if hostname looks like an id128 then skip testing it */ + if (id128_is_valid(hostname)) + log_notice("hostname is an id128, skipping test"); + else { + condition = condition_new(CONDITION_HOST, hostname, false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + } +} + +static void test_condition_test_architecture(void) { + Condition *condition; + const char *sa; + int a; + + a = uname_architecture(); + assert_se(a >= 0); + + sa = architecture_to_string(a); + assert_se(sa); + + condition = condition_new(CONDITION_ARCHITECTURE, sa, false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_ARCHITECTURE, "garbage value", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_ARCHITECTURE, sa, false, true); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); +} + +static void test_condition_test_kernel_command_line(void) { + Condition *condition; + + condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "thisreallyshouldntbeonthekernelcommandline", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_COMMAND_LINE, "andthis=neither", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); +} + +static void test_condition_test_kernel_version(void) { + Condition *condition; + struct utsname u; + const char *v; + + condition = condition_new(CONDITION_KERNEL_VERSION, "*thisreallyshouldntbeinthekernelversion*", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "*", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + /* An artificially empty condition. It evaluates to true, but normally + * such condition cannot be created, because the condition list is reset instead. */ + condition = condition_new(CONDITION_KERNEL_VERSION, "", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + assert_se(uname(&u) >= 0); + + condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + strshorten(u.release, 4); + strcpy(strchr(u.release, 0), "*"); + + condition = condition_new(CONDITION_KERNEL_VERSION, u.release, false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + /* 0.1.2 would be a very very very old kernel */ + condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, ">0.1.2", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "'>0.1.2' '<9.0.0'", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "> 0.1.2 < 9.0.0", false, false); + assert_se(condition); + assert_se(condition_test(condition) == -EINVAL); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, ">", false, false); + assert_se(condition); + assert_se(condition_test(condition) == -EINVAL); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, ">= 0.1.2", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "< 0.1.2", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "<= 0.1.2", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "= 0.1.2", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + /* 4711.8.15 is a very very very future kernel */ + condition = condition_new(CONDITION_KERNEL_VERSION, "< 4711.8.15", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "<= 4711.8.15", false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "= 4711.8.15", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, "> 4711.8.15", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_KERNEL_VERSION, ">= 4711.8.15", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + assert_se(uname(&u) >= 0); + + v = strjoina(">=", u.release); + condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + v = strjoina("= ", u.release); + condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + v = strjoina("<=", u.release); + condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + v = strjoina("> ", u.release); + condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + v = strjoina("< ", u.release); + condition = condition_new(CONDITION_KERNEL_VERSION, v, false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); +} + +static void test_condition_test_null(void) { + Condition *condition; + + condition = condition_new(CONDITION_NULL, NULL, false, false); + assert_se(condition); + assert_se(condition_test(condition) > 0); + condition_free(condition); + + condition = condition_new(CONDITION_NULL, NULL, false, true); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); +} + +static void test_condition_test_security(void) { + Condition *condition; + + condition = condition_new(CONDITION_SECURITY, "garbage oifdsjfoidsjoj", false, false); + assert_se(condition); + assert_se(condition_test(condition) == 0); + condition_free(condition); + + condition = condition_new(CONDITION_SECURITY, "selinux", false, true); + assert_se(condition); + assert_se(condition_test(condition) != mac_selinux_use()); + condition_free(condition); + + condition = condition_new(CONDITION_SECURITY, "apparmor", false, false); + assert_se(condition); + assert_se(condition_test(condition) == mac_apparmor_use()); + condition_free(condition); + + condition = condition_new(CONDITION_SECURITY, "tomoyo", false, false); + assert_se(condition); + assert_se(condition_test(condition) == mac_tomoyo_use()); + condition_free(condition); + + condition = condition_new(CONDITION_SECURITY, "ima", false, false); + assert_se(condition); + assert_se(condition_test(condition) == use_ima()); + condition_free(condition); + + condition = condition_new(CONDITION_SECURITY, "smack", false, false); + assert_se(condition); + assert_se(condition_test(condition) == mac_smack_use()); + condition_free(condition); + + condition = condition_new(CONDITION_SECURITY, "audit", false, false); + assert_se(condition); + assert_se(condition_test(condition) == use_audit()); + condition_free(condition); + + condition = condition_new(CONDITION_SECURITY, "uefi-secureboot", false, false); + assert_se(condition); + assert_se(condition_test(condition) == is_efi_secure_boot()); + condition_free(condition); +} + +static void print_securities(void) { + log_info("------ enabled security technologies ------"); + log_info("SELinux: %s", yes_no(mac_selinux_use())); + log_info("AppArmor: %s", yes_no(mac_apparmor_use())); + log_info("Tomoyo: %s", yes_no(mac_tomoyo_use())); + log_info("IMA: %s", yes_no(use_ima())); + log_info("SMACK: %s", yes_no(mac_smack_use())); + log_info("Audit: %s", yes_no(use_audit())); + log_info("UEFI secure boot: %s", yes_no(is_efi_secure_boot())); + log_info("-------------------------------------------"); +} + +static void test_condition_test_virtualization(void) { + Condition *condition; + const char *virt; + int r; + + condition = condition_new(CONDITION_VIRTUALIZATION, "garbage oifdsjfoidsjoj", false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionVirtualization=garbage → %i", r); + assert_se(r == 0); + condition_free(condition); + + condition = condition_new(CONDITION_VIRTUALIZATION, "container", false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionVirtualization=container → %i", r); + assert_se(r == !!detect_container()); + condition_free(condition); + + condition = condition_new(CONDITION_VIRTUALIZATION, "vm", false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionVirtualization=vm → %i", r); + assert_se(r == (detect_vm() && !detect_container())); + condition_free(condition); + + condition = condition_new(CONDITION_VIRTUALIZATION, "private-users", false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionVirtualization=private-users → %i", r); + assert_se(r == !!running_in_userns()); + condition_free(condition); + + NULSTR_FOREACH(virt, + "kvm\0" + "qemu\0" + "bochs\0" + "xen\0" + "uml\0" + "vmware\0" + "oracle\0" + "microsoft\0" + "zvm\0" + "parallels\0" + "bhyve\0" + "vm_other\0") { + + condition = condition_new(CONDITION_VIRTUALIZATION, virt, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionVirtualization=%s → %i", virt, r); + assert_se(r >= 0); + condition_free(condition); + } +} + +static void test_condition_test_user(void) { + Condition *condition; + char* uid; + char* username; + int r; + + condition = condition_new(CONDITION_USER, "garbage oifdsjfoidsjoj", false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionUser=garbage → %i", r); + assert_se(r == 0); + condition_free(condition); + + assert_se(asprintf(&uid, "%"PRIu32, UINT32_C(0xFFFF)) > 0); + condition = condition_new(CONDITION_USER, uid, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionUser=%s → %i", uid, r); + assert_se(r == 0); + condition_free(condition); + free(uid); + + assert_se(asprintf(&uid, "%u", (unsigned)getuid()) > 0); + condition = condition_new(CONDITION_USER, uid, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionUser=%s → %i", uid, r); + assert_se(r > 0); + condition_free(condition); + free(uid); + + assert_se(asprintf(&uid, "%u", (unsigned)getuid()+1) > 0); + condition = condition_new(CONDITION_USER, uid, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionUser=%s → %i", uid, r); + assert_se(r == 0); + condition_free(condition); + free(uid); + + username = getusername_malloc(); + assert_se(username); + condition = condition_new(CONDITION_USER, username, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionUser=%s → %i", username, r); + assert_se(r > 0); + condition_free(condition); + free(username); + + username = (char*)(geteuid() == 0 ? NOBODY_USER_NAME : "root"); + condition = condition_new(CONDITION_USER, username, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionUser=%s → %i", username, r); + assert_se(r == 0); + condition_free(condition); + + condition = condition_new(CONDITION_USER, "@system", false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionUser=@system → %i", r); + if (uid_is_system(getuid()) || uid_is_system(geteuid())) + assert_se(r > 0); + else + assert_se(r == 0); + condition_free(condition); +} + +static void test_condition_test_group(void) { + Condition *condition; + char* gid; + char* groupname; + gid_t *gids, max_gid; + int ngroups_max, ngroups, r, i; + + assert_se(0 < asprintf(&gid, "%u", UINT32_C(0xFFFF))); + condition = condition_new(CONDITION_GROUP, gid, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionGroup=%s → %i", gid, r); + assert_se(r == 0); + condition_free(condition); + free(gid); + + assert_se(0 < asprintf(&gid, "%u", getgid())); + condition = condition_new(CONDITION_GROUP, gid, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionGroup=%s → %i", gid, r); + assert_se(r > 0); + condition_free(condition); + free(gid); + + ngroups_max = sysconf(_SC_NGROUPS_MAX); + assert(ngroups_max > 0); + + gids = newa(gid_t, ngroups_max); + + ngroups = getgroups(ngroups_max, gids); + assert(ngroups >= 0); + + max_gid = getgid(); + for (i = 0; i < ngroups; i++) { + assert_se(0 < asprintf(&gid, "%u", gids[i])); + condition = condition_new(CONDITION_GROUP, gid, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionGroup=%s → %i", gid, r); + assert_se(r > 0); + condition_free(condition); + free(gid); + max_gid = gids[i] > max_gid ? gids[i] : max_gid; + + groupname = gid_to_name(gids[i]); + assert_se(groupname); + condition = condition_new(CONDITION_GROUP, groupname, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionGroup=%s → %i", groupname, r); + assert_se(r > 0); + condition_free(condition); + free(groupname); + max_gid = gids[i] > max_gid ? gids[i] : max_gid; + } + + assert_se(0 < asprintf(&gid, "%u", max_gid+1)); + condition = condition_new(CONDITION_GROUP, gid, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionGroup=%s → %i", gid, r); + assert_se(r == 0); + condition_free(condition); + free(gid); + + groupname = (char*)(getegid() == 0 ? NOBODY_GROUP_NAME : "root"); + condition = condition_new(CONDITION_GROUP, groupname, false, false); + assert_se(condition); + r = condition_test(condition); + log_info("ConditionGroup=%s → %i", groupname, r); + assert_se(r == 0); + condition_free(condition); +} + +static void test_condition_test_cpus_one(const char *s, bool result) { + Condition *condition; + int r; + + log_debug("%s=%s", condition_type_to_string(CONDITION_CPUS), s); + + condition = condition_new(CONDITION_CPUS, s, false, false); + assert_se(condition); + + r = condition_test(condition); + assert_se(r >= 0); + assert_se(r == result); + condition_free(condition); +} + +static void test_condition_test_cpus(void) { + _cleanup_free_ char *t = NULL; + int cpus; + + cpus = cpus_in_affinity_mask(); + assert_se(cpus >= 0); + + test_condition_test_cpus_one("> 0", true); + test_condition_test_cpus_one(">= 0", true); + test_condition_test_cpus_one("!= 0", true); + test_condition_test_cpus_one("<= 0", false); + test_condition_test_cpus_one("< 0", false); + test_condition_test_cpus_one("= 0", false); + + test_condition_test_cpus_one("> 100000", false); + test_condition_test_cpus_one("= 100000", false); + test_condition_test_cpus_one(">= 100000", false); + test_condition_test_cpus_one("< 100000", true); + test_condition_test_cpus_one("!= 100000", true); + test_condition_test_cpus_one("<= 100000", true); + + assert_se(asprintf(&t, "= %i", cpus) >= 0); + test_condition_test_cpus_one(t, true); + t = mfree(t); + + assert_se(asprintf(&t, "<= %i", cpus) >= 0); + test_condition_test_cpus_one(t, true); + t = mfree(t); + + assert_se(asprintf(&t, ">= %i", cpus) >= 0); + test_condition_test_cpus_one(t, true); + t = mfree(t); + + assert_se(asprintf(&t, "!= %i", cpus) >= 0); + test_condition_test_cpus_one(t, false); + t = mfree(t); + + assert_se(asprintf(&t, "< %i", cpus) >= 0); + test_condition_test_cpus_one(t, false); + t = mfree(t); + + assert_se(asprintf(&t, "> %i", cpus) >= 0); + test_condition_test_cpus_one(t, false); + t = mfree(t); +} + +static void test_condition_test_memory_one(const char *s, bool result) { + Condition *condition; + int r; + + log_debug("%s=%s", condition_type_to_string(CONDITION_MEMORY), s); + + condition = condition_new(CONDITION_MEMORY, s, false, false); + assert_se(condition); + + r = condition_test(condition); + assert_se(r >= 0); + assert_se(r == result); + condition_free(condition); +} + +static void test_condition_test_memory(void) { + _cleanup_free_ char *t = NULL; + uint64_t memory; + + memory = physical_memory(); + + test_condition_test_memory_one("> 0", true); + test_condition_test_memory_one(">= 0", true); + test_condition_test_memory_one("!= 0", true); + test_condition_test_memory_one("<= 0", false); + test_condition_test_memory_one("< 0", false); + test_condition_test_memory_one("= 0", false); + + test_condition_test_memory_one("> 18446744073709547520", false); + test_condition_test_memory_one("= 18446744073709547520", false); + test_condition_test_memory_one(">= 18446744073709547520", false); + test_condition_test_memory_one("< 18446744073709547520", true); + test_condition_test_memory_one("!= 18446744073709547520", true); + test_condition_test_memory_one("<= 18446744073709547520", true); + + assert_se(asprintf(&t, "= %" PRIu64, memory) >= 0); + test_condition_test_memory_one(t, true); + t = mfree(t); + + assert_se(asprintf(&t, "<= %" PRIu64, memory) >= 0); + test_condition_test_memory_one(t, true); + t = mfree(t); + + assert_se(asprintf(&t, ">= %" PRIu64, memory) >= 0); + test_condition_test_memory_one(t, true); + t = mfree(t); + + assert_se(asprintf(&t, "!= %" PRIu64, memory) >= 0); + test_condition_test_memory_one(t, false); + t = mfree(t); + + assert_se(asprintf(&t, "< %" PRIu64, memory) >= 0); + test_condition_test_memory_one(t, false); + t = mfree(t); + + assert_se(asprintf(&t, "> %" PRIu64, memory) >= 0); + test_condition_test_memory_one(t, false); + t = mfree(t); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_condition_test_path(); + test_condition_test_ac_power(); + test_condition_test_host(); + test_condition_test_architecture(); + test_condition_test_kernel_command_line(); + test_condition_test_kernel_version(); + test_condition_test_null(); + test_condition_test_security(); + print_securities(); + test_condition_test_virtualization(); + test_condition_test_user(); + test_condition_test_group(); + test_condition_test_control_group_controller(); + test_condition_test_cpus(); + test_condition_test_memory(); + + return 0; +} diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c new file mode 100644 index 00000000..f37f32f1 --- /dev/null +++ b/src/test/test-conf-files.c @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2014 Michael Marineau +***/ + +#include +#include + +#include "alloc-util.h" +#include "conf-files.h" +#include "fileio.h" +#include "fs-util.h" +#include "macro.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "user-util.h" +#include "util.h" + +static void setup_test_dir(char *tmp_dir, const char *files, ...) { + va_list ap; + + assert_se(mkdtemp(tmp_dir)); + + va_start(ap, files); + while (files) { + _cleanup_free_ char *path; + + assert_se(path = path_join(tmp_dir, files)); + (void) mkdir_parents(path, 0755); + assert_se(write_string_file(path, "foobar", WRITE_STRING_FILE_CREATE) >= 0); + + files = va_arg(ap, const char *); + } + va_end(ap); +} + +static void test_conf_files_list(bool use_root) { + char tmp_dir[] = "/tmp/test-conf-files-XXXXXX"; + _cleanup_strv_free_ char **found_files = NULL, **found_files2 = NULL; + const char *root_dir, *search, *expect_a, *expect_b, *expect_c, *mask; + + log_info("/* %s(%s) */", __func__, yes_no(use_root)); + + setup_test_dir(tmp_dir, + "/dir/a.conf", + "/dir/b.conf", + "/dir/c.foo", + NULL); + + mask = strjoina(tmp_dir, "/dir/d.conf"); + assert_se(symlink("/dev/null", mask) >= 0); + + if (use_root) { + root_dir = tmp_dir; + search = "/dir"; + } else { + root_dir = NULL; + search = strjoina(tmp_dir, "/dir"); + } + + expect_a = strjoina(tmp_dir, "/dir/a.conf"); + expect_b = strjoina(tmp_dir, "/dir/b.conf"); + expect_c = strjoina(tmp_dir, "/dir/c.foo"); + + log_debug("/* Check when filtered by suffix */"); + + assert_se(conf_files_list(&found_files, ".conf", root_dir, CONF_FILES_FILTER_MASKED, search) == 0); + strv_print(found_files); + + assert_se(found_files); + assert_se(streq_ptr(found_files[0], expect_a)); + assert_se(streq_ptr(found_files[1], expect_b)); + assert_se(!found_files[2]); + + log_debug("/* Check when unfiltered */"); + assert_se(conf_files_list(&found_files2, NULL, root_dir, CONF_FILES_FILTER_MASKED, search) == 0); + strv_print(found_files2); + + assert_se(found_files2); + assert_se(streq_ptr(found_files2[0], expect_a)); + assert_se(streq_ptr(found_files2[1], expect_b)); + assert_se(streq_ptr(found_files2[2], expect_c)); + assert_se(!found_files2[3]); + + assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0); +} + +static void test_conf_files_insert(const char *root) { + _cleanup_strv_free_ char **s = NULL; + + log_info("/* %s root=%s */", __func__, strempty(root)); + + char **dirs = STRV_MAKE("/dir1", "/dir2", "/dir3"); + + _cleanup_free_ const char + *foo1 = path_join(root, "/dir1/foo.conf"), + *foo2 = path_join(root, "/dir2/foo.conf"), + *bar2 = path_join(root, "/dir2/bar.conf"), + *zzz3 = path_join(root, "/dir3/zzz.conf"), + *whatever = path_join(root, "/whatever.conf"); + + assert_se(conf_files_insert(&s, root, dirs, "/dir2/foo.conf") == 0); + assert_se(strv_equal(s, STRV_MAKE(foo2))); + + /* The same file again, https://github.com/systemd/systemd/issues/11124 */ + assert_se(conf_files_insert(&s, root, dirs, "/dir2/foo.conf") == 0); + assert_se(strv_equal(s, STRV_MAKE(foo2))); + + /* Lower priority → new entry is ignored */ + assert_se(conf_files_insert(&s, root, dirs, "/dir3/foo.conf") == 0); + assert_se(strv_equal(s, STRV_MAKE(foo2))); + + /* Higher priority → new entry replaces */ + assert_se(conf_files_insert(&s, root, dirs, "/dir1/foo.conf") == 0); + assert_se(strv_equal(s, STRV_MAKE(foo1))); + + /* Earlier basename */ + assert_se(conf_files_insert(&s, root, dirs, "/dir2/bar.conf") == 0); + assert_se(strv_equal(s, STRV_MAKE(bar2, foo1))); + + /* Later basename */ + assert_se(conf_files_insert(&s, root, dirs, "/dir3/zzz.conf") == 0); + assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, zzz3))); + + /* All lower priority → all ignored */ + assert_se(conf_files_insert(&s, root, dirs, "/dir3/zzz.conf") == 0); + assert_se(conf_files_insert(&s, root, dirs, "/dir2/bar.conf") == 0); + assert_se(conf_files_insert(&s, root, dirs, "/dir3/bar.conf") == 0); + assert_se(conf_files_insert(&s, root, dirs, "/dir2/foo.conf") == 0); + assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, zzz3))); + + /* Two entries that don't match any of the directories, but match basename */ + assert_se(conf_files_insert(&s, root, dirs, "/dir4/zzz.conf") == 0); + assert_se(conf_files_insert(&s, root, dirs, "/zzz.conf") == 0); + assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, zzz3))); + + /* An entry that doesn't match any of the directories, no match at all */ + assert_se(conf_files_insert(&s, root, dirs, "/whatever.conf") == 0); + assert_se(strv_equal(s, STRV_MAKE(bar2, foo1, whatever, zzz3))); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_conf_files_list(false); + test_conf_files_list(true); + test_conf_files_insert(NULL); + test_conf_files_insert("/root"); + test_conf_files_insert("/root/"); + + return 0; +} diff --git a/src/test/test-conf-parser.c b/src/test/test-conf-parser.c new file mode 100644 index 00000000..661eb179 --- /dev/null +++ b/src/test/test-conf-parser.c @@ -0,0 +1,395 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "conf-parser.h" +#include "fd-util.h" +#include "fs-util.h" +#include "log.h" +#include "macro.h" +#include "string-util.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "util.h" + +static void test_config_parse_path_one(const char *rvalue, const char *expected) { + _cleanup_free_ char *path = NULL; + + assert_se(config_parse_path("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &path, NULL) >= 0); + assert_se(streq_ptr(expected, path)); +} + +static void test_config_parse_log_level_one(const char *rvalue, int expected) { + int log_level = 0; + + assert_se(config_parse_log_level("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_level, NULL) >= 0); + assert_se(expected == log_level); +} + +static void test_config_parse_log_facility_one(const char *rvalue, int expected) { + int log_facility = 0; + + assert_se(config_parse_log_facility("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &log_facility, NULL) >= 0); + assert_se(expected == log_facility); +} + +static void test_config_parse_iec_size_one(const char *rvalue, size_t expected) { + size_t iec_size = 0; + + assert_se(config_parse_iec_size("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &iec_size, NULL) >= 0); + assert_se(expected == iec_size); +} + +static void test_config_parse_si_size_one(const char *rvalue, size_t expected) { + size_t si_size = 0; + + assert_se(config_parse_si_size("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &si_size, NULL) >= 0); + assert_se(expected == si_size); +} + +static void test_config_parse_int_one(const char *rvalue, int expected) { + int v = -1; + + assert_se(config_parse_int("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); + assert_se(expected == v); +} + +static void test_config_parse_unsigned_one(const char *rvalue, unsigned expected) { + unsigned v = 0; + + assert_se(config_parse_unsigned("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); + assert_se(expected == v); +} + +static void test_config_parse_strv_one(const char *rvalue, char **expected) { + _cleanup_strv_free_ char **strv = NULL; + + assert_se(config_parse_strv("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &strv, NULL) >= 0); + assert_se(strv_equal(expected, strv)); +} + +static void test_config_parse_mode_one(const char *rvalue, mode_t expected) { + mode_t v = 0; + + assert_se(config_parse_mode("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); + assert_se(expected == v); +} + +static void test_config_parse_sec_one(const char *rvalue, usec_t expected) { + usec_t v = 0; + + assert_se(config_parse_sec("unit", "filename", 1, "section", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); + assert_se(expected == v); +} + +static void test_config_parse_nsec_one(const char *rvalue, nsec_t expected) { + nsec_t v = 0; + + assert_se(config_parse_nsec("unit", "filename", 1, "nsection", 1, "lvalue", 0, rvalue, &v, NULL) >= 0); + assert_se(expected == v); +} + +static void test_config_parse_path(void) { + test_config_parse_path_one("/path", "/path"); + test_config_parse_path_one("/path//////////", "/path"); + test_config_parse_path_one("///path/foo///bar////bar//", "/path/foo/bar/bar"); + test_config_parse_path_one("/path//./////hogehoge///.", "/path/hogehoge"); + test_config_parse_path_one("/path/\xc3\x80", "/path/\xc3\x80"); + + test_config_parse_path_one("not_absolute/path", NULL); + test_config_parse_path_one("/path/\xc3\x7f", NULL); +} + +static void test_config_parse_log_level(void) { + test_config_parse_log_level_one("debug", LOG_DEBUG); + test_config_parse_log_level_one("info", LOG_INFO); + + test_config_parse_log_level_one("garbage", 0); +} + +static void test_config_parse_log_facility(void) { + test_config_parse_log_facility_one("mail", LOG_MAIL); + test_config_parse_log_facility_one("user", LOG_USER); + + test_config_parse_log_facility_one("garbage", 0); +} + +static void test_config_parse_iec_size(void) { + test_config_parse_iec_size_one("1024", 1024); + test_config_parse_iec_size_one("2K", 2048); + test_config_parse_iec_size_one("10M", 10 * 1024 * 1024); + test_config_parse_iec_size_one("1G", 1 * 1024 * 1024 * 1024); + test_config_parse_iec_size_one("0G", 0); + test_config_parse_iec_size_one("0", 0); + + test_config_parse_iec_size_one("-982", 0); + test_config_parse_iec_size_one("49874444198739873000000G", 0); + test_config_parse_iec_size_one("garbage", 0); +} + +static void test_config_parse_si_size(void) { + test_config_parse_si_size_one("1024", 1024); + test_config_parse_si_size_one("2K", 2000); + test_config_parse_si_size_one("10M", 10 * 1000 * 1000); + test_config_parse_si_size_one("1G", 1 * 1000 * 1000 * 1000); + test_config_parse_si_size_one("0G", 0); + test_config_parse_si_size_one("0", 0); + + test_config_parse_si_size_one("-982", 0); + test_config_parse_si_size_one("49874444198739873000000G", 0); + test_config_parse_si_size_one("garbage", 0); +} + +static void test_config_parse_int(void) { + test_config_parse_int_one("1024", 1024); + test_config_parse_int_one("-1024", -1024); + test_config_parse_int_one("0", 0); + + test_config_parse_int_one("99999999999999999999999999999999999999999999999999999999", -1); + test_config_parse_int_one("-99999999999999999999999999999999999999999999999999999999", -1); + test_config_parse_int_one("1G", -1); + test_config_parse_int_one("garbage", -1); +} + +static void test_config_parse_unsigned(void) { + test_config_parse_unsigned_one("10241024", 10241024); + test_config_parse_unsigned_one("1024", 1024); + test_config_parse_unsigned_one("0", 0); + + test_config_parse_unsigned_one("99999999999999999999999999999999999999999999999999999999", 0); + test_config_parse_unsigned_one("1G", 0); + test_config_parse_unsigned_one("garbage", 0); + test_config_parse_unsigned_one("1000garbage", 0); +} + +static void test_config_parse_strv(void) { + test_config_parse_strv_one("", STRV_MAKE_EMPTY); + test_config_parse_strv_one("foo", STRV_MAKE("foo")); + test_config_parse_strv_one("foo bar foo", STRV_MAKE("foo", "bar", "foo")); + test_config_parse_strv_one("\"foo bar\" foo", STRV_MAKE("foo bar", "foo")); + test_config_parse_strv_one("\xc3\x80", STRV_MAKE("\xc3\x80")); + test_config_parse_strv_one("\xc3\x7f", STRV_MAKE("\xc3\x7f")); +} + +static void test_config_parse_mode(void) { + test_config_parse_mode_one("777", 0777); + test_config_parse_mode_one("644", 0644); + + test_config_parse_mode_one("-777", 0); + test_config_parse_mode_one("999", 0); + test_config_parse_mode_one("garbage", 0); + test_config_parse_mode_one("777garbage", 0); + test_config_parse_mode_one("777 garbage", 0); +} + +static void test_config_parse_sec(void) { + test_config_parse_sec_one("1", 1 * USEC_PER_SEC); + test_config_parse_sec_one("1s", 1 * USEC_PER_SEC); + test_config_parse_sec_one("100ms", 100 * USEC_PER_MSEC); + test_config_parse_sec_one("5min 20s", 5 * 60 * USEC_PER_SEC + 20 * USEC_PER_SEC); + + test_config_parse_sec_one("-1", 0); + test_config_parse_sec_one("10foo", 0); + test_config_parse_sec_one("garbage", 0); +} + +static void test_config_parse_nsec(void) { + test_config_parse_nsec_one("1", 1); + test_config_parse_nsec_one("1s", 1 * NSEC_PER_SEC); + test_config_parse_nsec_one("100ms", 100 * NSEC_PER_MSEC); + test_config_parse_nsec_one("5min 20s", 5 * 60 * NSEC_PER_SEC + 20 * NSEC_PER_SEC); + + test_config_parse_nsec_one("-1", 0); + test_config_parse_nsec_one("10foo", 0); + test_config_parse_nsec_one("garbage", 0); +} + +static void test_config_parse_iec_uint64(void) { + uint64_t offset = 0; + assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4M", &offset, NULL) == 0); + assert_se(offset == 4 * 1024 * 1024); + + assert_se(config_parse_iec_uint64(NULL, "/this/file", 11, "Section", 22, "Size", 0, "4.5M", &offset, NULL) == 0); +} + +#define x10(x) x x x x x x x x x x +#define x100(x) x10(x10(x)) +#define x1000(x) x10(x100(x)) + +static const char* const config_file[] = { + "[Section]\n" + "setting1=1\n", + + "[Section]\n" + "setting1=1", /* no terminating newline */ + + "\n\n\n\n[Section]\n\n\n" + "setting1=1", /* some whitespace, no terminating newline */ + + "[Section]\n" + "[Section]\n" + "setting1=1\n" + "setting1= 2 \t\n" + "setting1= 1\n", /* repeated settings */ + + "[Section]\n" + "[Section]\n" + "setting1=1\n" + "setting1=2\\\n" + " \n" /* empty line breaks continuation */ + "setting1=1\n", /* repeated settings */ + + "[Section]\n" + "setting1=1\\\n" /* normal continuation */ + "2\\\n" + "3\n", + + "[Section]\n" + "#hogehoge\\\n" /* continuation is ignored in comment */ + "setting1=1\\\n" /* normal continuation */ + "2\\\n" + "3\n", + + "[Section]\n" + "setting1=1\\\n" /* normal continuation */ + "#hogehoge\\\n" /* commented out line in continuation is ignored */ + "2\\\n" + "3\n", + + "[Section]\n" + " #hogehoge\\\n" /* whitespaces before comments */ + " setting1=1\\\n" /* whitespaces before key */ + "2\\\n" + "3\n", + + "[Section]\n" + " setting1=1\\\n" /* whitespaces before key */ + " #hogehoge\\\n" /* commented out line prefixed with whitespaces in continuation */ + "2\\\n" + "3\n", + + "[Section]\n" + "setting1=1\\\n" /* continuation with extra trailing backslash at the end */ + "2\\\n" + "3\\\n", + + "[Section]\n" + "setting1=1\\\\\\\n" /* continuation with trailing escape symbols */ + "\\\\2\n", /* note that C requires one level of escaping, so the + * parser gets "…1 BS BS BS NL BS BS 2 NL", which + * it translates into "…1 BS BS SP BS BS 2" */ + + "\n[Section]\n\n" + "setting1=" /* a line above LINE_MAX length */ + x1000("ABCD") + "\n", + + "[Section]\n" + "setting1=" /* a line above LINE_MAX length, with continuation */ + x1000("ABCD") "\\\n" + "foobar", + + "[Section]\n" + "setting1=" /* a line above LINE_MAX length, with continuation */ + x1000("ABCD") "\\\n" /* and an extra trailing backslash */ + "foobar\\\n", + + "[Section]\n" + "setting1=" /* a line above the allowed limit: 9 + 1050000 + 1 */ + x1000(x1000("x") x10("abcde")) "\n", + + "[Section]\n" + "setting1=" /* many continuation lines, together above the limit */ + x1000(x1000("x") x10("abcde") "\\\n") "xxx", +}; + +static void test_config_parse(unsigned i, const char *s) { + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-conf-parser.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *setting1 = NULL; + int r; + + const ConfigTableItem items[] = { + { "Section", "setting1", config_parse_string, 0, &setting1}, + {} + }; + + log_info("== %s[%i] ==", __func__, i); + + assert_se(fmkostemp_safe(name, "r+", &f) == 0); + assert_se(fwrite(s, strlen(s), 1, f) == 1); + rewind(f); + + /* + int config_parse(const char *unit, + const char *filename, + FILE *f, + const char *sections, + ConfigItemLookup lookup, + const void *table, + bool relaxed, + bool allow_include, + bool warn, + void *userdata) + */ + + r = config_parse(NULL, name, f, + "Section\0", + config_item_table_lookup, items, + CONFIG_PARSE_WARN, NULL); + + switch (i) { + case 0 ... 4: + assert_se(r == 0); + assert_se(streq(setting1, "1")); + break; + + case 5 ... 10: + assert_se(r == 0); + assert_se(streq(setting1, "1 2 3")); + break; + + case 11: + assert_se(r == 0); + assert_se(streq(setting1, "1\\\\ \\\\2")); + break; + + case 12: + assert_se(r == 0); + assert_se(streq(setting1, x1000("ABCD"))); + break; + + case 13 ... 14: + assert_se(r == 0); + assert_se(streq(setting1, x1000("ABCD") " foobar")); + break; + + case 15 ... 16: + assert_se(r == -ENOBUFS); + assert_se(setting1 == NULL); + break; + } +} + +int main(int argc, char **argv) { + unsigned i; + + log_parse_environment(); + log_open(); + + test_config_parse_path(); + test_config_parse_log_level(); + test_config_parse_log_facility(); + test_config_parse_iec_size(); + test_config_parse_si_size(); + test_config_parse_int(); + test_config_parse_unsigned(); + test_config_parse_strv(); + test_config_parse_mode(); + test_config_parse_sec(); + test_config_parse_nsec(); + test_config_parse_iec_uint64(); + + for (i = 0; i < ELEMENTSOF(config_file); i++) + test_config_parse(i, config_file[i]); + + return 0; +} diff --git a/src/test/test-copy.c b/src/test/test-copy.c new file mode 100644 index 00000000..68905c66 --- /dev/null +++ b/src/test/test-copy.c @@ -0,0 +1,297 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "copy.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hexdecoct.h" +#include "log.h" +#include "macro.h" +#include "mkdir.h" +#include "path-util.h" +#include "rm-rf.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "tmpfile-util.h" +#include "user-util.h" +#include "util.h" +#include "xattr-util.h" + +static void test_copy_file(void) { + _cleanup_free_ char *buf = NULL; + char fn[] = "/tmp/test-copy_file.XXXXXX"; + char fn_copy[] = "/tmp/test-copy_file.XXXXXX"; + size_t sz = 0; + int fd; + + log_info("%s", __func__); + + fd = mkostemp_safe(fn); + assert_se(fd >= 0); + close(fd); + + fd = mkostemp_safe(fn_copy); + assert_se(fd >= 0); + close(fd); + + assert_se(write_string_file(fn, "foo bar bar bar foo", WRITE_STRING_FILE_CREATE) == 0); + + assert_se(copy_file(fn, fn_copy, 0, 0644, 0, 0, COPY_REFLINK) == 0); + + assert_se(read_full_file(fn_copy, &buf, &sz) == 0); + assert_se(streq(buf, "foo bar bar bar foo\n")); + assert_se(sz == 20); + + unlink(fn); + unlink(fn_copy); +} + +static void test_copy_file_fd(void) { + char in_fn[] = "/tmp/test-copy-file-fd-XXXXXX"; + char out_fn[] = "/tmp/test-copy-file-fd-XXXXXX"; + _cleanup_close_ int in_fd = -1, out_fd = -1; + const char *text = "boohoo\nfoo\n\tbar\n"; + char buf[64] = {}; + + log_info("%s", __func__); + + in_fd = mkostemp_safe(in_fn); + assert_se(in_fd >= 0); + out_fd = mkostemp_safe(out_fn); + assert_se(out_fd >= 0); + + assert_se(write_string_file(in_fn, text, WRITE_STRING_FILE_CREATE) == 0); + assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd, COPY_REFLINK) < 0); + assert_se(copy_file_fd(in_fn, out_fd, COPY_REFLINK) >= 0); + assert_se(lseek(out_fd, SEEK_SET, 0) == 0); + + assert_se(read(out_fd, buf, sizeof buf) == (ssize_t) strlen(text)); + assert_se(streq(buf, text)); + + unlink(in_fn); + unlink(out_fn); +} + +static void test_copy_tree(void) { + char original_dir[] = "/var/tmp/test-copy_tree/"; + char copy_dir[] = "/var/tmp/test-copy_tree-copy/"; + char **files = STRV_MAKE("file", "dir1/file", "dir1/dir2/file", "dir1/dir2/dir3/dir4/dir5/file"); + char **links = STRV_MAKE("link", "file", + "link2", "dir1/file"); + const char *unixsockp; + char **p, **link; + struct stat st; + int xattr_worked = -1; /* xattr support is optional in temporary directories, hence use it if we can, + * but don't fail if we can't */ + + log_info("%s", __func__); + + (void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL); + + STRV_FOREACH(p, files) { + _cleanup_free_ char *f, *c; + int k; + + assert_se(f = path_join(original_dir, *p)); + + assert_se(mkdir_parents(f, 0755) >= 0); + assert_se(write_string_file(f, "file", WRITE_STRING_FILE_CREATE) == 0); + + assert_se(base64mem(*p, strlen(*p), &c) >= 0); + + k = setxattr(f, "user.testxattr", c, strlen(c), 0); + assert_se(xattr_worked < 0 || ((k >= 0) == !!xattr_worked)); + xattr_worked = k >= 0; + } + + STRV_FOREACH_PAIR(link, p, links) { + _cleanup_free_ char *f, *l; + + assert_se(f = path_join(original_dir, *p)); + assert_se(l = path_join(original_dir, *link)); + + assert_se(mkdir_parents(l, 0755) >= 0); + assert_se(symlink(f, l) == 0); + } + + unixsockp = strjoina(original_dir, "unixsock"); + assert_se(mknod(unixsockp, S_IFSOCK|0644, 0) >= 0); + + assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE) == 0); + + STRV_FOREACH(p, files) { + _cleanup_free_ char *buf, *f, *c = NULL; + size_t sz; + int k; + + assert_se(f = path_join(copy_dir, *p)); + + assert_se(access(f, F_OK) == 0); + assert_se(read_full_file(f, &buf, &sz) == 0); + assert_se(streq(buf, "file\n")); + + k = getxattr_malloc(f, "user.testxattr", &c, false); + assert_se(xattr_worked < 0 || ((k >= 0) == !!xattr_worked)); + + if (k >= 0) { + _cleanup_free_ char *d = NULL; + + assert_se(base64mem(*p, strlen(*p), &d) >= 0); + assert_se(streq(d, c)); + } + } + + STRV_FOREACH_PAIR(link, p, links) { + _cleanup_free_ char *target, *f, *l; + + assert_se(f = strjoin(original_dir, *p)); + assert_se(l = strjoin(copy_dir, *link)); + + assert_se(chase_symlinks(l, NULL, 0, &target, NULL) == 1); + assert_se(path_equal(f, target)); + } + + unixsockp = strjoina(copy_dir, "unixsock"); + assert_se(stat(unixsockp, &st) >= 0); + assert_se(S_ISSOCK(st.st_mode)); + + assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK) < 0); + assert_se(copy_tree("/tmp/inexistent/foo/bar/fsdoi", copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK) < 0); + + (void) rm_rf(copy_dir, REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf(original_dir, REMOVE_ROOT|REMOVE_PHYSICAL); +} + +static void test_copy_bytes(void) { + _cleanup_close_pair_ int pipefd[2] = {-1, -1}; + _cleanup_close_ int infd = -1; + int r, r2; + char buf[1024], buf2[1024]; + + infd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC); + if (infd < 0) + infd = open("/etc/os-release", O_RDONLY|O_CLOEXEC); + assert_se(infd >= 0); + + assert_se(pipe2(pipefd, O_CLOEXEC) == 0); + + r = copy_bytes(infd, pipefd[1], (uint64_t) -1, 0); + assert_se(r == 0); + + r = read(pipefd[0], buf, sizeof(buf)); + assert_se(r >= 0); + + assert_se(lseek(infd, 0, SEEK_SET) == 0); + r2 = read(infd, buf2, sizeof(buf2)); + assert_se(r == r2); + + assert_se(strneq(buf, buf2, r)); + + /* test copy_bytes with invalid descriptors */ + r = copy_bytes(pipefd[0], pipefd[0], 1, 0); + assert_se(r == -EBADF); + + r = copy_bytes(pipefd[1], pipefd[1], 1, 0); + assert_se(r == -EBADF); + + r = copy_bytes(pipefd[1], infd, 1, 0); + assert_se(r == -EBADF); +} + +static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint64_t max_bytes) { + char fn2[] = "/tmp/test-copy-file-XXXXXX"; + char fn3[] = "/tmp/test-copy-file-XXXXXX"; + _cleanup_close_ int fd = -1, fd2 = -1, fd3 = -1; + int r; + struct stat buf, buf2, buf3; + + log_info("%s try_reflink=%s max_bytes=%" PRIu64, __func__, yes_no(try_reflink), max_bytes); + + fd = open(src, O_RDONLY | O_CLOEXEC | O_NOCTTY); + assert_se(fd >= 0); + + fd2 = mkostemp_safe(fn2); + assert_se(fd2 >= 0); + + fd3 = mkostemp_safe(fn3); + assert_se(fd3 >= 0); + + r = copy_bytes(fd, fd2, max_bytes, try_reflink ? COPY_REFLINK : 0); + if (max_bytes == (uint64_t) -1) + assert_se(r == 0); + else + assert_se(IN_SET(r, 0, 1)); + + assert_se(fstat(fd, &buf) == 0); + assert_se(fstat(fd2, &buf2) == 0); + assert_se((uint64_t) buf2.st_size == MIN((uint64_t) buf.st_size, max_bytes)); + + if (max_bytes < (uint64_t) -1) + /* Make sure the file is now higher than max_bytes */ + assert_se(ftruncate(fd2, max_bytes + 1) == 0); + + assert_se(lseek(fd2, 0, SEEK_SET) == 0); + + r = copy_bytes(fd2, fd3, max_bytes, try_reflink ? COPY_REFLINK : 0); + if (max_bytes == (uint64_t) -1) + assert_se(r == 0); + else + /* We cannot distinguish between the input being exactly max_bytes + * or longer than max_bytes (without trying to read one more byte, + * or calling stat, or FION_READ, etc, and we don't want to do any + * of that). So we expect "truncation" since we know that file we + * are copying is exactly max_bytes bytes. */ + assert_se(r == 1); + + assert_se(fstat(fd3, &buf3) == 0); + + if (max_bytes == (uint64_t) -1) + assert_se(buf3.st_size == buf2.st_size); + else + assert_se((uint64_t) buf3.st_size == max_bytes); + + unlink(fn2); + unlink(fn3); +} + +static void test_copy_atomic(void) { + _cleanup_(rm_rf_physical_and_freep) char *p = NULL; + const char *q; + int r; + + assert_se(mkdtemp_malloc(NULL, &p) >= 0); + + q = strjoina(p, "/fstab"); + + r = copy_file_atomic("/etc/fstab", q, 0644, 0, 0, COPY_REFLINK); + if (r == -ENOENT) + return; + + assert_se(copy_file_atomic("/etc/fstab", q, 0644, 0, 0, COPY_REFLINK) == -EEXIST); + + assert_se(copy_file_atomic("/etc/fstab", q, 0644, 0, 0, COPY_REPLACE) >= 0); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_copy_file(); + test_copy_file_fd(); + test_copy_tree(); + test_copy_bytes(); + test_copy_bytes_regular_file(argv[0], false, (uint64_t) -1); + test_copy_bytes_regular_file(argv[0], true, (uint64_t) -1); + test_copy_bytes_regular_file(argv[0], false, 1000); /* smaller than copy buffer size */ + test_copy_bytes_regular_file(argv[0], true, 1000); + test_copy_bytes_regular_file(argv[0], false, 32000); /* larger than copy buffer size */ + test_copy_bytes_regular_file(argv[0], true, 32000); + test_copy_atomic(); + + return 0; +} diff --git a/src/test/test-cpu-set-util.c b/src/test/test-cpu-set-util.c new file mode 100644 index 00000000..e1dd2eb3 --- /dev/null +++ b/src/test/test-cpu-set-util.c @@ -0,0 +1,290 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "cpu-set-util.h" +#include "string-util.h" +#include "macro.h" + +static void test_parse_cpu_set(void) { + CPUSet c = {}; + _cleanup_free_ char *str = NULL; + int cpu; + + log_info("/* %s */", __func__); + + /* Single value */ + assert_se(parse_cpu_set_full("0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.set); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_ISSET_S(0, c.allocated, c.set)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 1); + + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); + assert_se(streq(str, "0")); + str = mfree(str); + cpu_set_reset(&c); + + /* Simple range (from CPUAffinity example) */ + assert_se(parse_cpu_set_full("1 2 4", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.set); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_ISSET_S(1, c.allocated, c.set)); + assert_se(CPU_ISSET_S(2, c.allocated, c.set)); + assert_se(CPU_ISSET_S(4, c.allocated, c.set)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 3); + + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); + assert_se(streq(str, "1-2 4")); + str = mfree(str); + cpu_set_reset(&c); + + /* A more interesting range */ + assert_se(parse_cpu_set_full("0 1 2 3 8 9 10 11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); + assert_se(streq(str, "0-3 8-11")); + str = mfree(str); + cpu_set_reset(&c); + + /* Quoted strings */ + assert_se(parse_cpu_set_full("8 '9' 10 \"11\"", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 4); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); + assert_se(streq(str, "8-11")); + str = mfree(str); + cpu_set_reset(&c); + + /* Use commas as separators */ + assert_se(parse_cpu_set_full("0,1,2,3 8,9,10,11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + cpu_set_reset(&c); + + /* Commas with spaces (and trailing comma, space) */ + assert_se(parse_cpu_set_full("0, 1, 2, 3, 4, 5, 6, 7, 63, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 9); + for (cpu = 0; cpu < 8; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + + assert_se(CPU_ISSET_S(63, c.allocated, c.set)); + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); + assert_se(streq(str, "0-7 63")); + str = mfree(str); + cpu_set_reset(&c); + + /* Ranges */ + assert_se(parse_cpu_set_full("0-3,8-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + cpu_set_reset(&c); + + /* Ranges with trailing comma, space */ + assert_se(parse_cpu_set_full("0-3 8-11, ", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 8); + for (cpu = 0; cpu < 4; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + for (cpu = 8; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); + assert_se(streq(str, "0-3 8-11")); + str = mfree(str); + cpu_set_reset(&c); + + /* Negative range (returns empty cpu_set) */ + assert_se(parse_cpu_set_full("3-0", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 0); + cpu_set_reset(&c); + + /* Overlapping ranges */ + assert_se(parse_cpu_set_full("0-7 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 12); + for (cpu = 0; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); + assert_se(streq(str, "0-11")); + str = mfree(str); + cpu_set_reset(&c); + + /* Mix ranges and individual CPUs */ + assert_se(parse_cpu_set_full("0,2 4-11", &c, true, NULL, "fake", 1, "CPUAffinity") >= 0); + assert_se(c.allocated >= DIV_ROUND_UP(sizeof(__cpu_mask), 8)); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 10); + assert_se(CPU_ISSET_S(0, c.allocated, c.set)); + assert_se(CPU_ISSET_S(2, c.allocated, c.set)); + for (cpu = 4; cpu < 12; cpu++) + assert_se(CPU_ISSET_S(cpu, c.allocated, c.set)); + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); + assert_se(streq(str, "0 2 4-11")); + str = mfree(str); + cpu_set_reset(&c); + + /* Garbage */ + assert_se(parse_cpu_set_full("0 1 2 3 garbage", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL); + assert_se(!c.set); + assert_se(c.allocated == 0); + + /* Range with garbage */ + assert_se(parse_cpu_set_full("0-3 8-garbage", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL); + assert_se(!c.set); + assert_se(c.allocated == 0); + + /* Empty string */ + assert_se(parse_cpu_set_full("", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); + assert_se(!c.set); /* empty string returns NULL */ + assert_se(c.allocated == 0); + + /* Runaway quoted string */ + assert_se(parse_cpu_set_full("0 1 2 3 \"4 5 6 7 ", &c, true, NULL, "fake", 1, "CPUAffinity") == -EINVAL); + assert_se(!c.set); + assert_se(c.allocated == 0); + + /* Maximum allocation */ + assert_se(parse_cpu_set_full("8000-8191", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 192); + assert_se(str = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", str); + str = mfree(str); + assert_se(str = cpu_set_to_range_string(&c)); + log_info("cpu_set_to_range_string: %s", str); + assert_se(streq(str, "8000-8191")); + str = mfree(str); + cpu_set_reset(&c); +} + +static void test_parse_cpu_set_extend(void) { + CPUSet c = {}; + _cleanup_free_ char *s1 = NULL, *s2 = NULL; + + log_info("/* %s */", __func__); + + assert_se(parse_cpu_set_extend("1 3", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 2); + assert_se(s1 = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", s1); + + assert_se(parse_cpu_set_extend("4", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 3); + assert_se(s2 = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", s2); + + assert_se(parse_cpu_set_extend("", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); + assert_se(!c.set); + assert_se(c.allocated == 0); + log_info("cpu_set_to_string: (null)"); +} + +static void test_cpu_set_to_from_dbus(void) { + _cleanup_(cpu_set_reset) CPUSet c = {}, c2 = {}; + _cleanup_free_ char *s = NULL; + + log_info("/* %s */", __func__); + + assert_se(parse_cpu_set_extend("1 3 8 100-200", &c, true, NULL, "fake", 1, "CPUAffinity") == 0); + assert_se(s = cpu_set_to_string(&c)); + log_info("cpu_set_to_string: %s", s); + assert_se(CPU_COUNT_S(c.allocated, c.set) == 104); + + _cleanup_free_ uint8_t *array = NULL; + size_t allocated; + static const char expected[32] = + "\x0A\x01\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\xF0\xFF\xFF\xFF\xFF\xFF\xFF\xFF" + "\xFF\xFF\xFF\xFF\xFF\x01"; + + assert_se(cpu_set_to_dbus(&c, &array, &allocated) == 0); + assert_se(array); + assert_se(allocated == c.allocated); + + assert_se(allocated <= sizeof expected); + assert_se(allocated >= DIV_ROUND_UP(201u, 8u)); /* We need at least 201 bits for our mask */ + assert(memcmp(array, expected, allocated) == 0); + + assert_se(cpu_set_from_dbus(array, allocated, &c2) == 0); + assert_se(c2.set); + assert_se(c2.allocated == c.allocated); + assert_se(memcmp(c.set, c2.set, c.allocated) == 0); +} + +static void test_cpus_in_affinity_mask(void) { + int r; + + r = cpus_in_affinity_mask(); + assert(r > 0); + log_info("cpus_in_affinity_mask: %d", r); +} + +int main(int argc, char *argv[]) { + log_info("CPU_ALLOC_SIZE(1) = %zu", CPU_ALLOC_SIZE(1)); + log_info("CPU_ALLOC_SIZE(9) = %zu", CPU_ALLOC_SIZE(9)); + log_info("CPU_ALLOC_SIZE(64) = %zu", CPU_ALLOC_SIZE(64)); + log_info("CPU_ALLOC_SIZE(65) = %zu", CPU_ALLOC_SIZE(65)); + log_info("CPU_ALLOC_SIZE(1024) = %zu", CPU_ALLOC_SIZE(1024)); + log_info("CPU_ALLOC_SIZE(1025) = %zu", CPU_ALLOC_SIZE(1025)); + log_info("CPU_ALLOC_SIZE(8191) = %zu", CPU_ALLOC_SIZE(8191)); + + test_parse_cpu_set(); + test_parse_cpu_set_extend(); + test_cpus_in_affinity_mask(); + test_cpu_set_to_from_dbus(); + + return 0; +} diff --git a/src/test/test-daemon.c b/src/test/test-daemon.c new file mode 100644 index 00000000..6ca82158 --- /dev/null +++ b/src/test/test-daemon.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "sd-daemon.h" + +#include "parse-util.h" +#include "strv.h" +#include "time-util.h" + +int main(int argc, char *argv[]) { + _cleanup_strv_free_ char **l = NULL; + int n, i; + usec_t duration = USEC_PER_SEC / 10; + + if (argc >= 2) { + unsigned x; + + assert_se(safe_atou(argv[1], &x) >= 0); + duration = x * USEC_PER_SEC; + } + + n = sd_listen_fds_with_names(false, &l); + if (n < 0) { + log_error_errno(n, "Failed to get listening fds: %m"); + return EXIT_FAILURE; + } + + for (i = 0; i < n; i++) + log_info("fd=%i name=%s\n", SD_LISTEN_FDS_START + i, l[i]); + + sd_notify(0, + "STATUS=Starting up"); + usleep(duration); + + sd_notify(0, + "STATUS=Running\n" + "READY=1"); + usleep(duration); + + sd_notify(0, + "STATUS=Reloading\n" + "RELOADING=1"); + usleep(duration); + + sd_notify(0, + "STATUS=Running\n" + "READY=1"); + usleep(duration); + + sd_notify(0, + "STATUS=Quitting\n" + "STOPPING=1"); + usleep(duration); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-date.c b/src/test/test-date.c new file mode 100644 index 00000000..7d27cfa7 --- /dev/null +++ b/src/test/test-date.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "string-util.h" +#include "tests.h" +#include "time-util.h" + +static void test_should_pass(const char *p) { + usec_t t, q; + char buf[FORMAT_TIMESTAMP_MAX], buf_relative[FORMAT_TIMESTAMP_RELATIVE_MAX]; + + log_info("Test: %s", p); + assert_se(parse_timestamp(p, &t) >= 0); + assert_se(format_timestamp_us(buf, sizeof(buf), t)); + log_info("\"%s\" → \"%s\"", p, buf); + + assert_se(parse_timestamp(buf, &q) >= 0); + if (q != t) { + char tmp[FORMAT_TIMESTAMP_MAX]; + + log_error("round-trip failed: \"%s\" → \"%s\"", + buf, format_timestamp_us(tmp, sizeof(tmp), q)); + } + assert_se(q == t); + + assert_se(format_timestamp_relative(buf_relative, sizeof(buf_relative), t)); + log_info("%s", strna(buf_relative)); +} + +static void test_should_parse(const char *p) { + usec_t t; + + log_info("Test: %s", p); + assert_se(parse_timestamp(p, &t) >= 0); + log_info("\"%s\" → \"@%" PRI_USEC "\"", p, t); +} + +static void test_should_fail(const char *p) { + usec_t t; + int r; + + log_info("Test: %s", p); + r = parse_timestamp(p, &t); + if (r >= 0) + log_info("\"%s\" → \"@%" PRI_USEC "\" (unexpected)", p, t); + else + log_info("parse_timestamp() returns %d (expected)", r); + assert_se(r < 0); +} + +static void test_one(const char *p) { + _cleanup_free_ char *with_utc; + + with_utc = strjoin(p, " UTC"); + test_should_pass(p); + test_should_pass(with_utc); +} + +static void test_one_noutc(const char *p) { + _cleanup_free_ char *with_utc; + + with_utc = strjoin(p, " UTC"); + test_should_pass(p); + test_should_fail(with_utc); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_one("17:41"); + test_one("18:42:44"); + test_one("18:42:44.0"); + test_one("18:42:44.999999999999"); + test_one("12-10-02 12:13:14"); + test_one("12-10-2 12:13:14"); + test_one("12-10-03 12:13"); + test_one("2012-12-30 18:42"); + test_one("2012-10-02"); + test_one("Tue 2012-10-02"); + test_one("yesterday"); + test_one("today"); + test_one("tomorrow"); + test_one_noutc("16:20 UTC"); + test_one_noutc("16:20 Asia/Seoul"); + test_one_noutc("tomorrow Asia/Seoul"); + test_one_noutc("2012-12-30 18:42 Asia/Seoul"); + test_one_noutc("now"); + test_one_noutc("+2d"); + test_one_noutc("+2y 4d"); + test_one_noutc("5months ago"); + test_one_noutc("@1395716396"); + test_should_parse("1970-1-1 UTC"); + test_should_pass("1970-1-1 00:00:01 UTC"); + test_should_fail("1969-12-31 UTC"); + test_should_fail("-100y"); + test_should_fail("today UTC UTC"); + test_should_fail("now Asia/Seoul"); + test_should_fail("+2d Asia/Seoul"); + test_should_fail("@1395716396 Asia/Seoul"); +#if SIZEOF_TIME_T == 8 + test_should_pass("9999-12-30 23:59:59 UTC"); + test_should_fail("9999-12-31 00:00:00 UTC"); + test_should_fail("10000-01-01 00:00:00 UTC"); +#elif SIZEOF_TIME_T == 4 + test_should_pass("2038-01-19 03:14:07 UTC"); + test_should_fail("2038-01-19 03:14:08 UTC"); +#endif + + return 0; +} diff --git a/src/test/test-dev-setup.c b/src/test/test-dev-setup.c new file mode 100644 index 00000000..9414ea6c --- /dev/null +++ b/src/test/test-dev-setup.c @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "capability-util.h" +#include "dev-setup.h" +#include "fs-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "tmpfile-util.h" + +int main(int argc, char *argv[]) { + _cleanup_(rm_rf_physical_and_freep) char *p = NULL; + const char *f; + struct stat st; + + if (have_effective_cap(CAP_DAC_OVERRIDE) <= 0) + return EXIT_TEST_SKIP; + + assert_se(mkdtemp_malloc("/tmp/test-dev-setupXXXXXX", &p) >= 0); + + f = prefix_roota(p, "/run"); + assert_se(mkdir(f, 0755) >= 0); + + assert_se(make_inaccessible_nodes(p, 1, 1) >= 0); + + f = prefix_roota(p, "/run/systemd/inaccessible/reg"); + assert_se(stat(f, &st) >= 0); + assert_se(S_ISREG(st.st_mode)); + assert_se((st.st_mode & 07777) == 0000); + + f = prefix_roota(p, "/run/systemd/inaccessible/dir"); + assert_se(stat(f, &st) >= 0); + assert_se(S_ISDIR(st.st_mode)); + assert_se((st.st_mode & 07777) == 0000); + + f = prefix_roota(p, "/run/systemd/inaccessible/fifo"); + assert_se(stat(f, &st) >= 0); + assert_se(S_ISFIFO(st.st_mode)); + assert_se((st.st_mode & 07777) == 0000); + + f = prefix_roota(p, "/run/systemd/inaccessible/sock"); + assert_se(stat(f, &st) >= 0); + assert_se(S_ISSOCK(st.st_mode)); + assert_se((st.st_mode & 07777) == 0000); + + f = prefix_roota(p, "/run/systemd/inaccessible/chr"); + if (stat(f, &st) < 0) + assert_se(errno == ENOENT); + else { + assert_se(S_ISCHR(st.st_mode)); + assert_se((st.st_mode & 07777) == 0000); + } + + f = prefix_roota(p, "/run/systemd/inaccessible/blk"); + if (stat(f, &st) < 0) + assert_se(errno == ENOENT); + else { + assert_se(S_ISBLK(st.st_mode)); + assert_se((st.st_mode & 07777) == 0000); + } + + return EXIT_SUCCESS; +} diff --git a/src/test/test-device-nodes.c b/src/test/test-device-nodes.c new file mode 100644 index 00000000..ad8d9ace --- /dev/null +++ b/src/test/test-device-nodes.c @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "device-nodes.h" +#include "string-util.h" +#include "util.h" + +/* helpers for test_encode_devnode_name */ +static char *do_encode_string(const char *in) { + size_t out_len = strlen(in) * 4 + 1; + char *out = malloc(out_len); + + assert_se(out); + assert_se(encode_devnode_name(in, out, out_len) >= 0); + puts(out); + + return out; +} + +static bool expect_encoded_as(const char *in, const char *expected) { + _cleanup_free_ char *encoded = do_encode_string(in); + return streq(encoded, expected); +} + +static void test_encode_devnode_name(void) { + assert_se(expect_encoded_as("systemd sucks", "systemd\\x20sucks")); + assert_se(expect_encoded_as("pinkiepie", "pinkiepie")); + assert_se(expect_encoded_as("valíd\\ųtf8", "valíd\\x5cųtf8")); + assert_se(expect_encoded_as("s/ash/ng", "s\\x2fash\\x2fng")); + assert_se(expect_encoded_as("/", "\\x2f")); + assert_se(expect_encoded_as("!", "\\x21")); +} + +int main(int argc, char *argv[]) { + test_encode_devnode_name(); + + return 0; +} diff --git a/src/test/test-dissect-image.c b/src/test/test-dissect-image.c new file mode 100644 index 00000000..7b32e837 --- /dev/null +++ b/src/test/test-dissect-image.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "dissect-image.h" +#include "log.h" +#include "loop-util.h" +#include "string-util.h" +#include "tests.h" + +int main(int argc, char *argv[]) { + _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; + _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; + int r, i; + + test_setup_logging(LOG_DEBUG); + + if (argc < 2) { + log_error("Requires one command line argument."); + return EXIT_FAILURE; + } + + r = loop_device_make_by_path(argv[1], O_RDONLY, &d); + if (r < 0) { + log_error_errno(r, "Failed to set up loopback device: %m"); + return EXIT_FAILURE; + } + + r = dissect_image(d->fd, NULL, 0, DISSECT_IMAGE_REQUIRE_ROOT, &m); + if (r < 0) { + log_error_errno(r, "Failed to dissect image: %m"); + return EXIT_FAILURE; + } + + for (i = 0; i < _PARTITION_DESIGNATOR_MAX; i++) { + + if (!m->partitions[i].found) + continue; + + printf("Found %s partition, %s of type %s at #%i (%s)\n", + partition_designator_to_string(i), + m->partitions[i].rw ? "writable" : "read-only", + strna(m->partitions[i].fstype), + m->partitions[i].partno, + strna(m->partitions[i].node)); + } + + return EXIT_SUCCESS; +} diff --git a/src/test/test-dlopen.c b/src/test/test-dlopen.c new file mode 100644 index 00000000..148ebaa4 --- /dev/null +++ b/src/test/test-dlopen.c @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "macro.h" + +int main(int argc, char **argv) { + void *handle; + + assert_se(handle = dlopen(argv[1], RTLD_NOW)); + assert_se(dlclose(handle) == 0); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c new file mode 100644 index 00000000..ead53117 --- /dev/null +++ b/src/test/test-dns-domain.c @@ -0,0 +1,815 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "dns-domain.h" +#include "macro.h" +#include "string-util.h" +#include "tests.h" + +static void test_dns_label_unescape_one(const char *what, const char *expect, size_t buffer_sz, int ret, int ret_ldh) { + char buffer[buffer_sz]; + int r; + const char *w = what; + + log_info("%s, %s, %zu, →%d/%d", what, expect, buffer_sz, ret, ret_ldh); + + r = dns_label_unescape(&w, buffer, buffer_sz, 0); + assert_se(r == ret); + if (r >= 0) + assert_se(streq(buffer, expect)); + + w = what; + r = dns_label_unescape(&w, buffer, buffer_sz, DNS_LABEL_LDH); + assert_se(r == ret_ldh); + if (r >= 0) + assert_se(streq(buffer, expect)); + + w = what; + r = dns_label_unescape(&w, buffer, buffer_sz, DNS_LABEL_NO_ESCAPES); + const int ret_noe = strchr(what, '\\') ? -EINVAL : ret; + assert_se(r == ret_noe); + if (r >= 0) + assert_se(streq(buffer, expect)); +} + +static void test_dns_label_unescape(void) { + log_info("/* %s */", __func__); + + test_dns_label_unescape_one("hallo", "hallo", 6, 5, 5); + test_dns_label_unescape_one("hallo", "hallo", 4, -ENOBUFS, -ENOBUFS); + test_dns_label_unescape_one("", "", 10, 0, 0); + test_dns_label_unescape_one("hallo\\.foobar", "hallo.foobar", 20, 12, -EINVAL); + test_dns_label_unescape_one("hallo.foobar", "hallo", 10, 5, 5); + test_dns_label_unescape_one("hallo\n.foobar", "hallo", 20, -EINVAL, -EINVAL); + test_dns_label_unescape_one("hallo\\", "hallo", 20, -EINVAL, -EINVAL); + test_dns_label_unescape_one("hallo\\032 ", "hallo ", 20, 7, -EINVAL); + test_dns_label_unescape_one(".", "", 20, 0, 0); + test_dns_label_unescape_one("..", "", 20, -EINVAL, -EINVAL); + test_dns_label_unescape_one(".foobar", "", 20, -EINVAL, -EINVAL); + test_dns_label_unescape_one("foobar.", "foobar", 20, 6, 6); + test_dns_label_unescape_one("foobar..", "foobar", 20, -EINVAL, -EINVAL); + test_dns_label_unescape_one("foo-bar", "foo-bar", 20, 7, 7); + test_dns_label_unescape_one("foo-", "foo-", 20, 4, -EINVAL); + test_dns_label_unescape_one("-foo", "-foo", 20, 4, -EINVAL); + test_dns_label_unescape_one("-foo-", "-foo-", 20, 5, -EINVAL); + test_dns_label_unescape_one("foo-.", "foo-", 20, 4, -EINVAL); + test_dns_label_unescape_one("foo.-", "foo", 20, 3, 3); + test_dns_label_unescape_one("foo\\032", "foo ", 20, 4, -EINVAL); + test_dns_label_unescape_one("foo\\045", "foo-", 20, 4, -EINVAL); + test_dns_label_unescape_one("głąb", "głąb", 20, 6, -EINVAL); +} + +static void test_dns_name_to_wire_format_one(const char *what, const char *expect, size_t buffer_sz, int ret) { + uint8_t buffer[buffer_sz]; + int r; + + log_info("%s, %s, %zu, →%d", what, expect, buffer_sz, ret); + + r = dns_name_to_wire_format(what, buffer, buffer_sz, false); + assert_se(r == ret); + + if (r < 0) + return; + + assert_se(!memcmp(buffer, expect, r)); +} + +static void test_dns_name_to_wire_format(void) { + static const char out0[] = { 0 }; + static const char out1[] = { 3, 'f', 'o', 'o', 0 }; + static const char out2[] = { 5, 'h', 'a', 'l', 'l', 'o', 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 }; + static const char out3[] = { 4, ' ', 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 }; + static const char out4[] = { 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 9, 'a', '1', '2', '3', '4', '5', '6', '7', '8', + 3, 'a', '1', '2', 0 }; + + log_info("/* %s */", __func__); + + test_dns_name_to_wire_format_one("", out0, sizeof(out0), sizeof(out0)); + + test_dns_name_to_wire_format_one("foo", out1, sizeof(out1), sizeof(out1)); + test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) + 1, sizeof(out1)); + test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) - 1, -ENOBUFS); + + test_dns_name_to_wire_format_one("hallo.foo.bar", out2, sizeof(out2), sizeof(out2)); + test_dns_name_to_wire_format_one("hallo.foo..bar", NULL, 32, -EINVAL); + + test_dns_name_to_wire_format_one("\\032foo.bar", out3, sizeof(out3), sizeof(out3)); + + test_dns_name_to_wire_format_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a123", NULL, 500, -EINVAL); + test_dns_name_to_wire_format_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12", out4, sizeof(out4), sizeof(out4)); +} + +static void test_dns_label_unescape_suffix_one(const char *what, const char *expect1, const char *expect2, size_t buffer_sz, int ret1, int ret2) { + char buffer[buffer_sz]; + const char *label; + int r; + + log_info("%s, %s, %s, %zu, %d, %d", what, expect1, expect2, buffer_sz, ret1, ret2); + + label = what + strlen(what); + + r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz); + assert_se(r == ret1); + if (r >= 0) + assert_se(streq(buffer, expect1)); + + r = dns_label_unescape_suffix(what, &label, buffer, buffer_sz); + assert_se(r == ret2); + if (r >= 0) + assert_se(streq(buffer, expect2)); +} + +static void test_dns_label_unescape_suffix(void) { + log_info("/* %s */", __func__); + + test_dns_label_unescape_suffix_one("hallo", "hallo", "", 6, 5, 0); + test_dns_label_unescape_suffix_one("hallo", "hallo", "", 4, -ENOBUFS, -ENOBUFS); + test_dns_label_unescape_suffix_one("", "", "", 10, 0, 0); + test_dns_label_unescape_suffix_one("hallo\\.foobar", "hallo.foobar", "", 20, 12, 0); + test_dns_label_unescape_suffix_one("hallo.foobar", "foobar", "hallo", 10, 6, 5); + test_dns_label_unescape_suffix_one("hallo.foobar\n", "foobar", "foobar", 20, -EINVAL, -EINVAL); + test_dns_label_unescape_suffix_one("hallo\\", "hallo", "hallo", 20, -EINVAL, -EINVAL); + test_dns_label_unescape_suffix_one("hallo\\032 ", "hallo ", "", 20, 7, 0); + test_dns_label_unescape_suffix_one(".", "", "", 20, 0, 0); + test_dns_label_unescape_suffix_one("..", "", "", 20, 0, -EINVAL); + test_dns_label_unescape_suffix_one(".foobar", "foobar", "", 20, 6, -EINVAL); + test_dns_label_unescape_suffix_one("foobar.", "foobar", "", 20, 6, 0); + test_dns_label_unescape_suffix_one("foo\\\\bar", "foo\\bar", "", 20, 7, 0); + test_dns_label_unescape_suffix_one("foo.bar", "bar", "foo", 20, 3, 3); + test_dns_label_unescape_suffix_one("foo..bar", "bar", "", 20, 3, -EINVAL); + test_dns_label_unescape_suffix_one("foo...bar", "bar", "", 20, 3, -EINVAL); + test_dns_label_unescape_suffix_one("foo\\.bar", "foo.bar", "", 20, 7, 0); + test_dns_label_unescape_suffix_one("foo\\\\.bar", "bar", "foo\\", 20, 3, 4); + test_dns_label_unescape_suffix_one("foo\\\\\\.bar", "foo\\.bar", "", 20, 8, 0); +} + +static void test_dns_label_escape_one(const char *what, size_t l, const char *expect, int ret) { + _cleanup_free_ char *t = NULL; + int r; + + log_info("%s, %zu, %s, →%d", what, l, expect, ret); + + r = dns_label_escape_new(what, l, &t); + assert_se(r == ret); + + if (r < 0) + return; + + assert_se(streq_ptr(expect, t)); +} + +static void test_dns_label_escape(void) { + log_info("/* %s */", __func__); + + test_dns_label_escape_one("", 0, NULL, -EINVAL); + test_dns_label_escape_one("hallo", 5, "hallo", 5); + test_dns_label_escape_one("hallo", 6, "hallo\\000", 9); + test_dns_label_escape_one("hallo hallo.foobar,waldi", 24, "hallo\\032hallo\\.foobar\\044waldi", 31); +} + +static void test_dns_name_normalize_one(const char *what, const char *expect, int ret) { + _cleanup_free_ char *t = NULL; + int r; + + r = dns_name_normalize(what, 0, &t); + assert_se(r == ret); + + if (r < 0) + return; + + assert_se(streq_ptr(expect, t)); +} + +static void test_dns_name_normalize(void) { + test_dns_name_normalize_one("", ".", 0); + test_dns_name_normalize_one("f", "f", 0); + test_dns_name_normalize_one("f.waldi", "f.waldi", 0); + test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0); + test_dns_name_normalize_one("\\000", "\\000", 0); + test_dns_name_normalize_one("..", NULL, -EINVAL); + test_dns_name_normalize_one(".foobar", NULL, -EINVAL); + test_dns_name_normalize_one("foobar.", "foobar", 0); + test_dns_name_normalize_one(".", ".", 0); +} + +static void test_dns_name_equal_one(const char *a, const char *b, int ret) { + int r; + + r = dns_name_equal(a, b); + assert_se(r == ret); + + r = dns_name_equal(b, a); + assert_se(r == ret); +} + +static void test_dns_name_equal(void) { + test_dns_name_equal_one("", "", true); + test_dns_name_equal_one("x", "x", true); + test_dns_name_equal_one("x", "x.", true); + test_dns_name_equal_one("abc.def", "abc.def", true); + test_dns_name_equal_one("abc.def", "ABC.def", true); + test_dns_name_equal_one("abc.def", "CBA.def", false); + test_dns_name_equal_one("", "xxx", false); + test_dns_name_equal_one("ab", "a", false); + test_dns_name_equal_one("\\000", "\\000", true); + test_dns_name_equal_one(".", "", true); + test_dns_name_equal_one(".", ".", true); + test_dns_name_equal_one("..", "..", -EINVAL); +} + +static void test_dns_name_between_one(const char *a, const char *b, const char *c, int ret) { + int r; + + r = dns_name_between(a, b, c); + assert_se(r == ret); + + r = dns_name_between(c, b, a); + if (ret >= 0) + assert_se(r == 0 || dns_name_equal(a, c) > 0); + else + assert_se(r == ret); +} + +static void test_dns_name_between(void) { + /* see https://tools.ietf.org/html/rfc4034#section-6.1 + Note that we use "\033.z.example" in stead of "\001.z.example" as we + consider the latter invalid */ + test_dns_name_between_one("example", "a.example", "yljkjljk.a.example", true); + test_dns_name_between_one("a.example", "yljkjljk.a.example", "Z.a.example", true); + test_dns_name_between_one("yljkjljk.a.example", "Z.a.example", "zABC.a.EXAMPLE", true); + test_dns_name_between_one("Z.a.example", "zABC.a.EXAMPLE", "z.example", true); + test_dns_name_between_one("zABC.a.EXAMPLE", "z.example", "\\033.z.example", true); + test_dns_name_between_one("z.example", "\\033.z.example", "*.z.example", true); + test_dns_name_between_one("\\033.z.example", "*.z.example", "\\200.z.example", true); + test_dns_name_between_one("*.z.example", "\\200.z.example", "example", true); + test_dns_name_between_one("\\200.z.example", "example", "a.example", true); + + test_dns_name_between_one("example", "a.example", "example", true); + test_dns_name_between_one("example", "example", "example", false); + test_dns_name_between_one("example", "example", "yljkjljk.a.example", false); + test_dns_name_between_one("example", "yljkjljk.a.example", "yljkjljk.a.example", false); + test_dns_name_between_one("hkps.pool.sks-keyservers.net", "_pgpkey-https._tcp.hkps.pool.sks-keyservers.net", "ipv4.pool.sks-keyservers.net", true); +} + +static void test_dns_name_endswith_one(const char *a, const char *b, int ret) { + assert_se(dns_name_endswith(a, b) == ret); +} + +static void test_dns_name_endswith(void) { + test_dns_name_endswith_one("", "", true); + test_dns_name_endswith_one("", "xxx", false); + test_dns_name_endswith_one("xxx", "", true); + test_dns_name_endswith_one("x", "x", true); + test_dns_name_endswith_one("x", "y", false); + test_dns_name_endswith_one("x.y", "y", true); + test_dns_name_endswith_one("x.y", "Y", true); + test_dns_name_endswith_one("x.y", "x", false); + test_dns_name_endswith_one("x.y.z", "Z", true); + test_dns_name_endswith_one("x.y.z", "y.Z", true); + test_dns_name_endswith_one("x.y.z", "x.y.Z", true); + test_dns_name_endswith_one("x.y.z", "waldo", false); + test_dns_name_endswith_one("x.y.z.u.v.w", "y.z", false); + test_dns_name_endswith_one("x.y.z.u.v.w", "u.v.w", true); + test_dns_name_endswith_one("x.y\001.z", "waldo", -EINVAL); +} + +static void test_dns_name_startswith_one(const char *a, const char *b, int ret) { + assert_se(dns_name_startswith(a, b) == ret); +} + +static void test_dns_name_startswith(void) { + test_dns_name_startswith_one("", "", true); + test_dns_name_startswith_one("", "xxx", false); + test_dns_name_startswith_one("xxx", "", true); + test_dns_name_startswith_one("x", "x", true); + test_dns_name_startswith_one("x", "y", false); + test_dns_name_startswith_one("x.y", "x.y", true); + test_dns_name_startswith_one("x.y", "y.x", false); + test_dns_name_startswith_one("x.y", "x", true); + test_dns_name_startswith_one("x.y", "X", true); + test_dns_name_startswith_one("x.y", "y", false); + test_dns_name_startswith_one("x.y", "", true); + test_dns_name_startswith_one("x.y", "X", true); +} + +static void test_dns_name_is_root(void) { + assert_se(dns_name_is_root("")); + assert_se(dns_name_is_root(".")); + assert_se(!dns_name_is_root("xxx")); + assert_se(!dns_name_is_root("xxx.")); + assert_se(!dns_name_is_root("..")); +} + +static void test_dns_name_is_single_label(void) { + assert_se(!dns_name_is_single_label("")); + assert_se(!dns_name_is_single_label(".")); + assert_se(!dns_name_is_single_label("..")); + assert_se(dns_name_is_single_label("x")); + assert_se(dns_name_is_single_label("x.")); + assert_se(!dns_name_is_single_label("xx.yy")); +} + +static void test_dns_name_reverse_one(const char *address, const char *name) { + _cleanup_free_ char *p = NULL; + union in_addr_union a, b = {}; + int familya, familyb; + + assert_se(in_addr_from_string_auto(address, &familya, &a) >= 0); + assert_se(dns_name_reverse(familya, &a, &p) >= 0); + assert_se(streq(p, name)); + assert_se(dns_name_address(p, &familyb, &b) > 0); + assert_se(familya == familyb); + assert_se(in_addr_equal(familya, &a, &b)); +} + +static void test_dns_name_reverse(void) { + test_dns_name_reverse_one("47.11.8.15", "15.8.11.47.in-addr.arpa"); + test_dns_name_reverse_one("fe80::47", "7.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa"); + test_dns_name_reverse_one("127.0.0.1", "1.0.0.127.in-addr.arpa"); + test_dns_name_reverse_one("::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa"); +} + +static void test_dns_name_concat_one(const char *a, const char *b, int r, const char *result) { + _cleanup_free_ char *p = NULL; + + assert_se(dns_name_concat(a, b, 0, &p) == r); + assert_se(streq_ptr(p, result)); +} + +static void test_dns_name_concat(void) { + test_dns_name_concat_one("", "", 0, "."); + test_dns_name_concat_one(".", "", 0, "."); + test_dns_name_concat_one("", ".", 0, "."); + test_dns_name_concat_one(".", ".", 0, "."); + test_dns_name_concat_one("foo", "bar", 0, "foo.bar"); + test_dns_name_concat_one("foo.foo", "bar.bar", 0, "foo.foo.bar.bar"); + test_dns_name_concat_one("foo", NULL, 0, "foo"); + test_dns_name_concat_one("foo", ".", 0, "foo"); + test_dns_name_concat_one("foo.", "bar.", 0, "foo.bar"); + test_dns_name_concat_one(NULL, NULL, 0, "."); + test_dns_name_concat_one(NULL, ".", 0, "."); + test_dns_name_concat_one(NULL, "foo", 0, "foo"); +} + +static void test_dns_name_is_valid_one(const char *s, int ret, int ret_ldh) { + log_info("%s, →%d", s, ret); + + assert_se(dns_name_is_valid(s) == ret); + assert_se(dns_name_is_valid_ldh(s) == ret_ldh); +} + +static void test_dns_name_is_valid(void) { + log_info("/* %s */", __func__); + + test_dns_name_is_valid_one("foo", 1, 1); + test_dns_name_is_valid_one("foo.", 1, 1); + test_dns_name_is_valid_one("foo..", 0, 0); + test_dns_name_is_valid_one("Foo", 1, 1); + test_dns_name_is_valid_one("foo.bar", 1, 1); + test_dns_name_is_valid_one("foo.bar.baz", 1, 1); + test_dns_name_is_valid_one("", 1, 1); + test_dns_name_is_valid_one("foo..bar", 0, 0); + test_dns_name_is_valid_one(".foo.bar", 0, 0); + test_dns_name_is_valid_one("foo.bar.", 1, 1); + test_dns_name_is_valid_one("foo.bar..", 0, 0); + test_dns_name_is_valid_one("\\zbar", 0, 0); + test_dns_name_is_valid_one("ä", 1, 0); + test_dns_name_is_valid_one("\n", 0, 0); + + test_dns_name_is_valid_one("dash-", 1, 0); + test_dns_name_is_valid_one("-dash", 1, 0); + test_dns_name_is_valid_one("dash-dash", 1, 1); + test_dns_name_is_valid_one("foo.dash-", 1, 0); + test_dns_name_is_valid_one("foo.-dash", 1, 0); + test_dns_name_is_valid_one("foo.dash-dash", 1, 1); + test_dns_name_is_valid_one("foo.dash-.bar", 1, 0); + test_dns_name_is_valid_one("foo.-dash.bar", 1, 0); + test_dns_name_is_valid_one("foo.dash-dash.bar", 1, 1); + test_dns_name_is_valid_one("dash-.bar", 1, 0); + test_dns_name_is_valid_one("-dash.bar", 1, 0); + test_dns_name_is_valid_one("dash-dash.bar", 1, 1); + test_dns_name_is_valid_one("-.bar", 1, 0); + test_dns_name_is_valid_one("foo.-", 1, 0); + + /* 256 characters */ + test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345", 0, 0); + + /* 255 characters */ + test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a1234", 0, 0); + + /* 254 characters */ + test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a123", 0, 0); + + /* 253 characters */ + test_dns_name_is_valid_one("a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12345678.a12", 1, 1); + + /* label of 64 chars length */ + test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a123", 0, 0); + + /* label of 63 chars length */ + test_dns_name_is_valid_one("a123456789a123456789a123456789a123456789a123456789a123456789a12", 1, 1); +} + +static void test_dns_service_name_is_valid(void) { + log_info("/* %s */", __func__); + + assert_se(dns_service_name_is_valid("Lennart's Compüter")); + assert_se(dns_service_name_is_valid("piff.paff")); + + assert_se(!dns_service_name_is_valid(NULL)); + assert_se(!dns_service_name_is_valid("")); + assert_se(!dns_service_name_is_valid("foo\nbar")); + assert_se(!dns_service_name_is_valid("foo\201bar")); + assert_se(!dns_service_name_is_valid("this is an overly long string that is certainly longer than 63 characters")); +} + +static void test_dns_srv_type_is_valid(void) { + log_info("/* %s */", __func__); + + assert_se(dns_srv_type_is_valid("_http._tcp")); + assert_se(dns_srv_type_is_valid("_foo-bar._tcp")); + assert_se(dns_srv_type_is_valid("_w._udp")); + assert_se(dns_srv_type_is_valid("_a800._tcp")); + assert_se(dns_srv_type_is_valid("_a-800._tcp")); + + assert_se(!dns_srv_type_is_valid(NULL)); + assert_se(!dns_srv_type_is_valid("")); + assert_se(!dns_srv_type_is_valid("x")); + assert_se(!dns_srv_type_is_valid("_foo")); + assert_se(!dns_srv_type_is_valid("_tcp")); + assert_se(!dns_srv_type_is_valid("_")); + assert_se(!dns_srv_type_is_valid("_foo.")); + assert_se(!dns_srv_type_is_valid("_föo._tcp")); + assert_se(!dns_srv_type_is_valid("_f\no._tcp")); + assert_se(!dns_srv_type_is_valid("_800._tcp")); + assert_se(!dns_srv_type_is_valid("_-800._tcp")); + assert_se(!dns_srv_type_is_valid("_-foo._tcp")); + assert_se(!dns_srv_type_is_valid("_piep._foo._udp")); +} + +static void test_dnssd_srv_type_is_valid(void) { + log_info("/* %s */", __func__); + + assert_se(dnssd_srv_type_is_valid("_http._tcp")); + assert_se(dnssd_srv_type_is_valid("_foo-bar._tcp")); + assert_se(dnssd_srv_type_is_valid("_w._udp")); + assert_se(dnssd_srv_type_is_valid("_a800._tcp")); + assert_se(dnssd_srv_type_is_valid("_a-800._tcp")); + + assert_se(!dnssd_srv_type_is_valid(NULL)); + assert_se(!dnssd_srv_type_is_valid("")); + assert_se(!dnssd_srv_type_is_valid("x")); + assert_se(!dnssd_srv_type_is_valid("_foo")); + assert_se(!dnssd_srv_type_is_valid("_tcp")); + assert_se(!dnssd_srv_type_is_valid("_")); + assert_se(!dnssd_srv_type_is_valid("_foo.")); + assert_se(!dnssd_srv_type_is_valid("_föo._tcp")); + assert_se(!dnssd_srv_type_is_valid("_f\no._tcp")); + assert_se(!dnssd_srv_type_is_valid("_800._tcp")); + assert_se(!dnssd_srv_type_is_valid("_-800._tcp")); + assert_se(!dnssd_srv_type_is_valid("_-foo._tcp")); + assert_se(!dnssd_srv_type_is_valid("_piep._foo._udp")); + assert_se(!dnssd_srv_type_is_valid("_foo._unknown")); +} + +static void test_dns_service_join_one(const char *a, const char *b, const char *c, int r, const char *d) { + _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL; + + log_info("%s, %s, %s, →%d, %s", a, b, c, r, d); + + assert_se(dns_service_join(a, b, c, &t) == r); + assert_se(streq_ptr(t, d)); + + if (r < 0) + return; + + assert_se(dns_service_split(t, &x, &y, &z) >= 0); + assert_se(streq_ptr(a, x)); + assert_se(streq_ptr(b, y)); + assert_se(dns_name_equal(c, z) > 0); +} + +static void test_dns_service_join(void) { + log_info("/* %s */", __func__); + + test_dns_service_join_one("", "", "", -EINVAL, NULL); + test_dns_service_join_one("", "_http._tcp", "", -EINVAL, NULL); + test_dns_service_join_one("", "_http._tcp", "foo", -EINVAL, NULL); + test_dns_service_join_one("foo", "", "foo", -EINVAL, NULL); + test_dns_service_join_one("foo", "foo", "foo", -EINVAL, NULL); + + test_dns_service_join_one("foo", "_http._tcp", "", 0, "foo._http._tcp"); + test_dns_service_join_one(NULL, "_http._tcp", "", 0, "_http._tcp"); + test_dns_service_join_one("foo", "_http._tcp", "foo", 0, "foo._http._tcp.foo"); + test_dns_service_join_one(NULL, "_http._tcp", "foo", 0, "_http._tcp.foo"); + test_dns_service_join_one("Lennart's PC", "_pc._tcp", "foo.bar.com", 0, "Lennart\\039s\\032PC._pc._tcp.foo.bar.com"); + test_dns_service_join_one(NULL, "_pc._tcp", "foo.bar.com", 0, "_pc._tcp.foo.bar.com"); +} + +static void test_dns_service_split_one(const char *joined, const char *a, const char *b, const char *c, int r) { + _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *t = NULL; + + log_info("%s, %s, %s, %s, →%d", joined, a, b, c, r); + + assert_se(dns_service_split(joined, &x, &y, &z) == r); + assert_se(streq_ptr(x, a)); + assert_se(streq_ptr(y, b)); + assert_se(streq_ptr(z, c)); + + if (r < 0) + return; + + if (y) { + assert_se(dns_service_join(x, y, z, &t) == 0); + assert_se(dns_name_equal(joined, t) > 0); + } else + assert_se(!x && dns_name_equal(z, joined) > 0); +} + +static void test_dns_service_split(void) { + log_info("/* %s */", __func__); + + test_dns_service_split_one("", NULL, NULL, ".", 0); + test_dns_service_split_one("foo", NULL, NULL, "foo", 0); + test_dns_service_split_one("foo.bar", NULL, NULL, "foo.bar", 0); + test_dns_service_split_one("_foo.bar", NULL, NULL, "_foo.bar", 0); + test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", ".", 0); + test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", ".", 0); + test_dns_service_split_one("Wuff\\032Wuff._foo._bar.waldo.com", "Wuff Wuff", "_foo._bar", "waldo.com", 0); +} + +static void test_dns_name_change_suffix_one(const char *name, const char *old_suffix, const char *new_suffix, int r, const char *result) { + _cleanup_free_ char *s = NULL; + + log_info("%s, %s, %s, →%s", name, old_suffix, new_suffix, result); + + assert_se(dns_name_change_suffix(name, old_suffix, new_suffix, &s) == r); + assert_se(streq_ptr(s, result)); +} + +static void test_dns_name_change_suffix(void) { + log_info("/* %s */", __func__); + + test_dns_name_change_suffix_one("foo.bar", "bar", "waldo", 1, "foo.waldo"); + test_dns_name_change_suffix_one("foo.bar.waldi.quux", "foo.bar.waldi.quux", "piff.paff", 1, "piff.paff"); + test_dns_name_change_suffix_one("foo.bar.waldi.quux", "bar.waldi.quux", "piff.paff", 1, "foo.piff.paff"); + test_dns_name_change_suffix_one("foo.bar.waldi.quux", "waldi.quux", "piff.paff", 1, "foo.bar.piff.paff"); + test_dns_name_change_suffix_one("foo.bar.waldi.quux", "quux", "piff.paff", 1, "foo.bar.waldi.piff.paff"); + test_dns_name_change_suffix_one("foo.bar.waldi.quux", "", "piff.paff", 1, "foo.bar.waldi.quux.piff.paff"); + test_dns_name_change_suffix_one("", "", "piff.paff", 1, "piff.paff"); + test_dns_name_change_suffix_one("", "", "", 1, "."); + test_dns_name_change_suffix_one("a", "b", "c", 0, NULL); +} + +static void test_dns_name_suffix_one(const char *name, unsigned n_labels, const char *result, int ret) { + const char *p = NULL; + + log_info("%s, %d, →%s, %d", name, n_labels, result, ret); + + assert_se(ret == dns_name_suffix(name, n_labels, &p)); + assert_se(streq_ptr(p, result)); +} + +static void test_dns_name_suffix(void) { + log_info("/* %s */", __func__); + + test_dns_name_suffix_one("foo.bar", 2, "foo.bar", 0); + test_dns_name_suffix_one("foo.bar", 1, "bar", 1); + test_dns_name_suffix_one("foo.bar", 0, "", 2); + test_dns_name_suffix_one("foo.bar", 3, NULL, -EINVAL); + test_dns_name_suffix_one("foo.bar", 4, NULL, -EINVAL); + + test_dns_name_suffix_one("bar", 1, "bar", 0); + test_dns_name_suffix_one("bar", 0, "", 1); + test_dns_name_suffix_one("bar", 2, NULL, -EINVAL); + test_dns_name_suffix_one("bar", 3, NULL, -EINVAL); + + test_dns_name_suffix_one("", 0, "", 0); + test_dns_name_suffix_one("", 1, NULL, -EINVAL); + test_dns_name_suffix_one("", 2, NULL, -EINVAL); +} + +static void test_dns_name_count_labels_one(const char *name, int n) { + log_info("%s, →%d", name, n); + + assert_se(dns_name_count_labels(name) == n); +} + +static void test_dns_name_count_labels(void) { + log_info("/* %s */", __func__); + + test_dns_name_count_labels_one("foo.bar.quux.", 3); + test_dns_name_count_labels_one("foo.bar.quux", 3); + test_dns_name_count_labels_one("foo.bar.", 2); + test_dns_name_count_labels_one("foo.bar", 2); + test_dns_name_count_labels_one("foo.", 1); + test_dns_name_count_labels_one("foo", 1); + test_dns_name_count_labels_one("", 0); + test_dns_name_count_labels_one(".", 0); + test_dns_name_count_labels_one("..", -EINVAL); +} + +static void test_dns_name_equal_skip_one(const char *a, unsigned n_labels, const char *b, int ret) { + log_info("%s, %u, %s, →%d", a, n_labels, b, ret); + + assert_se(dns_name_equal_skip(a, n_labels, b) == ret); +} + +static void test_dns_name_equal_skip(void) { + log_info("/* %s */", __func__); + + test_dns_name_equal_skip_one("foo", 0, "bar", 0); + test_dns_name_equal_skip_one("foo", 0, "foo", 1); + test_dns_name_equal_skip_one("foo", 1, "foo", 0); + test_dns_name_equal_skip_one("foo", 2, "foo", 0); + + test_dns_name_equal_skip_one("foo.bar", 0, "foo.bar", 1); + test_dns_name_equal_skip_one("foo.bar", 1, "foo.bar", 0); + test_dns_name_equal_skip_one("foo.bar", 2, "foo.bar", 0); + test_dns_name_equal_skip_one("foo.bar", 3, "foo.bar", 0); + + test_dns_name_equal_skip_one("foo.bar", 0, "bar", 0); + test_dns_name_equal_skip_one("foo.bar", 1, "bar", 1); + test_dns_name_equal_skip_one("foo.bar", 2, "bar", 0); + test_dns_name_equal_skip_one("foo.bar", 3, "bar", 0); + + test_dns_name_equal_skip_one("foo.bar", 0, "", 0); + test_dns_name_equal_skip_one("foo.bar", 1, "", 0); + test_dns_name_equal_skip_one("foo.bar", 2, "", 1); + test_dns_name_equal_skip_one("foo.bar", 3, "", 0); + + test_dns_name_equal_skip_one("", 0, "", 1); + test_dns_name_equal_skip_one("", 1, "", 0); + test_dns_name_equal_skip_one("", 1, "foo", 0); + test_dns_name_equal_skip_one("", 2, "foo", 0); +} + +static void test_dns_name_compare_func(void) { + log_info("/* %s */", __func__); + + assert_se(dns_name_compare_func("", "") == 0); + assert_se(dns_name_compare_func("", ".") == 0); + assert_se(dns_name_compare_func(".", "") == 0); + assert_se(dns_name_compare_func("foo", "foo.") == 0); + assert_se(dns_name_compare_func("foo.", "foo") == 0); + assert_se(dns_name_compare_func("foo", "foo") == 0); + assert_se(dns_name_compare_func("foo.", "foo.") == 0); + assert_se(dns_name_compare_func("heise.de", "HEISE.DE.") == 0); + + assert_se(dns_name_compare_func("de.", "heise.de") != 0); +} + +static void test_dns_name_common_suffix_one(const char *a, const char *b, const char *result) { + const char *c; + + log_info("%s, %s, →%s", a, b, result); + + assert_se(dns_name_common_suffix(a, b, &c) >= 0); + assert_se(streq(c, result)); +} + +static void test_dns_name_common_suffix(void) { + log_info("/* %s */", __func__); + + test_dns_name_common_suffix_one("", "", ""); + test_dns_name_common_suffix_one("foo", "", ""); + test_dns_name_common_suffix_one("", "foo", ""); + test_dns_name_common_suffix_one("foo", "bar", ""); + test_dns_name_common_suffix_one("bar", "foo", ""); + test_dns_name_common_suffix_one("foo", "foo", "foo"); + test_dns_name_common_suffix_one("quux.foo", "foo", "foo"); + test_dns_name_common_suffix_one("foo", "quux.foo", "foo"); + test_dns_name_common_suffix_one("this.is.a.short.sentence", "this.is.another.short.sentence", "short.sentence"); + test_dns_name_common_suffix_one("FOO.BAR", "tEST.bAR", "BAR"); +} + +static void test_dns_name_apply_idna_one(const char *s, int expected, const char *result) { + _cleanup_free_ char *buf = NULL; + int r; + + r = dns_name_apply_idna(s, &buf); + log_debug("dns_name_apply_idna: \"%s\" → %d/\"%s\" (expected %d/\"%s\")", + s, r, strnull(buf), expected, strnull(result)); + + /* Different libidn2 versions are more and less accepting + * of underscore-prefixed names. So let's list the lowest + * expected return value. */ + assert_se(r >= expected); + if (expected == 1) + assert_se(dns_name_equal(buf, result) == 1); +} + +static void test_dns_name_apply_idna(void) { +#if HAVE_LIBIDN2 || HAVE_LIBIDN + const int ret = 1; +#else + const int ret = 0; +#endif + log_info("/* %s */", __func__); + + /* IDNA2008 forbids names with hyphens in third and fourth positions + * (https://tools.ietf.org/html/rfc5891#section-4.2.3.1). + * IDNA2003 does not have this restriction + * (https://tools.ietf.org/html/rfc3490#section-5). + * This means that when using libidn we will transform and test more + * labels. If registrars follow IDNA2008 we'll just be performing a + * useless lookup. + */ +#if HAVE_LIBIDN + const int ret2 = 1; +#else + const int ret2 = 0; +#endif + + test_dns_name_apply_idna_one("", ret, ""); + test_dns_name_apply_idna_one("foo", ret, "foo"); + test_dns_name_apply_idna_one("foo.", ret, "foo"); + test_dns_name_apply_idna_one("foo.bar", ret, "foo.bar"); + test_dns_name_apply_idna_one("foo.bar.", ret, "foo.bar"); + test_dns_name_apply_idna_one("föö", ret, "xn--f-1gaa"); + test_dns_name_apply_idna_one("föö.", ret, "xn--f-1gaa"); + test_dns_name_apply_idna_one("föö.bär", ret, "xn--f-1gaa.xn--br-via"); + test_dns_name_apply_idna_one("föö.bär.", ret, "xn--f-1gaa.xn--br-via"); + test_dns_name_apply_idna_one("xn--f-1gaa.xn--br-via", ret, "xn--f-1gaa.xn--br-via"); + + test_dns_name_apply_idna_one("_443._tcp.fedoraproject.org", ret2, + "_443._tcp.fedoraproject.org"); + test_dns_name_apply_idna_one("_443", ret2, "_443"); + test_dns_name_apply_idna_one("gateway", ret, "gateway"); + test_dns_name_apply_idna_one("_gateway", ret2, "_gateway"); + + test_dns_name_apply_idna_one("r3---sn-ab5l6ne7.googlevideo.com", ret2, + ret2 ? "r3---sn-ab5l6ne7.googlevideo.com" : ""); +} + +static void test_dns_name_is_valid_or_address(void) { + log_info("/* %s */", __func__); + + assert_se(dns_name_is_valid_or_address(NULL) == 0); + assert_se(dns_name_is_valid_or_address("") == 0); + assert_se(dns_name_is_valid_or_address("foobar") > 0); + assert_se(dns_name_is_valid_or_address("foobar.com") > 0); + assert_se(dns_name_is_valid_or_address("foobar..com") == 0); + assert_se(dns_name_is_valid_or_address("foobar.com.") > 0); + assert_se(dns_name_is_valid_or_address("127.0.0.1") > 0); + assert_se(dns_name_is_valid_or_address("::") > 0); + assert_se(dns_name_is_valid_or_address("::1") > 0); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_dns_label_unescape(); + test_dns_label_unescape_suffix(); + test_dns_label_escape(); + test_dns_name_normalize(); + test_dns_name_equal(); + test_dns_name_endswith(); + test_dns_name_startswith(); + test_dns_name_between(); + test_dns_name_is_root(); + test_dns_name_is_single_label(); + test_dns_name_reverse(); + test_dns_name_concat(); + test_dns_name_is_valid(); + test_dns_name_to_wire_format(); + test_dns_service_name_is_valid(); + test_dns_srv_type_is_valid(); + test_dnssd_srv_type_is_valid(); + test_dns_service_join(); + test_dns_service_split(); + test_dns_name_change_suffix(); + test_dns_name_suffix(); + test_dns_name_count_labels(); + test_dns_name_equal_skip(); + test_dns_name_compare_func(); + test_dns_name_common_suffix(); + test_dns_name_apply_idna(); + test_dns_name_is_valid_or_address(); + + return 0; +} diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c new file mode 100644 index 00000000..92692bd4 --- /dev/null +++ b/src/test/test-ellipsize.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "def.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "util.h" +#include "utf8.h" + +static void test_ellipsize_mem_one(const char *s, size_t old_length, size_t new_length) { + _cleanup_free_ char *n = NULL; + _cleanup_free_ char *t1 = NULL, *t2 = NULL, *t3 = NULL; + char buf[LINE_MAX]; + bool has_wide_chars; + size_t max_width; + + n = memdup_suffix0(s, old_length); + + if (!utf8_is_valid(n)) + /* We don't support invalid sequences… */ + return; + + /* Report out inputs. We duplicate the data so that cellescape + * can properly report truncated multibyte sequences. */ + log_info("%s \"%s\" old_length=%zu/%zu new_length=%zu", __func__, + cellescape(buf, sizeof buf, n), + old_length, utf8_console_width(n), + new_length); + + /* To keep this test simple, any case with wide chars starts with this glyph */ + has_wide_chars = startswith(s, "ä½ "); + max_width = MIN(utf8_console_width(n), new_length); + + t1 = ellipsize_mem(n, old_length, new_length, 30); + log_info("30%% → %s utf8_console_width=%zu", t1, utf8_console_width(t1)); + if (!has_wide_chars) + assert_se(utf8_console_width(t1) == max_width); + else + assert_se(utf8_console_width(t1) <= max_width); + + t2 = ellipsize_mem(n, old_length, new_length, 90); + log_info("90%% → %s utf8_console_width=%zu", t2, utf8_console_width(t2)); + if (!has_wide_chars) + assert_se(utf8_console_width(t2) == max_width); + else + assert_se(utf8_console_width(t2) <= max_width); + + t3 = ellipsize_mem(n, old_length, new_length, 100); + log_info("100%% → %s utf8_console_width=%zu", t3, utf8_console_width(t3)); + if (!has_wide_chars) + assert_se(utf8_console_width(t3) == max_width); + else + assert_se(utf8_console_width(t3) <= max_width); + + if (new_length >= old_length) { + assert_se(streq(t1, n)); + assert_se(streq(t2, n)); + assert_se(streq(t3, n)); + } +} + +static void test_ellipsize_mem(void) { + const char *s; + ssize_t l, k; + + FOREACH_STRING(s, + "_XXXXXXXXXXX_", /* ASCII */ + "_aąęółśćńżźć_", /* two-byte utf-8 */ + "გამარჯობა", /* multi-byte utf-8 */ + "你好世界", /* wide characters */ + "你გą世óoó界") /* a mix */ + + for (l = strlen(s); l >= 0; l--) + for (k = strlen(s) + 1; k >= 0; k--) + test_ellipsize_mem_one(s, l, k); +} + +static void test_ellipsize_one(const char *p) { + _cleanup_free_ char *t; + t = ellipsize(p, columns(), 70); + puts(t); + free(t); + t = ellipsize(p, columns(), 0); + puts(t); + free(t); + t = ellipsize(p, columns(), 100); + puts(t); + free(t); + t = ellipsize(p, 0, 50); + puts(t); + free(t); + t = ellipsize(p, 1, 50); + puts(t); + free(t); + t = ellipsize(p, 2, 50); + puts(t); + free(t); + t = ellipsize(p, 3, 50); + puts(t); + free(t); + t = ellipsize(p, 4, 50); + puts(t); + free(t); + t = ellipsize(p, 5, 50); + puts(t); +} + +static void test_ellipsize(void) { + test_ellipsize_one(DIGITS LETTERS DIGITS LETTERS); + test_ellipsize_one("한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어한국어"); + test_ellipsize_one("-日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国日本国"); + test_ellipsize_one("中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国中国-中国中国中国中国中国中国中国中国中国中国中国中国中国"); + test_ellipsize_one("sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd sÿstëmd"); + test_ellipsize_one("🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮🐮"); + test_ellipsize_one("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); + test_ellipsize_one("shórt"); +} + +int main(int argc, char *argv[]) { + test_ellipsize_mem(); + test_ellipsize(); + + return 0; +} diff --git a/src/test/test-emergency-action.c b/src/test/test-emergency-action.c new file mode 100644 index 00000000..8ce28ed9 --- /dev/null +++ b/src/test/test-emergency-action.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "emergency-action.h" +#include "tests.h" + +static void test_parse_emergency_action(void) { + EmergencyAction x; + + log_info("/* %s */", __func__); + + assert_se(parse_emergency_action("none", false, &x) == 0); + assert_se(x == EMERGENCY_ACTION_NONE); + assert_se(parse_emergency_action("reboot", false, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("reboot-force", false, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("reboot-immediate", false, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("poweroff", false, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("poweroff-force", false, &x) == -EOPNOTSUPP); + assert_se(parse_emergency_action("poweroff-immediate", false, &x) == -EOPNOTSUPP); + assert_se(x == EMERGENCY_ACTION_NONE); + assert_se(parse_emergency_action("exit", false, &x) == 0); + assert_se(x == EMERGENCY_ACTION_EXIT); + assert_se(parse_emergency_action("exit-force", false, &x) == 0); + assert_se(x == EMERGENCY_ACTION_EXIT_FORCE); + assert_se(parse_emergency_action("exit-forcee", false, &x) == -EINVAL); + + assert_se(parse_emergency_action("none", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_NONE); + assert_se(parse_emergency_action("reboot", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_REBOOT); + assert_se(parse_emergency_action("reboot-force", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_REBOOT_FORCE); + assert_se(parse_emergency_action("reboot-immediate", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_REBOOT_IMMEDIATE); + assert_se(parse_emergency_action("poweroff", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_POWEROFF); + assert_se(parse_emergency_action("poweroff-force", true, &x) == 0); + assert_se(x == EMERGENCY_ACTION_POWEROFF_FORCE); + assert_se(parse_emergency_action("poweroff-immediate", true, &x) == 0); + assert_se(parse_emergency_action("exit", true, &x) == 0); + assert_se(parse_emergency_action("exit-force", true, &x) == 0); + assert_se(parse_emergency_action("exit-forcee", true, &x) == -EINVAL); + assert_se(x == EMERGENCY_ACTION_EXIT_FORCE); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_INFO); + + test_parse_emergency_action(); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-engine.c b/src/test/test-engine.c new file mode 100644 index 00000000..b8351141 --- /dev/null +++ b/src/test/test-engine.c @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "bus-util.h" +#include "manager.h" +#include "rm-rf.h" +#include "strv.h" +#include "tests.h" +#include "service.h" + +int main(int argc, char *argv[]) { + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL; + _cleanup_(manager_freep) Manager *m = NULL; + Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL, + *h = NULL, *i = NULL, *a_conj = NULL, *unit_with_multiple_dashes = NULL; + Job *j; + int r; + + test_setup_logging(LOG_DEBUG); + + r = enter_cgroup_subroot(NULL); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + /* prepare the test */ + assert_se(set_unit_path(get_testdata_dir()) >= 0); + assert_se(runtime_dir = setup_fake_runtime_dir()); + r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m); + if (manager_errno_skip_test(r)) + return log_tests_skipped_errno(r, "manager_new"); + assert_se(r >= 0); + assert_se(manager_startup(m, NULL, NULL) >= 0); + + printf("Load1:\n"); + assert_se(manager_load_startable_unit_or_warn(m, "a.service", NULL, &a) >= 0); + assert_se(manager_load_startable_unit_or_warn(m, "b.service", NULL, &b) >= 0); + assert_se(manager_load_startable_unit_or_warn(m, "c.service", NULL, &c) >= 0); + manager_dump_units(m, stdout, "\t"); + + printf("Test1: (Trivial)\n"); + r = manager_add_job(m, JOB_START, c, JOB_REPLACE, NULL, &err, &j); + if (sd_bus_error_is_set(&err)) + log_error("error: %s: %s", err.name, err.message); + assert_se(r == 0); + manager_dump_jobs(m, stdout, "\t"); + + printf("Load2:\n"); + manager_clear_jobs(m); + assert_se(manager_load_startable_unit_or_warn(m, "d.service", NULL, &d) >= 0); + assert_se(manager_load_startable_unit_or_warn(m, "e.service", NULL, &e) >= 0); + manager_dump_units(m, stdout, "\t"); + + printf("Test2: (Cyclic Order, Unfixable)\n"); + assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, NULL, &j) == -EDEADLK); + manager_dump_jobs(m, stdout, "\t"); + + printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n"); + assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, NULL, &j) == 0); + manager_dump_jobs(m, stdout, "\t"); + + printf("Test4: (Identical transaction)\n"); + assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, NULL, &j) == 0); + manager_dump_jobs(m, stdout, "\t"); + + printf("Load3:\n"); + assert_se(manager_load_startable_unit_or_warn(m, "g.service", NULL, &g) >= 0); + manager_dump_units(m, stdout, "\t"); + + printf("Test5: (Colliding transaction, fail)\n"); + assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, NULL, &j) == -EDEADLK); + + printf("Test6: (Colliding transaction, replace)\n"); + assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, NULL, &j) == 0); + manager_dump_jobs(m, stdout, "\t"); + + printf("Test7: (Unmergeable job type, fail)\n"); + assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, NULL, &j) == -EDEADLK); + + printf("Test8: (Mergeable job type, fail)\n"); + assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, NULL, &j) == 0); + manager_dump_jobs(m, stdout, "\t"); + + printf("Test9: (Unmergeable job type, replace)\n"); + assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, NULL, &j) == 0); + manager_dump_jobs(m, stdout, "\t"); + + printf("Load4:\n"); + assert_se(manager_load_startable_unit_or_warn(m, "h.service", NULL, &h) >= 0); + manager_dump_units(m, stdout, "\t"); + + printf("Test10: (Unmergeable job type of auxiliary job, fail)\n"); + assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, NULL, &j) == 0); + manager_dump_jobs(m, stdout, "\t"); + + printf("Load5:\n"); + manager_clear_jobs(m); + assert_se(manager_load_startable_unit_or_warn(m, "i.service", NULL, &i) >= 0); + SERVICE(a)->state = SERVICE_RUNNING; + SERVICE(d)->state = SERVICE_RUNNING; + manager_dump_units(m, stdout, "\t"); + + printf("Test11: (Start/stop job ordering, execution cycle)\n"); + assert_se(manager_add_job(m, JOB_START, i, JOB_FAIL, NULL, NULL, &j) == 0); + assert_se(unit_has_job_type(a, JOB_STOP)); + assert_se(unit_has_job_type(d, JOB_STOP)); + assert_se(unit_has_job_type(b, JOB_START)); + manager_dump_jobs(m, stdout, "\t"); + + printf("Load6:\n"); + manager_clear_jobs(m); + assert_se(manager_load_startable_unit_or_warn(m, "a-conj.service", NULL, &a_conj) >= 0); + SERVICE(a)->state = SERVICE_DEAD; + manager_dump_units(m, stdout, "\t"); + + printf("Test12: (Trivial cycle, Unfixable)\n"); + assert_se(manager_add_job(m, JOB_START, a_conj, JOB_REPLACE, NULL, NULL, &j) == -EDEADLK); + manager_dump_jobs(m, stdout, "\t"); + + assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], b)); + assert_se(!hashmap_get(b->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a)); + assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], c)); + assert_se(!hashmap_get(c->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a)); + + assert_se(unit_add_dependency(a, UNIT_PROPAGATES_RELOAD_TO, b, true, UNIT_DEPENDENCY_UDEV) == 0); + assert_se(unit_add_dependency(a, UNIT_PROPAGATES_RELOAD_TO, c, true, UNIT_DEPENDENCY_PROC_SWAP) == 0); + + assert_se(hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], b)); + assert_se(hashmap_get(b->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a)); + assert_se(hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], c)); + assert_se(hashmap_get(c->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a)); + + unit_remove_dependencies(a, UNIT_DEPENDENCY_UDEV); + + assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], b)); + assert_se(!hashmap_get(b->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a)); + assert_se(hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], c)); + assert_se(hashmap_get(c->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a)); + + unit_remove_dependencies(a, UNIT_DEPENDENCY_PROC_SWAP); + + assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], b)); + assert_se(!hashmap_get(b->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a)); + assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], c)); + assert_se(!hashmap_get(c->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a)); + + assert_se(manager_load_unit(m, "unit-with-multiple-dashes.service", NULL, NULL, &unit_with_multiple_dashes) >= 0); + + assert_se(strv_equal(unit_with_multiple_dashes->documentation, STRV_MAKE("man:test", "man:override2", "man:override3"))); + assert_se(streq_ptr(unit_with_multiple_dashes->description, "override4")); + + return 0; +} diff --git a/src/test/test-env-file.c b/src/test/test-env-file.c new file mode 100644 index 00000000..47f86a56 --- /dev/null +++ b/src/test/test-env-file.c @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "env-file.h" +#include "fd-util.h" +#include "fs-util.h" +#include "macro.h" +#include "strv.h" +#include "tests.h" +#include "tmpfile-util.h" + +#define env_file_1 \ + "a=a\n" \ + "b=b\\\n" \ + "c\n" \ + "d=d\\\n" \ + "e\\\n" \ + "f\n" \ + "g=g\\ \n" \ + "h=h\n" \ + "i=i\\" + +#define env_file_2 \ + "a=a\\\n" + +#define env_file_3 \ + "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \ + "#--nouser-config \\\n" \ + "normal=line" + +#define env_file_4 \ + "# Generated\n" \ + "\n" \ + "HWMON_MODULES=\"coretemp f71882fg\"\n" \ + "\n" \ + "# For compatibility reasons\n" \ + "\n" \ + "MODULE_0=coretemp\n" \ + "MODULE_1=f71882fg" + +#define env_file_5 \ + "a=\n" \ + "b=" + +static void test_load_env_file_1(void) { + _cleanup_strv_free_ char **data = NULL; + int r; + + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; + _cleanup_close_ int fd; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, env_file_1, strlen(env_file_1)) == strlen(env_file_1)); + + r = load_env_file(NULL, name, &data); + assert_se(r == 0); + assert_se(streq(data[0], "a=a")); + assert_se(streq(data[1], "b=bc")); + assert_se(streq(data[2], "d=def")); + assert_se(streq(data[3], "g=g ")); + assert_se(streq(data[4], "h=h")); + assert_se(streq(data[5], "i=i")); + assert_se(data[6] == NULL); +} + +static void test_load_env_file_2(void) { + _cleanup_strv_free_ char **data = NULL; + int r; + + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; + _cleanup_close_ int fd; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, env_file_2, strlen(env_file_2)) == strlen(env_file_2)); + + r = load_env_file(NULL, name, &data); + assert_se(r == 0); + assert_se(streq(data[0], "a=a")); + assert_se(data[1] == NULL); +} + +static void test_load_env_file_3(void) { + _cleanup_strv_free_ char **data = NULL; + int r; + + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; + _cleanup_close_ int fd; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, env_file_3, strlen(env_file_3)) == strlen(env_file_3)); + + r = load_env_file(NULL, name, &data); + assert_se(r == 0); + assert_se(data == NULL); +} + +static void test_load_env_file_4(void) { + _cleanup_strv_free_ char **data = NULL; + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; + _cleanup_close_ int fd; + int r; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, env_file_4, strlen(env_file_4)) == strlen(env_file_4)); + + r = load_env_file(NULL, name, &data); + assert_se(r == 0); + assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg")); + assert_se(streq(data[1], "MODULE_0=coretemp")); + assert_se(streq(data[2], "MODULE_1=f71882fg")); + assert_se(data[3] == NULL); +} + +static void test_load_env_file_5(void) { + _cleanup_strv_free_ char **data = NULL; + int r; + + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; + _cleanup_close_ int fd; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, env_file_5, strlen(env_file_5)) == strlen(env_file_5)); + + r = load_env_file(NULL, name, &data); + assert_se(r == 0); + assert_se(streq(data[0], "a=")); + assert_se(streq(data[1], "b=")); + assert_se(data[2] == NULL); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + test_load_env_file_1(); + test_load_env_file_2(); + test_load_env_file_3(); + test_load_env_file_4(); + test_load_env_file_5(); +} diff --git a/src/test/test-env-util.c b/src/test/test-env-util.c new file mode 100644 index 00000000..f0ffe897 --- /dev/null +++ b/src/test/test-env-util.c @@ -0,0 +1,323 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "serialize.h" +#include "string-util.h" +#include "strv.h" +#include "util.h" + +static void test_strv_env_delete(void) { + _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL; + + a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF"); + assert_se(a); + + b = strv_new("PIEP", "FOO"); + assert_se(b); + + c = strv_new("SCHLUMPF"); + assert_se(c); + + d = strv_env_delete(a, 2, b, c); + assert_se(d); + + assert_se(streq(d[0], "WALDO=WALDO")); + assert_se(streq(d[1], "WALDO=")); + assert_se(strv_length(d) == 2); +} + +static void test_strv_env_get(void) { + char **l; + + l = STRV_MAKE("ONE_OR_TWO=1", "THREE=3", "ONE_OR_TWO=2", "FOUR=4"); + + assert_se(streq(strv_env_get(l, "ONE_OR_TWO"), "2")); + assert_se(streq(strv_env_get(l, "THREE"), "3")); + assert_se(streq(strv_env_get(l, "FOUR"), "4")); +} + +static void test_strv_env_unset(void) { + _cleanup_strv_free_ char **l = NULL; + + l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES"); + assert_se(l); + + assert_se(strv_env_unset(l, "SCHLUMPF") == l); + + assert_se(streq(l[0], "PIEP")); + assert_se(streq(l[1], "NANANANA=YES")); + assert_se(strv_length(l) == 2); +} + +static void test_strv_env_set(void) { + _cleanup_strv_free_ char **l = NULL, **r = NULL; + + l = strv_new("PIEP", "SCHLUMPF=SMURFF", "NANANANA=YES"); + assert_se(l); + + r = strv_env_set(l, "WALDO=WALDO"); + assert_se(r); + + assert_se(streq(r[0], "PIEP")); + assert_se(streq(r[1], "SCHLUMPF=SMURFF")); + assert_se(streq(r[2], "NANANANA=YES")); + assert_se(streq(r[3], "WALDO=WALDO")); + assert_se(strv_length(r) == 4); +} + +static void test_strv_env_merge(void) { + _cleanup_strv_free_ char **a = NULL, **b = NULL, **r = NULL; + + a = strv_new("FOO=BAR", "WALDO=WALDO", "WALDO=", "PIEP", "SCHLUMPF=SMURF"); + assert_se(a); + + b = strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES"); + assert_se(b); + + r = strv_env_merge(2, a, b); + assert_se(r); + assert_se(streq(r[0], "FOO=")); + assert_se(streq(r[1], "WALDO=")); + assert_se(streq(r[2], "PIEP")); + assert_se(streq(r[3], "SCHLUMPF=SMURFF")); + assert_se(streq(r[4], "PIEP=")); + assert_se(streq(r[5], "NANANANA=YES")); + assert_se(strv_length(r) == 6); + + assert_se(strv_env_clean(r) == r); + assert_se(streq(r[0], "FOO=")); + assert_se(streq(r[1], "WALDO=")); + assert_se(streq(r[2], "SCHLUMPF=SMURFF")); + assert_se(streq(r[3], "PIEP=")); + assert_se(streq(r[4], "NANANANA=YES")); + assert_se(strv_length(r) == 5); +} + +static void test_env_strv_get_n(void) { + const char *_env[] = { + "FOO=NO NO NO", + "FOO=BAR BAR", + "BAR=waldo", + "PATH=unset", + NULL + }; + char **env = (char**) _env; + + assert_se(streq(strv_env_get_n(env, "FOO__", 3, 0), "BAR BAR")); + assert_se(streq(strv_env_get_n(env, "FOO__", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR")); + assert_se(streq(strv_env_get_n(env, "FOO", 3, 0), "BAR BAR")); + assert_se(streq(strv_env_get_n(env, "FOO", 3, REPLACE_ENV_USE_ENVIRONMENT), "BAR BAR")); + + assert_se(streq(strv_env_get_n(env, "PATH__", 4, 0), "unset")); + assert_se(streq(strv_env_get_n(env, "PATH", 4, 0), "unset")); + assert_se(streq(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset")); + assert_se(streq(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT), "unset")); + + env[3] = NULL; /* kill our $PATH */ + + assert_se(!strv_env_get_n(env, "PATH__", 4, 0)); + assert_se(!strv_env_get_n(env, "PATH", 4, 0)); + assert_se(streq_ptr(strv_env_get_n(env, "PATH__", 4, REPLACE_ENV_USE_ENVIRONMENT), + getenv("PATH"))); + assert_se(streq_ptr(strv_env_get_n(env, "PATH", 4, REPLACE_ENV_USE_ENVIRONMENT), + getenv("PATH"))); +} + +static void test_replace_env(bool braceless) { + const char *env[] = { + "FOO=BAR BAR", + "BAR=waldo", + NULL + }; + _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL; + unsigned flags = REPLACE_ENV_ALLOW_BRACELESS*braceless; + + t = replace_env("FOO=$FOO=${FOO}", (char**) env, flags); + assert_se(streq(t, braceless ? "FOO=BAR BAR=BAR BAR" : "FOO=$FOO=BAR BAR")); + + s = replace_env("BAR=$BAR=${BAR}", (char**) env, flags); + assert_se(streq(s, braceless ? "BAR=waldo=waldo" : "BAR=$BAR=waldo")); + + q = replace_env("BARBAR=$BARBAR=${BARBAR}", (char**) env, flags); + assert_se(streq(q, braceless ? "BARBAR==" : "BARBAR=$BARBAR=")); + + r = replace_env("BAR=$BAR$BAR${BAR}${BAR}", (char**) env, flags); + assert_se(streq(r, braceless ? "BAR=waldowaldowaldowaldo" : "BAR=$BAR$BARwaldowaldo")); + + p = replace_env("${BAR}$BAR$BAR", (char**) env, flags); + assert_se(streq(p, braceless ? "waldowaldowaldo" : "waldo$BAR$BAR")); +} + +static void test_replace_env2(bool extended) { + const char *env[] = { + "FOO=foo", + "BAR=bar", + NULL + }; + _cleanup_free_ char *t = NULL, *s = NULL, *q = NULL, *r = NULL, *p = NULL, *x = NULL; + unsigned flags = REPLACE_ENV_ALLOW_EXTENDED*extended; + + t = replace_env("FOO=${FOO:-${BAR}}", (char**) env, flags); + assert_se(streq(t, extended ? "FOO=foo" : "FOO=${FOO:-bar}")); + + s = replace_env("BAR=${XXX:-${BAR}}", (char**) env, flags); + assert_se(streq(s, extended ? "BAR=bar" : "BAR=${XXX:-bar}")); + + q = replace_env("XXX=${XXX:+${BAR}}", (char**) env, flags); + assert_se(streq(q, extended ? "XXX=" : "XXX=${XXX:+bar}")); + + r = replace_env("FOO=${FOO:+${BAR}}", (char**) env, flags); + assert_se(streq(r, extended ? "FOO=bar" : "FOO=${FOO:+bar}")); + + p = replace_env("FOO=${FOO:-${BAR}post}", (char**) env, flags); + assert_se(streq(p, extended ? "FOO=foo" : "FOO=${FOO:-barpost}")); + + x = replace_env("XXX=${XXX:+${BAR}post}", (char**) env, flags); + assert_se(streq(x, extended ? "XXX=" : "XXX=${XXX:+barpost}")); +} + +static void test_replace_env_argv(void) { + const char *env[] = { + "FOO=BAR BAR", + "BAR=waldo", + NULL + }; + const char *line[] = { + "FOO$FOO", + "FOO$FOOFOO", + "FOO${FOO}$FOO", + "FOO${FOO}", + "${FOO}", + "$FOO", + "$FOO$FOO", + "${FOO}${BAR}", + "${FOO", + "FOO$$${FOO}", + "$$FOO${FOO}", + "${FOO:-${BAR}}", + "${QUUX:-${FOO}}", + "${FOO:+${BAR}}", + "${QUUX:+${BAR}}", + "${FOO:+|${BAR}|}}", + "${FOO:+|${BAR}{|}", + NULL + }; + _cleanup_strv_free_ char **r = NULL; + + r = replace_env_argv((char**) line, (char**) env); + assert_se(r); + assert_se(streq(r[0], "FOO$FOO")); + assert_se(streq(r[1], "FOO$FOOFOO")); + assert_se(streq(r[2], "FOOBAR BAR$FOO")); + assert_se(streq(r[3], "FOOBAR BAR")); + assert_se(streq(r[4], "BAR BAR")); + assert_se(streq(r[5], "BAR")); + assert_se(streq(r[6], "BAR")); + assert_se(streq(r[7], "BAR BARwaldo")); + assert_se(streq(r[8], "${FOO")); + assert_se(streq(r[9], "FOO$BAR BAR")); + assert_se(streq(r[10], "$FOOBAR BAR")); + assert_se(streq(r[11], "${FOO:-waldo}")); + assert_se(streq(r[12], "${QUUX:-BAR BAR}")); + assert_se(streq(r[13], "${FOO:+waldo}")); + assert_se(streq(r[14], "${QUUX:+waldo}")); + assert_se(streq(r[15], "${FOO:+|waldo|}}")); + assert_se(streq(r[16], "${FOO:+|waldo{|}")); + assert_se(strv_length(r) == 17); +} + +static void test_env_clean(void) { + _cleanup_strv_free_ char **e; + + e = strv_new("FOOBAR=WALDO", + "FOOBAR=WALDO", + "FOOBAR", + "F", + "X=", + "F=F", + "=", + "=F", + "", + "0000=000", + "äöüß=abcd", + "abcd=äöüß", + "xyz\n=xyz", + "xyz=xyz\n", + "another=one", + "another=final one"); + assert_se(e); + assert_se(!strv_env_is_valid(e)); + assert_se(strv_env_clean(e) == e); + assert_se(strv_env_is_valid(e)); + + assert_se(streq(e[0], "FOOBAR=WALDO")); + assert_se(streq(e[1], "X=")); + assert_se(streq(e[2], "F=F")); + assert_se(streq(e[3], "abcd=äöüß")); + assert_se(streq(e[4], "xyz=xyz\n")); + assert_se(streq(e[5], "another=final one")); + assert_se(e[6] == NULL); +} + +static void test_env_name_is_valid(void) { + assert_se(env_name_is_valid("test")); + + assert_se(!env_name_is_valid(NULL)); + assert_se(!env_name_is_valid("")); + assert_se(!env_name_is_valid("xxx\a")); + assert_se(!env_name_is_valid("xxx\007b")); + assert_se(!env_name_is_valid("\007\009")); + assert_se(!env_name_is_valid("5_starting_with_a_number_is_wrong")); + assert_se(!env_name_is_valid("#¤%&?_only_numbers_letters_and_underscore_allowed")); +} + +static void test_env_value_is_valid(void) { + assert_se(env_value_is_valid("")); + assert_se(env_value_is_valid("głąb kapuściany")); + assert_se(env_value_is_valid("printf \"\\x1b]0;\\x07\"")); + assert_se(env_value_is_valid("tab\tcharacter")); + assert_se(env_value_is_valid("new\nline")); +} + +static void test_env_assignment_is_valid(void) { + assert_se(env_assignment_is_valid("a=")); + assert_se(env_assignment_is_valid("b=głąb kapuściany")); + assert_se(env_assignment_is_valid("c=\\007\\009\\011")); + assert_se(env_assignment_is_valid("e=printf \"\\x1b]0;\\x07\"")); + assert_se(env_assignment_is_valid("f=tab\tcharacter")); + assert_se(env_assignment_is_valid("g=new\nline")); + + assert_se(!env_assignment_is_valid("=")); + assert_se(!env_assignment_is_valid("a b=")); + assert_se(!env_assignment_is_valid("a =")); + assert_se(!env_assignment_is_valid(" b=")); + /* no dots or dashes: http://tldp.org/LDP/abs/html/gotchas.html */ + assert_se(!env_assignment_is_valid("a.b=")); + assert_se(!env_assignment_is_valid("a-b=")); + assert_se(!env_assignment_is_valid("\007=głąb kapuściany")); + assert_se(!env_assignment_is_valid("c\009=\007\009\011")); + assert_se(!env_assignment_is_valid("głąb=printf \"\x1b]0;\x07\"")); +} + +int main(int argc, char *argv[]) { + test_strv_env_delete(); + test_strv_env_get(); + test_strv_env_unset(); + test_strv_env_set(); + test_strv_env_merge(); + test_env_strv_get_n(); + test_replace_env(false); + test_replace_env(true); + test_replace_env2(false); + test_replace_env2(true); + test_replace_env_argv(); + test_env_clean(); + test_env_name_is_valid(); + test_env_value_is_valid(); + test_env_assignment_is_valid(); + + return 0; +} diff --git a/src/test/test-escape.c b/src/test/test-escape.c new file mode 100644 index 00000000..add17f95 --- /dev/null +++ b/src/test/test-escape.c @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "escape.h" +#include "macro.h" +#include "tests.h" + +static void test_cescape(void) { + _cleanup_free_ char *t; + + assert_se(t = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313")); + assert_se(streq(t, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313")); +} + +static void test_xescape(void) { + _cleanup_free_ char *t; + + assert_se(t = xescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", "")); + assert_se(streq(t, "abc\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\\x7f\\x9c\\xcb")); +} + +static void test_xescape_full(bool eight_bits) { + const char* escaped = !eight_bits ? + "a\\x62c\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\\x7f\\x9c\\xcb" : + "a\\x62c\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\177\234\313"; + const unsigned full_fit = !eight_bits ? 55 : 46; + + for (unsigned i = 0; i < 60; i++) { + _cleanup_free_ char *t; + + assert_se(t = xescape_full("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", "b", i, eight_bits)); + + log_info("%02d: %s", i, t); + + if (i >= full_fit) + assert_se(streq(t, escaped)); + else if (i >= 3) { + /* We need up to four columns, so up to three three columns may be wasted */ + assert_se(strlen(t) == i || strlen(t) == i - 1 || strlen(t) == i - 2 || strlen(t) == i - 3); + assert_se(strneq(t, escaped, i - 3) || strneq(t, escaped, i - 4) || + strneq(t, escaped, i - 5) || strneq(t, escaped, i - 6)); + assert_se(endswith(t, "...")); + } else { + assert_se(strlen(t) == i); + assert_se(strneq(t, "...", i)); + } + } +} + +static void test_cunescape(void) { + _cleanup_free_ char *unescaped; + + assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0); + assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00")); + unescaped = mfree(unescaped); + + /* incomplete sequences */ + assert_se(cunescape("\\x0", 0, &unescaped) < 0); + assert_se(cunescape("\\x0", UNESCAPE_RELAX, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, "\\x0")); + unescaped = mfree(unescaped); + + assert_se(cunescape("\\x", 0, &unescaped) < 0); + assert_se(cunescape("\\x", UNESCAPE_RELAX, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, "\\x")); + unescaped = mfree(unescaped); + + assert_se(cunescape("\\", 0, &unescaped) < 0); + assert_se(cunescape("\\", UNESCAPE_RELAX, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, "\\")); + unescaped = mfree(unescaped); + + assert_se(cunescape("\\11", 0, &unescaped) < 0); + assert_se(cunescape("\\11", UNESCAPE_RELAX, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, "\\11")); + unescaped = mfree(unescaped); + + assert_se(cunescape("\\1", 0, &unescaped) < 0); + assert_se(cunescape("\\1", UNESCAPE_RELAX, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, "\\1")); + unescaped = mfree(unescaped); + + assert_se(cunescape("\\u0000", 0, &unescaped) < 0); + assert_se(cunescape("\\u00DF\\U000000df\\u03a0\\U00000041", UNESCAPE_RELAX, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, "ßßΠA")); + unescaped = mfree(unescaped); + + assert_se(cunescape("\\073", 0, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, ";")); + unescaped = mfree(unescaped); + + assert_se(cunescape("A=A\\\\x0aB", 0, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, "A=A\\x0aB")); + unescaped = mfree(unescaped); + + assert_se(cunescape("A=A\\\\x0aB", UNESCAPE_RELAX, &unescaped) >= 0); + assert_se(streq_ptr(unescaped, "A=A\\x0aB")); +} + +static void test_shell_escape_one(const char *s, const char *bad, const char *expected) { + _cleanup_free_ char *r; + + assert_se(r = shell_escape(s, bad)); + assert_se(streq_ptr(r, expected)); +} + +static void test_shell_escape(void) { + test_shell_escape_one("", "", ""); + test_shell_escape_one("\\", "", "\\\\"); + test_shell_escape_one("foobar", "", "foobar"); + test_shell_escape_one("foobar", "o", "f\\o\\obar"); + test_shell_escape_one("foo:bar,baz", ",:", "foo\\:bar\\,baz"); +} + +static void test_shell_maybe_quote_one(const char *s, + EscapeStyle style, + const char *expected) { + _cleanup_free_ char *ret = NULL; + + assert_se(ret = shell_maybe_quote(s, style)); + log_debug("[%s] → [%s] (%s)", s, ret, expected); + assert_se(streq(ret, expected)); +} + +static void test_shell_maybe_quote(void) { + + test_shell_maybe_quote_one("", ESCAPE_BACKSLASH, ""); + test_shell_maybe_quote_one("", ESCAPE_POSIX, ""); + test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH, "\"\\\\\""); + test_shell_maybe_quote_one("\\", ESCAPE_POSIX, "$'\\\\'"); + test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH, "\"\\\"\""); + test_shell_maybe_quote_one("\"", ESCAPE_POSIX, "$'\"'"); + test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH, "foobar"); + test_shell_maybe_quote_one("foobar", ESCAPE_POSIX, "foobar"); + test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH, "\"foo bar\""); + test_shell_maybe_quote_one("foo bar", ESCAPE_POSIX, "$'foo bar'"); + test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH, "\"foo\tbar\""); + test_shell_maybe_quote_one("foo\tbar", ESCAPE_POSIX, "$'foo\\tbar'"); + test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH, "\"foo\nbar\""); + test_shell_maybe_quote_one("foo\nbar", ESCAPE_POSIX, "$'foo\\nbar'"); + test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH, "\"foo \\\"bar\\\" waldo\""); + test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_POSIX, "$'foo \"bar\" waldo'"); + test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH, "\"foo\\$bar\""); + test_shell_maybe_quote_one("foo$bar", ESCAPE_POSIX, "$'foo$bar'"); + + /* Note that current users disallow control characters, so this "test" + * is here merely to establish current behaviour. If control characters + * were allowed, they should be quoted, i.e. \001 should become \\001. */ + test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH, "\"a\nb\001\""); + test_shell_maybe_quote_one("a\nb\001", ESCAPE_POSIX, "$'a\\nb\001'"); + + test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH, "\"foo!bar\""); + test_shell_maybe_quote_one("foo!bar", ESCAPE_POSIX, "$'foo!bar'"); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_cescape(); + test_xescape(); + test_xescape_full(false); + test_xescape_full(true); + test_cunescape(); + test_shell_escape(); + test_shell_maybe_quote(); + + return 0; +} diff --git a/src/test/test-exec-util.c b/src/test/test-exec-util.c new file mode 100644 index 00000000..3168411d --- /dev/null +++ b/src/test/test-exec-util.c @@ -0,0 +1,461 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "copy.h" +#include "def.h" +#include "env-util.h" +#include "exec-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "log.h" +#include "macro.h" +#include "path-util.h" +#include "rm-rf.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" + +static int here = 0, here2 = 0, here3 = 0; +void *ignore_stdout_args[] = {&here, &here2, &here3}; + +/* noop handlers, just check that arguments are passed correctly */ +static int ignore_stdout_func(int fd, void *arg) { + assert(fd >= 0); + assert(arg == &here); + safe_close(fd); + + return 0; +} +static int ignore_stdout_func2(int fd, void *arg) { + assert(fd >= 0); + assert(arg == &here2); + safe_close(fd); + + return 0; +} +static int ignore_stdout_func3(int fd, void *arg) { + assert(fd >= 0); + assert(arg == &here3); + safe_close(fd); + + return 0; +} + +static const gather_stdout_callback_t ignore_stdout[] = { + ignore_stdout_func, + ignore_stdout_func2, + ignore_stdout_func3, +}; + +static void test_execute_directory(bool gather_stdout) { + char template_lo[] = "/tmp/test-exec-util.lo.XXXXXXX"; + char template_hi[] = "/tmp/test-exec-util.hi.XXXXXXX"; + const char * dirs[] = {template_hi, template_lo, NULL}; + const char *name, *name2, *name3, + *overridden, *override, + *masked, *mask, + *masked2, *mask2, /* the mask is non-executable */ + *masked2e, *mask2e; /* the mask is executable */ + + log_info("/* %s (%s) */", __func__, gather_stdout ? "gathering stdout" : "asynchronous"); + + assert_se(mkdtemp(template_lo)); + assert_se(mkdtemp(template_hi)); + + name = strjoina(template_lo, "/script"); + name2 = strjoina(template_hi, "/script2"); + name3 = strjoina(template_lo, "/useless"); + overridden = strjoina(template_lo, "/overridden"); + override = strjoina(template_hi, "/overridden"); + masked = strjoina(template_lo, "/masked"); + mask = strjoina(template_hi, "/masked"); + masked2 = strjoina(template_lo, "/masked2"); + mask2 = strjoina(template_hi, "/masked2"); + masked2e = strjoina(template_lo, "/masked2e"); + mask2e = strjoina(template_hi, "/masked2e"); + + assert_se(write_string_file(name, + "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(name2, + "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/it_works2", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(overridden, + "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(override, + "#!/bin/sh\necho 'Executing '$0", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(masked, + "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(masked2, + "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(masked2e, + "#!/bin/sh\necho 'Executing '$0\ntouch $(dirname $0)/failed", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(symlink("/dev/null", mask) == 0); + assert_se(touch(mask2) == 0); + assert_se(touch(mask2e) == 0); + assert_se(touch(name3) >= 0); + + assert_se(chmod(name, 0755) == 0); + assert_se(chmod(name2, 0755) == 0); + assert_se(chmod(overridden, 0755) == 0); + assert_se(chmod(override, 0755) == 0); + assert_se(chmod(masked, 0755) == 0); + assert_se(chmod(masked2, 0755) == 0); + assert_se(chmod(masked2e, 0755) == 0); + assert_se(chmod(mask2e, 0755) == 0); + + if (gather_stdout) + execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + else + execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + + assert_se(chdir(template_lo) == 0); + assert_se(access("it_works", F_OK) >= 0); + assert_se(access("failed", F_OK) < 0); + + assert_se(chdir(template_hi) == 0); + assert_se(access("it_works2", F_OK) >= 0); + assert_se(access("failed", F_OK) < 0); + + (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL); +} + +static void test_execution_order(void) { + char template_lo[] = "/tmp/test-exec-util-lo.XXXXXXX"; + char template_hi[] = "/tmp/test-exec-util-hi.XXXXXXX"; + const char *dirs[] = {template_hi, template_lo, NULL}; + const char *name, *name2, *name3, *overridden, *override, *masked, *mask; + const char *output, *t; + _cleanup_free_ char *contents = NULL; + + assert_se(mkdtemp(template_lo)); + assert_se(mkdtemp(template_hi)); + + output = strjoina(template_hi, "/output"); + + log_info("/* %s >>%s */", __func__, output); + + /* write files in "random" order */ + name2 = strjoina(template_lo, "/90-bar"); + name = strjoina(template_hi, "/80-foo"); + name3 = strjoina(template_lo, "/last"); + overridden = strjoina(template_lo, "/30-override"); + override = strjoina(template_hi, "/30-override"); + masked = strjoina(template_lo, "/10-masked"); + mask = strjoina(template_hi, "/10-masked"); + + t = strjoina("#!/bin/sh\necho $(basename $0) >>", output); + assert_se(write_string_file(name, t, WRITE_STRING_FILE_CREATE) == 0); + + t = strjoina("#!/bin/sh\necho $(basename $0) >>", output); + assert_se(write_string_file(name2, t, WRITE_STRING_FILE_CREATE) == 0); + + t = strjoina("#!/bin/sh\necho $(basename $0) >>", output); + assert_se(write_string_file(name3, t, WRITE_STRING_FILE_CREATE) == 0); + + t = strjoina("#!/bin/sh\necho OVERRIDDEN >>", output); + assert_se(write_string_file(overridden, t, WRITE_STRING_FILE_CREATE) == 0); + + t = strjoina("#!/bin/sh\necho $(basename $0) >>", output); + assert_se(write_string_file(override, t, WRITE_STRING_FILE_CREATE) == 0); + + t = strjoina("#!/bin/sh\necho MASKED >>", output); + assert_se(write_string_file(masked, t, WRITE_STRING_FILE_CREATE) == 0); + + assert_se(symlink("/dev/null", mask) == 0); + + assert_se(chmod(name, 0755) == 0); + assert_se(chmod(name2, 0755) == 0); + assert_se(chmod(name3, 0755) == 0); + assert_se(chmod(overridden, 0755) == 0); + assert_se(chmod(override, 0755) == 0); + assert_se(chmod(masked, 0755) == 0); + + execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + + assert_se(read_full_file(output, &contents, NULL) >= 0); + assert_se(streq(contents, "30-override\n80-foo\n90-bar\nlast\n")); + + (void) rm_rf(template_lo, REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf(template_hi, REMOVE_ROOT|REMOVE_PHYSICAL); +} + +static int gather_stdout_one(int fd, void *arg) { + char ***s = arg, *t; + char buf[128] = {}; + + assert_se(s); + assert_se(read(fd, buf, sizeof buf) >= 0); + safe_close(fd); + + assert_se(t = strndup(buf, sizeof buf)); + assert_se(strv_push(s, t) >= 0); + + return 0; +} +static int gather_stdout_two(int fd, void *arg) { + char ***s = arg, **t; + + STRV_FOREACH(t, *s) + assert_se(write(fd, *t, strlen(*t)) == (ssize_t) strlen(*t)); + safe_close(fd); + + return 0; +} +static int gather_stdout_three(int fd, void *arg) { + char **s = arg; + char buf[128] = {}; + + assert_se(read(fd, buf, sizeof buf - 1) > 0); + safe_close(fd); + assert_se(*s = strndup(buf, sizeof buf)); + + return 0; +} + +const gather_stdout_callback_t gather_stdout[] = { + gather_stdout_one, + gather_stdout_two, + gather_stdout_three, +}; + +static void test_stdout_gathering(void) { + char template[] = "/tmp/test-exec-util.XXXXXXX"; + const char *dirs[] = {template, NULL}; + const char *name, *name2, *name3; + int r; + + char **tmp = NULL; /* this is only used in the forked process, no cleanup here */ + _cleanup_free_ char *output = NULL; + + void* args[] = {&tmp, &tmp, &output}; + + assert_se(mkdtemp(template)); + + log_info("/* %s */", __func__); + + /* write files */ + name = strjoina(template, "/10-foo"); + name2 = strjoina(template, "/20-bar"); + name3 = strjoina(template, "/30-last"); + + assert_se(write_string_file(name, + "#!/bin/sh\necho a\necho b\necho c\n", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(name2, + "#!/bin/sh\necho d\n", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(name3, + "#!/bin/sh\nsleep 1", + WRITE_STRING_FILE_CREATE) == 0); + + assert_se(chmod(name, 0755) == 0); + assert_se(chmod(name2, 0755) == 0); + assert_se(chmod(name3, 0755) == 0); + + r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + assert_se(r >= 0); + + log_info("got: %s", output); + + assert_se(streq(output, "a\nb\nc\nd\n")); +} + +static void test_environment_gathering(void) { + char template[] = "/tmp/test-exec-util.XXXXXXX", **p; + const char *dirs[] = {template, NULL}; + const char *name, *name2, *name3, *old; + int r; + + char **tmp = NULL; /* this is only used in the forked process, no cleanup here */ + _cleanup_strv_free_ char **env = NULL; + + void* const args[] = { &tmp, &tmp, &env }; + + assert_se(mkdtemp(template)); + + log_info("/* %s */", __func__); + + /* write files */ + name = strjoina(template, "/10-foo"); + name2 = strjoina(template, "/20-bar"); + name3 = strjoina(template, "/30-last"); + + assert_se(write_string_file(name, + "#!/bin/sh\n" + "echo A=23\n", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(name2, + "#!/bin/sh\n" + "echo A=22:$A\n\n\n", /* substitution from previous generator */ + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(name3, + "#!/bin/sh\n" + "echo A=$A:24\n" + "echo B=12\n" + "echo C=000\n" + "echo C=001\n" /* variable overwriting */ + /* various invalid entries */ + "echo unset A\n" + "echo unset A=\n" + "echo unset A=B\n" + "echo unset \n" + "echo A B=C\n" + "echo A\n" + /* test variable assignment without newline */ + "echo PATH=$PATH:/no/such/file", /* no newline */ + WRITE_STRING_FILE_CREATE) == 0); + + assert_se(chmod(name, 0755) == 0); + assert_se(chmod(name2, 0755) == 0); + assert_se(chmod(name3, 0755) == 0); + + /* When booting in containers or without initramfs there might not be + * any PATH in the environment and if there is no PATH /bin/sh built-in + * PATH may leak and override systemd's DEFAULT_PATH which is not + * good. Force our own PATH in environment, to prevent expansion of sh + * built-in $PATH */ + old = getenv("PATH"); + r = setenv("PATH", "no-sh-built-in-path", 1); + assert_se(r >= 0); + + r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + assert_se(r >= 0); + + STRV_FOREACH(p, env) + log_info("got env: \"%s\"", *p); + + assert_se(streq(strv_env_get(env, "A"), "22:23:24")); + assert_se(streq(strv_env_get(env, "B"), "12")); + assert_se(streq(strv_env_get(env, "C"), "001")); + assert_se(streq(strv_env_get(env, "PATH"), "no-sh-built-in-path:/no/such/file")); + + /* now retest with "default" path passed in, as created by + * manager_default_environment */ + env = strv_free(env); + env = strv_new("PATH=" DEFAULT_PATH); + assert_se(env); + + r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, env, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS); + assert_se(r >= 0); + + STRV_FOREACH(p, env) + log_info("got env: \"%s\"", *p); + + assert_se(streq(strv_env_get(env, "A"), "22:23:24")); + assert_se(streq(strv_env_get(env, "B"), "12")); + assert_se(streq(strv_env_get(env, "C"), "001")); + assert_se(streq(strv_env_get(env, "PATH"), DEFAULT_PATH ":/no/such/file")); + + /* reset environ PATH */ + if (old) + (void) setenv("PATH", old, 1); + else + (void) unsetenv("PATH"); +} + +static void test_error_catching(void) { + char template[] = "/tmp/test-exec-util.XXXXXXX"; + const char *dirs[] = {template, NULL}; + const char *name, *name2, *name3; + int r; + + assert_se(mkdtemp(template)); + + log_info("/* %s */", __func__); + + /* write files */ + name = strjoina(template, "/10-foo"); + name2 = strjoina(template, "/20-bar"); + name3 = strjoina(template, "/30-last"); + + assert_se(write_string_file(name, + "#!/bin/sh\necho a\necho b\necho c\n", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(name2, + "#!/bin/sh\nexit 42\n", + WRITE_STRING_FILE_CREATE) == 0); + assert_se(write_string_file(name3, + "#!/bin/sh\nexit 12", + WRITE_STRING_FILE_CREATE) == 0); + + assert_se(chmod(name, 0755) == 0); + assert_se(chmod(name2, 0755) == 0); + assert_se(chmod(name3, 0755) == 0); + + r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL, NULL, EXEC_DIR_NONE); + + /* we should exit with the error code of the first script that failed */ + assert_se(r == 42); +} + +static void test_exec_command_flags_from_strv(void) { + ExecCommandFlags flags = 0; + char **valid_strv = STRV_MAKE("no-env-expand", "no-setuid", "ignore-failure"); + char **invalid_strv = STRV_MAKE("no-env-expand", "no-setuid", "nonexistent-option", "ignore-failure"); + int r; + + r = exec_command_flags_from_strv(valid_strv, &flags); + + assert_se(r == 0); + assert_se(FLAGS_SET(flags, EXEC_COMMAND_NO_ENV_EXPAND)); + assert_se(FLAGS_SET(flags, EXEC_COMMAND_NO_SETUID)); + assert_se(FLAGS_SET(flags, EXEC_COMMAND_IGNORE_FAILURE)); + assert_se(!FLAGS_SET(flags, EXEC_COMMAND_AMBIENT_MAGIC)); + assert_se(!FLAGS_SET(flags, EXEC_COMMAND_FULLY_PRIVILEGED)); + + r = exec_command_flags_from_strv(invalid_strv, &flags); + + assert_se(r == -EINVAL); +} + +static void test_exec_command_flags_to_strv(void) { + _cleanup_strv_free_ char **opts = NULL, **empty_opts = NULL, **invalid_opts = NULL; + ExecCommandFlags flags = 0; + int r; + + flags |= (EXEC_COMMAND_AMBIENT_MAGIC|EXEC_COMMAND_NO_ENV_EXPAND|EXEC_COMMAND_IGNORE_FAILURE); + + r = exec_command_flags_to_strv(flags, &opts); + + assert_se(r == 0); + assert_se(strv_equal(opts, STRV_MAKE("ignore-failure", "ambient", "no-env-expand"))); + + r = exec_command_flags_to_strv(0, &empty_opts); + + assert_se(r == 0); + assert_se(strv_equal(empty_opts, STRV_MAKE_EMPTY)); + + flags = _EXEC_COMMAND_FLAGS_INVALID; + + r = exec_command_flags_to_strv(flags, &invalid_opts); + + assert_se(r == -EINVAL); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_execute_directory(true); + test_execute_directory(false); + test_execution_order(); + test_stdout_gathering(); + test_environment_gathering(); + test_error_catching(); + test_exec_command_flags_from_strv(); + test_exec_command_flags_to_strv(); + + return 0; +} diff --git a/src/test/test-execute.c b/src/test/test-execute.c new file mode 100644 index 00000000..3b4bbeed --- /dev/null +++ b/src/test/test-execute.c @@ -0,0 +1,926 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "capability-util.h" +#include "cpu-set-util.h" +#include "errno-list.h" +#include "fileio.h" +#include "fs-util.h" +#include "macro.h" +#include "manager.h" +#include "missing_prctl.h" +#include "mkdir.h" +#include "path-util.h" +#include "rm-rf.h" +#if HAVE_SECCOMP +#include "seccomp-util.h" +#endif +#include "service.h" +#include "stat-util.h" +#include "tests.h" +#include "unit.h" +#include "user-util.h" +#include "util.h" +#include "virt.h" + +static bool can_unshare; + +typedef void (*test_function_t)(Manager *m); + +static int cld_dumped_to_killed(int code) { + /* Depending on the system, seccomp version, … some signals might result in dumping, others in plain + * killing. Let's ignore the difference here, and map both cases to CLD_KILLED */ + return code == CLD_DUMPED ? CLD_KILLED : code; +} + +_unused_ static bool is_run_on_travis_ci(void) { + /* https://docs.travis-ci.com/user/environment-variables#default-environment-variables */ + return streq_ptr(getenv("TRAVIS"), "true"); +} + +static void wait_for_service_finish(Manager *m, Unit *unit) { + Service *service = NULL; + usec_t ts; + usec_t timeout = 2 * USEC_PER_MINUTE; + + assert_se(m); + assert_se(unit); + + service = SERVICE(unit); + printf("%s\n", unit->id); + exec_context_dump(&service->exec_context, stdout, "\t"); + ts = now(CLOCK_MONOTONIC); + while (!IN_SET(service->state, SERVICE_DEAD, SERVICE_FAILED)) { + int r; + usec_t n; + + r = sd_event_run(m->event, 100 * USEC_PER_MSEC); + assert_se(r >= 0); + + n = now(CLOCK_MONOTONIC); + if (ts + timeout < n) { + log_error("Test timeout when testing %s", unit->id); + r = unit_kill(unit, KILL_ALL, SIGKILL, NULL); + if (r < 0) + log_error_errno(r, "Failed to kill %s: %m", unit->id); + exit(EXIT_FAILURE); + } + } +} + +static void check_main_result(const char *func, Manager *m, Unit *unit, int status_expected, int code_expected) { + Service *service = NULL; + + assert_se(m); + assert_se(unit); + + wait_for_service_finish(m, unit); + + service = SERVICE(unit); + exec_status_dump(&service->main_exec_status, stdout, "\t"); + + if (cld_dumped_to_killed(service->main_exec_status.code) != cld_dumped_to_killed(code_expected)) { + log_error("%s: %s: exit code %d, expected %d", + func, unit->id, + service->main_exec_status.code, code_expected); + abort(); + } + + if (service->main_exec_status.status != status_expected) { + log_error("%s: %s: exit status %d, expected %d", + func, unit->id, + service->main_exec_status.status, status_expected); + abort(); + } +} + +static void check_service_result(const char *func, Manager *m, Unit *unit, ServiceResult result_expected) { + Service *service = NULL; + + assert_se(m); + assert_se(unit); + + wait_for_service_finish(m, unit); + + service = SERVICE(unit); + + if (service->result != result_expected) { + log_error("%s: %s: service end result %s, expected %s", + func, unit->id, + service_result_to_string(service->result), + service_result_to_string(result_expected)); + abort(); + } +} + +static bool check_nobody_user_and_group(void) { + static int cache = -1; + struct passwd *p; + struct group *g; + + if (cache >= 0) + return !!cache; + + if (!synthesize_nobody()) + goto invalid; + + p = getpwnam(NOBODY_USER_NAME); + if (!p || + !streq(p->pw_name, NOBODY_USER_NAME) || + p->pw_uid != UID_NOBODY || + p->pw_gid != GID_NOBODY) + goto invalid; + + p = getpwuid(UID_NOBODY); + if (!p || + !streq(p->pw_name, NOBODY_USER_NAME) || + p->pw_uid != UID_NOBODY || + p->pw_gid != GID_NOBODY) + goto invalid; + + g = getgrnam(NOBODY_GROUP_NAME); + if (!g || + !streq(g->gr_name, NOBODY_GROUP_NAME) || + g->gr_gid != GID_NOBODY) + goto invalid; + + g = getgrgid(GID_NOBODY); + if (!g || + !streq(g->gr_name, NOBODY_GROUP_NAME) || + g->gr_gid != GID_NOBODY) + goto invalid; + + cache = 1; + return true; + +invalid: + cache = 0; + return false; +} + +static bool check_user_has_group_with_same_name(const char *name) { + struct passwd *p; + struct group *g; + + assert(name); + + p = getpwnam(name); + if (!p || + !streq(p->pw_name, name)) + return false; + + g = getgrgid(p->pw_gid); + if (!g || + !streq(g->gr_name, name)) + return false; + + return true; +} + +static bool is_inaccessible_available(void) { + const char *p; + + FOREACH_STRING(p, + "/run/systemd/inaccessible/reg", + "/run/systemd/inaccessible/dir", + "/run/systemd/inaccessible/chr", + "/run/systemd/inaccessible/blk", + "/run/systemd/inaccessible/fifo", + "/run/systemd/inaccessible/sock" + ) { + if (access(p, F_OK) < 0) + return false; + } + + return true; +} + +static void test(const char *func, Manager *m, const char *unit_name, int status_expected, int code_expected) { + Unit *unit; + + assert_se(unit_name); + + assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0); + assert_se(unit_start(unit) >= 0); + check_main_result(func, m, unit, status_expected, code_expected); +} + +static void test_service(const char *func, Manager *m, const char *unit_name, ServiceResult result_expected) { + Unit *unit; + + assert_se(unit_name); + + assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0); + assert_se(unit_start(unit) >= 0); + check_service_result(func, m, unit, result_expected); +} + +static void test_exec_bindpaths(Manager *m) { + assert_se(mkdir_p("/tmp/test-exec-bindpaths", 0755) >= 0); + assert_se(mkdir_p("/tmp/test-exec-bindreadonlypaths", 0755) >= 0); + + test(__func__, m, "exec-bindpaths.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + + (void) rm_rf("/tmp/test-exec-bindpaths", REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf("/tmp/test-exec-bindreadonlypaths", REMOVE_ROOT|REMOVE_PHYSICAL); +} + +static void test_exec_cpuaffinity(Manager *m) { + _cleanup_(cpu_set_reset) CPUSet c = {}; + + assert_se(cpu_set_realloc(&c, 8192) >= 0); /* just allocate the maximum possible size */ + assert_se(sched_getaffinity(0, c.allocated, c.set) >= 0); + + if (!CPU_ISSET_S(0, c.allocated, c.set)) { + log_notice("Cannot use CPU 0, skipping %s", __func__); + return; + } + + test(__func__, m, "exec-cpuaffinity1.service", 0, CLD_EXITED); + test(__func__, m, "exec-cpuaffinity2.service", 0, CLD_EXITED); + + if (!CPU_ISSET_S(1, c.allocated, c.set) || + !CPU_ISSET_S(2, c.allocated, c.set)) { + log_notice("Cannot use CPU 1 or 2, skipping remaining tests in %s", __func__); + return; + } + + test(__func__, m, "exec-cpuaffinity3.service", 0, CLD_EXITED); +} + +static void test_exec_workingdirectory(Manager *m) { + assert_se(mkdir_p("/tmp/test-exec_workingdirectory", 0755) >= 0); + + test(__func__, m, "exec-workingdirectory.service", 0, CLD_EXITED); + test(__func__, m, "exec-workingdirectory-trailing-dot.service", 0, CLD_EXITED); + + (void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL); +} + +static void test_exec_personality(Manager *m) { +#if defined(__x86_64__) + test(__func__, m, "exec-personality-x86-64.service", 0, CLD_EXITED); + +#elif defined(__s390__) + test(__func__, m, "exec-personality-s390.service", 0, CLD_EXITED); + +#elif defined(__powerpc64__) +# if __BYTE_ORDER == __BIG_ENDIAN + test(__func__, m, "exec-personality-ppc64.service", 0, CLD_EXITED); +# else + test(__func__, m, "exec-personality-ppc64le.service", 0, CLD_EXITED); +# endif + +#elif defined(__aarch64__) + test(__func__, m, "exec-personality-aarch64.service", 0, CLD_EXITED); + +#elif defined(__i386__) + test(__func__, m, "exec-personality-x86.service", 0, CLD_EXITED); +#else + log_notice("Unknown personality, skipping %s", __func__); +#endif +} + +static void test_exec_ignoresigpipe(Manager *m) { + test(__func__, m, "exec-ignoresigpipe-yes.service", 0, CLD_EXITED); + test(__func__, m, "exec-ignoresigpipe-no.service", SIGPIPE, CLD_KILLED); +} + +static void test_exec_privatetmp(Manager *m) { + assert_se(touch("/tmp/test-exec_privatetmp") >= 0); + + test(__func__, m, "exec-privatetmp-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + test(__func__, m, "exec-privatetmp-no.service", 0, CLD_EXITED); + + unlink("/tmp/test-exec_privatetmp"); +} + +static void test_exec_privatedevices(Manager *m) { + int r; + + if (detect_container() > 0) { + log_notice("Testing in container, skipping %s", __func__); + return; + } + if (!is_inaccessible_available()) { + log_notice("Testing without inaccessible, skipping %s", __func__); + return; + } + + test(__func__, m, "exec-privatedevices-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + test(__func__, m, "exec-privatedevices-no.service", 0, CLD_EXITED); + test(__func__, m, "exec-privatedevices-disabled-by-prefix.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + + /* We use capsh to test if the capabilities are + * properly set, so be sure that it exists */ + r = find_binary("capsh", NULL); + if (r < 0) { + log_notice_errno(r, "Could not find capsh binary, skipping remaining tests in %s: %m", __func__); + return; + } + + test(__func__, m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED); + test(__func__, m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED); + test(__func__, m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED); + test(__func__, m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED); +} + +static void test_exec_protecthome(Manager *m) { + if (!can_unshare) { + log_notice("Cannot reliably unshare, skipping %s", __func__); + return; + } + + test(__func__, m, "exec-protecthome-tmpfs-vs-protectsystem-strict.service", 0, CLD_EXITED); +} + +static void test_exec_protectkernelmodules(Manager *m) { + int r; + + if (detect_container() > 0) { + log_notice("Testing in container, skipping %s", __func__); + return; + } + if (!is_inaccessible_available()) { + log_notice("Testing without inaccessible, skipping %s", __func__); + return; + } + + r = find_binary("capsh", NULL); + if (r < 0) { + log_notice_errno(r, "Skipping %s, could not find capsh binary: %m", __func__); + return; + } + + test(__func__, m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED); + test(__func__, m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED); + test(__func__, m, "exec-protectkernelmodules-yes-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); +} + +static void test_exec_readonlypaths(Manager *m) { + + test(__func__, m, "exec-readonlypaths-simple.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + + if (path_is_read_only_fs("/var") > 0) { + log_notice("Directory /var is readonly, skipping remaining tests in %s", __func__); + return; + } + + test(__func__, m, "exec-readonlypaths.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + test(__func__, m, "exec-readonlypaths-with-bindpaths.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + test(__func__, m, "exec-readonlypaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); +} + +static void test_exec_readwritepaths(Manager *m) { + + if (path_is_read_only_fs("/") > 0) { + log_notice("Root directory is readonly, skipping %s", __func__); + return; + } + + test(__func__, m, "exec-readwritepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); +} + +static void test_exec_inaccessiblepaths(Manager *m) { + + if (!is_inaccessible_available()) { + log_notice("Testing without inaccessible, skipping %s", __func__); + return; + } + + test(__func__, m, "exec-inaccessiblepaths-sys.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + + if (path_is_read_only_fs("/") > 0) { + log_notice("Root directory is readonly, skipping remaining tests in %s", __func__); + return; + } + + test(__func__, m, "exec-inaccessiblepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); +} + +static void test_exec_temporaryfilesystem(Manager *m) { + + test(__func__, m, "exec-temporaryfilesystem-options.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + test(__func__, m, "exec-temporaryfilesystem-ro.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + test(__func__, m, "exec-temporaryfilesystem-rw.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + test(__func__, m, "exec-temporaryfilesystem-usr.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); +} + +static void test_exec_systemcallfilter(Manager *m) { +#if HAVE_SECCOMP + int r; + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + + test(__func__, m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED); + test(__func__, m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED); + test(__func__, m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED); + test(__func__, m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED); + + r = find_binary("python3", NULL); + if (r < 0) { + log_notice_errno(r, "Skipping remaining tests in %s, could not find python3 binary: %m", __func__); + return; + } + + test(__func__, m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED); + test(__func__, m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED); + test(__func__, m, "exec-systemcallfilter-with-errno-multi.service", errno_from_name("EILSEQ"), CLD_EXITED); +#endif +} + +static void test_exec_systemcallerrornumber(Manager *m) { +#if HAVE_SECCOMP + int r; + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + + r = find_binary("python3", NULL); + if (r < 0) { + log_notice_errno(r, "Skipping %s, could not find python3 binary: %m", __func__); + return; + } + + test(__func__, m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED); + test(__func__, m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED); +#endif +} + +static void test_exec_restrictnamespaces(Manager *m) { +#if HAVE_SECCOMP + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + + test(__func__, m, "exec-restrictnamespaces-no.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + test(__func__, m, "exec-restrictnamespaces-yes.service", 1, CLD_EXITED); + test(__func__, m, "exec-restrictnamespaces-mnt.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + test(__func__, m, "exec-restrictnamespaces-mnt-blacklist.service", 1, CLD_EXITED); + test(__func__, m, "exec-restrictnamespaces-merge-and.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + test(__func__, m, "exec-restrictnamespaces-merge-or.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + test(__func__, m, "exec-restrictnamespaces-merge-all.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); +#endif +} + +static void test_exec_systemcallfilter_system(Manager *m) { +/* Skip this particular test case when running under ASan, as + * LSan intermittently segfaults when accessing memory right + * after the test finishes. Generally, ASan & LSan don't like + * the seccomp stuff. + */ +#if HAVE_SECCOMP && !HAS_FEATURE_ADDRESS_SANITIZER + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + + test(__func__, m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED); + + if (!check_nobody_user_and_group()) { + log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__); + return; + } + + if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) { + log_notice("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__); + return; + } + + test(__func__, m, "exec-systemcallfilter-system-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED); +#endif +} + +static void test_exec_user(Manager *m) { + test(__func__, m, "exec-user.service", 0, CLD_EXITED); + + if (!check_nobody_user_and_group()) { + log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__); + return; + } + + if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) { + log_notice("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__); + return; + } + + test(__func__, m, "exec-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED); +} + +static void test_exec_group(Manager *m) { + test(__func__, m, "exec-group.service", 0, CLD_EXITED); + + if (!check_nobody_user_and_group()) { + log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__); + return; + } + + if (!STR_IN_SET(NOBODY_GROUP_NAME, "nobody", "nfsnobody", "nogroup")) { + log_notice("Unsupported nobody group name '%s', skipping remaining tests in %s", NOBODY_GROUP_NAME, __func__); + return; + } + + test(__func__, m, "exec-group-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED); +} + +static void test_exec_supplementarygroups(Manager *m) { + test(__func__, m, "exec-supplementarygroups.service", 0, CLD_EXITED); + test(__func__, m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED); + test(__func__, m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED); + test(__func__, m, "exec-supplementarygroups-multiple-groups-default-group-user.service", 0, CLD_EXITED); + test(__func__, m, "exec-supplementarygroups-multiple-groups-withgid.service", 0, CLD_EXITED); + test(__func__, m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED); +} + +static void test_exec_dynamicuser(Manager *m) { + + test(__func__, m, "exec-dynamicuser-fixeduser.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + if (check_user_has_group_with_same_name("adm")) + test(__func__, m, "exec-dynamicuser-fixeduser-adm.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + if (check_user_has_group_with_same_name("games")) + test(__func__, m, "exec-dynamicuser-fixeduser-games.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + test(__func__, m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + test(__func__, m, "exec-dynamicuser-supplementarygroups.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + test(__func__, m, "exec-dynamicuser-statedir.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + + (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL); + + test(__func__, m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED); + test(__func__, m, "exec-dynamicuser-statedir-migrate-step2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); + + (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL); +} + +static void test_exec_environment(Manager *m) { + test(__func__, m, "exec-environment-no-substitute.service", 0, CLD_EXITED); + test(__func__, m, "exec-environment.service", 0, CLD_EXITED); + test(__func__, m, "exec-environment-multiple.service", 0, CLD_EXITED); + test(__func__, m, "exec-environment-empty.service", 0, CLD_EXITED); +} + +static void test_exec_environmentfile(Manager *m) { + static const char e[] = + "VAR1='word1 word2'\n" + "VAR2=word3 \n" + "# comment1\n" + "\n" + "; comment2\n" + " ; # comment3\n" + "line without an equal\n" + "VAR3='$word 5 6'\n" + "VAR4='new\nline'\n" + "VAR5=password\\with\\backslashes"; + int r; + + r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE); + assert_se(r == 0); + + test(__func__, m, "exec-environmentfile.service", 0, CLD_EXITED); + + (void) unlink("/tmp/test-exec_environmentfile.conf"); +} + +static void test_exec_passenvironment(Manager *m) { + /* test-execute runs under MANAGER_USER which, by default, forwards all + * variables present in the environment, but only those that are + * present _at the time it is created_! + * + * So these PassEnvironment checks are still expected to work, since we + * are ensuring the variables are not present at manager creation (they + * are unset explicitly in main) and are only set here. + * + * This is still a good approximation of how a test for MANAGER_SYSTEM + * would work. + */ + assert_se(setenv("VAR1", "word1 word2", 1) == 0); + assert_se(setenv("VAR2", "word3", 1) == 0); + assert_se(setenv("VAR3", "$word 5 6", 1) == 0); + assert_se(setenv("VAR4", "new\nline", 1) == 0); + assert_se(setenv("VAR5", "passwordwithbackslashes", 1) == 0); + test(__func__, m, "exec-passenvironment.service", 0, CLD_EXITED); + test(__func__, m, "exec-passenvironment-repeated.service", 0, CLD_EXITED); + test(__func__, m, "exec-passenvironment-empty.service", 0, CLD_EXITED); + assert_se(unsetenv("VAR1") == 0); + assert_se(unsetenv("VAR2") == 0); + assert_se(unsetenv("VAR3") == 0); + assert_se(unsetenv("VAR4") == 0); + assert_se(unsetenv("VAR5") == 0); + test(__func__, m, "exec-passenvironment-absent.service", 0, CLD_EXITED); +} + +static void test_exec_umask(Manager *m) { + test(__func__, m, "exec-umask-default.service", 0, CLD_EXITED); + test(__func__, m, "exec-umask-0177.service", 0, CLD_EXITED); +} + +static void test_exec_runtimedirectory(Manager *m) { + test(__func__, m, "exec-runtimedirectory.service", 0, CLD_EXITED); + test(__func__, m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED); + test(__func__, m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED); + + if (!check_nobody_user_and_group()) { + log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__); + return; + } + + if (!STR_IN_SET(NOBODY_GROUP_NAME, "nobody", "nfsnobody", "nogroup")) { + log_notice("Unsupported nobody group name '%s', skipping remaining tests in %s", NOBODY_GROUP_NAME, __func__); + return; + } + + test(__func__, m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED); +} + +static void test_exec_capabilityboundingset(Manager *m) { + int r; + + r = find_binary("capsh", NULL); + if (r < 0) { + log_notice_errno(r, "Skipping %s, could not find capsh binary: %m", __func__); + return; + } + + if (have_effective_cap(CAP_CHOWN) <= 0 || + have_effective_cap(CAP_FOWNER) <= 0 || + have_effective_cap(CAP_KILL) <= 0) { + log_notice("Skipping %s, this process does not have enough capabilities", __func__); + return; + } + + test(__func__, m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED); + test(__func__, m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED); + test(__func__, m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED); + test(__func__, m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED); +} + +static void test_exec_basic(Manager *m) { + test(__func__, m, "exec-basic.service", 0, CLD_EXITED); +} + +static void test_exec_ambientcapabilities(Manager *m) { + int r; + + /* Check if the kernel has support for ambient capabilities. Run + * the tests only if that's the case. Clearing all ambient + * capabilities is fine, since we are expecting them to be unset + * in the first place for the tests. */ + r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); + if (r < 0 && IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS)) { + log_notice("Skipping %s, the kernel does not support ambient capabilities", __func__); + return; + } + + if (have_effective_cap(CAP_CHOWN) <= 0 || + have_effective_cap(CAP_NET_RAW) <= 0) { + log_notice("Skipping %s, this process does not have enough capabilities", __func__); + return; + } + + test(__func__, m, "exec-ambientcapabilities.service", 0, CLD_EXITED); + test(__func__, m, "exec-ambientcapabilities-merge.service", 0, CLD_EXITED); + + if (!check_nobody_user_and_group()) { + log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__); + return; + } + + if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) { + log_notice("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__); + return; + } + + test(__func__, m, "exec-ambientcapabilities-" NOBODY_USER_NAME ".service", 0, CLD_EXITED); + test(__func__, m, "exec-ambientcapabilities-merge-" NOBODY_USER_NAME ".service", 0, CLD_EXITED); +} + +static void test_exec_privatenetwork(Manager *m) { + int r; + + r = find_binary("ip", NULL); + if (r < 0) { + log_notice_errno(r, "Skipping %s, could not find ip binary: %m", __func__); + return; + } + + test(__func__, m, "exec-privatenetwork-yes.service", can_unshare ? 0 : EXIT_NETWORK, CLD_EXITED); +} + +static void test_exec_oomscoreadjust(Manager *m) { + test(__func__, m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED); + + if (detect_container() > 0) { + log_notice("Testing in container, skipping remaining tests in %s", __func__); + return; + } + test(__func__, m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED); +} + +static void test_exec_ioschedulingclass(Manager *m) { + test(__func__, m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED); + test(__func__, m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED); + test(__func__, m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED); + + if (detect_container() > 0) { + log_notice("Testing in container, skipping remaining tests in %s", __func__); + return; + } + test(__func__, m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED); +} + +static void test_exec_unsetenvironment(Manager *m) { + test(__func__, m, "exec-unsetenvironment.service", 0, CLD_EXITED); +} + +static void test_exec_specifier(Manager *m) { + test(__func__, m, "exec-specifier.service", 0, CLD_EXITED); + test(__func__, m, "exec-specifier@foo-bar.service", 0, CLD_EXITED); + test(__func__, m, "exec-specifier-interpolation.service", 0, CLD_EXITED); +} + +static void test_exec_standardinput(Manager *m) { + test(__func__, m, "exec-standardinput-data.service", 0, CLD_EXITED); + test(__func__, m, "exec-standardinput-file.service", 0, CLD_EXITED); + test(__func__, m, "exec-standardinput-file-cat.service", 0, CLD_EXITED); +} + +static void test_exec_standardoutput(Manager *m) { + test(__func__, m, "exec-standardoutput-file.service", 0, CLD_EXITED); +} + +static void test_exec_standardoutput_append(Manager *m) { + test(__func__, m, "exec-standardoutput-append.service", 0, CLD_EXITED); +} + +static void test_exec_condition(Manager *m) { + test_service(__func__, m, "exec-condition-failed.service", SERVICE_FAILURE_EXIT_CODE); + test_service(__func__, m, "exec-condition-skip.service", SERVICE_SKIP_CONDITION); +} + +typedef struct test_entry { + test_function_t f; + const char *name; +} test_entry; + +#define entry(x) {x, #x} + +static int run_tests(UnitFileScope scope, const test_entry tests[], char **patterns) { + const test_entry *test = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + int r; + + assert_se(tests); + + r = manager_new(scope, MANAGER_TEST_RUN_BASIC, &m); + m->default_std_output = EXEC_OUTPUT_NULL; /* don't rely on host journald */ + if (manager_errno_skip_test(r)) + return log_tests_skipped_errno(r, "manager_new"); + assert_se(r >= 0); + assert_se(manager_startup(m, NULL, NULL) >= 0); + + for (test = tests; test && test->f; test++) + if (strv_fnmatch_or_empty(patterns, test->name, FNM_NOESCAPE)) + test->f(m); + else + log_info("Skipping %s because it does not match any pattern.", test->name); + + return 0; +} + +int main(int argc, char *argv[]) { + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + _cleanup_free_ char *test_execute_path = NULL; + + static const test_entry user_tests[] = { + entry(test_exec_basic), + entry(test_exec_ambientcapabilities), + entry(test_exec_bindpaths), + entry(test_exec_capabilityboundingset), + entry(test_exec_condition), + entry(test_exec_cpuaffinity), + entry(test_exec_environment), + entry(test_exec_environmentfile), + entry(test_exec_group), + entry(test_exec_ignoresigpipe), + entry(test_exec_inaccessiblepaths), + entry(test_exec_ioschedulingclass), + entry(test_exec_oomscoreadjust), + entry(test_exec_passenvironment), + entry(test_exec_personality), + entry(test_exec_privatedevices), + entry(test_exec_privatenetwork), + entry(test_exec_privatetmp), + entry(test_exec_protecthome), + entry(test_exec_protectkernelmodules), + entry(test_exec_readonlypaths), + entry(test_exec_readwritepaths), + entry(test_exec_restrictnamespaces), + entry(test_exec_runtimedirectory), + entry(test_exec_standardinput), + entry(test_exec_standardoutput), + entry(test_exec_standardoutput_append), + entry(test_exec_supplementarygroups), + entry(test_exec_systemcallerrornumber), + entry(test_exec_systemcallfilter), + entry(test_exec_temporaryfilesystem), + entry(test_exec_umask), + entry(test_exec_unsetenvironment), + entry(test_exec_user), + entry(test_exec_workingdirectory), + {}, + }; + static const test_entry system_tests[] = { + entry(test_exec_dynamicuser), + entry(test_exec_specifier), + entry(test_exec_systemcallfilter_system), + {}, + }; + int r; + + test_setup_logging(LOG_DEBUG); + +#if HAS_FEATURE_ADDRESS_SANITIZER + if (is_run_on_travis_ci()) { + log_notice("Running on TravisCI under ASan, skipping, see https://github.com/systemd/systemd/issues/10696"); + return EXIT_TEST_SKIP; + } +#endif + + (void) unsetenv("USER"); + (void) unsetenv("LOGNAME"); + (void) unsetenv("SHELL"); + (void) unsetenv("HOME"); + + can_unshare = have_namespaces(); + + /* It is needed otherwise cgroup creation fails */ + if (getuid() != 0) + return log_tests_skipped("not root"); + + r = enter_cgroup_subroot(NULL); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + assert_se(runtime_dir = setup_fake_runtime_dir()); + test_execute_path = path_join(get_testdata_dir(), "test-execute"); + assert_se(set_unit_path(test_execute_path) >= 0); + + /* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test + * cases, otherwise (and if they are present in the environment), + * `manager_default_environment` will copy them into the default + * environment which is passed to each created job, which will make the + * tests that expect those not to be present to fail. + */ + assert_se(unsetenv("VAR1") == 0); + assert_se(unsetenv("VAR2") == 0); + assert_se(unsetenv("VAR3") == 0); + + r = run_tests(UNIT_FILE_USER, user_tests, argv + 1); + if (r != 0) + return r; + + r = run_tests(UNIT_FILE_SYSTEM, system_tests, argv + 1); + if (r != 0) + return r; + +#if HAVE_SECCOMP + /* The following tests are for 1beab8b0d0ff2d7d1436b52d4a0c3d56dc908962. */ + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping unshare() filtered tests."); + return 0; + } + + _cleanup_hashmap_free_ Hashmap *s = NULL; + assert_se(s = hashmap_new(NULL)); + r = seccomp_syscall_resolve_name("unshare"); + assert_se(r != __NR_SCMP_ERROR); + assert_se(hashmap_put(s, UINT32_TO_PTR(r + 1), INT_TO_PTR(-1)) >= 0); + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EOPNOTSUPP), true) >= 0); + assert_se(unshare(CLONE_NEWNS) < 0); + assert_se(errno == EOPNOTSUPP); + + can_unshare = false; + + r = run_tests(UNIT_FILE_USER, user_tests, argv + 1); + if (r != 0) + return r; + + return run_tests(UNIT_FILE_SYSTEM, system_tests, argv + 1); +#else + return 0; +#endif +} diff --git a/src/test/test-exit-status.c b/src/test/test-exit-status.c new file mode 100644 index 00000000..e90375f6 --- /dev/null +++ b/src/test/test-exit-status.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "exit-status.h" +#include "string-util.h" +#include "tests.h" + +static void test_exit_status_to_string(void) { + log_info("/* %s */", __func__); + + for (int i = -1; i <= 256; i++) { + const char *s, *class; + + s = exit_status_to_string(i, EXIT_STATUS_FULL); + class = exit_status_class(i); + log_info("%d: %s%s%s%s", + i, s ?: "-", + class ? " (" : "", strempty(class), class ? ")" : ""); + + if (s) + assert_se(exit_status_from_string(s) == i); + } +} + +static void test_exit_status_from_string(void) { + log_info("/* %s */", __func__); + + assert_se(exit_status_from_string("11") == 11); + assert_se(exit_status_from_string("-1") == -ERANGE); + assert_se(exit_status_from_string("256") == -ERANGE); + assert_se(exit_status_from_string("foo") == -EINVAL); + assert_se(exit_status_from_string("SUCCESS") == 0); + assert_se(exit_status_from_string("FAILURE") == 1); +} + +static void test_exit_status_NUMA_POLICY(void) { + log_info("/* %s */", __func__); + + assert_se(streq(exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_FULL), "NUMA_POLICY")); + assert_se(streq(exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_SYSTEMD), "NUMA_POLICY")); + assert_se(!exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_BSD)); + assert_se(!exit_status_to_string(EXIT_NUMA_POLICY, EXIT_STATUS_LSB)); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_exit_status_to_string(); + test_exit_status_from_string(); + test_exit_status_NUMA_POLICY(); + + return 0; +} diff --git a/src/test/test-extract-word.c b/src/test/test-extract-word.c new file mode 100644 index 00000000..4ca57555 --- /dev/null +++ b/src/test/test-extract-word.c @@ -0,0 +1,562 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "extract-word.h" +#include "log.h" +#include "string-util.h" + +static void test_extract_first_word(void) { + const char *p, *original; + char *t; + + p = original = "foobar waldo"; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 7); + + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word(&p, &t, NULL, 0) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\"foobar\" \'waldo\'"; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "\"foobar\"")); + free(t); + assert_se(p == original + 9); + + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "\'waldo\'")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word(&p, &t, NULL, 0) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\"foobar\" \'waldo\'"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 9); + + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word(&p, &t, NULL, 0) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\""; + assert_se(extract_first_word(&p, &t, NULL, 0) == 1); + assert_se(streq(t, "\"")); + free(t); + assert_se(isempty(p)); + + p = original = "\""; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'"; + assert_se(extract_first_word(&p, &t, NULL, 0) == 1); + assert_se(streq(t, "\'")); + free(t); + assert_se(isempty(p)); + + p = original = "\'"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'fooo"; + assert_se(extract_first_word(&p, &t, NULL, 0) == 1); + assert_se(streq(t, "\'fooo")); + free(t); + assert_se(isempty(p)); + + p = original = "KEY=val \"KEY2=val with space\" \"KEY3=val with \\\"quotation\\\"\""; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == 1); + assert_se(streq(t, "KEY=val")); + free(t); + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == 1); + assert_se(streq(t, "KEY2=val with space")); + free(t); + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == 1); + assert_se(streq(t, "KEY3=val with \"quotation\"")); + free(t); + assert_se(isempty(p)); + + p = original = "KEY=val \"KEY2=val space\" \"KEY3=val with \\\"quotation\\\"\""; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) == 1); + assert_se(streq(t, "KEY=val")); + free(t); + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) == 1); + assert_se(streq(t, "\"KEY2=val")); + free(t); + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) == 1); + assert_se(streq(t, "space\"")); + free(t); + assert_se(startswith(p, "\"KEY3=")); + + p = original = "\'fooo"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\'fooo"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(isempty(p)); + + p = original = "\"fooo"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(isempty(p)); + + p = original = "yay\'foo\'bar"; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "yay\'foo\'bar")); + free(t); + assert_se(isempty(p)); + + p = original = "yay\'foo\'bar"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) > 0); + assert_se(streq(t, "yayfoobar")); + free(t); + assert_se(isempty(p)); + + p = original = " foobar "; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(isempty(p)); + + p = original = " foo\\ba\\x6ar "; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0); + assert_se(streq(t, "foo\ba\x6ar")); + free(t); + assert_se(isempty(p)); + + p = original = " foo\\ba\\x6ar "; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "foobax6ar")); + free(t); + assert_se(isempty(p)); + + p = original = " f\\u00f6o \"pi\\U0001F4A9le\" "; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) > 0); + assert_se(streq(t, "föo")); + free(t); + assert_se(p == original + 13); + + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE) > 0); + assert_se(streq(t, "pi\360\237\222\251le")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "\"foo\\"; + assert_se(extract_first_word(&p, &t, NULL, 0) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX) > 0); + assert_se(streq(t, "foo")); + free(t); + assert_se(isempty(p)); + + p = original = "foo::bar"; + assert_se(extract_first_word(&p, &t, ":", 0) == 1); + assert_se(streq(t, "foo")); + free(t); + assert_se(p == original + 5); + + assert_se(extract_first_word(&p, &t, ":", 0) == 1); + assert_se(streq(t, "bar")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word(&p, &t, ":", 0) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "foo\\:bar::waldo"; + assert_se(extract_first_word(&p, &t, ":", 0) == 1); + assert_se(streq(t, "foo:bar")); + free(t); + assert_se(p == original + 10); + + assert_se(extract_first_word(&p, &t, ":", 0) == 1); + assert_se(streq(t, "waldo")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word(&p, &t, ":", 0) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\"foo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE_RELAX) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); + assert_se(streq(t, "foo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "\"foo\\"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); + assert_se(streq(t, "foo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE_RELAX|EXTRACT_RELAX) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL); + assert_se(p == original + 5); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "fooo\\ bar")); + free(t); + assert_se(p == original + 10); + + p = original = "\\w+@\\K[\\d.]+"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\\w+@\\K[\\d.]+"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "\\w+@\\K[\\d.]+")); + free(t); + assert_se(isempty(p)); + + p = original = "\\w+\\b"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_CUNESCAPE|EXTRACT_CUNESCAPE_RELAX) > 0); + assert_se(streq(t, "\\w+\b")); + free(t); + assert_se(isempty(p)); + + p = original = "-N ''"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) > 0); + assert_se(streq(t, "-N")); + free(t); + assert_se(p == original + 3); + + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_UNQUOTE) > 0); + assert_se(streq(t, "")); + free(t); + assert_se(isempty(p)); + + p = original = ":foo\\:bar::waldo:"; + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(t); + assert_se(streq(t, "")); + free(t); + assert_se(p == original + 1); + + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(streq(t, "foo:bar")); + free(t); + assert_se(p == original + 10); + + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(t); + assert_se(streq(t, "")); + free(t); + assert_se(p == original + 11); + + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(streq(t, "waldo")); + free(t); + assert_se(p == original + 17); + + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 1); + assert_se(streq(t, "")); + free(t); + assert_se(p == NULL); + + assert_se(extract_first_word(&p, &t, ":", EXTRACT_DONT_COALESCE_SEPARATORS) == 0); + assert_se(!t); + assert_se(!p); + + p = "foo\\xbar"; + assert_se(extract_first_word(&p, &t, NULL, 0) > 0); + assert_se(streq(t, "fooxbar")); + free(t); + assert_se(p == NULL); + + p = "foo\\xbar"; + assert_se(extract_first_word(&p, &t, NULL, EXTRACT_RETAIN_ESCAPE) > 0); + assert_se(streq(t, "foo\\xbar")); + free(t); + assert_se(p == NULL); +} + +static void test_extract_first_word_and_warn(void) { + const char *p, *original; + char *t; + + p = original = "foobar waldo"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 7); + + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\"foobar\" \'waldo\'"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foobar")); + free(t); + assert_se(p == original + 9); + + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "waldo")); + free(t); + assert_se(isempty(p)); + + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) == 0); + assert_se(!t); + assert_se(isempty(p)); + + p = original = "\""; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 1); + + p = original = "\'fooo"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\'fooo"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(isempty(p)); + + p = original = " foo\\ba\\x6ar "; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foo\ba\x6ar")); + free(t); + assert_se(isempty(p)); + + p = original = " foo\\ba\\x6ar "; + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foobax6ar")); + free(t); + assert_se(isempty(p)); + + p = original = " f\\u00f6o \"pi\\U0001F4A9le\" "; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "föo")); + free(t); + assert_se(p == original + 13); + + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "pi\360\237\222\251le")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo\\")); + free(t); + assert_se(isempty(p)); + + p = original = "\"foo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foo")); + free(t); + assert_se(isempty(p)); + + p = original = "\"foo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE, NULL, "fake", 1, original) == -EINVAL); + assert_se(p == original + 5); + + p = original = "\"foo\\"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE|EXTRACT_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "foo")); + free(t); + assert_se(isempty(p)); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_RELAX, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, 0, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo bar")); + free(t); + assert_se(p == original + 10); + + p = original = "fooo\\ bar quux"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "fooo\\ bar")); + free(t); + assert_se(p == original + 10); + + p = original = "\\w+@\\K[\\d.]+"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "\\w+@\\K[\\d.]+")); + free(t); + assert_se(isempty(p)); + + p = original = "\\w+\\b"; + assert_se(extract_first_word_and_warn(&p, &t, NULL, EXTRACT_CUNESCAPE, NULL, "fake", 1, original) > 0); + assert_se(streq(t, "\\w+\b")); + free(t); + assert_se(isempty(p)); +} + +static void test_extract_many_words(void) { + const char *p, *original; + char *a, *b, *c; + + p = original = "foobar waldi piep"; + assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3); + assert_se(isempty(p)); + assert_se(streq_ptr(a, "foobar")); + assert_se(streq_ptr(b, "waldi")); + assert_se(streq_ptr(c, "piep")); + free(a); + free(b); + free(c); + + p = original = "'foobar' wa\"ld\"i "; + assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 2); + assert_se(isempty(p)); + assert_se(streq_ptr(a, "'foobar'")); + assert_se(streq_ptr(b, "wa\"ld\"i")); + assert_se(streq_ptr(c, NULL)); + free(a); + free(b); + + p = original = "'foobar' wa\"ld\"i "; + assert_se(extract_many_words(&p, NULL, EXTRACT_UNQUOTE, &a, &b, &c, NULL) == 2); + assert_se(isempty(p)); + assert_se(streq_ptr(a, "foobar")); + assert_se(streq_ptr(b, "waldi")); + assert_se(streq_ptr(c, NULL)); + free(a); + free(b); + + p = original = ""; + assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0); + assert_se(isempty(p)); + assert_se(streq_ptr(a, NULL)); + assert_se(streq_ptr(b, NULL)); + assert_se(streq_ptr(c, NULL)); + + p = original = " "; + assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 0); + assert_se(isempty(p)); + assert_se(streq_ptr(a, NULL)); + assert_se(streq_ptr(b, NULL)); + assert_se(streq_ptr(c, NULL)); + + p = original = "foobar"; + assert_se(extract_many_words(&p, NULL, 0, NULL) == 0); + assert_se(p == original); + + p = original = "foobar waldi"; + assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1); + assert_se(p == original+7); + assert_se(streq_ptr(a, "foobar")); + free(a); + + p = original = " foobar "; + assert_se(extract_many_words(&p, NULL, 0, &a, NULL) == 1); + assert_se(isempty(p)); + assert_se(streq_ptr(a, "foobar")); + free(a); +} + +int main(int argc, char *argv[]) { + log_parse_environment(); + log_open(); + + test_extract_first_word(); + test_extract_first_word_and_warn(); + test_extract_many_words(); + + return 0; +} diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c new file mode 100644 index 00000000..71379581 --- /dev/null +++ b/src/test/test-fd-util.c @@ -0,0 +1,335 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "macro.h" +#include "memory-util.h" +#include "path-util.h" +#include "process-util.h" +#include "random-util.h" +#include "serialize.h" +#include "string-util.h" +#include "tests.h" +#include "tmpfile-util.h" + +static void test_close_many(void) { + int fds[3]; + char name0[] = "/tmp/test-close-many.XXXXXX"; + char name1[] = "/tmp/test-close-many.XXXXXX"; + char name2[] = "/tmp/test-close-many.XXXXXX"; + + fds[0] = mkostemp_safe(name0); + fds[1] = mkostemp_safe(name1); + fds[2] = mkostemp_safe(name2); + + close_many(fds, 2); + + assert_se(fcntl(fds[0], F_GETFD) == -1); + assert_se(fcntl(fds[1], F_GETFD) == -1); + assert_se(fcntl(fds[2], F_GETFD) >= 0); + + safe_close(fds[2]); + + unlink(name0); + unlink(name1); + unlink(name2); +} + +static void test_close_nointr(void) { + char name[] = "/tmp/test-test-close_nointr.XXXXXX"; + int fd; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(close_nointr(fd) >= 0); + assert_se(close_nointr(fd) < 0); + + unlink(name); +} + +static void test_same_fd(void) { + _cleanup_close_pair_ int p[2] = { -1, -1 }; + _cleanup_close_ int a = -1, b = -1, c = -1; + + assert_se(pipe2(p, O_CLOEXEC) >= 0); + assert_se((a = fcntl(p[0], F_DUPFD, 3)) >= 0); + assert_se((b = open("/dev/null", O_RDONLY|O_CLOEXEC)) >= 0); + assert_se((c = fcntl(a, F_DUPFD, 3)) >= 0); + + assert_se(same_fd(p[0], p[0]) > 0); + assert_se(same_fd(p[1], p[1]) > 0); + assert_se(same_fd(a, a) > 0); + assert_se(same_fd(b, b) > 0); + + assert_se(same_fd(a, p[0]) > 0); + assert_se(same_fd(p[0], a) > 0); + assert_se(same_fd(c, p[0]) > 0); + assert_se(same_fd(p[0], c) > 0); + assert_se(same_fd(a, c) > 0); + assert_se(same_fd(c, a) > 0); + + assert_se(same_fd(p[0], p[1]) == 0); + assert_se(same_fd(p[1], p[0]) == 0); + assert_se(same_fd(p[0], b) == 0); + assert_se(same_fd(b, p[0]) == 0); + assert_se(same_fd(p[1], a) == 0); + assert_se(same_fd(a, p[1]) == 0); + assert_se(same_fd(p[1], b) == 0); + assert_se(same_fd(b, p[1]) == 0); + + assert_se(same_fd(a, b) == 0); + assert_se(same_fd(b, a) == 0); +} + +static void test_open_serialization_fd(void) { + _cleanup_close_ int fd = -1; + + fd = open_serialization_fd("test"); + assert_se(fd >= 0); + + assert_se(write(fd, "test\n", 5) == 5); +} + +static void test_acquire_data_fd_one(unsigned flags) { + char wbuffer[196*1024 - 7]; + char rbuffer[sizeof(wbuffer)]; + int fd; + + fd = acquire_data_fd("foo", 3, flags); + assert_se(fd >= 0); + + zero(rbuffer); + assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 3); + assert_se(streq(rbuffer, "foo")); + + fd = safe_close(fd); + + fd = acquire_data_fd("", 0, flags); + assert_se(fd >= 0); + + zero(rbuffer); + assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 0); + assert_se(streq(rbuffer, "")); + + fd = safe_close(fd); + + random_bytes(wbuffer, sizeof(wbuffer)); + + fd = acquire_data_fd(wbuffer, sizeof(wbuffer), flags); + assert_se(fd >= 0); + + zero(rbuffer); + assert_se(read(fd, rbuffer, sizeof(rbuffer)) == sizeof(rbuffer)); + assert_se(memcmp(rbuffer, wbuffer, sizeof(rbuffer)) == 0); + + fd = safe_close(fd); +} + +static void test_acquire_data_fd(void) { + + test_acquire_data_fd_one(0); + test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL); + test_acquire_data_fd_one(ACQUIRE_NO_MEMFD); + test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD); + test_acquire_data_fd_one(ACQUIRE_NO_PIPE); + test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_PIPE); + test_acquire_data_fd_one(ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE); + test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE); + test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE|ACQUIRE_NO_TMPFILE); +} + +static void test_fd_move_above_stdio(void) { + int original_stdin, new_fd; + + original_stdin = fcntl(0, F_DUPFD, 3); + assert_se(original_stdin >= 3); + assert_se(close_nointr(0) != EBADF); + + new_fd = open("/dev/null", O_RDONLY); + assert_se(new_fd == 0); + + new_fd = fd_move_above_stdio(new_fd); + assert_se(new_fd >= 3); + + assert_se(dup(original_stdin) == 0); + assert_se(close_nointr(original_stdin) != EBADF); + assert_se(close_nointr(new_fd) != EBADF); +} + +static void test_rearrange_stdio(void) { + pid_t pid; + int r; + + r = safe_fork("rearrange", FORK_WAIT|FORK_LOG, &pid); + assert_se(r >= 0); + + if (r == 0) { + _cleanup_free_ char *path = NULL; + char buffer[10]; + + /* Child */ + + safe_close(STDERR_FILENO); /* Let's close an fd < 2, to make it more interesting */ + + assert_se(rearrange_stdio(-1, -1, -1) >= 0); + + assert_se(fd_get_path(STDIN_FILENO, &path) >= 0); + assert_se(path_equal(path, "/dev/null")); + path = mfree(path); + + assert_se(fd_get_path(STDOUT_FILENO, &path) >= 0); + assert_se(path_equal(path, "/dev/null")); + path = mfree(path); + + assert_se(fd_get_path(STDOUT_FILENO, &path) >= 0); + assert_se(path_equal(path, "/dev/null")); + path = mfree(path); + + safe_close(STDIN_FILENO); + safe_close(STDOUT_FILENO); + safe_close(STDERR_FILENO); + + { + int pair[2]; + assert_se(pipe(pair) >= 0); + assert_se(pair[0] == 0); + assert_se(pair[1] == 1); + assert_se(fd_move_above_stdio(0) == 3); + } + assert_se(open("/dev/full", O_WRONLY|O_CLOEXEC) == 0); + assert_se(acquire_data_fd("foobar", 6, 0) == 2); + + assert_se(rearrange_stdio(2, 0, 1) >= 0); + + assert_se(write(1, "x", 1) < 0 && errno == ENOSPC); + assert_se(write(2, "z", 1) == 1); + assert_se(read(3, buffer, sizeof(buffer)) == 1); + assert_se(buffer[0] == 'z'); + assert_se(read(0, buffer, sizeof(buffer)) == 6); + assert_se(memcmp(buffer, "foobar", 6) == 0); + + assert_se(rearrange_stdio(-1, 1, 2) >= 0); + assert_se(write(1, "a", 1) < 0 && errno == ENOSPC); + assert_se(write(2, "y", 1) == 1); + assert_se(read(3, buffer, sizeof(buffer)) == 1); + assert_se(buffer[0] == 'y'); + + assert_se(fd_get_path(0, &path) >= 0); + assert_se(path_equal(path, "/dev/null")); + path = mfree(path); + + _exit(EXIT_SUCCESS); + } +} + +static void assert_equal_fd(int fd1, int fd2) { + + for (;;) { + uint8_t a[4096], b[4096]; + ssize_t x, y; + + x = read(fd1, a, sizeof(a)); + assert(x >= 0); + + y = read(fd2, b, sizeof(b)); + assert(y >= 0); + + assert(x == y); + + if (x == 0) + break; + + assert(memcmp(a, b, x) == 0); + } +} + +static void test_fd_duplicate_data_fd(void) { + _cleanup_close_ int fd1 = -1, fd2 = -1; + _cleanup_(close_pairp) int sfd[2] = { -1, -1 }; + _cleanup_(sigkill_waitp) pid_t pid = -1; + uint64_t i, j; + int r; + + fd1 = open("/etc/fstab", O_RDONLY|O_CLOEXEC); + if (fd1 >= 0) { + + fd2 = fd_duplicate_data_fd(fd1); + assert_se(fd2 >= 0); + + assert_se(lseek(fd1, 0, SEEK_SET) == 0); + assert_equal_fd(fd1, fd2); + } + + fd1 = safe_close(fd1); + fd2 = safe_close(fd2); + + fd1 = acquire_data_fd("hallo", 6, 0); + assert_se(fd1 >= 0); + + fd2 = fd_duplicate_data_fd(fd1); + assert_se(fd2 >= 0); + + safe_close(fd1); + fd1 = acquire_data_fd("hallo", 6, 0); + assert_se(fd1 >= 0); + + assert_equal_fd(fd1, fd2); + + fd1 = safe_close(fd1); + fd2 = safe_close(fd2); + + assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0); + + r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid); + assert_se(r >= 0); + + if (r == 0) { + /* child */ + + sfd[0] = safe_close(sfd[0]); + + for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++) + assert_se(write(sfd[1], &i, sizeof(i)) == sizeof(i)); + + sfd[1] = safe_close(sfd[1]); + + _exit(EXIT_SUCCESS); + } + + sfd[1] = safe_close(sfd[1]); + + fd2 = fd_duplicate_data_fd(sfd[0]); + assert_se(fd2 >= 0); + + for (i = 0; i < 1536*1024 / sizeof(uint64_t); i++) { + assert_se(read(fd2, &j, sizeof(j)) == sizeof(j)); + assert_se(i == j); + } + + assert_se(read(fd2, &j, sizeof(j)) == 0); +} + +static void test_read_nr_open(void) { + log_info("nr-open: %i", read_nr_open()); +} + +int main(int argc, char *argv[]) { + + test_setup_logging(LOG_DEBUG); + + test_close_many(); + test_close_nointr(); + test_same_fd(); + test_open_serialization_fd(); + test_acquire_data_fd(); + test_fd_move_above_stdio(); + test_rearrange_stdio(); + test_fd_duplicate_data_fd(); + test_read_nr_open(); + + return 0; +} diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c new file mode 100644 index 00000000..fb9d3975 --- /dev/null +++ b/src/test/test-fdset.c @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "fd-util.h" +#include "fdset.h" +#include "macro.h" +#include "tmpfile-util.h" +#include "util.h" + +static void test_fdset_new_fill(void) { + int fd = -1; + _cleanup_fdset_free_ FDSet *fdset = NULL; + char name[] = "/tmp/test-fdset_new_fill.XXXXXX"; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(fdset_new_fill(&fdset) >= 0); + assert_se(fdset_contains(fdset, fd)); + + unlink(name); +} + +static void test_fdset_put_dup(void) { + _cleanup_close_ int fd = -1; + int copyfd = -1; + _cleanup_fdset_free_ FDSet *fdset = NULL; + char name[] = "/tmp/test-fdset_put_dup.XXXXXX"; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + + fdset = fdset_new(); + assert_se(fdset); + copyfd = fdset_put_dup(fdset, fd); + assert_se(copyfd >= 0 && copyfd != fd); + assert_se(fdset_contains(fdset, copyfd)); + assert_se(!fdset_contains(fdset, fd)); + + unlink(name); +} + +static void test_fdset_cloexec(void) { + int fd = -1; + _cleanup_fdset_free_ FDSet *fdset = NULL; + int flags = -1; + char name[] = "/tmp/test-fdset_cloexec.XXXXXX"; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + + fdset = fdset_new(); + assert_se(fdset); + assert_se(fdset_put(fdset, fd)); + + assert_se(fdset_cloexec(fdset, false) >= 0); + flags = fcntl(fd, F_GETFD); + assert_se(flags >= 0); + assert_se(!(flags & FD_CLOEXEC)); + + assert_se(fdset_cloexec(fdset, true) >= 0); + flags = fcntl(fd, F_GETFD); + assert_se(flags >= 0); + assert_se(flags & FD_CLOEXEC); + + unlink(name); +} + +static void test_fdset_close_others(void) { + int fd = -1; + int copyfd = -1; + _cleanup_fdset_free_ FDSet *fdset = NULL; + int flags = -1; + char name[] = "/tmp/test-fdset_close_others.XXXXXX"; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + + fdset = fdset_new(); + assert_se(fdset); + copyfd = fdset_put_dup(fdset, fd); + assert_se(copyfd >= 0); + + assert_se(fdset_close_others(fdset) >= 0); + flags = fcntl(fd, F_GETFD); + assert_se(flags < 0); + flags = fcntl(copyfd, F_GETFD); + assert_se(flags >= 0); + + unlink(name); +} + +static void test_fdset_remove(void) { + _cleanup_close_ int fd = -1; + FDSet *fdset = NULL; + char name[] = "/tmp/test-fdset_remove.XXXXXX"; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + + fdset = fdset_new(); + assert_se(fdset); + assert_se(fdset_put(fdset, fd) >= 0); + assert_se(fdset_remove(fdset, fd) >= 0); + assert_se(!fdset_contains(fdset, fd)); + fdset_free(fdset); + + assert_se(fcntl(fd, F_GETFD) >= 0); + + unlink(name); +} + +static void test_fdset_iterate(void) { + int fd = -1; + FDSet *fdset = NULL; + char name[] = "/tmp/test-fdset_iterate.XXXXXX"; + Iterator i; + int c = 0; + int a; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + + fdset = fdset_new(); + assert_se(fdset); + assert_se(fdset_put(fdset, fd) >= 0); + assert_se(fdset_put(fdset, fd) >= 0); + assert_se(fdset_put(fdset, fd) >= 0); + + FDSET_FOREACH(a, fdset, i) { + c++; + assert_se(a == fd); + } + assert_se(c == 1); + + fdset_free(fdset); + + unlink(name); +} + +static void test_fdset_isempty(void) { + int fd; + _cleanup_fdset_free_ FDSet *fdset = NULL; + char name[] = "/tmp/test-fdset_isempty.XXXXXX"; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + + fdset = fdset_new(); + assert_se(fdset); + + assert_se(fdset_isempty(fdset)); + assert_se(fdset_put(fdset, fd) >= 0); + assert_se(!fdset_isempty(fdset)); + + unlink(name); +} + +static void test_fdset_steal_first(void) { + int fd; + _cleanup_fdset_free_ FDSet *fdset = NULL; + char name[] = "/tmp/test-fdset_steal_first.XXXXXX"; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + + fdset = fdset_new(); + assert_se(fdset); + + assert_se(fdset_steal_first(fdset) < 0); + assert_se(fdset_put(fdset, fd) >= 0); + assert_se(fdset_steal_first(fdset) == fd); + assert_se(fdset_steal_first(fdset) < 0); + assert_se(fdset_put(fdset, fd) >= 0); + + unlink(name); +} + +static void test_fdset_new_array(void) { + int fds[] = {10, 11, 12, 13}; + _cleanup_fdset_free_ FDSet *fdset = NULL; + + assert_se(fdset_new_array(&fdset, fds, 4) >= 0); + assert_se(fdset_size(fdset) == 4); + assert_se(fdset_contains(fdset, 10)); + assert_se(fdset_contains(fdset, 11)); + assert_se(fdset_contains(fdset, 12)); + assert_se(fdset_contains(fdset, 13)); +} + +int main(int argc, char *argv[]) { + test_fdset_new_fill(); + test_fdset_put_dup(); + test_fdset_cloexec(); + test_fdset_close_others(); + test_fdset_remove(); + test_fdset_iterate(); + test_fdset_isempty(); + test_fdset_steal_first(); + test_fdset_new_array(); + + return 0; +} diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c new file mode 100644 index 00000000..23c7d370 --- /dev/null +++ b/src/test/test-fileio.c @@ -0,0 +1,870 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "ctype.h" +#include "env-file.h" +#include "env-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "io-util.h" +#include "parse-util.h" +#include "process-util.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "tmpfile-util.h" +#include "util.h" + +static void test_parse_env_file(void) { + _cleanup_(unlink_tempfilep) char + t[] = "/tmp/test-fileio-in-XXXXXX", + p[] = "/tmp/test-fileio-out-XXXXXX"; + FILE *f; + _cleanup_free_ char *one = NULL, *two = NULL, *three = NULL, *four = NULL, *five = NULL, + *six = NULL, *seven = NULL, *eight = NULL, *nine = NULL, *ten = NULL, + *eleven = NULL, *twelve = NULL, *thirteen = NULL; + _cleanup_strv_free_ char **a = NULL, **b = NULL; + char **i; + unsigned k; + int r; + + assert_se(fmkostemp_safe(t, "w", &f) == 0); + fputs("one=BAR \n" + "# comment\n" + " # comment \n" + " ; comment \n" + " two = bar \n" + "invalid line\n" + "invalid line #comment\n" + "three = \"333\n" + "xxxx\"\n" + "four = \'44\\\"44\'\n" + "five = \"55\\\"55\" \"FIVE\" cinco \n" + "six = seis sechs\\\n" + " sis\n" + "seven=\"sevenval\" #nocomment\n" + "eight=eightval #nocomment\n" + "export nine=nineval\n" + "ten=ignored\n" + "ten=ignored\n" + "ten=\n" + "eleven=\\value\n" + "twelve=\"\\value\"\n" + "thirteen='\\value'", f); + + fflush(f); + fclose(f); + + r = load_env_file(NULL, t, &a); + assert_se(r >= 0); + + STRV_FOREACH(i, a) + log_info("Got: <%s>", *i); + + assert_se(streq_ptr(a[0], "one=BAR")); + assert_se(streq_ptr(a[1], "two=bar")); + assert_se(streq_ptr(a[2], "three=333\nxxxx")); + assert_se(streq_ptr(a[3], "four=44\\\"44")); + assert_se(streq_ptr(a[4], "five=55\"55FIVEcinco")); + assert_se(streq_ptr(a[5], "six=seis sechs sis")); + assert_se(streq_ptr(a[6], "seven=sevenval#nocomment")); + assert_se(streq_ptr(a[7], "eight=eightval #nocomment")); + assert_se(streq_ptr(a[8], "export nine=nineval")); + assert_se(streq_ptr(a[9], "ten=")); + assert_se(streq_ptr(a[10], "eleven=value")); + assert_se(streq_ptr(a[11], "twelve=\\value")); + assert_se(streq_ptr(a[12], "thirteen=\\value")); + assert_se(a[13] == NULL); + + strv_env_clean(a); + + k = 0; + STRV_FOREACH(i, b) { + log_info("Got2: <%s>", *i); + assert_se(streq(*i, a[k++])); + } + + r = parse_env_file( + NULL, t, + "one", &one, + "two", &two, + "three", &three, + "four", &four, + "five", &five, + "six", &six, + "seven", &seven, + "eight", &eight, + "export nine", &nine, + "ten", &ten, + "eleven", &eleven, + "twelve", &twelve, + "thirteen", &thirteen); + + assert_se(r >= 0); + + log_info("one=[%s]", strna(one)); + log_info("two=[%s]", strna(two)); + log_info("three=[%s]", strna(three)); + log_info("four=[%s]", strna(four)); + log_info("five=[%s]", strna(five)); + log_info("six=[%s]", strna(six)); + log_info("seven=[%s]", strna(seven)); + log_info("eight=[%s]", strna(eight)); + log_info("export nine=[%s]", strna(nine)); + log_info("ten=[%s]", strna(nine)); + log_info("eleven=[%s]", strna(eleven)); + log_info("twelve=[%s]", strna(twelve)); + log_info("thirteen=[%s]", strna(thirteen)); + + assert_se(streq(one, "BAR")); + assert_se(streq(two, "bar")); + assert_se(streq(three, "333\nxxxx")); + assert_se(streq(four, "44\\\"44")); + assert_se(streq(five, "55\"55FIVEcinco")); + assert_se(streq(six, "seis sechs sis")); + assert_se(streq(seven, "sevenval#nocomment")); + assert_se(streq(eight, "eightval #nocomment")); + assert_se(streq(nine, "nineval")); + assert_se(ten == NULL); + assert_se(streq(eleven, "value")); + assert_se(streq(twelve, "\\value")); + assert_se(streq(thirteen, "\\value")); + + { + /* prepare a temporary file to write the environment to */ + _cleanup_close_ int fd = mkostemp_safe(p); + assert_se(fd >= 0); + } + + r = write_env_file(p, a); + assert_se(r >= 0); + + r = load_env_file(NULL, p, &b); + assert_se(r >= 0); +} + +static void test_parse_multiline_env_file(void) { + _cleanup_(unlink_tempfilep) char + t[] = "/tmp/test-fileio-in-XXXXXX", + p[] = "/tmp/test-fileio-out-XXXXXX"; + FILE *f; + _cleanup_strv_free_ char **a = NULL, **b = NULL; + char **i; + int r; + + assert_se(fmkostemp_safe(t, "w", &f) == 0); + fputs("one=BAR\\\n" + " VAR\\\n" + "\tGAR\n" + "#comment\n" + "two=\"bar\\\n" + " var\\\n" + "\tgar\"\n" + "#comment\n" + "tri=\"bar \\\n" + " var \\\n" + "\tgar \"\n", f); + + fflush(f); + fclose(f); + + r = load_env_file(NULL, t, &a); + assert_se(r >= 0); + + STRV_FOREACH(i, a) + log_info("Got: <%s>", *i); + + assert_se(streq_ptr(a[0], "one=BAR VAR\tGAR")); + assert_se(streq_ptr(a[1], "two=bar var\tgar")); + assert_se(streq_ptr(a[2], "tri=bar var \tgar ")); + assert_se(a[3] == NULL); + + { + _cleanup_close_ int fd = mkostemp_safe(p); + assert_se(fd >= 0); + } + + r = write_env_file(p, a); + assert_se(r >= 0); + + r = load_env_file(NULL, p, &b); + assert_se(r >= 0); +} + +static void test_merge_env_file(void) { + _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_strv_free_ char **a = NULL; + char **i; + int r; + + assert_se(fmkostemp_safe(t, "w", &f) == 0); + log_info("/* %s (%s) */", __func__, t); + + r = write_string_stream(f, + "one=1 \n" + "twelve=${one}2\n" + "twentyone=2${one}\n" + "one=2\n" + "twentytwo=2${one}\n" + "xxx_minus_three=$xxx - 3\n" + "xxx=0x$one$one$one\n" + "yyy=${one:-fallback}\n" + "zzz=${one:+replacement}\n" + "zzzz=${foobar:-${nothing}}\n" + "zzzzz=${nothing:+${nothing}}\n" + , WRITE_STRING_FILE_AVOID_NEWLINE); + assert(r >= 0); + + r = merge_env_file(&a, NULL, t); + assert_se(r >= 0); + strv_sort(a); + + STRV_FOREACH(i, a) + log_info("Got: <%s>", *i); + + assert_se(streq(a[0], "one=2")); + assert_se(streq(a[1], "twelve=12")); + assert_se(streq(a[2], "twentyone=21")); + assert_se(streq(a[3], "twentytwo=22")); + assert_se(streq(a[4], "xxx=0x222")); + assert_se(streq(a[5], "xxx_minus_three= - 3")); + assert_se(streq(a[6], "yyy=2")); + assert_se(streq(a[7], "zzz=replacement")); + assert_se(streq(a[8], "zzzz=")); + assert_se(streq(a[9], "zzzzz=")); + assert_se(a[10] == NULL); + + r = merge_env_file(&a, NULL, t); + assert_se(r >= 0); + strv_sort(a); + + STRV_FOREACH(i, a) + log_info("Got2: <%s>", *i); + + assert_se(streq(a[0], "one=2")); + assert_se(streq(a[1], "twelve=12")); + assert_se(streq(a[2], "twentyone=21")); + assert_se(streq(a[3], "twentytwo=22")); + assert_se(streq(a[4], "xxx=0x222")); + assert_se(streq(a[5], "xxx_minus_three=0x222 - 3")); + assert_se(streq(a[6], "yyy=2")); + assert_se(streq(a[7], "zzz=replacement")); + assert_se(streq(a[8], "zzzz=")); + assert_se(streq(a[9], "zzzzz=")); + assert_se(a[10] == NULL); +} + +static void test_merge_env_file_invalid(void) { + _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_strv_free_ char **a = NULL; + char **i; + int r; + + assert_se(fmkostemp_safe(t, "w", &f) == 0); + log_info("/* %s (%s) */", __func__, t); + + r = write_string_stream(f, + "unset one \n" + "unset one= \n" + "unset one=1 \n" + "one \n" + "one = \n" + "one two =\n" + "\x20two=\n" + "#comment=comment\n" + ";comment2=comment2\n" + "#\n" + "\n\n" /* empty line */ + , WRITE_STRING_FILE_AVOID_NEWLINE); + assert(r >= 0); + + r = merge_env_file(&a, NULL, t); + assert_se(r >= 0); + + STRV_FOREACH(i, a) + log_info("Got: <%s>", *i); + + assert_se(strv_isempty(a)); +} + +static void test_executable_is_script(void) { + _cleanup_(unlink_tempfilep) char t[] = "/tmp/test-fileio-XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + char *command; + int r; + + assert_se(fmkostemp_safe(t, "w", &f) == 0); + fputs("#! /bin/script -a -b \ngoo goo", f); + fflush(f); + + r = executable_is_script(t, &command); + assert_se(r > 0); + assert_se(streq(command, "/bin/script")); + free(command); + + r = executable_is_script("/bin/sh", &command); + assert_se(r == 0); + + r = executable_is_script("/usr/bin/yum", &command); + assert_se(r > 0 || r == -ENOENT); + if (r > 0) { + assert_se(startswith(command, "/")); + free(command); + } +} + +static void test_status_field(void) { + _cleanup_free_ char *t = NULL, *p = NULL, *s = NULL, *z = NULL; + unsigned long long total = 0, buffers = 0; + int r; + + assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0); + puts(t); + assert_se(streq(t, "1")); + + r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p); + if (r != -ENOENT) { + assert_se(r == 0); + puts(p); + assert_se(safe_atollu(p, &total) == 0); + } + + r = get_proc_field("/proc/meminfo", "Buffers", WHITESPACE, &s); + if (r != -ENOENT) { + assert_se(r == 0); + puts(s); + assert_se(safe_atollu(s, &buffers) == 0); + } + + if (p) + assert_se(buffers < total); + + /* Seccomp should be a good test for field full of zeros. */ + r = get_proc_field("/proc/meminfo", "Seccomp", WHITESPACE, &z); + if (r != -ENOENT) { + assert_se(r == 0); + puts(z); + assert_se(safe_atollu(z, &buffers) == 0); + } +} + +static void test_capeff(void) { + int pid, p; + + for (pid = 0; pid < 2; pid++) { + _cleanup_free_ char *capeff = NULL; + int r; + + r = get_process_capeff(0, &capeff); + log_info("capeff: '%s' (r=%d)", capeff, r); + + if (IN_SET(r, -ENOENT, -EPERM)) + return; + + assert_se(r == 0); + assert_se(*capeff); + p = capeff[strspn(capeff, HEXDIGITS)]; + assert_se(!p || isspace(p)); + } +} + +static void test_write_string_stream(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_stream-XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + int fd; + char buf[64]; + + fd = mkostemp_safe(fn); + assert_se(fd >= 0); + + f = fdopen(fd, "r"); + assert_se(f); + assert_se(write_string_stream(f, "boohoo", 0) < 0); + f = safe_fclose(f); + + f = fopen(fn, "r+"); + assert_se(f); + + assert_se(write_string_stream(f, "boohoo", 0) == 0); + rewind(f); + + assert_se(fgets(buf, sizeof(buf), f)); + assert_se(streq(buf, "boohoo\n")); + f = safe_fclose(f); + + f = fopen(fn, "w+"); + assert_se(f); + + assert_se(write_string_stream(f, "boohoo", WRITE_STRING_FILE_AVOID_NEWLINE) == 0); + rewind(f); + + assert_se(fgets(buf, sizeof(buf), f)); + printf(">%s<", buf); + assert_se(streq(buf, "boohoo")); +} + +static void test_write_string_file(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file-XXXXXX"; + char buf[64] = {}; + _cleanup_close_ int fd; + + fd = mkostemp_safe(fn); + assert_se(fd >= 0); + + assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0); + + assert_se(read(fd, buf, sizeof(buf)) == 7); + assert_se(streq(buf, "boohoo\n")); +} + +static void test_write_string_file_no_create(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-write_string_file_no_create-XXXXXX"; + _cleanup_close_ int fd; + char buf[64] = {}; + + fd = mkostemp_safe(fn); + assert_se(fd >= 0); + + assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0); + assert_se(write_string_file(fn, "boohoo", 0) == 0); + + assert_se(read(fd, buf, sizeof buf) == (ssize_t) strlen("boohoo\n")); + assert_se(streq(buf, "boohoo\n")); +} + +static void test_write_string_file_verify(void) { + _cleanup_free_ char *buf = NULL, *buf2 = NULL; + int r; + + assert_se(read_one_line_file("/proc/cmdline", &buf) >= 0); + assert_se(buf2 = strjoin(buf, "\n")); + + r = write_string_file("/proc/cmdline", buf, 0); + assert_se(IN_SET(r, -EACCES, -EIO)); + r = write_string_file("/proc/cmdline", buf2, 0); + assert_se(IN_SET(r, -EACCES, -EIO)); + + assert_se(write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0); + assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE) == 0); + + r = write_string_file("/proc/cmdline", buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE); + assert_se(IN_SET(r, -EACCES, -EIO)); + assert_se(write_string_file("/proc/cmdline", buf2, WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_AVOID_NEWLINE) == 0); +} + +static void test_load_env_file_pairs(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX"; + int fd, r; + _cleanup_fclose_ FILE *f = NULL; + _cleanup_strv_free_ char **l = NULL; + char **k, **v; + + fd = mkostemp_safe(fn); + assert_se(fd >= 0); + + r = write_string_file(fn, + "NAME=\"Arch Linux\"\n" + "ID=arch\n" + "PRETTY_NAME=\"Arch Linux\"\n" + "ANSI_COLOR=\"0;36\"\n" + "HOME_URL=\"https://www.archlinux.org/\"\n" + "SUPPORT_URL=\"https://bbs.archlinux.org/\"\n" + "BUG_REPORT_URL=\"https://bugs.archlinux.org/\"\n", + WRITE_STRING_FILE_CREATE); + assert_se(r == 0); + + f = fdopen(fd, "r"); + assert_se(f); + + r = load_env_file_pairs(f, fn, &l); + assert_se(r >= 0); + + assert_se(strv_length(l) == 14); + STRV_FOREACH_PAIR(k, v, l) { + assert_se(STR_IN_SET(*k, "NAME", "ID", "PRETTY_NAME", "ANSI_COLOR", "HOME_URL", "SUPPORT_URL", "BUG_REPORT_URL")); + printf("%s=%s\n", *k, *v); + if (streq(*k, "NAME")) assert_se(streq(*v, "Arch Linux")); + if (streq(*k, "ID")) assert_se(streq(*v, "arch")); + if (streq(*k, "PRETTY_NAME")) assert_se(streq(*v, "Arch Linux")); + if (streq(*k, "ANSI_COLOR")) assert_se(streq(*v, "0;36")); + if (streq(*k, "HOME_URL")) assert_se(streq(*v, "https://www.archlinux.org/")); + if (streq(*k, "SUPPORT_URL")) assert_se(streq(*v, "https://bbs.archlinux.org/")); + if (streq(*k, "BUG_REPORT_URL")) assert_se(streq(*v, "https://bugs.archlinux.org/")); + } +} + +static void test_search_and_fopen(void) { + const char *dirs[] = {"/tmp/foo/bar", "/tmp", NULL}; + + char name[] = "/tmp/test-search_and_fopen.XXXXXX"; + int fd, r; + FILE *f; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + close(fd); + + r = search_and_fopen(basename(name), "r", NULL, dirs, &f); + assert_se(r >= 0); + fclose(f); + + r = search_and_fopen(name, "r", NULL, dirs, &f); + assert_se(r >= 0); + fclose(f); + + r = search_and_fopen(basename(name), "r", "/", dirs, &f); + assert_se(r >= 0); + fclose(f); + + r = search_and_fopen("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f); + assert_se(r < 0); + r = search_and_fopen("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f); + assert_se(r < 0); + + r = unlink(name); + assert_se(r == 0); + + r = search_and_fopen(basename(name), "r", NULL, dirs, &f); + assert_se(r < 0); +} + +static void test_search_and_fopen_nulstr(void) { + const char dirs[] = "/tmp/foo/bar\0/tmp\0"; + + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-search_and_fopen.XXXXXX"; + int fd, r; + FILE *f; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + close(fd); + + r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f); + assert_se(r >= 0); + fclose(f); + + r = search_and_fopen_nulstr(name, "r", NULL, dirs, &f); + assert_se(r >= 0); + fclose(f); + + r = search_and_fopen_nulstr("/a/file/which/does/not/exist/i/guess", "r", NULL, dirs, &f); + assert_se(r < 0); + r = search_and_fopen_nulstr("afilewhichdoesnotexistiguess", "r", NULL, dirs, &f); + assert_se(r < 0); + + r = unlink(name); + assert_se(r == 0); + + r = search_and_fopen_nulstr(basename(name), "r", NULL, dirs, &f); + assert_se(r < 0); +} + +static void test_writing_tmpfile(void) { + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-systemd_writing_tmpfile.XXXXXX"; + _cleanup_free_ char *contents = NULL; + size_t size; + _cleanup_close_ int fd = -1; + struct iovec iov[3]; + int r; + + iov[0] = IOVEC_MAKE_STRING("abc\n"); + iov[1] = IOVEC_MAKE_STRING(ALPHANUMERICAL "\n"); + iov[2] = IOVEC_MAKE_STRING(""); + + fd = mkostemp_safe(name); + printf("tmpfile: %s", name); + + r = writev(fd, iov, 3); + assert_se(r >= 0); + + r = read_full_file(name, &contents, &size); + assert_se(r == 0); + printf("contents: %s", contents); + assert_se(streq(contents, "abc\n" ALPHANUMERICAL "\n")); +} + +static void test_tempfn(void) { + char *ret = NULL, *p; + + assert_se(tempfn_xxxxxx("/foo/bar/waldo", NULL, &ret) >= 0); + assert_se(streq_ptr(ret, "/foo/bar/.#waldoXXXXXX")); + free(ret); + + assert_se(tempfn_xxxxxx("/foo/bar/waldo", "[miau]", &ret) >= 0); + assert_se(streq_ptr(ret, "/foo/bar/.#[miau]waldoXXXXXX")); + free(ret); + + assert_se(tempfn_random("/foo/bar/waldo", NULL, &ret) >= 0); + assert_se(p = startswith(ret, "/foo/bar/.#waldo")); + assert_se(strlen(p) == 16); + assert_se(in_charset(p, "0123456789abcdef")); + free(ret); + + assert_se(tempfn_random("/foo/bar/waldo", "[wuff]", &ret) >= 0); + assert_se(p = startswith(ret, "/foo/bar/.#[wuff]waldo")); + assert_se(strlen(p) == 16); + assert_se(in_charset(p, "0123456789abcdef")); + free(ret); + + assert_se(tempfn_random_child("/foo/bar/waldo", NULL, &ret) >= 0); + assert_se(p = startswith(ret, "/foo/bar/waldo/.#")); + assert_se(strlen(p) == 16); + assert_se(in_charset(p, "0123456789abcdef")); + free(ret); + + assert_se(tempfn_random_child("/foo/bar/waldo", "[kikiriki]", &ret) >= 0); + assert_se(p = startswith(ret, "/foo/bar/waldo/.#[kikiriki]")); + assert_se(strlen(p) == 16); + assert_se(in_charset(p, "0123456789abcdef")); + free(ret); +} + +static const char chars[] = + "Aąę„”\n루\377"; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" + +static void test_fgetc(void) { + _cleanup_fclose_ FILE *f = NULL; + char c; + + f = fmemopen_unlocked((void*) chars, sizeof(chars), "re"); + assert_se(f); + + for (size_t i = 0; i < sizeof(chars); i++) { + assert_se(safe_fgetc(f, &c) == 1); + assert_se(c == chars[i]); + + if (ungetc(c, f) == EOF) { + /* EOF is -1, and hence we can't push value 255 in this way – if char is signed */ + assert_se(c == (char) EOF); + assert_se(CHAR_MIN == -128); /* verify that char is signed on this platform */ + } else { + assert_se(safe_fgetc(f, &c) == 1); + assert_se(c == chars[i]); + } + + /* But it works when we push it properly cast */ + assert_se(ungetc((unsigned char) c, f) != EOF); + assert_se(safe_fgetc(f, &c) == 1); + assert_se(c == chars[i]); + } + + assert_se(safe_fgetc(f, &c) == 0); +} + +#pragma GCC diagnostic pop + +static const char buffer[] = + "Some test data\n" + "루Non-ascii chars: ąę„”\n" + "terminators\r\n" + "and even more\n\r" + "now the same with a NUL\n\0" + "and more\r\0" + "and even more\r\n\0" + "and yet even more\n\r\0" + "With newlines, and a NUL byte\0" + "\n" + "an empty line\n" + "an ignored line\n" + "and a very long line that is supposed to be truncated, because it is so long\n"; + +static void test_read_line_one_file(FILE *f) { + _cleanup_free_ char *line = NULL; + + assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "Some test data")); + line = mfree(line); + + assert_se(read_line(f, (size_t) -1, &line) > 0 && streq(line, "루Non-ascii chars: ąę„”")); + line = mfree(line); + + assert_se(read_line(f, (size_t) -1, &line) == 13 && streq(line, "terminators")); + line = mfree(line); + + assert_se(read_line(f, (size_t) -1, &line) == 15 && streq(line, "and even more")); + line = mfree(line); + + assert_se(read_line(f, (size_t) -1, &line) == 25 && streq(line, "now the same with a NUL")); + line = mfree(line); + + assert_se(read_line(f, (size_t) -1, &line) == 10 && streq(line, "and more")); + line = mfree(line); + + assert_se(read_line(f, (size_t) -1, &line) == 16 && streq(line, "and even more")); + line = mfree(line); + + assert_se(read_line(f, (size_t) -1, &line) == 20 && streq(line, "and yet even more")); + line = mfree(line); + + assert_se(read_line(f, 1024, &line) == 30 && streq(line, "With newlines, and a NUL byte")); + line = mfree(line); + + assert_se(read_line(f, 1024, &line) == 1 && streq(line, "")); + line = mfree(line); + + assert_se(read_line(f, 1024, &line) == 14 && streq(line, "an empty line")); + line = mfree(line); + + assert_se(read_line(f, (size_t) -1, NULL) == 16); + + assert_se(read_line(f, 16, &line) == -ENOBUFS); + line = mfree(line); + + /* read_line() stopped when it hit the limit, that means when we continue reading we'll read at the first + * character after the previous limit. Let's make use of that to continue our test. */ + assert_se(read_line(f, 1024, &line) == 62 && streq(line, "line that is supposed to be truncated, because it is so long")); + line = mfree(line); + + assert_se(read_line(f, 1024, &line) == 0 && streq(line, "")); +} + +static void test_read_line(void) { + _cleanup_fclose_ FILE *f = NULL; + + f = fmemopen_unlocked((void*) buffer, sizeof(buffer), "re"); + assert_se(f); + + test_read_line_one_file(f); +} + +static void test_read_line2(void) { + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-fileio.XXXXXX"; + int fd; + _cleanup_fclose_ FILE *f = NULL; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se((size_t) write(fd, buffer, sizeof(buffer)) == sizeof(buffer)); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(f = fdopen(fd, "r")); + + test_read_line_one_file(f); +} + +static void test_read_line3(void) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *line = NULL; + int r; + + f = fopen("/proc/cmdline", "re"); + if (!f && IN_SET(errno, ENOENT, EPERM)) + return; + assert_se(f); + + r = read_line(f, LINE_MAX, &line); + assert_se(r >= 0); + if (r == 0) + assert_se(line && isempty(line)); + else + assert_se((size_t) r == strlen(line) + 1); + assert_se(read_line(f, LINE_MAX, NULL) == 0); +} + +static void test_read_line4(void) { + static const struct { + size_t length; + const char *string; + } eof_endings[] = { + /* Each of these will be followed by EOF and should generate the one same single string */ + { 3, "foo" }, + { 4, "foo\n" }, + { 4, "foo\r" }, + { 4, "foo\0" }, + { 5, "foo\n\0" }, + { 5, "foo\r\0" }, + { 5, "foo\r\n" }, + { 5, "foo\n\r" }, + { 6, "foo\r\n\0" }, + { 6, "foo\n\r\0" }, + }; + + size_t i; + int r; + + for (i = 0; i < ELEMENTSOF(eof_endings); i++) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *s = NULL; + + assert_se(f = fmemopen_unlocked((void*) eof_endings[i].string, eof_endings[i].length, "r")); + + r = read_line(f, (size_t) -1, &s); + assert_se((size_t) r == eof_endings[i].length); + assert_se(streq_ptr(s, "foo")); + + assert_se(read_line(f, (size_t) -1, NULL) == 0); /* Ensure we hit EOF */ + } +} + +static void test_read_nul_string(void) { + static const char test[] = "string nr. 1\0" + "string nr. 2\n\0" + "\377empty string follows\0" + "\0" + "final string\n is empty\0" + "\0"; + + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *s = NULL; + + assert_se(f = fmemopen_unlocked((void*) test, sizeof(test)-1, "r")); + + assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 13 && streq_ptr(s, "string nr. 1")); + s = mfree(s); + + assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 14 && streq_ptr(s, "string nr. 2\n")); + s = mfree(s); + + assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 22 && streq_ptr(s, "\377empty string follows")); + s = mfree(s); + + assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 1 && streq_ptr(s, "")); + s = mfree(s); + + assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 23 && streq_ptr(s, "final string\n is empty")); + s = mfree(s); + + assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 1 && streq_ptr(s, "")); + s = mfree(s); + + assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 0 && streq_ptr(s, "")); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_parse_env_file(); + test_parse_multiline_env_file(); + test_merge_env_file(); + test_merge_env_file_invalid(); + test_executable_is_script(); + test_status_field(); + test_capeff(); + test_write_string_stream(); + test_write_string_file(); + test_write_string_file_no_create(); + test_write_string_file_verify(); + test_load_env_file_pairs(); + test_search_and_fopen(); + test_search_and_fopen_nulstr(); + test_writing_tmpfile(); + test_tempfn(); + test_fgetc(); + test_read_line(); + test_read_line2(); + test_read_line3(); + test_read_line4(); + test_read_nul_string(); + + return 0; +} diff --git a/src/test/test-firewall-util.c b/src/test/test-firewall-util.c new file mode 100644 index 00000000..1788e8d1 --- /dev/null +++ b/src/test/test-firewall-util.c @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "firewall-util.h" +#include "log.h" +#include "tests.h" + +#define MAKE_IN_ADDR_UNION(a,b,c,d) (union in_addr_union) { .in.s_addr = htobe32((uint32_t) (a) << 24 | (uint32_t) (b) << 16 | (uint32_t) (c) << 8 | (uint32_t) (d))} + +int main(int argc, char *argv[]) { + int r; + test_setup_logging(LOG_DEBUG); + + r = fw_add_masquerade(true, AF_INET, 0, NULL, 0, "foobar", NULL, 0); + if (r < 0) + log_error_errno(r, "Failed to modify firewall: %m"); + + r = fw_add_masquerade(true, AF_INET, 0, NULL, 0, "foobar", NULL, 0); + if (r < 0) + log_error_errno(r, "Failed to modify firewall: %m"); + + r = fw_add_masquerade(false, AF_INET, 0, NULL, 0, "foobar", NULL, 0); + if (r < 0) + log_error_errno(r, "Failed to modify firewall: %m"); + + r = fw_add_local_dnat(true, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 4), 815, NULL); + if (r < 0) + log_error_errno(r, "Failed to modify firewall: %m"); + + r = fw_add_local_dnat(true, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 4), 815, NULL); + if (r < 0) + log_error_errno(r, "Failed to modify firewall: %m"); + + r = fw_add_local_dnat(true, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 5), 815, &MAKE_IN_ADDR_UNION(1, 2, 3, 4)); + if (r < 0) + log_error_errno(r, "Failed to modify firewall: %m"); + + r = fw_add_local_dnat(false, AF_INET, IPPROTO_TCP, NULL, NULL, 0, NULL, 0, 4711, &MAKE_IN_ADDR_UNION(1, 2, 3, 5), 815, NULL); + if (r < 0) + log_error_errno(r, "Failed to modify firewall: %m"); + + return 0; +} diff --git a/src/test/test-format-table.c b/src/test/test-format-table.c new file mode 100644 index 00000000..96b1d777 --- /dev/null +++ b/src/test/test-format-table.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "format-table.h" +#include "string-util.h" +#include "time-util.h" + +static void test_issue_9549(void) { + _cleanup_(table_unrefp) Table *table = NULL; + _cleanup_free_ char *formatted = NULL; + + assert_se(table = table_new("name", "type", "ro", "usage", "created", "modified")); + assert_se(table_set_align_percent(table, TABLE_HEADER_CELL(3), 100) >= 0); + assert_se(table_add_many(table, + TABLE_STRING, "foooo", + TABLE_STRING, "raw", + TABLE_BOOLEAN, false, + TABLE_SIZE, (uint64_t) (673.7*1024*1024), + TABLE_STRING, "Wed 2018-07-11 00:10:33 JST", + TABLE_STRING, "Wed 2018-07-11 00:16:00 JST") >= 0); + + table_set_width(table, 75); + assert_se(table_format(table, &formatted) >= 0); + + printf("%s\n", formatted); + assert_se(streq(formatted, + "NAME TYPE RO USAGE CREATED MODIFIED \n" + "foooo raw no 673.6M Wed 2018-07-11 00:10:33 J… Wed 2018-07-11 00:16:00 JST\n" + )); +} + +int main(int argc, char *argv[]) { + + _cleanup_(table_unrefp) Table *t = NULL; + _cleanup_free_ char *formatted = NULL; + + assert_se(setenv("SYSTEMD_COLORS", "0", 1) >= 0); + assert_se(setenv("COLUMNS", "40", 1) >= 0); + + assert_se(t = table_new("one", "two", "three")); + + assert_se(table_set_align_percent(t, TABLE_HEADER_CELL(2), 100) >= 0); + + assert_se(table_add_many(t, + TABLE_STRING, "xxx", + TABLE_STRING, "yyy", + TABLE_BOOLEAN, true) >= 0); + + assert_se(table_add_many(t, + TABLE_STRING, "a long field", + TABLE_STRING, "yyy", + TABLE_SET_UPPERCASE, 1, + TABLE_BOOLEAN, false) >= 0); + + assert_se(table_format(t, &formatted) >= 0); + printf("%s\n", formatted); + + assert_se(streq(formatted, + "ONE TWO THREE\n" + "xxx yyy yes\n" + "a long field YYY no\n")); + + formatted = mfree(formatted); + + table_set_width(t, 40); + + assert_se(table_format(t, &formatted) >= 0); + printf("%s\n", formatted); + + assert_se(streq(formatted, + "ONE TWO THREE\n" + "xxx yyy yes\n" + "a long field YYY no\n")); + + formatted = mfree(formatted); + + table_set_width(t, 12); + assert_se(table_format(t, &formatted) >= 0); + printf("%s\n", formatted); + + assert_se(streq(formatted, + "ONE TWO THR…\n" + "xxx yyy yes\n" + "a … YYY no\n")); + + formatted = mfree(formatted); + + table_set_width(t, 5); + assert_se(table_format(t, &formatted) >= 0); + printf("%s\n", formatted); + + assert_se(streq(formatted, + "… … …\n" + "… … …\n" + "… … …\n")); + + formatted = mfree(formatted); + + table_set_width(t, 3); + assert_se(table_format(t, &formatted) >= 0); + printf("%s\n", formatted); + + assert_se(streq(formatted, + "… … …\n" + "… … …\n" + "… … …\n")); + + formatted = mfree(formatted); + + table_set_width(t, (size_t) -1); + assert_se(table_set_sort(t, (size_t) 0, (size_t) 2, (size_t) -1) >= 0); + + assert_se(table_format(t, &formatted) >= 0); + printf("%s\n", formatted); + + assert_se(streq(formatted, + "ONE TWO THREE\n" + "a long field YYY no\n" + "xxx yyy yes\n")); + + formatted = mfree(formatted); + + table_set_header(t, false); + + assert_se(table_add_many(t, + TABLE_STRING, "fäää", + TABLE_STRING, "uuu", + TABLE_BOOLEAN, true) >= 0); + + assert_se(table_add_many(t, + TABLE_STRING, "fäää", + TABLE_STRING, "zzz", + TABLE_BOOLEAN, false) >= 0); + + assert_se(table_add_many(t, + TABLE_EMPTY, + TABLE_SIZE, (uint64_t) 4711, + TABLE_TIMESPAN, (usec_t) 5*USEC_PER_MINUTE) >= 0); + + assert_se(table_format(t, &formatted) >= 0); + printf("%s\n", formatted); + + assert_se(streq(formatted, + "a long field YYY no\n" + "fäää zzz no\n" + "fäää uuu yes\n" + "xxx yyy yes\n" + " 4.6K 5min\n")); + + formatted = mfree(formatted); + + assert_se(table_set_display(t, (size_t) 2, (size_t) 0, (size_t) 2, (size_t) 0, (size_t) 0, (size_t) -1) >= 0); + + assert_se(table_format(t, &formatted) >= 0); + printf("%s\n", formatted); + + if (isatty(STDOUT_FILENO)) + assert_se(streq(formatted, + " no a long f… no a long f… a long fi…\n" + " no fäää no fäää fäää \n" + " yes fäää yes fäää fäää \n" + " yes xxx yes xxx xxx \n" + "5min 5min \n")); + else + assert_se(streq(formatted, + " no a long field no a long field a long field\n" + " no fäää no fäää fäää \n" + " yes fäää yes fäää fäää \n" + " yes xxx yes xxx xxx \n" + "5min 5min \n")); + + test_issue_9549(); + + return 0; +} diff --git a/src/test/test-format-util.c b/src/test/test-format-util.c new file mode 100644 index 00000000..6558ee2b --- /dev/null +++ b/src/test/test-format-util.c @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "format-util.h" +#include "macro.h" +#include "string-util.h" + +static void test_format_bytes_one(uint64_t val, bool trailing_B, const char *iec_with_p, const char *iec_without_p, + const char *si_with_p, const char *si_without_p) { + char buf[FORMAT_BYTES_MAX]; + + assert_se(streq_ptr(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_USE_IEC | FORMAT_BYTES_BELOW_POINT | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), iec_with_p)); + assert_se(streq_ptr(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_USE_IEC | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), iec_without_p)); + assert_se(streq_ptr(format_bytes_full(buf, sizeof buf, val, FORMAT_BYTES_BELOW_POINT | (trailing_B ? FORMAT_BYTES_TRAILING_B : 0)), si_with_p)); + assert_se(streq_ptr(format_bytes_full(buf, sizeof buf, val, trailing_B ? FORMAT_BYTES_TRAILING_B : 0), si_without_p)); +} + +static void test_format_bytes(void) { + test_format_bytes_one(900, true, "900B", "900B", "900B", "900B"); + test_format_bytes_one(900, false, "900", "900", "900", "900"); + test_format_bytes_one(1023, true, "1023B", "1023B", "1.0K", "1K"); + test_format_bytes_one(1023, false, "1023", "1023", "1.0K", "1K"); + test_format_bytes_one(1024, true, "1.0K", "1K", "1.0K", "1K"); + test_format_bytes_one(1024, false, "1.0K", "1K", "1.0K", "1K"); + test_format_bytes_one(1100, true, "1.0K", "1K", "1.1K", "1K"); + test_format_bytes_one(1500, true, "1.4K", "1K", "1.5K", "1K"); + test_format_bytes_one(UINT64_C(3)*1024*1024, true, "3.0M", "3M", "3.1M", "3M"); + test_format_bytes_one(UINT64_C(3)*1024*1024*1024, true, "3.0G", "3G", "3.2G", "3G"); + test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024, true, "3.0T", "3T", "3.2T", "3T"); + test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024*1024, true, "3.0P", "3P", "3.3P", "3P"); + test_format_bytes_one(UINT64_C(3)*1024*1024*1024*1024*1024*1024, true, "3.0E", "3E", "3.4E", "3E"); + test_format_bytes_one(UINT64_MAX, true, NULL, NULL, NULL, NULL); + test_format_bytes_one(UINT64_MAX, false, NULL, NULL, NULL, NULL); +} + +int main(void) { + test_format_bytes(); + + return 0; +} diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c new file mode 100644 index 00000000..ac8b95ae --- /dev/null +++ b/src/test/test-fs-util.c @@ -0,0 +1,814 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "id128-util.h" +#include "macro.h" +#include "mkdir.h" +#include "path-util.h" +#include "rm-rf.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "tmpfile-util.h" +#include "umask-util.h" +#include "user-util.h" +#include "util.h" +#include "virt.h" + +static const char *arg_test_dir = NULL; + +static void test_chase_symlinks(void) { + _cleanup_free_ char *result = NULL; + char *temp; + const char *top, *p, *pslash, *q, *qslash; + struct stat st; + int r, pfd; + + log_info("/* %s */", __func__); + + temp = strjoina(arg_test_dir ?: "/tmp", "/test-chase.XXXXXX"); + assert_se(mkdtemp(temp)); + + top = strjoina(temp, "/top"); + assert_se(mkdir(top, 0700) >= 0); + + p = strjoina(top, "/dot"); + if (symlink(".", p) < 0) { + assert_se(IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM)); + log_tests_skipped_errno(errno, "symlink() not possible"); + goto cleanup; + }; + + p = strjoina(top, "/dotdot"); + assert_se(symlink("..", p) >= 0); + + p = strjoina(top, "/dotdota"); + assert_se(symlink("../a", p) >= 0); + + p = strjoina(temp, "/a"); + assert_se(symlink("b", p) >= 0); + + p = strjoina(temp, "/b"); + assert_se(symlink("/usr", p) >= 0); + + p = strjoina(temp, "/start"); + assert_se(symlink("top/dot/dotdota", p) >= 0); + + /* Paths that use symlinks underneath the "root" */ + + r = chase_symlinks(p, NULL, 0, &result, NULL); + assert_se(r > 0); + assert_se(path_equal(result, "/usr")); + result = mfree(result); + + pslash = strjoina(p, "/"); + r = chase_symlinks(pslash, NULL, 0, &result, NULL); + assert_se(r > 0); + assert_se(path_equal(result, "/usr/")); + result = mfree(result); + + r = chase_symlinks(p, temp, 0, &result, NULL); + assert_se(r == -ENOENT); + + r = chase_symlinks(pslash, temp, 0, &result, NULL); + assert_se(r == -ENOENT); + + q = strjoina(temp, "/usr"); + + r = chase_symlinks(p, temp, CHASE_NONEXISTENT, &result, NULL); + assert_se(r == 0); + assert_se(path_equal(result, q)); + result = mfree(result); + + qslash = strjoina(q, "/"); + + r = chase_symlinks(pslash, temp, CHASE_NONEXISTENT, &result, NULL); + assert_se(r == 0); + assert_se(path_equal(result, qslash)); + result = mfree(result); + + assert_se(mkdir(q, 0700) >= 0); + + r = chase_symlinks(p, temp, 0, &result, NULL); + assert_se(r > 0); + assert_se(path_equal(result, q)); + result = mfree(result); + + r = chase_symlinks(pslash, temp, 0, &result, NULL); + assert_se(r > 0); + assert_se(path_equal(result, qslash)); + result = mfree(result); + + p = strjoina(temp, "/slash"); + assert_se(symlink("/", p) >= 0); + + r = chase_symlinks(p, NULL, 0, &result, NULL); + assert_se(r > 0); + assert_se(path_equal(result, "/")); + result = mfree(result); + + r = chase_symlinks(p, temp, 0, &result, NULL); + assert_se(r > 0); + assert_se(path_equal(result, temp)); + result = mfree(result); + + /* Paths that would "escape" outside of the "root" */ + + p = strjoina(temp, "/6dots"); + assert_se(symlink("../../..", p) >= 0); + + r = chase_symlinks(p, temp, 0, &result, NULL); + assert_se(r > 0 && path_equal(result, temp)); + result = mfree(result); + + p = strjoina(temp, "/6dotsusr"); + assert_se(symlink("../../../usr", p) >= 0); + + r = chase_symlinks(p, temp, 0, &result, NULL); + assert_se(r > 0 && path_equal(result, q)); + result = mfree(result); + + p = strjoina(temp, "/top/8dotsusr"); + assert_se(symlink("../../../../usr", p) >= 0); + + r = chase_symlinks(p, temp, 0, &result, NULL); + assert_se(r > 0 && path_equal(result, q)); + result = mfree(result); + + /* Paths that contain repeated slashes */ + + p = strjoina(temp, "/slashslash"); + assert_se(symlink("///usr///", p) >= 0); + + r = chase_symlinks(p, NULL, 0, &result, NULL); + assert_se(r > 0); + assert_se(path_equal(result, "/usr")); + result = mfree(result); + + r = chase_symlinks(p, temp, 0, &result, NULL); + assert_se(r > 0); + assert_se(path_equal(result, q)); + result = mfree(result); + + /* Paths underneath the "root" with different UIDs while using CHASE_SAFE */ + + if (geteuid() == 0) { + p = strjoina(temp, "/user"); + assert_se(mkdir(p, 0755) >= 0); + assert_se(chown(p, UID_NOBODY, GID_NOBODY) >= 0); + + q = strjoina(temp, "/user/root"); + assert_se(mkdir(q, 0755) >= 0); + + p = strjoina(q, "/link"); + assert_se(symlink("/", p) >= 0); + + /* Fail when user-owned directories contain root-owned subdirectories. */ + r = chase_symlinks(p, temp, CHASE_SAFE, &result, NULL); + assert_se(r == -ENOLINK); + result = mfree(result); + + /* Allow this when the user-owned directories are all in the "root". */ + r = chase_symlinks(p, q, CHASE_SAFE, &result, NULL); + assert_se(r > 0); + result = mfree(result); + } + + /* Paths using . */ + + r = chase_symlinks("/etc/./.././", NULL, 0, &result, NULL); + assert_se(r > 0); + assert_se(path_equal(result, "/")); + result = mfree(result); + + r = chase_symlinks("/etc/./.././", "/etc", 0, &result, NULL); + assert_se(r > 0 && path_equal(result, "/etc")); + result = mfree(result); + + r = chase_symlinks("/../.././//../../etc", NULL, 0, &result, NULL); + assert_se(r > 0); + assert_se(streq(result, "/etc")); + result = mfree(result); + + r = chase_symlinks("/../.././//../../test-chase.fsldajfl", NULL, CHASE_NONEXISTENT, &result, NULL); + assert_se(r == 0); + assert_se(streq(result, "/test-chase.fsldajfl")); + result = mfree(result); + + r = chase_symlinks("/../.././//../../etc", "/", CHASE_PREFIX_ROOT, &result, NULL); + assert_se(r > 0); + assert_se(streq(result, "/etc")); + result = mfree(result); + + r = chase_symlinks("/../.././//../../test-chase.fsldajfl", "/", CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &result, NULL); + assert_se(r == 0); + assert_se(streq(result, "/test-chase.fsldajfl")); + result = mfree(result); + + r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result, NULL); + assert_se(r == -ENOTDIR); + result = mfree(result); + + /* Path that loops back to self */ + + p = strjoina(temp, "/recursive-symlink"); + assert_se(symlink("recursive-symlink", p) >= 0); + r = chase_symlinks(p, NULL, 0, &result, NULL); + assert_se(r == -ELOOP); + + /* Path which doesn't exist */ + + p = strjoina(temp, "/idontexist"); + r = chase_symlinks(p, NULL, 0, &result, NULL); + assert_se(r == -ENOENT); + + r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL); + assert_se(r == 0); + assert_se(path_equal(result, p)); + result = mfree(result); + + p = strjoina(temp, "/idontexist/meneither"); + r = chase_symlinks(p, NULL, 0, &result, NULL); + assert_se(r == -ENOENT); + + r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL); + assert_se(r == 0); + assert_se(path_equal(result, p)); + result = mfree(result); + + /* Path which doesn't exist, but contains weird stuff */ + + p = strjoina(temp, "/idontexist/.."); + r = chase_symlinks(p, NULL, 0, &result, NULL); + assert_se(r == -ENOENT); + + r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result, NULL); + assert_se(r == -ENOENT); + + p = strjoina(temp, "/target"); + q = strjoina(temp, "/top"); + assert_se(symlink(q, p) >= 0); + p = strjoina(temp, "/target/idontexist"); + r = chase_symlinks(p, NULL, 0, &result, NULL); + assert_se(r == -ENOENT); + + if (geteuid() == 0) { + p = strjoina(temp, "/priv1"); + assert_se(mkdir(p, 0755) >= 0); + + q = strjoina(p, "/priv2"); + assert_se(mkdir(q, 0755) >= 0); + + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); + + assert_se(chown(q, UID_NOBODY, GID_NOBODY) >= 0); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); + + assert_se(chown(p, UID_NOBODY, GID_NOBODY) >= 0); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); + + assert_se(chown(q, 0, 0) >= 0); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) == -ENOLINK); + + assert_se(rmdir(q) >= 0); + assert_se(symlink("/etc/passwd", q) >= 0); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) == -ENOLINK); + + assert_se(chown(p, 0, 0) >= 0); + assert_se(chase_symlinks(q, NULL, CHASE_SAFE, NULL, NULL) >= 0); + } + + p = strjoina(temp, "/machine-id-test"); + assert_se(symlink("/usr/../etc/./machine-id", p) >= 0); + + r = chase_symlinks(p, NULL, 0, NULL, &pfd); + if (r != -ENOENT) { + _cleanup_close_ int fd = -1; + sd_id128_t a, b; + + assert_se(pfd >= 0); + + fd = fd_reopen(pfd, O_RDONLY|O_CLOEXEC); + assert_se(fd >= 0); + safe_close(pfd); + + assert_se(id128_read_fd(fd, ID128_PLAIN, &a) >= 0); + assert_se(sd_id128_get_machine(&b) >= 0); + assert_se(sd_id128_equal(a, b)); + } + + /* Test CHASE_NOFOLLOW */ + + p = strjoina(temp, "/target"); + q = strjoina(temp, "/symlink"); + assert_se(symlink(p, q) >= 0); + r = chase_symlinks(q, NULL, CHASE_NOFOLLOW, &result, &pfd); + assert_se(r >= 0); + assert_se(pfd >= 0); + assert_se(path_equal(result, q)); + assert_se(fstat(pfd, &st) >= 0); + assert_se(S_ISLNK(st.st_mode)); + result = mfree(result); + + /* s1 -> s2 -> nonexistent */ + q = strjoina(temp, "/s1"); + assert_se(symlink("s2", q) >= 0); + p = strjoina(temp, "/s2"); + assert_se(symlink("nonexistent", p) >= 0); + r = chase_symlinks(q, NULL, CHASE_NOFOLLOW, &result, &pfd); + assert_se(r >= 0); + assert_se(pfd >= 0); + assert_se(path_equal(result, q)); + assert_se(fstat(pfd, &st) >= 0); + assert_se(S_ISLNK(st.st_mode)); + result = mfree(result); + + /* Test CHASE_ONE */ + + p = strjoina(temp, "/start"); + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); + assert_se(r == 0); + p = strjoina(temp, "/top/dot/dotdota"); + assert_se(streq(p, result)); + result = mfree(result); + + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); + assert_se(r == 0); + p = strjoina(temp, "/top/./dotdota"); + assert_se(streq(p, result)); + result = mfree(result); + + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); + assert_se(r == 0); + p = strjoina(temp, "/top/../a"); + assert_se(streq(p, result)); + result = mfree(result); + + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); + assert_se(r == 0); + p = strjoina(temp, "/a"); + assert_se(streq(p, result)); + result = mfree(result); + + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); + assert_se(r == 0); + p = strjoina(temp, "/b"); + assert_se(streq(p, result)); + result = mfree(result); + + r = chase_symlinks(p, NULL, CHASE_STEP, &result, NULL); + assert_se(r == 0); + assert_se(streq("/usr", result)); + result = mfree(result); + + r = chase_symlinks("/usr", NULL, CHASE_STEP, &result, NULL); + assert_se(r > 0); + assert_se(streq("/usr", result)); + result = mfree(result); + + cleanup: + assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); +} + +static void test_unlink_noerrno(void) { + char *name; + int fd; + + log_info("/* %s */", __func__); + + name = strjoina(arg_test_dir ?: "/tmp", "/test-close_nointr.XXXXXX"); + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(close_nointr(fd) >= 0); + + { + PROTECT_ERRNO; + errno = 42; + assert_se(unlink_noerrno(name) >= 0); + assert_se(errno == 42); + assert_se(unlink_noerrno(name) < 0); + assert_se(errno == 42); + } +} + +static void test_readlink_and_make_absolute(void) { + const char *tempdir, *name, *name2, *name_alias; + _cleanup_free_ char *r1 = NULL, *r2 = NULL, *pwd = NULL; + + log_info("/* %s */", __func__); + + tempdir = strjoina(arg_test_dir ?: "/tmp", "/test-readlink_and_make_absolute"); + name = strjoina(tempdir, "/original"); + name2 = "test-readlink_and_make_absolute/original"; + name_alias = strjoina(arg_test_dir ?: "/tmp", "/test-readlink_and_make_absolute-alias"); + + assert_se(mkdir_safe(tempdir, 0755, getuid(), getgid(), MKDIR_WARN_MODE) >= 0); + assert_se(touch(name) >= 0); + + if (symlink(name, name_alias) < 0) { + assert_se(IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM)); + log_tests_skipped_errno(errno, "symlink() not possible"); + } else { + assert_se(readlink_and_make_absolute(name_alias, &r1) >= 0); + assert_se(streq(r1, name)); + assert_se(unlink(name_alias) >= 0); + + assert_se(safe_getcwd(&pwd) >= 0); + + assert_se(chdir(tempdir) >= 0); + assert_se(symlink(name2, name_alias) >= 0); + assert_se(readlink_and_make_absolute(name_alias, &r2) >= 0); + assert_se(streq(r2, name)); + assert_se(unlink(name_alias) >= 0); + + assert_se(chdir(pwd) >= 0); + } + + assert_se(rm_rf(tempdir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); +} + +static void test_get_files_in_directory(void) { + _cleanup_strv_free_ char **l = NULL, **t = NULL; + + assert_se(get_files_in_directory(arg_test_dir ?: "/tmp", &l) >= 0); + assert_se(get_files_in_directory(".", &t) >= 0); + assert_se(get_files_in_directory(".", NULL) >= 0); +} + +static void test_var_tmp(void) { + _cleanup_free_ char *tmpdir_backup = NULL, *temp_backup = NULL, *tmp_backup = NULL; + const char *tmp_dir = NULL, *t; + + log_info("/* %s */", __func__); + + t = getenv("TMPDIR"); + if (t) { + tmpdir_backup = strdup(t); + assert_se(tmpdir_backup); + } + + t = getenv("TEMP"); + if (t) { + temp_backup = strdup(t); + assert_se(temp_backup); + } + + t = getenv("TMP"); + if (t) { + tmp_backup = strdup(t); + assert_se(tmp_backup); + } + + assert_se(unsetenv("TMPDIR") >= 0); + assert_se(unsetenv("TEMP") >= 0); + assert_se(unsetenv("TMP") >= 0); + + assert_se(var_tmp_dir(&tmp_dir) >= 0); + assert_se(streq(tmp_dir, "/var/tmp")); + + assert_se(setenv("TMPDIR", "/tmp", true) >= 0); + assert_se(streq(getenv("TMPDIR"), "/tmp")); + + assert_se(var_tmp_dir(&tmp_dir) >= 0); + assert_se(streq(tmp_dir, "/tmp")); + + assert_se(setenv("TMPDIR", "/88_does_not_exist_88", true) >= 0); + assert_se(streq(getenv("TMPDIR"), "/88_does_not_exist_88")); + + assert_se(var_tmp_dir(&tmp_dir) >= 0); + assert_se(streq(tmp_dir, "/var/tmp")); + + if (tmpdir_backup) { + assert_se(setenv("TMPDIR", tmpdir_backup, true) >= 0); + assert_se(streq(getenv("TMPDIR"), tmpdir_backup)); + } + + if (temp_backup) { + assert_se(setenv("TEMP", temp_backup, true) >= 0); + assert_se(streq(getenv("TEMP"), temp_backup)); + } + + if (tmp_backup) { + assert_se(setenv("TMP", tmp_backup, true) >= 0); + assert_se(streq(getenv("TMP"), tmp_backup)); + } +} + +static void test_dot_or_dot_dot(void) { + log_info("/* %s */", __func__); + + assert_se(!dot_or_dot_dot(NULL)); + assert_se(!dot_or_dot_dot("")); + assert_se(!dot_or_dot_dot("xxx")); + assert_se(dot_or_dot_dot(".")); + assert_se(dot_or_dot_dot("..")); + assert_se(!dot_or_dot_dot(".foo")); + assert_se(!dot_or_dot_dot("..foo")); +} + +static void test_access_fd(void) { + _cleanup_(rmdir_and_freep) char *p = NULL; + _cleanup_close_ int fd = -1; + const char *a; + + log_info("/* %s */", __func__); + + a = strjoina(arg_test_dir ?: "/tmp", "/access-fd.XXXXXX"); + assert_se(mkdtemp_malloc(a, &p) >= 0); + + fd = open(p, O_RDONLY|O_DIRECTORY|O_CLOEXEC); + assert_se(fd >= 0); + + assert_se(access_fd(fd, R_OK) >= 0); + assert_se(access_fd(fd, F_OK) >= 0); + assert_se(access_fd(fd, W_OK) >= 0); + + assert_se(fchmod(fd, 0000) >= 0); + + assert_se(access_fd(fd, F_OK) >= 0); + + if (geteuid() == 0) { + assert_se(access_fd(fd, R_OK) >= 0); + assert_se(access_fd(fd, W_OK) >= 0); + } else { + assert_se(access_fd(fd, R_OK) == -EACCES); + assert_se(access_fd(fd, W_OK) == -EACCES); + } +} + +static void test_touch_file(void) { + uid_t test_uid, test_gid; + _cleanup_(rm_rf_physical_and_freep) char *p = NULL; + struct stat st; + const char *a; + usec_t test_mtime; + int r; + + log_info("/* %s */", __func__); + + test_uid = geteuid() == 0 ? 65534 : getuid(); + test_gid = geteuid() == 0 ? 65534 : getgid(); + + test_mtime = usec_sub_unsigned(now(CLOCK_REALTIME), USEC_PER_WEEK); + + a = strjoina(arg_test_dir ?: "/dev/shm", "/touch-file-XXXXXX"); + assert_se(mkdtemp_malloc(a, &p) >= 0); + + a = strjoina(p, "/regular"); + r = touch_file(a, false, test_mtime, test_uid, test_gid, 0640); + if (r < 0) { + assert_se(IN_SET(r, -EINVAL, -ENOSYS, -ENOTTY, -EPERM)); + log_tests_skipped_errno(errno, "touch_file() not possible"); + return; + } + + assert_se(lstat(a, &st) >= 0); + assert_se(st.st_uid == test_uid); + assert_se(st.st_gid == test_gid); + assert_se(S_ISREG(st.st_mode)); + assert_se((st.st_mode & 0777) == 0640); + assert_se(timespec_load(&st.st_mtim) == test_mtime); + + a = strjoina(p, "/dir"); + assert_se(mkdir(a, 0775) >= 0); + assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0); + assert_se(lstat(a, &st) >= 0); + assert_se(st.st_uid == test_uid); + assert_se(st.st_gid == test_gid); + assert_se(S_ISDIR(st.st_mode)); + assert_se((st.st_mode & 0777) == 0640); + assert_se(timespec_load(&st.st_mtim) == test_mtime); + + a = strjoina(p, "/fifo"); + assert_se(mkfifo(a, 0775) >= 0); + assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0); + assert_se(lstat(a, &st) >= 0); + assert_se(st.st_uid == test_uid); + assert_se(st.st_gid == test_gid); + assert_se(S_ISFIFO(st.st_mode)); + assert_se((st.st_mode & 0777) == 0640); + assert_se(timespec_load(&st.st_mtim) == test_mtime); + + a = strjoina(p, "/sock"); + assert_se(mknod(a, 0775 | S_IFSOCK, 0) >= 0); + assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0); + assert_se(lstat(a, &st) >= 0); + assert_se(st.st_uid == test_uid); + assert_se(st.st_gid == test_gid); + assert_se(S_ISSOCK(st.st_mode)); + assert_se((st.st_mode & 0777) == 0640); + assert_se(timespec_load(&st.st_mtim) == test_mtime); + + if (geteuid() == 0) { + a = strjoina(p, "/cdev"); + r = mknod(a, 0775 | S_IFCHR, makedev(0, 0)); + if (r < 0 && errno == EPERM && detect_container() > 0) { + log_notice("Running in unprivileged container? Skipping remaining tests in %s", __func__); + return; + } + assert_se(r >= 0); + assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0); + assert_se(lstat(a, &st) >= 0); + assert_se(st.st_uid == test_uid); + assert_se(st.st_gid == test_gid); + assert_se(S_ISCHR(st.st_mode)); + assert_se((st.st_mode & 0777) == 0640); + assert_se(timespec_load(&st.st_mtim) == test_mtime); + + a = strjoina(p, "/bdev"); + assert_se(mknod(a, 0775 | S_IFBLK, makedev(0, 0)) >= 0); + assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0); + assert_se(lstat(a, &st) >= 0); + assert_se(st.st_uid == test_uid); + assert_se(st.st_gid == test_gid); + assert_se(S_ISBLK(st.st_mode)); + assert_se((st.st_mode & 0777) == 0640); + assert_se(timespec_load(&st.st_mtim) == test_mtime); + } + + a = strjoina(p, "/lnk"); + assert_se(symlink("target", a) >= 0); + assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0); + assert_se(lstat(a, &st) >= 0); + assert_se(st.st_uid == test_uid); + assert_se(st.st_gid == test_gid); + assert_se(S_ISLNK(st.st_mode)); + assert_se(timespec_load(&st.st_mtim) == test_mtime); +} + +static void test_unlinkat_deallocate(void) { + _cleanup_free_ char *p = NULL; + _cleanup_close_ int fd = -1; + struct stat st; + + log_info("/* %s */", __func__); + + assert_se(tempfn_random_child(arg_test_dir, "unlink-deallocation", &p) >= 0); + + fd = open(p, O_WRONLY|O_CLOEXEC|O_CREAT|O_EXCL, 0600); + assert_se(fd >= 0); + + assert_se(write(fd, "hallo\n", 6) == 6); + + assert_se(fstat(fd, &st) >= 0); + assert_se(st.st_size == 6); + assert_se(st.st_blocks > 0); + assert_se(st.st_nlink == 1); + + assert_se(unlinkat_deallocate(AT_FDCWD, p, 0) >= 0); + + assert_se(fstat(fd, &st) >= 0); + assert_se(IN_SET(st.st_size, 0, 6)); /* depending on whether hole punching worked the size will be 6 + (it worked) or 0 (we had to resort to truncation) */ + assert_se(st.st_blocks == 0); + assert_se(st.st_nlink == 0); +} + +static void test_fsync_directory_of_file(void) { + _cleanup_close_ int fd = -1; + + log_info("/* %s */", __func__); + + fd = open_tmpfile_unlinkable(arg_test_dir, O_RDWR); + assert_se(fd >= 0); + + assert_se(fsync_directory_of_file(fd) >= 0); +} + +static void test_rename_noreplace(void) { + static const char* const table[] = { + "/reg", + "/dir", + "/fifo", + "/socket", + "/symlink", + NULL + }; + + _cleanup_(rm_rf_physical_and_freep) char *z = NULL; + const char *j = NULL; + char **a, **b; + + log_info("/* %s */", __func__); + + if (arg_test_dir) + j = strjoina(arg_test_dir, "/testXXXXXX"); + assert_se(mkdtemp_malloc(j, &z) >= 0); + + j = strjoina(z, table[0]); + assert_se(touch(j) >= 0); + + j = strjoina(z, table[1]); + assert_se(mkdir(j, 0777) >= 0); + + j = strjoina(z, table[2]); + (void) mkfifo(j, 0777); + + j = strjoina(z, table[3]); + (void) mknod(j, S_IFSOCK | 0777, 0); + + j = strjoina(z, table[4]); + (void) symlink("foobar", j); + + STRV_FOREACH(a, (char**) table) { + _cleanup_free_ char *x = NULL, *y = NULL; + + x = strjoin(z, *a); + assert_se(x); + + if (access(x, F_OK) < 0) { + assert_se(errno == ENOENT); + continue; + } + + STRV_FOREACH(b, (char**) table) { + _cleanup_free_ char *w = NULL; + + w = strjoin(w, *b); + assert_se(w); + + if (access(w, F_OK) < 0) { + assert_se(errno == ENOENT); + continue; + } + + assert_se(rename_noreplace(AT_FDCWD, w, AT_FDCWD, y) == -EEXIST); + } + + y = strjoin(z, "/somethingelse"); + assert_se(y); + + assert_se(rename_noreplace(AT_FDCWD, x, AT_FDCWD, y) >= 0); + assert_se(rename_noreplace(AT_FDCWD, y, AT_FDCWD, x) >= 0); + } +} + +static void test_chmod_and_chown(void) { + _cleanup_(rm_rf_physical_and_freep) char *d = NULL; + _unused_ _cleanup_umask_ mode_t u = umask(0000); + struct stat st; + const char *p; + + if (geteuid() != 0) + return; + + log_info("/* %s */", __func__); + + assert_se(mkdtemp_malloc(NULL, &d) >= 0); + + p = strjoina(d, "/reg"); + assert_se(mknod(p, S_IFREG | 0123, 0) >= 0); + + assert_se(chmod_and_chown(p, S_IFREG | 0321, 1, 2) >= 0); + assert_se(chmod_and_chown(p, S_IFDIR | 0555, 3, 4) == -EINVAL); + + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISREG(st.st_mode)); + assert_se((st.st_mode & 07777) == 0321); + + p = strjoina(d, "/dir"); + assert_se(mkdir(p, 0123) >= 0); + + assert_se(chmod_and_chown(p, S_IFDIR | 0321, 1, 2) >= 0); + assert_se(chmod_and_chown(p, S_IFREG | 0555, 3, 4) == -EINVAL); + + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISDIR(st.st_mode)); + assert_se((st.st_mode & 07777) == 0321); + + p = strjoina(d, "/lnk"); + assert_se(symlink("idontexist", p) >= 0); + + assert_se(chmod_and_chown(p, S_IFLNK | 0321, 1, 2) >= 0); + assert_se(chmod_and_chown(p, S_IFREG | 0555, 3, 4) == -EINVAL); + assert_se(chmod_and_chown(p, S_IFDIR | 0555, 3, 4) == -EINVAL); + + assert_se(lstat(p, &st) >= 0); + assert_se(S_ISLNK(st.st_mode)); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + arg_test_dir = argv[1]; + + test_chase_symlinks(); + test_unlink_noerrno(); + test_readlink_and_make_absolute(); + test_get_files_in_directory(); + test_var_tmp(); + test_dot_or_dot_dot(); + test_access_fd(); + test_touch_file(); + test_unlinkat_deallocate(); + test_fsync_directory_of_file(); + test_rename_noreplace(); + test_chmod_and_chown(); + + return 0; +} diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c new file mode 100644 index 00000000..c1c7ec91 --- /dev/null +++ b/src/test/test-fstab-util.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "fstab-util.h" +#include "log.h" +#include "string-util.h" + +/* +int fstab_filter_options(const char *opts, const char *names, + const char **namefound, char **value, char **filtered); +*/ + +static void do_fstab_filter_options(const char *opts, + const char *remove, + int r_expected, + const char *name_expected, + const char *value_expected, + const char *filtered_expected) { + + int r; + const char *name; + _cleanup_free_ char *value, *filtered; + + r = fstab_filter_options(opts, remove, &name, &value, &filtered); + log_info("\"%s\" → %d, \"%s\", \"%s\", \"%s\", expected %d, \"%s\", \"%s\", \"%s\"", + opts, r, name, value, filtered, + r_expected, name_expected, value_expected, filtered_expected ?: opts); + assert_se(r == r_expected); + assert_se(streq_ptr(name, name_expected)); + assert_se(streq_ptr(value, value_expected)); + assert_se(streq_ptr(filtered, filtered_expected ?: opts)); + + /* also test the malloc-less mode */ + r = fstab_filter_options(opts, remove, &name, NULL, NULL); + log_info("\"%s\" → %d, \"%s\", expected %d, \"%s\"", + opts, r, name, + r_expected, name_expected); + assert_se(r == r_expected); + assert_se(streq_ptr(name, name_expected)); +} + +static void test_fstab_filter_options(void) { + do_fstab_filter_options("opt=0", "opt\0x-opt\0", 1, "opt", "0", ""); + do_fstab_filter_options("opt=0", "x-opt\0opt\0", 1, "opt", "0", ""); + do_fstab_filter_options("opt", "opt\0x-opt\0", 1, "opt", NULL, ""); + do_fstab_filter_options("opt", "x-opt\0opt\0", 1, "opt", NULL, ""); + do_fstab_filter_options("x-opt", "x-opt\0opt\0", 1, "x-opt", NULL, ""); + + do_fstab_filter_options("opt=0,other", "opt\0x-opt\0", 1, "opt", "0", "other"); + do_fstab_filter_options("opt=0,other", "x-opt\0opt\0", 1, "opt", "0", "other"); + do_fstab_filter_options("opt,other", "opt\0x-opt\0", 1, "opt", NULL, "other"); + do_fstab_filter_options("opt,other", "x-opt\0opt\0", 1, "opt", NULL, "other"); + do_fstab_filter_options("x-opt,other", "opt\0x-opt\0", 1, "x-opt", NULL, "other"); + + do_fstab_filter_options("opto=0,other", "opt\0x-opt\0", 0, NULL, NULL, NULL); + do_fstab_filter_options("opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL); + do_fstab_filter_options("x-opto,other", "opt\0x-opt\0", 0, NULL, NULL, NULL); + + do_fstab_filter_options("first,opt=0", "opt\0x-opt\0", 1, "opt", "0", "first"); + do_fstab_filter_options("first=1,opt=0", "opt\0x-opt\0", 1, "opt", "0", "first=1"); + do_fstab_filter_options("first,opt=", "opt\0x-opt\0", 1, "opt", "", "first"); + do_fstab_filter_options("first=1,opt", "opt\0x-opt\0", 1, "opt", NULL, "first=1"); + do_fstab_filter_options("first=1,x-opt", "opt\0x-opt\0", 1, "x-opt", NULL, "first=1"); + + do_fstab_filter_options("first,opt=0,last=1", "opt\0x-opt\0", 1, "opt", "0", "first,last=1"); + do_fstab_filter_options("first=1,opt=0,last=2", "x-opt\0opt\0", 1, "opt", "0", "first=1,last=2"); + do_fstab_filter_options("first,opt,last", "opt\0", 1, "opt", NULL, "first,last"); + do_fstab_filter_options("first=1,opt,last", "x-opt\0opt\0", 1, "opt", NULL, "first=1,last"); + do_fstab_filter_options("first=,opt,last", "opt\0noopt\0", 1, "opt", NULL, "first=,last"); + + /* check repeated options */ + do_fstab_filter_options("first,opt=0,noopt=1,last=1", "opt\0noopt\0", 1, "noopt", "1", "first,last=1"); + do_fstab_filter_options("first=1,opt=0,last=2,opt=1", "opt\0", 1, "opt", "1", "first=1,last=2"); + do_fstab_filter_options("x-opt=0,x-opt=1", "opt\0x-opt\0", 1, "x-opt", "1", ""); + do_fstab_filter_options("opt=0,x-opt=1", "opt\0x-opt\0", 1, "x-opt", "1", ""); + + /* check that semicolons are not misinterpreted */ + do_fstab_filter_options("opt=0;", "opt\0", 1, "opt", "0;", ""); + do_fstab_filter_options("opt;=0", "x-opt\0opt\0noopt\0x-noopt\0", 0, NULL, NULL, NULL); + do_fstab_filter_options("opt;", "opt\0x-opt\0", 0, NULL, NULL, NULL); + + /* check that spaces are not misinterpreted */ + do_fstab_filter_options("opt=0 ", "opt\0", 1, "opt", "0 ", ""); + do_fstab_filter_options("opt =0", "x-opt\0opt\0noopt\0x-noopt\0", 0, NULL, NULL, NULL); + do_fstab_filter_options(" opt ", "opt\0x-opt\0", 0, NULL, NULL, NULL); + + /* check function will NULL args */ + do_fstab_filter_options(NULL, "opt\0", 0, NULL, NULL, ""); + do_fstab_filter_options("", "opt\0", 0, NULL, NULL, ""); +} + +static void test_fstab_find_pri(void) { + int pri = -1; + + assert_se(fstab_find_pri("pri", &pri) == 0); + assert_se(pri == -1); + + assert_se(fstab_find_pri("pri=11", &pri) == 1); + assert_se(pri == 11); + + assert_se(fstab_find_pri("pri=-2", &pri) == 1); + assert_se(pri == -2); + + assert_se(fstab_find_pri("opt,pri=12,opt", &pri) == 1); + assert_se(pri == 12); + + assert_se(fstab_find_pri("opt,opt,pri=12,pri=13", &pri) == 1); + assert_se(pri == 13); +} + +static void test_fstab_yes_no_option(void) { + assert_se(fstab_test_yes_no_option("nofail,fail,nofail", "nofail\0fail\0") == true); + assert_se(fstab_test_yes_no_option("nofail,nofail,fail", "nofail\0fail\0") == false); + assert_se(fstab_test_yes_no_option("abc,cde,afail", "nofail\0fail\0") == false); + assert_se(fstab_test_yes_no_option("nofail,fail=0,nofail=0", "nofail\0fail\0") == true); + assert_se(fstab_test_yes_no_option("nofail,nofail=0,fail=0", "nofail\0fail\0") == false); +} + +static void test_fstab_node_to_udev_node(void) { + char *n; + + n = fstab_node_to_udev_node("LABEL=applé/jack"); + puts(n); + assert_se(streq(n, "/dev/disk/by-label/applé\\x2fjack")); + free(n); + + n = fstab_node_to_udev_node("PARTLABEL=pinkié pie"); + puts(n); + assert_se(streq(n, "/dev/disk/by-partlabel/pinkié\\x20pie")); + free(n); + + n = fstab_node_to_udev_node("UUID=037b9d94-148e-4ee4-8d38-67bfe15bb535"); + puts(n); + assert_se(streq(n, "/dev/disk/by-uuid/037b9d94-148e-4ee4-8d38-67bfe15bb535")); + free(n); + + n = fstab_node_to_udev_node("PARTUUID=037b9d94-148e-4ee4-8d38-67bfe15bb535"); + puts(n); + assert_se(streq(n, "/dev/disk/by-partuuid/037b9d94-148e-4ee4-8d38-67bfe15bb535")); + free(n); + + n = fstab_node_to_udev_node("PONIES=awesome"); + puts(n); + assert_se(streq(n, "PONIES=awesome")); + free(n); + + n = fstab_node_to_udev_node("/dev/xda1"); + puts(n); + assert_se(streq(n, "/dev/xda1")); + free(n); +} + +int main(void) { + test_fstab_filter_options(); + test_fstab_find_pri(); + test_fstab_yes_no_option(); + test_fstab_node_to_udev_node(); + + return 0; +} diff --git a/src/test/test-gcrypt-util.c b/src/test/test-gcrypt-util.c new file mode 100644 index 00000000..b28b4eb5 --- /dev/null +++ b/src/test/test-gcrypt-util.c @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "gcrypt-util.h" +#include "macro.h" +#include "string-util.h" + +static void test_string_hashsum(void) { + _cleanup_free_ char *out1 = NULL, *out2 = NULL, *out3 = NULL, *out4 = NULL; + + assert_se(string_hashsum("asdf", 4, GCRY_MD_SHA224, &out1) == 0); + /* echo -n 'asdf' | sha224sum - */ + assert_se(streq(out1, "7872a74bcbf298a1e77d507cd95d4f8d96131cbbd4cdfc571e776c8a")); + + assert_se(string_hashsum("asdf", 4, GCRY_MD_SHA256, &out2) == 0); + /* echo -n 'asdf' | sha256sum - */ + assert_se(streq(out2, "f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b")); + + assert_se(string_hashsum("", 0, GCRY_MD_SHA224, &out3) == 0); + /* echo -n '' | sha224sum - */ + assert_se(streq(out3, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f")); + + assert_se(string_hashsum("", 0, GCRY_MD_SHA256, &out4) == 0); + /* echo -n '' | sha256sum - */ + assert_se(streq(out4, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")); +} + +int main(int argc, char **argv) { + test_string_hashsum(); + + return 0; +} diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c new file mode 100644 index 00000000..667d1533 --- /dev/null +++ b/src/test/test-glob-util.c @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "dirent-util.h" +#include "fs-util.h" +#include "glob-util.h" +#include "macro.h" +#include "rm-rf.h" +#include "tmpfile-util.h" + +static void test_glob_exists(void) { + char name[] = "/tmp/test-glob_exists.XXXXXX"; + int fd = -1; + int r; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + close(fd); + + r = glob_exists("/tmp/test-glob_exists*"); + assert_se(r == 1); + + r = unlink(name); + assert_se(r == 0); + r = glob_exists("/tmp/test-glob_exists*"); + assert_se(r == 0); +} + +static void closedir_wrapper(void* v) { + (void) closedir(v); +} + +static void test_glob_no_dot(void) { + char template[] = "/tmp/test-glob-util.XXXXXXX"; + const char *fn; + + _cleanup_globfree_ glob_t g = { + .gl_closedir = closedir_wrapper, + .gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot, + .gl_opendir = (void *(*)(const char *)) opendir, + .gl_lstat = lstat, + .gl_stat = stat, + }; + + int r; + + assert_se(mkdtemp(template)); + + fn = strjoina(template, "/*"); + r = glob(fn, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g); + assert_se(r == GLOB_NOMATCH); + + fn = strjoina(template, "/.*"); + r = glob(fn, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g); + assert_se(r == GLOB_NOMATCH); + + (void) rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL); +} + +static void test_safe_glob(void) { + char template[] = "/tmp/test-glob-util.XXXXXXX"; + const char *fn, *fn2, *fname; + + _cleanup_globfree_ glob_t g = {}; + int r; + + assert_se(mkdtemp(template)); + + fn = strjoina(template, "/*"); + r = safe_glob(fn, 0, &g); + assert_se(r == -ENOENT); + + fn2 = strjoina(template, "/.*"); + r = safe_glob(fn2, GLOB_NOSORT|GLOB_BRACE, &g); + assert_se(r == -ENOENT); + + fname = strjoina(template, "/.foobar"); + assert_se(touch(fname) == 0); + + r = safe_glob(fn, 0, &g); + assert_se(r == -ENOENT); + + r = safe_glob(fn2, GLOB_NOSORT|GLOB_BRACE, &g); + assert_se(r == 0); + assert_se(g.gl_pathc == 1); + assert_se(streq(g.gl_pathv[0], fname)); + assert_se(g.gl_pathv[1] == NULL); + + (void) rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL); +} + +int main(void) { + test_glob_exists(); + test_glob_no_dot(); + test_safe_glob(); + + return 0; +} diff --git a/src/test/test-hash.c b/src/test/test-hash.c new file mode 100644 index 00000000..44d1044b --- /dev/null +++ b/src/test/test-hash.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "log.h" +#include "string-util.h" +#include "khash.h" +#include "tests.h" + +int main(int argc, char *argv[]) { + _cleanup_(khash_unrefp) khash *h = NULL, *copy = NULL; + _cleanup_free_ char *s = NULL; + int r; + + test_setup_logging(LOG_DEBUG); + + assert_se(khash_new(&h, NULL) == -EINVAL); + assert_se(khash_new(&h, "") == -EINVAL); + + r = khash_supported(); + assert_se(r >= 0); + if (r == 0) + return log_tests_skipped("khash not supported on this kernel"); + + assert_se(khash_new(&h, "foobar") == -EOPNOTSUPP); /* undefined hash function */ + + assert_se(khash_new(&h, "sha256") >= 0); + assert_se(khash_get_size(h) == 32); + assert_se(streq(khash_get_algorithm(h), "sha256")); + + assert_se(khash_digest_string(h, &s) >= 0); + assert_se(streq(s, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")); + s = mfree(s); + + assert_se(khash_put(h, "foobar", 6) >= 0); + assert_se(khash_digest_string(h, &s) >= 0); + assert_se(streq(s, "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2")); + s = mfree(s); + + assert_se(khash_put(h, "piep", 4) >= 0); + assert_se(khash_digest_string(h, &s) >= 0); + assert_se(streq(s, "f114d872b5ea075d3be9040d0b7a429514b3f9324a8e8e3dc3fb24c34ee56bea")); + s = mfree(s); + + assert_se(khash_put(h, "foo", 3) >= 0); + assert_se(khash_dup(h, ©) >= 0); + + assert_se(khash_put(h, "bar", 3) >= 0); + assert_se(khash_put(copy, "bar", 3) >= 0); + + assert_se(khash_digest_string(h, &s) >= 0); + assert_se(streq(s, "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2")); + s = mfree(s); + + assert_se(khash_digest_string(copy, &s) >= 0); + assert_se(streq(s, "c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2")); + s = mfree(s); + + h = khash_unref(h); + + assert_se(khash_new_with_key(&h, "hmac(sha256)", "quux", 4) >= 0); + assert_se(khash_get_size(h) == 32); + assert_se(streq(khash_get_algorithm(h), "hmac(sha256)")); + + assert_se(khash_digest_string(h, &s) >= 0); + assert_se(streq(s, "abed9f8218ab473f77218a6a7d39abf1d21fa46d0700c4898e330ba88309d5ae")); + s = mfree(s); + + assert_se(khash_put(h, "foobar", 6) >= 0); + assert_se(khash_digest_string(h, &s) >= 0); + assert_se(streq(s, "33f6c70a60db66007d5325d5d1dea37c371354e5b83347a59ad339ce9f4ba3dc")); + + return 0; +} diff --git a/src/test/test-hashmap-ordered.awk b/src/test/test-hashmap-ordered.awk new file mode 100644 index 00000000..10f4386f --- /dev/null +++ b/src/test/test-hashmap-ordered.awk @@ -0,0 +1,11 @@ +BEGIN { + print "/* GENERATED FILE */"; + print "#define ORDERED" +} +{ + if (!match($0, "^#include")) + gsub(/hashmap/, "ordered_hashmap"); + gsub(/HASHMAP/, "ORDERED_HASHMAP"); + gsub(/Hashmap/, "OrderedHashmap"); + print +} diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c new file mode 100644 index 00000000..57cf89ff --- /dev/null +++ b/src/test/test-hashmap-plain.c @@ -0,0 +1,1099 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "hashmap.h" +#include "log.h" +#include "nulstr-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "tests.h" + +void test_hashmap_funcs(void); + +static void test_hashmap_replace(void) { + Hashmap *m; + char *val1, *val2, *val3, *val4, *val5, *r; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + + val1 = strdup("val1"); + assert_se(val1); + val2 = strdup("val2"); + assert_se(val2); + val3 = strdup("val3"); + assert_se(val3); + val4 = strdup("val4"); + assert_se(val4); + val5 = strdup("val5"); + assert_se(val5); + + hashmap_put(m, "key 1", val1); + hashmap_put(m, "key 2", val2); + hashmap_put(m, "key 3", val3); + hashmap_put(m, "key 4", val4); + + hashmap_replace(m, "key 3", val1); + r = hashmap_get(m, "key 3"); + assert_se(streq(r, "val1")); + + hashmap_replace(m, "key 5", val5); + r = hashmap_get(m, "key 5"); + assert_se(streq(r, "val5")); + + free(val1); + free(val2); + free(val3); + free(val4); + free(val5); + hashmap_free(m); +} + +static void test_hashmap_copy(void) { + Hashmap *m, *copy; + char *val1, *val2, *val3, *val4, *r; + + log_info("/* %s */", __func__); + + val1 = strdup("val1"); + assert_se(val1); + val2 = strdup("val2"); + assert_se(val2); + val3 = strdup("val3"); + assert_se(val3); + val4 = strdup("val4"); + assert_se(val4); + + m = hashmap_new(&string_hash_ops); + + hashmap_put(m, "key 1", val1); + hashmap_put(m, "key 2", val2); + hashmap_put(m, "key 3", val3); + hashmap_put(m, "key 4", val4); + + copy = hashmap_copy(m); + + r = hashmap_get(copy, "key 1"); + assert_se(streq(r, "val1")); + r = hashmap_get(copy, "key 2"); + assert_se(streq(r, "val2")); + r = hashmap_get(copy, "key 3"); + assert_se(streq(r, "val3")); + r = hashmap_get(copy, "key 4"); + assert_se(streq(r, "val4")); + + hashmap_free_free(copy); + hashmap_free(m); +} + +static void test_hashmap_get_strv(void) { + Hashmap *m; + char **strv; + char *val1, *val2, *val3, *val4; + + log_info("/* %s */", __func__); + + val1 = strdup("val1"); + assert_se(val1); + val2 = strdup("val2"); + assert_se(val2); + val3 = strdup("val3"); + assert_se(val3); + val4 = strdup("val4"); + assert_se(val4); + + m = hashmap_new(&string_hash_ops); + + hashmap_put(m, "key 1", val1); + hashmap_put(m, "key 2", val2); + hashmap_put(m, "key 3", val3); + hashmap_put(m, "key 4", val4); + + strv = hashmap_get_strv(m); + +#ifndef ORDERED + strv = strv_sort(strv); +#endif + + assert_se(streq(strv[0], "val1")); + assert_se(streq(strv[1], "val2")); + assert_se(streq(strv[2], "val3")); + assert_se(streq(strv[3], "val4")); + + strv_free(strv); + + hashmap_free(m); +} + +static void test_hashmap_move_one(void) { + Hashmap *m, *n; + char *val1, *val2, *val3, *val4, *r; + + log_info("/* %s */", __func__); + + val1 = strdup("val1"); + assert_se(val1); + val2 = strdup("val2"); + assert_se(val2); + val3 = strdup("val3"); + assert_se(val3); + val4 = strdup("val4"); + assert_se(val4); + + m = hashmap_new(&string_hash_ops); + n = hashmap_new(&string_hash_ops); + + hashmap_put(m, "key 1", val1); + hashmap_put(m, "key 2", val2); + hashmap_put(m, "key 3", val3); + hashmap_put(m, "key 4", val4); + + assert_se(hashmap_move_one(n, NULL, "key 3") == -ENOENT); + assert_se(hashmap_move_one(n, m, "key 5") == -ENOENT); + assert_se(hashmap_move_one(n, m, "key 3") == 0); + assert_se(hashmap_move_one(n, m, "key 4") == 0); + + r = hashmap_get(n, "key 3"); + assert_se(r && streq(r, "val3")); + r = hashmap_get(n, "key 4"); + assert_se(r && streq(r, "val4")); + r = hashmap_get(m, "key 3"); + assert_se(!r); + + assert_se(hashmap_move_one(n, m, "key 3") == -EEXIST); + + hashmap_free_free(m); + hashmap_free_free(n); +} + +static void test_hashmap_move(void) { + Hashmap *m, *n; + char *val1, *val2, *val3, *val4, *r; + + log_info("/* %s */", __func__); + + val1 = strdup("val1"); + assert_se(val1); + val2 = strdup("val2"); + assert_se(val2); + val3 = strdup("val3"); + assert_se(val3); + val4 = strdup("val4"); + assert_se(val4); + + m = hashmap_new(&string_hash_ops); + n = hashmap_new(&string_hash_ops); + + hashmap_put(n, "key 1", strdup(val1)); + hashmap_put(m, "key 1", val1); + hashmap_put(m, "key 2", val2); + hashmap_put(m, "key 3", val3); + hashmap_put(m, "key 4", val4); + + assert_se(hashmap_move(n, NULL) == 0); + assert_se(hashmap_move(n, m) == 0); + + assert_se(hashmap_size(m) == 1); + r = hashmap_get(m, "key 1"); + assert_se(r && streq(r, "val1")); + + r = hashmap_get(n, "key 1"); + assert_se(r && streq(r, "val1")); + r = hashmap_get(n, "key 2"); + assert_se(r && streq(r, "val2")); + r = hashmap_get(n, "key 3"); + assert_se(r && streq(r, "val3")); + r = hashmap_get(n, "key 4"); + assert_se(r && streq(r, "val4")); + + hashmap_free_free(m); + hashmap_free_free(n); +} + +static void test_hashmap_update(void) { + Hashmap *m; + char *val1, *val2, *r; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + val1 = strdup("old_value"); + assert_se(val1); + val2 = strdup("new_value"); + assert_se(val2); + + hashmap_put(m, "key 1", val1); + r = hashmap_get(m, "key 1"); + assert_se(streq(r, "old_value")); + + assert_se(hashmap_update(m, "key 2", val2) == -ENOENT); + r = hashmap_get(m, "key 1"); + assert_se(streq(r, "old_value")); + + assert_se(hashmap_update(m, "key 1", val2) == 0); + r = hashmap_get(m, "key 1"); + assert_se(streq(r, "new_value")); + + free(val1); + free(val2); + hashmap_free(m); +} + +static void test_hashmap_put(void) { + Hashmap *m = NULL; + int valid_hashmap_put; + void *val1 = (void*) "val 1"; + void *val2 = (void*) "val 2"; + _cleanup_free_ char* key1 = NULL; + + log_info("/* %s */", __func__); + + assert_se(hashmap_ensure_allocated(&m, &string_hash_ops) >= 0); + assert_se(m); + + valid_hashmap_put = hashmap_put(m, "key 1", val1); + assert_se(valid_hashmap_put == 1); + assert_se(hashmap_put(m, "key 1", val1) == 0); + assert_se(hashmap_put(m, "key 1", val2) == -EEXIST); + key1 = strdup("key 1"); + assert_se(hashmap_put(m, key1, val1) == 0); + assert_se(hashmap_put(m, key1, val2) == -EEXIST); + + hashmap_free(m); +} + +static void test_hashmap_remove(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + char *r; + + log_info("/* %s */", __func__); + + r = hashmap_remove(NULL, "key 1"); + assert_se(r == NULL); + + m = hashmap_new(&string_hash_ops); + assert_se(m); + + r = hashmap_remove(m, "no such key"); + assert_se(r == NULL); + + hashmap_put(m, "key 1", (void*) "val 1"); + hashmap_put(m, "key 2", (void*) "val 2"); + + r = hashmap_remove(m, "key 1"); + assert_se(streq(r, "val 1")); + + r = hashmap_get(m, "key 2"); + assert_se(streq(r, "val 2")); + assert_se(!hashmap_get(m, "key 1")); +} + +static void test_hashmap_remove2(void) { + _cleanup_hashmap_free_free_free_ Hashmap *m = NULL; + char key1[] = "key 1"; + char key2[] = "key 2"; + char val1[] = "val 1"; + char val2[] = "val 2"; + void *r, *r2; + + log_info("/* %s */", __func__); + + r = hashmap_remove2(NULL, "key 1", &r2); + assert_se(r == NULL); + + m = hashmap_new(&string_hash_ops); + assert_se(m); + + r = hashmap_remove2(m, "no such key", &r2); + assert_se(r == NULL); + + hashmap_put(m, strdup(key1), strdup(val1)); + hashmap_put(m, strdup(key2), strdup(val2)); + + r = hashmap_remove2(m, key1, &r2); + assert_se(streq(r, val1)); + assert_se(streq(r2, key1)); + free(r); + free(r2); + + r = hashmap_get(m, key2); + assert_se(streq(r, val2)); + assert_se(!hashmap_get(m, key1)); +} + +static void test_hashmap_remove_value(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + char *r; + + char val1[] = "val 1"; + char val2[] = "val 2"; + + log_info("/* %s */", __func__); + + r = hashmap_remove_value(NULL, "key 1", val1); + assert_se(r == NULL); + + m = hashmap_new(&string_hash_ops); + assert_se(m); + + r = hashmap_remove_value(m, "key 1", val1); + assert_se(r == NULL); + + hashmap_put(m, "key 1", val1); + hashmap_put(m, "key 2", val2); + + r = hashmap_remove_value(m, "key 1", val1); + assert_se(streq(r, "val 1")); + + r = hashmap_get(m, "key 2"); + assert_se(streq(r, "val 2")); + assert_se(!hashmap_get(m, "key 1")); + + r = hashmap_remove_value(m, "key 2", val1); + assert_se(r == NULL); + + r = hashmap_get(m, "key 2"); + assert_se(streq(r, "val 2")); + assert_se(!hashmap_get(m, "key 1")); +} + +static void test_hashmap_remove_and_put(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + int valid; + char *r; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + assert_se(m); + + valid = hashmap_remove_and_put(m, "invalid key", "new key", NULL); + assert_se(valid == -ENOENT); + + valid = hashmap_put(m, "key 1", (void*) (const char *) "val 1"); + assert_se(valid == 1); + + valid = hashmap_remove_and_put(NULL, "key 1", "key 2", (void*) (const char *) "val 2"); + assert_se(valid == -ENOENT); + + valid = hashmap_remove_and_put(m, "key 1", "key 2", (void*) (const char *) "val 2"); + assert_se(valid == 0); + + r = hashmap_get(m, "key 2"); + assert_se(streq(r, "val 2")); + assert_se(!hashmap_get(m, "key 1")); + + valid = hashmap_put(m, "key 3", (void*) (const char *) "val 3"); + assert_se(valid == 1); + valid = hashmap_remove_and_put(m, "key 3", "key 2", (void*) (const char *) "val 2"); + assert_se(valid == -EEXIST); +} + +static void test_hashmap_remove_and_replace(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + int valid; + void *key1 = UINT_TO_PTR(1); + void *key2 = UINT_TO_PTR(2); + void *key3 = UINT_TO_PTR(3); + void *r; + int i, j; + + log_info("/* %s */", __func__); + + m = hashmap_new(&trivial_hash_ops); + assert_se(m); + + valid = hashmap_remove_and_replace(m, key1, key2, NULL); + assert_se(valid == -ENOENT); + + valid = hashmap_put(m, key1, key1); + assert_se(valid == 1); + + valid = hashmap_remove_and_replace(NULL, key1, key2, key2); + assert_se(valid == -ENOENT); + + valid = hashmap_remove_and_replace(m, key1, key2, key2); + assert_se(valid == 0); + + r = hashmap_get(m, key2); + assert_se(r == key2); + assert_se(!hashmap_get(m, key1)); + + valid = hashmap_put(m, key3, key3); + assert_se(valid == 1); + valid = hashmap_remove_and_replace(m, key3, key2, key2); + assert_se(valid == 0); + r = hashmap_get(m, key2); + assert_se(r == key2); + assert_se(!hashmap_get(m, key3)); + + /* Repeat this test several times to increase the chance of hitting + * the less likely case in hashmap_remove_and_replace where it + * compensates for the backward shift. */ + for (i = 0; i < 20; i++) { + hashmap_clear(m); + + for (j = 1; j < 7; j++) + hashmap_put(m, UINT_TO_PTR(10*i + j), UINT_TO_PTR(10*i + j)); + valid = hashmap_remove_and_replace(m, UINT_TO_PTR(10*i + 1), + UINT_TO_PTR(10*i + 2), + UINT_TO_PTR(10*i + 2)); + assert_se(valid == 0); + assert_se(!hashmap_get(m, UINT_TO_PTR(10*i + 1))); + for (j = 2; j < 7; j++) { + r = hashmap_get(m, UINT_TO_PTR(10*i + j)); + assert_se(r == UINT_TO_PTR(10*i + j)); + } + } +} + +static void test_hashmap_ensure_allocated(void) { + Hashmap *m; + int valid_hashmap; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + + valid_hashmap = hashmap_ensure_allocated(&m, &string_hash_ops); + assert_se(valid_hashmap == 0); + + assert_se(m); + hashmap_free(m); +} + +static void test_hashmap_foreach_key(void) { + Hashmap *m; + Iterator i; + bool key_found[] = { false, false, false, false }; + const char *s; + const char *key; + static const char key_table[] = + "key 1\0" + "key 2\0" + "key 3\0" + "key 4\0"; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + + NULSTR_FOREACH(key, key_table) + hashmap_put(m, key, (void*) (const char*) "my dummy val"); + + HASHMAP_FOREACH_KEY(s, key, m, i) { + assert(s); + if (!key_found[0] && streq(key, "key 1")) + key_found[0] = true; + else if (!key_found[1] && streq(key, "key 2")) + key_found[1] = true; + else if (!key_found[2] && streq(key, "key 3")) + key_found[2] = true; + else if (!key_found[3] && streq(key, "fail")) + key_found[3] = true; + } + + assert_se(m); + assert_se(key_found[0] && key_found[1] && key_found[2] && !key_found[3]); + + hashmap_free(m); +} + +static void test_hashmap_foreach(void) { + Hashmap *m; + Iterator i; + bool value_found[] = { false, false, false, false }; + char *val1, *val2, *val3, *val4, *s; + unsigned count; + + log_info("/* %s */", __func__); + + val1 = strdup("my val1"); + assert_se(val1); + val2 = strdup("my val2"); + assert_se(val2); + val3 = strdup("my val3"); + assert_se(val3); + val4 = strdup("my val4"); + assert_se(val4); + + m = NULL; + + count = 0; + HASHMAP_FOREACH(s, m, i) + count++; + assert_se(count == 0); + + m = hashmap_new(&string_hash_ops); + + count = 0; + HASHMAP_FOREACH(s, m, i) + count++; + assert_se(count == 0); + + hashmap_put(m, "Key 1", val1); + hashmap_put(m, "Key 2", val2); + hashmap_put(m, "Key 3", val3); + hashmap_put(m, "Key 4", val4); + + HASHMAP_FOREACH(s, m, i) { + if (!value_found[0] && streq(s, val1)) + value_found[0] = true; + else if (!value_found[1] && streq(s, val2)) + value_found[1] = true; + else if (!value_found[2] && streq(s, val3)) + value_found[2] = true; + else if (!value_found[3] && streq(s, val4)) + value_found[3] = true; + } + + assert_se(m); + assert_se(value_found[0] && value_found[1] && value_found[2] && value_found[3]); + + hashmap_free_free(m); +} + +static void test_hashmap_merge(void) { + Hashmap *m; + Hashmap *n; + char *val1, *val2, *val3, *val4, *r; + + log_info("/* %s */", __func__); + + val1 = strdup("my val1"); + assert_se(val1); + val2 = strdup("my val2"); + assert_se(val2); + val3 = strdup("my val3"); + assert_se(val3); + val4 = strdup("my val4"); + assert_se(val4); + + n = hashmap_new(&string_hash_ops); + m = hashmap_new(&string_hash_ops); + + hashmap_put(m, "Key 1", val1); + hashmap_put(m, "Key 2", val2); + hashmap_put(n, "Key 3", val3); + hashmap_put(n, "Key 4", val4); + + assert_se(hashmap_merge(m, n) == 0); + r = hashmap_get(m, "Key 3"); + assert_se(r && streq(r, "my val3")); + r = hashmap_get(m, "Key 4"); + assert_se(r && streq(r, "my val4")); + + assert_se(n); + assert_se(m); + hashmap_free(n); + hashmap_free_free(m); +} + +static void test_hashmap_contains(void) { + Hashmap *m; + char *val1; + + log_info("/* %s */", __func__); + + val1 = strdup("my val"); + assert_se(val1); + + m = hashmap_new(&string_hash_ops); + + assert_se(!hashmap_contains(m, "Key 1")); + hashmap_put(m, "Key 1", val1); + assert_se(hashmap_contains(m, "Key 1")); + assert_se(!hashmap_contains(m, "Key 2")); + + assert_se(!hashmap_contains(NULL, "Key 1")); + + assert_se(m); + hashmap_free_free(m); +} + +static void test_hashmap_isempty(void) { + Hashmap *m; + char *val1; + + log_info("/* %s */", __func__); + + val1 = strdup("my val"); + assert_se(val1); + + m = hashmap_new(&string_hash_ops); + + assert_se(hashmap_isempty(m)); + hashmap_put(m, "Key 1", val1); + assert_se(!hashmap_isempty(m)); + + assert_se(m); + hashmap_free_free(m); +} + +static void test_hashmap_size(void) { + Hashmap *m; + char *val1, *val2, *val3, *val4; + + log_info("/* %s */", __func__); + + val1 = strdup("my val"); + assert_se(val1); + val2 = strdup("my val"); + assert_se(val2); + val3 = strdup("my val"); + assert_se(val3); + val4 = strdup("my val"); + assert_se(val4); + + assert_se(hashmap_size(NULL) == 0); + assert_se(hashmap_buckets(NULL) == 0); + + m = hashmap_new(&string_hash_ops); + + hashmap_put(m, "Key 1", val1); + hashmap_put(m, "Key 2", val2); + hashmap_put(m, "Key 3", val3); + hashmap_put(m, "Key 4", val4); + + assert_se(m); + assert_se(hashmap_size(m) == 4); + assert_se(hashmap_buckets(m) >= 4); + hashmap_free_free(m); +} + +static void test_hashmap_get(void) { + Hashmap *m; + char *r; + char *val; + + log_info("/* %s */", __func__); + + val = strdup("my val"); + assert_se(val); + + r = hashmap_get(NULL, "Key 1"); + assert_se(r == NULL); + + m = hashmap_new(&string_hash_ops); + + hashmap_put(m, "Key 1", val); + + r = hashmap_get(m, "Key 1"); + assert_se(streq(r, val)); + + r = hashmap_get(m, "no such key"); + assert_se(r == NULL); + + assert_se(m); + hashmap_free_free(m); +} + +static void test_hashmap_get2(void) { + Hashmap *m; + char *r; + char *val; + char key_orig[] = "Key 1"; + void *key_copy; + + log_info("/* %s */", __func__); + + val = strdup("my val"); + assert_se(val); + + key_copy = strdup(key_orig); + assert_se(key_copy); + + r = hashmap_get2(NULL, key_orig, &key_copy); + assert_se(r == NULL); + + m = hashmap_new(&string_hash_ops); + + hashmap_put(m, key_copy, val); + key_copy = NULL; + + r = hashmap_get2(m, key_orig, &key_copy); + assert_se(streq(r, val)); + assert_se(key_orig != key_copy); + assert_se(streq(key_orig, key_copy)); + + r = hashmap_get2(m, "no such key", NULL); + assert_se(r == NULL); + + assert_se(m); + hashmap_free_free_free(m); +} + +static void crippled_hashmap_func(const void *p, struct siphash *state) { + return trivial_hash_func(INT_TO_PTR(PTR_TO_INT(p) & 0xff), state); +} + +static const struct hash_ops crippled_hashmap_ops = { + .hash = crippled_hashmap_func, + .compare = trivial_compare_func, +}; + +static void test_hashmap_many(void) { + Hashmap *h; + unsigned i, j; + void *v, *k; + bool slow = slow_tests_enabled(); + const struct { + const char *title; + const struct hash_ops *ops; + unsigned n_entries; + } tests[] = { + { "trivial_hashmap_ops", NULL, slow ? 1 << 20 : 240 }, + { "crippled_hashmap_ops", &crippled_hashmap_ops, slow ? 1 << 14 : 140 }, + }; + + log_info("/* %s (%s) */", __func__, slow ? "slow" : "fast"); + + for (j = 0; j < ELEMENTSOF(tests); j++) { + usec_t ts = now(CLOCK_MONOTONIC), n; + char b[FORMAT_TIMESPAN_MAX]; + + assert_se(h = hashmap_new(tests[j].ops)); + + for (i = 1; i < tests[j].n_entries*3; i+=3) { + assert_se(hashmap_put(h, UINT_TO_PTR(i), UINT_TO_PTR(i)) >= 0); + assert_se(PTR_TO_UINT(hashmap_get(h, UINT_TO_PTR(i))) == i); + } + + for (i = 1; i < tests[j].n_entries*3; i++) + assert_se(hashmap_contains(h, UINT_TO_PTR(i)) == (i % 3 == 1)); + + log_info("%s %u <= %u * 0.8 = %g", + tests[j].title, hashmap_size(h), hashmap_buckets(h), hashmap_buckets(h) * 0.8); + + assert_se(hashmap_size(h) <= hashmap_buckets(h) * 0.8); + assert_se(hashmap_size(h) == tests[j].n_entries); + + while (!hashmap_isempty(h)) { + k = hashmap_first_key(h); + v = hashmap_remove(h, k); + assert_se(v == k); + } + + hashmap_free(h); + + n = now(CLOCK_MONOTONIC); + log_info("test took %s", format_timespan(b, sizeof b, n - ts, 0)); + } +} + +extern unsigned custom_counter; +extern const struct hash_ops boring_hash_ops, custom_hash_ops; + +static void test_hashmap_free(void) { + Hashmap *h; + bool slow = slow_tests_enabled(); + usec_t ts, n; + char b[FORMAT_TIMESPAN_MAX]; + unsigned n_entries = slow ? 1 << 20 : 240; + + const struct { + const char *title; + const struct hash_ops *ops; + unsigned expect_counter; + } tests[] = { + { "string_hash_ops", &boring_hash_ops, 2 * n_entries}, + { "custom_free_hash_ops", &custom_hash_ops, 0 }, + }; + + log_info("/* %s (%s, %u entries) */", __func__, slow ? "slow" : "fast", n_entries); + + for (unsigned j = 0; j < ELEMENTSOF(tests); j++) { + ts = now(CLOCK_MONOTONIC); + assert_se(h = hashmap_new(tests[j].ops)); + + custom_counter = 0; + for (unsigned i = 0; i < n_entries; i++) { + char s[DECIMAL_STR_MAX(unsigned)]; + char *k, *v; + + xsprintf(s, "%u", i); + assert_se(k = strdup(s)); + assert_se(v = strdup(s)); + custom_counter += 2; + + assert_se(hashmap_put(h, k, v) >= 0); + } + + hashmap_free(h); + + n = now(CLOCK_MONOTONIC); + log_info("%s test took %s", tests[j].title, format_timespan(b, sizeof b, n - ts, 0)); + + assert_se(custom_counter == tests[j].expect_counter); + } +} + +typedef struct Item { + int seen; +} Item; +static void item_seen(Item *item) { + item->seen++; +} + +static void test_hashmap_free_with_destructor(void) { + Hashmap *m; + struct Item items[4] = {}; + unsigned i; + + log_info("/* %s */", __func__); + + assert_se(m = hashmap_new(NULL)); + for (i = 0; i < ELEMENTSOF(items) - 1; i++) + assert_se(hashmap_put(m, INT_TO_PTR(i), items + i) == 1); + + m = hashmap_free_with_destructor(m, item_seen); + assert_se(items[0].seen == 1); + assert_se(items[1].seen == 1); + assert_se(items[2].seen == 1); + assert_se(items[3].seen == 0); +} + +static void test_hashmap_first(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + assert_se(m); + + assert_se(!hashmap_first(m)); + assert_se(hashmap_put(m, "key 1", (void*) "val 1") == 1); + assert_se(streq(hashmap_first(m), "val 1")); + assert_se(hashmap_put(m, "key 2", (void*) "val 2") == 1); +#ifdef ORDERED + assert_se(streq(hashmap_first(m), "val 1")); + assert_se(hashmap_remove(m, "key 1")); + assert_se(streq(hashmap_first(m), "val 2")); +#endif +} + +static void test_hashmap_first_key(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + assert_se(m); + + assert_se(!hashmap_first_key(m)); + assert_se(hashmap_put(m, "key 1", NULL) == 1); + assert_se(streq(hashmap_first_key(m), "key 1")); + assert_se(hashmap_put(m, "key 2", NULL) == 1); +#ifdef ORDERED + assert_se(streq(hashmap_first_key(m), "key 1")); + assert_se(hashmap_remove(m, "key 1") == NULL); + assert_se(streq(hashmap_first_key(m), "key 2")); +#endif +} + +static void test_hashmap_steal_first_key(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + assert_se(m); + + assert_se(!hashmap_steal_first_key(m)); + assert_se(hashmap_put(m, "key 1", NULL) == 1); + assert_se(streq(hashmap_steal_first_key(m), "key 1")); + + assert_se(hashmap_isempty(m)); +} + +static void test_hashmap_steal_first(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + int seen[3] = {}; + char *val; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + assert_se(m); + + assert_se(hashmap_put(m, "key 1", (void*) "1") == 1); + assert_se(hashmap_put(m, "key 2", (void*) "22") == 1); + assert_se(hashmap_put(m, "key 3", (void*) "333") == 1); + + while ((val = hashmap_steal_first(m))) + seen[strlen(val) - 1]++; + + assert_se(seen[0] == 1 && seen[1] == 1 && seen[2] == 1); + + assert_se(hashmap_isempty(m)); +} + +static void test_hashmap_clear_free_free(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + assert_se(m); + + assert_se(hashmap_put(m, strdup("key 1"), NULL) == 1); + assert_se(hashmap_put(m, strdup("key 2"), NULL) == 1); + assert_se(hashmap_put(m, strdup("key 3"), NULL) == 1); + + hashmap_clear_free_free(m); + assert_se(hashmap_isempty(m)); + + assert_se(hashmap_put(m, strdup("key 1"), strdup("value 1")) == 1); + assert_se(hashmap_put(m, strdup("key 2"), strdup("value 2")) == 1); + assert_se(hashmap_put(m, strdup("key 3"), strdup("value 3")) == 1); + + hashmap_clear_free_free(m); + assert_se(hashmap_isempty(m)); +} + +DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(test_hash_ops_key, char, string_hash_func, string_compare_func, free); +DEFINE_PRIVATE_HASH_OPS_FULL(test_hash_ops_full, char, string_hash_func, string_compare_func, free, char, free); + +static void test_hashmap_clear_free_with_destructor(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + + log_info("/* %s */", __func__); + + m = hashmap_new(&test_hash_ops_key); + assert_se(m); + + assert_se(hashmap_put(m, strdup("key 1"), NULL) == 1); + assert_se(hashmap_put(m, strdup("key 2"), NULL) == 1); + assert_se(hashmap_put(m, strdup("key 3"), NULL) == 1); + + hashmap_clear_free(m); + assert_se(hashmap_isempty(m)); + m = hashmap_free(m); + + m = hashmap_new(&test_hash_ops_full); + assert_se(m); + + assert_se(hashmap_put(m, strdup("key 1"), strdup("value 1")) == 1); + assert_se(hashmap_put(m, strdup("key 2"), strdup("value 2")) == 1); + assert_se(hashmap_put(m, strdup("key 3"), strdup("value 3")) == 1); + + hashmap_clear_free(m); + assert_se(hashmap_isempty(m)); +} + +static void test_hashmap_reserve(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + + log_info("/* %s */", __func__); + + m = hashmap_new(&string_hash_ops); + + assert_se(hashmap_reserve(m, 1) == 0); + assert_se(hashmap_buckets(m) < 1000); + assert_se(hashmap_reserve(m, 1000) == 0); + assert_se(hashmap_buckets(m) >= 1000); + assert_se(hashmap_isempty(m)); + + assert_se(hashmap_put(m, "key 1", (void*) "val 1") == 1); + + assert_se(hashmap_reserve(m, UINT_MAX) == -ENOMEM); + assert_se(hashmap_reserve(m, UINT_MAX - 1) == -ENOMEM); +} + +static void test_path_hashmap(void) { + _cleanup_hashmap_free_ Hashmap *h = NULL; + + log_info("/* %s */", __func__); + + assert_se(h = hashmap_new(&path_hash_ops)); + + assert_se(hashmap_put(h, "foo", INT_TO_PTR(1)) >= 0); + assert_se(hashmap_put(h, "/foo", INT_TO_PTR(2)) >= 0); + assert_se(hashmap_put(h, "//foo", INT_TO_PTR(3)) == -EEXIST); + assert_se(hashmap_put(h, "//foox/", INT_TO_PTR(4)) >= 0); + assert_se(hashmap_put(h, "/foox////", INT_TO_PTR(5)) == -EEXIST); + assert_se(hashmap_put(h, "foo//////bar/quux//", INT_TO_PTR(6)) >= 0); + assert_se(hashmap_put(h, "foo/bar//quux/", INT_TO_PTR(8)) == -EEXIST); + + assert_se(hashmap_get(h, "foo") == INT_TO_PTR(1)); + assert_se(hashmap_get(h, "foo/") == INT_TO_PTR(1)); + assert_se(hashmap_get(h, "foo////") == INT_TO_PTR(1)); + assert_se(hashmap_get(h, "/foo") == INT_TO_PTR(2)); + assert_se(hashmap_get(h, "//foo") == INT_TO_PTR(2)); + assert_se(hashmap_get(h, "/////foo////") == INT_TO_PTR(2)); + assert_se(hashmap_get(h, "/////foox////") == INT_TO_PTR(4)); + assert_se(hashmap_get(h, "/foox/") == INT_TO_PTR(4)); + assert_se(hashmap_get(h, "/foox") == INT_TO_PTR(4)); + assert_se(!hashmap_get(h, "foox")); + assert_se(hashmap_get(h, "foo/bar/quux") == INT_TO_PTR(6)); + assert_se(hashmap_get(h, "foo////bar////quux/////") == INT_TO_PTR(6)); + assert_se(!hashmap_get(h, "/foo////bar////quux/////")); +} + +static void test_string_strv_hashmap(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + char **s; + + log_info("/* %s */", __func__); + + assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 1); + assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 0); + assert_se(string_strv_hashmap_put(&m, "foo", "BAR") == 1); + assert_se(string_strv_hashmap_put(&m, "foo", "BAR") == 0); + assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 0); + assert_se(hashmap_contains(m, "foo")); + + s = hashmap_get(m, "foo"); + assert_se(strv_equal(s, STRV_MAKE("bar", "BAR"))); + + assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 1); + assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 0); + assert_se(string_strv_hashmap_put(&m, "xxx", "BAR") == 1); + assert_se(string_strv_hashmap_put(&m, "xxx", "BAR") == 0); + assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 0); + assert_se(hashmap_contains(m, "xxx")); + + s = hashmap_get(m, "xxx"); + assert_se(strv_equal(s, STRV_MAKE("bar", "BAR"))); +} + +void test_hashmap_funcs(void) { + log_info("/************ %s ************/", __func__); + + test_hashmap_copy(); + test_hashmap_get_strv(); + test_hashmap_move_one(); + test_hashmap_move(); + test_hashmap_replace(); + test_hashmap_update(); + test_hashmap_put(); + test_hashmap_remove(); + test_hashmap_remove2(); + test_hashmap_remove_value(); + test_hashmap_remove_and_put(); + test_hashmap_remove_and_replace(); + test_hashmap_ensure_allocated(); + test_hashmap_foreach(); + test_hashmap_foreach_key(); + test_hashmap_contains(); + test_hashmap_merge(); + test_hashmap_isempty(); + test_hashmap_get(); + test_hashmap_get2(); + test_hashmap_size(); + test_hashmap_many(); + test_hashmap_free(); + test_hashmap_free_with_destructor(); + test_hashmap_first(); + test_hashmap_first_key(); + test_hashmap_steal_first_key(); + test_hashmap_steal_first(); + test_hashmap_clear_free_free(); + test_hashmap_clear_free_with_destructor(); + test_hashmap_reserve(); + test_path_hashmap(); + test_string_strv_hashmap(); +} diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c new file mode 100644 index 00000000..1a6e8ffa --- /dev/null +++ b/src/test/test-hashmap.c @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "hashmap.h" +#include "util.h" + +unsigned custom_counter = 0; +static void custom_destruct(void* p) { + custom_counter--; + free(p); +} + +DEFINE_HASH_OPS_FULL(boring_hash_ops, char, string_hash_func, string_compare_func, free, char, free); +DEFINE_HASH_OPS_FULL(custom_hash_ops, char, string_hash_func, string_compare_func, custom_destruct, char, custom_destruct); + +void test_hashmap_funcs(void); +void test_ordered_hashmap_funcs(void); + +static void test_ordered_hashmap_next(void) { + _cleanup_ordered_hashmap_free_ OrderedHashmap *m = NULL; + int i; + + log_info("/* %s */", __func__); + + assert_se(m = ordered_hashmap_new(NULL)); + for (i = -2; i <= 2; i++) + assert_se(ordered_hashmap_put(m, INT_TO_PTR(i), INT_TO_PTR(i+10)) == 1); + for (i = -2; i <= 1; i++) + assert_se(ordered_hashmap_next(m, INT_TO_PTR(i)) == INT_TO_PTR(i+11)); + assert_se(!ordered_hashmap_next(m, INT_TO_PTR(2))); + assert_se(!ordered_hashmap_next(NULL, INT_TO_PTR(1))); + assert_se(!ordered_hashmap_next(m, INT_TO_PTR(3))); +} + +static void test_uint64_compare_func(void) { + const uint64_t a = 0x100, b = 0x101; + + assert_se(uint64_compare_func(&a, &a) == 0); + assert_se(uint64_compare_func(&a, &b) == -1); + assert_se(uint64_compare_func(&b, &a) == 1); +} + +static void test_trivial_compare_func(void) { + assert_se(trivial_compare_func(INT_TO_PTR('a'), INT_TO_PTR('a')) == 0); + assert_se(trivial_compare_func(INT_TO_PTR('a'), INT_TO_PTR('b')) == -1); + assert_se(trivial_compare_func(INT_TO_PTR('b'), INT_TO_PTR('a')) == 1); +} + +static void test_string_compare_func(void) { + assert_se(string_compare_func("fred", "wilma") != 0); + assert_se(string_compare_func("fred", "fred") == 0); +} + +static void compare_cache(Hashmap *map, IteratedCache *cache) { + const void **keys = NULL, **values = NULL; + unsigned num, idx; + Iterator iter; + void *k, *v; + + assert_se(iterated_cache_get(cache, &keys, &values, &num) == 0); + assert_se(num == 0 || keys); + assert_se(num == 0 || values); + + idx = 0; + HASHMAP_FOREACH_KEY(v, k, map, iter) { + assert_se(v == values[idx]); + assert_se(k == keys[idx]); + + idx++; + } + + assert_se(idx == num); +} + +static void test_iterated_cache(void) { + Hashmap *m; + IteratedCache *c; + + log_info("/* %s */", __func__); + + assert_se(m = hashmap_new(NULL)); + assert_se(c = hashmap_iterated_cache_new(m)); + compare_cache(m, c); + + for (int stage = 0; stage < 100; stage++) { + + for (int i = 0; i < 100; i++) { + int foo = stage * 1000 + i; + + assert_se(hashmap_put(m, INT_TO_PTR(foo), INT_TO_PTR(foo + 777)) == 1); + } + + compare_cache(m, c); + + if (!(stage % 10)) { + for (int i = 0; i < 100; i++) { + int foo = stage * 1000 + i; + + assert_se(hashmap_remove(m, INT_TO_PTR(foo)) == INT_TO_PTR(foo + 777)); + } + + compare_cache(m, c); + } + } + + hashmap_clear(m); + compare_cache(m, c); + + assert_se(hashmap_free(m) == NULL); + assert_se(iterated_cache_free(c) == NULL); +} + +int main(int argc, const char *argv[]) { + /* This file tests in test-hashmap-plain.c, and tests in test-hashmap-ordered.c, which is generated + * from test-hashmap-plain.c. Hashmap tests should be added to test-hashmap-plain.c, and here only if + * they don't apply to ordered hashmaps. */ + + log_parse_environment(); + log_open(); + + test_hashmap_funcs(); + test_ordered_hashmap_funcs(); + + log_info("/************ non-shared tests ************/"); + + test_ordered_hashmap_next(); + test_uint64_compare_func(); + test_trivial_compare_func(); + test_string_compare_func(); + test_iterated_cache(); + + return 0; +} diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c new file mode 100644 index 00000000..52217429 --- /dev/null +++ b/src/test/test-hexdecoct.c @@ -0,0 +1,355 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "hexdecoct.h" +#include "macro.h" +#include "string-util.h" + +static void test_hexchar(void) { + assert_se(hexchar(0xa) == 'a'); + assert_se(hexchar(0x0) == '0'); +} + +static void test_unhexchar(void) { + assert_se(unhexchar('a') == 0xA); + assert_se(unhexchar('A') == 0xA); + assert_se(unhexchar('0') == 0x0); +} + +static void test_base32hexchar(void) { + assert_se(base32hexchar(0) == '0'); + assert_se(base32hexchar(9) == '9'); + assert_se(base32hexchar(10) == 'A'); + assert_se(base32hexchar(31) == 'V'); +} + +static void test_unbase32hexchar(void) { + assert_se(unbase32hexchar('0') == 0); + assert_se(unbase32hexchar('9') == 9); + assert_se(unbase32hexchar('A') == 10); + assert_se(unbase32hexchar('V') == 31); + assert_se(unbase32hexchar('=') == -EINVAL); +} + +static void test_base64char(void) { + assert_se(base64char(0) == 'A'); + assert_se(base64char(26) == 'a'); + assert_se(base64char(63) == '/'); +} + +static void test_unbase64char(void) { + assert_se(unbase64char('A') == 0); + assert_se(unbase64char('Z') == 25); + assert_se(unbase64char('a') == 26); + assert_se(unbase64char('z') == 51); + assert_se(unbase64char('0') == 52); + assert_se(unbase64char('9') == 61); + assert_se(unbase64char('+') == 62); + assert_se(unbase64char('/') == 63); + assert_se(unbase64char('=') == -EINVAL); +} + +static void test_octchar(void) { + assert_se(octchar(00) == '0'); + assert_se(octchar(07) == '7'); +} + +static void test_unoctchar(void) { + assert_se(unoctchar('0') == 00); + assert_se(unoctchar('7') == 07); +} + +static void test_decchar(void) { + assert_se(decchar(0) == '0'); + assert_se(decchar(9) == '9'); +} + +static void test_undecchar(void) { + assert_se(undecchar('0') == 0); + assert_se(undecchar('9') == 9); +} + +static void test_unhexmem_one(const char *s, size_t l, int retval) { + _cleanup_free_ char *hex = NULL; + _cleanup_free_ void *mem = NULL; + size_t len; + + assert_se(unhexmem(s, l, &mem, &len) == retval); + if (retval == 0) { + char *answer; + + if (l == (size_t) -1) + l = strlen(s); + + assert_se(hex = hexmem(mem, len)); + answer = strndupa(strempty(s), l); + assert_se(streq(delete_chars(answer, WHITESPACE), hex)); + } +} + +static void test_unhexmem(void) { + const char *hex = "efa2149213"; + const char *hex_space = " e f a\n 2\r 14\n\r\t9\t2 \n1\r3 \r\r\t"; + const char *hex_invalid = "efa214921o"; + + test_unhexmem_one(NULL, 0, 0); + test_unhexmem_one("", 0, 0); + test_unhexmem_one("", (size_t) -1, 0); + test_unhexmem_one(" \n \t\r \t\t \n\n\n", (size_t) -1, 0); + test_unhexmem_one(hex_invalid, strlen(hex_invalid), -EINVAL); + test_unhexmem_one(hex_invalid, (size_t) - 1, -EINVAL); + test_unhexmem_one(hex, strlen(hex) - 1, -EPIPE); + test_unhexmem_one(hex, strlen(hex), 0); + test_unhexmem_one(hex, (size_t) -1, 0); + test_unhexmem_one(hex_space, strlen(hex_space), 0); + test_unhexmem_one(hex_space, (size_t) -1, 0); +} + +/* https://tools.ietf.org/html/rfc4648#section-10 */ +static void test_base32hexmem(void) { + char *b32; + + b32 = base32hexmem("", STRLEN(""), true); + assert_se(b32); + assert_se(streq(b32, "")); + free(b32); + + b32 = base32hexmem("f", STRLEN("f"), true); + assert_se(b32); + assert_se(streq(b32, "CO======")); + free(b32); + + b32 = base32hexmem("fo", STRLEN("fo"), true); + assert_se(b32); + assert_se(streq(b32, "CPNG====")); + free(b32); + + b32 = base32hexmem("foo", STRLEN("foo"), true); + assert_se(b32); + assert_se(streq(b32, "CPNMU===")); + free(b32); + + b32 = base32hexmem("foob", STRLEN("foob"), true); + assert_se(b32); + assert_se(streq(b32, "CPNMUOG=")); + free(b32); + + b32 = base32hexmem("fooba", STRLEN("fooba"), true); + assert_se(b32); + assert_se(streq(b32, "CPNMUOJ1")); + free(b32); + + b32 = base32hexmem("foobar", STRLEN("foobar"), true); + assert_se(b32); + assert_se(streq(b32, "CPNMUOJ1E8======")); + free(b32); + + b32 = base32hexmem("", STRLEN(""), false); + assert_se(b32); + assert_se(streq(b32, "")); + free(b32); + + b32 = base32hexmem("f", STRLEN("f"), false); + assert_se(b32); + assert_se(streq(b32, "CO")); + free(b32); + + b32 = base32hexmem("fo", STRLEN("fo"), false); + assert_se(b32); + assert_se(streq(b32, "CPNG")); + free(b32); + + b32 = base32hexmem("foo", STRLEN("foo"), false); + assert_se(b32); + assert_se(streq(b32, "CPNMU")); + free(b32); + + b32 = base32hexmem("foob", STRLEN("foob"), false); + assert_se(b32); + assert_se(streq(b32, "CPNMUOG")); + free(b32); + + b32 = base32hexmem("fooba", STRLEN("fooba"), false); + assert_se(b32); + assert_se(streq(b32, "CPNMUOJ1")); + free(b32); + + b32 = base32hexmem("foobar", STRLEN("foobar"), false); + assert_se(b32); + assert_se(streq(b32, "CPNMUOJ1E8")); + free(b32); +} + +static void test_unbase32hexmem_one(const char *hex, bool padding, int retval, const char *ans) { + _cleanup_free_ void *mem = NULL; + size_t len; + + assert_se(unbase32hexmem(hex, (size_t) -1, padding, &mem, &len) == retval); + if (retval == 0) { + char *str; + + str = strndupa(mem, len); + assert_se(streq(str, ans)); + } +} + +static void test_unbase32hexmem(void) { + test_unbase32hexmem_one("", true, 0, ""); + + test_unbase32hexmem_one("CO======", true, 0, "f"); + test_unbase32hexmem_one("CPNG====", true, 0, "fo"); + test_unbase32hexmem_one("CPNMU===", true, 0, "foo"); + test_unbase32hexmem_one("CPNMUOG=", true, 0, "foob"); + test_unbase32hexmem_one("CPNMUOJ1", true, 0, "fooba"); + test_unbase32hexmem_one("CPNMUOJ1E8======", true, 0, "foobar"); + + test_unbase32hexmem_one("A", true, -EINVAL, NULL); + test_unbase32hexmem_one("A=======", true, -EINVAL, NULL); + test_unbase32hexmem_one("AAA=====", true, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAAA==", true, -EINVAL, NULL); + test_unbase32hexmem_one("AB======", true, -EINVAL, NULL); + test_unbase32hexmem_one("AAAB====", true, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAB===", true, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAAAB=", true, -EINVAL, NULL); + + test_unbase32hexmem_one("XPNMUOJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CXNMUOJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPXMUOJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPNXUOJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPNMXOJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPNMUXJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPNMUOX1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPNMUOJX", true, -EINVAL, NULL); + + test_unbase32hexmem_one("", false, 0, ""); + test_unbase32hexmem_one("CO", false, 0, "f"); + test_unbase32hexmem_one("CPNG", false, 0, "fo"); + test_unbase32hexmem_one("CPNMU", false, 0, "foo"); + test_unbase32hexmem_one("CPNMUOG", false, 0, "foob"); + test_unbase32hexmem_one("CPNMUOJ1", false, 0, "fooba"); + test_unbase32hexmem_one("CPNMUOJ1E8", false, 0, "foobar"); + test_unbase32hexmem_one("CPNMUOG=", false, -EINVAL, NULL); + test_unbase32hexmem_one("CPNMUOJ1E8======", false, -EINVAL, NULL); + + test_unbase32hexmem_one("A", false, -EINVAL, NULL); + test_unbase32hexmem_one("AAA", false, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAAA", false, -EINVAL, NULL); + test_unbase32hexmem_one("AB", false, -EINVAL, NULL); + test_unbase32hexmem_one("AAAB", false, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAB", false, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAAAB", false, -EINVAL, NULL); +} + +/* https://tools.ietf.org/html/rfc4648#section-10 */ +static void test_base64mem(void) { + char *b64; + + assert_se(base64mem("", STRLEN(""), &b64) == 0); + assert_se(streq(b64, "")); + free(b64); + + assert_se(base64mem("f", STRLEN("f"), &b64) == 4); + assert_se(streq(b64, "Zg==")); + free(b64); + + assert_se(base64mem("fo", STRLEN("fo"), &b64) == 4); + assert_se(streq(b64, "Zm8=")); + free(b64); + + assert_se(base64mem("foo", STRLEN("foo"), &b64) == 4); + assert_se(streq(b64, "Zm9v")); + free(b64); + + assert_se(base64mem("foob", STRLEN("foob"), &b64) == 8); + assert_se(streq(b64, "Zm9vYg==")); + free(b64); + + assert_se(base64mem("fooba", STRLEN("fooba"), &b64) == 8); + assert_se(streq(b64, "Zm9vYmE=")); + free(b64); + + assert_se(base64mem("foobar", STRLEN("foobar"), &b64) == 8); + assert_se(streq(b64, "Zm9vYmFy")); + free(b64); +} + +static void test_unbase64mem_one(const char *input, const char *output, int ret) { + _cleanup_free_ void *buffer = NULL; + size_t size = 0; + + assert_se(unbase64mem(input, (size_t) -1, &buffer, &size) == ret); + + if (ret >= 0) { + assert_se(size == strlen(output)); + assert_se(memcmp(buffer, output, size) == 0); + assert_se(((char*) buffer)[size] == 0); + } +} + +static void test_unbase64mem(void) { + + test_unbase64mem_one("", "", 0); + test_unbase64mem_one("Zg==", "f", 0); + test_unbase64mem_one("Zm8=", "fo", 0); + test_unbase64mem_one("Zm9v", "foo", 0); + test_unbase64mem_one("Zm9vYg==", "foob", 0); + test_unbase64mem_one("Zm9vYmE=", "fooba", 0); + test_unbase64mem_one("Zm9vYmFy", "foobar", 0); + + test_unbase64mem_one(" ", "", 0); + test_unbase64mem_one(" \n\r ", "", 0); + test_unbase64mem_one(" Zg\n== ", "f", 0); + test_unbase64mem_one(" Zm 8=\r", "fo", 0); + test_unbase64mem_one(" Zm9\n\r\r\nv ", "foo", 0); + test_unbase64mem_one(" Z m9vYg==\n\r", "foob", 0); + test_unbase64mem_one(" Zm 9vYmE= ", "fooba", 0); + test_unbase64mem_one(" Z m9v YmFy ", "foobar", 0); + + test_unbase64mem_one("A", NULL, -EPIPE); + test_unbase64mem_one("A====", NULL, -EINVAL); + test_unbase64mem_one("AAB==", NULL, -EINVAL); + test_unbase64mem_one(" A A A B = ", NULL, -EINVAL); + test_unbase64mem_one(" Z m 8 = q u u x ", NULL, -ENAMETOOLONG); +} + +static void test_hexdump(void) { + uint8_t data[146]; + unsigned i; + + hexdump(stdout, NULL, 0); + hexdump(stdout, "", 0); + hexdump(stdout, "", 1); + hexdump(stdout, "x", 1); + hexdump(stdout, "x", 2); + hexdump(stdout, "foobar", 7); + hexdump(stdout, "f\nobar", 7); + hexdump(stdout, "xxxxxxxxxxxxxxxxxxxxyz", 23); + + for (i = 0; i < ELEMENTSOF(data); i++) + data[i] = i*2; + + hexdump(stdout, data, sizeof(data)); +} + +int main(int argc, char *argv[]) { + test_hexchar(); + test_unhexchar(); + test_base32hexchar(); + test_unbase32hexchar(); + test_base64char(); + test_unbase64char(); + test_octchar(); + test_unoctchar(); + test_decchar(); + test_undecchar(); + test_unhexmem(); + test_base32hexmem(); + test_unbase32hexmem(); + test_base64mem(); + test_unbase64mem(); + test_hexdump(); + + return 0; +} diff --git a/src/test/test-hostname-util.c b/src/test/test-hostname-util.c new file mode 100644 index 00000000..ec34f9cd --- /dev/null +++ b/src/test/test-hostname-util.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "fileio.h" +#include "hostname-util.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "util.h" + +static void test_hostname_is_valid(void) { + assert_se(hostname_is_valid("foobar", false)); + assert_se(hostname_is_valid("foobar.com", false)); + assert_se(!hostname_is_valid("foobar.com.", false)); + assert_se(hostname_is_valid("fooBAR", false)); + assert_se(hostname_is_valid("fooBAR.com", false)); + assert_se(!hostname_is_valid("fooBAR.", false)); + assert_se(!hostname_is_valid("fooBAR.com.", false)); + assert_se(!hostname_is_valid("fööbar", false)); + assert_se(!hostname_is_valid("", false)); + assert_se(!hostname_is_valid(".", false)); + assert_se(!hostname_is_valid("..", false)); + assert_se(!hostname_is_valid("foobar.", false)); + assert_se(!hostname_is_valid(".foobar", false)); + assert_se(!hostname_is_valid("foo..bar", false)); + assert_se(!hostname_is_valid("foo.bar..", false)); + assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", false)); + assert_se(!hostname_is_valid("au-xph5-rvgrdsb5hcxc-47et3a5vvkrc-server-wyoz4elpdpe3.openstack.local", false)); + + assert_se(hostname_is_valid("foobar", true)); + assert_se(hostname_is_valid("foobar.com", true)); + assert_se(hostname_is_valid("foobar.com.", true)); + assert_se(hostname_is_valid("fooBAR", true)); + assert_se(hostname_is_valid("fooBAR.com", true)); + assert_se(!hostname_is_valid("fooBAR.", true)); + assert_se(hostname_is_valid("fooBAR.com.", true)); + assert_se(!hostname_is_valid("fööbar", true)); + assert_se(!hostname_is_valid("", true)); + assert_se(!hostname_is_valid(".", true)); + assert_se(!hostname_is_valid("..", true)); + assert_se(!hostname_is_valid("foobar.", true)); + assert_se(!hostname_is_valid(".foobar", true)); + assert_se(!hostname_is_valid("foo..bar", true)); + assert_se(!hostname_is_valid("foo.bar..", true)); + assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true)); +} + +static void test_hostname_cleanup(void) { + char *s; + + s = strdupa("foobar"); + assert_se(streq(hostname_cleanup(s), "foobar")); + s = strdupa("foobar.com"); + assert_se(streq(hostname_cleanup(s), "foobar.com")); + s = strdupa("foobar.com."); + assert_se(streq(hostname_cleanup(s), "foobar.com")); + s = strdupa("foo-bar.-com-."); + assert_se(streq(hostname_cleanup(s), "foo-bar.com")); + s = strdupa("foo-bar-.-com-."); + assert_se(streq(hostname_cleanup(s), "foo-bar--com")); + s = strdupa("--foo-bar.-com"); + assert_se(streq(hostname_cleanup(s), "foo-bar.com")); + s = strdupa("fooBAR"); + assert_se(streq(hostname_cleanup(s), "fooBAR")); + s = strdupa("fooBAR.com"); + assert_se(streq(hostname_cleanup(s), "fooBAR.com")); + s = strdupa("fooBAR."); + assert_se(streq(hostname_cleanup(s), "fooBAR")); + s = strdupa("fooBAR.com."); + assert_se(streq(hostname_cleanup(s), "fooBAR.com")); + s = strdupa("fööbar"); + assert_se(streq(hostname_cleanup(s), "fbar")); + s = strdupa(""); + assert_se(isempty(hostname_cleanup(s))); + s = strdupa("."); + assert_se(isempty(hostname_cleanup(s))); + s = strdupa(".."); + assert_se(isempty(hostname_cleanup(s))); + s = strdupa("foobar."); + assert_se(streq(hostname_cleanup(s), "foobar")); + s = strdupa(".foobar"); + assert_se(streq(hostname_cleanup(s), "foobar")); + s = strdupa("foo..bar"); + assert_se(streq(hostname_cleanup(s), "foo.bar")); + s = strdupa("foo.bar.."); + assert_se(streq(hostname_cleanup(s), "foo.bar")); + s = strdupa("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + assert_se(streq(hostname_cleanup(s), "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")); + s = strdupa("xxxx........xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + assert_se(streq(hostname_cleanup(s), "xxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")); +} + +static void test_read_etc_hostname(void) { + char path[] = "/tmp/hostname.XXXXXX"; + char *hostname; + int fd; + + fd = mkostemp_safe(path); + assert(fd > 0); + close(fd); + + /* simple hostname */ + assert_se(write_string_file(path, "foo", WRITE_STRING_FILE_CREATE) == 0); + assert_se(read_etc_hostname(path, &hostname) == 0); + assert_se(streq(hostname, "foo")); + hostname = mfree(hostname); + + /* with comment */ + assert_se(write_string_file(path, "# comment\nfoo", WRITE_STRING_FILE_CREATE) == 0); + assert_se(read_etc_hostname(path, &hostname) == 0); + assert_se(hostname); + assert_se(streq(hostname, "foo")); + hostname = mfree(hostname); + + /* with comment and extra whitespace */ + assert_se(write_string_file(path, "# comment\n\n foo ", WRITE_STRING_FILE_CREATE) == 0); + assert_se(read_etc_hostname(path, &hostname) == 0); + assert_se(hostname); + assert_se(streq(hostname, "foo")); + hostname = mfree(hostname); + + /* cleans up name */ + assert_se(write_string_file(path, "!foo/bar.com", WRITE_STRING_FILE_CREATE) == 0); + assert_se(read_etc_hostname(path, &hostname) == 0); + assert_se(hostname); + assert_se(streq(hostname, "foobar.com")); + hostname = mfree(hostname); + + /* no value set */ + hostname = (char*) 0x1234; + assert_se(write_string_file(path, "# nothing here\n", WRITE_STRING_FILE_CREATE) == 0); + assert_se(read_etc_hostname(path, &hostname) == -ENOENT); + assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */ + + /* nonexisting file */ + assert_se(read_etc_hostname("/non/existing", &hostname) == -ENOENT); + assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */ + + unlink(path); +} + +int main(int argc, char *argv[]) { + log_parse_environment(); + log_open(); + + test_hostname_is_valid(); + test_hostname_cleanup(); + test_read_etc_hostname(); + + return 0; +} diff --git a/src/test/test-hostname.c b/src/test/test-hostname.c new file mode 100644 index 00000000..710c0572 --- /dev/null +++ b/src/test/test-hostname.c @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "hostname-setup.h" +#include "util.h" + +int main(int argc, char* argv[]) { + int r; + + r = hostname_setup(); + if (r < 0) + log_error_errno(r, "hostname: %m"); + + return 0; +} diff --git a/src/test/test-id128.c b/src/test/test-id128.c new file mode 100644 index 00000000..4d7513f6 --- /dev/null +++ b/src/test/test-id128.c @@ -0,0 +1,161 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "id128-util.h" +#include "macro.h" +#include "string-util.h" +#include "tmpfile-util.h" +#include "util.h" + +#define ID128_WALDI SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10) +#define STR_WALDI "0102030405060708090a0b0c0d0e0f10" +#define UUID_WALDI "01020304-0506-0708-090a-0b0c0d0e0f10" + +int main(int argc, char *argv[]) { + sd_id128_t id, id2; + char t[33], q[37]; + _cleanup_free_ char *b = NULL; + _cleanup_close_ int fd = -1; + int r; + + assert_se(sd_id128_randomize(&id) == 0); + printf("random: %s\n", sd_id128_to_string(id, t)); + + assert_se(sd_id128_from_string(t, &id2) == 0); + assert_se(sd_id128_equal(id, id2)); + + if (sd_booted() > 0) { + assert_se(sd_id128_get_machine(&id) == 0); + printf("machine: %s\n", sd_id128_to_string(id, t)); + + assert_se(sd_id128_get_boot(&id) == 0); + printf("boot: %s\n", sd_id128_to_string(id, t)); + } + + printf("waldi: %s\n", sd_id128_to_string(ID128_WALDI, t)); + assert_se(streq(t, STR_WALDI)); + + assert_se(asprintf(&b, SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 32); + printf("waldi2: %s\n", b); + assert_se(streq(t, b)); + + printf("waldi3: %s\n", id128_to_uuid_string(ID128_WALDI, q)); + assert_se(streq(q, UUID_WALDI)); + + b = mfree(b); + assert_se(asprintf(&b, SD_ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(ID128_WALDI)) == 36); + printf("waldi4: %s\n", b); + assert_se(streq(q, b)); + + assert_se(sd_id128_from_string(STR_WALDI, &id) >= 0); + assert_se(sd_id128_equal(id, ID128_WALDI)); + + assert_se(sd_id128_from_string(UUID_WALDI, &id) >= 0); + assert_se(sd_id128_equal(id, ID128_WALDI)); + + assert_se(sd_id128_from_string("", &id) < 0); + assert_se(sd_id128_from_string("01020304-0506-0708-090a-0b0c0d0e0f101", &id) < 0); + assert_se(sd_id128_from_string("01020304-0506-0708-090a-0b0c0d0e0f10-", &id) < 0); + assert_se(sd_id128_from_string("01020304-0506-0708-090a0b0c0d0e0f10", &id) < 0); + assert_se(sd_id128_from_string("010203040506-0708-090a-0b0c0d0e0f10", &id) < 0); + + assert_se(id128_is_valid(STR_WALDI)); + assert_se(id128_is_valid(UUID_WALDI)); + assert_se(!id128_is_valid("")); + assert_se(!id128_is_valid("01020304-0506-0708-090a-0b0c0d0e0f101")); + assert_se(!id128_is_valid("01020304-0506-0708-090a-0b0c0d0e0f10-")); + assert_se(!id128_is_valid("01020304-0506-0708-090a0b0c0d0e0f10")); + assert_se(!id128_is_valid("010203040506-0708-090a-0b0c0d0e0f10")); + + fd = open_tmpfile_unlinkable(NULL, O_RDWR|O_CLOEXEC); + assert_se(fd >= 0); + + /* First, write as UUID */ + assert_se(sd_id128_randomize(&id) >= 0); + assert_se(id128_write_fd(fd, ID128_UUID, id, false) >= 0); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_ANY, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + /* Second, write as plain */ + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(ftruncate(fd, 0) >= 0); + + assert_se(sd_id128_randomize(&id) >= 0); + assert_se(id128_write_fd(fd, ID128_PLAIN, id, false) >= 0); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_UUID, &id2) == -EINVAL); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_ANY, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + /* Third, write plain without trailing newline */ + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(ftruncate(fd, 0) >= 0); + + assert_se(sd_id128_randomize(&id) >= 0); + assert_se(write(fd, sd_id128_to_string(id, t), 32) == 32); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_UUID, &id2) == -EINVAL); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + /* Third, write UUID without trailing newline */ + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(ftruncate(fd, 0) >= 0); + + assert_se(sd_id128_randomize(&id) >= 0); + assert_se(write(fd, id128_to_uuid_string(id, q), 36) == 36); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + r = sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id); + if (r == -EOPNOTSUPP) + log_info("khash not supported on this kernel, skipping sd_id128_get_machine_app_specific() checks"); + else { + assert_se(r >= 0); + assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(51,df,0b,4b,c3,b0,4c,97,80,e2,99,b9,8c,a3,73,b8), &id2) >= 0); + assert_se(!sd_id128_equal(id, id2)); + } + + /* Query the invocation ID */ + r = sd_id128_get_invocation(&id); + if (r < 0) + log_warning_errno(r, "Failed to get invocation ID, ignoring: %m"); + else + log_info("Invocation ID: " SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)); + + return 0; +} diff --git a/src/test/test-in-addr-util.c b/src/test/test-in-addr-util.c new file mode 100644 index 00000000..916bd35f --- /dev/null +++ b/src/test/test-in-addr-util.c @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "log.h" +#include "strv.h" +#include "in-addr-util.h" + +static void test_in_addr_prefix_from_string_one( + const char *p, + int family, + int ret, + const union in_addr_union *u, + unsigned char prefixlen, + int ret_refuse, + unsigned char prefixlen_refuse, + int ret_legacy, + unsigned char prefixlen_legacy) { + + union in_addr_union q; + unsigned char l; + int f, r; + + r = in_addr_prefix_from_string(p, family, &q, &l); + assert_se(r == ret); + + if (r < 0) + return; + + assert_se(in_addr_equal(family, &q, u)); + assert_se(l == prefixlen); + + r = in_addr_prefix_from_string_auto(p, &f, &q, &l); + assert_se(r >= 0); + + assert_se(f == family); + assert_se(in_addr_equal(family, &q, u)); + assert_se(l == prefixlen); + + r = in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_REFUSE, &f, &q, &l); + assert_se(r == ret_refuse); + + if (r >= 0) { + assert_se(f == family); + assert_se(in_addr_equal(family, &q, u)); + assert_se(l == prefixlen_refuse); + } + + r = in_addr_prefix_from_string_auto_internal(p, PREFIXLEN_LEGACY, &f, &q, &l); + assert_se(r == ret_legacy); + + if (r >= 0) { + assert_se(f == family); + assert_se(in_addr_equal(family, &q, u)); + assert_se(l == prefixlen_legacy); + } +} + +static void test_in_addr_prefix_from_string(void) { + test_in_addr_prefix_from_string_one("", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0); + test_in_addr_prefix_from_string_one("/", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0); + test_in_addr_prefix_from_string_one("/8", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0); + test_in_addr_prefix_from_string_one("1.2.3.4", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, -ENOANO, 0, 0, 8); + test_in_addr_prefix_from_string_one("1.2.3.4/0", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 0, 0, 0, 0, 0); + test_in_addr_prefix_from_string_one("1.2.3.4/1", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 1, 0, 1, 0, 1); + test_in_addr_prefix_from_string_one("1.2.3.4/2", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 2, 0, 2, 0, 2); + test_in_addr_prefix_from_string_one("1.2.3.4/32", AF_INET, 0, &(union in_addr_union) { .in = (struct in_addr) { .s_addr = htobe32(0x01020304) } }, 32, 0, 32, 0, 32); + test_in_addr_prefix_from_string_one("1.2.3.4/33", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0); + test_in_addr_prefix_from_string_one("1.2.3.4/-1", AF_INET, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0); + test_in_addr_prefix_from_string_one("::1", AF_INET, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0); + + test_in_addr_prefix_from_string_one("", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0); + test_in_addr_prefix_from_string_one("/", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0); + test_in_addr_prefix_from_string_one("/8", AF_INET6, -EINVAL, NULL, 0, -EINVAL, 0, -EINVAL, 0); + test_in_addr_prefix_from_string_one("::1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, -ENOANO, 0, 0, 0); + test_in_addr_prefix_from_string_one("::1/0", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 0, 0, 0, 0, 0); + test_in_addr_prefix_from_string_one("::1/1", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 1, 0, 1, 0, 1); + test_in_addr_prefix_from_string_one("::1/2", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 2, 0, 2, 0, 2); + test_in_addr_prefix_from_string_one("::1/32", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 32, 0, 32, 0, 32); + test_in_addr_prefix_from_string_one("::1/33", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 33, 0, 33, 0, 33); + test_in_addr_prefix_from_string_one("::1/64", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 64, 0, 64, 0, 64); + test_in_addr_prefix_from_string_one("::1/128", AF_INET6, 0, &(union in_addr_union) { .in6 = IN6ADDR_LOOPBACK_INIT }, 128, 0, 128, 0, 128); + test_in_addr_prefix_from_string_one("::1/129", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0); + test_in_addr_prefix_from_string_one("::1/-1", AF_INET6, -ERANGE, NULL, 0, -ERANGE, 0, -ERANGE, 0); +} + +static void test_in_addr_prefix_to_string_valid(int family, const char *p) { + _cleanup_free_ char *str = NULL; + union in_addr_union u; + unsigned char l; + + log_info("/* %s */", p); + + assert_se(in_addr_prefix_from_string(p, family, &u, &l) >= 0); + assert_se(in_addr_prefix_to_string(family, &u, l, &str) >= 0); + assert_se(streq(str, p)); +} + +static void test_in_addr_prefix_to_string_unoptimized(int family, const char *p) { + _cleanup_free_ char *str1 = NULL, *str2 = NULL; + union in_addr_union u1, u2; + unsigned char len1, len2; + + log_info("/* %s */", p); + + assert_se(in_addr_prefix_from_string(p, family, &u1, &len1) >= 0); + assert_se(in_addr_prefix_to_string(family, &u1, len1, &str1) >= 0); + assert_se(in_addr_prefix_from_string(str1, family, &u2, &len2) >= 0); + assert_se(in_addr_prefix_to_string(family, &u2, len2, &str2) >= 0); + + assert_se(streq(str1, str2)); + assert_se(len1 == len2); + assert_se(in_addr_equal(family, &u1, &u2) > 0); +} + +static void test_in_addr_prefix_to_string(void) { + test_in_addr_prefix_to_string_valid(AF_INET, "0.0.0.0/32"); + test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/0"); + test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/24"); + test_in_addr_prefix_to_string_valid(AF_INET, "1.2.3.4/32"); + test_in_addr_prefix_to_string_valid(AF_INET, "255.255.255.255/32"); + + test_in_addr_prefix_to_string_valid(AF_INET6, "::1/128"); + test_in_addr_prefix_to_string_valid(AF_INET6, "fd00:abcd::1/64"); + test_in_addr_prefix_to_string_valid(AF_INET6, "fd00:abcd::1234:1/64"); + test_in_addr_prefix_to_string_valid(AF_INET6, "1111:2222:3333:4444:5555:6666:7777:8888/128"); + + test_in_addr_prefix_to_string_unoptimized(AF_INET, "0.0.0.0"); + test_in_addr_prefix_to_string_unoptimized(AF_INET, "192.168.0.1"); + + test_in_addr_prefix_to_string_unoptimized(AF_INET6, "fd00:0000:0000:0000:0000:0000:0000:0001/64"); + test_in_addr_prefix_to_string_unoptimized(AF_INET6, "fd00:1111::0000:2222:3333:4444:0001/64"); +} + +static void test_in_addr_random_prefix(void) { + _cleanup_free_ char *str = NULL; + union in_addr_union a; + + assert_se(in_addr_from_string(AF_INET, "192.168.10.1", &a) >= 0); + + assert_se(in_addr_random_prefix(AF_INET, &a, 31, 32) >= 0); + assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0); + assert_se(STR_IN_SET(str, "192.168.10.0", "192.168.10.1")); + str = mfree(str); + + assert_se(in_addr_random_prefix(AF_INET, &a, 24, 26) >= 0); + assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0); + assert_se(startswith(str, "192.168.10.")); + str = mfree(str); + + assert_se(in_addr_random_prefix(AF_INET, &a, 16, 24) >= 0); + assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0); + assert_se(fnmatch("192.168.[0-9]*.0", str, 0) == 0); + str = mfree(str); + + assert_se(in_addr_random_prefix(AF_INET, &a, 8, 24) >= 0); + assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0); + assert_se(fnmatch("192.[0-9]*.[0-9]*.0", str, 0) == 0); + str = mfree(str); + + assert_se(in_addr_random_prefix(AF_INET, &a, 8, 16) >= 0); + assert_se(in_addr_to_string(AF_INET, &a, &str) >= 0); + assert_se(fnmatch("192.[0-9]*.0.0", str, 0) == 0); + str = mfree(str); + + assert_se(in_addr_from_string(AF_INET6, "fd00::1", &a) >= 0); + + assert_se(in_addr_random_prefix(AF_INET6, &a, 16, 64) >= 0); + assert_se(in_addr_to_string(AF_INET6, &a, &str) >= 0); + assert_se(startswith(str, "fd00:")); + str = mfree(str); + + assert_se(in_addr_random_prefix(AF_INET6, &a, 8, 16) >= 0); + assert_se(in_addr_to_string(AF_INET6, &a, &str) >= 0); + assert_se(fnmatch("fd??::", str, 0) == 0); + str = mfree(str); +} + +int main(int argc, char *argv[]) { + test_in_addr_prefix_from_string(); + test_in_addr_random_prefix(); + test_in_addr_prefix_to_string(); + + return 0; +} diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c new file mode 100644 index 00000000..323e1124 --- /dev/null +++ b/src/test/test-install-root.c @@ -0,0 +1,1084 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "fileio.h" +#include "install.h" +#include "mkdir.h" +#include "rm-rf.h" +#include "special.h" +#include "string-util.h" +#include "tests.h" + +static void test_basic_mask_and_enable(const char *root) { + const char *p; + UnitFileState state; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + + test_setup_logging(LOG_DEBUG); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/a.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", NULL) >= 0); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, "/usr/lib/systemd/system/b.service"); + assert_se(symlink("a.service", p) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) >= 0); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, "/usr/lib/systemd/system/c.service"); + assert_se(symlink("/usr/lib/systemd/system/a.service", p) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) >= 0); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, "/usr/lib/systemd/system/d.service"); + assert_se(symlink("c.service", p) >= 0); + + /* This one is interesting, as d follows a relative, then an absolute symlink */ + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) >= 0); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_mask(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/dev/null")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service"); + assert_se(streq(changes[0].path, p)); + + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_MASKED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_MASKED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_MASKED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_MASKED); + + /* Enabling a masked unit should fail! */ + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) == -ERFKILL); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_unmask(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/a.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) == 1); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + + /* Enabling it again should succeed but be a NOP */ + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 0); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + /* Disabling a disabled unit must succeed but be a NOP */ + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("a.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 0); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + /* Let's enable this indirectly via a symlink */ + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("d.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/a.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + + /* Let's try to reenable */ + + assert_se(unit_file_reenable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("b.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 2); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/a.service"); + assert_se(streq(changes[0].path, p)); + assert_se(changes[1].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[1].source, "/usr/lib/systemd/system/a.service")); + assert_se(streq(changes[1].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "a.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED); +} + +static void test_linked_units(const char *root) { + const char *p, *q; + UnitFileState state; + UnitFileChange *changes = NULL; + size_t n_changes = 0, i; + + /* + * We'll test three cases here: + * + * a) a unit file in /opt, that we use "systemctl link" and + * "systemctl enable" on to make it available to the system + * + * b) a unit file in /opt, that is statically linked into + * /usr/lib/systemd/system, that "enable" should work on + * correctly. + * + * c) a unit file in /opt, that is linked into + * /etc/systemd/system, and where "enable" should result in + * -ELOOP, since using information from /etc to generate + * information in /etc should not be allowed. + */ + + p = strjoina(root, "/opt/linked.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/opt/linked2.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/opt/linked3.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", NULL) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", NULL) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/linked2.service"); + assert_se(symlink("/opt/linked2.service", p) >= 0); + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked3.service"); + assert_se(symlink("/opt/linked3.service", p) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked2.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked3.service", &state) >= 0 && state == UNIT_FILE_LINKED); + + /* First, let's link the unit into the search path */ + assert_se(unit_file_link(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/opt/linked.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_LINKED); + + /* Let's unlink it from the search path again */ + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT); + + /* Now, let's not just link it, but also enable it */ + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("/opt/linked.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 2); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service"); + q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); + for (i = 0 ; i < n_changes; i++) { + assert_se(changes[i].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[i].source, "/opt/linked.service")); + + if (p && streq(changes[i].path, p)) + p = NULL; + else if (q && streq(changes[i].path, q)) + q = NULL; + else + assert_not_reached("wut?"); + } + assert(!p && !q); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + + /* And let's unlink it again */ + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 2); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked.service"); + q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked.service"); + for (i = 0; i < n_changes; i++) { + assert_se(changes[i].type == UNIT_FILE_UNLINK); + + if (p && streq(changes[i].path, p)) + p = NULL; + else if (q && streq(changes[i].path, q)) + q = NULL; + else + assert_not_reached("wut?"); + } + assert(!p && !q); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "linked.service", NULL) == -ENOENT); + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked2.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 2); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/linked2.service"); + q = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/linked2.service"); + for (i = 0 ; i < n_changes; i++) { + assert_se(changes[i].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[i].source, "/opt/linked2.service")); + + if (p && streq(changes[i].path, p)) + p = NULL; + else if (q && streq(changes[i].path, q)) + q = NULL; + else + assert_not_reached("wut?"); + } + assert(!p && !q); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("linked3.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(startswith(changes[0].path, root)); + assert_se(endswith(changes[0].path, "linked3.service")); + assert_se(streq(changes[0].source, "/opt/linked3.service")); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; +} + +static void test_default(const char *root) { + _cleanup_free_ char *def = NULL; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + const char *p; + + p = strjoina(root, "/usr/lib/systemd/system/test-default-real.target"); + assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/test-default.target"); + assert_se(symlink("test-default-real.target", p) >= 0); + + assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT); + + assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, 0, root, "idontexist.target", &changes, &n_changes) == -ENOENT); + assert_se(n_changes == 1); + assert_se(changes[0].type == -ENOENT); + assert_se(streq_ptr(changes[0].path, "idontexist.target")); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) == -ENOENT); + + assert_se(unit_file_set_default(UNIT_FILE_SYSTEM, 0, root, "test-default.target", &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/test-default-real.target")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH "/" SPECIAL_DEFAULT_TARGET); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_default(UNIT_FILE_SYSTEM, root, &def) >= 0); + assert_se(streq_ptr(def, "test-default-real.target")); +} + +static void test_add_dependency(const char *root) { + UnitFileChange *changes = NULL; + size_t n_changes = 0; + const char *p; + + p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-target.target"); + assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-target.target"); + assert_se(symlink("real-add-dependency-test-target.target", p) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/real-add-dependency-test-service.service"); + assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/add-dependency-test-service.service"); + assert_se(symlink("real-add-dependency-test-service.service", p) >= 0); + + assert_se(unit_file_add_dependency(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("add-dependency-test-service.service"), "add-dependency-test-target.target", UNIT_WANTS, &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/real-add-dependency-test-service.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/real-add-dependency-test-target.target.wants/real-add-dependency-test-service.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; +} + +static void test_template_enable(const char *root) { + UnitFileChange *changes = NULL; + size_t n_changes = 0; + UnitFileState state; + const char *p; + + log_info("== %s ==", __func__); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/template@.service"); + assert_se(write_string_file(p, + "[Install]\n" + "DefaultInstance=def\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/template-symlink@.service"); + assert_se(symlink("template@.service", p) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + log_info("== %s with template@.service enabled ==", __func__); + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@def.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + log_info("== %s with template@foo.service enabled ==", __func__); + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@foo.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template@foo.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + log_info("== %s with template-symlink@quux.service enabled ==", __func__); + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("template-symlink@quux.service"), &changes, &n_changes) >= 0); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/template@.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/template@quux.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "template-symlink@quux.service", &state) >= 0 && state == UNIT_FILE_ENABLED); +} + +static void test_indirect(const char *root) { + UnitFileChange *changes = NULL; + size_t n_changes = 0; + UnitFileState state; + const char *p; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/indirecta.service"); + assert_se(write_string_file(p, + "[Install]\n" + "Also=indirectb.service\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/indirectb.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/indirectc.service"); + assert_se(symlink("indirecta.service", p) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/indirectb.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirecta.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectb.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "indirectc.service", &state) >= 0 && state == UNIT_FILE_INDIRECT); + + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("indirectc.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/indirectb.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; +} + +static void test_preset_and_list(const char *root) { + UnitFileChange *changes = NULL; + size_t n_changes = 0, i; + const char *p, *q; + UnitFileState state; + bool got_yes = false, got_no = false; + Iterator j; + UnitFileList *fl; + Hashmap *h; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/preset-no.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset"); + assert_se(write_string_file(p, + "enable *-yes.*\n" + "disable *\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-yes.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/preset-yes.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-yes.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("preset-no.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); + assert_se(n_changes == 0); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, 0, root, UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); + + assert_se(n_changes > 0); + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/preset-yes.service"); + + for (i = 0; i < n_changes; i++) { + + if (changes[i].type == UNIT_FILE_SYMLINK) { + assert_se(streq(changes[i].source, "/usr/lib/systemd/system/preset-yes.service")); + assert_se(streq(changes[i].path, p)); + } else + assert_se(changes[i].type == UNIT_FILE_UNLINK); + } + + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-yes.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "preset-no.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(h = hashmap_new(&string_hash_ops)); + assert_se(unit_file_get_list(UNIT_FILE_SYSTEM, root, h, NULL, NULL) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/preset-yes.service"); + q = strjoina(root, "/usr/lib/systemd/system/preset-no.service"); + + HASHMAP_FOREACH(fl, h, j) { + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, basename(fl->path), &state) >= 0); + assert_se(fl->state == state); + + if (streq(fl->path, p)) { + got_yes = true; + assert_se(fl->state == UNIT_FILE_ENABLED); + } else if (streq(fl->path, q)) { + got_no = true; + assert_se(fl->state == UNIT_FILE_DISABLED); + } else + assert_se(IN_SET(fl->state, UNIT_FILE_DISABLED, UNIT_FILE_STATIC, UNIT_FILE_INDIRECT)); + } + + unit_file_list_free(h); + + assert_se(got_yes && got_no); +} + +static void test_revert(const char *root) { + const char *p; + UnitFileState state; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + + assert(root); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "yy.service", NULL) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/xx.service"); + assert_se(write_string_file(p, "# Empty\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", NULL) >= 0); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "xx.service", &state) >= 0 && state == UNIT_FILE_STATIC); + + /* Initially there's nothing to revert */ + assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 0); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service"); + assert_se(write_string_file(p, "# Empty override\n", WRITE_STRING_FILE_CREATE) >= 0); + + /* Revert the override file */ + assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d/dropin.conf"); + assert_se(mkdir_parents(p, 0755) >= 0); + assert_se(write_string_file(p, "# Empty dropin\n", WRITE_STRING_FILE_CREATE) >= 0); + + /* Revert the dropin file */ + assert_se(unit_file_revert(UNIT_FILE_SYSTEM, root, STRV_MAKE("xx.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 2); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + assert_se(streq(changes[0].path, p)); + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/xx.service.d"); + assert_se(changes[1].type == UNIT_FILE_UNLINK); + assert_se(streq(changes[1].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; +} + +static void test_preset_order(const char *root) { + UnitFileChange *changes = NULL; + size_t n_changes = 0; + const char *p; + UnitFileState state; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/prefix-1.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/prefix-2.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset"); + assert_se(write_string_file(p, + "enable prefix-1.service\n" + "disable prefix-*.service\n" + "enable prefix-2.service\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("prefix-1.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/prefix-1.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/prefix-1.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("prefix-2.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); + assert_se(n_changes == 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "prefix-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED); +} + +static void test_static_instance(const char *root) { + UnitFileState state; + const char *p; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/static-instance@.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, "/usr/lib/systemd/system/static-instance@foo.service"); + assert_se(symlink("static-instance@.service", p) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "static-instance@foo.service", &state) >= 0 && state == UNIT_FILE_STATIC); +} + +static void test_with_dropin(const char *root) { + const char *p; + UnitFileState state; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1.service.d/dropin.conf"); + assert_se(mkdir_parents(p, 0755) >= 0); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2.service.d/dropin.conf"); + assert_se(mkdir_parents(p, 0755) >= 0); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-3.service.d/dropin.conf"); + assert_se(mkdir_parents(p, 0755) >= 0); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-4a.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-4a.service.d/dropin.conf"); + assert_se(mkdir_parents(p, 0755) >= 0); + assert_se(write_string_file(p, + "[Install]\n" + "Also=with-dropin-4b.service\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-4b.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-1.service"), &changes, &n_changes) == 1); + assert_se(n_changes == 2); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(changes[1].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-1.service")); + assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-1.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-1.service"); + assert_se(streq(changes[0].path, p)); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-1.service"); + assert_se(streq(changes[1].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2.service"), &changes, &n_changes) == 1); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(n_changes == 2); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(changes[1].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service")); + assert_se(streq(changes[1].source, SYSTEM_CONFIG_UNIT_PATH"/with-dropin-2.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2.service"); + assert_se(streq(changes[0].path, p)); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-2.service"); + assert_se(streq(changes[1].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-3.service"), &changes, &n_changes) == 1); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(n_changes == 2); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(changes[1].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-3.service")); + assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-3.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-3.service"); + assert_se(streq(changes[0].path, p)); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-3.service"); + assert_se(streq(changes[1].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-4a.service"), &changes, &n_changes) == 2); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(n_changes == 2); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(changes[1].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-4a.service")); + assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-4b.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-4a.service"); + assert_se(streq(changes[0].path, p)); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-4b.service"); + assert_se(streq(changes[1].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4a.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-4b.service", &state) >= 0 && state == UNIT_FILE_ENABLED); +} + +static void test_with_dropin_template(const char *root) { + const char *p; + UnitFileState state; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@.service", &state) == -ENOENT); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@.service", &state) == -ENOENT); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1@.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-1@.service.d/dropin.conf"); + assert_se(mkdir_parents(p, 0755) >= 0); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2@.service"); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-2@instance-1.service.d/dropin.conf"); + assert_se(mkdir_parents(p, 0755) >= 0); + assert_se(write_string_file(p, + "[Install]\n" + "WantedBy=graphical.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3@.service"); + assert_se(write_string_file(p, + "[Install]\n" + "DefaultInstance=instance-1\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system/with-dropin-3@.service.d/dropin.conf"); + assert_se(mkdir_parents(p, 0755) >= 0); + assert_se(write_string_file(p, + "[Install]\n" + "DefaultInstance=instance-2\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-1@instance-1.service"), &changes, &n_changes) == 1); + assert_se(n_changes == 2); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(changes[1].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-1@.service")); + assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-1@.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-1@instance-1.service"); + assert_se(streq(changes[0].path, p)); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-1@instance-1.service"); + assert_se(streq(changes[1].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2@instance-1.service"), &changes, &n_changes) == 1); + assert_se(n_changes == 2); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(changes[1].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-2@.service")); + assert_se(streq(changes[1].source, "/usr/lib/systemd/system/with-dropin-2@.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2@instance-1.service"); + assert_se(streq(changes[0].path, p)); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/graphical.target.wants/with-dropin-2@instance-1.service"); + assert_se(streq(changes[1].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-2@instance-2.service"), &changes, &n_changes) == 1); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-2@.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-2@instance-2.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("with-dropin-3@.service"), &changes, &n_changes) == 1); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + assert_se(streq(changes[0].source, "/usr/lib/systemd/system/with-dropin-3@.service")); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/with-dropin-3@instance-2.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-1@instance-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@instance-1.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-2@instance-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@instance-1.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "with-dropin-3@instance-2.service", &state) >= 0 && state == UNIT_FILE_ENABLED); +} + +static void test_preset_multiple_instances(const char *root) { + UnitFileChange *changes = NULL; + size_t n_changes = 0; + const char *p; + UnitFileState state; + + /* Set up template service files and preset file */ + p = strjoina(root, "/usr/lib/systemd/system/foo@.service"); + assert_se(write_string_file(p, + "[Install]\n" + "DefaultInstance=def\n" + "WantedBy=multi-user.target\n", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + p = strjoina(root, "/usr/lib/systemd/system-preset/test.preset"); + assert_se(write_string_file(p, + "enable foo@.service bar0 bar1 bartest\n" + "enable emptylist@.service\n" /* This line ensures the old functionality for templated unit still works */ + "disable *\n" , WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + /* Preset a single instantiated unit specified in the list */ + assert_se(unit_file_preset(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("foo@bar0.service"), UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_SYMLINK); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/foo@bar0.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + assert_se(unit_file_disable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("foo@bar0.service"), &changes, &n_changes) >= 0); + assert_se(n_changes == 1); + assert_se(changes[0].type == UNIT_FILE_UNLINK); + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/multi-user.target.wants/foo@bar0.service"); + assert_se(streq(changes[0].path, p)); + unit_file_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + /* Check for preset-all case, only instances on the list should be enabled, not including the default instance */ + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar1.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bartest.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + + assert_se(unit_file_preset_all(UNIT_FILE_SYSTEM, 0, root, UNIT_FILE_PRESET_FULL, &changes, &n_changes) >= 0); + assert_se(n_changes > 0); + + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@def.service", &state) >= 0 && state == UNIT_FILE_DISABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar0.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bar1.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "foo@bartest.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + + unit_file_changes_free(changes, n_changes); +} + +int main(int argc, char *argv[]) { + char root[] = "/tmp/rootXXXXXX"; + const char *p; + + assert_se(mkdtemp(root)); + + p = strjoina(root, "/usr/lib/systemd/system/"); + assert_se(mkdir_p(p, 0755) >= 0); + + p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/"); + assert_se(mkdir_p(p, 0755) >= 0); + + p = strjoina(root, "/run/systemd/system/"); + assert_se(mkdir_p(p, 0755) >= 0); + + p = strjoina(root, "/opt/"); + assert_se(mkdir_p(p, 0755) >= 0); + + p = strjoina(root, "/usr/lib/systemd/system-preset/"); + assert_se(mkdir_p(p, 0755) >= 0); + + test_basic_mask_and_enable(root); + test_linked_units(root); + test_default(root); + test_add_dependency(root); + test_template_enable(root); + test_indirect(root); + test_preset_and_list(root); + test_preset_order(root); + test_preset_multiple_instances(root); + test_revert(root); + test_static_instance(root); + test_with_dropin(root); + test_with_dropin_template(root); + + assert_se(rm_rf(root, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); + + return 0; +} diff --git a/src/test/test-install.c b/src/test/test-install.c new file mode 100644 index 00000000..62daaccd --- /dev/null +++ b/src/test/test-install.c @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "install.h" +#include "tests.h" + +static void dump_changes(UnitFileChange *c, unsigned n) { + unsigned i; + + assert_se(n == 0 || c); + + for (i = 0; i < n; i++) { + if (c[i].type == UNIT_FILE_UNLINK) + printf("rm '%s'\n", c[i].path); + else if (c[i].type == UNIT_FILE_SYMLINK) + printf("ln -s '%s' '%s'\n", c[i].source, c[i].path); + } +} + +int main(int argc, char* argv[]) { + Hashmap *h; + UnitFileList *p; + Iterator i; + int r; + const char *const files[] = { "avahi-daemon.service", NULL }; + const char *const files2[] = { "/home/lennart/test.service", NULL }; + UnitFileChange *changes = NULL; + size_t n_changes = 0; + UnitFileState state = 0; + + test_setup_logging(LOG_DEBUG); + + h = hashmap_new(&string_hash_ops); + r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL); + assert_se(r == 0); + + HASHMAP_FOREACH(p, h, i) { + UnitFileState s = _UNIT_FILE_STATE_INVALID; + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(p->path), &s); + + assert_se((r < 0 && p->state == UNIT_FILE_BAD) || + (p->state == s)); + + fprintf(stderr, "%s (%s)\n", + p->path, + unit_file_state_to_string(p->state)); + } + + unit_file_list_free(h); + + log_info("/*** enable **/"); + + r = unit_file_enable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + + log_info("/*** enable2 **/"); + + r = unit_file_enable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_ENABLED); + + log_info("/*** disable ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_DISABLED); + + log_info("/*** mask ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_mask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + log_info("/*** mask2 ***/"); + r = unit_file_mask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_MASKED); + + log_info("/*** unmask ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_unmask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + log_info("/*** unmask2 ***/"); + r = unit_file_unmask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_DISABLED); + + log_info("/*** mask ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_mask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_MASKED); + + log_info("/*** disable ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + log_info("/*** disable2 ***/"); + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_MASKED); + + log_info("/*** umask ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_unmask(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, files[0], &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_DISABLED); + + log_info("/*** enable files2 ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_enable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_ENABLED); + + log_info("/*** disable files2 ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); + assert_se(r < 0); + + log_info("/*** link files2 ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_link(UNIT_FILE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_LINKED); + + log_info("/*** disable files2 ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); + assert_se(r < 0); + + log_info("/*** link files2 ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_link(UNIT_FILE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_LINKED); + + log_info("/*** reenable files2 ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_reenable(UNIT_FILE_SYSTEM, 0, NULL, (char**) files2, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_ENABLED); + + log_info("/*** disable files2 ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_disable(UNIT_FILE_SYSTEM, 0, NULL, STRV_MAKE(basename(files2[0])), &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files2[0]), &state); + assert_se(r < 0); + log_info("/*** preset files ***/"); + changes = NULL; + n_changes = 0; + + r = unit_file_preset(UNIT_FILE_SYSTEM, 0, NULL, (char**) files, UNIT_FILE_PRESET_FULL, &changes, &n_changes); + assert_se(r >= 0); + + dump_changes(changes, n_changes); + unit_file_changes_free(changes, n_changes); + + r = unit_file_get_state(UNIT_FILE_SYSTEM, NULL, basename(files[0]), &state); + assert_se(r >= 0); + assert_se(state == UNIT_FILE_ENABLED); + + return 0; +} diff --git a/src/test/test-io-util.c b/src/test/test-io-util.c new file mode 100644 index 00000000..42e632a8 --- /dev/null +++ b/src/test/test-io-util.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "io-util.h" +#include "macro.h" + +static void test_sparse_write_one(int fd, const char *buffer, size_t n) { + char check[n]; + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(ftruncate(fd, 0) >= 0); + assert_se(sparse_write(fd, buffer, n, 4) == (ssize_t) n); + + assert_se(lseek(fd, 0, SEEK_CUR) == (off_t) n); + assert_se(ftruncate(fd, n) >= 0); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(read(fd, check, n) == (ssize_t) n); + + assert_se(memcmp(buffer, check, n) == 0); +} + +static void test_sparse_write(void) { + const char test_a[] = "test"; + const char test_b[] = "\0\0\0\0test\0\0\0\0"; + const char test_c[] = "\0\0test\0\0\0\0"; + const char test_d[] = "\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0test\0\0\0test\0\0\0\0test\0\0\0\0\0\0\0\0"; + const char test_e[] = "test\0\0\0\0test"; + _cleanup_close_ int fd = -1; + char fn[] = "/tmp/sparseXXXXXX"; + + fd = mkostemp(fn, O_CLOEXEC); + assert_se(fd >= 0); + unlink(fn); + + test_sparse_write_one(fd, test_a, sizeof(test_a)); + test_sparse_write_one(fd, test_b, sizeof(test_b)); + test_sparse_write_one(fd, test_c, sizeof(test_c)); + test_sparse_write_one(fd, test_d, sizeof(test_d)); + test_sparse_write_one(fd, test_e, sizeof(test_e)); +} + +int main(void) { + test_sparse_write(); + + return 0; +} diff --git a/src/test/test-ip-protocol-list.c b/src/test/test-ip-protocol-list.c new file mode 100644 index 00000000..79390e52 --- /dev/null +++ b/src/test/test-ip-protocol-list.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "macro.h" +#include "ip-protocol-list.h" +#include "stdio-util.h" +#include "string-util.h" + +static void test_int(int i) { + char str[DECIMAL_STR_MAX(int)]; + + assert_se(ip_protocol_from_name(ip_protocol_to_name(i)) == i); + + xsprintf(str, "%i", i); + assert_se(ip_protocol_from_name(ip_protocol_to_name(parse_ip_protocol(str))) == i); +} + +static void test_int_fail(int i) { + char str[DECIMAL_STR_MAX(int)]; + + assert_se(!ip_protocol_to_name(i)); + + xsprintf(str, "%i", i); + assert_se(parse_ip_protocol(str) == -EINVAL); +} + +static void test_str(const char *s) { + assert_se(streq(ip_protocol_to_name(ip_protocol_from_name(s)), s)); + assert_se(streq(ip_protocol_to_name(parse_ip_protocol(s)), s)); +} + +static void test_str_fail(const char *s) { + assert_se(ip_protocol_from_name(s) == -EINVAL); + assert_se(parse_ip_protocol(s) == -EINVAL); +} + +static void test_parse_ip_protocol(const char *s, int expected) { + assert_se(parse_ip_protocol(s) == expected); +} + +int main(int argc, const char *argv[]) { + test_int(IPPROTO_TCP); + test_int(IPPROTO_DCCP); + test_int_fail(-1); + test_int_fail(1024 * 1024); + + test_str("sctp"); + test_str("udp"); + test_str_fail("hoge"); + test_str_fail("-1"); + test_str_fail("1000000000"); + + test_parse_ip_protocol("sctp", IPPROTO_SCTP); + test_parse_ip_protocol("ScTp", IPPROTO_SCTP); + test_parse_ip_protocol("ip", IPPROTO_IP); + test_parse_ip_protocol("", IPPROTO_IP); + test_parse_ip_protocol("1", 1); + test_parse_ip_protocol("0", 0); + test_parse_ip_protocol("-10", -EINVAL); + test_parse_ip_protocol("100000000", -EINVAL); + + return 0; +} diff --git a/src/test/test-ipcrm.c b/src/test/test-ipcrm.c new file mode 100644 index 00000000..4b658a0b --- /dev/null +++ b/src/test/test-ipcrm.c @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "clean-ipc.h" +#include "user-util.h" +#include "tests.h" +#include "util.h" + +int main(int argc, char *argv[]) { + uid_t uid; + int r; + const char* name = argv[1] ?: NOBODY_USER_NAME; + + test_setup_logging(LOG_INFO); + + r = get_user_creds(&name, &uid, NULL, NULL, NULL, 0); + if (r == -ESRCH) + return log_tests_skipped("Failed to resolve user"); + if (r < 0) { + log_error_errno(r, "Failed to resolve \"%s\": %m", name); + return EXIT_FAILURE; + } + + r = clean_ipc_by_uid(uid); + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/test/test-job-type.c b/src/test/test-job-type.c new file mode 100644 index 00000000..33a95c6b --- /dev/null +++ b/src/test/test-job-type.c @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "service.h" +#include "unit.h" + +int main(int argc, char *argv[]) { + JobType a, b, c, ab, bc, ab_c, bc_a, a_bc; + const ServiceState test_states[] = { SERVICE_DEAD, SERVICE_RUNNING }; + unsigned i; + bool merged_ab; + + /* fake a unit */ + static Service s = { + .meta.load_state = UNIT_LOADED, + .type = SERVICE_SIMPLE, + }; + Unit *u = UNIT(&s); + + for (i = 0; i < ELEMENTSOF(test_states); i++) { + s.state = test_states[i]; + printf("\nWith collapsing for service state %s\n" + "=========================================\n", service_state_to_string(s.state)); + for (a = 0; a < _JOB_TYPE_MAX_MERGING; a++) { + for (b = 0; b < _JOB_TYPE_MAX_MERGING; b++) { + + ab = a; + merged_ab = (job_type_merge_and_collapse(&ab, b, u) >= 0); + + if (!job_type_is_mergeable(a, b)) { + assert_se(!merged_ab); + printf("Not mergeable: %s + %s\n", job_type_to_string(a), job_type_to_string(b)); + continue; + } + + assert_se(merged_ab); + printf("%s + %s = %s\n", job_type_to_string(a), job_type_to_string(b), job_type_to_string(ab)); + + for (c = 0; c < _JOB_TYPE_MAX_MERGING; c++) { + + /* Verify transitivity of mergeability of job types */ + assert_se(!job_type_is_mergeable(a, b) || + !job_type_is_mergeable(b, c) || + job_type_is_mergeable(a, c)); + + /* Verify that merged entries can be merged with the same entries + * they can be merged with separately */ + assert_se(!job_type_is_mergeable(a, c) || job_type_is_mergeable(ab, c)); + assert_se(!job_type_is_mergeable(b, c) || job_type_is_mergeable(ab, c)); + + /* Verify that if a merged with b is not mergeable with c, then + * either a or b is not mergeable with c either. */ + assert_se(job_type_is_mergeable(ab, c) || !job_type_is_mergeable(a, c) || !job_type_is_mergeable(b, c)); + + bc = b; + if (job_type_merge_and_collapse(&bc, c, u) >= 0) { + + /* Verify associativity */ + + ab_c = ab; + assert_se(job_type_merge_and_collapse(&ab_c, c, u) == 0); + + bc_a = bc; + assert_se(job_type_merge_and_collapse(&bc_a, a, u) == 0); + + a_bc = a; + assert_se(job_type_merge_and_collapse(&a_bc, bc, u) == 0); + + assert_se(ab_c == bc_a); + assert_se(ab_c == a_bc); + + printf("%s + %s + %s = %s\n", job_type_to_string(a), job_type_to_string(b), job_type_to_string(c), job_type_to_string(ab_c)); + } + } + } + } + } + + return 0; +} diff --git a/src/test/test-journal-importer.c b/src/test/test-journal-importer.c new file mode 100644 index 00000000..7e898735 --- /dev/null +++ b/src/test/test-journal-importer.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "log.h" +#include "journal-importer.h" +#include "path-util.h" +#include "string-util.h" +#include "tests.h" + +static void assert_iovec_entry(const struct iovec *iovec, const char* content) { + assert_se(strlen(content) == iovec->iov_len); + assert_se(memcmp(content, iovec->iov_base, iovec->iov_len) == 0); +} + +#define COREDUMP_PROC_GROUP \ + "COREDUMP_PROC_CGROUP=1:name=systemd:/\n" \ + "0::/user.slice/user-1002.slice/user@1002.service/gnome-terminal-server.service\n" + +static void test_basic_parsing(void) { + _cleanup_(journal_importer_cleanup) JournalImporter imp = JOURNAL_IMPORTER_INIT(-1); + _cleanup_free_ char *journal_data_path = NULL; + int r; + + journal_data_path = path_join(get_testdata_dir(), "journal-data/journal-1.txt"); + imp.fd = open(journal_data_path, O_RDONLY|O_CLOEXEC); + assert_se(imp.fd >= 0); + + do + r = journal_importer_process_data(&imp); + while (r == 0 && !journal_importer_eof(&imp)); + assert_se(r == 1); + + /* We read one entry, so we should get EOF on next read, but not yet */ + assert_se(!journal_importer_eof(&imp)); + + assert_se(imp.iovw.count == 6); + assert_iovec_entry(&imp.iovw.iovec[0], "_BOOT_ID=1531fd22ec84429e85ae888b12fadb91"); + assert_iovec_entry(&imp.iovw.iovec[1], "_TRANSPORT=journal"); + assert_iovec_entry(&imp.iovw.iovec[2], COREDUMP_PROC_GROUP); + assert_iovec_entry(&imp.iovw.iovec[3], "COREDUMP_RLIMIT=-1"); + assert_iovec_entry(&imp.iovw.iovec[4], COREDUMP_PROC_GROUP); + assert_iovec_entry(&imp.iovw.iovec[5], "_SOURCE_REALTIME_TIMESTAMP=1478389147837945"); + + /* Let's check if we get EOF now */ + r = journal_importer_process_data(&imp); + assert_se(r == 0); + assert_se(journal_importer_eof(&imp)); +} + +static void test_bad_input(void) { + _cleanup_(journal_importer_cleanup) JournalImporter imp = JOURNAL_IMPORTER_INIT(-1); + _cleanup_free_ char *journal_data_path = NULL; + int r; + + journal_data_path = path_join(get_testdata_dir(), "journal-data/journal-2.txt"); + imp.fd = open(journal_data_path, O_RDONLY|O_CLOEXEC); + assert_se(imp.fd >= 0); + + do + r = journal_importer_process_data(&imp); + while (!journal_importer_eof(&imp)); + assert_se(r == 0); /* If we don't have enough input, 0 is returned */ + + assert_se(journal_importer_eof(&imp)); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_basic_parsing(); + test_bad_input(); + + return 0; +} diff --git a/src/test/test-json.c b/src/test/test-json.c new file mode 100644 index 00000000..a6613043 --- /dev/null +++ b/src/test/test-json.c @@ -0,0 +1,471 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "json-internal.h" +#include "json.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "util.h" + +static void test_tokenizer(const char *data, ...) { + unsigned line = 0, column = 0; + void *state = NULL; + va_list ap; + + va_start(ap, data); + + for (;;) { + unsigned token_line, token_column; + _cleanup_free_ char *str = NULL; + JsonValue v = JSON_VALUE_NULL; + int t, tt; + + t = json_tokenize(&data, &str, &v, &token_line, &token_column, &state, &line, &column); + tt = va_arg(ap, int); + + assert_se(t == tt); + + if (t == JSON_TOKEN_END || t < 0) + break; + + else if (t == JSON_TOKEN_STRING) { + const char *nn; + + nn = va_arg(ap, const char *); + assert_se(streq_ptr(nn, str)); + + } else if (t == JSON_TOKEN_REAL) { + long double d; + + d = va_arg(ap, long double); + + /* Valgrind doesn't support long double calculations and automatically downgrades to 80bit: + * http://www.valgrind.org/docs/manual/manual-core.html#manual-core.limits. + * Some architectures might not support long double either. + */ + + assert_se(fabsl(d - v.real) < 1e-10 || + fabsl((d - v.real) / v.real) < 1e-10); + + } else if (t == JSON_TOKEN_INTEGER) { + intmax_t i; + + i = va_arg(ap, intmax_t); + assert_se(i == v.integer); + + } else if (t == JSON_TOKEN_UNSIGNED) { + uintmax_t u; + + u = va_arg(ap, uintmax_t); + assert_se(u == v.unsig); + + } else if (t == JSON_TOKEN_BOOLEAN) { + bool b; + + b = va_arg(ap, int); + assert_se(b == v.boolean); + } + } + + va_end(ap); +} + +typedef void (*Test)(JsonVariant *); + +static void test_variant(const char *data, Test test) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL; + _cleanup_free_ char *s = NULL; + int r; + + r = json_parse(data, &v, NULL, NULL); + assert_se(r == 0); + assert_se(v); + + r = json_variant_format(v, 0, &s); + assert_se(r >= 0); + assert_se(s); + assert_se((size_t) r == strlen(s)); + + log_info("formatted normally: %s\n", s); + + r = json_parse(data, &w, NULL, NULL); + assert_se(r == 0); + assert_se(w); + assert_se(json_variant_has_type(v, json_variant_type(w))); + assert_se(json_variant_has_type(w, json_variant_type(v))); + assert_se(json_variant_equal(v, w)); + + s = mfree(s); + w = json_variant_unref(w); + + r = json_variant_format(v, JSON_FORMAT_PRETTY, &s); + assert_se(r >= 0); + assert_se(s); + assert_se((size_t) r == strlen(s)); + + log_info("formatted prettily:\n%s", s); + + r = json_parse(data, &w, NULL, NULL); + assert_se(r == 0); + assert_se(w); + + assert_se(json_variant_has_type(v, json_variant_type(w))); + assert_se(json_variant_has_type(w, json_variant_type(v))); + assert_se(json_variant_equal(v, w)); + + s = mfree(s); + r = json_variant_format(v, JSON_FORMAT_COLOR, &s); + assert_se(r >= 0); + assert_se(s); + assert_se((size_t) r == strlen(s)); + printf("Normal with color: %s\n", s); + + s = mfree(s); + r = json_variant_format(v, JSON_FORMAT_COLOR|JSON_FORMAT_PRETTY, &s); + assert_se(r >= 0); + assert_se(s); + assert_se((size_t) r == strlen(s)); + printf("Pretty with color:\n%s\n", s); + + if (test) + test(v); +} + +static void test_1(JsonVariant *v) { + JsonVariant *p, *q; + unsigned i; + + /* 3 keys + 3 values */ + assert_se(json_variant_elements(v) == 6); + + /* has k */ + p = json_variant_by_key(v, "k"); + assert_se(p && json_variant_type(p) == JSON_VARIANT_STRING); + + /* k equals v */ + assert_se(streq(json_variant_string(p), "v")); + + /* has foo */ + p = json_variant_by_key(v, "foo"); + assert_se(p && json_variant_type(p) == JSON_VARIANT_ARRAY && json_variant_elements(p) == 3); + + /* check foo[0] = 1, foo[1] = 2, foo[2] = 3 */ + for (i = 0; i < 3; ++i) { + q = json_variant_by_index(p, i); + assert_se(q && json_variant_type(q) == JSON_VARIANT_UNSIGNED && json_variant_unsigned(q) == (i+1)); + assert_se(q && json_variant_has_type(q, JSON_VARIANT_INTEGER) && json_variant_integer(q) == (i+1)); + } + + /* has bar */ + p = json_variant_by_key(v, "bar"); + assert_se(p && json_variant_type(p) == JSON_VARIANT_OBJECT && json_variant_elements(p) == 2); + + /* zap is null */ + q = json_variant_by_key(p, "zap"); + assert_se(q && json_variant_type(q) == JSON_VARIANT_NULL); +} + +static void test_2(JsonVariant *v) { + JsonVariant *p, *q; + + /* 2 keys + 2 values */ + assert_se(json_variant_elements(v) == 4); + + /* has mutant */ + p = json_variant_by_key(v, "mutant"); + assert_se(p && json_variant_type(p) == JSON_VARIANT_ARRAY && json_variant_elements(p) == 4); + + /* mutant[0] == 1 */ + q = json_variant_by_index(p, 0); + assert_se(q && json_variant_type(q) == JSON_VARIANT_UNSIGNED && json_variant_unsigned(q) == 1); + assert_se(q && json_variant_has_type(q, JSON_VARIANT_INTEGER) && json_variant_integer(q) == 1); + + /* mutant[1] == null */ + q = json_variant_by_index(p, 1); + assert_se(q && json_variant_type(q) == JSON_VARIANT_NULL); + + /* mutant[2] == "1" */ + q = json_variant_by_index(p, 2); + assert_se(q && json_variant_type(q) == JSON_VARIANT_STRING && streq(json_variant_string(q), "1")); + + /* mutant[3] == JSON_VARIANT_OBJECT */ + q = json_variant_by_index(p, 3); + assert_se(q && json_variant_type(q) == JSON_VARIANT_OBJECT && json_variant_elements(q) == 2); + + /* has 1 */ + p = json_variant_by_key(q, "1"); + assert_se(p && json_variant_type(p) == JSON_VARIANT_ARRAY && json_variant_elements(p) == 2); + + /* "1"[0] == 1 */ + q = json_variant_by_index(p, 0); + assert_se(q && json_variant_type(q) == JSON_VARIANT_UNSIGNED && json_variant_unsigned(q) == 1); + assert_se(q && json_variant_has_type(q, JSON_VARIANT_INTEGER) && json_variant_integer(q) == 1); + + /* "1"[1] == "1" */ + q = json_variant_by_index(p, 1); + assert_se(q && json_variant_type(q) == JSON_VARIANT_STRING && streq(json_variant_string(q), "1")); + + /* has thisisaverylongproperty */ + p = json_variant_by_key(v, "thisisaverylongproperty"); + assert_se(p && json_variant_type(p) == JSON_VARIANT_REAL && fabsl(json_variant_real(p) - 1.27) < 0.001); +} + +static void test_zeroes(JsonVariant *v) { + size_t i; + + /* Make sure zero is how we expect it. */ + + assert_se(json_variant_elements(v) == 13); + + for (i = 0; i < json_variant_elements(v); i++) { + JsonVariant *w; + size_t j; + + assert_se(w = json_variant_by_index(v, i)); + + assert_se(json_variant_integer(w) == 0); + assert_se(json_variant_unsigned(w) == 0U); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + assert_se(json_variant_real(w) == 0.0L); +#pragma GCC diagnostic pop + + assert_se(json_variant_is_integer(w)); + assert_se(json_variant_is_unsigned(w)); + assert_se(json_variant_is_real(w)); + assert_se(json_variant_is_number(w)); + + assert_se(!json_variant_is_negative(w)); + + assert_se(IN_SET(json_variant_type(w), JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL)); + + for (j = 0; j < json_variant_elements(v); j++) { + JsonVariant *q; + + assert_se(q = json_variant_by_index(v, j)); + + assert_se(json_variant_equal(w, q)); + } + } +} + +static void test_build(void) { + _cleanup_(json_variant_unrefp) JsonVariant *a = NULL, *b = NULL; + _cleanup_free_ char *s = NULL, *t = NULL; + + assert_se(json_build(&a, JSON_BUILD_STRING("hallo")) >= 0); + assert_se(json_build(&b, JSON_BUILD_LITERAL(" \"hallo\" ")) >= 0); + assert_se(json_variant_equal(a, b)); + + b = json_variant_unref(b); + + assert_se(json_build(&b, JSON_BUILD_VARIANT(a)) >= 0); + assert_se(json_variant_equal(a, b)); + + b = json_variant_unref(b); + assert_se(json_build(&b, JSON_BUILD_STRING("pief")) >= 0); + assert_se(!json_variant_equal(a, b)); + + a = json_variant_unref(a); + b = json_variant_unref(b); + + assert_se(json_build(&a, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("one", JSON_BUILD_INTEGER(7)), + JSON_BUILD_PAIR("two", JSON_BUILD_REAL(2.0)), + JSON_BUILD_PAIR("three", JSON_BUILD_INTEGER(0)))) >= 0); + + assert_se(json_build(&b, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("two", JSON_BUILD_INTEGER(2)), + JSON_BUILD_PAIR("three", JSON_BUILD_REAL(0)), + JSON_BUILD_PAIR("one", JSON_BUILD_REAL(7)))) >= 0); + + assert_se(json_variant_equal(a, b)); + + a = json_variant_unref(a); + b = json_variant_unref(b); + + const char* arr_1234[] = {"one", "two", "three", "four", NULL}; + assert_se(json_build(&a, JSON_BUILD_ARRAY(JSON_BUILD_OBJECT(JSON_BUILD_PAIR("x", JSON_BUILD_BOOLEAN(true)), + JSON_BUILD_PAIR("y", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("this", JSON_BUILD_NULL)))), + JSON_BUILD_VARIANT(NULL), + JSON_BUILD_LITERAL(NULL), + JSON_BUILD_STRING(NULL), + JSON_BUILD_NULL, + JSON_BUILD_INTEGER(77), + JSON_BUILD_ARRAY(JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("foobar")), + JSON_BUILD_VARIANT(JSON_VARIANT_STRING_CONST("zzz"))), + JSON_BUILD_STRV((char**) arr_1234))) >= 0); + + assert_se(json_variant_format(a, 0, &s) >= 0); + log_info("GOT: %s\n", s); + assert_se(json_parse(s, &b, NULL, NULL) >= 0); + assert_se(json_variant_equal(a, b)); + + a = json_variant_unref(a); + b = json_variant_unref(b); + + assert_se(json_build(&a, JSON_BUILD_REAL(M_PIl)) >= 0); + + s = mfree(s); + assert_se(json_variant_format(a, 0, &s) >= 0); + log_info("GOT: %s\n", s); + assert_se(json_parse(s, &b, NULL, NULL) >= 0); + assert_se(json_variant_format(b, 0, &t) >= 0); + log_info("GOT: %s\n", t); + + assert_se(streq(s, t)); + + a = json_variant_unref(a); + b = json_variant_unref(b); + + assert_se(json_build(&a, JSON_BUILD_OBJECT( + JSON_BUILD_PAIR("x", JSON_BUILD_STRING("y")), + JSON_BUILD_PAIR("z", JSON_BUILD_STRING("a")), + JSON_BUILD_PAIR("b", JSON_BUILD_STRING("c")) + )) >= 0); + + assert_se(json_build(&b, JSON_BUILD_OBJECT( + JSON_BUILD_PAIR("x", JSON_BUILD_STRING("y")), + JSON_BUILD_PAIR_CONDITION(false, "p", JSON_BUILD_STRING("q")), + JSON_BUILD_PAIR_CONDITION(true, "z", JSON_BUILD_STRING("a")), + JSON_BUILD_PAIR_CONDITION(false, "j", JSON_BUILD_ARRAY(JSON_BUILD_STRING("k"), JSON_BUILD_STRING("u"), JSON_BUILD_STRING("i"))), + JSON_BUILD_PAIR("b", JSON_BUILD_STRING("c")) + )) >= 0); + + assert_se(json_variant_equal(a, b)); +} + +static void test_source(void) { + static const char data[] = + "\n" + "\n" + "{\n" + "\"foo\" : \"bar\", \n" + "\"qüüx\" : [ 1, 2, 3,\n" + "4,\n" + "5 ],\n" + "\"miep\" : { \"hallo\" : 1 },\n" + "\n" + "\"zzzzzz\" \n" + ":\n" + "[ true, \n" + "false, 7.5, {} ]\n" + "}\n"; + + _cleanup_fclose_ FILE *f = NULL; + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + + printf("--- original begin ---\n" + "%s" + "--- original end ---\n", data); + + assert_se(f = fmemopen_unlocked((void*) data, strlen(data), "r")); + + assert_se(json_parse_file(f, "waldo", &v, NULL, NULL) >= 0); + + printf("--- non-pretty begin ---\n"); + json_variant_dump(v, 0, stdout, NULL); + printf("\n--- non-pretty end ---\n"); + + printf("--- pretty begin ---\n"); + json_variant_dump(v, JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR|JSON_FORMAT_SOURCE, stdout, NULL); + printf("--- pretty end ---\n"); +} + +static void test_depth(void) { + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + unsigned i; + int r; + + v = JSON_VARIANT_STRING_CONST("start"); + + /* Let's verify that the maximum depth checks work */ + + for (i = 0;; i++) { + _cleanup_(json_variant_unrefp) JsonVariant *w = NULL; + + assert_se(i <= UINT16_MAX); + if (i & 1) + r = json_variant_new_array(&w, &v, 1); + else + r = json_variant_new_object(&w, (JsonVariant*[]) { JSON_VARIANT_STRING_CONST("key"), v }, 2); + if (r == -ELNRNG) { + log_info("max depth at %u", i); + break; + } +#if HAS_FEATURE_MEMORY_SANITIZER + /* msan doesn't like the stack nesting to be too deep. Let's quit early. */ + if (i >= 128) { + log_info("quitting early at depth %u", i); + break; + } +#endif + + assert_se(r >= 0); + + json_variant_unref(v); + v = TAKE_PTR(w); + } + + json_variant_dump(v, 0, stdout, NULL); + fputs("\n", stdout); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_tokenizer("x", -EINVAL); + test_tokenizer("", JSON_TOKEN_END); + test_tokenizer(" ", JSON_TOKEN_END); + test_tokenizer("0", JSON_TOKEN_UNSIGNED, (uintmax_t) 0, JSON_TOKEN_END); + test_tokenizer("-0", JSON_TOKEN_INTEGER, (intmax_t) 0, JSON_TOKEN_END); + test_tokenizer("1234", JSON_TOKEN_UNSIGNED, (uintmax_t) 1234, JSON_TOKEN_END); + test_tokenizer("-1234", JSON_TOKEN_INTEGER, (intmax_t) -1234, JSON_TOKEN_END); + test_tokenizer("18446744073709551615", JSON_TOKEN_UNSIGNED, (uintmax_t) UINT64_MAX, JSON_TOKEN_END); + test_tokenizer("-9223372036854775808", JSON_TOKEN_INTEGER, (intmax_t) INT64_MIN, JSON_TOKEN_END); + test_tokenizer("18446744073709551616", JSON_TOKEN_REAL, (long double) 18446744073709551616.0L, JSON_TOKEN_END); + test_tokenizer("-9223372036854775809", JSON_TOKEN_REAL, (long double) -9223372036854775809.0L, JSON_TOKEN_END); + test_tokenizer("-1234", JSON_TOKEN_INTEGER, (intmax_t) -1234, JSON_TOKEN_END); + test_tokenizer("3.141", JSON_TOKEN_REAL, (long double) 3.141, JSON_TOKEN_END); + test_tokenizer("0.0", JSON_TOKEN_REAL, (long double) 0.0, JSON_TOKEN_END); + test_tokenizer("7e3", JSON_TOKEN_REAL, (long double) 7e3, JSON_TOKEN_END); + test_tokenizer("-7e-3", JSON_TOKEN_REAL, (long double) -7e-3, JSON_TOKEN_END); + test_tokenizer("true", JSON_TOKEN_BOOLEAN, true, JSON_TOKEN_END); + test_tokenizer("false", JSON_TOKEN_BOOLEAN, false, JSON_TOKEN_END); + test_tokenizer("null", JSON_TOKEN_NULL, JSON_TOKEN_END); + test_tokenizer("{}", JSON_TOKEN_OBJECT_OPEN, JSON_TOKEN_OBJECT_CLOSE, JSON_TOKEN_END); + test_tokenizer("\t {\n} \n", JSON_TOKEN_OBJECT_OPEN, JSON_TOKEN_OBJECT_CLOSE, JSON_TOKEN_END); + test_tokenizer("[]", JSON_TOKEN_ARRAY_OPEN, JSON_TOKEN_ARRAY_CLOSE, JSON_TOKEN_END); + test_tokenizer("\t [] \n\n", JSON_TOKEN_ARRAY_OPEN, JSON_TOKEN_ARRAY_CLOSE, JSON_TOKEN_END); + test_tokenizer("\"\"", JSON_TOKEN_STRING, "", JSON_TOKEN_END); + test_tokenizer("\"foo\"", JSON_TOKEN_STRING, "foo", JSON_TOKEN_END); + test_tokenizer("\"foo\\nfoo\"", JSON_TOKEN_STRING, "foo\nfoo", JSON_TOKEN_END); + test_tokenizer("{\"foo\" : \"bar\"}", JSON_TOKEN_OBJECT_OPEN, JSON_TOKEN_STRING, "foo", JSON_TOKEN_COLON, JSON_TOKEN_STRING, "bar", JSON_TOKEN_OBJECT_CLOSE, JSON_TOKEN_END); + test_tokenizer("{\"foo\" : [true, false]}", JSON_TOKEN_OBJECT_OPEN, JSON_TOKEN_STRING, "foo", JSON_TOKEN_COLON, JSON_TOKEN_ARRAY_OPEN, JSON_TOKEN_BOOLEAN, true, JSON_TOKEN_COMMA, JSON_TOKEN_BOOLEAN, false, JSON_TOKEN_ARRAY_CLOSE, JSON_TOKEN_OBJECT_CLOSE, JSON_TOKEN_END); + test_tokenizer("\"\xef\xbf\xbd\"", JSON_TOKEN_STRING, "\xef\xbf\xbd", JSON_TOKEN_END); + test_tokenizer("\"\\ufffd\"", JSON_TOKEN_STRING, "\xef\xbf\xbd", JSON_TOKEN_END); + test_tokenizer("\"\\uf\"", -EINVAL); + test_tokenizer("\"\\ud800a\"", -EINVAL); + test_tokenizer("\"\\udc00\\udc00\"", -EINVAL); + test_tokenizer("\"\\ud801\\udc37\"", JSON_TOKEN_STRING, "\xf0\x90\x90\xb7", JSON_TOKEN_END); + + test_tokenizer("[1, 2, -3]", JSON_TOKEN_ARRAY_OPEN, JSON_TOKEN_UNSIGNED, (uintmax_t) 1, JSON_TOKEN_COMMA, JSON_TOKEN_UNSIGNED, (uintmax_t) 2, JSON_TOKEN_COMMA, JSON_TOKEN_INTEGER, (intmax_t) -3, JSON_TOKEN_ARRAY_CLOSE, JSON_TOKEN_END); + + test_variant("{\"k\": \"v\", \"foo\": [1, 2, 3], \"bar\": {\"zap\": null}}", test_1); + test_variant("{\"mutant\": [1, null, \"1\", {\"1\": [1, \"1\"]}], \"thisisaverylongproperty\": 1.27}", test_2); + test_variant("{\"foo\" : \"\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFFFFF\\\"\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFF\\uDBFF\\uDFFFF\\uDBFF\\uDFFF\\uDBFF\\uDFFF\\uDBFF\\uDFFF\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFFFF\\\"\\uDBFF\\uDFFF\\\"\\uD9FF\\uDFFF\\uDBFF\\uDFFF\"}", NULL); + + test_variant("[ 0, -0, 0.0, -0.0, 0.000, -0.000, 0e0, -0e0, 0e+0, -0e-0, 0e-0, -0e000, 0e+000 ]", test_zeroes); + + test_build(); + + test_source(); + + test_depth(); + + return 0; +} diff --git a/src/test/test-libmount.c b/src/test/test-libmount.c new file mode 100644 index 00000000..c3395493 --- /dev/null +++ b/src/test/test-libmount.c @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "fd-util.h" +#include "escape.h" +#include "libmount-util.h" +#include "tests.h" + +static void test_libmount_unescaping_one( + const char *title, + const char *string, + bool may_fail, + const char *expected_source, + const char *expected_target) { + /* A test for libmount really */ + int r; + + log_info("/* %s %s */", __func__, title); + + _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL; + _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL; + _cleanup_fclose_ FILE *f = NULL; + + f = fmemopen((char*) string, strlen(string), "re"); + assert_se(f); + + assert_se(libmount_parse(title, f, &table, &iter) >= 0); + + struct libmnt_fs *fs; + const char *source, *target; + _cleanup_free_ char *x = NULL, *cs = NULL, *s = NULL, *ct = NULL, *t = NULL; + + /* We allow this call and the checks below to fail in some cases. See the case definitions below. */ + + r = mnt_table_next_fs(table, iter, &fs); + if (r != 0 && may_fail) { + log_error_errno(r, "mnt_table_next_fs failed: %m"); + return; + } + assert_se(r == 0); + + assert_se(x = cescape(string)); + + assert_se(source = mnt_fs_get_source(fs)); + assert_se(target = mnt_fs_get_target(fs)); + + assert_se(cs = cescape(source)); + assert_se(ct = cescape(target)); + + assert_se(cunescape(source, UNESCAPE_RELAX, &s) >= 0); + assert_se(cunescape(target, UNESCAPE_RELAX, &t) >= 0); + + log_info("from '%s'", x); + log_info("source: '%s'", source); + log_info("source: '%s'", cs); + log_info("source: '%s'", s); + log_info("expected: '%s'", strna(expected_source)); + log_info("target: '%s'", target); + log_info("target: '%s'", ct); + log_info("target: '%s'", t); + log_info("expected: '%s'", strna(expected_target)); + + assert_se(may_fail || streq(source, expected_source)); + assert_se(may_fail || streq(target, expected_target)); + + assert_se(mnt_table_next_fs(table, iter, &fs) == 1); +} + +static void test_libmount_unescaping(void) { + test_libmount_unescaping_one( + "escaped space + utf8", + "729 38 0:59 / /tmp/„zupa\\040zębowa” rw,relatime shared:395 - tmpfs die\\040Brühe rw,seclabel", + false, + "die Brühe", + "/tmp/„zupa zębowa”" + ); + + test_libmount_unescaping_one( + "escaped newline", + "729 38 0:59 / /tmp/x\\012y rw,relatime shared:395 - tmpfs newline rw,seclabel", + false, + "newline", + "/tmp/x\ny" + ); + + /* The result of "mount -t tmpfs '' /tmp/emptysource". + * This will fail with libmount <= v2.33. + * See https://github.com/karelzak/util-linux/commit/18a52a5094. + */ + test_libmount_unescaping_one( + "empty source", + "760 38 0:60 / /tmp/emptysource rw,relatime shared:410 - tmpfs rw,seclabel", + true, + "", + "/tmp/emptysource" + ); + + /* The kernel leaves \r as is. + * Also see https://github.com/karelzak/util-linux/issues/780. + */ + test_libmount_unescaping_one( + "foo\\rbar", + "790 38 0:61 / /tmp/foo\rbar rw,relatime shared:425 - tmpfs tmpfs rw,seclabel", + true, + "tmpfs", + "/tmp/foo\rbar" + ); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_libmount_unescaping(); + return 0; +} diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c new file mode 100644 index 00000000..3ca8e1b1 --- /dev/null +++ b/src/test/test-libudev.c @@ -0,0 +1,584 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "build.h" +#include "fd-util.h" +#include "libudev-list-internal.h" +#include "libudev-util.h" +#include "log.h" +#include "main-func.h" +#include "stdio-util.h" +#include "string-util.h" +#include "tests.h" + +static bool arg_monitor = false; + +static void print_device(struct udev_device *device) { + const char *str; + dev_t devnum; + int count; + struct udev_list_entry *list_entry; + + log_info("*** device: %p ***", device); + str = udev_device_get_action(device); + if (str) + log_info("action: '%s'", str); + + str = udev_device_get_syspath(device); + log_info("syspath: '%s'", str); + + str = udev_device_get_sysname(device); + log_info("sysname: '%s'", str); + + str = udev_device_get_sysnum(device); + if (str) + log_info("sysnum: '%s'", str); + + str = udev_device_get_devpath(device); + log_info("devpath: '%s'", str); + + str = udev_device_get_subsystem(device); + if (str) + log_info("subsystem: '%s'", str); + + str = udev_device_get_devtype(device); + if (str) + log_info("devtype: '%s'", str); + + str = udev_device_get_driver(device); + if (str) + log_info("driver: '%s'", str); + + str = udev_device_get_devnode(device); + if (str) + log_info("devname: '%s'", str); + + devnum = udev_device_get_devnum(device); + if (major(devnum) > 0) + log_info("devnum: %u:%u", major(devnum), minor(devnum)); + + count = 0; + udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) { + log_info("link: '%s'", udev_list_entry_get_name(list_entry)); + count++; + } + if (count > 0) + log_info("found %i links", count); + + count = 0; + udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device)) { + log_info("property: '%s=%s'", + udev_list_entry_get_name(list_entry), + udev_list_entry_get_value(list_entry)); + count++; + } + if (count > 0) + log_info("found %i properties", count); + + str = udev_device_get_property_value(device, "MAJOR"); + if (str) + log_info("MAJOR: '%s'", str); + + str = udev_device_get_sysattr_value(device, "dev"); + if (str) + log_info("attr{dev}: '%s'", str); +} + +static void test_device(struct udev *udev, const char *syspath) { + _cleanup_(udev_device_unrefp) struct udev_device *device; + + log_info("/* %s, device %s */", __func__, syspath); + device = udev_device_new_from_syspath(udev, syspath); + if (device) + print_device(device); + else + log_warning_errno(errno, "udev_device_new_from_syspath: %m"); +} + +static void test_device_parents(struct udev *udev, const char *syspath) { + _cleanup_(udev_device_unrefp) struct udev_device *device; + struct udev_device *device_parent; + + log_info("/* %s, device %s */", __func__, syspath); + device = udev_device_new_from_syspath(udev, syspath); + if (device == NULL) + return; + + log_info("looking at parents"); + device_parent = device; + do { + print_device(device_parent); + device_parent = udev_device_get_parent(device_parent); + } while (device_parent != NULL); + + log_info("looking at parents again"); + device_parent = device; + do { + print_device(device_parent); + device_parent = udev_device_get_parent(device_parent); + } while (device_parent != NULL); +} + +static void test_device_devnum(struct udev *udev) { + dev_t devnum = makedev(1, 3); + _cleanup_(udev_device_unrefp) struct udev_device *device; + + log_info("/* %s, device %d:%d */", __func__, major(devnum), minor(devnum)); + + device = udev_device_new_from_devnum(udev, 'c', devnum); + if (device) + print_device(device); + else + log_warning_errno(errno, "udev_device_new_from_devnum: %m"); +} + +static void test_device_subsys_name(struct udev *udev, const char *subsys, const char *dev) { + _cleanup_(udev_device_unrefp) struct udev_device *device; + + log_info("looking up device: '%s:%s'", subsys, dev); + device = udev_device_new_from_subsystem_sysname(udev, subsys, dev); + if (device == NULL) + log_warning_errno(errno, "udev_device_new_from_subsystem_sysname: %m"); + else + print_device(device); +} + +static int enumerate_print_list(struct udev_enumerate *enumerate) { + struct udev_list_entry *list_entry; + int count = 0; + + udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { + struct udev_device *device; + + device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate), + udev_list_entry_get_name(list_entry)); + if (device) { + log_info("device: '%s' (%s)", + udev_device_get_syspath(device), + udev_device_get_subsystem(device)); + udev_device_unref(device); + count++; + } + } + log_info("found %i devices", count); + return count; +} + +static void test_monitor(struct udev *udev) { + _cleanup_(udev_monitor_unrefp) struct udev_monitor *udev_monitor; + _cleanup_close_ int fd_ep; + int fd_udev; + struct epoll_event ep_udev = { + .events = EPOLLIN, + }, ep_stdin = { + .events = EPOLLIN, + .data.fd = STDIN_FILENO, + }; + + log_info("/* %s */", __func__); + + fd_ep = epoll_create1(EPOLL_CLOEXEC); + assert_se(fd_ep >= 0); + + udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); + assert_se(udev_monitor != NULL); + + fd_udev = udev_monitor_get_fd(udev_monitor); + ep_udev.data.fd = fd_udev; + + assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "block", NULL) >= 0); + assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL) >= 0); + assert_se(udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device") >= 0); + + assert_se(udev_monitor_enable_receiving(udev_monitor) >= 0); + + assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) >= 0); + assert_se(epoll_ctl(fd_ep, EPOLL_CTL_ADD, STDIN_FILENO, &ep_stdin) >= 0); + + for (;;) { + int fdcount; + struct epoll_event ev[4]; + struct udev_device *device; + int i; + + printf("waiting for events from udev, press ENTER to exit\n"); + fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1); + printf("epoll fd count: %i\n", fdcount); + + for (i = 0; i < fdcount; i++) { + if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) { + device = udev_monitor_receive_device(udev_monitor); + if (device == NULL) { + printf("no device from socket\n"); + continue; + } + print_device(device); + udev_device_unref(device); + } else if (ev[i].data.fd == STDIN_FILENO && ev[i].events & EPOLLIN) { + printf("exiting loop\n"); + return; + } + } + } +} + +static void test_queue(struct udev *udev) { + struct udev_queue *udev_queue; + bool empty; + + log_info("/* %s */", __func__); + + assert_se(udev_queue = udev_queue_new(udev)); + + empty = udev_queue_get_queue_is_empty(udev_queue); + log_info("queue is %s", empty ? "empty" : "not empty"); + udev_queue_unref(udev_queue); +} + +static int test_enumerate(struct udev *udev, const char *subsystem) { + struct udev_enumerate *udev_enumerate; + int r; + + log_info("/* %s */", __func__); + + log_info("enumerate '%s'", subsystem == NULL ? "" : subsystem); + udev_enumerate = udev_enumerate_new(udev); + if (!udev_enumerate) + return -1; + udev_enumerate_add_match_subsystem(udev_enumerate, subsystem); + udev_enumerate_scan_devices(udev_enumerate); + enumerate_print_list(udev_enumerate); + udev_enumerate_unref(udev_enumerate); + + log_info("enumerate 'net' + duplicated scan + null + zero"); + udev_enumerate = udev_enumerate_new(udev); + if (!udev_enumerate) + return -1; + udev_enumerate_add_match_subsystem(udev_enumerate, "net"); + udev_enumerate_scan_devices(udev_enumerate); + udev_enumerate_scan_devices(udev_enumerate); + udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); + udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); + udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); + udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); + udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); + udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); + udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/null"); + udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); + udev_enumerate_add_syspath(udev_enumerate, "/sys/class/mem/zero"); + udev_enumerate_scan_devices(udev_enumerate); + enumerate_print_list(udev_enumerate); + udev_enumerate_unref(udev_enumerate); + + log_info("enumerate 'block'"); + udev_enumerate = udev_enumerate_new(udev); + if (!udev_enumerate) + return -1; + udev_enumerate_add_match_subsystem(udev_enumerate,"block"); + r = udev_enumerate_add_match_is_initialized(udev_enumerate); + if (r < 0) { + udev_enumerate_unref(udev_enumerate); + return r; + } + udev_enumerate_scan_devices(udev_enumerate); + enumerate_print_list(udev_enumerate); + udev_enumerate_unref(udev_enumerate); + + log_info("enumerate 'not block'"); + udev_enumerate = udev_enumerate_new(udev); + if (!udev_enumerate) + return -1; + udev_enumerate_add_nomatch_subsystem(udev_enumerate, "block"); + udev_enumerate_scan_devices(udev_enumerate); + enumerate_print_list(udev_enumerate); + udev_enumerate_unref(udev_enumerate); + + log_info("enumerate 'pci, mem, vc'"); + udev_enumerate = udev_enumerate_new(udev); + if (!udev_enumerate) + return -1; + udev_enumerate_add_match_subsystem(udev_enumerate, "pci"); + udev_enumerate_add_match_subsystem(udev_enumerate, "mem"); + udev_enumerate_add_match_subsystem(udev_enumerate, "vc"); + udev_enumerate_scan_devices(udev_enumerate); + enumerate_print_list(udev_enumerate); + udev_enumerate_unref(udev_enumerate); + + log_info("enumerate 'subsystem'"); + udev_enumerate = udev_enumerate_new(udev); + if (!udev_enumerate) + return -1; + udev_enumerate_scan_subsystems(udev_enumerate); + enumerate_print_list(udev_enumerate); + udev_enumerate_unref(udev_enumerate); + + log_info("enumerate 'property IF_FS_*=filesystem'"); + udev_enumerate = udev_enumerate_new(udev); + if (!udev_enumerate) + return -1; + udev_enumerate_add_match_property(udev_enumerate, "ID_FS*", "filesystem"); + udev_enumerate_scan_devices(udev_enumerate); + enumerate_print_list(udev_enumerate); + udev_enumerate_unref(udev_enumerate); + return 0; +} + +static void test_hwdb(struct udev *udev, const char *modalias) { + struct udev_hwdb *hwdb; + struct udev_list_entry *entry; + + log_info("/* %s */", __func__); + + hwdb = udev_hwdb_new(udev); + if (!hwdb) + log_warning_errno(errno, "Failed to open hwdb: %m"); + + udev_list_entry_foreach(entry, udev_hwdb_get_properties_list_entry(hwdb, modalias, 0)) + log_info("'%s'='%s'", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry)); + + hwdb = udev_hwdb_unref(hwdb); + assert_se(hwdb == NULL); +} + +static void test_util_replace_whitespace_one_len(const char *str, size_t len, const char *expected) { + _cleanup_free_ char *result = NULL; + int r; + + result = new(char, len + 1); + assert_se(result); + r = util_replace_whitespace(str, result, len); + assert_se((size_t) r == strlen(expected)); + assert_se(streq(result, expected)); +} + +static void test_util_replace_whitespace_one(const char *str, const char *expected) { + test_util_replace_whitespace_one_len(str, strlen(str), expected); +} + +static void test_util_replace_whitespace(void) { + log_info("/* %s */", __func__); + + test_util_replace_whitespace_one("hogehoge", "hogehoge"); + test_util_replace_whitespace_one("hoge hoge", "hoge_hoge"); + test_util_replace_whitespace_one(" hoge hoge ", "hoge_hoge"); + test_util_replace_whitespace_one(" ", ""); + test_util_replace_whitespace_one("hoge ", "hoge"); + + test_util_replace_whitespace_one_len("hoge hoge ", 9, "hoge_hoge"); + test_util_replace_whitespace_one_len("hoge hoge ", 8, "hoge_hog"); + test_util_replace_whitespace_one_len("hoge hoge ", 7, "hoge_ho"); + test_util_replace_whitespace_one_len("hoge hoge ", 6, "hoge_h"); + test_util_replace_whitespace_one_len("hoge hoge ", 5, "hoge"); + test_util_replace_whitespace_one_len("hoge hoge ", 4, "hoge"); + test_util_replace_whitespace_one_len("hoge hoge ", 3, "hog"); + test_util_replace_whitespace_one_len("hoge hoge ", 2, "ho"); + test_util_replace_whitespace_one_len("hoge hoge ", 1, "h"); + test_util_replace_whitespace_one_len("hoge hoge ", 0, ""); + + test_util_replace_whitespace_one_len(" hoge hoge ", 16, "hoge_hoge"); + test_util_replace_whitespace_one_len(" hoge hoge ", 15, "hoge_hoge"); + test_util_replace_whitespace_one_len(" hoge hoge ", 14, "hoge_hog"); + test_util_replace_whitespace_one_len(" hoge hoge ", 13, "hoge_ho"); + test_util_replace_whitespace_one_len(" hoge hoge ", 12, "hoge_h"); + test_util_replace_whitespace_one_len(" hoge hoge ", 11, "hoge"); + test_util_replace_whitespace_one_len(" hoge hoge ", 10, "hoge"); + test_util_replace_whitespace_one_len(" hoge hoge ", 9, "hoge"); + test_util_replace_whitespace_one_len(" hoge hoge ", 8, "hoge"); + test_util_replace_whitespace_one_len(" hoge hoge ", 7, "hog"); + test_util_replace_whitespace_one_len(" hoge hoge ", 6, "ho"); + test_util_replace_whitespace_one_len(" hoge hoge ", 5, "h"); + test_util_replace_whitespace_one_len(" hoge hoge ", 4, ""); + test_util_replace_whitespace_one_len(" hoge hoge ", 3, ""); + test_util_replace_whitespace_one_len(" hoge hoge ", 2, ""); + test_util_replace_whitespace_one_len(" hoge hoge ", 1, ""); + test_util_replace_whitespace_one_len(" hoge hoge ", 0, ""); +} + +static void test_util_resolve_subsys_kernel_one(const char *str, bool read_value, int retval, const char *expected) { + char result[UTIL_PATH_SIZE] = ""; + int r; + + r = util_resolve_subsys_kernel(str, result, sizeof(result), read_value); + log_info("\"%s\" → expect: \"%s\", %d, actual: \"%s\", %d", str, strnull(expected), retval, result, r); + assert_se(r == retval); + if (r >= 0) + assert_se(streq(result, expected)); +} + +static void test_util_resolve_subsys_kernel(void) { + log_info("/* %s */", __func__); + + test_util_resolve_subsys_kernel_one("hoge", false, -EINVAL, NULL); + test_util_resolve_subsys_kernel_one("[hoge", false, -EINVAL, NULL); + test_util_resolve_subsys_kernel_one("[hoge/foo", false, -EINVAL, NULL); + test_util_resolve_subsys_kernel_one("[hoge/]", false, -ENODEV, NULL); + + test_util_resolve_subsys_kernel_one("[net/lo]", false, 0, "/sys/devices/virtual/net/lo"); + test_util_resolve_subsys_kernel_one("[net/lo]/", false, 0, "/sys/devices/virtual/net/lo"); + test_util_resolve_subsys_kernel_one("[net/lo]hoge", false, 0, "/sys/devices/virtual/net/lo/hoge"); + test_util_resolve_subsys_kernel_one("[net/lo]/hoge", false, 0, "/sys/devices/virtual/net/lo/hoge"); + + test_util_resolve_subsys_kernel_one("[net/lo]", true, -EINVAL, NULL); + test_util_resolve_subsys_kernel_one("[net/lo]/", true, -EINVAL, NULL); + test_util_resolve_subsys_kernel_one("[net/lo]hoge", true, 0, ""); + test_util_resolve_subsys_kernel_one("[net/lo]/hoge", true, 0, ""); + test_util_resolve_subsys_kernel_one("[net/lo]address", true, 0, "00:00:00:00:00:00"); + test_util_resolve_subsys_kernel_one("[net/lo]/address", true, 0, "00:00:00:00:00:00"); +} + +static void test_list(void) { + _cleanup_(udev_list_freep) struct udev_list *list = NULL; + struct udev_list_entry *e; + + /* empty list */ + assert_se(list = udev_list_new(false)); + assert_se(!udev_list_get_entry(list)); + list = udev_list_free(list); + + /* unique == false */ + assert_se(list = udev_list_new(false)); + assert_se(udev_list_entry_add(list, "aaa", "hoge")); + assert_se(udev_list_entry_add(list, "aaa", "hogehoge")); + assert_se(udev_list_entry_add(list, "bbb", "foo")); + e = udev_list_get_entry(list); + assert_se(e); + assert_se(streq_ptr(udev_list_entry_get_name(e), "aaa")); + assert_se(streq_ptr(udev_list_entry_get_value(e), "hoge")); + e = udev_list_entry_get_next(e); + assert_se(e); + assert_se(streq_ptr(udev_list_entry_get_name(e), "aaa")); + assert_se(streq_ptr(udev_list_entry_get_value(e), "hogehoge")); + e = udev_list_entry_get_next(e); + assert_se(e); + assert_se(streq_ptr(udev_list_entry_get_name(e), "bbb")); + assert_se(streq_ptr(udev_list_entry_get_value(e), "foo")); + assert_se(!udev_list_entry_get_next(e)); + + assert_se(!udev_list_entry_get_by_name(e, "aaa")); + assert_se(!udev_list_entry_get_by_name(e, "bbb")); + assert_se(!udev_list_entry_get_by_name(e, "ccc")); + list = udev_list_free(list); + + /* unique == true */ + assert_se(list = udev_list_new(true)); + assert_se(udev_list_entry_add(list, "aaa", "hoge")); + assert_se(udev_list_entry_add(list, "aaa", "hogehoge")); + assert_se(udev_list_entry_add(list, "bbb", "foo")); + e = udev_list_get_entry(list); + assert_se(e); + assert_se(streq_ptr(udev_list_entry_get_name(e), "aaa")); + assert_se(streq_ptr(udev_list_entry_get_value(e), "hogehoge")); + e = udev_list_entry_get_next(e); + assert_se(streq_ptr(udev_list_entry_get_name(e), "bbb")); + assert_se(streq_ptr(udev_list_entry_get_value(e), "foo")); + assert_se(!udev_list_entry_get_next(e)); + + e = udev_list_entry_get_by_name(e, "bbb"); + assert_se(e); + assert_se(streq_ptr(udev_list_entry_get_name(e), "bbb")); + assert_se(streq_ptr(udev_list_entry_get_value(e), "foo")); + e = udev_list_entry_get_by_name(e, "aaa"); + assert_se(e); + assert_se(streq_ptr(udev_list_entry_get_name(e), "aaa")); + assert_se(streq_ptr(udev_list_entry_get_value(e), "hogehoge")); + assert_se(!udev_list_entry_get_by_name(e, "ccc")); +} + +static int parse_args(int argc, char *argv[], const char **syspath, const char **subsystem) { + static const struct option options[] = { + { "syspath", required_argument, NULL, 'p' }, + { "subsystem", required_argument, NULL, 's' }, + { "debug", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + { "monitor", no_argument, NULL, 'm' }, + {} + }; + int c; + + while ((c = getopt_long(argc, argv, "p:s:dhVm", options, NULL)) >= 0) + switch (c) { + case 'p': + *syspath = optarg; + break; + + case 's': + *subsystem = optarg; + break; + + case 'd': + log_set_max_level(LOG_DEBUG); + break; + + case 'h': + printf("--debug --syspath= --subsystem= --help\n"); + return 0; + + case 'V': + printf("%s\n", GIT_VERSION); + return 0; + + case 'm': + arg_monitor = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option code."); + } + + return 1; +} + +static int run(int argc, char *argv[]) { + _cleanup_(udev_unrefp) struct udev *udev = NULL; + + const char *syspath = "/devices/virtual/mem/null"; + const char *subsystem = NULL; + int r; + + test_setup_logging(LOG_INFO); + + r = parse_args(argc, argv, &syspath, &subsystem); + if (r <= 0) + return r; + + assert_se(udev = udev_new()); + + /* add sys path if needed */ + if (!startswith(syspath, "/sys")) + syspath = strjoina("/sys/", syspath); + + test_device(udev, syspath); + test_device_devnum(udev); + test_device_subsys_name(udev, "block", "sda"); + test_device_subsys_name(udev, "subsystem", "pci"); + test_device_subsys_name(udev, "drivers", "scsi:sd"); + test_device_subsys_name(udev, "module", "printk"); + test_device_parents(udev, syspath); + + test_enumerate(udev, subsystem); + + test_queue(udev); + + test_hwdb(udev, "usb:v0D50p0011*"); + + if (arg_monitor) + test_monitor(udev); + + test_util_replace_whitespace(); + test_util_resolve_subsys_kernel(); + + test_list(); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/test/test-list.c b/src/test/test-list.c new file mode 100644 index 00000000..24e0496d --- /dev/null +++ b/src/test/test-list.c @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2013 Jan Janssen +***/ + +#include "list.h" +#include "util.h" + +int main(int argc, const char *argv[]) { + size_t i; + typedef struct list_item { + LIST_FIELDS(struct list_item, item); + } list_item; + LIST_HEAD(list_item, head); + list_item items[4]; + list_item *cursor; + + LIST_HEAD_INIT(head); + assert_se(head == NULL); + + for (i = 0; i < ELEMENTSOF(items); i++) { + LIST_INIT(item, &items[i]); + assert_se(LIST_JUST_US(item, &items[i])); + LIST_PREPEND(item, head, &items[i]); + } + + i = 0; + LIST_FOREACH_OTHERS(item, cursor, &items[2]) { + i++; + assert_se(cursor != &items[2]); + } + assert_se(i == ELEMENTSOF(items)-1); + + i = 0; + LIST_FOREACH_OTHERS(item, cursor, &items[0]) { + i++; + assert_se(cursor != &items[0]); + } + assert_se(i == ELEMENTSOF(items)-1); + + i = 0; + LIST_FOREACH_OTHERS(item, cursor, &items[3]) { + i++; + assert_se(cursor != &items[3]); + } + assert_se(i == ELEMENTSOF(items)-1); + + assert_se(!LIST_JUST_US(item, head)); + + assert_se(items[0].item_next == NULL); + assert_se(items[1].item_next == &items[0]); + assert_se(items[2].item_next == &items[1]); + assert_se(items[3].item_next == &items[2]); + + assert_se(items[0].item_prev == &items[1]); + assert_se(items[1].item_prev == &items[2]); + assert_se(items[2].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + + LIST_FIND_HEAD(item, &items[0], cursor); + assert_se(cursor == &items[3]); + + LIST_FIND_TAIL(item, &items[3], cursor); + assert_se(cursor == &items[0]); + + LIST_REMOVE(item, head, &items[1]); + assert_se(LIST_JUST_US(item, &items[1])); + + assert_se(items[0].item_next == NULL); + assert_se(items[2].item_next == &items[0]); + assert_se(items[3].item_next == &items[2]); + + assert_se(items[0].item_prev == &items[2]); + assert_se(items[2].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + + LIST_INSERT_AFTER(item, head, &items[3], &items[1]); + assert_se(items[0].item_next == NULL); + assert_se(items[2].item_next == &items[0]); + assert_se(items[1].item_next == &items[2]); + assert_se(items[3].item_next == &items[1]); + + assert_se(items[0].item_prev == &items[2]); + assert_se(items[2].item_prev == &items[1]); + assert_se(items[1].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + + LIST_REMOVE(item, head, &items[1]); + assert_se(LIST_JUST_US(item, &items[1])); + + assert_se(items[0].item_next == NULL); + assert_se(items[2].item_next == &items[0]); + assert_se(items[3].item_next == &items[2]); + + assert_se(items[0].item_prev == &items[2]); + assert_se(items[2].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + + LIST_INSERT_BEFORE(item, head, &items[2], &items[1]); + assert_se(items[0].item_next == NULL); + assert_se(items[2].item_next == &items[0]); + assert_se(items[1].item_next == &items[2]); + assert_se(items[3].item_next == &items[1]); + + assert_se(items[0].item_prev == &items[2]); + assert_se(items[2].item_prev == &items[1]); + assert_se(items[1].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + + LIST_REMOVE(item, head, &items[0]); + assert_se(LIST_JUST_US(item, &items[0])); + + assert_se(items[2].item_next == NULL); + assert_se(items[1].item_next == &items[2]); + assert_se(items[3].item_next == &items[1]); + + assert_se(items[2].item_prev == &items[1]); + assert_se(items[1].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + + LIST_INSERT_BEFORE(item, head, &items[3], &items[0]); + assert_se(items[2].item_next == NULL); + assert_se(items[1].item_next == &items[2]); + assert_se(items[3].item_next == &items[1]); + assert_se(items[0].item_next == &items[3]); + + assert_se(items[2].item_prev == &items[1]); + assert_se(items[1].item_prev == &items[3]); + assert_se(items[3].item_prev == &items[0]); + assert_se(items[0].item_prev == NULL); + assert_se(head == &items[0]); + + LIST_REMOVE(item, head, &items[0]); + assert_se(LIST_JUST_US(item, &items[0])); + + assert_se(items[2].item_next == NULL); + assert_se(items[1].item_next == &items[2]); + assert_se(items[3].item_next == &items[1]); + + assert_se(items[2].item_prev == &items[1]); + assert_se(items[1].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + + LIST_INSERT_BEFORE(item, head, NULL, &items[0]); + assert_se(items[0].item_next == NULL); + assert_se(items[2].item_next == &items[0]); + assert_se(items[1].item_next == &items[2]); + assert_se(items[3].item_next == &items[1]); + + assert_se(items[0].item_prev == &items[2]); + assert_se(items[2].item_prev == &items[1]); + assert_se(items[1].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + + LIST_REMOVE(item, head, &items[0]); + assert_se(LIST_JUST_US(item, &items[0])); + + assert_se(items[2].item_next == NULL); + assert_se(items[1].item_next == &items[2]); + assert_se(items[3].item_next == &items[1]); + + assert_se(items[2].item_prev == &items[1]); + assert_se(items[1].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + + LIST_REMOVE(item, head, &items[1]); + assert_se(LIST_JUST_US(item, &items[1])); + + assert_se(items[2].item_next == NULL); + assert_se(items[3].item_next == &items[2]); + + assert_se(items[2].item_prev == &items[3]); + assert_se(items[3].item_prev == NULL); + + LIST_REMOVE(item, head, &items[2]); + assert_se(LIST_JUST_US(item, &items[2])); + assert_se(LIST_JUST_US(item, head)); + + LIST_REMOVE(item, head, &items[3]); + assert_se(LIST_JUST_US(item, &items[3])); + + assert_se(head == NULL); + + for (i = 0; i < ELEMENTSOF(items); i++) { + assert_se(LIST_JUST_US(item, &items[i])); + LIST_APPEND(item, head, &items[i]); + } + + assert_se(!LIST_JUST_US(item, head)); + + assert_se(items[0].item_next == &items[1]); + assert_se(items[1].item_next == &items[2]); + assert_se(items[2].item_next == &items[3]); + assert_se(items[3].item_next == NULL); + + assert_se(items[0].item_prev == NULL); + assert_se(items[1].item_prev == &items[0]); + assert_se(items[2].item_prev == &items[1]); + assert_se(items[3].item_prev == &items[2]); + + for (i = 0; i < ELEMENTSOF(items); i++) + LIST_REMOVE(item, head, &items[i]); + + assert_se(head == NULL); + + return 0; +} diff --git a/src/test/test-load-fragment.c b/src/test/test-load-fragment.c new file mode 100644 index 00000000..7de28643 --- /dev/null +++ b/src/test/test-load-fragment.c @@ -0,0 +1,798 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "all-units.h" +#include "alloc-util.h" +#include "capability-util.h" +#include "conf-parser.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "hostname-util.h" +#include "install-printf.h" +#include "install.h" +#include "load-fragment.h" +#include "macro.h" +#include "memory-util.h" +#include "rm-rf.h" +#include "specifier.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "tmpfile-util.h" +#include "user-util.h" + +static int test_unit_file_get_set(void) { + int r; + Hashmap *h; + Iterator i; + UnitFileList *p; + + h = hashmap_new(&string_hash_ops); + assert_se(h); + + r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL); + if (IN_SET(r, -EPERM, -EACCES)) + return log_tests_skipped_errno(r, "unit_file_get_list"); + + log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r, + "unit_file_get_list: %m"); + if (r < 0) + return EXIT_FAILURE; + + HASHMAP_FOREACH(p, h, i) + printf("%s = %s\n", p->path, unit_file_state_to_string(p->state)); + + unit_file_list_free(h); + + return 0; +} + +static void check_execcommand(ExecCommand *c, + const char* path, + const char* argv0, + const char* argv1, + const char* argv2, + bool ignore) { + size_t n; + + assert_se(c); + log_info("expect: \"%s\" [\"%s\" \"%s\" \"%s\"]", + path, argv0 ?: path, argv1, argv2); + n = strv_length(c->argv); + log_info("actual: \"%s\" [\"%s\" \"%s\" \"%s\"]", + c->path, c->argv[0], n > 0 ? c->argv[1] : NULL, n > 1 ? c->argv[2] : NULL); + assert_se(streq(c->path, path)); + assert_se(streq(c->argv[0], argv0 ?: path)); + if (n > 0) + assert_se(streq_ptr(c->argv[1], argv1)); + if (n > 1) + assert_se(streq_ptr(c->argv[2], argv2)); + assert_se(!!(c->flags & EXEC_COMMAND_IGNORE_FAILURE) == ignore); +} + +static void test_config_parse_exec(void) { + /* int config_parse_exec( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) */ + int r; + + ExecCommand *c = NULL, *c1; + const char *ccc; + _cleanup_(manager_freep) Manager *m = NULL; + _cleanup_(unit_freep) Unit *u = NULL; + + r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m); + if (manager_errno_skip_test(r)) { + log_notice_errno(r, "Skipping test: manager_new: %m"); + return; + } + + assert_se(r >= 0); + assert_se(manager_startup(m, NULL, NULL) >= 0); + + assert_se(u = unit_new(m, sizeof(Service))); + + log_info("/* basic test */"); + r = config_parse_exec(NULL, "fake", 1, "section", 1, + "LValue", 0, "/RValue r1", + &c, u); + assert_se(r >= 0); + check_execcommand(c, "/RValue", "/RValue", "r1", NULL, false); + + r = config_parse_exec(NULL, "fake", 2, "section", 1, + "LValue", 0, "/RValue///slashes r1///", + &c, u); + + log_info("/* test slashes */"); + assert_se(r >= 0); + c1 = c->command_next; + check_execcommand(c1, "/RValue/slashes", "/RValue///slashes", "r1///", NULL, false); + + log_info("/* trailing slash */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "/RValue/ argv0 r1", + &c, u); + assert_se(r == -ENOEXEC); + assert_se(c1->command_next == NULL); + + log_info("/* honour_argv0 */"); + r = config_parse_exec(NULL, "fake", 3, "section", 1, + "LValue", 0, "@/RValue///slashes2 ///argv0 r1", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/RValue/slashes2", "///argv0", "r1", NULL, false); + + log_info("/* honour_argv0, no args */"); + r = config_parse_exec(NULL, "fake", 3, "section", 1, + "LValue", 0, "@/RValue", + &c, u); + assert_se(r == -ENOEXEC); + assert_se(c1->command_next == NULL); + + log_info("/* no command, whitespace only, reset */"); + r = config_parse_exec(NULL, "fake", 3, "section", 1, + "LValue", 0, "", + &c, u); + assert_se(r == 0); + assert_se(c == NULL); + + log_info("/* ignore && honour_argv0 */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "-@/RValue///slashes3 argv0a r1", + &c, u); + assert_se(r >= 0); + c1 = c; + check_execcommand(c1, "/RValue/slashes3", "argv0a", "r1", NULL, true); + + log_info("/* ignore && honour_argv0 */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "@-/RValue///slashes4 argv0b r1", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/RValue/slashes4", "argv0b", "r1", NULL, true); + + log_info("/* ignore && ignore */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "--/RValue argv0 r1", + &c, u); + assert_se(r == 0); + assert_se(c1->command_next == NULL); + + log_info("/* ignore && ignore (2) */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "-@-/RValue argv0 r1", + &c, u); + assert_se(r == 0); + assert_se(c1->command_next == NULL); + + log_info("/* semicolon */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "-@/RValue argv0 r1 ; " + "/goo/goo boo", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); + + c1 = c1->command_next; + check_execcommand(c1, "/goo/goo", NULL, "boo", NULL, false); + + log_info("/* two semicolons in a row */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "-@/RValue argv0 r1 ; ; " + "/goo/goo boo", + &c, u); + assert_se(r == -ENOEXEC); + c1 = c1->command_next; + check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); + + /* second command fails because the executable name is ";" */ + assert_se(c1->command_next == NULL); + + log_info("/* trailing semicolon */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "-@/RValue argv0 r1 ; ", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); + + assert_se(c1->command_next == NULL); + + log_info("/* trailing semicolon, no whitespace */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "-@/RValue argv0 r1 ;", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); + + assert_se(c1->command_next == NULL); + + log_info("/* trailing semicolon in single quotes */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "-@/RValue argv0 r1 ';'", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/RValue", "argv0", "r1", ";", true); + + log_info("/* escaped semicolon */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/bin/find \\;", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); + + log_info("/* escaped semicolon with following arg */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/sbin/find \\; /x", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/sbin/find", NULL, ";", "/x", false); + + log_info("/* escaped semicolon as part of an expression */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/sbin/find \\;x", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/sbin/find", NULL, "\\;x", NULL, false); + + log_info("/* encoded semicolon */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/bin/find \\073", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); + + log_info("/* quoted semicolon */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/bin/find \";\"", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/bin/find", NULL, ";", NULL, false); + + log_info("/* quoted semicolon with following arg */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/sbin/find \";\" /x", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/sbin/find", NULL, ";", "/x", false); + + log_info("/* spaces in the filename */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "\"/PATH WITH SPACES/daemon\" -1 -2", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false); + + log_info("/* spaces in the filename, no args */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "\"/PATH WITH SPACES/daemon -1 -2\"", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/PATH WITH SPACES/daemon -1 -2", NULL, NULL, NULL, false); + + log_info("/* spaces in the filename, everything quoted */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "\"/PATH WITH SPACES/daemon\" \"-1\" '-2'", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/PATH WITH SPACES/daemon", NULL, "-1", "-2", false); + + log_info("/* escaped spaces in the filename */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "\"/PATH\\sWITH\\sSPACES/daemon\" '-1 -2'", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false); + + log_info("/* escaped spaces in the filename (2) */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "\"/PATH\\x20WITH\\x20SPACES/daemon\" \"-1 -2\"", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, + "/PATH WITH SPACES/daemon", NULL, "-1 -2", NULL, false); + + for (ccc = "abfnrtv\\\'\"x"; *ccc; ccc++) { + /* \\x is an incomplete hexadecimal sequence, invalid because of the slash */ + char path[] = "/path\\X"; + path[sizeof(path) - 2] = *ccc; + + log_info("/* invalid character: \\%c */", *ccc); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, path, + &c, u); + assert_se(r == -ENOEXEC); + assert_se(c1->command_next == NULL); + } + + log_info("/* valid character: \\s */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "/path\\s", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/path ", NULL, NULL, NULL, false); + + log_info("/* quoted backslashes */"); + r = config_parse_exec(NULL, "fake", 5, "section", 1, + "LValue", 0, + "/bin/grep '\\w+\\K'", + &c, u); + assert_se(r >= 0); + c1 = c1->command_next; + check_execcommand(c1, "/bin/grep", NULL, "\\w+\\K", NULL, false); + + log_info("/* trailing backslash: \\ */"); + /* backslash is invalid */ + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "/path\\", + &c, u); + assert_se(r == -ENOEXEC); + assert_se(c1->command_next == NULL); + + log_info("/* missing ending ' */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "/path 'foo", + &c, u); + assert_se(r == -ENOEXEC); + assert_se(c1->command_next == NULL); + + log_info("/* missing ending ' with trailing backslash */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "/path 'foo\\", + &c, u); + assert_se(r == -ENOEXEC); + assert_se(c1->command_next == NULL); + + log_info("/* invalid space between modifiers */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "- /path", + &c, u); + assert_se(r == 0); + assert_se(c1->command_next == NULL); + + log_info("/* only modifiers, no path */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "-", + &c, u); + assert_se(r == 0); + assert_se(c1->command_next == NULL); + + log_info("/* empty argument, reset */"); + r = config_parse_exec(NULL, "fake", 4, "section", 1, + "LValue", 0, "", + &c, u); + assert_se(r == 0); + assert_se(c == NULL); + + exec_command_free_list(c); +} + +static void test_config_parse_log_extra_fields(void) { + /* int config_parse_log_extra_fields( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) */ + + int r; + + _cleanup_(manager_freep) Manager *m = NULL; + _cleanup_(unit_freep) Unit *u = NULL; + ExecContext c = {}; + + r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m); + if (manager_errno_skip_test(r)) { + log_notice_errno(r, "Skipping test: manager_new: %m"); + return; + } + + assert_se(r >= 0); + assert_se(manager_startup(m, NULL, NULL) >= 0); + + assert_se(u = unit_new(m, sizeof(Service))); + + log_info("/* %s – basic test */", __func__); + r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1, + "LValue", 0, "FOO=BAR \"QOOF=quux ' ' \"", + &c, u); + assert_se(r >= 0); + assert_se(c.n_log_extra_fields == 2); + assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len)); + assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len)); + + log_info("/* %s – add some */", __func__); + r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1, + "LValue", 0, "FOO2=BAR2 QOOF2=quux ' '", + &c, u); + assert_se(r >= 0); + assert_se(c.n_log_extra_fields == 4); + assert_se(strneq(c.log_extra_fields[0].iov_base, "FOO=BAR", c.log_extra_fields[0].iov_len)); + assert_se(strneq(c.log_extra_fields[1].iov_base, "QOOF=quux ' ' ", c.log_extra_fields[1].iov_len)); + assert_se(strneq(c.log_extra_fields[2].iov_base, "FOO2=BAR2", c.log_extra_fields[2].iov_len)); + assert_se(strneq(c.log_extra_fields[3].iov_base, "QOOF2=quux", c.log_extra_fields[3].iov_len)); + + exec_context_dump(&c, stdout, " --> "); + + log_info("/* %s – reset */", __func__); + r = config_parse_log_extra_fields(NULL, "fake", 1, "section", 1, + "LValue", 0, "", + &c, u); + assert_se(r >= 0); + assert_se(c.n_log_extra_fields == 0); + + exec_context_free_log_extra_fields(&c); + + log_info("/* %s – bye */", __func__); +} + +static void test_install_printf(void) { + char name[] = "name.service", + path[] = "/run/systemd/system/name.service"; + UnitFileInstallInfo i = { .name = name, .path = path, }; + UnitFileInstallInfo i2 = { .name= name, .path = path, }; + char name3[] = "name@inst.service", + path3[] = "/run/systemd/system/name.service"; + UnitFileInstallInfo i3 = { .name = name3, .path = path3, }; + UnitFileInstallInfo i4 = { .name = name3, .path = path3, }; + + _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL; + + assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid); + assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid); + assert_se(host = gethostname_malloc()); + assert_se(group = gid_to_name(getgid())); + assert_se(asprintf(&gid, UID_FMT, getgid()) >= 0); + assert_se(user = uid_to_name(getuid())); + assert_se(asprintf(&uid, UID_FMT, getuid()) >= 0); + +#define expect(src, pattern, result) \ + do { \ + _cleanup_free_ char *t = NULL; \ + _cleanup_free_ char \ + *d1 = strdup(i.name), \ + *d2 = strdup(i.path); \ + assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \ + memzero(i.name, strlen(i.name)); \ + memzero(i.path, strlen(i.path)); \ + assert_se(d1 && d2); \ + if (result) { \ + printf("%s\n", t); \ + assert_se(streq(t, result)); \ + } else assert_se(t == NULL); \ + strcpy(i.name, d1); \ + strcpy(i.path, d2); \ + } while (false) + + expect(i, "%n", "name.service"); + expect(i, "%N", "name"); + expect(i, "%p", "name"); + expect(i, "%i", ""); + expect(i, "%j", "name"); + expect(i, "%g", group); + expect(i, "%G", gid); + expect(i, "%u", user); + expect(i, "%U", uid); + + expect(i, "%m", mid); + expect(i, "%b", bid); + expect(i, "%H", host); + + expect(i2, "%g", group); + expect(i2, "%G", gid); + expect(i2, "%u", user); + expect(i2, "%U", uid); + + expect(i3, "%n", "name@inst.service"); + expect(i3, "%N", "name@inst"); + expect(i3, "%p", "name"); + expect(i3, "%g", group); + expect(i3, "%G", gid); + expect(i3, "%u", user); + expect(i3, "%U", uid); + + expect(i3, "%m", mid); + expect(i3, "%b", bid); + expect(i3, "%H", host); + + expect(i4, "%g", group); + expect(i4, "%G", gid); + expect(i4, "%u", user); + expect(i4, "%U", uid); +} + +static uint64_t make_cap(int cap) { + return ((uint64_t) 1ULL << (uint64_t) cap); +} + +static void test_config_parse_capability_set(void) { + /* int config_parse_capability_set( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) */ + int r; + uint64_t capability_bounding_set = 0; + + r = config_parse_capability_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, "CAP_NET_RAW", + &capability_bounding_set, NULL); + assert_se(r >= 0); + assert_se(capability_bounding_set == make_cap(CAP_NET_RAW)); + + r = config_parse_capability_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, "CAP_NET_ADMIN", + &capability_bounding_set, NULL); + assert_se(r >= 0); + assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN))); + + r = config_parse_capability_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, "~CAP_NET_ADMIN", + &capability_bounding_set, NULL); + assert_se(r >= 0); + assert_se(capability_bounding_set == make_cap(CAP_NET_RAW)); + + r = config_parse_capability_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, "", + &capability_bounding_set, NULL); + assert_se(r >= 0); + assert_se(capability_bounding_set == UINT64_C(0)); + + r = config_parse_capability_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, "~", + &capability_bounding_set, NULL); + assert_se(r >= 0); + assert_se(cap_test_all(capability_bounding_set)); + + capability_bounding_set = 0; + r = config_parse_capability_set(NULL, "fake", 1, "section", 1, + "CapabilityBoundingSet", 0, " 'CAP_NET_RAW' WAT_CAP??? CAP_NET_ADMIN CAP'_trailing_garbage", + &capability_bounding_set, NULL); + assert_se(r >= 0); + assert_se(capability_bounding_set == (make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN))); +} + +static void test_config_parse_rlimit(void) { + struct rlimit * rl[_RLIMIT_MAX] = {}; + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55", rl, NULL) >= 0); + assert_se(rl[RLIMIT_NOFILE]); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "55:66", rl, NULL) >= 0); + assert_se(rl[RLIMIT_NOFILE]); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 55); + assert_se(rl[RLIMIT_NOFILE]->rlim_max == 66); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity", rl, NULL) >= 0); + assert_se(rl[RLIMIT_NOFILE]); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "infinity:infinity", rl, NULL) >= 0); + assert_se(rl[RLIMIT_NOFILE]); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == RLIM_INFINITY); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == rl[RLIMIT_NOFILE]->rlim_max); + + rl[RLIMIT_NOFILE]->rlim_cur = 10; + rl[RLIMIT_NOFILE]->rlim_max = 20; + + /* Invalid values don't change rl */ + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "10:20:30", rl, NULL) >= 0); + assert_se(rl[RLIMIT_NOFILE]); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10); + assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "wat:wat", rl, NULL) >= 0); + assert_se(rl[RLIMIT_NOFILE]); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10); + assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "66:wat", rl, NULL) >= 0); + assert_se(rl[RLIMIT_NOFILE]); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10); + assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitNOFILE", RLIMIT_NOFILE, "200:100", rl, NULL) >= 0); + assert_se(rl[RLIMIT_NOFILE]); + assert_se(rl[RLIMIT_NOFILE]->rlim_cur == 10); + assert_se(rl[RLIMIT_NOFILE]->rlim_max == 20); + + rl[RLIMIT_NOFILE] = mfree(rl[RLIMIT_NOFILE]); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "56", rl, NULL) >= 0); + assert_se(rl[RLIMIT_CPU]); + assert_se(rl[RLIMIT_CPU]->rlim_cur == 56); + assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "57s", rl, NULL) >= 0); + assert_se(rl[RLIMIT_CPU]); + assert_se(rl[RLIMIT_CPU]->rlim_cur == 57); + assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "40s:1m", rl, NULL) >= 0); + assert_se(rl[RLIMIT_CPU]); + assert_se(rl[RLIMIT_CPU]->rlim_cur == 40); + assert_se(rl[RLIMIT_CPU]->rlim_max == 60); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "infinity", rl, NULL) >= 0); + assert_se(rl[RLIMIT_CPU]); + assert_se(rl[RLIMIT_CPU]->rlim_cur == RLIM_INFINITY); + assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitCPU", RLIMIT_CPU, "1234ms", rl, NULL) >= 0); + assert_se(rl[RLIMIT_CPU]); + assert_se(rl[RLIMIT_CPU]->rlim_cur == 2); + assert_se(rl[RLIMIT_CPU]->rlim_cur == rl[RLIMIT_CPU]->rlim_max); + + rl[RLIMIT_CPU] = mfree(rl[RLIMIT_CPU]); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "58:60", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 58); + assert_se(rl[RLIMIT_RTTIME]->rlim_max == 60); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "59s:123s", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 59 * USEC_PER_SEC); + assert_se(rl[RLIMIT_RTTIME]->rlim_max == 123 * USEC_PER_SEC); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "infinity:infinity", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == RLIM_INFINITY); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); + + assert_se(config_parse_rlimit(NULL, "fake", 1, "section", 1, "LimitRTTIME", RLIMIT_RTTIME, "2345ms", rl, NULL) >= 0); + assert_se(rl[RLIMIT_RTTIME]); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == 2345 * USEC_PER_MSEC); + assert_se(rl[RLIMIT_RTTIME]->rlim_cur == rl[RLIMIT_RTTIME]->rlim_max); + + rl[RLIMIT_RTTIME] = mfree(rl[RLIMIT_RTTIME]); +} + +static void test_config_parse_pass_environ(void) { + /* int config_parse_pass_environ( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) */ + int r; + _cleanup_strv_free_ char **passenv = NULL; + + r = config_parse_pass_environ(NULL, "fake", 1, "section", 1, + "PassEnvironment", 0, "A B", + &passenv, NULL); + assert_se(r >= 0); + assert_se(strv_length(passenv) == 2); + assert_se(streq(passenv[0], "A")); + assert_se(streq(passenv[1], "B")); + + r = config_parse_pass_environ(NULL, "fake", 1, "section", 1, + "PassEnvironment", 0, "", + &passenv, NULL); + assert_se(r >= 0); + assert_se(strv_isempty(passenv)); + + r = config_parse_pass_environ(NULL, "fake", 1, "section", 1, + "PassEnvironment", 0, "'invalid name' 'normal_name' A=1 \\", + &passenv, NULL); + assert_se(r >= 0); + assert_se(strv_length(passenv) == 1); + assert_se(streq(passenv[0], "normal_name")); + +} + +static void test_unit_dump_config_items(void) { + unit_dump_config_items(stdout); +} + +int main(int argc, char *argv[]) { + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + int r; + + test_setup_logging(LOG_INFO); + + r = enter_cgroup_subroot(NULL); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + assert_se(runtime_dir = setup_fake_runtime_dir()); + + r = test_unit_file_get_set(); + test_config_parse_exec(); + test_config_parse_log_extra_fields(); + test_config_parse_capability_set(); + test_config_parse_rlimit(); + test_config_parse_pass_environ(); + TEST_REQ_RUNNING_SYSTEMD(test_install_printf()); + test_unit_dump_config_items(); + + return r; +} diff --git a/src/test/test-local-addresses.c b/src/test/test-local-addresses.c new file mode 100644 index 00000000..37505ea7 --- /dev/null +++ b/src/test/test-local-addresses.c @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "af-list.h" +#include "alloc-util.h" +#include "in-addr-util.h" +#include "local-addresses.h" +#include "tests.h" + +static void print_local_addresses(struct local_address *a, unsigned n) { + unsigned i; + + for (i = 0; i < n; i++) { + _cleanup_free_ char *b = NULL; + + assert_se(in_addr_to_string(a[i].family, &a[i].address, &b) >= 0); + printf("%s if%i scope=%i metric=%u address=%s\n", af_to_name(a[i].family), a[i].ifindex, a[i].scope, a[i].metric, b); + } +} + +int main(int argc, char *argv[]) { + struct local_address *a; + int n; + + test_setup_logging(LOG_DEBUG); + + a = NULL; + n = local_addresses(NULL, 0, AF_UNSPEC, &a); + assert_se(n >= 0); + + printf("Local Addresses:\n"); + print_local_addresses(a, (unsigned) n); + a = mfree(a); + + n = local_gateways(NULL, 0, AF_UNSPEC, &a); + assert_se(n >= 0); + + printf("Local Gateways:\n"); + print_local_addresses(a, (unsigned) n); + free(a); + + return 0; +} diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c new file mode 100644 index 00000000..28d90be8 --- /dev/null +++ b/src/test/test-locale-util.c @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "kbd-util.h" +#include "locale-util.h" +#include "macro.h" +#include "strv.h" +#include "util.h" + +static void test_get_locales(void) { + _cleanup_strv_free_ char **locales = NULL; + char **p; + int r; + + r = get_locales(&locales); + assert_se(r >= 0); + assert_se(locales); + + STRV_FOREACH(p, locales) { + puts(*p); + assert_se(locale_is_valid(*p)); + } +} + +static void test_locale_is_valid(void) { + log_info("/* %s */", __func__); + + assert_se(locale_is_valid("en_EN.utf8")); + assert_se(locale_is_valid("fr_FR.utf8")); + assert_se(locale_is_valid("fr_FR@euro")); + assert_se(locale_is_valid("fi_FI")); + assert_se(locale_is_valid("POSIX")); + assert_se(locale_is_valid("C")); + + assert_se(!locale_is_valid("")); + assert_se(!locale_is_valid("/usr/bin/foo")); + assert_se(!locale_is_valid("\x01gar\x02 bage\x03")); +} + +static void test_keymaps(void) { + _cleanup_strv_free_ char **kmaps = NULL; + char **p; + int r; + + log_info("/* %s */", __func__); + + assert_se(!keymap_is_valid("")); + assert_se(!keymap_is_valid("/usr/bin/foo")); + assert_se(!keymap_is_valid("\x01gar\x02 bage\x03")); + + r = get_keymaps(&kmaps); + if (r == -ENOENT) + return; /* skip test if no keymaps are installed */ + + assert_se(r >= 0); + assert_se(kmaps); + + STRV_FOREACH(p, kmaps) { + puts(*p); + assert_se(keymap_is_valid(*p)); + } + + assert_se(keymap_is_valid("uk")); + assert_se(keymap_is_valid("de-nodeadkeys")); + assert_se(keymap_is_valid("ANSI-dvorak")); + assert_se(keymap_is_valid("unicode")); +} + +#define dump_glyph(x) log_info(STRINGIFY(x) ": %s", special_glyph(x)) +static void dump_special_glyphs(void) { + assert_cc(SPECIAL_GLYPH_DEPRESSED_SMILEY + 1 == _SPECIAL_GLYPH_MAX); + + log_info("/* %s */", __func__); + + log_info("is_locale_utf8: %s", yes_no(is_locale_utf8())); + + dump_glyph(SPECIAL_GLYPH_TREE_VERTICAL); + dump_glyph(SPECIAL_GLYPH_TREE_BRANCH); + dump_glyph(SPECIAL_GLYPH_TREE_RIGHT); + dump_glyph(SPECIAL_GLYPH_TREE_SPACE); + dump_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET); + dump_glyph(SPECIAL_GLYPH_BLACK_CIRCLE); + dump_glyph(SPECIAL_GLYPH_BULLET); + dump_glyph(SPECIAL_GLYPH_ARROW); + dump_glyph(SPECIAL_GLYPH_MDASH); + dump_glyph(SPECIAL_GLYPH_ELLIPSIS); + dump_glyph(SPECIAL_GLYPH_MU); + dump_glyph(SPECIAL_GLYPH_CHECK_MARK); + dump_glyph(SPECIAL_GLYPH_CROSS_MARK); + dump_glyph(SPECIAL_GLYPH_ECSTATIC_SMILEY); + dump_glyph(SPECIAL_GLYPH_HAPPY_SMILEY); + dump_glyph(SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY); + dump_glyph(SPECIAL_GLYPH_NEUTRAL_SMILEY); + dump_glyph(SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY); + dump_glyph(SPECIAL_GLYPH_UNHAPPY_SMILEY); + dump_glyph(SPECIAL_GLYPH_DEPRESSED_SMILEY); +} + +int main(int argc, char *argv[]) { + test_get_locales(); + test_locale_is_valid(); + test_keymaps(); + + dump_special_glyphs(); + + return 0; +} diff --git a/src/test/test-log.c b/src/test/test-log.c new file mode 100644 index 00000000..c1f2f8b0 --- /dev/null +++ b/src/test/test-log.c @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "format-util.h" +#include "log.h" +#include "process-util.h" +#include "string-util.h" +#include "util.h" + +assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_FTP | LOG_DEBUG)) + == LOG_REALM_SYSTEMD); +assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_UDEV, LOG_LOCAL7 | LOG_DEBUG)) + == LOG_REALM_UDEV); +assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_LOCAL3 | LOG_DEBUG) & LOG_FACMASK) + == LOG_LOCAL3); +assert_cc((LOG_REALM_PLUS_LEVEL(LOG_REALM_UDEV, LOG_USER | LOG_INFO) & LOG_PRIMASK) + == LOG_INFO); + +assert_cc(IS_SYNTHETIC_ERRNO(SYNTHETIC_ERRNO(EINVAL))); +assert_cc(!IS_SYNTHETIC_ERRNO(EINVAL)); +assert_cc(IS_SYNTHETIC_ERRNO(SYNTHETIC_ERRNO(0))); +assert_cc(!IS_SYNTHETIC_ERRNO(0)); + +#define X10(x) x x x x x x x x x x +#define X100(x) X10(X10(x)) +#define X1000(x) X100(X10(x)) + +static void test_file(void) { + log_info("__FILE__: %s", __FILE__); + log_info("RELATIVE_SOURCE_PATH: %s", RELATIVE_SOURCE_PATH); + log_info("PROJECT_FILE: %s", PROJECT_FILE); + + assert(startswith(__FILE__, RELATIVE_SOURCE_PATH "/")); +} + +static void test_log_struct(void) { + log_struct(LOG_INFO, + "MESSAGE=Waldo PID="PID_FMT" (no errno)", getpid_cached(), + "SERVICE=piepapo"); + + log_struct_errno(LOG_INFO, EILSEQ, + "MESSAGE=Waldo PID="PID_FMT": %m (normal)", getpid_cached(), + "SERVICE=piepapo"); + + log_struct_errno(LOG_INFO, SYNTHETIC_ERRNO(EILSEQ), + "MESSAGE=Waldo PID="PID_FMT": %m (synthetic)", getpid_cached(), + "SERVICE=piepapo"); + + log_struct(LOG_INFO, + "MESSAGE=Foobar PID="PID_FMT, getpid_cached(), + "FORMAT_STR_TEST=1=%i A=%c 2=%hi 3=%li 4=%lli 1=%p foo=%s 2.5=%g 3.5=%g 4.5=%Lg", + (int) 1, 'A', (short) 2, (long int) 3, (long long int) 4, (void*) 1, "foo", (float) 2.5f, (double) 3.5, (long double) 4.5, + "SUFFIX=GOT IT"); +} + +static void test_long_lines(void) { + log_object_internal(LOG_NOTICE, + EUCLEAN, + X1000("abcd_") ".txt", + 1000000, + X1000("fff") "unc", + "OBJECT=", + X1000("obj_") "ect", + "EXTRA=", + X1000("ext_") "tra", + "asdfasdf %s asdfasdfa", "foobar"); +} + +static void test_log_syntax(void) { + assert_se(log_syntax("unit", LOG_ERR, "filename", 10, EINVAL, "EINVAL: %s: %m", "hogehoge") == -EINVAL); + assert_se(log_syntax("unit", LOG_ERR, "filename", 10, -ENOENT, "ENOENT: %s: %m", "hogehoge") == -ENOENT); + assert_se(log_syntax("unit", LOG_ERR, "filename", 10, SYNTHETIC_ERRNO(ENOTTY), "ENOTTY: %s: %m", "hogehoge") == -ENOTTY); +} + +int main(int argc, char* argv[]) { + int target; + + test_file(); + + for (target = 0; target < _LOG_TARGET_MAX; target++) { + log_set_target(target); + log_open(); + + test_log_struct(); + test_long_lines(); + test_log_syntax(); + } + + assert_se(log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), "foo") == -EUCLEAN); + + return 0; +} diff --git a/src/test/test-loopback.c b/src/test/test-loopback.c new file mode 100644 index 00000000..89b760fa --- /dev/null +++ b/src/test/test-loopback.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "log.h" +#include "loopback-setup.h" +#include "tests.h" + +int main(int argc, char* argv[]) { + int r; + + test_setup_logging(LOG_DEBUG); + + r = loopback_setup(); + if (r < 0) + log_error_errno(r, "loopback: %m"); + + return r >= 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c new file mode 100644 index 00000000..6986405d --- /dev/null +++ b/src/test/test-mount-util.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "mount-util.h" +#include "string-util.h" +#include "tests.h" + +static void test_mount_option_mangle(void) { + char *opts = NULL; + unsigned long f; + + assert_se(mount_option_mangle(NULL, MS_RDONLY|MS_NOSUID, &f, &opts) == 0); + assert_se(f == (MS_RDONLY|MS_NOSUID)); + assert_se(opts == NULL); + + assert_se(mount_option_mangle("", MS_RDONLY|MS_NOSUID, &f, &opts) == 0); + assert_se(f == (MS_RDONLY|MS_NOSUID)); + assert_se(opts == NULL); + + assert_se(mount_option_mangle("ro,nosuid,nodev,noexec", 0, &f, &opts) == 0); + assert_se(f == (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC)); + assert_se(opts == NULL); + + assert_se(mount_option_mangle("ro,nosuid,nodev,noexec,mode=755", 0, &f, &opts) == 0); + assert_se(f == (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC)); + assert_se(streq(opts, "mode=755")); + opts = mfree(opts); + + assert_se(mount_option_mangle("rw,nosuid,foo,hogehoge,nodev,mode=755", 0, &f, &opts) == 0); + assert_se(f == (MS_NOSUID|MS_NODEV)); + assert_se(streq(opts, "foo,hogehoge,mode=755")); + opts = mfree(opts); + + assert_se(mount_option_mangle("rw,nosuid,nodev,noexec,relatime,net_cls,net_prio", MS_RDONLY, &f, &opts) == 0); + assert_se(f == (MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_RELATIME)); + assert_se(streq(opts, "net_cls,net_prio")); + opts = mfree(opts); + + assert_se(mount_option_mangle("rw,nosuid,nodev,relatime,size=1630748k,mode=700,uid=1000,gid=1000", MS_RDONLY, &f, &opts) == 0); + assert_se(f == (MS_NOSUID|MS_NODEV|MS_RELATIME)); + assert_se(streq(opts, "size=1630748k,mode=700,uid=1000,gid=1000")); + opts = mfree(opts); + + assert_se(mount_option_mangle("size=1630748k,rw,gid=1000,,,nodev,relatime,,mode=700,nosuid,uid=1000", MS_RDONLY, &f, &opts) == 0); + assert_se(f == (MS_NOSUID|MS_NODEV|MS_RELATIME)); + assert_se(streq(opts, "size=1630748k,gid=1000,mode=700,uid=1000")); + opts = mfree(opts); + + assert_se(mount_option_mangle("rw,exec,size=8143984k,nr_inodes=2035996,mode=755", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, &f, &opts) == 0); + assert_se(f == (MS_NOSUID|MS_NODEV)); + assert_se(streq(opts, "size=8143984k,nr_inodes=2035996,mode=755")); + opts = mfree(opts); + + assert_se(mount_option_mangle("rw,relatime,fmask=0022,,,dmask=0022", MS_RDONLY, &f, &opts) == 0); + assert_se(f == MS_RELATIME); + assert_se(streq(opts, "fmask=0022,dmask=0022")); + opts = mfree(opts); + + assert_se(mount_option_mangle("rw,relatime,fmask=0022,dmask=0022,\"hogehoge", MS_RDONLY, &f, &opts) < 0); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_mount_option_mangle(); + + return 0; +} diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c new file mode 100644 index 00000000..499873f0 --- /dev/null +++ b/src/test/test-mountpoint-util.c @@ -0,0 +1,274 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "def.h" +#include "fd-util.h" +#include "fileio.h" +#include "hashmap.h" +#include "log.h" +#include "mountpoint-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "string-util.h" +#include "tests.h" + +static void test_mount_propagation_flags(const char *name, int ret, unsigned long expected) { + long unsigned flags; + + log_info("/* %s(%s) */", __func__, name); + + assert_se(mount_propagation_flags_from_string(name, &flags) == ret); + + if (ret >= 0) { + const char *c; + + assert_se(flags == expected); + + c = mount_propagation_flags_to_string(flags); + if (isempty(name)) + assert_se(isempty(c)); + else + assert_se(streq(c, name)); + } +} + +static void test_mnt_id(void) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_hashmap_free_free_ Hashmap *h = NULL; + Iterator i; + char *p; + void *k; + int r; + + log_info("/* %s */", __func__); + + assert_se(f = fopen("/proc/self/mountinfo", "re")); + assert_se(h = hashmap_new(&trivial_hash_ops)); + + for (;;) { + _cleanup_free_ char *line = NULL, *path = NULL; + int mnt_id; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r == 0) + break; + assert_se(r > 0); + + assert_se(sscanf(line, "%i %*s %*s %*s %ms", &mnt_id, &path) == 2); +#if HAS_FEATURE_MEMORY_SANITIZER + /* We don't know the length of the string, so we need to unpoison it one char at a time */ + for (const char *c = path; ;c++) { + msan_unpoison(c, 1); + if (!*c) + break; + } +#endif + log_debug("mountinfo: %s → %i", path, mnt_id); + + assert_se(hashmap_put(h, INT_TO_PTR(mnt_id), path) >= 0); + path = NULL; + } + + HASHMAP_FOREACH_KEY(p, k, h, i) { + int mnt_id = PTR_TO_INT(k), mnt_id2; + + r = path_get_mnt_id(p, &mnt_id2); + if (r < 0) { + log_debug_errno(r, "Failed to get the mnt id of %s: %m\n", p); + continue; + } + + if (mnt_id == mnt_id2) { + log_debug("mnt ids of %s is %i\n", p, mnt_id); + continue; + } else + log_debug("mnt ids of %s are %i, %i\n", p, mnt_id, mnt_id2); + + /* The ids don't match? If so, then there are two mounts on the same path, let's check if + * that's really the case */ + char *t = hashmap_get(h, INT_TO_PTR(mnt_id2)); + log_debug("the other path for mnt id %i is %s\n", mnt_id2, t); + assert_se(path_equal(p, t)); + } +} + +static void test_path_is_mount_point(void) { + int fd; + char tmp_dir[] = "/tmp/test-path-is-mount-point-XXXXXX"; + _cleanup_free_ char *file1 = NULL, *file2 = NULL, *link1 = NULL, *link2 = NULL; + _cleanup_free_ char *dir1 = NULL, *dir1file = NULL, *dirlink1 = NULL, *dirlink1file = NULL; + _cleanup_free_ char *dir2 = NULL, *dir2file = NULL; + + log_info("/* %s */", __func__); + + assert_se(path_is_mount_point("/", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/", NULL, 0) > 0); + assert_se(path_is_mount_point("//", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("//", NULL, 0) > 0); + + assert_se(path_is_mount_point("/proc", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/proc", NULL, 0) > 0); + assert_se(path_is_mount_point("/proc/", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/proc/", NULL, 0) > 0); + + assert_se(path_is_mount_point("/proc/1", NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point("/proc/1", NULL, 0) == 0); + assert_se(path_is_mount_point("/proc/1/", NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point("/proc/1/", NULL, 0) == 0); + + assert_se(path_is_mount_point("/sys", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/sys", NULL, 0) > 0); + assert_se(path_is_mount_point("/sys/", NULL, AT_SYMLINK_FOLLOW) > 0); + assert_se(path_is_mount_point("/sys/", NULL, 0) > 0); + + /* we'll create a hierarchy of different kinds of dir/file/link + * layouts: + * + * /file1, /file2 + * /link1 -> file1, /link2 -> file2 + * /dir1/ + * /dir1/file + * /dirlink1 -> dir1 + * /dirlink1file -> dirlink1/file + * /dir2/ + * /dir2/file + */ + + /* file mountpoints */ + assert_se(mkdtemp(tmp_dir) != NULL); + file1 = path_join(tmp_dir, "file1"); + assert_se(file1); + file2 = path_join(tmp_dir, "file2"); + assert_se(file2); + fd = open(file1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + fd = open(file2, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + link1 = path_join(tmp_dir, "link1"); + assert_se(link1); + assert_se(symlink("file1", link1) == 0); + link2 = path_join(tmp_dir, "link2"); + assert_se(link1); + assert_se(symlink("file2", link2) == 0); + + assert_se(path_is_mount_point(file1, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(file1, NULL, 0) == 0); + assert_se(path_is_mount_point(link1, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(link1, NULL, 0) == 0); + + /* directory mountpoints */ + dir1 = path_join(tmp_dir, "dir1"); + assert_se(dir1); + assert_se(mkdir(dir1, 0755) == 0); + dirlink1 = path_join(tmp_dir, "dirlink1"); + assert_se(dirlink1); + assert_se(symlink("dir1", dirlink1) == 0); + dirlink1file = path_join(tmp_dir, "dirlink1file"); + assert_se(dirlink1file); + assert_se(symlink("dirlink1/file", dirlink1file) == 0); + dir2 = path_join(tmp_dir, "dir2"); + assert_se(dir2); + assert_se(mkdir(dir2, 0755) == 0); + + assert_se(path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dir1, NULL, 0) == 0); + assert_se(path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dirlink1, NULL, 0) == 0); + + /* file in subdirectory mountpoints */ + dir1file = path_join(dir1, "file"); + assert_se(dir1file); + fd = open(dir1file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + + assert_se(path_is_mount_point(dir1file, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dir1file, NULL, 0) == 0); + assert_se(path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point(dirlink1file, NULL, 0) == 0); + + /* these tests will only work as root */ + if (mount(file1, file2, NULL, MS_BIND, NULL) >= 0) { + int rf, rt, rdf, rdt, rlf, rlt, rl1f, rl1t; + const char *file2d; + + /* files */ + /* capture results in vars, to avoid dangling mounts on failure */ + log_info("%s: %s", __func__, file2); + rf = path_is_mount_point(file2, NULL, 0); + rt = path_is_mount_point(file2, NULL, AT_SYMLINK_FOLLOW); + + file2d = strjoina(file2, "/"); + log_info("%s: %s", __func__, file2d); + rdf = path_is_mount_point(file2d, NULL, 0); + rdt = path_is_mount_point(file2d, NULL, AT_SYMLINK_FOLLOW); + + log_info("%s: %s", __func__, link2); + rlf = path_is_mount_point(link2, NULL, 0); + rlt = path_is_mount_point(link2, NULL, AT_SYMLINK_FOLLOW); + + assert_se(umount(file2) == 0); + + assert_se(rf == 1); + assert_se(rt == 1); + assert_se(rdf == -ENOTDIR); + assert_se(rdt == -ENOTDIR); + assert_se(rlf == 0); + assert_se(rlt == 1); + + /* dirs */ + dir2file = path_join(dir2, "file"); + assert_se(dir2file); + fd = open(dir2file, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0664); + assert_se(fd > 0); + close(fd); + + assert_se(mount(dir2, dir1, NULL, MS_BIND, NULL) >= 0); + + log_info("%s: %s", __func__, dir1); + rf = path_is_mount_point(dir1, NULL, 0); + rt = path_is_mount_point(dir1, NULL, AT_SYMLINK_FOLLOW); + log_info("%s: %s", __func__, dirlink1); + rlf = path_is_mount_point(dirlink1, NULL, 0); + rlt = path_is_mount_point(dirlink1, NULL, AT_SYMLINK_FOLLOW); + log_info("%s: %s", __func__, dirlink1file); + /* its parent is a mount point, but not /file itself */ + rl1f = path_is_mount_point(dirlink1file, NULL, 0); + rl1t = path_is_mount_point(dirlink1file, NULL, AT_SYMLINK_FOLLOW); + + assert_se(umount(dir1) == 0); + + assert_se(rf == 1); + assert_se(rt == 1); + assert_se(rlf == 0); + assert_se(rlt == 1); + assert_se(rl1f == 0); + assert_se(rl1t == 0); + + } else + printf("Skipping bind mount file test: %m\n"); + + assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_mount_propagation_flags("shared", 0, MS_SHARED); + test_mount_propagation_flags("slave", 0, MS_SLAVE); + test_mount_propagation_flags("private", 0, MS_PRIVATE); + test_mount_propagation_flags(NULL, 0, 0); + test_mount_propagation_flags("", 0, 0); + test_mount_propagation_flags("xxxx", -EINVAL, 0); + test_mount_propagation_flags(" ", -EINVAL, 0); + + test_mnt_id(); + test_path_is_mount_point(); + + return 0; +} diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c new file mode 100644 index 00000000..41ea733b --- /dev/null +++ b/src/test/test-namespace.c @@ -0,0 +1,200 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "namespace.h" +#include "process-util.h" +#include "string-util.h" +#include "tests.h" +#include "user-util.h" +#include "util.h" +#include "virt.h" + +static void test_tmpdir(const char *id, const char *A, const char *B) { + _cleanup_free_ char *a, *b; + struct stat x, y; + char *c, *d; + + assert_se(setup_tmp_dirs(id, &a, &b) == 0); + assert_se(startswith(a, A)); + assert_se(startswith(b, B)); + + assert_se(stat(a, &x) >= 0); + assert_se(stat(b, &y) >= 0); + + assert_se(S_ISDIR(x.st_mode)); + assert_se(S_ISDIR(y.st_mode)); + + assert_se((x.st_mode & 01777) == 0700); + assert_se((y.st_mode & 01777) == 0700); + + c = strjoina(a, "/tmp"); + d = strjoina(b, "/tmp"); + + assert_se(stat(c, &x) >= 0); + assert_se(stat(d, &y) >= 0); + + assert_se(S_ISDIR(x.st_mode)); + assert_se(S_ISDIR(y.st_mode)); + + assert_se((x.st_mode & 01777) == 01777); + assert_se((y.st_mode & 01777) == 01777); + + assert_se(rmdir(c) >= 0); + assert_se(rmdir(d) >= 0); + + assert_se(rmdir(a) >= 0); + assert_se(rmdir(b) >= 0); +} + +static void test_netns(void) { + _cleanup_close_pair_ int s[2] = { -1, -1 }; + pid_t pid1, pid2, pid3; + int r, n = 0; + siginfo_t si; + + if (geteuid() > 0) { + (void) log_tests_skipped("not root"); + return; + } + + assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, s) >= 0); + + pid1 = fork(); + assert_se(pid1 >= 0); + + if (pid1 == 0) { + r = setup_netns(s); + assert_se(r >= 0); + _exit(r); + } + + pid2 = fork(); + assert_se(pid2 >= 0); + + if (pid2 == 0) { + r = setup_netns(s); + assert_se(r >= 0); + exit(r); + } + + pid3 = fork(); + assert_se(pid3 >= 0); + + if (pid3 == 0) { + r = setup_netns(s); + assert_se(r >= 0); + exit(r); + } + + r = wait_for_terminate(pid1, &si); + assert_se(r >= 0); + assert_se(si.si_code == CLD_EXITED); + n += si.si_status; + + r = wait_for_terminate(pid2, &si); + assert_se(r >= 0); + assert_se(si.si_code == CLD_EXITED); + n += si.si_status; + + r = wait_for_terminate(pid3, &si); + assert_se(r >= 0); + assert_se(si.si_code == CLD_EXITED); + n += si.si_status; + + assert_se(n == 1); +} + +static void test_protect_kernel_logs(void) { + int r; + pid_t pid; + static const NamespaceInfo ns_info = { + .protect_kernel_logs = true, + }; + + if (geteuid() > 0) { + (void) log_tests_skipped("not root"); + return; + } + + /* In a container we likely don't have access to /dev/kmsg */ + if (detect_container() > 0) { + (void) log_tests_skipped("in container"); + return; + } + + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + _cleanup_close_ int fd = -1; + + fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC); + assert_se(fd > 0); + + r = setup_namespace(NULL, + NULL, + &ns_info, + NULL, + NULL, + NULL, + NULL, + NULL, 0, + NULL, 0, + NULL, + NULL, + PROTECT_HOME_NO, + PROTECT_SYSTEM_NO, + 0, + 0, + NULL); + assert_se(r == 0); + + assert_se(setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY) >= 0); + assert_se(open("/dev/kmsg", O_RDONLY | O_CLOEXEC) < 0); + assert_se(errno == EACCES); + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +int main(int argc, char *argv[]) { + sd_id128_t bid; + char boot_id[SD_ID128_STRING_MAX]; + _cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL; + + test_setup_logging(LOG_INFO); + + if (!have_namespaces()) { + log_tests_skipped("Don't have namespace support"); + return EXIT_TEST_SKIP; + } + + assert_se(sd_id128_get_boot(&bid) >= 0); + sd_id128_to_string(bid, boot_id); + + x = strjoin("/tmp/systemd-private-", boot_id, "-abcd.service-"); + y = strjoin("/var/tmp/systemd-private-", boot_id, "-abcd.service-"); + assert_se(x && y); + + test_tmpdir("abcd.service", x, y); + + z = strjoin("/tmp/systemd-private-", boot_id, "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-"); + zz = strjoin("/var/tmp/systemd-private-", boot_id, "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-"); + + assert_se(z && zz); + + test_tmpdir("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz); + + test_netns(); + test_protect_kernel_logs(); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-netlink-manual.c b/src/test/test-netlink-manual.c new file mode 100644 index 00000000..a734524e --- /dev/null +++ b/src/test/test-netlink-manual.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-netlink.h" + +#include "macro.h" +#include "module-util.h" +#include "tests.h" +#include "util.h" + +static int load_module(const char *mod_name) { + _cleanup_(kmod_unrefp) struct kmod_ctx *ctx = NULL; + _cleanup_(kmod_module_unref_listp) struct kmod_list *list = NULL; + struct kmod_list *l; + int r; + + ctx = kmod_new(NULL, NULL); + if (!ctx) + return log_oom(); + + r = kmod_module_new_from_lookup(ctx, mod_name, &list); + if (r < 0) + return r; + + kmod_list_foreach(l, list) { + _cleanup_(kmod_module_unrefp) struct kmod_module *mod = NULL; + + mod = kmod_module_get_module(l); + + r = kmod_module_probe_insert_module(mod, 0, NULL, NULL, NULL, NULL); + if (r > 0) + r = -EINVAL; + } + + return r; +} + +static int test_tunnel_configure(sd_netlink *rtnl) { + int r; + sd_netlink_message *m, *n; + struct in_addr local, remote; + + /* skip test if module cannot be loaded */ + r = load_module("ipip"); + if (r < 0) + return log_tests_skipped_errno(r, "failed to load module 'ipip'"); + + r = load_module("sit"); + if (r < 0) + return log_tests_skipped_errno(r, "failed to load module 'sit'"); + + if (getuid() != 0) + return log_tests_skipped("not root"); + + /* IPIP tunnel */ + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0); + assert_se(m); + + assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, "ipip-tunnel") >= 0); + assert_se(sd_netlink_message_append_u32(m, IFLA_MTU, 1234)>= 0); + + assert_se(sd_netlink_message_open_container(m, IFLA_LINKINFO) >= 0); + + assert_se(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "ipip") >= 0); + + inet_pton(AF_INET, "192.168.21.1", &local.s_addr); + assert_se(sd_netlink_message_append_u32(m, IFLA_IPTUN_LOCAL, local.s_addr) >= 0); + + inet_pton(AF_INET, "192.168.21.2", &remote.s_addr); + assert_se(sd_netlink_message_append_u32(m, IFLA_IPTUN_REMOTE, remote.s_addr) >= 0); + + assert_se(sd_netlink_message_close_container(m) >= 0); + assert_se(sd_netlink_message_close_container(m) >= 0); + + assert_se(sd_netlink_call(rtnl, m, -1, 0) == 1); + + assert_se((m = sd_netlink_message_unref(m)) == NULL); + + /* sit */ + assert_se(sd_rtnl_message_new_link(rtnl, &n, RTM_NEWLINK, 0) >= 0); + assert_se(n); + + assert_se(sd_netlink_message_append_string(n, IFLA_IFNAME, "sit-tunnel") >= 0); + assert_se(sd_netlink_message_append_u32(n, IFLA_MTU, 1234)>= 0); + + assert_se(sd_netlink_message_open_container(n, IFLA_LINKINFO) >= 0); + + assert_se(sd_netlink_message_open_container_union(n, IFLA_INFO_DATA, "sit") >= 0); + + assert_se(sd_netlink_message_append_u8(n, IFLA_IPTUN_PROTO, IPPROTO_IPIP) >= 0); + + inet_pton(AF_INET, "192.168.21.3", &local.s_addr); + assert_se(sd_netlink_message_append_u32(n, IFLA_IPTUN_LOCAL, local.s_addr) >= 0); + + inet_pton(AF_INET, "192.168.21.4", &remote.s_addr); + assert_se(sd_netlink_message_append_u32(n, IFLA_IPTUN_REMOTE, remote.s_addr) >= 0); + + assert_se(sd_netlink_message_close_container(n) >= 0); + assert_se(sd_netlink_message_close_container(n) >= 0); + + assert_se(sd_netlink_call(rtnl, n, -1, 0) == 1); + + assert_se((n = sd_netlink_message_unref(n)) == NULL); + + return EXIT_SUCCESS; +} + +int main(int argc, char *argv[]) { + sd_netlink *rtnl; + int r; + + test_setup_logging(LOG_INFO); + + assert_se(sd_netlink_open(&rtnl) >= 0); + assert_se(rtnl); + + r = test_tunnel_configure(rtnl); + + assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); + + return r; +} diff --git a/src/test/test-ns.c b/src/test/test-ns.c new file mode 100644 index 00000000..e9233a16 --- /dev/null +++ b/src/test/test-ns.c @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "log.h" +#include "namespace.h" +#include "tests.h" + +int main(int argc, char *argv[]) { + const char * const writable[] = { + "/home", + "-/home/lennart/projects/foobar", /* this should be masked automatically */ + NULL + }; + + const char * const readonly[] = { + /* "/", */ + /* "/usr", */ + "/boot", + "/lib", + "/usr/lib", + "-/lib64", + "-/usr/lib64", + NULL + }; + + const char *inaccessible[] = { + "/home/lennart/projects", + NULL + }; + + static const NamespaceInfo ns_info = { + .private_dev = true, + .protect_control_groups = true, + .protect_kernel_tunables = true, + .protect_kernel_modules = true, + }; + + char *root_directory; + char *projects_directory; + int r; + char tmp_dir[] = "/tmp/systemd-private-XXXXXX", + var_tmp_dir[] = "/var/tmp/systemd-private-XXXXXX"; + + test_setup_logging(LOG_DEBUG); + + assert_se(mkdtemp(tmp_dir)); + assert_se(mkdtemp(var_tmp_dir)); + + root_directory = getenv("TEST_NS_CHROOT"); + projects_directory = getenv("TEST_NS_PROJECTS"); + + if (projects_directory) + inaccessible[0] = projects_directory; + + log_info("Inaccessible directory: '%s'", inaccessible[0]); + if (root_directory) + log_info("Chroot: '%s'", root_directory); + else + log_info("Not chrooted"); + + r = setup_namespace(root_directory, + NULL, + &ns_info, + (char **) writable, + (char **) readonly, + (char **) inaccessible, + NULL, + &(BindMount) { .source = (char*) "/usr/bin", .destination = (char*) "/etc/systemd", .read_only = true }, 1, + &(TemporaryFileSystem) { .path = (char*) "/var", .options = (char*) "ro" }, 1, + tmp_dir, + var_tmp_dir, + PROTECT_HOME_NO, + PROTECT_SYSTEM_NO, + 0, + 0, + NULL); + if (r < 0) { + log_error_errno(r, "Failed to setup namespace: %m"); + + log_info("Usage:\n" + " sudo TEST_NS_PROJECTS=/home/lennart/projects ./test-ns\n" + " sudo TEST_NS_CHROOT=/home/alban/debian-tree TEST_NS_PROJECTS=/home/alban/debian-tree/home/alban/Documents ./test-ns"); + + return 1; + } + + execl("/bin/sh", "/bin/sh", NULL); + log_error_errno(errno, "execl(): %m"); + + return 1; +} diff --git a/src/test/test-nscd-flush.c b/src/test/test-nscd-flush.c new file mode 100644 index 00000000..97c21959 --- /dev/null +++ b/src/test/test-nscd-flush.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "main-func.h" +#include "nscd-flush.h" +#include "strv.h" +#include "tests.h" + +static int run(int argc, char *argv[]) { + int r; + + test_setup_logging(LOG_DEBUG); + + r = nscd_flush_cache(STRV_MAKE("group", "passwd", "hosts")); + if (r < 0) + return log_error_errno(r, "Failed to flush NSCD cache"); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/test/test-nss.c b/src/test/test-nss.c new file mode 100644 index 00000000..6ba0f688 --- /dev/null +++ b/src/test/test-nss.c @@ -0,0 +1,521 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "af-list.h" +#include "alloc-util.h" +#include "errno-list.h" +#include "format-util.h" +#include "hexdecoct.h" +#include "hostname-util.h" +#include "in-addr-util.h" +#include "local-addresses.h" +#include "log.h" +#include "main-func.h" +#include "nss-util.h" +#include "path-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" + +static const char* nss_status_to_string(enum nss_status status, char *buf, size_t buf_len) { + switch (status) { + case NSS_STATUS_TRYAGAIN: + return "NSS_STATUS_TRYAGAIN"; + case NSS_STATUS_UNAVAIL: + return "NSS_STATUS_UNAVAIL"; + case NSS_STATUS_NOTFOUND: + return "NSS_STATUS_NOTFOUND"; + case NSS_STATUS_SUCCESS: + return "NSS_STATUS_SUCCESS"; + case NSS_STATUS_RETURN: + return "NSS_STATUS_RETURN"; + default: + snprintf(buf, buf_len, "%i", status); + return buf; + } +}; + +static const char* af_to_string(int family, char *buf, size_t buf_len) { + const char *name; + + if (family == AF_UNSPEC) + return "*"; + + name = af_to_name(family); + if (name) + return name; + + snprintf(buf, buf_len, "%i", family); + return buf; +} + +static void* open_handle(const char* dir, const char* module, int flags) { + const char *path = NULL; + void *handle; + + if (dir) + path = strjoina(dir, "/libnss_", module, ".so.2"); + if (!path || access(path, F_OK) < 0) + path = strjoina("libnss_", module, ".so.2"); + + handle = dlopen(path, flags); + if (!handle) + log_error("Failed to load module %s: %s", module, dlerror()); + return handle; +} + +static int print_gaih_addrtuples(const struct gaih_addrtuple *tuples) { + const struct gaih_addrtuple *it; + int n = 0; + + for (it = tuples; it; it = it->next) { + _cleanup_free_ char *a = NULL; + union in_addr_union u; + int r; + char family_name[DECIMAL_STR_MAX(int)]; + char ifname[IF_NAMESIZE + 1]; + + memcpy(&u, it->addr, 16); + r = in_addr_to_string(it->family, &u, &a); + assert_se(IN_SET(r, 0, -EAFNOSUPPORT)); + if (r == -EAFNOSUPPORT) + assert_se(a = hexmem(it->addr, 16)); + + if (it->scopeid == 0) + goto numerical_index; + + if (!format_ifname(it->scopeid, ifname)) { + log_warning_errno(errno, "if_indextoname(%d) failed: %m", it->scopeid); + numerical_index: + xsprintf(ifname, "%i", it->scopeid); + }; + + log_info(" \"%s\" %s %s %%%s", + it->name, + af_to_string(it->family, family_name, sizeof family_name), + a, + ifname); + n ++; + } + return n; +} + +static void print_struct_hostent(struct hostent *host, const char *canon) { + char **s; + + log_info(" \"%s\"", host->h_name); + STRV_FOREACH(s, host->h_aliases) + log_info(" alias \"%s\"", *s); + STRV_FOREACH(s, host->h_addr_list) { + union in_addr_union u; + _cleanup_free_ char *a = NULL; + char family_name[DECIMAL_STR_MAX(int)]; + int r; + + assert_se((unsigned) host->h_length == FAMILY_ADDRESS_SIZE(host->h_addrtype)); + memcpy(&u, *s, host->h_length); + r = in_addr_to_string(host->h_addrtype, &u, &a); + assert_se(r == 0); + log_info(" %s %s", + af_to_string(host->h_addrtype, family_name, sizeof family_name), + a); + } + if (canon) + log_info(" canonical: \"%s\"", canon); +} + +static void test_gethostbyname4_r(void *handle, const char *module, const char *name) { + const char *fname; + _nss_gethostbyname4_r_t f; + char buffer[2000]; + struct gaih_addrtuple *pat = NULL; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + int32_t ttl = INT32_MAX; /* nss-dns wants to return the lowest ttl, + and will access this variable through *ttlp, + so we need to set it to something. + I'm not sure if this is a bug in nss-dns + or not. */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + int n; + + fname = strjoina("_nss_", module, "_gethostbyname4_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + assert_se(f); + + status = f(name, &pat, buffer, sizeof buffer, &errno1, &errno2, &ttl); + if (status == NSS_STATUS_SUCCESS) { + log_info("%s(\"%s\") → status=%s%-20spat=buffer+0x%tx errno=%d/%s h_errno=%d/%s ttl=%"PRIi32, + fname, name, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + pat ? (char*) pat - buffer : 0, + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2), + ttl); + n = print_gaih_addrtuples(pat); + } else { + log_info("%s(\"%s\") → status=%s%-20spat=0x%p errno=%d/%s h_errno=%d/%s", + fname, name, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + pat, + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2)); + n = 0; + } + + if (STR_IN_SET(module, "resolve", "mymachines") && status == NSS_STATUS_UNAVAIL) + return; + + if (STR_IN_SET(module, "myhostname", "resolve") && streq(name, "localhost")) { + assert_se(status == NSS_STATUS_SUCCESS); + assert_se(n == 2); + } +} + +static void test_gethostbyname3_r(void *handle, const char *module, const char *name, int af) { + const char *fname; + _nss_gethostbyname3_r_t f; + char buffer[2000]; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + int32_t ttl = INT32_MAX; /* nss-dns wants to return the lowest ttl, + and will access this variable through *ttlp, + so we need to set it to something. + I'm not sure if this is a bug in nss-dns + or not. */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct hostent host; + char *canon; + char family_name[DECIMAL_STR_MAX(int)]; + + fname = strjoina("_nss_", module, "_gethostbyname3_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + assert_se(f); + + status = f(name, af, &host, buffer, sizeof buffer, &errno1, &errno2, &ttl, &canon); + log_info("%s(\"%s\", %s) → status=%s%-20serrno=%d/%s h_errno=%d/%s ttl=%"PRIi32, + fname, name, af_to_string(af, family_name, sizeof family_name), + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2), + ttl); + if (status == NSS_STATUS_SUCCESS) + print_struct_hostent(&host, canon); +} + +static void test_gethostbyname2_r(void *handle, const char *module, const char *name, int af) { + const char *fname; + _nss_gethostbyname2_r_t f; + char buffer[2000]; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct hostent host; + char family_name[DECIMAL_STR_MAX(int)]; + + fname = strjoina("_nss_", module, "_gethostbyname2_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + assert_se(f); + + status = f(name, af, &host, buffer, sizeof buffer, &errno1, &errno2); + log_info("%s(\"%s\", %s) → status=%s%-20serrno=%d/%s h_errno=%d/%s", + fname, name, af_to_string(af, family_name, sizeof family_name), + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2)); + if (status == NSS_STATUS_SUCCESS) + print_struct_hostent(&host, NULL); +} + +static void test_gethostbyname_r(void *handle, const char *module, const char *name) { + const char *fname; + _nss_gethostbyname_r_t f; + char buffer[2000]; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct hostent host; + + fname = strjoina("_nss_", module, "_gethostbyname_r"); + f = dlsym(handle, fname); + log_debug("dlsym(0x%p, %s) → 0x%p", handle, fname, f); + assert_se(f); + + status = f(name, &host, buffer, sizeof buffer, &errno1, &errno2); + log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s h_errno=%d/%s", + fname, name, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2)); + if (status == NSS_STATUS_SUCCESS) + print_struct_hostent(&host, NULL); +} + +static void test_gethostbyaddr2_r(void *handle, + const char *module, + const void* addr, socklen_t len, + int af) { + + const char *fname; + _nss_gethostbyaddr2_r_t f; + char buffer[2000]; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct hostent host; + int32_t ttl = INT32_MAX; + _cleanup_free_ char *addr_pretty = NULL; + + fname = strjoina("_nss_", module, "_gethostbyaddr2_r"); + f = dlsym(handle, fname); + + log_full_errno(f ? LOG_DEBUG : LOG_INFO, errno, + "dlsym(0x%p, %s) → 0x%p: %m", handle, fname, f); + if (!f) + return; + + assert_se(in_addr_to_string(af, addr, &addr_pretty) >= 0); + + status = f(addr, len, af, &host, buffer, sizeof buffer, &errno1, &errno2, &ttl); + log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s h_errno=%d/%s ttl=%"PRIi32, + fname, addr_pretty, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2), + ttl); + if (status == NSS_STATUS_SUCCESS) + print_struct_hostent(&host, NULL); +} + +static void test_gethostbyaddr_r(void *handle, + const char *module, + const void* addr, socklen_t len, + int af) { + + const char *fname; + _nss_gethostbyaddr_r_t f; + char buffer[2000]; + int errno1 = 999, errno2 = 999; /* nss-dns doesn't set those */ + enum nss_status status; + char pretty_status[DECIMAL_STR_MAX(enum nss_status)]; + struct hostent host; + _cleanup_free_ char *addr_pretty = NULL; + + fname = strjoina("_nss_", module, "_gethostbyaddr_r"); + f = dlsym(handle, fname); + + log_full_errno(f ? LOG_DEBUG : LOG_INFO, errno, + "dlsym(0x%p, %s) → 0x%p: %m", handle, fname, f); + if (!f) + return; + + assert_se(in_addr_to_string(af, addr, &addr_pretty) >= 0); + + status = f(addr, len, af, &host, buffer, sizeof buffer, &errno1, &errno2); + log_info("%s(\"%s\") → status=%s%-20serrno=%d/%s h_errno=%d/%s", + fname, addr_pretty, + nss_status_to_string(status, pretty_status, sizeof pretty_status), "\n", + errno1, errno_to_name(errno1) ?: "---", + errno2, hstrerror(errno2)); + if (status == NSS_STATUS_SUCCESS) + print_struct_hostent(&host, NULL); +} + +static void test_byname(void *handle, const char *module, const char *name) { + test_gethostbyname4_r(handle, module, name); + puts(""); + + test_gethostbyname3_r(handle, module, name, AF_INET); + puts(""); + test_gethostbyname3_r(handle, module, name, AF_INET6); + puts(""); + test_gethostbyname3_r(handle, module, name, AF_UNSPEC); + puts(""); + test_gethostbyname3_r(handle, module, name, AF_LOCAL); + puts(""); + + test_gethostbyname2_r(handle, module, name, AF_INET); + puts(""); + test_gethostbyname2_r(handle, module, name, AF_INET6); + puts(""); + test_gethostbyname2_r(handle, module, name, AF_UNSPEC); + puts(""); + test_gethostbyname2_r(handle, module, name, AF_LOCAL); + puts(""); + + test_gethostbyname_r(handle, module, name); + puts(""); +} + +static void test_byaddr(void *handle, + const char *module, + const void* addr, socklen_t len, + int af) { + test_gethostbyaddr2_r(handle, module, addr, len, af); + puts(""); + + test_gethostbyaddr_r(handle, module, addr, len, af); + puts(""); +} + +static int make_addresses(struct local_address **addresses) { + int n; + size_t n_alloc; + _cleanup_free_ struct local_address *addrs = NULL; + + n = local_addresses(NULL, 0, AF_UNSPEC, &addrs); + if (n < 0) + log_info_errno(n, "Failed to query local addresses: %m"); + + n_alloc = n; /* we _can_ do that */ + if (!GREEDY_REALLOC(addrs, n_alloc, n + 3)) + return log_oom(); + + addrs[n++] = (struct local_address) { .family = AF_INET, + .address.in = { htobe32(0x7F000001) } }; + addrs[n++] = (struct local_address) { .family = AF_INET, + .address.in = { htobe32(0x7F000002) } }; + addrs[n++] = (struct local_address) { .family = AF_INET6, + .address.in6 = in6addr_loopback }; + return 0; +} + +static int test_one_module(const char* dir, + const char *module, + char **names, + struct local_address *addresses, + int n_addresses) { + void *handle; + char **name; + int i; + + log_info("======== %s ========", module); + + handle = open_handle(dir, module, RTLD_LAZY|RTLD_NODELETE); + if (!handle) + return -EINVAL; + + STRV_FOREACH(name, names) + test_byname(handle, module, *name); + + for (i = 0; i < n_addresses; i++) + test_byaddr(handle, module, + &addresses[i].address, + FAMILY_ADDRESS_SIZE(addresses[i].family), + addresses[i].family); + + log_info(" "); + dlclose(handle); + return 0; +} + +static int parse_argv(int argc, char **argv, + char ***the_modules, + char ***the_names, + struct local_address **the_addresses, int *n_addresses) { + + int r, n = 0; + _cleanup_strv_free_ char **modules = NULL, **names = NULL; + _cleanup_free_ struct local_address *addrs = NULL; + size_t n_allocated = 0; + + if (argc > 1) + modules = strv_new(argv[1]); + else + modules = strv_new( +#if ENABLE_NSS_MYHOSTNAME + "myhostname", +#endif +#if ENABLE_NSS_RESOLVE + "resolve", +#endif +#if ENABLE_NSS_MYMACHINES + "mymachines", +#endif + "dns"); + if (!modules) + return -ENOMEM; + + if (argc > 2) { + char **name; + int family; + union in_addr_union address; + + STRV_FOREACH(name, argv + 2) { + r = in_addr_from_string_auto(*name, &family, &address); + if (r < 0) { + /* assume this is a name */ + r = strv_extend(&names, *name); + if (r < 0) + return r; + } else { + if (!GREEDY_REALLOC0(addrs, n_allocated, n + 1)) + return -ENOMEM; + + addrs[n++] = (struct local_address) { .family = family, + .address = address }; + } + } + } else { + _cleanup_free_ char *hostname; + + hostname = gethostname_malloc(); + if (!hostname) + return -ENOMEM; + + names = strv_new("localhost", "_gateway", "foo_no_such_host", hostname); + if (!names) + return -ENOMEM; + + n = make_addresses(&addrs); + if (n < 0) + return n; + } + + *the_modules = modules; + *the_names = names; + modules = names = NULL; + *the_addresses = addrs; + *n_addresses = n; + addrs = NULL; + return 0; +} + +static int run(int argc, char **argv) { + _cleanup_free_ char *dir = NULL; + _cleanup_strv_free_ char **modules = NULL, **names = NULL; + _cleanup_free_ struct local_address *addresses = NULL; + int n_addresses = 0; + char **module; + int r; + + test_setup_logging(LOG_INFO); + + r = parse_argv(argc, argv, &modules, &names, &addresses, &n_addresses); + if (r < 0) { + log_error_errno(r, "Failed to parse arguments: %m"); + return EXIT_FAILURE; + } + + dir = dirname_malloc(argv[0]); + if (!dir) + return log_oom(); + + STRV_FOREACH(module, modules) { + r = test_one_module(dir, *module, names, addresses, n_addresses); + if (r < 0) + return r; + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/test/test-ordered-set.c b/src/test/test-ordered-set.c new file mode 100644 index 00000000..0d29fcfa --- /dev/null +++ b/src/test/test-ordered-set.c @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "ordered-set.h" +#include "string-util.h" +#include "strv.h" + +static void test_set_steal_first(void) { + _cleanup_ordered_set_free_ OrderedSet *m = NULL; + int seen[3] = {}; + char *val; + + m = ordered_set_new(&string_hash_ops); + assert_se(m); + + assert_se(ordered_set_put(m, (void*) "1") == 1); + assert_se(ordered_set_put(m, (void*) "22") == 1); + assert_se(ordered_set_put(m, (void*) "333") == 1); + + ordered_set_print(stdout, "SET=", m); + + while ((val = ordered_set_steal_first(m))) + seen[strlen(val) - 1]++; + + assert_se(seen[0] == 1 && seen[1] == 1 && seen[2] == 1); + + assert_se(ordered_set_isempty(m)); + + ordered_set_print(stdout, "SET=", m); +} + +typedef struct Item { + int seen; +} Item; +static void item_seen(Item *item) { + item->seen++; +} + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_hash_ops, void, trivial_hash_func, trivial_compare_func, Item, item_seen); + +static void test_set_free_with_hash_ops(void) { + OrderedSet *m; + struct Item items[4] = {}; + unsigned i; + + assert_se(m = ordered_set_new(&item_hash_ops)); + for (i = 0; i < ELEMENTSOF(items) - 1; i++) + assert_se(ordered_set_put(m, items + i) == 1); + + m = ordered_set_free(m); + assert_se(items[0].seen == 1); + assert_se(items[1].seen == 1); + assert_se(items[2].seen == 1); + assert_se(items[3].seen == 0); +} + +static void test_set_put(void) { + _cleanup_ordered_set_free_ OrderedSet *m = NULL; + _cleanup_free_ char **t = NULL; + + m = ordered_set_new(&string_hash_ops); + assert_se(m); + + assert_se(ordered_set_put(m, (void*) "1") == 1); + assert_se(ordered_set_put(m, (void*) "22") == 1); + assert_se(ordered_set_put(m, (void*) "333") == 1); + assert_se(ordered_set_put(m, (void*) "333") == 0); + assert_se(ordered_set_remove(m, (void*) "333")); + assert_se(ordered_set_put(m, (void*) "333") == 1); + assert_se(ordered_set_put(m, (void*) "333") == 0); + assert_se(ordered_set_put(m, (void*) "22") == 0); + + assert_se(t = ordered_set_get_strv(m)); + assert_se(streq(t[0], "1")); + assert_se(streq(t[1], "22")); + assert_se(streq(t[2], "333")); + assert_se(!t[3]); + + ordered_set_print(stdout, "FOO=", m); +} + +static void test_set_put_string_set(void) { + _cleanup_ordered_set_free_free_ OrderedSet *m = NULL; + _cleanup_ordered_set_free_ OrderedSet *q = NULL; + _cleanup_free_ char **final = NULL; /* "just free" because the strings are in the set */ + void *t; + + m = ordered_set_new(&string_hash_ops); + assert_se(m); + + q = ordered_set_new(&string_hash_ops); + assert_se(q); + + assert_se(t = strdup("1")); + assert_se(ordered_set_put(m, t) == 1); + assert_se(t = strdup("22")); + assert_se(ordered_set_put(m, t) == 1); + assert_se(t = strdup("333")); + assert_se(ordered_set_put(m, t) == 1); + + assert_se(ordered_set_put(q, (void*) "11") == 1); + assert_se(ordered_set_put(q, (void*) "22") == 1); + assert_se(ordered_set_put(q, (void*) "33") == 1); + + assert_se(ordered_set_put_string_set(m, q) == 2); + + assert_se(final = ordered_set_get_strv(m)); + assert_se(strv_equal(final, STRV_MAKE("1", "22", "333", "11", "33"))); + + ordered_set_print(stdout, "BAR=", m); +} + +int main(int argc, const char *argv[]) { + test_set_steal_first(); + test_set_free_with_hash_ops(); + test_set_put(); + test_set_put_string_set(); + + return 0; +} diff --git a/src/test/test-os-util.c b/src/test/test-os-util.c new file mode 100644 index 00000000..c215a2e9 --- /dev/null +++ b/src/test/test-os-util.c @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "log.h" +#include "os-util.h" +#include "tests.h" + +static void test_path_is_os_tree(void) { + assert_se(path_is_os_tree("/") > 0); + assert_se(path_is_os_tree("/etc") == 0); + assert_se(path_is_os_tree("/idontexist") == -ENOENT); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_path_is_os_tree(); + + return 0; +} diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c new file mode 100644 index 00000000..d732f402 --- /dev/null +++ b/src/test/test-parse-util.c @@ -0,0 +1,853 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "errno-list.h" +#include "log.h" +#include "parse-util.h" +#include "string-util.h" + +static void test_parse_boolean(void) { + assert_se(parse_boolean("1") == 1); + assert_se(parse_boolean("y") == 1); + assert_se(parse_boolean("Y") == 1); + assert_se(parse_boolean("yes") == 1); + assert_se(parse_boolean("YES") == 1); + assert_se(parse_boolean("true") == 1); + assert_se(parse_boolean("TRUE") == 1); + assert_se(parse_boolean("on") == 1); + assert_se(parse_boolean("ON") == 1); + + assert_se(parse_boolean("0") == 0); + assert_se(parse_boolean("n") == 0); + assert_se(parse_boolean("N") == 0); + assert_se(parse_boolean("no") == 0); + assert_se(parse_boolean("NO") == 0); + assert_se(parse_boolean("false") == 0); + assert_se(parse_boolean("FALSE") == 0); + assert_se(parse_boolean("off") == 0); + assert_se(parse_boolean("OFF") == 0); + + assert_se(parse_boolean("garbage") < 0); + assert_se(parse_boolean("") < 0); + assert_se(parse_boolean("full") < 0); +} + +static void test_parse_pid(void) { + int r; + pid_t pid; + + r = parse_pid("100", &pid); + assert_se(r == 0); + assert_se(pid == 100); + + r = parse_pid("0x7FFFFFFF", &pid); + assert_se(r == 0); + assert_se(pid == 2147483647); + + pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ + r = parse_pid("0", &pid); + assert_se(r == -ERANGE); + assert_se(pid == 65); + + pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ + r = parse_pid("-100", &pid); + assert_se(r == -ERANGE); + assert_se(pid == 65); + + pid = 65; /* pid is left unchanged on ERANGE. Set to known arbitrary value. */ + r = parse_pid("0xFFFFFFFFFFFFFFFFF", &pid); + assert_se(r == -ERANGE); + assert_se(pid == 65); + + r = parse_pid("junk", &pid); + assert_se(r == -EINVAL); + + r = parse_pid("", &pid); + assert_se(r == -EINVAL); +} + +static void test_parse_mode(void) { + mode_t m; + + assert_se(parse_mode("-1", &m) < 0); + assert_se(parse_mode("", &m) < 0); + assert_se(parse_mode("888", &m) < 0); + assert_se(parse_mode("77777", &m) < 0); + + assert_se(parse_mode("544", &m) >= 0 && m == 0544); + assert_se(parse_mode("777", &m) >= 0 && m == 0777); + assert_se(parse_mode("7777", &m) >= 0 && m == 07777); + assert_se(parse_mode("0", &m) >= 0 && m == 0); +} + +static void test_parse_size(void) { + uint64_t bytes; + + assert_se(parse_size("", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("111", 1024, &bytes) == 0); + assert_se(bytes == 111); + + assert_se(parse_size("111.4", 1024, &bytes) == 0); + assert_se(bytes == 111); + + assert_se(parse_size(" 112 B", 1024, &bytes) == 0); + assert_se(bytes == 112); + + assert_se(parse_size(" 112.6 B", 1024, &bytes) == 0); + assert_se(bytes == 112); + + assert_se(parse_size("3.5 K", 1024, &bytes) == 0); + assert_se(bytes == 3*1024 + 512); + + assert_se(parse_size("3. K", 1024, &bytes) == 0); + assert_se(bytes == 3*1024); + + assert_se(parse_size("3.0 K", 1024, &bytes) == 0); + assert_se(bytes == 3*1024); + + assert_se(parse_size("3. 0 K", 1024, &bytes) == -EINVAL); + + assert_se(parse_size(" 4 M 11.5K", 1024, &bytes) == 0); + assert_se(bytes == 4*1024*1024 + 11 * 1024 + 512); + + assert_se(parse_size("3B3.5G", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("3.5G3B", 1024, &bytes) == 0); + assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 3); + + assert_se(parse_size("3.5G 4B", 1024, &bytes) == 0); + assert_se(bytes == 3ULL*1024*1024*1024 + 512*1024*1024 + 4); + + assert_se(parse_size("3B3G4T", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("4T3G3B", 1024, &bytes) == 0); + assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3); + + assert_se(parse_size(" 4 T 3 G 3 B", 1024, &bytes) == 0); + assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3); + + assert_se(parse_size("12P", 1024, &bytes) == 0); + assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024); + + assert_se(parse_size("12P12P", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("3E 2P", 1024, &bytes) == 0); + assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024); + + assert_se(parse_size("12X", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("12.5X", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("12.5e3", 1024, &bytes) == -EINVAL); + + assert_se(parse_size("1024E", 1024, &bytes) == -ERANGE); + assert_se(parse_size("-1", 1024, &bytes) == -ERANGE); + assert_se(parse_size("-1024E", 1024, &bytes) == -ERANGE); + + assert_se(parse_size("-1024P", 1024, &bytes) == -ERANGE); + + assert_se(parse_size("-10B 20K", 1024, &bytes) == -ERANGE); +} + +static void test_parse_range(void) { + unsigned lower, upper; + + /* Successful cases */ + assert_se(parse_range("111", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 111); + + assert_se(parse_range("111-123", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 123); + + assert_se(parse_range("123-111", &lower, &upper) == 0); + assert_se(lower == 123); + assert_se(upper == 111); + + assert_se(parse_range("123-123", &lower, &upper) == 0); + assert_se(lower == 123); + assert_se(upper == 123); + + assert_se(parse_range("0", &lower, &upper) == 0); + assert_se(lower == 0); + assert_se(upper == 0); + + assert_se(parse_range("0-15", &lower, &upper) == 0); + assert_se(lower == 0); + assert_se(upper == 15); + + assert_se(parse_range("15-0", &lower, &upper) == 0); + assert_se(lower == 15); + assert_se(upper == 0); + + assert_se(parse_range("128-65535", &lower, &upper) == 0); + assert_se(lower == 128); + assert_se(upper == 65535); + + assert_se(parse_range("1024-4294967295", &lower, &upper) == 0); + assert_se(lower == 1024); + assert_se(upper == 4294967295); + + /* Leading whitespace is acceptable */ + assert_se(parse_range(" 111", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 111); + + assert_se(parse_range(" 111-123", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 123); + + assert_se(parse_range("111- 123", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 123); + + assert_se(parse_range("\t111-\t123", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 123); + + assert_se(parse_range(" \t 111- \t 123", &lower, &upper) == 0); + assert_se(lower == 111); + assert_se(upper == 123); + + /* Error cases, make sure they fail as expected */ + lower = upper = 9999; + assert_se(parse_range("111garbage", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("garbage111", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("garbage", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123garbage", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111garbage-123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* Empty string */ + lower = upper = 9999; + assert_se(parse_range("", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* 111--123 will pass -123 to safe_atou which returns -ERANGE for negative */ + assert_se(parse_range("111--123", &lower, &upper) == -ERANGE); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("-123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("-111-123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111.4-123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123.4", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111,4-123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123,4", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* Error on trailing dash */ + assert_se(parse_range("111-", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123-", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111--", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111- ", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* Whitespace is not a separator */ + assert_se(parse_range("111 123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111\t123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111 \t 123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* Trailing whitespace is invalid (from safe_atou) */ + assert_se(parse_range("111 ", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111-123 ", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111 -123", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111 -123 ", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111\t-123\t", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + assert_se(parse_range("111 \t -123 \t ", &lower, &upper) == -EINVAL); + assert_se(lower == 9999); + assert_se(upper == 9999); + + /* Out of the "unsigned" range, this is 1<<64 */ + assert_se(parse_range("0-18446744073709551616", &lower, &upper) == -ERANGE); + assert_se(lower == 9999); + assert_se(upper == 9999); +} + +static void test_safe_atolli(void) { + int r; + long long l; + + r = safe_atolli("12345", &l); + assert_se(r == 0); + assert_se(l == 12345); + + r = safe_atolli(" 12345", &l); + assert_se(r == 0); + assert_se(l == 12345); + + r = safe_atolli("-12345", &l); + assert_se(r == 0); + assert_se(l == -12345); + + r = safe_atolli(" -12345", &l); + assert_se(r == 0); + assert_se(l == -12345); + + r = safe_atolli("12345678901234567890", &l); + assert_se(r == -ERANGE); + + r = safe_atolli("-12345678901234567890", &l); + assert_se(r == -ERANGE); + + r = safe_atolli("junk", &l); + assert_se(r == -EINVAL); + + r = safe_atolli("123x", &l); + assert_se(r == -EINVAL); + + r = safe_atolli("12.3", &l); + assert_se(r == -EINVAL); + + r = safe_atolli("", &l); + assert_se(r == -EINVAL); +} + +static void test_safe_atou16(void) { + int r; + uint16_t l; + + r = safe_atou16("12345", &l); + assert_se(r == 0); + assert_se(l == 12345); + + r = safe_atou16(" 12345", &l); + assert_se(r == 0); + assert_se(l == 12345); + + r = safe_atou16("123456", &l); + assert_se(r == -ERANGE); + + r = safe_atou16("-1", &l); + assert_se(r == -ERANGE); + + r = safe_atou16(" -1", &l); + assert_se(r == -ERANGE); + + r = safe_atou16("junk", &l); + assert_se(r == -EINVAL); + + r = safe_atou16("123x", &l); + assert_se(r == -EINVAL); + + r = safe_atou16("12.3", &l); + assert_se(r == -EINVAL); + + r = safe_atou16("", &l); + assert_se(r == -EINVAL); +} + +static void test_safe_atoi16(void) { + int r; + int16_t l; + + r = safe_atoi16("-12345", &l); + assert_se(r == 0); + assert_se(l == -12345); + + r = safe_atoi16(" -12345", &l); + assert_se(r == 0); + assert_se(l == -12345); + + r = safe_atoi16("32767", &l); + assert_se(r == 0); + assert_se(l == 32767); + + r = safe_atoi16(" 32767", &l); + assert_se(r == 0); + assert_se(l == 32767); + + r = safe_atoi16("36536", &l); + assert_se(r == -ERANGE); + + r = safe_atoi16("-32769", &l); + assert_se(r == -ERANGE); + + r = safe_atoi16("junk", &l); + assert_se(r == -EINVAL); + + r = safe_atoi16("123x", &l); + assert_se(r == -EINVAL); + + r = safe_atoi16("12.3", &l); + assert_se(r == -EINVAL); + + r = safe_atoi16("", &l); + assert_se(r == -EINVAL); +} + +static void test_safe_atoux16(void) { + int r; + uint16_t l; + + r = safe_atoux16("1234", &l); + assert_se(r == 0); + assert_se(l == 0x1234); + + r = safe_atoux16("abcd", &l); + assert_se(r == 0); + assert_se(l == 0xabcd); + + r = safe_atoux16(" 1234", &l); + assert_se(r == 0); + assert_se(l == 0x1234); + + r = safe_atoux16("12345", &l); + assert_se(r == -ERANGE); + + r = safe_atoux16("-1", &l); + assert_se(r == -ERANGE); + + r = safe_atoux16(" -1", &l); + assert_se(r == -ERANGE); + + r = safe_atoux16("junk", &l); + assert_se(r == -EINVAL); + + r = safe_atoux16("123x", &l); + assert_se(r == -EINVAL); + + r = safe_atoux16("12.3", &l); + assert_se(r == -EINVAL); + + r = safe_atoux16("", &l); + assert_se(r == -EINVAL); +} + +static void test_safe_atou64(void) { + int r; + uint64_t l; + + r = safe_atou64("12345", &l); + assert_se(r == 0); + assert_se(l == 12345); + + r = safe_atou64(" 12345", &l); + assert_se(r == 0); + assert_se(l == 12345); + + r = safe_atou64("18446744073709551617", &l); + assert_se(r == -ERANGE); + + r = safe_atou64("-1", &l); + assert_se(r == -ERANGE); + + r = safe_atou64(" -1", &l); + assert_se(r == -ERANGE); + + r = safe_atou64("junk", &l); + assert_se(r == -EINVAL); + + r = safe_atou64("123x", &l); + assert_se(r == -EINVAL); + + r = safe_atou64("12.3", &l); + assert_se(r == -EINVAL); + + r = safe_atou64("", &l); + assert_se(r == -EINVAL); +} + +static void test_safe_atoi64(void) { + int r; + int64_t l; + + r = safe_atoi64("-12345", &l); + assert_se(r == 0); + assert_se(l == -12345); + + r = safe_atoi64(" -12345", &l); + assert_se(r == 0); + assert_se(l == -12345); + + r = safe_atoi64("32767", &l); + assert_se(r == 0); + assert_se(l == 32767); + + r = safe_atoi64(" 32767", &l); + assert_se(r == 0); + assert_se(l == 32767); + + r = safe_atoi64("9223372036854775813", &l); + assert_se(r == -ERANGE); + + r = safe_atoi64("-9223372036854775813", &l); + assert_se(r == -ERANGE); + + r = safe_atoi64("junk", &l); + assert_se(r == -EINVAL); + + r = safe_atoi64("123x", &l); + assert_se(r == -EINVAL); + + r = safe_atoi64("12.3", &l); + assert_se(r == -EINVAL); + + r = safe_atoi64("", &l); + assert_se(r == -EINVAL); +} + +static void test_safe_atod(void) { + int r; + double d; + char *e; + + r = safe_atod("junk", &d); + assert_se(r == -EINVAL); + + r = safe_atod("0.2244", &d); + assert_se(r == 0); + assert_se(fabs(d - 0.2244) < 0.000001); + + r = safe_atod("0,5", &d); + assert_se(r == -EINVAL); + + errno = 0; + strtod("0,5", &e); + assert_se(*e == ','); + + r = safe_atod("", &d); + assert_se(r == -EINVAL); + + /* Check if this really is locale independent */ + if (setlocale(LC_NUMERIC, "de_DE.utf8")) { + + r = safe_atod("0.2244", &d); + assert_se(r == 0); + assert_se(fabs(d - 0.2244) < 0.000001); + + r = safe_atod("0,5", &d); + assert_se(r == -EINVAL); + + errno = 0; + assert_se(fabs(strtod("0,5", &e) - 0.5) < 0.00001); + + r = safe_atod("", &d); + assert_se(r == -EINVAL); + } + + /* And check again, reset */ + assert_se(setlocale(LC_NUMERIC, "C")); + + r = safe_atod("0.2244", &d); + assert_se(r == 0); + assert_se(fabs(d - 0.2244) < 0.000001); + + r = safe_atod("0,5", &d); + assert_se(r == -EINVAL); + + errno = 0; + strtod("0,5", &e); + assert_se(*e == ','); + + r = safe_atod("", &d); + assert_se(r == -EINVAL); +} + +static void test_parse_percent(void) { + assert_se(parse_percent("") == -EINVAL); + assert_se(parse_percent("foo") == -EINVAL); + assert_se(parse_percent("0") == -EINVAL); + assert_se(parse_percent("50") == -EINVAL); + assert_se(parse_percent("100") == -EINVAL); + assert_se(parse_percent("-1") == -EINVAL); + assert_se(parse_percent("0%") == 0); + assert_se(parse_percent("55%") == 55); + assert_se(parse_percent("100%") == 100); + assert_se(parse_percent("-7%") == -ERANGE); + assert_se(parse_percent("107%") == -ERANGE); + assert_se(parse_percent("%") == -EINVAL); + assert_se(parse_percent("%%") == -EINVAL); + assert_se(parse_percent("%1") == -EINVAL); + assert_se(parse_percent("1%%") == -EINVAL); + assert_se(parse_percent("3.2%") == -EINVAL); +} + +static void test_parse_percent_unbounded(void) { + assert_se(parse_percent_unbounded("101%") == 101); + assert_se(parse_percent_unbounded("400%") == 400); +} + +static void test_parse_permille(void) { + assert_se(parse_permille("") == -EINVAL); + assert_se(parse_permille("foo") == -EINVAL); + assert_se(parse_permille("0") == -EINVAL); + assert_se(parse_permille("50") == -EINVAL); + assert_se(parse_permille("100") == -EINVAL); + assert_se(parse_permille("-1") == -EINVAL); + + assert_se(parse_permille("0‰") == 0); + assert_se(parse_permille("555‰") == 555); + assert_se(parse_permille("1000‰") == 1000); + assert_se(parse_permille("-7‰") == -ERANGE); + assert_se(parse_permille("1007‰") == -ERANGE); + assert_se(parse_permille("‰") == -EINVAL); + assert_se(parse_permille("‰‰") == -EINVAL); + assert_se(parse_permille("‰1") == -EINVAL); + assert_se(parse_permille("1‰‰") == -EINVAL); + assert_se(parse_permille("3.2‰") == -EINVAL); + + assert_se(parse_permille("0%") == 0); + assert_se(parse_permille("55%") == 550); + assert_se(parse_permille("55.5%") == 555); + assert_se(parse_permille("100%") == 1000); + assert_se(parse_permille("-7%") == -ERANGE); + assert_se(parse_permille("107%") == -ERANGE); + assert_se(parse_permille("%") == -EINVAL); + assert_se(parse_permille("%%") == -EINVAL); + assert_se(parse_permille("%1") == -EINVAL); + assert_se(parse_permille("1%%") == -EINVAL); + assert_se(parse_permille("3.21%") == -EINVAL); +} + +static void test_parse_permille_unbounded(void) { + assert_se(parse_permille_unbounded("1001‰") == 1001); + assert_se(parse_permille_unbounded("4000‰") == 4000); + assert_se(parse_permille_unbounded("2147483647‰") == 2147483647); + assert_se(parse_permille_unbounded("2147483648‰") == -ERANGE); + assert_se(parse_permille_unbounded("4294967295‰") == -ERANGE); + assert_se(parse_permille_unbounded("4294967296‰") == -ERANGE); + + assert_se(parse_permille_unbounded("101%") == 1010); + assert_se(parse_permille_unbounded("400%") == 4000); + assert_se(parse_permille_unbounded("214748364.7%") == 2147483647); + assert_se(parse_permille_unbounded("214748364.8%") == -ERANGE); + assert_se(parse_permille_unbounded("429496729.5%") == -ERANGE); + assert_se(parse_permille_unbounded("429496729.6%") == -ERANGE); +} + +static void test_parse_nice(void) { + int n; + + assert_se(parse_nice("0", &n) >= 0 && n == 0); + assert_se(parse_nice("+0", &n) >= 0 && n == 0); + assert_se(parse_nice("-1", &n) >= 0 && n == -1); + assert_se(parse_nice("-2", &n) >= 0 && n == -2); + assert_se(parse_nice("1", &n) >= 0 && n == 1); + assert_se(parse_nice("2", &n) >= 0 && n == 2); + assert_se(parse_nice("+1", &n) >= 0 && n == 1); + assert_se(parse_nice("+2", &n) >= 0 && n == 2); + assert_se(parse_nice("-20", &n) >= 0 && n == -20); + assert_se(parse_nice("19", &n) >= 0 && n == 19); + assert_se(parse_nice("+19", &n) >= 0 && n == 19); + + assert_se(parse_nice("", &n) == -EINVAL); + assert_se(parse_nice("-", &n) == -EINVAL); + assert_se(parse_nice("+", &n) == -EINVAL); + assert_se(parse_nice("xx", &n) == -EINVAL); + assert_se(parse_nice("-50", &n) == -ERANGE); + assert_se(parse_nice("50", &n) == -ERANGE); + assert_se(parse_nice("+50", &n) == -ERANGE); + assert_se(parse_nice("-21", &n) == -ERANGE); + assert_se(parse_nice("20", &n) == -ERANGE); + assert_se(parse_nice("+20", &n) == -ERANGE); +} + +static void test_parse_dev(void) { + dev_t dev; + + assert_se(parse_dev("", &dev) == -EINVAL); + assert_se(parse_dev("junk", &dev) == -EINVAL); + assert_se(parse_dev("0", &dev) == -EINVAL); + assert_se(parse_dev("5", &dev) == -EINVAL); + assert_se(parse_dev("5:", &dev) == -EINVAL); + assert_se(parse_dev(":5", &dev) == -EINVAL); + assert_se(parse_dev("-1:-1", &dev) == -EINVAL); +#if SIZEOF_DEV_T < 8 + assert_se(parse_dev("4294967295:4294967295", &dev) == -EINVAL); +#endif + assert_se(parse_dev("8:11", &dev) >= 0 && major(dev) == 8 && minor(dev) == 11); + assert_se(parse_dev("0:0", &dev) >= 0 && major(dev) == 0 && minor(dev) == 0); +} + +static void test_parse_errno(void) { + assert_se(parse_errno("EILSEQ") == EILSEQ); + assert_se(parse_errno("EINVAL") == EINVAL); + assert_se(parse_errno("0") == 0); + assert_se(parse_errno("1") == 1); + assert_se(parse_errno("4095") == 4095); + + assert_se(parse_errno("-1") == -ERANGE); + assert_se(parse_errno("-3") == -ERANGE); + assert_se(parse_errno("4096") == -ERANGE); + + assert_se(parse_errno("") == -EINVAL); + assert_se(parse_errno("12.3") == -EINVAL); + assert_se(parse_errno("123junk") == -EINVAL); + assert_se(parse_errno("junk123") == -EINVAL); + assert_se(parse_errno("255EILSEQ") == -EINVAL); + assert_se(parse_errno("EINVAL12") == -EINVAL); + assert_se(parse_errno("-EINVAL") == -EINVAL); + assert_se(parse_errno("EINVALaaa") == -EINVAL); +} + +static void test_parse_syscall_and_errno(void) { + _cleanup_free_ char *n = NULL; + int e; + + assert_se(parse_syscall_and_errno("uname:EILSEQ", &n, &e) >= 0); + assert_se(streq(n, "uname")); + assert_se(e == errno_from_name("EILSEQ") && e >= 0); + n = mfree(n); + + assert_se(parse_syscall_and_errno("uname:EINVAL", &n, &e) >= 0); + assert_se(streq(n, "uname")); + assert_se(e == errno_from_name("EINVAL") && e >= 0); + n = mfree(n); + + assert_se(parse_syscall_and_errno("@sync:4095", &n, &e) >= 0); + assert_se(streq(n, "@sync")); + assert_se(e == 4095); + n = mfree(n); + + /* If errno is omitted, then e is set to -1 */ + assert_se(parse_syscall_and_errno("mount", &n, &e) >= 0); + assert_se(streq(n, "mount")); + assert_se(e == -1); + n = mfree(n); + + /* parse_syscall_and_errno() does not check the syscall name is valid or not. */ + assert_se(parse_syscall_and_errno("hoge:255", &n, &e) >= 0); + assert_se(streq(n, "hoge")); + assert_se(e == 255); + n = mfree(n); + + /* The function checks the syscall name is empty or not. */ + assert_se(parse_syscall_and_errno("", &n, &e) == -EINVAL); + assert_se(parse_syscall_and_errno(":255", &n, &e) == -EINVAL); + + /* errno must be a valid errno name or number between 0 and ERRNO_MAX == 4095 */ + assert_se(parse_syscall_and_errno("hoge:4096", &n, &e) == -ERANGE); + assert_se(parse_syscall_and_errno("hoge:-3", &n, &e) == -ERANGE); + assert_se(parse_syscall_and_errno("hoge:12.3", &n, &e) == -EINVAL); + assert_se(parse_syscall_and_errno("hoge:123junk", &n, &e) == -EINVAL); + assert_se(parse_syscall_and_errno("hoge:junk123", &n, &e) == -EINVAL); + assert_se(parse_syscall_and_errno("hoge:255:EILSEQ", &n, &e) == -EINVAL); + assert_se(parse_syscall_and_errno("hoge:-EINVAL", &n, &e) == -EINVAL); + assert_se(parse_syscall_and_errno("hoge:EINVALaaa", &n, &e) == -EINVAL); + assert_se(parse_syscall_and_errno("hoge:", &n, &e) == -EINVAL); +} + +static void test_parse_mtu(void) { + uint32_t mtu = 0; + + assert_se(parse_mtu(AF_UNSPEC, "1500", &mtu) >= 0 && mtu == 1500); + assert_se(parse_mtu(AF_UNSPEC, "1400", &mtu) >= 0 && mtu == 1400); + assert_se(parse_mtu(AF_UNSPEC, "65535", &mtu) >= 0 && mtu == 65535); + assert_se(parse_mtu(AF_UNSPEC, "65536", &mtu) >= 0 && mtu == 65536); + assert_se(parse_mtu(AF_UNSPEC, "4294967295", &mtu) >= 0 && mtu == 4294967295); + assert_se(parse_mtu(AF_UNSPEC, "500", &mtu) >= 0 && mtu == 500); + assert_se(parse_mtu(AF_UNSPEC, "1280", &mtu) >= 0 && mtu == 1280); + assert_se(parse_mtu(AF_INET6, "1280", &mtu) >= 0 && mtu == 1280); + assert_se(parse_mtu(AF_INET6, "1279", &mtu) == -ERANGE); + assert_se(parse_mtu(AF_UNSPEC, "4294967296", &mtu) == -ERANGE); + assert_se(parse_mtu(AF_INET6, "4294967296", &mtu) == -ERANGE); + assert_se(parse_mtu(AF_INET6, "68", &mtu) == -ERANGE); + assert_se(parse_mtu(AF_UNSPEC, "68", &mtu) >= 0 && mtu == 68); + assert_se(parse_mtu(AF_UNSPEC, "67", &mtu) == -ERANGE); + assert_se(parse_mtu(AF_UNSPEC, "0", &mtu) == -ERANGE); + assert_se(parse_mtu(AF_UNSPEC, "", &mtu) == -EINVAL); +} + +int main(int argc, char *argv[]) { + log_parse_environment(); + log_open(); + + test_parse_boolean(); + test_parse_pid(); + test_parse_mode(); + test_parse_size(); + test_parse_range(); + test_safe_atolli(); + test_safe_atou16(); + test_safe_atoi16(); + test_safe_atoux16(); + test_safe_atou64(); + test_safe_atoi64(); + test_safe_atod(); + test_parse_percent(); + test_parse_percent_unbounded(); + test_parse_permille(); + test_parse_permille_unbounded(); + test_parse_nice(); + test_parse_dev(); + test_parse_errno(); + test_parse_syscall_and_errno(); + test_parse_mtu(); + + return 0; +} diff --git a/src/test/test-path-lookup.c b/src/test/test-path-lookup.c new file mode 100644 index 00000000..62ebc9c9 --- /dev/null +++ b/src/test/test-path-lookup.c @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "log.h" +#include "path-lookup.h" +#include "rm-rf.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" + +static void test_paths(UnitFileScope scope) { + char template[] = "/tmp/test-path-lookup.XXXXXXX"; + + _cleanup_(lookup_paths_free) LookupPaths lp_without_env = {}; + _cleanup_(lookup_paths_free) LookupPaths lp_with_env = {}; + char *systemd_unit_path; + + assert_se(mkdtemp(template)); + + assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0); + assert_se(lookup_paths_init(&lp_without_env, scope, 0, NULL) >= 0); + assert_se(!strv_isempty(lp_without_env.search_path)); + lookup_paths_log(&lp_without_env); + + systemd_unit_path = strjoina(template, "/systemd-unit-path"); + assert_se(setenv("SYSTEMD_UNIT_PATH", systemd_unit_path, 1) == 0); + assert_se(lookup_paths_init(&lp_with_env, scope, 0, NULL) == 0); + assert_se(strv_length(lp_with_env.search_path) == 1); + assert_se(streq(lp_with_env.search_path[0], systemd_unit_path)); + lookup_paths_log(&lp_with_env); + assert_se(strv_equal(lp_with_env.search_path, STRV_MAKE(systemd_unit_path))); + + assert_se(rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); +} + +static void test_user_and_global_paths(void) { + _cleanup_(lookup_paths_free) LookupPaths lp_global = {}, lp_user = {}; + char **u, **g, **p; + unsigned k = 0; + + assert_se(unsetenv("SYSTEMD_UNIT_PATH") == 0); + assert_se(unsetenv("XDG_DATA_DIRS") == 0); + assert_se(unsetenv("XDG_CONFIG_DIRS") == 0); + + assert_se(lookup_paths_init(&lp_global, UNIT_FILE_GLOBAL, 0, NULL) == 0); + assert_se(lookup_paths_init(&lp_user, UNIT_FILE_USER, 0, NULL) == 0); + g = lp_global.search_path; + u = lp_user.search_path; + + /* Go over all entries in global search path, and verify + * that they also exist in the user search path. Skip any + * entries in user search path which don't exist in the global + * one, but not vice versa. */ + log_info("/* %s */", __func__); + STRV_FOREACH(p, g) { + while (u[k] && !streq(*p, u[k])) { + log_info("+ %s", u[k]); + k++; + } + log_info(" %s", *p); + assert(u[k]); /* If NULL, we didn't find a matching entry */ + k++; + } + STRV_FOREACH(p, u + k) + log_info("+ %s", *p); +} + +static void print_generator_binary_paths(UnitFileScope scope) { + _cleanup_strv_free_ char **paths; + char **dir; + + log_info("Generators dirs (%s):", scope == UNIT_FILE_SYSTEM ? "system" : "user"); + + paths = generator_binary_paths(scope); + STRV_FOREACH(dir, paths) + log_info(" %s", *dir); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_paths(UNIT_FILE_SYSTEM); + test_paths(UNIT_FILE_USER); + test_paths(UNIT_FILE_GLOBAL); + + test_user_and_global_paths(); + + print_generator_binary_paths(UNIT_FILE_SYSTEM); + print_generator_binary_paths(UNIT_FILE_USER); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c new file mode 100644 index 00000000..46cdbaf5 --- /dev/null +++ b/src/test/test-path-util.c @@ -0,0 +1,691 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "macro.h" +#include "mountpoint-util.h" +#include "path-util.h" +#include "rm-rf.h" +#include "stat-util.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "util.h" + +static void test_print_paths(void) { + log_info("DEFAULT_PATH=%s", DEFAULT_PATH); + log_info("DEFAULT_USER_PATH=%s", DEFAULT_USER_PATH); +} + +#define test_path_compare(a, b, result) { \ + assert_se(path_compare(a, b) == result); \ + assert_se(path_compare(b, a) == -result); \ + assert_se(path_equal(a, b) == !result); \ + assert_se(path_equal(b, a) == !result); \ + } + +static void test_path_simplify(const char *in, const char *out, const char *out_dot) { + char *p; + + log_info("/* %s */", __func__); + + p = strdupa(in); + assert_se(streq(path_simplify(p, false), out)); + + p = strdupa(in); + assert_se(streq(path_simplify(p, true), out_dot)); +} + +static void test_path(void) { + _cleanup_close_ int fd = -1; + + log_info("/* %s */", __func__); + + test_path_compare("/goo", "/goo", 0); + test_path_compare("/goo", "/goo", 0); + test_path_compare("//goo", "/goo", 0); + test_path_compare("//goo/////", "/goo", 0); + test_path_compare("goo/////", "goo", 0); + + test_path_compare("/goo/boo", "/goo//boo", 0); + test_path_compare("//goo/boo", "/goo/boo//", 0); + + test_path_compare("/", "///", 0); + + test_path_compare("/x", "x/", 1); + test_path_compare("x/", "/", -1); + + test_path_compare("/x/./y", "x/y", 1); + test_path_compare("x/.y", "x/y", -1); + + test_path_compare("foo", "/foo", -1); + test_path_compare("/foo", "/foo/bar", -1); + test_path_compare("/foo/aaa", "/foo/b", -1); + test_path_compare("/foo/aaa", "/foo/b/a", -1); + test_path_compare("/foo/a", "/foo/aaa", -1); + test_path_compare("/foo/a/b", "/foo/aaa", -1); + + assert_se(path_is_absolute("/")); + assert_se(!path_is_absolute("./")); + + assert_se(is_path("/dir")); + assert_se(is_path("a/b")); + assert_se(!is_path(".")); + + assert_se(streq(basename("./aa/bb/../file.da."), "file.da.")); + assert_se(streq(basename("/aa///.file"), ".file")); + assert_se(streq(basename("/aa///file..."), "file...")); + assert_se(streq(basename("file.../"), "")); + + fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY); + assert_se(fd >= 0); + assert_se(fd_is_mount_point(fd, "/", 0) > 0); + + test_path_simplify("aaa/bbb////ccc", "aaa/bbb/ccc", "aaa/bbb/ccc"); + test_path_simplify("//aaa/.////ccc", "/aaa/./ccc", "/aaa/ccc"); + test_path_simplify("///", "/", "/"); + test_path_simplify("///.//", "/.", "/"); + test_path_simplify("///.//.///", "/./.", "/"); + test_path_simplify("////.././///../.", "/.././../.", "/../.."); + test_path_simplify(".", ".", "."); + test_path_simplify("./", ".", "."); + test_path_simplify(".///.//./.", "./././.", "."); + test_path_simplify(".///.//././/", "./././.", "."); + test_path_simplify("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/.", + "/./aaa/././.bbb/../c./d.dd/..eeee/.", + "/aaa/.bbb/../c./d.dd/..eeee"); + test_path_simplify("//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..", + "/./aaa/././.bbb/../c./d.dd/..eeee/..", + "/aaa/.bbb/../c./d.dd/..eeee/.."); + test_path_simplify(".//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..", + "././aaa/././.bbb/../c./d.dd/..eeee/..", + "aaa/.bbb/../c./d.dd/..eeee/.."); + test_path_simplify("..//./aaa///.//./.bbb/..///c.//d.dd///..eeee/..", + ".././aaa/././.bbb/../c./d.dd/..eeee/..", + "../aaa/.bbb/../c./d.dd/..eeee/.."); + + assert_se(PATH_IN_SET("/bin", "/", "/bin", "/foo")); + assert_se(PATH_IN_SET("/bin", "/bin")); + assert_se(PATH_IN_SET("/bin", "/foo/bar", "/bin")); + assert_se(PATH_IN_SET("/", "/", "/", "/foo/bar")); + assert_se(!PATH_IN_SET("/", "/abc", "/def")); + + assert_se(path_equal_ptr(NULL, NULL)); + assert_se(path_equal_ptr("/a", "/a")); + assert_se(!path_equal_ptr("/a", "/b")); + assert_se(!path_equal_ptr("/a", NULL)); + assert_se(!path_equal_ptr(NULL, "/a")); +} + +static void test_path_equal_root(void) { + /* Nail down the details of how path_equal("/", ...) works. */ + + log_info("/* %s */", __func__); + + assert_se(path_equal("/", "/")); + assert_se(path_equal("/", "//")); + + assert_se(!path_equal("/", "/./")); + assert_se(!path_equal("/", "/../")); + + assert_se(!path_equal("/", "/.../")); + + /* Make sure that files_same works as expected. */ + + assert_se(files_same("/", "/", 0) > 0); + assert_se(files_same("/", "/", AT_SYMLINK_NOFOLLOW) > 0); + assert_se(files_same("/", "//", 0) > 0); + assert_se(files_same("/", "//", AT_SYMLINK_NOFOLLOW) > 0); + + assert_se(files_same("/", "/./", 0) > 0); + assert_se(files_same("/", "/./", AT_SYMLINK_NOFOLLOW) > 0); + assert_se(files_same("/", "/../", 0) > 0); + assert_se(files_same("/", "/../", AT_SYMLINK_NOFOLLOW) > 0); + + assert_se(files_same("/", "/.../", 0) == -ENOENT); + assert_se(files_same("/", "/.../", AT_SYMLINK_NOFOLLOW) == -ENOENT); + + /* The same for path_equal_or_files_same. */ + + assert_se(path_equal_or_files_same("/", "/", 0)); + assert_se(path_equal_or_files_same("/", "/", AT_SYMLINK_NOFOLLOW)); + assert_se(path_equal_or_files_same("/", "//", 0)); + assert_se(path_equal_or_files_same("/", "//", AT_SYMLINK_NOFOLLOW)); + + assert_se(path_equal_or_files_same("/", "/./", 0)); + assert_se(path_equal_or_files_same("/", "/./", AT_SYMLINK_NOFOLLOW)); + assert_se(path_equal_or_files_same("/", "/../", 0)); + assert_se(path_equal_or_files_same("/", "/../", AT_SYMLINK_NOFOLLOW)); + + assert_se(!path_equal_or_files_same("/", "/.../", 0)); + assert_se(!path_equal_or_files_same("/", "/.../", AT_SYMLINK_NOFOLLOW)); +} + +static void test_find_binary(const char *self) { + char *p; + + log_info("/* %s */", __func__); + + assert_se(find_binary("/bin/sh", &p) == 0); + puts(p); + assert_se(path_equal(p, "/bin/sh")); + free(p); + + assert_se(find_binary(self, &p) == 0); + puts(p); + /* libtool might prefix the binary name with "lt-" */ + assert_se(endswith(p, "/lt-test-path-util") || endswith(p, "/test-path-util")); + assert_se(path_is_absolute(p)); + free(p); + + assert_se(find_binary("sh", &p) == 0); + puts(p); + assert_se(endswith(p, "/sh")); + assert_se(path_is_absolute(p)); + free(p); + + assert_se(find_binary("xxxx-xxxx", &p) == -ENOENT); + assert_se(find_binary("/some/dir/xxxx-xxxx", &p) == -ENOENT); +} + +static void test_prefixes(void) { + static const char* const values[] = { + "/a/b/c/d", + "/a/b/c", + "/a/b", + "/a", + "", + NULL + }; + unsigned i; + char s[PATH_MAX]; + bool b; + + log_info("/* %s */", __func__); + + i = 0; + PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") { + log_error("---%s---", s); + assert_se(streq(s, values[i++])); + } + assert_se(values[i] == NULL); + + i = 1; + PATH_FOREACH_PREFIX(s, "/a/b/c/d") { + log_error("---%s---", s); + assert_se(streq(s, values[i++])); + } + assert_se(values[i] == NULL); + + i = 0; + PATH_FOREACH_PREFIX_MORE(s, "////a////b////c///d///////") + assert_se(streq(s, values[i++])); + assert_se(values[i] == NULL); + + i = 1; + PATH_FOREACH_PREFIX(s, "////a////b////c///d///////") + assert_se(streq(s, values[i++])); + assert_se(values[i] == NULL); + + PATH_FOREACH_PREFIX(s, "////") + assert_not_reached("Wut?"); + + b = false; + PATH_FOREACH_PREFIX_MORE(s, "////") { + assert_se(!b); + assert_se(streq(s, "")); + b = true; + } + assert_se(b); + + PATH_FOREACH_PREFIX(s, "") + assert_not_reached("wut?"); + + b = false; + PATH_FOREACH_PREFIX_MORE(s, "") { + assert_se(!b); + assert_se(streq(s, "")); + b = true; + } +} + +static void test_path_join(void) { + log_info("/* %s */", __func__); + +#define test_join(expected, ...) { \ + _cleanup_free_ char *z = NULL; \ + z = path_join(__VA_ARGS__); \ + log_debug("got \"%s\", expected \"%s\"", z, expected); \ + assert_se(streq(z, expected)); \ + } + + test_join("/root/a/b/c", "/root", "/a/b", "/c"); + test_join("/root/a/b/c", "/root", "a/b", "c"); + test_join("/root/a/b/c", "/root", "/a/b", "c"); + test_join("/root/c", "/root", "/", "c"); + test_join("/root/", "/root", "/", NULL); + + test_join("/a/b/c", "", "/a/b", "/c"); + test_join("a/b/c", "", "a/b", "c"); + test_join("/a/b/c", "", "/a/b", "c"); + test_join("/c", "", "/", "c"); + test_join("/", "", "/", NULL); + + test_join("/a/b/c", NULL, "/a/b", "/c"); + test_join("a/b/c", NULL, "a/b", "c"); + test_join("/a/b/c", NULL, "/a/b", "c"); + test_join("/c", NULL, "/", "c"); + test_join("/", NULL, "/", NULL); + + test_join("", "", NULL); + test_join("", NULL, ""); + test_join("", NULL, NULL); + + test_join("foo/bar", "foo", "bar"); + test_join("foo/bar", "", "foo", "bar"); + test_join("foo/bar", NULL, "foo", NULL, "bar"); + test_join("foo/bar", "", "foo", "", "bar", ""); + test_join("foo/bar", "", "", "", "", "foo", "", "", "", "bar", "", "", ""); + + test_join("//foo///bar//", "", "/", "", "/foo/", "", "/", "", "/bar/", "", "/", ""); + test_join("/foo/bar/", "/", "foo", "/", "bar", "/"); + test_join("foo/bar/baz", "foo", "bar", "baz"); + test_join("foo/bar/baz", "foo/", "bar", "/baz"); + test_join("foo//bar//baz", "foo/", "/bar/", "/baz"); + test_join("//foo////bar////baz//", "//foo/", "///bar/", "///baz//"); +} + +static void test_fsck_exists(void) { + log_info("/* %s */", __func__); + + /* Ensure we use a sane default for PATH. */ + unsetenv("PATH"); + + /* fsck.minix is provided by util-linux and will probably exist. */ + assert_se(fsck_exists("minix") == 1); + + assert_se(fsck_exists("AbCdE") == 0); + assert_se(fsck_exists("/../bin/") == 0); +} + +static void test_make_relative(void) { + char *result; + + log_info("/* %s */", __func__); + + assert_se(path_make_relative("some/relative/path", "/some/path", &result) < 0); + assert_se(path_make_relative("/some/path", "some/relative/path", &result) < 0); + assert_se(path_make_relative("/some/dotdot/../path", "/some/path", &result) < 0); + +#define test(from_dir, to_path, expected) { \ + _cleanup_free_ char *z = NULL; \ + path_make_relative(from_dir, to_path, &z); \ + assert_se(streq(z, expected)); \ + } + + test("/", "/", "."); + test("/", "/some/path", "some/path"); + test("/some/path", "/some/path", "."); + test("/some/path", "/some/path/in/subdir", "in/subdir"); + test("/some/path", "/", "../.."); + test("/some/path", "/some/other/path", "../other/path"); + test("/some/path/./dot", "/some/further/path", "../../further/path"); + test("//extra.//.//./.slashes//./won't////fo.ol///anybody//", "/././/extra././/.slashes////ar.e/.just/././.fine///", "../../../ar.e/.just/.fine"); +} + +static void test_strv_resolve(void) { + char tmp_dir[] = "/tmp/test-path-util-XXXXXX"; + _cleanup_strv_free_ char **search_dirs = NULL; + _cleanup_strv_free_ char **absolute_dirs = NULL; + char **d; + + assert_se(mkdtemp(tmp_dir) != NULL); + + search_dirs = strv_new("/dir1", "/dir2", "/dir3"); + assert_se(search_dirs); + STRV_FOREACH(d, search_dirs) { + char *p = path_join(tmp_dir, *d); + assert_se(p); + assert_se(strv_push(&absolute_dirs, p) == 0); + } + + assert_se(mkdir(absolute_dirs[0], 0700) == 0); + assert_se(mkdir(absolute_dirs[1], 0700) == 0); + assert_se(symlink("dir2", absolute_dirs[2]) == 0); + + path_strv_resolve(search_dirs, tmp_dir); + assert_se(streq(search_dirs[0], "/dir1")); + assert_se(streq(search_dirs[1], "/dir2")); + assert_se(streq(search_dirs[2], "/dir2")); + + assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0); +} + +static void test_path_startswith(void) { + const char *p; + + log_info("/* %s */", __func__); + + p = path_startswith("/foo/bar/barfoo/", "/foo"); + assert_se(streq_ptr(p, "bar/barfoo/")); + + p = path_startswith("/foo/bar/barfoo/", "/foo/"); + assert_se(streq_ptr(p, "bar/barfoo/")); + + p = path_startswith("/foo/bar/barfoo/", "/"); + assert_se(streq_ptr(p, "foo/bar/barfoo/")); + + p = path_startswith("/foo/bar/barfoo/", "////"); + assert_se(streq_ptr(p, "foo/bar/barfoo/")); + + p = path_startswith("/foo/bar/barfoo/", "/foo//bar/////barfoo///"); + assert_se(streq_ptr(p, "")); + + p = path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo////"); + assert_se(streq_ptr(p, "")); + + p = path_startswith("/foo/bar/barfoo/", "/foo/bar///barfoo/"); + assert_se(streq_ptr(p, "")); + + p = path_startswith("/foo/bar/barfoo/", "/foo////bar/barfoo/"); + assert_se(streq_ptr(p, "")); + + p = path_startswith("/foo/bar/barfoo/", "////foo/bar/barfoo/"); + assert_se(streq_ptr(p, "")); + + p = path_startswith("/foo/bar/barfoo/", "/foo/bar/barfoo"); + assert_se(streq_ptr(p, "")); + + assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa/")); + assert_se(!path_startswith("/foo/bar/barfoo/", "/foo/bar/barfooa")); + assert_se(!path_startswith("/foo/bar/barfoo/", "")); + assert_se(!path_startswith("/foo/bar/barfoo/", "/bar/foo")); + assert_se(!path_startswith("/foo/bar/barfoo/", "/f/b/b/")); +} + +static void test_prefix_root_one(const char *r, const char *p, const char *expected) { + _cleanup_free_ char *s = NULL; + const char *t; + + assert_se(s = path_join(r, p)); + assert_se(path_equal_ptr(s, expected)); + + t = prefix_roota(r, p); + assert_se(t); + assert_se(path_equal_ptr(t, expected)); +} + +static void test_prefix_root(void) { + log_info("/* %s */", __func__); + + test_prefix_root_one("/", "/foo", "/foo"); + test_prefix_root_one(NULL, "/foo", "/foo"); + test_prefix_root_one("", "/foo", "/foo"); + test_prefix_root_one("///", "/foo", "/foo"); + test_prefix_root_one("/", "////foo", "/foo"); + test_prefix_root_one(NULL, "////foo", "/foo"); + test_prefix_root_one("/", "foo", "/foo"); + test_prefix_root_one("", "foo", "foo"); + test_prefix_root_one(NULL, "foo", "foo"); + + test_prefix_root_one("/foo", "/bar", "/foo/bar"); + test_prefix_root_one("/foo", "bar", "/foo/bar"); + test_prefix_root_one("foo", "bar", "foo/bar"); + test_prefix_root_one("/foo/", "/bar", "/foo/bar"); + test_prefix_root_one("/foo/", "//bar", "/foo/bar"); + test_prefix_root_one("/foo///", "//bar", "/foo/bar"); +} + +static void test_file_in_same_dir(void) { + char *t; + + log_info("/* %s */", __func__); + + t = file_in_same_dir("/", "a"); + assert_se(streq(t, "/a")); + free(t); + + t = file_in_same_dir("/", "/a"); + assert_se(streq(t, "/a")); + free(t); + + t = file_in_same_dir("", "a"); + assert_se(streq(t, "a")); + free(t); + + t = file_in_same_dir("a/", "a"); + assert_se(streq(t, "a/a")); + free(t); + + t = file_in_same_dir("bar/foo", "bar"); + assert_se(streq(t, "bar/bar")); + free(t); +} + +static void test_last_path_component(void) { + assert_se(last_path_component(NULL) == NULL); + assert_se(streq(last_path_component("a/b/c"), "c")); + assert_se(streq(last_path_component("a/b/c/"), "c/")); + assert_se(streq(last_path_component("/"), "/")); + assert_se(streq(last_path_component("//"), "/")); + assert_se(streq(last_path_component("///"), "/")); + assert_se(streq(last_path_component("."), ".")); + assert_se(streq(last_path_component("./."), ".")); + assert_se(streq(last_path_component("././"), "./")); + assert_se(streq(last_path_component("././/"), ".//")); + assert_se(streq(last_path_component("/foo/a"), "a")); + assert_se(streq(last_path_component("/foo/a/"), "a/")); + assert_se(streq(last_path_component(""), "")); + assert_se(streq(last_path_component("a"), "a")); + assert_se(streq(last_path_component("a/"), "a/")); + assert_se(streq(last_path_component("/a"), "a")); + assert_se(streq(last_path_component("/a/"), "a/")); +} + +static void test_path_extract_filename_one(const char *input, const char *output, int ret) { + _cleanup_free_ char *k = NULL; + int r; + + r = path_extract_filename(input, &k); + log_info("%s → %s/%s [expected: %s/%s]", strnull(input), strnull(k), strerror_safe(r), strnull(output), strerror_safe(ret)); + assert_se(streq_ptr(k, output)); + assert_se(r == ret); +} + +static void test_path_extract_filename(void) { + log_info("/* %s */", __func__); + + test_path_extract_filename_one(NULL, NULL, -EINVAL); + test_path_extract_filename_one("a/b/c", "c", 0); + test_path_extract_filename_one("a/b/c/", "c", 0); + test_path_extract_filename_one("/", NULL, -EINVAL); + test_path_extract_filename_one("//", NULL, -EINVAL); + test_path_extract_filename_one("///", NULL, -EINVAL); + test_path_extract_filename_one(".", NULL, -EINVAL); + test_path_extract_filename_one("./.", NULL, -EINVAL); + test_path_extract_filename_one("././", NULL, -EINVAL); + test_path_extract_filename_one("././/", NULL, -EINVAL); + test_path_extract_filename_one("/foo/a", "a", 0); + test_path_extract_filename_one("/foo/a/", "a", 0); + test_path_extract_filename_one("", NULL, -EINVAL); + test_path_extract_filename_one("a", "a", 0); + test_path_extract_filename_one("a/", "a", 0); + test_path_extract_filename_one("/a", "a", 0); + test_path_extract_filename_one("/a/", "a", 0); + test_path_extract_filename_one("/////////////a/////////////", "a", 0); + test_path_extract_filename_one("xx/.", NULL, -EINVAL); + test_path_extract_filename_one("xx/..", NULL, -EINVAL); + test_path_extract_filename_one("..", NULL, -EINVAL); + test_path_extract_filename_one("/..", NULL, -EINVAL); + test_path_extract_filename_one("../", NULL, -EINVAL); + test_path_extract_filename_one(".", NULL, -EINVAL); + test_path_extract_filename_one("/.", NULL, -EINVAL); + test_path_extract_filename_one("./", NULL, -EINVAL); +} + +static void test_filename_is_valid(void) { + char foo[FILENAME_MAX+2]; + int i; + + log_info("/* %s */", __func__); + + assert_se(!filename_is_valid("")); + assert_se(!filename_is_valid("/bar/foo")); + assert_se(!filename_is_valid("/")); + assert_se(!filename_is_valid(".")); + assert_se(!filename_is_valid("..")); + + for (i=0; i= 0); + log_info("%s has systemd >= %u: %s", + path ?: "Current installation", versions[i], yes_no(r)); + } +} + +static void test_skip_dev_prefix(void) { + log_info("/* %s */", __func__); + + assert_se(streq(skip_dev_prefix("/"), "/")); + assert_se(streq(skip_dev_prefix("/dev"), "")); + assert_se(streq(skip_dev_prefix("/dev/"), "")); + assert_se(streq(skip_dev_prefix("/dev/foo"), "foo")); + assert_se(streq(skip_dev_prefix("/dev/foo/bar"), "foo/bar")); + assert_se(streq(skip_dev_prefix("//dev"), "")); + assert_se(streq(skip_dev_prefix("//dev//"), "")); + assert_se(streq(skip_dev_prefix("/dev///foo"), "foo")); + assert_se(streq(skip_dev_prefix("///dev///foo///bar"), "foo///bar")); + assert_se(streq(skip_dev_prefix("//foo"), "//foo")); + assert_se(streq(skip_dev_prefix("foo"), "foo")); +} + +static void test_empty_or_root(void) { + log_info("/* %s */", __func__); + + assert_se(empty_or_root(NULL)); + assert_se(empty_or_root("")); + assert_se(empty_or_root("/")); + assert_se(empty_or_root("//")); + assert_se(empty_or_root("///")); + assert_se(empty_or_root("/////////////////")); + assert_se(!empty_or_root("xxx")); + assert_se(!empty_or_root("/xxx")); + assert_se(!empty_or_root("/xxx/")); + assert_se(!empty_or_root("//yy//")); +} + +static void test_path_startswith_set(void) { + log_info("/* %s */", __func__); + + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo/bar", "/zzz"), "")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo/", "/zzz"), "bar")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo", "/zzz"), "bar")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/", "/zzz"), "foo/bar")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "", "/zzz"), NULL)); + + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo/bar", "/zzz"), NULL)); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo/", "/zzz"), "bar2")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/foo", "/zzz"), "bar2")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "/", "/zzz"), "foo/bar2")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar2", "/foo/quux", "", "/zzz"), NULL)); + + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo/bar", "/zzz"), NULL)); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo/", "/zzz"), NULL)); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/foo", "/zzz"), NULL)); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "/", "/zzz"), "foo2/bar")); + assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "", "/zzz"), NULL)); +} + +static void test_path_startswith_strv(void) { + log_info("/* %s */", __func__); + + assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), "")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), "bar")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo", "/zzz")), "bar")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo/bar")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "", "/zzz")), NULL)); + + assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), NULL)); + assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), "bar2")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo", "/zzz")), "bar2")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo/bar2")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "", "/zzz")), NULL)); + + assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), NULL)); + assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), NULL)); + assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo", "/zzz")), NULL)); + assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo2/bar")); + assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "", "/zzz")), NULL)); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_print_paths(); + test_path(); + test_path_equal_root(); + test_find_binary(argv[0]); + test_prefixes(); + test_path_join(); + test_fsck_exists(); + test_make_relative(); + test_strv_resolve(); + test_path_startswith(); + test_prefix_root(); + test_file_in_same_dir(); + test_last_path_component(); + test_path_extract_filename(); + test_filename_is_valid(); + test_hidden_or_backup_file(); + test_skip_dev_prefix(); + test_empty_or_root(); + test_path_startswith_set(); + test_path_startswith_strv(); + + test_systemd_installation_has_version(argv[1]); /* NULL is OK */ + + return 0; +} diff --git a/src/test/test-path.c b/src/test/test-path.c new file mode 100644 index 00000000..6ad222b5 --- /dev/null +++ b/src/test/test-path.c @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "all-units.h" +#include "fd-util.h" +#include "fs-util.h" +#include "macro.h" +#include "manager.h" +#include "mkdir.h" +#include "path-util.h" +#include "rm-rf.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "unit.h" +#include "util.h" + +typedef void (*test_function_t)(Manager *m); + +static int setup_test(Manager **m) { + char **tests_path = STRV_MAKE("exists", "existsglobFOOBAR", "changed", "modified", "unit", + "directorynotempty", "makedirectory"); + char **test_path; + Manager *tmp = NULL; + int r; + + assert_se(m); + + r = enter_cgroup_subroot(NULL); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &tmp); + if (manager_errno_skip_test(r)) + return log_tests_skipped_errno(r, "manager_new"); + assert_se(r >= 0); + assert_se(manager_startup(tmp, NULL, NULL) >= 0); + + STRV_FOREACH(test_path, tests_path) { + _cleanup_free_ char *p = NULL; + + p = strjoin("/tmp/test-path_", *test_path); + assert_se(p); + + (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL); + } + + *m = tmp; + + return 0; +} + +static void shutdown_test(Manager *m) { + assert_se(m); + + manager_free(m); +} + +static void check_stop_unlink(Manager *m, Unit *unit, const char *test_path, const char *service_name) { + _cleanup_free_ char *tmp = NULL; + Unit *service_unit = NULL; + Service *service = NULL; + usec_t ts; + usec_t timeout = 2 * USEC_PER_SEC; + + assert_se(m); + assert_se(unit); + assert_se(test_path); + + if (!service_name) { + assert_se(tmp = strreplace(unit->id, ".path", ".service")); + service_unit = manager_get_unit(m, tmp); + } else + service_unit = manager_get_unit(m, service_name); + assert_se(service_unit); + service = SERVICE(service_unit); + + ts = now(CLOCK_MONOTONIC); + /* We process events until the service related to the path has been successfully started */ + while (service->result != SERVICE_SUCCESS || service->state != SERVICE_START) { + usec_t n; + int r; + + r = sd_event_run(m->event, 100 * USEC_PER_MSEC); + assert_se(r >= 0); + + printf("%s: state = %s; result = %s \n", + service_unit->id, + service_state_to_string(service->state), + service_result_to_string(service->result)); + + /* But we timeout if the service has not been started in the allocated time */ + n = now(CLOCK_MONOTONIC); + if (ts + timeout < n) { + log_error("Test timeout when testing %s", unit->id); + exit(EXIT_FAILURE); + } + } + + assert_se(unit_stop(unit) >= 0); + (void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL); +} + +static void test_path_exists(Manager *m) { + const char *test_path = "/tmp/test-path_exists"; + Unit *unit = NULL; + + assert_se(m); + + assert_se(manager_load_startable_unit_or_warn(m, "path-exists.path", NULL, &unit) >= 0); + assert_se(unit_start(unit) >= 0); + + assert_se(touch(test_path) >= 0); + + check_stop_unlink(m, unit, test_path, NULL); +} + +static void test_path_existsglob(Manager *m) { + const char *test_path = "/tmp/test-path_existsglobFOOBAR"; + Unit *unit = NULL; + + assert_se(m); + assert_se(manager_load_startable_unit_or_warn(m, "path-existsglob.path", NULL, &unit) >= 0); + assert_se(unit_start(unit) >= 0); + + assert_se(touch(test_path) >= 0); + + check_stop_unlink(m, unit, test_path, NULL); +} + +static void test_path_changed(Manager *m) { + const char *test_path = "/tmp/test-path_changed"; + FILE *f; + Unit *unit = NULL; + + assert_se(m); + + assert_se(touch(test_path) >= 0); + + assert_se(manager_load_startable_unit_or_warn(m, "path-changed.path", NULL, &unit) >= 0); + assert_se(unit_start(unit) >= 0); + + f = fopen(test_path, "w"); + assert_se(f); + fclose(f); + + check_stop_unlink(m, unit, test_path, NULL); +} + +static void test_path_modified(Manager *m) { + _cleanup_fclose_ FILE *f = NULL; + const char *test_path = "/tmp/test-path_modified"; + Unit *unit = NULL; + + assert_se(m); + + assert_se(touch(test_path) >= 0); + + assert_se(manager_load_startable_unit_or_warn(m, "path-modified.path", NULL, &unit) >= 0); + assert_se(unit_start(unit) >= 0); + + f = fopen(test_path, "w"); + assert_se(f); + fputs("test", f); + + check_stop_unlink(m, unit, test_path, NULL); +} + +static void test_path_unit(Manager *m) { + const char *test_path = "/tmp/test-path_unit"; + Unit *unit = NULL; + + assert_se(m); + + assert_se(manager_load_startable_unit_or_warn(m, "path-unit.path", NULL, &unit) >= 0); + assert_se(unit_start(unit) >= 0); + + assert_se(touch(test_path) >= 0); + + check_stop_unlink(m, unit, test_path, "path-mycustomunit.service"); +} + +static void test_path_directorynotempty(Manager *m) { + const char *test_path = "/tmp/test-path_directorynotempty/"; + Unit *unit = NULL; + + assert_se(m); + + assert_se(access(test_path, F_OK) < 0); + + assert_se(manager_load_startable_unit_or_warn(m, "path-directorynotempty.path", NULL, &unit) >= 0); + assert_se(unit_start(unit) >= 0); + + /* MakeDirectory default to no */ + assert_se(access(test_path, F_OK) < 0); + + assert_se(mkdir_p(test_path, 0755) >= 0); + assert_se(touch(strjoina(test_path, "test_file")) >= 0); + + check_stop_unlink(m, unit, test_path, NULL); +} + +static void test_path_makedirectory_directorymode(Manager *m) { + const char *test_path = "/tmp/test-path_makedirectory/"; + Unit *unit = NULL; + struct stat s; + + assert_se(m); + + assert_se(access(test_path, F_OK) < 0); + + assert_se(manager_load_startable_unit_or_warn(m, "path-makedirectory.path", NULL, &unit) >= 0); + assert_se(unit_start(unit) >= 0); + + /* Check if the directory has been created */ + assert_se(access(test_path, F_OK) >= 0); + + /* Check the mode we specified with DirectoryMode=0744 */ + assert_se(stat(test_path, &s) >= 0); + assert_se((s.st_mode & S_IRWXU) == 0700); + assert_se((s.st_mode & S_IRWXG) == 0040); + assert_se((s.st_mode & S_IRWXO) == 0004); + + assert_se(unit_stop(unit) >= 0); + (void) rm_rf(test_path, REMOVE_ROOT|REMOVE_PHYSICAL); +} + +int main(int argc, char *argv[]) { + static const test_function_t tests[] = { + test_path_exists, + test_path_existsglob, + test_path_changed, + test_path_modified, + test_path_unit, + test_path_directorynotempty, + test_path_makedirectory_directorymode, + NULL, + }; + + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + _cleanup_free_ char *test_path = NULL; + const test_function_t *test = NULL; + Manager *m = NULL; + + umask(022); + + test_setup_logging(LOG_INFO); + + test_path = path_join(get_testdata_dir(), "test-path"); + assert_se(set_unit_path(test_path) >= 0); + assert_se(runtime_dir = setup_fake_runtime_dir()); + + for (test = tests; test && *test; test++) { + int r; + + /* We create a clean environment for each test */ + r = setup_test(&m); + if (r != 0) + return r; + + (*test)(m); + + shutdown_test(m); + } + + return 0; +} diff --git a/src/test/test-pretty-print.c b/src/test/test-pretty-print.c new file mode 100644 index 00000000..9236eb13 --- /dev/null +++ b/src/test/test-pretty-print.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "macro.h" +#include "pretty-print.h" +#include "strv.h" +#include "tests.h" + +static void test_terminal_urlify(void) { + _cleanup_free_ char *formatted = NULL; + + assert_se(terminal_urlify("https://www.freedesktop.org/wiki/Software/systemd/", "systemd homepage", &formatted) >= 0); + printf("Hey, consider visiting the %s right now! It is very good!\n", formatted); + + formatted = mfree(formatted); + + assert_se(terminal_urlify_path("/etc/fstab", "this link to your /etc/fstab", &formatted) >= 0); + printf("Or click on %s to have a look at it!\n", formatted); +} + +static void test_cat_files(void) { + assert_se(cat_files("/no/such/file", NULL, 0) == -ENOENT); + assert_se(cat_files("/no/such/file", NULL, CAT_FLAGS_MAIN_FILE_OPTIONAL) == 0); + + if (access("/etc/fstab", R_OK) >= 0) + assert_se(cat_files("/etc/fstab", STRV_MAKE("/etc/fstab", "/etc/fstab"), 0) == 0); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + test_terminal_urlify(); + test_cat_files(); + + print_separator(); + + return 0; +} diff --git a/src/test/test-prioq.c b/src/test/test-prioq.c new file mode 100644 index 00000000..21d5b44f --- /dev/null +++ b/src/test/test-prioq.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "prioq.h" +#include "set.h" +#include "siphash24.h" +#include "sort-util.h" + +#define SET_SIZE 1024*4 + +static int unsigned_compare(const unsigned *a, const unsigned *b) { + return CMP(*a, *b); +} + +static void test_unsigned(void) { + _cleanup_(prioq_freep) Prioq *q = NULL; + unsigned buffer[SET_SIZE], i, u, n; + + srand(0); + + assert_se(q = prioq_new(trivial_compare_func)); + + for (i = 0; i < ELEMENTSOF(buffer); i++) { + u = (unsigned) rand(); + buffer[i] = u; + assert_se(prioq_put(q, UINT_TO_PTR(u), NULL) >= 0); + + n = prioq_size(q); + assert_se(prioq_remove(q, UINT_TO_PTR(u), &n) == 0); + } + + typesafe_qsort(buffer, ELEMENTSOF(buffer), unsigned_compare); + + for (i = 0; i < ELEMENTSOF(buffer); i++) { + assert_se(prioq_size(q) == ELEMENTSOF(buffer) - i); + + u = PTR_TO_UINT(prioq_pop(q)); + assert_se(buffer[i] == u); + } + + assert_se(prioq_isempty(q)); +} + +struct test { + unsigned value; + unsigned idx; +}; + +static int test_compare(const struct test *x, const struct test *y) { + return CMP(x->value, y->value); +} + +static void test_hash(const struct test *x, struct siphash *state) { + siphash24_compress(&x->value, sizeof(x->value), state); +} + +DEFINE_PRIVATE_HASH_OPS(test_hash_ops, struct test, test_hash, test_compare); + +static void test_struct(void) { + _cleanup_(prioq_freep) Prioq *q = NULL; + _cleanup_(set_freep) Set *s = NULL; + unsigned previous = 0, i; + struct test *t; + + srand(0); + + assert_se(q = prioq_new((compare_func_t) test_compare)); + assert_se(s = set_new(&test_hash_ops)); + + assert_se(prioq_peek(q) == NULL); + assert_se(prioq_peek_by_index(q, 0) == NULL); + assert_se(prioq_peek_by_index(q, 1) == NULL); + assert_se(prioq_peek_by_index(q, (unsigned) -1) == NULL); + + for (i = 0; i < SET_SIZE; i++) { + assert_se(t = new0(struct test, 1)); + t->value = (unsigned) rand(); + + assert_se(prioq_put(q, t, &t->idx) >= 0); + + if (i % 4 == 0) + assert_se(set_consume(s, t) >= 0); + } + + for (i = 0; i < SET_SIZE; i++) + assert_se(prioq_peek_by_index(q, i)); + assert_se(prioq_peek_by_index(q, SET_SIZE) == NULL); + + unsigned count = 0; + PRIOQ_FOREACH_ITEM(q, t) { + assert_se(t); + count++; + } + assert_se(count == SET_SIZE); + + while ((t = set_steal_first(s))) { + assert_se(prioq_remove(q, t, &t->idx) == 1); + assert_se(prioq_remove(q, t, &t->idx) == 0); + assert_se(prioq_remove(q, t, NULL) == 0); + + free(t); + } + + for (i = 0; i < SET_SIZE * 3 / 4; i++) { + assert_se(prioq_size(q) == (SET_SIZE * 3 / 4) - i); + + assert_se(t = prioq_pop(q)); + assert_se(prioq_remove(q, t, &t->idx) == 0); + assert_se(prioq_remove(q, t, NULL) == 0); + assert_se(previous <= t->value); + + previous = t->value; + free(t); + } + + assert_se(prioq_isempty(q)); + assert_se(set_isempty(s)); +} + +int main(int argc, char* argv[]) { + + test_unsigned(); + test_struct(); + + return 0; +} diff --git a/src/test/test-proc-cmdline.c b/src/test/test-proc-cmdline.c new file mode 100644 index 00000000..bdcd1fc4 --- /dev/null +++ b/src/test/test-proc-cmdline.c @@ -0,0 +1,265 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "env-util.h" +#include "log.h" +#include "macro.h" +#include "proc-cmdline.h" +#include "special.h" +#include "string-util.h" +#include "tests.h" +#include "util.h" + +static int obj; + +static int parse_item(const char *key, const char *value, void *data) { + assert_se(key); + assert_se(data == &obj); + + log_info("kernel cmdline option <%s> = <%s>", key, strna(value)); + return 0; +} + +static void test_proc_cmdline_parse(void) { + log_info("/* %s */", __func__); + + assert_se(proc_cmdline_parse(parse_item, &obj, PROC_CMDLINE_STRIP_RD_PREFIX) >= 0); +} + +static void test_proc_cmdline_override(void) { + log_info("/* %s */", __func__); + + assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm some_arg_with_space='foo bar' and_one_more=\"zzz aaa\"") == 0); + assert_se(putenv((char*) "SYSTEMD_EFI_OPTIONS=differnt") == 0); + + /* First test if the overrides for /proc/cmdline still work */ + _cleanup_free_ char *line = NULL, *value = NULL; + assert_se(proc_cmdline(&line) >= 0); + + /* Test if parsing makes uses of the override */ + assert_se(streq(line, "foo_bar=quux wuff-piep=tuet zumm some_arg_with_space='foo bar' and_one_more=\"zzz aaa\"")); + assert_se(proc_cmdline_get_key("foo_bar", 0, &value) > 0 && streq_ptr(value, "quux")); + value = mfree(value); + + assert_se(proc_cmdline_get_key("some_arg_with_space", 0, &value) > 0 && streq_ptr(value, "foo bar")); + value = mfree(value); + + assert_se(proc_cmdline_get_key("and_one_more", 0, &value) > 0 && streq_ptr(value, "zzz aaa")); + value = mfree(value); + + assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=") == 0); + assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm some_arg_with_space='foo bar' and_one_more=\"zzz aaa\"") == 0); + + assert_se(streq(line, "foo_bar=quux wuff-piep=tuet zumm some_arg_with_space='foo bar' and_one_more=\"zzz aaa\"")); + assert_se(proc_cmdline_get_key("foo_bar", 0, &value) > 0 && streq_ptr(value, "quux")); + value = mfree(value); + + assert_se(proc_cmdline_get_key("some_arg_with_space", 0, &value) > 0 && streq_ptr(value, "foo bar")); + value = mfree(value); + + assert_se(proc_cmdline_get_key("and_one_more", 0, &value) > 0 && streq_ptr(value, "zzz aaa")); + value = mfree(value); +} + +static int parse_item_given(const char *key, const char *value, void *data) { + assert_se(key); + assert_se(data); + + bool *strip = data; + + log_info("%s: option <%s> = <%s>", __func__, key, strna(value)); + if (proc_cmdline_key_streq(key, "foo_bar")) + assert_se(streq(value, "quux")); + else if (proc_cmdline_key_streq(key, "wuff-piep")) + assert_se(streq(value, "tuet ")); + else if (proc_cmdline_key_streq(key, "space")) + assert_se(streq(value, "x y z")); + else if (proc_cmdline_key_streq(key, "miepf")) + assert_se(streq(value, "uuu")); + else if (in_initrd() && *strip && proc_cmdline_key_streq(key, "zumm")) + assert_se(!value); + else if (in_initrd() && !*strip && proc_cmdline_key_streq(key, "rd.zumm")) + assert_se(!value); + else + assert_not_reached("Bad key!"); + + return 0; +} + +static void test_proc_cmdline_given(bool flip_initrd) { + log_info("/* %s (flip: %s) */", __func__, yes_no(flip_initrd)); + + if (flip_initrd) + in_initrd_force(!in_initrd()); + + bool t = true, f = false; + assert_se(proc_cmdline_parse_given("foo_bar=quux wuff-piep=\"tuet \" rd.zumm space='x y z' miepf=\"uuu\"", + parse_item_given, &t, PROC_CMDLINE_STRIP_RD_PREFIX) >= 0); + + assert_se(proc_cmdline_parse_given("foo_bar=quux wuff-piep=\"tuet \" rd.zumm space='x y z' miepf=\"uuu\"", + parse_item_given, &f, 0) >= 0); + + if (flip_initrd) + in_initrd_force(!in_initrd()); +} + +static void test_proc_cmdline_get_key(void) { + _cleanup_free_ char *value = NULL; + + log_info("/* %s */", __func__); + assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm spaaace='ö ü ß' ticks=\"''\"\n\nkkk=uuu\n\n\n") == 0); + + assert_se(proc_cmdline_get_key("", 0, &value) == -EINVAL); + assert_se(proc_cmdline_get_key("abc", 0, NULL) == 0); + assert_se(proc_cmdline_get_key("abc", 0, &value) == 0 && value == NULL); + assert_se(proc_cmdline_get_key("abc", PROC_CMDLINE_VALUE_OPTIONAL, &value) == 0 && value == NULL); + + assert_se(proc_cmdline_get_key("foo_bar", 0, &value) > 0 && streq_ptr(value, "quux")); + value = mfree(value); + assert_se(proc_cmdline_get_key("foo_bar", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && streq_ptr(value, "quux")); + value = mfree(value); + assert_se(proc_cmdline_get_key("foo-bar", 0, &value) > 0 && streq_ptr(value, "quux")); + value = mfree(value); + assert_se(proc_cmdline_get_key("foo-bar", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && streq_ptr(value, "quux")); + value = mfree(value); + assert_se(proc_cmdline_get_key("foo-bar", 0, NULL) == 0); + assert_se(proc_cmdline_get_key("foo-bar", PROC_CMDLINE_VALUE_OPTIONAL, NULL) == -EINVAL); + + assert_se(proc_cmdline_get_key("wuff-piep", 0, &value) > 0 && streq_ptr(value, "tuet")); + value = mfree(value); + assert_se(proc_cmdline_get_key("wuff-piep", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && streq_ptr(value, "tuet")); + value = mfree(value); + assert_se(proc_cmdline_get_key("wuff_piep", 0, &value) > 0 && streq_ptr(value, "tuet")); + value = mfree(value); + assert_se(proc_cmdline_get_key("wuff_piep", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && streq_ptr(value, "tuet")); + value = mfree(value); + assert_se(proc_cmdline_get_key("wuff_piep", 0, NULL) == 0); + assert_se(proc_cmdline_get_key("wuff_piep", PROC_CMDLINE_VALUE_OPTIONAL, NULL) == -EINVAL); + + assert_se(proc_cmdline_get_key("zumm", 0, &value) == 0 && value == NULL); + assert_se(proc_cmdline_get_key("zumm", PROC_CMDLINE_VALUE_OPTIONAL, &value) > 0 && value == NULL); + assert_se(proc_cmdline_get_key("zumm", 0, NULL) > 0); + + assert_se(proc_cmdline_get_key("spaaace", 0, &value) > 0 && streq_ptr(value, "ö ü ß")); + value = mfree(value); + + assert_se(proc_cmdline_get_key("ticks", 0, &value) > 0 && streq_ptr(value, "''")); + value = mfree(value); + + assert_se(proc_cmdline_get_key("kkk", 0, &value) > 0 && streq_ptr(value, "uuu")); +} + +static void test_proc_cmdline_get_bool(void) { + bool value = false; + + log_info("/* %s */", __func__); + assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar bar-waldo=1 x_y-z=0 quux=miep\nda=yes\nthe=1") == 0); + assert_se(putenv((char*) "SYSTEMD_EFI_OPTIONS=") == 0); + + assert_se(proc_cmdline_get_bool("", &value) == -EINVAL); + assert_se(proc_cmdline_get_bool("abc", &value) == 0 && value == false); + assert_se(proc_cmdline_get_bool("foo_bar", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("foo-bar", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("bar-waldo", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("bar_waldo", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("x_y-z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("x-y-z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("x-y_z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("x_y_z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("quux", &value) == -EINVAL && value == false); + assert_se(proc_cmdline_get_bool("da", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("the", &value) > 0 && value == true); + + assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=") == 0); + assert_se(putenv((char*) "SYSTEMD_EFI_OPTIONS=foo_bar bar-waldo=1 x_y-z=0 quux=miep\nda=yes\nthe=1") == 0); + +#if ENABLE_EFI + assert_se(proc_cmdline_get_bool("", &value) == -EINVAL); + assert_se(proc_cmdline_get_bool("abc", &value) == 0 && value == false); + assert_se(proc_cmdline_get_bool("foo_bar", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("foo-bar", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("bar-waldo", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("bar_waldo", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("x_y-z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("x-y-z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("x-y_z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("x_y_z", &value) > 0 && value == false); + assert_se(proc_cmdline_get_bool("quux", &value) == -EINVAL && value == false); + assert_se(proc_cmdline_get_bool("da", &value) > 0 && value == true); + assert_se(proc_cmdline_get_bool("the", &value) > 0 && value == true); +#endif +} + +static void test_proc_cmdline_get_key_many(void) { + _cleanup_free_ char *value1 = NULL, *value2 = NULL, *value3 = NULL, *value4 = NULL, *value5 = NULL, *value6 = NULL, *value7 = NULL; + + log_info("/* %s */", __func__); + assert_se(putenv((char*) "SYSTEMD_PROC_CMDLINE=foo_bar=quux wuff-piep=tuet zumm SPACE='one two' doubleticks=\" aaa aaa \"\n\nzummm='\n'\n") == 0); + + assert_se(proc_cmdline_get_key_many(0, + "wuff-piep", &value3, + "foo_bar", &value1, + "idontexist", &value2, + "zumm", &value4, + "SPACE", &value5, + "doubleticks", &value6, + "zummm", &value7) == 5); + + assert_se(streq_ptr(value1, "quux")); + assert_se(!value2); + assert_se(streq_ptr(value3, "tuet")); + assert_se(!value4); + assert_se(streq_ptr(value5, "one two")); + assert_se(streq_ptr(value6, " aaa aaa ")); + assert_se(streq_ptr(value7, "\n")); +} + +static void test_proc_cmdline_key_streq(void) { + log_info("/* %s */", __func__); + + assert_se(proc_cmdline_key_streq("", "")); + assert_se(proc_cmdline_key_streq("a", "a")); + assert_se(!proc_cmdline_key_streq("", "a")); + assert_se(!proc_cmdline_key_streq("a", "")); + assert_se(proc_cmdline_key_streq("a", "a")); + assert_se(!proc_cmdline_key_streq("a", "b")); + assert_se(proc_cmdline_key_streq("x-y-z", "x-y-z")); + assert_se(proc_cmdline_key_streq("x-y-z", "x_y_z")); + assert_se(proc_cmdline_key_streq("x-y-z", "x-y_z")); + assert_se(proc_cmdline_key_streq("x-y-z", "x_y-z")); + assert_se(proc_cmdline_key_streq("x_y-z", "x-y_z")); + assert_se(!proc_cmdline_key_streq("x_y-z", "x-z_z")); +} + +static void test_proc_cmdline_key_startswith(void) { + log_info("/* %s */", __func__); + + assert_se(proc_cmdline_key_startswith("", "")); + assert_se(proc_cmdline_key_startswith("x", "")); + assert_se(!proc_cmdline_key_startswith("", "x")); + assert_se(proc_cmdline_key_startswith("x", "x")); + assert_se(!proc_cmdline_key_startswith("x", "y")); + assert_se(!proc_cmdline_key_startswith("foo-bar", "quux")); + assert_se(proc_cmdline_key_startswith("foo-bar", "foo")); + assert_se(proc_cmdline_key_startswith("foo-bar", "foo-bar")); + assert_se(proc_cmdline_key_startswith("foo-bar", "foo_bar")); + assert_se(proc_cmdline_key_startswith("foo-bar", "foo_")); + assert_se(!proc_cmdline_key_startswith("foo-bar", "foo_xx")); +} + +int main(void) { + test_setup_logging(LOG_INFO); + + test_proc_cmdline_parse(); + test_proc_cmdline_override(); + test_proc_cmdline_given(false); + /* Repeat the same thing, but now flip our ininitrdness */ + test_proc_cmdline_given(true); + test_proc_cmdline_key_streq(); + test_proc_cmdline_key_startswith(); + test_proc_cmdline_get_key(); + test_proc_cmdline_get_bool(); + test_proc_cmdline_get_key_many(); + + return 0; +} diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c new file mode 100644 index 00000000..d0f126b2 --- /dev/null +++ b/src/test/test-process-util.c @@ -0,0 +1,632 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_VALGRIND_VALGRIND_H +#include +#endif + +#include "alloc-util.h" +#include "architecture.h" +#include "fd-util.h" +#include "log.h" +#include "macro.h" +#include "missing_sched.h" +#include "missing_syscall.h" +#include "parse-util.h" +#include "process-util.h" +#include "signal-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "terminal-util.h" +#include "tests.h" +#include "util.h" +#include "virt.h" + +static void test_get_process_comm(pid_t pid) { + struct stat st; + _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL; + _cleanup_free_ char *env = NULL; + char path[STRLEN("/proc//comm") + DECIMAL_STR_MAX(pid_t)]; + pid_t e; + uid_t u; + gid_t g; + dev_t h; + int r; + + xsprintf(path, "/proc/"PID_FMT"/comm", pid); + + if (stat(path, &st) == 0) { + assert_se(get_process_comm(pid, &a) >= 0); + log_info("PID"PID_FMT" comm: '%s'", pid, a); + } else + log_warning("%s not exist.", path); + + assert_se(get_process_cmdline(pid, 0, PROCESS_CMDLINE_COMM_FALLBACK, &c) >= 0); + log_info("PID"PID_FMT" cmdline: '%s'", pid, c); + + assert_se(get_process_cmdline(pid, 8, 0, &d) >= 0); + log_info("PID"PID_FMT" cmdline truncated to 8: '%s'", pid, d); + + free(d); + assert_se(get_process_cmdline(pid, 1, 0, &d) >= 0); + log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d); + + assert_se(get_process_ppid(pid, &e) >= 0); + log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e); + assert_se(pid == 1 ? e == 0 : e > 0); + + assert_se(is_kernel_thread(pid) == 0 || pid != 1); + + r = get_process_exe(pid, &f); + assert_se(r >= 0 || r == -EACCES); + log_info("PID"PID_FMT" exe: '%s'", pid, strna(f)); + + assert_se(get_process_uid(pid, &u) == 0); + log_info("PID"PID_FMT" UID: "UID_FMT, pid, u); + + assert_se(get_process_gid(pid, &g) == 0); + log_info("PID"PID_FMT" GID: "GID_FMT, pid, g); + + r = get_process_environ(pid, &env); + assert_se(r >= 0 || r == -EACCES); + log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno); + + if (!detect_container()) + assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1); + + (void) getenv_for_pid(pid, "PATH", &i); + log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i)); +} + +static void test_get_process_comm_escape_one(const char *input, const char *output) { + _cleanup_free_ char *n = NULL; + + log_info("input: <%s> — output: <%s>", input, output); + + assert_se(prctl(PR_SET_NAME, input) >= 0); + assert_se(get_process_comm(0, &n) >= 0); + + log_info("got: <%s>", n); + + assert_se(streq_ptr(n, output)); +} + +static void test_get_process_comm_escape(void) { + _cleanup_free_ char *saved = NULL; + + assert_se(get_process_comm(0, &saved) >= 0); + + test_get_process_comm_escape_one("", ""); + test_get_process_comm_escape_one("foo", "foo"); + test_get_process_comm_escape_one("012345678901234", "012345678901234"); + test_get_process_comm_escape_one("0123456789012345", "012345678901234"); + test_get_process_comm_escape_one("äöüß", "\\303\\244\\303\\266\\303\\274\\303\\237"); + test_get_process_comm_escape_one("xäöüß", "x\\303\\244\\303\\266\\303\\274\\303\\237"); + test_get_process_comm_escape_one("xxäöüß", "xx\\303\\244\\303\\266\\303\\274\\303\\237"); + test_get_process_comm_escape_one("xxxäöüß", "xxx\\303\\244\\303\\266\\303\\274\\303\\237"); + test_get_process_comm_escape_one("xxxxäöüß", "xxxx\\303\\244\\303\\266\\303\\274\\303\\237"); + test_get_process_comm_escape_one("xxxxxäöüß", "xxxxx\\303\\244\\303\\266\\303\\274\\303\\237"); + + assert_se(prctl(PR_SET_NAME, saved) >= 0); +} + +static void test_pid_is_unwaited(void) { + pid_t pid; + + pid = fork(); + assert_se(pid >= 0); + if (pid == 0) { + _exit(EXIT_SUCCESS); + } else { + int status; + + waitpid(pid, &status, 0); + assert_se(!pid_is_unwaited(pid)); + } + assert_se(pid_is_unwaited(getpid_cached())); + assert_se(!pid_is_unwaited(-1)); +} + +static void test_pid_is_alive(void) { + pid_t pid; + + pid = fork(); + assert_se(pid >= 0); + if (pid == 0) { + _exit(EXIT_SUCCESS); + } else { + int status; + + waitpid(pid, &status, 0); + assert_se(!pid_is_alive(pid)); + } + assert_se(pid_is_alive(getpid_cached())); + assert_se(!pid_is_alive(-1)); +} + +static void test_personality(void) { + + assert_se(personality_to_string(PER_LINUX)); + assert_se(!personality_to_string(PERSONALITY_INVALID)); + + assert_se(streq(personality_to_string(PER_LINUX), architecture_to_string(native_architecture()))); + + assert_se(personality_from_string(personality_to_string(PER_LINUX)) == PER_LINUX); + assert_se(personality_from_string(architecture_to_string(native_architecture())) == PER_LINUX); + +#ifdef __x86_64__ + assert_se(streq_ptr(personality_to_string(PER_LINUX), "x86-64")); + assert_se(streq_ptr(personality_to_string(PER_LINUX32), "x86")); + + assert_se(personality_from_string("x86-64") == PER_LINUX); + assert_se(personality_from_string("x86") == PER_LINUX32); + assert_se(personality_from_string("ia64") == PERSONALITY_INVALID); + assert_se(personality_from_string(NULL) == PERSONALITY_INVALID); + + assert_se(personality_from_string(personality_to_string(PER_LINUX32)) == PER_LINUX32); +#endif +} + +static void test_get_process_cmdline_harder(void) { + char path[] = "/tmp/test-cmdlineXXXXXX"; + _cleanup_close_ int fd = -1; + _cleanup_free_ char *line = NULL; + pid_t pid; + + if (geteuid() != 0) { + log_info("Skipping %s: not root", __func__); + return; + } + + if (!have_namespaces()) { + log_notice("Testing without namespaces, skipping %s", __func__); + return; + } + +#if HAVE_VALGRIND_VALGRIND_H + /* valgrind patches open(/proc//cmdline) + * so, test_get_process_cmdline_harder fails always + * See https://github.com/systemd/systemd/pull/3555#issuecomment-226564908 */ + if (RUNNING_ON_VALGRIND) { + log_info("Skipping %s: running on valgrind", __func__); + return; + } +#endif + + pid = fork(); + if (pid > 0) { + siginfo_t si; + + (void) wait_for_terminate(pid, &si); + + assert_se(si.si_code == CLD_EXITED); + assert_se(si.si_status == 0); + + return; + } + + assert_se(pid == 0); + assert_se(unshare(CLONE_NEWNS) >= 0); + + if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) { + log_warning_errno(errno, "mount(..., \"/\", MS_SLAVE|MS_REC, ...) failed: %m"); + assert_se(IN_SET(errno, EPERM, EACCES)); + return; + } + + fd = mkostemp(path, O_CLOEXEC); + assert_se(fd >= 0); + + /* Note that we don't unmount the following bind-mount at the end of the test because the kernel + * will clear up its /proc/PID/ hierarchy automatically as soon as the test stops. */ + if (mount(path, "/proc/self/cmdline", "bind", MS_BIND, NULL) < 0) { + /* This happens under selinux… Abort the test in this case. */ + log_warning_errno(errno, "mount(..., \"/proc/self/cmdline\", \"bind\", ...) failed: %m"); + assert_se(IN_SET(errno, EPERM, EACCES)); + return; + } + + assert_se(unlink(path) >= 0); + + assert_se(prctl(PR_SET_NAME, "testa") >= 0); + + assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) == -ENOENT); + + assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[testa]")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 0, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + log_info("'%s'", line); + assert_se(streq(line, "")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[t…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[te…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[tes…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[test…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[testa]")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[testa]")); + line = mfree(line); + + assert_se(write(fd, "foo\0bar", 8) == 8); + + assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) >= 0); + log_info("'%s'", line); + assert_se(streq(line, "foo bar")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo bar")); + line = mfree(line); + + assert_se(write(fd, "quux", 4) == 4); + assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) >= 0); + log_info("'%s'", line); + assert_se(streq(line, "foo bar quux")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo bar quux")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 1, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 2, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "f…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 3, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "fo…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 4, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 5, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo …")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 6, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo b…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 7, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo ba…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 8, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo bar…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 9, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo bar …")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo bar q…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo bar qu…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo bar quux")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 13, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo bar quux")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 14, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo bar quux")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 1000, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "foo bar quux")); + line = mfree(line); + + assert_se(ftruncate(fd, 0) >= 0); + assert_se(prctl(PR_SET_NAME, "aaaa bbbb cccc") >= 0); + + assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, 0, &line) == -ENOENT); + + assert_se(get_process_cmdline(getpid_cached(), SIZE_MAX, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[aaaa bbbb cccc]")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 10, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[aaaa bbb…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 11, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[aaaa bbbb…")); + line = mfree(line); + + assert_se(get_process_cmdline(getpid_cached(), 12, PROCESS_CMDLINE_COMM_FALLBACK, &line) >= 0); + assert_se(streq(line, "[aaaa bbbb …")); + line = mfree(line); + + safe_close(fd); + _exit(EXIT_SUCCESS); +} + +static void test_rename_process_now(const char *p, int ret) { + _cleanup_free_ char *comm = NULL, *cmdline = NULL; + int r; + + r = rename_process(p); + assert_se(r == ret || + (ret == 0 && r >= 0) || + (ret > 0 && r > 0)); + + if (r < 0) + return; + +#if HAVE_VALGRIND_VALGRIND_H + /* see above, valgrind is weird, we can't verify what we are doing here */ + if (RUNNING_ON_VALGRIND) + return; +#endif + + assert_se(get_process_comm(0, &comm) >= 0); + log_info("comm = <%s>", comm); + assert_se(strneq(comm, p, TASK_COMM_LEN-1)); + /* We expect comm to be at most 16 bytes (TASK_COMM_LEN). The kernel may raise this limit in the + * future. We'd only check the initial part, at least until we recompile, but this will still pass. */ + + r = get_process_cmdline(0, SIZE_MAX, 0, &cmdline); + assert_se(r >= 0); + /* we cannot expect cmdline to be renamed properly without privileges */ + if (geteuid() == 0) { + if (r == 0 && detect_container() > 0) + log_info("cmdline = <%s> (not verified, Running in unprivileged container?)", cmdline); + else { + log_info("cmdline = <%s>", cmdline); + assert_se(strneq(p, cmdline, STRLEN("test-process-util"))); + assert_se(startswith(p, cmdline)); + } + } else + log_info("cmdline = <%s> (not verified)", cmdline); +} + +static void test_rename_process_one(const char *p, int ret) { + siginfo_t si; + pid_t pid; + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + /* child */ + test_rename_process_now(p, ret); + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate(pid, &si) >= 0); + assert_se(si.si_code == CLD_EXITED); + assert_se(si.si_status == EXIT_SUCCESS); +} + +static void test_rename_process_multi(void) { + pid_t pid; + + pid = fork(); + assert_se(pid >= 0); + + if (pid > 0) { + siginfo_t si; + + assert_se(wait_for_terminate(pid, &si) >= 0); + assert_se(si.si_code == CLD_EXITED); + assert_se(si.si_status == EXIT_SUCCESS); + + return; + } + + /* child */ + test_rename_process_now("one", 1); + test_rename_process_now("more", 0); /* longer than "one", hence truncated */ + (void) setresuid(99, 99, 99); /* change uid when running privileged */ + test_rename_process_now("time!", 0); + test_rename_process_now("0", 1); /* shorter than "one", should fit */ + test_rename_process_one("", -EINVAL); + test_rename_process_one(NULL, -EINVAL); + _exit(EXIT_SUCCESS); +} + +static void test_rename_process(void) { + test_rename_process_one(NULL, -EINVAL); + test_rename_process_one("", -EINVAL); + test_rename_process_one("foo", 1); /* should always fit */ + test_rename_process_one("this is a really really long process name, followed by some more words", 0); /* unlikely to fit */ + test_rename_process_one("1234567", 1); /* should always fit */ + test_rename_process_multi(); /* multiple invocations and dropped privileges */ +} + +static void test_getpid_cached(void) { + siginfo_t si; + pid_t a, b, c, d, e, f, child; + + a = raw_getpid(); + b = getpid_cached(); + c = getpid(); + + assert_se(a == b && a == c); + + child = fork(); + assert_se(child >= 0); + + if (child == 0) { + /* In child */ + a = raw_getpid(); + b = getpid_cached(); + c = getpid(); + + assert_se(a == b && a == c); + _exit(EXIT_SUCCESS); + } + + d = raw_getpid(); + e = getpid_cached(); + f = getpid(); + + assert_se(a == d && a == e && a == f); + + assert_se(wait_for_terminate(child, &si) >= 0); + assert_se(si.si_status == 0); + assert_se(si.si_code == CLD_EXITED); +} + +#define MEASURE_ITERATIONS (10000000LLU) + +static void test_getpid_measure(void) { + unsigned long long i; + usec_t t, q; + + t = now(CLOCK_MONOTONIC); + for (i = 0; i < MEASURE_ITERATIONS; i++) + (void) getpid(); + q = now(CLOCK_MONOTONIC) - t; + + log_info(" glibc getpid(): %lf µs each\n", (double) q / MEASURE_ITERATIONS); + + t = now(CLOCK_MONOTONIC); + for (i = 0; i < MEASURE_ITERATIONS; i++) + (void) getpid_cached(); + q = now(CLOCK_MONOTONIC) - t; + + log_info("getpid_cached(): %lf µs each\n", (double) q / MEASURE_ITERATIONS); +} + +static void test_safe_fork(void) { + siginfo_t status; + pid_t pid; + int r; + + BLOCK_SIGNALS(SIGCHLD); + + r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_REOPEN_LOG, &pid); + assert_se(r >= 0); + + if (r == 0) { + /* child */ + usleep(100 * USEC_PER_MSEC); + + _exit(88); + } + + assert_se(wait_for_terminate(pid, &status) >= 0); + assert_se(status.si_code == CLD_EXITED); + assert_se(status.si_status == 88); +} + +static void test_pid_to_ptr(void) { + + assert_se(PTR_TO_PID(NULL) == 0); + assert_se(PID_TO_PTR(0) == NULL); + + assert_se(PTR_TO_PID(PID_TO_PTR(1)) == 1); + assert_se(PTR_TO_PID(PID_TO_PTR(2)) == 2); + assert_se(PTR_TO_PID(PID_TO_PTR(-1)) == -1); + assert_se(PTR_TO_PID(PID_TO_PTR(-2)) == -2); + + assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MAX)) == INT16_MAX); + assert_se(PTR_TO_PID(PID_TO_PTR(INT16_MIN)) == INT16_MIN); + +#if SIZEOF_PID_T >= 4 + assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MAX)) == INT32_MAX); + assert_se(PTR_TO_PID(PID_TO_PTR(INT32_MIN)) == INT32_MIN); +#endif +} + +static void test_ioprio_class_from_to_string_one(const char *val, int expected) { + assert_se(ioprio_class_from_string(val) == expected); + if (expected >= 0) { + _cleanup_free_ char *s = NULL; + unsigned ret; + + assert_se(ioprio_class_to_string_alloc(expected, &s) == 0); + /* We sometimes get a class number and sometimes a number back */ + assert_se(streq(s, val) || + safe_atou(val, &ret) == 0); + } +} + +static void test_ioprio_class_from_to_string(void) { + test_ioprio_class_from_to_string_one("none", IOPRIO_CLASS_NONE); + test_ioprio_class_from_to_string_one("realtime", IOPRIO_CLASS_RT); + test_ioprio_class_from_to_string_one("best-effort", IOPRIO_CLASS_BE); + test_ioprio_class_from_to_string_one("idle", IOPRIO_CLASS_IDLE); + test_ioprio_class_from_to_string_one("0", 0); + test_ioprio_class_from_to_string_one("1", 1); + test_ioprio_class_from_to_string_one("7", 7); + test_ioprio_class_from_to_string_one("8", 8); + test_ioprio_class_from_to_string_one("9", -1); + test_ioprio_class_from_to_string_one("-1", -1); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + save_argc_argv(argc, argv); + + if (argc > 1) { + pid_t pid = 0; + + (void) parse_pid(argv[1], &pid); + test_get_process_comm(pid); + } else { + TEST_REQ_RUNNING_SYSTEMD(test_get_process_comm(1)); + test_get_process_comm(getpid()); + } + + test_get_process_comm_escape(); + test_pid_is_unwaited(); + test_pid_is_alive(); + test_personality(); + test_get_process_cmdline_harder(); + test_rename_process(); + test_getpid_cached(); + test_getpid_measure(); + test_safe_fork(); + test_pid_to_ptr(); + test_ioprio_class_from_to_string(); + + return 0; +} diff --git a/src/test/test-procfs-util.c b/src/test/test-procfs-util.c new file mode 100644 index 00000000..662688e0 --- /dev/null +++ b/src/test/test-procfs-util.c @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "format-util.h" +#include "log.h" +#include "procfs-util.h" + +int main(int argc, char *argv[]) { + char buf[CONST_MAX(FORMAT_TIMESPAN_MAX, FORMAT_BYTES_MAX)]; + nsec_t nsec; + uint64_t v; + int r; + + log_parse_environment(); + log_open(); + + assert_se(procfs_cpu_get_usage(&nsec) >= 0); + log_info("Current system CPU time: %s", format_timespan(buf, sizeof(buf), nsec/NSEC_PER_USEC, 1)); + + assert_se(procfs_memory_get_used(&v) >= 0); + log_info("Current memory usage: %s", format_bytes(buf, sizeof(buf), v)); + + assert_se(procfs_tasks_get_current(&v) >= 0); + log_info("Current number of tasks: %" PRIu64, v); + + assert_se(procfs_tasks_get_limit(&v) >= 0); + log_info("Limit of tasks: %" PRIu64, v); + assert_se(v > 0); + assert_se(procfs_tasks_set_limit(v) >= 0); + + if (v > 100) { + uint64_t w; + r = procfs_tasks_set_limit(v-1); + assert_se(IN_SET(r, 0, -EPERM, -EACCES, -EROFS)); + + assert_se(procfs_tasks_get_limit(&w) >= 0); + assert_se((r == 0 && w == v - 1) || (r < 0 && w == v)); + + assert_se(procfs_tasks_set_limit(v) >= 0); + + assert_se(procfs_tasks_get_limit(&w) >= 0); + assert_se(v == w); + } + + return 0; +} diff --git a/src/test/test-random-util.c b/src/test/test-random-util.c new file mode 100644 index 00000000..94c431f7 --- /dev/null +++ b/src/test/test-random-util.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "hexdecoct.h" +#include "random-util.h" +#include "log.h" +#include "tests.h" + +static void test_genuine_random_bytes(RandomFlags flags) { + uint8_t buf[16] = {}; + unsigned i; + + log_info("/* %s */", __func__); + + for (i = 1; i < sizeof buf; i++) { + assert_se(genuine_random_bytes(buf, i, flags) == 0); + if (i + 1 < sizeof buf) + assert_se(buf[i] == 0); + + hexdump(stdout, buf, i); + } +} + +static void test_pseudo_random_bytes(void) { + uint8_t buf[16] = {}; + unsigned i; + + log_info("/* %s */", __func__); + + for (i = 1; i < sizeof buf; i++) { + pseudo_random_bytes(buf, i); + if (i + 1 < sizeof buf) + assert_se(buf[i] == 0); + + hexdump(stdout, buf, i); + } +} + +static void test_rdrand(void) { + int r, i; + + for (i = 0; i < 10; i++) { + unsigned long x = 0; + + r = rdrand(&x); + if (r < 0) { + log_error_errno(r, "RDRAND failed: %m"); + return; + } + + printf("%lx\n", x); + } +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_genuine_random_bytes(RANDOM_EXTEND_WITH_PSEUDO); + test_genuine_random_bytes(0); + test_genuine_random_bytes(RANDOM_BLOCK); + test_genuine_random_bytes(RANDOM_ALLOW_RDRAND); + + test_pseudo_random_bytes(); + + test_rdrand(); + + return 0; +} diff --git a/src/test/test-ratelimit.c b/src/test/test-ratelimit.c new file mode 100644 index 00000000..56a6fa2d --- /dev/null +++ b/src/test/test-ratelimit.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "macro.h" +#include "ratelimit.h" +#include "time-util.h" + +static void test_ratelimit_below(void) { + int i; + RateLimit ratelimit = { 1 * USEC_PER_SEC, 10 }; + + for (i = 0; i < 10; i++) + assert_se(ratelimit_below(&ratelimit)); + assert_se(!ratelimit_below(&ratelimit)); + sleep(1); + for (i = 0; i < 10; i++) + assert_se(ratelimit_below(&ratelimit)); + + ratelimit = (RateLimit) { 0, 10 }; + for (i = 0; i < 10000; i++) + assert_se(ratelimit_below(&ratelimit)); +} + +int main(int argc, char *argv[]) { + test_ratelimit_below(); + + return 0; +} diff --git a/src/test/test-replace-var.c b/src/test/test-replace-var.c new file mode 100644 index 00000000..8620e72b --- /dev/null +++ b/src/test/test-replace-var.c @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "macro.h" +#include "replace-var.h" +#include "string-util.h" + +static char *lookup(const char *variable, void *userdata) { + return strjoin("<<<", variable, ">>>"); +} + +int main(int argc, char *argv[]) { + char *r; + + assert_se(r = replace_var("@@@foobar@xyz@HALLO@foobar@test@@testtest@TEST@...@@@", lookup, NULL)); + puts(r); + assert_se(streq(r, "@@@foobar@xyz<<>>foobar@test@@testtest<<>>...@@@")); + free(r); + + assert_se(r = strreplace("XYZFFFFXYZFFFFXYZ", "XYZ", "ABC")); + puts(r); + assert_se(streq(r, "ABCFFFFABCFFFFABC")); + free(r); + + return 0; +} diff --git a/src/test/test-rlimit-util.c b/src/test/test-rlimit-util.c new file mode 100644 index 00000000..90eda96a --- /dev/null +++ b/src/test/test-rlimit-util.c @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "capability-util.h" +#include "macro.h" +#include "missing_resource.h" +#include "rlimit-util.h" +#include "string-util.h" +#include "time-util.h" + +static void test_rlimit_parse_format(int resource, const char *string, rlim_t soft, rlim_t hard, int ret, const char *formatted) { + _cleanup_free_ char *f = NULL; + struct rlimit rl = { + .rlim_cur = 4711, + .rlim_max = 4712, + }, rl2 = { + .rlim_cur = 4713, + .rlim_max = 4714 + }; + + assert_se(rlimit_parse(resource, string, &rl) == ret); + if (ret < 0) + return; + + assert_se(rl.rlim_cur == soft); + assert_se(rl.rlim_max == hard); + + assert_se(rlimit_format(&rl, &f) >= 0); + assert_se(streq(formatted, f)); + + assert_se(rlimit_parse(resource, formatted, &rl2) >= 0); + assert_se(memcmp(&rl, &rl2, sizeof(struct rlimit)) == 0); +} + +int main(int argc, char *argv[]) { + struct rlimit old, new, high; + struct rlimit err = { + .rlim_cur = 10, + .rlim_max = 5, + }; + int i; + + log_parse_environment(); + log_open(); + + assert_se(drop_capability(CAP_SYS_RESOURCE) == 0); + + assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0); + new.rlim_cur = MIN(5U, old.rlim_max); + new.rlim_max = old.rlim_max; + assert_se(setrlimit(RLIMIT_NOFILE, &new) >= 0); + + assert_se(rlimit_from_string("NOFILE") == RLIMIT_NOFILE); + assert_se(rlimit_from_string("LimitNOFILE") == -1); + assert_se(rlimit_from_string("RLIMIT_NOFILE") == -1); + assert_se(rlimit_from_string("xxxNOFILE") == -1); + assert_se(rlimit_from_string("DefaultLimitNOFILE") == -1); + + assert_se(rlimit_from_string_harder("NOFILE") == RLIMIT_NOFILE); + assert_se(rlimit_from_string_harder("LimitNOFILE") == RLIMIT_NOFILE); + assert_se(rlimit_from_string_harder("RLIMIT_NOFILE") == RLIMIT_NOFILE); + assert_se(rlimit_from_string_harder("xxxNOFILE") == -1); + assert_se(rlimit_from_string_harder("DefaultLimitNOFILE") == -1); + + for (i = 0; i < _RLIMIT_MAX; i++) { + _cleanup_free_ char *prefixed = NULL; + const char *p; + + assert_se(p = rlimit_to_string(i)); + log_info("%i = %s", i, p); + + assert_se(rlimit_from_string(p) == i); + assert_se(rlimit_from_string_harder(p) == i); + + assert_se(prefixed = strjoin("Limit", p)); + + assert_se(rlimit_from_string(prefixed) < 0); + assert_se(rlimit_from_string_harder(prefixed) == i); + + prefixed = mfree(prefixed); + assert_se(prefixed = strjoin("RLIMIT_", p)); + + assert_se(rlimit_from_string(prefixed) < 0); + assert_se(rlimit_from_string_harder(prefixed) == i); + } + + assert_se(streq_ptr(rlimit_to_string(RLIMIT_NOFILE), "NOFILE")); + assert_se(rlimit_to_string(-1) == NULL); + + assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0); + assert_se(setrlimit_closest(RLIMIT_NOFILE, &old) == 0); + assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0); + assert_se(old.rlim_cur == new.rlim_cur); + assert_se(old.rlim_max == new.rlim_max); + + assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0); + high = RLIMIT_MAKE_CONST(old.rlim_max == RLIM_INFINITY ? old.rlim_max : old.rlim_max + 1); + assert_se(setrlimit_closest(RLIMIT_NOFILE, &high) == 0); + assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0); + assert_se(new.rlim_max == old.rlim_max); + assert_se(new.rlim_cur == new.rlim_max); + + assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0); + assert_se(setrlimit_closest(RLIMIT_NOFILE, &err) == -EINVAL); + assert_se(getrlimit(RLIMIT_NOFILE, &new) == 0); + assert_se(old.rlim_cur == new.rlim_cur); + assert_se(old.rlim_max == new.rlim_max); + + test_rlimit_parse_format(RLIMIT_NOFILE, "4:5", 4, 5, 0, "4:5"); + test_rlimit_parse_format(RLIMIT_NOFILE, "6", 6, 6, 0, "6"); + test_rlimit_parse_format(RLIMIT_NOFILE, "infinity", RLIM_INFINITY, RLIM_INFINITY, 0, "infinity"); + test_rlimit_parse_format(RLIMIT_NOFILE, "infinity:infinity", RLIM_INFINITY, RLIM_INFINITY, 0, "infinity"); + test_rlimit_parse_format(RLIMIT_NOFILE, "8:infinity", 8, RLIM_INFINITY, 0, "8:infinity"); + test_rlimit_parse_format(RLIMIT_CPU, "25min:13h", (25*USEC_PER_MINUTE) / USEC_PER_SEC, (13*USEC_PER_HOUR) / USEC_PER_SEC, 0, "1500:46800"); + test_rlimit_parse_format(RLIMIT_NOFILE, "", 0, 0, -EINVAL, NULL); + test_rlimit_parse_format(RLIMIT_NOFILE, "5:4", 0, 0, -EILSEQ, NULL); + test_rlimit_parse_format(RLIMIT_NOFILE, "5:4:3", 0, 0, -EINVAL, NULL); + test_rlimit_parse_format(RLIMIT_NICE, "20", 20, 20, 0, "20"); + test_rlimit_parse_format(RLIMIT_NICE, "40", 40, 40, 0, "40"); + test_rlimit_parse_format(RLIMIT_NICE, "41", 41, 41, -ERANGE, "41"); + test_rlimit_parse_format(RLIMIT_NICE, "0", 0, 0, 0, "0"); + test_rlimit_parse_format(RLIMIT_NICE, "-7", 27, 27, 0, "27"); + test_rlimit_parse_format(RLIMIT_NICE, "-20", 40, 40, 0, "40"); + test_rlimit_parse_format(RLIMIT_NICE, "-21", 41, 41, -ERANGE, "41"); + test_rlimit_parse_format(RLIMIT_NICE, "-0", 20, 20, 0, "20"); + test_rlimit_parse_format(RLIMIT_NICE, "+7", 13, 13, 0, "13"); + test_rlimit_parse_format(RLIMIT_NICE, "+19", 1, 1, 0, "1"); + test_rlimit_parse_format(RLIMIT_NICE, "+20", 0, 0, -ERANGE, "0"); + test_rlimit_parse_format(RLIMIT_NICE, "+0", 20, 20, 0, "20"); + + return 0; +} diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c new file mode 100644 index 00000000..cd455378 --- /dev/null +++ b/src/test/test-sched-prio.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2012 Holger Hans Peter Freyther +***/ + +#include + +#include "all-units.h" +#include "macro.h" +#include "manager.h" +#include "rm-rf.h" +#include "tests.h" + +int main(int argc, char *argv[]) { + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + Unit *idle_ok, *idle_bad, *rr_ok, *rr_bad, *rr_sched; + Service *ser; + int r; + + test_setup_logging(LOG_INFO); + + r = enter_cgroup_subroot(NULL); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + /* prepare the test */ + assert_se(set_unit_path(get_testdata_dir()) >= 0); + assert_se(runtime_dir = setup_fake_runtime_dir()); + r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m); + if (manager_errno_skip_test(r)) + return log_tests_skipped_errno(r, "manager_new"); + assert_se(r >= 0); + assert_se(manager_startup(m, NULL, NULL) >= 0); + + /* load idle ok */ + assert_se(manager_load_startable_unit_or_warn(m, "sched_idle_ok.service", NULL, &idle_ok) >= 0); + ser = SERVICE(idle_ok); + assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER); + assert_se(ser->exec_context.cpu_sched_priority == 0); + + /* + * load idle bad. This should print a warning but we have no way to look at it. + */ + assert_se(manager_load_startable_unit_or_warn(m, "sched_idle_bad.service", NULL, &idle_bad) >= 0); + ser = SERVICE(idle_ok); + assert_se(ser->exec_context.cpu_sched_policy == SCHED_OTHER); + assert_se(ser->exec_context.cpu_sched_priority == 0); + + /* + * load rr ok. + * Test that the default priority is moving from 0 to 1. + */ + assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_ok.service", NULL, &rr_ok) >= 0); + ser = SERVICE(rr_ok); + assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); + assert_se(ser->exec_context.cpu_sched_priority == 1); + + /* + * load rr bad. + * Test that the value of 0 and 100 is ignored. + */ + assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_bad.service", NULL, &rr_bad) >= 0); + ser = SERVICE(rr_bad); + assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); + assert_se(ser->exec_context.cpu_sched_priority == 1); + + /* + * load rr change. + * Test that anything between 1 and 99 can be set. + */ + assert_se(manager_load_startable_unit_or_warn(m, "sched_rr_change.service", NULL, &rr_sched) >= 0); + ser = SERVICE(rr_sched); + assert_se(ser->exec_context.cpu_sched_policy == SCHED_RR); + assert_se(ser->exec_context.cpu_sched_priority == 99); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-sd-hwdb.c b/src/test/test-sd-hwdb.c new file mode 100644 index 00000000..17ca6a0e --- /dev/null +++ b/src/test/test-sd-hwdb.c @@ -0,0 +1,74 @@ +#include "sd-hwdb.h" + +#include "alloc-util.h" +#include "errno.h" +#include "tests.h" + +static int test_failed_enumerate(void) { + _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; + const char *key, *value; + int r; + + log_info("/* %s */", __func__); + + r = sd_hwdb_new(&hwdb); + if (r == -ENOENT) + return r; + assert_se(r == 0); + + assert_se(sd_hwdb_seek(hwdb, "no-such-modalias-should-exist") == 0); + + assert_se(sd_hwdb_enumerate(hwdb, &key, &value) == 0); + assert_se(sd_hwdb_enumerate(hwdb, &key, NULL) == -EINVAL); + assert_se(sd_hwdb_enumerate(hwdb, NULL, &value) == -EINVAL); + + return 0; +} + +#define DELL_MODALIAS \ + "evdev:atkbd:dmi:bvnXXX:bvrYYY:bdZZZ:svnDellXXX:pnYYY" + +static void test_basic_enumerate(void) { + _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; + const char *key, *value; + size_t len1 = 0, len2 = 0; + int r; + + log_info("/* %s */", __func__); + + assert_se(sd_hwdb_new(&hwdb) == 0); + + assert_se(sd_hwdb_seek(hwdb, DELL_MODALIAS) == 0); + + for (;;) { + r = sd_hwdb_enumerate(hwdb, &key, &value); + assert(IN_SET(r, 0, 1)); + if (r == 0) + break; + assert(key); + assert(value); + log_debug("A: \"%s\" → \"%s\"", key, value); + len1 += strlen(key) + strlen(value); + } + + SD_HWDB_FOREACH_PROPERTY(hwdb, DELL_MODALIAS, key, value) { + log_debug("B: \"%s\" → \"%s\"", key, value); + len2 += strlen(key) + strlen(value); + } + + assert_se(len1 == len2); +} + +int main(int argc, char *argv[]) { + int r; + + test_setup_logging(LOG_DEBUG); + + r = test_failed_enumerate(); + if (r < 0) + return log_tests_skipped_errno(r, "cannot open hwdb"); + + test_basic_enumerate(); + + return 0; +} diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c new file mode 100644 index 00000000..75566199 --- /dev/null +++ b/src/test/test-seccomp.c @@ -0,0 +1,1040 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "macro.h" +#include "memory-util.h" +#include "missing_sched.h" +#include "nsflags.h" +#include "nulstr-util.h" +#include "process-util.h" +#include "raw-clone.h" +#include "rm-rf.h" +#include "seccomp-util.h" +#include "set.h" +#include "string-util.h" +#include "tests.h" +#include "tmpfile-util.h" +#include "virt.h" + +/* __NR_socket may be invalid due to libseccomp */ +#if !defined(__NR_socket) || __NR_socket < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__) +/* On these archs, socket() is implemented via the socketcall() syscall multiplexer, + * and we can't restrict it hence via seccomp. */ +# define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1 +#else +# define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 0 +#endif + +static void test_seccomp_arch_to_string(void) { + uint32_t a, b; + const char *name; + + log_info("/* %s */", __func__); + + a = seccomp_arch_native(); + assert_se(a > 0); + name = seccomp_arch_to_string(a); + assert_se(name); + assert_se(seccomp_arch_from_string(name, &b) >= 0); + assert_se(a == b); +} + +static void test_architecture_table(void) { + const char *n, *n2; + + log_info("/* %s */", __func__); + + NULSTR_FOREACH(n, + "native\0" + "x86\0" + "x86-64\0" + "x32\0" + "arm\0" + "arm64\0" + "mips\0" + "mips64\0" + "mips64-n32\0" + "mips-le\0" + "mips64-le\0" + "mips64-le-n32\0" + "ppc\0" + "ppc64\0" + "ppc64-le\0" + "s390\0" + "s390x\0") { + uint32_t c; + + assert_se(seccomp_arch_from_string(n, &c) >= 0); + n2 = seccomp_arch_to_string(c); + log_info("seccomp-arch: %s → 0x%"PRIx32" → %s", n, c, n2); + assert_se(streq_ptr(n, n2)); + } +} + +static void test_syscall_filter_set_find(void) { + log_info("/* %s */", __func__); + + assert_se(!syscall_filter_set_find(NULL)); + assert_se(!syscall_filter_set_find("")); + assert_se(!syscall_filter_set_find("quux")); + assert_se(!syscall_filter_set_find("@quux")); + + assert_se(syscall_filter_set_find("@clock") == syscall_filter_sets + SYSCALL_FILTER_SET_CLOCK); + assert_se(syscall_filter_set_find("@default") == syscall_filter_sets + SYSCALL_FILTER_SET_DEFAULT); + assert_se(syscall_filter_set_find("@raw-io") == syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO); +} + +static void test_filter_sets(void) { + unsigned i; + int r; + + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { + pid_t pid; + + log_info("Testing %s", syscall_filter_sets[i].name); + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { /* Child? */ + int fd; + + /* If we look at the default set (or one that includes it), whitelist instead of blacklist */ + if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_SYSTEM_SERVICE)) + r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW, true); + else + r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN), true); + if (r < 0) + _exit(EXIT_FAILURE); + + /* Test the sycall filter with one random system call */ + fd = eventfd(0, EFD_NONBLOCK|EFD_CLOEXEC); + if (IN_SET(i, SYSCALL_FILTER_SET_IO_EVENT, SYSCALL_FILTER_SET_DEFAULT)) + assert_se(fd < 0 && errno == EUCLEAN); + else { + assert_se(fd >= 0); + safe_close(fd); + } + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check(syscall_filter_sets[i].name, pid, WAIT_LOG) == EXIT_SUCCESS); + } +} + +static void test_filter_sets_ordered(void) { + size_t i; + + log_info("/* %s */", __func__); + + /* Ensure "@default" always remains at the beginning of the list */ + assert_se(SYSCALL_FILTER_SET_DEFAULT == 0); + assert_se(streq(syscall_filter_sets[0].name, "@default")); + + for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { + const char *k, *p = NULL; + + /* Make sure each group has a description */ + assert_se(!isempty(syscall_filter_sets[0].help)); + + /* Make sure the groups are ordered alphabetically, except for the first entry */ + assert_se(i < 2 || strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0); + + NULSTR_FOREACH(k, syscall_filter_sets[i].value) { + + /* Ensure each syscall list is in itself ordered, but groups before names */ + assert_se(!p || + (*p == '@' && *k != '@') || + (((*p == '@' && *k == '@') || + (*p != '@' && *k != '@')) && + strcmp(p, k) < 0)); + + p = k; + } + } +} + +static void test_restrict_namespace(void) { + char *s = NULL; + unsigned long ul; + pid_t pid; + + if (!have_namespaces()) { + log_notice("Testing without namespaces, skipping %s", __func__); + return; + } + + log_info("/* %s */", __func__); + + assert_se(namespace_flags_to_string(0, &s) == 0 && streq(s, "")); + s = mfree(s); + assert_se(namespace_flags_to_string(CLONE_NEWNS, &s) == 0 && streq(s, "mnt")); + s = mfree(s); + assert_se(namespace_flags_to_string(CLONE_NEWNS|CLONE_NEWIPC, &s) == 0 && streq(s, "ipc mnt")); + s = mfree(s); + assert_se(namespace_flags_to_string(CLONE_NEWCGROUP, &s) == 0 && streq(s, "cgroup")); + s = mfree(s); + + assert_se(namespace_flags_from_string("mnt", &ul) == 0 && ul == CLONE_NEWNS); + assert_se(namespace_flags_from_string(NULL, &ul) == 0 && ul == 0); + assert_se(namespace_flags_from_string("", &ul) == 0 && ul == 0); + assert_se(namespace_flags_from_string("uts", &ul) == 0 && ul == CLONE_NEWUTS); + assert_se(namespace_flags_from_string("mnt uts ipc", &ul) == 0 && ul == (CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC)); + + assert_se(namespace_flags_to_string(CLONE_NEWUTS, &s) == 0 && streq(s, "uts")); + assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == CLONE_NEWUTS); + s = mfree(s); + assert_se(namespace_flags_from_string("ipc", &ul) == 0 && ul == CLONE_NEWIPC); + assert_se(namespace_flags_to_string(ul, &s) == 0 && streq(s, "ipc")); + s = mfree(s); + + assert_se(namespace_flags_to_string(NAMESPACE_FLAGS_ALL, &s) == 0); + assert_se(streq(s, "cgroup ipc net mnt pid user uts")); + assert_se(namespace_flags_from_string(s, &ul) == 0 && ul == NAMESPACE_FLAGS_ALL); + s = mfree(s); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping remaining tests in %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping remaining tests in %s", __func__); + return; + } + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + + assert_se(seccomp_restrict_namespaces(CLONE_NEWNS|CLONE_NEWNET) >= 0); + + assert_se(unshare(CLONE_NEWNS) == 0); + assert_se(unshare(CLONE_NEWNET) == 0); + assert_se(unshare(CLONE_NEWUTS) == -1); + assert_se(errno == EPERM); + assert_se(unshare(CLONE_NEWIPC) == -1); + assert_se(errno == EPERM); + assert_se(unshare(CLONE_NEWNET|CLONE_NEWUTS) == -1); + assert_se(errno == EPERM); + + /* We use fd 0 (stdin) here, which of course will fail with EINVAL on setns(). Except of course our + * seccomp filter worked, and hits first and makes it return EPERM */ + assert_se(setns(0, CLONE_NEWNS) == -1); + assert_se(errno == EINVAL); + assert_se(setns(0, CLONE_NEWNET) == -1); + assert_se(errno == EINVAL); + assert_se(setns(0, CLONE_NEWUTS) == -1); + assert_se(errno == EPERM); + assert_se(setns(0, CLONE_NEWIPC) == -1); + assert_se(errno == EPERM); + assert_se(setns(0, CLONE_NEWNET|CLONE_NEWUTS) == -1); + assert_se(errno == EPERM); + assert_se(setns(0, 0) == -1); + assert_se(errno == EPERM); + + pid = raw_clone(CLONE_NEWNS); + assert_se(pid >= 0); + if (pid == 0) + _exit(EXIT_SUCCESS); + pid = raw_clone(CLONE_NEWNET); + assert_se(pid >= 0); + if (pid == 0) + _exit(EXIT_SUCCESS); + pid = raw_clone(CLONE_NEWUTS); + assert_se(pid < 0); + assert_se(errno == EPERM); + pid = raw_clone(CLONE_NEWIPC); + assert_se(pid < 0); + assert_se(errno == EPERM); + pid = raw_clone(CLONE_NEWNET|CLONE_NEWUTS); + assert_se(pid < 0); + assert_se(errno == EPERM); + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("nsseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +static void test_protect_sysctl(void) { + pid_t pid; + + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + /* in containers _sysctl() is likely missing anyway */ + if (detect_container() > 0) { + log_notice("Testing in container, skipping %s", __func__); + return; + } + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { +#if defined __NR__sysctl && __NR__sysctl >= 0 + assert_se(syscall(__NR__sysctl, NULL) < 0); + assert_se(errno == EFAULT); +#endif + + assert_se(seccomp_protect_sysctl() >= 0); + +#if defined __NR__sysctl && __NR__sysctl >= 0 + assert_se(syscall(__NR__sysctl, 0, 0, 0) < 0); + assert_se(errno == EPERM); +#endif + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("sysctlseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +static void test_protect_syslog(void) { + pid_t pid; + + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + /* in containers syslog() is likely missing anyway */ + if (detect_container() > 0) { + log_notice("Testing in container, skipping %s", __func__); + return; + } + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { +#if defined __NR_syslog && __NR_syslog >= 0 + assert_se(syscall(__NR_syslog, -1, NULL, 0) < 0); + assert_se(errno == EINVAL); +#endif + + assert_se(seccomp_protect_syslog() >= 0); + +#if defined __NR_syslog && __NR_syslog >= 0 + assert_se(syscall(__NR_syslog, 0, 0, 0) < 0); + assert_se(errno == EPERM); +#endif + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("syslogseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +static void test_restrict_address_families(void) { + pid_t pid; + + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + int fd; + Set *s; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + assert_se(fd >= 0); + safe_close(fd); + + fd = socket(AF_UNIX, SOCK_DGRAM, 0); + assert_se(fd >= 0); + safe_close(fd); + + fd = socket(AF_NETLINK, SOCK_DGRAM, 0); + assert_se(fd >= 0); + safe_close(fd); + + assert_se(s = set_new(NULL)); + assert_se(set_put(s, INT_TO_PTR(AF_UNIX)) >= 0); + + assert_se(seccomp_restrict_address_families(s, false) >= 0); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + assert_se(fd >= 0); + safe_close(fd); + + fd = socket(AF_UNIX, SOCK_DGRAM, 0); +#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN + assert_se(fd >= 0); + safe_close(fd); +#else + assert_se(fd < 0); + assert_se(errno == EAFNOSUPPORT); +#endif + + fd = socket(AF_NETLINK, SOCK_DGRAM, 0); + assert_se(fd >= 0); + safe_close(fd); + + set_clear(s); + + assert_se(set_put(s, INT_TO_PTR(AF_INET)) >= 0); + + assert_se(seccomp_restrict_address_families(s, true) >= 0); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + assert_se(fd >= 0); + safe_close(fd); + + fd = socket(AF_UNIX, SOCK_DGRAM, 0); +#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN + assert_se(fd >= 0); + safe_close(fd); +#else + assert_se(fd < 0); + assert_se(errno == EAFNOSUPPORT); +#endif + + fd = socket(AF_NETLINK, SOCK_DGRAM, 0); +#if SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN + assert_se(fd >= 0); + safe_close(fd); +#else + assert_se(fd < 0); + assert_se(errno == EAFNOSUPPORT); +#endif + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("socketseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +static void test_restrict_realtime(void) { + pid_t pid; + + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + /* in containers RT privs are likely missing anyway */ + if (detect_container() > 0) { + log_notice("Testing in container, skipping %s", __func__); + return; + } + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) >= 0); + assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) >= 0); + assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0); + assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0); + assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0); + + assert_se(seccomp_restrict_realtime() >= 0); + + assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0); + assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0); + assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0); + + assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) < 0); + assert_se(errno == EPERM); + assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) < 0); + assert_se(errno == EPERM); + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("realtimeseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +static void test_memory_deny_write_execute_mmap(void) { + pid_t pid; + + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + void *p; + + p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0); + assert_se(p != MAP_FAILED); + assert_se(munmap(p, page_size()) >= 0); + + p = mmap(NULL, page_size(), PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1,0); + assert_se(p != MAP_FAILED); + assert_se(munmap(p, page_size()) >= 0); + + assert_se(seccomp_memory_deny_write_execute() >= 0); + + p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0); +#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc64__) || defined(__arm__) || defined(__aarch64__) + assert_se(p == MAP_FAILED); + assert_se(errno == EPERM); +#endif + /* Depending on kernel, libseccomp, and glibc versions, other architectures + * might fail or not. Let's not assert success. */ + if (p != MAP_FAILED) + assert_se(munmap(p, page_size()) == 0); + + p = mmap(NULL, page_size(), PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1,0); + assert_se(p != MAP_FAILED); + assert_se(munmap(p, page_size()) >= 0); + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("memoryseccomp-mmap", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +static void test_memory_deny_write_execute_shmat(void) { + int shmid; + pid_t pid; + uint32_t arch; + + log_info("/* %s */", __func__); + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + log_debug("arch %s: SCMP_SYS(mmap) = %d", seccomp_arch_to_string(arch), SCMP_SYS(mmap)); + log_debug("arch %s: SCMP_SYS(mmap2) = %d", seccomp_arch_to_string(arch), SCMP_SYS(mmap2)); + log_debug("arch %s: SCMP_SYS(shmget) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmget)); + log_debug("arch %s: SCMP_SYS(shmat) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmat)); + log_debug("arch %s: SCMP_SYS(shmdt) = %d", seccomp_arch_to_string(arch), SCMP_SYS(shmdt)); + } + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + shmid = shmget(IPC_PRIVATE, page_size(), 0); + assert_se(shmid >= 0); + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + void *p; + + p = shmat(shmid, NULL, 0); + assert_se(p != MAP_FAILED); + assert_se(shmdt(p) == 0); + + p = shmat(shmid, NULL, SHM_EXEC); + assert_se(p != MAP_FAILED); + assert_se(shmdt(p) == 0); + + assert_se(seccomp_memory_deny_write_execute() >= 0); + + p = shmat(shmid, NULL, SHM_EXEC); + log_debug_errno(p == MAP_FAILED ? errno : 0, "shmat(SHM_EXEC): %m"); +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) + assert_se(p == MAP_FAILED); + assert_se(errno == EPERM); +#endif + /* Depending on kernel, libseccomp, and glibc versions, other architectures + * might fail or not. Let's not assert success. */ + if (p != MAP_FAILED) + assert_se(shmdt(p) == 0); + + p = shmat(shmid, NULL, 0); + log_debug_errno(p == MAP_FAILED ? errno : 0, "shmat(0): %m"); + assert_se(p != MAP_FAILED); + assert_se(shmdt(p) == 0); + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("memoryseccomp-shmat", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +static void test_restrict_archs(void) { + pid_t pid; + + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + _cleanup_set_free_ Set *s = NULL; + + assert_se(access("/", F_OK) >= 0); + + assert_se(s = set_new(NULL)); + +#ifdef __x86_64__ + assert_se(set_put(s, UINT32_TO_PTR(SCMP_ARCH_X86+1)) >= 0); +#endif + assert_se(seccomp_restrict_archs(s) >= 0); + + assert_se(access("/", F_OK) >= 0); + assert_se(seccomp_restrict_archs(NULL) >= 0); + + assert_se(access("/", F_OK) >= 0); + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("archseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +static void test_load_syscall_filter_set_raw(void) { + pid_t pid; + + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + _cleanup_hashmap_free_ Hashmap *s = NULL; + + assert_se(access("/", F_OK) >= 0); + assert_se(poll(NULL, 0, 0) == 0); + + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, scmp_act_kill_process(), true) >= 0); + assert_se(access("/", F_OK) >= 0); + assert_se(poll(NULL, 0, 0) == 0); + + assert_se(s = hashmap_new(NULL)); +#if defined __NR_access && __NR_access >= 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(-1)) >= 0); +#else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0); +#endif + + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0); + + assert_se(access("/", F_OK) < 0); + assert_se(errno == EUCLEAN); + + assert_se(poll(NULL, 0, 0) == 0); + + s = hashmap_free(s); + + assert_se(s = hashmap_new(NULL)); +#if defined __NR_access && __NR_access >= 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(EILSEQ)) >= 0); +#else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(EILSEQ)) >= 0); +#endif + + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0); + + assert_se(access("/", F_OK) < 0); + assert_se(errno == EILSEQ); + + assert_se(poll(NULL, 0, 0) == 0); + + s = hashmap_free(s); + + assert_se(s = hashmap_new(NULL)); +#if defined __NR_poll && __NR_poll >= 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(-1)) >= 0); +#else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(-1)) >= 0); +#endif + + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH), true) >= 0); + + assert_se(access("/", F_OK) < 0); + assert_se(errno == EILSEQ); + + assert_se(poll(NULL, 0, 0) < 0); + assert_se(errno == EUNATCH); + + s = hashmap_free(s); + + assert_se(s = hashmap_new(NULL)); +#if defined __NR_poll && __NR_poll >= 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(EILSEQ)) >= 0); +#else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(EILSEQ)) >= 0); +#endif + + assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH), true) >= 0); + + assert_se(access("/", F_OK) < 0); + assert_se(errno == EILSEQ); + + assert_se(poll(NULL, 0, 0) < 0); + assert_se(errno == EILSEQ); + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("syscallrawseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +static void test_lock_personality(void) { + unsigned long current; + pid_t pid; + + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + assert_se(opinionated_personality(¤t) >= 0); + + log_info("current personality=%lu", current); + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + assert_se(seccomp_lock_personality(current) >= 0); + + assert_se((unsigned long) safe_personality(current) == current); + + /* Note, we also test that safe_personality() works correctly, by checkig whether errno is properly + * set, in addition to the return value */ + errno = 0; + assert_se(safe_personality(PER_LINUX | ADDR_NO_RANDOMIZE) == -EPERM); + assert_se(errno == EPERM); + + assert_se(safe_personality(PER_LINUX | MMAP_PAGE_ZERO) == -EPERM); + assert_se(safe_personality(PER_LINUX | ADDR_COMPAT_LAYOUT) == -EPERM); + assert_se(safe_personality(PER_LINUX | READ_IMPLIES_EXEC) == -EPERM); + assert_se(safe_personality(PER_LINUX_32BIT) == -EPERM); + assert_se(safe_personality(PER_SVR4) == -EPERM); + assert_se(safe_personality(PER_BSD) == -EPERM); + assert_se(safe_personality(current == PER_LINUX ? PER_LINUX32 : PER_LINUX) == -EPERM); + assert_se(safe_personality(PER_LINUX32_3GB) == -EPERM); + assert_se(safe_personality(PER_UW7) == -EPERM); + assert_se(safe_personality(0x42) == -EPERM); + + assert_se(safe_personality(PERSONALITY_INVALID) == -EPERM); /* maybe remove this later */ + + assert_se((unsigned long) personality(current) == current); + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("lockpersonalityseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +static int real_open(const char *path, int flags, mode_t mode) { + /* glibc internally calls openat() when open() is requested. Let's hence define our own wrapper for + * testing purposes that calls the real syscall, on architectures where SYS_open is defined. On + * other architectures, let's just fall back to the glibc call. */ + +#if defined __NR_open && __NR_open >= 0 + return (int) syscall(__NR_open, path, flags, mode); +#else + return open(path, flags, mode); +#endif +} + +static void test_restrict_suid_sgid(void) { + pid_t pid; + + log_info("/* %s */", __func__); + + if (!is_seccomp_available()) { + log_notice("Seccomp not available, skipping %s", __func__); + return; + } + if (geteuid() != 0) { + log_notice("Not root, skipping %s", __func__); + return; + } + + pid = fork(); + assert_se(pid >= 0); + + if (pid == 0) { + char path[] = "/tmp/suidsgidXXXXXX", dir[] = "/tmp/suidsgiddirXXXXXX"; + int fd = -1, k = -1; + const char *z; + + fd = mkostemp_safe(path); + assert_se(fd >= 0); + + assert_se(mkdtemp(dir)); + z = strjoina(dir, "/test"); + + assert_se(chmod(path, 0755 | S_ISUID) >= 0); + assert_se(chmod(path, 0755 | S_ISGID) >= 0); + assert_se(chmod(path, 0755 | S_ISGID | S_ISUID) >= 0); + assert_se(chmod(path, 0755) >= 0); + + assert_se(fchmod(fd, 0755 | S_ISUID) >= 0); + assert_se(fchmod(fd, 0755 | S_ISGID) >= 0); + assert_se(fchmod(fd, 0755 | S_ISGID | S_ISUID) >= 0); + assert_se(fchmod(fd, 0755) >= 0); + + assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISUID, 0) >= 0); + assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID, 0) >= 0); + assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0); + assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0); + + k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = creat(z, 0644 | S_ISUID); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = creat(z, 0644 | S_ISGID); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = creat(z, 0644 | S_ISUID | S_ISGID); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = creat(z, 0644); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + assert_se(mkdir(z, 0755 | S_ISUID) >= 0); + assert_se(rmdir(z) >= 0); + assert_se(mkdir(z, 0755 | S_ISGID) >= 0); + assert_se(rmdir(z) >= 0); + assert_se(mkdir(z, 0755 | S_ISUID | S_ISGID) >= 0); + assert_se(rmdir(z) >= 0); + assert_se(mkdir(z, 0755) >= 0); + assert_se(rmdir(z) >= 0); + + assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID) >= 0); + assert_se(rmdir(z) >= 0); + assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISGID) >= 0); + assert_se(rmdir(z) >= 0); + assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID | S_ISGID) >= 0); + assert_se(rmdir(z) >= 0); + assert_se(mkdirat(AT_FDCWD, z, 0755) >= 0); + assert_se(rmdir(z) >= 0); + + assert_se(mknod(z, S_IFREG | 0755 | S_ISUID, 0) >= 0); + assert_se(unlink(z) >= 0); + assert_se(mknod(z, S_IFREG | 0755 | S_ISGID, 0) >= 0); + assert_se(unlink(z) >= 0); + assert_se(mknod(z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) >= 0); + assert_se(unlink(z) >= 0); + assert_se(mknod(z, S_IFREG | 0755, 0) >= 0); + assert_se(unlink(z) >= 0); + + assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID, 0) >= 0); + assert_se(unlink(z) >= 0); + assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISGID, 0) >= 0); + assert_se(unlink(z) >= 0); + assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) >= 0); + assert_se(unlink(z) >= 0); + assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755, 0) >= 0); + assert_se(unlink(z) >= 0); + + assert_se(seccomp_restrict_suid_sgid() >= 0); + + assert_se(chmod(path, 0775 | S_ISUID) < 0 && errno == EPERM); + assert_se(chmod(path, 0775 | S_ISGID) < 0 && errno == EPERM); + assert_se(chmod(path, 0775 | S_ISGID | S_ISUID) < 0 && errno == EPERM); + assert_se(chmod(path, 0775) >= 0); + + assert_se(fchmod(fd, 0775 | S_ISUID) < 0 && errno == EPERM); + assert_se(fchmod(fd, 0775 | S_ISGID) < 0 && errno == EPERM); + assert_se(fchmod(fd, 0775 | S_ISGID | S_ISUID) < 0 && errno == EPERM); + assert_se(fchmod(fd, 0775) >= 0); + + assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISUID, 0) < 0 && errno == EPERM); + assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID, 0) < 0 && errno == EPERM); + assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM); + assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0); + + assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM); + assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM); + assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM); + k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + assert_se(creat(z, 0644 | S_ISUID) < 0 && errno == EPERM); + assert_se(creat(z, 0644 | S_ISGID) < 0 && errno == EPERM); + assert_se(creat(z, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM); + k = creat(z, 0644); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM); + assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM); + assert_se(openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM); + k = openat(AT_FDCWD, z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644); + k = safe_close(k); + assert_se(unlink(z) >= 0); + + assert_se(mkdir(z, 0755 | S_ISUID) < 0 && errno == EPERM); + assert_se(mkdir(z, 0755 | S_ISGID) < 0 && errno == EPERM); + assert_se(mkdir(z, 0755 | S_ISUID | S_ISGID) < 0 && errno == EPERM); + assert_se(mkdir(z, 0755) >= 0); + assert_se(rmdir(z) >= 0); + + assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID) < 0 && errno == EPERM); + assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISGID) < 0 && errno == EPERM); + assert_se(mkdirat(AT_FDCWD, z, 0755 | S_ISUID | S_ISGID) < 0 && errno == EPERM); + assert_se(mkdirat(AT_FDCWD, z, 0755) >= 0); + assert_se(rmdir(z) >= 0); + + assert_se(mknod(z, S_IFREG | 0755 | S_ISUID, 0) < 0 && errno == EPERM); + assert_se(mknod(z, S_IFREG | 0755 | S_ISGID, 0) < 0 && errno == EPERM); + assert_se(mknod(z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) < 0 && errno == EPERM); + assert_se(mknod(z, S_IFREG | 0755, 0) >= 0); + assert_se(unlink(z) >= 0); + + assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID, 0) < 0 && errno == EPERM); + assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISGID, 0) < 0 && errno == EPERM); + assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755 | S_ISUID | S_ISGID, 0) < 0 && errno == EPERM); + assert_se(mknodat(AT_FDCWD, z, S_IFREG | 0755, 0) >= 0); + assert_se(unlink(z) >= 0); + + assert_se(unlink(path) >= 0); + assert_se(rm_rf(dir, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0); + + _exit(EXIT_SUCCESS); + } + + assert_se(wait_for_terminate_and_check("suidsgidseccomp", pid, WAIT_LOG) == EXIT_SUCCESS); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_seccomp_arch_to_string(); + test_architecture_table(); + test_syscall_filter_set_find(); + test_filter_sets(); + test_filter_sets_ordered(); + test_restrict_namespace(); + test_protect_sysctl(); + test_protect_syslog(); + test_restrict_address_families(); + test_restrict_realtime(); + test_memory_deny_write_execute_mmap(); + test_memory_deny_write_execute_shmat(); + test_restrict_archs(); + test_load_syscall_filter_set_raw(); + test_lock_personality(); + test_restrict_suid_sgid(); + + return 0; +} diff --git a/src/test/test-selinux.c b/src/test/test-selinux.c new file mode 100644 index 00000000..59b4f719 --- /dev/null +++ b/src/test/test-selinux.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "log.h" +#include "selinux-util.h" +#include "string-util.h" +#include "tests.h" +#include "time-util.h" +#include "util.h" + +static void test_testing(void) { + bool b; + + log_info("============ %s ==========", __func__); + + b = mac_selinux_use(); + log_info("mac_selinux_use → %s", yes_no(b)); + + b = mac_selinux_use(); + log_info("mac_selinux_use → %s", yes_no(b)); + + mac_selinux_retest(); + + b = mac_selinux_use(); + log_info("mac_selinux_use → %s", yes_no(b)); + + b = mac_selinux_use(); + log_info("mac_selinux_use → %s", yes_no(b)); +} + +static void test_loading(void) { + usec_t n1, n2; + int r; + + log_info("============ %s ==========", __func__); + + n1 = now(CLOCK_MONOTONIC); + r = mac_selinux_init(); + n2 = now(CLOCK_MONOTONIC); + log_info_errno(r, "mac_selinux_init → %d %.2fs (%m)", r, (n2 - n1)/1e6); +} + +static void test_cleanup(void) { + usec_t n1, n2; + + log_info("============ %s ==========", __func__); + + n1 = now(CLOCK_MONOTONIC); + mac_selinux_finish(); + n2 = now(CLOCK_MONOTONIC); + log_info("mac_selinux_finish → %.2fs", (n2 - n1)/1e6); +} + +static void test_misc(const char* fname) { + _cleanup_(mac_selinux_freep) char *label = NULL, *label2 = NULL, *label3 = NULL; + int r; + _cleanup_close_ int fd = -1; + + log_info("============ %s ==========", __func__); + + r = mac_selinux_get_our_label(&label); + log_info_errno(r, "mac_selinux_get_our_label → %d, \"%s\" (%m)", + r, strnull(label)); + + r = mac_selinux_get_create_label_from_exe(fname, &label2); + log_info_errno(r, "mac_selinux_create_label_from_exe → %d, \"%s\" (%m)", + r, strnull(label2)); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + assert_se(fd >= 0); + + r = mac_selinux_get_child_mls_label(fd, fname, label2, &label3); + log_info_errno(r, "mac_selinux_get_child_mls_label → %d, \"%s\" (%m)", + r, strnull(label3)); +} + +static void test_create_file_prepare(const char* fname) { + int r; + + log_info("============ %s ==========", __func__); + + r = mac_selinux_create_file_prepare(fname, S_IRWXU); + log_info_errno(r, "mac_selinux_create_file_prepare → %d (%m)", r); + + mac_selinux_create_file_clear(); +} + +int main(int argc, char **argv) { + const char *path = SYSTEMD_BINARY_PATH; + if (argc >= 2) + path = argv[1]; + + test_setup_logging(LOG_DEBUG); + + test_testing(); + test_loading(); + test_misc(path); + test_create_file_prepare(path); + test_cleanup(); + + return 0; +} diff --git a/src/test/test-serialize.c b/src/test/test-serialize.c new file mode 100644 index 00000000..a57d5db2 --- /dev/null +++ b/src/test/test-serialize.c @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "log.h" +#include "serialize.h" +#include "strv.h" +#include "tests.h" +#include "tmpfile-util.h" + +char long_string[LONG_LINE_MAX+1]; + +static void test_serialize_item(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + log_info("/* %s (%s) */", __func__, fn); + + assert_se(serialize_item(f, "a", NULL) == 0); + assert_se(serialize_item(f, "a", "bbb") == 1); + assert_se(serialize_item(f, "a", "bbb") == 1); + assert_se(serialize_item(f, "a", long_string) == -EINVAL); + assert_se(serialize_item(f, long_string, "a") == -EINVAL); + assert_se(serialize_item(f, long_string, long_string) == -EINVAL); + + rewind(f); + + _cleanup_free_ char *line1 = NULL, *line2 = NULL, *line3 = NULL; + assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0); + assert_se(streq(line1, "a=bbb")); + assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0); + assert_se(streq(line2, "a=bbb")); + assert_se(read_line(f, LONG_LINE_MAX, &line3) == 0); + assert_se(streq(line3, "")); +} + +static void test_serialize_item_escaped(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + log_info("/* %s (%s) */", __func__, fn); + + assert_se(serialize_item_escaped(f, "a", NULL) == 0); + assert_se(serialize_item_escaped(f, "a", "bbb") == 1); + assert_se(serialize_item_escaped(f, "a", "bbb") == 1); + assert_se(serialize_item_escaped(f, "a", long_string) == -EINVAL); + assert_se(serialize_item_escaped(f, long_string, "a") == -EINVAL); + assert_se(serialize_item_escaped(f, long_string, long_string) == -EINVAL); + + rewind(f); + + _cleanup_free_ char *line1 = NULL, *line2 = NULL, *line3 = NULL; + assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0); + assert_se(streq(line1, "a=bbb")); + assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0); + assert_se(streq(line2, "a=bbb")); + assert_se(read_line(f, LONG_LINE_MAX, &line3) == 0); + assert_se(streq(line3, "")); +} + +static void test_serialize_usec(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + log_info("/* %s (%s) */", __func__, fn); + + assert_se(serialize_usec(f, "usec1", USEC_INFINITY) == 0); + assert_se(serialize_usec(f, "usec2", 0) == 1); + assert_se(serialize_usec(f, "usec3", USEC_INFINITY-1) == 1); + + rewind(f); + + _cleanup_free_ char *line1 = NULL, *line2 = NULL; + usec_t x; + + assert_se(read_line(f, LONG_LINE_MAX, &line1) > 0); + assert_se(streq(line1, "usec2=0")); + assert_se(deserialize_usec(line1 + 6, &x) == 0); + assert_se(x == 0); + + assert_se(read_line(f, LONG_LINE_MAX, &line2) > 0); + assert_se(startswith(line2, "usec3=")); + assert_se(deserialize_usec(line2 + 6, &x) == 0); + assert_se(x == USEC_INFINITY-1); +} + +static void test_serialize_strv(void) { + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-serialize.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + + char **strv = STRV_MAKE("a", "b", "foo foo", + "nasty1 \"", + "\"nasty2 ", + "nasty3 '", + "\"nasty4 \"", + "nasty5\n", + "\nnasty5\nfoo=bar", + "\nnasty5\nfoo=bar"); + + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + log_info("/* %s (%s) */", __func__, fn); + + assert_se(serialize_strv(f, "strv1", NULL) == 0); + assert_se(serialize_strv(f, "strv2", STRV_MAKE_EMPTY) == 0); + assert_se(serialize_strv(f, "strv3", strv) == 1); + assert_se(serialize_strv(f, "strv4", STRV_MAKE(long_string)) == -EINVAL); + + rewind(f); + + _cleanup_strv_free_ char **strv2 = NULL; + for (;;) { + _cleanup_free_ char *line = NULL; + int r; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r == 0) + break; + assert_se(r > 0); + + const char *t = startswith(line, "strv3="); + assert_se(t); + + char *un; + assert_se(cunescape(t, 0, &un) >= 0); + assert_se(strv_consume(&strv2, un) >= 0); + } + + assert_se(strv_equal(strv, strv2)); +} + +static void test_deserialize_environment(void) { + _cleanup_strv_free_ char **env; + + log_info("/* %s */", __func__); + + assert_se(env = strv_new("A=1")); + + assert_se(deserialize_environment("B=2", &env) >= 0); + assert_se(deserialize_environment("FOO%%=a\\177b\\nc\\td e", &env) >= 0); + + assert_se(strv_equal(env, STRV_MAKE("A=1", "B=2", "FOO%%=a\177b\nc\td e"))); + + assert_se(deserialize_environment("foo\\", &env) < 0); + assert_se(deserialize_environment("bar\\_baz", &env) < 0); +} + +static void test_serialize_environment(void) { + _cleanup_strv_free_ char **env = NULL, **env2 = NULL; + _cleanup_(unlink_tempfilep) char fn[] = "/tmp/test-env-util.XXXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert_se(fmkostemp_safe(fn, "r+", &f) == 0); + log_info("/* %s (%s) */", __func__, fn); + + assert_se(env = strv_new("A=1", + "B=2", + "C=ąęółń", + "D=D=a\\x0Ab", + "FOO%%=a\177b\nc\td e")); + + assert_se(serialize_strv(f, "env", env) == 1); + assert_se(fflush_and_check(f) == 0); + + rewind(f); + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *l; + + r = read_line(f, LONG_LINE_MAX, &line); + assert_se(r >= 0); + + if (r == 0) + break; + + l = strstrip(line); + + assert_se(startswith(l, "env=")); + + r = deserialize_environment(l+4, &env2); + assert_se(r >= 0); + } + assert_se(feof(f)); + + assert_se(strv_equal(env, env2)); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + memset(long_string, 'x', sizeof(long_string)-1); + char_array_0(long_string); + + test_serialize_item(); + test_serialize_item_escaped(); + test_serialize_usec(); + test_serialize_strv(); + test_deserialize_environment(); + test_serialize_environment(); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-set-disable-mempool.c b/src/test/test-set-disable-mempool.c new file mode 100644 index 00000000..aea83d26 --- /dev/null +++ b/src/test/test-set-disable-mempool.c @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "process-util.h" +#include "set.h" +#include "tests.h" + +#define NUM 100 + +static void* thread(void *p) { + Set **s = p; + + assert_se(s); + assert_se(*s); + + assert_se(!is_main_thread()); + assert_se(set_size(*s) == NUM); + *s = set_free(*s); + + return NULL; +} + +static void test_one(const char *val) { + pthread_t t; + int x[NUM] = {}; + unsigned i; + Set *s; + + log_info("Testing with SYSTEMD_MEMPOOL=%s", val); + assert_se(setenv("SYSTEMD_MEMPOOL", val, true) == 0); + assert_se(is_main_thread()); + + assert_se(s = set_new(NULL)); + for (i = 0; i < NUM; i++) + assert_se(set_put(s, &x[i])); + + assert_se(pthread_create(&t, NULL, thread, &s) == 0); + assert_se(pthread_join(t, NULL) == 0); + + assert_se(!s); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_one("0"); + /* The value $SYSTEMD_MEMPOOL= is cached. So the following + * test should also succeed. */ + test_one("1"); + + return 0; +} diff --git a/src/test/test-set.c b/src/test/test-set.c new file mode 100644 index 00000000..b4e7a52f --- /dev/null +++ b/src/test/test-set.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "set.h" +#include "strv.h" + +static void test_set_steal_first(void) { + _cleanup_set_free_ Set *m = NULL; + int seen[3] = {}; + char *val; + + m = set_new(&string_hash_ops); + assert_se(m); + + assert_se(set_put(m, (void*) "1") == 1); + assert_se(set_put(m, (void*) "22") == 1); + assert_se(set_put(m, (void*) "333") == 1); + + while ((val = set_steal_first(m))) + seen[strlen(val) - 1]++; + + assert_se(seen[0] == 1 && seen[1] == 1 && seen[2] == 1); + + assert_se(set_isempty(m)); +} + +typedef struct Item { + int seen; +} Item; +static void item_seen(Item *item) { + item->seen++; +} + +static void test_set_free_with_destructor(void) { + Set *m; + struct Item items[4] = {}; + unsigned i; + + assert_se(m = set_new(NULL)); + for (i = 0; i < ELEMENTSOF(items) - 1; i++) + assert_se(set_put(m, items + i) == 1); + + m = set_free_with_destructor(m, item_seen); + assert_se(items[0].seen == 1); + assert_se(items[1].seen == 1); + assert_se(items[2].seen == 1); + assert_se(items[3].seen == 0); +} + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_hash_ops, void, trivial_hash_func, trivial_compare_func, Item, item_seen); + +static void test_set_free_with_hash_ops(void) { + Set *m; + struct Item items[4] = {}; + unsigned i; + + assert_se(m = set_new(&item_hash_ops)); + for (i = 0; i < ELEMENTSOF(items) - 1; i++) + assert_se(set_put(m, items + i) == 1); + + m = set_free(m); + assert_se(items[0].seen == 1); + assert_se(items[1].seen == 1); + assert_se(items[2].seen == 1); + assert_se(items[3].seen == 0); +} + +static void test_set_put(void) { + _cleanup_set_free_ Set *m = NULL; + + m = set_new(&string_hash_ops); + assert_se(m); + + assert_se(set_put(m, (void*) "1") == 1); + assert_se(set_put(m, (void*) "22") == 1); + assert_se(set_put(m, (void*) "333") == 1); + assert_se(set_put(m, (void*) "333") == 0); + assert_se(set_remove(m, (void*) "333")); + assert_se(set_put(m, (void*) "333") == 1); + assert_se(set_put(m, (void*) "333") == 0); + assert_se(set_put(m, (void*) "22") == 0); + + _cleanup_free_ char **t = set_get_strv(m); + assert_se(strv_contains(t, "1")); + assert_se(strv_contains(t, "22")); + assert_se(strv_contains(t, "333")); + assert_se(strv_length(t) == 3); +} + +int main(int argc, const char *argv[]) { + test_set_steal_first(); + test_set_free_with_destructor(); + test_set_free_with_hash_ops(); + test_set_put(); + + return 0; +} diff --git a/src/test/test-sigbus.c b/src/test/test-sigbus.c new file mode 100644 index 00000000..f753e383 --- /dev/null +++ b/src/test/test-sigbus.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#if HAVE_VALGRIND_VALGRIND_H +# include +#endif + +#include "fd-util.h" +#include "memory-util.h" +#include "sigbus.h" +#include "tests.h" + +int main(int argc, char *argv[]) { + _cleanup_close_ int fd = -1; + char template[] = "/tmp/sigbus-test-XXXXXX"; + void *addr = NULL; + uint8_t *p; + + test_setup_logging(LOG_INFO); + +#if HAS_FEATURE_ADDRESS_SANITIZER + return log_tests_skipped("address-sanitizer is enabled"); +#endif +#if HAVE_VALGRIND_VALGRIND_H + if (RUNNING_ON_VALGRIND) + return log_tests_skipped("This test cannot run on valgrind"); +#endif + + sigbus_install(); + + assert_se(sigbus_pop(&addr) == 0); + + assert_se((fd = mkostemp(template, O_RDWR|O_CREAT|O_EXCL)) >= 0); + assert_se(unlink(template) >= 0); + assert_se(posix_fallocate(fd, 0, page_size() * 8) >= 0); + + p = mmap(NULL, page_size() * 16, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + assert_se(p != MAP_FAILED); + + assert_se(sigbus_pop(&addr) == 0); + + p[0] = 0xFF; + assert_se(sigbus_pop(&addr) == 0); + + p[page_size()] = 0xFF; + assert_se(sigbus_pop(&addr) == 0); + + p[page_size()*8] = 0xFF; + p[page_size()*8+1] = 0xFF; + p[page_size()*10] = 0xFF; + assert_se(sigbus_pop(&addr) > 0); + assert_se(addr == p + page_size() * 8); + assert_se(sigbus_pop(&addr) > 0); + assert_se(addr == p + page_size() * 10); + assert_se(sigbus_pop(&addr) == 0); + + sigbus_reset(); +} diff --git a/src/test/test-signal-util.c b/src/test/test-signal-util.c new file mode 100644 index 00000000..1a8c60ad --- /dev/null +++ b/src/test/test-signal-util.c @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "log.h" +#include "macro.h" +#include "signal-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "process-util.h" + +#define info(sig) log_info(#sig " = " STRINGIFY(sig) " = %d", sig) + +static void test_rt_signals(void) { + info(SIGRTMIN); + info(SIGRTMAX); + + /* We use signals SIGRTMIN+0 to SIGRTMIN+24 unconditionally */ + assert(SIGRTMAX - SIGRTMIN >= 24); +} + +static void test_signal_to_string_one(int val) { + const char *p; + + assert_se(p = signal_to_string(val)); + + assert_se(signal_from_string(p) == val); + + p = strjoina("SIG", p); + assert_se(signal_from_string(p) == val); +} + +static void test_signal_from_string_one(const char *s, int val) { + const char *p; + + assert_se(signal_from_string(s) == val); + + p = strjoina("SIG", s); + assert_se(signal_from_string(p) == val); +} + +static void test_signal_from_string_number(const char *s, int val) { + const char *p; + + assert_se(signal_from_string(s) == val); + + p = strjoina("SIG", s); + assert_se(signal_from_string(p) == -EINVAL); +} + +static void test_signal_from_string(void) { + char buf[STRLEN("RTMIN+") + DECIMAL_STR_MAX(int) + 1]; + + test_signal_to_string_one(SIGHUP); + test_signal_to_string_one(SIGTERM); + test_signal_to_string_one(SIGRTMIN); + test_signal_to_string_one(SIGRTMIN+3); + test_signal_to_string_one(SIGRTMAX-4); + + test_signal_from_string_one("RTMIN", SIGRTMIN); + test_signal_from_string_one("RTMAX", SIGRTMAX); + + xsprintf(buf, "RTMIN+%d", SIGRTMAX-SIGRTMIN); + test_signal_from_string_one(buf, SIGRTMAX); + + xsprintf(buf, "RTMIN+%d", INT_MAX); + test_signal_from_string_one(buf, -ERANGE); + + xsprintf(buf, "RTMAX-%d", SIGRTMAX-SIGRTMIN); + test_signal_from_string_one(buf, SIGRTMIN); + + xsprintf(buf, "RTMAX-%d", INT_MAX); + test_signal_from_string_one(buf, -ERANGE); + + test_signal_from_string_one("", -EINVAL); + test_signal_from_string_one("hup", -EINVAL); + test_signal_from_string_one("HOGEHOGE", -EINVAL); + + test_signal_from_string_one("RTMIN-5", -EINVAL); + test_signal_from_string_one("RTMIN- 5", -EINVAL); + test_signal_from_string_one("RTMIN -5", -EINVAL); + test_signal_from_string_one("RTMIN+ 5", -EINVAL); + test_signal_from_string_one("RTMIN +5", -EINVAL); + test_signal_from_string_one("RTMIN+100", -ERANGE); + test_signal_from_string_one("RTMIN+-3", -EINVAL); + test_signal_from_string_one("RTMIN++3", -EINVAL); + test_signal_from_string_one("RTMIN+HUP", -EINVAL); + test_signal_from_string_one("RTMIN3", -EINVAL); + + test_signal_from_string_one("RTMAX+5", -EINVAL); + test_signal_from_string_one("RTMAX+ 5", -EINVAL); + test_signal_from_string_one("RTMAX +5", -EINVAL); + test_signal_from_string_one("RTMAX- 5", -EINVAL); + test_signal_from_string_one("RTMAX -5", -EINVAL); + test_signal_from_string_one("RTMAX-100", -ERANGE); + test_signal_from_string_one("RTMAX-+3", -EINVAL); + test_signal_from_string_one("RTMAX--3", -EINVAL); + test_signal_from_string_one("RTMAX-HUP", -EINVAL); + + test_signal_from_string_number("3", 3); + test_signal_from_string_number("+5", 5); + test_signal_from_string_number(" +5", 5); + test_signal_from_string_number("10000", -ERANGE); + test_signal_from_string_number("-2", -ERANGE); +} + +static void test_block_signals(void) { + sigset_t ss; + + assert_se(sigprocmask(0, NULL, &ss) >= 0); + + assert_se(sigismember(&ss, SIGUSR1) == 0); + assert_se(sigismember(&ss, SIGALRM) == 0); + assert_se(sigismember(&ss, SIGVTALRM) == 0); + + { + BLOCK_SIGNALS(SIGUSR1, SIGVTALRM); + + assert_se(sigprocmask(0, NULL, &ss) >= 0); + assert_se(sigismember(&ss, SIGUSR1) == 1); + assert_se(sigismember(&ss, SIGALRM) == 0); + assert_se(sigismember(&ss, SIGVTALRM) == 1); + + } + + assert_se(sigprocmask(0, NULL, &ss) >= 0); + assert_se(sigismember(&ss, SIGUSR1) == 0); + assert_se(sigismember(&ss, SIGALRM) == 0); + assert_se(sigismember(&ss, SIGVTALRM) == 0); +} + +static void test_ignore_signals(void) { + assert_se(ignore_signals(SIGINT, -1) >= 0); + assert_se(kill(getpid_cached(), SIGINT) >= 0); + assert_se(ignore_signals(SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0); + assert_se(kill(getpid_cached(), SIGUSR1) >= 0); + assert_se(kill(getpid_cached(), SIGUSR2) >= 0); + assert_se(kill(getpid_cached(), SIGTERM) >= 0); + assert_se(kill(getpid_cached(), SIGPIPE) >= 0); + assert_se(default_signals(SIGINT, SIGUSR1, SIGUSR2, SIGTERM, SIGPIPE, -1) >= 0); +} + +int main(int argc, char *argv[]) { + test_rt_signals(); + test_signal_from_string(); + test_block_signals(); + test_ignore_signals(); + + return 0; +} diff --git a/src/test/test-siphash24.c b/src/test/test-siphash24.c new file mode 100644 index 00000000..6ae272fa --- /dev/null +++ b/src/test/test-siphash24.c @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "memory-util.h" +#include "siphash24.h" + +#define ITERATIONS 10000000ULL + +static void do_test(const uint8_t *in, size_t len, const uint8_t *key) { + struct siphash state = {}; + uint64_t out; + unsigned i, j; + + out = siphash24(in, len, key); + assert_se(out == 0xa129ca6149be45e5); + + /* verify the internal state as given in the above paper */ + siphash24_init(&state, key); + assert_se(state.v0 == 0x7469686173716475); + assert_se(state.v1 == 0x6b617f6d656e6665); + assert_se(state.v2 == 0x6b7f62616d677361); + assert_se(state.v3 == 0x7b6b696e727e6c7b); + siphash24_compress(in, len, &state); + assert_se(state.v0 == 0x4a017198de0a59e0); + assert_se(state.v1 == 0x0d52f6f62a4f59a4); + assert_se(state.v2 == 0x634cb3577b01fd3d); + assert_se(state.v3 == 0xa5224d6f55c7d9c8); + out = siphash24_finalize(&state); + assert_se(out == 0xa129ca6149be45e5); + assert_se(state.v0 == 0xf6bcd53893fecff1); + assert_se(state.v1 == 0x54b9964c7ea0d937); + assert_se(state.v2 == 0x1b38329c099bb55a); + assert_se(state.v3 == 0x1814bb89ad7be679); + + /* verify that decomposing the input in three chunks gives the + same result */ + for (i = 0; i < len; i++) { + for (j = i; j < len; j++) { + siphash24_init(&state, key); + siphash24_compress(in, i, &state); + siphash24_compress(&in[i], j - i, &state); + siphash24_compress(&in[j], len - j, &state); + out = siphash24_finalize(&state); + assert_se(out == 0xa129ca6149be45e5); + } + } +} + +static void test_short_hashes(void) { + const uint8_t one[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }; + const uint8_t key[16] = { 0x22, 0x24, 0x41, 0x22, 0x55, 0x77, 0x88, 0x07, + 0x23, 0x09, 0x23, 0x14, 0x0c, 0x33, 0x0e, 0x0f}; + uint8_t two[sizeof one] = {}; + + struct siphash state1 = {}, state2 = {}; + unsigned i, j; + + siphash24_init(&state1, key); + siphash24_init(&state2, key); + + /* hashing 1, 2, 3, 4, 5, ..., 16 bytes, with the byte after the buffer different */ + for (i = 1; i <= sizeof one; i++) { + siphash24_compress(one, i, &state1); + + two[i-1] = one[i-1]; + siphash24_compress(two, i, &state2); + + assert_se(memcmp(&state1, &state2, sizeof state1) == 0); + } + + /* hashing n and 1, n and 2, n and 3, ..., n-1 and 1, n-2 and 2, ... */ + for (i = sizeof one; i > 0; i--) { + zero(two); + + for (j = 1; j <= sizeof one; j++) { + siphash24_compress(one, i, &state1); + siphash24_compress(one, j, &state1); + + siphash24_compress(one, i, &state2); + two[j-1] = one[j-1]; + siphash24_compress(two, j, &state2); + + assert_se(memcmp(&state1, &state2, sizeof state1) == 0); + } + } +} + +/* see https://131002.net/siphash/siphash.pdf, Appendix A */ +int main(int argc, char *argv[]) { + const uint8_t in[15] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e }; + const uint8_t key[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; + uint8_t in_buf[20]; + + /* Test with same input but different alignments. */ + memcpy(in_buf, in, sizeof(in)); + do_test(in_buf, sizeof(in), key); + memcpy(in_buf + 1, in, sizeof(in)); + do_test(in_buf + 1, sizeof(in), key); + memcpy(in_buf + 2, in, sizeof(in)); + do_test(in_buf + 2, sizeof(in), key); + memcpy(in_buf + 4, in, sizeof(in)); + do_test(in_buf + 4, sizeof(in), key); + + test_short_hashes(); +} diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c new file mode 100644 index 00000000..7fc16a62 --- /dev/null +++ b/src/test/test-sizeof.c @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include + +#include "time-util.h" + +/* Print information about various types. Useful when diagnosing + * gcc diagnostics on an unfamiliar architecture. */ + +#pragma GCC diagnostic ignored "-Wtype-limits" + +#define info(t) \ + printf("%s → %zu bits%s, %zu byte alignment\n", STRINGIFY(t), \ + sizeof(t)*CHAR_BIT, \ + strstr(STRINGIFY(t), "signed") ? "" : \ + (t)-1 < (t)0 ? ", signed" : ", unsigned", \ + __alignof__(t)) + +enum Enum { + enum_value, +}; + +enum BigEnum { + big_enum_value = UINT64_C(1), +}; + +enum BigEnum2 { + big_enum2_pos = UINT64_C(1), + big_enum2_neg = UINT64_C(-1), +}; + +int main(void) { + info(char); + info(signed char); + info(unsigned char); + info(short unsigned); + info(unsigned); + info(long unsigned); + info(long long unsigned); + info(__syscall_ulong_t); + info(__syscall_slong_t); + + info(float); + info(double); + info(long double); + +#ifdef FLT128_MAX + info(_Float128); + info(_Float64); + info(_Float64x); + info(_Float32); + info(_Float32x); +#endif + + info(size_t); + info(ssize_t); + info(time_t); + info(usec_t); + info(__time_t); + info(pid_t); + info(uid_t); + info(gid_t); + + info(__cpu_mask); + + info(enum Enum); + info(enum BigEnum); + info(enum BigEnum2); + assert_cc(sizeof(enum BigEnum2) == 8); + printf("big_enum2_pos → %zu\n", sizeof(big_enum2_pos)); + printf("big_enum2_neg → %zu\n", sizeof(big_enum2_neg)); + + return 0; +} diff --git a/src/test/test-sleep.c b/src/test/test-sleep.c new file mode 100644 index 00000000..014b1aa7 --- /dev/null +++ b/src/test/test-sleep.c @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include + +#include "errno-util.h" +#include "fd-util.h" +#include "log.h" +#include "memory-util.h" +#include "sleep-config.h" +#include "strv.h" +#include "tests.h" +#include "util.h" + +static void test_parse_sleep_config(void) { + _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL; + log_info("/* %s */", __func__); + + assert(parse_sleep_config(&sleep_config) == 0); + + _cleanup_free_ char *sum, *sus, *him, *his, *hym, *hys; + + sum = strv_join(sleep_config->suspend_modes, ", "); + sus = strv_join(sleep_config->suspend_states, ", "); + him = strv_join(sleep_config->hibernate_modes, ", "); + his = strv_join(sleep_config->hibernate_states, ", "); + hym = strv_join(sleep_config->hybrid_modes, ", "); + hys = strv_join(sleep_config->hybrid_states, ", "); + log_debug(" allow_suspend: %u", sleep_config->allow_suspend); + log_debug(" allow_hibernate: %u", sleep_config->allow_hibernate); + log_debug(" allow_s2h: %u", sleep_config->allow_s2h); + log_debug(" allow_hybrid_sleep: %u", sleep_config->allow_hybrid_sleep); + log_debug(" suspend modes: %s", sum); + log_debug(" states: %s", sus); + log_debug(" hibernate modes: %s", him); + log_debug(" states: %s", his); + log_debug(" hybrid modes: %s", hym); + log_debug(" states: %s", hys); +} + +static int test_fiemap(const char *path) { + _cleanup_free_ struct fiemap *fiemap = NULL; + _cleanup_close_ int fd = -1; + int r; + + log_info("/* %s */", __func__); + + fd = open(path, O_RDONLY | O_CLOEXEC | O_NONBLOCK); + if (fd < 0) + return log_error_errno(errno, "failed to open %s: %m", path); + r = read_fiemap(fd, &fiemap); + if (r == -EOPNOTSUPP) + exit(log_tests_skipped("Not supported")); + if (r < 0) + return log_error_errno(r, "Unable to read extent map for '%s': %m", path); + log_info("extent map information for %s:", path); + log_info("\t start: %" PRIu64, (uint64_t) fiemap->fm_start); + log_info("\t length: %" PRIu64, (uint64_t) fiemap->fm_length); + log_info("\t flags: %" PRIu32, fiemap->fm_flags); + log_info("\t number of mapped extents: %" PRIu32, fiemap->fm_mapped_extents); + log_info("\t extent count: %" PRIu32, fiemap->fm_extent_count); + if (fiemap->fm_extent_count > 0) + log_info("\t first extent location: %" PRIu64, + (uint64_t) (fiemap->fm_extents[0].fe_physical / page_size())); + + return 0; +} + +static void test_sleep(void) { + _cleanup_strv_free_ char + **standby = strv_new("standby"), + **mem = strv_new("mem"), + **disk = strv_new("disk"), + **suspend = strv_new("suspend"), + **reboot = strv_new("reboot"), + **platform = strv_new("platform"), + **shutdown = strv_new("shutdown"), + **freeze = strv_new("freeze"); + int r; + + log_info("/* %s */", __func__); + + log_info("/= configuration =/"); + log_info("Standby configured: %s", yes_no(can_sleep_state(standby) > 0)); + log_info("Suspend configured: %s", yes_no(can_sleep_state(mem) > 0)); + log_info("Hibernate configured: %s", yes_no(can_sleep_state(disk) > 0)); + log_info("Hibernate+Suspend (Hybrid-Sleep) configured: %s", yes_no(can_sleep_disk(suspend) > 0)); + log_info("Hibernate+Reboot configured: %s", yes_no(can_sleep_disk(reboot) > 0)); + log_info("Hibernate+Platform configured: %s", yes_no(can_sleep_disk(platform) > 0)); + log_info("Hibernate+Shutdown configured: %s", yes_no(can_sleep_disk(shutdown) > 0)); + log_info("Freeze configured: %s", yes_no(can_sleep_state(freeze) > 0)); + + log_info("/= running system =/"); + r = can_sleep("suspend"); + log_info("Suspend configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); + r = can_sleep("hibernate"); + log_info("Hibernation configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); + r = can_sleep("hybrid-sleep"); + log_info("Hybrid-sleep configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); + r = can_sleep("suspend-then-hibernate"); + log_info("Suspend-then-Hibernate configured and possible: %s", r >= 0 ? yes_no(r) : strerror_safe(r)); +} + +int main(int argc, char* argv[]) { + int i, r = 0, k; + + test_setup_logging(LOG_DEBUG); + + if (getuid() != 0) + log_warning("This program is unlikely to work for unprivileged users"); + + test_parse_sleep_config(); + test_sleep(); + + if (argc <= 1) + assert_se(test_fiemap(argv[0]) == 0); + else + for (i = 1; i < argc; i++) { + k = test_fiemap(argv[i]); + if (r == 0) + r = k; + } + + return r; +} diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c new file mode 100644 index 00000000..b36e0052 --- /dev/null +++ b/src/test/test-socket-util.c @@ -0,0 +1,909 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "async.h" +#include "escape.h" +#include "exit-status.h" +#include "fd-util.h" +#include "in-addr-util.h" +#include "io-util.h" +#include "log.h" +#include "macro.h" +#include "missing_network.h" +#include "process-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "tests.h" +#include "tmpfile-util.h" + +static void test_ifname_valid(void) { + log_info("/* %s */", __func__); + + assert(ifname_valid("foo")); + assert(ifname_valid("eth0")); + + assert(!ifname_valid("0")); + assert(!ifname_valid("99")); + assert(ifname_valid("a99")); + assert(ifname_valid("99a")); + + assert(!ifname_valid(NULL)); + assert(!ifname_valid("")); + assert(!ifname_valid(" ")); + assert(!ifname_valid(" foo")); + assert(!ifname_valid("bar\n")); + assert(!ifname_valid(".")); + assert(!ifname_valid("..")); + assert(ifname_valid("foo.bar")); + assert(!ifname_valid("x:y")); + + assert(ifname_valid("xxxxxxxxxxxxxxx")); + assert(!ifname_valid("xxxxxxxxxxxxxxxx")); +} + +static void test_socket_address_parse_one(const char *in, int ret, int family, const char *expected) { + SocketAddress a; + _cleanup_free_ char *out = NULL; + int r; + + r = socket_address_parse(&a, in); + if (r >= 0) + assert_se(socket_address_print(&a, &out) >= 0); + + log_info("\"%s\" → %s → \"%s\" (expect \"%s\")", in, + r >= 0 ? "✓" : "✗", empty_to_dash(out), r >= 0 ? expected ?: in : "-"); + assert_se(r == ret); + if (r >= 0) { + assert_se(a.sockaddr.sa.sa_family == family); + assert_se(streq(out, expected ?: in)); + } +} + +#define SUN_PATH_LEN (sizeof(((struct sockaddr_un){}).sun_path)) +assert_cc(SUN_PATH_LEN == 108); + +static void test_socket_address_parse(void) { + log_info("/* %s */", __func__); + + test_socket_address_parse_one("junk", -EINVAL, 0, NULL); + test_socket_address_parse_one("192.168.1.1", -EINVAL, 0, NULL); + test_socket_address_parse_one(".168.1.1", -EINVAL, 0, NULL); + test_socket_address_parse_one("989.168.1.1", -EINVAL, 0, NULL); + test_socket_address_parse_one("192.168.1.1:65536", -ERANGE, 0, NULL); + test_socket_address_parse_one("192.168.1.1:0", -EINVAL, 0, NULL); + test_socket_address_parse_one("0", -EINVAL, 0, NULL); + test_socket_address_parse_one("65536", -ERANGE, 0, NULL); + + const int default_family = socket_ipv6_is_supported() ? AF_INET6 : AF_INET; + + test_socket_address_parse_one("65535", 0, default_family, "[::]:65535"); + + /* The checks below will pass even if ipv6 is disabled in + * kernel. The underlying glibc's inet_pton() is just a string + * parser and doesn't make any syscalls. */ + + test_socket_address_parse_one("[::1]", -EINVAL, 0, NULL); + test_socket_address_parse_one("[::1]8888", -EINVAL, 0, NULL); + test_socket_address_parse_one("::1", -EINVAL, 0, NULL); + test_socket_address_parse_one("[::1]:0", -EINVAL, 0, NULL); + test_socket_address_parse_one("[::1]:65536", -ERANGE, 0, NULL); + test_socket_address_parse_one("[a:b:1]:8888", -EINVAL, 0, NULL); + + test_socket_address_parse_one("8888", 0, default_family, "[::]:8888"); + test_socket_address_parse_one("[2001:0db8:0000:85a3:0000:0000:ac1f:8001]:8888", 0, AF_INET6, + "[2001:db8:0:85a3::ac1f:8001]:8888"); + test_socket_address_parse_one("[::1]:8888", 0, AF_INET6, NULL); + test_socket_address_parse_one("192.168.1.254:8888", 0, AF_INET, NULL); + test_socket_address_parse_one("/foo/bar", 0, AF_UNIX, NULL); + test_socket_address_parse_one("/", 0, AF_UNIX, NULL); + test_socket_address_parse_one("@abstract", 0, AF_UNIX, NULL); + + { + char aaa[SUN_PATH_LEN + 1] = "@"; + + memset(aaa + 1, 'a', SUN_PATH_LEN - 1); + char_array_0(aaa); + + test_socket_address_parse_one(aaa, -EINVAL, 0, NULL); + + aaa[SUN_PATH_LEN - 1] = '\0'; + test_socket_address_parse_one(aaa, 0, AF_UNIX, NULL); + } + + test_socket_address_parse_one("vsock:2:1234", 0, AF_VSOCK, NULL); + test_socket_address_parse_one("vsock::1234", 0, AF_VSOCK, NULL); + test_socket_address_parse_one("vsock:2:1234x", -EINVAL, 0, NULL); + test_socket_address_parse_one("vsock:2x:1234", -EINVAL, 0, NULL); + test_socket_address_parse_one("vsock:2", -EINVAL, 0, NULL); +} + +static void test_socket_print_unix_one(const char *in, size_t len_in, const char *expected) { + _cleanup_free_ char *out = NULL, *c = NULL; + + assert(len_in <= SUN_PATH_LEN); + SocketAddress a = { .sockaddr = { .un = { .sun_family = AF_UNIX } }, + .size = offsetof(struct sockaddr_un, sun_path) + len_in, + .type = SOCK_STREAM, + }; + memcpy(a.sockaddr.un.sun_path, in, len_in); + + assert_se(socket_address_print(&a, &out) >= 0); + assert_se(c = cescape(in)); + log_info("\"%s\" → \"%s\" (expect \"%s\")", in, out, expected); + assert_se(streq(out, expected)); +} + +static void test_socket_print_unix(void) { + log_info("/* %s */", __func__); + + /* Some additional tests for abstract addresses which we don't parse */ + + test_socket_print_unix_one("\0\0\0\0", 4, "@\\000\\000\\000"); + test_socket_print_unix_one("@abs", 5, "@abs"); + test_socket_print_unix_one("\n", 2, "\\n"); + test_socket_print_unix_one("", 1, ""); + test_socket_print_unix_one("\0", 1, ""); + test_socket_print_unix_one("\0_________________________there's 108 characters in this string_____________________________________________", 108, + "@_________________________there\\'s 108 characters in this string_____________________________________________"); + test_socket_print_unix_one("////////////////////////////////////////////////////////////////////////////////////////////////////////////", 108, + "////////////////////////////////////////////////////////////////////////////////////////////////////////////"); + test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000"); +} + +static void test_socket_address_parse_netlink(void) { + SocketAddress a; + + log_info("/* %s */", __func__); + + assert_se(socket_address_parse_netlink(&a, "junk") < 0); + assert_se(socket_address_parse_netlink(&a, "") < 0); + + assert_se(socket_address_parse_netlink(&a, "route") >= 0); + assert_se(a.sockaddr.nl.nl_family == AF_NETLINK); + assert_se(a.sockaddr.nl.nl_groups == 0); + assert_se(a.protocol == NETLINK_ROUTE); + assert_se(socket_address_parse_netlink(&a, "route") >= 0); + assert_se(socket_address_parse_netlink(&a, "route 10") >= 0); + assert_se(a.sockaddr.nl.nl_family == AF_NETLINK); + assert_se(a.sockaddr.nl.nl_groups == 10); + assert_se(a.protocol == NETLINK_ROUTE); + + /* With spaces and tabs */ + assert_se(socket_address_parse_netlink(&a, " kobject-uevent ") >= 0); + assert_se(a.sockaddr.nl.nl_family == AF_NETLINK); + assert_se(a.sockaddr.nl.nl_groups == 0); + assert_se(a.protocol == NETLINK_KOBJECT_UEVENT); + assert_se(socket_address_parse_netlink(&a, " \t kobject-uevent \t 10") >= 0); + assert_se(a.sockaddr.nl.nl_family == AF_NETLINK); + assert_se(a.sockaddr.nl.nl_groups == 10); + assert_se(a.protocol == NETLINK_KOBJECT_UEVENT); + assert_se(socket_address_parse_netlink(&a, "kobject-uevent\t10") >= 0); + assert_se(a.sockaddr.nl.nl_family == AF_NETLINK); + assert_se(a.sockaddr.nl.nl_groups == 10); + assert_se(a.protocol == NETLINK_KOBJECT_UEVENT); + + /* trailing space is not supported */ + assert_se(socket_address_parse_netlink(&a, "kobject-uevent\t10 ") < 0); + + /* Group must be unsigned */ + assert_se(socket_address_parse_netlink(&a, "kobject-uevent -1") < 0); + + /* oss-fuzz #6884 */ + assert_se(socket_address_parse_netlink(&a, "\xff") < 0); +} + +static void test_socket_address_equal(void) { + SocketAddress a, b; + + log_info("/* %s */", __func__); + + assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); + assert_se(socket_address_parse(&b, "192.168.1.1:888") >= 0); + assert_se(!socket_address_equal(&a, &b)); + + assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); + assert_se(socket_address_parse(&b, "192.16.1.1:8888") >= 0); + assert_se(!socket_address_equal(&a, &b)); + + assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); + assert_se(socket_address_parse(&b, "8888") >= 0); + assert_se(!socket_address_equal(&a, &b)); + + assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); + assert_se(socket_address_parse(&b, "/foo/bar/") >= 0); + assert_se(!socket_address_equal(&a, &b)); + + assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); + assert_se(socket_address_parse(&b, "192.168.1.1:8888") >= 0); + assert_se(socket_address_equal(&a, &b)); + + assert_se(socket_address_parse(&a, "/foo/bar") >= 0); + assert_se(socket_address_parse(&b, "/foo/bar") >= 0); + assert_se(socket_address_equal(&a, &b)); + + assert_se(socket_address_parse(&a, "[::1]:8888") >= 0); + assert_se(socket_address_parse(&b, "[::1]:8888") >= 0); + assert_se(socket_address_equal(&a, &b)); + + assert_se(socket_address_parse(&a, "@abstract") >= 0); + assert_se(socket_address_parse(&b, "@abstract") >= 0); + assert_se(socket_address_equal(&a, &b)); + + assert_se(socket_address_parse_netlink(&a, "firewall") >= 0); + assert_se(socket_address_parse_netlink(&b, "firewall") >= 0); + assert_se(socket_address_equal(&a, &b)); + + assert_se(socket_address_parse(&a, "vsock:2:1234") >= 0); + assert_se(socket_address_parse(&b, "vsock:2:1234") >= 0); + assert_se(socket_address_equal(&a, &b)); + assert_se(socket_address_parse(&b, "vsock:2:1235") >= 0); + assert_se(!socket_address_equal(&a, &b)); + assert_se(socket_address_parse(&b, "vsock:3:1234") >= 0); + assert_se(!socket_address_equal(&a, &b)); +} + +static void test_socket_address_get_path(void) { + SocketAddress a; + + log_info("/* %s */", __func__); + + assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); + assert_se(!socket_address_get_path(&a)); + + assert_se(socket_address_parse(&a, "@abstract") >= 0); + assert_se(!socket_address_get_path(&a)); + + assert_se(socket_address_parse(&a, "[::1]:8888") >= 0); + assert_se(!socket_address_get_path(&a)); + + assert_se(socket_address_parse(&a, "/foo/bar") >= 0); + assert_se(streq(socket_address_get_path(&a), "/foo/bar")); + + assert_se(socket_address_parse(&a, "vsock:2:1234") >= 0); + assert_se(!socket_address_get_path(&a)); +} + +static void test_socket_address_is(void) { + SocketAddress a; + + log_info("/* %s */", __func__); + + assert_se(socket_address_parse(&a, "192.168.1.1:8888") >= 0); + assert_se(socket_address_is(&a, "192.168.1.1:8888", SOCK_STREAM)); + assert_se(!socket_address_is(&a, "route", SOCK_STREAM)); + assert_se(!socket_address_is(&a, "192.168.1.1:8888", SOCK_RAW)); +} + +static void test_socket_address_is_netlink(void) { + SocketAddress a; + + log_info("/* %s */", __func__); + + assert_se(socket_address_parse_netlink(&a, "route 10") >= 0); + assert_se(socket_address_is_netlink(&a, "route 10")); + assert_se(!socket_address_is_netlink(&a, "192.168.1.1:8888")); + assert_se(!socket_address_is_netlink(&a, "route 1")); +} + +static void test_in_addr_is_null(void) { + union in_addr_union i = {}; + + log_info("/* %s */", __func__); + + assert_se(in_addr_is_null(AF_INET, &i) == true); + assert_se(in_addr_is_null(AF_INET6, &i) == true); + + i.in.s_addr = 0x1000000; + assert_se(in_addr_is_null(AF_INET, &i) == false); + assert_se(in_addr_is_null(AF_INET6, &i) == false); + + assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT); +} + +static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) { + union in_addr_union ua, ub; + + assert_se(in_addr_from_string(f, a, &ua) >= 0); + assert_se(in_addr_from_string(f, b, &ub) >= 0); + + assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result); +} + +static void test_in_addr_prefix_intersect(void) { + log_info("/* %s */", __func__); + + test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0); + test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1); + test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1); + + test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1); + test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0); + + test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1); + test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1); + test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1); + test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0); + + test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", 128, 0); + test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1); + test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1); + + test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1); + test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0); + + test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1); + test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1); + test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1); + test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0); +} + +static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) { + union in_addr_union ubefore, uafter, t; + + assert_se(in_addr_from_string(f, before, &ubefore) >= 0); + + t = ubefore; + assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after); + + if (after) { + assert_se(in_addr_from_string(f, after, &uafter) >= 0); + assert_se(in_addr_equal(f, &t, &uafter) > 0); + } +} + +static void test_in_addr_prefix_next(void) { + log_info("/* %s */", __func__); + + test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0"); + test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0"); + test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0"); + + test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1"); + test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL); + test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL); + + test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001"); + test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100"); + test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002"); + test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::"); + test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::"); + + test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1"); + + test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL); + test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL); +} + +static void test_in_addr_to_string_one(int f, const char *addr) { + union in_addr_union ua; + _cleanup_free_ char *r = NULL; + + assert_se(in_addr_from_string(f, addr, &ua) >= 0); + assert_se(in_addr_to_string(f, &ua, &r) >= 0); + printf("test_in_addr_to_string_one: %s == %s\n", addr, r); + assert_se(streq(addr, r)); +} + +static void test_in_addr_to_string(void) { + log_info("/* %s */", __func__); + + test_in_addr_to_string_one(AF_INET, "192.168.0.1"); + test_in_addr_to_string_one(AF_INET, "10.11.12.13"); + test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + test_in_addr_to_string_one(AF_INET6, "::1"); + test_in_addr_to_string_one(AF_INET6, "fe80::"); +} + +static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) { + _cleanup_free_ char *r = NULL; + union in_addr_union ua, uuaa; + int ff, ifindex2; + + assert_se(in_addr_from_string(f, a, &ua) >= 0); + assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0); + printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r); + assert_se(streq(b, r)); + + assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0); + assert_se(ff == f); + assert_se(in_addr_equal(f, &ua, &uuaa)); + assert_se(ifindex2 == ifindex || ifindex2 == 0); +} + +static void test_in_addr_ifindex_to_string(void) { + log_info("/* %s */", __func__); + + test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1"); + test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13"); + test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1"); +} + +static void test_in_addr_ifindex_from_string_auto(void) { + int family, ifindex; + union in_addr_union ua; + + log_info("/* %s */", __func__); + /* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */ + + assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0); + assert_se(family == AF_INET6); + assert_se(ifindex == 0); + + assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0); + assert_se(family == AF_INET6); + assert_se(ifindex == 19); + + assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0); + assert_se(family == AF_INET6); + assert_se(ifindex == LOOPBACK_IFINDEX); + + assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV); +} + +static void test_sockaddr_equal(void) { + union sockaddr_union a = { + .in.sin_family = AF_INET, + .in.sin_port = 0, + .in.sin_addr.s_addr = htobe32(INADDR_ANY), + }; + union sockaddr_union b = { + .in.sin_family = AF_INET, + .in.sin_port = 0, + .in.sin_addr.s_addr = htobe32(INADDR_ANY), + }; + union sockaddr_union c = { + .in.sin_family = AF_INET, + .in.sin_port = 0, + .in.sin_addr.s_addr = htobe32(1234), + }; + union sockaddr_union d = { + .in6.sin6_family = AF_INET6, + .in6.sin6_port = 0, + .in6.sin6_addr = IN6ADDR_ANY_INIT, + }; + union sockaddr_union e = { + .vm.svm_family = AF_VSOCK, + .vm.svm_port = 0, + .vm.svm_cid = VMADDR_CID_ANY, + }; + + log_info("/* %s */", __func__); + + assert_se(sockaddr_equal(&a, &a)); + assert_se(sockaddr_equal(&a, &b)); + assert_se(sockaddr_equal(&d, &d)); + assert_se(sockaddr_equal(&e, &e)); + assert_se(!sockaddr_equal(&a, &c)); + assert_se(!sockaddr_equal(&b, &c)); + assert_se(!sockaddr_equal(&a, &e)); +} + +static void test_sockaddr_un_len(void) { + log_info("/* %s */", __func__); + + static const struct sockaddr_un fs = { + .sun_family = AF_UNIX, + .sun_path = "/foo/bar/waldo", + }; + + static const struct sockaddr_un abstract = { + .sun_family = AF_UNIX, + .sun_path = "\0foobar", + }; + + assert_se(SOCKADDR_UN_LEN(fs) == offsetof(struct sockaddr_un, sun_path) + strlen(fs.sun_path) + 1); + assert_se(SOCKADDR_UN_LEN(abstract) == offsetof(struct sockaddr_un, sun_path) + 1 + strlen(abstract.sun_path + 1)); +} + +static void test_in_addr_is_multicast(void) { + union in_addr_union a, b; + int f; + + log_info("/* %s */", __func__); + + assert_se(in_addr_from_string_auto("192.168.3.11", &f, &a) >= 0); + assert_se(in_addr_is_multicast(f, &a) == 0); + + assert_se(in_addr_from_string_auto("224.0.0.1", &f, &a) >= 0); + assert_se(in_addr_is_multicast(f, &a) == 1); + + assert_se(in_addr_from_string_auto("FF01:0:0:0:0:0:0:1", &f, &b) >= 0); + assert_se(in_addr_is_multicast(f, &b) == 1); + + assert_se(in_addr_from_string_auto("2001:db8::c:69b:aeff:fe53:743e", &f, &b) >= 0); + assert_se(in_addr_is_multicast(f, &b) == 0); +} + +static void test_getpeercred_getpeergroups(void) { + int r; + + log_info("/* %s */", __func__); + + r = safe_fork("(getpeercred)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); + assert_se(r >= 0); + + if (r == 0) { + static const gid_t gids[] = { 3, 4, 5, 6, 7 }; + gid_t *test_gids; + size_t n_test_gids; + uid_t test_uid; + gid_t test_gid; + struct ucred ucred; + int pair[2]; + + if (geteuid() == 0) { + test_uid = 1; + test_gid = 2; + test_gids = (gid_t*) gids; + n_test_gids = ELEMENTSOF(gids); + + assert_se(setgroups(n_test_gids, test_gids) >= 0); + assert_se(setresgid(test_gid, test_gid, test_gid) >= 0); + assert_se(setresuid(test_uid, test_uid, test_uid) >= 0); + + } else { + long ngroups_max; + + test_uid = getuid(); + test_gid = getgid(); + + ngroups_max = sysconf(_SC_NGROUPS_MAX); + assert(ngroups_max > 0); + + test_gids = newa(gid_t, ngroups_max); + + r = getgroups(ngroups_max, test_gids); + assert_se(r >= 0); + n_test_gids = (size_t) r; + } + + assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0); + + assert_se(getpeercred(pair[0], &ucred) >= 0); + + assert_se(ucred.uid == test_uid); + assert_se(ucred.gid == test_gid); + assert_se(ucred.pid == getpid_cached()); + + { + _cleanup_free_ gid_t *peer_groups = NULL; + + r = getpeergroups(pair[0], &peer_groups); + assert_se(r >= 0 || IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT)); + + if (r >= 0) { + assert_se((size_t) r == n_test_gids); + assert_se(memcmp(peer_groups, test_gids, sizeof(gid_t) * n_test_gids) == 0); + } + } + + safe_close_pair(pair); + _exit(EXIT_SUCCESS); + } +} + +static void test_passfd_read(void) { + static const char file_contents[] = "test contents for passfd"; + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + int r; + + log_info("/* %s */", __func__); + + assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0); + + r = safe_fork("(passfd_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); + assert_se(r >= 0); + + if (r == 0) { + /* Child */ + char tmpfile[] = "/tmp/test-socket-util-passfd-read-XXXXXX"; + _cleanup_close_ int tmpfd = -1; + + pair[0] = safe_close(pair[0]); + + tmpfd = mkostemp_safe(tmpfile); + assert_se(tmpfd >= 0); + assert_se(write(tmpfd, file_contents, strlen(file_contents)) == (ssize_t) strlen(file_contents)); + tmpfd = safe_close(tmpfd); + + tmpfd = open(tmpfile, O_RDONLY); + assert_se(tmpfd >= 0); + assert_se(unlink(tmpfile) == 0); + + assert_se(send_one_fd(pair[1], tmpfd, MSG_DONTWAIT) == 0); + _exit(EXIT_SUCCESS); + } + + /* Parent */ + char buf[64]; + struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1); + _cleanup_close_ int fd = -1; + + pair[1] = safe_close(pair[1]); + + assert_se(receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd) == 0); + + assert_se(fd >= 0); + r = read(fd, buf, sizeof(buf)-1); + assert_se(r >= 0); + buf[r] = 0; + assert_se(streq(buf, file_contents)); +} + +static void test_passfd_contents_read(void) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + static const char file_contents[] = "test contents in the file"; + static const char wire_contents[] = "test contents on the wire"; + int r; + + log_info("/* %s */", __func__); + + assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0); + + r = safe_fork("(passfd_contents_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); + assert_se(r >= 0); + + if (r == 0) { + /* Child */ + struct iovec iov = IOVEC_INIT_STRING(wire_contents); + char tmpfile[] = "/tmp/test-socket-util-passfd-contents-read-XXXXXX"; + _cleanup_close_ int tmpfd = -1; + + pair[0] = safe_close(pair[0]); + + tmpfd = mkostemp_safe(tmpfile); + assert_se(tmpfd >= 0); + assert_se(write(tmpfd, file_contents, strlen(file_contents)) == (ssize_t) strlen(file_contents)); + tmpfd = safe_close(tmpfd); + + tmpfd = open(tmpfile, O_RDONLY); + assert_se(tmpfd >= 0); + assert_se(unlink(tmpfile) == 0); + + assert_se(send_one_fd_iov(pair[1], tmpfd, &iov, 1, MSG_DONTWAIT) > 0); + _exit(EXIT_SUCCESS); + } + + /* Parent */ + char buf[64]; + struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1); + _cleanup_close_ int fd = -1; + ssize_t k; + + pair[1] = safe_close(pair[1]); + + k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd); + assert_se(k > 0); + buf[k] = 0; + assert_se(streq(buf, wire_contents)); + + assert_se(fd >= 0); + r = read(fd, buf, sizeof(buf)-1); + assert_se(r >= 0); + buf[r] = 0; + assert_se(streq(buf, file_contents)); +} + +static void test_receive_nopassfd(void) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + static const char wire_contents[] = "no fd passed here"; + int r; + + log_info("/* %s */", __func__); + + assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0); + + r = safe_fork("(receive_nopassfd)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); + assert_se(r >= 0); + + if (r == 0) { + /* Child */ + struct iovec iov = IOVEC_INIT_STRING(wire_contents); + + pair[0] = safe_close(pair[0]); + + assert_se(send_one_fd_iov(pair[1], -1, &iov, 1, MSG_DONTWAIT) > 0); + _exit(EXIT_SUCCESS); + } + + /* Parent */ + char buf[64]; + struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1); + int fd = -999; + ssize_t k; + + pair[1] = safe_close(pair[1]); + + k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd); + assert_se(k > 0); + buf[k] = 0; + assert_se(streq(buf, wire_contents)); + + /* no fd passed here, confirm it was reset */ + assert_se(fd == -1); +} + +static void test_send_nodata_nofd(void) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + int r; + + log_info("/* %s */", __func__); + + assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0); + + r = safe_fork("(send_nodata_nofd)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); + assert_se(r >= 0); + + if (r == 0) { + /* Child */ + pair[0] = safe_close(pair[0]); + + assert_se(send_one_fd_iov(pair[1], -1, NULL, 0, MSG_DONTWAIT) == -EINVAL); + _exit(EXIT_SUCCESS); + } + + /* Parent */ + char buf[64]; + struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1); + int fd = -999; + ssize_t k; + + pair[1] = safe_close(pair[1]); + + k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd); + /* recvmsg() will return errno EAGAIN if nothing was sent */ + assert_se(k == -EAGAIN); + + /* receive_one_fd_iov returned error, so confirm &fd wasn't touched */ + assert_se(fd == -999); +} + +static void test_send_emptydata(void) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + int r; + + log_info("/* %s */", __func__); + + assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0); + + r = safe_fork("(send_emptydata)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL); + assert_se(r >= 0); + + if (r == 0) { + /* Child */ + struct iovec iov = IOVEC_INIT_STRING(""); /* zero-length iov */ + assert_se(iov.iov_len == 0); + + pair[0] = safe_close(pair[0]); + + /* This will succeed, since iov is set. */ + assert_se(send_one_fd_iov(pair[1], -1, &iov, 1, MSG_DONTWAIT) == 0); + _exit(EXIT_SUCCESS); + } + + /* Parent */ + char buf[64]; + struct iovec iov = IOVEC_INIT(buf, sizeof(buf)-1); + int fd = -999; + ssize_t k; + + pair[1] = safe_close(pair[1]); + + k = receive_one_fd_iov(pair[0], &iov, 1, MSG_DONTWAIT, &fd); + /* receive_one_fd_iov() returns -EIO if an fd is not found and no data was returned. */ + assert_se(k == -EIO); + + /* receive_one_fd_iov returned error, so confirm &fd wasn't touched */ + assert_se(fd == -999); +} + +static void test_flush_accept(void) { + _cleanup_close_ int listen_stream = -1, listen_dgram = -1, listen_seqpacket = 1, connect_stream = -1, connect_dgram = -1, connect_seqpacket = -1; + static const union sockaddr_union sa = { .un.sun_family = AF_UNIX }; + union sockaddr_union lsa; + socklen_t l; + + listen_stream = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + assert_se(listen_stream >= 0); + + listen_dgram = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + assert_se(listen_dgram >= 0); + + listen_seqpacket = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + assert_se(listen_seqpacket >= 0); + + assert_se(flush_accept(listen_stream) < 0); + assert_se(flush_accept(listen_dgram) < 0); + assert_se(flush_accept(listen_seqpacket) < 0); + + assert_se(bind(listen_stream, &sa.sa, sizeof(sa_family_t)) >= 0); + assert_se(bind(listen_dgram, &sa.sa, sizeof(sa_family_t)) >= 0); + assert_se(bind(listen_seqpacket, &sa.sa, sizeof(sa_family_t)) >= 0); + + assert_se(flush_accept(listen_stream) < 0); + assert_se(flush_accept(listen_dgram) < 0); + assert_se(flush_accept(listen_seqpacket) < 0); + + assert_se(listen(listen_stream, SOMAXCONN) >= 0); + assert_se(listen(listen_dgram, SOMAXCONN) < 0); + assert_se(listen(listen_seqpacket, SOMAXCONN) >= 0); + + assert_se(flush_accept(listen_stream) >= 0); + assert_se(flush_accept(listen_dgram) < 0); + assert_se(flush_accept(listen_seqpacket) >= 0); + + connect_stream = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + assert_se(connect_stream >= 0); + + connect_dgram = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + assert_se(connect_dgram >= 0); + + connect_seqpacket = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + assert_se(connect_seqpacket >= 0); + + l = sizeof(lsa); + assert_se(getsockname(listen_stream, &lsa.sa, &l) >= 0); + assert_se(connect(connect_stream, &lsa.sa, l) >= 0); + + l = sizeof(lsa); + assert_se(getsockname(listen_dgram, &lsa.sa, &l) >= 0); + assert_se(connect(connect_dgram, &lsa.sa, l) >= 0); + + l = sizeof(lsa); + assert_se(getsockname(listen_seqpacket, &lsa.sa, &l) >= 0); + assert_se(connect(connect_seqpacket, &lsa.sa, l) >= 0); + + assert_se(flush_accept(listen_stream) >= 0); + assert_se(flush_accept(listen_dgram) < 0); + assert_se(flush_accept(listen_seqpacket) >= 0); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_ifname_valid(); + + test_socket_address_parse(); + test_socket_print_unix(); + test_socket_address_parse_netlink(); + test_socket_address_equal(); + test_socket_address_get_path(); + test_socket_address_is(); + test_socket_address_is_netlink(); + + test_in_addr_is_null(); + test_in_addr_prefix_intersect(); + test_in_addr_prefix_next(); + test_in_addr_to_string(); + test_in_addr_ifindex_to_string(); + test_in_addr_ifindex_from_string_auto(); + + test_sockaddr_equal(); + + test_sockaddr_un_len(); + + test_in_addr_is_multicast(); + + test_getpeercred_getpeergroups(); + + test_passfd_read(); + test_passfd_contents_read(); + test_receive_nopassfd(); + test_send_nodata_nofd(); + test_send_emptydata(); + test_flush_accept(); + + return 0; +} diff --git a/src/test/test-specifier.c b/src/test/test-specifier.c new file mode 100644 index 00000000..a0ffdf6c --- /dev/null +++ b/src/test/test-specifier.c @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "log.h" +#include "specifier.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" + +static void test_specifier_escape_one(const char *a, const char *b) { + _cleanup_free_ char *x = NULL; + + x = specifier_escape(a); + assert_se(streq_ptr(x, b)); +} + +static void test_specifier_escape(void) { + test_specifier_escape_one(NULL, NULL); + test_specifier_escape_one("", ""); + test_specifier_escape_one("%", "%%"); + test_specifier_escape_one("foo bar", "foo bar"); + test_specifier_escape_one("foo%bar", "foo%%bar"); + test_specifier_escape_one("%%%%%", "%%%%%%%%%%"); +} + +static void test_specifier_escape_strv_one(char **a, char **b) { + _cleanup_strv_free_ char **x = NULL; + + assert_se(specifier_escape_strv(a, &x) >= 0); + assert_se(strv_equal(x, b)); +} + +static void test_specifier_escape_strv(void) { + test_specifier_escape_strv_one(NULL, NULL); + test_specifier_escape_strv_one(STRV_MAKE(NULL), STRV_MAKE(NULL)); + test_specifier_escape_strv_one(STRV_MAKE(""), STRV_MAKE("")); + test_specifier_escape_strv_one(STRV_MAKE("foo"), STRV_MAKE("foo")); + test_specifier_escape_strv_one(STRV_MAKE("%"), STRV_MAKE("%%")); + test_specifier_escape_strv_one(STRV_MAKE("foo", "%", "foo%", "%foo", "foo%foo", "quux", "%%%"), STRV_MAKE("foo", "%%", "foo%%", "%%foo", "foo%%foo", "quux", "%%%%%%")); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_specifier_escape(); + test_specifier_escape_strv(); + + return 0; +} diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c new file mode 100644 index 00000000..9d9dbd4d --- /dev/null +++ b/src/test/test-stat-util.c @@ -0,0 +1,167 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "macro.h" +#include "mountpoint-util.h" +#include "namespace-util.h" +#include "path-util.h" +#include "stat-util.h" +#include "tmpfile-util.h" + +static void test_files_same(void) { + _cleanup_close_ int fd = -1; + char name[] = "/tmp/test-files_same.XXXXXX"; + char name_alias[] = "/tmp/test-files_same.alias"; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(symlink(name, name_alias) >= 0); + + assert_se(files_same(name, name, 0)); + assert_se(files_same(name, name, AT_SYMLINK_NOFOLLOW)); + assert_se(files_same(name, name_alias, 0)); + assert_se(!files_same(name, name_alias, AT_SYMLINK_NOFOLLOW)); + + unlink(name); + unlink(name_alias); +} + +static void test_is_symlink(void) { + char name[] = "/tmp/test-is_symlink.XXXXXX"; + char name_link[] = "/tmp/test-is_symlink.link"; + _cleanup_close_ int fd = -1; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(symlink(name, name_link) >= 0); + + assert_se(is_symlink(name) == 0); + assert_se(is_symlink(name_link) == 1); + assert_se(is_symlink("/a/file/which/does/not/exist/i/guess") < 0); + + unlink(name); + unlink(name_link); +} + +static void test_path_is_fs_type(void) { + /* run might not be a mount point in build chroots */ + if (path_is_mount_point("/run", NULL, AT_SYMLINK_FOLLOW) > 0) { + assert_se(path_is_fs_type("/run", TMPFS_MAGIC) > 0); + assert_se(path_is_fs_type("/run", BTRFS_SUPER_MAGIC) == 0); + } + assert_se(path_is_fs_type("/proc", PROC_SUPER_MAGIC) > 0); + assert_se(path_is_fs_type("/proc", BTRFS_SUPER_MAGIC) == 0); + assert_se(path_is_fs_type("/i-dont-exist", BTRFS_SUPER_MAGIC) == -ENOENT); +} + +static void test_path_is_temporary_fs(void) { + /* run might not be a mount point in build chroots */ + if (path_is_mount_point("/run", NULL, AT_SYMLINK_FOLLOW) > 0) + assert_se(path_is_temporary_fs("/run") > 0); + assert_se(path_is_temporary_fs("/proc") == 0); + assert_se(path_is_temporary_fs("/i-dont-exist") == -ENOENT); +} + +static void test_fd_is_network_ns(void) { + _cleanup_close_ int fd = -1; + assert_se(fd_is_network_ns(STDIN_FILENO) == 0); + assert_se(fd_is_network_ns(STDERR_FILENO) == 0); + assert_se(fd_is_network_ns(STDOUT_FILENO) == 0); + + assert_se((fd = open("/proc/self/ns/mnt", O_CLOEXEC|O_RDONLY)) >= 0); + assert_se(IN_SET(fd_is_network_ns(fd), 0, -EUCLEAN)); + fd = safe_close(fd); + + assert_se((fd = open("/proc/self/ns/net", O_CLOEXEC|O_RDONLY)) >= 0); + assert_se(IN_SET(fd_is_network_ns(fd), 1, -EUCLEAN)); +} + +static void test_device_major_minor_valid(void) { + /* on glibc dev_t is 64bit, even though in the kernel it is only 32bit */ + assert_cc(sizeof(dev_t) == sizeof(uint64_t)); + + assert_se(DEVICE_MAJOR_VALID(0U)); + assert_se(DEVICE_MINOR_VALID(0U)); + + assert_se(DEVICE_MAJOR_VALID(1U)); + assert_se(DEVICE_MINOR_VALID(1U)); + + assert_se(!DEVICE_MAJOR_VALID(-1U)); + assert_se(!DEVICE_MINOR_VALID(-1U)); + + assert_se(DEVICE_MAJOR_VALID(1U << 10)); + assert_se(DEVICE_MINOR_VALID(1U << 10)); + + assert_se(DEVICE_MAJOR_VALID((1U << 12) - 1)); + assert_se(DEVICE_MINOR_VALID((1U << 20) - 1)); + + assert_se(!DEVICE_MAJOR_VALID((1U << 12))); + assert_se(!DEVICE_MINOR_VALID((1U << 20))); + + assert_se(!DEVICE_MAJOR_VALID(1U << 25)); + assert_se(!DEVICE_MINOR_VALID(1U << 25)); + + assert_se(!DEVICE_MAJOR_VALID(UINT32_MAX)); + assert_se(!DEVICE_MINOR_VALID(UINT32_MAX)); + + assert_se(!DEVICE_MAJOR_VALID(UINT64_MAX)); + assert_se(!DEVICE_MINOR_VALID(UINT64_MAX)); + + assert_se(DEVICE_MAJOR_VALID(major(0))); + assert_se(DEVICE_MINOR_VALID(minor(0))); +} + +static void test_device_path_make_canonical_one(const char *path) { + _cleanup_free_ char *resolved = NULL, *raw = NULL; + struct stat st; + dev_t devno; + mode_t mode; + int r; + + assert_se(stat(path, &st) >= 0); + r = device_path_make_canonical(st.st_mode, st.st_rdev, &resolved); + if (r == -ENOENT) /* maybe /dev/char/x:y and /dev/block/x:y are missing in this test environment, because we + * run in a container or so? */ + return; + + assert_se(r >= 0); + assert_se(path_equal(path, resolved)); + + assert_se(device_path_make_major_minor(st.st_mode, st.st_rdev, &raw) >= 0); + assert_se(device_path_parse_major_minor(raw, &mode, &devno) >= 0); + + assert_se(st.st_rdev == devno); + assert_se((st.st_mode & S_IFMT) == (mode & S_IFMT)); +} + +static void test_device_path_make_canonical(void) { + + test_device_path_make_canonical_one("/dev/null"); + test_device_path_make_canonical_one("/dev/zero"); + test_device_path_make_canonical_one("/dev/full"); + test_device_path_make_canonical_one("/dev/random"); + test_device_path_make_canonical_one("/dev/urandom"); + test_device_path_make_canonical_one("/dev/tty"); + + if (is_device_node("/run/systemd/inaccessible/chr") > 0) { + test_device_path_make_canonical_one("/run/systemd/inaccessible/chr"); + test_device_path_make_canonical_one("/run/systemd/inaccessible/blk"); + } +} + +int main(int argc, char *argv[]) { + test_files_same(); + test_is_symlink(); + test_path_is_fs_type(); + test_path_is_temporary_fs(); + test_fd_is_network_ns(); + test_device_major_minor_valid(); + test_device_path_make_canonical(); + + return 0; +} diff --git a/src/test/test-static-destruct.c b/src/test/test-static-destruct.c new file mode 100644 index 00000000..eb0523d8 --- /dev/null +++ b/src/test/test-static-destruct.c @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "static-destruct.h" +#include "tests.h" + +static int foo = 0; +static int bar = 0; +static int baz = 0; +static char* memory = NULL; + +static void test_destroy(int *b) { + (*b)++; +} + +STATIC_DESTRUCTOR_REGISTER(foo, test_destroy); +STATIC_DESTRUCTOR_REGISTER(bar, test_destroy); +STATIC_DESTRUCTOR_REGISTER(bar, test_destroy); +STATIC_DESTRUCTOR_REGISTER(baz, test_destroy); +STATIC_DESTRUCTOR_REGISTER(baz, test_destroy); +STATIC_DESTRUCTOR_REGISTER(baz, test_destroy); +STATIC_DESTRUCTOR_REGISTER(memory, freep); + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + assert_se(memory = strdup("hallo")); + + assert_se(foo == 0 && bar == 0 && baz == 0); + static_destruct(); + assert_se(foo == 1 && bar == 2 && baz == 3); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-strbuf.c b/src/test/test-strbuf.c new file mode 100644 index 00000000..483ba44c --- /dev/null +++ b/src/test/test-strbuf.c @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "strbuf.h" +#include "string-util.h" +#include "strv.h" +#include "util.h" + +static ssize_t add_string(struct strbuf *sb, const char *s) { + return strbuf_add_string(sb, s, strlen(s)); +} + +static void test_strbuf(void) { + _cleanup_(strbuf_cleanupp) struct strbuf *sb; + _cleanup_strv_free_ char **l; + ssize_t a, b, c, d, e, f, g, h; + + sb = strbuf_new(); + + a = add_string(sb, "waldo"); + b = add_string(sb, "foo"); + c = add_string(sb, "bar"); + d = add_string(sb, "waldo"); /* duplicate */ + e = add_string(sb, "aldo"); /* duplicate */ + f = add_string(sb, "do"); /* duplicate */ + g = add_string(sb, "waldorf"); /* not a duplicate: matches from tail */ + h = add_string(sb, ""); + + /* check the content of the buffer directly */ + l = strv_parse_nulstr(sb->buf, sb->len); + + assert_se(streq(l[0], "")); /* root */ + assert_se(streq(l[1], "waldo")); + assert_se(streq(l[2], "foo")); + assert_se(streq(l[3], "bar")); + assert_se(streq(l[4], "waldorf")); + assert_se(l[5] == NULL); + + assert_se(sb->nodes_count == 5); /* root + 4 non-duplicates */ + assert_se(sb->dedup_count == 4); + assert_se(sb->in_count == 8); + + assert_se(sb->in_len == 29); /* length of all strings added */ + assert_se(sb->dedup_len == 11); /* length of all strings duplicated */ + assert_se(sb->len == 23); /* buffer length: in - dedup + \0 for each node */ + + /* check the returned offsets and the respective content in the buffer */ + assert_se(a == 1); + assert_se(b == 7); + assert_se(c == 11); + assert_se(d == 1); + assert_se(e == 2); + assert_se(f == 4); + assert_se(g == 15); + assert_se(h == 0); + + assert_se(streq(sb->buf + a, "waldo")); + assert_se(streq(sb->buf + b, "foo")); + assert_se(streq(sb->buf + c, "bar")); + assert_se(streq(sb->buf + d, "waldo")); + assert_se(streq(sb->buf + e, "aldo")); + assert_se(streq(sb->buf + f, "do")); + assert_se(streq(sb->buf + g, "waldorf")); + assert_se(streq(sb->buf + h, "")); + + strbuf_complete(sb); + assert_se(sb->root == NULL); +} + +int main(int argc, const char *argv[]) { + test_strbuf(); + + return 0; +} diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c new file mode 100644 index 00000000..8ea39943 --- /dev/null +++ b/src/test/test-string-util.c @@ -0,0 +1,576 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "locale-util.h" +#include "macro.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "utf8.h" +#include "util.h" + +static void test_free_and_strndup_one(char **t, const char *src, size_t l, const char *expected, bool change) { + int r; + + log_debug("%s: \"%s\", \"%s\", %zd (expect \"%s\", %s)", + __func__, strnull(*t), strnull(src), l, strnull(expected), yes_no(change)); + + r = free_and_strndup(t, src, l); + assert_se(streq_ptr(*t, expected)); + assert_se(r == change); /* check that change occurs only when necessary */ +} + +static void test_free_and_strndup(void) { + static const struct test_case { + const char *src; + size_t len; + const char *expected; + } cases[] = { + {"abc", 0, ""}, + {"abc", 0, ""}, + {"abc", 1, "a"}, + {"abc", 2, "ab"}, + {"abc", 3, "abc"}, + {"abc", 4, "abc"}, + {"abc", 5, "abc"}, + {"abc", 5, "abc"}, + {"abc", 4, "abc"}, + {"abc", 3, "abc"}, + {"abc", 2, "ab"}, + {"abc", 1, "a"}, + {"abc", 0, ""}, + + {"", 0, ""}, + {"", 1, ""}, + {"", 2, ""}, + {"", 0, ""}, + {"", 1, ""}, + {"", 2, ""}, + {"", 2, ""}, + {"", 1, ""}, + {"", 0, ""}, + + {NULL, 0, NULL}, + + {"foo", 3, "foo"}, + {"foobar", 6, "foobar"}, + }; + + _cleanup_free_ char *t = NULL; + const char *prev_expected = t; + + for (unsigned i = 0; i < ELEMENTSOF(cases); i++) { + test_free_and_strndup_one(&t, + cases[i].src, cases[i].len, cases[i].expected, + !streq_ptr(cases[i].expected, prev_expected)); + prev_expected = t; + } +} + +static void test_ascii_strcasecmp_n(void) { + + assert_se(ascii_strcasecmp_n("", "", 0) == 0); + assert_se(ascii_strcasecmp_n("", "", 1) == 0); + assert_se(ascii_strcasecmp_n("", "a", 1) < 0); + assert_se(ascii_strcasecmp_n("", "a", 2) < 0); + assert_se(ascii_strcasecmp_n("a", "", 1) > 0); + assert_se(ascii_strcasecmp_n("a", "", 2) > 0); + assert_se(ascii_strcasecmp_n("a", "a", 1) == 0); + assert_se(ascii_strcasecmp_n("a", "a", 2) == 0); + assert_se(ascii_strcasecmp_n("a", "b", 1) < 0); + assert_se(ascii_strcasecmp_n("a", "b", 2) < 0); + assert_se(ascii_strcasecmp_n("b", "a", 1) > 0); + assert_se(ascii_strcasecmp_n("b", "a", 2) > 0); + assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxYxxxx", 9) == 0); + assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxyxxxx", 9) < 0); + assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxyxxxx", 9) < 0); + assert_se(ascii_strcasecmp_n("xxxxxxxxx", "xxxxYxxxx", 9) < 0); + assert_se(ascii_strcasecmp_n("xxxxXxxxx", "xxxxYxxxx", 9) < 0); + + assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxYxxxx", 9) == 0); + assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxxxxxx", 9) > 0); + assert_se(ascii_strcasecmp_n("xxxxyxxxx", "xxxxXxxxx", 9) > 0); + assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxxxxxx", 9) > 0); + assert_se(ascii_strcasecmp_n("xxxxYxxxx", "xxxxXxxxx", 9) > 0); +} + +static void test_ascii_strcasecmp_nn(void) { + assert_se(ascii_strcasecmp_nn("", 0, "", 0) == 0); + assert_se(ascii_strcasecmp_nn("", 0, "", 1) < 0); + assert_se(ascii_strcasecmp_nn("", 1, "", 0) > 0); + assert_se(ascii_strcasecmp_nn("", 1, "", 1) == 0); + + assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaAa", 4) == 0); + assert_se(ascii_strcasecmp_nn("aaa", 3, "aaAa", 4) < 0); + assert_se(ascii_strcasecmp_nn("aaa", 4, "aaAa", 4) < 0); + assert_se(ascii_strcasecmp_nn("aaaa", 4, "aaA", 3) > 0); + assert_se(ascii_strcasecmp_nn("aaaa", 4, "AAA", 4) > 0); + + assert_se(ascii_strcasecmp_nn("aaaa", 4, "bbbb", 4) < 0); + assert_se(ascii_strcasecmp_nn("aaAA", 4, "BBbb", 4) < 0); + assert_se(ascii_strcasecmp_nn("BBbb", 4, "aaaa", 4) > 0); +} + +static void test_cellescape(void) { + char buf[40]; + + assert_se(streq(cellescape(buf, 1, ""), "")); + assert_se(streq(cellescape(buf, 1, "1"), "")); + assert_se(streq(cellescape(buf, 1, "12"), "")); + + assert_se(streq(cellescape(buf, 2, ""), "")); + assert_se(streq(cellescape(buf, 2, "1"), "1")); + assert_se(streq(cellescape(buf, 2, "12"), ".")); + assert_se(streq(cellescape(buf, 2, "123"), ".")); + + assert_se(streq(cellescape(buf, 3, ""), "")); + assert_se(streq(cellescape(buf, 3, "1"), "1")); + assert_se(streq(cellescape(buf, 3, "12"), "12")); + assert_se(streq(cellescape(buf, 3, "123"), "..")); + assert_se(streq(cellescape(buf, 3, "1234"), "..")); + + assert_se(streq(cellescape(buf, 4, ""), "")); + assert_se(streq(cellescape(buf, 4, "1"), "1")); + assert_se(streq(cellescape(buf, 4, "12"), "12")); + assert_se(streq(cellescape(buf, 4, "123"), "123")); + assert_se(streq(cellescape(buf, 4, "1234"), is_locale_utf8() ? "…" : "...")); + assert_se(streq(cellescape(buf, 4, "12345"), is_locale_utf8() ? "…" : "...")); + + assert_se(streq(cellescape(buf, 5, ""), "")); + assert_se(streq(cellescape(buf, 5, "1"), "1")); + assert_se(streq(cellescape(buf, 5, "12"), "12")); + assert_se(streq(cellescape(buf, 5, "123"), "123")); + assert_se(streq(cellescape(buf, 5, "1234"), "1234")); + assert_se(streq(cellescape(buf, 5, "12345"), is_locale_utf8() ? "1…" : "1...")); + assert_se(streq(cellescape(buf, 5, "123456"), is_locale_utf8() ? "1…" : "1...")); + + assert_se(streq(cellescape(buf, 1, "\020"), "")); + assert_se(streq(cellescape(buf, 2, "\020"), ".")); + assert_se(streq(cellescape(buf, 3, "\020"), "..")); + assert_se(streq(cellescape(buf, 4, "\020"), "…")); + assert_se(streq(cellescape(buf, 5, "\020"), "\\020")); + + assert_se(streq(cellescape(buf, 5, "1234\020"), "1…")); + assert_se(streq(cellescape(buf, 6, "1234\020"), "12…")); + assert_se(streq(cellescape(buf, 7, "1234\020"), "123…")); + assert_se(streq(cellescape(buf, 8, "1234\020"), "1234…")); + assert_se(streq(cellescape(buf, 9, "1234\020"), "1234\\020")); + + assert_se(streq(cellescape(buf, 1, "\t\n"), "")); + assert_se(streq(cellescape(buf, 2, "\t\n"), ".")); + assert_se(streq(cellescape(buf, 3, "\t\n"), "..")); + assert_se(streq(cellescape(buf, 4, "\t\n"), "…")); + assert_se(streq(cellescape(buf, 5, "\t\n"), "\\t\\n")); + + assert_se(streq(cellescape(buf, 5, "1234\t\n"), "1…")); + assert_se(streq(cellescape(buf, 6, "1234\t\n"), "12…")); + assert_se(streq(cellescape(buf, 7, "1234\t\n"), "123…")); + assert_se(streq(cellescape(buf, 8, "1234\t\n"), "1234…")); + assert_se(streq(cellescape(buf, 9, "1234\t\n"), "1234\\t\\n")); + + assert_se(streq(cellescape(buf, 4, "x\t\020\n"), "…")); + assert_se(streq(cellescape(buf, 5, "x\t\020\n"), "x…")); + assert_se(streq(cellescape(buf, 6, "x\t\020\n"), "x…")); + assert_se(streq(cellescape(buf, 7, "x\t\020\n"), "x\\t…")); + assert_se(streq(cellescape(buf, 8, "x\t\020\n"), "x\\t…")); + assert_se(streq(cellescape(buf, 9, "x\t\020\n"), "x\\t…")); + assert_se(streq(cellescape(buf, 10, "x\t\020\n"), "x\\t\\020\\n")); + + assert_se(streq(cellescape(buf, 6, "1\011"), "1\\t")); + assert_se(streq(cellescape(buf, 6, "1\020"), "1\\020")); + assert_se(streq(cellescape(buf, 6, "1\020x"), is_locale_utf8() ? "1…" : "1...")); + + assert_se(streq(cellescape(buf, 40, "1\020"), "1\\020")); + assert_se(streq(cellescape(buf, 40, "1\020x"), "1\\020x")); + + assert_se(streq(cellescape(buf, 40, "\a\b\f\n\r\t\v\\\"'"), "\\a\\b\\f\\n\\r\\t\\v\\\\\\\"\\'")); + assert_se(streq(cellescape(buf, 6, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a...")); + assert_se(streq(cellescape(buf, 7, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a…" : "\\a...")); + assert_se(streq(cellescape(buf, 8, "\a\b\f\n\r\t\v\\\"'"), is_locale_utf8() ? "\\a\\b…" : "\\a\\b...")); + + assert_se(streq(cellescape(buf, sizeof buf, "1\020"), "1\\020")); + assert_se(streq(cellescape(buf, sizeof buf, "1\020x"), "1\\020x")); +} + +static void test_streq_ptr(void) { + assert_se(streq_ptr(NULL, NULL)); + assert_se(!streq_ptr("abc", "cdef")); +} + +static void test_strstrip(void) { + char *r; + char input[] = " hello, waldo. "; + + r = strstrip(input); + assert_se(streq(r, "hello, waldo.")); +} + +static void test_strextend(void) { + _cleanup_free_ char *str = NULL; + + assert_se(strextend(&str, NULL)); + assert_se(streq_ptr(str, "")); + assert_se(strextend(&str, "", "0", "", "", "123", NULL)); + assert_se(streq_ptr(str, "0123")); + assert_se(strextend(&str, "456", "78", "9", NULL)); + assert_se(streq_ptr(str, "0123456789")); +} + +static void test_strextend_with_separator(void) { + _cleanup_free_ char *str = NULL; + + assert_se(strextend_with_separator(&str, NULL, NULL)); + assert_se(streq_ptr(str, "")); + str = mfree(str); + + assert_se(strextend_with_separator(&str, "...", NULL)); + assert_se(streq_ptr(str, "")); + assert_se(strextend_with_separator(&str, "...", NULL)); + assert_se(streq_ptr(str, "")); + str = mfree(str); + + assert_se(strextend_with_separator(&str, "xyz", "a", "bb", "ccc", NULL)); + assert_se(streq_ptr(str, "axyzbbxyzccc")); + str = mfree(str); + + assert_se(strextend_with_separator(&str, ",", "start", "", "1", "234", NULL)); + assert_se(streq_ptr(str, "start,,1,234")); + assert_se(strextend_with_separator(&str, ";", "more", "5", "678", NULL)); + assert_se(streq_ptr(str, "start,,1,234;more;5;678")); +} + +static void test_strrep(void) { + _cleanup_free_ char *one, *three, *zero; + one = strrep("waldo", 1); + three = strrep("waldo", 3); + zero = strrep("waldo", 0); + + assert_se(streq(one, "waldo")); + assert_se(streq(three, "waldowaldowaldo")); + assert_se(streq(zero, "")); +} + +static void test_string_has_cc(void) { + assert_se(string_has_cc("abc\1", NULL)); + assert_se(string_has_cc("abc\x7f", NULL)); + assert_se(string_has_cc("abc\x7f", NULL)); + assert_se(string_has_cc("abc\t\x7f", "\t")); + assert_se(string_has_cc("abc\t\x7f", "\t")); + assert_se(string_has_cc("\x7f", "\t")); + assert_se(string_has_cc("\x7f", "\t\a")); + + assert_se(!string_has_cc("abc\t\t", "\t")); + assert_se(!string_has_cc("abc\t\t\a", "\t\a")); + assert_se(!string_has_cc("a\ab\tc", "\t\a")); +} + +static void test_ascii_strlower(void) { + char a[] = "AabBcC Jk Ii Od LKJJJ kkd LK"; + assert_se(streq(ascii_strlower(a), "aabbcc jk ii od lkjjj kkd lk")); +} + +static void test_strshorten(void) { + char s[] = "foobar"; + + assert_se(strlen(strshorten(s, 6)) == 6); + assert_se(strlen(strshorten(s, 12)) == 6); + assert_se(strlen(strshorten(s, 2)) == 2); + assert_se(strlen(strshorten(s, 0)) == 0); +} + +static void test_strjoina(void) { + char *actual; + + actual = strjoina("", "foo", "bar"); + assert_se(streq(actual, "foobar")); + + actual = strjoina("foo", "bar", "baz"); + assert_se(streq(actual, "foobarbaz")); + + actual = strjoina("foo", "", "bar", "baz"); + assert_se(streq(actual, "foobarbaz")); + + actual = strjoina("foo"); + assert_se(streq(actual, "foo")); + + actual = strjoina(NULL); + assert_se(streq(actual, "")); + + actual = strjoina(NULL, "foo"); + assert_se(streq(actual, "")); + + actual = strjoina("foo", NULL, "bar"); + assert_se(streq(actual, "foo")); +} + +static void test_strcmp_ptr(void) { + assert_se(strcmp_ptr(NULL, NULL) == 0); + assert_se(strcmp_ptr("", NULL) > 0); + assert_se(strcmp_ptr("foo", NULL) > 0); + assert_se(strcmp_ptr(NULL, "") < 0); + assert_se(strcmp_ptr(NULL, "bar") < 0); + assert_se(strcmp_ptr("foo", "bar") > 0); + assert_se(strcmp_ptr("bar", "baz") < 0); + assert_se(strcmp_ptr("foo", "foo") == 0); + assert_se(strcmp_ptr("", "") == 0); +} + +static void test_foreach_word(void) { + const char *word, *state; + size_t l; + int i = 0; + const char test[] = "test abc d\te f "; + const char * const expected[] = { + "test", + "abc", + "d", + "e", + "f", + "", + NULL + }; + + FOREACH_WORD(word, l, test, state) + assert_se(strneq(expected[i++], word, l)); +} + +static void check(const char *test, char** expected, bool trailing) { + int i = 0, r; + + printf("<<<%s>>>\n", test); + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&test, &word, NULL, EXTRACT_UNQUOTE); + if (r == 0) { + assert_se(!trailing); + break; + } else if (r < 0) { + assert_se(trailing); + break; + } + + assert_se(streq(word, expected[i++])); + printf("<%s>\n", word); + } + assert_se(expected[i] == NULL); +} + +static void test_foreach_word_quoted(void) { + check("test a b c 'd' e '' '' hhh '' '' \"a b c\"", + STRV_MAKE("test", + "a", + "b", + "c", + "d", + "e", + "", + "", + "hhh", + "", + "", + "a b c"), + false); + + check("test \"xxx", + STRV_MAKE("test"), + true); + + check("test\\", + STRV_MAKE_EMPTY, + true); +} + +static void test_endswith(void) { + assert_se(endswith("foobar", "bar")); + assert_se(endswith("foobar", "")); + assert_se(endswith("foobar", "foobar")); + assert_se(endswith("", "")); + + assert_se(!endswith("foobar", "foo")); + assert_se(!endswith("foobar", "foobarfoofoo")); +} + +static void test_endswith_no_case(void) { + assert_se(endswith_no_case("fooBAR", "bar")); + assert_se(endswith_no_case("foobar", "")); + assert_se(endswith_no_case("foobar", "FOOBAR")); + assert_se(endswith_no_case("", "")); + + assert_se(!endswith_no_case("foobar", "FOO")); + assert_se(!endswith_no_case("foobar", "FOOBARFOOFOO")); +} + +static void test_delete_chars(void) { + char *s, input[] = " hello, waldo. abc"; + + s = delete_chars(input, WHITESPACE); + assert_se(streq(s, "hello,waldo.abc")); + assert_se(s == input); +} + +static void test_delete_trailing_chars(void) { + + char *s, + input1[] = " \n \r k \n \r ", + input2[] = "kkkkthiskkkiskkkaktestkkk", + input3[] = "abcdef"; + + s = delete_trailing_chars(input1, WHITESPACE); + assert_se(streq(s, " \n \r k")); + assert_se(s == input1); + + s = delete_trailing_chars(input2, "kt"); + assert_se(streq(s, "kkkkthiskkkiskkkaktes")); + assert_se(s == input2); + + s = delete_trailing_chars(input3, WHITESPACE); + assert_se(streq(s, "abcdef")); + assert_se(s == input3); + + s = delete_trailing_chars(input3, "fe"); + assert_se(streq(s, "abcd")); + assert_se(s == input3); +} + +static void test_delete_trailing_slashes(void) { + char s1[] = "foobar//", + s2[] = "foobar/", + s3[] = "foobar", + s4[] = ""; + + assert_se(streq(delete_trailing_chars(s1, "_"), "foobar//")); + assert_se(streq(delete_trailing_chars(s1, "/"), "foobar")); + assert_se(streq(delete_trailing_chars(s2, "/"), "foobar")); + assert_se(streq(delete_trailing_chars(s3, "/"), "foobar")); + assert_se(streq(delete_trailing_chars(s4, "/"), "")); +} + +static void test_skip_leading_chars(void) { + char input1[] = " \n \r k \n \r ", + input2[] = "kkkkthiskkkiskkkaktestkkk", + input3[] = "abcdef"; + + assert_se(streq(skip_leading_chars(input1, WHITESPACE), "k \n \r ")); + assert_se(streq(skip_leading_chars(input2, "k"), "thiskkkiskkkaktestkkk")); + assert_se(streq(skip_leading_chars(input2, "tk"), "hiskkkiskkkaktestkkk")); + assert_se(streq(skip_leading_chars(input3, WHITESPACE), "abcdef")); + assert_se(streq(skip_leading_chars(input3, "bcaef"), "def")); +} + +static void test_in_charset(void) { + assert_se(in_charset("dddaaabbbcccc", "abcd")); + assert_se(!in_charset("dddaaabbbcccc", "abc f")); +} + +static void test_split_pair(void) { + _cleanup_free_ char *a = NULL, *b = NULL; + + assert_se(split_pair("", "", &a, &b) == -EINVAL); + assert_se(split_pair("foo=bar", "", &a, &b) == -EINVAL); + assert_se(split_pair("", "=", &a, &b) == -EINVAL); + assert_se(split_pair("foo=bar", "=", &a, &b) >= 0); + assert_se(streq(a, "foo")); + assert_se(streq(b, "bar")); + free(a); + free(b); + assert_se(split_pair("==", "==", &a, &b) >= 0); + assert_se(streq(a, "")); + assert_se(streq(b, "")); + free(a); + free(b); + + assert_se(split_pair("===", "==", &a, &b) >= 0); + assert_se(streq(a, "")); + assert_se(streq(b, "=")); +} + +static void test_first_word(void) { + assert_se(first_word("Hello", "")); + assert_se(first_word("Hello", "Hello")); + assert_se(first_word("Hello world", "Hello")); + assert_se(first_word("Hello\tworld", "Hello")); + assert_se(first_word("Hello\nworld", "Hello")); + assert_se(first_word("Hello\rworld", "Hello")); + assert_se(first_word("Hello ", "Hello")); + + assert_se(!first_word("Hello", "Hellooo")); + assert_se(!first_word("Hello", "xxxxx")); + assert_se(!first_word("Hellooo", "Hello")); +} + +static void test_strlen_ptr(void) { + assert_se(strlen_ptr("foo") == 3); + assert_se(strlen_ptr("") == 0); + assert_se(strlen_ptr(NULL) == 0); +} + +static void test_memory_startswith(void) { + assert_se(streq(memory_startswith("", 0, ""), "")); + assert_se(streq(memory_startswith("", 1, ""), "")); + assert_se(streq(memory_startswith("x", 2, ""), "x")); + assert_se(!memory_startswith("", 1, "x")); + assert_se(!memory_startswith("", 1, "xxxxxxxx")); + assert_se(streq(memory_startswith("xxx", 4, "x"), "xx")); + assert_se(streq(memory_startswith("xxx", 4, "xx"), "x")); + assert_se(streq(memory_startswith("xxx", 4, "xxx"), "")); + assert_se(!memory_startswith("xxx", 4, "xxxx")); +} + +static void test_memory_startswith_no_case(void) { + assert_se(streq(memory_startswith_no_case("", 0, ""), "")); + assert_se(streq(memory_startswith_no_case("", 1, ""), "")); + assert_se(streq(memory_startswith_no_case("x", 2, ""), "x")); + assert_se(streq(memory_startswith_no_case("X", 2, ""), "X")); + assert_se(!memory_startswith_no_case("", 1, "X")); + assert_se(!memory_startswith_no_case("", 1, "xxxxXXXX")); + assert_se(streq(memory_startswith_no_case("xxx", 4, "X"), "xx")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "x"), "XX")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "X"), "XX")); + assert_se(streq(memory_startswith_no_case("xxx", 4, "XX"), "x")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "xx"), "X")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "XX"), "X")); + assert_se(streq(memory_startswith_no_case("xxx", 4, "XXX"), "")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "xxx"), "")); + assert_se(streq(memory_startswith_no_case("XXX", 4, "XXX"), "")); + + assert_se(memory_startswith_no_case((char[2]){'x', 'x'}, 2, "xx")); + assert_se(memory_startswith_no_case((char[2]){'x', 'X'}, 2, "xX")); + assert_se(memory_startswith_no_case((char[2]){'X', 'x'}, 2, "Xx")); + assert_se(memory_startswith_no_case((char[2]){'X', 'X'}, 2, "XX")); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_DEBUG); + + test_free_and_strndup(); + test_ascii_strcasecmp_n(); + test_ascii_strcasecmp_nn(); + test_cellescape(); + test_streq_ptr(); + test_strstrip(); + test_strextend(); + test_strextend_with_separator(); + test_strrep(); + test_string_has_cc(); + test_ascii_strlower(); + test_strshorten(); + test_strjoina(); + test_strcmp_ptr(); + test_foreach_word(); + test_foreach_word_quoted(); + test_endswith(); + test_endswith_no_case(); + test_delete_chars(); + test_delete_trailing_chars(); + test_delete_trailing_slashes(); + test_skip_leading_chars(); + test_in_charset(); + test_split_pair(); + test_first_word(); + test_strlen_ptr(); + test_memory_startswith(); + test_memory_startswith_no_case(); + + return 0; +} diff --git a/src/test/test-strip-tab-ansi.c b/src/test/test-strip-tab-ansi.c new file mode 100644 index 00000000..8e305f37 --- /dev/null +++ b/src/test/test-strip-tab-ansi.c @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "pretty-print.h" +#include "string-util.h" +#include "terminal-util.h" +#include "util.h" + +int main(int argc, char *argv[]) { + _cleanup_free_ char *urlified = NULL, *q = NULL, *qq = NULL; + char *p, *z; + + assert_se(p = strdup("\tFoobar\tbar\twaldo\t")); + assert_se(strip_tab_ansi(&p, NULL, NULL)); + fprintf(stdout, "<%s>\n", p); + assert_se(streq(p, " Foobar bar waldo ")); + free(p); + + assert_se(p = strdup(ANSI_HIGHLIGHT "Hello" ANSI_NORMAL ANSI_HIGHLIGHT_RED " world!" ANSI_NORMAL)); + assert_se(strip_tab_ansi(&p, NULL, NULL)); + fprintf(stdout, "<%s>\n", p); + assert_se(streq(p, "Hello world!")); + free(p); + + assert_se(p = strdup("\x1B[\x1B[\t\x1B[" ANSI_HIGHLIGHT "\x1B[" "Hello" ANSI_NORMAL ANSI_HIGHLIGHT_RED " world!" ANSI_NORMAL)); + assert_se(strip_tab_ansi(&p, NULL, NULL)); + assert_se(streq(p, "\x1B[\x1B[ \x1B[\x1B[Hello world!")); + free(p); + + assert_se(p = strdup("\x1B[waldo")); + assert_se(strip_tab_ansi(&p, NULL, NULL)); + assert_se(streq(p, "\x1B[waldo")); + free(p); + + assert_se(p = strdup("\r\rwaldo")); + assert_se(strip_tab_ansi(&p, NULL, NULL)); + assert_se(streq(p, "\r\rwaldo")); + free(p); + + assert_se(p = strdup("waldo\r\r")); + assert_se(strip_tab_ansi(&p, NULL, NULL)); + assert_se(streq(p, "waldo")); + free(p); + + assert_se(p = strdup("waldo\r\r\n\r\n")); + assert_se(strip_tab_ansi(&p, NULL, NULL)); + assert_se(streq(p, "waldo\n\n")); + free(p); + + assert_se(terminal_urlify_path("/etc/fstab", "i am a fabulous link", &urlified) >= 0); + assert_se(p = strjoin("something ", urlified, " something-else")); + assert_se(q = strdup(p)); + printf("<%s>\n", p); + assert_se(strip_tab_ansi(&p, NULL, NULL)); + printf("<%s>\n", p); + assert_se(streq(p, "something i am a fabulous link something-else")); + p = mfree(p); + + /* Truncate the formatted string in the middle of an ANSI sequence (in which case we shouldn't touch the + * incomplete sequence) */ + z = strstr(q, "fstab"); + if (z) { + *z = 0; + assert_se(qq = strdup(q)); + assert_se(strip_tab_ansi(&q, NULL, NULL)); + assert_se(streq(q, qq)); + } + + return 0; +} diff --git a/src/test/test-strv.c b/src/test/test-strv.c new file mode 100644 index 00000000..f31ea6f8 --- /dev/null +++ b/src/test/test-strv.c @@ -0,0 +1,1004 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "escape.h" +#include "nulstr-util.h" +#include "specifier.h" +#include "string-util.h" +#include "strv.h" + +static void test_specifier_printf(void) { + static const Specifier table[] = { + { 'a', specifier_string, (char*) "AAAA" }, + { 'b', specifier_string, (char*) "BBBB" }, + { 'm', specifier_machine_id, NULL }, + { 'B', specifier_boot_id, NULL }, + { 'H', specifier_host_name, NULL }, + { 'v', specifier_kernel_release, NULL }, + {} + }; + + _cleanup_free_ char *w = NULL; + int r; + + log_info("/* %s */", __func__); + + r = specifier_printf("xxx a=%a b=%b yyy", table, NULL, &w); + assert_se(r >= 0); + assert_se(w); + + puts(w); + assert_se(streq(w, "xxx a=AAAA b=BBBB yyy")); + + free(w); + r = specifier_printf("machine=%m, boot=%B, host=%H, version=%v", table, NULL, &w); + assert_se(r >= 0); + assert_se(w); + puts(w); +} + +static void test_str_in_set(void) { + log_info("/* %s */", __func__); + + assert_se(STR_IN_SET("x", "x", "y", "z")); + assert_se(!STR_IN_SET("X", "x", "y", "z")); + assert_se(!STR_IN_SET("", "x", "y", "z")); + assert_se(STR_IN_SET("x", "w", "x")); +} + +static void test_strptr_in_set(void) { + log_info("/* %s */", __func__); + + assert_se(STRPTR_IN_SET("x", "x", "y", "z")); + assert_se(!STRPTR_IN_SET("X", "x", "y", "z")); + assert_se(!STRPTR_IN_SET("", "x", "y", "z")); + assert_se(STRPTR_IN_SET("x", "w", "x")); + + assert_se(!STRPTR_IN_SET(NULL, "x", "y", "z")); + assert_se(!STRPTR_IN_SET(NULL, "")); + /* strv cannot contain a null, hence the result below */ + assert_se(!STRPTR_IN_SET(NULL, NULL)); +} + +static void test_startswith_set(void) { + log_info("/* %s */", __func__); + + assert_se(!STARTSWITH_SET("foo", "bar", "baz", "waldo")); + assert_se(!STARTSWITH_SET("foo", "bar")); + + assert_se(STARTSWITH_SET("abc", "a", "ab", "abc")); + assert_se(STARTSWITH_SET("abc", "ax", "ab", "abc")); + assert_se(STARTSWITH_SET("abc", "ax", "abx", "abc")); + assert_se(!STARTSWITH_SET("abc", "ax", "abx", "abcx")); + + assert_se(streq_ptr(STARTSWITH_SET("foobar", "hhh", "kkk", "foo", "zzz"), "bar")); + assert_se(streq_ptr(STARTSWITH_SET("foobar", "hhh", "kkk", "", "zzz"), "foobar")); + assert_se(streq_ptr(STARTSWITH_SET("", "hhh", "kkk", "zzz", ""), "")); +} + +static const char* const input_table_multiple[] = { + "one", + "two", + "three", + NULL, +}; + +static const char* const input_table_quoted[] = { + "one", + " two\t three ", + " four five", + NULL, +}; + +static const char* const input_table_one[] = { + "one", + NULL, +}; + +static const char* const input_table_none[] = { + NULL, +}; + +static const char* const input_table_two_empties[] = { + "", + "", + NULL, +}; + +static const char* const input_table_one_empty[] = { + "", + NULL, +}; + +static void test_strv_find(void) { + log_info("/* %s */", __func__); + + assert_se(strv_find((char **)input_table_multiple, "three")); + assert_se(!strv_find((char **)input_table_multiple, "four")); +} + +static void test_strv_find_prefix(void) { + log_info("/* %s */", __func__); + + assert_se(strv_find_prefix((char **)input_table_multiple, "o")); + assert_se(strv_find_prefix((char **)input_table_multiple, "one")); + assert_se(strv_find_prefix((char **)input_table_multiple, "")); + assert_se(!strv_find_prefix((char **)input_table_multiple, "xxx")); + assert_se(!strv_find_prefix((char **)input_table_multiple, "onee")); +} + +static void test_strv_find_startswith(void) { + char *r; + + log_info("/* %s */", __func__); + + r = strv_find_startswith((char **)input_table_multiple, "o"); + assert_se(r && streq(r, "ne")); + + r = strv_find_startswith((char **)input_table_multiple, "one"); + assert_se(r && streq(r, "")); + + r = strv_find_startswith((char **)input_table_multiple, ""); + assert_se(r && streq(r, "one")); + + assert_se(!strv_find_startswith((char **)input_table_multiple, "xxx")); + assert_se(!strv_find_startswith((char **)input_table_multiple, "onee")); +} + +static void test_strv_join(void) { + _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL; + + log_info("/* %s */", __func__); + + p = strv_join((char **)input_table_multiple, ", "); + assert_se(p); + assert_se(streq(p, "one, two, three")); + + q = strv_join((char **)input_table_multiple, ";"); + assert_se(q); + assert_se(streq(q, "one;two;three")); + + r = strv_join((char **)input_table_multiple, NULL); + assert_se(r); + assert_se(streq(r, "one two three")); + + s = strv_join((char **)input_table_one, ", "); + assert_se(s); + assert_se(streq(s, "one")); + + t = strv_join((char **)input_table_none, ", "); + assert_se(t); + assert_se(streq(t, "")); + + v = strv_join((char **)input_table_two_empties, ", "); + assert_se(v); + assert_se(streq(v, ", ")); + + w = strv_join((char **)input_table_one_empty, ", "); + assert_se(w); + assert_se(streq(w, "")); +} + +static void test_strv_join_prefix(void) { + _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL; + + log_info("/* %s */", __func__); + + p = strv_join_prefix((char **)input_table_multiple, ", ", "foo"); + assert_se(p); + assert_se(streq(p, "fooone, footwo, foothree")); + + q = strv_join_prefix((char **)input_table_multiple, ";", "foo"); + assert_se(q); + assert_se(streq(q, "fooone;footwo;foothree")); + + r = strv_join_prefix((char **)input_table_multiple, NULL, "foo"); + assert_se(r); + assert_se(streq(r, "fooone footwo foothree")); + + s = strv_join_prefix((char **)input_table_one, ", ", "foo"); + assert_se(s); + assert_se(streq(s, "fooone")); + + t = strv_join_prefix((char **)input_table_none, ", ", "foo"); + assert_se(t); + assert_se(streq(t, "")); + + v = strv_join_prefix((char **)input_table_two_empties, ", ", "foo"); + assert_se(v); + assert_se(streq(v, "foo, foo")); + + w = strv_join_prefix((char **)input_table_one_empty, ", ", "foo"); + assert_se(w); + assert_se(streq(w, "foo")); +} + +static void test_strv_unquote(const char *quoted, char **list) { + _cleanup_strv_free_ char **s; + _cleanup_free_ char *j; + unsigned i = 0; + char **t; + int r; + + log_info("/* %s */", __func__); + + r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE); + assert_se(r == (int) strv_length(list)); + assert_se(s); + j = strv_join(s, " | "); + assert_se(j); + puts(j); + + STRV_FOREACH(t, s) + assert_se(streq(list[i++], *t)); + + assert_se(list[i] == NULL); +} + +static void test_invalid_unquote(const char *quoted) { + char **s = NULL; + int r; + + log_info("/* %s */", __func__); + + r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE); + assert_se(s == NULL); + assert_se(r == -EINVAL); +} + +static void test_strv_split(void) { + _cleanup_(strv_free_erasep) char **l = NULL; + const char str[] = "one,two,three"; + + log_info("/* %s */", __func__); + + l = strv_split(str, ","); + assert_se(l); + assert_se(strv_equal(l, (char**) input_table_multiple)); + + strv_free_erase(l); + + l = strv_split(" one two\t three", WHITESPACE); + assert_se(l); + assert_se(strv_equal(l, (char**) input_table_multiple)); + + strv_free_erase(l); + + /* Setting NULL for separator is equivalent to WHITESPACE */ + l = strv_split(" one two\t three", NULL); + assert_se(l); + assert_se(strv_equal(l, (char**) input_table_multiple)); + + strv_free_erase(l); + + l = strv_split_full(" one two\t three", NULL, 0); + assert_se(l); + assert_se(strv_equal(l, (char**) input_table_multiple)); + + strv_free_erase(l); + + l = strv_split_full(" 'one' \" two\t three \" ' four five'", NULL, SPLIT_QUOTES); + assert_se(l); + assert_se(strv_equal(l, (char**) input_table_quoted)); + + strv_free_erase(l); + + /* missing last quote ignores the last element. */ + l = strv_split_full(" 'one' \" two\t three \" ' four five' ' ignored element ", NULL, SPLIT_QUOTES); + assert_se(l); + assert_se(strv_equal(l, (char**) input_table_quoted)); + + strv_free_erase(l); + + /* missing last quote, but the last element is _not_ ignored with SPLIT_RELAX. */ + l = strv_split_full(" 'one' \" two\t three \" ' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX); + assert_se(l); + assert_se(strv_equal(l, (char**) input_table_quoted)); + + strv_free_erase(l); + + /* missing separator between */ + l = strv_split_full(" 'one' \" two\t three \"' four five'", NULL, SPLIT_QUOTES | SPLIT_RELAX); + assert_se(l); + assert_se(strv_equal(l, (char**) input_table_quoted)); + + strv_free_erase(l); + + l = strv_split_full(" 'one' \" two\t three \"' four five", NULL, SPLIT_QUOTES | SPLIT_RELAX); + assert_se(l); + assert_se(strv_equal(l, (char**) input_table_quoted)); +} + +static void test_strv_split_empty(void) { + _cleanup_strv_free_ char **l = NULL; + + log_info("/* %s */", __func__); + + l = strv_split("", WHITESPACE); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split("", NULL); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split_full("", NULL, 0); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split_full("", NULL, SPLIT_QUOTES); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split_full("", WHITESPACE, SPLIT_QUOTES); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split_full("", WHITESPACE, SPLIT_QUOTES | SPLIT_RELAX); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split(" ", WHITESPACE); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split(" ", NULL); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split_full(" ", NULL, 0); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split_full(" ", WHITESPACE, SPLIT_QUOTES); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split_full(" ", NULL, SPLIT_QUOTES); + assert_se(l); + assert_se(strv_isempty(l)); + + strv_free(l); + l = strv_split_full(" ", NULL, SPLIT_QUOTES | SPLIT_RELAX); + assert_se(l); + assert_se(strv_isempty(l)); +} + +static void test_strv_split_extract(void) { + _cleanup_strv_free_ char **l = NULL; + const char *str = ":foo\\:bar::waldo:"; + int r; + + log_info("/* %s */", __func__); + + r = strv_split_extract(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS); + assert_se(r == (int) strv_length(l)); + assert_se(streq_ptr(l[0], "")); + assert_se(streq_ptr(l[1], "foo:bar")); + assert_se(streq_ptr(l[2], "")); + assert_se(streq_ptr(l[3], "waldo")); + assert_se(streq_ptr(l[4], "")); + assert_se(streq_ptr(l[5], NULL)); +} + +static void test_strv_split_newlines(void) { + unsigned i = 0; + char **s; + _cleanup_strv_free_ char **l = NULL; + const char str[] = "one\ntwo\nthree"; + + log_info("/* %s */", __func__); + + l = strv_split_newlines(str); + assert_se(l); + + STRV_FOREACH(s, l) { + assert_se(streq(*s, input_table_multiple[i++])); + } +} + +static void test_strv_split_nulstr(void) { + _cleanup_strv_free_ char **l = NULL; + const char nulstr[] = "str0\0str1\0str2\0str3\0"; + + log_info("/* %s */", __func__); + + l = strv_split_nulstr (nulstr); + assert_se(l); + + assert_se(streq(l[0], "str0")); + assert_se(streq(l[1], "str1")); + assert_se(streq(l[2], "str2")); + assert_se(streq(l[3], "str3")); +} + +static void test_strv_parse_nulstr(void) { + _cleanup_strv_free_ char **l = NULL; + const char nulstr[] = "hoge\0hoge2\0hoge3\0\0hoge5\0\0xxx"; + + log_info("/* %s */", __func__); + + l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1); + assert_se(l); + puts("Parse nulstr:"); + strv_print(l); + + assert_se(streq(l[0], "hoge")); + assert_se(streq(l[1], "hoge2")); + assert_se(streq(l[2], "hoge3")); + assert_se(streq(l[3], "")); + assert_se(streq(l[4], "hoge5")); + assert_se(streq(l[5], "")); + assert_se(streq(l[6], "xxx")); +} + +static void test_strv_overlap(void) { + const char * const input_table[] = { + "one", + "two", + "three", + NULL + }; + const char * const input_table_overlap[] = { + "two", + NULL + }; + const char * const input_table_unique[] = { + "four", + "five", + "six", + NULL + }; + + log_info("/* %s */", __func__); + + assert_se(strv_overlap((char **)input_table, (char**)input_table_overlap)); + assert_se(!strv_overlap((char **)input_table, (char**)input_table_unique)); +} + +static void test_strv_sort(void) { + const char* input_table[] = { + "durian", + "apple", + "citrus", + "CAPITAL LETTERS FIRST", + "banana", + NULL + }; + + log_info("/* %s */", __func__); + + strv_sort((char **)input_table); + + assert_se(streq(input_table[0], "CAPITAL LETTERS FIRST")); + assert_se(streq(input_table[1], "apple")); + assert_se(streq(input_table[2], "banana")); + assert_se(streq(input_table[3], "citrus")); + assert_se(streq(input_table[4], "durian")); +} + +static void test_strv_extend_strv_concat(void) { + _cleanup_strv_free_ char **a = NULL, **b = NULL; + + log_info("/* %s */", __func__); + + a = strv_new("without", "suffix"); + b = strv_new("with", "suffix"); + assert_se(a); + assert_se(b); + + assert_se(strv_extend_strv_concat(&a, b, "_suffix") >= 0); + + assert_se(streq(a[0], "without")); + assert_se(streq(a[1], "suffix")); + assert_se(streq(a[2], "with_suffix")); + assert_se(streq(a[3], "suffix_suffix")); +} + +static void test_strv_extend_strv(void) { + _cleanup_strv_free_ char **a = NULL, **b = NULL, **n = NULL; + + log_info("/* %s */", __func__); + + a = strv_new("abc", "def", "ghi"); + b = strv_new("jkl", "mno", "abc", "pqr"); + assert_se(a); + assert_se(b); + + assert_se(strv_extend_strv(&a, b, true) == 3); + + assert_se(streq(a[0], "abc")); + assert_se(streq(a[1], "def")); + assert_se(streq(a[2], "ghi")); + assert_se(streq(a[3], "jkl")); + assert_se(streq(a[4], "mno")); + assert_se(streq(a[5], "pqr")); + assert_se(strv_length(a) == 6); + + assert_se(strv_extend_strv(&n, b, false) >= 0); + assert_se(streq(n[0], "jkl")); + assert_se(streq(n[1], "mno")); + assert_se(streq(n[2], "abc")); + assert_se(streq(n[3], "pqr")); + assert_se(strv_length(n) == 4); +} + +static void test_strv_extend(void) { + _cleanup_strv_free_ char **a = NULL, **b = NULL; + + log_info("/* %s */", __func__); + + a = strv_new("test", "test1"); + assert_se(a); + assert_se(strv_extend(&a, "test2") >= 0); + assert_se(strv_extend(&b, "test3") >= 0); + + assert_se(streq(a[0], "test")); + assert_se(streq(a[1], "test1")); + assert_se(streq(a[2], "test2")); + assert_se(streq(b[0], "test3")); +} + +static void test_strv_extendf(void) { + _cleanup_strv_free_ char **a = NULL, **b = NULL; + + log_info("/* %s */", __func__); + + a = strv_new("test", "test1"); + assert_se(a); + assert_se(strv_extendf(&a, "test2 %s %d %s", "foo", 128, "bar") >= 0); + assert_se(strv_extendf(&b, "test3 %s %s %d", "bar", "foo", 128) >= 0); + + assert_se(streq(a[0], "test")); + assert_se(streq(a[1], "test1")); + assert_se(streq(a[2], "test2 foo 128 bar")); + assert_se(streq(b[0], "test3 bar foo 128")); +} + +static void test_strv_foreach(void) { + _cleanup_strv_free_ char **a; + unsigned i = 0; + char **check; + + log_info("/* %s */", __func__); + + a = strv_new("one", "two", "three"); + assert_se(a); + + STRV_FOREACH(check, a) + assert_se(streq(*check, input_table_multiple[i++])); +} + +static void test_strv_foreach_backwards(void) { + _cleanup_strv_free_ char **a; + unsigned i = 2; + char **check; + + log_info("/* %s */", __func__); + + a = strv_new("one", "two", "three"); + + assert_se(a); + + STRV_FOREACH_BACKWARDS(check, a) + assert_se(streq_ptr(*check, input_table_multiple[i--])); + + STRV_FOREACH_BACKWARDS(check, (char**) NULL) + assert_not_reached("Let's see that we check empty strv right, too."); + + STRV_FOREACH_BACKWARDS(check, (char**) { NULL }) + assert_not_reached("Let's see that we check empty strv right, too."); +} + +static void test_strv_foreach_pair(void) { + _cleanup_strv_free_ char **a = NULL; + char **x, **y; + + log_info("/* %s */", __func__); + + a = strv_new("pair_one", "pair_one", + "pair_two", "pair_two", + "pair_three", "pair_three"); + STRV_FOREACH_PAIR(x, y, a) + assert_se(streq(*x, *y)); +} + +static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) { + char **j; + unsigned i; + + log_info("/* %s */", __func__); + + j = strv_from_stdarg_alloca(first); + + for (i = 0;; i++) { + assert_se(streq_ptr(l[i], j[i])); + + if (!l[i]) + break; + } +} + +static void test_strv_from_stdarg_alloca(void) { + log_info("/* %s */", __func__); + + test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL); + test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL); + test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY, NULL); +} + +static void test_strv_insert(void) { + _cleanup_strv_free_ char **a = NULL; + + log_info("/* %s */", __func__); + + assert_se(strv_insert(&a, 0, strdup("first")) == 0); + assert_se(streq(a[0], "first")); + assert_se(!a[1]); + + assert_se(strv_insert(&a, 0, NULL) == 0); + assert_se(streq(a[0], "first")); + assert_se(!a[1]); + + assert_se(strv_insert(&a, 1, strdup("two")) == 0); + assert_se(streq(a[0], "first")); + assert_se(streq(a[1], "two")); + assert_se(!a[2]); + + assert_se(strv_insert(&a, 4, strdup("tri")) == 0); + assert_se(streq(a[0], "first")); + assert_se(streq(a[1], "two")); + assert_se(streq(a[2], "tri")); + assert_se(!a[3]); + + assert_se(strv_insert(&a, 1, strdup("duo")) == 0); + assert_se(streq(a[0], "first")); + assert_se(streq(a[1], "duo")); + assert_se(streq(a[2], "two")); + assert_se(streq(a[3], "tri")); + assert_se(!a[4]); +} + +static void test_strv_push_prepend(void) { + _cleanup_strv_free_ char **a = NULL; + + log_info("/* %s */", __func__); + + a = strv_new("foo", "bar", "three"); + + assert_se(strv_push_prepend(&a, strdup("first")) >= 0); + assert_se(streq(a[0], "first")); + assert_se(streq(a[1], "foo")); + assert_se(streq(a[2], "bar")); + assert_se(streq(a[3], "three")); + assert_se(!a[4]); + + assert_se(strv_consume_prepend(&a, strdup("first2")) >= 0); + assert_se(streq(a[0], "first2")); + assert_se(streq(a[1], "first")); + assert_se(streq(a[2], "foo")); + assert_se(streq(a[3], "bar")); + assert_se(streq(a[4], "three")); + assert_se(!a[5]); +} + +static void test_strv_push(void) { + _cleanup_strv_free_ char **a = NULL; + char *i, *j; + + log_info("/* %s */", __func__); + + assert_se(i = strdup("foo")); + assert_se(strv_push(&a, i) >= 0); + + assert_se(i = strdup("a")); + assert_se(j = strdup("b")); + assert_se(strv_push_pair(&a, i, j) >= 0); + + assert_se(streq_ptr(a[0], "foo")); + assert_se(streq_ptr(a[1], "a")); + assert_se(streq_ptr(a[2], "b")); + assert_se(streq_ptr(a[3], NULL)); +} + +static void test_strv_equal(void) { + _cleanup_strv_free_ char **a = NULL; + _cleanup_strv_free_ char **b = NULL; + _cleanup_strv_free_ char **c = NULL; + + log_info("/* %s */", __func__); + + a = strv_new("one", "two", "three"); + assert_se(a); + b = strv_new("one", "two", "three"); + assert_se(a); + c = strv_new("one", "two", "three", "four"); + assert_se(a); + + assert_se(strv_equal(a, a)); + assert_se(strv_equal(a, b)); + assert_se(strv_equal(NULL, NULL)); + + assert_se(!strv_equal(a, c)); + assert_se(!strv_equal(b, c)); + assert_se(!strv_equal(b, NULL)); +} + +static void test_strv_is_uniq(void) { + _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL; + + log_info("/* %s */", __func__); + + a = strv_new(NULL); + assert_se(a); + assert_se(strv_is_uniq(a)); + + b = strv_new("foo"); + assert_se(b); + assert_se(strv_is_uniq(b)); + + c = strv_new("foo", "bar"); + assert_se(c); + assert_se(strv_is_uniq(c)); + + d = strv_new("foo", "bar", "waldo", "bar", "piep"); + assert_se(d); + assert_se(!strv_is_uniq(d)); +} + +static void test_strv_reverse(void) { + _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL; + + log_info("/* %s */", __func__); + + a = strv_new(NULL); + assert_se(a); + + strv_reverse(a); + assert_se(strv_isempty(a)); + + b = strv_new("foo"); + assert_se(b); + strv_reverse(b); + assert_se(streq_ptr(b[0], "foo")); + assert_se(streq_ptr(b[1], NULL)); + + c = strv_new("foo", "bar"); + assert_se(c); + strv_reverse(c); + assert_se(streq_ptr(c[0], "bar")); + assert_se(streq_ptr(c[1], "foo")); + assert_se(streq_ptr(c[2], NULL)); + + d = strv_new("foo", "bar", "waldo"); + assert_se(d); + strv_reverse(d); + assert_se(streq_ptr(d[0], "waldo")); + assert_se(streq_ptr(d[1], "bar")); + assert_se(streq_ptr(d[2], "foo")); + assert_se(streq_ptr(d[3], NULL)); +} + +static void test_strv_shell_escape(void) { + _cleanup_strv_free_ char **v = NULL; + + log_info("/* %s */", __func__); + + v = strv_new("foo:bar", "bar,baz", "wal\\do"); + assert_se(v); + assert_se(strv_shell_escape(v, ",:")); + assert_se(streq_ptr(v[0], "foo\\:bar")); + assert_se(streq_ptr(v[1], "bar\\,baz")); + assert_se(streq_ptr(v[2], "wal\\\\do")); + assert_se(streq_ptr(v[3], NULL)); +} + +static void test_strv_skip_one(char **a, size_t n, char **b) { + a = strv_skip(a, n); + assert_se(strv_equal(a, b)); +} + +static void test_strv_skip(void) { + log_info("/* %s */", __func__); + + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz")); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz")); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz")); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 3, STRV_MAKE(NULL)); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 4, STRV_MAKE(NULL)); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 55, STRV_MAKE(NULL)); + + test_strv_skip_one(STRV_MAKE("quux"), 0, STRV_MAKE("quux")); + test_strv_skip_one(STRV_MAKE("quux"), 1, STRV_MAKE(NULL)); + test_strv_skip_one(STRV_MAKE("quux"), 55, STRV_MAKE(NULL)); + + test_strv_skip_one(STRV_MAKE(NULL), 0, STRV_MAKE(NULL)); + test_strv_skip_one(STRV_MAKE(NULL), 1, STRV_MAKE(NULL)); + test_strv_skip_one(STRV_MAKE(NULL), 55, STRV_MAKE(NULL)); +} + +static void test_strv_extend_n(void) { + _cleanup_strv_free_ char **v = NULL; + + log_info("/* %s */", __func__); + + v = strv_new("foo", "bar"); + assert_se(v); + + assert_se(strv_extend_n(&v, "waldo", 3) >= 0); + assert_se(strv_extend_n(&v, "piep", 2) >= 0); + + assert_se(streq(v[0], "foo")); + assert_se(streq(v[1], "bar")); + assert_se(streq(v[2], "waldo")); + assert_se(streq(v[3], "waldo")); + assert_se(streq(v[4], "waldo")); + assert_se(streq(v[5], "piep")); + assert_se(streq(v[6], "piep")); + assert_se(v[7] == NULL); + + v = strv_free(v); + + assert_se(strv_extend_n(&v, "foo", 1) >= 0); + assert_se(strv_extend_n(&v, "bar", 0) >= 0); + + assert_se(streq(v[0], "foo")); + assert_se(v[1] == NULL); +} + +static void test_strv_make_nulstr_one(char **l) { + _cleanup_free_ char *b = NULL, *c = NULL; + _cleanup_strv_free_ char **q = NULL; + const char *s = NULL; + size_t n, m; + unsigned i = 0; + + log_info("/* %s */", __func__); + + assert_se(strv_make_nulstr(l, &b, &n) >= 0); + assert_se(q = strv_parse_nulstr(b, n)); + assert_se(strv_equal(l, q)); + + assert_se(strv_make_nulstr(q, &c, &m) >= 0); + assert_se(m == n); + assert_se(memcmp(b, c, m) == 0); + + NULSTR_FOREACH(s, b) + assert_se(streq(s, l[i++])); + assert_se(i == strv_length(l)); +} + +static void test_strv_make_nulstr(void) { + log_info("/* %s */", __func__); + + test_strv_make_nulstr_one(NULL); + test_strv_make_nulstr_one(STRV_MAKE(NULL)); + test_strv_make_nulstr_one(STRV_MAKE("foo")); + test_strv_make_nulstr_one(STRV_MAKE("foo", "bar")); + test_strv_make_nulstr_one(STRV_MAKE("foo", "bar", "quuux")); +} + +static void test_strv_free_free(void) { + char ***t; + + log_info("/* %s */", __func__); + + assert_se(t = new(char**, 3)); + assert_se(t[0] = strv_new("a", "b")); + assert_se(t[1] = strv_new("c", "d", "e")); + t[2] = NULL; + + t = strv_free_free(t); +} + +static void test_foreach_string(void) { + const char * const t[] = { + "foo", + "bar", + "waldo", + NULL + }; + const char *x; + unsigned i = 0; + + log_info("/* %s */", __func__); + + FOREACH_STRING(x, "foo", "bar", "waldo") + assert_se(streq_ptr(t[i++], x)); + + assert_se(i == 3); + + FOREACH_STRING(x, "zzz") + assert_se(streq(x, "zzz")); +} + +static void test_strv_fnmatch(void) { + _cleanup_strv_free_ char **v = NULL; + + log_info("/* %s */", __func__); + + assert_se(!strv_fnmatch(STRV_MAKE_EMPTY, "a", 0)); + + v = strv_new("*\\*"); + assert_se(!strv_fnmatch(v, "\\", 0)); + assert_se(strv_fnmatch(v, "\\", FNM_NOESCAPE)); +} + +int main(int argc, char *argv[]) { + test_specifier_printf(); + test_str_in_set(); + test_strptr_in_set(); + test_startswith_set(); + test_strv_foreach(); + test_strv_foreach_backwards(); + test_strv_foreach_pair(); + test_strv_find(); + test_strv_find_prefix(); + test_strv_find_startswith(); + test_strv_join(); + test_strv_join_prefix(); + + test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz")); + test_strv_unquote("", STRV_MAKE_EMPTY); + test_strv_unquote(" ", STRV_MAKE_EMPTY); + test_strv_unquote(" ", STRV_MAKE_EMPTY); + test_strv_unquote(" x", STRV_MAKE("x")); + test_strv_unquote("x ", STRV_MAKE("x")); + test_strv_unquote(" x ", STRV_MAKE("x")); + test_strv_unquote(" \"x\" ", STRV_MAKE("x")); + test_strv_unquote(" 'x' ", STRV_MAKE("x")); + test_strv_unquote(" 'x\"' ", STRV_MAKE("x\"")); + test_strv_unquote(" \"x'\" ", STRV_MAKE("x'")); + test_strv_unquote("a '--b=c \"d e\"'", STRV_MAKE("a", "--b=c \"d e\"")); + + /* trailing backslashes */ + test_strv_unquote(" x\\\\", STRV_MAKE("x\\")); + test_invalid_unquote(" x\\"); + + test_invalid_unquote("a --b='c \"d e\"''"); + test_invalid_unquote("a --b='c \"d e\" '\""); + test_invalid_unquote("a --b='c \"d e\"garbage"); + test_invalid_unquote("'"); + test_invalid_unquote("\""); + test_invalid_unquote("'x'y'g"); + + test_strv_split(); + test_strv_split_empty(); + test_strv_split_extract(); + test_strv_split_newlines(); + test_strv_split_nulstr(); + test_strv_parse_nulstr(); + test_strv_overlap(); + test_strv_sort(); + test_strv_extend_strv(); + test_strv_extend_strv_concat(); + test_strv_extend(); + test_strv_extendf(); + test_strv_from_stdarg_alloca(); + test_strv_insert(); + test_strv_push_prepend(); + test_strv_push(); + test_strv_equal(); + test_strv_is_uniq(); + test_strv_reverse(); + test_strv_shell_escape(); + test_strv_skip(); + test_strv_extend_n(); + test_strv_make_nulstr(); + test_strv_free_free(); + + test_foreach_string(); + test_strv_fnmatch(); + + return 0; +} diff --git a/src/test/test-strxcpyx.c b/src/test/test-strxcpyx.c new file mode 100644 index 00000000..749aa46d --- /dev/null +++ b/src/test/test-strxcpyx.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "string-util.h" +#include "strxcpyx.h" +#include "util.h" + +static void test_strpcpy(void) { + char target[25]; + char *s = target; + size_t space_left; + + space_left = sizeof(target); + space_left = strpcpy(&s, space_left, "12345"); + space_left = strpcpy(&s, space_left, "hey hey hey"); + space_left = strpcpy(&s, space_left, "waldo"); + space_left = strpcpy(&s, space_left, "ba"); + space_left = strpcpy(&s, space_left, "r"); + space_left = strpcpy(&s, space_left, "foo"); + + assert_se(streq(target, "12345hey hey heywaldobar")); + assert_se(space_left == 0); +} + +static void test_strpcpyf(void) { + char target[25]; + char *s = target; + size_t space_left; + + space_left = sizeof(target); + space_left = strpcpyf(&s, space_left, "space left: %zu. ", space_left); + space_left = strpcpyf(&s, space_left, "foo%s", "bar"); + + assert_se(streq(target, "space left: 25. foobar")); + assert_se(space_left == 3); + + /* test overflow */ + s = target; + space_left = strpcpyf(&s, 12, "00 left: %i. ", 999); + assert_se(streq(target, "00 left: 99")); + assert_se(space_left == 0); + assert_se(target[12] == '2'); +} + +static void test_strpcpyl(void) { + char target[25]; + char *s = target; + size_t space_left; + + space_left = sizeof(target); + space_left = strpcpyl(&s, space_left, "waldo", " test", " waldo. ", NULL); + space_left = strpcpyl(&s, space_left, "Banana", NULL); + + assert_se(streq(target, "waldo test waldo. Banana")); + assert_se(space_left == 1); +} + +static void test_strscpy(void) { + char target[25]; + size_t space_left; + + space_left = sizeof(target); + space_left = strscpy(target, space_left, "12345"); + + assert_se(streq(target, "12345")); + assert_se(space_left == 20); +} + +static void test_strscpyl(void) { + char target[25]; + size_t space_left; + + space_left = sizeof(target); + space_left = strscpyl(target, space_left, "12345", "waldo", "waldo", NULL); + + assert_se(streq(target, "12345waldowaldo")); + assert_se(space_left == 10); +} + +static void test_sd_event_code_migration(void) { + char b[100 * DECIMAL_STR_MAX(unsigned) + 1]; + char c[100 * DECIMAL_STR_MAX(unsigned) + 1], *p; + unsigned i; + size_t l; + int o; + + for (i = o = 0; i < 100; i++) + o += snprintf(&b[o], sizeof(b) - o, "%u ", i); + + p = c; + l = sizeof(c); + for (i = 0; i < 100; i++) + l = strpcpyf(&p, l, "%u ", i); + + assert_se(streq(b, c)); +} + +int main(int argc, char *argv[]) { + test_strpcpy(); + test_strpcpyf(); + test_strpcpyl(); + test_strscpy(); + test_strscpyl(); + + test_sd_event_code_migration(); + + return 0; +} diff --git a/src/test/test-sysctl-util.c b/src/test/test-sysctl-util.c new file mode 100644 index 00000000..2b957dd4 --- /dev/null +++ b/src/test/test-sysctl-util.c @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "strv.h" +#include "sysctl-util.h" +#include "tests.h" + +static const char* cases[] = { + "a.b.c", "a/b/c", + "a/b/c", "a/b/c", + "a/b.c/d", "a/b.c/d", + "a.b/c.d", "a/b.c/d", + + "net.ipv4.conf.enp3s0/200.forwarding", "net/ipv4/conf/enp3s0.200/forwarding", + "net/ipv4/conf/enp3s0.200/forwarding", "net/ipv4/conf/enp3s0.200/forwarding", + + "a...b...c", "a/b/c", + "a///b///c", "a/b/c", + ".a...b...c", "a/b/c", + "/a///b///c", "a/b/c", + NULL, +}; + +static void test_sysctl_normalize(void) { + log_info("/* %s */", __func__); + + const char **s, **expected; + STRV_FOREACH_PAIR(s, expected, cases) { + _cleanup_free_ char *t; + + assert_se(t = strdup(*s)); + assert_se(sysctl_normalize(t) == t); + + log_info("\"%s\" → \"%s\", expected \"%s\"", *s, t, *expected); + assert_se(streq(t, *expected)); + } +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + test_sysctl_normalize(); + + return 0; +} diff --git a/src/test/test-systemd-tmpfiles.py b/src/test/test-systemd-tmpfiles.py new file mode 100755 index 00000000..7f4af389 --- /dev/null +++ b/src/test/test-systemd-tmpfiles.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +import os +import sys +import socket +import subprocess +import tempfile +import pwd +import grp + +try: + from systemd import id128 +except ImportError: + id128 = None + +EX_DATAERR = 65 # from sysexits.h +EXIT_TEST_SKIP = 77 + +try: + subprocess.run +except AttributeError: + sys.exit(EXIT_TEST_SKIP) + +exe_with_args = sys.argv[1:] + +def test_line(line, *, user, returncode=EX_DATAERR, extra={}): + args = ['--user'] if user else [] + print('Running {} on {!r}'.format(' '.join(exe_with_args + args), line)) + c = subprocess.run(exe_with_args + ['--create', '-'] + args, + input=line, stdout=subprocess.PIPE, universal_newlines=True, + **extra) + assert c.returncode == returncode, c + +def test_invalids(*, user): + test_line('asdfa', user=user) + test_line('f "open quote', user=user) + test_line('f closed quote""', user=user) + test_line('Y /unknown/letter', user=user) + test_line('w non/absolute/path', user=user) + test_line('s', user=user) # s is for short + test_line('f!! /too/many/bangs', user=user) + test_line('f++ /too/many/plusses', user=user) + test_line('f+!+ /too/many/plusses', user=user) + test_line('f!+! /too/many/bangs', user=user) + test_line('w /unresolved/argument - - - - "%Y"', user=user) + test_line('w /unresolved/argument/sandwich - - - - "%v%Y%v"', user=user) + test_line('w /unresolved/filename/%Y - - - - "whatever"', user=user) + test_line('w /unresolved/filename/sandwich/%v%Y%v - - - - "whatever"', user=user) + test_line('w - - - - - "no file specified"', user=user) + test_line('C - - - - - "no file specified"', user=user) + test_line('C non/absolute/path - - - - -', user=user) + test_line('b - - - - - -', user=user) + test_line('b 1234 - - - - -', user=user) + test_line('c - - - - - -', user=user) + test_line('c 1234 - - - - -', user=user) + test_line('t - - -', user=user) + test_line('T - - -', user=user) + test_line('a - - -', user=user) + test_line('A - - -', user=user) + test_line('h - - -', user=user) + test_line('H - - -', user=user) + +def test_uninitialized_t(): + if os.getuid() == 0: + return + + test_line('w /foo - - - - "specifier for --user %t"', + user=True, returncode=0, extra={'env':{}}) + +def test_content(line, expected, *, user, extra={}): + d = tempfile.TemporaryDirectory(prefix='test-systemd-tmpfiles.') + arg = d.name + '/arg' + spec = line.format(arg) + test_line(spec, user=user, returncode=0, extra=extra) + content = open(arg).read() + print('expect: {!r}\nactual: {!r}'.format(expected, content)) + assert content == expected + +def test_valid_specifiers(*, user): + test_content('f {} - - - - two words', 'two words', user=user) + if id128: + try: + test_content('f {} - - - - %m', '{}'.format(id128.get_machine().hex), user=user) + except AssertionError as e: + print(e) + print('/etc/machine-id: {!r}'.format(open('/etc/machine-id').read())) + print('/proc/cmdline: {!r}'.format(open('/proc/cmdline').read())) + print('skipping') + test_content('f {} - - - - %b', '{}'.format(id128.get_boot().hex), user=user) + test_content('f {} - - - - %H', '{}'.format(socket.gethostname()), user=user) + test_content('f {} - - - - %v', '{}'.format(os.uname().release), user=user) + test_content('f {} - - - - %U', '{}'.format(os.getuid()), user=user) + test_content('f {} - - - - %G', '{}'.format(os.getgid()), user=user) + + puser = pwd.getpwuid(os.getuid()) + test_content('f {} - - - - %u', '{}'.format(puser.pw_name), user=user) + + pgroup = grp.getgrgid(os.getgid()) + test_content('f {} - - - - %g', '{}'.format(pgroup.gr_name), user=user) + + # Note that %h is the only specifier in which we look the environment, + # because we check $HOME. Should we even be doing that? + home = os.path.expanduser("~") + test_content('f {} - - - - %h', '{}'.format(home), user=user) + + xdg_runtime_dir = os.getenv('XDG_RUNTIME_DIR') + if xdg_runtime_dir is not None or not user: + test_content('f {} - - - - %t', + xdg_runtime_dir if user else '/run', + user=user) + + xdg_config_home = os.getenv('XDG_CONFIG_HOME') + if xdg_config_home is not None or not user: + test_content('f {} - - - - %S', + xdg_config_home if user else '/var/lib', + user=user) + + xdg_cache_home = os.getenv('XDG_CACHE_HOME') + if xdg_cache_home is not None or not user: + test_content('f {} - - - - %C', + xdg_cache_home if user else '/var/cache', + user=user) + + if xdg_config_home is not None or not user: + test_content('f {} - - - - %L', + xdg_config_home + '/log' if user else '/var/log', + user=user) + + test_content('f {} - - - - %%', '%', user=user) + +if __name__ == '__main__': + test_invalids(user=False) + test_invalids(user=True) + test_uninitialized_t() + + test_valid_specifiers(user=False) + test_valid_specifiers(user=True) diff --git a/src/test/test-tables.c b/src/test/test-tables.c new file mode 100644 index 00000000..59f90b76 --- /dev/null +++ b/src/test/test-tables.c @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "architecture.h" +#include "automount.h" +#include "cgroup.h" +#include "compress.h" +#include "condition.h" +#include "device-private.h" +#include "device.h" +#include "execute.h" +#include "import-util.h" +#include "install.h" +#include "job.h" +#include "journald-server.h" +#include "kill.h" +#include "link-config.h" +#include "locale-util.h" +#include "log.h" +#include "logs-show.h" +#include "machine-image.h" +#include "mount.h" +#include "path.h" +#include "process-util.h" +#include "resolve-util.h" +#include "rlimit-util.h" +#include "scope.h" +#include "service.h" +#include "show-status.h" +#include "slice.h" +#include "socket-util.h" +#include "socket.h" +#include "swap.h" +#include "target.h" +#include "test-tables.h" +#include "timer.h" +#include "unit-name.h" +#include "unit.h" +#include "util.h" +#include "virt.h" + +int main(int argc, char **argv) { + test_table(architecture, ARCHITECTURE); + test_table(assert_type, CONDITION_TYPE); + test_table(automount_result, AUTOMOUNT_RESULT); + test_table(automount_state, AUTOMOUNT_STATE); + test_table(cgroup_controller, CGROUP_CONTROLLER); + test_table(cgroup_device_policy, CGROUP_DEVICE_POLICY); + test_table(cgroup_io_limit_type, CGROUP_IO_LIMIT_TYPE); + test_table(collect_mode, COLLECT_MODE); + test_table(condition_result, CONDITION_RESULT); + test_table(condition_type, CONDITION_TYPE); + test_table(device_action, DEVICE_ACTION); + test_table(device_state, DEVICE_STATE); + test_table(dns_over_tls_mode, DNS_OVER_TLS_MODE); + test_table(dnssec_mode, DNSSEC_MODE); + test_table(emergency_action, EMERGENCY_ACTION); + test_table(exec_directory_type, EXEC_DIRECTORY_TYPE); + test_table(exec_input, EXEC_INPUT); + test_table(exec_keyring_mode, EXEC_KEYRING_MODE); + test_table(exec_output, EXEC_OUTPUT); + test_table(exec_preserve_mode, EXEC_PRESERVE_MODE); + test_table(exec_utmp_mode, EXEC_UTMP_MODE); + test_table(image_type, IMAGE_TYPE); + test_table(import_verify, IMPORT_VERIFY); + test_table(job_mode, JOB_MODE); + test_table(job_result, JOB_RESULT); + test_table(job_state, JOB_STATE); + test_table(job_type, JOB_TYPE); + test_table(kill_mode, KILL_MODE); + test_table(kill_who, KILL_WHO); + test_table(locale_variable, VARIABLE_LC); + test_table(log_target, LOG_TARGET); + test_table(mac_address_policy, MAC_ADDRESS_POLICY); + test_table(manager_state, MANAGER_STATE); + test_table(manager_timestamp, MANAGER_TIMESTAMP); + test_table(mount_exec_command, MOUNT_EXEC_COMMAND); + test_table(mount_result, MOUNT_RESULT); + test_table(mount_state, MOUNT_STATE); + test_table(name_policy, NAMEPOLICY); + test_table(namespace_type, NAMESPACE_TYPE); + test_table(notify_access, NOTIFY_ACCESS); + test_table(notify_state, NOTIFY_STATE); + test_table(output_mode, OUTPUT_MODE); + test_table(partition_designator, PARTITION_DESIGNATOR); + test_table(path_result, PATH_RESULT); + test_table(path_state, PATH_STATE); + test_table(path_type, PATH_TYPE); + test_table(protect_home, PROTECT_HOME); + test_table(protect_system, PROTECT_SYSTEM); + test_table(resolve_support, RESOLVE_SUPPORT); + test_table(rlimit, RLIMIT); + test_table(scope_result, SCOPE_RESULT); + test_table(scope_state, SCOPE_STATE); + test_table(service_exec_command, SERVICE_EXEC_COMMAND); + test_table(service_restart, SERVICE_RESTART); + test_table(service_result, SERVICE_RESULT); + test_table(service_state, SERVICE_STATE); + test_table(service_type, SERVICE_TYPE); + test_table(show_status, SHOW_STATUS); + test_table(slice_state, SLICE_STATE); + test_table(socket_address_bind_ipv6_only, SOCKET_ADDRESS_BIND_IPV6_ONLY); + test_table(socket_exec_command, SOCKET_EXEC_COMMAND); + test_table(socket_result, SOCKET_RESULT); + test_table(socket_state, SOCKET_STATE); + test_table(split_mode, SPLIT); + test_table(storage, STORAGE); + test_table(swap_exec_command, SWAP_EXEC_COMMAND); + test_table(swap_result, SWAP_RESULT); + test_table(swap_state, SWAP_STATE); + test_table(target_state, TARGET_STATE); + test_table(timer_base, TIMER_BASE); + test_table(timer_result, TIMER_RESULT); + test_table(timer_state, TIMER_STATE); + test_table(unit_active_state, UNIT_ACTIVE_STATE); + test_table(unit_dependency, UNIT_DEPENDENCY); + test_table(unit_file_change_type, UNIT_FILE_CHANGE_TYPE); + test_table(unit_file_preset_mode, UNIT_FILE_PRESET); + test_table(unit_file_state, UNIT_FILE_STATE); + test_table(unit_load_state, UNIT_LOAD_STATE); + test_table(unit_type, UNIT_TYPE); + test_table(virtualization, VIRTUALIZATION); + + test_table_sparse(object_compressed, OBJECT_COMPRESSED); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c new file mode 100644 index 00000000..0e563f54 --- /dev/null +++ b/src/test/test-terminal-util.c @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "macro.h" +#include "path-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "tests.h" +#include "tmpfile-util.h" +#include "util.h" + +static void test_default_term_for_tty(void) { + log_info("/* %s */", __func__); + + puts(default_term_for_tty("/dev/tty23")); + puts(default_term_for_tty("/dev/ttyS23")); + puts(default_term_for_tty("/dev/tty0")); + puts(default_term_for_tty("/dev/pty0")); + puts(default_term_for_tty("/dev/pts/0")); + puts(default_term_for_tty("/dev/console")); + puts(default_term_for_tty("tty23")); + puts(default_term_for_tty("ttyS23")); + puts(default_term_for_tty("tty0")); + puts(default_term_for_tty("pty0")); + puts(default_term_for_tty("pts/0")); + puts(default_term_for_tty("console")); +} + +static void test_read_one_char(void) { + _cleanup_fclose_ FILE *file = NULL; + char r; + bool need_nl; + char name[] = "/tmp/test-read_one_char.XXXXXX"; + + log_info("/* %s */", __func__); + + assert_se(fmkostemp_safe(name, "r+", &file) == 0); + + assert_se(fputs("c\n", file) >= 0); + rewind(file); + assert_se(read_one_char(file, &r, 1000000, &need_nl) >= 0); + assert_se(!need_nl); + assert_se(r == 'c'); + assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0); + + rewind(file); + assert_se(fputs("foobar\n", file) >= 0); + rewind(file); + assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0); + + rewind(file); + assert_se(fputs("\n", file) >= 0); + rewind(file); + assert_se(read_one_char(file, &r, 1000000, &need_nl) < 0); + + assert_se(unlink(name) >= 0); +} + +static void test_getttyname_malloc(void) { + _cleanup_free_ char *ttyname = NULL; + _cleanup_close_ int master = -1; + + log_info("/* %s */", __func__); + + assert_se((master = posix_openpt(O_RDWR|O_NOCTTY)) >= 0); + assert_se(getttyname_malloc(master, &ttyname) >= 0); + log_info("ttyname = %s", ttyname); + + assert_se(PATH_IN_SET(ttyname, "ptmx", "pts/ptmx")); +} + +static void test_one_color(const char *name, const char *color) { + printf("<%s%s%s>\n", color, name, ansi_normal()); +} + +static void test_colors(void) { + log_info("/* %s */", __func__); + + test_one_color("normal", ansi_normal()); + test_one_color("highlight", ansi_highlight()); + test_one_color("red", ansi_red()); + test_one_color("green", ansi_green()); + test_one_color("yellow", ansi_yellow()); + test_one_color("blue", ansi_blue()); + test_one_color("megenta", ansi_magenta()); + test_one_color("grey", ansi_grey()); + test_one_color("highlight-red", ansi_highlight_red()); + test_one_color("highlight-green", ansi_highlight_green()); + test_one_color("highlight-yellow", ansi_highlight_yellow()); + test_one_color("highlight-blue", ansi_highlight_blue()); + test_one_color("highlight-magenta", ansi_highlight_magenta()); + test_one_color("highlight-grey", ansi_highlight_grey()); + + test_one_color("underline", ansi_underline()); + test_one_color("highlight-underline", ansi_highlight_underline()); + test_one_color("highlight-red-underline", ansi_highlight_red_underline()); + test_one_color("highlight-green-underline", ansi_highlight_green_underline()); + test_one_color("highlight-yellow-underline", ansi_highlight_yellow_underline()); + test_one_color("highlight-blue-underline", ansi_highlight_blue_underline()); + test_one_color("highlight-magenta-underline", ansi_highlight_magenta_underline()); + test_one_color("highlight-grey-underline", ansi_highlight_grey_underline()); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + test_default_term_for_tty(); + test_read_one_char(); + test_getttyname_malloc(); + test_colors(); + + return 0; +} diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c new file mode 100644 index 00000000..a422cc8d --- /dev/null +++ b/src/test/test-time-util.c @@ -0,0 +1,524 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "random-util.h" +#include "serialize.h" +#include "string-util.h" +#include "strv.h" +#include "tests.h" +#include "time-util.h" + +static void test_parse_sec(void) { + usec_t u; + + log_info("/* %s */", __func__); + + assert_se(parse_sec("5s", &u) >= 0); + assert_se(u == 5 * USEC_PER_SEC); + assert_se(parse_sec("5s500ms", &u) >= 0); + assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC); + assert_se(parse_sec(" 5s 500ms ", &u) >= 0); + assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC); + assert_se(parse_sec(" 5.5s ", &u) >= 0); + assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC); + assert_se(parse_sec(" 5.5s 0.5ms ", &u) >= 0); + assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC + 500); + assert_se(parse_sec(" .22s ", &u) >= 0); + assert_se(u == 220 * USEC_PER_MSEC); + assert_se(parse_sec(" .50y ", &u) >= 0); + assert_se(u == USEC_PER_YEAR / 2); + assert_se(parse_sec("2.5", &u) >= 0); + assert_se(u == 2500 * USEC_PER_MSEC); + assert_se(parse_sec(".7", &u) >= 0); + assert_se(u == 700 * USEC_PER_MSEC); + assert_se(parse_sec("23us", &u) >= 0); + assert_se(u == 23); + assert_se(parse_sec("23µs", &u) >= 0); + assert_se(u == 23); + assert_se(parse_sec("infinity", &u) >= 0); + assert_se(u == USEC_INFINITY); + assert_se(parse_sec(" infinity ", &u) >= 0); + assert_se(u == USEC_INFINITY); + assert_se(parse_sec("+3.1s", &u) >= 0); + assert_se(u == 3100 * USEC_PER_MSEC); + assert_se(parse_sec("3.1s.2", &u) >= 0); + assert_se(u == 3300 * USEC_PER_MSEC); + assert_se(parse_sec("3.1 .2", &u) >= 0); + assert_se(u == 3300 * USEC_PER_MSEC); + assert_se(parse_sec("3.1 sec .2 sec", &u) >= 0); + assert_se(u == 3300 * USEC_PER_MSEC); + assert_se(parse_sec("3.1 sec 1.2 sec", &u) >= 0); + assert_se(u == 4300 * USEC_PER_MSEC); + + assert_se(parse_sec(" xyz ", &u) < 0); + assert_se(parse_sec("", &u) < 0); + assert_se(parse_sec(" . ", &u) < 0); + assert_se(parse_sec(" 5. ", &u) < 0); + assert_se(parse_sec(".s ", &u) < 0); + assert_se(parse_sec("-5s ", &u) < 0); + assert_se(parse_sec("-0.3s ", &u) < 0); + assert_se(parse_sec("-0.0s ", &u) < 0); + assert_se(parse_sec("-0.-0s ", &u) < 0); + assert_se(parse_sec("0.-0s ", &u) < 0); + assert_se(parse_sec("3.-0s ", &u) < 0); + assert_se(parse_sec(" infinity .7", &u) < 0); + assert_se(parse_sec(".3 infinity", &u) < 0); + assert_se(parse_sec("3.+1s", &u) < 0); + assert_se(parse_sec("3. 1s", &u) < 0); + assert_se(parse_sec("3.s", &u) < 0); + assert_se(parse_sec("12.34.56", &u) < 0); + assert_se(parse_sec("12..34", &u) < 0); + assert_se(parse_sec("..1234", &u) < 0); + assert_se(parse_sec("1234..", &u) < 0); +} + +static void test_parse_sec_fix_0(void) { + usec_t u; + + log_info("/* %s */", __func__); + + assert_se(parse_sec_fix_0("5s", &u) >= 0); + assert_se(u == 5 * USEC_PER_SEC); + assert_se(parse_sec_fix_0("0s", &u) >= 0); + assert_se(u == USEC_INFINITY); + assert_se(parse_sec_fix_0("0", &u) >= 0); + assert_se(u == USEC_INFINITY); + assert_se(parse_sec_fix_0(" 0", &u) >= 0); + assert_se(u == USEC_INFINITY); +} + +static void test_parse_sec_def_infinity(void) { + usec_t u; + + log_info("/* %s */", __func__); + + assert_se(parse_sec_def_infinity("5s", &u) >= 0); + assert_se(u == 5 * USEC_PER_SEC); + assert_se(parse_sec_def_infinity("", &u) >= 0); + assert_se(u == USEC_INFINITY); + assert_se(parse_sec_def_infinity(" ", &u) >= 0); + assert_se(u == USEC_INFINITY); + assert_se(parse_sec_def_infinity("0s", &u) >= 0); + assert_se(u == 0); + assert_se(parse_sec_def_infinity("0", &u) >= 0); + assert_se(u == 0); + assert_se(parse_sec_def_infinity(" 0", &u) >= 0); + assert_se(u == 0); + assert_se(parse_sec_def_infinity("-5s", &u) < 0); +} + +static void test_parse_time(void) { + usec_t u; + + log_info("/* %s */", __func__); + + assert_se(parse_time("5", &u, 1) >= 0); + assert_se(u == 5); + + assert_se(parse_time("5", &u, USEC_PER_MSEC) >= 0); + assert_se(u == 5 * USEC_PER_MSEC); + + assert_se(parse_time("5", &u, USEC_PER_SEC) >= 0); + assert_se(u == 5 * USEC_PER_SEC); + + assert_se(parse_time("5s", &u, 1) >= 0); + assert_se(u == 5 * USEC_PER_SEC); + + assert_se(parse_time("5s", &u, USEC_PER_SEC) >= 0); + assert_se(u == 5 * USEC_PER_SEC); + + assert_se(parse_time("5s", &u, USEC_PER_MSEC) >= 0); + assert_se(u == 5 * USEC_PER_SEC); + + assert_se(parse_time("11111111111111y", &u, 1) == -ERANGE); + assert_se(parse_time("1.1111111111111y", &u, 1) >= 0); +} + +static void test_parse_nsec(void) { + nsec_t u; + + log_info("/* %s */", __func__); + + assert_se(parse_nsec("5s", &u) >= 0); + assert_se(u == 5 * NSEC_PER_SEC); + assert_se(parse_nsec("5s500ms", &u) >= 0); + assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC); + assert_se(parse_nsec(" 5s 500ms ", &u) >= 0); + assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC); + assert_se(parse_nsec(" 5.5s ", &u) >= 0); + assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC); + assert_se(parse_nsec(" 5.5s 0.5ms ", &u) >= 0); + assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC + 500 * NSEC_PER_USEC); + assert_se(parse_nsec(" .22s ", &u) >= 0); + assert_se(u == 220 * NSEC_PER_MSEC); + assert_se(parse_nsec(" .50y ", &u) >= 0); + assert_se(u == NSEC_PER_YEAR / 2); + assert_se(parse_nsec("2.5", &u) >= 0); + assert_se(u == 2); + assert_se(parse_nsec(".7", &u) >= 0); + assert_se(u == 0); + assert_se(parse_nsec("infinity", &u) >= 0); + assert_se(u == NSEC_INFINITY); + assert_se(parse_nsec(" infinity ", &u) >= 0); + assert_se(u == NSEC_INFINITY); + assert_se(parse_nsec("+3.1s", &u) >= 0); + assert_se(u == 3100 * NSEC_PER_MSEC); + assert_se(parse_nsec("3.1s.2", &u) >= 0); + assert_se(u == 3100 * NSEC_PER_MSEC); + assert_se(parse_nsec("3.1 .2s", &u) >= 0); + assert_se(u == 200 * NSEC_PER_MSEC + 3); + assert_se(parse_nsec("3.1 sec .2 sec", &u) >= 0); + assert_se(u == 3300 * NSEC_PER_MSEC); + assert_se(parse_nsec("3.1 sec 1.2 sec", &u) >= 0); + assert_se(u == 4300 * NSEC_PER_MSEC); + + assert_se(parse_nsec(" xyz ", &u) < 0); + assert_se(parse_nsec("", &u) < 0); + assert_se(parse_nsec(" . ", &u) < 0); + assert_se(parse_nsec(" 5. ", &u) < 0); + assert_se(parse_nsec(".s ", &u) < 0); + assert_se(parse_nsec(" infinity .7", &u) < 0); + assert_se(parse_nsec(".3 infinity", &u) < 0); + assert_se(parse_nsec("-5s ", &u) < 0); + assert_se(parse_nsec("-0.3s ", &u) < 0); + assert_se(parse_nsec("-0.0s ", &u) < 0); + assert_se(parse_nsec("-0.-0s ", &u) < 0); + assert_se(parse_nsec("0.-0s ", &u) < 0); + assert_se(parse_nsec("3.-0s ", &u) < 0); + assert_se(parse_nsec(" infinity .7", &u) < 0); + assert_se(parse_nsec(".3 infinity", &u) < 0); + assert_se(parse_nsec("3.+1s", &u) < 0); + assert_se(parse_nsec("3. 1s", &u) < 0); + assert_se(parse_nsec("3.s", &u) < 0); + assert_se(parse_nsec("12.34.56", &u) < 0); + assert_se(parse_nsec("12..34", &u) < 0); + assert_se(parse_nsec("..1234", &u) < 0); + assert_se(parse_nsec("1234..", &u) < 0); + assert_se(parse_nsec("1111111111111y", &u) == -ERANGE); + assert_se(parse_nsec("1.111111111111y", &u) >= 0); +} + +static void test_format_timespan_one(usec_t x, usec_t accuracy) { + char l[FORMAT_TIMESPAN_MAX]; + const char *t; + usec_t y; + + log_info(USEC_FMT" (at accuracy "USEC_FMT")", x, accuracy); + + assert_se(t = format_timespan(l, sizeof l, x, accuracy)); + log_info(" = <%s>", t); + + assert_se(parse_sec(t, &y) >= 0); + log_info(" = "USEC_FMT, y); + + if (accuracy <= 0) + accuracy = 1; + + assert_se(x / accuracy == y / accuracy); +} + +static void test_format_timespan(usec_t accuracy) { + log_info("/* %s accuracy="USEC_FMT" */", __func__, accuracy); + + test_format_timespan_one(0, accuracy); + test_format_timespan_one(1, accuracy); + test_format_timespan_one(1*USEC_PER_SEC, accuracy); + test_format_timespan_one(999*USEC_PER_MSEC, accuracy); + test_format_timespan_one(1234567, accuracy); + test_format_timespan_one(12, accuracy); + test_format_timespan_one(123, accuracy); + test_format_timespan_one(1234, accuracy); + test_format_timespan_one(12345, accuracy); + test_format_timespan_one(123456, accuracy); + test_format_timespan_one(1234567, accuracy); + test_format_timespan_one(12345678, accuracy); + test_format_timespan_one(1200000, accuracy); + test_format_timespan_one(1230000, accuracy); + test_format_timespan_one(1234000, accuracy); + test_format_timespan_one(1234500, accuracy); + test_format_timespan_one(1234560, accuracy); + test_format_timespan_one(1234567, accuracy); + test_format_timespan_one(986087, accuracy); + test_format_timespan_one(500 * USEC_PER_MSEC, accuracy); + test_format_timespan_one(9*USEC_PER_YEAR/5 - 23, accuracy); + test_format_timespan_one(USEC_INFINITY, accuracy); +} + +static void test_timezone_is_valid(void) { + log_info("/* %s */", __func__); + + assert_se(timezone_is_valid("Europe/Berlin", LOG_ERR)); + assert_se(timezone_is_valid("Australia/Sydney", LOG_ERR)); + assert_se(!timezone_is_valid("Europe/Do not exist", LOG_ERR)); +} + +static void test_get_timezones(void) { + _cleanup_strv_free_ char **zones = NULL; + int r; + char **zone; + + log_info("/* %s */", __func__); + + r = get_timezones(&zones); + assert_se(r == 0); + + STRV_FOREACH(zone, zones) { + log_info("zone: %s", *zone); + assert_se(timezone_is_valid(*zone, LOG_ERR)); + } +} + +static void test_usec_add(void) { + log_info("/* %s */", __func__); + + assert_se(usec_add(0, 0) == 0); + assert_se(usec_add(1, 4) == 5); + assert_se(usec_add(USEC_INFINITY, 5) == USEC_INFINITY); + assert_se(usec_add(5, USEC_INFINITY) == USEC_INFINITY); + assert_se(usec_add(USEC_INFINITY-5, 2) == USEC_INFINITY-3); + assert_se(usec_add(USEC_INFINITY-2, 2) == USEC_INFINITY); + assert_se(usec_add(USEC_INFINITY-1, 2) == USEC_INFINITY); + assert_se(usec_add(USEC_INFINITY, 2) == USEC_INFINITY); +} + +static void test_usec_sub_unsigned(void) { + log_info("/* %s */", __func__); + + assert_se(usec_sub_unsigned(0, 0) == 0); + assert_se(usec_sub_unsigned(0, 2) == 0); + assert_se(usec_sub_unsigned(0, USEC_INFINITY) == 0); + assert_se(usec_sub_unsigned(1, 0) == 1); + assert_se(usec_sub_unsigned(1, 1) == 0); + assert_se(usec_sub_unsigned(1, 2) == 0); + assert_se(usec_sub_unsigned(1, 3) == 0); + assert_se(usec_sub_unsigned(1, USEC_INFINITY) == 0); + assert_se(usec_sub_unsigned(USEC_INFINITY-1, 0) == USEC_INFINITY-1); + assert_se(usec_sub_unsigned(USEC_INFINITY-1, 1) == USEC_INFINITY-2); + assert_se(usec_sub_unsigned(USEC_INFINITY-1, 2) == USEC_INFINITY-3); + assert_se(usec_sub_unsigned(USEC_INFINITY-1, USEC_INFINITY-2) == 1); + assert_se(usec_sub_unsigned(USEC_INFINITY-1, USEC_INFINITY-1) == 0); + assert_se(usec_sub_unsigned(USEC_INFINITY-1, USEC_INFINITY) == 0); + assert_se(usec_sub_unsigned(USEC_INFINITY, 0) == USEC_INFINITY); + assert_se(usec_sub_unsigned(USEC_INFINITY, 1) == USEC_INFINITY); + assert_se(usec_sub_unsigned(USEC_INFINITY, 2) == USEC_INFINITY); + assert_se(usec_sub_unsigned(USEC_INFINITY, USEC_INFINITY) == USEC_INFINITY); +} + +static void test_usec_sub_signed(void) { + log_info("/* %s */", __func__); + + assert_se(usec_sub_signed(0, 0) == 0); + assert_se(usec_sub_signed(4, 1) == 3); + assert_se(usec_sub_signed(4, 4) == 0); + assert_se(usec_sub_signed(4, 5) == 0); + assert_se(usec_sub_signed(USEC_INFINITY-3, -3) == USEC_INFINITY); + assert_se(usec_sub_signed(USEC_INFINITY-3, -4) == USEC_INFINITY); + assert_se(usec_sub_signed(USEC_INFINITY-3, -5) == USEC_INFINITY); + assert_se(usec_sub_signed(USEC_INFINITY, 5) == USEC_INFINITY); +} + +static void test_format_timestamp(void) { + unsigned i; + + log_info("/* %s */", __func__); + + for (i = 0; i < 100; i++) { + char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESPAN_MAX)]; + usec_t x, y; + + random_bytes(&x, sizeof(x)); + x = x % (2147483600 * USEC_PER_SEC) + 1; + + assert_se(format_timestamp(buf, sizeof(buf), x)); + log_info("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC); + + assert_se(format_timestamp_utc(buf, sizeof(buf), x)); + log_info("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC); + + assert_se(format_timestamp_us(buf, sizeof(buf), x)); + log_info("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + assert_se(x == y); + + assert_se(format_timestamp_us_utc(buf, sizeof(buf), x)); + log_info("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + assert_se(x == y); + + assert_se(format_timestamp_relative(buf, sizeof(buf), x)); + log_info("%s", buf); + assert_se(parse_timestamp(buf, &y) >= 0); + + /* The two calls above will run with a slightly different local time. Make sure we are in the same + * range however, but give enough leeway that this is unlikely to explode. And of course, + * format_timestamp_relative() scales the accuracy with the distance from the current time up to one + * month, cover for that too. */ + assert_se(y > x ? y - x : x - y <= USEC_PER_MONTH + USEC_PER_DAY); + } +} + +static void test_format_timestamp_utc_one(usec_t val, const char *result) { + char buf[FORMAT_TIMESTAMP_MAX]; + const char *t; + + t = format_timestamp_utc(buf, sizeof(buf), val); + assert_se(streq_ptr(t, result)); +} + +static void test_format_timestamp_utc(void) { + log_info("/* %s */", __func__); + + test_format_timestamp_utc_one(0, NULL); + test_format_timestamp_utc_one(1, "Thu 1970-01-01 00:00:00 UTC"); + test_format_timestamp_utc_one(USEC_PER_SEC, "Thu 1970-01-01 00:00:01 UTC"); + +#if SIZEOF_TIME_T == 8 + test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Thu 9999-12-30 23:59:59 UTC"); + test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX"); +#elif SIZEOF_TIME_T == 4 + test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Tue 2038-01-19 03:14:07 UTC"); + test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX"); +#endif + + test_format_timestamp_utc_one(USEC_INFINITY, NULL); +} + +static void test_deserialize_dual_timestamp(void) { + int r; + dual_timestamp t; + + log_info("/* %s */", __func__); + + r = deserialize_dual_timestamp("1234 5678", &t); + assert_se(r == 0); + assert_se(t.realtime == 1234); + assert_se(t.monotonic == 5678); + + r = deserialize_dual_timestamp("1234x 5678", &t); + assert_se(r == -EINVAL); + + r = deserialize_dual_timestamp("1234 5678y", &t); + assert_se(r == -EINVAL); + + r = deserialize_dual_timestamp("-1234 5678", &t); + assert_se(r == -EINVAL); + + r = deserialize_dual_timestamp("1234 -5678", &t); + assert_se(r == -EINVAL); + + /* Check that output wasn't modified. */ + assert_se(t.realtime == 1234); + assert_se(t.monotonic == 5678); + + r = deserialize_dual_timestamp("+123 567", &t); + assert_se(r == 0); + assert_se(t.realtime == 123); + assert_se(t.monotonic == 567); + + /* Check that we get "infinity" on overflow. */ + r = deserialize_dual_timestamp("18446744073709551617 0", &t); + assert_se(r == 0); + assert_se(t.realtime == USEC_INFINITY); + assert_se(t.monotonic == 0); +} + +static void assert_similar(usec_t a, usec_t b) { + usec_t d; + + if (a > b) + d = a - b; + else + d = b - a; + + assert(d < 10*USEC_PER_SEC); +} + +static void test_usec_shift_clock(void) { + usec_t rt, mn, bt; + + log_info("/* %s */", __func__); + + rt = now(CLOCK_REALTIME); + mn = now(CLOCK_MONOTONIC); + bt = now(clock_boottime_or_monotonic()); + + assert_se(usec_shift_clock(USEC_INFINITY, CLOCK_REALTIME, CLOCK_MONOTONIC) == USEC_INFINITY); + + assert_similar(usec_shift_clock(rt + USEC_PER_HOUR, CLOCK_REALTIME, CLOCK_MONOTONIC), mn + USEC_PER_HOUR); + assert_similar(usec_shift_clock(rt + 2*USEC_PER_HOUR, CLOCK_REALTIME, clock_boottime_or_monotonic()), bt + 2*USEC_PER_HOUR); + assert_se(usec_shift_clock(rt + 3*USEC_PER_HOUR, CLOCK_REALTIME, CLOCK_REALTIME_ALARM) == rt + 3*USEC_PER_HOUR); + + assert_similar(usec_shift_clock(mn + 4*USEC_PER_HOUR, CLOCK_MONOTONIC, CLOCK_REALTIME_ALARM), rt + 4*USEC_PER_HOUR); + assert_similar(usec_shift_clock(mn + 5*USEC_PER_HOUR, CLOCK_MONOTONIC, clock_boottime_or_monotonic()), bt + 5*USEC_PER_HOUR); + assert_se(usec_shift_clock(mn + 6*USEC_PER_HOUR, CLOCK_MONOTONIC, CLOCK_MONOTONIC) == mn + 6*USEC_PER_HOUR); + + assert_similar(usec_shift_clock(bt + 7*USEC_PER_HOUR, clock_boottime_or_monotonic(), CLOCK_MONOTONIC), mn + 7*USEC_PER_HOUR); + assert_similar(usec_shift_clock(bt + 8*USEC_PER_HOUR, clock_boottime_or_monotonic(), CLOCK_REALTIME_ALARM), rt + 8*USEC_PER_HOUR); + assert_se(usec_shift_clock(bt + 9*USEC_PER_HOUR, clock_boottime_or_monotonic(), clock_boottime_or_monotonic()) == bt + 9*USEC_PER_HOUR); + + if (mn > USEC_PER_MINUTE) { + assert_similar(usec_shift_clock(rt - 30 * USEC_PER_SEC, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC), mn - 30 * USEC_PER_SEC); + assert_similar(usec_shift_clock(rt - 50 * USEC_PER_SEC, CLOCK_REALTIME, clock_boottime_or_monotonic()), bt - 50 * USEC_PER_SEC); + } +} + +static void test_in_utc_timezone(void) { + log_info("/* %s */", __func__); + + assert_se(setenv("TZ", ":UTC", 1) >= 0); + assert_se(in_utc_timezone()); + assert_se(streq(tzname[0], "UTC")); + assert_se(streq(tzname[1], "UTC")); + assert_se(timezone == 0); + assert_se(daylight == 0); + + assert_se(setenv("TZ", ":Europe/Berlin", 1) >= 0); + assert_se(!in_utc_timezone()); + assert_se(streq(tzname[0], "CET")); + assert_se(streq(tzname[1], "CEST")); + + assert_se(unsetenv("TZ") >= 0); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + log_info("realtime=" USEC_FMT "\n" + "monotonic=" USEC_FMT "\n" + "boottime=" USEC_FMT "\n", + now(CLOCK_REALTIME), + now(CLOCK_MONOTONIC), + now(clock_boottime_or_monotonic())); + + test_parse_sec(); + test_parse_sec_fix_0(); + test_parse_sec_def_infinity(); + test_parse_time(); + test_parse_nsec(); + test_format_timespan(1); + test_format_timespan(USEC_PER_MSEC); + test_format_timespan(USEC_PER_SEC); + test_timezone_is_valid(); + test_get_timezones(); + test_usec_add(); + test_usec_sub_signed(); + test_usec_sub_unsigned(); + test_format_timestamp(); + test_format_timestamp_utc(); + test_deserialize_dual_timestamp(); + test_usec_shift_clock(); + test_in_utc_timezone(); + + /* Ensure time_t is signed */ + assert_cc((time_t) -1 < (time_t) 1); + + /* Ensure TIME_T_MAX works correctly */ + uintmax_t x = TIME_T_MAX; + x++; + assert((time_t) x < 0); + + return 0; +} diff --git a/src/test/test-tmpfiles.c b/src/test/test-tmpfiles.c new file mode 100644 index 00000000..b5268716 --- /dev/null +++ b/src/test/test-tmpfiles.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "log.h" +#include "process-util.h" +#include "string-util.h" +#include "tests.h" +#include "tmpfile-util.h" +#include "util.h" + +int main(int argc, char** argv) { + _cleanup_free_ char *cmd = NULL, *cmd2 = NULL, *ans = NULL, *ans2 = NULL, *d = NULL, *tmp = NULL, *line = NULL; + _cleanup_close_ int fd = -1, fd2 = -1; + const char *p = argv[1] ?: "/tmp"; + char *pattern; + + test_setup_logging(LOG_DEBUG); + + pattern = strjoina(p, "/systemd-test-XXXXXX"); + + fd = open_tmpfile_unlinkable(p, O_RDWR|O_CLOEXEC); + assert_se(fd >= 0); + + assert_se(asprintf(&cmd, "ls -l /proc/"PID_FMT"/fd/%d", getpid_cached(), fd) > 0); + (void) system(cmd); + assert_se(readlink_malloc(cmd + 6, &ans) >= 0); + log_debug("link1: %s", ans); + assert_se(endswith(ans, " (deleted)")); + + fd2 = mkostemp_safe(pattern); + assert_se(fd >= 0); + assert_se(unlink(pattern) == 0); + + assert_se(asprintf(&cmd2, "ls -l /proc/"PID_FMT"/fd/%d", getpid_cached(), fd2) > 0); + (void) system(cmd2); + assert_se(readlink_malloc(cmd2 + 6, &ans2) >= 0); + log_debug("link2: %s", ans2); + assert_se(endswith(ans2, " (deleted)")); + + pattern = strjoina(p, "/tmpfiles-test"); + assert_se(tempfn_random(pattern, NULL, &d) >= 0); + + fd = open_tmpfile_linkable(d, O_RDWR|O_CLOEXEC, &tmp); + assert_se(fd >= 0); + assert_se(write(fd, "foobar\n", 7) == 7); + + assert_se(touch(d) >= 0); + assert_se(link_tmpfile(fd, tmp, d) == -EEXIST); + assert_se(unlink(d) >= 0); + assert_se(link_tmpfile(fd, tmp, d) >= 0); + + assert_se(read_one_line_file(d, &line) >= 0); + assert_se(streq(line, "foobar")); + assert_se(unlink(d) >= 0); + + return 0; +} diff --git a/src/test/test-udev.c b/src/test/test-udev.c new file mode 100644 index 00000000..e87a8ec0 --- /dev/null +++ b/src/test/test-udev.c @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2003-2004 Greg Kroah-Hartman +***/ + +#include +#include +#include +#include +#include +#include +#include + +#include "build.h" +#include "device-private.h" +#include "fs-util.h" +#include "log.h" +#include "main-func.h" +#include "mkdir.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "string-util.h" +#include "tests.h" +#include "udev-event.h" + +static int fake_filesystems(void) { + static const struct fakefs { + const char *src; + const char *target; + const char *error; + bool ignore_mount_error; + } fakefss[] = { + { "test/tmpfs/sys", "/sys", "Failed to mount test /sys", false }, + { "test/tmpfs/dev", "/dev", "Failed to mount test /dev", false }, + { "test/run", "/run", "Failed to mount test /run", false }, + { "test/run", "/etc/udev/rules.d", "Failed to mount empty /etc/udev/rules.d", true }, + { "test/run", UDEVLIBEXECDIR "/rules.d", "Failed to mount empty " UDEVLIBEXECDIR "/rules.d", true }, + }; + unsigned i; + + if (unshare(CLONE_NEWNS) < 0) + return log_error_errno(errno, "Failed to call unshare(): %m"); + + if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) + return log_error_errno(errno, "Failed to mount / as private: %m"); + + for (i = 0; i < ELEMENTSOF(fakefss); i++) + if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) { + log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error); + if (!fakefss[i].ignore_mount_error) + return -errno; + } + + return 0; +} + +static int run(int argc, char *argv[]) { + _cleanup_(udev_rules_freep) UdevRules *rules = NULL; + _cleanup_(udev_event_freep) UdevEvent *event = NULL; + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + const char *devpath, *devname, *action; + int r; + + test_setup_logging(LOG_INFO); + + if (!IN_SET(argc, 2, 3)) { + log_error("This program needs one or two arguments, %d given", argc - 1); + return -EINVAL; + } + + r = fake_filesystems(); + if (r < 0) + return r; + + if (argc == 2) { + if (!streq(argv[1], "check")) { + log_error("Unknown argument: %s", argv[1]); + return -EINVAL; + } + + return 0; + } + + log_debug("version %s", GIT_VERSION); + mac_selinux_init(); + + action = argv[1]; + devpath = argv[2]; + + assert_se(udev_rules_new(&rules, RESOLVE_NAME_EARLY) == 0); + + const char *syspath = strjoina("/sys", devpath); + r = device_new_from_synthetic_event(&dev, syspath, action); + if (r < 0) + return log_debug_errno(r, "Failed to open device '%s'", devpath); + + assert_se(event = udev_event_new(dev, 0, NULL)); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0); + + /* do what devtmpfs usually provides us */ + if (sd_device_get_devname(dev, &devname) >= 0) { + const char *subsystem; + mode_t mode = 0600; + + if (sd_device_get_subsystem(dev, &subsystem) >= 0 && streq(subsystem, "block")) + mode |= S_IFBLK; + else + mode |= S_IFCHR; + + if (!streq(action, "remove")) { + dev_t devnum = makedev(0, 0); + + (void) mkdir_parents_label(devname, 0755); + (void) sd_device_get_devnum(dev, &devnum); + if (mknod(devname, mode, devnum) < 0) + return log_error_errno(errno, "mknod() failed for '%s': %m", devname); + } else { + if (unlink(devname) < 0) + return log_error_errno(errno, "unlink('%s') failed: %m", devname); + (void) rmdir_parents(devname, "/"); + } + } + + udev_event_execute_rules(event, 3 * USEC_PER_SEC, NULL, rules); + udev_event_execute_run(event, 3 * USEC_PER_SEC); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/test/test-uid-range.c b/src/test/test-uid-range.c new file mode 100644 index 00000000..65a556c9 --- /dev/null +++ b/src/test/test-uid-range.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "uid-range.h" +#include "user-util.h" +#include "util.h" + +int main(int argc, char *argv[]) { + _cleanup_free_ UidRange *p = NULL; + unsigned n = 0; + uid_t search; + + assert_se(uid_range_add_str(&p, &n, "500-999") >= 0); + assert_se(n == 1); + assert_se(p[0].start == 500); + assert_se(p[0].nr == 500); + + assert_se(!uid_range_contains(p, n, 499)); + assert_se(uid_range_contains(p, n, 500)); + assert_se(uid_range_contains(p, n, 999)); + assert_se(!uid_range_contains(p, n, 1000)); + + search = UID_INVALID; + assert_se(uid_range_next_lower(p, n, &search)); + assert_se(search == 999); + assert_se(uid_range_next_lower(p, n, &search)); + assert_se(search == 998); + search = 501; + assert_se(uid_range_next_lower(p, n, &search)); + assert_se(search == 500); + assert_se(uid_range_next_lower(p, n, &search) == -EBUSY); + + assert_se(uid_range_add_str(&p, &n, "1000") >= 0); + assert_se(n == 1); + assert_se(p[0].start == 500); + assert_se(p[0].nr == 501); + + assert_se(uid_range_add_str(&p, &n, "30-40") >= 0); + assert_se(n == 2); + assert_se(p[0].start == 30); + assert_se(p[0].nr == 11); + assert_se(p[1].start == 500); + assert_se(p[1].nr == 501); + + assert_se(uid_range_add_str(&p, &n, "60-70") >= 0); + assert_se(n == 3); + assert_se(p[0].start == 30); + assert_se(p[0].nr == 11); + assert_se(p[1].start == 60); + assert_se(p[1].nr == 11); + assert_se(p[2].start == 500); + assert_se(p[2].nr == 501); + + assert_se(uid_range_add_str(&p, &n, "20-2000") >= 0); + assert_se(n == 1); + assert_se(p[0].start == 20); + assert_se(p[0].nr == 1981); + + assert_se(uid_range_add_str(&p, &n, "2002") >= 0); + assert_se(n == 2); + assert_se(p[0].start == 20); + assert_se(p[0].nr == 1981); + assert_se(p[1].start == 2002); + assert_se(p[1].nr == 1); + + assert_se(uid_range_add_str(&p, &n, "2001") >= 0); + assert_se(n == 1); + assert_se(p[0].start == 20); + assert_se(p[0].nr == 1983); + + return 0; +} diff --git a/src/test/test-umask-util.c b/src/test/test-umask-util.c new file mode 100644 index 00000000..27f6b565 --- /dev/null +++ b/src/test/test-umask-util.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "tests.h" +#include "umask-util.h" + +int main(int argc, char *argv[]) { + size_t n; + mode_t u; + + test_setup_logging(LOG_DEBUG); + + u = umask(0111); + + n = 0; + RUN_WITH_UMASK(0123) { + assert_se(umask(000) == 0123); + n++; + } + + assert_se(n == 1); + assert_se(umask(u) == 0111); + + RUN_WITH_UMASK(0135) { + assert_se(umask(000) == 0135); + n++; + } + + assert_se(n == 2); + assert_se(umask(0111) == u); + + RUN_WITH_UMASK(0315) { + assert_se(umask(000) == 0315); + n++; + break; + } + + assert_se(n == 3); + assert_se(umask(u) == 0111); + + return EXIT_SUCCESS; +} diff --git a/src/test/test-umount.c b/src/test/test-umount.c new file mode 100644 index 00000000..6ab5758e --- /dev/null +++ b/src/test/test-umount.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "log.h" +#include "path-util.h" +#include "string-util.h" +#include "tests.h" +#include "umount.h" +#include "util.h" + +static void test_mount_points_list(const char *fname) { + _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head); + _cleanup_free_ char *testdata_fname = NULL; + MountPoint *m; + + log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/self/mountinfo"); + + if (fname) + fname = testdata_fname = path_join(get_testdata_dir(), fname); + + LIST_HEAD_INIT(mp_list_head); + assert_se(mount_points_list_get(fname, &mp_list_head) >= 0); + + LIST_FOREACH(mount_point, m, mp_list_head) + log_debug("path=%s o=%s f=0x%lx try-ro=%s dev=%u:%u", + m->path, + strempty(m->remount_options), + m->remount_flags, + yes_no(m->try_remount_ro), + major(m->devnum), minor(m->devnum)); +} + +static void test_swap_list(const char *fname) { + _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head); + _cleanup_free_ char *testdata_fname = NULL; + MountPoint *m; + + log_info("/* %s(\"%s\") */", __func__, fname ?: "/proc/swaps"); + + if (fname) + fname = testdata_fname = path_join(get_testdata_dir(), fname); + + LIST_HEAD_INIT(mp_list_head); + assert_se(swap_list_get(fname, &mp_list_head) >= 0); + + LIST_FOREACH(mount_point, m, mp_list_head) + log_debug("path=%s o=%s f=0x%lx try-ro=%s dev=%u:%u", + m->path, + strempty(m->remount_options), + m->remount_flags, + yes_no(m->try_remount_ro), + major(m->devnum), minor(m->devnum)); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_mount_points_list(NULL); + test_mount_points_list("/test-umount/empty.mountinfo"); + test_mount_points_list("/test-umount/garbled.mountinfo"); + test_mount_points_list("/test-umount/rhbug-1554943.mountinfo"); + + test_swap_list(NULL); + test_swap_list("/test-umount/example.swaps"); +} diff --git a/src/test/test-unaligned.c b/src/test/test-unaligned.c new file mode 100644 index 00000000..3d6f9a03 --- /dev/null +++ b/src/test/test-unaligned.c @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "memory-util.h" +#include "sparse-endian.h" +#include "unaligned.h" + +static uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +}; + +static void test_be(void) { + uint8_t scratch[16]; + + assert_se(unaligned_read_be16(&data[0]) == 0x0001); + assert_se(unaligned_read_be16(&data[1]) == 0x0102); + + assert_se(unaligned_read_be32(&data[0]) == 0x00010203); + assert_se(unaligned_read_be32(&data[1]) == 0x01020304); + assert_se(unaligned_read_be32(&data[2]) == 0x02030405); + assert_se(unaligned_read_be32(&data[3]) == 0x03040506); + + assert_se(unaligned_read_be64(&data[0]) == 0x0001020304050607); + assert_se(unaligned_read_be64(&data[1]) == 0x0102030405060708); + assert_se(unaligned_read_be64(&data[2]) == 0x0203040506070809); + assert_se(unaligned_read_be64(&data[3]) == 0x030405060708090a); + assert_se(unaligned_read_be64(&data[4]) == 0x0405060708090a0b); + assert_se(unaligned_read_be64(&data[5]) == 0x05060708090a0b0c); + assert_se(unaligned_read_be64(&data[6]) == 0x060708090a0b0c0d); + assert_se(unaligned_read_be64(&data[7]) == 0x0708090a0b0c0d0e); + + zero(scratch); + unaligned_write_be16(&scratch[0], 0x0001); + assert_se(memcmp(&scratch[0], &data[0], sizeof(uint16_t)) == 0); + zero(scratch); + unaligned_write_be16(&scratch[1], 0x0102); + assert_se(memcmp(&scratch[1], &data[1], sizeof(uint16_t)) == 0); + + zero(scratch); + unaligned_write_be32(&scratch[0], 0x00010203); + assert_se(memcmp(&scratch[0], &data[0], sizeof(uint32_t)) == 0); + zero(scratch); + unaligned_write_be32(&scratch[1], 0x01020304); + assert_se(memcmp(&scratch[1], &data[1], sizeof(uint32_t)) == 0); + zero(scratch); + unaligned_write_be32(&scratch[2], 0x02030405); + assert_se(memcmp(&scratch[2], &data[2], sizeof(uint32_t)) == 0); + zero(scratch); + unaligned_write_be32(&scratch[3], 0x03040506); + assert_se(memcmp(&scratch[3], &data[3], sizeof(uint32_t)) == 0); + + zero(scratch); + unaligned_write_be64(&scratch[0], 0x0001020304050607); + assert_se(memcmp(&scratch[0], &data[0], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_be64(&scratch[1], 0x0102030405060708); + assert_se(memcmp(&scratch[1], &data[1], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_be64(&scratch[2], 0x0203040506070809); + assert_se(memcmp(&scratch[2], &data[2], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_be64(&scratch[3], 0x030405060708090a); + assert_se(memcmp(&scratch[3], &data[3], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_be64(&scratch[4], 0x0405060708090a0b); + assert_se(memcmp(&scratch[4], &data[4], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_be64(&scratch[5], 0x05060708090a0b0c); + assert_se(memcmp(&scratch[5], &data[5], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_be64(&scratch[6], 0x060708090a0b0c0d); + assert_se(memcmp(&scratch[6], &data[6], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_be64(&scratch[7], 0x0708090a0b0c0d0e); + assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0); +} + +static void test_le(void) { + uint8_t scratch[16]; + + assert_se(unaligned_read_le16(&data[0]) == 0x0100); + assert_se(unaligned_read_le16(&data[1]) == 0x0201); + + assert_se(unaligned_read_le32(&data[0]) == 0x03020100); + assert_se(unaligned_read_le32(&data[1]) == 0x04030201); + assert_se(unaligned_read_le32(&data[2]) == 0x05040302); + assert_se(unaligned_read_le32(&data[3]) == 0x06050403); + + assert_se(unaligned_read_le64(&data[0]) == 0x0706050403020100); + assert_se(unaligned_read_le64(&data[1]) == 0x0807060504030201); + assert_se(unaligned_read_le64(&data[2]) == 0x0908070605040302); + assert_se(unaligned_read_le64(&data[3]) == 0x0a09080706050403); + assert_se(unaligned_read_le64(&data[4]) == 0x0b0a090807060504); + assert_se(unaligned_read_le64(&data[5]) == 0x0c0b0a0908070605); + assert_se(unaligned_read_le64(&data[6]) == 0x0d0c0b0a09080706); + assert_se(unaligned_read_le64(&data[7]) == 0x0e0d0c0b0a090807); + + zero(scratch); + unaligned_write_le16(&scratch[0], 0x0100); + assert_se(memcmp(&scratch[0], &data[0], sizeof(uint16_t)) == 0); + zero(scratch); + unaligned_write_le16(&scratch[1], 0x0201); + assert_se(memcmp(&scratch[1], &data[1], sizeof(uint16_t)) == 0); + + zero(scratch); + unaligned_write_le32(&scratch[0], 0x03020100); + + assert_se(memcmp(&scratch[0], &data[0], sizeof(uint32_t)) == 0); + zero(scratch); + unaligned_write_le32(&scratch[1], 0x04030201); + assert_se(memcmp(&scratch[1], &data[1], sizeof(uint32_t)) == 0); + zero(scratch); + unaligned_write_le32(&scratch[2], 0x05040302); + assert_se(memcmp(&scratch[2], &data[2], sizeof(uint32_t)) == 0); + zero(scratch); + unaligned_write_le32(&scratch[3], 0x06050403); + assert_se(memcmp(&scratch[3], &data[3], sizeof(uint32_t)) == 0); + + zero(scratch); + unaligned_write_le64(&scratch[0], 0x0706050403020100); + assert_se(memcmp(&scratch[0], &data[0], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[1], 0x0807060504030201); + assert_se(memcmp(&scratch[1], &data[1], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[2], 0x0908070605040302); + assert_se(memcmp(&scratch[2], &data[2], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[3], 0x0a09080706050403); + assert_se(memcmp(&scratch[3], &data[3], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[4], 0x0B0A090807060504); + assert_se(memcmp(&scratch[4], &data[4], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[5], 0x0c0b0a0908070605); + assert_se(memcmp(&scratch[5], &data[5], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[6], 0x0d0c0b0a09080706); + assert_se(memcmp(&scratch[6], &data[6], sizeof(uint64_t)) == 0); + zero(scratch); + unaligned_write_le64(&scratch[7], 0x0e0d0c0b0a090807); + assert_se(memcmp(&scratch[7], &data[7], sizeof(uint64_t)) == 0); +} + +static void test_ne(void) { + uint16_t x = 4711; + uint32_t y = 123456; + uint64_t z = 9876543210; + + /* Note that we don't bother actually testing alignment issues in this function, after all the _ne() functions + * are just aliases for the _le() or _be() implementations, which we test extensively above. Hence, in this + * function, just ensure that they map to the right version on the local architecture. */ + + assert_se(unaligned_read_ne16(&x) == 4711); + assert_se(unaligned_read_ne32(&y) == 123456); + assert_se(unaligned_read_ne64(&z) == 9876543210); + + unaligned_write_ne16(&x, 1); + unaligned_write_ne32(&y, 2); + unaligned_write_ne64(&z, 3); + + assert_se(x == 1); + assert_se(y == 2); + assert_se(z == 3); +} + +int main(int argc, const char *argv[]) { + test_be(); + test_le(); + test_ne(); + return 0; +} diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c new file mode 100644 index 00000000..60211647 --- /dev/null +++ b/src/test/test-unit-file.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "path-lookup.h" +#include "set.h" +#include "special.h" +#include "strv.h" +#include "tests.h" +#include "unit-file.h" + +static void test_unit_validate_alias_symlink_and_warn(void) { + log_info("/* %s */", __func__); + + assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.service") == 0); + assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.socket") == -EXDEV); + assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.foobar") == -EXDEV); + assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@.service") == 0); + assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@.socket") == -EXDEV); + assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@YYY.service") == -EXDEV); + assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@YYY.socket") == -EXDEV); + assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@YYY.service") == -EXDEV); + assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@XXX.service") == 0); + assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@.service") == 0); + assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b.service") == -EXDEV); + assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b@.service") == -EXDEV); + assert_se(unit_validate_alias_symlink_and_warn("/path/a@.slice", "/other/b.slice") == -EINVAL); + assert_se(unit_validate_alias_symlink_and_warn("/path/a.slice", "/other/b.slice") == -EINVAL); +} + +static void test_unit_file_build_name_map(char **ids) { + _cleanup_(lookup_paths_free) LookupPaths lp = {}; + _cleanup_hashmap_free_ Hashmap *unit_ids = NULL; + _cleanup_hashmap_free_ Hashmap *unit_names = NULL; + Iterator i; + const char *k, *dst; + char **v; + usec_t mtime = 0; + int r; + + assert_se(lookup_paths_init(&lp, UNIT_FILE_SYSTEM, 0, NULL) >= 0); + + assert_se(unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL) == 1); + + HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) + log_info("ids: %s → %s", k, dst); + + HASHMAP_FOREACH_KEY(v, k, unit_names, i) { + _cleanup_free_ char *j = strv_join(v, ", "); + log_info("aliases: %s ← %s", k, j); + } + + char buf[FORMAT_TIMESTAMP_MAX]; + log_debug("Last modification time: %s", format_timestamp(buf, sizeof buf, mtime)); + + r = unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL); + assert_se(IN_SET(r, 0, 1)); + if (r == 0) + log_debug("Cache rebuild skipped based on mtime."); + + char **id; + STRV_FOREACH(id, ids) { + const char *fragment, *name; + Iterator it; + _cleanup_set_free_free_ Set *names = NULL; + log_info("*** %s ***", *id); + r = unit_file_find_fragment(unit_ids, + unit_names, + *id, + &fragment, + &names); + assert(r == 0); + log_info("fragment: %s", fragment); + log_info("names:"); + SET_FOREACH(name, names, it) + log_info(" %s", name); + } +} + +static void test_runlevel_to_target(void) { + log_info("/* %s */", __func__); + + in_initrd_force(false); + assert_se(streq_ptr(runlevel_to_target(NULL), NULL)); + assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL)); + assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL)); + assert_se(streq_ptr(runlevel_to_target("3"), SPECIAL_MULTI_USER_TARGET)); + assert_se(streq_ptr(runlevel_to_target("rd.rescue"), NULL)); + + in_initrd_force(true); + assert_se(streq_ptr(runlevel_to_target(NULL), NULL)); + assert_se(streq_ptr(runlevel_to_target("unknown-runlevel"), NULL)); + assert_se(streq_ptr(runlevel_to_target("rd.unknown-runlevel"), NULL)); + assert_se(streq_ptr(runlevel_to_target("3"), NULL)); + assert_se(streq_ptr(runlevel_to_target("rd.rescue"), SPECIAL_RESCUE_TARGET)); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_unit_validate_alias_symlink_and_warn(); + test_unit_file_build_name_map(strv_skip(argv, 1)); + test_runlevel_to_target(); + + return 0; +} diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c new file mode 100644 index 00000000..5d18711a --- /dev/null +++ b/src/test/test-unit-name.c @@ -0,0 +1,901 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "alloc-util.h" +#include "all-units.h" +#include "glob-util.h" +#include "format-util.h" +#include "hostname-util.h" +#include "macro.h" +#include "manager.h" +#include "path-util.h" +#include "rm-rf.h" +#include "special.h" +#include "specifier.h" +#include "string-util.h" +#include "tests.h" +#include "unit-def.h" +#include "unit-name.h" +#include "unit-printf.h" +#include "unit.h" +#include "user-util.h" +#include "util.h" + +static void test_unit_name_is_valid_one(const char *name, UnitNameFlags flags, bool expected) { + log_info("%s ( %s%s%s ): %s", + name, + (flags & UNIT_NAME_PLAIN) ? "plain" : "", + (flags & UNIT_NAME_INSTANCE) ? " instance" : "", + (flags & UNIT_NAME_TEMPLATE) ? " template" : "", + yes_no(expected)); + assert_se(unit_name_is_valid(name, flags) == expected); +} + +static void test_unit_name_is_valid(void) { + log_info("/* %s */", __func__); + + test_unit_name_is_valid_one("foo.service", UNIT_NAME_ANY, true); + test_unit_name_is_valid_one("foo.service", UNIT_NAME_PLAIN, true); + test_unit_name_is_valid_one("foo.service", UNIT_NAME_INSTANCE, false); + test_unit_name_is_valid_one("foo.service", UNIT_NAME_TEMPLATE, false); + test_unit_name_is_valid_one("foo.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE, false); + + test_unit_name_is_valid_one("foo@bar.service", UNIT_NAME_ANY, true); + test_unit_name_is_valid_one("foo@bar.service", UNIT_NAME_PLAIN, false); + test_unit_name_is_valid_one("foo@bar.service", UNIT_NAME_INSTANCE, true); + test_unit_name_is_valid_one("foo@bar.service", UNIT_NAME_TEMPLATE, false); + test_unit_name_is_valid_one("foo@bar.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE, true); + + test_unit_name_is_valid_one("foo@bar@bar.service", UNIT_NAME_ANY, true); + test_unit_name_is_valid_one("foo@bar@bar.service", UNIT_NAME_PLAIN, false); + test_unit_name_is_valid_one("foo@bar@bar.service", UNIT_NAME_INSTANCE, true); + test_unit_name_is_valid_one("foo@bar@bar.service", UNIT_NAME_TEMPLATE, false); + test_unit_name_is_valid_one("foo@bar@bar.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE, true); + + test_unit_name_is_valid_one("foo@.service", UNIT_NAME_ANY, true); + test_unit_name_is_valid_one("foo@.service", UNIT_NAME_PLAIN, false); + test_unit_name_is_valid_one("foo@.service", UNIT_NAME_INSTANCE, false); + test_unit_name_is_valid_one("foo@.service", UNIT_NAME_TEMPLATE, true); + test_unit_name_is_valid_one("foo@.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE, true); + test_unit_name_is_valid_one(".test.service", UNIT_NAME_PLAIN, true); + test_unit_name_is_valid_one(".test@.service", UNIT_NAME_TEMPLATE, true); + test_unit_name_is_valid_one("_strange::::.service", UNIT_NAME_ANY, true); + + test_unit_name_is_valid_one(".service", UNIT_NAME_ANY, false); + test_unit_name_is_valid_one("", UNIT_NAME_ANY, false); + test_unit_name_is_valid_one("foo.waldo", UNIT_NAME_ANY, false); + test_unit_name_is_valid_one("@.service", UNIT_NAME_ANY, false); + test_unit_name_is_valid_one("@piep.service", UNIT_NAME_ANY, false); + + test_unit_name_is_valid_one("user@1000.slice", UNIT_NAME_ANY, true); + test_unit_name_is_valid_one("user@1000.slice", UNIT_NAME_INSTANCE, true); + test_unit_name_is_valid_one("user@1000.slice", UNIT_NAME_TEMPLATE, false); + + test_unit_name_is_valid_one("foo@%i.service", UNIT_NAME_ANY, false); + test_unit_name_is_valid_one("foo@%i.service", UNIT_NAME_INSTANCE, false); + test_unit_name_is_valid_one("foo@%%i.service", UNIT_NAME_INSTANCE, false); + test_unit_name_is_valid_one("foo@%%i%f.service", UNIT_NAME_INSTANCE, false); + test_unit_name_is_valid_one("foo@%F.service", UNIT_NAME_INSTANCE, false); +} + +static void test_unit_name_replace_instance_one(const char *pattern, const char *repl, const char *expected, int ret) { + _cleanup_free_ char *t = NULL; + assert_se(unit_name_replace_instance(pattern, repl, &t) == ret); + puts(strna(t)); + assert_se(streq_ptr(t, expected)); +} + +static void test_unit_name_replace_instance(void) { + log_info("/* %s */", __func__); + + test_unit_name_replace_instance_one("foo@.service", "waldo", "foo@waldo.service", 0); + test_unit_name_replace_instance_one("foo@xyz.service", "waldo", "foo@waldo.service", 0); + test_unit_name_replace_instance_one("xyz", "waldo", NULL, -EINVAL); + test_unit_name_replace_instance_one("", "waldo", NULL, -EINVAL); + test_unit_name_replace_instance_one("foo.service", "waldo", NULL, -EINVAL); + test_unit_name_replace_instance_one(".service", "waldo", NULL, -EINVAL); + test_unit_name_replace_instance_one("foo@", "waldo", NULL, -EINVAL); + test_unit_name_replace_instance_one("@bar", "waldo", NULL, -EINVAL); +} + +static void test_unit_name_from_path_one(const char *path, const char *suffix, const char *expected, int ret) { + _cleanup_free_ char *t = NULL; + + assert_se(unit_name_from_path(path, suffix, &t) == ret); + puts(strna(t)); + assert_se(streq_ptr(t, expected)); + + if (t) { + _cleanup_free_ char *k = NULL; + assert_se(unit_name_to_path(t, &k) == 0); + puts(strna(k)); + assert_se(path_equal(k, empty_to_root(path))); + } +} + +static void test_unit_name_from_path(void) { + log_info("/* %s */", __func__); + + test_unit_name_from_path_one("/waldo", ".mount", "waldo.mount", 0); + test_unit_name_from_path_one("/waldo/quuix", ".mount", "waldo-quuix.mount", 0); + test_unit_name_from_path_one("/waldo/quuix/", ".mount", "waldo-quuix.mount", 0); + test_unit_name_from_path_one("", ".mount", "-.mount", 0); + test_unit_name_from_path_one("/", ".mount", "-.mount", 0); + test_unit_name_from_path_one("///", ".mount", "-.mount", 0); + test_unit_name_from_path_one("/foo/../bar", ".mount", NULL, -EINVAL); + test_unit_name_from_path_one("/foo/./bar", ".mount", NULL, -EINVAL); +} + +static void test_unit_name_from_path_instance_one(const char *pattern, const char *path, const char *suffix, const char *expected, int ret) { + _cleanup_free_ char *t = NULL; + + assert_se(unit_name_from_path_instance(pattern, path, suffix, &t) == ret); + puts(strna(t)); + assert_se(streq_ptr(t, expected)); + + if (t) { + _cleanup_free_ char *k = NULL, *v = NULL; + + assert_se(unit_name_to_instance(t, &k) > 0); + assert_se(unit_name_path_unescape(k, &v) == 0); + assert_se(path_equal(v, empty_to_root(path))); + } +} + +static void test_unit_name_from_path_instance(void) { + log_info("/* %s */", __func__); + + test_unit_name_from_path_instance_one("waldo", "/waldo", ".mount", "waldo@waldo.mount", 0); + test_unit_name_from_path_instance_one("waldo", "/waldo////quuix////", ".mount", "waldo@waldo-quuix.mount", 0); + test_unit_name_from_path_instance_one("waldo", "/", ".mount", "waldo@-.mount", 0); + test_unit_name_from_path_instance_one("waldo", "", ".mount", "waldo@-.mount", 0); + test_unit_name_from_path_instance_one("waldo", "///", ".mount", "waldo@-.mount", 0); + test_unit_name_from_path_instance_one("waldo", "..", ".mount", NULL, -EINVAL); + test_unit_name_from_path_instance_one("waldo", "/foo", ".waldi", NULL, -EINVAL); + test_unit_name_from_path_instance_one("wa--ldo", "/--", ".mount", "wa--ldo@\\x2d\\x2d.mount", 0); +} + +static void test_unit_name_to_path_one(const char *unit, const char *path, int ret) { + _cleanup_free_ char *p = NULL; + + assert_se(unit_name_to_path(unit, &p) == ret); + assert_se(streq_ptr(path, p)); +} + +static void test_unit_name_to_path(void) { + log_info("/* %s */", __func__); + + test_unit_name_to_path_one("home.mount", "/home", 0); + test_unit_name_to_path_one("home-lennart.mount", "/home/lennart", 0); + test_unit_name_to_path_one("home-lennart-.mount", NULL, -EINVAL); + test_unit_name_to_path_one("-home-lennart.mount", NULL, -EINVAL); + test_unit_name_to_path_one("-home--lennart.mount", NULL, -EINVAL); + test_unit_name_to_path_one("home-..-lennart.mount", NULL, -EINVAL); + test_unit_name_to_path_one("", NULL, -EINVAL); + test_unit_name_to_path_one("home/foo", NULL, -EINVAL); +} + +static void test_unit_name_mangle_one(bool allow_globs, const char *pattern, const char *expect, int ret) { + _cleanup_free_ char *t = NULL; + + assert_se(unit_name_mangle(pattern, (allow_globs * UNIT_NAME_MANGLE_GLOB) | UNIT_NAME_MANGLE_WARN, &t) == ret); + puts(strna(t)); + assert_se(streq_ptr(t, expect)); + + if (t) { + _cleanup_free_ char *k = NULL; + + assert_se(unit_name_is_valid(t, UNIT_NAME_ANY) || + (allow_globs && string_is_glob(t))); + + assert_se(unit_name_mangle(t, (allow_globs * UNIT_NAME_MANGLE_GLOB) | UNIT_NAME_MANGLE_WARN, &k) == 0); + assert_se(streq_ptr(t, k)); + } +} + +static void test_unit_name_mangle(void) { + log_info("/* %s */", __func__); + + test_unit_name_mangle_one(false, "foo.service", "foo.service", 0); + test_unit_name_mangle_one(false, "/home", "home.mount", 1); + test_unit_name_mangle_one(false, "/dev/sda", "dev-sda.device", 1); + test_unit_name_mangle_one(false, "üxknürz.service", "\\xc3\\xbcxkn\\xc3\\xbcrz.service", 1); + test_unit_name_mangle_one(false, "foobar-meh...waldi.service", "foobar-meh...waldi.service", 0); + test_unit_name_mangle_one(false, "_____####----.....service", "_____\\x23\\x23\\x23\\x23----.....service", 1); + test_unit_name_mangle_one(false, "_____##@;;;,,,##----.....service", "_____\\x23\\x23@\\x3b\\x3b\\x3b\\x2c\\x2c\\x2c\\x23\\x23----.....service", 1); + test_unit_name_mangle_one(false, "xxx@@@@/////\\\\\\\\\\yyy.service", "xxx@@@@-----\\\\\\\\\\yyy.service", 1); + test_unit_name_mangle_one(false, "", NULL, -EINVAL); + + test_unit_name_mangle_one(true, "foo.service", "foo.service", 0); + test_unit_name_mangle_one(true, "foo", "foo.service", 1); + test_unit_name_mangle_one(true, "foo*", "foo*", 0); + test_unit_name_mangle_one(true, "ü*", "\\xc3\\xbc*", 1); +} + +static int test_unit_printf(void) { + _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL, *shell = NULL, *home = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + Unit *u; + int r; + + log_info("/* %s */", __func__); + + assert_se(specifier_machine_id('m', NULL, NULL, &mid) >= 0 && mid); + assert_se(specifier_boot_id('b', NULL, NULL, &bid) >= 0 && bid); + assert_se(host = gethostname_malloc()); + assert_se(user = uid_to_name(getuid())); + assert_se(group = gid_to_name(getgid())); + assert_se(asprintf(&uid, UID_FMT, getuid())); + assert_se(asprintf(&gid, UID_FMT, getgid())); + assert_se(get_home_dir(&home) >= 0); + assert_se(get_shell(&shell) >= 0); + + r = manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_MINIMAL, &m); + if (manager_errno_skip_test(r)) + return log_tests_skipped_errno(r, "manager_new"); + assert_se(r == 0); + +#define expect(unit, pattern, expected) \ + { \ + char *e; \ + _cleanup_free_ char *t = NULL; \ + assert_se(unit_full_printf(unit, pattern, &t) >= 0); \ + printf("result: %s\nexpect: %s\n", t, expected); \ + if ((e = endswith(expected, "*"))) \ + assert_se(strncmp(t, e, e-expected)); \ + else \ + assert_se(streq(t, expected)); \ + } + + assert_se(u = unit_new(m, sizeof(Service))); + assert_se(unit_add_name(u, "blah.service") == 0); + assert_se(unit_add_name(u, "blah.service") == 0); + + /* general tests */ + expect(u, "%%", "%"); + expect(u, "%%s", "%s"); + expect(u, "%,", "%,"); + expect(u, "%", "%"); + + /* normal unit */ + expect(u, "%n", "blah.service"); + expect(u, "%f", "/blah"); + expect(u, "%N", "blah"); + expect(u, "%p", "blah"); + expect(u, "%P", "blah"); + expect(u, "%i", ""); + expect(u, "%I", ""); + expect(u, "%j", "blah"); + expect(u, "%J", "blah"); + expect(u, "%g", group); + expect(u, "%G", gid); + expect(u, "%u", user); + expect(u, "%U", uid); + expect(u, "%h", home); + expect(u, "%m", mid); + expect(u, "%b", bid); + expect(u, "%H", host); + expect(u, "%t", "/run/user/*"); + + /* templated */ + assert_se(u = unit_new(m, sizeof(Service))); + assert_se(unit_add_name(u, "blah@foo-foo.service") == 0); + assert_se(unit_add_name(u, "blah@foo-foo.service") == 0); + + expect(u, "%n", "blah@foo-foo.service"); + expect(u, "%N", "blah@foo-foo"); + expect(u, "%f", "/foo/foo"); + expect(u, "%p", "blah"); + expect(u, "%P", "blah"); + expect(u, "%i", "foo-foo"); + expect(u, "%I", "foo/foo"); + expect(u, "%j", "blah"); + expect(u, "%J", "blah"); + expect(u, "%g", group); + expect(u, "%G", gid); + expect(u, "%u", user); + expect(u, "%U", uid); + expect(u, "%h", home); + expect(u, "%m", mid); + expect(u, "%b", bid); + expect(u, "%H", host); + expect(u, "%t", "/run/user/*"); + + /* templated with components */ + assert_se(u = unit_new(m, sizeof(Slice))); + assert_se(unit_add_name(u, "blah-blah\\x2d.slice") == 0); + + expect(u, "%n", "blah-blah\\x2d.slice"); + expect(u, "%N", "blah-blah\\x2d"); + expect(u, "%f", "/blah/blah-"); + expect(u, "%p", "blah-blah\\x2d"); + expect(u, "%P", "blah/blah-"); + expect(u, "%i", ""); + expect(u, "%I", ""); + expect(u, "%j", "blah\\x2d"); + expect(u, "%J", "blah-"); + +#undef expect + + return 0; +} + +static void test_unit_instance_is_valid(void) { + log_info("/* %s */", __func__); + + assert_se(unit_instance_is_valid("fooBar")); + assert_se(unit_instance_is_valid("foo-bar")); + assert_se(unit_instance_is_valid("foo.stUff")); + assert_se(unit_instance_is_valid("fOo123.stuff")); + assert_se(unit_instance_is_valid("@f_oo123.Stuff")); + + assert_se(!unit_instance_is_valid("$¢£")); + assert_se(!unit_instance_is_valid("")); + assert_se(!unit_instance_is_valid("foo bar")); + assert_se(!unit_instance_is_valid("foo/bar")); +} + +static void test_unit_prefix_is_valid(void) { + log_info("/* %s */", __func__); + + assert_se(unit_prefix_is_valid("fooBar")); + assert_se(unit_prefix_is_valid("foo-bar")); + assert_se(unit_prefix_is_valid("foo.stUff")); + assert_se(unit_prefix_is_valid("fOo123.stuff")); + assert_se(unit_prefix_is_valid("foo123.Stuff")); + + assert_se(!unit_prefix_is_valid("$¢£")); + assert_se(!unit_prefix_is_valid("")); + assert_se(!unit_prefix_is_valid("foo bar")); + assert_se(!unit_prefix_is_valid("foo/bar")); + assert_se(!unit_prefix_is_valid("@foo-bar")); +} + +static void test_unit_name_change_suffix(void) { + char *t; + + log_info("/* %s */", __func__); + + assert_se(unit_name_change_suffix("foo.mount", ".service", &t) == 0); + assert_se(streq(t, "foo.service")); + free(t); + + assert_se(unit_name_change_suffix("foo@stuff.service", ".socket", &t) == 0); + assert_se(streq(t, "foo@stuff.socket")); + free(t); +} + +static void test_unit_name_build(void) { + char *t; + + log_info("/* %s */", __func__); + + assert_se(unit_name_build("foo", "bar", ".service", &t) == 0); + assert_se(streq(t, "foo@bar.service")); + free(t); + + assert_se(unit_name_build("fo0-stUff_b", "bar", ".mount", &t) == 0); + assert_se(streq(t, "fo0-stUff_b@bar.mount")); + free(t); + + assert_se(unit_name_build("foo", NULL, ".service", &t) == 0); + assert_se(streq(t, "foo.service")); + free(t); +} + +static void test_slice_name_is_valid(void) { + log_info("/* %s */", __func__); + + assert_se( slice_name_is_valid(SPECIAL_ROOT_SLICE)); + assert_se( slice_name_is_valid("foo.slice")); + assert_se( slice_name_is_valid("foo-bar.slice")); + assert_se( slice_name_is_valid("foo-bar-baz.slice")); + assert_se(!slice_name_is_valid("-foo-bar-baz.slice")); + assert_se(!slice_name_is_valid("foo-bar-baz-.slice")); + assert_se(!slice_name_is_valid("-foo-bar-baz-.slice")); + assert_se(!slice_name_is_valid("foo-bar--baz.slice")); + assert_se(!slice_name_is_valid("foo--bar--baz.slice")); + assert_se(!slice_name_is_valid(".slice")); + assert_se(!slice_name_is_valid("")); + assert_se(!slice_name_is_valid("foo.service")); + + assert_se(!slice_name_is_valid("foo@.slice")); + assert_se(!slice_name_is_valid("foo@bar.slice")); + assert_se(!slice_name_is_valid("foo-bar@baz.slice")); + assert_se(!slice_name_is_valid("foo@bar@baz.slice")); + assert_se(!slice_name_is_valid("foo@bar-baz.slice")); + assert_se(!slice_name_is_valid("-foo-bar-baz@.slice")); + assert_se(!slice_name_is_valid("foo-bar-baz@-.slice")); + assert_se(!slice_name_is_valid("foo-bar-baz@a--b.slice")); + assert_se(!slice_name_is_valid("-foo-bar-baz@-.slice")); + assert_se(!slice_name_is_valid("foo-bar--baz@.slice")); + assert_se(!slice_name_is_valid("foo--bar--baz@.slice")); + assert_se(!slice_name_is_valid("@.slice")); + assert_se(!slice_name_is_valid("foo@bar.service")); +} + +static void test_build_subslice(void) { + char *a; + char *b; + + log_info("/* %s */", __func__); + + assert_se(slice_build_subslice(SPECIAL_ROOT_SLICE, "foo", &a) >= 0); + assert_se(slice_build_subslice(a, "bar", &b) >= 0); + free(a); + assert_se(slice_build_subslice(b, "barfoo", &a) >= 0); + free(b); + assert_se(slice_build_subslice(a, "foobar", &b) >= 0); + free(a); + assert_se(streq(b, "foo-bar-barfoo-foobar.slice")); + free(b); + + assert_se(slice_build_subslice("foo.service", "bar", &a) < 0); + assert_se(slice_build_subslice("foo", "bar", &a) < 0); +} + +static void test_build_parent_slice_one(const char *name, const char *expect, int ret) { + _cleanup_free_ char *s = NULL; + + assert_se(slice_build_parent_slice(name, &s) == ret); + assert_se(streq_ptr(s, expect)); +} + +static void test_build_parent_slice(void) { + log_info("/* %s */", __func__); + + test_build_parent_slice_one(SPECIAL_ROOT_SLICE, NULL, 0); + test_build_parent_slice_one("foo.slice", SPECIAL_ROOT_SLICE, 1); + test_build_parent_slice_one("foo-bar.slice", "foo.slice", 1); + test_build_parent_slice_one("foo-bar-baz.slice", "foo-bar.slice", 1); + test_build_parent_slice_one("foo-bar--baz.slice", NULL, -EINVAL); + test_build_parent_slice_one("-foo-bar.slice", NULL, -EINVAL); + test_build_parent_slice_one("foo-bar-.slice", NULL, -EINVAL); + test_build_parent_slice_one("foo-bar.service", NULL, -EINVAL); + test_build_parent_slice_one(".slice", NULL, -EINVAL); + test_build_parent_slice_one("foo@bar.slice", NULL, -EINVAL); + test_build_parent_slice_one("foo-bar@baz.slice", NULL, -EINVAL); + test_build_parent_slice_one("foo-bar--@baz.slice", NULL, -EINVAL); + test_build_parent_slice_one("-foo-bar@bar.slice", NULL, -EINVAL); + test_build_parent_slice_one("foo-bar@-.slice", NULL, -EINVAL); + test_build_parent_slice_one("foo@bar.service", NULL, -EINVAL); + test_build_parent_slice_one("@.slice", NULL, -EINVAL); +} + +static void test_unit_name_to_instance(void) { + char *instance; + int r; + + log_info("/* %s */", __func__); + + r = unit_name_to_instance("foo@bar.service", &instance); + assert_se(r == UNIT_NAME_INSTANCE); + assert_se(streq(instance, "bar")); + free(instance); + + r = unit_name_to_instance("foo@.service", &instance); + assert_se(r == UNIT_NAME_TEMPLATE); + assert_se(streq(instance, "")); + free(instance); + + r = unit_name_to_instance("fo0-stUff_b@b.service", &instance); + assert_se(r == UNIT_NAME_INSTANCE); + assert_se(streq(instance, "b")); + free(instance); + + r = unit_name_to_instance("foo.service", &instance); + assert_se(r == UNIT_NAME_PLAIN); + assert_se(!instance); + + r = unit_name_to_instance("fooj@unk", &instance); + assert_se(r < 0); + assert_se(!instance); + + r = unit_name_to_instance("foo@", &instance); + assert_se(r < 0); + assert_se(!instance); +} + +static void test_unit_name_escape(void) { + _cleanup_free_ char *r; + + log_info("/* %s */", __func__); + + r = unit_name_escape("ab+-c.a/bc@foo.service"); + assert_se(r); + assert_se(streq(r, "ab\\x2b\\x2dc.a-bc\\x40foo.service")); +} + +static void test_u_n_t_one(const char *name, const char *expected, int ret) { + _cleanup_free_ char *f = NULL; + + assert_se(unit_name_template(name, &f) == ret); + printf("got: %s, expected: %s\n", strna(f), strna(expected)); + assert_se(streq_ptr(f, expected)); +} + +static void test_unit_name_template(void) { + log_info("/* %s */", __func__); + + test_u_n_t_one("foo@bar.service", "foo@.service", 0); + test_u_n_t_one("foo.mount", NULL, -EINVAL); +} + +static void test_unit_name_path_unescape_one(const char *name, const char *path, int ret) { + _cleanup_free_ char *p = NULL; + + assert_se(unit_name_path_unescape(name, &p) == ret); + assert_se(streq_ptr(path, p)); +} + +static void test_unit_name_path_unescape(void) { + log_info("/* %s */", __func__); + + test_unit_name_path_unescape_one("foo", "/foo", 0); + test_unit_name_path_unescape_one("foo-bar", "/foo/bar", 0); + test_unit_name_path_unescape_one("foo-.bar", "/foo/.bar", 0); + test_unit_name_path_unescape_one("foo-bar-baz", "/foo/bar/baz", 0); + test_unit_name_path_unescape_one("-", "/", 0); + test_unit_name_path_unescape_one("--", NULL, -EINVAL); + test_unit_name_path_unescape_one("-foo-bar", NULL, -EINVAL); + test_unit_name_path_unescape_one("foo--bar", NULL, -EINVAL); + test_unit_name_path_unescape_one("foo-bar-", NULL, -EINVAL); + test_unit_name_path_unescape_one(".-bar", NULL, -EINVAL); + test_unit_name_path_unescape_one("foo-..", NULL, -EINVAL); + test_unit_name_path_unescape_one("", NULL, -EINVAL); +} + +static void test_unit_name_to_prefix_one(const char *input, int ret, const char *output) { + _cleanup_free_ char *k = NULL; + + assert_se(unit_name_to_prefix(input, &k) == ret); + assert_se(streq_ptr(k, output)); +} + +static void test_unit_name_to_prefix(void) { + log_info("/* %s */", __func__); + + test_unit_name_to_prefix_one("foobar.service", 0, "foobar"); + test_unit_name_to_prefix_one("", -EINVAL, NULL); + test_unit_name_to_prefix_one("foobar", -EINVAL, NULL); + test_unit_name_to_prefix_one(".service", -EINVAL, NULL); + test_unit_name_to_prefix_one("quux.quux", -EINVAL, NULL); + test_unit_name_to_prefix_one("quux.mount", 0, "quux"); + test_unit_name_to_prefix_one("quux-quux.mount", 0, "quux-quux"); + test_unit_name_to_prefix_one("quux@bar.mount", 0, "quux"); + test_unit_name_to_prefix_one("quux-@.mount", 0, "quux-"); + test_unit_name_to_prefix_one("@.mount", -EINVAL, NULL); +} + +static void test_unit_name_from_dbus_path_one(const char *input, int ret, const char *output) { + _cleanup_free_ char *k = NULL; + + assert_se(unit_name_from_dbus_path(input, &k) == ret); + assert_se(streq_ptr(k, output)); +} + +static void test_unit_name_from_dbus_path(void) { + log_info("/* %s */", __func__); + + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2esocket", 0, "dbus.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2emount", 0, "-.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/_2d_2eslice", 0, "-.slice"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/accounts_2ddaemon_2eservice", 0, "accounts-daemon.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/auditd_2eservice", 0, "auditd.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/basic_2etarget", 0, "basic.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/bluetooth_2etarget", 0, "bluetooth.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/boot_2eautomount", 0, "boot.automount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/boot_2emount", 0, "boot.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/btrfs_2emount", 0, "btrfs.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/cryptsetup_2dpre_2etarget", 0, "cryptsetup-pre.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/cryptsetup_2etarget", 0, "cryptsetup.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2eservice", 0, "dbus.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dbus_2esocket", 0, "dbus.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dcdrom_2edevice", 0, "dev-cdrom.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M120G2GC_5fCVPO044405HH120QGN_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M120G2GC_CVPO044405HH120QGN.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M120G2GC_5fCVPO044405HH120QGN_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M120G2GC_CVPO044405HH120QGN\\x2dpart1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN\\x2dpart1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_5cx2dpart2_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN\\x2dpart2.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dINTEL_5fSSDSA2M160G2GC_5fCVPO951003RY160AGN_5cx2dpart3_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dINTEL_SSDSA2M160G2GC_CVPO951003RY160AGN\\x2dpart3.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2data_5cx2dTSSTcorp_5fCDDVDW_5fTS_5cx2dL633C_5fR6176GLZB14646_2edevice", 0, "dev-disk-by\\x2did-ata\\x2dTSSTcorp_CDDVDW_TS\\x2dL633C_R6176GLZB14646.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae\\x2dpart1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_5cx2dpart2_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae\\x2dpart2.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x50015179591245ae_5cx2dpart3_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x50015179591245ae\\x2dpart3.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x500151795946eab5_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x500151795946eab5.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2did_2dwwn_5cx2d0x500151795946eab5_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2did-wwn\\x2d0x500151795946eab5\\x2dpart1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dlabel_2d_5cxe3_5cx82_5cxb7_5cxe3_5cx82_5cxb9_5cxe3_5cx83_5cx86_5cxe3_5cx83_5cxa0_5cxe3_5cx81_5cxa7_5cxe4_5cxba_5cx88_5cxe7_5cxb4_5cx84_5cxe6_5cxb8_5cx88_5cxe3_5cx81_5cxbf_2edevice", 0, "dev-disk-by\\x2dlabel-\\xe3\\x82\\xb7\\xe3\\x82\\xb9\\xe3\\x83\\x86\\xe3\\x83\\xa0\\xe3\\x81\\xa7\\xe4\\xba\\x88\\xe7\\xb4\\x84\\xe6\\xb8\\x88\\xe3\\x81\\xbf.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d59834e50_5cx2d01_2edevice", 0, "dev-disk-by\\x2dpartuuid-59834e50\\x2d01.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d63e2a7b3_5cx2d01_2edevice", 0, "dev-disk-by\\x2dpartuuid-63e2a7b3\\x2d01.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d63e2a7b3_5cx2d02_2edevice", 0, "dev-disk-by\\x2dpartuuid-63e2a7b3\\x2d02.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpartuuid_2d63e2a7b3_5cx2d03_2edevice", 0, "dev-disk-by\\x2dpartuuid-63e2a7b3\\x2d03.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1\\x2dpart1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_5cx2dpart2_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1\\x2dpart2.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d1_5cx2dpart3_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d1\\x2dpart3.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d2_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d2.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d6_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d6.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2dpath_2dpci_5cx2d0000_3a00_3a1f_2e2_5cx2data_5cx2d6_5cx2dpart1_2edevice", 0, "dev-disk-by\\x2dpath-pci\\x2d0000:00:1f.2\\x2data\\x2d6\\x2dpart1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2d1A34E3F034E3CD37_2edevice", 0, "dev-disk-by\\x2duuid-1A34E3F034E3CD37.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2dB670EBFE70EBC2EB_2edevice", 0, "dev-disk-by\\x2duuid-B670EBFE70EBC2EB.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2dFCD4F509D4F4C6C4_2edevice", 0, "dev-disk-by\\x2duuid-FCD4F509D4F4C6C4.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2ddisk_2dby_5cx2duuid_2db49ead57_5cx2d907c_5cx2d446c_5cx2db405_5cx2d5ca6cd865f5e_2edevice", 0, "dev-disk-by\\x2duuid-b49ead57\\x2d907c\\x2d446c\\x2db405\\x2d5ca6cd865f5e.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dhugepages_2emount", 0, "dev-hugepages.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dmqueue_2emount", 0, "dev-mqueue.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2drfkill_2edevice", 0, "dev-rfkill.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda1_2edevice", 0, "dev-sda1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda2_2edevice", 0, "dev-sda2.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda3_2edevice", 0, "dev-sda3.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsda_2edevice", 0, "dev-sda.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsdb1_2edevice", 0, "dev-sdb1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsdb_2edevice", 0, "dev-sdb.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dsr0_2edevice", 0, "dev-sr0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS0_2edevice", 0, "dev-ttyS0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS10_2edevice", 0, "dev-ttyS10.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS11_2edevice", 0, "dev-ttyS11.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS12_2edevice", 0, "dev-ttyS12.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS13_2edevice", 0, "dev-ttyS13.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS14_2edevice", 0, "dev-ttyS14.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS15_2edevice", 0, "dev-ttyS15.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS16_2edevice", 0, "dev-ttyS16.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS17_2edevice", 0, "dev-ttyS17.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS18_2edevice", 0, "dev-ttyS18.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS19_2edevice", 0, "dev-ttyS19.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS1_2edevice", 0, "dev-ttyS1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS20_2edevice", 0, "dev-ttyS20.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS21_2edevice", 0, "dev-ttyS21.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS22_2edevice", 0, "dev-ttyS22.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS23_2edevice", 0, "dev-ttyS23.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS24_2edevice", 0, "dev-ttyS24.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS25_2edevice", 0, "dev-ttyS25.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS26_2edevice", 0, "dev-ttyS26.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS27_2edevice", 0, "dev-ttyS27.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS28_2edevice", 0, "dev-ttyS28.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS29_2edevice", 0, "dev-ttyS29.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS2_2edevice", 0, "dev-ttyS2.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS30_2edevice", 0, "dev-ttyS30.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS31_2edevice", 0, "dev-ttyS31.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS3_2edevice", 0, "dev-ttyS3.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS4_2edevice", 0, "dev-ttyS4.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS5_2edevice", 0, "dev-ttyS5.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS6_2edevice", 0, "dev-ttyS6.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS7_2edevice", 0, "dev-ttyS7.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS8_2edevice", 0, "dev-ttyS8.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dev_2dttyS9_2edevice", 0, "dev-ttyS9.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dcmdline_2eservice", 0, "dracut-cmdline.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dinitqueue_2eservice", 0, "dracut-initqueue.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dmount_2eservice", 0, "dracut-mount.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dmount_2eservice", 0, "dracut-pre-mount.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dpivot_2eservice", 0, "dracut-pre-pivot.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dtrigger_2eservice", 0, "dracut-pre-trigger.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dpre_2dudev_2eservice", 0, "dracut-pre-udev.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/dracut_2dshutdown_2eservice", 0, "dracut-shutdown.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ebtables_2eservice", 0, "ebtables.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/emergency_2eservice", 0, "emergency.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/emergency_2etarget", 0, "emergency.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/fedora_2dimport_2dstate_2eservice", 0, "fedora-import-state.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/fedora_2dreadonly_2eservice", 0, "fedora-readonly.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/firewalld_2eservice", 0, "firewalld.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/getty_2dpre_2etarget", 0, "getty-pre.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/getty_2etarget", 0, "getty.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/getty_40tty1_2eservice", 0, "getty@tty1.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/graphical_2etarget", 0, "graphical.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/home_2emount", 0, "home.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/init_2escope", 0, "init.scope"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dcleanup_2eservice", 0, "initrd-cleanup.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dfs_2etarget", 0, "initrd-fs.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dparse_2detc_2eservice", 0, "initrd-parse-etc.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2droot_2ddevice_2etarget", 0, "initrd-root-device.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2droot_2dfs_2etarget", 0, "initrd-root-fs.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dswitch_2droot_2eservice", 0, "initrd-switch-root.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dswitch_2droot_2etarget", 0, "initrd-switch-root.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2dudevadm_2dcleanup_2ddb_2eservice", 0, "initrd-udevadm-cleanup-db.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/initrd_2etarget", 0, "initrd.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ip6tables_2eservice", 0, "ip6tables.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ipset_2eservice", 0, "ipset.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/iptables_2eservice", 0, "iptables.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/irqbalance_2eservice", 0, "irqbalance.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/kmod_2dstatic_2dnodes_2eservice", 0, "kmod-static-nodes.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/ldconfig_2eservice", 0, "ldconfig.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/lightdm_2eservice", 0, "lightdm.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/livesys_2dlate_2eservice", 0, "livesys-late.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/lm_5fsensors_2eservice", 0, "lm_sensors.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/local_2dfs_2dpre_2etarget", 0, "local-fs-pre.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/local_2dfs_2etarget", 0, "local-fs.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/machines_2etarget", 0, "machines.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/mcelog_2eservice", 0, "mcelog.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/multi_2duser_2etarget", 0, "multi-user.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/network_2dpre_2etarget", 0, "network-pre.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/network_2etarget", 0, "network.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/nss_2dlookup_2etarget", 0, "nss-lookup.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/nss_2duser_2dlookup_2etarget", 0, "nss-user-lookup.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/paths_2etarget", 0, "paths.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/plymouth_2dquit_2dwait_2eservice", 0, "plymouth-quit-wait.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/plymouth_2dquit_2eservice", 0, "plymouth-quit.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/plymouth_2dstart_2eservice", 0, "plymouth-start.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/polkit_2eservice", 0, "polkit.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount", 0, "proc-sys-fs-binfmt_misc.automount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2emount", 0, "proc-sys-fs-binfmt_misc.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/rc_2dlocal_2eservice", 0, "rc-local.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/remote_2dcryptsetup_2etarget", 0, "remote-cryptsetup.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/remote_2dfs_2dpre_2etarget", 0, "remote-fs-pre.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/remote_2dfs_2etarget", 0, "remote-fs.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/rescue_2eservice", 0, "rescue.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/rescue_2etarget", 0, "rescue.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/run_2duser_2d1000_2emount", 0, "run-user-1000.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/session_2d2_2escope", 0, "session-2.scope"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/shutdown_2etarget", 0, "shutdown.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/slices_2etarget", 0, "slices.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/smartd_2eservice", 0, "smartd.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sockets_2etarget", 0, "sockets.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sound_2etarget", 0, "sound.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_2etarget", 0, "sshd-keygen.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_40ecdsa_2eservice", 0, "sshd-keygen@ecdsa.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_40ed25519_2eservice", 0, "sshd-keygen@ed25519.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2dkeygen_40rsa_2eservice", 0, "sshd-keygen@rsa.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sshd_2eservice", 0, "sshd.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/swap_2etarget", 0, "swap.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a02_2e0_2dbacklight_2dacpi_5fvideo0_2edevice", 0, "sys-devices-pci0000:00-0000:00:02.0-backlight-acpi_video0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a02_2e0_2ddrm_2dcard0_2dcard0_5cx2dLVDS_5cx2d1_2dintel_5fbacklight_2edevice", 0, "sys-devices-pci0000:00-0000:00:02.0-drm-card0-card0\\x2dLVDS\\x2d1-intel_backlight.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1a_2e0_2dusb1_2d1_5cx2d1_2d1_5cx2d1_2e6_2d1_5cx2d1_2e6_3a1_2e0_2dbluetooth_2dhci0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1a.0-usb1-1\\x2d1-1\\x2d1.6-1\\x2d1.6:1.0-bluetooth-hci0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1b_2e0_2dsound_2dcard0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1b.0-sound-card0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1c_2e0_2d0000_3a02_3a00_2e0_2dnet_2dwlp2s0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1c.0-0000:02:00.0-net-wlp2s0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1c_2e2_2d0000_3a04_3a00_2e0_2dnet_2denp4s0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1c.2-0000:04:00.0-net-enp4s0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2dsda1_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2dsda2_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda2.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2dsda3_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda-sda3.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data1_2dhost0_2dtarget0_3a0_3a0_2d0_3a0_3a0_3a0_2dblock_2dsda_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata1-host0-target0:0:0-0:0:0:0-block-sda.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data2_2dhost1_2dtarget1_3a0_3a0_2d1_3a0_3a0_3a0_2dblock_2dsr0_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata2-host1-target1:0:0-1:0:0:0-block-sr0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data6_2dhost5_2dtarget5_3a0_3a0_2d5_3a0_3a0_3a0_2dblock_2dsdb_2dsdb1_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata6-host5-target5:0:0-5:0:0:0-block-sdb-sdb1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dpci0000_3a00_2d0000_3a00_3a1f_2e2_2data6_2dhost5_2dtarget5_3a0_3a0_2d5_3a0_3a0_3a0_2dblock_2dsdb_2edevice", 0, "sys-devices-pci0000:00-0000:00:1f.2-ata6-host5-target5:0:0-5:0:0:0-block-sdb.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS0_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS10_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS10.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS11_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS11.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS12_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS12.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS13_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS13.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS14_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS14.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS15_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS15.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS16_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS16.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS17_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS17.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS18_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS18.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS19_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS19.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS1_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS1.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS20_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS20.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS21_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS21.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS22_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS22.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS23_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS23.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS24_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS24.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS25_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS25.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS26_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS26.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS27_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS27.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS28_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS28.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS29_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS29.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS2_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS2.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS30_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS30.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS31_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS31.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS3_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS3.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS4_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS4.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS5_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS5.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS6_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS6.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS7_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS7.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS8_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS8.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dplatform_2dserial8250_2dtty_2dttyS9_2edevice", 0, "sys-devices-platform-serial8250-tty-ttyS9.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2ddevices_2dvirtual_2dmisc_2drfkill_2edevice", 0, "sys-devices-virtual-misc-rfkill.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dfs_2dfuse_2dconnections_2emount", 0, "sys-fs-fuse-connections.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dkernel_2dconfig_2emount", 0, "sys-kernel-config.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dkernel_2ddebug_2emount", 0, "sys-kernel-debug.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dmodule_2dconfigfs_2edevice", 0, "sys-module-configfs.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dbluetooth_2ddevices_2dhci0_2edevice", 0, "sys-subsystem-bluetooth-devices-hci0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2denp4s0_2edevice", 0, "sys-subsystem-net-devices-enp4s0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sys_2dsubsystem_2dnet_2ddevices_2dwlp2s0_2edevice", 0, "sys-subsystem-net-devices-wlp2s0.device"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sysinit_2etarget", 0, "sysinit.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/syslog_2eservice", 0, "syslog.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/syslog_2esocket", 0, "syslog.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/syslog_2etarget", 0, "syslog.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/sysroot_2emount", 0, "sysroot.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dgetty_2eslice", 0, "system-getty.slice"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dsshd_5cx2dkeygen_2eslice", 0, "system-sshd\\x2dkeygen.slice"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dsystemd_5cx2dbacklight_2eslice", 0, "system-systemd\\x2dbacklight.slice"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2dsystemd_5cx2dcoredump_2eslice", 0, "system-systemd\\x2dcoredump.slice"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2duser_5cx2druntime_5cx2ddir_2eslice", 0, "system-user\\x2druntime\\x2ddir.slice"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/system_2eslice", 0, "system.slice"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dconsole_2epath", 0, "systemd-ask-password-console.path"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dconsole_2eservice", 0, "systemd-ask-password-console.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dwall_2epath", 0, "systemd-ask-password-wall.path"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dask_2dpassword_2dwall_2eservice", 0, "systemd-ask-password-wall.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dbacklight_40backlight_3aacpi_5fvideo0_2eservice", 0, "systemd-backlight@backlight:acpi_video0.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dbacklight_40backlight_3aintel_5fbacklight_2eservice", 0, "systemd-backlight@backlight:intel_backlight.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dbinfmt_2eservice", 0, "systemd-binfmt.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dcoredump_2esocket", 0, "systemd-coredump.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dcoredump_400_2eservice", 0, "systemd-coredump@0.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dfirstboot_2eservice", 0, "systemd-firstboot.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dfsck_2droot_2eservice", 0, SPECIAL_FSCK_ROOT_SERVICE); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dhwdb_2dupdate_2eservice", 0, "systemd-hwdb-update.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dinitctl_2eservice", 0, "systemd-initctl.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dinitctl_2esocket", 0, "systemd-initctl.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournal_2dcatalog_2dupdate_2eservice", 0, "systemd-journal-catalog-update.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournal_2dflush_2eservice", 0, "systemd-journal-flush.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2daudit_2esocket", 0, "systemd-journald-audit.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2ddev_2dlog_2esocket", 0, "systemd-journald-dev-log.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2eservice", 0, "systemd-journald.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2djournald_2esocket", 0, "systemd-journald.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dlogind_2eservice", 0, "systemd-logind.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dmachine_2did_2dcommit_2eservice", 0, "systemd-machine-id-commit.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dmodules_2dload_2eservice", 0, "systemd-modules-load.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dnetworkd_2eservice", 0, "systemd-networkd.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dnetworkd_2esocket", 0, "systemd-networkd.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2drandom_2dseed_2eservice", 0, "systemd-random-seed.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dremount_2dfs_2eservice", 0, "systemd-remount-fs.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dresolved_2eservice", 0, "systemd-resolved.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2drfkill_2eservice", 0, "systemd-rfkill.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2drfkill_2esocket", 0, "systemd-rfkill.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dsysctl_2eservice", 0, "systemd-sysctl.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dsysusers_2eservice", 0, "systemd-sysusers.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtimesyncd_2eservice", 0, "systemd-timesyncd.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2eservice", 0, "systemd-tmpfiles-clean.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer", 0, "systemd-tmpfiles-clean.timer"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dsetup_2ddev_2eservice", 0, "systemd-tmpfiles-setup-dev.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dsetup_2eservice", 0, "systemd-tmpfiles-setup.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudev_2dtrigger_2eservice", 0, "systemd-udev-trigger.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2dcontrol_2esocket", 0, "systemd-udevd-control.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2dkernel_2esocket", 0, "systemd-udevd-kernel.socket"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2eservice", 0, "systemd-udevd.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dupdate_2ddone_2eservice", 0, "systemd-update-done.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dupdate_2dutmp_2drunlevel_2eservice", 0, "systemd-update-utmp-runlevel.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dupdate_2dutmp_2eservice", 0, "systemd-update-utmp.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2duser_2dsessions_2eservice", 0, "systemd-user-sessions.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dvconsole_2dsetup_2eservice", 0, "systemd-vconsole-setup.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/time_2dsync_2etarget", 0, "time-sync.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/timers_2etarget", 0, "timers.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/tmp_2emount", 0, "tmp.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/umount_2etarget", 0, "umount.target"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/unbound_2danchor_2eservice", 0, "unbound-anchor.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/unbound_2danchor_2etimer", 0, "unbound-anchor.timer"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/upower_2eservice", 0, "upower.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_2d1000_2eslice", 0, "user-1000.slice"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_2druntime_2ddir_401000_2eservice", 0, "user-runtime-dir@1000.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_2eslice", 0, "user.slice"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/user_401000_2eservice", 0, "user@1000.service"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/usr_2dlocal_2dtexlive_2emount", 0, "usr-local-texlive.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/var_2dlib_2dmachines_2emount", 0, "var-lib-machines.mount"); + test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/wpa_5fsupplicant_2eservice", 0, "wpa_supplicant.service"); +} + +int main(int argc, char* argv[]) { + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + int r, rc = 0; + + test_setup_logging(LOG_INFO); + + r = enter_cgroup_subroot(NULL); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + assert_se(runtime_dir = setup_fake_runtime_dir()); + + test_unit_name_is_valid(); + test_unit_name_replace_instance(); + test_unit_name_from_path(); + test_unit_name_from_path_instance(); + test_unit_name_mangle(); + test_unit_name_to_path(); + TEST_REQ_RUNNING_SYSTEMD(rc = test_unit_printf()); + test_unit_instance_is_valid(); + test_unit_prefix_is_valid(); + test_unit_name_change_suffix(); + test_unit_name_build(); + test_slice_name_is_valid(); + test_build_subslice(); + test_build_parent_slice(); + test_unit_name_to_instance(); + test_unit_name_escape(); + test_unit_name_template(); + test_unit_name_path_unescape(); + test_unit_name_to_prefix(); + test_unit_name_from_dbus_path(); + + return rc; +} diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c new file mode 100644 index 00000000..47baacb5 --- /dev/null +++ b/src/test/test-user-util.c @@ -0,0 +1,335 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "format-util.h" +#include "log.h" +#include "macro.h" +#include "path-util.h" +#include "string-util.h" +#include "user-util.h" + +static void test_uid_to_name_one(uid_t uid, const char *name) { + _cleanup_free_ char *t = NULL; + + log_info("/* %s("UID_FMT", \"%s\") */", __func__, uid, name); + + assert_se(t = uid_to_name(uid)); + if (!synthesize_nobody() && streq(name, NOBODY_USER_NAME)) { + log_info("(skipping detailed tests because nobody is not synthesized)"); + return; + } + assert_se(streq_ptr(t, name)); +} + +static void test_gid_to_name_one(gid_t gid, const char *name) { + _cleanup_free_ char *t = NULL; + + log_info("/* %s("GID_FMT", \"%s\") */", __func__, gid, name); + + assert_se(t = gid_to_name(gid)); + if (!synthesize_nobody() && streq(name, NOBODY_GROUP_NAME)) { + log_info("(skipping detailed tests because nobody is not synthesized)"); + return; + } + assert_se(streq_ptr(t, name)); +} + +static void test_parse_uid(void) { + int r; + uid_t uid; + + log_info("/* %s */", __func__); + + r = parse_uid("100", &uid); + assert_se(r == 0); + assert_se(uid == 100); + + r = parse_uid("65535", &uid); + assert_se(r == -ENXIO); + + r = parse_uid("asdsdas", &uid); + assert_se(r == -EINVAL); +} + +static void test_uid_ptr(void) { + log_info("/* %s */", __func__); + + assert_se(UID_TO_PTR(0) != NULL); + assert_se(UID_TO_PTR(1000) != NULL); + + assert_se(PTR_TO_UID(UID_TO_PTR(0)) == 0); + assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000); +} + +static void test_valid_user_group_name_compat(void) { + log_info("/* %s */", __func__); + + assert_se(!valid_user_group_name_compat(NULL)); + assert_se(!valid_user_group_name_compat("")); + assert_se(!valid_user_group_name_compat("1")); + assert_se(!valid_user_group_name_compat("65535")); + assert_se(!valid_user_group_name_compat("-1")); + assert_se(!valid_user_group_name_compat("-kkk")); + assert_se(!valid_user_group_name_compat("rööt")); + assert_se(!valid_user_group_name_compat(".")); + assert_se(!valid_user_group_name_compat(".eff")); + assert_se(!valid_user_group_name_compat("foo\nbar")); + assert_se(!valid_user_group_name_compat("0123456789012345678901234567890123456789")); + assert_se(!valid_user_group_name_or_id_compat("aaa:bbb")); + assert_se(!valid_user_group_name_compat(".")); + assert_se(!valid_user_group_name_compat(".1")); + assert_se(!valid_user_group_name_compat(".65535")); + assert_se(!valid_user_group_name_compat(".-1")); + assert_se(!valid_user_group_name_compat(".-kkk")); + assert_se(!valid_user_group_name_compat(".rööt")); + assert_se(!valid_user_group_name_or_id_compat(".aaa:bbb")); + + assert_se(valid_user_group_name_compat("root")); + assert_se(valid_user_group_name_compat("lennart")); + assert_se(valid_user_group_name_compat("LENNART")); + assert_se(valid_user_group_name_compat("_kkk")); + assert_se(valid_user_group_name_compat("kkk-")); + assert_se(valid_user_group_name_compat("kk-k")); + assert_se(valid_user_group_name_compat("eff.eff")); + assert_se(valid_user_group_name_compat("eff.")); + + assert_se(valid_user_group_name_compat("some5")); + assert_se(!valid_user_group_name_compat("5some")); + assert_se(valid_user_group_name_compat("INNER5NUMBER")); +} + +static void test_valid_user_group_name(void) { + log_info("/* %s */", __func__); + + assert_se(!valid_user_group_name(NULL)); + assert_se(!valid_user_group_name("")); + assert_se(!valid_user_group_name("1")); + assert_se(!valid_user_group_name("65535")); + assert_se(!valid_user_group_name("-1")); + assert_se(!valid_user_group_name("-kkk")); + assert_se(!valid_user_group_name("rööt")); + assert_se(!valid_user_group_name(".")); + assert_se(!valid_user_group_name(".eff")); + assert_se(!valid_user_group_name("foo\nbar")); + assert_se(!valid_user_group_name("0123456789012345678901234567890123456789")); + assert_se(!valid_user_group_name_or_id("aaa:bbb")); + assert_se(!valid_user_group_name(".")); + assert_se(!valid_user_group_name(".1")); + assert_se(!valid_user_group_name(".65535")); + assert_se(!valid_user_group_name(".-1")); + assert_se(!valid_user_group_name(".-kkk")); + assert_se(!valid_user_group_name(".rööt")); + assert_se(!valid_user_group_name_or_id(".aaa:bbb")); + + assert_se(valid_user_group_name("root")); + assert_se(valid_user_group_name("lennart")); + assert_se(valid_user_group_name("LENNART")); + assert_se(valid_user_group_name("_kkk")); + assert_se(valid_user_group_name("kkk-")); + assert_se(valid_user_group_name("kk-k")); + assert_se(!valid_user_group_name("eff.eff")); + assert_se(!valid_user_group_name("eff.")); + + assert_se(valid_user_group_name("some5")); + assert_se(!valid_user_group_name("5some")); + assert_se(valid_user_group_name("INNER5NUMBER")); +} + +static void test_valid_user_group_name_or_id_compat(void) { + log_info("/* %s */", __func__); + + assert_se(!valid_user_group_name_or_id_compat(NULL)); + assert_se(!valid_user_group_name_or_id_compat("")); + assert_se(valid_user_group_name_or_id_compat("0")); + assert_se(valid_user_group_name_or_id_compat("1")); + assert_se(valid_user_group_name_or_id_compat("65534")); + assert_se(!valid_user_group_name_or_id_compat("65535")); + assert_se(valid_user_group_name_or_id_compat("65536")); + assert_se(!valid_user_group_name_or_id_compat("-1")); + assert_se(!valid_user_group_name_or_id_compat("-kkk")); + assert_se(!valid_user_group_name_or_id_compat("rööt")); + assert_se(!valid_user_group_name_or_id_compat(".")); + assert_se(!valid_user_group_name_or_id_compat(".eff")); + assert_se(valid_user_group_name_or_id_compat("eff.eff")); + assert_se(valid_user_group_name_or_id_compat("eff.")); + assert_se(!valid_user_group_name_or_id_compat("foo\nbar")); + assert_se(!valid_user_group_name_or_id_compat("0123456789012345678901234567890123456789")); + assert_se(!valid_user_group_name_or_id_compat("aaa:bbb")); + + assert_se(valid_user_group_name_or_id_compat("root")); + assert_se(valid_user_group_name_or_id_compat("lennart")); + assert_se(valid_user_group_name_or_id_compat("LENNART")); + assert_se(valid_user_group_name_or_id_compat("_kkk")); + assert_se(valid_user_group_name_or_id_compat("kkk-")); + assert_se(valid_user_group_name_or_id_compat("kk-k")); + + assert_se(valid_user_group_name_or_id_compat("some5")); + assert_se(!valid_user_group_name_or_id_compat("5some")); + assert_se(valid_user_group_name_or_id_compat("INNER5NUMBER")); +} + +static void test_valid_user_group_name_or_id(void) { + log_info("/* %s */", __func__); + + assert_se(!valid_user_group_name_or_id(NULL)); + assert_se(!valid_user_group_name_or_id("")); + assert_se(valid_user_group_name_or_id("0")); + assert_se(valid_user_group_name_or_id("1")); + assert_se(valid_user_group_name_or_id("65534")); + assert_se(!valid_user_group_name_or_id("65535")); + assert_se(valid_user_group_name_or_id("65536")); + assert_se(!valid_user_group_name_or_id("-1")); + assert_se(!valid_user_group_name_or_id("-kkk")); + assert_se(!valid_user_group_name_or_id("rööt")); + assert_se(!valid_user_group_name_or_id(".")); + assert_se(!valid_user_group_name_or_id(".eff")); + assert_se(!valid_user_group_name_or_id("eff.eff")); + assert_se(!valid_user_group_name_or_id("eff.")); + assert_se(!valid_user_group_name_or_id("foo\nbar")); + assert_se(!valid_user_group_name_or_id("0123456789012345678901234567890123456789")); + assert_se(!valid_user_group_name_or_id("aaa:bbb")); + + assert_se(valid_user_group_name_or_id("root")); + assert_se(valid_user_group_name_or_id("lennart")); + assert_se(valid_user_group_name_or_id("LENNART")); + assert_se(valid_user_group_name_or_id("_kkk")); + assert_se(valid_user_group_name_or_id("kkk-")); + assert_se(valid_user_group_name_or_id("kk-k")); + + assert_se(valid_user_group_name_or_id("some5")); + assert_se(!valid_user_group_name_or_id("5some")); + assert_se(valid_user_group_name_or_id("INNER5NUMBER")); +} + +static void test_valid_gecos(void) { + log_info("/* %s */", __func__); + + assert_se(!valid_gecos(NULL)); + assert_se(valid_gecos("")); + assert_se(valid_gecos("test")); + assert_se(valid_gecos("Ümläüt")); + assert_se(!valid_gecos("In\nvalid")); + assert_se(!valid_gecos("In:valid")); +} + +static void test_valid_home(void) { + log_info("/* %s */", __func__); + + assert_se(!valid_home(NULL)); + assert_se(!valid_home("")); + assert_se(!valid_home(".")); + assert_se(!valid_home("/home/..")); + assert_se(!valid_home("/home/../")); + assert_se(!valid_home("/home\n/foo")); + assert_se(!valid_home("./piep")); + assert_se(!valid_home("piep")); + assert_se(!valid_home("/home/user:lennart")); + + assert_se(valid_home("/")); + assert_se(valid_home("/home")); + assert_se(valid_home("/home/foo")); +} + +static void test_get_user_creds_one(const char *id, const char *name, uid_t uid, gid_t gid, const char *home, const char *shell) { + const char *rhome = NULL; + const char *rshell = NULL; + uid_t ruid = UID_INVALID; + gid_t rgid = GID_INVALID; + int r; + + log_info("/* %s(\"%s\", \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\") */", + __func__, id, name, uid, gid, home, shell); + + r = get_user_creds(&id, &ruid, &rgid, &rhome, &rshell, 0); + log_info_errno(r, "got \"%s\", "UID_FMT", "GID_FMT", \"%s\", \"%s\": %m", + id, ruid, rgid, strnull(rhome), strnull(rshell)); + if (!synthesize_nobody() && streq(name, NOBODY_USER_NAME)) { + log_info("(skipping detailed tests because nobody is not synthesized)"); + return; + } + assert_se(r == 0); + assert_se(streq_ptr(id, name)); + assert_se(ruid == uid); + assert_se(rgid == gid); + assert_se(path_equal(rhome, home)); + assert_se(path_equal(rshell, shell)); +} + +static void test_get_group_creds_one(const char *id, const char *name, gid_t gid) { + gid_t rgid = GID_INVALID; + int r; + + log_info("/* %s(\"%s\", \"%s\", "GID_FMT") */", __func__, id, name, gid); + + r = get_group_creds(&id, &rgid, 0); + log_info_errno(r, "got \"%s\", "GID_FMT": %m", id, rgid); + if (!synthesize_nobody() && streq(name, NOBODY_GROUP_NAME)) { + log_info("(skipping detailed tests because nobody is not synthesized)"); + return; + } + assert_se(r == 0); + assert_se(streq_ptr(id, name)); + assert_se(rgid == gid); +} + +static void test_make_salt(void) { + log_info("/* %s */", __func__); + + _cleanup_free_ char *s, *t; + + assert_se(make_salt(&s) == 0); + log_info("got %s", s); + + assert_se(make_salt(&t) == 0); + log_info("got %s", t); + + assert(!streq(s, t)); +} + +static void test_in_gid(void) { + + assert(in_gid(getgid()) >= 0); + assert(in_gid(getegid()) >= 0); + + assert(in_gid(GID_INVALID) < 0); + assert(in_gid(TTY_GID) == 0); /* The TTY gid is for owning ttys, it would be really really weird if we were in it. */ +} + +int main(int argc, char *argv[]) { + test_uid_to_name_one(0, "root"); + test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME); + test_uid_to_name_one(0xFFFF, "65535"); + test_uid_to_name_one(0xFFFFFFFF, "4294967295"); + + test_gid_to_name_one(0, "root"); + test_gid_to_name_one(GID_NOBODY, NOBODY_GROUP_NAME); + test_gid_to_name_one(TTY_GID, "tty"); + test_gid_to_name_one(0xFFFF, "65535"); + test_gid_to_name_one(0xFFFFFFFF, "4294967295"); + + test_get_user_creds_one("root", "root", 0, 0, "/root", "/bin/sh"); + test_get_user_creds_one("0", "root", 0, 0, "/root", "/bin/sh"); + test_get_user_creds_one(NOBODY_USER_NAME, NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", NOLOGIN); + test_get_user_creds_one("65534", NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", NOLOGIN); + + test_get_group_creds_one("root", "root", 0); + test_get_group_creds_one("0", "root", 0); + test_get_group_creds_one(NOBODY_GROUP_NAME, NOBODY_GROUP_NAME, GID_NOBODY); + test_get_group_creds_one("65534", NOBODY_GROUP_NAME, GID_NOBODY); + + test_parse_uid(); + test_uid_ptr(); + + test_valid_user_group_name_compat(); + test_valid_user_group_name(); + test_valid_user_group_name_or_id_compat(); + test_valid_user_group_name_or_id(); + test_valid_gecos(); + test_valid_home(); + + test_make_salt(); + + test_in_gid(); + + return 0; +} diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c new file mode 100644 index 00000000..8937f562 --- /dev/null +++ b/src/test/test-utf8.c @@ -0,0 +1,233 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "string-util.h" +#include "strv.h" +#include "utf8.h" +#include "util.h" + +static void test_utf8_is_printable(void) { + log_info("/* %s */", __func__); + + assert_se(utf8_is_printable("ascii is valid\tunicode", 22)); + assert_se(utf8_is_printable("\342\204\242", 3)); + assert_se(!utf8_is_printable("\341\204", 2)); + assert_se(utf8_is_printable("ąę", 4)); + assert_se(!utf8_is_printable("\r", 1)); + assert_se(utf8_is_printable("\n", 1)); + assert_se(utf8_is_printable("\t", 1)); +} + +static void test_utf8_is_valid(void) { + log_info("/* %s */", __func__); + + assert_se(utf8_is_valid("ascii is valid unicode")); + assert_se(utf8_is_valid("\342\204\242")); + assert_se(!utf8_is_valid("\341\204")); +} + +static void test_ascii_is_valid(void) { + log_info("/* %s */", __func__); + + assert_se( ascii_is_valid("alsdjf\t\vbarr\nba z")); + assert_se(!ascii_is_valid("\342\204\242")); + assert_se(!ascii_is_valid("\341\204")); +} + +static void test_ascii_is_valid_n(void) { + log_info("/* %s */", __func__); + + assert_se( ascii_is_valid_n("alsdjf\t\vbarr\nba z", 17)); + assert_se( ascii_is_valid_n("alsdjf\t\vbarr\nba z", 16)); + assert_se(!ascii_is_valid_n("alsdjf\t\vbarr\nba z", 18)); + assert_se(!ascii_is_valid_n("\342\204\242", 3)); + assert_se(!ascii_is_valid_n("\342\204\242", 2)); + assert_se(!ascii_is_valid_n("\342\204\242", 1)); + assert_se( ascii_is_valid_n("\342\204\242", 0)); +} + +static void test_utf8_encoded_valid_unichar(void) { + log_info("/* %s */", __func__); + + assert_se(utf8_encoded_valid_unichar("\342\204\242", 1) == -EINVAL); /* truncated */ + assert_se(utf8_encoded_valid_unichar("\342\204\242", 2) == -EINVAL); /* truncated */ + assert_se(utf8_encoded_valid_unichar("\342\204\242", 3) == 3); + assert_se(utf8_encoded_valid_unichar("\342\204\242", 4) == 3); + assert_se(utf8_encoded_valid_unichar("\302\256", 1) == -EINVAL); /* truncated */ + assert_se(utf8_encoded_valid_unichar("\302\256", 2) == 2); + assert_se(utf8_encoded_valid_unichar("\302\256", 3) == 2); + assert_se(utf8_encoded_valid_unichar("\302\256", (size_t) -1) == 2); + assert_se(utf8_encoded_valid_unichar("a", 1) == 1); + assert_se(utf8_encoded_valid_unichar("a", 2) == 1); + assert_se(utf8_encoded_valid_unichar("\341\204", 1) == -EINVAL); /* truncated, potentially valid */ + assert_se(utf8_encoded_valid_unichar("\341\204", 2) == -EINVAL); /* truncated, potentially valid */ + assert_se(utf8_encoded_valid_unichar("\341\204", 3) == -EINVAL); + assert_se(utf8_encoded_valid_unichar("\341\204\341\204", 4) == -EINVAL); + assert_se(utf8_encoded_valid_unichar("\341\204\341\204", 5) == -EINVAL); +} + +static void test_utf8_escape_invalid(void) { + _cleanup_free_ char *p1, *p2, *p3; + + log_info("/* %s */", __func__); + + p1 = utf8_escape_invalid("goo goo goo"); + puts(p1); + assert_se(utf8_is_valid(p1)); + + p2 = utf8_escape_invalid("\341\204\341\204"); + puts(p2); + assert_se(utf8_is_valid(p2)); + + p3 = utf8_escape_invalid("\341\204"); + puts(p3); + assert_se(utf8_is_valid(p3)); +} + +static void test_utf8_escape_non_printable(void) { + _cleanup_free_ char *p1, *p2, *p3, *p4, *p5, *p6; + + log_info("/* %s */", __func__); + + p1 = utf8_escape_non_printable("goo goo goo"); + puts(p1); + assert_se(utf8_is_valid(p1)); + + p2 = utf8_escape_non_printable("\341\204\341\204"); + puts(p2); + assert_se(utf8_is_valid(p2)); + + p3 = utf8_escape_non_printable("\341\204"); + puts(p3); + assert_se(utf8_is_valid(p3)); + + p4 = utf8_escape_non_printable("ąę\n가너도루\n1234\n\341\204\341\204\n\001 \019\20\a"); + puts(p4); + assert_se(utf8_is_valid(p4)); + + p5 = utf8_escape_non_printable("\001 \019\20\a"); + puts(p5); + assert_se(utf8_is_valid(p5)); + + p6 = utf8_escape_non_printable("\xef\xbf\x30\x13"); + puts(p6); + assert_se(utf8_is_valid(p6)); +} + +static void test_utf8_escape_non_printable_full(void) { + log_info("/* %s */", __func__); + + for (size_t i = 0; i < 20; i++) { + _cleanup_free_ char *p; + + p = utf8_escape_non_printable_full("goo goo goo", i); + puts(p); + assert_se(utf8_is_valid(p)); + assert_se(utf8_console_width(p) <= i); + } + + for (size_t i = 0; i < 20; i++) { + _cleanup_free_ char *p; + + p = utf8_escape_non_printable_full("\001 \019\20\a", i); + puts(p); + assert_se(utf8_is_valid(p)); + assert_se(utf8_console_width(p) <= i); + } + + for (size_t i = 0; i < 20; i++) { + _cleanup_free_ char *p; + + p = utf8_escape_non_printable_full("\xef\xbf\x30\x13", i); + puts(p); + assert_se(utf8_is_valid(p)); + assert_se(utf8_console_width(p) <= i); + } +} + +static void test_utf16_to_utf8(void) { + const char16_t utf16[] = { htole16('a'), htole16(0xd800), htole16('b'), htole16(0xdc00), htole16('c'), htole16(0xd801), htole16(0xdc37) }; + static const char utf8[] = { 'a', 'b', 'c', 0xf0, 0x90, 0x90, 0xb7 }; + _cleanup_free_ char16_t *b = NULL; + _cleanup_free_ char *a = NULL; + + log_info("/* %s */", __func__); + + /* Convert UTF-16 to UTF-8, filtering embedded bad chars */ + a = utf16_to_utf8(utf16, sizeof(utf16)); + assert_se(a); + assert_se(memcmp(a, utf8, sizeof(utf8)) == 0); + + /* Convert UTF-8 to UTF-16, and back */ + b = utf8_to_utf16(utf8, sizeof(utf8)); + assert_se(b); + + free(a); + a = utf16_to_utf8(b, char16_strlen(b) * 2); + assert_se(a); + assert_se(strlen(a) == sizeof(utf8)); + assert_se(memcmp(a, utf8, sizeof(utf8)) == 0); +} + +static void test_utf8_n_codepoints(void) { + log_info("/* %s */", __func__); + + assert_se(utf8_n_codepoints("abc") == 3); + assert_se(utf8_n_codepoints("zażółcić gęślą jaźń") == 19); + assert_se(utf8_n_codepoints("串") == 1); + assert_se(utf8_n_codepoints("") == 0); + assert_se(utf8_n_codepoints("…👊🔪💐…") == 5); + assert_se(utf8_n_codepoints("\xF1") == (size_t) -1); +} + +static void test_utf8_console_width(void) { + log_info("/* %s */", __func__); + + assert_se(utf8_console_width("abc") == 3); + assert_se(utf8_console_width("zażółcić gęślą jaźń") == 19); + assert_se(utf8_console_width("串") == 2); + assert_se(utf8_console_width("") == 0); + assert_se(utf8_console_width("…👊🔪💐…") == 8); + assert_se(utf8_console_width("\xF1") == (size_t) -1); +} + +static void test_utf8_to_utf16(void) { + const char *p; + + log_info("/* %s */", __func__); + + FOREACH_STRING(p, + "abc", + "zażółcić gęślą jaźń", + "串", + "", + "…👊🔪💐…") { + + _cleanup_free_ char16_t *a = NULL; + _cleanup_free_ char *b = NULL; + + a = utf8_to_utf16(p, strlen(p)); + assert_se(a); + + b = utf16_to_utf8(a, char16_strlen(a) * 2); + assert_se(b); + assert_se(streq(p, b)); + } +} + +int main(int argc, char *argv[]) { + test_utf8_is_valid(); + test_utf8_is_printable(); + test_ascii_is_valid(); + test_ascii_is_valid_n(); + test_utf8_encoded_valid_unichar(); + test_utf8_escape_invalid(); + test_utf8_escape_non_printable(); + test_utf8_escape_non_printable_full(); + test_utf16_to_utf8(); + test_utf8_n_codepoints(); + test_utf8_console_width(); + test_utf8_to_utf16(); + + return 0; +} diff --git a/src/test/test-util.c b/src/test/test-util.c new file mode 100644 index 00000000..61725bdf --- /dev/null +++ b/src/test/test-util.c @@ -0,0 +1,421 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "fileio.h" +#include "fs-util.h" +#include "limits-util.h" +#include "memory-util.h" +#include "missing_syscall.h" +#include "parse-util.h" +#include "process-util.h" +#include "raw-clone.h" +#include "rm-rf.h" +#include "string-util.h" +#include "tests.h" +#include "util.h" + +static void test_align_power2(void) { + unsigned long i, p2; + + log_info("/* %s */", __func__); + + assert_se(ALIGN_POWER2(0) == 0); + assert_se(ALIGN_POWER2(1) == 1); + assert_se(ALIGN_POWER2(2) == 2); + assert_se(ALIGN_POWER2(3) == 4); + assert_se(ALIGN_POWER2(12) == 16); + + assert_se(ALIGN_POWER2(ULONG_MAX) == 0); + assert_se(ALIGN_POWER2(ULONG_MAX - 1) == 0); + assert_se(ALIGN_POWER2(ULONG_MAX - 1024) == 0); + assert_se(ALIGN_POWER2(ULONG_MAX / 2) == ULONG_MAX / 2 + 1); + assert_se(ALIGN_POWER2(ULONG_MAX + 1) == 0); + + for (i = 1; i < 131071; ++i) { + for (p2 = 1; p2 < i; p2 <<= 1) + /* empty */ ; + + assert_se(ALIGN_POWER2(i) == p2); + } + + for (i = ULONG_MAX - 1024; i < ULONG_MAX; ++i) { + for (p2 = 1; p2 && p2 < i; p2 <<= 1) + /* empty */ ; + + assert_se(ALIGN_POWER2(i) == p2); + } +} + +static void test_max(void) { + static const struct { + int a; + int b[CONST_MAX(10, 100)]; + } val1 = { + .a = CONST_MAX(10, 100), + }; + int d = 0; + unsigned long x = 12345; + unsigned long y = 54321; + const char str[] = "a_string_constant"; + const unsigned long long arr[] = {9999ULL, 10ULL, 0ULL, 3000ULL, 2000ULL, 1000ULL, 100ULL, 9999999ULL}; + void *p = (void *)str; + void *q = (void *)&str[16]; + + log_info("/* %s */", __func__); + + assert_cc(sizeof(val1.b) == sizeof(int) * 100); + + /* CONST_MAX returns (void) instead of a value if the passed arguments + * are not of the same type or not constant expressions. */ + assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 10)), int)); + assert_cc(__builtin_types_compatible_p(typeof(CONST_MAX(1, 1U)), void)); + + assert_se(val1.a == 100); + assert_se(MAX(++d, 0) == 1); + assert_se(d == 1); + + assert_cc(MAXSIZE(char[3], uint16_t) == 3); + assert_cc(MAXSIZE(char[3], uint32_t) == 4); + assert_cc(MAXSIZE(char, long) == sizeof(long)); + + assert_se(MAX(-5, 5) == 5); + assert_se(MAX(5, 5) == 5); + assert_se(MAX(MAX(1, MAX(2, MAX(3, 4))), 5) == 5); + assert_se(MAX(MAX(1, MAX(2, MAX(3, 2))), 1) == 3); + assert_se(MAX(MIN(1, MIN(2, MIN(3, 4))), 5) == 5); + assert_se(MAX(MAX(1, MIN(2, MIN(3, 2))), 1) == 2); + assert_se(LESS_BY(8, 4) == 4); + assert_se(LESS_BY(8, 8) == 0); + assert_se(LESS_BY(4, 8) == 0); + assert_se(LESS_BY(16, LESS_BY(8, 4)) == 12); + assert_se(LESS_BY(4, LESS_BY(8, 4)) == 0); + assert_se(CMP(3, 5) == -1); + assert_se(CMP(5, 3) == 1); + assert_se(CMP(5, 5) == 0); + assert_se(CMP(x, y) == -1); + assert_se(CMP(y, x) == 1); + assert_se(CMP(x, x) == 0); + assert_se(CMP(y, y) == 0); + assert_se(CMP(UINT64_MAX, (uint64_t) 0) == 1); + assert_se(CMP((uint64_t) 0, UINT64_MAX) == -1); + assert_se(CMP(UINT64_MAX, UINT64_MAX) == 0); + assert_se(CMP(INT64_MIN, INT64_MAX) == -1); + assert_se(CMP(INT64_MAX, INT64_MIN) == 1); + assert_se(CMP(INT64_MAX, INT64_MAX) == 0); + assert_se(CMP(INT64_MIN, INT64_MIN) == 0); + assert_se(CMP(INT64_MAX, (int64_t) 0) == 1); + assert_se(CMP((int64_t) 0, INT64_MIN) == 1); + assert_se(CMP(INT64_MIN, (int64_t) 0) == -1); + assert_se(CMP((int64_t) 0, INT64_MAX) == -1); + assert_se(CMP(&str[2], &str[7]) == -1); + assert_se(CMP(&str[2], &str[2]) == 0); + assert_se(CMP(&str[7], (const char *)str) == 1); + assert_se(CMP(str[2], str[7]) == 1); + assert_se(CMP(str[7], *str) == 1); + assert_se(CMP((const unsigned long long *)arr, &arr[3]) == -1); + assert_se(CMP(*arr, arr[3]) == 1); + assert_se(CMP(p, q) == -1); + assert_se(CMP(q, p) == 1); + assert_se(CMP(p, p) == 0); + assert_se(CMP(q, q) == 0); + assert_se(CLAMP(-5, 0, 1) == 0); + assert_se(CLAMP(5, 0, 1) == 1); + assert_se(CLAMP(5, -10, 1) == 1); + assert_se(CLAMP(5, -10, 10) == 5); + assert_se(CLAMP(CLAMP(0, -10, 10), CLAMP(-5, 10, 20), CLAMP(100, -5, 20)) == 10); +} + +#pragma GCC diagnostic push +#ifdef __clang__ +# pragma GCC diagnostic ignored "-Waddress-of-packed-member" +#endif + +static void test_container_of(void) { + struct mytype { + uint8_t pad1[3]; + uint64_t v1; + uint8_t pad2[2]; + uint32_t v2; + } myval = { }; + + log_info("/* %s */", __func__); + + assert_cc(sizeof(myval) >= 17); + assert_se(container_of(&myval.v1, struct mytype, v1) == &myval); + assert_se(container_of(&myval.v2, struct mytype, v2) == &myval); + assert_se(container_of(&container_of(&myval.v2, + struct mytype, + v2)->v1, + struct mytype, + v1) == &myval); +} + +#pragma GCC diagnostic pop + +static void test_div_round_up(void) { + int div; + + log_info("/* %s */", __func__); + + /* basic tests */ + assert_se(DIV_ROUND_UP(0, 8) == 0); + assert_se(DIV_ROUND_UP(1, 8) == 1); + assert_se(DIV_ROUND_UP(8, 8) == 1); + assert_se(DIV_ROUND_UP(12, 8) == 2); + assert_se(DIV_ROUND_UP(16, 8) == 2); + + /* test multiple evaluation */ + div = 0; + assert_se(DIV_ROUND_UP(div++, 8) == 0 && div == 1); + assert_se(DIV_ROUND_UP(++div, 8) == 1 && div == 2); + assert_se(DIV_ROUND_UP(8, div++) == 4 && div == 3); + assert_se(DIV_ROUND_UP(8, ++div) == 2 && div == 4); + + /* overflow test with exact division */ + assert_se(sizeof(0U) == 4); + assert_se(0xfffffffaU % 10U == 0U); + assert_se(0xfffffffaU / 10U == 429496729U); + assert_se(DIV_ROUND_UP(0xfffffffaU, 10U) == 429496729U); + assert_se((0xfffffffaU + 10U - 1U) / 10U == 0U); + assert_se(0xfffffffaU / 10U + !!(0xfffffffaU % 10U) == 429496729U); + + /* overflow test with rounded division */ + assert_se(0xfffffffdU % 10U == 3U); + assert_se(0xfffffffdU / 10U == 429496729U); + assert_se(DIV_ROUND_UP(0xfffffffdU, 10U) == 429496730U); + assert_se((0xfffffffdU + 10U - 1U) / 10U == 0U); + assert_se(0xfffffffdU / 10U + !!(0xfffffffdU % 10U) == 429496730U); +} + +static void test_u64log2(void) { + log_info("/* %s */", __func__); + + assert_se(u64log2(0) == 0); + assert_se(u64log2(8) == 3); + assert_se(u64log2(9) == 3); + assert_se(u64log2(15) == 3); + assert_se(u64log2(16) == 4); + assert_se(u64log2(1024*1024) == 20); + assert_se(u64log2(1024*1024+5) == 20); +} + +static void test_protect_errno(void) { + log_info("/* %s */", __func__); + + errno = 12; + { + PROTECT_ERRNO; + errno = 11; + } + assert_se(errno == 12); +} + +static void test_unprotect_errno_inner_function(void) { + PROTECT_ERRNO; + + errno = 2222; +} + +static void test_unprotect_errno(void) { + log_info("/* %s */", __func__); + + errno = 4711; + + PROTECT_ERRNO; + + errno = 815; + + UNPROTECT_ERRNO; + + assert_se(errno == 4711); + + test_unprotect_errno_inner_function(); + + assert_se(errno == 4711); +} + +static void test_in_set(void) { + log_info("/* %s */", __func__); + + assert_se(IN_SET(1, 1)); + assert_se(IN_SET(1, 1, 2, 3, 4)); + assert_se(IN_SET(2, 1, 2, 3, 4)); + assert_se(IN_SET(3, 1, 2, 3, 4)); + assert_se(IN_SET(4, 1, 2, 3, 4)); + assert_se(!IN_SET(0, 1)); + assert_se(!IN_SET(0, 1, 2, 3, 4)); +} + +static void test_log2i(void) { + log_info("/* %s */", __func__); + + assert_se(log2i(1) == 0); + assert_se(log2i(2) == 1); + assert_se(log2i(3) == 1); + assert_se(log2i(4) == 2); + assert_se(log2i(32) == 5); + assert_se(log2i(33) == 5); + assert_se(log2i(63) == 5); + assert_se(log2i(INT_MAX) == sizeof(int)*8-2); +} + +static void test_eqzero(void) { + const uint32_t zeros[] = {0, 0, 0}; + const uint32_t ones[] = {1, 1}; + const uint32_t mixed[] = {0, 1, 0, 0, 0}; + const uint8_t longer[] = {[55] = 255}; + + log_info("/* %s */", __func__); + + assert_se(eqzero(zeros)); + assert_se(!eqzero(ones)); + assert_se(!eqzero(mixed)); + assert_se(!eqzero(longer)); +} + +static void test_raw_clone(void) { + pid_t parent, pid, pid2; + + log_info("/* %s */", __func__); + + parent = getpid(); + log_info("before clone: getpid()→"PID_FMT, parent); + assert_se(raw_getpid() == parent); + + pid = raw_clone(0); + assert_se(pid >= 0); + + pid2 = raw_getpid(); + log_info("raw_clone: "PID_FMT" getpid()→"PID_FMT" raw_getpid()→"PID_FMT, + pid, getpid(), pid2); + if (pid == 0) { + assert_se(pid2 != parent); + _exit(EXIT_SUCCESS); + } else { + int status; + + assert_se(pid2 == parent); + waitpid(pid, &status, __WCLONE); + assert_se(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS); + } + + errno = 0; + assert_se(raw_clone(CLONE_FS|CLONE_NEWNS) == -1); + assert_se(errno == EINVAL); +} + +static void test_physical_memory(void) { + uint64_t p; + char buf[FORMAT_BYTES_MAX]; + + log_info("/* %s */", __func__); + + p = physical_memory(); + assert_se(p > 0); + assert_se(p < UINT64_MAX); + assert_se(p % page_size() == 0); + + log_info("Memory: %s (%" PRIu64 ")", format_bytes(buf, sizeof(buf), p), p); +} + +static void test_physical_memory_scale(void) { + uint64_t p; + + log_info("/* %s */", __func__); + + p = physical_memory(); + + assert_se(physical_memory_scale(0, 100) == 0); + assert_se(physical_memory_scale(100, 100) == p); + + log_info("Memory original: %" PRIu64, physical_memory()); + log_info("Memory scaled by 50%%: %" PRIu64, physical_memory_scale(50, 100)); + log_info("Memory divided by 2: %" PRIu64, physical_memory() / 2); + log_info("Page size: %zu", page_size()); + + /* There might be an uneven number of pages, hence permit these calculations to be half a page off... */ + assert_se(page_size()/2 + physical_memory_scale(50, 100) - p/2 <= page_size()); + assert_se(physical_memory_scale(200, 100) == p*2); + + assert_se(physical_memory_scale(0, 1) == 0); + assert_se(physical_memory_scale(1, 1) == p); + assert_se(physical_memory_scale(2, 1) == p*2); + + assert_se(physical_memory_scale(0, 2) == 0); + + assert_se(page_size()/2 + physical_memory_scale(1, 2) - p/2 <= page_size()); + assert_se(physical_memory_scale(2, 2) == p); + assert_se(physical_memory_scale(4, 2) == p*2); + + assert_se(physical_memory_scale(0, UINT32_MAX) == 0); + assert_se(physical_memory_scale(UINT32_MAX, UINT32_MAX) == p); + + /* overflow */ + assert_se(physical_memory_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX); +} + +static void test_system_tasks_max(void) { + uint64_t t; + + log_info("/* %s */", __func__); + + t = system_tasks_max(); + assert_se(t > 0); + assert_se(t < UINT64_MAX); + + log_info("Max tasks: %" PRIu64, t); +} + +static void test_system_tasks_max_scale(void) { + uint64_t t; + + log_info("/* %s */", __func__); + + t = system_tasks_max(); + + assert_se(system_tasks_max_scale(0, 100) == 0); + assert_se(system_tasks_max_scale(100, 100) == t); + + assert_se(system_tasks_max_scale(0, 1) == 0); + assert_se(system_tasks_max_scale(1, 1) == t); + assert_se(system_tasks_max_scale(2, 1) == 2*t); + + assert_se(system_tasks_max_scale(0, 2) == 0); + assert_se(system_tasks_max_scale(1, 2) == t/2); + assert_se(system_tasks_max_scale(2, 2) == t); + assert_se(system_tasks_max_scale(3, 2) == (3*t)/2); + assert_se(system_tasks_max_scale(4, 2) == t*2); + + assert_se(system_tasks_max_scale(0, UINT32_MAX) == 0); + assert_se(system_tasks_max_scale((UINT32_MAX-1)/2, UINT32_MAX-1) == t/2); + assert_se(system_tasks_max_scale(UINT32_MAX, UINT32_MAX) == t); + + /* overflow */ + + assert_se(system_tasks_max_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + test_align_power2(); + test_max(); + test_container_of(); + test_div_round_up(); + test_u64log2(); + test_protect_errno(); + test_unprotect_errno(); + test_in_set(); + test_log2i(); + test_eqzero(); + test_raw_clone(); + test_physical_memory(); + test_physical_memory_scale(); + test_system_tasks_max(); + test_system_tasks_max_scale(); + + return 0; +} diff --git a/src/test/test-varlink.c b/src/test/test-varlink.c new file mode 100644 index 00000000..fbfc72cd --- /dev/null +++ b/src/test/test-varlink.c @@ -0,0 +1,239 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "sd-event.h" + +#include "fd-util.h" +#include "json.h" +#include "rm-rf.h" +#include "strv.h" +#include "tmpfile-util.h" +#include "user-util.h" +#include "varlink.h" + +/* Let's pick some high value, that is higher than the largest listen() backlog, but leaves enough room below + the typical RLIMIT_NOFILE value of 1024 so that we can process both sides of each socket in our + process. Or in other words: "OVERLOAD_CONNECTIONS * 2 + x < 1024" should hold, for some small x that + should cover any auxiliary fds, the listener server fds, stdin/stdout/stderr and whatever else. */ +#define OVERLOAD_CONNECTIONS 333 + +static int n_done = 0; +static int block_write_fd = -1; + +static int method_something(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { + _cleanup_(json_variant_unrefp) JsonVariant *ret = NULL; + JsonVariant *a, *b; + intmax_t x, y; + int r; + + a = json_variant_by_key(parameters, "a"); + if (!a) + return varlink_error(link, "io.test.BadParameters", NULL); + + x = json_variant_integer(a); + + b = json_variant_by_key(parameters, "b"); + if (!b) + return varlink_error(link, "io.test.BadParameters", NULL); + + y = json_variant_integer(b); + + r = json_build(&ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("sum", JSON_BUILD_INTEGER(x + y)))); + if (r < 0) + return r; + + return varlink_reply(link, ret); +} + +static int method_done(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) { + + if (++n_done == 2) + sd_event_exit(varlink_get_event(link), EXIT_FAILURE); + + return 0; +} + +static int reply(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) { + JsonVariant *sum; + + sum = json_variant_by_key(parameters, "sum"); + + assert_se(json_variant_integer(sum) == 7+22); + + if (++n_done == 2) + sd_event_exit(varlink_get_event(link), EXIT_FAILURE); + + return 0; +} + +static int on_connect(VarlinkServer *s, Varlink *link, void *userdata) { + uid_t uid = UID_INVALID; + + assert(s); + assert(link); + + assert_se(varlink_get_peer_uid(link, &uid) >= 0); + assert_se(getuid() == uid); + + return 0; +} + +static int overload_reply(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) { + + /* This method call reply should always be called with a disconnection, since the method call should + * be talking to an overloaded server */ + + log_debug("Over reply triggered with error: %s", strna(error_id)); + assert_se(streq(error_id, VARLINK_ERROR_DISCONNECTED)); + sd_event_exit(varlink_get_event(link), 0); + + return 0; +} + +static void flood_test(const char *address) { + _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL; + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_free_ Varlink **connections = NULL; + size_t k; + char x = 'x'; + + log_debug("Flooding server..."); + + /* Block the main event loop while we flood */ + assert_se(write(block_write_fd, &x, sizeof(x)) == sizeof(x)); + + assert_se(sd_event_default(&e) >= 0); + + /* Flood the server with connections */ + assert_se(connections = new0(Varlink*, OVERLOAD_CONNECTIONS)); + for (k = 0; k < OVERLOAD_CONNECTIONS; k++) { + _cleanup_free_ char *t = NULL; + log_debug("connection %zu", k); + assert_se(varlink_connect_address(connections + k, address) >= 0); + + assert_se(asprintf(&t, "flood-%zu", k) >= 0); + assert_se(varlink_set_description(connections[k], t) >= 0); + assert_se(varlink_attach_event(connections[k], e, k) >= 0); + assert_se(varlink_sendb(connections[k], "io.test.Rubbish", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("id", JSON_BUILD_INTEGER(k)))) >= 0); + } + + /* Then, create one more, which should fail */ + log_debug("Creating overload connection..."); + assert_se(varlink_connect_address(&c, address) >= 0); + assert_se(varlink_set_description(c, "overload-client") >= 0); + assert_se(varlink_attach_event(c, e, k) >= 0); + assert_se(varlink_bind_reply(c, overload_reply) >= 0); + assert_se(varlink_invokeb(c, "io.test.Overload", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("foo", JSON_BUILD_STRING("bar")))) >= 0); + + /* Unblock it */ + log_debug("Unblocking server..."); + block_write_fd = safe_close(block_write_fd); + + /* This loop will terminate as soon as the overload reply callback is called */ + assert_se(sd_event_loop(e) >= 0); + + /* And close all connections again */ + for (k = 0; k < OVERLOAD_CONNECTIONS; k++) + connections[k] = varlink_unref(connections[k]); +} + +static void *thread(void *arg) { + _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL; + _cleanup_(json_variant_unrefp) JsonVariant *i = NULL; + JsonVariant *o = NULL; + const char *e; + + assert_se(json_build(&i, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("a", JSON_BUILD_INTEGER(88)), + JSON_BUILD_PAIR("b", JSON_BUILD_INTEGER(99)))) >= 0); + + assert_se(varlink_connect_address(&c, arg) >= 0); + assert_se(varlink_set_description(c, "thread-client") >= 0); + + assert_se(varlink_call(c, "io.test.DoSomething", i, &o, &e, NULL) >= 0); + assert_se(json_variant_integer(json_variant_by_key(o, "sum")) == 88 + 99); + assert_se(!e); + + assert_se(varlink_callb(c, "io.test.IDontExist", &o, &e, NULL, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("x", JSON_BUILD_REAL(5.5)))) >= 0); + assert_se(streq_ptr(json_variant_string(json_variant_by_key(o, "method")), "io.test.IDontExist")); + assert_se(streq(e, VARLINK_ERROR_METHOD_NOT_FOUND)); + + flood_test(arg); + + assert_se(varlink_send(c, "io.test.Done", NULL) >= 0); + + return NULL; +} + +static int block_fd_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + char c; + + assert_se(fd_nonblock(fd, false) >= 0); + + assert_se(read(fd, &c, sizeof(c)) == sizeof(c)); + /* When a character is written to this pipe we'll block until the pipe is closed. */ + + assert_se(read(fd, &c, sizeof(c)) == 0); + + assert_se(fd_nonblock(fd, true) >= 0); + + assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); + + return 0; +} + +int main(int argc, char *argv[]) { + _cleanup_(sd_event_source_unrefp) sd_event_source *block_event = NULL; + _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL; + _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL; + _cleanup_(rm_rf_physical_and_freep) char *tmpdir = NULL; + _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_(close_pairp) int block_fds[2] = { -1, -1 }; + pthread_t t; + const char *sp; + + log_set_max_level(LOG_DEBUG); + log_open(); + + assert_se(mkdtemp_malloc("/tmp/varlink-test-XXXXXX", &tmpdir) >= 0); + sp = strjoina(tmpdir, "/socket"); + + assert_se(sd_event_default(&e) >= 0); + + assert_se(pipe2(block_fds, O_NONBLOCK|O_CLOEXEC) >= 0); + assert_se(sd_event_add_io(e, &block_event, block_fds[0], EPOLLIN, block_fd_handler, NULL) >= 0); + assert_se(sd_event_source_set_priority(block_event, SD_EVENT_PRIORITY_IMPORTANT) >= 0); + block_write_fd = TAKE_FD(block_fds[1]); + + assert_se(varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID) >= 0); + assert_se(varlink_server_set_description(s, "our-server") >= 0); + + assert_se(varlink_server_bind_method(s, "io.test.DoSomething", method_something) >= 0); + assert_se(varlink_server_bind_method(s, "io.test.Done", method_done) >= 0); + assert_se(varlink_server_bind_connect(s, on_connect) >= 0); + assert_se(varlink_server_listen_address(s, sp, 0600) >= 0); + assert_se(varlink_server_attach_event(s, e, 0) >= 0); + assert_se(varlink_server_set_connections_max(s, OVERLOAD_CONNECTIONS) >= 0); + + assert_se(varlink_connect_address(&c, sp) >= 0); + assert_se(varlink_set_description(c, "main-client") >= 0); + assert_se(varlink_bind_reply(c, reply) >= 0); + + assert_se(json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("a", JSON_BUILD_INTEGER(7)), + JSON_BUILD_PAIR("b", JSON_BUILD_INTEGER(22)))) >= 0); + + assert_se(varlink_invoke(c, "io.test.DoSomething", v) >= 0); + + assert_se(varlink_attach_event(c, e, 0) >= 0); + + assert_se(pthread_create(&t, NULL, thread, (void*) sp) == 0); + + assert_se(sd_event_loop(e) >= 0); + + assert_se(pthread_join(t, NULL) == 0); + + return 0; +} diff --git a/src/test/test-verbs.c b/src/test/test-verbs.c new file mode 100644 index 00000000..24593c75 --- /dev/null +++ b/src/test/test-verbs.c @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "macro.h" +#include "strv.h" +#include "verbs.h" + +static int noop_dispatcher(int argc, char *argv[], void *userdata) { + return 0; +} + +#define test_dispatch_one(argv, verbs, expected) \ + optind = 0; \ + assert_se(dispatch_verb(strv_length(argv), argv, verbs, NULL) == expected); + +static void test_verbs(void) { + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, noop_dispatcher }, + { "list-images", VERB_ANY, 1, 0, noop_dispatcher }, + { "list", VERB_ANY, 2, VERB_DEFAULT, noop_dispatcher }, + { "status", 2, VERB_ANY, 0, noop_dispatcher }, + { "show", VERB_ANY, VERB_ANY, 0, noop_dispatcher }, + { "terminate", 2, VERB_ANY, 0, noop_dispatcher }, + { "login", 2, 2, 0, noop_dispatcher }, + { "copy-to", 3, 4, 0, noop_dispatcher }, + {} + }; + + /* not found */ + test_dispatch_one(STRV_MAKE("command-not-found"), verbs, -EINVAL); + + /* found */ + test_dispatch_one(STRV_MAKE("show"), verbs, 0); + + /* found, too few args */ + test_dispatch_one(STRV_MAKE("copy-to", "foo"), verbs, -EINVAL); + + /* found, meets min args */ + test_dispatch_one(STRV_MAKE("status", "foo", "bar"), verbs, 0); + + /* found, too many args */ + test_dispatch_one(STRV_MAKE("copy-to", "foo", "bar", "baz", "quux", "qaax"), verbs, -EINVAL); + + /* no verb, but a default is set */ + test_dispatch_one(STRV_MAKE_EMPTY, verbs, 0); +} + +static void test_verbs_no_default(void) { + static const Verb verbs[] = { + { "help", VERB_ANY, VERB_ANY, 0, noop_dispatcher }, + {}, + }; + + test_dispatch_one(STRV_MAKE(NULL), verbs, -EINVAL); +} + +int main(int argc, char *argv[]) { + test_verbs(); + test_verbs_no_default(); + + return 0; +} diff --git a/src/test/test-watch-pid.c b/src/test/test-watch-pid.c new file mode 100644 index 00000000..bad28976 --- /dev/null +++ b/src/test/test-watch-pid.c @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "log.h" +#include "manager.h" +#include "rm-rf.h" +#include "service.h" +#include "tests.h" + +int main(int argc, char *argv[]) { + _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + Unit *a, *b, *c, *u; + int r; + + test_setup_logging(LOG_DEBUG); + + if (getuid() != 0) + return log_tests_skipped("not root"); + r = enter_cgroup_subroot(NULL); + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + + assert_se(set_unit_path(get_testdata_dir()) >= 0); + assert_se(runtime_dir = setup_fake_runtime_dir()); + + assert_se(manager_new(UNIT_FILE_USER, MANAGER_TEST_RUN_BASIC, &m) >= 0); + assert_se(manager_startup(m, NULL, NULL) >= 0); + + assert_se(a = unit_new(m, sizeof(Service))); + assert_se(unit_add_name(a, "a.service") >= 0); + assert_se(set_isempty(a->pids)); + + assert_se(b = unit_new(m, sizeof(Service))); + assert_se(unit_add_name(b, "b.service") >= 0); + assert_se(set_isempty(b->pids)); + + assert_se(c = unit_new(m, sizeof(Service))); + assert_se(unit_add_name(c, "c.service") >= 0); + assert_se(set_isempty(c->pids)); + + assert_se(hashmap_isempty(m->watch_pids)); + assert_se(manager_get_unit_by_pid(m, 4711) == NULL); + + assert_se(unit_watch_pid(a, 4711, false) >= 0); + assert_se(manager_get_unit_by_pid(m, 4711) == a); + + assert_se(unit_watch_pid(a, 4711, false) >= 0); + assert_se(manager_get_unit_by_pid(m, 4711) == a); + + assert_se(unit_watch_pid(b, 4711, false) >= 0); + u = manager_get_unit_by_pid(m, 4711); + assert_se(u == a || u == b); + + assert_se(unit_watch_pid(b, 4711, false) >= 0); + u = manager_get_unit_by_pid(m, 4711); + assert_se(u == a || u == b); + + assert_se(unit_watch_pid(c, 4711, false) >= 0); + u = manager_get_unit_by_pid(m, 4711); + assert_se(u == a || u == b || u == c); + + assert_se(unit_watch_pid(c, 4711, false) >= 0); + u = manager_get_unit_by_pid(m, 4711); + assert_se(u == a || u == b || u == c); + + unit_unwatch_pid(b, 4711); + u = manager_get_unit_by_pid(m, 4711); + assert_se(u == a || u == c); + + unit_unwatch_pid(b, 4711); + u = manager_get_unit_by_pid(m, 4711); + assert_se(u == a || u == c); + + unit_unwatch_pid(a, 4711); + assert_se(manager_get_unit_by_pid(m, 4711) == c); + + unit_unwatch_pid(a, 4711); + assert_se(manager_get_unit_by_pid(m, 4711) == c); + + unit_unwatch_pid(c, 4711); + assert_se(manager_get_unit_by_pid(m, 4711) == NULL); + + unit_unwatch_pid(c, 4711); + assert_se(manager_get_unit_by_pid(m, 4711) == NULL); + + return 0; +} diff --git a/src/test/test-watchdog.c b/src/test/test-watchdog.c new file mode 100644 index 00000000..ab66d5c4 --- /dev/null +++ b/src/test/test-watchdog.c @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "log.h" +#include "tests.h" +#include "watchdog.h" + +int main(int argc, char *argv[]) { + usec_t t; + unsigned i, count; + int r; + bool slow; + + test_setup_logging(LOG_DEBUG); + + slow = slow_tests_enabled(); + + t = slow ? 10 * USEC_PER_SEC : 1 * USEC_PER_SEC; + count = slow ? 5 : 3; + + r = watchdog_set_timeout(&t); + if (r < 0) + log_warning_errno(r, "Failed to open watchdog: %m"); + if (r == -EPERM) + t = 0; + + for (i = 0; i < count; i++) { + log_info("Pinging..."); + r = watchdog_ping(); + if (r < 0) + log_warning_errno(r, "Failed to ping watchdog: %m"); + + usleep(t/2); + } + + watchdog_close(true); + return 0; +} diff --git a/src/test/test-web-util.c b/src/test/test-web-util.c new file mode 100644 index 00000000..dd1df8c2 --- /dev/null +++ b/src/test/test-web-util.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "macro.h" +#include "web-util.h" + +static void test_is_valid_documentation_url(void) { + assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd")); + assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt")); /* dead */ + assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst")); + assert_se(documentation_url_is_valid("https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html")); + assert_se(documentation_url_is_valid("file:/foo/foo")); + assert_se(documentation_url_is_valid("man:systemd.special(7)")); + assert_se(documentation_url_is_valid("info:bar")); + + assert_se(!documentation_url_is_valid("foo:")); + assert_se(!documentation_url_is_valid("info:")); + assert_se(!documentation_url_is_valid("")); +} + +int main(int argc, char *argv[]) { + test_is_valid_documentation_url(); + + return 0; +} diff --git a/src/test/test-xattr-util.c b/src/test/test-xattr-util.c new file mode 100644 index 00000000..3e6df96c --- /dev/null +++ b/src/test/test-xattr-util.c @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "macro.h" +#include "string-util.h" +#include "tests.h" +#include "tmpfile-util.h" +#include "xattr-util.h" + +static void test_fgetxattrat_fake(void) { + char t[] = "/var/tmp/xattrtestXXXXXX"; + _cleanup_close_ int fd = -1; + const char *x; + char v[3]; + int r; + size_t size; + + assert_se(mkdtemp(t)); + x = strjoina(t, "/test"); + assert_se(touch(x) >= 0); + + r = setxattr(x, "user.foo", "bar", 3, 0); + if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */ + goto cleanup; + assert_se(r >= 0); + + fd = open(t, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY); + assert_se(fd >= 0); + + assert_se(fgetxattrat_fake(fd, "test", "user.foo", v, 3, 0, &size) >= 0); + assert_se(size == 3); + assert_se(memcmp(v, "bar", 3) == 0); + + safe_close(fd); + fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY); + assert_se(fd >= 0); + assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0, &size) == -ENODATA); + +cleanup: + assert_se(unlink(x) >= 0); + assert_se(rmdir(t) >= 0); +} + +static void test_getcrtime(void) { + + _cleanup_close_ int fd = -1; + char ts[FORMAT_TIMESTAMP_MAX]; + const char *vt; + usec_t usec, k; + int r; + + assert_se(tmp_dir(&vt) >= 0); + + fd = open_tmpfile_unlinkable(vt, O_RDWR); + assert_se(fd >= 0); + + r = fd_getcrtime(fd, &usec); + if (r < 0) + log_debug_errno(r, "btime: %m"); + else + log_debug("btime: %s", format_timestamp(ts, sizeof(ts), usec)); + + k = now(CLOCK_REALTIME); + + r = fd_setcrtime(fd, 1519126446UL * USEC_PER_SEC); + if (!IN_SET(r, -EOPNOTSUPP, -ENOTTY)) { + assert_se(fd_getcrtime(fd, &usec) >= 0); + assert_se(k < 1519126446UL * USEC_PER_SEC || + usec == 1519126446UL * USEC_PER_SEC); + } +} + +int main(void) { + test_setup_logging(LOG_DEBUG); + + test_fgetxattrat_fake(); + test_getcrtime(); + + return 0; +} diff --git a/src/test/test-xml.c b/src/test/test-xml.c new file mode 100644 index 00000000..63e7a10e --- /dev/null +++ b/src/test/test-xml.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "string-util.h" +#include "util.h" +#include "xml.h" + +static void test_one(const char *data, ...) { + void *state = NULL; + va_list ap; + + va_start(ap, data); + + for (;;) { + _cleanup_free_ char *name = NULL; + int t, tt; + const char *nn; + + t = xml_tokenize(&data, &name, &state, NULL); + assert_se(t >= 0); + + tt = va_arg(ap, int); + assert_se(tt >= 0); + + assert_se(t == tt); + if (t == XML_END) + break; + + nn = va_arg(ap, const char *); + assert_se(streq_ptr(nn, name)); + } + + va_end(ap); +} + +int main(int argc, char *argv[]) { + + test_one("", XML_END); + + test_one("", + XML_TAG_OPEN, "foo", + XML_TAG_CLOSE, "foo", + XML_END); + + test_one("", + XML_TAG_OPEN, "foo", + XML_ATTRIBUTE_NAME, "waldo", + XML_ATTRIBUTE_VALUE, "piep", + XML_ATTRIBUTE_NAME, "meh", + XML_ATTRIBUTE_VALUE, "huhu", + XML_TAG_CLOSE_EMPTY, NULL, + XML_END); + + test_one("xxxx\n" + " ", + XML_TEXT, "xxxx\n", + XML_TAG_OPEN, "foo", + XML_TEXT, " ", + XML_TEXT, " ", + XML_TAG_CLOSE, "foo", + XML_END); + + return 0; +} diff --git a/src/time-wait-sync/time-wait-sync.c b/src/time-wait-sync/time-wait-sync.c new file mode 100644 index 00000000..e880f9e6 --- /dev/null +++ b/src/time-wait-sync/time-wait-sync.c @@ -0,0 +1,250 @@ +/* + * systemd service to wait until kernel realtime clock is synchronized + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-event.h" + +#include "fd-util.h" +#include "fs-util.h" +#include "main-func.h" +#include "signal-util.h" +#include "time-util.h" + +typedef struct ClockState { + int timerfd_fd; /* non-negative is descriptor from timerfd_create */ + int adjtime_state; /* return value from last adjtimex(2) call */ + sd_event_source *timerfd_event_source; /* non-null is the active io event source */ + int inotify_fd; + sd_event_source *inotify_event_source; + int run_systemd_wd; + int run_systemd_timesync_wd; + bool has_watchfile; +} ClockState; + +static void clock_state_release_timerfd(ClockState *sp) { + sp->timerfd_event_source = sd_event_source_unref(sp->timerfd_event_source); + sp->timerfd_fd = safe_close(sp->timerfd_fd); +} + +static void clock_state_release(ClockState *sp) { + clock_state_release_timerfd(sp); + sp->inotify_event_source = sd_event_source_unref(sp->inotify_event_source); + sp->inotify_fd = safe_close(sp->inotify_fd); +} + +static int clock_state_update(ClockState *sp, sd_event *event); + +static int update_notify_run_systemd_timesync(ClockState *sp) { + sp->run_systemd_timesync_wd = inotify_add_watch(sp->inotify_fd, "/run/systemd/timesync", IN_CREATE|IN_DELETE_SELF); + return sp->run_systemd_timesync_wd; +} + +static int timerfd_handler(sd_event_source *s, + int fd, + uint32_t revents, + void *userdata) { + ClockState *sp = userdata; + + return clock_state_update(sp, sd_event_source_get_event(s)); +} + +static void process_inotify_event(sd_event *event, ClockState *sp, struct inotify_event *e) { + if (e->wd == sp->run_systemd_wd) { + /* Only thing we care about is seeing if we can start watching /run/systemd/timesync. */ + if (sp->run_systemd_timesync_wd < 0) + update_notify_run_systemd_timesync(sp); + } else if (e->wd == sp->run_systemd_timesync_wd) { + if (e->mask & IN_DELETE_SELF) { + /* Somebody removed /run/systemd/timesync. */ + (void) inotify_rm_watch(sp->inotify_fd, sp->run_systemd_timesync_wd); + sp->run_systemd_timesync_wd = -1; + } else + /* Somebody might have created /run/systemd/timesync/synchronized. */ + clock_state_update(sp, event); + } +} + +static int inotify_handler(sd_event_source *s, + int fd, + uint32_t revents, + void *userdata) { + sd_event *event = sd_event_source_get_event(s); + ClockState *sp = userdata; + union inotify_event_buffer buffer; + struct inotify_event *e; + ssize_t l; + + l = read(fd, &buffer, sizeof(buffer)); + if (l < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 0; + + return log_warning_errno(errno, "Lost access to inotify: %m"); + } + FOREACH_INOTIFY_EVENT(e, buffer, l) + process_inotify_event(event, sp, e); + + return 0; +} + +static int clock_state_update( + ClockState *sp, + sd_event *event) { + + char buf[MAX((size_t)FORMAT_TIMESTAMP_MAX, STRLEN("unrepresentable"))]; + struct timex tx = {}; + const char * ts; + usec_t t; + int r; + + clock_state_release_timerfd(sp); + + /* The kernel supports cancelling timers whenever its realtime clock is "set" (which can happen in a variety of + * ways, generally adjustments of at least 500 ms). The way this module works is we set up a timerfd that will + * wake when the clock is set, and when that happens we read the clock synchronization state from the return + * value of adjtimex(2), which supports the NTP time adjustment protocol. + * + * The kernel determines whether the clock is synchronized using driver-specific tests, based on time + * information passed by an application, generally through adjtimex(2). If the application asserts the clock is + * synchronized, but does not also do something that "sets the clock", the timer will not be cancelled and + * synchronization will not be detected. + * + * Similarly, this service will never complete if the application sets the time without also providing + * information that adjtimex(2) can use to determine that the clock is synchronized. This generally doesn't + * happen, but can if the system has a hardware clock that is accurate enough that the adjustment is too small + * to be a "set". + * + * Both these failure-to-detect situations are covered by having the presence/creation of + * /run/systemd/timesync/synchronized, which is considered sufficient to indicate a synchronized clock even if + * the kernel has not been updated. + * + * For timesyncd the initial setting of the time uses settimeofday(2), which sets the clock but does not mark + * it synchronized. When an NTP source is selected it sets the clock again with clock_adjtime(2) which marks it + * synchronized and also touches /run/systemd/timesync/synchronized which covers the case when the clock wasn't + * "set". */ + + r = time_change_fd(); + if (r < 0) { + log_error_errno(r, "Failed to create timerfd: %m"); + goto finish; + } + sp->timerfd_fd = r; + + r = adjtimex(&tx); + if (r < 0) { + log_error_errno(errno, "Failed to read adjtimex state: %m"); + goto finish; + } + sp->adjtime_state = r; + + if (tx.status & STA_NANO) + tx.time.tv_usec /= 1000; + t = timeval_load(&tx.time); + ts = format_timestamp_us_utc(buf, sizeof(buf), t); + if (!ts) + strcpy(buf, "unrepresentable"); + log_info("adjtime state %d status %x time %s", sp->adjtime_state, tx.status, ts); + + sp->has_watchfile = access("/run/systemd/timesync/synchronized", F_OK) >= 0; + if (sp->has_watchfile) + /* Presence of watch file overrides adjtime_state */ + r = 0; + else if (sp->adjtime_state == TIME_ERROR) { + /* Not synchronized. Do a one-shot wait on the descriptor and inform the caller we need to keep + * running. */ + r = sd_event_add_io(event, &sp->timerfd_event_source, sp->timerfd_fd, + EPOLLIN, timerfd_handler, sp); + if (r < 0) { + log_error_errno(r, "Failed to create time change monitor source: %m"); + goto finish; + } + r = 1; + } else + /* Synchronized; we can exit. */ + r = 0; + + finish: + if (r <= 0) + (void) sd_event_exit(event, r); + return r; +} + +static int run(int argc, char * argv[]) { + _cleanup_(sd_event_unrefp) sd_event *event; + _cleanup_(clock_state_release) ClockState state = { + .timerfd_fd = -1, + .inotify_fd = -1, + .run_systemd_wd = -1, + .run_systemd_timesync_wd = -1, + }; + int r; + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create sigterm event source: %m"); + + r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to create sigint event source: %m"); + + r = sd_event_set_watchdog(event, true); + if (r < 0) + return log_error_errno(r, "Failed to create watchdog event source: %m"); + + r = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); + if (r < 0) + return log_error_errno(errno, "Failed to create inotify descriptor: %m"); + + state.inotify_fd = r; + + r = sd_event_add_io(event, &state.inotify_event_source, state.inotify_fd, + EPOLLIN, inotify_handler, &state); + if (r < 0) + return log_error_errno(r, "Failed to create notify event source: %m"); + + r = inotify_add_watch_and_warn(state.inotify_fd, "/run/systemd/", IN_CREATE); + if (r < 0) + return r; + + state.run_systemd_wd = r; + + (void) update_notify_run_systemd_timesync(&state); + + r = clock_state_update(&state, event); + if (r > 0) { + r = sd_event_loop(event); + if (r < 0) + log_error_errno(r, "Failed in event loop: %m"); + } + + if (state.has_watchfile) + log_debug("Exit enabled by: /run/systemd/timesync/synchronized"); + + if (state.adjtime_state == TIME_ERROR) + log_info("Exit without adjtimex synchronized."); + + return r; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/timedate/meson.build b/src/timedate/meson.build new file mode 100644 index 00000000..46c7360d --- /dev/null +++ b/src/timedate/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +if conf.get('ENABLE_TIMEDATED') == 1 + install_data('org.freedesktop.timedate1.conf', + install_dir : dbuspolicydir) + install_data('org.freedesktop.timedate1.service', + install_dir : dbussystemservicedir) + install_data('org.freedesktop.timedate1.policy', + install_dir : polkitpolicydir) +endif diff --git a/src/timedate/org.freedesktop.timedate1.conf b/src/timedate/org.freedesktop.timedate1.conf new file mode 100644 index 00000000..53f6c843 --- /dev/null +++ b/src/timedate/org.freedesktop.timedate1.conf @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/timedate/org.freedesktop.timedate1.policy b/src/timedate/org.freedesktop.timedate1.policy new file mode 100644 index 00000000..b6303ba1 --- /dev/null +++ b/src/timedate/org.freedesktop.timedate1.policy @@ -0,0 +1,62 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Set system time + Authentication is required to set the system time. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.timedate1.set-timezone org.freedesktop.timedate1.set-ntp + + + + Set system timezone + Authentication is required to set the system timezone. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Set RTC to local timezone or UTC + Authentication is required to control whether the RTC stores the local or UTC time. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Turn network time synchronization on or off + Authentication is required to control whether network time synchronization shall be enabled. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + diff --git a/src/timedate/org.freedesktop.timedate1.service b/src/timedate/org.freedesktop.timedate1.service new file mode 100644 index 00000000..d5f3a6e3 --- /dev/null +++ b/src/timedate/org.freedesktop.timedate1.service @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.timedate1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.timedate1.service diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c new file mode 100644 index 00000000..d31b3190 --- /dev/null +++ b/src/timedate/timedatectl.c @@ -0,0 +1,989 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-bus.h" + +#include "bus-error.h" +#include "bus-util.h" +#include "in-addr-util.h" +#include "main-func.h" +#include "pager.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "spawn-polkit-agent.h" +#include "sparse-endian.h" +#include "string-table.h" +#include "strv.h" +#include "terminal-util.h" +#include "util.h" +#include "verbs.h" + +static PagerFlags arg_pager_flags = 0; +static bool arg_ask_password = true; +static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; +static char *arg_host = NULL; +static bool arg_adjust_system_clock = false; +static bool arg_monitor = false; +static char **arg_property = NULL; +static bool arg_value = false; +static bool arg_all = false; + +typedef struct StatusInfo { + usec_t time; + const char *timezone; + + usec_t rtc_time; + bool rtc_local; + + bool ntp_capable; + bool ntp_active; + bool ntp_synced; +} StatusInfo; + +static void print_status_info(const StatusInfo *i) { + const char *old_tz = NULL, *tz, *tz_colon; + bool have_time = false; + char a[LINE_MAX]; + struct tm tm; + time_t sec; + size_t n; + int r; + + assert(i); + + /* Save the old $TZ */ + tz = getenv("TZ"); + if (tz) + old_tz = strdupa(tz); + + /* Set the new $TZ */ + tz_colon = strjoina(":", isempty(i->timezone) ? "UTC" : i->timezone); + if (setenv("TZ", tz_colon, true) < 0) + log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m"); + else + tzset(); + + if (i->time != 0) { + sec = (time_t) (i->time / USEC_PER_SEC); + have_time = true; + } else if (IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) { + sec = time(NULL); + have_time = true; + } else + log_warning("Could not get time from timedated and not operating locally, ignoring."); + + if (have_time) { + n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)); + printf(" Local time: %s\n", n > 0 ? a : "n/a"); + + n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)); + printf(" Universal time: %s\n", n > 0 ? a : "n/a"); + } else { + printf(" Local time: %s\n", "n/a"); + printf(" Universal time: %s\n", "n/a"); + } + + if (i->rtc_time > 0) { + time_t rtc_sec; + + rtc_sec = (time_t) (i->rtc_time / USEC_PER_SEC); + n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm)); + printf(" RTC time: %s\n", n > 0 ? a : "n/a"); + } else + printf(" RTC time: %s\n", "n/a"); + + if (have_time) + n = strftime(a, sizeof a, "%Z, %z", localtime_r(&sec, &tm)); + + /* Restore the $TZ */ + if (old_tz) + r = setenv("TZ", old_tz, true); + else + r = unsetenv("TZ"); + if (r < 0) + log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m"); + else + tzset(); + + printf(" Time zone: %s (%s)\n" + "System clock synchronized: %s\n" + " NTP service: %s\n" + " RTC in local TZ: %s\n", + strna(i->timezone), have_time && n > 0 ? a : "n/a", + yes_no(i->ntp_synced), + i->ntp_capable ? (i->ntp_active ? "active" : "inactive") : "n/a", + yes_no(i->rtc_local)); + + if (i->rtc_local) + printf("\n%s" + "Warning: The system is configured to read the RTC time in the local time zone.\n" + " This mode cannot be fully supported. It will create various problems\n" + " with time zone changes and daylight saving time adjustments. The RTC\n" + " time is never updated, it relies on external facilities to maintain it.\n" + " If at all possible, use RTC in UTC by calling\n" + " 'timedatectl set-local-rtc 0'.%s\n", ansi_highlight(), ansi_normal()); +} + +static int show_status(int argc, char **argv, void *userdata) { + StatusInfo info = {}; + static const struct bus_properties_map map[] = { + { "Timezone", "s", NULL, offsetof(StatusInfo, timezone) }, + { "LocalRTC", "b", NULL, offsetof(StatusInfo, rtc_local) }, + { "NTP", "b", NULL, offsetof(StatusInfo, ntp_active) }, + { "CanNTP", "b", NULL, offsetof(StatusInfo, ntp_capable) }, + { "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced) }, + { "TimeUSec", "t", NULL, offsetof(StatusInfo, time) }, + { "RTCTimeUSec", "t", NULL, offsetof(StatusInfo, rtc_time) }, + {} + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + r = bus_map_all_properties(bus, + "org.freedesktop.timedate1", + "/org/freedesktop/timedate1", + map, + BUS_MAP_BOOLEAN_AS_BOOL, + &error, + &m, + &info); + if (r < 0) + return log_error_errno(r, "Failed to query server: %s", bus_error_message(&error, r)); + + print_status_info(&info); + + return r; +} + +static int show_properties(int argc, char **argv, void *userdata) { + sd_bus *bus = userdata; + int r; + + assert(bus); + + r = bus_print_all_properties(bus, + "org.freedesktop.timedate1", + "/org/freedesktop/timedate1", + NULL, + arg_property, + arg_value, + arg_all, + NULL); + if (r < 0) + return bus_log_parse_error(r); + + return 0; +} + +static int set_time(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + bool relative = false, interactive = arg_ask_password; + sd_bus *bus = userdata; + usec_t t; + int r; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = parse_timestamp(argv[1], &t); + if (r < 0) + return log_error_errno(r, "Failed to parse time specification '%s': %m", argv[1]); + + r = sd_bus_call_method(bus, + "org.freedesktop.timedate1", + "/org/freedesktop/timedate1", + "org.freedesktop.timedate1", + "SetTime", + &error, + NULL, + "xbb", (int64_t) t, relative, interactive); + if (r < 0) + return log_error_errno(r, "Failed to set time: %s", bus_error_message(&error, r)); + + return 0; +} + +static int set_timezone(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call_method(bus, + "org.freedesktop.timedate1", + "/org/freedesktop/timedate1", + "org.freedesktop.timedate1", + "SetTimezone", + &error, + NULL, + "sb", argv[1], arg_ask_password); + if (r < 0) + return log_error_errno(r, "Failed to set time zone: %s", bus_error_message(&error, r)); + + return 0; +} + +static int set_local_rtc(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int r, b; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + b = parse_boolean(argv[1]); + if (b < 0) + return log_error_errno(b, "Failed to parse local RTC setting '%s': %m", argv[1]); + + r = sd_bus_call_method(bus, + "org.freedesktop.timedate1", + "/org/freedesktop/timedate1", + "org.freedesktop.timedate1", + "SetLocalRTC", + &error, + NULL, + "bbb", b, arg_adjust_system_clock, arg_ask_password); + if (r < 0) + return log_error_errno(r, "Failed to set local RTC: %s", bus_error_message(&error, r)); + + return 0; +} + +static int set_ntp(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int b, r; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + b = parse_boolean(argv[1]); + if (b < 0) + return log_error_errno(b, "Failed to parse NTP setting '%s': %m", argv[1]); + + r = sd_bus_call_method(bus, + "org.freedesktop.timedate1", + "/org/freedesktop/timedate1", + "org.freedesktop.timedate1", + "SetNTP", + &error, + NULL, + "bb", b, arg_ask_password); + if (r < 0) + return log_error_errno(r, "Failed to set ntp: %s", bus_error_message(&error, r)); + + return 0; +} + +static int list_timezones(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int r; + char** zones; + + r = sd_bus_call_method(bus, + "org.freedesktop.timedate1", + "/org/freedesktop/timedate1", + "org.freedesktop.timedate1", + "ListTimezones", + &error, + &reply, + NULL); + if (r < 0) + return log_error_errno(r, "Failed to request list of time zones: %s", + bus_error_message(&error, r)); + + r = sd_bus_message_read_strv(reply, &zones); + if (r < 0) + return bus_log_parse_error(r); + + (void) pager_open(arg_pager_flags); + strv_print(zones); + + return 0; +} + +typedef struct NTPStatusInfo { + const char *server_name; + char *server_address; + usec_t poll_interval, poll_max, poll_min; + usec_t root_distance_max; + + uint32_t leap, version, mode, stratum; + int32_t precision; + usec_t root_delay, root_dispersion; + union { + char str[5]; + uint32_t val; + } reference; + usec_t origin, recv, trans, dest; + + bool spike; + uint64_t packet_count; + usec_t jitter; + + int64_t freq; +} NTPStatusInfo; + +static void ntp_status_info_clear(NTPStatusInfo *p) { + p->server_address = mfree(p->server_address); +} + +static const char * const ntp_leap_table[4] = { + [0] = "normal", + [1] = "last minute of the day has 61 seconds", + [2] = "last minute of the day has 59 seconds", + [3] = "not synchronized", +}; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(ntp_leap, uint32_t); +#pragma GCC diagnostic pop + +static void print_ntp_status_info(NTPStatusInfo *i) { + char ts[FORMAT_TIMESPAN_MAX], tmin[FORMAT_TIMESPAN_MAX], tmax[FORMAT_TIMESPAN_MAX]; + usec_t delay, t14, t23, offset, root_distance; + bool offset_sign; + + assert(i); + + /* + * "Timestamp Name ID When Generated + * ------------------------------------------------------------ + * Originate Timestamp T1 time request sent by client + * Receive Timestamp T2 time request received by server + * Transmit Timestamp T3 time reply sent by server + * Destination Timestamp T4 time reply received by client + * + * The round-trip delay, d, and system clock offset, t, are defined as: + * d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2" + */ + + printf(" Server: %s (%s)\n", + i->server_address, i->server_name); + printf("Poll interval: %s (min: %s; max %s)\n", + format_timespan(ts, sizeof(ts), i->poll_interval, 0), + format_timespan(tmin, sizeof(tmin), i->poll_min, 0), + format_timespan(tmax, sizeof(tmax), i->poll_max, 0)); + + if (i->packet_count == 0) { + printf(" Packet count: 0\n"); + return; + } + + if (i->dest < i->origin || i->trans < i->recv || i->dest - i->origin < i->trans - i->recv) { + log_error("Invalid NTP response"); + return; + } + + delay = (i->dest - i->origin) - (i->trans - i->recv); + + t14 = i->origin + i->dest; + t23 = i->recv + i->trans; + offset_sign = t14 < t23; + offset = (offset_sign ? t23 - t14 : t14 - t23) / 2; + + root_distance = i->root_delay / 2 + i->root_dispersion; + + printf(" Leap: %s\n" + " Version: %" PRIu32 "\n" + " Stratum: %" PRIu32 "\n", + ntp_leap_to_string(i->leap), + i->version, + i->stratum); + if (i->stratum <= 1) + printf(" Reference: %s\n", i->reference.str); + else + printf(" Reference: %" PRIX32 "\n", be32toh(i->reference.val)); + printf(" Precision: %s (%" PRIi32 ")\n", + format_timespan(ts, sizeof(ts), DIV_ROUND_UP((nsec_t) (exp2(i->precision) * NSEC_PER_SEC), NSEC_PER_USEC), 0), + i->precision); + printf("Root distance: %s (max: %s)\n", + format_timespan(ts, sizeof(ts), root_distance, 0), + format_timespan(tmax, sizeof(tmax), i->root_distance_max, 0)); + printf(" Offset: %s%s\n", + offset_sign ? "+" : "-", + format_timespan(ts, sizeof(ts), offset, 0)); + printf(" Delay: %s\n", + format_timespan(ts, sizeof(ts), delay, 0)); + printf(" Jitter: %s\n", + format_timespan(ts, sizeof(ts), i->jitter, 0)); + printf(" Packet count: %" PRIu64 "\n", i->packet_count); + + if (!i->spike) + printf(" Frequency: %+.3fppm\n", + (double) i->freq / 0x10000); +} + +static int map_server_address(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + char **p = (char **) userdata; + const void *d; + int family, r; + size_t sz; + + assert(p); + + r = sd_bus_message_enter_container(m, 'r', "iay"); + if (r < 0) + return r; + + r = sd_bus_message_read(m, "i", &family); + if (r < 0) + return r; + + r = sd_bus_message_read_array(m, 'y', &d, &sz); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + if (sz == 0 && family == AF_UNSPEC) { + *p = mfree(*p); + return 0; + } + + if (!IN_SET(family, AF_INET, AF_INET6)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown address family %i", family); + + if (sz != FAMILY_ADDRESS_SIZE(family)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid address size"); + + r = in_addr_to_string(family, d, p); + if (r < 0) + return r; + + return 0; +} + +static int map_ntp_message(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { + NTPStatusInfo *p = userdata; + const void *d; + size_t sz; + int32_t b; + int r; + + assert(p); + + r = sd_bus_message_enter_container(m, 'r', "uuuuittayttttbtt"); + if (r < 0) + return r; + + r = sd_bus_message_read(m, "uuuuitt", + &p->leap, &p->version, &p->mode, &p->stratum, &p->precision, + &p->root_delay, &p->root_dispersion); + if (r < 0) + return r; + + r = sd_bus_message_read_array(m, 'y', &d, &sz); + if (r < 0) + return r; + + r = sd_bus_message_read(m, "ttttbtt", + &p->origin, &p->recv, &p->trans, &p->dest, + &b, &p->packet_count, &p->jitter); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + if (sz != 4) + return -EINVAL; + + memcpy(p->reference.str, d, sz); + + p->spike = b; + + return 0; +} + +static int show_timesync_status_once(sd_bus *bus) { + static const struct bus_properties_map map_timesync[] = { + { "ServerName", "s", NULL, offsetof(NTPStatusInfo, server_name) }, + { "ServerAddress", "(iay)", map_server_address, offsetof(NTPStatusInfo, server_address) }, + { "PollIntervalUSec", "t", NULL, offsetof(NTPStatusInfo, poll_interval) }, + { "PollIntervalMinUSec", "t", NULL, offsetof(NTPStatusInfo, poll_min) }, + { "PollIntervalMaxUSec", "t", NULL, offsetof(NTPStatusInfo, poll_max) }, + { "RootDistanceMaxUSec", "t", NULL, offsetof(NTPStatusInfo, root_distance_max) }, + { "NTPMessage", "(uuuuittayttttbtt)", map_ntp_message, 0 }, + { "Frequency", "x", NULL, offsetof(NTPStatusInfo, freq) }, + {} + }; + _cleanup_(ntp_status_info_clear) NTPStatusInfo info = {}; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + int r; + + assert(bus); + + r = bus_map_all_properties(bus, + "org.freedesktop.timesync1", + "/org/freedesktop/timesync1", + map_timesync, + BUS_MAP_BOOLEAN_AS_BOOL, + &error, + &m, + &info); + if (r < 0) + return log_error_errno(r, "Failed to query server: %s", bus_error_message(&error, r)); + + if (arg_monitor && !terminal_is_dumb()) + fputs(ANSI_HOME_CLEAR, stdout); + + print_ntp_status_info(&info); + + return 0; +} + +static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + const char *name; + int r; + + assert(m); + + r = sd_bus_message_read(m, "s", &name); + if (r < 0) + return log_error_errno(r, "Failed to read interface name: %m"); + + if (!streq_ptr(name, "org.freedesktop.timesync1.Manager")) + return 0; + + return show_timesync_status_once(sd_bus_message_get_bus(m)); +} + +static int show_timesync_status(int argc, char **argv, void *userdata) { + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + sd_bus *bus = userdata; + int r; + + assert(bus); + + r = show_timesync_status_once(bus); + if (r < 0) + return r; + + if (!arg_monitor) + return 0; + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to get event loop: %m"); + + r = sd_bus_match_signal(bus, + NULL, + "org.freedesktop.timesync1", + "/org/freedesktop/timesync1", + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + on_properties_changed, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request match for PropertiesChanged signal: %m"); + + r = sd_bus_attach_event(bus, event, SD_EVENT_PRIORITY_NORMAL); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + return 0; +} + +static int print_timesync_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) { + char type; + const char *contents; + int r; + + assert(name); + assert(m); + + r = sd_bus_message_peek_type(m, &type, &contents); + if (r < 0) + return r; + + switch (type) { + + case SD_BUS_TYPE_STRUCT: + if (streq(name, "NTPMessage")) { + _cleanup_(ntp_status_info_clear) NTPStatusInfo i = {}; + char ts[FORMAT_TIMESPAN_MAX], stamp[FORMAT_TIMESTAMP_MAX]; + + r = map_ntp_message(NULL, NULL, m, NULL, &i); + if (r < 0) + return r; + + if (i.packet_count == 0) + return 1; + + if (!value) { + fputs(name, stdout); + fputc('=', stdout); + } + + printf("{ Leap=%u, Version=%u, Mode=%u, Stratum=%u, Precision=%i,", + i.leap, i.version, i.mode, i.stratum, i.precision); + printf(" RootDelay=%s,", + format_timespan(ts, sizeof(ts), i.root_delay, 0)); + printf(" RootDispersion=%s,", + format_timespan(ts, sizeof(ts), i.root_dispersion, 0)); + + if (i.stratum == 1) + printf(" Reference=%s,", i.reference.str); + else + printf(" Reference=%" PRIX32 ",", be32toh(i.reference.val)); + + printf(" OriginateTimestamp=%s,", + format_timestamp(stamp, sizeof(stamp), i.origin)); + printf(" ReceiveTimestamp=%s,", + format_timestamp(stamp, sizeof(stamp), i.recv)); + printf(" TransmitTimestamp=%s,", + format_timestamp(stamp, sizeof(stamp), i.trans)); + printf(" DestinationTimestamp=%s,", + format_timestamp(stamp, sizeof(stamp), i.dest)); + printf(" Ignored=%s PacketCount=%" PRIu64 ",", + yes_no(i.spike), i.packet_count); + printf(" Jitter=%s }\n", + format_timespan(ts, sizeof(ts), i.jitter, 0)); + + return 1; + + } else if (streq(name, "ServerAddress")) { + _cleanup_free_ char *str = NULL; + + r = map_server_address(NULL, NULL, m, NULL, &str); + if (r < 0) + return r; + + if (arg_all || !isempty(str)) + bus_print_property_value(name, expected_value, value, str); + + return 1; + } + break; + } + + return 0; +} + +static int show_timesync(int argc, char **argv, void *userdata) { + sd_bus *bus = userdata; + int r; + + assert(bus); + + r = bus_print_all_properties(bus, + "org.freedesktop.timesync1", + "/org/freedesktop/timesync1", + print_timesync_property, + arg_property, + arg_value, + arg_all, + NULL); + if (r < 0) + return bus_log_parse_error(r); + + return 0; +} + +static int parse_ifindex_bus(sd_bus *bus, const char *str, int *ret) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int32_t i; + int r; + + assert(bus); + assert(str); + assert(ret); + + r = parse_ifindex(str, ret); + if (r >= 0) + return 0; + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "GetLinkByName", + &error, + &reply, + "s", str); + if (r < 0) + return log_error_errno(r, "Failed to get ifindex of interfaces %s: %s", str, bus_error_message(&error, r)); + + r = sd_bus_message_read(reply, "io", &i, NULL); + if (r < 0) + return bus_log_create_error(r); + + *ret = i; + return 0; +} + +static int verb_ntp_servers(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL; + sd_bus *bus = userdata; + int ifindex, r; + + assert(bus); + + r = parse_ifindex_bus(bus, argv[1], &ifindex); + if (r < 0) + return r; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_message_new_method_call( + bus, + &req, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "SetLinkNTP"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(req, "i", ifindex); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(req, argv + 2); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, req, 0, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to set NTP servers: %s", bus_error_message(&error, r)); + + return 0; +} + +static int verb_revert(int argc, char **argv, void *userdata) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus *bus = userdata; + int ifindex, r; + + assert(bus); + + r = parse_ifindex_bus(bus, argv[1], &ifindex); + if (r < 0) + return r; + + polkit_agent_open_if_enabled(arg_transport, arg_ask_password); + + r = sd_bus_call_method( + bus, + "org.freedesktop.network1", + "/org/freedesktop/network1", + "org.freedesktop.network1.Manager", + "RevertLinkNTP", + &error, + NULL, + "i", ifindex); + if (r < 0) + return log_error_errno(r, "Failed to revert interface configuration: %s", bus_error_message(&error, r)); + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("timedatectl", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] COMMAND ...\n" + "\n%sQuery or change system time and date settings.%s\n" + "\nCommands:\n" + " status Show current time settings\n" + " show Show properties of systemd-timedated\n" + " set-time TIME Set system time\n" + " set-timezone ZONE Set system time zone\n" + " list-timezones Show known time zones\n" + " set-local-rtc BOOL Control whether RTC is in local time\n" + " set-ntp BOOL Enable or disable network time synchronization\n" + "\nsystemd-timesyncd Commands:\n" + " timesync-status Show status of systemd-timesyncd\n" + " show-timesync Show properties of systemd-timesyncd\n" + "\nOptions:\n" + " -h --help Show this help message\n" + " --version Show package version\n" + " --no-pager Do not pipe output into a pager\n" + " --no-ask-password Do not prompt for password\n" + " -H --host=[USER@]HOST Operate on remote host\n" + " -M --machine=CONTAINER Operate on local container\n" + " --adjust-system-clock Adjust system clock when changing local RTC mode\n" + " --monitor Monitor status of systemd-timesyncd\n" + " -p --property=NAME Show only properties by this name\n" + " -a --all Show all properties, including empty ones\n" + " --value When showing properties, only print the value\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , ansi_highlight() + , ansi_normal() + , link + ); + + return 0; +} + +static int verb_help(int argc, char **argv, void *userdata) { + return help(); +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_NO_PAGER, + ARG_ADJUST_SYSTEM_CLOCK, + ARG_NO_ASK_PASSWORD, + ARG_MONITOR, + ARG_VALUE, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "host", required_argument, NULL, 'H' }, + { "machine", required_argument, NULL, 'M' }, + { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "adjust-system-clock", no_argument, NULL, ARG_ADJUST_SYSTEM_CLOCK }, + { "monitor", no_argument, NULL, ARG_MONITOR }, + { "property", required_argument, NULL, 'p' }, + { "all", no_argument, NULL, 'a' }, + { "value", no_argument, NULL, ARG_VALUE }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hH:M:p:a", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case 'H': + arg_transport = BUS_TRANSPORT_REMOTE; + arg_host = optarg; + break; + + case 'M': + arg_transport = BUS_TRANSPORT_MACHINE; + arg_host = optarg; + break; + + case ARG_NO_ASK_PASSWORD: + arg_ask_password = false; + break; + + case ARG_ADJUST_SYSTEM_CLOCK: + arg_adjust_system_clock = true; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case ARG_MONITOR: + arg_monitor = true; + break; + + case 'p': { + r = strv_extend(&arg_property, optarg); + if (r < 0) + return log_oom(); + + /* If the user asked for a particular + * property, show it to him, even if it is + * empty. */ + arg_all = true; + break; + } + + case 'a': + arg_all = true; + break; + + case ARG_VALUE: + arg_value = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; +} + +static int timedatectl_main(sd_bus *bus, int argc, char *argv[]) { + static const Verb verbs[] = { + { "status", VERB_ANY, 1, VERB_DEFAULT, show_status }, + { "show", VERB_ANY, 1, 0, show_properties }, + { "set-time", 2, 2, 0, set_time }, + { "set-timezone", 2, 2, 0, set_timezone }, + { "list-timezones", VERB_ANY, 1, 0, list_timezones }, + { "set-local-rtc", 2, 2, 0, set_local_rtc }, + { "set-ntp", 2, 2, 0, set_ntp }, + { "timesync-status", VERB_ANY, 1, 0, show_timesync_status }, + { "show-timesync", VERB_ANY, 1, 0, show_timesync }, + { "ntp-servers", 3, VERB_ANY, 0, verb_ntp_servers }, + { "revert", 2, 2, 0, verb_revert }, + { "help", VERB_ANY, VERB_ANY, 0, verb_help }, /* Not documented, but supported since it is created. */ + {} + }; + + return dispatch_verb(argc, argv, verbs, bus); +} + +static int run(int argc, char *argv[]) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + setlocale(LC_ALL, ""); + log_show_color(true); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = bus_connect_transport(arg_transport, arg_host, false, &bus); + if (r < 0) + return log_error_errno(r, "Failed to create bus connection: %m"); + + return timedatectl_main(bus, argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c new file mode 100644 index 00000000..5e2fb50d --- /dev/null +++ b/src/timedate/timedated.c @@ -0,0 +1,1132 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-event.h" +#include "sd-messages.h" + +#include "alloc-util.h" +#include "bus-common-errors.h" +#include "bus-error.h" +#include "bus-polkit.h" +#include "clock-util.h" +#include "conf-files.h" +#include "def.h" +#include "fd-util.h" +#include "fileio-label.h" +#include "fileio.h" +#include "fs-util.h" +#include "hashmap.h" +#include "list.h" +#include "main-func.h" +#include "memory-util.h" +#include "missing_capability.h" +#include "path-util.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "string-util.h" +#include "strv.h" +#include "unit-def.h" +#include "unit-name.h" +#include "user-util.h" + +#define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n" +#define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n" + +#define UNIT_LIST_DIRS (const char* const*) CONF_PATHS_STRV("systemd/ntp-units.d") + +typedef struct UnitStatusInfo { + char *name; + char *load_state; + char *unit_file_state; + char *active_state; + char *path; + + LIST_FIELDS(struct UnitStatusInfo, units); +} UnitStatusInfo; + +typedef struct Context { + char *zone; + bool local_rtc; + Hashmap *polkit_registry; + sd_bus_message *cache; + + sd_bus_slot *slot_job_removed; + + LIST_HEAD(UnitStatusInfo, units); +} Context; + +#define log_unit_full(unit, level, error, ...) \ + ({ \ + const UnitStatusInfo *_u = (unit); \ + log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, \ + "UNIT=", _u->name, NULL, NULL, ##__VA_ARGS__); \ + }) + +#define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__) +#define log_unit_info(unit, ...) log_unit_full(unit, LOG_INFO, 0, ##__VA_ARGS__) +#define log_unit_notice(unit, ...) log_unit_full(unit, LOG_NOTICE, 0, ##__VA_ARGS__) +#define log_unit_warning(unit, ...) log_unit_full(unit, LOG_WARNING, 0, ##__VA_ARGS__) +#define log_unit_error(unit, ...) log_unit_full(unit, LOG_ERR, 0, ##__VA_ARGS__) + +#define log_unit_debug_errno(unit, error, ...) log_unit_full(unit, LOG_DEBUG, error, ##__VA_ARGS__) +#define log_unit_info_errno(unit, error, ...) log_unit_full(unit, LOG_INFO, error, ##__VA_ARGS__) +#define log_unit_notice_errno(unit, error, ...) log_unit_full(unit, LOG_NOTICE, error, ##__VA_ARGS__) +#define log_unit_warning_errno(unit, error, ...) log_unit_full(unit, LOG_WARNING, error, ##__VA_ARGS__) +#define log_unit_error_errno(unit, error, ...) log_unit_full(unit, LOG_ERR, error, ##__VA_ARGS__) + +static void unit_status_info_clear(UnitStatusInfo *p) { + assert(p); + + p->load_state = mfree(p->load_state); + p->unit_file_state = mfree(p->unit_file_state); + p->active_state = mfree(p->active_state); +} + +static void unit_status_info_free(UnitStatusInfo *p) { + assert(p); + + unit_status_info_clear(p); + free(p->name); + free(p->path); + free(p); +} + +static void context_clear(Context *c) { + UnitStatusInfo *p; + + assert(c); + + free(c->zone); + bus_verify_polkit_async_registry_free(c->polkit_registry); + sd_bus_message_unref(c->cache); + + sd_bus_slot_unref(c->slot_job_removed); + + while ((p = c->units)) { + LIST_REMOVE(units, c->units, p); + unit_status_info_free(p); + } +} + +static int context_add_ntp_service(Context *c, const char *s, const char *source) { + UnitStatusInfo *u; + + if (!unit_name_is_valid(s, UNIT_NAME_PLAIN)) + return -EINVAL; + + /* Do not add this if it is already listed */ + LIST_FOREACH(units, u, c->units) + if (streq(u->name, s)) + return 0; + + u = new0(UnitStatusInfo, 1); + if (!u) + return -ENOMEM; + + u->name = strdup(s); + if (!u->name) { + free(u); + return -ENOMEM; + } + + LIST_APPEND(units, c->units, u); + log_unit_debug(u, "added from %s.", source); + + return 0; +} + +static int context_parse_ntp_services_from_environment(Context *c) { + const char *env, *p; + int r; + + assert(c); + + env = getenv("SYSTEMD_TIMEDATED_NTP_SERVICES"); + if (!env) + return 0; + + log_debug("Using list of ntp services from environment variable $SYSTEMD_TIMEDATED_NTP_SERVICES=%s.", env); + + for (p = env;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, ":", 0); + if (r == 0) + break; + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_error("Invalid syntax, ignoring: %s", env); + break; + } + + r = context_add_ntp_service(c, word, "$SYSTEMD_TIMEDATED_NTP_SERVICES"); + if (r < 0) + log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word); + } + + return 1; +} + +static int context_parse_ntp_services_from_disk(Context *c) { + _cleanup_strv_free_ char **files = NULL; + char **f; + int r; + + r = conf_files_list_strv(&files, ".list", NULL, CONF_FILES_FILTER_MASKED, UNIT_LIST_DIRS); + if (r < 0) + return log_error_errno(r, "Failed to enumerate .list files: %m"); + + STRV_FOREACH(f, files) { + _cleanup_fclose_ FILE *file = NULL; + + log_debug("Reading file '%s'", *f); + + r = fopen_unlocked(*f, "re", &file); + if (r < 0) { + log_error_errno(r, "Failed to open %s, ignoring: %m", *f); + continue; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + const char *word; + + r = read_line(file, LINE_MAX, &line); + if (r < 0) { + log_error_errno(r, "Failed to read %s, ignoring: %m", *f); + continue; + } + if (r == 0) + break; + + word = strstrip(line); + if (isempty(word) || startswith("#", word)) + continue; + + r = context_add_ntp_service(c, word, *f); + if (r < 0) + log_warning_errno(r, "Failed to add NTP service \"%s\", ignoring: %m", word); + } + } + + return 1; +} + +static int context_parse_ntp_services(Context *c) { + int r; + + r = context_parse_ntp_services_from_environment(c); + if (r != 0) + return r; + + return context_parse_ntp_services_from_disk(c); +} + +static int context_ntp_service_is_active(Context *c) { + UnitStatusInfo *info; + int count = 0; + + assert(c); + + /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */ + + LIST_FOREACH(units, info, c->units) + count += !STRPTR_IN_SET(info->active_state, "inactive", "failed"); + + return count; +} + +static int context_ntp_service_exists(Context *c) { + UnitStatusInfo *info; + int count = 0; + + assert(c); + + /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */ + + LIST_FOREACH(units, info, c->units) + count += streq_ptr(info->load_state, "loaded"); + + return count; +} + +static int context_read_data(Context *c) { + _cleanup_free_ char *t = NULL; + int r; + + assert(c); + + r = get_timezone(&t); + if (r == -EINVAL) + log_warning_errno(r, "/etc/localtime should be a symbolic link to a time zone data file in /usr/share/zoneinfo/."); + else if (r < 0) + log_warning_errno(r, "Failed to get target of /etc/localtime: %m"); + + free_and_replace(c->zone, t); + + c->local_rtc = clock_is_localtime(NULL) > 0; + + return 0; +} + +static int context_write_data_timezone(Context *c) { + _cleanup_free_ char *p = NULL; + const char *source; + + assert(c); + + /* No timezone is very similar to UTC. Hence in either of these cases link the UTC file in. Except if + * it isn't installed, in which case we remove the symlink altogether. Since glibc defaults to an + * internal version of UTC in that case behaviour is mostly equivalent. We still prefer creating the + * symlink though, since things are more self explanatory then. */ + + if (isempty(c->zone) || streq(c->zone, "UTC")) { + + if (access("/usr/share/zoneinfo/UTC", F_OK) < 0) { + + if (unlink("/etc/localtime") < 0 && errno != ENOENT) + return -errno; + + return 0; + } + + source = "../usr/share/zoneinfo/UTC"; + } else { + p = path_join("../usr/share/zoneinfo", c->zone); + if (!p) + return -ENOMEM; + + source = p; + } + + return symlink_atomic(source, "/etc/localtime"); +} + +static int context_write_data_local_rtc(Context *c) { + _cleanup_free_ char *s = NULL, *w = NULL; + int r; + + assert(c); + + r = read_full_file("/etc/adjtime", &s, NULL); + if (r < 0) { + if (r != -ENOENT) + return r; + + if (!c->local_rtc) + return 0; + + w = strdup(NULL_ADJTIME_LOCAL); + if (!w) + return -ENOMEM; + } else { + char *p; + const char *e = "\n"; /* default if there is less than 3 lines */ + const char *prepend = ""; + size_t a, b; + + p = strchrnul(s, '\n'); + if (*p == '\0') + /* only one line, no \n terminator */ + prepend = "\n0\n"; + else if (p[1] == '\0') { + /* only one line, with \n terminator */ + ++p; + prepend = "0\n"; + } else { + p = strchr(p+1, '\n'); + if (!p) { + /* only two lines, no \n terminator */ + prepend = "\n"; + p = s + strlen(s); + } else { + char *end; + /* third line might have a \n terminator or not */ + p++; + end = strchr(p, '\n'); + /* if we actually have a fourth line, use that as suffix "e", otherwise the default \n */ + if (end) + e = end; + } + } + + a = p - s; + b = strlen(e); + + w = new(char, a + (c->local_rtc ? 5 : 3) + strlen(prepend) + b + 1); + if (!w) + return -ENOMEM; + + *(char*) mempcpy(stpcpy(stpcpy(mempcpy(w, s, a), prepend), c->local_rtc ? "LOCAL" : "UTC"), e, b) = 0; + + if (streq(w, NULL_ADJTIME_UTC)) { + if (unlink("/etc/adjtime") < 0) + if (errno != ENOENT) + return -errno; + + return 0; + } + } + + mac_selinux_init(); + return write_string_file_atomic_label("/etc/adjtime", w); +} + +static int context_update_ntp_status(Context *c, sd_bus *bus, sd_bus_message *m) { + static const struct bus_properties_map map[] = { + { "LoadState", "s", NULL, offsetof(UnitStatusInfo, load_state) }, + { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) }, + { "UnitFileState", "s", NULL, offsetof(UnitStatusInfo, unit_file_state) }, + {} + }; + UnitStatusInfo *u; + int r; + + assert(c); + assert(bus); + + /* Suppress calling context_update_ntp_status() multiple times within single DBus transaction. */ + if (m) { + if (m == c->cache) + return 0; + + sd_bus_message_unref(c->cache); + c->cache = sd_bus_message_ref(m); + } + + LIST_FOREACH(units, u, c->units) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + + unit_status_info_clear(u); + + path = unit_dbus_path_from_name(u->name); + if (!path) + return -ENOMEM; + + r = bus_map_all_properties( + bus, + "org.freedesktop.systemd1", + path, + map, + BUS_MAP_STRDUP, + &error, + NULL, + u); + if (r < 0) + return log_unit_error_errno(u, r, "Failed to get properties: %s", bus_error_message(&error, r)); + } + + return 0; +} + +static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) { + Context *c = userdata; + UnitStatusInfo *u; + const char *path; + unsigned n = 0; + int r; + + assert(c); + assert(m); + + r = sd_bus_message_read(m, "uoss", NULL, &path, NULL, NULL); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + + LIST_FOREACH(units, u, c->units) + if (streq_ptr(path, u->path)) + u->path = mfree(u->path); + else + n += !!u->path; + + if (n == 0) { + c->slot_job_removed = sd_bus_slot_unref(c->slot_job_removed); + + (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), + "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "NTP", + NULL); + } + + return 0; +} + +static int unit_start_or_stop(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool start) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *path; + int r; + + assert(u); + assert(bus); + assert(error); + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + start ? "StartUnit" : "StopUnit", + error, + &reply, + "ss", + u->name, + "replace"); + log_unit_full(u, r < 0 ? LOG_WARNING : LOG_DEBUG, r, + "%s unit: %m", start ? "Starting" : "Stopping"); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "o", &path); + if (r < 0) + return bus_log_parse_error(r); + + r = free_and_strdup(&u->path, path); + if (r < 0) + return log_oom(); + + return 0; +} + +static int unit_enable_or_disable(UnitStatusInfo *u, sd_bus *bus, sd_bus_error *error, bool enable) { + int r; + + assert(u); + assert(bus); + assert(error); + + /* Call context_update_ntp_status() to update UnitStatusInfo before calling this. */ + + if (streq(u->unit_file_state, "enabled") == enable) { + log_unit_debug(u, "already %sd.", enable_disable(enable)); + return 0; + } + + log_unit_info(u, "%s unit.", enable ? "Enabling" : "Disabling"); + + if (enable) + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "EnableUnitFiles", + error, + NULL, + "asbb", 1, + u->name, + false, true); + else + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "DisableUnitFiles", + error, + NULL, + "asb", 1, + u->name, + false); + if (r < 0) + return r; + + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "Reload", + error, + NULL, + NULL); + if (r < 0) + return r; + + return 0; +} + +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_time, "t", now(CLOCK_REALTIME)); +static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_ntp_sync, "b", ntp_synced()); + +static int property_get_rtc_time( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + struct tm tm = {}; + usec_t t = 0; + int r; + + r = clock_get_hwclock(&tm); + if (r == -EBUSY) + log_warning("/dev/rtc is busy. Is somebody keeping it open continuously? That's not a good idea... Returning a bogus RTC timestamp."); + else if (r == -ENOENT) + log_debug("/dev/rtc not found."); + else if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to read RTC: %m"); + else + t = (usec_t) timegm(&tm) * USEC_PER_SEC; + + return sd_bus_message_append(reply, "t", t); +} + +static int property_get_can_ntp( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Context *c = userdata; + int r; + + assert(c); + assert(bus); + assert(property); + assert(reply); + assert(error); + + if (c->slot_job_removed) + /* When the previous request is not finished, then assume NTP is enabled. */ + return sd_bus_message_append(reply, "b", true); + + r = context_update_ntp_status(c, bus, reply); + if (r < 0) + return r; + + return sd_bus_message_append(reply, "b", context_ntp_service_exists(c) > 0); +} + +static int property_get_ntp( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Context *c = userdata; + int r; + + assert(c); + assert(bus); + assert(property); + assert(reply); + assert(error); + + if (c->slot_job_removed) + /* When the previous request is not finished, then assume NTP is active. */ + return sd_bus_message_append(reply, "b", true); + + r = context_update_ntp_status(c, bus, reply); + if (r < 0) + return r; + + return sd_bus_message_append(reply, "b", context_ntp_service_is_active(c) > 0); +} + +static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *error) { + Context *c = userdata; + int interactive, r; + const char *z; + + assert(m); + assert(c); + + r = sd_bus_message_read(m, "sb", &z, &interactive); + if (r < 0) + return r; + + if (!timezone_is_valid(z, LOG_DEBUG)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid or not installed time zone '%s'", z); + + if (streq_ptr(z, c->zone)) + return sd_bus_reply_method_return(m, NULL); + + r = bus_verify_polkit_async( + m, + CAP_SYS_TIME, + "org.freedesktop.timedate1.set-timezone", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ + + r = free_and_strdup(&c->zone, z); + if (r < 0) + return r; + + /* 1. Write new configuration file */ + r = context_write_data_timezone(c); + if (r < 0) { + log_error_errno(r, "Failed to set time zone: %m"); + return sd_bus_error_set_errnof(error, r, "Failed to set time zone: %m"); + } + + /* 2. Make glibc notice the new timezone */ + tzset(); + + /* 3. Tell the kernel our timezone */ + r = clock_set_timezone(NULL); + if (r < 0) + log_debug_errno(r, "Failed to tell kernel about timezone, ignoring: %m"); + + if (c->local_rtc) { + struct timespec ts; + struct tm tm; + + /* 4. Sync RTC from system clock, with the new delta */ + assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); + assert_se(localtime_r(&ts.tv_sec, &tm)); + + r = clock_set_hwclock(&tm); + if (r < 0) + log_debug_errno(r, "Failed to sync time to hardware clock, ignoring: %m"); + } + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_TIMEZONE_CHANGE_STR, + "TIMEZONE=%s", c->zone, + "TIMEZONE_SHORTNAME=%s", tzname[daylight], + "DAYLIGHT=%i", daylight, + LOG_MESSAGE("Changed time zone to '%s' (%s).", c->zone, tzname[daylight])); + + (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), + "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "Timezone", + NULL); + + return sd_bus_reply_method_return(m, NULL); +} + +static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error *error) { + int lrtc, fix_system, interactive; + Context *c = userdata; + struct timespec ts; + int r; + + assert(m); + assert(c); + + r = sd_bus_message_read(m, "bbb", &lrtc, &fix_system, &interactive); + if (r < 0) + return r; + + if (lrtc == c->local_rtc) + return sd_bus_reply_method_return(m, NULL); + + r = bus_verify_polkit_async( + m, + CAP_SYS_TIME, + "org.freedesktop.timedate1.set-local-rtc", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; + + c->local_rtc = lrtc; + + /* 1. Write new configuration file */ + r = context_write_data_local_rtc(c); + if (r < 0) { + log_error_errno(r, "Failed to set RTC to %s: %m", lrtc ? "local" : "UTC"); + return sd_bus_error_set_errnof(error, r, "Failed to set RTC to %s: %m", lrtc ? "local" : "UTC"); + } + + /* 2. Tell the kernel our timezone */ + r = clock_set_timezone(NULL); + if (r < 0) + log_debug_errno(r, "Failed to tell kernel about timezone, ignoring: %m"); + + /* 3. Synchronize clocks */ + assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0); + + if (fix_system) { + struct tm tm; + + /* Sync system clock from RTC; first, initialize the timezone fields of struct tm. */ + if (c->local_rtc) + localtime_r(&ts.tv_sec, &tm); + else + gmtime_r(&ts.tv_sec, &tm); + + /* Override the main fields of struct tm, but not the timezone fields */ + r = clock_get_hwclock(&tm); + if (r < 0) + log_debug_errno(r, "Failed to get hardware clock, ignoring: %m"); + else { + /* And set the system clock with this */ + if (c->local_rtc) + ts.tv_sec = mktime(&tm); + else + ts.tv_sec = timegm(&tm); + + if (clock_settime(CLOCK_REALTIME, &ts) < 0) + log_debug_errno(errno, "Failed to update system clock, ignoring: %m"); + } + + } else { + struct tm tm; + + /* Sync RTC from system clock */ + if (c->local_rtc) + localtime_r(&ts.tv_sec, &tm); + else + gmtime_r(&ts.tv_sec, &tm); + + r = clock_set_hwclock(&tm); + if (r < 0) + log_debug_errno(r, "Failed to sync time to hardware clock, ignoring: %m"); + } + + log_info("RTC configured to %s time.", c->local_rtc ? "local" : "UTC"); + + (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), + "/org/freedesktop/timedate1", "org.freedesktop.timedate1", "LocalRTC", + NULL); + + return sd_bus_reply_method_return(m, NULL); +} + +static int method_set_time(sd_bus_message *m, void *userdata, sd_bus_error *error) { + sd_bus *bus = sd_bus_message_get_bus(m); + int relative, interactive, r; + Context *c = userdata; + int64_t utc; + struct timespec ts; + usec_t start; + struct tm tm; + + assert(m); + assert(c); + + if (c->slot_job_removed) + return sd_bus_error_set(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Previous request is not finished, refusing."); + + r = context_update_ntp_status(c, bus, m); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to update context: %m"); + + if (context_ntp_service_is_active(c) > 0) + return sd_bus_error_set(error, BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, "Automatic time synchronization is enabled"); + + /* this only gets used if dbus does not provide a timestamp */ + start = now(CLOCK_MONOTONIC); + + r = sd_bus_message_read(m, "xbb", &utc, &relative, &interactive); + if (r < 0) + return r; + + if (!relative && utc <= 0) + return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid absolute time"); + + if (relative && utc == 0) + return sd_bus_reply_method_return(m, NULL); + + if (relative) { + usec_t n, x; + + n = now(CLOCK_REALTIME); + x = n + utc; + + if ((utc > 0 && x < n) || + (utc < 0 && x > n)) + return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Time value overflow"); + + timespec_store(&ts, x); + } else + timespec_store(&ts, (usec_t) utc); + + r = bus_verify_polkit_async( + m, + CAP_SYS_TIME, + "org.freedesktop.timedate1.set-time", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; + + /* adjust ts for time spent in program */ + r = sd_bus_message_get_monotonic_usec(m, &start); + /* when sd_bus_message_get_monotonic_usec() returns -ENODATA it does not modify &start */ + if (r < 0 && r != -ENODATA) + return r; + + timespec_store(&ts, timespec_load(&ts) + (now(CLOCK_MONOTONIC) - start)); + + /* Set system clock */ + if (clock_settime(CLOCK_REALTIME, &ts) < 0) { + log_error_errno(errno, "Failed to set local time: %m"); + return sd_bus_error_set_errnof(error, errno, "Failed to set local time: %m"); + } + + /* Sync down to RTC */ + if (c->local_rtc) + localtime_r(&ts.tv_sec, &tm); + else + gmtime_r(&ts.tv_sec, &tm); + + r = clock_set_hwclock(&tm); + if (r < 0) + log_debug_errno(r, "Failed to update hardware clock, ignoring: %m"); + + log_struct(LOG_INFO, + "MESSAGE_ID=" SD_MESSAGE_TIME_CHANGE_STR, + "REALTIME="USEC_FMT, timespec_load(&ts), + LOG_MESSAGE("Changed local time to %s", ctime(&ts.tv_sec))); + + return sd_bus_reply_method_return(m, NULL); +} + +static int method_set_ntp(sd_bus_message *m, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; + sd_bus *bus = sd_bus_message_get_bus(m); + Context *c = userdata; + UnitStatusInfo *u; + const UnitStatusInfo *selected = NULL; + int enable, interactive, q, r; + + assert(m); + assert(bus); + assert(c); + + r = sd_bus_message_read(m, "bb", &enable, &interactive); + if (r < 0) + return r; + + r = context_update_ntp_status(c, bus, m); + if (r < 0) + return r; + + if (context_ntp_service_exists(c) <= 0) + return sd_bus_error_set(error, BUS_ERROR_NO_NTP_SUPPORT, "NTP not supported"); + + r = bus_verify_polkit_async( + m, + CAP_SYS_TIME, + "org.freedesktop.timedate1.set-ntp", + NULL, + interactive, + UID_INVALID, + &c->polkit_registry, + error); + if (r < 0) + return r; + if (r == 0) + return 1; + + /* This method may be called frequently. Forget the previous job if it has not completed yet. */ + LIST_FOREACH(units, u, c->units) + u->path = mfree(u->path); + + if (!c->slot_job_removed) { + r = sd_bus_match_signal_async( + bus, + &slot, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "JobRemoved", + match_job_removed, NULL, c); + if (r < 0) + return r; + } + + if (enable) + LIST_FOREACH(units, u, c->units) { + bool enable_this_one = !selected; + + if (!streq(u->load_state, "loaded")) + continue; + + r = unit_enable_or_disable(u, bus, error, enable_this_one); + if (r < 0) + /* If enablement failed, don't start this unit. */ + enable_this_one = false; + + r = unit_start_or_stop(u, bus, error, enable_this_one); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to %s %sd NTP unit, ignoring: %m", + enable_this_one ? "start" : "stop", + enable_disable(enable_this_one)); + if (enable_this_one) + selected = u; + } + else + LIST_FOREACH(units, u, c->units) { + if (!streq(u->load_state, "loaded")) + continue; + + q = unit_enable_or_disable(u, bus, error, false); + if (q < 0) + r = q; + + q = unit_start_or_stop(u, bus, error, false); + if (q < 0) + r = q; + } + + if (r < 0) + return r; + if (enable && !selected) + return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "No NTP service found to enable."); + + if (slot) + c->slot_job_removed = TAKE_PTR(slot); + + if (selected) + log_info("Set NTP to enabled (%s).", selected->name); + else + log_info("Set NTP to disabled."); + + return sd_bus_reply_method_return(m, NULL); +} + +static int method_list_timezones(sd_bus_message *m, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_strv_free_ char **zones = NULL; + int r; + + assert(m); + + r = get_timezones(&zones); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to read list of time zones: %m"); + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_append_strv(reply, zones); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} + +static const sd_bus_vtable timedate_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Timezone", "s", NULL, offsetof(Context, zone), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("LocalRTC", "b", bus_property_get_bool, offsetof(Context, local_rtc), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("CanNTP", "b", property_get_can_ntp, 0, 0), + SD_BUS_PROPERTY("NTP", "b", property_get_ntp, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("NTPSynchronized", "b", property_get_ntp_sync, 0, 0), + SD_BUS_PROPERTY("TimeUSec", "t", property_get_time, 0, 0), + SD_BUS_PROPERTY("RTCTimeUSec", "t", property_get_rtc_time, 0, 0), + SD_BUS_METHOD("SetTime", "xbb", NULL, method_set_time, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetTimezone", "sb", NULL, method_set_timezone, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLocalRTC", "bbb", NULL, method_set_local_rtc, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetNTP", "bb", NULL, method_set_ntp, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListTimezones", NULL, "as", method_list_timezones, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_VTABLE_END, +}; + +static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + assert(c); + assert(event); + assert(_bus); + + r = sd_bus_default_system(&bus); + if (r < 0) + return log_error_errno(r, "Failed to get system bus connection: %m"); + + r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c); + if (r < 0) + return log_error_errno(r, "Failed to register object: %m"); + + r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.timedate1", 0, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + r = sd_bus_attach_event(bus, event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + *_bus = TAKE_PTR(bus); + + return 0; +} + +static int run(int argc, char *argv[]) { + _cleanup_(context_clear) Context context = {}; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + int r; + + log_setup_service(); + + umask(0022); + + if (argc != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + (void) sd_event_set_watchdog(event, true); + + r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to install SIGINT handler: %m"); + + r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to install SIGTERM handler: %m"); + + r = connect_bus(&context, event, &bus); + if (r < 0) + return r; + + (void) sd_bus_negotiate_timestamp(bus, true); + + r = context_read_data(&context); + if (r < 0) + return log_error_errno(r, "Failed to read time zone data: %m"); + + r = context_parse_ntp_services(&context); + if (r < 0) + return r; + + r = bus_event_loop_with_idle(event, bus, "org.freedesktop.timedate1", DEFAULT_EXIT_USEC, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/timesync/80-systemd-timesync.list b/src/timesync/80-systemd-timesync.list new file mode 100644 index 00000000..d5959ade --- /dev/null +++ b/src/timesync/80-systemd-timesync.list @@ -0,0 +1 @@ +systemd-timesyncd.service diff --git a/src/timesync/meson.build b/src/timesync/meson.build new file mode 100644 index 00000000..e5c118c8 --- /dev/null +++ b/src/timesync/meson.build @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +systemd_timesyncd_sources = files(''' + timesyncd.c + timesyncd-bus.c + timesyncd-bus.h + timesyncd-conf.c + timesyncd-conf.h + timesyncd-manager.c + timesyncd-manager.h + timesyncd-ntp-message.h + timesyncd-server.c + timesyncd-server.h +'''.split()) + +timesyncd_gperf_c = custom_target( + 'timesyncd-gperf.c', + input : 'timesyncd-gperf.gperf', + output : 'timesyncd-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + +systemd_timesyncd_sources += [timesyncd_gperf_c] + +if conf.get('ENABLE_TIMESYNCD') == 1 + timesyncd_conf = configure_file( + input : 'timesyncd.conf.in', + output : 'timesyncd.conf', + configuration : substs) + install_data(timesyncd_conf, + install_dir : pkgsysconfdir) + install_data('org.freedesktop.timesync1.conf', + install_dir : dbuspolicydir) + install_data('org.freedesktop.timesync1.service', + install_dir : dbussystemservicedir) + install_data('80-systemd-timesync.list', + install_dir : ntpservicelistdir) +endif + +############################################################ + +tests += [ + [['src/timesync/test-timesync.c', + 'src/timesync/timesyncd-manager.c', + 'src/timesync/timesyncd-manager.h', + 'src/timesync/timesyncd-conf.c', + 'src/timesync/timesyncd-conf.h', + 'src/timesync/timesyncd-server.c', + 'src/timesync/timesyncd-server.h', + timesyncd_gperf_c], + [libshared], + [libm], + 'ENABLE_TIMESYNCD'], +] diff --git a/src/timesync/org.freedesktop.timesync1.conf b/src/timesync/org.freedesktop.timesync1.conf new file mode 100644 index 00000000..eccdbec7 --- /dev/null +++ b/src/timesync/org.freedesktop.timesync1.conf @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/timesync/org.freedesktop.timesync1.service b/src/timesync/org.freedesktop.timesync1.service new file mode 100644 index 00000000..84b4b4f9 --- /dev/null +++ b/src/timesync/org.freedesktop.timesync1.service @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[D-BUS Service] +Name=org.freedesktop.timesync1 +Exec=/bin/false +User=root +SystemdService=dbus-org.freedesktop.timesync1.service diff --git a/src/timesync/test-timesync.c b/src/timesync/test-timesync.c new file mode 100644 index 00000000..bd03a1dd --- /dev/null +++ b/src/timesync/test-timesync.c @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +/* Some unit tests for the helper functions in timesyncd. */ + +#include "log.h" +#include "macro.h" +#include "timesyncd-conf.h" +#include "tests.h" + +static void test_manager_parse_string(void) { + /* Make sure that NTP_SERVERS is configured to something + * that we can actually parse successfully. */ + + _cleanup_(manager_freep) Manager *m = NULL; + + assert_se(manager_new(&m) == 0); + + assert_se(!m->have_fallbacks); + assert_se(manager_parse_server_string(m, SERVER_FALLBACK, NTP_SERVERS) == 0); + assert_se(m->have_fallbacks); + assert_se(manager_parse_fallback_string(m, NTP_SERVERS) == 0); + + assert_se(manager_parse_server_string(m, SERVER_SYSTEM, "time1.foobar.com time2.foobar.com axrfav.,avf..ra 12345..123") == 0); + assert_se(manager_parse_server_string(m, SERVER_FALLBACK, "time1.foobar.com time2.foobar.com axrfav.,avf..ra 12345..123") == 0); + assert_se(manager_parse_server_string(m, SERVER_LINK, "time1.foobar.com time2.foobar.com axrfav.,avf..ra 12345..123") == 0); +} + +int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_manager_parse_string(); + + return 0; +} diff --git a/src/timesync/timesyncd-bus.c b/src/timesync/timesyncd-bus.c new file mode 100644 index 00000000..5a5896f0 --- /dev/null +++ b/src/timesync/timesyncd-bus.c @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-internal.h" +#include "bus-protocol.h" +#include "bus-util.h" +#include "in-addr-util.h" +#include "log.h" +#include "macro.h" +#include "time-util.h" +#include "timesyncd-bus.h" + +static int property_get_servers( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ServerName *p, **s = userdata; + int r; + + assert(s); + assert(bus); + assert(reply); + + r = sd_bus_message_open_container(reply, 'a', "s"); + if (r < 0) + return r; + + LIST_FOREACH(names, p, *s) { + r = sd_bus_message_append(reply, "s", p->string); + if (r < 0) + return r; + } + + return sd_bus_message_close_container(reply); +} + +static int property_get_current_server_name( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ServerName **s = userdata; + + assert(s); + assert(bus); + assert(reply); + + return sd_bus_message_append(reply, "s", *s ? (*s)->string : NULL); +} + +static int property_get_current_server_address( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ServerAddress *a; + int r; + + assert(bus); + assert(reply); + assert(userdata); + + a = *(ServerAddress **) userdata; + + if (!a) + return sd_bus_message_append(reply, "(iay)", AF_UNSPEC, 0); + + assert(IN_SET(a->sockaddr.sa.sa_family, AF_INET, AF_INET6)); + + r = sd_bus_message_open_container(reply, 'r', "iay"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "i", a->sockaddr.sa.sa_family); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', + a->sockaddr.sa.sa_family == AF_INET ? (void*) &a->sockaddr.in.sin_addr : (void*) &a->sockaddr.in6.sin6_addr, + FAMILY_ADDRESS_SIZE(a->sockaddr.sa.sa_family)); + if (r < 0) + return r; + + return sd_bus_message_close_container(reply); +} + +static usec_t ntp_ts_short_to_usec(const struct ntp_ts_short *ts) { + return be16toh(ts->sec) * USEC_PER_SEC + (be16toh(ts->frac) * USEC_PER_SEC) / (usec_t) 0x10000ULL; +} + +static usec_t ntp_ts_to_usec(const struct ntp_ts *ts) { + return (be32toh(ts->sec) - OFFSET_1900_1970) * USEC_PER_SEC + (be32toh(ts->frac) * USEC_PER_SEC) / (usec_t) 0x100000000ULL; +} + +static int property_get_ntp_message( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + Manager *m = userdata; + int r; + + assert(m); + assert(reply); + + r = sd_bus_message_open_container(reply, 'r', "uuuuittayttttbtt"); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "uuuuitt", + NTP_FIELD_LEAP(m->ntpmsg.field), + NTP_FIELD_VERSION(m->ntpmsg.field), + NTP_FIELD_MODE(m->ntpmsg.field), + m->ntpmsg.stratum, + m->ntpmsg.precision, + ntp_ts_short_to_usec(&m->ntpmsg.root_delay), + ntp_ts_short_to_usec(&m->ntpmsg.root_dispersion)); + if (r < 0) + return r; + + r = sd_bus_message_append_array(reply, 'y', m->ntpmsg.refid, 4); + if (r < 0) + return r; + + r = sd_bus_message_append(reply, "ttttbtt", + timespec_load(&m->origin_time), + ntp_ts_to_usec(&m->ntpmsg.recv_time), + ntp_ts_to_usec(&m->ntpmsg.trans_time), + timespec_load(&m->dest_time), + m->spike, + m->packet_count, + (usec_t) (m->samples_jitter * USEC_PER_SEC)); + if (r < 0) + return r; + + return sd_bus_message_close_container(reply); +} + +static const sd_bus_vtable manager_vtable[] = { + SD_BUS_VTABLE_START(0), + + SD_BUS_PROPERTY("LinkNTPServers", "as", property_get_servers, offsetof(Manager, link_servers), 0), + SD_BUS_PROPERTY("SystemNTPServers", "as", property_get_servers, offsetof(Manager, system_servers), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("FallbackNTPServers", "as", property_get_servers, offsetof(Manager, fallback_servers), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("ServerName", "s", property_get_current_server_name, offsetof(Manager, current_server_name), 0), + SD_BUS_PROPERTY("ServerAddress", "(iay)", property_get_current_server_address, offsetof(Manager, current_server_address), 0), + SD_BUS_PROPERTY("RootDistanceMaxUSec", "t", bus_property_get_usec, offsetof(Manager, max_root_distance_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PollIntervalMinUSec", "t", bus_property_get_usec, offsetof(Manager, poll_interval_min_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PollIntervalMaxUSec", "t", bus_property_get_usec, offsetof(Manager, poll_interval_max_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PollIntervalUSec", "t", bus_property_get_usec, offsetof(Manager, poll_interval_usec), 0), + SD_BUS_PROPERTY("NTPMessage", "(uuuuittayttttbtt)", property_get_ntp_message, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Frequency", "x", NULL, offsetof(Manager, drift_freq), 0), + + SD_BUS_VTABLE_END +}; + +int manager_connect_bus(Manager *m) { + int r; + + assert(m); + + if (m->bus) + return 0; + + r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-timesync"); + if (r < 0) + return log_error_errno(r, "Failed to connect to bus: %m"); + + r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/timesync1", "org.freedesktop.timesync1.Manager", manager_vtable, m); + if (r < 0) + return log_error_errno(r, "Failed to add manager object vtable: %m"); + + r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.timesync1", 0, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to request name: %m"); + + r = sd_bus_attach_event(m->bus, m->event, 0); + if (r < 0) + return log_error_errno(r, "Failed to attach bus to event loop: %m"); + + return 0; +} diff --git a/src/timesync/timesyncd-bus.h b/src/timesync/timesyncd-bus.h new file mode 100644 index 00000000..6670ffbc --- /dev/null +++ b/src/timesync/timesyncd-bus.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "timesyncd-manager.h" + +int manager_connect_bus(Manager *m); diff --git a/src/timesync/timesyncd-conf.c b/src/timesync/timesyncd-conf.c new file mode 100644 index 00000000..a26c2dad --- /dev/null +++ b/src/timesync/timesyncd-conf.c @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "def.h" +#include "dns-domain.h" +#include "extract-word.h" +#include "string-util.h" +#include "timesyncd-conf.h" +#include "timesyncd-manager.h" +#include "timesyncd-server.h" + +int manager_parse_server_string(Manager *m, ServerType type, const char *string) { + ServerName *first; + int r; + + assert(m); + assert(string); + + first = type == SERVER_FALLBACK ? m->fallback_servers : m->system_servers; + + if (type == SERVER_FALLBACK) + m->have_fallbacks = true; + + for (;;) { + _cleanup_free_ char *word = NULL; + bool found = false; + ServerName *n; + + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return log_error_errno(r, "Failed to parse timesyncd server syntax \"%s\": %m", string); + if (r == 0) + break; + + r = dns_name_is_valid_or_address(word); + if (r < 0) + return log_error_errno(r, "Failed to check validity of NTP server name or address '%s': %m", word); + if (r == 0) { + log_error("Invalid NTP server name or address, ignoring: %s", word); + continue; + } + + /* Filter out duplicates */ + LIST_FOREACH(names, n, first) + if (streq_ptr(n->string, word)) { + found = true; + break; + } + + if (found) + continue; + + r = server_name_new(m, NULL, type, word); + if (r < 0) + return r; + } + + return 0; +} + +int manager_parse_fallback_string(Manager *m, const char *string) { + if (m->have_fallbacks) + return 0; + + return manager_parse_server_string(m, SERVER_FALLBACK, string); +} + +int config_parse_servers( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Manager *m = userdata; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) + manager_flush_server_names(m, ltype); + else { + r = manager_parse_server_string(m, ltype, rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse NTP server string '%s'. Ignoring.", rvalue); + return 0; + } + } + + return 0; +} + +int manager_parse_config_file(Manager *m) { + int r; + + assert(m); + + r = config_parse_many_nulstr(PKGSYSCONFDIR "/timesyncd.conf", + CONF_PATHS_NULSTR("systemd/timesyncd.conf.d"), + "Time\0", + config_item_perf_lookup, timesyncd_gperf_lookup, + CONFIG_PARSE_WARN, m); + if (r < 0) + return r; + + if (m->poll_interval_min_usec < 16 * USEC_PER_SEC) { + log_warning("Invalid PollIntervalMinSec=. Using default value."); + m->poll_interval_min_usec = NTP_POLL_INTERVAL_MIN_USEC; + } + + if (m->poll_interval_max_usec < m->poll_interval_min_usec) { + log_warning("PollIntervalMaxSec= is smaller than PollIntervalMinSec=. Using default value."); + m->poll_interval_max_usec = MAX(NTP_POLL_INTERVAL_MAX_USEC, m->poll_interval_min_usec * 32); + } + + return r; +} diff --git a/src/timesync/timesyncd-conf.h b/src/timesync/timesyncd-conf.h new file mode 100644 index 00000000..bbe27cf2 --- /dev/null +++ b/src/timesync/timesyncd-conf.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "conf-parser.h" +#include "timesyncd-manager.h" + +const struct ConfigPerfItem* timesyncd_gperf_lookup(const char *key, GPERF_LEN_TYPE length); + +int manager_parse_server_string(Manager *m, ServerType type, const char *string); + +CONFIG_PARSER_PROTOTYPE(config_parse_servers); + +int manager_parse_config_file(Manager *m); +int manager_parse_fallback_string(Manager *m, const char *string); diff --git a/src/timesync/timesyncd-gperf.gperf b/src/timesync/timesyncd-gperf.gperf new file mode 100644 index 00000000..b5020276 --- /dev/null +++ b/src/timesync/timesyncd-gperf.gperf @@ -0,0 +1,25 @@ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif +#include +#include "conf-parser.h" +#include "timesyncd-conf.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name timesyncd_gperf_hash +%define lookup-function-name timesyncd_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +Time.NTP, config_parse_servers, SERVER_SYSTEM, 0 +Time.Servers, config_parse_servers, SERVER_SYSTEM, 0 +Time.FallbackNTP, config_parse_servers, SERVER_FALLBACK, 0 +Time.RootDistanceMaxSec, config_parse_sec, 0, offsetof(Manager, max_root_distance_usec) +Time.PollIntervalMinSec, config_parse_sec, 0, offsetof(Manager, poll_interval_min_usec) +Time.PollIntervalMaxSec, config_parse_sec, 0, offsetof(Manager, poll_interval_max_usec) diff --git a/src/timesync/timesyncd-manager.c b/src/timesync/timesyncd-manager.c new file mode 100644 index 00000000..7b71e98f --- /dev/null +++ b/src/timesync/timesyncd-manager.c @@ -0,0 +1,1122 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-daemon.h" + +#include "alloc-util.h" +#include "dns-domain.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "list.h" +#include "log.h" +#include "network-util.h" +#include "ratelimit.h" +#include "resolve-private.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "timesyncd-conf.h" +#include "timesyncd-manager.h" +#include "util.h" + +#ifndef ADJ_SETOFFSET +#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */ +#endif + +/* expected accuracy of time synchronization; used to adjust the poll interval */ +#define NTP_ACCURACY_SEC 0.2 + +/* + * Maximum delta in seconds which the system clock is gradually adjusted + * (slewed) to approach the network time. Deltas larger that this are set by + * letting the system time jump. The kernel's limit for adjtime is 0.5s. + */ +#define NTP_MAX_ADJUST 0.4 + +/* Default of maximum acceptable root distance in microseconds. */ +#define NTP_MAX_ROOT_DISTANCE (5 * USEC_PER_SEC) + +/* Maximum number of missed replies before selecting another source. */ +#define NTP_MAX_MISSED_REPLIES 2 + +#define RETRY_USEC (30*USEC_PER_SEC) +#define RATELIMIT_INTERVAL_USEC (10*USEC_PER_SEC) +#define RATELIMIT_BURST 10 + +#define TIMEOUT_USEC (10*USEC_PER_SEC) + +static int manager_arm_timer(Manager *m, usec_t next); +static int manager_clock_watch_setup(Manager *m); +static int manager_listen_setup(Manager *m); +static void manager_listen_stop(Manager *m); + +static double ntp_ts_short_to_d(const struct ntp_ts_short *ts) { + return be16toh(ts->sec) + (be16toh(ts->frac) / 65536.0); +} + +static double ntp_ts_to_d(const struct ntp_ts *ts) { + return be32toh(ts->sec) + ((double)be32toh(ts->frac) / UINT_MAX); +} + +static double ts_to_d(const struct timespec *ts) { + return ts->tv_sec + (1.0e-9 * ts->tv_nsec); +} + +static int manager_timeout(sd_event_source *source, usec_t usec, void *userdata) { + _cleanup_free_ char *pretty = NULL; + Manager *m = userdata; + + assert(m); + assert(m->current_server_name); + assert(m->current_server_address); + + server_address_pretty(m->current_server_address, &pretty); + log_info("Timed out waiting for reply from %s (%s).", strna(pretty), m->current_server_name->string); + + return manager_connect(m); +} + +static int manager_send_request(Manager *m) { + _cleanup_free_ char *pretty = NULL; + struct ntp_msg ntpmsg = { + /* + * "The client initializes the NTP message header, sends the request + * to the server, and strips the time of day from the Transmit + * Timestamp field of the reply. For this purpose, all the NTP + * header fields are set to 0, except the Mode, VN, and optional + * Transmit Timestamp fields." + */ + .field = NTP_FIELD(0, 4, NTP_MODE_CLIENT), + }; + ssize_t len; + int r; + + assert(m); + assert(m->current_server_name); + assert(m->current_server_address); + + m->event_timeout = sd_event_source_unref(m->event_timeout); + + r = manager_listen_setup(m); + if (r < 0) + return log_warning_errno(r, "Failed to setup connection socket: %m"); + + /* + * Set transmit timestamp, remember it; the server will send that back + * as the origin timestamp and we have an indication that this is the + * matching answer to our request. + * + * The actual value does not matter, We do not care about the correct + * NTP UINT_MAX fraction; we just pass the plain nanosecond value. + */ + assert_se(clock_gettime(clock_boottime_or_monotonic(), &m->trans_time_mon) >= 0); + assert_se(clock_gettime(CLOCK_REALTIME, &m->trans_time) >= 0); + ntpmsg.trans_time.sec = htobe32(m->trans_time.tv_sec + OFFSET_1900_1970); + ntpmsg.trans_time.frac = htobe32(m->trans_time.tv_nsec); + + server_address_pretty(m->current_server_address, &pretty); + + len = sendto(m->server_socket, &ntpmsg, sizeof(ntpmsg), MSG_DONTWAIT, &m->current_server_address->sockaddr.sa, m->current_server_address->socklen); + if (len == sizeof(ntpmsg)) { + m->pending = true; + log_debug("Sent NTP request to %s (%s).", strna(pretty), m->current_server_name->string); + } else { + log_debug_errno(errno, "Sending NTP request to %s (%s) failed: %m", strna(pretty), m->current_server_name->string); + return manager_connect(m); + } + + /* re-arm timer with increasing timeout, in case the packets never arrive back */ + if (m->retry_interval > 0) { + if (m->retry_interval < m->poll_interval_max_usec) + m->retry_interval *= 2; + } else + m->retry_interval = m->poll_interval_min_usec; + + r = manager_arm_timer(m, m->retry_interval); + if (r < 0) + return log_error_errno(r, "Failed to rearm timer: %m"); + + m->missed_replies++; + if (m->missed_replies > NTP_MAX_MISSED_REPLIES) { + r = sd_event_add_time( + m->event, + &m->event_timeout, + clock_boottime_or_monotonic(), + now(clock_boottime_or_monotonic()) + TIMEOUT_USEC, 0, + manager_timeout, m); + if (r < 0) + return log_error_errno(r, "Failed to arm timeout timer: %m"); + } + + return 0; +} + +static int manager_timer(sd_event_source *source, usec_t usec, void *userdata) { + Manager *m = userdata; + + assert(m); + + return manager_send_request(m); +} + +static int manager_arm_timer(Manager *m, usec_t next) { + int r; + + assert(m); + + if (next == 0) { + m->event_timer = sd_event_source_unref(m->event_timer); + return 0; + } + + if (m->event_timer) { + r = sd_event_source_set_time(m->event_timer, now(clock_boottime_or_monotonic()) + next); + if (r < 0) + return r; + + return sd_event_source_set_enabled(m->event_timer, SD_EVENT_ONESHOT); + } + + return sd_event_add_time( + m->event, + &m->event_timer, + clock_boottime_or_monotonic(), + now(clock_boottime_or_monotonic()) + next, 0, + manager_timer, m); +} + +static int manager_clock_watch(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + + assert(m); + + /* rearm timer */ + manager_clock_watch_setup(m); + + /* skip our own jumps */ + if (m->jumped) { + m->jumped = false; + return 0; + } + + /* resync */ + log_debug("System time changed. Resyncing."); + m->poll_resync = true; + + return manager_send_request(m); +} + +/* wake up when the system time changes underneath us */ +static int manager_clock_watch_setup(Manager *m) { + int r; + + assert(m); + + m->event_clock_watch = sd_event_source_unref(m->event_clock_watch); + safe_close(m->clock_watch_fd); + + m->clock_watch_fd = time_change_fd(); + if (m->clock_watch_fd < 0) + return log_error_errno(m->clock_watch_fd, "Failed to create timerfd: %m"); + + r = sd_event_add_io(m->event, &m->event_clock_watch, m->clock_watch_fd, EPOLLIN, manager_clock_watch, m); + if (r < 0) + return log_error_errno(r, "Failed to create clock watch event source: %m"); + + return 0; +} + +static int manager_adjust_clock(Manager *m, double offset, int leap_sec) { + struct timex tmx = {}; + int r; + + assert(m); + + /* + * For small deltas, tell the kernel to gradually adjust the system + * clock to the NTP time, larger deltas are just directly set. + */ + if (fabs(offset) < NTP_MAX_ADJUST) { + tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR; + tmx.status = STA_PLL; + tmx.offset = offset * NSEC_PER_SEC; + tmx.constant = log2i(m->poll_interval_usec / USEC_PER_SEC) - 4; + tmx.maxerror = 0; + tmx.esterror = 0; + log_debug(" adjust (slew): %+.3f sec", offset); + } else { + tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_SETOFFSET | ADJ_MAXERROR | ADJ_ESTERROR; + + /* ADJ_NANO uses nanoseconds in the microseconds field */ + tmx.time.tv_sec = (long)offset; + tmx.time.tv_usec = (offset - tmx.time.tv_sec) * NSEC_PER_SEC; + tmx.maxerror = 0; + tmx.esterror = 0; + + /* the kernel expects -0.3s as {-1, 7000.000.000} */ + if (tmx.time.tv_usec < 0) { + tmx.time.tv_sec -= 1; + tmx.time.tv_usec += NSEC_PER_SEC; + } + + m->jumped = true; + log_debug(" adjust (jump): %+.3f sec", offset); + } + + /* + * An unset STA_UNSYNC will enable the kernel's 11-minute mode, + * which syncs the system time periodically to the RTC. + * + * In case the RTC runs in local time, never touch the RTC, + * we have no way to properly handle daylight saving changes and + * mobile devices moving between time zones. + */ + if (m->rtc_local_time) + tmx.status |= STA_UNSYNC; + + switch (leap_sec) { + case 1: + tmx.status |= STA_INS; + break; + case -1: + tmx.status |= STA_DEL; + break; + } + + r = clock_adjtime(CLOCK_REALTIME, &tmx); + if (r < 0) + return -errno; + + /* If touch fails, there isn't much we can do. Maybe it'll work next time. */ + (void) touch("/var/lib/systemd/timesync/clock"); + (void) touch("/run/systemd/timesync/synchronized"); + + m->drift_freq = tmx.freq; + + log_debug(" status : %04i %s\n" + " time now : %"PRI_TIME".%03"PRI_USEC"\n" + " constant : %"PRI_TIMEX"\n" + " offset : %+.3f sec\n" + " freq offset : %+"PRI_TIMEX" (%+"PRI_TIMEX" ppm)\n", + tmx.status, tmx.status & STA_UNSYNC ? "unsync" : "sync", + tmx.time.tv_sec, tmx.time.tv_usec / NSEC_PER_MSEC, + tmx.constant, + (double)tmx.offset / NSEC_PER_SEC, + tmx.freq, tmx.freq / 65536); + + return 0; +} + +static bool manager_sample_spike_detection(Manager *m, double offset, double delay) { + unsigned i, idx_cur, idx_new, idx_min; + double jitter; + double j; + + assert(m); + + m->packet_count++; + + /* ignore initial sample */ + if (m->packet_count == 1) + return false; + + /* store the current data in our samples array */ + idx_cur = m->samples_idx; + idx_new = (idx_cur + 1) % ELEMENTSOF(m->samples); + m->samples_idx = idx_new; + m->samples[idx_new].offset = offset; + m->samples[idx_new].delay = delay; + + /* calculate new jitter value from the RMS differences relative to the lowest delay sample */ + jitter = m->samples_jitter; + for (idx_min = idx_cur, i = 0; i < ELEMENTSOF(m->samples); i++) + if (m->samples[i].delay > 0 && m->samples[i].delay < m->samples[idx_min].delay) + idx_min = i; + + j = 0; + for (i = 0; i < ELEMENTSOF(m->samples); i++) + j += pow(m->samples[i].offset - m->samples[idx_min].offset, 2); + m->samples_jitter = sqrt(j / (ELEMENTSOF(m->samples) - 1)); + + /* ignore samples when resyncing */ + if (m->poll_resync) + return false; + + /* always accept offset if we are farther off than the round-trip delay */ + if (fabs(offset) > delay) + return false; + + /* we need a few samples before looking at them */ + if (m->packet_count < 4) + return false; + + /* do not accept anything worse than the maximum possible error of the best sample */ + if (fabs(offset) > m->samples[idx_min].delay) + return true; + + /* compare the difference between the current offset to the previous offset and jitter */ + return fabs(offset - m->samples[idx_cur].offset) > 3 * jitter; +} + +static void manager_adjust_poll(Manager *m, double offset, bool spike) { + assert(m); + + if (m->poll_resync) { + m->poll_interval_usec = m->poll_interval_min_usec; + m->poll_resync = false; + return; + } + + /* set to minimal poll interval */ + if (!spike && fabs(offset) > NTP_ACCURACY_SEC) { + m->poll_interval_usec = m->poll_interval_min_usec; + return; + } + + /* increase polling interval */ + if (fabs(offset) < NTP_ACCURACY_SEC * 0.25) { + if (m->poll_interval_usec < m->poll_interval_max_usec) + m->poll_interval_usec *= 2; + return; + } + + /* decrease polling interval */ + if (spike || fabs(offset) > NTP_ACCURACY_SEC * 0.75) { + if (m->poll_interval_usec > m->poll_interval_min_usec) + m->poll_interval_usec /= 2; + return; + } +} + +static int manager_receive_response(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + struct ntp_msg ntpmsg; + + struct iovec iov = { + .iov_base = &ntpmsg, + .iov_len = sizeof(ntpmsg), + }; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(struct timeval))]; + } control; + union sockaddr_union server_addr; + struct msghdr msghdr = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + .msg_name = &server_addr, + .msg_namelen = sizeof(server_addr), + }; + struct cmsghdr *cmsg; + struct timespec *recv_time = NULL; + ssize_t len; + double origin, receive, trans, dest; + double delay, offset; + double root_distance; + bool spike; + int leap_sec; + int r; + + assert(source); + assert(m); + + if (revents & (EPOLLHUP|EPOLLERR)) { + log_warning("Server connection returned error."); + return manager_connect(m); + } + + len = recvmsg(fd, &msghdr, MSG_DONTWAIT); + if (len < 0) { + if (errno == EAGAIN) + return 0; + + log_warning("Error receiving message. Disconnecting."); + return manager_connect(m); + } + + /* Too short or too long packet? */ + if (iov.iov_len < sizeof(struct ntp_msg) || (msghdr.msg_flags & MSG_TRUNC)) { + log_warning("Invalid response from server. Disconnecting."); + return manager_connect(m); + } + + if (!m->current_server_name || + !m->current_server_address || + !sockaddr_equal(&server_addr, &m->current_server_address->sockaddr)) { + log_debug("Response from unknown server."); + return 0; + } + + CMSG_FOREACH(cmsg, &msghdr) { + if (cmsg->cmsg_level != SOL_SOCKET) + continue; + + switch (cmsg->cmsg_type) { + case SCM_TIMESTAMPNS: + recv_time = (struct timespec *) CMSG_DATA(cmsg); + break; + } + } + if (!recv_time) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid packet timestamp."); + + if (!m->pending) { + log_debug("Unexpected reply. Ignoring."); + return 0; + } + + m->missed_replies = 0; + + /* check our "time cookie" (we just stored nanoseconds in the fraction field) */ + if (be32toh(ntpmsg.origin_time.sec) != m->trans_time.tv_sec + OFFSET_1900_1970 || + be32toh(ntpmsg.origin_time.frac) != (unsigned long) m->trans_time.tv_nsec) { + log_debug("Invalid reply; not our transmit time. Ignoring."); + return 0; + } + + m->event_timeout = sd_event_source_unref(m->event_timeout); + + if (be32toh(ntpmsg.recv_time.sec) < TIME_EPOCH + OFFSET_1900_1970 || + be32toh(ntpmsg.trans_time.sec) < TIME_EPOCH + OFFSET_1900_1970) { + log_debug("Invalid reply, returned times before epoch. Ignoring."); + return manager_connect(m); + } + + if (NTP_FIELD_LEAP(ntpmsg.field) == NTP_LEAP_NOTINSYNC || + ntpmsg.stratum == 0 || ntpmsg.stratum >= 16) { + log_debug("Server is not synchronized. Disconnecting."); + return manager_connect(m); + } + + if (!IN_SET(NTP_FIELD_VERSION(ntpmsg.field), 3, 4)) { + log_debug("Response NTPv%d. Disconnecting.", NTP_FIELD_VERSION(ntpmsg.field)); + return manager_connect(m); + } + + if (NTP_FIELD_MODE(ntpmsg.field) != NTP_MODE_SERVER) { + log_debug("Unsupported mode %d. Disconnecting.", NTP_FIELD_MODE(ntpmsg.field)); + return manager_connect(m); + } + + root_distance = ntp_ts_short_to_d(&ntpmsg.root_delay) / 2 + ntp_ts_short_to_d(&ntpmsg.root_dispersion); + if (root_distance > (double) m->max_root_distance_usec / (double) USEC_PER_SEC) { + log_info("Server has too large root distance. Disconnecting."); + return manager_connect(m); + } + + /* valid packet */ + m->pending = false; + m->retry_interval = 0; + + /* Stop listening */ + manager_listen_stop(m); + + /* announce leap seconds */ + if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_PLUSSEC) + leap_sec = 1; + else if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_MINUSSEC) + leap_sec = -1; + else + leap_sec = 0; + + /* + * "Timestamp Name ID When Generated + * ------------------------------------------------------------ + * Originate Timestamp T1 time request sent by client + * Receive Timestamp T2 time request received by server + * Transmit Timestamp T3 time reply sent by server + * Destination Timestamp T4 time reply received by client + * + * The round-trip delay, d, and system clock offset, t, are defined as: + * d = (T4 - T1) - (T3 - T2) t = ((T2 - T1) + (T3 - T4)) / 2" + */ + origin = ts_to_d(&m->trans_time) + OFFSET_1900_1970; + receive = ntp_ts_to_d(&ntpmsg.recv_time); + trans = ntp_ts_to_d(&ntpmsg.trans_time); + dest = ts_to_d(recv_time) + OFFSET_1900_1970; + + offset = ((receive - origin) + (trans - dest)) / 2; + delay = (dest - origin) - (trans - receive); + + spike = manager_sample_spike_detection(m, offset, delay); + + manager_adjust_poll(m, offset, spike); + + log_debug("NTP response:\n" + " leap : %u\n" + " version : %u\n" + " mode : %u\n" + " stratum : %u\n" + " precision : %.6f sec (%d)\n" + " root distance: %.6f sec\n" + " reference : %.4s\n" + " origin : %.3f\n" + " receive : %.3f\n" + " transmit : %.3f\n" + " dest : %.3f\n" + " offset : %+.3f sec\n" + " delay : %+.3f sec\n" + " packet count : %"PRIu64"\n" + " jitter : %.3f%s\n" + " poll interval: " USEC_FMT "\n", + NTP_FIELD_LEAP(ntpmsg.field), + NTP_FIELD_VERSION(ntpmsg.field), + NTP_FIELD_MODE(ntpmsg.field), + ntpmsg.stratum, + exp2(ntpmsg.precision), ntpmsg.precision, + root_distance, + ntpmsg.stratum == 1 ? ntpmsg.refid : "n/a", + origin - OFFSET_1900_1970, + receive - OFFSET_1900_1970, + trans - OFFSET_1900_1970, + dest - OFFSET_1900_1970, + offset, delay, + m->packet_count, + m->samples_jitter, spike ? " spike" : "", + m->poll_interval_usec / USEC_PER_SEC); + + if (!spike) { + m->sync = true; + r = manager_adjust_clock(m, offset, leap_sec); + if (r < 0) + log_error_errno(r, "Failed to call clock_adjtime(): %m"); + } + + /* Save NTP response */ + m->ntpmsg = ntpmsg; + m->origin_time = m->trans_time; + m->dest_time = *recv_time; + m->spike = spike; + + log_debug("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+"PRIi64"ppm%s", + m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_freq / 65536, + spike ? " (ignored)" : ""); + + (void) sd_bus_emit_properties_changed(m->bus, "/org/freedesktop/timesync1", "org.freedesktop.timesync1.Manager", "NTPMessage", NULL); + + if (!m->good) { + _cleanup_free_ char *pretty = NULL; + + m->good = true; + + server_address_pretty(m->current_server_address, &pretty); + /* "Initial", as further successful syncs will not be logged. */ + log_info("Initial synchronization to time server %s (%s).", strna(pretty), m->current_server_name->string); + sd_notifyf(false, "STATUS=Initial synchronization to time server %s (%s).", strna(pretty), m->current_server_name->string); + } + + r = manager_arm_timer(m, m->poll_interval_usec); + if (r < 0) + return log_error_errno(r, "Failed to rearm timer: %m"); + + return 0; +} + +static int manager_listen_setup(Manager *m) { + union sockaddr_union addr = {}; + int r; + + assert(m); + + if (m->server_socket >= 0) + return 0; + + assert(!m->event_receive); + assert(m->current_server_address); + + addr.sa.sa_family = m->current_server_address->sockaddr.sa.sa_family; + + m->server_socket = socket(addr.sa.sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (m->server_socket < 0) + return -errno; + + r = bind(m->server_socket, &addr.sa, m->current_server_address->socklen); + if (r < 0) + return -errno; + + r = setsockopt_int(m->server_socket, SOL_SOCKET, SO_TIMESTAMPNS, true); + if (r < 0) + return r; + + (void) setsockopt_int(m->server_socket, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); + + return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m); +} + +static void manager_listen_stop(Manager *m) { + assert(m); + + m->event_receive = sd_event_source_unref(m->event_receive); + m->server_socket = safe_close(m->server_socket); +} + +static int manager_begin(Manager *m) { + _cleanup_free_ char *pretty = NULL; + int r; + + assert(m); + assert_return(m->current_server_name, -EHOSTUNREACH); + assert_return(m->current_server_address, -EHOSTUNREACH); + + m->good = false; + m->missed_replies = NTP_MAX_MISSED_REPLIES; + if (m->poll_interval_usec == 0) + m->poll_interval_usec = m->poll_interval_min_usec; + + server_address_pretty(m->current_server_address, &pretty); + log_debug("Connecting to time server %s (%s).", strna(pretty), m->current_server_name->string); + sd_notifyf(false, "STATUS=Connecting to time server %s (%s).", strna(pretty), m->current_server_name->string); + + r = manager_clock_watch_setup(m); + if (r < 0) + return r; + + return manager_send_request(m); +} + +void manager_set_server_name(Manager *m, ServerName *n) { + assert(m); + + if (m->current_server_name == n) + return; + + m->current_server_name = n; + m->current_server_address = NULL; + + manager_disconnect(m); + + if (n) + log_debug("Selected server %s.", n->string); +} + +void manager_set_server_address(Manager *m, ServerAddress *a) { + assert(m); + + if (m->current_server_address == a) + return; + + m->current_server_address = a; + /* If a is NULL, we are just clearing the address, without + * changing the name. Keep the existing name in that case. */ + if (a) + m->current_server_name = a->name; + + manager_disconnect(m); + + if (a) { + _cleanup_free_ char *pretty = NULL; + server_address_pretty(a, &pretty); + log_debug("Selected address %s of server %s.", strna(pretty), a->name->string); + } +} + +static int manager_resolve_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, Manager *m) { + int r; + + assert(q); + assert(m); + assert(m->current_server_name); + + m->resolve_query = sd_resolve_query_unref(m->resolve_query); + + if (ret != 0) { + log_debug("Failed to resolve %s: %s", m->current_server_name->string, gai_strerror(ret)); + + /* Try next host */ + return manager_connect(m); + } + + for (; ai; ai = ai->ai_next) { + _cleanup_free_ char *pretty = NULL; + ServerAddress *a; + + assert(ai->ai_addr); + assert(ai->ai_addrlen >= offsetof(struct sockaddr, sa_data)); + + if (!IN_SET(ai->ai_addr->sa_family, AF_INET, AF_INET6)) { + log_warning("Unsuitable address protocol for %s", m->current_server_name->string); + continue; + } + + r = server_address_new(m->current_server_name, &a, (const union sockaddr_union*) ai->ai_addr, ai->ai_addrlen); + if (r < 0) + return log_error_errno(r, "Failed to add server address: %m"); + + server_address_pretty(a, &pretty); + log_debug("Resolved address %s for %s.", pretty, m->current_server_name->string); + } + + if (!m->current_server_name->addresses) { + log_error("Failed to find suitable address for host %s.", m->current_server_name->string); + + /* Try next host */ + return manager_connect(m); + } + + manager_set_server_address(m, m->current_server_name->addresses); + + return manager_begin(m); +} + +static int manager_retry_connect(sd_event_source *source, usec_t usec, void *userdata) { + Manager *m = userdata; + + assert(m); + + return manager_connect(m); +} + +int manager_connect(Manager *m) { + int r; + + assert(m); + + manager_disconnect(m); + + m->event_retry = sd_event_source_unref(m->event_retry); + if (!ratelimit_below(&m->ratelimit)) { + log_debug("Delaying attempts to contact servers."); + + r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + RETRY_USEC, 0, manager_retry_connect, m); + if (r < 0) + return log_error_errno(r, "Failed to create retry timer: %m"); + + return 0; + } + + /* If we already are operating on some address, switch to the + * next one. */ + if (m->current_server_address && m->current_server_address->addresses_next) + manager_set_server_address(m, m->current_server_address->addresses_next); + else { + struct addrinfo hints = { + .ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG, + .ai_socktype = SOCK_DGRAM, + }; + + /* Hmm, we are through all addresses, let's look for the next host instead */ + if (m->current_server_name && m->current_server_name->names_next) + manager_set_server_name(m, m->current_server_name->names_next); + else { + ServerName *f; + bool restart = true; + + /* Our current server name list is exhausted, + * let's find the next one to iterate. First + * we try the system list, then the link list. + * After having processed the link list we + * jump back to the system list. However, if + * both lists are empty, we change to the + * fallback list. */ + if (!m->current_server_name || m->current_server_name->type == SERVER_LINK) { + f = m->system_servers; + if (!f) + f = m->link_servers; + } else { + f = m->link_servers; + if (!f) + f = m->system_servers; + else + restart = false; + } + + if (!f) + f = m->fallback_servers; + + if (!f) { + manager_set_server_name(m, NULL); + log_debug("No server found."); + return 0; + } + + if (restart && !m->exhausted_servers && m->poll_interval_usec) { + log_debug("Waiting after exhausting servers."); + r = sd_event_add_time(m->event, &m->event_retry, clock_boottime_or_monotonic(), now(clock_boottime_or_monotonic()) + m->poll_interval_usec, 0, manager_retry_connect, m); + if (r < 0) + return log_error_errno(r, "Failed to create retry timer: %m"); + + m->exhausted_servers = true; + + /* Increase the polling interval */ + if (m->poll_interval_usec < m->poll_interval_max_usec) + m->poll_interval_usec *= 2; + + return 0; + } + + m->exhausted_servers = false; + + manager_set_server_name(m, f); + } + + /* Tell the resolver to reread /etc/resolv.conf, in + * case it changed. */ + res_init(); + + /* Flush out any previously resolved addresses */ + server_name_flush_addresses(m->current_server_name); + + log_debug("Resolving %s...", m->current_server_name->string); + + r = resolve_getaddrinfo(m->resolve, &m->resolve_query, m->current_server_name->string, "123", &hints, manager_resolve_handler, NULL, m); + if (r < 0) + return log_error_errno(r, "Failed to create resolver: %m"); + + return 1; + } + + r = manager_begin(m); + if (r < 0) + return r; + + return 1; +} + +void manager_disconnect(Manager *m) { + assert(m); + + m->resolve_query = sd_resolve_query_unref(m->resolve_query); + + m->event_timer = sd_event_source_unref(m->event_timer); + + manager_listen_stop(m); + + m->event_clock_watch = sd_event_source_unref(m->event_clock_watch); + m->clock_watch_fd = safe_close(m->clock_watch_fd); + + m->event_timeout = sd_event_source_unref(m->event_timeout); + + sd_notifyf(false, "STATUS=Idle."); +} + +void manager_flush_server_names(Manager *m, ServerType t) { + assert(m); + + if (t == SERVER_SYSTEM) + while (m->system_servers) + server_name_free(m->system_servers); + + if (t == SERVER_LINK) + while (m->link_servers) + server_name_free(m->link_servers); + + if (t == SERVER_FALLBACK) + while (m->fallback_servers) + server_name_free(m->fallback_servers); +} + +void manager_free(Manager *m) { + if (!m) + return; + + manager_disconnect(m); + manager_flush_server_names(m, SERVER_SYSTEM); + manager_flush_server_names(m, SERVER_LINK); + manager_flush_server_names(m, SERVER_FALLBACK); + + sd_event_source_unref(m->event_retry); + + sd_event_source_unref(m->network_event_source); + sd_network_monitor_unref(m->network_monitor); + + sd_resolve_unref(m->resolve); + sd_event_unref(m->event); + + sd_bus_flush_close_unref(m->bus); + + free(m); +} + +static int manager_network_read_link_servers(Manager *m) { + _cleanup_strv_free_ char **ntp = NULL; + ServerName *n, *nx; + char **i; + bool changed = false; + int r; + + assert(m); + + r = sd_network_get_ntp(&ntp); + if (r < 0) { + if (r == -ENOMEM) + log_oom(); + else + log_debug_errno(r, "Failed to get link NTP servers: %m"); + goto clear; + } + + LIST_FOREACH(names, n, m->link_servers) + n->marked = true; + + STRV_FOREACH(i, ntp) { + bool found = false; + + r = dns_name_is_valid_or_address(*i); + if (r < 0) { + log_error_errno(r, "Failed to check validity of NTP server name or address '%s': %m", *i); + goto clear; + } else if (r == 0) { + log_error("Invalid NTP server name or address, ignoring: %s", *i); + continue; + } + + LIST_FOREACH(names, n, m->link_servers) + if (streq(n->string, *i)) { + n->marked = false; + found = true; + break; + } + + if (!found) { + r = server_name_new(m, NULL, SERVER_LINK, *i); + if (r < 0) { + log_oom(); + goto clear; + } + + changed = true; + } + } + + LIST_FOREACH_SAFE(names, n, nx, m->link_servers) + if (n->marked) { + server_name_free(n); + changed = true; + } + + return changed; + +clear: + manager_flush_server_names(m, SERVER_LINK); + return r; +} + +static bool manager_is_connected(Manager *m) { + /* Return true when the manager is sending a request, resolving a server name, or + * in a poll interval. */ + return m->server_socket >= 0 || m->resolve_query || m->event_timer; +} + +static int manager_network_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Manager *m = userdata; + bool changed, connected, online; + int r; + + assert(m); + + sd_network_monitor_flush(m->network_monitor); + + /* When manager_network_read_link_servers() failed, we assume that the servers are changed. */ + changed = manager_network_read_link_servers(m); + + /* check if the machine is online */ + online = network_is_online(); + + /* check if the client is currently connected */ + connected = manager_is_connected(m); + + if (connected && !online) { + log_info("No network connectivity, watching for changes."); + manager_disconnect(m); + + } else if ((!connected || changed) && online) { + log_info("Network configuration changed, trying to establish connection."); + + if (m->current_server_address) + r = manager_begin(m); + else + r = manager_connect(m); + if (r < 0) + return r; + } + + return 0; +} + +static int manager_network_monitor_listen(Manager *m) { + int r, fd, events; + + assert(m); + + r = sd_network_monitor_new(&m->network_monitor, NULL); + if (r == -ENOENT) { + log_info("systemd does not appear to be running, not listening for systemd-networkd events."); + return 0; + } + if (r < 0) + return r; + + fd = sd_network_monitor_get_fd(m->network_monitor); + if (fd < 0) + return fd; + + events = sd_network_monitor_get_events(m->network_monitor); + if (events < 0) + return events; + + r = sd_event_add_io(m->event, &m->network_event_source, fd, events, manager_network_event_handler, m); + if (r < 0) + return r; + + return 0; +} + +int manager_new(Manager **ret) { + _cleanup_(manager_freep) Manager *m = NULL; + int r; + + assert(ret); + + m = new0(Manager, 1); + if (!m) + return -ENOMEM; + + m->max_root_distance_usec = NTP_MAX_ROOT_DISTANCE; + m->poll_interval_min_usec = NTP_POLL_INTERVAL_MIN_USEC; + m->poll_interval_max_usec = NTP_POLL_INTERVAL_MAX_USEC; + + m->server_socket = m->clock_watch_fd = -1; + + m->ratelimit = (RateLimit) { RATELIMIT_INTERVAL_USEC, RATELIMIT_BURST }; + + r = sd_event_default(&m->event); + if (r < 0) + return r; + + (void) sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); + (void) sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); + + (void) sd_event_set_watchdog(m->event, true); + + r = sd_resolve_default(&m->resolve); + if (r < 0) + return r; + + r = sd_resolve_attach_event(m->resolve, m->event, 0); + if (r < 0) + return r; + + r = manager_network_monitor_listen(m); + if (r < 0) + return r; + + (void) manager_network_read_link_servers(m); + + *ret = TAKE_PTR(m); + + return 0; +} diff --git a/src/timesync/timesyncd-manager.h b/src/timesync/timesyncd-manager.h new file mode 100644 index 00000000..97c4e2ff --- /dev/null +++ b/src/timesync/timesyncd-manager.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "sd-bus.h" +#include "sd-event.h" +#include "sd-network.h" +#include "sd-resolve.h" + +#include "list.h" +#include "ratelimit.h" +#include "time-util.h" +#include "timesyncd-ntp-message.h" + +typedef struct Manager Manager; + +#include "timesyncd-server.h" + +/* + * "A client MUST NOT under any conditions use a poll interval less + * than 15 seconds." + */ +#define NTP_POLL_INTERVAL_MIN_USEC (32 * USEC_PER_SEC) +#define NTP_POLL_INTERVAL_MAX_USEC (2048 * USEC_PER_SEC) + +struct Manager { + sd_bus *bus; + sd_event *event; + sd_resolve *resolve; + + LIST_HEAD(ServerName, system_servers); + LIST_HEAD(ServerName, link_servers); + LIST_HEAD(ServerName, fallback_servers); + + bool have_fallbacks:1; + + RateLimit ratelimit; + bool exhausted_servers; + + /* network */ + sd_event_source *network_event_source; + sd_network_monitor *network_monitor; + + /* peer */ + sd_resolve_query *resolve_query; + sd_event_source *event_receive; + ServerName *current_server_name; + ServerAddress *current_server_address; + int server_socket; + int missed_replies; + uint64_t packet_count; + sd_event_source *event_timeout; + bool good; + + /* last sent packet */ + struct timespec trans_time_mon; + struct timespec trans_time; + usec_t retry_interval; + bool pending; + + /* poll timer */ + sd_event_source *event_timer; + usec_t poll_interval_usec; + usec_t poll_interval_min_usec; + usec_t poll_interval_max_usec; + bool poll_resync; + + /* history data */ + struct { + double offset; + double delay; + } samples[8]; + unsigned samples_idx; + double samples_jitter; + usec_t max_root_distance_usec; + + /* last change */ + bool jumped; + bool sync; + int64_t drift_freq; + + /* watch for time changes */ + sd_event_source *event_clock_watch; + int clock_watch_fd; + + /* Retry connections */ + sd_event_source *event_retry; + + /* RTC runs in local time, leave it alone */ + bool rtc_local_time; + + /* NTP response */ + struct ntp_msg ntpmsg; + struct timespec origin_time, dest_time; + bool spike; +}; + +int manager_new(Manager **ret); +void manager_free(Manager *m); + +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); + +void manager_set_server_name(Manager *m, ServerName *n); +void manager_set_server_address(Manager *m, ServerAddress *a); +void manager_flush_server_names(Manager *m, ServerType t); + +int manager_connect(Manager *m); +void manager_disconnect(Manager *m); diff --git a/src/timesync/timesyncd-ntp-message.h b/src/timesync/timesyncd-ntp-message.h new file mode 100644 index 00000000..14fba6d2 --- /dev/null +++ b/src/timesync/timesyncd-ntp-message.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sparse-endian.h" + +/* NTP protocol, packet header */ +#define NTP_LEAP_PLUSSEC 1 +#define NTP_LEAP_MINUSSEC 2 +#define NTP_LEAP_NOTINSYNC 3 +#define NTP_MODE_CLIENT 3 +#define NTP_MODE_SERVER 4 +#define NTP_FIELD_LEAP(f) (((f) >> 6) & 3) +#define NTP_FIELD_VERSION(f) (((f) >> 3) & 7) +#define NTP_FIELD_MODE(f) ((f) & 7) +#define NTP_FIELD(l, v, m) (((l) << 6) | ((v) << 3) | (m)) + +/* + * "NTP timestamps are represented as a 64-bit unsigned fixed-point number, + * in seconds relative to 0h on 1 January 1900." + */ +#define OFFSET_1900_1970 UINT64_C(2208988800) + +struct ntp_ts { + be32_t sec; + be32_t frac; +} _packed_; + +struct ntp_ts_short { + be16_t sec; + be16_t frac; +} _packed_; + +struct ntp_msg { + uint8_t field; + uint8_t stratum; + int8_t poll; + int8_t precision; + struct ntp_ts_short root_delay; + struct ntp_ts_short root_dispersion; + char refid[4]; + struct ntp_ts reference_time; + struct ntp_ts origin_time; + struct ntp_ts recv_time; + struct ntp_ts trans_time; +} _packed_; diff --git a/src/timesync/timesyncd-server.c b/src/timesync/timesyncd-server.c new file mode 100644 index 00000000..aadecb6a --- /dev/null +++ b/src/timesync/timesyncd-server.c @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "alloc-util.h" +#include "timesyncd-server.h" + +int server_address_new( + ServerName *n, + ServerAddress **ret, + const union sockaddr_union *sockaddr, + socklen_t socklen) { + + ServerAddress *a, *tail; + + assert(n); + assert(sockaddr); + assert(socklen >= offsetof(struct sockaddr, sa_data)); + assert(socklen <= sizeof(union sockaddr_union)); + + a = new0(ServerAddress, 1); + if (!a) + return -ENOMEM; + + memcpy(&a->sockaddr, sockaddr, socklen); + a->socklen = socklen; + + LIST_FIND_TAIL(addresses, n->addresses, tail); + LIST_INSERT_AFTER(addresses, n->addresses, tail, a); + a->name = n; + + if (ret) + *ret = a; + + return 0; +} + +ServerAddress* server_address_free(ServerAddress *a) { + if (!a) + return NULL; + + if (a->name) { + LIST_REMOVE(addresses, a->name->addresses, a); + + if (a->name->manager && a->name->manager->current_server_address == a) + manager_set_server_address(a->name->manager, NULL); + } + + return mfree(a); +} + +int server_name_new( + Manager *m, + ServerName **ret, + ServerType type, + const char *string) { + + ServerName *n, *tail; + + assert(m); + assert(string); + + n = new0(ServerName, 1); + if (!n) + return -ENOMEM; + + n->type = type; + n->string = strdup(string); + if (!n->string) { + free(n); + return -ENOMEM; + } + + if (type == SERVER_SYSTEM) { + LIST_FIND_TAIL(names, m->system_servers, tail); + LIST_INSERT_AFTER(names, m->system_servers, tail, n); + } else if (type == SERVER_LINK) { + LIST_FIND_TAIL(names, m->link_servers, tail); + LIST_INSERT_AFTER(names, m->link_servers, tail, n); + } else if (type == SERVER_FALLBACK) { + LIST_FIND_TAIL(names, m->fallback_servers, tail); + LIST_INSERT_AFTER(names, m->fallback_servers, tail, n); + } else + assert_not_reached("Unknown server type"); + + n->manager = m; + + if (type != SERVER_FALLBACK && + m->current_server_name && + m->current_server_name->type == SERVER_FALLBACK) + manager_set_server_name(m, NULL); + + log_debug("Added new server %s.", string); + + if (ret) + *ret = n; + + return 0; +} + +ServerName *server_name_free(ServerName *n) { + if (!n) + return NULL; + + server_name_flush_addresses(n); + + if (n->manager) { + if (n->type == SERVER_SYSTEM) + LIST_REMOVE(names, n->manager->system_servers, n); + else if (n->type == SERVER_LINK) + LIST_REMOVE(names, n->manager->link_servers, n); + else if (n->type == SERVER_FALLBACK) + LIST_REMOVE(names, n->manager->fallback_servers, n); + else + assert_not_reached("Unknown server type"); + + if (n->manager->current_server_name == n) + manager_set_server_name(n->manager, NULL); + } + + log_debug("Removed server %s.", n->string); + + free(n->string); + return mfree(n); +} + +void server_name_flush_addresses(ServerName *n) { + assert(n); + + while (n->addresses) + server_address_free(n->addresses); +} diff --git a/src/timesync/timesyncd-server.h b/src/timesync/timesyncd-server.h new file mode 100644 index 00000000..d30bd2a3 --- /dev/null +++ b/src/timesync/timesyncd-server.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "list.h" +#include "socket-util.h" + +typedef struct ServerAddress ServerAddress; +typedef struct ServerName ServerName; + +typedef enum ServerType { + SERVER_SYSTEM, + SERVER_FALLBACK, + SERVER_LINK, +} ServerType; + +#include "timesyncd-manager.h" + +struct ServerAddress { + ServerName *name; + + union sockaddr_union sockaddr; + socklen_t socklen; + + LIST_FIELDS(ServerAddress, addresses); +}; + +struct ServerName { + Manager *manager; + + ServerType type; + char *string; + + bool marked:1; + + LIST_HEAD(ServerAddress, addresses); + LIST_FIELDS(ServerName, names); +}; + +int server_address_new(ServerName *n, ServerAddress **ret, const union sockaddr_union *sockaddr, socklen_t socklen); +ServerAddress* server_address_free(ServerAddress *a); +static inline int server_address_pretty(ServerAddress *a, char **pretty) { + return sockaddr_pretty(&a->sockaddr.sa, a->socklen, true, true, pretty); +} + +int server_name_new(Manager *m, ServerName **ret, ServerType type,const char *string); +ServerName *server_name_free(ServerName *n); +void server_name_flush_addresses(ServerName *n); diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c new file mode 100644 index 00000000..e56e09ca --- /dev/null +++ b/src/timesync/timesyncd.c @@ -0,0 +1,178 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-daemon.h" +#include "sd-event.h" + +#include "capability-util.h" +#include "clock-util.h" +#include "daemon-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "main-func.h" +#include "mkdir.h" +#include "network-util.h" +#include "process-util.h" +#include "signal-util.h" +#include "timesyncd-bus.h" +#include "timesyncd-conf.h" +#include "timesyncd-manager.h" +#include "user-util.h" + +#define STATE_DIR "/var/lib/systemd/timesync" +#define CLOCK_FILE STATE_DIR "/clock" + +static int load_clock_timestamp(uid_t uid, gid_t gid) { + _cleanup_close_ int fd = -1; + usec_t min = TIME_EPOCH * USEC_PER_SEC; + usec_t ct; + int r; + + /* Let's try to make sure that the clock is always + * monotonically increasing, by saving the clock whenever we + * have a new NTP time, or when we shut down, and restoring it + * when we start again. This is particularly helpful on + * systems lacking a battery backed RTC. We also will adjust + * the time to at least the build time of systemd. */ + + fd = open(CLOCK_FILE, O_RDWR|O_CLOEXEC, 0644); + if (fd >= 0) { + struct stat st; + usec_t stamp; + + /* check if the recorded time is later than the compiled-in one */ + r = fstat(fd, &st); + if (r >= 0) { + stamp = timespec_load(&st.st_mtim); + if (stamp > min) + min = stamp; + } + + if (geteuid() == 0) { + /* Try to fix the access mode, so that we can still + touch the file after dropping privileges */ + r = fchmod_and_chown(fd, 0644, uid, gid); + if (r < 0) + log_warning_errno(r, "Failed to chmod or chown %s, ignoring: %m", CLOCK_FILE); + } + + } else { + r = mkdir_safe_label(STATE_DIR, 0755, uid, gid, + MKDIR_FOLLOW_SYMLINK | MKDIR_WARN_MODE); + if (r < 0) { + log_debug_errno(r, "Failed to create state directory, ignoring: %m"); + goto settime; + } + + /* create stamp file with the compiled-in date */ + r = touch_file(CLOCK_FILE, false, min, uid, gid, 0644); + if (r < 0) + log_debug_errno(r, "Failed to create %s, ignoring: %m", CLOCK_FILE); + } + +settime: + ct = now(CLOCK_REALTIME); + if (ct < min) { + struct timespec ts; + char date[FORMAT_TIMESTAMP_MAX]; + + log_info("System clock time unset or jumped backwards, restoring from recorded timestamp: %s", + format_timestamp(date, sizeof(date), min)); + + if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, min)) < 0) + log_error_errno(errno, "Failed to restore system clock, ignoring: %m"); + } + + return 0; +} + +static int run(int argc, char *argv[]) { + _cleanup_(notify_on_cleanup) const char *notify_message = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + const char *user = "systemd-timesync"; + uid_t uid, uid_current; + gid_t gid; + int r; + + log_set_facility(LOG_CRON); + log_setup_service(); + + umask(0022); + + if (argc != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program does not take arguments."); + + uid = uid_current = geteuid(); + gid = getegid(); + + if (uid_current == 0) { + r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0); + if (r < 0) + return log_error_errno(r, "Cannot resolve user name %s: %m", user); + } + + r = load_clock_timestamp(uid, gid); + if (r < 0) + return r; + + /* Drop privileges, but only if we have been started as root. If we are not running as root we assume all + * privileges are already dropped. */ + if (uid_current == 0) { + r = drop_privileges(uid, gid, (1ULL << CAP_SYS_TIME)); + if (r < 0) + return log_error_errno(r, "Failed to drop privileges: %m"); + } + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + + r = manager_new(&m); + if (r < 0) + return log_error_errno(r, "Failed to allocate manager: %m"); + + r = manager_connect_bus(m); + if (r < 0) + return log_error_errno(r, "Could not connect to bus: %m"); + + if (clock_is_localtime(NULL) > 0) { + log_info("The system is configured to read the RTC time in the local time zone. " + "This mode cannot be fully supported. All system time to RTC updates are disabled."); + m->rtc_local_time = true; + } + + r = manager_parse_config_file(m); + if (r < 0) + log_warning_errno(r, "Failed to parse configuration file: %m"); + + r = manager_parse_fallback_string(m, NTP_SERVERS); + if (r < 0) + return log_error_errno(r, "Failed to parse fallback server strings: %m"); + + log_debug("systemd-timesyncd running as pid " PID_FMT, getpid_cached()); + + notify_message = notify_start("READY=1\n" + "STATUS=Daemon is running", + NOTIFY_STOPPING); + + if (network_is_online()) { + r = manager_connect(m); + if (r < 0) + return r; + } + + r = sd_event_loop(m->event); + if (r < 0) + return log_error_errno(r, "Failed to run event loop: %m"); + + /* if we got an authoritative time, store it in the file system */ + if (m->sync) { + r = touch(CLOCK_FILE); + if (r < 0) + log_debug_errno(r, "Failed to touch %s, ignoring: %m", CLOCK_FILE); + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/timesync/timesyncd.conf.in b/src/timesync/timesyncd.conf.in new file mode 100644 index 00000000..f91c034a --- /dev/null +++ b/src/timesync/timesyncd.conf.in @@ -0,0 +1,19 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Entries in this file show the compile time defaults. +# You can change settings by editing this file. +# Defaults can be restored by simply deleting this file. +# +# See timesyncd.conf(5) for details. + +[Time] +#NTP= +#FallbackNTP=@NTP_SERVERS@ +#RootDistanceMaxSec=5 +#PollIntervalMinSec=32 +#PollIntervalMaxSec=2048 diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c new file mode 100644 index 00000000..193ed0bc --- /dev/null +++ b/src/tmpfiles/tmpfiles.c @@ -0,0 +1,3278 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-path.h" + +#include "acl-util.h" +#include "alloc-util.h" +#include "btrfs-util.h" +#include "capability-util.h" +#include "chattr-util.h" +#include "conf-files.h" +#include "copy.h" +#include "def.h" +#include "dirent-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "glob-util.h" +#include "io-util.h" +#include "label.h" +#include "log.h" +#include "macro.h" +#include "main-func.h" +#include "mkdir.h" +#include "mountpoint-util.h" +#include "pager.h" +#include "parse-util.h" +#include "path-lookup.h" +#include "path-util.h" +#include "pretty-print.h" +#include "rlimit-util.h" +#include "rm-rf.h" +#include "selinux-util.h" +#include "set.h" +#include "sort-util.h" +#include "specifier.h" +#include "stat-util.h" +#include "stdio-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "umask-util.h" +#include "user-util.h" + +/* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates + * them in the file system. This is intended to be used to create + * properly owned directories beneath /tmp, /var/tmp, /run, which are + * volatile and hence need to be recreated on bootup. */ + +typedef enum OperationMask { + OPERATION_CREATE = 1 << 0, + OPERATION_REMOVE = 1 << 1, + OPERATION_CLEAN = 1 << 2, +} OperationMask; + +typedef enum ItemType { + /* These ones take file names */ + CREATE_FILE = 'f', + TRUNCATE_FILE = 'F', /* deprecated: use f+ */ + CREATE_DIRECTORY = 'd', + TRUNCATE_DIRECTORY = 'D', + CREATE_SUBVOLUME = 'v', + CREATE_SUBVOLUME_INHERIT_QUOTA = 'q', + CREATE_SUBVOLUME_NEW_QUOTA = 'Q', + CREATE_FIFO = 'p', + CREATE_SYMLINK = 'L', + CREATE_CHAR_DEVICE = 'c', + CREATE_BLOCK_DEVICE = 'b', + COPY_FILES = 'C', + + /* These ones take globs */ + WRITE_FILE = 'w', + EMPTY_DIRECTORY = 'e', + SET_XATTR = 't', + RECURSIVE_SET_XATTR = 'T', + SET_ACL = 'a', + RECURSIVE_SET_ACL = 'A', + SET_ATTRIBUTE = 'h', + RECURSIVE_SET_ATTRIBUTE = 'H', + IGNORE_PATH = 'x', + IGNORE_DIRECTORY_PATH = 'X', + REMOVE_PATH = 'r', + RECURSIVE_REMOVE_PATH = 'R', + RELABEL_PATH = 'z', + RECURSIVE_RELABEL_PATH = 'Z', + ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */ +} ItemType; + +typedef struct Item { + ItemType type; + + char *path; + char *argument; + char **xattrs; +#if HAVE_ACL + acl_t acl_access; + acl_t acl_default; +#endif + uid_t uid; + gid_t gid; + mode_t mode; + usec_t age; + + dev_t major_minor; + unsigned attribute_value; + unsigned attribute_mask; + + bool uid_set:1; + bool gid_set:1; + bool mode_set:1; + bool age_set:1; + bool mask_perms:1; + bool attribute_set:1; + + bool keep_first_level:1; + + bool append_or_force:1; + + bool allow_failure:1; + + OperationMask done; +} Item; + +typedef struct ItemArray { + Item *items; + size_t n_items; + size_t allocated; + + struct ItemArray *parent; + Set *children; +} ItemArray; + +typedef enum DirectoryType { + DIRECTORY_RUNTIME, + DIRECTORY_STATE, + DIRECTORY_CACHE, + DIRECTORY_LOGS, + _DIRECTORY_TYPE_MAX, +} DirectoryType; + +static bool arg_cat_config = false; +static bool arg_user = false; +static OperationMask arg_operation = 0; +static bool arg_boot = false; +static PagerFlags arg_pager_flags = 0; + +static char **arg_include_prefixes = NULL; +static char **arg_exclude_prefixes = NULL; +static char *arg_root = NULL; +static char *arg_replace = NULL; + +#define MAX_DEPTH 256 + +static OrderedHashmap *items = NULL, *globs = NULL; +static Set *unix_sockets = NULL; + +STATIC_DESTRUCTOR_REGISTER(items, ordered_hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(globs, ordered_hashmap_freep); +STATIC_DESTRUCTOR_REGISTER(unix_sockets, set_free_freep); +STATIC_DESTRUCTOR_REGISTER(arg_include_prefixes, freep); +STATIC_DESTRUCTOR_REGISTER(arg_exclude_prefixes, freep); +STATIC_DESTRUCTOR_REGISTER(arg_root, freep); + +static int specifier_machine_id_safe(char specifier, const void *data, const void *userdata, char **ret); +static int specifier_directory(char specifier, const void *data, const void *userdata, char **ret); + +static const Specifier specifier_table[] = { + { 'm', specifier_machine_id_safe, NULL }, + { 'b', specifier_boot_id, NULL }, + { 'H', specifier_host_name, NULL }, + { 'v', specifier_kernel_release, NULL }, + + { 'g', specifier_group_name, NULL }, + { 'G', specifier_group_id, NULL }, + { 'U', specifier_user_id, NULL }, + { 'u', specifier_user_name, NULL }, + { 'h', specifier_user_home, NULL }, + + { 't', specifier_directory, UINT_TO_PTR(DIRECTORY_RUNTIME) }, + { 'S', specifier_directory, UINT_TO_PTR(DIRECTORY_STATE) }, + { 'C', specifier_directory, UINT_TO_PTR(DIRECTORY_CACHE) }, + { 'L', specifier_directory, UINT_TO_PTR(DIRECTORY_LOGS) }, + { 'T', specifier_tmp_dir, NULL }, + { 'V', specifier_var_tmp_dir, NULL }, + {} +}; + +static int specifier_machine_id_safe(char specifier, const void *data, const void *userdata, char **ret) { + int r; + + /* If /etc/machine_id is missing or empty (e.g. in a chroot environment) + * return a recognizable error so that the caller can skip the rule + * gracefully. */ + + r = specifier_machine_id(specifier, data, userdata, ret); + if (IN_SET(r, -ENOENT, -ENOMEDIUM)) + return -ENXIO; + + return r; +} + +static int specifier_directory(char specifier, const void *data, const void *userdata, char **ret) { + struct table_entry { + uint64_t type; + const char *suffix; + }; + + static const struct table_entry paths_system[] = { + [DIRECTORY_RUNTIME] = { SD_PATH_SYSTEM_RUNTIME }, + [DIRECTORY_STATE] = { SD_PATH_SYSTEM_STATE_PRIVATE }, + [DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE }, + [DIRECTORY_LOGS] = { SD_PATH_SYSTEM_STATE_LOGS }, + }; + + static const struct table_entry paths_user[] = { + [DIRECTORY_RUNTIME] = { SD_PATH_USER_RUNTIME }, + [DIRECTORY_STATE] = { SD_PATH_USER_CONFIGURATION }, + [DIRECTORY_CACHE] = { SD_PATH_USER_STATE_CACHE }, + [DIRECTORY_LOGS] = { SD_PATH_USER_CONFIGURATION, "log" }, + }; + + unsigned i; + const struct table_entry *paths; + + assert_cc(ELEMENTSOF(paths_system) == ELEMENTSOF(paths_user)); + paths = arg_user ? paths_user : paths_system; + + i = PTR_TO_UINT(data); + assert(i < ELEMENTSOF(paths_system)); + + return sd_path_home(paths[i].type, paths[i].suffix, ret); +} + +static int log_unresolvable_specifier(const char *filename, unsigned line) { + static bool notified = false; + + /* In system mode, this is called when /etc is not fully initialized (e.g. + * in a chroot environment) where some specifiers are unresolvable. In user + * mode, this is called when some variables are not defined. These cases are + * not considered as an error so log at LOG_NOTICE only for the first time + * and then downgrade this to LOG_DEBUG for the rest. */ + + log_full(notified ? LOG_DEBUG : LOG_NOTICE, + "[%s:%u] Failed to resolve specifier: %s, skipping", + filename, line, + arg_user ? "Required $XDG_... variable not defined" : "uninitialized /etc detected"); + + if (!notified) + log_notice("All rules containing unresolvable specifiers will be skipped."); + + notified = true; + return 0; +} + +static int user_config_paths(char*** ret) { + _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL; + _cleanup_free_ char *persistent_config = NULL, *runtime_config = NULL, *data_home = NULL; + _cleanup_strv_free_ char **res = NULL; + int r; + + r = xdg_user_dirs(&config_dirs, &data_dirs); + if (r < 0) + return r; + + r = xdg_user_config_dir(&persistent_config, "/user-tmpfiles.d"); + if (r < 0 && r != -ENXIO) + return r; + + r = xdg_user_runtime_dir(&runtime_config, "/user-tmpfiles.d"); + if (r < 0 && r != -ENXIO) + return r; + + r = xdg_user_data_dir(&data_home, "/user-tmpfiles.d"); + if (r < 0 && r != -ENXIO) + return r; + + r = strv_extend_strv_concat(&res, config_dirs, "/user-tmpfiles.d"); + if (r < 0) + return r; + + r = strv_extend(&res, persistent_config); + if (r < 0) + return r; + + r = strv_extend(&res, runtime_config); + if (r < 0) + return r; + + r = strv_extend(&res, data_home); + if (r < 0) + return r; + + r = strv_extend_strv_concat(&res, data_dirs, "/user-tmpfiles.d"); + if (r < 0) + return r; + + r = path_strv_make_absolute_cwd(res); + if (r < 0) + return r; + + *ret = TAKE_PTR(res); + return 0; +} + +static bool needs_glob(ItemType t) { + return IN_SET(t, + WRITE_FILE, + IGNORE_PATH, + IGNORE_DIRECTORY_PATH, + REMOVE_PATH, + RECURSIVE_REMOVE_PATH, + EMPTY_DIRECTORY, + ADJUST_MODE, + RELABEL_PATH, + RECURSIVE_RELABEL_PATH, + SET_XATTR, + RECURSIVE_SET_XATTR, + SET_ACL, + RECURSIVE_SET_ACL, + SET_ATTRIBUTE, + RECURSIVE_SET_ATTRIBUTE); +} + +static bool takes_ownership(ItemType t) { + return IN_SET(t, + CREATE_FILE, + TRUNCATE_FILE, + CREATE_DIRECTORY, + EMPTY_DIRECTORY, + TRUNCATE_DIRECTORY, + CREATE_SUBVOLUME, + CREATE_SUBVOLUME_INHERIT_QUOTA, + CREATE_SUBVOLUME_NEW_QUOTA, + CREATE_FIFO, + CREATE_SYMLINK, + CREATE_CHAR_DEVICE, + CREATE_BLOCK_DEVICE, + COPY_FILES, + WRITE_FILE, + IGNORE_PATH, + IGNORE_DIRECTORY_PATH, + REMOVE_PATH, + RECURSIVE_REMOVE_PATH); +} + +static struct Item* find_glob(OrderedHashmap *h, const char *match) { + ItemArray *j; + Iterator i; + + ORDERED_HASHMAP_FOREACH(j, h, i) { + size_t n; + + for (n = 0; n < j->n_items; n++) { + Item *item = j->items + n; + + if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0) + return item; + } + } + + return NULL; +} + +static int load_unix_sockets(void) { + _cleanup_set_free_free_ Set *sockets = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + if (unix_sockets) + return 0; + + /* We maintain a cache of the sockets we found in /proc/net/unix to speed things up a little. */ + + sockets = set_new(&path_hash_ops); + if (!sockets) + return log_oom(); + + f = fopen("/proc/net/unix", "re"); + if (!f) + return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, + "Failed to open /proc/net/unix, ignoring: %m"); + + /* Skip header */ + r = read_line(f, LONG_LINE_MAX, NULL); + if (r < 0) + return log_warning_errno(r, "Failed to skip /proc/net/unix header line: %m"); + if (r == 0) + return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Premature end of file reading /proc/net/unix."); + + for (;;) { + _cleanup_free_ char *line = NULL, *s = NULL; + char *p; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) + return log_warning_errno(r, "Failed to read /proc/net/unix line, ignoring: %m"); + if (r == 0) /* EOF */ + break; + + p = strchr(line, ':'); + if (!p) + continue; + + if (strlen(p) < 37) + continue; + + p += 37; + p += strspn(p, WHITESPACE); + p += strcspn(p, WHITESPACE); /* skip one more word */ + p += strspn(p, WHITESPACE); + + if (*p != '/') + continue; + + s = strdup(p); + if (!s) + return log_oom(); + + path_simplify(s, false); + + r = set_consume(sockets, s); + if (r == -EEXIST) + continue; + if (r < 0) + return log_warning_errno(r, "Failed to add AF_UNIX socket to set, ignoring: %m"); + + TAKE_PTR(s); + } + + unix_sockets = TAKE_PTR(sockets); + return 1; +} + +static bool unix_socket_alive(const char *fn) { + assert(fn); + + if (load_unix_sockets() < 0) + return true; /* We don't know, so assume yes */ + + return !!set_get(unix_sockets, (char*) fn); +} + +static DIR* xopendirat_nomod(int dirfd, const char *path) { + DIR *dir; + + dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME); + if (dir) + return dir; + + log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path); + if (errno != EPERM) + return NULL; + + dir = xopendirat(dirfd, path, O_NOFOLLOW); + if (!dir) + log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path); + + return dir; +} + +static DIR* opendir_nomod(const char *path) { + return xopendirat_nomod(AT_FDCWD, path); +} + +static int dir_cleanup( + Item *i, + const char *p, + DIR *d, + const struct stat *ds, + usec_t cutoff, + dev_t rootdev, + bool mountpoint, + int maxdepth, + bool keep_this_level) { + + struct dirent *dent; + bool deleted = false; + int r = 0; + + FOREACH_DIRENT_ALL(dent, d, break) { + struct stat s; + usec_t age; + _cleanup_free_ char *sub_path = NULL; + + if (dot_or_dot_dot(dent->d_name)) + continue; + + if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) { + if (errno == ENOENT) + continue; + + /* FUSE, NFS mounts, SELinux might return EACCES */ + r = log_full_errno(errno == EACCES ? LOG_DEBUG : LOG_ERR, errno, + "stat(%s/%s) failed: %m", p, dent->d_name); + continue; + } + + /* Stay on the same filesystem */ + if (s.st_dev != rootdev) { + log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name); + continue; + } + + /* Try to detect bind mounts of the same filesystem instance; they + * do not differ in device major/minors. This type of query is not + * supported on all kernels or filesystem types though. */ + if (S_ISDIR(s.st_mode)) { + int q; + + q = fd_is_mount_point(dirfd(d), dent->d_name, 0); + if (q < 0) + log_debug_errno(q, "Failed to determine whether \"%s/%s\" is a mount point, ignoring: %m", p, dent->d_name); + else if (q > 0) { + log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.", p, dent->d_name); + continue; + } + } + + sub_path = path_join(p, dent->d_name); + if (!sub_path) { + r = log_oom(); + goto finish; + } + + /* Is there an item configured for this path? */ + if (ordered_hashmap_get(items, sub_path)) { + log_debug("Ignoring \"%s\": a separate entry exists.", sub_path); + continue; + } + + if (find_glob(globs, sub_path)) { + log_debug("Ignoring \"%s\": a separate glob exists.", sub_path); + continue; + } + + if (S_ISDIR(s.st_mode)) { + _cleanup_closedir_ DIR *sub_dir = NULL; + + if (mountpoint && + streq(dent->d_name, "lost+found") && + s.st_uid == 0) { + log_debug("Ignoring directory \"%s\".", sub_path); + continue; + } + + if (maxdepth <= 0) + log_warning("Reached max depth on \"%s\".", sub_path); + else { + int q; + + sub_dir = xopendirat_nomod(dirfd(d), dent->d_name); + if (!sub_dir) { + if (errno != ENOENT) + r = log_warning_errno(errno, "Opening directory \"%s\" failed, ignoring: %m", sub_path); + + continue; + } + + if (flock(dirfd(sub_dir), LOCK_EX|LOCK_NB) < 0) { + log_debug_errno(errno, "Couldn't acquire shared BSD lock on directory \"%s\", skipping: %m", p); + continue; + } + + q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false); + if (q < 0) + r = q; + } + + /* Note: if you are wondering why we don't support the sticky bit for excluding + * directories from cleaning like we do it for other file system objects: well, the + * sticky bit already has a meaning for directories, so we don't want to overload + * that. */ + + if (keep_this_level) { + log_debug("Keeping directory \"%s\".", sub_path); + continue; + } + + /* Ignore ctime, we change it when deleting */ + age = timespec_load(&s.st_mtim); + if (age >= cutoff) { + char a[FORMAT_TIMESTAMP_MAX]; + /* Follows spelling in stat(1). */ + log_debug("Directory \"%s\": modify time %s is too new.", + sub_path, + format_timestamp_us(a, sizeof(a), age)); + continue; + } + + age = timespec_load(&s.st_atim); + if (age >= cutoff) { + char a[FORMAT_TIMESTAMP_MAX]; + log_debug("Directory \"%s\": access time %s is too new.", + sub_path, + format_timestamp_us(a, sizeof(a), age)); + continue; + } + + log_debug("Removing directory \"%s\".", sub_path); + if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0) + if (!IN_SET(errno, ENOENT, ENOTEMPTY)) + r = log_warning_errno(errno, "Failed to remove directory \"%s\", ignoring: %m", sub_path); + + } else { + /* Skip files for which the sticky bit is set. These are semantics we define, and are + * unknown elsewhere. See XDG_RUNTIME_DIR specification for details. */ + if (s.st_mode & S_ISVTX) { + log_debug("Skipping \"%s\": sticky bit set.", sub_path); + continue; + } + + if (mountpoint && + S_ISREG(s.st_mode) && + s.st_uid == 0 && + STR_IN_SET(dent->d_name, + ".journal", + "aquota.user", + "aquota.group")) { + log_debug("Skipping \"%s\".", sub_path); + continue; + } + + /* Ignore sockets that are listed in /proc/net/unix */ + if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) { + log_debug("Skipping \"%s\": live socket.", sub_path); + continue; + } + + /* Ignore device nodes */ + if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) { + log_debug("Skipping \"%s\": a device.", sub_path); + continue; + } + + /* Keep files on this level around if this is requested */ + if (keep_this_level) { + log_debug("Keeping \"%s\".", sub_path); + continue; + } + + age = timespec_load(&s.st_mtim); + if (age >= cutoff) { + char a[FORMAT_TIMESTAMP_MAX]; + /* Follows spelling in stat(1). */ + log_debug("File \"%s\": modify time %s is too new.", + sub_path, + format_timestamp_us(a, sizeof(a), age)); + continue; + } + + age = timespec_load(&s.st_atim); + if (age >= cutoff) { + char a[FORMAT_TIMESTAMP_MAX]; + log_debug("File \"%s\": access time %s is too new.", + sub_path, + format_timestamp_us(a, sizeof(a), age)); + continue; + } + + age = timespec_load(&s.st_ctim); + if (age >= cutoff) { + char a[FORMAT_TIMESTAMP_MAX]; + log_debug("File \"%s\": change time %s is too new.", + sub_path, + format_timestamp_us(a, sizeof(a), age)); + continue; + } + + log_debug("Removing \"%s\".", sub_path); + if (unlinkat(dirfd(d), dent->d_name, 0) < 0) + if (errno != ENOENT) + r = log_warning_errno(errno, "Failed to remove \"%s\", ignoring: %m", sub_path); + + deleted = true; + } + } + +finish: + if (deleted) { + char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX]; + usec_t age1, age2; + + age1 = timespec_load(&ds->st_atim); + age2 = timespec_load(&ds->st_mtim); + + log_debug("Restoring access and modification time on \"%s\": %s, %s", + p, + format_timestamp_us(a, sizeof(a), age1), + format_timestamp_us(b, sizeof(b), age2)); + + /* Restore original directory timestamps */ + if (futimens(dirfd(d), (struct timespec[]) { + ds->st_atim, + ds->st_mtim }) < 0) + log_warning_errno(errno, "Failed to revert timestamps of '%s', ignoring: %m", p); + } + + return r; +} + +static bool dangerous_hardlinks(void) { + _cleanup_free_ char *value = NULL; + static int cached = -1; + int r; + + /* Check whether the fs.protected_hardlinks sysctl is on. If we can't determine it we assume its off, as that's + * what the upstream default is. */ + + if (cached >= 0) + return cached; + + r = read_one_line_file("/proc/sys/fs/protected_hardlinks", &value); + if (r < 0) { + log_debug_errno(r, "Failed to read fs.protected_hardlinks sysctl: %m"); + return true; + } + + r = parse_boolean(value); + if (r < 0) { + log_debug_errno(r, "Failed to parse fs.protected_hardlinks sysctl: %m"); + return true; + } + + cached = r == 0; + return cached; +} + +static bool hardlink_vulnerable(const struct stat *st) { + assert(st); + + return !S_ISDIR(st->st_mode) && st->st_nlink > 1 && dangerous_hardlinks(); +} + +static mode_t process_mask_perms(mode_t mode, mode_t current) { + + if ((current & 0111) == 0) + mode &= ~0111; + if ((current & 0222) == 0) + mode &= ~0222; + if ((current & 0444) == 0) + mode &= ~0444; + if (!S_ISDIR(current)) + mode &= ~07000; /* remove sticky/sgid/suid bit, unless directory */ + + return mode; +} + +static int fd_set_perms(Item *i, int fd, const char *path, const struct stat *st) { + struct stat stbuf; + mode_t new_mode; + bool do_chown; + + assert(i); + assert(fd); + assert(path); + + if (!i->mode_set && !i->uid_set && !i->gid_set) + goto shortcut; + + if (!st) { + if (fstat(fd, &stbuf) < 0) + return log_error_errno(errno, "fstat(%s) failed: %m", path); + st = &stbuf; + } + + if (hardlink_vulnerable(st)) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Refusing to set permissions on hardlinked file %s while the fs.protected_hardlinks sysctl is turned off.", + path); + + /* Do we need a chown()? */ + do_chown = + (i->uid_set && i->uid != st->st_uid) || + (i->gid_set && i->gid != st->st_gid); + + /* Calculate the mode to apply */ + new_mode = i->mode_set ? (i->mask_perms ? + process_mask_perms(i->mode, st->st_mode) : + i->mode) : + (st->st_mode & 07777); + + if (i->mode_set && do_chown) { + /* Before we issue the chmod() let's reduce the access mode to the common bits of the old and + * the new mode. That way there's no time window where the file exists under the old owner + * with more than the old access modes — and not under the new owner with more than the new + * access modes either. */ + + if (S_ISLNK(st->st_mode)) + log_debug("Skipping temporary mode fix for symlink %s.", path); + else { + mode_t m = new_mode & st->st_mode; /* Mask new mode by old mode */ + + if (((m ^ st->st_mode) & 07777) == 0) + log_debug("\"%s\" matches temporary mode %o already.", path, m); + else { + log_debug("Temporarily changing \"%s\" to mode %o.", path, m); + if (fchmod_opath(fd, m) < 0) + return log_error_errno(errno, "fchmod() of %s failed: %m", path); + } + } + } + + if (do_chown) { + log_debug("Changing \"%s\" to owner "UID_FMT":"GID_FMT, + path, + i->uid_set ? i->uid : UID_INVALID, + i->gid_set ? i->gid : GID_INVALID); + + if (fchownat(fd, + "", + i->uid_set ? i->uid : UID_INVALID, + i->gid_set ? i->gid : GID_INVALID, + AT_EMPTY_PATH) < 0) + return log_error_errno(errno, "fchownat() of %s failed: %m", path); + } + + /* Now, apply the final mode. We do this in two cases: when the user set a mode explicitly, or after a + * chown(), since chown()'s mangle the access mode in regards to sgid/suid in some conditions. */ + if (i->mode_set || do_chown) { + if (S_ISLNK(st->st_mode)) + log_debug("Skipping mode fix for symlink %s.", path); + else { + /* Check if the chmod() is unnecessary. Note that if we did a chown() before we always + * chmod() here again, since it might have mangled the bits. */ + if (!do_chown && ((new_mode ^ st->st_mode) & 07777) == 0) + log_debug("\"%s\" matches mode %o already.", path, new_mode); + else { + log_debug("Changing \"%s\" to mode %o.", path, new_mode); + if (fchmod_opath(fd, new_mode) < 0) + return log_error_errno(errno, "fchmod() of %s failed: %m", path); + } + } + } + +shortcut: + return label_fix(path, 0); +} + +static int path_open_parent_safe(const char *path) { + _cleanup_free_ char *dn = NULL; + int r, fd; + + if (path_equal(path, "/") || !path_is_normalized(path)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to open parent of '%s': invalid path.", + path); + + dn = dirname_malloc(path); + if (!dn) + return log_oom(); + + r = chase_symlinks(dn, arg_root, CHASE_SAFE|CHASE_WARN, NULL, &fd); + if (r < 0 && r != -ENOLINK) + return log_error_errno(r, "Failed to validate path %s: %m", path); + + return r < 0 ? r : fd; +} + +static int path_open_safe(const char *path) { + int r, fd; + + /* path_open_safe() returns a file descriptor opened with O_PATH after + * verifying that the path doesn't contain unsafe transitions, except + * for its final component as the function does not follow symlink. */ + + assert(path); + + if (!path_is_normalized(path)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to open invalid path '%s'.", + path); + + r = chase_symlinks(path, arg_root, CHASE_SAFE|CHASE_WARN|CHASE_NOFOLLOW, NULL, &fd); + if (r < 0 && r != -ENOLINK) + return log_error_errno(r, "Failed to validate path %s: %m", path); + + return r < 0 ? r : fd; +} + +static int path_set_perms(Item *i, const char *path) { + _cleanup_close_ int fd = -1; + + assert(i); + assert(path); + + fd = path_open_safe(path); + if (fd < 0) + return fd; + + return fd_set_perms(i, fd, path, NULL); +} + +static int parse_xattrs_from_arg(Item *i) { + const char *p; + int r; + + assert(i); + assert(i->argument); + + p = i->argument; + + for (;;) { + _cleanup_free_ char *name = NULL, *value = NULL, *xattr = NULL; + + r = extract_first_word(&p, &xattr, NULL, EXTRACT_UNQUOTE|EXTRACT_CUNESCAPE); + if (r < 0) + log_warning_errno(r, "Failed to parse extended attribute '%s', ignoring: %m", p); + if (r <= 0) + break; + + r = split_pair(xattr, "=", &name, &value); + if (r < 0) { + log_warning_errno(r, "Failed to parse extended attribute, ignoring: %s", xattr); + continue; + } + + if (isempty(name) || isempty(value)) { + log_warning("Malformed extended attribute found, ignoring: %s", xattr); + continue; + } + + if (strv_push_pair(&i->xattrs, name, value) < 0) + return log_oom(); + + name = value = NULL; + } + + return 0; +} + +static int fd_set_xattrs(Item *i, int fd, const char *path, const struct stat *st) { + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + char **name, **value; + + assert(i); + assert(fd); + assert(path); + + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + + STRV_FOREACH_PAIR(name, value, i->xattrs) { + log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path); + if (setxattr(procfs_path, *name, *value, strlen(*value), 0) < 0) + return log_error_errno(errno, "Setting extended attribute %s=%s on %s failed: %m", + *name, *value, path); + } + return 0; +} + +static int path_set_xattrs(Item *i, const char *path) { + _cleanup_close_ int fd = -1; + + assert(i); + assert(path); + + fd = path_open_safe(path); + if (fd < 0) + return fd; + + return fd_set_xattrs(i, fd, path, NULL); +} + +static int parse_acls_from_arg(Item *item) { +#if HAVE_ACL + int r; + + assert(item); + + /* If append_or_force (= modify) is set, we will not modify the acl + * afterwards, so the mask can be added now if necessary. */ + + r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->append_or_force); + if (r < 0) + log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring", item->argument); +#else + log_warning_errno(SYNTHETIC_ERRNO(ENOSYS), "ACLs are not supported. Ignoring"); +#endif + + return 0; +} + +#if HAVE_ACL +static int path_set_acl(const char *path, const char *pretty, acl_type_t type, acl_t acl, bool modify) { + _cleanup_(acl_free_charpp) char *t = NULL; + _cleanup_(acl_freep) acl_t dup = NULL; + int r; + + /* Returns 0 for success, positive error if already warned, + * negative error otherwise. */ + + if (modify) { + r = acls_for_file(path, type, acl, &dup); + if (r < 0) + return r; + + r = calc_acl_mask_if_needed(&dup); + if (r < 0) + return r; + } else { + dup = acl_dup(acl); + if (!dup) + return -errno; + + /* the mask was already added earlier if needed */ + } + + r = add_base_acls_if_needed(&dup, path); + if (r < 0) + return r; + + t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE); + log_debug("Setting %s ACL %s on %s.", + type == ACL_TYPE_ACCESS ? "access" : "default", + strna(t), pretty); + + r = acl_set_file(path, type, dup); + if (r < 0) + /* Return positive to indicate we already warned */ + return -log_error_errno(errno, + "Setting %s ACL \"%s\" on %s failed: %m", + type == ACL_TYPE_ACCESS ? "access" : "default", + strna(t), pretty); + + return 0; +} +#endif + +static int fd_set_acls(Item *item, int fd, const char *path, const struct stat *st) { + int r = 0; +#if HAVE_ACL + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + struct stat stbuf; + + assert(item); + assert(fd); + assert(path); + + if (!st) { + if (fstat(fd, &stbuf) < 0) + return log_error_errno(errno, "fstat(%s) failed: %m", path); + st = &stbuf; + } + + if (hardlink_vulnerable(st)) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Refusing to set ACLs on hardlinked file %s while the fs.protected_hardlinks sysctl is turned off.", + path); + + if (S_ISLNK(st->st_mode)) { + log_debug("Skipping ACL fix for symlink %s.", path); + return 0; + } + + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + + if (item->acl_access) + r = path_set_acl(procfs_path, path, ACL_TYPE_ACCESS, item->acl_access, item->append_or_force); + + /* set only default acls to folders */ + if (r == 0 && item->acl_default && S_ISDIR(st->st_mode)) + r = path_set_acl(procfs_path, path, ACL_TYPE_DEFAULT, item->acl_default, item->append_or_force); + + if (r > 0) + return -r; /* already warned */ + if (r == -EOPNOTSUPP) { + log_debug_errno(r, "ACLs not supported by file system at %s", path); + return 0; + } + if (r < 0) + return log_error_errno(r, "ACL operation on \"%s\" failed: %m", path); +#endif + return r; +} + +static int path_set_acls(Item *item, const char *path) { + int r = 0; +#if HAVE_ACL + _cleanup_close_ int fd = -1; + + assert(item); + assert(path); + + fd = path_open_safe(path); + if (fd < 0) + return fd; + + r = fd_set_acls(item, fd, path, NULL); +#endif + return r; +} + +static int parse_attribute_from_arg(Item *item) { + + static const struct { + char character; + unsigned value; + } attributes[] = { + { 'A', FS_NOATIME_FL }, /* do not update atime */ + { 'S', FS_SYNC_FL }, /* Synchronous updates */ + { 'D', FS_DIRSYNC_FL }, /* dirsync behaviour (directories only) */ + { 'a', FS_APPEND_FL }, /* writes to file may only append */ + { 'c', FS_COMPR_FL }, /* Compress file */ + { 'd', FS_NODUMP_FL }, /* do not dump file */ + { 'e', FS_EXTENT_FL }, /* Extents */ + { 'i', FS_IMMUTABLE_FL }, /* Immutable file */ + { 'j', FS_JOURNAL_DATA_FL }, /* Reserved for ext3 */ + { 's', FS_SECRM_FL }, /* Secure deletion */ + { 'u', FS_UNRM_FL }, /* Undelete */ + { 't', FS_NOTAIL_FL }, /* file tail should not be merged */ + { 'T', FS_TOPDIR_FL }, /* Top of directory hierarchies */ + { 'C', FS_NOCOW_FL }, /* Do not cow file */ + { 'P', FS_PROJINHERIT_FL }, /* Inherit the quota project ID */ + }; + + enum { + MODE_ADD, + MODE_DEL, + MODE_SET + } mode = MODE_ADD; + + unsigned value = 0, mask = 0; + const char *p; + + assert(item); + + p = item->argument; + if (p) { + if (*p == '+') { + mode = MODE_ADD; + p++; + } else if (*p == '-') { + mode = MODE_DEL; + p++; + } else if (*p == '=') { + mode = MODE_SET; + p++; + } + } + + if (isempty(p) && mode != MODE_SET) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Setting file attribute on '%s' needs an attribute specification.", + item->path); + + for (; p && *p ; p++) { + unsigned i, v; + + for (i = 0; i < ELEMENTSOF(attributes); i++) + if (*p == attributes[i].character) + break; + + if (i >= ELEMENTSOF(attributes)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown file attribute '%c' on '%s'.", + *p, item->path); + + v = attributes[i].value; + + SET_FLAG(value, v, IN_SET(mode, MODE_ADD, MODE_SET)); + + mask |= v; + } + + if (mode == MODE_SET) + mask |= CHATTR_ALL_FL; + + assert(mask != 0); + + item->attribute_mask = mask; + item->attribute_value = value; + item->attribute_set = true; + + return 0; +} + +static int fd_set_attribute(Item *item, int fd, const char *path, const struct stat *st) { + _cleanup_close_ int procfs_fd = -1; + struct stat stbuf; + unsigned f; + int r; + + assert(item); + assert(fd); + assert(path); + + if (!item->attribute_set || item->attribute_mask == 0) + return 0; + + if (!st) { + if (fstat(fd, &stbuf) < 0) + return log_error_errno(errno, "fstat(%s) failed: %m", path); + st = &stbuf; + } + + /* Issuing the file attribute ioctls on device nodes is not + * safe, as that will be delivered to the drivers, not the + * file system containing the device node. */ + if (!S_ISREG(st->st_mode) && !S_ISDIR(st->st_mode)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Setting file flags is only supported on regular files and directories, cannot set on '%s'.", + path); + + f = item->attribute_value & item->attribute_mask; + + /* Mask away directory-specific flags */ + if (!S_ISDIR(st->st_mode)) + f &= ~FS_DIRSYNC_FL; + + procfs_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_NOATIME); + if (procfs_fd < 0) + return log_error_errno(procfs_fd, "Failed to re-open '%s': %m", path); + + r = chattr_fd(procfs_fd, f, item->attribute_mask, NULL); + if (r < 0) + log_full_errno(IN_SET(r, -ENOTTY, -EOPNOTSUPP) ? LOG_DEBUG : LOG_WARNING, + r, + "Cannot set file attribute for '%s', value=0x%08x, mask=0x%08x, ignoring: %m", + path, item->attribute_value, item->attribute_mask); + + return 0; +} + +static int path_set_attribute(Item *item, const char *path) { + _cleanup_close_ int fd = -1; + + if (!item->attribute_set || item->attribute_mask == 0) + return 0; + + fd = path_open_safe(path); + if (fd < 0) + return fd; + + return fd_set_attribute(item, fd, path, NULL); +} + +static int write_one_file(Item *i, const char *path) { + _cleanup_close_ int fd = -1, dir_fd = -1; + char *bn; + int flags, r; + + assert(i); + assert(path); + assert(i->argument); + assert(i->type == WRITE_FILE); + + /* Validate the path and keep the fd on the directory for opening the + * file so we're sure that it can't be changed behind our back. */ + dir_fd = path_open_parent_safe(path); + if (dir_fd < 0) + return dir_fd; + + bn = basename(path); + + flags = O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY; + + /* Follows symlinks */ + fd = openat(dir_fd, bn, i->append_or_force ? flags|O_APPEND : flags, i->mode); + if (fd < 0) { + if (errno == ENOENT) { + log_debug_errno(errno, "Not writing missing file \"%s\": %m", path); + return 0; + } + return log_error_errno(errno, "Failed to open file \"%s\": %m", path); + } + + /* 'w' is allowed to write into any kind of files. */ + log_debug("Writing to \"%s\".", path); + + r = loop_write(fd, i->argument, strlen(i->argument), false); + if (r < 0) + return log_error_errno(r, "Failed to write file \"%s\": %m", path); + + return fd_set_perms(i, fd, path, NULL); +} + +static int create_file(Item *i, const char *path) { + _cleanup_close_ int fd = -1, dir_fd = -1; + struct stat stbuf, *st = NULL; + int r = 0; + char *bn; + + assert(i); + assert(path); + assert(i->type == CREATE_FILE); + + /* 'f' operates on regular files exclusively. */ + + /* Validate the path and keep the fd on the directory for opening the + * file so we're sure that it can't be changed behind our back. */ + dir_fd = path_open_parent_safe(path); + if (dir_fd < 0) + return dir_fd; + + bn = basename(path); + + RUN_WITH_UMASK(0000) { + mac_selinux_create_file_prepare(path, S_IFREG); + fd = openat(dir_fd, bn, O_CREAT|O_EXCL|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode); + mac_selinux_create_file_clear(); + } + + if (fd < 0) { + /* Even on a read-only filesystem, open(2) returns EEXIST if the + * file already exists. It returns EROFS only if it needs to + * create the file. */ + if (errno != EEXIST) + return log_error_errno(errno, "Failed to create file %s: %m", path); + + /* Re-open the file. At that point it must exist since open(2) + * failed with EEXIST. We still need to check if the perms/mode + * need to be changed. For read-only filesystems, we let + * fd_set_perms() report the error if the perms need to be + * modified. */ + fd = openat(dir_fd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH, i->mode); + if (fd < 0) + return log_error_errno(errno, "Failed to re-open file %s: %m", path); + + if (fstat(fd, &stbuf) < 0) + return log_error_errno(errno, "stat(%s) failed: %m", path); + + if (!S_ISREG(stbuf.st_mode)) { + log_error("%s exists and is not a regular file.", path); + return -EEXIST; + } + + st = &stbuf; + } else { + + log_debug("\"%s\" has been created.", path); + + if (i->argument) { + log_debug("Writing to \"%s\".", path); + + r = loop_write(fd, i->argument, strlen(i->argument), false); + if (r < 0) + return log_error_errno(r, "Failed to write file \"%s\": %m", path); + } + } + + return fd_set_perms(i, fd, path, st); +} + +static int truncate_file(Item *i, const char *path) { + _cleanup_close_ int fd = -1, dir_fd = -1; + struct stat stbuf, *st = NULL; + bool erofs = false; + int r = 0; + char *bn; + + assert(i); + assert(path); + assert(i->type == TRUNCATE_FILE || (i->type == CREATE_FILE && i->append_or_force)); + + /* We want to operate on regular file exclusively especially since + * O_TRUNC is unspecified if the file is neither a regular file nor a + * fifo nor a terminal device. Therefore we first open the file and make + * sure it's a regular one before truncating it. */ + + /* Validate the path and keep the fd on the directory for opening the + * file so we're sure that it can't be changed behind our back. */ + dir_fd = path_open_parent_safe(path); + if (dir_fd < 0) + return dir_fd; + + bn = basename(path); + + RUN_WITH_UMASK(0000) { + mac_selinux_create_file_prepare(path, S_IFREG); + fd = openat(dir_fd, bn, O_CREAT|O_NOFOLLOW|O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode); + mac_selinux_create_file_clear(); + } + + if (fd < 0) { + if (errno != EROFS) + return log_error_errno(errno, "Failed to open/create file %s: %m", path); + + /* On a read-only filesystem, we don't want to fail if the + * target is already empty and the perms are set. So we still + * proceed with the sanity checks and let the remaining + * operations fail with EROFS if they try to modify the target + * file. */ + + fd = openat(dir_fd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH, i->mode); + if (fd < 0) { + if (errno == ENOENT) { + log_error("Cannot create file %s on a read-only file system.", path); + return -EROFS; + } + + return log_error_errno(errno, "Failed to re-open file %s: %m", path); + } + + erofs = true; + } + + if (fstat(fd, &stbuf) < 0) + return log_error_errno(errno, "stat(%s) failed: %m", path); + + if (!S_ISREG(stbuf.st_mode)) { + log_error("%s exists and is not a regular file.", path); + return -EEXIST; + } + + if (stbuf.st_size > 0) { + if (ftruncate(fd, 0) < 0) { + r = erofs ? -EROFS : -errno; + return log_error_errno(r, "Failed to truncate file %s: %m", path); + } + } else + st = &stbuf; + + log_debug("\"%s\" has been created.", path); + + if (i->argument) { + log_debug("Writing to \"%s\".", path); + + r = loop_write(fd, i->argument, strlen(i->argument), false); + if (r < 0) { + r = erofs ? -EROFS : r; + return log_error_errno(r, "Failed to write file %s: %m", path); + } + } + + return fd_set_perms(i, fd, path, st); +} + +static int copy_files(Item *i) { + _cleanup_close_ int dfd = -1, fd = -1; + char *bn; + int r; + + log_debug("Copying tree \"%s\" to \"%s\".", i->argument, i->path); + + bn = basename(i->path); + + /* Validate the path and use the returned directory fd for copying the + * target so we're sure that the path can't be changed behind our + * back. */ + dfd = path_open_parent_safe(i->path); + if (dfd < 0) + return dfd; + + r = copy_tree_at(AT_FDCWD, i->argument, + dfd, bn, + i->uid_set ? i->uid : UID_INVALID, + i->gid_set ? i->gid : GID_INVALID, + COPY_REFLINK | COPY_MERGE_EMPTY); + if (r < 0) { + struct stat a, b; + + /* If the target already exists on read-only filesystems, trying + * to create the target will not fail with EEXIST but with + * EROFS. */ + if (r == -EROFS && faccessat(dfd, bn, F_OK, AT_SYMLINK_NOFOLLOW) == 0) + r = -EEXIST; + + if (r != -EEXIST) + return log_error_errno(r, "Failed to copy files to %s: %m", i->path); + + if (stat(i->argument, &a) < 0) + return log_error_errno(errno, "stat(%s) failed: %m", i->argument); + + if (fstatat(dfd, bn, &b, AT_SYMLINK_NOFOLLOW) < 0) + return log_error_errno(errno, "stat(%s) failed: %m", i->path); + + if ((a.st_mode ^ b.st_mode) & S_IFMT) { + log_debug("Can't copy to %s, file exists already and is of different type", i->path); + return 0; + } + } + + fd = openat(dfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH); + if (fd < 0) + return log_error_errno(errno, "Failed to openat(%s): %m", i->path); + + return fd_set_perms(i, fd, i->path, NULL); +} + +typedef enum { + CREATION_NORMAL, + CREATION_EXISTING, + CREATION_FORCE, + _CREATION_MODE_MAX, + _CREATION_MODE_INVALID = -1 +} CreationMode; + +static const char *const creation_mode_verb_table[_CREATION_MODE_MAX] = { + [CREATION_NORMAL] = "Created", + [CREATION_EXISTING] = "Found existing", + [CREATION_FORCE] = "Created replacement", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode); + +static int create_directory_or_subvolume(const char *path, mode_t mode, bool subvol, CreationMode *creation) { + _cleanup_close_ int pfd = -1; + CreationMode c; + int r; + + assert(path); + + if (!creation) + creation = &c; + + pfd = path_open_parent_safe(path); + if (pfd < 0) + return pfd; + + if (subvol) { + if (btrfs_is_subvol(empty_to_root(arg_root)) <= 0) + + /* Don't create a subvolume unless the root directory is + * one, too. We do this under the assumption that if the + * root directory is just a plain directory (i.e. very + * light-weight), we shouldn't try to split it up into + * subvolumes (i.e. more heavy-weight). Thus, chroot() + * environments and suchlike will get a full brtfs + * subvolume set up below their tree only if they + * specifically set up a btrfs subvolume for the root + * dir too. */ + + subvol = false; + else { + RUN_WITH_UMASK((~mode) & 0777) + r = btrfs_subvol_make_fd(pfd, basename(path)); + } + } else + r = 0; + + if (!subvol || r == -ENOTTY) + RUN_WITH_UMASK(0000) + r = mkdirat_label(pfd, basename(path), mode); + + if (r < 0) { + int k; + + if (!IN_SET(r, -EEXIST, -EROFS)) + return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", path); + + k = is_dir_fd(pfd); + if (k == -ENOENT && r == -EROFS) + return log_error_errno(r, "%s does not exist and cannot be created as the file system is read-only.", path); + if (k < 0) + return log_error_errno(k, "Failed to check if %s exists: %m", path); + if (!k) { + log_warning("\"%s\" already exists and is not a directory.", path); + return -EEXIST; + } + + *creation = CREATION_EXISTING; + } else + *creation = CREATION_NORMAL; + + log_debug("%s directory \"%s\".", creation_mode_verb_to_string(*creation), path); + + r = openat(pfd, basename(path), O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (r < 0) + return log_error_errno(errno, "Failed to open directory '%s': %m", basename(path)); + + return r; +} + +static int create_directory(Item *i, const char *path) { + _cleanup_close_ int fd = -1; + + assert(i); + assert(IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY)); + + fd = create_directory_or_subvolume(path, i->mode, false, NULL); + if (fd == -EEXIST) + return 0; + if (fd < 0) + return fd; + + return fd_set_perms(i, fd, path, NULL); +} + +static int create_subvolume(Item *i, const char *path) { + _cleanup_close_ int fd = -1; + CreationMode creation; + int r, q = 0; + + assert(i); + assert(IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)); + + fd = create_directory_or_subvolume(path, i->mode, true, &creation); + if (fd == -EEXIST) + return 0; + if (fd < 0) + return fd; + + if (creation == CREATION_NORMAL && + IN_SET(i->type, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)) { + r = btrfs_subvol_auto_qgroup_fd(fd, 0, i->type == CREATE_SUBVOLUME_NEW_QUOTA); + if (r == -ENOTTY) + log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (unsupported fs or dir not a subvolume): %m", i->path); + else if (r == -EROFS) + log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (fs is read-only).", i->path); + else if (r == -ENOPROTOOPT) + log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (quota support is disabled).", i->path); + else if (r < 0) + q = log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path); + else if (r > 0) + log_debug("Adjusted quota for subvolume \"%s\".", i->path); + else if (r == 0) + log_debug("Quota for subvolume \"%s\" already in place, no change made.", i->path); + } + + r = fd_set_perms(i, fd, path, NULL); + if (q < 0) /* prefer the quota change error from above */ + return q; + + return r; +} + +static int empty_directory(Item *i, const char *path) { + int r; + + assert(i); + assert(i->type == EMPTY_DIRECTORY); + + r = is_dir(path, false); + if (r == -ENOENT) { + /* Option "e" operates only on existing objects. Do not + * print errors about non-existent files or directories */ + log_debug("Skipping missing directory: %s", path); + return 0; + } + if (r < 0) + return log_error_errno(r, "is_dir() failed on path %s: %m", path); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "'%s' already exists and is not a directory.", + path); + + return path_set_perms(i, path); +} + +static int create_device(Item *i, mode_t file_type) { + _cleanup_close_ int dfd = -1, fd = -1; + CreationMode creation; + char *bn; + int r; + + assert(i); + assert(IN_SET(file_type, S_IFBLK, S_IFCHR)); + + bn = basename(i->path); + + /* Validate the path and use the returned directory fd for copying the + * target so we're sure that the path can't be changed behind our + * back. */ + dfd = path_open_parent_safe(i->path); + if (dfd < 0) + return dfd; + + RUN_WITH_UMASK(0000) { + mac_selinux_create_file_prepare(i->path, file_type); + r = mknodat(dfd, bn, i->mode | file_type, i->major_minor); + mac_selinux_create_file_clear(); + } + + if (r < 0) { + struct stat st; + + if (errno == EPERM) { + log_debug("We lack permissions, possibly because of cgroup configuration; " + "skipping creation of device node %s.", i->path); + return 0; + } + + if (errno != EEXIST) + return log_error_errno(errno, "Failed to create device node %s: %m", i->path); + + if (fstatat(dfd, bn, &st, 0) < 0) + return log_error_errno(errno, "stat(%s) failed: %m", i->path); + + if ((st.st_mode & S_IFMT) != file_type) { + + if (i->append_or_force) { + + RUN_WITH_UMASK(0000) { + mac_selinux_create_file_prepare(i->path, file_type); + /* FIXME: need to introduce mknodat_atomic() */ + r = mknod_atomic(i->path, i->mode | file_type, i->major_minor); + mac_selinux_create_file_clear(); + } + + if (r < 0) + return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path); + creation = CREATION_FORCE; + } else { + log_debug("%s is not a device node.", i->path); + return 0; + } + } else + creation = CREATION_EXISTING; + } else + creation = CREATION_NORMAL; + + log_debug("%s %s device node \"%s\" %u:%u.", + creation_mode_verb_to_string(creation), + i->type == CREATE_BLOCK_DEVICE ? "block" : "char", + i->path, major(i->mode), minor(i->mode)); + + fd = openat(dfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH); + if (fd < 0) + return log_error_errno(errno, "Failed to openat(%s): %m", i->path); + + return fd_set_perms(i, fd, i->path, NULL); +} + +static int create_fifo(Item *i, const char *path) { + _cleanup_close_ int pfd = -1, fd = -1; + CreationMode creation; + struct stat st; + char *bn; + int r; + + pfd = path_open_parent_safe(path); + if (pfd < 0) + return pfd; + + bn = basename(path); + + RUN_WITH_UMASK(0000) { + mac_selinux_create_file_prepare(path, S_IFIFO); + r = mkfifoat(pfd, bn, i->mode); + mac_selinux_create_file_clear(); + } + + if (r < 0) { + if (errno != EEXIST) + return log_error_errno(errno, "Failed to create fifo %s: %m", path); + + if (fstatat(pfd, bn, &st, AT_SYMLINK_NOFOLLOW) < 0) + return log_error_errno(errno, "stat(%s) failed: %m", path); + + if (!S_ISFIFO(st.st_mode)) { + + if (i->append_or_force) { + RUN_WITH_UMASK(0000) { + mac_selinux_create_file_prepare(path, S_IFIFO); + r = mkfifoat_atomic(pfd, bn, i->mode); + mac_selinux_create_file_clear(); + } + + if (r < 0) + return log_error_errno(r, "Failed to create fifo %s: %m", path); + creation = CREATION_FORCE; + } else { + log_warning("\"%s\" already exists and is not a fifo.", path); + return 0; + } + } else + creation = CREATION_EXISTING; + } else + creation = CREATION_NORMAL; + + log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), path); + + fd = openat(pfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH); + if (fd < 0) + return log_error_errno(errno, "Failed to openat(%s): %m", path); + + return fd_set_perms(i, fd, i->path, NULL); +} + +typedef int (*action_t)(Item *i, const char *path); +typedef int (*fdaction_t)(Item *i, int fd, const char *path, const struct stat *st); + +static int item_do(Item *i, int fd, const char *path, fdaction_t action) { + struct stat st; + int r = 0, q; + + assert(i); + assert(path); + assert(fd >= 0); + + if (fstat(fd, &st) < 0) { + r = log_error_errno(errno, "fstat() on file failed: %m"); + goto finish; + } + + /* This returns the first error we run into, but nevertheless + * tries to go on */ + r = action(i, fd, path, &st); + + if (S_ISDIR(st.st_mode)) { + char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + + /* The passed 'fd' was opened with O_PATH. We need to convert + * it into a 'regular' fd before reading the directory content. */ + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + + d = opendir(procfs_path); + if (!d) { + log_error_errno(errno, "Failed to opendir() '%s': %m", procfs_path); + if (r == 0) + r = -errno; + goto finish; + } + + FOREACH_DIRENT_ALL(de, d, q = -errno; goto finish) { + int de_fd; + + if (dot_or_dot_dot(de->d_name)) + continue; + + de_fd = openat(fd, de->d_name, O_NOFOLLOW|O_CLOEXEC|O_PATH); + if (de_fd < 0) + q = log_error_errno(errno, "Failed to open() file '%s': %m", de->d_name); + else { + _cleanup_free_ char *de_path = NULL; + + de_path = path_join(path, de->d_name); + if (!de_path) + q = log_oom(); + else + /* Pass ownership of dirent fd over */ + q = item_do(i, de_fd, de_path, action); + } + + if (q < 0 && r == 0) + r = q; + } + } +finish: + safe_close(fd); + return r; +} + +static int glob_item(Item *i, action_t action) { + _cleanup_globfree_ glob_t g = { + .gl_opendir = (void *(*)(const char *)) opendir_nomod, + }; + int r = 0, k; + char **fn; + + k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g); + if (k < 0 && k != -ENOENT) + return log_error_errno(k, "glob(%s) failed: %m", i->path); + + STRV_FOREACH(fn, g.gl_pathv) { + k = action(i, *fn); + if (k < 0 && r == 0) + r = k; + } + + return r; +} + +static int glob_item_recursively(Item *i, fdaction_t action) { + _cleanup_globfree_ glob_t g = { + .gl_opendir = (void *(*)(const char *)) opendir_nomod, + }; + int r = 0, k; + char **fn; + + k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g); + if (k < 0 && k != -ENOENT) + return log_error_errno(k, "glob(%s) failed: %m", i->path); + + STRV_FOREACH(fn, g.gl_pathv) { + _cleanup_close_ int fd = -1; + + /* Make sure we won't trigger/follow file object (such as + * device nodes, automounts, ...) pointed out by 'fn' with + * O_PATH. Note, when O_PATH is used, flags other than + * O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW are ignored. */ + + fd = open(*fn, O_CLOEXEC|O_NOFOLLOW|O_PATH); + if (fd < 0) { + log_error_errno(errno, "Opening '%s' failed: %m", *fn); + if (r == 0) + r = -errno; + continue; + } + + k = item_do(i, fd, *fn, action); + if (k < 0 && r == 0) + r = k; + + /* we passed fd ownership to the previous call */ + fd = -1; + } + + return r; +} + +static int create_item(Item *i) { + CreationMode creation; + int r = 0; + + assert(i); + + log_debug("Running create action for entry %c %s", (char) i->type, i->path); + + switch (i->type) { + + case IGNORE_PATH: + case IGNORE_DIRECTORY_PATH: + case REMOVE_PATH: + case RECURSIVE_REMOVE_PATH: + return 0; + + case TRUNCATE_FILE: + case CREATE_FILE: + RUN_WITH_UMASK(0000) + (void) mkdir_parents_label(i->path, 0755); + + if ((i->type == CREATE_FILE && i->append_or_force) || i->type == TRUNCATE_FILE) + r = truncate_file(i, i->path); + else + r = create_file(i, i->path); + + if (r < 0) + return r; + break; + + case COPY_FILES: + RUN_WITH_UMASK(0000) + (void) mkdir_parents_label(i->path, 0755); + + r = copy_files(i); + if (r < 0) + return r; + break; + + case WRITE_FILE: + r = glob_item(i, write_one_file); + if (r < 0) + return r; + + break; + + case CREATE_DIRECTORY: + case TRUNCATE_DIRECTORY: + RUN_WITH_UMASK(0000) + (void) mkdir_parents_label(i->path, 0755); + + r = create_directory(i, i->path); + if (r < 0) + return r; + break; + + case CREATE_SUBVOLUME: + case CREATE_SUBVOLUME_INHERIT_QUOTA: + case CREATE_SUBVOLUME_NEW_QUOTA: + RUN_WITH_UMASK(0000) + (void) mkdir_parents_label(i->path, 0755); + + r = create_subvolume(i, i->path); + if (r < 0) + return r; + break; + + case EMPTY_DIRECTORY: + r = glob_item(i, empty_directory); + if (r < 0) + return r; + break; + + case CREATE_FIFO: + RUN_WITH_UMASK(0000) + (void) mkdir_parents_label(i->path, 0755); + + r = create_fifo(i, i->path); + if (r < 0) + return r; + break; + + case CREATE_SYMLINK: { + RUN_WITH_UMASK(0000) + (void) mkdir_parents_label(i->path, 0755); + + mac_selinux_create_file_prepare(i->path, S_IFLNK); + r = symlink(i->argument, i->path); + mac_selinux_create_file_clear(); + + if (r < 0) { + _cleanup_free_ char *x = NULL; + + if (errno != EEXIST) + return log_error_errno(errno, "symlink(%s, %s) failed: %m", i->argument, i->path); + + r = readlink_malloc(i->path, &x); + if (r < 0 || !streq(i->argument, x)) { + + if (i->append_or_force) { + mac_selinux_create_file_prepare(i->path, S_IFLNK); + r = symlink_atomic(i->argument, i->path); + mac_selinux_create_file_clear(); + + if (IN_SET(r, -EISDIR, -EEXIST, -ENOTEMPTY)) { + r = rm_rf(i->path, REMOVE_ROOT|REMOVE_PHYSICAL); + if (r < 0) + return log_error_errno(r, "rm -fr %s failed: %m", i->path); + + mac_selinux_create_file_prepare(i->path, S_IFLNK); + r = symlink(i->argument, i->path) < 0 ? -errno : 0; + mac_selinux_create_file_clear(); + } + if (r < 0) + return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path); + + creation = CREATION_FORCE; + } else { + log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path); + return 0; + } + } else + creation = CREATION_EXISTING; + } else + + creation = CREATION_NORMAL; + log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path); + break; + } + + case CREATE_BLOCK_DEVICE: + case CREATE_CHAR_DEVICE: + if (have_effective_cap(CAP_MKNOD) == 0) { + /* In a container we lack CAP_MKNOD. We shouldn't attempt to create the device node in that + * case to avoid noise, and we don't support virtualized devices in containers anyway. */ + + log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path); + return 0; + } + + RUN_WITH_UMASK(0000) + (void) mkdir_parents_label(i->path, 0755); + + r = create_device(i, i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR); + if (r < 0) + return r; + + break; + + case ADJUST_MODE: + case RELABEL_PATH: + r = glob_item(i, path_set_perms); + if (r < 0) + return r; + break; + + case RECURSIVE_RELABEL_PATH: + r = glob_item_recursively(i, fd_set_perms); + if (r < 0) + return r; + break; + + case SET_XATTR: + r = glob_item(i, path_set_xattrs); + if (r < 0) + return r; + break; + + case RECURSIVE_SET_XATTR: + r = glob_item_recursively(i, fd_set_xattrs); + if (r < 0) + return r; + break; + + case SET_ACL: + r = glob_item(i, path_set_acls); + if (r < 0) + return r; + break; + + case RECURSIVE_SET_ACL: + r = glob_item_recursively(i, fd_set_acls); + if (r < 0) + return r; + break; + + case SET_ATTRIBUTE: + r = glob_item(i, path_set_attribute); + if (r < 0) + return r; + break; + + case RECURSIVE_SET_ATTRIBUTE: + r = glob_item_recursively(i, fd_set_attribute); + if (r < 0) + return r; + break; + } + + return 0; +} + +static int remove_item_instance(Item *i, const char *instance) { + int r; + + assert(i); + + switch (i->type) { + + case REMOVE_PATH: + if (remove(instance) < 0 && errno != ENOENT) + return log_error_errno(errno, "rm(%s): %m", instance); + + break; + + case RECURSIVE_REMOVE_PATH: + /* FIXME: we probably should use dir_cleanup() here instead of rm_rf() so that 'x' is honoured. */ + log_debug("rm -rf \"%s\"", instance); + r = rm_rf(instance, REMOVE_ROOT|REMOVE_SUBVOLUME|REMOVE_PHYSICAL); + if (r < 0 && r != -ENOENT) + return log_error_errno(r, "rm_rf(%s): %m", instance); + + break; + + default: + assert_not_reached("wut?"); + } + + return 0; +} + +static int remove_item(Item *i) { + int r; + + assert(i); + + log_debug("Running remove action for entry %c %s", (char) i->type, i->path); + + switch (i->type) { + + case TRUNCATE_DIRECTORY: + /* FIXME: we probably should use dir_cleanup() here instead of rm_rf() so that 'x' is honoured. */ + log_debug("rm -rf \"%s\"", i->path); + r = rm_rf(i->path, REMOVE_PHYSICAL); + if (r < 0 && r != -ENOENT) + return log_error_errno(r, "rm_rf(%s): %m", i->path); + + return 0; + + case REMOVE_PATH: + case RECURSIVE_REMOVE_PATH: + return glob_item(i, remove_item_instance); + + default: + return 0; + } +} + +static int clean_item_instance(Item *i, const char* instance) { + _cleanup_closedir_ DIR *d = NULL; + struct stat s, ps; + bool mountpoint; + usec_t cutoff, n; + char timestamp[FORMAT_TIMESTAMP_MAX]; + + assert(i); + + if (!i->age_set) + return 0; + + n = now(CLOCK_REALTIME); + if (n < i->age) + return 0; + + cutoff = n - i->age; + + d = opendir_nomod(instance); + if (!d) { + if (IN_SET(errno, ENOENT, ENOTDIR)) { + log_debug_errno(errno, "Directory \"%s\": %m", instance); + return 0; + } + + return log_error_errno(errno, "Failed to open directory %s: %m", instance); + } + + if (fstat(dirfd(d), &s) < 0) + return log_error_errno(errno, "stat(%s) failed: %m", i->path); + + if (!S_ISDIR(s.st_mode)) + return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), + "%s is not a directory.", i->path); + + if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0) + return log_error_errno(errno, "stat(%s/..) failed: %m", i->path); + + mountpoint = s.st_dev != ps.st_dev || s.st_ino == ps.st_ino; + + log_debug("Cleanup threshold for %s \"%s\" is %s", + mountpoint ? "mount point" : "directory", + instance, + format_timestamp_us(timestamp, sizeof(timestamp), cutoff)); + + return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint, + MAX_DEPTH, i->keep_first_level); +} + +static int clean_item(Item *i) { + assert(i); + + log_debug("Running clean action for entry %c %s", (char) i->type, i->path); + + switch (i->type) { + case CREATE_DIRECTORY: + case CREATE_SUBVOLUME: + case CREATE_SUBVOLUME_INHERIT_QUOTA: + case CREATE_SUBVOLUME_NEW_QUOTA: + case TRUNCATE_DIRECTORY: + case IGNORE_PATH: + case COPY_FILES: + clean_item_instance(i, i->path); + return 0; + case EMPTY_DIRECTORY: + case IGNORE_DIRECTORY_PATH: + return glob_item(i, clean_item_instance); + default: + return 0; + } +} + +static int process_item(Item *i, OperationMask operation) { + OperationMask todo; + int r, q, p; + + assert(i); + + todo = operation & ~i->done; + if (todo == 0) /* Everything already done? */ + return 0; + + i->done |= operation; + + r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL, NULL); + if (r == -EREMOTE) { + log_notice_errno(r, "Skipping %s", i->path); + return 0; + } + if (r < 0) + log_debug_errno(r, "Failed to determine whether '%s' is below autofs, ignoring: %m", i->path); + + r = FLAGS_SET(operation, OPERATION_CREATE) ? create_item(i) : 0; + /* Failure can only be tolerated for create */ + if (i->allow_failure) + r = 0; + + q = FLAGS_SET(operation, OPERATION_REMOVE) ? remove_item(i) : 0; + p = FLAGS_SET(operation, OPERATION_CLEAN) ? clean_item(i) : 0; + + return r < 0 ? r : + q < 0 ? q : + p; +} + +static int process_item_array(ItemArray *array, OperationMask operation) { + int r = 0; + size_t n; + + assert(array); + + /* Create any parent first. */ + if (FLAGS_SET(operation, OPERATION_CREATE) && array->parent) + r = process_item_array(array->parent, operation & OPERATION_CREATE); + + /* Clean up all children first */ + if ((operation & (OPERATION_REMOVE|OPERATION_CLEAN)) && !set_isempty(array->children)) { + Iterator i; + ItemArray *c; + + SET_FOREACH(c, array->children, i) { + int k; + + k = process_item_array(c, operation & (OPERATION_REMOVE|OPERATION_CLEAN)); + if (k < 0 && r == 0) + r = k; + } + } + + for (n = 0; n < array->n_items; n++) { + int k; + + k = process_item(array->items + n, operation); + if (k < 0 && r == 0) + r = k; + } + + return r; +} + +static void item_free_contents(Item *i) { + assert(i); + free(i->path); + free(i->argument); + strv_free(i->xattrs); + +#if HAVE_ACL + acl_free(i->acl_access); + acl_free(i->acl_default); +#endif +} + +static ItemArray* item_array_free(ItemArray *a) { + size_t n; + + if (!a) + return NULL; + + for (n = 0; n < a->n_items; n++) + item_free_contents(a->items + n); + + set_free(a->children); + free(a->items); + return mfree(a); +} + +static int item_compare(const Item *a, const Item *b) { + /* Make sure that the ownership taking item is put first, so + * that we first create the node, and then can adjust it */ + + if (takes_ownership(a->type) && !takes_ownership(b->type)) + return -1; + if (!takes_ownership(a->type) && takes_ownership(b->type)) + return 1; + + return CMP(a->type, b->type); +} + +static bool item_compatible(Item *a, Item *b) { + assert(a); + assert(b); + assert(streq(a->path, b->path)); + + if (takes_ownership(a->type) && takes_ownership(b->type)) + /* check if the items are the same */ + return streq_ptr(a->argument, b->argument) && + + a->uid_set == b->uid_set && + a->uid == b->uid && + + a->gid_set == b->gid_set && + a->gid == b->gid && + + a->mode_set == b->mode_set && + a->mode == b->mode && + + a->age_set == b->age_set && + a->age == b->age && + + a->mask_perms == b->mask_perms && + + a->keep_first_level == b->keep_first_level && + + a->major_minor == b->major_minor; + + return true; +} + +static bool should_include_path(const char *path) { + char **prefix; + + STRV_FOREACH(prefix, arg_exclude_prefixes) + if (path_startswith(path, *prefix)) { + log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.", + path, *prefix); + return false; + } + + STRV_FOREACH(prefix, arg_include_prefixes) + if (path_startswith(path, *prefix)) { + log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix); + return true; + } + + /* no matches, so we should include this path only if we + * have no whitelist at all */ + if (strv_isempty(arg_include_prefixes)) + return true; + + log_debug("Entry \"%s\" does not match any include prefix, skipping.", path); + return false; +} + +static int specifier_expansion_from_arg(Item *i) { + _cleanup_free_ char *unescaped = NULL, *resolved = NULL; + char **xattr; + int r; + + assert(i); + + if (!i->argument) + return 0; + + switch (i->type) { + case COPY_FILES: + case CREATE_SYMLINK: + case CREATE_FILE: + case TRUNCATE_FILE: + case WRITE_FILE: + r = cunescape(i->argument, 0, &unescaped); + if (r < 0) + return log_error_errno(r, "Failed to unescape parameter to write: %s", i->argument); + + r = specifier_printf(unescaped, specifier_table, NULL, &resolved); + if (r < 0) + return r; + + free_and_replace(i->argument, resolved); + break; + + case SET_XATTR: + case RECURSIVE_SET_XATTR: + assert(i->xattrs); + + STRV_FOREACH (xattr, i->xattrs) { + r = specifier_printf(*xattr, specifier_table, NULL, &resolved); + if (r < 0) + return r; + + free_and_replace(*xattr, resolved); + } + break; + + default: + break; + } + return 0; +} + +static int patch_var_run(const char *fname, unsigned line, char **path) { + const char *k; + char *n; + + assert(path); + assert(*path); + + /* Optionally rewrites lines referencing /var/run/, to use /run/ instead. Why bother? tmpfiles merges lines in + * some cases and detects conflicts in others. If files/directories are specified through two equivalent lines + * this is problematic as neither case will be detected. Ideally we'd detect these cases by resolving symlinks + * early, but that's precisely not what we can do here as this code very likely is running very early on, at a + * time where the paths in question are not available yet, or even more importantly, our own tmpfiles rules + * might create the paths that are intermediary to the listed paths. We can't really cover the generic case, + * but the least we can do is cover the specific case of /var/run vs. /run, as /var/run is a legacy name for + * /run only, and we explicitly document that and require that on systemd systems the former is a symlink to + * the latter. Moreover files below this path are by far the primary usecase for tmpfiles.d/. */ + + k = path_startswith(*path, "/var/run/"); + if (isempty(k)) /* Don't complain about other paths than /var/run, and not about /var/run itself either. */ + return 0; + + n = path_join("/run", k); + if (!n) + return log_oom(); + + /* Also log about this briefly. We do so at LOG_NOTICE level, as we fixed up the situation automatically, hence + * there's no immediate need for action by the user. However, in the interest of making things less confusing + * to the user, let's still inform the user that these snippets should really be updated. */ + log_syntax(NULL, LOG_NOTICE, fname, line, 0, "Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.", *path, n); + + free_and_replace(*path, n); + + return 0; +} + +static int parse_line(const char *fname, unsigned line, const char *buffer, bool *invalid_config) { + + _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL; + _cleanup_(item_free_contents) Item i = {}; + ItemArray *existing; + OrderedHashmap *h; + int r, pos; + bool append_or_force = false, boot = false, allow_failure = false; + + assert(fname); + assert(line >= 1); + assert(buffer); + + r = extract_many_words( + &buffer, + NULL, + EXTRACT_UNQUOTE, + &action, + &path, + &mode, + &user, + &group, + &age, + NULL); + if (r < 0) { + if (IN_SET(r, -EINVAL, -EBADSLT)) + /* invalid quoting and such or an unknown specifier */ + *invalid_config = true; + return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line); + } else if (r < 2) { + *invalid_config = true; + log_error("[%s:%u] Syntax error.", fname, line); + return -EIO; + } + + if (!empty_or_dash(buffer)) { + i.argument = strdup(buffer); + if (!i.argument) + return log_oom(); + } + + if (isempty(action)) { + *invalid_config = true; + log_error("[%s:%u] Command too short '%s'.", fname, line, action); + return -EINVAL; + } + + for (pos = 1; action[pos]; pos++) { + if (action[pos] == '!' && !boot) + boot = true; + else if (action[pos] == '+' && !append_or_force) + append_or_force = true; + else if (action[pos] == '-' && !allow_failure) + allow_failure = true; + else { + *invalid_config = true; + log_error("[%s:%u] Unknown modifiers in command '%s'", + fname, line, action); + return -EINVAL; + } + } + + if (boot && !arg_boot) { + log_debug("Ignoring entry %s \"%s\" because --boot is not specified.", + action, path); + return 0; + } + + i.type = action[0]; + i.append_or_force = append_or_force; + i.allow_failure = allow_failure; + + r = specifier_printf(path, specifier_table, NULL, &i.path); + if (r == -ENXIO) + return log_unresolvable_specifier(fname, line); + if (r < 0) { + if (IN_SET(r, -EINVAL, -EBADSLT)) + *invalid_config = true; + return log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, path); + } + + r = patch_var_run(fname, line, &i.path); + if (r < 0) + return r; + + switch (i.type) { + + case CREATE_DIRECTORY: + case CREATE_SUBVOLUME: + case CREATE_SUBVOLUME_INHERIT_QUOTA: + case CREATE_SUBVOLUME_NEW_QUOTA: + case EMPTY_DIRECTORY: + case TRUNCATE_DIRECTORY: + case CREATE_FIFO: + case IGNORE_PATH: + case IGNORE_DIRECTORY_PATH: + case REMOVE_PATH: + case RECURSIVE_REMOVE_PATH: + case ADJUST_MODE: + case RELABEL_PATH: + case RECURSIVE_RELABEL_PATH: + if (i.argument) + log_warning("[%s:%u] %c lines don't take argument fields, ignoring.", fname, line, i.type); + + break; + + case CREATE_FILE: + case TRUNCATE_FILE: + break; + + case CREATE_SYMLINK: + if (!i.argument) { + i.argument = path_join("/usr/share/factory", i.path); + if (!i.argument) + return log_oom(); + } + break; + + case WRITE_FILE: + if (!i.argument) { + *invalid_config = true; + log_error("[%s:%u] Write file requires argument.", fname, line); + return -EBADMSG; + } + break; + + case COPY_FILES: + if (!i.argument) { + i.argument = path_join(arg_root, "/usr/share/factory", i.path); + if (!i.argument) + return log_oom(); + + } else if (!path_is_absolute(i.argument)) { + *invalid_config = true; + log_error("[%s:%u] Source path is not absolute.", fname, line); + return -EBADMSG; + + } else if (arg_root) { + char *p; + + p = path_join(arg_root, i.argument); + if (!p) + return log_oom(); + free_and_replace(i.argument, p); + } + + path_simplify(i.argument, false); + break; + + case CREATE_CHAR_DEVICE: + case CREATE_BLOCK_DEVICE: + if (!i.argument) { + *invalid_config = true; + log_error("[%s:%u] Device file requires argument.", fname, line); + return -EBADMSG; + } + + r = parse_dev(i.argument, &i.major_minor); + if (r < 0) { + *invalid_config = true; + log_error_errno(r, "[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument); + return -EBADMSG; + } + + break; + + case SET_XATTR: + case RECURSIVE_SET_XATTR: + if (!i.argument) { + *invalid_config = true; + log_error("[%s:%u] Set extended attribute requires argument.", fname, line); + return -EBADMSG; + } + r = parse_xattrs_from_arg(&i); + if (r < 0) + return r; + break; + + case SET_ACL: + case RECURSIVE_SET_ACL: + if (!i.argument) { + *invalid_config = true; + log_error("[%s:%u] Set ACLs requires argument.", fname, line); + return -EBADMSG; + } + r = parse_acls_from_arg(&i); + if (r < 0) + return r; + break; + + case SET_ATTRIBUTE: + case RECURSIVE_SET_ATTRIBUTE: + if (!i.argument) { + *invalid_config = true; + log_error("[%s:%u] Set file attribute requires argument.", fname, line); + return -EBADMSG; + } + r = parse_attribute_from_arg(&i); + if (IN_SET(r, -EINVAL, -EBADSLT)) + *invalid_config = true; + if (r < 0) + return r; + break; + + default: + log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type); + *invalid_config = true; + return -EBADMSG; + } + + if (!path_is_absolute(i.path)) { + log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path); + *invalid_config = true; + return -EBADMSG; + } + + path_simplify(i.path, false); + + if (!should_include_path(i.path)) + return 0; + + r = specifier_expansion_from_arg(&i); + if (r == -ENXIO) + return log_unresolvable_specifier(fname, line); + if (r < 0) { + if (IN_SET(r, -EINVAL, -EBADSLT)) + *invalid_config = true; + return log_error_errno(r, "[%s:%u] Failed to substitute specifiers in argument: %m", + fname, line); + } + + if (arg_root) { + char *p; + + p = path_join(arg_root, i.path); + if (!p) + return log_oom(); + free_and_replace(i.path, p); + } + + if (!empty_or_dash(user)) { + const char *u = user; + + r = get_user_creds(&u, &i.uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); + if (r < 0) { + *invalid_config = true; + return log_error_errno(r, "[%s:%u] Unknown user '%s'.", fname, line, user); + } + + i.uid_set = true; + } + + if (!empty_or_dash(group)) { + const char *g = group; + + r = get_group_creds(&g, &i.gid, USER_CREDS_ALLOW_MISSING); + if (r < 0) { + *invalid_config = true; + log_error("[%s:%u] Unknown group '%s'.", fname, line, group); + return r; + } + + i.gid_set = true; + } + + if (!empty_or_dash(mode)) { + const char *mm = mode; + unsigned m; + + if (*mm == '~') { + i.mask_perms = true; + mm++; + } + + if (parse_mode(mm, &m) < 0) { + *invalid_config = true; + log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode); + return -EBADMSG; + } + + i.mode = m; + i.mode_set = true; + } else + i.mode = IN_SET(i.type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA) ? 0755 : 0644; + + if (!empty_or_dash(age)) { + const char *a = age; + + if (*a == '~') { + i.keep_first_level = true; + a++; + } + + if (parse_sec(a, &i.age) < 0) { + *invalid_config = true; + log_error("[%s:%u] Invalid age '%s'.", fname, line, age); + return -EBADMSG; + } + + i.age_set = true; + } + + h = needs_glob(i.type) ? globs : items; + + existing = ordered_hashmap_get(h, i.path); + if (existing) { + size_t n; + + for (n = 0; n < existing->n_items; n++) { + if (!item_compatible(existing->items + n, &i) && !i.append_or_force) { + log_notice("[%s:%u] Duplicate line for path \"%s\", ignoring.", + fname, line, i.path); + return 0; + } + } + } else { + existing = new0(ItemArray, 1); + if (!existing) + return log_oom(); + + r = ordered_hashmap_put(h, i.path, existing); + if (r < 0) { + free(existing); + return log_oom(); + } + } + + if (!GREEDY_REALLOC(existing->items, existing->allocated, existing->n_items + 1)) + return log_oom(); + + existing->items[existing->n_items++] = i; + i = (struct Item) {}; + + /* Sort item array, to enforce stable ordering of application */ + typesafe_qsort(existing->items, existing->n_items, item_compare); + + return 0; +} + +static int cat_config(char **config_dirs, char **args) { + _cleanup_strv_free_ char **files = NULL; + int r; + + r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, NULL); + if (r < 0) + return r; + + return cat_files(NULL, files, 0); +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-tmpfiles", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n" + "Creates, deletes and cleans up volatile and temporary files and directories.\n\n" + " -h --help Show this help\n" + " --user Execute user configuration\n" + " --version Show package version\n" + " --cat-config Show configuration files\n" + " --create Create marked files/directories\n" + " --clean Clean up marked directories\n" + " --remove Remove marked files/directories\n" + " --boot Execute actions only safe at boot\n" + " --prefix=PATH Only apply rules with the specified prefix\n" + " --exclude-prefix=PATH Ignore rules with the specified prefix\n" + " --root=PATH Operate on an alternate filesystem root\n" + " --replace=PATH Treat arguments as replacement for PATH\n" + " --no-pager Do not pipe output into a pager\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_CAT_CONFIG, + ARG_USER, + ARG_CREATE, + ARG_CLEAN, + ARG_REMOVE, + ARG_BOOT, + ARG_PREFIX, + ARG_EXCLUDE_PREFIX, + ARG_ROOT, + ARG_REPLACE, + ARG_NO_PAGER, + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "user", no_argument, NULL, ARG_USER }, + { "version", no_argument, NULL, ARG_VERSION }, + { "cat-config", no_argument, NULL, ARG_CAT_CONFIG }, + { "create", no_argument, NULL, ARG_CREATE }, + { "clean", no_argument, NULL, ARG_CLEAN }, + { "remove", no_argument, NULL, ARG_REMOVE }, + { "boot", no_argument, NULL, ARG_BOOT }, + { "prefix", required_argument, NULL, ARG_PREFIX }, + { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX }, + { "root", required_argument, NULL, ARG_ROOT }, + { "replace", required_argument, NULL, ARG_REPLACE }, + { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_CAT_CONFIG: + arg_cat_config = true; + break; + + case ARG_USER: + arg_user = true; + break; + + case ARG_CREATE: + arg_operation |= OPERATION_CREATE; + break; + + case ARG_CLEAN: + arg_operation |= OPERATION_CLEAN; + break; + + case ARG_REMOVE: + arg_operation |= OPERATION_REMOVE; + break; + + case ARG_BOOT: + arg_boot = true; + break; + + case ARG_PREFIX: + if (strv_push(&arg_include_prefixes, optarg) < 0) + return log_oom(); + break; + + case ARG_EXCLUDE_PREFIX: + if (strv_push(&arg_exclude_prefixes, optarg) < 0) + return log_oom(); + break; + + case ARG_ROOT: + r = parse_path_argument_and_warn(optarg, true, &arg_root); + if (r < 0) + return r; + break; + + case ARG_REPLACE: + if (!path_is_absolute(optarg) || + !endswith(optarg, ".conf")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "The argument to --replace= must an absolute path to a config file"); + + arg_replace = optarg; + break; + + case ARG_NO_PAGER: + arg_pager_flags |= PAGER_DISABLE; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (arg_operation == 0 && !arg_cat_config) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "You need to specify at least one of --clean, --create or --remove."); + + if (arg_replace && arg_cat_config) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Option --replace= is not supported with --cat-config"); + + if (arg_replace && optind >= argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "When --replace= is given, some configuration items must be specified"); + + return 1; +} + +static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoent, bool *invalid_config) { + _cleanup_fclose_ FILE *_f = NULL; + Iterator iterator; + unsigned v = 0; + FILE *f; + Item *i; + int r = 0; + + assert(fn); + + if (streq(fn, "-")) { + log_debug("Reading config from stdin…"); + fn = ""; + f = stdin; + } else { + r = search_and_fopen(fn, "re", arg_root, (const char**) config_dirs, &_f); + if (r < 0) { + if (ignore_enoent && r == -ENOENT) { + log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn); + return 0; + } + + return log_error_errno(r, "Failed to open '%s': %m", fn); + } + log_debug("Reading config file \"%s\"…", fn); + f = _f; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + bool invalid_line = false; + char *l; + int k; + + k = read_line(f, LONG_LINE_MAX, &line); + if (k < 0) + return log_error_errno(k, "Failed to read '%s': %m", fn); + if (k == 0) + break; + + v++; + + l = strstrip(line); + if (IN_SET(*l, 0, '#')) + continue; + + k = parse_line(fn, v, l, &invalid_line); + if (k < 0) { + if (invalid_line) + /* Allow reporting with a special code if the caller requested this */ + *invalid_config = true; + else if (r == 0) + /* The first error becomes our return value */ + r = k; + } + } + + /* we have to determine age parameter for each entry of type X */ + ORDERED_HASHMAP_FOREACH(i, globs, iterator) { + Iterator iter; + Item *j, *candidate_item = NULL; + + if (i->type != IGNORE_DIRECTORY_PATH) + continue; + + ORDERED_HASHMAP_FOREACH(j, items, iter) { + if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) + continue; + + if (path_equal(j->path, i->path)) { + candidate_item = j; + break; + } + + if ((!candidate_item && path_startswith(i->path, j->path)) || + (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0))) + candidate_item = j; + } + + if (candidate_item && candidate_item->age_set) { + i->age = candidate_item->age; + i->age_set = true; + } + } + + if (ferror(f)) { + log_error_errno(errno, "Failed to read from file %s: %m", fn); + if (r == 0) + r = -EIO; + } + + return r; +} + +static int parse_arguments(char **config_dirs, char **args, bool *invalid_config) { + char **arg; + int r; + + STRV_FOREACH(arg, args) { + r = read_config_file(config_dirs, *arg, false, invalid_config); + if (r < 0) + return r; + } + + return 0; +} + +static int read_config_files(char **config_dirs, char **args, bool *invalid_config) { + _cleanup_strv_free_ char **files = NULL; + _cleanup_free_ char *p = NULL; + char **f; + int r; + + r = conf_files_list_with_replacement(arg_root, config_dirs, arg_replace, &files, &p); + if (r < 0) + return r; + + STRV_FOREACH(f, files) + if (p && path_equal(*f, p)) { + log_debug("Parsing arguments at position \"%s\"…", *f); + + r = parse_arguments(config_dirs, args, invalid_config); + if (r < 0) + return r; + } else + /* Just warn, ignore result otherwise. + * read_config_file() has some debug output, so no need to print anything. */ + (void) read_config_file(config_dirs, *f, true, invalid_config); + + return 0; +} + +static int link_parent(ItemArray *a) { + const char *path; + char *prefix; + int r; + + assert(a); + + /* Finds the closest "parent" item array for the specified item array. Then registers the specified item array + * as child of it, and fills the parent in, linking them both ways. This allows us to later create parents + * before their children, and clean up/remove children before their parents. */ + + if (a->n_items <= 0) + return 0; + + path = a->items[0].path; + prefix = newa(char, strlen(path) + 1); + PATH_FOREACH_PREFIX(prefix, path) { + ItemArray *j; + + j = ordered_hashmap_get(items, prefix); + if (!j) + j = ordered_hashmap_get(globs, prefix); + if (j) { + r = set_ensure_allocated(&j->children, NULL); + if (r < 0) + return log_oom(); + + r = set_put(j->children, a); + if (r < 0) + return log_oom(); + + a->parent = j; + return 1; + } + } + + return 0; +} + +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(item_array_hash_ops, char, string_hash_func, string_compare_func, + ItemArray, item_array_free); + +static int run(int argc, char *argv[]) { + _cleanup_strv_free_ char **config_dirs = NULL; + bool invalid_config = false; + Iterator iterator; + ItemArray *a; + enum { + PHASE_REMOVE_AND_CLEAN, + PHASE_CREATE, + _PHASE_MAX + } phase; + int r, k; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + log_setup_service(); + + /* Descending down file system trees might take a lot of fds */ + (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); + + if (arg_user) { + r = user_config_paths(&config_dirs); + if (r < 0) + return log_error_errno(r, "Failed to initialize configuration directory list: %m"); + } else { + config_dirs = strv_split_nulstr(CONF_PATHS_NULSTR("tmpfiles.d")); + if (!config_dirs) + return log_oom(); + } + + if (DEBUG_LOGGING) { + _cleanup_free_ char *t = NULL; + + t = strv_join(config_dirs, "\n\t"); + if (t) + log_debug("Looking for configuration files in (higher priority first):\n\t%s", t); + } + + if (arg_cat_config) { + (void) pager_open(arg_pager_flags); + + return cat_config(config_dirs, argv + optind); + } + + umask(0022); + + mac_selinux_init(); + + items = ordered_hashmap_new(&item_array_hash_ops); + globs = ordered_hashmap_new(&item_array_hash_ops); + if (!items || !globs) + return log_oom(); + + /* If command line arguments are specified along with --replace, read all + * configuration files and insert the positional arguments at the specified + * place. Otherwise, if command line arguments are specified, execute just + * them, and finally, without --replace= or any positional arguments, just + * read configuration and execute it. + */ + if (arg_replace || optind >= argc) + r = read_config_files(config_dirs, argv + optind, &invalid_config); + else + r = parse_arguments(config_dirs, argv + optind, &invalid_config); + if (r < 0) + return r; + + /* Let's now link up all child/parent relationships */ + ORDERED_HASHMAP_FOREACH(a, items, iterator) { + r = link_parent(a); + if (r < 0) + return r; + } + ORDERED_HASHMAP_FOREACH(a, globs, iterator) { + r = link_parent(a); + if (r < 0) + return r; + } + + /* If multiple operations are requested, let's first run the remove/clean operations, and only then the create + * operations. i.e. that we first clean out the platform we then build on. */ + for (phase = 0; phase < _PHASE_MAX; phase++) { + OperationMask op; + + if (phase == PHASE_REMOVE_AND_CLEAN) + op = arg_operation & (OPERATION_REMOVE|OPERATION_CLEAN); + else if (phase == PHASE_CREATE) + op = arg_operation & OPERATION_CREATE; + else + assert_not_reached("unexpected phase"); + + if (op == 0) /* Nothing requested in this phase */ + continue; + + /* The non-globbing ones usually create things, hence we apply them first */ + ORDERED_HASHMAP_FOREACH(a, items, iterator) { + k = process_item_array(a, op); + if (k < 0 && r >= 0) + r = k; + } + + /* The globbing ones usually alter things, hence we apply them second. */ + ORDERED_HASHMAP_FOREACH(a, globs, iterator) { + k = process_item_array(a, op); + if (k < 0 && r >= 0) + r = k; + } + } + + if (ERRNO_IS_RESOURCE(-r)) + return r; + if (invalid_config) + return EX_DATAERR; + if (r < 0) + return EX_CANTCREAT; + return 0; +} + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c new file mode 100644 index 00000000..784dd0df --- /dev/null +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -0,0 +1,711 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2015 Werner Fink +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "ask-password-api.h" +#include "conf-parser.h" +#include "def.h" +#include "dirent-util.h" +#include "exit-status.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hashmap.h" +#include "io-util.h" +#include "macro.h" +#include "main-func.h" +#include "memory-util.h" +#include "mkdir.h" +#include "path-util.h" +#include "pretty-print.h" +#include "process-util.h" +#include "set.h" +#include "signal-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "utmp-wtmp.h" + +static enum { + ACTION_LIST, + ACTION_QUERY, + ACTION_WATCH, + ACTION_WALL +} arg_action = ACTION_QUERY; + +static bool arg_plymouth = false; +static bool arg_console = false; +static const char *arg_device = NULL; + +static int send_passwords(const char *socket_name, char **passwords) { + _cleanup_(erase_and_freep) char *packet = NULL; + _cleanup_close_ int socket_fd = -1; + union sockaddr_union sa = {}; + size_t packet_length = 1; + char **p, *d; + ssize_t n; + int salen; + + assert(socket_name); + + salen = sockaddr_un_set_path(&sa.un, socket_name); + if (salen < 0) + return salen; + + STRV_FOREACH(p, passwords) + packet_length += strlen(*p) + 1; + + packet = new(char, packet_length); + if (!packet) + return -ENOMEM; + + packet[0] = '+'; + + d = packet + 1; + STRV_FOREACH(p, passwords) + d = stpcpy(d, *p) + 1; + + socket_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (socket_fd < 0) + return log_debug_errno(errno, "socket(): %m"); + + n = sendto(socket_fd, packet, packet_length, MSG_NOSIGNAL, &sa.sa, salen); + if (n < 0) + return log_debug_errno(errno, "sendto(): %m"); + + return (int) n; +} + +static bool wall_tty_match(const char *path, void *userdata) { + _cleanup_free_ char *p = NULL; + _cleanup_close_ int fd = -1; + struct stat st; + + if (!path_is_absolute(path)) + path = strjoina("/dev/", path); + + if (lstat(path, &st) < 0) { + log_debug_errno(errno, "Failed to stat %s: %m", path); + return true; + } + + if (!S_ISCHR(st.st_mode)) { + log_debug("%s is not a character device.", path); + return true; + } + + /* We use named pipes to ensure that wall messages suggesting + * password entry are not printed over password prompts + * already shown. We use the fact here that opening a pipe in + * non-blocking mode for write-only will succeed only if + * there's some writer behind it. Using pipes has the + * advantage that the block will automatically go away if the + * process dies. */ + + if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0) { + log_oom(); + return true; + } + + fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (fd < 0) { + log_debug_errno(errno, "Failed to open the wall pipe: %m"); + return 1; + } + + /* What, we managed to open the pipe? Then this tty is filtered. */ + return 0; +} + +static int agent_ask_password_tty( + const char *message, + usec_t until, + AskPasswordFlags flags, + const char *flag_file, + char ***ret) { + + int tty_fd = -1; + int r; + + if (arg_console) { + const char *con = arg_device ?: "/dev/console"; + + tty_fd = acquire_terminal(con, ACQUIRE_TERMINAL_WAIT, USEC_INFINITY); + if (tty_fd < 0) + return log_error_errno(tty_fd, "Failed to acquire %s: %m", con); + + r = reset_terminal_fd(tty_fd, true); + if (r < 0) + log_warning_errno(r, "Failed to reset terminal, ignoring: %m"); + + } + + r = ask_password_tty(tty_fd, message, NULL, until, flags, flag_file, ret); + + if (arg_console) { + tty_fd = safe_close(tty_fd); + release_terminal(); + } + + return 0; +} + +static int process_one_password_file(const char *filename) { + _cleanup_free_ char *socket_name = NULL, *message = NULL; + bool accept_cached = false, echo = false; + uint64_t not_after = 0; + unsigned pid = 0; + + const ConfigTableItem items[] = { + { "Ask", "Socket", config_parse_string, 0, &socket_name }, + { "Ask", "NotAfter", config_parse_uint64, 0, ¬_after }, + { "Ask", "Message", config_parse_string, 0, &message }, + { "Ask", "PID", config_parse_unsigned, 0, &pid }, + { "Ask", "AcceptCached", config_parse_bool, 0, &accept_cached }, + { "Ask", "Echo", config_parse_bool, 0, &echo }, + {} + }; + + int r; + + assert(filename); + + r = config_parse(NULL, filename, NULL, + NULL, + config_item_table_lookup, items, + CONFIG_PARSE_RELAXED|CONFIG_PARSE_WARN, NULL); + if (r < 0) + return r; + + if (!socket_name) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), + "Invalid password file %s", filename); + + if (not_after > 0 && now(CLOCK_MONOTONIC) > not_after) + return 0; + + if (pid > 0 && !pid_is_alive(pid)) + return 0; + + switch (arg_action) { + case ACTION_LIST: + printf("'%s' (PID %u)\n", message, pid); + return 0; + + case ACTION_WALL: { + _cleanup_free_ char *wall = NULL; + + if (asprintf(&wall, + "Password entry required for \'%s\' (PID %u).\r\n" + "Please enter password with the systemd-tty-ask-password-agent tool.", + message, + pid) < 0) + return log_oom(); + + (void) utmp_wall(wall, NULL, NULL, wall_tty_match, NULL); + return 0; + } + case ACTION_QUERY: + case ACTION_WATCH: { + _cleanup_strv_free_erase_ char **passwords = NULL; + AskPasswordFlags flags = 0; + + if (access(socket_name, W_OK) < 0) { + if (arg_action == ACTION_QUERY) + log_info("Not querying '%s' (PID %u), lacking privileges.", message, pid); + + return 0; + } + + SET_FLAG(flags, ASK_PASSWORD_ACCEPT_CACHED, accept_cached); + SET_FLAG(flags, ASK_PASSWORD_CONSOLE_COLOR, arg_console); + SET_FLAG(flags, ASK_PASSWORD_ECHO, echo); + + if (arg_plymouth) + r = ask_password_plymouth(message, not_after, flags, filename, &passwords); + else + r = agent_ask_password_tty(message, not_after, flags, filename, &passwords); + + if (r < 0) { + /* If the query went away, that's OK */ + if (IN_SET(r, -ETIME, -ENOENT)) + return 0; + + return log_error_errno(r, "Failed to query password: %m"); + } + + if (strv_isempty(passwords)) + return -ECANCELED; + + r = send_passwords(socket_name, passwords); + if (r < 0) + return log_error_errno(r, "Failed to send: %m"); + break; + } + } + + return 0; +} + +static int wall_tty_block(void) { + _cleanup_free_ char *p = NULL; + dev_t devnr; + int fd, r; + + r = get_ctty_devnr(0, &devnr); + if (r == -ENXIO) /* We have no controlling tty */ + return -ENOTTY; + if (r < 0) + return log_error_errno(r, "Failed to get controlling TTY: %m"); + + if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(devnr), minor(devnr)) < 0) + return log_oom(); + + (void) mkdir_parents_label(p, 0700); + (void) mkfifo(p, 0600); + + fd = open(p, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (fd < 0) + return log_debug_errno(errno, "Failed to open %s: %m", p); + + return fd; +} + +static int process_password_files(void) { + _cleanup_closedir_ DIR *d; + struct dirent *de; + int r = 0; + + d = opendir("/run/systemd/ask-password"); + if (!d) { + if (errno == ENOENT) + return 0; + + return log_error_errno(errno, "Failed to open /run/systemd/ask-password: %m"); + } + + FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read directory: %m")) { + _cleanup_free_ char *p = NULL; + int q; + + /* We only support /run on tmpfs, hence we can rely on + * d_type to be reliable */ + + if (de->d_type != DT_REG) + continue; + + if (!startswith(de->d_name, "ask.")) + continue; + + p = path_join("/run/systemd/ask-password", de->d_name); + if (!p) + return log_oom(); + + q = process_one_password_file(p); + if (q < 0 && r == 0) + r = q; + } + + return r; +} + +static int process_and_watch_password_files(bool watch) { + enum { + FD_SIGNAL, + FD_INOTIFY, + _FD_MAX + }; + + _cleanup_close_ int notify = -1, signal_fd = -1, tty_block_fd = -1; + struct pollfd pollfd[_FD_MAX]; + sigset_t mask; + int r; + + tty_block_fd = wall_tty_block(); + + (void) mkdir_p_label("/run/systemd/ask-password", 0755); + + assert_se(sigemptyset(&mask) >= 0); + assert_se(sigset_add_many(&mask, SIGTERM, -1) >= 0); + assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) >= 0); + + if (watch) { + signal_fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); + if (signal_fd < 0) + return log_error_errno(errno, "Failed to allocate signal file descriptor: %m"); + + pollfd[FD_SIGNAL] = (struct pollfd) { .fd = signal_fd, .events = POLLIN }; + + notify = inotify_init1(IN_CLOEXEC); + if (notify < 0) + return log_error_errno(errno, "Failed to allocate directory watch: %m"); + + r = inotify_add_watch_and_warn(notify, "/run/systemd/ask-password", IN_CLOSE_WRITE|IN_MOVED_TO); + if (r < 0) + return r; + + pollfd[FD_INOTIFY] = (struct pollfd) { .fd = notify, .events = POLLIN }; + } + + for (;;) { + int timeout = -1; + + r = process_password_files(); + if (r < 0) { + if (r == -ECANCELED) + /* Disable poll() timeout since at least one password has + * been skipped and therefore one file remains and is + * unlikely to trigger any events. */ + timeout = 0; + else + /* FIXME: we should do something here since otherwise the service + * requesting the password won't notice the error and will wait + * indefinitely. */ + log_error_errno(r, "Failed to process password: %m"); + } + + if (!watch) + break; + + if (poll(pollfd, _FD_MAX, timeout) < 0) { + if (errno == EINTR) + continue; + + return -errno; + } + + if (pollfd[FD_INOTIFY].revents != 0) + (void) flush_fd(notify); + + if (pollfd[FD_SIGNAL].revents != 0) + break; + } + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-tty-ask-password-agent", "1", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n\n" + "Process system password requests.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --list Show pending password requests\n" + " --query Process pending password requests\n" + " --watch Continuously process password requests\n" + " --wall Continuously forward password requests to wall\n" + " --plymouth Ask question with Plymouth instead of on TTY\n" + " --console Ask question on /dev/console instead of current TTY\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_LIST = 0x100, + ARG_QUERY, + ARG_WATCH, + ARG_WALL, + ARG_PLYMOUTH, + ARG_CONSOLE, + ARG_VERSION + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "list", no_argument, NULL, ARG_LIST }, + { "query", no_argument, NULL, ARG_QUERY }, + { "watch", no_argument, NULL, ARG_WATCH }, + { "wall", no_argument, NULL, ARG_WALL }, + { "plymouth", no_argument, NULL, ARG_PLYMOUTH }, + { "console", optional_argument, NULL, ARG_CONSOLE }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + return version(); + + case ARG_LIST: + arg_action = ACTION_LIST; + break; + + case ARG_QUERY: + arg_action = ACTION_QUERY; + break; + + case ARG_WATCH: + arg_action = ACTION_WATCH; + break; + + case ARG_WALL: + arg_action = ACTION_WALL; + break; + + case ARG_PLYMOUTH: + arg_plymouth = true; + break; + + case ARG_CONSOLE: + arg_console = true; + if (optarg) { + + if (isempty(optarg)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Empty console device path is not allowed."); + + arg_device = optarg; + } + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + if (optind != argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s takes no arguments.", program_invocation_short_name); + + if (arg_plymouth || arg_console) { + + if (!IN_SET(arg_action, ACTION_QUERY, ACTION_WATCH)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Options --query and --watch conflict."); + + if (arg_plymouth && arg_console) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Options --plymouth and --console conflict."); + } + + return 1; +} + +/* + * To be able to ask on all terminal devices of /dev/console the devices are collected. If more than one + * device is found, then on each of the terminals a inquiring task is forked. Every task has its own session + * and its own controlling terminal. If one of the tasks does handle a password, the remaining tasks will be + * terminated. + */ +static int ask_on_this_console(const char *tty, pid_t *ret_pid, char **arguments) { + static const struct sigaction sigchld = { + .sa_handler = nop_signal_handler, + .sa_flags = SA_NOCLDSTOP | SA_RESTART, + }; + static const struct sigaction sighup = { + .sa_handler = SIG_DFL, + .sa_flags = SA_RESTART, + }; + int r; + + assert_se(sigaction(SIGCHLD, &sigchld, NULL) >= 0); + assert_se(sigaction(SIGHUP, &sighup, NULL) >= 0); + assert_se(sigprocmask_many(SIG_UNBLOCK, NULL, SIGHUP, SIGCHLD, -1) >= 0); + + r = safe_fork("(sd-passwd)", FORK_RESET_SIGNALS|FORK_LOG, ret_pid); + if (r < 0) + return r; + if (r == 0) { + char **i; + + assert_se(prctl(PR_SET_PDEATHSIG, SIGHUP) >= 0); + + STRV_FOREACH(i, arguments) { + char *k; + + if (!streq(*i, "--console")) + continue; + + k = strjoin("--console=", tty); + if (!k) { + log_oom(); + _exit(EXIT_FAILURE); + } + + free_and_replace(*i, k); + } + + execv(SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, arguments); + _exit(EXIT_FAILURE); + } + + return 0; +} + +static void terminate_agents(Set *pids) { + struct timespec ts; + siginfo_t status = {}; + sigset_t set; + Iterator i; + void *p; + int r, signum; + + /* + * Request termination of the remaining processes as those + * are not required anymore. + */ + SET_FOREACH(p, pids, i) + (void) kill(PTR_TO_PID(p), SIGTERM); + + /* + * Collect the processes which have go away. + */ + assert_se(sigemptyset(&set) >= 0); + assert_se(sigaddset(&set, SIGCHLD) >= 0); + timespec_store(&ts, 50 * USEC_PER_MSEC); + + while (!set_isempty(pids)) { + + zero(status); + r = waitid(P_ALL, 0, &status, WEXITED|WNOHANG); + if (r < 0 && errno == EINTR) + continue; + + if (r == 0 && status.si_pid > 0) { + set_remove(pids, PID_TO_PTR(status.si_pid)); + continue; + } + + signum = sigtimedwait(&set, NULL, &ts); + if (signum < 0) { + if (errno != EAGAIN) + log_error_errno(errno, "sigtimedwait() failed: %m"); + break; + } + assert(signum == SIGCHLD); + } + + /* + * Kill hanging processes. + */ + SET_FOREACH(p, pids, i) { + log_warning("Failed to terminate child %d, killing it", PTR_TO_PID(p)); + (void) kill(PTR_TO_PID(p), SIGKILL); + } +} + +static int ask_on_consoles(char *argv[]) { + _cleanup_set_free_ Set *pids = NULL; + _cleanup_strv_free_ char **consoles = NULL, **arguments = NULL; + siginfo_t status = {}; + char **tty; + pid_t pid; + int r; + + r = get_kernel_consoles(&consoles); + if (r < 0) + return log_error_errno(r, "Failed to determine devices of /dev/console: %m"); + + pids = set_new(NULL); + if (!pids) + return log_oom(); + + arguments = strv_copy(argv); + if (!arguments) + return log_oom(); + + /* Start an agent on each console. */ + STRV_FOREACH(tty, consoles) { + r = ask_on_this_console(*tty, &pid, arguments); + if (r < 0) + return r; + + if (set_put(pids, PID_TO_PTR(pid)) < 0) + return log_oom(); + } + + /* Wait for an agent to exit. */ + for (;;) { + zero(status); + + if (waitid(P_ALL, 0, &status, WEXITED) < 0) { + if (errno == EINTR) + continue; + + return log_error_errno(errno, "waitid() failed: %m"); + } + + set_remove(pids, PID_TO_PTR(status.si_pid)); + break; + } + + if (!is_clean_exit(status.si_code, status.si_status, EXIT_CLEAN_DAEMON, NULL)) + log_error("Password agent failed with: %d", status.si_status); + + terminate_agents(pids); + return 0; +} + +static int run(int argc, char *argv[]) { + int r; + + log_setup_service(); + + umask(0022); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (arg_console && !arg_device) + /* + * Spawn a separate process for each console device. + */ + return ask_on_consoles(argv); + + if (arg_device) { + /* + * Later on, a controlling terminal will be acquired, + * therefore the current process has to become a session + * leader and should not have a controlling terminal already. + */ + (void) setsid(); + (void) release_terminal(); + } + + return process_and_watch_password_files(arg_action != ACTION_QUERY); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/udev/.vimrc b/src/udev/.vimrc new file mode 100644 index 00000000..366fbdca --- /dev/null +++ b/src/udev/.vimrc @@ -0,0 +1,4 @@ +" 'set exrc' in ~/.vimrc will read .vimrc from the current directory +set tabstop=8 +set shiftwidth=8 +set expandtab diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c new file mode 100644 index 00000000..deeb939f --- /dev/null +++ b/src/udev/ata_id/ata_id.c @@ -0,0 +1,653 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * ata_id - reads product/serial number from ATA drives + * + * Copyright © 2009-2010 David Zeuthen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fd-util.h" +#include "libudev-util.h" +#include "log.h" +#include "memory-util.h" +#include "udev-util.h" + +#define COMMAND_TIMEOUT_MSEC (30 * 1000) + +static int disk_scsi_inquiry_command( + int fd, + void *buf, + size_t buf_len) { + + uint8_t cdb[6] = { + /* INQUIRY, see SPC-4 section 6.4 */ + [0] = 0x12, /* OPERATION CODE: INQUIRY */ + [3] = (buf_len >> 8), /* ALLOCATION LENGTH */ + [4] = (buf_len & 0xff), + }; + uint8_t sense[32] = {}; + struct sg_io_v4 io_v4 = { + .guard = 'Q', + .protocol = BSG_PROTOCOL_SCSI, + .subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD, + .request_len = sizeof(cdb), + .request = (uintptr_t) cdb, + .max_response_len = sizeof(sense), + .response = (uintptr_t) sense, + .din_xfer_len = buf_len, + .din_xferp = (uintptr_t) buf, + .timeout = COMMAND_TIMEOUT_MSEC, + }; + int ret; + + ret = ioctl(fd, SG_IO, &io_v4); + if (ret != 0) { + /* could be that the driver doesn't do version 4, try version 3 */ + if (errno == EINVAL) { + struct sg_io_hdr io_hdr = { + .interface_id = 'S', + .cmdp = (unsigned char*) cdb, + .cmd_len = sizeof (cdb), + .dxferp = buf, + .dxfer_len = buf_len, + .sbp = sense, + .mx_sb_len = sizeof(sense), + .dxfer_direction = SG_DXFER_FROM_DEV, + .timeout = COMMAND_TIMEOUT_MSEC, + }; + + ret = ioctl(fd, SG_IO, &io_hdr); + if (ret != 0) + return ret; + + /* even if the ioctl succeeds, we need to check the return value */ + if (!(io_hdr.status == 0 && + io_hdr.host_status == 0 && + io_hdr.driver_status == 0)) { + errno = EIO; + return -1; + } + } else + return ret; + } + + /* even if the ioctl succeeds, we need to check the return value */ + if (!(io_v4.device_status == 0 && + io_v4.transport_status == 0 && + io_v4.driver_status == 0)) { + errno = EIO; + return -1; + } + + return 0; +} + +static int disk_identify_command( + int fd, + void *buf, + size_t buf_len) { + + uint8_t cdb[12] = { + /* + * ATA Pass-Through 12 byte command, as described in + * + * T10 04-262r8 ATA Command Pass-Through + * + * from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf + */ + [0] = 0xa1, /* OPERATION CODE: 12 byte pass through */ + [1] = 4 << 1, /* PROTOCOL: PIO Data-in */ + [2] = 0x2e, /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */ + [3] = 0, /* FEATURES */ + [4] = 1, /* SECTORS */ + [5] = 0, /* LBA LOW */ + [6] = 0, /* LBA MID */ + [7] = 0, /* LBA HIGH */ + [8] = 0 & 0x4F, /* SELECT */ + [9] = 0xEC, /* Command: ATA IDENTIFY DEVICE */ + }; + uint8_t sense[32] = {}; + uint8_t *desc = sense + 8; + struct sg_io_v4 io_v4 = { + .guard = 'Q', + .protocol = BSG_PROTOCOL_SCSI, + .subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD, + .request_len = sizeof(cdb), + .request = (uintptr_t) cdb, + .max_response_len = sizeof(sense), + .response = (uintptr_t) sense, + .din_xfer_len = buf_len, + .din_xferp = (uintptr_t) buf, + .timeout = COMMAND_TIMEOUT_MSEC, + }; + int ret; + + ret = ioctl(fd, SG_IO, &io_v4); + if (ret != 0) { + /* could be that the driver doesn't do version 4, try version 3 */ + if (errno == EINVAL) { + struct sg_io_hdr io_hdr = { + .interface_id = 'S', + .cmdp = (unsigned char*) cdb, + .cmd_len = sizeof (cdb), + .dxferp = buf, + .dxfer_len = buf_len, + .sbp = sense, + .mx_sb_len = sizeof (sense), + .dxfer_direction = SG_DXFER_FROM_DEV, + .timeout = COMMAND_TIMEOUT_MSEC, + }; + + ret = ioctl(fd, SG_IO, &io_hdr); + if (ret != 0) + return ret; + } else + return ret; + } + + if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c) && + !(sense[0] == 0x70 && sense[12] == 0x00 && sense[13] == 0x1d)) { + errno = EIO; + return -1; + } + + return 0; +} + +static int disk_identify_packet_device_command( + int fd, + void *buf, + size_t buf_len) { + + uint8_t cdb[16] = { + /* + * ATA Pass-Through 16 byte command, as described in + * + * T10 04-262r8 ATA Command Pass-Through + * + * from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf + */ + [0] = 0x85, /* OPERATION CODE: 16 byte pass through */ + [1] = 4 << 1, /* PROTOCOL: PIO Data-in */ + [2] = 0x2e, /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */ + [3] = 0, /* FEATURES */ + [4] = 0, /* FEATURES */ + [5] = 0, /* SECTORS */ + [6] = 1, /* SECTORS */ + [7] = 0, /* LBA LOW */ + [8] = 0, /* LBA LOW */ + [9] = 0, /* LBA MID */ + [10] = 0, /* LBA MID */ + [11] = 0, /* LBA HIGH */ + [12] = 0, /* LBA HIGH */ + [13] = 0, /* DEVICE */ + [14] = 0xA1, /* Command: ATA IDENTIFY PACKET DEVICE */ + [15] = 0, /* CONTROL */ + }; + uint8_t sense[32] = {}; + uint8_t *desc = sense + 8; + struct sg_io_v4 io_v4 = { + .guard = 'Q', + .protocol = BSG_PROTOCOL_SCSI, + .subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD, + .request_len = sizeof (cdb), + .request = (uintptr_t) cdb, + .max_response_len = sizeof (sense), + .response = (uintptr_t) sense, + .din_xfer_len = buf_len, + .din_xferp = (uintptr_t) buf, + .timeout = COMMAND_TIMEOUT_MSEC, + }; + int ret; + + ret = ioctl(fd, SG_IO, &io_v4); + if (ret != 0) { + /* could be that the driver doesn't do version 4, try version 3 */ + if (errno == EINVAL) { + struct sg_io_hdr io_hdr = { + .interface_id = 'S', + .cmdp = (unsigned char*) cdb, + .cmd_len = sizeof (cdb), + .dxferp = buf, + .dxfer_len = buf_len, + .sbp = sense, + .mx_sb_len = sizeof (sense), + .dxfer_direction = SG_DXFER_FROM_DEV, + .timeout = COMMAND_TIMEOUT_MSEC, + }; + + ret = ioctl(fd, SG_IO, &io_hdr); + if (ret != 0) + return ret; + } else + return ret; + } + + if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) { + errno = EIO; + return -1; + } + + return 0; +} + +/** + * disk_identify_get_string: + * @identify: A block of IDENTIFY data + * @offset_words: Offset of the string to get, in words. + * @dest: Destination buffer for the string. + * @dest_len: Length of destination buffer, in bytes. + * + * Copies the ATA string from @identify located at @offset_words into @dest. + */ +static void disk_identify_get_string( + uint8_t identify[512], + unsigned offset_words, + char *dest, + size_t dest_len) { + + unsigned c1; + unsigned c2; + + while (dest_len > 0) { + c1 = identify[offset_words * 2 + 1]; + c2 = identify[offset_words * 2]; + *dest = c1; + dest++; + *dest = c2; + dest++; + offset_words++; + dest_len -= 2; + } +} + +static void disk_identify_fixup_string( + uint8_t identify[512], + unsigned offset_words, + size_t len) { + disk_identify_get_string(identify, offset_words, + (char *) identify + offset_words * 2, len); +} + +static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned offset_words) { + uint16_t *p; + + p = (uint16_t *) identify; + p[offset_words] = le16toh (p[offset_words]); +} + +/** + * disk_identify: + * @fd: File descriptor for the block device. + * @out_identify: Return location for IDENTIFY data. + * @out_is_packet_device: Return location for whether returned data is from a IDENTIFY PACKET DEVICE. + * + * Sends the IDENTIFY DEVICE or IDENTIFY PACKET DEVICE command to the + * device represented by @fd. If successful, then the result will be + * copied into @out_identify and @out_is_packet_device. + * + * This routine is based on code from libatasmart, LGPL v2.1. + * + * Returns: 0 if the data was successfully obtained, otherwise + * non-zero with errno set. + */ +static int disk_identify(int fd, + uint8_t out_identify[512], + int *out_is_packet_device) { + int ret; + uint8_t inquiry_buf[36]; + int peripheral_device_type; + int all_nul_bytes; + int n; + int is_packet_device = 0; + + /* init results */ + memzero(out_identify, 512); + + /* If we were to use ATA PASS_THROUGH (12) on an ATAPI device + * we could accidentally blank media. This is because MMC's BLANK + * command has the same op-code (0x61). + * + * To prevent this from happening we bail out if the device + * isn't a Direct Access Block Device, e.g. SCSI type 0x00 + * (CD/DVD devices are type 0x05). So we send a SCSI INQUIRY + * command first... libata is handling this via its SCSI + * emulation layer. + * + * This also ensures that we're actually dealing with a device + * that understands SCSI commands. + * + * (Yes, it is a bit perverse that we're tunneling the ATA + * command through SCSI and relying on the ATA driver + * emulating SCSI well-enough...) + * + * (See commit 160b069c25690bfb0c785994c7c3710289179107 for + * the original bug-fix and see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=556635 + * for the original bug-report.) + */ + ret = disk_scsi_inquiry_command (fd, inquiry_buf, sizeof (inquiry_buf)); + if (ret != 0) + goto out; + + /* SPC-4, section 6.4.2: Standard INQUIRY data */ + peripheral_device_type = inquiry_buf[0] & 0x1f; + if (peripheral_device_type == 0x05) + { + is_packet_device = 1; + ret = disk_identify_packet_device_command(fd, out_identify, 512); + goto check_nul_bytes; + } + if (peripheral_device_type != 0x00) { + ret = -1; + errno = EIO; + goto out; + } + + /* OK, now issue the IDENTIFY DEVICE command */ + ret = disk_identify_command(fd, out_identify, 512); + if (ret != 0) + goto out; + + check_nul_bytes: + /* Check if IDENTIFY data is all NUL bytes - if so, bail */ + all_nul_bytes = 1; + for (n = 0; n < 512; n++) { + if (out_identify[n] != '\0') { + all_nul_bytes = 0; + break; + } + } + + if (all_nul_bytes) { + ret = -1; + errno = EIO; + goto out; + } + +out: + if (out_is_packet_device) + *out_is_packet_device = is_packet_device; + return ret; +} + +int main(int argc, char *argv[]) { + struct hd_driveid id; + union { + uint8_t byte[512]; + uint16_t wyde[256]; + } identify; + char model[41]; + char model_enc[256]; + char serial[21]; + char revision[9]; + const char *node = NULL; + int export = 0; + _cleanup_close_ int fd = -1; + uint16_t word; + int is_packet_device = 0; + static const struct option options[] = { + { "export", no_argument, NULL, 'x' }, + { "help", no_argument, NULL, 'h' }, + {} + }; + + log_set_target(LOG_TARGET_AUTO); + udev_parse_config(); + log_parse_environment(); + log_open(); + + for (;;) { + int option; + + option = getopt_long(argc, argv, "xh", options, NULL); + if (option == -1) + break; + + switch (option) { + case 'x': + export = 1; + break; + case 'h': + printf("Usage: %s [--export] [--help] \n" + " -x,--export print values as environment keys\n" + " -h,--help print this help text\n\n", + program_invocation_short_name); + return 0; + } + } + + node = argv[optind]; + if (!node) { + log_error("no node specified"); + return 1; + } + + fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC); + if (fd < 0) { + log_error("unable to open '%s'", node); + return 1; + } + + if (disk_identify(fd, identify.byte, &is_packet_device) == 0) { + /* + * fix up only the fields from the IDENTIFY data that we are going to + * use and copy it into the hd_driveid struct for convenience + */ + disk_identify_fixup_string(identify.byte, 10, 20); /* serial */ + disk_identify_fixup_string(identify.byte, 23, 8); /* fwrev */ + disk_identify_fixup_string(identify.byte, 27, 40); /* model */ + disk_identify_fixup_uint16(identify.byte, 0); /* configuration */ + disk_identify_fixup_uint16(identify.byte, 75); /* queue depth */ + disk_identify_fixup_uint16(identify.byte, 76); /* SATA capabilities */ + disk_identify_fixup_uint16(identify.byte, 82); /* command set supported */ + disk_identify_fixup_uint16(identify.byte, 83); /* command set supported */ + disk_identify_fixup_uint16(identify.byte, 84); /* command set supported */ + disk_identify_fixup_uint16(identify.byte, 85); /* command set supported */ + disk_identify_fixup_uint16(identify.byte, 86); /* command set supported */ + disk_identify_fixup_uint16(identify.byte, 87); /* command set supported */ + disk_identify_fixup_uint16(identify.byte, 89); /* time required for SECURITY ERASE UNIT */ + disk_identify_fixup_uint16(identify.byte, 90); /* time required for enhanced SECURITY ERASE UNIT */ + disk_identify_fixup_uint16(identify.byte, 91); /* current APM values */ + disk_identify_fixup_uint16(identify.byte, 94); /* current AAM value */ + disk_identify_fixup_uint16(identify.byte, 108); /* WWN */ + disk_identify_fixup_uint16(identify.byte, 109); /* WWN */ + disk_identify_fixup_uint16(identify.byte, 110); /* WWN */ + disk_identify_fixup_uint16(identify.byte, 111); /* WWN */ + disk_identify_fixup_uint16(identify.byte, 128); /* device lock function */ + disk_identify_fixup_uint16(identify.byte, 217); /* nominal media rotation rate */ + memcpy(&id, identify.byte, sizeof id); + } else { + /* If this fails, then try HDIO_GET_IDENTITY */ + if (ioctl(fd, HDIO_GET_IDENTITY, &id) != 0) { + log_debug_errno(errno, "HDIO_GET_IDENTITY failed for '%s': %m", node); + return 2; + } + } + + memcpy(model, id.model, 40); + model[40] = '\0'; + udev_util_encode_string(model, model_enc, sizeof(model_enc)); + util_replace_whitespace((char *) id.model, model, 40); + util_replace_chars(model, NULL); + util_replace_whitespace((char *) id.serial_no, serial, 20); + util_replace_chars(serial, NULL); + util_replace_whitespace((char *) id.fw_rev, revision, 8); + util_replace_chars(revision, NULL); + + if (export) { + /* Set this to convey the disk speaks the ATA protocol */ + printf("ID_ATA=1\n"); + + if ((id.config >> 8) & 0x80) { + /* This is an ATAPI device */ + switch ((id.config >> 8) & 0x1f) { + case 0: + printf("ID_TYPE=cd\n"); + break; + case 1: + printf("ID_TYPE=tape\n"); + break; + case 5: + printf("ID_TYPE=cd\n"); + break; + case 7: + printf("ID_TYPE=optical\n"); + break; + default: + printf("ID_TYPE=generic\n"); + break; + } + } else { + printf("ID_TYPE=disk\n"); + } + printf("ID_BUS=ata\n"); + printf("ID_MODEL=%s\n", model); + printf("ID_MODEL_ENC=%s\n", model_enc); + printf("ID_REVISION=%s\n", revision); + if (serial[0] != '\0') { + printf("ID_SERIAL=%s_%s\n", model, serial); + printf("ID_SERIAL_SHORT=%s\n", serial); + } else { + printf("ID_SERIAL=%s\n", model); + } + + if (id.command_set_1 & (1<<5)) { + printf("ID_ATA_WRITE_CACHE=1\n"); + printf("ID_ATA_WRITE_CACHE_ENABLED=%d\n", (id.cfs_enable_1 & (1<<5)) ? 1 : 0); + } + if (id.command_set_1 & (1<<10)) { + printf("ID_ATA_FEATURE_SET_HPA=1\n"); + printf("ID_ATA_FEATURE_SET_HPA_ENABLED=%d\n", (id.cfs_enable_1 & (1<<10)) ? 1 : 0); + + /* + * TODO: use the READ NATIVE MAX ADDRESS command to get the native max address + * so it is easy to check whether the protected area is in use. + */ + } + if (id.command_set_1 & (1<<3)) { + printf("ID_ATA_FEATURE_SET_PM=1\n"); + printf("ID_ATA_FEATURE_SET_PM_ENABLED=%d\n", (id.cfs_enable_1 & (1<<3)) ? 1 : 0); + } + if (id.command_set_1 & (1<<1)) { + printf("ID_ATA_FEATURE_SET_SECURITY=1\n"); + printf("ID_ATA_FEATURE_SET_SECURITY_ENABLED=%d\n", (id.cfs_enable_1 & (1<<1)) ? 1 : 0); + printf("ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN=%d\n", id.trseuc * 2); + if ((id.cfs_enable_1 & (1<<1))) /* enabled */ { + if (id.dlf & (1<<8)) + printf("ID_ATA_FEATURE_SET_SECURITY_LEVEL=maximum\n"); + else + printf("ID_ATA_FEATURE_SET_SECURITY_LEVEL=high\n"); + } + if (id.dlf & (1<<5)) + printf("ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN=%d\n", id.trsEuc * 2); + if (id.dlf & (1<<4)) + printf("ID_ATA_FEATURE_SET_SECURITY_EXPIRE=1\n"); + if (id.dlf & (1<<3)) + printf("ID_ATA_FEATURE_SET_SECURITY_FROZEN=1\n"); + if (id.dlf & (1<<2)) + printf("ID_ATA_FEATURE_SET_SECURITY_LOCKED=1\n"); + } + if (id.command_set_1 & (1<<0)) { + printf("ID_ATA_FEATURE_SET_SMART=1\n"); + printf("ID_ATA_FEATURE_SET_SMART_ENABLED=%d\n", (id.cfs_enable_1 & (1<<0)) ? 1 : 0); + } + if (id.command_set_2 & (1<<9)) { + printf("ID_ATA_FEATURE_SET_AAM=1\n"); + printf("ID_ATA_FEATURE_SET_AAM_ENABLED=%d\n", (id.cfs_enable_2 & (1<<9)) ? 1 : 0); + printf("ID_ATA_FEATURE_SET_AAM_VENDOR_RECOMMENDED_VALUE=%d\n", id.acoustic >> 8); + printf("ID_ATA_FEATURE_SET_AAM_CURRENT_VALUE=%d\n", id.acoustic & 0xff); + } + if (id.command_set_2 & (1<<5)) { + printf("ID_ATA_FEATURE_SET_PUIS=1\n"); + printf("ID_ATA_FEATURE_SET_PUIS_ENABLED=%d\n", (id.cfs_enable_2 & (1<<5)) ? 1 : 0); + } + if (id.command_set_2 & (1<<3)) { + printf("ID_ATA_FEATURE_SET_APM=1\n"); + printf("ID_ATA_FEATURE_SET_APM_ENABLED=%d\n", (id.cfs_enable_2 & (1<<3)) ? 1 : 0); + if ((id.cfs_enable_2 & (1<<3))) + printf("ID_ATA_FEATURE_SET_APM_CURRENT_VALUE=%d\n", id.CurAPMvalues & 0xff); + } + if (id.command_set_2 & (1<<0)) + printf("ID_ATA_DOWNLOAD_MICROCODE=1\n"); + + /* + * Word 76 indicates the capabilities of a SATA device. A PATA device shall set + * word 76 to 0000h or FFFFh. If word 76 is set to 0000h or FFFFh, then + * the device does not claim compliance with the Serial ATA specification and words + * 76 through 79 are not valid and shall be ignored. + */ + + word = identify.wyde[76]; + if (!IN_SET(word, 0x0000, 0xffff)) { + printf("ID_ATA_SATA=1\n"); + /* + * If bit 2 of word 76 is set to one, then the device supports the Gen2 + * signaling rate of 3.0 Gb/s (see SATA 2.6). + * + * If bit 1 of word 76 is set to one, then the device supports the Gen1 + * signaling rate of 1.5 Gb/s (see SATA 2.6). + */ + if (word & (1<<2)) + printf("ID_ATA_SATA_SIGNAL_RATE_GEN2=1\n"); + if (word & (1<<1)) + printf("ID_ATA_SATA_SIGNAL_RATE_GEN1=1\n"); + } + + /* Word 217 indicates the nominal media rotation rate of the device */ + word = identify.wyde[217]; + if (word == 0x0001) + printf ("ID_ATA_ROTATION_RATE_RPM=0\n"); /* non-rotating e.g. SSD */ + else if (word >= 0x0401 && word <= 0xfffe) + printf ("ID_ATA_ROTATION_RATE_RPM=%d\n", word); + + /* + * Words 108-111 contain a mandatory World Wide Name (WWN) in the NAA IEEE Registered identifier + * format. Word 108 bits (15:12) shall contain 5h, indicating that the naming authority is IEEE. + * All other values are reserved. + */ + word = identify.wyde[108]; + if ((word & 0xf000) == 0x5000) { + uint64_t wwwn; + + wwwn = identify.wyde[108]; + wwwn <<= 16; + wwwn |= identify.wyde[109]; + wwwn <<= 16; + wwwn |= identify.wyde[110]; + wwwn <<= 16; + wwwn |= identify.wyde[111]; + printf("ID_WWN=0x%1$" PRIx64 "\n" + "ID_WWN_WITH_EXTENSION=0x%1$" PRIx64 "\n", + wwwn); + } + + /* from Linux's include/linux/ata.h */ + if (IN_SET(identify.wyde[0], 0x848a, 0x844a) || + (identify.wyde[83] & 0xc004) == 0x4004) + printf("ID_ATA_CFA=1\n"); + } else { + if (serial[0] != '\0') + printf("%s_%s\n", model, serial); + else + printf("%s\n", model); + } + + return 0; +} diff --git a/src/udev/cdrom_id/cdrom_id.c b/src/udev/cdrom_id/cdrom_id.c new file mode 100644 index 00000000..13b947be --- /dev/null +++ b/src/udev/cdrom_id/cdrom_id.c @@ -0,0 +1,1018 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * cdrom_id - optical drive and media information prober + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "memory-util.h" +#include "random-util.h" +#include "udev-util.h" + +/* device info */ +static unsigned cd_cd_rom; +static unsigned cd_cd_r; +static unsigned cd_cd_rw; +static unsigned cd_dvd_rom; +static unsigned cd_dvd_r; +static unsigned cd_dvd_rw; +static unsigned cd_dvd_ram; +static unsigned cd_dvd_plus_r; +static unsigned cd_dvd_plus_rw; +static unsigned cd_dvd_plus_r_dl; +static unsigned cd_dvd_plus_rw_dl; +static unsigned cd_bd; +static unsigned cd_bd_r; +static unsigned cd_bd_re; +static unsigned cd_hddvd; +static unsigned cd_hddvd_r; +static unsigned cd_hddvd_rw; +static unsigned cd_mo; +static unsigned cd_mrw; +static unsigned cd_mrw_w; + +/* media info */ +static unsigned cd_media; +static unsigned cd_media_cd_rom; +static unsigned cd_media_cd_r; +static unsigned cd_media_cd_rw; +static unsigned cd_media_dvd_rom; +static unsigned cd_media_dvd_r; +static unsigned cd_media_dvd_rw; +static unsigned cd_media_dvd_rw_ro; /* restricted overwrite mode */ +static unsigned cd_media_dvd_rw_seq; /* sequential mode */ +static unsigned cd_media_dvd_ram; +static unsigned cd_media_dvd_plus_r; +static unsigned cd_media_dvd_plus_rw; +static unsigned cd_media_dvd_plus_r_dl; +static unsigned cd_media_dvd_plus_rw_dl; +static unsigned cd_media_bd; +static unsigned cd_media_bd_r; +static unsigned cd_media_bd_re; +static unsigned cd_media_hddvd; +static unsigned cd_media_hddvd_r; +static unsigned cd_media_hddvd_rw; +static unsigned cd_media_mo; +static unsigned cd_media_mrw; +static unsigned cd_media_mrw_w; + +static const char *cd_media_state = NULL; +static unsigned cd_media_session_next; +static unsigned cd_media_session_count; +static unsigned cd_media_track_count; +static unsigned cd_media_track_count_data; +static unsigned cd_media_track_count_audio; +static unsigned long long int cd_media_session_last_offset; + +#define ERRCODE(s) ((((s)[2] & 0x0F) << 16) | ((s)[12] << 8) | ((s)[13])) +#define SK(errcode) (((errcode) >> 16) & 0xF) +#define ASC(errcode) (((errcode) >> 8) & 0xFF) +#define ASCQ(errcode) ((errcode) & 0xFF) + +static void info_scsi_cmd_err(const char *cmd, int err) { + if (err == -1) + log_debug("%s failed", cmd); + else + log_debug("%s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh", cmd, SK(err), ASC(err), ASCQ(err)); +} + +struct scsi_cmd { + struct cdrom_generic_command cgc; + union { + struct request_sense s; + unsigned char u[18]; + } _sense; + struct sg_io_hdr sg_io; +}; + +static void scsi_cmd_init(struct scsi_cmd *cmd) { + memzero(cmd, sizeof(struct scsi_cmd)); + cmd->cgc.quiet = 1; + cmd->cgc.sense = &cmd->_sense.s; + cmd->sg_io.interface_id = 'S'; + cmd->sg_io.mx_sb_len = sizeof(cmd->_sense); + cmd->sg_io.cmdp = cmd->cgc.cmd; + cmd->sg_io.sbp = cmd->_sense.u; + cmd->sg_io.flags = SG_FLAG_LUN_INHIBIT | SG_FLAG_DIRECT_IO; +} + +static void scsi_cmd_set(struct scsi_cmd *cmd, size_t i, unsigned char arg) { + cmd->sg_io.cmd_len = i + 1; + cmd->cgc.cmd[i] = arg; +} + +#define CHECK_CONDITION 0x01 + +static int scsi_cmd_run(struct scsi_cmd *cmd, int fd, unsigned char *buf, size_t bufsize) { + int ret = 0; + + if (bufsize > 0) { + cmd->sg_io.dxferp = buf; + cmd->sg_io.dxfer_len = bufsize; + cmd->sg_io.dxfer_direction = SG_DXFER_FROM_DEV; + } else + cmd->sg_io.dxfer_direction = SG_DXFER_NONE; + + if (ioctl(fd, SG_IO, &cmd->sg_io)) + return -1; + + if ((cmd->sg_io.info & SG_INFO_OK_MASK) != SG_INFO_OK) { + errno = EIO; + ret = -1; + if (cmd->sg_io.masked_status & CHECK_CONDITION) { + ret = ERRCODE(cmd->_sense.u); + if (ret == 0) + ret = -1; + } + } + return ret; +} + +static int media_lock(int fd, bool lock) { + int err; + + /* disable the kernel's lock logic */ + err = ioctl(fd, CDROM_CLEAR_OPTIONS, CDO_LOCK); + if (err < 0) + log_debug("CDROM_CLEAR_OPTIONS, CDO_LOCK failed"); + + err = ioctl(fd, CDROM_LOCKDOOR, lock ? 1 : 0); + if (err < 0) + log_debug("CDROM_LOCKDOOR failed"); + + return err; +} + +static int media_eject(int fd) { + struct scsi_cmd sc; + int err; + + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x1b); + scsi_cmd_set(&sc, 4, 0x02); + scsi_cmd_set(&sc, 5, 0); + err = scsi_cmd_run(&sc, fd, NULL, 0); + if (err != 0) { + info_scsi_cmd_err("START_STOP_UNIT", err); + return -1; + } + return 0; +} + +static int cd_capability_compat(int fd) { + int capability; + + capability = ioctl(fd, CDROM_GET_CAPABILITY, NULL); + if (capability < 0) + return log_debug_errno(errno, "CDROM_GET_CAPABILITY failed"); + + if (capability & CDC_CD_R) + cd_cd_r = 1; + if (capability & CDC_CD_RW) + cd_cd_rw = 1; + if (capability & CDC_DVD) + cd_dvd_rom = 1; + if (capability & CDC_DVD_R) + cd_dvd_r = 1; + if (capability & CDC_DVD_RAM) + cd_dvd_ram = 1; + if (capability & CDC_MRW) + cd_mrw = 1; + if (capability & CDC_MRW_W) + cd_mrw_w = 1; + return 0; +} + +static int cd_media_compat(int fd) { + if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK) + return log_debug_errno(errno, "CDROM_DRIVE_STATUS != CDS_DISC_OK"); + + cd_media = 1; + return 0; +} + +static int cd_inquiry(int fd) { + struct scsi_cmd sc; + unsigned char inq[128]; + int err; + + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x12); + scsi_cmd_set(&sc, 4, 36); + scsi_cmd_set(&sc, 5, 0); + err = scsi_cmd_run(&sc, fd, inq, 36); + if (err != 0) { + info_scsi_cmd_err("INQUIRY", err); + return -1; + } + + if ((inq[0] & 0x1F) != 5) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "not an MMC unit"); + + log_debug("INQUIRY: [%.8s][%.16s][%.4s]", inq + 8, inq + 16, inq + 32); + return 0; +} + +static void feature_profile_media(int cur_profile) { + switch (cur_profile) { + case 0x03: + case 0x04: + case 0x05: + log_debug("profile 0x%02x ", cur_profile); + cd_media = 1; + cd_media_mo = 1; + break; + case 0x08: + log_debug("profile 0x%02x media_cd_rom", cur_profile); + cd_media = 1; + cd_media_cd_rom = 1; + break; + case 0x09: + log_debug("profile 0x%02x media_cd_r", cur_profile); + cd_media = 1; + cd_media_cd_r = 1; + break; + case 0x0a: + log_debug("profile 0x%02x media_cd_rw", cur_profile); + cd_media = 1; + cd_media_cd_rw = 1; + break; + case 0x10: + log_debug("profile 0x%02x media_dvd_ro", cur_profile); + cd_media = 1; + cd_media_dvd_rom = 1; + break; + case 0x11: + log_debug("profile 0x%02x media_dvd_r", cur_profile); + cd_media = 1; + cd_media_dvd_r = 1; + break; + case 0x12: + log_debug("profile 0x%02x media_dvd_ram", cur_profile); + cd_media = 1; + cd_media_dvd_ram = 1; + break; + case 0x13: + log_debug("profile 0x%02x media_dvd_rw_ro", cur_profile); + cd_media = 1; + cd_media_dvd_rw = 1; + cd_media_dvd_rw_ro = 1; + break; + case 0x14: + log_debug("profile 0x%02x media_dvd_rw_seq", cur_profile); + cd_media = 1; + cd_media_dvd_rw = 1; + cd_media_dvd_rw_seq = 1; + break; + case 0x1B: + log_debug("profile 0x%02x media_dvd_plus_r", cur_profile); + cd_media = 1; + cd_media_dvd_plus_r = 1; + break; + case 0x1A: + log_debug("profile 0x%02x media_dvd_plus_rw", cur_profile); + cd_media = 1; + cd_media_dvd_plus_rw = 1; + break; + case 0x2A: + log_debug("profile 0x%02x media_dvd_plus_rw_dl", cur_profile); + cd_media = 1; + cd_media_dvd_plus_rw_dl = 1; + break; + case 0x2B: + log_debug("profile 0x%02x media_dvd_plus_r_dl", cur_profile); + cd_media = 1; + cd_media_dvd_plus_r_dl = 1; + break; + case 0x40: + log_debug("profile 0x%02x media_bd", cur_profile); + cd_media = 1; + cd_media_bd = 1; + break; + case 0x41: + case 0x42: + log_debug("profile 0x%02x media_bd_r", cur_profile); + cd_media = 1; + cd_media_bd_r = 1; + break; + case 0x43: + log_debug("profile 0x%02x media_bd_re", cur_profile); + cd_media = 1; + cd_media_bd_re = 1; + break; + case 0x50: + log_debug("profile 0x%02x media_hddvd", cur_profile); + cd_media = 1; + cd_media_hddvd = 1; + break; + case 0x51: + log_debug("profile 0x%02x media_hddvd_r", cur_profile); + cd_media = 1; + cd_media_hddvd_r = 1; + break; + case 0x52: + log_debug("profile 0x%02x media_hddvd_rw", cur_profile); + cd_media = 1; + cd_media_hddvd_rw = 1; + break; + default: + log_debug("profile 0x%02x ", cur_profile); + break; + } +} + +static int feature_profiles(const unsigned char *profiles, size_t size) { + unsigned i; + + for (i = 0; i+4 <= size; i += 4) { + int profile; + + profile = profiles[i] << 8 | profiles[i+1]; + switch (profile) { + case 0x03: + case 0x04: + case 0x05: + log_debug("profile 0x%02x mo", profile); + cd_mo = 1; + break; + case 0x08: + log_debug("profile 0x%02x cd_rom", profile); + cd_cd_rom = 1; + break; + case 0x09: + log_debug("profile 0x%02x cd_r", profile); + cd_cd_r = 1; + break; + case 0x0A: + log_debug("profile 0x%02x cd_rw", profile); + cd_cd_rw = 1; + break; + case 0x10: + log_debug("profile 0x%02x dvd_rom", profile); + cd_dvd_rom = 1; + break; + case 0x12: + log_debug("profile 0x%02x dvd_ram", profile); + cd_dvd_ram = 1; + break; + case 0x13: + case 0x14: + log_debug("profile 0x%02x dvd_rw", profile); + cd_dvd_rw = 1; + break; + case 0x1B: + log_debug("profile 0x%02x dvd_plus_r", profile); + cd_dvd_plus_r = 1; + break; + case 0x1A: + log_debug("profile 0x%02x dvd_plus_rw", profile); + cd_dvd_plus_rw = 1; + break; + case 0x2A: + log_debug("profile 0x%02x dvd_plus_rw_dl", profile); + cd_dvd_plus_rw_dl = 1; + break; + case 0x2B: + log_debug("profile 0x%02x dvd_plus_r_dl", profile); + cd_dvd_plus_r_dl = 1; + break; + case 0x40: + cd_bd = 1; + log_debug("profile 0x%02x bd", profile); + break; + case 0x41: + case 0x42: + cd_bd_r = 1; + log_debug("profile 0x%02x bd_r", profile); + break; + case 0x43: + cd_bd_re = 1; + log_debug("profile 0x%02x bd_re", profile); + break; + case 0x50: + cd_hddvd = 1; + log_debug("profile 0x%02x hddvd", profile); + break; + case 0x51: + cd_hddvd_r = 1; + log_debug("profile 0x%02x hddvd_r", profile); + break; + case 0x52: + cd_hddvd_rw = 1; + log_debug("profile 0x%02x hddvd_rw", profile); + break; + default: + log_debug("profile 0x%02x ", profile); + break; + } + } + return 0; +} + +/* returns 0 if media was detected */ +static int cd_profiles_old_mmc(int fd) { + struct scsi_cmd sc; + int err; + + unsigned char header[32]; + + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x51); + scsi_cmd_set(&sc, 8, sizeof(header)); + scsi_cmd_set(&sc, 9, 0); + err = scsi_cmd_run(&sc, fd, header, sizeof(header)); + if (err != 0) { + info_scsi_cmd_err("READ DISC INFORMATION", err); + if (cd_media == 1) { + log_debug("no current profile, but disc is present; assuming CD-ROM"); + cd_media_cd_rom = 1; + cd_media_track_count = 1; + cd_media_track_count_data = 1; + return 0; + } else + return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM), + "no current profile, assuming no media"); + }; + + cd_media = 1; + + if (header[2] & 16) { + cd_media_cd_rw = 1; + log_debug("profile 0x0a media_cd_rw"); + } else if ((header[2] & 3) < 2 && cd_cd_r) { + cd_media_cd_r = 1; + log_debug("profile 0x09 media_cd_r"); + } else { + cd_media_cd_rom = 1; + log_debug("profile 0x08 media_cd_rom"); + } + return 0; +} + +/* returns 0 if media was detected */ +static int cd_profiles(int fd) { + struct scsi_cmd sc; + unsigned char features[65530]; + unsigned cur_profile = 0; + unsigned len; + unsigned i; + int err; + int ret; + + ret = -1; + + /* First query the current profile */ + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x46); + scsi_cmd_set(&sc, 8, 8); + scsi_cmd_set(&sc, 9, 0); + err = scsi_cmd_run(&sc, fd, features, 8); + if (err != 0) { + info_scsi_cmd_err("GET CONFIGURATION", err); + /* handle pre-MMC2 drives which do not support GET CONFIGURATION */ + if (SK(err) == 0x5 && IN_SET(ASC(err), 0x20, 0x24)) { + log_debug("drive is pre-MMC2 and does not support 46h get configuration command"); + log_debug("trying to work around the problem"); + ret = cd_profiles_old_mmc(fd); + } + goto out; + } + + cur_profile = features[6] << 8 | features[7]; + if (cur_profile > 0) { + log_debug("current profile 0x%02x", cur_profile); + feature_profile_media(cur_profile); + ret = 0; /* we have media */ + } else + log_debug("no current profile, assuming no media"); + + len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3]; + log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len); + + if (len > sizeof(features)) { + log_debug("cannot get features in a single query, truncating"); + len = sizeof(features); + } else if (len <= 8) + len = sizeof(features); + + /* Now get the full feature buffer */ + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x46); + scsi_cmd_set(&sc, 7, ( len >> 8 ) & 0xff); + scsi_cmd_set(&sc, 8, len & 0xff); + scsi_cmd_set(&sc, 9, 0); + err = scsi_cmd_run(&sc, fd, features, len); + if (err != 0) { + info_scsi_cmd_err("GET CONFIGURATION", err); + return -1; + } + + /* parse the length once more, in case the drive decided to have other features suddenly :) */ + len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3]; + log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len); + + if (len > sizeof(features)) { + log_debug("cannot get features in a single query, truncating"); + len = sizeof(features); + } + + /* device features */ + for (i = 8; i+4 < len; i += (4 + features[i+3])) { + unsigned feature; + + feature = features[i] << 8 | features[i+1]; + + switch (feature) { + case 0x00: + log_debug("GET CONFIGURATION: feature 'profiles', with %i entries", features[i+3] / 4); + feature_profiles(&features[i]+4, MIN(features[i+3], len - i - 4)); + break; + default: + log_debug("GET CONFIGURATION: feature 0x%04x , with 0x%02x bytes", feature, features[i+3]); + break; + } + } +out: + return ret; +} + +static int cd_media_info(int fd) { + struct scsi_cmd sc; + unsigned char header[32]; + static const char *const media_status[] = { + "blank", + "appendable", + "complete", + "other" + }; + int err; + + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x51); + scsi_cmd_set(&sc, 8, sizeof(header) & 0xff); + scsi_cmd_set(&sc, 9, 0); + err = scsi_cmd_run(&sc, fd, header, sizeof(header)); + if (err != 0) { + info_scsi_cmd_err("READ DISC INFORMATION", err); + return -1; + }; + + cd_media = 1; + log_debug("disk type %02x", header[8]); + log_debug("hardware reported media status: %s", media_status[header[2] & 3]); + + /* exclude plain CDROM, some fake cdroms return 0 for "blank" media here */ + if (!cd_media_cd_rom) + cd_media_state = media_status[header[2] & 3]; + + /* fresh DVD-RW in restricted overwrite mode reports itself as + * "appendable"; change it to "blank" to make it consistent with what + * gets reported after blanking, and what userspace expects */ + if (cd_media_dvd_rw_ro && (header[2] & 3) == 1) + cd_media_state = media_status[0]; + + /* DVD+RW discs (and DVD-RW in restricted mode) once formatted are + * always "complete", DVD-RAM are "other" or "complete" if the disc is + * write protected; we need to check the contents if it is blank */ + if ((cd_media_dvd_rw_ro || cd_media_dvd_plus_rw || cd_media_dvd_plus_rw_dl || cd_media_dvd_ram) && (header[2] & 3) > 1) { + unsigned char buffer[32 * 2048]; + unsigned char len; + int offset; + + if (cd_media_dvd_ram) { + /* a write protected dvd-ram may report "complete" status */ + + unsigned char dvdstruct[8]; + unsigned char format[12]; + + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0xAD); + scsi_cmd_set(&sc, 7, 0xC0); + scsi_cmd_set(&sc, 9, sizeof(dvdstruct)); + scsi_cmd_set(&sc, 11, 0); + err = scsi_cmd_run(&sc, fd, dvdstruct, sizeof(dvdstruct)); + if (err != 0) { + info_scsi_cmd_err("READ DVD STRUCTURE", err); + return -1; + } + if (dvdstruct[4] & 0x02) { + cd_media_state = media_status[2]; + log_debug("write-protected DVD-RAM media inserted"); + goto determined; + } + + /* let's make sure we don't try to read unformatted media */ + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x23); + scsi_cmd_set(&sc, 8, sizeof(format)); + scsi_cmd_set(&sc, 9, 0); + err = scsi_cmd_run(&sc, fd, format, sizeof(format)); + if (err != 0) { + info_scsi_cmd_err("READ DVD FORMAT CAPACITIES", err); + return -1; + } + + len = format[3]; + if (len & 7 || len < 16) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "invalid format capacities length"); + + switch(format[8] & 3) { + case 1: + log_debug("unformatted DVD-RAM media inserted"); + /* This means that last format was interrupted + * or failed, blank dvd-ram discs are factory + * formatted. Take no action here as it takes + * quite a while to reformat a dvd-ram and it's + * not automatically started */ + goto determined; + + case 2: + log_debug("formatted DVD-RAM media inserted"); + break; + + case 3: + cd_media = 0; //return no media + return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM), + "format capacities returned no media"); + } + } + + /* Take a closer look at formatted media (unformatted DVD+RW + * has "blank" status", DVD-RAM was examined earlier) and check + * for ISO and UDF PVDs or a fs superblock presence and do it + * in one ioctl (we need just sectors 0 and 16) */ + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x28); + scsi_cmd_set(&sc, 5, 0); + scsi_cmd_set(&sc, 8, 32); + scsi_cmd_set(&sc, 9, 0); + err = scsi_cmd_run(&sc, fd, buffer, sizeof(buffer)); + if (err != 0) { + cd_media = 0; + info_scsi_cmd_err("READ FIRST 32 BLOCKS", err); + return -1; + } + + /* if any non-zero data is found in sector 16 (iso and udf) or + * eventually 0 (fat32 boot sector, ext2 superblock, etc), disc + * is assumed non-blank */ + + for (offset = 32768; offset < (32768 + 2048); offset++) { + if (buffer [offset]) { + log_debug("data in block 16, assuming complete"); + goto determined; + } + } + + for (offset = 0; offset < 2048; offset++) { + if (buffer [offset]) { + log_debug("data in block 0, assuming complete"); + goto determined; + } + } + + cd_media_state = media_status[0]; + log_debug("no data in blocks 0 or 16, assuming blank"); + } + +determined: + /* "other" is e. g. DVD-RAM, can't append sessions there; DVDs in + * restricted overwrite mode can never append, only in sequential mode */ + if ((header[2] & 3) < 2 && !cd_media_dvd_rw_ro) + cd_media_session_next = header[10] << 8 | header[5]; + cd_media_session_count = header[9] << 8 | header[4]; + cd_media_track_count = header[11] << 8 | header[6]; + + return 0; +} + +static int cd_media_toc(int fd) { + struct scsi_cmd sc; + unsigned char header[12]; + unsigned char toc[65536]; + unsigned len, i, num_tracks; + unsigned char *p; + int err; + + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x43); + scsi_cmd_set(&sc, 6, 1); + scsi_cmd_set(&sc, 8, sizeof(header) & 0xff); + scsi_cmd_set(&sc, 9, 0); + err = scsi_cmd_run(&sc, fd, header, sizeof(header)); + if (err != 0) { + info_scsi_cmd_err("READ TOC", err); + return -1; + } + + len = (header[0] << 8 | header[1]) + 2; + log_debug("READ TOC: len: %d, start track: %d, end track: %d", len, header[2], header[3]); + if (len > sizeof(toc)) + return -1; + if (len < 2) + return -1; + /* 2: first track, 3: last track */ + num_tracks = header[3] - header[2] + 1; + + /* empty media has no tracks */ + if (len < 8) + return 0; + + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x43); + scsi_cmd_set(&sc, 6, header[2]); /* First Track/Session Number */ + scsi_cmd_set(&sc, 7, (len >> 8) & 0xff); + scsi_cmd_set(&sc, 8, len & 0xff); + scsi_cmd_set(&sc, 9, 0); + err = scsi_cmd_run(&sc, fd, toc, len); + if (err != 0) { + info_scsi_cmd_err("READ TOC (tracks)", err); + return -1; + } + + /* Take care to not iterate beyond the last valid track as specified in + * the TOC, but also avoid going beyond the TOC length, just in case + * the last track number is invalidly large */ + for (p = toc+4, i = 4; i < len-8 && num_tracks > 0; i += 8, p += 8, --num_tracks) { + unsigned block; + unsigned is_data_track; + + is_data_track = (p[1] & 0x04) != 0; + + block = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; + log_debug("track=%u info=0x%x(%s) start_block=%u", + p[2], p[1] & 0x0f, is_data_track ? "data":"audio", block); + + if (is_data_track) + cd_media_track_count_data++; + else + cd_media_track_count_audio++; + } + + scsi_cmd_init(&sc); + scsi_cmd_set(&sc, 0, 0x43); + scsi_cmd_set(&sc, 2, 1); /* Session Info */ + scsi_cmd_set(&sc, 8, sizeof(header)); + scsi_cmd_set(&sc, 9, 0); + err = scsi_cmd_run(&sc, fd, header, sizeof(header)); + if (err != 0) { + info_scsi_cmd_err("READ TOC (multi session)", err); + return -1; + } + len = header[4+4] << 24 | header[4+5] << 16 | header[4+6] << 8 | header[4+7]; + log_debug("last track %u starts at block %u", header[4+2], len); + cd_media_session_last_offset = (unsigned long long int)len * 2048; + return 0; +} + +int main(int argc, char *argv[]) { + static const struct option options[] = { + { "lock-media", no_argument, NULL, 'l' }, + { "unlock-media", no_argument, NULL, 'u' }, + { "eject-media", no_argument, NULL, 'e' }, + { "debug", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + {} + }; + bool eject = false; + bool lock = false; + bool unlock = false; + const char *node = NULL; + int fd = -1; + int cnt; + int rc = 0; + + log_set_target(LOG_TARGET_AUTO); + udev_parse_config(); + log_parse_environment(); + log_open(); + + for (;;) { + int option; + + option = getopt_long(argc, argv, "deluh", options, NULL); + if (option == -1) + break; + + switch (option) { + case 'l': + lock = true; + break; + case 'u': + unlock = true; + break; + case 'e': + eject = true; + break; + case 'd': + log_set_target(LOG_TARGET_CONSOLE); + log_set_max_level(LOG_DEBUG); + log_open(); + break; + case 'h': + printf("Usage: %s [options] \n" + " -l,--lock-media lock the media (to enable eject request events)\n" + " -u,--unlock-media unlock the media\n" + " -e,--eject-media eject the media\n" + " -d,--debug debug to stderr\n" + " -h,--help print this help text\n\n", + program_invocation_short_name); + goto exit; + default: + rc = 1; + goto exit; + } + } + + node = argv[optind]; + if (!node) { + log_error("no device"); + rc = 1; + goto exit; + } + + initialize_srand(); + for (cnt = 20; cnt > 0; cnt--) { + struct timespec duration; + + fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC); + if (fd >= 0 || errno != EBUSY) + break; + duration.tv_sec = 0; + duration.tv_nsec = (100 * 1000 * 1000) + (rand() % 100 * 1000 * 1000); + nanosleep(&duration, NULL); + } + if (fd < 0) { + log_debug("unable to open '%s'", node); + rc = 1; + goto exit; + } + log_debug("probing: '%s'", node); + + /* same data as original cdrom_id */ + if (cd_capability_compat(fd) < 0) { + rc = 1; + goto exit; + } + + /* check for media - don't bail if there's no media as we still need to + * to read profiles */ + cd_media_compat(fd); + + /* check if drive talks MMC */ + if (cd_inquiry(fd) < 0) + goto work; + + /* read drive and possibly current profile */ + if (cd_profiles(fd) != 0) + goto work; + + /* at this point we are guaranteed to have media in the drive - find out more about it */ + + /* get session/track info */ + cd_media_toc(fd); + + /* get writable media state */ + cd_media_info(fd); + +work: + /* lock the media, so we enable eject button events */ + if (lock && cd_media) { + log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (lock)"); + media_lock(fd, true); + } + + if (unlock && cd_media) { + log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)"); + media_lock(fd, false); + } + + if (eject) { + log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)"); + media_lock(fd, false); + log_debug("START_STOP_UNIT (eject)"); + media_eject(fd); + } + + printf("ID_CDROM=1\n"); + if (cd_cd_rom) + printf("ID_CDROM_CD=1\n"); + if (cd_cd_r) + printf("ID_CDROM_CD_R=1\n"); + if (cd_cd_rw) + printf("ID_CDROM_CD_RW=1\n"); + if (cd_dvd_rom) + printf("ID_CDROM_DVD=1\n"); + if (cd_dvd_r) + printf("ID_CDROM_DVD_R=1\n"); + if (cd_dvd_rw) + printf("ID_CDROM_DVD_RW=1\n"); + if (cd_dvd_ram) + printf("ID_CDROM_DVD_RAM=1\n"); + if (cd_dvd_plus_r) + printf("ID_CDROM_DVD_PLUS_R=1\n"); + if (cd_dvd_plus_rw) + printf("ID_CDROM_DVD_PLUS_RW=1\n"); + if (cd_dvd_plus_r_dl) + printf("ID_CDROM_DVD_PLUS_R_DL=1\n"); + if (cd_dvd_plus_rw_dl) + printf("ID_CDROM_DVD_PLUS_RW_DL=1\n"); + if (cd_bd) + printf("ID_CDROM_BD=1\n"); + if (cd_bd_r) + printf("ID_CDROM_BD_R=1\n"); + if (cd_bd_re) + printf("ID_CDROM_BD_RE=1\n"); + if (cd_hddvd) + printf("ID_CDROM_HDDVD=1\n"); + if (cd_hddvd_r) + printf("ID_CDROM_HDDVD_R=1\n"); + if (cd_hddvd_rw) + printf("ID_CDROM_HDDVD_RW=1\n"); + if (cd_mo) + printf("ID_CDROM_MO=1\n"); + if (cd_mrw) + printf("ID_CDROM_MRW=1\n"); + if (cd_mrw_w) + printf("ID_CDROM_MRW_W=1\n"); + + if (cd_media) + printf("ID_CDROM_MEDIA=1\n"); + if (cd_media_mo) + printf("ID_CDROM_MEDIA_MO=1\n"); + if (cd_media_mrw) + printf("ID_CDROM_MEDIA_MRW=1\n"); + if (cd_media_mrw_w) + printf("ID_CDROM_MEDIA_MRW_W=1\n"); + if (cd_media_cd_rom) + printf("ID_CDROM_MEDIA_CD=1\n"); + if (cd_media_cd_r) + printf("ID_CDROM_MEDIA_CD_R=1\n"); + if (cd_media_cd_rw) + printf("ID_CDROM_MEDIA_CD_RW=1\n"); + if (cd_media_dvd_rom) + printf("ID_CDROM_MEDIA_DVD=1\n"); + if (cd_media_dvd_r) + printf("ID_CDROM_MEDIA_DVD_R=1\n"); + if (cd_media_dvd_ram) + printf("ID_CDROM_MEDIA_DVD_RAM=1\n"); + if (cd_media_dvd_rw) + printf("ID_CDROM_MEDIA_DVD_RW=1\n"); + if (cd_media_dvd_plus_r) + printf("ID_CDROM_MEDIA_DVD_PLUS_R=1\n"); + if (cd_media_dvd_plus_rw) + printf("ID_CDROM_MEDIA_DVD_PLUS_RW=1\n"); + if (cd_media_dvd_plus_rw_dl) + printf("ID_CDROM_MEDIA_DVD_PLUS_RW_DL=1\n"); + if (cd_media_dvd_plus_r_dl) + printf("ID_CDROM_MEDIA_DVD_PLUS_R_DL=1\n"); + if (cd_media_bd) + printf("ID_CDROM_MEDIA_BD=1\n"); + if (cd_media_bd_r) + printf("ID_CDROM_MEDIA_BD_R=1\n"); + if (cd_media_bd_re) + printf("ID_CDROM_MEDIA_BD_RE=1\n"); + if (cd_media_hddvd) + printf("ID_CDROM_MEDIA_HDDVD=1\n"); + if (cd_media_hddvd_r) + printf("ID_CDROM_MEDIA_HDDVD_R=1\n"); + if (cd_media_hddvd_rw) + printf("ID_CDROM_MEDIA_HDDVD_RW=1\n"); + + if (cd_media_state) + printf("ID_CDROM_MEDIA_STATE=%s\n", cd_media_state); + if (cd_media_session_next > 0) + printf("ID_CDROM_MEDIA_SESSION_NEXT=%u\n", cd_media_session_next); + if (cd_media_session_count > 0) + printf("ID_CDROM_MEDIA_SESSION_COUNT=%u\n", cd_media_session_count); + if (cd_media_session_count > 1 && cd_media_session_last_offset > 0) + printf("ID_CDROM_MEDIA_SESSION_LAST_OFFSET=%llu\n", cd_media_session_last_offset); + if (cd_media_track_count > 0) + printf("ID_CDROM_MEDIA_TRACK_COUNT=%u\n", cd_media_track_count); + if (cd_media_track_count_audio > 0) + printf("ID_CDROM_MEDIA_TRACK_COUNT_AUDIO=%u\n", cd_media_track_count_audio); + if (cd_media_track_count_data > 0) + printf("ID_CDROM_MEDIA_TRACK_COUNT_DATA=%u\n", cd_media_track_count_data); +exit: + if (fd >= 0) + close(fd); + log_close(); + return rc; +} diff --git a/src/udev/fido_id/fido_id.c b/src/udev/fido_id/fido_id.c new file mode 100644 index 00000000..83761d72 --- /dev/null +++ b/src/udev/fido_id/fido_id.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/* + * Identifies FIDO CTAP1 ("U2F")/CTAP2 security tokens based on the usage declared in their report + * descriptor and outputs suitable environment variables. + * + * Inspired by Andrew Lutomirski's 'u2f-hidraw-policy.c' + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "device-internal.h" +#include "device-private.h" +#include "device-util.h" +#include "fd-util.h" +#include "fido_id_desc.h" +#include "log.h" +#include "macro.h" +#include "main-func.h" +#include "path-util.h" +#include "string-util.h" +#include "udev-util.h" + +static int run(int argc, char **argv) { + _cleanup_(sd_device_unrefp) struct sd_device *device = NULL; + _cleanup_free_ char *desc_path = NULL; + _cleanup_close_ int fd = -1; + + struct sd_device *hid_device; + const char *sys_path; + uint8_t desc[HID_MAX_DESCRIPTOR_SIZE]; + ssize_t desc_len; + + int r; + + log_set_target(LOG_TARGET_AUTO); + udev_parse_config(); + log_parse_environment(); + log_open(); + + if (argc > 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Usage: %s [SYSFS_PATH]", program_invocation_short_name); + + if (argc == 1) { + r = device_new_from_strv(&device, environ); + if (r < 0) + return log_error_errno(r, "Failed to get current device from environment: %m"); + } else { + r = sd_device_new_from_syspath(&device, argv[1]); + if (r < 0) + return log_error_errno(r, "Failed to get device from syspath: %m"); + } + + r = sd_device_get_parent(device, &hid_device); + if (r < 0) + return log_device_error_errno(device, r, "Failed to get parent HID device: %m"); + + r = sd_device_get_syspath(hid_device, &sys_path); + if (r < 0) + return log_device_error_errno(hid_device, r, "Failed to get syspath for HID device: %m"); + + desc_path = path_join(sys_path, "report_descriptor"); + if (!desc_path) + return log_oom(); + + fd = open(desc_path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); + if (fd < 0) + return log_device_error_errno(hid_device, errno, + "Failed to open report descriptor at '%s': %m", desc_path); + + desc_len = read(fd, desc, sizeof(desc)); + if (desc_len < 0) + return log_device_error_errno(hid_device, errno, + "Failed to read report descriptor at '%s': %m", desc_path); + if (desc_len == 0) + return log_device_debug_errno(hid_device, SYNTHETIC_ERRNO(EINVAL), + "Empty report descriptor at '%s'.", desc_path); + + r = is_fido_security_token_desc(desc, desc_len); + if (r < 0) + return log_device_debug_errno(hid_device, r, + "Failed to parse report descriptor at '%s'.", desc_path); + if (r > 0) { + printf("ID_FIDO_TOKEN=1\n"); + printf("ID_SECURITY_TOKEN=1\n"); + } + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/udev/fido_id/fido_id_desc.c b/src/udev/fido_id/fido_id_desc.c new file mode 100644 index 00000000..bbfcf937 --- /dev/null +++ b/src/udev/fido_id/fido_id_desc.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/* Inspired by Andrew Lutomirski's 'u2f-hidraw-policy.c' */ + +#include +#include +#include +#include + +#include "fido_id_desc.h" + +#define HID_RPTDESC_FIRST_BYTE_LONG_ITEM 0xfeu +#define HID_RPTDESC_TYPE_GLOBAL 0x1u +#define HID_RPTDESC_TYPE_LOCAL 0x2u +#define HID_RPTDESC_TAG_USAGE_PAGE 0x0u +#define HID_RPTDESC_TAG_USAGE 0x0u + +/* + * HID usage for FIDO CTAP1 ("U2F") and CTAP2 security tokens. + * https://fidoalliance.org/specs/fido-u2f-v1.0-ps-20141009/fido-u2f-u2f_hid.h-v1.0-ps-20141009.txt + * https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#usb-discovery + * https://www.usb.org/sites/default/files/hutrr48.pdf + */ +#define FIDO_FULL_USAGE_CTAPHID 0xf1d00001u + +/* + * Parses a HID report descriptor and identifies FIDO CTAP1 ("U2F")/CTAP2 security tokens based on their + * declared usage. + * A positive return value indicates that the report descriptor belongs to a FIDO security token. + * https://www.usb.org/sites/default/files/documents/hid1_11.pdf (Section 6.2.2) + */ +int is_fido_security_token_desc(const uint8_t *desc, size_t desc_len) { + uint32_t usage = 0; + + for (size_t pos = 0; pos < desc_len; ) { + uint8_t tag, type, size_code; + size_t size; + uint32_t value; + + /* Report descriptors consists of short items (1-5 bytes) and long items (3-258 bytes). */ + if (desc[pos] == HID_RPTDESC_FIRST_BYTE_LONG_ITEM) { + /* No long items are defined in the spec; skip them. + * The length of the data in a long item is contained in the byte after the long + * item tag. The header consists of three bytes: special long item tag, length, + * actual tag. */ + if (pos + 1 >= desc_len) + return -EINVAL; + pos += desc[pos + 1] + 3; + continue; + } + + /* The first byte of a short item encodes tag, type and size. */ + tag = desc[pos] >> 4; /* Bits 7 to 4 */ + type = (desc[pos] >> 2) & 0x3; /* Bits 3 and 2 */ + size_code = desc[pos] & 0x3; /* Bits 1 and 0 */ + /* Size is coded as follows: + * 0 -> 0 bytes, 1 -> 1 byte, 2 -> 2 bytes, 3 -> 4 bytes + */ + size = size_code < 3 ? size_code : 4; + /* Consume header byte. */ + pos++; + + /* Extract the item value coded on size bytes. */ + if (pos + size > desc_len) + return -EINVAL; + value = 0; + for (size_t i = 0; i < size; i++) + value |= (uint32_t) desc[pos + i] << (8 * i); + /* Consume value bytes. */ + pos += size; + + if (type == HID_RPTDESC_TYPE_GLOBAL && tag == HID_RPTDESC_TAG_USAGE_PAGE) { + /* A usage page is a 16 bit value coded on at most 16 bits. */ + if (size > 2) + return -EINVAL; + /* A usage page sets the upper 16 bits of a following usage. */ + usage = (value & 0x0000ffffu) << 16; + } + + if (type == HID_RPTDESC_TYPE_LOCAL && tag == HID_RPTDESC_TAG_USAGE) { + /* A usage is a 32 bit value, but is prepended with the current usage page if + * coded on less than 4 bytes (that is, at most 2 bytes). */ + if (size == 4) + usage = value; + else + usage = (usage & 0xffff0000u) | (value & 0x0000ffffu); + if (usage == FIDO_FULL_USAGE_CTAPHID) + return 1; + } + } + + return 0; +} diff --git a/src/udev/fido_id/fido_id_desc.h b/src/udev/fido_id/fido_id_desc.h new file mode 100644 index 00000000..c813a3a4 --- /dev/null +++ b/src/udev/fido_id/fido_id_desc.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#pragma once + +#include +#include + +int is_fido_security_token_desc(const uint8_t *desc, size_t desc_len); diff --git a/src/udev/fido_id/fuzz-fido-id-desc.c b/src/udev/fido_id/fuzz-fido-id-desc.c new file mode 100644 index 00000000..45a4879e --- /dev/null +++ b/src/udev/fido_id/fuzz-fido-id-desc.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "fido_id_desc.h" +#include "fuzz.h" +#include "log.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + /* We don't want to fill the logs with messages about parse errors. + * Disable most logging if not running standalone */ + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + if (size > HID_MAX_DESCRIPTOR_SIZE) + return 0; + (void) is_fido_security_token_desc(data, size); + + return 0; +} diff --git a/src/udev/fido_id/test-fido-id-desc.c b/src/udev/fido_id/test-fido-id-desc.c new file mode 100644 index 00000000..38eec2bc --- /dev/null +++ b/src/udev/fido_id/test-fido-id-desc.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "fido_id_desc.h" +#include "macro.h" + +static void test_is_fido_security_token_desc__fido(void) { + static const uint8_t FIDO_HID_DESC_1[] = { + 0x06, 0xd0, 0xf1, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, + 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, + 0x40, 0x91, 0x02, 0xc0, + }; + assert_se(is_fido_security_token_desc(FIDO_HID_DESC_1, sizeof(FIDO_HID_DESC_1)) > 0); + + static const uint8_t FIDO_HID_DESC_2[] = { + 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, + 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x05, + 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03, 0x91, + 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00, 0x29, 0x65, + 0x81, 0x00, 0x09, 0x03, 0x75, 0x08, 0x95, 0x08, 0xb1, 0x02, 0xc0, + 0x06, 0xd0, 0xf1, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, + 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, + 0x40, 0x91, 0x02, 0xc0, + }; + assert_se(is_fido_security_token_desc(FIDO_HID_DESC_2, sizeof(FIDO_HID_DESC_2)) > 0); +} + +static void test_is_fido_security_token_desc__non_fido(void) { + /* Wrong usage page */ + static const uint8_t NON_FIDO_HID_DESC_1[] = { + 0x06, 0xd0, 0xf0, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, + 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, + 0x40, 0x91, 0x02, 0xc0, + }; + assert_se(is_fido_security_token_desc(NON_FIDO_HID_DESC_1, sizeof(NON_FIDO_HID_DESC_1)) == 0); + + /* Wrong usage */ + static const uint8_t NON_FIDO_HID_DESC_2[] = { + 0x06, 0xd0, 0xf1, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, + 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, + 0x40, 0x91, 0x02, 0xc0, + }; + assert_se(is_fido_security_token_desc(NON_FIDO_HID_DESC_2, sizeof(NON_FIDO_HID_DESC_2)) == 0); + + static const uint8_t NON_FIDO_HID_DESC_3[] = { + 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, + 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x05, + 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03, 0x91, + 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00, 0x29, 0x65, + 0x81, 0x00, 0x09, 0x03, 0x75, 0x08, 0x95, 0x08, 0xb1, 0x02, 0xc0, + }; + assert_se(is_fido_security_token_desc(NON_FIDO_HID_DESC_3, sizeof(NON_FIDO_HID_DESC_3)) == 0); +} + +static void test_is_fido_security_token_desc__invalid(void) { + /* Size coded on 1 byte, but no byte given */ + static const uint8_t INVALID_HID_DESC_1[] = { 0x01 }; + assert_se(is_fido_security_token_desc(INVALID_HID_DESC_1, sizeof(INVALID_HID_DESC_1)) < 0); + + /* Size coded on 2 bytes, but only 1 byte given */ + static const uint8_t INVALID_HID_DESC_2[] = { 0x02, 0x01 }; + assert_se(is_fido_security_token_desc(INVALID_HID_DESC_2, sizeof(INVALID_HID_DESC_2)) < 0); + + /* Size coded on 4 bytes, but only 3 bytes given */ + static const uint8_t INVALID_HID_DESC_3[] = { 0x03, 0x01, 0x02, 0x03 }; + assert_se(is_fido_security_token_desc(INVALID_HID_DESC_3, sizeof(INVALID_HID_DESC_3)) < 0); + + /* Long item without a size byte */ + static const uint8_t INVALID_HID_DESC_4[] = { 0xfe }; + assert_se(is_fido_security_token_desc(INVALID_HID_DESC_4, sizeof(INVALID_HID_DESC_4)) < 0); + + /* Usage pages are coded on at most 2 bytes */ + static const uint8_t INVALID_HID_DESC_5[] = { 0x07, 0x01, 0x02, 0x03, 0x04 }; + assert_se(is_fido_security_token_desc(INVALID_HID_DESC_5, sizeof(INVALID_HID_DESC_5)) < 0); +} + +int main(int argc, char *argv[]) { + test_is_fido_security_token_desc__fido(); + test_is_fido_security_token_desc__non_fido(); + test_is_fido_security_token_desc__invalid(); + + return EXIT_SUCCESS; +} diff --git a/src/udev/generate-keyboard-keys-gperf.sh b/src/udev/generate-keyboard-keys-gperf.sh new file mode 100755 index 00000000..c78652a8 --- /dev/null +++ b/src/udev/generate-keyboard-keys-gperf.sh @@ -0,0 +1,18 @@ +#!/bin/sh +set -eu + +awk ' + BEGIN { + print "%{\n\ +#if __GNUC__ >= 7\n\ +_Pragma(\"GCC diagnostic ignored \\\"-Wimplicit-fallthrough\\\"\")\n\ +#endif\n\ +%}" + print "struct key_name { const char* name; unsigned short id; };" + print "%null-strings" + print "%%" + } + + /^KEY_/ { print tolower(substr($1 ,5)) ", " $1 } + { print tolower($1) ", " $1 } +' < "$1" diff --git a/src/udev/generate-keyboard-keys-list.sh b/src/udev/generate-keyboard-keys-list.sh new file mode 100755 index 00000000..aa00c15c --- /dev/null +++ b/src/udev/generate-keyboard-keys-list.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -eu + +$1 -dM -include linux/input.h - / { next } + /^#define[ \t]+(KEY|BTN)_[^ ]+[ \t]+[0-9BK]/ { print $2 } +' diff --git a/src/udev/meson.build b/src/udev/meson.build new file mode 100644 index 00000000..991d2eb2 --- /dev/null +++ b/src/udev/meson.build @@ -0,0 +1,224 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +udevadm_sources = files(''' + udevadm.c + udevadm.h + udevadm-control.c + udevadm-hwdb.c + udevadm-info.c + udevadm-monitor.c + udevadm-settle.c + udevadm-test.c + udevadm-test-builtin.c + udevadm-trigger.c + udevadm-util.c + udevadm-util.h +'''.split()) + +systemd_udevd_sources = files('udevd.c') + +libudev_core_sources = ''' + udev-ctrl.c + udev-ctrl.h + udev-event.c + udev-event.h + udev-node.c + udev-node.h + udev-rules.c + udev-rules.h + udev-watch.c + udev-watch.h + udev-builtin.c + udev-builtin.h + udev-builtin-btrfs.c + udev-builtin-hwdb.c + udev-builtin-input_id.c + udev-builtin-keyboard.c + udev-builtin-net_id.c + udev-builtin-net_setup_link.c + udev-builtin-path_id.c + udev-builtin-usb_id.c + net/link-config.c + net/link-config.h + net/naming-scheme.c + net/naming-scheme.h +'''.split() + +if conf.get('HAVE_KMOD') == 1 + libudev_core_sources += ['udev-builtin-kmod.c'] +endif + +if conf.get('HAVE_BLKID') == 1 + libudev_core_sources += ['udev-builtin-blkid.c'] +endif + +if conf.get('HAVE_ACL') == 1 + libudev_core_sources += ['udev-builtin-uaccess.c', + logind_acl_c, + sd_login_sources] +endif + +############################################################ + +generate_keyboard_keys_list = find_program('generate-keyboard-keys-list.sh') +keyboard_keys_list_txt = custom_target( + 'keyboard-keys-list.txt', + output : 'keyboard-keys-list.txt', + command : [generate_keyboard_keys_list, cpp], + capture : true) + +generate_keyboard_keys_gperf = find_program('generate-keyboard-keys-gperf.sh') +fname = 'keyboard-keys-from-name.gperf' +gperf_file = custom_target( + fname, + input : keyboard_keys_list_txt, + output : fname, + command : [generate_keyboard_keys_gperf, '@INPUT@'], + capture : true) + +fname = 'keyboard-keys-from-name.h' +keyboard_keys_from_name_h = custom_target( + fname, + input : gperf_file, + output : fname, + command : [gperf, + '-L', 'ANSI-C', '-t', + '-N', 'keyboard_lookup_key', + '-H', 'hash_key_name', + '-p', '-C', + '@INPUT@'], + capture : true) + +############################################################ + +link_config_gperf_c = custom_target( + 'link-config-gperf.c', + input : 'net/link-config-gperf.gperf', + output : 'link-config-gperf.c', + command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) + +############################################################ + +if get_option('link-udev-shared') + udev_link_with = [libshared] + udev_rpath = rootlibexecdir +else + udev_link_with = [libshared_static, + libsystemd_static] + udev_rpath = '' +endif + +libudev_basic = static_library( + 'udev-basic', + libudev_sources, + include_directories : includes, + c_args : ['-fvisibility=default']) + +libudev_static = static_library( + 'udev_static', + include_directories : includes, + link_with : udev_link_with, + link_whole : libudev_basic) + +static_libudev = get_option('static-libudev') +static_libudev_pic = static_libudev == 'true' or static_libudev == 'pic' +install_libudev_static = static_library( + 'udev', + basic_sources, + shared_sources, + libsystemd_sources, + libudev_sources, + disable_mempool_c, + include_directories : includes, + build_by_default : static_libudev != 'false', + install : static_libudev != 'false', + install_dir : rootlibdir, + link_depends : libudev_sym, + dependencies : libshared_deps + [libmount], + c_args : static_libudev_pic ? [] : ['-fno-PIC'], + pic : static_libudev_pic) + +libudev = shared_library( + 'udev', + disable_mempool_c, + version : libudev_version, + include_directories : includes, + link_args : ['-shared', + '-Wl,--version-script=' + libudev_sym_path], + link_with : [libsystemd_static, libshared_static], + link_whole : libudev_basic, + dependencies : [threads], + link_depends : libudev_sym, + install : true, + install_dir : rootlibdir) + +libudev_core_includes = [includes, include_directories('net')] +libudev_core = static_library( + 'udev-core', + libudev_core_sources, + link_config_gperf_c, + keyboard_keys_from_name_h, + include_directories : libudev_core_includes, + c_args : ['-DLOG_REALM=LOG_REALM_UDEV'], + link_with : udev_link_with, + dependencies : [libblkid, libkmod]) + +foreach prog : [['ata_id/ata_id.c'], + ['cdrom_id/cdrom_id.c'], + ['fido_id/fido_id.c', + 'fido_id/fido_id_desc.c', + 'fido_id/fido_id_desc.h'], + ['scsi_id/scsi_id.c', + 'scsi_id/scsi_id.h', + 'scsi_id/scsi_serial.c', + 'scsi_id/scsi.h'], + ['v4l_id/v4l_id.c'], + ['mtd_probe/mtd_probe.c', + 'mtd_probe/mtd_probe.h', + 'mtd_probe/probe_smartmedia.c']] + + executable(prog[0].split('/')[0], + prog, + include_directories : includes, + c_args : ['-DLOG_REALM=LOG_REALM_UDEV'], + dependencies : [versiondep], + link_with : [libudev_static], + install_rpath : udev_rpath, + install : true, + install_dir : udevlibexecdir) +endforeach + +install_data('udev.conf', + install_dir : join_paths(sysconfdir, 'udev')) + +configure_file( + input : 'udev.pc.in', + output : 'udev.pc', + configuration : substs, + install_dir : pkgconfigdatadir == 'no' ? '' : pkgconfigdatadir) + +meson.add_install_script('sh', '-c', + mkdir_p.format(join_paths(sysconfdir, 'udev/rules.d'))) + +fuzzers += [ + [['src/udev/net/fuzz-link-parser.c', + 'src/fuzz/fuzz.h'], + [libudev_core, + libudev_static, + libsystemd_network, + libshared], + [threads, + libacl]], + + [['src/udev/fido_id/fuzz-fido-id-desc.c', + 'src/udev/fido_id/fido_id_desc.c'], + [], + []], + ] + +tests += [ + [['src/udev/fido_id/test-fido-id-desc.c', + 'src/udev/fido_id/fido_id_desc.c'], + [], + []], + ] diff --git a/src/udev/mtd_probe/mtd_probe.c b/src/udev/mtd_probe/mtd_probe.c new file mode 100644 index 00000000..f47b1337 --- /dev/null +++ b/src/udev/mtd_probe/mtd_probe.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright © 2010 - Maxim Levitsky + * + * mtd_probe is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mtd_probe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with mtd_probe; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "mtd_probe.h" + +int main(int argc, char** argv) { + _cleanup_close_ int mtd_fd = -1; + mtd_info_t mtd_info; + + if (argc != 2) { + printf("usage: mtd_probe /dev/mtd[n]\n"); + return EXIT_FAILURE; + } + + mtd_fd = open(argv[1], O_RDONLY|O_CLOEXEC); + if (mtd_fd < 0) { + log_error_errno(errno, "Failed to open: %m"); + return EXIT_FAILURE; + } + + if (ioctl(mtd_fd, MEMGETINFO, &mtd_info) < 0) { + log_error_errno(errno, "Failed to issue MEMGETINFO ioctl: %m"); + return EXIT_FAILURE; + } + + if (probe_smart_media(mtd_fd, &mtd_info) < 0) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} diff --git a/src/udev/mtd_probe/mtd_probe.h b/src/udev/mtd_probe/mtd_probe.h new file mode 100644 index 00000000..1d8c93b7 --- /dev/null +++ b/src/udev/mtd_probe/mtd_probe.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +/* + * Copyright © 2010 - Maxim Levitsky + * + * mtd_probe is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mtd_probe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with mtd_probe; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include + +#include "macro.h" + +/* Full oob structure as written on the flash */ +struct sm_oob { + uint32_t reserved; + uint8_t data_status; + uint8_t block_status; + uint8_t lba_copy1[2]; + uint8_t ecc2[3]; + uint8_t lba_copy2[2]; + uint8_t ecc1[3]; +} _packed_; + +/* one sector is always 512 bytes, but it can consist of two nand pages */ +#define SM_SECTOR_SIZE 512 + +/* oob area is also 16 bytes, but might be from two pages */ +#define SM_OOB_SIZE 16 + +/* This is maximum zone size, and all devices that have more that one zone + have this size */ +#define SM_MAX_ZONE_SIZE 1024 + +/* support for small page nand */ +#define SM_SMALL_PAGE 256 +#define SM_SMALL_OOB_SIZE 8 + +int probe_smart_media(int mtd_fd, mtd_info_t *info); diff --git a/src/udev/mtd_probe/probe_smartmedia.c b/src/udev/mtd_probe/probe_smartmedia.c new file mode 100644 index 00000000..f8e1b140 --- /dev/null +++ b/src/udev/mtd_probe/probe_smartmedia.c @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright © 2010 - Maxim Levitsky + * + * mtd_probe is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mtd_probe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with mtd_probe; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "mtd_probe.h" + +static const uint8_t cis_signature[] = { + 0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20 +}; + +int probe_smart_media(int mtd_fd, mtd_info_t* info) { + int sector_size; + int block_size; + int size_in_megs; + int spare_count; + _cleanup_free_ uint8_t *cis_buffer = NULL; + int offset; + int cis_found = 0; + + cis_buffer = malloc(SM_SECTOR_SIZE); + if (!cis_buffer) + return log_oom(); + + if (info->type != MTD_NANDFLASH) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Not marked MTD_NANDFLASH."); + + sector_size = info->writesize; + block_size = info->erasesize; + size_in_megs = info->size / (1024 * 1024); + + if (!IN_SET(sector_size, SM_SECTOR_SIZE, SM_SMALL_PAGE)) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Unexpected sector size: %i", sector_size); + + switch(size_in_megs) { + case 1: + case 2: + spare_count = 6; + break; + case 4: + spare_count = 12; + break; + default: + spare_count = 24; + break; + } + + for (offset = 0; offset < block_size * spare_count; offset += sector_size) { + (void) lseek(mtd_fd, SEEK_SET, offset); + + if (read(mtd_fd, cis_buffer, SM_SECTOR_SIZE) == SM_SECTOR_SIZE) { + cis_found = 1; + break; + } + } + + if (!cis_found) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "CIS not found"); + + if (memcmp(cis_buffer, cis_signature, sizeof(cis_signature)) != 0 && + memcmp(cis_buffer + SM_SMALL_PAGE, cis_signature, sizeof(cis_signature)) != 0) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "CIS signature didn't match"); + + printf("MTD_FTL=smartmedia\n"); + return 0; +} diff --git a/src/udev/net/fuzz-link-parser.c b/src/udev/net/fuzz-link-parser.c new file mode 100644 index 00000000..e0dacc73 --- /dev/null +++ b/src/udev/net/fuzz-link-parser.c @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "fd-util.h" +#include "fs-util.h" +#include "fuzz.h" +#include "link-config.h" +#include "tmpfile-util.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL; + _cleanup_(unlink_tempfilep) char filename[] = "/tmp/fuzz-link-config.XXXXXX"; + _cleanup_fclose_ FILE *f = NULL; + + if (size > 65535) + return 0; + + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + assert_se(fmkostemp_safe(filename, "r+", &f) == 0); + if (size != 0) + assert_se(fwrite(data, size, 1, f) == 1); + + fflush(f); + assert_se(link_config_ctx_new(&ctx) >= 0); + (void) link_load_one(ctx, filename); + return 0; +} diff --git a/src/udev/net/fuzz-link-parser.options b/src/udev/net/fuzz-link-parser.options new file mode 100644 index 00000000..0824b19f --- /dev/null +++ b/src/udev/net/fuzz-link-parser.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 65535 diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf new file mode 100644 index 00000000..c6ff796e --- /dev/null +++ b/src/udev/net/link-config-gperf.gperf @@ -0,0 +1,57 @@ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#endif +#include +#include "conf-parser.h" +#include "ethtool-util.h" +#include "link-config.h" +#include "network-internal.h" +%} +struct ConfigPerfItem; +%null_strings +%language=ANSI-C +%define slot-name section_and_lvalue +%define hash-function-name link_config_gperf_hash +%define lookup-function-name link_config_gperf_lookup +%readonly-tables +%omit-struct-type +%struct-type +%includes +%% +Match.MACAddress, config_parse_hwaddrs, 0, offsetof(link_config, match_mac) +Match.OriginalName, config_parse_match_ifnames, 0, offsetof(link_config, match_name) +Match.Path, config_parse_match_strv, 0, offsetof(link_config, match_path) +Match.Driver, config_parse_match_strv, 0, offsetof(link_config, match_driver) +Match.Type, config_parse_match_strv, 0, offsetof(link_config, match_type) +Match.Property, config_parse_match_property, 0, offsetof(link_config, match_property) +Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(link_config, conditions) +Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(link_config, conditions) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(link_config, conditions) +Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(link_config, conditions) +Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(link_config, conditions) +Link.Description, config_parse_string, 0, offsetof(link_config, description) +Link.MACAddressPolicy, config_parse_mac_address_policy, 0, offsetof(link_config, mac_address_policy) +Link.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, mac) +Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy) +Link.Name, config_parse_ifname, 0, offsetof(link_config, name) +Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias) +Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu) +Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed) +Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex) +Link.AutoNegotiation, config_parse_tristate, 0, offsetof(link_config, autonegotiation) +Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol) +Link.Port, config_parse_port, 0, offsetof(link_config, port) +Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GSO]) +Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO]) +Link.TCP6SegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO6]) +Link.UDPSegmentationOffload, config_parse_warn_compat, DISABLED_LEGACY, 0 +Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GRO]) +Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_LRO]) +Link.RxChannels, config_parse_channel, 0, offsetof(link_config, channels) +Link.TxChannels, config_parse_channel, 0, offsetof(link_config, channels) +Link.OtherChannels, config_parse_channel, 0, offsetof(link_config, channels) +Link.CombinedChannels, config_parse_channel, 0, offsetof(link_config, channels) +Link.Advertise, config_parse_advertise, 0, offsetof(link_config, advertise) +Link.RxBufferSize, config_parse_nic_buffer_size, 0, offsetof(link_config, ring) +Link.TxBufferSize, config_parse_nic_buffer_size, 0, offsetof(link_config, ring) diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c new file mode 100644 index 00000000..7b07e2f3 --- /dev/null +++ b/src/udev/net/link-config.c @@ -0,0 +1,506 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "sd-device.h" +#include "sd-netlink.h" + +#include "alloc-util.h" +#include "conf-files.h" +#include "conf-parser.h" +#include "def.h" +#include "device-util.h" +#include "ethtool-util.h" +#include "fd-util.h" +#include "link-config.h" +#include "log.h" +#include "memory-util.h" +#include "naming-scheme.h" +#include "netlink-util.h" +#include "network-internal.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "random-util.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" + +struct link_config_ctx { + LIST_HEAD(link_config, links); + + int ethtool_fd; + + bool enable_name_policy; + + sd_netlink *rtnl; + + usec_t network_dirs_ts_usec; +}; + +static void link_config_free(link_config *link) { + if (!link) + return; + + free(link->filename); + + set_free_free(link->match_mac); + strv_free(link->match_path); + strv_free(link->match_driver); + strv_free(link->match_type); + strv_free(link->match_name); + strv_free(link->match_property); + condition_free_list(link->conditions); + + free(link->description); + free(link->mac); + free(link->name_policy); + free(link->name); + free(link->alias); + + free(link); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(link_config*, link_config_free); + +static void link_configs_free(link_config_ctx *ctx) { + link_config *link, *link_next; + + if (!ctx) + return; + + LIST_FOREACH_SAFE(links, link, link_next, ctx->links) + link_config_free(link); +} + +void link_config_ctx_free(link_config_ctx *ctx) { + if (!ctx) + return; + + safe_close(ctx->ethtool_fd); + + sd_netlink_unref(ctx->rtnl); + + link_configs_free(ctx); + + free(ctx); + + return; +} + +int link_config_ctx_new(link_config_ctx **ret) { + _cleanup_(link_config_ctx_freep) link_config_ctx *ctx = NULL; + + if (!ret) + return -EINVAL; + + ctx = new0(link_config_ctx, 1); + if (!ctx) + return -ENOMEM; + + LIST_HEAD_INIT(ctx->links); + + ctx->ethtool_fd = -1; + + ctx->enable_name_policy = true; + + *ret = TAKE_PTR(ctx); + + return 0; +} + +int link_load_one(link_config_ctx *ctx, const char *filename) { + _cleanup_(link_config_freep) link_config *link = NULL; + _cleanup_fclose_ FILE *file = NULL; + _cleanup_free_ char *name = NULL; + size_t i; + int r; + + assert(ctx); + assert(filename); + + file = fopen(filename, "re"); + if (!file) + return errno == ENOENT ? 0 : -errno; + + if (null_or_empty_fd(fileno(file))) { + log_debug("Skipping empty file: %s", filename); + return 0; + } + + name = strdup(filename); + if (!name) + return -ENOMEM; + + link = new(link_config, 1); + if (!link) + return -ENOMEM; + + *link = (link_config) { + .filename = TAKE_PTR(name), + .mac_address_policy = _MAC_ADDRESS_POLICY_INVALID, + .wol = _WOL_INVALID, + .duplex = _DUP_INVALID, + .port = _NET_DEV_PORT_INVALID, + .autonegotiation = -1, + }; + + for (i = 0; i < ELEMENTSOF(link->features); i++) + link->features[i] = -1; + + r = config_parse(NULL, filename, file, + "Match\0Link\0", + config_item_perf_lookup, link_config_gperf_lookup, + CONFIG_PARSE_WARN, link); + if (r < 0) + return r; + + if (link->speed > UINT_MAX) + return -ERANGE; + + if (set_isempty(link->match_mac) && strv_isempty(link->match_path) && + strv_isempty(link->match_driver) && strv_isempty(link->match_type) && + strv_isempty(link->match_name) && strv_isempty(link->match_property) && !link->conditions) + log_warning("%s: No valid settings found in the [Match] section. " + "The file will match all interfaces. " + "If that is intended, please add OriginalName=* in the [Match] section.", + filename); + + if (!condition_test_list(link->conditions, NULL, NULL, NULL)) { + log_debug("%s: Conditions do not match the system environment, skipping.", filename); + return 0; + } + + log_debug("Parsed configuration file %s", filename); + + LIST_PREPEND(links, ctx->links, TAKE_PTR(link)); + return 0; +} + +static bool enable_name_policy(void) { + bool b; + + return proc_cmdline_get_bool("net.ifnames", &b) <= 0 || b; +} + +static int link_unsigned_attribute(sd_device *device, const char *attr, unsigned *type) { + const char *s; + int r; + + r = sd_device_get_sysattr_value(device, attr, &s); + if (r < 0) + return log_device_debug_errno(device, r, "Failed to query %s: %m", attr); + + r = safe_atou(s, type); + if (r < 0) + return log_device_warning_errno(device, r, "Failed to parse %s \"%s\": %m", attr, s); + + log_device_debug(device, "Device has %s=%u", attr, *type); + return 0; +} + +int link_config_load(link_config_ctx *ctx) { + _cleanup_strv_free_ char **files; + char **f; + int r; + + link_configs_free(ctx); + + if (!enable_name_policy()) { + ctx->enable_name_policy = false; + log_info("Network interface NamePolicy= disabled on kernel command line, ignoring."); + } + + /* update timestamp */ + paths_check_timestamp(NETWORK_DIRS, &ctx->network_dirs_ts_usec, true); + + r = conf_files_list_strv(&files, ".link", NULL, 0, NETWORK_DIRS); + if (r < 0) + return log_error_errno(r, "failed to enumerate link files: %m"); + + STRV_FOREACH_BACKWARDS(f, files) { + r = link_load_one(ctx, *f); + if (r < 0) + log_error_errno(r, "Failed to load %s, ignoring: %m", *f); + } + + return 0; +} + +bool link_config_should_reload(link_config_ctx *ctx) { + return paths_check_timestamp(NETWORK_DIRS, &ctx->network_dirs_ts_usec, false); +} + +int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) { + link_config *link; + + assert(ctx); + assert(device); + assert(ret); + + LIST_FOREACH(links, link, ctx->links) { + if (net_match_config(link->match_mac, link->match_path, link->match_driver, + link->match_type, link->match_name, link->match_property, NULL, NULL, NULL, + device, NULL, NULL, 0, NULL, NULL)) { + if (link->match_name && !strv_contains(link->match_name, "*")) { + unsigned name_assign_type = NET_NAME_UNKNOWN; + + (void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type); + + if (name_assign_type == NET_NAME_ENUM) { + log_device_warning(device, "Config file %s applies to device based on potentially unpredictable interface name", + link->filename); + *ret = link; + + return 0; + } else if (name_assign_type == NET_NAME_RENAMED) { + log_device_warning(device, "Config file %s matches device based on renamed interface name, ignoring", + link->filename); + + continue; + } + } + + log_device_debug(device, "Config file %s is applied", link->filename); + + *ret = link; + return 0; + } + } + + *ret = NULL; + return -ENOENT; +} + +static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr *mac) { + unsigned addr_type; + bool want_random = policy == MAC_ADDRESS_POLICY_RANDOM; + int r; + + assert(IN_SET(policy, MAC_ADDRESS_POLICY_RANDOM, MAC_ADDRESS_POLICY_PERSISTENT)); + + r = link_unsigned_attribute(device, "addr_assign_type", &addr_type); + if (r < 0) + return r; + switch (addr_type) { + case NET_ADDR_SET: + return log_device_debug(device, "MAC on the device already set by userspace"); + case NET_ADDR_STOLEN: + return log_device_debug(device, "MAC on the device already set based on another device"); + case NET_ADDR_RANDOM: + case NET_ADDR_PERM: + break; + default: + return log_device_warning(device, "Unknown addr_assign_type %u, ignoring", addr_type); + } + + if (want_random == (addr_type == NET_ADDR_RANDOM)) + return log_device_debug(device, "MAC on the device already matches policy *%s*", + mac_address_policy_to_string(policy)); + + if (want_random) { + log_device_debug(device, "Using random bytes to generate MAC"); + random_bytes(mac->ether_addr_octet, ETH_ALEN); + } else { + uint64_t result; + + r = net_get_unique_predictable_data(device, + naming_scheme_has(NAMING_STABLE_VIRTUAL_MACS), + &result); + if (r < 0) + return log_device_warning_errno(device, r, "Could not generate persistent MAC: %m"); + + log_device_debug(device, "Using generated persistent MAC address"); + assert_cc(ETH_ALEN <= sizeof(result)); + memcpy(mac->ether_addr_octet, &result, ETH_ALEN); + } + + /* see eth_random_addr in the kernel */ + mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */ + mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */ + return 1; +} + +int link_config_apply(link_config_ctx *ctx, link_config *config, + sd_device *device, const char **name) { + struct ether_addr generated_mac; + struct ether_addr *mac = NULL; + const char *new_name = NULL; + const char *old_name; + unsigned speed, name_type = NET_NAME_UNKNOWN; + NamePolicy policy; + int r, ifindex; + + assert(ctx); + assert(config); + assert(device); + assert(name); + + r = sd_device_get_sysname(device, &old_name); + if (r < 0) + return r; + + r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, + config->autonegotiation, config->advertise, + config->speed, config->duplex, config->port); + if (r < 0) { + + if (config->port != _NET_DEV_PORT_INVALID) + log_warning_errno(r, "Could not set port (%s) of %s: %m", port_to_string(config->port), old_name); + + if (!eqzero(config->advertise)) + log_warning_errno(r, "Could not set advertise mode: %m"); /* TODO: include modes in the log message. */ + + if (config->speed) { + speed = DIV_ROUND_UP(config->speed, 1000000); + if (r == -EOPNOTSUPP) { + r = ethtool_set_speed(&ctx->ethtool_fd, old_name, speed, config->duplex); + if (r < 0) + log_warning_errno(r, "Could not set speed of %s to %u Mbps: %m", old_name, speed); + } + } + + if (config->duplex != _DUP_INVALID) + log_warning_errno(r, "Could not set duplex of %s to %s: %m", old_name, duplex_to_string(config->duplex)); + } + + r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol); + if (r < 0) + log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m", + old_name, wol_to_string(config->wol)); + + r = ethtool_set_features(&ctx->ethtool_fd, old_name, config->features); + if (r < 0) + log_warning_errno(r, "Could not set offload features of %s: %m", old_name); + + if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) { + r = ethtool_set_channels(&ctx->ethtool_fd, old_name, &config->channels); + if (r < 0) + log_warning_errno(r, "Could not set channels of %s: %m", old_name); + } + + if (config->ring.rx_pending_set || config->ring.tx_pending_set) { + r = ethtool_set_nic_buffer_size(&ctx->ethtool_fd, old_name, &config->ring); + if (r < 0) + log_warning_errno(r, "Could not set ring buffer of %s: %m", old_name); + } + + r = sd_device_get_ifindex(device, &ifindex); + if (r < 0) + return log_device_warning_errno(device, r, "Could not find ifindex: %m"); + + (void) link_unsigned_attribute(device, "name_assign_type", &name_type); + + if (IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED) + && !naming_scheme_has(NAMING_ALLOW_RERENAMES)) { + log_device_debug(device, "Device already has a name given by userspace, not renaming."); + goto no_rename; + } + + if (ctx->enable_name_policy && config->name_policy) + for (NamePolicy *p = config->name_policy; !new_name && *p != _NAMEPOLICY_INVALID; p++) { + policy = *p; + + switch (policy) { + case NAMEPOLICY_KERNEL: + if (name_type != NET_NAME_PREDICTABLE) + continue; + + /* The kernel claims to have given a predictable name, keep it. */ + log_device_debug(device, "Policy *%s*: keeping predictable kernel name", + name_policy_to_string(policy)); + goto no_rename; + case NAMEPOLICY_KEEP: + if (!IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED)) + continue; + + log_device_debug(device, "Policy *%s*: keeping existing userspace name", + name_policy_to_string(policy)); + goto no_rename; + case NAMEPOLICY_DATABASE: + (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name); + break; + case NAMEPOLICY_ONBOARD: + (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name); + break; + case NAMEPOLICY_SLOT: + (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name); + break; + case NAMEPOLICY_PATH: + (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name); + break; + case NAMEPOLICY_MAC: + (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name); + break; + default: + assert_not_reached("invalid policy"); + } + } + + if (new_name) + log_device_debug(device, "Policy *%s* yields \"%s\".", name_policy_to_string(policy), new_name); + else if (config->name) { + new_name = config->name; + log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", new_name); + } else + log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming."); + no_rename: + + if (IN_SET(config->mac_address_policy, MAC_ADDRESS_POLICY_PERSISTENT, MAC_ADDRESS_POLICY_RANDOM)) { + if (get_mac(device, config->mac_address_policy, &generated_mac) > 0) + mac = &generated_mac; + } else + mac = config->mac; + + r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac, config->mtu); + if (r < 0) + return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name); + + *name = new_name; + + return 0; +} + +int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret) { + const char *name; + char *driver = NULL; + int r; + + r = sd_device_get_sysname(device, &name); + if (r < 0) + return r; + + r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver); + if (r < 0) + return r; + + *ret = driver; + return 0; +} + +static const char* const mac_address_policy_table[_MAC_ADDRESS_POLICY_MAX] = { + [MAC_ADDRESS_POLICY_PERSISTENT] = "persistent", + [MAC_ADDRESS_POLICY_RANDOM] = "random", + [MAC_ADDRESS_POLICY_NONE] = "none", +}; + +DEFINE_STRING_TABLE_LOOKUP(mac_address_policy, MACAddressPolicy); +DEFINE_CONFIG_PARSE_ENUM(config_parse_mac_address_policy, mac_address_policy, MACAddressPolicy, + "Failed to parse MAC address policy"); + +static const char* const name_policy_table[_NAMEPOLICY_MAX] = { + [NAMEPOLICY_KERNEL] = "kernel", + [NAMEPOLICY_KEEP] = "keep", + [NAMEPOLICY_DATABASE] = "database", + [NAMEPOLICY_ONBOARD] = "onboard", + [NAMEPOLICY_SLOT] = "slot", + [NAMEPOLICY_PATH] = "path", + [NAMEPOLICY_MAC] = "mac", +}; + +DEFINE_STRING_TABLE_LOOKUP(name_policy, NamePolicy); +DEFINE_CONFIG_PARSE_ENUMV(config_parse_name_policy, name_policy, NamePolicy, + _NAMEPOLICY_INVALID, + "Failed to parse interface name policy"); diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h new file mode 100644 index 00000000..52a02b9b --- /dev/null +++ b/src/udev/net/link-config.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "sd-device.h" + +#include "condition.h" +#include "conf-parser.h" +#include "ethtool-util.h" +#include "list.h" +#include "set.h" + +typedef struct link_config_ctx link_config_ctx; +typedef struct link_config link_config; + +typedef enum MACAddressPolicy { + MAC_ADDRESS_POLICY_PERSISTENT, + MAC_ADDRESS_POLICY_RANDOM, + MAC_ADDRESS_POLICY_NONE, + _MAC_ADDRESS_POLICY_MAX, + _MAC_ADDRESS_POLICY_INVALID = -1 +} MACAddressPolicy; + +typedef enum NamePolicy { + NAMEPOLICY_KERNEL, + NAMEPOLICY_KEEP, + NAMEPOLICY_DATABASE, + NAMEPOLICY_ONBOARD, + NAMEPOLICY_SLOT, + NAMEPOLICY_PATH, + NAMEPOLICY_MAC, + _NAMEPOLICY_MAX, + _NAMEPOLICY_INVALID = -1 +} NamePolicy; + +struct link_config { + char *filename; + + Set *match_mac; + char **match_path; + char **match_driver; + char **match_type; + char **match_name; + char **match_property; + LIST_HEAD(Condition, conditions); + + char *description; + struct ether_addr *mac; + MACAddressPolicy mac_address_policy; + NamePolicy *name_policy; + char *name; + char *alias; + uint32_t mtu; + size_t speed; + Duplex duplex; + int autonegotiation; + uint32_t advertise[N_ADVERTISE]; + WakeOnLan wol; + NetDevPort port; + int features[_NET_DEV_FEAT_MAX]; + netdev_channels channels; + netdev_ring_param ring; + + LIST_FIELDS(link_config, links); +}; + +int link_config_ctx_new(link_config_ctx **ret); +void link_config_ctx_free(link_config_ctx *ctx); +DEFINE_TRIVIAL_CLEANUP_FUNC(link_config_ctx*, link_config_ctx_free); + +int link_load_one(link_config_ctx *ctx, const char *filename); +int link_config_load(link_config_ctx *ctx); +bool link_config_should_reload(link_config_ctx *ctx); + +int link_config_get(link_config_ctx *ctx, sd_device *device, struct link_config **ret); +int link_config_apply(link_config_ctx *ctx, struct link_config *config, sd_device *device, const char **name); +int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret); + +const char *name_policy_to_string(NamePolicy p) _const_; +NamePolicy name_policy_from_string(const char *p) _pure_; + +const char *mac_address_policy_to_string(MACAddressPolicy p) _const_; +MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_; + +/* gperf lookup function */ +const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN_TYPE length); + +CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy); +CONFIG_PARSER_PROTOTYPE(config_parse_name_policy); diff --git a/src/udev/net/naming-scheme.c b/src/udev/net/naming-scheme.c new file mode 100644 index 00000000..0d7f413e --- /dev/null +++ b/src/udev/net/naming-scheme.c @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#include "alloc-util.h" +#include "naming-scheme.h" +#include "proc-cmdline.h" +#include "string-util.h" + +static const NamingScheme naming_schemes[] = { + { "v238", NAMING_V238 }, + { "v239", NAMING_V239 }, + { "v240", NAMING_V240 }, + { "v241", NAMING_V241 }, + { "v243", NAMING_V243 }, + /* … add more schemes here, as the logic to name devices is updated … */ +}; + +static const NamingScheme* naming_scheme_from_name(const char *name) { + size_t i; + + if (streq(name, "latest")) + return naming_schemes + ELEMENTSOF(naming_schemes) - 1; + + for (i = 0; i < ELEMENTSOF(naming_schemes); i++) + if (streq(naming_schemes[i].name, name)) + return naming_schemes + i; + + return NULL; +} + +const NamingScheme* naming_scheme(void) { + static const NamingScheme *cache = NULL; + _cleanup_free_ char *buffer = NULL; + const char *e, *k; + + if (cache) + return cache; + + /* Acquire setting from the kernel command line */ + (void) proc_cmdline_get_key("net.naming-scheme", 0, &buffer); + + /* Also acquire it from an env var */ + e = getenv("NET_NAMING_SCHEME"); + if (e) { + if (*e == ':') { + /* If prefixed with ':' the kernel cmdline takes precedence */ + k = buffer ?: e + 1; + } else + k = e; /* Otherwise the env var takes precedence */ + } else + k = buffer; + + if (k) { + cache = naming_scheme_from_name(k); + if (cache) { + log_info("Using interface naming scheme '%s'.", cache->name); + return cache; + } + + log_warning("Unknown interface naming scheme '%s' requested, ignoring.", k); + } + + cache = naming_scheme_from_name(DEFAULT_NET_NAMING_SCHEME); + assert(cache); + log_info("Using default interface naming scheme '%s'.", cache->name); + + return cache; +} diff --git a/src/udev/net/naming-scheme.h b/src/udev/net/naming-scheme.h new file mode 100644 index 00000000..38dfa75f --- /dev/null +++ b/src/udev/net/naming-scheme.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "macro.h" + +/* So here's the deal: net_id is supposed to be an exercise in providing stable names for network devices. However, we + * also want to keep updating the naming scheme used in future versions of net_id. These two goals of course are + * contradictory: on one hand we want things to not change and on the other hand we want them to improve. Our way out + * of this dilemma is to introduce the "naming scheme" concept: each time we improve the naming logic we define a new + * flag for it. Then, we keep a list of schemes, each identified by a name associated with the flags it implements. Via + * a kernel command line and environment variable we then allow the user to pick the scheme they want us to follow: + * installers could "freeze" the used scheme at the moment of installation this way. + * + * Developers: each time you tweak the naming logic here, define a new flag below, and condition the tweak with + * it. Each time we do a release we'll then add a new scheme entry and include all newly defined flags. + * + * Note that this is only half a solution to the problem though: not only udev/net_id gets updated all the time, the + * kernel gets too. And thus a kernel that previously didn't expose some sysfs attribute we look for might eventually + * do, and thus affect our naming scheme too. Thus, enforcing a naming scheme will make interfacing more stable across + * OS versions, but not fully stabilize them. */ +typedef enum NamingSchemeFlags { + /* First, the individual features */ + NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a */ + NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6ea */ + NAMING_INFINIBAND = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df */ + NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Use zero acpi_index field, see d81186ef4f6a */ + NAMING_ALLOW_RERENAMES = 1 << 4, /* Allow re-renaming of devices, see #9006 */ + NAMING_STABLE_VIRTUAL_MACS = 1 << 5, /* Use device name to generate MAC, see 6d3646406560 */ + NAMING_NETDEVSIM = 1 << 6, /* Generate names for netdevsim devices, see eaa9d507d855 */ + NAMING_LABEL_NOPREFIX = 1 << 7, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */ + + /* And now the masks that combine the features above */ + NAMING_V238 = 0, + NAMING_V239 = NAMING_V238 | NAMING_SR_IOV_V | NAMING_NPAR_ARI, + NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES, + NAMING_V241 = NAMING_V240 | NAMING_STABLE_VIRTUAL_MACS, + NAMING_V243 = NAMING_V241 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX, + + _NAMING_SCHEME_FLAGS_INVALID = -1, +} NamingSchemeFlags; + +typedef struct NamingScheme { + const char *name; + NamingSchemeFlags flags; +} NamingScheme; + +const NamingScheme* naming_scheme(void); + +static inline bool naming_scheme_has(NamingSchemeFlags flags) { + return FLAGS_SET(naming_scheme()->flags, flags); +} diff --git a/src/udev/scsi_id/README b/src/udev/scsi_id/README new file mode 100644 index 00000000..9cfe7399 --- /dev/null +++ b/src/udev/scsi_id/README @@ -0,0 +1,4 @@ +scsi_id - generate a SCSI unique identifier for a given SCSI device + +Please send questions, comments or patches to or +. diff --git a/src/udev/scsi_id/scsi.h b/src/udev/scsi_id/scsi.h new file mode 100644 index 00000000..208b3e72 --- /dev/null +++ b/src/udev/scsi_id/scsi.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +/* + * scsi.h + * + * General scsi and linux scsi specific defines and structs. + * + * Copyright (C) IBM Corp. 2003 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2 of the License. + */ + +#include + +struct scsi_ioctl_command { + unsigned inlen; /* excluding scsi command length */ + unsigned outlen; + unsigned char data[1]; + /* on input, scsi command starts here then opt. data */ +}; + +/* + * Default 5 second timeout + */ +#define DEF_TIMEOUT 5000 + +#define SENSE_BUFF_LEN 32 + +/* + * The request buffer size passed to the SCSI INQUIRY commands, use 254, + * as this is a nice value for some devices, especially some of the usb + * mass storage devices. + */ +#define SCSI_INQ_BUFF_LEN 254 + +/* + * SCSI INQUIRY vendor and model (really product) lengths. + */ +#define VENDOR_LENGTH 8 +#define MODEL_LENGTH 16 + +#define INQUIRY_CMD 0x12 +#define INQUIRY_CMDLEN 6 + +/* + * INQUIRY VPD page 0x83 identifier descriptor related values. Reference the + * SCSI Primary Commands specification for details. + */ + +/* + * id type values of id descriptors. These are assumed to fit in 4 bits. + */ +#define SCSI_ID_VENDOR_SPECIFIC 0 +#define SCSI_ID_T10_VENDOR 1 +#define SCSI_ID_EUI_64 2 +#define SCSI_ID_NAA 3 +#define SCSI_ID_RELPORT 4 +#define SCSI_ID_TGTGROUP 5 +#define SCSI_ID_LUNGROUP 6 +#define SCSI_ID_MD5 7 +#define SCSI_ID_NAME 8 + +/* + * Supported NAA values. These fit in 4 bits, so the "don't care" value + * cannot conflict with real values. + */ +#define SCSI_ID_NAA_DONT_CARE 0xff +#define SCSI_ID_NAA_IEEE_REG 0x05 +#define SCSI_ID_NAA_IEEE_REG_EXTENDED 0x06 + +/* + * Supported Code Set values. + */ +#define SCSI_ID_BINARY 1 +#define SCSI_ID_ASCII 2 + +struct scsi_id_search_values { + u_char id_type; + u_char naa_type; + u_char code_set; +}; + +/* + * Following are the "true" SCSI status codes. Linux has traditionally + * used a 1 bit right and masked version of these. So now CHECK_CONDITION + * and friends (in ) are deprecated. + */ +#define SCSI_CHECK_CONDITION 0x02 +#define SCSI_CONDITION_MET 0x04 +#define SCSI_BUSY 0x08 +#define SCSI_IMMEDIATE 0x10 +#define SCSI_IMMEDIATE_CONDITION_MET 0x14 +#define SCSI_RESERVATION_CONFLICT 0x18 +#define SCSI_COMMAND_TERMINATED 0x22 +#define SCSI_TASK_SET_FULL 0x28 +#define SCSI_ACA_ACTIVE 0x30 +#define SCSI_TASK_ABORTED 0x40 diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c new file mode 100644 index 00000000..94c3b232 --- /dev/null +++ b/src/udev/scsi_id/scsi_id.c @@ -0,0 +1,596 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright © IBM Corp. 2003 + * Copyright © SUSE Linux Products GmbH, 2006 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "build.h" +#include "fd-util.h" +#include "libudev-util.h" +#include "scsi_id.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "udev-util.h" + +static const struct option options[] = { + { "device", required_argument, NULL, 'd' }, + { "config", required_argument, NULL, 'f' }, + { "page", required_argument, NULL, 'p' }, + { "blacklisted", no_argument, NULL, 'b' }, + { "whitelisted", no_argument, NULL, 'g' }, + { "replace-whitespace", no_argument, NULL, 'u' }, + { "sg-version", required_argument, NULL, 's' }, + { "verbose", no_argument, NULL, 'v' }, + { "version", no_argument, NULL, 'V' }, /* don't advertise -V */ + { "export", no_argument, NULL, 'x' }, + { "help", no_argument, NULL, 'h' }, + {} +}; + +static bool all_good = false; +static bool dev_specified = false; +static char config_file[MAX_PATH_LEN] = "/etc/scsi_id.config"; +static enum page_code default_page_code = PAGE_UNSPECIFIED; +static int sg_version = 4; +static bool reformat_serial = false; +static bool export = false; +static char vendor_str[64]; +static char model_str[64]; +static char vendor_enc_str[256]; +static char model_enc_str[256]; +static char revision_str[16]; +static char type_str[16]; + +static void set_type(const char *from, char *to, size_t len) { + int type_num; + char *eptr; + const char *type = "generic"; + + type_num = strtoul(from, &eptr, 0); + if (eptr != from) { + switch (type_num) { + case 0: + type = "disk"; + break; + case 1: + type = "tape"; + break; + case 4: + type = "optical"; + break; + case 5: + type = "cd"; + break; + case 7: + type = "optical"; + break; + case 0xe: + type = "disk"; + break; + case 0xf: + type = "optical"; + break; + default: + break; + } + } + strscpy(to, len, type); +} + +/* + * get_value: + * + * buf points to an '=' followed by a quoted string ("foo") or a string ending + * with a space or ','. + * + * Return a pointer to the NUL terminated string, returns NULL if no + * matches. + */ +static char *get_value(char **buffer) { + static const char *quote_string = "\"\n"; + static const char *comma_string = ",\n"; + char *val; + const char *end; + + if (**buffer == '"') { + /* + * skip leading quote, terminate when quote seen + */ + (*buffer)++; + end = quote_string; + } else { + end = comma_string; + } + val = strsep(buffer, end); + if (val && end == quote_string) + /* + * skip trailing quote + */ + (*buffer)++; + + while (isspace(**buffer)) + (*buffer)++; + + return val; +} + +static int argc_count(char *opts) { + int i = 0; + while (*opts != '\0') + if (*opts++ == ' ') + i++; + return i; +} + +/* + * get_file_options: + * + * If vendor == NULL, find a line in the config file with only "OPTIONS="; + * if vendor and model are set find the first OPTIONS line in the config + * file that matches. Set argc and argv to match the OPTIONS string. + * + * vendor and model can end in '\n'. + */ +static int get_file_options(const char *vendor, const char *model, + int *argc, char ***newargv) { + _cleanup_free_ char *buffer = NULL; + _cleanup_fclose_ FILE *f; + char *buf; + char *str1; + char *vendor_in, *model_in, *options_in; /* read in from file */ + int lineno; + int c; + int retval = 0; + + f = fopen(config_file, "re"); + if (!f) { + if (errno == ENOENT) + return 1; + else { + log_error_errno(errno, "can't open %s: %m", config_file); + return -1; + } + } + + /* + * Allocate a buffer rather than put it on the stack so we can + * keep it around to parse any options (any allocated newargv + * points into this buffer for its strings). + */ + buffer = malloc(MAX_BUFFER_LEN); + if (!buffer) + return log_oom(); + + *newargv = NULL; + lineno = 0; + for (;;) { + vendor_in = model_in = options_in = NULL; + + buf = fgets(buffer, MAX_BUFFER_LEN, f); + if (!buf) + break; + lineno++; + if (buf[strlen(buffer) - 1] != '\n') { + log_error("Config file line %d too long", lineno); + break; + } + + while (isspace(*buf)) + buf++; + + /* blank or all whitespace line */ + if (*buf == '\0') + continue; + + /* comment line */ + if (*buf == '#') + continue; + + str1 = strsep(&buf, "="); + if (str1 && strcaseeq(str1, "VENDOR")) { + str1 = get_value(&buf); + if (!str1) { + retval = log_oom(); + break; + } + vendor_in = str1; + + str1 = strsep(&buf, "="); + if (str1 && strcaseeq(str1, "MODEL")) { + str1 = get_value(&buf); + if (!str1) { + retval = log_oom(); + break; + } + model_in = str1; + str1 = strsep(&buf, "="); + } + } + + if (str1 && strcaseeq(str1, "OPTIONS")) { + str1 = get_value(&buf); + if (!str1) { + retval = log_oom(); + break; + } + options_in = str1; + } + + /* + * Only allow: [vendor=foo[,model=bar]]options=stuff + */ + if (!options_in || (!vendor_in && model_in)) { + log_error("Error parsing config file line %d '%s'", lineno, buffer); + retval = -1; + break; + } + if (vendor == NULL) { + if (!vendor_in) + break; + } else if (vendor_in && + startswith(vendor, vendor_in) && + (!model_in || startswith(model, model_in))) { + /* + * Matched vendor and optionally model. + * + * Note: a short vendor_in or model_in can + * give a partial match (that is FOO + * matches FOOBAR). + */ + break; + } + } + + if (retval == 0) { + if (vendor_in != NULL || model_in != NULL || + options_in != NULL) { + /* + * Something matched. Allocate newargv, and store + * values found in options_in. + */ + strcpy(buffer, options_in); + c = argc_count(buffer) + 2; + *newargv = calloc(c, sizeof(**newargv)); + if (!*newargv) + retval = log_oom(); + else { + *argc = c; + c = 0; + /* + * argv[0] at 0 is skipped by getopt, but + * store the buffer address there for + * later freeing + */ + (*newargv)[c] = buffer; + for (c = 1; c < *argc; c++) + (*newargv)[c] = strsep(&buffer, " \t"); + buffer = NULL; + } + } else { + /* No matches */ + retval = 1; + } + } + return retval; +} + +static void help(void) { + printf("Usage: %s [OPTION...] DEVICE\n\n" + "SCSI device identification.\n\n" + " -h --help Print this message\n" + " --version Print version of the program\n\n" + " -d --device= Device node for SG_IO commands\n" + " -f --config= Location of config file\n" + " -p --page=0x80|0x83|pre-spc3-83 SCSI page (0x80, 0x83, pre-spc3-83)\n" + " -s --sg-version=3|4 Use SGv3 or SGv4\n" + " -b --blacklisted Treat device as blacklisted\n" + " -g --whitelisted Treat device as whitelisted\n" + " -u --replace-whitespace Replace all whitespace by underscores\n" + " -v --verbose Verbose logging\n" + " -x --export Print values as environment keys\n" + , program_invocation_short_name); + +} + +static int set_options(int argc, char **argv, + char *maj_min_dev) { + int option; + + /* + * optind is a global extern used by getopt. Since we can call + * set_options twice (once for command line, and once for config + * file) we have to reset this back to 1. + */ + optind = 1; + while ((option = getopt_long(argc, argv, "d:f:gp:uvVxhbs:", options, NULL)) >= 0) + switch (option) { + case 'b': + all_good = false; + break; + + case 'd': + dev_specified = true; + strscpy(maj_min_dev, MAX_PATH_LEN, optarg); + break; + + case 'f': + strscpy(config_file, MAX_PATH_LEN, optarg); + break; + + case 'g': + all_good = true; + break; + + case 'h': + help(); + exit(EXIT_SUCCESS); + + case 'p': + if (streq(optarg, "0x80")) + default_page_code = PAGE_80; + else if (streq(optarg, "0x83")) + default_page_code = PAGE_83; + else if (streq(optarg, "pre-spc3-83")) + default_page_code = PAGE_83_PRE_SPC3; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown page code '%s'", + optarg); + break; + + case 's': + sg_version = atoi(optarg); + if (sg_version < 3 || sg_version > 4) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Unknown SG version '%s'", + optarg); + break; + + case 'u': + reformat_serial = true; + break; + + case 'v': + log_set_target(LOG_TARGET_CONSOLE); + log_set_max_level(LOG_DEBUG); + log_open(); + break; + + case 'V': + printf("%s\n", GIT_VERSION); + exit(EXIT_SUCCESS); + + case 'x': + export = true; + break; + + case '?': + return -1; + + default: + assert_not_reached("Unknown option"); + } + + if (optind < argc && !dev_specified) { + dev_specified = true; + strscpy(maj_min_dev, MAX_PATH_LEN, argv[optind]); + } + + return 0; +} + +static int per_dev_options(struct scsi_id_device *dev_scsi, int *good_bad, int *page_code) { + int retval; + int newargc; + char **newargv = NULL; + int option; + + *good_bad = all_good; + *page_code = default_page_code; + + retval = get_file_options(vendor_str, model_str, &newargc, &newargv); + + optind = 1; /* reset this global extern */ + while (retval == 0) { + option = getopt_long(newargc, newargv, "bgp:", options, NULL); + if (option == -1) + break; + + switch (option) { + case 'b': + *good_bad = 0; + break; + + case 'g': + *good_bad = 1; + break; + + case 'p': + if (streq(optarg, "0x80")) { + *page_code = PAGE_80; + } else if (streq(optarg, "0x83")) { + *page_code = PAGE_83; + } else if (streq(optarg, "pre-spc3-83")) { + *page_code = PAGE_83_PRE_SPC3; + } else { + log_error("Unknown page code '%s'", optarg); + retval = -1; + } + break; + + default: + log_error("Unknown or bad option '%c' (0x%x)", option, option); + retval = -1; + break; + } + } + + if (newargv) { + free(newargv[0]); + free(newargv); + } + return retval; +} + +static int set_inq_values(struct scsi_id_device *dev_scsi, const char *path) { + int retval; + + dev_scsi->use_sg = sg_version; + + retval = scsi_std_inquiry(dev_scsi, path); + if (retval) + return retval; + + udev_util_encode_string(dev_scsi->vendor, vendor_enc_str, sizeof(vendor_enc_str)); + udev_util_encode_string(dev_scsi->model, model_enc_str, sizeof(model_enc_str)); + + util_replace_whitespace(dev_scsi->vendor, vendor_str, sizeof(vendor_str)-1); + util_replace_chars(vendor_str, NULL); + util_replace_whitespace(dev_scsi->model, model_str, sizeof(model_str)-1); + util_replace_chars(model_str, NULL); + set_type(dev_scsi->type, type_str, sizeof(type_str)); + util_replace_whitespace(dev_scsi->revision, revision_str, sizeof(revision_str)-1); + util_replace_chars(revision_str, NULL); + return 0; +} + +/* + * scsi_id: try to get an id, if one is found, printf it to stdout. + * returns a value passed to exit() - 0 if printed an id, else 1. + */ +static int scsi_id(char *maj_min_dev) { + struct scsi_id_device dev_scsi = {}; + int good_dev; + int page_code; + int retval = 0; + + if (set_inq_values(&dev_scsi, maj_min_dev) < 0) { + retval = 1; + goto out; + } + + /* get per device (vendor + model) options from the config file */ + per_dev_options(&dev_scsi, &good_dev, &page_code); + if (!good_dev) { + retval = 1; + goto out; + } + + /* read serial number from mode pages (no values for optical drives) */ + scsi_get_serial(&dev_scsi, maj_min_dev, page_code, MAX_SERIAL_LEN); + + if (export) { + char serial_str[MAX_SERIAL_LEN]; + + printf("ID_SCSI=1\n"); + printf("ID_VENDOR=%s\n", vendor_str); + printf("ID_VENDOR_ENC=%s\n", vendor_enc_str); + printf("ID_MODEL=%s\n", model_str); + printf("ID_MODEL_ENC=%s\n", model_enc_str); + printf("ID_REVISION=%s\n", revision_str); + printf("ID_TYPE=%s\n", type_str); + if (dev_scsi.serial[0] != '\0') { + util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)-1); + util_replace_chars(serial_str, NULL); + printf("ID_SERIAL=%s\n", serial_str); + util_replace_whitespace(dev_scsi.serial_short, serial_str, sizeof(serial_str)-1); + util_replace_chars(serial_str, NULL); + printf("ID_SERIAL_SHORT=%s\n", serial_str); + } + if (dev_scsi.wwn[0] != '\0') { + printf("ID_WWN=0x%s\n", dev_scsi.wwn); + if (dev_scsi.wwn_vendor_extension[0] != '\0') { + printf("ID_WWN_VENDOR_EXTENSION=0x%s\n", dev_scsi.wwn_vendor_extension); + printf("ID_WWN_WITH_EXTENSION=0x%s%s\n", dev_scsi.wwn, dev_scsi.wwn_vendor_extension); + } else + printf("ID_WWN_WITH_EXTENSION=0x%s\n", dev_scsi.wwn); + } + if (dev_scsi.tgpt_group[0] != '\0') + printf("ID_TARGET_PORT=%s\n", dev_scsi.tgpt_group); + if (dev_scsi.unit_serial_number[0] != '\0') + printf("ID_SCSI_SERIAL=%s\n", dev_scsi.unit_serial_number); + goto out; + } + + if (dev_scsi.serial[0] == '\0') { + retval = 1; + goto out; + } + + if (reformat_serial) { + char serial_str[MAX_SERIAL_LEN]; + + util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)-1); + util_replace_chars(serial_str, NULL); + printf("%s\n", serial_str); + goto out; + } + + printf("%s\n", dev_scsi.serial); +out: + return retval; +} + +int main(int argc, char **argv) { + int retval = 0; + char maj_min_dev[MAX_PATH_LEN]; + int newargc; + char **newargv = NULL; + + log_set_target(LOG_TARGET_AUTO); + udev_parse_config(); + log_parse_environment(); + log_open(); + + /* + * Get config file options. + */ + retval = get_file_options(NULL, NULL, &newargc, &newargv); + if (retval < 0) { + retval = 1; + goto exit; + } + if (retval == 0) { + assert(newargv); + + if (set_options(newargc, newargv, maj_min_dev) < 0) { + retval = 2; + goto exit; + } + } + + /* + * Get command line options (overriding any config file settings). + */ + if (set_options(argc, argv, maj_min_dev) < 0) + exit(EXIT_FAILURE); + + if (!dev_specified) { + log_error("No device specified."); + retval = 1; + goto exit; + } + + retval = scsi_id(maj_min_dev); + +exit: + if (newargv) { + free(newargv[0]); + free(newargv); + } + log_close(); + return retval; +} diff --git a/src/udev/scsi_id/scsi_id.h b/src/udev/scsi_id/scsi_id.h new file mode 100644 index 00000000..70e804fb --- /dev/null +++ b/src/udev/scsi_id/scsi_id.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +/* + * Copyright © IBM Corp. 2003 + */ + +#define MAX_PATH_LEN 512 + +/* + * MAX_ATTR_LEN: maximum length of the result of reading a sysfs + * attribute. + */ +#define MAX_ATTR_LEN 256 + +/* + * MAX_SERIAL_LEN: the maximum length of the serial number, including + * added prefixes such as vendor and product (model) strings. + */ +#define MAX_SERIAL_LEN 256 + +/* + * MAX_BUFFER_LEN: maximum buffer size and line length used while reading + * the config file. + */ +#define MAX_BUFFER_LEN 256 + +struct scsi_id_device { + char vendor[9]; + char model[17]; + char revision[5]; + char type[33]; + char kernel[64]; + char serial[MAX_SERIAL_LEN]; + char serial_short[MAX_SERIAL_LEN]; + int use_sg; + + /* Always from page 0x80 e.g. 'B3G1P8500RWT' - may not be unique */ + char unit_serial_number[MAX_SERIAL_LEN]; + + /* NULs if not set - otherwise hex encoding using lower-case e.g. '50014ee0016eb572' */ + char wwn[17]; + + /* NULs if not set - otherwise hex encoding using lower-case e.g. '0xe00000d80000' */ + char wwn_vendor_extension[17]; + + /* NULs if not set - otherwise decimal number */ + char tgpt_group[8]; +}; + +int scsi_std_inquiry(struct scsi_id_device *dev_scsi, const char *devname); +int scsi_get_serial(struct scsi_id_device *dev_scsi, const char *devname, + int page_code, int len); + +/* + * Page code values. + */ +enum page_code { + PAGE_83_PRE_SPC3 = -0x83, + PAGE_UNSPECIFIED = 0x00, + PAGE_80 = 0x80, + PAGE_83 = 0x83, +}; diff --git a/src/udev/scsi_id/scsi_serial.c b/src/udev/scsi_id/scsi_serial.c new file mode 100644 index 00000000..7f25824d --- /dev/null +++ b/src/udev/scsi_id/scsi_serial.c @@ -0,0 +1,893 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright © IBM Corp. 2003 + * + * Author: Patrick Mansfield + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "memory-util.h" +#include "random-util.h" +#include "scsi.h" +#include "scsi_id.h" +#include "string-util.h" + +/* + * A priority based list of id, naa, and binary/ascii for the identifier + * descriptor in VPD page 0x83. + * + * Brute force search for a match starting with the first value in the + * following id_search_list. This is not a performance issue, since there + * is normally one or some small number of descriptors. + */ +static const struct scsi_id_search_values id_search_list[] = { + { SCSI_ID_TGTGROUP, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, + { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_BINARY }, + { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG_EXTENDED, SCSI_ID_ASCII }, + { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_BINARY }, + { SCSI_ID_NAA, SCSI_ID_NAA_IEEE_REG, SCSI_ID_ASCII }, + /* + * Devices already exist using NAA values that are now marked + * reserved. These should not conflict with other values, or it is + * a bug in the device. As long as we find the IEEE extended one + * first, we really don't care what other ones are used. Using + * don't care here means that a device that returns multiple + * non-IEEE descriptors in a random order will get different + * names. + */ + { SCSI_ID_NAA, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, + { SCSI_ID_NAA, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, + { SCSI_ID_EUI_64, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, + { SCSI_ID_EUI_64, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, + { SCSI_ID_T10_VENDOR, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, + { SCSI_ID_T10_VENDOR, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, + { SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_BINARY }, + { SCSI_ID_VENDOR_SPECIFIC, SCSI_ID_NAA_DONT_CARE, SCSI_ID_ASCII }, +}; + +static const char hex_str[]="0123456789abcdef"; + +/* + * Values returned in the result/status, only the ones used by the code + * are used here. + */ + +#define DID_NO_CONNECT 0x01 /* Unable to connect before timeout */ +#define DID_BUS_BUSY 0x02 /* Bus remain busy until timeout */ +#define DID_TIME_OUT 0x03 /* Timed out for some other reason */ +#define DRIVER_TIMEOUT 0x06 +#define DRIVER_SENSE 0x08 /* Sense_buffer has been set */ + +/* The following "category" function returns one of the following */ +#define SG_ERR_CAT_CLEAN 0 /* No errors or other information */ +#define SG_ERR_CAT_MEDIA_CHANGED 1 /* interpreted from sense buffer */ +#define SG_ERR_CAT_RESET 2 /* interpreted from sense buffer */ +#define SG_ERR_CAT_TIMEOUT 3 +#define SG_ERR_CAT_RECOVERED 4 /* Successful command after recovered err */ +#define SG_ERR_CAT_NOTSUPPORTED 5 /* Illegal / unsupported command */ +#define SG_ERR_CAT_SENSE 98 /* Something else in the sense buffer */ +#define SG_ERR_CAT_OTHER 99 /* Some other error/warning */ + +static int do_scsi_page80_inquiry(struct scsi_id_device *dev_scsi, int fd, + char *serial, char *serial_short, int max_len); + +static int sg_err_category_new(int scsi_status, int msg_status, int + host_status, int driver_status, const + unsigned char *sense_buffer, int sb_len) { + scsi_status &= 0x7e; + + /* + * XXX change to return only two values - failed or OK. + */ + + if (!scsi_status && !host_status && !driver_status) + return SG_ERR_CAT_CLEAN; + + if (IN_SET(scsi_status, SCSI_CHECK_CONDITION, SCSI_COMMAND_TERMINATED) || + (driver_status & 0xf) == DRIVER_SENSE) { + if (sense_buffer && (sb_len > 2)) { + int sense_key; + unsigned char asc; + + if (sense_buffer[0] & 0x2) { + sense_key = sense_buffer[1] & 0xf; + asc = sense_buffer[2]; + } else { + sense_key = sense_buffer[2] & 0xf; + asc = (sb_len > 12) ? sense_buffer[12] : 0; + } + + if (sense_key == RECOVERED_ERROR) + return SG_ERR_CAT_RECOVERED; + else if (sense_key == UNIT_ATTENTION) { + if (0x28 == asc) + return SG_ERR_CAT_MEDIA_CHANGED; + if (0x29 == asc) + return SG_ERR_CAT_RESET; + } else if (sense_key == ILLEGAL_REQUEST) + return SG_ERR_CAT_NOTSUPPORTED; + } + return SG_ERR_CAT_SENSE; + } + if (host_status) { + if (IN_SET(host_status, DID_NO_CONNECT, DID_BUS_BUSY, DID_TIME_OUT)) + return SG_ERR_CAT_TIMEOUT; + } + if (driver_status) { + if (driver_status == DRIVER_TIMEOUT) + return SG_ERR_CAT_TIMEOUT; + } + return SG_ERR_CAT_OTHER; +} + +static int sg_err_category3(struct sg_io_hdr *hp) { + return sg_err_category_new(hp->status, hp->msg_status, + hp->host_status, hp->driver_status, + hp->sbp, hp->sb_len_wr); +} + +static int sg_err_category4(struct sg_io_v4 *hp) { + return sg_err_category_new(hp->device_status, 0, + hp->transport_status, hp->driver_status, + (unsigned char *)(uintptr_t)hp->response, + hp->response_len); +} + +static int scsi_dump_sense(struct scsi_id_device *dev_scsi, + unsigned char *sense_buffer, int sb_len) { + int s; + int code; + int sense_class; + int sense_key; + int asc, ascq; + + /* + * Figure out and print the sense key, asc and ascq. + * + * If you want to suppress these for a particular drive model, add + * a black list entry in the scsi_id config file. + * + * XXX We probably need to: lookup the sense/asc/ascq in a retry + * table, and if found return 1 (after dumping the sense, asc, and + * ascq). So, if/when we get something like a power on/reset, + * we'll retry the command. + */ + + if (sb_len < 1) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: sense buffer empty", + dev_scsi->kernel); + + sense_class = (sense_buffer[0] >> 4) & 0x07; + code = sense_buffer[0] & 0xf; + + if (sense_class == 7) { + /* + * extended sense data. + */ + s = sense_buffer[7] + 8; + if (sb_len < s) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: sense buffer too small %d bytes, %d bytes too short", + dev_scsi->kernel, sb_len, + s - sb_len); + + if (IN_SET(code, 0x0, 0x1)) { + sense_key = sense_buffer[2] & 0xf; + if (s < 14) + /* + * Possible? + */ + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: sense result too small %d bytes", + dev_scsi->kernel, s); + + asc = sense_buffer[12]; + ascq = sense_buffer[13]; + } else if (IN_SET(code, 0x2, 0x3)) { + sense_key = sense_buffer[1] & 0xf; + asc = sense_buffer[2]; + ascq = sense_buffer[3]; + } else + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: invalid sense code 0x%x", + dev_scsi->kernel, code); + + log_debug("%s: sense key 0x%x ASC 0x%x ASCQ 0x%x", + dev_scsi->kernel, sense_key, asc, ascq); + } else { + if (sb_len < 4) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: sense buffer too small %d bytes, %d bytes too short", + dev_scsi->kernel, sb_len, + 4 - sb_len); + + if (sense_buffer[0] < 15) + log_debug("%s: old sense key: 0x%x", dev_scsi->kernel, sense_buffer[0] & 0x0f); + else + log_debug("%s: sense = %2x %2x", + dev_scsi->kernel, sense_buffer[0], sense_buffer[2]); + log_debug("%s: non-extended sense class %d code 0x%0x", + dev_scsi->kernel, sense_class, code); + + } + + return -1; +} + +static int scsi_dump(struct scsi_id_device *dev_scsi, struct sg_io_hdr *io) { + if (!io->status && !io->host_status && !io->msg_status && + !io->driver_status) + /* + * Impossible, should not be called. + */ + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: called with no error", + __FUNCTION__); + + log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x", + dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status); + if (io->status == SCSI_CHECK_CONDITION) + return scsi_dump_sense(dev_scsi, io->sbp, io->sb_len_wr); + else + return -1; +} + +static int scsi_dump_v4(struct scsi_id_device *dev_scsi, struct sg_io_v4 *io) { + if (!io->device_status && !io->transport_status && + !io->driver_status) + /* + * Impossible, should not be called. + */ + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: called with no error", + __FUNCTION__); + + log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x", + dev_scsi->kernel, io->driver_status, io->transport_status, io->device_status); + if (io->device_status == SCSI_CHECK_CONDITION) + return scsi_dump_sense(dev_scsi, (unsigned char *)(uintptr_t)io->response, + io->response_len); + else + return -1; +} + +static int scsi_inquiry(struct scsi_id_device *dev_scsi, int fd, + unsigned char evpd, unsigned char page, + unsigned char *buf, unsigned buflen) { + unsigned char inq_cmd[INQUIRY_CMDLEN] = + { INQUIRY_CMD, evpd, page, 0, buflen, 0 }; + unsigned char sense[SENSE_BUFF_LEN]; + void *io_buf; + struct sg_io_v4 io_v4; + struct sg_io_hdr io_hdr; + int retry = 3; /* rather random */ + int retval; + + if (buflen > SCSI_INQ_BUFF_LEN) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "buflen %d too long", buflen); + +resend: + if (dev_scsi->use_sg == 4) { + memzero(&io_v4, sizeof(struct sg_io_v4)); + io_v4.guard = 'Q'; + io_v4.protocol = BSG_PROTOCOL_SCSI; + io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD; + io_v4.request_len = sizeof(inq_cmd); + io_v4.request = (uintptr_t)inq_cmd; + io_v4.max_response_len = sizeof(sense); + io_v4.response = (uintptr_t)sense; + io_v4.din_xfer_len = buflen; + io_v4.din_xferp = (uintptr_t)buf; + io_buf = (void *)&io_v4; + } else { + memzero(&io_hdr, sizeof(struct sg_io_hdr)); + io_hdr.interface_id = 'S'; + io_hdr.cmd_len = sizeof(inq_cmd); + io_hdr.mx_sb_len = sizeof(sense); + io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; + io_hdr.dxfer_len = buflen; + io_hdr.dxferp = buf; + io_hdr.cmdp = inq_cmd; + io_hdr.sbp = sense; + io_hdr.timeout = DEF_TIMEOUT; + io_buf = (void *)&io_hdr; + } + + retval = ioctl(fd, SG_IO, io_buf); + if (retval < 0) { + if (IN_SET(errno, EINVAL, ENOSYS) && dev_scsi->use_sg == 4) { + dev_scsi->use_sg = 3; + goto resend; + } + log_debug_errno(errno, "%s: ioctl failed: %m", dev_scsi->kernel); + goto error; + } + + if (dev_scsi->use_sg == 4) + retval = sg_err_category4(io_buf); + else + retval = sg_err_category3(io_buf); + + switch (retval) { + case SG_ERR_CAT_NOTSUPPORTED: + buf[1] = 0; + _fallthrough_; + case SG_ERR_CAT_CLEAN: + case SG_ERR_CAT_RECOVERED: + retval = 0; + break; + + default: + if (dev_scsi->use_sg == 4) + retval = scsi_dump_v4(dev_scsi, io_buf); + else + retval = scsi_dump(dev_scsi, io_buf); + } + + if (!retval) { + retval = buflen; + } else if (retval > 0) { + if (--retry > 0) + goto resend; + retval = -1; + } + +error: + if (retval < 0) + log_debug("%s: Unable to get INQUIRY vpd %d page 0x%x.", + dev_scsi->kernel, evpd, page); + + return retval; +} + +/* Get list of supported EVPD pages */ +static int do_scsi_page0_inquiry(struct scsi_id_device *dev_scsi, int fd, + unsigned char *buffer, unsigned len) { + int retval; + + memzero(buffer, len); + retval = scsi_inquiry(dev_scsi, fd, 1, 0x0, buffer, len); + if (retval < 0) + return 1; + + if (buffer[1] != 0) { + log_debug("%s: page 0 not available.", dev_scsi->kernel); + return 1; + } + if (buffer[3] > len) { + log_debug("%s: page 0 buffer too long %d", dev_scsi->kernel, buffer[3]); + return 1; + } + + /* + * Following check is based on code once included in the 2.5.x + * kernel. + * + * Some ill behaved devices return the standard inquiry here + * rather than the evpd data, snoop the data to verify. + */ + if (buffer[3] > MODEL_LENGTH) { + /* + * If the vendor id appears in the page assume the page is + * invalid. + */ + if (strneq((char*) buffer + VENDOR_LENGTH, dev_scsi->vendor, VENDOR_LENGTH)) { + log_debug("%s: invalid page0 data", dev_scsi->kernel); + return 1; + } + } + return 0; +} + +static int append_vendor_model( + const struct scsi_id_device *dev_scsi, + char buf[static VENDOR_LENGTH + MODEL_LENGTH]) { + + assert(dev_scsi); + assert(buf); + + if (strnlen(dev_scsi->vendor, VENDOR_LENGTH) != VENDOR_LENGTH) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: bad vendor string \"%s\"", + dev_scsi->kernel, dev_scsi->vendor); + if (strnlen(dev_scsi->model, MODEL_LENGTH) != MODEL_LENGTH) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: bad model string \"%s\"", + dev_scsi->kernel, dev_scsi->model); + memcpy(buf, dev_scsi->vendor, VENDOR_LENGTH); + memcpy(buf + VENDOR_LENGTH, dev_scsi->model, MODEL_LENGTH); + return VENDOR_LENGTH + MODEL_LENGTH; +} + +/* + * check_fill_0x83_id - check the page 0x83 id, if OK allocate and fill + * serial number. + */ +static int check_fill_0x83_id(struct scsi_id_device *dev_scsi, + unsigned char *page_83, + const struct scsi_id_search_values + *id_search, char *serial, char *serial_short, + int max_len, char *wwn, + char *wwn_vendor_extension, char *tgpt_group) { + int i, j, s, len; + + /* + * ASSOCIATION must be with the device (value 0) + * or with the target port for SCSI_ID_TGTPORT + */ + if ((page_83[1] & 0x30) == 0x10) { + if (id_search->id_type != SCSI_ID_TGTGROUP) + return 1; + } else if ((page_83[1] & 0x30) != 0) + return 1; + + if ((page_83[1] & 0x0f) != id_search->id_type) + return 1; + + /* + * Possibly check NAA sub-type. + */ + if ((id_search->naa_type != SCSI_ID_NAA_DONT_CARE) && + (id_search->naa_type != (page_83[4] & 0xf0) >> 4)) + return 1; + + /* + * Check for matching code set - ASCII or BINARY. + */ + if ((page_83[0] & 0x0f) != id_search->code_set) + return 1; + + /* + * page_83[3]: identifier length + */ + len = page_83[3]; + if ((page_83[0] & 0x0f) != SCSI_ID_ASCII) + /* + * If not ASCII, use two bytes for each binary value. + */ + len *= 2; + + /* + * Add one byte for the NUL termination, and one for the id_type. + */ + len += 2; + if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) + len += VENDOR_LENGTH + MODEL_LENGTH; + + if (max_len < len) { + log_debug("%s: length %d too short - need %d", + dev_scsi->kernel, max_len, len); + return 1; + } + + if (id_search->id_type == SCSI_ID_TGTGROUP && tgpt_group != NULL) { + unsigned group; + + group = ((unsigned)page_83[6] << 8) | page_83[7]; + sprintf(tgpt_group,"%x", group); + return 1; + } + + serial[0] = hex_str[id_search->id_type]; + + /* + * For SCSI_ID_VENDOR_SPECIFIC prepend the vendor and model before + * the id since it is not unique across all vendors and models, + * this differs from SCSI_ID_T10_VENDOR, where the vendor is + * included in the identifier. + */ + if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) + if (append_vendor_model(dev_scsi, serial + 1) < 0) + return 1; + + i = 4; /* offset to the start of the identifier */ + s = j = strlen(serial); + if ((page_83[0] & 0x0f) == SCSI_ID_ASCII) { + /* + * ASCII descriptor. + */ + while (i < (4 + page_83[3])) + serial[j++] = page_83[i++]; + } else { + /* + * Binary descriptor, convert to ASCII, using two bytes of + * ASCII for each byte in the page_83. + */ + while (i < (4 + page_83[3])) { + serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4]; + serial[j++] = hex_str[page_83[i] & 0x0f]; + i++; + } + } + + strcpy(serial_short, serial + s); + + if (id_search->id_type == SCSI_ID_NAA && wwn != NULL) { + strncpy(wwn, serial + s, 16); + if (wwn_vendor_extension) + strncpy(wwn_vendor_extension, serial + s + 16, 16); + } + + return 0; +} + +/* Extract the raw binary from VPD 0x83 pre-SPC devices */ +static int check_fill_0x83_prespc3(struct scsi_id_device *dev_scsi, + unsigned char *page_83, + const struct scsi_id_search_values + *id_search, char *serial, char *serial_short, int max_len) { + int i, j; + + serial[0] = hex_str[SCSI_ID_NAA]; + /* serial has been memset to zero before */ + j = strlen(serial); /* j = 1; */ + + for (i = 0; (i < page_83[3]) && (j < max_len-3); ++i) { + serial[j++] = hex_str[(page_83[4+i] & 0xf0) >> 4]; + serial[j++] = hex_str[ page_83[4+i] & 0x0f]; + } + serial[max_len-1] = 0; + strncpy(serial_short, serial, max_len-1); + return 0; +} + +/* Get device identification VPD page */ +static int do_scsi_page83_inquiry(struct scsi_id_device *dev_scsi, int fd, + char *serial, char *serial_short, int len, + char *unit_serial_number, char *wwn, + char *wwn_vendor_extension, char *tgpt_group) { + int retval; + unsigned id_ind, j; + unsigned char page_83[SCSI_INQ_BUFF_LEN]; + + /* also pick up the page 80 serial number */ + do_scsi_page80_inquiry(dev_scsi, fd, NULL, unit_serial_number, MAX_SERIAL_LEN); + + memzero(page_83, SCSI_INQ_BUFF_LEN); + retval = scsi_inquiry(dev_scsi, fd, 1, PAGE_83, page_83, + SCSI_INQ_BUFF_LEN); + if (retval < 0) + return 1; + + if (page_83[1] != PAGE_83) { + log_debug("%s: Invalid page 0x83", dev_scsi->kernel); + return 1; + } + + /* + * XXX Some devices (IBM 3542) return all spaces for an identifier if + * the LUN is not actually configured. This leads to identifiers of + * the form: "1 ". + */ + + /* + * Model 4, 5, and (some) model 6 EMC Symmetrix devices return + * a page 83 reply according to SCSI-2 format instead of SPC-2/3. + * + * The SCSI-2 page 83 format returns an IEEE WWN in binary + * encoded hexi-decimal in the 16 bytes following the initial + * 4-byte page 83 reply header. + * + * Both the SPC-2 and SPC-3 formats return an IEEE WWN as part + * of an Identification descriptor. The 3rd byte of the first + * Identification descriptor is a reserved (BSZ) byte field. + * + * Reference the 7th byte of the page 83 reply to determine + * whether the reply is compliant with SCSI-2 or SPC-2/3 + * specifications. A zero value in the 7th byte indicates + * an SPC-2/3 conformant reply, (i.e., the reserved field of the + * first Identification descriptor). This byte will be non-zero + * for a SCSI-2 conformant page 83 reply from these EMC + * Symmetrix models since the 7th byte of the reply corresponds + * to the 4th and 5th nibbles of the 6-byte OUI for EMC, that is, + * 0x006048. + */ + + if (page_83[6] != 0) + return check_fill_0x83_prespc3(dev_scsi, page_83, id_search_list, + serial, serial_short, len); + + /* + * Search for a match in the prioritized id_search_list - since WWN ids + * come first we can pick up the WWN in check_fill_0x83_id(). + */ + for (id_ind = 0; + id_ind < sizeof(id_search_list)/sizeof(id_search_list[0]); + id_ind++) { + /* + * Examine each descriptor returned. There is normally only + * one or a small number of descriptors. + */ + for (j = 4; j <= ((unsigned)page_83[2] << 8) + (unsigned)page_83[3] + 3; j += page_83[j + 3] + 4) { + retval = check_fill_0x83_id(dev_scsi, page_83 + j, + id_search_list + id_ind, + serial, serial_short, len, + wwn, wwn_vendor_extension, + tgpt_group); + if (!retval) + return retval; + else if (retval < 0) + return retval; + } + } + return 1; +} + +/* + * Get device identification VPD page for older SCSI-2 device which is not + * compliant with either SPC-2 or SPC-3 format. + * + * Return the hard coded error code value 2 if the page 83 reply is not + * conformant to the SCSI-2 format. + */ +static int do_scsi_page83_prespc3_inquiry(struct scsi_id_device *dev_scsi, int fd, + char *serial, char *serial_short, int len) { + int retval; + int i, j; + unsigned char page_83[SCSI_INQ_BUFF_LEN]; + + memzero(page_83, SCSI_INQ_BUFF_LEN); + retval = scsi_inquiry(dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN); + if (retval < 0) + return 1; + + if (page_83[1] != PAGE_83) { + log_debug("%s: Invalid page 0x83", dev_scsi->kernel); + return 1; + } + /* + * Model 4, 5, and (some) model 6 EMC Symmetrix devices return + * a page 83 reply according to SCSI-2 format instead of SPC-2/3. + * + * The SCSI-2 page 83 format returns an IEEE WWN in binary + * encoded hexi-decimal in the 16 bytes following the initial + * 4-byte page 83 reply header. + * + * Both the SPC-2 and SPC-3 formats return an IEEE WWN as part + * of an Identification descriptor. The 3rd byte of the first + * Identification descriptor is a reserved (BSZ) byte field. + * + * Reference the 7th byte of the page 83 reply to determine + * whether the reply is compliant with SCSI-2 or SPC-2/3 + * specifications. A zero value in the 7th byte indicates + * an SPC-2/3 conformant reply, (i.e., the reserved field of the + * first Identification descriptor). This byte will be non-zero + * for a SCSI-2 conformant page 83 reply from these EMC + * Symmetrix models since the 7th byte of the reply corresponds + * to the 4th and 5th nibbles of the 6-byte OUI for EMC, that is, + * 0x006048. + */ + if (page_83[6] == 0) + return 2; + + serial[0] = hex_str[SCSI_ID_NAA]; + /* + * The first four bytes contain data, not a descriptor. + */ + i = 4; + j = strlen(serial); + /* + * Binary descriptor, convert to ASCII, + * using two bytes of ASCII for each byte + * in the page_83. + */ + while (i < (page_83[3]+4)) { + serial[j++] = hex_str[(page_83[i] & 0xf0) >> 4]; + serial[j++] = hex_str[page_83[i] & 0x0f]; + i++; + } + return 0; +} + +/* Get unit serial number VPD page */ +static int do_scsi_page80_inquiry(struct scsi_id_device *dev_scsi, int fd, + char *serial, char *serial_short, int max_len) { + int retval; + int ser_ind; + int i; + int len; + unsigned char buf[SCSI_INQ_BUFF_LEN]; + + memzero(buf, SCSI_INQ_BUFF_LEN); + retval = scsi_inquiry(dev_scsi, fd, 1, PAGE_80, buf, SCSI_INQ_BUFF_LEN); + if (retval < 0) + return retval; + + if (buf[1] != PAGE_80) { + log_debug("%s: Invalid page 0x80", dev_scsi->kernel); + return 1; + } + + len = 1 + VENDOR_LENGTH + MODEL_LENGTH + buf[3]; + if (max_len < len) { + log_debug("%s: length %d too short - need %d", + dev_scsi->kernel, max_len, len); + return 1; + } + /* + * Prepend 'S' to avoid unlikely collision with page 0x83 vendor + * specific type where we prepend '0' + vendor + model. + */ + len = buf[3]; + if (serial) { + serial[0] = 'S'; + ser_ind = append_vendor_model(dev_scsi, serial + 1); + if (ser_ind < 0) + return 1; + ser_ind++; /* for the leading 'S' */ + for (i = 4; i < len + 4; i++, ser_ind++) + serial[ser_ind] = buf[i]; + } + if (serial_short) { + memcpy(serial_short, buf + 4, len); + serial_short[len] = '\0'; + } + return 0; +} + +int scsi_std_inquiry(struct scsi_id_device *dev_scsi, const char *devname) { + int fd; + unsigned char buf[SCSI_INQ_BUFF_LEN]; + struct stat statbuf; + int err = 0; + + fd = open(devname, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (fd < 0) { + log_debug_errno(errno, "scsi_id: cannot open %s: %m", devname); + return 1; + } + + if (fstat(fd, &statbuf) < 0) { + log_debug_errno(errno, "scsi_id: cannot stat %s: %m", devname); + err = 2; + goto out; + } + sprintf(dev_scsi->kernel,"%d:%d", major(statbuf.st_rdev), + minor(statbuf.st_rdev)); + + memzero(buf, SCSI_INQ_BUFF_LEN); + err = scsi_inquiry(dev_scsi, fd, 0, 0, buf, SCSI_INQ_BUFF_LEN); + if (err < 0) + goto out; + + err = 0; + memcpy(dev_scsi->vendor, buf + 8, 8); + dev_scsi->vendor[8] = '\0'; + memcpy(dev_scsi->model, buf + 16, 16); + dev_scsi->model[16] = '\0'; + memcpy(dev_scsi->revision, buf + 32, 4); + dev_scsi->revision[4] = '\0'; + sprintf(dev_scsi->type,"%x", buf[0] & 0x1f); + +out: + close(fd); + return err; +} + +int scsi_get_serial(struct scsi_id_device *dev_scsi, const char *devname, + int page_code, int len) { + unsigned char page0[SCSI_INQ_BUFF_LEN]; + int fd = -1; + int cnt; + int ind; + int retval; + + memzero(dev_scsi->serial, len); + initialize_srand(); + for (cnt = 20; cnt > 0; cnt--) { + struct timespec duration; + + fd = open(devname, O_RDONLY | O_NONBLOCK | O_CLOEXEC); + if (fd >= 0 || errno != EBUSY) + break; + duration.tv_sec = 0; + duration.tv_nsec = (200 * 1000 * 1000) + (rand() % 100 * 1000 * 1000); + nanosleep(&duration, NULL); + } + if (fd < 0) + return 1; + + if (page_code == PAGE_80) { + if (do_scsi_page80_inquiry(dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) { + retval = 1; + goto completed; + } else { + retval = 0; + goto completed; + } + } else if (page_code == PAGE_83) { + if (do_scsi_page83_inquiry(dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { + retval = 1; + goto completed; + } else { + retval = 0; + goto completed; + } + } else if (page_code == PAGE_83_PRE_SPC3) { + retval = do_scsi_page83_prespc3_inquiry(dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len); + if (retval) { + /* + * Fallback to servicing a SPC-2/3 compliant page 83 + * inquiry if the page 83 reply format does not + * conform to pre-SPC3 expectations. + */ + if (retval == 2) { + if (do_scsi_page83_inquiry(dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { + retval = 1; + goto completed; + } else { + retval = 0; + goto completed; + } + } + else { + retval = 1; + goto completed; + } + } else { + retval = 0; + goto completed; + } + } else if (page_code != 0x00) { + log_debug("%s: unsupported page code 0x%d", dev_scsi->kernel, page_code); + retval = 1; + goto completed; + } + + /* + * Get page 0, the page of the pages. By default, try from best to + * worst of supported pages: 0x83 then 0x80. + */ + if (do_scsi_page0_inquiry(dev_scsi, fd, page0, SCSI_INQ_BUFF_LEN)) { + /* + * Don't try anything else. Black list if a specific page + * should be used for this vendor+model, or maybe have an + * optional fall-back to page 0x80 or page 0x83. + */ + retval = 1; + goto completed; + } + + for (ind = 4; ind <= page0[3] + 3; ind++) + if (page0[ind] == PAGE_83) + if (!do_scsi_page83_inquiry(dev_scsi, fd, + dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { + /* + * Success + */ + retval = 0; + goto completed; + } + + for (ind = 4; ind <= page0[3] + 3; ind++) + if (page0[ind] == PAGE_80) + if (!do_scsi_page80_inquiry(dev_scsi, fd, + dev_scsi->serial, dev_scsi->serial_short, len)) { + /* + * Success + */ + retval = 0; + goto completed; + } + retval = 1; + +completed: + close(fd); + return retval; +} diff --git a/src/udev/udev-builtin-blkid.c b/src/udev/udev-builtin-blkid.c new file mode 100644 index 00000000..1df41dab --- /dev/null +++ b/src/udev/udev-builtin-blkid.c @@ -0,0 +1,317 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * probe disks for filesystems and partitions + * + * Copyright © 2011 Karel Zak + */ + +#include +#include +#include +#include +#include +#include + +#include "sd-id128.h" + +#include "alloc-util.h" +#include "blkid-util.h" +#include "device-util.h" +#include "efi-loader.h" +#include "errno-util.h" +#include "fd-util.h" +#include "gpt.h" +#include "parse-util.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "udev-builtin.h" + +static void print_property(sd_device *dev, bool test, const char *name, const char *value) { + char s[256]; + + s[0] = '\0'; + + if (streq(name, "TYPE")) { + udev_builtin_add_property(dev, test, "ID_FS_TYPE", value); + + } else if (streq(name, "USAGE")) { + udev_builtin_add_property(dev, test, "ID_FS_USAGE", value); + + } else if (streq(name, "VERSION")) { + udev_builtin_add_property(dev, test, "ID_FS_VERSION", value); + + } else if (streq(name, "UUID")) { + blkid_safe_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_UUID", s); + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s); + + } else if (streq(name, "UUID_SUB")) { + blkid_safe_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s); + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s); + + } else if (streq(name, "LABEL")) { + blkid_safe_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_LABEL", s); + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s); + + } else if (streq(name, "PTTYPE")) { + udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value); + + } else if (streq(name, "PTUUID")) { + udev_builtin_add_property(dev, test, "ID_PART_TABLE_UUID", value); + + } else if (streq(name, "PART_ENTRY_NAME")) { + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s); + + } else if (streq(name, "PART_ENTRY_TYPE")) { + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_PART_ENTRY_TYPE", s); + + } else if (startswith(name, "PART_ENTRY_")) { + strscpyl(s, sizeof(s), "ID_", name, NULL); + udev_builtin_add_property(dev, test, s, value); + + } else if (streq(name, "SYSTEM_ID")) { + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_SYSTEM_ID", s); + + } else if (streq(name, "PUBLISHER_ID")) { + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_PUBLISHER_ID", s); + + } else if (streq(name, "APPLICATION_ID")) { + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_APPLICATION_ID", s); + + } else if (streq(name, "BOOT_SYSTEM_ID")) { + blkid_encode_string(value, s, sizeof(s)); + udev_builtin_add_property(dev, test, "ID_FS_BOOT_SYSTEM_ID", s); + } +} + +static int find_gpt_root(sd_device *dev, blkid_probe pr, bool test) { + +#if defined(GPT_ROOT_NATIVE) && ENABLE_EFI + + _cleanup_free_ char *root_id = NULL; + bool found_esp = false; + blkid_partlist pl; + int i, nvals, r; + + assert(pr); + + /* Iterate through the partitions on this disk, and see if the + * EFI ESP we booted from is on it. If so, find the first root + * disk, and add a property indicating its partition UUID. */ + + errno = 0; + pl = blkid_probe_get_partitions(pr); + if (!pl) + return errno_or_else(ENOMEM); + + nvals = blkid_partlist_numof_partitions(pl); + for (i = 0; i < nvals; i++) { + blkid_partition pp; + const char *stype, *sid; + sd_id128_t type; + + pp = blkid_partlist_get_partition(pl, i); + if (!pp) + continue; + + sid = blkid_partition_get_uuid(pp); + if (!sid) + continue; + + stype = blkid_partition_get_type_string(pp); + if (!stype) + continue; + + if (sd_id128_from_string(stype, &type) < 0) + continue; + + if (sd_id128_equal(type, GPT_ESP)) { + sd_id128_t id, esp; + + /* We found an ESP, let's see if it matches + * the ESP we booted from. */ + + if (sd_id128_from_string(sid, &id) < 0) + continue; + + r = efi_loader_get_device_part_uuid(&esp); + if (r < 0) + return r; + + if (sd_id128_equal(id, esp)) + found_esp = true; + + } else if (sd_id128_equal(type, GPT_ROOT_NATIVE)) { + unsigned long long flags; + + flags = blkid_partition_get_flags(pp); + if (flags & GPT_FLAG_NO_AUTO) + continue; + + /* We found a suitable root partition, let's + * remember the first one. */ + + if (!root_id) { + root_id = strdup(sid); + if (!root_id) + return -ENOMEM; + } + } + } + + /* We found the ESP on this disk, and also found a root + * partition, nice! Let's export its UUID */ + if (found_esp && root_id) + udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT_UUID", root_id); +#endif + + return 0; +} + +static int probe_superblocks(blkid_probe pr) { + struct stat st; + int rc; + + /* TODO: Return negative errno. */ + + if (fstat(blkid_probe_get_fd(pr), &st)) + return -errno; + + blkid_probe_enable_partitions(pr, 1); + + if (!S_ISCHR(st.st_mode) && + blkid_probe_get_size(pr) <= 1024 * 1440 && + blkid_probe_is_wholedisk(pr)) { + /* + * check if the small disk is partitioned, if yes then + * don't probe for filesystems. + */ + blkid_probe_enable_superblocks(pr, 0); + + rc = blkid_do_fullprobe(pr); + if (rc < 0) + return rc; /* -1 = error, 1 = nothing, 0 = success */ + + if (blkid_probe_lookup_value(pr, "PTTYPE", NULL, NULL) == 0) + return 0; /* partition table detected */ + } + + blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS); + blkid_probe_enable_superblocks(pr, 1); + + return blkid_do_safeprobe(pr); +} + +static int builtin_blkid(sd_device *dev, int argc, char *argv[], bool test) { + const char *devnode, *root_partition = NULL, *data, *name; + _cleanup_(blkid_free_probep) blkid_probe pr = NULL; + bool noraid = false, is_gpt = false; + _cleanup_close_ int fd = -1; + int64_t offset = 0; + int nvals, i, r; + + static const struct option options[] = { + { "offset", required_argument, NULL, 'o' }, + { "noraid", no_argument, NULL, 'R' }, + {} + }; + + for (;;) { + int option; + + option = getopt_long(argc, argv, "o:R", options, NULL); + if (option == -1) + break; + + switch (option) { + case 'o': + r = safe_atoi64(optarg, &offset); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to parse '%s' as an integer: %m", optarg); + if (offset < 0) + return log_device_error_errno(dev, SYNTHETIC_ERRNO(ERANGE), "Invalid offset %"PRIi64": %m", offset); + break; + case 'R': + noraid = true; + break; + } + } + + errno = 0; + pr = blkid_new_probe(); + if (!pr) + return log_device_debug_errno(dev, errno > 0 ? errno : ENOMEM, "Failed to create blkid prober: %m"); + + blkid_probe_set_superblocks_flags(pr, + BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | + BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | + BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); + + if (noraid) + blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); + + r = sd_device_get_devname(dev, &devnode); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get device name: %m"); + + fd = open(devnode, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) + return log_device_debug_errno(dev, errno, "Failed to open block device %s: %m", devnode); + + errno = 0; + r = blkid_probe_set_device(pr, fd, offset, 0); + if (r < 0) + return log_device_debug_errno(dev, errno > 0 ? errno : ENOMEM, "Failed to set device to blkid prober: %m"); + + log_device_debug(dev, "Probe %s with %sraid and offset=%"PRIi64, devnode, noraid ? "no" : "", offset); + + r = probe_superblocks(pr); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to probe superblocks: %m"); + + /* If the device is a partition then its parent passed the root partition UUID to the device */ + (void) sd_device_get_property_value(dev, "ID_PART_GPT_AUTO_ROOT_UUID", &root_partition); + + errno = 0; + nvals = blkid_probe_numof_values(pr); + if (nvals < 0) + return log_device_debug_errno(dev, errno > 0 ? errno : ENOMEM, "Failed to get number of probed values: %m"); + + for (i = 0; i < nvals; i++) { + if (blkid_probe_get_value(pr, i, &name, &data, NULL) < 0) + continue; + + print_property(dev, test, name, data); + + /* Is this a disk with GPT partition table? */ + if (streq(name, "PTTYPE") && streq(data, "gpt")) + is_gpt = true; + + /* Is this a partition that matches the root partition + * property inherited from the parent? */ + if (root_partition && streq(name, "PART_ENTRY_UUID") && streq(data, root_partition)) + udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT", "1"); + } + + if (is_gpt) + find_gpt_root(dev, pr, test); + + return 0; +} + +const UdevBuiltin udev_builtin_blkid = { + .name = "blkid", + .cmd = builtin_blkid, + .help = "Filesystem and partition probing", + .run_once = true, +}; diff --git a/src/udev/udev-builtin-btrfs.c b/src/udev/udev-builtin-btrfs.c new file mode 100644 index 00000000..1f0073e5 --- /dev/null +++ b/src/udev/udev-builtin-btrfs.c @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#include "device-util.h" +#include "fd-util.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "udev-builtin.h" +#include "util.h" + +static int builtin_btrfs(sd_device *dev, int argc, char *argv[], bool test) { + struct btrfs_ioctl_vol_args args = {}; + _cleanup_close_ int fd = -1; + int r; + + if (argc != 3 || !streq(argv[1], "ready")) + return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Invalid arguments"); + + fd = open("/dev/btrfs-control", O_RDWR|O_CLOEXEC); + if (fd < 0) + return log_device_debug_errno(dev, errno, "Failed to open /dev/btrfs-control: %m"); + + strscpy(args.name, sizeof(args.name), argv[2]); + r = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args); + if (r < 0) + return log_device_debug_errno(dev, errno, "Failed to call BTRFS_IOC_DEVICES_READY: %m"); + + udev_builtin_add_property(dev, test, "ID_BTRFS_READY", one_zero(r == 0)); + return 0; +} + +const UdevBuiltin udev_builtin_btrfs = { + .name = "btrfs", + .cmd = builtin_btrfs, + .help = "btrfs volume management", +}; diff --git a/src/udev/udev-builtin-hwdb.c b/src/udev/udev-builtin-hwdb.c new file mode 100644 index 00000000..36cda504 --- /dev/null +++ b/src/udev/udev-builtin-hwdb.c @@ -0,0 +1,218 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "sd-hwdb.h" + +#include "alloc-util.h" +#include "device-util.h" +#include "hwdb-util.h" +#include "parse-util.h" +#include "string-util.h" +#include "udev-builtin.h" + +static sd_hwdb *hwdb; + +int udev_builtin_hwdb_lookup(sd_device *dev, + const char *prefix, const char *modalias, + const char *filter, bool test) { + _cleanup_free_ char *lookup = NULL; + const char *key, *value; + int n = 0, r; + + if (!hwdb) + return -ENOENT; + + if (prefix) { + lookup = strjoin(prefix, modalias); + if (!lookup) + return -ENOMEM; + modalias = lookup; + } + + SD_HWDB_FOREACH_PROPERTY(hwdb, modalias, key, value) { + if (filter && fnmatch(filter, key, FNM_NOESCAPE) != 0) + continue; + + r = udev_builtin_add_property(dev, test, key, value); + if (r < 0) + return r; + n++; + } + return n; +} + +static const char *modalias_usb(sd_device *dev, char *s, size_t size) { + const char *v, *p; + uint16_t vn, pn; + + if (sd_device_get_sysattr_value(dev, "idVendor", &v) < 0) + return NULL; + if (sd_device_get_sysattr_value(dev, "idProduct", &p) < 0) + return NULL; + if (safe_atoux16(v, &vn) < 0) + return NULL; + if (safe_atoux16(p, &pn) < 0) + return NULL; + snprintf(s, size, "usb:v%04Xp%04X*", vn, pn); + return s; +} + +static int udev_builtin_hwdb_search(sd_device *dev, sd_device *srcdev, + const char *subsystem, const char *prefix, + const char *filter, bool test) { + sd_device *d; + char s[16]; + bool last = false; + int r = 0; + + assert(dev); + + if (!srcdev) + srcdev = dev; + + for (d = srcdev; d; ) { + const char *dsubsys, *devtype, *modalias = NULL; + + if (sd_device_get_subsystem(d, &dsubsys) < 0) + goto next; + + /* look only at devices of a specific subsystem */ + if (subsystem && !streq(dsubsys, subsystem)) + goto next; + + (void) sd_device_get_property_value(d, "MODALIAS", &modalias); + + if (streq(dsubsys, "usb") && + sd_device_get_devtype(d, &devtype) >= 0 && + streq(devtype, "usb_device")) { + /* if the usb_device does not have a modalias, compose one */ + if (!modalias) + modalias = modalias_usb(d, s, sizeof(s)); + + /* avoid looking at any parent device, they are usually just a USB hub */ + last = true; + } + + if (!modalias) + goto next; + + r = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, test); + if (r > 0) + break; + + if (last) + break; +next: + if (sd_device_get_parent(d, &d) < 0) + break; + } + + return r; +} + +static int builtin_hwdb(sd_device *dev, int argc, char *argv[], bool test) { + static const struct option options[] = { + { "filter", required_argument, NULL, 'f' }, + { "device", required_argument, NULL, 'd' }, + { "subsystem", required_argument, NULL, 's' }, + { "lookup-prefix", required_argument, NULL, 'p' }, + {} + }; + const char *filter = NULL; + const char *device = NULL; + const char *subsystem = NULL; + const char *prefix = NULL; + _cleanup_(sd_device_unrefp) sd_device *srcdev = NULL; + int r; + + if (!hwdb) + return -EINVAL; + + for (;;) { + int option; + + option = getopt_long(argc, argv, "f:d:s:p:", options, NULL); + if (option == -1) + break; + + switch (option) { + case 'f': + filter = optarg; + break; + + case 'd': + device = optarg; + break; + + case 's': + subsystem = optarg; + break; + + case 'p': + prefix = optarg; + break; + } + } + + /* query a specific key given as argument */ + if (argv[optind]) { + r = udev_builtin_hwdb_lookup(dev, prefix, argv[optind], filter, test); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to lookup hwdb: %m"); + if (r == 0) + return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENODATA), "No entry found from hwdb."); + return r; + } + + /* read data from another device than the device we will store the data */ + if (device) { + r = sd_device_new_from_device_id(&srcdev, device); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to create sd_device object '%s': %m", device); + } + + r = udev_builtin_hwdb_search(dev, srcdev, subsystem, prefix, filter, test); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to lookup hwdb: %m"); + if (r == 0) + return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENODATA), "No entry found from hwdb."); + return r; +} + +/* called at udev startup and reload */ +static int builtin_hwdb_init(void) { + int r; + + if (hwdb) + return 0; + + r = sd_hwdb_new(&hwdb); + if (r < 0) + return r; + + return 0; +} + +/* called on udev shutdown and reload request */ +static void builtin_hwdb_exit(void) { + hwdb = sd_hwdb_unref(hwdb); +} + +/* called every couple of seconds during event activity; 'true' if config has changed */ +static bool builtin_hwdb_validate(void) { + return hwdb_validate(hwdb); +} + +const UdevBuiltin udev_builtin_hwdb = { + .name = "hwdb", + .cmd = builtin_hwdb, + .init = builtin_hwdb_init, + .exit = builtin_hwdb_exit, + .validate = builtin_hwdb_validate, + .help = "Hardware database", +}; diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c new file mode 100644 index 00000000..840bd01e --- /dev/null +++ b/src/udev/udev-builtin-input_id.c @@ -0,0 +1,362 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * expose input properties via udev + * + * Portions Copyright © 2004 David Zeuthen, + * Copyright © 2014 Carlos Garnacho + */ + +#include +#include +#include +#include +#include +#include + +#include "device-util.h" +#include "fd-util.h" +#include "missing_input.h" +#include "stdio-util.h" +#include "string-util.h" +#include "udev-builtin.h" +#include "util.h" + +/* we must use this kernel-compatible implementation */ +#define BITS_PER_LONG (sizeof(unsigned long) * 8) +#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) +#define OFF(x) ((x)%BITS_PER_LONG) +#define BIT(x) (1UL<> OFF(bit)) & 1) + +struct range { + unsigned start; + unsigned end; +}; + +/* key code ranges above BTN_MISC (start is inclusive, stop is exclusive)*/ +static const struct range high_key_blocks[] = { + { KEY_OK, BTN_DPAD_UP }, + { KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY } +}; + +static int abs_size_mm(const struct input_absinfo *absinfo) { + /* Resolution is defined to be in units/mm for ABS_X/Y */ + return (absinfo->maximum - absinfo->minimum) / absinfo->resolution; +} + +static void extract_info(sd_device *dev, const char *devpath, bool test) { + char width[DECIMAL_STR_MAX(int)], height[DECIMAL_STR_MAX(int)]; + struct input_absinfo xabsinfo = {}, yabsinfo = {}; + _cleanup_close_ int fd = -1; + + fd = open(devpath, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return; + + if (ioctl(fd, EVIOCGABS(ABS_X), &xabsinfo) < 0 || + ioctl(fd, EVIOCGABS(ABS_Y), &yabsinfo) < 0) + return; + + if (xabsinfo.resolution <= 0 || yabsinfo.resolution <= 0) + return; + + xsprintf(width, "%d", abs_size_mm(&xabsinfo)); + xsprintf(height, "%d", abs_size_mm(&yabsinfo)); + + udev_builtin_add_property(dev, test, "ID_INPUT_WIDTH_MM", width); + udev_builtin_add_property(dev, test, "ID_INPUT_HEIGHT_MM", height); +} + +/* + * Read a capability attribute and return bitmask. + * @param dev sd_device + * @param attr sysfs attribute name (e. g. "capabilities/key") + * @param bitmask: Output array which has a sizeof of bitmask_size + */ +static void get_cap_mask(sd_device *pdev, const char* attr, + unsigned long *bitmask, size_t bitmask_size, + bool test) { + const char *v; + char text[4096]; + unsigned i; + char* word; + unsigned long val; + + if (sd_device_get_sysattr_value(pdev, attr, &v) < 0) + v = ""; + + xsprintf(text, "%s", v); + log_device_debug(pdev, "%s raw kernel attribute: %s", attr, text); + + memzero(bitmask, bitmask_size); + i = 0; + while ((word = strrchr(text, ' ')) != NULL) { + val = strtoul(word+1, NULL, 16); + if (i < bitmask_size / sizeof(unsigned long)) + bitmask[i] = val; + else + log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val); + *word = '\0'; + ++i; + } + val = strtoul (text, NULL, 16); + if (i < bitmask_size / sizeof(unsigned long)) + bitmask[i] = val; + else + log_device_debug(pdev, "Ignoring %s block %lX which is larger than maximum size", attr, val); + + if (test) { + /* printf pattern with the right unsigned long number of hex chars */ + xsprintf(text, " bit %%4u: %%0%zulX\n", + 2 * sizeof(unsigned long)); + log_device_debug(pdev, "%s decoded bit map:", attr); + val = bitmask_size / sizeof (unsigned long); + /* skip over leading zeros */ + while (bitmask[val-1] == 0 && val > 0) + --val; + for (i = 0; i < val; ++i) { + DISABLE_WARNING_FORMAT_NONLITERAL; + log_device_debug(pdev, text, i * BITS_PER_LONG, bitmask[i]); + REENABLE_WARNING; + } + } +} + +/* pointer devices */ +static bool test_pointers(sd_device *dev, + const unsigned long* bitmask_ev, + const unsigned long* bitmask_abs, + const unsigned long* bitmask_key, + const unsigned long* bitmask_rel, + const unsigned long* bitmask_props, + bool test) { + int button, axis; + bool has_abs_coordinates = false; + bool has_rel_coordinates = false; + bool has_mt_coordinates = false; + bool has_joystick_axes_or_buttons = false; + bool is_direct = false; + bool has_touch = false; + bool has_3d_coordinates = false; + bool has_keys = false; + bool stylus_or_pen = false; + bool finger_but_no_pen = false; + bool has_mouse_button = false; + bool is_mouse = false; + bool is_touchpad = false; + bool is_touchscreen = false; + bool is_tablet = false; + bool is_joystick = false; + bool is_accelerometer = false; + bool is_pointing_stick= false; + + has_keys = test_bit(EV_KEY, bitmask_ev); + has_abs_coordinates = test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs); + has_3d_coordinates = has_abs_coordinates && test_bit(ABS_Z, bitmask_abs); + is_accelerometer = test_bit(INPUT_PROP_ACCELEROMETER, bitmask_props); + + if (!has_keys && has_3d_coordinates) + is_accelerometer = true; + + if (is_accelerometer) { + udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1"); + return true; + } + + is_pointing_stick = test_bit(INPUT_PROP_POINTING_STICK, bitmask_props); + stylus_or_pen = test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key); + finger_but_no_pen = test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key); + for (button = BTN_MOUSE; button < BTN_JOYSTICK && !has_mouse_button; button++) + has_mouse_button = test_bit(button, bitmask_key); + has_rel_coordinates = test_bit(EV_REL, bitmask_ev) && test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel); + has_mt_coordinates = test_bit(ABS_MT_POSITION_X, bitmask_abs) && test_bit(ABS_MT_POSITION_Y, bitmask_abs); + + /* unset has_mt_coordinates if devices claims to have all abs axis */ + if (has_mt_coordinates && test_bit(ABS_MT_SLOT, bitmask_abs) && test_bit(ABS_MT_SLOT - 1, bitmask_abs)) + has_mt_coordinates = false; + is_direct = test_bit(INPUT_PROP_DIRECT, bitmask_props); + has_touch = test_bit(BTN_TOUCH, bitmask_key); + + /* joysticks don't necessarily have buttons; e. g. + * rudders/pedals are joystick-like, but buttonless; they have + * other fancy axes. Others have buttons only but no axes. + * + * The BTN_JOYSTICK range starts after the mouse range, so a mouse + * with more than 16 buttons runs into the joystick range (e.g. Mad + * Catz Mad Catz M.M.O.TE). Skip those. + */ + if (!test_bit(BTN_JOYSTICK - 1, bitmask_key)) { + for (button = BTN_JOYSTICK; button < BTN_DIGI && !has_joystick_axes_or_buttons; button++) + has_joystick_axes_or_buttons = test_bit(button, bitmask_key); + for (button = BTN_TRIGGER_HAPPY1; button <= BTN_TRIGGER_HAPPY40 && !has_joystick_axes_or_buttons; button++) + has_joystick_axes_or_buttons = test_bit(button, bitmask_key); + for (button = BTN_DPAD_UP; button <= BTN_DPAD_RIGHT && !has_joystick_axes_or_buttons; button++) + has_joystick_axes_or_buttons = test_bit(button, bitmask_key); + } + for (axis = ABS_RX; axis < ABS_PRESSURE && !has_joystick_axes_or_buttons; axis++) + has_joystick_axes_or_buttons = test_bit(axis, bitmask_abs); + + if (has_abs_coordinates) { + if (stylus_or_pen) + is_tablet = true; + else if (finger_but_no_pen && !is_direct) + is_touchpad = true; + else if (has_mouse_button) + /* This path is taken by VMware's USB mouse, which has + * absolute axes, but no touch/pressure button. */ + is_mouse = true; + else if (has_touch || is_direct) + is_touchscreen = true; + else if (has_joystick_axes_or_buttons) + is_joystick = true; + } else if (has_joystick_axes_or_buttons) { + is_joystick = true; + } + + if (has_mt_coordinates) { + if (stylus_or_pen) + is_tablet = true; + else if (finger_but_no_pen && !is_direct) + is_touchpad = true; + else if (has_touch || is_direct) + is_touchscreen = true; + } + + if (!is_tablet && !is_touchpad && !is_joystick && + has_mouse_button && + (has_rel_coordinates || + !has_abs_coordinates)) /* mouse buttons and no axis */ + is_mouse = true; + + if (is_pointing_stick) + udev_builtin_add_property(dev, test, "ID_INPUT_POINTINGSTICK", "1"); + if (is_mouse) + udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1"); + if (is_touchpad) + udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHPAD", "1"); + if (is_touchscreen) + udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1"); + if (is_joystick) + udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1"); + if (is_tablet) + udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1"); + + return is_tablet || is_mouse || is_touchpad || is_touchscreen || is_joystick || is_pointing_stick; +} + +/* key like devices */ +static bool test_key(sd_device *dev, + const unsigned long* bitmask_ev, + const unsigned long* bitmask_key, + bool test) { + unsigned i; + unsigned long found; + unsigned long mask; + bool ret = false; + + /* do we have any KEY_* capability? */ + if (!test_bit(EV_KEY, bitmask_ev)) { + log_device_debug(dev, "test_key: no EV_KEY capability"); + return false; + } + + /* only consider KEY_* here, not BTN_* */ + found = 0; + for (i = 0; i < BTN_MISC/BITS_PER_LONG; ++i) { + found |= bitmask_key[i]; + log_device_debug(dev, "test_key: checking bit block %lu for any keys; found=%i", (unsigned long)i*BITS_PER_LONG, found > 0); + } + /* If there are no keys in the lower block, check the higher blocks */ + if (!found) { + unsigned block; + for (block = 0; block < (sizeof(high_key_blocks) / sizeof(struct range)); ++block) { + for (i = high_key_blocks[block].start; i < high_key_blocks[block].end; ++i) { + if (test_bit(i, bitmask_key)) { + log_device_debug(dev, "test_key: Found key %x in high block", i); + found = 1; + break; + } + } + } + } + + if (found > 0) { + udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1"); + ret = true; + } + + /* the first 32 bits are ESC, numbers, and Q to D; if we have all of + * those, consider it a full keyboard; do not test KEY_RESERVED, though */ + mask = 0xFFFFFFFE; + if (FLAGS_SET(bitmask_key[0], mask)) { + udev_builtin_add_property(dev, test, "ID_INPUT_KEYBOARD", "1"); + ret = true; + } + + return ret; +} + +static int builtin_input_id(sd_device *dev, int argc, char *argv[], bool test) { + sd_device *pdev; + unsigned long bitmask_ev[NBITS(EV_MAX)]; + unsigned long bitmask_abs[NBITS(ABS_MAX)]; + unsigned long bitmask_key[NBITS(KEY_MAX)]; + unsigned long bitmask_rel[NBITS(REL_MAX)]; + unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)]; + const char *sysname, *devnode; + bool is_pointer; + bool is_key; + + assert(dev); + + /* walk up the parental chain until we find the real input device; the + * argument is very likely a subdevice of this, like eventN */ + for (pdev = dev; pdev; ) { + const char *s; + + if (sd_device_get_sysattr_value(pdev, "capabilities/ev", &s) >= 0) + break; + + if (sd_device_get_parent_with_subsystem_devtype(pdev, "input", NULL, &pdev) >= 0) + continue; + + pdev = NULL; + break; + } + + if (pdev) { + /* Use this as a flag that input devices were detected, so that this + * program doesn't need to be called more than once per device */ + udev_builtin_add_property(dev, test, "ID_INPUT", "1"); + get_cap_mask(pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), test); + get_cap_mask(pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), test); + get_cap_mask(pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), test); + get_cap_mask(pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), test); + get_cap_mask(pdev, "properties", bitmask_props, sizeof(bitmask_props), test); + is_pointer = test_pointers(dev, bitmask_ev, bitmask_abs, + bitmask_key, bitmask_rel, + bitmask_props, test); + is_key = test_key(dev, bitmask_ev, bitmask_key, test); + /* Some evdev nodes have only a scrollwheel */ + if (!is_pointer && !is_key && test_bit(EV_REL, bitmask_ev) && + (test_bit(REL_WHEEL, bitmask_rel) || test_bit(REL_HWHEEL, bitmask_rel))) + udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1"); + if (test_bit(EV_SW, bitmask_ev)) + udev_builtin_add_property(dev, test, "ID_INPUT_SWITCH", "1"); + + } + + if (sd_device_get_devname(dev, &devnode) >= 0 && + sd_device_get_sysname(dev, &sysname) >= 0 && + startswith(sysname, "event")) + extract_info(dev, devnode, test); + + return 0; +} + +const UdevBuiltin udev_builtin_input_id = { + .name = "input_id", + .cmd = builtin_input_id, + .help = "Input device properties", +}; diff --git a/src/udev/udev-builtin-keyboard.c b/src/udev/udev-builtin-keyboard.c new file mode 100644 index 00000000..bb82e8ae --- /dev/null +++ b/src/udev/udev-builtin-keyboard.c @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "device-util.h" +#include "fd-util.h" +#include "parse-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "udev-builtin.h" + +static const struct key_name *keyboard_lookup_key(const char *str, GPERF_LEN_TYPE len); +#include "keyboard-keys-from-name.h" + +static int install_force_release(sd_device *dev, const unsigned *release, unsigned release_count) { + sd_device *atkbd; + const char *cur; + char codes[4096]; + char *s; + size_t l; + unsigned i; + int r; + + assert(dev); + assert(release); + + r = sd_device_get_parent_with_subsystem_devtype(dev, "serio", NULL, &atkbd); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get serio parent: %m"); + + r = sd_device_get_sysattr_value(atkbd, "force_release", &cur); + if (r < 0) + return log_device_error_errno(atkbd, r, "Failed to get force-release attribute: %m"); + + s = codes; + l = sizeof(codes); + + /* copy current content */ + l = strpcpy(&s, l, cur); + + /* append new codes */ + for (i = 0; i < release_count; i++) + l = strpcpyf(&s, l, ",%u", release[i]); + + log_device_debug(atkbd, "keyboard: updating force-release list with '%s'", codes); + r = sd_device_set_sysattr_value(atkbd, "force_release", codes); + if (r < 0) + return log_device_error_errno(atkbd, r, "Failed to set force-release attribute: %m"); + + return 0; +} + +static int map_keycode(sd_device *dev, int fd, int scancode, const char *keycode) { + struct { + unsigned scan; + unsigned key; + } map; + char *endptr; + const struct key_name *k; + unsigned keycode_num; + + /* translate identifier to key code */ + k = keyboard_lookup_key(keycode, strlen(keycode)); + if (k) { + keycode_num = k->id; + } else { + /* check if it's a numeric code already */ + keycode_num = strtoul(keycode, &endptr, 0); + if (endptr[0] !='\0') + return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "Failed to parse key identifier '%s'", keycode); + } + + map.scan = scancode; + map.key = keycode_num; + + log_device_debug(dev, "keyboard: mapping scan code %d (0x%x) to key code %d (0x%x)", + map.scan, map.scan, map.key, map.key); + + if (ioctl(fd, EVIOCSKEYCODE, &map) < 0) + return log_device_error_errno(dev, errno, "Failed to call EVIOCSKEYCODE with scan code 0x%x, and key code %d: %m", map.scan, map.key); + + return 0; +} + +static char* parse_token(const char *current, int32_t *val_out) { + char *next; + int32_t val; + + if (!current) + return NULL; + + val = strtol(current, &next, 0); + if (*next && *next != ':') + return NULL; + + if (next != current) + *val_out = val; + + if (*next) + next++; + + return next; +} + +static int override_abs(sd_device *dev, int fd, unsigned evcode, const char *value) { + struct input_absinfo absinfo; + char *next; + int r; + + r = ioctl(fd, EVIOCGABS(evcode), &absinfo); + if (r < 0) + return log_device_error_errno(dev, errno, "Failed to call EVIOCGABS"); + + next = parse_token(value, &absinfo.minimum); + next = parse_token(next, &absinfo.maximum); + next = parse_token(next, &absinfo.resolution); + next = parse_token(next, &absinfo.fuzz); + next = parse_token(next, &absinfo.flat); + if (!next) + return log_device_error(dev, "Failed to parse EV_ABS override '%s'", value); + + log_device_debug(dev, "keyboard: %x overridden with %"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32"/%"PRIi32, + evcode, absinfo.minimum, absinfo.maximum, absinfo.resolution, absinfo.fuzz, absinfo.flat); + r = ioctl(fd, EVIOCSABS(evcode), &absinfo); + if (r < 0) + return log_device_error_errno(dev, errno, "Failed to call EVIOCSABS"); + + return 0; +} + +static int set_trackpoint_sensitivity(sd_device *dev, const char *value) { + sd_device *pdev; + char val_s[DECIMAL_STR_MAX(int)]; + int r, val_i; + + assert(dev); + assert(value); + + /* The sensitivity sysfs attr belongs to the serio parent device */ + r = sd_device_get_parent_with_subsystem_devtype(dev, "serio", NULL, &pdev); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get serio parent: %m"); + + r = safe_atoi(value, &val_i); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to parse POINTINGSTICK_SENSITIVITY '%s': %m", value); + else if (val_i < 0 || val_i > 255) + return log_device_error_errno(dev, SYNTHETIC_ERRNO(ERANGE), "POINTINGSTICK_SENSITIVITY %d outside range [0..255]", val_i); + + xsprintf(val_s, "%d", val_i); + + r = sd_device_set_sysattr_value(pdev, "sensitivity", val_s); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to write 'sensitivity' attribute: %m"); + + return 0; +} + +static int builtin_keyboard(sd_device *dev, int argc, char *argv[], bool test) { + unsigned release[1024]; + unsigned release_count = 0; + _cleanup_close_ int fd = -1; + const char *node, *key, *value; + int has_abs = -1, r; + + r = sd_device_get_devname(dev, &node); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get device name: %m"); + + FOREACH_DEVICE_PROPERTY(dev, key, value) { + char *endptr; + + if (startswith(key, "KEYBOARD_KEY_")) { + const char *keycode = value; + unsigned scancode; + + /* KEYBOARD_KEY_= */ + scancode = strtoul(key + 13, &endptr, 16); + if (endptr[0] != '\0') { + log_device_warning(dev, "Failed to parse scan code from \"%s\", ignoring", key); + continue; + } + + /* a leading '!' needs a force-release entry */ + if (keycode[0] == '!') { + keycode++; + + release[release_count] = scancode; + if (release_count < ELEMENTSOF(release)-1) + release_count++; + + if (keycode[0] == '\0') + continue; + } + + if (fd < 0) { + fd = open(node, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (fd < 0) + return log_device_error_errno(dev, errno, "Failed to open device '%s': %m", node); + } + + (void) map_keycode(dev, fd, scancode, keycode); + } else if (startswith(key, "EVDEV_ABS_")) { + unsigned evcode; + + /* EVDEV_ABS_=:::: */ + evcode = strtoul(key + 10, &endptr, 16); + if (endptr[0] != '\0') { + log_device_warning(dev, "Failed to parse EV_ABS code from \"%s\", ignoring", key); + continue; + } + + if (fd < 0) { + fd = open(node, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (fd < 0) + return log_device_error_errno(dev, errno, "Failed to open device '%s': %m", node); + } + + if (has_abs == -1) { + unsigned long bits; + int rc; + + rc = ioctl(fd, EVIOCGBIT(0, sizeof(bits)), &bits); + if (rc < 0) + return log_device_error_errno(dev, errno, "Failed to set EVIOCGBIT"); + + has_abs = !!(bits & (1 << EV_ABS)); + if (!has_abs) + log_device_warning(dev, "EVDEV_ABS override set but no EV_ABS present on device"); + } + + if (!has_abs) + continue; + + (void) override_abs(dev, fd, evcode, value); + } else if (streq(key, "POINTINGSTICK_SENSITIVITY")) + (void) set_trackpoint_sensitivity(dev, value); + } + + /* install list of force-release codes */ + if (release_count > 0) + (void) install_force_release(dev, release, release_count); + + return 0; +} + +const UdevBuiltin udev_builtin_keyboard = { + .name = "keyboard", + .cmd = builtin_keyboard, + .help = "Keyboard scan code to key mapping", +}; diff --git a/src/udev/udev-builtin-kmod.c b/src/udev/udev-builtin-kmod.c new file mode 100644 index 00000000..b3daddcd --- /dev/null +++ b/src/udev/udev-builtin-kmod.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * load kernel modules + * + * Copyright © 2011 ProFUSION embedded systems + */ + +#include +#include +#include +#include + +#include "module-util.h" +#include "string-util.h" +#include "udev-builtin.h" + +static struct kmod_ctx *ctx = NULL; + +_printf_(6,0) static void udev_kmod_log(void *data, int priority, const char *file, int line, const char *fn, const char *format, va_list args) { + log_internalv(priority, 0, file, line, fn, format, args); +} + +static int builtin_kmod(sd_device *dev, int argc, char *argv[], bool test) { + int i; + + if (!ctx) + return 0; + + if (argc < 3 || !streq(argv[1], "load")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "%s: expected: load ", argv[0]); + + for (i = 2; argv[i]; i++) + (void) module_load_and_warn(ctx, argv[i], false); + + return 0; +} + +/* called at udev startup and reload */ +static int builtin_kmod_init(void) { + if (ctx) + return 0; + + ctx = kmod_new(NULL, NULL); + if (!ctx) + return -ENOMEM; + + log_debug("Load module index"); + kmod_set_log_fn(ctx, udev_kmod_log, NULL); + kmod_load_resources(ctx); + return 0; +} + +/* called on udev shutdown and reload request */ +static void builtin_kmod_exit(void) { + log_debug("Unload module index"); + ctx = kmod_unref(ctx); +} + +/* called every couple of seconds during event activity; 'true' if config has changed */ +static bool builtin_kmod_validate(void) { + log_debug("Validate module index"); + if (!ctx) + return false; + return (kmod_validate_resources(ctx) != KMOD_RESOURCES_OK); +} + +const UdevBuiltin udev_builtin_kmod = { + .name = "kmod", + .cmd = builtin_kmod, + .init = builtin_kmod_init, + .exit = builtin_kmod_exit, + .validate = builtin_kmod_validate, + .help = "Kernel module loader", + .run_once = false, +}; diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c new file mode 100644 index 00000000..65f668d2 --- /dev/null +++ b/src/udev/udev-builtin-net_id.c @@ -0,0 +1,932 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +/* + * Predictable network interface device names based on: + * - firmware/bios-provided index numbers for on-board devices + * - firmware-provided pci-express hotplug slot index number + * - physical/geographical location of the hardware + * - the interface's MAC address + * + * http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames + * + * When the code here is changed, man/systemd.net-naming-scheme.xml must be updated too. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "naming-scheme.h" +#include "parse-util.h" +#include "proc-cmdline.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "strxcpyx.h" +#include "udev-builtin.h" + +#define ONBOARD_INDEX_MAX (16*1024-1) + +enum netname_type{ + NET_UNDEF, + NET_PCI, + NET_USB, + NET_BCMA, + NET_VIRTIO, + NET_CCW, + NET_VIO, + NET_PLATFORM, + NET_NETDEVSIM, +}; + +struct netnames { + enum netname_type type; + + uint8_t mac[6]; + bool mac_valid; + + sd_device *pcidev; + char pci_slot[IFNAMSIZ]; + char pci_path[IFNAMSIZ]; + char pci_onboard[IFNAMSIZ]; + const char *pci_onboard_label; + + char usb_ports[IFNAMSIZ]; + char bcma_core[IFNAMSIZ]; + char ccw_busid[IFNAMSIZ]; + char vio_slot[IFNAMSIZ]; + char platform_path[IFNAMSIZ]; + char netdevsim_path[IFNAMSIZ]; +}; + +struct virtfn_info { + sd_device *physfn_pcidev; + char suffix[IFNAMSIZ]; +}; + +/* skip intermediate virtio devices */ +static sd_device *skip_virtio(sd_device *dev) { + sd_device *parent; + + /* there can only ever be one virtio bus per parent device, so we can + * safely ignore any virtio buses. see + * http://lists.linuxfoundation.org/pipermail/virtualization/2015-August/030331.html */ + for (parent = dev; parent; ) { + const char *subsystem; + + if (sd_device_get_subsystem(parent, &subsystem) < 0) + break; + + if (!streq(subsystem, "virtio")) + break; + + if (sd_device_get_parent(parent, &parent) < 0) + return NULL; + } + + return parent; +} + +static int get_virtfn_info(sd_device *dev, struct netnames *names, struct virtfn_info *ret) { + _cleanup_(sd_device_unrefp) sd_device *physfn_pcidev = NULL; + const char *physfn_link_file, *syspath; + _cleanup_free_ char *physfn_pci_syspath = NULL; + _cleanup_free_ char *virtfn_pci_syspath = NULL; + struct dirent *dent; + _cleanup_closedir_ DIR *dir = NULL; + char suffix[IFNAMSIZ]; + int r; + + assert(dev); + assert(names); + assert(ret); + + r = sd_device_get_syspath(names->pcidev, &syspath); + if (r < 0) + return r; + + /* Check if this is a virtual function. */ + physfn_link_file = strjoina(syspath, "/physfn"); + r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath, NULL); + if (r < 0) + return r; + + /* Get physical function's pci device. */ + r = sd_device_new_from_syspath(&physfn_pcidev, physfn_pci_syspath); + if (r < 0) + return r; + + /* Find the virtual function number by finding the right virtfn link. */ + dir = opendir(physfn_pci_syspath); + if (!dir) + return -errno; + + FOREACH_DIRENT_ALL(dent, dir, break) { + _cleanup_free_ char *virtfn_link_file = NULL; + + if (!startswith(dent->d_name, "virtfn")) + continue; + + virtfn_link_file = path_join(physfn_pci_syspath, dent->d_name); + if (!virtfn_link_file) + return -ENOMEM; + + if (chase_symlinks(virtfn_link_file, NULL, 0, &virtfn_pci_syspath, NULL) < 0) + continue; + + if (streq(syspath, virtfn_pci_syspath)) { + if (!snprintf_ok(suffix, sizeof(suffix), "v%s", &dent->d_name[6])) + return -ENOENT; + + break; + } + } + if (isempty(suffix)) + return -ENOENT; + + ret->physfn_pcidev = TAKE_PTR(physfn_pcidev); + strncpy(ret->suffix, suffix, sizeof(ret->suffix)); + + return 0; +} + +/* retrieve on-board index number and label from firmware */ +static int dev_pci_onboard(sd_device *dev, struct netnames *names) { + unsigned long idx, dev_port = 0; + const char *attr, *port_name = NULL; + size_t l; + char *s; + int r; + + /* ACPI _DSM — device specific method for naming a PCI or PCI Express device */ + if (sd_device_get_sysattr_value(names->pcidev, "acpi_index", &attr) < 0) { + /* SMBIOS type 41 — Onboard Devices Extended Information */ + r = sd_device_get_sysattr_value(names->pcidev, "index", &attr); + if (r < 0) + return r; + } + + r = safe_atolu(attr, &idx); + if (r < 0) + return r; + if (idx == 0 && !naming_scheme_has(NAMING_ZERO_ACPI_INDEX)) + return -EINVAL; + + /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to + * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We + * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network + * interface a system might have. Ideally the kernel would already filter his crap for us, but it + * doesn't currently. */ + if (idx > ONBOARD_INDEX_MAX) + return -ENOENT; + + /* kernel provided port index for multiple ports on a single PCI function */ + if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) + dev_port = strtoul(attr, NULL, 10); + + /* kernel provided front panel port name for multiple port PCI device */ + (void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name); + + s = names->pci_onboard; + l = sizeof(names->pci_onboard); + l = strpcpyf(&s, l, "o%lu", idx); + if (port_name) + l = strpcpyf(&s, l, "n%s", port_name); + else if (dev_port > 0) + l = strpcpyf(&s, l, "d%lu", dev_port); + if (l == 0) + names->pci_onboard[0] = '\0'; + + if (sd_device_get_sysattr_value(names->pcidev, "label", &names->pci_onboard_label) < 0) + names->pci_onboard_label = NULL; + + return 0; +} + +/* read the 256 bytes PCI configuration space to check the multi-function bit */ +static bool is_pci_multifunction(sd_device *dev) { + _cleanup_close_ int fd = -1; + const char *filename, *syspath; + uint8_t config[64]; + + if (sd_device_get_syspath(dev, &syspath) < 0) + return false; + + filename = strjoina(syspath, "/config"); + fd = open(filename, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return false; + if (read(fd, &config, sizeof(config)) != sizeof(config)) + return false; + + /* bit 0-6 header type, bit 7 multi/single function device */ + return config[PCI_HEADER_TYPE] & 0x80; +} + +static bool is_pci_ari_enabled(sd_device *dev) { + const char *a; + + if (sd_device_get_sysattr_value(dev, "ari_enabled", &a) < 0) + return false; + + return streq(a, "1"); +} + +static int dev_pci_slot(sd_device *dev, struct netnames *names) { + unsigned long dev_port = 0; + unsigned domain, bus, slot, func, hotplug_slot = 0; + size_t l; + char *s; + const char *sysname, *attr, *port_name = NULL, *syspath; + _cleanup_(sd_device_unrefp) sd_device *pci = NULL; + sd_device *hotplug_slot_dev; + char slots[PATH_MAX]; + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *dent; + int r; + + r = sd_device_get_sysname(names->pcidev, &sysname); + if (r < 0) + return r; + + if (sscanf(sysname, "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4) + return -ENOENT; + + if (naming_scheme_has(NAMING_NPAR_ARI) && + is_pci_ari_enabled(names->pcidev)) + /* ARI devices support up to 256 functions on a single device ("slot"), and interpret the + * traditional 5-bit slot and 3-bit function number as a single 8-bit function number, + * where the slot makes up the upper 5 bits. */ + func += slot * 8; + + /* kernel provided port index for multiple ports on a single PCI function */ + if (sd_device_get_sysattr_value(dev, "dev_port", &attr) >= 0) { + dev_port = strtoul(attr, NULL, 10); + /* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously + * provide the port number in the 'dev_id' sysfs attribute instead of 'dev_port', + * which thus stays initialized as 0. */ + if (dev_port == 0 && + sd_device_get_sysattr_value(dev, "type", &attr) >= 0) { + unsigned long type; + + type = strtoul(attr, NULL, 10); + if (type == ARPHRD_INFINIBAND && + sd_device_get_sysattr_value(dev, "dev_id", &attr) >= 0) + dev_port = strtoul(attr, NULL, 16); + } + } + + /* kernel provided front panel port name for multi-port PCI device */ + (void) sd_device_get_sysattr_value(dev, "phys_port_name", &port_name); + + /* compose a name based on the raw kernel's PCI bus, slot numbers */ + s = names->pci_path; + l = sizeof(names->pci_path); + if (domain > 0) + l = strpcpyf(&s, l, "P%u", domain); + l = strpcpyf(&s, l, "p%us%u", bus, slot); + if (func > 0 || is_pci_multifunction(names->pcidev)) + l = strpcpyf(&s, l, "f%u", func); + if (port_name) + l = strpcpyf(&s, l, "n%s", port_name); + else if (dev_port > 0) + l = strpcpyf(&s, l, "d%lu", dev_port); + if (l == 0) + names->pci_path[0] = '\0'; + + /* ACPI _SUN — slot user number */ + r = sd_device_new_from_subsystem_sysname(&pci, "subsystem", "pci"); + if (r < 0) + return r; + + r = sd_device_get_syspath(pci, &syspath); + if (r < 0) + return r; + if (!snprintf_ok(slots, sizeof slots, "%s/slots", syspath)) + return -ENAMETOOLONG; + + dir = opendir(slots); + if (!dir) + return -errno; + + hotplug_slot_dev = names->pcidev; + while (hotplug_slot_dev) { + if (sd_device_get_sysname(hotplug_slot_dev, &sysname) < 0) + continue; + + FOREACH_DIRENT_ALL(dent, dir, break) { + unsigned i; + char str[PATH_MAX]; + _cleanup_free_ char *address = NULL; + + if (dent->d_name[0] == '.') + continue; + r = safe_atou_full(dent->d_name, 10, &i); + if (r < 0 || i <= 0) + continue; + + /* match slot address with device by stripping the function */ + if (snprintf_ok(str, sizeof str, "%s/%s/address", slots, dent->d_name) && + read_one_line_file(str, &address) >= 0 && + startswith(sysname, address)) { + hotplug_slot = i; + break; + } + } + if (hotplug_slot > 0) + break; + if (sd_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL, &hotplug_slot_dev) < 0) + break; + rewinddir(dir); + } + + if (hotplug_slot > 0) { + s = names->pci_slot; + l = sizeof(names->pci_slot); + if (domain > 0) + l = strpcpyf(&s, l, "P%d", domain); + l = strpcpyf(&s, l, "s%d", hotplug_slot); + if (func > 0 || is_pci_multifunction(names->pcidev)) + l = strpcpyf(&s, l, "f%d", func); + if (port_name) + l = strpcpyf(&s, l, "n%s", port_name); + else if (dev_port > 0) + l = strpcpyf(&s, l, "d%lu", dev_port); + if (l == 0) + names->pci_slot[0] = '\0'; + } + + return 0; +} + +static int names_vio(sd_device *dev, struct netnames *names) { + sd_device *parent; + unsigned busid, slotid, ethid; + const char *syspath, *subsystem; + int r; + + /* check if our direct parent is a VIO device with no other bus in-between */ + r = sd_device_get_parent(dev, &parent); + if (r < 0) + return r; + + r = sd_device_get_subsystem(parent, &subsystem); + if (r < 0) + return r; + if (!streq("vio", subsystem)) + return -ENOENT; + + /* The devices' $DEVPATH number is tied to (virtual) hardware (slot id + * selected in the HMC), thus this provides a reliable naming (e.g. + * "/devices/vio/30000002/net/eth1"); we ignore the bus number, as + * there should only ever be one bus, and then remove leading zeros. */ + r = sd_device_get_syspath(dev, &syspath); + if (r < 0) + return r; + + if (sscanf(syspath, "/sys/devices/vio/%4x%4x/net/eth%u", &busid, &slotid, ðid) != 3) + return -EINVAL; + + xsprintf(names->vio_slot, "v%u", slotid); + names->type = NET_VIO; + return 0; +} + +#define _PLATFORM_TEST "/sys/devices/platform/vvvvPPPP" +#define _PLATFORM_PATTERN4 "/sys/devices/platform/%4s%4x:%2x/net/eth%u" +#define _PLATFORM_PATTERN3 "/sys/devices/platform/%3s%4x:%2x/net/eth%u" + +static int names_platform(sd_device *dev, struct netnames *names, bool test) { + sd_device *parent; + char vendor[5]; + unsigned model, instance, ethid; + const char *syspath, *pattern, *validchars, *subsystem; + int r; + + /* check if our direct parent is a platform device with no other bus in-between */ + r = sd_device_get_parent(dev, &parent); + if (r < 0) + return r; + + r = sd_device_get_subsystem(parent, &subsystem); + if (r < 0) + return r; + + if (!streq("platform", subsystem)) + return -ENOENT; + + r = sd_device_get_syspath(dev, &syspath); + if (r < 0) + return r; + + /* syspath is too short, to have a valid ACPI instance */ + if (strlen(syspath) < sizeof _PLATFORM_TEST) + return -EINVAL; + + /* Vendor ID can be either PNP ID (3 chars A-Z) or ACPI ID (4 chars A-Z and numerals) */ + if (syspath[sizeof _PLATFORM_TEST - 1] == ':') { + pattern = _PLATFORM_PATTERN4; + validchars = UPPERCASE_LETTERS DIGITS; + } else { + pattern = _PLATFORM_PATTERN3; + validchars = UPPERCASE_LETTERS; + } + + /* Platform devices are named after ACPI table match, and instance id + * eg. "/sys/devices/platform/HISI00C2:00"); + * The Vendor (3 or 4 char), followed by hexdecimal model number : instance id. + */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + if (sscanf(syspath, pattern, vendor, &model, &instance, ðid) != 4) + return -EINVAL; +#pragma GCC diagnostic pop + + if (!in_charset(vendor, validchars)) + return -ENOENT; + + ascii_strlower(vendor); + + xsprintf(names->platform_path, "a%s%xi%u", vendor, model, instance); + names->type = NET_PLATFORM; + return 0; +} + +static int names_pci(sd_device *dev, struct netnames *names) { + sd_device *parent; + struct netnames vf_names = {}; + struct virtfn_info vf_info = {}; + const char *subsystem; + int r; + + assert(dev); + assert(names); + + r = sd_device_get_parent(dev, &parent); + if (r < 0) + return r; + /* skip virtio subsystem if present */ + parent = skip_virtio(parent); + + if (!parent) + return -ENOENT; + + /* check if our direct parent is a PCI device with no other bus in-between */ + if (sd_device_get_subsystem(parent, &subsystem) >= 0 && + streq("pci", subsystem)) { + names->type = NET_PCI; + names->pcidev = parent; + } else { + r = sd_device_get_parent_with_subsystem_devtype(dev, "pci", NULL, &names->pcidev); + if (r < 0) + return r; + } + + if (naming_scheme_has(NAMING_SR_IOV_V) && + get_virtfn_info(dev, names, &vf_info) >= 0) { + /* If this is an SR-IOV virtual device, get base name using physical device and add virtfn suffix. */ + vf_names.pcidev = vf_info.physfn_pcidev; + dev_pci_onboard(dev, &vf_names); + dev_pci_slot(dev, &vf_names); + if (vf_names.pci_onboard[0]) + if (strlen(vf_names.pci_onboard) + strlen(vf_info.suffix) < sizeof(names->pci_onboard)) + strscpyl(names->pci_onboard, sizeof(names->pci_onboard), + vf_names.pci_onboard, vf_info.suffix, NULL); + if (vf_names.pci_slot[0]) + if (strlen(vf_names.pci_slot) + strlen(vf_info.suffix) < sizeof(names->pci_slot)) + strscpyl(names->pci_slot, sizeof(names->pci_slot), + vf_names.pci_slot, vf_info.suffix, NULL); + if (vf_names.pci_path[0]) + if (strlen(vf_names.pci_path) + strlen(vf_info.suffix) < sizeof(names->pci_path)) + strscpyl(names->pci_path, sizeof(names->pci_path), + vf_names.pci_path, vf_info.suffix, NULL); + sd_device_unref(vf_info.physfn_pcidev); + } else { + dev_pci_onboard(dev, names); + dev_pci_slot(dev, names); + } + + return 0; +} + +static int names_usb(sd_device *dev, struct netnames *names) { + sd_device *usbdev; + char name[256], *ports, *config, *interf, *s; + const char *sysname; + size_t l; + int r; + + assert(dev); + assert(names); + + r = sd_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface", &usbdev); + if (r < 0) + return r; + + r = sd_device_get_sysname(usbdev, &sysname); + if (r < 0) + return r; + + /* get USB port number chain, configuration, interface */ + strscpy(name, sizeof(name), sysname); + s = strchr(name, '-'); + if (!s) + return -EINVAL; + ports = s+1; + + s = strchr(ports, ':'); + if (!s) + return -EINVAL; + s[0] = '\0'; + config = s+1; + + s = strchr(config, '.'); + if (!s) + return -EINVAL; + s[0] = '\0'; + interf = s+1; + + /* prefix every port number in the chain with "u" */ + s = ports; + while ((s = strchr(s, '.'))) + s[0] = 'u'; + s = names->usb_ports; + l = strpcpyl(&s, sizeof(names->usb_ports), "u", ports, NULL); + + /* append USB config number, suppress the common config == 1 */ + if (!streq(config, "1")) + l = strpcpyl(&s, sizeof(names->usb_ports), "c", config, NULL); + + /* append USB interface number, suppress the interface == 0 */ + if (!streq(interf, "0")) + l = strpcpyl(&s, sizeof(names->usb_ports), "i", interf, NULL); + if (l == 0) + return -ENAMETOOLONG; + + names->type = NET_USB; + return 0; +} + +static int names_bcma(sd_device *dev, struct netnames *names) { + sd_device *bcmadev; + unsigned core; + const char *sysname; + int r; + + assert(dev); + assert(names); + + r = sd_device_get_parent_with_subsystem_devtype(dev, "bcma", NULL, &bcmadev); + if (r < 0) + return r; + + r = sd_device_get_sysname(bcmadev, &sysname); + if (r < 0) + return r; + + /* bus num:core num */ + if (sscanf(sysname, "bcma%*u:%u", &core) != 1) + return -EINVAL; + /* suppress the common core == 0 */ + if (core > 0) + xsprintf(names->bcma_core, "b%u", core); + + names->type = NET_BCMA; + return 0; +} + +static int names_ccw(sd_device *dev, struct netnames *names) { + sd_device *cdev; + const char *bus_id, *subsys; + size_t bus_id_len; + size_t bus_id_start; + int r; + + assert(dev); + assert(names); + + /* Retrieve the associated CCW device */ + r = sd_device_get_parent(dev, &cdev); + if (r < 0) + return r; + + /* skip virtio subsystem if present */ + cdev = skip_virtio(cdev); + if (!cdev) + return -ENOENT; + + r = sd_device_get_subsystem(cdev, &subsys); + if (r < 0) + return r; + + /* Network devices are either single or grouped CCW devices */ + if (!STR_IN_SET(subsys, "ccwgroup", "ccw")) + return -ENOENT; + + /* Retrieve bus-ID of the CCW device. The bus-ID uniquely + * identifies the network device on the Linux on System z channel + * subsystem. Note that the bus-ID contains lowercase characters. + */ + r = sd_device_get_sysname(cdev, &bus_id); + if (r < 0) + return r; + + /* Check the length of the bus-ID. Rely on the fact that the kernel provides a correct bus-ID; + * alternatively, improve this check and parse and verify each bus-ID part... + */ + bus_id_len = strlen(bus_id); + if (!IN_SET(bus_id_len, 8, 9)) + return -EINVAL; + + /* Strip leading zeros from the bus id for aesthetic purposes. This + * keeps the ccw names stable, yet much shorter in general case of + * bus_id 0.0.0600 -> 600. This is similar to e.g. how PCI domain is + * not prepended when it is zero. Preserve the last 0 for 0.0.0000. + */ + bus_id_start = strspn(bus_id, ".0"); + bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1; + + /* Store the CCW bus-ID for use as network device name */ + if (snprintf_ok(names->ccw_busid, sizeof(names->ccw_busid), "c%s", bus_id)) + names->type = NET_CCW; + + return 0; +} + +static int names_mac(sd_device *dev, struct netnames *names) { + const char *s; + unsigned long i; + unsigned a1, a2, a3, a4, a5, a6; + int r; + + /* Some kinds of devices tend to have hardware addresses + * that are impossible to use in an iface name. + */ + r = sd_device_get_sysattr_value(dev, "type", &s); + if (r < 0) + return r; + + i = strtoul(s, NULL, 0); + switch (i) { + /* The persistent part of a hardware address of an InfiniBand NIC + * is 8 bytes long. We cannot fit this much in an iface name. + */ + case ARPHRD_INFINIBAND: + return -EINVAL; + default: + break; + } + + /* check for NET_ADDR_PERM, skip random MAC addresses */ + r = sd_device_get_sysattr_value(dev, "addr_assign_type", &s); + if (r < 0) + return r; + i = strtoul(s, NULL, 0); + if (i != 0) + return 0; + + r = sd_device_get_sysattr_value(dev, "address", &s); + if (r < 0) + return r; + if (sscanf(s, "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6) != 6) + return -EINVAL; + + /* skip empty MAC addresses */ + if (a1 + a2 + a3 + a4 + a5 + a6 == 0) + return -EINVAL; + + names->mac[0] = a1; + names->mac[1] = a2; + names->mac[2] = a3; + names->mac[3] = a4; + names->mac[4] = a5; + names->mac[5] = a6; + names->mac_valid = true; + return 0; +} + +static int names_netdevsim(sd_device *dev, struct netnames *names) { + sd_device *netdevsimdev; + const char *sysname; + unsigned addr; + const char *port_name = NULL; + int r; + bool ok; + + if (!naming_scheme_has(NAMING_NETDEVSIM)) + return 0; + + assert(dev); + assert(names); + + r = sd_device_get_parent_with_subsystem_devtype(dev, "netdevsim", NULL, &netdevsimdev); + if (r < 0) + return r; + r = sd_device_get_sysname(netdevsimdev, &sysname); + if (r < 0) + return r; + + if (sscanf(sysname, "netdevsim%u", &addr) != 1) + return -EINVAL; + + r = sd_device_get_sysattr_value(dev, "phys_port_name", &port_name); + if (r < 0) + return r; + + ok = snprintf_ok(names->netdevsim_path, sizeof(names->netdevsim_path), "i%un%s", addr, port_name); + if (!ok) + return -ENOBUFS; + + names->type = NET_NETDEVSIM; + + return 0; +} + +/* IEEE Organizationally Unique Identifier vendor string */ +static int ieee_oui(sd_device *dev, struct netnames *names, bool test) { + char str[32]; + + if (!names->mac_valid) + return -ENOENT; + /* skip commonly misused 00:00:00 (Xerox) prefix */ + if (memcmp(names->mac, "\0\0\0", 3) == 0) + return -EINVAL; + xsprintf(str, "OUI:%02X%02X%02X%02X%02X%02X", names->mac[0], + names->mac[1], names->mac[2], names->mac[3], names->mac[4], + names->mac[5]); + udev_builtin_hwdb_lookup(dev, NULL, str, NULL, test); + return 0; +} + +static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) { + const char *s, *p, *devtype, *prefix = "en"; + struct netnames names = {}; + unsigned long i; + int r; + + /* handle only ARPHRD_ETHER, ARPHRD_SLIP and ARPHRD_INFINIBAND devices */ + r = sd_device_get_sysattr_value(dev, "type", &s); + if (r < 0) + return r; + + i = strtoul(s, NULL, 0); + switch (i) { + case ARPHRD_ETHER: + prefix = "en"; + break; + case ARPHRD_INFINIBAND: + if (naming_scheme_has(NAMING_INFINIBAND)) + prefix = "ib"; + else + return 0; + break; + case ARPHRD_SLIP: + prefix = "sl"; + break; + default: + return 0; + } + + /* skip stacked devices, like VLANs, ... */ + r = sd_device_get_sysattr_value(dev, "ifindex", &s); + if (r < 0) + return r; + r = sd_device_get_sysattr_value(dev, "iflink", &p); + if (r < 0) + return r; + if (!streq(s, p)) + return 0; + + if (sd_device_get_devtype(dev, &devtype) >= 0) { + if (streq("wlan", devtype)) + prefix = "wl"; + else if (streq("wwan", devtype)) + prefix = "ww"; + } + + udev_builtin_add_property(dev, test, "ID_NET_NAMING_SCHEME", naming_scheme()->name); + + r = names_mac(dev, &names); + if (r >= 0 && names.mac_valid) { + char str[IFNAMSIZ]; + + xsprintf(str, "%sx%02x%02x%02x%02x%02x%02x", prefix, + names.mac[0], names.mac[1], names.mac[2], + names.mac[3], names.mac[4], names.mac[5]); + udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str); + + ieee_oui(dev, &names, test); + } + + /* get path names for Linux on System z network devices */ + if (names_ccw(dev, &names) >= 0 && names.type == NET_CCW) { + char str[IFNAMSIZ]; + + if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.ccw_busid)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); + return 0; + } + + /* get ibmveth/ibmvnic slot-based names. */ + if (names_vio(dev, &names) >= 0 && names.type == NET_VIO) { + char str[IFNAMSIZ]; + + if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.vio_slot)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); + return 0; + } + + /* get ACPI path names for ARM64 platform devices */ + if (names_platform(dev, &names, test) >= 0 && names.type == NET_PLATFORM) { + char str[IFNAMSIZ]; + + if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.platform_path)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); + return 0; + } + + /* get netdevsim path names */ + if (names_netdevsim(dev, &names) >= 0 && names.type == NET_NETDEVSIM) { + char str[IFNAMSIZ]; + + if (snprintf_ok(str, sizeof str, "%s%s", prefix, names.netdevsim_path)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); + + return 0; + } + + /* get PCI based path names, we compose only PCI based paths */ + if (names_pci(dev, &names) < 0) + return 0; + + /* plain PCI device */ + if (names.type == NET_PCI) { + char str[IFNAMSIZ]; + + if (names.pci_onboard[0] && + snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_onboard)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str); + + if (names.pci_onboard_label && + snprintf_ok(str, sizeof str, "%s%s", + naming_scheme_has(NAMING_LABEL_NOPREFIX) ? "" : prefix, + names.pci_onboard_label)) + udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str); + + if (names.pci_path[0] && + snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_path)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); + + if (names.pci_slot[0] && + snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_slot)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); + return 0; + } + + /* USB device */ + if (names_usb(dev, &names) >= 0 && names.type == NET_USB) { + char str[IFNAMSIZ]; + + if (names.pci_path[0] && + snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_path, names.usb_ports)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); + + if (names.pci_slot[0] && + snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_slot, names.usb_ports)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); + return 0; + } + + /* Broadcom bus */ + if (names_bcma(dev, &names) >= 0 && names.type == NET_BCMA) { + char str[IFNAMSIZ]; + + if (names.pci_path[0] && + snprintf_ok(str, sizeof str, "%s%s%s", prefix, names.pci_path, names.bcma_core)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); + + if (names.pci_slot[0] && + snprintf(str, sizeof str, "%s%s%s", prefix, names.pci_slot, names.bcma_core)) + udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); + return 0; + } + + return 0; +} + +const UdevBuiltin udev_builtin_net_id = { + .name = "net_id", + .cmd = builtin_net_id, + .help = "Network device properties", +}; diff --git a/src/udev/udev-builtin-net_setup_link.c b/src/udev/udev-builtin-net_setup_link.c new file mode 100644 index 00000000..ee3ca9fa --- /dev/null +++ b/src/udev/udev-builtin-net_setup_link.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "device-util.h" +#include "alloc-util.h" +#include "link-config.h" +#include "log.h" +#include "string-util.h" +#include "udev-builtin.h" + +static link_config_ctx *ctx = NULL; + +static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool test) { + _cleanup_free_ char *driver = NULL; + const char *name = NULL; + link_config *link; + int r; + + if (argc > 1) + return log_device_error_errno(dev, SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); + + r = link_get_driver(ctx, dev, &driver); + if (r >= 0) + udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver); + + r = link_config_get(ctx, dev, &link); + if (r < 0) { + if (r == -ENOENT) + return log_device_debug_errno(dev, r, "No matching link configuration found."); + + return log_device_error_errno(dev, r, "Failed to get link config: %m"); + } + + r = link_config_apply(ctx, link, dev, &name); + if (r < 0) + log_device_warning_errno(dev, r, "Could not apply link config, ignoring: %m"); + + udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE", link->filename); + + if (name) + udev_builtin_add_property(dev, test, "ID_NET_NAME", name); + + return 0; +} + +static int builtin_net_setup_link_init(void) { + int r; + + if (ctx) + return 0; + + r = link_config_ctx_new(&ctx); + if (r < 0) + return r; + + r = link_config_load(ctx); + if (r < 0) + return r; + + log_debug("Created link configuration context."); + return 0; +} + +static void builtin_net_setup_link_exit(void) { + link_config_ctx_free(ctx); + ctx = NULL; + log_debug("Unloaded link configuration context."); +} + +static bool builtin_net_setup_link_validate(void) { + log_debug("Check if link configuration needs reloading."); + if (!ctx) + return false; + + return link_config_should_reload(ctx); +} + +const UdevBuiltin udev_builtin_net_setup_link = { + .name = "net_setup_link", + .cmd = builtin_net_setup_link, + .init = builtin_net_setup_link_init, + .exit = builtin_net_setup_link_exit, + .validate = builtin_net_setup_link_validate, + .help = "Configure network link", + .run_once = false, +}; diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c new file mode 100644 index 00000000..ca38f560 --- /dev/null +++ b/src/udev/udev-builtin-path_id.c @@ -0,0 +1,682 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * compose persistent device path + * + * Logic based on Hannes Reinecke's shell script. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "libudev-util.h" +#include "string-util.h" +#include "strv.h" +#include "sysexits.h" +#include "udev-builtin.h" + +_printf_(2,3) +static void path_prepend(char **path, const char *fmt, ...) { + va_list va; + _cleanup_free_ char *pre = NULL; + int r; + + va_start(va, fmt); + r = vasprintf(&pre, fmt, va); + va_end(va); + if (r < 0) { + log_oom(); + exit(EX_OSERR); + } + + if (*path) { + char *new; + + new = strjoin(pre, "-", *path); + if (!new) { + log_oom(); + exit(EX_OSERR); + } + + free_and_replace(*path, new); + } else + *path = TAKE_PTR(pre); +} + +/* +** Linux only supports 32 bit luns. +** See drivers/scsi/scsi_scan.c::scsilun_to_int() for more details. +*/ +static int format_lun_number(sd_device *dev, char **path) { + const char *sysnum; + unsigned long lun; + int r; + + r = sd_device_get_sysnum(dev, &sysnum); + if (r < 0) + return r; + if (!sysnum) + return -ENOENT; + + lun = strtoul(sysnum, NULL, 10); + if (lun < 256) + /* address method 0, peripheral device addressing with bus id of zero */ + path_prepend(path, "lun-%lu", lun); + else + /* handle all other lun addressing methods by using a variant of the original lun format */ + path_prepend(path, "lun-0x%04lx%04lx00000000", lun & 0xffff, (lun >> 16) & 0xffff); + + return 0; +} + +static sd_device *skip_subsystem(sd_device *dev, const char *subsys) { + sd_device *parent; + + assert(dev); + assert(subsys); + + for (parent = dev; ; ) { + const char *subsystem; + + if (sd_device_get_subsystem(parent, &subsystem) < 0) + break; + + if (!streq(subsystem, subsys)) + break; + + dev = parent; + if (sd_device_get_parent(dev, &parent) < 0) + break; + } + + return dev; +} + +static sd_device *handle_scsi_fibre_channel(sd_device *parent, char **path) { + sd_device *targetdev; + _cleanup_(sd_device_unrefp) sd_device *fcdev = NULL; + const char *port, *sysname; + _cleanup_free_ char *lun = NULL; + + assert(parent); + assert(path); + + if (sd_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target", &targetdev) < 0) + return NULL; + if (sd_device_get_sysname(targetdev, &sysname) < 0) + return NULL; + if (sd_device_new_from_subsystem_sysname(&fcdev, "fc_transport", sysname) < 0) + return NULL; + if (sd_device_get_sysattr_value(fcdev, "port_name", &port) < 0) + return NULL; + + format_lun_number(parent, &lun); + path_prepend(path, "fc-%s-%s", port, lun); + return parent; +} + +static sd_device *handle_scsi_sas_wide_port(sd_device *parent, char **path) { + sd_device *targetdev, *target_parent; + _cleanup_(sd_device_unrefp) sd_device *sasdev = NULL; + const char *sas_address, *sysname; + _cleanup_free_ char *lun = NULL; + + assert(parent); + assert(path); + + if (sd_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target", &targetdev) < 0) + return NULL; + if (sd_device_get_parent(targetdev, &target_parent) < 0) + return NULL; + if (sd_device_get_sysname(target_parent, &sysname) < 0) + return NULL; + if (sd_device_new_from_subsystem_sysname(&sasdev, "sas_device", sysname) < 0) + return NULL; + if (sd_device_get_sysattr_value(sasdev, "sas_address", &sas_address) < 0) + return NULL; + + format_lun_number(parent, &lun); + path_prepend(path, "sas-%s-%s", sas_address, lun); + return parent; +} + +static sd_device *handle_scsi_sas(sd_device *parent, char **path) { + sd_device *targetdev, *target_parent, *port, *expander; + _cleanup_(sd_device_unrefp) sd_device *target_sasdev = NULL, *expander_sasdev = NULL, *port_sasdev = NULL; + const char *sas_address = NULL; + const char *phy_id; + const char *phy_count, *sysname; + _cleanup_free_ char *lun = NULL; + + assert(parent); + assert(path); + + if (sd_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target", &targetdev) < 0) + return NULL; + if (sd_device_get_parent(targetdev, &target_parent) < 0) + return NULL; + if (sd_device_get_sysname(target_parent, &sysname) < 0) + return NULL; + /* Get sas device */ + if (sd_device_new_from_subsystem_sysname(&target_sasdev, "sas_device", sysname) < 0) + return NULL; + /* The next parent is sas port */ + if (sd_device_get_parent(target_parent, &port) < 0) + return NULL; + if (sd_device_get_sysname(port, &sysname) < 0) + return NULL; + /* Get port device */ + if (sd_device_new_from_subsystem_sysname(&port_sasdev, "sas_port", sysname) < 0) + return NULL; + if (sd_device_get_sysattr_value(port_sasdev, "num_phys", &phy_count) < 0) + return NULL; + + /* Check if we are simple disk */ + if (strncmp(phy_count, "1", 2) != 0) + return handle_scsi_sas_wide_port(parent, path); + + /* Get connected phy */ + if (sd_device_get_sysattr_value(target_sasdev, "phy_identifier", &phy_id) < 0) + return NULL; + + /* The port's parent is either hba or expander */ + if (sd_device_get_parent(port, &expander) < 0) + return NULL; + + if (sd_device_get_sysname(expander, &sysname) < 0) + return NULL; + /* Get expander device */ + if (sd_device_new_from_subsystem_sysname(&expander_sasdev, "sas_device", sysname) >= 0) { + /* Get expander's address */ + if (sd_device_get_sysattr_value(expander_sasdev, "sas_address", &sas_address) < 0) + return NULL; + } + + format_lun_number(parent, &lun); + if (sas_address) + path_prepend(path, "sas-exp%s-phy%s-%s", sas_address, phy_id, lun); + else + path_prepend(path, "sas-phy%s-%s", phy_id, lun); + + return parent; +} + +static sd_device *handle_scsi_iscsi(sd_device *parent, char **path) { + sd_device *transportdev; + _cleanup_(sd_device_unrefp) sd_device *sessiondev = NULL, *conndev = NULL; + const char *target, *connname, *addr, *port; + _cleanup_free_ char *lun = NULL; + const char *sysname, *sysnum; + + assert(parent); + assert(path); + + /* find iscsi session */ + for (transportdev = parent; ; ) { + + if (sd_device_get_parent(transportdev, &transportdev) < 0) + return NULL; + if (sd_device_get_sysname(transportdev, &sysname) < 0) + return NULL; + if (startswith(sysname, "session")) + break; + } + + /* find iscsi session device */ + if (sd_device_new_from_subsystem_sysname(&sessiondev, "iscsi_session", sysname) < 0) + return NULL; + + if (sd_device_get_sysattr_value(sessiondev, "targetname", &target) < 0) + return NULL; + + if (sd_device_get_sysnum(transportdev, &sysnum) < 0 || !sysnum) + return NULL; + connname = strjoina("connection", sysnum, ":0"); + if (sd_device_new_from_subsystem_sysname(&conndev, "iscsi_connection", connname) < 0) + return NULL; + + if (sd_device_get_sysattr_value(conndev, "persistent_address", &addr) < 0) + return NULL; + if (sd_device_get_sysattr_value(conndev, "persistent_port", &port) < 0) + return NULL; + + format_lun_number(parent, &lun); + path_prepend(path, "ip-%s:%s-iscsi-%s-%s", addr, port, target, lun); + return parent; +} + +static sd_device *handle_scsi_ata(sd_device *parent, char **path) { + sd_device *targetdev, *target_parent; + _cleanup_(sd_device_unrefp) sd_device *atadev = NULL; + const char *port_no, *sysname; + + assert(parent); + assert(path); + + if (sd_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host", &targetdev) < 0) + return NULL; + + if (sd_device_get_parent(targetdev, &target_parent) < 0) + return NULL; + + if (sd_device_get_sysname(target_parent, &sysname) < 0) + return NULL; + if (sd_device_new_from_subsystem_sysname(&atadev, "ata_port", sysname) < 0) + return NULL; + + if (sd_device_get_sysattr_value(atadev, "port_no", &port_no) < 0) + return NULL; + + path_prepend(path, "ata-%s", port_no); + return parent; +} + +static sd_device *handle_scsi_default(sd_device *parent, char **path) { + sd_device *hostdev; + int host, bus, target, lun; + const char *name, *base, *pos; + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *dent; + int basenum = -1; + + assert(parent); + assert(path); + + if (sd_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host", &hostdev) < 0) + return NULL; + + if (sd_device_get_sysname(parent, &name) < 0) + return NULL; + if (sscanf(name, "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) + return NULL; + + /* + * Rebase host offset to get the local relative number + * + * Note: This is by definition racy, unreliable and too simple. + * Please do not copy this model anywhere. It's just a left-over + * from the time we had no idea how things should look like in + * the end. + * + * Making assumptions about a global in-kernel counter and use + * that to calculate a local offset is a very broken concept. It + * can only work as long as things are in strict order. + * + * The kernel needs to export the instance/port number of a + * controller directly, without the need for rebase magic like + * this. Manual driver unbind/bind, parallel hotplug/unplug will + * get into the way of this "I hope it works" logic. + */ + + if (sd_device_get_syspath(hostdev, &base) < 0) + return NULL; + pos = strrchr(base, '/'); + if (!pos) + return NULL; + + base = strndupa(base, pos - base); + dir = opendir(base); + if (!dir) + return NULL; + + FOREACH_DIRENT_ALL(dent, dir, break) { + char *rest; + int i; + + if (dent->d_name[0] == '.') + continue; + if (!IN_SET(dent->d_type, DT_DIR, DT_LNK)) + continue; + if (!startswith(dent->d_name, "host")) + continue; + i = strtoul(&dent->d_name[4], &rest, 10); + if (rest[0] != '\0') + continue; + /* + * find the smallest number; the host really needs to export its + * own instance number per parent device; relying on the global host + * enumeration and plainly rebasing the numbers sounds unreliable + */ + if (basenum == -1 || i < basenum) + basenum = i; + } + if (basenum == -1) + return hostdev; + host -= basenum; + + path_prepend(path, "scsi-%u:%u:%u:%u", host, bus, target, lun); + return hostdev; +} + +static sd_device *handle_scsi_hyperv(sd_device *parent, char **path, size_t guid_str_len) { + sd_device *hostdev; + sd_device *vmbusdev; + const char *guid_str; + _cleanup_free_ char *lun = NULL; + char guid[39]; + size_t i, k; + + assert(parent); + assert(path); + assert(guid_str_len < sizeof(guid)); + + if (sd_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host", &hostdev) < 0) + return NULL; + + if (sd_device_get_parent(hostdev, &vmbusdev) < 0) + return NULL; + + if (sd_device_get_sysattr_value(vmbusdev, "device_id", &guid_str) < 0) + return NULL; + + if (strlen(guid_str) < guid_str_len || guid_str[0] != '{' || guid_str[guid_str_len-1] != '}') + return NULL; + + for (i = 1, k = 0; i < guid_str_len-1; i++) { + if (guid_str[i] == '-') + continue; + guid[k++] = guid_str[i]; + } + guid[k] = '\0'; + + format_lun_number(parent, &lun); + path_prepend(path, "vmbus-%s-%s", guid, lun); + return parent; +} + +static sd_device *handle_scsi(sd_device *parent, char **path, bool *supported_parent) { + const char *devtype, *id, *name; + + if (sd_device_get_devtype(parent, &devtype) < 0 || + !streq(devtype, "scsi_device")) + return parent; + + /* firewire */ + if (sd_device_get_sysattr_value(parent, "ieee1394_id", &id) >= 0) { + path_prepend(path, "ieee1394-0x%s", id); + *supported_parent = true; + return skip_subsystem(parent, "scsi"); + } + + /* scsi sysfs does not have a "subsystem" for the transport */ + if (sd_device_get_syspath(parent, &name) < 0) + return NULL; + + if (strstr(name, "/rport-")) { + *supported_parent = true; + return handle_scsi_fibre_channel(parent, path); + } + + if (strstr(name, "/end_device-")) { + *supported_parent = true; + return handle_scsi_sas(parent, path); + } + + if (strstr(name, "/session")) { + *supported_parent = true; + return handle_scsi_iscsi(parent, path); + } + + if (strstr(name, "/ata")) + return handle_scsi_ata(parent, path); + + if (strstr(name, "/vmbus_")) + return handle_scsi_hyperv(parent, path, 37); + else if (strstr(name, "/VMBUS")) + return handle_scsi_hyperv(parent, path, 38); + + return handle_scsi_default(parent, path); +} + +static sd_device *handle_cciss(sd_device *parent, char **path) { + const char *str; + unsigned controller, disk; + + if (sd_device_get_sysname(parent, &str) < 0) + return NULL; + if (sscanf(str, "c%ud%u%*s", &controller, &disk) != 2) + return NULL; + + path_prepend(path, "cciss-disk%u", disk); + return skip_subsystem(parent, "cciss"); +} + +static void handle_scsi_tape(sd_device *dev, char **path) { + const char *name; + + /* must be the last device in the syspath */ + if (*path) + return; + + if (sd_device_get_sysname(dev, &name) < 0) + return; + + if (startswith(name, "nst") && strchr("lma", name[3])) + path_prepend(path, "nst%c", name[3]); + else if (startswith(name, "st") && strchr("lma", name[2])) + path_prepend(path, "st%c", name[2]); +} + +static sd_device *handle_usb(sd_device *parent, char **path) { + const char *devtype, *str, *port; + + if (sd_device_get_devtype(parent, &devtype) < 0) + return parent; + if (!STR_IN_SET(devtype, "usb_interface", "usb_device")) + return parent; + + if (sd_device_get_sysname(parent, &str) < 0) + return parent; + port = strchr(str, '-'); + if (!port) + return parent; + port++; + + path_prepend(path, "usb-0:%s", port); + return skip_subsystem(parent, "usb"); +} + +static sd_device *handle_bcma(sd_device *parent, char **path) { + const char *sysname; + unsigned core; + + if (sd_device_get_sysname(parent, &sysname) < 0) + return NULL; + if (sscanf(sysname, "bcma%*u:%u", &core) != 1) + return NULL; + + path_prepend(path, "bcma-%u", core); + return parent; +} + +/* Handle devices of AP bus in System z platform. */ +static sd_device *handle_ap(sd_device *parent, char **path) { + const char *type, *func; + + assert(parent); + assert(path); + + if (sd_device_get_sysattr_value(parent, "type", &type) >= 0 && + sd_device_get_sysattr_value(parent, "ap_functions", &func) >= 0) + path_prepend(path, "ap-%s-%s", type, func); + else { + const char *sysname; + + if (sd_device_get_sysname(parent, &sysname) >= 0) + path_prepend(path, "ap-%s", sysname); + } + + return skip_subsystem(parent, "ap"); +} + +static int builtin_path_id(sd_device *dev, int argc, char *argv[], bool test) { + sd_device *parent; + _cleanup_free_ char *path = NULL; + bool supported_transport = false; + bool supported_parent = false; + const char *subsystem; + + assert(dev); + + /* walk up the chain of devices and compose path */ + parent = dev; + while (parent) { + const char *subsys, *sysname; + + if (sd_device_get_subsystem(parent, &subsys) < 0 || + sd_device_get_sysname(parent, &sysname) < 0) { + ; + } else if (streq(subsys, "scsi_tape")) { + handle_scsi_tape(parent, &path); + } else if (streq(subsys, "scsi")) { + parent = handle_scsi(parent, &path, &supported_parent); + supported_transport = true; + } else if (streq(subsys, "cciss")) { + parent = handle_cciss(parent, &path); + supported_transport = true; + } else if (streq(subsys, "usb")) { + parent = handle_usb(parent, &path); + supported_transport = true; + } else if (streq(subsys, "bcma")) { + parent = handle_bcma(parent, &path); + supported_transport = true; + } else if (streq(subsys, "serio")) { + const char *sysnum; + + if (sd_device_get_sysnum(parent, &sysnum) >= 0 && sysnum) { + path_prepend(&path, "serio-%s", sysnum); + parent = skip_subsystem(parent, "serio"); + } + } else if (streq(subsys, "pci")) { + path_prepend(&path, "pci-%s", sysname); + parent = skip_subsystem(parent, "pci"); + supported_parent = true; + } else if (streq(subsys, "platform")) { + path_prepend(&path, "platform-%s", sysname); + parent = skip_subsystem(parent, "platform"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "acpi")) { + path_prepend(&path, "acpi-%s", sysname); + parent = skip_subsystem(parent, "acpi"); + supported_parent = true; + } else if (streq(subsys, "xen")) { + path_prepend(&path, "xen-%s", sysname); + parent = skip_subsystem(parent, "xen"); + supported_parent = true; + } else if (streq(subsys, "virtio")) { + parent = skip_subsystem(parent, "virtio"); + supported_transport = true; + } else if (streq(subsys, "scm")) { + path_prepend(&path, "scm-%s", sysname); + parent = skip_subsystem(parent, "scm"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "ccw")) { + path_prepend(&path, "ccw-%s", sysname); + parent = skip_subsystem(parent, "ccw"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "ccwgroup")) { + path_prepend(&path, "ccwgroup-%s", sysname); + parent = skip_subsystem(parent, "ccwgroup"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "ap")) { + parent = handle_ap(parent, &path); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "iucv")) { + path_prepend(&path, "iucv-%s", sysname); + parent = skip_subsystem(parent, "iucv"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "nvme")) { + const char *nsid; + + if (sd_device_get_sysattr_value(dev, "nsid", &nsid) >= 0) { + path_prepend(&path, "nvme-%s", nsid); + parent = skip_subsystem(parent, "nvme"); + supported_parent = true; + supported_transport = true; + } + } + + if (!parent) + break; + if (sd_device_get_parent(parent, &parent) < 0) + break; + } + + if (!path) + return -ENOENT; + + /* + * Do not return devices with an unknown parent device type. They + * might produce conflicting IDs if the parent does not provide a + * unique and predictable name. + */ + if (!supported_parent) + return -ENOENT; + + /* + * Do not return block devices without a well-known transport. Some + * devices do not expose their buses and do not provide a unique + * and predictable name that way. + */ + if (sd_device_get_subsystem(dev, &subsystem) >= 0 && + streq(subsystem, "block") && + !supported_transport) + return -ENOENT; + + { + char tag[UTIL_NAME_SIZE]; + size_t i; + const char *p; + + /* compose valid udev tag name */ + for (p = path, i = 0; *p; p++) { + if ((*p >= '0' && *p <= '9') || + (*p >= 'A' && *p <= 'Z') || + (*p >= 'a' && *p <= 'z') || + *p == '-') { + tag[i++] = *p; + continue; + } + + /* skip all leading '_' */ + if (i == 0) + continue; + + /* avoid second '_' */ + if (tag[i-1] == '_') + continue; + + tag[i++] = '_'; + } + /* strip trailing '_' */ + while (i > 0 && tag[i-1] == '_') + i--; + tag[i] = '\0'; + + udev_builtin_add_property(dev, test, "ID_PATH", path); + udev_builtin_add_property(dev, test, "ID_PATH_TAG", tag); + } + + return 0; +} + +const UdevBuiltin udev_builtin_path_id = { + .name = "path_id", + .cmd = builtin_path_id, + .help = "Compose persistent device path", + .run_once = true, +}; diff --git a/src/udev/udev-builtin-uaccess.c b/src/udev/udev-builtin-uaccess.c new file mode 100644 index 00000000..63401a57 --- /dev/null +++ b/src/udev/udev-builtin-uaccess.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * manage device node user ACL + */ + +#include +#include +#include +#include + +#include "sd-login.h" + +#include "device-util.h" +#include "login-util.h" +#include "logind-acl.h" +#include "log.h" +#include "udev-builtin.h" + +static int builtin_uaccess(sd_device *dev, int argc, char *argv[], bool test) { + const char *path = NULL, *seat; + bool changed_acl = false; + uid_t uid; + int r; + + umask(0022); + + /* don't muck around with ACLs when the system is not running systemd */ + if (!logind_running()) + return 0; + + r = sd_device_get_devname(dev, &path); + if (r < 0) { + log_device_error_errno(dev, r, "Failed to get device name: %m"); + goto finish; + } + + if (sd_device_get_property_value(dev, "ID_SEAT", &seat) < 0) + seat = "seat0"; + + r = sd_seat_get_active(seat, NULL, &uid); + if (r < 0) { + if (IN_SET(r, -ENXIO, -ENODATA)) + /* No active session on this seat */ + r = 0; + else + log_device_error_errno(dev, r, "Failed to determine active user on seat %s: %m", seat); + + goto finish; + } + + r = devnode_acl(path, true, false, 0, true, uid); + if (r < 0) { + log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, "Failed to apply ACL: %m"); + goto finish; + } + + changed_acl = true; + r = 0; + +finish: + if (path && !changed_acl) { + int k; + + /* Better be safe than sorry and reset ACL */ + k = devnode_acl(path, true, false, 0, false, 0); + if (k < 0) { + log_device_full(dev, k == -ENOENT ? LOG_DEBUG : LOG_ERR, k, "Failed to apply ACL: %m"); + if (r >= 0) + r = k; + } + } + + return r; +} + +const UdevBuiltin udev_builtin_uaccess = { + .name = "uaccess", + .cmd = builtin_uaccess, + .help = "Manage device node user ACL", +}; diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c new file mode 100644 index 00000000..c12af28d --- /dev/null +++ b/src/udev/udev-builtin-usb_id.c @@ -0,0 +1,462 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * USB device properties and persistent device path + * + * Copyright (c) 2005 SUSE Linux Products GmbH, Germany + * Author: Hannes Reinecke + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "device-util.h" +#include "fd-util.h" +#include "libudev-util.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "udev-builtin.h" + +static void set_usb_iftype(char *to, int if_class_num, size_t len) { + const char *type = "generic"; + + switch (if_class_num) { + case 1: + type = "audio"; + break; + case 2: /* CDC-Control */ + break; + case 3: + type = "hid"; + break; + case 5: /* Physical */ + break; + case 6: + type = "media"; + break; + case 7: + type = "printer"; + break; + case 8: + type = "storage"; + break; + case 9: + type = "hub"; + break; + case 0x0a: /* CDC-Data */ + break; + case 0x0b: /* Chip/Smart Card */ + break; + case 0x0d: /* Content Security */ + break; + case 0x0e: + type = "video"; + break; + case 0xdc: /* Diagnostic Device */ + break; + case 0xe0: /* Wireless Controller */ + break; + case 0xfe: /* Application-specific */ + break; + case 0xff: /* Vendor-specific */ + break; + default: + break; + } + strncpy(to, type, len); + to[len-1] = '\0'; +} + +static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len) { + int type_num = 0; + char *eptr; + const char *type = "generic"; + + type_num = strtoul(from, &eptr, 0); + if (eptr != from) { + switch (type_num) { + case 1: /* RBC devices */ + type = "rbc"; + break; + case 2: + type = "atapi"; + break; + case 3: + type = "tape"; + break; + case 4: /* UFI */ + type = "floppy"; + break; + case 6: /* Transparent SPC-2 devices */ + type = "scsi"; + break; + default: + break; + } + } + strscpy(to, len, type); + return type_num; +} + +static void set_scsi_type(char *to, const char *from, size_t len) { + int type_num; + char *eptr; + const char *type = "generic"; + + type_num = strtoul(from, &eptr, 0); + if (eptr != from) { + switch (type_num) { + case 0: + case 0xe: + type = "disk"; + break; + case 1: + type = "tape"; + break; + case 4: + case 7: + case 0xf: + type = "optical"; + break; + case 5: + type = "cd"; + break; + default: + break; + } + } + strscpy(to, len, type); +} + +#define USB_DT_DEVICE 0x01 +#define USB_DT_INTERFACE 0x04 + +static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) { + _cleanup_close_ int fd = -1; + ssize_t size; + unsigned char buf[18 + 65535]; + size_t pos = 0; + unsigned strpos = 0; + const char *filename, *syspath; + int r; + struct usb_interface_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; + } _packed_; + + r = sd_device_get_syspath(dev, &syspath); + if (r < 0) + return r; + + filename = strjoina(syspath, "/descriptors"); + fd = open(filename, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return log_device_debug_errno(dev, errno, "Failed to open \"%s\": %m", filename); + + size = read(fd, buf, sizeof(buf)); + if (size < 18) + return log_device_warning_errno(dev, SYNTHETIC_ERRNO(EIO), + "Short read from \"%s\"", filename); + assert((size_t) size <= sizeof buf); + + ifs_str[0] = '\0'; + while (pos + sizeof(struct usb_interface_descriptor) < (size_t) size && + strpos + 7 < len - 2) { + + struct usb_interface_descriptor *desc; + char if_str[8]; + + desc = (struct usb_interface_descriptor *) (buf + pos); + if (desc->bLength < 3) + break; + if (desc->bLength > size - sizeof(struct usb_interface_descriptor)) + return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EIO), + "Corrupt data read from \"%s\"", filename); + pos += desc->bLength; + + if (desc->bDescriptorType != USB_DT_INTERFACE) + continue; + + if (snprintf(if_str, 8, ":%02x%02x%02x", + desc->bInterfaceClass, + desc->bInterfaceSubClass, + desc->bInterfaceProtocol) != 7) + continue; + + if (strstr(ifs_str, if_str)) + continue; + + memcpy(&ifs_str[strpos], if_str, 8), + strpos += 7; + } + + if (strpos > 0) { + ifs_str[strpos++] = ':'; + ifs_str[strpos++] = '\0'; + } + + return 0; +} + +/* + * A unique USB identification is generated like this: + * + * 1.) Get the USB device type from InterfaceClass and InterfaceSubClass + * 2.) If the device type is 'Mass-Storage/SPC-2' or 'Mass-Storage/RBC', + * use the SCSI vendor and model as USB-Vendor and USB-model. + * 3.) Otherwise, use the USB manufacturer and product as + * USB-Vendor and USB-model. Any non-printable characters + * in those strings will be skipped; a slash '/' will be converted + * into a full stop '.'. + * 4.) If that fails, too, we will use idVendor and idProduct + * as USB-Vendor and USB-model. + * 5.) The USB identification is the USB-vendor and USB-model + * string concatenated with an underscore '_'. + * 6.) If the device supplies a serial number, this number + * is concatenated with the identification with an underscore '_'. + */ +static int builtin_usb_id(sd_device *dev, int argc, char *argv[], bool test) { + char vendor_str[64] = ""; + char vendor_str_enc[256]; + const char *vendor_id; + char model_str[64] = ""; + char model_str_enc[256]; + const char *product_id; + char serial_str[UTIL_NAME_SIZE] = ""; + char packed_if_str[UTIL_NAME_SIZE] = ""; + char revision_str[64] = ""; + char type_str[64] = ""; + char instance_str[64] = ""; + const char *ifnum = NULL; + const char *driver = NULL; + char serial[256]; + + sd_device *dev_interface, *dev_usb; + const char *if_class, *if_subclass; + int if_class_num; + int protocol = 0; + size_t l; + char *s; + + const char *syspath, *sysname, *devtype, *interface_syspath; + int r; + + assert(dev); + + r = sd_device_get_syspath(dev, &syspath); + if (r < 0) + return r; + + r = sd_device_get_sysname(dev, &sysname); + if (r < 0) + return r; + + /* shortcut, if we are called directly for a "usb_device" type */ + if (sd_device_get_devtype(dev, &devtype) >= 0 && streq(devtype, "usb_device")) { + dev_if_packed_info(dev, packed_if_str, sizeof(packed_if_str)); + dev_usb = dev; + goto fallback; + } + + /* usb interface directory */ + r = sd_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface", &dev_interface); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to access usb_interface: %m"); + + r = sd_device_get_syspath(dev_interface, &interface_syspath); + if (r < 0) + return log_device_debug_errno(dev_interface, r, "Failed to get syspath: %m"); + (void) sd_device_get_sysattr_value(dev_interface, "bInterfaceNumber", &ifnum); + (void) sd_device_get_sysattr_value(dev_interface, "driver", &driver); + + r = sd_device_get_sysattr_value(dev_interface, "bInterfaceClass", &if_class); + if (r < 0) + return log_device_debug_errno(dev_interface, r, "Failed to get bInterfaceClass attribute: %m"); + + if_class_num = strtoul(if_class, NULL, 16); + if (if_class_num == 8) { + /* mass storage */ + if (sd_device_get_sysattr_value(dev_interface, "bInterfaceSubClass", &if_subclass) >= 0) + protocol = set_usb_mass_storage_ifsubtype(type_str, if_subclass, sizeof(type_str)-1); + } else + set_usb_iftype(type_str, if_class_num, sizeof(type_str)-1); + + log_device_debug(dev_interface, "if_class:%d protocol:%d", if_class_num, protocol); + + /* usb device directory */ + r = sd_device_get_parent_with_subsystem_devtype(dev_interface, "usb", "usb_device", &dev_usb); + if (r < 0) + return log_device_debug_errno(dev_interface, r, "Failed to find parent 'usb' device"); + + /* all interfaces of the device in a single string */ + dev_if_packed_info(dev_usb, packed_if_str, sizeof(packed_if_str)); + + /* mass storage : SCSI or ATAPI */ + if (IN_SET(protocol, 6, 2)) { + sd_device *dev_scsi; + const char *scsi_sysname, *scsi_model, *scsi_vendor, *scsi_type, *scsi_rev; + int host, bus, target, lun; + + /* get scsi device */ + r = sd_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device", &dev_scsi); + if (r < 0) { + log_device_debug_errno(dev, r, "Unable to find parent SCSI device"); + goto fallback; + } + if (sd_device_get_sysname(dev_scsi, &scsi_sysname) < 0) + goto fallback; + if (sscanf(scsi_sysname, "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) { + log_device_debug(dev_scsi, "Invalid SCSI device"); + goto fallback; + } + + /* Generic SPC-2 device */ + r = sd_device_get_sysattr_value(dev_scsi, "vendor", &scsi_vendor); + if (r < 0) { + log_device_debug_errno(dev_scsi, r, "Failed to get SCSI vendor attribute: %m"); + goto fallback; + } + udev_util_encode_string(scsi_vendor, vendor_str_enc, sizeof(vendor_str_enc)); + util_replace_whitespace(scsi_vendor, vendor_str, sizeof(vendor_str)-1); + util_replace_chars(vendor_str, NULL); + + r = sd_device_get_sysattr_value(dev_scsi, "model", &scsi_model); + if (r < 0) { + log_device_debug_errno(dev_scsi, r, "Failed to get SCSI model attribute: %m"); + goto fallback; + } + udev_util_encode_string(scsi_model, model_str_enc, sizeof(model_str_enc)); + util_replace_whitespace(scsi_model, model_str, sizeof(model_str)-1); + util_replace_chars(model_str, NULL); + + r = sd_device_get_sysattr_value(dev_scsi, "type", &scsi_type); + if (r < 0) { + log_device_debug_errno(dev_scsi, r, "Failed to get SCSI type attribute: %m"); + goto fallback; + } + set_scsi_type(type_str, scsi_type, sizeof(type_str)-1); + + r = sd_device_get_sysattr_value(dev_scsi, "rev", &scsi_rev); + if (r < 0) { + log_device_debug_errno(dev_scsi, r, "Failed to get SCSI revision attribute: %m"); + goto fallback; + } + util_replace_whitespace(scsi_rev, revision_str, sizeof(revision_str)-1); + util_replace_chars(revision_str, NULL); + + /* + * some broken devices have the same identifiers + * for all luns, export the target:lun number + */ + sprintf(instance_str, "%d:%d", target, lun); + } + +fallback: + r = sd_device_get_sysattr_value(dev_usb, "idVendor", &vendor_id); + if (r < 0) + return log_device_debug_errno(dev_usb, r, "Failed to get idVendor attribute: %m"); + + r = sd_device_get_sysattr_value(dev_usb, "idProduct", &product_id); + if (r < 0) + return log_device_debug_errno(dev_usb, r, "Failed to get idProduct attribute: %m"); + + /* fallback to USB vendor & device */ + if (vendor_str[0] == '\0') { + const char *usb_vendor; + + if (sd_device_get_sysattr_value(dev_usb, "manufacturer", &usb_vendor) < 0) + usb_vendor = vendor_id; + udev_util_encode_string(usb_vendor, vendor_str_enc, sizeof(vendor_str_enc)); + util_replace_whitespace(usb_vendor, vendor_str, sizeof(vendor_str)-1); + util_replace_chars(vendor_str, NULL); + } + + if (model_str[0] == '\0') { + const char *usb_model; + + if (sd_device_get_sysattr_value(dev_usb, "product", &usb_model) < 0) + usb_model = product_id; + udev_util_encode_string(usb_model, model_str_enc, sizeof(model_str_enc)); + util_replace_whitespace(usb_model, model_str, sizeof(model_str)-1); + util_replace_chars(model_str, NULL); + } + + if (revision_str[0] == '\0') { + const char *usb_rev; + + if (sd_device_get_sysattr_value(dev_usb, "bcdDevice", &usb_rev) >= 0) { + util_replace_whitespace(usb_rev, revision_str, sizeof(revision_str)-1); + util_replace_chars(revision_str, NULL); + } + } + + if (serial_str[0] == '\0') { + const char *usb_serial; + + if (sd_device_get_sysattr_value(dev_usb, "serial", &usb_serial) >= 0) { + const unsigned char *p; + + /* http://msdn.microsoft.com/en-us/library/windows/hardware/gg487321.aspx */ + for (p = (unsigned char *) usb_serial; *p != '\0'; p++) + if (*p < 0x20 || *p > 0x7f || *p == ',') { + usb_serial = NULL; + break; + } + + if (usb_serial) { + util_replace_whitespace(usb_serial, serial_str, sizeof(serial_str)-1); + util_replace_chars(serial_str, NULL); + } + } + } + + s = serial; + l = strpcpyl(&s, sizeof(serial), vendor_str, "_", model_str, NULL); + if (!isempty(serial_str)) + l = strpcpyl(&s, l, "_", serial_str, NULL); + + if (!isempty(instance_str)) + strpcpyl(&s, l, "-", instance_str, NULL); + + udev_builtin_add_property(dev, test, "ID_VENDOR", vendor_str); + udev_builtin_add_property(dev, test, "ID_VENDOR_ENC", vendor_str_enc); + udev_builtin_add_property(dev, test, "ID_VENDOR_ID", vendor_id); + udev_builtin_add_property(dev, test, "ID_MODEL", model_str); + udev_builtin_add_property(dev, test, "ID_MODEL_ENC", model_str_enc); + udev_builtin_add_property(dev, test, "ID_MODEL_ID", product_id); + udev_builtin_add_property(dev, test, "ID_REVISION", revision_str); + udev_builtin_add_property(dev, test, "ID_SERIAL", serial); + if (!isempty(serial_str)) + udev_builtin_add_property(dev, test, "ID_SERIAL_SHORT", serial_str); + if (!isempty(type_str)) + udev_builtin_add_property(dev, test, "ID_TYPE", type_str); + if (!isempty(instance_str)) + udev_builtin_add_property(dev, test, "ID_INSTANCE", instance_str); + udev_builtin_add_property(dev, test, "ID_BUS", "usb"); + if (!isempty(packed_if_str)) + udev_builtin_add_property(dev, test, "ID_USB_INTERFACES", packed_if_str); + if (ifnum) + udev_builtin_add_property(dev, test, "ID_USB_INTERFACE_NUM", ifnum); + if (driver) + udev_builtin_add_property(dev, test, "ID_USB_DRIVER", driver); + return 0; +} + +const UdevBuiltin udev_builtin_usb_id = { + .name = "usb_id", + .cmd = builtin_usb_id, + .help = "USB device properties", + .run_once = true, +}; diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c new file mode 100644 index 00000000..b41fbfc3 --- /dev/null +++ b/src/udev/udev-builtin.c @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "device-private.h" +#include "device-util.h" +#include "string-util.h" +#include "strv.h" +#include "udev-builtin.h" + +static bool initialized; + +static const UdevBuiltin *const builtins[_UDEV_BUILTIN_MAX] = { +#if HAVE_BLKID + [UDEV_BUILTIN_BLKID] = &udev_builtin_blkid, +#endif + [UDEV_BUILTIN_BTRFS] = &udev_builtin_btrfs, + [UDEV_BUILTIN_HWDB] = &udev_builtin_hwdb, + [UDEV_BUILTIN_INPUT_ID] = &udev_builtin_input_id, + [UDEV_BUILTIN_KEYBOARD] = &udev_builtin_keyboard, +#if HAVE_KMOD + [UDEV_BUILTIN_KMOD] = &udev_builtin_kmod, +#endif + [UDEV_BUILTIN_NET_ID] = &udev_builtin_net_id, + [UDEV_BUILTIN_NET_LINK] = &udev_builtin_net_setup_link, + [UDEV_BUILTIN_PATH_ID] = &udev_builtin_path_id, + [UDEV_BUILTIN_USB_ID] = &udev_builtin_usb_id, +#if HAVE_ACL + [UDEV_BUILTIN_UACCESS] = &udev_builtin_uaccess, +#endif +}; + +void udev_builtin_init(void) { + unsigned i; + + if (initialized) + return; + + for (i = 0; i < _UDEV_BUILTIN_MAX; i++) + if (builtins[i] && builtins[i]->init) + builtins[i]->init(); + + initialized = true; +} + +void udev_builtin_exit(void) { + unsigned i; + + if (!initialized) + return; + + for (i = 0; i < _UDEV_BUILTIN_MAX; i++) + if (builtins[i] && builtins[i]->exit) + builtins[i]->exit(); + + initialized = false; +} + +bool udev_builtin_validate(void) { + unsigned i; + + for (i = 0; i < _UDEV_BUILTIN_MAX; i++) + if (builtins[i] && builtins[i]->validate && builtins[i]->validate()) + return true; + return false; +} + +void udev_builtin_list(void) { + unsigned i; + + for (i = 0; i < _UDEV_BUILTIN_MAX; i++) + if (builtins[i]) + fprintf(stderr, " %-14s %s\n", builtins[i]->name, builtins[i]->help); +} + +const char *udev_builtin_name(UdevBuiltinCommand cmd) { + assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX); + + if (!builtins[cmd]) + return NULL; + + return builtins[cmd]->name; +} + +bool udev_builtin_run_once(UdevBuiltinCommand cmd) { + assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX); + + if (!builtins[cmd]) + return false; + + return builtins[cmd]->run_once; +} + +UdevBuiltinCommand udev_builtin_lookup(const char *command) { + UdevBuiltinCommand i; + size_t n; + + assert(command); + + command += strspn(command, WHITESPACE); + n = strcspn(command, WHITESPACE); + for (i = 0; i < _UDEV_BUILTIN_MAX; i++) + if (builtins[i] && strneq(builtins[i]->name, command, n)) + return i; + + return _UDEV_BUILTIN_INVALID; +} + +int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command, bool test) { + _cleanup_strv_free_ char **argv = NULL; + + assert(dev); + assert(cmd >= 0 && cmd < _UDEV_BUILTIN_MAX); + assert(command); + + if (!builtins[cmd]) + return -EOPNOTSUPP; + + argv = strv_split_full(command, NULL, SPLIT_QUOTES | SPLIT_RELAX); + if (!argv) + return -ENOMEM; + + /* we need '0' here to reset the internal state */ + optind = 0; + return builtins[cmd]->cmd(dev, strv_length(argv), argv, test); +} + +int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val) { + int r; + + assert(dev); + assert(key); + + r = device_add_property(dev, key, val); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to add property '%s%s%s'", + key, val ? "=" : "", strempty(val)); + + if (test) + printf("%s=%s\n", key, strempty(val)); + + return 0; +} diff --git a/src/udev/udev-builtin.h b/src/udev/udev-builtin.h new file mode 100644 index 00000000..99af5055 --- /dev/null +++ b/src/udev/udev-builtin.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +#include + +#include "sd-device.h" + +typedef enum { +#if HAVE_BLKID + UDEV_BUILTIN_BLKID, +#endif + UDEV_BUILTIN_BTRFS, + UDEV_BUILTIN_HWDB, + UDEV_BUILTIN_INPUT_ID, + UDEV_BUILTIN_KEYBOARD, +#if HAVE_KMOD + UDEV_BUILTIN_KMOD, +#endif + UDEV_BUILTIN_NET_ID, + UDEV_BUILTIN_NET_LINK, + UDEV_BUILTIN_PATH_ID, + UDEV_BUILTIN_USB_ID, +#if HAVE_ACL + UDEV_BUILTIN_UACCESS, +#endif + _UDEV_BUILTIN_MAX, + _UDEV_BUILTIN_INVALID = -1, +} UdevBuiltinCommand; + +typedef struct UdevBuiltin { + const char *name; + int (*cmd)(sd_device *dev, int argc, char *argv[], bool test); + const char *help; + int (*init)(void); + void (*exit)(void); + bool (*validate)(void); + bool run_once; +} UdevBuiltin; + +#define PTR_TO_UDEV_BUILTIN_CMD(p) ((UdevBuiltinCommand) ((intptr_t) (p)-1)) +#define UDEV_BUILTIN_CMD_TO_PTR(u) ((void *) ((intptr_t) (u)+1)) + +#if HAVE_BLKID +extern const UdevBuiltin udev_builtin_blkid; +#endif +extern const UdevBuiltin udev_builtin_btrfs; +extern const UdevBuiltin udev_builtin_hwdb; +extern const UdevBuiltin udev_builtin_input_id; +extern const UdevBuiltin udev_builtin_keyboard; +#if HAVE_KMOD +extern const UdevBuiltin udev_builtin_kmod; +#endif +extern const UdevBuiltin udev_builtin_net_id; +extern const UdevBuiltin udev_builtin_net_setup_link; +extern const UdevBuiltin udev_builtin_path_id; +extern const UdevBuiltin udev_builtin_usb_id; +#if HAVE_ACL +extern const UdevBuiltin udev_builtin_uaccess; +#endif + +void udev_builtin_init(void); +void udev_builtin_exit(void); +UdevBuiltinCommand udev_builtin_lookup(const char *command); +const char *udev_builtin_name(UdevBuiltinCommand cmd); +bool udev_builtin_run_once(UdevBuiltinCommand cmd); +int udev_builtin_run(sd_device *dev, UdevBuiltinCommand cmd, const char *command, bool test); +void udev_builtin_list(void); +bool udev_builtin_validate(void); +int udev_builtin_add_property(sd_device *dev, bool test, const char *key, const char *val); +int udev_builtin_hwdb_lookup(sd_device *dev, const char *prefix, const char *modalias, + const char *filter, bool test); diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c new file mode 100644 index 00000000..b8c0d83a --- /dev/null +++ b/src/udev/udev-ctrl.c @@ -0,0 +1,407 @@ +/* SPDX-License-Identifier: LGPL-2.1+ + * + * libudev - interface to udev device information + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sd-event.h" + +#include "alloc-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "io-util.h" +#include "socket-util.h" +#include "strxcpyx.h" +#include "udev-ctrl.h" +#include "util.h" + +/* wire protocol magic must match */ +#define UDEV_CTRL_MAGIC 0xdead1dea + +struct udev_ctrl_msg_wire { + char version[16]; + unsigned magic; + enum udev_ctrl_msg_type type; + union udev_ctrl_msg_value value; +}; + +struct udev_ctrl { + unsigned n_ref; + int sock; + int sock_connect; + union sockaddr_union saddr; + socklen_t addrlen; + bool bound:1; + bool cleanup_socket:1; + bool connected:1; + bool maybe_disconnected:1; + sd_event *event; + sd_event_source *event_source; + sd_event_source *event_source_connect; + udev_ctrl_handler_t callback; + void *userdata; +}; + +int udev_ctrl_new_from_fd(struct udev_ctrl **ret, int fd) { + _cleanup_close_ int sock = -1; + struct udev_ctrl *uctrl; + int r; + + assert(ret); + + if (fd < 0) { + sock = socket(AF_LOCAL, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); + if (sock < 0) + return log_error_errno(errno, "Failed to create socket: %m"); + } + + uctrl = new(struct udev_ctrl, 1); + if (!uctrl) + return -ENOMEM; + + *uctrl = (struct udev_ctrl) { + .n_ref = 1, + .sock = fd >= 0 ? fd : TAKE_FD(sock), + .sock_connect = -1, + .bound = fd >= 0, + }; + + /* + * FIXME: remove it as soon as we can depend on this: + * http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=90c6bd34f884cd9cee21f1d152baf6c18bcac949 + */ + r = setsockopt_int(uctrl->sock, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + log_warning_errno(r, "Failed to set SO_PASSCRED: %m"); + + uctrl->saddr.un = (struct sockaddr_un) { + .sun_family = AF_UNIX, + .sun_path = "/run/udev/control", + }; + + uctrl->addrlen = SOCKADDR_UN_LEN(uctrl->saddr.un); + + *ret = TAKE_PTR(uctrl); + return 0; +} + +int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) { + int r; + + assert(uctrl); + + if (uctrl->bound) + return 0; + + r = bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen); + if (r < 0 && errno == EADDRINUSE) { + (void) sockaddr_un_unlink(&uctrl->saddr.un); + r = bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen); + } + + if (r < 0) + return log_error_errno(errno, "Failed to bind udev control socket: %m"); + + if (listen(uctrl->sock, 0) < 0) + return log_error_errno(errno, "Failed to listen udev control socket: %m"); + + uctrl->bound = true; + uctrl->cleanup_socket = true; + + return 0; +} + +static void udev_ctrl_disconnect(struct udev_ctrl *uctrl) { + if (!uctrl) + return; + + uctrl->event_source_connect = sd_event_source_unref(uctrl->event_source_connect); + uctrl->sock_connect = safe_close(uctrl->sock_connect); +} + +static struct udev_ctrl *udev_ctrl_free(struct udev_ctrl *uctrl) { + assert(uctrl); + + udev_ctrl_disconnect(uctrl); + + sd_event_source_unref(uctrl->event_source); + safe_close(uctrl->sock); + + sd_event_unref(uctrl->event); + return mfree(uctrl); +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl, udev_ctrl, udev_ctrl_free); + +int udev_ctrl_cleanup(struct udev_ctrl *uctrl) { + if (!uctrl) + return 0; + if (uctrl->cleanup_socket) + sockaddr_un_unlink(&uctrl->saddr.un); + return 0; +} + +int udev_ctrl_attach_event(struct udev_ctrl *uctrl, sd_event *event) { + int r; + + assert_return(uctrl, -EINVAL); + assert_return(!uctrl->event, -EBUSY); + + if (event) + uctrl->event = sd_event_ref(event); + else { + r = sd_event_default(&uctrl->event); + if (r < 0) + return r; + } + + return 0; +} + +sd_event_source *udev_ctrl_get_event_source(struct udev_ctrl *uctrl) { + assert(uctrl); + + return uctrl->event_source; +} + +static void udev_ctrl_disconnect_and_listen_again(struct udev_ctrl *uctrl) { + udev_ctrl_disconnect(uctrl); + udev_ctrl_unref(uctrl); + (void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_ON); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl *, udev_ctrl_disconnect_and_listen_again); + +static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + _cleanup_(udev_ctrl_disconnect_and_listen_againp) struct udev_ctrl *uctrl = NULL; + struct udev_ctrl_msg_wire msg_wire; + struct iovec iov = IOVEC_MAKE(&msg_wire, sizeof(struct udev_ctrl_msg_wire)); + char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; + struct msghdr smsg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cred_msg, + .msg_controllen = sizeof(cred_msg), + }; + struct cmsghdr *cmsg; + struct ucred *cred; + ssize_t size; + + assert(userdata); + + /* When UDEV_CTRL_EXIT is received, manager unref udev_ctrl object. + * To avoid the object freed, let's increment the refcount. */ + uctrl = udev_ctrl_ref(userdata); + + size = next_datagram_size_fd(fd); + if (size < 0) + return log_error_errno(size, "Failed to get size of message: %m"); + if (size == 0) + return 0; /* Client disconnects? */ + + size = recvmsg(fd, &smsg, 0); + if (size < 0) { + if (errno != EINTR) + return log_error_errno(errno, "Failed to receive ctrl message: %m"); + + return 0; + } + + cmsg_close_all(&smsg); + + cmsg = CMSG_FIRSTHDR(&smsg); + + if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) { + log_error("No sender credentials received, ignoring message"); + return 0; + } + + cred = (struct ucred *) CMSG_DATA(cmsg); + + if (cred->uid != 0) { + log_error("Invalid sender uid "UID_FMT", ignoring message", cred->uid); + return 0; + } + + if (msg_wire.magic != UDEV_CTRL_MAGIC) { + log_error("Message magic 0x%08x doesn't match, ignoring message", msg_wire.magic); + return 0; + } + + if (msg_wire.type == _UDEV_CTRL_END_MESSAGES) + return 0; + + if (uctrl->callback) + (void) uctrl->callback(uctrl, msg_wire.type, &msg_wire.value, uctrl->userdata); + + /* Do not disconnect and wait for next message. */ + uctrl = udev_ctrl_unref(uctrl); + return 0; +} + +static int udev_ctrl_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + struct udev_ctrl *uctrl = userdata; + _cleanup_close_ int sock = -1; + struct ucred ucred; + int r; + + assert(uctrl); + + sock = accept4(fd, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK); + if (sock < 0) { + if (ERRNO_IS_ACCEPT_AGAIN(errno)) + return 0; + + return log_error_errno(errno, "Failed to accept ctrl connection: %m"); + } + + /* check peer credential of connection */ + r = getpeercred(sock, &ucred); + if (r < 0) { + log_error_errno(r, "Failed to receive credentials of ctrl connection: %m"); + return 0; + } + + if (ucred.uid > 0) { + log_error("Invalid sender uid "UID_FMT", closing connection", ucred.uid); + return 0; + } + + /* enable receiving of the sender credentials in the messages */ + r = setsockopt_int(sock, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + log_warning_errno(r, "Failed to set SO_PASSCRED, ignoring: %m"); + + r = sd_event_add_io(uctrl->event, &uctrl->event_source_connect, sock, EPOLLIN, udev_ctrl_connection_event_handler, uctrl); + if (r < 0) { + log_error_errno(r, "Failed to create event source for udev control connection: %m"); + return 0; + } + + (void) sd_event_source_set_description(uctrl->event_source_connect, "udev-ctrl-connection"); + + /* Do not accept multiple connection. */ + (void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_OFF); + + uctrl->sock_connect = TAKE_FD(sock); + return 0; +} + +int udev_ctrl_start(struct udev_ctrl *uctrl, udev_ctrl_handler_t callback, void *userdata) { + int r; + + assert(uctrl); + + if (!uctrl->event) { + r = udev_ctrl_attach_event(uctrl, NULL); + if (r < 0) + return r; + } + + r = udev_ctrl_enable_receiving(uctrl); + if (r < 0) + return r; + + uctrl->callback = callback; + uctrl->userdata = userdata; + + r = sd_event_add_io(uctrl->event, &uctrl->event_source, uctrl->sock, EPOLLIN, udev_ctrl_event_handler, uctrl); + if (r < 0) + return r; + + (void) sd_event_source_set_description(uctrl->event_source, "udev-ctrl"); + + return 0; +} + +int udev_ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf) { + struct udev_ctrl_msg_wire ctrl_msg_wire = { + .version = "udev-" STRINGIFY(PROJECT_VERSION), + .magic = UDEV_CTRL_MAGIC, + .type = type, + }; + + if (uctrl->maybe_disconnected) + return -ENOANO; /* to distinguish this from other errors. */ + + if (buf) + strscpy(ctrl_msg_wire.value.buf, sizeof(ctrl_msg_wire.value.buf), buf); + else + ctrl_msg_wire.value.intval = intval; + + if (!uctrl->connected) { + if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0) + return -errno; + uctrl->connected = true; + } + + if (send(uctrl->sock, &ctrl_msg_wire, sizeof(ctrl_msg_wire), 0) < 0) + return -errno; + + if (type == UDEV_CTRL_EXIT) + uctrl->maybe_disconnected = true; + + return 0; +} + +static int udev_ctrl_wait_io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + return sd_event_exit(sd_event_source_get_event(s), 0); +} + +int udev_ctrl_wait(struct udev_ctrl *uctrl, usec_t timeout) { + _cleanup_(sd_event_source_unrefp) sd_event_source *source_io = NULL, *source_timeout = NULL; + int r; + + assert(uctrl); + + if (uctrl->sock < 0) + return 0; + if (!uctrl->connected) + return 0; + + if (!uctrl->maybe_disconnected) { + r = udev_ctrl_send(uctrl, _UDEV_CTRL_END_MESSAGES, 0, NULL); + if (r < 0) + return r; + } + + if (timeout == 0) + return 0; + + if (!uctrl->event) { + r = udev_ctrl_attach_event(uctrl, NULL); + if (r < 0) + return r; + } + + r = sd_event_add_io(uctrl->event, &source_io, uctrl->sock, EPOLLIN, udev_ctrl_wait_io_handler, NULL); + if (r < 0) + return r; + + (void) sd_event_source_set_description(source_io, "udev-ctrl-wait-io"); + + if (timeout != USEC_INFINITY) { + r = sd_event_add_time(uctrl->event, &source_timeout, clock_boottime_or_monotonic(), + usec_add(now(clock_boottime_or_monotonic()), timeout), + 0, NULL, INT_TO_PTR(-ETIMEDOUT)); + if (r < 0) + return r; + + (void) sd_event_source_set_description(source_timeout, "udev-ctrl-wait-timeout"); + } + + return sd_event_loop(uctrl->event); +} diff --git a/src/udev/udev-ctrl.h b/src/udev/udev-ctrl.h new file mode 100644 index 00000000..2c84a8b1 --- /dev/null +++ b/src/udev/udev-ctrl.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +#include "sd-event.h" + +#include "macro.h" +#include "time-util.h" + +struct udev_ctrl; + +enum udev_ctrl_msg_type { + _UDEV_CTRL_END_MESSAGES, + UDEV_CTRL_SET_LOG_LEVEL, + UDEV_CTRL_STOP_EXEC_QUEUE, + UDEV_CTRL_START_EXEC_QUEUE, + UDEV_CTRL_RELOAD, + UDEV_CTRL_SET_ENV, + UDEV_CTRL_SET_CHILDREN_MAX, + UDEV_CTRL_PING, + UDEV_CTRL_EXIT, +}; + +union udev_ctrl_msg_value { + int intval; + char buf[256]; +}; + +typedef int (*udev_ctrl_handler_t)(struct udev_ctrl *udev_ctrl, enum udev_ctrl_msg_type type, + const union udev_ctrl_msg_value *value, void *userdata); + +int udev_ctrl_new_from_fd(struct udev_ctrl **ret, int fd); +static inline int udev_ctrl_new(struct udev_ctrl **ret) { + return udev_ctrl_new_from_fd(ret, -1); +} + +int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl); +struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl); +struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl); +int udev_ctrl_cleanup(struct udev_ctrl *uctrl); +int udev_ctrl_attach_event(struct udev_ctrl *uctrl, sd_event *event); +int udev_ctrl_start(struct udev_ctrl *uctrl, udev_ctrl_handler_t callback, void *userdata); +sd_event_source *udev_ctrl_get_event_source(struct udev_ctrl *uctrl); + +int udev_ctrl_wait(struct udev_ctrl *uctrl, usec_t timeout); + +int udev_ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf); +static inline int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority) { + return udev_ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, priority, NULL); +} + +static inline int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl) { + return udev_ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, 0, NULL); +} + +static inline int udev_ctrl_send_start_exec_queue(struct udev_ctrl *uctrl) { + return udev_ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, 0, NULL); +} + +static inline int udev_ctrl_send_reload(struct udev_ctrl *uctrl) { + return udev_ctrl_send(uctrl, UDEV_CTRL_RELOAD, 0, NULL); +} + +static inline int udev_ctrl_send_set_env(struct udev_ctrl *uctrl, const char *key) { + return udev_ctrl_send(uctrl, UDEV_CTRL_SET_ENV, 0, key); +} + +static inline int udev_ctrl_send_set_children_max(struct udev_ctrl *uctrl, int count) { + return udev_ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, count, NULL); +} + +static inline int udev_ctrl_send_ping(struct udev_ctrl *uctrl) { + return udev_ctrl_send(uctrl, UDEV_CTRL_PING, 0, NULL); +} + +static inline int udev_ctrl_send_exit(struct udev_ctrl *uctrl) { + return udev_ctrl_send(uctrl, UDEV_CTRL_EXIT, 0, NULL); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl*, udev_ctrl_unref); diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c new file mode 100644 index 00000000..58d48428 --- /dev/null +++ b/src/udev/udev-event.c @@ -0,0 +1,1023 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-event.h" + +#include "alloc-util.h" +#include "device-private.h" +#include "device-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "format-util.h" +#include "libudev-util.h" +#include "netlink-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "process-util.h" +#include "rlimit-util.h" +#include "signal-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "strxcpyx.h" +#include "udev-builtin.h" +#include "udev-event.h" +#include "udev-node.h" +#include "udev-util.h" +#include "udev-watch.h" +#include "user-util.h" + +typedef struct Spawn { + sd_device *device; + const char *cmd; + pid_t pid; + usec_t timeout_warn_usec; + usec_t timeout_usec; + usec_t event_birth_usec; + bool accept_failure; + int fd_stdout; + int fd_stderr; + char *result; + size_t result_size; + size_t result_len; +} Spawn; + +UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl) { + UdevEvent *event; + + assert(dev); + + event = new(UdevEvent, 1); + if (!event) + return NULL; + + *event = (UdevEvent) { + .dev = sd_device_ref(dev), + .birth_usec = now(CLOCK_MONOTONIC), + .exec_delay_usec = exec_delay_usec, + .rtnl = sd_netlink_ref(rtnl), + .uid = UID_INVALID, + .gid = GID_INVALID, + .mode = MODE_INVALID, + }; + + return event; +} + +UdevEvent *udev_event_free(UdevEvent *event) { + if (!event) + return NULL; + + sd_device_unref(event->dev); + sd_device_unref(event->dev_db_clone); + sd_netlink_unref(event->rtnl); + ordered_hashmap_free_free_key(event->run_list); + ordered_hashmap_free_free_free(event->seclabel_list); + free(event->program_result); + free(event->name); + + return mfree(event); +} + +typedef enum { + FORMAT_SUBST_DEVNODE, + FORMAT_SUBST_ATTR, + FORMAT_SUBST_ENV, + FORMAT_SUBST_KERNEL, + FORMAT_SUBST_KERNEL_NUMBER, + FORMAT_SUBST_DRIVER, + FORMAT_SUBST_DEVPATH, + FORMAT_SUBST_ID, + FORMAT_SUBST_MAJOR, + FORMAT_SUBST_MINOR, + FORMAT_SUBST_RESULT, + FORMAT_SUBST_PARENT, + FORMAT_SUBST_NAME, + FORMAT_SUBST_LINKS, + FORMAT_SUBST_ROOT, + FORMAT_SUBST_SYS, + _FORMAT_SUBST_TYPE_MAX, + _FORMAT_SUBST_TYPE_INVALID = -1 +} FormatSubstitutionType; + +struct subst_map_entry { + const char *name; + const char fmt; + FormatSubstitutionType type; +}; + +static const struct subst_map_entry map[] = { + { .name = "devnode", .fmt = 'N', .type = FORMAT_SUBST_DEVNODE }, + { .name = "tempnode", .fmt = 'N', .type = FORMAT_SUBST_DEVNODE }, /* deprecated */ + { .name = "attr", .fmt = 's', .type = FORMAT_SUBST_ATTR }, + { .name = "sysfs", .fmt = 's', .type = FORMAT_SUBST_ATTR }, /* deprecated */ + { .name = "env", .fmt = 'E', .type = FORMAT_SUBST_ENV }, + { .name = "kernel", .fmt = 'k', .type = FORMAT_SUBST_KERNEL }, + { .name = "number", .fmt = 'n', .type = FORMAT_SUBST_KERNEL_NUMBER }, + { .name = "driver", .fmt = 'd', .type = FORMAT_SUBST_DRIVER }, + { .name = "devpath", .fmt = 'p', .type = FORMAT_SUBST_DEVPATH }, + { .name = "id", .fmt = 'b', .type = FORMAT_SUBST_ID }, + { .name = "major", .fmt = 'M', .type = FORMAT_SUBST_MAJOR }, + { .name = "minor", .fmt = 'm', .type = FORMAT_SUBST_MINOR }, + { .name = "result", .fmt = 'c', .type = FORMAT_SUBST_RESULT }, + { .name = "parent", .fmt = 'P', .type = FORMAT_SUBST_PARENT }, + { .name = "name", .fmt = 'D', .type = FORMAT_SUBST_NAME }, + { .name = "links", .fmt = 'L', .type = FORMAT_SUBST_LINKS }, + { .name = "root", .fmt = 'r', .type = FORMAT_SUBST_ROOT }, + { .name = "sys", .fmt = 'S', .type = FORMAT_SUBST_SYS }, +}; + +static const char *format_type_to_string(FormatSubstitutionType t) { + for (size_t i = 0; i < ELEMENTSOF(map); i++) + if (map[i].type == t) + return map[i].name; + return NULL; +} + +static char format_type_to_char(FormatSubstitutionType t) { + for (size_t i = 0; i < ELEMENTSOF(map); i++) + if (map[i].type == t) + return map[i].fmt; + return '\0'; +} + +static int get_subst_type(const char **str, bool strict, FormatSubstitutionType *ret_type, char ret_attr[static UTIL_PATH_SIZE]) { + const char *p = *str, *q = NULL; + size_t i; + + assert(str); + assert(*str); + assert(ret_type); + assert(ret_attr); + + if (*p == '$') { + p++; + if (*p == '$') { + *str = p; + return 0; + } + for (i = 0; i < ELEMENTSOF(map); i++) + if ((q = startswith(p, map[i].name))) + break; + } else if (*p == '%') { + p++; + if (*p == '%') { + *str = p; + return 0; + } + + for (i = 0; i < ELEMENTSOF(map); i++) + if (*p == map[i].fmt) { + q = p + 1; + break; + } + } else + return 0; + if (!q) + /* When 'strict' flag is set, then '$' and '%' must be escaped. */ + return strict ? -EINVAL : 0; + + if (*q == '{') { + const char *start, *end; + size_t len; + + start = q + 1; + end = strchr(start, '}'); + if (!end) + return -EINVAL; + + len = end - start; + if (len == 0 || len >= UTIL_PATH_SIZE) + return -EINVAL; + + strnscpy(ret_attr, UTIL_PATH_SIZE, start, len); + q = end + 1; + } else + *ret_attr = '\0'; + + *str = q; + *ret_type = map[i].type; + return 1; +} + +static int safe_atou_optional_plus(const char *s, unsigned *ret) { + const char *p; + int r; + + assert(s); + assert(ret); + + /* Returns 1 if plus, 0 if no plus, negative on error */ + + p = endswith(s, "+"); + if (p) + s = strndupa(s, p - s); + + r = safe_atou(s, ret); + if (r < 0) + return r; + + return !!p; +} + +static ssize_t udev_event_subst_format( + UdevEvent *event, + FormatSubstitutionType type, + const char *attr, + char *dest, + size_t l) { + sd_device *parent, *dev = event->dev; + const char *val = NULL; + char *s = dest; + int r; + + switch (type) { + case FORMAT_SUBST_DEVPATH: + r = sd_device_get_devpath(dev, &val); + if (r < 0) + return r; + l = strpcpy(&s, l, val); + break; + case FORMAT_SUBST_KERNEL: + r = sd_device_get_sysname(dev, &val); + if (r < 0) + return r; + l = strpcpy(&s, l, val); + break; + case FORMAT_SUBST_KERNEL_NUMBER: + r = sd_device_get_sysnum(dev, &val); + if (r == -ENOENT) + goto null_terminate; + if (r < 0) + return r; + l = strpcpy(&s, l, val); + break; + case FORMAT_SUBST_ID: + if (!event->dev_parent) + goto null_terminate; + r = sd_device_get_sysname(event->dev_parent, &val); + if (r < 0) + return r; + l = strpcpy(&s, l, val); + break; + case FORMAT_SUBST_DRIVER: + if (!event->dev_parent) + goto null_terminate; + r = sd_device_get_driver(event->dev_parent, &val); + if (r == -ENOENT) + goto null_terminate; + if (r < 0) + return r; + l = strpcpy(&s, l, val); + break; + case FORMAT_SUBST_MAJOR: + case FORMAT_SUBST_MINOR: { + dev_t devnum; + + r = sd_device_get_devnum(dev, &devnum); + if (r < 0 && r != -ENOENT) + return r; + l = strpcpyf(&s, l, "%u", r < 0 ? 0 : type == FORMAT_SUBST_MAJOR ? major(devnum) : minor(devnum)); + break; + } + case FORMAT_SUBST_RESULT: { + unsigned index = 0; /* 0 means whole string */ + bool has_plus; + + if (!event->program_result) + goto null_terminate; + + if (!isempty(attr)) { + r = safe_atou_optional_plus(attr, &index); + if (r < 0) + return r; + + has_plus = r; + } + + if (index == 0) + l = strpcpy(&s, l, event->program_result); + else { + const char *start, *p; + unsigned i; + + p = skip_leading_chars(event->program_result, NULL); + + for (i = 1; i < index; i++) { + while (*p && !strchr(WHITESPACE, *p)) + p++; + p = skip_leading_chars(p, NULL); + if (*p == '\0') + break; + } + if (i != index) { + log_device_debug(dev, "requested part of result string not found"); + goto null_terminate; + } + + start = p; + /* %c{2+} copies the whole string from the second part on */ + if (has_plus) + l = strpcpy(&s, l, start); + else { + while (*p && !strchr(WHITESPACE, *p)) + p++; + l = strnpcpy(&s, l, start, p - start); + } + } + break; + } + case FORMAT_SUBST_ATTR: { + char vbuf[UTIL_NAME_SIZE]; + int count; + + if (isempty(attr)) + return -EINVAL; + + /* try to read the value specified by "[dmi/id]product_name" */ + if (util_resolve_subsys_kernel(attr, vbuf, sizeof(vbuf), true) == 0) + val = vbuf; + + /* try to read the attribute the device */ + if (!val) + (void) sd_device_get_sysattr_value(dev, attr, &val); + + /* try to read the attribute of the parent device, other matches have selected */ + if (!val && event->dev_parent && event->dev_parent != dev) + (void) sd_device_get_sysattr_value(event->dev_parent, attr, &val); + + if (!val) + goto null_terminate; + + /* strip trailing whitespace, and replace unwanted characters */ + if (val != vbuf) + strscpy(vbuf, sizeof(vbuf), val); + delete_trailing_chars(vbuf, NULL); + count = util_replace_chars(vbuf, UDEV_ALLOWED_CHARS_INPUT); + if (count > 0) + log_device_debug(dev, "%i character(s) replaced", count); + l = strpcpy(&s, l, vbuf); + break; + } + case FORMAT_SUBST_PARENT: + r = sd_device_get_parent(dev, &parent); + if (r == -ENODEV) + goto null_terminate; + if (r < 0) + return r; + r = sd_device_get_devname(parent, &val); + if (r == -ENOENT) + goto null_terminate; + if (r < 0) + return r; + l = strpcpy(&s, l, val + STRLEN("/dev/")); + break; + case FORMAT_SUBST_DEVNODE: + r = sd_device_get_devname(dev, &val); + if (r == -ENOENT) + goto null_terminate; + if (r < 0) + return r; + l = strpcpy(&s, l, val); + break; + case FORMAT_SUBST_NAME: + if (event->name) + l = strpcpy(&s, l, event->name); + else if (sd_device_get_devname(dev, &val) >= 0) + l = strpcpy(&s, l, val + STRLEN("/dev/")); + else { + r = sd_device_get_sysname(dev, &val); + if (r < 0) + return r; + l = strpcpy(&s, l, val); + } + break; + case FORMAT_SUBST_LINKS: + FOREACH_DEVICE_DEVLINK(dev, val) + if (s == dest) + l = strpcpy(&s, l, val + STRLEN("/dev/")); + else + l = strpcpyl(&s, l, " ", val + STRLEN("/dev/"), NULL); + if (s == dest) + goto null_terminate; + break; + case FORMAT_SUBST_ROOT: + l = strpcpy(&s, l, "/dev"); + break; + case FORMAT_SUBST_SYS: + l = strpcpy(&s, l, "/sys"); + break; + case FORMAT_SUBST_ENV: + if (isempty(attr)) + return -EINVAL; + r = sd_device_get_property_value(dev, attr, &val); + if (r == -ENOENT) + goto null_terminate; + if (r < 0) + return r; + l = strpcpy(&s, l, val); + break; + default: + assert_not_reached("Unknown format substitution type"); + } + + return s - dest; + +null_terminate: + *s = '\0'; + return 0; +} + +ssize_t udev_event_apply_format(UdevEvent *event, + const char *src, char *dest, size_t size, + bool replace_whitespace) { + const char *s = src; + int r; + + assert(event); + assert(event->dev); + assert(src); + assert(dest); + assert(size > 0); + + while (*s) { + FormatSubstitutionType type; + char attr[UTIL_PATH_SIZE]; + ssize_t subst_len; + + r = get_subst_type(&s, false, &type, attr); + if (r < 0) + return log_device_warning_errno(event->dev, r, "Invalid format string, ignoring: %s", src); + if (r == 0) { + if (size < 2) /* need space for this char and the terminating NUL */ + break; + *dest++ = *s++; + size--; + continue; + } + + subst_len = udev_event_subst_format(event, type, attr, dest, size); + if (subst_len < 0) + return log_device_warning_errno(event->dev, subst_len, + "Failed to substitute variable '$%s' or apply format '%%%c', ignoring: %m", + format_type_to_string(type), format_type_to_char(type)); + + /* FORMAT_SUBST_RESULT handles spaces itself */ + if (replace_whitespace && type != FORMAT_SUBST_RESULT) + /* util_replace_whitespace can replace in-place, + * and does nothing if subst_len == 0 */ + subst_len = util_replace_whitespace(dest, dest, subst_len); + + dest += subst_len; + size -= subst_len; + } + + assert(size >= 1); + *dest = '\0'; + return size; +} + +int udev_check_format(const char *value, size_t *offset, const char **hint) { + FormatSubstitutionType type; + const char *s = value; + char attr[UTIL_PATH_SIZE]; + int r; + + while (*s) { + r = get_subst_type(&s, true, &type, attr); + if (r < 0) { + if (offset) + *offset = s - value; + if (hint) + *hint = "invalid substitution type"; + return r; + } else if (r == 0) { + s++; + continue; + } + + if (IN_SET(type, FORMAT_SUBST_ATTR, FORMAT_SUBST_ENV) && isempty(attr)) { + if (offset) + *offset = s - value; + if (hint) + *hint = "attribute value missing"; + return -EINVAL; + } + + if (type == FORMAT_SUBST_RESULT && !isempty(attr)) { + unsigned i; + + r = safe_atou_optional_plus(attr, &i); + if (r < 0) { + if (offset) + *offset = s - value; + if (hint) + *hint = "attribute value not a valid number"; + return r; + } + } + } + + return 0; +} + +static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Spawn *spawn = userdata; + char buf[4096], *p; + size_t size; + ssize_t l; + + assert(spawn); + assert(fd == spawn->fd_stdout || fd == spawn->fd_stderr); + assert(!spawn->result || spawn->result_len < spawn->result_size); + + if (fd == spawn->fd_stdout && spawn->result) { + p = spawn->result + spawn->result_len; + size = spawn->result_size - spawn->result_len; + } else { + p = buf; + size = sizeof(buf); + } + + l = read(fd, p, size - 1); + if (l < 0) { + if (errno != EAGAIN) + log_device_error_errno(spawn->device, errno, + "Failed to read stdout of '%s': %m", spawn->cmd); + + return 0; + } + + p[l] = '\0'; + if (fd == spawn->fd_stdout && spawn->result) + spawn->result_len += l; + + /* Log output only if we watch stderr. */ + if (l > 0 && spawn->fd_stderr >= 0) { + _cleanup_strv_free_ char **v = NULL; + char **q; + + v = strv_split_newlines(p); + if (!v) + return 0; + + STRV_FOREACH(q, v) + log_device_debug(spawn->device, "'%s'(%s) '%s'", spawn->cmd, + fd == spawn->fd_stdout ? "out" : "err", *q); + } + + return 0; +} + +static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) { + Spawn *spawn = userdata; + char timeout[FORMAT_TIMESPAN_MAX]; + + assert(spawn); + + kill_and_sigcont(spawn->pid, SIGKILL); + + log_device_error(spawn->device, "Spawned process '%s' ["PID_FMT"] timed out after %s, killing", + spawn->cmd, spawn->pid, + format_timespan(timeout, sizeof(timeout), spawn->timeout_usec, USEC_PER_SEC)); + + return 1; +} + +static int on_spawn_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) { + Spawn *spawn = userdata; + char timeout[FORMAT_TIMESPAN_MAX]; + + assert(spawn); + + log_device_warning(spawn->device, "Spawned process '%s' ["PID_FMT"] is taking longer than %s to complete", + spawn->cmd, spawn->pid, + format_timespan(timeout, sizeof(timeout), spawn->timeout_warn_usec, USEC_PER_SEC)); + + return 1; +} + +static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) { + Spawn *spawn = userdata; + int ret = -EIO; + + assert(spawn); + + switch (si->si_code) { + case CLD_EXITED: + if (si->si_status == 0) + log_device_debug(spawn->device, "Process '%s' succeeded.", spawn->cmd); + else + log_device_full(spawn->device, spawn->accept_failure ? LOG_DEBUG : LOG_WARNING, 0, + "Process '%s' failed with exit code %i.", spawn->cmd, si->si_status); + ret = si->si_status; + break; + case CLD_KILLED: + case CLD_DUMPED: + log_device_error(spawn->device, "Process '%s' terminated by signal %s.", spawn->cmd, signal_to_string(si->si_status)); + break; + default: + log_device_error(spawn->device, "Process '%s' failed due to unknown reason.", spawn->cmd); + } + + sd_event_exit(sd_event_source_get_event(s), ret); + return 1; +} + +static int spawn_wait(Spawn *spawn) { + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + int r; + + assert(spawn); + + r = sd_event_new(&e); + if (r < 0) + return r; + + if (spawn->timeout_usec > 0) { + usec_t usec, age_usec; + + usec = now(CLOCK_MONOTONIC); + age_usec = usec - spawn->event_birth_usec; + if (age_usec < spawn->timeout_usec) { + if (spawn->timeout_warn_usec > 0 && + spawn->timeout_warn_usec < spawn->timeout_usec && + spawn->timeout_warn_usec > age_usec) { + spawn->timeout_warn_usec -= age_usec; + + r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC, + usec + spawn->timeout_warn_usec, USEC_PER_SEC, + on_spawn_timeout_warning, spawn); + if (r < 0) + return r; + } + + spawn->timeout_usec -= age_usec; + + r = sd_event_add_time(e, NULL, CLOCK_MONOTONIC, + usec + spawn->timeout_usec, USEC_PER_SEC, on_spawn_timeout, spawn); + if (r < 0) + return r; + } + } + + if (spawn->fd_stdout >= 0) { + r = sd_event_add_io(e, NULL, spawn->fd_stdout, EPOLLIN, on_spawn_io, spawn); + if (r < 0) + return r; + } + + if (spawn->fd_stderr >= 0) { + r = sd_event_add_io(e, NULL, spawn->fd_stderr, EPOLLIN, on_spawn_io, spawn); + if (r < 0) + return r; + } + + r = sd_event_add_child(e, NULL, spawn->pid, WEXITED, on_spawn_sigchld, spawn); + if (r < 0) + return r; + + return sd_event_loop(e); +} + +int udev_event_spawn(UdevEvent *event, + usec_t timeout_usec, + bool accept_failure, + const char *cmd, + char *result, size_t ressize) { + _cleanup_close_pair_ int outpipe[2] = {-1, -1}, errpipe[2] = {-1, -1}; + _cleanup_strv_free_ char **argv = NULL; + char **envp = NULL; + Spawn spawn; + pid_t pid; + int r; + + assert(event); + assert(event->dev); + assert(result || ressize == 0); + + /* pipes from child to parent */ + if (result || log_get_max_level() >= LOG_INFO) + if (pipe2(outpipe, O_NONBLOCK|O_CLOEXEC) != 0) + return log_device_error_errno(event->dev, errno, + "Failed to create pipe for command '%s': %m", cmd); + + if (log_get_max_level() >= LOG_INFO) + if (pipe2(errpipe, O_NONBLOCK|O_CLOEXEC) != 0) + return log_device_error_errno(event->dev, errno, + "Failed to create pipe for command '%s': %m", cmd); + + argv = strv_split_full(cmd, NULL, SPLIT_QUOTES|SPLIT_RELAX); + if (!argv) + return log_oom(); + + if (isempty(argv[0])) + return log_device_error_errno(event->dev, SYNTHETIC_ERRNO(EINVAL), + "Invalid command '%s'", cmd); + + /* allow programs in /usr/lib/udev/ to be called without the path */ + if (!path_is_absolute(argv[0])) { + char *program; + + program = path_join(UDEVLIBEXECDIR, argv[0]); + if (!program) + return log_oom(); + + free_and_replace(argv[0], program); + } + + r = device_get_properties_strv(event->dev, &envp); + if (r < 0) + return log_device_error_errno(event->dev, r, "Failed to get device properties"); + + log_device_debug(event->dev, "Starting '%s'", cmd); + + r = safe_fork("(spawn)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid); + if (r < 0) + return log_device_error_errno(event->dev, r, + "Failed to fork() to execute command '%s': %m", cmd); + if (r == 0) { + if (rearrange_stdio(-1, outpipe[WRITE_END], errpipe[WRITE_END]) < 0) + _exit(EXIT_FAILURE); + + (void) close_all_fds(NULL, 0); + (void) rlimit_nofile_safe(); + + execve(argv[0], argv, envp); + _exit(EXIT_FAILURE); + } + + /* parent closed child's ends of pipes */ + outpipe[WRITE_END] = safe_close(outpipe[WRITE_END]); + errpipe[WRITE_END] = safe_close(errpipe[WRITE_END]); + + spawn = (Spawn) { + .device = event->dev, + .cmd = cmd, + .pid = pid, + .accept_failure = accept_failure, + .timeout_warn_usec = udev_warn_timeout(timeout_usec), + .timeout_usec = timeout_usec, + .event_birth_usec = event->birth_usec, + .fd_stdout = outpipe[READ_END], + .fd_stderr = errpipe[READ_END], + .result = result, + .result_size = ressize, + }; + r = spawn_wait(&spawn); + if (r < 0) + return log_device_error_errno(event->dev, r, + "Failed to wait for spawned command '%s': %m", cmd); + + if (result) + result[spawn.result_len] = '\0'; + + return r; /* 0 for success, and positive if the program failed */ +} + +static int rename_netif(UdevEvent *event) { + sd_device *dev = event->dev; + const char *oldname; + int ifindex, r; + + if (!event->name) + return 0; /* No new name is requested. */ + + r = sd_device_get_sysname(dev, &oldname); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get sysname: %m"); + + if (streq(event->name, oldname)) + return 0; /* The interface name is already requested name. */ + + if (!device_for_action(dev, DEVICE_ACTION_ADD)) + return 0; /* Rename the interface only when it is added. */ + + r = sd_device_get_ifindex(dev, &ifindex); + if (r == -ENOENT) + return 0; /* Device is not a network interface. */ + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get ifindex: %m"); + + r = rtnl_set_link_name(&event->rtnl, ifindex, event->name); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m", + ifindex, oldname, event->name); + + /* Set ID_RENAMING boolean property here, and drop it in the corresponding move uevent later. */ + r = device_add_property(dev, "ID_RENAMING", "1"); + if (r < 0) + return log_device_warning_errno(dev, r, "Failed to add 'ID_RENAMING' property: %m"); + + r = device_rename(dev, event->name); + if (r < 0) + return log_device_warning_errno(dev, r, "Failed to update properties with new name '%s': %m", event->name); + + log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, event->name); + + return 1; +} + +static int update_devnode(UdevEvent *event) { + sd_device *dev = event->dev; + int r; + + r = sd_device_get_devnum(dev, NULL); + if (r == -ENOENT) + return 0; + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get devnum: %m"); + + /* remove/update possible left-over symlinks from old database entry */ + if (event->dev_db_clone) + (void) udev_node_update_old_links(dev, event->dev_db_clone); + + if (!uid_is_valid(event->uid)) { + r = device_get_devnode_uid(dev, &event->uid); + if (r < 0 && r != -ENOENT) + return log_device_error_errno(dev, r, "Failed to get devnode UID: %m"); + } + + if (!gid_is_valid(event->gid)) { + r = device_get_devnode_gid(dev, &event->gid); + if (r < 0 && r != -ENOENT) + return log_device_error_errno(dev, r, "Failed to get devnode GID: %m"); + } + + if (event->mode == MODE_INVALID) { + r = device_get_devnode_mode(dev, &event->mode); + if (r < 0 && r != -ENOENT) + return log_device_error_errno(dev, r, "Failed to get devnode mode: %m"); + } + if (event->mode == MODE_INVALID && gid_is_valid(event->gid) && event->gid > 0) + /* If group is set, but mode is not set, "upgrade" mode for the group. */ + event->mode = 0660; + + bool apply_mac = device_for_action(dev, DEVICE_ACTION_ADD); + + return udev_node_add(dev, apply_mac, event->mode, event->uid, event->gid, event->seclabel_list); +} + +static void event_execute_rules_on_remove( + UdevEvent *event, + usec_t timeout_usec, + Hashmap *properties_list, + UdevRules *rules) { + + sd_device *dev = event->dev; + int r; + + r = device_read_db_internal(dev, true); + if (r < 0) + log_device_debug_errno(dev, r, "Failed to read database under /run/udev/data/: %m"); + + r = device_tag_index(dev, NULL, false); + if (r < 0) + log_device_debug_errno(dev, r, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m"); + + r = device_delete_db(dev); + if (r < 0) + log_device_debug_errno(dev, r, "Failed to delete database under /run/udev/data/, ignoring: %m"); + + if (sd_device_get_devnum(dev, NULL) >= 0) + (void) udev_watch_end(dev); + + (void) udev_rules_apply_to_event(rules, event, timeout_usec, properties_list); + + if (sd_device_get_devnum(dev, NULL) >= 0) + (void) udev_node_remove(dev); +} + +static int udev_event_on_move(UdevEvent *event) { + sd_device *dev = event->dev; + int r; + + if (event->dev_db_clone && + sd_device_get_devnum(dev, NULL) < 0) { + r = device_copy_properties(dev, event->dev_db_clone); + if (r < 0) + log_device_debug_errno(dev, r, "Failed to copy properties from cloned sd_device object, ignoring: %m"); + } + + /* Drop previously added property */ + r = device_add_property(dev, "ID_RENAMING", NULL); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to remove 'ID_RENAMING' property: %m"); + + return 0; +} + +int udev_event_execute_rules(UdevEvent *event, + usec_t timeout_usec, + Hashmap *properties_list, + UdevRules *rules) { + const char *subsystem; + DeviceAction action; + sd_device *dev; + int r; + + assert(event); + assert(rules); + + dev = event->dev; + + r = sd_device_get_subsystem(dev, &subsystem); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get subsystem: %m"); + + r = device_get_action(dev, &action); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get ACTION: %m"); + + if (action == DEVICE_ACTION_REMOVE) { + event_execute_rules_on_remove(event, timeout_usec, properties_list, rules); + return 0; + } + + r = device_clone_with_db(dev, &event->dev_db_clone); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to clone sd_device object: %m"); + + if (event->dev_db_clone && sd_device_get_devnum(dev, NULL) >= 0) + /* Disable watch during event processing. */ + (void) udev_watch_end(event->dev_db_clone); + + if (action == DEVICE_ACTION_MOVE) { + r = udev_event_on_move(event); + if (r < 0) + return r; + } + + r = udev_rules_apply_to_event(rules, event, timeout_usec, properties_list); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to apply udev rules: %m"); + + r = rename_netif(event); + if (r < 0) + return r; + + r = update_devnode(event); + if (r < 0) + return r; + + /* preserve old, or get new initialization timestamp */ + r = device_ensure_usec_initialized(dev, event->dev_db_clone); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to set initialization timestamp: %m"); + + /* (re)write database file */ + r = device_tag_index(dev, event->dev_db_clone, true); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/: %m"); + + r = device_update_db(dev); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m"); + + device_set_is_initialized(dev); + + event->dev_db_clone = sd_device_unref(event->dev_db_clone); + + return 0; +} + +void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec) { + const char *command; + void *val; + Iterator i; + int r; + + ORDERED_HASHMAP_FOREACH_KEY(val, command, event->run_list, i) { + UdevBuiltinCommand builtin_cmd = PTR_TO_UDEV_BUILTIN_CMD(val); + + if (builtin_cmd != _UDEV_BUILTIN_INVALID) { + log_device_debug(event->dev, "Running built-in command \"%s\"", command); + r = udev_builtin_run(event->dev, builtin_cmd, command, false); + if (r < 0) + log_device_debug_errno(event->dev, r, "Failed to run built-in command \"%s\", ignoring: %m", command); + } else { + if (event->exec_delay_usec > 0) { + char buf[FORMAT_TIMESPAN_MAX]; + + log_device_debug(event->dev, "Delaying execution of \"%s\" for %s.", + command, format_timespan(buf, sizeof(buf), event->exec_delay_usec, USEC_PER_SEC)); + (void) usleep(event->exec_delay_usec); + } + + log_device_debug(event->dev, "Running command \"%s\"", command); + r = udev_event_spawn(event, timeout_usec, false, command, NULL, 0); + if (r < 0) + log_device_warning_errno(event->dev, r, "Failed to execute '%s', ignoring: %m", command); + else if (r > 0) /* returned value is positive when program fails */ + log_device_debug(event->dev, "Command \"%s\" returned %d (error), ignoring.", command, r); + } + } +} diff --git a/src/udev/udev-event.h b/src/udev/udev-event.h new file mode 100644 index 00000000..a05e1252 --- /dev/null +++ b/src/udev/udev-event.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +/* + * Copyright © 2003 Greg Kroah-Hartman + */ + +#include "sd-device.h" +#include "sd-netlink.h" + +#include "hashmap.h" +#include "macro.h" +#include "udev-rules.h" +#include "udev-util.h" +#include "util.h" + +#define READ_END 0 +#define WRITE_END 1 + +typedef struct UdevEvent { + sd_device *dev; + sd_device *dev_parent; + sd_device *dev_db_clone; + char *name; + char *program_result; + mode_t mode; + uid_t uid; + gid_t gid; + OrderedHashmap *seclabel_list; + OrderedHashmap *run_list; + usec_t exec_delay_usec; + usec_t birth_usec; + sd_netlink *rtnl; + unsigned builtin_run; + unsigned builtin_ret; + UdevRuleEscapeType esc:8; + bool inotify_watch:1; + bool inotify_watch_final:1; + bool group_final:1; + bool owner_final:1; + bool mode_final:1; + bool name_final:1; + bool devlink_final:1; + bool run_final:1; +} UdevEvent; + +UdevEvent *udev_event_new(sd_device *dev, usec_t exec_delay_usec, sd_netlink *rtnl); +UdevEvent *udev_event_free(UdevEvent *event); +DEFINE_TRIVIAL_CLEANUP_FUNC(UdevEvent*, udev_event_free); + +ssize_t udev_event_apply_format(UdevEvent *event, + const char *src, char *dest, size_t size, + bool replace_whitespace); +int udev_check_format(const char *value, size_t *offset, const char **hint); +int udev_event_spawn(UdevEvent *event, + usec_t timeout_usec, + bool accept_failure, + const char *cmd, char *result, size_t ressize); +int udev_event_execute_rules(UdevEvent *event, + usec_t timeout_usec, + Hashmap *properties_list, + UdevRules *rules); +void udev_event_execute_run(UdevEvent *event, usec_t timeout_usec); + +static inline usec_t udev_warn_timeout(usec_t timeout_usec) { + return DIV_ROUND_UP(timeout_usec, 3); +} diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c new file mode 100644 index 00000000..a34b8d69 --- /dev/null +++ b/src/udev/udev-node.c @@ -0,0 +1,468 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "device-nodes.h" +#include "device-private.h" +#include "device-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "fs-util.h" +#include "libudev-util.h" +#include "mkdir.h" +#include "path-util.h" +#include "selinux-util.h" +#include "smack-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "udev-node.h" +#include "user-util.h" + +static int node_symlink(sd_device *dev, const char *node, const char *slink) { + _cleanup_free_ char *slink_dirname = NULL, *target = NULL; + const char *id_filename, *slink_tmp; + struct stat stats; + int r; + + assert(dev); + assert(node); + assert(slink); + + slink_dirname = dirname_malloc(slink); + if (!slink_dirname) + return log_oom(); + + /* use relative link */ + r = path_make_relative(slink_dirname, node, &target); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get relative path from '%s' to '%s': %m", slink, node); + + /* preserve link with correct target, do not replace node of other device */ + if (lstat(slink, &stats) == 0) { + if (S_ISBLK(stats.st_mode) || S_ISCHR(stats.st_mode)) { + log_device_error(dev, "Conflicting device node '%s' found, link to '%s' will not be created.", slink, node); + return -EOPNOTSUPP; + } else if (S_ISLNK(stats.st_mode)) { + _cleanup_free_ char *buf = NULL; + + if (readlink_malloc(slink, &buf) >= 0 && + streq(target, buf)) { + log_device_debug(dev, "Preserve already existing symlink '%s' to '%s'", slink, target); + (void) label_fix(slink, LABEL_IGNORE_ENOENT); + (void) utimensat(AT_FDCWD, slink, NULL, AT_SYMLINK_NOFOLLOW); + return 0; + } + } + } else { + log_device_debug(dev, "Creating symlink '%s' to '%s'", slink, target); + do { + r = mkdir_parents_label(slink, 0755); + if (!IN_SET(r, 0, -ENOENT)) + break; + mac_selinux_create_file_prepare(slink, S_IFLNK); + if (symlink(target, slink) < 0) + r = -errno; + mac_selinux_create_file_clear(); + } while (r == -ENOENT); + if (r == 0) + return 0; + if (r < 0) + log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s', trying to replace '%s': %m", slink, target, slink); + } + + log_device_debug(dev, "Atomically replace '%s'", slink); + r = device_get_id_filename(dev, &id_filename); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get id_filename: %m"); + slink_tmp = strjoina(slink, ".tmp-", id_filename); + (void) unlink(slink_tmp); + do { + r = mkdir_parents_label(slink_tmp, 0755); + if (!IN_SET(r, 0, -ENOENT)) + break; + mac_selinux_create_file_prepare(slink_tmp, S_IFLNK); + if (symlink(target, slink_tmp) < 0) + r = -errno; + mac_selinux_create_file_clear(); + } while (r == -ENOENT); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to create symlink '%s' to '%s': %m", slink_tmp, target); + + if (rename(slink_tmp, slink) < 0) { + r = log_device_error_errno(dev, errno, "Failed to rename '%s' to '%s': %m", slink_tmp, slink); + (void) unlink(slink_tmp); + } + + return r; +} + +/* find device node of device with highest priority */ +static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir, char **ret) { + _cleanup_closedir_ DIR *dir = NULL; + _cleanup_free_ char *target = NULL; + struct dirent *dent; + int r, priority = 0; + + assert(!add || dev); + assert(stackdir); + assert(ret); + + if (add) { + const char *devnode; + + r = device_get_devlink_priority(dev, &priority); + if (r < 0) + return r; + + r = sd_device_get_devname(dev, &devnode); + if (r < 0) + return r; + + target = strdup(devnode); + if (!target) + return -ENOMEM; + } + + dir = opendir(stackdir); + if (!dir) { + if (target) { + *ret = TAKE_PTR(target); + return 0; + } + + return -errno; + } + + FOREACH_DIRENT_ALL(dent, dir, break) { + _cleanup_(sd_device_unrefp) sd_device *dev_db = NULL; + const char *devnode, *id_filename; + int db_prio = 0; + + if (dent->d_name[0] == '\0') + break; + if (dent->d_name[0] == '.') + continue; + + log_device_debug(dev, "Found '%s' claiming '%s'", dent->d_name, stackdir); + + if (device_get_id_filename(dev, &id_filename) < 0) + continue; + + /* did we find ourself? */ + if (streq(dent->d_name, id_filename)) + continue; + + if (sd_device_new_from_device_id(&dev_db, dent->d_name) < 0) + continue; + + if (sd_device_get_devname(dev_db, &devnode) < 0) + continue; + + if (device_get_devlink_priority(dev_db, &db_prio) < 0) + continue; + + if (target && db_prio <= priority) + continue; + + log_device_debug(dev_db, "Device claims priority %i for '%s'", db_prio, stackdir); + + r = free_and_strdup(&target, devnode); + if (r < 0) + return r; + priority = db_prio; + } + + if (!target) + return -ENOENT; + + *ret = TAKE_PTR(target); + return 0; +} + +/* manage "stack of names" with possibly specified device priorities */ +static int link_update(sd_device *dev, const char *slink, bool add) { + _cleanup_free_ char *target = NULL, *filename = NULL, *dirname = NULL; + char name_enc[PATH_MAX]; + const char *id_filename; + int r; + + assert(dev); + assert(slink); + + r = device_get_id_filename(dev, &id_filename); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get id_filename: %m"); + + util_path_encode(slink + STRLEN("/dev"), name_enc, sizeof(name_enc)); + dirname = path_join("/run/udev/links/", name_enc); + if (!dirname) + return log_oom(); + filename = path_join(dirname, id_filename); + if (!filename) + return log_oom(); + + if (!add && unlink(filename) == 0) + (void) rmdir(dirname); + + r = link_find_prioritized(dev, add, dirname, &target); + if (r < 0) { + log_device_debug(dev, "No reference left, removing '%s'", slink); + if (unlink(slink) == 0) + (void) rmdir_parents(slink, "/"); + } else + (void) node_symlink(dev, target, slink); + + if (add) + do { + _cleanup_close_ int fd = -1; + + r = mkdir_parents(filename, 0755); + if (!IN_SET(r, 0, -ENOENT)) + break; + fd = open(filename, O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC|O_NOFOLLOW, 0444); + if (fd < 0) + r = -errno; + } while (r == -ENOENT); + + return r; +} + +int udev_node_update_old_links(sd_device *dev, sd_device *dev_old) { + const char *name, *devpath; + int r; + + assert(dev); + assert(dev_old); + + r = sd_device_get_devpath(dev, &devpath); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get devpath: %m"); + + /* update possible left-over symlinks */ + FOREACH_DEVICE_DEVLINK(dev_old, name) { + const char *name_current; + bool found = false; + + /* check if old link name still belongs to this device */ + FOREACH_DEVICE_DEVLINK(dev, name_current) + if (streq(name, name_current)) { + found = true; + break; + } + + if (found) + continue; + + log_device_debug(dev, "Updating old name, '%s' no longer belonging to '%s'", + name, devpath); + link_update(dev, name, false); + } + + return 0; +} + +static int node_permissions_apply(sd_device *dev, bool apply_mac, + mode_t mode, uid_t uid, gid_t gid, + OrderedHashmap *seclabel_list) { + const char *devnode, *subsystem, *id_filename = NULL; + struct stat stats; + dev_t devnum; + bool apply_mode, apply_uid, apply_gid; + int r; + + assert(dev); + + r = sd_device_get_devname(dev, &devnode); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get devname: %m"); + r = sd_device_get_subsystem(dev, &subsystem); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get subsystem: %m"); + r = sd_device_get_devnum(dev, &devnum); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get devnum: %m"); + (void) device_get_id_filename(dev, &id_filename); + + if (streq(subsystem, "block")) + mode |= S_IFBLK; + else + mode |= S_IFCHR; + + if (lstat(devnode, &stats) < 0) { + if (errno == ENOENT) + return 0; /* this is necessarily racey, so ignore missing the device */ + return log_device_debug_errno(dev, errno, "cannot stat() node %s: %m", devnode); + } + + if ((mode != MODE_INVALID && (stats.st_mode & S_IFMT) != (mode & S_IFMT)) || stats.st_rdev != devnum) + return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST), + "Found node '%s' with non-matching devnum %s, skip handling", + devnode, id_filename); + + apply_mode = mode != MODE_INVALID && (stats.st_mode & 0777) != (mode & 0777); + apply_uid = uid_is_valid(uid) && stats.st_uid != uid; + apply_gid = gid_is_valid(gid) && stats.st_gid != gid; + + if (apply_mode || apply_uid || apply_gid || apply_mac) { + bool selinux = false, smack = false; + const char *name, *label; + Iterator i; + + if (apply_mode || apply_uid || apply_gid) { + log_device_debug(dev, "Setting permissions %s, uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o", + devnode, + uid_is_valid(uid) ? uid : stats.st_uid, + gid_is_valid(gid) ? gid : stats.st_gid, + mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); + + r = chmod_and_chown(devnode, mode, uid, gid); + if (r < 0) + log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, + "Failed to set owner/mode of %s to uid=" UID_FMT + ", gid=" GID_FMT ", mode=%#o: %m", + devnode, + uid_is_valid(uid) ? uid : stats.st_uid, + gid_is_valid(gid) ? gid : stats.st_gid, + mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); + } else + log_device_debug(dev, "Preserve permissions of %s, uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o", + devnode, + uid_is_valid(uid) ? uid : stats.st_uid, + gid_is_valid(gid) ? gid : stats.st_gid, + mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); + + /* apply SECLABEL{$module}=$label */ + ORDERED_HASHMAP_FOREACH_KEY(label, name, seclabel_list, i) { + int q; + + if (streq(name, "selinux")) { + selinux = true; + + q = mac_selinux_apply(devnode, label); + if (q < 0) + log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, + "SECLABEL: failed to set SELinux label '%s': %m", label); + else + log_device_debug(dev, "SECLABEL: set SELinux label '%s'", label); + + } else if (streq(name, "smack")) { + smack = true; + + q = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label); + if (q < 0) + log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, + "SECLABEL: failed to set SMACK label '%s': %m", label); + else + log_device_debug(dev, "SECLABEL: set SMACK label '%s'", label); + + } else + log_device_error(dev, "SECLABEL: unknown subsystem, ignoring '%s'='%s'", name, label); + } + + /* set the defaults */ + if (!selinux) + (void) mac_selinux_fix(devnode, LABEL_IGNORE_ENOENT); + if (!smack) + (void) mac_smack_apply(devnode, SMACK_ATTR_ACCESS, NULL); + } + + /* always update timestamp when we re-use the node, like on media change events */ + (void) utimensat(AT_FDCWD, devnode, NULL, 0); + + return r; +} + +static int xsprintf_dev_num_path_from_sd_device(sd_device *dev, char **ret) { + char filename[DEV_NUM_PATH_MAX], *s; + const char *subsystem; + dev_t devnum; + int r; + + assert(ret); + + r = sd_device_get_subsystem(dev, &subsystem); + if (r < 0) + return r; + + r = sd_device_get_devnum(dev, &devnum); + if (r < 0) + return r; + + xsprintf_dev_num_path(filename, + streq(subsystem, "block") ? "block" : "char", + devnum); + + s = strdup(filename); + if (!s) + return -ENOMEM; + + *ret = s; + return 0; +} + +int udev_node_add(sd_device *dev, bool apply, + mode_t mode, uid_t uid, gid_t gid, + OrderedHashmap *seclabel_list) { + const char *devnode, *devlink; + _cleanup_free_ char *filename = NULL; + int r; + + assert(dev); + + r = sd_device_get_devname(dev, &devnode); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get devnode: %m"); + + if (DEBUG_LOGGING) { + const char *id_filename = NULL; + + (void) device_get_id_filename(dev, &id_filename); + log_device_debug(dev, "Handling device node '%s', devnum=%s", devnode, strnull(id_filename)); + } + + r = node_permissions_apply(dev, apply, mode, uid, gid, seclabel_list); + if (r < 0) + return r; + + r = xsprintf_dev_num_path_from_sd_device(dev, &filename); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get device path: %m"); + + /* always add /dev/{block,char}/$major:$minor */ + (void) node_symlink(dev, devnode, filename); + + /* create/update symlinks, add symlinks to name index */ + FOREACH_DEVICE_DEVLINK(dev, devlink) + (void) link_update(dev, devlink, true); + + return 0; +} + +int udev_node_remove(sd_device *dev) { + _cleanup_free_ char *filename = NULL; + const char *devlink; + int r; + + assert(dev); + + /* remove/update symlinks, remove symlinks from name index */ + FOREACH_DEVICE_DEVLINK(dev, devlink) + (void) link_update(dev, devlink, false); + + r = xsprintf_dev_num_path_from_sd_device(dev, &filename); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get device path: %m"); + + /* remove /dev/{block,char}/$major:$minor */ + (void) unlink(filename); + + return 0; +} diff --git a/src/udev/udev-node.h b/src/udev/udev-node.h new file mode 100644 index 00000000..5ae816d6 --- /dev/null +++ b/src/udev/udev-node.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +#include +#include + +#include "sd-device.h" + +#include "hashmap.h" + +int udev_node_add(sd_device *dev, bool apply, + mode_t mode, uid_t uid, gid_t gid, + OrderedHashmap *seclabel_list); +int udev_node_remove(sd_device *dev); +int udev_node_update_old_links(sd_device *dev, sd_device *dev_old); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c new file mode 100644 index 00000000..b9b350d1 --- /dev/null +++ b/src/udev/udev-rules.c @@ -0,0 +1,2393 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include + +#include "alloc-util.h" +#include "architecture.h" +#include "conf-files.h" +#include "def.h" +#include "device-util.h" +#include "dirent-util.h" +#include "escape.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "glob-util.h" +#include "libudev-util.h" +#include "list.h" +#include "mkdir.h" +#include "nulstr-util.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "stat-util.h" +#include "strv.h" +#include "strxcpyx.h" +#include "sysctl-util.h" +#include "udev-builtin.h" +#include "udev-event.h" +#include "udev-rules.h" +#include "user-util.h" +#include "virt.h" + +#define RULES_DIRS (const char* const*) CONF_PATHS_STRV("udev/rules.d") + +typedef enum { + OP_MATCH, /* == */ + OP_NOMATCH, /* != */ + OP_ADD, /* += */ + OP_REMOVE, /* -= */ + OP_ASSIGN, /* = */ + OP_ASSIGN_FINAL, /* := */ + _OP_TYPE_MAX, + _OP_TYPE_INVALID = -1 +} UdevRuleOperatorType; + +typedef enum { + MATCH_TYPE_EMPTY, /* empty string */ + MATCH_TYPE_PLAIN, /* no special characters */ + MATCH_TYPE_PLAIN_WITH_EMPTY, /* no special characters with empty string, e.g., "|foo" */ + MATCH_TYPE_GLOB, /* shell globs ?,*,[] */ + MATCH_TYPE_GLOB_WITH_EMPTY, /* shell globs ?,*,[] with empty string, e.g., "|foo*" */ + MATCH_TYPE_SUBSYSTEM, /* "subsystem", "bus", or "class" */ + _MATCH_TYPE_MAX, + _MATCH_TYPE_INVALID = -1 +} UdevRuleMatchType; + +typedef enum { + SUBST_TYPE_PLAIN, /* no substitution */ + SUBST_TYPE_FORMAT, /* % or $ */ + SUBST_TYPE_SUBSYS, /* "[/]" format */ + _SUBST_TYPE_MAX, + _SUBST_TYPE_INVALID = -1 +} UdevRuleSubstituteType; + +typedef enum { + /* lvalues which take match or nomatch operator */ + TK_M_ACTION, /* string, device_get_action() */ + TK_M_DEVPATH, /* path, sd_device_get_devpath() */ + TK_M_KERNEL, /* string, sd_device_get_sysname() */ + TK_M_DEVLINK, /* strv, sd_device_get_devlink_first(), sd_device_get_devlink_next() */ + TK_M_NAME, /* string, name of network interface */ + TK_M_ENV, /* string, device property, takes key through attribute */ + TK_M_CONST, /* string, system-specific hard-coded constant */ + TK_M_TAG, /* strv, sd_device_get_tag_first(), sd_device_get_tag_next() */ + TK_M_SUBSYSTEM, /* string, sd_device_get_subsystem() */ + TK_M_DRIVER, /* string, sd_device_get_driver() */ + TK_M_ATTR, /* string, takes filename through attribute, sd_device_get_sysattr_value(), util_resolve_subsys_kernel(), etc. */ + TK_M_SYSCTL, /* string, takes kernel parameter through attribute */ + + /* matches parent paramters */ + TK_M_PARENTS_KERNEL, /* string */ + TK_M_PARENTS_SUBSYSTEM, /* string */ + TK_M_PARENTS_DRIVER, /* string */ + TK_M_PARENTS_ATTR, /* string */ + TK_M_PARENTS_TAG, /* strv */ + + TK_M_TEST, /* path, optionally mode_t can be specified by attribute, test the existence of a file */ + TK_M_PROGRAM, /* string, execute a program */ + TK_M_IMPORT_FILE, /* path */ + TK_M_IMPORT_PROGRAM, /* string, import properties from the result of program */ + TK_M_IMPORT_BUILTIN, /* string, import properties from the result of built-in command */ + TK_M_IMPORT_DB, /* string, import properties from database */ + TK_M_IMPORT_CMDLINE, /* string, kernel command line */ + TK_M_IMPORT_PARENT, /* string, parent property */ + TK_M_RESULT, /* string, result of TK_M_PROGRAM */ + +#define _TK_M_MAX (TK_M_RESULT + 1) +#define _TK_A_MIN _TK_M_MAX + + /* lvalues which take one of assign operators */ + TK_A_OPTIONS_STRING_ESCAPE_NONE, /* no argument */ + TK_A_OPTIONS_STRING_ESCAPE_REPLACE, /* no argument */ + TK_A_OPTIONS_DB_PERSIST, /* no argument */ + TK_A_OPTIONS_INOTIFY_WATCH, /* boolean */ + TK_A_OPTIONS_DEVLINK_PRIORITY, /* int */ + TK_A_OWNER, /* user name */ + TK_A_GROUP, /* group name */ + TK_A_MODE, /* mode string */ + TK_A_OWNER_ID, /* uid_t */ + TK_A_GROUP_ID, /* gid_t */ + TK_A_MODE_ID, /* mode_t */ + TK_A_TAG, /* string */ + TK_A_OPTIONS_STATIC_NODE, /* device path, /dev/... */ + TK_A_SECLABEL, /* string with attribute */ + TK_A_ENV, /* string with attribute */ + TK_A_NAME, /* ifname */ + TK_A_DEVLINK, /* string */ + TK_A_ATTR, /* string with attribute */ + TK_A_SYSCTL, /* string with attribute */ + TK_A_RUN_BUILTIN, /* string */ + TK_A_RUN_PROGRAM, /* string */ + + _TK_TYPE_MAX, + _TK_TYPE_INVALID = -1, +} UdevRuleTokenType; + +typedef enum { + LINE_HAS_NAME = 1 << 0, /* has NAME= */ + LINE_HAS_DEVLINK = 1 << 1, /* has SYMLINK=, OWNER=, GROUP= or MODE= */ + LINE_HAS_STATIC_NODE = 1 << 2, /* has OPTIONS=static_node */ + LINE_HAS_GOTO = 1 << 3, /* has GOTO= */ + LINE_HAS_LABEL = 1 << 4, /* has LABEL= */ + LINE_UPDATE_SOMETHING = 1 << 5, /* has other TK_A_* or TK_M_IMPORT tokens */ +} UdevRuleLineType; + +typedef struct UdevRuleFile UdevRuleFile; +typedef struct UdevRuleLine UdevRuleLine; +typedef struct UdevRuleToken UdevRuleToken; + +struct UdevRuleToken { + UdevRuleTokenType type:8; + UdevRuleOperatorType op:8; + UdevRuleMatchType match_type:8; + UdevRuleSubstituteType attr_subst_type:7; + bool attr_match_remove_trailing_whitespace:1; + const char *value; + void *data; + LIST_FIELDS(UdevRuleToken, tokens); +}; + +struct UdevRuleLine { + char *line; + unsigned line_number; + UdevRuleLineType type; + + const char *label; + const char *goto_label; + UdevRuleLine *goto_line; + + UdevRuleFile *rule_file; + UdevRuleToken *current_token; + LIST_HEAD(UdevRuleToken, tokens); + LIST_FIELDS(UdevRuleLine, rule_lines); +}; + +struct UdevRuleFile { + char *filename; + UdevRuleLine *current_line; + LIST_HEAD(UdevRuleLine, rule_lines); + LIST_FIELDS(UdevRuleFile, rule_files); +}; + +struct UdevRules { + usec_t dirs_ts_usec; + ResolveNameTiming resolve_name_timing; + Hashmap *known_users; + Hashmap *known_groups; + UdevRuleFile *current_file; + LIST_HEAD(UdevRuleFile, rule_files); +}; + +/*** Logging helpers ***/ + +#define log_rule_full(device, rules, level, error, fmt, ...) \ + ({ \ + UdevRules *_r = (rules); \ + UdevRuleFile *_f = _r ? _r->current_file : NULL; \ + UdevRuleLine *_l = _f ? _f->current_line : NULL; \ + const char *_n = _f ? _f->filename : NULL; \ + \ + log_device_full(device, level, error, "%s:%u " fmt, \ + strna(_n), _l ? _l->line_number : 0, \ + ##__VA_ARGS__); \ + }) + +#define log_rule_debug(device, rules, ...) log_rule_full(device, rules, LOG_DEBUG, 0, ##__VA_ARGS__) +#define log_rule_info(device, rules, ...) log_rule_full(device, rules, LOG_INFO, 0, ##__VA_ARGS__) +#define log_rule_notice(device, rules, ...) log_rule_full(device, rules, LOG_NOTICE, 0, ##__VA_ARGS__) +#define log_rule_warning(device, rules, ...) log_rule_full(device, rules, LOG_WARNING, 0, ##__VA_ARGS__) +#define log_rule_error(device, rules, ...) log_rule_full(device, rules, LOG_ERR, 0, ##__VA_ARGS__) + +#define log_rule_debug_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_DEBUG, error, ##__VA_ARGS__) +#define log_rule_info_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_INFO, error, ##__VA_ARGS__) +#define log_rule_notice_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_NOTICE, error, ##__VA_ARGS__) +#define log_rule_warning_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_WARNING, error, ##__VA_ARGS__) +#define log_rule_error_errno(device, rules, error, ...) log_rule_full(device, rules, LOG_ERR, error, ##__VA_ARGS__) + +#define log_token_full(rules, ...) log_rule_full(NULL, rules, ##__VA_ARGS__) + +#define log_token_debug(rules, ...) log_token_full(rules, LOG_DEBUG, 0, ##__VA_ARGS__) +#define log_token_info(rules, ...) log_token_full(rules, LOG_INFO, 0, ##__VA_ARGS__) +#define log_token_notice(rules, ...) log_token_full(rules, LOG_NOTICE, 0, ##__VA_ARGS__) +#define log_token_warning(rules, ...) log_token_full(rules, LOG_WARNING, 0, ##__VA_ARGS__) +#define log_token_error(rules, ...) log_token_full(rules, LOG_ERR, 0, ##__VA_ARGS__) + +#define log_token_debug_errno(rules, error, ...) log_token_full(rules, LOG_DEBUG, error, ##__VA_ARGS__) +#define log_token_info_errno(rules, error, ...) log_token_full(rules, LOG_INFO, error, ##__VA_ARGS__) +#define log_token_notice_errno(rules, error, ...) log_token_full(rules, LOG_NOTICE, error, ##__VA_ARGS__) +#define log_token_warning_errno(rules, error, ...) log_token_full(rules, LOG_WARNING, error, ##__VA_ARGS__) +#define log_token_error_errno(rules, error, ...) log_token_full(rules, LOG_ERR, error, ##__VA_ARGS__) + +#define _log_token_invalid(rules, key, type) \ + log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), \ + "Invalid %s for %s.", type, key) + +#define log_token_invalid_op(rules, key) _log_token_invalid(rules, key, "operator") +#define log_token_invalid_attr(rules, key) _log_token_invalid(rules, key, "attribute") + +#define log_token_invalid_attr_format(rules, key, attr, offset, hint) \ + log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), \ + "Invalid attribute \"%s\" for %s (char %zu: %s), ignoring, but please fix it.", \ + attr, key, offset, hint) +#define log_token_invalid_value(rules, key, value, offset, hint) \ + log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), \ + "Invalid value \"%s\" for %s (char %zu: %s), ignoring, but please fix it.", \ + value, key, offset, hint) + +static void log_unknown_owner(sd_device *dev, UdevRules *rules, int error, const char *entity, const char *name) { + if (IN_SET(abs(error), ENOENT, ESRCH)) + log_rule_error(dev, rules, "Unknown %s '%s', ignoring", entity, name); + else + log_rule_error_errno(dev, rules, error, "Failed to resolve %s '%s', ignoring: %m", entity, name); +} + +/*** Other functions ***/ + +static void udev_rule_token_free(UdevRuleToken *token) { + free(token); +} + +static void udev_rule_line_clear_tokens(UdevRuleLine *rule_line) { + UdevRuleToken *i, *next; + + assert(rule_line); + + LIST_FOREACH_SAFE(tokens, i, next, rule_line->tokens) + udev_rule_token_free(i); + + rule_line->tokens = NULL; +} + +static void udev_rule_line_free(UdevRuleLine *rule_line) { + if (!rule_line) + return; + + udev_rule_line_clear_tokens(rule_line); + + if (rule_line->rule_file) { + if (rule_line->rule_file->current_line == rule_line) + rule_line->rule_file->current_line = rule_line->rule_lines_prev; + + LIST_REMOVE(rule_lines, rule_line->rule_file->rule_lines, rule_line); + } + + free(rule_line->line); + free(rule_line); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(UdevRuleLine*, udev_rule_line_free); + +static void udev_rule_file_free(UdevRuleFile *rule_file) { + UdevRuleLine *i, *next; + + if (!rule_file) + return; + + LIST_FOREACH_SAFE(rule_lines, i, next, rule_file->rule_lines) + udev_rule_line_free(i); + + free(rule_file->filename); + free(rule_file); +} + +UdevRules *udev_rules_free(UdevRules *rules) { + UdevRuleFile *i, *next; + + if (!rules) + return NULL; + + LIST_FOREACH_SAFE(rule_files, i, next, rules->rule_files) + udev_rule_file_free(i); + + hashmap_free_free_key(rules->known_users); + hashmap_free_free_key(rules->known_groups); + return mfree(rules); +} + +static int rule_resolve_user(UdevRules *rules, const char *name, uid_t *ret) { + _cleanup_free_ char *n = NULL; + uid_t uid; + void *val; + int r; + + assert(rules); + assert(name); + + val = hashmap_get(rules->known_users, name); + if (val) { + *ret = PTR_TO_UID(val); + return 0; + } + + r = get_user_creds(&name, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); + if (r < 0) { + log_unknown_owner(NULL, rules, r, "user", name); + *ret = UID_INVALID; + return 0; + } + + n = strdup(name); + if (!n) + return -ENOMEM; + + r = hashmap_ensure_allocated(&rules->known_users, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(rules->known_users, n, UID_TO_PTR(uid)); + if (r < 0) + return r; + + TAKE_PTR(n); + *ret = uid; + return 0; +} + +static int rule_resolve_group(UdevRules *rules, const char *name, gid_t *ret) { + _cleanup_free_ char *n = NULL; + gid_t gid; + void *val; + int r; + + assert(rules); + assert(name); + + val = hashmap_get(rules->known_groups, name); + if (val) { + *ret = PTR_TO_GID(val); + return 0; + } + + r = get_group_creds(&name, &gid, USER_CREDS_ALLOW_MISSING); + if (r < 0) { + log_unknown_owner(NULL, rules, r, "group", name); + *ret = GID_INVALID; + return 0; + } + + n = strdup(name); + if (!n) + return -ENOMEM; + + r = hashmap_ensure_allocated(&rules->known_groups, &string_hash_ops); + if (r < 0) + return r; + + r = hashmap_put(rules->known_groups, n, GID_TO_PTR(gid)); + if (r < 0) + return r; + + TAKE_PTR(n); + *ret = gid; + return 0; +} + +static UdevRuleSubstituteType rule_get_substitution_type(const char *str) { + assert(str); + + if (str[0] == '[') + return SUBST_TYPE_SUBSYS; + if (strchr(str, '%') || strchr(str, '$')) + return SUBST_TYPE_FORMAT; + return SUBST_TYPE_PLAIN; +} + +static void rule_line_append_token(UdevRuleLine *rule_line, UdevRuleToken *token) { + assert(rule_line); + assert(token); + + if (rule_line->current_token) + LIST_APPEND(tokens, rule_line->current_token, token); + else + LIST_APPEND(tokens, rule_line->tokens, token); + + rule_line->current_token = token; +} + +static int rule_line_add_token(UdevRuleLine *rule_line, UdevRuleTokenType type, UdevRuleOperatorType op, char *value, void *data) { + UdevRuleToken *token; + UdevRuleMatchType match_type = _MATCH_TYPE_INVALID; + UdevRuleSubstituteType subst_type = _SUBST_TYPE_INVALID; + bool remove_trailing_whitespace = false; + size_t len; + + assert(rule_line); + assert(type >= 0 && type < _TK_TYPE_MAX); + assert(op >= 0 && op < _OP_TYPE_MAX); + + if (type < _TK_M_MAX) { + assert(value); + assert(IN_SET(op, OP_MATCH, OP_NOMATCH)); + + if (type == TK_M_SUBSYSTEM && STR_IN_SET(value, "subsystem", "bus", "class")) + match_type = MATCH_TYPE_SUBSYSTEM; + else if (isempty(value)) + match_type = MATCH_TYPE_EMPTY; + else if (streq(value, "?*")) { + /* Convert KEY=="?*" -> KEY!="" */ + match_type = MATCH_TYPE_EMPTY; + op = op == OP_MATCH ? OP_NOMATCH : OP_MATCH; + } else if (string_is_glob(value)) + match_type = MATCH_TYPE_GLOB; + else + match_type = MATCH_TYPE_PLAIN; + + if (type < TK_M_TEST || type == TK_M_RESULT) { + /* Convert value string to nulstr. */ + bool bar = true, empty = false; + char *a, *b; + + for (a = b = value; *a != '\0'; a++) { + if (*a != '|') { + *b++ = *a; + bar = false; + } else { + if (bar) + empty = true; + else + *b++ = '\0'; + bar = true; + } + } + *b = '\0'; + if (bar) + empty = true; + + if (empty) { + if (match_type == MATCH_TYPE_GLOB) + match_type = MATCH_TYPE_GLOB_WITH_EMPTY; + if (match_type == MATCH_TYPE_PLAIN) + match_type = MATCH_TYPE_PLAIN_WITH_EMPTY; + } + } + } + + if (IN_SET(type, TK_M_ATTR, TK_M_PARENTS_ATTR)) { + assert(value); + assert(data); + + len = strlen(value); + if (len > 0 && !isspace(value[len - 1])) + remove_trailing_whitespace = true; + + subst_type = rule_get_substitution_type((const char*) data); + } + + token = new(UdevRuleToken, 1); + if (!token) + return -ENOMEM; + + *token = (UdevRuleToken) { + .type = type, + .op = op, + .value = value, + .data = data, + .match_type = match_type, + .attr_subst_type = subst_type, + .attr_match_remove_trailing_whitespace = remove_trailing_whitespace, + }; + + rule_line_append_token(rule_line, token); + + if (token->type == TK_A_NAME) + SET_FLAG(rule_line->type, LINE_HAS_NAME, true); + + else if (IN_SET(token->type, TK_A_DEVLINK, + TK_A_OWNER, TK_A_GROUP, TK_A_MODE, + TK_A_OWNER_ID, TK_A_GROUP_ID, TK_A_MODE_ID)) + SET_FLAG(rule_line->type, LINE_HAS_DEVLINK, true); + + else if (token->type == TK_A_OPTIONS_STATIC_NODE) + SET_FLAG(rule_line->type, LINE_HAS_STATIC_NODE, true); + + else if (token->type >= _TK_A_MIN || + IN_SET(token->type, TK_M_PROGRAM, + TK_M_IMPORT_FILE, TK_M_IMPORT_PROGRAM, TK_M_IMPORT_BUILTIN, + TK_M_IMPORT_DB, TK_M_IMPORT_CMDLINE, TK_M_IMPORT_PARENT)) + SET_FLAG(rule_line->type, LINE_UPDATE_SOMETHING, true); + + return 0; +} + +static void check_value_format_and_warn(UdevRules *rules, const char *key, const char *value, bool nonempty) { + size_t offset; + const char *hint; + + if (nonempty && isempty(value)) + log_token_invalid_value(rules, key, value, (size_t) 0, "empty value"); + else if (udev_check_format(value, &offset, &hint) < 0) + log_token_invalid_value(rules, key, value, offset + 1, hint); +} + +static int check_attr_format_and_warn(UdevRules *rules, const char *key, const char *value) { + size_t offset; + const char *hint; + + if (isempty(value)) + return log_token_invalid_attr(rules, key); + if (udev_check_format(value, &offset, &hint) < 0) + log_token_invalid_attr_format(rules, key, value, offset + 1, hint); + return 0; +} + +static int parse_token(UdevRules *rules, const char *key, char *attr, UdevRuleOperatorType op, char *value) { + bool is_match = IN_SET(op, OP_MATCH, OP_NOMATCH); + UdevRuleLine *rule_line; + int r; + + assert(rules); + assert(rules->current_file); + assert(rules->current_file->current_line); + assert(key); + assert(value); + + rule_line = rules->current_file->current_line; + + if (streq(key, "ACTION")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + + r = rule_line_add_token(rule_line, TK_M_ACTION, op, value, NULL); + } else if (streq(key, "DEVPATH")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + + r = rule_line_add_token(rule_line, TK_M_DEVPATH, op, value, NULL); + } else if (streq(key, "KERNEL")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + + r = rule_line_add_token(rule_line, TK_M_KERNEL, op, value, NULL); + } else if (streq(key, "SYMLINK")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (op == OP_REMOVE) + return log_token_invalid_op(rules, key); + + if (!is_match) { + check_value_format_and_warn(rules, key, value, false); + r = rule_line_add_token(rule_line, TK_A_DEVLINK, op, value, NULL); + } else + r = rule_line_add_token(rule_line, TK_M_DEVLINK, op, value, NULL); + } else if (streq(key, "NAME")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (op == OP_ADD) { + log_token_warning(rules, "%s key takes '==', '!=', '=', or ':=' operator, assuming '=', but please fix it.", key); + op = OP_ASSIGN; + } + + if (!is_match) { + if (streq(value, "%k")) + return log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), + "Ignoring NAME=\"%%k\" is ignored, as it breaks kernel supplied names."); + if (isempty(value)) + return log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), + "Ignoring NAME=\"\", as udev will not delete any device nodes."); + check_value_format_and_warn(rules, key, value, false); + + r = rule_line_add_token(rule_line, TK_A_NAME, op, value, NULL); + } else + r = rule_line_add_token(rule_line, TK_M_NAME, op, value, NULL); + } else if (streq(key, "ENV")) { + if (isempty(attr)) + return log_token_invalid_attr(rules, key); + if (op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (op == OP_ASSIGN_FINAL) { + log_token_warning(rules, "%s key takes '==', '!=', '=', or '+=' operator, assuming '=', but please fix it.", key); + op = OP_ASSIGN; + } + + if (!is_match) { + if (STR_IN_SET(attr, + "ACTION", "DEVLINKS", "DEVNAME", "DEVPATH", "DEVTYPE", "DRIVER", + "IFINDEX", "MAJOR", "MINOR", "SEQNUM", "SUBSYSTEM", "TAGS")) + return log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), + "Invalid ENV attribute. '%s' cannot be set.", attr); + + check_value_format_and_warn(rules, key, value, false); + + r = rule_line_add_token(rule_line, TK_A_ENV, op, value, attr); + } else + r = rule_line_add_token(rule_line, TK_M_ENV, op, value, attr); + } else if (streq(key, "CONST")) { + if (isempty(attr) || !STR_IN_SET(attr, "arch", "virt")) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + r = rule_line_add_token(rule_line, TK_M_CONST, op, value, attr); + } else if (streq(key, "TAG")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (op == OP_ASSIGN_FINAL) { + log_token_warning(rules, "%s key takes '==', '!=', '=', or '+=' operator, assuming '=', but please fix it.", key); + op = OP_ASSIGN; + } + + if (!is_match) { + check_value_format_and_warn(rules, key, value, true); + + r = rule_line_add_token(rule_line, TK_A_TAG, op, value, NULL); + } else + r = rule_line_add_token(rule_line, TK_M_TAG, op, value, NULL); + } else if (streq(key, "SUBSYSTEM")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + + if (STR_IN_SET(value, "bus", "class")) + log_token_warning(rules, "'%s' must be specified as 'subsystem'; please fix it", value); + + r = rule_line_add_token(rule_line, TK_M_SUBSYSTEM, op, value, NULL); + } else if (streq(key, "DRIVER")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + + r = rule_line_add_token(rule_line, TK_M_DRIVER, op, value, NULL); + } else if (streq(key, "ATTR")) { + r = check_attr_format_and_warn(rules, key, attr); + if (r < 0) + return r; + if (op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (IN_SET(op, OP_ADD, OP_ASSIGN_FINAL)) { + log_token_warning(rules, "%s key takes '==', '!=', or '=' operator, assuming '=', but please fix it.", key); + op = OP_ASSIGN; + } + + if (!is_match) { + check_value_format_and_warn(rules, key, value, false); + r = rule_line_add_token(rule_line, TK_A_ATTR, op, value, attr); + } else + r = rule_line_add_token(rule_line, TK_M_ATTR, op, value, attr); + } else if (streq(key, "SYSCTL")) { + r = check_attr_format_and_warn(rules, key, attr); + if (r < 0) + return r; + if (op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (IN_SET(op, OP_ADD, OP_ASSIGN_FINAL)) { + log_token_warning(rules, "%s key takes '==', '!=', or '=' operator, assuming '=', but please fix it.", key); + op = OP_ASSIGN; + } + + if (!is_match) { + check_value_format_and_warn(rules, key, value, false); + r = rule_line_add_token(rule_line, TK_A_SYSCTL, op, value, attr); + } else + r = rule_line_add_token(rule_line, TK_M_SYSCTL, op, value, attr); + } else if (streq(key, "KERNELS")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + + r = rule_line_add_token(rule_line, TK_M_PARENTS_KERNEL, op, value, NULL); + } else if (streq(key, "SUBSYSTEMS")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + + r = rule_line_add_token(rule_line, TK_M_PARENTS_SUBSYSTEM, op, value, NULL); + } else if (streq(key, "DRIVERS")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + + r = rule_line_add_token(rule_line, TK_M_PARENTS_DRIVER, op, value, NULL); + } else if (streq(key, "ATTRS")) { + r = check_attr_format_and_warn(rules, key, attr); + if (r < 0) + return r; + if (!is_match) + return log_token_invalid_op(rules, key); + + if (startswith(attr, "device/")) + log_token_warning(rules, "'device' link may not be available in future kernels; please fix it."); + if (strstr(attr, "../")) + log_token_warning(rules, "Direct reference to parent sysfs directory, may break in future kernels; please fix it."); + + r = rule_line_add_token(rule_line, TK_M_PARENTS_ATTR, op, value, attr); + } else if (streq(key, "TAGS")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + + r = rule_line_add_token(rule_line, TK_M_PARENTS_TAG, op, value, NULL); + } else if (streq(key, "TEST")) { + mode_t mode = MODE_INVALID; + + if (!isempty(attr)) { + r = parse_mode(attr, &mode); + if (r < 0) + return log_token_error_errno(rules, r, "Failed to parse mode '%s': %m", attr); + } + check_value_format_and_warn(rules, key, value, true); + if (!is_match) + return log_token_invalid_op(rules, key); + + r = rule_line_add_token(rule_line, TK_M_TEST, op, value, MODE_TO_PTR(mode)); + } else if (streq(key, "PROGRAM")) { + if (attr) + return log_token_invalid_attr(rules, key); + check_value_format_and_warn(rules, key, value, true); + if (op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (!is_match) { + log_token_debug(rules, "%s key takes '==' or '!=' operator, assuming '=='.", key); + op = OP_MATCH; + } + + r = rule_line_add_token(rule_line, TK_M_PROGRAM, op, value, NULL); + } else if (streq(key, "IMPORT")) { + if (isempty(attr)) + return log_token_invalid_attr(rules, key); + check_value_format_and_warn(rules, key, value, true); + if (op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (!is_match) { + log_token_debug(rules, "%s key takes '==' or '!=' operator, assuming '=='.", key); + op = OP_MATCH; + } + + if (streq(attr, "file")) + r = rule_line_add_token(rule_line, TK_M_IMPORT_FILE, op, value, NULL); + else if (streq(attr, "program")) { + UdevBuiltinCommand cmd; + + cmd = udev_builtin_lookup(value); + if (cmd >= 0) { + log_token_debug(rules,"Found builtin command '%s' for %s, replacing attribute", value, key); + r = rule_line_add_token(rule_line, TK_M_IMPORT_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd)); + } else + r = rule_line_add_token(rule_line, TK_M_IMPORT_PROGRAM, op, value, NULL); + } else if (streq(attr, "builtin")) { + UdevBuiltinCommand cmd; + + cmd = udev_builtin_lookup(value); + if (cmd < 0) + return log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), + "Unknown builtin command: %s", value); + r = rule_line_add_token(rule_line, TK_M_IMPORT_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd)); + } else if (streq(attr, "db")) + r = rule_line_add_token(rule_line, TK_M_IMPORT_DB, op, value, NULL); + else if (streq(attr, "cmdline")) + r = rule_line_add_token(rule_line, TK_M_IMPORT_CMDLINE, op, value, NULL); + else if (streq(attr, "parent")) + r = rule_line_add_token(rule_line, TK_M_IMPORT_PARENT, op, value, NULL); + else + return log_token_invalid_attr(rules, key); + } else if (streq(key, "RESULT")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (!is_match) + return log_token_invalid_op(rules, key); + + r = rule_line_add_token(rule_line, TK_M_RESULT, op, value, NULL); + } else if (streq(key, "OPTIONS")) { + char *tmp; + + if (attr) + return log_token_invalid_attr(rules, key); + if (is_match || op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (op == OP_ADD) { + log_token_debug(rules, "Operator '+=' is specified to %s key, assuming '='.", key); + op = OP_ASSIGN; + } + + if (streq(value, "string_escape=none")) + r = rule_line_add_token(rule_line, TK_A_OPTIONS_STRING_ESCAPE_NONE, op, NULL, NULL); + else if (streq(value, "string_escape=replace")) + r = rule_line_add_token(rule_line, TK_A_OPTIONS_STRING_ESCAPE_REPLACE, op, NULL, NULL); + else if (streq(value, "db_persist")) + r = rule_line_add_token(rule_line, TK_A_OPTIONS_DB_PERSIST, op, NULL, NULL); + else if (streq(value, "watch")) + r = rule_line_add_token(rule_line, TK_A_OPTIONS_INOTIFY_WATCH, op, NULL, INT_TO_PTR(1)); + else if (streq(value, "nowatch")) + r = rule_line_add_token(rule_line, TK_A_OPTIONS_INOTIFY_WATCH, op, NULL, INT_TO_PTR(0)); + else if ((tmp = startswith(value, "static_node="))) + r = rule_line_add_token(rule_line, TK_A_OPTIONS_STATIC_NODE, op, tmp, NULL); + else if ((tmp = startswith(value, "link_priority="))) { + int prio; + + r = safe_atoi(tmp, &prio); + if (r < 0) + return log_token_error_errno(rules, r, "Failed to parse link priority '%s': %m", tmp); + r = rule_line_add_token(rule_line, TK_A_OPTIONS_DEVLINK_PRIORITY, op, NULL, INT_TO_PTR(prio)); + } else { + log_token_warning(rules, "Invalid value for OPTIONS key, ignoring: '%s'", value); + return 0; + } + } else if (streq(key, "OWNER")) { + uid_t uid; + + if (attr) + return log_token_invalid_attr(rules, key); + if (is_match || op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (op == OP_ADD) { + log_token_warning(rules, "%s key takes '=' or ':=' operator, assuming '=', but please fix it.", key); + op = OP_ASSIGN; + } + + if (parse_uid(value, &uid) >= 0) + r = rule_line_add_token(rule_line, TK_A_OWNER_ID, op, NULL, UID_TO_PTR(uid)); + else if (rules->resolve_name_timing == RESOLVE_NAME_EARLY && + rule_get_substitution_type(value) == SUBST_TYPE_PLAIN) { + r = rule_resolve_user(rules, value, &uid); + if (r < 0) + return log_token_error_errno(rules, r, "Failed to resolve user name '%s': %m", value); + + r = rule_line_add_token(rule_line, TK_A_OWNER_ID, op, NULL, UID_TO_PTR(uid)); + } else if (rules->resolve_name_timing != RESOLVE_NAME_NEVER) { + check_value_format_and_warn(rules, key, value, true); + r = rule_line_add_token(rule_line, TK_A_OWNER, op, value, NULL); + } else { + log_token_debug(rules, "Resolving user name is disabled, ignoring %s=%s", key, value); + return 0; + } + } else if (streq(key, "GROUP")) { + gid_t gid; + + if (attr) + return log_token_invalid_attr(rules, key); + if (is_match || op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (op == OP_ADD) { + log_token_warning(rules, "%s key takes '=' or ':=' operator, assuming '=', but please fix it.", key); + op = OP_ASSIGN; + } + + if (parse_gid(value, &gid) >= 0) + r = rule_line_add_token(rule_line, TK_A_GROUP_ID, op, NULL, GID_TO_PTR(gid)); + else if (rules->resolve_name_timing == RESOLVE_NAME_EARLY && + rule_get_substitution_type(value) == SUBST_TYPE_PLAIN) { + r = rule_resolve_group(rules, value, &gid); + if (r < 0) + return log_token_error_errno(rules, r, "Failed to resolve group name '%s': %m", value); + + r = rule_line_add_token(rule_line, TK_A_GROUP_ID, op, NULL, GID_TO_PTR(gid)); + } else if (rules->resolve_name_timing != RESOLVE_NAME_NEVER) { + check_value_format_and_warn(rules, key, value, true); + r = rule_line_add_token(rule_line, TK_A_GROUP, op, value, NULL); + } else { + log_token_debug(rules, "Resolving group name is disabled, ignoring %s=%s", key, value); + return 0; + } + } else if (streq(key, "MODE")) { + mode_t mode; + + if (attr) + return log_token_invalid_attr(rules, key); + if (is_match || op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (op == OP_ADD) { + log_token_warning(rules, "%s key takes '=' or ':=' operator, assuming '=', but please fix it.", key); + op = OP_ASSIGN; + } + + if (parse_mode(value, &mode) >= 0) + r = rule_line_add_token(rule_line, TK_A_MODE_ID, op, NULL, MODE_TO_PTR(mode)); + else { + check_value_format_and_warn(rules, key, value, true); + r = rule_line_add_token(rule_line, TK_A_MODE, op, value, NULL); + } + } else if (streq(key, "SECLABEL")) { + if (isempty(attr)) + return log_token_invalid_attr(rules, key); + check_value_format_and_warn(rules, key, value, true); + if (is_match || op == OP_REMOVE) + return log_token_invalid_op(rules, key); + if (op == OP_ASSIGN_FINAL) { + log_token_warning(rules, "%s key takes '=' or '+=' operator, assuming '=', but please fix it.", key); + op = OP_ASSIGN; + } + + r = rule_line_add_token(rule_line, TK_A_SECLABEL, op, value, NULL); + } else if (streq(key, "RUN")) { + if (is_match || op == OP_REMOVE) + return log_token_invalid_op(rules, key); + check_value_format_and_warn(rules, key, value, true); + if (!attr || streq(attr, "program")) + r = rule_line_add_token(rule_line, TK_A_RUN_PROGRAM, op, value, NULL); + else if (streq(attr, "builtin")) { + UdevBuiltinCommand cmd; + + cmd = udev_builtin_lookup(value); + if (cmd < 0) + return log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), + "Unknown builtin command '%s', ignoring", value); + r = rule_line_add_token(rule_line, TK_A_RUN_BUILTIN, op, value, UDEV_BUILTIN_CMD_TO_PTR(cmd)); + } else + return log_token_invalid_attr(rules, key); + } else if (streq(key, "GOTO")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (op != OP_ASSIGN) + return log_token_invalid_op(rules, key); + if (FLAGS_SET(rule_line->type, LINE_HAS_GOTO)) { + log_token_warning(rules, "Contains multiple GOTO key, ignoring GOTO=\"%s\".", value); + return 0; + } + + rule_line->goto_label = value; + SET_FLAG(rule_line->type, LINE_HAS_GOTO, true); + return 1; + } else if (streq(key, "LABEL")) { + if (attr) + return log_token_invalid_attr(rules, key); + if (op != OP_ASSIGN) + return log_token_invalid_op(rules, key); + + rule_line->label = value; + SET_FLAG(rule_line->type, LINE_HAS_LABEL, true); + return 1; + } else + return log_token_error_errno(rules, SYNTHETIC_ERRNO(EINVAL), "Invalid key '%s'", key); + if (r < 0) + return log_oom(); + + return 1; +} + +static UdevRuleOperatorType parse_operator(const char *op) { + assert(op); + + if (startswith(op, "==")) + return OP_MATCH; + if (startswith(op, "!=")) + return OP_NOMATCH; + if (startswith(op, "+=")) + return OP_ADD; + if (startswith(op, "-=")) + return OP_REMOVE; + if (startswith(op, "=")) + return OP_ASSIGN; + if (startswith(op, ":=")) + return OP_ASSIGN_FINAL; + + return _OP_TYPE_INVALID; +} + +static int parse_line(char **line, char **ret_key, char **ret_attr, UdevRuleOperatorType *ret_op, char **ret_value) { + char *key_begin, *key_end, *attr, *tmp, *value, *i, *j; + UdevRuleOperatorType op; + + assert(line); + assert(*line); + assert(ret_key); + assert(ret_op); + assert(ret_value); + + key_begin = skip_leading_chars(*line, WHITESPACE ","); + + if (isempty(key_begin)) + return 0; + + for (key_end = key_begin; ; key_end++) { + if (key_end[0] == '\0') + return -EINVAL; + if (strchr(WHITESPACE "={", key_end[0])) + break; + if (strchr("+-!:", key_end[0]) && key_end[1] == '=') + break; + } + if (key_end[0] == '{') { + attr = key_end + 1; + tmp = strchr(attr, '}'); + if (!tmp) + return -EINVAL; + *tmp++ = '\0'; + } else { + attr = NULL; + tmp = key_end; + } + + tmp = skip_leading_chars(tmp, NULL); + op = parse_operator(tmp); + if (op < 0) + return -EINVAL; + + key_end[0] = '\0'; + + tmp += op == OP_ASSIGN ? 1 : 2; + value = skip_leading_chars(tmp, NULL); + + /* value must be double quotated */ + if (value[0] != '"') + return -EINVAL; + value++; + + /* unescape double quotation '\"' -> '"' */ + for (i = j = value; ; i++, j++) { + if (*i == '"') + break; + if (*i == '\0') + return -EINVAL; + if (i[0] == '\\' && i[1] == '"') + i++; + *j = *i; + } + j[0] = '\0'; + + *line = i+1; + *ret_key = key_begin; + *ret_attr = attr; + *ret_op = op; + *ret_value = value; + return 1; +} + +static void sort_tokens(UdevRuleLine *rule_line) { + UdevRuleToken *head_old; + + assert(rule_line); + + head_old = TAKE_PTR(rule_line->tokens); + rule_line->current_token = NULL; + + while (!LIST_IS_EMPTY(head_old)) { + UdevRuleToken *t, *min_token = NULL; + + LIST_FOREACH(tokens, t, head_old) + if (!min_token || min_token->type > t->type) + min_token = t; + + LIST_REMOVE(tokens, head_old, min_token); + rule_line_append_token(rule_line, min_token); + } +} + +static int rule_add_line(UdevRules *rules, const char *line_str, unsigned line_nr) { + _cleanup_(udev_rule_line_freep) UdevRuleLine *rule_line = NULL; + _cleanup_free_ char *line = NULL; + UdevRuleFile *rule_file; + char *p; + int r; + + assert(rules); + assert(rules->current_file); + assert(line_str); + + rule_file = rules->current_file; + + if (isempty(line_str)) + return 0; + + line = strdup(line_str); + if (!line) + return log_oom(); + + rule_line = new(UdevRuleLine, 1); + if (!rule_line) + return log_oom(); + + *rule_line = (UdevRuleLine) { + .line = TAKE_PTR(line), + .line_number = line_nr, + .rule_file = rule_file, + }; + + if (rule_file->current_line) + LIST_APPEND(rule_lines, rule_file->current_line, rule_line); + else + LIST_APPEND(rule_lines, rule_file->rule_lines, rule_line); + + rule_file->current_line = rule_line; + + for (p = rule_line->line; !isempty(p); ) { + char *key, *attr, *value; + UdevRuleOperatorType op; + + r = parse_line(&p, &key, &attr, &op, &value); + if (r < 0) + return log_token_error_errno(rules, r, "Invalid key/value pair, ignoring."); + if (r == 0) + break; + + r = parse_token(rules, key, attr, op, value); + if (r < 0) + return r; + } + + if (rule_line->type == 0) { + log_token_warning(rules, "The line takes no effect, ignoring."); + return 0; + } + + sort_tokens(rule_line); + TAKE_PTR(rule_line); + return 0; +} + +static void rule_resolve_goto(UdevRuleFile *rule_file) { + UdevRuleLine *line, *line_next, *i; + + assert(rule_file); + + /* link GOTOs to LABEL rules in this file to be able to fast-forward */ + LIST_FOREACH_SAFE(rule_lines, line, line_next, rule_file->rule_lines) { + if (!FLAGS_SET(line->type, LINE_HAS_GOTO)) + continue; + + LIST_FOREACH_AFTER(rule_lines, i, line) + if (streq_ptr(i->label, line->goto_label)) { + line->goto_line = i; + break; + } + + if (!line->goto_line) { + log_error("%s:%u: GOTO=\"%s\" has no matching label, ignoring", + rule_file->filename, line->line_number, line->goto_label); + + SET_FLAG(line->type, LINE_HAS_GOTO, false); + line->goto_label = NULL; + + if ((line->type & ~LINE_HAS_LABEL) == 0) { + log_notice("%s:%u: The line takes no effect any more, dropping", + rule_file->filename, line->line_number); + if (line->type == LINE_HAS_LABEL) + udev_rule_line_clear_tokens(line); + else + udev_rule_line_free(line); + } + } + } +} + +static int parse_file(UdevRules *rules, const char *filename) { + _cleanup_free_ char *continuation = NULL, *name = NULL; + _cleanup_fclose_ FILE *f = NULL; + UdevRuleFile *rule_file; + bool ignore_line = false; + unsigned line_nr = 0; + int r; + + f = fopen(filename, "re"); + if (!f) { + if (errno == ENOENT) + return 0; + + return -errno; + } + + (void) fd_warn_permissions(filename, fileno(f)); + + if (null_or_empty_fd(fileno(f))) { + log_debug("Skipping empty file: %s", filename); + return 0; + } + + log_debug("Reading rules file: %s", filename); + + name = strdup(filename); + if (!name) + return log_oom(); + + rule_file = new(UdevRuleFile, 1); + if (!rule_file) + return log_oom(); + + *rule_file = (UdevRuleFile) { + .filename = TAKE_PTR(name), + }; + + if (rules->current_file) + LIST_APPEND(rule_files, rules->current_file, rule_file); + else + LIST_APPEND(rule_files, rules->rule_files, rule_file); + + rules->current_file = rule_file; + + for (;;) { + _cleanup_free_ char *buf = NULL; + size_t len; + char *line; + + r = read_line(f, UTIL_LINE_SIZE, &buf); + if (r < 0) + return r; + if (r == 0) + break; + + line_nr++; + line = skip_leading_chars(buf, NULL); + + if (line[0] == '#') + continue; + + len = strlen(line); + + if (continuation && !ignore_line) { + if (strlen(continuation) + len >= UTIL_LINE_SIZE) + ignore_line = true; + + if (!strextend(&continuation, line, NULL)) + return log_oom(); + + if (!ignore_line) { + line = continuation; + len = strlen(line); + } + } + + if (len > 0 && line[len - 1] == '\\') { + if (ignore_line) + continue; + + line[len - 1] = '\0'; + if (!continuation) { + continuation = strdup(line); + if (!continuation) + return log_oom(); + } + + continue; + } + + if (ignore_line) + log_error("%s:%u: Line is too long, ignored", filename, line_nr); + else if (len > 0) + (void) rule_add_line(rules, line, line_nr); + + continuation = mfree(continuation); + ignore_line = false; + } + + rule_resolve_goto(rule_file); + return 0; +} + +int udev_rules_new(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing) { + _cleanup_(udev_rules_freep) UdevRules *rules = NULL; + _cleanup_strv_free_ char **files = NULL; + char **f; + int r; + + assert(resolve_name_timing >= 0 && resolve_name_timing < _RESOLVE_NAME_TIMING_MAX); + + rules = new(UdevRules, 1); + if (!rules) + return -ENOMEM; + + *rules = (UdevRules) { + .resolve_name_timing = resolve_name_timing, + }; + + (void) udev_rules_check_timestamp(rules); + + r = conf_files_list_strv(&files, ".rules", NULL, 0, RULES_DIRS); + if (r < 0) + return log_error_errno(r, "Failed to enumerate rules files: %m"); + + STRV_FOREACH(f, files) + (void) parse_file(rules, *f); + + *ret_rules = TAKE_PTR(rules); + return 0; +} + +bool udev_rules_check_timestamp(UdevRules *rules) { + if (!rules) + return false; + + return paths_check_timestamp(RULES_DIRS, &rules->dirs_ts_usec, true); +} + +static bool token_match_string(UdevRuleToken *token, const char *str) { + const char *i, *value; + bool match = false; + + assert(token); + assert(token->value); + assert(token->type < _TK_M_MAX); + + str = strempty(str); + value = token->value; + + switch (token->match_type) { + case MATCH_TYPE_EMPTY: + match = isempty(str); + break; + case MATCH_TYPE_SUBSYSTEM: + NULSTR_FOREACH(i, "subsystem\0class\0bus\0") + if (streq(i, str)) { + match = true; + break; + } + break; + case MATCH_TYPE_PLAIN_WITH_EMPTY: + if (isempty(str)) { + match = true; + break; + } + _fallthrough_; + case MATCH_TYPE_PLAIN: + NULSTR_FOREACH(i, value) + if (streq(i, str)) { + match = true; + break; + } + break; + case MATCH_TYPE_GLOB_WITH_EMPTY: + if (isempty(str)) { + match = true; + break; + } + _fallthrough_; + case MATCH_TYPE_GLOB: + NULSTR_FOREACH(i, value) + if ((fnmatch(i, str, 0) == 0)) { + match = true; + break; + } + break; + default: + assert_not_reached("Invalid match type"); + } + + return token->op == (match ? OP_MATCH : OP_NOMATCH); +} + +static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *event) { + char nbuf[UTIL_NAME_SIZE], vbuf[UTIL_NAME_SIZE]; + const char *name, *value; + + assert(token); + assert(dev); + assert(event); + + name = (const char*) token->data; + + switch (token->attr_subst_type) { + case SUBST_TYPE_FORMAT: + (void) udev_event_apply_format(event, name, nbuf, sizeof(nbuf), false); + name = nbuf; + _fallthrough_; + case SUBST_TYPE_PLAIN: + if (sd_device_get_sysattr_value(dev, name, &value) < 0) + return false; + break; + case SUBST_TYPE_SUBSYS: + if (util_resolve_subsys_kernel(name, vbuf, sizeof(vbuf), true) < 0) + return false; + value = vbuf; + break; + default: + assert_not_reached("Invalid attribute substitution type"); + } + + /* remove trailing whitespace, if not asked to match for it */ + if (token->attr_match_remove_trailing_whitespace) { + if (value != vbuf) { + strscpy(vbuf, sizeof(vbuf), value); + value = vbuf; + } + + delete_trailing_chars(vbuf, NULL); + } + + return token_match_string(token, value); +} + +static int get_property_from_string(char *line, char **ret_key, char **ret_value) { + char *key, *val; + size_t len; + + assert(line); + assert(ret_key); + assert(ret_value); + + /* find key */ + key = skip_leading_chars(line, NULL); + + /* comment or empty line */ + if (IN_SET(key[0], '#', '\0')) { + *ret_key = *ret_value = NULL; + return 0; + } + + /* split key/value */ + val = strchr(key, '='); + if (!val) + return -EINVAL; + *val++ = '\0'; + + key = strstrip(key); + if (isempty(key)) + return -EINVAL; + + val = strstrip(val); + if (isempty(val)) + return -EINVAL; + + /* unquote */ + if (IN_SET(val[0], '"', '\'')) { + len = strlen(val); + if (len == 1 || val[len-1] != val[0]) + return -EINVAL; + val[len-1] = '\0'; + val++; + } + + *ret_key = key; + *ret_value = val; + return 1; +} + +static int import_parent_into_properties(sd_device *dev, const char *filter) { + const char *key, *val; + sd_device *parent; + int r; + + assert(dev); + assert(filter); + + r = sd_device_get_parent(dev, &parent); + if (r == -ENOENT) + return 0; + if (r < 0) + return r; + + FOREACH_DEVICE_PROPERTY(parent, key, val) { + if (fnmatch(filter, key, 0) != 0) + continue; + r = device_add_property(dev, key, val); + if (r < 0) + return r; + } + + return 1; +} + +static int attr_subst_subdir(char attr[static UTIL_PATH_SIZE]) { + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *dent; + char buf[UTIL_PATH_SIZE], *p; + const char *tail; + size_t len, size; + + assert(attr); + + tail = strstr(attr, "/*/"); + if (!tail) + return 0; + + len = tail - attr + 1; /* include slash at the end */ + tail += 2; /* include slash at the beginning */ + + p = buf; + size = sizeof(buf); + size -= strnpcpy(&p, size, attr, len); + + dir = opendir(buf); + if (!dir) + return -errno; + + FOREACH_DIRENT_ALL(dent, dir, break) { + if (dent->d_name[0] == '.') + continue; + + strscpyl(p, size, dent->d_name, tail, NULL); + if (faccessat(dirfd(dir), p, F_OK, 0) < 0) + continue; + + strcpy(attr, buf); + return 0; + } + + return -ENOENT; +} + +static int udev_rule_apply_token_to_event( + UdevRules *rules, + sd_device *dev, + UdevEvent *event, + usec_t timeout_usec, + Hashmap *properties_list) { + + UdevRuleToken *token; + char buf[UTIL_PATH_SIZE]; + const char *val; + size_t count; + bool match; + int r; + + assert(rules); + assert(dev); + assert(event); + + /* This returns the following values: + * 0 on the current token does not match the event, + * 1 on the current token matches the event, and + * negative errno on some critical errors. */ + + token = rules->current_file->current_line->current_token; + + switch (token->type) { + case TK_M_ACTION: { + DeviceAction a; + + r = device_get_action(dev, &a); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to get uevent action type: %m"); + + return token_match_string(token, device_action_to_string(a)); + } + case TK_M_DEVPATH: + r = sd_device_get_devpath(dev, &val); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to get devpath: %m"); + + return token_match_string(token, val); + case TK_M_KERNEL: + case TK_M_PARENTS_KERNEL: + r = sd_device_get_sysname(dev, &val); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to get sysname: %m"); + + return token_match_string(token, val); + case TK_M_DEVLINK: + FOREACH_DEVICE_DEVLINK(dev, val) + if (token_match_string(token, strempty(startswith(val, "/dev/")))) + return token->op == OP_MATCH; + return token->op == OP_NOMATCH; + case TK_M_NAME: + return token_match_string(token, event->name); + case TK_M_ENV: + if (sd_device_get_property_value(dev, (const char*) token->data, &val) < 0) + val = hashmap_get(properties_list, token->data); + + return token_match_string(token, val); + case TK_M_CONST: { + const char *k = token->data; + + if (streq(k, "arch")) + val = architecture_to_string(uname_architecture()); + else if (streq(k, "virt")) + val = virtualization_to_string(detect_virtualization()); + else + assert_not_reached("Invalid CONST key"); + return token_match_string(token, val); + } + case TK_M_TAG: + case TK_M_PARENTS_TAG: + FOREACH_DEVICE_TAG(dev, val) + if (token_match_string(token, val)) + return token->op == OP_MATCH; + return token->op == OP_NOMATCH; + case TK_M_SUBSYSTEM: + case TK_M_PARENTS_SUBSYSTEM: + r = sd_device_get_subsystem(dev, &val); + if (r == -ENOENT) + val = NULL; + else if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to get subsystem: %m"); + + return token_match_string(token, val); + case TK_M_DRIVER: + case TK_M_PARENTS_DRIVER: + r = sd_device_get_driver(dev, &val); + if (r == -ENOENT) + val = NULL; + else if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to get driver: %m"); + + return token_match_string(token, val); + case TK_M_ATTR: + case TK_M_PARENTS_ATTR: + return token_match_attr(token, dev, event); + case TK_M_SYSCTL: { + _cleanup_free_ char *value = NULL; + + (void) udev_event_apply_format(event, (const char*) token->data, buf, sizeof(buf), false); + r = sysctl_read(sysctl_normalize(buf), &value); + if (r < 0 && r != -ENOENT) + return log_rule_error_errno(dev, rules, r, "Failed to read sysctl '%s': %m", buf); + + return token_match_string(token, strstrip(value)); + } + case TK_M_TEST: { + mode_t mode = PTR_TO_MODE(token->data); + struct stat statbuf; + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false); + if (!path_is_absolute(buf) && + util_resolve_subsys_kernel(buf, buf, sizeof(buf), false) < 0) { + char tmp[UTIL_PATH_SIZE]; + + r = sd_device_get_syspath(dev, &val); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to get syspath: %m"); + + strscpy(tmp, sizeof(tmp), buf); + strscpyl(buf, sizeof(buf), val, "/", tmp, NULL); + } + + r = attr_subst_subdir(buf); + if (r == -ENOENT) + return token->op == OP_NOMATCH; + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to test the existence of '%s': %m", buf); + + if (stat(buf, &statbuf) < 0) + return token->op == OP_NOMATCH; + + if (mode == MODE_INVALID) + return token->op == OP_MATCH; + + match = (statbuf.st_mode & mode) > 0; + return token->op == (match ? OP_MATCH : OP_NOMATCH); + } + case TK_M_PROGRAM: { + char result[UTIL_LINE_SIZE]; + + event->program_result = mfree(event->program_result); + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false); + log_rule_debug(dev, rules, "Running PROGRAM '%s'", buf); + + r = udev_event_spawn(event, timeout_usec, true, buf, result, sizeof(result)); + if (r != 0) { + if (r < 0) + log_rule_warning_errno(dev, rules, r, "Failed to execute '%s', ignoring: %m", buf); + else /* returned value is positive when program fails */ + log_rule_debug(dev, rules, "Command \"%s\" returned %d (error), ignoring", buf, r); + return token->op == OP_NOMATCH; + } + + delete_trailing_chars(result, "\n"); + count = util_replace_chars(result, UDEV_ALLOWED_CHARS_INPUT); + if (count > 0) + log_rule_debug(dev, rules, "Replaced %zu character(s) from result of '%s'", + count, buf); + + event->program_result = strdup(result); + return token->op == OP_MATCH; + } + case TK_M_IMPORT_FILE: { + _cleanup_fclose_ FILE *f = NULL; + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false); + log_rule_debug(dev, rules, "Importing properties from '%s'", buf); + + f = fopen(buf, "re"); + if (!f) { + if (errno != ENOENT) + return log_rule_error_errno(dev, rules, errno, + "Failed to open '%s': %m", buf); + return token->op == OP_NOMATCH; + } + + for (;;) { + _cleanup_free_ char *line = NULL; + char *key, *value; + + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) { + log_rule_debug_errno(dev, rules, r, + "Failed to read '%s', ignoring: %m", buf); + return token->op == OP_NOMATCH; + } + if (r == 0) + break; + + r = get_property_from_string(line, &key, &value); + if (r < 0) { + log_rule_debug_errno(dev, rules, r, + "Failed to parse key and value from '%s', ignoring: %m", + line); + continue; + } + if (r == 0) + continue; + + r = device_add_property(dev, key, value); + if (r < 0) + return log_rule_error_errno(dev, rules, r, + "Failed to add property %s=%s: %m", + key, value); + } + + return token->op == OP_MATCH; + } + case TK_M_IMPORT_PROGRAM: { + char result[UTIL_LINE_SIZE], *line, *pos; + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false); + log_rule_debug(dev, rules, "Importing properties from results of '%s'", buf); + + r = udev_event_spawn(event, timeout_usec, true, buf, result, sizeof result); + if (r != 0) { + if (r < 0) + log_rule_warning_errno(dev, rules, r, "Failed to execute '%s', ignoring: %m", buf); + else /* returned value is positive when program fails */ + log_rule_debug(dev, rules, "Command \"%s\" returned %d (error), ignoring", buf, r); + return token->op == OP_NOMATCH; + } + + for (line = result; !isempty(line); line = pos) { + char *key, *value; + + pos = strchr(line, '\n'); + if (pos) + *pos++ = '\0'; + + r = get_property_from_string(line, &key, &value); + if (r < 0) { + log_rule_debug_errno(dev, rules, r, + "Failed to parse key and value from '%s', ignoring: %m", + line); + continue; + } + if (r == 0) + continue; + + r = device_add_property(dev, key, value); + if (r < 0) + return log_rule_error_errno(dev, rules, r, + "Failed to add property %s=%s: %m", + key, value); + } + + return token->op == OP_MATCH; + } + case TK_M_IMPORT_BUILTIN: { + UdevBuiltinCommand cmd = PTR_TO_UDEV_BUILTIN_CMD(token->data); + unsigned mask = 1U << (int) cmd; + + if (udev_builtin_run_once(cmd)) { + /* check if we ran already */ + if (event->builtin_run & mask) { + log_rule_debug(dev, rules, "Skipping builtin '%s' in IMPORT key", + udev_builtin_name(cmd)); + /* return the result from earlier run */ + return token->op == (event->builtin_ret & mask ? OP_NOMATCH : OP_MATCH); + } + /* mark as ran */ + event->builtin_run |= mask; + } + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false); + log_rule_debug(dev, rules, "Importing properties from results of builtin command '%s'", buf); + + r = udev_builtin_run(dev, cmd, buf, false); + if (r < 0) { + /* remember failure */ + log_rule_debug_errno(dev, rules, r, "Failed to run builtin '%s': %m", buf); + event->builtin_ret |= mask; + } + return token->op == (r >= 0 ? OP_MATCH : OP_NOMATCH); + } + case TK_M_IMPORT_DB: { + if (!event->dev_db_clone) + return token->op == OP_NOMATCH; + r = sd_device_get_property_value(event->dev_db_clone, token->value, &val); + if (r == -ENOENT) + return token->op == OP_NOMATCH; + if (r < 0) + return log_rule_error_errno(dev, rules, r, + "Failed to get property '%s' from database: %m", + token->value); + + r = device_add_property(dev, token->value, val); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to add property '%s=%s': %m", + token->value, val); + return token->op == OP_MATCH; + } + case TK_M_IMPORT_CMDLINE: { + _cleanup_free_ char *value = NULL; + + r = proc_cmdline_get_key(token->value, PROC_CMDLINE_VALUE_OPTIONAL, &value); + if (r < 0) + return log_rule_error_errno(dev, rules, r, + "Failed to read '%s' option from /proc/cmdline: %m", + token->value); + if (r == 0) + return token->op == OP_NOMATCH; + + r = device_add_property(dev, token->value, value ?: "1"); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to add property '%s=%s': %m", + token->value, value ?: "1"); + return token->op == OP_MATCH; + } + case TK_M_IMPORT_PARENT: { + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false); + r = import_parent_into_properties(dev, buf); + if (r < 0) + return log_rule_error_errno(dev, rules, r, + "Failed to import properties '%s' from parent: %m", + buf); + return token->op == (r > 0 ? OP_MATCH : OP_NOMATCH); + } + case TK_M_RESULT: + return token_match_string(token, event->program_result); + case TK_A_OPTIONS_STRING_ESCAPE_NONE: + event->esc = ESCAPE_NONE; + break; + case TK_A_OPTIONS_STRING_ESCAPE_REPLACE: + event->esc = ESCAPE_REPLACE; + break; + case TK_A_OPTIONS_DB_PERSIST: + device_set_db_persist(dev); + break; + case TK_A_OPTIONS_INOTIFY_WATCH: + if (event->inotify_watch_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->inotify_watch_final = true; + + event->inotify_watch = token->data; + break; + case TK_A_OPTIONS_DEVLINK_PRIORITY: + device_set_devlink_priority(dev, PTR_TO_INT(token->data)); + break; + case TK_A_OWNER: { + char owner[UTIL_NAME_SIZE]; + const char *ow = owner; + + if (event->owner_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->owner_final = true; + + (void) udev_event_apply_format(event, token->value, owner, sizeof(owner), false); + r = get_user_creds(&ow, &event->uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); + if (r < 0) + log_unknown_owner(dev, rules, r, "user", owner); + else + log_rule_debug(dev, rules, "OWNER %s(%u)", owner, event->uid); + break; + } + case TK_A_GROUP: { + char group[UTIL_NAME_SIZE]; + const char *gr = group; + + if (event->group_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->group_final = true; + + (void) udev_event_apply_format(event, token->value, group, sizeof(group), false); + r = get_group_creds(&gr, &event->gid, USER_CREDS_ALLOW_MISSING); + if (r < 0) + log_unknown_owner(dev, rules, r, "group", group); + else + log_rule_debug(dev, rules, "GROUP %s(%u)", group, event->gid); + break; + } + case TK_A_MODE: { + char mode_str[UTIL_NAME_SIZE]; + + if (event->mode_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->mode_final = true; + + (void) udev_event_apply_format(event, token->value, mode_str, sizeof(mode_str), false); + r = parse_mode(mode_str, &event->mode); + if (r < 0) + log_rule_error_errno(dev, rules, r, "Failed to parse mode '%s', ignoring: %m", mode_str); + else + log_rule_debug(dev, rules, "MODE %#o", event->mode); + break; + } + case TK_A_OWNER_ID: + if (event->owner_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->owner_final = true; + if (!token->data) + break; + event->uid = PTR_TO_UID(token->data); + log_rule_debug(dev, rules, "OWNER %u", event->uid); + break; + case TK_A_GROUP_ID: + if (event->group_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->group_final = true; + if (!token->data) + break; + event->gid = PTR_TO_GID(token->data); + log_rule_debug(dev, rules, "GROUP %u", event->gid); + break; + case TK_A_MODE_ID: + if (event->mode_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->mode_final = true; + if (!token->data) + break; + event->mode = PTR_TO_MODE(token->data); + log_rule_debug(dev, rules, "MODE %#o", event->mode); + break; + case TK_A_SECLABEL: { + _cleanup_free_ char *name = NULL, *label = NULL; + char label_str[UTIL_LINE_SIZE] = {}; + + name = strdup((const char*) token->data); + if (!name) + return log_oom(); + + (void) udev_event_apply_format(event, token->value, label_str, sizeof(label_str), false); + if (!isempty(label_str)) + label = strdup(label_str); + else + label = strdup(token->value); + if (!label) + return log_oom(); + + if (token->op == OP_ASSIGN) + ordered_hashmap_clear_free_free(event->seclabel_list); + + r = ordered_hashmap_ensure_allocated(&event->seclabel_list, NULL); + if (r < 0) + return log_oom(); + + r = ordered_hashmap_put(event->seclabel_list, name, label); + if (r < 0) + return log_oom(); + log_rule_debug(dev, rules, "SECLABEL{%s}='%s'", name, label); + name = label = NULL; + break; + } + case TK_A_ENV: { + const char *name = (const char*) token->data; + char value_new[UTIL_NAME_SIZE], *p = value_new; + size_t l = sizeof(value_new); + + if (isempty(token->value)) { + if (token->op == OP_ADD) + break; + r = device_add_property(dev, name, NULL); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to remove property '%s': %m", name); + break; + } + + if (token->op == OP_ADD && + sd_device_get_property_value(dev, name, &val) >= 0) + l = strpcpyl(&p, l, val, " ", NULL); + + (void) udev_event_apply_format(event, token->value, p, l, false); + + r = device_add_property(dev, name, value_new); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to add property '%s=%s': %m", name, value_new); + break; + } + case TK_A_TAG: { + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false); + if (token->op == OP_ASSIGN) + device_cleanup_tags(dev); + + if (buf[strspn(buf, ALPHANUMERICAL "-_")] != '\0') { + log_rule_error(dev, rules, "Invalid tag name '%s', ignoring", buf); + break; + } + if (token->op == OP_REMOVE) + device_remove_tag(dev, buf); + else { + r = device_add_tag(dev, buf); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to add tag '%s': %m", buf); + } + break; + } + case TK_A_NAME: { + if (event->name_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->name_final = true; + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false); + if (IN_SET(event->esc, ESCAPE_UNSET, ESCAPE_REPLACE)) { + count = util_replace_chars(buf, "/"); + if (count > 0) + log_rule_debug(dev, rules, "Replaced %zu character(s) from result of NAME=\"%s\"", + count, token->value); + } + if (sd_device_get_devnum(dev, NULL) >= 0 && + (sd_device_get_devname(dev, &val) < 0 || + !streq_ptr(buf, startswith(val, "/dev/")))) { + log_rule_error(dev, rules, + "Kernel device nodes cannot be renamed, ignoring NAME=\"%s\"; please fix it.", + token->value); + break; + } + if (free_and_strdup(&event->name, buf) < 0) + return log_oom(); + + log_rule_debug(dev, rules, "NAME '%s'", event->name); + break; + } + case TK_A_DEVLINK: { + char *p; + + if (event->devlink_final) + break; + if (sd_device_get_devnum(dev, NULL) < 0) + break; + if (token->op == OP_ASSIGN_FINAL) + event->devlink_final = true; + if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL)) + device_cleanup_devlinks(dev); + + /* allow multiple symlinks separated by spaces */ + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), event->esc != ESCAPE_NONE); + if (event->esc == ESCAPE_UNSET) + count = util_replace_chars(buf, "/ "); + else if (event->esc == ESCAPE_REPLACE) + count = util_replace_chars(buf, "/"); + else + count = 0; + if (count > 0) + log_rule_debug(dev, rules, "Replaced %zu character(s) from result of LINK", count); + + p = skip_leading_chars(buf, NULL); + while (!isempty(p)) { + char filename[UTIL_PATH_SIZE], *next; + + next = strchr(p, ' '); + if (next) { + *next++ = '\0'; + next = skip_leading_chars(next, NULL); + } + + strscpyl(filename, sizeof(filename), "/dev/", p, NULL); + r = device_add_devlink(dev, filename); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to add devlink '%s': %m", filename); + + log_rule_debug(dev, rules, "LINK '%s'", p); + p = next; + } + break; + } + case TK_A_ATTR: { + const char *key_name = (const char*) token->data; + char value[UTIL_NAME_SIZE]; + + if (util_resolve_subsys_kernel(key_name, buf, sizeof(buf), false) < 0 && + sd_device_get_syspath(dev, &val) >= 0) + strscpyl(buf, sizeof(buf), val, "/", key_name, NULL); + + r = attr_subst_subdir(buf); + if (r < 0) { + log_rule_error_errno(dev, rules, r, "Could not find file matches '%s', ignoring: %m", buf); + break; + } + (void) udev_event_apply_format(event, token->value, value, sizeof(value), false); + + log_rule_debug(dev, rules, "ATTR '%s' writing '%s'", buf, value); + r = write_string_file(buf, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_AVOID_NEWLINE); + if (r < 0) + log_rule_error_errno(dev, rules, r, "Failed to write ATTR{%s}, ignoring: %m", buf); + break; + } + case TK_A_SYSCTL: { + char value[UTIL_NAME_SIZE]; + + (void) udev_event_apply_format(event, (const char*) token->data, buf, sizeof(buf), false); + (void) udev_event_apply_format(event, token->value, value, sizeof(value), false); + sysctl_normalize(buf); + log_rule_debug(dev, rules, "SYSCTL '%s' writing '%s'", buf, value); + r = sysctl_write(buf, value); + if (r < 0) + log_rule_error_errno(dev, rules, r, "Failed to write SYSCTL{%s}='%s', ignoring: %m", buf, value); + break; + } + case TK_A_RUN_BUILTIN: + case TK_A_RUN_PROGRAM: { + _cleanup_free_ char *cmd = NULL; + + if (event->run_final) + break; + if (token->op == OP_ASSIGN_FINAL) + event->run_final = true; + + if (IN_SET(token->op, OP_ASSIGN, OP_ASSIGN_FINAL)) + ordered_hashmap_clear_free_key(event->run_list); + + r = ordered_hashmap_ensure_allocated(&event->run_list, NULL); + if (r < 0) + return log_oom(); + + (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false); + + cmd = strdup(buf); + if (!cmd) + return log_oom(); + + r = ordered_hashmap_put(event->run_list, cmd, token->data); + if (r < 0) + return log_oom(); + + TAKE_PTR(cmd); + + log_rule_debug(dev, rules, "RUN '%s'", token->value); + break; + } + case TK_A_OPTIONS_STATIC_NODE: + /* do nothing for events. */ + break; + default: + assert_not_reached("Invalid token type"); + } + + return true; +} + +static bool token_is_for_parents(UdevRuleToken *token) { + return token->type >= TK_M_PARENTS_KERNEL && token->type <= TK_M_PARENTS_TAG; +} + +static int udev_rule_apply_parent_token_to_event( + UdevRules *rules, + UdevEvent *event) { + + UdevRuleLine *line; + UdevRuleToken *head; + int r; + + line = rules->current_file->current_line; + head = rules->current_file->current_line->current_token; + event->dev_parent = event->dev; + for (;;) { + LIST_FOREACH(tokens, line->current_token, head) { + if (!token_is_for_parents(line->current_token)) + return true; /* All parent tokens match. */ + r = udev_rule_apply_token_to_event(rules, event->dev_parent, event, 0, NULL); + if (r < 0) + return r; + if (r == 0) + break; + } + if (!line->current_token) + /* All parent tokens match. But no assign tokens in the line. Hmm... */ + return true; + + if (sd_device_get_parent(event->dev_parent, &event->dev_parent) < 0) { + event->dev_parent = NULL; + return false; + } + } +} + +static int udev_rule_apply_line_to_event( + UdevRules *rules, + UdevEvent *event, + usec_t timeout_usec, + Hashmap *properties_list, + UdevRuleLine **next_line) { + + UdevRuleLine *line = rules->current_file->current_line; + UdevRuleLineType mask = LINE_HAS_GOTO | LINE_UPDATE_SOMETHING; + UdevRuleToken *token, *next_token; + bool parents_done = false; + DeviceAction action; + int r; + + r = device_get_action(event->dev, &action); + if (r < 0) + return r; + + if (action != DEVICE_ACTION_REMOVE) { + if (sd_device_get_devnum(event->dev, NULL) >= 0) + mask |= LINE_HAS_DEVLINK; + + if (sd_device_get_ifindex(event->dev, NULL) >= 0) + mask |= LINE_HAS_NAME; + } + + if ((line->type & mask) == 0) + return 0; + + event->esc = ESCAPE_UNSET; + LIST_FOREACH_SAFE(tokens, token, next_token, line->tokens) { + line->current_token = token; + + if (token_is_for_parents(token)) { + if (parents_done) + continue; + + r = udev_rule_apply_parent_token_to_event(rules, event); + if (r <= 0) + return r; + + parents_done = true; + continue; + } + + r = udev_rule_apply_token_to_event(rules, event->dev, event, timeout_usec, properties_list); + if (r <= 0) + return r; + } + + if (line->goto_line) + *next_line = line->goto_line; + + return 0; +} + +int udev_rules_apply_to_event( + UdevRules *rules, + UdevEvent *event, + usec_t timeout_usec, + Hashmap *properties_list) { + + UdevRuleFile *file; + UdevRuleLine *next_line; + int r; + + assert(rules); + assert(event); + + LIST_FOREACH(rule_files, file, rules->rule_files) { + rules->current_file = file; + LIST_FOREACH_SAFE(rule_lines, file->current_line, next_line, file->rule_lines) { + r = udev_rule_apply_line_to_event(rules, event, timeout_usec, properties_list, &next_line); + if (r < 0) + return r; + } + } + + return 0; +} + +static int apply_static_dev_perms(const char *devnode, uid_t uid, gid_t gid, mode_t mode, char **tags) { + char device_node[UTIL_PATH_SIZE], tags_dir[UTIL_PATH_SIZE], tag_symlink[UTIL_PATH_SIZE]; + _cleanup_free_ char *unescaped_filename = NULL; + struct stat stats; + char **t; + int r; + + assert(devnode); + + if (uid == UID_INVALID && gid == GID_INVALID && mode == MODE_INVALID && !tags) + return 0; + + strscpyl(device_node, sizeof(device_node), "/dev/", devnode, NULL); + if (stat(device_node, &stats) < 0) { + if (errno != ENOENT) + return log_error_errno(errno, "Failed to stat %s: %m", device_node); + return 0; + } + + if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) { + log_warning("%s is neither block nor character device, ignoring.", device_node); + return 0; + } + + if (!strv_isempty(tags)) { + unescaped_filename = xescape(devnode, "/."); + if (!unescaped_filename) + return log_oom(); + } + + /* export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */ + STRV_FOREACH(t, tags) { + strscpyl(tags_dir, sizeof(tags_dir), "/run/udev/static_node-tags/", *t, "/", NULL); + r = mkdir_p(tags_dir, 0755); + if (r < 0) + return log_error_errno(r, "Failed to create %s: %m", tags_dir); + + strscpyl(tag_symlink, sizeof(tag_symlink), tags_dir, unescaped_filename, NULL); + r = symlink(device_node, tag_symlink); + if (r < 0 && errno != EEXIST) + return log_error_errno(errno, "Failed to create symlink %s -> %s: %m", + tag_symlink, device_node); + } + + /* don't touch the permissions if only the tags were set */ + if (uid == UID_INVALID && gid == GID_INVALID && mode == MODE_INVALID) + return 0; + + if (mode == MODE_INVALID) + mode = gid_is_valid(gid) ? 0660 : 0600; + if (!uid_is_valid(uid)) + uid = 0; + if (!gid_is_valid(gid)) + gid = 0; + + r = chmod_and_chown(device_node, mode, uid, gid); + if (r == -ENOENT) + return 0; + if (r < 0) + return log_error_errno(r, "Failed to chown '%s' %u %u: %m", device_node, uid, gid); + else + log_debug("chown '%s' %u:%u with mode %#o", device_node, uid, gid, mode); + + (void) utimensat(AT_FDCWD, device_node, NULL, 0); + return 0; +} + +static int udev_rule_line_apply_static_dev_perms(UdevRuleLine *rule_line) { + UdevRuleToken *token; + _cleanup_strv_free_ char **tags = NULL; + uid_t uid = UID_INVALID; + gid_t gid = GID_INVALID; + mode_t mode = MODE_INVALID; + int r; + + assert(rule_line); + + if (!FLAGS_SET(rule_line->type, LINE_HAS_STATIC_NODE)) + return 0; + + LIST_FOREACH(tokens, token, rule_line->tokens) + if (token->type == TK_A_OWNER_ID) + uid = PTR_TO_UID(token->data); + else if (token->type == TK_A_GROUP_ID) + gid = PTR_TO_GID(token->data); + else if (token->type == TK_A_MODE_ID) + mode = PTR_TO_MODE(token->data); + else if (token->type == TK_A_TAG) { + r = strv_extend(&tags, token->value); + if (r < 0) + return log_oom(); + } else if (token->type == TK_A_OPTIONS_STATIC_NODE) { + r = apply_static_dev_perms(token->value, uid, gid, mode, tags); + if (r < 0) + return r; + } + + return 0; +} + +int udev_rules_apply_static_dev_perms(UdevRules *rules) { + UdevRuleFile *file; + UdevRuleLine *line; + int r; + + assert(rules); + + LIST_FOREACH(rule_files, file, rules->rule_files) + LIST_FOREACH(rule_lines, line, file->rule_lines) { + r = udev_rule_line_apply_static_dev_perms(line); + if (r < 0) + return r; + } + + return 0; +} diff --git a/src/udev/udev-rules.h b/src/udev/udev-rules.h new file mode 100644 index 00000000..9fff5da7 --- /dev/null +++ b/src/udev/udev-rules.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +#include "hashmap.h" +#include "time-util.h" +#include "udev-util.h" + +typedef struct UdevRules UdevRules; +typedef struct UdevEvent UdevEvent; + +typedef enum { + ESCAPE_UNSET, + ESCAPE_NONE, /* OPTIONS="string_escape=none" */ + ESCAPE_REPLACE, /* OPTIONS="string_escape=replace" */ + _ESCAPE_TYPE_MAX, + _ESCAPE_TYPE_INVALID = -1 +} UdevRuleEscapeType; + +int udev_rules_new(UdevRules **ret_rules, ResolveNameTiming resolve_name_timing); +UdevRules *udev_rules_free(UdevRules *rules); +DEFINE_TRIVIAL_CLEANUP_FUNC(UdevRules*, udev_rules_free); + +bool udev_rules_check_timestamp(UdevRules *rules); +int udev_rules_apply_to_event(UdevRules *rules, UdevEvent *event, + usec_t timeout_usec, + Hashmap *properties_list); +int udev_rules_apply_static_dev_perms(UdevRules *rules); diff --git a/src/udev/udev-watch.c b/src/udev/udev-watch.c new file mode 100644 index 00000000..68b51d04 --- /dev/null +++ b/src/udev/udev-watch.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright © 2009 Canonical Ltd. + * Copyright © 2009 Scott James Remnant + */ + +#include +#include + +#include "alloc-util.h" +#include "device-private.h" +#include "device-util.h" +#include "dirent-util.h" +#include "fs-util.h" +#include "mkdir.h" +#include "stdio-util.h" +#include "udev-watch.h" + +static int inotify_fd = -1; + +/* inotify descriptor, will be shared with rules directory; + * set to cloexec since we need our children to be able to add + * watches for us. */ +int udev_watch_init(void) { + inotify_fd = inotify_init1(IN_CLOEXEC); + if (inotify_fd < 0) + return -errno; + + return inotify_fd; +} + +/* Move any old watches directory out of the way, and then restore the watches. */ +int udev_watch_restore(void) { + struct dirent *ent; + DIR *dir; + int r; + + if (inotify_fd < 0) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid inotify descriptor."); + + if (rename("/run/udev/watch", "/run/udev/watch.old") < 0) { + if (errno != ENOENT) + return log_warning_errno(errno, "Failed to move watches directory /run/udev/watch. Old watches will not be restored: %m"); + + return 0; + } + + dir = opendir("/run/udev/watch.old"); + if (!dir) + return log_warning_errno(errno, "Failed to open old watches directory /run/udev/watch.old. Old watches will not be restored: %m"); + + FOREACH_DIRENT_ALL(ent, dir, break) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + _cleanup_free_ char *device = NULL; + + if (ent->d_name[0] == '.') + continue; + + r = readlinkat_malloc(dirfd(dir), ent->d_name, &device); + if (r < 0) { + log_debug_errno(r, "Failed to read link '/run/udev/watch.old/%s', ignoring: %m", ent->d_name); + goto unlink; + } + + r = sd_device_new_from_device_id(&dev, device); + if (r < 0) { + log_debug_errno(r, "Failed to create sd_device object for '%s', ignoring: %m", device); + goto unlink; + } + + log_device_debug(dev, "Restoring old watch"); + (void) udev_watch_begin(dev); +unlink: + (void) unlinkat(dirfd(dir), ent->d_name, 0); + } + + (void) closedir(dir); + (void) rmdir("/run/udev/watch.old"); + + return 0; +} + +int udev_watch_begin(sd_device *dev) { + char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)]; + const char *devnode, *id_filename; + int wd, r; + + if (inotify_fd < 0) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid inotify descriptor."); + + r = sd_device_get_devname(dev, &devnode); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get device name: %m"); + + log_device_debug(dev, "Adding watch on '%s'", devnode); + wd = inotify_add_watch(inotify_fd, devnode, IN_CLOSE_WRITE); + if (wd < 0) + return log_device_full(dev, + errno == ENOENT ? LOG_DEBUG : LOG_ERR, + errno, + "Failed to add device '%s' to watch: %m", devnode); + + device_set_watch_handle(dev, wd); + + xsprintf(filename, "/run/udev/watch/%d", wd); + r = mkdir_parents(filename, 0755); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to create parent directory of '%s': %m", filename); + (void) unlink(filename); + + r = device_get_id_filename(dev, &id_filename); + if (r < 0) + return log_device_error_errno(dev, r, "Failed to get device id-filename: %m"); + + if (symlink(id_filename, filename) < 0) + return log_device_error_errno(dev, errno, "Failed to create symlink %s: %m", filename); + + return 0; +} + +int udev_watch_end(sd_device *dev) { + char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)]; + int wd, r; + + if (inotify_fd < 0) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid inotify descriptor."); + + r = device_get_watch_handle(dev, &wd); + if (r == -ENOENT) + return 0; + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get watch handle, ignoring: %m"); + + log_device_debug(dev, "Removing watch"); + (void) inotify_rm_watch(inotify_fd, wd); + + xsprintf(filename, "/run/udev/watch/%d", wd); + (void) unlink(filename); + + device_set_watch_handle(dev, -1); + + return 0; +} + +int udev_watch_lookup(int wd, sd_device **ret) { + char filename[STRLEN("/run/udev/watch/") + DECIMAL_STR_MAX(int)]; + _cleanup_free_ char *device = NULL; + int r; + + assert(ret); + + if (inotify_fd < 0) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid inotify descriptor."); + + if (wd < 0) + return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid watch handle."); + + xsprintf(filename, "/run/udev/watch/%d", wd); + r = readlink_malloc(filename, &device); + if (r == -ENOENT) + return 0; + if (r < 0) + return log_debug_errno(r, "Failed to read link '%s': %m", filename); + + r = sd_device_new_from_device_id(ret, device); + if (r == -ENODEV) + return 0; + if (r < 0) + return log_debug_errno(r, "Failed to create sd_device object for '%s': %m", device); + + return 1; +} diff --git a/src/udev/udev-watch.h b/src/udev/udev-watch.h new file mode 100644 index 00000000..24a136d2 --- /dev/null +++ b/src/udev/udev-watch.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +#include "sd-device.h" + +int udev_watch_init(void); +int udev_watch_restore(void); +int udev_watch_begin(sd_device *dev); +int udev_watch_end(sd_device *dev); +int udev_watch_lookup(int wd, sd_device **ret); diff --git a/src/udev/udev.conf b/src/udev/udev.conf new file mode 100644 index 00000000..7deb7715 --- /dev/null +++ b/src/udev/udev.conf @@ -0,0 +1,10 @@ +# see udev.conf(5) for details +# +# udevd is also started in the initrd. When this file is modified you might +# also want to rebuild the initrd, so that it will include the modified configuration. + +#udev_log=info +#children_max= +#exec_delay= +#event_timeout=180 +#resolve_names=early diff --git a/src/udev/udev.pc.in b/src/udev/udev.pc.in new file mode 100644 index 00000000..5acbb2d0 --- /dev/null +++ b/src/udev/udev.pc.in @@ -0,0 +1,5 @@ +Name: udev +Description: udev +Version: @PROJECT_VERSION@ + +udevdir=@udevlibexecdir@ diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c new file mode 100644 index 00000000..82e25149 --- /dev/null +++ b/src/udev/udevadm-control.c @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "parse-util.h" +#include "process-util.h" +#include "syslog-util.h" +#include "time-util.h" +#include "udevadm.h" +#include "udev-ctrl.h" +#include "util.h" +#include "virt.h" + +static int help(void) { + printf("%s control OPTION\n\n" + "Control the udev daemon.\n\n" + " -h --help Show this help\n" + " -V --version Show package version\n" + " -e --exit Instruct the daemon to cleanup and exit\n" + " -l --log-priority=LEVEL Set the udev log level for the daemon\n" + " -s --stop-exec-queue Do not execute events, queue only\n" + " -S --start-exec-queue Execute events, flush queue\n" + " -R --reload Reload rules and databases\n" + " -p --property=KEY=VALUE Set a global property for all events\n" + " -m --children-max=N Maximum number of children\n" + " --ping Wait for udev to respond to a ping message\n" + " -t --timeout=SECONDS Maximum time to block for a reply\n" + , program_invocation_short_name); + + return 0; +} + +int control_main(int argc, char *argv[], void *userdata) { + _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL; + usec_t timeout = 60 * USEC_PER_SEC; + int c, r; + + enum { + ARG_PING = 0x100, + }; + + static const struct option options[] = { + { "exit", no_argument, NULL, 'e' }, + { "log-priority", required_argument, NULL, 'l' }, + { "stop-exec-queue", no_argument, NULL, 's' }, + { "start-exec-queue", no_argument, NULL, 'S' }, + { "reload", no_argument, NULL, 'R' }, + { "reload-rules", no_argument, NULL, 'R' }, /* alias for -R */ + { "property", required_argument, NULL, 'p' }, + { "env", required_argument, NULL, 'p' }, /* alias for -p */ + { "children-max", required_argument, NULL, 'm' }, + { "ping", no_argument, NULL, ARG_PING }, + { "timeout", required_argument, NULL, 't' }, + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + {} + }; + + if (running_in_chroot() > 0) { + log_info("Running in chroot, ignoring request."); + return 0; + } + + if (argc <= 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This command expects one or more options."); + + r = udev_ctrl_new(&uctrl); + if (r < 0) + return log_error_errno(r, "Failed to initialize udev control: %m"); + + while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0) + switch (c) { + case 'e': + r = udev_ctrl_send_exit(uctrl); + if (r == -ENOANO) + log_warning("Cannot specify --exit after --exit, ignoring."); + else if (r < 0) + return log_error_errno(r, "Failed to send exit request: %m"); + break; + case 'l': + r = log_level_from_string(optarg); + if (r < 0) + return log_error_errno(r, "Failed to parse log priority '%s': %m", optarg); + + r = udev_ctrl_send_set_log_level(uctrl, r); + if (r == -ENOANO) + log_warning("Cannot specify --log-priority after --exit, ignoring."); + else if (r < 0) + return log_error_errno(r, "Failed to send request to set log level: %m"); + break; + case 's': + r = udev_ctrl_send_stop_exec_queue(uctrl); + if (r == -ENOANO) + log_warning("Cannot specify --stop-exec-queue after --exit, ignoring."); + else if (r < 0) + return log_error_errno(r, "Failed to send request to stop exec queue: %m"); + break; + case 'S': + r = udev_ctrl_send_start_exec_queue(uctrl); + if (r == -ENOANO) + log_warning("Cannot specify --start-exec-queue after --exit, ignoring."); + else if (r < 0) + return log_error_errno(r, "Failed to send request to start exec queue: %m"); + break; + case 'R': + r = udev_ctrl_send_reload(uctrl); + if (r == -ENOANO) + log_warning("Cannot specify --reload after --exit, ignoring."); + else if (r < 0) + return log_error_errno(r, "Failed to send reload request: %m"); + break; + case 'p': + if (!strchr(optarg, '=')) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "expect = instead of '%s'", optarg); + + r = udev_ctrl_send_set_env(uctrl, optarg); + if (r == -ENOANO) + log_warning("Cannot specify --property after --exit, ignoring."); + else if (r < 0) + return log_error_errno(r, "Failed to send request to update environment: %m"); + break; + case 'm': { + unsigned i; + + r = safe_atou(optarg, &i); + if (r < 0) + return log_error_errno(r, "Failed to parse maximum number of events '%s': %m", optarg); + + r = udev_ctrl_send_set_children_max(uctrl, i); + if (r == -ENOANO) + log_warning("Cannot specify --children-max after --exit, ignoring."); + else if (r < 0) + return log_error_errno(r, "Failed to send request to set number of children: %m"); + break; + } + case ARG_PING: + r = udev_ctrl_send_ping(uctrl); + if (r == -ENOANO) + log_error("Cannot specify --ping after --exit, ignoring."); + else if (r < 0) + return log_error_errno(r, "Failed to send a ping message: %m"); + break; + case 't': + r = parse_sec(optarg, &timeout); + if (r < 0) + return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg); + break; + case 'V': + return print_version(); + case 'h': + return help(); + case '?': + return -EINVAL; + default: + assert_not_reached("Unknown option."); + } + + if (optind < argc) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Extraneous argument: %s", argv[optind]); + + r = udev_ctrl_wait(uctrl, timeout); + if (r < 0) + return log_error_errno(r, "Failed to wait for daemon to reply: %m"); + + return 0; +} diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c new file mode 100644 index 00000000..7f8960f5 --- /dev/null +++ b/src/udev/udevadm-hwdb.c @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "hwdb-util.h" +#include "udevadm.h" +#include "util.h" + +static const char *arg_test = NULL; +static const char *arg_root = NULL; +static const char *arg_hwdb_bin_dir = NULL; +static bool arg_update = false; +static bool arg_strict = false; + +static int help(void) { + printf("%s hwdb [OPTIONS]\n\n" + " -h --help Print this message\n" + " -V --version Print version of the program\n" + " -u --update Update the hardware database\n" + " -s --strict When updating, return non-zero exit value on any parsing error\n" + " --usr Generate in " UDEVLIBEXECDIR " instead of /etc/udev\n" + " -t --test=MODALIAS Query database and print result\n" + " -r --root=PATH Alternative root path in the filesystem\n\n" + "NOTE:\n" + "The sub-command 'hwdb' is deprecated, and is left for backwards compatibility.\n" + "Please use systemd-hwdb instead.\n" + , program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + enum { + ARG_USR = 0x100, + }; + + static const struct option options[] = { + { "update", no_argument, NULL, 'u' }, + { "usr", no_argument, NULL, ARG_USR }, + { "strict", no_argument, NULL, 's' }, + { "test", required_argument, NULL, 't' }, + { "root", required_argument, NULL, 'r' }, + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + {} + }; + + int c; + + while ((c = getopt_long(argc, argv, "ust:r:Vh", options, NULL)) >= 0) + switch(c) { + case 'u': + arg_update = true; + break; + case ARG_USR: + arg_hwdb_bin_dir = UDEVLIBEXECDIR; + break; + case 's': + arg_strict = true; + break; + case 't': + arg_test = optarg; + break; + case 'r': + arg_root = optarg; + break; + case 'V': + return print_version(); + case 'h': + return help(); + case '?': + return -EINVAL; + default: + assert_not_reached("Unknown option"); + } + + return 1; +} + +int hwdb_main(int argc, char *argv[], void *userdata) { + int r; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (!arg_update && !arg_test) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Either --update or --test must be used."); + + if (arg_update) { + r = hwdb_update(arg_root, arg_hwdb_bin_dir, arg_strict, true); + if (r < 0) + return r; + } + + if (arg_test) + return hwdb_query(arg_test); + + return 0; +} diff --git a/src/udev/udevadm-info.c b/src/udev/udevadm-info.c new file mode 100644 index 00000000..2d2bc002 --- /dev/null +++ b/src/udev/udevadm-info.c @@ -0,0 +1,490 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-device.h" + +#include "alloc-util.h" +#include "device-enumerator-private.h" +#include "device-private.h" +#include "device-util.h" +#include "dirent-util.h" +#include "fd-util.h" +#include "string-table.h" +#include "string-util.h" +#include "udev-util.h" +#include "udevadm-util.h" +#include "udevadm.h" + +typedef enum ActionType { + ACTION_QUERY, + ACTION_ATTRIBUTE_WALK, + ACTION_DEVICE_ID_FILE, +} ActionType; + +typedef enum QueryType { + QUERY_NAME, + QUERY_PATH, + QUERY_SYMLINK, + QUERY_PROPERTY, + QUERY_ALL, +} QueryType; + +static bool arg_root = false; +static bool arg_export = false; +static const char *arg_export_prefix = NULL; +static usec_t arg_wait_for_initialization_timeout = 0; + +static bool skip_attribute(const char *name) { + static const char* const skip[] = { + "uevent", + "dev", + "modalias", + "resource", + "driver", + "subsystem", + "module", + }; + + return string_table_lookup(skip, ELEMENTSOF(skip), name) >= 0; +} + +static void print_all_attributes(sd_device *device, const char *key) { + const char *name, *value; + + FOREACH_DEVICE_SYSATTR(device, name) { + size_t len; + + if (skip_attribute(name)) + continue; + + if (sd_device_get_sysattr_value(device, name, &value) < 0) + continue; + + /* skip any values that look like a path */ + if (value[0] == '/') + continue; + + /* skip nonprintable attributes */ + len = strlen(value); + while (len > 0 && isprint(value[len-1])) + len--; + if (len > 0) + continue; + + printf(" %s{%s}==\"%s\"\n", key, name, value); + } + puts(""); +} + +static int print_device_chain(sd_device *device) { + sd_device *child, *parent; + const char *str; + + printf("\n" + "Udevadm info starts with the device specified by the devpath and then\n" + "walks up the chain of parent devices. It prints for every device\n" + "found, all possible attributes in the udev rules key format.\n" + "A rule to match, can be composed by the attributes of the device\n" + "and the attributes from one single parent device.\n" + "\n"); + + (void) sd_device_get_devpath(device, &str); + printf(" looking at device '%s':\n", str); + (void) sd_device_get_sysname(device, &str); + printf(" KERNEL==\"%s\"\n", str); + if (sd_device_get_subsystem(device, &str) < 0) + str = ""; + printf(" SUBSYSTEM==\"%s\"\n", str); + if (sd_device_get_driver(device, &str) < 0) + str = ""; + printf(" DRIVER==\"%s\"\n", str); + print_all_attributes(device, "ATTR"); + + for (child = device; sd_device_get_parent(child, &parent) >= 0; child = parent) { + (void) sd_device_get_devpath(parent, &str); + printf(" looking at parent device '%s':\n", str); + (void) sd_device_get_sysname(parent, &str); + printf(" KERNELS==\"%s\"\n", str); + if (sd_device_get_subsystem(parent, &str) < 0) + str = ""; + printf(" SUBSYSTEMS==\"%s\"\n", str); + if (sd_device_get_driver(parent, &str) < 0) + str = ""; + printf(" DRIVERS==\"%s\"\n", str); + print_all_attributes(parent, "ATTRS"); + } + + return 0; +} + +static int print_record(sd_device *device) { + const char *str, *val; + int i; + + (void) sd_device_get_devpath(device, &str); + printf("P: %s\n", str); + + if (sd_device_get_devname(device, &str) >= 0) { + assert_se(val = path_startswith(str, "/dev/")); + printf("N: %s\n", val); + } + + if (device_get_devlink_priority(device, &i) >= 0) + printf("L: %i\n", i); + + FOREACH_DEVICE_DEVLINK(device, str) { + assert_se(val = path_startswith(str, "/dev/")); + printf("S: %s\n", val); + } + + FOREACH_DEVICE_PROPERTY(device, str, val) + printf("E: %s=%s\n", str, val); + + puts(""); + return 0; +} + +static int stat_device(const char *name, bool export, const char *prefix) { + struct stat statbuf; + + if (stat(name, &statbuf) != 0) + return -errno; + + if (export) { + if (!prefix) + prefix = "INFO_"; + printf("%sMAJOR=%u\n" + "%sMINOR=%u\n", + prefix, major(statbuf.st_dev), + prefix, minor(statbuf.st_dev)); + } else + printf("%u:%u\n", major(statbuf.st_dev), minor(statbuf.st_dev)); + return 0; +} + +static int export_devices(void) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *d; + int r; + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + r = device_enumerator_scan_devices(e); + if (r < 0) + return r; + + FOREACH_DEVICE_AND_SUBSYSTEM(e, d) + print_record(d); + + return 0; +} + +static void cleanup_dir(DIR *dir, mode_t mask, int depth) { + struct dirent *dent; + + if (depth <= 0) + return; + + FOREACH_DIRENT_ALL(dent, dir, break) { + struct stat stats; + + if (dent->d_name[0] == '.') + continue; + if (fstatat(dirfd(dir), dent->d_name, &stats, AT_SYMLINK_NOFOLLOW) != 0) + continue; + if ((stats.st_mode & mask) != 0) + continue; + if (S_ISDIR(stats.st_mode)) { + _cleanup_closedir_ DIR *dir2 = NULL; + + dir2 = fdopendir(openat(dirfd(dir), dent->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)); + if (dir2) + cleanup_dir(dir2, mask, depth-1); + + (void) unlinkat(dirfd(dir), dent->d_name, AT_REMOVEDIR); + } else + (void) unlinkat(dirfd(dir), dent->d_name, 0); + } +} + +static void cleanup_db(void) { + _cleanup_closedir_ DIR *dir1 = NULL, *dir2 = NULL, *dir3 = NULL, *dir4 = NULL, *dir5 = NULL; + + (void) unlink("/run/udev/queue.bin"); + + dir1 = opendir("/run/udev/data"); + if (dir1) + cleanup_dir(dir1, S_ISVTX, 1); + + dir2 = opendir("/run/udev/links"); + if (dir2) + cleanup_dir(dir2, 0, 2); + + dir3 = opendir("/run/udev/tags"); + if (dir3) + cleanup_dir(dir3, 0, 2); + + dir4 = opendir("/run/udev/static_node-tags"); + if (dir4) + cleanup_dir(dir4, 0, 2); + + dir5 = opendir("/run/udev/watch"); + if (dir5) + cleanup_dir(dir5, 0, 1); +} + +static int query_device(QueryType query, sd_device* device) { + int r; + + assert(device); + + switch(query) { + case QUERY_NAME: { + const char *node; + + r = sd_device_get_devname(device, &node); + if (r < 0) + return log_error_errno(r, "No device node found: %m"); + + if (!arg_root) + assert_se(node = path_startswith(node, "/dev/")); + printf("%s\n", node); + return 0; + } + + case QUERY_SYMLINK: { + const char *devlink, *prefix = ""; + + FOREACH_DEVICE_DEVLINK(device, devlink) { + if (!arg_root) + assert_se(devlink = path_startswith(devlink, "/dev/")); + printf("%s%s", prefix, devlink); + prefix = " "; + } + puts(""); + return 0; + } + + case QUERY_PATH: { + const char *devpath; + + r = sd_device_get_devpath(device, &devpath); + if (r < 0) + return log_error_errno(r, "Failed to get device path: %m"); + + printf("%s\n", devpath); + return 0; + } + + case QUERY_PROPERTY: { + const char *key, *value; + + FOREACH_DEVICE_PROPERTY(device, key, value) + if (arg_export) + printf("%s%s='%s'\n", strempty(arg_export_prefix), key, value); + else + printf("%s=%s\n", key, value); + return 0; + } + + case QUERY_ALL: + return print_record(device); + } + + assert_not_reached("unknown query type"); + return 0; +} + +static int help(void) { + printf("%s info [OPTIONS] [DEVPATH|FILE]\n\n" + "Query sysfs or the udev database.\n\n" + " -h --help Print this message\n" + " -V --version Print version of the program\n" + " -q --query=TYPE Query device information:\n" + " name Name of device node\n" + " symlink Pointing to node\n" + " path sysfs device path\n" + " property The device properties\n" + " all All values\n" + " -p --path=SYSPATH sysfs device path used for query or attribute walk\n" + " -n --name=NAME Node or symlink name used for query or attribute walk\n" + " -r --root Prepend dev directory to path names\n" + " -a --attribute-walk Print all key matches walking along the chain\n" + " of parent devices\n" + " -d --device-id-of-file=FILE Print major:minor of device containing this file\n" + " -x --export Export key/value pairs\n" + " -P --export-prefix Export the key name with a prefix\n" + " -e --export-db Export the content of the udev database\n" + " -c --cleanup-db Clean up the udev database\n" + " -w --wait-for-initialization[=SECONDS]\n" + " Wait for device to be initialized\n" + , program_invocation_short_name); + + return 0; +} + +int info_main(int argc, char *argv[], void *userdata) { + _cleanup_strv_free_ char **devices = NULL; + _cleanup_free_ char *name = NULL; + int c, r; + + static const struct option options[] = { + { "name", required_argument, NULL, 'n' }, + { "path", required_argument, NULL, 'p' }, + { "query", required_argument, NULL, 'q' }, + { "attribute-walk", no_argument, NULL, 'a' }, + { "cleanup-db", no_argument, NULL, 'c' }, + { "export-db", no_argument, NULL, 'e' }, + { "root", no_argument, NULL, 'r' }, + { "device-id-of-file", required_argument, NULL, 'd' }, + { "export", no_argument, NULL, 'x' }, + { "export-prefix", required_argument, NULL, 'P' }, + { "wait-for-initialization", optional_argument, NULL, 'w' }, + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + {} + }; + + ActionType action = ACTION_QUERY; + QueryType query = QUERY_ALL; + + while ((c = getopt_long(argc, argv, "aced:n:p:q:rxP:w::Vh", options, NULL)) >= 0) + switch (c) { + case 'n': + case 'p': { + const char *prefix = c == 'n' ? "/dev/" : "/sys/"; + char *path; + + path = path_join(path_startswith(optarg, prefix) ? NULL : prefix, optarg); + if (!path) + return log_oom(); + + r = strv_consume(&devices, path); + if (r < 0) + return log_oom(); + break; + } + + case 'q': + action = ACTION_QUERY; + if (streq(optarg, "property") || streq(optarg, "env")) + query = QUERY_PROPERTY; + else if (streq(optarg, "name")) + query = QUERY_NAME; + else if (streq(optarg, "symlink")) + query = QUERY_SYMLINK; + else if (streq(optarg, "path")) + query = QUERY_PATH; + else if (streq(optarg, "all")) + query = QUERY_ALL; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "unknown query type"); + break; + case 'r': + arg_root = true; + break; + case 'd': + action = ACTION_DEVICE_ID_FILE; + r = free_and_strdup(&name, optarg); + if (r < 0) + return log_oom(); + break; + case 'a': + action = ACTION_ATTRIBUTE_WALK; + break; + case 'e': + return export_devices(); + case 'c': + cleanup_db(); + return 0; + case 'x': + arg_export = true; + break; + case 'P': + arg_export = true; + arg_export_prefix = optarg; + break; + case 'w': + if (optarg) { + r = parse_sec(optarg, &arg_wait_for_initialization_timeout); + if (r < 0) + return log_error_errno(r, "Failed to parse timeout value: %m"); + } else + arg_wait_for_initialization_timeout = USEC_INFINITY; + break; + case 'V': + return print_version(); + case 'h': + return help(); + case '?': + return -EINVAL; + default: + assert_not_reached("Unknown option"); + } + + if (action == ACTION_DEVICE_ID_FILE) { + if (argv[optind]) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Positional arguments are not allowed with -d/--device-id-of-file."); + assert(name); + return stat_device(name, arg_export, arg_export_prefix); + } + + r = strv_extend_strv(&devices, argv + optind, false); + if (r < 0) + return log_error_errno(r, "Failed to build argument list: %m"); + + if (strv_isempty(devices)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "A device name or path is required"); + if (action == ACTION_ATTRIBUTE_WALK && strv_length(devices) > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Only one device may be specified with -a/--attribute-walk"); + + char **p; + STRV_FOREACH(p, devices) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + + r = find_device(*p, NULL, &device); + if (r == -EINVAL) + return log_error_errno(r, "Bad argument \"%s\", expected an absolute path in /dev/ or /sys or a unit name: %m", *p); + if (r < 0) + return log_error_errno(r, "Unknown device \"%s\": %m", *p); + + if (arg_wait_for_initialization_timeout > 0) { + sd_device *d; + + r = device_wait_for_initialization(device, NULL, arg_wait_for_initialization_timeout, &d); + if (r < 0) + return r; + + sd_device_unref(device); + device = d; + } + + if (action == ACTION_QUERY) + r = query_device(query, device); + else if (action == ACTION_ATTRIBUTE_WALK) + r = print_device_chain(device); + else + assert_not_reached("Unknown action"); + if (r < 0) + return r; + } + + return 0; +} diff --git a/src/udev/udevadm-monitor.c b/src/udev/udevadm-monitor.c new file mode 100644 index 00000000..2ca98a72 --- /dev/null +++ b/src/udev/udevadm-monitor.c @@ -0,0 +1,266 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include +#include + +#include "sd-device.h" +#include "sd-event.h" + +#include "alloc-util.h" +#include "device-monitor-private.h" +#include "device-private.h" +#include "device-util.h" +#include "fd-util.h" +#include "format-util.h" +#include "hashmap.h" +#include "set.h" +#include "signal-util.h" +#include "string-util.h" +#include "udevadm.h" +#include "virt.h" +#include "time-util.h" + +static bool arg_show_property = false; +static bool arg_print_kernel = false; +static bool arg_print_udev = false; +static Set *arg_tag_filter = NULL; +static Hashmap *arg_subsystem_filter = NULL; + +static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, void *userdata) { + DeviceAction action = _DEVICE_ACTION_INVALID; + const char *devpath = NULL, *subsystem = NULL; + MonitorNetlinkGroup group = PTR_TO_INT(userdata); + struct timespec ts; + + assert(device); + assert(IN_SET(group, MONITOR_GROUP_UDEV, MONITOR_GROUP_KERNEL)); + + (void) device_get_action(device, &action); + (void) sd_device_get_devpath(device, &devpath); + (void) sd_device_get_subsystem(device, &subsystem); + + assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); + + printf("%-6s[%"PRI_TIME".%06"PRI_NSEC"] %-8s %s (%s)\n", + group == MONITOR_GROUP_UDEV ? "UDEV" : "KERNEL", + ts.tv_sec, (nsec_t)ts.tv_nsec/1000, + strna(device_action_to_string(action)), + devpath, subsystem); + + if (arg_show_property) { + const char *key, *value; + + FOREACH_DEVICE_PROPERTY(device, key, value) + printf("%s=%s\n", key, value); + + printf("\n"); + } + + return 0; +} + +static int setup_monitor(MonitorNetlinkGroup sender, sd_event *event, sd_device_monitor **ret) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL; + const char *subsystem, *devtype, *tag; + Iterator i; + int r; + + r = device_monitor_new_full(&monitor, sender, -1); + if (r < 0) + return log_error_errno(r, "Failed to create netlink socket: %m"); + + (void) sd_device_monitor_set_receive_buffer_size(monitor, 128*1024*1024); + + r = sd_device_monitor_attach_event(monitor, event); + if (r < 0) + return log_error_errno(r, "Failed to attach event: %m"); + + HASHMAP_FOREACH_KEY(devtype, subsystem, arg_subsystem_filter, i) { + r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, subsystem, devtype); + if (r < 0) + return log_error_errno(r, "Failed to apply subsystem filter '%s%s%s': %m", + subsystem, devtype ? "/" : "", strempty(devtype)); + } + + SET_FOREACH(tag, arg_tag_filter, i) { + r = sd_device_monitor_filter_add_match_tag(monitor, tag); + if (r < 0) + return log_error_errno(r, "Failed to apply tag filter '%s': %m", tag); + } + + r = sd_device_monitor_start(monitor, device_monitor_handler, INT_TO_PTR(sender)); + if (r < 0) + return log_error_errno(r, "Failed to start device monitor: %m"); + + (void) sd_event_source_set_description(sd_device_monitor_get_event_source(monitor), + sender == MONITOR_GROUP_UDEV ? "device-monitor-udev" : "device-monitor-kernel"); + + *ret = TAKE_PTR(monitor); + return 0; +} + +static int help(void) { + printf("%s monitor [OPTIONS]\n\n" + "Listen to kernel and udev events.\n\n" + " -h --help Show this help\n" + " -V --version Show package version\n" + " -p --property Print the event properties\n" + " -k --kernel Print kernel uevents\n" + " -u --udev Print udev events\n" + " -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n" + " -t --tag-match=TAG Filter events by tag\n" + , program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + static const struct option options[] = { + { "property", no_argument, NULL, 'p' }, + { "environment", no_argument, NULL, 'e' }, /* alias for -p */ + { "kernel", no_argument, NULL, 'k' }, + { "udev", no_argument, NULL, 'u' }, + { "subsystem-match", required_argument, NULL, 's' }, + { "tag-match", required_argument, NULL, 't' }, + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + {} + }; + + int r, c; + + while ((c = getopt_long(argc, argv, "pekus:t:Vh", options, NULL)) >= 0) + switch (c) { + case 'p': + case 'e': + arg_show_property = true; + break; + case 'k': + arg_print_kernel = true; + break; + case 'u': + arg_print_udev = true; + break; + case 's': { + _cleanup_free_ char *subsystem = NULL, *devtype = NULL; + const char *slash; + + slash = strchr(optarg, '/'); + if (slash) { + devtype = strdup(slash + 1); + if (!devtype) + return -ENOMEM; + + subsystem = strndup(optarg, slash - optarg); + } else + subsystem = strdup(optarg); + + if (!subsystem) + return -ENOMEM; + + r = hashmap_ensure_allocated(&arg_subsystem_filter, NULL); + if (r < 0) + return r; + + r = hashmap_put(arg_subsystem_filter, subsystem, devtype); + if (r < 0) + return r; + + subsystem = devtype = NULL; + break; + } + case 't': { + _cleanup_free_ char *tag = NULL; + + r = set_ensure_allocated(&arg_tag_filter, &string_hash_ops); + if (r < 0) + return r; + + tag = strdup(optarg); + if (!tag) + return -ENOMEM; + + r = set_put(arg_tag_filter, tag); + if (r < 0) + return r; + + tag = NULL; + break; + } + case 'V': + return print_version(); + case 'h': + return help(); + case '?': + return -EINVAL; + default: + assert_not_reached("Unknown option."); + } + + if (!arg_print_kernel && !arg_print_udev) { + arg_print_kernel = true; + arg_print_udev = true; + } + + return 1; +} + +int monitor_main(int argc, char *argv[], void *userdata) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *kernel_monitor = NULL, *udev_monitor = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + int r; + + r = parse_argv(argc, argv); + if (r <= 0) + goto finalize; + + if (running_in_chroot() > 0) { + log_info("Running in chroot, ignoring request."); + return 0; + } + + /* Callers are expecting to see events as they happen: Line buffering */ + setlinebuf(stdout); + + r = sd_event_default(&event); + if (r < 0) { + log_error_errno(r, "Failed to initialize event: %m"); + goto finalize; + } + + assert_se(sigprocmask_many(SIG_UNBLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); + (void) sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL); + (void) sd_event_add_signal(event, NULL, SIGINT, NULL, NULL); + + printf("monitor will print the received events for:\n"); + if (arg_print_udev) { + r = setup_monitor(MONITOR_GROUP_UDEV, event, &udev_monitor); + if (r < 0) + goto finalize; + + printf("UDEV - the event which udev sends out after rule processing\n"); + } + + if (arg_print_kernel) { + r = setup_monitor(MONITOR_GROUP_KERNEL, event, &kernel_monitor); + if (r < 0) + goto finalize; + + printf("KERNEL - the kernel uevent\n"); + } + printf("\n"); + + r = sd_event_loop(event); + if (r < 0) { + log_error_errno(r, "Failed to run event loop: %m"); + goto finalize; + } + + r = 0; + +finalize: + hashmap_free_free_free(arg_subsystem_filter); + set_free_free(arg_tag_filter); + + return r; +} diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c new file mode 100644 index 00000000..7d7044ea --- /dev/null +++ b/src/udev/udevadm-settle.c @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright © 2009 Canonical Ltd. + * Copyright © 2009 Scott James Remnant + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus.h" +#include "sd-login.h" + +#include "libudev-util.h" +#include "string-util.h" +#include "strv.h" +#include "time-util.h" +#include "udev-ctrl.h" +#include "udevadm.h" +#include "unit-def.h" +#include "util.h" +#include "virt.h" + +static usec_t arg_timeout = 120 * USEC_PER_SEC; +static const char *arg_exists = NULL; + +static int help(void) { + printf("%s settle [OPTIONS]\n\n" + "Wait for pending udev events.\n\n" + " -h --help Show this help\n" + " -V --version Show package version\n" + " -t --timeout=SEC Maximum time to wait for events\n" + " -E --exit-if-exists=FILE Stop waiting if file exists\n" + , program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + static const struct option options[] = { + { "timeout", required_argument, NULL, 't' }, + { "exit-if-exists", required_argument, NULL, 'E' }, + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + { "seq-start", required_argument, NULL, 's' }, /* removed */ + { "seq-end", required_argument, NULL, 'e' }, /* removed */ + { "quiet", no_argument, NULL, 'q' }, /* removed */ + {} + }; + + int c, r; + + while ((c = getopt_long(argc, argv, "t:E:Vhs:e:q", options, NULL)) >= 0) { + switch (c) { + case 't': + r = parse_sec(optarg, &arg_timeout); + if (r < 0) + return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg); + break; + case 'E': + arg_exists = optarg; + break; + case 'V': + return print_version(); + case 'h': + return help(); + case 's': + case 'e': + case 'q': + return log_info_errno(SYNTHETIC_ERRNO(EINVAL), + "Option -%c no longer supported.", + c); + case '?': + return -EINVAL; + default: + assert_not_reached("Unknown option."); + } + } + + return 1; +} + +static int emit_deprecation_warning(void) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_free_ char *unit = NULL, *unit_path = NULL; + _cleanup_strv_free_ char **a = NULL, **b = NULL; + int r; + + r = sd_pid_get_unit(0, &unit); + if (r < 0 || !streq(unit, "systemd-udev-settle.service")) + return 0; + + log_notice("systemd-udev-settle.service is deprecated."); + + r = sd_bus_open_system(&bus); + if (r < 0) + return log_debug_errno(r, "Failed to open system bus, skipping dependency queries: %m"); + + unit_path = unit_dbus_path_from_name("systemd-udev-settle.service"); + if (!unit_path) + return -ENOMEM; + + (void) sd_bus_get_property_strv( + bus, + "org.freedesktop.systemd1", + unit_path, + "org.freedesktop.systemd1.Unit", + "WantedBy", + NULL, + &a); + + (void) sd_bus_get_property_strv( + bus, + "org.freedesktop.systemd1", + unit_path, + "org.freedesktop.systemd1.Unit", + "RequiredBy", + NULL, + &b); + + r = strv_extend_strv(&a, b, true); + if (r < 0) + return r; + + if (!strv_isempty(a)) { + _cleanup_free_ char *t = NULL; + + t = strv_join(a, ", "); + if (!t) + return -ENOMEM; + + log_notice("Hint: please fix %s not to pull it in.", t); + } + + return 0; +} + +int settle_main(int argc, char *argv[], void *userdata) { + _cleanup_(udev_queue_unrefp) struct udev_queue *queue = NULL; + struct pollfd pfd; + usec_t deadline; + int r; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + if (running_in_chroot() > 0) { + log_info("Running in chroot, ignoring request."); + return 0; + } + + deadline = now(CLOCK_MONOTONIC) + arg_timeout; + + /* guarantee that the udev daemon isn't pre-processing */ + if (getuid() == 0) { + _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL; + + if (udev_ctrl_new(&uctrl) >= 0) { + r = udev_ctrl_send_ping(uctrl); + if (r < 0) { + log_debug_errno(r, "Failed to connect to udev daemon: %m"); + return 0; + } + + r = udev_ctrl_wait(uctrl, MAX(5 * USEC_PER_SEC, arg_timeout)); + if (r < 0) + return log_error_errno(r, "Failed to wait for daemon to reply: %m"); + } + } + + queue = udev_queue_new(NULL); + if (!queue) + return log_error_errno(errno, "Failed to get udev queue: %m"); + + r = udev_queue_get_fd(queue); + if (r < 0) { + log_debug_errno(r, "Queue is empty, nothing to watch."); + return 0; + } + + pfd = (struct pollfd) { + .events = POLLIN, + .fd = r, + }; + + (void) emit_deprecation_warning(); + + for (;;) { + if (arg_exists && access(arg_exists, F_OK) >= 0) + return 0; + + /* exit if queue is empty */ + if (udev_queue_get_queue_is_empty(queue)) + return 0; + + if (now(CLOCK_MONOTONIC) >= deadline) + return -ETIMEDOUT; + + /* wake up when queue becomes empty */ + if (poll(&pfd, 1, MSEC_PER_SEC) > 0 && pfd.revents & POLLIN) { + r = udev_queue_flush(queue); + if (r < 0) + return log_error_errno(r, "Failed to flush queue: %m"); + } + } +} diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c new file mode 100644 index 00000000..eb5d3e2b --- /dev/null +++ b/src/udev/udevadm-test-builtin.c @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include +#include +#include +#include +#include + +#include "log.h" +#include "udev-builtin.h" +#include "udevadm.h" +#include "udevadm-util.h" + +static const char *arg_command = NULL; +static const char *arg_syspath = NULL; + +static int help(void) { + printf("%s test-builtin [OPTIONS] COMMAND DEVPATH\n\n" + "Test a built-in command.\n\n" + " -h --help Print this message\n" + " -V --version Print version of the program\n\n" + "Commands:\n" + , program_invocation_short_name); + + udev_builtin_list(); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + static const struct option options[] = { + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + {} + }; + + int c; + + while ((c = getopt_long(argc, argv, "Vh", options, NULL)) >= 0) + switch (c) { + case 'V': + return print_version(); + case 'h': + return help(); + case '?': + return -EINVAL; + default: + assert_not_reached("Unknown option"); + } + + arg_command = argv[optind++]; + if (!arg_command) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Command missing."); + + arg_syspath = argv[optind++]; + if (!arg_syspath) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "syspath missing."); + + return 1; +} + +int builtin_main(int argc, char *argv[], void *userdata) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + UdevBuiltinCommand cmd; + int r; + + log_set_max_level(LOG_DEBUG); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + udev_builtin_init(); + + cmd = udev_builtin_lookup(arg_command); + if (cmd < 0) { + log_error("Unknown command '%s'", arg_command); + r = -EINVAL; + goto finish; + } + + r = find_device(arg_syspath, "/sys", &dev); + if (r < 0) { + log_error_errno(r, "Failed to open device '%s': %m", arg_syspath); + goto finish; + } + + r = udev_builtin_run(dev, cmd, arg_command, true); + if (r < 0) + log_debug_errno(r, "Builtin command '%s' fails: %m", arg_command); + +finish: + udev_builtin_exit(); + return r; +} diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c new file mode 100644 index 00000000..7ad9993f --- /dev/null +++ b/src/udev/udevadm-test.c @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright © 2003-2004 Greg Kroah-Hartman + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-device.h" + +#include "device-private.h" +#include "device-util.h" +#include "libudev-util.h" +#include "string-util.h" +#include "strxcpyx.h" +#include "udev-builtin.h" +#include "udev-event.h" +#include "udevadm.h" + +static const char *arg_action = "add"; +static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY; +static char arg_syspath[UTIL_PATH_SIZE] = {}; + +static int help(void) { + + printf("%s test [OPTIONS] DEVPATH\n\n" + "Test an event run.\n\n" + " -h --help Show this help\n" + " -V --version Show package version\n" + " -a --action=ACTION|help Set action string\n" + " -N --resolve-names=early|late|never When to resolve names\n" + , program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + static const struct option options[] = { + { "action", required_argument, NULL, 'a' }, + { "resolve-names", required_argument, NULL, 'N' }, + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + {} + }; + + int c; + + while ((c = getopt_long(argc, argv, "a:N:Vh", options, NULL)) >= 0) + switch (c) { + case 'a': { + DeviceAction a; + + if (streq(optarg, "help")) { + dump_device_action_table(); + return 0; + } + + a = device_action_from_string(optarg); + if (a < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid action '%s'", optarg); + + arg_action = optarg; + break; + } + case 'N': + arg_resolve_name_timing = resolve_name_timing_from_string(optarg); + if (arg_resolve_name_timing < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--resolve-names= must be early, late or never"); + break; + case 'V': + return print_version(); + case 'h': + return help(); + case '?': + return -EINVAL; + default: + assert_not_reached("Unknown option"); + } + + if (!argv[optind]) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "syspath parameter missing."); + + /* add /sys if needed */ + if (!startswith(argv[optind], "/sys")) + strscpyl(arg_syspath, sizeof(arg_syspath), "/sys", argv[optind], NULL); + else + strscpy(arg_syspath, sizeof(arg_syspath), argv[optind]); + + return 1; +} + +int test_main(int argc, char *argv[], void *userdata) { + _cleanup_(udev_rules_freep) UdevRules *rules = NULL; + _cleanup_(udev_event_freep) UdevEvent *event = NULL; + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + const char *cmd, *key, *value; + sigset_t mask, sigmask_orig; + Iterator i; + void *val; + int r; + + log_set_max_level(LOG_DEBUG); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + printf("This program is for debugging only, it does not run any program\n" + "specified by a RUN key. It may show incorrect results, because\n" + "some values may be different, or not available at a simulation run.\n" + "\n"); + + assert_se(sigprocmask(SIG_SETMASK, NULL, &sigmask_orig) >= 0); + + udev_builtin_init(); + + r = udev_rules_new(&rules, arg_resolve_name_timing); + if (r < 0) { + log_error_errno(r, "Failed to read udev rules: %m"); + goto out; + } + + r = device_new_from_synthetic_event(&dev, arg_syspath, arg_action); + if (r < 0) { + log_error_errno(r, "Failed to open device '%s': %m", arg_syspath); + goto out; + } + + /* don't read info from the db */ + device_seal(dev); + + event = udev_event_new(dev, 0, NULL); + + assert_se(sigfillset(&mask) >= 0); + assert_se(sigprocmask(SIG_SETMASK, &mask, &sigmask_orig) >= 0); + + udev_event_execute_rules(event, 60 * USEC_PER_SEC, NULL, rules); + + FOREACH_DEVICE_PROPERTY(dev, key, value) + printf("%s=%s\n", key, value); + + ORDERED_HASHMAP_FOREACH_KEY(val, cmd, event->run_list, i) { + char program[UTIL_PATH_SIZE]; + + udev_event_apply_format(event, cmd, program, sizeof(program), false); + printf("run: '%s'\n", program); + } + + r = 0; +out: + udev_builtin_exit(); + return r; +} diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c new file mode 100644 index 00000000..60c68b50 --- /dev/null +++ b/src/udev/udevadm-trigger.c @@ -0,0 +1,391 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include +#include + +#include "sd-device.h" +#include "sd-event.h" + +#include "device-enumerator-private.h" +#include "device-private.h" +#include "fd-util.h" +#include "fileio.h" +#include "path-util.h" +#include "process-util.h" +#include "set.h" +#include "string-util.h" +#include "strv.h" +#include "udevadm.h" +#include "udevadm-util.h" +#include "udev-ctrl.h" +#include "virt.h" + +static bool arg_verbose = false; +static bool arg_dry_run = false; + +static int exec_list(sd_device_enumerator *e, const char *action, Set *settle_set) { + sd_device *d; + int r, ret = 0; + + FOREACH_DEVICE_AND_SUBSYSTEM(e, d) { + _cleanup_free_ char *filename = NULL; + const char *syspath; + + if (sd_device_get_syspath(d, &syspath) < 0) + continue; + + if (arg_verbose) + printf("%s\n", syspath); + if (arg_dry_run) + continue; + + filename = path_join(syspath, "uevent"); + if (!filename) + return log_oom(); + + r = write_string_file(filename, action, WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) { + bool ignore = IN_SET(r, -ENOENT, -EACCES, -ENODEV, -EROFS); + + log_full_errno(ignore ? LOG_DEBUG : LOG_ERR, r, + "Failed to write '%s' to '%s'%s: %m", + action, filename, ignore ? ", ignoring" : ""); + if (r == -EROFS) + return 0; /* Read only filesystem. Return earlier. */ + if (ret == 0 && !ignore) + ret = r; + continue; + } + + if (settle_set) { + r = set_put_strdup(settle_set, syspath); + if (r < 0) + return log_oom(); + } + } + + return ret; +} + +static int device_monitor_handler(sd_device_monitor *m, sd_device *dev, void *userdata) { + _cleanup_free_ char *val = NULL; + Set *settle_set = userdata; + const char *syspath; + + assert(dev); + assert(settle_set); + + if (sd_device_get_syspath(dev, &syspath) < 0) + return 0; + + if (arg_verbose) + printf("settle %s\n", syspath); + + val = set_remove(settle_set, syspath); + if (!val) + log_debug("Got epoll event on syspath %s not present in syspath set", syspath); + + if (set_isempty(settle_set)) + return sd_event_exit(sd_device_monitor_get_event(m), 0); + + return 0; +} + +static char* keyval(const char *str, const char **key, const char **val) { + char *buf, *pos; + + buf = strdup(str); + if (!buf) + return NULL; + + pos = strchr(buf, '='); + if (pos) { + pos[0] = 0; + pos++; + } + + *key = buf; + *val = pos; + + return buf; +} + +static int help(void) { + printf("%s trigger [OPTIONS] DEVPATH\n\n" + "Request events from the kernel.\n\n" + " -h --help Show this help\n" + " -V --version Show package version\n" + " -v --verbose Print the list of devices while running\n" + " -n --dry-run Do not actually trigger the events\n" + " -t --type= Type of events to trigger\n" + " devices sysfs devices (default)\n" + " subsystems sysfs subsystems and drivers\n" + " -c --action=ACTION|help Event action value, default is \"change\"\n" + " -s --subsystem-match=SUBSYSTEM Trigger devices from a matching subsystem\n" + " -S --subsystem-nomatch=SUBSYSTEM Exclude devices from a matching subsystem\n" + " -a --attr-match=FILE[=VALUE] Trigger devices with a matching attribute\n" + " -A --attr-nomatch=FILE[=VALUE] Exclude devices with a matching attribute\n" + " -p --property-match=KEY=VALUE Trigger devices with a matching property\n" + " -g --tag-match=KEY=VALUE Trigger devices with a matching property\n" + " -y --sysname-match=NAME Trigger devices with this /sys path\n" + " --name-match=NAME Trigger devices with this /dev name\n" + " -b --parent-match=NAME Trigger devices with that parent device\n" + " -w --settle Wait for the triggered events to complete\n" + " --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n" + " before triggering uevents\n" + , program_invocation_short_name); + + return 0; +} + +int trigger_main(int argc, char *argv[], void *userdata) { + enum { + ARG_NAME = 0x100, + ARG_PING, + }; + + static const struct option options[] = { + { "verbose", no_argument, NULL, 'v' }, + { "dry-run", no_argument, NULL, 'n' }, + { "type", required_argument, NULL, 't' }, + { "action", required_argument, NULL, 'c' }, + { "subsystem-match", required_argument, NULL, 's' }, + { "subsystem-nomatch", required_argument, NULL, 'S' }, + { "attr-match", required_argument, NULL, 'a' }, + { "attr-nomatch", required_argument, NULL, 'A' }, + { "property-match", required_argument, NULL, 'p' }, + { "tag-match", required_argument, NULL, 'g' }, + { "sysname-match", required_argument, NULL, 'y' }, + { "name-match", required_argument, NULL, ARG_NAME }, + { "parent-match", required_argument, NULL, 'b' }, + { "settle", no_argument, NULL, 'w' }, + { "wait-daemon", optional_argument, NULL, ARG_PING }, + { "version", no_argument, NULL, 'V' }, + { "help", no_argument, NULL, 'h' }, + {} + }; + enum { + TYPE_DEVICES, + TYPE_SUBSYSTEMS, + } device_type = TYPE_DEVICES; + const char *action = "change"; + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_set_free_free_ Set *settle_set = NULL; + usec_t ping_timeout_usec = 5 * USEC_PER_SEC; + bool settle = false, ping = false; + int c, r; + + if (running_in_chroot() > 0) { + log_info("Running in chroot, ignoring request."); + return 0; + } + + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + while ((c = getopt_long(argc, argv, "vnt:c:s:S:a:A:p:g:y:b:wVh", options, NULL)) >= 0) { + _cleanup_free_ char *buf = NULL; + const char *key, *val; + + switch (c) { + case 'v': + arg_verbose = true; + break; + case 'n': + arg_dry_run = true; + break; + case 't': + if (streq(optarg, "devices")) + device_type = TYPE_DEVICES; + else if (streq(optarg, "subsystems")) + device_type = TYPE_SUBSYSTEMS; + else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown type --type=%s", optarg); + break; + case 'c': + if (streq(optarg, "help")) { + dump_device_action_table(); + return 0; + } + if (device_action_from_string(optarg) < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown action '%s'", optarg); + + action = optarg; + break; + case 's': + r = sd_device_enumerator_add_match_subsystem(e, optarg, true); + if (r < 0) + return log_error_errno(r, "Failed to add subsystem match '%s': %m", optarg); + break; + case 'S': + r = sd_device_enumerator_add_match_subsystem(e, optarg, false); + if (r < 0) + return log_error_errno(r, "Failed to add negative subsystem match '%s': %m", optarg); + break; + case 'a': + buf = keyval(optarg, &key, &val); + if (!buf) + return log_oom(); + r = sd_device_enumerator_add_match_sysattr(e, key, val, true); + if (r < 0) + return log_error_errno(r, "Failed to add sysattr match '%s=%s': %m", key, val); + break; + case 'A': + buf = keyval(optarg, &key, &val); + if (!buf) + return log_oom(); + r = sd_device_enumerator_add_match_sysattr(e, key, val, false); + if (r < 0) + return log_error_errno(r, "Failed to add negative sysattr match '%s=%s': %m", key, val); + break; + case 'p': + buf = keyval(optarg, &key, &val); + if (!buf) + return log_oom(); + r = sd_device_enumerator_add_match_property(e, key, val); + if (r < 0) + return log_error_errno(r, "Failed to add property match '%s=%s': %m", key, val); + break; + case 'g': + r = sd_device_enumerator_add_match_tag(e, optarg); + if (r < 0) + return log_error_errno(r, "Failed to add tag match '%s': %m", optarg); + break; + case 'y': + r = sd_device_enumerator_add_match_sysname(e, optarg); + if (r < 0) + return log_error_errno(r, "Failed to add sysname match '%s': %m", optarg); + break; + case 'b': { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + + r = find_device(optarg, "/sys", &dev); + if (r < 0) + return log_error_errno(r, "Failed to open the device '%s': %m", optarg); + + r = device_enumerator_add_match_parent_incremental(e, dev); + if (r < 0) + return log_error_errno(r, "Failed to add parent match '%s': %m", optarg); + break; + } + case 'w': + settle = true; + break; + + case ARG_NAME: { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + + r = find_device(optarg, "/dev/", &dev); + if (r < 0) + return log_error_errno(r, "Failed to open the device '%s': %m", optarg); + + r = device_enumerator_add_match_parent_incremental(e, dev); + if (r < 0) + return log_error_errno(r, "Failed to add parent match '%s': %m", optarg); + break; + } + + case ARG_PING: { + ping = true; + if (optarg) { + r = parse_sec(optarg, &ping_timeout_usec); + if (r < 0) + log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", optarg); + } + break; + } + + case 'V': + return print_version(); + case 'h': + return help(); + case '?': + return -EINVAL; + default: + assert_not_reached("Unknown option"); + } + } + + if (ping) { + _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL; + + r = udev_ctrl_new(&uctrl); + if (r < 0) + return log_error_errno(r, "Failed to initialize udev control: %m"); + + r = udev_ctrl_send_ping(uctrl); + if (r < 0) + return log_error_errno(r, "Failed to connect to udev daemon: %m"); + + r = udev_ctrl_wait(uctrl, ping_timeout_usec); + if (r < 0) + return log_error_errno(r, "Failed to wait for daemon to reply: %m"); + } + + for (; optind < argc; optind++) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + + r = find_device(argv[optind], NULL, &dev); + if (r < 0) + return log_error_errno(r, "Failed to open the device '%s': %m", argv[optind]); + + r = device_enumerator_add_match_parent_incremental(e, dev); + if (r < 0) + return log_error_errno(r, "Failed to add parent match '%s': %m", argv[optind]); + } + + if (settle) { + settle_set = set_new(&string_hash_ops); + if (!settle_set) + return log_oom(); + + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to get default event: %m"); + + r = sd_device_monitor_new(&m); + if (r < 0) + return log_error_errno(r, "Failed to create device monitor object: %m"); + + r = sd_device_monitor_attach_event(m, event); + if (r < 0) + return log_error_errno(r, "Failed to attach event to device monitor: %m"); + + r = sd_device_monitor_start(m, device_monitor_handler, settle_set); + if (r < 0) + return log_error_errno(r, "Failed to start device monitor: %m"); + } + + switch (device_type) { + case TYPE_SUBSYSTEMS: + r = device_enumerator_scan_subsystems(e); + if (r < 0) + return log_error_errno(r, "Failed to scan subsystems: %m"); + break; + case TYPE_DEVICES: + r = device_enumerator_scan_devices(e); + if (r < 0) + return log_error_errno(r, "Failed to scan devices: %m"); + break; + default: + assert_not_reached("Unknown device type"); + } + r = exec_list(e, action, settle_set); + if (r < 0) + return r; + + if (event && !set_isempty(settle_set)) { + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); + } + + return 0; +} diff --git a/src/udev/udevadm-util.c b/src/udev/udevadm-util.c new file mode 100644 index 00000000..557982b2 --- /dev/null +++ b/src/udev/udevadm-util.c @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include + +#include "alloc-util.h" +#include "device-private.h" +#include "path-util.h" +#include "udevadm-util.h" +#include "unit-name.h" + +int find_device(const char *id, const char *prefix, sd_device **ret) { + _cleanup_free_ char *path = NULL; + int r; + + assert(id); + assert(ret); + + if (prefix) { + if (!path_startswith(id, prefix)) { + id = path = path_join(prefix, id); + if (!path) + return -ENOMEM; + } + } else { + /* In cases where the argument is generic (no prefix specified), + * check if the argument looks like a device unit name. */ + if (unit_name_is_valid(id, UNIT_NAME_PLAIN) && + unit_name_to_type(id) == UNIT_DEVICE) { + r = unit_name_to_path(id, &path); + if (r < 0) + return log_debug_errno(r, "Failed to convert \"%s\" to a device path: %m", id); + id = path; + } + } + + if (path_startswith(id, "/sys/")) + return sd_device_new_from_syspath(ret, id); + + if (path_startswith(id, "/dev/")) { + struct stat st; + + if (stat(id, &st) < 0) + return -errno; + + return device_new_from_stat_rdev(ret, &st); + } + + return -EINVAL; +} diff --git a/src/udev/udevadm-util.h b/src/udev/udevadm-util.h new file mode 100644 index 00000000..59e89022 --- /dev/null +++ b/src/udev/udevadm-util.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +#include "sd-device.h" + +int find_device(const char *id, const char *prefix, sd_device **ret); diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c new file mode 100644 index 00000000..e6dbb111 --- /dev/null +++ b/src/udev/udevadm.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include +#include +#include +#include + +#include "alloc-util.h" +#include "main-func.h" +#include "pretty-print.h" +#include "selinux-util.h" +#include "string-util.h" +#include "udevadm.h" +#include "udev-util.h" +#include "verbs.h" +#include "util.h" + +static int help(void) { + static const char *const short_descriptions[][2] = { + { "info", "Query sysfs or the udev database" }, + { "trigger", "Request events from the kernel" }, + { "settle", "Wait for pending udev events" }, + { "control", "Control the udev daemon" }, + { "monitor", "Listen to kernel and udev events" }, + { "test", "Test an event run" }, + { "test-builtin", "Test a built-in command" }, + }; + + _cleanup_free_ char *link = NULL; + size_t i; + int r; + + r = terminal_urlify_man("udevadm", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n\n" + "Send control commands or test the device manager.\n\n" + "Commands:\n" + , program_invocation_short_name); + + for (i = 0; i < ELEMENTSOF(short_descriptions); i++) + printf(" %-12s %s\n", short_descriptions[i][0], short_descriptions[i][1]); + + printf("\nSee the %s for details.\n", link); + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + static const struct option options[] = { + { "debug", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + {} + }; + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0) + switch (c) { + + case 'd': + log_set_max_level(LOG_DEBUG); + break; + + case 'h': + return help(); + + case 'V': + return print_version(); + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + return 1; /* work to do */ +} + +static int version_main(int argc, char *argv[], void *userdata) { + return print_version(); +} + +static int help_main(int argc, char *argv[], void *userdata) { + return help(); +} + +static int udevadm_main(int argc, char *argv[]) { + static const Verb verbs[] = { + { "info", VERB_ANY, VERB_ANY, 0, info_main }, + { "trigger", VERB_ANY, VERB_ANY, 0, trigger_main }, + { "settle", VERB_ANY, VERB_ANY, 0, settle_main }, + { "control", VERB_ANY, VERB_ANY, 0, control_main }, + { "monitor", VERB_ANY, VERB_ANY, 0, monitor_main }, + { "hwdb", VERB_ANY, VERB_ANY, 0, hwdb_main }, + { "test", VERB_ANY, VERB_ANY, 0, test_main }, + { "test-builtin", VERB_ANY, VERB_ANY, 0, builtin_main }, + { "version", VERB_ANY, VERB_ANY, 0, version_main }, + { "help", VERB_ANY, VERB_ANY, 0, help_main }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + +static int run(int argc, char *argv[]) { + int r; + + udev_parse_config(); + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level()); + + mac_selinux_init(); + return udevadm_main(argc, argv); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/udev/udevadm.h b/src/udev/udevadm.h new file mode 100644 index 00000000..86b24af0 --- /dev/null +++ b/src/udev/udevadm.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#pragma once + +#include + +#include "build.h" +#include "macro.h" + +int info_main(int argc, char *argv[], void *userdata); +int trigger_main(int argc, char *argv[], void *userdata); +int settle_main(int argc, char *argv[], void *userdata); +int control_main(int argc, char *argv[], void *userdata); +int monitor_main(int argc, char *argv[], void *userdata); +int hwdb_main(int argc, char *argv[], void *userdata); +int test_main(int argc, char *argv[], void *userdata); +int builtin_main(int argc, char *argv[], void *userdata); + +static inline int print_version(void) { + /* Dracut relies on the version being a single integer */ + puts(STRINGIFY(PROJECT_VERSION)); + return 0; +} diff --git a/src/udev/udevd.c b/src/udev/udevd.c new file mode 100644 index 00000000..76783318 --- /dev/null +++ b/src/udev/udevd.c @@ -0,0 +1,1819 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright © 2004 Chris Friesen + * Copyright © 2009 Canonical Ltd. + * Copyright © 2009 Scott James Remnant + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-daemon.h" +#include "sd-event.h" + +#include "alloc-util.h" +#include "build.h" +#include "cgroup-util.h" +#include "cpu-set-util.h" +#include "dev-setup.h" +#include "device-monitor-private.h" +#include "device-private.h" +#include "device-util.h" +#include "event-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "format-util.h" +#include "fs-util.h" +#include "hashmap.h" +#include "io-util.h" +#include "libudev-device-internal.h" +#include "limits-util.h" +#include "list.h" +#include "main-func.h" +#include "mkdir.h" +#include "netlink-util.h" +#include "parse-util.h" +#include "pretty-print.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "selinux-util.h" +#include "signal-util.h" +#include "socket-util.h" +#include "string-util.h" +#include "strv.h" +#include "strxcpyx.h" +#include "syslog-util.h" +#include "udev-builtin.h" +#include "udev-ctrl.h" +#include "udev-event.h" +#include "udev-util.h" +#include "udev-watch.h" +#include "user-util.h" + +#define WORKER_NUM_MAX 2048U + +static bool arg_debug = false; +static int arg_daemonize = false; +static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY; +static unsigned arg_children_max = 0; +static usec_t arg_exec_delay_usec = 0; +static usec_t arg_event_timeout_usec = 180 * USEC_PER_SEC; + +typedef struct Manager { + sd_event *event; + Hashmap *workers; + LIST_HEAD(struct event, events); + const char *cgroup; + pid_t pid; /* the process that originally allocated the manager object */ + + UdevRules *rules; + Hashmap *properties; + + sd_netlink *rtnl; + + sd_device_monitor *monitor; + struct udev_ctrl *ctrl; + int fd_inotify; + int worker_watch[2]; + + sd_event_source *inotify_event; + sd_event_source *kill_workers_event; + + usec_t last_usec; + + bool stop_exec_queue:1; + bool exit:1; +} Manager; + +enum event_state { + EVENT_UNDEF, + EVENT_QUEUED, + EVENT_RUNNING, +}; + +struct event { + Manager *manager; + struct worker *worker; + enum event_state state; + + sd_device *dev; + sd_device *dev_kernel; /* clone of originally received device */ + + uint64_t seqnum; + uint64_t delaying_seqnum; + + sd_event_source *timeout_warning_event; + sd_event_source *timeout_event; + + LIST_FIELDS(struct event, event); +}; + +static void event_queue_cleanup(Manager *manager, enum event_state type); + +enum worker_state { + WORKER_UNDEF, + WORKER_RUNNING, + WORKER_IDLE, + WORKER_KILLED, +}; + +struct worker { + Manager *manager; + pid_t pid; + sd_device_monitor *monitor; + enum worker_state state; + struct event *event; +}; + +/* passed from worker to main process */ +struct worker_message { +}; + +static void event_free(struct event *event) { + if (!event) + return; + + assert(event->manager); + + LIST_REMOVE(event, event->manager->events, event); + sd_device_unref(event->dev); + sd_device_unref(event->dev_kernel); + + sd_event_source_unref(event->timeout_warning_event); + sd_event_source_unref(event->timeout_event); + + if (event->worker) + event->worker->event = NULL; + + /* only clean up the queue from the process that created it */ + if (LIST_IS_EMPTY(event->manager->events) && + event->manager->pid == getpid_cached()) + if (unlink("/run/udev/queue") < 0) + log_warning_errno(errno, "Failed to unlink /run/udev/queue: %m"); + + free(event); +} + +static void worker_free(struct worker *worker) { + if (!worker) + return; + + assert(worker->manager); + + hashmap_remove(worker->manager->workers, PID_TO_PTR(worker->pid)); + sd_device_monitor_unref(worker->monitor); + event_free(worker->event); + + free(worker); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct worker *, worker_free); +DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(worker_hash_op, void, trivial_hash_func, trivial_compare_func, struct worker, worker_free); + +static int worker_new(struct worker **ret, Manager *manager, sd_device_monitor *worker_monitor, pid_t pid) { + _cleanup_(worker_freep) struct worker *worker = NULL; + int r; + + assert(ret); + assert(manager); + assert(worker_monitor); + assert(pid > 1); + + /* close monitor, but keep address around */ + device_monitor_disconnect(worker_monitor); + + worker = new(struct worker, 1); + if (!worker) + return -ENOMEM; + + *worker = (struct worker) { + .manager = manager, + .monitor = sd_device_monitor_ref(worker_monitor), + .pid = pid, + }; + + r = hashmap_ensure_allocated(&manager->workers, &worker_hash_op); + if (r < 0) + return r; + + r = hashmap_put(manager->workers, PID_TO_PTR(pid), worker); + if (r < 0) + return r; + + *ret = TAKE_PTR(worker); + + return 0; +} + +static int on_event_timeout(sd_event_source *s, uint64_t usec, void *userdata) { + struct event *event = userdata; + + assert(event); + assert(event->worker); + + kill_and_sigcont(event->worker->pid, SIGKILL); + event->worker->state = WORKER_KILLED; + + log_device_error(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" killed", event->worker->pid, event->seqnum); + + return 1; +} + +static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) { + struct event *event = userdata; + + assert(event); + assert(event->worker); + + log_device_warning(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" is taking a long time", event->worker->pid, event->seqnum); + + return 1; +} + +static void worker_attach_event(struct worker *worker, struct event *event) { + sd_event *e; + uint64_t usec; + + assert(worker); + assert(worker->manager); + assert(event); + assert(!event->worker); + assert(!worker->event); + + worker->state = WORKER_RUNNING; + worker->event = event; + event->state = EVENT_RUNNING; + event->worker = worker; + + e = worker->manager->event; + + assert_se(sd_event_now(e, CLOCK_MONOTONIC, &usec) >= 0); + + (void) sd_event_add_time(e, &event->timeout_warning_event, CLOCK_MONOTONIC, + usec + udev_warn_timeout(arg_event_timeout_usec), USEC_PER_SEC, on_event_timeout_warning, event); + + (void) sd_event_add_time(e, &event->timeout_event, CLOCK_MONOTONIC, + usec + arg_event_timeout_usec, USEC_PER_SEC, on_event_timeout, event); +} + +static void manager_clear_for_worker(Manager *manager) { + assert(manager); + + manager->inotify_event = sd_event_source_unref(manager->inotify_event); + manager->kill_workers_event = sd_event_source_unref(manager->kill_workers_event); + + manager->event = sd_event_unref(manager->event); + + manager->workers = hashmap_free(manager->workers); + event_queue_cleanup(manager, EVENT_UNDEF); + + manager->monitor = sd_device_monitor_unref(manager->monitor); + manager->ctrl = udev_ctrl_unref(manager->ctrl); + + manager->worker_watch[READ_END] = safe_close(manager->worker_watch[READ_END]); +} + +static void manager_free(Manager *manager) { + if (!manager) + return; + + udev_builtin_exit(); + + if (manager->pid == getpid_cached()) + udev_ctrl_cleanup(manager->ctrl); + + manager_clear_for_worker(manager); + + sd_netlink_unref(manager->rtnl); + + hashmap_free_free_free(manager->properties); + udev_rules_free(manager->rules); + + safe_close(manager->fd_inotify); + safe_close_pair(manager->worker_watch); + + free(manager); +} + +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); + +static int worker_send_message(int fd) { + struct worker_message message = {}; + + return loop_write(fd, &message, sizeof(message), false); +} + +static int worker_lock_block_device(sd_device *dev, int *ret_fd) { + _cleanup_close_ int fd = -1; + const char *val; + int r; + + assert(dev); + assert(ret_fd); + + /* + * Take a shared lock on the device node; this establishes + * a concept of device "ownership" to serialize device + * access. External processes holding an exclusive lock will + * cause udev to skip the event handling; in the case udev + * acquired the lock, the external process can block until + * udev has finished its event handling. + */ + + if (device_for_action(dev, DEVICE_ACTION_REMOVE)) + return 0; + + r = sd_device_get_subsystem(dev, &val); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get subsystem: %m"); + + if (!streq(val, "block")) + return 0; + + r = sd_device_get_sysname(dev, &val); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get sysname: %m"); + + if (STARTSWITH_SET(val, "dm-", "md", "drbd")) + return 0; + + r = sd_device_get_devtype(dev, &val); + if (r < 0 && r != -ENOENT) + return log_device_debug_errno(dev, r, "Failed to get devtype: %m"); + if (r >= 0 && streq(val, "partition")) { + r = sd_device_get_parent(dev, &dev); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get parent device: %m"); + } + + r = sd_device_get_devname(dev, &val); + if (r == -ENOENT) + return 0; + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get devname: %m"); + + fd = open(val, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK); + if (fd < 0) { + log_device_debug_errno(dev, errno, "Failed to open '%s', ignoring: %m", val); + return 0; + } + + if (flock(fd, LOCK_SH|LOCK_NB) < 0) + return log_device_debug_errno(dev, errno, "Failed to flock(%s): %m", val); + + *ret_fd = TAKE_FD(fd); + return 1; +} + +static int worker_process_device(Manager *manager, sd_device *dev) { + _cleanup_(udev_event_freep) UdevEvent *udev_event = NULL; + _cleanup_close_ int fd_lock = -1; + DeviceAction action; + uint64_t seqnum; + int r; + + assert(manager); + assert(dev); + + r = device_get_seqnum(dev, &seqnum); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get SEQNUM: %m"); + + r = device_get_action(dev, &action); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to get ACTION: %m"); + + log_device_debug(dev, "Processing device (SEQNUM=%"PRIu64", ACTION=%s)", + seqnum, device_action_to_string(action)); + + udev_event = udev_event_new(dev, arg_exec_delay_usec, manager->rtnl); + if (!udev_event) + return -ENOMEM; + + r = worker_lock_block_device(dev, &fd_lock); + if (r < 0) + return r; + + /* apply rules, create node, symlinks */ + r = udev_event_execute_rules(udev_event, arg_event_timeout_usec, manager->properties, manager->rules); + if (r < 0) + return r; + + udev_event_execute_run(udev_event, arg_event_timeout_usec); + + if (!manager->rtnl) + /* in case rtnl was initialized */ + manager->rtnl = sd_netlink_ref(udev_event->rtnl); + + /* apply/restore inotify watch */ + if (udev_event->inotify_watch) { + (void) udev_watch_begin(dev); + r = device_update_db(dev); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m"); + } + + log_device_debug(dev, "Device (SEQNUM=%"PRIu64", ACTION=%s) processed", + seqnum, device_action_to_string(action)); + + return 0; +} + +static int worker_device_monitor_handler(sd_device_monitor *monitor, sd_device *dev, void *userdata) { + Manager *manager = userdata; + int r; + + assert(dev); + assert(manager); + + r = worker_process_device(manager, dev); + if (r < 0) + log_device_warning_errno(dev, r, "Failed to process device, ignoring: %m"); + + /* send processed event back to libudev listeners */ + r = device_monitor_send_device(monitor, NULL, dev); + if (r < 0) + log_device_warning_errno(dev, r, "Failed to send device, ignoring: %m"); + + /* send udevd the result of the event execution */ + r = worker_send_message(manager->worker_watch[WRITE_END]); + if (r < 0) + log_device_warning_errno(dev, r, "Failed to send signal to main daemon, ignoring: %m"); + + return 1; +} + +static int worker_main(Manager *_manager, sd_device_monitor *monitor, sd_device *first_device) { + _cleanup_(sd_device_unrefp) sd_device *dev = first_device; + _cleanup_(manager_freep) Manager *manager = _manager; + int r; + + assert(manager); + assert(monitor); + assert(dev); + + unsetenv("NOTIFY_SOCKET"); + + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, -1) >= 0); + + /* Reset OOM score, we only protect the main daemon. */ + r = set_oom_score_adjust(0); + if (r < 0) + log_debug_errno(r, "Failed to reset OOM score, ignoring: %m"); + + /* Clear unnecessary data in Manager object.*/ + manager_clear_for_worker(manager); + + r = sd_event_new(&manager->event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + r = sd_event_add_signal(manager->event, NULL, SIGTERM, NULL, NULL); + if (r < 0) + return log_error_errno(r, "Failed to set SIGTERM event: %m"); + + r = sd_device_monitor_attach_event(monitor, manager->event); + if (r < 0) + return log_error_errno(r, "Failed to attach event loop to device monitor: %m"); + + r = sd_device_monitor_start(monitor, worker_device_monitor_handler, manager); + if (r < 0) + return log_error_errno(r, "Failed to start device monitor: %m"); + + (void) sd_event_source_set_description(sd_device_monitor_get_event_source(monitor), "worker-device-monitor"); + + /* Process first device */ + (void) worker_device_monitor_handler(monitor, dev, manager); + + r = sd_event_loop(manager->event); + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); + + return 0; +} + +static int worker_spawn(Manager *manager, struct event *event) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *worker_monitor = NULL; + struct worker *worker; + pid_t pid; + int r; + + /* listen for new events */ + r = device_monitor_new_full(&worker_monitor, MONITOR_GROUP_NONE, -1); + if (r < 0) + return r; + + /* allow the main daemon netlink address to send devices to the worker */ + r = device_monitor_allow_unicast_sender(worker_monitor, manager->monitor); + if (r < 0) + return log_error_errno(r, "Worker: Failed to set unicast sender: %m"); + + r = device_monitor_enable_receiving(worker_monitor); + if (r < 0) + return log_error_errno(r, "Worker: Failed to enable receiving of device: %m"); + + r = safe_fork(NULL, FORK_DEATHSIG, &pid); + if (r < 0) { + event->state = EVENT_QUEUED; + return log_error_errno(r, "Failed to fork() worker: %m"); + } + if (r == 0) { + /* Worker process */ + r = worker_main(manager, worker_monitor, sd_device_ref(event->dev)); + log_close(); + _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); + } + + r = worker_new(&worker, manager, worker_monitor, pid); + if (r < 0) + return log_error_errno(r, "Failed to create worker object: %m"); + + worker_attach_event(worker, event); + + log_device_debug(event->dev, "Worker ["PID_FMT"] is forked for processing SEQNUM=%"PRIu64".", pid, event->seqnum); + return 0; +} + +static void event_run(Manager *manager, struct event *event) { + static bool log_children_max_reached = true; + struct worker *worker; + Iterator i; + int r; + + assert(manager); + assert(event); + + HASHMAP_FOREACH(worker, manager->workers, i) { + if (worker->state != WORKER_IDLE) + continue; + + r = device_monitor_send_device(manager->monitor, worker->monitor, event->dev); + if (r < 0) { + log_device_error_errno(event->dev, r, "Worker ["PID_FMT"] did not accept message, killing the worker: %m", + worker->pid); + (void) kill(worker->pid, SIGKILL); + worker->state = WORKER_KILLED; + continue; + } + worker_attach_event(worker, event); + return; + } + + if (hashmap_size(manager->workers) >= arg_children_max) { + + /* Avoid spamming the debug logs if the limit is already reached and + * many events still need to be processed */ + if (log_children_max_reached && arg_children_max > 1) { + log_debug("Maximum number (%u) of children reached.", hashmap_size(manager->workers)); + log_children_max_reached = false; + } + return; + } + + /* Re-enable the debug message for the next batch of events */ + log_children_max_reached = true; + + /* start new worker and pass initial device */ + worker_spawn(manager, event); +} + +static int event_queue_insert(Manager *manager, sd_device *dev) { + _cleanup_(sd_device_unrefp) sd_device *clone = NULL; + struct event *event; + DeviceAction action; + uint64_t seqnum; + int r; + + assert(manager); + assert(dev); + + /* only one process can add events to the queue */ + assert(manager->pid == getpid_cached()); + + /* We only accepts devices received by device monitor. */ + r = device_get_seqnum(dev, &seqnum); + if (r < 0) + return r; + + /* Refuse devices do not have ACTION property. */ + r = device_get_action(dev, &action); + if (r < 0) + return r; + + /* Save original device to restore the state on failures. */ + r = device_shallow_clone(dev, &clone); + if (r < 0) + return r; + + r = device_copy_properties(clone, dev); + if (r < 0) + return r; + + event = new(struct event, 1); + if (!event) + return -ENOMEM; + + *event = (struct event) { + .manager = manager, + .dev = sd_device_ref(dev), + .dev_kernel = TAKE_PTR(clone), + .seqnum = seqnum, + .state = EVENT_QUEUED, + }; + + if (LIST_IS_EMPTY(manager->events)) { + r = touch("/run/udev/queue"); + if (r < 0) + log_warning_errno(r, "Failed to touch /run/udev/queue: %m"); + } + + LIST_APPEND(event, manager->events, event); + + log_device_debug(dev, "Device (SEQNUM=%"PRIu64", ACTION=%s) is queued", + seqnum, device_action_to_string(action)); + + return 0; +} + +static void manager_kill_workers(Manager *manager) { + struct worker *worker; + Iterator i; + + assert(manager); + + HASHMAP_FOREACH(worker, manager->workers, i) { + if (worker->state == WORKER_KILLED) + continue; + + worker->state = WORKER_KILLED; + (void) kill(worker->pid, SIGTERM); + } +} + +/* lookup event for identical, parent, child device */ +static int is_device_busy(Manager *manager, struct event *event) { + const char *subsystem, *devpath, *devpath_old = NULL; + dev_t devnum = makedev(0, 0); + struct event *loop_event; + size_t devpath_len; + int r, ifindex = 0; + bool is_block; + + r = sd_device_get_subsystem(event->dev, &subsystem); + if (r < 0) + return r; + + is_block = streq(subsystem, "block"); + + r = sd_device_get_devpath(event->dev, &devpath); + if (r < 0) + return r; + + devpath_len = strlen(devpath); + + r = sd_device_get_property_value(event->dev, "DEVPATH_OLD", &devpath_old); + if (r < 0 && r != -ENOENT) + return r; + + r = sd_device_get_devnum(event->dev, &devnum); + if (r < 0 && r != -ENOENT) + return r; + + r = sd_device_get_ifindex(event->dev, &ifindex); + if (r < 0 && r != -ENOENT) + return r; + + /* check if queue contains events we depend on */ + LIST_FOREACH(event, loop_event, manager->events) { + size_t loop_devpath_len, common; + const char *loop_devpath; + + /* we already found a later event, earlier cannot block us, no need to check again */ + if (loop_event->seqnum < event->delaying_seqnum) + continue; + + /* event we checked earlier still exists, no need to check again */ + if (loop_event->seqnum == event->delaying_seqnum) + return true; + + /* found ourself, no later event can block us */ + if (loop_event->seqnum >= event->seqnum) + break; + + /* check major/minor */ + if (major(devnum) != 0) { + const char *s; + dev_t d; + + if (sd_device_get_subsystem(loop_event->dev, &s) < 0) + continue; + + if (sd_device_get_devnum(loop_event->dev, &d) >= 0 && + devnum == d && is_block == streq(s, "block")) + goto set_delaying_seqnum; + } + + /* check network device ifindex */ + if (ifindex > 0) { + int i; + + if (sd_device_get_ifindex(loop_event->dev, &i) >= 0 && + ifindex == i) + goto set_delaying_seqnum; + } + + if (sd_device_get_devpath(loop_event->dev, &loop_devpath) < 0) + continue; + + /* check our old name */ + if (devpath_old && streq(devpath_old, loop_devpath)) + goto set_delaying_seqnum; + + loop_devpath_len = strlen(loop_devpath); + + /* compare devpath */ + common = MIN(devpath_len, loop_devpath_len); + + /* one devpath is contained in the other? */ + if (!strneq(devpath, loop_devpath, common)) + continue; + + /* identical device event found */ + if (devpath_len == loop_devpath_len) + goto set_delaying_seqnum; + + /* parent device event found */ + if (devpath[common] == '/') + goto set_delaying_seqnum; + + /* child device event found */ + if (loop_devpath[common] == '/') + goto set_delaying_seqnum; + } + + return false; + +set_delaying_seqnum: + event->delaying_seqnum = loop_event->seqnum; + return true; +} + +static void manager_exit(Manager *manager) { + assert(manager); + + manager->exit = true; + + sd_notify(false, + "STOPPING=1\n" + "STATUS=Starting shutdown..."); + + /* close sources of new events and discard buffered events */ + manager->ctrl = udev_ctrl_unref(manager->ctrl); + + manager->inotify_event = sd_event_source_unref(manager->inotify_event); + manager->fd_inotify = safe_close(manager->fd_inotify); + + manager->monitor = sd_device_monitor_unref(manager->monitor); + + /* discard queued events and kill workers */ + event_queue_cleanup(manager, EVENT_QUEUED); + manager_kill_workers(manager); +} + +/* reload requested, HUP signal received, rules changed, builtin changed */ +static void manager_reload(Manager *manager) { + + assert(manager); + + sd_notify(false, + "RELOADING=1\n" + "STATUS=Flushing configuration..."); + + manager_kill_workers(manager); + manager->rules = udev_rules_free(manager->rules); + udev_builtin_exit(); + + sd_notifyf(false, + "READY=1\n" + "STATUS=Processing with %u children at max", arg_children_max); +} + +static int on_kill_workers_event(sd_event_source *s, uint64_t usec, void *userdata) { + Manager *manager = userdata; + + assert(manager); + + log_debug("Cleanup idle workers"); + manager_kill_workers(manager); + + return 1; +} + +static void event_queue_start(Manager *manager) { + struct event *event; + usec_t usec; + int r; + + assert(manager); + + if (LIST_IS_EMPTY(manager->events) || + manager->exit || manager->stop_exec_queue) + return; + + assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0); + /* check for changed config, every 3 seconds at most */ + if (manager->last_usec == 0 || + usec - manager->last_usec > 3 * USEC_PER_SEC) { + if (udev_rules_check_timestamp(manager->rules) || + udev_builtin_validate()) + manager_reload(manager); + + manager->last_usec = usec; + } + + r = event_source_disable(manager->kill_workers_event); + if (r < 0) + log_warning_errno(r, "Failed to disable event source for cleaning up idle workers, ignoring: %m"); + + udev_builtin_init(); + + if (!manager->rules) { + r = udev_rules_new(&manager->rules, arg_resolve_name_timing); + if (r < 0) { + log_warning_errno(r, "Failed to read udev rules: %m"); + return; + } + } + + LIST_FOREACH(event, event, manager->events) { + if (event->state != EVENT_QUEUED) + continue; + + /* do not start event if parent or child event is still running */ + if (is_device_busy(manager, event) != 0) + continue; + + event_run(manager, event); + } +} + +static void event_queue_cleanup(Manager *manager, enum event_state match_type) { + struct event *event, *tmp; + + LIST_FOREACH_SAFE(event, event, tmp, manager->events) { + if (match_type != EVENT_UNDEF && match_type != event->state) + continue; + + event_free(event); + } +} + +static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Manager *manager = userdata; + + assert(manager); + + for (;;) { + struct worker_message msg; + struct iovec iovec = { + .iov_base = &msg, + .iov_len = sizeof(msg), + }; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; + } control = {}; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + struct cmsghdr *cmsg; + ssize_t size; + struct ucred *ucred = NULL; + struct worker *worker; + + size = recvmsg(fd, &msghdr, MSG_DONTWAIT); + if (size < 0) { + if (errno == EINTR) + continue; + else if (errno == EAGAIN) + /* nothing more to read */ + break; + + return log_error_errno(errno, "Failed to receive message: %m"); + } else if (size != sizeof(struct worker_message)) { + log_warning("Ignoring worker message with invalid size %zi bytes", size); + continue; + } + + CMSG_FOREACH(cmsg, &msghdr) + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) + ucred = (struct ucred*) CMSG_DATA(cmsg); + + if (!ucred || ucred->pid <= 0) { + log_warning("Ignoring worker message without valid PID"); + continue; + } + + /* lookup worker who sent the signal */ + worker = hashmap_get(manager->workers, PID_TO_PTR(ucred->pid)); + if (!worker) { + log_debug("Worker ["PID_FMT"] returned, but is no longer tracked", ucred->pid); + continue; + } + + if (worker->state != WORKER_KILLED) + worker->state = WORKER_IDLE; + + /* worker returned */ + event_free(worker->event); + } + + /* we have free workers, try to schedule events */ + event_queue_start(manager); + + return 1; +} + +static int on_uevent(sd_device_monitor *monitor, sd_device *dev, void *userdata) { + Manager *manager = userdata; + int r; + + assert(manager); + + device_ensure_usec_initialized(dev, NULL); + + r = event_queue_insert(manager, dev); + if (r < 0) { + log_device_error_errno(dev, r, "Failed to insert device into event queue: %m"); + return 1; + } + + /* we have fresh events, try to schedule them */ + event_queue_start(manager); + + return 1; +} + +/* receive the udevd message from userspace */ +static int on_ctrl_msg(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, const union udev_ctrl_msg_value *value, void *userdata) { + Manager *manager = userdata; + int r; + + assert(value); + assert(manager); + + switch (type) { + case UDEV_CTRL_SET_LOG_LEVEL: + log_debug("Received udev control message (SET_LOG_LEVEL), setting log_priority=%i", value->intval); + log_set_max_level_realm(LOG_REALM_UDEV, value->intval); + log_set_max_level_realm(LOG_REALM_SYSTEMD, value->intval); + manager_kill_workers(manager); + break; + case UDEV_CTRL_STOP_EXEC_QUEUE: + log_debug("Received udev control message (STOP_EXEC_QUEUE)"); + manager->stop_exec_queue = true; + break; + case UDEV_CTRL_START_EXEC_QUEUE: + log_debug("Received udev control message (START_EXEC_QUEUE)"); + manager->stop_exec_queue = false; + event_queue_start(manager); + break; + case UDEV_CTRL_RELOAD: + log_debug("Received udev control message (RELOAD)"); + manager_reload(manager); + break; + case UDEV_CTRL_SET_ENV: { + _cleanup_free_ char *key = NULL, *val = NULL, *old_key = NULL, *old_val = NULL; + const char *eq; + + eq = strchr(value->buf, '='); + if (!eq) { + log_error("Invalid key format '%s'", value->buf); + return 1; + } + + key = strndup(value->buf, eq - value->buf); + if (!key) { + log_oom(); + return 1; + } + + old_val = hashmap_remove2(manager->properties, key, (void **) &old_key); + + r = hashmap_ensure_allocated(&manager->properties, &string_hash_ops); + if (r < 0) { + log_oom(); + return 1; + } + + eq++; + if (isempty(eq)) { + log_debug("Received udev control message (ENV), unsetting '%s'", key); + + r = hashmap_put(manager->properties, key, NULL); + if (r < 0) { + log_oom(); + return 1; + } + } else { + val = strdup(eq); + if (!val) { + log_oom(); + return 1; + } + + log_debug("Received udev control message (ENV), setting '%s=%s'", key, val); + + r = hashmap_put(manager->properties, key, val); + if (r < 0) { + log_oom(); + return 1; + } + } + + key = val = NULL; + manager_kill_workers(manager); + break; + } + case UDEV_CTRL_SET_CHILDREN_MAX: + if (value->intval <= 0) { + log_debug("Received invalid udev control message (SET_MAX_CHILDREN, %i), ignoring.", value->intval); + return 0; + } + + log_debug("Received udev control message (SET_MAX_CHILDREN), setting children_max=%i", value->intval); + arg_children_max = value->intval; + + (void) sd_notifyf(false, + "READY=1\n" + "STATUS=Processing with %u children at max", arg_children_max); + break; + case UDEV_CTRL_PING: + log_debug("Received udev control message (PING)"); + break; + case UDEV_CTRL_EXIT: + log_debug("Received udev control message (EXIT)"); + manager_exit(manager); + break; + default: + log_debug("Received unknown udev control message, ignoring"); + } + + return 1; +} + +static int synthesize_change_one(sd_device *dev, const char *syspath) { + const char *filename; + int r; + + filename = strjoina(syspath, "/uevent"); + log_device_debug(dev, "device is closed, synthesising 'change' on %s", syspath); + r = write_string_file(filename, "change", WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to write 'change' to %s: %m", filename); + return 0; +} + +static int synthesize_change(sd_device *dev) { + const char *subsystem, *sysname, *devname, *syspath, *devtype; + int r; + + r = sd_device_get_subsystem(dev, &subsystem); + if (r < 0) + return r; + + r = sd_device_get_sysname(dev, &sysname); + if (r < 0) + return r; + + r = sd_device_get_devname(dev, &devname); + if (r < 0) + return r; + + r = sd_device_get_syspath(dev, &syspath); + if (r < 0) + return r; + + r = sd_device_get_devtype(dev, &devtype); + if (r < 0) + return r; + + if (streq_ptr("block", subsystem) && + streq_ptr("disk", devtype) && + !startswith(sysname, "dm-")) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + bool part_table_read = false, has_partitions = false; + sd_device *d; + int fd; + + /* + * Try to re-read the partition table. This only succeeds if + * none of the devices is busy. The kernel returns 0 if no + * partition table is found, and we will not get an event for + * the disk. + */ + fd = open(devname, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NONBLOCK); + if (fd >= 0) { + r = flock(fd, LOCK_EX|LOCK_NB); + if (r >= 0) + r = ioctl(fd, BLKRRPART, 0); + + close(fd); + if (r >= 0) + part_table_read = true; + } + + /* search for partitions */ + r = sd_device_enumerator_new(&e); + if (r < 0) + return r; + + r = sd_device_enumerator_allow_uninitialized(e); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_parent(e, dev); + if (r < 0) + return r; + + r = sd_device_enumerator_add_match_subsystem(e, "block", true); + if (r < 0) + return r; + + FOREACH_DEVICE(e, d) { + const char *t; + + if (sd_device_get_devtype(d, &t) < 0 || + !streq("partition", t)) + continue; + + has_partitions = true; + break; + } + + /* + * We have partitions and re-read the table, the kernel already sent + * out a "change" event for the disk, and "remove/add" for all + * partitions. + */ + if (part_table_read && has_partitions) + return 0; + + /* + * We have partitions but re-reading the partition table did not + * work, synthesize "change" for the disk and all partitions. + */ + (void) synthesize_change_one(dev, syspath); + + FOREACH_DEVICE(e, d) { + const char *t, *n, *s; + + if (sd_device_get_devtype(d, &t) < 0 || + !streq("partition", t)) + continue; + + if (sd_device_get_devname(d, &n) < 0 || + sd_device_get_syspath(d, &s) < 0) + continue; + + (void) synthesize_change_one(dev, s); + } + + } else + (void) synthesize_change_one(dev, syspath); + + return 0; +} + +static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + Manager *manager = userdata; + union inotify_event_buffer buffer; + struct inotify_event *e; + ssize_t l; + int r; + + assert(manager); + + r = event_source_disable(manager->kill_workers_event); + if (r < 0) + log_warning_errno(r, "Failed to disable event source for cleaning up idle workers, ignoring: %m"); + + l = read(fd, &buffer, sizeof(buffer)); + if (l < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) + return 1; + + return log_error_errno(errno, "Failed to read inotify fd: %m"); + } + + FOREACH_INOTIFY_EVENT(e, buffer, l) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + const char *devnode; + + if (udev_watch_lookup(e->wd, &dev) <= 0) + continue; + + if (sd_device_get_devname(dev, &devnode) < 0) + continue; + + log_device_debug(dev, "Inotify event: %x for %s", e->mask, devnode); + if (e->mask & IN_CLOSE_WRITE) + synthesize_change(dev); + else if (e->mask & IN_IGNORED) + udev_watch_end(dev); + } + + return 1; +} + +static int on_sigterm(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *manager = userdata; + + assert(manager); + + manager_exit(manager); + + return 1; +} + +static int on_sighup(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *manager = userdata; + + assert(manager); + + manager_reload(manager); + + return 1; +} + +static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *manager = userdata; + int r; + + assert(manager); + + for (;;) { + pid_t pid; + int status; + struct worker *worker; + + pid = waitpid(-1, &status, WNOHANG); + if (pid <= 0) + break; + + worker = hashmap_get(manager->workers, PID_TO_PTR(pid)); + if (!worker) { + log_warning("Worker ["PID_FMT"] is unknown, ignoring", pid); + continue; + } + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == 0) + log_debug("Worker ["PID_FMT"] exited", pid); + else + log_warning("Worker ["PID_FMT"] exited with return code %i", pid, WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) + log_warning("Worker ["PID_FMT"] terminated by signal %i (%s)", pid, WTERMSIG(status), signal_to_string(WTERMSIG(status))); + else if (WIFSTOPPED(status)) { + log_info("Worker ["PID_FMT"] stopped", pid); + continue; + } else if (WIFCONTINUED(status)) { + log_info("Worker ["PID_FMT"] continued", pid); + continue; + } else + log_warning("Worker ["PID_FMT"] exit with status 0x%04x", pid, status); + + if ((!WIFEXITED(status) || WEXITSTATUS(status) != 0) && worker->event) { + log_device_error(worker->event->dev, "Worker ["PID_FMT"] failed", pid); + + /* delete state from disk */ + device_delete_db(worker->event->dev); + device_tag_index(worker->event->dev, NULL, false); + + if (manager->monitor) { + /* forward kernel event without amending it */ + r = device_monitor_send_device(manager->monitor, NULL, worker->event->dev_kernel); + if (r < 0) + log_device_error_errno(worker->event->dev_kernel, r, "Failed to send back device to kernel: %m"); + } + } + + worker_free(worker); + } + + /* we can start new workers, try to schedule events */ + event_queue_start(manager); + + /* Disable unnecessary cleanup event */ + if (hashmap_isempty(manager->workers)) { + r = event_source_disable(manager->kill_workers_event); + if (r < 0) + log_warning_errno(r, "Failed to disable event source for cleaning up idle workers, ignoring: %m"); + } + + return 1; +} + +static int on_post(sd_event_source *s, void *userdata) { + Manager *manager = userdata; + + assert(manager); + + if (!LIST_IS_EMPTY(manager->events)) + return 1; + + /* There are no pending events. Let's cleanup idle process. */ + + if (!hashmap_isempty(manager->workers)) { + /* There are idle workers */ + (void) event_reset_time(manager->event, &manager->kill_workers_event, CLOCK_MONOTONIC, + now(CLOCK_MONOTONIC) + 3 * USEC_PER_SEC, USEC_PER_SEC, + on_kill_workers_event, manager, 0, "kill-workers-event", false); + return 1; + } + + /* There are no idle workers. */ + + if (manager->exit) + return sd_event_exit(manager->event, 0); + + if (manager->cgroup) + /* cleanup possible left-over processes in our cgroup */ + (void) cg_kill(SYSTEMD_CGROUP_CONTROLLER, manager->cgroup, SIGKILL, CGROUP_IGNORE_SELF, NULL, NULL, NULL); + + return 1; +} + +static int listen_fds(int *ret_ctrl, int *ret_netlink) { + int ctrl_fd = -1, netlink_fd = -1; + int fd, n; + + assert(ret_ctrl); + assert(ret_netlink); + + n = sd_listen_fds(true); + if (n < 0) + return n; + + for (fd = SD_LISTEN_FDS_START; fd < n + SD_LISTEN_FDS_START; fd++) { + if (sd_is_socket(fd, AF_LOCAL, SOCK_SEQPACKET, -1) > 0) { + if (ctrl_fd >= 0) + return -EINVAL; + ctrl_fd = fd; + continue; + } + + if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) { + if (netlink_fd >= 0) + return -EINVAL; + netlink_fd = fd; + continue; + } + + return -EINVAL; + } + + *ret_ctrl = ctrl_fd; + *ret_netlink = netlink_fd; + + return 0; +} + +/* + * read the kernel command line, in case we need to get into debug mode + * udev.log_priority= syslog priority + * udev.children_max= events are fully serialized if set to 1 + * udev.exec_delay= delay execution of every executed program + * udev.event_timeout= seconds to wait before terminating an event + */ +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + int r = 0; + + assert(key); + + if (!value) + return 0; + + if (proc_cmdline_key_streq(key, "udev.log_priority")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = log_level_from_string(value); + if (r >= 0) + log_set_max_level(r); + + } else if (proc_cmdline_key_streq(key, "udev.event_timeout")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = parse_sec(value, &arg_event_timeout_usec); + + } else if (proc_cmdline_key_streq(key, "udev.children_max")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = safe_atou(value, &arg_children_max); + + } else if (proc_cmdline_key_streq(key, "udev.exec_delay")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = parse_sec(value, &arg_exec_delay_usec); + + } else if (startswith(key, "udev.")) + log_warning("Unknown udev kernel command line option \"%s\", ignoring", key); + + if (r < 0) + log_warning_errno(r, "Failed to parse \"%s=%s\", ignoring: %m", key, value); + + return 0; +} + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-udevd.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s [OPTIONS...]\n\n" + "Manages devices.\n\n" + " -h --help Print this message\n" + " -V --version Print version of the program\n" + " -d --daemon Detach and run in the background\n" + " -D --debug Enable debug output\n" + " -c --children-max=INT Set maximum number of workers\n" + " -e --exec-delay=SECONDS Seconds to wait before executing RUN=\n" + " -t --event-timeout=SECONDS Seconds to wait before terminating an event\n" + " -N --resolve-names=early|late|never\n" + " When to resolve users and groups\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + static const struct option options[] = { + { "daemon", no_argument, NULL, 'd' }, + { "debug", no_argument, NULL, 'D' }, + { "children-max", required_argument, NULL, 'c' }, + { "exec-delay", required_argument, NULL, 'e' }, + { "event-timeout", required_argument, NULL, 't' }, + { "resolve-names", required_argument, NULL, 'N' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, + {} + }; + + int c, r; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "c:de:Dt:N:hV", options, NULL)) >= 0) { + switch (c) { + + case 'd': + arg_daemonize = true; + break; + case 'c': + r = safe_atou(optarg, &arg_children_max); + if (r < 0) + log_warning_errno(r, "Failed to parse --children-max= value '%s', ignoring: %m", optarg); + break; + case 'e': + r = parse_sec(optarg, &arg_exec_delay_usec); + if (r < 0) + log_warning_errno(r, "Failed to parse --exec-delay= value '%s', ignoring: %m", optarg); + break; + case 't': + r = parse_sec(optarg, &arg_event_timeout_usec); + if (r < 0) + log_warning_errno(r, "Failed to parse --event-timeout= value '%s', ignoring: %m", optarg); + break; + case 'D': + arg_debug = true; + break; + case 'N': { + ResolveNameTiming t; + + t = resolve_name_timing_from_string(optarg); + if (t < 0) + log_warning("Invalid --resolve-names= value '%s', ignoring.", optarg); + else + arg_resolve_name_timing = t; + break; + } + case 'h': + return help(); + case 'V': + printf("%s\n", GIT_VERSION); + return 0; + case '?': + return -EINVAL; + default: + assert_not_reached("Unhandled option"); + + } + } + + return 1; +} + +static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cgroup) { + _cleanup_(manager_freep) Manager *manager = NULL; + int r; + + assert(ret); + + manager = new(Manager, 1); + if (!manager) + return log_oom(); + + *manager = (Manager) { + .fd_inotify = -1, + .worker_watch = { -1, -1 }, + .cgroup = cgroup, + }; + + r = udev_ctrl_new_from_fd(&manager->ctrl, fd_ctrl); + if (r < 0) + return log_error_errno(r, "Failed to initialize udev control socket: %m"); + + r = udev_ctrl_enable_receiving(manager->ctrl); + if (r < 0) + return log_error_errno(r, "Failed to bind udev control socket: %m"); + + r = device_monitor_new_full(&manager->monitor, MONITOR_GROUP_KERNEL, fd_uevent); + if (r < 0) + return log_error_errno(r, "Failed to initialize device monitor: %m"); + + (void) sd_device_monitor_set_receive_buffer_size(manager->monitor, 128 * 1024 * 1024); + + r = device_monitor_enable_receiving(manager->monitor); + if (r < 0) + return log_error_errno(r, "Failed to bind netlink socket: %m"); + + *ret = TAKE_PTR(manager); + + return 0; +} + +static int main_loop(Manager *manager) { + int fd_worker, r; + + manager->pid = getpid_cached(); + + /* unnamed socket from workers to the main daemon */ + r = socketpair(AF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC, 0, manager->worker_watch); + if (r < 0) + return log_error_errno(errno, "Failed to create socketpair for communicating with workers: %m"); + + fd_worker = manager->worker_watch[READ_END]; + + r = setsockopt_int(fd_worker, SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return log_error_errno(r, "Failed to enable SO_PASSCRED: %m"); + + r = udev_watch_init(); + if (r < 0) + return log_error_errno(r, "Failed to create inotify descriptor: %m"); + manager->fd_inotify = r; + + udev_watch_restore(); + + /* block and listen to all signals on signalfd */ + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0); + + r = sd_event_default(&manager->event); + if (r < 0) + return log_error_errno(r, "Failed to allocate event loop: %m"); + + r = sd_event_add_signal(manager->event, NULL, SIGINT, on_sigterm, manager); + if (r < 0) + return log_error_errno(r, "Failed to create SIGINT event source: %m"); + + r = sd_event_add_signal(manager->event, NULL, SIGTERM, on_sigterm, manager); + if (r < 0) + return log_error_errno(r, "Failed to create SIGTERM event source: %m"); + + r = sd_event_add_signal(manager->event, NULL, SIGHUP, on_sighup, manager); + if (r < 0) + return log_error_errno(r, "Failed to create SIGHUP event source: %m"); + + r = sd_event_add_signal(manager->event, NULL, SIGCHLD, on_sigchld, manager); + if (r < 0) + return log_error_errno(r, "Failed to create SIGCHLD event source: %m"); + + r = sd_event_set_watchdog(manager->event, true); + if (r < 0) + return log_error_errno(r, "Failed to create watchdog event source: %m"); + + r = udev_ctrl_attach_event(manager->ctrl, manager->event); + if (r < 0) + return log_error_errno(r, "Failed to attach event to udev control: %m"); + + r = udev_ctrl_start(manager->ctrl, on_ctrl_msg, manager); + if (r < 0) + return log_error_errno(r, "Failed to start device monitor: %m"); + + /* This needs to be after the inotify and uevent handling, to make sure + * that the ping is send back after fully processing the pending uevents + * (including the synthetic ones we may create due to inotify events). + */ + r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE); + if (r < 0) + return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m"); + + r = sd_event_add_io(manager->event, &manager->inotify_event, manager->fd_inotify, EPOLLIN, on_inotify, manager); + if (r < 0) + return log_error_errno(r, "Failed to create inotify event source: %m"); + + r = sd_device_monitor_attach_event(manager->monitor, manager->event); + if (r < 0) + return log_error_errno(r, "Failed to attach event to device monitor: %m"); + + r = sd_device_monitor_start(manager->monitor, on_uevent, manager); + if (r < 0) + return log_error_errno(r, "Failed to start device monitor: %m"); + + (void) sd_event_source_set_description(sd_device_monitor_get_event_source(manager->monitor), "device-monitor"); + + r = sd_event_add_io(manager->event, NULL, fd_worker, EPOLLIN, on_worker, manager); + if (r < 0) + return log_error_errno(r, "Failed to create worker event source: %m"); + + r = sd_event_add_post(manager->event, NULL, on_post, manager); + if (r < 0) + return log_error_errno(r, "Failed to create post event source: %m"); + + udev_builtin_init(); + + r = udev_rules_new(&manager->rules, arg_resolve_name_timing); + if (!manager->rules) + return log_error_errno(r, "Failed to read udev rules: %m"); + + r = udev_rules_apply_static_dev_perms(manager->rules); + if (r < 0) + log_error_errno(r, "Failed to apply permissions on static device nodes: %m"); + + (void) sd_notifyf(false, + "READY=1\n" + "STATUS=Processing with %u children at max", arg_children_max); + + r = sd_event_loop(manager->event); + if (r < 0) + log_error_errno(r, "Event loop failed: %m"); + + sd_notify(false, + "STOPPING=1\n" + "STATUS=Shutting down..."); + return r; +} + +static int run(int argc, char *argv[]) { + _cleanup_free_ char *cgroup = NULL; + _cleanup_(manager_freep) Manager *manager = NULL; + int fd_ctrl = -1, fd_uevent = -1; + int r; + + log_set_target(LOG_TARGET_AUTO); + log_open(); + udev_parse_config_full(&arg_children_max, &arg_exec_delay_usec, &arg_event_timeout_usec, &arg_resolve_name_timing); + log_parse_environment(); + log_open(); /* Done again to update after reading configuration. */ + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); + if (r < 0) + log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); + + if (arg_debug) { + log_set_target(LOG_TARGET_CONSOLE); + log_set_max_level(LOG_DEBUG); + } + + log_set_max_level_realm(LOG_REALM_SYSTEMD, log_get_max_level()); + + r = must_be_root(); + if (r < 0) + return r; + + if (arg_children_max == 0) { + unsigned long cpu_limit, mem_limit; + unsigned long cpu_count = 1; + cpu_set_t cpu_set; + + if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) == 0) + cpu_count = CPU_COUNT(&cpu_set); + + cpu_limit = cpu_count * 2 + 16; + mem_limit = MAX(physical_memory() / (128UL*1024*1024), 10U); + + arg_children_max = MIN(cpu_limit, mem_limit); + arg_children_max = MIN(WORKER_NUM_MAX, arg_children_max); + + log_debug("Set children_max to %u", arg_children_max); + } + + /* set umask before creating any file/directory */ + r = chdir("/"); + if (r < 0) + return log_error_errno(errno, "Failed to change dir to '/': %m"); + + umask(022); + + r = mac_selinux_init(); + if (r < 0) + return log_error_errno(r, "Could not initialize labelling: %m"); + + r = mkdir_errno_wrapper("/run/udev", 0755); + if (r < 0 && r != -EEXIST) + return log_error_errno(r, "Failed to create /run/udev: %m"); + + dev_setup(NULL, UID_INVALID, GID_INVALID); + + if (getppid() == 1 && sd_booted() > 0) { + /* Get our own cgroup, we regularly kill everything udev has left behind. + * We only do this on systemd systems, and only if we are directly spawned + * by PID1. Otherwise we are not guaranteed to have a dedicated cgroup. */ + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup); + if (r < 0) { + if (IN_SET(r, -ENOENT, -ENOMEDIUM)) + log_debug_errno(r, "Dedicated cgroup not found: %m"); + else + log_warning_errno(r, "Failed to get cgroup: %m"); + } + } + + r = listen_fds(&fd_ctrl, &fd_uevent); + if (r < 0) + return log_error_errno(r, "Failed to listen on fds: %m"); + + r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup); + if (r < 0) + return log_error_errno(r, "Failed to create manager: %m"); + + if (arg_daemonize) { + pid_t pid; + + log_info("Starting version " GIT_VERSION); + + /* connect /dev/null to stdin, stdout, stderr */ + if (log_get_max_level() < LOG_DEBUG) { + r = make_null_stdio(); + if (r < 0) + log_warning_errno(r, "Failed to redirect standard streams to /dev/null: %m"); + } + + pid = fork(); + if (pid < 0) + return log_error_errno(errno, "Failed to fork daemon: %m"); + if (pid > 0) + /* parent */ + return 0; + + /* child */ + (void) setsid(); + + r = set_oom_score_adjust(-1000); + if (r < 0) + log_debug_errno(r, "Failed to adjust OOM score, ignoring: %m"); + } + + return main_loop(manager); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/udev/v4l_id/v4l_id.c b/src/udev/v4l_id/v4l_id.c new file mode 100644 index 00000000..5de26b80 --- /dev/null +++ b/src/udev/v4l_id/v4l_id.c @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2009 Filippo Argiolas + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details: + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fd-util.h" +#include "util.h" + +int main(int argc, char *argv[]) { + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + {} + }; + _cleanup_close_ int fd = -1; + char *device; + struct v4l2_capability v2cap; + int c; + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + + switch (c) { + case 'h': + printf("%s [-h,--help] \n\n" + "Video4Linux device identification.\n\n" + " -h Print this message\n" + , program_invocation_short_name); + return 0; + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + + device = argv[optind]; + if (!device) + return 2; + + fd = open(device, O_RDONLY); + if (fd < 0) + return 3; + + if (ioctl(fd, VIDIOC_QUERYCAP, &v2cap) == 0) { + int capabilities; + printf("ID_V4L_VERSION=2\n"); + printf("ID_V4L_PRODUCT=%s\n", v2cap.card); + printf("ID_V4L_CAPABILITIES=:"); + if (v2cap.capabilities & V4L2_CAP_DEVICE_CAPS) + capabilities = v2cap.device_caps; + else + capabilities = v2cap.capabilities; + if ((capabilities & V4L2_CAP_VIDEO_CAPTURE) > 0 || + (capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) > 0) + printf("capture:"); + if ((capabilities & V4L2_CAP_VIDEO_OUTPUT) > 0 || + (capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE) > 0) + printf("video_output:"); + if ((capabilities & V4L2_CAP_VIDEO_OVERLAY) > 0) + printf("video_overlay:"); + if ((capabilities & V4L2_CAP_AUDIO) > 0) + printf("audio:"); + if ((capabilities & V4L2_CAP_TUNER) > 0) + printf("tuner:"); + if ((capabilities & V4L2_CAP_RADIO) > 0) + printf("radio:"); + printf("\n"); + } + + return 0; +} diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c new file mode 100644 index 00000000..bbd14165 --- /dev/null +++ b/src/update-done/update-done.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "fileio-label.h" +#include "selinux-util.h" +#include "time-util.h" + +#define MESSAGE \ + "# This file was created by systemd-update-done. Its only \n" \ + "# purpose is to hold a timestamp of the time this directory\n" \ + "# was updated. See man:systemd-update-done.service(8).\n" + +static int apply_timestamp(const char *path, struct timespec *ts) { + _cleanup_free_ char *message = NULL; + int r; + + /* + * We store the timestamp both as mtime of the file and in the file itself, + * to support filesystems which cannot store nanosecond-precision timestamps. + */ + + if (asprintf(&message, + MESSAGE + "TIMESTAMP_NSEC=" NSEC_FMT "\n", + timespec_load_nsec(ts)) < 0) + return log_oom(); + + r = write_string_file_atomic_label_ts(path, message, ts); + if (r == -EROFS) + return log_debug("Cannot create \"%s\", file system is read-only.", path); + if (r < 0) + return log_error_errno(r, "Failed to write \"%s\": %m", path); + return 0; +} + +int main(int argc, char *argv[]) { + struct stat st; + int r, q = 0; + + log_setup_service(); + + if (stat("/usr", &st) < 0) { + log_error_errno(errno, "Failed to stat /usr: %m"); + return EXIT_FAILURE; + } + + r = mac_selinux_init(); + if (r < 0) { + log_error_errno(r, "SELinux setup failed: %m"); + return EXIT_FAILURE; + } + + r = apply_timestamp("/etc/.updated", &st.st_mtim); + q = apply_timestamp("/var/.updated", &st.st_mtim); + + return r < 0 || q < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/update-utmp/update-utmp.c b/src/update-utmp/update-utmp.c new file mode 100644 index 00000000..55fd8ba4 --- /dev/null +++ b/src/update-utmp/update-utmp.c @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include + +#if HAVE_AUDIT +#include +#endif + +#include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-error.h" +#include "bus-util.h" +#include "format-util.h" +#include "log.h" +#include "macro.h" +#include "main-func.h" +#include "process-util.h" +#include "special.h" +#include "stdio-util.h" +#include "strv.h" +#include "unit-name.h" +#include "util.h" +#include "utmp-wtmp.h" + +typedef struct Context { + sd_bus *bus; +#if HAVE_AUDIT + int audit_fd; +#endif +} Context; + +static void context_clear(Context *c) { + assert(c); + + c->bus = sd_bus_flush_close_unref(c->bus); +#if HAVE_AUDIT + if (c->audit_fd >= 0) + audit_close(c->audit_fd); + c->audit_fd = -1; +#endif +} + +static usec_t get_startup_time(Context *c) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + usec_t t = 0; + int r; + + assert(c); + + r = sd_bus_get_property_trivial( + c->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "UserspaceTimestamp", + &error, + 't', &t); + if (r < 0) { + log_error_errno(r, "Failed to get timestamp: %s", bus_error_message(&error, r)); + return 0; + } + + return t; +} + +static int get_current_runlevel(Context *c) { + static const struct { + const int runlevel; + const char *special; + } table[] = { + /* The first target of this list that is active or has + * a job scheduled wins. We prefer runlevels 5 and 3 + * here over the others, since these are the main + * runlevels used on Fedora. It might make sense to + * change the order on some distributions. */ + { '5', SPECIAL_GRAPHICAL_TARGET }, + { '3', SPECIAL_MULTI_USER_TARGET }, + { '1', SPECIAL_RESCUE_TARGET }, + }; + + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + unsigned i; + + assert(c); + + for (i = 0; i < ELEMENTSOF(table); i++) { + _cleanup_free_ char *state = NULL, *path = NULL; + + path = unit_dbus_path_from_name(table[i].special); + if (!path) + return log_oom(); + + r = sd_bus_get_property_string( + c->bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + "ActiveState", + &error, + &state); + if (r < 0) + return log_warning_errno(r, "Failed to get state: %s", bus_error_message(&error, r)); + + if (STR_IN_SET(state, "active", "reloading")) + return table[i].runlevel; + } + + return 0; +} + +static int on_reboot(Context *c) { + int r = 0, q; + usec_t t; + + assert(c); + + /* We finished start-up, so let's write the utmp + * record and send the audit msg */ + +#if HAVE_AUDIT + if (c->audit_fd >= 0) + if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_BOOT, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && + errno != EPERM) { + r = log_error_errno(errno, "Failed to send audit message: %m"); + } +#endif + + /* If this call fails it will return 0, which + * utmp_put_reboot() will then fix to the current time */ + t = get_startup_time(c); + + q = utmp_put_reboot(t); + if (q < 0) { + log_error_errno(q, "Failed to write utmp record: %m"); + r = q; + } + + return r; +} + +static int on_shutdown(Context *c) { + int r = 0, q; + + assert(c); + + /* We started shut-down, so let's write the utmp + * record and send the audit msg */ + +#if HAVE_AUDIT + if (c->audit_fd >= 0) + if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_SHUTDOWN, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && + errno != EPERM) { + r = log_error_errno(errno, "Failed to send audit message: %m"); + } +#endif + + q = utmp_put_shutdown(); + if (q < 0) { + log_error_errno(q, "Failed to write utmp record: %m"); + r = q; + } + + return r; +} + +static int on_runlevel(Context *c) { + int r = 0, q, previous, runlevel; + + assert(c); + + /* We finished changing runlevel, so let's write the + * utmp record and send the audit msg */ + + /* First, get last runlevel */ + q = utmp_get_runlevel(&previous, NULL); + + if (q < 0) { + if (!IN_SET(q, -ESRCH, -ENOENT)) + return log_error_errno(q, "Failed to get current runlevel: %m"); + + previous = 0; + } + + /* Secondly, get new runlevel */ + runlevel = get_current_runlevel(c); + if (runlevel < 0) + return runlevel; + if (runlevel == 0) + return log_warning("Failed to get new runlevel, utmp update skipped."); + + if (previous == runlevel) + return 0; + +#if HAVE_AUDIT + if (c->audit_fd >= 0) { + char s[STRLEN("old-level=_ new-level=_") + 1]; + + xsprintf(s, "old-level=%c new-level=%c", + previous > 0 ? previous : 'N', + runlevel); + + if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, + "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM) + r = log_error_errno(errno, "Failed to send audit message: %m"); + } +#endif + + q = utmp_put_runlevel(runlevel, previous); + if (q < 0 && !IN_SET(q, -ESRCH, -ENOENT)) + return log_error_errno(q, "Failed to write utmp record: %m"); + + return r; +} + +static int run(int argc, char *argv[]) { + _cleanup_(context_clear) Context c = { +#if HAVE_AUDIT + .audit_fd = -1 +#endif + }; + int r; + + if (getppid() != 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program should be invoked by init only."); + if (argc != 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program requires one argument."); + + log_setup_service(); + + umask(0022); + +#if HAVE_AUDIT + /* If the kernel lacks netlink or audit support, don't worry about it. */ + c.audit_fd = audit_open(); + if (c.audit_fd < 0) + log_full_errno(IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT) ? LOG_DEBUG : LOG_ERR, + errno, "Failed to connect to audit log: %m"); +#endif + r = bus_connect_system_systemd(&c.bus); + if (r < 0) + return log_error_errno(r, "Failed to get D-Bus connection: %m"); + + if (streq(argv[1], "reboot")) + return on_reboot(&c); + if (streq(argv[1], "shutdown")) + return on_shutdown(&c); + if (streq(argv[1], "runlevel")) + return on_runlevel(&c); + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown command %s", argv[1]); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/user-sessions/user-sessions.c b/src/user-sessions/user-sessions.c new file mode 100644 index 00000000..c2414295 --- /dev/null +++ b/src/user-sessions/user-sessions.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "fileio.h" +#include "fileio-label.h" +#include "fs-util.h" +#include "main-func.h" +#include "log.h" +#include "selinux-util.h" +#include "string-util.h" + +static int run(int argc, char *argv[]) { + int r, k; + + if (argc != 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program requires one argument."); + + log_setup_service(); + + umask(0022); + + mac_selinux_init(); + + if (streq(argv[1], "start")) { + r = unlink_or_warn("/run/nologin"); + k = unlink_or_warn("/etc/nologin"); + if (r < 0) + return r; + return k; + + } else if (streq(argv[1], "stop")) + return create_shutdown_run_nologin_or_warn(); + + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb '%s'.", argv[1]); +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/vconsole/90-vconsole.rules.in b/src/vconsole/90-vconsole.rules.in new file mode 100644 index 00000000..70679b6d --- /dev/null +++ b/src/vconsole/90-vconsole.rules.in @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# Each vtcon keeps its own state of fonts. +# +ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon*", RUN+="@rootlibexecdir@/systemd-vconsole-setup" diff --git a/src/vconsole/meson.build b/src/vconsole/meson.build new file mode 100644 index 00000000..03065ec2 --- /dev/null +++ b/src/vconsole/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +if conf.get('ENABLE_VCONSOLE') == 1 + vconsole_rules = configure_file( + input : '90-vconsole.rules.in', + output : '90-vconsole.rules', + configuration : substs) + install_data(vconsole_rules, + install_dir : udevrulesdir) +endif diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c new file mode 100644 index 00000000..9d706085 --- /dev/null +++ b/src/vconsole/vconsole-setup.c @@ -0,0 +1,479 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/*** + Copyright © 2016 Michal Soltys +***/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "env-file.h" +#include "fd-util.h" +#include "fileio.h" +#include "io-util.h" +#include "locale-util.h" +#include "log.h" +#include "proc-cmdline.h" +#include "process-util.h" +#include "signal-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "util.h" +#include "virt.h" + +static int verify_vc_device(int fd) { + unsigned char data[] = { + TIOCL_GETFGCONSOLE, + }; + + int r; + + r = ioctl(fd, TIOCLINUX, data); + if (r < 0) + return -errno; + + return r; +} + +static int verify_vc_allocation(unsigned idx) { + char vcname[sizeof("/dev/vcs") + DECIMAL_STR_MAX(unsigned) - 2]; + + xsprintf(vcname, "/dev/vcs%u", idx); + + if (access(vcname, F_OK) < 0) + return -errno; + + return 0; +} + +static int verify_vc_allocation_byfd(int fd) { + struct vt_stat vcs = {}; + + if (ioctl(fd, VT_GETSTATE, &vcs) < 0) + return -errno; + + return verify_vc_allocation(vcs.v_active); +} + +static int verify_vc_kbmode(int fd) { + int curr_mode; + + /* + * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode. + * Otherwise we would (likely) interfere with X11's processing of the + * key events. + * + * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html + */ + + if (ioctl(fd, KDGKBMODE, &curr_mode) < 0) + return -errno; + + return IN_SET(curr_mode, K_XLATE, K_UNICODE) ? 0 : -EBUSY; +} + +static int toggle_utf8_vc(const char *name, int fd, bool utf8) { + int r; + struct termios tc = {}; + + assert(name); + assert(fd >= 0); + + r = ioctl(fd, KDSKBMODE, utf8 ? K_UNICODE : K_XLATE); + if (r < 0) + return log_warning_errno(errno, "Failed to %s UTF-8 kbdmode on %s: %m", enable_disable(utf8), name); + + r = loop_write(fd, utf8 ? "\033%G" : "\033%@", 3, false); + if (r < 0) + return log_warning_errno(r, "Failed to %s UTF-8 term processing on %s: %m", enable_disable(utf8), name); + + r = tcgetattr(fd, &tc); + if (r >= 0) { + SET_FLAG(tc.c_iflag, IUTF8, utf8); + r = tcsetattr(fd, TCSANOW, &tc); + } + if (r < 0) + return log_warning_errno(errno, "Failed to %s iutf8 flag on %s: %m", enable_disable(utf8), name); + + log_debug("UTF-8 kbdmode %sd on %s", enable_disable(utf8), name); + return 0; +} + +static int toggle_utf8_sysfs(bool utf8) { + int r; + + r = write_string_file("/sys/module/vt/parameters/default_utf8", one_zero(utf8), WRITE_STRING_FILE_DISABLE_BUFFER); + if (r < 0) + return log_warning_errno(r, "Failed to %s sysfs UTF-8 flag: %m", enable_disable(utf8)); + + log_debug("Sysfs UTF-8 flag %sd", enable_disable(utf8)); + return 0; +} + +static int keyboard_load_and_wait(const char *vc, const char *map, const char *map_toggle, bool utf8) { + const char *args[8]; + unsigned i = 0; + pid_t pid; + int r; + + /* An empty map means kernel map */ + if (isempty(map)) + return 0; + + args[i++] = KBD_LOADKEYS; + args[i++] = "-q"; + args[i++] = "-C"; + args[i++] = vc; + if (utf8) + args[i++] = "-u"; + args[i++] = map; + if (map_toggle) + args[i++] = map_toggle; + args[i++] = NULL; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *cmd; + + cmd = strv_join((char**) args, " "); + log_debug("Executing \"%s\"...", strnull(cmd)); + } + + r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + execv(args[0], (char **) args); + _exit(EXIT_FAILURE); + } + + return wait_for_terminate_and_check(KBD_LOADKEYS, pid, WAIT_LOG); +} + +static int font_load_and_wait(const char *vc, const char *font, const char *map, const char *unimap) { + const char *args[9]; + unsigned i = 0; + pid_t pid; + int r; + + /* Any part can be set independently */ + if (isempty(font) && isempty(map) && isempty(unimap)) + return 0; + + args[i++] = KBD_SETFONT; + args[i++] = "-C"; + args[i++] = vc; + if (!isempty(map)) { + args[i++] = "-m"; + args[i++] = map; + } + if (!isempty(unimap)) { + args[i++] = "-u"; + args[i++] = unimap; + } + if (!isempty(font)) + args[i++] = font; + args[i++] = NULL; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *cmd; + + cmd = strv_join((char**) args, " "); + log_debug("Executing \"%s\"...", strnull(cmd)); + } + + r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); + if (r < 0) + return r; + if (r == 0) { + execv(args[0], (char **) args); + _exit(EXIT_FAILURE); + } + + return wait_for_terminate_and_check(KBD_SETFONT, pid, WAIT_LOG); +} + +/* + * A newly allocated VT uses the font from the source VT. Here + * we update all possibly already allocated VTs with the configured + * font. It also allows to restart systemd-vconsole-setup.service, + * to apply a new font to all VTs. + * + * We also setup per-console utf8 related stuff: kbdmode, term + * processing, stty iutf8. + */ +static void setup_remaining_vcs(int src_fd, unsigned src_idx, bool utf8) { + struct console_font_op cfo = { + .op = KD_FONT_OP_GET, + .width = UINT_MAX, .height = UINT_MAX, + .charcount = UINT_MAX, + }; + struct unimapinit adv = {}; + struct unimapdesc unimapd; + _cleanup_free_ struct unipair* unipairs = NULL; + _cleanup_free_ void *fontbuf = NULL; + unsigned i; + int r; + + unipairs = new(struct unipair, USHRT_MAX); + if (!unipairs) { + log_oom(); + return; + } + + /* get metadata of the current font (width, height, count) */ + r = ioctl(src_fd, KDFONTOP, &cfo); + if (r < 0) + log_warning_errno(errno, "KD_FONT_OP_GET failed while trying to get the font metadata: %m"); + else { + /* verify parameter sanity first */ + if (cfo.width > 32 || cfo.height > 32 || cfo.charcount > 512) + log_warning("Invalid font metadata - width: %u (max 32), height: %u (max 32), count: %u (max 512)", + cfo.width, cfo.height, cfo.charcount); + else { + /* + * Console fonts supported by the kernel are limited in size to 32 x 32 and maximum 512 + * characters. Thus with 1 bit per pixel it requires up to 65536 bytes. The height always + * requires 32 per glyph, regardless of the actual height - see the comment above #define + * max_font_size 65536 in drivers/tty/vt/vt.c for more details. + */ + fontbuf = malloc_multiply((cfo.width + 7) / 8 * 32, cfo.charcount); + if (!fontbuf) { + log_oom(); + return; + } + /* get fonts from the source console */ + cfo.data = fontbuf; + r = ioctl(src_fd, KDFONTOP, &cfo); + if (r < 0) + log_warning_errno(errno, "KD_FONT_OP_GET failed while trying to read the font data: %m"); + else { + unimapd.entries = unipairs; + unimapd.entry_ct = USHRT_MAX; + r = ioctl(src_fd, GIO_UNIMAP, &unimapd); + if (r < 0) + log_warning_errno(errno, "GIO_UNIMAP failed while trying to read unicode mappings: %m"); + else + cfo.op = KD_FONT_OP_SET; + } + } + } + + if (cfo.op != KD_FONT_OP_SET) + log_warning("Fonts will not be copied to remaining consoles"); + + for (i = 1; i <= 63; i++) { + char ttyname[sizeof("/dev/tty63")]; + _cleanup_close_ int fd_d = -1; + + if (i == src_idx || verify_vc_allocation(i) < 0) + continue; + + /* try to open terminal */ + xsprintf(ttyname, "/dev/tty%u", i); + fd_d = open_terminal(ttyname, O_RDWR|O_CLOEXEC|O_NOCTTY); + if (fd_d < 0) { + log_warning_errno(fd_d, "Unable to open tty%u, fonts will not be copied: %m", i); + continue; + } + + if (verify_vc_kbmode(fd_d) < 0) + continue; + + (void) toggle_utf8_vc(ttyname, fd_d, utf8); + + if (cfo.op != KD_FONT_OP_SET) + continue; + + r = ioctl(fd_d, KDFONTOP, &cfo); + if (r < 0) { + int last_errno, mode; + + /* The fonts couldn't have been copied. It might be due to the + * terminal being in graphical mode. In this case the kernel + * returns -EINVAL which is too generic for distinguishing this + * specific case. So we need to retrieve the terminal mode and if + * the graphical mode is in used, let's assume that something else + * is using the terminal and the failure was expected as we + * shouldn't have tried to copy the fonts. */ + + last_errno = errno; + if (ioctl(fd_d, KDGETMODE, &mode) >= 0 && mode != KD_TEXT) + log_debug("KD_FONT_OP_SET skipped: tty%u is not in text mode", i); + else + log_warning_errno(last_errno, "KD_FONT_OP_SET failed, fonts will not be copied to tty%u: %m", i); + + continue; + } + + /* + * copy unicode translation table unimapd is a ushort count and a pointer + * to an array of struct unipair { ushort, ushort } + */ + r = ioctl(fd_d, PIO_UNIMAPCLR, &adv); + if (r < 0) { + log_warning_errno(errno, "PIO_UNIMAPCLR failed, unimaps might be incorrect for tty%u: %m", i); + continue; + } + + r = ioctl(fd_d, PIO_UNIMAP, &unimapd); + if (r < 0) { + log_warning_errno(errno, "PIO_UNIMAP failed, unimaps might be incorrect for tty%u: %m", i); + continue; + } + + log_debug("Font and unimap successfully copied to %s", ttyname); + } +} + +static int find_source_vc(char **ret_path, unsigned *ret_idx) { + _cleanup_free_ char *path = NULL; + int r, err = 0; + unsigned i; + + path = new(char, sizeof("/dev/tty63")); + if (!path) + return log_oom(); + + for (i = 1; i <= 63; i++) { + _cleanup_close_ int fd = -1; + + r = verify_vc_allocation(i); + if (r < 0) { + if (!err) + err = -r; + continue; + } + + sprintf(path, "/dev/tty%u", i); + fd = open_terminal(path, O_RDWR|O_CLOEXEC|O_NOCTTY); + if (fd < 0) { + if (!err) + err = -fd; + continue; + } + r = verify_vc_kbmode(fd); + if (r < 0) { + if (!err) + err = -r; + continue; + } + + /* all checks passed, return this one as a source console */ + *ret_idx = i; + *ret_path = TAKE_PTR(path); + return TAKE_FD(fd); + } + + return log_error_errno(err, "No usable source console found: %m"); +} + +static int verify_source_vc(char **ret_path, const char *src_vc) { + _cleanup_close_ int fd = -1; + char *path; + int r; + + fd = open_terminal(src_vc, O_RDWR|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return log_error_errno(fd, "Failed to open %s: %m", src_vc); + + r = verify_vc_device(fd); + if (r < 0) + return log_error_errno(r, "Device %s is not a virtual console: %m", src_vc); + + r = verify_vc_allocation_byfd(fd); + if (r < 0) + return log_error_errno(r, "Virtual console %s is not allocated: %m", src_vc); + + r = verify_vc_kbmode(fd); + if (r < 0) + return log_error_errno(r, "Virtual console %s is not in K_XLATE or K_UNICODE: %m", src_vc); + + path = strdup(src_vc); + if (!path) + return log_oom(); + + *ret_path = path; + return TAKE_FD(fd); +} + +int main(int argc, char **argv) { + _cleanup_free_ char + *vc = NULL, + *vc_keymap = NULL, *vc_keymap_toggle = NULL, + *vc_font = NULL, *vc_font_map = NULL, *vc_font_unimap = NULL; + _cleanup_close_ int fd = -1; + bool utf8, keyboard_ok; + unsigned idx = 0; + int r; + + log_setup_service(); + + umask(0022); + + if (argv[1]) + fd = verify_source_vc(&vc, argv[1]); + else + fd = find_source_vc(&vc, &idx); + if (fd < 0) + return EXIT_FAILURE; + + utf8 = is_locale_utf8(); + + r = parse_env_file(NULL, "/etc/vconsole.conf", + "KEYMAP", &vc_keymap, + "KEYMAP_TOGGLE", &vc_keymap_toggle, + "FONT", &vc_font, + "FONT_MAP", &vc_font_map, + "FONT_UNIMAP", &vc_font_unimap); + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to read /etc/vconsole.conf: %m"); + + /* Let the kernel command line override /etc/vconsole.conf */ + r = proc_cmdline_get_key_many( + PROC_CMDLINE_STRIP_RD_PREFIX, + "vconsole.keymap", &vc_keymap, + "vconsole.keymap_toggle", &vc_keymap_toggle, + "vconsole.font", &vc_font, + "vconsole.font_map", &vc_font_map, + "vconsole.font_unimap", &vc_font_unimap, + /* compatibility with obsolete multiple-dot scheme */ + "vconsole.keymap.toggle", &vc_keymap_toggle, + "vconsole.font.map", &vc_font_map, + "vconsole.font.unimap", &vc_font_unimap); + if (r < 0 && r != -ENOENT) + log_warning_errno(r, "Failed to read /proc/cmdline: %m"); + + (void) toggle_utf8_sysfs(utf8); + (void) toggle_utf8_vc(vc, fd, utf8); + + r = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap); + keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) == 0; + + if (idx > 0) { + if (r == 0) + setup_remaining_vcs(fd, idx, utf8); + else if (r == EX_OSERR) + /* setfont returns EX_OSERR when ioctl(KDFONTOP/PIO_FONTX/PIO_FONTX) fails. + * This might mean various things, but in particular lack of a graphical + * console. Let's be generous and not treat this as an error. */ + log_notice("Setting fonts failed with a \"system error\", ignoring."); + else + log_warning("Setting source virtual console failed, ignoring remaining ones"); + } + + return IN_SET(r, 0, EX_OSERR) && keyboard_ok ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/veritysetup/veritysetup-generator.c b/src/veritysetup/veritysetup-generator.c new file mode 100644 index 00000000..f2b74f3d --- /dev/null +++ b/src/veritysetup/veritysetup-generator.c @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include +#include +#include + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fstab-util.h" +#include "generator.h" +#include "hexdecoct.h" +#include "id128-util.h" +#include "main-func.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "specifier.h" +#include "string-util.h" +#include "unit-name.h" + +#define SYSTEMD_VERITYSETUP_SERVICE "systemd-veritysetup@root.service" + +static const char *arg_dest = NULL; +static bool arg_enabled = true; +static char *arg_root_hash = NULL; +static char *arg_data_what = NULL; +static char *arg_hash_what = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep); +STATIC_DESTRUCTOR_REGISTER(arg_data_what, freep); +STATIC_DESTRUCTOR_REGISTER(arg_hash_what, freep); + +static int create_device(void) { + _cleanup_free_ char *u = NULL, *v = NULL, *d = NULL, *e = NULL, *u_escaped = NULL, *v_escaped = NULL, *root_hash_escaped = NULL; + _cleanup_fclose_ FILE *f = NULL; + const char *to; + int r; + + /* If all three pieces of information are missing, then verity is turned off */ + if (!arg_root_hash && !arg_data_what && !arg_hash_what) + return 0; + + /* if one of them is missing however, the data is simply incomplete and this is an error */ + if (!arg_root_hash) + log_error("Verity information incomplete, root hash unspecified."); + if (!arg_data_what) + log_error("Verity information incomplete, root data device unspecified."); + if (!arg_hash_what) + log_error("Verity information incomplete, root hash device unspecified."); + + if (!arg_root_hash || !arg_data_what || !arg_hash_what) + return -EINVAL; + + log_debug("Using root verity data device %s,\n" + " hash device %s,\n" + " and root hash %s.", arg_data_what, arg_hash_what, arg_root_hash); + + u = fstab_node_to_udev_node(arg_data_what); + if (!u) + return log_oom(); + v = fstab_node_to_udev_node(arg_hash_what); + if (!v) + return log_oom(); + + u_escaped = specifier_escape(u); + if (!u_escaped) + return log_oom(); + v_escaped = specifier_escape(v); + if (!v_escaped) + return log_oom(); + + r = unit_name_from_path(u, ".device", &d); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + r = unit_name_from_path(v, ".device", &e); + if (r < 0) + return log_error_errno(r, "Failed to generate unit name: %m"); + + root_hash_escaped = specifier_escape(arg_root_hash); + if (!root_hash_escaped) + return log_oom(); + + r = generator_open_unit_file(arg_dest, NULL, SYSTEMD_VERITYSETUP_SERVICE, &f); + if (r < 0) + return r; + + fprintf(f, + "[Unit]\n" + "Description=Integrity Protection Setup for %%I\n" + "Documentation=man:systemd-veritysetup-generator(8) man:systemd-veritysetup@.service(8)\n" + "SourcePath=/proc/cmdline\n" + "DefaultDependencies=no\n" + "Conflicts=umount.target\n" + "BindsTo=%s %s\n" + "IgnoreOnIsolate=true\n" + "After=cryptsetup-pre.target %s %s\n" + "Before=cryptsetup.target umount.target\n" + "\n[Service]\n" + "Type=oneshot\n" + "RemainAfterExit=yes\n" + "ExecStart=" ROOTLIBEXECDIR "/systemd-veritysetup attach root '%s' '%s' '%s'\n" + "ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach root\n", + d, e, + d, e, + u_escaped, v_escaped, root_hash_escaped); + + r = fflush_and_check(f); + if (r < 0) + return log_error_errno(r, "Failed to write file unit "SYSTEMD_VERITYSETUP_SERVICE": %m"); + + to = strjoina(arg_dest, "/cryptsetup.target.requires/" SYSTEMD_VERITYSETUP_SERVICE); + + (void) mkdir_parents(to, 0755); + if (symlink("../" SYSTEMD_VERITYSETUP_SERVICE, to) < 0) + return log_error_errno(errno, "Failed to create symlink %s: %m", to); + + return 0; +} + +static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { + int r; + + if (proc_cmdline_key_streq(key, "systemd.verity")) { + + r = value ? parse_boolean(value) : 1; + if (r < 0) + log_warning("Failed to parse verity= kernel command line switch %s. Ignoring.", value); + else + arg_enabled = r; + + } else if (proc_cmdline_key_streq(key, "roothash")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = free_and_strdup(&arg_root_hash, value); + if (r < 0) + return log_oom(); + + } else if (proc_cmdline_key_streq(key, "systemd.verity_root_data")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = free_and_strdup(&arg_data_what, value); + if (r < 0) + return log_oom(); + + } else if (proc_cmdline_key_streq(key, "systemd.verity_root_hash")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = free_and_strdup(&arg_hash_what, value); + if (r < 0) + return log_oom(); + } + + return 0; +} + +static int determine_devices(void) { + _cleanup_free_ void *m = NULL; + sd_id128_t root_uuid, verity_uuid; + char ids[37]; + size_t l; + int r; + + /* Try to automatically derive the root data and hash device paths from the root hash */ + + if (!arg_root_hash) + return 0; + + if (arg_data_what && arg_hash_what) + return 0; + + r = unhexmem(arg_root_hash, strlen(arg_root_hash), &m, &l); + if (r < 0) + return log_error_errno(r, "Failed to parse root hash: %s", arg_root_hash); + if (l < sizeof(sd_id128_t)) { + log_debug("Root hash is shorter than 128 bits (32 characters), ignoring for discovering verity partition."); + return 0; + } + + if (!arg_data_what) { + memcpy(&root_uuid, m, sizeof(root_uuid)); + + arg_data_what = path_join("/dev/disk/by-partuuid", id128_to_uuid_string(root_uuid, ids)); + if (!arg_data_what) + return log_oom(); + } + + if (!arg_hash_what) { + memcpy(&verity_uuid, (uint8_t*) m + l - sizeof(verity_uuid), sizeof(verity_uuid)); + + arg_hash_what = path_join("/dev/disk/by-partuuid", id128_to_uuid_string(verity_uuid, ids)); + if (!arg_hash_what) + return log_oom(); + } + + return 1; +} + +static int run(const char *dest, const char *dest_early, const char *dest_late) { + int r; + + assert_se(arg_dest = dest); + + r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX); + if (r < 0) + return log_warning_errno(r, "Failed to parse kernel command line: %m"); + + /* For now we only support the root device on verity. Later on we might want to add support for /etc/veritytab + * or similar to define additional mappings */ + + if (!arg_enabled) + return 0; + + r = determine_devices(); + if (r < 0) + return r; + + return create_device(); +} + +DEFINE_MAIN_GENERATOR_FUNCTION(run); diff --git a/src/veritysetup/veritysetup.c b/src/veritysetup/veritysetup.c new file mode 100644 index 00000000..9c2fe9a1 --- /dev/null +++ b/src/veritysetup/veritysetup.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include +#include + +#include "alloc-util.h" +#include "crypt-util.h" +#include "hexdecoct.h" +#include "log.h" +#include "main-func.h" +#include "pretty-print.h" +#include "string-util.h" +#include "terminal-util.h" + +static char *arg_root_hash = NULL; +static char *arg_data_what = NULL; +static char *arg_hash_what = NULL; + +STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep); +STATIC_DESTRUCTOR_REGISTER(arg_data_what, freep); +STATIC_DESTRUCTOR_REGISTER(arg_hash_what, freep); + +static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("systemd-veritysetup@.service", "8", &link); + if (r < 0) + return log_oom(); + + printf("%s attach VOLUME DATADEVICE HASHDEVICE ROOTHASH\n" + "%s detach VOLUME\n\n" + "Attaches or detaches an integrity protected block device.\n" + "\nSee the %s for details.\n" + , program_invocation_short_name + , program_invocation_short_name + , link + ); + + return 0; +} + +static int run(int argc, char *argv[]) { + _cleanup_(crypt_freep) struct crypt_device *cd = NULL; + int r; + + if (argc <= 1) + return help(); + + if (argc < 3) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program requires at least two arguments."); + + log_setup_service(); + + umask(0022); + + if (streq(argv[1], "attach")) { + _cleanup_free_ void *m = NULL; + crypt_status_info status; + size_t l; + + if (argc < 6) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "attach requires at least two arguments."); + + r = unhexmem(argv[5], strlen(argv[5]), &m, &l); + if (r < 0) + return log_error_errno(r, "Failed to parse root hash: %m"); + + r = crypt_init(&cd, argv[4]); + if (r < 0) + return log_error_errno(r, "Failed to open verity device %s: %m", argv[4]); + + crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); + + status = crypt_status(cd, argv[2]); + if (IN_SET(status, CRYPT_ACTIVE, CRYPT_BUSY)) { + log_info("Volume %s already active.", argv[2]); + return 0; + } + + r = crypt_load(cd, CRYPT_VERITY, NULL); + if (r < 0) + return log_error_errno(r, "Failed to load verity superblock: %m"); + + r = crypt_set_data_device(cd, argv[3]); + if (r < 0) + return log_error_errno(r, "Failed to configure data device: %m"); + + r = crypt_activate_by_volume_key(cd, argv[2], m, l, CRYPT_ACTIVATE_READONLY); + if (r < 0) + return log_error_errno(r, "Failed to set up verity device: %m"); + + } else if (streq(argv[1], "detach")) { + + r = crypt_init_by_name(&cd, argv[2]); + if (r == -ENODEV) { + log_info("Volume %s already inactive.", argv[2]); + return 0; + } + if (r < 0) + return log_error_errno(r, "crypt_init_by_name() failed: %m"); + + crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); + + r = crypt_deactivate(cd, argv[2]); + if (r < 0) + return log_error_errno(r, "Failed to deactivate: %m"); + + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb %s.", argv[1]); + + return 0; +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/version/version.h.in b/src/version/version.h.in new file mode 100644 index 00000000..9f82d905 --- /dev/null +++ b/src/version/version.h.in @@ -0,0 +1 @@ +#define GIT_VERSION "@VCS_TAG@" diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c new file mode 100644 index 00000000..af78a87d --- /dev/null +++ b/src/volatile-root/volatile-root.c @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include + +#include "alloc-util.h" +#include "blockdev-util.h" +#include "escape.h" +#include "fs-util.h" +#include "main-func.h" +#include "mkdir.h" +#include "mount-util.h" +#include "mountpoint-util.h" +#include "path-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "volatile-util.h" + +static int make_volatile(const char *path) { + _cleanup_free_ char *old_usr = NULL; + int r; + + assert(path); + + r = chase_symlinks("/usr", path, CHASE_PREFIX_ROOT, &old_usr, NULL); + if (r < 0) + return log_error_errno(r, "/usr not available in old root: %m"); + + r = mkdir_p("/run/systemd/volatile-sysroot", 0700); + if (r < 0) + return log_error_errno(r, "Couldn't generate volatile sysroot directory: %m"); + + r = mount_verbose(LOG_ERR, "tmpfs", "/run/systemd/volatile-sysroot", "tmpfs", MS_STRICTATIME, "mode=755"); + if (r < 0) + goto finish_rmdir; + + if (mkdir("/run/systemd/volatile-sysroot/usr", 0755) < 0) { + r = log_error_errno(errno, "Failed to create /usr directory: %m"); + goto finish_umount; + } + + r = mount_verbose(LOG_ERR, old_usr, "/run/systemd/volatile-sysroot/usr", NULL, MS_BIND|MS_REC, NULL); + if (r < 0) + goto finish_umount; + + r = bind_remount_recursive("/run/systemd/volatile-sysroot/usr", MS_RDONLY, MS_RDONLY, NULL); + if (r < 0) { + log_error_errno(r, "Failed to remount /usr read-only: %m"); + goto finish_umount; + } + + r = umount_recursive(path, 0); + if (r < 0) { + log_error_errno(r, "Failed to unmount %s: %m", path); + goto finish_umount; + } + + if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) + log_warning_errno(errno, "Failed to remount %s MS_SLAVE|MS_REC, ignoring: %m", path); + + r = mount_verbose(LOG_ERR, "/run/systemd/volatile-sysroot", path, NULL, MS_MOVE, NULL); + +finish_umount: + (void) umount_recursive("/run/systemd/volatile-sysroot", 0); + +finish_rmdir: + (void) rmdir("/run/systemd/volatile-sysroot"); + + return r; +} + +static int make_overlay(const char *path) { + _cleanup_free_ char *escaped_path = NULL; + bool tmpfs_mounted = false; + const char *options = NULL; + int r; + + assert(path); + + r = mkdir_p("/run/systemd/overlay-sysroot", 0700); + if (r < 0) + return log_error_errno(r, "Couldn't create overlay sysroot directory: %m"); + + r = mount_verbose(LOG_ERR, "tmpfs", "/run/systemd/overlay-sysroot", "tmpfs", MS_STRICTATIME, "mode=755"); + if (r < 0) + goto finish; + + tmpfs_mounted = true; + + if (mkdir("/run/systemd/overlay-sysroot/upper", 0755) < 0) { + r = log_error_errno(errno, "Failed to create /run/systemd/overlay-sysroot/upper: %m"); + goto finish; + } + + if (mkdir("/run/systemd/overlay-sysroot/work", 0755) < 0) { + r = log_error_errno(errno, "Failed to create /run/systemd/overlay-sysroot/work: %m"); + goto finish; + } + + escaped_path = shell_escape(path, ",:"); + if (!escaped_path) { + r = log_oom(); + goto finish; + } + + options = strjoina("lowerdir=", escaped_path, ",upperdir=/run/systemd/overlay-sysroot/upper,workdir=/run/systemd/overlay-sysroot/work"); + r = mount_verbose(LOG_ERR, "overlay", path, "overlay", 0, options); + +finish: + if (tmpfs_mounted) + (void) umount_verbose("/run/systemd/overlay-sysroot"); + + (void) rmdir("/run/systemd/overlay-sysroot"); + return r; +} + +static int run(int argc, char *argv[]) { + VolatileMode m = _VOLATILE_MODE_INVALID; + const char *path; + dev_t devt; + int r; + + log_setup_service(); + + if (argc > 3) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Too many arguments. Expected directory and mode."); + + r = query_volatile_mode(&m); + if (r < 0) + return log_error_errno(r, "Failed to determine volatile mode from kernel command line."); + if (r == 0 && argc >= 2) { + /* The kernel command line always wins. However if nothing was set there, the argument passed here wins instead. */ + m = volatile_mode_from_string(argv[1]); + if (m < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Couldn't parse volatile mode: %s", argv[1]); + } + + if (argc < 3) + path = "/sysroot"; + else { + path = argv[2]; + + if (isempty(path)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Directory name cannot be empty."); + if (!path_is_absolute(path)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Directory must be specified as absolute path."); + if (path_equal(path, "/")) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Directory cannot be the root directory."); + } + + if (!IN_SET(m, VOLATILE_YES, VOLATILE_OVERLAY)) + return 0; + + r = path_is_mount_point(path, NULL, AT_SYMLINK_FOLLOW); + if (r < 0) + return log_error_errno(r, "Couldn't determine whether %s is a mount point: %m", path); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "%s is not a mount point.", path); + + r = path_is_temporary_fs(path); + if (r < 0) + return log_error_errno(r, "Couldn't determine whether %s is a temporary file system: %m", path); + if (r > 0) { + log_info("%s already is a temporary file system.", path); + return 0; + } + + /* We are about to replace the root directory with something else. Later code might want to know what we + * replaced here, hence let's save that information as a symlink we can later use. (This is particularly + * relevant for the overlayfs case where we'll fully obstruct the view onto the underlying device, hence + * querying the backing device node from the file system directly is no longer possible. */ + r = get_block_device_harder(path, &devt); + if (r < 0) + return log_error_errno(r, "Failed to determine device major/minor of %s: %m", path); + else if (r > 0) { + _cleanup_free_ char *dn = NULL; + + r = device_path_make_major_minor(S_IFBLK, devt, &dn); + if (r < 0) + return log_error_errno(r, "Failed to format device node path: %m"); + + if (symlink(dn, "/run/systemd/volatile-root") < 0) + log_warning_errno(errno, "Failed to create symlink /run/systemd/volatile-root: %m"); + } + + if (m == VOLATILE_YES) + return make_volatile(path); + else { + assert(m == VOLATILE_OVERLAY); + return make_overlay(path); + } +} + +DEFINE_MAIN_FUNCTION(run); diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in new file mode 100644 index 00000000..47bf8476 --- /dev/null +++ b/sysctl.d/50-coredump.conf.in @@ -0,0 +1,12 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See sysctl.d(5) for the description of the files in this directory, +# and systemd-coredump(8) and core(5) for the explanation of the +# setting below. + +kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %c %h diff --git a/sysctl.d/50-default.conf b/sysctl.d/50-default.conf new file mode 100644 index 00000000..41bd1f91 --- /dev/null +++ b/sysctl.d/50-default.conf @@ -0,0 +1,50 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See sysctl.d(5) and core(5) for documentation. + +# To override settings in this file, create a local file in /etc +# (e.g. /etc/sysctl.d/90-override.conf), and put any assignments +# there. + +# System Request functionality of the kernel (SYNC) +# +# Use kernel.sysrq = 1 to allow all keys. +# See https://www.kernel.org/doc/html/latest/admin-guide/sysrq.html for a list +# of values and keys. +kernel.sysrq = 16 + +# Append the PID to the core filename +kernel.core_uses_pid = 1 + +# Source route verification +net.ipv4.conf.all.rp_filter = 2 + +# Do not accept source routing +net.ipv4.conf.all.accept_source_route = 0 + +# Promote secondary addresses when the primary address is removed +net.ipv4.conf.all.promote_secondaries = 1 + +# ping(8) without CAP_NET_ADMIN and CAP_NET_RAW +# The upper limit is set to 2^31-1. Values greater than that get rejected by +# the kernel because of this definition in linux/include/net/ping.h: +# #define GID_T_MAX (((gid_t)~0U) >> 1) +# That's not so bad because values between 2^31 and 2^32-1 are reserved on +# systemd-based systems anyway: https://systemd.io/UIDS-GIDS.html#summary +-net.ipv4.ping_group_range = 0 2147483647 + +# Fair Queue CoDel packet scheduler to fight bufferbloat +net.core.default_qdisc = fq_codel + +# Enable hard and soft link protection +fs.protected_hardlinks = 1 +fs.protected_symlinks = 1 + +# Enable regular file and FIFO protection +fs.protected_regular = 1 +fs.protected_fifos = 1 diff --git a/sysctl.d/50-pid-max.conf b/sysctl.d/50-pid-max.conf new file mode 100644 index 00000000..1eff2d7e --- /dev/null +++ b/sysctl.d/50-pid-max.conf @@ -0,0 +1,16 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See sysctl.d(5) and core(5) for documentation. + +# To override settings in this file, create a local file in /etc +# (e.g. /etc/sysctl.d/90-override.conf), and put any assignments +# there. + +# Bump the numeric PID range to its maximum of 2^22 (from the in-kernel default +# of 2^16), to make PID collisions less likely. +kernel.pid_max = 4194304 diff --git a/sysctl.d/meson.build b/sysctl.d/meson.build new file mode 100644 index 00000000..3f072e3d --- /dev/null +++ b/sysctl.d/meson.build @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +install_data( + '50-default.conf', + install_dir : sysctldir) + +in_files = [] + +# Kernel determines PID_MAX_LIMIT by +# #define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \ +# (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT)) +if cc.sizeof('long') > 4 + install_data('50-pid-max.conf', install_dir : sysctldir) +endif + +if conf.get('ENABLE_COREDUMP') == 1 + in_files += ['50-coredump.conf'] +endif + +foreach file : in_files + gen = configure_file( + input : file + '.in', + output : file, + configuration : substs) + install_data(gen, + install_dir : sysctldir) +endforeach + +meson.add_install_script('sh', '-c', + mkdir_p.format(join_paths(sysconfdir, 'sysctl.d'))) diff --git a/sysusers.d/basic.conf.in b/sysusers.d/basic.conf.in new file mode 100644 index 00000000..8e358c02 --- /dev/null +++ b/sysusers.d/basic.conf.in @@ -0,0 +1,38 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# The superuser +u root 0 "Super User" /root + +# The nobody user for NFS file systems +u @NOBODY_USER_NAME@ 65534 "Nobody" - + +# Administrator group: can *see* more than normal users +g adm - - - + +# Administrator group: can *do* more than normal users +g wheel - - - + +# Access to certain kernel and userspace facilities +g kmem - - - +g tty @TTY_GID@ - - +g utmp - - - + +# Hardware access groups +g audio - - - +g cdrom - - - +g dialout - - - +g disk - - - +g input - - - +g kvm - - - +g lp - - - +g render - - - +g tape - - - +g video - - - + +# Default group for normal users +g users @USERS_GID@ - - diff --git a/sysusers.d/meson.build b/sysusers.d/meson.build new file mode 100644 index 00000000..eb99957e --- /dev/null +++ b/sysusers.d/meson.build @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +in_files = ['basic.conf'] + +enable_sysusers = conf.get('ENABLE_SYSUSERS') == 1 + +foreach file : in_files + gen = configure_file( + input : file + '.in', + output : file, + configuration : substs) + if enable_sysusers + install_data(gen, + install_dir : sysusersdir) + endif +endforeach + +m4_files = ['systemd.conf'] + +if conf.get('ENABLE_REMOTE') == 1 and conf.get('HAVE_MICROHTTPD') == 1 + m4_files += ['systemd-remote.conf'] +endif + +foreach file : m4_files + custom_target( + 'sysusers.d_' + file, + input : file + '.m4', + output: file, + command : [meson_apply_m4, config_h, '@INPUT@'], + capture : true, + install : enable_sysusers, + install_dir : sysusersdir) +endforeach diff --git a/sysusers.d/systemd-remote.conf.m4 b/sysusers.d/systemd-remote.conf.m4 new file mode 100644 index 00000000..98891767 --- /dev/null +++ b/sysusers.d/systemd-remote.conf.m4 @@ -0,0 +1,10 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +m4_ifdef(`HAVE_MICROHTTPD', +u systemd-journal-remote - "systemd Journal Remote" +)m4_dnl diff --git a/sysusers.d/systemd.conf.m4 b/sysusers.d/systemd.conf.m4 new file mode 100644 index 00000000..ef5a3cb6 --- /dev/null +++ b/sysusers.d/systemd.conf.m4 @@ -0,0 +1,20 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +g systemd-journal - - +m4_ifdef(`ENABLE_NETWORKD', +u systemd-network - "systemd Network Management" +)m4_dnl +m4_ifdef(`ENABLE_RESOLVE', +u systemd-resolve - "systemd Resolver" +)m4_dnl +m4_ifdef(`ENABLE_TIMESYNCD', +u systemd-timesync - "systemd Time Synchronization" +)m4_dnl +m4_ifdef(`ENABLE_COREDUMP', +u systemd-coredump - "systemd Core Dumper" +)m4_dnl diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 00000000..fd7483da --- /dev/null +++ b/test/.gitignore @@ -0,0 +1,5 @@ +.testdir +test.log +/dev +/run +/sys diff --git a/test/README.testsuite b/test/README.testsuite new file mode 100644 index 00000000..9e0c3651 --- /dev/null +++ b/test/README.testsuite @@ -0,0 +1,122 @@ +The extended testsuite only works with UID=0. It contains of several +subdirectories named "test/TEST-??-*", which are run one by one. + +To run the extended testsuite do the following: + +$ ninja -C build # Avoid building anything as root later +$ sudo test/run-integration-tests.sh +ninja: Entering directory `/home/zbyszek/src/systemd/build' +ninja: no work to do. +--x-- Running TEST-01-BASIC --x-- ++ make -C TEST-01-BASIC BUILD_DIR=/home/zbyszek/src/systemd/build clean setup run +make: Entering directory '/home/zbyszek/src/systemd/test/TEST-01-BASIC' +TEST CLEANUP: Basic systemd setup +TEST SETUP: Basic systemd setup +... +TEST RUN: Basic systemd setup [OK] +make: Leaving directory '/home/zbyszek/src/systemd/test/TEST-01-BASIC' +--x-- Result of TEST-01-BASIC: 0 --x-- +--x-- Running TEST-02-CRYPTSETUP --x-- ++ make -C TEST-02-CRYPTSETUP BUILD_DIR=/home/zbyszek/src/systemd/build clean setup run + +If one of the tests fails, then $subdir/test.log contains the log file of +the test. + +To run just one of the cases: + +$ sudo make -C test/TEST-01-BASIC clean setup run + +Specifying the build directory +============================== + +If the build directory is not detected automatically, it can be specified +with BUILD_DIR=: + +$ sudo BUILD_DIR=some-other-build/ test/run-integration-tests + +or + +$ sudo make -C test/TEST-01-BASIC BUILD_DIR=../../some-other-build/ ... + +Note that in the second case, the path is relative to the test case directory. +An absolute path may also be used in both cases. + +Configuration variables +======================= + +TEST_NO_QEMU=1 + Don't run tests under QEMU + +TEST_NO_NSPAWN=1 + Don't run tests under systemd-nspawn + +TEST_NO_KVM=1 + Disable QEMU KVM autodetection (may be necessary when you're trying to run the + *vanilla* QEMU and have both qemu and qemu-kvm installed) + +TEST_NESTED_KVM=1 + Allow tests to run with nested KVM. By default, the testsuite disables + nested KVM if the host machine already runs under KVM. Setting this + variable disables such checks + +QEMU_MEM=512M + Configure amount of memory for QEMU VMs (defaults to 512M) + +QEMU_SMP=1 + Configure number of CPUs for QEMU VMs (defaults to 1) + +KERNEL_APPEND='...' + Append additional parameters to the kernel command line + +NSPAWN_ARGUMENTS='...' + Specify additional arguments for systemd-nspawn + +QEMU_TIMEOUT=infinity + Set a timeout for tests under QEMU (defaults to infinity) + +NSPAWN_TIMEOUT=infinity + Set a timeout for tests under systemd-nspawn (defaults to infinity) + +INTERACTIVE_DEBUG=1 + Configure the machine to be more *user-friendly* for interactive debuggung + (e.g. by setting a usable default terminal, suppressing the shutdown after + the test, etc.) + +The kernel and initramfs can be specified with $KERNEL_BIN and $INITRD. +(Fedora's or Debian's default kernel path and initramfs are used by default) + +A script will try to find your QEMU binary. If you want to specify a different +one with $QEMU_BIN. + +Debugging the qemu image +======================== + +If you want to log in the testsuite virtual machine, you can specify additional +kernel command line parameter with $KERNEL_APPEND and then log in as root. + +$ sudo make -C test/TEST-01-BASIC KERNEL_APPEND="systemd.unit=multi-user.target" run + +Root password is empty. + +Ubuntu CI +========= + +New PR submitted to the project are run through regression tests, and one set +of those is the 'autopkgtest' runs for several different architectures, called +'Ubuntu CI'. Part of that testing is to run all these tests. Sometimes these +tests are temporarily blacklisted from running in the 'autopkgtest' tests while +debugging a flaky test; that is done by creating a file in the test directory +named 'blacklist-ubuntu-ci', for example to prevent the TEST-01-BASIC test from +running in the 'autopkgtest' runs, create the file +'TEST-01-BASIC/blacklist-ubuntu-ci'. + +The tests may be disabled only for specific archs, by creating a blacklist file +with the arch name at the end, e.g. +'TEST-01-BASIC/blacklist-ubuntu-ci-arm64' to disable the TEST-01-BASIC test +only on test runs for the 'arm64' architecture. + +Note the arch naming is not from 'uname -m', it is Debian arch names: +https://wiki.debian.org/ArchitectureSpecificsMemo + +For PRs that fix a currently blacklisted test, the PR should include removal +of the blacklist file. diff --git a/test/TEST-01-BASIC/Makefile b/test/TEST-01-BASIC/Makefile new file mode 100644 index 00000000..45e9bfc6 --- /dev/null +++ b/test/TEST-01-BASIC/Makefile @@ -0,0 +1,9 @@ +BUILD_DIR=$(shell ../../tools/find-build-dir.sh) + +all setup run: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@ + +clean clean-again: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --clean + +.PHONY: all setup run clean clean-again diff --git a/test/TEST-01-BASIC/test.sh b/test/TEST-01-BASIC/test.sh new file mode 100755 index 00000000..007ee7a9 --- /dev/null +++ b/test/TEST-01-BASIC/test.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="Basic systemd setup" +RUN_IN_UNPRIVILEGED_CONTAINER=${RUN_IN_UNPRIVILEGED_CONTAINER:-yes} + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /failed ; systemctl daemon-reload ; echo OK > /testok' +Type=oneshot +EOF + + setup_testsuite + ) + setup_nspawn_root +} + +do_test "$@" diff --git a/test/TEST-02-CRYPTSETUP/Makefile b/test/TEST-02-CRYPTSETUP/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-02-CRYPTSETUP/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh new file mode 100755 index 00000000..a7563f44 --- /dev/null +++ b/test/TEST-02-CRYPTSETUP/test.sh @@ -0,0 +1,89 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="cryptsetup systemd setup" +TEST_NO_NSPAWN=1 + +. $TEST_BASE_DIR/test-functions + +check_result_qemu() { + ret=1 + mkdir -p $initdir + mount ${LOOPDEV}p1 $initdir + [[ -e $initdir/testok ]] && ret=0 + [[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR + cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile + mount /dev/mapper/varcrypt $initdir/var + cp -a $initdir/var/log/journal $TESTDIR + umount $initdir/var + umount $initdir + cryptsetup luksClose /dev/mapper/varcrypt + [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed + ls -l $TESTDIR/journal/*/*.journal + test -s $TESTDIR/failed && ret=$(($ret+1)) + return $ret +} + + +test_setup() { + create_empty_image_rootdir + echo -n test >$TESTDIR/keyfile + cryptsetup -q luksFormat --pbkdf pbkdf2 --pbkdf-force-iterations 1000 ${LOOPDEV}p2 $TESTDIR/keyfile + cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile + mkfs.ext4 -L var /dev/mapper/varcrypt + mkdir -p $initdir/var + mount /dev/mapper/varcrypt $initdir/var + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=/dev/mapper/varcrypt) + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /failed ; echo OK > /testok' +Type=oneshot +EOF + + setup_testsuite + + install_dmevent + generate_module_dependencies + cat >$initdir/etc/crypttab < $initdir/etc/varkey + cat $initdir/etc/crypttab | ddebug + + cat >>$initdir/etc/fstab < /root/list-jobs.txt +while ! grep 'sleep\.service.*running' /root/list-jobs.txt; do + systemctl list-jobs > /root/list-jobs.txt +done + +grep 'hello\.service.*waiting' /root/list-jobs.txt + +# This is supposed to finish quickly, not wait for sleep to finish. +START_SEC=$(date -u '+%s') +systemctl start --job-mode=ignore-dependencies hello +END_SEC=$(date -u '+%s') +ELAPSED=$(($END_SEC-$START_SEC)) + +[ "$ELAPSED" -lt 3 ] + +# sleep should still be running, hello not. +systemctl list-jobs > /root/list-jobs.txt +grep 'sleep\.service.*running' /root/list-jobs.txt +grep 'hello\.service' /root/list-jobs.txt && exit 1 +systemctl stop sleep.service hello-after-sleep.target + +# Some basic testing that --show-transaction does something useful +! systemctl is-active systemd-importd +systemctl -T start systemd-importd +systemctl is-active systemd-importd +systemctl --show-transaction stop systemd-importd +! systemctl is-active systemd-importd + +# Test for a crash when enqueuing a JOB_NOP when other job already exists +systemctl start --no-block hello-after-sleep.target +# hello.service should still be waiting, so these try-restarts will collapse +# into NOPs. +systemctl try-restart --job-mode=fail hello.service +systemctl try-restart hello.service +systemctl stop hello.service sleep.service hello-after-sleep.target + +# TODO: add more job queueing/merging tests here. + +# Test for irreversible jobs +systemctl start unstoppable.service + +# This is expected to fail with 'job cancelled' +systemctl stop unstoppable.service && exit 1 +# But this should succeed +systemctl stop --job-mode=replace-irreversibly unstoppable.service + +# We're going to shutdown soon. Let's see if it succeeds when +# there's an active service that tries to be unstoppable. +# Shutdown of the container/VM will hang if not. +systemctl start unstoppable.service + +# Test waiting for a started unit(s) to terminate again +cat < /run/systemd/system/wait2.service +[Unit] +Description=Wait for 2 seconds +[Service] +ExecStart=/bin/sh -ec 'sleep 2' +EOF +cat < /run/systemd/system/wait5fail.service +[Unit] +Description=Wait for 5 seconds and fail +[Service] +ExecStart=/bin/sh -ec 'sleep 5; false' +EOF + +# wait2 succeeds +START_SEC=$(date -u '+%s') +systemctl start --wait wait2.service +END_SEC=$(date -u '+%s') +ELAPSED=$(($END_SEC-$START_SEC)) +[[ "$ELAPSED" -ge 2 ]] && [[ "$ELAPSED" -le 4 ]] || exit 1 + +# wait5fail fails, so systemctl should fail +START_SEC=$(date -u '+%s') +! systemctl start --wait wait2.service wait5fail.service || exit 1 +END_SEC=$(date -u '+%s') +ELAPSED=$(($END_SEC-$START_SEC)) +[[ "$ELAPSED" -ge 5 ]] && [[ "$ELAPSED" -le 7 ]] || exit 1 + +# Test time-limited scopes +START_SEC=$(date -u '+%s') +set +e +systemd-run --scope --property=RuntimeMaxSec=3s sleep 10 +RESULT=$? +END_SEC=$(date -u '+%s') +ELAPSED=$(($END_SEC-$START_SEC)) +[[ "$ELAPSED" -ge 3 ]] && [[ "$ELAPSED" -le 5 ]] || exit 1 +[[ "$RESULT" -ne 0 ]] || exit 1 + +touch /testok diff --git a/test/TEST-03-JOBS/test.sh b/test/TEST-03-JOBS/test.sh new file mode 100755 index 00000000..50b7bce3 --- /dev/null +++ b/test/TEST-03-JOBS/test.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="Job-related tests" +TEST_NO_QEMU=1 + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service </expected +printf $'\n\n\n' | systemd-cat -t "$ID" --level-prefix false +journalctl --sync +journalctl -b -o cat -t "$ID" >/output +cmp /expected /output + +ID=$(journalctl --new-id128 | sed -n 2p) +>/expected +printf $'<5>\n<6>\n<7>\n' | systemd-cat -t "$ID" --level-prefix true +journalctl --sync +journalctl -b -o cat -t "$ID" >/output +cmp /expected /output + +# Remove trailing spaces +ID=$(journalctl --new-id128 | sed -n 2p) +printf "Trailing spaces\n">/expected +printf $'<5>Trailing spaces \t \n' | systemd-cat -t "$ID" --level-prefix true +journalctl --sync +journalctl -b -o cat -t "$ID" >/output +cmp /expected /output + +ID=$(journalctl --new-id128 | sed -n 2p) +printf "Trailing spaces\n">/expected +printf $'Trailing spaces \t \n' | systemd-cat -t "$ID" --level-prefix false +journalctl --sync +journalctl -b -o cat -t "$ID" >/output +cmp /expected /output + +# Don't remove leading spaces +ID=$(journalctl --new-id128 | sed -n 2p) +printf $' \t Leading spaces\n'>/expected +printf $'<5> \t Leading spaces\n' | systemd-cat -t "$ID" --level-prefix true +journalctl --sync +journalctl -b -o cat -t "$ID" >/output +cmp /expected /output + +ID=$(journalctl --new-id128 | sed -n 2p) +printf $' \t Leading spaces\n'>/expected +printf $' \t Leading spaces\n' | systemd-cat -t "$ID" --level-prefix false +journalctl --sync +journalctl -b -o cat -t "$ID" >/output +cmp /expected /output + +# --output-fields restricts output +ID=$(journalctl --new-id128 | sed -n 2p) +printf $'foo' | systemd-cat -t "$ID" --level-prefix false +journalctl --sync +journalctl -b -o export --output-fields=MESSAGE,FOO --output-fields=PRIORITY,MESSAGE -t "$ID" >/output +[[ `grep -c . /output` -eq 6 ]] +grep -q '^__CURSOR=' /output +grep -q '^MESSAGE=foo$' /output +grep -q '^PRIORITY=6$' /output +! grep -q '^FOO=' /output +! grep -q '^SYSLOG_FACILITY=' /output + +# `-b all` negates earlier use of -b (-b and -m are otherwise exclusive) +journalctl -b -1 -b all -m > /dev/null + +# -b always behaves like -b0 +journalctl -q -b-1 -b0 | head -1 > /expected +journalctl -q -b-1 -b | head -1 > /output +cmp /expected /output +# ... even when another option follows (both of these should fail due to -m) +{ journalctl -ball -b0 -m 2>&1 || :; } | head -1 > /expected +{ journalctl -ball -b -m 2>&1 || :; } | head -1 > /output +cmp /expected /output + +# https://github.com/systemd/systemd/issues/13708 +ID=$(systemd-id128 new) +systemd-cat -t "$ID" bash -c 'echo parent; (echo child) & wait' & +PID=$! +wait %% +journalctl --sync +# We can drop this grep when https://github.com/systemd/systemd/issues/13937 +# has a fix. +journalctl -b -o export -t "$ID" --output-fields=_PID | grep '^_PID=' >/output +[[ `grep -c . /output` -eq 2 ]] +grep -q "^_PID=$PID" /output +grep -vq "^_PID=$PID" /output + +# Add new tests before here, the journald restarts below +# may make tests flappy. + +# Don't lose streams on restart +systemctl start forever-print-hola +sleep 3 +systemctl restart systemd-journald +sleep 3 +systemctl stop forever-print-hola +[[ ! -f "/i-lose-my-logs" ]] + +# https://github.com/systemd/systemd/issues/4408 +rm -f /i-lose-my-logs +systemctl start forever-print-hola +sleep 3 +systemctl kill --signal=SIGKILL systemd-journald +sleep 3 +[[ ! -f "/i-lose-my-logs" ]] + +touch /testok diff --git a/test/TEST-04-JOURNAL/test.sh b/test/TEST-04-JOURNAL/test.sh new file mode 100755 index 00000000..a18d2153 --- /dev/null +++ b/test/TEST-04-JOURNAL/test.sh @@ -0,0 +1,44 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="Journal-related tests" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/forever-print-hola.service <$initdir/etc/systemd/system.conf <$initdir/etc/systemd/system/testsuite.service </sys/fs/selinux/enforce +runcon -t systemd_test_start_t systemctl start hola +runcon -t systemd_test_reload_t systemctl reload hola +runcon -t systemd_test_stop_t systemctl stop hola + +touch /testok diff --git a/test/TEST-06-SELINUX/test.sh b/test/TEST-06-SELINUX/test.sh new file mode 100755 index 00000000..646dfe02 --- /dev/null +++ b/test/TEST-06-SELINUX/test.sh @@ -0,0 +1,97 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="SELinux tests" +TEST_NO_NSPAWN=1 + +# Requirements: +# Fedora 23 +# selinux-policy-targeted +# selinux-policy-devel + +# Check if selinux-policy-devel is installed, and if it isn't bail out early instead of failing +test -f /usr/share/selinux/devel/include/system/systemd.if || exit 0 + +. $TEST_BASE_DIR/test-functions +SETUP_SELINUX=yes +KERNEL_APPEND="$KERNEL_APPEND selinux=1 security=selinux" + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat <$initdir/etc/systemd/system/testsuite.service +[Unit] +Description=Testsuite service + +[Service] +ExecStart=/test-selinux-checks.sh +Type=oneshot +EOF + + cat <$initdir/etc/systemd/system/hola.service +[Service] +Type=oneshot +ExecStart=/bin/echo Start Hola +ExecReload=/bin/echo Reload Hola +ExecStop=/bin/echo Stop Hola +RemainAfterExit=yes +EOF + + setup_testsuite + + cat <$initdir/etc/systemd/system/load-systemd-test-module.service +[Unit] +Description=Load systemd-test module +DefaultDependencies=no +Requires=local-fs.target +Conflicts=shutdown.target +After=local-fs.target +Before=sysinit.target shutdown.target autorelabel.service +ConditionSecurity=selinux +ConditionPathExists=|/.load-systemd-test-module + +[Service] +ExecStart=/bin/sh -x -c 'echo 0 >/sys/fs/selinux/enforce && cd /systemd-test-module && make -f /usr/share/selinux/devel/Makefile load && rm /.load-systemd-test-module' +Type=oneshot +TimeoutSec=0 +RemainAfterExit=yes +EOF + + touch $initdir/.load-systemd-test-module + mkdir -p $initdir/etc/systemd/system/basic.target.wants + ln -fs load-systemd-test-module.service $initdir/etc/systemd/system/basic.target.wants/load-systemd-test-module.service + + local _modules_dir=/var/lib/selinux + rm -rf $initdir/$_modules_dir + if ! cp -ar $_modules_dir $initdir/$_modules_dir; then + dfatal "Failed to copy $_modules_dir" + exit 1 + fi + + local _policy_headers_dir=/usr/share/selinux/devel + rm -rf $initdir/$_policy_headers_dir + inst_dir /usr/share/selinux + if ! cp -ar $_policy_headers_dir $initdir/$_policy_headers_dir; then + dfatal "Failed to copy $_policy_headers_dir" + exit 1 + fi + + mkdir $initdir/systemd-test-module + cp systemd_test.te $initdir/systemd-test-module + cp systemd_test.if $initdir/systemd-test-module + cp test-selinux-checks.sh $initdir + dracut_install -o sesearch + dracut_install runcon + dracut_install checkmodule semodule semodule_package m4 make /usr/libexec/selinux/hll/pp load_policy sefcontext_compile + ) +} + +do_test "$@" diff --git a/test/TEST-07-ISSUE-1981/Makefile b/test/TEST-07-ISSUE-1981/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-07-ISSUE-1981/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-07-ISSUE-1981/test-segfault.sh b/test/TEST-07-ISSUE-1981/test-segfault.sh new file mode 100755 index 00000000..82339c23 --- /dev/null +++ b/test/TEST-07-ISSUE-1981/test-segfault.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -x +set -e + +>/failed + +cat <<'EOL' >/lib/systemd/system/my.service +[Service] +Type=oneshot +ExecStart=/bin/echo Timer runs me +EOL + +cat <<'EOL' >/lib/systemd/system/my.timer +[Timer] +OnBootSec=10s +OnUnitInactiveSec=1h +EOL + +systemctl unmask my.timer + +systemctl start my.timer + +mkdir -p /etc/systemd/system/my.timer.d/ +cat <<'EOL' >/etc/systemd/system/my.timer.d/override.conf +[Timer] +OnBootSec=10s +OnUnitInactiveSec=1h +EOL + +systemctl daemon-reload + +systemctl mask my.timer + +touch /testok +rm /failed diff --git a/test/TEST-07-ISSUE-1981/test.sh b/test/TEST-07-ISSUE-1981/test.sh new file mode 100755 index 00000000..e72c11fd --- /dev/null +++ b/test/TEST-07-ISSUE-1981/test.sh @@ -0,0 +1,38 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/1981" +TEST_NO_QEMU=1 + +. $TEST_BASE_DIR/test-functions + +NSPAWN_TIMEOUT=30 + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service < /testok; systemctl poweroff' +Type=oneshot +EOF + + rm $initdir/etc/fstab + cat >$initdir/etc/systemd/system/-.mount <$initdir/etc/systemd/system/systemd-remount-fs.service <$initdir/etc/systemd/system/testsuite.service <<'EOF' +[Unit] +Description=Testsuite service + +[Service] +Type=oneshot +ExecStart=/bin/sh -c '>/testok' +RemainAfterExit=yes +ExecStop=/bin/sh -c 'kill -SEGV $$$$' +TimeoutStopSec=270s +EOF + + setup_testsuite + ) +} + +do_test "$@" diff --git a/test/TEST-10-ISSUE-2467/Makefile b/test/TEST-10-ISSUE-2467/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-10-ISSUE-2467/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-10-ISSUE-2467/test.sh b/test/TEST-10-ISSUE-2467/test.sh new file mode 100755 index 00000000..7bb25696 --- /dev/null +++ b/test/TEST-10-ISSUE-2467/test.sh @@ -0,0 +1,48 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/2467" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + dracut_install true rm socat + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <<'EOF' +[Unit] +Description=Testsuite service + +[Service] +Type=oneshot +ExecStart=/bin/sh -e -x -c 'rm -f /tmp/nonexistent; systemctl start test.socket; printf x > test.file; socat -t20 OPEN:test.file UNIX-CONNECT:/run/test.ctl; >/testok' +EOF + + cat >$initdir/etc/systemd/system/test.socket <<'EOF' +[Socket] +ListenStream=/run/test.ctl +EOF + + cat > $initdir/etc/systemd/system/test.service <<'EOF' +[Unit] +Requires=test.socket +ConditionPathExistsGlob=/tmp/nonexistent + +[Service] +ExecStart=/bin/true +EOF + + setup_testsuite + ) + setup_nspawn_root +} + +do_test "$@" diff --git a/test/TEST-11-ISSUE-3166/Makefile b/test/TEST-11-ISSUE-3166/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-11-ISSUE-3166/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-11-ISSUE-3166/test.sh b/test/TEST-11-ISSUE-3166/test.sh new file mode 100755 index 00000000..81c12a27 --- /dev/null +++ b/test/TEST-11-ISSUE-3166/test.sh @@ -0,0 +1,61 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/3166" +TEST_NO_NSPAWN=1 + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + dracut_install false touch + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/fail-on-restart.service <$initdir/test-fail-on-restart.sh <<'EOF' +#!/bin/bash -x + +systemctl start fail-on-restart.service +active_state=$(systemctl show --property ActiveState fail-on-restart.service) +while [[ "$active_state" == "ActiveState=activating" || "$active_state" == "ActiveState=active" ]]; do + sleep 1 + active_state=$(systemctl show --property ActiveState fail-on-restart.service) +done +systemctl is-failed fail-on-restart.service || exit 1 +touch /testok +EOF + + chmod 0755 $initdir/test-fail-on-restart.sh + setup_testsuite + ) +} + +do_test "$@" diff --git a/test/TEST-12-ISSUE-3171/Makefile b/test/TEST-12-ISSUE-3171/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-12-ISSUE-3171/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-12-ISSUE-3171/test.sh b/test/TEST-12-ISSUE-3171/test.sh new file mode 100755 index 00000000..d9a0e1a3 --- /dev/null +++ b/test/TEST-12-ISSUE-3171/test.sh @@ -0,0 +1,89 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/3171" +TEST_NO_QEMU=1 + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + dracut_install cat mv stat nc + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <$initdir/test-socket-group.sh <<'EOF' +#!/bin/bash +set -x +set -e +set -o pipefail + +U=/run/systemd/system/test.socket +cat <<'EOL' >$U +[Unit] +Description=Test socket +[Socket] +Accept=yes +ListenStream=/run/test.socket +SocketGroup=adm +SocketMode=0660 +EOL + +cat <<'EOL' > /run/systemd/system/test@.service +[Unit] +Description=Test service +[Service] +StandardInput=socket +ExecStart=/bin/sh -x -c cat +EOL + +systemctl start test.socket +systemctl is-active test.socket +[[ "$(stat --format='%G' /run/test.socket)" == adm ]] +echo A | nc -w1 -U /run/test.socket + +mv $U ${U}.disabled +systemctl daemon-reload +systemctl is-active test.socket +[[ "$(stat --format='%G' /run/test.socket)" == adm ]] +echo B | nc -w1 -U /run/test.socket && exit 1 + +mv ${U}.disabled $U +systemctl daemon-reload +systemctl is-active test.socket +echo C | nc -w1 -U /run/test.socket && exit 1 +[[ "$(stat --format='%G' /run/test.socket)" == adm ]] + +systemctl restart test.socket +systemctl is-active test.socket +echo D | nc -w1 -U /run/test.socket +[[ "$(stat --format='%G' /run/test.socket)" == adm ]] + + +touch /testok +EOF + + chmod 0755 $initdir/test-socket-group.sh + setup_testsuite + ) + + setup_nspawn_root +} + +do_test "$@" diff --git a/test/TEST-13-NSPAWN-SMOKE/Makefile b/test/TEST-13-NSPAWN-SMOKE/Makefile new file mode 100644 index 00000000..e5e33502 --- /dev/null +++ b/test/TEST-13-NSPAWN-SMOKE/Makefile @@ -0,0 +1,10 @@ +BUILD_DIR=$(shell ../../tools/find-build-dir.sh) + +all setup run: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@ + +clean clean-again: + @basedir=../.. TEST_BASE_DIR=../ ./test.sh --clean + @rm -f has-overflow + +.PHONY: all setup run clean clean-again diff --git a/test/TEST-13-NSPAWN-SMOKE/create-busybox-container b/test/TEST-13-NSPAWN-SMOKE/create-busybox-container new file mode 100755 index 00000000..868dfd85 --- /dev/null +++ b/test/TEST-13-NSPAWN-SMOKE/create-busybox-container @@ -0,0 +1,53 @@ +#!/bin/bash + +set -e +set -u +set -o pipefail + +root="${1:?Usage $0 container-root}" +mkdir -p "$root" +mkdir "$root/bin" +cp $(type -P busybox) "$root/bin" + +mkdir -p "$root/usr/lib" +touch "$root/usr/lib/os-release" + +ln -s busybox "$root/bin/sh" +ln -s busybox "$root/bin/cat" +ln -s busybox "$root/bin/tr" +ln -s busybox "$root/bin/ps" +ln -s busybox "$root/bin/ip" + +mkdir -p "$root/sbin" +cat <<'EOF' >"$root/sbin/init" +#!/bin/sh + +printf "ps aufx:\n" +ps aufx + +printf "/proc/1/cmdline:\n" +printf "%s\n\n" "$(tr '\0' ' ' $initdir/etc/systemd/system/testsuite.service <$initdir/test-nspawn.sh <<'EOF' +#!/bin/bash +set -x +set -e +set -u +set -o pipefail + +export SYSTEMD_LOG_LEVEL=debug + +# check cgroup-v2 +is_v2_supported=no +mkdir -p /tmp/cgroup2 +if mount -t cgroup2 cgroup2 /tmp/cgroup2; then + is_v2_supported=yes + umount /tmp/cgroup2 +fi +rmdir /tmp/cgroup2 + +# check cgroup namespaces +is_cgns_supported=no +if [[ -f /proc/1/ns/cgroup ]]; then + is_cgns_supported=yes +fi + +is_user_ns_supported=no +# On some systems (e.g. CentOS 7) the default limit for user namespaces +# is set to 0, which causes the following unshare syscall to fail, even +# with enabled user namespaces support. By setting this value explicitly +# we can ensure the user namespaces support to be detected correctly. +sysctl -w user.max_user_namespaces=10000 +if unshare -U sh -c :; then + is_user_ns_supported=yes +fi + +function check_bind_tmp_path { + # https://github.com/systemd/systemd/issues/4789 + local _root="/var/lib/machines/bind-tmp-path" + /create-busybox-container "$_root" + >/tmp/bind + systemd-nspawn --register=no -D "$_root" --bind=/tmp/bind /bin/sh -c 'test -e /tmp/bind' +} + +function check_norbind { + # https://github.com/systemd/systemd/issues/13170 + local _root="/var/lib/machines/norbind-path" + mkdir -p /tmp/binddir/subdir + echo -n "outer" > /tmp/binddir/subdir/file + mount -t tmpfs tmpfs /tmp/binddir/subdir + echo -n "inner" > /tmp/binddir/subdir/file + /create-busybox-container "$_root" + systemd-nspawn --register=no -D "$_root" --bind=/tmp/binddir:/mnt:norbind /bin/sh -c 'CONTENT=$(cat /mnt/subdir/file); if [[ $CONTENT != "outer" ]]; then echo "*** unexpected content: $CONTENT"; return 1; fi' +} + +function check_notification_socket { + # https://github.com/systemd/systemd/issues/4944 + local _cmd='echo a | $(busybox which nc) -U -u -w 1 /run/systemd/nspawn/notify' + systemd-nspawn --register=no -D /nc-container /bin/sh -x -c "$_cmd" + systemd-nspawn --register=no -D /nc-container -U /bin/sh -x -c "$_cmd" +} + +function run { + if [[ "$1" = "yes" && "$is_v2_supported" = "no" ]]; then + printf "Unified cgroup hierarchy is not supported. Skipping.\n" >&2 + return 0 + fi + if [[ "$2" = "yes" && "$is_cgns_supported" = "no" ]]; then + printf "CGroup namespaces are not supported. Skipping.\n" >&2 + return 0 + fi + + local _root="/var/lib/machines/unified-$1-cgns-$2-api-vfs-writable-$3" + /create-busybox-container "$_root" + SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" -b + SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" --private-network -b + + if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" -U -b; then + [[ "$is_user_ns_supported" = "yes" && "$3" = "network" ]] && return 1 + else + [[ "$is_user_ns_supported" = "no" && "$3" = "network" ]] && return 1 + fi + + if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" --private-network -U -b; then + [[ "$is_user_ns_supported" = "yes" && "$3" = "yes" ]] && return 1 + else + [[ "$is_user_ns_supported" = "no" && "$3" = "yes" ]] && return 1 + fi + + local _netns_opt="--network-namespace-path=/proc/self/ns/net" + + # --network-namespace-path and network-related options cannot be used together + if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-interface=lo -b; then + return 1 + fi + + if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-macvlan=lo -b; then + return 1 + fi + + if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-ipvlan=lo -b; then + return 1 + fi + + if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-veth -b; then + return 1 + fi + + if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-veth-extra=lo -b; then + return 1 + fi + + if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-bridge=lo -b; then + return 1 + fi + + if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --network-zone=zone -b; then + return 1 + fi + + if SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" --private-network -b; then + return 1 + fi + + # test --network-namespace-path works with a network namespace created by "ip netns" + ip netns add nspawn_test + _netns_opt="--network-namespace-path=/run/netns/nspawn_test" + SYSTEMD_NSPAWN_UNIFIED_HIERARCHY="$1" SYSTEMD_NSPAWN_USE_CGNS="$2" SYSTEMD_NSPAWN_API_VFS_WRITABLE="$3" systemd-nspawn --register=no -D "$_root" "$_netns_opt" /bin/ip a | grep -v -E '^1: lo.*UP' + local r=$? + ip netns del nspawn_test + + if [ $r -ne 0 ]; then + return 1 + fi + + return 0 +} + +check_bind_tmp_path + +check_norbind + +check_notification_socket + +for api_vfs_writable in yes no network; do + run no no $api_vfs_writable + run yes no $api_vfs_writable + run no yes $api_vfs_writable + run yes yes $api_vfs_writable +done + +touch /testok +EOF + + chmod 0755 $initdir/test-nspawn.sh + setup_testsuite + ) +} + +do_test "$@" diff --git a/test/TEST-14-MACHINE-ID/Makefile b/test/TEST-14-MACHINE-ID/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-14-MACHINE-ID/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-14-MACHINE-ID/test.sh b/test/TEST-14-MACHINE-ID/test.sh new file mode 100755 index 00000000..72d7eacb --- /dev/null +++ b/test/TEST-14-MACHINE-ID/test.sh @@ -0,0 +1,78 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="/etc/machine-id testing" +TEST_NO_NSPAWN=1 + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + printf "556f48e837bc4424a710fa2e2c9d3e3c\ne3d\n" >$initdir/etc/machine-id + dracut_install mount cmp + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /failed ; echo OK > /testok' +Type=oneshot +EOF + +cat >$initdir/test-machine-id-setup.sh <<'EOF' +#!/bin/bash + +set -e +set -x + +function setup_root { + local _root="$1" + mkdir -p "$_root" + mount -t tmpfs tmpfs "$_root" + mkdir -p "$_root/etc" "$_root/run" +} + +function check { + printf "Expected\n" + cat "$1" + printf "\nGot\n" + cat "$2" + cmp "$1" "$2" +} + +r="$(pwd)/overwrite-broken-machine-id" +setup_root "$r" +systemd-machine-id-setup --print --root "$r" +echo abc >>"$r/etc/machine-id" +id=$(systemd-machine-id-setup --print --root "$r") +echo $id >expected +check expected "$r/etc/machine-id" + +r="$(pwd)/transient-machine-id" +setup_root "$r" +systemd-machine-id-setup --print --root "$r" +echo abc >>"$r/etc/machine-id" +mount -o remount,ro "$r" +mount -t tmpfs tmpfs "$r/run" +transient_id=$(systemd-machine-id-setup --print --root "$r") +mount -o remount,rw "$r" +commited_id=$(systemd-machine-id-setup --print --commit --root "$r") +[[ "$transient_id" = "$commited_id" ]] +check "$r/etc/machine-id" "$r/run/machine-id" +EOF +chmod +x $initdir/test-machine-id-setup.sh + + setup_testsuite + ) +} + +do_test "$@" diff --git a/test/TEST-15-DROPIN/Makefile b/test/TEST-15-DROPIN/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-15-DROPIN/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-15-DROPIN/test-dropin.sh b/test/TEST-15-DROPIN/test-dropin.sh new file mode 100755 index 00000000..fd500c1a --- /dev/null +++ b/test/TEST-15-DROPIN/test-dropin.sh @@ -0,0 +1,441 @@ +#! /bin/bash +set -e +set -x + +_clear_service () { + systemctl stop $1.service 2>/dev/null || : + rm -f /{etc,run,usr/lib}/systemd/system/$1.service + rm -fr /{etc,run,usr/lib}/systemd/system/$1.service.d + rm -fr /{etc,run,usr/lib}/systemd/system/$1.service.{wants,requires} +} + +clear_services () { + for u in $*; do + _clear_service $u + done + systemctl daemon-reload +} + +create_service () { + clear_services $1 + + cat >/etc/systemd/system/$1.service</usr/lib/systemd/system/service.d/override.conf <>/etc/systemd/system/bar@.service <>/etc/systemd/system/yup@.service </usr/lib/systemd/system/a.service.d/override.conf </usr/lib/systemd/system/a.service.d/wants-b.conf<> "${TL}" + fi +} + +# This checks all stages, start, runtime and stop, can be extended by +# EXTEND_TIMEOUT_USEC + +wait_for success_all + +# These check that EXTEND_TIMEOUT_USEC that occurs at greater than the +# extend timeout interval but less then the stage limit (TimeoutStartSec, +# RuntimeMaxSec, TimeoutStopSec) still succeed. + +wait_for success_start +wait_for success_runtime +wait_for success_stop + +# These ensure that EXTEND_TIMEOUT_USEC will still timeout in the +# approprate stage, after the stage limit, when the EXTEND_TIMEOUT_USEC +# message isn't sent within the extend timeout interval. + +wait_for fail_start startfail +wait_for fail_stop stopfail +wait_for fail_runtime runtimefail + +if [[ -f "${TL}" ]] +then + # no mv + cp "${TL}" /test.log + exit 1 +else + touch /testok + exit 0 +fi diff --git a/test/TEST-16-EXTEND-TIMEOUT/extend_timeout_test_service.sh b/test/TEST-16-EXTEND-TIMEOUT/extend_timeout_test_service.sh new file mode 100755 index 00000000..1fd2768f --- /dev/null +++ b/test/TEST-16-EXTEND-TIMEOUT/extend_timeout_test_service.sh @@ -0,0 +1,70 @@ +#!/bin/bash +set -x +set -e +set -o pipefail + +# sleep interval (seconds) +sleep_interval=1 +# extend_timeout_interval second(s) +extend_timeout_interval=1 +# number of sleep_intervals before READY=1 +start_intervals=10 +# number of sleep_intervals before exiting +stop_intervals=10 +# run intervals, number of sleep_intervals to run +run_intervals=7 +# service name +SERVICE=unknown + +while [ $# -gt 0 ]; +do + eval ${1%=*}=${1#*=} + shift +done + +# We convert to usec +extend_timeout_interval=$(( $extend_timeout_interval * 1000000 )) + +trap "{ touch /${SERVICE}.terminated; exit 1; }" SIGTERM SIGABRT + +rm -f /${SERVICE}.* +touch /${SERVICE}.startfail + +systemd-notify EXTEND_TIMEOUT_USEC=$extend_timeout_interval +while [ $start_intervals -gt 0 ] +do + sleep $sleep_interval + start_intervals=$(( $start_intervals - 1 )) + systemd-notify EXTEND_TIMEOUT_USEC=$extend_timeout_interval +done + +systemd-notify --ready --status="Waiting for your request" + +touch /${SERVICE}.runtimefail +rm /${SERVICE}.startfail + +systemd-notify EXTEND_TIMEOUT_USEC=$extend_timeout_interval +while [ $run_intervals -gt 0 ] +do + sleep $sleep_interval + run_intervals=$(( $run_intervals - 1 )) + systemd-notify EXTEND_TIMEOUT_USEC=$extend_timeout_interval +done + +systemd-notify STOPPING=1 + +touch /${SERVICE}.stopfail +rm /${SERVICE}.runtimefail + +systemd-notify EXTEND_TIMEOUT_USEC=$extend_timeout_interval +while [ $stop_intervals -gt 0 ] +do + sleep $sleep_interval + stop_intervals=$(( $stop_intervals - 1 )) + systemd-notify EXTEND_TIMEOUT_USEC=$extend_timeout_interval +done + +touch /${SERVICE}.success +rm /${SERVICE}.stopfail + +exit 0 diff --git a/test/TEST-16-EXTEND-TIMEOUT/test.sh b/test/TEST-16-EXTEND-TIMEOUT/test.sh new file mode 100755 index 00000000..c5f8af6e --- /dev/null +++ b/test/TEST-16-EXTEND-TIMEOUT/test.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="EXTEND_TIMEOUT_USEC=usec start/runtime/stop tests" +SKIP_INITRD=yes +TEST_NO_QEMU=1 + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image + + # Create what will eventually be our root filesystem onto an overlay + ( + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + for s in success-all success-start success-stop success-runtime \ + fail-start fail-stop fail-runtime + do + cp testsuite-${s}.service ${initdir}/etc/systemd/system + done + cp testsuite.service ${initdir}/etc/systemd/system + + cp extend_timeout_test_service.sh ${initdir}/ + cp assess.sh ${initdir}/ + + setup_testsuite + ) + + setup_nspawn_root +} + +do_test "$@" diff --git a/test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-runtime.service b/test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-runtime.service new file mode 100644 index 00000000..e0b9f6a7 --- /dev/null +++ b/test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-runtime.service @@ -0,0 +1,13 @@ + +[Unit] +Description=Testsuite: Fail Runtime (EXTEND_TIMEOUT_USEC Didn't occur in sufficient time after RuntimeSecMax.) + +[Service] + +# EXTEND_TIMEOUT_USEC on runtime start (0) and 7 seconds after. Systemd will expect one at 7+5 (extend_timeout_interval) +# seconds this won't happen until 7 + 7 (sleep interval) seconds. Therefore timeout at 12 seconds. +Type=notify +TimeoutStartSec=4 +TimeoutStopSec=4 +RuntimeMaxSec=10 +ExecStart=/extend_timeout_test_service.sh SERVICE=fail_runtime extend_timeout_interval=5 sleep_interval=7 start_intervals=0 run_intervals=2 stop_intervals=0 diff --git a/test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-start.service b/test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-start.service new file mode 100644 index 00000000..c3fcf23d --- /dev/null +++ b/test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-start.service @@ -0,0 +1,13 @@ + +[Unit] +Description=Testsuite: Fail Start (EXTEND_TIMEOUT_USEC Didn't occur in sufficient time after TimeoutStartSec.) + +[Service] + +# EXTEND_TIMEOUT_USEC on startup and 7 seconds from start. Systemd will expect one at 7+5 (extend_timeout_interval) +# seconds this won't happen until 7 + 7 (sleep interval) seconds. Therefore timeout at 12 seconds. +Type=notify +TimeoutStartSec=10 +TimeoutStopSec=4 +RuntimeMaxSec=4 +ExecStart=/extend_timeout_test_service.sh SERVICE=fail_start extend_timeout_interval=5 sleep_interval=7 start_intervals=2 run_intervals=0 stop_intervals=0 diff --git a/test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-stop.service b/test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-stop.service new file mode 100644 index 00000000..ce76d10d --- /dev/null +++ b/test/TEST-16-EXTEND-TIMEOUT/testsuite-fail-stop.service @@ -0,0 +1,16 @@ + +[Unit] +Description=Testsuite: Fail Stop (EXTEND_TIMEOUT_USEC Didn't occur in sufficient time after TimeoutStopSec.) + +[Service] + +# EXTEND_TIMEOUT_USEC on stop (0) and 7 seconds after. Systemd will expect one at 7+5 (extend_timeout_interval) +# seconds this won't happen until 7 + 7 (sleep interval) seconds. Therefore timeout at 12 seconds. +Type=notify +TimeoutStartSec=4 +TimeoutStopSec=10 +RuntimeMaxSec=4 +ExecStart=/extend_timeout_test_service.sh SERVICE=fail_stop extend_timeout_interval=5 sleep_interval=7 start_intervals=0 run_intervals=0 stop_intervals=2 +# Due to 6041a7ee2c1bbff6301082f192fc1b0882400d42 SIGTERM isn't sent as the service shuts down with STOPPING=1 +# This file makes the test assess.sh quicker by notifing it that this test has finished. +ExecStopPost=/bin/bash -c '[[ $SERVICE_RESULT == timeout && $EXIT_CODE == killed ]] && touch /fail_runtime.terminated' diff --git a/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-all.service b/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-all.service new file mode 100644 index 00000000..666f4229 --- /dev/null +++ b/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-all.service @@ -0,0 +1,14 @@ + +[Unit] +Description=Testsuite: EXTEND_TIMEOUT_USEC Success - extend timeout on all services + +[Service] + +# Normal success - startup / runtime / shutdown all take 8 seconds which is within the EXTEND_TIMEOUT_USEC=4 seconds interval +# runtime is 8+8+8 seconds. so we are relying on the EXTEND_TIMEOUT_USEC to exceed all stages, Start, Runtime and Stop. +# success occurs after 24 seconds +Type=notify +TimeoutStartSec=4 +TimeoutStopSec=4 +RuntimeMaxSec=4 +ExecStart=/extend_timeout_test_service.sh SERVICE=success_all extend_timeout_interval=4 sleep_interval=2 start_intervals=3 run_intervals=3 stop_intervals=3 diff --git a/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-runtime.service b/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-runtime.service new file mode 100644 index 00000000..dc226f50 --- /dev/null +++ b/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-runtime.service @@ -0,0 +1,13 @@ + +[Unit] +Description=Testsuite: Success Runtime (EXTEND_TIMEOUT_USEC > WATCHDOG_USEC however < RuntimeMaxSec) + +[Service] + +# EXTEND_TIMEOUT_USEC=4 second once during runtime, but sleep for 6 seconds. +# Runtime is 6 seconds and < RuntimeMaxSec so still successful. +Type=notify +TimeoutStartSec=4 +TimeoutStopSec=4 +RuntimeMaxSec=8 +ExecStart=/extend_timeout_test_service.sh SERVICE=success_runtime extend_timeout_interval=4 sleep_interval=6 start_intervals=0 run_intervals=1 stop_intervals=0 diff --git a/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-start.service b/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-start.service new file mode 100644 index 00000000..228eece7 --- /dev/null +++ b/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-start.service @@ -0,0 +1,13 @@ + +[Unit] +Description=Testsuite: Success Start (EXTEND_TIMEOUT_USEC > WATCHDOG_USEC however < TimeoutStartSec) + +[Service] + +# EXTEND_TIMEOUT_USEC=4 second interval once at startup, but sleep 6 seconds. +# Therefore startup is 6 seconds and < TimeoutStartSec so still successful. +Type=notify +TimeoutStartSec=8 +TimeoutStopSec=4 +RuntimeMaxSec=4 +ExecStart=/extend_timeout_test_service.sh SERVICE=success_start extend_timeout_interval=4 sleep_interval=6 start_intervals=1 run_intervals=0 stop_intervals=0 diff --git a/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-stop.service b/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-stop.service new file mode 100644 index 00000000..b809397b --- /dev/null +++ b/test/TEST-16-EXTEND-TIMEOUT/testsuite-success-stop.service @@ -0,0 +1,13 @@ + +[Unit] +Description=Testsuite: Success Stop (EXTEND_TIMEOUT_USEC > WATCHDOG_USEC however < TimeoutStopSec) + +[Service] + +# EXTEND_TIMEOUT_USEC=4 seconds once during shutdown, but sleep for 6 seconds. +# Therefore stop time is 6 seconds and < TimeoutStopSec so still successful. +Type=notify +TimeoutStartSec=4 +TimeoutStopSec=8 +RuntimeMaxSec=4 +ExecStart=/extend_timeout_test_service.sh SERVICE=success_stop extend_timeout_interval=4 sleep_interval=6 start_intervals=0 run_intervals=0 stop_intervals=1 diff --git a/test/TEST-16-EXTEND-TIMEOUT/testsuite.service b/test/TEST-16-EXTEND-TIMEOUT/testsuite.service new file mode 100644 index 00000000..7512ba9e --- /dev/null +++ b/test/TEST-16-EXTEND-TIMEOUT/testsuite.service @@ -0,0 +1,18 @@ + +[Unit] +Description=Testsuite: Assess all other testsuite-*.services worked as expected + +Wants=testsuite-success-all.service +Wants=testsuite-success-start.service +Wants=testsuite-success-runtime.service +Wants=testsuite-success-stop.service +Wants=testsuite-fail-start.service +Wants=testsuite-fail-stop.service +Wants=testsuite-fail-runtime.service +StopWhenUnneeded=yes + +[Service] +Type=simple +TimeoutStartSec=infinity +ExecStartPre=/assess.sh +ExecStart=/bin/true diff --git a/test/TEST-17-UDEV-WANTS/Makefile b/test/TEST-17-UDEV-WANTS/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-17-UDEV-WANTS/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-17-UDEV-WANTS/test.sh b/test/TEST-17-UDEV-WANTS/test.sh new file mode 100755 index 00000000..1cdbbd2d --- /dev/null +++ b/test/TEST-17-UDEV-WANTS/test.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="UDEV SYSTEMD_WANTS property" +TEST_NO_NSPAWN=1 + +. $TEST_BASE_DIR/test-functions +QEMU_TIMEOUT=300 + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /run/udev/rules.d/50-testsuite.rules < /run/udev/rules.d/50-testsuite.rules < /testok + +exit 0 diff --git a/test/TEST-18-FAILUREACTION/Makefile b/test/TEST-18-FAILUREACTION/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-18-FAILUREACTION/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-18-FAILUREACTION/test.sh b/test/TEST-18-FAILUREACTION/test.sh new file mode 100755 index 00000000..e9f6ee7a --- /dev/null +++ b/test/TEST-18-FAILUREACTION/test.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="FailureAction= operation" + +. $TEST_BASE_DIR/test-functions +QEMU_TIMEOUT=600 + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /firstphase + systemd-run --wait -p SuccessAction=reboot true +else + echo OK > /testok + systemd-run --wait -p FailureAction=poweroff false +fi + +sleep infinity diff --git a/test/TEST-19-DELEGATE/Makefile b/test/TEST-19-DELEGATE/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-19-DELEGATE/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-19-DELEGATE/test.sh b/test/TEST-19-DELEGATE/test.sh new file mode 100755 index 00000000..706f0e9f --- /dev/null +++ b/test/TEST-19-DELEGATE/test.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="test cgroup delegation in the unified hierarchy" +TEST_NO_NSPAWN=1 + +. $TEST_BASE_DIR/test-functions +QEMU_TIMEOUT=600 +UNIFIED_CGROUP_HIERARCHY=yes + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <&2 +fi + +echo OK > /testok + +exit 0 diff --git a/test/TEST-20-MAINPIDGAMES/Makefile b/test/TEST-20-MAINPIDGAMES/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-20-MAINPIDGAMES/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-20-MAINPIDGAMES/test.sh b/test/TEST-20-MAINPIDGAMES/test.sh new file mode 100755 index 00000000..05fa847a --- /dev/null +++ b/test/TEST-20-MAINPIDGAMES/test.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="test changing main PID" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service </tmp/mainpid.sh < /run/mainpidsh/pid +EOF +chmod +x /tmp/mainpid.sh + +systemd-run --unit=mainpidsh.service -p StandardOutput=tty -p StandardError=tty -p Type=forking -p RuntimeDirectory=mainpidsh -p PIDFile=/run/mainpidsh/pid /tmp/mainpid.sh +test `systemctl show -p MainPID --value mainpidsh.service` -eq `cat /run/mainpidsh/pid` + +cat >/tmp/mainpid2.sh < /run/mainpidsh2/pid +chown 1001:1001 /run/mainpidsh2/pid +EOF +chmod +x /tmp/mainpid2.sh + +systemd-run --unit=mainpidsh2.service -p StandardOutput=tty -p StandardError=tty -p Type=forking -p RuntimeDirectory=mainpidsh2 -p PIDFile=/run/mainpidsh2/pid /tmp/mainpid2.sh +test `systemctl show -p MainPID --value mainpidsh2.service` -eq `cat /run/mainpidsh2/pid` + +cat >/dev/shm/mainpid3.sh < /testok + +exit 0 diff --git a/test/TEST-21-SYSUSERS/Makefile b/test/TEST-21-SYSUSERS/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-21-SYSUSERS/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-21-SYSUSERS/inline.expected-group b/test/TEST-21-SYSUSERS/inline.expected-group new file mode 100644 index 00000000..cc9093f8 --- /dev/null +++ b/test/TEST-21-SYSUSERS/inline.expected-group @@ -0,0 +1,2 @@ +g1:x:111: +u1:x:222: diff --git a/test/TEST-21-SYSUSERS/inline.expected-passwd b/test/TEST-21-SYSUSERS/inline.expected-passwd new file mode 100644 index 00000000..f50f25c7 --- /dev/null +++ b/test/TEST-21-SYSUSERS/inline.expected-passwd @@ -0,0 +1 @@ +u1:x:222:222::/:/bin/zsh diff --git a/test/TEST-21-SYSUSERS/test-1.expected-group b/test/TEST-21-SYSUSERS/test-1.expected-group new file mode 100644 index 00000000..cc9093f8 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-1.expected-group @@ -0,0 +1,2 @@ +g1:x:111: +u1:x:222: diff --git a/test/TEST-21-SYSUSERS/test-1.expected-passwd b/test/TEST-21-SYSUSERS/test-1.expected-passwd new file mode 100644 index 00000000..f59303b5 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-1.expected-passwd @@ -0,0 +1 @@ +u1:x:222:222::/:NOLOGIN diff --git a/test/TEST-21-SYSUSERS/test-1.input b/test/TEST-21-SYSUSERS/test-1.input new file mode 100644 index 00000000..297bbe35 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-1.input @@ -0,0 +1,5 @@ +# Trivial smoke test that covers the most basic functionality +# +#Type Name ID GECOS HOMEDIR +u u1 222 - - +g g1 111 - - diff --git a/test/TEST-21-SYSUSERS/test-10.expected-group b/test/TEST-21-SYSUSERS/test-10.expected-group new file mode 100644 index 00000000..1c921587 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-10.expected-group @@ -0,0 +1,2 @@ +u1:x:300:u2 +u2:x:SYSTEM_UID_MAX: diff --git a/test/TEST-21-SYSUSERS/test-10.expected-passwd b/test/TEST-21-SYSUSERS/test-10.expected-passwd new file mode 100644 index 00000000..ca2d764e --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-10.expected-passwd @@ -0,0 +1,2 @@ +u1:x:300:300::/:NOLOGIN +u2:x:SYSTEM_UID_MAX:SYSTEM_UID_MAX::/:NOLOGIN diff --git a/test/TEST-21-SYSUSERS/test-10.input b/test/TEST-21-SYSUSERS/test-10.input new file mode 100644 index 00000000..8e18a00a --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-10.input @@ -0,0 +1,5 @@ +# check that 'm' lines do not conflicts 'u' line +# +#Type Name ID GECOS HOMEDIR +u u1 300 - - +m u2 u1 diff --git a/test/TEST-21-SYSUSERS/test-11.expected-group b/test/TEST-21-SYSUSERS/test-11.expected-group new file mode 100644 index 00000000..815a6c59 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-11.expected-group @@ -0,0 +1,6 @@ +o1:x:100: +g1:x:111: +u1:x:222: ++giant:::bill,tina,alan,hetty +-transport::: ++::: diff --git a/test/TEST-21-SYSUSERS/test-11.expected-passwd b/test/TEST-21-SYSUSERS/test-11.expected-passwd new file mode 100644 index 00000000..737e43bf --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-11.expected-passwd @@ -0,0 +1,6 @@ +root:x:0:0:root:/root:/bin/bash +systemd-network:x:492:492:Systemd Network Management:/:/usr/sbin/nologin +systemd-resolve:x:491:491:Systemd Resolver:/:/usr/sbin/nologin +systemd-timesync:x:493:493:Systemd Time Synchronization:/:/usr/sbin/nologin +u1:x:222:222::/:NOLOGIN ++:::::: diff --git a/test/TEST-21-SYSUSERS/test-11.initial-group b/test/TEST-21-SYSUSERS/test-11.initial-group new file mode 100644 index 00000000..88d31f2c --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-11.initial-group @@ -0,0 +1,4 @@ +o1:x:100 ++giant:::bill,tina,alan,hetty +-transport::: ++::: diff --git a/test/TEST-21-SYSUSERS/test-11.initial-passwd b/test/TEST-21-SYSUSERS/test-11.initial-passwd new file mode 100644 index 00000000..45d3ffd5 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-11.initial-passwd @@ -0,0 +1,5 @@ +root:x:0:0:root:/root:/bin/bash +systemd-network:x:492:492:Systemd Network Management:/:/usr/sbin/nologin +systemd-resolve:x:491:491:Systemd Resolver:/:/usr/sbin/nologin +systemd-timesync:x:493:493:Systemd Time Synchronization:/:/usr/sbin/nologin ++:::::: diff --git a/test/TEST-21-SYSUSERS/test-11.input b/test/TEST-21-SYSUSERS/test-11.input new file mode 100644 index 00000000..bffc2cd7 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-11.input @@ -0,0 +1,3 @@ +#Type Name ID GECOS HOMEDIR +u u1 222 - - +g g1 111 - - diff --git a/test/TEST-21-SYSUSERS/test-12.expected-group b/test/TEST-21-SYSUSERS/test-12.expected-group new file mode 100644 index 00000000..5d94846e --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-12.expected-group @@ -0,0 +1,2 @@ +root:x:0: +systemd-coredump:x:1: diff --git a/test/TEST-21-SYSUSERS/test-12.expected-passwd b/test/TEST-21-SYSUSERS/test-12.expected-passwd new file mode 100644 index 00000000..f076f3d0 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-12.expected-passwd @@ -0,0 +1,2 @@ +root:x:0:0:root:/root:/bin/bash +systemd-coredump:x:1:1:systemd Core Dumper:/:NOLOGIN diff --git a/test/TEST-21-SYSUSERS/test-12.initial-group b/test/TEST-21-SYSUSERS/test-12.initial-group new file mode 100644 index 00000000..1dbf9013 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-12.initial-group @@ -0,0 +1 @@ +root:x:0: diff --git a/test/TEST-21-SYSUSERS/test-12.initial-passwd b/test/TEST-21-SYSUSERS/test-12.initial-passwd new file mode 100644 index 00000000..aebc4923 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-12.initial-passwd @@ -0,0 +1 @@ +root:x:0:0:root:/root:/bin/bash diff --git a/test/TEST-21-SYSUSERS/test-12.input b/test/TEST-21-SYSUSERS/test-12.input new file mode 100644 index 00000000..29131202 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-12.input @@ -0,0 +1 @@ +u systemd-coredump 1 "systemd Core Dumper" diff --git a/test/TEST-21-SYSUSERS/test-2.expected-group b/test/TEST-21-SYSUSERS/test-2.expected-group new file mode 100644 index 00000000..8fcc03f4 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-2.expected-group @@ -0,0 +1,4 @@ +u1:x:SYSTEM_UID_MAX: +u2:x:777: +u3:x:778: +u4:x:779: diff --git a/test/TEST-21-SYSUSERS/test-2.expected-passwd b/test/TEST-21-SYSUSERS/test-2.expected-passwd new file mode 100644 index 00000000..af806881 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-2.expected-passwd @@ -0,0 +1,4 @@ +u1:x:SYSTEM_UID_MAX:SYSTEM_UID_MAX:some gecos:/random/dir:NOLOGIN +u2:x:777:777:some gecos:/random/dir:/bin/zsh +u3:x:778:778::/random/dir2:/bin/bash +u4:x:779:779::/:/bin/csh diff --git a/test/TEST-21-SYSUSERS/test-2.input b/test/TEST-21-SYSUSERS/test-2.input new file mode 100644 index 00000000..cedea9e4 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-2.input @@ -0,0 +1,8 @@ +# Test generation of ID dynamically based on SYSTEM_UID_MAX and +# replacement of all fields up to the login shell. +# +#Type Name ID GECOS homedir shell +u u1 - "some gecos" /random/dir - +u u2 777 "some gecos" /random/dir /bin/zsh +u u3 778 - /random/dir2 /bin/bash +u u4 779 - - /bin/csh diff --git a/test/TEST-21-SYSUSERS/test-3.expected-group b/test/TEST-21-SYSUSERS/test-3.expected-group new file mode 100644 index 00000000..c3a63285 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-3.expected-group @@ -0,0 +1,4 @@ +hoge:x:300: +baz:x:302: +foo:x:301: +ccc:x:305: diff --git a/test/TEST-21-SYSUSERS/test-3.expected-passwd b/test/TEST-21-SYSUSERS/test-3.expected-passwd new file mode 100644 index 00000000..946303f9 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-3.expected-passwd @@ -0,0 +1,4 @@ +foo:x:301:301::/:NOLOGIN +aaa:x:303:302::/:NOLOGIN +bbb:x:304:302::/:NOLOGIN +ccc:x:305:305::/:NOLOGIN diff --git a/test/TEST-21-SYSUSERS/test-3.input b/test/TEST-21-SYSUSERS/test-3.input new file mode 100644 index 00000000..3257082c --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-3.input @@ -0,0 +1,10 @@ +# Ensure that the semantic for the uid:gid syntax is correct +# +#Type Name ID GECOS HOMEDIR +g hoge 300 - - +u foo 301 - - + +g baz 302 - - +u aaa 303:302 - - +u bbb 304:302 - - +u ccc 305 - - diff --git a/test/TEST-21-SYSUSERS/test-4.expected-group b/test/TEST-21-SYSUSERS/test-4.expected-group new file mode 100644 index 00000000..64913a5f --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-4.expected-group @@ -0,0 +1 @@ +xxx:x:310: diff --git a/test/TEST-21-SYSUSERS/test-4.expected-passwd b/test/TEST-21-SYSUSERS/test-4.expected-passwd new file mode 100644 index 00000000..99d1048d --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-4.expected-passwd @@ -0,0 +1,2 @@ +yyy:x:311:310::/:NOLOGIN +xxx:x:312:310::/:NOLOGIN diff --git a/test/TEST-21-SYSUSERS/test-4.input b/test/TEST-21-SYSUSERS/test-4.input new file mode 100644 index 00000000..557f61c4 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-4.input @@ -0,0 +1,6 @@ +# Ensure that already created groups are used when using the uid:gid syntax +# +#Type Name ID GECOS HOMEDIR +g xxx 310 +u yyy 311:310 +u xxx 312:310 diff --git a/test/TEST-21-SYSUSERS/test-5.expected-group b/test/TEST-21-SYSUSERS/test-5.expected-group new file mode 100644 index 00000000..e9ef0a79 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-5.expected-group @@ -0,0 +1,39 @@ +adm:x:4: +tty:x:5: +disk:x:6: +man:x:12: +kmem:x:15: +dialout:x:20: +fax:x:21: +voice:x:22: +cdrom:x:24: +floppy:x:25: +tape:x:26: +sudo:x:27: +audio:x:29: +dip:x:30: +operator:x:37: +src:x:40: +shadow:x:42: +utmp:x:43: +video:x:44: +sasl:x:45: +plugdev:x:46: +staff:x:50: +games:x:60: +users:x:100: +nogroup:x:65534: +root:x:0: +daemon:x:1: +bin:x:2: +sys:x:3: +lp:x:7: +mail:x:8: +news:x:9: +uucp:x:10: +proxy:x:13: +www-data:x:33: +backup:x:34: +list:x:38: +irc:x:39: +gnats:x:41: diff --git a/test/TEST-21-SYSUSERS/test-5.expected-passwd b/test/TEST-21-SYSUSERS/test-5.expected-passwd new file mode 100644 index 00000000..a83d566b --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-5.expected-passwd @@ -0,0 +1,18 @@ +root:x:0:0::/root:/bin/sh +daemon:x:1:1::/usr/sbin:NOLOGIN +bin:x:2:2::/bin:NOLOGIN +sys:x:3:3::/dev:NOLOGIN +sync:x:4:65534::/bin:NOLOGIN +games:x:5:60::/usr/games:NOLOGIN +man:x:6:12::/var/cache/man:NOLOGIN +lp:x:7:7::/var/spool/lpd:NOLOGIN +mail:x:8:8::/var/mail:NOLOGIN +news:x:9:9::/var/spool/news:NOLOGIN +uucp:x:10:10::/var/spool/uucp:NOLOGIN +proxy:x:13:13::/bin:NOLOGIN +www-data:x:33:33::/var/www:NOLOGIN +backup:x:34:34::/var/backups:NOLOGIN +list:x:38:38::/var/list:NOLOGIN +irc:x:39:39::/var/run/ircd:NOLOGIN +gnats:x:41:41::/var/lib/gnats:NOLOGIN +nobody:x:65534:65534::/nonexistent:NOLOGIN diff --git a/test/TEST-21-SYSUSERS/test-5.input b/test/TEST-21-SYSUSERS/test-5.input new file mode 100644 index 00000000..57519d7c --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-5.input @@ -0,0 +1,47 @@ +# Reproduce the base-passwd master.{passwd,group} from Debian +# +#Type Name ID GECOS Home directory +g adm 4 - +g tty 5 - +g disk 6 - +g man 12 - +g kmem 15 - +g dialout 20 - +g fax 21 - +g voice 22 - +g cdrom 24 - +g floppy 25 - +g tape 26 - +g sudo 27 - +g audio 29 - +g dip 30 - +g operator 37 - +g src 40 - +g shadow 42 - +g utmp 43 - +g video 44 - +g sasl 45 - +g plugdev 46 - +g staff 50 - +g games 60 - +g users 100 - +g nogroup 65534 - + +u root 0 - /root +u daemon 1 - /usr/sbin +u bin 2 - /bin +u sys 3 - /dev +u sync 4:65534 - /bin +u games 5:60 - /usr/games +u man 6:12 - /var/cache/man +u lp 7 - /var/spool/lpd +u mail 8 - /var/mail +u news 9 - /var/spool/news +u uucp 10 - /var/spool/uucp +u proxy 13 - /bin +u www-data 33 - /var/www +u backup 34 - /var/backups +u list 38 - /var/list +u irc 39 - /var/run/ircd +u gnats 41 - /var/lib/gnats +u nobody 65534:65534 - /nonexistent diff --git a/test/TEST-21-SYSUSERS/test-6.expected-group b/test/TEST-21-SYSUSERS/test-6.expected-group new file mode 100644 index 00000000..499c9008 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-6.expected-group @@ -0,0 +1,2 @@ +g1:x:111: +u1:x:SYSTEM_UID_MAX: diff --git a/test/TEST-21-SYSUSERS/test-6.expected-passwd b/test/TEST-21-SYSUSERS/test-6.expected-passwd new file mode 100644 index 00000000..ba55a13e --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-6.expected-passwd @@ -0,0 +1 @@ +u1:x:SYSTEM_UID_MAX:SYSTEM_UID_MAX::/:NOLOGIN diff --git a/test/TEST-21-SYSUSERS/test-6.input b/test/TEST-21-SYSUSERS/test-6.input new file mode 100644 index 00000000..764f57e8 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-6.input @@ -0,0 +1,7 @@ +# Ensure that existing IDs are not reused by default. I.e. the existing +# ID 111 from g1 will cause u1 to get a new and different ID (999 on most +# systems). +# +#Type Name ID GECOS HOMEDIR +g g1 111 - - +u u1 111 - - diff --git a/test/TEST-21-SYSUSERS/test-7.expected-group b/test/TEST-21-SYSUSERS/test-7.expected-group new file mode 100644 index 00000000..ae9539c9 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-7.expected-group @@ -0,0 +1,16 @@ +sys:x:3: +mem:x:8: +ftp:x:11: +mail:x:12: +log:x:19: +smmsp:x:25: +proc:x:26: +games:x:50: +lock:x:54: +network:x:90: +floppy:x:94: +scanner:x:96: +power:x:98: +bin:x:1: +daemon:x:2: +http:x:33: diff --git a/test/TEST-21-SYSUSERS/test-7.expected-passwd b/test/TEST-21-SYSUSERS/test-7.expected-passwd new file mode 100644 index 00000000..0c5d370f --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-7.expected-passwd @@ -0,0 +1,5 @@ +bin:x:1:1::/:NOLOGIN +daemon:x:2:2::/:NOLOGIN +mail:x:8:12::/var/spool/mail:NOLOGIN +ftp:x:14:11::/srv/ftp:NOLOGIN +http:x:33:33::/srv/http:NOLOGIN diff --git a/test/TEST-21-SYSUSERS/test-7.input b/test/TEST-21-SYSUSERS/test-7.input new file mode 100644 index 00000000..4e10b742 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-7.input @@ -0,0 +1,26 @@ +# Issue #8315 +# +#Type Name ID GECOS HOMEDIR + +# default arch groups +# groups first, because we have user/group id mismatch on ftp and mail +g sys 3 - - +g mem 8 - - +g ftp 11 - - +g mail 12 - - +g log 19 - - +g smmsp 25 - - +g proc 26 - - +g games 50 - - +g lock 54 - - +g network 90 - - +g floppy 94 - - +g scanner 96 - - +g power 98 - - + +# default arch users +u bin 1 - - +u daemon 2 - - +u mail 8 - /var/spool/mail +u ftp 14 - /srv/ftp +u http 33 - /srv/http diff --git a/test/TEST-21-SYSUSERS/test-8.expected-group b/test/TEST-21-SYSUSERS/test-8.expected-group new file mode 100644 index 00000000..f09b2b64 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-8.expected-group @@ -0,0 +1 @@ +groupname:x:300: diff --git a/test/TEST-21-SYSUSERS/test-8.expected-passwd b/test/TEST-21-SYSUSERS/test-8.expected-passwd new file mode 100644 index 00000000..23e99f05 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-8.expected-passwd @@ -0,0 +1 @@ +username:x:SYSTEM_UID_MAX:300::/:NOLOGIN diff --git a/test/TEST-21-SYSUSERS/test-8.input b/test/TEST-21-SYSUSERS/test-8.input new file mode 100644 index 00000000..b76dd3e2 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-8.input @@ -0,0 +1,2 @@ +g groupname 300 +u username -:300 diff --git a/test/TEST-21-SYSUSERS/test-9.expected-group b/test/TEST-21-SYSUSERS/test-9.expected-group new file mode 100644 index 00000000..33335d4e --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-9.expected-group @@ -0,0 +1 @@ +user1:x:300: diff --git a/test/TEST-21-SYSUSERS/test-9.expected-passwd b/test/TEST-21-SYSUSERS/test-9.expected-passwd new file mode 100644 index 00000000..0bffbcd9 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-9.expected-passwd @@ -0,0 +1,2 @@ +user1:x:300:300::/:NOLOGIN +user2:x:SYSTEM_UID_MAX:300::/:NOLOGIN diff --git a/test/TEST-21-SYSUSERS/test-9.input b/test/TEST-21-SYSUSERS/test-9.input new file mode 100644 index 00000000..4d536472 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test-9.input @@ -0,0 +1,2 @@ +u user1 300 +u user2 -:300 diff --git a/test/TEST-21-SYSUSERS/test.sh b/test/TEST-21-SYSUSERS/test.sh new file mode 100755 index 00000000..add16ea1 --- /dev/null +++ b/test/TEST-21-SYSUSERS/test.sh @@ -0,0 +1,127 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="Sysuser-related tests" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + mkdir -p $TESTDIR/etc/sysusers.d $TESTDIR/usr/lib/sysusers.d $TESTDIR/tmp +} + +prepare_testdir() { + rm -f $TESTDIR/etc/*{passwd,group,shadow} + for i in $1.initial-{passwd,group,shadow}; do + test -f $i && cp $i $TESTDIR/etc/${i#*.initial-} + done + return 0 +} + +preprocess() { + in="$1" + + # see meson.build how to extract this. gcc -E was used before to + # get this value from config.h, however the autopkgtest fails with + # it + SYSTEM_UID_MAX=$(awk 'BEGIN { uid=999 } /^\s*SYS_UID_MAX\s+/ { uid=$2 } END { print uid }' /etc/login.defs) + + # we can't rely on config.h to get the nologin path, as autopkgtest + # uses pre-compiled binaries, so extract it from the systemd-sysusers + # binary which we are about to execute + NOLOGIN=$(strings $(type -p systemd-sysusers) | grep nologin) + + sed -e "s/SYSTEM_UID_MAX/${SYSTEM_UID_MAX}/g" \ + -e "s#NOLOGIN#${NOLOGIN}#g" "$in" +} + +compare() { + if ! diff -u $TESTDIR/etc/passwd <(preprocess ${1%.*}.expected-passwd); then + echo "**** Unexpected output for $f" + exit 1 + fi + + if ! diff -u $TESTDIR/etc/group <(preprocess ${1%.*}.expected-group); then + echo "**** Unexpected output for $f $2" + exit 1 + fi +} + +test_run() { + # ensure our build of systemd-sysusers is run + PATH=${BUILD_DIR}:$PATH + + rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/* + + # happy tests + for f in test-*.input; do + echo "*** Running $f" + prepare_testdir ${f%.input} + cp $f $TESTDIR/usr/lib/sysusers.d/test.conf + systemd-sysusers --root=$TESTDIR + + compare $f "" + done + + for f in test-*.input; do + echo "*** Running $f on stdin" + prepare_testdir ${f%.input} + touch $TESTDIR/etc/sysusers.d/test.conf + cat $f | systemd-sysusers --root=$TESTDIR - + + compare $f "on stdin" + done + + for f in test-*.input; do + echo "*** Running $f on stdin with --replace" + prepare_testdir ${f%.input} + touch $TESTDIR/etc/sysusers.d/test.conf + # this overrides test.conf which is masked on disk + cat $f | systemd-sysusers --root=$TESTDIR --replace=/etc/sysusers.d/test.conf - + # this should be ignored + cat test-1.input | systemd-sysusers --root=$TESTDIR --replace=/usr/lib/sysusers.d/test.conf - + + compare $f "on stdin with --replace" + done + + # test --inline + echo "*** Testing --inline" + prepare_testdir + # copy a random file to make sure it is ignored + cp $f $TESTDIR/etc/sysusers.d/confuse.conf + systemd-sysusers --root=$TESTDIR --inline \ + "u u1 222 - - /bin/zsh" \ + "g g1 111" + + compare inline "(--inline)" + + # test --replace + echo "*** Testing --inline with --replace" + prepare_testdir + # copy a random file to make sure it is ignored + cp $f $TESTDIR/etc/sysusers.d/confuse.conf + systemd-sysusers --root=$TESTDIR \ + --inline \ + --replace=/etc/sysusers.d/confuse.conf \ + "u u1 222 - - /bin/zsh" \ + "g g1 111" + + compare inline "(--inline --replace=…)" + + rm -f $TESTDIR/etc/sysusers.d/* $TESTDIR/usr/lib/sysusers.d/* + + # tests for error conditions + for f in unhappy-*.input; do + echo "*** Running test $f" + prepare_testdir ${f%.input} + cp $f $TESTDIR/usr/lib/sysusers.d/test.conf + systemd-sysusers --root=$TESTDIR 2> /dev/null + journalctl --sync + journalctl -t systemd-sysusers -o cat | tail -n1 > $TESTDIR/tmp/err + if ! diff -u $TESTDIR/tmp/err ${f%.*}.expected-err; then + echo "**** Unexpected error output for $f" + cat $TESTDIR/tmp/err + exit 1 + fi + done +} + +do_test "$@" diff --git a/test/TEST-21-SYSUSERS/unhappy-1.expected-err b/test/TEST-21-SYSUSERS/unhappy-1.expected-err new file mode 100644 index 00000000..d3342402 --- /dev/null +++ b/test/TEST-21-SYSUSERS/unhappy-1.expected-err @@ -0,0 +1 @@ +Failed to parse UID: '9999999999': Numerical result out of range diff --git a/test/TEST-21-SYSUSERS/unhappy-1.input b/test/TEST-21-SYSUSERS/unhappy-1.input new file mode 100644 index 00000000..b8ed8552 --- /dev/null +++ b/test/TEST-21-SYSUSERS/unhappy-1.input @@ -0,0 +1,4 @@ +# Ensure invalid uids are detected +# +#Type Name ID GECOS HOMEDIR +u u1 9999999999 - - diff --git a/test/TEST-21-SYSUSERS/unhappy-2.expected-err b/test/TEST-21-SYSUSERS/unhappy-2.expected-err new file mode 100644 index 00000000..5db5c202 --- /dev/null +++ b/test/TEST-21-SYSUSERS/unhappy-2.expected-err @@ -0,0 +1 @@ +Failed to create u1: please create GID 100 diff --git a/test/TEST-21-SYSUSERS/unhappy-2.input b/test/TEST-21-SYSUSERS/unhappy-2.input new file mode 100644 index 00000000..3266b222 --- /dev/null +++ b/test/TEST-21-SYSUSERS/unhappy-2.input @@ -0,0 +1,4 @@ +# Ensure it is not allowed to create groups implicitly in the uid:gid syntax +# +#Type Name ID GECOS HOMEDIR +u u1 100:100 - diff --git a/test/TEST-22-TMPFILES/Makefile b/test/TEST-22-TMPFILES/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-22-TMPFILES/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-22-TMPFILES/run-tmpfiles-tests.sh b/test/TEST-22-TMPFILES/run-tmpfiles-tests.sh new file mode 100755 index 00000000..3ad652f4 --- /dev/null +++ b/test/TEST-22-TMPFILES/run-tmpfiles-tests.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -x +set -e + +>/failed + +for t in test-*.sh; do + echo "Running $t"; ./$t +done + +touch /testok +rm /failed diff --git a/test/TEST-22-TMPFILES/test-01.sh b/test/TEST-22-TMPFILES/test-01.sh new file mode 100755 index 00000000..d233e37f --- /dev/null +++ b/test/TEST-22-TMPFILES/test-01.sh @@ -0,0 +1,13 @@ +#! /bin/bash +# +# With "e" don't attempt to set permissions when file doesn't exist, see +# https://github.com/systemd/systemd/pull/6682. +# + +set -e + +rm -fr /tmp/test + +echo "e /tmp/test - root root 1d" | systemd-tmpfiles --create - + +! test -e /tmp/test diff --git a/test/TEST-22-TMPFILES/test-02.sh b/test/TEST-22-TMPFILES/test-02.sh new file mode 100755 index 00000000..d1bf1ea0 --- /dev/null +++ b/test/TEST-22-TMPFILES/test-02.sh @@ -0,0 +1,122 @@ +#! /bin/bash +# +# Basic tests for types creating directories +# + +set -e +set -x + +rm -fr /tmp/{C,d,D,e} +mkdir /tmp/{C,d,D,e} + +# +# 'd' +# +mkdir /tmp/d/2 +chmod 777 /tmp/d/2 + +systemd-tmpfiles --create - </tmp/F/truncated +echo "This should be truncated" >/tmp/F/truncated-with-content + +systemd-tmpfiles --create - </tmp/F/rw-fs/foo +! systemd-tmpfiles --create - </tmp/F/rw-fs/foo +! systemd-tmpfiles --create - < fails. +! systemd-tmpfiles --create - <$initdir/etc/systemd/system/testsuite.service < /testok + +exit 0 diff --git a/test/TEST-24-UNIT-TESTS/Makefile b/test/TEST-24-UNIT-TESTS/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-24-UNIT-TESTS/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-24-UNIT-TESTS/blacklist-ubuntu-ci-ppc64el b/test/TEST-24-UNIT-TESTS/blacklist-ubuntu-ci-ppc64el new file mode 100644 index 00000000..e69de29b diff --git a/test/TEST-24-UNIT-TESTS/test.sh b/test/TEST-24-UNIT-TESTS/test.sh new file mode 100755 index 00000000..3c993e67 --- /dev/null +++ b/test/TEST-24-UNIT-TESTS/test.sh @@ -0,0 +1,101 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="Run unit tests under containers" +RUN_IN_UNPRIVILEGED_CONTAINER=yes + +. $TEST_BASE_DIR/test-functions + +check_result_nspawn() { + local _ret=1 + [[ -e $TESTDIR/$1/testok ]] && _ret=0 + if [[ -s $TESTDIR/$1/failed ]]; then + _ret=$(($_ret+1)) + echo "=== Failed test log ===" + cat $TESTDIR/$1/failed + else + if [[ -s $TESTDIR/$1/skipped ]]; then + echo "=== Skipped test log ==" + cat $TESTDIR/$1/skipped + fi + if [[ -s $TESTDIR/$1/testok ]]; then + echo "=== Passed tests ===" + cat $TESTDIR/$1/testok + fi + fi + cp -a $TESTDIR/$1/var/log/journal $TESTDIR + [[ -n "$TIMED_OUT" ]] && _ret=$(($_ret+1)) + return $_ret +} + +check_result_qemu() { + local _ret=1 + mkdir -p $initdir + mount ${LOOPDEV}p1 $initdir + [[ -e $initdir/testok ]] && _ret=0 + if [[ -s $initdir/failed ]]; then + _ret=$(($_ret+1)) + echo "=== Failed test log ===" + cat $initdir/failed + else + if [[ -s $initdir/skipped ]]; then + echo "=== Skipped test log ==" + cat $initdir/skipped + fi + if [[ -s $initdir/testok ]]; then + echo "=== Passed tests ===" + cat $initdir/testok + fi + fi + cp -a $initdir/var/log/journal $TESTDIR + umount $initdir + [[ -n "$TIMED_OUT" ]] && _ret=$(($_ret+1)) + return $_ret +} + +test_setup() { + if type -P meson && [[ "$(meson configure $BUILD_DIR | grep install-tests | awk '{ print $2 }')" != "true" ]]; then + dfatal "Needs to be built with -Dinstall-tests=true" + exit 1 + fi + + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + for i in getfacl dirname basename capsh cut rev stat mktemp rmdir ionice unshare uname tr awk getent diff xzcat lz4cat; do + inst_binary $i + done + + inst /etc/hosts + + setup_basic_environment + install_keymaps yes + install_zoneinfo + # Install nproc to determine # of CPUs for correct parallelization + inst_binary nproc + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <&2 "check_result: missing arguments" + exit 1 + fi + + local name="${1##*/}" + local ret=$2 + + if [[ $ret -ne 0 && $ret != 77 ]]; then + echo "$name failed with $ret" + echo "$name" >> /failed-tests + { + echo "--- $name begin ---" + cat "/$name.log" + echo "--- $name end ---" + } >> /failed + elif [[ $ret == 77 ]]; then + echo "$name skipped" + echo "$name" >> /skipped-tests + { + echo "--- $name begin ---" + cat "/$name.log" + echo "--- $name end ---" + } >> /skipped + else + echo "$name OK" + echo "$name" >> /testok + fi + + systemd-cat echo "--- $name ---" + systemd-cat cat "/$name.log" +} + +# Associative array for running tasks, where running[test-path]=PID +declare -A running=() +for task in "${TEST_LIST[@]}"; do + # If there's MAX_QUEUE_SIZE running tasks, keep checking the running queue + # until one of the tasks finishes, so we can replace it. + while [[ ${#running[@]} -ge $MAX_QUEUE_SIZE ]]; do + for key in "${!running[@]}"; do + if ! kill -0 ${running[$key]} &>/dev/null; then + # Task has finished, report its result and drop it from the queue + wait ${running[$key]} + ec=$? + report_result "$key" $ec + unset running["$key"] + # Break from inner for loop and outer while loop to skip + # the sleep below when we find a free slot in the queue + break 2 + fi + done + + # Precisely* calculated constant to keep the spinlock from burning the CPU(s) + sleep 0.01 + done + + if [[ -x $task ]]; then + log_file="/${task##*/}.log" + $task &> "$log_file" & + running[$task]=$! + fi +done + +# Wait for remaining running tasks +for key in "${!running[@]}"; do + wait ${running[$key]} + ec=$? + report_result "$key" $ec + unset running["$key"] +done + +exit 0 diff --git a/test/TEST-25-IMPORT/Makefile b/test/TEST-25-IMPORT/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-25-IMPORT/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-25-IMPORT/blacklist-ubuntu-ci b/test/TEST-25-IMPORT/blacklist-ubuntu-ci new file mode 100644 index 00000000..e69de29b diff --git a/test/TEST-25-IMPORT/test.sh b/test/TEST-25-IMPORT/test.sh new file mode 100755 index 00000000..c0f51f3b --- /dev/null +++ b/test/TEST-25-IMPORT/test.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="test importd" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + dracut_install dd gunzip mv tar diff + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /var/tmp/scratch/adirectory/athirdfile + +# Test import-fs +machinectl import-fs /var/tmp/scratch/ +test -d /var/lib/machines/scratch +machinectl image-status scratch + +# Test export-tar +machinectl export-tar scratch /var/tmp/scratch.tar.gz +test -f /var/tmp/scratch.tar.gz +mkdir /var/tmp/extract +(cd /var/tmp/extract ; tar xzf /var/tmp/scratch.tar.gz) +diff -r /var/tmp/scratch/ /var/tmp/extract/ +rm -rf /var/tmp/extract + +# Test import-tar +machinectl import-tar /var/tmp/scratch.tar.gz scratch2 +test -d /var/lib/machines/scratch2 +machinectl image-status scratch2 +diff -r /var/tmp/scratch/ /var/lib/machines/scratch2 + +# Test removal +machinectl remove scratch +! test -f /var/lib/machines/scratch +! machinectl image-status scratch + +# Test clone +machinectl clone scratch2 scratch3 +test -d /var/lib/machines/scratch2 +machinectl image-status scratch2 +test -d /var/lib/machines/scratch3 +machinectl image-status scratch3 +diff -r /var/tmp/scratch/ /var/lib/machines/scratch3 + +# Test removal +machinectl remove scratch2 +! test -f /var/lib/machines/scratch2 +! machinectl image-status scratch2 + +# Test rename +machinectl rename scratch3 scratch4 +test -d /var/lib/machines/scratch4 +machinectl image-status scratch4 +! test -f /var/lib/machines/scratch3 +! machinectl image-status scratch3 +diff -r /var/tmp/scratch/ /var/lib/machines/scratch4 + +# Test removal +machinectl remove scratch4 +! test -f /var/lib/machines/scratch4 +! machinectl image-status scratch4 + +# Test import-tar hypen/stdin pipe behavior +cat /var/tmp/scratch.tar.gz | machinectl import-tar - scratch5 +test -d /var/lib/machines/scratch5 +machinectl image-status scratch5 +diff -r /var/tmp/scratch/ /var/lib/machines/scratch5 + +# Test export-tar hypen/stdout pipe behavior +mkdir -p /var/tmp/extract +machinectl export-tar scratch5 - | tar xvf - -C /var/tmp/extract/ +diff -r /var/tmp/scratch/ /var/tmp/extract/ +rm -rf /var/tmp/extract + +rm -rf /var/tmp/scratch + +echo OK > /testok + +exit 0 diff --git a/test/TEST-26-SETENV/Makefile b/test/TEST-26-SETENV/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-26-SETENV/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-26-SETENV/test.sh b/test/TEST-26-SETENV/test.sh new file mode 100755 index 00000000..065a8e46 --- /dev/null +++ b/test/TEST-26-SETENV/test.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="test setenv" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <&2' +cmp /tmp/stdout <&2' +cmp /tmp/stdout <&2' +cmp /tmp/stdout < /testok + +exit 0 diff --git a/test/TEST-28-PERCENTJ-WANTEDBY/Makefile b/test/TEST-28-PERCENTJ-WANTEDBY/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-28-PERCENTJ-WANTEDBY/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-28-PERCENTJ-WANTEDBY/test.sh b/test/TEST-28-PERCENTJ-WANTEDBY/test.sh new file mode 100755 index 00000000..3427ba7a --- /dev/null +++ b/test/TEST-28-PERCENTJ-WANTEDBY/test.sh @@ -0,0 +1,56 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="Ensure %j Wants directives work" +RUN_IN_UNPRIVILEGED_CONTAINER=yes + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # Set up the services. + cat >$initdir/etc/systemd/system/specifier-j-wants.service << EOF +[Unit] +Description=Wants with percent-j specifier +Wants=specifier-j-depends-%j.service +After=specifier-j-depends-%j.service + +[Service] +Type=oneshot +ExecStart=test -f /tmp/test-specifier-j-%j +ExecStart=/bin/sh -c 'echo OK > /testok' +EOF + cat >$initdir/etc/systemd/system/specifier-j-depends-wants.service << EOF +[Unit] +Description=Dependent service for percent-j specifier + +[Service] +Type=oneshot +ExecStart=touch /tmp/test-specifier-j-wants +EOF + cat >$initdir/etc/systemd/system/testsuite.service << EOF +[Unit] +Description=Testsuite: Ensure %j Wants directives work +Wants=specifier-j-wants.service +After=specifier-j-wants.service + +[Service] +Type=oneshot +ExecStart=/bin/true +EOF + + setup_testsuite + ) + + setup_nspawn_root +} + +do_test "$@" diff --git a/test/TEST-29-UDEV-ID_RENAMING/Makefile b/test/TEST-29-UDEV-ID_RENAMING/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-29-UDEV-ID_RENAMING/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-29-UDEV-ID_RENAMING/test.sh b/test/TEST-29-UDEV-ID_RENAMING/test.sh new file mode 100755 index 00000000..7d173c84 --- /dev/null +++ b/test/TEST-29-UDEV-ID_RENAMING/test.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="UDEV ID_RENAMING property" +TEST_NO_NSPAWN=1 + +. $TEST_BASE_DIR/test-functions +QEMU_TIMEOUT=300 + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /run/udev/rules.d/50-testsuite.rules < /testok + +exit 0 diff --git a/test/TEST-30-ONCLOCKCHANGE/Makefile b/test/TEST-30-ONCLOCKCHANGE/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-30-ONCLOCKCHANGE/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-30-ONCLOCKCHANGE/blacklist-ubuntu-ci-i386 b/test/TEST-30-ONCLOCKCHANGE/blacklist-ubuntu-ci-i386 new file mode 100644 index 00000000..e69de29b diff --git a/test/TEST-30-ONCLOCKCHANGE/test.sh b/test/TEST-30-ONCLOCKCHANGE/test.sh new file mode 100755 index 00000000..8976e953 --- /dev/null +++ b/test/TEST-30-ONCLOCKCHANGE/test.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="test OnClockChange= + OnTimezoneChange=" +TEST_NO_NSPAWN=1 + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + inst_any /usr/share/zoneinfo/Europe/Kiev + inst_any /usr/share/zoneinfo/Europe/Berlin + + setup_basic_environment + mask_supporting_services + + # extend the watchdog + mkdir -p $initdir/etc/systemd/system/systemd-timedated.service.d + cat >$initdir/etc/systemd/system/systemd-timedated.service.d/watchdog.conf <$initdir/etc/systemd/system/testsuite.service < /testok + +exit 0 diff --git a/test/TEST-31-DEVICE-ENUMERATION/Makefile b/test/TEST-31-DEVICE-ENUMERATION/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-31-DEVICE-ENUMERATION/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-31-DEVICE-ENUMERATION/test.sh b/test/TEST-31-DEVICE-ENUMERATION/test.sh new file mode 100755 index 00000000..e88e0c36 --- /dev/null +++ b/test/TEST-31-DEVICE-ENUMERATION/test.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="plugged -> dead -> plugged issue #11997" +TEST_NO_NSPAWN=1 + +. $TEST_BASE_DIR/test-functions +QEMU_TIMEOUT=300 + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < dead'; then + exit 1 +fi + +echo OK > /testok +exit 0 diff --git a/test/TEST-32-OOMPOLICY/Makefile b/test/TEST-32-OOMPOLICY/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-32-OOMPOLICY/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-32-OOMPOLICY/test.sh b/test/TEST-32-OOMPOLICY/test.sh new file mode 100755 index 00000000..1726b21f --- /dev/null +++ b/test/TEST-32-OOMPOLICY/test.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="test OOM killer logic" +TEST_NO_NSPAWN=1 + +. $TEST_BASE_DIR/test-functions + +UNIFIED_CGROUP_HIERARCHY=yes + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /proc/sys/kernel/sysrq + echo f > /proc/sysrq-trigger + + while : ; do + STATE=`systemctl show -p ActiveState --value oomtest.service` + [ "$STATE" = "failed" ] && break + sleep .5 + done + + RESULT=`systemctl show -p Result --value oomtest.service` + test "$RESULT" = "oom-kill" + + systemd-analyze log-level info +fi + +echo OK > /testok + +exit 0 diff --git a/test/TEST-33-CLEAN-UNIT/Makefile b/test/TEST-33-CLEAN-UNIT/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-33-CLEAN-UNIT/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-33-CLEAN-UNIT/test.sh b/test/TEST-33-CLEAN-UNIT/test.sh new file mode 100755 index 00000000..b3316bdc --- /dev/null +++ b/test/TEST-33-CLEAN-UNIT/test.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh +set -e +TEST_DESCRIPTION="test CleanUnit" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /etc/systemd/system/testservice.service < /etc/systemd/system/testservice.service < /etc/systemd/system/tmp-hoge.mount < /etc/systemd/system/testservice.socket < /testok + +exit 0 diff --git a/test/TEST-34-DYNAMICUSERMIGRATE/Makefile b/test/TEST-34-DYNAMICUSERMIGRATE/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-34-DYNAMICUSERMIGRATE/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-34-DYNAMICUSERMIGRATE/test.sh b/test/TEST-34-DYNAMICUSERMIGRATE/test.sh new file mode 100755 index 00000000..c7c1b29d --- /dev/null +++ b/test/TEST-34-DYNAMICUSERMIGRATE/test.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="test migrating state directory from DynamicUser=1 to DynamicUser=0 and back" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /testok + +exit 0 diff --git a/test/TEST-35-NETWORK-GENERATOR/Makefile b/test/TEST-35-NETWORK-GENERATOR/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-35-NETWORK-GENERATOR/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-35-NETWORK-GENERATOR/test-01-dhcp.expected/91-default.network b/test/TEST-35-NETWORK-GENERATOR/test-01-dhcp.expected/91-default.network new file mode 100644 index 00000000..e42ce1e3 --- /dev/null +++ b/test/TEST-35-NETWORK-GENERATOR/test-01-dhcp.expected/91-default.network @@ -0,0 +1,11 @@ +# Automatically generated by systemd-network-generator + +[Match] +Name=* + +[Link] + +[Network] +DHCP=ipv4 + +[DHCP] diff --git a/test/TEST-35-NETWORK-GENERATOR/test-01-dhcp.input b/test/TEST-35-NETWORK-GENERATOR/test-01-dhcp.input new file mode 100644 index 00000000..e55893e7 --- /dev/null +++ b/test/TEST-35-NETWORK-GENERATOR/test-01-dhcp.input @@ -0,0 +1 @@ +ip=dhcp diff --git a/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-bridge99.netdev b/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-bridge99.netdev new file mode 100644 index 00000000..97c22485 --- /dev/null +++ b/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-bridge99.netdev @@ -0,0 +1,5 @@ +# Automatically generated by systemd-network-generator + +[NetDev] +Kind=bridge +Name=bridge99 diff --git a/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-bridge99.network b/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-bridge99.network new file mode 100644 index 00000000..f8d19baa --- /dev/null +++ b/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-bridge99.network @@ -0,0 +1,13 @@ +# Automatically generated by systemd-network-generator + +[Match] +Name=bridge99 + +[Link] +MACAddress=00:11:22:33:44:55 +MTUBytes=1530 + +[Network] +DHCP=ipv4 + +[DHCP] diff --git a/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-eth0.network b/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-eth0.network new file mode 100644 index 00000000..8842b579 --- /dev/null +++ b/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-eth0.network @@ -0,0 +1,21 @@ +# Automatically generated by systemd-network-generator + +[Match] +Name=eth0 + +[Link] + +[Network] +DHCP=no +DNS=10.10.10.10 +DNS=10.10.10.11 +Bridge=bridge99 + +[DHCP] +Hostname=hogehoge + +[Address] +Address=192.168.0.10/24 + +[Route] +Gateway=192.168.0.1 diff --git a/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-eth1.network b/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-eth1.network new file mode 100644 index 00000000..feff4f5b --- /dev/null +++ b/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.expected/90-eth1.network @@ -0,0 +1,21 @@ +# Automatically generated by systemd-network-generator + +[Match] +Name=eth1 + +[Link] + +[Network] +DHCP=no +DNS=10.10.10.10 +DNS=10.10.10.11 +Bridge=bridge99 + +[DHCP] +Hostname=hogehoge + +[Address] +Address=192.168.0.11/24 + +[Route] +Gateway=192.168.0.1 diff --git a/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.input b/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.input new file mode 100644 index 00000000..0c863fc3 --- /dev/null +++ b/test/TEST-35-NETWORK-GENERATOR/test-02-bridge.input @@ -0,0 +1,4 @@ +ip=192.168.0.10::192.168.0.1:255.255.255.0:hogehoge:eth0:off:10.10.10.10:10.10.10.11 +ip=192.168.0.11::192.168.0.1:255.255.255.0:hogehoge:eth1:off:10.10.10.10:10.10.10.11 +ip=bridge99:dhcp:1530:00:11:22:33:44:55 +bridge=bridge99:eth0,eth1 diff --git a/test/TEST-35-NETWORK-GENERATOR/test.sh b/test/TEST-35-NETWORK-GENERATOR/test.sh new file mode 100755 index 00000000..4ee5da53 --- /dev/null +++ b/test/TEST-35-NETWORK-GENERATOR/test.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="network-generator tests" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + mkdir -p $TESTDIR/run/systemd/network +} + +test_run() { + local generator + + if [[ -x $BUILD_DIR/systemd-network-generator ]]; then + generator=$BUILD_DIR/systemd-network-generator + elif [[ -x /usr/lib/systemd/systemd-network-generator ]]; then + generator=/usr/lib/systemd/systemd-network-generator + elif [[ -x /lib/systemd/systemd-network-generator ]]; then + generator=/lib/systemd/systemd-network-generator + else + exit 1 + fi + + for f in test-*.input; do + echo "*** Running $f" + rm -f $TESTDIR/run/systemd/network/* + $generator --root $TESTDIR -- $(cat $f) + + if ! diff -u $TESTDIR/run/systemd/network ${f%.input}.expected; then + echo "**** Unexpected output for $f" + exit 1 + fi + done +} + +do_test "$@" diff --git a/test/TEST-36-NUMAPOLICY/Makefile b/test/TEST-36-NUMAPOLICY/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-36-NUMAPOLICY/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-36-NUMAPOLICY/blacklist-ubuntu-ci-s390x b/test/TEST-36-NUMAPOLICY/blacklist-ubuntu-ci-s390x new file mode 100644 index 00000000..e69de29b diff --git a/test/TEST-36-NUMAPOLICY/test.sh b/test/TEST-36-NUMAPOLICY/test.sh new file mode 100755 index 00000000..e4c0e45e --- /dev/null +++ b/test/TEST-36-NUMAPOLICY/test.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -e + +TEST_DESCRIPTION="test MUMAPolicy= and NUMAMask= options" +TEST_NO_NSPAWN=1 +QEMU_OPTIONS="-numa node,nodeid=0" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + dracut_install mktemp + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service </dev/null; do sleep 0.1; done +} + +startJournalctl() { + # Save journal's cursor for later navigation + journalctl --no-pager --cursor-file="$journalCursorFile" -n0 -ocat +} + +stopJournalctl() { + local unit="${1:-init.scope}" + # Using journalctl --sync should be better than using SIGRTMIN+1, as + # the --sync wait until the synchronization is complete + echo "Force journald to write all queued messages" + journalctl --sync + journalctl -u $unit --cursor-file="$journalCursorFile" > "$journalLog" +} + +checkNUMA() { + # NUMA enabled system should have at least NUMA node0 + test -e /sys/devices/system/node/node0 +} + +writePID1NUMAPolicy() { + echo [Manager] > $confDir/numa.conf + echo NUMAPolicy=$1 >> $confDir/numa.conf + echo NUMAMask=$2>> $confDir/numa.conf +} + +writeTestUnit() { + echo [Service] > $testUnitFile + echo ExecStart=/bin/sleep 3600 >> $testUnitFile + mkdir -p $testUnitFile.d/ +} + +writeTestUnitNUMAPolicy() { + echo [Service] > $testUnitNUMAConf + echo NUMAPolicy=$1 >> $testUnitNUMAConf + echo NUMAMask=$2>> $testUnitNUMAConf + systemctl daemon-reload +} + +pid1ReloadWithStrace() { + startStrace + systemctl daemon-reload + sleep $sleepAfterStart + stopStrace +} + +pid1ReloadWithJournal() { + startJournalctl + systemctl daemon-reload + stopJournalctl +} + +pid1StartUnitWithStrace() { + startStrace '-f' + systemctl start $1 + sleep $sleepAfterStart + stopStrace +} + +pid1StartUnitWithJournal() { + startJournalctl + systemctl start $1 + sleep $sleepAfterStart + stopJournalctl +} + +pid1StopUnit() { + systemctl stop $1 +} + +systemctlCheckNUMAProperties() { + local LOGFILE="$(mktemp)" + systemctl show -p NUMAPolicy $1 > "$LOGFILE" + grep "NUMAPolicy=$2" "$LOGFILE" + + > "$LOGFILE" + + if [ -n $3 ]; then + systemctl show -p NUMAMask $1 > "$LOGFILE" + grep "NUMAMask=$3" "$LOGFILE" + fi +} + +writeTestUnit + +# Create systemd config drop-in directory +confDir="/etc/systemd/system.conf.d/" +mkdir -p "$confDir" + +if ! checkNUMA; then + echo >&2 "NUMA is not supported on this machine, switching to a simple sanity check" + + echo "PID1 NUMAPolicy=default && NUMAMask=0 check without NUMA support" + writePID1NUMAPolicy "default" "0" + startJournalctl + systemctl daemon-reload + stopJournalctl + grep "NUMA support not available, ignoring" "$journalLog" + + echo "systemd-run NUMAPolicy=default && NUMAMask=0 check without NUMA support" + runUnit='numa-systemd-run-test.service' + startJournalctl + systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000 + sleep $sleepAfterStart + pid1StopUnit $runUnit + stopJournalctl $runUnit + grep "NUMA support not available, ignoring" "$journalLog" + +else + echo "PID1 NUMAPolicy support - Default policy w/o mask" + writePID1NUMAPolicy "default" + pid1ReloadWithStrace + # Kernel requires that nodemask argument is set to NULL when setting default policy + grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog + + echo "PID1 NUMAPolicy support - Default policy w/ mask" + writePID1NUMAPolicy "default" "0" + pid1ReloadWithStrace + grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog + + echo "PID1 NUMAPolicy support - Bind policy w/o mask" + writePID1NUMAPolicy "bind" + pid1ReloadWithJournal + grep "Failed to set NUMA memory policy: Invalid argument" $journalLog + + echo "PID1 NUMAPolicy support - Bind policy w/ mask" + writePID1NUMAPolicy "bind" "0" + pid1ReloadWithStrace + grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog + + echo "PID1 NUMAPolicy support - Interleave policy w/o mask" + writePID1NUMAPolicy "interleave" + pid1ReloadWithJournal + grep "Failed to set NUMA memory policy: Invalid argument" $journalLog + + echo "PID1 NUMAPolicy support - Interleave policy w/ mask" + writePID1NUMAPolicy "interleave" "0" + pid1ReloadWithStrace + grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog + + echo "PID1 NUMAPolicy support - Preferred policy w/o mask" + writePID1NUMAPolicy "preferred" + pid1ReloadWithJournal + # Preferred policy with empty node mask is actually allowed and should reset allocation policy to default + ! grep "Failed to set NUMA memory policy: Invalid argument" $journalLog + + echo "PID1 NUMAPolicy support - Preferred policy w/ mask" + writePID1NUMAPolicy "preferred" "0" + pid1ReloadWithStrace + grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog + + echo "PID1 NUMAPolicy support - Local policy w/o mask" + writePID1NUMAPolicy "local" + pid1ReloadWithStrace + # Kernel requires that nodemask argument is set to NULL when setting default policy + # The unpatched versions of strace don't recognize the MPOL_LOCAL constant and + # return a numerical constant instead (with a comment): + # set_mempolicy(0x4 /* MPOL_??? */, NULL, 0) = 0 + # Let's cover this scenario as well + grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog + + echo "PID1 NUMAPolicy support - Local policy w/ mask" + writePID1NUMAPolicy "local" "0" + pid1ReloadWithStrace + grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog + + echo "Unit file NUMAPolicy support - Default policy w/o mask" + writeTestUnitNUMAPolicy "default" + pid1StartUnitWithStrace $testUnit + systemctlCheckNUMAProperties $testUnit "default" + pid1StopUnit $testUnit + grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog + + echo "Unit file NUMAPolicy support - Default policy w/ mask" + writeTestUnitNUMAPolicy "default" "0" + pid1StartUnitWithStrace $testUnit + systemctlCheckNUMAProperties $testUnit "default" "0" + pid1StopUnit $testUnit + # Maks must be ignored + grep "set_mempolicy(MPOL_DEFAULT, NULL" $straceLog + + echo "Unit file NUMAPolicy support - Bind policy w/o mask" + writeTestUnitNUMAPolicy "bind" + pid1StartUnitWithJournal $testUnit + pid1StopUnit $testUnit + grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog + + echo "Unit file NUMAPolicy support - Bind policy w/ mask" + writeTestUnitNUMAPolicy "bind" "0" + pid1StartUnitWithStrace $testUnit + systemctlCheckNUMAProperties $testUnit "bind" "0" + pid1StopUnit $testUnit + grep -P "set_mempolicy\(MPOL_BIND, \[0x0*1\]" $straceLog + + echo "Unit file NUMAPolicy support - Interleave policy w/o mask" + writeTestUnitNUMAPolicy "interleave" + pid1StartUnitWithStrace $testUnit + pid1StopUnit $testUnit + grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog + + echo "Unit file NUMAPolicy support - Interleave policy w/ mask" + writeTestUnitNUMAPolicy "interleave" "0" + pid1StartUnitWithStrace $testUnit + systemctlCheckNUMAProperties $testUnit "interleave" "0" + pid1StopUnit $testUnit + grep -P "set_mempolicy\(MPOL_INTERLEAVE, \[0x0*1\]" $straceLog + + echo "Unit file NUMAPolicy support - Preferred policy w/o mask" + writeTestUnitNUMAPolicy "preferred" + pid1StartUnitWithJournal $testUnit + systemctlCheckNUMAProperties $testUnit "preferred" + pid1StopUnit $testUnit + ! grep "numa-test.service: Main process exited, code=exited, status=242/NUMA" $journalLog + + echo "Unit file NUMAPolicy support - Preferred policy w/ mask" + writeTestUnitNUMAPolicy "preferred" "0" + pid1StartUnitWithStrace $testUnit + systemctlCheckNUMAProperties $testUnit "preferred" "0" + pid1StopUnit $testUnit + grep -P "set_mempolicy\(MPOL_PREFERRED, \[0x0*1\]" $straceLog + + echo "Unit file NUMAPolicy support - Local policy w/o mask" + writeTestUnitNUMAPolicy "local" + pid1StartUnitWithStrace $testUnit + systemctlCheckNUMAProperties $testUnit "local" + pid1StopUnit $testUnit + grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog + + echo "Unit file NUMAPolicy support - Local policy w/ mask" + writeTestUnitNUMAPolicy "local" "0" + pid1StartUnitWithStrace $testUnit + systemctlCheckNUMAProperties $testUnit "local" "0" + pid1StopUnit $testUnit + # Maks must be ignored + grep -E "set_mempolicy\((MPOL_LOCAL|0x4 [^,]*), NULL" $straceLog + + echo "systemd-run NUMAPolicy support" + runUnit='numa-systemd-run-test.service' + + systemd-run -p NUMAPolicy=default --unit $runUnit sleep 1000 + systemctlCheckNUMAProperties $runUnit "default" + pid1StopUnit $runUnit + + systemd-run -p NUMAPolicy=default -p NUMAMask=0 --unit $runUnit sleep 1000 + systemctlCheckNUMAProperties $runUnit "default" "" + pid1StopUnit $runUnit + + systemd-run -p NUMAPolicy=bind -p NUMAMask=0 --unit $runUnit sleep 1000 + systemctlCheckNUMAProperties $runUnit "bind" "0" + pid1StopUnit $runUnit + + systemd-run -p NUMAPolicy=interleave -p NUMAMask=0 --unit $runUnit sleep 1000 + systemctlCheckNUMAProperties $runUnit "interleave" "0" + pid1StopUnit $runUnit + + systemd-run -p NUMAPolicy=preferred -p NUMAMask=0 --unit $runUnit sleep 1000 + systemctlCheckNUMAProperties $runUnit "preferred" "0" + pid1StopUnit $runUnit + + systemd-run -p NUMAPolicy=local --unit $runUnit sleep 1000 + systemctlCheckNUMAProperties $runUnit "local" + pid1StopUnit $runUnit + + systemd-run -p NUMAPolicy=local -p NUMAMask=0 --unit $runUnit sleep 1000 + systemctlCheckNUMAProperties $runUnit "local" "" + pid1StopUnit $runUnit +fi + +# Cleanup +rm -rf $testDir +rm -rf $confDir +systemctl daemon-reload + +systemd-analyze log-level info + +echo OK > /testok + +exit 0 diff --git a/test/TEST-37-RUNTIMEDIRECTORYPRESERVE/Makefile b/test/TEST-37-RUNTIMEDIRECTORYPRESERVE/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-37-RUNTIMEDIRECTORYPRESERVE/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-37-RUNTIMEDIRECTORYPRESERVE/test.sh b/test/TEST-37-RUNTIMEDIRECTORYPRESERVE/test.sh new file mode 100755 index 00000000..ffe0ee94 --- /dev/null +++ b/test/TEST-37-RUNTIMEDIRECTORYPRESERVE/test.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh +set -e +TEST_DESCRIPTION="test RuntimeDirectoryPreserve=yes" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /testok + +exit 0 diff --git a/test/TEST-39-EXECRELOAD/Makefile b/test/TEST-39-EXECRELOAD/Makefile new file mode 120000 index 00000000..e9f93b11 --- /dev/null +++ b/test/TEST-39-EXECRELOAD/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-39-EXECRELOAD/test.sh b/test/TEST-39-EXECRELOAD/test.sh new file mode 100755 index 00000000..d2b1663a --- /dev/null +++ b/test/TEST-39-EXECRELOAD/test.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="Test ExecReload= (PR #13098)" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + dracut_install mktemp + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < "$SERVICE_PATH" << EOF +[Service] +ExecStart=/bin/sleep infinity +ExecReload=/bin/false +EOF + +systemctl daemon-reload +systemctl start $SERVICE_NAME +systemctl status $SERVICE_NAME +# The reload SHOULD fail but SHOULD NOT affect the service state +! systemctl reload $SERVICE_NAME +systemctl status $SERVICE_NAME +systemctl stop $SERVICE_NAME + + +echo "[#2] Failing ExecReload= should not kill the service (multiple ExecReload=)" +cat > "$SERVICE_PATH" << EOF +[Service] +ExecStart=/bin/sleep infinity +ExecReload=/bin/true +ExecReload=/bin/false +ExecReload=/bin/true +EOF + +systemctl daemon-reload +systemctl start $SERVICE_NAME +systemctl status $SERVICE_NAME +# The reload SHOULD fail but SHOULD NOT affect the service state +! systemctl reload $SERVICE_NAME +systemctl status $SERVICE_NAME +systemctl stop $SERVICE_NAME + +echo "[#3] Failing ExecReload=- should not affect reload's exit code" +cat > "$SERVICE_PATH" << EOF +[Service] +ExecStart=/bin/sleep infinity +ExecReload=-/bin/false +EOF + +systemctl daemon-reload +systemctl start $SERVICE_NAME +systemctl status $SERVICE_NAME +systemctl reload $SERVICE_NAME +systemctl status $SERVICE_NAME +systemctl stop $SERVICE_NAME + +systemd-analyze log-level info + +echo OK > /testok + +exit 0 diff --git a/test/TEST-40-EXEC-COMMAND-EX/Makefile b/test/TEST-40-EXEC-COMMAND-EX/Makefile new file mode 100644 index 00000000..45e9bfc6 --- /dev/null +++ b/test/TEST-40-EXEC-COMMAND-EX/Makefile @@ -0,0 +1,9 @@ +BUILD_DIR=$(shell ../../tools/find-build-dir.sh) + +all setup run: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@ + +clean clean-again: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --clean + +.PHONY: all setup run clean clean-again diff --git a/test/TEST-40-EXEC-COMMAND-EX/blacklist-ubuntu-ci-arm64 b/test/TEST-40-EXEC-COMMAND-EX/blacklist-ubuntu-ci-arm64 new file mode 100644 index 00000000..e69de29b diff --git a/test/TEST-40-EXEC-COMMAND-EX/test.sh b/test/TEST-40-EXEC-COMMAND-EX/test.sh new file mode 100755 index 00000000..01d725eb --- /dev/null +++ b/test/TEST-40-EXEC-COMMAND-EX/test.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="test ExecXYZEx= service unit dbus hookups" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /testok + +exit 0 diff --git a/test/TEST-41-ONESHOT-RESTART/Makefile b/test/TEST-41-ONESHOT-RESTART/Makefile new file mode 100644 index 00000000..45e9bfc6 --- /dev/null +++ b/test/TEST-41-ONESHOT-RESTART/Makefile @@ -0,0 +1,9 @@ +BUILD_DIR=$(shell ../../tools/find-build-dir.sh) + +all setup run: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@ + +clean clean-again: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --clean + +.PHONY: all setup run clean clean-again diff --git a/test/TEST-41-ONESHOT-RESTART/test.sh b/test/TEST-41-ONESHOT-RESTART/test.sh new file mode 100755 index 00000000..96c21da6 --- /dev/null +++ b/test/TEST-41-ONESHOT-RESTART/test.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="Test oneshot unit restart on failure" +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + mask_supporting_services + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <> $TMP_FILE\"" /bin/bash -c "exit 1" + +# wait for at least 3 restarts +for ((secs=0; secs<$MAX_SECS; secs++)); do + [[ $(cat $TMP_FILE) != "aaa" ]] || break + sleep 1 +done +if [[ $(cat $TMP_FILE) != "aaa" ]]; then + exit 1 +fi + +# wait for 5 more seconds to make sure there aren't excess restarts +sleep 5 +if [[ $(cat $TMP_FILE) != "aaa" ]]; then + exit 1 +fi + +systemd-analyze log-level info + +echo OK > /testok + +exit 0 diff --git a/test/TEST-42-EXECSTOPPOST/Makefile b/test/TEST-42-EXECSTOPPOST/Makefile new file mode 100644 index 00000000..45e9bfc6 --- /dev/null +++ b/test/TEST-42-EXECSTOPPOST/Makefile @@ -0,0 +1,9 @@ +BUILD_DIR=$(shell ../../tools/find-build-dir.sh) + +all setup run: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@ + +clean clean-again: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --clean + +.PHONY: all setup run clean clean-again diff --git a/test/TEST-42-EXECSTOPPOST/test.sh b/test/TEST-42-EXECSTOPPOST/test.sh new file mode 100755 index 00000000..865989d0 --- /dev/null +++ b/test/TEST-42-EXECSTOPPOST/test.sh @@ -0,0 +1,49 @@ +#!/bin/bash +set -e +TEST_DESCRIPTION="test that ExecStopPost= is always run" + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image_rootdir + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + + mask_supporting_services + + # setup policy for Type=dbus test + mkdir -p $initdir/etc/dbus-1/system.d + cat > $initdir/etc/dbus-1/system.d/systemd.test.ExecStopPost.conf < + + + + + + +EOF + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service < /tmp/forking1.sh < /tmp/forking2.sh < /tmp/notify1.sh < /testok + +exit 0 diff --git a/test/a-conj.service b/test/a-conj.service new file mode 100644 index 00000000..db37ae71 --- /dev/null +++ b/test/a-conj.service @@ -0,0 +1,8 @@ +[Unit] +Description=A conjugate +Requires=a.service +After=a.service +Before=a.service + +[Service] +ExecStart=/bin/true diff --git a/test/a.service b/test/a.service new file mode 100644 index 00000000..4168d2d0 --- /dev/null +++ b/test/a.service @@ -0,0 +1,7 @@ +[Unit] +Description=A +Requires=b.service +Before=b.service + +[Service] +ExecStart=/bin/true diff --git a/test/b.service b/test/b.service new file mode 100644 index 00000000..e03bae36 --- /dev/null +++ b/test/b.service @@ -0,0 +1,6 @@ +[Unit] +Description=B +Wants=f.service + +[Service] +ExecStart=/bin/true diff --git a/test/basic.target b/test/basic.target new file mode 120000 index 00000000..06129346 --- /dev/null +++ b/test/basic.target @@ -0,0 +1 @@ +../units/basic.target \ No newline at end of file diff --git a/test/c.service b/test/c.service new file mode 100644 index 00000000..e2f60a8f --- /dev/null +++ b/test/c.service @@ -0,0 +1,6 @@ +[Unit] +Description=C +Requires=a.service + +[Service] +ExecStart=/bin/true diff --git a/test/create-sys-script.py b/test/create-sys-script.py new file mode 100755 index 00000000..d03ca2cb --- /dev/null +++ b/test/create-sys-script.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ + +OUTFILE_HEADER = """#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ +# +# create-sys-script.py +# +# © 2017 Canonical Ltd. +# Author: Dan Streetman +""" + +# Use this only to (re-)create the test/sys-script.py script, +# after adding or modifying anything in the test/sys/ directory + + +import os, sys +import stat +import tempfile +import filecmp +import subprocess + +OUTFILE_MODE = 0o775 + +OUTFILE_FUNCS = r""" +import os, sys +import shutil + +def d(path, mode): + os.mkdir(path, mode) + +def l(path, src): + os.symlink(src, path) + +def f(path, mode, contents): + with open(path, "wb") as f: + f.write(contents) + os.chmod(path, mode) +""" + +OUTFILE_MAIN = """ +if len(sys.argv) < 2: + exit("Usage: {} ".format(sys.argv[0])) + +if not os.path.isdir(sys.argv[1]): + exit("Target dir {} not found".format(sys.argv[1])) + +os.chdir(sys.argv[1]) + +if os.path.exists('sys'): + shutil.rmtree('sys') +""" + + +def handle_dir(outfile, path): + m = os.lstat(path).st_mode & 0o777 + outfile.write(f"d('{path}', {m:#o})\n") + + +def handle_link(outfile, path): + src = os.readlink(path) + outfile.write(f"l('{path}', '{src}')\n") + + +def escape_single_quotes(b): + # remove the b'' wrapping each line repr + r = repr(b)[2:-1] + # python escapes all ' only if there are ' and " in the string + if '"' not in r: + r = r.replace("'", r"\'") + # return line with all ' escaped + return r + + +def handle_file(outfile, path): + m = os.lstat(path).st_mode & 0o777 + with open(path, "rb") as f: + b = f.read() + if b.count(b"\n") > 1: + r = "\n".join( escape_single_quotes(l) for l in b.split(b"\n") ) + r = f"b'''{r}'''" + else: + r = repr(b) + outfile.write(f"f('{path}', {m:#o}, {r})\n") + + +def process_sysdir(outfile): + for (dirpath, dirnames, filenames) in os.walk('sys'): + handle_dir(outfile, dirpath) + for d in dirnames: + path = os.path.join(dirpath, d) + if stat.S_ISLNK(os.lstat(path).st_mode): + handle_link(outfile, path) + for f in filenames: + path = os.path.join(dirpath, f) + mode = os.lstat(path).st_mode + if stat.S_ISLNK(mode): + handle_link(outfile, path) + elif stat.S_ISREG(mode): + handle_file(outfile, path) + + +def verify_dir(tmpd, path_a): + path_b = os.path.join(tmpd, path_a) + mode_a = os.lstat(path_a).st_mode + mode_b = os.lstat(path_b).st_mode + if not stat.S_ISDIR(mode_b): + raise Exception("Not directory") + if (mode_a & 0o777) != (mode_b & 0o777): + raise Exception("Permissions mismatch") + + +def verify_link(tmpd, path_a): + path_b = os.path.join(tmpd, path_a) + if not stat.S_ISLNK(os.lstat(path_b).st_mode): + raise Exception("Not symlink") + if os.readlink(path_a) != os.readlink(path_b): + raise Exception("Symlink dest mismatch") + + +def verify_file(tmpd, path_a): + path_b = os.path.join(tmpd, path_a) + mode_a = os.lstat(path_a).st_mode + mode_b = os.lstat(path_b).st_mode + if not stat.S_ISREG(mode_b): + raise Exception("Not file") + if (mode_a & 0o777) != (mode_b & 0o777): + raise Exception("Permissions mismatch") + if not filecmp.cmp(path_a, path_b, shallow=False): + raise Exception("File contents mismatch") + + +def verify_script(tmpd): + any = False + for (dirpath, dirnames, filenames) in os.walk("sys"): + any = True + try: + path = dirpath + verify_dir(tmpd, path) + for d in dirnames: + path = os.path.join(dirpath, d) + if stat.S_ISLNK(os.lstat(path).st_mode): + verify_link(tmpd, path) + for f in filenames: + path = os.path.join(dirpath, f) + mode = os.lstat(path).st_mode + if stat.S_ISLNK(mode): + verify_link(tmpd, path) + elif stat.S_ISREG(mode): + verify_file(tmpd, path) + except Exception: + print(f'FAIL on "{path}"', file=sys.stderr) + raise + if not any: + exit('Nothing found!') + +if __name__ == "__main__": + if len(sys.argv) < 2: + exit('Usage: create-sys-script.py /path/to/test/') + + outfile = os.path.abspath(os.path.dirname(sys.argv[0]) + '/sys-script.py') + print(f'Creating {outfile} using contents of {sys.argv[1]}/sys') + + os.chdir(sys.argv[1]) + + with open(outfile, "w") as f: + os.chmod(outfile, OUTFILE_MODE) + f.write(OUTFILE_HEADER.replace(os.path.basename(sys.argv[0]), + os.path.basename(outfile))) + f.write(OUTFILE_FUNCS) + f.write(OUTFILE_MAIN) + process_sysdir(f) + + with tempfile.TemporaryDirectory() as tmpd: + print(f'Recreating sys/ using {outfile} at {tmpd}') + subprocess.check_call([outfile, tmpd]) + verify_script(tmpd) + + print(f'Verification successful, {outfile} is correct') diff --git a/test/d.service b/test/d.service new file mode 100644 index 00000000..921fd2ee --- /dev/null +++ b/test/d.service @@ -0,0 +1,8 @@ +[Unit] +Description=D:Cyclic +After=b.service +Before=a.service +Requires=a.service + +[Service] +ExecStart=/bin/true diff --git a/test/daughter.service b/test/daughter.service new file mode 100644 index 00000000..c790b9d0 --- /dev/null +++ b/test/daughter.service @@ -0,0 +1,8 @@ +[Unit] +Description=Daughter Service + +[Service] +Slice=parent.slice +Type=oneshot +ExecStart=/bin/true +CPUAccounting=true diff --git a/test/dml-discard-empty.service b/test/dml-discard-empty.service new file mode 100644 index 00000000..75228f64 --- /dev/null +++ b/test/dml-discard-empty.service @@ -0,0 +1,7 @@ +[Unit] +Description=DML discard empty service + +[Service] +Slice=dml-discard.slice +Type=oneshot +ExecStart=/bin/true diff --git a/test/dml-discard-set-ml.service b/test/dml-discard-set-ml.service new file mode 100644 index 00000000..591c9927 --- /dev/null +++ b/test/dml-discard-set-ml.service @@ -0,0 +1,8 @@ +[Unit] +Description=DML discard set ml service + +[Service] +Slice=dml-discard.slice +Type=oneshot +ExecStart=/bin/true +MemoryLow=15 diff --git a/test/dml-discard.slice b/test/dml-discard.slice new file mode 100644 index 00000000..e26d8684 --- /dev/null +++ b/test/dml-discard.slice @@ -0,0 +1,5 @@ +[Unit] +Description=DML discard slice + +[Slice] +DefaultMemoryLow= diff --git a/test/dml-override-empty.service b/test/dml-override-empty.service new file mode 100644 index 00000000..142c9872 --- /dev/null +++ b/test/dml-override-empty.service @@ -0,0 +1,7 @@ +[Unit] +Description=DML override empty service + +[Service] +Slice=dml-override.slice +Type=oneshot +ExecStart=/bin/true diff --git a/test/dml-override.slice b/test/dml-override.slice new file mode 100644 index 00000000..feb6773e --- /dev/null +++ b/test/dml-override.slice @@ -0,0 +1,5 @@ +[Unit] +Description=DML override slice + +[Slice] +DefaultMemoryLow=10 diff --git a/test/dml-passthrough-empty.service b/test/dml-passthrough-empty.service new file mode 100644 index 00000000..34832de4 --- /dev/null +++ b/test/dml-passthrough-empty.service @@ -0,0 +1,7 @@ +[Unit] +Description=DML passthrough empty service + +[Service] +Slice=dml-passthrough.slice +Type=oneshot +ExecStart=/bin/true diff --git a/test/dml-passthrough-set-dml.service b/test/dml-passthrough-set-dml.service new file mode 100644 index 00000000..5bdf4ed4 --- /dev/null +++ b/test/dml-passthrough-set-dml.service @@ -0,0 +1,8 @@ +[Unit] +Description=DML passthrough set DML service + +[Service] +Slice=dml-passthrough.slice +Type=oneshot +ExecStart=/bin/true +DefaultMemoryLow=15 diff --git a/test/dml-passthrough-set-ml.service b/test/dml-passthrough-set-ml.service new file mode 100644 index 00000000..2e568b5d --- /dev/null +++ b/test/dml-passthrough-set-ml.service @@ -0,0 +1,8 @@ +[Unit] +Description=DML passthrough set ML service + +[Service] +Slice=dml-passthrough.slice +Type=oneshot +ExecStart=/bin/true +MemoryLow=0 diff --git a/test/dml-passthrough.slice b/test/dml-passthrough.slice new file mode 100644 index 00000000..1b1a848e --- /dev/null +++ b/test/dml-passthrough.slice @@ -0,0 +1,5 @@ +[Unit] +Description=DML passthrough slice + +[Slice] +MemoryLow=100 diff --git a/test/dml.slice b/test/dml.slice new file mode 100644 index 00000000..84e333ef --- /dev/null +++ b/test/dml.slice @@ -0,0 +1,5 @@ +[Unit] +Description=DML slice + +[Slice] +DefaultMemoryLow=50 diff --git a/test/e.service b/test/e.service new file mode 100644 index 00000000..5ba98c7c --- /dev/null +++ b/test/e.service @@ -0,0 +1,8 @@ +[Unit] +Description=E:Cyclic +After=b.service +Before=a.service +Wants=a.service + +[Service] +ExecStart=/bin/true diff --git a/test/end.service b/test/end.service new file mode 100644 index 00000000..6e1996fd --- /dev/null +++ b/test/end.service @@ -0,0 +1,10 @@ +[Unit] +Description=End the test +After=testsuite.service +OnFailure=poweroff.target +OnFailureJobMode=replace-irreversibly + +[Service] +Type=oneshot +ExecStart=/bin/sh -x -c 'systemctl poweroff --no-block' +TimeoutStartSec=5m diff --git a/test/f.service b/test/f.service new file mode 100644 index 00000000..7dde681c --- /dev/null +++ b/test/f.service @@ -0,0 +1,5 @@ +[Unit] +Description=F + +[Service] +ExecStart=/bin/true diff --git a/test/fuzz/.gitattributes b/test/fuzz/.gitattributes new file mode 100644 index 00000000..7b1b3e18 --- /dev/null +++ b/test/fuzz/.gitattributes @@ -0,0 +1 @@ +/*/* -whitespace diff --git a/test/fuzz/fuzz-bus-message/crash-26bba7182dedc8848939931d9fcefcb7922f2e56 b/test/fuzz/fuzz-bus-message/crash-26bba7182dedc8848939931d9fcefcb7922f2e56 new file mode 100644 index 0000000000000000000000000000000000000000..f1bf3229effc982c8b129182fe60739efe3c5013 GIT binary patch literal 157 mcmd1#|DTC5gMmSS0SHWtK_neOii>$FgGM4Akdcw0DF6TjSP;el literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-bus-message/crash-29ed3c202e0ffade3cad42c8bbeb6cc68a21eb8e b/test/fuzz/fuzz-bus-message/crash-29ed3c202e0ffade3cad42c8bbeb6cc68a21eb8e new file mode 100644 index 0000000000000000000000000000000000000000..4488f0a6c685b5d43eddbe41a0c6a3b6be9b02e2 GIT binary patch literal 51 fcmc~1WMC4sJpJnr13KV`0|t%6q+%$@&=ddw)CUPg literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-bus-message/crash-32bf69483cbd4f2e6d46c25a2f92a472109aee45 b/test/fuzz/fuzz-bus-message/crash-32bf69483cbd4f2e6d46c25a2f92a472109aee45 new file mode 100644 index 0000000000000000000000000000000000000000..aa0c6ff7f7b6d2e3fa4358716ee1d05ba74cefc0 GIT binary patch literal 89 scmc~*W&P&W-;Q0Fg|9>Elfq|V9OfmRED27Bi2!jjC2Wn-| z17hYPAOVtNW-Ml42GVKy`9P9^ffdMS1=8h-IVt%J91NTwNgyEFV4&K>#6$*=MMgl( r%#fH?l1eMv=;=K=_yi-CK!KUB2_%6r0c0u^mlS2@rGxk|0FGY(dwVLU literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-bus-message/crash-4162a61a79e4c5a832ca5232212f75fa560a1f75 b/test/fuzz/fuzz-bus-message/crash-4162a61a79e4c5a832ca5232212f75fa560a1f75 new file mode 100644 index 0000000000000000000000000000000000000000..5faf3308e7ac9c14d66422169e74ba8c05ad7319 GIT binary patch literal 534 zcmd5(y$ZrW3{L#Rf|Cy*1sA)t;uE+zxcCZJw53qIqj#v2xH$UGez{(yI63-3NWO$5 zU+!uqzB5rdCwdYQvnEi=V1glA8o?i`lMy}upTQSe=c-Assy=GTr+lHv=4$0!Vy$EX z_LzYX&1*Ob(W(=vPGKsxuBpzYaDn6&un5*x;uk`Xz?Yk^O%qgGJ(zdq)(CT7OTMiz#q2KEMtDT&4= liD{N8W@+Y0hK!61V4zWvq@j_NlvJFQnL&wm%}Py80RUy_C0PIf literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-bus-message/crash-603dfd98252375ac7dbced53c2ec312671939a36 b/test/fuzz/fuzz-bus-message/crash-603dfd98252375ac7dbced53c2ec312671939a36 new file mode 100644 index 0000000000000000000000000000000000000000..b3fee9e07af4f925697a549bbc8ffc03a277fac0 GIT binary patch literal 40 mcmc~{Vqjzdg7laF|BC@>cE)0c{}2$`*K@IKT2AZ~5ElR}@e}O; literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-bus-message/crash-b88ad9ecf4aacf4a0caca5b5543953265367f084 b/test/fuzz/fuzz-bus-message/crash-b88ad9ecf4aacf4a0caca5b5543953265367f084 new file mode 100644 index 0000000000000000000000000000000000000000..52469650b5498a45d5d95bd9d933c989cfb47ca7 GIT binary patch literal 32 ccmd1#|DTBg0(2Mzp)7_%AVVXuuuM|`09r!?!~g&Q literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-bus-message/crash-c1b37b4729b42c0c05b23cba4eed5d8102498a1e b/test/fuzz/fuzz-bus-message/crash-c1b37b4729b42c0c05b23cba4eed5d8102498a1e new file mode 100644 index 0000000000000000000000000000000000000000..2ae1a8715a12c65fba27d8e60216112a99b0ace7 GIT binary patch literal 93 wcmd1FDP>|PH8L_f3B<@i03SeB2xg~!`?q0o*WZ8t85PAeqj{pplqVrYQgbfcytC literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-bus-message/leak-c09c0e2256d43bc5e2d02748c8d8760e7bc25d20 b/test/fuzz/fuzz-bus-message/leak-c09c0e2256d43bc5e2d02748c8d8760e7bc25d20 new file mode 100644 index 0000000000000000000000000000000000000000..c371824ffb604708619fd0713e8fca609bac18f7 GIT binary patch literal 534 zcmZ{h!A`?442GSJP20o?A&zJgm*%pT#&`l!4rxq{&>8YmwQrOs;B(}I_m11m8`nFp`#ek1>oQYVSs`!XH?7Y=}3y9Ye+UliL9^x9s66$8wH+TPdOG`n| z5Uhx&NW6m6ZC#~`RCNGV2*icg27V{4hLEuI z*Z%6nv6IG-c{fDW8PO*Z8RG~@1*A4LLPziq^|n=>fKTCf&ROnOFWhXL{-6KzKQR>* zA}kdo{MtXi^_lPUKI=U`x#dhG*Hq0w(L%415E=fPT+(I2*knx96tO2RVnnVP6o! Yuz#WfEX)Cqd!b_JHzYppZsXhk08nC8%>V!Z literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-bus-message/oss-fuzz-14016 b/test/fuzz/fuzz-bus-message/oss-fuzz-14016 new file mode 100644 index 0000000000000000000000000000000000000000..c82d1ba4adfbc829ef148bfc61907c51f1fc9b74 GIT binary patch literal 49343 zcmeHPOO7PR4Q&W8prww{S{h#XJZcQQGN6UMkTyPqbX6U|3^JK~43d!%oz>k{HQ9?u z^6~K#WaMXhM*8l{ET!ef^gI z{MvrL@v4gu-zI-7EI1GdS`^tS!nZ;C)Vi z2wD``DZ;lw`qVJ4Qj}dJ`Ab8>HAuX0HCrbcsWXsjwlBVIwuA2~EPFX)ke#`Bs|tr0 zI6?DRq_WCq0uho(IhqhV$iIcQcDQLKwas)*IO5#pY-(nJOpo~Ftc7MWV8Xk-_4>nQ?wReT%iRiLsHmE z6<+6Z;#{sw(vPueqb}>1yqBWsm8nos;tJMvF^QMfF#tKlkzMleI_eM+l1Mq45IZOx z_Tgh^x{0!&k2XCA}MU8?B#oySn3AX90fulULSQZX%(TFGLxct8B8(6M}zG^#@?RVz&$Ja zf}2JW%fqBKc`rrbDg-D_fUts#7mW!xfuKc^og#c2q)!c-D@EBwlD{-0T!X|5SF?4J zkvapZX1hM>Vs~hm(jb_s0Fm1ewuxy(Q|A*ObsB{T{i-pjDhG+L(_ecAvI`Ja-B!37 z6HEkx7DaZ7@NJMjHEgaFWfw{Q(vWZs5-(iM)=5U{45XUv`a?_X4h>Tp1XC3tavQ=n zF^y>Ie0^iIE@?ORtF&%g$DIf3x+od;w5iY@f#Jv9Hm+Jy0(%6MC1eK3^oTDxE+3ka zY!R&MViGSM=>X&qM|R1>D-~J3ABm7e%F%?_LFuu&&f(r-8A{i*kxHWzA2?{EAZ!Ef zS<&Ze8bvG*lkUWODGFC1Kyd9X%G#48QJiK2Mn8aW$cq)0Iv4g1;uEGV0eO(+pM|KbDp&L{}mB-)6k`A&S&Y6yO- znUY9QQ(`>{T{i-pjDhG+L(_C%ZG+ur2EllJ{zsYiV%u)lw~7gx&m)0==ImD4&^6*MEm3JT!l1Mq45Id;d?As4#?#zcO`LZ9x z*?`;?l89eUQ}o1Zh<7D%R*Tf^$Jc%oTPuf`a^Iz)tfTZO4P~fi5HDOyx{)HqY}bcd z?9S?81IM$k{t)c=vu6f4e)pd5?@UBf@cseCKE4eMQD?R>&7WMO#_$%-Y1N zSfDz}(a9Lv-*;?Weh%Rfuk<^ldOrUf!x6H?i`%&@0uf6RIIUn=MU;7w0- za+cy7+cfel50k5+ztz>)t`ZiC5Fo7R<78t3Odx1cWTyz<2I*77=1Ng^k>oE83D+R; z!qse@WTehOs@cAS8%H)9n@}P&O!0xKj)JgFqK#;p@5D!)hTsXBl1NZfVm%36Hv*iD zf#^>|(};Zj(V9%}0VXo&Q)lvRgWYBZ!FavC0lG#`tG=;KBiHi>Rl-6Q0)!Pt>_uY& zP9SJeWTyz<2I*77=1Ng^k>oE83D+R;!qse@WTehOs@bk@fY==xrZfnqDnR5mgl%FP z(bW0GH-Hp0OfocT33z?L-NIbf#pMQZv+lf0GSJl`@faM)?Uiu-rz2^TmJihGm^gu? zp2_tQ&zJSv3_NCvj-9>pE=j?wMcOu@KSR+suW3ZTKF_R?yL5e?4G+?8{Gb!H&tVfN zpJdt-E8v;F9B)gt*}&?|2}GI6^%0LxEk(b)P46V=m5RRRrjh0R1E5QMC-3&weBQ8> z=l9;1Ec%zuE0*+tr&CYbyRI`Mid}LD4BX+WND5m==bu>W2G<;A!r9{^SyrbGwH=Aq zmv=hS);2j3M-2q~>Xuy777!Rvur)v$&>x`X zw%kicbUS?2A@9Yd9nc;W#thyAPG;b0B+yJ}ue;h9c6YL3ha6>^^cXkQ8V-1 z$xT=t({;z`qiNLYPwtXTbaj;O91NBI!&X}`x|Z!J4dW8T4c3xw9H0;gS`^tS!nZ;C z)T6$sO?HvwFAWLTAo0T0Y@KAJ&OoZ!p7O8nV0$9Q4s3`qfkGf?QDmnG-v;SZ>p>b_ z%T1PsVXfkYYe_d!q?qj~51HSvY}R8#jpivnFxWCk`{HGzge-ZG@gqKxE&NOc#wKZL zyTreP-NInj#pMQZx5SHAN?HDnmI$u7qU2~o?4b7R;PB(#5m1)a792`IoV%P&%?yx< z?vJPXzkapbJ#?Y$8W^%ZaiG!=(jWjW-bA!I*{A>$2wD``DZ;lw`qa>-Qj}dJ`Ab8> zHAuX0HCrbcsWXsjw(IQ}yFx^;0h?5tx6c69J0g{@TN=ieRH8TXxHRf%M@ z2}xY4j&x@WGEM$5;IPm#Kb6EbDQ!g4;;*lV@q3MWsI7u)jsl?&(^vH2xF=4eP|AU4 z2EllpJeSjT5YcCB8iD2AukG?)il$elLPd!ySl7iQURuWhJ4zocKW8Q4qEP_pIo1HH{*kzuhD(6emDf_dfK3F~LG0Xi;RR z2;T{bq#KRcXaqucBV88ixe+hOS+LF z#cU6JBha=UU?PVnWGBc_;;^<~$$P_7OpvxN``CM+fZwcYOa|_;NFL64*Az{!eI6;& zQIAs(7)d-Ad_v(61D>R?m8vN}A&Hel%F%?_LG3$g`{DGR`A{WaDO;oLK<)}j#4o2Q zdg3+21xcK}rpY2T`|-6O1tciNa^Iz)tfTZO4P~fi5HDOyx{)HqY!CdtnmseJ+1P{< znGLJ~IDsfLxz64(+wH8`yX#B^&gB7jTi&=chUErvx9+@4GSSr{-8mR4U;GqpwaMIY zEh{#Xqs*L+lJmY}$%W1B{vfE|UDE zA>kS%UbvdAlZ@0ENHyDcaO22kV-re*hABQU)lm?(Nwg77^PTvp(-1sCQxXYkN~|ZL z>qdZ+F%bP}Xd02vKU$ONJ-|c;edccdtL8!+}~C zXGRoH-MyTNSXn^eI0jn-qyhcizucC4>4Ocitr# z>}rwOaVW6sz0^Ne_C_rqsMRrX0!cTM>m%O6>$e$r%oM$Ma~D3iOZ&@0s%z_>x)%xx zY;j$bn0=-tokI*ftZb2}$lHBM5AxEBIO~VKpZmf{&m2lj{F4eY10uE#53W<-tiaEm5KPu^wmAQ25(s;|sW(G*~ z{Et8#3U7L;r(?2jY}1H;eLHBo;TmtCac7&=cNc@P1%OJt)j<0AdvUOdvRZP6dPlVI o7rZ68H1w4^UA%C0W>k!XsK{n(((kXYZ*RZ-{QCBD`}yhR|MEbWjsO4v literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-bus-message/timeout-08ee8f6446a4064db064e8e0b3d220147f7d0b5b b/test/fuzz/fuzz-bus-message/timeout-08ee8f6446a4064db064e8e0b3d220147f7d0b5b new file mode 100644 index 0000000000000000000000000000000000000000..c975f906eef521a3cfac5627c8b371ee55aa0e6c GIT binary patch literal 534 zcmcJL!Ab-%42J(Y?m8o$d;nSS(q4Ae_Yi!A47)oFEOwaGU5e<<_x8`!K@h}~fslMn zn)c7Z!M!`6y9Pc0I2S?0hHh3l#W~|szZ;Ct$XAT}7+V?FCpm1RoiBemuU&_Ys%S@7 zdCkYS>{AZe=OjL~Ie67zrCwgdYud(O^J==RG>!dpXFS^tlZIX@tK0h@{D4MV@hJsW zyR)R1zXEs6tHM*H04&I}2-7)y>9oEVCxw(Vn{LBxXmJ)=frMcRdZlJ-~v b#4gh=OPF@NW^U~wGO=l?@b9nvyZbuI}lc?U|j~-6T6`GMQ|udtO()dR5(L;1a+rY;FEtdH{I+ zJwJc+lWxw!T0hIKCU|v|l&-rS{Bl1{d+B};l8k4!#5*F3wE20l8THflUURYAzuAHk3nR+d%G2cnWu~n z-I)_Vnz>tjkdt3Q6srf?6=Ay-1{t#(>e;8%RHZjWshMEyvTQtkWLYNQnRU+bPJYsk zGH9oTWr`ZsJ!d>7R2K}~iEd6CXzV@cOtRv}l&J|^J7={#s!jp0N=LYC$q9hUxKAsc zT$R>|*M@T`n$tex?w{ql(#lba&6@3UvAs*9d+VShot31zd@vNJW6BPv+sjF`#R z@3|)hQSsn0BC{t*iyF#+nzF`M<&5TR&1fSkO7*$wW3+wa^;a+6Y`@)p`3{}K>ecJH z*V{`D^^HZLTxIu*DLm$-j5{sWC!Cz=$r7J;aaZNRRQ2^`pHP#=`18qR*SfJ!mN zWxs=jPL&k1pJ8C1e|VmePb{)d(6VsHQOhRDs5#yYhMh{u%u}}n}v-% Otk58v0Xg;}jsG993Dt}M literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-dhcp6-client/crash-4003c06fce43a11fbd22f02584df2807ac333eae b/test/fuzz/fuzz-dhcp6-client/crash-4003c06fce43a11fbd22f02584df2807ac333eae new file mode 100644 index 0000000000000000000000000000000000000000..630ee6632cc9ddbb44258646ff705b84bb71b735 GIT binary patch literal 14 VcmZQqW?*2DU|?fq;Ny{C000By0Du4h literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-dhcp6-client/crash-6e88fcb6b85c9436bcbe05219aa8e550194645ef b/test/fuzz/fuzz-dhcp6-client/crash-6e88fcb6b85c9436bcbe05219aa8e550194645ef new file mode 100644 index 0000000000000000000000000000000000000000..44883be9f0be6f2ba225812ea93526e8d7523048 GIT binary patch literal 9 QcmZQ_5s-3WVPIeY00gT5xc~qF literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-dhcp6-client/oss-fuzz-10746 b/test/fuzz/fuzz-dhcp6-client/oss-fuzz-10746 new file mode 100644 index 0000000000000000000000000000000000000000..41c0da0db41c8b496c7aa7219559244435cd086b GIT binary patch literal 99 ycmZQqP*7lyWQYb*3jcwS0SJI1Ff98YB!LV-iVy&(T8cpyB=jFB0mSG4C;|YQauoys literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-dhcp6-client/oss-fuzz-11019 b/test/fuzz/fuzz-dhcp6-client/oss-fuzz-11019 new file mode 100644 index 0000000000000000000000000000000000000000..542b08521c4c9982b0c1276f269ba35403b0787f GIT binary patch literal 61198 zcmeIu%MCz45CG7zh!!NG0gbz=NDEppyBzf3O)~%6oBD{Dqm-;yjv3vPTU#O@HR>_q zJX(9p5c@K&-;0?50RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U WAV7cs0RjXF5FkK+009Dj5x4=>gagw6 literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-dns-packet/crash-497be373856c321a8a7b06589df9b2ff2e0d866a b/test/fuzz/fuzz-dns-packet/crash-497be373856c321a8a7b06589df9b2ff2e0d866a new file mode 100644 index 0000000000000000000000000000000000000000..8d24e57dfe77802d5456b6b6c07a72bffda530fc GIT binary patch literal 34 acmWGzfC4532t)h6@phx literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-dns-packet/oss-fuzz-13422 b/test/fuzz/fuzz-dns-packet/oss-fuzz-13422 new file mode 100644 index 0000000000000000000000000000000000000000..439aec54e39683d952a81c3adcaccb633c2469df GIT binary patch literal 36510 zcmeI5TaO&Y6~|{C8!Y0NNT4VJM@C7IAkgZrzK$g#*6ZD;C=wDcQKTrdb4e`L*usX8 zmnb~)kgpKsi$wVQlUT4KW)yLhbFY5Q251MRAn$-&Hx9iuhE?2Sn;jYge99ILbvGO^w`H8^S zu$`w}mr%p)z?IJMXa2QW_|KZBjfW5_8(^KsHI5MS!#5w?U$`50Ke~CGjI+Yc_A7Ve zjmgQ$8fx{_to=vL(>LWID2OX0JbZWf;0Xxg4ztuCUs2YUBCwv!TKPqC_B(5?FOtY# zcCM#bb^1_ROZg5@Us136*0A|`V}8%oh9_UA4S!)1-}8Qcc{xGXq-}Wh9r(Tmxc~{+ zfg;~Lq|RNe*DP8+?LfwJ0r}24DCph^6o!1F5&P2z31_d^tt5B1w+paDr;EOHuD&S! zI(<pUyDap!(^Gmnxgk1~FeI@9Wd zD*+rw)98@mX)R7G&! zapcBP<$&&oBTscjax^dFtV-hBz2gCwPZrr?d^}$q2j~pk^v;8+t7iE$$>*W*X1C%+ z<%%j9$HyVK`Q6ET(>wPk5AWQ2F9i4gy$AF6-o5u>S)|i0-1V1M@-n&U4vOsfR(vbT zrne76fMtAp79GYjH=mHo2S(g4<9t5J5B8IBH7x^x)5*ih$)6rPj1Jwx5 z%EHJLnIM_k;&s7zOmAZiVRA&Ggq-22wZJ0E0Qc;68*A1F#u!jb6{;u)ojloM;X5O` zXsqee$dDccEJYR5s4`RmKt>bN24_&K1Sywi3z7$60GR}K7h&=sji8d@J>qR*rn==) z%v@YZUB`&HF(QCVE@lQG(v4ChY=$bh1oGgZ;dPjfPO1tIS!dX!0Eo&sOk@#OS4OJm4mL8(84NQP7lp_Sg2NcZ3|QZzx8xD)l*s0p_7St3LTzG`)WDhu0lZmg z8YVcJ4_t`^#bNTKkQx;ff5KDCE+dUhAMk~8A893-NEkQ`n?00D`Y&X{>Y7Cr!kudY z;WbKhs5f(o&JQoUG$^>Af!UjMZ4cf8;VPvo*;)>Kdtge8t zMizjI1tlCkEtgtjAR`aQI#Gqxn3{P(22<(>{Vi2kDL=ZHhYcxQMhysqi57y$fJgx; zp`)?J0zK6N;ZB%5#1pd1u-p(coNEHJAyOdFlqvw2)-ga*hUF1VV2%)~!t%)SBs_vO z0EM#Dfw&?_N9iE?3i1Zl03s7EH-k9LNd>X-o2$LFjSR0P6w+$Y0XPpEDa3�*X2W zk-_~cgM#IT?U5Oi_9MSxd8{y@GCUAIY;loAMuROTAf_4epta*LXT}f^F7mGoYaxLA zI3*Tg@(^Ll$zbY@D21>mks-y?7+8Zgnx*)7+_$hm*rBkJI3Yv-x83!AUjF(TDydm#G)CgQMHC#iYoytlyde_`!n| zNBoCLS}y!>=Ev8Y{5riAN3(K~-Wt#1%FVhI-+-i`P{esOt7hYJI``1ofILVh`_p4L ziV9)&g_5A&mP|8|;AtISowb)M3^JWOs)W*#3m#%$8|GOn`Rlc7z>#q@YKp3JK< zUBpLTHDwc$BFVkz?&Lu>i|5B4hc+PZPs+5KMsC5lS>m~{22$=pfhjtR9U_wLrF@-| z6Gkel!a=0{xHphWZ%CoN_@Xs?5@U#D|4?&l_9`mS@HpiQ;dNp(lqC|Fk3Ij?o}C;+ zh%=_2jdUPoRt0L0DablpD?Dq|8I#H)R+E@1HX!9Cu!h7Xey-Ra6R$jGnHX4$o)iNW z@W-R_oCjrx!>4O9ya z9uafErkbY~BsF!kBZ2Y;mFhJTRup`pM?P0PQZ9vzib&R&kVms`3$WX`tD?wwvJ3{5 zh~S)%mvIQM6DzMm67n1y>m*N7B0vV~?^1Nu$tsoo5EmO%qP$0RPc6X3hD~NjtPSu) zr(uj#dxcLZvLD2@*C~4po#0Vs&5jteQ$p5aNuBa4P*-SfctfTo3{t_wqEd-?U~ENE zgPSGl3)2a?Eh8f42dcYcMiGbVLl22=&k&<^~INQ#)6vx7S|3`F0=y)I4=iZ~g(xf`s(e!I5#NnC zL}|UEKi<|`FAr9G^_|&8b84VSUDz&ZD?r6=9H)_Y)SCuqoBU?jdOPGzR*?dzzoFAv z=dzwdQW3}^l^U#S6i67FkgC3tDeM zB6m91VMJE!F|fI!FpR=hcubI1HbMQ;h#Bgr28I&T`}N&6H(4R^mqI(kdOJ#Kdeko3j=DmE}YBMF&*L|+{00j_O=+0cxg*bwmmzLwIn0?1~-YQ zmF;3i$HqG4+?g7S=M4FTn6k%E-ogkI0;IBIBTi=PQJJxH*~rS}Hfk?}9vOZUNHSC6 z5ROm<`Ht;IF_;<1up~?5(F|EpLz0D#oI9-Y_u^XI6r{ESm2ZZ5q@BeY9n*pdl5DRI zt-{>YrXsdMLSodHv_^%0pycmsv@ybIqe;XpTecV5kRl}R6-dLO6vsu?!ui!SHd~ zHGr5*Zso<=ny=3zC{GA#hayVhP5$nmx@l3V-cDkjMCwMY2&C+sGAX07r!+#iGrbXe ztLz#}lv!uk($)o9N%FSc*fvI(1R@}9$QX56xfiS~bx5kfL3*kRB?D6HeHaqFk)_%t z8Dk@t@K% z#WpX#ZkjjD$TMyG?M&)m}x$hP-5EYE^-o7%o;FcOMaq*J5F5KA< zwLiW#A?&46rIU(l)c4H~`^daX}aLXfi~`lRuE2KJxf-_;K6Tb)<>y9MU#!Q&v-XbnaPPI(>+wGO z;)}m&ywx!i6#V4g?`yBeI^JH6HwujRyOUpySl>e?+xA*x%1VE`#8jg_D{TMw_?f*& zZ(i2-u1WNE5z%ch+a`WWK1){X`2Hu!U-s^dMox74`K8wCk{|r?k)+^ZJgA(&;{Jy`=7hr&Rs!$YcA;yO@G!+!pbq~(nJSv=v>mah;8z4ppO$V z+Eew8#?3_c#*C zxi9a$LVH9Vj~Y6cZ1aUO_Bw0Bfv2H!$#!3eLhHT+XN~*=5iK!;hC}C)R(8-L4`*R? zYFtO5yhB4Rz~yl*ok;fYy|e-GmYnU;&C;-G=2%bNp+cw7f+l6?ToNP?iQCY*q+h~0 z2s3mp*-jqP+o5xb*B7I)W{_v-TrzYn=^EeGDbe~ID_INSnsK{g=v*>%F7b*3D_I&k zmnfOnd1oEV58u!dBsu2Lxg>0txQQ@yF0t;Qs5YdVPt@*=n`F9AK6Eaz?!I$_Z0KA< zEv?Vauljrpol8_n96Fb5?%B4YN=%ZfTe{plbS~+q5_j@cL>fAmboT$-vZMwIs_$## zDHt=Ps+mF0pP)bK!aD zT!QEJHs)H^X6Rg^h8#oZl74HWzMn(q603X1(79yjToSglL+6sAbIH)Tq&bhZ*$JiR z|HpZH$P>^|Nrj!)V31IUY9|wCQ{|gIY zJI0d2L7cYsg4ISO)5p6bL*Dn@iOTcNC`scaoQA&iT@yII!Wm7VbUI?hjB6tryr)LZ+~wbCQ+P3!{g9xq{nG5-p}{iov23=e<6u>yMtl07j=`c zIZBgex)TkWog^MKFzvLx-wm^x>+Jm7tX4%1w#o%Rl+^_WvNAe>KNpq`{OOnm zFJHhVED9kMR9uXvU}y~{X&^Bi{dO_F!URh15@LIV8wSRu}v(WIZ;DPH#KEeXC zM!rA)>bE-w(V$DK?knzaQwUyi$8hbdB2Yf#fiO;>eJ&gML7WZ;?S3~rc{{zB6lc|9 zWe;KQc!7gGyw*(PQPSxy3lB!027==5(7i1zZ;y@}fhzA8sA7dcbsj*Vo@TQpyt-|E zB|mdlmea@GJVM*U@8FS#u{|{>V2jstAadde{X9Ddo`Fk_t1Q406?^6Or{86DU>PA8 za4vyu=6ry@dY(<70{AlMOF)=#U9qRQmB6!nM*M*;;~bM-ltAc#Nl2!l%HdKkxP->E z=FOZ`EP5F(rJw$hEoJ=`;ic{eFK-2SAy@q8d7yv!b3R`~qFF9Lof2Ef!P*vAMO#Pv z1-fRH|Afe$^k{q3ug{=N23UFG^a6WTi0`rW4C*EHjChTlV%WRK_-)^u&K+wwG)NB$ zHoQ#6KjI563e|)R^4aDi7?jHXu1LpVSc)2p*=RA-4SKVF1Q!L&(GQQ1!8mNSIv8J4 zG$|nHAtZo*>jNQO54mNxJ#2^9IqeIyosIBfaX$$7D?k97^yv_|wGyM1cAT}Ww7-#+ zu9mO#i{(Y9M3Hl6(TSqw(^vY76`hsnJt7Qe7eF(hZS@g;64pKYR|gO#ss?dLT%`ln zFbo8PN)5H3opIC4xgoQVP?;!$In_|nC;iqQd=UA7Ex7S_z#Hgi7@*W(tExJK6*Mcd zBI@81&>v&SUdCcLj+{gn@t!h$bP*8}36fA@Oid(Hgujg^?_nd3{v^eh=tQ_bJic+< zwV)u_2ny_S6x?|9`eq%UO+AEdYuj6&k+-$&*IL_d4?q4lhaVr+zW!Qr(e`xZGmZhb y8EBh)0M@0v>R_qzV_3Vbv!b!+2=o=DHR(4 literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45 b/test/fuzz/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45 new file mode 100644 index 0000000000000000000000000000000000000000..535d49ea7a01a37782964e4edf2b7ddee59a6e3c GIT binary patch literal 2490 zcmeHJO>fjN5asL>KY;@hDiT^xVmr20MoqVA8_`XcB#TrOh~j)updX0sVOxGYymX7y z3#BVvzVd zv9rApN(U5>lw9yYxE{Wy>v=%BuZ=%GwPdv7z9X*<#urxfEtd_esw@f*i+CDULzfrf zbY@9#L7Z?%PCD@6HBEcJFPEk(mwjW)Wn*wsx#T@8PQYqZxoqVX%>7$*4ra^`Q=QNl z_;?x-$gyf3?^@2P{ncd}P7dNEs&J6v~ ze7?9it4}+YALWPXel^46o(w!h)Dz)}NP;^PWRG@#6Fm*2}} z4P+6{w&s8r|KLv-&&y@d^8teZWD9h1?{Yxpc6kOD0Fc991B3%IJHCak1tRs!*Q;=i zcQp9L8I1CHWpi*PgmhR&*S=Z3vv0m2*!5a)g@uijN46>!9$pd>&T8hk<$d?iaR9z`^oo7{T$`v-vZ;ve8{(NO}Sh7S?nzWNkr*4?(Z|Ch@ zZYVPWQphp+kejnlUOnw8{2r} zIE|c+_=ZWn5Q&mp@;GLKNnt#&+Ic3q@~w_GPExK_!Xm@NPHvp1YoE+NO)(nmR@r#e z(5a+WGuiLtJ?Q;y+*?!#{R{j{*rw1^aD21eTzU|Wk>KAVPyz^Ca2)t_i%|7tq>ZJ z2+=eadW%h3SS-i9U&PngKo?)Y?4RO>pa%1_H7BqO1K%1RxCxqlykHhI+w-6CV7QY_ zM)cMb%|mWm!8;yWZW7%}oiHwi4W&uA3Ywj~tR{o;C_Q>LJwI(v+~UpdVR;zK5dYx^ z!!qA5hNHhv522!%C&A{R8l>!oKLN6C&V;*MxXXn_E-XQ(4_a{~S=_*we z*HFdq7O3J&2nWfOIGoE0C&e?5>ocemREFc~T4+9h8cN?||2j z>r+4=MhtibK_ZoMYz?;#>ZBf#8e+2;fA}sOGV>d?3uyS`k-(jJOo_>7~oejrYqj!!kh?g2#bPFkf1yD8 zaTG|dK>_?pH$j2_*dnWTi^O*uNh*M1Wl2$E<~=^tS+ZU48x?3JQ6r{Kj%hd|wfA z)-Yd+Jo)ers;~74mWoxZ0p*l_OS{ApJH*DYPYOsB^_Zo;+<+J~cF|i@-&@EEeKjk3 z2EuE$)}h?dd4P@!HXPus+?~Vj&SA52*iz2SXZ86#Dp;U4b#fgjM6F-TQJ~tm0=ZCi zKwA(M0|#|b=5w@t1oU_!?iu^$J!fE*SDFe>mAAgY6LGU~7R6!X4 literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-journal-remote/oss-fuzz-8658 b/test/fuzz/fuzz-journal-remote/oss-fuzz-8658 new file mode 100644 index 0000000000000000000000000000000000000000..c78d65c569f648165f5c7f2cc9677dc23672f66d GIT binary patch literal 10 OcmY%3QUC%5AOHXa;ex0Fkw8H%pnR~SyDL~8A%o1~ x90j8xFd70QF$7EuObiVSfyl(d*wpX~my2VFqpblPaB;N literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-journal-remote/sample.txt b/test/fuzz/fuzz-journal-remote/sample.txt new file mode 100644 index 00000000..891c0003 --- /dev/null +++ b/test/fuzz/fuzz-journal-remote/sample.txt @@ -0,0 +1,180 @@ +__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12d7;t=4fd05c +__REALTIME_TIMESTAMP=1404101101501873 +__MONOTONIC_TIMESTAMP=1753961140951 +_BOOT_ID=f446871715504074bf7049ef0718fa93 +_TRANSPORT=syslog +PRIORITY=3 +SYSLOG_FACILITY=6 +SYSLOG_IDENTIFIER=/USR/SBIN/CRON +MESSAGE=\x1b\r"\x9a\xea]\x90rU\xb0SX5\nY\xebi\xdac\x1f\xde\xb4\xf6\x0e\x8d/!\xd0\x9a\xe8\x8b\xc3#hN\xf4\x9c\x8e\xc5\x92>\xaa\xf8Ih\x13\xd2\xbbOa\xedK\x04\xa449\xf3f\x9e\xfc=\xc9\xc1\x0fe\xb4\xf96\xd5z\xcfQ\xcb\xb1\xb4\xe48\xb3\x9f\x1b +_UID=0 +_GID=0 +_MACHINE_ID=69121ca41d12c1b69a7960174c27b618 +_HOSTNAME=hostname +SYSLOG_PID=25721 +_PID=25721 +_SOURCE_REALTIME_TIMESTAMP=1404101101483516 +DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000000 + +__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12d8;t=4fd05c +__REALTIME_TIMESTAMP=1404101101501874 +__MONOTONIC_TIMESTAMP=1753961140952 +_BOOT_ID=f446871715504074bf7049ef0718fa93 +_TRANSPORT=syslog +PRIORITY=3 +SYSLOG_FACILITY=6 +SYSLOG_IDENTIFIER=/USR/SBIN/CRON +MESSAGE=l\x1a\xf4^\xb1\x14\xfb@\r\xa1\x11\xda0\xe0]3Ms$\x7f06\xde\xd9\x02y\xf9@\n\xe8\x01\x83\xcb\xe0)\xed\x98*>\xa1\xc2Y\xe8IR\x95h\xa1\xbb\x16\xba\xedK\x11\xfcj\x04\xfb\x0b\x9b)p\x10\xecH\x1f\x0b\x89{\xeb'\x0e\x1d\xaa\xcbZ\x86\xe0k1 +_UID=0 +_GID=0 +_MACHINE_ID=69121ca41d12c1b69a7960174c27b618 +_HOSTNAME=hostname +SYSLOG_PID=25721 +_PID=25721 +_SOURCE_REALTIME_TIMESTAMP=1404101101483517 +DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000001 + +__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12d9;t=4fd05c +__REALTIME_TIMESTAMP=1404101101501875 +__MONOTONIC_TIMESTAMP=1753961140953 +_BOOT_ID=f446871715504074bf7049ef0718fa93 +_TRANSPORT=syslog +PRIORITY=3 +SYSLOG_FACILITY=6 +SYSLOG_IDENTIFIER=/USR/SBIN/CRON +MESSAGE=MzV_\xbb\xc1\x14f\x84\x15\xf5\xe0\xe6\xd2\x0e6#N\xf1\x1b\xe9Z*\x8f\x8a\x13\xad\xa4%r\x02\xd1\xc4^U\xc0u!\xdfjl\x15\xb6\xcc\x93\x1dRi<\x1a\xa9/\x9c\xcb\xe8\x99\xe3\x1cN\x06\xf0\xb41a\xa7L\x99\xda\x83Q: ]\x1c\xb9Hiz\n\x94 +_UID=0 +_GID=0 +_MACHINE_ID=69121ca41d12c1b69a7960174c27b618 +_HOSTNAME=hostname +SYSLOG_PID=25721 +_PID=25721 +_SOURCE_REALTIME_TIMESTAMP=1404101101483518 +DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000002 + +__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12da;t=4fd05c +__REALTIME_TIMESTAMP=1404101101501876 +__MONOTONIC_TIMESTAMP=1753961140954 +_BOOT_ID=f446871715504074bf7049ef0718fa93 +_TRANSPORT=syslog +PRIORITY=3 +SYSLOG_FACILITY=6 +SYSLOG_IDENTIFIER=/USR/SBIN/CRON +MESSAGE=\x8aF\xfcG\xd7\xeeZ\x86\xcb.O\xb1!,2\xbf\x86\\&\x15\xa7\xe6\xe7-\x81\xed\xf8\x7f=\xf7\x90YF\xe1\xe6\x99\x83\x84\r\xe48\x93\xc7\xdd\tJy\x86\\\xb4\xf9\xefT\r\x04\xae\x1d\x99\xfe'\x99m\xc4#\x8d\x89w\xb1\xecC\xaf\xe6\x1b\xfd\xc5\xbc\xfd\xe3w2 +_UID=0 +_GID=0 +_MACHINE_ID=69121ca41d12c1b69a7960174c27b618 +_HOSTNAME=hostname +SYSLOG_PID=25721 +_PID=25721 +_SOURCE_REALTIME_TIMESTAMP=1404101101483519 +DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000003 + +__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12db;t=4fd05c +__REALTIME_TIMESTAMP=1404101101501877 +__MONOTONIC_TIMESTAMP=1753961140955 +_BOOT_ID=f446871715504074bf7049ef0718fa93 +_TRANSPORT=syslog +PRIORITY=3 +SYSLOG_FACILITY=6 +SYSLOG_IDENTIFIER=/USR/SBIN/CRON +MESSAGE=`\xc7\r\xb6\xc3NPjc\xa129L\xe1\x17\xa2\x96\xa8w\x0c\x07\x8f\x98\x1eS-N\xb7lt\xc5=\xd1\x93\x10_1\xdc\xa9x\xd1\x8a\n\xb1\x90\xdca\xc4\x94\x98\x92\x00\x90)d{\x96\x9e\xc2A\xbf\x81s\xf82_\xe0;\xc3\x06\x8eO\xe4\x8a5GX\xe1\xff\xea +_UID=0 +_GID=0 +_MACHINE_ID=69121ca41d12c1b69a7960174c27b618 +_HOSTNAME=hostname +SYSLOG_PID=25721 +_PID=25721 +_SOURCE_REALTIME_TIMESTAMP=1404101101483520 +DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000004 + +__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12dc;t=4fd05c +__REALTIME_TIMESTAMP=1404101101501878 +__MONOTONIC_TIMESTAMP=1753961140956 +_BOOT_ID=f446871715504074bf7049ef0718fa93 +_TRANSPORT=syslog +PRIORITY=3 +SYSLOG_FACILITY=6 +SYSLOG_IDENTIFIER=/USR/SBIN/CRON +MESSAGE=\r\t \xdf-\xed\xd5\xde\xa1/\xa5T\x1a\xdd\xf9a\xe2\x8b()\xd5\xf2\x1b\xbcu~\xaa\x97\xc7~\x0e~2\x11\xa0\xb5\xd3\xd7^ \xea\x16\x02{\xd1\xbe\xa02\xad\x00\xba$\xf2\xd5\x7f\x9a\xf0\xf9\xf2\x14\xf0/\xb5\xd3"`\xd8\x8e\xb6w\x1bP\x96\xf1\x0c\xf0#\xd2\x12\x88 +_UID=0 +_GID=0 +_MACHINE_ID=69121ca41d12c1b69a7960174c27b618 +_HOSTNAME=hostname +SYSLOG_PID=25721 +_PID=25721 +_SOURCE_REALTIME_TIMESTAMP=1404101101483521 +DATA=00000000000000000000000000000000000000000000000000000000000000000000000000000005 + +__CURSOR=s=6863c726210b4560b7048889d8ada5c5;i=3e931;b=f446871715504074bf7049ef0718fa93;m=198603b12dd;t=4fd05c +__REALTIME_TIMESTAMP=1404101101501879 +__MONOTONIC_TIMESTAMP=1753961140957 +_BOOT_ID=f446871715504074bf7049ef0718fa93 +_TRANSPORT=syslog +PRIORITY=3 +SYSLOG_FACILITY=6 +SYSLOG_IDENTIFIER=/USR/SBIN/CRON +MESSAGE=\x1a\x15\xd3\x8d\x98\x83m\xe2\x02\xfa\x81\x98\xef\xa2\x8a\xcc\x10\xc5=q=\xd0\xd7_\x0e\x92D\xb1\xc7 \xaa\xae-\x18\xff\xb0jX0aSiiycD2<{NiEaQE6vG)izFLb8I!M@KGyCofm$koW*k7h3}^0B8*cRR910 literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-journald-stream/basic b/test/fuzz/fuzz-journald-stream/basic new file mode 100644 index 00000000..a088f1a5 --- /dev/null +++ b/test/fuzz/fuzz-journald-stream/basic @@ -0,0 +1,8 @@ + + +6 +1 +0 +0 +0 +hey \ No newline at end of file diff --git a/test/fuzz/fuzz-journald-syslog/github-9795 b/test/fuzz/fuzz-journald-syslog/github-9795 new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/test/fuzz/fuzz-journald-syslog/github-9795 @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/fuzz/fuzz-journald-syslog/github-9820 b/test/fuzz/fuzz-journald-syslog/github-9820 new file mode 100644 index 00000000..55e1bb59 --- /dev/null +++ b/test/fuzz/fuzz-journald-syslog/github-9820 @@ -0,0 +1 @@ +<13>Aug 4 04:08:03 something-is-about-to-go-wrong: \ No newline at end of file diff --git a/test/fuzz/fuzz-journald-syslog/github-9827 b/test/fuzz/fuzz-journald-syslog/github-9827 new file mode 100644 index 00000000..6787e487 --- /dev/null +++ b/test/fuzz/fuzz-journald-syslog/github-9827 @@ -0,0 +1 @@ +<> \ No newline at end of file diff --git a/test/fuzz/fuzz-journald-syslog/github-9829 b/test/fuzz/fuzz-journald-syslog/github-9829 new file mode 100644 index 00000000..22ded55a --- /dev/null +++ b/test/fuzz/fuzz-journald-syslog/github-9829 @@ -0,0 +1 @@ +: \ No newline at end of file diff --git a/test/fuzz/fuzz-json/crash-5639441482252288 b/test/fuzz/fuzz-json/crash-5639441482252288 new file mode 100644 index 00000000..c6cf59a5 --- /dev/null +++ b/test/fuzz/fuzz-json/crash-5639441482252288 @@ -0,0 +1,9 @@ +[[],[],[ ],[[],[[],[[ ],[[],[],[],[[],[],[[ ],[],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]],[],[[],[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ + + + + + +[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],0]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] + +]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] diff --git a/test/fuzz/fuzz-json/oss-fuzz-10908 b/test/fuzz/fuzz-json/oss-fuzz-10908 new file mode 100644 index 00000000..5aee8e7c --- /dev/null +++ b/test/fuzz/fuzz-json/oss-fuzz-10908 @@ -0,0 +1,9 @@ +[[],[],[ ],[[],[[],[[ ],[[],[],[],[[],[],[[ ],[],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]],[],[[],[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ + + + + + +[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]],[],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]],[],""]]]],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[],[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],0]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] + +]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] \ No newline at end of file diff --git a/test/fuzz/fuzz-link-parser/99-default.link b/test/fuzz/fuzz-link-parser/99-default.link new file mode 100644 index 00000000..92fcbe83 --- /dev/null +++ b/test/fuzz/fuzz-link-parser/99-default.link @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Link] +NamePolicy=keep kernel database onboard slot path +MACAddressPolicy=persistent diff --git a/test/fuzz/fuzz-link-parser/advertise-segv.link b/test/fuzz/fuzz-link-parser/advertise-segv.link new file mode 100644 index 00000000..305e846a --- /dev/null +++ b/test/fuzz/fuzz-link-parser/advertise-segv.link @@ -0,0 +1,2 @@ +[Link] +Advertise=hoge foo diff --git a/test/fuzz/fuzz-link-parser/condition-memleak.link b/test/fuzz/fuzz-link-parser/condition-memleak.link new file mode 100644 index 00000000..523e4ba6 --- /dev/null +++ b/test/fuzz/fuzz-link-parser/condition-memleak.link @@ -0,0 +1,7 @@ +[Match] +OriginalName=eth0 +Host=hogehoge +Virtualization=qemu +KernelCommandLine=aaa +KernelVersion=4.20.3 +Architecture=x86-64 diff --git a/test/fuzz/fuzz-link-parser/directives.link b/test/fuzz/fuzz-link-parser/directives.link new file mode 100644 index 00000000..e7d0737a --- /dev/null +++ b/test/fuzz/fuzz-link-parser/directives.link @@ -0,0 +1,38 @@ +[Match] +MACAddress= +OriginalName= +Path= +Driver= +Type= +Property= +Host= +Virtualization= +KernelCommandLine= +KernelVersion= +Architecture= +[Link] +Description= +MACAddressPolicy= +MACAddress= +NamePolicy= +Name= +Alias= +MTUBytes= +BitsPerSecond= +Duplex= +AutoNegotiation= +WakeOnLan= +Port= +GenericSegmentationOffload= +TCPSegmentationOffload= +TCP6SegmentationOffload= +UDPSegmentationOffload= +GenericReceiveOffload= +LargeReceiveOffload= +RxChannels= +TxChannels= +OtherChannels= +CombinedChannels= +Advertise= +RxBufferSize= +TxBufferSize= diff --git a/test/fuzz/fuzz-link-parser/oss-fuzz-13878 b/test/fuzz/fuzz-link-parser/oss-fuzz-13878 new file mode 100644 index 00000000..dbb2abec --- /dev/null +++ b/test/fuzz/fuzz-link-parser/oss-fuzz-13878 @@ -0,0 +1,4 @@ +[Match] +KernelVersion=t +Virtualization=q +KernelVersion= \ No newline at end of file diff --git a/test/fuzz/fuzz-link-parser/oss-fuzz-13882 b/test/fuzz/fuzz-link-parser/oss-fuzz-13882 new file mode 100644 index 0000000000000000000000000000000000000000..7c56ec222d8ad80b37986f731e523f530e62f062 GIT binary patch literal 2015 zcmeHI&2Q5%6wkONyC6=8lMB)iXnSh2B%OtVl$lSBjvWddS|r@oU85AIvLmF4f1dZ8 zrle3nLpyNbskNQ>z2~2Q?;~EW3pmXydl7q1_CAcAc;4-?=h1IGroR(5T;%rA{FdiE z@J0h!O&1@7K_)W!SyhWPcxLi1%9u15UaeFbyee&#TAK!MO@5hcxjaX`G`Ntcd*{&P zTG>@q<)xlaN@-@yF3XCo%!o9Q{5{&&M@Y$IA@d_L zBBGK6pUBqH)^9>|ri@n0_sUo#J5BH2^G`@4hPYE}h9GX@JP@%@{|qv^3*v#qj|3pD z1g?1|<>gDIl{%M)g@TN(+{z-#q)Tm=im|N8E_dw^`s=$rHOde@0#7C=Vk8nDK>>G) zHBBKjR5-w>y|HkNj!;=-zDTlT0H2(XIC{i|d#G6ig8*}({m7=`b^o9SQca0ravMU1 z(+L`{ePWn#jbnuIqL82BMm_rnAwHwu9!|abC=l1EsU@3Xt`sihY^$jBS7s*CDppd# zJ#iIBiQx>sZ|tl@vekQy-2ZziohLlBL5N_ti(WU~fRL`i{u)!ulWQPb{i8XH7@3q8 z!I5p43CIHm(klJ<>nqIiZ`7>OnUSNOw n-^iNk{g)dVHg1wk;-}>XWUCh1NkvuN?|Vrg8GC`BP!8}7-`O(3 literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-lldp/basic b/test/fuzz/fuzz-lldp/basic new file mode 100644 index 0000000000000000000000000000000000000000..43debea6e4c64f967d811d911421f2466cbce33c GIT binary patch literal 52 zcmZQJFDl_;4vq}wVM)u+XJB9e E0Kr8E{Qv*} literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-lldp/incomplete b/test/fuzz/fuzz-lldp/incomplete new file mode 100644 index 0000000000000000000000000000000000000000..53dce6001b312e193abd190b7e11aec62b9b90a7 GIT binary patch literal 31 jcmZQmz;z~)!h$ITAt+jeLkR{EMDA3$Qfn7(Tqvazq`5-28UjXA z3-%u&uuEgWhyfLbI~fpQ;9x*Nny?8XrZ59SoV+)?GjH~G_qaSuv}k=6(Cypd?GNqE zciwy7_vX!|OP4PBOI|h+25o2f>fH4P-(v2(i+lLf|BrvFC+N9vPjk;Ntle^c3w^b2 z>^Utp5AW3Jlqk&KwmO!-3RtS|Xp09OZqhhM4;l^neARjF_UhTw zXY0K5mtJAODd`>cUgXSw=(%f8bI0ZN=jz&C#{SfLJ&o6>2aN{(dT2QPcWs^5x>c)T zz$vHSw{_Li8hY;9)7){juD+yg^e1^)jn}9LjRt+2q2cu3wRN7JyLcOL%IWuAe2b31 z_T06nx$6Qw9g6-WFRSqy^`Oz9Z!pzKd_s@z{aqBK6ANYwN~#u zKDCTe&-`}bfGUpYS^oSiq=V|KUN-_I)9gH|^kJ}NAFlIlGV>QwdsXMgks@9ETw z$>aC@4`TNizSo=eTfWD@ugxZ(&&CI3;kMl4-Ys0^j(l!( zUoUU1uRR@K*GvCKF1_LXhTDF$6}}Z7w{Y>PFMGc`zlEof%j}HYj&tK5R-IdW^6q>4 zD<|^Uh5U1F)fJ~~3ZRwShuX^=#6bTNv`+pVLb6}I=|E>c1}LMo32+c;~ROv zlTV-c>OV7{ZNE8*e{xrS`0~`l*N@ljt@4sWgqTa7TzChZeA;k z@_UiOVf9Y#b!{VeZ!de`>WTH&93O|vO=j!5e|S^h@Y<^<^6K@kYqH5}Tw5zXxpm9A zkIQP?bEW+B-ap+h@9TCf+el9Mz!mw;^`_x6OW&lvU$t}FZsKNp&fi|~het>k7SzkF-#d>Jm}T;3n&WEcWKE!0@U zfY7(SNk$`kah(#QQ9cMInbF8F#AwusoVpPJCD7yo00KaQ5FAPzN=XaAq12Z^W^R>2 zMPea|g%?<%^V}Oy~oW+9!8qfVc<~-00AHX)B_%E20+?9m|P|AK)QlV^9pmm z)F5Aa-V>9navg*QLIddtg9+E8h0s9SJlbTW;>Ut7UBcf(zHFOMgjJn&#EgwW!;Yi_Xld8Yw+H);y3=l{F7qPy#?YzLM82 z??Ac&GpmyAMIe|A_Ai8D#4CyA>I*_BLMSGq zmP#{`9)S;m4{4DhxvdAG7@^X=2S5M_0J$CK#y_me0`5=VeQ$r|L})Z!EFD5o-vNZ8 z8D8E)C_*SgC>o)7{Lgjwm*2@~dFP!y_lmDdx|Ld%&HLHzZV*m>@!PWWEB`w5M@L6D zj{MWVxv#?b>UD6Ly0Ih<{rx|Mf8`(V6z_cf-@<+Wr9}DCR_r;y@~3d}k)Hh3m12Cb zxm^}loIlvSRu;Y(zx|`P)U98YF)tjrr>Sjs_YXl%9AdI7H#%1sEzADjT>K4NS3%r;rR3uc8P50U!XB^hp$8sH9Vn@@7h-mXd*# zOmPE`N@$=OK>!Eh<$p8od30x?8K+yxWnRJ+N7utj)KoP?dwkJT*5ugZzUsat-#mnBCCaxt&$?BcV^O50LCvjrY zhF;Y8z@jxA0U!X>0LPF600e-RatWte+wez~6~HCT0ZLe`b_#I`rCU&VszvO>>ci^e z1LZ2CmNDTl;g&MtVD&2m0U!Xh6o7uFJ`k+FvH4Mg)o-!-GM%5r1s(@Kh4o`uKX&QV z2rG*r(ty%349{^;wmrjhYj~!r00eW+7CkE_N z$Kc1{$87CQL&iV}00AHX1c1ckOj!&p5Rxk6ia>E(V*v+HfCKf8eGLtS20{a&fzUv? z*2!fw5E@9(L3wt{vkOUn_6hEWo?%g3v&{xdm~fbIm~fbIm~gq-mdluMri3671Sh>4 zEL@J8Bm*D-B$&Ym!Uw_!O0gQ2sM5qamZ)NhDq|{0CMB7aWYS*$BI%Clm~~icr1b14 z_aUPy+1M>8B^Mn4^&kfgga&HC#u@;Sb`Qrg5*jjbUW#{9u`M_-1X2m45=bSGDylN+ zNV2h05J&{#K*WIr9mIi%1BnIw{Bz-`XkwL2qC`cLRz(x@Z8OacJp?_3cWaS3yj#3m zyj#3myxZKP&1Jk>yj#3mT`kI8m9T(tU{iNvay^I0Vi^DdAOHk_mR$?j&?6EPRdQNm zUM4`%sfu1|4P?H)NF?Ht2Bm2(7rm-0A%IBy+nx{rApr5xw!{e78Mz%ty85P-VQ=aAsmW2p5vW5Qv= zVZvd;VZwFVZ_@a@LI5m^U1=pW5E=*#WEzM7g#{*}M1Z0rKoN#dU3#?IE_-hSNiAvW z2(13@Zj;Whk648-cAe%Pg={ziK-HiEfSMRtcm#j|5EiXjve6kO+_nu=_+Wi`8%2d(SKUjHQR7LQx%TZeA;k zr7S%F1b_e#0Fu1k*QLUVlsB2I6z)rprDqmil(6(#mR??fAx)m4#w0Z+sWDmE75WJc zYZeA95-gG-W1s|p01)1-8Rr9GV_yS600;m9AW~7T1o?vic%pA00E$-0Q57B@DZShVF}w4py&utgyEA3rkmSkaRrNZ z#UCCWh1Y;Z8-sT#aL2N)xqCS05(1#vp7XZ>P=t-`0Z@*cBm*E@x`TB)3@&X60431m z0ssO)0u~k)XX!O@S)TvG;sd#S`x>Mqq~ubhB&ASHaiks`k*pFZ(*pPhl; zb4IWE?E@v;d-GB7PVi0!!p6P^fB?`^{MgSlY0r=`Py#>z2mmp0Nur>YvFxT}ved{C z2zdcefKY&t2#^SQK3T0L-k*+B6(YCg9`|nH+&d)MD81pX`as!D-HplhT*oYy$x$BkO+_nkO+_nqNE@ZI&C>jI7~Q9I7~Q9I6*NdABB;bMjGqa_g3JAJ>2(4}m-c@(}QVlsbqTc?iYbvZhg*$KYHm(6WNeEIZCfDFFh8L($e5vBnX0vUN{Isv zxiLS1^lA&xk-<@ip$R|}fNm2TS#&Cu*fsE|1b_gLrnrz^-Gv@$OWYs;s*%#OLj$3K zx-bNQbbKX;P~L%b1*uxkdRdhTMh+o4gyayCLzo+x#DRzd5eKSP01Cz=%l(Wgbxo=3 zfCb_}l-Wtjfg%T$7gc>iV?$#r%L0wvMZx7B1~hgLe+_^DP!D*t85&!=2Q;?418D5r z^n%8It~9o-h8zYb_z?II@?tAJ4Ics@0v|H@e5ONUu98XXOFkZ1NzyR}t%?Gnm_rCc z5k5ryT?oa>)@psihiLbJ50Q5OAChYh_>kwyhp=))|H5`JqzOk^3@e8bCCXy7%3@S& zp9FV4ehjF&k`KItWJYI3XOgZ-x)y&Xc`zhhlXRVUTOO#7*k(z7E^Oh#4m#9BB4KsvsX<|6Mvx&qa!lI=wxl|U+iR064@F_VrYkP3|* zsB2a+VHFcrF{#EyW@}bXRjnnUv6X><#)igDt`v(fL{bhG?n1M0r25AMf7_Gl-%9n* zN!H{$5}=5KVE3M(@j?%crtAkw@T>5v@T>5v@T)nen#-gKlO`EPQ7SxUuv^gsy`0TKZc!AJxG6c(6> z5&?>i07V#IRR>htW$$eusU=;OZA-!zJ0rK_-1vu8=hmLQ``-S_i71{zwGUa-@($z; zku@Frkw+mLjsQ?KsNCz?M(*C8#zp~9!cGtX5CFoWHH)^1jsZsi2mk>f07P6lk0s|a zab@Dl#FbybRp(*#EBg);4igR&&P+I1{mA9p9#+4_>T7xo@nGl6Kr1>YHcsEhtc>uE zR$cd83~PN^5-O(avdAO=B7S3**DmoJ;x_{b=jK=NT?|102mm$FG2jRQ0U(@zbN&ZF zruh{B1b_gL0SNZYShFa>p0(IB*5`cun4*3Z^{c4SrFmovt&7C!Xnh2($XaX zAOO@tk2C-v^2C^?Y!+9N2r?36B*$-nqO5utQDb34E&57mmVTgt)@k`82watX6%q++( F004n>6w&|y literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-netdev-parser/oss-fuzz-11280 b/test/fuzz/fuzz-netdev-parser/oss-fuzz-11280 new file mode 100644 index 0000000000000000000000000000000000000000..33d24990b74651f3c65b73553263950f73fb8cf1 GIT binary patch literal 76 zcma#{OD%CpEsN#y&df`(Ez3#F6?003kw B6cGRb literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-netdev-parser/oss-fuzz-11296 b/test/fuzz/fuzz-netdev-parser/oss-fuzz-11296 new file mode 100644 index 0000000000000000000000000000000000000000..05d57f702bea7a1c8b4092449e63309556737151 GIT binary patch literal 318 zcma#{OD%CpEsNz+fCKN$ycFB=%%arv(!`<^1+HkgOe~y*!a&lCB2GRhI;1o&FEt0` os$?9dFhpaz9EVbnuwP~ShDrJ*=BC;vF@V)10VM(SF%lL4 literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-netdev-parser/oss-fuzz-11324 b/test/fuzz/fuzz-netdev-parser/oss-fuzz-11324 new file mode 100644 index 0000000000000000000000000000000000000000..dea1dcf6e403a79b24a6befe357ef2f01fdda279 GIT binary patch literal 79 zcma#{OD%CpEsN#yOUzBRE#mUd%uBJ&EHFziN-aq&;EE0@&C5&8iRJRlOGzzA1rm8B awj~VFFkQZm&W@5=!zteA~2W3j0Ypo>g>1Yoc+$()zOO=@B#z?0YCr{00aO5KmZT`1ONd* z01yBK0D-+jfQJ_#00;mA+k$|&ErNoafWU4e(Ae$nLGShf0fD?kol9Qpec=#MBw51f zg1(dCiF|j*OF~nW2=2*}Dh~-lo$@J}a2#SVuV(D?1nZnOQB;vO@$xNgt)}$8h#Ki> zV})QY<9~g>59mT40Rcb&5C8-K0YCr{00j0D0f-d$a@e8MfB+x>2mk_r03ZMe00Mvj zAOHwNAOMkK1UT>&AOHve0)PM@00;mAfB+x>2mk_mi2y{3dpYbWb-MGZ^WQ)JUU76w z=O*Gq6pYW-RuT58wnd+iU2BLZHH?hj zsoFcqkf*d*9(UVV5-OFBA0WqFa;T+<6J8^FSL*fip%jYxS7Btz8vkgFf~SomszV*#4 ziD=VIwVErw$saj`gR5C4moGX8D0N|~-9Gbz{w(0D*ZNn!6X@?>u`F8-JcH==+7}9J zwS?VQw~x(zV^~8>xk`q}IgFK4V>J4a?~)2=gHXSgiv~ z7LOrvIFJzCaEqh4 zQm{C0BHj)aeYx{pN_{4a=|NNWPgCd`75L^|@y*Z7jMp>6l|hm`tyR_3*-+$s9VhaG z?2Dc_bH@@kl}ai5(rG`|K3Q8`IQJeV%~RU4Kfvf*k;fy9Zd9URWUpBmdl%7V?W86M z3Q<*zEs|eE*qsAX-5GyGjGAkBT$=9$-K?IB>NB&1Z+m~ z0BVi8+nGj=%F@ZexfBkJUHrWkK+<=Gq{B`Y%hlKujK>kh;lEF&6LEwDlD=w^zOl3T z(i12wk-`$GxiGe*XPNV%Yar<>4YW7bhApJs#MsU-FcK|B4TwrU2NVA8PUK*F@zKG z!-=SjsC92QyaNJ&03ZMe00JvPK*|xVms1~T(c3#Ar`LOv6<6^$`a#Gtr=$Dpa#mP@ z08TAW4KG)vQq*MS1L6q&0!NvP8=Pciz)C4qeIu!DWWc7I*D05O;Y`*bZ%=>&y*~{EYm(KGfq(Fyna=0 z*E!S>aIu1}Z|`J{I^RMe``uBQMIS#lG3(p|#b4pc5A+r&p{59Ag0m{4y6;+I^I0Za zF-pOQIH|OBHSXjTUsqRXXsZ|AQ=~hEIVLw0y9>C}Z})@2v78m0Lgch0cDgKLk)eg? zoKZnNbZ+kC#;TGVnpDc@rCxT>_41M|aWomy!iBR(8JM5wgx_ejn>G5Z1%tXYiw4gz z<}zBqJ%|u3>Ix7d>t0Rskrh6k;~|)9<0meq*qDE3)!nx;SXdL!^F1FSkz3lR`2&br z_+uV6!0Dz$)Iw&ntz=M?KbYBp?U6oh3S}X1+TY|@B}D0F6zZtJ6p!cA8=Fg^%`n)sDV63;#ibHXShDWK-o}tu z5Cjka1OS0Z1jw3lB|zKt#|^G@g<<;=pHITtXAgk2Rzg(`-HcAjkbh{?<>0&;X)Wve PvMEXgEAqRn_k#Zejr1uw literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-netdev-parser/oss-fuzz-14157 b/test/fuzz/fuzz-netdev-parser/oss-fuzz-14157 new file mode 100644 index 00000000..d3a65e1f --- /dev/null +++ b/test/fuzz/fuzz-netdev-parser/oss-fuzz-14157 @@ -0,0 +1,5 @@ +[NetDev] +Name=w +Kind=wireguard +[WireGuardPeer] +PublicKey=e \ No newline at end of file diff --git a/test/fuzz/fuzz-netdev-parser/oss-fuzz-14158 b/test/fuzz/fuzz-netdev-parser/oss-fuzz-14158 new file mode 100644 index 00000000..6f6bf723 --- /dev/null +++ b/test/fuzz/fuzz-netdev-parser/oss-fuzz-14158 @@ -0,0 +1,5 @@ +[NetDev] +Name=w +Kind=wireguard +[WireGuard] +PrivateKey=E \ No newline at end of file diff --git a/test/fuzz/fuzz-network-parser/21-vlan.network b/test/fuzz/fuzz-network-parser/21-vlan.network new file mode 100644 index 00000000..a4fa1dec --- /dev/null +++ b/test/fuzz/fuzz-network-parser/21-vlan.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +VLAN=vlan99 diff --git a/test/fuzz/fuzz-network-parser/23-active-slave.network b/test/fuzz/fuzz-network-parser/23-active-slave.network new file mode 100644 index 00000000..59a65960 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/23-active-slave.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +Bond=bond199 +ActiveSlave=true diff --git a/test/fuzz/fuzz-network-parser/23-bond199.network b/test/fuzz/fuzz-network-parser/23-bond199.network new file mode 100644 index 00000000..31e5d12f --- /dev/null +++ b/test/fuzz/fuzz-network-parser/23-bond199.network @@ -0,0 +1,2 @@ +[Match] +Name=bond199 diff --git a/test/fuzz/fuzz-network-parser/23-emit-lldp.network b/test/fuzz/fuzz-network-parser/23-emit-lldp.network new file mode 100644 index 00000000..de350453 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/23-emit-lldp.network @@ -0,0 +1,5 @@ +[Match] +Name=veth-peer + +[Network] +EmitLLDP=yes diff --git a/test/fuzz/fuzz-network-parser/23-primary-slave.network b/test/fuzz/fuzz-network-parser/23-primary-slave.network new file mode 100644 index 00000000..380ae267 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/23-primary-slave.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +Bond=bond199 +PrimarySlave=true diff --git a/test/fuzz/fuzz-network-parser/23-test1-bond199.network b/test/fuzz/fuzz-network-parser/23-test1-bond199.network new file mode 100644 index 00000000..6e7c28df --- /dev/null +++ b/test/fuzz/fuzz-network-parser/23-test1-bond199.network @@ -0,0 +1,6 @@ +[Match] +Name=test1 + +[Network] +Bond=bond199 +PrimarySlave=true diff --git a/test/fuzz/fuzz-network-parser/24-lldp.network b/test/fuzz/fuzz-network-parser/24-lldp.network new file mode 100644 index 00000000..fbdfb1b6 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/24-lldp.network @@ -0,0 +1,5 @@ +[Match] +Name=veth99 + +[Network] +LLDP=yes diff --git a/test/fuzz/fuzz-network-parser/24-search-domain.network b/test/fuzz/fuzz-network-parser/24-search-domain.network new file mode 100644 index 00000000..970b130a --- /dev/null +++ b/test/fuzz/fuzz-network-parser/24-search-domain.network @@ -0,0 +1,7 @@ +[Match] +Name=dummy98 + +[Network] +Address=192.168.42.100 +DNS=192.168.42.1 +Domains= one two three four five six seven eight nine ten diff --git a/test/fuzz/fuzz-network-parser/25-address-link-section.network b/test/fuzz/fuzz-network-parser/25-address-link-section.network new file mode 100644 index 00000000..759e83c3 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-address-link-section.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Link] +MACAddress=00:01:02:aa:bb:cc diff --git a/test/fuzz/fuzz-network-parser/25-address-section-miscellaneous.network b/test/fuzz/fuzz-network-parser/25-address-section-miscellaneous.network new file mode 100644 index 00000000..3a37d036 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-address-section-miscellaneous.network @@ -0,0 +1,10 @@ +[Match] +Name=dummy98 + +[Address] +Address=10.2.3.4/16 +PreferredLifetime=0 +Scope=link + +[Address] +Address=2001:0db8:0:f101::1/64 diff --git a/test/fuzz/fuzz-network-parser/25-address-section.network b/test/fuzz/fuzz-network-parser/25-address-section.network new file mode 100644 index 00000000..d0fae693 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-address-section.network @@ -0,0 +1,11 @@ +[Match] +Name=dummy98 + +[Address] +Address=10.2.3.4/16 +Peer=10.2.3.5/16 +Label=32 + +[Address] +Address=10.6.7.8/16 +Label=33 diff --git a/test/fuzz/fuzz-network-parser/25-fibrule-port-range.network b/test/fuzz/fuzz-network-parser/25-fibrule-port-range.network new file mode 100644 index 00000000..36646ec0 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-fibrule-port-range.network @@ -0,0 +1,11 @@ +[Match] +Name=test1 + +[RoutingPolicyRule] +TypeOfService=0x08 +Table=7 +From= 192.168.100.18 +Priority=111 +SourcePort = 1123-1150 +DestinationPort = 3224-3290 +IPProtocol = tcp diff --git a/test/fuzz/fuzz-network-parser/25-ipv6-address-label-section.network b/test/fuzz/fuzz-network-parser/25-ipv6-address-label-section.network new file mode 100644 index 00000000..945b7dcc --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-ipv6-address-label-section.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[IPv6AddressLabel] +Label=4444 +Prefix=2004:da8:1:0::/64 diff --git a/test/fuzz/fuzz-network-parser/25-link-section-unmanaged.network b/test/fuzz/fuzz-network-parser/25-link-section-unmanaged.network new file mode 100644 index 00000000..4fe49160 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-link-section-unmanaged.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Link] +MACAddress=00:01:02:aa:bb:cc +Unmanaged=true diff --git a/test/fuzz/fuzz-network-parser/25-neighbor-section.network b/test/fuzz/fuzz-network-parser/25-neighbor-section.network new file mode 100644 index 00000000..dd750dd5 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-neighbor-section.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Neighbor] +Address=2004:da8:1:0:: +MACAddress=00:00:5e:00:02:00 diff --git a/test/fuzz/fuzz-network-parser/25-route-section.network b/test/fuzz/fuzz-network-parser/25-route-section.network new file mode 100644 index 00000000..c9c7a722 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-route-section.network @@ -0,0 +1,8 @@ +[Match] +Name=dummy98 + +[Network] +Address=192.168.0.15/24 + +[Route] +Gateway=192.168.0.1 diff --git a/test/fuzz/fuzz-network-parser/25-route-tcp-window-settings.network b/test/fuzz/fuzz-network-parser/25-route-tcp-window-settings.network new file mode 100644 index 00000000..e77a7217 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-route-tcp-window-settings.network @@ -0,0 +1,10 @@ +[Match] +Name=test1 + +[Route] +Destination=192.168.1.1 +InitialCongestionWindow=20 + +[Route] +Destination=192.168.1.2 +InitialAdvertisedReceiveWindow=30 diff --git a/test/fuzz/fuzz-network-parser/25-route-type.network b/test/fuzz/fuzz-network-parser/25-route-type.network new file mode 100644 index 00000000..9a104137 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-route-type.network @@ -0,0 +1,14 @@ +[Match] +Name=dummy98 + +[Route] +Type=blackhole +Destination=202.54.1.2 + +[Route] +Type=unreachable +Destination=202.54.1.3 + +[Route] +Type=prohibit +Destination=202.54.1.4 diff --git a/test/fuzz/fuzz-network-parser/25-sysctl.network b/test/fuzz/fuzz-network-parser/25-sysctl.network new file mode 100644 index 00000000..2452fb7e --- /dev/null +++ b/test/fuzz/fuzz-network-parser/25-sysctl.network @@ -0,0 +1,10 @@ +[Match] +Name=dummy98 + +[Network] +IPForward=true +IPv6PrivacyExtensions=true +IPv6DuplicateAddressDetection=3 +IPv6HopLimit=5 +IPv4ProxyARP=true +IPv6ProxyNDP=true diff --git a/test/fuzz/fuzz-network-parser/26-bridge-slave-interface-1.network b/test/fuzz/fuzz-network-parser/26-bridge-slave-interface-1.network new file mode 100644 index 00000000..81b372fb --- /dev/null +++ b/test/fuzz/fuzz-network-parser/26-bridge-slave-interface-1.network @@ -0,0 +1,12 @@ +[Match] +Name=dummy98 + +[Network] +Bridge=bridge99 + +[Bridge] +Cost=400 +HairPin = true +FastLeave = true +UnicastFlood = true +MulticastToUnicast = true diff --git a/test/fuzz/fuzz-network-parser/26-bridge-slave-interface-2.network b/test/fuzz/fuzz-network-parser/26-bridge-slave-interface-2.network new file mode 100644 index 00000000..45ec2de9 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/26-bridge-slave-interface-2.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +Bridge=bridge99 diff --git a/test/fuzz/fuzz-network-parser/27-xfrm.network b/test/fuzz/fuzz-network-parser/27-xfrm.network new file mode 100644 index 00000000..fa26c84e --- /dev/null +++ b/test/fuzz/fuzz-network-parser/27-xfrm.network @@ -0,0 +1,5 @@ +[Match] +Name=eth0 + +[Network] +Xfrm=xfrm99 diff --git a/test/fuzz/fuzz-network-parser/bridge99.network b/test/fuzz/fuzz-network-parser/bridge99.network new file mode 100644 index 00000000..39e48ce2 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/bridge99.network @@ -0,0 +1,6 @@ +[Match] +Name=bridge99 + +[Network] +Address=192.168.0.15/24 +Gateway=192.168.0.1 diff --git a/test/fuzz/fuzz-network-parser/configure-without-carrier.network b/test/fuzz/fuzz-network-parser/configure-without-carrier.network new file mode 100644 index 00000000..5bd9d7e8 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/configure-without-carrier.network @@ -0,0 +1,7 @@ +[Match] +Name=test1 + +[Network] +Address=192.168.0.15/24 +Gateway=192.168.0.1 +ConfigureWithoutCarrier=true diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-anonymize.network b/test/fuzz/fuzz-network-parser/dhcp-client-anonymize.network new file mode 100644 index 00000000..a910cba0 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-anonymize.network @@ -0,0 +1,16 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCP] +Anonymize=true +UseMTU=true +UseRoutes=true +SendHostname=true +UseHostname=true +Hostname=test-hostname +ClientIdentifier=mac +VendorClassIdentifier=SusantVendorTest diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-critical-connection.network b/test/fuzz/fuzz-network-parser/dhcp-client-critical-connection.network new file mode 100644 index 00000000..0e65dec0 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-critical-connection.network @@ -0,0 +1,9 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCP] +CriticalConnection=true diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-ipv4-dhcp-settings.network b/test/fuzz/fuzz-network-parser/dhcp-client-ipv4-dhcp-settings.network new file mode 100644 index 00000000..5c4ca22a --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-ipv4-dhcp-settings.network @@ -0,0 +1,15 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCP] +UseMTU=true +UseRoutes=true +SendHostname=true +UseHostname=true +Hostname=test-hostname +ClientIdentifier=mac +VendorClassIdentifier=SusantVendorTest diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-ipv4-only-ipv6-disabled.network b/test/fuzz/fuzz-network-parser/dhcp-client-ipv4-only-ipv6-disabled.network new file mode 100644 index 00000000..c980bf9f --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-ipv4-only-ipv6-disabled.network @@ -0,0 +1,6 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-ipv4-only.network b/test/fuzz/fuzz-network-parser/dhcp-client-ipv4-only.network new file mode 100644 index 00000000..9bc019a6 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-ipv4-only.network @@ -0,0 +1,5 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-ipv6-only.network b/test/fuzz/fuzz-network-parser/dhcp-client-ipv6-only.network new file mode 100644 index 00000000..1f70c3b8 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-ipv6-only.network @@ -0,0 +1,5 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv6 diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-ipv6-rapid-commit.network b/test/fuzz/fuzz-network-parser/dhcp-client-ipv6-rapid-commit.network new file mode 100644 index 00000000..52fa5872 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-ipv6-rapid-commit.network @@ -0,0 +1,8 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv6 + +[DHCP] +RapidCommit=false diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-listen-port.network b/test/fuzz/fuzz-network-parser/dhcp-client-listen-port.network new file mode 100644 index 00000000..73ac3646 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-listen-port.network @@ -0,0 +1,8 @@ +[Match] +Name=veth99 + +[Network] +DHCP=yes + +[DHCP] +ListenPort=5555 diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-route-metric.network b/test/fuzz/fuzz-network-parser/dhcp-client-route-metric.network new file mode 100644 index 00000000..aa04aaef --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-route-metric.network @@ -0,0 +1,10 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCP] +UseRoutes=true +RouteMetric=24 diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-route-table.network b/test/fuzz/fuzz-network-parser/dhcp-client-route-table.network new file mode 100644 index 00000000..75f16aa2 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-route-table.network @@ -0,0 +1,10 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCP] +UseRoutes=true +RouteTable=12 diff --git a/test/fuzz/fuzz-network-parser/dhcp-client-timezone-router.network b/test/fuzz/fuzz-network-parser/dhcp-client-timezone-router.network new file mode 100644 index 00000000..6316f9cf --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client-timezone-router.network @@ -0,0 +1,8 @@ +[Match] +Name=veth99 + +[Network] +IPv6AcceptRA=false +DHCP=ipv4 +UseRoutes=true +UseTimezone=true diff --git a/test/fuzz/fuzz-network-parser/dhcp-client.network b/test/fuzz/fuzz-network-parser/dhcp-client.network new file mode 100644 index 00000000..5629bc48 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-client.network @@ -0,0 +1,5 @@ +[Match] +Name=veth99 + +[Network] +DHCP=yes diff --git a/test/fuzz/fuzz-network-parser/dhcp-server-timezone-router.network b/test/fuzz/fuzz-network-parser/dhcp-server-timezone-router.network new file mode 100644 index 00000000..3ebbf05d --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-server-timezone-router.network @@ -0,0 +1,13 @@ +[Match] +Name=veth-peer + +[Network] +IPv6AcceptRA=false +Address=192.168.5.1/24 +DHCPServer=yes + +[DHCPServer] +PoolOffset=10 +PoolSize=50 +EmitRouter=yes +Timezone=Europe/Berlin diff --git a/test/fuzz/fuzz-network-parser/dhcp-server-veth-peer.network b/test/fuzz/fuzz-network-parser/dhcp-server-veth-peer.network new file mode 100644 index 00000000..7b38e72b --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-server-veth-peer.network @@ -0,0 +1,6 @@ +[Match] +Name=veth-peer + +[Network] +Address=2600::1 +Address=192.168.5.1/24 diff --git a/test/fuzz/fuzz-network-parser/dhcp-server.network b/test/fuzz/fuzz-network-parser/dhcp-server.network new file mode 100644 index 00000000..9e49691a --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-server.network @@ -0,0 +1,12 @@ +[Match] +Name=veth-peer + +[Network] +Address=192.168.5.1/24 +DHCPServer=yes + +[DHCPServer] +PoolOffset=10 +PoolSize=50 +DNS=192.168.5.1 +NTP=192.168.5.1 diff --git a/test/fuzz/fuzz-network-parser/dhcp-v4-server-veth-peer.network b/test/fuzz/fuzz-network-parser/dhcp-v4-server-veth-peer.network new file mode 100644 index 00000000..5c91d654 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/dhcp-v4-server-veth-peer.network @@ -0,0 +1,6 @@ +[Match] +Name=veth-peer + +[Network] +Address=192.168.0.1 +Address=192.168.5.1 diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network new file mode 100644 index 00000000..5bd80dec --- /dev/null +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -0,0 +1,273 @@ +[Bridge] +Cost= +UseBPDU= +HairPin= +UnicastFlood= +FastLeave= +Priority= +AllowPortToBeRoot= +MulticastToUnicast= +MulticastFlood= +NeighborSuppression= +Learning= +ProxyARP= +ProxyARPWiFi= +MulticastRouter= +[Match] +KernelVersion= +Type= +Driver= +Architecture= +Path= +WLANInterfaceType= +SSID= +BSSID= +Name= +Property= +Virtualization= +KernelCommandLine= +Host= +MACAddress= +[Link] +RequiredForOnline= +ARP= +AllMulticast= +Unmanaged= +MTUBytes= +Multicast= +MACAddress= +[BridgeFDB] +VLANId= +MACAddress= +Destination= +VNI= +AssociatedWith= +[DHCP] +UseDomains= +UseRoutes= +IAID= +UserClass= +UseNTP= +RapidCommit= +ForceDHCPv6PDOtherInformation= +UseMTU= +UseDomainName= +RouteMetric= +SendHostname= +Anonymize= +VendorClassIdentifier= +Hostname= +DUIDType= +UseHostname= +UseDNS= +CriticalConnection= +DUIDRawData= +RequestBroadcast= +ClientIdentifier= +ListenPort= +UseTimezone= +RouteTable= +[DHCPv4] +UseDNS= +RoutesToDNS= +UseDomains= +UseRoutes= +IAID= +UserClass= +UseNTP= +UseSIP= +UseMTU= +UseDomainName= +RouteMetric= +SendHostname= +Anonymize= +VendorClassIdentifier= +Hostname= +DUIDType= +UseHostname= +CriticalConnection= +DUIDRawData= +RequestBroadcast= +ClientIdentifier= +ListenPort= +UseTimezone= +RouteTable= +BlackList= +RequestOptions= +SendRelease= +MaxAttempts= +IPServiceType= +SendOption= +[DHCPv6] +UseNTP= +UseDNS= +RapidCommit= +ForceDHCPv6PDOtherInformation= +PrefixDelegationHint= +[Route] +Destination= +Protocol= +Table= +Gateway= +InitialAdvertisedReceiveWindow= +GatewayOnLink= +GatewayOnlink= +Type= +InitialCongestionWindow= +IPv6Preference= +PreferredSource= +Scope= +MTUBytes= +QuickAck= +FastOpenNoCookie= +Source= +Metric= +TTLPropagate= +[Network] +IPv6DuplicateAddressDetection= +IPMasquerade= +ProxyARP= +PrimarySlave= +IPv4LLRoute= +DefaultRouteOnDevice= +Address= +IPv6ProxyNDPAddress= +IPv6AcceptRA= +IPv6AcceptRouterAdvertisements= +DNSSECNegativeTrustAnchors= +MACVTAP= +IPv6PrivacyExtensions= +MACVLAN= +MulticastDNS= +LLDP= +Tunnel= +Gateway= +IPv4LL= +IPVLAN= +IPVTAP= +EmitLLDP= +IPv6MTUBytes= +IPv4ProxyARP= +Bridge= +DNSOverTLS= +Bond= +IPv6ProxyNDP= +DNS= +ActiveSlave= +LLMNR= +DNSSEC= +IPv6HopLimit= +IPForward= +IPv6Token= +Xfrm= +Description= +VXLAN= +L2TP= +MACsec= +LinkLocalAddressing= +ConfigureWithoutCarrier= +NTP= +DHCP= +Domains= +IPv6PrefixDelegation= +VLAN= +DHCPServer= +BindCarrier= +VRF= +IgnoreCarrierLoss= +KeepConfiguration= +[IPv6Prefix] +Prefix= +OnLink= +PreferredLifetimeSec= +AddressAutoconfiguration= +ValidLifetimeSec= +[IPv6RoutePrefix] +Route= +LifetimeSec= +[BridgeVLAN] +EgressUntagged= +VLAN= +PVID= +[CAN] +SamplePoint= +BitRate= +RestartSec= +TripleSampling= +[Address] +DuplicateAddressDetection= +AutoJoin= +PreferredLifetime= +Address= +Scope= +HomeAddress= +PrefixRoute= +AddPrefixRoute= +ManageTemporaryAddress= +Broadcast= +Peer= +Label= +[RoutingPolicyRule] +Table= +IncomingInterface= +To= +OutgoingInterface= +From= +TypeOfService= +Priority= +FirewallMark= +SourcePort= +DestinationPort= +IPProtocol= +InvertRule= +Family= +[IPv6PrefixDelegation] +RouterPreference= +DNSLifetimeSec= +DNS= +DNSDefaultRoute= +RouterLifetimeSec= +Domains= +EmitDNS= +EmitDomains= +Managed= +OtherInformation= +[Neighbor] +Address= +LinkLayerAddress= +MACAddress= +[IPv6AddressLabel] +Label= +Prefix= +[IPv6AcceptRA] +UseDomains= +RouteTable= +UseDNS= +UseAutonomousPrefix= +UseOnLinkPrefix= +BlackList= +[DHCPServer] +EmitNTP= +PoolSize= +PoolOffset= +Timezone= +EmitDNS= +NTP= +EmitSIP= +SIP= +EmitRouter= +MaxLeaseTimeSec= +DefaultLeaseTimeSec= +EmitTimezone= +DNS= +SendOption= +[NextHop] +Id= +Gateway= +[TrafficControlQueueingDiscipline] +Parent= +NetworkEmulatorDelaySec= +NetworkEmulatorDelayJitterSec= +NetworkEmulatorLossRate= +NetworkEmulatorDuplicateRate= +NetworkEmulatorPacketLimit= diff --git a/test/fuzz/fuzz-network-parser/github-10639 b/test/fuzz/fuzz-network-parser/github-10639 new file mode 100644 index 00000000..530a29b2 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/github-10639 @@ -0,0 +1,8 @@ +[Match] +Name=dummy98 + +[Network] +Address=192.168.0.15/2424 + +[Rou] +Gateway=192.136.0.1 diff --git a/test/fuzz/fuzz-network-parser/github-13938 b/test/fuzz/fuzz-network-parser/github-13938 new file mode 100644 index 0000000000000000000000000000000000000000..a944a5bc06e17212b494703b5b85d27675c8d10c GIT binary patch literal 65 zcma#{3@9@T$}cTR4Jb-Y%dCjy^2tm~Ey>JH4NgtA&CE;7%*(VYsbmOC%*jl_lq#tN E031~qkpKVy literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-network-parser/gretap.network b/test/fuzz/fuzz-network-parser/gretap.network new file mode 100644 index 00000000..88b92503 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/gretap.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=gretap99 diff --git a/test/fuzz/fuzz-network-parser/gretun.network b/test/fuzz/fuzz-network-parser/gretun.network new file mode 100644 index 00000000..376074cb --- /dev/null +++ b/test/fuzz/fuzz-network-parser/gretun.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=gretun99 diff --git a/test/fuzz/fuzz-network-parser/ip6gretap.network b/test/fuzz/fuzz-network-parser/ip6gretap.network new file mode 100644 index 00000000..cad0bae0 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/ip6gretap.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=ip6gretap99 diff --git a/test/fuzz/fuzz-network-parser/ip6tnl.network b/test/fuzz/fuzz-network-parser/ip6tnl.network new file mode 100644 index 00000000..41e34484 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/ip6tnl.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=ip6tnl99 diff --git a/test/fuzz/fuzz-network-parser/ipip.network b/test/fuzz/fuzz-network-parser/ipip.network new file mode 100644 index 00000000..4ce67149 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/ipip.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=ipiptun99 diff --git a/test/fuzz/fuzz-network-parser/ipv6-prefix-veth.network b/test/fuzz/fuzz-network-parser/ipv6-prefix-veth.network new file mode 100644 index 00000000..3d2acecd --- /dev/null +++ b/test/fuzz/fuzz-network-parser/ipv6-prefix-veth.network @@ -0,0 +1,5 @@ +[Match] +Name=veth99 + +[Network] +IPv6AcceptRA=true diff --git a/test/fuzz/fuzz-network-parser/ipv6-prefix.network b/test/fuzz/fuzz-network-parser/ipv6-prefix.network new file mode 100644 index 00000000..c1932a84 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/ipv6-prefix.network @@ -0,0 +1,10 @@ +[Match] +Name=veth-peer + +[Network] +IPv6PrefixDelegation=yes + +[IPv6Prefix] +Prefix=2002:da8:1:0::/64 +PreferredLifetimeSec=1000s +ValidLifetimeSec=2100s diff --git a/test/fuzz/fuzz-network-parser/ipvlan.network b/test/fuzz/fuzz-network-parser/ipvlan.network new file mode 100644 index 00000000..d0532205 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/ipvlan.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +IPVLAN=ipvlan99 diff --git a/test/fuzz/fuzz-network-parser/macvlan.network b/test/fuzz/fuzz-network-parser/macvlan.network new file mode 100644 index 00000000..a41c1f91 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/macvlan.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +MACVLAN=macvlan99 diff --git a/test/fuzz/fuzz-network-parser/macvtap.network b/test/fuzz/fuzz-network-parser/macvtap.network new file mode 100644 index 00000000..6ee99ab9 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/macvtap.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +MACVTAP=macvtap99 diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-11285 b/test/fuzz/fuzz-network-parser/oss-fuzz-11285 new file mode 100644 index 00000000..e0aad02c --- /dev/null +++ b/test/fuzz/fuzz-network-parser/oss-fuzz-11285 @@ -0,0 +1,2 @@ +[IPv6PrefixDelegation] +Domains=m \ No newline at end of file diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-11302 b/test/fuzz/fuzz-network-parser/oss-fuzz-11302 new file mode 100644 index 00000000..0ef0dccb --- /dev/null +++ b/test/fuzz/fuzz-network-parser/oss-fuzz-11302 @@ -0,0 +1,2 @@ +[Network] +IPv6MTUBytes=7K \ No newline at end of file diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-11314 b/test/fuzz/fuzz-network-parser/oss-fuzz-11314 new file mode 100644 index 00000000..2fb68e98 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/oss-fuzz-11314 @@ -0,0 +1,5 @@ + +[Network] +IPv6MTUBytes=6M + +Bond= diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-11345 b/test/fuzz/fuzz-network-parser/oss-fuzz-11345 new file mode 100644 index 00000000..b097fcd0 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/oss-fuzz-11345 @@ -0,0 +1,2 @@ +[IPv6PrefixDelegation] +DNS=:: \ No newline at end of file diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-13059 b/test/fuzz/fuzz-network-parser/oss-fuzz-13059 new file mode 100644 index 0000000000000000000000000000000000000000..d4267ffc0e39e4f3e76980d3888b89cfb8fc5b30 GIT binary patch literal 6558 zcmeI0-*3|}5XbWXFa0b0!UL63eD*oEAEHt5<89NVfhx32qHGZjXe~6^`1iRiIPIE5 zZAptX zMs4+(&?pxd@7|oHU#CTOKTJOr888^#z7N@n>qK3*_nTzw!H7Cj_l$*;tQ;(jf28qU zUX170r62K7(O-}Kcv%`aKc=mI)YhV5T?SHHQxx>GB?{+VTl97K%li-QIdInW?8C)o zI2t7lDkYUdZ3PFxISSBR8xX>x<hkzQ5jL__nOr-?^SfKzA$!%>S1KPNU zS9$qEO%t#x#b1i7cZ$gY=k;qhP6t5Fw^iWIa&rlkOOUP}T!tVyO&p@^8lzrjl&U8H zC}#&?uhx<6Q_zy0Lm)?@wuW2?$O(MOz#v8%k!z{BRSF`A94>1p)9r5SeJ2$2lk3?y zWXpKI7sP(e|gcIp0sV zp!cS+7iZu(Yk7Iwj&Pgq{d3jZ>!sLpwy~4&dbW27sNaB(SzW!Jb!`TG-CWaZuV-G* iHV&P!#<-bLRJ(yX^E^wn_i#xyEmPp>Nm# literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-13354 b/test/fuzz/fuzz-network-parser/oss-fuzz-13354 new file mode 100644 index 0000000000000000000000000000000000000000..2274fa5bd978b27ae12c2be04794f0d52155aa1b GIT binary patch literal 918848 zcmeI5UvJyUmhFXun}^N^=-1&x-wR9t^^g+v??Fg1nR|c%I!4m*^g&=Xa5FxhwBe3@ zuIwatzWptds$z*Mip4)gk>alrc$_n_EmN!ZUVH7ecX?j)-}dIeZvS5x+>FG3-ygPj zzdwKd_rL$g&Ew;Gx*2Uo|1GA)5z43k?d1LSD>5t!^Kfk)Tc}l)$ z`G3~Y*NXr1{NEnFe7e1VT>tF-tbhK;!}jsk3)e5i7e9->!&^^$O#b{${FDzL{`Z@U zo6nz~Zoj>_`S^4jc)`zK{yO$v%6}yOY4N}N+pQOWk@&~rpWk}pzuiVZ>}LIsoAuYn zr`Pw_(d$^hn2G<_{_FVX=nLfQ_+)$?>Z>OQUmg7->Z`?XA^vLkE##{+{r2kD-+sF^ zKLh#I;(IsuyDj~2Ih!uS*=#zSg^Sh14<^1JPJ)HMSO$~HDqQ(N{bx9l?`8T7gK!Zp zr}J=G;$hAflQ0NYlUWdip?KMg<$M_|mhzh?&t-?2Lx3fZ_&=X+Yd>P~0_3ZHC4Wv1 zfaGgSe{uPh*&`4gLGfP=T#kdOFW$H?oaX%ubH$D~uL10-I8yu;7#>d(kP|^o zgWNa>eF6Nb7c9eYz6e8qF%HmVI^KJ#j$CuZCydHbo_5H((+&GpX zaa03}v&DS2T1~^*Y7vS@D1J?UG6|+Df9{J9xj)$O1_YCZ;i0$k zumVxtXAS#E183kYs*znsG;jvaz}ax*pswZ3DgqCAGb5hLAnvwiE+wggvy2W+#VJuL z60V)xrSwy?HWRlHz!^BpiH6`TI%jdm%R!M&JnK_D0|32fhY1acghoOuN@%yK-rnEEZY=?- z9@t38n<{iDm8R=BleJ0W3Iu0IO_S;4A#aj5b$jg*ZA`kVRBR~YGy!Me44f&;ciJJe zKUG-6G@tuky{RISVk-CH%no~UfcBW%k$l|v5dbN% z7f}T1o*?C5?5R&Zgv_u&zDXJC2z7)yLLEhLYh*l=yh%%}s3q3K7%(_h_7L$$rKi39R6uY55X1m?*mf59Wqqq{NW=+>hh$4!i=W4V=S{#r3cAOF_LN<6(=|=g)^4SR@@5>&Pw5orHl>W zOwes_>?%Pc2@gOLZmF*v1C{1+5+Pk3STYb92u59cyIs4T1v&{VdlK1Dsw+{%>b0k; zc>K;v>g66J5r*uW4S2DX=BOSTIBUMC)jgbvVClkW(WBc|86kB(Lb~58qh2#j$0-Wq z>hYjI4M2aA31)l3+qD7OfPedV%^t;l#wqf6VHfe#53aAH3FKRl%f{gZX#HGdUTjZH5+WyFN9if2F_wS((b^0 z^STB*B@Y&%W!DfvE+LmXxn!rLscY7JXrfmsdq_z8W@(?Dk`cepn~#Um%Q4O>brA84 z((!;A(n9J*3#p~qA9hMAv1ljFqxx$rZBWTj$$G1ju~SlRzY{CVvx*SDI(&7yB7{+R zm-b}ARqTds3WZdS_f?;3UCI_YT)c@ztyrU<_*MmfH-?51oo>*-Yy~t z&wbW&r8J=_uA>JCM>9mA3_( z#(_JkkZ9kdNaR9r z5H|Lr0*X*as3X+j7T4Y4ECw0p1A=ZF-8Q;yblYsml@e2qSUw8WX>qsop(0}{MaDts zFQ@aV7c9eYz6e8qFKH%rcXO;i1?*Y+=tce09+yJ$!v;T7xN zHMso^N|{;;kgafSehBdjZuyXl1wF%COr|DNpF^e|{iSq?N>yL_k=cZ!u0^zPIbQ~g zrHqnVc5f*SfU`m1Yyr-^N)!Z!7O~eTE^S6IG%s((ls@JG&UQ%IpN5h-uF~V75}*<| zhf1I{*?^yweq?>D1K?+R`$}}ZQP5u8d_+N8yVRl&)!cldJIp%3)TXGWoGaa#ghoQc zu5yw<)A*<~JIA~+@r-yzJoCIS>>QID7|ZZVge`xi z)waMu9ifhvA(6~yF32c_S&G6^l-upMOAQAySZL;Y@u}T%1sfU;KXbn3Jz9vtK*Uie zHoD}|$1^x`8GFYFP0mBpzERQDBrK=9zo+{rL$NG5i4y*DTToDXjmiE0M0}i=x$btcWeM77A^IaW1yxo{>|r4;(ysKtpjHRz!{7hMxEJFSwh29 zMTiT9peA94$TUD?nhl4{6&W3<90UsAr z4tha?l7o`d#%=*{2F`|svwul+^VG$uI=b6>w#HhWNCYSZs5Z_aIO{&n*w#m7raBW4 zGzeN7i2Z{9)dBPN63VONf>KN9<8Hna%PpcyLrO(Idd5#RXL{v8hK5hI?xcqVXm zH5uomUKy&2>0KjllwjmKAK;CuIHp&V@Fd6LsljWuP=RHpw-(NAsxKC6;l9wTaE(!d zv*=;a6~EYP`wp{UqmrVMvg4Hyr|v6~jgNc0zt5UDZMc_xX=GSD2hO^WGkW9$%$r{# z&iLo;{oNag6AENw3M9hTx83GIRe=;siWYe@(=|ba)b5=?96}r_5{KZ@1LQbT7o+?2 z0=H5O1~+*VF5L*n>F5&4bRm$v659fHZ zy?6NNVEHJQ8;yx)(fQve@$_@)=jz2AX8&}7Lpmu&-Xw40^-cCz%nOGi@`Ku3Nz@}~2=$*RSDy~p5Oa3oFG zyI45g+jEjAeoCf<_v&qXFd(^NHNk4q;HnTPz33nB)`AJT6#r#h)DOYZRQiz>;*2fZ zQCSBB-E9#mgdin?5~P$3icr^lsB?ugwrnGLq)ITwH(R!&{fTh9&QZ~Vyd(cB;C6T3JaZ78QHoHC+KA5J>;PwtPx`WD8|AwK*F0fDYfJea z9&!4@mTh_G07|zA3Ju-!XMJFYNzkny4}~DNQ|L34u8bSt44i>8#!p1?S?F*-NgdFH z_Rx4CtxOWi5^M8pq$H`n8sZ7@WW`Lu1TMnhfiPG!iewXv3ZA;nw;-OG%Q-A#SjKu| z88bte`TDb(uiwqjF<&2*y7@=bCh3tk*%zX(>(cxsI4h%vu^G9(%3){bDK4WSVi2+X zXis5DVcCSbSX7OJv*vNeVh|RCjMG(y4t%fF0)or211ScXOImv}oUs^03m}RAPrT1B zn8V0+q-x3h*u2=e+lIfS-#8QZXkA&ABI6+Rm(%&w3zlIxUxcB*m@fR)Y!=Lexjd** zx^j}aA75Vo@p|lS*Y^+k*S6OeU1p2<|#7qbmQlnXO}sAeP-{T?M|0|BU|Cx{1D<5-103d7W52lDGZDl7~4oNu5mW{ zi<_8jbwy+Sn0*-a(&{`*u8C-+IAOS)FN4KWMoBHZyG>-u+xSXylbjeXUs-Yd24^&6 zXvnasop@Gd_K>_;DsL{xn_h8BHk4H044k!5Qh_sY2F|#F?ixpFj~%5BycY-#rL{mC zogM2sfu<_(&ni5$uIJ4!>>R72`?+pCmL?lr$C)@f@e~q`$9$WP zLH7e^SSi}jW55|W17|8lefs=q=L*0`A?cCwo}8o(u(IM7xI-H+q*W`g)U&aN6okMV z=NO!H(L}ustvKHH?tMJ+>X7!3_H>kLCcz@VdZ};%&cGQsi`w>5G{J*=)Wm?twsZL&q6=4%u_4ttoThwLeLN^>K|cDI%O)x~aSmQ3>Lt6lKq$7C^F&$iYb- z6h)6u%EC~p^;@fE1ZVU)+Tijvakkm`ql?RT>t8pUAAa;Un)J?s45YCTQe z5}(FWSKj`@QbEB<#=aFVaL@P@i*rUtfA;;Bo2qtS!M-W>O|fsPMEGjlwaWM>Vd*2deobgXC!Rp2(SbHkyk=9k$WLQEiq1GzYVg!-Rd0G{;Dri-dXjK$lyN$7} zg6`g4ds?*C)5SN39K2*=Kyn$ns|a0bqLfU|QN|D?b6qSPd-eR*n_EN~IuWDQtw&qPied@>89 zRaO@o(~Ggv=Bxd0UcWFO2U9;-_+dDeuTB*pQEx^GB{!cxiNC%`e287{TltQ*mXvrr z&4X_og#L0mpL)SE4Cjk5^cT~Gznaa0c`%o7iQcYTFQ(Vx)A%oi0_pjP8+?^Q&y*W|S}iTY~dS?pQo!|Cqt>1L-SJ0<%=wf5(fk4(iH7S`Ww%h zq4eOarP-g+)y2)z_lND>@6RtT->rY$Y`h=6&E}){2w@ga;A&S|5$a4!*quL~!4+oU ztT~*qQxeI82p*XL=yTBLIE;n@7-u_)Qnqi)PD$DF$!g;i<5WUz7|FmHIIDrPt9{8R zdX~!kx3|$`fH-@0>y57_BS;`IZ}=y32{22NH#v{`~LnqLs#itCPN!_oY(s`cTRnITX$r7fE7Cv z<*|I@MsWBNDMNqW-rv2s7`ie9&K%+l1(FRJ`-Q5Tcm~eE8938UK}u;O?uk&JseBMn z`yrt2pXq8_EE+GQRj5^c9|~y->B1`|Z9qbxCQ$2QQQ}T4cXcT^6FkVteXmw~U?^~K zh~&3+AfBahzXZ^w1 zq4Bh(e2AKZn$t!w0%zc?CpZ&rCAnkmxP~$gLVr1(PrYCnhVw-j`itqpU(II0JebQu zqDp0FmAM~ZUjOlW>}}Wg4=)^wF0;jawpvZY*=iAr-Dl$0^e2;Gy7K3~_>lX9P1i3> z7KVpn`>-|3eu+nV`1;Hv0sCVE>D$igk$h|!-eQ*Ham81SjTs^q=wF?G3|-@F^q115 zgH_DNv7oPKP-)g2lRJ4MK)9SQgT=D-M5fd@a8~+g_7P{?Jh4AaZ=D(#&5Y7!M3Lhi z{#gR+I&+pjoW!%zkBoSRmeLa~#RjU9OBJ_VsW`p7m3g`gs?vibZ<06l;`>NVR_nlm zGjImZT#W!bwR-AB1&*njR~TSj$GWbQHd9lp@lk1Zj(KAQ2Ly*Us^_lb>%_a$#PYrI+r**(6kfps))3oH7D4}Ic zX2Gra=aGS|OPCu6Q$JYvVK|kqPQ`?LH%6C}tACDnE3;;nHM8xt(^UjGLYj~ukRbFT ztwbg)#Xi9qI2$6)STc+2!r(#BkAf=a&&G9;E-X!bCbHBj{%ud^x)8|^tLW!Xy8^in z@0b)lS~92>GU}H4$}v#WQ+D(DllWg=+p8*- zD!M`AjBR}mMvI7NvaS8Uo=_~2~Up>>b~h-bvJ zHjXAZ183k2W6hh3w2ak7EY&tD)ABcwg{~O5=me^_)S<4yPRWCyn%y8!`jB{~ixuj- z(vPf=54B_f9bH}AJbi!I-u?c3H&^XNbJZWkM^Sb~qR3`sur%TgJ@v&Cu|?N(wymq> zLI{$=+DKt|kX_-7#X>~zv>d?QPZPgu%Qh%><&0QuEubbNWwB5m)i-g>G^(a00?mmq zoK2T($7fDk)yxfQoi*dz*_+|6_UouLF4fk$&elrpjkT)pu^`p^<RD3d_XYo z!@Q5)smvLE&;|73aujlT5El^_dm}Eg806cF zWbe50gDbwqVi4>_A{iuqk`ea`9#h)!@gP}~H^6xoGf3Fju(9b?c*N?kOYVZ1qPWDf zHsir&SYN zz41a?QAc&%tMmB60pb8vIzW*L_*Re~(@GXY9s_6K44kn7U#Ns*3TYZ@G}QEHNFnW< z=u${iNb5%qVUW9wxyv|CJUHHVp|O3(TQM1aRbXSaSC<(%VdSJYBPZ6v61=VquM+}9 z2gATGA3iv!h;2#=1^}uI0F3Wnzw~x1@pDDs4&qGc(rx1GTPpd2vnn`yX>+eLID^(e zYi_sSE;Ss;sz7rmiBIF{CggV)Nq{nK(Ejh2Z@nuq1T0Qi^5=wuz`u#reh%~I*Q&B1 z6bK5$tZft@WTX@tM-w)*qINo|Nj`A#?4dv>Oij_&S%;~~=35)AX zl2wZ4Ju$RnFle*mQzOg`6rbsdv_Flc)9&KTQJVVvNs#jF4$h>Q-`zyeij<-RnB+jD5$;t&1 zCxw7M#}+q~Ww+u+uaipV&4`=E4i*Snyo+8u4hl|_MS%ukRK>|7m(o5xcU6*?TrSo9Z_4jCj^hLuz6yY^4Rn zA>okp^N{SXYJ7^y6(mt^Hq=xsJ1#Ye#aA`&2_?mFG2 zls;f6~WsZAl_{J(T)KB5E0&!0GR{tD3DB~dXm(%&w3zlIxUxcB*m@fR)Y!=Lec?B?* zvr9d`y#C|$*xRn}AM)=PtFL*_7W3I^H4SI0MJRl-;@9*ilVG~?=f3!mE4G`G@?>Fn zC~nJ)!`EjnGxj@v{XAp+Cl(M1jMO4yOGP067?w2bi|?8IIYuN*>9dGFl#AGG^b#9t z)FV@GvpFJn(sdDHJoJhi?WWw{dgkvn&M>$(u%R#x`A33_gk&W^lY!DJ8)`jBQ`$9A zfK#*{TIwt7+=P)a@ibH)oslu|H1_TdC!XyDKl`9lUjsQ*5%NouF2}P93IRJMrLzYZ zX;M2Kd8>{*J0(v++bV=Pc1rFHK*hxnaj?5_P!MMqZ;!q!<;?gE2cLt#yPp%qP}WpY z310T9^DfyZ&aGZ!r=-?50%)brW*=K^v_KkYfk>n@B&f4f(m^>(Jd-FDv;(gz78Q0% zmf^27q6g53?v^D*{r8H&k@xaG>Bk1rNQYrss&DH167&ai`(c1 zlRTvyrJTO%=SWBdXBl7Y&XDQC{V*7>Cte7=5O^W-Hrs`O4I?= z0X6CXBvdxW>hQ_0UkEha4>XN?uHN5Q;rIv+2o6yo@y16~sjdn25cC3q{w3|t1JQUPtvnv328ZoKmm!ZK*qmChv0cVRN++drWlbzSw|k!yz4wF6hc}Xz z7%eecVo5EW>0=y`^J`I6B$uRJk}k6y+NH36ZEr4)q)*asLL(?*O0IF%$xAQjq84;f zp<6`?_CFW-$#D0sDL4!$#~Y%l`x~Li<_tK58J!n zpYLv3_M)4XKZ=jB32(SnWjoiQK;6KZE*PScJw7$n@7@jBMwzAE*3e0;3y=s%gki8A ze*pdf`~h)!aV!aJHvVWwfPaVxFgJvAL%1LghszeT+N%qvoU8$>Il?Ei;5K^cf>ye2 zBa~sQ<6!Cs3qK5}^3_>9-7c3$z89Qda%IgdYi8SPr>h8XB#@ln8LJl7mHE3%LA}f{ zW0zyOcuT+;h0+iUC6>(Mx-fVU^rN5z*)rkYMPX!0A)?fY1>W(gJyl0IjJ=`5FpH)C z(&AS=x)`I@58@p=_0U)Dg(lV@FJ#m$^_63w(mYO@n{7k}T3ox?8-ctR$!b;N*#P2M zh02XiDV|u)NozTFObB)43jX{l zC5n254UdLLQ?E5=!n_s7Y;Tv%F60`7F6y-b)oa^&WC$i>K2{9SbeGAnR<(m`RoT|Z z&LX84QwSst3mP{xZs2Dxu-ql9l|%_AWfAeIo!bIMv%*8e+6m6y?ox1c&Nd?kc zsB1pdxiU?$SV$U3>EgQ^$0^OPw%;zb2rCO9#5>U`KOnP+Du^nrh$<`=k~(JX`jPk+ zES83_PJBD6R*^@KJ|0|`$6c3Kw)WKl;_R7l_g+oLIeuvws*2YKAdP6my<_tixE4F; zS}fXip(>u7qZw`Y0B0;b(zm=I6hNepGQ|NB9I@~Sr3j^{6{U!k({gc(!$8ycxX1hZ z>kN&s;a>Ko5gisfEbFh#<92PGxoH*Rm&mdE=k5L7n~S|Wm>tG53PJc8{0x4UD5#m4 z@FU_+EdoM3J6b2xQ90gG$)GfPmTCbpc~d+M_NCAea@i1S!VT4UA+5TEYU-9kIw}6y zoXFOP zcC9#cru4)X5@vd#WLeLA0QY?F+RUwK}C9%x6C-DO&l#I#zMB806dTqIIQesrQVswlLpXq$Yv0SlummI6IbjtOo>CTuvnIojN7GpJ^N4!3Z5V17~fh<0r(K zgHuDGp{LZwsR3sPIBR^KiNzq^7@Qs841zwuy!nO2AaYGo8MhQ2V+QH<)gC$1ih8S3 zDUjeSZm(h2#;%QB8@o1k?J5LhXaZ^z+C$@ov`Xo!5o{y+*{?9bs>p^-Hf$zMB?KD; zn!+ufS zyrYe&FgO=IjCd!BgCt<4-RbzTJ&7Zpb(hxkByU<>uMW<@SsfqSZ(_Bd&DP$EIIDa? zClm+@1OT(xzfjfvF-aYtUdcDV1^Tt3|_s9h$|O zE4}2Ysz|jfCWbS^888AyaeF8g?J!JP8>TQAI1rUp-F9S57r6tuV}NppBZI-`Poh4_ z?%<3{mUg8S4u1N`#nX@f!u2uDulodN;H(X4*cxZs{En2(_o$_tAV48Nu^T6G$cR*v zmcjO?>TCokRxUUwXJ5%SWKKCdK%5m#b=xGpo+$tkofrQJ;)NIQf?Ik75U%vBn<9e- zp*kdc=~!2L)Fz)Yvyo@kxG{+K_L;=cKcxF)38{t2oD z)f)AMY7x%@FCcGX?$dRqND$sR(Zr{Awy46=v8CCc(bdJx)Axt%-S5vYF5j(x-E6!c zz0KyM_?Yl5m7eyRB7-B$P`5{e>%0)fB3h#Qn|oF1xL5;P7%e>t5`y zrlm6_5~lPiGU-wJP%dJ-TsFxD97T%Ku`gXSP{r+GO2`lQS?NAp&bc(1OOun#=MZNL zaOPDyuzC;|q1#=8&PE2_u`|p-E%lXSpym|y;EWLqMl1~6PD%;IX`;RcQid|>8Ayt_ zZZ!^7gcPc96)HD&O3DcjV5CXybmXl%^2K9OUFtdvILtADy=xbdPMxMx$2b!_$wiuC zr)1J1Rs_plF+>+QLtUT(k9K_Uxz^39xngKp_Mu*5r{wyDO3N^2DJxiaCsp1un;#f( zHqC2*vjd#5Q__KV4xAm}tg}-xCES=aZfM-lxS??)f*ZTB`mq~p-voSwE8F)Tds=XE zhXM8G;Y2X?rg#ELMxzekk|~|t4Z0z~PRX~?`=9(#jCXGbOdnKcl74$hAITNT_1lqK z8lhTkQ7v{#Mhn@HD3B<`i8~UJdhB5yuJL~QscqN6;Z0FeE6`X-HaK=3@yJX22O499*2vm<&W8>FB+}ERcegQzm-u;Tb z@j0aTa;KpR?_F0U6CIA7`(hMZR;XG^GIhNiqyQU`uqnrCQ%aM!9hQA;LKzdwMo79nZz)rMIF%nI)FKG2c-6u zG>qj09{W>8L&)XE%!8Se3Rq~okXEFfLOOT%JO`+f+Cm}SvqBn+g^Gq{HtRw>A)am2 zf8Y$9fivX-?2Z6U-Xw4C7k3oWE(>X{IEi;xh)4*|z*+tl5VJ5?JUVXvI`XZT|EO)c z8|WeEA$qe}v%iQ>V|(T~ZguEpn)>B~i~SLVff&Z|CPHgWTcw-v{p*+B&eEML&OwKu zL-{${3TIZgl7KUC2F`A`-!3&A$S&zXXbl%QS%pf2Q47E1x%nl38+%q@sF*juR`nB7 zaZ_;*u;L~)Sw$mK)0R#Oos{gd&56hE0Coq&`_3upk6lRaq(#zV zHZ5|6xH5UEQ4w>v!eCHgu!qSw2M^7RPmC<*Wn^(=F!=mQa1icSFfrfkPH83+m`q?Y zfysnM?ytdZ+o{3qup z!5KJng0l!_QqdM{51gGH&KAr0GFU7n>5oFnZrQm>zW@Md2LP2sxTeXi8PnzlC__b! z>31&$p`bcCutUSy+a0Xbt8n;??-R5`6xaLei>2B z&B)LT!d;2GQule}+*_s7NHnzlPz-f*P2F}ZTC0;=a*|MGr{*2;^zB+lkX6X)euRXq z_JyqWf3kkF@kcuX{6j>56L-&3g9|c=Z^Sp^TYgD7G}{*&YNWo~*8zpKm-l&gz%h`&bJQ7^))y}mwCK3-)uO5+d!X!9LVB+fW z&{CkKP~#Zl|7RdjhfjV1K%nVHU3nA+$}C#=bOyphM8tm2Wu#XJ%Evjo|Pl zGPV49dw=)l;)V{3`NS;m~l_M9gWtkXF4a zb%g|lbV8QX)dBY9oSOnC&$U0a1BAt*QHzCjr3lU-1P}u5V9ZMH6w(yZO^{j^x5dhJ zlkRjI63=1~7K7+6C~dILdddr&F&fuK3IJz~;f%{b9eB&YXJhz8cjGcpd&SjYY_O86 zesOZ?2w}ig7#QEbe(CK52=ByraB}Z4Rf}`xsT!a^DuT=DcVP_Y82) zfa!GWAy=6zav6((zV>jQrr%jTorJEo?Awacp z4#8RXamLC82jwgcLPkg53b9z|j42xiXYBmdvu=uvq|+kMvgA75NPOAG zjbo(=&nKQwJfBevwy&;TNVEBg0RasGO{Wk?Oab-~##pn(5s`I7B%MR)b4?=>MT}zU z1Y?4+9*pBl@}TsYjyqBqQrO#Fpor{~@xZ9#Eb3;<`FjX&BE z;2$Ca%s{a;_`pzGXQ-OiASD`y56$t)0pTD(Z4OF4BMO#NWthv8JdIu%y(>&z~L z&o4jC-hETlI0*gabUyWhWf;yEVdyWW3x7461@mBD0gQ^mTS4*h<@F!0$KG~*|L`Jr ziA#Mga<-VyR;y_^TP;H2UlhNlKbZv6l|T2zhuj}*G9OG9hKJ&I-@@VRGZ&4vtAx6I z#u%kOEQYO4l9fBK{z*E-Vn1U!I0I+-`*VsImr8Pq(U>E0CtVlea=r`}%huDFdT7Km zgr7E4jB~)5h(zA_NN|y-SVi+P37S!!0gUpr)K`vyntD#yDQU2I)!y<%<<`11XL{t; z^za-qkmM?EH4a4%T`+1UD5SFo0YH=5vBO*0;fuYxggF@`tuup*FxUNNgHYXM!6Kei z>4yf+NC@lRhpri=&p^7fS1fqi-9f4X zwkoloiSqwylD8=V4s?H=8L6;gE9E(m$gHV(q4u~tH61k_H61k_+U`hr`p@B4;~}0k^dQNbbcowX3`4`&!OTeojjQoOT7_CQ4sIj*QAnF< zHm)))o6}Lvw4o6O4}?JmMk^$NqK5{~z*!Sy1DwT*Vw1ZmY{(UPlf0>`ZdH1a;4JRd zeu*|6(74@o031*aa0brWpc>$;F`N~Tj=#bvb?cQ&9pJMue5RgydzBI0t-HFLa36H= z?fJ!t$CxnSDh!P8U%&Krb3M6T;SS==jh7vqxx$&%5`S>k-E_k}6jl&67@UXJkLRY; z@y;DeJR_dvuYoI;1AY@K>)2uwV?~^OeSE5BQ=yYWCxuQ*9OQR`R!f7U#UUeEL9LE8 zB^@OlC0!>vDHAUsZ<063o8(Qi$@%=H1C#-jfp`T?+KY_BA!*SnEn+ahXcdODDN4MR zD0cqo)DTMTtsREPlbQ5&WH9*rNf<}7lgXMFwxF66S@EdNU4=-Ru-Mp-K5nv zzawQ66PwI1Fd3LkxgnfxEHLrrP-g+)y2)z_lND>@6RtT->rY$Y`h=6&E}){ z7{pEB%^@3#>&KF_mFQyBBHJb(V zU|s=?<>qr9Uta(5dhBi2_YW?wdYvuiv(;)E&Q^<1|*+6}g0|+t^aIZIi#4);cn+#ZJj+Se~AE+|Lr$d)8P8@mzAi_SHk;nf>yLVks zs+g+;%T1KqlM0xijLAH-S2DF{-haVijpB`_%-`qbH{li=FBlL8# z_m_hzVVAP>+_Kp`Y=fU~|0;f|&yRoqtk$?QnpJL0{-mg3GpO<+L9X#!E#-t|Rt7J&0S8tGf(M7$uh8UZpF~9hcOIc*E zazB4zBaVv>@J%!!I-gJW*-1G?SyApIBNN~LuQ;Z}^y73)qix<~N*5}zlOx|;G~8#j zQB+aS+^A!sfQEt<6e=3|k6LrYdB%-HM@yw^H2dV~=Mr)GBrJ;(~ zP%1u6YP+Hopx)*q5-ahn+wp8){7G2QKx<3OK8)%V@0H#|k7qP9(*n9dtID~;ie~0M zNJx{UNxi8u7&=BXGwQ4qSU=2^!zACBN-xa_L^D%=l!h{hW@c3UMSlt&lqo>P)qd?} zEzL|Zb!O3zvaQlzNiim;O1Ce27+BUKMgxrPZFFExeA=*L$aB<8^x}Co{XA)AYI>X& zfMnc0%*2CiX13it?ds3_&-m(aQ*96@n`nsi>>`~!3YE&JbCuWxf$s-lOV&hLq0_J| zP&2*e_+6TTJ7o!FNxTk31{*E!7N{;g>$g&t7~W#5@KhX&%2K&AOx7jBeV3mnWl32q zQ25#`m!yj#K28%m=GT`Z-cXrmXF0KxYMuC| zYC^hu2Q$Oq44e&l45Q2{G#J*Y8CG$-hIrPCc*c75ecsA?^_sUtpa0#8tXJ0*?&3AE zJM)Kqq1=!DFQsE6{&T^S<{NGI z3G&;i(2qTy=1JT*2>s=BKJ|iS7|s`A=r5)Ve>Iy0^I$G@oaFe%^jdsscb2W7`1tbr zkJn>wyS{&Tk!z-?-&>h2=Cjpm8qQXWP&`8MYxOn6PLW{KwuOn+&eZ6B*|!{wma{bgLh1d9;VQ2uKrCt z$(kIh1YoWSo^D&}E5|@hy#Q?NHYm-tL#zoYUBMZQTE$@erHMmd!~_`)n~P@^a5mt1 z@JxAt0H8_j2mn@_;B)&9gt=~ox%iG^3Obt|@5I6G#z9Bh6hD6w9E1*tsa!~;{ zR%J`GKkSrL4CW|dKB6Sq3%!Om9icAiJfvY`FB8zkq>HH+wWW?BJ0+u@9w#e_Fr}b# zE1sK4O(BAFU5kK5a;oUto=@MFosxNp0)`4htxUnlqgsfpRVY#k9j}D0;A`1_juPsg ziDP&*$=gL_4@(G-cA7B|VIaal6qiD~JM3F((a>$csCHm@a?lC{XMMsM0ANLiUZ(Ce zI)h+KC3U=#>Vop!_@wXq^0zuN8OMqYWezyfJ)#ioSt0l(YKi`Ndw=%^+gS;Lmb}^h zyjgVnGx4mZT|0GCU~jBrZ^TBc)Ol>Q`5S+TXXqM()is(BIU6se55txXr?BraBG?>V z!&2)(V&%cgqidu`L=AA}?if-?Q%JXQ48a*V180WIyzG-3jyD`{tY*92e!J9gAdgQp z1+%k$iBIFdj1g>{3O1#8W9_@5A^fJbKL{9!=t4(>j>hLtPYp)#?_8-#@%?SftDr z^Vw=O4QH!GDB3sT*YqcoV7l_>zW9*)gAHLkm@Etr#r9!qvkxU6>EY`$*M0kb|(BTV27oPje%l&J*99+kkpT8{%ubKWp&-m_72VTy_`cR|_6 zSItm1=s~Q%V$6#6&7*6SmVy*}JR-9?%A2M(1%;q81-GQpoDcxwH`E2#{QAYUgj)L4 z5NHk_S>vP9>>MMZF(RSDa~d57m^Z($b4+evJah@9$jH{oS1`@nw?`0TlsN zlikvxrf6Beqe756V6)TdN0~?A>cCP@LNF#6>%lmlzNB^Wr5p;pjU=tCB*>?71waHqbKGD8lRhq_6hW2t7fla$Jy zLoI-0+dy>qPu=1FxVHjJTkax0jUyAc2~@G)6s0{P_`&E;(IXoGQ`l_$(Z%Jv^{<=F z4?lXFO%g6y25+9{H2Dl*s9`vpE*A~#?9wzX$tO#shsi9s75}_z^VH*D>IVxy45#wd zsjw2Mw@L=R`TR-z^~FtYdh81L{B!ivvu2hxv*Lbl}weRkb^&jgWrgif&|mC!e_ zir@^KfwQF34nKpR!Ot4uXY7wpA9YOehN?%AR+P2fM5RyX_SxntFyg_1+b53+{?mHA{i zW3dnsJY_nr{Gdc|m_i%X95{1{GZqWwQGIad5_c@H>cb8p+`Y=cr^?5Ui9T2RcR1ur z7XyrE&xCp8YBJ7Y!1f+Z7Y2XcsET_n=pxZYYNPG|XW$H+8MJ@$W_NbT-+B&&>y9y8 zA!X|45aI-JQmvI87|w>EH$Lw1zEZ5R5Ahqh17EbvcT15WP7o(OVCR(IwJikTtR&99 zM5dNMZ}0EkT}P^x zF-WxZ$662~)Dh|kb^Q!=uEs7|3^L9K1a`ubcEZ>}X7K+~Wk(>3`Zk-9;qiboaMp%v zq$bW-43c+%iEqTWHV!a217|gG#$u3fyMZ)ykW~AC#UNf>3tFp5o`shhdlB{`>_u_m zhrKA>Kbl_&tGFE1%I!Wf;#vC0t&;#P1&LDYM|MJ-F%ZZ=pk6-Y$Kjev5vx4q<_m`j zt?_v#7K3Iz35jGTbT#xFmD!(Oq`IQ z6VEm~xArLWC|nIxgEKlRdPxM%9-maeRtxTJLZbboKY5e9x&GP=&YJMEHeN_`fGDIZ zi0L*_mX0bNRlT^<`ec3RKx9}w0<_JUuf?n=a42vna02osd6T>u=i7E|HLnV6g7(Rc zJr3+~V2{J?_S>a~19^O?14L=jgcwxR9Wuu=uW%cq`RhJ?{j>AkZ`px7ob?V;Gmp+ zB?lmKlyCc>gGWkh7WB;U5Yc(@pCDdw8wi|HaO%k-MMhHY2%zlharhbhOh-yi7SX*w zmHMaP44i>8WzwL7=+zS?ddANpdKUkIpS`)bp&?-HqZ~lqjIOiq(txB@uaRQ8zr}L@ zgYi?u$4P@6RtT->rY$Y`h=6&E}){n6O-xp7x6F0aTUVRU2|6t_*Mn&fJuu z@y+y!Xo^vozHL;|${E+ReWDk@l^T;oa3VMn+)V@*!oWTai=d_sag&U6v++ke0{lZn zfSY&qQzSKCB%P^L#h<3hU)g5*`Gx(Lp^jm1)c;g>Ja%T2-rv4bJ+Gvydgt9>UKkAvcOV#34~q zn@W#|7LfzPz90$iR@Cv1Ie5op)$XOT=H%?1sf_3f&Zyi})>MZR zMlGYEb+PNBay!pme<^jdr)>-&Xi_^i7bqRBw2y^l6KxtH{ZFHbK7(jW@ zJ=!MP{VviJBcyFvE2!6~*96}$ZuXO429#jfDXH}*VazaQ2DMIN17oKoyZ+QNI|TLU z42nNaJk}Hf6ao|iv6zvmy^q+^?8SVOJym{nbflSqO9GI17VIt+kD@_on7m2eWCpJ9 zGjQ-TnHY#?Lyu?dlswR*vh0aNGW0{TKVilc4O2AVj@;5H>aL@6%gQFHT7^f-V$51c z%v$V}jMR?2`FL<Gv3eU1cY8$P&Pg|xjaPXO7GVQngKh@hjO!yMb{dn@HmZFzZ)Bk1 zYF~cKPZR@;XU|0We>EBBq~4a_s0>r*jT%>5xWatEfaU}0-R@|A!VRt|a0brW;D6u@ zoYlY?zI|on93aDOQ7OU~)`Bmr@j0aT_u2Zj>xv{eYXN6}Yrr|tz_);)n^l2El%a!f z{UwsC{=B`vx(S{EWPr7|Ur6gXy-Lp)hIo8Q~Zb^Y!hn*FH)XW$H+-EO~KYB-R`r#miLQM;xFDpnM` zy!Eh*@pDOCZS1*>XJ1XLClxo%8G~nk68n?b*BKv7jrl==j<%%e z*d2X5%ybW6rhDSiv7=+x(Y=F%?AWCqGAYt3*EUk9i#p(Ooo`h$_+ zBBW2b?2MUb<6U9pf`f7vf>xT-+9bW6c|IdLFaDDYV!#;%ry-NT&){c8{A{tDcikkH zT)JK?tey>VLeeIok6P3Am~6eQ9Ko?T;L3xwTrVaD9xG8FK5^~h49O+adJVF zcpi9lO_t>B<6&4SCBa`E)zzcBEV^&e+f#t}C1=vGwR&u+c( z)g*7%g}sDE$?Cdf6>pR+j!}UJpaQe9O4Um0c5{d{M7j-D2+sP1GY2v*0O%6{AWoYd zKObctMGptH8lPu+Uuj#GeQ9JUG$H5^blt)4>KKBvk~sSkIXV8ky}x^NAuf*;6*sms zQ)3*@kAMcApX@~nHexw>Geg048?Zf}bDIrFSlEymdV>%^2%1O&3^>P157uj}*NVR6Ub_eJj4Wei9uER^Nda1u z6%n9uya|mNVGv<3zj&e!pbj`)9l&Lv4!mXPA^jgYG57eWA8OVQ-K0ame2DMb6?`2T zp${^``2O`vZ|7aeEoPzJ-_p_*`5pOPzxO(FKb5_;7g|%{p;6v}v(uG#w5@4dH%n@Z zpg^$$uicG##UX=@*qNgV)rM-f!5Ry3*3zb8QI6{K zID3tA90;k5Q)~8SXclXnF7i}Wq}nzt{`@;4zz7({?V(gmiOLAd$qZ*T(|imD7!1O2 zHeD{3edsK@RIW&;E(Y#1<$)uE0jnge4KbNFgoAGtQ_i198#q+0au%EoNEg`V8>kC4 zEJ4-*nmK$U3^1CIf3nOKU0Md)pQ^LL87mhYl(XOrkJMYy{}DQ4+6Dq=>@L(dY^KOy zccI=ZP1CV%ZYj23QE=8AWkJ|L*l@B!6k%gP!bX1eg|3mLs5HS1u-+`%?qmZJI@MO4 z>N+?}46IjgBa)i@Nm^YLF%&TrF^T$@QJ|kN(LAXtjr-4%2pSc(jHR}mMSe2aGN4+O z?i7M*Ij36tSE#zWcSm)MwTL7VSQ`XS{gflW8#n`Jy4)}S# zExF5=3=eXMDfP=iSp$hsiVzW;2u=i7?52+XOi|STiM-9mAMFV64-o-QY%WbMqOby`IMZy=5*0~V88aI3>CqZZpE;xK(~^Fk zu`>EnSj~R_YOufd-I)TIwsSvtkIG;A{XmqjFO*n9A*-5i7#OQ4Lc)GNln7NqS}d zSnQNMJ&}<{W4BV7Qy2|&r4l42h3>%sCPkVW_hXW;A~H|wt^ zmaigGdJGN!lhB1zcXDkpw5Hm}#;d$DO~@nU>B2^Orkg#$;0&DAz}XcGp0a9_Dp#M0 z^8ad*M~ch01NI*^0l|_3H5)H$5}u?h&q`0BYRLo8epzqBip$P(Gw8VU1FG%6Mg=IW*+(b$RuT-;;c|$>mKtn>S(BXY01^gT)JwTi_K8N(a(j9vC zPoBkIG+nI4a0 zTcY3$oPo0d0hJ4i^;oLO{NmHNUhk$k_U$fwMXxcoTUF4w8ZV?3X;(U_bG}5Ui$T6N z@)$S+XW&dZdueo>*Xr0M8zgNsM}v}2Ax$COMq&VG;0&B0*jyvn^ir@n&#QEbN5?U+ zu+^anv9f4eCpa4d&V&HbL1XqWA7Ue_FpM-gGhw5h)4!@hhsO7>UwS(tg)bMJ;md6! zLxVGL2F{W#NwgDbC$^#H^$=&jx%GeBE~Po};X}2nQ0)_1`K2=|nPwM8sq7Af#NV}> z2$pkJQJ0~zqpC=xfC52*pg>TdMz@=FxidWR=-AP*W6$+CrWL#O-lnar73|wZWaE{j zG&wUw_H$|-l-z|A%fTaa!OzaK@rwZz18B4DE_1lTV9=8=XSs@piSkZ%u=|rv9plWA z!Qk^J^e0wHz@vA!%ta1P^mO#})||Xs?tQx!|CjH7f@wRKrrJ zqIE6eKZo6Wa5jVy14iMkJUfiSZ|UqLZA}!-s1x!{+RG3&5H?y9HqbTDHPAKsu4^Q> zsz|>MMGWK;av7ELaWQZ1n#G<%s1{TUs&!&-=}&Bh6uMY9*F+;x9M2*-)@VJZsHN7q zn<8K zcw{EbLxdnUGldp)B?Dc|{&X=9l|7Sx#et>5lUme~s6p{f@vRf(NUhlkvEtMCFBC;C zrWA?b;Oy;=+(zdtx&LXi@kcuX{6j>56IWxC3n{@JxI4t15oekmLXMf2NDq@)a4Y_K zG%(a9%#DMoA1wSZoXS_HXwt4#VW=~^yq&{8$0?j~5c-&cnxq@N+0)4ia&sM8xI9n}3p=5|()1OR&>B^t`;zRBa zHsN!!Fgz5uWyay_GnW~*w@-KZj3GfFK_m;WOehsujzY=Vy1g!uhr^iHPtMT6cor__ z%V4o=J&l!P23D^6`pf{F>0WG!36+D&JRVv^sj0ozgVZyh$amh@O!xNI#PN>pm)b-I zsVTJ7SB`dnp7|?R}()CQHV%Edr+^tBJvfcD^u&gzut?8gUJ0_NXY6@xT^K~;3YvqMnXnHK5Gei>?u99 z%n)*6^tx)!Yct7Ad)b6$M&vRNt)X&x>@nM;5XlPt4XZmVE zr_b1N`OzD(-^5YwJcQcM$u9YyKRn#5pTE8QkAMB|r<=$1^Y>qGukT)8->sj2c=)=# zj{bi)Putt;_49Q5{J+2ZHhs8XKmY#ezt_+I{r>i8{ruhb=D%*X+nc}3uljKP@Q<6r z>hC~ali2@ua~Z!3@e=;+A{9f#|GfRGX|>_a=${^MzTezG75zgYD(yA8_x>W)an&l( zW=myTce8oe20!2aRs2$)AOHT#L)28r?n8{f&)$fH;Tt7qHYUC50LM`yVu72@MlAA= zzxh+VJ!|jR9r(}7yoU~+_Sh2xLcM>3Y|}zRjEzjXKLFGKV|yEc&;h=QCPe4MW%VlJ z^(^~bCzU}_R#cqgNIzj9nfQOD+3j@ib=$nDR_R2J!~_s$<0Kt7r#W_8)wnudABl%? zB$yu7c^}deZu{-hvMBmn14OEUZy^gnrD8u5b;#8uN}4n?N2C3++S!InQxG@30S^2* z>TN#KsC9v}GTo8^_H2Fn*(Di!Fqo~e8Jy9~Oo6el zde}c`rLqc??O4RQhA*0#`ye4rcANHR$XtFNAWfD_lQc7<&Wb9b95XVSnL2wjl-o2j zPu^Y;B7$DgIB53J%zSf^(hqxnYE=m67A^a4ZJ@sApGjl+)B(O}W~Q~6*ivi=^HCX} zy_q`ZbXZM_nue`EPnwz9W?3sN53-rrcJs8WKkq+3?%kR-h)7q9XPm3V)*JVkaCZtu VE`XYNwvXju!@a4R=`|;H{eO`lLx2DP literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-13433 b/test/fuzz/fuzz-network-parser/oss-fuzz-13433 new file mode 100644 index 0000000000000000000000000000000000000000..1aef8b7d83bd93df5dcc191efabeee598eb8ec7a GIT binary patch literal 29 ccma#{OD!qSFUpSP3XAY@^s_Ci$YFr90GG1~?EnA( literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-13888 b/test/fuzz/fuzz-network-parser/oss-fuzz-13888 new file mode 100644 index 0000000000000000000000000000000000000000..c75fcb4e8a932562412ddb05cc4349bf596cc6cb GIT binary patch literal 56 zcmXRaOXZ68O)N>yh-F~*vE}l}FD|iFwB-uREGj8Y%*m`uEXmBzvxQ1PrF|Wp0slA= A@c;k- literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-network-parser/oss-fuzz-15678 b/test/fuzz/fuzz-network-parser/oss-fuzz-15678 new file mode 100644 index 00000000..2a37d5f4 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/oss-fuzz-15678 @@ -0,0 +1,2 @@ +[IPv6AcceptRA] +BlackList=70:: 70:: \ No newline at end of file diff --git a/test/fuzz/fuzz-network-parser/routing-policy-rule.network b/test/fuzz/fuzz-network-parser/routing-policy-rule.network new file mode 100644 index 00000000..46b87c5a --- /dev/null +++ b/test/fuzz/fuzz-network-parser/routing-policy-rule.network @@ -0,0 +1,10 @@ +[Match] +Name=test1 + +[RoutingPolicyRule] +TypeOfService=0x08 +Table=7 +From= 192.168.100.18 +Priority=111 +IncomingInterface=test1 +OutgoingInterface=test1 diff --git a/test/fuzz/fuzz-network-parser/sit.network b/test/fuzz/fuzz-network-parser/sit.network new file mode 100644 index 00000000..84e5af0f --- /dev/null +++ b/test/fuzz/fuzz-network-parser/sit.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=sittun99 diff --git a/test/fuzz/fuzz-network-parser/test-static.network b/test/fuzz/fuzz-network-parser/test-static.network new file mode 100644 index 00000000..636c55c8 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/test-static.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +Address=192.168.0.15/24 +Gateway=192.168.0.1 diff --git a/test/fuzz/fuzz-network-parser/vti.network b/test/fuzz/fuzz-network-parser/vti.network new file mode 100644 index 00000000..7fbad6a8 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/vti.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=vtitun99 diff --git a/test/fuzz/fuzz-network-parser/vti6.network b/test/fuzz/fuzz-network-parser/vti6.network new file mode 100644 index 00000000..49a9d11f --- /dev/null +++ b/test/fuzz/fuzz-network-parser/vti6.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=vti6tun99 diff --git a/test/fuzz/fuzz-network-parser/vxlan.network b/test/fuzz/fuzz-network-parser/vxlan.network new file mode 100644 index 00000000..80b40557 --- /dev/null +++ b/test/fuzz/fuzz-network-parser/vxlan.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +VXLAN=vxlan99 diff --git a/test/fuzz/fuzz-nspawn-oci/basic.json b/test/fuzz/fuzz-nspawn-oci/basic.json new file mode 100644 index 00000000..f42739e0 --- /dev/null +++ b/test/fuzz/fuzz-nspawn-oci/basic.json @@ -0,0 +1,141 @@ +{ + "ociVersion": "1.0.0", + + "root": { + "path": "rootfs", + "readonly": true + }, + + "process": { + "terminal": false, + "consoleSize": { + "height":6667, + "width":6668 + }, + + "user": { + "uid": 14, + "gid": 14, + "additionalGids": [59, 81] + }, + + "args": [ + "/tmp/verify.sh" + ], + + "env": [ + "FOO=BAR", + "WITHSPACES=FOO BAR", + "WITHSHELLCHARS=$ASDF \\\"asdf asdf\\\" !", + "WITHCONTROLCHARS=\\123\\125\\010\\020", + "TERM=xterm" + ], + + "cwd": "/tmp/src", + + "rlimits": [ + { + "type": "RLIMIT_NOFILE", + "hard": 1020, + "soft": 1020 + } + ] + }, + + "mounts": [ + { + "destination": "/tmp/src", + "source": "src", + "options": ["ro"] + }, + + { + "destination": "/tmp/verify.sh", + "source": "verify.sh", + "options": ["ro"] + }, + + { + "destination": "/proc", + "type": "proc", + "source": "proc" + }, + { + "destination": "/dev", + "type": "tmpfs", + "source": "tmpfs", + "options": [ + "mode=777" + ] + }, + { + "destination": "/dev/pts", + "type": "devpts", + "source": "devpts", + "options": [ + "mode=777" + ] + }, + { + "destination": "/dev/shm", + "type": "tmpfs", + "source": "shm", + "options": [ + "mode=777" + ] + }, + { + "destination": "/dev/mqueue", + "type": "mqueue", + "source": "mqueue", + "options": [ + "mode=777" + ] + }, + { + "destination": "/sys", + "type": "sysfs", + "source": "sysfs", + "options": [ + "mode=777" + ] + }, + { + "destination": "/sys/fs/cgroup", + "type": "cgroup", + "source": "cgroup", + "options": [ + "mode=777" + ] + } + ], + + "hooks": {}, + + "linux": { + "resources": { + "devices": [ + { + "allow": false, + "access": "rwm" + } + ] + }, + "namespaces": [ + { + "type": "pid" + }, + { + "type": "ipc" + }, + { + "type": "mount" + } + ] + }, + + "annotations": { + "com.example.key1": "value1", + "com.example.key2": "value2" + } +} diff --git a/test/fuzz/fuzz-nspawn-oci/crash-bffbd2085d4e95c47e9749b3f4a2dbc0580c20d3 b/test/fuzz/fuzz-nspawn-oci/crash-bffbd2085d4e95c47e9749b3f4a2dbc0580c20d3 new file mode 100644 index 00000000..22e42d3b --- /dev/null +++ b/test/fuzz/fuzz-nspawn-oci/crash-bffbd2085d4e95c47e9749b3f4a2dbc0580c20d3 @@ -0,0 +1,5 @@ +{"ociVersion": "1.0.0", +"linux": {"devices": [ { "access": "mmmw;r"} +] }, "e": "}e" + } + \ No newline at end of file diff --git a/test/fuzz/fuzz-nspawn-oci/crash-db0595479ee2e625fa5419a821009b5eb4d809b7 b/test/fuzz/fuzz-nspawn-oci/crash-db0595479ee2e625fa5419a821009b5eb4d809b7 new file mode 100644 index 00000000..0bf017ce --- /dev/null +++ b/test/fuzz/fuzz-nspawn-oci/crash-db0595479ee2e625fa5419a821009b5eb4d809b7 @@ -0,0 +1,92 @@ +{ + "ociVersion": "1.0.0", + + "root": { + "path": "rootfs", + "readonly": true + }, + + "process": { + "terminal": false, + "consoleSize": { + "height":6667, + "width":6668 + }, + + "user": { + "uid": 14, + "gid": 14, + "additionalGids": [59, 81] + }, + + "args": [ + "/tmp/verify.sh" + ], + + "env": [ + "FOO=BAR", + "WITHSPACES=FOO BAR", + "WITHSHELLCHARS=$ASDF \\\"asdf asdf\\\" !", + "WITHCONTROLCHARS=\\123\\125\\010\\020", + "TERM=xterm" + ], + + "cwd": "/tmp/src", + + "rlimits": [ + { + "type": "RLIMIT_NOFILE", + "hard": 1020, + "soft": 1020 + } + ] + }, + + "mounts": [ + { + "destination": "/tmp/src" }, + { + "source": "sysfs", + "options": [ + "mode=777" + ] + }, + { + "destination": "/sys/fs/cgroup", + "type": "cgroup", + "source": "cgroup", + "options": [ + "mode=777" + ] + } + ], + + "hooks": {}, + + "linux": { + "resources": { + "devices": [ + { + "allow": false, + "access": "rwm" + } + ] + }, + "namespaces": [ + { + "type": "pid" + }, + { + "type": "ipc" + }, + { + "type": "mount" + } + ] + }, + + "annotations": { + "com.example.key1": "value1", + "com.example.key2": "value2" + } +} diff --git a/test/fuzz/fuzz-nspawn-settings/basic-config b/test/fuzz/fuzz-nspawn-settings/basic-config new file mode 100644 index 00000000..be0d4e7c --- /dev/null +++ b/test/fuzz/fuzz-nspawn-settings/basic-config @@ -0,0 +1,36 @@ +[Exec] +Boot=off +ProcessTwo=off +Parameters=/sbin/init -x=1 +Environment=THIS=that +User=user +WorkingDirectory=/cwd +PivotRoot=/newroot +Capability=CAP_NET +DropCapability=CAP_ADMIN +KillSignal=SIGTERM +Personality=shy +MachineID=edbfea3309ba41ea83e2318c58a8d498 +PrivateUser=1:2 +NotifyReady=no +SystemCallFilters=write + +[Files] +ReadOnly=no +Volatile=no +Bind=/bindthis +BindReadOnly=/bindthisro +TemporaryFileSystem=/thisismytmpfs:rw +Overlay=/thisisanoverlay:/thisisanoverlaytoo +PrivateUsersChown=no + +[Network] +Private=off +VirtualEthernet=yes +VirtualEthernetExtra=veth1:veth2 +Interface=eth1 enp0s1 +MacVLAN=eno1 eno2 +IPVLAN=eno3 enp2s124 +Bridge=bridge123 bridge125 +Zone=myzone +Port=1234 156 -1 diff --git a/test/fuzz/fuzz-nspawn-settings/leak-4ff0e2498f596a77ea68d185c61e9e9ff9bb657f b/test/fuzz/fuzz-nspawn-settings/leak-4ff0e2498f596a77ea68d185c61e9e9ff9bb657f new file mode 100644 index 0000000000000000000000000000000000000000..7be2d2c9da3b551d29207ecb280af51bd3585c8b GIT binary patch literal 133 zcmWlRF$%*l5CmOclb_fxP~$+_n2@9~E{^z&4-_rv4h#R@Qn#}VGY@?~EHnZhux&JD z{KV{C(C{{K=D$2Nx?~F_s|(RwS!|(~@cK;g3<>l_WUqJIqoy@Lal*kl^65aW Q>%lG`tF`-%lA2C*0S4JFU;qFB literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-nspawn-settings/oss-fuzz-13691 b/test/fuzz/fuzz-nspawn-settings/oss-fuzz-13691 new file mode 100644 index 00000000..51f46e37 --- /dev/null +++ b/test/fuzz/fuzz-nspawn-settings/oss-fuzz-13691 @@ -0,0 +1,2 @@ +[Files] +Overlay=/:: \ No newline at end of file diff --git a/test/fuzz/fuzz-udev-database/sample.txt b/test/fuzz/fuzz-udev-database/sample.txt new file mode 100644 index 00000000..041c6188 --- /dev/null +++ b/test/fuzz/fuzz-udev-database/sample.txt @@ -0,0 +1,500 @@ +E:ID_ATA=1 +E:ID_ATA_DOWNLOAD_MICROCODE=1 +E:ID_ATA_FEATURE_SET_HPA=1 +E:ID_ATA_FEATURE_SET_HPA_ENABLED=1 +E:ID_ATA_FEATURE_SET_PM=1 +E:ID_ATA_FEATURE_SET_PM_ENABLED=1 +E:ID_ATA_FEATURE_SET_SECURITY=1 +E:ID_ATA_FEATURE_SET_SECURITY_ENABLED=0 +E:ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN=8 +E:ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN=2 +E:ID_ATA_FEATURE_SET_SECURITY_FROZEN=1 +E:ID_ATA_FEATURE_SET_SMART=1 +E:ID_ATA_FEATURE_SET_SMART_ENABLED=1 +E:ID_ATA_ROTATION_RATE_RPM=0 +E:ID_ATA_SATA=1 +E:ID_ATA_SATA_SIGNAL_RATE_GEN1=1 +E:ID_ATA_SATA_SIGNAL_RATE_GEN2=1 +E:ID_ATA_WRITE_CACHE=1 +E:ID_ATA_WRITE_CACHE_ENABLED=1 +E:ID_BTRFS_READY=1 +E:ID_BUS=ata +E:ID_BUS=i8042 +E:ID_BUS=pci +E:ID_BUS=usb +E:ID_FOR_SEAT=drm-pci-0000_00_02_0 +E:ID_FOR_SEAT=graphics-pci-0000_00_02_0 +E:ID_FOR_SEAT=input-acpi-LNXVIDEO_00 +E:ID_FOR_SEAT=input-acpi-PNP0C0C_00 +E:ID_FOR_SEAT=input-acpi-PNP0C0D_00 +E:ID_FOR_SEAT=input-acpi-SNY5001_00 +E:ID_FOR_SEAT=input-pci-0000_00_03_0 +E:ID_FOR_SEAT=input-pci-0000_00_14_0-usb-0_5_1_0 +E:ID_FOR_SEAT=input-pci-0000_00_1b_0 +E:ID_FOR_SEAT=input-platform-i8042-serio-0 +E:ID_FOR_SEAT=input-platform-i8042-serio-1 +E:ID_FOR_SEAT=sound-pci-0000_00_03_0 +E:ID_FOR_SEAT=sound-pci-0000_00_1b_0 +E:ID_FOR_SEAT=usb-pci-0000_00_14_0 +E:ID_FOR_SEAT=usb-pci-0000_00_1d_0 +E:ID_FOR_SEAT=usb-pci-0000_00_1d_0-usb-0_1 +E:ID_FOR_SEAT=video4linux-pci-0000_00_14_0-usb-0_5_1_0 +E:ID_FS_LABEL_ENC=回復 +E:ID_FS_LABEL=回復 +E:ID_FS_TYPE= +E:ID_FS_TYPE=btrfs +E:ID_FS_TYPE=ext4 +E:ID_FS_TYPE=ntfs +E:ID_FS_TYPE=swap +E:ID_FS_TYPE=vfat +E:ID_FS_USAGE=filesystem +E:ID_FS_USAGE=other +E:ID_FS_UUID=0f12f260-d308-49b4-9a9f-465a749937ce +E:ID_FS_UUID=23451e06-2ec4-4ae0-86b1-36602653dd78 +E:ID_FS_UUID=5C1A-DCBA +E:ID_FS_UUID=64A41A20A419F570 +E:ID_FS_UUID=9C12322A123209B2 +E:ID_FS_UUID=b95e2a35-09fd-493f-9be7-5616eb9ffc19 +E:ID_FS_UUID=beeb37c6-d4e2-494f-b329-3eb27452e469 +E:ID_FS_UUID=D60878D80878B8D7 +E:ID_FS_UUID_ENC=0f12f260-d308-49b4-9a9f-465a749937ce +E:ID_FS_UUID_ENC=23451e06-2ec4-4ae0-86b1-36602653dd78 +E:ID_FS_UUID_ENC=5C1A-DCBA +E:ID_FS_UUID_ENC=64A41A20A419F570 +E:ID_FS_UUID_ENC=9C12322A123209B2 +E:ID_FS_UUID_ENC=b95e2a35-09fd-493f-9be7-5616eb9ffc19 +E:ID_FS_UUID_ENC=beeb37c6-d4e2-494f-b329-3eb27452e469 +E:ID_FS_UUID_ENC=D60878D80878B8D7 +E:ID_FS_UUID_SUB=7f4127d5-2d4f-48a4-81ff-ddd959f2d653 +E:ID_FS_UUID_SUB_ENC=7f4127d5-2d4f-48a4-81ff-ddd959f2d653 +E:ID_FS_VERSION=1 +E:ID_FS_VERSION=1.0 +E:ID_FS_VERSION=FAT32 +E:ID_INPUT=1 +E:ID_INPUT_HEIGHT_MM=52 +E:ID_INPUT_JOYSTICK=1 +E:ID_INPUT_KEY=1 +E:ID_INPUT_KEYBOARD=1 +E:ID_INPUT_MOUSE=1 +E:ID_INPUT_SWITCH=1 +E:ID_INPUT_TOUCHPAD=1 +E:ID_INPUT_TOUCHPAD_INTEGRATION=internal +E:ID_INPUT_WIDTH_MM=88 +E:ID_MODEL=07dc +E:ID_MODEL=8000 +E:ID_MODEL=EHCI_Host_Controller +E:ID_MODEL_ENC=07dc +E:ID_MODEL_ENC=8000 +E:ID_MODEL_ENC=EHCI\x20Host\x20Controller +E:ID_MODEL_ENC=Nexus\x205X +E:ID_MODEL_ENC=SAMSUNG\x20MZNTD256HAGL-00000\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20 +E:ID_MODEL_ENC=USB\x202.0\x20Camera +E:ID_MODEL_ENC=xHCI\x20Host\x20Controller +E:ID_MODEL_FROM_DATABASE=2.0 root hub +E:ID_MODEL_FROM_DATABASE=3.0 root hub +E:ID_MODEL_FROM_DATABASE=8 Series HD Audio Controller +E:ID_MODEL_FROM_DATABASE=8 Series HECI +E:ID_MODEL_FROM_DATABASE=8 Series LPC Controller +E:ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 3 +E:ID_MODEL_FROM_DATABASE=8 Series PCI Express Root Port 4 +E:ID_MODEL_FROM_DATABASE=8 Series SATA Controller 1 [AHCI mode] +E:ID_MODEL_FROM_DATABASE=8 Series SMBus Controller +E:ID_MODEL_FROM_DATABASE=8 Series USB EHCI +E:ID_MODEL_FROM_DATABASE=8 Series USB xHCI HC +E:ID_MODEL_FROM_DATABASE=Haswell-ULT DRAM Controller +E:ID_MODEL_FROM_DATABASE=Haswell-ULT HD Audio Controller +E:ID_MODEL_FROM_DATABASE=Haswell-ULT Integrated Graphics Controller +E:ID_MODEL_FROM_DATABASE=Nexus Device (MTP) +E:ID_MODEL_FROM_DATABASE=Wireless 7260 (Dual Band Wireless-N 7260) +E:ID_MODEL_ID=0002 +E:ID_MODEL_ID=0003 +E:ID_MODEL_ID=07dc +E:ID_MODEL_ID=0x08b1 +E:ID_MODEL_ID=0x0a0c +E:ID_MODEL_ID=0x9c20 +E:ID_MODEL_ID=4ee1 +E:ID_MODEL_ID=8000 +E:ID_MODEL_ID=b3be +E:ID_MODEL=Nexus_5X +E:ID_MODEL=SAMSUNG_MZNTD256HAGL-00000 +E:ID_MODEL=USB_2.0_Camera +E:ID_MODEL=xHCI_Host_Controller +E:ID_NET_DRIVER=bridge +E:ID_NET_DRIVER=iwlwifi +E:ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link +E:ID_NET_NAME_MAC=wlx00123456abcd +E:ID_NET_NAME_MAC=wlx5c514f1383eb +E:ID_NET_NAME_PATH=wlp1s0 +E:ID_NET_NAME=wlp1s0 +E:ID_NET_NAMING_SCHEME=v240 +E:ID_OUI_FROM_DATABASE=Intel Corporate +E:ID_PART_ENTRY_DISK=8:0 +E:ID_PART_ENTRY_FLAGS=0x1 +E:ID_PART_ENTRY_FLAGS=0x8000000000000001 +E:ID_PART_ENTRY_NAME=Basic\x20data\x20partition +E:ID_PART_ENTRY_NAME=EFI\x20System\x20Partition +E:ID_PART_ENTRY_NAME=Microsoft\x20reserved\x20partition +E:ID_PART_ENTRY_NUMBER=1 +E:ID_PART_ENTRY_NUMBER=2 +E:ID_PART_ENTRY_NUMBER=3 +E:ID_PART_ENTRY_NUMBER=4 +E:ID_PART_ENTRY_NUMBER=5 +E:ID_PART_ENTRY_NUMBER=6 +E:ID_PART_ENTRY_NUMBER=7 +E:ID_PART_ENTRY_NUMBER=8 +E:ID_PART_ENTRY_NUMBER=9 +E:ID_PART_ENTRY_OFFSET=1128448 +E:ID_PART_ENTRY_OFFSET=1161216 +E:ID_PART_ENTRY_OFFSET=132481024 +E:ID_PART_ENTRY_OFFSET=134219776 +E:ID_PART_ENTRY_OFFSET=135243776 +E:ID_PART_ENTRY_OFFSET=143372288 +E:ID_PART_ENTRY_OFFSET=2048 +E:ID_PART_ENTRY_OFFSET=248229888 +E:ID_PART_ENTRY_OFFSET=923648 +E:ID_PART_ENTRY_SCHEME=gpt +E:ID_PART_ENTRY_SIZE=1024000 +E:ID_PART_ENTRY_SIZE=104857600 +E:ID_PART_ENTRY_SIZE=131319561 +E:ID_PART_ENTRY_SIZE=1738752 +E:ID_PART_ENTRY_SIZE=204800 +E:ID_PART_ENTRY_SIZE=251887616 +E:ID_PART_ENTRY_SIZE=32768 +E:ID_PART_ENTRY_SIZE=8128512 +E:ID_PART_ENTRY_SIZE=921600 +E:ID_PART_ENTRY_TYPE=0657fd6d-a4ab-43c4-84e5-0933c84b4f4f +E:ID_PART_ENTRY_TYPE=0fc63daf-8483-4772-8e79-3d69d8477de4 +E:ID_PART_ENTRY_TYPE=c12a7328-f81f-11d2-ba4b-00a0c93ec93b +E:ID_PART_ENTRY_TYPE=de94bba4-06d1-4d40-a16a-bfd50179d6ac +E:ID_PART_ENTRY_TYPE=e3c9e316-0b5c-4db8-817d-f92df00215ae +E:ID_PART_ENTRY_TYPE=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 +E:ID_PART_ENTRY_UUID=1d655759-7350-4d1e-b679-ae54e599c796 +E:ID_PART_ENTRY_UUID=55202025-f2e2-4b92-9b4b-7fa16d804a35 +E:ID_PART_ENTRY_UUID=611ffa59-e1da-4e0c-8b7e-83dd61edf945 +E:ID_PART_ENTRY_UUID=9e241958-b22d-4813-8504-791d45cbf0bc +E:ID_PART_ENTRY_UUID=9ee3d84f-122d-4d5c-b62b-1006defbcbc1 +E:ID_PART_ENTRY_UUID=a4b0949c-5d61-499b-b336-592ef4e0d423 +E:ID_PART_ENTRY_UUID=b092dc67-d577-4c77-84c4-db681a69a200 +E:ID_PART_ENTRY_UUID=cc77a315-4305-4982-88e6-b52721460ce7 +E:ID_PART_ENTRY_UUID=f17bf199-921b-4cbd-bcbf-15b75ec80b21 +E:ID_PART_TABLE_TYPE=gpt +E:ID_PART_TABLE_UUID=130de398-eb17-4bac-8a19-fe2e64163e91 +E:ID_PATH=acpi-LNXVIDEO:00 +E:ID_PATH=acpi-PNP0C0C:00 +E:ID_PATH=acpi-PNP0C0D:00 +E:ID_PATH=acpi-SNY5001:00 +E:ID_PATH=pci-0000:00:02.0 +E:ID_PATH=pci-0000:00:03.0 +E:ID_PATH=pci-0000:00:14.0 +E:ID_PATH=pci-0000:00:14.0-usb-0:5:1.0 +E:ID_PATH=pci-0000:00:14.0-usb-0:6:1.0 +E:ID_PATH=pci-0000:00:1b.0 +E:ID_PATH=pci-0000:00:1d.0 +E:ID_PATH=pci-0000:00:1d.0-usb-0:1 +E:ID_PATH=pci-0000:00:1f.2-ata-4 +E:ID_PATH=pci-0000:01:00.0 +E:ID_PATH=platform-i8042-serio-0 +E:ID_PATH=platform-i8042-serio-1 +E:ID_PATH_TAG=acpi-LNXVIDEO_00 +E:ID_PATH_TAG=acpi-PNP0C0C_00 +E:ID_PATH_TAG=acpi-PNP0C0D_00 +E:ID_PATH_TAG=acpi-SNY5001_00 +E:ID_PATH_TAG=pci-0000_00_02_0 +E:ID_PATH_TAG=pci-0000_00_03_0 +E:ID_PATH_TAG=pci-0000_00_14_0 +E:ID_PATH_TAG=pci-0000_00_14_0-usb-0_5_1_0 +E:ID_PATH_TAG=pci-0000_00_14_0-usb-0_6_1_0 +E:ID_PATH_TAG=pci-0000_00_1b_0 +E:ID_PATH_TAG=pci-0000_00_1d_0 +E:ID_PATH_TAG=pci-0000_00_1d_0-usb-0_1 +E:ID_PATH_TAG=pci-0000_00_1f_2-ata-4 +E:ID_PATH_TAG=pci-0000_01_00_0 +E:ID_PATH_TAG=platform-i8042-serio-0 +E:ID_PATH_TAG=platform-i8042-serio-1 +E:ID_PCI_CLASS_FROM_DATABASE=Bridge +E:ID_PCI_CLASS_FROM_DATABASE=Communication controller +E:ID_PCI_CLASS_FROM_DATABASE=Display controller +E:ID_PCI_CLASS_FROM_DATABASE=Mass storage controller +E:ID_PCI_CLASS_FROM_DATABASE=Multimedia controller +E:ID_PCI_CLASS_FROM_DATABASE=Network controller +E:ID_PCI_CLASS_FROM_DATABASE=Serial bus controller +E:ID_PCI_INTERFACE_FROM_DATABASE=AHCI 1.0 +E:ID_PCI_INTERFACE_FROM_DATABASE=EHCI +E:ID_PCI_INTERFACE_FROM_DATABASE=Normal decode +E:ID_PCI_INTERFACE_FROM_DATABASE=VGA controller +E:ID_PCI_INTERFACE_FROM_DATABASE=XHCI +E:ID_PCI_SUBCLASS_FROM_DATABASE=Audio device +E:ID_PCI_SUBCLASS_FROM_DATABASE=Communication controller +E:ID_PCI_SUBCLASS_FROM_DATABASE=Host bridge +E:ID_PCI_SUBCLASS_FROM_DATABASE=ISA bridge +E:ID_PCI_SUBCLASS_FROM_DATABASE=Network controller +E:ID_PCI_SUBCLASS_FROM_DATABASE=PCI bridge +E:ID_PCI_SUBCLASS_FROM_DATABASE=SATA controller +E:ID_PCI_SUBCLASS_FROM_DATABASE=SMBus +E:ID_PCI_SUBCLASS_FROM_DATABASE=USB controller +E:ID_PCI_SUBCLASS_FROM_DATABASE=VGA compatible controller +E:ID_REVISION=0001 +E:ID_REVISION=0004 +E:ID_REVISION=0310 +E:ID_REVISION=0420 +E:ID_REVISION=5811 +E:ID_REVISION=DXT2300Q +E:ID_SERIAL=8087_07dc +E:ID_SERIAL=8087_8000 +E:ID_SERIAL=Chicony_Electronics_Co._Ltd._USB_2.0_Camera_0x0001 +E:ID_SERIAL=LGE_Nexus_5X_026442e0677ccae8 +E:ID_SERIAL=Linux_4.20.11-200.fc29.x86_64_ehci_hcd_EHCI_Host_Controller_0000:00:1d.0 +E:ID_SERIAL=Linux_4.20.11-200.fc29.x86_64_xhci-hcd_xHCI_Host_Controller_0000:00:14.0 +E:ID_SERIAL=noserial +E:ID_SERIAL=SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616 +E:ID_SERIAL_SHORT=0000:00:14.0 +E:ID_SERIAL_SHORT=0000:00:1d.0 +E:ID_SERIAL_SHORT=026442e0677ccae8 +E:ID_SERIAL_SHORT=0x0001 +E:ID_SERIAL_SHORT=S15ZNYAD408616 +E:ID_TYPE=disk +E:ID_TYPE=video +E:ID_USB_CLASS_FROM_DATABASE=Hub +E:ID_USB_CLASS_FROM_DATABASE=Miscellaneous Device +E:ID_USB_CLASS_FROM_DATABASE=Wireless +E:ID_USB_DRIVER=uvcvideo +E:ID_USB_INTERFACE_NUM=00 +E:ID_USB_INTERFACES=:090000: +E:ID_USB_INTERFACES=:0e0100:0e0200: +E:ID_USB_INTERFACES=:e00101: +E:ID_USB_INTERFACES=:ffff00: +E:ID_USB_PROTOCOL_FROM_DATABASE=Bluetooth +E:ID_USB_PROTOCOL_FROM_DATABASE=Full speed (or root) hub +E:ID_USB_PROTOCOL_FROM_DATABASE=Interface Association +E:ID_USB_PROTOCOL_FROM_DATABASE=Single TT +E:ID_USB_SUBCLASS_FROM_DATABASE=Radio Frequency +E:ID_V4L_CAPABILITIES=:capture: +E:ID_V4L_PRODUCT=USB 2.0 Camera: USB 2.0 Camera +E:ID_V4L_VERSION=2 +E:ID_VENDOR=8087 +E:ID_VENDOR=Chicony_Electronics_Co._Ltd. +E:ID_VENDOR_ENC=8087 +E:ID_VENDOR_ENC=Chicony\x20Electronics\x20Co.\x2cLtd. +E:ID_VENDOR_ENC=LGE +E:ID_VENDOR_ENC=Linux\x204.20.11-200.fc29.x86_64\x20ehci_hcd +E:ID_VENDOR_ENC=Linux\x204.20.11-200.fc29.x86_64\x20xhci-hcd +E:ID_VENDOR_FROM_DATABASE=Chicony Electronics Co., Ltd +E:ID_VENDOR_FROM_DATABASE=Google Inc. +E:ID_VENDOR_FROM_DATABASE=Intel Corp. +E:ID_VENDOR_FROM_DATABASE=Intel Corporation +E:ID_VENDOR_FROM_DATABASE=Linux Foundation +E:ID_VENDOR_FROM_DATABASE=NXP Semiconductors bv. +E:ID_VENDOR_FROM_DATABASE=The Linux Foundation +E:ID_VENDOR_ID=04f2 +E:ID_VENDOR_ID=0x8086 +E:ID_VENDOR_ID=18d1 +E:ID_VENDOR_ID=1d6b +E:ID_VENDOR_ID=8087 +E:ID_VENDOR=LGE +E:ID_VENDOR=Linux_4.20.11-200.fc29.x86_64_ehci_hcd +E:ID_VENDOR=Linux_4.20.11-200.fc29.x86_64_xhci-hcd +E:ID_WWN=0x500253850002aca7 +E:ID_WWN_WITH_EXTENSION=0x500253850002aca7 +E:KEYBOARD_KEY_06=mute +E:KEYBOARD_KEY_07=volumedown +E:KEYBOARD_KEY_08=volumeup +E:KEYBOARD_KEY_09=brightnessdown +E:KEYBOARD_KEY_0a=brightnessup +E:KEYBOARD_KEY_0b=switchvideomode +E:KEYBOARD_KEY_0e=zoom +E:KEYBOARD_KEY_10=suspend +E:LIBINPUT_DEVICE_GROUP= +E:LIBINPUT_DEVICE_GROUP=0/0/0:ALSA +E:LIBINPUT_DEVICE_GROUP=11/1/1:isa0060/serio0 +E:LIBINPUT_DEVICE_GROUP=11/2/7:isa0060/serio1 +E:LIBINPUT_DEVICE_GROUP=19/0/1:PNP0C0C/button +E:LIBINPUT_DEVICE_GROUP=19/0/6:LNXVIDEO/video +E:LIBINPUT_DEVICE_GROUP=3/4f2/b3be:usb-0000:00:14.0-5/button +E:SOUND_FORM_FACTOR=internal +E:SOUND_INITIALIZED=1 +E:SYSTEMD_ALIAS=/sys/subsystem/bluetooth/devices/hci0 +E:SYSTEMD_ALIAS=/sys/subsystem/net/devices/docker0 +E:SYSTEMD_ALIAS=/sys/subsystem/net/devices/wlp1s0 /sys/subsystem/net/devices/wlp1s0 +E:SYSTEMD_RFKILL=1 +E:SYSTEMD_WANTS=bluetooth.target +E:SYSTEMD_WANTS=sound.target +E:SYSTEMD_WANTS=sys-kernel-config.mount +E:SYSTEMD_WANTS=systemd-backlight@backlight:intel_backlight.service +E:SYSTEMD_WANTS=systemd-rfkill.socket +G:master-of-seat +G:power-switch +G:seat +G:systemd +G:uaccess +I:10305698 +I:10395221 +I:10782777 +I:10810535 +I:11197034 +I:11264776 +I:11840274 +I:11863672 +I:11921972 +I:12272821 +I:124311058 +I:124356828 +I:12608364 +I:12651337 +I:12666911 +I:12717449 +I:12737331 +I:12824659 +I:13034589 +I:13446543 +I:16700949 +I:16848532 +I:16854530 +I:16854680 +I:16943840 +I:17041135 +I:17125002 +I:17310738 +I:17346430 +I:17447492 +I:17523623 +I:17918119 +I:17925442 +I:18121723 +I:18140865 +I:18291271 +I:18306009 +I:18313790 +I:18351304 +I:18357657 +I:18398601 +I:18598995 +I:18618482 +I:18712164 +I:18723922 +I:18735577 +I:18740647 +I:18788491 +I:18944489 +I:19057658 +I:19100102 +I:19137360 +I:19562855 +I:19766580 +I:20762981 +I:20781206 +I:20800551 +I:20849301 +I:20875108 +I:20952531 +I:20973791 +I:5594028 +I:6515738 +I:8368250 +I:8459962 +I:8528809 +I:8529967 +I:8586056 +I:8593736 +I:8914299 +I:9003355 +I:9037102 +I:9042481 +I:9057797 +I:9117477 +I:9120365 +I:9208582 +I:9209296 +I:9244279 +I:9250754 +I:9257625 +I:9258871 +I:9317204 +I:9347715 +I:9358092 +I:9380474 +I:9450065 +I:9484613 +I:9495455 +I:9551757 +I:9706931 +I:9749967 +I:9876257 +L:-100 +S:disk/by-id/ata-SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616 +S:disk/by-id/ata-SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616-part1 +S:disk/by-id/ata-SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616-part2 +S:disk/by-id/ata-SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616-part3 +S:disk/by-id/ata-SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616-part4 +S:disk/by-id/ata-SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616-part5 +S:disk/by-id/ata-SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616-part6 +S:disk/by-id/ata-SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616-part7 +S:disk/by-id/ata-SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616-part8 +S:disk/by-id/ata-SAMSUNG_MZNTD256HAGL-00000_S15ZNYAD408616-part9 +S:disk/by-id/wwn-0x500253850002aca7 +S:disk/by-id/wwn-0x500253850002aca7-part1 +S:disk/by-id/wwn-0x500253850002aca7-part2 +S:disk/by-id/wwn-0x500253850002aca7-part3 +S:disk/by-id/wwn-0x500253850002aca7-part4 +S:disk/by-id/wwn-0x500253850002aca7-part5 +S:disk/by-id/wwn-0x500253850002aca7-part6 +S:disk/by-id/wwn-0x500253850002aca7-part7 +S:disk/by-id/wwn-0x500253850002aca7-part8 +S:disk/by-id/wwn-0x500253850002aca7-part9 +S:disk/by-label/回復 +S:disk/by-partlabel/Basic\x20data\x20partition +S:disk/by-partlabel/EFI\x20System\x20Partition +S:disk/by-partlabel/Microsoft\x20reserved\x20partition +S:disk/by-partuuid/1d655759-7350-4d1e-b679-ae54e599c796 +S:disk/by-partuuid/55202025-f2e2-4b92-9b4b-7fa16d804a35 +S:disk/by-partuuid/611ffa59-e1da-4e0c-8b7e-83dd61edf945 +S:disk/by-partuuid/9e241958-b22d-4813-8504-791d45cbf0bc +S:disk/by-partuuid/9ee3d84f-122d-4d5c-b62b-1006defbcbc1 +S:disk/by-partuuid/a4b0949c-5d61-499b-b336-592ef4e0d423 +S:disk/by-partuuid/b092dc67-d577-4c77-84c4-db681a69a200 +S:disk/by-partuuid/cc77a315-4305-4982-88e6-b52721460ce7 +S:disk/by-partuuid/f17bf199-921b-4cbd-bcbf-15b75ec80b21 +S:disk/by-path/pci-0000:00:1f.2-ata-4 +S:disk/by-path/pci-0000:00:1f.2-ata-4-part1 +S:disk/by-path/pci-0000:00:1f.2-ata-4-part2 +S:disk/by-path/pci-0000:00:1f.2-ata-4-part3 +S:disk/by-path/pci-0000:00:1f.2-ata-4-part4 +S:disk/by-path/pci-0000:00:1f.2-ata-4-part5 +S:disk/by-path/pci-0000:00:1f.2-ata-4-part6 +S:disk/by-path/pci-0000:00:1f.2-ata-4-part7 +S:disk/by-path/pci-0000:00:1f.2-ata-4-part8 +S:disk/by-path/pci-0000:00:1f.2-ata-4-part9 +S:disk/by-uuid/0f12f260-d308-49b4-9a9f-465a749937ce +S:disk/by-uuid/23451e06-2ec4-4ae0-86b1-36602653dd78 +S:disk/by-uuid/5C1A-DCBA +S:disk/by-uuid/64A41A20A419F570 +S:disk/by-uuid/9C12322A123209B2 +S:disk/by-uuid/b95e2a35-09fd-493f-9be7-5616eb9ffc19 +S:disk/by-uuid/beeb37c6-d4e2-494f-b329-3eb27452e469 +S:disk/by-uuid/D60878D80878B8D7 +S:dri/by-path/pci-0000:00:02.0-card +S:dri/by-path/pci-0000:00:02.0-render +S:input/by-id/usb-Chicony_Electronics_Co._Ltd._USB_2.0_Camera_0x0001-event-if00 +S:input/by-path/acpi-SNY5001:00-event-joystick +S:input/by-path/acpi-SNY5001:00-event-mouse +S:input/by-path/acpi-SNY5001:00-mouse +S:input/by-path/pci-0000:00:14.0-usb-0:5:1.0-event +S:input/by-path/platform-i8042-serio-0-event-kbd +S:input/by-path/platform-i8042-serio-1-event-mouse +S:input/by-path/platform-i8042-serio-1-mouse +S:rtc +S:snd/by-path/pci-0000:00:03.0 +S:snd/by-path/pci-0000:00:1b.0 +S:v4l/by-id/usb-Chicony_Electronics_Co._Ltd._USB_2.0_Camera_0x0001-video-index0 +S:v4l/by-id/usb-Chicony_Electronics_Co._Ltd._USB_2.0_Camera_0x0001-video-index1 +S:v4l/by-path/pci-0000:00:14.0-usb-0:5:1.0-video-index0 +S:v4l/by-path/pci-0000:00:14.0-usb-0:5:1.0-video-index1 +W:1 +W:10 +W:2 +W:3 +W:4 +W:5 +W:6 +W:7 +W:8 +W:9 diff --git a/test/fuzz/fuzz-udev-rules/50-udev-default.rules b/test/fuzz/fuzz-udev-rules/50-udev-default.rules new file mode 100644 index 00000000..8e06c133 --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/50-udev-default.rules @@ -0,0 +1,86 @@ +# do not edit this file, it will be overwritten on update + +# run a command on remove events +ACTION=="remove", ENV{REMOVE_CMD}!="", RUN+="$env{REMOVE_CMD}" +ACTION=="remove", GOTO="default_end" + +SUBSYSTEM=="virtio-ports", KERNEL=="vport*", ATTR{name}=="?*", SYMLINK+="virtio-ports/$attr{name}" + +# select "system RTC" or just use the first one +SUBSYSTEM=="rtc", ATTR{hctosys}=="1", SYMLINK+="rtc" +SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100" + +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" +ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}" + +ACTION!="add", GOTO="default_end" + +SUBSYSTEM=="tty", KERNEL=="ptmx", GROUP="tty", MODE="0666" +SUBSYSTEM=="tty", KERNEL=="tty", GROUP="tty", MODE="0666" +SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0620" +SUBSYSTEM=="tty", KERNEL=="sclp_line[0-9]*", GROUP="tty", MODE="0620" +SUBSYSTEM=="tty", KERNEL=="ttysclp[0-9]*", GROUP="tty", MODE="0620" +SUBSYSTEM=="tty", KERNEL=="3270/tty[0-9]*", GROUP="tty", MODE="0620" +SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", GROUP="tty" +KERNEL=="tty[A-Z]*[0-9]|ttymxc[0-9]*|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout" + +SUBSYSTEM=="mem", KERNEL=="mem|kmem|port", GROUP="kmem", MODE="0640" + +SUBSYSTEM=="input", GROUP="input" +SUBSYSTEM=="input", KERNEL=="js[0-9]*", MODE="0664" + +SUBSYSTEM=="video4linux", GROUP="video" +SUBSYSTEM=="graphics", GROUP="video" +SUBSYSTEM=="drm", KERNEL!="renderD*", GROUP="video" +SUBSYSTEM=="dvb", GROUP="video" +SUBSYSTEM=="media", GROUP="video" +SUBSYSTEM=="cec", GROUP="video" + +SUBSYSTEM=="drm", KERNEL=="renderD*", GROUP="render", MODE="0666" +SUBSYSTEM=="kfd", GROUP="render", MODE="0666" + +SUBSYSTEM=="sound", GROUP="audio", \ + OPTIONS+="static_node=snd/seq", OPTIONS+="static_node=snd/timer" + +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", MODE="0664" + +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x00010*", GROUP="video" +SUBSYSTEM=="firewire", ATTR{units}=="*0x00b09d:0x00010*", GROUP="video" +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x010001*", GROUP="video" +SUBSYSTEM=="firewire", ATTR{units}=="*0x00a02d:0x014001*", GROUP="video" + +KERNEL=="parport[0-9]*", GROUP="lp" +SUBSYSTEM=="printer", KERNEL=="lp*", GROUP="lp" +SUBSYSTEM=="ppdev", GROUP="lp" +KERNEL=="lp[0-9]*", GROUP="lp" +KERNEL=="irlpt[0-9]*", GROUP="lp" +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", GROUP="lp" + +SUBSYSTEM=="block", GROUP="disk" +SUBSYSTEM=="block", KERNEL=="sr[0-9]*", GROUP="cdrom" +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", GROUP="cdrom" +KERNEL=="sch[0-9]*", GROUP="cdrom" +KERNEL=="pktcdvd[0-9]*", GROUP="cdrom" +KERNEL=="pktcdvd", GROUP="cdrom" + +SUBSYSTEM=="scsi_generic|scsi_tape", SUBSYSTEMS=="scsi", ATTRS{type}=="1|8", GROUP="tape" +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="0", GROUP="disk" +KERNEL=="qft[0-9]*|nqft[0-9]*|zqft[0-9]*|nzqft[0-9]*|rawqft[0-9]*|nrawqft[0-9]*", GROUP="disk" +KERNEL=="loop-control", GROUP="disk", OPTIONS+="static_node=loop-control" +KERNEL=="btrfs-control", GROUP="disk" +KERNEL=="rawctl", GROUP="disk" +SUBSYSTEM=="raw", KERNEL=="raw[0-9]*", GROUP="disk" +SUBSYSTEM=="aoe", GROUP="disk", MODE="0220" +SUBSYSTEM=="aoe", KERNEL=="err", MODE="0440" + +KERNEL=="rfkill", MODE="0664" +KERNEL=="tun", MODE="0666", OPTIONS+="static_node=net/tun" + +KERNEL=="fuse", MODE="0666", OPTIONS+="static_node=fuse" + +# The static_node is required on s390x and ppc (they are using MODULE_ALIAS) +KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm" + +SUBSYSTEM=="ptp", ATTR{clock_name}=="KVM virtual PTP", SYMLINK += "ptp_kvm" + +LABEL="default_end" diff --git a/test/fuzz/fuzz-udev-rules/60-block.rules b/test/fuzz/fuzz-udev-rules/60-block.rules new file mode 100644 index 00000000..343fc06f --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-block.rules @@ -0,0 +1,11 @@ +# do not edit this file, it will be overwritten on update + +# enable in-kernel media-presence polling +ACTION=="add", SUBSYSTEM=="module", KERNEL=="block", ATTR{parameters/events_dfl_poll_msecs}=="0", \ + ATTR{parameters/events_dfl_poll_msecs}="2000" + +# forward scsi device event to corresponding block device +ACTION=="change", SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST=="block", ATTR{block/*/uevent}="change" + +# watch metadata changes, caused by tools closing the device node which was opened for writing +ACTION!="remove", SUBSYSTEM=="block", KERNEL=="loop*|nvme*|sd*|vd*|xvd*|pmem*|mmcblk*", OPTIONS+="watch" diff --git a/test/fuzz/fuzz-udev-rules/60-cdrom_id.rules b/test/fuzz/fuzz-udev-rules/60-cdrom_id.rules new file mode 100644 index 00000000..288f8ce2 --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-cdrom_id.rules @@ -0,0 +1,29 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="cdrom_end" +SUBSYSTEM!="block", GOTO="cdrom_end" +KERNEL!="sr[0-9]*|vdisk*|xvd*", GOTO="cdrom_end" +ENV{DEVTYPE}!="disk", GOTO="cdrom_end" + +# unconditionally tag device as CDROM +KERNEL=="sr[0-9]*", ENV{ID_CDROM}="1" + +# stop automatically any mount units bound to the device if the media eject +# button is pressed. +ENV{ID_CDROM}=="1", ENV{SYSTEMD_MOUNT_DEVICE_BOUND}="1" + +# media eject button pressed +ENV{DISK_EJECT_REQUEST}=="?*", RUN+="cdrom_id --eject-media $devnode", GOTO="cdrom_end" + +# import device and media properties and lock tray to +# enable the receiving of media eject button events +IMPORT{program}="cdrom_id --lock-media $devnode" + +# ejecting a CD does not remove the device node, so mark the systemd device +# unit as inactive while there is no medium; this automatically cleans up of +# stale mounts after ejecting +ENV{DISK_MEDIA_CHANGE}=="?*", ENV{ID_CDROM_MEDIA}!="?*", ENV{SYSTEMD_READY}="0" + +KERNEL=="sr0", SYMLINK+="cdrom", OPTIONS+="link_priority=-100" + +LABEL="cdrom_end" diff --git a/test/fuzz/fuzz-udev-rules/60-drm.rules b/test/fuzz/fuzz-udev-rules/60-drm.rules new file mode 100644 index 00000000..f7f3435d --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-drm.rules @@ -0,0 +1,8 @@ +# do not edit this file, it will be overwritten on update + +ACTION!="remove", SUBSYSTEM=="drm", SUBSYSTEMS=="pci|usb|platform", IMPORT{builtin}="path_id" + +# by-path +ENV{ID_PATH}=="?*", KERNEL=="card*", SYMLINK+="dri/by-path/$env{ID_PATH}-card" +ENV{ID_PATH}=="?*", KERNEL=="controlD*", SYMLINK+="dri/by-path/$env{ID_PATH}-control" +ENV{ID_PATH}=="?*", KERNEL=="renderD*", SYMLINK+="dri/by-path/$env{ID_PATH}-render" diff --git a/test/fuzz/fuzz-udev-rules/60-evdev.rules b/test/fuzz/fuzz-udev-rules/60-evdev.rules new file mode 100644 index 00000000..e5e608ac --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-evdev.rules @@ -0,0 +1,23 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="evdev_end" +KERNEL!="event*", GOTO="evdev_end" + +# skip later rules when we find something for this input device +IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \ + RUN{builtin}+="keyboard", GOTO="evdev_end" + +# AT keyboard matching by the machine's DMI data +DRIVERS=="atkbd", \ + IMPORT{builtin}="hwdb 'evdev:atkbd:$attr{[dmi/id]modalias}'", \ + RUN{builtin}+="keyboard", GOTO="evdev_end" + +# device matching the input device name + properties + the machine's DMI data +KERNELS=="input*", IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:phys:$attr{phys}:ev:$attr{capabilities/ev}:$attr{[dmi/id]modalias}'", \ + RUN{builtin}+="keyboard", GOTO="evdev_end" + +# device matching the input device name and the machine's DMI data +KERNELS=="input*", IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:$attr{[dmi/id]modalias}'", \ + RUN{builtin}+="keyboard", GOTO="evdev_end" + +LABEL="evdev_end" diff --git a/test/fuzz/fuzz-udev-rules/60-input-id.rules b/test/fuzz/fuzz-udev-rules/60-input-id.rules new file mode 100644 index 00000000..bb8a812d --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-input-id.rules @@ -0,0 +1,8 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="id_input_end" + +SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id" +SUBSYSTEM=="input", IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=id-input:modalias:" + +LABEL="id_input_end" diff --git a/test/fuzz/fuzz-udev-rules/60-persistent-alsa.rules b/test/fuzz/fuzz-udev-rules/60-persistent-alsa.rules new file mode 100644 index 00000000..8154e2db --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-persistent-alsa.rules @@ -0,0 +1,14 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="persistent_alsa_end" +SUBSYSTEM!="sound", GOTO="persistent_alsa_end" +KERNEL!="controlC[0-9]*", GOTO="persistent_alsa_end" + +SUBSYSTEMS=="usb", ENV{ID_MODEL}=="", IMPORT{builtin}="usb_id" +ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", SYMLINK+="snd/by-id/$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}" +ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", SYMLINK+="snd/by-id/$env{ID_BUS}-$env{ID_SERIAL}" + +IMPORT{builtin}="path_id" +ENV{ID_PATH}=="?*", SYMLINK+="snd/by-path/$env{ID_PATH}" + +LABEL="persistent_alsa_end" diff --git a/test/fuzz/fuzz-udev-rules/60-persistent-input.rules b/test/fuzz/fuzz-udev-rules/60-persistent-input.rules new file mode 100644 index 00000000..255547d9 --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-persistent-input.rules @@ -0,0 +1,42 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="persistent_input_end" +SUBSYSTEM!="input", GOTO="persistent_input_end" +SUBSYSTEMS=="bluetooth", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end" +# Bluetooth devices don't always have the bluetooth subsystem +ATTRS{id/bustype}=="0005", ENV{ID_BUS}="bluetooth", GOTO="persistent_input_end" +SUBSYSTEMS=="rmi4", ENV{ID_BUS}="rmi" +SUBSYSTEMS=="serio", ENV{ID_BUS}="i8042" + +SUBSYSTEMS=="usb", ENV{ID_BUS}=="", IMPORT{builtin}="usb_id" + +# determine class name for persistent symlinks +ENV{ID_INPUT_KEYBOARD}=="?*", ENV{.INPUT_CLASS}="kbd" +ENV{ID_INPUT_MOUSE}=="?*", ENV{.INPUT_CLASS}="mouse" +ENV{ID_INPUT_TOUCHPAD}=="?*", ENV{.INPUT_CLASS}="mouse" +ENV{ID_INPUT_TABLET}=="?*", ENV{.INPUT_CLASS}="mouse" +ENV{ID_INPUT_JOYSTICK}=="?*", ENV{.INPUT_CLASS}="joystick" +DRIVERS=="pcspkr", ENV{.INPUT_CLASS}="spkr" +ATTRS{name}=="*dvb*|*DVB*|* IR *", ENV{.INPUT_CLASS}="ir" + +# fill empty serial number +ENV{.INPUT_CLASS}=="?*", ENV{ID_SERIAL}=="", ENV{ID_SERIAL}="noserial" + +# by-id links +KERNEL=="mouse*|js*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="|00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-$env{.INPUT_CLASS}" +KERNEL=="mouse*|js*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="?*", ATTRS{bInterfaceNumber}!="00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$attr{bInterfaceNumber}-$env{.INPUT_CLASS}" +KERNEL=="event*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="|00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-event-$env{.INPUT_CLASS}" +KERNEL=="event*", ENV{ID_BUS}=="?*", ENV{.INPUT_CLASS}=="?*", ATTRS{bInterfaceNumber}=="?*", ATTRS{bInterfaceNumber}!="00", SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$attr{bInterfaceNumber}-event-$env{.INPUT_CLASS}" +# allow empty class for USB devices, by appending the interface number +SUBSYSTEMS=="usb", ENV{ID_BUS}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="", ATTRS{bInterfaceNumber}=="?*", \ + SYMLINK+="input/by-id/$env{ID_BUS}-$env{ID_SERIAL}-event-if$attr{bInterfaceNumber}" + +# by-path +SUBSYSTEMS=="pci|usb|platform|acpi", IMPORT{builtin}="path_id" +ENV{ID_PATH}=="?*", KERNEL=="mouse*|js*", ENV{.INPUT_CLASS}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-$env{.INPUT_CLASS}" +ENV{ID_PATH}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-event-$env{.INPUT_CLASS}" +# allow empty class for platform and usb devices; platform supports only a single interface that way +SUBSYSTEMS=="usb|platform", ENV{ID_PATH}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="", \ + SYMLINK+="input/by-path/$env{ID_PATH}-event" + +LABEL="persistent_input_end" diff --git a/test/fuzz/fuzz-udev-rules/60-persistent-storage-tape.rules b/test/fuzz/fuzz-udev-rules/60-persistent-storage-tape.rules new file mode 100644 index 00000000..0136140a --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-persistent-storage-tape.rules @@ -0,0 +1,36 @@ +# do not edit this file, it will be overwritten on update + +# persistent storage links: /dev/tape/{by-id,by-path} + +ACTION=="remove", GOTO="persistent_storage_tape_end" +ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="persistent_storage_tape_end" + +# type 8 devices are "Medium Changers" +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{program}="scsi_id --sg-version=3 --export --whitelisted -d $devnode", \ + SYMLINK+="tape/by-id/scsi-$env{ID_SERIAL}" + +# iSCSI devices from the same host have all the same ID_SERIAL, +# but additionally a property named ID_SCSI_SERIAL. +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", ENV{ID_SCSI_SERIAL}=="?*", \ + SYMLINK+="tape/by-id/scsi-$env{ID_SCSI_SERIAL}" + +SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{builtin}="path_id", \ + SYMLINK+="tape/by-path/$env{ID_PATH}-changer" + +SUBSYSTEM!="scsi_tape", GOTO="persistent_storage_tape_end" + +KERNEL=="st*[0-9]|nst*[0-9]", ATTRS{ieee1394_id}=="?*", ENV{ID_SERIAL}="$attr{ieee1394_id}", ENV{ID_BUS}="ieee1394" +KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" +KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", KERNELS=="[0-9]*:*[0-9]", ENV{.BSG_DEV}="$root/bsg/$id" +KERNEL=="st*[0-9]|nst*[0-9]", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --whitelisted --export --device=$env{.BSG_DEV}", ENV{ID_BUS}="scsi" +KERNEL=="st*[0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SERIAL}" +KERNEL=="st*[0-9]", ENV{ID_SCSI_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SCSI_SERIAL}" +KERNEL=="nst*[0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SERIAL}-nst" +KERNEL=="nst*[0-9]", ENV{ID_SCSI_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS}-$env{ID_SCSI_SERIAL}-nst" + +# by-path (parent device path) +KERNEL=="st*[0-9]|nst*[0-9]", IMPORT{builtin}="path_id" +KERNEL=="st*[0-9]", ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}" +KERNEL=="nst*[0-9]", ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}-nst" + +LABEL="persistent_storage_tape_end" diff --git a/test/fuzz/fuzz-udev-rules/60-persistent-storage.rules b/test/fuzz/fuzz-udev-rules/60-persistent-storage.rules new file mode 100644 index 00000000..1d8880ef --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-persistent-storage.rules @@ -0,0 +1,109 @@ +# do not edit this file, it will be overwritten on update + +# persistent storage links: /dev/disk/{by-id,by-uuid,by-label,by-path} +# scheme based on "Linux persistent device names", 2004, Hannes Reinecke + +ACTION=="remove", GOTO="persistent_storage_end" +ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="persistent_storage_end" + +SUBSYSTEM!="block", GOTO="persistent_storage_end" +KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*|scm*|pmem*|nbd*|zd*", GOTO="persistent_storage_end" + +# ignore partitions that span the entire disk +TEST=="whole_disk", GOTO="persistent_storage_end" + +# for partitions import parent information +ENV{DEVTYPE}=="partition", IMPORT{parent}="ID_*" + +# NVMe +KERNEL=="nvme*[0-9]n*[0-9]", ATTR{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}" +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{wwid}=="?*", SYMLINK+="disk/by-id/nvme-$attr{wwid}-part%n" + +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}" +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{wwid}=="?*", ENV{ID_WWN}="$attr{wwid}" +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}" +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{firmware_rev}=="?*", ENV{ID_REVISION}="$attr{firmware_rev}" +KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \ + ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}" + +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}" +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}" +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{firmware_rev}=="?*", ENV{ID_REVISION}="$attr{firmware_rev}" +KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", \ + ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n" + +# virtio-blk +KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}" +KERNEL=="vd*[0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}-part%n" + +# ATA +KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", IMPORT{program}="ata_id --export $devnode" + +# ATAPI devices (SPC-3 or later) +KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{type}=="5", ATTRS{scsi_level}=="[6-9]*", IMPORT{program}="ata_id --export $devnode" + +# Run ata_id on non-removable USB Mass Storage (SATA/PATA disks in enclosures) +KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", ATTR{removable}=="0", SUBSYSTEMS=="usb", IMPORT{program}="ata_id --export $devnode" + +# Fall back usb_id for USB devices +KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" + +# SCSI devices +KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_BUS}="scsi" +KERNEL=="cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $devnode", ENV{ID_BUS}="cciss" +KERNEL=="sd*|sr*|cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}" +KERNEL=="sd*|cciss*", ENV{DEVTYPE}=="partition", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}-part%n" + +# PMEM devices +KERNEL=="pmem*", ENV{DEVTYPE}=="disk", ATTRS{uuid}=="?*", SYMLINK+="disk/by-id/pmem-$attr{uuid}" + +# FireWire +KERNEL=="sd*[!0-9]|sr*", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}" +KERNEL=="sd*[0-9]", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}-part%n" + +# MMC +KERNEL=="mmcblk[0-9]", SUBSYSTEMS=="mmc", ATTRS{name}=="?*", ATTRS{serial}=="?*", \ + ENV{ID_NAME}="$attr{name}", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}" +KERNEL=="mmcblk[0-9]p[0-9]*", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}-part%n" + +# UBI-MTD +SUBSYSTEM=="ubi", KERNEL=="ubi*_*", ATTRS{mtd_num}=="*", SYMLINK+="ubi_mtd%s{mtd_num}_%s{name}" + +# Memstick +KERNEL=="msblk[0-9]|mspblk[0-9]", SUBSYSTEMS=="memstick", ATTRS{name}=="?*", ATTRS{serial}=="?*", \ + ENV{ID_NAME}="$attr{name}", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/memstick-$env{ID_NAME}_$env{ID_SERIAL}" +KERNEL=="msblk[0-9]p[0-9]|mspblk[0-9]p[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/memstick-$env{ID_NAME}_$env{ID_SERIAL}-part%n" + +# by-path +ENV{DEVTYPE}=="disk", DEVPATH!="*/virtual/*", IMPORT{builtin}="path_id" +KERNEL=="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-boot%n" +KERNEL!="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}" +ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n" + +# legacy virtio-pci by-path links (deprecated) +KERNEL=="vd*[!0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}" +KERNEL=="vd*[0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}-part%n" + +# probe filesystem metadata of optical drives which have a media inserted +KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="?*", \ + IMPORT{builtin}="blkid --offset=$env{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}" +# single-session CDs do not have ID_CDROM_MEDIA_SESSION_LAST_OFFSET +KERNEL=="sr*", ENV{DISK_EJECT_REQUEST}!="?*", ENV{ID_CDROM_MEDIA_TRACK_COUNT_DATA}=="?*", ENV{ID_CDROM_MEDIA_SESSION_LAST_OFFSET}=="", \ + IMPORT{builtin}="blkid --noraid" + +# probe filesystem metadata of disks +KERNEL!="sr*", IMPORT{builtin}="blkid" + +# by-label/by-uuid links (filesystem metadata) +ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}" +ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}" + +# by-id (World Wide Name) +ENV{DEVTYPE}=="disk", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}" +ENV{DEVTYPE}=="partition", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}-part%n" + +# by-partlabel/by-partuuid links (partition metadata) +ENV{ID_PART_ENTRY_UUID}=="?*", SYMLINK+="disk/by-partuuid/$env{ID_PART_ENTRY_UUID}" +ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_NAME}=="?*", SYMLINK+="disk/by-partlabel/$env{ID_PART_ENTRY_NAME}" + +LABEL="persistent_storage_end" diff --git a/test/fuzz/fuzz-udev-rules/60-persistent-v4l.rules b/test/fuzz/fuzz-udev-rules/60-persistent-v4l.rules new file mode 100644 index 00000000..93c5ee8c --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-persistent-v4l.rules @@ -0,0 +1,20 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="persistent_v4l_end" +SUBSYSTEM!="video4linux", GOTO="persistent_v4l_end" +ENV{MAJOR}=="", GOTO="persistent_v4l_end" + +IMPORT{program}="v4l_id $devnode" + +SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" +KERNEL=="video*", ENV{ID_SERIAL}=="?*", SYMLINK+="v4l/by-id/$env{ID_BUS}-$env{ID_SERIAL}-video-index$attr{index}" + +# check for valid "index" number +TEST!="index", GOTO="persistent_v4l_end" +ATTR{index}!="?*", GOTO="persistent_v4l_end" + +IMPORT{builtin}="path_id" +ENV{ID_PATH}=="?*", KERNEL=="video*|vbi*", SYMLINK+="v4l/by-path/$env{ID_PATH}-video-index$attr{index}" +ENV{ID_PATH}=="?*", KERNEL=="audio*", SYMLINK+="v4l/by-path/$env{ID_PATH}-audio-index$attr{index}" + +LABEL="persistent_v4l_end" diff --git a/test/fuzz/fuzz-udev-rules/60-sensor.rules b/test/fuzz/fuzz-udev-rules/60-sensor.rules new file mode 100644 index 00000000..7ad2c36b --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-sensor.rules @@ -0,0 +1,18 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="sensor_end" + +# device matching the sensor's name and the machine's DMI data for IIO devices +SUBSYSTEM=="iio", KERNEL=="iio*", SUBSYSTEMS=="usb|i2c", \ + IMPORT{builtin}="hwdb 'sensor:modalias:$attr{modalias}:$attr{[dmi/id]modalias}'", \ + GOTO="sensor_end" + +SUBSYSTEM=="input", ENV{ID_INPUT_ACCELEROMETER}=="1", SUBSYSTEMS=="acpi", \ + IMPORT{builtin}="hwdb 'sensor:modalias:acpi:$attr{hid}:$attr{[dmi/id]modalias}'", \ + GOTO="sensor_end" + +SUBSYSTEM=="input", ENV{ID_INPUT_ACCELEROMETER}=="1", SUBSYSTEMS=="platform", \ + IMPORT{builtin}="hwdb 'sensor:modalias:platform:$id:$attr{[dmi/id]modalias}'", \ + GOTO="sensor_end" + +LABEL="sensor_end" diff --git a/test/fuzz/fuzz-udev-rules/60-serial.rules b/test/fuzz/fuzz-udev-rules/60-serial.rules new file mode 100644 index 00000000..f303e27f --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/60-serial.rules @@ -0,0 +1,26 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="serial_end" +SUBSYSTEM!="tty", GOTO="serial_end" + +SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" +SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci" +SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" + +# /dev/serial/by-path/, /dev/serial/by-id/ for USB devices +KERNEL!="ttyUSB[0-9]*|ttyACM[0-9]*", GOTO="serial_end" + +SUBSYSTEMS=="usb-serial", ENV{.ID_PORT}="$attr{port_number}" + +IMPORT{builtin}="path_id" +ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", SYMLINK+="serial/by-path/$env{ID_PATH}" +ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-path/$env{ID_PATH}-port$env{.ID_PORT}" + +IMPORT{builtin}="usb_id" +ENV{ID_SERIAL}=="", GOTO="serial_end" +SUBSYSTEMS=="usb", ENV{ID_USB_INTERFACE_NUM}="$attr{bInterfaceNumber}" +ENV{ID_USB_INTERFACE_NUM}=="", GOTO="serial_end" +ENV{.ID_PORT}=="", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}" +ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-id/$env{ID_BUS}-$env{ID_SERIAL}-if$env{ID_USB_INTERFACE_NUM}-port$env{.ID_PORT}" + +LABEL="serial_end" diff --git a/test/fuzz/fuzz-udev-rules/64-btrfs.rules b/test/fuzz/fuzz-udev-rules/64-btrfs.rules new file mode 100644 index 00000000..0fa79df8 --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/64-btrfs.rules @@ -0,0 +1,17 @@ +# do not edit this file, it will be overwritten on update + +SUBSYSTEM!="block", GOTO="btrfs_end" +ACTION=="remove", GOTO="btrfs_end" +ENV{ID_FS_TYPE}!="btrfs", GOTO="btrfs_end" +ENV{SYSTEMD_READY}=="0", GOTO="btrfs_end" + +# let the kernel know about this btrfs filesystem, and check if it is complete +IMPORT{builtin}="btrfs ready $devnode" + +# mark the device as not ready to be used by the system +ENV{ID_BTRFS_READY}=="0", ENV{SYSTEMD_READY}="0" + +# reconsider pending devices in case when multidevice volume awaits +ENV{ID_BTRFS_READY}=="1", RUN+="/usr/bin/udevadm trigger -s block -p ID_BTRFS_READY=0" + +LABEL="btrfs_end" diff --git a/test/fuzz/fuzz-udev-rules/70-joystick.rules b/test/fuzz/fuzz-udev-rules/70-joystick.rules new file mode 100644 index 00000000..b80d2036 --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/70-joystick.rules @@ -0,0 +1,12 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="joystick_end" +ENV{ID_INPUT_JOYSTICK}=="", GOTO="joystick_end" +KERNEL!="event*", GOTO="joystick_end" + +# joystick::vp:name::* +KERNELS=="input*", ENV{ID_BUS}!="", \ + IMPORT{builtin}="hwdb 'joystick:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \ + GOTO="joystick_end" + +LABEL="joystick_end" diff --git a/test/fuzz/fuzz-udev-rules/70-mouse.rules b/test/fuzz/fuzz-udev-rules/70-mouse.rules new file mode 100644 index 00000000..3ea743af --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/70-mouse.rules @@ -0,0 +1,18 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="mouse_end" +KERNEL!="event*", GOTO="mouse_end" +ENV{ID_INPUT_MOUSE}=="", GOTO="mouse_end" + +# mouse::vp:name::* +KERNELS=="input*", ENV{ID_BUS}=="usb", \ + IMPORT{builtin}="hwdb 'mouse:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \ + GOTO="mouse_end" +KERNELS=="input*", ENV{ID_BUS}=="bluetooth", \ + IMPORT{builtin}="hwdb 'mouse:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \ + GOTO="mouse_end" +DRIVERS=="psmouse", SUBSYSTEMS=="serio", \ + IMPORT{builtin}="hwdb 'mouse:ps2::name:$attr{device/name}:'", \ + GOTO="mouse_end" + +LABEL="mouse_end" diff --git a/test/fuzz/fuzz-udev-rules/70-touchpad.rules b/test/fuzz/fuzz-udev-rules/70-touchpad.rules new file mode 100644 index 00000000..7bede02d --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/70-touchpad.rules @@ -0,0 +1,13 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="touchpad_end" +ENV{ID_INPUT}=="", GOTO="touchpad_end" +ENV{ID_INPUT_TOUCHPAD}=="", GOTO="touchpad_end" +KERNEL!="event*", GOTO="touchpad_end" + +# touchpad::vp:name::* +KERNELS=="input*", ENV{ID_BUS}!="", \ + IMPORT{builtin}="hwdb 'touchpad:$env{ID_BUS}:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \ + GOTO="touchpad_end" + +LABEL="touchpad_end" diff --git a/test/fuzz/fuzz-udev-rules/75-net-description.rules b/test/fuzz/fuzz-udev-rules/75-net-description.rules new file mode 100644 index 00000000..7e62f8b2 --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/75-net-description.rules @@ -0,0 +1,14 @@ +# do not edit this file, it will be overwritten on update + +ACTION=="remove", GOTO="net_end" +SUBSYSTEM!="net", GOTO="net_end" + +IMPORT{builtin}="net_id" + +SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" +SUBSYSTEMS=="usb", GOTO="net_end" + +SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" +SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci" + +LABEL="net_end" diff --git a/test/fuzz/fuzz-udev-rules/75-probe_mtd.rules b/test/fuzz/fuzz-udev-rules/75-probe_mtd.rules new file mode 100644 index 00000000..8848aeea --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/75-probe_mtd.rules @@ -0,0 +1,7 @@ +# do not edit this file, it will be overwritten on update + +ACTION!="add", GOTO="mtd_probe_end" + +KERNEL=="mtd*ro", IMPORT{program}="mtd_probe $devnode" + +LABEL="mtd_probe_end" diff --git a/test/fuzz/fuzz-udev-rules/78-sound-card.rules b/test/fuzz/fuzz-udev-rules/78-sound-card.rules new file mode 100644 index 00000000..f2fc2773 --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/78-sound-card.rules @@ -0,0 +1,96 @@ +# do not edit this file, it will be overwritten on update + +SUBSYSTEM!="sound", GOTO="sound_end" + +ACTION=="add|change", KERNEL=="controlC*", ATTR{../uevent}="change" +ACTION!="change", GOTO="sound_end" + +# Ok, we probably need a little explanation here for what the two lines above +# are good for. +# +# The story goes like this: when ALSA registers a new sound card it emits a +# series of 'add' events to userspace, for the main card device and for all the +# child device nodes that belong to it. udev relays those to applications, +# however only maintains the order between father and child, but not between +# the siblings. The control device node creation can be used as synchronization +# point. All other devices that belong to a card are created in the kernel +# before it. However unfortunately due to the fact that siblings are forwarded +# out of order by udev this fact is lost to applications. +# +# OTOH before an application can open a device it needs to make sure that all +# its device nodes are completely created and set up. +# +# As a workaround for this issue we have added the udev rule above which will +# generate a 'change' event on the main card device from the 'add' event of the +# card's control device. Due to the ordering semantics of udev this event will +# only be relayed after all child devices have finished processing properly. +# When an application needs to listen for appearing devices it can hence look +# for 'change' events only, and ignore the actual 'add' events. +# +# When the application is initialized at the same time as a device is plugged +# in it may need to figure out if the 'change' event has already been triggered +# or not for a card. To find that out we store the flag environment variable +# SOUND_INITIALIZED on the device which simply tells us if the card 'change' +# event has already been processed. + +KERNEL!="card*", GOTO="sound_end" + +ENV{SOUND_INITIALIZED}="1" + +IMPORT{builtin}="hwdb" +SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id" +SUBSYSTEMS=="usb", GOTO="skip_pci" + +SUBSYSTEMS=="firewire", ATTRS{guid}=="?*", \ + ENV{ID_BUS}="firewire", ENV{ID_SERIAL}="$attr{guid}", ENV{ID_SERIAL_SHORT}="$attr{guid}", \ + ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{model}", \ + ENV{ID_VENDOR}="$attr{vendor_name}", ENV{ID_MODEL}="$attr{model_name}" +SUBSYSTEMS=="firewire", GOTO="skip_pci" + +SUBSYSTEMS=="pci", ENV{ID_BUS}="pci", ENV{ID_VENDOR_ID}="$attr{vendor}", ENV{ID_MODEL_ID}="$attr{device}" +SUBSYSTEMS=="pci", GOTO="skip_pci" + +# If we reach here, the device nor any of its parents are USB/PCI/firewire bus devices. +# If we now find a parent that is a platform device, assume that we're working with +# an internal sound card. +SUBSYSTEMS=="platform", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" + +LABEL="skip_pci" + +# Define ID_ID if ID_BUS and ID_SERIAL are set. This will work for both +# USB and firewire. +ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="?*", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}-$env{ID_USB_INTERFACE_NUM}" +ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", ENV{ID_ID}="$env{ID_BUS}-$env{ID_SERIAL}" + +IMPORT{builtin}="path_id" + +# The values used here for $SOUND_FORM_FACTOR and $SOUND_CLASS should be kept +# in sync with those defined for PulseAudio's src/pulse/proplist.h +# PA_PROP_DEVICE_FORM_FACTOR, PA_PROP_DEVICE_CLASS properties. + +# If the first PCM device of this card has the pcm class 'modem', then the card is a modem +ATTR{pcmC%nD0p/pcm_class}=="modem", ENV{SOUND_CLASS}="modem", GOTO="sound_end" + +# Identify cards on the internal PCI bus as internal +SUBSYSTEMS=="pci", DEVPATH=="*/0000:00:??.?/sound/*", ENV{SOUND_FORM_FACTOR}="internal", GOTO="sound_end" + +# Devices that also support Image/Video interfaces are most likely webcams +SUBSYSTEMS=="usb", ENV{ID_USB_INTERFACES}=="*:0e????:*", ENV{SOUND_FORM_FACTOR}="webcam", GOTO="sound_end" + +# Matching on the model strings is a bit ugly, I admit +ENV{ID_MODEL}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" +ENV{ID_MODEL_FROM_DATABASE}=="*[Ss]peaker*", ENV{SOUND_FORM_FACTOR}="speaker", GOTO="sound_end" + +ENV{ID_MODEL}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" +ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadphone*", ENV{SOUND_FORM_FACTOR}="headphone", GOTO="sound_end" + +ENV{ID_MODEL}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" +ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]eadset*", ENV{SOUND_FORM_FACTOR}="headset", GOTO="sound_end" + +ENV{ID_MODEL}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" +ENV{ID_MODEL_FROM_DATABASE}=="*[Hh]andset*", ENV{SOUND_FORM_FACTOR}="handset", GOTO="sound_end" + +ENV{ID_MODEL}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" +ENV{ID_MODEL_FROM_DATABASE}=="*[Mm]icrophone*", ENV{SOUND_FORM_FACTOR}="microphone", GOTO="sound_end" + +LABEL="sound_end" diff --git a/test/fuzz/fuzz-udev-rules/80-drivers.rules b/test/fuzz/fuzz-udev-rules/80-drivers.rules new file mode 100644 index 00000000..16fa5d8e --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/80-drivers.rules @@ -0,0 +1,13 @@ +# do not edit this file, it will be overwritten on update + +ACTION!="add", GOTO="drivers_end" + +ENV{MODALIAS}=="?*", RUN{builtin}+="kmod load $env{MODALIAS}" +SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN{builtin}+="kmod load tifm_sd" +SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN{builtin}+="kmod load tifm_ms" +SUBSYSTEM=="memstick", RUN{builtin}+="kmod load ms_block mspro_block" +SUBSYSTEM=="i2o", RUN{builtin}+="kmod load i2o_block" +SUBSYSTEM=="module", KERNEL=="parport_pc", RUN{builtin}+="kmod load ppdev" +KERNEL=="mtd*ro", ENV{MTD_FTL}=="smartmedia", RUN{builtin}+="kmod load sm_ftl" + +LABEL="drivers_end" diff --git a/test/fuzz/fuzz-udev-rules/80-net-setup-link.rules b/test/fuzz/fuzz-udev-rules/80-net-setup-link.rules new file mode 100644 index 00000000..6e411a91 --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/80-net-setup-link.rules @@ -0,0 +1,13 @@ +# do not edit this file, it will be overwritten on update + +SUBSYSTEM!="net", GOTO="net_setup_link_end" + +IMPORT{builtin}="path_id" + +ACTION!="add", GOTO="net_setup_link_end" + +IMPORT{builtin}="net_setup_link" + +NAME=="", ENV{ID_NET_NAME}!="", NAME="$env{ID_NET_NAME}" + +LABEL="net_setup_link_end" diff --git a/test/fuzz/fuzz-udev-rules/99-systemd.rules b/test/fuzz/fuzz-udev-rules/99-systemd.rules new file mode 100644 index 00000000..6ae98981 --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/99-systemd.rules @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +ACTION=="remove", GOTO="systemd_end" + +SUBSYSTEM=="tty", KERNEL=="tty[a-zA-Z]*|hvc*|xvc*|hvsi*|ttysclp*|sclp_line*|3270/tty[0-9]*", TAG+="systemd" +KERNEL=="vport*", TAG+="systemd" + +SUBSYSTEM=="ubi", TAG+="systemd" + +SUBSYSTEM=="block", TAG+="systemd" +SUBSYSTEM=="block", ACTION=="add", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0" + +# Ignore encrypted devices with no identified superblock on it, since +# we are probably still calling mke2fs or mkswap on it. +SUBSYSTEM=="block", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0" + +# add symlink to GPT root disk +SUBSYSTEM=="block", ENV{ID_PART_GPT_AUTO_ROOT}=="1", ENV{ID_FS_TYPE}!="crypto_LUKS", SYMLINK+="gpt-auto-root" +SUBSYSTEM=="block", ENV{ID_PART_GPT_AUTO_ROOT}=="1", ENV{ID_FS_TYPE}=="crypto_LUKS", SYMLINK+="gpt-auto-root-luks" +SUBSYSTEM=="block", ENV{DM_UUID}=="CRYPT-*", ENV{DM_NAME}=="root", SYMLINK+="gpt-auto-root" + +# Ignore raid devices that are not yet assembled and started +SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", TEST!="md/array_state", ENV{SYSTEMD_READY}="0" +SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", ATTR{md/array_state}=="|clear|inactive", ENV{SYSTEMD_READY}="0" + +# Ignore loop devices that don't have any file attached +SUBSYSTEM=="block", KERNEL=="loop[0-9]*", ENV{DEVTYPE}=="disk", TEST!="loop/backing_file", ENV{SYSTEMD_READY}="0" + +# Ignore nbd devices until the PID file exists (which signals a connected device) +SUBSYSTEM=="block", KERNEL=="nbd*", ENV{DEVTYPE}=="disk", TEST!="pid", ENV{SYSTEMD_READY}="0" + +# We need a hardware independent way to identify network devices. We +# use the /sys/subsystem/ path for this. Kernel "bus" and "class" names +# should be treated as one namespace, like udev handles it. This is mostly +# just an identification string for systemd, so whether the path actually is +# accessible or not does not matter as long as it is unique and in the +# filesystem namespace. +# +# http://cgit.freedesktop.org/systemd/systemd/tree/src/libudev/libudev-enumerate.c#n955 + +SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/net/devices/$name" +SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k" + +SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}+="bluetooth.target" +ENV{ID_SMARTCARD_READER}=="?*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target" +SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target" + +SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" +SUBSYSTEM=="usb", KERNEL=="lp*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_USB_INTERFACES}=="*:0701??:*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" + +# Apply sysctl variables to network devices (and only to those) as they appear. +ACTION=="add", SUBSYSTEM=="net", KERNEL!="lo", RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/net/ipv4/conf/$name --prefix=/net/ipv4/neigh/$name --prefix=/net/ipv6/conf/$name --prefix=/net/ipv6/neigh/$name" + +# Pull in backlight save/restore for all backlight devices and +# keyboard backlights +SUBSYSTEM=="backlight", TAG+="systemd", IMPORT{builtin}="path_id", ENV{SYSTEMD_WANTS}+="systemd-backlight@backlight:$name.service" +SUBSYSTEM=="leds", KERNEL=="*kbd_backlight", TAG+="systemd", IMPORT{builtin}="path_id", ENV{SYSTEMD_WANTS}+="systemd-backlight@leds:$name.service" + +# Pull in rfkill save/restore for all rfkill devices +SUBSYSTEM=="rfkill", ENV{SYSTEMD_RFKILL}="1" +SUBSYSTEM=="rfkill", IMPORT{builtin}="path_id" +SUBSYSTEM=="misc", KERNEL=="rfkill", TAG+="systemd", ENV{SYSTEMD_WANTS}+="systemd-rfkill.socket" + +# Asynchronously mount file systems implemented by these modules as soon as they are loaded. +SUBSYSTEM=="module", KERNEL=="fuse", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-fs-fuse-connections.mount" +SUBSYSTEM=="module", KERNEL=="configfs", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sys-kernel-config.mount" + +LABEL="systemd_end" diff --git a/test/fuzz/fuzz-udev-rules/oss-fuzz-12980 b/test/fuzz/fuzz-udev-rules/oss-fuzz-12980 new file mode 100644 index 00000000..37846f42 --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/oss-fuzz-12980 @@ -0,0 +1 @@ + SUBSYSTEM==" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " GROUP=" " MODE=" " GROUP=" " KERNEL==" " GROUP=" " KERNEL==" "GROUP=" " KERNEL==" " GROUP=" " MODE =" "KERNEL==" " GROUP=" " KERNEL==" " GROUP=" "MODE =" " KERNEL==" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " GROUP=" " MODE=" " GROUP=" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " GROUP=" " MODE="" MODE =" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL=="" GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " KERNEL==" " OPTIONS =" string_escape=replace watch " \ No newline at end of file diff --git "a/test/fuzz/fuzz-unit-file/dev-mapper-fedora_krowka\\x2dswap.swap" "b/test/fuzz/fuzz-unit-file/dev-mapper-fedora_krowka\\x2dswap.swap" new file mode 100644 index 00000000..2886021b --- /dev/null +++ "b/test/fuzz/fuzz-unit-file/dev-mapper-fedora_krowka\\x2dswap.swap" @@ -0,0 +1,10 @@ +swap +[Unit] +SourcePath=/etc/fstab +Documentation=man:fstab(5) man:systemd-fstab-generator(8) + +[Swap] +What=/dev/mapper/fedora_krowka-swap +Options=defaults,x-systemd.device-timeout=0 +Priority=11 +TimeoutSec=123h 5min 2y diff --git a/test/fuzz/fuzz-unit-file/directives.scope b/test/fuzz/fuzz-unit-file/directives.scope new file mode 100644 index 00000000..d0e194c3 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/directives.scope @@ -0,0 +1,2 @@ +scope +RuntimeMaxSec= diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service new file mode 100644 index 00000000..31a45043 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/directives.service @@ -0,0 +1,924 @@ +service +Accept= +AccuracySec= +After= +Alias= +AllowedCPUs= +AllowedMemoryNodes= +AllowIsolate= +Also= +AmbientCapabilities= +AssertACPower= +AssertArchitecture= +AssertCapability= +AssertControlGroupController= +AssertDirectoryNotEmpty= +AssertFileIsExecutable= +AssertFileNotEmpty= +AssertFirstBoot= +AssertGroup= +AssertHost= +AssertKernelCommandLine= +AssertKernelVersion= +AssertNeedsUpdate= +AssertPathExists= +AssertPathExistsGlob= +AssertPathIsDirectory= +AssertPathIsMountPoint= +AssertPathIsReadWrite= +AssertPathIsSymbolicLink= +AssertSecurity= +AssertUser= +AssertVirtualization= +Backlog= +Before= +BindIPv6Only= +BindPaths= +BindReadOnlyPaths= +BindToDevice= +BindsTo= +BlockIOAccounting= +BlockIODeviceWeight= +BlockIOReadBandwidth= +BlockIOWeight= +BlockIOWriteBandwidth= +Broadcast= +BusName= +CPUAccounting= +CPUQuota= +CPUShares= +CPUWeight= +CapabilityBoundingSet= +CollectMode= +ConditionACPower= +ConditionArchitecture= +ConditionCapability= +ConditionControlGroupController= +ConditionDirectoryNotEmpty= +ConditionFileIsExecutable= +ConditionFileNotEmpty= +ConditionFirstBoot= +ConditionGroup= +ConditionHost= +ConditionKernelCommandLine= +ConditionKernelVersion= +ConditionNeedsUpdate= +ConditionPathExists= +ConditionPathExistsGlob= +ConditionPathIsDirectory= +ConditionPathIsMountPoint= +ConditionPathIsReadWrite= +ConditionPathIsSymbolicLink= +ConditionSecurity= +ConditionUser= +ConditionVirtualization= +Conflicts= +DefaultDependencies= +DefaultInstance= +DeferAcceptSec= +Delegate= +Description= +DeviceAllow= +DevicePolicy= +DirectoryMode= +DirectoryNotEmpty= +Documentation= +DynamicUser= +ExecReload= +ExecCondition= +ExecStart= +ExecStartPost= +ExecStartPre= +ExecStop= +ExecStopPost= +ExecStopPre= +FailureAction= +FileDescriptorName= +FileDescriptorStoreMax= +ForceUnmount= +FreeBind= +Group= +GuessMainPID= +IOAccounting= +IODeviceWeight= +IOReadBandwidthMax= +IOReadIOPSMax= +IOWeight= +IOWriteBandwidthMax= +IOWriteIOPSMax= +IPAccounting= +IPAddressAllow= +IPAddressDeny= +IPTOS= +IPTTL= +IgnoreOnIsolate= +JobRunningTimeoutSec= +JobTimeoutAction= +JobTimeoutRebootArgument= +JobTimeoutSec= +JoinsNamespaceOf= +KeepAlive= +KeepAliveIntervalSec= +KeepAliveProbes= +KeepAliveTimeSec= +KillMode= +KillSignal= +LazyUnmount= +ListenDatagram= +ListenFIFO= +ListenMessageQueue= +#ListenNetlink= +ListenSequentialPacket= +ListenSpecial= +ListenStream= +ListenUSBFunction= +MakeDirectory= +Mark= +MaxConnections= +MaxConnectionsPerSource= +MemoryAccounting= +MemoryHigh= +MemoryLimit= +MemoryLow= +MemoryMax= +MemorySwapMax= +MessageQueueMaxMessages= +MessageQueueMessageSize= +MountAPIVFS= +NoDelay= +NoNewPrivileges= +NonBlocking= +NotifyAccess= +OnActiveSec= +OnBootSec= +OnCalendar= +OnFailure= +OnFailureJobMode= +OnStartupSec= +OnUnitActiveSec= +OnUnitInactiveSec= +Options= +PAMName= +PIDFile= +PartOf= +PassCredentials= +PassSecurity= +PathChanged= +PathExists= +PathExistsGlob= +PathModified= +PermissionsStartOnly= +Persistent= +PipeSize= +Priority= +PropagatesReloadTo= +RandomizedDelaySec= +RebootArgument= +ReceiveBuffer= +RefuseManualStart= +RefuseManualStop= +ReloadPropagatedFrom= +RemainAfterElapse= +RemainAfterExit= +RemoveOnStop= +RequiredBy= +Requires= +RequiresMountsFor= +Requisite= +Restart= +RestartForceExitStatus= +RestartKillSignal= +RestartPreventExitStatus= +RestartSec= +ReusePort= +RootDirectory= +RootDirectoryStartOnly= +RootImage= +RuntimeMaxSec= +SELinuxContextFromNet= +SecureBits= +SendBuffer= +SendSIGHUP= +SendSIGKILL= +Service= +Slice= +SloppyOptions= +SmackLabel= +SmackLabelIPIn= +SmackLabelIPOut= +SocketGroup= +SocketMode= +SocketProtocol= +SocketUser= +Sockets= +SourcePath= +StartLimitAction= +StartLimitBurst= +StartLimitIntervalSec= +StartupBlockIOWeight= +StartupCPUShares= +StartupCPUWeight= +StartupIOWeight= +StopWhenUnneeded= +SuccessAction= +SuccessExitStatus= +SupplementaryGroups= +Symlinks= +TCPCongestion= +TasksAccounting= +TasksMax= +TimeoutIdleSec= +TimeoutSec= +TimeoutStartSec= +TimeoutStopSec= +TimeoutAbortSec= +Transparent= +TriggerLimitBurst= +TriggerLimitIntervalSec= +Type= +USBFunctionDescriptors= +USBFunctionStrings= +Unit= +User= +WakeSystem= +WantedBy= +Wants= +WatchdogSec= +What= +Where= +WorkingDirectory= +Writable= +fsck.mode= +fsck.repair= +fstab= +locale.LANG= +locale.LANGUAGE= +locale.LC_ADDRESS= +locale.LC_COLLATE= +locale.LC_CTYPE= +locale.LC_IDENTIFICATION= +locale.LC_MEASUREMENT= +locale.LC_MESSAGES= +locale.LC_MONETARY= +locale.LC_NAME= +locale.LC_NUMERIC= +locale.LC_PAPER= +locale.LC_TELEPHONE= +locale.LC_TIME= +luks.crypttab= +luks.key= +luks.name= +luks.options= +luks.uuid= +luks= +modules_load= +mount.usr= +mount.usrflags= +mount.usrfstype= +net.ifnames= +plymouth.enable= +quotacheck.mode= +rd.fstab= +rd.luks.crypttab= +rd.luks.key= +rd.luks.name= +rd.luks.options= +rd.luks.uuid= +rd.luks= +rd.modules_load= +rd.systemd.gpt_auto= +rd.systemd.unit= +rd.systemd.verity= +rd.udev.children_max= +rd.udev.event_timeout= +rd.udev.exec_delay= +rd.udev.log_priority= +resume= +resumeflags= +root= +rootflags= +rootfstype= +roothash= +systemd.default_standard_error= +systemd.default_standard_output= +systemd.default_timeout_start_sec= +systemd.firstboot= +systemd.gpt_auto= +systemd.journald.forward_to_console= +systemd.journald.forward_to_kmsg= +systemd.journald.forward_to_syslog= +systemd.journald.forward_to_wall= +systemd.log_level= +systemd.log_location= +systemd.log_target= +systemd.machine_id= +systemd.mask= +systemd.restore_state= +systemd.service_watchdogs= +systemd.setenv= +systemd.unit= +systemd.verity= +systemd.verity_root_data= +systemd.verity_root_hash= +systemd.volatile= +systemd.wants= +systemd.watchdog_device= +udev.children_max= +udev.event_timeout= +udev.exec_delay= +udev.log_priority= +vconsole.font= +vconsole.font_map= +vconsole.font_unimap= +vconsole.keymap= +vconsole.keymap_toggle= +ID_MODEL= +ID_MODEL_FROM_DATABASE= +SYSTEMD_ALIAS= +SYSTEMD_MOUNT_OPTIONS= +SYSTEMD_MOUNT_WHERE= +SYSTEMD_READY= +SYSTEMD_USER_WANTS= +SYSTEMD_WANTS= +link_priority= +static_node= +string_escape= +ARP= +ARPAllTargets= +ARPIPTargets= +ARPIntervalSec= +ARPValidate= +ActiveSlave= +AdSelect= +Address= +AddressAutoconfiguration= +AgeingTimeSec= +Alias= +AllSlavesActive= +AllowLocalRemote= +AllowPortToBeRoot= +AllowedIPs= +Anonymize= +Architecture= +AutoJoin= +AutoNegotiation= +BindCarrier= +BitsPerSecond= +Bond= +Bridge= +Broadcast= +Cache= +ClientIdentifier= +ConfigureWithoutCarrier= +CopyDSCP= +Cost= +CriticalConnection= +DHCP= +DHCPServer= +DNS= +DNSLifetimeSec= +DNSSEC= +DNSSECNegativeTrustAnchors= +DNSStubListener= +DUIDRawData= +DUIDType= +DefaultLeaseTimeSec= +DefaultPVID= +Description= +Destination= +DestinationPort= +DiscoverPathMTU= +Domains= +DownDelaySec= +Driver= +Duplex= +DuplicateAddressDetection= +EgressUntagged= +EmitDNS= +EmitDomains= +EmitLLDP= +EmitNTP= +EmitRouter= +EmitTimezone= +EncapsulationLimit= +Endpoint= +FDBAgeingSec= +FailOverMACPolicy= +FallbackDNS= +FallbackNTP= +FastLeave= +FirewallMark= +Flags= +FlowLabel= +ForwardDelaySec= +From= +FwMark= +GVRP= +Gateway= +GatewayOnLink= +GenericReceiveOffload= +GenericSegmentationOffload= +GratuitousARP= +Group= +GroupForwardMask= +GroupPolicyExtension= +HairPin= +MulticastToUnicast= +HelloTimeSec= +HomeAddress= +Host= +Hostname= +IAID= +IPForward= +IPMasquerade= +IPv4LLRoute= +IPv4ProxyARP= +IPv6AcceptRA= +IPv6DuplicateAddressDetection= +IPv6FlowLabel= +IPv6HopLimit= +IPv6Preference= +IPv6PrefixDelegation= +IPv6PrivacyExtensions= +IPv6ProxyNDP= +IPv6ProxyNDPAddress= +IPv6Token= +Id= +IncomingInterface= +Independent= +InitialAdvertisedReceiveWindow= +InitialCongestionWindow= +InputKey= +InvertRule= +KernelCommandLine= +KernelVersion= +Key= +Kind= +L2MissNotification= +L3MissNotification= +LACPTransmitRate= +LLDP= +LLMNR= +Label= +LargeReceiveOffload= +LearnPacketIntervalSec= +LinkLocalAddressing= +ListenPort= +Local= +LooseBinding= +MACAddress= +MACAddressPolicy= +MACVLAN= +MIIMonitorSec= +MTUBytes= +MVRP= +MacLearning= +ManageTemporaryAddress= +Managed= +MaxAgeSec= +MaxLeaseTimeSec= +MaximumFDBEntries= +Metric= +MinLinks= +Mode= +MultiQueue= +MulticastDNS= +MulticastQuerier= +MulticastSnooping= +NTP= +Name= +NamePolicy= +OnLink= +OneQueue= +OriginalName= +OtherInformation= +OutgoingInterface= +OutputKey= +PVID= +PacketInfo= +PacketsPerSlave= +Path= +Peer= +PersistentKeepalive= +PollIntervalMaxSec= +PollIntervalMinSec= +PoolOffset= +PoolSize= +Port= +PortRange= +PreferredLifetime= +PreferredLifetimeSec= +PreferredSource= +Prefix= +PrefixRoute= +PresharedKey= +PrimaryReselectPolicy= +PrimarySlave= +Priority= +PrivateKey= +Protocol= +PublicKey= +QuickAck= +RapidCommit= +ReduceARPProxy= +Remote= +RemoteChecksumRx= +RemoteChecksumTx= +ReorderHeader= +RequestBroadcast= +RequiredForOnline= +ResendIGMP= +RootDistanceMaxSec= +RouteMetric= +RouteShortCircuit= +RouteTable= +RouterLifetimeSec= +RouterPreference= +STP= +Scope= +SendHostname= +Source= +TCP6SegmentationOffload= +TCPSegmentationOffload= +TOS= +TTL= +Table= +Timezone= +To= +TransmitHashPolicy= +Tunnel= +TxtData= +TxtText= +Type= +TypeOfService= +UDP6ZeroChecksumRx= +UDP6ZeroChecksumTx= +UDPChecksum= +UDPSegmentationOffload= +UnicastFlood= +Unmanaged= +UpDelaySec= +UseBPDU= +UseDNS= +UseDomains= +UseHostname= +UseMTU= +UseNTP= +UseRoutes= +UseTimezone= +User= +VLAN= +VLANFiltering= +VLANId= +VNetHeader= +VRF= +VXLAN= +ValidLifetimeSec= +VendorClassIdentifier= +Virtualization= +WakeOnLan= +Weight= +CODE_FILE= +CODE_FUNC= +CODE_LINE= +COREDUMP_UNIT= +COREDUMP_USER_UNIT= +ERRNO= +MESSAGE= +MESSAGE_ID= +OBJECT_AUDIT_LOGINUID= +OBJECT_AUDIT_SESSION= +OBJECT_CMDLINE= +OBJECT_COMM= +OBJECT_EXE= +OBJECT_GID= +OBJECT_PID= +OBJECT_SYSTEMD_CGROUP= +OBJECT_SYSTEMD_OWNER_UID= +OBJECT_SYSTEMD_SESSION= +OBJECT_SYSTEMD_UNIT= +OBJECT_SYSTEMD_USER_UNIT= +OBJECT_UID= +PRIORITY= +SYSLOG_FACILITY= +SYSLOG_IDENTIFIER= +SYSLOG_PID= +_AUDIT_LOGINUID= +_AUDIT_SESSION= +_BOOT_ID= +_CAP_EFFECTIVE= +_CMDLINE= +_COMM= +_EXE= +_GID= +_HOSTNAME= +_KERNEL_DEVICE= +_KERNEL_SUBSYSTEM= +_LINE_BREAK= +_MACHINE_ID= +_PID= +_SELINUX_CONTEXT= +_SOURCE_REALTIME_TIMESTAMP= +_STREAM_ID= +_SYSTEMD_CGROUP= +_SYSTEMD_INVOCATION_ID= +_SYSTEMD_OWNER_UID= +_SYSTEMD_SESSION= +_SYSTEMD_SLICE= +_SYSTEMD_UNIT= +_SYSTEMD_USER_UNIT= +_TRANSPORT= +_UDEV_DEVLINK= +_UDEV_DEVNODE= +_UDEV_SYSNAME= +_UID= +__CURSOR= +__MONOTONIC_TIMESTAMP= +__REALTIME_TIMESTAMP= +class= +type= +cipher= +hash= +header= +key-slot= +keyfile-offset= +keyfile-size= +offset= +size= +skip= +tcrypt-keyfile= +timeout= +tries= +x-systemd.after= +x-systemd.before= +x-systemd.device-timeout= +x-systemd.idle-timeout= +x-systemd.mount-timeout= +x-systemd.requires-mounts-for= +x-systemd.requires= +CPUAffinity= +CapabilityBoundingSet= +CrashChangeVT= +CrashReboot= +CrashShell= +CtrlAltDelBurstAction= +DefaultBlockIOAccounting= +DefaultCPUAccounting= +DefaultEnvironment= +DefaultIPAccounting= +DefaultLimitAS= +DefaultLimitCORE= +DefaultLimitCPU= +DefaultLimitDATA= +DefaultLimitFSIZE= +DefaultLimitLOCKS= +DefaultLimitMEMLOCK= +DefaultLimitMSGQUEUE= +DefaultLimitNICE= +DefaultLimitNOFILE= +DefaultLimitNPROC= +DefaultLimitRSS= +DefaultLimitRTPRIO= +DefaultLimitRTTIME= +DefaultLimitSIGPENDING= +DefaultLimitSTACK= +DefaultMemoryAccounting= +DefaultRestartSec= +DefaultStandardError= +DefaultStandardOutput= +DefaultStartLimitBurst= +DefaultStartLimitIntervalSec= +DefaultTasksAccounting= +DefaultTasksMax= +DefaultTimeoutStartSec= +DefaultTimeoutStopSec= +DefaultTimeoutAbortSec= +DefaultTimerAccuracySec= +DumpCore= +HibernateMode= +HibernateState= +HybridSleepMode= +HybridSleepState= +LogColor= +LogLevel= +LogLocation= +LogTarget= +RuntimeWatchdogSec= +ShowStatus= +RebootWatchdogSec= +ShutdownWatchdogSec= +KExecWatchdogSec= +SuspendMode= +SuspendState= +SystemCallArchitectures= +TimerSlackNSec= +WatchdogDevice= +-N= +-c= +-e= +-t= +ANSI_COLOR= +AppArmorProfile= +BUG_REPORT_URL= +BUILD_ID= +Bind= +BindReadOnly= +Boot= +Bridge= +CHASSIS= +CPE_NAME= +CPUAffinity= +CPUSchedulingPolicy= +CPUSchedulingPriority= +CPUSchedulingResetOnFork= +CacheDirectory= +CacheDirectoryMode= +Capability= +Compress= +ConfigurationDirectory= +ConfigurationDirectoryMode= +DEPLOYMENT= +DropCapability= +Environment= +EnvironmentFile= +ExternalSizeMax= +FONT= +FONT_MAP= +FONT_UNIMAP= +ForwardToConsole= +ForwardToKMsg= +ForwardToSyslog= +ForwardToWall= +HOME_URL= +HandleHibernateKey= +HandleLidSwitch= +HandleLidSwitchDocked= +HandleLidSwitchExternalPower= +HandlePowerKey= +HandleSuspendKey= +HibernateKeyIgnoreInhibited= +HoldoffTimeoutSec= +ICON_NAME= +ID= +ID_LIKE= +IOSchedulingClass= +IOSchedulingPriority= +IPVLAN= +IdleAction= +IdleActionSec= +IgnoreSIGPIPE= +InaccessiblePaths= +InhibitDelayMaxSec= +InhibitorsMax= +Interface= +JournalSizeMax= +KEYMAP= +KEYMAP_TOGGLE= +KeepFree= +KeyringMode= +KillExcludeUsers= +KillOnlyUsers= +KillSignal= +WatchdogSignal= +KillUserProcesses= +LOCATION= +LidSwitchIgnoreInhibited= +LimitAS= +LimitCORE= +LimitCPU= +LimitDATA= +LimitFSIZE= +LimitLOCKS= +LimitMEMLOCK= +LimitMSGQUEUE= +LimitNICE= +LimitNOFILE= +LimitNPROC= +LimitRSS= +LimitRTPRIO= +LimitRTTIME= +LimitSIGPENDING= +LimitSTACK= +LineMax= +LockPersonality= +LogExtraFields= +LogLevelMax= +LogRateLimitIntervalSec= +LogRateLimitBurst= +LogsDirectory= +LogsDirectoryMode= +MACVLAN= +MachineID= +MaxFileSec= +MaxLevelConsole= +MaxLevelKMsg= +MaxLevelStore= +MaxLevelSyslog= +MaxLevelWall= +MaxRetentionSec= +MaxUse= +MemoryDenyWriteExecute= +MountFlags= +NAME= +NAutoVTs= +Nice= +NoNewPrivileges= +NotifyReady= +OOMScoreAdjust= +Overlay= +OverlayReadOnly= +PRETTY_HOSTNAME= +PRETTY_NAME= +PRIVACY_POLICY_URL= +Parameters= +PassEnvironment= +Personality= +PivotRoot= +Port= +PowerKeyIgnoreInhibited= +Private= +PrivateDevices= +PrivateNetwork= +PrivateTmp= +PrivateUsers= +PrivateUsersChown= +ProcessSizeMax= +ProcessTwo= +ProtectControlGroups= +ProtectHome= +ProtectKernelModules= +ProtectKernelTunables= +ProtectSystem= +RateLimitBurst= +RateLimitIntervalSec= +ReadKMsg= +ReadOnly= +ReadOnlyPaths= +ReadWritePaths= +RemoveIPC= +ReserveVT= +RestrictAddressFamilies= +RestrictNamespaces= +RestrictRealtime= +RestrictSUIDSGID= +RuntimeDirectory= +RuntimeDirectoryMode= +RuntimeDirectoryPreserve= +RuntimeDirectorySize= +RuntimeKeepFree= +RuntimeMaxFileSize= +RuntimeMaxFiles= +RuntimeMaxUse= +SELinuxContext= +SUPPORT_URL= +Seal= +ServerCertificateFile= +ServerKeyFile= +SessionsMax= +SmackProcessLabel= +SplitMode= +StandardError= +StandardInput= +StandardInputData= +StandardInputText= +StandardOutput= +StateDirectory= +StateDirectoryMode= +Storage= +SuspendKeyIgnoreInhibited= +SyncIntervalSec= +SyslogFacility= +SyslogIdentifier= +SyslogLevel= +SyslogLevelPrefix= +SystemCallArchitectures= +SystemCallErrorNumber= +SystemCallFilter= +SystemKeepFree= +SystemMaxFileSize= +SystemMaxFiles= +SystemMaxUse= +TTYPath= +TTYReset= +TTYVHangup= +TTYVTDisallocate= +TemporaryFileSystem= +TimerSlackNSec= +TrustedCertificateFile= +UMask= +URL= +UnsetEnvironment= +User= +UserTasksMax= +UtmpIdentifier= +UtmpMode= +VARIANT= +VARIANT_ID= +VERSION= +VERSION_CODENAME= +VERSION_ID= +VirtualEthernet= +VirtualEthernetExtra= +Volatile= +WorkingDirectory= +Zone= diff --git a/test/fuzz/fuzz-unit-file/empty.scope b/test/fuzz/fuzz-unit-file/empty.scope new file mode 100644 index 00000000..8df7245f --- /dev/null +++ b/test/fuzz/fuzz-unit-file/empty.scope @@ -0,0 +1,2 @@ +scope +[Scope] diff --git a/test/fuzz/fuzz-unit-file/machine.slice b/test/fuzz/fuzz-unit-file/machine.slice new file mode 100644 index 00000000..bf8c6bfc --- /dev/null +++ b/test/fuzz/fuzz-unit-file/machine.slice @@ -0,0 +1,14 @@ +slice +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Virtual Machine and Container Slice +Documentation=man:systemd.special(7) +Before=slices.target diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-10007 b/test/fuzz/fuzz-unit-file/oss-fuzz-10007 new file mode 100644 index 00000000..893630c8 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-10007 @@ -0,0 +1,6 @@ +socket + # +[Socket] +ListenStream=vsock u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H5%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%HHs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%HHs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fus-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0s-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%u%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%s-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H23372036708:255 +ListenStream=vsock:34843013755:210 +Bis0%Hs-fu%H%H0%Hs-fu%H%H0%Hs-fu%H%H0%s-fu/H%H0%Hs-fu%H%H32767%Hs-fu%H%H0%Hs-fu%H%H0%Hs-f \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-11569 b/test/fuzz/fuzz-unit-file/oss-fuzz-11569 new file mode 100644 index 0000000000000000000000000000000000000000..c49b8c6b1c5f671f4f1ce14adb0412817e5d685d GIT binary patch literal 277466 zcmeI*&2Agl6$kJv8v(QH1GuP}T@q20ZKZ&KriBByKpn$!SBX)mG*Jk3=v0)Ax_OoK z5xVWR`>y&3d6dqFNa|yFNB8n;hW>>yMe@#!W)9E&f1GnkO-ASM&W5ACd-v{rb5cEi zxp(q9f9d#M?@8~;r~Si&qr-lXOm)+y_1X6@vGDGSHBy7|Mud= z=oFHh>qac=DL z!<9o7M>@|>^w+)oI?7$<`%O1n^fTWw=3H(Zc(~}W#p?|R&d>PDMcz2@{OR>aC$j_p z^7gOJf8q2tkKXi^x^T}npKsK3*2R|dgU=689$|i04OGv|`{ISsq(0$_e7km=XI(!3 z%8`ax7Te6v>XX^gW)EhE|HbT4F_s6V$n^66>)S3J%gJPvAMyG@%U?M^f%zHFU+ewj z_Ab|7xl<^fk4|5GJ%0UucHr`TEiQI`D;}of!0b3h9+$V4UGcSRou1+RT=Vz*`WuvA zL-l@rH{Iw;O3hv>uJk;=yMKB3UzL|$J}DnnPpgOd{f*x-J3*LFVNc(=s}vgA_v@s zyX(i@#m=g%7k+!*8{aQVb02{Hx+DIJOKnZIsxix#o3(0jSpXg8k$H4$vIHu9@@4J$ zGA+1Yw%NL^K;_HY^W{ccR=zBtx&W%Rf5<#CkMQ&z&0%0Vn@8r6d1M|{OW0PgmEa3} zfiLg{zEo?7H|53PF5HE?a2M{v-7PJkxwcROAK@c>gpcqMKEg*i8@9AdiKp>&Ol}tW zQnZ)0na*-n&c-BQW4=@r-MCqi_kq^xt`3Qd>9*48W*+${!*j znQkkcZs;7Hqw|V%0v-_VCgLtSN9Xa&s7$xS>4whHIXXw@A<|h!=AiRXWYHGd;?Av` zvTmy4iFn~3;HJP3+)cz?bdJvBC#mU{INi8&?wmX4&O@ZLjLbpjp~#{ww8fos=iE7W z-ic2&p>uT3ov-TSO5`8;NB)t2Ta$n29G#`Hw%pr3&Aal?;I!EW| z9G!3DZ~c%tWX?)u4mwBY=p3D+b97#ci}nBEBqB7jA$6a)e&bf2$oIB^v z+v9l2zeM?m&e1tKN9X7qoul(sEF4&-%7xC+IXXw@=p3D+b97#^VL(uHdPvbHvFM|> zRo~kZ7jd!H!di=vhYT=gBOh_+p~yCd4?Kfs@C=?qAhHZR!x#7xgD>bjG!xM|cWy=Q z2ENS-ZK16g+LABz`GU^Tx!$?nx!$?nd1+o+(LQFQ5^WSZN9X7qouhMfj?P=5WtM5q zpmTJN&e1tKN9X7qotJDF5EPvrQuIkI`si)d_qN1ET=a-54;f$vxSNQ(+&Op7opa~h zId{&TbLZT7KxOXg5cQm>p1E`GoIB^vLmo0f8jZNiorfaZ7(Va}p20JC4uQxr@C;wz zOANlC^UzF0=Uk}Io%`JRuu-rCI6E)|U*OA1@dcfubG>uDbG>uD^HN;2qJ2!}B+49g zj?U3JI!EW|9G$m9%PdpPLFeckouhMfj?U3JIxpEUASgOLr0A1a^eNu;PQUYMCof;* z%SwBp=8>gvmcnsc+!nXh9!W*!kU3<|29}g6wuf9K7y?6JXag|Bg>s=WE>ynM=L4sX52My|5M+aj|sL(#fqYo#f8BbMBlw z=gzrv?wmX4&Ue*<2d;|?- z384w0384uQ@=5__fV+vf%bkZZPFf|V6*@=f=p3Dgz!ja>gX=PJLFb{2L+AAwCobY* zY10OlHj%|-af~cR=jdGTT<=`(T<^RT>8)rVvkQrK0iC0BbdJu^IXXw@tS zl4bG49LSx(5cQm>o)u3OPh*Ow@oWv$4I!EW|9G#z(VJ>z(VJmt@h3_HiR^r8DAgS98!gI!EW|9G#;T0@+Br;xO48D zJLk^1bMBlww-l~q!$L&HlS2FV;?B8qy>q>Dz4JAcJ_GO%cN1}!JLk^hg_!A-c(|$_~dHq5!xCh8l5~JLk^hld&+U?j?NX86_pj06_wjlIU@hazm>{A z?wmU(bI2Srhs+^!^v?CpceN25xGt`Ot5~V4P&}1-q}C&Q;vz0&4w*ydY**&oO|=AQ z5s(A&7$BD~@zQC8R;LG#T>8r2DuitOukFo`jB5g=NpdNa}MOQz?U}ROU%0wnAj~Df-mqTCZpwx ze338sNPSm*SA92UL+cr=XQ-f{C5k@nH0V0IE(Xiwi+qtUe855<&>P=>_T`HwKh;l@ zG?MD{UJ$cB6~skcFbO7E$RtZHpn)&&1-`%+_@ZL1Vx6<0inWThiuJJ5#e~4g)4TL; z493eB`66FZ{n1MPN}DNY3YvncQ}FTl&G_Q@-Y~z*KFa^gKHhsges^|0`fjHNdXwp` zd@#SOUap>BZd3i(`H*z^0)Kn@{pp|2UY}jO|IM4X<5y?nznqLNj^FKP2S3aD53)&i znDw)V+0o@YTD{4iTz!@uJjnWo+2Any_;}pU_V=^?L3U9*?Dw<7pAWJJ*->`zMb>|m z4F=^lpJv(7!~K3%{y5mr1`o2q!^>Ury^pfu2>B7KJ&&?MzGv*##kuSc^2^vCJUTq+ zX9t5Uzo`9#tb8piUa3wuKc`1oes*7EgM+=xXp}^_;tz^`nB@A;AAkH`IGP`3T$-!E z;zEoOW65G{)~z*<7R{rVpZC5!w?68Ib(SxS@+B`-%a>b_EMMfyt)$QwsZWY^$7K@z bYXfK0k|6+7|E9JqE|bkJYY8N0QegfM)Gs$k literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-13125 b/test/fuzz/fuzz-unit-file/oss-fuzz-13125 new file mode 100644 index 00000000..b671e110 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-13125 @@ -0,0 +1,10 @@ +timer + . +[Timer] +OnCalendar= CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%%H%H%CCH%L%H%L%H%H%L%H%H%H%H%C%L%HrH%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CL%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%%%H%HHH%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%HL%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%HeH%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%%H%%H%CLH%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%HH%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H.[ H/var/lH%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%HH%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H;C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%HeH%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%HH%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CLANG=C.%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%HeH%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%LH%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%%H%%H%CLH%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%HH%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H;C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%HeH%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%H%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%HeH%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%HeH%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%HeH%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%HH%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH󠁪%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%HeH%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%L%H%H%C%H%H%CH%L%H%L%HH%E%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,8,40,04,4..0=|w=s utc +[Timer] +OnCalendar=Wed utc + +OnCalendar=s%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%w=s utc +[Timer] +OnCHalend%CH%L%H%L%HH%H%ar0,4C%H. \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-6884 b/test/fuzz/fuzz-unit-file/oss-fuzz-6884 new file mode 100644 index 00000000..00d105ad --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-6884 @@ -0,0 +1,3 @@ +socket +[Socket] +ListenNetlink=ÿ \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-6885 b/test/fuzz/fuzz-unit-file/oss-fuzz-6885 new file mode 100644 index 00000000..1859136f --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-6885 @@ -0,0 +1,3 @@ +service +[Service] +DeviceAllow=%D \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-6886 b/test/fuzz/fuzz-unit-file/oss-fuzz-6886 new file mode 100644 index 00000000..1fbe5ffd --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-6886 @@ -0,0 +1,3 @@ +timer +[Timer] +OnCalendar=@88588582097858858 \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-6892 b/test/fuzz/fuzz-unit-file/oss-fuzz-6892 new file mode 100644 index 00000000..31f746d0 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-6892 @@ -0,0 +1,3 @@ +service +[Service] +USBFunctionStrings=/ \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-6897 b/test/fuzz/fuzz-unit-file/oss-fuzz-6897 new file mode 100644 index 00000000..742fd9bf --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-6897 @@ -0,0 +1,4 @@ +service +[Service] +Slice=%H.slice +TemporaryFileSystem=%c \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-6897-evverx b/test/fuzz/fuzz-unit-file/oss-fuzz-6897-evverx new file mode 100644 index 00000000..126678e7 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-6897-evverx @@ -0,0 +1,4 @@ +service +[Service] +Slice=abc-def.slice +TemporaryFileSystem=%c diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-6908 b/test/fuzz/fuzz-unit-file/oss-fuzz-6908 new file mode 100644 index 00000000..8f2404b1 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-6908 @@ -0,0 +1,3 @@ +socket +[Socket] +IOSchedulingClass=531473 \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-6917 b/test/fuzz/fuzz-unit-file/oss-fuzz-6917 new file mode 100644 index 00000000..9a79cf00 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-6917 @@ -0,0 +1,4 @@ +timer + [Timer] + = +OnCalendar=*-02 9,04,40,04,4,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,0,04,4,40,300,0,04,4,40,04,4..0,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,65535,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,1..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,0440,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,0,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,5,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,0404,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,00,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04,4..0,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,04,4..0,04,04,0,4..0,0,04,4,40,30,04,4..0,0,04,4,40,04 \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-6977 b/test/fuzz/fuzz-unit-file/oss-fuzz-6977 new file mode 100644 index 00000000..3d844e6f --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-6977 @@ -0,0 +1,3 @@ +swap +[Unit] +SourcePath=2h=s=%ps=%pwh=s=Sous=%ps=%pwh=s=%ps=%pw%pours=%ps=%pw%pours=%ps=%pwaa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥poursÀ½%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pwaa[Unt=%p=À¥pours=%ps=%pwh=s=%ps=%pw%pours=%ps=%pwaa[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePanh=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%poh=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePÀ¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pourw=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=ÀAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[waa[Unt=%p=À¥pours=%ps=%pAaa!Unt=%pourcePath=s=%pwa=%p=ou[w \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-6977-unminimized b/test/fuzz/fuzz-unit-file/oss-fuzz-6977-unminimized new file mode 100644 index 00000000..718f94f0 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-6977-unminimized @@ -0,0 +1,3 @@ +swap +[Unit] +Documentation=DH⁦0.õi%H±aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaation=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctiocumentation=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=Documentation=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH1.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%H󠁫N%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ctio‭n=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±ction=DH0.õi%HN%H%H±c \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-7004 b/test/fuzz/fuzz-unit-file/oss-fuzz-7004 new file mode 100644 index 00000000..77a5e5e8 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-7004 @@ -0,0 +1,3 @@ +timer +[Timer] +OnCalendar=*-31/2147483640 \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-8064 b/test/fuzz/fuzz-unit-file/oss-fuzz-8064 new file mode 100644 index 00000000..2c6c1eae --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-8064 @@ -0,0 +1,3 @@ +service +[Service] +RestartForceExitStatus=RTMIN+2147483644 \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/oss-fuzz-8827 b/test/fuzz/fuzz-unit-file/oss-fuzz-8827 new file mode 100644 index 00000000..c71b75e1 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/oss-fuzz-8827 @@ -0,0 +1,5 @@ +timer +[Timer] +OnCalendar=.[ H%LH%L%H%H%L%H%L%LLCL%H%C%L%HeH%CH%H%C%L%H%H%C%H%H%CH%L%H%L%L%%imer +[Timer] +OnCalendar=.[ H%LH%L%H%H%L%H%L%LLCL%H%C%L%HeH%CH%H%C%L%HeH%CH%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%S%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%C%H%H%CH%L%H%L%HH%H%C%H%H%H%H%C%H%H%CH%L%H%L%H%H%L%H%H%H%H%C%L%H%H%H%H%H%H%C \ No newline at end of file diff --git a/test/fuzz/fuzz-unit-file/proc-sys-fs-binfmt_misc.automount b/test/fuzz/fuzz-unit-file/proc-sys-fs-binfmt_misc.automount new file mode 100644 index 00000000..777a123e --- /dev/null +++ b/test/fuzz/fuzz-unit-file/proc-sys-fs-binfmt_misc.automount @@ -0,0 +1,21 @@ +automount +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Arbitrary Executable File Formats File System Automount Point +Documentation=https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.html +Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems +DefaultDependencies=no +Before=sysinit.target +ConditionPathExists=/proc/sys/fs/binfmt_misc/ +ConditionPathIsReadWrite=/proc/sys/ + +[Automount] +Where=/proc/sys/fs/binfmt_misc diff --git a/test/fuzz/fuzz-unit-file/syslog.socket b/test/fuzz/fuzz-unit-file/syslog.socket new file mode 100644 index 00000000..2eb316fc --- /dev/null +++ b/test/fuzz/fuzz-unit-file/syslog.socket @@ -0,0 +1,117 @@ +socket +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Syslog Socket +Documentation=man:systemd.special(7) +Documentation=https://www.freedesktop.org/wiki/Software/systemd/syslog +DefaultDependencies=no +Before=sockets.target + +# Don't allow logging until the very end +Conflicts=shutdown.target +Before=shutdown.target + +# Don't try to activate syslog.service if sysinit.target has failed. +Conflicts=emergency.service +Before=emergency.service + +[Socket] +ListenDatagram=/run/systemd/journal/syslog +SocketMode=0666 +PassCredentials=yes +PassSecurity=yes +ReceiveBuffer=8M + +# The default syslog implementation should make syslog.service a +# symlink to itself, so that this socket activates the right actual +# syslog service. +# +# Examples: +# +# /etc/systemd/system/syslog.service -> /lib/systemd/system/rsyslog.service +# /etc/systemd/system/syslog.service -> /lib/systemd/system/syslog-ng.service +# +# Best way to achieve that is by adding this to your unit file +# (i.e. to rsyslog.service or syslog-ng.service): +# +# [Install] +# Alias=syslog.service +# +# See https://www.freedesktop.org/wiki/Software/systemd/syslog for details. + +[Socket] +ListenStream=1.2.3.4:1234 +ListenDatagram=1.2.3.4:1234 +ListenSequentialPacket=1.2.3.4:1234 +ListenFIFO= +ListenSpecial= +#ListenNetlink= +ListenMessageQueue= +ListenUSBFunction= +SocketProtocol=udplite +SocketProtocol=sctp +SocketProtocol= +BindIPv6Only=false +Backlog=33 +BindToDevice=eth0 +SocketUser=daemon +SocketGroup=nobody +SocketMode=0111 +DirectoryMode=0555 +Accept=true +Accept=false +Writable=true +MaxConnections=11 +MaxConnectionsPerSource=12 +KeepAlive=yes +KeepAliveTimeSec=12345 +KeepAliveIntervalSec=12345 +KeepAliveProbes=12345 +NoDelay=true +Priority=0 +DeferAcceptSec=1 +ReceiveBuffer=1G +SendBuffer=1G +IPTOS=low-delay +IPTOS=throughput +IPTOS=reliability +IPTOS=low-cost +IPTOS= +IPTTL=7 +Mark=123 +ReusePort=true +SmackLabel=smack-label +SmackLabelIPIn=smack-label +SmackLabelIPOut=no idea what to put here +SELinuxContextFromNet=true +PipeSize=11111 +MessageQueueMaxMessages=200 +MessageQueueMessageSize=200 +FreeBind=false +Transparent=true +Broadcast=true +PassCredentials=true +PassSecurity=true +TCPCongestion=westwood +TCPCongestion=veno +TCPCongestion=cubic +TCPCongestion=lp +ExecStartPre=/bin/true "arg ' ' " +ExecStartPost=-!!/bin/false +ExecStopPre=/bin/true +ExecStopPost=-!!/bin/false +TimeoutSec=2343 +Symlinks=a b c d e +Symlinks= +Symlinks=/a /b /c /d /e +FileDescriptorName=name +TriggerLimitIntervalSec=2343 +TriggerLimitBurst=234 diff --git a/test/fuzz/fuzz-unit-file/systemd-ask-password-console.path b/test/fuzz/fuzz-unit-file/systemd-ask-password-console.path new file mode 100644 index 00000000..3e12c752 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/systemd-ask-password-console.path @@ -0,0 +1,22 @@ +path +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Dispatch Password Requests to Console Directory Watch +Documentation=man:systemd-ask-password-console.service(8) +DefaultDependencies=no +Conflicts=shutdown.target +After=plymouth-start.service +Before=paths.target shutdown.target cryptsetup.target +ConditionPathExists=!/run/plymouth/pid + +[Path] +DirectoryNotEmpty=/run/systemd/ask-password +MakeDirectory=yes diff --git a/test/fuzz/fuzz-unit-file/systemd-machined.service b/test/fuzz/fuzz-unit-file/systemd-machined.service new file mode 100644 index 00000000..70b627c5 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/systemd-machined.service @@ -0,0 +1,52 @@ +service +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Virtual Machine and Container Registration Service +Documentation=man:systemd-machined.service(8) +Documentation=https://www.freedesktop.org/wiki/Software/systemd/machined +Wants=machine.slice +After=machine.slice +RequiresMountsFor=/var/lib/machines +ConditionNull=true +ConditionNull= +ConditionNull=|!false +OnFailureIsolate=false +FailureActionExitStatus=222 +FailureActionExitStatus= +SuccessActionExitStatus=0 +SuccessActionExitStatus= + +[Service] +ExecStart=/usr/lib/systemd/systemd-machined +BusName=org.freedesktop.machine1 +WatchdogSec=3min +CapabilityBoundingSet=CAP_KILL CAP_SYS_PTRACE CAP_SYS_ADMIN CAP_SETGID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE CAP_CHOWN CAP_FOWNER CAP_FSETID CAP_MKNOD +MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 +SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap +SystemCallArchitectures=native +LockPersonality=yes +IPAddressDeny=any + +# Note that machined cannot be placed in a mount namespace, since it +# needs access to the host's mount namespace in order to implement the +# "machinectl bind" operation. + +SELinuxContext=system_u:system_r:kernel_t:s0 +AppArmorProfile=profile +SELinuxContext=-system_u:system_r:kernel_t:s22 +AppArmorProfile=-profile +IODeviceLatencyTargetSec=/dev/sda 25ms +IODeviceLatencyTargetSec=/dev/sdb 2h +PIDFile=%t/mypid +PIDFile= +DisableControllers= diff --git a/test/fuzz/fuzz-unit-file/systemd-resolved.service b/test/fuzz/fuzz-unit-file/systemd-resolved.service new file mode 100644 index 00000000..0854c5f8 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/systemd-resolved.service @@ -0,0 +1,50 @@ +service +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Network Name Resolution +Documentation=man:systemd-resolved.service(8) +Documentation=https://www.freedesktop.org/wiki/Software/systemd/resolved +Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers +Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients +DefaultDependencies=no +After=systemd-sysusers.service systemd-networkd.service +Before=network.target nss-lookup.target shutdown.target +Conflicts=shutdown.target +Wants=nss-lookup.target + +[Service] +Type=notify +Restart=always +RestartSec=0 +ExecStart=!!/usr/lib/systemd/systemd-resolved +WatchdogSec=3min +User=systemd-resolve +CapabilityBoundingSet=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE +AmbientCapabilities=CAP_SETPCAP CAP_NET_RAW CAP_NET_BIND_SERVICE +PrivateTmp=yes +PrivateDevices=yes +ProtectSystem=strict +ProtectHome=yes +ProtectControlGroups=yes +ProtectKernelTunables=yes +ProtectKernelModules=yes +MemoryDenyWriteExecute=yes +RestrictRealtime=yes +RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 +SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap +SystemCallArchitectures=native +LockPersonality=yes +RuntimeDirectory=systemd/resolve +RuntimeDirectoryPreserve=yes + +[Install] +WantedBy=multi-user.target +Alias=dbus-org.freedesktop.resolve1.service diff --git a/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer b/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer new file mode 100644 index 00000000..7db361cd --- /dev/null +++ b/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer @@ -0,0 +1,40 @@ +timer +# SPDX-License-Identifier: LGPL-2.1+ +[Unit] +Description=Daily Cleanup of Temporary Directories +Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8) + +[Timer] +OnBootSec=15min +OnUnitActiveSec=1d +OnBootSec=1s +OnStartupSec=234 +OnUnitActiveSec=2y +OnUnitInactiveSec=23434 +OnCalendar=minutely +OnCalendar=*-*-* *:*:00 +OnCalendar=hourly +OnCalendar=*-*-* *:00:00 +OnCalendar=daily +OnCalendar=*-*-* 00:00:00 +OnCalendar=monthly +OnCalendar=*-*-01 00:00:00 +OnCalendar=weekly +OnCalendar=Mon *-*-* 00:00:00 +OnCalendar=yearly +OnCalendar=*-01-01 00:00:00 +OnCalendar=quarterly +OnCalendar=*-01,04,07,10-01 00:00:00 +OnCalendar=semiannually +OnCalendar=*-01,07-01 00:00:00 +OnCalendar=Fri 2012-11-23 11:12:13 + +Persistent=true +AccuracySec=24h +RandomizedDelaySec=234234234 + +Persistent=no +Unit=foo.service + +WakeSystem=false +RemainAfterElapse=true diff --git a/test/fuzz/fuzz-unit-file/timers.target b/test/fuzz/fuzz-unit-file/timers.target new file mode 100644 index 00000000..171226c6 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/timers.target @@ -0,0 +1,16 @@ +target +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Timers +Documentation=man:systemd.special(7) + +DefaultDependencies=no +Conflicts=shutdown.target diff --git a/test/fuzz/fuzz-unit-file/var-lib-machines.mount b/test/fuzz/fuzz-unit-file/var-lib-machines.mount new file mode 100644 index 00000000..9c257d11 --- /dev/null +++ b/test/fuzz/fuzz-unit-file/var-lib-machines.mount @@ -0,0 +1,19 @@ +mount +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Virtual Machine and Container Storage +ConditionPathExists=/var/lib/machines.raw + +[Mount] +What=/var/lib/machines.raw +Where=/var/lib/machines +Type=btrfs +Options=loop diff --git a/test/fuzz/fuzz-varlink/array b/test/fuzz/fuzz-varlink/array new file mode 100644 index 0000000000000000000000000000000000000000..f3ee40bcca777c00af494960ff3031f2d618b125 GIT binary patch literal 5 Mcma!!j*Vpi00jvFaR2}S literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-varlink/do-something b/test/fuzz/fuzz-varlink/do-something new file mode 100644 index 0000000000000000000000000000000000000000..3b124cb7d41abba22bc1b069e0303fd4470c309a GIT binary patch literal 81 zcmb>CQczIJO)bgDPf@Z`P|D2LD@iRb(R0ZU&IgHR=A|p?fRq#@79|1&Qj3a#%Bq1P ZK%kVCpRc3<)RmN2qy!YI<*Mak008Rl7QO%g literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-varlink/huge-method b/test/fuzz/fuzz-varlink/huge-method new file mode 100644 index 00000000..a480e417 --- /dev/null +++ b/test/fuzz/fuzz-varlink/huge-method @@ -0,0 +1 @@ +{"method":" "} \ No newline at end of file diff --git a/test/fuzz/fuzz-varlink/method-call b/test/fuzz/fuzz-varlink/method-call new file mode 100644 index 0000000000000000000000000000000000000000..8654a7c06d30569327a3c2b86cf809ac3796e10a GIT binary patch literal 301 zcmZ{eK@Ni;5JkK86oz#r5m2yOPeK$a34%dLni%iiku>V2+yCeNH(ODbXjbvw%_1;ZJry!&84m}TQkwF5f!V2UD31mYGLAiJa5LxfEiD^{F zKH<2g8PDgid{$LWFuSVJtWmllQ%rD5SSJW&D0}wf0oaZ*X!YM#F@gCtdAEVAyPCU< THmq%V+XycB&jzx+*o(&(yG%`2 literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-varlink/method-error b/test/fuzz/fuzz-varlink/method-error new file mode 100644 index 0000000000000000000000000000000000000000..9ce68d8e4bf17efe29ad2681270ead269435e994 GIT binary patch literal 110 zcmXwxQ3`+{5C!}86tdsp0lI|I4HkQbpcd-}L3H=*qu&{3ZeuM$WEYw&?Xo#sT#gJE vHM^OG3l!o{^>N|4fyS>me$je%+m1Sn33>fC;S@ntx2C3C1E~AQJZ5+SxS1k& literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-varlink/method-reply b/test/fuzz/fuzz-varlink/method-reply new file mode 100644 index 0000000000000000000000000000000000000000..cd4bd947ab80d10efaf8db55e083e56e7321248f GIT binary patch literal 142 zcmYL>K@LDL5Jjzfie}a}+EL;*O${NTGHM~xyBij4{^Gs7e<`hD^XwN8Q5+W?b zb(qG3eVXF>VG;XA)C&M>(4w&j}Luo^7(kzx~6S@+y7@!SyMa28s0R^W|dWO E1C;F}C;$Ke literal 0 HcmV?d00001 diff --git a/test/fuzz/fuzz-varlink/oss-fuzz-14688 b/test/fuzz/fuzz-varlink/oss-fuzz-14688 new file mode 100644 index 00000000..9d615db7 --- /dev/null +++ b/test/fuzz/fuzz-varlink/oss-fuzz-14688 @@ -0,0 +1 @@ + {"method":" "} \ No newline at end of file diff --git a/test/fuzz/fuzz-varlink/oss-fuzz-14708 b/test/fuzz/fuzz-varlink/oss-fuzz-14708 new file mode 100644 index 00000000..d4391cd3 --- /dev/null +++ b/test/fuzz/fuzz-varlink/oss-fuzz-14708 @@ -0,0 +1 @@ + {"method":" "} { "method": " "} { "method": " "} vvvvvvvv \ No newline at end of file diff --git a/test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf b/test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf new file mode 100644 index 0000000000000000000000000000000000000000..b0d8618298a986b6efdc10b1436ccf09a78c572a GIT binary patch literal 10014 zcmeI2v2KGf5Qa17DJ)MNQa1qyL)P>SI(D)Whgu>yB1Wnd(P!w~x9Gcc&)!$)(t|Xi zO=$x|B^u5HAUMu$Q!->vp?sTTB=a5YT~@l()3$s`ViVtL=E6nnVw7tF#IX7dj1zW zOcTIw;$k@HN+uG%y{TlqA1*>?X_Bb;Fn%zEG%|6hpFc{%Iolb6iM5P?X#Cu$Hx2UV z5;UmmVpmptaT+&B00|(0ngqToj$E9)JpCX}Dwf}xouJu&C2&+855I}miu$OMXWB5U z)|OqH8m2n13xEBUG928AjDV + +set -e + +export SYSTEMD_LOG_LEVEL=info +ROOTDIR=$(dirname $(dirname $(readlink -f $0))) +SYSTEMD_HWDB=./systemd-hwdb + +if [ ! -x "$SYSTEMD_HWDB" ]; then + echo "$SYSTEMD_HWDB does not exist, please build first" + exit 1 +fi + +D=$(mktemp --directory) +trap "rm -rf '$D'" EXIT INT QUIT PIPE +mkdir -p "$D/etc/udev" +ln -s "$ROOTDIR/hwdb.d" "$D/etc/udev/hwdb.d" + +# Test "good" properties" — no warnings or errors allowed +err=$("$SYSTEMD_HWDB" update --root "$D" 2>&1 >/dev/null) && rc= || rc=$? +if [ -n "$err" ]; then + echo "$err" + exit ${rc:-1} +fi +if [ -n "$rc" ]; then + echo "$SYSTEMD_HWDB returned $rc" + exit $rc +fi + +if [ ! -e "$D/etc/udev/hwdb.bin" ]; then + echo "$D/etc/udev/hwdb.bin was not generated" + exit 1 +fi + +# Test "bad" properties" — warnings required, errors not allowed +rm -f "$D/etc/udev/hwdb.bin" "$D/etc/udev/hwdb.d" + +ln -s "$ROOTDIR/test/hwdb.d" "$D/etc/udev/hwdb.d" +err=$("$SYSTEMD_HWDB" update --root "$D" 2>&1 >/dev/null) && rc= || rc=$? +if [ -n "$rc" ]; then + echo "$SYSTEMD_HWDB returned $rc" + exit $rc +fi +if [ -n "$err" ]; then + echo "Expected warnings" + echo "$err" +else + echo "$SYSTEMD_HWDB unexpectedly printed no warnings" + exit 1 +fi + +if [ ! -e "$D/etc/udev/hwdb.bin" ]; then + echo "$D/etc/udev/hwdb.bin was not generated" + exit 1 +fi diff --git a/test/hwdb.d/10-bad.hwdb b/test/hwdb.d/10-bad.hwdb new file mode 100644 index 00000000..0e1e1473 --- /dev/null +++ b/test/hwdb.d/10-bad.hwdb @@ -0,0 +1,26 @@ +BAD:1:no properties + +BAD:2:no properties +BAD:2:no properties + +BAD:3:no properties +BAD:3:no properties +BAD:3:no properties + +GOOD:5:bad property + NO_VALUE + +GOOD:6:bad property + =NO_NAME + NO_VALUE= + +BAD:7:match at wrong place + X=Y +BAD:7:match at wrong place + +BAD:8:match at wrong place + X=Y +BAD:8:match at wrong place + Z=z + +BAD:8:match at EOF diff --git a/test/i.service b/test/i.service new file mode 100644 index 00000000..938ea77b --- /dev/null +++ b/test/i.service @@ -0,0 +1,8 @@ +[Unit] +Description=I +Conflicts=a.service d.service +Wants=b.service +After=b.service + +[Service] +ExecStart=/bin/true diff --git a/test/journal-data/journal-1.txt b/test/journal-data/journal-1.txt new file mode 100644 index 0000000000000000000000000000000000000000..92a9199a93024812bed9b2b9f1f276e7b2dfbe7a GIT binary patch literal 586 zcmc(cO>crg5Qcl+|3ckQ*oACTi=-hDmn?AJF0k9!h$f(>{r5#Z=*?s2FrUxlon(wj z8(k?aC&{4?F~^X&D53;Yj>53(Y|C3DT471DmDpm&qokFH5#)P}UB@ZK!f|FD=QD}D z?OTD8K?>%Ow+K0&93`VrgtYY@hX^M>(m@i!&RXP|Wt@0mjLw$pIxjMFaaFx6N{ML1 z2^ZH8i3rYAp*E^kn>>BMLP{cvW)O1@%)3&x$yZNL1g6%@O;svg%kRT!+}j;UmCja8 zQJPY#)TAF;H6{3bxfzQ0c5rg~osMqk;{||myf{s6e4TdN&Rx?0L5Lsfw_EMT^M&}@ s9|jj3-8gJ#wP0R7U$$>ka97vsyvS=ApnL0I4lb_xh?|pX?QdfN7fErx=DNM5>C7@=Qft?KgB(w2#KSO(|VriEsAJ z2wtNO#5m|e~mgm!4f?0JFWe~Y}qsXb1TFP4gOsdgAvK147n zauG^e3oAn$EfV0hMKL(*N`o=1aRf1)j$s^@l`m>bPptxMhoeh1(QDhD(HApf-ZQ#q z+87gL5V*x8IV;w?Z@b_i*~r{d=-y|XBks#-mKAli%514?r@Fs_hK!gTAG8p6v-xaJ L;;~C1vo!ew_xGxy literal 0 HcmV?d00001 diff --git a/test/loopy.service b/test/loopy.service new file mode 100644 index 00000000..9eb64574 --- /dev/null +++ b/test/loopy.service @@ -0,0 +1,2 @@ +[Service] +ExecStart=/bin/true diff --git a/test/loopy.service.d/compat.conf b/test/loopy.service.d/compat.conf new file mode 100644 index 00000000..51b84b89 --- /dev/null +++ b/test/loopy.service.d/compat.conf @@ -0,0 +1,5 @@ +[Unit] +BindsTo=loopy2.service + +[Install] +Also=loopy2.service diff --git a/test/loopy2.service b/test/loopy2.service new file mode 120000 index 00000000..961b1fe9 --- /dev/null +++ b/test/loopy2.service @@ -0,0 +1 @@ +loopy.service \ No newline at end of file diff --git a/test/loopy3.service b/test/loopy3.service new file mode 100644 index 00000000..606e26b5 --- /dev/null +++ b/test/loopy3.service @@ -0,0 +1,5 @@ +[Service] +ExecStart=/bin/true + +[Unit] +Conflicts=loopy4.service diff --git a/test/loopy4.service b/test/loopy4.service new file mode 120000 index 00000000..43e5658b --- /dev/null +++ b/test/loopy4.service @@ -0,0 +1 @@ +loopy3.service \ No newline at end of file diff --git a/test/meson.build b/test/meson.build new file mode 100644 index 00000000..26861918 --- /dev/null +++ b/test/meson.build @@ -0,0 +1,290 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +test_data_files = ''' + a.service + a-conj.service + b.service + basic.target + c.service + d.service + daughter.service + dml.slice + dml-passthrough.slice + dml-passthrough-empty.service + dml-passthrough-set-dml.service + dml-passthrough-set-ml.service + dml-override.slice + dml-override-empty.service + dml-discard.slice + dml-discard-empty.service + dml-discard-set-ml.service + e.service + end.service + f.service + g.service + grandchild.service + h.service + hello-after-sleep.target + hello.service + hwdb.d/10-bad.hwdb + i.service + journal-data/journal-1.txt + journal-data/journal-2.txt + nomem.slice + nomemleaf.service + parent-deep.slice + parent.slice + sched_idle_bad.service + sched_idle_ok.service + sched_rr_bad.service + sched_rr_change.service + sched_rr_ok.service + shutdown.target + sleep.service + sockets.target + son.service + sysinit.target + test-execute/exec-basic.service + test-execute/exec-ambientcapabilities-merge-nfsnobody.service + test-execute/exec-ambientcapabilities-merge-nobody.service + test-execute/exec-ambientcapabilities-merge.service + test-execute/exec-ambientcapabilities-nfsnobody.service + test-execute/exec-ambientcapabilities-nobody.service + test-execute/exec-ambientcapabilities.service + test-execute/exec-bindpaths.service + test-execute/exec-capabilityboundingset-invert.service + test-execute/exec-capabilityboundingset-merge.service + test-execute/exec-capabilityboundingset-reset.service + test-execute/exec-capabilityboundingset-simple.service + test-execute/exec-condition-failed.service + test-execute/exec-condition-skip.service + test-execute/exec-cpuaffinity1.service + test-execute/exec-cpuaffinity2.service + test-execute/exec-cpuaffinity3.service + test-execute/exec-dynamicuser-fixeduser-adm.service + test-execute/exec-dynamicuser-fixeduser-games.service + test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service + test-execute/exec-dynamicuser-fixeduser.service + test-execute/exec-dynamicuser-statedir-migrate-step1.service + test-execute/exec-dynamicuser-statedir-migrate-step2.service + test-execute/exec-dynamicuser-statedir.service + test-execute/exec-dynamicuser-supplementarygroups.service + test-execute/exec-environment-no-substitute.service + test-execute/exec-environment-empty.service + test-execute/exec-environment-multiple.service + test-execute/exec-environment.service + test-execute/exec-environmentfile.service + test-execute/exec-group-nfsnobody.service + test-execute/exec-group-nobody.service + test-execute/exec-group-nogroup.service + test-execute/exec-group.service + test-execute/exec-ignoresigpipe-no.service + test-execute/exec-ignoresigpipe-yes.service + test-execute/exec-inaccessiblepaths-mount-propagation.service + test-execute/exec-inaccessiblepaths-sys.service + test-execute/exec-ioschedulingclass-best-effort.service + test-execute/exec-ioschedulingclass-idle.service + test-execute/exec-ioschedulingclass-none.service + test-execute/exec-ioschedulingclass-realtime.service + test-execute/exec-oomscoreadjust-negative.service + test-execute/exec-oomscoreadjust-positive.service + test-execute/exec-passenvironment-absent.service + test-execute/exec-passenvironment-empty.service + test-execute/exec-passenvironment-repeated.service + test-execute/exec-passenvironment.service + test-execute/exec-personality-aarch64.service + test-execute/exec-personality-ppc64.service + test-execute/exec-personality-ppc64le.service + test-execute/exec-personality-s390.service + test-execute/exec-personality-x86-64.service + test-execute/exec-personality-x86.service + test-execute/exec-privatedevices-disabled-by-prefix.service + test-execute/exec-privatedevices-no-capability-mknod.service + test-execute/exec-privatedevices-no-capability-sys-rawio.service + test-execute/exec-privatedevices-no.service + test-execute/exec-privatedevices-yes-capability-mknod.service + test-execute/exec-privatedevices-yes-capability-sys-rawio.service + test-execute/exec-privatedevices-yes.service + test-execute/exec-privatenetwork-yes.service + test-execute/exec-privatetmp-no.service + test-execute/exec-privatetmp-yes.service + test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service + test-execute/exec-protectkernellogs-yes-capabilities.service + test-execute/exec-protectkernellogs-no-capabilities.service + test-execute/exec-protectkernelmodules-no-capabilities.service + test-execute/exec-protectkernelmodules-yes-capabilities.service + test-execute/exec-protectkernelmodules-yes-mount-propagation.service + test-execute/exec-readonlypaths-mount-propagation.service + test-execute/exec-readonlypaths-simple.service + test-execute/exec-readonlypaths-with-bindpaths.service + test-execute/exec-readonlypaths.service + test-execute/exec-readwritepaths-mount-propagation.service + test-execute/exec-restrictnamespaces-merge-all.service + test-execute/exec-restrictnamespaces-merge-and.service + test-execute/exec-restrictnamespaces-merge-or.service + test-execute/exec-restrictnamespaces-mnt-blacklist.service + test-execute/exec-restrictnamespaces-mnt.service + test-execute/exec-restrictnamespaces-no.service + test-execute/exec-restrictnamespaces-yes.service + test-execute/exec-runtimedirectory-mode.service + test-execute/exec-runtimedirectory-owner-nfsnobody.service + test-execute/exec-runtimedirectory-owner-nobody.service + test-execute/exec-runtimedirectory-owner-nogroup.service + test-execute/exec-runtimedirectory-owner.service + test-execute/exec-runtimedirectory.service + test-execute/exec-specifier-interpolation.service + test-execute/exec-specifier.service + test-execute/exec-specifier@.service + test-execute/exec-standardinput-data.service + test-execute/exec-standardinput-file.service + test-execute/exec-standardinput-file-cat.service + test-execute/exec-standardoutput-file.service + test-execute/exec-standardoutput-append.service + test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service + test-execute/exec-supplementarygroups-multiple-groups-withgid.service + test-execute/exec-supplementarygroups-multiple-groups-withuid.service + test-execute/exec-supplementarygroups-single-group-user.service + test-execute/exec-supplementarygroups-single-group.service + test-execute/exec-supplementarygroups.service + test-execute/exec-systemcallerrornumber-name.service + test-execute/exec-systemcallerrornumber-number.service + test-execute/exec-systemcallfilter-failing.service + test-execute/exec-systemcallfilter-failing2.service + test-execute/exec-systemcallfilter-not-failing.service + test-execute/exec-systemcallfilter-not-failing2.service + test-execute/exec-systemcallfilter-system-user-nfsnobody.service + test-execute/exec-systemcallfilter-system-user-nobody.service + test-execute/exec-systemcallfilter-system-user.service + test-execute/exec-systemcallfilter-with-errno-multi.service + test-execute/exec-systemcallfilter-with-errno-name.service + test-execute/exec-systemcallfilter-with-errno-number.service + test-execute/exec-temporaryfilesystem-options.service + test-execute/exec-temporaryfilesystem-ro.service + test-execute/exec-temporaryfilesystem-rw.service + test-execute/exec-temporaryfilesystem-usr.service + test-execute/exec-umask-0177.service + test-execute/exec-umask-default.service + test-execute/exec-unsetenvironment.service + test-execute/exec-user-nfsnobody.service + test-execute/exec-user-nobody.service + test-execute/exec-user.service + test-execute/exec-workingdirectory.service + test-execute/exec-workingdirectory-trailing-dot.service + test-path/basic.target + test-path/path-changed.path + test-path/path-changed.service + test-path/path-directorynotempty.path + test-path/path-directorynotempty.service + test-path/path-exists.path + test-path/path-exists.service + test-path/path-existsglob.path + test-path/path-existsglob.service + test-path/path-makedirectory.path + test-path/path-makedirectory.service + test-path/path-modified.path + test-path/path-modified.service + test-path/path-mycustomunit.service + test-path/path-service.service + test-path/path-unit.path + test-path/paths.target + test-path/sysinit.target + test-umount/empty.mountinfo + test-umount/example.swaps + test-umount/garbled.mountinfo + test-umount/rhbug-1554943.mountinfo + testsuite.target + timers.target + unit-with-.service.d/20-override.conf + unit-with-multiple-.service.d/20-override.conf + unit-with-multiple-.service.d/30-override.conf + unit-with-multiple-dashes.service + unit-with-multiple-dashes.service.d/10-override.conf + unstoppable.service +'''.split() + +if conf.get('ENABLE_RESOLVE') == 1 + test_data_files += ''' + test-resolve/_openpgpkey.fedoraproject.org.pkts + test-resolve/fedoraproject.org.pkts + test-resolve/gandi.net.pkts + test-resolve/google.com.pkts + test-resolve/root.pkts + test-resolve/sw1a1aa-sw1a2aa-sw1a2ab-sw1a2ac.find.me.uk.pkts + test-resolve/teamits.com.pkts + test-resolve/zbyszek@fedoraproject.org.pkts + test-resolve/_443._tcp.fedoraproject.org.pkts + test-resolve/kyhwana.org.pkts + test-resolve/fake-caa.pkts + '''.split() +endif + +if install_tests + foreach file : test_data_files + subdir = file.split('/')[0] + if subdir == file + subdir = '' + endif + + install_data(file, + install_dir : testsdir + '/testdata/' + subdir) + endforeach +endif + +############################################################ + +rule_syntax_check_py = find_program('rule-syntax-check.py') +if want_tests != 'false' + test('rule-syntax-check', + rule_syntax_check_py, + args : all_rules) +endif + +############################################################ + +if conf.get('HAVE_SYSV_COMPAT') == 1 + sysv_generator_test_py = find_program('sysv-generator-test.py') + if want_tests != 'false' + test('sysv-generator-test', + sysv_generator_test_py) + endif +endif + +############################################################ + +if install_tests + install_data('run-unit-tests.py', + install_mode : 'rwxr-xr-x', + install_dir : testsdir) +endif + +############################################################ + +# prepare test/sys tree +sys_script_py = find_program('sys-script.py') +custom_target( + 'sys', + command : [sys_script_py, meson.current_build_dir()], + output : 'sys', + build_by_default : want_tests != 'false') + +if perl.found() + udev_test_pl = find_program('udev-test.pl') + if want_tests != 'false' + test('udev-test', + udev_test_pl, + timeout : 180) + endif +else + message('Skipping udev-test because perl is not available') +endif + +if conf.get('ENABLE_HWDB') == 1 + hwdb_test_sh = find_program('hwdb-test.sh') + if want_tests != 'false' + test('hwdb-test', + hwdb_test_sh, + timeout : 90) + endif +endif + +subdir('fuzz') diff --git a/test/mkosi.build.networkd-test b/test/mkosi.build.networkd-test new file mode 100755 index 00000000..cdaa4302 --- /dev/null +++ b/test/mkosi.build.networkd-test @@ -0,0 +1,24 @@ +#!/bin/sh +set -ex + +# First, source in the main build script +. "$SRCDIR"/mkosi.build + +mkdir -p "$DESTDIR"/usr/local/bin +cp "$SRCDIR"/test/networkd-test.py "$DESTDIR"/usr/local/bin/networkd-test.py + +mkdir -p "$DESTDIR"/etc/systemd/system +cat > "$DESTDIR"/etc/systemd/system/networkd-test.service <&$fd + sleep 0.1 + done +done diff --git a/test/networkd-test.py b/test/networkd-test.py new file mode 100755 index 00000000..beb3bd9e --- /dev/null +++ b/test/networkd-test.py @@ -0,0 +1,1123 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ +# +# networkd integration test +# This uses temporary configuration in /run and temporary veth devices, and +# does not write anything on disk or change any system configuration; +# but it assumes (and checks at the beginning) that networkd is not currently +# running. +# +# This can be run on a normal installation, in QEMU, nspawn (with +# --private-network), LXD (with "--config raw.lxc=lxc.aa_profile=unconfined"), +# or LXC system containers. You need at least the "ip" tool from the iproute +# package; it is recommended to install dnsmasq too to get full test coverage. +# +# ATTENTION: This uses the *installed* networkd, not the one from the built +# source tree. +# +# © 2015 Canonical Ltd. +# Author: Martin Pitt + +import errno +import os +import shutil +import socket +import subprocess +import sys +import tempfile +import time +import unittest + +HAVE_DNSMASQ = shutil.which('dnsmasq') is not None +IS_CONTAINER = subprocess.call(['systemd-detect-virt', '--quiet', '--container']) == 0 + +NETWORK_UNITDIR = '/run/systemd/network' + +NETWORKD_WAIT_ONLINE = shutil.which('systemd-networkd-wait-online', + path='/usr/lib/systemd:/lib/systemd') + +RESOLV_CONF = '/run/systemd/resolve/resolv.conf' + +tmpmounts = [] +running_units = [] +stopped_units = [] + + +def setUpModule(): + global tmpmounts + + """Initialize the environment, and perform sanity checks on it.""" + if NETWORKD_WAIT_ONLINE is None: + raise OSError(errno.ENOENT, 'systemd-networkd-wait-online not found') + + # Do not run any tests if the system is using networkd already and it's not virtualized + if (subprocess.call(['systemctl', 'is-active', '--quiet', 'systemd-networkd.service']) == 0 and + subprocess.call(['systemd-detect-virt', '--quiet']) != 0): + raise unittest.SkipTest('not virtualized and networkd is already active') + + # Ensure we don't mess with an existing networkd config + for u in ['systemd-networkd.socket', 'systemd-networkd', 'systemd-resolved']: + if subprocess.call(['systemctl', 'is-active', '--quiet', u]) == 0: + subprocess.call(['systemctl', 'stop', u]) + running_units.append(u) + else: + stopped_units.append(u) + + # create static systemd-network user for networkd-test-router.service (it + # needs to do some stuff as root and can't start as user; but networkd + # still insists on the user) + if subprocess.call(['getent', 'passwd', 'systemd-network']) != 0: + subprocess.call(['useradd', '--system', '--no-create-home', 'systemd-network']) + + for d in ['/etc/systemd/network', '/run/systemd/network', + '/run/systemd/netif', '/run/systemd/resolve']: + if os.path.isdir(d): + subprocess.check_call(["mount", "-t", "tmpfs", "none", d]) + tmpmounts.append(d) + if os.path.isdir('/run/systemd/resolve'): + os.chmod('/run/systemd/resolve', 0o755) + shutil.chown('/run/systemd/resolve', 'systemd-resolve', 'systemd-resolve') + if os.path.isdir('/run/systemd/netif'): + os.chmod('/run/systemd/netif', 0o755) + shutil.chown('/run/systemd/netif', 'systemd-network', 'systemd-network') + + # Avoid "Failed to open /dev/tty" errors in containers. + os.environ['SYSTEMD_LOG_TARGET'] = 'journal' + + # Ensure the unit directory exists so tests can dump files into it. + os.makedirs(NETWORK_UNITDIR, exist_ok=True) + + +def tearDownModule(): + global tmpmounts + for d in tmpmounts: + subprocess.check_call(["umount", d]) + for u in stopped_units: + subprocess.call(["systemctl", "stop", u]) + for u in running_units: + subprocess.call(["systemctl", "restart", u]) + + +class NetworkdTestingUtilities: + """Provide a set of utility functions to facilitate networkd tests. + + This class must be inherited along with unittest.TestCase to define + some required methods. + """ + + def add_veth_pair(self, veth, peer, veth_options=(), peer_options=()): + """Add a veth interface pair, and queue them to be removed.""" + subprocess.check_call(['ip', 'link', 'add', 'name', veth] + + list(veth_options) + + ['type', 'veth', 'peer', 'name', peer] + + list(peer_options)) + self.addCleanup(subprocess.call, ['ip', 'link', 'del', 'dev', peer]) + + def write_config(self, path, contents): + """"Write a configuration file, and queue it to be removed.""" + + with open(path, 'w') as f: + f.write(contents) + + self.addCleanup(os.remove, path) + + def write_network(self, unit_name, contents): + """Write a network unit file, and queue it to be removed.""" + self.write_config(os.path.join(NETWORK_UNITDIR, unit_name), contents) + + def write_network_dropin(self, unit_name, dropin_name, contents): + """Write a network unit drop-in, and queue it to be removed.""" + dropin_dir = os.path.join(NETWORK_UNITDIR, "{}.d".format(unit_name)) + dropin_path = os.path.join(dropin_dir, "{}.conf".format(dropin_name)) + + os.makedirs(dropin_dir, exist_ok=True) + self.addCleanup(os.rmdir, dropin_dir) + with open(dropin_path, 'w') as dropin: + dropin.write(contents) + self.addCleanup(os.remove, dropin_path) + + def read_attr(self, link, attribute): + """Read a link attributed from the sysfs.""" + # Note we we don't want to check if interface `link' is managed, we + # want to evaluate link variable and pass the value of the link to + # assert_link_states e.g. eth0=managed. + self.assert_link_states(**{link:'managed'}) + with open(os.path.join('/sys/class/net', link, attribute)) as f: + return f.readline().strip() + + def assert_link_states(self, **kwargs): + """Match networkctl link states to the given ones. + + Each keyword argument should be the name of a network interface + with its expected value of the "SETUP" column in output from + networkctl. The interfaces have five seconds to come online + before the check is performed. Every specified interface must + be present in the output, and any other interfaces found in the + output are ignored. + + A special interface state "managed" is supported, which matches + any value in the "SETUP" column other than "unmanaged". + """ + if not kwargs: + return + interfaces = set(kwargs) + + # Wait for the requested interfaces, but don't fail for them. + subprocess.call([NETWORKD_WAIT_ONLINE, '--timeout=5'] + + ['--interface={}'.format(iface) for iface in kwargs]) + + # Validate each link state found in the networkctl output. + out = subprocess.check_output(['networkctl', '--no-legend']).rstrip() + for line in out.decode('utf-8').split('\n'): + fields = line.split() + if len(fields) >= 5 and fields[1] in kwargs: + iface = fields[1] + expected = kwargs[iface] + actual = fields[-1] + if (actual != expected and + not (expected == 'managed' and actual != 'unmanaged')): + self.fail("Link {} expects state {}, found {}".format(iface, expected, actual)) + interfaces.remove(iface) + + # Ensure that all requested interfaces have been covered. + if interfaces: + self.fail("Missing links in status output: {}".format(interfaces)) + + +class BridgeTest(NetworkdTestingUtilities, unittest.TestCase): + """Provide common methods for testing networkd against servers.""" + + def setUp(self): + self.write_network('port1.netdev', '''\ +[NetDev] +Name=port1 +Kind=dummy +MACAddress=12:34:56:78:9a:bc''') + self.write_network('port2.netdev', '''\ +[NetDev] +Name=port2 +Kind=dummy +MACAddress=12:34:56:78:9a:bd''') + self.write_network('mybridge.netdev', '''\ +[NetDev] +Name=mybridge +Kind=bridge''') + self.write_network('port1.network', '''\ +[Match] +Name=port1 +[Network] +Bridge=mybridge''') + self.write_network('port2.network', '''\ +[Match] +Name=port2 +[Network] +Bridge=mybridge''') + self.write_network('mybridge.network', '''\ +[Match] +Name=mybridge +[Network] +DNS=192.168.250.1 +Address=192.168.250.33/24 +Gateway=192.168.250.1''') + subprocess.call(['systemctl', 'reset-failed', 'systemd-networkd', 'systemd-resolved']) + subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) + + def tearDown(self): + subprocess.check_call(['systemctl', 'stop', 'systemd-networkd']) + subprocess.check_call(['ip', 'link', 'del', 'mybridge']) + subprocess.check_call(['ip', 'link', 'del', 'port1']) + subprocess.check_call(['ip', 'link', 'del', 'port2']) + + def test_bridge_init(self): + self.assert_link_states( + port1='managed', + port2='managed', + mybridge='managed') + + def test_bridge_port_priority(self): + self.assertEqual(self.read_attr('port1', 'brport/priority'), '32') + self.write_network_dropin('port1.network', 'priority', '''\ +[Bridge] +Priority=28 +''') + subprocess.check_call(['systemctl', 'restart', 'systemd-networkd']) + self.assertEqual(self.read_attr('port1', 'brport/priority'), '28') + + def test_bridge_port_priority_set_zero(self): + """It should be possible to set the bridge port priority to 0""" + self.assertEqual(self.read_attr('port2', 'brport/priority'), '32') + self.write_network_dropin('port2.network', 'priority', '''\ +[Bridge] +Priority=0 +''') + subprocess.check_call(['systemctl', 'restart', 'systemd-networkd']) + self.assertEqual(self.read_attr('port2', 'brport/priority'), '0') + + def test_bridge_port_property(self): + """Test the "[Bridge]" section keys""" + self.assertEqual(self.read_attr('port2', 'brport/priority'), '32') + self.write_network_dropin('port2.network', 'property', '''\ +[Bridge] +UnicastFlood=true +HairPin=true +UseBPDU=true +FastLeave=true +AllowPortToBeRoot=true +Cost=555 +Priority=23 +''') + subprocess.check_call(['systemctl', 'restart', 'systemd-networkd']) + + self.assertEqual(self.read_attr('port2', 'brport/priority'), '23') + self.assertEqual(self.read_attr('port2', 'brport/hairpin_mode'), '1') + self.assertEqual(self.read_attr('port2', 'brport/path_cost'), '555') + self.assertEqual(self.read_attr('port2', 'brport/multicast_fast_leave'), '1') + self.assertEqual(self.read_attr('port2', 'brport/unicast_flood'), '1') + self.assertEqual(self.read_attr('port2', 'brport/bpdu_guard'), '1') + self.assertEqual(self.read_attr('port2', 'brport/root_block'), '1') + +class ClientTestBase(NetworkdTestingUtilities): + """Provide common methods for testing networkd against servers.""" + + @classmethod + def setUpClass(klass): + klass.orig_log_level = subprocess.check_output( + ['systemctl', 'show', '--value', '--property', 'LogLevel'], + universal_newlines=True).strip() + subprocess.check_call(['systemd-analyze', 'log-level', 'debug']) + + @classmethod + def tearDownClass(klass): + subprocess.check_call(['systemd-analyze', 'log-level', klass.orig_log_level]) + + def setUp(self): + self.iface = 'test_eth42' + self.if_router = 'router_eth42' + self.workdir_obj = tempfile.TemporaryDirectory() + self.workdir = self.workdir_obj.name + self.config = 'test_eth42.network' + + # get current journal cursor + subprocess.check_output(['journalctl', '--sync']) + out = subprocess.check_output(['journalctl', '-b', '--quiet', + '--no-pager', '-n0', '--show-cursor'], + universal_newlines=True) + self.assertTrue(out.startswith('-- cursor:')) + self.journal_cursor = out.split()[-1] + + subprocess.call(['systemctl', 'reset-failed', 'systemd-networkd', 'systemd-resolved']) + + def tearDown(self): + self.shutdown_iface() + subprocess.call(['systemctl', 'stop', 'systemd-networkd']) + subprocess.call(['ip', 'link', 'del', 'dummy0'], + stderr=subprocess.DEVNULL) + + def show_journal(self, unit): + '''Show journal of given unit since start of the test''' + + print('---- {} ----'.format(unit)) + subprocess.check_output(['journalctl', '--sync']) + sys.stdout.flush() + subprocess.call(['journalctl', '-b', '--no-pager', '--quiet', + '--cursor', self.journal_cursor, '-u', unit]) + + def create_iface(self, ipv6=False): + '''Create test interface with DHCP server behind it''' + + raise NotImplementedError('must be implemented by a subclass') + + def shutdown_iface(self): + '''Remove test interface and stop DHCP server''' + + raise NotImplementedError('must be implemented by a subclass') + + def print_server_log(self): + '''Print DHCP server log for debugging failures''' + + raise NotImplementedError('must be implemented by a subclass') + + def start_unit(self, unit): + try: + subprocess.check_call(['systemctl', 'start', unit]) + except subprocess.CalledProcessError: + self.show_journal(unit) + raise + + def do_test(self, coldplug=True, ipv6=False, extra_opts='', + online_timeout=10, dhcp_mode='yes'): + self.start_unit('systemd-resolved') + self.write_network(self.config, '''\ +[Match] +Name={} +[Network] +DHCP={} +{}'''.format(self.iface, dhcp_mode, extra_opts)) + + if coldplug: + # create interface first, then start networkd + self.create_iface(ipv6=ipv6) + self.start_unit('systemd-networkd') + elif coldplug is not None: + # start networkd first, then create interface + self.start_unit('systemd-networkd') + self.create_iface(ipv6=ipv6) + else: + # "None" means test sets up interface by itself + self.start_unit('systemd-networkd') + + try: + subprocess.check_call([NETWORKD_WAIT_ONLINE, '--interface', + self.iface, '--timeout=%i' % online_timeout]) + + if ipv6: + # check iface state and IP 6 address; FIXME: we need to wait a bit + # longer, as the iface is "configured" already with IPv4 *or* + # IPv6, but we want to wait for both + for _ in range(10): + out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.iface]) + if b'state UP' in out and b'inet6 2600' in out and b'inet 192.168' in out: + break + time.sleep(1) + else: + self.fail('timed out waiting for IPv6 configuration') + + self.assertRegex(out, b'inet6 2600::.* scope global .*dynamic') + self.assertRegex(out, b'inet6 fe80::.* scope link') + else: + # should have link-local address on IPv6 only + out = subprocess.check_output(['ip', '-6', 'a', 'show', 'dev', self.iface]) + self.assertRegex(out, br'inet6 fe80::.* scope link') + self.assertNotIn(b'scope global', out) + + # should have IPv4 address + out = subprocess.check_output(['ip', '-4', 'a', 'show', 'dev', self.iface]) + self.assertIn(b'state UP', out) + self.assertRegex(out, br'inet 192.168.5.\d+/.* scope global dynamic') + + # check networkctl state + out = subprocess.check_output(['networkctl']) + self.assertRegex(out, (r'{}\s+ether\s+[a-z-]+\s+unmanaged'.format(self.if_router)).encode()) + self.assertRegex(out, (r'{}\s+ether\s+routable\s+configured'.format(self.iface)).encode()) + + out = subprocess.check_output(['networkctl', 'status', self.iface]) + self.assertRegex(out, br'Type:\s+ether') + self.assertRegex(out, br'State:\s+routable.*configured') + self.assertRegex(out, br'Address:\s+192.168.5.\d+') + if ipv6: + self.assertRegex(out, br'2600::') + else: + self.assertNotIn(br'2600::', out) + self.assertRegex(out, br'fe80::') + self.assertRegex(out, br'Gateway:\s+192.168.5.1') + self.assertRegex(out, br'DNS:\s+192.168.5.1') + except (AssertionError, subprocess.CalledProcessError): + # show networkd status, journal, and DHCP server log on failure + with open(os.path.join(NETWORK_UNITDIR, self.config)) as f: + print('\n---- {} ----\n{}'.format(self.config, f.read())) + print('---- interface status ----') + sys.stdout.flush() + subprocess.call(['ip', 'a', 'show', 'dev', self.iface]) + print('---- networkctl status {} ----'.format(self.iface)) + sys.stdout.flush() + rc = subprocess.call(['networkctl', 'status', self.iface]) + if rc != 0: + print("'networkctl status' exited with an unexpected code {}".format(rc)) + self.show_journal('systemd-networkd.service') + self.print_server_log() + raise + + for timeout in range(50): + with open(RESOLV_CONF) as f: + contents = f.read() + if 'nameserver 192.168.5.1\n' in contents: + break + time.sleep(0.1) + else: + self.fail('nameserver 192.168.5.1 not found in ' + RESOLV_CONF) + + if coldplug is False: + # check post-down.d hook + self.shutdown_iface() + + def test_coldplug_dhcp_yes_ip4(self): + # we have a 12s timeout on RA, so we need to wait longer + self.do_test(coldplug=True, ipv6=False, online_timeout=15) + + def test_coldplug_dhcp_yes_ip4_no_ra(self): + # with disabling RA explicitly things should be fast + self.do_test(coldplug=True, ipv6=False, + extra_opts='IPv6AcceptRA=False') + + def test_coldplug_dhcp_ip4_only(self): + # we have a 12s timeout on RA, so we need to wait longer + self.do_test(coldplug=True, ipv6=False, dhcp_mode='ipv4', + online_timeout=15) + + def test_coldplug_dhcp_ip4_only_no_ra(self): + # with disabling RA explicitly things should be fast + self.do_test(coldplug=True, ipv6=False, dhcp_mode='ipv4', + extra_opts='IPv6AcceptRA=False') + + def test_coldplug_dhcp_ip6(self): + self.do_test(coldplug=True, ipv6=True) + + def test_hotplug_dhcp_ip4(self): + # With IPv4 only we have a 12s timeout on RA, so we need to wait longer + self.do_test(coldplug=False, ipv6=False, online_timeout=15) + + def test_hotplug_dhcp_ip6(self): + self.do_test(coldplug=False, ipv6=True) + + def test_route_only_dns(self): + self.write_network('myvpn.netdev', '''\ +[NetDev] +Name=dummy0 +Kind=dummy +MACAddress=12:34:56:78:9a:bc''') + self.write_network('myvpn.network', '''\ +[Match] +Name=dummy0 +[Network] +Address=192.168.42.100/24 +DNS=192.168.42.1 +Domains= ~company''') + + try: + self.do_test(coldplug=True, ipv6=False, + extra_opts='IPv6AcceptRouterAdvertisements=False') + except subprocess.CalledProcessError as e: + # networkd often fails to start in LXC: https://github.com/systemd/systemd/issues/11848 + if IS_CONTAINER and e.cmd == ['systemctl', 'start', 'systemd-networkd']: + raise unittest.SkipTest('https://github.com/systemd/systemd/issues/11848') + else: + raise + + with open(RESOLV_CONF) as f: + contents = f.read() + # ~company is not a search domain, only a routing domain + self.assertNotRegex(contents, 'search.*company') + # our global server should appear + self.assertIn('nameserver 192.168.5.1\n', contents) + # should not have domain-restricted server as global server + self.assertNotIn('nameserver 192.168.42.1\n', contents) + + def test_route_only_dns_all_domains(self): + self.write_network('myvpn.netdev', '''[NetDev] +Name=dummy0 +Kind=dummy +MACAddress=12:34:56:78:9a:bc''') + self.write_network('myvpn.network', '''[Match] +Name=dummy0 +[Network] +Address=192.168.42.100/24 +DNS=192.168.42.1 +Domains= ~company ~.''') + + try: + self.do_test(coldplug=True, ipv6=False, + extra_opts='IPv6AcceptRouterAdvertisements=False') + except subprocess.CalledProcessError as e: + # networkd often fails to start in LXC: https://github.com/systemd/systemd/issues/11848 + if IS_CONTAINER and e.cmd == ['systemctl', 'start', 'systemd-networkd']: + raise unittest.SkipTest('https://github.com/systemd/systemd/issues/11848') + else: + raise + + with open(RESOLV_CONF) as f: + contents = f.read() + + # ~company is not a search domain, only a routing domain + self.assertNotRegex(contents, 'search.*company') + + # our global server should appear + self.assertIn('nameserver 192.168.5.1\n', contents) + # should have company server as global server due to ~. + self.assertIn('nameserver 192.168.42.1\n', contents) + + +@unittest.skipUnless(HAVE_DNSMASQ, 'dnsmasq not installed') +class DnsmasqClientTest(ClientTestBase, unittest.TestCase): + '''Test networkd client against dnsmasq''' + + def setUp(self): + super().setUp() + self.dnsmasq = None + self.iface_mac = 'de:ad:be:ef:47:11' + + def create_iface(self, ipv6=False, dnsmasq_opts=None): + '''Create test interface with DHCP server behind it''' + + # add veth pair + subprocess.check_call(['ip', 'link', 'add', 'name', self.iface, + 'address', self.iface_mac, + 'type', 'veth', 'peer', 'name', self.if_router]) + + # give our router an IP + subprocess.check_call(['ip', 'a', 'flush', 'dev', self.if_router]) + subprocess.check_call(['ip', 'a', 'add', '192.168.5.1/24', 'dev', self.if_router]) + if ipv6: + subprocess.check_call(['ip', 'a', 'add', '2600::1/64', 'dev', self.if_router]) + subprocess.check_call(['ip', 'link', 'set', self.if_router, 'up']) + + # add DHCP server + self.dnsmasq_log = os.path.join(self.workdir, 'dnsmasq.log') + lease_file = os.path.join(self.workdir, 'dnsmasq.leases') + if ipv6: + extra_opts = ['--enable-ra', '--dhcp-range=2600::10,2600::20'] + else: + extra_opts = [] + if dnsmasq_opts: + extra_opts += dnsmasq_opts + self.dnsmasq = subprocess.Popen( + ['dnsmasq', '--keep-in-foreground', '--log-queries', + '--log-facility=' + self.dnsmasq_log, '--conf-file=/dev/null', + '--dhcp-leasefile=' + lease_file, '--bind-interfaces', + '--interface=' + self.if_router, '--except-interface=lo', + '--dhcp-range=192.168.5.10,192.168.5.200'] + extra_opts) + + def shutdown_iface(self): + '''Remove test interface and stop DHCP server''' + + if self.if_router: + subprocess.check_call(['ip', 'link', 'del', 'dev', self.if_router]) + self.if_router = None + if self.dnsmasq: + self.dnsmasq.kill() + self.dnsmasq.wait() + self.dnsmasq = None + + def print_server_log(self): + '''Print DHCP server log for debugging failures''' + + with open(self.dnsmasq_log) as f: + sys.stdout.write('\n\n---- dnsmasq log ----\n{}\n------\n\n'.format(f.read())) + + def test_resolved_domain_restricted_dns(self): + '''resolved: domain-restricted DNS servers''' + + # FIXME: resolvectl query fails with enabled DNSSEC against our dnsmasq + conf = '/run/systemd/resolved.conf.d/test-disable-dnssec.conf' + os.makedirs(os.path.dirname(conf), exist_ok=True) + with open(conf, 'w') as f: + f.write('[Resolve]\nDNSSEC=no\n') + self.addCleanup(os.remove, conf) + + # create interface for generic connections; this will map all DNS names + # to 192.168.42.1 + self.create_iface(dnsmasq_opts=['--address=/#/192.168.42.1']) + self.write_network('general.network', '''\ +[Match] +Name={} +[Network] +DHCP=ipv4 +IPv6AcceptRA=False'''.format(self.iface)) + + # create second device/dnsmasq for a .company/.lab VPN interface + # static IPs for simplicity + self.add_veth_pair('testvpnclient', 'testvpnrouter') + subprocess.check_call(['ip', 'a', 'flush', 'dev', 'testvpnrouter']) + subprocess.check_call(['ip', 'a', 'add', '10.241.3.1/24', 'dev', 'testvpnrouter']) + subprocess.check_call(['ip', 'link', 'set', 'testvpnrouter', 'up']) + + vpn_dnsmasq_log = os.path.join(self.workdir, 'dnsmasq-vpn.log') + vpn_dnsmasq = subprocess.Popen( + ['dnsmasq', '--keep-in-foreground', '--log-queries', + '--log-facility=' + vpn_dnsmasq_log, '--conf-file=/dev/null', + '--dhcp-leasefile=/dev/null', '--bind-interfaces', + '--interface=testvpnrouter', '--except-interface=lo', + '--address=/math.lab/10.241.3.3', '--address=/cantina.company/10.241.4.4']) + self.addCleanup(vpn_dnsmasq.wait) + self.addCleanup(vpn_dnsmasq.kill) + + self.write_network('vpn.network', '''\ +[Match] +Name=testvpnclient +[Network] +IPv6AcceptRA=False +Address=10.241.3.2/24 +DNS=10.241.3.1 +Domains= ~company ~lab''') + + self.start_unit('systemd-networkd') + subprocess.check_call([NETWORKD_WAIT_ONLINE, '--interface', self.iface, + '--interface=testvpnclient', '--timeout=20']) + + # ensure we start fresh with every test + subprocess.check_call(['systemctl', 'restart', 'systemd-resolved']) + + # test vpnclient specific domains; these should *not* be answered by + # the general DNS + out = subprocess.check_output(['resolvectl', 'query', 'math.lab']) + self.assertIn(b'math.lab: 10.241.3.3', out) + out = subprocess.check_output(['resolvectl', 'query', 'kettle.cantina.company']) + self.assertIn(b'kettle.cantina.company: 10.241.4.4', out) + + # test general domains + out = subprocess.check_output(['resolvectl', 'query', 'megasearch.net']) + self.assertIn(b'megasearch.net: 192.168.42.1', out) + + with open(self.dnsmasq_log) as f: + general_log = f.read() + with open(vpn_dnsmasq_log) as f: + vpn_log = f.read() + + # VPN domains should only be sent to VPN DNS + self.assertRegex(vpn_log, 'query.*math.lab') + self.assertRegex(vpn_log, 'query.*cantina.company') + self.assertNotIn('.lab', general_log) + self.assertNotIn('.company', general_log) + + # general domains should not be sent to the VPN DNS + self.assertRegex(general_log, 'query.*megasearch.net') + self.assertNotIn('megasearch.net', vpn_log) + + def test_resolved_etc_hosts(self): + '''resolved queries to /etc/hosts''' + + # FIXME: -t MX query fails with enabled DNSSEC (even when using + # the known negative trust anchor .internal instead of .example.com) + conf = '/run/systemd/resolved.conf.d/test-disable-dnssec.conf' + os.makedirs(os.path.dirname(conf), exist_ok=True) + with open(conf, 'w') as f: + f.write('[Resolve]\nDNSSEC=no\nLLMNR=no\nMulticastDNS=no\n') + self.addCleanup(os.remove, conf) + + # create /etc/hosts bind mount which resolves my.example.com for IPv4 + hosts = os.path.join(self.workdir, 'hosts') + with open(hosts, 'w') as f: + f.write('172.16.99.99 my.example.com\n') + subprocess.check_call(['mount', '--bind', hosts, '/etc/hosts']) + self.addCleanup(subprocess.call, ['umount', '/etc/hosts']) + subprocess.check_call(['systemctl', 'stop', 'systemd-resolved.service']) + + # note: different IPv4 address here, so that it's easy to tell apart + # what resolved the query + self.create_iface(dnsmasq_opts=['--host-record=my.example.com,172.16.99.1,2600::99:99', + '--host-record=other.example.com,172.16.0.42,2600::42', + '--mx-host=example.com,mail.example.com'], + ipv6=True) + self.do_test(coldplug=None, ipv6=True) + + try: + # family specific queries + out = subprocess.check_output(['resolvectl', 'query', '-4', 'my.example.com']) + self.assertIn(b'my.example.com: 172.16.99.99', out) + # we don't expect an IPv6 answer; if /etc/hosts has any IP address, + # it's considered a sufficient source + self.assertNotEqual(subprocess.call(['resolvectl', 'query', '-6', 'my.example.com']), 0) + # "any family" query; IPv4 should come from /etc/hosts + out = subprocess.check_output(['resolvectl', 'query', 'my.example.com']) + self.assertIn(b'my.example.com: 172.16.99.99', out) + # IP → name lookup; again, takes the /etc/hosts one + out = subprocess.check_output(['resolvectl', 'query', '172.16.99.99']) + self.assertIn(b'172.16.99.99: my.example.com', out) + + # non-address RRs should fall back to DNS + out = subprocess.check_output(['resolvectl', 'query', '--type=MX', 'example.com']) + self.assertIn(b'example.com IN MX 1 mail.example.com', out) + + # other domains query DNS + out = subprocess.check_output(['resolvectl', 'query', 'other.example.com']) + self.assertIn(b'172.16.0.42', out) + out = subprocess.check_output(['resolvectl', 'query', '172.16.0.42']) + self.assertIn(b'172.16.0.42: other.example.com', out) + except (AssertionError, subprocess.CalledProcessError): + self.show_journal('systemd-resolved.service') + self.print_server_log() + raise + + def test_transient_hostname(self): + '''networkd sets transient hostname from DHCP''' + + orig_hostname = socket.gethostname() + self.addCleanup(socket.sethostname, orig_hostname) + # temporarily move /etc/hostname away; restart hostnamed to pick it up + if os.path.exists('/etc/hostname'): + subprocess.check_call(['mount', '--bind', '/dev/null', '/etc/hostname']) + self.addCleanup(subprocess.call, ['umount', '/etc/hostname']) + subprocess.check_call(['systemctl', 'stop', 'systemd-hostnamed.service']) + self.addCleanup(subprocess.call, ['systemctl', 'stop', 'systemd-hostnamed.service']) + + self.create_iface(dnsmasq_opts=['--dhcp-host={},192.168.5.210,testgreen'.format(self.iface_mac)]) + self.do_test(coldplug=None, extra_opts='IPv6AcceptRA=False', dhcp_mode='ipv4') + + try: + # should have received the fixed IP above + out = subprocess.check_output(['ip', '-4', 'a', 'show', 'dev', self.iface]) + self.assertRegex(out, b'inet 192.168.5.210/24 .* scope global dynamic') + # should have set transient hostname in hostnamed; this is + # sometimes a bit lagging (issue #4753), so retry a few times + for retry in range(1, 6): + out = subprocess.check_output(['hostnamectl']) + if b'testgreen' in out: + break + time.sleep(5) + sys.stdout.write('[retry %i] ' % retry) + sys.stdout.flush() + else: + self.fail('Transient hostname not found in hostnamectl:\n{}'.format(out.decode())) + # and also applied to the system + self.assertEqual(socket.gethostname(), 'testgreen') + except AssertionError: + self.show_journal('systemd-networkd.service') + self.show_journal('systemd-hostnamed.service') + self.print_server_log() + raise + + def test_transient_hostname_with_static(self): + '''transient hostname is not applied if static hostname exists''' + + orig_hostname = socket.gethostname() + self.addCleanup(socket.sethostname, orig_hostname) + + if not os.path.exists('/etc/hostname'): + self.write_config('/etc/hostname', "foobarqux") + else: + self.write_config('/run/hostname.tmp', "foobarqux") + subprocess.check_call(['mount', '--bind', '/run/hostname.tmp', '/etc/hostname']) + self.addCleanup(subprocess.call, ['umount', '/etc/hostname']) + + socket.sethostname("foobarqux"); + + subprocess.check_call(['systemctl', 'stop', 'systemd-hostnamed.service']) + self.addCleanup(subprocess.call, ['systemctl', 'stop', 'systemd-hostnamed.service']) + + self.create_iface(dnsmasq_opts=['--dhcp-host={},192.168.5.210,testgreen'.format(self.iface_mac)]) + self.do_test(coldplug=None, extra_opts='IPv6AcceptRA=False', dhcp_mode='ipv4') + + try: + # should have received the fixed IP above + out = subprocess.check_output(['ip', '-4', 'a', 'show', 'dev', self.iface]) + self.assertRegex(out, b'inet 192.168.5.210/24 .* scope global dynamic') + # static hostname wins over transient one, thus *not* applied + self.assertEqual(socket.gethostname(), "foobarqux") + except AssertionError: + self.show_journal('systemd-networkd.service') + self.show_journal('systemd-hostnamed.service') + self.print_server_log() + raise + + +class NetworkdClientTest(ClientTestBase, unittest.TestCase): + '''Test networkd client against networkd server''' + + def setUp(self): + super().setUp() + self.dnsmasq = None + + def create_iface(self, ipv6=False, dhcpserver_opts=None): + '''Create test interface with DHCP server behind it''' + + # run "router-side" networkd in own mount namespace to shield it from + # "client-side" configuration and networkd + (fd, script) = tempfile.mkstemp(prefix='networkd-router.sh') + self.addCleanup(os.remove, script) + with os.fdopen(fd, 'w+') as f: + f.write('''\ +#!/bin/sh +set -eu +mkdir -p /run/systemd/network +mkdir -p /run/systemd/netif +mount -t tmpfs none /run/systemd/network +mount -t tmpfs none /run/systemd/netif +[ ! -e /run/dbus ] || mount -t tmpfs none /run/dbus +# create router/client veth pair +cat << EOF > /run/systemd/network/test.netdev +[NetDev] +Name=%(ifr)s +Kind=veth + +[Peer] +Name=%(ifc)s +EOF + +cat << EOF > /run/systemd/network/test.network +[Match] +Name=%(ifr)s + +[Network] +Address=192.168.5.1/24 +%(addr6)s +DHCPServer=yes + +[DHCPServer] +PoolOffset=10 +PoolSize=50 +DNS=192.168.5.1 +%(dhopts)s +EOF + +# run networkd as in systemd-networkd.service +exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ { s/^.*=//; s/^[@+-]//; s/^!*//; p}') +''' % {'ifr': self.if_router, 'ifc': self.iface, 'addr6': ipv6 and 'Address=2600::1/64' or '', + 'dhopts': dhcpserver_opts or ''}) + + os.fchmod(fd, 0o755) + + subprocess.check_call(['systemd-run', '--unit=networkd-test-router.service', + '-p', 'InaccessibleDirectories=-/etc/systemd/network', + '-p', 'InaccessibleDirectories=-/run/systemd/network', + '-p', 'InaccessibleDirectories=-/run/systemd/netif', + '--service-type=notify', script]) + + # wait until devices got created + for _ in range(50): + out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.if_router]) + if b'state UP' in out and b'scope global' in out: + break + time.sleep(0.1) + + def shutdown_iface(self): + '''Remove test interface and stop DHCP server''' + + if self.if_router: + subprocess.check_call(['systemctl', 'stop', 'networkd-test-router.service']) + # ensure failed transient unit does not stay around + subprocess.call(['systemctl', 'reset-failed', 'networkd-test-router.service']) + subprocess.call(['ip', 'link', 'del', 'dev', self.if_router]) + self.if_router = None + + def print_server_log(self): + '''Print DHCP server log for debugging failures''' + + self.show_journal('networkd-test-router.service') + + @unittest.skip('networkd does not have DHCPv6 server support') + def test_hotplug_dhcp_ip6(self): + pass + + @unittest.skip('networkd does not have DHCPv6 server support') + def test_coldplug_dhcp_ip6(self): + pass + + def test_search_domains(self): + + # we don't use this interface for this test + self.if_router = None + + self.write_network('test.netdev', '''\ +[NetDev] +Name=dummy0 +Kind=dummy +MACAddress=12:34:56:78:9a:bc''') + self.write_network('test.network', '''\ +[Match] +Name=dummy0 +[Network] +Address=192.168.42.100/24 +DNS=192.168.42.1 +Domains= one two three four five six seven eight nine ten''') + + self.start_unit('systemd-networkd') + + for timeout in range(50): + with open(RESOLV_CONF) as f: + contents = f.read() + if ' one' in contents: + break + time.sleep(0.1) + self.assertRegex(contents, 'search .*one two three four') + self.assertNotIn('seven\n', contents) + self.assertIn('# Too many search domains configured, remaining ones ignored.\n', contents) + + def test_search_domains_too_long(self): + + # we don't use this interface for this test + self.if_router = None + + name_prefix = 'a' * 60 + + self.write_network('test.netdev', '''\ +[NetDev] +Name=dummy0 +Kind=dummy +MACAddress=12:34:56:78:9a:bc''') + self.write_network('test.network', '''\ +[Match] +Name=dummy0 +[Network] +Address=192.168.42.100/24 +DNS=192.168.42.1 +Domains={p}0 {p}1 {p}2 {p}3 {p}4'''.format(p=name_prefix)) + + self.start_unit('systemd-networkd') + + for timeout in range(50): + with open(RESOLV_CONF) as f: + contents = f.read() + if ' one' in contents: + break + time.sleep(0.1) + self.assertRegex(contents, 'search .*{p}0 {p}1 {p}2'.format(p=name_prefix)) + self.assertIn('# Total length of all search domains is too long, remaining ones ignored.', contents) + + def test_dropin(self): + # we don't use this interface for this test + self.if_router = None + + self.write_network('test.netdev', '''\ +[NetDev] +Name=dummy0 +Kind=dummy +MACAddress=12:34:56:78:9a:bc''') + self.write_network('test.network', '''\ +[Match] +Name=dummy0 +[Network] +Address=192.168.42.100/24 +DNS=192.168.42.1''') + self.write_network_dropin('test.network', 'dns', '''\ +[Network] +DNS=127.0.0.1''') + + self.start_unit('systemd-resolved') + self.start_unit('systemd-networkd') + + for timeout in range(50): + with open(RESOLV_CONF) as f: + contents = f.read() + if ' 127.0.0.1' in contents and '192.168.42.1' in contents: + break + time.sleep(0.1) + self.assertIn('nameserver 192.168.42.1\n', contents) + self.assertIn('nameserver 127.0.0.1\n', contents) + + def test_dhcp_timezone(self): + '''networkd sets time zone from DHCP''' + + def get_tz(): + out = subprocess.check_output(['busctl', 'get-property', 'org.freedesktop.timedate1', + '/org/freedesktop/timedate1', 'org.freedesktop.timedate1', 'Timezone']) + assert out.startswith(b's "') + out = out.strip() + assert out.endswith(b'"') + return out[3:-1].decode() + + orig_timezone = get_tz() + self.addCleanup(subprocess.call, ['timedatectl', 'set-timezone', orig_timezone]) + + self.create_iface(dhcpserver_opts='EmitTimezone=yes\nTimezone=Pacific/Honolulu') + self.do_test(coldplug=None, extra_opts='IPv6AcceptRA=false\n[DHCP]\nUseTimezone=true', dhcp_mode='ipv4') + + # should have applied the received timezone + try: + self.assertEqual(get_tz(), 'Pacific/Honolulu') + except AssertionError: + self.show_journal('systemd-networkd.service') + self.show_journal('systemd-hostnamed.service') + raise + + +class MatchClientTest(unittest.TestCase, NetworkdTestingUtilities): + """Test [Match] sections in .network files. + + Be aware that matching the test host's interfaces will wipe their + configuration, so as a precaution, all network files should have a + restrictive [Match] section to only ever interfere with the + temporary veth interfaces created here. + """ + + def tearDown(self): + """Stop networkd.""" + subprocess.call(['systemctl', 'stop', 'systemd-networkd']) + + def test_basic_matching(self): + """Verify the Name= line works throughout this class.""" + self.add_veth_pair('test_if1', 'fake_if2') + self.write_network('test.network', "[Match]\nName=test_*\n[Network]") + subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) + self.assert_link_states(test_if1='managed', fake_if2='unmanaged') + + def test_inverted_matching(self): + """Verify that a '!'-prefixed value inverts the match.""" + # Use a MAC address as the interfaces' common matching attribute + # to avoid depending on udev, to support testing in containers. + mac = '00:01:02:03:98:99' + self.add_veth_pair('test_veth', 'test_peer', + ['addr', mac], ['addr', mac]) + self.write_network('no-veth.network', """\ +[Match] +MACAddress={} +Name=!nonexistent *peer* +[Network]""".format(mac)) + subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) + self.assert_link_states(test_veth='managed', test_peer='unmanaged') + + +class UnmanagedClientTest(unittest.TestCase, NetworkdTestingUtilities): + """Test if networkd manages the correct interfaces.""" + + def setUp(self): + """Write .network files to match the named veth devices.""" + # Define the veth+peer pairs to be created. + # Their pairing doesn't actually matter, only their names do. + self.veths = { + 'm1def': 'm0unm', + 'm1man': 'm1unm', + } + + # Define the contents of .network files to be read in order. + self.configs = ( + "[Match]\nName=m1def\n", + "[Match]\nName=m1unm\n[Link]\nUnmanaged=yes\n", + "[Match]\nName=m1*\n[Link]\nUnmanaged=no\n", + ) + + # Write out the .network files to be cleaned up automatically. + for i, config in enumerate(self.configs): + self.write_network("%02d-test.network" % i, config) + + def tearDown(self): + """Stop networkd.""" + subprocess.call(['systemctl', 'stop', 'systemd-networkd']) + + def create_iface(self): + """Create temporary veth pairs for interface matching.""" + for veth, peer in self.veths.items(): + self.add_veth_pair(veth, peer) + + def test_unmanaged_setting(self): + """Verify link states with Unmanaged= settings, hot-plug.""" + subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) + self.create_iface() + self.assert_link_states(m1def='managed', + m1man='managed', + m1unm='unmanaged', + m0unm='unmanaged') + + def test_unmanaged_setting_coldplug(self): + """Verify link states with Unmanaged= settings, cold-plug.""" + self.create_iface() + subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) + self.assert_link_states(m1def='managed', + m1man='managed', + m1unm='unmanaged', + m0unm='unmanaged') + + def test_catchall_config(self): + """Verify link states with a catch-all config, hot-plug.""" + # Don't actually catch ALL interfaces. It messes up the host. + self.write_network('all.network', "[Match]\nName=m[01]???\n") + subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) + self.create_iface() + self.assert_link_states(m1def='managed', + m1man='managed', + m1unm='unmanaged', + m0unm='managed') + + def test_catchall_config_coldplug(self): + """Verify link states with a catch-all config, cold-plug.""" + # Don't actually catch ALL interfaces. It messes up the host. + self.write_network('all.network', "[Match]\nName=m[01]???\n") + self.create_iface() + subprocess.check_call(['systemctl', 'start', 'systemd-networkd']) + self.assert_link_states(m1def='managed', + m1man='managed', + m1unm='unmanaged', + m0unm='managed') + + +if __name__ == '__main__': + unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, + verbosity=2)) diff --git a/test/nomem.slice b/test/nomem.slice new file mode 100644 index 00000000..9c5d208c --- /dev/null +++ b/test/nomem.slice @@ -0,0 +1,5 @@ +[Unit] +Description=Nomem Parent Slice + +[Slice] +DisableControllers=memory diff --git a/test/nomemleaf.service b/test/nomemleaf.service new file mode 100644 index 00000000..3cbaccb8 --- /dev/null +++ b/test/nomemleaf.service @@ -0,0 +1,9 @@ +[Unit] +Description=Nomem Leaf Service + +[Service] +Slice=nomem.slice +Type=oneshot +ExecStart=/bin/true +IOWeight=200 +MemoryAccounting=true diff --git a/test/parent-deep.slice b/test/parent-deep.slice new file mode 100644 index 00000000..79b302f3 --- /dev/null +++ b/test/parent-deep.slice @@ -0,0 +1,5 @@ +[Unit] +Description=Deeper Parent Slice + +[Slice] +MemoryLimit=3G diff --git a/test/parent.slice b/test/parent.slice new file mode 100644 index 00000000..a95f9039 --- /dev/null +++ b/test/parent.slice @@ -0,0 +1,5 @@ +[Unit] +Description=Parent Slice + +[Slice] +IOWeight=200 diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py new file mode 100755 index 00000000..658b9459 --- /dev/null +++ b/test/rule-syntax-check.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ +# +# Simple udev rules syntax checker +# +# © 2010 Canonical Ltd. +# Author: Martin Pitt + +import re +import sys +import os +from glob import glob + +rules_files = sys.argv[1:] +if not rules_files: + sys.exit('Specify files to test as arguments') + +quoted_string_re = r'"(?:[^\\"]|\\.)*"' +no_args_tests = re.compile(r'(ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|PROGRAM|RESULT|TEST)\s*(?:=|!)=\s*' + quoted_string_re + '$') +# PROGRAM can also be specified as an assignment. +program_assign = re.compile(r'PROGRAM\s*=\s*' + quoted_string_re + '$') +args_tests = re.compile(r'(ATTRS?|ENV|CONST|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*' + quoted_string_re + '$') +no_args_assign = re.compile(r'(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|RUN|LABEL|GOTO|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*' + quoted_string_re + '$') +args_assign = re.compile(r'(ATTR|ENV|IMPORT|RUN){([a-zA-Z0-9/_.*%-]+)}\s*(=|\+=)\s*' + quoted_string_re + '$') +# Find comma-separated groups, but allow commas that are inside quoted strings. +# Using quoted_string_re + '?' so that strings missing the last double quote +# will still match for this part that splits on commas. +comma_separated_group_re = re.compile(r'(?:[^,"]|' + quoted_string_re + '?)+') + +result = 0 +buffer = '' +for path in rules_files: + print('# looking at {}'.format(path)) + lineno = 0 + for line in open(path): + lineno += 1 + + # handle line continuation + if line.endswith('\\\n'): + buffer += line[:-2] + continue + else: + line = buffer + line + buffer = '' + + # filter out comments and empty lines + line = line.strip() + if not line or line.startswith('#'): + continue + + # Separator ',' is normally optional but we make it mandatory here as + # it generally improves the readability of the rules. + for clause_match in comma_separated_group_re.finditer(line): + clause = clause_match.group().strip() + if not (no_args_tests.match(clause) or args_tests.match(clause) or + no_args_assign.match(clause) or args_assign.match(clause) or + program_assign.match(clause)): + + print('Invalid line {}:{}: {}'.format(path, lineno, line)) + print(' clause:', clause) + print() + result = 1 + break + +sys.exit(result) diff --git a/test/run-integration-tests.sh b/test/run-integration-tests.sh new file mode 100755 index 00000000..74fd64d2 --- /dev/null +++ b/test/run-integration-tests.sh @@ -0,0 +1,50 @@ +#!/bin/bash -e + +BUILD_DIR="$($(dirname "$0")/../tools/find-build-dir.sh)" +if [ $# -gt 0 ]; then + args="$@" +else + args="clean setup run clean-again" +fi + +ninja -C "$BUILD_DIR" + +declare -A results + +COUNT=0 +FAILURES=0 + +cd "$(dirname "$0")" +for TEST in TEST-??-* ; do + COUNT=$(($COUNT+1)) + + echo -e "\n--x-- Running $TEST --x--" + set +e + ( set -x ; make -C "$TEST" "BUILD_DIR=$BUILD_DIR" $args ) + RESULT=$? + set -e + echo "--x-- Result of $TEST: $RESULT --x--" + + results["$TEST"]="$RESULT" + + [ "$RESULT" -ne "0" ] && FAILURES=$(($FAILURES+1)) +done + +echo "" + +for TEST in ${!results[@]}; do + RESULT="${results[$TEST]}" + if [ "$RESULT" -eq "0" ] ; then + echo "$TEST: SUCCESS" + else + echo "$TEST: FAIL" + fi +done | sort + +if [ "$FAILURES" -eq 0 ] ; then + echo -e "\nALL $COUNT TESTS PASSED" +else + echo -e "\nTOTAL FAILURES: $FAILURES OF $COUNT" +fi + +exit "$FAILURES" diff --git a/test/run-unit-tests.py b/test/run-unit-tests.py new file mode 100755 index 00000000..9a75cd42 --- /dev/null +++ b/test/run-unit-tests.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 + +import argparse +import dataclasses +import glob +import os +import subprocess +import sys +try: + import colorama as c + GREEN = c.Fore.GREEN + YELLOW = c.Fore.YELLOW + RED = c.Fore.RED + RESET_ALL = c.Style.RESET_ALL + BRIGHT = c.Style.BRIGHT +except ImportError: + GREEN = YELLOW = RED = RESET_ALL = BRIGHT = '' + +@dataclasses.dataclass +class Total: + total:int + good:int = 0 + skip:int = 0 + fail:int = 0 + +def argument_parser(): + p = argparse.ArgumentParser() + p.add_argument('-u', '--unsafe', action='store_true', + help='run "unsafe" tests too') + return p + +opts = argument_parser().parse_args() + +tests = glob.glob('/usr/lib/systemd/tests/test-*') +if opts.unsafe: + tests += glob.glob('/usr/lib/systemd/tests/unsafe/test-*') + +total = Total(total=len(tests)) +for test in tests: + name = os.path.basename(test) + + ex = subprocess.run(test, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if ex.returncode == 0: + print(f'{GREEN}PASS: {name}{RESET_ALL}') + total.good += 1 + elif ex.returncode == 77: + print(f'{YELLOW}SKIP: {name}{RESET_ALL}') + total.skip += 1 + else: + print(f'{RED}FAIL: {name}{RESET_ALL}') + total.fail += 1 + + # stdout/stderr might not be valid unicode, let's just dump it to the terminal. + # Also let's reset the style afterwards, in case our output sets something. + sys.stdout.buffer.write(ex.stdout) + print(f'{RESET_ALL}{BRIGHT}') + sys.stdout.buffer.write(ex.stderr) + print(f'{RESET_ALL}') + +print(f'{BRIGHT}OK: {total.good} SKIP: {total.skip} FAIL: {total.fail}{RESET_ALL}') +sys.exit(total.fail > 0) diff --git a/test/sched_idle_bad.service b/test/sched_idle_bad.service new file mode 100644 index 00000000..589a87cc --- /dev/null +++ b/test/sched_idle_bad.service @@ -0,0 +1,6 @@ +[Unit] +Description=Bad sched priority for Idle + +[Service] +ExecStart=/bin/true +CPUSchedulingPriority=1 diff --git a/test/sched_idle_ok.service b/test/sched_idle_ok.service new file mode 100644 index 00000000..262ef3e3 --- /dev/null +++ b/test/sched_idle_ok.service @@ -0,0 +1,6 @@ +[Unit] +Description=Sched idle with prio 0 + +[Service] +ExecStart=/bin/true +CPUSchedulingPriority=0 diff --git a/test/sched_rr_bad.service b/test/sched_rr_bad.service new file mode 100644 index 00000000..0be534a5 --- /dev/null +++ b/test/sched_rr_bad.service @@ -0,0 +1,8 @@ +[Unit] +Description=Bad sched priority for RR + +[Service] +ExecStart=/bin/true +CPUSchedulingPolicy=rr +CPUSchedulingPriority=0 +CPUSchedulingPriority=100 diff --git a/test/sched_rr_change.service b/test/sched_rr_change.service new file mode 100644 index 00000000..b3e3a000 --- /dev/null +++ b/test/sched_rr_change.service @@ -0,0 +1,9 @@ +[Unit] +Description=Change prio + +[Service] +ExecStart=/bin/true +CPUSchedulingPolicy=rr +CPUSchedulingPriority=1 +CPUSchedulingPriority=2 +CPUSchedulingPriority=99 diff --git a/test/sched_rr_ok.service b/test/sched_rr_ok.service new file mode 100644 index 00000000..b88adc54 --- /dev/null +++ b/test/sched_rr_ok.service @@ -0,0 +1,6 @@ +[Unit] +Description=Default prio for RR + +[Service] +ExecStart=/bin/true +CPUSchedulingPolicy=rr diff --git a/test/shutdown.target b/test/shutdown.target new file mode 120000 index 00000000..1a3c2eec --- /dev/null +++ b/test/shutdown.target @@ -0,0 +1 @@ +../units/shutdown.target \ No newline at end of file diff --git a/test/sleep.service b/test/sleep.service new file mode 100644 index 00000000..946c44b6 --- /dev/null +++ b/test/sleep.service @@ -0,0 +1,6 @@ +[Unit] +Description=Sleep for 1 minute + +[Service] +Type=oneshot +ExecStart=/bin/sleep 60 diff --git a/test/sockets.target b/test/sockets.target new file mode 120000 index 00000000..8ff86a07 --- /dev/null +++ b/test/sockets.target @@ -0,0 +1 @@ +../units/sockets.target \ No newline at end of file diff --git a/test/son.service b/test/son.service new file mode 100644 index 00000000..50bb96a9 --- /dev/null +++ b/test/son.service @@ -0,0 +1,8 @@ +[Unit] +Description=Son Service + +[Service] +Slice=parent.slice +Type=oneshot +ExecStart=/bin/true +CPUShares=100 diff --git a/test/splash.bmp b/test/splash.bmp new file mode 100644 index 0000000000000000000000000000000000000000..27247f7a22b61f5571ba5a6069c4fe52845d65cd GIT binary patch literal 289238 zcmeF42bdgJmA0!V2hB*6N2AdMO%9r>i4Z`Xb6JLlfIHDmFw zcE>oHZbvtuih$#^@)~f8oM>Jb@%=+7jw}B4CUczbKWE0=(S> z#3-#p@t(JC-ujbY0)7ejC2&C{;BmwAN#RVA7m_y;kHnv0s1S`nrKl{V5?+f?KGJ+* zn7ozGCknxz{1Wg>;B}XPxa2WOF_`C*#H1l86AeWLNc^cpwWt9#qfw#PMqWpv3RH~p zka#8!CEw-yCknxz{1Wg>V89Xx_ex$qNggMXN%BbYMm0$M8G|OGsb~h88PYUf_4#Nd zM#)pjLy2v@@rjT9$u9xF1pE@{Q3By!$&25V!}ek~`6Q1?@<{SWjw=Qbacp&Axq-pMck*P48GSxc z2>#@kfL{V`35ZGIToNNZucWw3`JoZ03W+K5K4Q{*v=psDmm;xf2ilGHqC1k4lkdyO z$ap?CH`ns=@;sg7{r16w2g^T+by~mpr}jJbFNj9kAAj;oz%PNfZwZJ2l6asP&dV!# zUP*aw#b0%3EK)8>KFMQ}>xuY(7ZQ(djERZ4FFif|dz*&lBjvX*Mw^j*l9+T1COwdyoqhgwFe#ExTgXAln`yi9YlJrDJkiN zi2QaqYx;a&P*BjRi>iEpMXyj^a4^C67y!c|Q*+hEx07HYBffC0^-Uw7b3XM!ix|QBhxP z(&t}=ccpAc_u+YYaqXv9w|M(EH-$4p$LX;}$E`L2N%5_6aFTwrf#l7r<-B!hecrmY z9j{Ei?emd8`6cidEdia2I!ATh%9|+ftvpW|Qk%YV-r|z_DkQe zWy`Q(!+QNZl3|*!xVX5#c{jm6<;BHI^?A~MYJauge@m0c1dm4^i*&pmgOqpEZ=`b2 zHAJzlByM{e682u7dGly~EvMzR9_16oG_7B}@>u0_io)=xzjz6#KImN3xv6ti=d#-F zN1!^SzLay3`g1F{v=i+|AE3`o=+?Vz$zpRjQ0GfAFPzp3Wea#~*3A2Cea z@_40fiGkX7U!3AAfAUM<|D*&|FTy>O&RgYos*u{_W}#(Baoi3hE`2mLHTC5I`YO4s z86aNk=8-s7Qc}|We;Aj%&u+-d%KBULPLWK~^+9a#cqDF!Me>Vci@2jWTlWVQqY_k# z~Fr8n5Uk5T)e!KJVgwWclv9b zRPNe$mA#I`W0E|K7@=!~cqD#^CE|*>qkdl_k$xYwPc)-ZNY@c*Y)Ib!qxoOoYd+1d z<+OYaszl;eF%tL1K5bLm);{Qb2bzL!oVgQ}5 zI+tf4c_zhjyU~~EAJ88^di}1vyu8=XBfXJ0Hh_2fCvsb=L#jKfGm1S_PyX8KhxS)> zTjj1}P}zG-l1I{SpyL#e#1FAVToG@^Bjx|p7k@gMiDscWA}6$MiclpjssMX`5nUZ=6z&O8csP*1kuha7O*L{SNHDKfQ%ZKLb`6OKr4}cr_~YCXOg~G`>N*G za*NRdB!-Du;?+c?-(1`DI5mRzVx;yf3#B3LYowR*7!}SbX7eY%1pcHFP+jSbO{x<* zcXhsB#TWto=Dj05P~`uL*M<)t-p!!M@4f%UumQZ&`|(c7l_;01IueV#I>Fnw>=e!= z?X$QlucZ2}I7-JR?HHw#42rT8uB1ZAjGvs?NMvAM& znC)mM+Kp~@oN*s^oWoytocG=DI3Ih&aX$a7<9ze1<9z>|<9rW&H>B_J*?+yjcTYOb zSAWiY-(~(!JI;IVB#n3(n-{CJEiq7>nvJHR31}3mL)ym@6zQdOEXhc`jYB@8CIZuI;A1$ZKNdF7`@j2O}1x=z5#VeFSY zhw8cNdlb^KywxV{lO!&w-fDjp7iA*(kWw@f=~|%J%43o|jXaKcv;)Bp=L+n~M;+(7 z2VhH!ny;U{)6+1qlsHrMdk|8cSKZgKyp<;Hk5|6oTvG04I4VafXL%FV|HVk& zMKRY_vPSi8#q&d;&P)nFj^Zt3h`vdbohJJ${ju6WSkmKpm(ECSUcASTQ0jJ)_ z?p#7zJlsoZ-{tq}Q57mdIyU_-x^8$mDW6dkhCjWb5)hkIw{;Hbe9A+*rjJ51(czSo zlpc%;kLAkB%3MZ;f7ai7<;4f`TVhyMRaJl9>DR=W@*avMl#dl#z3Vb>|Dsc0T#_eM z-K|8;XbKYhSD;JLHnayF<|p{E<9y~7$N4pkfF%wrk;D&AQBMY$BNoMUnG^eRP;tEW zC3l`S<~zl*&!OMJEY=hC+n@rxy5jQyay}opKhpO}a4Zoepm-Fgb)8|I ztT*~u#5Pcr@`JUg3>6|>>-0ON zA)Q}7qbLM_x}Xy9>XW>O&KsRW%5hep(MaCuV|~SS;*-}7*H4b9hwoB90mW?|+j@Id ztf+bVS?8z7gDHMc4)(1O*Lmf5AzTvg#ifl%d8Pg6!;W)Pm*WtRId~hr2Jl3Iv#AgswOPWXXYMB(I<;5(IS6Y8;JKJI(qP1OKqxe6- z_5*z9^w5irbL!t6=L@iPs&bR_&~&7HfV`ouZ}Q+pNas{vj8d8TK8ix{r`ME#>Xm$U zZ{BGlpKnM=Na(lkrQ);!?mOwhBE@V2<*LM{e!No)OsgO#E|w}D62mZXZc{wpquz@HQ79TIW)m~yb;J=dMSKx!GEf%ELAhvXNO`<^@;=LD z`5csuvQQ>UM`>s{PGfPx@%!xhV_&lC zj(*y%JMwWmeAB<#H8=jNU3LAx*rDq_Vpm@KVY}k$d+oqgAF};de!vc0`>%HR#?RRG zN50JKH|^jx-?K}${IAVg{Fs&1pR)KgJd?+%*w8+CobvY7+xOt>!^C^H^GKcL6vqON zeI`QNuUw?X=mw@V+&I!*uW%6Eis|JljyBQayU+*MF zDVL;Nw#TdfUd0`$uX)s;V1Qivw+QPLC;X*yPAW66++GitcC*|8^cnh1_TW-9JQ`Ww zX_sz1X*b;Th~0Gb2X^F^ucJ@fjYmFcyZ2mgD^{$wsZ*z#`htnuy-CdPODfmCr0YR_ zeZ5VaHqF+q+hO|;+-V1{yw~;}_^fT*@?9G{>9>}esr-8fUJ6B_K$slf2SvR1(nmSO zi%C88#i%06K-WN>Ys$;%8k2xLM)`3bh2c+b9n-lW|B;Avt|*^Vg6fg3eP7`j1%0wa zjL~=}7n1ANys97aTK%z1bwysR5AW2)ddg`>Ol9B1RIyd8_`jI`R4#py+Z5qahoz)+ z*y=T>?D(w@+N~!(Z|m3Zv(ckRTYv2jD!<;C6#iLXY|`g_u}PonH|$M{+2_q$Xxn!j zv0az_v#sCwHESI8gvBH%Hx+K6?43Fu(NP^R=}d zcKrCmcI&O5wCU4lyDSoqBGt<=cb7vXiy9glZ1(Iq_^!RgY`5FZCq8O7-umyvdjHR^ zJ^lr|=9aJ6RmZ+z2akT&t~l~tyZol_*!~;7ZTqhOrtP`*KD+FiuiLJxzG^$K{EF?p z>I-(@@c$zY{21Qpy>{8Y6SijU4)%4rn_JXxH+}ki+q~tSwsG^PY|_*REIx@GzMDH& z{v0{oYIB^^pXQ#KO@w!zkD5r?=)9^yx(4Q>@LZIxk-mqb5d5jzJE@MVuB**gF;fAm zMq|*?3mL;neyG2A&8u&!TVhjxeV&w?lKSA+y~K6OS?E0ezhF~;Tv9m=#HH_!9{qWH z*SmghmtTI|Z4Y4oO^Rev`2Q*|#ai>`FS0E=4%-dK?zNlW`FXqX_V3t@ciwN;-Sv=N zd-qee`No%Q{$Aq3)qk{{+2q5UQByB!3W+oWx7q6Fx9qh6Q@37<(29?g`Wz97n#H_|w~~1oWFn#&$V;rgKK^Ejo|BHc)J* zxIx}YF`37qzFy^tmVCfe z6zP|);~1X0{r0cfzJ0g3$LcXD{8c;}GiI!9-F}@Nx%Cs|xW8@J-}Y0x_V&kZ^R>_0 zjIEtkvgl=t8v{c;=7>LUNHC`WS_U^ma#!vj2MaR+?p;tzo`wD%|x6##WF6A`^>DpI^ zHi<#K@lM~%SM{-;O7_KLllJ@1F?nSozvRWcVxqWIftrx6{R_})vFeEWa$9v_WyX_r!{MhC#f61b@72x{!WP@a)uw>bL59 zC8|a8O5zf%2*8bSrg-n8;7`<;o{HxG3lhslhvcqD>k5;*4Q*Evue_K~K2G~r9opA2 z_PYcXavb@{WfaGij$l+?>9cmphELg5SG~hFZTV-*9;$m|xuBv3@jCE};x5&QpFN9Vr*;dngLwZ8}BP$?)7t6=kCH=5rU4ds4nzKA|^H6#kjK zk)-+?{<+@kv)(@EyIIuxKNp+4G6-k1+Pc+#srn)hIT_7I;?hR63mwGEJ@>x%eUUL= zYF)1+HqD*8oPGj7va)LKMM( z(2{3u%eIf$;cM@-B}>0-G4b5X_gY2~=bifx#=~1j@y?_y73Ycn)o27#*=HfO&#FDy z_fQnV+i+6dj7IVdx=!hQ(6y@wsqJ?Hx?eF$Bum2omnTwu*H_Hu%`5iE8}-4UzP7Ot zesX|Gr@U$* z@^a){`9w90{V?5{pMb7Ty6F`FN#qunoYl_-wl)-_wwC+#AV&w>Bk>+ z&*QNy^tzP#@3HC4Iw!Rro#S54P1k3|63Tm&BGnOH&*!2QNL<>94)Cn1r{43P&s#%7 zv&*G1V`U%(hae1h<N ziv1hgY1+>i7#a-NxA^=k{n;sfGfllms&8=Op(M_qNfM7_mps7|YHtDdXA$5Z#k z0P#p{5GT@Mk@z9ry-fOdFEp)lGckgXB zXC8eJRo6T&rS{Jy#c|@2Jc;~?>VKMe1QT-LQC^5cVu-j>x~$8}mv>p^$}X!~)nzrS zyR3FimyKN8Wp(SitUjcMi@PjR-gkP{ypopFI;vTh)>pBj%gWe>wxjK7yZP)xUWixP zFYTZ9Q=Teue22xusR0>P6k=3vusrfApSFXC{)ss6@2q(oV-Abuu7?Wo=~YI(;5g6T z;y8D!{JlJs+GdK7u9doms9iY$#UlNV-fzlVfBG9O0sY32aZb3OP`$k_BO~LLh?vXs zH}0$W^agTDJ=PJie&xd7Og8BlbzXbaH-%uQ(oX1Rb5xN9zNBhvXuDa^o=U1%Q z=yK`s;rHA42^y=7x)nz~OG2r5Ci$hINOiMJehH1lV>IA3nmfqhP`5*VNwJ&ieHK1R z-bG$U{zjY-i^LD{M9gVk-({mWblKQVT{doWmrdBxWfQk{*`#eD=U!aa-tqmP>ImcguiYSYGl+$7f!_L^2ou9HjdvCB6YrbGniR8&+DZgmt%TXXC zhgav!1B?l}mB-LbrR>!vQ-kDbb*)tFtsIokCko+hG)3}B*C>xq#k|)!atnOwcg%t} z(KCrzquJh@!KUzI(|N5NhT4PFc3p*32d1MXh&Cj59NoRVetP@%!>?@JddTo^cJs~u zYIXG*N3stt753zkQ%}7m4vMB8$CAGho8&>{MO5E&=5!KYb>dq(@i0L))UE5Zrb|0v zN2kjXF-6>&wzJD-?(VYLd%A4S-Y%QBugm7|@3IA#ciF-NuWHd1ufEsk`d-q!T4pZN zI%ZwgWiwcx)+>&QTVhu8`c9bGiO1@+iV&xUvyZv#tGtvLl{~4#66B%AaBOflienU` zoRRRUCW29g@M##zZn4E{zQesQSK5wUAF-6o7hyZ)7=wE7iE+@K)8xuuyqkNbXYd=y z%gVc#AhqMEE!F1}h440;!s~E&d?!y`gjA1jfERy^@HhQ=pFib0jYaUMvMKVI#9W=< z>cdollz-JVdJ$TSwxB)e11neV`s2Zace-4<_S%26#wMN}pliMAR3b{nGbs-)zoa@? z3Y%QNME!(Ij&d{9-Do^hEM6l4&!Kv)`mMZl?%Ym16F%i4IIyCVn5`2Z6Xeo({Ee6) zc8DWliWsvP_AEKrWy=nA*@~;XY~?jww(4+~tww9E?OXa@^J#u9r{yoYGPo`=OxzN) zrtb=}P}?5`r|My4)yhsQUCO?O7?nP~1HN_;o61AA;|bgGhV;p7)Nv!1QIv)Hc$J|M zlud!ksl~?6{vX@2^=jL>`@L3NMLVAQ8fffb*F(XjKuC_usGsAZ@UY9q^Lwa`q73PG zQ;yu{6NT_Lnw`FWbf=FWaV& zHXnW2Jb9n#`wce-=hbo-Bdtf=(t5Riu}UnIuTnfXW@FGxiBXF8@`?2nj}Dm@@=zRC z?3i}^A$)3rO$}j;s)kJ!s1!aGqx=>tANLr2%5UM`;p^ygz%%$1pHCSeI8ngHlp3=I{K5g-F4T;-2Bq!&4(G=h`vkF)Eiyj zRgY5OQ#x$Q#S0Y3FQF>xpK>np4e}4Fqj)BdO)5os!C+au%r@!qI@c87_Z81VVTE0UuULl&Fnwt9LK>Z8eAio}Gz1o(z zsQk6gyVo;$T+*`Icd<3RO-^yb9JCy*N9x0LFgZE-C4>?pW5M5JN=m2iS6W{I>mO!EHMtG?HKnqSLpKH3HAg6kCjv>h>O#_mpX>cMRkm*97cG!NIVYkx{89|kbNK=x zxzB<*`BR>sHJ=oe_$1$}>!jjy#p%i;hW9VvUw`@=E`e}9sgCRSSB&R*DD_vYjEjqV zFMT9C-ynnf%18a2^(n8Q?aBANo@=7F-`+lZxo`2b8jV3S(Nc6N+JW|?N8k0XPcoiT zBmFB!+tFhW2Cv_WH4@Mu*pvpFa_~&bpU4ALBKd-P)a{q3ld78`1&DQ`6!ReQDGra3 zKs`>TKBrD?cRiHHs5}@|fF~(l(m{T_gSN8{+W$Mc^H3AEbdnnna$*kSIf)rd4tBcn z*sDJ3RYu7lh4V>V+IxGK?YpC=^qI#ju}YkhrxNQF`zhwrcINI2ZeO|j+BF@tEp`y& z;Q?W6D!lE%Cyv``Qn{dpP#KNnwVE=kK&35~UjMvZw*MZ+3Z845c6`R7hQOpG$~r#8 zr|8%4=`qK7h~I5~IG=P46Q7hL_4!00yiF$6bFZ%JcNZr-52YAM?eMyOO&c;~$d|as zrQd!AuY+HD2D#QPucmWO{!RNa&=kI}T2AMz7&jbMqETo%ifohn-px0^|NP9E%iOWx z?z;Os7MGy<3hf%&b#HScypKuSAG^w5YPl7&5d8o`;uX-t$ zQ}`2?Q!C*VJZPjHZ8S08gv}vN?SdI_Y9XAu2!5;}ZzL}zrfk4V$p>wNGvdwe+k&3S z`3pM8LG{C@a7MXt9&D0%z?uDD$Bx%wCAT=cGE z-nnui=L?JZ(_eWBcy(UCyZngiz2Ysg!()_u)ExS0eg#JL+t=U%8C5|$ojjW7*9SV+ z^u45g6hn2c>YA$kQVh_Drl5sr4f5LLKDmAS_2)NiIB2v%+Ko5X|%&>Ry;v>V7Zp5Mq<~)ElGZqr6y8UP|%NVEj}Xxg5ny zIkP)#=-dw4$vWr8-_?!ZrV*o<8rJvg6 z?c7s?7o5_De`+JXYom>_jhvgxCR9cqqv|QUk;wH>EjDc2A8hx&ciN~?V{FIXk6Uym zJW8SL6Hy%RW5W34GV1rO@QL5=@JN2g5lDH4A;`-Cczog`e|j5~fLHewU-iZ)og2!R z>pC`ij3`^A>SmgBkpgW*yZTp9+K$dfqby>Q9ReZLyVxph%>5=D=p zo{kH?*Z)#LbrwbOoxYFJJk(_=eta9b6IA#YQ-_6;ADhQ{<->;d7Re*Iorv)?L?W>*0$yBQLcRFC|9F zC%KHmGet7W^HD($#qu|G(q|zUOU~ZYK@Li}vDd>V%C8YMpgL4bnc|^JrvBEp?K)yj zO`~l4-cML`7UiF+-vBPf9!na&rT z6aMt}DS>cCDbDkJlwv)_P-22|l;T1S{Q!=Uk9zEN=FHDBe;v7L#ba8hd{BSaLhX~z zMeU3BL+7Z@)gn}j#-Z6rx$g~V7rK`Flv{M4ocdN)Rn;&K(NBXhgs#;|)QiEeDHAs3 z!KPx^L=56y>s6;bzvOx*m?LlCDU3_0Q{fFh!sAkpSLT+c#}-ln>(Y;hRtfT!nti$varo6mb6<9tZG=*Zlf=5w+S2DZR*x`n}wg6 zzqiAdT+uY45*rjxi4TgY)IO&3W({8Iv)qT$c7a~%{miRn z!{fT%ypzWzaZ=}`;!H2cRK@$zXa>3nU4nL?%cG*Ao__bcKjV&bqGzw)cH4hgg6e>B z9Ev4U;Zg=%8VZ++;8IzLONvFrCFOYg;gUSjkmF)@e?oJMC80rlpE{=1(#E!0=7d(unbc~-rnOq(%vLLbRTZ$Rc4?b6u4=O} zaB3o)nuf=jLoBv%e}^qS*kP-#?y!sTQXB9>iub&nRBwz@oagaLF`oFemSw~F5OS?>Il4$)%^1-&LMHJht<_69w`%o+26L<;>-+Jx1wz zrt_ua=nsYX&_MD~G zowKyYbCx-Z_W5z=Y}ll8RyeK2O6Rm%)xuV*Th?mLtJ`ecC2clkGhS*(yUiyiy9h6} z5=O1Nt|N?5o#f3siS;^d{~bYHekZSJ@9mw$fy!HT(vBxSv5qS{T>ms-OFR8X+sTi& zksoiPj|5&1kCy;DW8mm(_#{qwd~%PM^5qyW+4Bva{V>5MO`d6Mx86stkKZDV-y}uX z4UbRqPQ>4VhvCzMzjU1cY^J%Rh~HLu1+NW7=c3LLe|meDfX4}4tHg>(M(KK{I7=Q% z+}Hwl?j@d5Kg-B`llT7>cpC3qi_9Z<+taps%Q4mS`6M(Sk(cQ1_x*3=z0a>(x6kEL zeSH(p4*7X7pP}pWAkKf)gB-Y25XL3tMHGMZ$|Z3M$rs4a;1{ZhtA^uUV(<*!=iQ#c z^A6r?4<@l4c?fL}_BfS_B~j^F3zVSZGZuxSi_TaKiY+{CaYd&sVZ>=mEIDI?D$ZDH z|PvhZU9egTxHfx{6>lRrdZe%P2Ne~Dew?{`ssu4sfJX7u1k@5N}o>@ zia)v6DV+;ql;kl=`Dw*@inny%K`Bx@%K^MgU+sDyCZDc$Ht$>u_fFn6#3gYnGRHKY z&*q>N$jdPuZEPIfq5I?Hm((tIf>X%CcF{zC0k3cZU-JfCdawzAt8|wtf7e}FJ;+_~3n|spY zhMwf!|5KI(vj)Md!4;=1z2=N%H=eP)v1hFSKUFfL#i|yxSl!ZA8@;C0CT?i68QVNY zwY#z2CD(VjzG&Mmown;l&_nIRGkHEL+&=~LPvo{8*{H%O%7`AgT3%c_c)Swa=p_p;L}g; zb(}90@q6nU=y@kyyL>iL2>#Tg1U!Ct-bM`3Ig^2OeJep+>zt2~TJpS7`0FFYbp?Dc z?%}y&ZTc#d-2j zVw9x!yF>Ba2Kp$hCda;*7;(n#cJ6U$qknrF{T|4L5myc-7nV4&g*HoK(=o)U#GVd$ zv)9P;Pn65JH4ob=o{OikRkvUEPRni}#{_?!bR9dtSpwITSner`l6U%*ywl5s>+}z~ zP1iH|bmcyEzW8}33c;UVQv%|X)El344vj$djCuQMa!`@}N$qvD^gY*n$|H$E9-nm1 ziA!FNN%NGU@Ep@R{@;d_V|wV=u@4g`R9jkFn)}@0tFQTSFg8$(pt`PpHDUoVlT!{O z#0te%;)m*tca0B!4f!R-ZpBO57{f&OoN#}>V!817!rzD0zhL~vcE}&O+Z++bB*ih> zC-F%8r+jcS`>Op-K=OL=)XzBlgB1U~1*or5RMHC;o$`Xk41UpK(_XZAIF*Q}8dPx7 z2A7_)^s3X`H*(tY$DOs}sW58pIhRpm@KKXt)a;#YwrGF5tvD3SMQyyPgMJ4cc&H9H zo)ecO<)p-?ZO1$4UqF5xJ}o>z-hF2~_bn^7ZKJPyD}A37>%PjTsDb#TGNRl!9{ewx zFmaMQF8zUPK5Pl4ltGTlMCGC5=eT3YJ4KOq3Oop(?*A>%?kuJWxgL2LaY=cQ9&8e)kgokm z^(=3GD`SlW>tqV~mDl(I&98NMTq399uD?e943R5x$QwDtV{YBU_c%k4{6RAN>BgNQ z4#lcIh7`?fq(a{X;8lRS8^yBGgI=)M!7o@``iqvB^O7YGJ87xKFskBIkWs{YBc`6U zs(I(EVJV(vU8_yo(q?max7kIoW;OZppoi+9J+GrXS1vv&_atU*g@8*dHep2+Es4VIf*hJE>`rgOAYp0#U_eZpl^ZEdaXy_$RP3MeC3 z>kJ8%P25wI0rx%zekt#Set5m({JYwCJ+Cc)t@F>H{1WJ^1p4Arczm~zcD$Fu_@wcG zXVKqWv7OF0@k!^Lr1$!)2q`w~tsm1BAhGqtiO;(EC2?u;2cnL)TtigLN%d z3{?svs$hkr@o1e z@<|?(@IG$bB2OgVxC~<4qrjKYd#Hm~qfKa4NE>-Qh;HTkkK-k%r^**cKWBls=PWAW zIg3tu-eOXox45(yEFt?vOU`=M zc`G=+b=S4q#+%xEcqn-%@kz|ue3X6(#DOY{IV>}g{#Etl-GjMt`aH~NCHK@q?kN=8 zQGNsQX~g_z7`Na?H@2HTW1cNq|6>?VIc4#?rHb1eW9$J+Z^Rholhl5vm`wTctCgn?D!}@p;$c+ca~3lQMh$^cSwTh(hEbVSCv9ls zX)Bs|#wuo?wYtSEHg*lqCfI~840)(E*R<2Wyq!K#o`+JLCok1O-vZ^(JLp@`PTvCh zDqKdth0XM}B33M3qTG|ptcBbYeIe-U5Jfv;U^L}23N`nlP}yC4#gB>Yrnr3Cx#zg$ zjiJxSP|7TWGJ~~F0(rw2jT`YGeEJE;{NG%YKB2s(ytUd;HYKmNJySZ>9N z%{Fclxzj|>XI*nMIlsk*VmLwjyQ3J3zCtcX=r80lCDJd2{!g6HV$H-X8>x$m=Tdu% z<-)n7^@>ZCY^Rj%6~d*w(Dh&O32~RZUp<)ged^gw=t4L&&^+6yw;!SYK4yWKXDur3 zSs3*!jCu}6J#UHGFW8`AFIpNoo$T6EmOuJ5_mZ5kn)!IB<>zeD`WBnDz10@&YqOPC z!Q<=OZPU#`9__?4DX!D2@=_b{R;v%UGoFj$+&0D;rk~ZSR&r0=-#fd7+!JGoPdGLi7Gr=L+?KmNYseA8>M z(|M-zP3N6I`6bX_3FsV=biR1)Y|3>j_f&#v(Hx$ScPh*~J;nR+F)=ZU-NYkF^ED&& zW15FnqK#-bx(?K}uV4Qo?$H`+^rdp!=dQc{KZBlxJh6MtB|q#kLLNpj7X5;HaLJ9u zs524Q^f<2hRV!QZOYP)X+THf3KxDn@=8|}aXv=ph*-i;eA}8(ShOYbMft+MmiJx&| z6@wwQJvn#1Nlc1l*2S#%-E8BRJs1_6@|?vJ>m}v9V5tQ!T1NRxHnicC6-_v86|>G* z{gQJwZf%QA-_mOH@k7fFw%OXlZ7zql9t(OXu}R)Zo=WAi;%fSM?r&p!I{K(z(n`Nf z`mfJtd=&aI1Ywuu z$UAl7ow$~*k}uae=Cg@H@TUtZ0kKIwTY1U^q;p8uxk6Nh{5@ zws@~0K1CCQsBL@&-a$E*v9yRzb?miV3azV-^=jSPhPE}F>wFH|RvV$N^~&SI1Sc9r!Og&@ zsZ(M`I79y2@7J^4kFx#Wx{QiWc*bIqpS5`Eds6oEmOA_eJk*PfrF+tfC!VsZIcKbC z*;$)#@j08hRWTl%zOs#b^MZNuEl1mJ>oMh{f_bUcc&o)%(06J#{n0nJ@|>#{#`#oi z$GtZ6Ur3m6me}qrxhKkORG6B1AEErYFWTM%x47P^qN2jCyz%RJC(09+Ixy9Vr$0dq z{RxzJa_;{R`igt~ocy*rDuzE@a0&F~or+n5Vz<#~4SgoVpWXQ=tXjc_MP-3Z!Rh7EfdHl679OxGN~*Amk?cT+is6$8*d)d%kOp1!S z)Y8)5V}&EXO`F=IRyOTX8`1o~mRIx{j`z4lMJZ-`BRnH-9{8LEqW@q~u}@oc!qXO; z@{A>BK8J^T-qJ?AU^z7}S;3f-RzCf-)h#+>V^^QGX`5S!@mh)TTHP2=dGgJ0N!oa` z+6jp5u4-dkI_~8oU)4n0U-|MD`W2ibw&Q-lDcm18{w%Q__vDaQ>X%RaE{AUYo>f*> zx_nx-cDs#PNDdr^I)nLr6X}Z?tDHD}F#|t+n7GbstMl1J;Y|@V&<++Gd=eJI>b_@8sL2zUGSM#*Ld|7p)`*LC)9p zE4f@}3l+=3CHf#bwIMFKo{75g8a4$vl}y{x==H6(4Nq{{I~apxGxv#6r@F809?x7Z zvCdl7UCA~|*p};;U{V@&Xb^P>Z{kq@ooIO_<(96yAfCj>-(?l`za=+K9-el==Cx=g zV$6Z&MTkDwjT2wQFMf+-KVgBu8}VS*!l(a5@F^ZXB|n3Qde)M&pS8gS&skRGiRZ#Huyd(oYI+6^!k;_jny+HqnnN zmp-3ErgP8o#Iv;91-;Wid>T6YCEI`SR+mkR?XDv)?ht=EY5czIs}qNJil&c9;DHYM z6Obn;QF}`)(z)hOehFM?350tm^(jz(Kz#$$ms0%+6xYo{5BG9U@bB?Zdl~OUZF1t$ zCwRms&m#C8V+&kw^oeqH-3_0%fOw#s1Z`2yaM&bX(C^Txfgg&y8jzS2E{`?5#u0PW z5{sywU494m-jfH;oGHH)Vv{$omamWCQi1#u+fDC{OI+ifLl?lM)zmlQuA%HZv1b&0 zsFLWfkU?8vF@1*W>D$;$|Ig;xh4z@W*FSB;3qEg&i5IesaIYn%eE>c^iHG`w z#o$NcTo3iErRG0p8D%fnP@W}PJn}@C<(AL9i(v5Bh3fO!AQ* z_Soe2BcPJ_)9WgMaPKsTCFPye-$`w8YKNPO-mkt%VR>=y{b%_6Am5*0R<4te+tpWp z%YBBE*fee0e49CsYiKH5%7hKdO%%h59a=FYx2vlEjb-J0keKh13)rT|sa+O` z`ldz2JcWmP3J>+PC8R%NgL0oG#(Um!YG1U%aW7f<%+pqX(HR>@4r=;V@^O2K@vdxj z{nEvFC`sOFDWAN-s$LVUnGY}8K=Ug1j;sszL;+LK0u$6&-rYkg80)LDgn!c1 zuflTT9+x!6)6MiNxSC~t={Was9evU^Z@xOrGkqp_EfpJb@h%z*yp%d#g=bRCRfpu6 zT;IfNIG1=IfK6F5&oUlctL?wNoqJr{Z8G`a1mcfiK8j_S$6e0jlGd$l&<^iz)8kTN zIG4E2I|nX+5#*@{eV_HgQ{~0fj;NfL^7iV#&e$pL7*iUXQ)6^SF-Ae)4DlR&92nEQ zd0dAzPvqH6lX-6Nv@UCy@v_y7rR^>6<1mVKUr=5O&*r=r5A{1dRFF^cL!PnZoM&mr zBgU(K!SctvWTi7s+sMUdY|PrTHgyZ*#O-OtU$(k_NnDcTrxsm7Uvu)}Op`Nvj$`>qe)JrykbyhDtW24qkZm?(e zZeqO4TX;qb{WU2&u}Qp=cbbBCYNkJDC4CZxFJxRi$~9%mS;l%|Y^t#Xc&Db*wsh~4 z^!H!n@=5KnH{bdleruIAY+@hP$JB9tb-;1HtLvSg3#SnL=?#@YxOdWZ&g)O0oVeQS z*1;h4#XK32cX~P}C%={FDw6+w!Y;k^if+$z?G2v|dVJcMoMCW+zB*1hb-bE7ERLwI ziz(cX-y5IesUHpWHQaKf&8~z?JC5tQ0qUbn-S@mwHl#2U`^1G6BompG7^uY~nfuul4EcY8X;b?U?J-iOC_ha!#p?>=Kvulyean-Ylo z262C1TDxUecG<}3aB21*ZRFfntajlmRuVh>TpG|M5O8N_hN+6O=YWr0`agR;v%d`w_i;j+dE;7DLPQDw@^mTX4IG#6b z^XD(Oanr~%so#M7iyO;P$17oz>bb|IZZ>hgi&4Z1QVeyWbjev;cWtX(ai{X%^dH0n z44Nb^y*gjFU#e!k;!+WDV;1IWrkvC0(W7nGfd|6aq;cmS-9jHH_3ib2 z6NTVUZ>R(!*(Bejz68pLE2f)`)R$>9x{GJ9^cd@D*su~?zI?NZOUi*CzW#GTe^0x& zGaOcopzg|l(8oFGnW)2&Typ&r`5M?WboLp>(r$H`B+qo|^{qCX>$<-4_|=0;+~468 z!x8y2aY=cPB(CAzT+(wv?i#r6i%S{gNeb~>rL3!p{jOu5RVTH-@_c28@lD*mqZ&U! z3_s8!KJ0dbt}$W#YM)m56sGE zy+VxlF9YwR%cskz_Yb*zih@ruDNk8Ed`f~(gDao6Eclc^^^}z@BnP$ftc`&`Q?_wG z9(Aj?q@k0%8Q>NFMfu+_-VWozX$jAb@Qp4O&mXLn!4dR zTebR9D=aK@{nIVCeVOY4*MV5dTi1fX<4Yaq+sYI8_pDF|{`7`QKy1?aqw`4lrYuy5 zYSBcr0Ifyp%cSuI?$6B3^K#pb@~Wb$d7vE!WWxh)vWUB>HZ+Q(y6N93zCua;F@D8JOrC43I~7ne)P#1(4G##=a1 z;?jFApw1tJr{tmvU|I?LUcr9XvfqttN88oDGnR?lUgzHT!h4PJ;&6;&lb$OX%RGt9 zn}TObgH2hmX(((O-pO)Z?CZr!JtL?}jJ8WIZsg7`~OWz8dzM`$U{3_HiVyVyoKg3Q->4 zX?&0X^SNwdAN2g&1m+#Yz7D}RWx^(M;Z8nmD#ACF!KW(NH1dxe%O5QRK2?x&DxZIz z=N!PLX=WuOjd9%0Q?B2JPxM{rkqhrFU;bX#p9EszQz9|mVA}C=;1ls^O3e$F4xfg? zr(*b2wfw9#T}+He4ob1yH2OkKgHvMDn2q#(pv|t-^-gE#Q*avZ#B&^sL6_)oS^-WfgxlHgMse9EIAR0;RGjD%10f6ATCcn0vP zVi`H8b=)t!p8N5LRPA1DL$Jh1b=#6B@phJ)IR6s zz{`2BewX2%X(#{VnW7$}?S(q?qz%n`g1&~$J@}NCyNx)8I$KDcrT=o!Gf{8lJ-WFR zs`DW}1>jB|Ii_U?TkuLjF710qo7>J5uX+*5CGOjBN?14daJXEOPZO6k#u;@qnCtif z`*`U9b$bWPJiz|4OaaT5u%1fxy_R)1vd{8OitAhsvQ6&0b#wd4Y}bK@Vw1d+`#c8b zReN1JY|4gBd2p!!-&6vdD&SHLT&l-6HKTgiRPzd-zhYUV&s)hPxKtM6Qi)k%lUc!N zvy6iOW*e&qIEH=fgT|eN2i$8L81#FK%J_rD4(DE%^5-qN{zV%yj&U{dLIvF8QU;%D zX~S!}ggn$n#y){dqc;TEq?~y1k~6f~_2Qiv3&G`66UW(z>L?fTabuUiVC&a!?Pk+E zZvPtlqP~}pf0p)JKMzi&@u$~a0^*XSHWZyh-Z&}6yx09I$}`PJ^zH2)FYeRsn6q$+ z>!R)7f1i8bTtvSDi_iZ|kR7Viu4m#r9*M-J*YJt4vnQOgnLEzf-ggko;g{r_R$axt z@?7s-KFDWjIr$}VNqOo*n2-w}((yVeaD|+U%O%y(0K6G+oRf{zQO#yDrP<9 ztgnW3H?R%WLG81ob&O>n6J)xxGqRQieqiqBhK$@!pPDuPSIbp@l$hL1I#bzn9)U*2z3{|bB_9&;SA z9D5>s8VsLuxYvdFG@ibhN!))oc*04`n!%WL^BJ>_KIB#8$m{S>jWDW-I9h(H8a9>S zUGr(<%bXSTPHvkW*M}%Cu2Z>)*>2gqV2OCl8_U};tby;y0(o!ecRhr8}m$a^geS*G$-y3!Cy`Q!#8RgH2U%X(U`~#5YMJVUzMs zWw5CjWxirDG3U7t5iSwS6*R*oJd?PTKhbR16tje!dj~ikj@R{0Fd?4f8T2~~WISb2 z!x(R+lyNojfk~sd1~A4-CVa}n7ZuTmyc`czy$T<-Ca5ajmn=O^U(D0Qb*Jbneu}t` zXYY+YY0>;n0oLI%n;f{q{W1=|%qe=7eE65U*>uGf$E>7`@(esiuJWs1Jg0NbpZpTI zkP^_jq8xzdnRJhD4jO^#(PXp;dCzfD+uRQv=abYCT@#cVhUVp490T9#ia>wiC8ahs#z}mqGD5z^?zJ}@32oC zk335vRa=36kAi3H_&dMd&89VL*4fNiPdyRJHR=5Fb4?V2 zKV5JMM0zIg{@yCq;Pq!(!TU|TUd{Y_>OJ?5q@h2??u0_#r z%FV;6oj~mc>T8kzv>kiL54zd3WXTd+y!dy2kH7ZgIVz4ny{;1QJd^yk+EL`0)Mua+ zHKM6VtxE+XlqM{z>z9{Mj=RM;cZQJ%O%g@g@#=x|SifUW2{(d~j)0URMxd)%J zhflGah4)$@YrCbFUT$Mn{>(1BwI#%*R@-}9tBqezzdzLh&o3#i5|>>6 z!t&X0Bn>_!<98Ils4l8b2L6Nn!xQyae*?#0$wRE;VHig|SHwC>SyvU@siU4Xv#olz zRSk2>_`itliG}nVa-x~nk(gi4vrXi4jZw$5F`X=8ouRNv&q^ObJXa2zs$o+dY-$Sm zrds%v7!go12@huCCr1#w@cv$DSglYqjMEx#x5W^;}%i z`7bUhuA)6$v4cZ?*X7b67$I-q`XzDce%8COk2>qsaO?wC}}pUHmavd{U%bGrAp3^rA@ zvQF642%8#V(@3PellnMu?~0QLlcIPPn_}=z*{~_^Jo{vpN-jJP&omUzluO@&96VFD z*o1$I$$UpY#|W1-E{X23)wtbB>~9)u(*BFF6+9;o?-Y$MjAh({`0+1U65~Im;$72b z@cgM+$6thGkseq&ysbr`$eZg_J|i@43(SL6=S9)3j;RIyZ0m z4P#ks@^Vf56ti(T+dX-Yh*vmoqTo`-3m_9-a?%SvT6N>|D;W+*kzNv z)A}9Xr(SW6k`r~xp0nf;_w-=X(7XbR%~-sP$WWa?K_>c%!RR2^Dxp#wZSIA>fZ?AAG;Rh`LE9&ZRU=D05 zrtX%rz8cosz&4uT%t*MTyp#G8sNTtQ455Czu`KiJJ`BcDau`R+8O*#H?4$ZR={Z(< zF0jT-VGJjy7B)4=Ga-4WYE%xJMj-B8aT0iScn!d&bbQlL*pv^Oip-+QVG^Dx7tfS~ zXUd)pmta)pWTRi@`vy2pj*-6NPAuh;NcjwAe_@AH!2Y`ZNqHtZy+71rRCRT&B{%;3 zRW2!?0qfjrz8I0oc2w8ICB-a?UGQ;^^Ns=PD}Ew|+;`e9@F%~9Bag67mM>#nRdA*b z7B#b-dg@v=@5`viMQm>v-(|DSXy$ceS#1|i={`M;Z=k*e8pl&(pX)i?C9p})FRvk< ztA|a^ZM-7ooGOs|IjJA!5adYkX%KA6flb3;Q{j2$L9l5saa|5P%EmKg!KX|-R0eTg zY}P#k9P3xy-^q!gToTytRCo$IT>n?bKC6F3J$%ADMZubA6bpCaCj=Rl42#4mN$xZP>8wo!hrRp?FShz&hXj$uEI{N+8@b zMfS5C#lkZX_h!1!a@xh~F}h!NY5bEQn;x@;i+{*CvyCpB^n9qDm*2#q-A}yNvSqG`Mgl^@np`T+(%3>&<8V zs$WB3NwWAry^DdB@&|zr4p3L|P*MK^(;j3Uzr>&5nF?60g!NRynUSo!k^Po$s$p9d z{6B*FHXP-$%>=QJ`Nbynb=G~Xj7#FAF@F~OsByA27P-bt(eulz@l18FsR<@EpjxE1 zx>8tFgmO^;Zi!7Xuqhih_$j zDdVY97dX##zQckm4}HWGlS#{#Z?zF)sIQ6_x;+!;t**`RWpMtA9&9QtEwu>~Cb(L* zY?&=wxX@YU4^ud#1y`md{j z+hEDhxVFQl+=r;655oYKFK54N;7ajI z{Ex5$E>)l!gC9ma+N-f##(1;zQG6G>x&PyJzWOSg;yKO~$}E%p)_sC5o8Z06CK%Jq zzN5fs{Lq*exo_@87)35>Tu8i+(PtI9h2T#EmOyWwX&6gYAoa7HiNgC?a?jj+`V6RUicODNWAo2#&YY#)Y}$Y5 z--G9TF?BV}Gr4T4dW2^|=DPi#)YobF@ZqjUl22N(Vg>g&thbdbSF*l2u8)#$k`HqN zv2X)6lyL5AJOEvn(>ecD$K(Ut=L>0ni2a-$1Ju*q_?-LU8uMoV5`TyPD}pm+tg8z4 z)Up0%7{l`hoNC^eQP)D?Tu&D|5)S+tpliKS>@V)?P%oK<3#il{{rX1Kb3^oPo2Rwvm|)r z#d7KN#Z0MXy92dDI^Uvf_|5c;xOk2=h2t22O^&z&pFBo+oQf8+LJEjs>i6aLt)R@@ zc#g8lfbq1A+;aSr9-AJ%_ug;#@f?-OpDwrr#3o(K)HbI)ljoW0crVYi5QX=%{0)72 zsSBLrI@hBfu`90pl-r+4o~fp$-sZ3QU+NWgS{zZkRu%PCF@t0&tc z9X!rY;miZ9>sRoB+ z{V|L)>E64ddss?{=iD)diRbF!PBZ+eN6I->AoX)nKg?{TaeBq3SlE^wFlh)wK!7W+P&eJ>S*<(v3@ z#F;SP7iquVp>J@EGyQ^@)0 zdM3_Q-5;y-UhVJY@E{Ox2?+_NF;f()(RSl{r2YH%a~@yAeR%tA>C&Y(e*Ad%9(K*k zc7w|Q9)5zlqZQxR+`g-sQ(N%#KNi%X~h??hjMG;xW0>xK~H zMW@{{z;UnVd%R(Q{Z?5eaJ;GPyUI~)QjTB0Pl!z(cjS{iiB0lR9=F_AaY-zzgK5?L z&SIR_m(6-v|BQK$*^(v8#iowiZu?OB-FM&Z$8(&_{&YblpnC>%zC_;78+mWacIMH& zDNiz1VX$uMJdb+V_U!wjd(WIaliJ+2?dN;fGjX1}o+*q?89OZy2)Oxj^>-1M7A;z2 zd-m+H6DLmCkt0XwQ@-1#PMvC#CQWktaPkaJwijYk9!$xB6>0E*c)^WLl-p%LoWR$Z zZw=~)P0BG1`X83Z*Jb0GhT(yVIF2&-R?Rx=s8`MGcO7i4R-I*AMSMOC4rb|i;h6)U z)K^Gxr1D(K!>f;VE*#ch?-!N;<{?HK`?3v{wcKvp2cnI|G0V1yUV61jv)pm z{(tt~15A$U%HQtpnVy_;&N*qMQAQ}|oHGh2iy%Y}BH3WlV!(jGU;`$ZWWZ#DvB}wF zFgXgPkqzEmd-wBy*Y|sWxBHH2S~DZWOYxKu194UYKq%AedV)FoH)@eSg^pHfByOA z;)^dfXPtExV;ZKJ(W6J3*49>QTXnEW@uoc5&fvP2Kcaho5GL7qVqwibYYQBXPCg4u zUV<~PVh6o}Uc#74+Npzc%`m1PjFH{c$g$S&e+Bz0M)FuEM*EP>1e;>mZz9K#%6H1E zQr@R>#5JBzPqi>xVUFg=)4Wice?`yhn6u7~UCHLN{|~eWn^Z$Q2Y;>r&J@EY z`qErq6b{xvKwH+vK5cmYfo&F9C6&wx#x4O zD?d@O2kXy?OI-IQH?pmdarM!RWvMlzMvXEW!*JYj$C-1^Imck{Gk@Jm%PYmjWmjoV z&X|}OyPYp)0QL!Nk}r~gog+S2E^#dToF8Q|I{66Oz5q+Gz4Bg%0dK(x^t6Vy8fmu` z#)wVL-1qCyS>+OxurK9_D`(v1n6gbY`_uk)9E!y&&q?{E8e3=QUcqKk-A&aH*PN1? z%c>F4{414+o#%je)xy;LD*+gmiOrPvC+sfRqHNmM z{@niQb&+wG@Bs)vn z`I1fx-Rl$KLM&X8Zz4NjzsB&w#pLJEM{K4XVqS&VOl9b4H9Fb=WBS0DHgu~6-D=>o zp4TY{vygph9y;bOu{Kix{iff(WR?@_wfRAc%PUtxWBN4rifU4+ws1fABfClSfa+OY z6{7rbjbBM%9n}#Rn^IUO7oX47!Bl>D4Qx_P0@X~RMz5=dX`j_8m!Ogy@pAk+<&(#( zq@8`S>6txjisif|(eF(4kG?85LcbG?@xz$*}Wo(?+U~9AqFq))SlJ_?&}3SAgB5dUMKks)jcmHF{xF8*Gy8)P&ts zhbY&H@hg7D*Toj9|NG+7D%PRDvYVng{y6%bLLZb1p=Xa(FhzC`^`XzoOI59gQqF~H@oCP7gm=v;r#@-pg~Y;- zxcTOngZz$)ZT7x;&p=OSpevh6`Am^rM6B57Sh+*k@1tz{EcbJ4pFC`)Vz#Sb`&t;+h<>)BpM7DI;!SnvmU0P{ zAD++miQ+Na`S1aQ=yxJEN2+WN*2`smJu}o87L6a%_&(K=Qr$<*M~1XD&BY!_jH^2fEf}<43S5C9SYy{O<7K z!|gM=*|TTccRiDnC=b)iChOOwm7z=Mlj65Ayjw1zW4;TJxm}1yR|7ZVe?5h*g6)&@ zTUdh4RECdM4c{8j&pzm98~WLT4OGwPYWh&dehS%71|0LVt!$TJdNtzsh+=`X9N~$UMS@`Y5tW$Bwk!%UCnWz`r*0wbE-F20-KbF>1y=4 zT9{%}3&Pw`HkY6hHfd~KA(Hg~$2Xt0JpJwR^R28$p9AnIhCX1^_|oa4a<$6ngT~^J zyBQz{-q}pzQqK6@Rx-L|6MfKF9@S`2&b;be70{l}P13ujb-;UO@!~c5JzohwpOej` z>#q0Jdj`5Y1CcgUIxBi}z?IMBtsD0G4& zJFJsku_?UFe+qgCThica_6z9F%jh*WQzhHi!I)+^)Q@|;>?YYyiiww_v&HCcE_xjO z82k7w`+`kz{GSZZ(%DY7fnvxd=%b#QYy6ni-zPYaL_5HSqN&KDJc-RG&N#c??vS>XFP|bmAuJcGXh53}4 zGq8hA^6SJS%|)%xihb+(ooW&2xty0x`kb9R5`Tnyf0VfNJjb&f>48hWWg%ZKmE+39 zX3B#x#W1FVHfmu^Bf8m&ZuW&S&FEB}Y(Dg=1ij6Ne+f_0zHCK!7K6={#D3HGE{pB* zSYQ5&i}@=@g4##6=A-6cQ5{cPBN+aavt0A9g-;*IC$8d0)XS*rXiH%0F>j za7lFuT3}N@*ktR6!=`$q8a8R{N(oYc?UZpVZOz*cIgWMUvFxU3e#1EWmP|jg>4$P7 zR6CC`IsQJ|nSXSLNjzv5HF?{q8QxA^aPdig9r31NdUi*wyg$bd!>rAu8V&XQ-pWl? zjZmE%waq@h^WEF!&;9X&3vNgtC#2V(bK2MY-rX7S+Dxix8EG?V+?+QD{AQo;B(80) zX>mzDLG;^Z{N!iIJ!&@vxJgf@bgq}Qs4nG4Iu$c;BOc{)+hA|EAanFZE zZSbXq1KF?Y#fVL^nVRTNEx&g;=P@5%XTbKvcT9cDJ3N0qT=$zNuD$kA z7X$D0=eW3gU)`Poug#>ImaaZiSG5MHwHw?W%4g!bc0NJyZL?|f4INyP-L&!O8__S> zOkAhdW|Gc|OA@Z%u%rywZiY?&2{}vIroO)3GD>yiluypF?2$ma38Y_S@(P+d@hLwa z+bVb|>vhE?&oV#kN_ZSQ2iqqbo2dYwrWD3h(vLc9re;{w55BabPmQpq2AwL0OGW5y zF8qrACHr`uKEtL2^g0EeWw0IjI=%w7k^dqaQSpA&5m)Y^n|nnyTr?lK@|-l^OCgdf zCUI_joR4_c&w*k2u&Ed}sTQWjuhjhsU58DoIcMvK!zFK>-g5X<{QuYvNxho3_J>Pa z=hyUuK13lgunC*j`lb2wTTH2?A224mZM%sdveU-Di?Ed{rtfCnf)JY&dx{@Q-qQg3 zqPh&K8zY;^j)8{Jsu7yQIaN$B{%v#2anBj*O8j-zs!hXw^PA^-{kd+{vGUU*3sL z^6j#+8d-l%53&IJ;6d7fO_@()W5AeV+N*#$wJ@d$o1qoG?2A4%@vgX&atTV%*?e?2 z{#Ug981f>v4m?Yy@9Aup&3dj@Zv{H7zS`&R(pOkyYZviuYjLtn`Qb(Au*TS_9;Vn7 z#pf*6(X+ZDVol1yti*1r{Wlo*C-faQsTQWUPOtKuDiDqPRV^otF^O72d*aT%WF70! zZ_6frzgYU0L|-|#zCswQn#0u3^S5lHPWTSyFxY8rCfQ5XvvxDbN{CJAqm=LDVUvx4 z(--~DIu~k7Z7LqeKF&PzcI@NA?U!D9cW+J;7kBS#pJ%|?OuAlVGr2n8O?*BGnS^K_ z%+-j-&3)?gJ;Jq(ZrW!&T-*2rYd73$bG0@8RyNa$)u)Q!H56Dp5dIXEFSHqYnYriR3N*~C}hbkh^P{v3+b``YIj&~p;mOd6k(isU2JNIzs0 z;%ZuM;PVeLpSZ5MrZop{fa^N?O=`QnNeujaTSGu>l59BocJzm9RQf9az}if*n>@n3 zIq%@@X8jpoc5vyK^S?41&iv9;jzfnvo>u;aVzaqi=Xw^V`+MBmCOYJKiBI|Y z#pH@l;rM1p$SUlfN70kV(LZda0vJ)k`8D$l6SH3_hRryiPUmG_Qiju&Az- zYGR5_3H+Y}$80T3{JC=2R0W&r{*|_1Q!8w0gH5g2PEEYmA*zR2jugYCe8i45UPyb6 zJ^On96~AAYO?r+1J1j$Vj>QzQrHT1{`)wx%zLPqdyNEHhGpFxv=FAMSDSv`uP&?~WaxJthn{S)iNytp^bmQx?sd@BEW=9!mgUvtehy)kfBJ`ab{QE> z9N+BD5`8N?`891k$-Vqp^ak6f0>;#$mrdwSD>~VieaNp<+)23vC484pKjR*tEp%DW z=Hls73Ob#^cR9aBbp799+@Co%#MZ;)U3pFwNC~341i47UnY6br9=Y$2U|sqy zHbo&Z{Dykg$k=RO0p~&XAN61S)X<9|4w!QA4xY{JvNlumg5AvJ3!7%P$v3-iLnaZ%4s^Lxp?e&2#ZSbXqebmFHDwdV9k3zne zo#p!l@(enR&6JD{mCo{P)^Rn&D>y#YCBO%=c7uJ6j;*Be_j*>Rx<$$l*Z38UV^Qw9 zY$iYFM|FBNA9(?>rV{))<%rjO#c}*AEP_pa#il>e?w?^5qFe&yhilAl5u!Tc8V9&v zd6te%SFnHBq?#_#^aY#7)}G4ZJQQ&rbl&MpRM?-(7`fAwPHngLQtRRnn<}QaTU#mt zn<^T9`T8QVnRE^`*Mr7E>o?Og%=kCWocXVkvo_|h3l}b1aPPgnIZfzN@2lrCATH_t zCEq^*adlAY`K&p5$0PHQLy^OgR~Vwgb*~sUbx3L>oUPK>rSTE`h z+IXD(!KNg5md0}W+o^_lHH=ZMUN^si;x5XG)-y=ubg3qcYGmirCyi^dwfE57M7GIh zy?i*PJg0KltVtr`E;5aO3&-65sj-;4e@+LwNs*xrpEX`I_!*?=6EI7>~>=zd?A#GyN|k9J}+?J|89wVQrR#in-rJLNj<p( zD#3Odx@f04TK-(vZrXJAm!{8j#&1=j?}~dAav#@oFx`I>xX$H&XpD%h`~6dnWtNrn z^yac9*r|rJn-{sfoS)FnTO873He#XKy z--EQlb_v)_sce_YcghPdVttKYsX~`kGo=Z=lz!?tx_ySuXT|?D{@%@Tpt>V^cA)wC zg7hs*b`*MDg#TB%n|;G3)#+6&C)IT7_wOOQshRhV8sdCb4RO^a$c0S_^liVnG>>(U zM(CTkZv8p>lSqG*2a!*Iy3efH11zIQj8AgqA%&_jp8BlJ)*H&biemM$FVF$W?E7FTXAr&U#HJ8 z$(NvakJ8Q)FyL9*#TKeYHydcH5AC+mKKX#YdfKmISt;!o@_j1X_-;qoE|%?7r#FNB z=D86|CKrtufODNAt<7HJFL}To9?6&qEcADz+=EAQ6Sf(7z z3fNSQKWFP<{t+hO&xuX8hB%*H4e>IT6(OqUln%%It7%ir*o;sa6%PLbf9?<1O!#zgY4bUM zFb6Nw{v+#kG-zdLB{)g`M)|dM}#}eX_drwRpx)+;r^7|Wq_OD>TQ?!ZA zRE1vF(@ryO_Jc2dXupxqH87`~<61eulZM!_&=L%lt)mEKUao7r?GW)f586wievg$ zI0uisHN>m=zZ@xsOZiAP5`6=0&W(_s7`2#n;jEv&h)qGxrH)JXjrHeXE$80f^tlOA zdpLR6c9TD0r>UFMZkaS>Wr$6+v)fJH_?^VTcTk&vK8VX~V}Ii^+E9BAY5!vqsw zBd6(l#lT;=>Z*r&Z6=hd_qES6pg5Ca;If&#c>`_yKN@klma2pDbD!@Fu4{1#k=-I2 zfH=bJ1)K`dO*eO@}{f0ARFk91}eVSAIEU9%UTQVI@3r_sp@7*k6dO>bhCz?Z&osfqUW ztge#&l+boQ_EF4jw0#fzc?|u6Q>xRO#ddk#2J|)p7aYQ^R5BaA7?AciCq4beEh=K1kEeqR? zxOC7ee7dE|aoR;3d37XP|gxcDVAeE10Rz>gSn z*IiHOdec3z_tkp_x;q2TpVPD4L?kkAU=queYpJ|}O@zyL+VKtY1;i$eBhx)M{tdJK z@Q^>J7?W(Kw*G_6pc#B8+o#3}JnCdSeQJXEK}(L^ZS5s-Niumg&!e?XN%-C?KSO>2 z`?33zK575H^N|@5GL!#jnqY7|Y%1);r~HCq6D+%(V?r+*UgtiKF1DeIEij`VE>&^7 zrL?QL5RxCDotu!~;Ez0wj=eyPiRHPhQ^c{9aZFX%KB^(!M89mUUO40CH&8z-)CWX$ zK{ReQ3VY3tJA_S|XTjC!Ey16wz@MvzP4(DJsx{|oh|6|rL|m=jGCmg}c}P0qzlb&? zIkd0;?_eAH65w}?roVCYiD&!P|0CoM#@8Wh- zK276S7-KhBwNvQ3wVCLbYVH-#N9BDfH7Yppj1&PnKf^>_xH zKc`&FedP^Y#bY|IX|88)oFeu$lbVk|x8!KcB*vB7_myi-H*u;d(uqx6x6)Y;pK^w7 zHAl#w3v=o4@BH3WkLCWWTDOW< zMxl3X--0gogD-vHQX`*h(4lhlR5{|=PocNh((W(WANxsxDc(B0r5sNs$5qSmHKNCT zuoYxC=$WEoPV!ro=VW8}^dkpdjiX(A?$}=v|7#v^)#)w97b=5IRj{dUH{1V#cD|&& zKZf|!#Csi5jg%wBNCA=!msF$5#+T;s?qpwFTFJWDjed?N0H1>NIpH;II?h2Z=cAN9 zQPb1k^cnu#7ba!cHeyOUP1F2c)@B;HF2p9;P{osX5+mPkViarY6SkRDr?>>ZsV%ih z+kM(zB@cW9bpgk1x%Jk^Wi!cE?|t>2f$q+Lvzc7pfMVco{uGxtFqdU35#6PrRZ zf733LAboc=C9}{!-P75R-CvZrg!s-xX7nij;6)}kfA8mZiB;dhSE5~s{5r<}`6|%S z68e^peH6Trc7M)(eho*SfsHKdsME{(s)wnuzp5eL0*7p^Ubuul+j%u*cUZQJSm*iXOTw>E$+eS7{A;(t1F*7%40M5n@{K906+)fO9r|Gw( z-3(u|+l+!u^6MJr?II78SQG4uZi7p9ZU=r-ZLgYpS=g4z^gHeqYFj?4S}0#$c;QX) z^XAR#wV6<+-dB%jz}ZZ)v6B%O18?E8t81xR;K~~~hg1Uc2DqLbn_QeC@pZFi!?m`a zlIp!>XJ^~FzZY+KWS?vbpaU~E?&{#u=I{O9w9TMSkbHt7bYJm`bguERU*L;ImvpZe zGkmj<=^lyX)Dm>#VH1~k!Ctmgeqoh~>hna%c2YdN3NDqRuLUqD=^om=7UB5gStpG+ zQx@MTm!Oz+%hBO#bWb%?nqiFU^txKT_2{Nptay#$Et(T5lXat>q&@hjdUqLor?I#N zY^OQV%VCqo*V!84u&MRS5SujrN+X|Zc~`De8KSYjs^^r-yB){a9gn(OE=JKWKXy}q zJ_R|K@vuqbZgM!bV%Vfy2;%zD^eJ)Z7bcJKLUnU?n!zjD&FJ+ZHVs`9z6@LES1{l)lTkElFFs|Ip}&ebX%69X+AM-g%6;-*N!$0cKlqo5&6J5hmrGxj zgQ+^bRp?zE$Jc}os}^QI>>t@qnp3leWwINr&Br>*$BLy5JHG?lCiB0ohspXy*cxT{ zbFPMX<8FMpKj6#3omTjxdFzx%P|dP(q?peINH(7X_<+8($ZU^v$0P6ZlUP6O&*@xh zEVL>CY^fdArivTL zIAHm-dLB^8_C@;L`0X{GC+=l)?D0>j*3EyOa>~W|4?XnIfnYO5@<)2)74^}H{MYWp zt)q9hy|--^|5Ltn4s?@l6>RxZ3 z&CNx}ruQHV;J_pB4Zf5-X`;&SGx>#;d+{m0;$m1ryCv`^|5^5NEp6VyejY}*p2Eh# zW>QYL@|;|q-dc1|^)UOuqBiUW%?l+Tw3hxV&q;QJd?Urlk~vR`rORfDg|k_Fuekv< zr>(0YUW3i#YW4R012!1^kzdzRXY+{L+qH_;pqF_z@psnOIQ6m}qXyCGTGiJkXGvV;vW(16Cg;gb!cUX1>@#p+{ z79cJw2UT;>KV%={M@j;x3MPHL% zGl#Cf-Of{>oTjFxCd;Nn54$?#8^}MX?m~1O!>BRKw|8*qi0@DfXe2soZ6@yFvYF&- zB;a%C{%&n1_U*d_nHHAmymujivtYol(YMF3Ii6-;&zr=`)AwRiUSWd?l(L@2uO!|{ zTR%b`VxQPg>DW8jFiZ8rOVD4{>8(NU8qmKMj^EZ0hfhtgMzwmY(CadoR3xr){2Azb z;8(OKrqU19dsIxkfNhi?Zs#<{pHs~g)#`2iJ*@jf$aYdZT)6~QNEuRu7A~-Z~Dv2gh&oK z{&?9V-e{bc?(xbGRD47ty;4q&M1F}^v`pV?J#C|H9k(2-A{oUh2mDLtUguorS?AQ{ zf!Fc5s~Gr4Hpi#K7l02z^i^?+l-JGb^%wHIKBzijrlO+4<~1$dcwf(KLI+|RJ~qpb zC)R{7Ct0{@r%9+s?{xo`u4sHe?6dcF-Q#ty_sc(8giPx}X26+yU;un6#rCPf_Niz4 z=2uL1>BznKlvcO|zwJ@l{sC=bSHwJmzOr2w+vT&*V)VBh{Z*abdX7!?FjYU?)ezS) zE61rE-PZgDvKth?kAaK6ClQ?|=`8E0CarQX%eHb{_;Z@ixN#Re+8yGO=7rMy2K7ia z%gT`wqyWiAtS<+5ZLDn;?>(_7^1EADAJ+QeQxyG*g-x1=IFr5=aJ-tI0b4hKe;SLQ zmN9Z0IRe|sW7>($)NUp-wsHJn?ZlmSnc7)9OwO1uO#HylO_cmu*^J_{YN+Gm`x0L< z3284=3*~CXz~8v?$_I3<>6-hdvZ*T`iKSi^c^TwokMu|5PnCb8m~9S{i{v4Slc+Xh zq-eRm*LvDU+o~P$O03ep#6Rud%P9UmpkMkO)L-#g=fN8T*E|JN5l;+!7%_0JXRj|1 z3!AXnv&mDOF>9q|Q%y~c%Iz|b)q?wtZ)s7?Wo)#pPD1TORNblZ9aRq z890kt9J;;>!uMW1+p;zjZAHBly5HLv^)!y92k~PchicKoCiv3#4HMIJ zJ8UY7;8UTAjX#MtZ$$SW#5RE`wiYIRE@Izh@KIw}R4=6o{Z)-##l%!Yyn%k{d7b7Y zck>&lEMcg0gbQGxPCpaQw?#AU9odu!6wbI-qOyo!5z(S(1JAZxdy3Zc_~te zXpVzeIA(tbF-KhLP9mA4|JNa~R`WZk?o^QTiCyDMrEfXdIby2pKJFK?gA%caa>s6? zM$-;6bmcBH@rd1K>QTGRSQuqvO)x8C#1|&E|7Rv3yHVT9X3C+jsql{aF^8^s#ta%X z_`jDeJ8bNI_dWSdwV51~#7&8pNAkUN@0N~;8M1rCAk|wGf5a9sN6)s4ky4}_sX(fb zYNQ6KMRebHqW`sA-)lW>qir>hk=j)I+LvRL^z@&FPx?Ld8|d82w$%C1d1^yOBeRg@ zi1NUn^!cvjy5@TJ`T{%`R-9tOtl!wVPh>Z#rgwUJx|ua^t;tkAqvMi$kKj}5^sQl= zX}4K>$}W@BADy>$2fD3$c{10y;vv!_>67%zcQ`T?>48o0#9}FeFFaj93x!Rv&@bf;&4oPn3@AiH3>8?pPS#nTSvSO4pkv#yXXg!kEDo8 zY~wo;>5fU=Ef<@vLBec`;#|gXP7^t|8L!hm$E|xp?T5zC+{H2dKPQg#1u^jL#Fcgu z`);>f5}QV@Z8v=u?li>{x0w|9735ifU;eCYMzy2%l3t;{;BU?8XZ+NVhx@^0m)V-T z(tBNZ-=vq0N5>_-cTAG4;&>$8a4eF2BMyl{Wr+AAoe^j1kw&B$>4Wq|q)U3HGyoZh z$RF{Fmg)O`NGsBWh+Se;2_m~nwv?EtwGsLLy(Ecd}I}J3_s0( z_vu%M2>BtZ17MjXHgzT9)grck3|4T=&X;R}acyu( zd}?@^F?x@g+=9lv_>_{qnivx{ldXlx{*>!f!8SE)t2(`^>169+!lfqqrW)c^aH$MG zrU<=MO#(4B_z1@VbT)G9B8J6xi)YbBpY=bYXG0_3|uJakEW8=JJ(>K*o(7CrU@K3`r@Gppg?=XXw z@3L{G>6>@s)3p<8q7DJJR383Z;vn)2ltZE1_+rjMht2eoS-Siw=8GTt*ST|-&AIC? z8)p&&z9}#1fYSrVB;BXQ0QqY2t>jCH53-5M5HUj>5`$V0@keYCW285#SA8%t0vUyj zM#duJknzZb2+=Zqul2Nzwimn9u5_^y(Y|#Y;*)$l>8v=aV?PjI>X-T_4$Ed#-^&s4 zemF7>Q7x2p$n})B*e75HH4nFHh-;1m`E`0$ zr~FIhVcNM@_+Ilk#fVGn%f{Ipo4R`Mic4B{CBkuuO&T*3L*EiPx9RjRk7F;TZRP{@ zAx8naAwLuWL7hmQlZH#x|2VoV?67@-r1{)0jfd z?_h1Fm#O#gBDt17)!e3^U3%#^ZhVTae{oVeAYG3|#3bpz?$bGle5*2~8j(#T7RkO5 zhlV0z&`4wqBF5-`J_V8P%s^%$vynN-JVf{UNYV1Sh}P3K+Fl$RfrwGkN9|vH%0k3U z@l!0-@v9#P+Dm;>|J2V^ME3@r1Kk63u63?fAcrBp3)KeUns#gwD{L*=S502st7h7a zWtK^iCo$MyZrw>g2(2vcg@3vbuEj@aNNz%ODx_`^|2>S(g zj7KzF(!Ji=ZgY9}aHy-#Y3w`vT&}Y(haM^(E?cVfY5cDzOlHpLz4(+}FpT41oicQ{ z3bv@`oU7B@4?UFaq6YNp%TQ*~Wht$M^&c;Ip37DR;C$c7=2p{%Y*6 z<~MM4#M@w!=7v%{ybca2*Gc17ijjOISzN--@|}%z#iO2GalRA|A zC+1=IS38@DbC61#@h_Q`s~_V&HQ=u^W-MBH!wru)UE*^3hrV>(OT;7{lkUy3MVy@^ zCW!;(i0q?gM1I*|L@XMOh(nVRF-ZJz>{-ZX#b=iyhak(57097sS;hP62+^{Y$O=T; zEJDO8wLKOQ10A2l$_ykC(Q!v1>dS%l5_5xy?iI3K^?S&MlwB(RFFyWmrQ;@-!c({7GFyWJc# zS21vOSbCDpHJ%1XbYIu~UH5t2?`=NM6y77n%c@myr8{4a_Nr;C>}l449T^WW&%ud% z&3~Zrc1gvjaO@mIEytpoDYi~8_EI1EqL@=HwvcLwt5$CT>*T;N)pLq|kmGwGbgmS~ zS4=#Q^_Aal=QqHgQ@u}DN4y_AYDJoN!Yia27AZ&E&T+tdCbpHIZB%R1a%o2Ry(b<; zes>w$@EiJJQxxYhhI5bro6_J&F2`OicUHa;yNLaAtaUG9m(T{!<@We;v{iwQ7Q-dwJq0eL zy{k-8$`O0nPRh}Ys(J+bh~sI2Ew)ZC$KJ%}I*zl7<;o9N4RO^Z$kg%TN80*x>_gAL zGWlLPPRha5{06E`tJ-?1q0Ky3zP_+XwZvPH2AEW{onuEdwyu!x^N^sp1QTuk_YB^< zl1LVL|6js3^jB;Oa9*NeQyk|(`JkB`cOm`I^F?bjeT>cYnMoV5m0Bp<7(2HEJ874h zb!@wtdpz;LP3=6d+i7ZNZZp{<$jijHjnZ=f)rraBJg5$6{EKG&#>dEK>hssBQ|GR` z;fCKxhjhLDqh7k+-8HXc(RHtTvh&~c45$>TL8Jp>lJsCKG6fNj<|ERH<%l@67I6$Z zjXdKY!;y#J$(wLxCw%#f?r&X*a%_5%h;9BK%zB;nuAtqq)Eg2%WlQMz#n*r2d1d!s z`%Ax*?j7>6laXAc66uGGLiAhcHxT>(==1%Q>zZrY#VN!JY<9~I7_xHh<%au%oriAV zz=1sL${`>8RAS9s?_M@V@F||>@N2j1G{=0e-ArHmg$e38myIRE62(Bc|5_cAE=i{} z-;y0`AHkwXR%K(ekYnj&szNDd#EfTG~68e*N6|Qy(y=)BhS-DOcSC>cIS?nu?^WwjiHh&fJnUvq7c)oHWRBuFM>onF` zb>>uWPIF3XPHxS?(zu=Fh;p4Yex;c2^N}Pt=7VRxE0C_3)YCG@r%TzEbEllJD9&RH z=Q9CrlXqn2B`$$0nnNA?C#v-mlQ85n#>ahOYG-ew2Fgy$qj@Ln#%?0-@-XV7EZJ_# zCT%t8L-GBZ@c}iLXg&;<&6xC(Ny&b}9Dl+kx(+_O=%U-i0bOgl=KkIk}a{nK2zsv)VEjeHI5L-Ux(2hqNLHzSiHB!W|Z{5fLW zHm20+xt!OR!#7I1hjva!Zel<8V?R7IdOt|Eiy~H`Nxs}s-?}b9Y?p} zx{#mH6`N!qA#F20#b(-NRvfq8Bx`O;`30&YDVo zdOpR6?7cpnTA?+guO(k#myyjh|3q>wsabQ-${nVb`ViR%f5KdWA28;T{!z2bm%+J6 zdeP)l@cp&vDB1RU!=e4qt3&D^3rb? zL=uopL^)pion+6-zt*z`*{{1pp9gK#Z4ynEZNvYUHWq9 zWa*Re$mr2$n zGINjlm{^nixt*r};%%mE0`VwfgRzX;3FtXMHs>RiHshZ+CvUk={>)z&Em}9@rkfrS zo1{D9gkwfm@A}?}*7u5A-qm()nOjHO>AKc_V-e}Dm?Ymo*LgltibUEuq`&H~&clK7QeX7@>37RQ$`C!5 z7=cVj^emI#Ch5OJ^^5KbvB}0NxV9CmuyY^1YL>0N&Dup^Eu9&nX>eeJ#6aW z6M7ovRFL@Tp(pMzN1VYNjKi=ER6kPwMK-eW7SVIB0ah~vvc z7qehz8s{T$C+*$Jal$_NHCgmQ_Mc*B%ClCEmz{eBf6mTv0F!JjahRk$f@+vl0h3B# zQUQ|j32m{Rt&KUK_i0E^Eb8vNAFv(Ar1`3%IEOLM^4oE|Nmp^qX?(YbOZY3Mv9Ym( zOO8*<2Pvo+W@a4q1<&VpnC7{R`yKU(Nn+09AT?tA1u!^+^O5v|Y3}!oS-g0i>g~Sw zgCG1{*Ou5IM(A4WNwkhc_D!U?@3g)2Fj8E*ZhPr#BBD5|YztlA@_}^!twNd*XDf~8 zvuve>$O>c~ayarGZ2wn@CH>X?{$i5+wSBSU>-e7eXG}vwgU!X!yL8IiF8<@IoMZJ% z{Z#)C6gJ8J(|tz2rG7uf11pif$SB0c!LQ`e1lRAi2>R@N0`WrJkWaw|+7g6>wpBCjZBYUN#%(e?qkmOIU&P1{Vo#-}M}A>Tmr14zH+cSx5y z*mO0=;bl|gXIK^7jK74NUOs&z-s?-}TxdM79S1@?n&Tjo?PdGv*_WMr1;(h>f@(T7!ynCY zp!rvryW2jiQ!as<7s}1Q5-l!aZ`yg|#HFsJJ07{^OW6+QikAV{6wPtRaeN8z)gRAy zd$^>}inWSI0|pE*Lxv2o?~YH>i-9w4Hba(CCuPcKCTr+NCZ0J(qpZ!u`A&J!_!FLE z{_tBB|NigQt2a-+?6RB01;s>kjfqoEq)$%VGOZ)g`m%An;%!6Qi9Jrd?Pz;#rx=Cw zR?l||kWxfUYC!a?$HkSV@OducY^9BS-h^CFy!21bfBQO_M~eAqi^57 zMk2pMIXGIbb+o>hN$xW`re}BM%oC#XCpJl+4+Ou?%O?Hqx~Ehlx|fVa^lV}!@@Oc& zqigwIu5a$U&L<$QVCO#~{<(bhd6rGGm2_Rp4;5$Nvxvc@&1AzZ%z4`8>7_Ol;&B`n+YLTYpWRr@iMbPbpZBzs9<%=ah)v zTXx^WvGO^C?Q>wO7^@s{H}^`%90yzR<=~Q?ABoRyUZ`^Hsbbibk0jv#`CzrpQMn(I@#DvvF=NJ4UwBVSqK807d9X%jjA^z<(K z4SQ}O$0{Dn#yHT}B->f{8C?hZ4F@8!apxhckhel{aIxwB5SzpbF+=QtAu&a-nuW|; zAiGJwqu8Y1cJZ=fOi*=19FO*Tf5(ho@|oFi>UNVm09`CakBiV}J?qh&Z(?5@Owqkw zY_j!54&{9!62T+y|E1_&$9Oq(#^qSbmrJ>uZBIk4r~Uib7dDh)Pp(Em4f||>XDu8@ zKN#Bjwn?fyc`w^Z&+&p;H(=YrYB5gj1>jp6c2pMo6km(rtj5;qIRN8kZN0gc&uAAO z$!^j-+?rF;&c6be-25vU_q8r8uj*~BHSn@#=n&rI$?ADTq+494UiC<10x})Z_3dmW#g$|$DX#RD?yvIU#HH^1H?c@OiDZ%E zk(lH}%ewN(dg9Lhd>4*6oyYOYwvZklNNkFxKZ*s&?$+;Ihv>eddy1Y@tVVYDe3x-8 zi%k!N;uVVX67Te-;M0(2Sl0HEeMToX>9-P_bR92Sg^i=ww(KE|=ZIiafH=is;uo{l zGk(3A^)%i?`HR`GLG!+GAGY;tb-%YZ6AZC2aIq;;9ILPw7{66>1as`ohV+9CPy<#?RQ6oT7ny@hLlR7L5>S&8i%=5O_{3}Htvn}gIv0u##WorzGOI=A% zOwxCp2j9<-Fq>4LJVtENvM8i8o1{PDknE+^t5-7z${}XXoH^F7lg%VwPumpr-D1ke ze_}HFzi(p6ISnXxA`PD7$8J3QL2F;s*Ec+N;e|iz!}_vS#D{v1=o;%vw2u5OZPS8i zdvQhY`d`cSy|%4EWaEoLde{GAk=oFD+O9vMYx!VgG%^tpljb5z5cve_ki(J9$Sqv6 ze{pdo<-sVgs5?eDHi(Ir#^=536nMLq13cn|^_QL^3Jj|EP87Kkano%LVC!?`&*{+p+gxiH$L# zyJfJiihbFf19YvG?fY@evYi?@o|>0UY}vK2sq@@+x{i~QmeJ-N94GB$z&7O)NMDQD zR()1of;#LV)ihEqam_!XdF$-_EBvqe>2?lvn3T_Xh=UAxxWPx9|{|5uD$+m#Hw(i9y0 zp-E<5(O~K8#;-XYlAklBHBXr}YfqHT^zUb$dDST5w6ed&hc-mMl#{-E?n?B%*4K7o zisC`K7WJ0l2u9P632lj4Yc9)<&y7a`!kX2Y5ReQ z7!&)EeI+}q5B5$Q$J~cwQOv29WtDKU^aYbzuy@XrY86Ds+`ze@jV#v7V|~qWApcZ3 zKN`o;2yxQzrth`>FhpD# z>5&n9)^dHX_2r{E?ukc^Y2ujnJql4=Lf7$3WIp0-CEafiLr&rv{m`2iASQL^!+jkb z`M+obHhlt9)98=vrUQ{pneC2MZA zEK**KxTNO{^6w5=%XS@X5~DivY0&JC&7_r|F;P%CYXDR2^QRLg2i_-SMXhoy}6gUi0?PS`Ug$0 z>6a$h{D=uQJZyrs5AoccW#td?jEi{{3ZEda{xK63^DyU)Wl_tJ3D_zVyO2rrW9mNS zOui3uDFEk!usvS>+$NTbF(L8${Wiv=xYFXqi_N*`o@>rK?>x(=DO0AHkt0WT_;T7N zKE2fxaz9BX_cU1Ys`1;Lu4m1(S--{~oT!|ET^C$%>j>7>H6)gJ`6O;Q8%P}Tik3%m zNq(4hM_-#d5m>*5qV{Y#il@$~UPV^bo15}Qg9*~YqO$p&7E+(0;-YgugiF^qUPWXFgZ zVu!|OFmJ{oYkp#F{6diP=7UGFDdPX4`$E2%p35n|o&Ou!xQ1=d!8g1e+lD^u6=R|w z&9KOh1?D*Pxt`;w<~YjfXAy1X!N{y9Onl~9d$Gwe>L2}{pI?aWQi4<=)tw|audm6? zE4KOGvK1tXlgN*oIB}vm`Q($$_rL#rbJ0Z?nN_P+Ssza}lb&hl`JE)Mbhyc_SYonD zR-5#KLzy#W1vU9r(8f%)_t#OQraVwn({csdT#j!ixePgv|Gx(hoSe!y*c18R$x-}& zIPFW0RoozFzldl_-B)lX~-;clU8CE-opMr z_iXRl>3EmD^mVb~@7<2Z$Z*|dW7{5Rc2f+$so0c-lp*rtM<6qhLy(6;^ThrL-4>gE z6}|_D*_46q!jh${F0pKq&n~-3F+s6u>AIUjailKz6jSpyG4Rh!QX_tkV^aZa(wHq>+NvG73th_#u-ro)g4J&Wc@@%nN}ceDOkv~dIN5-;mA#)Pfr#sbTBk`1Njbro=_ zn7-z79N8R4I>$hb-ptHV9oO|gnn(ZJ{p)$E@&gqAUb%9mIsNq0t=%L>={cSJJgxJ; zZU5V}o%H)}VTy}=yI8p1-E%qbGWXfV(cN}`%f7?EQ2{pLfx;%m%M@=Co05=hq#RK^ zaU>!ieHrq6C`J=zQxtk{{R8wh1-+H;g%7s$&zUr6&P={dB<@hg6z*lH?mC$Ntg?4BrWCcn6Z{o`AVj1Nm!jGD~;*v|QK%Bl2! zpY?x8d&FNlHZ@&DJLA8+ALUo z=N>ji@Tqddd!~3Ov0p8>Y=RH_WE1S^V3T8%dl#$b!$5e_;mcjivh(oi?!fNB<|}|N zHjjyQI>nec2A4msXLWjJr&^eW^febQWwKo=+s9&eDVN-Lok`1FxEGtG2kN`4Y4P`d z-{1SM^hLTbY}haxXHwi-&*tXNooksieE9JHwXV8jaL?8M(eL}iroScDBJK-+2Ifrd;#1~`PK4VPSY^u>)4VT2XBDj=C zJ6YI@X>cil=K%hn(k6CT)cq!q@vzCw@3R-5G(I@BY^_PFSZ~s*HiV>t_j3L(MM~D0 zv?9JQL~>S}v^3&2X_Jv=q~&jr(QLakB`an3gVGYPlqPN?alqWb50g#!X6Un#r$T&fH#`O?uHLlbU;kNy<3ROqh5C_v{Mg zCw?_+_Ui8tS3WZ=XYlToWBC6l;!*pO&8#Cin%KZG5%Q^rF?udFi|=Pfh?dPp<`d&u zO*?CmQ~Cd`o?=aESJ&&;!HIuF8)3Vt5`BwBU;mld^qJ3h5&Gz56TFb!l!^|ApP4US zc7kP-ejBk#u|+s;CM~+JGnX8rU{leMckt)J+$!<1iC9wyo3L3r*mOO|F%Id5OIjXS z4^OVc|AIw!uHP$&TiyFVh%v!i=MQS!Z#G;?=NVrzT#EWRZHjfb^FQ`u=94Bm=T?(n zU~7GKVpLMqcd^6B3F!ARxdB4TWsgGBQo+uE2@c%Rgb$X48! zEMy(^nd9zvE{6W8!D{oL-Kygduqx>zRHq@3R z*&}P<%rkK0QDhLGwGTa)a^m*swol5)6_cEN?MjQX1nB*0Wm+L9l z@*lyS{n=;OZp!4j!GXjkG1ePz>dJ1~>GNI8b$TTtyNT;Q7B(e1HoahCihpb7Ej--l zd9-}t&TN7UWpJkpNp6zO6#h=N*^01RRBJ@}i^6?94C^kikhgE?! zFoR=_(lKN21>wnl$CzNEd$y-qn5vhO0hdzXQVjjDjQ$bN;rZXr3x(e2KW9>~CA`yAJEKKT;5j+86+b%@%MNY}jLmV5W1XXX;O%&nvC#4RyP zj7vrIEIJn{MyilC@JeH4JAOaKOQq}k!-Q|jI@o-F=9&}B)%SlUyQ#gy{_tNFx*vD2 z3BQZlAaSKHnmO|~ST-qU=h!5_VA8_w*%YPuC&ecDb7E7W*o3}1HpNA&u zz%tkglYE=d(`(=qvGD&I*~A?QB21in1@S@^v1 zmp;dMmcbp@x8qb&?f1ws2A6F87jh_6pWD`vP@3Irv-f@ZJ zj)qII^dX79z!D#}j*na2FOy^R3h7=40=*`HATCS7)7l2l_umY>-X_zD7}dUCI9J!)@o7B~FQ-vZ-WG ziBb7TDKZJa^#=UDPIi=hyl+chI6lgDehc+YY|{Dpw!eCcH;trodQP_-+1-gv_PUqd zBwxX?>4gq9>A8Zgcm1{@HvIy9ggcs}yOV_NCCethlkV6WZRnB4^(S+`k7GZ&|H}@L zJz(vY2o~+dsyVE8JaRI}2+Q)(*-m5SU|**^CV1##Ol9m-HByvgkcGXZe1oL>+5c^{ z_Z^PmW{!*HnX;+qe*yh3;dm<;>s)yozTKYZb~zbI!IRK@Ge8}}A-G`(w*`aMBC z^oCCMlb#PLZ-u1M;QaWOg7VBk2~)B zW9QGmPx>!?(DfwwTVJl7eZ6 zd>ih#)Y z0hePxJ-~7psXV8A^uCzw%3xg;TqUNTSa~+ST(wEAImP%j2B!%w)$^_~%*uziV+FAl zgKX#f0n#0lx?3K}D*1LlM#5YQaBM+-pE!P>WVo0KJM%f8rQ~ndykVjl|CZ4IJ?2FD zz*J6t$CUIv-V~Ko+h@_lVQ9xsUgZ?iXWEmddcylAXW-i=vG!GbIbuxdPn+c2Cz+Sv zGV9BY7%}1g!w$R8>4JFhO?^35NoT!`lD{WkPw^<(P-RFfby|P!<&(zy?$0wk_x#QK z{`c_t#7_LsJ7JUhBmRDqe+v$8zh3HtelOii;CU5Sg*!1NdyNOs!G}nJDc7y5_ zrQy>M%ZOu~+3b1itxu=C4B1Wc*|`syX-n?3x*`3rq8hfH>?g5_WyEQHg~Xb2xX)8( z!iN#|q}*x0t0O_86)DwYLKfgwMnEm)fW6WYJKhdd_s*D1!tel!MHulVp~eU;cGHT1#G4F!iZ&q3c082bX38nBmY;8F#)l5!*p zktDY9{R|OTCLrB$Xn&TU$o3C&ZeUXYvA+$+mk2xc+vL)>VvetpI1|Sg*Y6#ZL0!?( z2_Ko(`JbARt3Ef=j{Mw=Ty(b?Jnbqoe92R0=+aM3{ge-x$Mkn5rSWxQi7(;H(buFW z%?T&np_)vpv-{;4XZ~EioOJ!$qzmqv*Kv!hUK>jBaum*;%{>3nm&%Ma)-PA(p~ zTmj`v$TwDQllNWA-8x$T>*7|pe$%<|RDSEX?f2l2yM2jG`i$h9qp`m854|PC9>*rVNAhXE*@W%V$!>~dQ~3Y*SW5>!VK8-)AISo4Un4V%iIM@+mf=dba(qE3{HV;<3m$4{2i0VIOjNg)u>!-JldPL_+fIP#_1UzzTAc5#*F!e*O%im z`PRI|C&wt~=gA-P#-Ymie;R%L2z#W%$5WhK*L9?y=e3o@AIB%hCdFV~{-vv<@9N6A z`j%S9@$7%Xu5zATz|Q5c$;Fz!P4@~;bGI)qn-m``MOu)95smfLc)A^-I1gN~Y(f`e z!}n&zGthyk!WYc^MMqk@$+1cI7(KUJwE70vgiYiTKWy@&GaXX)3iWN#Tj`RmBgs8q zK1m#U7K8^HCnMWH&k22FkZzddmPgNpGpt)6F8vh!4*Ur)J!`t!Cy?+sy2vx0$JjZ#5$rZ{26sN2YWXHIjM07++0{sel+0 zzFcGf$IObA$JpG0@#Cl8vv%#h-v(cfOSi|D5% z8VjsC1un)Edl&oQxE22n-hqF_Hd!z-JU5h&=W@PEwL!ml?&WL2KC<&^!lf1%)xiHX z*h+d1sb`Rda7pnw-+E+xSV9bPO!B^W%_lFjPNfaUCD>$bS&lCemZ!0w9FC83=~q5d zJ)B`|Q0B1rO!>qQO}_=7m{Hc3+iGS}({I`lTlxPp(~q%3731DBSp(iO3AL|KM*%Kn zK5de6pD-t#{39DW^$F`9&`0KyfISZ!iTL>P4>&C04n7 zgTHr8700-6tmy-eiIz?UO7Ru6NUu$dJ1Zi7p*oiuKlxhM6! z-p19G>z>K_zGD!_rO>gWY|_87={hUaomnBz{o-OfuZU+$!nt{^q@&Tp$P$K~1O%kfF~X|E0C%{LIEWJj%6 zJp-=|A9V9#EW2Y8U0l~Cu|E}Bm6=4Etl+bIX+{j_^Mfs zUFa)eoqV_yeJpM6;ZkQNO<+v4YBYry<-QB8KY{JMGKK$dK*C&7y_#qwjy@!Dd>I^H z9&9fmeoY)KhTPVafxk2Pquw`l(?2wWiF1!zNBkRGNiuHjXJ*jik4^35_f7smZ<~~6 zV&6P>4CK;BxHM0UMV$K zPQi!z!f`3`T|S>;=Wbl(*To`lJ7S>r!@dV`EC-4mYk!FFAIB#B2J*8DkUB)QaV8-1 zk!O8&K5pzLu_$7`>ly8 zCl`ok?r}A*ns}aXN#giFRyj1%seE!7@g=McVA&+Q3H|F})1mBVbXdA!l4DmCahWP~ zx%O7xZ-y6qF1ZdS5r@(1C(&T?!-)q1jd70c&ux53 zTpGOi6H`C+18T*+V^WEI$5!(D6mb4Co;0=0Ewgm#X3M39hQ{riHs675J?%i$0WRB4 zFX@D{p}dT8zMk|%@sB)YCV4W~5r@_on2wlvSD$59iC40%#4P!N;!9*)-OC^MS?g$h zZKpQEOw#@yMh-MPmeXoq`W-5l@bXPcg7d@z+2$ zIwt=_`_Pradg$V{3)xr&Iqq4>}jr#`IAm)0e<~BIR-V z!|x!jlyeR_xACoSnarW@n6mNjn?7?tGQ(GVY9>-EYx2g=t-UmK>BpvV`Uj?H1kdDn zJ`h)p-KrdS#t3GXK5mXV?h?x-o~8d~%c(b1=Hy(b>qI)MYvw?IsgIG2lFg{Nj(iOH zdu|+z{0*^c7=EwD6+b{+s!PAGD`qKX@thi2#@pI9DE+VGiuKj@H;P4mnT zOvxzno!Z_o@%X3FihXB4ZK5+CCy(hy>Sg9xHXU}@nMY2Xc<+IFZ|0Ki@#STd*Oqde z(mh@Flw*~AKiO5{RRwhcR2Sh`&ZXuBe-PdH9X$DuZdlVDgWPiYkmBBnytnc0{Y`Y7 z2inWs8zS>BTj}UXWCn5$wmf>_*z_~>0-cTLew_@P($PiioM{Vhw)3iR@91DtVqzjW znHz{FVQa`=gH1tlX5xv3B*UgOxRgPRLy{&w!K^qK7M=SX^+(XRMEDoWzM`>T0v7$5&bVV z$)582)vrA~3w;*jZblrJI0wOUHXy1C zqxv%Ez?_T1ayIWLBjQ^rF+a7feTYe38}>lt5?!<}U3a< za+o(DllkCM>+to;Uo+m!oSnecb3bZl3k_zP5FPaw@R_4s@Qiu$JB!T)EB?41!;s0rD|^} z?d)Na*c4*YIBcTv@Mi){nn=C9Nnx368P(Zlie%G7jth?3=W^^jfOvhmRE{N!djsdo zPabHn?p2e>+*LWl-Z52^-nV%H!IWHz7i;({au?bs4WBbJlF+*&U??tSm zqW|M&z`%pJ{|7qQr20+$2MjUQ!?-6GqXU*rzcmTu1<8-gYI)t{F(-I_+nXl0FZL6< zlFT!(IL4_(XFq8I(!F@>gJ9Th@}rwpPsI{1n<78=z$)w$U*d5Heq1aPIFGhYpkK#^ zY$(N_6o*orTsBq#aVS04D}~7}AEA+FdDTCLTSwEzOt!~wv=V76jk8P&2187Wi<@km zh*4TDW(5MWts=Q3&Yg?g9}>-{97X?wFk0s%8Jj7SbD#Gt{_+bZnsb^!JUes9Tc!;5 zw7?+wZlkf8#vsF%eQa9id|)cZziV<>Cy6;^g4_oJ`EV)Y2{U}$17_x|LoAoDeW}Ux z|F?G@z;$2Ooqi3y5CGAL-dF&V00Dv^!Ct^Bkznr<)g?!=noHJ}Y|F81$9A09aZ#}? zQdV*V)wvEW!Ws zcmWJl&R2S2h)s|2JWH`*CdK0mS>MB!`LpQu2wo*&O7i18#uqVIOp4`l@daloxLB_00QK~TIX{aW-Xwh2ciQU6A$6?!CA9&+ws{v3 z&s`F6se3*By>O{&=4mUUcPE?L(S&*e;alUx7wwvlf5~x4TKD3MKY7!pO}q7(@N0sb z;qveBfM?0OU3=z?yneU){yU!fL-8x}h4?J}sF+xLqhqmNY!S8&%cyZePo!8cIjj-w z5lPz+e<|m&X{**#%j={gNf55A?!l*yz-Vj*n!ZH)3f%V1S}kTrh=@8@Hzd#w0! zuHkI%8u%p!X581^K9@(COiHDez@DXOq~-8v1wJ^>S$=-RD6g5srARZ4WE0OHdlD0u zFum^-Y|4R6Vs#066stFu z>qj%qzTnsHdJ12QOVzVZTQUC58Fz#lSMpQ%HlJRdn?CnrcTSz=f{z>5{$Fmm@gZXS zp*p6(CO*L7@;mi_bfscm<-=90(THXC)qN$Z$NnyBhWI9d4$91Xr03Ia+QH9Yk^cXR zO{y8w*PC{bbB0ZdKg6b7v8g>`Q^WL=*2=nRn|<0^U{rnYajRrTKruCrxts}?D%)p? zLdA8gO|4O_SEnhYE6_ObDdN%s*84)@q(!X#0cW}`PGvGm8tc9J$yaI zxaShgk28lUt70E#gx~M>FT^Fy1iAUhk`1sE#0xX31i`Xl}N0A0@08{+BOa{h;d!)oc{8NqHxJ*EVjyHG@se@Fk`w z<}B~Zu45*x)HeH+jh}nk#?3ix%`;9~O*eaZ?AI4?He7av;<^_tuIKV`-4LJdHYUKX|XA>uw+j--sAEYjMoIgwDH=q9WpAQZU zeCT@R`1pm(2iyZbuG7AyYB1g{=akNef1m&7cfbk$pXabZn-Tt`lIY~PF4Gj)dJ zk+`J!4m=in)Bg!J@&8(RTjIJL@<~M#j=-ijVbclr@lIR2*4Mn#+$Q(rw9`>5Za#!| z;w+QWy_P5-u9JR9vR(645c9L%LY|71D0uPoBnOHTFQ@X#`RPS{y-IYp- zZ~A@lPLC^nw9GL_?C~rrD;s3i=W1tSlQ9#si*B$~mc4Y~&2g zRebN&Xiw{V5u1|aM8t}G){V}(CDzEMPk+t&t5{>hy(_9ISh@N#a!dyupOQ_7ExYA4 z>cEd!IdhciryX}Z>X`qwOInS9co z-3GMNe5ajKsfCU~;!=M8QrMsvE3$$DF-5VLVz7u+o>x8&6oWj6&SlXGW_g|mbIwN> zt%5;=oO89Bcxa7PR?4X5s#xpTBwiI2o$q42bGeimEAHU+D~@{{gGu62BF!b8(_C4kEIPtOOoL~M2yZE2c z>t>Q_F6qF)>Q^qg^igpsxqM{X!S>ly9am(Kp&vYN%x1?kxv1-I3aj2?lE&2X+^yjP}GJP#R ziB;m37$$x7+qrZNuUl-@d%)sYg7@V1L3y8gzdB2}9N)o~1Tzq_$YmE$^I1;p+kmeo zoOcGDL=Jq-J2r9UJFx1lA-$B_uHI_&lH<}|+i}@rHhso?UR#l~_V!7C{pmmaDLKXq zJePuI`n_D5ANd!h&!x{f`8ua@d{2G90~mAW%E>u>mvwX->*%g?V-Ef=Z@Tb1Fe1*n z%yVo~o>gZWEL=m(!o0|Ya=6WhEuWs*vPnm+cIq)}BlZxJrYt_=Y|;YalvyXN4((Jv zLE34*<&e8g7XO?*J96TRC#5Z-^=(}7`FXjenBQ_0LUEM~0w%+kdToT8Ixun`l)jLHs z4N+dpYo?od?Ykorlirg{Fki7)16;yqdDK{xp*3sgog$Wd+wo{Jx~UyTH4lvB5_+iy zy#(7fUht^RohRN#T%srIAHMK~d+Vo7yDQ|r`EZBJ@3jYfT&Fsxk+lT#_@3grzl`S8 zicNRI2-cM1j-j}2ugzK(&AaEmF5jfuaItE`4(?B`Btd>Vg?7rLZ?=T_lQpoZb>>N% zIRCVD6N~gL5ue_+4%S}t^kY_ywkqMQf&AK+EsJ^GiNfbBo&%dwut^$2Yuc~z*sV@G zDK9QQ<>U;w7*5*9v#FwD5RR;dH)2j?W5%pS|40X|8^NHB^n-6?FKZJuq?@UU*y2pL z^}YIfacSLITq-P7oq+o0)Tw0QXD-LY{wDsao=x4wz-i_#5d*^{T{kT{O^iq1bPqj=%o}!ksfHRTxOCxVyKL5M zak|j42~GQtpZUz4T}zkV8|o|hpoYuuy$8f5AJ_R>0?p{1h^c=?aoyw5j1sYle0btP zVl38D9(>ZdZKZpxq-BpSTd|e37jtLlsOMU@H*BXj1UAL%#ioOn+j^Kfg4eAYZPe0# zf|xF1Q!jblsq8OxE_#bNkhrDy4XfaOMa)jhWhQQlvrZBPtX<`al`r<1!>@H_3B=>` z&?@ucL&PV=cH)!tk!O>5R9m|a9kd?CY)CU`BMjOEf5f59)R1oBJ!~B^eJwtTOVUqb zS!LyF_qcj|#e>RYDR(6<`F*}&F3B%%1U!d?=6!{^#{m(AGRELqa0HO zzG}c%ZAzOwesj(F z=RX>_#0N86J}@50jO#MzIr$p#kHuo$zi~akF6YEL%OWp5w3kFqoPD58+rHp<#5!Od zH@e&FxBMY&qAo{k4IPlf`YGm|lgh3)tZBw^>zIGa>85GR&sZO4r}dzrq@`Nx=EqD52ZCxfC%;T#77W(q_k`VXd^r#e~XXDL19uyYlL)Rgi8|U4yR;jrQbjO20PG zC9XB6&vA+Okb@r!VEm}(BfV7hlJi#rKV^-lo}%*&Du17w&Rj!S27dmH&gT;~~;sh=7f70X32oxU%P zC9Nf$q`Z}KSe{AJO1^$dOgfuOTX_F>rnw|;N-vGzlHNzAUP^N*j*qg~Gsv4vk58}m zTXk7oH;Lbdq@j$E}E3j2!ZEN$xK$rKtD5_7e{>yS>M8NpZF2CT`t&?RPhC zen@+A(#QH+hfDCl2gL)Kah>0<^E1RXr*{dq%k}L`H!0_oq+U?k$;EZ-E0w-rQ|9cp z@#EValXNBozhh&^O|Y(o=mKVLC#Va^V$Z2y>|tgPyl!<<-z0uJVO``<`pBL1Q%5+1 zJW4OQ-cI6`u``d87e7i~{1CC-e#@=iOU={I;S-OSjdoJrOBzIL-o;B|fb6SqLN(ah zzwElR)jg>mGphYO zn@NK_KXI&k9qHGj*B9q@f@?878@-f=@AN)O&`UbYrCNH4cntp}$5IPMPOgYpZ8QuT zGl%_w`H@w#S5P+Xm=$&&J&Q{Pjr;6VpSg#+$_d1n1#WJl>hqT@S^w0fmp%|`1wJS% zF}%)q^MH@*REJrNX%=QH){V`_b}+X0pQ2e#uql2I>&(X_%9T7%z2pnjIjNr{Mt-K* zU8`1n^)~kQn4z6u-!0XM25LQIr5&$ZP0t(F27e}_1*VZh5u0YRA1*%i5W7r7E3}Xo zujyiMj~Q+*wyW4<$x+01`TrW9cEYD^XKAP?4;AUCf`TRFhnKl{Ppm2_QO&@x>3ga} zP|iv`Qf)#MyDiLM(tO_IytJ+0S~0C^yy-i129G?Gk}%2bA;8o;^peixEJ1IUEAJg~ zN#`Xb*el2;ca%@eTLObB@y{6eEt7sK?WK8#UpuRZlr$Ei;b6pp$5& zw_wv5o6WxXtW{@h`gv~?>zyXHJ3(ys2K#oeSxMUg%ddNhewG*D6S1A1R~p3Wr?fT^ z3x?PrMtluEt;FV{qvkmsrCgNfRBrA7+!=6jpJG3mzE-YE@u2Rf`%8aC`6Sh%XEJF6 z&+!#3lSw?UUWeln*YZ;q8ZTGAf=k8n6?zHI#>T*lG#zLB@jF`8g zpFYEx^v>a@lBsW4{^TPWTzbh`dtb1tul*)mEkO^Ca(krWQg?UXuW!8ZZvM~A4>e4D zAj9PY?*Zi_lrQx?EIQ+$4eP-cU|*qLk9BxE>yDh0_Uqi5OUEZ@rkg2yoo~*i^LF3gO%XIbwOp0giruN|pUgwh*FNCFNzE~N0iJbLFE+yeo zHnE&EQ!(*w>9mMX(n`hM%rqtr&Kk>X&}Q})$iMY2eA>3}_@s;BnC)uQr%xwW*2pQYs2DoyGUz2fh~e^q_CTg~Qchg6dcAg1J%O~--@4vkvB|}CXad%r*8{oL z&)MMGt5~x!S5u?wiIcjmeGXcI_#?r&CD~2;$vGXg(d4=7rXF?dnKE$7rjv7;jb@rl zz4IJQI!bzK(gON|(GGPz^t-gP&)57)nos1O9G}o4dJS;EX%un6Gh!q=98W&Y>sz1Z z&0NPT>8fEH$)e@l|3d7u7@F~%$An8fUp#?{N2$jwk-ggzxsO`{CM61g#w^cgn1%kl z#mOzjbxuMpdWjfUdMT#8e{ygs_Ahg&iO=tnZh}w5yt0B$W`cGw7X_as$h*Zk_jCFB zUDRxBV;?f#&GGB+?{_(-i4(j3>bmRiE-Eh{nyDMO#D_3kKJXsU=h$nfJZ`H_T-r%9 z=e&0MaWvD($91erAFrf!!N%=>$~un|4@EJZu2*k`Wob60Sd)3^pOW^&XvBaTOj zUDh+q%6r~YoGF!rNeQ@;Xh1{47=q`rip1PNua`$QBzQcUlPyT7I%Ri+!J3LYJ zbQC-3wPf*{)R*iSmFClXGHN8V&iy(be;D4vBJ`1C5j;v}J!+}!$1DYpvfxoRJjyP5 z(sD|EX1Qh0T5iR2)Q$e!a>nejY{j9(wW+38IDeg(jJP%iZ(?n*3C$F-iI|N&f*g31 zD<(-RQQwtprLLYcUt0T~x2vxC6ZRL&o#`B9#c}Fk95-&_-(Gk9PPp`qz@-n}k_>Ms z?SYZn$=6~k@1#AudDz2Ie51JT#}NY*Pf52(zo28b?~wi&X4BmHtE_S|GX-E%Lba5{ zb%kSJWft#Y=E@zl@pF#Zl!24zq_=DiJQAB^(of2b_pMOh-7uf(dS17Rjzi?1USZzT zKI#izAP4oF(P>KNcpPTLVN@JF6Hme?bWRM$oMYs%<8hhz6ImkhFbsNR$dai? zESVCEc3D==F3Zk)4BKtFg-=*6JjyTqnH7wF#tJK+v%>11TVd^sR#?B6IiCACLq;s# z&#Z3FfrCd$W-}zn8+k6ps2PZ(o08PQE3V5zCuNb3OK~5^G5ob+<1Smf{z@0aX%AFd zsi&vM<-pt8Cj9s7uK#gWW#yLxm-x_y%ZJ(nBej!eV%B5rnChKYQeyBwquyWk>y#5$ z90dzvz!2#3$uNR&0c0ifLGDS;Qy#tkqKDvl`;GwwZ5GOK`&amY;Sx zCuybyYu|xSito!%*Es>z3#<%C?niPgxQz zlguOUlcO9EmPPD^-buijA%j7lJ&r%pLzozp#qVY3K4v+vD7WBoSoFB%7e8qQB~Mvl z+0#~B@r;eCdd^B}er~1pFIs8iUMp>W$x7Q^v68X-t$5r4YE56|9EXFJg9ggd-oJDb z*V0Ro!KQJt==+b1ydkY;M9X503O!D26-Ph=)zq$T~AC0c9 z{Y>BzAIxz1(0d?LJNZ33)jPFdUDzD#t|;#Wo0JnL#)+}+W8{Bh1y9jq^0aN<_K6`j zaerI4nYa!%#p~#gBj+M5Q9S-ttK!_ZroN-ZY{!V}PO?X*xbBQ&(?~u|M_2U_-%VO@ zf*krW_j@(Og%uqKse$70nqES$>|rMM3zk<&&DH2;f$R@wDxB z`bQclhwnN5z@R+tmtQP<(hA{FQQ6O|c=Xd&Qu&OPlJ768dEUw!Ua*SBJyzMW&nnwq zva0c~SS6gS>_88q>B`twEWwJ1&GN~uXxenWEy-`0?YNe(LO;_Se^5yR)pg_=dnGK49VUk?}yLc2WhZmyH!I>k$9kr>(}M(!m>9(ZuWozzv29^%vV{sC*~p>C4gOQN1SC2}u? zV-MKqiHF#Od)>y(deg;q(^o{=Nt$Wlx?ec+`bqgG#eK?6b&@}yFy}Zq@;9tuDz%(l zhplSjK`Vz3Wo<88Nz*d)(W;yGS`AvJX533wM=wrY#{sLG^s3cOK4^73zc^Vf zR(4V^+DX3+dy$3g{pS&(sh#}%6wSqK#5AKoGsQp0`LFZ< z--UL%Kh3A%*e<{7XSR9kjYDiwuie^he@7Ep z^}3w+Tjatc?d16+4dwIW{p8H25&tR1lZKi=zN)RC{^4mytiI``9(NIIW}^Sc=`mq-oQpx%{_SwRGwFw=TWxZhDK{ zxhUFK)!!;yf(JfI9`Jn9SuDP$Kr_W#F(2E#=JwhZ*J&Tj#dc^X#dhSRmks`iUW(cw zKCN7RrR6s5aWy(g_>@DQxQKjA#pJ`(R~~VUnX*VZ@zdnQ-*)*X&n8{F7!O9xgL(tshKc(zt~>T~ zj^zG`J(D@BnESNCpSJFUHg4)68$a!^P3U{gCQN_bCd}Y9_8+wgGpWnsImXUp)(g6= z39F-ieT-(i^c=NP*i=ky=@6IFv7ERR_jz!ymEh8t-hFn}b+?gMn(pdWRTI$H*XOu2 zWy%zKYl@v-+Pd}QudZGD6S#DR^pgHQflD|cTt1Q>&}U!k!1uEF*lrx(n~H6S#rpms z7W)xwdT3ZXQG2M^F01S*yWpamhuAcFbUEj;5Cf*QQx@7OAMF(7#9wpq*?VcHMeC#Z zPK=tL)=+cEODR7kMoC90*3*8U;=Re}sfndq(SO7y z&OBn1W*xQ3v&qe4opaxej9ggf{9`tm$J1lB&pqb$7Tc8b>VMPfroV|^dc(@;O)fz% zDUNeoQf(4i$>qPvF~yxuO2=<7si1woZNBVY>Qygw_1)StP>-&U;dEPCNi&$Py6Tpn zELe0Oe}|zN-+@bf0K?@Y>j8cKeLbe~;+l=A*iQB09atas-DpMuwNBcjce$tG*ltSy z{nQH19pclP4cA*Xc_7s{r^q|yI_-2|NIOaQNIOk;dv?-JXNK}l;*)38f_3cU4KXUJ zg;KA}40`dDGZ(9RmqxtmS$xuD-HT2P8#=3puf0tjIAOA0?&oc)|2=ru#cOifjF|xA z>9c8tOO5@3U%H`iVF?N9ag{xooj4_mkd4`g`2^U23{s(I4BT{AWbQ%&aU zZl*YOLg&PG?Au*%(Vw_=#{HN%Qf32AJ8{Mn^_WgOv1eD>PHdCTJ4u^NC709>W3*@I z^WvUO?s@|{3Ra0x5vQVhP2cmPyt!(l#4BklnetS_rvBoz@jSXM{Uw`DJyjn$dBux8 z@NJ6nTFg&shf8DOQuC~1R!{$JHB8FXO3Ha_KQ0B6lBxx8S_vMdnWVhZ)aB1Im-0`o zwQW2-#X0F(fMKoF+1cr0IQ?wu)Y<=d<&{5JQd6@N-%s_qrJ$GiAcaftK-vRZ4?ead z-w`Xt)X$>alV;FS^VIX-VzGNOwA1juU1{ADwsre(UVO#MD{RzQYB8mqly_p!u82Lm za`M;Ovr`_Y6J0ZHnQFx&J}K9vcy1)07Nr>_PDQLz%!j$y4_--IVRK!r)bO=>_GDt1 z;~3X7mBWHxs`c!}y5UkMy?!0)Ii7dIT4vFAj8+;mEuB~L`EJ#7t42UfB5q5h>jB)} z8#+l$YMlA9U3uLd);~-0Rd z2Z9GOJm9sH<`ih(&es*xa9cIwtfAPIvDkKIJV`rc#CGZ2)AYIb*wo%Aw$s{MxAoi1 zE~3XQ-OrInY&Xi)I~}q{_Pn(B)}?w(w9BlOXX~f47zLZer(ydgjPfR3l{VPrc*WNd ztA3GY6Se1Xsb8~M;8O2$&!p3iN#oHFp^4qFW z%4AXjbp~55e~@~w>zqasmo&FnId1Vt*4^FByt^`|qx7?@um1Aso~id!vvI5Z?e!8j z!zFkic;H<;Fp^K2RiK)2)jf^H)YJ0KSnQ7?Hi=K#x67y*U$gOh)QdN`+*4;4_06;B zQDc^D5<7cWq3H$k!8Va{7Q%KQR)S;+H7*&lYMJbG(#c3CX+8@~a{F)Oxm6c1#3X8!vZ?h>sRu>#x>d`qJ~=d! zESs9})jJ-w3&<&nJL-8ZEiH9tvU?`!T61&7YQ=B^11oLow%Z@d&3lOXejk@k4P3$r z;SxOXZ}31SpL}jyvs5(0S9^Ej)8kR@Nxf^nt{}>dC#lWeamhDa9~k#D<;6?KK5q&5 zlp^<(Lr-fVy)2`t^R7|uX~r<06yGWTG@H0fIVjaSDGwzRt9;(c=g3`LM{KA2DW3E3 zo6|_-pftZu8mR~Fb;*I%x!xTz^Rhlalat z>E@^Ga&k(IO>K@zn*F9Z#p=!VTvA?1^WdbTR8x7y6`!+7lXreUmUsZax|wi+OMFPe zC3xU{c);_?=f<^nm&qsQsbsz2W*zz1&euKBbC+BCgk5_1S6ttPw8XX@UttbEXV9hj zl-u;O6*1#-w0iB}lk}6~JLR9W*Cq|6e6@6x<~^x5*qiE}R97I&%!MoeJ(Ndc|4#XB z$0KSDl;0jV_c(FeF>8QFHS``=QKK{(ja0(C%_90v@|jug`r*(>Da{2yCk-)4GnlBG zj5qIxgS+jDtG~va^mfN2=_U2RiAmlxKR_&!PEviqs=!#<=H`;yY>!s;SFV&3HQZ`Y6!H? z7S%k#B4RboG3ey?CaR8{eZaBQ0JNZw8sU-ZCacLKRZNL`O^Q1XTOmDgdE><-&OPx= zB34T<-zCnR6YH;)d$@56p%6Yf6v^XA#$-TXE?BYwl zX*IP!Jrj%nlv=UxXXcjV-*5>Y2p)L<9(XrCNk94glk(%ej4#+9)n%T`r@XSqZQF%k za&b*Lv+XLyBh4eH_pJyf<-?;~c$D47d7s2; zIx`@Fsi#D<0b-g9hh_2F7H@dOF1hl{*4fqLbdqY4)Mp|Nc@vkUofN-`NzBZ(OE3F6 zHQ*2Y25#RLOWdd2QYM$)|6e2gM({xJK&A&q^2z6)#3$|FwP5IhhP~(LC*{ZK3(hLq zZR<9EgIb?1EnEIzG<~`MRzvg;-73-&(2=eK}4cX`ab&4EW* z@F;~g((I&!cqA5SelD{CWcg!XwpH66unRB!Jo9i{o%U;Hrjq6acpmv{%?wbkNla>Q z@3PA-|EkTJb3gN>9{y{%w2AY6eGC_JOPQana65S5Kkk8d z`HpnLaEzz91)5Ju4r;;TJ8WR_2Idx2*wzcbY-P>N*Dn9LrK(@FY&2A!G?Z!#U{o1( z1{KUMsGOnBy%D)yX((K>LQx`)tABBX+^1-!RSY)Ly^pj}*6gCi&}0lP1w$QseHU z_-$}-hh22>x2%04?>Cycxi=PnklB291g*q}AzXq7{y%y^jPiV9{l!#2t{k~yJg=e7 zi^VQI6^s33m`{H86SL_wM|bx8A5cU7X`3^5z_#!BV{4lD1ZR}MsPgDcfNb{kvK8+! zD_k*Op8AD}`<%fn&A?S1r!1Fx^Bnk-O>KgDV^Xjug$7H~$EP_h30S9jQkr?^j2`49 zkJ~k$`7RgVX&W|wf-|j}+@7M&SJE6@&mvtbkK}n2<+o?qg*!fH>o?qH71eMzV$vy? zw2D1AnB5k%5+8E^F~dMG zYR{16(0klB@R)79;5+c>Q`RxD+vSLKPC$Em`w)*5uPKi6eYo0_8#}h$Hg3AnwlJHj zV>0u`6|0I#iHF6ci(|?AnJ?2XCWTtc-@ykmJZ11eh6j9%r?sdxDGjChPuj;*9;y-( zqn5^E*Bl(`!ON^QaJeYXRANqd&-8n3uDJ3RTfh0+HmUCsOEIfb=O&0% z&Nyo+fwoefN)~rU&mQM&#)%7KeC;i-?s?{-JY}ml-(?%Ne$B;@&CO#?XIH7_NcBhR zDG`g*Pommw#d4}iQoJ^2?n>LVcJuKJ>_-S{mVSn(t4n|q&4nEDv=a-X#7wx_Il@{`sv?Fs9ijRsqJ zH#362Z-eW+0%qbx6`o1qB7}tlR|)*Vu+lpW?ay z*p{7lm(?`DA@S4mDDlYOlSlg@^#IdjS$Fu@EmJ22CgJFC2_E=8@<1k|q#;zRnaL={ zdaBvf%#{_f*k|sEC4TgGZcd$Jl&_1*

Kx6+UJioe$XggWrZTx7a4~LYp^VZYx&~ z+M-2Et$*eM>L91FUpCfhAkA#!@y{{MY^$xUb^RpLNb}|`rAGTwm+#ts;jPRR{;tiM zcb`?&!bdUkY##kHG3l$Z_yZq{C3cciyE-rlCx=V$zz56&Vw5zL&y{;dDb`ayN;z}I zd*T%5O-;HW7W>+LvBX_}Gt4RFaKtFjDQOpJs>r0P#<3?hd*1D6oA27n)!)LtZYu}B zf_(w|EOxWIJ-FspbkH}bt@<-twfdX3Wch8@)AtjrYkJgj3e%74IW(+|lta=!<5Rq* zt73_Jc%8S3M|v;fu77`?$9yYXf(L>JJ^&u@Yu0lrGan@_x`fK-*MMz{`tp^KdgNH0dm@3g+)ta zsXKXH7m?p@@;n+Dx9PowOYlJOzz5d@o>M*_<#STXn|n?vH>EmGu}ZTxVO23Xs_MD1 z*iARY61Uw!EJe-G{r?#q^Do1Deu@Lrv7l$nZ@Z4_LB*h7@;J|9--;#fy&{&}Ig9f_ zdCmG5=;H*mRR!kt7C~D+)PaP#dopm$!T55_b-Sgf4C?XyS>6=Mx=7EP zsf_}Ua7efW4}63@;92E!H<_%;r6p|GSwC8p)x+qVO3E9ta+IKOV^B)w|u!WSGDG zZuiUl-urp}aNpp8;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q z;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q z;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q e;DO+Q;DO+Q;DO+Q;DO+Q;DO+Q;DLX;2mUXkcAf(O literal 0 HcmV?d00001 diff --git a/test/sys-script.py b/test/sys-script.py new file mode 100755 index 00000000..a5111260 --- /dev/null +++ b/test/sys-script.py @@ -0,0 +1,16850 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ +# +# sys-script.py +# +# © 2017 Canonical Ltd. +# Author: Dan Streetman + +import os, sys +import shutil + +def d(path, mode): + os.mkdir(path, mode) + +def l(path, src): + os.symlink(src, path) + +def f(path, mode, contents): + with open(path, "wb") as f: + f.write(contents) + os.chmod(path, mode) + +if len(sys.argv) < 2: + exit("Usage: {} ".format(sys.argv[0])) + +if not os.path.isdir(sys.argv[1]): + exit("Target dir {} not found".format(sys.argv[1])) + +os.chdir(sys.argv[1]) + +if os.path.exists('sys'): + shutil.rmtree('sys') +d('sys', 0o755) +d('sys/kernel', 0o775) +f('sys/kernel/kexec_crash_loaded', 0o664, b'0\n') +f('sys/kernel/kexec_loaded', 0o664, b'0\n') +f('sys/kernel/uevent_helper', 0o664, b'\n') +f('sys/kernel/vmcoreinfo', 0o664, b'f15380 1000\n') +f('sys/kernel/notes', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00Z\r!\x804\xc2\x8atA<"f5(\xe7m\xe8-i-') +f('sys/kernel/uevent_seqnum', 0o664, b'1407\n') +d('sys/kernel/slab', 0o775) +d('sys/kernel/slab/kmalloc-96', 0o775) +f('sys/kernel/slab/kmalloc-96/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-96/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-96/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-96/slab_size', 0o664, b'168\n') +f('sys/kernel/slab/kmalloc-96/total_objects', 0o664, b'768\n') +f('sys/kernel/slab/kmalloc-96/slabs', 0o664, b'32\n') +f('sys/kernel/slab/kmalloc-96/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-96/alloc_calls', 0o664, b''' 5 sched_create_group+0x1f/0x220 age=8351870/8359354/8366881 pid=1333-2177 cpus=0-1 + 10 __register_sysctl_paths+0x56/0x340 age=8370387/8378535/8379888 pid=1-901 cpus=0-1 + 15 __create_workqueue_key+0x31/0x290 age=8370409/8377818/8380009 pid=1-900 cpus=0-1 + 59 load_module+0x19c0/0x1b30 age=8303111/8368469/8376350 pid=105-2754 cpus=0-1 + 5 __vmalloc_area_node+0xfb/0x140 age=8355400/8371519/8376226 pid=147-1813 cpus=0 + 22 __register_chrdev_region+0x2d/0x1a0 age=8309177/8375269/8380004 pid=1-2711 cpus=0-1 + 1 do_sys_poll+0xdb/0x450 age=9671 pid=2262 cpus=1 + 98 d_alloc+0x19d/0x1f0 age=22395/7516545/8376320 pid=317-13453 cpus=0-1 + 8 sys_eventfd2+0x51/0xb0 age=8339333/8339377/8339421 pid=2400 cpus=0 + 1 mb_cache_create+0x62/0x1f0 age=8379846 pid=1 cpus=1 + 9 sysfs_setattr+0x19a/0x1f0 age=61999/6511912/8377277 pid=63-13308 cpus=0-1 + 1 sysfs_open_file+0x1c5/0x230 age=0 pid=13466 cpus=0 + 17 copy_semundo+0x71/0xc0 age=3847042/8077586/8366263 pid=1370-2590 cpus=0-1 + 2 __crypto_alloc_tfm+0x43/0x1b0 age=8373678/8373678/8373678 pid=126 cpus=1 + 2 pcim_iomap_table+0x45/0x60 age=8379289/8379547/8379805 pid=1 cpus=0-1 + 26 pci_create_attr+0x3d/0x140 age=8378994/8378994/8378995 pid=1 cpus=0 + 8 pci_enable_msi+0xb1/0x2b0 age=8356336/8373963/8379844 pid=1-1541 cpus=0-1 + 1 fb_add_videomode+0x89/0xf0 age=8379841 pid=1 cpus=1 + 1 soft_cursor+0x92/0x220 age=8379841 pid=1 cpus=1 + 20 acpi_os_create_semaphore+0x36/0xaa age=8379969/8380118/8380142 pid=0-1 cpus=0 + 6 acpi_ds_build_internal_package_obj+0xaf/0x1df age=8379981/8379985/8379993 pid=1 cpus=0 + 2 acpi_ds_build_internal_buffer_obj+0xe1/0x121 age=8379986/8379986/8379987 pid=1 cpus=0 + 1 acpi_ev_create_gpe_block+0x5f/0x3bf age=8379999 pid=1 cpus=0 + 62 pnp_new_resource+0x25/0x60 age=8379891/8379894/8379895 pid=1 cpus=0 + 1 tty_register_driver+0x1b3/0x2a0 age=8379806 pid=1 cpus=1 + 5 kbd_connect+0x4e/0xe0 age=8374352/8375743/8379035 pid=17-341 cpus=0-1 + 17 __class_create+0x3d/0xa0 age=8374616/8377737/8380008 pid=1-215 cpus=0-1 + 2 scsi_probe_and_add_lun+0x65e/0xd80 age=8379084/8379252/8379421 pid=1 cpus=0-1 + 3 inet_rtm_newaddr+0xdb/0x220 age=8325560/8353789/8367912 pid=1197-1541 cpus=0-1 + 2 cache_add_dev+0x7c/0x546 age=8379855/8379855/8379856 pid=1 cpus=0 + 22 kernel_param_sysfs_setup+0x2f/0xc9 age=8380005/8380005/8380005 pid=1 cpus=0 + 15 acpi_system_init+0x12e/0x260 age=8379898/8379898/8379899 pid=1 cpus=0 + 1 pci_mmcfg_insert_resources+0x5d/0x123 age=8378994 pid=1 cpus=0 + 1 0xffffffffa0065104 age=8356008 pid=1766 cpus=0 + 1 bitmap_create+0x373/0xad0 [md_mod] age=8370145 pid=916 cpus=0 + 256 r1bio_pool_alloc+0x2f/0x60 [raid1] age=8370154/8370154/8370154 pid=916 cpus=0 + 8 ip6addrlbl_add+0x75/0x330 [ipv6] age=8360215/8360215/8360215 pid=1549 cpus=0 + 1 ip6_route_net_init+0x22/0xd0 [ipv6] age=8360216 pid=1549 cpus=0 + 6 snd_mixer_oss_build_input+0x431/0x5c0 [snd_mixer_oss] age=8355594/8355594/8355595 pid=1813 cpus=0 +''') +f('sys/kernel/slab/kmalloc-96/objs_per_slab', 0o664, b'24\n') +f('sys/kernel/slab/kmalloc-96/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-96/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-96/object_size', 0o664, b'96\n') +f('sys/kernel/slab/kmalloc-96/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-96/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-96/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-96/objects_partial', 0o664, b'95\n') +f('sys/kernel/slab/kmalloc-96/objects', 0o664, b'743\n') +f('sys/kernel/slab/kmalloc-96/order', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-96/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-96/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-96/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-96/partial', 0o664, b'5\n') +f('sys/kernel/slab/kmalloc-96/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-96/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-96/free_calls', 0o664, b''' 507 age=4303047439 pid=0 cpus=0 + 1 free_notes_attrs+0x4b/0x50 age=8375086 pid=383 cpus=0 + 1 audit_send_list+0x88/0xa0 age=8361087 pid=1538 cpus=1 + 6 __vunmap+0xe9/0x120 age=8309178/8363011/8375091 pid=126-2711 cpus=0-1 + 1 do_sys_poll+0x32b/0x450 age=9672 pid=2262 cpus=1 + 30 d_callback+0x22/0x40 age=22587/7808930/8375651 pid=0-13433 cpus=0-1 + 20 sysfs_release+0x63/0xa0 age=22407/6699376/8376561 pid=165-13453 cpus=0-1 + 1 release_sysfs_dirent+0x22/0xd0 age=8367199 pid=1309 cpus=1 + 116 free_rb_tree_fname+0x5c/0xb0 age=53501/7931736/8376455 pid=163-13373 cpus=0-1 + 7 kobject_uevent_env+0x11a/0x470 age=67088/6542620/8379296 pid=1-419 cpus=0-1 + 1 msi_free_irqs+0xad/0x110 age=8356355 pid=1541 cpus=0 + 1 acpi_os_execute_deferred+0x34/0x39 age=8379958 pid=13 cpus=1 + 1 acpi_walk_resources+0xa4/0xbd age=8379895 pid=1 cpus=0 + 1 acpi_pci_irq_add_prt+0x30b/0x324 age=8379922 pid=1 cpus=0 + 6 scsi_execute_req+0x9f/0xf0 age=8335607/8359788/8379422 pid=1-1456 cpus=0-1 + 9 netlink_destroy_callback+0x21/0x30 age=8325561/8347615/8367913 pid=1197-2527 cpus=0-1 + 12 huft_free+0x1e/0x2f age=8379857/8379857/8379857 pid=1 cpus=0 + 2 r1bio_pool_free+0x9/0x10 [raid1] age=8364428/8364431/8364434 pid=0 cpus=0 +''') +f('sys/kernel/slab/kmalloc-96/aliases', 0o664, b'0\n') +d('sys/kernel/slab/blkdev_requests', 0o775) +f('sys/kernel/slab/blkdev_requests/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_requests/ctor', 0o664, b'') +f('sys/kernel/slab/blkdev_requests/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_requests/slab_size', 0o664, b'376\n') +f('sys/kernel/slab/blkdev_requests/total_objects', 0o664, b'84\n') +f('sys/kernel/slab/blkdev_requests/slabs', 0o664, b'4\n') +f('sys/kernel/slab/blkdev_requests/poison', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_requests/alloc_calls', 0o664, b' 12 mempool_alloc_slab+0x11/0x20 age=61529/5606309/8378864 pid=1-13295 cpus=0-1\n') +f('sys/kernel/slab/blkdev_requests/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/blkdev_requests/shrink', 0o664, b'') +f('sys/kernel/slab/blkdev_requests/trace', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_requests/object_size', 0o664, b'304\n') +f('sys/kernel/slab/blkdev_requests/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_requests/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_requests/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_requests/objects_partial', 0o664, b'8\n') +f('sys/kernel/slab/blkdev_requests/objects', 0o664, b'50\n') +f('sys/kernel/slab/blkdev_requests/order', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_requests/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_requests/store_user', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_requests/align', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_requests/partial', 0o664, b'2\n') +f('sys/kernel/slab/blkdev_requests/validate', 0o664, b'') +f('sys/kernel/slab/blkdev_requests/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_requests/free_calls', 0o664, b''' 7 age=4303046881 pid=0 cpus=0 + 5 mempool_free_slab+0x12/0x20 age=63050/1742015/8378750 pid=0-1456 cpus=0 +''') +f('sys/kernel/slab/blkdev_requests/aliases', 0o664, b'0\n') +d('sys/kernel/slab/tw_sock_TCP', 0o775) +f('sys/kernel/slab/tw_sock_TCP/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCP/ctor', 0o664, b'') +f('sys/kernel/slab/tw_sock_TCP/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCP/slab_size', 0o664, b'256\n') +f('sys/kernel/slab/tw_sock_TCP/total_objects', 0o664, b'16\n') +f('sys/kernel/slab/tw_sock_TCP/slabs', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCP/poison', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCP/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/tw_sock_TCP/objs_per_slab', 0o664, b'16\n') +f('sys/kernel/slab/tw_sock_TCP/shrink', 0o664, b'') +f('sys/kernel/slab/tw_sock_TCP/trace', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCP/object_size', 0o664, b'136\n') +f('sys/kernel/slab/tw_sock_TCP/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCP/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCP/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCP/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCP/objects', 0o664, b'16\n') +f('sys/kernel/slab/tw_sock_TCP/order', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCP/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCP/store_user', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCP/align', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCP/partial', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCP/validate', 0o664, b'') +f('sys/kernel/slab/tw_sock_TCP/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCP/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/tw_sock_TCP/aliases', 0o664, b'0\n') +d('sys/kernel/slab/Acpi-Parse', 0o775) +f('sys/kernel/slab/Acpi-Parse/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Parse/ctor', 0o664, b'') +f('sys/kernel/slab/Acpi-Parse/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Parse/slab_size', 0o664, b'120\n') +f('sys/kernel/slab/Acpi-Parse/total_objects', 0o664, b'68\n') +f('sys/kernel/slab/Acpi-Parse/slabs', 0o664, b'2\n') +f('sys/kernel/slab/Acpi-Parse/poison', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Parse/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/Acpi-Parse/objs_per_slab', 0o664, b'34\n') +f('sys/kernel/slab/Acpi-Parse/shrink', 0o664, b'') +f('sys/kernel/slab/Acpi-Parse/trace', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Parse/object_size', 0o664, b'48\n') +f('sys/kernel/slab/Acpi-Parse/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Parse/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Parse/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Parse/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Parse/objects', 0o664, b'68\n') +f('sys/kernel/slab/Acpi-Parse/order', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Parse/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Parse/store_user', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Parse/align', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Parse/partial', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Parse/validate', 0o664, b'') +f('sys/kernel/slab/Acpi-Parse/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Parse/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/Acpi-Parse/aliases', 0o664, b'0\n') +d('sys/kernel/slab/sgpool-8', 0o775) +f('sys/kernel/slab/sgpool-8/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-8/ctor', 0o664, b'') +f('sys/kernel/slab/sgpool-8/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-8/slab_size', 0o664, b'384\n') +f('sys/kernel/slab/sgpool-8/total_objects', 0o664, b'42\n') +f('sys/kernel/slab/sgpool-8/slabs', 0o664, b'2\n') +f('sys/kernel/slab/sgpool-8/poison', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-8/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379297/8379297/8379297 pid=1 cpus=0\n') +f('sys/kernel/slab/sgpool-8/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/sgpool-8/shrink', 0o664, b'') +f('sys/kernel/slab/sgpool-8/trace', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-8/object_size', 0o664, b'256\n') +f('sys/kernel/slab/sgpool-8/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-8/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-8/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-8/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-8/objects', 0o664, b'42\n') +f('sys/kernel/slab/sgpool-8/order', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-8/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-8/store_user', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-8/align', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-8/partial', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-8/validate', 0o664, b'') +f('sys/kernel/slab/sgpool-8/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-8/free_calls', 0o664, b' 2 age=4303046847 pid=0 cpus=0\n') +f('sys/kernel/slab/sgpool-8/aliases', 0o664, b'0\n') +d('sys/kernel/slab/dnotify_cache', 0o775) +f('sys/kernel/slab/dnotify_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/ctor', 0o664, b'') +f('sys/kernel/slab/dnotify_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/slab_size', 0o664, b'112\n') +f('sys/kernel/slab/dnotify_cache/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/slabs', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/dnotify_cache/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/dnotify_cache/objs_per_slab', 0o664, b'36\n') +f('sys/kernel/slab/dnotify_cache/shrink', 0o664, b'') +f('sys/kernel/slab/dnotify_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/object_size', 0o664, b'40\n') +f('sys/kernel/slab/dnotify_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/objects', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/dnotify_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/dnotify_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/dnotify_cache/validate', 0o664, b'') +f('sys/kernel/slab/dnotify_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/dnotify_cache/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/dnotify_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-16', 0o775) +f('sys/kernel/slab/kmalloc-16/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-16/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-16/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-16/slab_size', 0o664, b'88\n') +f('sys/kernel/slab/kmalloc-16/total_objects', 0o664, b'2254\n') +f('sys/kernel/slab/kmalloc-16/slabs', 0o664, b'49\n') +f('sys/kernel/slab/kmalloc-16/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-16/alloc_calls', 0o664, b''' 2 arch_acpi_processor_init_pdc+0x71/0x180 age=8375737/8375768/8375799 pid=330 cpus=0 + 2 arch_acpi_processor_init_pdc+0xab/0x180 age=8375737/8375768/8375799 pid=330 cpus=0 + 5 sched_create_group+0x40/0x220 age=8351840/8359324/8366851 pid=1333-2177 cpus=0-1 + 5 sched_create_group+0x62/0x220 age=8351840/8359324/8366851 pid=1333-2177 cpus=0-1 + 2 setup_modinfo_version+0x19/0x30 age=8374630/8375434/8376238 pid=122-126 cpus=0-1 + 365 load_module+0x1ac4/0x1b30 age=8303081/8369498/8376320 pid=105-2754 cpus=0-1 + 13 mempool_create_node+0x4b/0xf0 age=8379859/8379929/8379974 pid=1 cpus=0 + 1 krealloc+0x1e/0x60 age=8375802 pid=330 cpus=0 + 4 __vmalloc_area_node+0xfb/0x140 age=8374701/8375120/8375833 pid=126-392 cpus=0 + 7 alloc_vfsmnt+0x97/0x180 age=61473/7184623/8379853 pid=1-13348 cpus=0-1 + 2 proc_symlink+0x4d/0xb0 age=8380112/8380112/8380112 pid=0 cpus=0 + 1275 sysfs_new_dirent+0x10c/0x120 age=22645/7761348/8379979 pid=1-13295 cpus=0-1 + 2 ext3_fill_super+0x691/0x1a20 age=8369671/8374021/8378371 pid=1-962 cpus=0 + 406 kvasprintf+0x55/0x90 age=22645/7760583/8380112 pid=0-13295 cpus=0-1 + 1 bit_cursor+0x223/0x6a0 age=8356170 pid=7 cpus=0 + 12 acpi_ds_build_internal_package_obj+0xaf/0x1df age=8379944/8379946/8379954 pid=1 cpus=0 + 14 acpi_ds_build_internal_buffer_obj+0xe1/0x121 age=8379945/8379955/8379961 pid=1 cpus=0 + 2 acpi_ut_copy_simple_object+0x8f/0x11c age=8375657/8375665/8375674 pid=396 cpus=0 + 5 acpi_irq_stats_init+0x1bd/0x268 age=8379969/8379969/8379969 pid=1 cpus=0 + 14 pnp_add_id+0x1e/0xe0 age=8379861/8379863/8379866 pid=1 cpus=0 + 9 reserve_range+0x39/0x130 age=8379850/8379850/8379850 pid=1 cpus=0 + 1 trackpoint_detect+0x94/0x190 age=8378732 pid=17 cpus=0 + 2 proto_register+0xf2/0x260 age=8360199/8370021/8379844 pid=1-1549 cpus=0 + 2 neigh_sysctl_register+0x1cd/0x330 age=8360183/8366975/8373768 pid=126-1549 cpus=0-1 + 1 nl_pid_hash_rehash+0x180/0x1a0 age=8361057 pid=1533 cpus=0 + 1 genl_register_family+0x1b6/0x1e0 age=8379853 pid=1 cpus=0 + 1 __devinet_sysctl_register+0xb8/0x120 age=8373768 pid=126 cpus=1 + 1 pci_acpi_scan_root+0x3f/0x230 age=8379897 pid=1 cpus=0 + 1 acpi_parse_mcfg+0x61/0x140 age=8379976 pid=1 cpus=0 + 1 pci_mmcfg_arch_init+0x26/0x129 age=8379976 pid=1 cpus=0 + 1 icmp_sk_init+0x32/0x13f age=8379826 pid=1 cpus=0 + 5 hub_probe+0x26b/0x820 [usbcore] age=8374065/8374558/8374911 pid=143-147 cpus=0-1 + 12 usb_cache_string+0x65/0xa0 [usbcore] age=22646/4900582/8374931 pid=143-419 cpus=0-1 + 1 usb_create_ep_files+0x283/0x350 [usbcore] age=8374798 pid=143 cpus=0 + 1 0xffffffffa006595f age=8360191 pid=1549 cpus=0 + 13 snd_info_create_entry+0x30/0xa0 [snd] age=8355564/8372743/8374175 pid=107-1813 cpus=0-1 + 1 snd_oss_info_register+0x40/0xc0 [snd] age=8374813 pid=107 cpus=1 + 1 async_chainiv_givencrypt+0xf9/0x110 [crypto_blkcipher] age=8374570 pid=215 cpus=0 + 1 eseqiv_alloc+0x6d/0x80 [crypto_blkcipher] age=8374570 pid=215 cpus=0 + 1 run+0xa9/0x500 [raid1] age=8370124 pid=916 cpus=0 + 1 __addrconf_sysctl_register+0xcd/0x140 [ipv6] age=8360183 pid=1549 cpus=0 +''') +f('sys/kernel/slab/kmalloc-16/objs_per_slab', 0o664, b'46\n') +f('sys/kernel/slab/kmalloc-16/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-16/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-16/object_size', 0o664, b'16\n') +f('sys/kernel/slab/kmalloc-16/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-16/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-16/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-16/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-16/objects', 0o664, b'2254\n') +f('sys/kernel/slab/kmalloc-16/order', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-16/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-16/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-16/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-16/partial', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-16/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-16/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-16/free_calls', 0o664, b''' 1912 age=4303047409 pid=0 cpus=0 + 2 free_sched_group+0x62/0x80 age=8375109/8375395/8375681 pid=0-72 cpus=0-1 + 2 free_sched_group+0x6b/0x80 age=8375109/8375395/8375681 pid=0-72 cpus=0-1 + 3 free_sect_attrs+0x2e/0x50 age=8375055/8375055/8375055 pid=383 cpus=0 + 3 __vunmap+0xe9/0x120 age=8373650/8374619/8375152 pid=181-754 cpus=0 + 7 vfs_rename+0x301/0x450 age=125333/5028818/8367033 pid=829-13249 cpus=0 + 10 bio_free_map_data+0x14/0x30 age=23581/2550049/8379364 pid=0-1738 cpus=0-1 + 10 bio_free_map_data+0x1d/0x30 age=53581/4218001/8379379 pid=0-558 cpus=0-1 + 60 remove_kevent+0x44/0x60 age=61364/3011504/8354072 pid=1547-2544 cpus=0-1 + 49 release_sysfs_dirent+0x8c/0xd0 age=7824392/8263442/8379778 pid=1-2141 cpus=0-1 + 9 kobject_release+0xe1/0x140 age=7833231/8247578/8373891 pid=419-1541 cpus=0-1 + 70 kobject_uevent_env+0x11a/0x470 age=409229/8261185/8379979 pid=1-12942 cpus=0-1 + 2 bit_cursor+0x23b/0x6a0 age=8356171/8367984/8379797 pid=1-7 cpus=0-1 + 1 acpi_ds_create_operand+0x12c/0x209 age=8379867 pid=1 cpus=0 + 2 acpi_ns_get_node+0x92/0xa1 age=8374467/8374504/8374542 pid=215 cpus=0-1 + 8 acpi_ut_delete_internal_obj+0x15f/0x16f age=8366439/8374588/8375781 pid=330-1358 cpus=0 + 16 acpi_ut_delete_internal_object_list+0x28/0x2f age=8374469/8378935/8379920 pid=1-396 cpus=0 + 2 reserve_range+0x11d/0x130 age=8379851/8379851/8379851 pid=1 cpus=0 + 3 release_firmware+0x57/0x70 age=8356214/8363521/8367182 pid=1285-1541 cpus=0-1 + 8 module_add_driver+0x66/0xd0 age=8373538/8375876/8379266 pid=1-181 cpus=0-1 + 1 power_supply_uevent+0x1a0/0x210 age=8375647 pid=7 cpus=0 + 2 get_modalias+0xd4/0x120 age=8355835/8367906/8379977 pid=1-1772 cpus=0 + 1 nl_pid_hash_rehash+0x18e/0x1a0 age=8356437 pid=1708 cpus=0 + 2 fib_hash_free+0x35/0x40 age=8367899/8367899/8367899 pid=1185 cpus=0 + 2 wireless_send_event+0x172/0x330 age=8329605/8342854/8356103 pid=1545 cpus=0-1 + 10 usb_get_configuration+0x42d/0x1480 [usbcore] age=22733/6708190/8374932 pid=143-419 cpus=0-1 +''') +f('sys/kernel/slab/kmalloc-16/aliases', 0o664, b'0\n') +d('sys/kernel/slab/filp', 0o775) +f('sys/kernel/slab/filp/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/filp/ctor', 0o664, b'') +f('sys/kernel/slab/filp/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/filp/slab_size', 0o664, b'384\n') +f('sys/kernel/slab/filp/total_objects', 0o664, b'4158\n') +f('sys/kernel/slab/filp/slabs', 0o664, b'198\n') +f('sys/kernel/slab/filp/poison', 0o664, b'1\n') +f('sys/kernel/slab/filp/alloc_calls', 0o664, b' 4081 get_empty_filp+0x44/0x1a0 age=0/7917861/8378089 pid=1-20296 cpus=0-1\n') +f('sys/kernel/slab/filp/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/filp/shrink', 0o664, b'') +f('sys/kernel/slab/filp/trace', 0o664, b'0\n') +f('sys/kernel/slab/filp/object_size', 0o664, b'288\n') +f('sys/kernel/slab/filp/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/filp/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/filp/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/filp/objects_partial', 0o664, b'685\n') +f('sys/kernel/slab/filp/objects', 0o664, b'4064\n') +f('sys/kernel/slab/filp/order', 0o664, b'1\n') +f('sys/kernel/slab/filp/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/filp/store_user', 0o664, b'1\n') +f('sys/kernel/slab/filp/align', 0o664, b'0\n') +f('sys/kernel/slab/filp/partial', 0o664, b'33\n') +f('sys/kernel/slab/filp/validate', 0o664, b'') +f('sys/kernel/slab/filp/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/filp/free_calls', 0o664, b''' 866 age=4303047162 pid=0 cpus=0 + 3217 file_free_rcu+0x16/0x20 age=10/7799670/8377025 pid=0-20296 cpus=0-1 +''') +f('sys/kernel/slab/filp/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-2048', 0o775) +f('sys/kernel/slab/kmalloc-2048/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-2048/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-2048/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-2048/slab_size', 0o664, b'2120\n') +f('sys/kernel/slab/kmalloc-2048/total_objects', 0o664, b'600\n') +f('sys/kernel/slab/kmalloc-2048/slabs', 0o664, b'40\n') +f('sys/kernel/slab/kmalloc-2048/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-2048/alloc_calls', 0o664, b''' 53 load_module+0x18d5/0x1b30 age=8303006/8368517/8376245 pid=105-2754 cpus=0-1 + 1 mempool_create_node+0x4b/0xf0 age=8370049 pid=916 cpus=0 + 20 sget+0xc4/0x460 age=61397/7958673/8380037 pid=0-13348 cpus=0-1 + 15 alloc_fdtable+0x81/0x160 age=4219/6197046/8357231 pid=1532-12336 cpus=0-1 + 2 journal_init_common+0x1a/0x130 age=8369592/8373942/8378292 pid=1-962 cpus=0 + 15 alloc_disk_node+0x1b/0x120 age=61949/7263912/8379312 pid=1-13295 cpus=0-1 + 1 pci_create_bus+0x3a/0x240 age=8379822 pid=1 cpus=0 + 21 alloc_pci_dev+0x1a/0x40 age=8379818/8379820/8379822 pid=1 cpus=0 + 1 framebuffer_alloc+0x3a/0x80 age=8379737 pid=1 cpus=1 + 74 acpi_add_single_object+0x4e/0xd3c age=8379823/8379836/8379852 pid=1 cpus=0 + 1 acpi_irq_stats_init+0xcb/0x268 age=8379894 pid=1 cpus=0 + 11 pnp_alloc_dev+0x35/0x120 age=8379786/8379789/8379791 pid=1 cpus=0 + 11 init_dev+0x12e/0x6f0 age=7217110/8250882/8378132 pid=33-2593 cpus=0-1 + 3 init_dev+0x2aa/0x6f0 age=7217110/7969221/8364310 pid=1258-2593 cpus=0-1 + 1 tty_register_driver+0x1b3/0x2a0 age=8379706 pid=1 cpus=1 + 2 tty_write+0x160/0x280 age=913316/4463710/8014104 pid=1206-3110 cpus=0 + 2 kobj_map_init+0x22/0xa0 age=8379899/8379968/8380037 pid=0-1 cpus=0 + 3 mousedev_create+0x36/0x2d0 age=53460/5603607/8378947 pid=1-419 cpus=0 + 1 atkbd_connect+0x33/0x290 age=8378940 pid=17 cpus=1 + 2 thermal_zone_device_register+0x6f/0x310 age=8374790/8374807/8374825 pid=329 cpus=0-1 + 15 sk_prot_alloc+0x83/0xb0 age=8328308/8367505/8379903 pid=1-2586 cpus=0-1 + 1 reqsk_queue_alloc+0x112/0x120 age=8356786 pid=1690 cpus=0 + 255 __netdev_alloc_skb+0x1f/0x40 age=8356300/8356301/8356303 pid=1541 cpus=0 + 10 neigh_sysctl_register+0x8d/0x330 age=8360107/8368337/8379760 pid=1-1549 cpus=0-1 + 6 __devinet_sysctl_register+0x74/0x120 age=8373573/8377097/8379760 pid=1-126 cpus=0-1 + 7 pci_add_new_bus+0x25/0x160 age=8379818/8379818/8379820 pid=1 cpus=0 + 1 i8042_create_aux_port+0x36/0x10f age=8378959 pid=1 cpus=0 + 1 i8042_probe+0x190/0x68d age=8378959 pid=1 cpus=0 + 1 netdev_init+0x32/0xc2 age=8379782 pid=1 cpus=0 + 1 netdev_init+0x66/0xc2 age=8379782 pid=1 cpus=0 + 1 fib_net_init+0x21/0x14c age=8379760 pid=1 cpus=0 + 10 usb_alloc_dev+0x36/0x2c0 [usbcore] age=22875/5876181/8374868 pid=143-419 cpus=0-1 + 2 acpi_thermal_add+0x36/0x4bb [thermal] age=8374792/8374809/8374827 pid=329 cpus=0-1 + 5 evdev_open+0xaf/0x1e0 [evdev] age=8364377/8364927/8365226 pid=1443 cpus=0-1 + 8 evdev_connect+0x54/0x1f0 [evdev] age=53452/7334685/8375002 pid=187-419 cpus=0-1 + 1 rtc_device_register+0xa4/0x260 [rtc_core] age=8374707 pid=208 cpus=0 + 1 iwl3945_bg_request_scan+0x5d3/0x660 [iwl3945] age=8356027 pid=733 cpus=0 + 1 iwl3945_pci_probe+0xd26/0x1020 [iwl3945] age=8373700 pid=126 cpus=1 + 1 patch_ad1981+0x1b/0x1d0 [snd_hda_intel] age=8374101 pid=107 cpus=1 + 1 rfkill_allocate+0x24/0xc0 [rfkill] age=8374401 pid=215 cpus=0 + 1 fuse_fill_super+0x26d/0x6d0 [fuse] age=8335736 pid=2476 cpus=0 +''') +f('sys/kernel/slab/kmalloc-2048/objs_per_slab', 0o664, b'15\n') +f('sys/kernel/slab/kmalloc-2048/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-2048/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-2048/object_size', 0o664, b'2048\n') +f('sys/kernel/slab/kmalloc-2048/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-2048/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-2048/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-2048/objects_partial', 0o664, b'59\n') +f('sys/kernel/slab/kmalloc-2048/objects', 0o664, b'584\n') +f('sys/kernel/slab/kmalloc-2048/order', 0o664, b'3\n') +f('sys/kernel/slab/kmalloc-2048/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-2048/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-2048/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-2048/partial', 0o664, b'5\n') +f('sys/kernel/slab/kmalloc-2048/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-2048/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-2048/free_calls', 0o664, b''' 424 age=4303047334 pid=0 cpus=0 + 1 __vunmap+0xe9/0x120 age=8374513 pid=107 cpus=1 + 79 free_fdtable_rcu+0x71/0xb0 age=7254/7749386/8377555 pid=0-13365 cpus=0-1 + 4 show_stat+0x50e/0x530 age=23516/2125165/8360113 pid=1258-1868 cpus=0 + 4 acpi_add_single_object+0xc9a/0xd3c age=8379824/8379831/8379839 pid=1 cpus=0 + 20 release_one_tty+0x145/0x190 age=8352386/8360775/8370275 pid=55-2136 cpus=0-1 + 1 atkbd_connect+0x1ae/0x290 age=8378923 pid=17 cpus=0 + 8 sk_free+0xcd/0x100 age=656267/7395001/8360982 pid=1533-12333 cpus=0-1 + 18 skb_release_data+0x85/0xd0 age=61516/7352252/8379750 pid=1-13343 cpus=0-1 + 5 __scm_destroy+0x41/0x50 age=7217111/8111550/8352414 pid=2135-2593 cpus=0-1 + 1 huft_build+0x163/0x63e age=8379752 pid=1 cpus=0 + 1 inflate_fixed+0x17c/0x193 age=8379752 pid=1 cpus=0 + 1 usb_release_dev+0x59/0x70 [usbcore] age=53835 pid=419 cpus=0 + 1 acpi_processor_get_throttling_info+0x2e4/0x58c [processor] age=8375644 pid=330 cpus=0 + 1 acpi_thermal_add+0x457/0x4bb [thermal] age=8374828 pid=329 cpus=1 + 1 snd_ctl_ioctl+0x2cf/0x960 [snd] age=8373099 pid=786 cpus=0 +''') +f('sys/kernel/slab/kmalloc-2048/aliases', 0o664, b'0\n') +d('sys/kernel/slab/cfq_queue', 0o775) +f('sys/kernel/slab/cfq_queue/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/cfq_queue/ctor', 0o664, b'') +f('sys/kernel/slab/cfq_queue/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/cfq_queue/slab_size', 0o664, b'208\n') +f('sys/kernel/slab/cfq_queue/total_objects', 0o664, b'95\n') +f('sys/kernel/slab/cfq_queue/slabs', 0o664, b'5\n') +f('sys/kernel/slab/cfq_queue/poison', 0o664, b'1\n') +f('sys/kernel/slab/cfq_queue/alloc_calls', 0o664, b' 67 cfq_get_queue+0xc6/0x220 age=168/7825503/8379604 pid=1-13466 cpus=0-1\n') +f('sys/kernel/slab/cfq_queue/objs_per_slab', 0o664, b'19\n') +f('sys/kernel/slab/cfq_queue/shrink', 0o664, b'') +f('sys/kernel/slab/cfq_queue/trace', 0o664, b'0\n') +f('sys/kernel/slab/cfq_queue/object_size', 0o664, b'136\n') +f('sys/kernel/slab/cfq_queue/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/cfq_queue/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/cfq_queue/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/cfq_queue/objects_partial', 0o664, b'35\n') +f('sys/kernel/slab/cfq_queue/objects', 0o664, b'92\n') +f('sys/kernel/slab/cfq_queue/order', 0o664, b'0\n') +f('sys/kernel/slab/cfq_queue/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/cfq_queue/store_user', 0o664, b'1\n') +f('sys/kernel/slab/cfq_queue/align', 0o664, b'8\n') +f('sys/kernel/slab/cfq_queue/partial', 0o664, b'2\n') +f('sys/kernel/slab/cfq_queue/validate', 0o664, b'') +f('sys/kernel/slab/cfq_queue/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/cfq_queue/free_calls', 0o664, b''' 11 age=4303047621 pid=0 cpus=0 + 56 cfq_put_queue+0x6f/0xe0 age=45755/7905388/8375272 pid=163-26529 cpus=0-1 +''') +f('sys/kernel/slab/cfq_queue/aliases', 0o664, b'0\n') +d('sys/kernel/slab/ext3_xattr', 0o775) +f('sys/kernel/slab/ext3_xattr/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/ext3_xattr/ctor', 0o664, b'') +f('sys/kernel/slab/ext3_xattr/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/ext3_xattr/slab_size', 0o664, b'160\n') +f('sys/kernel/slab/ext3_xattr/total_objects', 0o664, b'25\n') +f('sys/kernel/slab/ext3_xattr/slabs', 0o664, b'1\n') +f('sys/kernel/slab/ext3_xattr/poison', 0o664, b'1\n') +f('sys/kernel/slab/ext3_xattr/alloc_calls', 0o664, b' 4 mb_cache_entry_alloc+0x15/0x50 age=5766034/7671829/8319899 pid=2676-9046 cpus=0\n') +f('sys/kernel/slab/ext3_xattr/objs_per_slab', 0o664, b'25\n') +f('sys/kernel/slab/ext3_xattr/shrink', 0o664, b'') +f('sys/kernel/slab/ext3_xattr/trace', 0o664, b'0\n') +f('sys/kernel/slab/ext3_xattr/object_size', 0o664, b'88\n') +f('sys/kernel/slab/ext3_xattr/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/ext3_xattr/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/ext3_xattr/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/ext3_xattr/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/ext3_xattr/objects', 0o664, b'25\n') +f('sys/kernel/slab/ext3_xattr/order', 0o664, b'0\n') +f('sys/kernel/slab/ext3_xattr/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/ext3_xattr/store_user', 0o664, b'1\n') +f('sys/kernel/slab/ext3_xattr/align', 0o664, b'0\n') +f('sys/kernel/slab/ext3_xattr/partial', 0o664, b'0\n') +f('sys/kernel/slab/ext3_xattr/validate', 0o664, b'') +f('sys/kernel/slab/ext3_xattr/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/ext3_xattr/free_calls', 0o664, b' 4 age=4303047503 pid=0 cpus=0\n') +f('sys/kernel/slab/ext3_xattr/aliases', 0o664, b'0\n') +d('sys/kernel/slab/bio', 0o775) +f('sys/kernel/slab/bio/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/bio/ctor', 0o664, b'') +f('sys/kernel/slab/bio/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/bio/slab_size', 0o664, b'192\n') +f('sys/kernel/slab/bio/total_objects', 0o664, b'42\n') +f('sys/kernel/slab/bio/slabs', 0o664, b'2\n') +f('sys/kernel/slab/bio/poison', 0o664, b'1\n') +f('sys/kernel/slab/bio/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379518/8379518/8379518 pid=1 cpus=0\n') +f('sys/kernel/slab/bio/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/bio/shrink', 0o664, b'') +f('sys/kernel/slab/bio/trace', 0o664, b'0\n') +f('sys/kernel/slab/bio/object_size', 0o664, b'104\n') +f('sys/kernel/slab/bio/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/bio/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/bio/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/bio/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/bio/objects', 0o664, b'42\n') +f('sys/kernel/slab/bio/order', 0o664, b'0\n') +f('sys/kernel/slab/bio/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/bio/store_user', 0o664, b'1\n') +f('sys/kernel/slab/bio/align', 0o664, b'8\n') +f('sys/kernel/slab/bio/partial', 0o664, b'0\n') +f('sys/kernel/slab/bio/validate', 0o664, b'') +f('sys/kernel/slab/bio/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/bio/free_calls', 0o664, b' 2 age=4303046952 pid=0 cpus=0\n') +f('sys/kernel/slab/bio/aliases', 0o664, b'0\n') +d('sys/kernel/slab/TCP', 0o775) +f('sys/kernel/slab/TCP/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/TCP/ctor', 0o664, b'') +f('sys/kernel/slab/TCP/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/TCP/slab_size', 0o664, b'2304\n') +f('sys/kernel/slab/TCP/total_objects', 0o664, b'28\n') +f('sys/kernel/slab/TCP/slabs', 0o664, b'2\n') +f('sys/kernel/slab/TCP/poison', 0o664, b'1\n') +f('sys/kernel/slab/TCP/alloc_calls', 0o664, b' 3 sk_prot_alloc+0x1e/0xb0 age=926836/5879023/8356238 pid=1206-1920 cpus=0\n') +f('sys/kernel/slab/TCP/objs_per_slab', 0o664, b'14\n') +f('sys/kernel/slab/TCP/shrink', 0o664, b'') +f('sys/kernel/slab/TCP/trace', 0o664, b'0\n') +f('sys/kernel/slab/TCP/object_size', 0o664, b'2200\n') +f('sys/kernel/slab/TCP/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/TCP/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/TCP/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/TCP/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/TCP/objects', 0o664, b'28\n') +f('sys/kernel/slab/TCP/order', 0o664, b'3\n') +f('sys/kernel/slab/TCP/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/TCP/store_user', 0o664, b'1\n') +f('sys/kernel/slab/TCP/align', 0o664, b'0\n') +f('sys/kernel/slab/TCP/partial', 0o664, b'0\n') +f('sys/kernel/slab/TCP/validate', 0o664, b'') +f('sys/kernel/slab/TCP/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/TCP/free_calls', 0o664, b' 3 sk_free+0x80/0x100 age=932105/5881414/8356684 pid=0-1762 cpus=0\n') +f('sys/kernel/slab/TCP/aliases', 0o664, b'0\n') +d('sys/kernel/slab/nsproxy', 0o775) +f('sys/kernel/slab/nsproxy/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/ctor', 0o664, b'') +f('sys/kernel/slab/nsproxy/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/slab_size', 0o664, b'128\n') +f('sys/kernel/slab/nsproxy/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/slabs', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/poison', 0o664, b'1\n') +f('sys/kernel/slab/nsproxy/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/nsproxy/objs_per_slab', 0o664, b'32\n') +f('sys/kernel/slab/nsproxy/shrink', 0o664, b'') +f('sys/kernel/slab/nsproxy/trace', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/object_size', 0o664, b'56\n') +f('sys/kernel/slab/nsproxy/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/objects', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/order', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/nsproxy/store_user', 0o664, b'1\n') +f('sys/kernel/slab/nsproxy/align', 0o664, b'8\n') +f('sys/kernel/slab/nsproxy/partial', 0o664, b'0\n') +f('sys/kernel/slab/nsproxy/validate', 0o664, b'') +f('sys/kernel/slab/nsproxy/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/nsproxy/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/nsproxy/aliases', 0o664, b'0\n') +d('sys/kernel/slab/inotify_watch_cache', 0o775) +f('sys/kernel/slab/inotify_watch_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/inotify_watch_cache/ctor', 0o664, b'') +f('sys/kernel/slab/inotify_watch_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/inotify_watch_cache/slab_size', 0o664, b'144\n') +f('sys/kernel/slab/inotify_watch_cache/total_objects', 0o664, b'168\n') +f('sys/kernel/slab/inotify_watch_cache/slabs', 0o664, b'6\n') +f('sys/kernel/slab/inotify_watch_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/inotify_watch_cache/alloc_calls', 0o664, b' 126 sys_inotify_add_watch+0x15e/0x1d0 age=60497/8227702/8376765 pid=72-13355 cpus=0-1\n') +f('sys/kernel/slab/inotify_watch_cache/objs_per_slab', 0o664, b'28\n') +f('sys/kernel/slab/inotify_watch_cache/shrink', 0o664, b'') +f('sys/kernel/slab/inotify_watch_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/inotify_watch_cache/object_size', 0o664, b'72\n') +f('sys/kernel/slab/inotify_watch_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/inotify_watch_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/inotify_watch_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/inotify_watch_cache/objects_partial', 0o664, b'24\n') +f('sys/kernel/slab/inotify_watch_cache/objects', 0o664, b'164\n') +f('sys/kernel/slab/inotify_watch_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/inotify_watch_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/inotify_watch_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/inotify_watch_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/inotify_watch_cache/partial', 0o664, b'1\n') +f('sys/kernel/slab/inotify_watch_cache/validate', 0o664, b'') +f('sys/kernel/slab/inotify_watch_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/inotify_watch_cache/free_calls', 0o664, b''' 122 age=4303047477 pid=0 cpus=0 + 4 free_inotify_user_watch+0x60/0x70 age=104648/4219698/8334832 pid=2423-13211 cpus=0 +''') +f('sys/kernel/slab/inotify_watch_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/fs_cache', 0o775) +f('sys/kernel/slab/fs_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/fs_cache/ctor', 0o664, b'') +f('sys/kernel/slab/fs_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/fs_cache/slab_size', 0o664, b'192\n') +f('sys/kernel/slab/fs_cache/total_objects', 0o664, b'126\n') +f('sys/kernel/slab/fs_cache/slabs', 0o664, b'6\n') +f('sys/kernel/slab/fs_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/fs_cache/alloc_calls', 0o664, b' 79 __copy_fs_struct+0x28/0xc0 age=4126/7761540/8379883 pid=1-12336 cpus=0-1\n') +f('sys/kernel/slab/fs_cache/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/fs_cache/shrink', 0o664, b'') +f('sys/kernel/slab/fs_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/fs_cache/object_size', 0o664, b'104\n') +f('sys/kernel/slab/fs_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/fs_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/fs_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/fs_cache/objects_partial', 0o664, b'75\n') +f('sys/kernel/slab/fs_cache/objects', 0o664, b'117\n') +f('sys/kernel/slab/fs_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/fs_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/fs_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/fs_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/fs_cache/partial', 0o664, b'4\n') +f('sys/kernel/slab/fs_cache/validate', 0o664, b'') +f('sys/kernel/slab/fs_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/fs_cache/free_calls', 0o664, b''' 7 age=4303047241 pid=0 cpus=0 + 72 put_fs_struct+0x37/0x40 age=7168/7706405/8375333 pid=145-20292 cpus=0-1 +''') +f('sys/kernel/slab/fs_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-512', 0o775) +f('sys/kernel/slab/kmalloc-512/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-512/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-512/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-512/slab_size', 0o664, b'584\n') +f('sys/kernel/slab/kmalloc-512/total_objects', 0o664, b'504\n') +f('sys/kernel/slab/kmalloc-512/slabs', 0o664, b'36\n') +f('sys/kernel/slab/kmalloc-512/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-512/alloc_calls', 0o664, b''' 14 __register_sysctl_paths+0x56/0x340 age=8360125/8372514/8379788 pid=1-1549 cpus=0 + 14 param_sysfs_setup+0x87/0x140 age=8355309/8375663/8379919 pid=1-1813 cpus=0-1 + 59 module_add_modinfo_attrs+0x25/0xf0 age=8303025/8368384/8376264 pid=105-2754 cpus=0-1 + 2 __vmalloc_area_node+0xfb/0x140 age=8374650/8375296/8375942 pid=126-144 cpus=0 + 1 dma_kmalloc_cache+0xca/0x150 age=8375776 pid=163 cpus=0 + 107 kmem_cache_create+0x4e/0x2e0 age=8360130/8377702/8380056 pid=0-1549 cpus=0-1 + 2 __percpu_alloc_mask+0xbc/0x140 age=8379768/8379768/8379768 pid=1 cpus=1 + 17 sys_inotify_init1+0xaa/0x220 age=8333709/8350157/8376641 pid=72-2544 cpus=0-1 + 4 sys_epoll_create1+0x41/0x100 age=2416994/6871289/8356805 pid=1690-20296 cpus=0-1 + 2 __crypto_alloc_tfm+0x43/0x1b0 age=8373592/8373592/8373592 pid=126 cpus=1 + 1 crypto_alloc_instance+0x2b/0xe0 age=8373592 pid=745 cpus=0 + 3 elevator_alloc+0x67/0xc0 age=62000/5606780/8379335 pid=1-13295 cpus=0-1 + 3 cfq_init_queue+0x1b/0x120 age=62000/5606780/8379335 pid=1-13295 cpus=0-1 + 1 fb_alloc_cmap+0x66/0x150 age=8379756 pid=1 cpus=1 + 1 fb_alloc_cmap+0x81/0x150 age=8379756 pid=1 cpus=1 + 1 fb_alloc_cmap+0x9c/0x150 age=8379756 pid=1 cpus=1 + 1 fbcon_startup+0xd6/0x2f0 age=8379755 pid=1 cpus=1 + 1 acpi_ds_build_internal_buffer_obj+0xe1/0x121 age=8379896 pid=1 cpus=0 + 1 make_acpi_ec+0x1a/0xcb age=8379913 pid=1 cpus=0 + 1 acpi_irq_stats_init+0x83/0x268 age=8379913 pid=1 cpus=0 + 1 acpi_irq_stats_init+0xa7/0x268 age=8379913 pid=1 cpus=0 + 5 alloc_tty_driver+0x1c/0x40 age=8309091/8365595/8379725 pid=1-2711 cpus=1 + 2 vt_ioctl+0x1874/0x1c30 age=8356613/8356613/8356613 pid=1703 cpus=0 + 8 set_inverse_transl+0xa0/0xb0 age=8355024/8367389/8379755 pid=1-1898 cpus=1 + 2 con_clear_unimap+0x2a/0xd0 age=8355024/8367389/8379755 pid=1-1898 cpus=1 + 7 vc_allocate+0x99/0x1b0 age=8356563/8358748/8368241 pid=1135-1729 cpus=0-1 + 1 hpet_alloc+0x6b/0x3c0 age=8379798 pid=1 cpus=0 + 4 uart_open+0x36c/0x4b0 age=8368845/8368914/8369120 pid=1059-1073 cpus=0-1 + 43 bus_add_driver+0x4f/0x280 age=8303025/8373842/8379841 pid=1-2754 cpus=0-1 + 9 bus_register+0x35/0x290 age=8373434/8378695/8379923 pid=1-770 cpus=0-1 + 30 __class_register+0x28/0x1e0 age=8374523/8378099/8379922 pid=1-352 cpus=0-1 + 1 mousedev_open+0xc8/0x1d0 age=8354269 pid=1738 cpus=0 + 1 cpufreq_add_dev+0x8f/0x5c0 age=8366381 pid=1358 cpus=0 + 4 sock_alloc_send_skb+0x1cd/0x200 age=8330763/8342704/8350746 pid=1738 cpus=0-1 + 1 alloc_netdev_mq+0x6c/0x180 age=8373712 pid=126 cpus=1 + 4 inetdev_init+0x28/0x190 age=8373592/8375784/8379779 pid=1-126 cpus=0-1 + 2 fib_hash_table+0x1c/0x80 age=8379779/8379779/8379779 pid=1 cpus=0 + 1 ioapic_init_sysfs+0x74/0xcf age=8379769 pid=1 cpus=1 + 3 snd_malloc_sgbuf_pages+0xbe/0x1f0 [snd_page_alloc] age=8374119/8374119/8374119 pid=107 cpus=1 + 1 usb_get_configuration+0x18f/0x1480 [usbcore] age=22677 pid=419 cpus=0 + 1 usb_get_configuration+0x5f2/0x1480 [usbcore] age=8372692 pid=419 cpus=0 + 2 acpi_processor_get_throttling_info+0x21f/0x58c [processor] age=8375662/8375686/8375710 pid=330 cpus=0 + 48 snd_info_create_entry+0x1b/0xa0 [snd] age=8355304/8371157/8374867 pid=107-1813 cpus=0-1 + 4 snd_timer_new+0x40/0x190 [snd_timer] age=8374097/8374262/8374757 pid=107 cpus=1 + 2 ieee80211_key_alloc+0x37/0xe0 [mac80211] age=3544694/3544694/3544694 pid=1545 cpus=0 + 3 snd_pcm_new_stream+0x161/0x520 [snd_pcm] age=8374119/8374119/8374119 pid=107 cpus=1 + 1 snd_hda_bus_new+0x31/0xf4 [snd_hda_intel] age=8374122 pid=107 cpus=1 + 1 crypto_blkcipher_type+0x54/0xffffffffffffff8e [crypto_blkcipher] age=8374450 pid=215 cpus=0 + 1 md_import_device+0x32/0x290 [md_mod] age=8370110 pid=916 cpus=0 + 1 bitmap_create+0x5e/0xad0 [md_mod] age=8370066 pid=916 cpus=0 + 1 run+0x42/0x500 [raid1] age=8370068 pid=916 cpus=0 + 1 ip6_route_net_init+0x4d/0xd0 [ipv6] age=8360130 pid=1549 cpus=0 +''') +f('sys/kernel/slab/kmalloc-512/objs_per_slab', 0o664, b'14\n') +f('sys/kernel/slab/kmalloc-512/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-512/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-512/object_size', 0o664, b'512\n') +f('sys/kernel/slab/kmalloc-512/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-512/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-512/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-512/objects_partial', 0o664, b'79\n') +f('sys/kernel/slab/kmalloc-512/objects', 0o664, b'443\n') +f('sys/kernel/slab/kmalloc-512/order', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-512/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-512/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-512/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-512/partial', 0o664, b'10\n') +f('sys/kernel/slab/kmalloc-512/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-512/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-512/free_calls', 0o664, b''' 163 age=4303047353 pid=0 cpus=0 + 4 __vunmap+0xe9/0x120 age=8374515/8375319/8376179 pid=122-215 cpus=0 + 1 kmem_cache_shrink+0x5d/0x1b0 age=8379872 pid=1 cpus=0 + 33 load_elf_binary+0xa7e/0x1e20 age=8303117/8365402/8377217 pid=62-2754 cpus=0-1 + 19 load_elf_binary+0xc37/0x1e20 age=8355044/8370854/8376371 pid=197-1912 cpus=0-1 + 1 crypto_larval_destroy+0x2b/0x40 age=8373593 pid=126 cpus=1 + 210 skb_release_data+0x85/0xd0 age=22792/8177097/8379923 pid=1-20296 cpus=0-1 + 1 acpi_processor_get_power_info+0x2eb/0x569 [processor] age=8375661 pid=330 cpus=1 + 1 skcipher_geniv_alloc+0xea/0x3f0 [crypto_blkcipher] age=8374478 pid=215 cpus=0 + 1 snd_mixer_oss_build_input+0x402/0x5c0 [snd_mixer_oss] age=8355509 pid=1813 cpus=0 +''') +f('sys/kernel/slab/kmalloc-512/aliases', 0o664, b'0\n') +d('sys/kernel/slab/biovec-256', 0o775) +f('sys/kernel/slab/biovec-256/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/biovec-256/ctor', 0o664, b'') +f('sys/kernel/slab/biovec-256/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/biovec-256/slab_size', 0o664, b'4224\n') +f('sys/kernel/slab/biovec-256/total_objects', 0o664, b'7\n') +f('sys/kernel/slab/biovec-256/slabs', 0o664, b'1\n') +f('sys/kernel/slab/biovec-256/poison', 0o664, b'1\n') +f('sys/kernel/slab/biovec-256/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379465/8379465/8379465 pid=1 cpus=0\n') +f('sys/kernel/slab/biovec-256/objs_per_slab', 0o664, b'7\n') +f('sys/kernel/slab/biovec-256/shrink', 0o664, b'') +f('sys/kernel/slab/biovec-256/trace', 0o664, b'0\n') +f('sys/kernel/slab/biovec-256/object_size', 0o664, b'4096\n') +f('sys/kernel/slab/biovec-256/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/biovec-256/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/biovec-256/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/biovec-256/objects_partial', 0o664, b'2\n') +f('sys/kernel/slab/biovec-256/objects', 0o664, b'2\n') +f('sys/kernel/slab/biovec-256/order', 0o664, b'3\n') +f('sys/kernel/slab/biovec-256/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/biovec-256/store_user', 0o664, b'1\n') +f('sys/kernel/slab/biovec-256/align', 0o664, b'0\n') +f('sys/kernel/slab/biovec-256/partial', 0o664, b'1\n') +f('sys/kernel/slab/biovec-256/validate', 0o664, b'') +f('sys/kernel/slab/biovec-256/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/biovec-256/free_calls', 0o664, b' 2 age=4303046899 pid=0 cpus=0\n') +f('sys/kernel/slab/biovec-256/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-128', 0o775) +f('sys/kernel/slab/kmalloc-128/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-128/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-128/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-128/slab_size', 0o664, b'200\n') +f('sys/kernel/slab/kmalloc-128/total_objects', 0o664, b'360\n') +f('sys/kernel/slab/kmalloc-128/slabs', 0o664, b'18\n') +f('sys/kernel/slab/kmalloc-128/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-128/alloc_calls', 0o664, b''' 17 param_sysfs_setup+0x87/0x140 age=8366402/8376536/8379939 pid=1-1358 cpus=0-1 + 1 mempool_create_node+0x4b/0xf0 age=8379025 pid=1 cpus=0 + 4 __vmalloc_area_node+0xfb/0x140 age=8303049/8349608/8370350 pid=900-2754 cpus=0 + 2 shmem_fill_super+0x38/0x200 age=8377584/8378686/8379788 pid=1-46 cpus=0-1 + 56 __percpu_alloc_mask+0xbc/0x140 age=61988/7483637/8379799 pid=1-13295 cpus=0-1 + 11 cdev_alloc+0x1a/0x50 age=61988/7621848/8379938 pid=1-13295 cpus=0-1 + 110 d_alloc+0x19d/0x1f0 age=22451/5346628/8376065 pid=401-13439 cpus=0-1 + 2 bm_register_write+0x63/0x630 age=8354053/8354053/8354053 pid=2054 cpus=1 + 2 alloc_disk_node+0x6c/0x120 age=62016/4220683/8379351 pid=1-13295 cpus=1 + 20 ida_pre_get+0x86/0x90 age=8298034/8372144/8380076 pid=0-2761 cpus=0-1 + 5 acpi_ds_build_internal_package_obj+0xaf/0x1df age=8379905/8379914/8379918 pid=1 cpus=0 + 2 acpi_ds_build_internal_buffer_obj+0xe1/0x121 age=8379921/8379921/8379921 pid=1 cpus=0 + 1 acpi_ev_create_gpe_block+0xb2/0x3bf age=8379933 pid=1 cpus=0 + 4 acpi_add_single_object+0x5d8/0xd3c age=8379862/8379869/8379873 pid=1 cpus=0 + 41 con_insert_unipair+0xd6/0x110 age=8355044/8369520/8379775 pid=1-1898 cpus=1 + 2 thermal_zone_bind_cooling_device+0xde/0x2a0 age=8374828/8374828/8374828 pid=329 cpus=0 + 4 led_trigger_register_simple+0x2b/0x80 age=8375615/8375659/8375793 pid=392-396 cpus=0 + 1 sock_kmalloc+0x5c/0x70 age=8328344 pid=2586 cpus=0 + 3 alloc_netdev_mq+0x6c/0x180 age=8373612/8376531/8379814 pid=1-126 cpus=0-1 + 2 neigh_table_init_no_netlink+0xd2/0x250 age=8360154/8369976/8379799 pid=1-1549 cpus=0 + 8 neigh_parms_alloc+0x5d/0x110 age=8360146/8367976/8379799 pid=1-1549 cpus=0-1 + 4 fz_hash_alloc+0x4a/0x60 age=8325493/8357250/8367862 pid=1185-1541 cpus=0-1 + 1 get_local_pda+0x39/0x9b age=8380015 pid=1 cpus=0 + 1 mnt_init+0xf9/0x202 age=8380076 pid=0 cpus=0 + 1 net_ns_init+0x49/0x16d age=8379942 pid=1 cpus=0 + 3 sg_add+0x8c/0x400 [sg] age=61988/5604850/8376284 pid=169-13295 cpus=0 + 3 usb_get_configuration+0x5f2/0x1480 [usbcore] age=22696/22696/22696 pid=419 cpus=0 + 15 usb_get_configuration+0x1388/0x1480 [usbcore] age=22696/3922325/8372712 pid=419 cpus=0 + 1 0xffffffffa0065117 age=8374777 pid=107 cpus=1 + 1 ieee80211_led_init+0x1b/0x230 [mac80211] age=8373612 pid=126 cpus=1 + 1 ieee80211_led_init+0x83/0x230 [mac80211] age=8373612 pid=126 cpus=1 + 1 ieee80211_led_init+0xeb/0x230 [mac80211] age=8373611 pid=126 cpus=1 + 1 ieee80211_led_init+0x153/0x230 [mac80211] age=8373611 pid=126 cpus=1 + 1 snd_hda_codec_new+0x1ec/0x559 [snd_hda_intel] age=8374142 pid=107 cpus=1 + 1 md_register_thread+0x35/0xd0 [md_mod] age=8370088 pid=916 cpus=0 + 1 fib6_net_init+0x7e/0x130 [ipv6] age=8360149 pid=1549 cpus=0 +''') +f('sys/kernel/slab/kmalloc-128/objs_per_slab', 0o664, b'20\n') +f('sys/kernel/slab/kmalloc-128/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-128/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-128/object_size', 0o664, b'128\n') +f('sys/kernel/slab/kmalloc-128/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-128/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-128/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-128/objects_partial', 0o664, b'83\n') +f('sys/kernel/slab/kmalloc-128/objects', 0o664, b'343\n') +f('sys/kernel/slab/kmalloc-128/order', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-128/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-128/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-128/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-128/partial', 0o664, b'5\n') +f('sys/kernel/slab/kmalloc-128/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-128/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-128/free_calls', 0o664, b''' 197 age=4303047372 pid=0 cpus=0 + 3 call_usermodehelper_freeinfo+0x27/0x30 age=8360145/8367948/8373612 pid=745-1532 cpus=0 + 2 __vunmap+0xe9/0x120 age=8375480/8375882/8376284 pid=105-169 cpus=0 + 5 percpu_free+0x2d/0x60 age=7838031/7838092/7838171 pid=419-3347 cpus=0 + 1 cdev_dynamic_release+0x19/0x20 age=7838171 pid=419 cpus=0 + 49 d_callback+0x22/0x40 age=53327/5302082/8375461 pid=0-13314 cpus=0-1 + 51 load_elf_binary+0xaf/0x1e20 age=25315/7326461/8377585 pid=46-21952 cpus=0-1 + 1 free_rb_tree_fname+0x5c/0xb0 age=8366816 pid=1274 cpus=0 + 1 disk_release+0x2e/0x50 age=7838031 pid=3347 cpus=0 + 2 free_bitmap+0x29/0x80 age=8368053/8369024/8369995 pid=55 cpus=0-1 + 1 acpi_evaluate_reference+0x100/0x117 age=8374829 pid=329 cpus=0 + 6 acpi_get_object_info+0x1b6/0x1d4 age=8379736/8379841/8379873 pid=1 cpus=0-1 + 4 do_acpi_find_child+0x48/0x51 age=8379209/8379658/8379850 pid=1 cpus=0-1 + 1 unpack_to_rootfs+0x105/0xa39 age=8379790 pid=1 cpus=0 + 1 sg_remove+0x1ca/0x240 [sg] age=7838171 pid=419 cpus=0 + 6 usb_release_interface_cache+0x2c/0x60 [usbcore] age=7833192/7833192/7833192 pid=419 cpus=1 + 2 usb_release_interface_cache+0x47/0x60 [usbcore] age=7833192/7833192/7833192 pid=419 cpus=1 + 1 acpi_processor_get_throttling_info+0x15e/0x58c [processor] age=8375683 pid=330 cpus=0 +''') +f('sys/kernel/slab/kmalloc-128/aliases', 0o664, b'0\n') +d('sys/kernel/slab/ip_dst_cache', 0o775) +f('sys/kernel/slab/ip_dst_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/ip_dst_cache/ctor', 0o664, b'') +f('sys/kernel/slab/ip_dst_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/ip_dst_cache/slab_size', 0o664, b'384\n') +f('sys/kernel/slab/ip_dst_cache/total_objects', 0o664, b'42\n') +f('sys/kernel/slab/ip_dst_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/ip_dst_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/ip_dst_cache/alloc_calls', 0o664, b' 1 dst_alloc+0x2b/0x90 age=920684 pid=1206 cpus=0\n') +f('sys/kernel/slab/ip_dst_cache/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/ip_dst_cache/shrink', 0o664, b'') +f('sys/kernel/slab/ip_dst_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/ip_dst_cache/object_size', 0o664, b'312\n') +f('sys/kernel/slab/ip_dst_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/ip_dst_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/ip_dst_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/ip_dst_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/ip_dst_cache/objects', 0o664, b'42\n') +f('sys/kernel/slab/ip_dst_cache/order', 0o664, b'1\n') +f('sys/kernel/slab/ip_dst_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/ip_dst_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/ip_dst_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/ip_dst_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/ip_dst_cache/validate', 0o664, b'') +f('sys/kernel/slab/ip_dst_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/ip_dst_cache/free_calls', 0o664, b' 1 age=4303046733 pid=0 cpus=0\n') +f('sys/kernel/slab/ip_dst_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/journal_head', 0o775) +f('sys/kernel/slab/journal_head/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/journal_head/ctor', 0o664, b'') +f('sys/kernel/slab/journal_head/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/journal_head/slab_size', 0o664, b'168\n') +f('sys/kernel/slab/journal_head/total_objects', 0o664, b'7680\n') +f('sys/kernel/slab/journal_head/slabs', 0o664, b'320\n') +f('sys/kernel/slab/journal_head/poison', 0o664, b'1\n') +f('sys/kernel/slab/journal_head/alloc_calls', 0o664, b' 7662 journal_add_journal_head+0x9f/0x1b0 age=0/2379/651354 pid=1336-13466 cpus=0-1\n') +f('sys/kernel/slab/journal_head/objs_per_slab', 0o664, b'24\n') +f('sys/kernel/slab/journal_head/shrink', 0o664, b'') +f('sys/kernel/slab/journal_head/trace', 0o664, b'0\n') +f('sys/kernel/slab/journal_head/object_size', 0o664, b'96\n') +f('sys/kernel/slab/journal_head/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/journal_head/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/journal_head/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/journal_head/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/journal_head/objects', 0o664, b'7680\n') +f('sys/kernel/slab/journal_head/order', 0o664, b'0\n') +f('sys/kernel/slab/journal_head/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/journal_head/store_user', 0o664, b'1\n') +f('sys/kernel/slab/journal_head/align', 0o664, b'0\n') +f('sys/kernel/slab/journal_head/partial', 0o664, b'0\n') +f('sys/kernel/slab/journal_head/validate', 0o664, b'') +f('sys/kernel/slab/journal_head/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/journal_head/free_calls', 0o664, b''' 7589 age=4303047557 pid=0 cpus=0 + 74 __journal_remove_journal_head+0xcb/0x160 age=1585/52253/654521 pid=32-13248 cpus=0-1 +''') +f('sys/kernel/slab/journal_head/aliases', 0o664, b'0\n') +d('sys/kernel/slab/scsi_data_buffer', 0o775) +f('sys/kernel/slab/scsi_data_buffer/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/ctor', 0o664, b'') +f('sys/kernel/slab/scsi_data_buffer/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/slab_size', 0o664, b'96\n') +f('sys/kernel/slab/scsi_data_buffer/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/slabs', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/poison', 0o664, b'1\n') +f('sys/kernel/slab/scsi_data_buffer/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/scsi_data_buffer/objs_per_slab', 0o664, b'42\n') +f('sys/kernel/slab/scsi_data_buffer/shrink', 0o664, b'') +f('sys/kernel/slab/scsi_data_buffer/trace', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/object_size', 0o664, b'24\n') +f('sys/kernel/slab/scsi_data_buffer/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/objects', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/order', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/scsi_data_buffer/store_user', 0o664, b'1\n') +f('sys/kernel/slab/scsi_data_buffer/align', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/partial', 0o664, b'0\n') +f('sys/kernel/slab/scsi_data_buffer/validate', 0o664, b'') +f('sys/kernel/slab/scsi_data_buffer/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/scsi_data_buffer/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/scsi_data_buffer/aliases', 0o664, b'0\n') +d('sys/kernel/slab/fuse_request', 0o775) +f('sys/kernel/slab/fuse_request/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/fuse_request/ctor', 0o664, b'') +f('sys/kernel/slab/fuse_request/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/fuse_request/slab_size', 0o664, b'728\n') +f('sys/kernel/slab/fuse_request/total_objects', 0o664, b'44\n') +f('sys/kernel/slab/fuse_request/slabs', 0o664, b'2\n') +f('sys/kernel/slab/fuse_request/poison', 0o664, b'1\n') +f('sys/kernel/slab/fuse_request/alloc_calls', 0o664, b' 1 fuse_request_alloc+0x1a/0x40 [fuse] age=8336120 pid=2476 cpus=0\n') +f('sys/kernel/slab/fuse_request/objs_per_slab', 0o664, b'22\n') +f('sys/kernel/slab/fuse_request/shrink', 0o664, b'') +f('sys/kernel/slab/fuse_request/trace', 0o664, b'0\n') +f('sys/kernel/slab/fuse_request/object_size', 0o664, b'656\n') +f('sys/kernel/slab/fuse_request/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/fuse_request/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/fuse_request/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/fuse_request/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/fuse_request/objects', 0o664, b'44\n') +f('sys/kernel/slab/fuse_request/order', 0o664, b'2\n') +f('sys/kernel/slab/fuse_request/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/fuse_request/store_user', 0o664, b'1\n') +f('sys/kernel/slab/fuse_request/align', 0o664, b'0\n') +f('sys/kernel/slab/fuse_request/partial', 0o664, b'0\n') +f('sys/kernel/slab/fuse_request/validate', 0o664, b'') +f('sys/kernel/slab/fuse_request/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/fuse_request/free_calls', 0o664, b' 1 age=4303047718 pid=0 cpus=0\n') +f('sys/kernel/slab/fuse_request/aliases', 0o664, b'0\n') +d('sys/kernel/slab/pid', 0o775) +f('sys/kernel/slab/pid/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/pid/ctor', 0o664, b'') +f('sys/kernel/slab/pid/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/pid/slab_size', 0o664, b'192\n') +f('sys/kernel/slab/pid/total_objects', 0o664, b'252\n') +f('sys/kernel/slab/pid/slabs', 0o664, b'12\n') +f('sys/kernel/slab/pid/poison', 0o664, b'1\n') +f('sys/kernel/slab/pid/alloc_calls', 0o664, b' 207 alloc_pid+0x26/0x430 age=4190/8015525/8379960 pid=0-13212 cpus=0-1\n') +f('sys/kernel/slab/pid/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/pid/shrink', 0o664, b'') +f('sys/kernel/slab/pid/trace', 0o664, b'0\n') +f('sys/kernel/slab/pid/object_size', 0o664, b'80\n') +f('sys/kernel/slab/pid/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/pid/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/pid/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/pid/objects_partial', 0o664, b'131\n') +f('sys/kernel/slab/pid/objects', 0o664, b'236\n') +f('sys/kernel/slab/pid/order', 0o664, b'0\n') +f('sys/kernel/slab/pid/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/pid/store_user', 0o664, b'1\n') +f('sys/kernel/slab/pid/align', 0o664, b'8\n') +f('sys/kernel/slab/pid/partial', 0o664, b'7\n') +f('sys/kernel/slab/pid/validate', 0o664, b'') +f('sys/kernel/slab/pid/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/pid/free_calls', 0o664, b''' 69 age=4303047306 pid=0 cpus=0 + 138 put_pid+0x36/0x40 age=7228/7841898/8377070 pid=0-13258 cpus=0-1 +''') +f('sys/kernel/slab/pid/aliases', 0o664, b'0\n') +d('sys/kernel/slab/ext2_inode_cache', 0o775) +f('sys/kernel/slab/ext2_inode_cache/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/ext2_inode_cache/ctor', 0o664, b'init_once+0x0/0x60\n') +f('sys/kernel/slab/ext2_inode_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/slab_size', 0o664, b'1456\n') +f('sys/kernel/slab/ext2_inode_cache/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/slabs', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/ext2_inode_cache/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/ext2_inode_cache/objs_per_slab', 0o664, b'22\n') +f('sys/kernel/slab/ext2_inode_cache/shrink', 0o664, b'') +f('sys/kernel/slab/ext2_inode_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/object_size', 0o664, b'1384\n') +f('sys/kernel/slab/ext2_inode_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/objects', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/order', 0o664, b'3\n') +f('sys/kernel/slab/ext2_inode_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/ext2_inode_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/ext2_inode_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/ext2_inode_cache/validate', 0o664, b'') +f('sys/kernel/slab/ext2_inode_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/ext2_inode_cache/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/ext2_inode_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-1024', 0o775) +f('sys/kernel/slab/kmalloc-1024/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-1024/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-1024/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-1024/slab_size', 0o664, b'1096\n') +f('sys/kernel/slab/kmalloc-1024/total_objects', 0o664, b'580\n') +f('sys/kernel/slab/kmalloc-1024/slabs', 0o664, b'20\n') +f('sys/kernel/slab/kmalloc-1024/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-1024/alloc_calls', 0o664, b''' 23 __register_sysctl_paths+0x56/0x340 age=8360116/8368981/8379769 pid=1-1549 cpus=0-1 + 5 param_sysfs_setup+0x87/0x140 age=8355550/8371926/8379909 pid=1-1805 cpus=0-1 + 5 load_module+0x18d5/0x1b30 age=8328407/8365286/8375764 pid=208-2578 cpus=0 + 2 __vmalloc_area_node+0xfb/0x140 age=8360170/8367347/8374524 pid=107-1549 cpus=0 + 4 __percpu_alloc_mask+0xbc/0x140 age=8379760/8379760/8379760 pid=1 cpus=0 + 113 alloc_pipe_info+0x25/0x60 age=125624/8270722/8377065 pid=1-13212 cpus=0-1 + 2 alloc_fdtable+0x81/0x160 age=2417000/5386894/8356789 pid=1690 cpus=0-1 + 1 mb_cache_create+0xb6/0x1f0 age=8379750 pid=1 cpus=1 + 1 mb_cache_create+0x11e/0x1f0 age=8379750 pid=1 cpus=1 + 8 add_partition+0x45/0x250 age=61959/7339549/8379206 pid=1-13295 cpus=0 + 2 __crypto_alloc_tfm+0x43/0x1b0 age=3544684/3544684/3544684 pid=1545 cpus=0 + 1 pci_create_bus+0x82/0x240 age=8379831 pid=1 cpus=0 + 14 pcie_port_device_register+0x254/0x4a0 age=8379746/8379746/8379748 pid=1 cpus=1 + 1 acpi_ev_create_gpe_block+0x10b/0x3bf age=8379903 pid=1 cpus=0 + 1 acpi_tb_resize_root_table_list+0x66/0xdb age=8375731 pid=330 cpus=0 + 2 tty_buffer_request_room+0x136/0x190 age=8214639/8272696/8330753 pid=0-2262 cpus=0 + 1 tty_register_driver+0x1b3/0x2a0 age=8309081 pid=2711 cpus=1 + 10 tty_write+0x160/0x280 age=7214010/8238951/8377659 pid=34-2590 cpus=0-1 + 2 set_inverse_trans_unicode+0xce/0xf0 age=8355014/8367379/8379745 pid=1-1898 cpus=1 + 1 uart_register_driver+0x31/0x1c0 age=8379710 pid=1 cpus=1 + 166 device_create_vargs+0x8c/0x100 age=22658/8173620/8379911 pid=1-13295 cpus=0-1 + 8 platform_device_alloc+0x37/0x90 age=8367172/8376785/8379911 pid=1-1285 cpus=0-1 + 3 scsi_alloc_target+0x63/0x2e0 age=61990/5606770/8379325 pid=1-13295 cpus=0-1 + 2 sd_probe+0x86/0x430 age=61986/4220653/8379321 pid=1-13295 cpus=1 + 1 ahci_port_start+0x34/0xe0 age=8379708 pid=1 cpus=1 + 1 psmouse_connect+0x5b/0x2c0 age=8378898 pid=17 cpus=1 + 2 thermal_cooling_device_register+0x7f/0x290 age=8375643/8375667/8375692 pid=330 cpus=0-1 + 1 hid_add_field+0xcc/0x3a0 age=53473 pid=419 cpus=0 + 4 sock_alloc_send_skb+0x1cd/0x200 age=8344775/8349266/8350926 pid=1738 cpus=0-1 + 3 __rtnl_register+0x79/0x90 age=8360119/8373266/8379912 pid=1-1549 cpus=0 + 6 qdisc_alloc+0x34/0xd0 age=8356043/8356079/8356257 pid=1541 cpus=0 + 1 dmi_id_init+0x2a4/0x30c age=8379910 pid=1 cpus=0 + 5 hub_probe+0xdd/0x820 [usbcore] age=8373999/8374492/8374845 pid=143-147 cpus=0-1 + 5 usb_create_hcd+0x39/0x150 [usbcore] age=8374071/8374526/8374892 pid=143-147 cpus=0 + 26 usb_set_configuration+0x441/0x5f0 [usbcore] age=22663/3237429/8374857 pid=143-419 cpus=0-1 + 10 usb_get_configuration+0x92/0x1480 [usbcore] age=22667/5876069/8374865 pid=143-419 cpus=0-1 + 34 usb_create_ep_files+0x51/0x350 [usbcore] age=22579/5431762/8374732 pid=143-419 cpus=0-1 + 1 acpi_battery_add+0x29/0x1d3 [battery] age=8375630 pid=396 cpus=0 + 1 snd_card_new+0x38/0x370 [snd] age=8374136 pid=107 cpus=0 + 1 sta_info_alloc+0x3c/0x1d0 [mac80211] age=8329523 pid=742 cpus=0 + 2 snd_pcm_new+0x47/0x130 [snd_pcm] age=8374109/8374109/8374109 pid=107 cpus=1 + 1 rs_alloc_sta+0x25/0x120 [iwl3945] age=8329523 pid=742 cpus=0 + 1 get_alloc_hash+0x9b/0x140 [snd_hda_intel] age=8373108 pid=786 cpus=0 + 1 azx_probe+0xb3/0xc20 [snd_hda_intel] age=8374129 pid=107 cpus=0 + 1 azx_probe+0x4a9/0xc20 [snd_hda_intel] age=8374122 pid=107 cpus=0 + 1 snd_hda_codec_new+0x3e/0x559 [snd_hda_intel] age=8374112 pid=107 cpus=1 + 1 md_probe+0xa1/0x360 [md_mod] age=8370183 pid=916 cpus=0 + 8 loop_alloc+0x28/0x140 [loop] age=8369639/8369639/8369639 pid=951 cpus=0 + 4 ipv6_add_dev+0x69/0x330 [ipv6] age=8360116/8360117/8360119 pid=1549 cpus=0 + 1 ipv6_route_sysctl_init+0x22/0xb0 [ipv6] age=8360115 pid=1549 cpus=0 + 2 snd_seq_create_port+0x35/0x180 [snd_seq] age=8355549/8355549/8355549 pid=1805 cpus=0 +''') +f('sys/kernel/slab/kmalloc-1024/objs_per_slab', 0o664, b'29\n') +f('sys/kernel/slab/kmalloc-1024/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-1024/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-1024/object_size', 0o664, b'1024\n') +f('sys/kernel/slab/kmalloc-1024/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-1024/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-1024/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-1024/objects_partial', 0o664, b'196\n') +f('sys/kernel/slab/kmalloc-1024/objects', 0o664, b'544\n') +f('sys/kernel/slab/kmalloc-1024/order', 0o664, b'3\n') +f('sys/kernel/slab/kmalloc-1024/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-1024/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-1024/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-1024/partial', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-1024/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-1024/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-1024/free_calls', 0o664, b''' 216 age=4303047343 pid=0 cpus=0 + 1 __vunmap+0xe9/0x120 age=8360137 pid=1549 cpus=0 + 64 __free_pipe_info+0x5c/0x70 age=55301/8227248/8377668 pid=34-13363 cpus=0-1 + 19 acpi_ds_delete_walk_state+0xc9/0xcd age=8355814/8376228/8380000 pid=0-1772 cpus=0-1 + 1 acpi_tb_resize_root_table_list+0xbf/0xdb age=8375732 pid=330 cpus=0 + 2 release_one_tty+0xc7/0x190 age=8352476/8361380/8370284 pid=55-1253 cpus=0-1 + 1 vt_ioctl+0x273/0x1c30 age=8356598 pid=1703 cpus=0 + 14 device_create_release+0x9/0x10 age=8352395/8354628/8356598 pid=1703-2139 cpus=0-1 + 1 fw_dev_release+0x20/0x30 age=8356148 pid=1541 cpus=0 + 184 skb_release_data+0x85/0xd0 age=22639/7036434/8379911 pid=0-13303 cpus=0-1 +''') +f('sys/kernel/slab/kmalloc-1024/aliases', 0o664, b'0\n') +d('sys/kernel/slab/files_cache', 0o775) +f('sys/kernel/slab/files_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/files_cache/ctor', 0o664, b'') +f('sys/kernel/slab/files_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/files_cache/slab_size', 0o664, b'896\n') +f('sys/kernel/slab/files_cache/total_objects', 0o664, b'108\n') +f('sys/kernel/slab/files_cache/slabs', 0o664, b'6\n') +f('sys/kernel/slab/files_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/files_cache/alloc_calls', 0o664, b' 80 dup_fd+0x2e/0x420 age=4136/7769280/8379905 pid=0-12336 cpus=0-1\n') +f('sys/kernel/slab/files_cache/objs_per_slab', 0o664, b'18\n') +f('sys/kernel/slab/files_cache/shrink', 0o664, b'') +f('sys/kernel/slab/files_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/files_cache/object_size', 0o664, b'768\n') +f('sys/kernel/slab/files_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/files_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/files_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/files_cache/objects_partial', 0o664, b'29\n') +f('sys/kernel/slab/files_cache/objects', 0o664, b'101\n') +f('sys/kernel/slab/files_cache/order', 0o664, b'2\n') +f('sys/kernel/slab/files_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/files_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/files_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/files_cache/partial', 0o664, b'2\n') +f('sys/kernel/slab/files_cache/validate', 0o664, b'') +f('sys/kernel/slab/files_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/files_cache/free_calls', 0o664, b''' 9 age=4303047250 pid=0 cpus=0 + 31 put_files_struct+0xb4/0xe0 age=7177/7367129/8366999 pid=1202-20292 cpus=0-1 + 40 free_fdtable_rcu+0xa0/0xb0 age=61634/7953135/8376143 pid=0-12335 cpus=0-1 +''') +f('sys/kernel/slab/files_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/UDP-Lite', 0o775) +f('sys/kernel/slab/UDP-Lite/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/ctor', 0o664, b'') +f('sys/kernel/slab/UDP-Lite/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/UDP-Lite/slab_size', 0o664, b'1344\n') +f('sys/kernel/slab/UDP-Lite/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/slabs', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/poison', 0o664, b'1\n') +f('sys/kernel/slab/UDP-Lite/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/UDP-Lite/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/UDP-Lite/shrink', 0o664, b'') +f('sys/kernel/slab/UDP-Lite/trace', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/object_size', 0o664, b'1232\n') +f('sys/kernel/slab/UDP-Lite/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/objects', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/order', 0o664, b'2\n') +f('sys/kernel/slab/UDP-Lite/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/UDP-Lite/store_user', 0o664, b'1\n') +f('sys/kernel/slab/UDP-Lite/align', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/partial', 0o664, b'0\n') +f('sys/kernel/slab/UDP-Lite/validate', 0o664, b'') +f('sys/kernel/slab/UDP-Lite/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/UDP-Lite/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/UDP-Lite/aliases', 0o664, b'0\n') +d('sys/kernel/slab/mnt_cache', 0o775) +f('sys/kernel/slab/mnt_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/mnt_cache/ctor', 0o664, b'') +f('sys/kernel/slab/mnt_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/mnt_cache/slab_size', 0o664, b'320\n') +f('sys/kernel/slab/mnt_cache/total_objects', 0o664, b'36\n') +f('sys/kernel/slab/mnt_cache/slabs', 0o664, b'3\n') +f('sys/kernel/slab/mnt_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/mnt_cache/alloc_calls', 0o664, b' 25 alloc_vfsmnt+0x1f/0x180 age=61162/8041266/8379801 pid=0-13348 cpus=0-1\n') +f('sys/kernel/slab/mnt_cache/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/mnt_cache/shrink', 0o664, b'') +f('sys/kernel/slab/mnt_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/mnt_cache/object_size', 0o664, b'224\n') +f('sys/kernel/slab/mnt_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/mnt_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/mnt_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/mnt_cache/objects_partial', 0o664, b'4\n') +f('sys/kernel/slab/mnt_cache/objects', 0o664, b'28\n') +f('sys/kernel/slab/mnt_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/mnt_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/mnt_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/mnt_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/mnt_cache/partial', 0o664, b'1\n') +f('sys/kernel/slab/mnt_cache/validate', 0o664, b'') +f('sys/kernel/slab/mnt_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/mnt_cache/free_calls', 0o664, b''' 24 age=4303047098 pid=0 cpus=0 + 1 free_vfsmnt+0x2c/0x40 age=7837771 pid=3347 cpus=0 +''') +f('sys/kernel/slab/mnt_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/skbuff_head_cache', 0o775) +f('sys/kernel/slab/skbuff_head_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_head_cache/ctor', 0o664, b'') +f('sys/kernel/slab/skbuff_head_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_head_cache/slab_size', 0o664, b'320\n') +f('sys/kernel/slab/skbuff_head_cache/total_objects', 0o664, b'588\n') +f('sys/kernel/slab/skbuff_head_cache/slabs', 0o664, b'49\n') +f('sys/kernel/slab/skbuff_head_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_head_cache/alloc_calls', 0o664, b' 550 __alloc_skb+0x44/0x150 age=1665/3999351/8355948 pid=733-1738 cpus=0-1\n') +f('sys/kernel/slab/skbuff_head_cache/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/skbuff_head_cache/shrink', 0o664, b'') +f('sys/kernel/slab/skbuff_head_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_head_cache/object_size', 0o664, b'208\n') +f('sys/kernel/slab/skbuff_head_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_head_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_head_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_head_cache/objects_partial', 0o664, b'18\n') +f('sys/kernel/slab/skbuff_head_cache/objects', 0o664, b'570\n') +f('sys/kernel/slab/skbuff_head_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_head_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_head_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_head_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_head_cache/partial', 0o664, b'3\n') +f('sys/kernel/slab/skbuff_head_cache/validate', 0o664, b'') +f('sys/kernel/slab/skbuff_head_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_head_cache/free_calls', 0o664, b''' 333 age=4303046979 pid=0 cpus=0 + 217 __kfree_skb+0x3a/0xa0 age=1666/662694/8356220 pid=0-13466 cpus=0-1 +''') +f('sys/kernel/slab/skbuff_head_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/fuse_inode', 0o775) +f('sys/kernel/slab/fuse_inode/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/fuse_inode/ctor', 0o664, b'fuse_inode_init_once+0x0/0x10 [fuse]\n') +f('sys/kernel/slab/fuse_inode/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/fuse_inode/slab_size', 0o664, b'1344\n') +f('sys/kernel/slab/fuse_inode/total_objects', 0o664, b'12\n') +f('sys/kernel/slab/fuse_inode/slabs', 0o664, b'1\n') +f('sys/kernel/slab/fuse_inode/poison', 0o664, b'1\n') +f('sys/kernel/slab/fuse_inode/alloc_calls', 0o664, b' 1 fuse_alloc_inode+0x1a/0xe0 [fuse] age=8336111 pid=2476 cpus=0\n') +f('sys/kernel/slab/fuse_inode/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/fuse_inode/shrink', 0o664, b'') +f('sys/kernel/slab/fuse_inode/trace', 0o664, b'0\n') +f('sys/kernel/slab/fuse_inode/object_size', 0o664, b'1248\n') +f('sys/kernel/slab/fuse_inode/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/fuse_inode/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/fuse_inode/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/fuse_inode/objects_partial', 0o664, b'1\n') +f('sys/kernel/slab/fuse_inode/objects', 0o664, b'1\n') +f('sys/kernel/slab/fuse_inode/order', 0o664, b'2\n') +f('sys/kernel/slab/fuse_inode/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/fuse_inode/store_user', 0o664, b'1\n') +f('sys/kernel/slab/fuse_inode/align', 0o664, b'0\n') +f('sys/kernel/slab/fuse_inode/partial', 0o664, b'1\n') +f('sys/kernel/slab/fuse_inode/validate', 0o664, b'') +f('sys/kernel/slab/fuse_inode/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/fuse_inode/free_calls', 0o664, b' 1 age=4303047710 pid=0 cpus=0\n') +f('sys/kernel/slab/fuse_inode/aliases', 0o664, b'0\n') +d('sys/kernel/slab/skbuff_fclone_cache', 0o775) +f('sys/kernel/slab/skbuff_fclone_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_fclone_cache/ctor', 0o664, b'') +f('sys/kernel/slab/skbuff_fclone_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_fclone_cache/slab_size', 0o664, b'512\n') +f('sys/kernel/slab/skbuff_fclone_cache/total_objects', 0o664, b'32\n') +f('sys/kernel/slab/skbuff_fclone_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/skbuff_fclone_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_fclone_cache/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/skbuff_fclone_cache/objs_per_slab', 0o664, b'16\n') +f('sys/kernel/slab/skbuff_fclone_cache/shrink', 0o664, b'') +f('sys/kernel/slab/skbuff_fclone_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_fclone_cache/object_size', 0o664, b'420\n') +f('sys/kernel/slab/skbuff_fclone_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_fclone_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_fclone_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_fclone_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_fclone_cache/objects', 0o664, b'32\n') +f('sys/kernel/slab/skbuff_fclone_cache/order', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_fclone_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_fclone_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_fclone_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_fclone_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/skbuff_fclone_cache/validate', 0o664, b'') +f('sys/kernel/slab/skbuff_fclone_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/skbuff_fclone_cache/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/skbuff_fclone_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/buffer_head', 0o775) +f('sys/kernel/slab/buffer_head/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/buffer_head/ctor', 0o664, b'init_buffer_head+0x0/0x20\n') +f('sys/kernel/slab/buffer_head/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/buffer_head/slab_size', 0o664, b'176\n') +f('sys/kernel/slab/buffer_head/total_objects', 0o664, b'31487\n') +f('sys/kernel/slab/buffer_head/slabs', 0o664, b'1369\n') +f('sys/kernel/slab/buffer_head/poison', 0o664, b'1\n') +f('sys/kernel/slab/buffer_head/alloc_calls', 0o664, b' 31488 alloc_buffer_head+0x19/0x50 age=1/3079345/8378152 pid=1-32767 cpus=0-1\n') +f('sys/kernel/slab/buffer_head/objs_per_slab', 0o664, b'23\n') +f('sys/kernel/slab/buffer_head/shrink', 0o664, b'') +f('sys/kernel/slab/buffer_head/trace', 0o664, b'0\n') +f('sys/kernel/slab/buffer_head/object_size', 0o664, b'104\n') +f('sys/kernel/slab/buffer_head/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/buffer_head/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/buffer_head/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/buffer_head/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/buffer_head/objects', 0o664, b'31487\n') +f('sys/kernel/slab/buffer_head/order', 0o664, b'0\n') +f('sys/kernel/slab/buffer_head/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/buffer_head/store_user', 0o664, b'1\n') +f('sys/kernel/slab/buffer_head/align', 0o664, b'0\n') +f('sys/kernel/slab/buffer_head/partial', 0o664, b'0\n') +f('sys/kernel/slab/buffer_head/validate', 0o664, b'') +f('sys/kernel/slab/buffer_head/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/buffer_head/free_calls', 0o664, b''' 14436 age=4303047199 pid=0 cpus=0 + 17053 free_buffer_head+0x20/0x40 age=1227/1928220/8379062 pid=1-32759 cpus=0-1 +''') +f('sys/kernel/slab/buffer_head/aliases', 0o664, b'0\n') +d('sys/kernel/slab/blkdev_queue', 0o775) +f('sys/kernel/slab/blkdev_queue/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_queue/ctor', 0o664, b'') +f('sys/kernel/slab/blkdev_queue/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_queue/slab_size', 0o664, b'2496\n') +f('sys/kernel/slab/blkdev_queue/total_objects', 0o664, b'26\n') +f('sys/kernel/slab/blkdev_queue/slabs', 0o664, b'2\n') +f('sys/kernel/slab/blkdev_queue/poison', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_queue/alloc_calls', 0o664, b' 12 blk_alloc_queue_node+0x1c/0xc0 age=61520/7678497/8378855 pid=1-13295 cpus=0-1\n') +f('sys/kernel/slab/blkdev_queue/objs_per_slab', 0o664, b'13\n') +f('sys/kernel/slab/blkdev_queue/shrink', 0o664, b'') +f('sys/kernel/slab/blkdev_queue/trace', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_queue/object_size', 0o664, b'2424\n') +f('sys/kernel/slab/blkdev_queue/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_queue/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_queue/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_queue/objects_partial', 0o664, b'10\n') +f('sys/kernel/slab/blkdev_queue/objects', 0o664, b'23\n') +f('sys/kernel/slab/blkdev_queue/order', 0o664, b'3\n') +f('sys/kernel/slab/blkdev_queue/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_queue/store_user', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_queue/align', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_queue/partial', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_queue/validate', 0o664, b'') +f('sys/kernel/slab/blkdev_queue/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_queue/free_calls', 0o664, b' 12 age=4303046873 pid=0 cpus=0\n') +f('sys/kernel/slab/blkdev_queue/aliases', 0o664, b'0\n') +d('sys/kernel/slab/RAW', 0o775) +f('sys/kernel/slab/RAW/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/RAW/ctor', 0o664, b'') +f('sys/kernel/slab/RAW/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/RAW/slab_size', 0o664, b'1280\n') +f('sys/kernel/slab/RAW/total_objects', 0o664, b'12\n') +f('sys/kernel/slab/RAW/slabs', 0o664, b'1\n') +f('sys/kernel/slab/RAW/poison', 0o664, b'1\n') +f('sys/kernel/slab/RAW/alloc_calls', 0o664, b' 3 sk_prot_alloc+0x1e/0xb0 age=8379168/8379171/8379177 pid=1 cpus=0\n') +f('sys/kernel/slab/RAW/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/RAW/shrink', 0o664, b'') +f('sys/kernel/slab/RAW/trace', 0o664, b'0\n') +f('sys/kernel/slab/RAW/object_size', 0o664, b'1208\n') +f('sys/kernel/slab/RAW/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/RAW/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/RAW/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/RAW/objects_partial', 0o664, b'3\n') +f('sys/kernel/slab/RAW/objects', 0o664, b'3\n') +f('sys/kernel/slab/RAW/order', 0o664, b'2\n') +f('sys/kernel/slab/RAW/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/RAW/store_user', 0o664, b'1\n') +f('sys/kernel/slab/RAW/align', 0o664, b'0\n') +f('sys/kernel/slab/RAW/partial', 0o664, b'1\n') +f('sys/kernel/slab/RAW/validate', 0o664, b'') +f('sys/kernel/slab/RAW/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/RAW/free_calls', 0o664, b' 3 age=4303046751 pid=0 cpus=0\n') +f('sys/kernel/slab/RAW/aliases', 0o664, b'0\n') +d('sys/kernel/slab/blkdev_ioc', 0o775) +f('sys/kernel/slab/blkdev_ioc/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_ioc/ctor', 0o664, b'') +f('sys/kernel/slab/blkdev_ioc/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_ioc/slab_size', 0o664, b'200\n') +f('sys/kernel/slab/blkdev_ioc/total_objects', 0o664, b'100\n') +f('sys/kernel/slab/blkdev_ioc/slabs', 0o664, b'5\n') +f('sys/kernel/slab/blkdev_ioc/poison', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_ioc/alloc_calls', 0o664, b' 64 alloc_io_context+0x19/0xa0 age=3410/8058449/8378873 pid=1-13466 cpus=0-1\n') +f('sys/kernel/slab/blkdev_ioc/objs_per_slab', 0o664, b'20\n') +f('sys/kernel/slab/blkdev_ioc/shrink', 0o664, b'') +f('sys/kernel/slab/blkdev_ioc/trace', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_ioc/object_size', 0o664, b'128\n') +f('sys/kernel/slab/blkdev_ioc/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_ioc/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_ioc/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_ioc/objects_partial', 0o664, b'38\n') +f('sys/kernel/slab/blkdev_ioc/objects', 0o664, b'98\n') +f('sys/kernel/slab/blkdev_ioc/order', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_ioc/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_ioc/store_user', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_ioc/align', 0o664, b'0\n') +f('sys/kernel/slab/blkdev_ioc/partial', 0o664, b'2\n') +f('sys/kernel/slab/blkdev_ioc/validate', 0o664, b'') +f('sys/kernel/slab/blkdev_ioc/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/blkdev_ioc/free_calls', 0o664, b''' 9 age=4303046891 pid=0 cpus=0 + 55 put_io_context+0xb2/0xd0 age=45025/8043308/8374605 pid=145-13349 cpus=0-1 +''') +f('sys/kernel/slab/blkdev_ioc/aliases', 0o664, b'0\n') +d('sys/kernel/slab/sigqueue', 0o775) +f('sys/kernel/slab/sigqueue/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/sigqueue/ctor', 0o664, b'') +f('sys/kernel/slab/sigqueue/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/sigqueue/slab_size', 0o664, b'232\n') +f('sys/kernel/slab/sigqueue/total_objects', 0o664, b'34\n') +f('sys/kernel/slab/sigqueue/slabs', 0o664, b'2\n') +f('sys/kernel/slab/sigqueue/poison', 0o664, b'1\n') +f('sys/kernel/slab/sigqueue/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/sigqueue/objs_per_slab', 0o664, b'17\n') +f('sys/kernel/slab/sigqueue/shrink', 0o664, b'') +f('sys/kernel/slab/sigqueue/trace', 0o664, b'0\n') +f('sys/kernel/slab/sigqueue/object_size', 0o664, b'160\n') +f('sys/kernel/slab/sigqueue/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/sigqueue/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/sigqueue/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/sigqueue/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/sigqueue/objects', 0o664, b'34\n') +f('sys/kernel/slab/sigqueue/order', 0o664, b'0\n') +f('sys/kernel/slab/sigqueue/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/sigqueue/store_user', 0o664, b'1\n') +f('sys/kernel/slab/sigqueue/align', 0o664, b'8\n') +f('sys/kernel/slab/sigqueue/partial', 0o664, b'0\n') +f('sys/kernel/slab/sigqueue/validate', 0o664, b'') +f('sys/kernel/slab/sigqueue/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/sigqueue/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/sigqueue/aliases', 0o664, b'0\n') +d('sys/kernel/slab/TCPv6', 0o775) +f('sys/kernel/slab/TCPv6/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/TCPv6/ctor', 0o664, b'') +f('sys/kernel/slab/TCPv6/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/TCPv6/slab_size', 0o664, b'2432\n') +f('sys/kernel/slab/TCPv6/total_objects', 0o664, b'26\n') +f('sys/kernel/slab/TCPv6/slabs', 0o664, b'2\n') +f('sys/kernel/slab/TCPv6/poison', 0o664, b'1\n') +f('sys/kernel/slab/TCPv6/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/TCPv6/objs_per_slab', 0o664, b'13\n') +f('sys/kernel/slab/TCPv6/shrink', 0o664, b'') +f('sys/kernel/slab/TCPv6/trace', 0o664, b'0\n') +f('sys/kernel/slab/TCPv6/object_size', 0o664, b'2336\n') +f('sys/kernel/slab/TCPv6/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/TCPv6/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/TCPv6/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/TCPv6/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/TCPv6/objects', 0o664, b'26\n') +f('sys/kernel/slab/TCPv6/order', 0o664, b'3\n') +f('sys/kernel/slab/TCPv6/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/TCPv6/store_user', 0o664, b'1\n') +f('sys/kernel/slab/TCPv6/align', 0o664, b'0\n') +f('sys/kernel/slab/TCPv6/partial', 0o664, b'0\n') +f('sys/kernel/slab/TCPv6/validate', 0o664, b'') +f('sys/kernel/slab/TCPv6/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/TCPv6/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/TCPv6/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kioctx', 0o775) +f('sys/kernel/slab/kioctx/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kioctx/ctor', 0o664, b'') +f('sys/kernel/slab/kioctx/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/kioctx/slab_size', 0o664, b'640\n') +f('sys/kernel/slab/kioctx/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/kioctx/slabs', 0o664, b'0\n') +f('sys/kernel/slab/kioctx/poison', 0o664, b'1\n') +f('sys/kernel/slab/kioctx/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/kioctx/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/kioctx/shrink', 0o664, b'') +f('sys/kernel/slab/kioctx/trace', 0o664, b'0\n') +f('sys/kernel/slab/kioctx/object_size', 0o664, b'512\n') +f('sys/kernel/slab/kioctx/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kioctx/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kioctx/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kioctx/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/kioctx/objects', 0o664, b'0\n') +f('sys/kernel/slab/kioctx/order', 0o664, b'1\n') +f('sys/kernel/slab/kioctx/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kioctx/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kioctx/align', 0o664, b'8\n') +f('sys/kernel/slab/kioctx/partial', 0o664, b'0\n') +f('sys/kernel/slab/kioctx/validate', 0o664, b'') +f('sys/kernel/slab/kioctx/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kioctx/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/kioctx/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-32', 0o775) +f('sys/kernel/slab/kmalloc-32/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-32/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-32/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-32/slab_size', 0o664, b'104\n') +f('sys/kernel/slab/kmalloc-32/total_objects', 0o664, b'624\n') +f('sys/kernel/slab/kmalloc-32/slabs', 0o664, b'16\n') +f('sys/kernel/slab/kmalloc-32/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-32/alloc_calls', 0o664, b''' 1 mtrr_file_add+0xb0/0xe0 age=8355511 pid=1738 cpus=0 + 2 arch_acpi_processor_init_pdc+0x8e/0x180 age=8375727/8375758/8375789 pid=330 cpus=0 + 1 pm_qos_add_requirement+0x34/0xe0 age=8376080 pid=122 cpus=1 + 59 setup_modinfo_srcversion+0x19/0x30 age=8303075/8368435/8376316 pid=105-2754 cpus=0-1 + 42 load_module+0x1455/0x1b30 age=8303075/8366312/8375832 pid=107-2754 cpus=0-1 + 151 load_module+0x1ac4/0x1b30 age=8303071/8368871/8376310 pid=105-2754 cpus=0-1 + 3 mempool_create_node+0x4b/0xf0 age=62046/5606826/8379381 pid=1-13295 cpus=0-1 + 1 strndup_user+0x6d/0xc0 age=8374925 pid=107 cpus=0 + 16 __vmalloc_area_node+0xfb/0x140 age=8328464/8366300/8376086 pid=107-2578 cpus=0-1 + 1 do_kern_mount+0xca/0x110 age=8335800 pid=2476 cpus=0 + 1 do_sys_poll+0xdb/0x450 age=1303 pid=1333 cpus=1 + 1 alloc_vfsmnt+0x97/0x180 age=8335801 pid=2476 cpus=0 + 1 single_open+0x3c/0xb0 age=8355816 pid=1738 cpus=0 + 66 sysfs_new_dirent+0x10c/0x120 age=8360190/8377926/8379815 pid=1-1549 cpus=0-1 + 30 do_shmat+0x169/0x410 age=8274161/8330033/8348616 pid=1738-2621 cpus=0-1 + 21 register_blkdev+0x60/0x150 age=8369695/8377753/8379765 pid=1-951 cpus=0-1 + 39 kvasprintf+0x55/0x90 age=8360190/8378048/8379814 pid=1-1549 cpus=0-1 + 7 pci_save_state+0x1a4/0x250 age=8373637/8378406/8379803 pid=1-126 cpus=0-1 + 2 pcim_enable_device+0x86/0xb0 age=8379255/8379510/8379765 pid=1 cpus=0-1 + 15 acpi_ds_build_internal_package_obj+0xaf/0x1df age=8379932/8379938/8379947 pid=1 cpus=0 + 21 acpi_ds_build_internal_buffer_obj+0xe1/0x121 age=3847501/7731852/8379949 pid=1-330 cpus=0 + 1 acpi_install_gpe_handler+0xa7/0x13a age=8379959 pid=1 cpus=0 + 1 acpi_ev_create_gpe_block+0x282/0x3bf age=8379959 pid=1 cpus=0 + 1 acpi_pci_bind_root+0x8d/0x13e age=8379883 pid=1 cpus=0 + 18 acpi_pci_bind+0x85/0x28d age=8379879/8379879/8379882 pid=1 cpus=0 + 15 rand_initialize_disk+0x1d/0x30 age=62014/7263977/8379377 pid=1-13295 cpus=0-1 + 1 ata_host_start+0xcb/0x1e0 age=8379764 pid=1 cpus=1 + 1 hidinput_connect+0x2372/0x24e0 age=53529 pid=419 cpus=0 + 1 sock_kmalloc+0x5c/0x70 age=8325518 pid=1849 cpus=1 + 2 proto_register+0x7c/0x260 age=8360191/8370012/8379834 pid=1-1549 cpus=0 + 2 neigh_hash_alloc+0x42/0x50 age=8325417/8327412/8329408 pid=0-1849 cpus=1 + 1 nl_pid_hash_rehash+0x180/0x1a0 age=947530 pid=1189 cpus=0 + 28 unix_bind+0xd8/0x3a0 age=8356458/8357177/8366824 pid=1336-1738 cpus=0-1 + 3 ipc_init_proc_interface+0x2e/0x7c age=8379805/8379805/8379805 pid=1 cpus=1 + 13 usb_cache_string+0x65/0xa0 [usbcore] age=22649/4521883/8374921 pid=143-419 cpus=0-1 + 6 usb_get_configuration+0x18f/0x1480 [usbcore] age=67053/6989971/8374921 pid=143-419 cpus=0-1 + 2 _snd_ctl_register_ioctl+0x2b/0x80 [snd] age=8374675/8374675/8374675 pid=107 cpus=0 + 2 snd_oss_info_register+0x40/0xc0 [snd] age=8355350/8355452/8355555 pid=1813 cpus=0 + 6 adjust_io+0xeb/0x120 [rsrc_nonstatic] age=8373110/8373182/8373542 pid=352-800 cpus=0 + 5 adjust_memory+0xe5/0x1a0 [rsrc_nonstatic] age=8373110/8373278/8373535 pid=352-800 cpus=0 + 1 ieee80211_sta_set_extra_ie+0x7d/0xe0 [mac80211] age=8329597 pid=1545 cpus=0 + 2 ieee80211_rx_bss_info+0x4df/0xa20 [mac80211] age=8330170/8342783/8355397 pid=0 cpus=0 + 2 ieee80211_rx_bss_info+0x568/0xa20 [mac80211] age=22736/4188782/8354829 pid=742-1951 cpus=0 + 2 ieee80211_rx_bss_info+0x5f7/0xa20 [mac80211] age=22736/4189294/8355852 pid=742-1772 cpus=0 + 1 rate_control_alloc+0x32/0x110 [mac80211] age=8373757 pid=126 cpus=1 + 2 ieee80211_rate_control_register+0x72/0xf0 [mac80211] age=8374580/8374635/8374690 pid=126 cpus=0-1 + 2 azx_probe+0x9a4/0xc20 [snd_hda_intel] age=8374165/8374165/8374165 pid=107 cpus=1 + 1 async_chainiv_givencrypt+0x71/0x110 [crypto_blkcipher] age=8374560 pid=215 cpus=0 + 1 run+0x66/0x500 [raid1] age=8370114 pid=916 cpus=0 + 1 acpi_cpufreq_cpu_init+0x4d/0x45c [acpi_cpufreq] age=8366427 pid=1358 cpus=0 +''') +f('sys/kernel/slab/kmalloc-32/objs_per_slab', 0o664, b'39\n') +f('sys/kernel/slab/kmalloc-32/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-32/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-32/object_size', 0o664, b'32\n') +f('sys/kernel/slab/kmalloc-32/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-32/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-32/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-32/objects_partial', 0o664, b'149\n') +f('sys/kernel/slab/kmalloc-32/objects', 0o664, b'617\n') +f('sys/kernel/slab/kmalloc-32/order', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-32/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-32/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-32/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-32/partial', 0o664, b'4\n') +f('sys/kernel/slab/kmalloc-32/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-32/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-32/free_calls', 0o664, b''' 409 age=4303047399 pid=0 cpus=0 + 4 __vunmap+0xe9/0x120 age=8366429/8372533/8374823 pid=215-1358 cpus=0-1 + 1 vfs_rename+0x301/0x450 age=8274772 pid=2851 cpus=0 + 8 do_sys_poll+0x32b/0x450 age=1304/6728883/8333312 pid=1333 cpus=0-1 + 1 seq_release_private+0x2d/0x60 age=8352378 pid=2141 cpus=0 + 5 single_release+0x2e/0x40 age=8343903/8358822/8366889 pid=1258-1806 cpus=0 + 1 setxattr+0xa6/0x130 age=8355591 pid=1816 cpus=0 + 6 bio_free_map_data+0x25/0x30 age=53571/4350975/8375998 pid=0-318 cpus=0 + 6 remove_kevent+0x44/0x60 age=7219423/7961750/8346613 pid=2271-2423 cpus=0-1 + 57 load_elf_binary+0xa72/0x1e20 age=22671/8213994/8376585 pid=102-13419 cpus=0-1 + 1 generic_acl_set+0x15e/0x1a0 age=8355591 pid=1816 cpus=0 + 67 kobject_uevent_env+0x11a/0x470 age=62016/8246870/8379965 pid=1-13295 cpus=0-1 + 2 pci_get_subsys+0x74/0xa0 age=8375728/8375759/8375790 pid=330 cpus=0 + 8 acpi_evaluate_integer+0xbf/0xd1 age=3847577/7810351/8379888 pid=1-2097 cpus=0 + 3 acpi_ds_create_operand+0x12c/0x209 age=3847578/6867437/8379889 pid=1-2097 cpus=0 + 3 acpi_ns_get_node+0x92/0xa1 age=8374447/8376288/8379960 pid=1-215 cpus=0-1 + 5 acpi_ut_delete_internal_obj+0x15f/0x16f age=8366428/8373878/8375771 pid=330-1358 cpus=0 + 3 acpi_pci_bind+0x277/0x28d age=8379881/8379881/8379883 pid=1 cpus=0 + 1 get_modalias+0xd4/0x120 age=8355825 pid=1772 cpus=0 + 2 ioctl_standard_iw_point+0x179/0x350 age=63360/84363/105367 pid=1541 cpus=0 + 1 pci_bus_assign_resources+0xfe/0x4d0 age=8379836 pid=1 cpus=0 + 1 sg_clean+0x3e/0x80 [usbcore] age=59566 pid=13294 cpus=0 + 9 usb_get_device_descriptor+0x9b/0xa0 [usbcore] age=22724/6523118/8374922 pid=143-419 cpus=0-1 + 1 ieee80211_rx_bss_info+0x552/0xa20 [mac80211] age=22737 pid=742 cpus=0 + 2 ieee80211_rx_bss_info+0x5e1/0xa20 [mac80211] age=22737/4189295/8355853 pid=742-1772 cpus=0 +''') +f('sys/kernel/slab/kmalloc-32/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-64', 0o775) +f('sys/kernel/slab/kmalloc-64/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-64/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-64/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-64/slab_size', 0o664, b'136\n') +f('sys/kernel/slab/kmalloc-64/total_objects', 0o664, b'15300\n') +f('sys/kernel/slab/kmalloc-64/slabs', 0o664, b'510\n') +f('sys/kernel/slab/kmalloc-64/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-64/alloc_calls', 0o664, b''' 30 alternatives_smp_module_add+0x81/0x160 age=8303055/8368397/8380085 pid=0-2754 cpus=0-1 + 39 __request_region+0x39/0x120 age=8373811/8378273/8379949 pid=1-352 cpus=0-1 + 1 audit_log_start+0x353/0x3f0 age=8379797 pid=1 cpus=1 + 16 request_irq+0x9a/0xf0 age=8356279/8374005/8379942 pid=1-1541 cpus=0-1 + 3 devm_request_irq+0x4b/0xc0 age=8379232/8379403/8379747 pid=1 cpus=0-1 + 1 strndup_user+0x6d/0xc0 age=8374545 pid=215 cpus=0 + 95 __get_vm_area_node+0x9b/0x220 age=8303058/8371551/8380085 pid=0-2754 cpus=0-1 + 17 __vmalloc_area_node+0xfb/0x140 age=8309125/8366469/8376299 pid=105-2711 cpus=0-1 + 1 add_swap_extent+0x57/0xc0 age=8372039 pid=867 cpus=0 + 33 dma_pool_alloc+0x6d/0x200 age=8309120/8340771/8374904 pid=143-2711 cpus=0-1 + 40 alloc_kmem_cache_cpu+0x81/0x90 age=8360159/8368022/8379787 pid=1-1549 cpus=0-1 + 164 __percpu_alloc_mask+0x52/0x140 age=61997/8067718/8380085 pid=0-13295 cpus=0-1 + 184 __percpu_alloc_mask+0xbc/0x140 age=62029/8100825/8380085 pid=0-13295 cpus=0-1 + 604 d_alloc+0x19d/0x1f0 age=22685/7859083/8376462 pid=72-24701 cpus=0-1 + 17 alloc_fdtable+0x57/0x160 age=4267/6101781/8357279 pid=1532-12336 cpus=0-1 + 17 alloc_fdtable+0xb4/0x160 age=4267/6101781/8357279 pid=1532-12336 cpus=0-1 + 1 bioset_create+0x21/0xc0 age=8379947 pid=1 cpus=0 + 1 bd_claim_by_disk+0x6f/0x270 age=8370131 pid=916 cpus=0 + 14 posix_acl_alloc+0x1b/0x30 age=53326/7759393/8352180 pid=2175-13390 cpus=0-1 + 5 proc_reg_open+0x3f/0x170 age=8355799/8361268/8366755 pid=1327-1738 cpus=0 + 12754 ext3_init_block_alloc_info+0x22/0x80 age=1/498494/8368528 pid=1-23373 cpus=0-1 + 4 ext3_readdir+0x617/0x650 age=8352064/8352079/8352114 pid=1370 cpus=0 + 8 ext3_htree_store_dirent+0x37/0x130 age=8352064/8352072/8352099 pid=1370 cpus=0 + 277 kobject_create+0x1a/0x40 age=22618/7771015/8380085 pid=0-13295 cpus=0-1 + 1 pci_create_sysfs_dev_files+0x23e/0x3b0 age=8378937 pid=1 cpus=0 + 11 acpi_os_validate_address+0x3d/0xa3 age=8379914/8379927/8379932 pid=1 cpus=0 + 124 acpi_ds_build_internal_package_obj+0xaf/0x1df age=3847484/8233379/8379936 pid=1-330 cpus=0 + 6 acpi_ds_build_internal_buffer_obj+0xe1/0x121 age=8379920/8379925/8379934 pid=1 cpus=0 + 1 acpi_ev_system_memory_region_setup+0x68/0x8f age=8379914 pid=1 cpus=0 + 3 acpi_add_single_object+0x596/0xd3c age=8379878/8379880/8379882 pid=1 cpus=0 + 3 acpi_add_single_object+0x5d8/0xd3c age=8379886/8379888/8379890 pid=1 cpus=0 + 27 acpi_add_single_object+0x9f7/0xd3c age=8379871/8379888/8379900 pid=1 cpus=0 + 55 acpi_ec_add_query_handler+0x31/0x91 age=8379870/8379870/8379870 pid=1 cpus=0 + 1 find_dock+0x2c9/0x426 age=8379950 pid=1 cpus=0 + 6 find_dock_devices+0x5e/0x92 age=8379950/8379950/8379950 pid=1 cpus=0 + 8 acpi_pci_link_add+0x32/0x1db age=8379843/8379844/8379846 pid=1 cpus=0 + 39 acpi_pci_irq_add_prt+0x181/0x324 age=8379862/8379863/8379865 pid=1 cpus=0 + 15 init_dev+0x3c8/0x6f0 age=7217158/8282400/8378180 pid=33-2593 cpus=0-1 + 15 init_dev+0x437/0x6f0 age=7217158/8282400/8378180 pid=33-2593 cpus=0-1 + 3 init_dev+0x5b2/0x6f0 age=7217158/7969269/8364358 pid=1258-2593 cpus=0-1 + 3 init_dev+0x637/0x6f0 age=7217158/7969269/8364358 pid=1258-2593 cpus=0-1 + 2 kobj_map_init+0x36/0xa0 age=8379947/8380016/8380085 pid=0-1 cpus=0 + 38 kobj_map+0x79/0x1a0 age=61997/7936136/8379947 pid=1-13295 cpus=0-1 + 3 dmam_alloc_coherent+0x3f/0xa0 age=8379232/8379403/8379747 pid=1 cpus=0-1 + 1 scsi_probe_and_add_lun+0x65e/0xd80 age=62028 pid=13295 cpus=0 + 170 scsi_dev_info_list_add+0x3d/0x120 age=8379831/8379831/8379831 pid=1 cpus=0 + 1 ahci_init_one+0x137/0xcb0 age=8379748 pid=1 cpus=1 + 1 cpufreq_stat_notifier_policy+0xa1/0x2e0 age=8366410 pid=1358 cpus=0 + 1 cpufreq_stat_notifier_policy+0x17e/0x2e0 age=8366410 pid=1358 cpus=0 + 1 hid_parse_report+0xa9/0x2c0 age=53512 pid=419 cpus=0 + 10 __dev_addr_add+0x69/0xe0 age=8325501/8345496/8360156 pid=8-1849 cpus=0-1 +''') +f('sys/kernel/slab/kmalloc-64/objs_per_slab', 0o664, b'30\n') +f('sys/kernel/slab/kmalloc-64/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-64/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-64/object_size', 0o664, b'64\n') +f('sys/kernel/slab/kmalloc-64/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-64/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-64/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-64/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-64/objects', 0o664, b'15300\n') +f('sys/kernel/slab/kmalloc-64/order', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-64/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-64/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-64/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-64/partial', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-64/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-64/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-64/free_calls', 0o664, b''' 13029 age=4303047386 pid=0 cpus=0 + 1 iounmap+0xc2/0x100 age=8379917 pid=1 cpus=0 + 1 memtype_get_idx+0x75/0xc0 age=782 pid=13466 cpus=0 + 2 __release_region+0xc6/0xd0 age=8379754/8379754/8379754 pid=1 cpus=1 + 3 __request_region+0x86/0x120 age=8379828/8379828/8379828 pid=1 cpus=0 + 1 generic_smp_call_function_single_interrupt+0xce/0xe0 age=8355499 pid=0 cpus=1 + 53 __stop_machine+0x216/0x220 age=8303059/8367652/8376299 pid=105-2754 cpus=0-1 + 2 free_irq+0xef/0x190 age=8356302/8367658/8379015 pid=1-1541 cpus=0 + 28 __vunmap+0xcd/0x120 age=8309125/8366969/8376298 pid=105-2711 cpus=0-1 + 8 __vunmap+0xe9/0x120 age=8328457/8364062/8376068 pid=107-2578 cpus=0-1 + 1 percpu_free+0x2d/0x60 age=61987 pid=13295 cpus=0 + 10 do_sys_poll+0x32b/0x450 age=61481/7500944/8334758 pid=1333-2262 cpus=0-1 + 187 d_callback+0x22/0x40 age=22704/7997936/8376459 pid=0-2156 cpus=0-1 + 198 free_fdtable_rcu+0x7a/0xb0 age=1292/3883175/8376371 pid=0-13456 cpus=0-1 + 224 free_fdtable_rcu+0x82/0xb0 age=1292/3491449/8377150 pid=0-13456 cpus=0-1 + 42 proc_reg_release+0x96/0x120 age=3564/7013222/8376067 pid=126-2586 cpus=0-1 + 50 proc_reg_open+0x138/0x170 age=656297/2956669/8367924 pid=1184-12336 cpus=0-1 + 1046 free_rb_tree_fname+0x5c/0xb0 age=5905/4315279/8376402 pid=102-24701 cpus=0-1 + 79 ext3_htree_free_dir_info+0x19/0x20 age=5905/6235661/8376402 pid=102-24701 cpus=0-1 + 26 ext3_clear_inode+0xa5/0xb0 age=12954/2421572/8354304 pid=1253-8445 cpus=0-1 + 1 dynamic_kobj_release+0x2c/0x40 age=8356191 pid=1541 cpus=0 + 66 kobject_uevent_env+0x11a/0x470 age=22624/7608199/8379955 pid=1-2711 cpus=0-1 + 16 acpi_ds_call_control_method+0xfe/0x180 age=3020/4710292/8379848 pid=1-13466 cpus=0-1 + 1 acpi_ev_execute_reg_method+0x129/0x13a age=8379946 pid=1 cpus=0 + 1 acpi_ev_asynch_execute_gpe_method+0xcc/0x119 age=8379905 pid=12 cpus=1 + 33 acpi_evaluate_object+0x1ea/0x1fc age=3015/5838124/8379955 pid=1-13466 cpus=0-1 + 4 acpi_get_object_info+0x1c4/0x1d4 age=8379876/8379888/8379895 pid=1 cpus=0 + 1 acpi_walk_resources+0xa4/0xbd age=8379755 pid=1 cpus=1 + 41 acpi_ut_evaluate_object+0x18d/0x19b age=8379223/8379861/8379919 pid=1 cpus=0-1 + 4 acpi_ut_delete_internal_obj+0x15f/0x16f age=8366416/8373412/8375744 pid=330-1358 cpus=0 + 7 acpi_bus_get_ejd+0x73/0x80 age=8379955/8379955/8379955 pid=1 cpus=0 + 11 pnp_show_options+0x459/0x600 age=1578/1602/1627 pid=13466 cpus=0 + 11 pnp_show_current_resources+0x16f/0x180 age=1578/1603/1628 pid=13466 cpus=0 + 19 release_one_tty+0x53/0x190 age=804540/7566113/8370327 pid=55-2106 cpus=0-1 + 24 release_one_tty+0x60/0x190 age=804540/7729452/8370327 pid=55-2141 cpus=0-1 + 6 release_one_tty+0x167/0x190 age=8352429/8353224/8354794 pid=1967-2141 cpus=0 + 4 devres_remove_group+0x9e/0xe0 age=8379026/8379313/8379753 pid=1 cpus=0-1 + 1 ata_acpi_on_devcfg+0x385/0x6a0 age=8379406 pid=25 cpus=0 + 3 serio_free_event+0x1d/0x30 age=8378463/8378812/8378999 pid=17 cpus=0-1 + 6 input_register_device+0x17c/0x230 age=53514/6988336/8378983 pid=17-803 cpus=0-1 + 1 ip_cork_release+0x1f/0x50 age=8333854 pid=2536 cpus=1 + 1 unix_sock_destructor+0x75/0xd0 age=7217178 pid=2344 cpus=0 + 13 huft_free+0x1e/0x2f age=8379804/8379804/8379804 pid=1 cpus=0 + 6 hub_port_init+0x522/0x740 [usbcore] age=22825/4210550/8374275 pid=419 cpus=0-1 + 1 usb_release_interface_cache+0x2c/0x60 [usbcore] age=8373868 pid=419 cpus=0 + 1 usb_release_interface_cache+0x47/0x60 [usbcore] age=8373868 pid=419 cpus=0 + 1 __param_str_act+0x16c/0xfffffffffffffb13 [thermal] age=8375113 pid=383 cpus=0 + 3 snd_card_file_remove+0x73/0x130 [snd] age=8333050/8337203/8339297 pid=2400-2425 cpus=0 + 2 hid_probe+0x222/0xf30 [usbhid] age=53517/4212911/8372306 pid=419-803 cpus=0 +''') +f('sys/kernel/slab/kmalloc-64/aliases', 0o664, b'0\n') +d('sys/kernel/slab/sgpool-128', 0o775) +f('sys/kernel/slab/sgpool-128/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-128/ctor', 0o664, b'') +f('sys/kernel/slab/sgpool-128/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-128/slab_size', 0o664, b'4224\n') +f('sys/kernel/slab/sgpool-128/total_objects', 0o664, b'14\n') +f('sys/kernel/slab/sgpool-128/slabs', 0o664, b'2\n') +f('sys/kernel/slab/sgpool-128/poison', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-128/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379262/8379262/8379262 pid=1 cpus=0\n') +f('sys/kernel/slab/sgpool-128/objs_per_slab', 0o664, b'7\n') +f('sys/kernel/slab/sgpool-128/shrink', 0o664, b'') +f('sys/kernel/slab/sgpool-128/trace', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-128/object_size', 0o664, b'4096\n') +f('sys/kernel/slab/sgpool-128/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-128/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-128/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-128/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-128/objects', 0o664, b'14\n') +f('sys/kernel/slab/sgpool-128/order', 0o664, b'3\n') +f('sys/kernel/slab/sgpool-128/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-128/store_user', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-128/align', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-128/partial', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-128/validate', 0o664, b'') +f('sys/kernel/slab/sgpool-128/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-128/free_calls', 0o664, b' 2 age=4303046812 pid=0 cpus=0\n') +f('sys/kernel/slab/sgpool-128/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kcopyd_job', 0o775) +f('sys/kernel/slab/kcopyd_job/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/ctor', 0o664, b'') +f('sys/kernel/slab/kcopyd_job/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/slab_size', 0o664, b'544\n') +f('sys/kernel/slab/kcopyd_job/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/slabs', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/poison', 0o664, b'1\n') +f('sys/kernel/slab/kcopyd_job/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/kcopyd_job/objs_per_slab', 0o664, b'15\n') +f('sys/kernel/slab/kcopyd_job/shrink', 0o664, b'') +f('sys/kernel/slab/kcopyd_job/trace', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/object_size', 0o664, b'472\n') +f('sys/kernel/slab/kcopyd_job/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/objects', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/order', 0o664, b'1\n') +f('sys/kernel/slab/kcopyd_job/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kcopyd_job/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kcopyd_job/align', 0o664, b'8\n') +f('sys/kernel/slab/kcopyd_job/partial', 0o664, b'0\n') +f('sys/kernel/slab/kcopyd_job/validate', 0o664, b'') +f('sys/kernel/slab/kcopyd_job/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kcopyd_job/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/kcopyd_job/aliases', 0o664, b'0\n') +d('sys/kernel/slab/dm_target_io', 0o775) +f('sys/kernel/slab/dm_target_io/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/ctor', 0o664, b'') +f('sys/kernel/slab/dm_target_io/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/slab_size', 0o664, b'96\n') +f('sys/kernel/slab/dm_target_io/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/slabs', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/poison', 0o664, b'1\n') +f('sys/kernel/slab/dm_target_io/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/dm_target_io/objs_per_slab', 0o664, b'42\n') +f('sys/kernel/slab/dm_target_io/shrink', 0o664, b'') +f('sys/kernel/slab/dm_target_io/trace', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/object_size', 0o664, b'24\n') +f('sys/kernel/slab/dm_target_io/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/objects', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/order', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/dm_target_io/store_user', 0o664, b'1\n') +f('sys/kernel/slab/dm_target_io/align', 0o664, b'8\n') +f('sys/kernel/slab/dm_target_io/partial', 0o664, b'0\n') +f('sys/kernel/slab/dm_target_io/validate', 0o664, b'') +f('sys/kernel/slab/dm_target_io/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/dm_target_io/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/dm_target_io/aliases', 0o664, b'0\n') +d('sys/kernel/slab/signal_cache', 0o775) +f('sys/kernel/slab/signal_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/signal_cache/ctor', 0o664, b'') +f('sys/kernel/slab/signal_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/signal_cache/slab_size', 0o664, b'1024\n') +f('sys/kernel/slab/signal_cache/total_objects', 0o664, b'160\n') +f('sys/kernel/slab/signal_cache/slabs', 0o664, b'10\n') +f('sys/kernel/slab/signal_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/signal_cache/alloc_calls', 0o664, b' 124 copy_process+0x93c/0x1220 age=4145/7851187/8379914 pid=0-12336 cpus=0-1\n') +f('sys/kernel/slab/signal_cache/objs_per_slab', 0o664, b'16\n') +f('sys/kernel/slab/signal_cache/shrink', 0o664, b'') +f('sys/kernel/slab/signal_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/signal_cache/object_size', 0o664, b'896\n') +f('sys/kernel/slab/signal_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/signal_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/signal_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/signal_cache/objects_partial', 0o664, b'70\n') +f('sys/kernel/slab/signal_cache/objects', 0o664, b'150\n') +f('sys/kernel/slab/signal_cache/order', 0o664, b'2\n') +f('sys/kernel/slab/signal_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/signal_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/signal_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/signal_cache/partial', 0o664, b'5\n') +f('sys/kernel/slab/signal_cache/validate', 0o664, b'') +f('sys/kernel/slab/signal_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/signal_cache/free_calls', 0o664, b''' 42 age=4303047259 pid=0 cpus=0 + 82 __cleanup_signal+0x20/0x30 age=7186/7586663/8375843 pid=1-13288 cpus=0-1 +''') +f('sys/kernel/slab/signal_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/radix_tree_node', 0o775) +f('sys/kernel/slab/radix_tree_node/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/radix_tree_node/ctor', 0o664, b'radix_tree_node_ctor+0x0/0x10\n') +f('sys/kernel/slab/radix_tree_node/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/radix_tree_node/slab_size', 0o664, b'624\n') +f('sys/kernel/slab/radix_tree_node/total_objects', 0o664, b'6747\n') +f('sys/kernel/slab/radix_tree_node/slabs', 0o664, b'519\n') +f('sys/kernel/slab/radix_tree_node/poison', 0o664, b'1\n') +f('sys/kernel/slab/radix_tree_node/alloc_calls', 0o664, b' 6737 radix_tree_preload+0x3b/0xb0 age=16/6612251/8379044 pid=1-32767 cpus=0-1\n') +f('sys/kernel/slab/radix_tree_node/objs_per_slab', 0o664, b'13\n') +f('sys/kernel/slab/radix_tree_node/shrink', 0o664, b'') +f('sys/kernel/slab/radix_tree_node/trace', 0o664, b'0\n') +f('sys/kernel/slab/radix_tree_node/object_size', 0o664, b'552\n') +f('sys/kernel/slab/radix_tree_node/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/radix_tree_node/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/radix_tree_node/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/radix_tree_node/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/radix_tree_node/objects', 0o664, b'6747\n') +f('sys/kernel/slab/radix_tree_node/order', 0o664, b'1\n') +f('sys/kernel/slab/radix_tree_node/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/radix_tree_node/store_user', 0o664, b'1\n') +f('sys/kernel/slab/radix_tree_node/align', 0o664, b'0\n') +f('sys/kernel/slab/radix_tree_node/partial', 0o664, b'0\n') +f('sys/kernel/slab/radix_tree_node/validate', 0o664, b'') +f('sys/kernel/slab/radix_tree_node/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/radix_tree_node/free_calls', 0o664, b''' 4146 age=4303047064 pid=0 cpus=0 + 2591 radix_tree_node_rcu_free+0x41/0x50 age=39290/6239072/8378908 pid=0-32584 cpus=0-1 +''') +f('sys/kernel/slab/radix_tree_node/aliases', 0o664, b'0\n') +d('sys/kernel/slab/uid_cache', 0o775) +f('sys/kernel/slab/uid_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/uid_cache/ctor', 0o664, b'') +f('sys/kernel/slab/uid_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/uid_cache/slab_size', 0o664, b'320\n') +f('sys/kernel/slab/uid_cache/total_objects', 0o664, b'24\n') +f('sys/kernel/slab/uid_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/uid_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/uid_cache/alloc_calls', 0o664, b' 5 alloc_uid+0xbd/0x1e0 age=8351086/8358570/8366097 pid=1333-2177 cpus=0-1\n') +f('sys/kernel/slab/uid_cache/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/uid_cache/shrink', 0o664, b'') +f('sys/kernel/slab/uid_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/uid_cache/object_size', 0o664, b'216\n') +f('sys/kernel/slab/uid_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/uid_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/uid_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/uid_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/uid_cache/objects', 0o664, b'24\n') +f('sys/kernel/slab/uid_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/uid_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/uid_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/uid_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/uid_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/uid_cache/validate', 0o664, b'') +f('sys/kernel/slab/uid_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/uid_cache/free_calls', 0o664, b''' 2 age=4303046654 pid=0 cpus=0 + 3 remove_user_sysfs_dir+0xd0/0x100 age=8357175/8367109/8374935 pid=7 cpus=0 +''') +f('sys/kernel/slab/uid_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/tw_sock_TCPv6', 0o775) +f('sys/kernel/slab/tw_sock_TCPv6/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/ctor', 0o664, b'') +f('sys/kernel/slab/tw_sock_TCPv6/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCPv6/slab_size', 0o664, b'256\n') +f('sys/kernel/slab/tw_sock_TCPv6/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/slabs', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/poison', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCPv6/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/tw_sock_TCPv6/objs_per_slab', 0o664, b'16\n') +f('sys/kernel/slab/tw_sock_TCPv6/shrink', 0o664, b'') +f('sys/kernel/slab/tw_sock_TCPv6/trace', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/object_size', 0o664, b'168\n') +f('sys/kernel/slab/tw_sock_TCPv6/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/objects', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/order', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCPv6/store_user', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCPv6/align', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/partial', 0o664, b'0\n') +f('sys/kernel/slab/tw_sock_TCPv6/validate', 0o664, b'') +f('sys/kernel/slab/tw_sock_TCPv6/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/tw_sock_TCPv6/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/tw_sock_TCPv6/aliases', 0o664, b'0\n') +d('sys/kernel/slab/sighand_cache', 0o775) +f('sys/kernel/slab/sighand_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/sighand_cache/ctor', 0o664, b'sighand_ctor+0x0/0x40\n') +f('sys/kernel/slab/sighand_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/sighand_cache/slab_size', 0o664, b'2304\n') +f('sys/kernel/slab/sighand_cache/total_objects', 0o664, b'154\n') +f('sys/kernel/slab/sighand_cache/slabs', 0o664, b'11\n') +f('sys/kernel/slab/sighand_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/sighand_cache/alloc_calls', 0o664, b''' 123 copy_process+0x82a/0x1220 age=4154/7846897/8379923 pid=0-12336 cpus=0-1 + 1 flush_old_exec+0x4e1/0x8a0 age=8378174 pid=1 cpus=0 +''') +f('sys/kernel/slab/sighand_cache/objs_per_slab', 0o664, b'14\n') +f('sys/kernel/slab/sighand_cache/shrink', 0o664, b'') +f('sys/kernel/slab/sighand_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/sighand_cache/object_size', 0o664, b'2184\n') +f('sys/kernel/slab/sighand_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/sighand_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/sighand_cache/destroy_by_rcu', 0o664, b'1\n') +f('sys/kernel/slab/sighand_cache/objects_partial', 0o664, b'61\n') +f('sys/kernel/slab/sighand_cache/objects', 0o664, b'145\n') +f('sys/kernel/slab/sighand_cache/order', 0o664, b'3\n') +f('sys/kernel/slab/sighand_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/sighand_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/sighand_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/sighand_cache/partial', 0o664, b'5\n') +f('sys/kernel/slab/sighand_cache/validate', 0o664, b'') +f('sys/kernel/slab/sighand_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/sighand_cache/free_calls', 0o664, b''' 46 age=4303047268 pid=0 cpus=0 + 78 __cleanup_sighand+0x27/0x30 age=7195/7547046/8375852 pid=1-13288 cpus=0-1 +''') +f('sys/kernel/slab/sighand_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/names_cache', 0o775) +f('sys/kernel/slab/names_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/names_cache/ctor', 0o664, b'') +f('sys/kernel/slab/names_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/names_cache/slab_size', 0o664, b'4224\n') +f('sys/kernel/slab/names_cache/total_objects', 0o664, b'14\n') +f('sys/kernel/slab/names_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/names_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/names_cache/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/names_cache/objs_per_slab', 0o664, b'7\n') +f('sys/kernel/slab/names_cache/shrink', 0o664, b'') +f('sys/kernel/slab/names_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/names_cache/object_size', 0o664, b'4096\n') +f('sys/kernel/slab/names_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/names_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/names_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/names_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/names_cache/objects', 0o664, b'14\n') +f('sys/kernel/slab/names_cache/order', 0o664, b'3\n') +f('sys/kernel/slab/names_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/names_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/names_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/names_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/names_cache/validate', 0o664, b'') +f('sys/kernel/slab/names_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/names_cache/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/names_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/dm_io', 0o775) +f('sys/kernel/slab/dm_io/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/ctor', 0o664, b'') +f('sys/kernel/slab/dm_io/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/slab_size', 0o664, b'104\n') +f('sys/kernel/slab/dm_io/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/slabs', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/poison', 0o664, b'1\n') +f('sys/kernel/slab/dm_io/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/dm_io/objs_per_slab', 0o664, b'39\n') +f('sys/kernel/slab/dm_io/shrink', 0o664, b'') +f('sys/kernel/slab/dm_io/trace', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/object_size', 0o664, b'32\n') +f('sys/kernel/slab/dm_io/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/objects', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/order', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/dm_io/store_user', 0o664, b'1\n') +f('sys/kernel/slab/dm_io/align', 0o664, b'8\n') +f('sys/kernel/slab/dm_io/partial', 0o664, b'0\n') +f('sys/kernel/slab/dm_io/validate', 0o664, b'') +f('sys/kernel/slab/dm_io/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/dm_io/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/dm_io/aliases', 0o664, b'0\n') +d('sys/kernel/slab/key_jar', 0o775) +f('sys/kernel/slab/key_jar/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/ctor', 0o664, b'') +f('sys/kernel/slab/key_jar/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/key_jar/slab_size', 0o664, b'320\n') +f('sys/kernel/slab/key_jar/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/slabs', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/poison', 0o664, b'1\n') +f('sys/kernel/slab/key_jar/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/key_jar/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/key_jar/shrink', 0o664, b'') +f('sys/kernel/slab/key_jar/trace', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/object_size', 0o664, b'232\n') +f('sys/kernel/slab/key_jar/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/objects', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/order', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/key_jar/store_user', 0o664, b'1\n') +f('sys/kernel/slab/key_jar/align', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/partial', 0o664, b'0\n') +f('sys/kernel/slab/key_jar/validate', 0o664, b'') +f('sys/kernel/slab/key_jar/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/key_jar/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/key_jar/aliases', 0o664, b'0\n') +d('sys/kernel/slab/tcp_bind_bucket', 0o775) +f('sys/kernel/slab/tcp_bind_bucket/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/tcp_bind_bucket/ctor', 0o664, b'') +f('sys/kernel/slab/tcp_bind_bucket/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/tcp_bind_bucket/slab_size', 0o664, b'128\n') +f('sys/kernel/slab/tcp_bind_bucket/total_objects', 0o664, b'64\n') +f('sys/kernel/slab/tcp_bind_bucket/slabs', 0o664, b'2\n') +f('sys/kernel/slab/tcp_bind_bucket/poison', 0o664, b'1\n') +f('sys/kernel/slab/tcp_bind_bucket/alloc_calls', 0o664, b' 3 inet_bind_bucket_create+0x27/0x80 age=926731/5878918/8356133 pid=1206-1920 cpus=0\n') +f('sys/kernel/slab/tcp_bind_bucket/objs_per_slab', 0o664, b'32\n') +f('sys/kernel/slab/tcp_bind_bucket/shrink', 0o664, b'') +f('sys/kernel/slab/tcp_bind_bucket/trace', 0o664, b'0\n') +f('sys/kernel/slab/tcp_bind_bucket/object_size', 0o664, b'40\n') +f('sys/kernel/slab/tcp_bind_bucket/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/tcp_bind_bucket/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/tcp_bind_bucket/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/tcp_bind_bucket/objects_partial', 0o664, b'2\n') +f('sys/kernel/slab/tcp_bind_bucket/objects', 0o664, b'34\n') +f('sys/kernel/slab/tcp_bind_bucket/order', 0o664, b'0\n') +f('sys/kernel/slab/tcp_bind_bucket/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/tcp_bind_bucket/store_user', 0o664, b'1\n') +f('sys/kernel/slab/tcp_bind_bucket/align', 0o664, b'0\n') +f('sys/kernel/slab/tcp_bind_bucket/partial', 0o664, b'1\n') +f('sys/kernel/slab/tcp_bind_bucket/validate', 0o664, b'') +f('sys/kernel/slab/tcp_bind_bucket/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/tcp_bind_bucket/free_calls', 0o664, b''' 1 age=4303046680 pid=0 cpus=0 + 2 inet_bind_bucket_destroy+0x29/0x30 age=1107644/4731733/8355822 pid=0-1707 cpus=0 +''') +f('sys/kernel/slab/tcp_bind_bucket/aliases', 0o664, b'0\n') +d('sys/kernel/slab/mm_struct', 0o775) +f('sys/kernel/slab/mm_struct/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/mm_struct/ctor', 0o664, b'') +f('sys/kernel/slab/mm_struct/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/mm_struct/slab_size', 0o664, b'1216\n') +f('sys/kernel/slab/mm_struct/total_objects', 0o664, b'91\n') +f('sys/kernel/slab/mm_struct/slabs', 0o664, b'7\n') +f('sys/kernel/slab/mm_struct/poison', 0o664, b'1\n') +f('sys/kernel/slab/mm_struct/alloc_calls', 0o664, b''' 52 mm_alloc+0x15/0x50 age=4100/7453183/8378125 pid=1-20296 cpus=0-1 + 27 dup_mm+0x61/0x390 age=8335613/8355052/8376513 pid=71-2467 cpus=0-1 +''') +f('sys/kernel/slab/mm_struct/objs_per_slab', 0o664, b'13\n') +f('sys/kernel/slab/mm_struct/shrink', 0o664, b'') +f('sys/kernel/slab/mm_struct/trace', 0o664, b'0\n') +f('sys/kernel/slab/mm_struct/object_size', 0o664, b'1144\n') +f('sys/kernel/slab/mm_struct/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/mm_struct/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/mm_struct/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/mm_struct/objects_partial', 0o664, b'23\n') +f('sys/kernel/slab/mm_struct/objects', 0o664, b'88\n') +f('sys/kernel/slab/mm_struct/order', 0o664, b'2\n') +f('sys/kernel/slab/mm_struct/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/mm_struct/store_user', 0o664, b'1\n') +f('sys/kernel/slab/mm_struct/align', 0o664, b'0\n') +f('sys/kernel/slab/mm_struct/partial', 0o664, b'2\n') +f('sys/kernel/slab/mm_struct/validate', 0o664, b'') +f('sys/kernel/slab/mm_struct/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/mm_struct/free_calls', 0o664, b''' 6 age=4303047216 pid=0 cpus=0 + 73 __mmdrop+0x47/0x60 age=7143/7714522/8376982 pid=1-20295 cpus=0-1 +''') +f('sys/kernel/slab/mm_struct/aliases', 0o664, b'0\n') +d('sys/kernel/slab/dentry', 0o775) +f('sys/kernel/slab/dentry/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/dentry/ctor', 0o664, b'') +f('sys/kernel/slab/dentry/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/dentry/slab_size', 0o664, b'328\n') +f('sys/kernel/slab/dentry/total_objects', 0o664, b'49656\n') +f('sys/kernel/slab/dentry/slabs', 0o664, b'4138\n') +f('sys/kernel/slab/dentry/poison', 0o664, b'1\n') +f('sys/kernel/slab/dentry/alloc_calls', 0o664, b' 49656 d_alloc+0x22/0x1f0 age=0/4250434/8379825 pid=0-32757 cpus=0-1\n') +f('sys/kernel/slab/dentry/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/dentry/shrink', 0o664, b'') +f('sys/kernel/slab/dentry/trace', 0o664, b'0\n') +f('sys/kernel/slab/dentry/object_size', 0o664, b'256\n') +f('sys/kernel/slab/dentry/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/dentry/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/dentry/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/dentry/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/dentry/objects', 0o664, b'49656\n') +f('sys/kernel/slab/dentry/order', 0o664, b'0\n') +f('sys/kernel/slab/dentry/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/dentry/store_user', 0o664, b'1\n') +f('sys/kernel/slab/dentry/align', 0o664, b'8\n') +f('sys/kernel/slab/dentry/partial', 0o664, b'0\n') +f('sys/kernel/slab/dentry/validate', 0o664, b'') +f('sys/kernel/slab/dentry/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/dentry/free_calls', 0o664, b''' 30093 age=4303047137 pid=0 cpus=0 + 2265 d_free+0x6c/0x80 age=519/5532797/8376904 pid=1-32728 cpus=0-1 + 17299 d_callback+0x31/0x40 age=1040/2433896/8379551 pid=0-30210 cpus=0-1 +''') +f('sys/kernel/slab/dentry/aliases', 0o664, b'0\n') +d('sys/kernel/slab/UDPv6', 0o775) +f('sys/kernel/slab/UDPv6/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/UDPv6/ctor', 0o664, b'') +f('sys/kernel/slab/UDPv6/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/UDPv6/slab_size', 0o664, b'1472\n') +f('sys/kernel/slab/UDPv6/total_objects', 0o664, b'22\n') +f('sys/kernel/slab/UDPv6/slabs', 0o664, b'1\n') +f('sys/kernel/slab/UDPv6/poison', 0o664, b'1\n') +f('sys/kernel/slab/UDPv6/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/UDPv6/objs_per_slab', 0o664, b'22\n') +f('sys/kernel/slab/UDPv6/shrink', 0o664, b'') +f('sys/kernel/slab/UDPv6/trace', 0o664, b'0\n') +f('sys/kernel/slab/UDPv6/object_size', 0o664, b'1368\n') +f('sys/kernel/slab/UDPv6/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/UDPv6/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/UDPv6/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/UDPv6/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/UDPv6/objects', 0o664, b'22\n') +f('sys/kernel/slab/UDPv6/order', 0o664, b'3\n') +f('sys/kernel/slab/UDPv6/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/UDPv6/store_user', 0o664, b'1\n') +f('sys/kernel/slab/UDPv6/align', 0o664, b'0\n') +f('sys/kernel/slab/UDPv6/partial', 0o664, b'0\n') +f('sys/kernel/slab/UDPv6/validate', 0o664, b'') +f('sys/kernel/slab/UDPv6/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/UDPv6/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/UDPv6/aliases', 0o664, b'0\n') +d('sys/kernel/slab/mqueue_inode_cache', 0o775) +f('sys/kernel/slab/mqueue_inode_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/mqueue_inode_cache/ctor', 0o664, b'init_once+0x0/0x10\n') +f('sys/kernel/slab/mqueue_inode_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/mqueue_inode_cache/slab_size', 0o664, b'1536\n') +f('sys/kernel/slab/mqueue_inode_cache/total_objects', 0o664, b'21\n') +f('sys/kernel/slab/mqueue_inode_cache/slabs', 0o664, b'1\n') +f('sys/kernel/slab/mqueue_inode_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/mqueue_inode_cache/alloc_calls', 0o664, b' 1 mqueue_alloc_inode+0x15/0x30 age=8380010 pid=1 cpus=1\n') +f('sys/kernel/slab/mqueue_inode_cache/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/mqueue_inode_cache/shrink', 0o664, b'') +f('sys/kernel/slab/mqueue_inode_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/mqueue_inode_cache/object_size', 0o664, b'1456\n') +f('sys/kernel/slab/mqueue_inode_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/mqueue_inode_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/mqueue_inode_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/mqueue_inode_cache/objects_partial', 0o664, b'1\n') +f('sys/kernel/slab/mqueue_inode_cache/objects', 0o664, b'1\n') +f('sys/kernel/slab/mqueue_inode_cache/order', 0o664, b'3\n') +f('sys/kernel/slab/mqueue_inode_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/mqueue_inode_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/mqueue_inode_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/mqueue_inode_cache/partial', 0o664, b'1\n') +f('sys/kernel/slab/mqueue_inode_cache/validate', 0o664, b'') +f('sys/kernel/slab/mqueue_inode_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/mqueue_inode_cache/free_calls', 0o664, b' 1 age=4303047603 pid=0 cpus=0\n') +f('sys/kernel/slab/mqueue_inode_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/biovec-128', 0o775) +f('sys/kernel/slab/biovec-128/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/biovec-128/ctor', 0o664, b'') +f('sys/kernel/slab/biovec-128/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/biovec-128/slab_size', 0o664, b'2176\n') +f('sys/kernel/slab/biovec-128/total_objects', 0o664, b'15\n') +f('sys/kernel/slab/biovec-128/slabs', 0o664, b'1\n') +f('sys/kernel/slab/biovec-128/poison', 0o664, b'1\n') +f('sys/kernel/slab/biovec-128/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379474/8379474/8379474 pid=1 cpus=0\n') +f('sys/kernel/slab/biovec-128/objs_per_slab', 0o664, b'15\n') +f('sys/kernel/slab/biovec-128/shrink', 0o664, b'') +f('sys/kernel/slab/biovec-128/trace', 0o664, b'0\n') +f('sys/kernel/slab/biovec-128/object_size', 0o664, b'2048\n') +f('sys/kernel/slab/biovec-128/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/biovec-128/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/biovec-128/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/biovec-128/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/biovec-128/objects', 0o664, b'15\n') +f('sys/kernel/slab/biovec-128/order', 0o664, b'3\n') +f('sys/kernel/slab/biovec-128/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/biovec-128/store_user', 0o664, b'1\n') +f('sys/kernel/slab/biovec-128/align', 0o664, b'0\n') +f('sys/kernel/slab/biovec-128/partial', 0o664, b'0\n') +f('sys/kernel/slab/biovec-128/validate', 0o664, b'') +f('sys/kernel/slab/biovec-128/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/biovec-128/free_calls', 0o664, b' 2 age=4303046908 pid=0 cpus=0\n') +f('sys/kernel/slab/biovec-128/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-192', 0o775) +f('sys/kernel/slab/kmalloc-192/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-192/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-192/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-192/slab_size', 0o664, b'264\n') +f('sys/kernel/slab/kmalloc-192/total_objects', 0o664, b'255\n') +f('sys/kernel/slab/kmalloc-192/slabs', 0o664, b'17\n') +f('sys/kernel/slab/kmalloc-192/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-192/alloc_calls', 0o664, b''' 10 sched_create_group+0x91/0x220 age=8351861/8359345/8366872 pid=1333-2177 cpus=0-1 + 10 sched_create_group+0xae/0x220 age=8351861/8359345/8366872 pid=1333-2177 cpus=0-1 + 10 groups_alloc+0x41/0xe0 age=17070/6159814/8366872 pid=1333-20296 cpus=0-1 + 9 param_sysfs_setup+0x87/0x140 age=8303102/8368759/8379996 pid=1-2754 cpus=0-1 + 2 futex_lock_pi+0x776/0xb00 age=125614/1986240/3846867 pid=2411-13213 cpus=0-1 + 18 mempool_create_node+0x2e/0xf0 age=62077/7917175/8379995 pid=1-13295 cpus=0-1 + 4 __vmalloc_area_node+0xfb/0x140 age=8370390/8373664/8374956 pid=107-901 cpus=0 + 30 __percpu_alloc_mask+0xbc/0x140 age=8370400/8377809/8380000 pid=1-900 cpus=0-1 + 4 d_alloc+0x19d/0x1f0 age=61160/6282991/8356935 pid=1706-13349 cpus=0-1 + 1 bm_register_write+0x63/0x630 age=8354110 pid=2054 cpus=1 + 1 sysfs_open_file+0xd6/0x230 age=0 pid=13466 cpus=0 + 15 ipc_rcu_alloc+0x4a/0x70 age=8274192/8330064/8348647 pid=2177-2621 cpus=0-1 + 28 kset_create_and_add+0x35/0xa0 age=8355999/8378311/8380000 pid=1-1766 cpus=0-1 + 1 acpi_ds_build_internal_package_obj+0xaf/0x1df age=8379979 pid=1 cpus=0 + 3 acpi_ds_build_internal_buffer_obj+0xe1/0x121 age=8379976/8379976/8379977 pid=1 cpus=0 + 1 acpi_power_add+0x4a/0x1d6 age=8379890 pid=1 cpus=0 + 2 ata_host_alloc+0x4f/0xf0 age=8379280/8379538/8379796 pid=1 cpus=0-1 + 8 cpuidle_add_state_sysfs+0xc3/0x140 age=125753/125759/125766 pid=13 cpus=0-1 + 1 hid_parse_report+0x43/0x2c0 age=53560 pid=419 cpus=0 + 2 hid_add_field+0x18a/0x3a0 age=53560/53560/53560 pid=419 cpus=0 + 6 fib_create_info+0x61/0x970 age=8324536/8346547/8367903 pid=1197-1541 cpus=0-1 + 1 unix_sysctl_register+0x2a/0x80 age=8379847 pid=1 cpus=0 + 1 rtnetlink_init+0x38/0x113 age=8379999 pid=1 cpus=0 + 1 inet_diag_init+0x15/0x6b age=8378998 pid=1 cpus=0 + 41 usb_alloc_urb+0x19/0x50 [usbcore] age=22746/1043846/8374920 pid=143-419 cpus=0-1 + 1 usb_get_configuration+0x5f2/0x1480 [usbcore] age=22753 pid=419 cpus=0 + 2 usb_get_configuration+0x1388/0x1480 [usbcore] age=8372394/8372581/8372769 pid=419 cpus=0 + 1 sr_probe+0x76/0x540 [sr_mod] age=8375854 pid=163 cpus=0 + 18 snd_ctl_new+0x28/0x90 [snd] age=8374174/8374174/8374174 pid=107 cpus=1 + 1 iwl3945_pci_probe+0xd3f/0x1020 [iwl3945] age=8373796 pid=126 cpus=1 + 1 blkcipher_walk_next+0x29c/0x390 [crypto_blkcipher] age=8374562 pid=215 cpus=1 + 3 dm_register_target+0x1f/0xf0 [dm_mod] age=8370400/8370400/8370401 pid=900 cpus=0 + 1 ipv6_icmp_sysctl_init+0x22/0x40 [ipv6] age=8360202 pid=1549 cpus=0 + 1 snd_seq_pool_new+0x1b/0x80 [snd_seq] age=8355636 pid=1805 cpus=0 +''') +f('sys/kernel/slab/kmalloc-192/objs_per_slab', 0o664, b'15\n') +f('sys/kernel/slab/kmalloc-192/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-192/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-192/object_size', 0o664, b'192\n') +f('sys/kernel/slab/kmalloc-192/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-192/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-192/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-192/objects_partial', 0o664, b'14\n') +f('sys/kernel/slab/kmalloc-192/objects', 0o664, b'254\n') +f('sys/kernel/slab/kmalloc-192/order', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-192/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-192/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-192/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-192/partial', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-192/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-192/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-192/free_calls', 0o664, b''' 149 age=4303047430 pid=0 cpus=0 + 5 free_sched_group+0x3b/0x80 age=363179/6767246/8375130 pid=0-1614 cpus=0-1 + 1 free_sched_group+0x50/0x80 age=8369988 pid=0 cpus=0 + 1 do_exit+0x713/0x960 age=8333169 pid=2558 cpus=1 + 7 groups_free+0x56/0x60 age=17071/4081875/8369994 pid=0-1690 cpus=0-1 + 1 __vunmap+0xe9/0x120 age=8356237 pid=1748 cpus=1 + 1 do_readv_writev+0xe4/0x1e0 age=8331191 pid=2262 cpus=0 + 4 getxattr+0x8c/0x140 age=0/6266155/8357946 pid=1610-13466 cpus=0-1 + 20 sysfs_release+0x7c/0xa0 age=53608/7118781/8376453 pid=226-2519 cpus=0-1 + 1 ipc_immediate_free+0x9/0x10 age=8330259 pid=2568 cpus=0 + 1 acpi_pci_irq_add_prt+0x30b/0x324 age=8379911 pid=1 cpus=0 + 6 cpuidle_remove_state_sysfs+0x4f/0x70 age=125768/1366349/3847513 pid=13 cpus=0 + 4 free_fib_info+0x34/0x60 age=8367904/8367909/8367920 pid=1185-1197 cpus=0-1 + 36 urb_destroy+0x23/0x30 [usbcore] age=22749/2596918/8374921 pid=143-13294 cpus=0-1 + 1 sg_clean+0x3e/0x80 [usbcore] age=61399 pid=13294 cpus=0 + 1 0xffffffffa006521f age=8355637 pid=1805 cpus=0 +''') +f('sys/kernel/slab/kmalloc-192/aliases', 0o664, b'0\n') +d('sys/kernel/slab/task_struct', 0o775) +f('sys/kernel/slab/task_struct/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/task_struct/ctor', 0o664, b'') +f('sys/kernel/slab/task_struct/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/task_struct/slab_size', 0o664, b'4400\n') +f('sys/kernel/slab/task_struct/total_objects', 0o664, b'224\n') +f('sys/kernel/slab/task_struct/slabs', 0o664, b'32\n') +f('sys/kernel/slab/task_struct/poison', 0o664, b'1\n') +f('sys/kernel/slab/task_struct/alloc_calls', 0o664, b' 203 copy_process+0xa4/0x1220 age=4172/8008848/8379941 pid=0-13212 cpus=0-1\n') +f('sys/kernel/slab/task_struct/objs_per_slab', 0o664, b'7\n') +f('sys/kernel/slab/task_struct/shrink', 0o664, b'') +f('sys/kernel/slab/task_struct/trace', 0o664, b'0\n') +f('sys/kernel/slab/task_struct/object_size', 0o664, b'4320\n') +f('sys/kernel/slab/task_struct/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/task_struct/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/task_struct/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/task_struct/objects_partial', 0o664, b'57\n') +f('sys/kernel/slab/task_struct/objects', 0o664, b'211\n') +f('sys/kernel/slab/task_struct/order', 0o664, b'3\n') +f('sys/kernel/slab/task_struct/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/task_struct/store_user', 0o664, b'1\n') +f('sys/kernel/slab/task_struct/align', 0o664, b'16\n') +f('sys/kernel/slab/task_struct/partial', 0o664, b'10\n') +f('sys/kernel/slab/task_struct/validate', 0o664, b'') +f('sys/kernel/slab/task_struct/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/task_struct/free_calls', 0o664, b''' 93 age=4303047286 pid=0 cpus=0 + 110 free_task+0x30/0x40 age=7208/7706854/8377050 pid=0-13258 cpus=0-1 +''') +f('sys/kernel/slab/task_struct/aliases', 0o664, b'0\n') +d('sys/kernel/slab/sgpool-16', 0o775) +f('sys/kernel/slab/sgpool-16/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-16/ctor', 0o664, b'') +f('sys/kernel/slab/sgpool-16/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-16/slab_size', 0o664, b'640\n') +f('sys/kernel/slab/sgpool-16/total_objects', 0o664, b'24\n') +f('sys/kernel/slab/sgpool-16/slabs', 0o664, b'2\n') +f('sys/kernel/slab/sgpool-16/poison', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-16/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379289/8379289/8379289 pid=1 cpus=0\n') +f('sys/kernel/slab/sgpool-16/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/sgpool-16/shrink', 0o664, b'') +f('sys/kernel/slab/sgpool-16/trace', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-16/object_size', 0o664, b'512\n') +f('sys/kernel/slab/sgpool-16/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-16/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-16/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-16/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-16/objects', 0o664, b'24\n') +f('sys/kernel/slab/sgpool-16/order', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-16/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-16/store_user', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-16/align', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-16/partial', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-16/validate', 0o664, b'') +f('sys/kernel/slab/sgpool-16/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-16/free_calls', 0o664, b' 2 age=4303046838 pid=0 cpus=0\n') +f('sys/kernel/slab/sgpool-16/aliases', 0o664, b'0\n') +d('sys/kernel/slab/request_sock_TCPv6', 0o775) +f('sys/kernel/slab/request_sock_TCPv6/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/ctor', 0o664, b'') +f('sys/kernel/slab/request_sock_TCPv6/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/request_sock_TCPv6/slab_size', 0o664, b'256\n') +f('sys/kernel/slab/request_sock_TCPv6/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/slabs', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/poison', 0o664, b'1\n') +f('sys/kernel/slab/request_sock_TCPv6/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/request_sock_TCPv6/objs_per_slab', 0o664, b'16\n') +f('sys/kernel/slab/request_sock_TCPv6/shrink', 0o664, b'') +f('sys/kernel/slab/request_sock_TCPv6/trace', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/object_size', 0o664, b'136\n') +f('sys/kernel/slab/request_sock_TCPv6/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/objects', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/order', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/request_sock_TCPv6/store_user', 0o664, b'1\n') +f('sys/kernel/slab/request_sock_TCPv6/align', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/partial', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCPv6/validate', 0o664, b'') +f('sys/kernel/slab/request_sock_TCPv6/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/request_sock_TCPv6/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/request_sock_TCPv6/aliases', 0o664, b'0\n') +d('sys/kernel/slab/Acpi-Namespace', 0o775) +f('sys/kernel/slab/Acpi-Namespace/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Namespace/ctor', 0o664, b'') +f('sys/kernel/slab/Acpi-Namespace/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Namespace/slab_size', 0o664, b'104\n') +f('sys/kernel/slab/Acpi-Namespace/total_objects', 0o664, b'1755\n') +f('sys/kernel/slab/Acpi-Namespace/slabs', 0o664, b'45\n') +f('sys/kernel/slab/Acpi-Namespace/poison', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Namespace/alloc_calls', 0o664, b' 1709 acpi_ns_create_node+0x34/0x45 age=8375345/8379655/8379737 pid=0-330 cpus=0\n') +f('sys/kernel/slab/Acpi-Namespace/objs_per_slab', 0o664, b'39\n') +f('sys/kernel/slab/Acpi-Namespace/shrink', 0o664, b'') +f('sys/kernel/slab/Acpi-Namespace/trace', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Namespace/object_size', 0o664, b'32\n') +f('sys/kernel/slab/Acpi-Namespace/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Namespace/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Namespace/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Namespace/objects_partial', 0o664, b'32\n') +f('sys/kernel/slab/Acpi-Namespace/objects', 0o664, b'1709\n') +f('sys/kernel/slab/Acpi-Namespace/order', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Namespace/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Namespace/store_user', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Namespace/align', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Namespace/partial', 0o664, b'2\n') +f('sys/kernel/slab/Acpi-Namespace/validate', 0o664, b'') +f('sys/kernel/slab/Acpi-Namespace/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Namespace/free_calls', 0o664, b' 1709 age=4303047034 pid=0 cpus=0\n') +f('sys/kernel/slab/Acpi-Namespace/aliases', 0o664, b'0\n') +d('sys/kernel/slab/posix_timers_cache', 0o775) +f('sys/kernel/slab/posix_timers_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/ctor', 0o664, b'') +f('sys/kernel/slab/posix_timers_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/slab_size', 0o664, b'320\n') +f('sys/kernel/slab/posix_timers_cache/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/slabs', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/posix_timers_cache/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/posix_timers_cache/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/posix_timers_cache/shrink', 0o664, b'') +f('sys/kernel/slab/posix_timers_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/object_size', 0o664, b'248\n') +f('sys/kernel/slab/posix_timers_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/objects', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/posix_timers_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/posix_timers_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/posix_timers_cache/validate', 0o664, b'') +f('sys/kernel/slab/posix_timers_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/posix_timers_cache/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/posix_timers_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/scsi_cmd_cache', 0o775) +f('sys/kernel/slab/scsi_cmd_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/scsi_cmd_cache/ctor', 0o664, b'') +f('sys/kernel/slab/scsi_cmd_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/scsi_cmd_cache/slab_size', 0o664, b'448\n') +f('sys/kernel/slab/scsi_cmd_cache/total_objects', 0o664, b'36\n') +f('sys/kernel/slab/scsi_cmd_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/scsi_cmd_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/scsi_cmd_cache/alloc_calls', 0o664, b' 7 scsi_pool_alloc_command+0x25/0x80 age=67290/7192324/8380005 pid=1-419 cpus=0-1\n') +f('sys/kernel/slab/scsi_cmd_cache/objs_per_slab', 0o664, b'18\n') +f('sys/kernel/slab/scsi_cmd_cache/shrink', 0o664, b'') +f('sys/kernel/slab/scsi_cmd_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/scsi_cmd_cache/object_size', 0o664, b'320\n') +f('sys/kernel/slab/scsi_cmd_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/scsi_cmd_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/scsi_cmd_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/scsi_cmd_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/scsi_cmd_cache/objects', 0o664, b'36\n') +f('sys/kernel/slab/scsi_cmd_cache/order', 0o664, b'1\n') +f('sys/kernel/slab/scsi_cmd_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/scsi_cmd_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/scsi_cmd_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/scsi_cmd_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/scsi_cmd_cache/validate', 0o664, b'') +f('sys/kernel/slab/scsi_cmd_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/scsi_cmd_cache/free_calls', 0o664, b''' 5 age=4303047639 pid=0 cpus=0 + 2 scsi_pool_free_command+0x4c/0x60 age=67789/4223648/8379508 pid=0 cpus=0 +''') +f('sys/kernel/slab/scsi_cmd_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/eventpoll_pwq', 0o775) +f('sys/kernel/slab/eventpoll_pwq/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_pwq/ctor', 0o664, b'') +f('sys/kernel/slab/eventpoll_pwq/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_pwq/slab_size', 0o664, b'144\n') +f('sys/kernel/slab/eventpoll_pwq/total_objects', 0o664, b'112\n') +f('sys/kernel/slab/eventpoll_pwq/slabs', 0o664, b'4\n') +f('sys/kernel/slab/eventpoll_pwq/poison', 0o664, b'1\n') +f('sys/kernel/slab/eventpoll_pwq/alloc_calls', 0o664, b' 65 ep_ptable_queue_proc+0x35/0xa0 age=2416434/8173328/8356246 pid=1690-20296 cpus=0-1\n') +f('sys/kernel/slab/eventpoll_pwq/objs_per_slab', 0o664, b'28\n') +f('sys/kernel/slab/eventpoll_pwq/shrink', 0o664, b'') +f('sys/kernel/slab/eventpoll_pwq/trace', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_pwq/object_size', 0o664, b'72\n') +f('sys/kernel/slab/eventpoll_pwq/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_pwq/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_pwq/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_pwq/objects_partial', 0o664, b'7\n') +f('sys/kernel/slab/eventpoll_pwq/objects', 0o664, b'91\n') +f('sys/kernel/slab/eventpoll_pwq/order', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_pwq/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/eventpoll_pwq/store_user', 0o664, b'1\n') +f('sys/kernel/slab/eventpoll_pwq/align', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_pwq/partial', 0o664, b'1\n') +f('sys/kernel/slab/eventpoll_pwq/validate', 0o664, b'') +f('sys/kernel/slab/eventpoll_pwq/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/eventpoll_pwq/free_calls', 0o664, b''' 61 age=4303046794 pid=0 cpus=0 + 4 ep_unregister_pollwait+0x61/0x80 age=2416452/6864185/8356241 pid=1690-2073 cpus=0-1 +''') +f('sys/kernel/slab/eventpoll_pwq/aliases', 0o664, b'0\n') +d('sys/kernel/slab/journal_handle', 0o775) +f('sys/kernel/slab/journal_handle/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/journal_handle/ctor', 0o664, b'') +f('sys/kernel/slab/journal_handle/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/journal_handle/slab_size', 0o664, b'128\n') +f('sys/kernel/slab/journal_handle/total_objects', 0o664, b'64\n') +f('sys/kernel/slab/journal_handle/slabs', 0o664, b'2\n') +f('sys/kernel/slab/journal_handle/poison', 0o664, b'1\n') +f('sys/kernel/slab/journal_handle/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/journal_handle/objs_per_slab', 0o664, b'32\n') +f('sys/kernel/slab/journal_handle/shrink', 0o664, b'') +f('sys/kernel/slab/journal_handle/trace', 0o664, b'0\n') +f('sys/kernel/slab/journal_handle/object_size', 0o664, b'56\n') +f('sys/kernel/slab/journal_handle/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/journal_handle/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/journal_handle/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/journal_handle/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/journal_handle/objects', 0o664, b'64\n') +f('sys/kernel/slab/journal_handle/order', 0o664, b'0\n') +f('sys/kernel/slab/journal_handle/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/journal_handle/store_user', 0o664, b'1\n') +f('sys/kernel/slab/journal_handle/align', 0o664, b'0\n') +f('sys/kernel/slab/journal_handle/partial', 0o664, b'0\n') +f('sys/kernel/slab/journal_handle/validate', 0o664, b'') +f('sys/kernel/slab/journal_handle/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/journal_handle/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/journal_handle/aliases', 0o664, b'0\n') +d('sys/kernel/slab/bsg_cmd', 0o775) +f('sys/kernel/slab/bsg_cmd/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/ctor', 0o664, b'') +f('sys/kernel/slab/bsg_cmd/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/slab_size', 0o664, b'384\n') +f('sys/kernel/slab/bsg_cmd/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/slabs', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/poison', 0o664, b'1\n') +f('sys/kernel/slab/bsg_cmd/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/bsg_cmd/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/bsg_cmd/shrink', 0o664, b'') +f('sys/kernel/slab/bsg_cmd/trace', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/object_size', 0o664, b'312\n') +f('sys/kernel/slab/bsg_cmd/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/objects', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/order', 0o664, b'1\n') +f('sys/kernel/slab/bsg_cmd/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/bsg_cmd/store_user', 0o664, b'1\n') +f('sys/kernel/slab/bsg_cmd/align', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/partial', 0o664, b'0\n') +f('sys/kernel/slab/bsg_cmd/validate', 0o664, b'') +f('sys/kernel/slab/bsg_cmd/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/bsg_cmd/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/bsg_cmd/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kiocb', 0o775) +f('sys/kernel/slab/kiocb/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/ctor', 0o664, b'') +f('sys/kernel/slab/kiocb/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/kiocb/slab_size', 0o664, b'320\n') +f('sys/kernel/slab/kiocb/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/slabs', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/poison', 0o664, b'1\n') +f('sys/kernel/slab/kiocb/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/kiocb/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/kiocb/shrink', 0o664, b'') +f('sys/kernel/slab/kiocb/trace', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/object_size', 0o664, b'240\n') +f('sys/kernel/slab/kiocb/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/objects', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/order', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kiocb/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kiocb/align', 0o664, b'8\n') +f('sys/kernel/slab/kiocb/partial', 0o664, b'0\n') +f('sys/kernel/slab/kiocb/validate', 0o664, b'') +f('sys/kernel/slab/kiocb/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kiocb/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/kiocb/aliases', 0o664, b'0\n') +d('sys/kernel/slab/file_lock_cache', 0o775) +f('sys/kernel/slab/file_lock_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/file_lock_cache/ctor', 0o664, b'init_once+0x0/0x10\n') +f('sys/kernel/slab/file_lock_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/file_lock_cache/slab_size', 0o664, b'296\n') +f('sys/kernel/slab/file_lock_cache/total_objects', 0o664, b'26\n') +f('sys/kernel/slab/file_lock_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/file_lock_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/file_lock_cache/alloc_calls', 0o664, b''' 2 flock_lock_file_wait+0x2d6/0x2f0 age=8355055/8355767/8356479 pid=1690-1807 cpus=0 + 1 __posix_lock_file+0x3f/0x560 age=8349601 pid=2262 cpus=0 +''') +f('sys/kernel/slab/file_lock_cache/objs_per_slab', 0o664, b'13\n') +f('sys/kernel/slab/file_lock_cache/shrink', 0o664, b'') +f('sys/kernel/slab/file_lock_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/file_lock_cache/object_size', 0o664, b'224\n') +f('sys/kernel/slab/file_lock_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/file_lock_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/file_lock_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/file_lock_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/file_lock_cache/objects', 0o664, b'26\n') +f('sys/kernel/slab/file_lock_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/file_lock_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/file_lock_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/file_lock_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/file_lock_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/file_lock_cache/validate', 0o664, b'') +f('sys/kernel/slab/file_lock_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/file_lock_cache/free_calls', 0o664, b' 3 locks_free_lock+0x3e/0x60 age=8351291/8355422/8359832 pid=1549-2189 cpus=0\n') +f('sys/kernel/slab/file_lock_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/inet_peer_cache', 0o775) +f('sys/kernel/slab/inet_peer_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/ctor', 0o664, b'') +f('sys/kernel/slab/inet_peer_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/inet_peer_cache/slab_size', 0o664, b'192\n') +f('sys/kernel/slab/inet_peer_cache/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/slabs', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/inet_peer_cache/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/inet_peer_cache/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/inet_peer_cache/shrink', 0o664, b'') +f('sys/kernel/slab/inet_peer_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/object_size', 0o664, b'64\n') +f('sys/kernel/slab/inet_peer_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/objects', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/inet_peer_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/inet_peer_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/inet_peer_cache/validate', 0o664, b'') +f('sys/kernel/slab/inet_peer_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/inet_peer_cache/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/inet_peer_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/arp_cache', 0o775) +f('sys/kernel/slab/arp_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/arp_cache/ctor', 0o664, b'') +f('sys/kernel/slab/arp_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/arp_cache/slab_size', 0o664, b'448\n') +f('sys/kernel/slab/arp_cache/total_objects', 0o664, b'36\n') +f('sys/kernel/slab/arp_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/arp_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/arp_cache/alloc_calls', 0o664, b' 1 neigh_create+0x8b/0x530 age=1133499 pid=952 cpus=0\n') +f('sys/kernel/slab/arp_cache/objs_per_slab', 0o664, b'18\n') +f('sys/kernel/slab/arp_cache/shrink', 0o664, b'') +f('sys/kernel/slab/arp_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/arp_cache/object_size', 0o664, b'348\n') +f('sys/kernel/slab/arp_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/arp_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/arp_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/arp_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/arp_cache/objects', 0o664, b'36\n') +f('sys/kernel/slab/arp_cache/order', 0o664, b'1\n') +f('sys/kernel/slab/arp_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/arp_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/arp_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/arp_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/arp_cache/validate', 0o664, b'') +f('sys/kernel/slab/arp_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/arp_cache/free_calls', 0o664, b' 1 neigh_destroy+0x10c/0x160 age=1135741 pid=0 cpus=0\n') +f('sys/kernel/slab/arp_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/biovec-4', 0o775) +f('sys/kernel/slab/biovec-4/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/biovec-4/ctor', 0o664, b'') +f('sys/kernel/slab/biovec-4/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/biovec-4/slab_size', 0o664, b'192\n') +f('sys/kernel/slab/biovec-4/total_objects', 0o664, b'42\n') +f('sys/kernel/slab/biovec-4/slabs', 0o664, b'2\n') +f('sys/kernel/slab/biovec-4/poison', 0o664, b'1\n') +f('sys/kernel/slab/biovec-4/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379500/8379500/8379500 pid=1 cpus=0\n') +f('sys/kernel/slab/biovec-4/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/biovec-4/shrink', 0o664, b'') +f('sys/kernel/slab/biovec-4/trace', 0o664, b'0\n') +f('sys/kernel/slab/biovec-4/object_size', 0o664, b'64\n') +f('sys/kernel/slab/biovec-4/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/biovec-4/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/biovec-4/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/biovec-4/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/biovec-4/objects', 0o664, b'42\n') +f('sys/kernel/slab/biovec-4/order', 0o664, b'0\n') +f('sys/kernel/slab/biovec-4/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/biovec-4/store_user', 0o664, b'1\n') +f('sys/kernel/slab/biovec-4/align', 0o664, b'0\n') +f('sys/kernel/slab/biovec-4/partial', 0o664, b'0\n') +f('sys/kernel/slab/biovec-4/validate', 0o664, b'') +f('sys/kernel/slab/biovec-4/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/biovec-4/free_calls', 0o664, b' 2 age=4303046934 pid=0 cpus=0\n') +f('sys/kernel/slab/biovec-4/aliases', 0o664, b'0\n') +d('sys/kernel/slab/scsi_sense_cache', 0o775) +f('sys/kernel/slab/scsi_sense_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/scsi_sense_cache/ctor', 0o664, b'') +f('sys/kernel/slab/scsi_sense_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/scsi_sense_cache/slab_size', 0o664, b'192\n') +f('sys/kernel/slab/scsi_sense_cache/total_objects', 0o664, b'42\n') +f('sys/kernel/slab/scsi_sense_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/scsi_sense_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/scsi_sense_cache/alloc_calls', 0o664, b' 7 scsi_pool_alloc_command+0x4a/0x80 age=67299/7192333/8380014 pid=1-419 cpus=0-1\n') +f('sys/kernel/slab/scsi_sense_cache/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/scsi_sense_cache/shrink', 0o664, b'') +f('sys/kernel/slab/scsi_sense_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/scsi_sense_cache/object_size', 0o664, b'96\n') +f('sys/kernel/slab/scsi_sense_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/scsi_sense_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/scsi_sense_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/scsi_sense_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/scsi_sense_cache/objects', 0o664, b'42\n') +f('sys/kernel/slab/scsi_sense_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/scsi_sense_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/scsi_sense_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/scsi_sense_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/scsi_sense_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/scsi_sense_cache/validate', 0o664, b'') +f('sys/kernel/slab/scsi_sense_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/scsi_sense_cache/free_calls', 0o664, b''' 5 age=4303047648 pid=0 cpus=0 + 2 scsi_pool_free_command+0x40/0x60 age=67798/4223657/8379517 pid=0 cpus=0 +''') +f('sys/kernel/slab/scsi_sense_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/cfq_io_context', 0o775) +f('sys/kernel/slab/cfq_io_context/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/cfq_io_context/ctor', 0o664, b'') +f('sys/kernel/slab/cfq_io_context/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/cfq_io_context/slab_size', 0o664, b'240\n') +f('sys/kernel/slab/cfq_io_context/total_objects', 0o664, b'85\n') +f('sys/kernel/slab/cfq_io_context/slabs', 0o664, b'5\n') +f('sys/kernel/slab/cfq_io_context/poison', 0o664, b'1\n') +f('sys/kernel/slab/cfq_io_context/alloc_calls', 0o664, b' 69 cfq_set_request+0x13d/0x390 age=177/7837888/8379613 pid=1-13466 cpus=0-1\n') +f('sys/kernel/slab/cfq_io_context/objs_per_slab', 0o664, b'17\n') +f('sys/kernel/slab/cfq_io_context/shrink', 0o664, b'') +f('sys/kernel/slab/cfq_io_context/trace', 0o664, b'0\n') +f('sys/kernel/slab/cfq_io_context/object_size', 0o664, b'168\n') +f('sys/kernel/slab/cfq_io_context/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/cfq_io_context/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/cfq_io_context/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/cfq_io_context/objects_partial', 0o664, b'16\n') +f('sys/kernel/slab/cfq_io_context/objects', 0o664, b'84\n') +f('sys/kernel/slab/cfq_io_context/order', 0o664, b'0\n') +f('sys/kernel/slab/cfq_io_context/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/cfq_io_context/store_user', 0o664, b'1\n') +f('sys/kernel/slab/cfq_io_context/align', 0o664, b'8\n') +f('sys/kernel/slab/cfq_io_context/partial', 0o664, b'1\n') +f('sys/kernel/slab/cfq_io_context/validate', 0o664, b'') +f('sys/kernel/slab/cfq_io_context/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/cfq_io_context/free_calls', 0o664, b''' 12 age=4303047630 pid=0 cpus=0 + 57 cfq_cic_free_rcu+0x21/0xc0 age=61842/7747595/8376055 pid=0-2535 cpus=0-1 +''') +f('sys/kernel/slab/cfq_io_context/aliases', 0o664, b'0\n') +d('sys/kernel/slab/idr_layer_cache', 0o775) +f('sys/kernel/slab/idr_layer_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/idr_layer_cache/ctor', 0o664, b'idr_cache_ctor+0x0/0x10\n') +f('sys/kernel/slab/idr_layer_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/idr_layer_cache/slab_size', 0o664, b'616\n') +f('sys/kernel/slab/idr_layer_cache/total_objects', 0o664, b'442\n') +f('sys/kernel/slab/idr_layer_cache/slabs', 0o664, b'34\n') +f('sys/kernel/slab/idr_layer_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/idr_layer_cache/alloc_calls', 0o664, b' 406 idr_pre_get+0x5d/0x80 age=60336/8278969/8380018 pid=0-13355 cpus=0-1\n') +f('sys/kernel/slab/idr_layer_cache/objs_per_slab', 0o664, b'13\n') +f('sys/kernel/slab/idr_layer_cache/shrink', 0o664, b'') +f('sys/kernel/slab/idr_layer_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/idr_layer_cache/object_size', 0o664, b'544\n') +f('sys/kernel/slab/idr_layer_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/idr_layer_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/idr_layer_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/idr_layer_cache/objects_partial', 0o664, b'82\n') +f('sys/kernel/slab/idr_layer_cache/objects', 0o664, b'420\n') +f('sys/kernel/slab/idr_layer_cache/order', 0o664, b'1\n') +f('sys/kernel/slab/idr_layer_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/idr_layer_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/idr_layer_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/idr_layer_cache/partial', 0o664, b'8\n') +f('sys/kernel/slab/idr_layer_cache/validate', 0o664, b'') +f('sys/kernel/slab/idr_layer_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/idr_layer_cache/free_calls', 0o664, b''' 304 age=4303047315 pid=0 cpus=0 + 3 idr_destroy+0x2f/0x40 age=104486/3178486/4715486 pid=13211-13803 cpus=0-1 + 4 idr_layer_rcu_free+0x17/0x20 age=8334501/8362397/8377168 pid=0-1155 cpus=0-1 + 95 ida_get_new_above+0x141/0x210 age=812584/8292482/8380019 pid=0-2593 cpus=0-1 +''') +f('sys/kernel/slab/idr_layer_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/vm_area_struct', 0o775) +f('sys/kernel/slab/vm_area_struct/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/vm_area_struct/ctor', 0o664, b'') +f('sys/kernel/slab/vm_area_struct/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/vm_area_struct/slab_size', 0o664, b'240\n') +f('sys/kernel/slab/vm_area_struct/total_objects', 0o664, b'12087\n') +f('sys/kernel/slab/vm_area_struct/slabs', 0o664, b'711\n') +f('sys/kernel/slab/vm_area_struct/poison', 0o664, b'1\n') +f('sys/kernel/slab/vm_area_struct/alloc_calls', 0o664, b''' 2751 dup_mm+0x194/0x390 age=8335622/8348807/8376522 pid=71-2467 cpus=0-1 + 52 install_special_mapping+0x3d/0xe0 age=4109/7453125/8378118 pid=1-20296 cpus=0-1 + 4006 split_vma+0x61/0x140 age=4107/7930710/8366050 pid=1206-20296 cpus=0-1 + 3 copy_vma+0x125/0x1b0 age=8353805/8353815/8353824 pid=1738 cpus=0 + 54 do_brk+0x2ec/0x360 age=4107/7486452/8378131 pid=1-20296 cpus=0-1 + 5097 mmap_region+0x195/0x5c0 age=4105/7877577/8378131 pid=1-20296 cpus=0-1 + 52 bprm_mm_init+0xa0/0x1b0 age=4109/7453192/8378134 pid=1-20296 cpus=0-1 +''') +f('sys/kernel/slab/vm_area_struct/objs_per_slab', 0o664, b'17\n') +f('sys/kernel/slab/vm_area_struct/shrink', 0o664, b'') +f('sys/kernel/slab/vm_area_struct/trace', 0o664, b'0\n') +f('sys/kernel/slab/vm_area_struct/object_size', 0o664, b'168\n') +f('sys/kernel/slab/vm_area_struct/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/vm_area_struct/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/vm_area_struct/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/vm_area_struct/objects_partial', 0o664, b'47\n') +f('sys/kernel/slab/vm_area_struct/objects', 0o664, b'12049\n') +f('sys/kernel/slab/vm_area_struct/order', 0o664, b'0\n') +f('sys/kernel/slab/vm_area_struct/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/vm_area_struct/store_user', 0o664, b'1\n') +f('sys/kernel/slab/vm_area_struct/align', 0o664, b'0\n') +f('sys/kernel/slab/vm_area_struct/partial', 0o664, b'5\n') +f('sys/kernel/slab/vm_area_struct/validate', 0o664, b'') +f('sys/kernel/slab/vm_area_struct/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/vm_area_struct/free_calls', 0o664, b''' 6424 age=4303047229 pid=0 cpus=0 + 5590 remove_vma+0x53/0x70 age=4110/7683818/8376767 pid=71-20296 cpus=0-1 + 1 vma_adjust+0x32c/0x570 age=8364245 pid=1371 cpus=0 +''') +f('sys/kernel/slab/vm_area_struct/aliases', 0o664, b'0\n') +d('sys/kernel/slab/biovec-1', 0o775) +f('sys/kernel/slab/biovec-1/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/biovec-1/ctor', 0o664, b'') +f('sys/kernel/slab/biovec-1/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/biovec-1/slab_size', 0o664, b'96\n') +f('sys/kernel/slab/biovec-1/total_objects', 0o664, b'126\n') +f('sys/kernel/slab/biovec-1/slabs', 0o664, b'3\n') +f('sys/kernel/slab/biovec-1/poison', 0o664, b'1\n') +f('sys/kernel/slab/biovec-1/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379509/8379509/8379509 pid=1 cpus=0\n') +f('sys/kernel/slab/biovec-1/objs_per_slab', 0o664, b'42\n') +f('sys/kernel/slab/biovec-1/shrink', 0o664, b'') +f('sys/kernel/slab/biovec-1/trace', 0o664, b'0\n') +f('sys/kernel/slab/biovec-1/object_size', 0o664, b'16\n') +f('sys/kernel/slab/biovec-1/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/biovec-1/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/biovec-1/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/biovec-1/objects_partial', 0o664, b'2\n') +f('sys/kernel/slab/biovec-1/objects', 0o664, b'86\n') +f('sys/kernel/slab/biovec-1/order', 0o664, b'0\n') +f('sys/kernel/slab/biovec-1/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/biovec-1/store_user', 0o664, b'1\n') +f('sys/kernel/slab/biovec-1/align', 0o664, b'0\n') +f('sys/kernel/slab/biovec-1/partial', 0o664, b'1\n') +f('sys/kernel/slab/biovec-1/validate', 0o664, b'') +f('sys/kernel/slab/biovec-1/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/biovec-1/free_calls', 0o664, b' 2 age=4303046943 pid=0 cpus=0\n') +f('sys/kernel/slab/biovec-1/aliases', 0o664, b'0\n') +d('sys/kernel/slab/secpath_cache', 0o775) +f('sys/kernel/slab/secpath_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/ctor', 0o664, b'') +f('sys/kernel/slab/secpath_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/secpath_cache/slab_size', 0o664, b'128\n') +f('sys/kernel/slab/secpath_cache/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/slabs', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/secpath_cache/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/secpath_cache/objs_per_slab', 0o664, b'32\n') +f('sys/kernel/slab/secpath_cache/shrink', 0o664, b'') +f('sys/kernel/slab/secpath_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/object_size', 0o664, b'56\n') +f('sys/kernel/slab/secpath_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/objects', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/secpath_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/secpath_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/secpath_cache/validate', 0o664, b'') +f('sys/kernel/slab/secpath_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/secpath_cache/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/secpath_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/UNIX', 0o775) +f('sys/kernel/slab/UNIX/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/UNIX/ctor', 0o664, b'') +f('sys/kernel/slab/UNIX/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/UNIX/slab_size', 0o664, b'1472\n') +f('sys/kernel/slab/UNIX/total_objects', 0o664, b'506\n') +f('sys/kernel/slab/UNIX/slabs', 0o664, b'23\n') +f('sys/kernel/slab/UNIX/poison', 0o664, b'1\n') +f('sys/kernel/slab/UNIX/alloc_calls', 0o664, b' 450 sk_prot_alloc+0x1e/0xb0 age=61033/8220474/8376385 pid=71-20296 cpus=0-1\n') +f('sys/kernel/slab/UNIX/objs_per_slab', 0o664, b'22\n') +f('sys/kernel/slab/UNIX/shrink', 0o664, b'') +f('sys/kernel/slab/UNIX/trace', 0o664, b'0\n') +f('sys/kernel/slab/UNIX/object_size', 0o664, b'1376\n') +f('sys/kernel/slab/UNIX/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/UNIX/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/UNIX/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/UNIX/objects_partial', 0o664, b'178\n') +f('sys/kernel/slab/UNIX/objects', 0o664, b'486\n') +f('sys/kernel/slab/UNIX/order', 0o664, b'3\n') +f('sys/kernel/slab/UNIX/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/UNIX/store_user', 0o664, b'1\n') +f('sys/kernel/slab/UNIX/align', 0o664, b'0\n') +f('sys/kernel/slab/UNIX/partial', 0o664, b'9\n') +f('sys/kernel/slab/UNIX/validate', 0o664, b'') +f('sys/kernel/slab/UNIX/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/UNIX/free_calls', 0o664, b''' 235 age=4303046663 pid=0 cpus=0 + 215 sk_free+0x80/0x100 age=61050/8083366/8375930 pid=76-20292 cpus=0-1 +''') +f('sys/kernel/slab/UNIX/aliases', 0o664, b'0\n') +d('sys/kernel/slab/RAWv6', 0o775) +f('sys/kernel/slab/RAWv6/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/RAWv6/ctor', 0o664, b'') +f('sys/kernel/slab/RAWv6/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/RAWv6/slab_size', 0o664, b'1472\n') +f('sys/kernel/slab/RAWv6/total_objects', 0o664, b'22\n') +f('sys/kernel/slab/RAWv6/slabs', 0o664, b'1\n') +f('sys/kernel/slab/RAWv6/poison', 0o664, b'1\n') +f('sys/kernel/slab/RAWv6/alloc_calls', 0o664, b' 5 sk_prot_alloc+0x1e/0xb0 age=8360545/8360552/8360555 pid=1549 cpus=0\n') +f('sys/kernel/slab/RAWv6/objs_per_slab', 0o664, b'22\n') +f('sys/kernel/slab/RAWv6/shrink', 0o664, b'') +f('sys/kernel/slab/RAWv6/trace', 0o664, b'0\n') +f('sys/kernel/slab/RAWv6/object_size', 0o664, b'1376\n') +f('sys/kernel/slab/RAWv6/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/RAWv6/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/RAWv6/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/RAWv6/objects_partial', 0o664, b'5\n') +f('sys/kernel/slab/RAWv6/objects', 0o664, b'5\n') +f('sys/kernel/slab/RAWv6/order', 0o664, b'3\n') +f('sys/kernel/slab/RAWv6/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/RAWv6/store_user', 0o664, b'1\n') +f('sys/kernel/slab/RAWv6/align', 0o664, b'0\n') +f('sys/kernel/slab/RAWv6/partial', 0o664, b'1\n') +f('sys/kernel/slab/RAWv6/validate', 0o664, b'') +f('sys/kernel/slab/RAWv6/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/RAWv6/free_calls', 0o664, b' 5 age=4303047773 pid=0 cpus=0\n') +f('sys/kernel/slab/RAWv6/aliases', 0o664, b'0\n') +d('sys/kernel/slab/sgpool-64', 0o775) +f('sys/kernel/slab/sgpool-64/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-64/ctor', 0o664, b'') +f('sys/kernel/slab/sgpool-64/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-64/slab_size', 0o664, b'2176\n') +f('sys/kernel/slab/sgpool-64/total_objects', 0o664, b'30\n') +f('sys/kernel/slab/sgpool-64/slabs', 0o664, b'2\n') +f('sys/kernel/slab/sgpool-64/poison', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-64/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379271/8379271/8379271 pid=1 cpus=0\n') +f('sys/kernel/slab/sgpool-64/objs_per_slab', 0o664, b'15\n') +f('sys/kernel/slab/sgpool-64/shrink', 0o664, b'') +f('sys/kernel/slab/sgpool-64/trace', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-64/object_size', 0o664, b'2048\n') +f('sys/kernel/slab/sgpool-64/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-64/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-64/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-64/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-64/objects', 0o664, b'30\n') +f('sys/kernel/slab/sgpool-64/order', 0o664, b'3\n') +f('sys/kernel/slab/sgpool-64/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-64/store_user', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-64/align', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-64/partial', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-64/validate', 0o664, b'') +f('sys/kernel/slab/sgpool-64/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-64/free_calls', 0o664, b' 2 age=4303046820 pid=0 cpus=0\n') +f('sys/kernel/slab/sgpool-64/aliases', 0o664, b'0\n') +d('sys/kernel/slab/bdev_cache', 0o775) +f('sys/kernel/slab/bdev_cache/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/bdev_cache/ctor', 0o664, b'init_once+0x0/0x100\n') +f('sys/kernel/slab/bdev_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/bdev_cache/slab_size', 0o664, b'1536\n') +f('sys/kernel/slab/bdev_cache/total_objects', 0o664, b'42\n') +f('sys/kernel/slab/bdev_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/bdev_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/bdev_cache/alloc_calls', 0o664, b' 13 bdev_alloc_inode+0x15/0x30 age=61383/7093434/8379778 pid=0-13333 cpus=0\n') +f('sys/kernel/slab/bdev_cache/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/bdev_cache/shrink', 0o664, b'') +f('sys/kernel/slab/bdev_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/bdev_cache/object_size', 0o664, b'1432\n') +f('sys/kernel/slab/bdev_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/bdev_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/bdev_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/bdev_cache/objects_partial', 0o664, b'11\n') +f('sys/kernel/slab/bdev_cache/objects', 0o664, b'32\n') +f('sys/kernel/slab/bdev_cache/order', 0o664, b'3\n') +f('sys/kernel/slab/bdev_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/bdev_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/bdev_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/bdev_cache/partial', 0o664, b'1\n') +f('sys/kernel/slab/bdev_cache/validate', 0o664, b'') +f('sys/kernel/slab/bdev_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/bdev_cache/free_calls', 0o664, b''' 9 age=4303047074 pid=0 cpus=0 + 4 bdev_destroy_inode+0x1f/0x30 age=61405/4218130/8374840 pid=488-13325 cpus=0-1 +''') +f('sys/kernel/slab/bdev_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/fasync_cache', 0o775) +f('sys/kernel/slab/fasync_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/fasync_cache/ctor', 0o664, b'') +f('sys/kernel/slab/fasync_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/fasync_cache/slab_size', 0o664, b'96\n') +f('sys/kernel/slab/fasync_cache/total_objects', 0o664, b'42\n') +f('sys/kernel/slab/fasync_cache/slabs', 0o664, b'1\n') +f('sys/kernel/slab/fasync_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/fasync_cache/alloc_calls', 0o664, b' 1 fasync_helper+0x115/0x130 age=8354059 pid=1738 cpus=0\n') +f('sys/kernel/slab/fasync_cache/objs_per_slab', 0o664, b'42\n') +f('sys/kernel/slab/fasync_cache/shrink', 0o664, b'') +f('sys/kernel/slab/fasync_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/fasync_cache/object_size', 0o664, b'24\n') +f('sys/kernel/slab/fasync_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/fasync_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/fasync_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/fasync_cache/objects_partial', 0o664, b'1\n') +f('sys/kernel/slab/fasync_cache/objects', 0o664, b'1\n') +f('sys/kernel/slab/fasync_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/fasync_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/fasync_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/fasync_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/fasync_cache/partial', 0o664, b'1\n') +f('sys/kernel/slab/fasync_cache/validate', 0o664, b'') +f('sys/kernel/slab/fasync_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/fasync_cache/free_calls', 0o664, b' 1 age=4303047449 pid=0 cpus=0\n') +f('sys/kernel/slab/fasync_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/UDPLITEv6', 0o775) +f('sys/kernel/slab/UDPLITEv6/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/ctor', 0o664, b'') +f('sys/kernel/slab/UDPLITEv6/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/UDPLITEv6/slab_size', 0o664, b'1472\n') +f('sys/kernel/slab/UDPLITEv6/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/slabs', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/poison', 0o664, b'1\n') +f('sys/kernel/slab/UDPLITEv6/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/UDPLITEv6/objs_per_slab', 0o664, b'22\n') +f('sys/kernel/slab/UDPLITEv6/shrink', 0o664, b'') +f('sys/kernel/slab/UDPLITEv6/trace', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/object_size', 0o664, b'1368\n') +f('sys/kernel/slab/UDPLITEv6/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/objects', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/order', 0o664, b'3\n') +f('sys/kernel/slab/UDPLITEv6/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/UDPLITEv6/store_user', 0o664, b'1\n') +f('sys/kernel/slab/UDPLITEv6/align', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/partial', 0o664, b'0\n') +f('sys/kernel/slab/UDPLITEv6/validate', 0o664, b'') +f('sys/kernel/slab/UDPLITEv6/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/UDPLITEv6/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/UDPLITEv6/aliases', 0o664, b'0\n') +d('sys/kernel/slab/Acpi-Operand', 0o775) +f('sys/kernel/slab/Acpi-Operand/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Operand/ctor', 0o664, b'') +f('sys/kernel/slab/Acpi-Operand/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Operand/slab_size', 0o664, b'144\n') +f('sys/kernel/slab/Acpi-Operand/total_objects', 0o664, b'2688\n') +f('sys/kernel/slab/Acpi-Operand/slabs', 0o664, b'96\n') +f('sys/kernel/slab/Acpi-Operand/poison', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Operand/alloc_calls', 0o664, b' 2653 acpi_ut_allocate_object_desc_dbg+0x39/0x75 age=2625/8339457/8379700 pid=0-13466 cpus=0-1\n') +f('sys/kernel/slab/Acpi-Operand/objs_per_slab', 0o664, b'28\n') +f('sys/kernel/slab/Acpi-Operand/shrink', 0o664, b'') +f('sys/kernel/slab/Acpi-Operand/trace', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Operand/object_size', 0o664, b'72\n') +f('sys/kernel/slab/Acpi-Operand/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Operand/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Operand/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Operand/objects_partial', 0o664, b'171\n') +f('sys/kernel/slab/Acpi-Operand/objects', 0o664, b'2663\n') +f('sys/kernel/slab/Acpi-Operand/order', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Operand/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Operand/store_user', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Operand/align', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-Operand/partial', 0o664, b'7\n') +f('sys/kernel/slab/Acpi-Operand/validate', 0o664, b'') +f('sys/kernel/slab/Acpi-Operand/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-Operand/free_calls', 0o664, b''' 2267 age=4303046997 pid=0 cpus=0 + 386 acpi_os_release_object+0x9/0xd age=2626/8137233/8379689 pid=0-13466 cpus=0-1 +''') +f('sys/kernel/slab/Acpi-Operand/aliases', 0o664, b'0\n') +d('sys/kernel/slab/xfrm_dst_cache', 0o775) +f('sys/kernel/slab/xfrm_dst_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/ctor', 0o664, b'') +f('sys/kernel/slab/xfrm_dst_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/xfrm_dst_cache/slab_size', 0o664, b'448\n') +f('sys/kernel/slab/xfrm_dst_cache/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/slabs', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/xfrm_dst_cache/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/xfrm_dst_cache/objs_per_slab', 0o664, b'18\n') +f('sys/kernel/slab/xfrm_dst_cache/shrink', 0o664, b'') +f('sys/kernel/slab/xfrm_dst_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/object_size', 0o664, b'344\n') +f('sys/kernel/slab/xfrm_dst_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/objects', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/order', 0o664, b'1\n') +f('sys/kernel/slab/xfrm_dst_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/xfrm_dst_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/xfrm_dst_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/xfrm_dst_cache/validate', 0o664, b'') +f('sys/kernel/slab/xfrm_dst_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/xfrm_dst_cache/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/xfrm_dst_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/eventpoll_epi', 0o775) +f('sys/kernel/slab/eventpoll_epi/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_epi/ctor', 0o664, b'') +f('sys/kernel/slab/eventpoll_epi/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/eventpoll_epi/slab_size', 0o664, b'256\n') +f('sys/kernel/slab/eventpoll_epi/total_objects', 0o664, b'96\n') +f('sys/kernel/slab/eventpoll_epi/slabs', 0o664, b'6\n') +f('sys/kernel/slab/eventpoll_epi/poison', 0o664, b'1\n') +f('sys/kernel/slab/eventpoll_epi/alloc_calls', 0o664, b' 65 sys_epoll_ctl+0x1a4/0x4d0 age=2416443/8173337/8356255 pid=1690-20296 cpus=0-1\n') +f('sys/kernel/slab/eventpoll_epi/objs_per_slab', 0o664, b'16\n') +f('sys/kernel/slab/eventpoll_epi/shrink', 0o664, b'') +f('sys/kernel/slab/eventpoll_epi/trace', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_epi/object_size', 0o664, b'128\n') +f('sys/kernel/slab/eventpoll_epi/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_epi/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_epi/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_epi/objects_partial', 0o664, b'15\n') +f('sys/kernel/slab/eventpoll_epi/objects', 0o664, b'79\n') +f('sys/kernel/slab/eventpoll_epi/order', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_epi/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/eventpoll_epi/store_user', 0o664, b'1\n') +f('sys/kernel/slab/eventpoll_epi/align', 0o664, b'0\n') +f('sys/kernel/slab/eventpoll_epi/partial', 0o664, b'2\n') +f('sys/kernel/slab/eventpoll_epi/validate', 0o664, b'') +f('sys/kernel/slab/eventpoll_epi/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/eventpoll_epi/free_calls', 0o664, b''' 61 age=4303046803 pid=0 cpus=0 + 4 ep_remove+0xae/0xc0 age=2416461/6864194/8356250 pid=1690-2073 cpus=0-1 +''') +f('sys/kernel/slab/eventpoll_epi/aliases', 0o664, b'0\n') +d('sys/kernel/slab/revoke_table', 0o775) +f('sys/kernel/slab/revoke_table/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/revoke_table/ctor', 0o664, b'') +f('sys/kernel/slab/revoke_table/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/revoke_table/slab_size', 0o664, b'88\n') +f('sys/kernel/slab/revoke_table/total_objects', 0o664, b'46\n') +f('sys/kernel/slab/revoke_table/slabs', 0o664, b'1\n') +f('sys/kernel/slab/revoke_table/poison', 0o664, b'1\n') +f('sys/kernel/slab/revoke_table/alloc_calls', 0o664, b' 4 journal_init_revoke_table+0x1b/0xb0 age=8369805/8374155/8378505 pid=1-962 cpus=0\n') +f('sys/kernel/slab/revoke_table/objs_per_slab', 0o664, b'46\n') +f('sys/kernel/slab/revoke_table/shrink', 0o664, b'') +f('sys/kernel/slab/revoke_table/trace', 0o664, b'0\n') +f('sys/kernel/slab/revoke_table/object_size', 0o664, b'16\n') +f('sys/kernel/slab/revoke_table/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/revoke_table/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/revoke_table/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/revoke_table/objects_partial', 0o664, b'4\n') +f('sys/kernel/slab/revoke_table/objects', 0o664, b'4\n') +f('sys/kernel/slab/revoke_table/order', 0o664, b'0\n') +f('sys/kernel/slab/revoke_table/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/revoke_table/store_user', 0o664, b'1\n') +f('sys/kernel/slab/revoke_table/align', 0o664, b'0\n') +f('sys/kernel/slab/revoke_table/partial', 0o664, b'1\n') +f('sys/kernel/slab/revoke_table/validate', 0o664, b'') +f('sys/kernel/slab/revoke_table/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/revoke_table/free_calls', 0o664, b' 4 age=4303047546 pid=0 cpus=0\n') +f('sys/kernel/slab/revoke_table/aliases', 0o664, b'0\n') +d('sys/kernel/slab/sgpool-32', 0o775) +f('sys/kernel/slab/sgpool-32/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-32/ctor', 0o664, b'') +f('sys/kernel/slab/sgpool-32/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-32/slab_size', 0o664, b'1152\n') +f('sys/kernel/slab/sgpool-32/total_objects', 0o664, b'28\n') +f('sys/kernel/slab/sgpool-32/slabs', 0o664, b'2\n') +f('sys/kernel/slab/sgpool-32/poison', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-32/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379280/8379280/8379280 pid=1 cpus=0\n') +f('sys/kernel/slab/sgpool-32/objs_per_slab', 0o664, b'14\n') +f('sys/kernel/slab/sgpool-32/shrink', 0o664, b'') +f('sys/kernel/slab/sgpool-32/trace', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-32/object_size', 0o664, b'1024\n') +f('sys/kernel/slab/sgpool-32/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-32/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-32/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-32/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-32/objects', 0o664, b'28\n') +f('sys/kernel/slab/sgpool-32/order', 0o664, b'2\n') +f('sys/kernel/slab/sgpool-32/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-32/store_user', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-32/align', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-32/partial', 0o664, b'0\n') +f('sys/kernel/slab/sgpool-32/validate', 0o664, b'') +f('sys/kernel/slab/sgpool-32/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/sgpool-32/free_calls', 0o664, b' 2 age=4303046829 pid=0 cpus=0\n') +f('sys/kernel/slab/sgpool-32/aliases', 0o664, b'0\n') +d('sys/kernel/slab/fib6_nodes', 0o775) +f('sys/kernel/slab/fib6_nodes/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/fib6_nodes/ctor', 0o664, b'') +f('sys/kernel/slab/fib6_nodes/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/fib6_nodes/slab_size', 0o664, b'128\n') +f('sys/kernel/slab/fib6_nodes/total_objects', 0o664, b'64\n') +f('sys/kernel/slab/fib6_nodes/slabs', 0o664, b'2\n') +f('sys/kernel/slab/fib6_nodes/poison', 0o664, b'1\n') +f('sys/kernel/slab/fib6_nodes/alloc_calls', 0o664, b''' 3 fib6_add+0x112/0x6a0 [ipv6] age=8328809/8339785/8360575 pid=8-2080 cpus=0-1 + 1 fib6_add+0x2a2/0x6a0 [ipv6] age=8329973 pid=8 cpus=1 + 1 fib6_add+0x2b6/0x6a0 [ipv6] age=8329973 pid=8 cpus=1 +''') +f('sys/kernel/slab/fib6_nodes/objs_per_slab', 0o664, b'32\n') +f('sys/kernel/slab/fib6_nodes/shrink', 0o664, b'') +f('sys/kernel/slab/fib6_nodes/trace', 0o664, b'0\n') +f('sys/kernel/slab/fib6_nodes/object_size', 0o664, b'48\n') +f('sys/kernel/slab/fib6_nodes/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/fib6_nodes/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/fib6_nodes/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/fib6_nodes/objects_partial', 0o664, b'5\n') +f('sys/kernel/slab/fib6_nodes/objects', 0o664, b'5\n') +f('sys/kernel/slab/fib6_nodes/order', 0o664, b'0\n') +f('sys/kernel/slab/fib6_nodes/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/fib6_nodes/store_user', 0o664, b'1\n') +f('sys/kernel/slab/fib6_nodes/align', 0o664, b'0\n') +f('sys/kernel/slab/fib6_nodes/partial', 0o664, b'2\n') +f('sys/kernel/slab/fib6_nodes/validate', 0o664, b'') +f('sys/kernel/slab/fib6_nodes/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/fib6_nodes/free_calls', 0o664, b' 5 age=4303047799 pid=0 cpus=0\n') +f('sys/kernel/slab/fib6_nodes/aliases', 0o664, b'0\n') +d('sys/kernel/slab/flow_cache', 0o775) +f('sys/kernel/slab/flow_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/ctor', 0o664, b'') +f('sys/kernel/slab/flow_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/slab_size', 0o664, b'168\n') +f('sys/kernel/slab/flow_cache/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/slabs', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/flow_cache/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/flow_cache/objs_per_slab', 0o664, b'24\n') +f('sys/kernel/slab/flow_cache/shrink', 0o664, b'') +f('sys/kernel/slab/flow_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/object_size', 0o664, b'96\n') +f('sys/kernel/slab/flow_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/objects', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/flow_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/flow_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/flow_cache/validate', 0o664, b'') +f('sys/kernel/slab/flow_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/flow_cache/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/flow_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/fat_cache', 0o775) +f('sys/kernel/slab/fat_cache/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/fat_cache/ctor', 0o664, b'init_once+0x0/0x10\n') +f('sys/kernel/slab/fat_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/fat_cache/slab_size', 0o664, b'104\n') +f('sys/kernel/slab/fat_cache/total_objects', 0o664, b'39\n') +f('sys/kernel/slab/fat_cache/slabs', 0o664, b'1\n') +f('sys/kernel/slab/fat_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/fat_cache/alloc_calls', 0o664, b' 14 fat_cache_add+0x11f/0x1c0 age=61297/61310/61330 pid=13349 cpus=0\n') +f('sys/kernel/slab/fat_cache/objs_per_slab', 0o664, b'39\n') +f('sys/kernel/slab/fat_cache/shrink', 0o664, b'') +f('sys/kernel/slab/fat_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/fat_cache/object_size', 0o664, b'32\n') +f('sys/kernel/slab/fat_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/fat_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/fat_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/fat_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/fat_cache/objects', 0o664, b'39\n') +f('sys/kernel/slab/fat_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/fat_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/fat_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/fat_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/fat_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/fat_cache/validate', 0o664, b'') +f('sys/kernel/slab/fat_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/fat_cache/free_calls', 0o664, b' 14 age=4303047585 pid=0 cpus=0\n') +f('sys/kernel/slab/fat_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/sock_inode_cache', 0o775) +f('sys/kernel/slab/sock_inode_cache/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/sock_inode_cache/ctor', 0o664, b'init_once+0x0/0x10\n') +f('sys/kernel/slab/sock_inode_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/sock_inode_cache/slab_size', 0o664, b'1280\n') +f('sys/kernel/slab/sock_inode_cache/total_objects', 0o664, b'504\n') +f('sys/kernel/slab/sock_inode_cache/slabs', 0o664, b'42\n') +f('sys/kernel/slab/sock_inode_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/sock_inode_cache/alloc_calls', 0o664, b' 481 sock_alloc_inode+0x1a/0x70 age=61330/8214562/8379530 pid=1-20296 cpus=0-1\n') +f('sys/kernel/slab/sock_inode_cache/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/sock_inode_cache/shrink', 0o664, b'') +f('sys/kernel/slab/sock_inode_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/sock_inode_cache/object_size', 0o664, b'1192\n') +f('sys/kernel/slab/sock_inode_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/sock_inode_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/sock_inode_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/sock_inode_cache/objects_partial', 0o664, b'83\n') +f('sys/kernel/slab/sock_inode_cache/objects', 0o664, b'491\n') +f('sys/kernel/slab/sock_inode_cache/order', 0o664, b'2\n') +f('sys/kernel/slab/sock_inode_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/sock_inode_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/sock_inode_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/sock_inode_cache/partial', 0o664, b'8\n') +f('sys/kernel/slab/sock_inode_cache/validate', 0o664, b'') +f('sys/kernel/slab/sock_inode_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/sock_inode_cache/free_calls', 0o664, b''' 276 age=4303046961 pid=0 cpus=0 + 205 sock_destroy_inode+0x14/0x20 age=61348/8035806/8376228 pid=76-20292 cpus=0-1 +''') +f('sys/kernel/slab/sock_inode_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/ip_fib_hash', 0o775) +f('sys/kernel/slab/ip_fib_hash/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_hash/ctor', 0o664, b'') +f('sys/kernel/slab/ip_fib_hash/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_hash/slab_size', 0o664, b'144\n') +f('sys/kernel/slab/ip_fib_hash/total_objects', 0o664, b'56\n') +f('sys/kernel/slab/ip_fib_hash/slabs', 0o664, b'2\n') +f('sys/kernel/slab/ip_fib_hash/poison', 0o664, b'1\n') +f('sys/kernel/slab/ip_fib_hash/alloc_calls', 0o664, b' 11 fn_hash_insert+0x5a6/0x800 age=8323831/8347847/8367198 pid=1197-1541 cpus=0-1\n') +f('sys/kernel/slab/ip_fib_hash/objs_per_slab', 0o664, b'28\n') +f('sys/kernel/slab/ip_fib_hash/shrink', 0o664, b'') +f('sys/kernel/slab/ip_fib_hash/trace', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_hash/object_size', 0o664, b'72\n') +f('sys/kernel/slab/ip_fib_hash/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_hash/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_hash/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_hash/objects_partial', 0o664, b'11\n') +f('sys/kernel/slab/ip_fib_hash/objects', 0o664, b'11\n') +f('sys/kernel/slab/ip_fib_hash/order', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_hash/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/ip_fib_hash/store_user', 0o664, b'1\n') +f('sys/kernel/slab/ip_fib_hash/align', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_hash/partial', 0o664, b'2\n') +f('sys/kernel/slab/ip_fib_hash/validate', 0o664, b'') +f('sys/kernel/slab/ip_fib_hash/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/ip_fib_hash/free_calls', 0o664, b''' 7 age=4303046724 pid=0 cpus=0 + 4 fn_hash_delete+0x22c/0x290 age=8367201/8367201/8367201 pid=1195 cpus=1 +''') +f('sys/kernel/slab/ip_fib_hash/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc_dma-512', 0o775) +f('sys/kernel/slab/kmalloc_dma-512/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc_dma-512/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc_dma-512/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc_dma-512/slab_size', 0o664, b'584\n') +f('sys/kernel/slab/kmalloc_dma-512/total_objects', 0o664, b'14\n') +f('sys/kernel/slab/kmalloc_dma-512/slabs', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc_dma-512/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc_dma-512/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/kmalloc_dma-512/objs_per_slab', 0o664, b'14\n') +f('sys/kernel/slab/kmalloc_dma-512/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc_dma-512/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc_dma-512/object_size', 0o664, b'512\n') +f('sys/kernel/slab/kmalloc_dma-512/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc_dma-512/cache_dma', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc_dma-512/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc_dma-512/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc_dma-512/objects', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc_dma-512/order', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc_dma-512/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc_dma-512/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc_dma-512/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc_dma-512/partial', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc_dma-512/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc_dma-512/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc_dma-512/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/kmalloc_dma-512/aliases', 0o664, b'0\n') +d('sys/kernel/slab/inode_cache', 0o775) +f('sys/kernel/slab/inode_cache/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/inode_cache/ctor', 0o664, b'init_once+0x0/0x10\n') +f('sys/kernel/slab/inode_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/inode_cache/slab_size', 0o664, b'1144\n') +f('sys/kernel/slab/inode_cache/total_objects', 0o664, b'11676\n') +f('sys/kernel/slab/inode_cache/slabs', 0o664, b'834\n') +f('sys/kernel/slab/inode_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/inode_cache/alloc_calls', 0o664, b' 11655 alloc_inode+0x251/0x280 age=665/7686826/8379810 pid=0-13466 cpus=0-1\n') +f('sys/kernel/slab/inode_cache/objs_per_slab', 0o664, b'14\n') +f('sys/kernel/slab/inode_cache/shrink', 0o664, b'') +f('sys/kernel/slab/inode_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/inode_cache/object_size', 0o664, b'1072\n') +f('sys/kernel/slab/inode_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/inode_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/inode_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/inode_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/inode_cache/objects', 0o664, b'11676\n') +f('sys/kernel/slab/inode_cache/order', 0o664, b'2\n') +f('sys/kernel/slab/inode_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/inode_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/inode_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/inode_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/inode_cache/validate', 0o664, b'') +f('sys/kernel/slab/inode_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/inode_cache/free_calls', 0o664, b''' 11113 age=4303047110 pid=0 cpus=0 + 542 destroy_inode+0x4f/0x60 age=1016/6891707/8377435 pid=7-15896 cpus=0-1 +''') +f('sys/kernel/slab/inode_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/inotify_event_cache', 0o775) +f('sys/kernel/slab/inotify_event_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/inotify_event_cache/ctor', 0o664, b'') +f('sys/kernel/slab/inotify_event_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/inotify_event_cache/slab_size', 0o664, b'112\n') +f('sys/kernel/slab/inotify_event_cache/total_objects', 0o664, b'72\n') +f('sys/kernel/slab/inotify_event_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/inotify_event_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/inotify_event_cache/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/inotify_event_cache/objs_per_slab', 0o664, b'36\n') +f('sys/kernel/slab/inotify_event_cache/shrink', 0o664, b'') +f('sys/kernel/slab/inotify_event_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/inotify_event_cache/object_size', 0o664, b'40\n') +f('sys/kernel/slab/inotify_event_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/inotify_event_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/inotify_event_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/inotify_event_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/inotify_event_cache/objects', 0o664, b'72\n') +f('sys/kernel/slab/inotify_event_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/inotify_event_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/inotify_event_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/inotify_event_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/inotify_event_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/inotify_event_cache/validate', 0o664, b'') +f('sys/kernel/slab/inotify_event_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/inotify_event_cache/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/inotify_event_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/UDP', 0o775) +f('sys/kernel/slab/UDP/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/UDP/ctor', 0o664, b'') +f('sys/kernel/slab/UDP/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/UDP/slab_size', 0o664, b'1344\n') +f('sys/kernel/slab/UDP/total_objects', 0o664, b'24\n') +f('sys/kernel/slab/UDP/slabs', 0o664, b'2\n') +f('sys/kernel/slab/UDP/poison', 0o664, b'1\n') +f('sys/kernel/slab/UDP/alloc_calls', 0o664, b' 5 sk_prot_alloc+0x1e/0xb0 age=8327731/8349275/8355457 pid=1545-2586 cpus=0-1\n') +f('sys/kernel/slab/UDP/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/UDP/shrink', 0o664, b'') +f('sys/kernel/slab/UDP/trace', 0o664, b'0\n') +f('sys/kernel/slab/UDP/object_size', 0o664, b'1232\n') +f('sys/kernel/slab/UDP/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/UDP/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/UDP/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/UDP/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/UDP/objects', 0o664, b'24\n') +f('sys/kernel/slab/UDP/order', 0o664, b'2\n') +f('sys/kernel/slab/UDP/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/UDP/store_user', 0o664, b'1\n') +f('sys/kernel/slab/UDP/align', 0o664, b'0\n') +f('sys/kernel/slab/UDP/partial', 0o664, b'0\n') +f('sys/kernel/slab/UDP/validate', 0o664, b'') +f('sys/kernel/slab/UDP/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/UDP/free_calls', 0o664, b''' 1 age=4303046759 pid=0 cpus=0 + 4 sk_free+0x80/0x100 age=8327731/8350484/8364461 pid=1371-2586 cpus=0-1 +''') +f('sys/kernel/slab/UDP/aliases', 0o664, b'0\n') +d('sys/kernel/slab/Acpi-ParseExt', 0o775) +f('sys/kernel/slab/Acpi-ParseExt/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-ParseExt/ctor', 0o664, b'') +f('sys/kernel/slab/Acpi-ParseExt/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-ParseExt/slab_size', 0o664, b'144\n') +f('sys/kernel/slab/Acpi-ParseExt/total_objects', 0o664, b'56\n') +f('sys/kernel/slab/Acpi-ParseExt/slabs', 0o664, b'2\n') +f('sys/kernel/slab/Acpi-ParseExt/poison', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-ParseExt/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/Acpi-ParseExt/objs_per_slab', 0o664, b'28\n') +f('sys/kernel/slab/Acpi-ParseExt/shrink', 0o664, b'') +f('sys/kernel/slab/Acpi-ParseExt/trace', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-ParseExt/object_size', 0o664, b'72\n') +f('sys/kernel/slab/Acpi-ParseExt/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-ParseExt/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-ParseExt/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-ParseExt/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-ParseExt/objects', 0o664, b'56\n') +f('sys/kernel/slab/Acpi-ParseExt/order', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-ParseExt/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-ParseExt/store_user', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-ParseExt/align', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-ParseExt/partial', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-ParseExt/validate', 0o664, b'') +f('sys/kernel/slab/Acpi-ParseExt/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-ParseExt/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/Acpi-ParseExt/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-8', 0o775) +f('sys/kernel/slab/kmalloc-8/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-8/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-8/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-8/slab_size', 0o664, b'80\n') +f('sys/kernel/slab/kmalloc-8/total_objects', 0o664, b'3366\n') +f('sys/kernel/slab/kmalloc-8/slabs', 0o664, b'66\n') +f('sys/kernel/slab/kmalloc-8/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-8/alloc_calls', 0o664, b''' 1 cache_k8_northbridges+0x5f/0x130 age=8379864 pid=1 cpus=0 + 1 pm_qos_add_requirement+0x51/0xe0 age=8376100 pid=122 cpus=1 + 5 setup_modinfo_version+0x19/0x30 age=8355991/8370769/8376336 pid=169-1766 cpus=0-1 + 379 load_module+0x1ac4/0x1b30 age=8303091/8368856/8376330 pid=105-2754 cpus=0-1 + 57 strndup_user+0x6d/0xc0 age=8303095/8368234/8376336 pid=105-2754 cpus=0-1 + 4 krealloc+0x1e/0x60 age=8355270/8362240/8377141 pid=71-1849 cpus=0-1 + 5 __vmalloc_area_node+0xfb/0x140 age=8373659/8374450/8375164 pid=181-754 cpus=0-1 + 17 alloc_vfsmnt+0x97/0x180 age=8354102/8377143/8380122 pid=0-2064 cpus=0-1 + 1 proc_symlink+0x4d/0xb0 age=8374163 pid=107 cpus=1 + 1954 sysfs_new_dirent+0x10c/0x120 age=22655/7531182/8380122 pid=0-13295 cpus=0-1 + 690 kvasprintf+0x55/0x90 age=22668/7820060/8380122 pid=0-13295 cpus=0-1 + 1 proc_bus_pci_open+0x1d/0x50 age=8355838 pid=1738 cpus=0 + 5 pcie_port_device_register+0x25/0x4a0 age=8379822/8379823/8379824 pid=1 cpus=1 + 19 acpi_ds_build_internal_buffer_obj+0xe1/0x121 age=8379961/8379970/8379972 pid=1 cpus=0 + 9 acpi_ev_pci_config_region_setup+0x162/0x270 age=8379256/8379854/8379947 pid=1-12 cpus=0-1 + 2 acpi_ut_copy_simple_object+0x8f/0x11c age=8375678/8375686/8375694 pid=396 cpus=0 + 35 acpi_irq_stats_init+0x1bd/0x268 age=8379979/8379979/8379979 pid=1 cpus=0 + 8 neigh_sysctl_register+0x1cd/0x330 age=8360192/8368781/8379845 pid=1-1549 cpus=0-1 + 7 netlink_kernel_create+0xab/0x1a0 age=8378987/8379768/8379988 pid=1 cpus=0-1 + 5 __devinet_sysctl_register+0xb8/0x120 age=8373658/8377862/8379845 pid=1-126 cpus=0-1 + 1 fz_hash_alloc+0x4a/0x60 age=8324525 pid=1541 cpus=0 + 1 init_vdso_vars+0x4c/0x24a age=8379835 pid=1 cpus=1 + 30 netlink_proto_init+0xf1/0x16b age=8379988/8379988/8379988 pid=1 cpus=0 + 5 hub_probe+0x20b/0x820 [usbcore] age=8374075/8374568/8374921 pid=143-147 cpus=0-1 + 3 usb_cache_string+0x65/0xa0 [usbcore] age=22742/37518/67072 pid=419 cpus=0 + 10 usb_get_configuration+0xbd/0x1480 [usbcore] age=22743/5876145/8374941 pid=143-419 cpus=0-1 + 35 snd_info_create_entry+0x30/0xa0 [snd] age=8355370/8370655/8374933 pid=107-1813 cpus=0-1 + 1 async_chainiv_givencrypt_first+0x56/0x80 [crypto_blkcipher] age=8374580 pid=215 cpus=0 + 1 md_seq_open+0x2d/0x90 [md_mod] age=8366135 pid=1371 cpus=0 + 1 bitmap_create+0x3aa/0xad0 [md_mod] age=8370125 pid=916 cpus=0 + 5 __addrconf_sysctl_register+0xcd/0x140 [ipv6] age=8360192/8360193/8360195 pid=1549 cpus=0 + 1 fib6_net_init+0x5d/0x130 [ipv6] age=8360195 pid=1549 cpus=0 +''') +f('sys/kernel/slab/kmalloc-8/objs_per_slab', 0o664, b'51\n') +f('sys/kernel/slab/kmalloc-8/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-8/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-8/object_size', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-8/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-8/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-8/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-8/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-8/objects', 0o664, b'3366\n') +f('sys/kernel/slab/kmalloc-8/order', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-8/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-8/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-8/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-8/partial', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-8/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-8/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-8/free_calls', 0o664, b''' 2657 age=4303047420 pid=0 cpus=0 + 3 free_sect_attrs+0x2e/0x50 age=8375066/8375066/8375066 pid=383 cpus=0 + 6 load_module+0x73f/0x1b30 age=8374844/8375309/8376003 pid=143-332 cpus=0-1 + 1 free_module+0xb9/0xf0 age=8375066 pid=383 cpus=0 + 1 krealloc+0x3a/0x60 age=8375814 pid=330 cpus=0 + 41 __vunmap+0xe9/0x120 age=8355636/8372979/8376319 pid=105-1805 cpus=0-1 + 1 vfs_rename+0x301/0x450 age=8367176 pid=72 cpus=1 + 254 release_sysfs_dirent+0x8c/0xd0 age=125751/7762571/8379789 pid=1-3347 cpus=0-1 + 61 kobject_release+0xe1/0x140 age=125751/6939731/8378264 pid=1-3347 cpus=0-1 + 1 match_number+0x95/0xb0 age=8335823 pid=2476 cpus=0 + 2 proc_bus_pci_release+0x18/0x30 age=8355841/8356005/8356169 pid=1738 cpus=0 + 49 acpi_ds_create_operand+0x12c/0x209 age=125757/8029619/8379980 pid=1-1442 cpus=0-1 + 128 acpi_ns_get_node+0x92/0xa1 age=8366449/8379363/8379989 pid=1-1358 cpus=0-1 + 2 acpi_ut_delete_internal_obj+0x15f/0x16f age=8375669/8375730/8375792 pid=330-396 cpus=0 + 2 module_add_driver+0x66/0xd0 age=8375989/8375992/8375996 pid=144 cpus=0 + 2 sd_media_changed+0xca/0x210 age=7839601/7929600/8019600 pid=2796 cpus=0 + 3 get_modalias+0xd4/0x120 age=8355846/8370834/8379988 pid=1-1772 cpus=0-1 + 1 fib_hash_free+0x35/0x40 age=8367910 pid=1185 cpus=0 + 1 usb_release_dev+0x39/0x70 [usbcore] age=7833240 pid=419 cpus=1 + 2 usb_release_dev+0x45/0x70 [usbcore] age=7833240/7835719/7838199 pid=419 cpus=0-1 + 4 sg_clean+0x3e/0x80 [usbcore] age=62037/2121033/8297977 pid=2760-13294 cpus=0 + 59 usb_control_msg+0xef/0x110 [usbcore] age=22658/5520135/8374943 pid=143-419 cpus=0-1 + 7 usb_set_configuration+0x338/0x5f0 [usbcore] age=53566/5999072/8374935 pid=143-419 cpus=0-1 + 4 usb_destroy_configuration+0x78/0x140 [usbcore] age=7824401/7967435/8373902 pid=419 cpus=0-1 + 7 sr_media_change+0xeb/0x2a0 [sr_mod] age=53597/5984195/8374963 pid=558-1456 cpus=0-1 +''') +f('sys/kernel/slab/kmalloc-8/aliases', 0o664, b'0\n') +d('sys/kernel/slab/revoke_record', 0o775) +f('sys/kernel/slab/revoke_record/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/revoke_record/ctor', 0o664, b'') +f('sys/kernel/slab/revoke_record/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/revoke_record/slab_size', 0o664, b'128\n') +f('sys/kernel/slab/revoke_record/total_objects', 0o664, b'64\n') +f('sys/kernel/slab/revoke_record/slabs', 0o664, b'2\n') +f('sys/kernel/slab/revoke_record/poison', 0o664, b'1\n') +f('sys/kernel/slab/revoke_record/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/revoke_record/objs_per_slab', 0o664, b'32\n') +f('sys/kernel/slab/revoke_record/shrink', 0o664, b'') +f('sys/kernel/slab/revoke_record/trace', 0o664, b'0\n') +f('sys/kernel/slab/revoke_record/object_size', 0o664, b'32\n') +f('sys/kernel/slab/revoke_record/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/revoke_record/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/revoke_record/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/revoke_record/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/revoke_record/objects', 0o664, b'64\n') +f('sys/kernel/slab/revoke_record/order', 0o664, b'0\n') +f('sys/kernel/slab/revoke_record/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/revoke_record/store_user', 0o664, b'1\n') +f('sys/kernel/slab/revoke_record/align', 0o664, b'0\n') +f('sys/kernel/slab/revoke_record/partial', 0o664, b'0\n') +f('sys/kernel/slab/revoke_record/validate', 0o664, b'') +f('sys/kernel/slab/revoke_record/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/revoke_record/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/revoke_record/aliases', 0o664, b'0\n') +d('sys/kernel/slab/ext3_inode_cache', 0o775) +f('sys/kernel/slab/ext3_inode_cache/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/ext3_inode_cache/ctor', 0o664, b'init_once+0x0/0x70\n') +f('sys/kernel/slab/ext3_inode_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/ext3_inode_cache/slab_size', 0o664, b'1544\n') +f('sys/kernel/slab/ext3_inode_cache/total_objects', 0o664, b'27342\n') +f('sys/kernel/slab/ext3_inode_cache/slabs', 0o664, b'1302\n') +f('sys/kernel/slab/ext3_inode_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/ext3_inode_cache/alloc_calls', 0o664, b' 27338 ext3_alloc_inode+0x15/0x60 age=0/2288559/8378475 pid=1-27944 cpus=0-1\n') +f('sys/kernel/slab/ext3_inode_cache/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/ext3_inode_cache/shrink', 0o664, b'') +f('sys/kernel/slab/ext3_inode_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/ext3_inode_cache/object_size', 0o664, b'1472\n') +f('sys/kernel/slab/ext3_inode_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/ext3_inode_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/ext3_inode_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/ext3_inode_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/ext3_inode_cache/objects', 0o664, b'27342\n') +f('sys/kernel/slab/ext3_inode_cache/order', 0o664, b'3\n') +f('sys/kernel/slab/ext3_inode_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/ext3_inode_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/ext3_inode_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/ext3_inode_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/ext3_inode_cache/validate', 0o664, b'') +f('sys/kernel/slab/ext3_inode_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/ext3_inode_cache/free_calls', 0o664, b''' 25981 age=4303047521 pid=0 cpus=0 + 1358 ext3_destroy_inode+0x2f/0x90 age=13089/2437961/8371953 pid=542-32759 cpus=0-1 +''') +f('sys/kernel/slab/ext3_inode_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/ndisc_cache', 0o775) +f('sys/kernel/slab/ndisc_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/ndisc_cache/ctor', 0o664, b'') +f('sys/kernel/slab/ndisc_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/ndisc_cache/slab_size', 0o664, b'448\n') +f('sys/kernel/slab/ndisc_cache/total_objects', 0o664, b'18\n') +f('sys/kernel/slab/ndisc_cache/slabs', 0o664, b'1\n') +f('sys/kernel/slab/ndisc_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/ndisc_cache/alloc_calls', 0o664, b' 1 neigh_create+0x8b/0x530 age=8360557 pid=1549 cpus=0\n') +f('sys/kernel/slab/ndisc_cache/objs_per_slab', 0o664, b'18\n') +f('sys/kernel/slab/ndisc_cache/shrink', 0o664, b'') +f('sys/kernel/slab/ndisc_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/ndisc_cache/object_size', 0o664, b'360\n') +f('sys/kernel/slab/ndisc_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/ndisc_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/ndisc_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/ndisc_cache/objects_partial', 0o664, b'1\n') +f('sys/kernel/slab/ndisc_cache/objects', 0o664, b'1\n') +f('sys/kernel/slab/ndisc_cache/order', 0o664, b'1\n') +f('sys/kernel/slab/ndisc_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/ndisc_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/ndisc_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/ndisc_cache/partial', 0o664, b'1\n') +f('sys/kernel/slab/ndisc_cache/validate', 0o664, b'') +f('sys/kernel/slab/ndisc_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/ndisc_cache/free_calls', 0o664, b' 1 age=4303047782 pid=0 cpus=0\n') +f('sys/kernel/slab/ndisc_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/ip_fib_alias', 0o775) +f('sys/kernel/slab/ip_fib_alias/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/ctor', 0o664, b'') +f('sys/kernel/slab/ip_fib_alias/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/slab_size', 0o664, b'104\n') +f('sys/kernel/slab/ip_fib_alias/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/slabs', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/poison', 0o664, b'1\n') +f('sys/kernel/slab/ip_fib_alias/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/ip_fib_alias/objs_per_slab', 0o664, b'39\n') +f('sys/kernel/slab/ip_fib_alias/shrink', 0o664, b'') +f('sys/kernel/slab/ip_fib_alias/trace', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/object_size', 0o664, b'32\n') +f('sys/kernel/slab/ip_fib_alias/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/objects', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/order', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/ip_fib_alias/store_user', 0o664, b'1\n') +f('sys/kernel/slab/ip_fib_alias/align', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/partial', 0o664, b'0\n') +f('sys/kernel/slab/ip_fib_alias/validate', 0o664, b'') +f('sys/kernel/slab/ip_fib_alias/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/ip_fib_alias/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/ip_fib_alias/aliases', 0o664, b'0\n') +d('sys/kernel/slab/proc_inode_cache', 0o775) +f('sys/kernel/slab/proc_inode_cache/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/proc_inode_cache/ctor', 0o664, b'init_once+0x0/0x10\n') +f('sys/kernel/slab/proc_inode_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/proc_inode_cache/slab_size', 0o664, b'1192\n') +f('sys/kernel/slab/proc_inode_cache/total_objects', 0o664, b'1677\n') +f('sys/kernel/slab/proc_inode_cache/slabs', 0o664, b'129\n') +f('sys/kernel/slab/proc_inode_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/proc_inode_cache/alloc_calls', 0o664, b' 1627 proc_alloc_inode+0x1b/0x90 age=61424/8163415/8379746 pid=0-19241 cpus=0-1\n') +f('sys/kernel/slab/proc_inode_cache/objs_per_slab', 0o664, b'13\n') +f('sys/kernel/slab/proc_inode_cache/shrink', 0o664, b'') +f('sys/kernel/slab/proc_inode_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/proc_inode_cache/object_size', 0o664, b'1120\n') +f('sys/kernel/slab/proc_inode_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/proc_inode_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/proc_inode_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/proc_inode_cache/objects_partial', 0o664, b'78\n') +f('sys/kernel/slab/proc_inode_cache/objects', 0o664, b'1651\n') +f('sys/kernel/slab/proc_inode_cache/order', 0o664, b'2\n') +f('sys/kernel/slab/proc_inode_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/proc_inode_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/proc_inode_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/proc_inode_cache/partial', 0o664, b'8\n') +f('sys/kernel/slab/proc_inode_cache/validate', 0o664, b'') +f('sys/kernel/slab/proc_inode_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/proc_inode_cache/free_calls', 0o664, b''' 1124 age=4303047043 pid=0 cpus=0 + 503 proc_destroy_inode+0x14/0x20 age=61430/7970819/8372808 pid=1-12336 cpus=0-1 +''') +f('sys/kernel/slab/proc_inode_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/biovec-16', 0o775) +f('sys/kernel/slab/biovec-16/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/biovec-16/ctor', 0o664, b'') +f('sys/kernel/slab/biovec-16/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/biovec-16/slab_size', 0o664, b'384\n') +f('sys/kernel/slab/biovec-16/total_objects', 0o664, b'63\n') +f('sys/kernel/slab/biovec-16/slabs', 0o664, b'3\n') +f('sys/kernel/slab/biovec-16/poison', 0o664, b'1\n') +f('sys/kernel/slab/biovec-16/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379491/8379491/8379491 pid=1 cpus=0\n') +f('sys/kernel/slab/biovec-16/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/biovec-16/shrink', 0o664, b'') +f('sys/kernel/slab/biovec-16/trace', 0o664, b'0\n') +f('sys/kernel/slab/biovec-16/object_size', 0o664, b'256\n') +f('sys/kernel/slab/biovec-16/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/biovec-16/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/biovec-16/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/biovec-16/objects_partial', 0o664, b'2\n') +f('sys/kernel/slab/biovec-16/objects', 0o664, b'44\n') +f('sys/kernel/slab/biovec-16/order', 0o664, b'1\n') +f('sys/kernel/slab/biovec-16/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/biovec-16/store_user', 0o664, b'1\n') +f('sys/kernel/slab/biovec-16/align', 0o664, b'0\n') +f('sys/kernel/slab/biovec-16/partial', 0o664, b'1\n') +f('sys/kernel/slab/biovec-16/validate', 0o664, b'') +f('sys/kernel/slab/biovec-16/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/biovec-16/free_calls', 0o664, b' 2 age=4303046925 pid=0 cpus=0\n') +f('sys/kernel/slab/biovec-16/aliases', 0o664, b'0\n') +d('sys/kernel/slab/Acpi-State', 0o775) +f('sys/kernel/slab/Acpi-State/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-State/ctor', 0o664, b'') +f('sys/kernel/slab/Acpi-State/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-State/slab_size', 0o664, b'152\n') +f('sys/kernel/slab/Acpi-State/total_objects', 0o664, b'52\n') +f('sys/kernel/slab/Acpi-State/slabs', 0o664, b'2\n') +f('sys/kernel/slab/Acpi-State/poison', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-State/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/Acpi-State/objs_per_slab', 0o664, b'26\n') +f('sys/kernel/slab/Acpi-State/shrink', 0o664, b'') +f('sys/kernel/slab/Acpi-State/trace', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-State/object_size', 0o664, b'80\n') +f('sys/kernel/slab/Acpi-State/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-State/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-State/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-State/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-State/objects', 0o664, b'52\n') +f('sys/kernel/slab/Acpi-State/order', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-State/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-State/store_user', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-State/align', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-State/partial', 0o664, b'0\n') +f('sys/kernel/slab/Acpi-State/validate', 0o664, b'') +f('sys/kernel/slab/Acpi-State/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/Acpi-State/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/Acpi-State/aliases', 0o664, b'0\n') +d('sys/kernel/slab/ip6_dst_cache', 0o775) +f('sys/kernel/slab/ip6_dst_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/ip6_dst_cache/ctor', 0o664, b'') +f('sys/kernel/slab/ip6_dst_cache/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/ip6_dst_cache/slab_size', 0o664, b'384\n') +f('sys/kernel/slab/ip6_dst_cache/total_objects', 0o664, b'42\n') +f('sys/kernel/slab/ip6_dst_cache/slabs', 0o664, b'2\n') +f('sys/kernel/slab/ip6_dst_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/ip6_dst_cache/alloc_calls', 0o664, b' 4 dst_alloc+0x2b/0x90 age=8329964/8337614/8360566 pid=8-1549 cpus=0-1\n') +f('sys/kernel/slab/ip6_dst_cache/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/ip6_dst_cache/shrink', 0o664, b'') +f('sys/kernel/slab/ip6_dst_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/ip6_dst_cache/object_size', 0o664, b'304\n') +f('sys/kernel/slab/ip6_dst_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/ip6_dst_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/ip6_dst_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/ip6_dst_cache/objects_partial', 0o664, b'4\n') +f('sys/kernel/slab/ip6_dst_cache/objects', 0o664, b'4\n') +f('sys/kernel/slab/ip6_dst_cache/order', 0o664, b'1\n') +f('sys/kernel/slab/ip6_dst_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/ip6_dst_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/ip6_dst_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/ip6_dst_cache/partial', 0o664, b'2\n') +f('sys/kernel/slab/ip6_dst_cache/validate', 0o664, b'') +f('sys/kernel/slab/ip6_dst_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/ip6_dst_cache/free_calls', 0o664, b' 4 age=4303047790 pid=0 cpus=0\n') +f('sys/kernel/slab/ip6_dst_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/task_xstate', 0o775) +f('sys/kernel/slab/task_xstate/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/task_xstate/ctor', 0o664, b'') +f('sys/kernel/slab/task_xstate/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/task_xstate/slab_size', 0o664, b'592\n') +f('sys/kernel/slab/task_xstate/total_objects', 0o664, b'169\n') +f('sys/kernel/slab/task_xstate/slabs', 0o664, b'13\n') +f('sys/kernel/slab/task_xstate/poison', 0o664, b'1\n') +f('sys/kernel/slab/task_xstate/alloc_calls', 0o664, b''' 99 arch_dup_task_struct+0x51/0xa0 age=125559/8275901/8376574 pid=71-13212 cpus=0-1 + 51 init_fpu+0xef/0x110 age=4157/7436734/8378165 pid=1-20296 cpus=0-1 +''') +f('sys/kernel/slab/task_xstate/objs_per_slab', 0o664, b'13\n') +f('sys/kernel/slab/task_xstate/shrink', 0o664, b'') +f('sys/kernel/slab/task_xstate/trace', 0o664, b'0\n') +f('sys/kernel/slab/task_xstate/object_size', 0o664, b'512\n') +f('sys/kernel/slab/task_xstate/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/task_xstate/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/task_xstate/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/task_xstate/objects_partial', 0o664, b'57\n') +f('sys/kernel/slab/task_xstate/objects', 0o664, b'161\n') +f('sys/kernel/slab/task_xstate/order', 0o664, b'1\n') +f('sys/kernel/slab/task_xstate/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/task_xstate/store_user', 0o664, b'1\n') +f('sys/kernel/slab/task_xstate/align', 0o664, b'16\n') +f('sys/kernel/slab/task_xstate/partial', 0o664, b'5\n') +f('sys/kernel/slab/task_xstate/validate', 0o664, b'') +f('sys/kernel/slab/task_xstate/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/task_xstate/free_calls', 0o664, b''' 53 age=4303047277 pid=0 cpus=0 + 97 free_thread_xstate+0x24/0x40 age=7199/7795238/8375118 pid=0-20296 cpus=0-1 +''') +f('sys/kernel/slab/task_xstate/aliases', 0o664, b'0\n') +d('sys/kernel/slab/scsi_io_context', 0o775) +f('sys/kernel/slab/scsi_io_context/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/ctor', 0o664, b'') +f('sys/kernel/slab/scsi_io_context/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/slab_size', 0o664, b'184\n') +f('sys/kernel/slab/scsi_io_context/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/slabs', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/poison', 0o664, b'1\n') +f('sys/kernel/slab/scsi_io_context/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/scsi_io_context/objs_per_slab', 0o664, b'22\n') +f('sys/kernel/slab/scsi_io_context/shrink', 0o664, b'') +f('sys/kernel/slab/scsi_io_context/trace', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/object_size', 0o664, b'112\n') +f('sys/kernel/slab/scsi_io_context/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/objects', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/order', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/scsi_io_context/store_user', 0o664, b'1\n') +f('sys/kernel/slab/scsi_io_context/align', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/partial', 0o664, b'0\n') +f('sys/kernel/slab/scsi_io_context/validate', 0o664, b'') +f('sys/kernel/slab/scsi_io_context/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/scsi_io_context/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/scsi_io_context/aliases', 0o664, b'0\n') +d('sys/kernel/slab/anon_vma', 0o775) +f('sys/kernel/slab/anon_vma/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/anon_vma/ctor', 0o664, b'anon_vma_ctor+0x0/0x40\n') +f('sys/kernel/slab/anon_vma/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/anon_vma/slab_size', 0o664, b'144\n') +f('sys/kernel/slab/anon_vma/total_objects', 0o664, b'3304\n') +f('sys/kernel/slab/anon_vma/slabs', 0o664, b'118\n') +f('sys/kernel/slab/anon_vma/poison', 0o664, b'1\n') +f('sys/kernel/slab/anon_vma/alloc_calls', 0o664, b' 3234 anon_vma_prepare+0xe0/0x100 age=4177/7981073/8378201 pid=1-20296 cpus=0-1\n') +f('sys/kernel/slab/anon_vma/objs_per_slab', 0o664, b'28\n') +f('sys/kernel/slab/anon_vma/shrink', 0o664, b'') +f('sys/kernel/slab/anon_vma/trace', 0o664, b'0\n') +f('sys/kernel/slab/anon_vma/object_size', 0o664, b'72\n') +f('sys/kernel/slab/anon_vma/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/anon_vma/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/anon_vma/destroy_by_rcu', 0o664, b'1\n') +f('sys/kernel/slab/anon_vma/objects_partial', 0o664, b'185\n') +f('sys/kernel/slab/anon_vma/objects', 0o664, b'3265\n') +f('sys/kernel/slab/anon_vma/order', 0o664, b'0\n') +f('sys/kernel/slab/anon_vma/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/anon_vma/store_user', 0o664, b'1\n') +f('sys/kernel/slab/anon_vma/align', 0o664, b'0\n') +f('sys/kernel/slab/anon_vma/partial', 0o664, b'8\n') +f('sys/kernel/slab/anon_vma/validate', 0o664, b'') +f('sys/kernel/slab/anon_vma/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/anon_vma/free_calls', 0o664, b''' 1575 age=4303047296 pid=0 cpus=0 + 1659 anon_vma_unlink+0x5f/0x70 age=7225/7638870/8377152 pid=56-20292 cpus=0-1 +''') +f('sys/kernel/slab/anon_vma/aliases', 0o664, b'0\n') +d('sys/kernel/slab/uhci_urb_priv', 0o775) +f('sys/kernel/slab/uhci_urb_priv/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/uhci_urb_priv/ctor', 0o664, b'') +f('sys/kernel/slab/uhci_urb_priv/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/uhci_urb_priv/slab_size', 0o664, b'128\n') +f('sys/kernel/slab/uhci_urb_priv/total_objects', 0o664, b'32\n') +f('sys/kernel/slab/uhci_urb_priv/slabs', 0o664, b'1\n') +f('sys/kernel/slab/uhci_urb_priv/poison', 0o664, b'1\n') +f('sys/kernel/slab/uhci_urb_priv/alloc_calls', 0o664, b' 1 uhci_urb_enqueue+0xb6/0xa30 [uhci_hcd] age=53794 pid=419 cpus=0\n') +f('sys/kernel/slab/uhci_urb_priv/objs_per_slab', 0o664, b'32\n') +f('sys/kernel/slab/uhci_urb_priv/shrink', 0o664, b'') +f('sys/kernel/slab/uhci_urb_priv/trace', 0o664, b'0\n') +f('sys/kernel/slab/uhci_urb_priv/object_size', 0o664, b'56\n') +f('sys/kernel/slab/uhci_urb_priv/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/uhci_urb_priv/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/uhci_urb_priv/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/uhci_urb_priv/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/uhci_urb_priv/objects', 0o664, b'32\n') +f('sys/kernel/slab/uhci_urb_priv/order', 0o664, b'0\n') +f('sys/kernel/slab/uhci_urb_priv/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/uhci_urb_priv/store_user', 0o664, b'1\n') +f('sys/kernel/slab/uhci_urb_priv/align', 0o664, b'0\n') +f('sys/kernel/slab/uhci_urb_priv/partial', 0o664, b'0\n') +f('sys/kernel/slab/uhci_urb_priv/validate', 0o664, b'') +f('sys/kernel/slab/uhci_urb_priv/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/uhci_urb_priv/free_calls', 0o664, b' 1 uhci_free_urb_priv+0x79/0xd0 [uhci_hcd] age=53806 pid=0 cpus=0\n') +f('sys/kernel/slab/uhci_urb_priv/aliases', 0o664, b'0\n') +d('sys/kernel/slab/shmem_inode_cache', 0o775) +f('sys/kernel/slab/shmem_inode_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/shmem_inode_cache/ctor', 0o664, b'init_once+0x0/0x40\n') +f('sys/kernel/slab/shmem_inode_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/shmem_inode_cache/slab_size', 0o664, b'1400\n') +f('sys/kernel/slab/shmem_inode_cache/total_objects', 0o664, b'1173\n') +f('sys/kernel/slab/shmem_inode_cache/slabs', 0o664, b'51\n') +f('sys/kernel/slab/shmem_inode_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/shmem_inode_cache/alloc_calls', 0o664, b' 1144 shmem_alloc_inode+0x15/0x30 age=21584/7506265/8379043 pid=1-13453 cpus=0-1\n') +f('sys/kernel/slab/shmem_inode_cache/objs_per_slab', 0o664, b'23\n') +f('sys/kernel/slab/shmem_inode_cache/shrink', 0o664, b'') +f('sys/kernel/slab/shmem_inode_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/shmem_inode_cache/object_size', 0o664, b'1328\n') +f('sys/kernel/slab/shmem_inode_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/shmem_inode_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/shmem_inode_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/shmem_inode_cache/objects_partial', 0o664, b'42\n') +f('sys/kernel/slab/shmem_inode_cache/objects', 0o664, b'1169\n') +f('sys/kernel/slab/shmem_inode_cache/order', 0o664, b'3\n') +f('sys/kernel/slab/shmem_inode_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/shmem_inode_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/shmem_inode_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/shmem_inode_cache/partial', 0o664, b'2\n') +f('sys/kernel/slab/shmem_inode_cache/validate', 0o664, b'') +f('sys/kernel/slab/shmem_inode_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/shmem_inode_cache/free_calls', 0o664, b''' 741 age=4303046628 pid=0 cpus=0 + 403 shmem_destroy_inode+0x24/0x30 age=21598/7406739/8375758 pid=72-13332 cpus=0-1 +''') +f('sys/kernel/slab/shmem_inode_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/fat_inode_cache', 0o775) +f('sys/kernel/slab/fat_inode_cache/reclaim_account', 0o664, b'1\n') +f('sys/kernel/slab/fat_inode_cache/ctor', 0o664, b'init_once+0x0/0x60\n') +f('sys/kernel/slab/fat_inode_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/fat_inode_cache/slab_size', 0o664, b'1272\n') +f('sys/kernel/slab/fat_inode_cache/total_objects', 0o664, b'100\n') +f('sys/kernel/slab/fat_inode_cache/slabs', 0o664, b'4\n') +f('sys/kernel/slab/fat_inode_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/fat_inode_cache/alloc_calls', 0o664, b' 76 fat_alloc_inode+0x15/0x30 age=61228/61276/61657 pid=13348-13354 cpus=0-1\n') +f('sys/kernel/slab/fat_inode_cache/objs_per_slab', 0o664, b'25\n') +f('sys/kernel/slab/fat_inode_cache/shrink', 0o664, b'') +f('sys/kernel/slab/fat_inode_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/fat_inode_cache/object_size', 0o664, b'1200\n') +f('sys/kernel/slab/fat_inode_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/fat_inode_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/fat_inode_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/fat_inode_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/fat_inode_cache/objects', 0o664, b'100\n') +f('sys/kernel/slab/fat_inode_cache/order', 0o664, b'3\n') +f('sys/kernel/slab/fat_inode_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/fat_inode_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/fat_inode_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/fat_inode_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/fat_inode_cache/validate', 0o664, b'') +f('sys/kernel/slab/fat_inode_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/fat_inode_cache/free_calls', 0o664, b' 76 age=4303047594 pid=0 cpus=0\n') +f('sys/kernel/slab/fat_inode_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-256', 0o775) +f('sys/kernel/slab/kmalloc-256/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-256/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-256/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-256/slab_size', 0o664, b'328\n') +f('sys/kernel/slab/kmalloc-256/total_objects', 0o664, b'516\n') +f('sys/kernel/slab/kmalloc-256/slabs', 0o664, b'43\n') +f('sys/kernel/slab/kmalloc-256/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-256/alloc_calls', 0o664, b''' 2 mempool_kmalloc+0x11/0x20 age=8379928/8379928/8379928 pid=1 cpus=0 + 2 __vmalloc_area_node+0xfb/0x140 age=8374585/8375388/8376192 pid=122-126 cpus=0-1 + 32 dma_pool_create+0x90/0x1e0 age=8374074/8374505/8374905 pid=143-147 cpus=0-1 + 28 __percpu_alloc_mask+0xbc/0x140 age=8360136/8365750/8379780 pid=1-1549 cpus=0 + 2 seq_open+0x84/0xa0 age=8355780/8360929/8366079 pid=1371-1738 cpus=0 + 19 inotify_init+0x1b/0x90 age=8333719/8353284/8379778 pid=1-2544 cpus=0-1 + 1 mounts_open_common+0x11e/0x210 age=8365844 pid=1371 cpus=0 + 347 __proc_create+0xa5/0x150 age=8355314/8375854/8380066 pid=0-1813 cpus=0-1 + 6 start_this_handle+0x3f5/0x410 age=4241/38502/142468 pid=21-13466 cpus=0-1 + 3 elevator_alloc+0x1b/0xc0 age=62010/5606790/8379345 pid=1-13295 cpus=0-1 + 2 acpi_ds_build_internal_buffer_obj+0xe1/0x121 age=8379913/8379914/8379915 pid=1 cpus=0 + 1 find_dock+0x414/0x426 age=8379931 pid=1 cpus=0 + 6 con_insert_unipair+0x96/0x110 age=8355034/8367399/8379765 pid=1-1898 cpus=1 + 2 neigh_resolve_output+0x226/0x2e0 age=1134112/4736669/8339226 pid=0-2401 cpus=0-1 + 1 genl_register_family+0x1b6/0x1e0 age=8375014 pid=126 cpus=0 + 5 ip_mc_inc_group+0x6b/0x280 age=8325482/8352347/8367852 pid=1185-1849 cpus=0-1 + 2 cache_add_dev+0x17b/0x546 age=8379779/8379779/8379780 pid=1 cpus=0-1 + 10 audit_register_class+0x1e/0xa1 age=8379779/8379779/8379779 pid=1 cpus=1 + 1 proc_net_ns_init+0x1b/0x81 age=8380066 pid=0 cpus=0 + 3 snd_malloc_sgbuf_pages+0xfa/0x1f0 [snd_page_alloc] age=8374129/8374129/8374129 pid=107 cpus=1 + 1 usb_get_configuration+0x18f/0x1480 [usbcore] age=8372709 pid=419 cpus=0 + 1 acpi_ac_add+0x3a/0x1b1 [ac] age=8375784 pid=392 cpus=0 + 1 acpi_processor_register_performance+0x2a0/0x3a6 [processor] age=8366391 pid=1358 cpus=0 + 3 snd_ctl_open+0x8e/0x180 [snd] age=8333026/8337179/8339273 pid=2400-2425 cpus=0 + 8 ieee80211_rx_bss_add+0x4e/0x140 [mac80211] age=8354793/8355457/8355979 pid=0-1951 cpus=0 + 2 ipv6_add_addr+0x199/0x3c0 [ipv6] age=8329536/8344837/8360138 pid=8-1549 cpus=0-1 + 5 ipv6_dev_mc_inc+0x141/0x3f0 [ipv6] age=8329536/8354016/8360138 pid=8-1549 cpus=0-1 +''') +f('sys/kernel/slab/kmalloc-256/objs_per_slab', 0o664, b'12\n') +f('sys/kernel/slab/kmalloc-256/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-256/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-256/object_size', 0o664, b'256\n') +f('sys/kernel/slab/kmalloc-256/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-256/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-256/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-256/objects_partial', 0o664, b'60\n') +f('sys/kernel/slab/kmalloc-256/objects', 0o664, b'504\n') +f('sys/kernel/slab/kmalloc-256/order', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-256/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-256/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-256/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-256/partial', 0o664, b'6\n') +f('sys/kernel/slab/kmalloc-256/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-256/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-256/free_calls', 0o664, b''' 389 age=4303047363 pid=0 cpus=0 + 1 __vunmap+0xe9/0x120 age=8374878 pid=107 cpus=1 + 38 do_execve+0x2b1/0x2d0 age=7303/7294190/8377088 pid=71-13465 cpus=0-1 + 51 seq_release+0x20/0x30 age=23541/7877166/8376202 pid=105-2535 cpus=0-1 + 3 free_proc_entry+0x73/0x90 age=8356279/8369643/8378992 pid=1-1541 cpus=0 + 3 __journal_drop_transaction+0xe6/0x170 age=8360317/8363466/8366128 pid=32 cpus=0 + 1 acpi_pci_irq_add_prt+0xc2/0x324 age=8379845 pid=1 cpus=0 + 2 acpi_pci_bind+0x26b/0x28d age=8379844/8379845/8379846 pid=1 cpus=0 + 1 wireless_send_event+0x172/0x330 age=8329538 pid=742 cpus=1 + 3 usb_string+0x17c/0x1e0 [usbcore] age=8374367/8374614/8374886 pid=143 cpus=0 + 3 snd_ctl_release+0xf9/0x130 [snd] age=8333027/8337180/8339274 pid=2400-2425 cpus=0 + 1 ieee80211_set_associated+0x421/0x520 [mac80211] age=8329538 pid=742 cpus=1 +''') +f('sys/kernel/slab/kmalloc-256/aliases', 0o664, b'0\n') +d('sys/kernel/slab/biovec-64', 0o775) +f('sys/kernel/slab/biovec-64/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/biovec-64/ctor', 0o664, b'') +f('sys/kernel/slab/biovec-64/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/biovec-64/slab_size', 0o664, b'1152\n') +f('sys/kernel/slab/biovec-64/total_objects', 0o664, b'28\n') +f('sys/kernel/slab/biovec-64/slabs', 0o664, b'2\n') +f('sys/kernel/slab/biovec-64/poison', 0o664, b'1\n') +f('sys/kernel/slab/biovec-64/alloc_calls', 0o664, b' 2 mempool_alloc_slab+0x11/0x20 age=8379482/8379482/8379482 pid=1 cpus=0\n') +f('sys/kernel/slab/biovec-64/objs_per_slab', 0o664, b'14\n') +f('sys/kernel/slab/biovec-64/shrink', 0o664, b'') +f('sys/kernel/slab/biovec-64/trace', 0o664, b'0\n') +f('sys/kernel/slab/biovec-64/object_size', 0o664, b'1024\n') +f('sys/kernel/slab/biovec-64/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/biovec-64/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/biovec-64/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/biovec-64/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/biovec-64/objects', 0o664, b'28\n') +f('sys/kernel/slab/biovec-64/order', 0o664, b'2\n') +f('sys/kernel/slab/biovec-64/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/biovec-64/store_user', 0o664, b'1\n') +f('sys/kernel/slab/biovec-64/align', 0o664, b'0\n') +f('sys/kernel/slab/biovec-64/partial', 0o664, b'0\n') +f('sys/kernel/slab/biovec-64/validate', 0o664, b'') +f('sys/kernel/slab/biovec-64/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/biovec-64/free_calls', 0o664, b' 2 age=4303046917 pid=0 cpus=0\n') +f('sys/kernel/slab/biovec-64/aliases', 0o664, b'0\n') +d('sys/kernel/slab/sysfs_dir_cache', 0o775) +f('sys/kernel/slab/sysfs_dir_cache/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/sysfs_dir_cache/ctor', 0o664, b'') +f('sys/kernel/slab/sysfs_dir_cache/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/sysfs_dir_cache/slab_size', 0o664, b'152\n') +f('sys/kernel/slab/sysfs_dir_cache/total_objects', 0o664, b'11518\n') +f('sys/kernel/slab/sysfs_dir_cache/slabs', 0o664, b'443\n') +f('sys/kernel/slab/sysfs_dir_cache/poison', 0o664, b'1\n') +f('sys/kernel/slab/sysfs_dir_cache/alloc_calls', 0o664, b' 11488 sysfs_new_dirent+0x38/0x120 age=22320/7764235/8379787 pid=0-13295 cpus=0-1\n') +f('sys/kernel/slab/sysfs_dir_cache/objs_per_slab', 0o664, b'26\n') +f('sys/kernel/slab/sysfs_dir_cache/shrink', 0o664, b'') +f('sys/kernel/slab/sysfs_dir_cache/trace', 0o664, b'0\n') +f('sys/kernel/slab/sysfs_dir_cache/object_size', 0o664, b'80\n') +f('sys/kernel/slab/sysfs_dir_cache/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/sysfs_dir_cache/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/sysfs_dir_cache/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/sysfs_dir_cache/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/sysfs_dir_cache/objects', 0o664, b'11518\n') +f('sys/kernel/slab/sysfs_dir_cache/order', 0o664, b'0\n') +f('sys/kernel/slab/sysfs_dir_cache/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/sysfs_dir_cache/store_user', 0o664, b'1\n') +f('sys/kernel/slab/sysfs_dir_cache/align', 0o664, b'0\n') +f('sys/kernel/slab/sysfs_dir_cache/partial', 0o664, b'0\n') +f('sys/kernel/slab/sysfs_dir_cache/validate', 0o664, b'') +f('sys/kernel/slab/sysfs_dir_cache/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/sysfs_dir_cache/free_calls', 0o664, b''' 11006 age=4303047087 pid=0 cpus=0 + 482 release_sysfs_dirent+0x5c/0xd0 age=61294/6319346/8379456 pid=1-2141 cpus=0-1 +''') +f('sys/kernel/slab/sysfs_dir_cache/aliases', 0o664, b'0\n') +d('sys/kernel/slab/request_sock_TCP', 0o775) +f('sys/kernel/slab/request_sock_TCP/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/ctor', 0o664, b'') +f('sys/kernel/slab/request_sock_TCP/hwcache_align', 0o664, b'1\n') +f('sys/kernel/slab/request_sock_TCP/slab_size', 0o664, b'192\n') +f('sys/kernel/slab/request_sock_TCP/total_objects', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/slabs', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/poison', 0o664, b'1\n') +f('sys/kernel/slab/request_sock_TCP/alloc_calls', 0o664, b'No data\n') +f('sys/kernel/slab/request_sock_TCP/objs_per_slab', 0o664, b'21\n') +f('sys/kernel/slab/request_sock_TCP/shrink', 0o664, b'') +f('sys/kernel/slab/request_sock_TCP/trace', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/object_size', 0o664, b'88\n') +f('sys/kernel/slab/request_sock_TCP/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/objects_partial', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/objects', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/order', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/request_sock_TCP/store_user', 0o664, b'1\n') +f('sys/kernel/slab/request_sock_TCP/align', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/partial', 0o664, b'0\n') +f('sys/kernel/slab/request_sock_TCP/validate', 0o664, b'') +f('sys/kernel/slab/request_sock_TCP/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/request_sock_TCP/free_calls', 0o664, b'No data\n') +f('sys/kernel/slab/request_sock_TCP/aliases', 0o664, b'0\n') +d('sys/kernel/slab/kmalloc-4096', 0o775) +f('sys/kernel/slab/kmalloc-4096/reclaim_account', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-4096/ctor', 0o664, b'') +f('sys/kernel/slab/kmalloc-4096/hwcache_align', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-4096/slab_size', 0o664, b'4168\n') +f('sys/kernel/slab/kmalloc-4096/total_objects', 0o664, b'385\n') +f('sys/kernel/slab/kmalloc-4096/slabs', 0o664, b'55\n') +f('sys/kernel/slab/kmalloc-4096/poison', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-4096/alloc_calls', 0o664, b''' 1 load_module+0x18d5/0x1b30 age=8375716 pid=330 cpus=0 + 1 __vmalloc_area_node+0xfb/0x140 age=8371983 pid=867 cpus=0 + 24 __percpu_alloc_mask+0xbc/0x140 age=8360098/8363374/8379742 pid=1-1549 cpus=0 + 1 seq_read+0x2f0/0x360 age=8365263 pid=1371 cpus=0 + 2 ext3_fill_super+0x68/0x1a20 age=8369599/8373987/8378375 pid=1-962 cpus=0 + 4 journal_init_revoke_table+0x4d/0xb0 age=8369583/8373933/8378283 pid=1-962 cpus=0 + 2 journal_init_inode+0x8d/0x130 age=8369583/8373933/8378283 pid=1-962 cpus=0 + 1 fat_fill_super+0x40/0xdd0 age=61388 pid=13348 cpus=1 + 7 scsi_host_alloc+0x35/0x360 age=66976/7192011/8379690 pid=1-419 cpus=0-1 + 3 scsi_alloc_sdev+0x6a/0x270 age=61972/5606752/8379307 pid=1-13295 cpus=0-1 + 8 input_allocate_device+0x1a/0xb0 age=53455/7335718/8378931 pid=17-419 cpus=0-1 + 1 reqsk_queue_alloc+0x112/0x120 age=8354535 pid=1920 cpus=0 + 3 alloc_netdev_mq+0x4f/0x180 age=8373564/8375671/8379766 pid=1-126 cpus=0-1 + 1 pidmap_init+0x15/0x4e age=8380028 pid=0 cpus=0 + 1 netlink_proto_init+0x47/0x16b age=8379894 pid=1 cpus=0 + 2 acpi_processor_add+0x25/0x6d [processor] age=8375653/8375684/8375715 pid=330 cpus=0 + 1 yenta_probe+0x38/0x6cd [yenta_socket] age=8373766 pid=352 cpus=0 + 281 iwl3945_rx_allocate+0xd5/0x160 [iwl3945] age=2011/7577/13684 pid=733 cpus=0 + 1 skcipher_geniv_alloc+0x304/0x3f0 [crypto_blkcipher] age=8374372 pid=215 cpus=1 + 2 bitmap_get_counter+0x153/0x220 [md_mod] age=8370027/8370029/8370031 pid=916 cpus=0 + 1 bitmap_create+0x2bc/0xad0 [md_mod] age=8370031 pid=916 cpus=0 + 6 __addrconf_sysctl_register+0x7b/0x140 [ipv6] age=8360098/8360099/8360101 pid=1549 cpus=0 + 1 acm_probe+0x34c/0xa50 [cdc_acm] age=22641 pid=419 cpus=0 +''') +f('sys/kernel/slab/kmalloc-4096/objs_per_slab', 0o664, b'7\n') +f('sys/kernel/slab/kmalloc-4096/shrink', 0o664, b'') +f('sys/kernel/slab/kmalloc-4096/trace', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-4096/object_size', 0o664, b'4096\n') +f('sys/kernel/slab/kmalloc-4096/cpu_slabs', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-4096/cache_dma', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-4096/destroy_by_rcu', 0o664, b'0\n') +f('sys/kernel/slab/kmalloc-4096/objects_partial', 0o664, b'17\n') +f('sys/kernel/slab/kmalloc-4096/objects', 0o664, b'367\n') +f('sys/kernel/slab/kmalloc-4096/order', 0o664, b'3\n') +f('sys/kernel/slab/kmalloc-4096/sanity_checks', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-4096/store_user', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-4096/align', 0o664, b'8\n') +f('sys/kernel/slab/kmalloc-4096/partial', 0o664, b'5\n') +f('sys/kernel/slab/kmalloc-4096/validate', 0o664, b'') +f('sys/kernel/slab/kmalloc-4096/red_zone', 0o664, b'1\n') +f('sys/kernel/slab/kmalloc-4096/free_calls', 0o664, b''' 187 age=4303047324 pid=0 cpus=0 + 5 seq_release+0x18/0x30 age=61430/6709712/8374782 pid=107-1371 cpus=0-1 + 1 cryptomgr_probe+0x81/0xf0 age=8373564 pid=745 cpus=0 + 30 kobject_uevent_env+0x122/0x470 age=22643/7542644/8379894 pid=1-1549 cpus=0-1 + 1 show_uevent+0xee/0x110 age=2013 pid=13466 cpus=0 + 1 input_dev_release+0x23/0x40 age=8378913 pid=17 cpus=0 + 130 skb_release_data+0x85/0xd0 age=2011/73374/8354535 pid=0-13466 cpus=0-1 +''') +f('sys/kernel/slab/kmalloc-4096/aliases', 0o664, b'0\n') +d('sys/kernel/debug', 0o775) +d('sys/kernel/debug/x86', 0o775) +f('sys/kernel/debug/x86/pat_memtype_list', 0o664, b'') +d('sys/kernel/debug/bdi', 0o775) +d('sys/kernel/debug/bdi/7:1', 0o775) +f('sys/kernel/debug/bdi/7:1/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189288 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/7:0', 0o775) +f('sys/kernel/debug/bdi/7:0/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189292 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/7:2', 0o775) +f('sys/kernel/debug/bdi/7:2/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189288 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/7:4', 0o775) +f('sys/kernel/debug/bdi/7:4/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189288 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/7:3', 0o775) +f('sys/kernel/debug/bdi/7:3/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189288 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/11:0', 0o775) +f('sys/kernel/debug/bdi/11:0/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189292 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/7:5', 0o775) +f('sys/kernel/debug/bdi/7:5/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189288 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/8:0', 0o775) +f('sys/kernel/debug/bdi/8:0/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 13696 kB +BdiDirtyThresh: 83368 kB +DirtyThresh: 189292 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/default', 0o775) +f('sys/kernel/debug/bdi/default/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189292 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/0:16', 0o775) +f('sys/kernel/debug/bdi/0:16/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189272 kB +BackgroundThresh: 94636 kB +''') +d('sys/kernel/debug/bdi/8:16', 0o775) +f('sys/kernel/debug/bdi/8:16/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189272 kB +BackgroundThresh: 94636 kB +''') +d('sys/kernel/debug/bdi/9:0', 0o775) +f('sys/kernel/debug/bdi/9:0/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189292 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/7:7', 0o775) +f('sys/kernel/debug/bdi/7:7/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189288 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/debug/bdi/7:6', 0o775) +f('sys/kernel/debug/bdi/7:6/stats', 0o664, b'''BdiWriteback: 0 kB +BdiReclaimable: 0 kB +BdiDirtyThresh: 0 kB +DirtyThresh: 189288 kB +BackgroundThresh: 94644 kB +''') +d('sys/kernel/uids', 0o775) +d('sys/kernel/uids/100', 0o775) +f('sys/kernel/uids/100/cpu_share', 0o664, b'1024\n') +d('sys/kernel/uids/103', 0o775) +f('sys/kernel/uids/103/cpu_share', 0o664, b'1024\n') +d('sys/kernel/uids/51', 0o775) +f('sys/kernel/uids/51/cpu_share', 0o664, b'1024\n') +d('sys/kernel/uids/105', 0o775) +f('sys/kernel/uids/105/cpu_share', 0o664, b'1024\n') +d('sys/kernel/uids/2702', 0o775) +f('sys/kernel/uids/2702/cpu_share', 0o664, b'1024\n') +d('sys/kernel/uids/0', 0o775) +f('sys/kernel/uids/0/cpu_share', 0o664, b'2048\n') +d('sys/power', 0o775) +f('sys/power/state', 0o664, b'mem\n') +d('sys/firmware', 0o775) +d('sys/firmware/memmap', 0o775) +d('sys/firmware/memmap/8', 0o775) +f('sys/firmware/memmap/8/start', 0o664, b'0xfec00000\n') +f('sys/firmware/memmap/8/type', 0o664, b'reserved\n') +f('sys/firmware/memmap/8/end', 0o664, b'0xfec0ffff\n') +d('sys/firmware/memmap/11', 0o775) +f('sys/firmware/memmap/11/start', 0o664, b'0xfed1c000\n') +f('sys/firmware/memmap/11/type', 0o664, b'reserved\n') +f('sys/firmware/memmap/11/end', 0o664, b'0xfed8ffff\n') +d('sys/firmware/memmap/6', 0o775) +f('sys/firmware/memmap/6/start', 0o664, b'0x7ff00000\n') +f('sys/firmware/memmap/6/type', 0o664, b'reserved\n') +f('sys/firmware/memmap/6/end', 0o664, b'0x7fffffff\n') +d('sys/firmware/memmap/5', 0o775) +f('sys/firmware/memmap/5/start', 0o664, b'0x7fedf000\n') +f('sys/firmware/memmap/5/type', 0o664, b'ACPI Non-volatile Storage\n') +f('sys/firmware/memmap/5/end', 0o664, b'0x7fefffff\n') +d('sys/firmware/memmap/9', 0o775) +f('sys/firmware/memmap/9/start', 0o664, b'0xfed00000\n') +f('sys/firmware/memmap/9/type', 0o664, b'reserved\n') +f('sys/firmware/memmap/9/end', 0o664, b'0xfed003ff\n') +d('sys/firmware/memmap/2', 0o775) +f('sys/firmware/memmap/2/start', 0o664, b'0xdc000\n') +f('sys/firmware/memmap/2/type', 0o664, b'reserved\n') +f('sys/firmware/memmap/2/end', 0o664, b'0xfffff\n') +d('sys/firmware/memmap/12', 0o775) +f('sys/firmware/memmap/12/start', 0o664, b'0xfee00000\n') +f('sys/firmware/memmap/12/type', 0o664, b'reserved\n') +f('sys/firmware/memmap/12/end', 0o664, b'0xfee00fff\n') +d('sys/firmware/memmap/4', 0o775) +f('sys/firmware/memmap/4/start', 0o664, b'0x7fed0000\n') +f('sys/firmware/memmap/4/type', 0o664, b'ACPI Tables\n') +f('sys/firmware/memmap/4/end', 0o664, b'0x7fedefff\n') +d('sys/firmware/memmap/3', 0o775) +f('sys/firmware/memmap/3/start', 0o664, b'0x100000\n') +f('sys/firmware/memmap/3/type', 0o664, b'System RAM\n') +f('sys/firmware/memmap/3/end', 0o664, b'0x7fecffff\n') +d('sys/firmware/memmap/10', 0o775) +f('sys/firmware/memmap/10/start', 0o664, b'0xfed14000\n') +f('sys/firmware/memmap/10/type', 0o664, b'reserved\n') +f('sys/firmware/memmap/10/end', 0o664, b'0xfed19fff\n') +d('sys/firmware/memmap/0', 0o775) +f('sys/firmware/memmap/0/start', 0o664, b'0x0\n') +f('sys/firmware/memmap/0/type', 0o664, b'System RAM\n') +f('sys/firmware/memmap/0/end', 0o664, b'0x9efff\n') +d('sys/firmware/memmap/7', 0o775) +f('sys/firmware/memmap/7/start', 0o664, b'0xf0000000\n') +f('sys/firmware/memmap/7/type', 0o664, b'reserved\n') +f('sys/firmware/memmap/7/end', 0o664, b'0xf3ffffff\n') +d('sys/firmware/memmap/1', 0o775) +f('sys/firmware/memmap/1/start', 0o664, b'0x9f000\n') +f('sys/firmware/memmap/1/type', 0o664, b'reserved\n') +f('sys/firmware/memmap/1/end', 0o664, b'0x9ffff\n') +d('sys/firmware/memmap/13', 0o775) +f('sys/firmware/memmap/13/start', 0o664, b'0xff800000\n') +f('sys/firmware/memmap/13/type', 0o664, b'reserved\n') +f('sys/firmware/memmap/13/end', 0o664, b'0xffffffff\n') +d('sys/firmware/edd', 0o775) +d('sys/firmware/edd/int13_dev80', 0o775) +l('sys/firmware/edd/int13_dev80/pci_dev', '../../../devices/pci0000:00/0000:00:1f.2') +f('sys/firmware/edd/int13_dev80/version', 0o664, b'0x30\n') +f('sys/firmware/edd/int13_dev80/raw_data', 0o664, b'J\x00\x01\x00\xff?\x00\x00\x10\x00\x00\x00?\x00\x00\x000"\xa5\x0b\x00\x00\x00\x00\x00\x02\xc6\x00@\x00\xdd\xbe,\x00\x00\x00PCI ATA \x00\x1f\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa5') +f('sys/firmware/edd/int13_dev80/sectors', 0o664, b'195371568\n') +f('sys/firmware/edd/int13_dev80/default_sectors_per_track', 0o664, b'63\n') +f('sys/firmware/edd/int13_dev80/legacy_max_cylinder', 0o664, b'1022\n') +f('sys/firmware/edd/int13_dev80/interface', 0o664, b'ATA \tdevice: 0\n') +f('sys/firmware/edd/int13_dev80/host_bus', 0o664, b'PCI \t00:1f.2 channel: 1\n') +f('sys/firmware/edd/int13_dev80/legacy_max_head', 0o664, b'239\n') +f('sys/firmware/edd/int13_dev80/mbr_signature', 0o664, b'0x00087b5f\n') +f('sys/firmware/edd/int13_dev80/info_flags', 0o664, b'DMA boundary error transparent\n') +f('sys/firmware/edd/int13_dev80/default_heads', 0o664, b'16\n') +f('sys/firmware/edd/int13_dev80/default_cylinders', 0o664, b'16383\n') +f('sys/firmware/edd/int13_dev80/legacy_sectors_per_track', 0o664, b'63\n') +f('sys/firmware/edd/int13_dev80/extensions', 0o664, b'''Fixed disk access +Enhanced Disk Drive support +''') +d('sys/firmware/acpi', 0o775) +d('sys/firmware/acpi/tables', 0o775) +f('sys/firmware/acpi/tables/DSDT', 0o664, b'''DSDT4\xd2\x00\x00\x01\x9aLENOVOTP-7I \x11\x00\x00MSFT\x0e\x00\x00\x01\x10 \\_PR_[\x83\x0bCPU0\x00\x10\x10\x00\x00\x06[\x83\x0bCPU1\x01\x10\x10\x00\x00\x06\x10\x83I\x0b\\_SB_\x14C2_INI\x00\xa0(\x93\\SCMP\\_OS_\rMicrosoft Windows\x00\x00p +\x01\\W98F\xa1C\x11\xa0F\t[\x12\\_OSI`\xa0,\\_OSI\rWindows 2001\x00p +\x01\\WNTFp +\x01\\WXPFp +\x00\\WSPV\xa0 \\_OSI\rWindows 2001 SP1\x00p +\x01\\WSPV\xa0 \\_OSI\rWindows 2001 SP2\x00p +\x02\\WSPV\xa0\x1c\\_OSI\rWindows 2006\x00p +\x01\\WVIS\xa1I\x07\xa0+\x93\\SCMP\\_OS_\rMicrosoft Windows NT\x00\x00p +\x01\\WNTF\xa1J\x04\xa0G\x04\x93\\SCMP\\_OS_\rMicrosoft WindowsME: Millennium Edition\x00\x00p +\x01\\WMEFp +\x01\\W98F\xa0\x12\x92\x95\\_REV +\x02p +\x01\\H8DRp +\x01\\OSIF\\/\x05_SB_PCI0LPC_MOU_MHIDp\\SRAH\\/\x03_SB_PCI0RID_\xa0\x1eVIGDp\\SRHE\\/\x04_SB_PCI0VID_RID_\xa1\x1ap\\SRHE\\/\x04_SB_PCI0AGP_RID_p\\SRE0\\/\x04_SB_PCI0EXP0RID_p\\SRE1\\/\x04_SB_PCI0EXP1RID_p\\SRE2\\/\x04_SB_PCI0EXP2RID_p\\SRE3\\/\x04_SB_PCI0EXP3RID_p\\SRU0\\/\x04_SB_PCI0USB0RID_p\\SRU1\\/\x04_SB_PCI0USB1RID_p\\SRU2\\/\x04_SB_PCI0USB2RID_p\\SRU3\\/\x04_SB_PCI0USB3RID_p\\SRU7\\/\x04_SB_PCI0USB7RID_p\\SRPB\\/\x04_SB_PCI0PCI1RID_p\\SRLP\\/\x04_SB_PCI0LPC_RID_p\\SRSA\\/\x04_SB_PCI0IDE0RID_p\\SRSA\\/\x04_SB_PCI0SATARID_p\\SRSM\\/\x04_SB_PCI0SMBURID_[\x82K\x11LNKA\x08_HID\x0cA\xd0\x0c\x0f\x08_UID +\x01\x14(_STA\x00\xa0\x1c\x92VPIR\\/\x04_SB_PCI0LPC_PIRA\xa4 +\t\xa1\x04\xa4 +\x0b\x08_PRS\x11\t +\x06#\xf8\x0e\x18y\x00\x14/_DIS\x00}\\/\x04_SB_PCI0LPC_PIRA +\x80\\/\x04_SB_PCI0LPC_PIRA\x08BUFA\x11\t +\x06#\x00\x00\x18y\x00\x8bBUFA +\x01IRA1\x14:_CRS\x00{\\/\x04_SB_PCI0LPC_PIRA +\x8f`\xa0\x0eVPIR`y +\x01`IRA1\xa1\x08p +\x00IRA1\xa4BUFA\x14F\x04_SRS\x01\x8bh +\x01IRA2\x82IRA2`{\\/\x04_SB_PCI0LPC_PIRA +pa}av`apa\\/\x04_SB_PCI0LPC_PIRA[\x82K\x11LNKB\x08_HID\x0cA\xd0\x0c\x0f\x08_UID +\x02\x14(_STA\x00\xa0\x1c\x92VPIR\\/\x04_SB_PCI0LPC_PIRB\xa4 +\t\xa1\x04\xa4 +\x0b\x08_PRS\x11\t +\x06#\xf8\x0e\x18y\x00\x14/_DIS\x00}\\/\x04_SB_PCI0LPC_PIRB +\x80\\/\x04_SB_PCI0LPC_PIRB\x08BUFB\x11\t +\x06#\x00\x00\x18y\x00\x8bBUFB +\x01IRB1\x14:_CRS\x00{\\/\x04_SB_PCI0LPC_PIRB +\x8f`\xa0\x0eVPIR`y +\x01`IRB1\xa1\x08p +\x00IRB1\xa4BUFB\x14F\x04_SRS\x01\x8bh +\x01IRB2\x82IRB2`{\\/\x04_SB_PCI0LPC_PIRB +pa}av`apa\\/\x04_SB_PCI0LPC_PIRB[\x82K\x11LNKC\x08_HID\x0cA\xd0\x0c\x0f\x08_UID +\x03\x14(_STA\x00\xa0\x1c\x92VPIR\\/\x04_SB_PCI0LPC_PIRC\xa4 +\t\xa1\x04\xa4 +\x0b\x08_PRS\x11\t +\x06#\xf8\x0e\x18y\x00\x14/_DIS\x00}\\/\x04_SB_PCI0LPC_PIRC +\x80\\/\x04_SB_PCI0LPC_PIRC\x08BUFC\x11\t +\x06#\x00\x00\x18y\x00\x8bBUFC +\x01IRC1\x14:_CRS\x00{\\/\x04_SB_PCI0LPC_PIRC +\x8f`\xa0\x0eVPIR`y +\x01`IRC1\xa1\x08p +\x00IRC1\xa4BUFC\x14F\x04_SRS\x01\x8bh +\x01IRC2\x82IRC2`{\\/\x04_SB_PCI0LPC_PIRC +pa}av`apa\\/\x04_SB_PCI0LPC_PIRC[\x82K\x11LNKD\x08_HID\x0cA\xd0\x0c\x0f\x08_UID +\x04\x14(_STA\x00\xa0\x1c\x92VPIR\\/\x04_SB_PCI0LPC_PIRD\xa4 +\t\xa1\x04\xa4 +\x0b\x08_PRS\x11\t +\x06#\xf8\x0e\x18y\x00\x14/_DIS\x00}\\/\x04_SB_PCI0LPC_PIRD +\x80\\/\x04_SB_PCI0LPC_PIRD\x08BUFD\x11\t +\x06#\x00\x00\x18y\x00\x8bBUFD +\x01IRD1\x14:_CRS\x00{\\/\x04_SB_PCI0LPC_PIRD +\x8f`\xa0\x0eVPIR`y +\x01`IRD1\xa1\x08p +\x00IRD1\xa4BUFD\x14F\x04_SRS\x01\x8bh +\x01IRD2\x82IRD2`{\\/\x04_SB_PCI0LPC_PIRD +pa}av`apa\\/\x04_SB_PCI0LPC_PIRD[\x82K\x11LNKE\x08_HID\x0cA\xd0\x0c\x0f\x08_UID +\x05\x14(_STA\x00\xa0\x1c\x92VPIR\\/\x04_SB_PCI0LPC_PIRE\xa4 +\t\xa1\x04\xa4 +\x0b\x08_PRS\x11\t +\x06#\xf8\x0e\x18y\x00\x14/_DIS\x00}\\/\x04_SB_PCI0LPC_PIRE +\x80\\/\x04_SB_PCI0LPC_PIRE\x08BUFE\x11\t +\x06#\x00\x00\x18y\x00\x8bBUFE +\x01IRE1\x14:_CRS\x00{\\/\x04_SB_PCI0LPC_PIRE +\x8f`\xa0\x0eVPIR`y +\x01`IRE1\xa1\x08p +\x00IRE1\xa4BUFE\x14F\x04_SRS\x01\x8bh +\x01IRE2\x82IRE2`{\\/\x04_SB_PCI0LPC_PIRE +pa}av`apa\\/\x04_SB_PCI0LPC_PIRE[\x82K\x11LNKF\x08_HID\x0cA\xd0\x0c\x0f\x08_UID +\x06\x14(_STA\x00\xa0\x1c\x92VPIR\\/\x04_SB_PCI0LPC_PIRF\xa4 +\t\xa1\x04\xa4 +\x0b\x08_PRS\x11\t +\x06#\xf8\x0e\x18y\x00\x14/_DIS\x00}\\/\x04_SB_PCI0LPC_PIRF +\x80\\/\x04_SB_PCI0LPC_PIRF\x08BUFF\x11\t +\x06#\x00\x00\x18y\x00\x8bBUFF +\x01IRF1\x14:_CRS\x00{\\/\x04_SB_PCI0LPC_PIRF +\x8f`\xa0\x0eVPIR`y +\x01`IRF1\xa1\x08p +\x00IRF1\xa4BUFF\x14F\x04_SRS\x01\x8bh +\x01IRF2\x82IRF2`{\\/\x04_SB_PCI0LPC_PIRF +pa}av`apa\\/\x04_SB_PCI0LPC_PIRF[\x82K\x11LNKG\x08_HID\x0cA\xd0\x0c\x0f\x08_UID +\x07\x14(_STA\x00\xa0\x1c\x92VPIR\\/\x04_SB_PCI0LPC_PIRG\xa4 +\t\xa1\x04\xa4 +\x0b\x08_PRS\x11\t +\x06#\xf8\x0e\x18y\x00\x14/_DIS\x00}\\/\x04_SB_PCI0LPC_PIRG +\x80\\/\x04_SB_PCI0LPC_PIRG\x08BUFG\x11\t +\x06#\x00\x00\x18y\x00\x8bBUFG +\x01IRG1\x14:_CRS\x00{\\/\x04_SB_PCI0LPC_PIRG +\x8f`\xa0\x0eVPIR`y +\x01`IRG1\xa1\x08p +\x00IRG1\xa4BUFG\x14F\x04_SRS\x01\x8bh +\x01IRG2\x82IRG2`{\\/\x04_SB_PCI0LPC_PIRG +pa}av`apa\\/\x04_SB_PCI0LPC_PIRG[\x82K\x11LNKH\x08_HID\x0cA\xd0\x0c\x0f\x08_UID +\x08\x14(_STA\x00\xa0\x1c\x92VPIR\\/\x04_SB_PCI0LPC_PIRH\xa4 +\t\xa1\x04\xa4 +\x0b\x08_PRS\x11\t +\x06#\xf8\x0e\x18y\x00\x14/_DIS\x00}\\/\x04_SB_PCI0LPC_PIRH +\x80\\/\x04_SB_PCI0LPC_PIRH\x08BUFH\x11\t +\x06#\x00\x00\x18y\x00\x8bBUFH +\x01IRH1\x14:_CRS\x00{\\/\x04_SB_PCI0LPC_PIRH +\x8f`\xa0\x0eVPIR`y +\x01`IRH1\xa1\x08p +\x00IRH1\xa4BUFH\x14F\x04_SRS\x01\x8bh +\x01IRH2\x82IRH2`{\\/\x04_SB_PCI0LPC_PIRH +pa}av`apa\\/\x04_SB_PCI0LPC_PIRH\x149VPIR\x01p +\x01`\xa0 +{h +\x80\x00p +\x00`\xa1!{h +\x0fa\xa0\t\x95a +\x03p +\x00`\xa1\x10\xa0\x0e\x91\x93a +\x08\x93a +\rp +\x00`\xa4`[\x82HhMEM_\x08_HID\x0cA\xd0\x0c\x01\x08ME98\x11B\x04 +>\x86\t\x00\x01\x00\x00\x00\x00\x00\x00 +\x00\x86\t\x00\x00\x00\x00\x0e\x00\x00\x00\x02\x00\x86\t\x00\x01\x00\x00\x10\x00\x00\x00\xee\x01\x86\t\x00\x00\x00\x00\xc0\xfe\x00\x00\x14\x00\x86\t\x00\x00\x00\x10\xd4\xfe\x00\xf0+\x01y\x00\x8aME98 +\x1cMEB0\x8aME98 + MEL0\x08MGAP\x11\x11 +\x0e\x86\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y\x00\x8aMGAP +\x04MGPB\x8aMGAP +\x08MGPL\x08MEMS\x11B\r +\xce\x86\t\x00\x01\x00\x00\x00\x00\x00\x00 +\x00\x86\t\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x86\t\x00\x00\x00@\x0c\x00\x00\x00\x00\x00\x86\t\x00\x00\x00\x80\x0c\x00\x00\x00\x00\x00\x86\t\x00\x00\x00\xc0\x0c\x00\x00\x00\x00\x00\x86\t\x00\x00\x00\x00\r\x00\x00\x00\x00\x00\x86\t\x00\x00\x00@\r\x00\x00\x00\x00\x00\x86\t\x00\x00\x00\x80\r\x00\x00\x00\x00\x00\x86\t\x00\x00\x00\xc0\r\x00\x00\x00\x00\x00\x86\t\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x86\t\x00\x00\x00@\x0e\x00\x00\x00\x00\x00\x86\t\x00\x00\x00\x80\x0e\x00\x00\x00\x00\x00\x86\t\x00\x00\x00\xc0\x0e\x00\x00\x00\x00\x00\x86\t\x00\x00\x00\x00\x0f\x00\x00\x00\x01\x00\x86\t\x00\x01\x00\x00\x10\x00\x00\x00\xee\x01\x86\t\x00\x00\x00\x00\xc0\xfe\x00\x00\x14\x00\x86\t\x00\x00\x00\x10\xd4\xfe\x00\xf0+\x01y\x00\x8aMEMS +\x14MC0L\x8aMEMS + MC4L\x8aMEMS +,MC8L\x8aMEMS +8MCCL\x8aMEMS +DMD0L\x8aMEMS +PMD4L\x8aMEMS +\\MD8L\x8aMEMS +hMDCL\x8aMEMS +tME0L\x8aMEMS +\x80ME4L\x8aMEMS +\x8cME8L\x8aMEMS +\x98MECL\x8dMEMS +xMC0W\x8dMEMS +\xd8MC4W\x8dMEMS\x0b8\x01MC8W\x8dMEMS\x0b\x98\x01MCCW\x8dMEMS\x0b\xf8\x01MD0W\x8dMEMS\x0bX\x02MD4W\x8dMEMS\x0b\xb8\x02MD8W\x8dMEMS\x0b\x18\x03MDCW\x8dMEMS\x0bx\x03ME0W\x8dMEMS\x0b\xd8\x03ME4W\x8dMEMS\x0b8\x04ME8W\x8dMEMS\x0b\x98\x04MECW\x8aMEMS +\xacMEB1\x8aMEMS +\xb0MEL1\x8aMEMS +\xbcMEL2\x8aMEMS +\xc8MEL3\x14F=_CRS\x00\xa0M\x17\\W98Ft\\MEMXMEB0MEL0p\\GAPAMGPBp\\GAPLMGPL\xa0I\x0c\x90MGPBMGPLt\x87ME98 +\x02`\x08MBF0\x11\x02`r`\x87MGAP`\x08MBF1\x11\x02`pME98MBF0sMBF0MGAPMBF1\xa0O\x07\x92\x93\\/\x05_SB_PCI0LPC_TPM__STA +\x0ft\x87MBF1 +\x02`\x08MBF2\x11\x02`r`\x87\\/\x05_SB_PCI0LPC_TPM__CRS`\x08MBF3\x11\x02`pMBF1MBF2sMBF2\\/\x05_SB_PCI0LPC_TPM__CRSMBF3\xa4MBF3\xa1\x06\xa4MBF1\xa1I\x08\xa0O\x07\x92\x93\\/\x05_SB_PCI0LPC_TPM__STA +\x0ft\x87ME98 +\x02`\x08MBF4\x11\x02`r`\x87\\/\x05_SB_PCI0LPC_TPM__CRS`\x08MBF5\x11\x02`pME98MBF4sMBF4\\/\x05_SB_PCI0LPC_TPM__CRSMBF5\xa4MBF5\xa1\x06\xa4ME98{\\/\x03_SB_PCI0PAM1 +\x03`\xa0\x18`p\x0b\x00@MC0L\xa0\r{` +\x02\x00p +\x01MC0W{\\/\x03_SB_PCI0PAM1 +0`\xa0\x18`p\x0b\x00@MC4L\xa0\r{` + \x00p +\x01MC4W{\\/\x03_SB_PCI0PAM2 +\x03`\xa0\x18`p\x0b\x00@MC8L\xa0\r{` +\x02\x00p +\x01MC8W{\\/\x03_SB_PCI0PAM2 +0`\xa0\x18`p\x0b\x00@MCCL\xa0\r{` + \x00p +\x01MCCW{\\/\x03_SB_PCI0PAM3 +\x03`\xa0\x18`p\x0b\x00@MD0L\xa0\r{` +\x02\x00p +\x01MD0W{\\/\x03_SB_PCI0PAM3 +0`\xa0\x18`p\x0b\x00@MD4L\xa0\r{` + \x00p +\x01MD4W{\\/\x03_SB_PCI0PAM4 +\x03`\xa0\x18`p\x0b\x00@MD8L\xa0\r{` +\x02\x00p +\x01MD8W{\\/\x03_SB_PCI0PAM4 +0`\xa0\x18`p\x0b\x00@MDCL\xa0\r{` + \x00p +\x01MDCW{\\/\x03_SB_PCI0PAM5 +\x03`\xa0\x18`p\x0b\x00@ME0L\xa0\r{` +\x02\x00p +\x01ME0W{\\/\x03_SB_PCI0PAM5 +0`\xa0\x18`p\x0b\x00@ME4L\xa0\r{` + \x00p +\x01ME4W{\\/\x03_SB_PCI0PAM6 +\x03`\xa0\x18`p\x0b\x00@ME8L\xa0\r{` +\x02\x00p +\x01ME8W{\\/\x03_SB_PCI0PAM6 +0`\xa0\x18`p\x0b\x00@MECL\xa0\r{` + \x00p +\x01MECWt\\MEMXMEB1MEL1\xa0-\x92\x93\\/\x05_SB_PCI0LPC_TPM__STA +\x0fp\x0c\x00\x00@\x01MEL2p +\x00MEL3\xa4MEMS[\x82I\rLID_\x08_HID\x0cA\xd0\x0c\r\x14<_LID\x00\xa0\x1e\\H8DR\xa4\\/\x05_SB_PCI0LPC_EC__HPLD\xa1\x16\xa0\x0f{\\RBEC +F +\x04\x00\xa4 +\x01\xa1\x04\xa4 +\x00\x14&_PRW\x00\xa0\x15\x90\\W98F\x92\\WMEF\xa4\x12\x06\x02 +\x18 +\x04\xa1\t\xa4\x12\x06\x02 +\x18 +\x03\x14D\x06_PSW\x01\xa0?\\H8DR\xa0\x1chp +\x01\\/\x05_SB_PCI0LPC_EC__HWLO\xa1\x1bp +\x00\\/\x05_SB_PCI0LPC_EC__HWLO\xa1\x1c\xa0\rh\\MBEC +2 +\xff +\x04\xa1\x0c\\MBEC +2 +\xfb +\x00[\x82L\tSLPB\x08_HID\x0cA\xd0\x0c\x0e\x14&_PRW\x00\xa0\x15\x90\\W98F\x92\\WMEF\xa4\x12\x06\x02 +\x18 +\x04\xa1\t\xa4\x12\x06\x02 +\x18 +\x03\x14D\x06_PSW\x01\xa0?\\H8DR\xa0\x1chp +\x01\\/\x05_SB_PCI0LPC_EC__HWFN\xa1\x1bp +\x00\\/\x05_SB_PCI0LPC_EC__HWFN\xa1\x1c\xa0\rh\\MBEC +2 +\xff +\x10\xa1\x0c\\MBEC +2 +\xef +\x00[\x82\x8fH\x07PCI0[\x82\x8a\x96\x04LPC_\x08_ADR\x0c\x00\x00\x1f\x00\x08_S3D +\x03\x08RID_ +\x00[\x82M\x1aSIO_\x08_HID\x0cA\xd0\x0c\x02\x08_UID +\x00\x08SCRS\x11B\x10 +\xfeG\x01\x10\x00\x10\x00\x01\x10G\x01\x90\x00\x90\x00\x01\x10G\x01$\x00$\x00\x01\x02G\x01(\x00(\x00\x01\x02G\x01,\x00,\x00\x01\x02G\x010\x000\x00\x01\x02G\x014\x004\x00\x01\x02G\x018\x008\x00\x01\x02G\x01<\x00<\x00\x01\x02G\x01\xa4\x00\xa4\x00\x01\x02G\x01\xa8\x00\xa8\x00\x01\x02G\x01\xac\x00\xac\x00\x01\x02G\x01\xb0\x00\xb0\x00\x01\x06G\x01\xb8\x00\xb8\x00\x01\x02G\x01\xbc\x00\xbc\x00\x01\x02G\x01P\x00P\x00\x01\x04G\x01r\x00r\x00\x01\x06G\x01N\x16N\x16\x01\x02G\x01.\x00.\x00\x01\x02G\x01\x00\x10\x00\x10\x01\x80G\x01\x80\x11\x80\x11\x01@G\x01\x00\x08\x00\x08\x01\x10G\x01\xe0\x15\xe0\x15\x01\x10G\x01\x00\x16\x00\x16\x01`\x86\t\x00\x01\x00\x00\x00\xf0\x00\x00\x00\x04\x86\t\x00\x01\x00\xc0\xd1\xfe\x00@\x00\x00\x86\t\x00\x01\x00@\xd1\xfe\x00@\x00\x00\x86\t\x00\x01\x00\x80\xd1\xfe\x00\x10\x00\x00\x86\t\x00\x01\x00\x90\xd1\xfe\x00\x10\x00\x00y\x00\x14M\x08_CRS\x00\xa0 \x93\\/\x05_SB_PCI0LPC_TPM__STA +\x0f\xa4SCRS\xa1D\x06t\x87SCRS +\x02`\x08BUF0\x11\x02`r`\x87\\/\x05_SB_PCI0LPC_TPM__CRS`\x08BUF1\x11\x02`pSCRSBUF0sBUF0\\/\x05_SB_PCI0LPC_TPM__CRSBUF1\xa4BUF1[\x80LPCS\x02 +\x00\x0b\x00\x01[\x81G +LPCS\x00\x00@0PIRA\x08PIRB\x08PIRC\x08PIRD\x08SERQ\x08\x00\x18PIRE\x08PIRF\x08PIRG\x08PIRH\x08\x00@ +XU1A\x03\x00\x01XU2A\x03\x00\x01XPA_\x02\x00\x02XFA_\x01\x00\x03XU1E\x01XU2E\x01XPE_\x01XFE_\x01\x00\x0cXG1E\x01\x00\x06XG1A\t\x00\x10XG2E\x01\x00\x03XG2A\x0c\x00@\x0b\x00\x02CLKR\x01GYEN\x01\x00\x03C4C3\x01\x00\x02EXPE\x01\x00\x05[\x80LPIO\x01\x0b\x80\x11 +@[\x81O +LPIO\x03GU00\x08GU01\x08GU02\x08GU03\x08GI00\x08GI01\x08GI02\x08GI03\x08\x00 GL00\x08GL01\x08GL02\x08GL03\x08\x00@\x04GB00\x08GB01\x08GB02\x08GB03\x08\x00@\x08GV00\x08GV01\x08GV02\x08GV03\x08GU04\x08GU05\x08GU06\x08GU07\x08GI04\x08GI05\x08GI06\x08GI07\x08GL04\x08GL05\x08GL06\x08GL07\x08[\x80PMIO\x01\x0b\x00\x10 +\x80[\x81\x10PMIO\x00\x00@!\x00\x01SWGE\x01[\x823PIC_\x08_HID\x0bA\xd0\x08_CRS\x11 +\x1dG\x01 \x00 \x00\x01\x02G\x01\xa0\x00\xa0\x00\x01\x02G\x01\xd0\x04\xd0\x04\x01\x02"\x04\x00y\x00[\x82%TIMR\x08_HID\x0cA\xd0\x01\x00\x08_CRS\x11\x10 +\rG\x01@\x00@\x00\x01\x04"\x01\x00y\x00[\x82B\x05HPET\x08_HID\x0cA\xd0\x01\x03\x14*_STA\x00\xa0\x08W98F\xa4 +\x00\xa1\x17\xa0\x10\x90\\WNTF\x92\\WXPF\xa4 +\x00\xa1\x04\xa4 +\x0f\xa4 +\x00\x08_CRS\x11\x11 +\x0e\x86\t\x00\x00\x00\x00\xd0\xfe\x00\x04\x00\x00y\x00[\x825DMAC\x08_HID\x0cA\xd0\x02\x00\x08_CRS\x11 +\x1dG\x01\x00\x00\x00\x00\x01\x10G\x01\x80\x00\x80\x00\x01\x10G\x01\xc0\x00\xc0\x00\x01 *\x10\x05y\x00[\x82"SPKR\x08_HID\x0cA\xd0\x08\x00\x08_CRS\x11\r + +G\x01a\x00a\x00\x01\x01y\x00[\x82%FPU_\x08_HID\x0cA\xd0\x0c\x04\x08_CRS\x11\x10 +\rG\x01\xf0\x00\xf0\x00\x01\x01"\x00 y\x00[\x82%RTC_\x08_HID\x0cA\xd0\x0b\x00\x08_CRS\x11\x10 +\rG\x01p\x00p\x00\x01\x02"\x00\x01y\x00[\x82-KBD_\x08_HID\x0cA\xd0\x03\x03\x08_CRS\x11\x18 +\x15G\x01`\x00`\x00\x01\x01G\x01d\x00d\x00\x01\x01"\x02\x00y\x00[\x82J\x05MOU_\x08_HID\x0c$M7\x80\x08_CID\x0cA\xd0\x0f\x13\x08_CRS\x11\x08 +\x05"\x00\x10y\x00\x141MHID\x00\xa0\x1e\\/\x04_SB_PCI0LPC_PADDp\x0c$M7\x80_HID\xa1\x0bp\x0c$M\x00W_HID[\x80IMGA\x01\x0b\xe0\x15 +\x10[\x81!IMGA\x01\x00\x08\x00\x08\x00\x08WAKR\x10\x008GAIX\x08\x00\x08GADT\x08\x00\x08[\x86I\x0bGAIXGADT\x01\x00H VAUX\x02\x00\x01WOLE\x01\x00\x04\x00@\x07\x00\x01CBPW\x01CBSL\x01VDPW\x01PDNE\x01BLPL\x01\x00\x01LEDS\x01TP4R\x01PADR\x01BPAD\x01\x00\x01\x00\x01PADD\x01\x00 +DLAN\x01\x00G\x06BUSC\x01BUSD\x01\x00\x01DSCI\x01\x00\x04EPWG\x01\x00\x02DSCS\x01\x00\x04CSON\x01URST\x01\x00N\x06GDR0\x01GDR1\x01GDR2\x01\x00\x05GDT0\x01GDT1\x01GDT2\x01\x00E(GAID\x08[\x80NCFG\x01 +. +\x02[\x81\x10NCFG\x01INDX\x08DATA\x08[\x86B +INDXDATA\x01\x008LDN_\x08\x00@\x0cSIOD\x08\x00\x08SCF2\x08\x00\x08SCF4\x08\x00\x02PPSE\x01\x00\x04PNF_\x01FDCD\x01PPD_\x01SP2D\x01SP1D\x01\x00\x01GPSR\x02\x00\x01SRID\x08\x00\x08SCF9\x08\x00\x08\x00(LDA_\x01\x00\x07\x00H\x17IOHI\x08IOLW\x08\x00@\x07IRQN\x04IRQW\x01\x00\x03IRQT\x01IRQL\x01\x00\x06\x00\x10DMA0\x03\x00\x05DMA1\x03\x00\x05[\x86#INDXDATA\x01\x00@xPTRS\x01PPMC\x01\x00\x02PERA\x01PMDS\x03[\x86#INDXDATA\x01\x00@xSTRS\x01SPMC\x01SBSY\x01\x00\x04SBSE\x01[\x86\x1cINDXDATA\x01\x00@xGPPS\x08GPPC\x08GPER\x08[\x80CFGS\x01\x0bN\x16 +\x02[\x81\x10CFGS\x01NDXS\x08ATAS\x08[\x86J +NDXSATAS\x01\x008LDNS\x08\x00@\x0c\x00\x08\x00\x08\x00\x08\x00\x08\x00\x08\x00\x02PSES\x01\x00\x04PNFS\x01DCDS\x01PPDS\x01SP2S\x01SP1S\x01\x00\x01PSRS\x02\x00\x01RIDS\x08\x00\x08CCSS\x02CCES\x01MCSS\x01MESS\x01\x00\x03\x00\x08\x00(LDAS\x01\x00\x07\x00H\x17OHIS\x08OLWS\x08\x00@\x07RQNS\x04RQWS\x01\x00\x03RQTS\x01RQLS\x01\x00\x06\x00\x10MA0S\x03\x00\x05MA1S\x03\x00\x05[\x86#NDXSATAS\x01\x00@xTRSS\x01PMCS\x01BSYS\x01\x00\x04SESS\x01[\x80NSDL\x01\x0bL\x16 +\x01[\x81\x0bNSDL\x01DLPC\x08[\x80NSIO\x01\x0b\x80\x16 +\x0c[\x81\'NSIO\x01DRST\x01DLPD\x01\x00\x06\x00\x04DKI0\x01\x00\x03\x008DKI1\x01DKI2\x01[\x80DSIO\x01\x0b \x16 +\x0c[\x81\x0fDSIO\x01\x00\x01DUSB\x01\x00\x06[\x82K\x18FDC_\x08_HID\x0cA\xd0\x07\x00\x14 _STA\x00\xa0\x14\\LFDC\xa0\x08XFE_\xa4 +\x0f\xa1\x04\xa4 +\r\xa1\x04\xa4 +\x00\x14)_DIS\x00p +\x00XFE_p +\x00LDN_p +\x00IRQNp +\x00LDA_p +\x01FDCD\x08_CRS\x11\x1b +\x18G\x01\xf0\x03\xf0\x03\x01\x06G\x01\xf7\x03\xf7\x03\x01\x01"@\x00*\x04\x00y\x00\x08_PRS\x11\x1b +\x18G\x01\xf0\x03\xf0\x03\x01\x06G\x01\xf7\x03\xf7\x03\x01\x01"@\x00*\x04\x00y\x00\x14M\x04_SRS\x01p +\x00LDN_p +\x00LDA_p +\x03IOHIp +\xf0IOLWp +\x06IRQNp +\x02DMA0p +\x00FDCDp +\x01LDA_p +\x00XFA_p +\x01XFE_\x14\x1b_PSC\x00p +\x00LDN_\xa0\x08LDA_\xa4 +\x00\xa1\x04\xa4 +\x03\x14\x14_PS0\x00p +\x00LDN_p +\x01LDA_\x14\x14_PS3\x00p +\x00LDN_p +\x00LDA_\x14#SLFD\x01\xa0\x0eh\\MISA\x0b\xf3\x03 +\xf3 +\x04\xa1\r\\MISA\x0b\xf3\x03 +\xf3 +\x00[\x824FDD0\x08_ADR +\x00\x08_FDI\x12"\x10 +\x00 +\x04 +O +\x12 +\x01 +\xdf +\x02 +% +\x02 +\x12 +\x1b +\xff +l +\xf6 +\x0f +\x05\x10\x86/\x01\\/\x03_SB_PCI0LPC_[\x82A-LURT\x08_UID +\x00\x14-_STA\x00\xa0\x16\x93\\/\x03_SB_LCIO_STA +\x00\xa4 +\x00\xa1\x0f\xa0\x08XU1E\xa4 +\x0f\xa1\x04\xa4 +\r\x08_HID\x0cA\xd0\x05\x01\x08_PRW\x12\x06\x02 +\x18 +\x03\x14D\x06_PSW\x01\xa0?\\H8DR\xa0\x1chp +\x01\\/\x05_SB_PCI0LPC_EC__HWRI\xa1\x1bp +\x00\\/\x05_SB_PCI0LPC_EC__HWRI\xa1\x1c\xa0\rh\\MBEC +2 +\xff +@\xa1\x0c\\MBEC +2 +\xbf +\x00\x14)_DIS\x00p +\x00XU1Ep +\x03LDN_p +\x00IRQNp +\x00LDA_p +\x01SP1D\x08U1BF\x11\x10 +\rG\x01\x00\x00\x00\x00\x01\x08"\x00\x00y\x00\x8bU1BF +\x02U1MN\x8bU1BF +\x04U1MX\x8bU1BF +\tU1IQ\x14J\x04_CRS\x00p +\x03LDN_}yIOHI +\x08\x00IOLW`p`U1MNp`U1MXpIRQN`\xa0\r`y +\x01IRQNU1IQ\xa1\x08p +\x00U1IQ\xa4U1BF\x08_PRS\x11O\x06 +k1\x00G\x01\xf8\x03\xf8\x03\x01\x08"\x10\x001\x01G\x01\xf8\x02\xf8\x02\x01\x08"\x08\x001\x01G\x01\xe8\x03\xe8\x03\x01\x08"\x10\x001\x01G\x01\xe8\x02\xe8\x02\x01\x08"\x08\x001\x02G\x01\xf8\x03\xf8\x03\x01\x08"\xa8\x001\x02G\x01\xf8\x02\xf8\x02\x01\x08"\xb0\x001\x02G\x01\xe8\x03\xe8\x03\x01\x08"\xa8\x001\x02G\x01\xe8\x02\xe8\x02\x01\x08"\xb0\x008y\x00\x14O\x0c_SRS\x01\x8ch +\x02RUIL\x8ch +\x03RUIH\x8bh +\x02RUIO\x8bh +\tRUIQp +\x03LDN_p +\x00LDA_pRUILIOLWpRUIHIOHI\xa0\x12RUIQ\x82RUIQ`pv`IRQN\xa1\x08p +\x00IRQNp +\x00SP1Dp +\x01LDA_\xa0\x10\x93RUIO\x0b\xf8\x03p +\x00XU1A\xa1E\x04\xa0\x10\x93RUIO\x0b\xf8\x02p +\x01XU1A\xa11\xa0\x10\x93RUIO\x0b\xe8\x03p +\x07XU1A\xa1\x1e\xa0\x10\x93RUIO\x0b\xe8\x02p +\x05XU1A\xa1\x0b[2\x02\x00\x00\x02\x90\x0b\xb5\x01p +\x01XU1E\x14\x1b_PSC\x00p +\x03LDN_\xa0\x08LDA_\xa4 +\x00\xa1\x04\xa4 +\x03\x14\x06_PS0\x00\x14\x06_PS3\x00[\x82G-DURT\x08_UID +\x01\x143_STA\x00\xa0\x1c\x92{ +\x08\\/\x04_SB_PCI0LPC_DLPC\x00\xa4 +\x00\xa1\x0f\xa0\x08XU1E\xa4 +\x0f\xa1\x04\xa4 +\r\x08_HID\x0cA\xd0\x05\x01\x08_PRW\x12\x06\x02 +\x18 +\x03\x14D\x06_PSW\x01\xa0?\\H8DR\xa0\x1chp +\x01\\/\x05_SB_PCI0LPC_EC__HWRI\xa1\x1bp +\x00\\/\x05_SB_PCI0LPC_EC__HWRI\xa1\x1c\xa0\rh\\MBEC +2 +\xff +@\xa1\x0c\\MBEC +2 +\xbf +\x00\x14)_DIS\x00p +\x00XU1Ep +\x03LDN_p +\x00IRQNp +\x00LDA_p +\x01SP1D\x08U1BF\x11\x10 +\rG\x01\x00\x00\x00\x00\x01\x08"\x00\x00y\x00\x8bU1BF +\x02U1MN\x8bU1BF +\x04U1MX\x8bU1BF +\tU1IQ\x14J\x04_CRS\x00p +\x03LDN_}yIOHI +\x08\x00IOLW`p`U1MNp`U1MXpIRQN`\xa0\r`y +\x01IRQNU1IQ\xa1\x08p +\x00U1IQ\xa4U1BF\x08_PRS\x11O\x06 +k1\x00G\x01\xf8\x03\xf8\x03\x01\x08"\x10\x001\x01G\x01\xf8\x02\xf8\x02\x01\x08"\x08\x001\x01G\x01\xe8\x03\xe8\x03\x01\x08"\x10\x001\x01G\x01\xe8\x02\xe8\x02\x01\x08"\x08\x001\x02G\x01\xf8\x03\xf8\x03\x01\x08"\xa8\x001\x02G\x01\xf8\x02\xf8\x02\x01\x08"\xb0\x001\x02G\x01\xe8\x03\xe8\x03\x01\x08"\xa8\x001\x02G\x01\xe8\x02\xe8\x02\x01\x08"\xb0\x008y\x00\x14O\x0c_SRS\x01\x8ch +\x02RUIL\x8ch +\x03RUIH\x8bh +\x02RUIO\x8bh +\tRUIQp +\x03LDN_p +\x00LDA_pRUILIOLWpRUIHIOHI\xa0\x12RUIQ\x82RUIQ`pv`IRQN\xa1\x08p +\x00IRQNp +\x00SP1Dp +\x01LDA_\xa0\x10\x93RUIO\x0b\xf8\x03p +\x00XU1A\xa1E\x04\xa0\x10\x93RUIO\x0b\xf8\x02p +\x01XU1A\xa11\xa0\x10\x93RUIO\x0b\xe8\x03p +\x07XU1A\xa1\x1e\xa0\x10\x93RUIO\x0b\xe8\x02p +\x05XU1A\xa1\x0b[2\x02\x00\x00\x02\x90\x0b\xb5\x01p +\x01XU1E\x14\x1b_PSC\x00p +\x03LDN_\xa0\x08LDA_\xa4 +\x00\xa1\x04\xa4 +\x03\x14\x06_PS0\x00\x14\x06_PS3\x00[\x82L1LLPT\x08_UID +\x00\x14=_STA\x00\xa0\x16\x93\\/\x03_SB_LCIO_STA +\x00\xa4 +\x00\xa1\x1f\xa0\x18\x92\x93\\PMOD +\x03\xa0\x08XPE_\xa4 +\x0f\xa1\x04\xa4 +\r\xa1\x04\xa4 +\x00\x08_HID\x0cA\xd0\x04\x00\x14)_DIS\x00p +\x00XPE_p +\x01LDN_p +\x00IRQNp +\x00LDA_p +\x01PPD_\x08PPBF\x11\x10 +\rG\x01\x00\x00\x00\x00\x01\x00"\x00\x00y\x00\x8bPPBF +\x02LPN0\x8bPPBF +\x04LPX0\x8cPPBF +\x07LPL0\x8bPPBF +\tLPIQ\x14@\x07_CRS\x00\xa0\x0e\x93\\PMOD +\x03\xa4PPBFp +\x01LDN_}yIOHI +\x08\x00IOLW`p`LPN0p`LPX0\xa0\r\x93`\x0b\xbc\x03p +\x03LPL0\xa1\x08p +\x08LPL0pIRQN`\xa0\r`y +\x01IRQNLPIQ\xa1\x08p +\x00LPIQ\xa4PPBF\x14\x19_PRS\x00\xa0\x0b\\PMOD\xa4PEPP\xa1\x06\xa4PLPT\x08PLPT\x11O\x04 +K0G\x01\xbc\x03\xbc\x03\x01\x03"\x80\x000G\x01x\x03x\x03\x01\x08"\x80\x000G\x01x\x02x\x02\x01\x08" \x000G\x01\xbc\x03\xbc\x03\x01\x03" \x000G\x01x\x03x\x03\x01\x08" \x000G\x01x\x02x\x02\x01\x08"\x80\x008y\x00\x08PEPP\x116 +30G\x01x\x03x\x03\x01\x08"\x80\x000G\x01x\x02x\x02\x01\x08" \x000G\x01x\x03x\x03\x01\x08" \x000G\x01x\x02x\x02\x01\x08"\x80\x008y\x00\x14H\x0f_SRS\x01\x8ch +\x02RLIL\x8ch +\x03RLIH\x8bh +\x02RLIO\x8bh +\tRLIQp +\x01LDN_p +\x00LDA_pRLILIOLWpRLIHIOHI\xa0\x12RLIQ\x82RLIQ`pv`IRQN\xa1\x08p +\x00IRQN\xa0 \x93\\PMOD +\x00\xa0\r\\PDIRp +\x01PMDS\xa1\x08p +\x00PMDS\xa1\x1b\xa0\x10\x93\\PMOD +\x01p +\x02PMDS\xa1\x08p +\x03PMDSp +\x00PPD_p +\x01LDA_\xa0\x10\x93RLIO\x0bx\x03p +\x00XPA_\xa11\xa0\x10\x93RLIO\x0bx\x02p +\x01XPA_\xa1\x1e\xa0\x10\x93RLIO\x0b\xbc\x03p +\x02XPA_\xa1\x0b[2\x02\x00\x00\x02\x90\x0b\xce\x01p +\x01XPE_\x14\x1b_PSC\x00p +\x01LDN_\xa0\x08LDA_\xa4 +\x00\xa1\x04\xa4 +\x03\x14\x14_PS0\x00p +\x01LDN_p +\x01LDA_\x14\x14_PS3\x00p +\x01LDN_p +\x00LDA_[\x82C2DLPT\x08_UID +\x01\x14D\x04_STA\x00\xa0\x1c\x92{ +\x08\\/\x04_SB_PCI0LPC_DLPC\x00\xa4 +\x00\xa1\x1f\xa0\x18\x92\x93\\PMOD +\x03\xa0\x08XPE_\xa4 +\x0f\xa1\x04\xa4 +\r\xa1\x04\xa4 +\x00\x08_HID\x0cA\xd0\x04\x00\x14)_DIS\x00p +\x00XPE_p +\x01LDN_p +\x00IRQNp +\x00LDA_p +\x01PPD_\x08PPBF\x11\x10 +\rG\x01\x00\x00\x00\x00\x01\x00"\x00\x00y\x00\x8bPPBF +\x02LPN0\x8bPPBF +\x04LPX0\x8cPPBF +\x07LPL0\x8bPPBF +\tLPIQ\x14@\x07_CRS\x00\xa0\x0e\x93\\PMOD +\x03\xa4PPBFp +\x01LDN_}yIOHI +\x08\x00IOLW`p`LPN0p`LPX0\xa0\r\x93`\x0b\xbc\x03p +\x03LPL0\xa1\x08p +\x08LPL0pIRQN`\xa0\r`y +\x01IRQNLPIQ\xa1\x08p +\x00LPIQ\xa4PPBF\x14\x19_PRS\x00\xa0\x0b\\PMOD\xa4PEPP\xa1\x06\xa4PLPT\x08PLPT\x11O\x04 +K0G\x01\xbc\x03\xbc\x03\x01\x03"\x80\x000G\x01x\x03x\x03\x01\x08"\x80\x000G\x01x\x02x\x02\x01\x08" \x000G\x01\xbc\x03\xbc\x03\x01\x03" \x000G\x01x\x03x\x03\x01\x08" \x000G\x01x\x02x\x02\x01\x08"\x80\x008y\x00\x08PEPP\x116 +30G\x01x\x03x\x03\x01\x08"\x80\x000G\x01x\x02x\x02\x01\x08" \x000G\x01x\x03x\x03\x01\x08" \x000G\x01x\x02x\x02\x01\x08"\x80\x008y\x00\x14H\x0f_SRS\x01\x8ch +\x02RLIL\x8ch +\x03RLIH\x8bh +\x02RLIO\x8bh +\tRLIQp +\x01LDN_p +\x00LDA_pRLILIOLWpRLIHIOHI\xa0\x12RLIQ\x82RLIQ`pv`IRQN\xa1\x08p +\x00IRQN\xa0 \x93\\PMOD +\x00\xa0\r\\PDIRp +\x01PMDS\xa1\x08p +\x00PMDS\xa1\x1b\xa0\x10\x93\\PMOD +\x01p +\x02PMDS\xa1\x08p +\x03PMDSp +\x00PPD_p +\x01LDA_\xa0\x10\x93RLIO\x0bx\x03p +\x00XPA_\xa11\xa0\x10\x93RLIO\x0bx\x02p +\x01XPA_\xa1\x1e\xa0\x10\x93RLIO\x0b\xbc\x03p +\x02XPA_\xa1\x0b[2\x02\x00\x00\x02\x90\x0b\xce\x01p +\x01XPE_\x14\x1b_PSC\x00p +\x01LDN_\xa0\x08LDA_\xa4 +\x00\xa1\x04\xa4 +\x03\x14\x14_PS0\x00p +\x01LDN_p +\x01LDA_\x14\x14_PS3\x00p +\x01LDN_p +\x00LDA_[\x82E7LECP\x08_UID +\x00\x14<_STA\x00\xa0\x16\x93\\/\x03_SB_LCIO_STA +\x00\xa4 +\x00\xa1\x1e\xa0\x17\x93\\PMOD +\x03\xa0\x08XPE_\xa4 +\x0f\xa1\x04\xa4 +\r\xa1\x04\xa4 +\x00\x08_HID\x0cA\xd0\x04\x01\x14)_DIS\x00p +\x00XPE_p +\x01LDN_p +\x00IRQNp +\x00LDA_p +\x01PPD_\x08EPBF\x11\x1b +\x18G\x01\x00\x00\x00\x00\x01\x00G\x01\x00\x00\x00\x00\x01\x00"\x00\x00*\x00\x00y\x00\x8bEPBF +\x02ECN0\x8bEPBF +\x04ECX0\x8cEPBF +\x07ECL0\x8bEPBF + +ECN1\x8bEPBF +\x0cECX1\x8cEPBF +\x0fECL1\x8bEPBF +\x11ECIQ\x8bEPBF +\x14ECDQ\x14N +_CRS\x00\xa0\x0f\x92\x93\\PMOD +\x03\xa4EPBFp +\x01LDN_}yIOHI +\x08\x00IOLW`p`ECN0p`ECX0r`\x0b\x00\x04ECN1r`\x0b\x00\x04ECX1\xa0\x14\x93`\x0b\xbc\x03p +\x03ECL0p +\x03ECL1\xa1\x0fp +\x08ECL0p +\x08ECL1pIRQN`\xa0\r`y +\x01IRQNECIQ\xa1\x08p +\x00ECIQpDMA0`\xa0\r\x95` +\x04y +\x01`ECDQ\xa1\x08p +\x00ECDQ\xa4EPBF\x08_PRS\x11A\t +\x8d0G\x01x\x03x\x03\x01\x08G\x01x\x07x\x07\x01\x08"\x80\x00*\x0b\x000G\x01x\x02x\x02\x01\x08G\x01x\x06x\x06\x01\x08" \x00*\x0b\x000G\x01\xbc\x03\xbc\x03\x01\x03G\x01\xbc\x07\xbc\x07\x01\x03"\x80\x00*\x0b\x000G\x01x\x03x\x03\x01\x08G\x01x\x07x\x07\x01\x08" \x00*\x0b\x000G\x01x\x02x\x02\x01\x08G\x01x\x06x\x06\x01\x08"\x80\x00*\x0b\x000G\x01\xbc\x03\xbc\x03\x01\x03G\x01\xbc\x07\xbc\x07\x01\x03" \x00*\x0b\x008y\x00\x14A\x0f_SRS\x01\x8ch +\x02RLIL\x8ch +\x03RLIH\x8bh +\x02RLIO\x8bh +\x11RLIQ\x8ch +\x14RLDQp +\x01LDN_p +\x00LDA_p +\x07PMDSp +\x01PERApRLILIOLWpRLIHIOHI\xa0\x12RLIQ\x82RLIQ`pv`IRQN\xa1\x08p +\x00IRQN\xa0\x16{RLDQ +\x0f\x00\x82RLDQ`pv`DMA0\xa1\x08p +\x04DMA0p +\x00PPD_p +\x01LDA_\xa0\x10\x93RLIO\x0bx\x03p +\x00XPA_\xa11\xa0\x10\x93RLIO\x0bx\x02p +\x01XPA_\xa1\x1e\xa0\x10\x93RLIO\x0b\xbc\x03p +\x02XPA_\xa1\x0b[2\x02\x00\x00\x02\x90\x0b\x9f\x01p +\x01XPE_\x14\x1b_PSC\x00p +\x01LDN_\xa0\x08LDA_\xa4 +\x00\xa1\x04\xa4 +\x03\x14\x14_PS0\x00p +\x01LDN_p +\x01LDA_\x14\x14_PS3\x00p +\x01LDN_p +\x00LDA_[\x82L7DECP\x08_UID +\x01\x14C\x04_STA\x00\xa0\x1c\x92{ +\x08\\/\x04_SB_PCI0LPC_DLPC\x00\xa4 +\x00\xa1\x1e\xa0\x17\x93\\PMOD +\x03\xa0\x08XPE_\xa4 +\x0f\xa1\x04\xa4 +\r\xa1\x04\xa4 +\x00\x08_HID\x0cA\xd0\x04\x01\x14)_DIS\x00p +\x00XPE_p +\x01LDN_p +\x00IRQNp +\x00LDA_p +\x01PPD_\x08EPBF\x11\x1b +\x18G\x01\x00\x00\x00\x00\x01\x00G\x01\x00\x00\x00\x00\x01\x00"\x00\x00*\x00\x00y\x00\x8bEPBF +\x02ECN0\x8bEPBF +\x04ECX0\x8cEPBF +\x07ECL0\x8bEPBF + +ECN1\x8bEPBF +\x0cECX1\x8cEPBF +\x0fECL1\x8bEPBF +\x11ECIQ\x8bEPBF +\x14ECDQ\x14N +_CRS\x00\xa0\x0f\x92\x93\\PMOD +\x03\xa4EPBFp +\x01LDN_}yIOHI +\x08\x00IOLW`p`ECN0p`ECX0r`\x0b\x00\x04ECN1r`\x0b\x00\x04ECX1\xa0\x14\x93`\x0b\xbc\x03p +\x03ECL0p +\x03ECL1\xa1\x0fp +\x08ECL0p +\x08ECL1pIRQN`\xa0\r`y +\x01IRQNECIQ\xa1\x08p +\x00ECIQpDMA0`\xa0\r\x95` +\x04y +\x01`ECDQ\xa1\x08p +\x00ECDQ\xa4EPBF\x08_PRS\x11A\t +\x8d0G\x01x\x03x\x03\x01\x08G\x01x\x07x\x07\x01\x08"\x80\x00*\x0b\x000G\x01x\x02x\x02\x01\x08G\x01x\x06x\x06\x01\x08" \x00*\x0b\x000G\x01\xbc\x03\xbc\x03\x01\x03G\x01\xbc\x07\xbc\x07\x01\x03"\x80\x00*\x0b\x000G\x01x\x03x\x03\x01\x08G\x01x\x07x\x07\x01\x08" \x00*\x0b\x000G\x01x\x02x\x02\x01\x08G\x01x\x06x\x06\x01\x08"\x80\x00*\x0b\x000G\x01\xbc\x03\xbc\x03\x01\x03G\x01\xbc\x07\xbc\x07\x01\x03" \x00*\x0b\x008y\x00\x14A\x0f_SRS\x01\x8ch +\x02RLIL\x8ch +\x03RLIH\x8bh +\x02RLIO\x8bh +\x11RLIQ\x8ch +\x14RLDQp +\x01LDN_p +\x00LDA_p +\x07PMDSp +\x01PERApRLILIOLWpRLIHIOHI\xa0\x12RLIQ\x82RLIQ`pv`IRQN\xa1\x08p +\x00IRQN\xa0\x16{RLDQ +\x0f\x00\x82RLDQ`pv`DMA0\xa1\x08p +\x04DMA0p +\x00PPD_p +\x01LDA_\xa0\x10\x93RLIO\x0bx\x03p +\x00XPA_\xa11\xa0\x10\x93RLIO\x0bx\x02p +\x01XPA_\xa1\x1e\xa0\x10\x93RLIO\x0b\xbc\x03p +\x02XPA_\xa1\x0b[2\x02\x00\x00\x02\x90\x0b\x9f\x01p +\x01XPE_\x14\x1b_PSC\x00p +\x01LDN_\xa0\x08LDA_\xa4 +\x00\xa1\x04\xa4 +\x03\x14\x14_PS0\x00p +\x01LDN_p +\x01LDA_\x14\x14_PS3\x00p +\x01LDN_p +\x00LDA_\x10#\\/\x04_SB_PCI0LPC_LURT\x08_EJD\r_SB.LCIO\x00\x10#\\/\x04_SB_PCI0LPC_DURT\x08_EJD\r_SB.GDCK\x00\x10#\\/\x04_SB_PCI0LPC_LLPT\x08_EJD\r_SB.LCIO\x00\x10#\\/\x04_SB_PCI0LPC_DLPT\x08_EJD\r_SB.GDCK\x00\x10#\\/\x04_SB_PCI0LPC_LECP\x08_EJD\r_SB.LCIO\x00\x10#\\/\x04_SB_PCI0LPC_DECP\x08_EJD\r_SB.GDCK\x00[\x82H.FIR_\x08_HID\x0c$M\x00q\x08_CID\x0cA\xd0\x05\x11\x14\x1d_STA\x00\xa0\x08HDIR\xa4 +\x00\xa0\x08XU2E\xa4 +\x0f\xa1\x04\xa4 +\r\x14)_DIS\x00p +\x00XU2Ep +\x02LDNSp +\x00RQNSp +\x00LDASp +\x01SP2S\x08U2BF\x11\x13 +\x10G\x01\x00\x00\x00\x00\x01\x08"\x00\x00*\x00\x00y\x00\x8bU2BF +\x02IRMN\x8bU2BF +\x04IRMX\x8bU2BF +\tIRIQ\x8cU2BF +\x0cIRDQ\x14G\x06_CRS\x00p +\x02LDNS}yOHIS +\x08\x00OLWS`p`IRMNp`IRMXpRQNS`\xa0\r`y +\x01RQNSIRIQ\xa1\x08p +\x00IRIQpMA0S`\xa0\r\x95` +\x04y +\x01`IRDQ\xa1\x08p +\x00IRDQ\xa4U2BF\x08_PRS\x11G\x08 +\x831\x00G\x01\xf8\x02\xf8\x02\x01\x08"\x08\x00*\x0b\x001\x01G\x01\xf8\x03\xf8\x03\x01\x08"\x10\x00*\x0b\x001\x01G\x01\xe8\x02\xe8\x02\x01\x08"\x08\x00*\x0b\x001\x01G\x01\xe8\x03\xe8\x03\x01\x08"\x10\x00*\x0b\x001\x02G\x01\xf8\x02\xf8\x02\x01\x08"\xb0\x00*\x0b\x001\x02G\x01\xf8\x03\xf8\x03\x01\x08"\xa8\x00*\x0b\x001\x02G\x01\xe8\x02\xe8\x02\x01\x08"\xb0\x00*\x0b\x001\x02G\x01\xe8\x03\xe8\x03\x01\x08"\xa8\x00*\x0b\x008y\x00\x14E\x10_SRS\x01\x8ch +\x02RIIL\x8ch +\x03RIIH\x8bh +\x02RIIO\x8bh +\tRIIQ\x8ch +\x0cRIDQp +\x02LDNSp +\x00LDASpRIILOLWSpRIIHOHIS\xa0\x12RIIQ\x82RIIQ`pv`RQNS\xa1\x08p +\x00RQNS\xa0\x16{RIDQ +\x0f\x00\x82RIDQ`pv`MA0S\xa1\x08p +\x04MA0Sp +\x04MA1Sp +\x01SESSp +\x00SP2Sp +\x01LDAS\xa0\x10\x93RIIO\x0b\xf8\x03p +\x00XU2A\xa1E\x04\xa0\x10\x93RIIO\x0b\xf8\x02p +\x01XU2A\xa11\xa0\x10\x93RIIO\x0b\xe8\x03p +\x07XU2A\xa1\x1e\xa0\x10\x93RIIO\x0b\xe8\x02p +\x05XU2A\xa1\x0b[2\x02\x00\x00\x02\x90\x0b\xa4\x01p +\x01XU2E\x14\x1b_PSC\x00p +\x02LDNS\xa0\x08LDAS\xa4 +\x00\xa1\x04\xa4 +\x03\x14\x14_PS0\x00p +\x02LDNSp +\x01LDAS\x14\x14_PS3\x00p +\x02LDNSp +\x00LDAS\x10C\x0e\\/\x03_SB_PCI0LPC_\x14A\rLCON\x01\xa0K +h\xa0G +EPWGp +\x01DLPDp +\x07DLPC\xa2\x0e\x92{ +\x08DLPC\x00[" +\x01p +\x01DRST\xa0L\x07\x92\x93SIOD +\xff}SCF9 +\xa0SCF9\xa2\x0e\x92{ +\x10SCF9\x00[" +\x01}SCF2 +\xebSCF2p +\x07LDN_{\x0b \x16 +\xff`p`IOLWz\x0b \x16 +\x08`{` +\xffIOHIp +\x01LDA_p +\x01GPPSp +\x03GPPCp +\x02GPPSp +\x03GPPCp +\x00DUSB\xa1\x1dp +\x01DUSBp +\x00DRSTp +\x00DLPDp +\x00DLPC[\x82GKTPM_\x08_HID\x0c\x06\x8d\x12\x00\x08_CID\x0cA\xd0\x0c1\x14\x1d_STA\x00\xa0\x0e{\\TPMP +\x01\x00p +\x0f`\xa1\x05p +\x00`\xa4`\x08_CRS\x11\x11 +\x0e\x86\t\x00\x01\x00\x00\xd4\xfe\x00\x10\x00\x00y\x00\x14GF_DSM\x0c\x08TMPB\x11\x05 +\x02\x00\x00\x8cTMPB +\x00LPCT\x8cTMPB +\x01SSUM\x08LRSP +\x00\x08PPRC +\x00\x08RQS1\x12\x06\x02 +\x0c +\r\x08PTOP\x12\x06\x02 +\x00 +\x00\x08RTOP\x12\x08\x03 +\x00 +\x00 +\x00\x8ah +\x00IID0\x8ah +\x04IID1\x8ah +\x08IID2\x8ah +\x0cIID3\x08UID0\x11\x13 +\x10\xa6\xfa\xdd=\x1b6\xb4N\xa4$\x8d\x10\x08\x9d\x16S\x8aUID0 +\x00EID0\x8aUID0 +\x04EID1\x8aUID0 +\x08EID2\x8aUID0 +\x0cEID3\xa0I,\x90\x90\x93IID0EID0\x93IID1EID1\x90\x93IID2EID2\x93IID3EID3\xa0\x0b\x93j +\x00\xa4\x11\x04 +\x01?\xa0\x0b\x93j +\x01\xa4\r1.0\x00\xa0L\x1c\x93j +\x02p +\x00PPRCTPHY +\x00p\\PH02LPCT\xa0@\x1aLPCTp +\x00SSUMrSSUM\\PH01SSUMrSSUM\\PH02SSUMrSSUM\\PH03SSUMrSSUM\\PH04SSUMrSSUM\\PH05SSUMrSSUM\\PH06SSUMrSSUM\\PH07SSUMrSSUM\\PH08SSUMrSSUM\\PH09SSUMrSSUM\\PH0ASSUMrSSUM\\PH0BSSUM\xa0\x0cSSUMp +\x02PPRC\xa1K\x0ep\x83\x88k +\x00\x00\\PH04p\x89RQS1\x01\\PH04\x00 +\x00 +\x00`\xa0\x0c\x92\x93`\xffp +\x01PPRC\xa1M\x0bp +\x00\\PH03p +\x00SSUMrSSUM\\PH01SSUMrSSUM\\PH02SSUMrSSUM\\PH03SSUMrSSUM\\PH04SSUMrSSUM\\PH05SSUMrSSUM\\PH06SSUMrSSUM\\PH07SSUMrSSUM\\PH08SSUMrSSUM\\PH09SSUMrSSUM\\PH0ASSUMrSSUM\\PH0BSSUMt +\x00SSUM\\PH03TPHY +\x01\xa1\x08p +\x02PPRC\xa4PPRC\xa0\x1e\x93j +\x03TPHY +\x00p\\PH04\x88PTOP +\x01\x00\xa4PTOP\xa0\x08\x93j +\x04\xa4 +\x01\xa0I\x08\x93j +\x05TPHY +\x00p\\PH07`p\\PH06LRSPp}y` +\x08`LRSP\x00LRSP\xa0\x1c\x90\x93\\PH06 +\xf0\x93\\PH07 +\xffp\x0c\xf0\xff\xff\xffLRSP\xa1\x1e\xa0\x1c\x90\x93\\PH06 +\xf1\x93\\PH07 +\xffp\x0c\xf1\xff\xff\xffLRSPpLRSP\x88RTOP +\x02\x00p\\PH05\x88RTOP +\x01\x00\xa4RTOP\xa0\x08\x93j +\x06\xa4 +\x02\x08UID1\x11\x13 +\x10\xedT`7\x13\xccuF\x90\x1cGV\xd7\xf2\xd4]\x8aUID1 +\x00EID4\x8aUID1 +\x04EID5\x8aUID1 +\x08EID6\x8aUID1 +\x0cEID7\xa0@\t\x90\x90\x93IID0EID4\x93IID1EID5\x90\x93IID2EID6\x93IID3EID7pj[1pk[1\xa0\x0b\x93j +\x00\xa4\x11\x04 +\x01\x01\xa0O\x04\x93j +\x01\xa0\x12\x93\x83\x88k +\x00\x00 +\x00p +\x00\\TCG0\xa0\x12\x93\x83\x88k +\x00\x00 +\x01p +\x01\\TCG0\xa0\x0f\x93\\TCG0 +\x00TMOR +\x00\xa0\x0f\x93\\TCG0 +\x01TMOR +\x01\xa4 +\x00\xa4 +\x01\xa4\x11\x04 +\x01\x00[\x80TSES\x00\x0c\x00\x00\xe8\xff\x0b\x00\x02[\x81F\x08TSES\x01\x00@\x06TSCM\x08\x00@(TCT0\x08TCT1\x08TCT2\x08\x00@\x05TMT0\x08\x00H\x04TMT1\x08\x00H\x04TMT2\x08\x00HzTLD0\x08TLD1\x08TLD2\x08TLDL\x18TLDB\x18TLDS\x10TSB0\x08TSB1\x08TSB2\x08TSBL\x08TSBBH\x04TSBF\x10TSBC\x10\x00@\x1aTSIM\x08[\x81\x0fTSES\x01\x00H.TCTAH\x11[\x81\x0fTSES\x01\x00@\xbaTCTLH\x05[\x81\x0fTSES\x01\x00H\xbfTCTBH\x08\x148TCSZ\x02\xa01\x92\x93TSCM +\x12\xa0\x0b\x93 +\x01hpiTCZ1\xa1\x1b\xa0\x0b\x93 +\x02hpiTCZ2\xa1\r\xa0\x0b\x93 +\x03hpiTCZ3\x14I\x0cTCST\x02\xa0A\x0c\x92\x93TSCM +\x12p +\x00`\xa0\x1e\x93 +\x01h\xa0\x18\x94iTMT0p +\x04TSIMpiTMT0p +\x01`\xa1B\x04\xa0\x1e\x93 +\x02h\xa0\x18\x94iTMT1p +\x04TSIMpiTMT1p +\x01`\xa1 \xa0\x1e\x93 +\x03h\xa0\x18\x94iTMT2p +\x04TSIMpiTMT2p +\x01`\xa0@\x05`p +\x00TCT2\x08TCTC\x11\x03 +#pTCTATCTCp +"cp +\x00a\xa2\x12cp\x83\x88TCTCc\x00brabavcp\x80a\x00bub{b +\xffapaTCT2p +\xfeTSIM\x14I\x08TCBS\x04\xa0A\x08\x92\x93TSCM +\x12\xa0F\x07\x93{h +\x07\x00 +\x00p +\x12TSIMphTSBLpiTSBBpjTSBFpkTSBCp +\x00TSB2\x08TCTD\x11\x03 +#pTCTBTCTDp +\x10`p +\x00a\xa2\x12`p\x83\x88TCTD`\x00brabav`p\x80a\x00bub{b +\xffapaTSB2p +\xfeTSIM\x14@\x07TSCL\x02\xa0H\x06\x92\x93TSCM +\x12p +\x15TSIMrTLDSiTLDSp +\x00TLD2\x08TLDD\x11\x03 +\x0bpTCTLTLDDp + +`p +\x00a\xa2\x12`p\x83\x88TLDD`\x00brabav`p\x80a\x00bub{b +\xffapaTLD2p +\xfeTSIM[\x82\x8e\x00\x02EC__\x08_HID\x0cA\xd0\x0c\t\x08_UID +\x00\x08_GPE +\x1c\x14\x13_REG\x02\xa0\x0c\x93h +\x03pi\\H8DR[\x80ECOR\x03 +\x00\x0b\x00\x01[\x81J+ECOR\x01HDBM\x01\x00\x01\x00\x01HFNE\x01\x00\x01\x00\x01HLDM\x01\x00\x01\x00\x01BTCM\x01\x00\x01\x00\x01\x00\x01HBPR\x01BTPC\x01\x00\x01HDUE\x01\x00\x07\x00\x01HETE\x01\x00\x0eHSPA\x01\x00\x07HSUN\x08HSRP\x08\x00 HLCL\x08\x00\x08HFNS\x02\x00\x06\x00\x04HAAA\x03\x00\x01HAM0\x08HAM1\x08HAM2\x08HAM3\x08HAM4\x08HAM5\x08HAM6\x08HAM7\x08HAM8\x08HAM9\x08HAMA\x08HAMB\x08HAMC\x08HAMD\x08HAME\x08HAMF\x08HT00\x01HT01\x01HT02\x01HT03\x01HT10\x01HT11\x01HT12\x01HT13\x01\x00\x10HANT\x08\x00\x10\x00\x01\x00\x01HANA\x02\x00\x01\x00\x01\x00\x1aHATR\x08HT0H\x08HT0L\x08HT1H\x08HT1L\x08HFSP\x08\x00\x06HMUT\x01\x00\x01HBRV\x08HWPM\x01HWLB\x01HWLO\x01HWDK\x01HWFN\x01HWBT\x01HWRI\x01HWBU\x01HWLU\x01\x00\x07\x00\x07HPLO\x01\x00\x08\x00\x10HB0S\x07HB0A\x01HB1S\x07HB1A\x01HCMU\x01\x00\x02OVRQ\x01DCBD\x01DCWL\x01DCWW\x01HB1I\x01\x00\x01KBLT\x01BTPW\x01BTDT\x01HUBS\x01BDPW\x01BDDT\x01HUBB\x01\x00@\x05\x00\x01BTWK\x01HPLD\x01\x00\x01HPAC\x01BTST\x01\x00\x02HPBU\x01\x00\x01HBID\x04HBCS\x01HPNF\x01\x00\x01GSTS\x01\x00\x02HLBU\x01BDST\x01HCBL\x01\x00)HWAK\x10HMPR\x08HMST\x05\x00\x02HMDN\x01HMAD\x08HMCM\x08\x00@\x10HMBC\x08\x00\x18TMP0\x08TMP1\x08TMP2\x08TMP3\x08TMP4\x08TMP5\x08TMP6\x08TMP7\x08\x00\x08HIID\x08\x00\x08HFNI\x08\x00 HDEC\x08HDEO\x08\x00\x18HDAA\x03HDAB\x03HDAC\x02\x00@\x11HDEN HDEP HDEM\x08HDES\x08\x00@\x07ATMX\x08HWAT\x08\x00H\x11\x00\x04HDDD\x01\x14A\x04_INI\x00\xa0\r\\H8DRp +\x00HSPA\xa1\x0c\\MBEC +\x05 +\xfe +\x00BINI\\/\x06_SB_PCI0LPC_EC__HKEYWGIN\x08_CRS\x11\x15 +\x12G\x01b\x00b\x00\x01\x01G\x01f\x00f\x00\x01\x01y\x00\x14!LED_\x02}hi`\xa0\x0c\\H8DRp`HLCL\xa1\t\\WBEC +\x0c`\x08BAON +\x00\x08WBON +\x00\x14N\x18BEEP\x01\xa0\x0c\x93h +\x05p +\x00WBONpWBONb\xa0O\x04BAON\xa0$\x93h +\x00p +\x00BAON\xa0\rWBONp +\x03`p +\x08a\xa1\tp +\x00`p +\x00a\xa1#p +\xff`p +\xffa\xa0\x0c\x93h +\x11p +\x00WBON\xa0\x0c\x93h +\x10p +\x01WBON\xa1G\x04ph`p +\xffa\xa0\x13\x93h +\x0fph`p +\x08ap +\x01BAON\xa0\x14\x93h +\x11p +\x00`p +\x00ap +\x00WBON\xa0\x14\x93h +\x10p +\x03`p +\x08ap +\x01WBON\xa02\x93h +\x03p +\x00WBON\xa0%bp +\x07`\xa0\x1e\x91\x93\\SPS_ +\x03\x93\\SPS_ +\x04p +\x00bp +\xff`p +\xffa\xa0\x14\x93h +\x07\xa0\x0ebp +\x00bp +\xff`p +\xffa\xa0C\x04\x90\\H8DR\x92\\W98F\xa0\x1a\x90b\x92WBONp +\x00HSRPp +\x00HSUN[" +d\xa0\x0c\x92\x93a +\xffpaHSRP\xa0\x0c\x92\x93` +\xffp`HSUN\xa1>\xa0\x1e\x90b\x92WBON\\WBEC +\x07 +\x00\\WBEC +\x06 +\x00[" +d\xa0\x0e\x92\x93a +\xff\\WBEC +\x07a\xa0\x0e\x92\x93` +\xff\\WBEC +\x06`\xa0\x05\x93h +\x03\xa0 +\x93h +\x07["\x0b\xf4\x01\x14C\tEVNT\x01\xa07\\H8DR\xa0\x18h}HAM7 +\x01HAM7}HAM5 +\x04HAM5\xa1\x17{HAM7 +\xfeHAM7{HAM5 +\xfbHAM5\xa1C\x05\xa0(h\\MBEC +\x17 +\xff +\x01\\MBEC +\x15 +\xff +\x04\xa0\x0f\\W98F\\WBEC +\x18 +\xff\xa1\'\\MBEC +\x17 +\xfe +\x00\\MBEC +\x15 +\xfb +\x00\xa0\x0f\\W98F\\WBEC +\x18 +\x00\x14K\x07PNST\x01\xa0=\x90hBSTA +\x02\xa0\x1b\x90\\H8DR\x92\\W98Fp +\x01HBPRp +\x01HUBB\xa1\x17\\MBEC +\x01 +\xff + \\MBEC +; +\xff +\x80\xa15\xa0\x1b\x90\\H8DR\x92\\W98Fp +\x00HBPRp +\x00HUBB\xa1\x17\\MBEC +\x01 +\xdf +\x00\\MBEC +; +\x7f +\x00[\x84I\x07PUBS\x03\x00\x00\x14+_STA\x00\xa0\x0c\\H8DRpHUBS`\xa1\x0c{\\RBEC +; +\x10`\xa0\x05`\xa4 +\x01\xa1\x04\xa4 +\x00\x14!_ON_\x00\xa0\r\\H8DRp +\x01HUBS\xa1\x0c\\MBEC +; +\xff +\x10\x14!_OFF\x00\xa0\r\\H8DRp +\x00HUBS\xa1\x0c\\MBEC +; +\xef +\x00\x14E\x0fLPMD\x00p +\x00`p +\x00ap +\x00b\xa0B\x06\\H8DR\xa0J\x05HPLO\xa0J\x04HPAC\xa0C\x04\x95HWAT +Z\xa0\x16\x91\x92HB0A\x95{HB0S +\x0f\x00 +\x03p +\x01a\xa0\x16\x91\x92HB1A\x95{HB1S +\x0f\x00 +\x03p +\x01b\xa0\x0b\x90abp\\LPST`\xa1\x08p\\LPST`\xa1L\x07\xa0I\x07{\\RBEC +4 +\x80\x00\xa0B\x06{\\RBEC +F +\x10\x00\xa0D\x05\x95\\RBEC +\xc9 +Zp\\RBEC +8c\xa0\x14\x91\x92{c +\x80\x00\x95{c +\x0f\x00 +\x03p +\x01ap\\RBEC +9c\xa0\x14\x91\x92{c +\x80\x00\x95{c +\x0f\x00 +\x03p +\x01b\xa0\x0b\x90abp\\LPST`\xa1\x08p\\LPST`\xa4`[\x01MCPU\x07\x14D\x04_Q10\x00\xa0<\\/\x06_SB_PCI0LPC_EC__HKEYMHKK +\x01\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x01\x10\x14G\x04_Q11\x00\xa0<\\/\x06_SB_PCI0LPC_EC__HKEYMHKK +\x02\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x02\x10\xa1\x02\xa3\x14$_Q12\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x03\x10\x14A\x05_Q13\x00\xa0:\\/\x06_SB_PCI0LPC_EC__HKEYDHKC\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x04\x10\xa1\x0e\x86\\._SB_SLPB +\x80\x14M\x10_Q64\x00\xa0<\\/\x06_SB_PCI0LPC_EC__HKEYMHKK +\x10\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x05\x10\xa1H\x0c\xa0>\x92{\\/\x06_SB_PCI0LPC_EC__HKEYWGFL + \x00\\/\x06_SB_PCI0LPC_EC__HKEYBPWC +\x01\xa1F\x08\\/\x06_SB_PCI0LPC_EC__HKEYBPWC +\x00\xa0F\x06\x92\\WVIS\xa0>\x92{\\/\x06_SB_PCI0LPC_EC__HKEYWGFL +\x02\x00\\/\x06_SB_PCI0LPC_EC__HKEYWPWC +\x01\xa1\x1e\\/\x06_SB_PCI0LPC_EC__HKEYWPWC +\x00\x14D\x04_Q65\x00\xa0<\\/\x06_SB_PCI0LPC_EC__HKEYMHKK + \\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x06\x10\x14C +_Q16\x00\xa0\'\\VPDFp +\x00\\VPDF\xa0\x18VIGD\\/\x04_SB_PCI0VID_VSPD\xa1C\x07\xa0<\\/\x06_SB_PCI0LPC_EC__HKEYMHKK +@\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x07\x10\xa13\xa0\x18VIGD\\/\x04_SB_PCI0VID_VSWT\xa1\x18\\/\x05_SB_PCI0AGP_VID_VSWT\x14B\x05_Q17\x00\xa0<\\/\x06_SB_PCI0LPC_EC__HKEYMHKK +\x80\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x08\x10\xa1\r\xa0\x0b\x92\\WNTFVEXP\x14F\x04_Q18\x00\xa0=\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0b\x00\x01\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\t\x10\xa3\x14E\x04_Q66\x00\xa0=\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0b\x00\x02\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b +\x10\x14E\x04_Q1A\x00\xa0=\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0b\x00\x04\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x0b\x10\x14$_Q1B\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x0c\x10\x14E\x04_Q62\x00\xa0=\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0b\x00\x10\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\r\x10\x14E\x04_Q60\x00\xa0=\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0b\x00 \\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x0e\x10\x14E\x04_Q61\x00\xa0=\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0b\x00@\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x0f\x10\x14N\x04_Q1F\x00\xa0?\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0c\x00\x00\x02\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x12\x10\\UCMS +\x0e\x14G\x04_Q67\x00\xa0?\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0c\x00\x00\x04\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x13\x10\x14O\x0e_Q26\x00\\UCMS +\x12DSPD +\x00["\x0b\xf4\x01\x86AC__ +\x80\x86\\._TZ_THM0 +\x80\x86\\._TZ_THM1 +\x80\xa0\x0e\\WXPF[#MCPU\xff\xff\xa07\\SPEN\xa0\'\\OSPX\x86\\._PR_CPU0 +\x80\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x80\xa1\x08\\STEP +\x00\xa0 +\\WXPF[" +d\xa0\'\\OSC4\x86\\._PR_CPU0 +\x81\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x81\xa0\x0c\\WXPF[\'MCPU\xa0#\x90\x92\\WXPF\\WNTFp +\x00\\/\x04_SB_PCI0LPC_C4C3ATMCDSPD +\x01\x14K\x12_Q27\x00\\UCMS +\x12["\x0b\xf4\x01\x86AC__ +\x80\x86\\._TZ_THM0 +\x80\x86\\._TZ_THM1 +\x80\xa0\x0e\\WXPF[#MCPU\xff\xff\xa07\\SPEN\xa0\'\\OSPX\x86\\._PR_CPU0 +\x80\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x80\xa1\x08\\STEP +\x01\xa0 +\\WXPF[" +d\xa0\'\\OSC4\x86\\._PR_CPU0 +\x81\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x81\xa0\x0c\\WXPF[\'MCPU\xa01\x90\\CWAC\x92\\CWAS\xa0#\x90\x92\\WXPF\\WNTFp +\x01\\/\x04_SB_PCI0LPC_C4C3ATMC\xa09\x91\x93\\/\x03_SB_GDCKGDID\x0c$M\x00L\x93\\/\x03_SB_GDCKGDID\x0c$M\x00D\x86\\._SB_GDCK +\x01\x14H\x06_Q2A\x00\xa0\x1aVIGD\\/\x04_SB_PCI0VID_VLOC +\x01\xa1\x1a\\/\x05_SB_PCI0AGP_VID_VLOC +\x01\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x02P\x86\\._SB_LID_ +\x80\x148_Q2B\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x01P\\UCMS +\r\x86\\._SB_LID_ +\x80\x14\x06_Q3D\x00\x14>_Q48\x00\xa07\\SPEN\xa0\'\\OSPX\x86\\._PR_CPU0 +\x80\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x80\xa1\x08\\STEP +\x04\x14>_Q49\x00\xa07\\SPEN\xa0\'\\OSPX\x86\\._PR_CPU0 +\x80\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x80\xa1\x08\\STEP +\x05\x14\x10_Q7F\x00[2\x01\x00\x00\x01\x80\x0b+\x03\x14$_Q4E\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x11`\x14$_Q4F\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x12`\x14\x1d_Q75\x00\\/\x05_SB_PCI0LPC_EC__TATR\x14$_Q46\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x12`\x14 _Q22\x00\xa0\x0cHB0A\x86BAT0 +\x80\xa0\x0cHB1A\x86BAT1 +\x80\x14\r_Q4A\x00\x86BAT0 +\x81\x14\r_Q4B\x00\x86BAT0 +\x80\x14 +_Q4C\x00_Q38\x14%_Q4D\x00\xa0\x1e{^.BAT1B1ST^.BAT1XB1S\x00\x86BAT1 +\x80\x14\r_Q24\x00\x86BAT0 +\x80\x14%_Q25\x00\xa0\x1e{^.BAT1B1ST^.BAT1XB1S\x00\x86BAT1 +\x80[\x811ECOR\x01\x00@PSBRC\x10SBFC\x10SBAE\x10SBRS\x10SBAC\x10SBVO\x10SBAF\x10SBBS\x10[\x81\x1aECOR\x01\x00@P\x00\x0fSBCM\x01SBMD\x10SBCC\x10[\x81\'ECOR\x01\x00@PSBDC\x10SBDV\x10SBOM\x10SBSI\x10SBDT\x10SBSN\x10[\x81\x0eECOR\x01\x00@PSBCH [\x81\x0fECOR\x01\x00@PSBMN@\x08[\x81\x0fECOR\x01\x00@PSBDN@\x08[\x01BATM\x07\x14C\x16GBIF\x03[#BATM\xff\xff\xa0C\x12j}h +\x01HIIDpSBCMg\x7fg +\x01\x88i +\x00\x00phHIID\xa0 +gwSBFC + +a\xa1\x07pSBFCapa\x88i +\x02\x00}h +\x02HIID\xa0 +gwSBDC + +`\xa1\x07pSBDC`p`\x88i +\x01\x00xa +\x14b\x88i +\x05\x00\xa0 +gp +\xc8\x88i +\x06\x00\xa1!\xa0\x15SBDVx\x0c@\r\x03\x00SBDVb\x88i +\x06\x00\xa1\tp +\x00\x88i +\x06\x00pSBDV\x88i +\x04\x00pSBSN`\x08SERN\x11\t +\x06 \x00p +\x04b\xa2\x15`x` + +a`ra +0\x88SERNb\x00vbpSERN\x88i + +\x00}h +\x06HIIDpSBDN\x88i +\t\x00}h +\x04HIID\x08BTYP\x11\x08 +\x05\x00\x00\x00\x00\x00pSBCHBTYPpBTYP\x88i +\x0b\x00}h +\x05HIIDpSBMN\x88i +\x0c\x00\xa1\'p\x0c\xff\xff\xff\xff\x88i +\x01\x00p +\x00\x88i +\x05\x00p +\x00\x88i +\x06\x00p\x0c\xff\xff\xff\xff\x88i +\x02\x00[\'BATM\xa4i\x14J\rGBST\x04[#BATM\xff\xff\xa0 +{i + \x00p +\x02`\xa1\x12\xa0 +{i +@\x00p +\x01`\xa1\x05p +\x00`\xa0\x06{i +\x0f\x00\xa1\x06}` +\x04`\xa0\x19\x93{i +\x0f\x00 +\x0fp +\x04`p +\x00ap +\x00bp +\x00c\xa1@\x06phHIIDpSBVOc\xa0 +jwSBRC + +b\xa1\x07pSBRCbpSBACa\xa0\x1c\x92\x95a\x0b\x00\x80\xa0\x0e{` +\x01\x00t\x0c\x00\x00\x01\x00aa\xa1\x05p +\x00a\xa1\r\xa0\x0b\x92{` +\x02\x00p +\x00a\xa0\rjwcaaxa\x0b\xe8\x03gap`\x88k +\x00\x00pa\x88k +\x01\x00pb\x88k +\x02\x00pc\x88k +\x03\x00[\'BATM\xa4k[\x82G\x15BAT0\x08_HID\x0cA\xd0\x0c +\x08_UID +\x00\x08_PCL\x12\x07\x01\\_SB_\x08B0ST +\x00\x08BT0I\x12#\r +\x00\x0c\xff\xff\xff\xff\x0c\xff\xff\xff\xff +\x01\x0b0* +\x00 +\x00 +\x01 +\x01\r\x00\r\x00\r\x00\r\x00\x08BT0P\x12\x02\x04\x14D\x04_STA\x00\xa0\x0f\\H8DRpHB0AB0ST\xa1\x1e\xa0\x13{\\RBEC +8 +\x80\x00p +\x01B0ST\xa1\x08p +\x00B0ST\xa0\x08B0ST\xa4 +\x1f\xa1\x04\xa4 +\x0f\x14G\x04_BIF\x00p +\x00gp + +f\xa2+\x90\x92gf\xa0\x1fHB0A\xa0\x13\x93{HB0S +\x0f\x00 +\x0f["\x0b\xe8\x03vf\xa1\x05p +\x01g\xa1\x05p +\x00f\xa4GBIF +\x00BT0Ig\x14#_BST\x00\x7f\x83\x88BT0I +\x00\x00 +\x01`\xa4GBST +\x00HB0S`BT0P\x14I\x04_BTP\x01{HAM4 +\xefHAM4\xa06hpha\xa0\x11\x92\x83\x88BT0I +\x00\x00xa + +`a{a +\xffHT0L{za +\x08\x00 +\xffHT0H}HAM4 +\x10HAM4[\x82A\x18BAT1\x08_HID\x0cA\xd0\x0c +\x08_UID +\x01\x08_PCL\x12\x07\x01\\_SB_\x08B1ST +\x00\x08XB1S +\x01\x08BT1I\x12#\r +\x00\x0c\xff\xff\xff\xff\x0c\xff\xff\xff\xff +\x01\x0b0* +\x00 +\x00 +\x01 +\x01\r\x00\r\x00\r\x00\r\x00\x08BT1P\x12\x02\x04\x14G\x06_STA\x00\xa0\x0f\\H8DRpHB1AB1ST\xa1\x1e\xa0\x13{\\RBEC +9 +\x80\x00p +\x01B1ST\xa1\x08p +\x00B1ST\xa0\x1fB1ST\xa0\x08XB1S\xa4 +\x1f\xa1\x10\xa0\t\\WNTF\xa4 +\x00\xa1\x04\xa4 +\x1f\xa1\x10\xa0\t\\WNTF\xa4 +\x00\xa1\x04\xa4 +\x0f\x14G\x04_BIF\x00p +\x00gp + +f\xa2+\x90\x92gf\xa0\x1fHB1A\xa0\x13\x93{HB1S +\x0f\x00 +\x0f["\x0b\xe8\x03vf\xa1\x05p +\x01g\xa1\x05p +\x00f\xa4GBIF +\x10BT1Ig\x14#_BST\x00\x7f\x83\x88BT1I +\x00\x00 +\x01`\xa4GBST +\x10HB1S`BT1P\x14I\x04_BTP\x01{HAM4 +\xdfHAM4\xa06hpha\xa0\x11\x92\x83\x88BT1I +\x00\x00xa + +`a{a +\xffHT1L{za +\x08\x00 +\xffHT1H}HAM4 + HAM4[\x82>AC__\x08_HID\rACPI0003\x00\x08_UID +\x00\x08_PCL\x12\x07\x01\\_SB_\x14\x0b_PSR\x00\xa4HPAC\x14\t_STA\x00\xa4 +\x0f[\x82IQHKEY\x08_HID\x0c$M\x00h\x14\t_STA\x00\xa4 +\x0f\x14 +MHKV\x00\xa4\x0b\x00\x01\x08DHKC +\x00\x08DHKB +\x01[\x01XDHK\x07\x08DHKH +\x00\x08DHKW +\x00\x08DHKS +\x00\x08DHKD +\x00\x08DHKN\x0b\x0c\x08\x08DHKT +\x00\x08DHWW +\x00\x14\x0cMHKA\x00\xa4\x0c\xff\xff\xff\x00\x14\x0bMHKN\x00\xa4DHKN\x14\x18MHKK\x01\xa0\rDHKC\xa4{DHKNh\x00\xa1\x03\xa4\x00\x14@\x05MHKM\x02[#XDHK\xff\xff\xa0\x06\x94h + \xa3\xa13y\x01vh`\xa0){`\x0c\xff\xff\xff\x00\x00\xa0\x0ci}`DHKNDHKN\xa1\x12{DHKN\x7f`\x0c\xff\xff\xff\xff\x00DHKN\xa1\x02\xa3[\'XDHK\x14\x13MHKS\x00\x86\\._SB_SLPB +\x80\x14\x0cMHKC\x01phDHKC\x14I\x08MHKP\x00[#XDHK\xff\xff\xa0\x11DHWWpDHWWap\x00DHWW\xa1O\x05\xa0\x11DHKWpDHKWap\x00DHKW\xa1J\x04\xa0\x11DHKDpDHKDap\x00DHKD\xa15\xa0\x11DHKSpDHKSap\x00DHKS\xa1!\xa0\x11DHKTpDHKTap\x00DHKT\xa1\rpDHKHap\x00DHKH[\'XDHK\xa4a\x14>MHKE\x01phDHKB[#XDHK\xff\xffp\x00DHKHp\x00DHKWp\x00DHKSp\x00DHKDp\x00DHKTp\x00DHWW[\'XDHK\x14E\x0bMHKQ\x01\xa0M +DHKB\xa0@\tDHKC[#XDHK\xff\xff\xa0\x06\x95h\x0b\x00\x10\xa1M\x06\xa0\x0c\x95h\x0b\x00 phDHKH\xa1M\x05\xa0\x0c\x95h\x0b\x000phDHKW\xa1M\x04\xa0\x0c\x95h\x0b\x00@phDHKS\xa1=\xa0\x0c\x95h\x0b\x00PphDHKD\xa1.\xa0\x0c\x95h\x0b\x00`phDHKH\xa1\x1f\xa0\x0c\x95h\x0b\x00pphDHKT\xa1\x10\xa0\x0c\x95h\x0b\x00\x80phDHWW\xa1\x01[\'XDHK\x86HKEY +\x80\xa1\x15\xa0\x13\x93h\x0b\x04\x10\x86\\._SB_SLPB +\x80\x14I\x05MHKB\x01\xa0&\x93h +\x00\\/\x05_SB_PCI0LPC_EC__BEEP +\x11p +\x00\\LIDB\xa1*\xa0&\x93h +\x01\\/\x05_SB_PCI0LPC_EC__BEEP +\x10p +\x01\\LIDB\xa1\x01\x14MHQC\x01\xa01\\WNTF\xa0\x0b\x93h +\x00\xa4\\CWAC\xa1\x1e\xa0\x0b\x93h +\x01\xa4\\CWAP\xa1\x10\xa0\x0b\x93h +\x02\xa4\\CWAT\xa1\x02\xa3\xa1\x02\xa3\xa4 +\x00\x14A\x08MHGC\x00\xa0C\x07\\WNTF[#XDHK\xff\xff\xa0:\\OSC4\xa0 \\/\x06_SB_PCI0LPC_EC__AC___PSRp +\x03`\xa1\x12\xa0 +\\C4NAp +\x03`\xa1\x05p +\x04`\xa1 \xa0\x18\\/\x04_SB_PCI0LPC_C4C3p +\x04`\xa1\x05p +\x03`[\'XDHK\xa4`\xa1\x02\xa3\xa4 +\x00\x14A\x13MHSC\x01\xa0F\x12\x90\\CWAC\\WNTF[#XDHK\xff\xff\xa0J\x08\\OSC4\xa0>\x93h +\x03\xa08\x92\\CWAS\x86\\._PR_CPU0 +\x81\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x81p +\x01\\CWASp +\x01\\C4NA\xa1C\x04\xa0=\x93h +\x04\xa07\\CWAS\x86\\._PR_CPU0 +\x81\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x81p +\x00\\CWASp +\x00\\C4NA\xa1\x02\xa3\xa1O\x07\xa0+\x93h +\x03\xa0%\x92\\CWASp +\x00\\/\x04_SB_PCI0LPC_C4C3p +\x01\\CWAS\xa1@\x05\xa0J\x04\x93h +\x04\xa0C\x04\\CWAS\xa03\x92\\/\x06_SB_PCI0LPC_EC__AC___PSRp +\x01\\/\x04_SB_PCI0LPC_C4C3p +\x00\\CWAS\xa1\x02\xa3[\'XDHK\xa1\x02\xa3\x10G\x14\\/\x05_SB_PCI0LPC_EC__HKEY\x14M\x04TDSC\x01p +\x01`\xa2\x1b`p\\/\x05_SB_PCI0LPC_EC__HANT`ph\\/\x05_SB_PCI0LPC_EC__HANT\xa0\x0c\x93h +!\\ATCC +\x00\x14\x0cTDSS\x01\\ATCCh\x14N\x08TDSG\x01{h +\xff`p`\\/\x05_SB_PCI0LPC_EC__HDAAzh +\x08`{` +\xffapa\\/\x05_SB_PCI0LPC_EC__HDABzh +\x10`{` +\xffapa\\/\x05_SB_PCI0LPC_EC__HDACzh +\x18`{` +\xffapa\\/\x05_SB_PCI0LPC_EC__HANA\x14!TDGC\x00p\\/\x05_SB_PCI0LPC_EC__HDDD`\xa4`\x14!TDGS\x00p\\/\x05_SB_PCI0LPC_EC__HAAA`\xa4`[\x81\x18ECOR\x11\x00@*HSD0\x08HSD1\x08HSD2\x08[\x81\x0eECOR\x11\x00@+HSDL\x10[\x81\x19ECOR\x11\x00@+HSDBH\x04HSDF\x10HSDC\x10[\x01I2CM\x07\x14?CHKS\x00p\x0b\xe8\x03`\xa2\x13HMPR[" +\x01v`\xa0\x07\x92`\xa4\x0b\x80\x80\xa0\x19HMDN\xa0\x0fHMST\xa4}\x0b\x00\x80HMST\x00\xa1\x03\xa4\x00\xa1\x05\xa4\x0b\x81\x80\x14 I2RT\x00p +\x02HMADp +!HMCMp +\x0bHMPR\xa4CHKS\x14&I2NT\x01p +\x02HMADp +"HMCMphHSD0p +\x06HMPR\xa4CHKS\x14K\x0eTATR\x00\xa0C\x0e\\H8DR[#I2CM\xff\xffI2RTpHSD0`\xa0%\x93` + \\/\x04_SB_PCI0LPC_TCSZHSD1HSD2I2NT`\xa1M\t\xa0%\x93` +!\\/\x04_SB_PCI0LPC_TCSTHSD1HSD2I2NT`\xa1D\x07\xa0I\x04\x93` +"\x08TSDC\x11\x0c +\t \x00pHSDBTSDC\\/\x04_SB_PCI0LPC_TCBSHSD1TSDCHSDFHSDCI2NT`\xa1\'\xa0%\x93` +#\\/\x04_SB_PCI0LPC_TSCLHSD1HSDLI2NT`[\'I2CM\x14\rTATE\x00p +\x01HETE\x08_ADR +\x00\x08_S3D +\x02\x08RID_ +\x00\x08LRRT\x12G\x13\x0e\x12\x15\x04\x0c\xff\xff\x01\x00 +\x00\\._SB_LNKA +\x00\x12\x15\x04\x0c\xff\xff\x02\x00 +\x00\\._SB_LNKA +\x00\x12\x15\x04\x0c\xff\xff\x1b\x00 +\x01\\._SB_LNKB +\x00\x12\x15\x04\x0c\xff\xff\x1c\x00 +\x00\\._SB_LNKE +\x00\x12\x15\x04\x0c\xff\xff\x1c\x00 +\x01\\._SB_LNKF +\x00\x12\x15\x04\x0c\xff\xff\x1c\x00 +\x02\\._SB_LNKG +\x00\x12\x15\x04\x0c\xff\xff\x1c\x00 +\x03\\._SB_LNKH +\x00\x12\x15\x04\x0c\xff\xff\x1d\x00 +\x00\\._SB_LNKA +\x00\x12\x15\x04\x0c\xff\xff\x1d\x00 +\x01\\._SB_LNKB +\x00\x12\x15\x04\x0c\xff\xff\x1d\x00 +\x02\\._SB_LNKC +\x00\x12\x15\x04\x0c\xff\xff\x1d\x00 +\x03\\._SB_LNKD +\x00\x12\x15\x04\x0c\xff\xff\x1f\x00 +\x00\\._SB_LNKH +\x00\x12\x15\x04\x0c\xff\xff\x1f\x00 +\x02\\._SB_LNKA +\x00\x12\x15\x04\x0c\xff\xff\x1f\x00 +\x01\\._SB_LNKA +\x00\x08ARRT\x12G\x0c\x0e\x12\r\x04\x0c\xff\xff\x01\x00 +\x00 +\x00 +\x10\x12\r\x04\x0c\xff\xff\x02\x00 +\x00 +\x00 +\x10\x12\r\x04\x0c\xff\xff\x1b\x00 +\x01 +\x00 +\x11\x12\r\x04\x0c\xff\xff\x1c\x00 +\x00 +\x00 +\x14\x12\r\x04\x0c\xff\xff\x1c\x00 +\x01 +\x00 +\x15\x12\r\x04\x0c\xff\xff\x1c\x00 +\x02 +\x00 +\x16\x12\r\x04\x0c\xff\xff\x1c\x00 +\x03 +\x00 +\x17\x12\r\x04\x0c\xff\xff\x1d\x00 +\x00 +\x00 +\x10\x12\r\x04\x0c\xff\xff\x1d\x00 +\x01 +\x00 +\x11\x12\r\x04\x0c\xff\xff\x1d\x00 +\x02 +\x00 +\x12\x12\r\x04\x0c\xff\xff\x1d\x00 +\x03 +\x00 +\x13\x12\r\x04\x0c\xff\xff\x1f\x00 +\x00 +\x00 +\x17\x12\r\x04\x0c\xff\xff\x1f\x00 +\x02 +\x00 +\x10\x12\r\x04\x0c\xff\xff\x1f\x00 +\x01 +\x00 +\x10\x14\x19_PRT\x00\xa0\x0b\\GPIC\xa4ARRT\xa1\x06\xa4LRRT\x08_HID\x0cA\xd0 +\x08\x08_CID\x0cA\xd0 +\x03\x08_BBN +\x00[\x80MHCS\x02 +\x00\x0b\x00\x01[\x815MHCS\x03\x00@HPAM0\x08PAM1\x08PAM2\x08PAM3\x08PAM4\x08PAM5\x08PAM6\x08\x00(\x00\x03TOUD\x05\x08_CRS\x11E\x1c\x0b\xc0\x01\x88\r\x00\x02\x0c\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x01G\x01\xf8\x0c\xf8\x0c\x01\x08\x88\r\x00\x01\x0c\x03\x00\x00\x00\x00\xf7\x0c\x00\x00\xf8\x0c\x88\r\x00\x01\x0c\x03\x00\x00\x00\r\xff\xff\x00\x00\x00\xf3\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\x00 +\x00\xff\xff\x0b\x00\x00\x00\x00\x00\x00\x00\x02\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\x00\x0c\x00\xff?\x0c\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00@\x0c\x00\xff\x7f\x0c\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\x80\x0c\x00\xff\xbf\x0c\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\xc0\x0c\x00\xff\xff\x0c\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\x00\r\x00\xff?\r\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00@\r\x00\xff\x7f\r\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\x80\r\x00\xff\xbf\r\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\xc0\r\x00\xff\xff\r\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\x00\x0e\x00\xff?\x0e\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00@\x0e\x00\xff\x7f\x0e\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\x80\x0e\x00\xff\xbf\x0e\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\xc0\x0e\x00\xff\xff\x0e\x00\x00\x00\x00\x00\x00@\x00\x00\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\x00\x10\x00\xff\xff\xbf\xfe\x00\x00\x00\x00\x00\x00\xb0\xfe\x87\x17\x00\x00\x0c\x03\x00\x00\x00\x00\x00\x00\xd4\xfe\xff\x0f\xd4\xfe\x00\x00\x00\x00\x00\x10\x00\x00y\x00\x8a_CRS +hC0LN\x8a_CRS +\x82C4LN\x8a_CRS +\x9cC8LN\x8a_CRS +\xb6CCLN\x8a_CRS +\xd0D0LN\x8a_CRS +\xeaD4LN\x8a_CRS\x0b\x04\x01D8LN\x8a_CRS\x0b\x1e\x01DCLN\x8a_CRS\x0b8\x01E0LN\x8a_CRS\x0bR\x01E4LN\x8a_CRS\x0bl\x01E8LN\x8a_CRS\x0b\x86\x01ECLN\x8a_CRS\x0b\x94\x01XXMN\x8a_CRS\x0b\x98\x01XXMX\x8a_CRS\x0b\xa0\x01XXLN\x8a_CRS\x0b\xae\x01F4MN\x8a_CRS\x0b\xb2\x01F4MX\x8a_CRS\x0b\xba\x01F4LN\x14A\x12_INI\x08\xa0\x11\x92\\OSIF\\._SB__INIyTOUD +\x1b`p`\\MEMXp`XXMNrtXXMXXXMN\x00 +\x01XXLN\xa0\x15\x92\x93{\\TPMP +\x01\x00 +\x01p +\x00F4LN\xa0\x10{PAM1 +\x03\x00p +\x00C0LN\xa0\x10{PAM1 +0\x00p +\x00C4LN\xa0\x10{PAM2 +\x03\x00p +\x00C8LN\xa0\x10{PAM2 +0\x00p +\x00CCLN\xa0\x10{PAM3 +\x03\x00p +\x00D0LN\xa0\x10{PAM3 +0\x00p +\x00D4LN\xa0\x10{PAM4 +\x03\x00p +\x00D8LN\xa0\x10{PAM4 +0\x00p +\x00DCLN\xa0\x10{PAM5 +\x03\x00p +\x00E0LN\xa0\x10{PAM5 +0\x00p +\x00E4LN\xa0\x10{PAM6 +\x03\x00p +\x00E8LN\xa0\x10{PAM6 +0\x00p +\x00ECLN\x08SUPP +\x00\x08CTRL +\x00\x14E,_OSC\x04\x8ak +\x00CDW1\x8ak +\x04CDW2\x8ak +\x08CDW3\x8ah +\x00IID0\x8ah +\x04IID1\x8ah +\x08IID2\x8ah +\x0cIID3\x08UID0\x11\x13 +\x10[M\xdb3\xf7\x1f\x1c@\x96WtA\xc0=\xd7f\x8aUID0 +\x00EID0\x8aUID0 +\x04EID1\x8aUID0 +\x08EID2\x8aUID0 +\x0cEID3\xa0A#\x90\x90\x93IID0EID0\x93IID1EID1\x90\x93IID2EID2\x93IID3EID3pCDW2SUPPpCDW3CTRL{CTRL +\x1dCTRL\xa0H\x1b\x80{CDW1 +\x01\x00\x00\xa0F\x0f{CTRL +\x01\x00\xa03\x92\\VIGDp +\x00\\/\x04_SB_PCI0AGP_HPGPp +\x00\\/\x04_SB_PCI0AGP_GMGPp +\x00\\/\x04_SB_PCI0EXP0HPCEp +\x01\\/\x04_SB_PCI0EXP0HPCSp +\x01\\/\x04_SB_PCI0EXP0ABP_p +\x01\\/\x04_SB_PCI0EXP0PDS_p +\x00\\/\x04_SB_PCI0EXP2HPCEp +\x01\\/\x04_SB_PCI0EXP2HPCSp +\x01\\/\x04_SB_PCI0EXP2ABP_p +\x01\\/\x04_SB_PCI0EXP2PDS_p +\x01\\NHPS\xa0D\x0b{CTRL +\x04\x00\xa03\x92\\VIGDp +\x00\\/\x04_SB_PCI0AGP_PMGPp +\x00\\/\x04_SB_PCI0AGP_GMGPp +\x00\\/\x04_SB_PCI0EXP0PMCEp +\x01\\/\x04_SB_PCI0EXP0PMCSp +\x00\\/\x04_SB_PCI0EXP2PMCEp +\x01\\/\x04_SB_PCI0EXP2PMCSp +\x00\\/\x04_SB_PCI0LPC_EXPEp +\x01\\NPME\xa0\x11\x92\x93i +\x01}CDW1 + +CDW1\xa0\x16\x92\x93CDW3CTRL}CDW1 +\x10CDW1pCTRLCDW3\xa1\x0c}CDW1 +\x06CDW1\xa4k[\x01MDGS\x07\x08VDEE +\x01\x08VDDA\x11\x03 +\x02\x8dVDDA +\x00VUPC\x8dVDDA +\x01VQDL\x8dVDDA +\x02VQDC\x8dVDDA +\x03VQDT\x8dVDDA +\x04VQDD\x8dVDDA +\x05VSDL\x8dVDDA +\x06VSDC\x8dVDDA +\x07VSDT\x8dVDDA +\x08VSDD\x8dVDDA + +MSWT\x8dVDDA +\x0bVWST[\x82OJVID_\x08_ADR\x0c\x00\x00\x02\x00\x08RID_ +\x00[\x80VPCG\x02 +\x00\x0b\x00\x01[\x81\x0eVPCG\x03\x00@jVPWR \x08_S3D +\x03\x145_INI\x00\\VUPS +\x02p\\VCDLVQDLp\\VCDCVQDCp\\VCDTVQDTp\\VCDDVQDD\x14\x07_PS0\x00\xa3\x14\x07_PS1\x00\xa3\x14\x07_PS2\x00\xa3\x14\x07_PS3\x00\xa3\x140VSWT\x00\xa0\x0f\\WVISp\\VEVT +\x07`\xa1 +p\\VEVT +\x05`{ +\x0f`a\xa0\taASWTa +\x01\x14E\x08VLOC\x01\xa0M\x07\x93h\\/\x03_SB_LID__LID\\VSLDh\xa0C\x06\x93VPWR +\x00\xa0?hp\\VEVT +\x01`\xa0\x13\\WXPF\x86\\._SB_PCI0 +\x00\xa1\x1a\xa0\x18\\WNTF\x86\\/\x03_SB_PCI0VID_ +\x00["\x0b\xee\x02\xa1 +p\\VEVT +\x02`{ +\x0f`a\xa0\taASWTa +\x00\x14G\x07_DOS\x01\xa0:\x93h +\x02p +\x14`\xa20`v`[#MDGS\xff\xff\xa0\x19\x93 +\x00MSWTp +\x01MSWTp +\x00`phVDEE[\'MDGS[" +\xc8\xa14[#MDGS\xff\xff\xa0\x0f\x93VDEE +\x02p +\x00MSWT\xa0\x0c\x94h +\x02p +\x01VDEE\xa1\x07phVDEE[\'MDGS\x14\x13_DOD\x00\xa4\x12\x0b\x03\x0b\x00\x01\x0b\x00\x03\x0b\x00\x04\x14L\x0bASWT\x02\xa0\x14\x93 +\x01VDEE{ +\x01ia\\VSDSha\xa1O\tp +\x14`\xa2A\x08`v`[#MDGS\xff\xff\xa0I\x06\x93 +\x00MSWTp +\x00`\xa0\r{ +\x01i\x00p +\x01VUPC\xa1\x08p +\x00VUPC\xa0\r{ +\x01h\x00p +\x01VQDL\xa1\x08p +\x00VQDL\xa0\r{ +\x02h\x00p +\x01VQDC\xa1\x08p +\x00VQDC\xa0\r{ +\x08h\x00p +\x01VQDD\xa1\x08p +\x00VQDD[\'MDGS[" +\xc8\xa0\r{ +\x02i\x00\x86VID_ +\x81\xa1\x08\x86VID_ +\x80\x14I\x06VDSW\x01\xa0A\x06\x93VPWR +\x00\xa0D\x04hp\\VEVT +\x03`\xa0\x15\\WVIS{ +\x0f`a\xa0\taASWTa +\x00\xa1!\xa0\x07\\WXPF\xa3\xa1\x17\xa0\x15\\WNTF{ +\x0f`a\xa0\taASWTa +\x00\xa1\x12p\\VEVT +\x04`ASWT +\x01 +\x00\x14\x1eVSPD\x00p\\VEVT +\x06`{ +\x0f`a\xa0\taASWTa +\x01[\x82H\x06LCD0\x08_ADR\x0b\x00\x04\x14\x1c_DCS\x00\\VUPS +\x00\xa0\t\\VCDL\xa4 +\x1f\xa1\x04\xa4 +\x1d\x14\x0b_DGS\x00\xa4VQDL\x140_DSS\x01{h +\x01VSDL\xa0!{h\x0c\x00\x00\x00\x80\x00\xa0\x0f{h\x0c\x00\x00\x00@\x00DSWT +\x02\xa1\x07DSWT +\x01[\x82@\x08CRT0\x08_ADR\x0b\x00\x01\x144_DCS\x00\\VUPS +\x01\xa0\x15\\VCSS\xa0\t\\VCDC\xa4 +\x1f\xa1\x04\xa4 +\x1d\xa1\x10\xa0\t\\VCDC\xa4 +\x0f\xa1\x04\xa4 +\r\x14\x0b_DGS\x00\xa4VQDC\x140_DSS\x01{h +\x01VSDC\xa0!{h\x0c\x00\x00\x00\x80\x00\xa0\x0f{h\x0c\x00\x00\x00@\x00DSWT +\x02\xa1\x07DSWT +\x01[\x82H\x06DVI0\x08_ADR\x0b\x00\x03\x14\x1c_DCS\x00\\VUPS +\x00\xa0\t\\VCDD\xa4 +\x1f\xa1\x04\xa4 +\x1d\x14\x0b_DGS\x00\xa4VQDD\x140_DSS\x01{h +\x01VSDD\xa0!{h\x0c\x00\x00\x00\x80\x00\xa0\x0f{h\x0c\x00\x00\x00@\x00DSWT +\x02\xa1\x07DSWT +\x01\x14?DSWT\x01\xa0\tVSDLp +\x01`\xa1\x05p +\x00`\xa0 +VSDC} +\x02``\xa0 +VSDD} +\x08``\xa0\x0f`\xa0\x0cVUPC\\VSDS`h\xa1\x02\xa3[\x82BUAGP_\x08_ADR\x0c\x00\x00\x01\x00\x08_S3D +\x03\x08RID_ +\x00\x08LART\x12*\x02\x12\x13\x04\x0b\xff\xff +\x00\\._SB_LNKA +\x00\x12\x13\x04\x0b\xff\xff +\x01\\._SB_LNKB +\x00\x08AART\x12\x1a\x02\x12\x0b\x04\x0b\xff\xff +\x00 +\x00 +\x10\x12\x0b\x04\x0b\xff\xff +\x01 +\x00 +\x11\x14\x19_PRT\x00\xa0\x0b\\GPIC\xa4AART\xa1\x06\xa4LART[\x01MDGS\x07\x08VDEE +\x01\x08VDDA\x11\x03 +\x02\x8dVDDA +\x00VUPC\x8dVDDA +\x01VQDL\x8dVDDA +\x02VQDC\x8dVDDA +\x03VQDT\x8dVDDA +\x04VQDD\x8dVDDA +\x05VSDL\x8dVDDA +\x06VSDC\x8dVDDA +\x07VSDT\x8dVDDA +\x08VSDD\x8dVDDA + +MSWT\x8dVDDA +\x0bVWST[\x82BAVID_\x08_ADR +\x00[\x80VPCG\x02 +\x00\x0b\x00\x01[\x81\x0eVPCG\x03\x00@*VPWR \x08_S3D +\x03\x145_INI\x00\\VUPS +\x02p\\VCDLVQDLp\\VCDCVQDCp\\VCDTVQDTp\\VCDDVQDD\x14\x07_PS0\x00\xa3\x14\x07_PS1\x00\xa3\x14\x07_PS2\x00\xa3\x14\x07_PS3\x00\xa3\x140VSWT\x00\xa0\x0f\\WVISp\\VEVT +\x07`\xa1 +p\\VEVT +\x05`{ +\x0f`a\xa0\taASWTa +\x01\x14@\x05VLOC\x01\xa0H\x04\x93h\\/\x03_SB_LID__LID\\VSLDh\xa0.\x93VPWR +\x00\xa0\x0bhp\\VEVT +\x01`\xa1 +p\\VEVT +\x02`{ +\x0f`a\xa0\taASWTa +\x00\x14G\x07_DOS\x01\xa0:\x93h +\x02p +\x14`\xa20`v`[#MDGS\xff\xff\xa0\x19\x93 +\x00MSWTp +\x01MSWTp +\x00`phVDEE[\'MDGS[" +\xc8\xa14[#MDGS\xff\xff\xa0\x0f\x93VDEE +\x02p +\x00MSWT\xa0\x0c\x94h +\x02p +\x01VDEE\xa1\x07phVDEE[\'MDGS\x14\x13_DOD\x00\xa4\x12\x0b\x03\x0b\x00\x01\x0b\x10\x02\x0b\x10\x01\x14L\x0bASWT\x02\xa0\x14\x93 +\x01VDEE{ +\x01ia\\VSDSha\xa1O\tp +\x14`\xa2A\x08`v`[#MDGS\xff\xff\xa0I\x06\x93 +\x00MSWTp +\x00`\xa0\r{ +\x01i\x00p +\x01VUPC\xa1\x08p +\x00VUPC\xa0\r{ +\x01h\x00p +\x01VQDL\xa1\x08p +\x00VQDL\xa0\r{ +\x02h\x00p +\x01VQDC\xa1\x08p +\x00VQDC\xa0\r{ +\x08h\x00p +\x01VQDD\xa1\x08p +\x00VQDD[\'MDGS[" +\xc8\xa0\r{ +\x02i\x00\x86VID_ +\x81\xa1\x08\x86VID_ +\x80[\x82C\tLCD0\x08_ADR\x0b\x10\x01\x14\x1c_DCS\x00\\VUPS +\x00\xa0\t\\VCDL\xa4 +\x1f\xa1\x04\xa4 +\x1d\x14*_DDC\x01\\VDDC\xa0\x0b\x93h +\x01\xa4\\DDC1\xa1\x12\xa0\x0b\x93h +\x02\xa4\\DDC2\xa1\x04\xa4 +\x00\x14\x0b_DGS\x00\xa4VQDL\x140_DSS\x01{h +\x01VSDL\xa0!{h\x0c\x00\x00\x00\x80\x00\xa0\x0f{h\x0c\x00\x00\x00@\x00DSWT +\x02\xa1\x07DSWT +\x01[\x82@\x08CRT0\x08_ADR\x0b\x00\x01\x144_DCS\x00\\VUPS +\x01\xa0\x15\\VCSS\xa0\t\\VCDC\xa4 +\x1f\xa1\x04\xa4 +\x1d\xa1\x10\xa0\t\\VCDC\xa4 +\x0f\xa1\x04\xa4 +\r\x14\x0b_DGS\x00\xa4VQDC\x140_DSS\x01{h +\x01VSDC\xa0!{h\x0c\x00\x00\x00\x80\x00\xa0\x0f{h\x0c\x00\x00\x00@\x00DSWT +\x02\xa1\x07DSWT +\x01[\x82H\x06DVI0\x08_ADR\x0b\x10\x02\x14\x1c_DCS\x00\\VUPS +\x00\xa0\t\\VCDD\xa4 +\x1f\xa1\x04\xa4 +\x1d\x14\x0b_DGS\x00\xa4VQDD\x140_DSS\x01{h +\x01VSDD\xa0!{h\x0c\x00\x00\x00\x80\x00\xa0\x0f{h\x0c\x00\x00\x00@\x00DSWT +\x02\xa1\x07DSWT +\x01\x14?DSWT\x01\xa0\tVSDLp +\x01`\xa1\x05p +\x00`\xa0 +VSDC} +\x02``\xa0 +VSDD} +\x08``\xa0\x0f`\xa0\x0cVUPC\\VSDS`h\xa1\x02\xa3[\x80PEGC\x02 +\x00\x0b\x00\x01[\x81\x18PEGC\x03\x00@vGMGP\x01HPGP\x01PMGP\x01[\x82I\x12EXP0\x08_ADR\x0c\x00\x00\x1c\x00\x08RID_ +\x00[\x80P0CS\x02 +\x00\x0b\x00\x01[\x81M\x04P0CS\x03\x00@-ABP_\x01\x00\x02PDC_\x01\x00\x02PDS_\x01\x00\x01\x00(RID0\x10PSP0\x01PPP0\x01\x00F<\x00\x06HPCE\x01PMCE\x01\x00\x18\x00\x06HPCS\x01PMCS\x01\x08_PRW\x12\x06\x02 +\t +\x04\x08LPRT\x12C\x05\x04\x12\x13\x04\x0b\xff\xff +\x00\\._SB_LNKA +\x00\x12\x13\x04\x0b\xff\xff +\x01\\._SB_LNKB +\x00\x12\x13\x04\x0b\xff\xff +\x02\\._SB_LNKC +\x00\x12\x13\x04\x0b\xff\xff +\x03\\._SB_LNKD +\x00\x08APRT\x122\x04\x12\x0b\x04\x0b\xff\xff +\x00 +\x00 +\x10\x12\x0b\x04\x0b\xff\xff +\x01 +\x00 +\x11\x12\x0b\x04\x0b\xff\xff +\x02 +\x00 +\x12\x12\x0b\x04\x0b\xff\xff +\x03 +\x00 +\x13\x14\x19_PRT\x00\xa0\x0b\\GPIC\xa4APRT\xa1\x06\xa4LPRT[\x82D\x0fEXP1\x08_ADR\x0c\x01\x00\x1c\x00\x08RID_ +\x00[\x80P1CS\x02 +\x00\x0b\x00\x01[\x81\x18P1CS\x03\x00@0RID1\x10PSP1\x01PPP1\x01\x08_PRW\x12\x06\x02 +\t +\x04\x08LPRT\x12C\x05\x04\x12\x13\x04\x0b\xff\xff +\x00\\._SB_LNKB +\x00\x12\x13\x04\x0b\xff\xff +\x01\\._SB_LNKC +\x00\x12\x13\x04\x0b\xff\xff +\x02\\._SB_LNKD +\x00\x12\x13\x04\x0b\xff\xff +\x03\\._SB_LNKA +\x00\x08APRT\x122\x04\x12\x0b\x04\x0b\xff\xff +\x00 +\x00 +\x11\x12\x0b\x04\x0b\xff\xff +\x01 +\x00 +\x12\x12\x0b\x04\x0b\xff\xff +\x02 +\x00 +\x13\x12\x0b\x04\x0b\xff\xff +\x03 +\x00 +\x10\x14\x19_PRT\x00\xa0\x0b\\GPIC\xa4APRT\xa1\x06\xa4LPRT[\x82H\x14EXP2\x08_ADR\x0c\x02\x00\x1c\x00\x08RID_ +\x00\x08XCPF +\x00[\x80P2CS\x02 +\x00\x0b\x00\x01[\x81M\x04P2CS\x03\x00@-ABP_\x01\x00\x02PDC_\x01\x00\x02PDS_\x01\x00\x01\x00(RID2\x10PSP2\x01PPP2\x01\x00F<\x00\x06HPCE\x01PMCE\x01\x00\x18\x00\x06HPCS\x01PMCS\x01\x08_PRW\x12\x06\x02 +\t +\x04\x08LPRT\x12C\x05\x04\x12\x13\x04\x0b\xff\xff +\x00\\._SB_LNKC +\x00\x12\x13\x04\x0b\xff\xff +\x01\\._SB_LNKD +\x00\x12\x13\x04\x0b\xff\xff +\x02\\._SB_LNKA +\x00\x12\x13\x04\x0b\xff\xff +\x03\\._SB_LNKB +\x00\x08APRT\x122\x04\x12\x0b\x04\x0b\xff\xff +\x00 +\x00 +\x12\x12\x0b\x04\x0b\xff\xff +\x01 +\x00 +\x13\x12\x0b\x04\x0b\xff\xff +\x02 +\x00 +\x10\x12\x0b\x04\x0b\xff\xff +\x03 +\x00 +\x11\x14\x19_PRT\x00\xa0\x0b\\GPIC\xa4APRT\xa1\x06\xa4LPRT[\x82\x16EXUP\x08_ADR +\x00\x14\t_RMV\x00\xa4 +\x01[\x82B\x10EXP3\x08_ADR\x0c\x03\x00\x1c\x00\x08RID_ +\x00[\x80P3CS\x02 +\x00\x0b\x00\x01[\x81\x18P3CS\x03\x00@0RID3\x10PSP3\x01PPP3\x01\x08_PRW\x12\x06\x02 +\t +\x04\x08LPRT\x12C\x05\x04\x12\x13\x04\x0b\xff\xff +\x00\\._SB_LNKD +\x00\x12\x13\x04\x0b\xff\xff +\x01\\._SB_LNKA +\x00\x12\x13\x04\x0b\xff\xff +\x02\\._SB_LNKB +\x00\x12\x13\x04\x0b\xff\xff +\x03\\._SB_LNKC +\x00\x08APRT\x122\x04\x12\x0b\x04\x0b\xff\xff +\x00 +\x00 +\x13\x12\x0b\x04\x0b\xff\xff +\x01 +\x00 +\x10\x12\x0b\x04\x0b\xff\xff +\x02 +\x00 +\x11\x12\x0b\x04\x0b\xff\xff +\x03 +\x00 +\x12\x14\x19_PRT\x00\xa0\x0b\\GPIC\xa4APRT\xa1\x06\xa4LPRT[\x82\x0cEXPD\x08_ADR +\x00[\x82O\x16PCI1\x08_ADR\x0c\x00\x00\x1e\x00\x08_S3D +\x02\x08RID_ +\x00\x08LPRT\x12G\t\x07\x12\x13\x04\x0b\xff\xff +\x00\\._SB_LNKA +\x00\x12\x13\x04\x0b\xff\xff +\x01\\._SB_LNKB +\x00\x12\x13\x04\x0b\xff\xff +\x02\\._SB_LNKC +\x00\x12\x15\x04\x0c\xff\xff\x01\x00 +\x00\\._SB_LNKA +\x00\x12\x15\x04\x0c\xff\xff\x02\x00 +\x00\\._SB_LNKF +\x00\x12\x15\x04\x0c\xff\xff\x02\x00 +\x01\\._SB_LNKG +\x00\x12\x15\x04\x0c\xff\xff\x08\x00 +\x00\\._SB_LNKE +\x00\x08APRT\x12O\x05\x07\x12\x0b\x04\x0b\xff\xff +\x00 +\x00 +\x10\x12\x0b\x04\x0b\xff\xff +\x01 +\x00 +\x11\x12\x0b\x04\x0b\xff\xff +\x02 +\x00 +\x12\x12\r\x04\x0c\xff\xff\x01\x00 +\x00 +\x00 +\x10\x12\r\x04\x0c\xff\xff\x02\x00 +\x00 +\x00 +\x15\x12\r\x04\x0c\xff\xff\x02\x00 +\x01 +\x00 +\x16\x12\r\x04\x0c\xff\xff\x08\x00 +\x00 +\x00 +\x14\x14\x19_PRT\x00\xa0\x0b\\GPIC\xa4APRT\xa1\x06\xa4LPRT\x08_PRW\x12\x06\x02 +\x0b +\x04[\x82\'CDBS\x08_ADR +\x00\x14\x13_S3D\x00\xa0\t\\WMEF\xa4 +\x02\xa4 +\x03\x08_SUN +\x01[\x82L\xb8IDE0\x08_ADR\x0c\x01\x00\x1f\x00\x08_S3D +\x03\x08RID_ +\x00[\x80IDCS\x02 +\x00\x0b\x00\x01[\x81@\x12IDCS\x03\x00@ PFT0\x01PIE0\x01PPE0\x01PDT0\x01PFT1\x01PIE1\x01PPE1\x01PDT1\x01PRC0\x02\x00\x02PIS0\x02PSIE\x01PIDE\x01SFT0\x01SIE0\x01SPE0\x01SDT0\x01SFT1\x01SIE1\x01SPE1\x01SDT1\x01SRC0\x02\x00\x02SIS0\x02SSIE\x01SIDE\x01PRC1\x02PIS1\x02SRC1\x02SIS1\x02\x00\x18PSD0\x01PSD1\x01SSD0\x01SSD1\x01\x00\x0cPCT0\x02\x00\x02PCT1\x02\x00\x02SCT0\x02\x00\x02SCT1\x02\x00\x02\x00@\x04PCB0\x01PCB1\x01SCB0\x01SCB1\x01PCR0\x01PCR1\x01SCR0\x01SCR1\x01\x00\x02WRPP\x01\x00\x01FPB0\x01FPB1\x01FSB0\x01FSB1\x01PSIG\x02SSIG\x02[\x81\x1fIDCS\x03\x00@ PTI0\x04PTI1\x04\x00\x08STI0\x04STI1\x04\x14\'GPCT\x04\xa0\t\x92}hi\x00\xa4 +\x00\xa0\t\x90\x92hi\xa4\x0b\x84\x03\xa4wt +\trjk\x00\x00 +\x1e\x00\x14*GDCT\x04\xa0\x06\x92h\xa4 +\x00\xa0\x05i\xa4 +\x14\xa0\x0cj\xa4wt +\x04k\x00 +\x0f\x00\xa4wt +\x04k\x00 +\x1e\x00\x142MTIM\x02p +\x00`\xa0\x07h}` +\x01`\xa0\x0b\x92\x95h +\x02}` +\x02`\xa0\x08\x92i}` +\x04`\xa0\x08\x92h}` +\x08`\xa4`\x14\x1aMISP\x01\xa0\x06\x92h\xa4 +\x00\xa0\t\x92\x94h +\x02\xa4 +\x01\xa4 +\x02\x14\x1cMRCT\x01\xa0\t\x92\x94h +\x02\xa4 +\x00\xa0\x08\x93h +\x03\xa4 +\x01\xa4 +\x03[\x82O\x95PRIM\x08_ADR +\x00\x08BGTM\x11\x03 +\x14\x8aBGTM +\x00GTP0\x8aBGTM +\x04GTD0\x8aBGTM +\x08GTP1\x8aBGTM +\x0cGTD1\x8aBGTM +\x10GTMF\x08BPI0 +\x00\x08BDM0 +\x00\x08BPI1 +\x00\x08BDM1 +\x00\x08DRE0 +\x00\x08DRE1 +\x00\x08DIP0 +\x00\x08DIP1 +\x00\x14M\x11_GTM\x00pGPCTPFT0PDT0PIS0PRC0GTP0pGDCTPSD0FPB0PCB0PCT0GTD0\xa0\x0f\x92GTD0pGTP0GTD0\xa0H\x04PSIEpGPCTPFT1PDT1PIS1PRC1GTP1pGDCTPSD1FPB1PCB1PCT1GTD1\xa0\x0f\x92GTD1pGTP1GTD1\xa1\x0fp +\x00GTP1p +\x00GTD1p +\x00GTMF\xa0\x10PSD0}GTMF +\x01GTMF\xa0\x1f\x92GTP0}GTMF +\x01GTMFp +xGTP0p +\x14GTD0\xa0\x10PIE0}GTMF +\x02GTMF\xa0\x10PSD1}GTMF +\x04GTMF\xa0\x10PIE1}GTMF +\x08GTMF}GTMF +\x10GTMF\xa4BGTM\x14@G_STM\x03\x8ah +\x00STP0\x8ah +\x04STD0\x8ah +\x08STP1\x8ah +\x0cSTD1\x8ah +\x10STMFp +\x00DRE0p +\x00DIP0\xa0G$\x93\x87i\x0b\x00\x02\x8bi +\x00M000\x8bi +bM049\x8bi +fM051\x8bi +jM053\x8bi +|M062\x8bi +~M063\x8bi +\x80M064\x8bi +\x82M065\x8bi +\x88M068\x8bi +\x9cM078\x8bi +\xacM086\x8bi +\xb0M088\x8bi +\xeeM119\x8bi\x0b(\x01M148\xa0\x1f\x93{M148\x0b\x00\xc0\x00\x0b\x00@\xa0\x10{M148 +\x04\x00p +\x01DRE0\xa0\x1b{M086\x0b\x00\x80\x00\xa0\x10{M119 +\x01\x00p +\x01DRE0\xa0E\t\\W98Fp\\UUDMM053M088STD0\xa0\x10STD0}STMF +\x01STMF\xa1\x0c{STMF +\xfeSTMFp\\UMDMM053M063M062M065STP0\xa0 \x92STP0p\\UPIOM053M064M051M068STP0\xa0\x15{M049\x0b\x00\x08\x00}STMF +\x02STMF\xa1\x0c{STMF +\xfdSTMFp\\DPIOSTP0{STMF +\x02\x00`p\\DUDMSTD0{STMF +\x01\x00a\xa0&\x92\x95\\/\x05_SB_PCI0LPC_EC__BGID +\x00 +\x0cp +\x00`p +\xffapMTIM`{M000\x0b\x00\x80\x00PTI0pMISP`PIS0pMRCT`PRC0\xa0\x0c\x93a +\xffp +\x00PSD0\xa1C\x06p +\x01PSD0\xa0\x0c\x92\x94a +\x02paPCT0\xa1\x18\xa0\r{a +\x01\x00p +\x01PCT0\xa1\x08p +\x02PCT0\xa0\r\x92\x95a +\x03p +\x01PCB0\xa1\x08p +\x00PCB0\xa0\x0c\x93a +\x05p +\x01FPB0\xa1\x08p +\x00FPB0p +\x01PCR0p\\FDMA`aBDM0p\\FPIO`BPI0\xa0J\x1e\x93\x87j\x0b\x00\x02\x8bj +\x00S000\x8bj +bS049\x8bj +fS051\x8bj +jS053\x8bj +|S062\x8bj +~S063\x8bj +\x80S064\x8bj +\x82S065\x8bj +\x88S068\x8bj +\xb0S088\xa0E\t\\W98Fp\\UUDMS053S088STD1\xa0\x10STD1}STMF +\x04STMF\xa1\x0c{STMF +\xfbSTMFp\\UMDMS053S063S062S065STP1\xa0 \x92STP1p\\UPIOS053S064S051S068STP1\xa0\x15{S049\x0b\x00\x08\x00}STMF +\x08STMF\xa1\x0c{STMF +\xf7STMFp\\DPIOSTP1{STMF +\x08\x00`p\\DUDMSTD1{STMF +\x04\x00a\xa0=STP1pMTIM`{S000\x0b\x00\x80\x00PTI1\xa0${STMF +\x10\x00pMISP`PIS1pMRCT`PRC1p +\x01PSIE\xa1\x0fp +\x00PTI1p +\x00PSIE\xa0\x0c\x93a +\xffp +\x00PSD1\xa1C\x06p +\x01PSD1\xa0\x0c\x92\x94a +\x02paPCT1\xa1\x18\xa0\r{a +\x01\x00p +\x01PCT1\xa1\x08p +\x02PCT1\xa0\r\x92\x95a +\x03p +\x01PCB1\xa1\x08p +\x00PCB1\xa0\x0c\x93a +\x05p +\x01FPB1\xa1\x08p +\x00FPB1p +\x01PCR1p\\FDMA`aBDM1p\\FPIO`BPI1[\x82I4MSTR\x08_ADR +\x00\x08HDTF\x11\x1f +\x1c\x02\x00\x00\x00\x00\xa0\xef\x00\x00\x00\x00\x00\xa0\xf5\x03\x00\x00\x00\x00\xa0\xef\x03\x00\x00\x00\x00\xa0\xef\x8cHDTF +\x0fHDMA\x8cHDTF +\x16HPIO\x8cHDTF +\rHFLC\x08ERTF\x11& +#\x02\x00\x00\x00\x00\xa0\xef\x00\x00\x00\x00\x00\xa0\xf5\x03\x00\x00\x00\x00\xa0\xef\x03\x00\x00\x00\x00\xa0\xef_\x00\x00\x00\x00\xa0\xef\x8cERTF +\x0fEDMA\x8cERTF +\x16EPIO\x8cERTF +\rEFLC\x08HPTF\x11& +#\x02\x00\x00\x00\x00\xa0\xef\x00\x00\x00\x00\x00\xa0\xf5\x03\x00\x00\x00\x00\xa0\xef\x03\x00\x00\x00\x00\xa0\xef\x10\x03\x00\x00\x00\xa0\xef\x8cHPTF +\x0fPDMA\x8cHPTF +\x16PPIO\x8cHPTF +\rPFLC\x08HXTF\x11- +*\x02\x00\x00\x00\x00\xa0\xef\x00\x00\x00\x00\x00\xa0\xf5\x03\x00\x00\x00\x00\xa0\xef\x03\x00\x00\x00\x00\xa0\xef_\x00\x00\x00\x00\xa0\xef\x10\x03\x00\x00\x00\xa0\xef\x8cHXTF +\x0fXDMA\x8cHXTF +\x16XPIO\x8cHXTF +\rXFLC\x08IDTF\x11\x11 +\x0e\x03\x00\x00\x00\x00\xa0\xef\x03\x00\x00\x00\x00\xa0\xef\x8cIDTF +\x01IDMA\x8cIDTF +\x08IPIO\x08DDTF\x11\x1f +\x1c\x03\x00\x00\x00\x00\xa0\xef\x03\x00\x00\x00\x00\xa0\xef\x00\x00\x00\x00\x00\xa0\xe3\x00\x00\x00\x00\x00\xa0\xe3\x8cDDTF +\x01DDMA\x8cDDTF +\x08DPIO\x8cDDTF +\x0fDTAT\x8cDDTF +\x16DTFT\x14@\x14_GTF\x00p\\/\x05_SB_PCI0LPC_EC__BGID +\x00`\xa0"\\OSSSp +\xe1HFLCp +\xe1EFLCp +\xe1PFLCp +\xe1XFLC\xa0M\x08\x93` +\x06\xa0H\x04^^DRE0\xa0"^^DIP0p^^BDM0XDMAp^^BPI0XPIO\xa4HXTF\xa1\x1cp^^BDM0EDMAp^^BPI0EPIO\xa4ERTF\xa0"^^DIP0p^^BDM0PDMAp^^BPI0PPIO\xa4HPTFp^^BDM0HDMAp^^BPI0HPIO\xa4HDTFp\x00a\xa0\x08\x93` +\x03p\x01a\xa0\x08\x93` + +p\x01a\xa0\x08\x93` +\x0bp\x01a\xa01ap\\CDFLDTFTp\\CDAHDTATp^^BDM0DDMAp^^BPI0DPIO\xa4DDTF\xa1\x1cp^^BDM0IDMAp^^BPI0IPIO\xa4IDTF\x14\x1e_EJ0\x01\\/\x05_SB_PCI0LPC_EC__BEJ0h\x14)_STA\x00\xa0\x1d\\/\x05_SB_PCI0LPC_EC__BSTA +\x01\xa4 +\x0f\xa1\x04\xa4 +\x00[\x82K"SATA\x08_ADR\x0c\x02\x00\x1f\x00\x08_S3D +\x03\x08RID_ +\x00[\x80IDCS\x02 +\x00\x0b\x00\x01[\x81@\x12IDCS\x03\x00@ PFT0\x01PIE0\x01PPE0\x01PDT0\x01PFT1\x01PIE1\x01PPE1\x01PDT1\x01PRC0\x02\x00\x02PIS0\x02PSIE\x01PIDE\x01SFT0\x01SIE0\x01SPE0\x01SDT0\x01SFT1\x01SIE1\x01SPE1\x01SDT1\x01SRC0\x02\x00\x02SIS0\x02SSIE\x01SIDE\x01PRC1\x02PIS1\x02SRC1\x02SIS1\x02\x00\x18PSD0\x01PSD1\x01SSD0\x01SSD1\x01\x00\x0cPCT0\x02\x00\x02PCT1\x02\x00\x02SCT0\x02\x00\x02SCT1\x02\x00\x02\x00@\x04PCB0\x01PCB1\x01SCB0\x01SCB1\x01PCR0\x01PCR1\x01SCR0\x01SCR1\x01\x00\x02WRPP\x01\x00\x01FPB0\x01FPB1\x01FSB0\x01FSB1\x01PSIG\x02SSIG\x02[\x81\x1fIDCS\x03\x00@ PTI0\x04PTI1\x04\x00\x08STI0\x04STI1\x04\x14\'GPCT\x04\xa0\t\x92}hi\x00\xa4 +\x00\xa0\t\x90\x92hi\xa4\x0b\x84\x03\xa4wt +\trjk\x00\x00 +\x1e\x00\x14*GDCT\x04\xa0\x06\x92h\xa4 +\x00\xa0\x05i\xa4 +\x14\xa0\x0cj\xa4wt +\x04k\x00 +\x0f\x00\xa4wt +\x04k\x00 +\x1e\x00\x142MTIM\x02p +\x00`\xa0\x07h}` +\x01`\xa0\x0b\x92\x95h +\x02}` +\x02`\xa0\x08\x92i}` +\x04`\xa0\x08\x92h}` +\x08`\xa4`\x14\x1aMISP\x01\xa0\x06\x92h\xa4 +\x00\xa0\t\x92\x94h +\x02\xa4 +\x01\xa4 +\x02\x14\x1cMRCT\x01\xa0\t\x92\x94h +\x02\xa4 +\x00\xa0\x08\x93h +\x03\xa4 +\x01\xa4 +\x03[\x82\x1dSMBU\x08_ADR\x0c\x03\x00\x1f\x00\x08_S3D +\x03\x08RID_ +\x00[\x82J\x0eUSB0\x08_ADR\x0c\x00\x00\x1d\x00\x08_S3D +\x02\x08RID_ +\x00[\x80U0CS\x02 +\xc4 +\x04[\x81\rU0CS\x03U0EN\x02\x00\x1e\x08_PR0\x12\x19\x01\\/\x05_SB_PCI0LPC_EC__PUBS\x08_PR1\x12\x19\x01\\/\x05_SB_PCI0LPC_EC__PUBS\x08_PR2\x12\x19\x01\\/\x05_SB_PCI0LPC_EC__PUBS\x08_PRW\x12\x1d\x03 +\x03 +\x03\\/\x05_SB_PCI0LPC_EC__PUBS\x141_PSW\x01\xa0\thp +\x03U0EN\xa1\x08p +\x00U0EN\\/\x05_SB_PCI0LPC_EC__PNSTh[\x82J\x07USB1\x08_ADR\x0c\x01\x00\x1d\x00\x08_S3D +\x02\x08RID_ +\x00[\x80U1CS\x02 +\xc4 +\x04[\x81\rU1CS\x03U1EN\x02\x00\x1e\x08_PRW\x12\x06\x02 +\x04 +\x03\x14\x19_PSW\x01\xa0\thp +\x03U1EN\xa1\x08p +\x00U1EN[\x82\x1aURTH\x08_ADR +\x00[\x82\x0cUPEX\x08_ADR +\x02[\x82N\x0eUSB2\x08_ADR\x0c\x02\x00\x1d\x00\x08_S3D +\x02\x08RID_ +\x00[\x80U2CS\x02 +\xc4 +\x04[\x81\rU2CS\x03U2EN\x02\x00\x1e\x08_PR0\x12\x19\x01\\/\x05_SB_PCI0LPC_EC__PUBS\x08_PR1\x12\x19\x01\\/\x05_SB_PCI0LPC_EC__PUBS\x08_PR2\x12\x19\x01\\/\x05_SB_PCI0LPC_EC__PUBS\x08_PRW\x12\x1d\x03 +\x0c +\x03\\/\x05_SB_PCI0LPC_EC__PUBS\x14\x19_PSW\x01\xa0\thp +\x03U2EN\xa1\x08p +\x00U2EN[\x82\x1aURTH\x08_ADR +\x00[\x82\x0cUPDK\x08_ADR +\x02[\x82\x16USB3\x08_ADR\x0c\x03\x00\x1d\x00\x08RID_ +\x00[\x82N\x0fUSB7\x08_ADR\x0c\x07\x00\x1d\x00\x08_S3D +\x03\x08RID_ +\x00[\x80U7CS\x02 +` +\x04[\x81\x14U7CS\x03\x00\x10PWKI\x01PWUC\x06\x00\t\x08_PR0\x12\x19\x01\\/\x05_SB_PCI0LPC_EC__PUBS\x08_PR1\x12\x19\x01\\/\x05_SB_PCI0LPC_EC__PUBS\x08_PR2\x12\x19\x01\\/\x05_SB_PCI0LPC_EC__PUBS\x14\x14_INI\x00p +\x01PWKIp +\x0fPWUC\x08_PRW\x12\x1d\x03 +\r +\x03\\/\x05_SB_PCI0LPC_EC__PUBS[\x82(URTH\x08_ADR +\x00[\x82\x0cUPDK\x08_ADR +\x06[\x82\x0cUPEX\x08_ADR +\x04[\x821HDEF\x08_ADR\x0c\x00\x00\x1b\x00\x08_S3D +\x03\x08RID_ +\x00\x08_PRW\x12\x06\x02 +\x05 +\x04\x14\x07_PSW\x01\xa3\x10C\xbe\\/\x04_SB_PCI0LPC_EC__\x08BDEV +\xff\x08BSTS +\x00\x08BHKE +\x00\x08BXCN +\x00\x142_Q2C\x00\xa0+\x93BSTS +\x00pBGID +\x00BDEV\xa0\rBXCNNXREBDEV\xa1\tNBREBDEV\x14)_Q2D\x00pBGID +\x00BDEV\xa0\rBXCNNXRCBDEV\xa1\tNBINBDEV\x14D\x07_Q38\x00pBGID +\x00`\xa01\x93` +\x0fBDIS\xa0\x17BXCNpBDEV`p +\x0fBDEVNXEJ`\xa1\x0fNBEJBDEVp`BDEV\xa12\xa0\x16HPBU\xa0\x10BXCNp`BDEVNXIN`\xa1\x19p`BDEV\xa0 +BXCNNXRC`\xa1\x06NBIN`\x14B\rNBRE\x01\xa0&\x93h +\r\xa0 \\LFDC\x86\\/\x05_SB_PCI0LPC_FDC_FDD0 +\x03\xa0F\x04\x95h +\x0c\xa0#\x93\\BIDE +\x03\x86\\/\x05_SB_PCI0SATASCNDMSTR +\x03\xa1\x1b\x86\\/\x05_SB_PCI0IDE0PRIMMSTR +\x03\xa0I\x04\x93h +\x10\xa0+\x91HPACHB0A\xa0 \\WNTF\x86\\/\x05_SB_PCI0LPC_EC__BAT1 +\x03\xa1\x16LED_ +\x04 +\xc0BEEP +\x0fp +\x02BSTS\xa0\x12\x93h +\x11\x86\\._SB_LCIO +\x03\x14K\x0eNBEJ\x01\xa0N\x0c\x93BSTS +\x00\xa0&\x93h +\r\xa0 \\LFDC\x86\\/\x05_SB_PCI0LPC_FDC_FDD0 +\x01\xa0F\x04\x95h +\x0c\xa0#\x93\\BIDE +\x03\x86\\/\x05_SB_PCI0SATASCNDMSTR +\x01\xa1\x1b\x86\\/\x05_SB_PCI0IDE0PRIMMSTR +\x01\xa0C\x04\x93h +\x10\xa0 \\WNTF\x86\\/\x05_SB_PCI0LPC_EC__BAT1 +\x01\xa1\x1b\x86\\/\x05_SB_PCI0LPC_EC__BAT1 +\x81\xa0\x12\x93h +\x11\x86\\._SB_LCIO +\x01LED_ +\x04 +\x00BEEP +\x00p +\x00BSTS\x14B\x15NBIN\x01\xa08\x93h +\r\xa02\\LFDCBEN_ +\x00BSFDLED_ +\x04 +\x80\x86\\/\x05_SB_PCI0LPC_FDC_FDD0 +\x01\xa0B\x06\x95h +\x0c\xa0\x0b\x93h +\x06BEN_ +\x02\xa1\x07BEN_ +\x01LED_ +\x04 +\x80\xa0#\x93\\BIDE +\x03\x86\\/\x05_SB_PCI0SATASCNDMSTR +\x01\xa1\x1b\x86\\/\x05_SB_PCI0IDE0PRIMMSTR +\x01\xa0I\x06\x93h +\x10LED_ +\x04 +\x80\xa0>\\WNTFp +\x01\\/\x06_SB_PCI0LPC_EC__BAT1XB1S\x86\\/\x05_SB_PCI0LPC_EC__BAT1 +\x01\xa1\x1b\x86\\/\x05_SB_PCI0LPC_EC__BAT1 +\x81\xa07\x93h +\x11\xa01\x92\\/\x04_SB_PCI0LPC_CSONLED_ +\x04 +\x80\xa0\x13\\WNTF\x86\\._SB_LCIO +\x01BEEP +\x00p +\x00BSTS\x14J\x07BEJ0\x01\xa0A\x06hBDISLED_ +\x04 +\x00\\BHDP +\x01 +\x00p +\x01BSTS\xa0*BHKEp +\x00BHKE\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x030\xa0\x16\x93BDEV +\x11p +\x0fBDEVp +\x00BSTS\xa1\x10LED_ +\x04 +\x80p +\x00BSTS\x14\x1dBEJ3\x01\xa0\rhBDISp +\x01BSTS\xa1\x08p +\x00BSTS\x14I\x07BPTS\x01p +\x01HDBM\xa0\x17\x92\x93BSTS +\x00p +\x0fBDEVp +\x00BSTSp +\x00BHKEp +\x01`\xa0\x1d\x92\x93BDEV +\x0f\xa0\x13\x90\x92\\LFDC\x93BDEV +\rp +\x00`\xa1\x05p +\x00`\xa0 +\x92\x95h +\x04p +\x00`\xa0\x08`BUWK +\x01\xa1\x0fLED_ +\x04 +\x00BUWK +\x00\x14D\x14BWAK\x01BUWK +\x00pBGID +\x00`\xa0\x10\x90\x92\\LFDC\x93` +\rBDIS\\/\x05_SB_PCI0LPC_FDC__INI\xa0K\x05\\LFDC\xa0C\x05\x92\x93` +\r\xa0K\x04\x93\\/\x05_SB_PCI0LPC_FDC_FD0S\\/\x05_SB_PCI0LPC_EC__HPNF\x86\\/\x05_SB_PCI0LPC_FDC_FDD0 +\x01\xa0J +\x93BSTS +\x00\xa0.\x92\x93`BDEV\xa0\x10BXCNp`BDEVNXRC`\xa1\x14NBEJBDEVp`BDEVNBIN`\xa1A\x07\xa0N\x06\x91\\LFDC\x92\x93BDEV +\r\xa0M\x05\x92\x93` +\x0fLED_ +\x04 +\x80\xa0M\x04HPBU}yh +\x08\x00\x0b\x05 BHKE\\/\x06_SB_PCI0LPC_EC__HKEYMHKQBHKE\xa0\x06\x92\x94h +\x02\xa1\x13\xa0 +BXCNNXRE`\xa1\x06NBRE`\x14N\x0fBDIS\x00\xa0F\x0f\x92\\/\x04_SB_PCI0LPC_CSON\xa0F\x06\x93\\BIDE +\x03p +\x00\\/\x04_SB_PCI0SATASIE0p +\x00\\/\x04_SB_PCI0SATASTI0p +\x00\\/\x04_SB_PCI0LPC_URST[! +\x0fp +\x01\\/\x04_SB_PCI0SATASSIG\xa1N\x05p +\x00\\/\x04_SB_PCI0IDE0PIE0p +\x00\\/\x04_SB_PCI0IDE0PTI0p +\x00\\/\x04_SB_PCI0LPC_URST[! +\x0fp +\x01\\/\x04_SB_PCI0IDE0PSIGp +\x01\\/\x04_SB_PCI0LPC_CSONBSFD\x14A\x0eBEN_\x01\xa0I\r\\/\x04_SB_PCI0LPC_CSONp +\x00\\/\x04_SB_PCI0LPC_URSTp +\x00\\/\x04_SB_PCI0LPC_CSON[" +\x0f\xa0C\th\xa05\x93\\BIDE +\x03p +\x00\\/\x04_SB_PCI0SATASSIGp +\x01\\/\x04_SB_PCI0SATASIDE\xa1-p +\x00\\/\x04_SB_PCI0IDE0PSIGp +\x01\\/\x04_SB_PCI0IDE0PIDE[! +-p +\x01\\/\x04_SB_PCI0LPC_URST\xa0 +\x93h +\x02["\x0b\xd0\x07\xa1\x06["\x0b\x90\x01\x14N\x05BSTA\x01\xa0\x17\\/\x04_SB_PCI0LPC_CSON\xa4 +\x00BINI\xa0\r\x93h +\x00\xa4\x93BDEV +\r\xa0\r\x93h +\x01\xa4\x95BDEV +\x0c\xa0\r\x93h +\x02\xa4\x93BDEV +\x0e\xa0\r\x93h +\x03\xa4\x93BDEV +\x11\xa4 +\x00\x14D\x06BUWK\x01\xa0?\\H8DR\xa0\x1chp +\x01\\/\x05_SB_PCI0LPC_EC__HWBU\xa1\x1bp +\x00\\/\x05_SB_PCI0LPC_EC__HWBU\xa1\x1c\xa0\rh\\MBEC +2 +\xff +\x80\xa1\x0c\\MBEC +2 +\x7f +\x00\x14\x1aBINI\x00\xa0\x13\x93BDEV +\xffpBGID +\x00BDEV\x14F\x0bBGID\x01\xa0\x06hp +\xff`\xa1E +\xa0\x0c\\H8DRpHBID`\xa1\x10zRBEC +G +\x02`{` +\x0f`{` +\x03`\xa0\t\x93` +\x00p +\x03`\xa1\x11\xa0\t\x93` +\x02p +\x06`\xa1\x05p +\x0f`\xa0)\x93` +\x0f\xa0\x10\\H8DR\xa0\tHB1Ap +\x10`\xa1\x12\xa0\x10{\\RBEC +9 +\x80\x00p +\x10`\xa09\x93` +\x0f\xa03\x92\\/\x04_SB_PCI0LPC_CSON\xa0\x1d\x92{\\/\x04_SB_PCI0LPC_GL00 +@\x00p +\x11`\xa4`\x14(BSFD\x00\xa0\x13BSTA +\x00\\MISA\x0b\xf3\x03 +\xf3 +\x00\xa1\r\\MISA\x0b\xf3\x03 +\xf3 +\x04\x14A\x0bNXRE\x01\xa0\x14\x93h +\x0fLED_ +\x04 +\x00p +\x00BSTS\xa0!\x93h +\r\xa0\x1b\\LFDCLED_ +\x04 +\xc0\x86\\._SB_SWAP +\x83\xa0\x1a\x95h +\x0cLED_ +\x04 +\xc0\x86\\._SB_SWAP +\x83\xa0\x1a\x93h +\x0eLED_ +\x04 +\xc0\x86\\._SB_SWAP +\x83\xa0<\x93h +\x10\xa0\x1f\x91HPACHB0ALED_ +\x04 +\xc0\x86\\._SB_SWAP +\x83\xa1\x16LED_ +\x04 +\xc0BEEP +\x0fp +\x02BSTS\x14E\x0cNXRC\x01\xa0+\x93h +\r\xa0%\\LFDCLED_ +\x04 +\x80BEN_ +\x00BSFD\x86\\._SB_SWAP +\x80\xa0.\x95h +\x0cLED_ +\x04 +\x80\xa0\x0b\x93h +\x06BEN_ +\x02\xa1\x07BEN_ +\x01\x86\\._SB_SWAP +\x80\xa0 \x93h +\x0eLED_ +\x04 +\x80BEN_ +\x00\x86\\._SB_SWAP +\x80\xa04\x93h +\x10\x86\\/\x05_SB_PCI0LPC_EC__BAT1 +\x81LED_ +\x04 +\x80\x86\\._SB_SWAP +\x80BEEP +\x00p +\x00BSTS\x14I\x04NXEJ\x01\xa0\x1f\x93h +\x10\x86\\/\x05_SB_PCI0LPC_EC__BAT1 +\x81\x86\\._SB_SWAP +\x82LED_ +\x04 +\x00BEEP +\x00p +\x00BSTS\x14\x13NXIN\x01\x86\\._SB_SWAP +\x81\x10C\x10\\/\x04_SB_PCI0LPC_FDC_\x08XFDS +\x00\x08DCFD +\x00\x14C\x05_INI\x00p +\x00XFDS\xa07\\H8DR}\\/\x05_SB_PCI0LPC_EC__HAMA +\x0c\\/\x05_SB_PCI0LPC_EC__HAMA\xa1\x0c\\MBEC +\x1a +\xff +\x0c\x08FDEB\x11\x17 +\x14\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x8cFDEB +\x00FD0S\x14C\x06_FDE\x00\xa0&\x91\\/\x05_SB_PCI0LPC_EC__BSTA +\x00DCFDp +\x01FD0S\xa1/\xa0$\x91\\/\x05_SB_PCI0LPC_EC__HPNFXFDSp +\x00FD0S\xa1\x08p +\x01FD0S\xa4FDEB\x10E\x06\\/\x05_SB_PCI0LPC_FDC_FDD0\x14K\x04_EJ0\x01\xa02\\/\x05_SB_PCI0LPC_EC__BSTA +\x00\\/\x05_SB_PCI0LPC_EC__BEJ0h\xa1\x10\xa0\x05DCFD\xa1\x08p +\x01XFDS\x10A\x12\\/\x04_SB_PCI0LPC_EC__\x14C\t_Q52\x00\xa02\\/\x05_SB_PCI0LPC_FDC_XFDSp +\x00\\/\x05_SB_PCI0LPC_FDC_XFDS\xa1H\x05\xa02\x91\\/\x05_SB_PCI0LPC_EC__BSTA +\x00\\/\x05_SB_PCI0LPC_FDC_DCFD\xa1"\xa0 \\LFDC\x86\\/\x05_SB_PCI0LPC_FDC_FDD0 +\x01\x14G\x07_Q53\x00p +\x00\\/\x05_SB_PCI0LPC_FDC_XFDS\xa02\x91\\/\x05_SB_PCI0LPC_EC__BSTA +\x00\\/\x05_SB_PCI0LPC_FDC_DCFD\xa1"\xa0 \\LFDC\x86\\/\x05_SB_PCI0LPC_FDC_FDD0 +\x01\x10F\x04\\/\x05_SB_PCI0LPC_EC__BAT1\x14,_EJ0\x01p +\x00B1STp +\x00XB1S\\/\x05_SB_PCI0LPC_EC__BEJ0h\x10@3\\_SB_[\x82G2SWAP\x08_HID\x0c$M\x00i\x14\x15_STA\x00\xa0\t\\WMEF\xa4 +\x0f\xa1\x04\xa4 +\x00\x14"XCNN\x01ph\\/\x05_SB_PCI0LPC_EC__BXCN\xa4 +\t\x14\tXSWP\x00\xa4 +\x01\x14\x1eXEJ0\x01\\/\x05_SB_PCI0LPC_EC__BEJ0h\x14\x1eXEJ3\x01\\/\x05_SB_PCI0LPC_EC__BEJ3h\x14@\x1fXDID\x00\x08XPCK\x12\x17\x06 +\x00 +\x00\x0c\xff\xff\xff\xff\x0c\xff\xff\xff\xff\x0c\xff\xff\xff\xff +\x00p\\/\x05_SB_PCI0LPC_EC__BDEV`p`\x88XPCK +\x00\x00\xa0D\r\x95` +\x0c\xa0J\x06\x93\\BIDE +\x03p\\/\x04_SB_PCI0SATA_ADR\x88XPCK +\x02\x00p\\/\x05_SB_PCI0SATASCND_ADR\x88XPCK +\x03\x00p\\/\x06_SB_PCI0SATASCNDMSTR_ADR\x88XPCK +\x04\x00\xa1B\x06p\\/\x04_SB_PCI0IDE0_ADR\x88XPCK +\x02\x00p\\/\x05_SB_PCI0IDE0PRIM_ADR\x88XPCK +\x03\x00p\\/\x06_SB_PCI0IDE0PRIMMSTR_ADR\x88XPCK +\x04\x00\xa0O\x05\x93` +\r\xa0K\x04\\LFDCp\\/\x05_SB_PCI0LPC_FDC__HID\x88XPCK +\x02\x00p\\/\x06_SB_PCI0LPC_FDC_FDD0_ADR\x88XPCK +\x04\x00\xa1\x0cp +\x0f\x88XPCK +\x00\x00\xa0N\x04\x93` +\x10p\\/\x06_SB_PCI0LPC_EC__BAT1_HID\x88XPCK +\x02\x00p\\/\x06_SB_PCI0LPC_EC__BAT1_UID\x88XPCK +\x04\x00p\x7f\\/\x04_SB_PCI0LPC_CSON +\x01\x00\x88XPCK +\x05\x00\xa4XPCK\x14H\x05XSTM\x01\x08XDMY\x11\x03 +\x14\xa0\'\x93\\BIDE +\x03\\/\x05_SB_PCI0SATASCND_STMXDMYh +\x00\xa1\x1f\\/\x05_SB_PCI0IDE0PRIM_STMXDMYh +\x00\x14K\x04XGTF\x00\xa0%\x93\\BIDE +\x03\xa4\\/\x06_SB_PCI0SATASCNDMSTR_GTF\xa1\x1d\xa4\\/\x06_SB_PCI0IDE0PRIMMSTR_GTF\x10L\xe9\\_SB_[\x82C\xe9GDCK\x08_HID\x0c$M\x00y\x08_CID\x0cA\xd0\x0c\x15\x08DOID\x0c\xff\xff\xff\xff\x08DIDB\x0c\xff\xff\xff\xff\x08FLAG +\x00\x08WUCT +\x00\x08DHKE +\x00[\x02DEVT\x14?DSTA\x00UDCKUDKT\xa0\x1a\x91\x93GDID\x0c$M\x00L\x93GDID\x0c$M\x00Dp +\x0f`\xa1\x13\xa0\x0b\x92\\W98Fp +\x00`\xa1\x05p +\x0c`\xa4`\x14G\x07DPTS\x01\xa0O\x06\x90\x92\x95h +\x01\x92\x94h +\x04p +\x00DHKE\xa0\x18DFLG +\x02 +\x02p +\x00DOIDDFLG +\x01 +\x02\xa0/\x91\x93GDID\x0c$M\x00L\x93GDID\x0c$M\x00D\\/\x05_SB_PCI0LPC_EC__DDWK +\x01pGDIDDIDBDFLG +\x00\x0b\x00\x01\x08DDTM +\x00\x14J\x18DWAK\x01p\x0c\xff\xff\xff\xffDOID\xa0H\x17\x90\x92\x95h +\x01\x92\x94h +\x04p +\x00DDTM\xa0\x1d\x91\x93DIDB\x0c$M\x00L\x93DIDB\x0c$M\x00Dp +\x01DDTM\xa0B\rDDTMp +\x00DDTM\xa0\x12\x93GDID\x0c$M\x00Lp +\x01DDTM\xa0\x12\x93GDID\x0c$M\x00Dp +\x01DDTM\xa0;DDTM\xa0"\x93h +\x04\xa0\x1c{\\/\x04_SB_PCI0LPC_WAKR +\x08\x00DGPEyh +\x08DHKE\xa0 +\x92DFLG +\x02 +\x08\xa1B\x06p +\x01\\/\x04_SB_PCI0LPC_BUSD\\/\x05_SB_PCI0LPC_EC__DATT +\x00 +\x01\\/\x05_SB_PCI0LPC_EC__DATT +\x01 +\x00\x86\\._SB_GDCK +\x00\\DHDP +\x00\xa1;p +\x00DDTM\xa0\x12\x93GDID\x0c$M\x00Lp +\x01DDTM\xa0\x12\x93GDID\x0c$M\x00Dp +\x01DDTM\xa0\tDDTMWDCK\xa1\x02\xa3DFLG +\x01\x0b\x00\x01DFLG +\x01 +\x02DFLG +\x01 +\x10DFLG +\x01 + p +\x01\\/\x04_SB_PCI0LPC_DSCI\x14\x0eDGPE\x00DFLG +\x00 +\x08\x14N\x12DDCK\x01\xa0J\x08h\\/\x05_SB_PCI0LPC_EC__LED_ +\x08 +\x00\\/\x05_SB_PCI0LPC_EC__LED_ +\t +\x80\\/\x04_SB_PCI0LPC_LCON +\x01BCON +\x01\\/\x05_SB_PCI0LPC_EC__DATT +\x00 +\x00\\/\x05_SB_PCI0LPC_EC__DATT +\x01 +\x01\xa1H\t\\/\x05_SB_PCI0LPC_EC__LED_ +\x08 +\x80\\/\x05_SB_PCI0LPC_EC__LED_ +\t +\xc0DFLG +\x00 +\x02\\DHDP +\x00BCON +\x00\\/\x04_SB_PCI0LPC_LCON +\x00\\/\x05_SB_PCI0LPC_EC__DATT +\x00 +\x01\\/\x05_SB_PCI0LPC_EC__DATT +\x01 +\x00\xa4 +\x01\x14C\x05DEJ0\x01\xa0\rhp +\x00DOIDUDKIDFLG +\x01 +\x02\\/\x05_SB_PCI0LPC_EC__LED_ +\x08 +\x00\\/\x05_SB_PCI0LPC_EC__LED_ +\t +\x00\x14\x1fDEJ3\x01\xa0\x18hDFLG +\x00 +\x10\xa0\r\x93\\SPS_ +\x03PDE3\x14\x11DEJ4\x01\xa0 +hDFLG +\x00 + \x14\x07PDE3\x00\xa3\x08HIDE +\x00\x14@\x08WDCK\x00\xa0/\x91DFLG +\x02 +\x10DFLG +\x02 + DDCK +\x01\xa0\x16\\W98FDFLG +\x00\x0b\x00\x02p +\x05HIDE\xa1H\x04\xa06\x93\\/\x05_SB_PCI0LPC_EC__BGID +\x00 +\x11\\/\x05_SB_PCI0LPC_EC__NBRE +\x11\xa1\x0e\x86\\._SB_GDCK +\x00\x14O\x07UDCK\x00\xa0G\x07DFLG +\x02 +\x08\xa0L\x06\x92DFLG +\x02\x0b\x00\x01}DHKE\x0b\x04 DHKE\xa0(\x93\\UOPT +\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQDHKE\xa0\x13\\W98F\x86\\._SB_GDCK +\x01\xa1\x0e\x86\\._SB_GDCK +\x03DFLG +\x01 +\x08\x14\x1dUDKI\x00\xa0\r\\WNTFp +\x01WUCT\xa1\x08p +\x05WUCT\x14C\x05UDKT\x00\xa0K\x04{DHKE\x0b\x04 \x00\xa0?\x93GDID +\x00\xa06\x92vWUCTp +\x00DHKE\xa0\'\x93\\UOPT +\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x03@\x145GDID\x00\xa0)\x93DOID\x0c\xff\xff\xff\xffp\x0c\xff\xff\xff\xff\\/\x03_SB_GDCKG_IDpRDIDDOID\xa4DOID\x14O\tRDID\x00p +\x00`\xa0A\t\\/\x04_SB_PCI0LPC_EPWG\xa0@\x06\x93\\/\x03_SB_GDCKGGID +\x00\xa0B\x04\\H8DR\xa01\\/\x05_SB_PCI0LPC_EC__EEPRp\\/\x05_SB_PCI0LPC_EC__HDEP`\xa1\x08p\x0c$M\x00L`\xa1\x08p\\DCKI`\xa0\x1a\x93\\/\x03_SB_GDCKGGID +\x01p\x0c$M\x00D`\xa4`\x14G\x08RDSR\x00p +\x00`\xa0I\x07\x92\x93GDID +\x00\xa0F\x05\x93\\/\x03_SB_GDCKGGID +\x00\xa08\\H8DR\xa01\\/\x05_SB_PCI0LPC_EC__EEPRp\\/\x05_SB_PCI0LPC_EC__HDEN`\xa1\x08p\\DCKS`\xa0\x17\x93\\/\x03_SB_GDCKGGID +\x01p +\x00`\xa4`\x14E\x17BCON\x01p\\/\x05_SB_PCI0LPC_EC__DATT +\x00 +\x02`\\/\x05_SB_PCI0LPC_EC__DATT +\x00 +\x01}\\/\x04_SB_PCI0LPC_SERQ +@\\/\x04_SB_PCI0LPC_SERQ{\\/\x04_SB_PCI0LPC_SERQ +\x7f\\/\x04_SB_PCI0LPC_SERQp\\/\x04_SB_PCI0LPC_CLKRa\xa0.hp +\x00\\/\x04_SB_PCI0LPC_CLKRp +\x01\\/\x04_SB_PCI0LPC_BUSC\xa1\x17p +\x01\\/\x04_SB_PCI0LPC_BUSDpa\\/\x04_SB_PCI0LPC_CLKR}\\/\x04_SB_PCI0LPC_SERQ +\xc0\\/\x04_SB_PCI0LPC_SERQ{\\/\x04_SB_PCI0LPC_SERQ +\xbf\\/\x04_SB_PCI0LPC_SERQ\xa0 \x93` +\x00\\/\x05_SB_PCI0LPC_EC__DATT +\x00 +\x00\x149DFLG\x02\xa0\x0f\x93h +\x00}FLAGiFLAG\xa0\x11\x93h +\x01{FLAG\x80i\x00FLAG\xa0\x0b{FLAGi\x00\xa4 +\x01\xa1\x04\xa4 +\x00\x10L\x1b\\/\x04_SB_PCI0LPC_EC__\x14A\x11_Q37\x00\xa0I\x10\\/\x04_SB_PCI0LPC_EPWGp\x0b\xd0\x07`[" +dp\x0c\xff\xff\xff\xff\\/\x03_SB_GDCKG_ID\xa20\x90\x93\\/\x03_SB_GDCKGGID +\x07`[" +\x01p\x0c\xff\xff\xff\xff\\/\x03_SB_GDCKG_IDv`p\x0c\xff\xff\xff\xff\\/\x03_SB_GDCKDOID\xa0O\x08\x91\x93\\/\x03_SB_GDCKGDID\x0c$M\x00L\x93\\/\x03_SB_GDCKGDID\x0c$M\x00D\xa06\x93\\/\x05_SB_PCI0LPC_EC__BGID +\x00 +\x11\\/\x05_SB_PCI0LPC_EC__NBRE +\x11\xa1*\xa0(HPACp +\x00\\/\x04_SB_PCI0LPC_DRST\x86\\._SB_GDCK +\x00\x14D\tEEPR\x00p +\x00`\xa0F\x08\\H8DRp +\x00HDEOp + +HDEC\xa2\x0e\x92{HDEC +\xc0\x00[" +\x01\xa0A\x06\x92{HDEC +@\x00p +\x00apHDENbp +\x04c\xa2\x11cra{b +\xff\x00azb +\x08bvcpHDEPbp +\x04c\xa2\x11cra{b +\xff\x00azb +\x08bvcraHDEMaraHDESa\xa0\x0b\x92{a +\xff\x00p +\x01`\xa4`\x14D\x04_STA\x00pGGID`\xa0\x0b\x92\\W98Fp +\x00a\xa1\x05p +\x0ca\xa0\x1b\x91\x93` +\x00\x93` +\x01p\\/\x03_SB_GDCKDSTAa\xa0\x06\x93` +\x02\xa3\xa4a\x14H\x0c_INI\x00\\/\x05_SB_PCI0LPC_EC__DATT +\x02 +\x01\xa0>\x93GGID +\x07\\/\x05_SB_PCI0LPC_EC__DATT +\x01 +\x00\\/\x05_SB_PCI0LPC_EC__DATT +\x00 +\x01\xa17\\/\x05_SB_PCI0LPC_EC__DATT +\x01 +\x01\\/\x05_SB_PCI0LPC_EC__DATT +\x00 +\x00\\/\x05_SB_PCI0LPC_EC__DDWK +\x00p +\x01\\/\x04_SB_PCI0LPC_DSCI\x14K\x04_DCK\x01p +\x00`\xa0"\x91\x93GGID +\x00\x93GGID +\x01p\\/\x03_SB_GDCKDDCKh`\xa0\x1a\\VIGD\\/\x04_SB_PCI0VID_VDSWh\xa4`\x08UDOP +\x00\x148_EJ0\x01\xa0\x18\x93GGID +\x00\\/\x03_SB_GDCKDEJ0h\xa0\x18\x93GGID +\x01\\/\x03_SB_GDCKDEJ0h\x148XEJ3\x01\xa0\x18\x93GGID +\x00\\/\x03_SB_GDCKDEJ3h\xa0\x18\x93GGID +\x01\\/\x03_SB_GDCKDEJ3h\x148_EJ4\x01\xa0\x18\x93GGID +\x00\\/\x03_SB_GDCKDEJ4h\xa0\x18\x93GGID +\x01\\/\x03_SB_GDCKDEJ4h\x146PEJ3\x00\xa0\x17\x93GGID +\x00\\/\x03_SB_GDCKPDE3\xa0\x17\x93GGID +\x01\\/\x03_SB_GDCKPDE3\x14A\x04_BDN\x00p +\x00`\xa0\x19\x93GGID +\x00p\\/\x03_SB_GDCKRDID`\xa0\x19\x93GGID +\x01p\\/\x03_SB_GDCKRDID`\xa4`\x14A\x04_UID\x00p +\x00`\xa0\x19\x93GGID +\x00p\\/\x03_SB_GDCKRDSR`\xa0\x19\x93GGID +\x01p\\/\x03_SB_GDCKRDSR`\xa4`\x14.GPTS\x01\\/\x03_SB_GDCKDPTSh\\/\x05_SB_PCI0LPC_EC__RPTSh\x14H\x04GWAK\x01\\/\x03_SB_GDCKDWAKh\\/\x05_SB_PCI0LPC_EC__RWAKh\\/\x05_SB_PCI0LPC_EC__DDWK +\x00\x146GGPE\x00\xa0\x17\x93GGID +\x00\\/\x03_SB_GDCKDGPE\xa0\x17\x93GGID +\x01\\/\x03_SB_GDCKDGPE\x08G_ID\x0c\xff\xff\xff\xff\x14N\x06GGID\x00pG_ID`\xa0N\x05\x93`\x0c\xff\xff\xff\xffp\\/\x04_SB_PCI0LPC_DKI0`p\\/\x04_SB_PCI0LPC_DKI1ap\\/\x04_SB_PCI0LPC_DKI2b}`ya +\x01\x00`}`yb +\x02\x00`p`G_ID\xa4`\x10F*\\/\x04_SB_PCI0LPC_EC__\x14M\x07_Q50\x00p\\/\x03_SB_GDCKGGID`\xa0D\x06\x91\x93` +\x00\x93` +\x01\\/\x05_SB_PCI0LPC_EC__LED_ +\x08 +\x80\\/\x05_SB_PCI0LPC_EC__LED_ +\t +\xc0\xa0\x13\\W98F\x86\\._SB_GDCK +\x01\xa1\x0e\x86\\._SB_GDCK +\x03\x14F\x19DATT\x02p +\x00`\xa0B\x08\x93h +\x00\xa0(\x93i +\x01\xa0\x11\\H8DR}HAM6 +\x80HAM6\xa1\x0c\\MBEC +\x16 +\xff +\x80p +\x01`\xa0$\x93i +\x00\xa0\x11\\H8DR{HAM6 +\x7fHAM6\xa1\x0c\\MBEC +\x16 +\x7f +\x00\xa0-\x93i +\x02\xa0\x14\\H8DR\xa0\r{HAM6 +\x80\x00p +\x01`\xa1\x12\xa0\x10{\\RBEC +\x16 +\x80\x00p +\x01`\xa0B\x08\x93h +\x01\xa0(\x93i +\x01\xa0\x11\\H8DR}HAMA +\x01HAMA\xa1\x0c\\MBEC +\x1a +\xff +\x01p +\x01`\xa0$\x93i +\x00\xa0\x11\\H8DR{HAMA +\xfeHAMA\xa1\x0c\\MBEC +\x1a +\xfe +\x00\xa0-\x93i +\x02\xa0\x14\\H8DR\xa0\r{HAMA +\x01\x00p +\x01`\xa1\x12\xa0\x10{\\RBEC +\x1a +\x01\x00p +\x01`\xa0B\x08\x93h +\x02\xa0(\x93i +\x01\xa0\x11\\H8DR}HAMB +\x01HAMB\xa1\x0c\\MBEC +\x1b +\xff +\x01p +\x01`\xa0$\x93i +\x00\xa0\x11\\H8DR{HAMB +\xfeHAMB\xa1\x0c\\MBEC +\x1a +\xfe +\x00\xa0-\x93i +\x02\xa0\x14\\H8DR\xa0\r{HAMB +\x01\x00p +\x01`\xa1\x12\xa0\x10{\\RBEC +\x1b +\x01\x00p +\x01`\xa4`\x14K\x07DDWK\x01p +\x00`\xa0#\x93h +\x01\xa0\x0c\\H8DRp\x01HWDK\xa1\x0c\\MBEC +2 +\xff +\x08p +\x01`\xa0\x1f\x93h +\x00\xa0\x0c\\H8DRp\x00HWDK\xa1\x0c\\MBEC +2 +\xf7 +\x00\xa0)\x93h +\x02\xa0\x10\\H8DR\xa0\tHWDKp +\x01`\xa1\x12\xa0\x10{\\RBEC +2 +\x08\x00p +\x01`\xa4`\x10#\\/\x04_SB_PCI0LPC_EC__\x14\x07RPTS\x01\xa3\x14\x06RWAK\x01\x10B\x10\\/\x04_SB_PCI0LPC_EC__\x14N\x04_Q1C\x00\xa0?\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0c\x00\x00 \x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x16\x10\\UCMS +\x00\x14N\x04_Q1D\x00\xa0?\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0c\x00\x00\x10\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x15\x10\\UCMS +\x01\x14N\x04_Q1E\x00\xa0?\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0c\x00\x00@\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x17\x10\\UCMS +\x02\x10L\x13\\/\x04_SB_PCI0LPC_EC__\x08BRTF +\x01\x14N\x08_Q14\x00\xa0=\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0b\x00\x80\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x10\x10\xa0?\\NBCF\xa0\x1c\\VIGD\x86\\/\x04_SB_PCI0VID_LCD0 +\x86\xa1\x1b\x86\\/\x05_SB_PCI0AGP_VID_LCD0 +\x86\xa1\x08\\UCMS +\x04\x14@\t_Q15\x00\xa0?\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0c\x00\x00\x01\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x11\x10\xa0?\\NBCF\xa0\x1c\\VIGD\x86\\/\x04_SB_PCI0VID_LCD0 +\x87\xa1\x1b\x86\\/\x05_SB_PCI0AGP_VID_LCD0 +\x87\xa1\x08\\UCMS +\x05\x10D\x06\\/\x04_SB_PCI0LPC_EC__\x14N\x04_Q19\x00\xa0?\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0c\x00\x00\x80\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x18\x10\\UCMS +\x03\x10D\x06\\/\x04_SB_PCI0LPC_EC__\x14N\x04_Q63\x00\xa0?\\/\x06_SB_PCI0LPC_EC__HKEYMHKK\x0c\x00\x00\x08\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x14\x10\\UCMS +\x0b\x10C\t\\/\x04_SB_PCI0LPC_EC__\x14 +_Q70\x00FNST\x14 +_Q72\x00FNST\x14 +_Q73\x00FNST\x14L\x05FNST\x00\xa0\x12\\H8DRpHFNS`pHFNEa\xa1\x17{\\RBEC +\x0e +\x03`{\\RBEC +\x00 +\x08a\xa0)a\xa0\x0c\x93` +\x00\\UCMS +\x11\xa0\x0c\x93` +\x01\\UCMS +\x0f\xa0\x0c\x93` +\x02\\UCMS +\x10\x10I<\\/\x05_SB_PCI0LPC_EC__HKEY\x08WGFL +\x00\x14\x1eWLSW\x00\xa4\\/\x05_SB_PCI0LPC_EC__GSTS\x14B\x04GWAN\x00p +\x00`\xa0\x0e{WGFL +\x01\x00}` +\x01`\xa0\x0b{WGFL +\x08\x00\xa4`\xa0 +WPWS}` +\x02`\xa0\x0e{WGFL +\x04\x00}` +\x04`\xa4`\x14K\x04SWAN\x01\xa0\x0c{h +\x02\x00WPWC +\x01\xa1\x07WPWC +\x00\xa0\x18{h +\x04\x00}WGFL +\x04WGFL\\WGSV +\x02\xa1\x15{WGFL\x80 +\x04\x00WGFL\\WGSV +\x03\x14B\x04GBDC\x00p +\x00`\xa0\x0e{WGFL +\x10\x00}` +\x01`\xa0\x0b{WGFL +\x80\x00\xa4`\xa0 +BPWS}` +\x02`\xa0\x0e{WGFL +@\x00}` +\x04`\xa4`\x14K\x04SBDC\x01\xa0\x0c{h +\x02\x00BPWC +\x01\xa1\x07BPWC +\x00\xa0\x18{h +\x04\x00}WGFL +@WGFL\\BLTH +\x02\xa1\x15{WGFL\x80 +@\x00WGFL\\BLTH +\x03\x14;WPWS\x00\xa0\x1f\\H8DRp\\/\x05_SB_PCI0LPC_EC__DCWW`\xa1\x12pz{\\RBEC +: +@\x00 +\x06\x00`\xa4`\x14\x19WTGL\x00\xa0\x12{WGFL +\x01\x00WPWC\x92WPWS\x14B\tWPWC\x01\xa0N\x04\x90h\x90{WGFL +\x01\x00\x92{WGFL +\x08\x00\xa0\x1f\\H8DRp\x01\\/\x05_SB_PCI0LPC_EC__DCWW\xa1\x0c\\MBEC +: +\xff +@}WGFL +\x02WGFL\xa1;\xa0\x1f\\H8DRp\x00\\/\x05_SB_PCI0LPC_EC__DCWW\xa1\x0c\\MBEC +: +\xbf +\x00{WGFL\x80 +\x02\x00WGFL\x14;BPWS\x00\xa0\x1f\\H8DRp\\/\x05_SB_PCI0LPC_EC__DCBD`\xa1\x12pz{\\RBEC +: +\x10\x00 +\x04\x00`\xa4`\x14\x19BTGL\x00\xa0\x12{WGFL +\x10\x00BPWC\x92BPWS\x14B\tBPWC\x01\xa0N\x04\x90h\x90{WGFL +\x10\x00\x92{WGFL +\x80\x00\xa0\x1f\\H8DRp\x01\\/\x05_SB_PCI0LPC_EC__DCBD\xa1\x0c\\MBEC +: +\xff +\x10}WGFL + WGFL\xa1;\xa0\x1f\\H8DRp\x00\\/\x05_SB_PCI0LPC_EC__DCBD\xa1\x0c\\MBEC +: +\xef +\x00{WGFL\x80 + \x00WGFL\x14;WGIN\x00p +\x00WGFLp\\WGSV +\x01WGFL\xa0\x10WPWS}WGFL +\x02WGFL\xa0\x10BPWS}WGFL + WGFL\x146WGPS\x01\xa0\r\x92\x95h +\x04\\BLTH +\x05\xa0\x10\x92{WGFL +\x04\x00WPWC +\x00\xa0\x10\x92{WGFL +@\x00BPWC +\x00\x14&WGWK\x01\xa0\x0f{WGFL + \x00BPWC +\x01\xa0\x0f{WGFL +\x02\x00WPWC +\x01\x109\\/\x04_SB_PCI0LPC_EC__\x14$_Q41\x00\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b\x00p\x10N\x0b\\_SB_[\x82E\x0bLCIO\x08_HID\x0c0\xae\x00\x01\x08_CID\x0cA\xd0 +\x06\x14)_STA\x00\xa0\x1d\\/\x05_SB_PCI0LPC_EC__BSTA +\x03\xa4 +\x0f\xa1\x04\xa4 +\x00\x14@\x07_EJ0\x01\\/\x05_SB_PCI0LPC_EC__BEJ0h\xa0@\x05\x91\x93\\/\x03_SB_GDCKGDID\x0c$M\x00L\x93\\/\x03_SB_GDCKGDID\x0c$M\x00Dp +\x00\\/\x04_SB_PCI0LPC_DRST\x86\\._SB_GDCK +\x00\x10#\\/\x04_SB_PCI0EXP3EXPD\x08_EJD\r_SB.GDCK\x00\x10\'\\/\x05_SB_PCI0USB2URTHUPDK\x08_EJD\r_SB.GDCK\x00\x10\'\\/\x05_SB_PCI0USB7URTHUPDK\x08_EJD\r_SB.GDCK\x00\x101\\/\x05_SB_PCI0USB1URTHUPEX\x08_EJD\r_SB.PCI0.EXP2.EXUP\x00\x101\\/\x05_SB_PCI0USB7URTHUPEX\x08_EJD\r_SB.PCI0.EXP2.EXUP\x00\x102\\/\x04_SB_PCI0EXP2EXUP\x08_EJD\r_SB.PCI0.USB7.URTH.UPEX\x00\x08\\_S0_\x12 +\x04 +\x00 +\x00 +\x00 +\x00\x08\\_S3_\x12 +\x04 +\x05 +\x05 +\x00 +\x00\x08\\_S4_\x12 +\x04 +\x06 +\x06 +\x00 +\x00\x08\\_S5_\x12 +\x04 +\x07 +\x07 +\x00 +\x00\x14O\x1d\\_PTS\x01p +\x01`\xa0\x0c\x93h\\SPS_p +\x00`\xa0\x0f\x91\x93h +\x00\x92\x95h +\x06p +\x00`\xa0E\x1b`ph\\SPS_\\/\x06_SB_PCI0LPC_EC__HKEYMHKE +\x00\xa0\x1f\\/\x05_SB_PCI0LPC_EC__KBLT\\UCMS +\r\xa0G\x05\x93h +\x01p\\/\x05_SB_PCI0LPC_EC__HFNI\\FNIDp +\x00\\/\x05_SB_PCI0LPC_EC__HFNIp +\x00\\/\x05_SB_PCI0LPC_EC__HFSP\xa02\x93h +\x03\\VVPD +\x03\\TRAPp\\/\x06_SB_PCI0LPC_EC__AC___PSR\\ACST\xa0)\x93h +\x04\\/\x03_SB_SLPB_PSW +\x00\xa0\r\\SPEN\\STEP +\x07\\TRAP\xa0 +\x93h +\x05\\TRAP\\/\x05_SB_PCI0LPC_EC__BPTSh\xa0 \x92\x95h +\x04p +\x00\\/\x05_SB_PCI0LPC_EC__HWLB\xa1\x1bp +\x01\\/\x05_SB_PCI0LPC_EC__HWLB\xa0<\x92\x93h +\x05p +\x01\\/\x05_SB_PCI0LPC_EC__HCMU\\/\x03_SB_GDCKGPTSh\xa0\x0b\\W98F\\CBRI\\/\x06_SB_PCI0LPC_EC__HKEYWGPSh\x08WAKI\x12\x06\x02 +\x00 +\x00\x14AJ\\_WAK\x01\xa0\x10\x91\x93h +\x00\x92\x95h +\x05\xa4WAKIp +\x00\\SPS_p +\x00\\/\x05_SB_PCI0LPC_EC__HCMUp +\x80\\/\x05_SB_PCI0LPC_EC__HFSP\\/\x05_SB_PCI0LPC_EC__EVNT +\x01\\/\x06_SB_PCI0LPC_EC__HKEYMHKE +\x01\\/\x05_SB_PCI0LPC_EC__FNST\\UCMS +\rp +\x00\\LIDB\xa0"\x93h +\x01p\\/\x05_SB_PCI0LPC_EC__HFNI\\FNID\xa0A\x13\x93h +\x03THRM +\x00\xa0E\x04\\WXPFp +\x00\\/\x04_SB_PCI0LPC_C4C3\xa0\'\\OSC4\x86\\._PR_CPU0 +\x81\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x81\xa1D\x07\xa0A\x07\\WNTF\xa02\\/\x06_SB_PCI0LPC_EC__AC___PSRp +\x00\\/\x04_SB_PCI0LPC_C4C3\xa16\xa0\x1c\\CWASp +\x00\\/\x04_SB_PCI0LPC_C4C3\xa1\x17p +\x01\\/\x04_SB_PCI0LPC_C4C3\xa0:\x92\x93\\ACST\\/\x06_SB_PCI0LPC_EC__AC___PSR\\/\x05_SB_PCI0LPC_EC__ATMC\xa0.\x90{\\CFGD\x0c\x00\x00\x00\x01\x00\x90\\WXPF\x92\x94\\WSPV +\x01\xa0\x10{\\CFGD +\xf0\x00PPMS +\x00\xa0@\x13\x93h +\x04\xa0\x0bDTSETHRM +\x02\xa0\x13\\W98F\x86\\._SB_SLPB +\x02\xa0\x1f\\WMEF\\/\x05_SB_PCI0LPC_EC__BEEP +\x05\xa0!\x92\\W98Fp +\x00\\/\x05_SB_PCI0LPC_EC__HSPA\xa0.\\WXPF\xa0\'\\OSC4\x86\\._PR_CPU0 +\x81\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x81\xa1D\x04\xa0A\x04\\WNTF\xa09\x91\x92\\/\x06_SB_PCI0LPC_EC__AC___PSR\\CWASp +\x00\\/\x04_SB_PCI0LPC_C4C3\xa0\r\\SPEN\\STEP +\x08\\/\x05_SB_PCI0LPC_EC__ATMC\xa0.\x90{\\CFGD\x0c\x00\x00\x00\x01\x00\x90\\WXPF\x92\x94\\WSPV +\x01\xa0\x10{\\CFGD +\xf0\x00PPMS +\x00\xa0O\x07\x7f\\/\x04_SB_PCI0EXP2PDS_\\/\x04_SB_PCI0EXP2XCPF\x00\xa0*\\/\x04_SB_PCI0EXP2PDS_p +\x01\\/\x04_SB_PCI0EXP2XCPF\xa1\x17p +\x00\\/\x04_SB_PCI0EXP2XCPF\x86\\/\x03_SB_PCI0EXP2 +\x00\\/\x03_SB_GDCKGWAKh\\/\x05_SB_PCI0LPC_EC__BWAKh\\/\x06_SB_PCI0LPC_EC__HKEYWGWKh\x86\\._TZ_THM0 +\x80\x86\\._TZ_THM1 +\x80\\VSLD\\/\x03_SB_LID__LID\xa01\x90\\W98F\x92\\WMEF\x86\\/\x03_SB_PCI0USB0 +\x00\x86\\/\x03_SB_PCI0USB1 +\x00\xa09\x95h +\x04\xa03{\\RRBF +\x02\x00yh +\x08`p}\x0b\x13 `\x00`\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ`p\x00\\RRBF\xa4WAKI\x10@\x1e\\_SI_\x14H\x1d_SST\x01\xa0;\x93h +\x00\\/\x05_SB_PCI0LPC_EC__LED_ +\x00 +\x00\\/\x05_SB_PCI0LPC_EC__LED_ +\x07 +\x00\xa0B\x06\x93h +\x01\xa0%\x91\\SPS_\\WNTF\\/\x05_SB_PCI0LPC_EC__BEEP +\x05\\/\x05_SB_PCI0LPC_EC__LED_ +\x00 +\x80\\/\x05_SB_PCI0LPC_EC__LED_ +\x07 +\x00\xa0;\x93h +\x02\\/\x05_SB_PCI0LPC_EC__LED_ +\x00 +\x80\\/\x05_SB_PCI0LPC_EC__LED_ +\x07 +\xc0\xa0K\x0b\x93h +\x03\xa0"\x94\\SPS_ +\x03\\/\x05_SB_PCI0LPC_EC__BEEP +\x07\xa1O\x04\xa01\x93\\SPS_ +\x03\\/\x05_SB_PCI0LPC_EC__BEEP +\x03\\/\x03_SB_GDCKPEJ3\xa1\x1a\\/\x05_SB_PCI0LPC_EC__BEEP +\x04\xa0\t\x93\\SPS_ +\x03\xa1\x1c\\/\x05_SB_PCI0LPC_EC__LED_ +\x00 +\x80\\/\x05_SB_PCI0LPC_EC__LED_ +\x07 +\xc0\xa09\x93h +\x04\\/\x05_SB_PCI0LPC_EC__BEEP +\x03\\/\x05_SB_PCI0LPC_EC__LED_ +\x07 +\xc0\x10C<\\_GPE[\x01MGPE\x07\x14N +_L18\x00p\\/\x05_SB_PCI0LPC_EC__HWAK`p`\\RRBF[" + +\xa0\x06{` +\x02\x00\xa0){` +\x04\x00\xa0\x13\\W98F\x86\\._SB_SLPB +\x02\xa1\x0e\x86\\._SB_LID_ +\x02\xa0"{` +\x08\x00\\/\x03_SB_GDCKGGPE\x86\\._SB_SLPB +\x02\xa0\x13{` +\x10\x00\x86\\._SB_SLPB +\x02\xa0\x06{` +@\x00\xa0\x13{` +\x80\x00\x86\\._SB_SLPB +\x02\x14K\x0f_L09\x00\xa0<\\/\x04_SB_PCI0EXP0PSP0p +\x01\\/\x04_SB_PCI0EXP0PSP0\x86\\/\x03_SB_PCI0EXP0 +\x02\xa0<\\/\x04_SB_PCI0EXP1PSP1p +\x01\\/\x04_SB_PCI0EXP1PSP1\x86\\/\x03_SB_PCI0EXP1 +\x02\xa0<\\/\x04_SB_PCI0EXP2PSP2p +\x01\\/\x04_SB_PCI0EXP2PSP2\x86\\/\x03_SB_PCI0EXP2 +\x02\xa0<\\/\x04_SB_PCI0EXP3PSP3p +\x01\\/\x04_SB_PCI0EXP3PSP3\x86\\/\x03_SB_PCI0EXP3 +\x02\x14D\x17_L01\x00\xa0@\x0f\\/\x04_SB_PCI0EXP2HPCSp +\x01\\/\x04_SB_PCI0EXP2HPCS\xa0*\\/\x04_SB_PCI0EXP2ABP_p +\x01\\/\x04_SB_PCI0EXP2ABP_\xa0I\t\\/\x04_SB_PCI0EXP2PDC_p +\x01\\/\x04_SB_PCI0EXP2PDC_p +\x00\\/\x04_SB_PCI0EXP2XCPF\x86\\/\x03_SB_PCI0EXP2 +\x00\xa0E\x04\\/\x04_SB_PCI0EXP2PDS_p +\x01\\/\x04_SB_PCI0EXP2XCPF[" +d\x86\\/\x04_SB_PCI0EXP2EXUP +\x01[#MGPE\xff\xff\xa0M\x06\\/\x04_SB_PCI0EXP0HPCSp +\x01\\/\x04_SB_PCI0EXP0HPCS\xa0A\x04\\/\x04_SB_PCI0EXP0PDC_[" +\xc8p +\x01\\/\x04_SB_PCI0EXP0PDC_\x86\\/\x03_SB_PCI0EXP0 +\x00[\'MGPE\x14D\t_L02\x00p +\x00\\/\x04_SB_PCI0LPC_SWGE\xa0A\x04\\/\x06_SB_PCI0LPC_EC__HKEYDHKC\xa0#DT02\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b"`\x86\\._TZ_THM1 +\x80\xa0\'\\OSPX\x86\\._PR_CPU0 +\x80\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x80\x10@(\\/\x05_SB_PCI0LPC_EC__HKEY\x14H\x0cMHQT\x01\xa0M\x0b\x90\\WNTF\\TATC\xa0\x0e\x93h +\x00p\\TATC`\xa4`\xa1@ +\xa0K\x04\x93h +\x01p\\TDFA`r`y\\TDTA +\x04\x00`r`y\\TDFD +\x08\x00`r`y\\TDTD +\x0c\x00`r`y\\TNFT +\x10\x00`r`y\\TNTT +\x14\x00`\xa4`\xa1A\x05\xa02\x93h +\x02p\\TCFA`r`y\\TCTA +\x04\x00`r`y\\TCFD +\x08\x00`r`y\\TCTD +\x0c\x00`\xa4`\xa1\x1b\xa0\x05\x93h +\x03\xa1\x13\xa0\x0e\x93h +\x04p\\TATW`\xa4`\xa1\x02\xa3\xa4 +\x00\x14O\x07MHAT\x01\xa0D\x07\x90\\WNTF\\TATCp{h +\xff\x00`\xa0 +\x92ATMV`\xa4 +\x00p{zh +\x08\x00 +\xff\x00`\xa0 +\x92ATMV`\xa4 +\x00p{h +\x0f\x00\\TCFAp{zh +\x04\x00 +\x0f\x00\\TCTAp{zh +\x08\x00 +\x0f\x00\\TCFDp{zh +\x0c\x00 +\x0f\x00\\TCTDATMC\xa4 +\x01\xa4 +\x00\x14@\rMHGT\x01\xa0E\x0c\x90\\WNTF\\TATCpy\\TSFT +\x10\x00`r`y\\TSTT +\x14\x00`p{h +\xff\x00a\xa0\x0b\x92ATMVa\xa4\x0b\xff\xffp{h +\x0f\x00a\xa0\r\x93a +\x00r`\\TIF0`\xa1&\xa0\r\x93a +\x01r`\\TIF1`\xa1\x16\xa0\r\x93a +\x02r`\\TIF2`\xa1\x06r` +\xff`p{zh +\x04\x00 +\x0f\x00a\xa0\x11\x93a +\x00r`y\\TIT0 +\x08\x00`\xa12\xa0\x11\x93a +\x01r`y\\TIT1 +\x08\x00`\xa1\x1e\xa0\x11\x93a +\x02r`y\\TIT2 +\x08\x00`\xa1 +r`y +\xff +\x08\x00`\xa4`\xa4 +\x00\x14L\x04ATMV\x01p{h +\x0f\x00ap\\TNFT`\xa0\x08\x92\x95a`\xa4 +\x00p{zh +\x04\x00 +\x0f\x00bp\\TNTT`\xa0\x08\x92\x95b`\xa4 +\x00\xa0\x0f\\TATL\xa0\x08\x7fab\x00\xa4 +\x00\xa4 +\x01\x10F\x10\\/\x04_SB_PCI0LPC_EC__\x14@\x0fATMC\x00\xa0H\x0e\x90\\WNTF\\TATC\xa0E\x06HPACp\\TCFA`p\\TCTAap}ya +\x04\x00`\x00ATMX\xa0\x1f\x93\\TCTA +\x00p\\TCR0\\TCRTp\\TPS0\\TPSV\xa1#\xa0\x1f\x93\\TCTA +\x01p\\TCR1\\TCRTp\\TPS1\\TPSV\xa1\x01\xa1A\x06p\\TCFD`p\\TCTDap}ya +\x04\x00`\x00ATMX\xa0\x1f\x93\\TCTD +\x00p\\TCR0\\TCRTp\\TPS0\\TPSV\xa1#\xa0\x1f\x93\\TCTD +\x01p\\TCR1\\TCRTp\\TPS1\\TPSV\xa1\x01\x86\\._TZ_THM0 +\x81THRM +\x01\x10C\x1f\\_TZ_[\x85L\x0cTHM0\x14\r_CRT\x00\xa4C2K_ +\x7f\x14G\x0b_TMP\x00\xa0B\x05\\H8DRp\\/\x05_SB_PCI0LPC_EC__TMP0`p\\/\x05_SB_PCI0LPC_EC__HT12ap\\/\x05_SB_PCI0LPC_EC__HT13b\xa1$p\\RBEC +x`p{\\RBEC + +@\x00ap{\\RBEC + +\x80\x00b\xa0\tb\xa4C2K_ +\x80\xa0\'\x92\\/\x06_SB_PCI0LPC_EC__HKEYDHKC\xa0\ta\xa4C2K_ +\x80\xa4C2K_`[\x85@\x0fTHM1\x143_PSL\x00\xa0\x1e\\MPEN\xa4\x12\x16\x02\\._PR_CPU0\\._PR_CPU1\xa4\x12\x0c\x01\\._PR_CPU0\x14\x0c_CRT\x00\xa4\\TCRT\x14\x0c_PSV\x00\xa4\\TPSV\x14\x0c_TC1\x00\xa4\\TTC1\x14\x0c_TC2\x00\xa4\\TTC2\x14\x0c_TSP\x00\xa4\\TTSP\x14D\x07_TMP\x00\xa0J\x05\\DTSETHRM +\x02pDTS1`\xa0\x11\x92\x95DTS0DTS1pDTS0`\xa0.\x92\\/\x06_SB_PCI0LPC_EC__HKEYDHKC\xa0\x10DT02r\\TCRT +\x01`\xa4`\xa4C2K_`\xa1\x11\xa4\\/\x03_TZ_THM0_TMP\x14+C2K_\x01rwh + +\x00\x0b\xac +`\xa0\x0c\x92\x94`\x0b\xac +p\x0b\xb8\x0b`\xa0\x0b\x94`\x0b\xac\x0fp\x0b\xb8\x0b`\xa4`\x10O\x13\\/\x04_SB_PCI0LPC_EC__\x14I\x12_Q40\x00\x86\\._TZ_THM0 +\x80\xa08\\H8DRp\\/\x05_SB_PCI0LPC_EC__HT11`p\\/\x05_SB_PCI0LPC_EC__HT12a\xa1\x1bp{\\RBEC + + \x00`p{\\RBEC + +@\x00a\xa0=\\/\x06_SB_PCI0LPC_EC__HKEYDHKC\xa0 a\\/\x06_SB_PCI0LPC_EC__HKEYMHKQ\x0b"`\xa0\x06VIGD\xa3\xa1\x06\\VTHR\xa0C\x07\\SPEN\xa0\'\\OSPX\x86\\._PR_CPU0 +\x80\xa0\x13\\MPEN\x86\\._PR_CPU1 +\x80\xa1C\x04\xa07\x91\\/\x05_SB_PCI0LPC_EC__HT00\\/\x05_SB_PCI0LPC_EC__HT10\\STEP +\t\xa1\x08\\STEP + +\x08GPIC +\x00\x14\r_PIC\x01ph\\GPIC[\x80MNVS\x00\x0c\x00@\xef\x7f\x0b\x00\x10[\x81B+MNVS\x03\x00\x80\x80\x07GAPA GAPL DCKI DCKS VCDL\x01VCDC\x01VCDT\x01VCDD\x01VIGD\x01VCSS\x01VCDB\x01VCIN\x01VPDF\x01\x00\x07VLID\x04VVPO\x04\x00\x08CDFL\x08CDAH\x08PMOD\x02PDIR\x01PDMA\x01\x00\x04LFDC\x01\x00\x07C2NA\x01C3NA\x01C4NA\x01\x00\x05SPEN\x01\x00\x01\x00\x01\x00\x01MPEN\x01\x00\x03OSPX\x01OSC4\x01OSSS\x01NHPS\x01NPME\x01\x00\x03UOPT\x08BTID LWST\x08LPST\x08TCRT\x10TPSV\x10TTC1\x10TTC2\x10TTSP\x10SRAH\x08SRHE\x08SRE0\x08SRE1\x08SRE2\x08SRE3\x08SRE4\x08SRE5\x08SRU0\x08SRU1\x08SRU2\x08SRU3\x08SRU7\x08SRPB\x08SRLP\x08SRSA\x08SRSM\x08CWAC\x01CWAS\x01\x00\x06CWAP\x10CWAT\x10DBGC\x01\x00\x07FS1L\x10FS1M\x10FS1H\x10FS2L\x10FS2M\x10FS2H\x10FS3L\x10FS3M\x10FS3H\x10TATC\x01\x00\x06TATL\x01TATW\x08TNFT\x04TNTT\x04TDFA\x04TDTA\x04TDFD\x04TDTD\x04TCFA\x04TCTA\x04TCFD\x04TCTD\x04TSFT\x04TSTT\x04TIT0\x08TCR0\x10TPS0\x10TIT1\x08TCR1\x10TPS1\x10TIT2\x08TCR2\x10TPS2\x10TIF0\x08TIF1\x08TIF2\x08\x00 TCZ1\x08TCZ2\x08TCZ3\x08BTHI\x01\x00\x07HDIR\x01HDEH\x01\x00\x06TPMP\x01TPMS\x01\x00\x06BIDE\x08\x00\x01DTSE\x01\x00\x06DTS0\x08DTS1\x08DT00\x01DT01\x01DT02\x01DT03\x01\x00\x04PH01\x08PH02\x08PH03\x08PH04\x08PH05\x08PH06\x08PH07\x08PH08\x08PH09\x08PH0A\x08PH0B\x08LIDB\x01\x00\x07TCG0\x01\x00\x07[\x81\x13MNVS\x01\x00\x80\x00\x07DDC1@@\x00@@[\x81\x10MNVS\x01\x00\x80\x00\x07DDC2@\x80[\x80SMI0\x01 +\xb2 +\x01[\x81\x0bSMI0\x01APMC\x08[\x81(MNVS\x00\x00\x80\xe0\x07CMD_\x08ERR_ PAR0 PAR1 PAR2 PAR3 [\x01MSMI\x07\x14F\x05SMI_\x05[#MSMI\xff\xffphCMD_piPAR0pjPAR1pkPAR2plPAR3p +\xf5APMC\xa2\x13\x93ERR_ +\x01[" +dp +\xf5APMCpPAR0`[\'MSMI\xa4`\x14\x14RPCI\x01\xa4SMI_ +\x00 +\x00h +\x00 +\x00\x14\x12WPCI\x02SMI_ +\x00 +\x01hi +\x00\x14\x11MPCI\x03SMI_ +\x00 +\x02hij\x14\x14RBEC\x01\xa4SMI_ +\x00 +\x03h +\x00 +\x00\x14\x12WBEC\x02SMI_ +\x00 +\x04hi +\x00\x14\x11MBEC\x03SMI_ +\x00 +\x05hij\x14\x14RISA\x01\xa4SMI_ +\x00 +\x06h +\x00 +\x00\x14\x12WISA\x02SMI_ +\x00 +\x07hi +\x00\x14\x11MISA\x03SMI_ +\x00 +\x08hij\x14\x14VEXP\x00SMI_ +\x01 +\x00 +\x00 +\x00 +\x00\x14\x13VUPS\x01SMI_ +\x01 +\x01h +\x00 +\x00\x14\x12VSDS\x02SMI_ +\x01 +\x02hi +\x00\x14\x14VDDC\x00SMI_ +\x01 +\x03 +\x00 +\x00 +\x00\x14\x13VVPD\x01SMI_ +\x01 +\x04h +\x00 +\x00\x14\x13VNRS\x01SMI_ +\x01 +\x05h +\x00 +\x00\x14\x15GLPW\x00\xa4SMI_ +\x01 +\x06 +\x00 +\x00 +\x00\x14\x13VSLD\x01SMI_ +\x01 +\x07h +\x00 +\x00\x14\x14VEVT\x01\xa4SMI_ +\x01 +\x08h +\x00 +\x00\x14\x15VTHR\x00\xa4SMI_ +\x01 +\t +\x00 +\x00 +\x00\x14\x13VBRC\x01SMI_ +\x01 + +h +\x00 +\x00\x14\x15VBRG\x00\xa4SMI_ +\x01 +\x0e +\x00 +\x00 +\x00\x14\x14UCMS\x01\xa4SMI_ +\x02h +\x00 +\x00 +\x00\x14\x13BHDP\x02\xa4SMI_ +\x03 +\x00hi +\x00\x14\x14DHDP\x01\xa4SMI_ +\x03 +\x01h +\x00 +\x00\x14\x13STEP\x01SMI_ +\x04h +\x00 +\x00 +\x00\x14\x14TRAP\x00SMI_ +\x05 +\x00 +\x00 +\x00 +\x00\x14\x14CBRI\x00SMI_ +\x05 +\x01 +\x00 +\x00 +\x00\x14"DSPD\x01\xa0\x18\x92\x94h +\x01rh +\x02hSMI_ +\x05h +\x00 +\x00 +\x00\xa1\x02\xa3\x14\x14BLTH\x01\xa4SMI_ +\x06h +\x00 +\x00 +\x00\x14\x14FISP\x00SMI_ +\x07 +\x00 +\x00 +\x00 +\x00\x14\x13ATCC\x01SMI_ +\x08h +\x00 +\x00 +\x00\x14\x14WGSV\x01\xa4SMI_ +\th +\x00 +\x00 +\x00\x14\x14THRM\x01\xa4SMI_ + +h +\x00 +\x00 +\x00\x14\x14PPMS\x01\xa4SMI_ +\x0bh +\x00 +\x00 +\x00\x14\x13TPHY\x01SMI_ +\x0ch +\x00 +\x00 +\x00\x14\x13TMOR\x01SMI_ +\rh +\x00 +\x00 +\x00\x143DPIO\x02\xa0\x06\x92h\xa4 +\x00\xa0\x08\x94h +\xf0\xa4 +\x00\xa0\x10\x94h +\xb4\xa0\x05i\xa4 +\x02\xa1\x04\xa4 +\x01\xa0\x08\x94h +x\xa4 +\x03\xa4 +\x04\x14=DUDM\x02\xa0\x06\x92i\xa4 +\xff\xa0\x08\x94h +Z\xa4 +\x00\xa0\x08\x94h +<\xa4 +\x01\xa0\x08\x94h +-\xa4 +\x02\xa0\x08\x94h +\x1e\xa4 +\x03\xa0\x08\x94h +\x14\xa4 +\x04\xa4 +\x05\x14(DMDM\x02\xa0\x05i\xa4 +\x00\xa0\x06\x92h\xa4 +\x00\xa0\x08\x94h +\x96\xa4 +\x01\xa0\x08\x94h +x\xa4 +\x02\xa4 +\x03\x14A\x05UUDM\x02\xa0 +\x92{h +\x04\x00\xa4 +\x00\xa0\t{i + \x00\xa4 +\x14\xa0\t{i +\x10\x00\xa4 +\x1e\xa0\t{i +\x08\x00\xa4 +-\xa0\t{i +\x04\x00\xa4 +<\xa0\t{i +\x02\x00\xa4 +Z\xa0\t{i +\x01\x00\xa4 +x\xa4 +\x00\x14H\x04UMDM\x04\xa0 +\x92{h +\x02\x00\xa4 +\x00\xa0\x08{i +\x04\x00\xa4k\xa0\x14{i +\x02\x00\xa0\t\x92\x94k +x\xa4 +\xb4\xa1\x03\xa4k\xa0\x14{j +\x04\x00\xa0\t\x92\x94k +\xb4\xa4 +\xf0\xa1\x03\xa4k\xa4 +\x00\x14K\x04UPIO\x04\xa0\x16\x92{h +\x02\x00\xa0\x08\x93j +\x02\xa4 +\xf0\xa1\x05\xa4\x0b\x84\x03\xa0\x08{i +\x02\x00\xa4k\xa0\x14{i +\x01\x00\xa0\t\x92\x94k +x\xa4 +\xb4\xa1\x03\xa4k\xa0\x08\x93j +\x02\xa4 +\xf0\xa1\x05\xa4\x0b\x84\x03\x14-FDMA\x02\xa0\x0c\x92\x93i +\xff\xa4}i +@\x00\xa0\x10\x92\x95h +\x03\xa4}th +\x02\x00 + \x00\xa0\x05h\xa4 +\x12\xa4 +\x00\x14\x1fFPIO\x01\xa0\x0c\x92\x95h +\x03\xa4}h +\x08\x00\xa0\x08\x93h +\x01\xa4 +\x01\xa4 +\x00\x14J\x05SCMP\x02p\x87h`\xa0\x08\x92\x93`\x87i\xa4\x01u`\x08STR1\x11\x02`\x08STR2\x11\x02`phSTR1piSTR2p\x00a\xa2"\x95a`p\x83\x88STR1a\x00bp\x83\x88STR2a\x00c\xa0\x07\x92\x93bc\xa4\x01ua\xa4\x00\x08SPS_ +\x00\x08OSIF +\x00\x08W98F +\x00\x08WNTF +\x00\x08WMEF +\x00\x08WXPF +\x00\x08WVIS +\x00\x08WSPV +\x00\x08LNUX +\x00\x08H8DR +\x00\x08MEMX +\x00\x08ACST +\x00\x08FNID +\x00\x08RRBF +\x00\x08NBCF +\x00''') +f('sys/firmware/acpi/tables/SSDT1', 0o664, b'''SSDT\xaa\x01\x00\x00\x01\x89LENOVOTP-7I \x11\x00\x00MSFT\x0e\x00\x00\x01\x10\x0e\\\x00\x14 +KOU2\x00[! +d\x10I\x0b\\/\x04_SB_PCI0VID_LCD0\x14&_BCL\x00p +\x01\\NBCF\xa4\x12\x16 + +d +\x1e +\x1e +( +2 +< +F +P +Z +d\x08BCLP\x12\x12\x08 +\x1e +( +2 +< +F +P +Z +d\x08BCLL\x12\x12\x08 +\x00 +\x01 +\x02 +\x03 +\x04 +\x05 +\x06 +\x07\x14*_BCM\x01p\x89BCLP\x01h\x00 +\x00 +\x00`\xa0\x15\x92\x93`\xffp\x83\x88BCLL`\x00a\\VBRCa\x14!_BQC\x00p\\VBRG`\xa0\x0f\x92\x94` +\x07\xa4\x83\x88BCLP`\x00\xa1\x03\xa4\x00\x10L\x0b\\/\x05_SB_PCI0AGP_VID_LCD0\x14%_BCL\x00p +\x01NBCF\xa4\x12\x16 + +d +\x1e +\x1e +( +2 +< +F +P +Z +d\x08BCLP\x12\x12\x08 +\x1e +( +2 +< +F +P +Z +d\x08BCLL\x12\x12\x08 +\x00 +\x01 +\x02 +\x03 +\x04 +\x05 +\x06 +\x07\x14*_BCM\x01p\x89BCLP\x01h\x00 +\x00 +\x00`\xa0\x15\x92\x93`\xffp\x83\x88BCLL`\x00a\\VBRCa\x14!_BQC\x00p\\VBRG`\xa0\x0f\x92\x94` +\x07\xa4\x83\x88BCLP`\x00\xa1\x03\xa4\x00''') +f('sys/firmware/acpi/tables/SLIC', 0o664, b'SLICv\x01\x00\x00\x01\x1dLENOVOTP-7I \x11\x00\x00 LTP\x00\x00\x00\x00\x00\x00\x00\x00\x9c\x00\x00\x00\x06\x02\x00\x00\x00$\x00\x00RSA1\x00\x04\x00\x00\x01\x00\x01\x00i\x16J\x9f\xb1K:\xfb\x80 \xaa\xaf\xc4\xf9>\xc1\x80I\xeeje&r\x1e\xcd\xbf_/\x96\xd6\xc0\n\x92\xf5\x06\xb5\x00\xb2;)\x02\xe2L\x8d\xc2\xf2\xbcAw\x9cp\xf0\xf3\x1b\t\xd2cZ\xdc\xa8\x83\xf8^\xc9\x15\x95\xf9\xfa\xfd\xdc\x05\xb7Mg\x7f-\xb3\x843 \xe1\xd1y*\xa7jw\xd1\xb6 *vB\xc5\xd5\xe9\xb6C@UD\xc3\xc97\x99_A\x97p\xf3\xd1\xf6\x07\xec{\x1a)\xa1\xc1\xf1\x91\xfdH\x86n>\xce\xcb\x01\x00\x00\x00\xb6\x00\x00\x00\x00\x00\x02\x00LENOVOTP-7I WINDOWS \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8bz\xb4\xe1\x0e{\x7fc\xd3M%N\xd7\tBd\x9c\x89\xf6F\xb8L\xd5M\x86sy\xf0\x15\xf2\x98\xad\x806\t\xbd\x8c%wn\xb8C\xf4\xb1\xf0W\x08x\x8d\xc6\x18T\xe1`G\xf07\xfdH\xd2\xfdM\x07\xdd\x91O\x9e*\xd6\xdd4\xeb\x9ac\x9a\xb8O%\xd4o\xf0\x95\xbb\xce\xbd:X\x04\xc5l\xb8\xa8\xd89\xf5\x02Oh\x84\x9c)K\xd0\x9b\x16\xb5\xf5A\xb0\x9d\xb8A\x07\x9dJ\x11\xaf\x19\xbd\xb7\xc7\x05\xb6\xa7\x93H\xf6\xcb') +f('sys/firmware/acpi/tables/SSDT3', 0o664, b'''SSDT\xa6\x00\x00\x00\x01hLENOVOTP-7I \x11\x00\x00INTL\x13\x05\x05 \x10A\x08\\._PR_CPU1\x08_TPC +\x00\x14\x16_PTC\x00\xa4\\/\x03_PR_CPU0_PTC\x14\x16_TSS\x00\xa4\\/\x03_PR_CPU0_TSS\x14?_TSD\x00\xa0\'\x90{CFGD\x0c\x00\x00\x00\x01\x00\x92{PDC1 +\x04\x00\xa4\x12\x0f\x01\x12\x0c\x05 +\x05 +\x00 +\x00 +\xfd +\x02\xa4\x12\x0f\x01\x12\x0c\x05 +\x05 +\x00 +\x01 +\xfc +\x01''') +f('sys/firmware/acpi/tables/SSDT5', 0o664, b'''SSDT\xd8\x01\x00\x00\x01\tLENOVOTP-7I \x11\x00\x00INTL\x13\x05\x05 \x10C\x1b\\/\x03_SB_PCI0SATA[\x82@\x1aPRT0\x08DRE0 +\x00\x08DIP0 +\x00\x08HDTF\x11\x11 +\x0e\x02\x00\x00\x00\x00\xa0\xef\x00\x00\x00\x00\x00\xa0\xf5\x8cHDTF +\rHFLC\x08ERTF\x11\x18 +\x15\x02\x00\x00\x00\x00\xa0\xef\x00\x00\x00\x00\x00\xa0\xf5_\x00\x00\x00\x00\xa0\xef\x8cERTF +\rEFLC\x08HPTF\x11\x18 +\x15\x02\x00\x00\x00\x00\xa0\xef\x00\x00\x00\x00\x00\xa0\xf5\x10\x03\x00\x00\x00\xa0\xef\x8cHPTF +\rPFLC\x08HXTF\x11\x1f +\x1c\x02\x00\x00\x00\x00\xa0\xef\x00\x00\x00\x00\x00\xa0\xf5_\x00\x00\x00\x00\xa0\xef\x10\x03\x00\x00\x00\xa0\xef\x8cHXTF +\rXFLC\x08_ADR\x0b\xff\xff\x14L\x08_SDD\x01p +\x00DRE0p +\x00DIP0\xa0F\x07\x93\x87h\x0b\x00\x02\x8bh +\x9cM078\x8bh +\xacM086\x8bh +\xeeM119\x8bh\x0b(\x01M148\xa0\x1f\x93{M148\x0b\x00\xc0\x00\x0b\x00@\xa0\x10{M148 +\x04\x00p +\x01DRE0\xa0\x1b{M086\x0b\x00\x80\x00\xa0\x10{M119 +\x01\x00p +\x01DRE0\xa0\x10{M078 +\x08\x00p +\x01DIP0\x14B\x05_GTF\x00\xa0"\\OSSSp +\xe1XFLCp +\xe1EFLCp +\xe1HFLCp +\xe1PFLC\xa0\x17DRE0\xa0 +DIP0\xa4HXTF\xa1\x06\xa4ERTF\xa0 +DIP0\xa4HPTF\xa4HDTF''') +f('sys/firmware/acpi/tables/HPET', 0o664, b'HPET8\x00\x00\x00\x01\xaaLENOVOTP-7I \x11\x00\x00LNVO\x01\x00\x00\x00\x01\xa2\x86\x80\x00\x00\x00\x00\x00\x00\xd0\xfe\x00\x00\x00\x00\x00\x80\x00\x00') +f('sys/firmware/acpi/tables/FACP', 0o664, b'FACP\xf4\x00\x00\x00\x03\xf0LENOVOTP-7I \x11\x00\x00LNVO\x01\x00\x00\x00\x00@\xef\x7f^\x19\xed\x7f\x00\x02\t\x00\xb2\x00\x00\x00\xf0\xf1\x00\xf3\x00\x10\x00\x00\x00\x00\x00\x00\x04\x10\x00\x00\x00\x00\x00\x00 \x10\x00\x00\x08\x10\x00\x00(\x10\x00\x00\x00\x00\x00\x00\x04\x02\x01\x04\x08\x00\x00\xf4\x01\x00U\x00\x00\x00\x00\x00\x01\x03\r\x002\x12\x00\x00\xad\xc2\x00\x00\x01\x08\x00\x00\xf9\x0c\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00@\xef\x7f\x00\x00\x00\x00^\x19\xed\x7f\x00\x00\x00\x00\x01 \x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x10\x00\x00\x04\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x08\x00\x00 \x10\x00\x00\x00\x00\x00\x00\x01 \x00\x00\x08\x10\x00\x00\x00\x00\x00\x00\x01 \x00\x00(\x10\x00\x00\x00\x00\x00\x00\x01 \x00\x00,\x10\x00\x00\x00\x00\x00\x00') +f('sys/firmware/acpi/tables/APIC', 0o664, b'''APICh\x00\x00\x00\x01lLENOVOTP-7I \x11\x00\x00LNVO\x01\x00\x00\x00\x00\x00\xe0\xfe\x01\x00\x00\x00\x00\x08\x00\x00\x01\x00\x00\x00\x00\x08\x01\x01\x01\x00\x00\x00\x01\x0c\x01\x00\x00\x00\xc0\xfe\x00\x00\x00\x00\x02 +\x00\x00\x02\x00\x00\x00\x00\x00\x02 +\x00\t\t\x00\x00\x00\r\x00\x04\x06\x00\x05\x00\x01\x04\x06\x01\x05\x00\x01''') +f('sys/firmware/acpi/tables/SSDT2', 0o664, b'''SSDT_\x02\x00\x00\x01\xc2LENOVOTP-7I \x11\x00\x00INTL\x13\x05\x05 \x10J#\\._PR_CPU0\x08_TPC +\x00\x14M\x06_PTC\x00\xa07{PDC0 +\x04\x00\xa4\x12,\x02\x11\x14 +\x11\x82\x0c\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y\x00\x11\x14 +\x11\x82\x0c\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y\x00\xa4\x12,\x02\x11\x14 +\x11\x82\x0c\x00\x01\x04\x01\x00\x10\x10\x00\x00\x00\x00\x00\x00y\x00\x11\x14 +\x11\x82\x0c\x00\x01\x04\x01\x00\x10\x10\x00\x00\x00\x00\x00\x00y\x00\x08TSSI\x12A\x07\x08\x12\r\x05 +d\x0b\xe8\x03 +\x00 +\x00 +\x00\x12\r\x05 +X\x0bk\x03 +\x00 +\x0f +\x00\x12\r\x05 +K\x0b\xee\x02 +\x00 +\x0e +\x00\x12\r\x05 +?\x0bq\x02 +\x00 +\r +\x00\x12\r\x05 +2\x0b\xf4\x01 +\x00 +\x0c +\x00\x12\r\x05 +&\x0bw\x01 +\x00 +\x0b +\x00\x12\x0c\x05 +\x19 +\xfa +\x00 + + +\x00\x12\x0c\x05 +\r +} +\x00 +\t +\x00\x08TSSM\x12A\x07\x08\x12\r\x05 +d\x0b\xe8\x03 +\x00 +\x00 +\x00\x12\r\x05 +X\x0bk\x03 +\x00 +\x1e +\x00\x12\r\x05 +K\x0b\xee\x02 +\x00 +\x1c +\x00\x12\r\x05 +?\x0bq\x02 +\x00 +\x1a +\x00\x12\r\x05 +2\x0b\xf4\x01 +\x00 +\x18 +\x00\x12\r\x05 +&\x0bw\x01 +\x00 +\x16 +\x00\x12\x0c\x05 +\x19 +\xfa +\x00 +\x14 +\x00\x12\x0c\x05 +\r +} +\x00 +\x12 +\x00\x08TSSF +\x00\x14C\x08_TSS\x00\xa0G\x06\x90\x92TSSF[\x12_PSS\x00p_PSS`p\x87`avap\x83\x88\x83\x88`a\x00 +\x01\x00bp +\x00c\xa25\x95c\x87TSSIpxwbt +\x08c\x00\x00 +\x08\x00\x00dpd\x88\x83\x88TSSIc\x00 +\x01\x00pd\x88\x83\x88TSSMc\x00 +\x01\x00ucp\xffTSSF\xa0\x0e{PDC0 +\x04\x00\xa4TSSM\xa4TSSI\x14?_TSD\x00\xa0\'\x90{CFGD\x0c\x00\x00\x00\x01\x00\x92{PDC0 +\x04\x00\xa4\x12\x0f\x01\x12\x0c\x05 +\x05 +\x00 +\x00 +\xfd +\x02\xa4\x12\x0f\x01\x12\x0c\x05 +\x05 +\x00 +\x00 +\xfc +\x01''') +f('sys/firmware/acpi/tables/BOOT', 0o664, b'BOOT(\x00\x00\x00\x01\xa8LENOVOTP-7I \x11\x00\x00 LTP\x01\x00\x00\x005\x00\x00\x00') +f('sys/firmware/acpi/tables/TCPA', 0o664, b'TCPA2\x00\x00\x00\x02YLENOVOTP-7I \x11\x00\x00LNVO\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\xce\x1a\xee\x7f\x00\x00\x00\x00') +f('sys/firmware/acpi/tables/SSDT4', 0o664, b'''SSDT\xf7\x04\x00\x00\x01\xa6LENOVOTP-7I \x11\x00\x00INTL\x13\x05\x05 \x10E\x08\\\x00\x08SSDT\x12C\x05\x0c\rCPU0IST \x00\x0c6\x1d\xef\x7f\x0c\xc4\x02\x00\x00\rCPU1IST \x00\x0cn\x1c\xef\x7f\x0c\xc8\x00\x00\x00\rCPU0CST \x00\x0c\x7f \xef\x7f\x0cZ\x06\x00\x00\rCPU1CST \x00\x0c\xfa\x1f\xef\x7f\x0c\x85\x00\x00\x00\x08CFGD\x0c\xf1i;\x11\x08\\PDC0\x0c\x00\x00\x00\x80\x08\\PDC1\x0c\x00\x00\x00\x80\x08\\SDTL +\x00\x10@!\\._PR_CPU0\x08HI0_ +\x00\x08HC0_ +\x00\x14H\x06_PDC\x01\x8ah +\x00REVS\x8ah +\x04SIZEp\x87h`pt` +\x08\x00a[\x13h +@wa +\x08\x00TEMP\x08STS0\x11\x07 +\x04\x00\x00\x00\x00sSTS0TEMPb_OSC\x11\x13 +\x10\x16\xa6w@\x0c)\xbeG\x9e\xbd\xd8pXq9SREVSSIZEb\x14L\x18_OSC\x04\x8ak +\x00STS0\x8ak +\x04CAP0\x8ah +\x00IID0\x8ah +\x04IID1\x8ah +\x08IID2\x8ah +\x0cIID3\x08UID0\x11\x13 +\x10\x16\xa6w@\x0c)\xbeG\x9e\xbd\xd8pXq9S\x8aUID0 +\x00EID0\x8aUID0 +\x04EID1\x8aUID0 +\x08EID2\x8aUID0 +\x0cEID3\xa02\x92\x90\x90\x93IID0EID0\x93IID1EID1\x90\x93IID2EID2\x93IID3EID3p +\x06STS0\xa4k\xa0\x0f\x92\x93i +\x01p + +STS0\xa4k}{PDC0\x0c\xff\xff\xff\x7f\x00CAP0PDC0\xa0L\x05{CFGD +\x01\x00\xa0A\x05\x90\x90{CFGD\x0c\x00\x00\x00\x01\x00\x93{PDC0 +\t\x00 +\t\x92{SDTL +\x01\x00}SDTL +\x01SDTL[\x80IST0\x00\x83\x88SSDT +\x01\x00\x83\x88SSDT +\x02\x00[ IST0HI0_\xa0I\x05{CFGD +\xf0\x00\xa0N\x04\x90\x90{CFGD\x0c\x00\x00\x00\x01\x00{PDC0 +\x18\x00\x92{SDTL +\x02\x00}SDTL +\x02SDTL[\x80CST0\x00\x83\x88SSDT +\x07\x00\x83\x88SSDT +\x08\x00[ CST0HC0_\xa4k\x10K#\\._PR_CPU1\x08HI1_ +\x00\x08HC1_ +\x00\x14H\x06_PDC\x01\x8ah +\x00REVS\x8ah +\x04SIZEp\x87h`pt` +\x08\x00a[\x13h +@wa +\x08\x00TEMP\x08STS1\x11\x07 +\x04\x00\x00\x00\x00sSTS1TEMPb_OSC\x11\x13 +\x10\x16\xa6w@\x0c)\xbeG\x9e\xbd\xd8pXq9SREVSSIZEb\x14L\x18_OSC\x04\x8ak +\x00STS1\x8ak +\x04CAP1\x8ah +\x00IID0\x8ah +\x04IID1\x8ah +\x08IID2\x8ah +\x0cIID3\x08UID1\x11\x13 +\x10\x16\xa6w@\x0c)\xbeG\x9e\xbd\xd8pXq9S\x8aUID1 +\x00EID0\x8aUID1 +\x04EID1\x8aUID1 +\x08EID2\x8aUID1 +\x0cEID3\xa02\x92\x90\x90\x93IID0EID0\x93IID1EID1\x90\x93IID2EID2\x93IID3EID3p +\x06STS1\xa4k\xa0\x0f\x92\x93i +\x01p + +STS1\xa4k}{PDC1\x0c\xff\xff\xff\x7f\x00CAP1PDC1\xa0L\x05{CFGD +\x01\x00\xa0A\x05\x90\x90{CFGD\x0c\x00\x00\x00\x01\x00\x93{PDC1 +\t\x00 +\t\x92{SDTL +\x10\x00}SDTL +\x10SDTL[\x80IST1\x00\x83\x88SSDT +\x04\x00\x83\x88SSDT +\x05\x00[ IST1HI1_\xa0I\x05{CFGD +\xf0\x00\xa0N\x04\x90\x90{CFGD\x0c\x00\x00\x00\x01\x00{PDC1 +\x18\x00\x92{SDTL + \x00}SDTL + SDTL[\x80CST1\x00\x83\x88SSDT + +\x00\x83\x88SSDT +\x0b\x00[ CST1HC1_\xa4k\x14*_INI\x00\xa0\x0c\\DTSETHRM +\x00\xa0\x16\x90\\WXPF\x92\x94\\WSPV +\x01PPMS +\x00''') +f('sys/firmware/acpi/tables/ECDT', 0o664, b'ECDTR\x00\x00\x00\x01ULENOVOTP-7I \x11\x00\x00LNVO\x01\x00\x00\x00\x01\x08\x00\x00f\x00\x00\x00\x00\x00\x00\x00\x01\x08\x00\x00b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\\_SB.PCI0.LPC.EC\x00') +f('sys/firmware/acpi/tables/FACS', 0o664, b'FACS@\x00\x00\x00/\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +f('sys/firmware/acpi/tables/MCFG', 0o664, b'MCFG<\x00\x00\x00\x01\x82LENOVOTP-7I \x11\x00\x00LNVO\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x00\x00?\x00\x00\x00\x00') +d('sys/firmware/acpi/interrupts', 0o775) +f('sys/firmware/acpi/interrupts/gpe1A', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe12', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe11', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe10', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/ff_pmtimer', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe0C', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe04', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe06', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe14', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe0B', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/sci', 0o664, b' 14240\n') +f('sys/firmware/acpi/interrupts/gpe08', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe15', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe17', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe0A', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/ff_rt_clk', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe09', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe19', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe03', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe01', 0o664, b' 1\tenable\n') +f('sys/firmware/acpi/interrupts/ff_slp_btn', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/error', 0o664, b' 0\n') +f('sys/firmware/acpi/interrupts/gpe1C', 0o664, b' 14039\tenable\n') +f('sys/firmware/acpi/interrupts/ff_pwr_btn', 0o664, b' 0\tenable\n') +f('sys/firmware/acpi/interrupts/gpe0D', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe05', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe02', 0o664, b' 200\tenable\n') +f('sys/firmware/acpi/interrupts/gpe1E', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe18', 0o664, b' 0\tenable\n') +f('sys/firmware/acpi/interrupts/gpe1D', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe1F', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe0E', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe00', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe1B', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe0F', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe07', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe16', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe13', 0o664, b' 0 invalid\n') +f('sys/firmware/acpi/interrupts/gpe_all', 0o664, b' 14240\n') +f('sys/firmware/acpi/interrupts/ff_gbl_lock', 0o664, b' 0\tenable\n') +d('sys/bus', 0o755) +d('sys/bus/pci_express', 0o755) +f('sys/bus/pci_express/drivers_autoprobe', 0o644, b'1\n') +d('sys/bus/pci_express/devices', 0o755) +l('sys/bus/pci_express/devices/0000:00:1c.2:pcie02', '../../../devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie02') +l('sys/bus/pci_express/devices/0000:00:1c.2:pcie00', '../../../devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie00') +l('sys/bus/pci_express/devices/0000:00:1c.0:pcie03', '../../../devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie03') +l('sys/bus/pci_express/devices/0000:00:01.0:pcie03', '../../../devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie03') +l('sys/bus/pci_express/devices/0000:00:1c.2:pcie03', '../../../devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie03') +l('sys/bus/pci_express/devices/0000:00:1c.1:pcie02', '../../../devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie02') +l('sys/bus/pci_express/devices/0000:00:1c.0:pcie00', '../../../devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie00') +l('sys/bus/pci_express/devices/0000:00:1c.3:pcie02', '../../../devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie02') +l('sys/bus/pci_express/devices/0000:00:1c.0:pcie02', '../../../devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie02') +l('sys/bus/pci_express/devices/0000:00:1c.1:pcie03', '../../../devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie03') +l('sys/bus/pci_express/devices/0000:00:1c.3:pcie03', '../../../devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie03') +l('sys/bus/pci_express/devices/0000:00:1c.1:pcie00', '../../../devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie00') +l('sys/bus/pci_express/devices/0000:00:1c.3:pcie00', '../../../devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie00') +l('sys/bus/pci_express/devices/0000:00:01.0:pcie00', '../../../devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie00') +d('sys/bus/acpi', 0o775) +f('sys/bus/acpi/drivers_autoprobe', 0o664, b'1\n') +d('sys/bus/acpi/drivers', 0o775) +d('sys/bus/acpi/drivers/thinkpad_hotkey', 0o775) +l('sys/bus/acpi/drivers/thinkpad_hotkey/IBM0068:00', '../../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00') +d('sys/bus/acpi/drivers/button', 0o775) +l('sys/bus/acpi/drivers/button/PNP0C0E:00', '../../../../devices/LNXSYSTM:00/device:00/PNP0C0E:00') +l('sys/bus/acpi/drivers/button/PNP0C0D:00', '../../../../devices/LNXSYSTM:00/device:00/PNP0C0D:00') +l('sys/bus/acpi/drivers/button/LNXPWRBN:00', '../../../../devices/LNXSYSTM:00/LNXPWRBN:00') +d('sys/bus/acpi/drivers/processor', 0o775) +l('sys/bus/acpi/drivers/processor/ACPI0007:01', '../../../../devices/LNXSYSTM:00/ACPI0007:01') +l('sys/bus/acpi/drivers/processor/ACPI0007:00', '../../../../devices/LNXSYSTM:00/ACPI0007:00') +d('sys/bus/acpi/drivers/power', 0o775) +l('sys/bus/acpi/drivers/power/LNXPOWER:00', '../../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00') +d('sys/bus/acpi/drivers/pci_link', 0o775) +l('sys/bus/acpi/drivers/pci_link/PNP0C0F:05', '../../../../devices/LNXSYSTM:00/device:00/PNP0C0F:05') +l('sys/bus/acpi/drivers/pci_link/PNP0C0F:07', '../../../../devices/LNXSYSTM:00/device:00/PNP0C0F:07') +l('sys/bus/acpi/drivers/pci_link/PNP0C0F:04', '../../../../devices/LNXSYSTM:00/device:00/PNP0C0F:04') +l('sys/bus/acpi/drivers/pci_link/PNP0C0F:02', '../../../../devices/LNXSYSTM:00/device:00/PNP0C0F:02') +l('sys/bus/acpi/drivers/pci_link/PNP0C0F:00', '../../../../devices/LNXSYSTM:00/device:00/PNP0C0F:00') +l('sys/bus/acpi/drivers/pci_link/PNP0C0F:01', '../../../../devices/LNXSYSTM:00/device:00/PNP0C0F:01') +l('sys/bus/acpi/drivers/pci_link/PNP0C0F:06', '../../../../devices/LNXSYSTM:00/device:00/PNP0C0F:06') +l('sys/bus/acpi/drivers/pci_link/PNP0C0F:03', '../../../../devices/LNXSYSTM:00/device:00/PNP0C0F:03') +d('sys/bus/acpi/drivers/battery', 0o775) +l('sys/bus/acpi/drivers/battery/PNP0C0A:00', '../../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00') +d('sys/bus/acpi/drivers/ec', 0o775) +l('sys/bus/acpi/drivers/ec/PNP0C09:00', '../../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00') +d('sys/bus/acpi/drivers/pci_root', 0o775) +l('sys/bus/acpi/drivers/pci_root/PNP0A08:00', '../../../../devices/LNXSYSTM:00/device:00/PNP0A08:00') +d('sys/bus/acpi/drivers/thermal', 0o775) +l('sys/bus/acpi/drivers/thermal/LNXTHERM:01', '../../../../devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01') +l('sys/bus/acpi/drivers/thermal/LNXTHERM:02', '../../../../devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02') +d('sys/bus/acpi/drivers/ac', 0o775) +l('sys/bus/acpi/drivers/ac/ACPI0003:00', '../../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00') +d('sys/bus/acpi/devices', 0o775) +l('sys/bus/acpi/devices/device:11', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11') +l('sys/bus/acpi/devices/device:21', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21') +l('sys/bus/acpi/devices/PNP0000:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0000:00') +l('sys/bus/acpi/devices/device:0b', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0b') +l('sys/bus/acpi/devices/device:1f', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/device:1f') +l('sys/bus/acpi/devices/LNXTHERM:01', '../../../devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01') +l('sys/bus/acpi/devices/PNP0103:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00') +l('sys/bus/acpi/devices/LNXPOWER:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00') +l('sys/bus/acpi/devices/device:1c', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/device:1c') +l('sys/bus/acpi/devices/device:06', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06') +l('sys/bus/acpi/devices/ACPI0003:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00') +l('sys/bus/acpi/devices/PNP0C0A:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00') +l('sys/bus/acpi/devices/device:0e', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/device:0e') +l('sys/bus/acpi/devices/ATM1200:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00') +l('sys/bus/acpi/devices/device:08', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:08') +l('sys/bus/acpi/devices/PNP0C0F:05', '../../../devices/LNXSYSTM:00/device:00/PNP0C0F:05') +l('sys/bus/acpi/devices/device:18', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:18') +l('sys/bus/acpi/devices/device:0c', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c') +l('sys/bus/acpi/devices/PNP0303:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00') +l('sys/bus/acpi/devices/device:17', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/device:17') +l('sys/bus/acpi/devices/device:02', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02') +l('sys/bus/acpi/devices/ACPI0007:01', '../../../devices/LNXSYSTM:00/ACPI0007:01') +l('sys/bus/acpi/devices/device:13', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13') +l('sys/bus/acpi/devices/PNP0C0E:00', '../../../devices/LNXSYSTM:00/device:00/PNP0C0E:00') +l('sys/bus/acpi/devices/device:04', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:04') +l('sys/bus/acpi/devices/PNP0A08:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00') +l('sys/bus/acpi/devices/PNP0C04:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00') +l('sys/bus/acpi/devices/LNXTHERM:00', '../../../devices/LNXSYSTM:00/LNXTHERM:00') +l('sys/bus/acpi/devices/device:15', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/device:15') +l('sys/bus/acpi/devices/IBM0079:00', '../../../devices/LNXSYSTM:00/device:00/IBM0079:00') +l('sys/bus/acpi/devices/device:1d', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d') +l('sys/bus/acpi/devices/PNP0C0D:00', '../../../devices/LNXSYSTM:00/device:00/PNP0C0D:00') +l('sys/bus/acpi/devices/device:23', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:23') +l('sys/bus/acpi/devices/device:19', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:19') +l('sys/bus/acpi/devices/device:12', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/device:12') +l('sys/bus/acpi/devices/device:1a', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a') +l('sys/bus/acpi/devices/device:00', '../../../devices/LNXSYSTM:00/device:00') +l('sys/bus/acpi/devices/PNP0800:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00') +l('sys/bus/acpi/devices/PNP0C02:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00') +l('sys/bus/acpi/devices/device:10', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/device:10') +l('sys/bus/acpi/devices/PNP0100:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0100:00') +l('sys/bus/acpi/devices/device:0d', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d') +l('sys/bus/acpi/devices/IBM0068:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00') +l('sys/bus/acpi/devices/device:25', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:25') +l('sys/bus/acpi/devices/PNP0C01:00', '../../../devices/LNXSYSTM:00/device:00/PNP0C01:00') +l('sys/bus/acpi/devices/device:01', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01') +l('sys/bus/acpi/devices/PNP0C0F:07', '../../../devices/LNXSYSTM:00/device:00/PNP0C0F:07') +l('sys/bus/acpi/devices/PNP0C0F:04', '../../../devices/LNXSYSTM:00/device:00/PNP0C0F:04') +l('sys/bus/acpi/devices/device:1b', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b') +l('sys/bus/acpi/devices/device:24', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:24') +l('sys/bus/acpi/devices/device:1e', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e') +l('sys/bus/acpi/devices/ACPI0007:00', '../../../devices/LNXSYSTM:00/ACPI0007:00') +l('sys/bus/acpi/devices/LNXTHERM:02', '../../../devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02') +l('sys/bus/acpi/devices/PNP0C09:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00') +l('sys/bus/acpi/devices/device:20', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:20') +l('sys/bus/acpi/devices/PNP0C0F:02', '../../../devices/LNXSYSTM:00/device:00/PNP0C0F:02') +l('sys/bus/acpi/devices/LNXSYSTM:00', '../../../devices/LNXSYSTM:00') +l('sys/bus/acpi/devices/device:05', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:05') +l('sys/bus/acpi/devices/PNP0C0F:00', '../../../devices/LNXSYSTM:00/device:00/PNP0C0F:00') +l('sys/bus/acpi/devices/device:0f', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f') +l('sys/bus/acpi/devices/device:16', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16') +l('sys/bus/acpi/devices/device:09', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:09') +l('sys/bus/acpi/devices/device:07', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07') +l('sys/bus/acpi/devices/device:03', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:03') +l('sys/bus/acpi/devices/device:22', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22') +l('sys/bus/acpi/devices/PNP0C0F:01', '../../../devices/LNXSYSTM:00/device:00/PNP0C0F:01') +l('sys/bus/acpi/devices/PNP0C0F:06', '../../../devices/LNXSYSTM:00/device:00/PNP0C0F:06') +l('sys/bus/acpi/devices/device:0a', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:0a') +l('sys/bus/acpi/devices/PNP0200:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00') +l('sys/bus/acpi/devices/device:14', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14') +l('sys/bus/acpi/devices/IBM0057:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00') +l('sys/bus/acpi/devices/PNP0B00:00', '../../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00') +l('sys/bus/acpi/devices/PNP0C0F:03', '../../../devices/LNXSYSTM:00/device:00/PNP0C0F:03') +l('sys/bus/acpi/devices/LNXPWRBN:00', '../../../devices/LNXSYSTM:00/LNXPWRBN:00') +d('sys/bus/serio', 0o755) +f('sys/bus/serio/drivers_autoprobe', 0o644, b'1\n') +d('sys/bus/serio/drivers', 0o755) +d('sys/bus/serio/drivers/psmouse', 0o755) +l('sys/bus/serio/drivers/psmouse/module', '../../../../module/psmouse') +l('sys/bus/serio/drivers/psmouse/serio1', '../../../../devices/platform/i8042/serio1') +f('sys/bus/serio/drivers/psmouse/bind_mode', 0o644, b'auto\n') +f('sys/bus/serio/drivers/psmouse/description', 0o644, b'PS/2 mouse driver\n') +d('sys/bus/serio/drivers/atkbd', 0o755) +l('sys/bus/serio/drivers/atkbd/serio0', '../../../../devices/platform/i8042/serio0') +l('sys/bus/serio/drivers/atkbd/module', '../../../../module/atkbd') +f('sys/bus/serio/drivers/atkbd/bind_mode', 0o644, b'auto\n') +f('sys/bus/serio/drivers/atkbd/description', 0o644, b'AT and PS/2 keyboard driver\n') +d('sys/bus/serio/devices', 0o755) +l('sys/bus/serio/devices/serio0', '../../../devices/platform/i8042/serio0') +l('sys/bus/serio/devices/serio1', '../../../devices/platform/i8042/serio1') +d('sys/bus/scsi', 0o755) +f('sys/bus/scsi/drivers_autoprobe', 0o644, b'1\n') +d('sys/bus/scsi/drivers', 0o755) +d('sys/bus/scsi/drivers/sd', 0o755) +l('sys/bus/scsi/drivers/sd/7:0:0:0', '../../../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0') +l('sys/bus/scsi/drivers/sd/0:0:0:0', '../../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0') +d('sys/bus/scsi/drivers/sr', 0o755) +l('sys/bus/scsi/drivers/sr/4:0:0:0', '../../../../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0') +d('sys/bus/scsi/devices', 0o755) +l('sys/bus/scsi/devices/target4:0:0', '../../../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0') +l('sys/bus/scsi/devices/host0', '../../../devices/pci0000:00/0000:00:1f.2/host0') +l('sys/bus/scsi/devices/host5', '../../../devices/pci0000:00/0000:00:1f.1/host5') +l('sys/bus/scsi/devices/host1', '../../../devices/pci0000:00/0000:00:1f.2/host1') +l('sys/bus/scsi/devices/target0:0:0', '../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0') +l('sys/bus/scsi/devices/host4', '../../../devices/pci0000:00/0000:00:1f.1/host4') +l('sys/bus/scsi/devices/7:0:0:0', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0') +l('sys/bus/scsi/devices/target7:0:0', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0') +l('sys/bus/scsi/devices/0:0:0:0', '../../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0') +l('sys/bus/scsi/devices/host2', '../../../devices/pci0000:00/0000:00:1f.2/host2') +l('sys/bus/scsi/devices/host7', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7') +l('sys/bus/scsi/devices/4:0:0:0', '../../../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0') +l('sys/bus/scsi/devices/host3', '../../../devices/pci0000:00/0000:00:1f.2/host3') +d('sys/bus/usb', 0o755) +f('sys/bus/usb/drivers_autoprobe', 0o644, b'1\n') +d('sys/bus/usb/drivers', 0o755) +d('sys/bus/usb/drivers/usb-storage', 0o755) +l('sys/bus/usb/drivers/usb-storage/module', '../../../../module/usb_storage') +l('sys/bus/usb/drivers/usb-storage/5-1:1.0', '../../../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0') +d('sys/bus/usb/drivers/cdc_acm', 0o755) +l('sys/bus/usb/drivers/cdc_acm/5-2:1.1', '../../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1') +l('sys/bus/usb/drivers/cdc_acm/5-2:1.0', '../../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0') +l('sys/bus/usb/drivers/cdc_acm/module', '../../../../module/cdc_acm') +d('sys/bus/usb/drivers/usbhid', 0o755) +l('sys/bus/usb/drivers/usbhid/3-1:1.0', '../../../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0') +l('sys/bus/usb/drivers/usbhid/module', '../../../../module/usbhid') +d('sys/bus/usb/drivers/hub', 0o755) +l('sys/bus/usb/drivers/hub/3-0:1.0', '../../../../devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0') +l('sys/bus/usb/drivers/hub/1-0:1.0', '../../../../devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0') +l('sys/bus/usb/drivers/hub/4-0:1.0', '../../../../devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0') +l('sys/bus/usb/drivers/hub/module', '../../../../module/usbcore') +l('sys/bus/usb/drivers/hub/2-0:1.0', '../../../../devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0') +l('sys/bus/usb/drivers/hub/5-0:1.0', '../../../../devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0') +d('sys/bus/usb/drivers/usb', 0o755) +l('sys/bus/usb/drivers/usb/usb5', '../../../../devices/pci0000:00/0000:00:1d.7/usb5') +l('sys/bus/usb/drivers/usb/usb1', '../../../../devices/pci0000:00/0000:00:1d.0/usb1') +l('sys/bus/usb/drivers/usb/4-2', '../../../../devices/pci0000:00/0000:00:1d.3/usb4/4-2') +l('sys/bus/usb/drivers/usb/5-1', '../../../../devices/pci0000:00/0000:00:1d.7/usb5/5-1') +l('sys/bus/usb/drivers/usb/5-2', '../../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2') +l('sys/bus/usb/drivers/usb/4-1', '../../../../devices/pci0000:00/0000:00:1d.3/usb4/4-1') +l('sys/bus/usb/drivers/usb/module', '../../../../module/usbcore') +l('sys/bus/usb/drivers/usb/usb4', '../../../../devices/pci0000:00/0000:00:1d.3/usb4') +l('sys/bus/usb/drivers/usb/usb3', '../../../../devices/pci0000:00/0000:00:1d.2/usb3') +l('sys/bus/usb/drivers/usb/usb2', '../../../../devices/pci0000:00/0000:00:1d.1/usb2') +l('sys/bus/usb/drivers/usb/3-1', '../../../../devices/pci0000:00/0000:00:1d.2/usb3/3-1') +d('sys/bus/usb/drivers/usbfs', 0o755) +l('sys/bus/usb/drivers/usbfs/module', '../../../../module/usbcore') +d('sys/bus/usb/devices', 0o755) +l('sys/bus/usb/devices/4-1:1.3', '../../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3') +l('sys/bus/usb/devices/5-2:1.4', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4') +l('sys/bus/usb/devices/usb5', '../../../devices/pci0000:00/0000:00:1d.7/usb5') +l('sys/bus/usb/devices/4-1:1.0', '../../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0') +l('sys/bus/usb/devices/5-2:1.2', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2') +l('sys/bus/usb/devices/3-0:1.0', '../../../devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0') +l('sys/bus/usb/devices/usb1', '../../../devices/pci0000:00/0000:00:1d.0/usb1') +l('sys/bus/usb/devices/4-2', '../../../devices/pci0000:00/0000:00:1d.3/usb4/4-2') +l('sys/bus/usb/devices/5-2:1.1', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1') +l('sys/bus/usb/devices/1-0:1.0', '../../../devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0') +l('sys/bus/usb/devices/5-1', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-1') +l('sys/bus/usb/devices/5-2:1.10', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10') +l('sys/bus/usb/devices/4-0:1.0', '../../../devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0') +l('sys/bus/usb/devices/5-2:1.0', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0') +l('sys/bus/usb/devices/5-2', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2') +l('sys/bus/usb/devices/5-2:1.9', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9') +l('sys/bus/usb/devices/3-1:1.0', '../../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0') +l('sys/bus/usb/devices/5-2:1.13', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13') +l('sys/bus/usb/devices/5-2:1.5', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5') +l('sys/bus/usb/devices/4-1', '../../../devices/pci0000:00/0000:00:1d.3/usb4/4-1') +l('sys/bus/usb/devices/4-1:1.2', '../../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2') +l('sys/bus/usb/devices/usb4', '../../../devices/pci0000:00/0000:00:1d.3/usb4') +l('sys/bus/usb/devices/2-0:1.0', '../../../devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0') +l('sys/bus/usb/devices/5-2:1.11', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11') +l('sys/bus/usb/devices/usb3', '../../../devices/pci0000:00/0000:00:1d.2/usb3') +l('sys/bus/usb/devices/5-2:1.12', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12') +l('sys/bus/usb/devices/5-2:1.3', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3') +l('sys/bus/usb/devices/5-2:1.6', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6') +l('sys/bus/usb/devices/4-1:1.1', '../../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1') +l('sys/bus/usb/devices/5-1:1.0', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0') +l('sys/bus/usb/devices/5-0:1.0', '../../../devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0') +l('sys/bus/usb/devices/4-2:1.0', '../../../devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0') +l('sys/bus/usb/devices/usb2', '../../../devices/pci0000:00/0000:00:1d.1/usb2') +l('sys/bus/usb/devices/3-1', '../../../devices/pci0000:00/0000:00:1d.2/usb3/3-1') +d('sys/bus/pci', 0o755) +f('sys/bus/pci/drivers_autoprobe', 0o644, b'1\n') +d('sys/bus/pci/drivers', 0o755) +d('sys/bus/pci/drivers/pcieport-driver', 0o755) +l('sys/bus/pci/drivers/pcieport-driver/0000:00:1c.2', '../../../../devices/pci0000:00/0000:00:1c.2') +l('sys/bus/pci/drivers/pcieport-driver/0000:00:1c.1', '../../../../devices/pci0000:00/0000:00:1c.1') +l('sys/bus/pci/drivers/pcieport-driver/0000:00:1c.3', '../../../../devices/pci0000:00/0000:00:1c.3') +l('sys/bus/pci/drivers/pcieport-driver/0000:00:1c.0', '../../../../devices/pci0000:00/0000:00:1c.0') +l('sys/bus/pci/drivers/pcieport-driver/0000:00:01.0', '../../../../devices/pci0000:00/0000:00:01.0') +d('sys/bus/pci/drivers/uhci_hcd', 0o755) +l('sys/bus/pci/drivers/uhci_hcd/0000:00:1d.3', '../../../../devices/pci0000:00/0000:00:1d.3') +l('sys/bus/pci/drivers/uhci_hcd/module', '../../../../module/uhci_hcd') +l('sys/bus/pci/drivers/uhci_hcd/0000:00:1d.0', '../../../../devices/pci0000:00/0000:00:1d.0') +l('sys/bus/pci/drivers/uhci_hcd/0000:00:1d.2', '../../../../devices/pci0000:00/0000:00:1d.2') +l('sys/bus/pci/drivers/uhci_hcd/0000:00:1d.1', '../../../../devices/pci0000:00/0000:00:1d.1') +d('sys/bus/pci/drivers/HDA Intel', 0o755) +l('sys/bus/pci/drivers/HDA Intel/0000:00:1b.0', '../../../../devices/pci0000:00/0000:00:1b.0') +l('sys/bus/pci/drivers/HDA Intel/module', '../../../../module/snd_hda_intel') +d('sys/bus/pci/drivers/ata_piix', 0o755) +l('sys/bus/pci/drivers/ata_piix/0000:00:1f.1', '../../../../devices/pci0000:00/0000:00:1f.1') +d('sys/bus/pci/drivers/yenta_cardbus', 0o755) +l('sys/bus/pci/drivers/yenta_cardbus/module', '../../../../module/yenta_socket') +l('sys/bus/pci/drivers/yenta_cardbus/0000:15:00.0', '../../../../devices/pci0000:00/0000:00:1e.0/0000:15:00.0') +d('sys/bus/pci/drivers/e1000e', 0o755) +l('sys/bus/pci/drivers/e1000e/0000:02:00.0', '../../../../devices/pci0000:00/0000:00:1c.0/0000:02:00.0') +l('sys/bus/pci/drivers/e1000e/module', '../../../../module/e1000e') +d('sys/bus/pci/drivers/iwl3945', 0o755) +l('sys/bus/pci/drivers/iwl3945/module', '../../../../module/iwl3945') +l('sys/bus/pci/drivers/iwl3945/0000:03:00.0', '../../../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0') +d('sys/bus/pci/drivers/ehci_hcd', 0o755) +l('sys/bus/pci/drivers/ehci_hcd/module', '../../../../module/ehci_hcd') +d('sys/bus/pci/drivers/agpgart-intel', 0o755) +l('sys/bus/pci/drivers/agpgart-intel/module', '../../../../module/intel_agp') +d('sys/bus/pci/drivers/ahci', 0o755) +l('sys/bus/pci/drivers/ahci/module', '../../../../module/ahci') +l('sys/bus/pci/drivers/ahci/0000:00:1f.2', '../../../../devices/pci0000:00/0000:00:1f.2') +d('sys/bus/pci/devices', 0o755) +l('sys/bus/pci/devices/0000:00:1d.3', '../../../devices/pci0000:00/0000:00:1d.3') +l('sys/bus/pci/devices/0000:00:1c.2', '../../../devices/pci0000:00/0000:00:1c.2') +l('sys/bus/pci/devices/0000:00:1b.0', '../../../devices/pci0000:00/0000:00:1b.0') +l('sys/bus/pci/devices/0000:02:00.0', '../../../devices/pci0000:00/0000:00:1c.0/0000:02:00.0') +l('sys/bus/pci/devices/0000:00:1c.1', '../../../devices/pci0000:00/0000:00:1c.1') +l('sys/bus/pci/devices/0000:00:00.0', '../../../devices/pci0000:00/0000:00:00.0') +l('sys/bus/pci/devices/0000:01:00.0', '../../../devices/pci0000:00/0000:00:01.0/0000:01:00.0') +l('sys/bus/pci/devices/0000:00:1c.3', '../../../devices/pci0000:00/0000:00:1c.3') +l('sys/bus/pci/devices/0000:00:1f.0', '../../../devices/pci0000:00/0000:00:1f.0') +l('sys/bus/pci/devices/0000:00:1c.0', '../../../devices/pci0000:00/0000:00:1c.0') +l('sys/bus/pci/devices/0000:15:00.0', '../../../devices/pci0000:00/0000:00:1e.0/0000:15:00.0') +l('sys/bus/pci/devices/0000:00:1f.3', '../../../devices/pci0000:00/0000:00:1f.3') +l('sys/bus/pci/devices/0000:00:1d.0', '../../../devices/pci0000:00/0000:00:1d.0') +l('sys/bus/pci/devices/0000:00:1f.2', '../../../devices/pci0000:00/0000:00:1f.2') +l('sys/bus/pci/devices/0000:00:1d.2', '../../../devices/pci0000:00/0000:00:1d.2') +l('sys/bus/pci/devices/0000:03:00.0', '../../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0') +l('sys/bus/pci/devices/0000:00:01.0', '../../../devices/pci0000:00/0000:00:01.0') +l('sys/bus/pci/devices/0000:00:1f.1', '../../../devices/pci0000:00/0000:00:1f.1') +l('sys/bus/pci/devices/0000:00:1e.0', '../../../devices/pci0000:00/0000:00:1e.0') +l('sys/bus/pci/devices/0000:00:1d.1', '../../../devices/pci0000:00/0000:00:1d.1') +d('sys/bus/pnp', 0o755) +f('sys/bus/pnp/drivers_autoprobe', 0o644, b'1\n') +d('sys/bus/pnp/drivers', 0o755) +d('sys/bus/pnp/drivers/system', 0o755) +l('sys/bus/pnp/drivers/system/00:02', '../../../../devices/pnp0/00:02') +l('sys/bus/pnp/drivers/system/00:00', '../../../../devices/pnp0/00:00') +d('sys/bus/pnp/drivers/i8042 kbd', 0o755) +l('sys/bus/pnp/drivers/i8042 kbd/00:08', '../../../../devices/pnp0/00:08') +d('sys/bus/pnp/drivers/rtc_cmos', 0o755) +l('sys/bus/pnp/drivers/rtc_cmos/00:07', '../../../../devices/pnp0/00:07') +d('sys/bus/pnp/drivers/i8042 aux', 0o755) +l('sys/bus/pnp/drivers/i8042 aux/00:09', '../../../../devices/pnp0/00:09') +d('sys/bus/pnp/devices', 0o755) +l('sys/bus/pnp/devices/00:04', '../../../devices/pnp0/00:04') +l('sys/bus/pnp/devices/00:0a', '../../../devices/pnp0/00:0a') +l('sys/bus/pnp/devices/00:03', '../../../devices/pnp0/00:03') +l('sys/bus/pnp/devices/00:02', '../../../devices/pnp0/00:02') +l('sys/bus/pnp/devices/00:00', '../../../devices/pnp0/00:00') +l('sys/bus/pnp/devices/00:09', '../../../devices/pnp0/00:09') +l('sys/bus/pnp/devices/00:07', '../../../devices/pnp0/00:07') +l('sys/bus/pnp/devices/00:06', '../../../devices/pnp0/00:06') +l('sys/bus/pnp/devices/00:08', '../../../devices/pnp0/00:08') +l('sys/bus/pnp/devices/00:05', '../../../devices/pnp0/00:05') +l('sys/bus/pnp/devices/00:01', '../../../devices/pnp0/00:01') +d('sys/bus/pcmcia', 0o755) +f('sys/bus/pcmcia/drivers_autoprobe', 0o644, b'1\n') +d('sys/bus/platform', 0o755) +f('sys/bus/platform/drivers_autoprobe', 0o644, b'1\n') +d('sys/bus/platform/drivers', 0o755) +d('sys/bus/platform/drivers/pcspkr', 0o755) +l('sys/bus/platform/drivers/pcspkr/pcspkr', '../../../../devices/platform/pcspkr') +l('sys/bus/platform/drivers/pcspkr/module', '../../../../module/pcspkr') +d('sys/bus/platform/drivers/serial8250', 0o755) +l('sys/bus/platform/drivers/serial8250/serial8250', '../../../../devices/platform/serial8250') +d('sys/bus/platform/drivers/thinkpad_acpi', 0o755) +l('sys/bus/platform/drivers/thinkpad_acpi/module', '../../../../module/thinkpad_acpi') +l('sys/bus/platform/drivers/thinkpad_acpi/thinkpad_acpi', '../../../../devices/platform/thinkpad_acpi') +f('sys/bus/platform/drivers/thinkpad_acpi/version', 0o644, b'ThinkPad ACPI Extras v0.21\n') +f('sys/bus/platform/drivers/thinkpad_acpi/debug_level', 0o644, b'0x0000\n') +f('sys/bus/platform/drivers/thinkpad_acpi/interface_version', 0o644, b'0x00020200\n') +d('sys/bus/platform/drivers/vesafb', 0o755) +l('sys/bus/platform/drivers/vesafb/vesafb.0', '../../../../devices/platform/vesafb.0') +d('sys/bus/platform/drivers/thinkpad_hwmon', 0o755) +l('sys/bus/platform/drivers/thinkpad_hwmon/module', '../../../../module/thinkpad_acpi') +l('sys/bus/platform/drivers/thinkpad_hwmon/thinkpad_hwmon', '../../../../devices/platform/thinkpad_hwmon') +f('sys/bus/platform/drivers/thinkpad_hwmon/version', 0o644, b'ThinkPad ACPI Extras v0.21\n') +f('sys/bus/platform/drivers/thinkpad_hwmon/fan_watchdog', 0o644, b'0\n') +f('sys/bus/platform/drivers/thinkpad_hwmon/debug_level', 0o644, b'0x0000\n') +f('sys/bus/platform/drivers/thinkpad_hwmon/interface_version', 0o644, b'0x00020200\n') +d('sys/bus/platform/drivers/i8042', 0o755) +l('sys/bus/platform/drivers/i8042/i8042', '../../../../devices/platform/i8042') +d('sys/bus/platform/devices', 0o755) +l('sys/bus/platform/devices/pcspkr', '../../../devices/platform/pcspkr') +l('sys/bus/platform/devices/vesafb.0', '../../../devices/platform/vesafb.0') +l('sys/bus/platform/devices/dock.0', '../../../devices/platform/dock.0') +l('sys/bus/platform/devices/serial8250', '../../../devices/platform/serial8250') +l('sys/bus/platform/devices/thinkpad_acpi', '../../../devices/platform/thinkpad_acpi') +l('sys/bus/platform/devices/thinkpad_hwmon', '../../../devices/platform/thinkpad_hwmon') +l('sys/bus/platform/devices/microcode', '../../../devices/platform/microcode') +l('sys/bus/platform/devices/i8042', '../../../devices/platform/i8042') +d('sys/fs', 0o775) +d('sys/fs/fuse', 0o775) +d('sys/fs/fuse/connections', 0o775) +d('sys/fs/fuse/connections/16', 0o775) +f('sys/fs/fuse/connections/16/waiting', 0o664, b'0\n') +f('sys/fs/fuse/connections/16/abort', 0o664, b'') +d('sys/dev', 0o755) +d('sys/dev/char', 0o755) +l('sys/dev/char/4:39', '../../devices/virtual/tty/tty39') +l('sys/dev/char/116:33', '../../devices/virtual/sound/timer') +l('sys/dev/char/10:229', '../../devices/virtual/misc/fuse') +l('sys/dev/char/4:23', '../../devices/virtual/tty/tty23') +l('sys/dev/char/4:19', '../../devices/virtual/tty/tty19') +l('sys/dev/char/252:1', '../../devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00') +l('sys/dev/char/4:48', '../../devices/virtual/tty/tty48') +l('sys/dev/char/7:129', '../../devices/virtual/vc/vcsa1') +l('sys/dev/char/4:34', '../../devices/virtual/tty/tty34') +l('sys/dev/char/189:0', '../../devices/pci0000:00/0000:00:1d.0/usb1') +l('sys/dev/char/4:61', '../../devices/virtual/tty/tty61') +l('sys/dev/char/4:5', '../../devices/virtual/tty/tty5') +l('sys/dev/char/10:1', '../../devices/virtual/misc/psaux') +l('sys/dev/char/4:47', '../../devices/virtual/tty/tty47') +l('sys/dev/char/254:2', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0') +l('sys/dev/char/252:7', '../../devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00') +l('sys/dev/char/7:1', '../../devices/virtual/vc/vcs1') +l('sys/dev/char/4:37', '../../devices/virtual/tty/tty37') +l('sys/dev/char/4:3', '../../devices/virtual/tty/tty3') +l('sys/dev/char/252:3', '../../devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00') +l('sys/dev/char/1:3', '../../devices/virtual/mem/null') +l('sys/dev/char/14:12', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/adsp') +l('sys/dev/char/7:0', '../../devices/virtual/vc/vcs') +l('sys/dev/char/252:14', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02') +l('sys/dev/char/4:52', '../../devices/virtual/tty/tty52') +l('sys/dev/char/252:18', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04') +l('sys/dev/char/1:5', '../../devices/virtual/mem/zero') +l('sys/dev/char/13:66', '../../devices/platform/pcspkr/input/input2/event2') +l('sys/dev/char/10:223', '../../devices/virtual/misc/uinput') +l('sys/dev/char/7:2', '../../devices/virtual/vc/vcs2') +l('sys/dev/char/4:40', '../../devices/virtual/tty/tty40') +l('sys/dev/char/4:31', '../../devices/virtual/tty/tty31') +l('sys/dev/char/252:21', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02') +l('sys/dev/char/4:11', '../../devices/virtual/tty/tty11') +l('sys/dev/char/4:17', '../../devices/virtual/tty/tty17') +l('sys/dev/char/252:31', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84') +l('sys/dev/char/189:256', '../../devices/pci0000:00/0000:00:1d.2/usb3') +l('sys/dev/char/252:5', '../../devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00') +l('sys/dev/char/7:4', '../../devices/virtual/vc/vcs4') +l('sys/dev/char/4:38', '../../devices/virtual/tty/tty38') +l('sys/dev/char/4:66', '../../devices/platform/serial8250/tty/ttyS2') +l('sys/dev/char/4:0', '../../devices/virtual/tty/tty0') +l('sys/dev/char/21:0', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_generic/sg0') +l('sys/dev/char/7:134', '../../devices/virtual/vc/vcsa6') +l('sys/dev/char/116:24', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c') +l('sys/dev/char/4:29', '../../devices/virtual/tty/tty29') +l('sys/dev/char/21:2', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg2') +l('sys/dev/char/4:27', '../../devices/virtual/tty/tty27') +l('sys/dev/char/4:21', '../../devices/virtual/tty/tty21') +l('sys/dev/char/13:64', '../../devices/platform/i8042/serio0/input/input0/event0') +l('sys/dev/char/252:30', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83') +l('sys/dev/char/4:51', '../../devices/virtual/tty/tty51') +l('sys/dev/char/254:1', '../../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0') +l('sys/dev/char/4:18', '../../devices/virtual/tty/tty18') +l('sys/dev/char/7:3', '../../devices/virtual/vc/vcs3') +l('sys/dev/char/252:32', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02') +l('sys/dev/char/252:27', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81') +l('sys/dev/char/252:12', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81') +l('sys/dev/char/1:1', '../../devices/virtual/mem/mem') +l('sys/dev/char/189:386', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-2') +l('sys/dev/char/10:62', '../../devices/virtual/misc/network_latency') +l('sys/dev/char/252:4', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81') +l('sys/dev/char/5:1', '../../devices/virtual/tty/console') +l('sys/dev/char/1:7', '../../devices/virtual/mem/full') +l('sys/dev/char/7:5', '../../devices/virtual/vc/vcs5') +l('sys/dev/char/4:4', '../../devices/virtual/tty/tty4') +l('sys/dev/char/4:15', '../../devices/virtual/tty/tty15') +l('sys/dev/char/4:9', '../../devices/virtual/tty/tty9') +l('sys/dev/char/4:20', '../../devices/virtual/tty/tty20') +l('sys/dev/char/10:228', '../../devices/virtual/misc/hpet') +l('sys/dev/char/4:59', '../../devices/virtual/tty/tty59') +l('sys/dev/char/252:2', '../../devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81') +l('sys/dev/char/4:7', '../../devices/virtual/tty/tty7') +l('sys/dev/char/4:35', '../../devices/virtual/tty/tty35') +l('sys/dev/char/254:0', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0') +l('sys/dev/char/189:128', '../../devices/pci0000:00/0000:00:1d.1/usb2') +l('sys/dev/char/10:184', '../../devices/virtual/misc/microcode') +l('sys/dev/char/7:131', '../../devices/virtual/vc/vcsa3') +l('sys/dev/char/116:1', '../../devices/virtual/sound/seq') +l('sys/dev/char/252:17', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84') +l('sys/dev/char/10:61', '../../devices/virtual/misc/network_throughput') +l('sys/dev/char/7:130', '../../devices/virtual/vc/vcsa2') +l('sys/dev/char/252:0', '../../devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81') +l('sys/dev/char/4:33', '../../devices/virtual/tty/tty33') +l('sys/dev/char/4:10', '../../devices/virtual/tty/tty10') +l('sys/dev/char/13:71', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/event7') +l('sys/dev/char/252:10', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81') +l('sys/dev/char/253:0', '../../devices/pnp0/00:07/rtc/rtc0') +l('sys/dev/char/252:19', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00') +l('sys/dev/char/7:10', '../../devices/virtual/vc/vcs10') +l('sys/dev/char/4:42', '../../devices/virtual/tty/tty42') +l('sys/dev/char/10:144', '../../devices/virtual/misc/nvram') +l('sys/dev/char/4:63', '../../devices/virtual/tty/tty63') +l('sys/dev/char/252:25', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81') +l('sys/dev/char/189:520', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2') +l('sys/dev/char/4:55', '../../devices/virtual/tty/tty55') +l('sys/dev/char/13:33', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/mouse1') +l('sys/dev/char/13:70', '../../devices/virtual/input/input6/event6') +l('sys/dev/char/252:29', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01') +l('sys/dev/char/4:45', '../../devices/virtual/tty/tty45') +l('sys/dev/char/4:56', '../../devices/virtual/tty/tty56') +l('sys/dev/char/10:60', '../../devices/virtual/misc/device-mapper') +l('sys/dev/char/5:2', '../../devices/virtual/tty/ptmx') +l('sys/dev/char/252:8', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81') +l('sys/dev/char/14:3', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/dsp') +l('sys/dev/char/13:68', '../../devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/event4') +l('sys/dev/char/13:67', '../../devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/event3') +l('sys/dev/char/1:4', '../../devices/virtual/mem/port') +l('sys/dev/char/116:0', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/controlC0') +l('sys/dev/char/4:46', '../../devices/virtual/tty/tty46') +l('sys/dev/char/4:41', '../../devices/virtual/tty/tty41') +l('sys/dev/char/189:512', '../../devices/pci0000:00/0000:00:1d.7/usb5') +l('sys/dev/char/4:62', '../../devices/virtual/tty/tty62') +l('sys/dev/char/252:15', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83') +l('sys/dev/char/7:133', '../../devices/virtual/vc/vcsa5') +l('sys/dev/char/4:2', '../../devices/virtual/tty/tty2') +l('sys/dev/char/1:8', '../../devices/virtual/mem/random') +l('sys/dev/char/7:138', '../../devices/virtual/vc/vcsa10') +l('sys/dev/char/4:64', '../../devices/platform/serial8250/tty/ttyS0') +l('sys/dev/char/4:1', '../../devices/virtual/tty/tty1') +l('sys/dev/char/4:28', '../../devices/virtual/tty/tty28') +l('sys/dev/char/13:32', '../../devices/platform/i8042/serio1/input/input1/mouse0') +l('sys/dev/char/4:44', '../../devices/virtual/tty/tty44') +l('sys/dev/char/4:36', '../../devices/virtual/tty/tty36') +l('sys/dev/char/4:43', '../../devices/virtual/tty/tty43') +l('sys/dev/char/7:128', '../../devices/virtual/vc/vcsa') +l('sys/dev/char/4:60', '../../devices/virtual/tty/tty60') +l('sys/dev/char/7:135', '../../devices/virtual/vc/vcsa7') +l('sys/dev/char/4:6', '../../devices/virtual/tty/tty6') +l('sys/dev/char/4:49', '../../devices/virtual/tty/tty49') +l('sys/dev/char/189:518', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1') +l('sys/dev/char/29:0', '../../devices/platform/vesafb.0/graphics/fb0') +l('sys/dev/char/252:23', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00') +l('sys/dev/char/10:227', '../../devices/virtual/misc/mcelog') +l('sys/dev/char/4:14', '../../devices/virtual/tty/tty14') +l('sys/dev/char/4:54', '../../devices/virtual/tty/tty54') +l('sys/dev/char/7:132', '../../devices/virtual/vc/vcsa4') +l('sys/dev/char/5:0', '../../devices/virtual/tty/tty') +l('sys/dev/char/252:26', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00') +l('sys/dev/char/1:2', '../../devices/virtual/mem/kmem') +l('sys/dev/char/189:259', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-1') +l('sys/dev/char/252:11', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02') +l('sys/dev/char/4:26', '../../devices/virtual/tty/tty26') +l('sys/dev/char/252:33', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00') +l('sys/dev/char/4:22', '../../devices/virtual/tty/tty22') +l('sys/dev/char/10:63', '../../devices/virtual/misc/cpu_dma_latency') +l('sys/dev/char/4:13', '../../devices/virtual/tty/tty13') +l('sys/dev/char/116:17', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D1p') +l('sys/dev/char/116:16', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0p') +l('sys/dev/char/252:16', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03') +l('sys/dev/char/4:8', '../../devices/virtual/tty/tty8') +l('sys/dev/char/252:28', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82') +l('sys/dev/char/21:1', '../../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_generic/sg1') +l('sys/dev/char/4:24', '../../devices/virtual/tty/tty24') +l('sys/dev/char/7:7', '../../devices/virtual/vc/vcs7') +l('sys/dev/char/252:20', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81') +l('sys/dev/char/166:0', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0') +l('sys/dev/char/4:58', '../../devices/virtual/tty/tty58') +l('sys/dev/char/4:57', '../../devices/virtual/tty/tty57') +l('sys/dev/char/189:384', '../../devices/pci0000:00/0000:00:1d.3/usb4') +l('sys/dev/char/4:50', '../../devices/virtual/tty/tty50') +l('sys/dev/char/7:6', '../../devices/virtual/vc/vcs6') +l('sys/dev/char/4:25', '../../devices/virtual/tty/tty25') +l('sys/dev/char/4:16', '../../devices/virtual/tty/tty16') +l('sys/dev/char/4:65', '../../devices/platform/serial8250/tty/ttyS1') +l('sys/dev/char/13:65', '../../devices/platform/i8042/serio1/input/input1/event1') +l('sys/dev/char/13:69', '../../devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/event5') +l('sys/dev/char/252:22', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83') +l('sys/dev/char/1:11', '../../devices/virtual/mem/kmsg') +l('sys/dev/char/189:385', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1') +l('sys/dev/char/4:12', '../../devices/virtual/tty/tty12') +l('sys/dev/char/252:13', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82') +l('sys/dev/char/1:9', '../../devices/virtual/mem/urandom') +l('sys/dev/char/4:67', '../../devices/platform/serial8250/tty/ttyS3') +l('sys/dev/char/13:63', '../../devices/virtual/input/mice') +l('sys/dev/char/252:24', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00') +l('sys/dev/char/252:9', '../../devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00') +l('sys/dev/char/4:53', '../../devices/virtual/tty/tty53') +l('sys/dev/char/4:30', '../../devices/virtual/tty/tty30') +l('sys/dev/char/14:4', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/audio') +l('sys/dev/char/14:0', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/mixer') +l('sys/dev/char/252:6', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81') +l('sys/dev/char/4:32', '../../devices/virtual/tty/tty32') +d('sys/dev/block', 0o755) +l('sys/dev/block/7:1', '../../devices/virtual/block/loop1') +l('sys/dev/block/7:0', '../../devices/virtual/block/loop0') +l('sys/dev/block/8:17', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1') +l('sys/dev/block/7:2', '../../devices/virtual/block/loop2') +l('sys/dev/block/7:4', '../../devices/virtual/block/loop4') +l('sys/dev/block/8:8', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8') +l('sys/dev/block/7:3', '../../devices/virtual/block/loop3') +l('sys/dev/block/11:0', '../../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0') +l('sys/dev/block/7:5', '../../devices/virtual/block/loop5') +l('sys/dev/block/8:5', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5') +l('sys/dev/block/8:10', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10') +l('sys/dev/block/8:0', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda') +l('sys/dev/block/8:9', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9') +l('sys/dev/block/8:7', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7') +l('sys/dev/block/8:16', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb') +l('sys/dev/block/9:0', '../../devices/virtual/block/md0') +l('sys/dev/block/7:7', '../../devices/virtual/block/loop7') +l('sys/dev/block/8:6', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6') +l('sys/dev/block/7:6', '../../devices/virtual/block/loop6') +l('sys/dev/block/8:1', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1') +d('sys/module', 0o775) +d('sys/module/arc4', 0o775) +f('sys/module/arc4/initstate', 0o664, b'live\n') +f('sys/module/arc4/srcversion', 0o664, b'0E7B177AF22D87B5B21A577\n') +f('sys/module/arc4/refcnt', 0o664, b'2\n') +d('sys/module/arc4/sections', 0o775) +f('sys/module/arc4/sections/.exit.text', 0o664, b'0xffffffffa006b0dc\n') +f('sys/module/arc4/sections/.note.gnu.build-id', 0o664, b'0xffffffffa006b0f0\n') +f('sys/module/arc4/sections/.strtab', 0o664, b'0xffffffffa006b400\n') +f('sys/module/arc4/sections/.bss', 0o664, b'0xffffffffa006ba00\n') +f('sys/module/arc4/sections/.text', 0o664, b'0xffffffffa006b000\n') +f('sys/module/arc4/sections/.init.text', 0o664, b'0xffffffffa009a000\n') +f('sys/module/arc4/sections/.data', 0o664, b'0xffffffffa006b520\n') +f('sys/module/arc4/sections/.symtab', 0o664, b'0xffffffffa006b118\n') +f('sys/module/arc4/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa006b640\n') +d('sys/module/arc4/notes', 0o775) +f('sys/module/arc4/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00[P \tR\xc2\xa7\xdd\xf0H\xaa\x06\x1a,\xb3\xa1\xa4\x9a\x13G') +d('sys/module/vt', 0o775) +d('sys/module/vt/parameters', 0o775) +f('sys/module/vt/parameters/default_grn', 0o664, b'0,0,170,85,0,0,170,170,85,85,255,255,85,85,255,255\n') +f('sys/module/vt/parameters/default_red', 0o664, b'0,170,0,170,0,170,0,170,85,255,85,255,85,255,85,255\n') +f('sys/module/vt/parameters/italic', 0o664, b'2\n') +f('sys/module/vt/parameters/underline', 0o664, b'3\n') +f('sys/module/vt/parameters/default_blu', 0o664, b'0,0,0,0,170,170,170,170,85,85,85,85,255,255,255,255\n') +f('sys/module/vt/parameters/default_utf8', 0o664, b'1\n') +d('sys/module/cdrom', 0o775) +f('sys/module/cdrom/initstate', 0o664, b'live\n') +f('sys/module/cdrom/srcversion', 0o664, b'D868CCB0789DA27F51280A8\n') +f('sys/module/cdrom/refcnt', 0o664, b'1\n') +d('sys/module/cdrom/holders', 0o775) +l('sys/module/cdrom/holders/sr_mod', '../../sr_mod') +d('sys/module/cdrom/sections', 0o775) +f('sys/module/cdrom/sections/__ksymtab_strings', 0o664, b'0xffffffffa002fe20\n') +f('sys/module/cdrom/sections/.exit.text', 0o664, b'0xffffffffa002e0f8\n') +f('sys/module/cdrom/sections/.note.gnu.build-id', 0o664, b'0xffffffffa002e120\n') +f('sys/module/cdrom/sections/.strtab', 0o664, b'0xffffffffa0030f60\n') +f('sys/module/cdrom/sections/__ksymtab', 0o664, b'0xffffffffa002fc10\n') +f('sys/module/cdrom/sections/.rodata', 0o664, b'0xffffffffa002e160\n') +f('sys/module/cdrom/sections/__param', 0o664, b'0xffffffffa002fd30\n') +f('sys/module/cdrom/sections/.bss', 0o664, b'0xffffffffa0032380\n') +f('sys/module/cdrom/sections/.text', 0o664, b'0xffffffffa0029000\n') +f('sys/module/cdrom/sections/.init.text', 0o664, b'0xffffffffa0034000\n') +f('sys/module/cdrom/sections/__kcrctab', 0o664, b'0xffffffffa002fcd0\n') +f('sys/module/cdrom/sections/.data', 0o664, b'0xffffffffa0031b80\n') +f('sys/module/cdrom/sections/.symtab', 0o664, b'0xffffffffa002fef8\n') +f('sys/module/cdrom/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0031fc0\n') +f('sys/module/cdrom/sections/.rodata.str1.1', 0o664, b'0xffffffffa002f896\n') +d('sys/module/cdrom/notes', 0o775) +f('sys/module/cdrom/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00C\x03\x04\xe9\x8a\x17\x19\x8b\xc7Y\xea\x1a\xa35\x85K\x9e\x1e\xf8=') +d('sys/module/rfkill', 0o775) +f('sys/module/rfkill/version', 0o664, b'1.0\n') +f('sys/module/rfkill/initstate', 0o664, b'live\n') +f('sys/module/rfkill/srcversion', 0o664, b'6B4E68548C57FD365EB4E71\n') +f('sys/module/rfkill/refcnt', 0o664, b'2\n') +d('sys/module/rfkill/holders', 0o775) +l('sys/module/rfkill/holders/thinkpad_acpi', '../../thinkpad_acpi') +d('sys/module/rfkill/parameters', 0o775) +f('sys/module/rfkill/parameters/default_state', 0o664, b'1\n') +d('sys/module/rfkill/sections', 0o775) +f('sys/module/rfkill/sections/__ksymtab_gpl', 0o664, b'0xffffffffa01d9f70\n') +f('sys/module/rfkill/sections/.smp_locks', 0o664, b'0xffffffffa01d9e80\n') +f('sys/module/rfkill/sections/__bug_table', 0o664, b'0xffffffffa01d9e36\n') +f('sys/module/rfkill/sections/__ksymtab_strings', 0o664, b'0xffffffffa01d9fe0\n') +f('sys/module/rfkill/sections/.exit.text', 0o664, b'0xffffffffa01d9c88\n') +f('sys/module/rfkill/sections/.note.gnu.build-id', 0o664, b'0xffffffffa01d9cb0\n') +f('sys/module/rfkill/sections/.strtab', 0o664, b'0xffffffffa01dae08\n') +f('sys/module/rfkill/sections/__ksymtab', 0o664, b'0xffffffffa01d9ee0\n') +f('sys/module/rfkill/sections/.rodata', 0o664, b'0xffffffffa01d9cd8\n') +f('sys/module/rfkill/sections/__param', 0o664, b'0xffffffffa01d9fb8\n') +f('sys/module/rfkill/sections/.bss', 0o664, b'0xffffffffa01dbe00\n') +f('sys/module/rfkill/sections/.text', 0o664, b'0xffffffffa01d9000\n') +f('sys/module/rfkill/sections/.init.text', 0o664, b'0xffffffffa009a000\n') +f('sys/module/rfkill/sections/__kcrctab', 0o664, b'0xffffffffa01d9f40\n') +f('sys/module/rfkill/sections/.data', 0o664, b'0xffffffffa01db780\n') +f('sys/module/rfkill/sections/.symtab', 0o664, b'0xffffffffa01da088\n') +f('sys/module/rfkill/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa01dba40\n') +f('sys/module/rfkill/sections/.rodata.str1.1', 0o664, b'0xffffffffa01d9d36\n') +f('sys/module/rfkill/sections/__kcrctab_gpl', 0o664, b'0xffffffffa01d9fa0\n') +d('sys/module/rfkill/notes', 0o775) +f('sys/module/rfkill/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xd1\x1fs\x98\x9b\x97\xc4\xec\x9dd\xac:\x94m\x1e\xc0Y\xcfd"') +d('sys/module/uinput', 0o775) +f('sys/module/uinput/version', 0o664, b'0.3\n') +f('sys/module/uinput/initstate', 0o664, b'live\n') +f('sys/module/uinput/srcversion', 0o664, b'2C3E0DB9E2496AD70174B85\n') +f('sys/module/uinput/refcnt', 0o664, b'0\n') +d('sys/module/uinput/sections', 0o775) +f('sys/module/uinput/sections/.smp_locks', 0o664, b'0xffffffffa0206448\n') +f('sys/module/uinput/sections/.exit.text', 0o664, b'0xffffffffa0206278\n') +f('sys/module/uinput/sections/.note.gnu.build-id', 0o664, b'0xffffffffa020628c\n') +f('sys/module/uinput/sections/.strtab', 0o664, b'0xffffffffa0206c88\n') +f('sys/module/uinput/sections/.rodata', 0o664, b'0xffffffffa02062c0\n') +f('sys/module/uinput/sections/.bss', 0o664, b'0xffffffffa02074c0\n') +f('sys/module/uinput/sections/.text', 0o664, b'0xffffffffa0205000\n') +f('sys/module/uinput/sections/.init.text', 0o664, b'0xffffffffa0070000\n') +f('sys/module/uinput/sections/.data', 0o664, b'0xffffffffa02070c0\n') +f('sys/module/uinput/sections/.symtab', 0o664, b'0xffffffffa0206490\n') +f('sys/module/uinput/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0207100\n') +f('sys/module/uinput/sections/.rodata.str1.1', 0o664, b'0xffffffffa0206398\n') +d('sys/module/uinput/notes', 0o775) +f('sys/module/uinput/notes/.note.gnu.build-id', 0o664, b"\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00'\n{\xdf\xe9m\x80\xea\xa8k\x8f=\x90\x8c\xe1\xf7{\x06\x15S") +d('sys/module/fuse', 0o775) +f('sys/module/fuse/initstate', 0o664, b'live\n') +f('sys/module/fuse/srcversion', 0o664, b'A6C92EE44A51B1B0DC4377D\n') +f('sys/module/fuse/refcnt', 0o664, b'3\n') +d('sys/module/fuse/sections', 0o775) +f('sys/module/fuse/sections/.smp_locks', 0o664, b'0xffffffffa0249d78\n') +f('sys/module/fuse/sections/__bug_table', 0o664, b'0xffffffffa024a032\n') +f('sys/module/fuse/sections/.exit.text', 0o664, b'0xffffffffa02493d0\n') +f('sys/module/fuse/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0249414\n') +f('sys/module/fuse/sections/.strtab', 0o664, b'0xffffffffa024c4e8\n') +f('sys/module/fuse/sections/.rodata', 0o664, b'0xffffffffa0249440\n') +f('sys/module/fuse/sections/.bss', 0o664, b'0xffffffffa024e300\n') +f('sys/module/fuse/sections/.text', 0o664, b'0xffffffffa0240000\n') +f('sys/module/fuse/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/fuse/sections/.data', 0o664, b'0xffffffffa024dba0\n') +f('sys/module/fuse/sections/.symtab', 0o664, b'0xffffffffa024a208\n') +f('sys/module/fuse/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa024df40\n') +f('sys/module/fuse/sections/.rodata.str1.1', 0o664, b'0xffffffffa0249e50\n') +d('sys/module/fuse/notes', 0o775) +f('sys/module/fuse/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\x7fh\xfe:\x1f\xc6\xddW\x96\x80\x16\x9fK\x7f\xba,\x8a\xc6\xf6E') +d('sys/module/hid', 0o775) +d('sys/module/hid/parameters', 0o775) +f('sys/module/hid/parameters/pb_fnmode', 0o664, b'1\n') +d('sys/module/uhci_hcd', 0o775) +f('sys/module/uhci_hcd/initstate', 0o664, b'live\n') +f('sys/module/uhci_hcd/srcversion', 0o664, b'E3F4B6BEC99D6670259FCC9\n') +f('sys/module/uhci_hcd/refcnt', 0o664, b'0\n') +d('sys/module/uhci_hcd/drivers', 0o775) +l('sys/module/uhci_hcd/drivers/pci:uhci_hcd', '../../../bus/pci/drivers/uhci_hcd') +d('sys/module/uhci_hcd/parameters', 0o775) +f('sys/module/uhci_hcd/parameters/ignore_oc', 0o664, b'N\n') +d('sys/module/uhci_hcd/sections', 0o775) +f('sys/module/uhci_hcd/sections/.smp_locks', 0o664, b'0xffffffffa00c6850\n') +f('sys/module/uhci_hcd/sections/.exit.text', 0o664, b'0xffffffffa00c621c\n') +f('sys/module/uhci_hcd/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00c6254\n') +f('sys/module/uhci_hcd/sections/.strtab', 0o664, b'0xffffffffa00c7690\n') +f('sys/module/uhci_hcd/sections/.rodata', 0o664, b'0xffffffffa00c6280\n') +f('sys/module/uhci_hcd/sections/__param', 0o664, b'0xffffffffa00c6888\n') +f('sys/module/uhci_hcd/sections/.bss', 0o664, b'0xffffffffa00c8400\n') +f('sys/module/uhci_hcd/sections/.text', 0o664, b'0xffffffffa00c2000\n') +f('sys/module/uhci_hcd/sections/.init.text', 0o664, b'0xffffffffa0027000\n') +f('sys/module/uhci_hcd/sections/.data', 0o664, b'0xffffffffa00c7ee0\n') +f('sys/module/uhci_hcd/sections/.symtab', 0o664, b'0xffffffffa00c68b0\n') +f('sys/module/uhci_hcd/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00c8040\n') +f('sys/module/uhci_hcd/sections/.rodata.str1.1', 0o664, b'0xffffffffa00c67d2\n') +d('sys/module/uhci_hcd/notes', 0o775) +f('sys/module/uhci_hcd/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00t\xd0\xa5\xd2A\xa2\x874\x12\xb5\xf6\x9c\xff\xb9\xee`\x8d\x9f[\x04') +d('sys/module/crypto_blkcipher', 0o775) +f('sys/module/crypto_blkcipher/initstate', 0o664, b'live\n') +f('sys/module/crypto_blkcipher/srcversion', 0o664, b'723F00BD2391209F4D65272\n') +f('sys/module/crypto_blkcipher/refcnt', 0o664, b'1\n') +d('sys/module/crypto_blkcipher/holders', 0o775) +l('sys/module/crypto_blkcipher/holders/ecb', '../../ecb') +d('sys/module/crypto_blkcipher/sections', 0o775) +f('sys/module/crypto_blkcipher/sections/__ksymtab_gpl', 0o664, b'0xffffffffa01f1610\n') +f('sys/module/crypto_blkcipher/sections/.smp_locks', 0o664, b'0xffffffffa01f18c0\n') +f('sys/module/crypto_blkcipher/sections/__bug_table', 0o664, b'0xffffffffa01f185f\n') +f('sys/module/crypto_blkcipher/sections/__ksymtab_strings', 0o664, b'0xffffffffa01f1748\n') +f('sys/module/crypto_blkcipher/sections/.exit.text', 0o664, b'0xffffffffa01f138c\n') +f('sys/module/crypto_blkcipher/sections/.note.gnu.build-id', 0o664, b'0xffffffffa01f13b0\n') +f('sys/module/crypto_blkcipher/sections/.strtab', 0o664, b'0xffffffffa01f2b10\n') +f('sys/module/crypto_blkcipher/sections/.rodata', 0o664, b'0xffffffffa01f13e0\n') +f('sys/module/crypto_blkcipher/sections/.bss', 0o664, b'0xffffffffa01f3ec0\n') +f('sys/module/crypto_blkcipher/sections/.text', 0o664, b'0xffffffffa01ef000\n') +f('sys/module/crypto_blkcipher/sections/.init.text', 0o664, b'0xffffffffa0027000\n') +f('sys/module/crypto_blkcipher/sections/.data', 0o664, b'0xffffffffa01f39e0\n') +f('sys/module/crypto_blkcipher/sections/.symtab', 0o664, b'0xffffffffa01f18f8\n') +f('sys/module/crypto_blkcipher/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa01f3b00\n') +f('sys/module/crypto_blkcipher/sections/.rodata.str1.1', 0o664, b'0xffffffffa01f1440\n') +f('sys/module/crypto_blkcipher/sections/__kcrctab_gpl', 0o664, b'0xffffffffa01f16e0\n') +d('sys/module/crypto_blkcipher/notes', 0o775) +f('sys/module/crypto_blkcipher/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00-_P~\xd2\x1eM\xee\xb0!\xc0\xd8\xb7\x00\x1b\xe4#-\xc8\xe0') +d('sys/module/soundcore', 0o775) +f('sys/module/soundcore/initstate', 0o664, b'live\n') +f('sys/module/soundcore/srcversion', 0o664, b'E4F49ED9C4CFD1A5A923330\n') +f('sys/module/soundcore/refcnt', 0o664, b'1\n') +d('sys/module/soundcore/holders', 0o775) +l('sys/module/soundcore/holders/snd', '../../snd') +d('sys/module/soundcore/sections', 0o775) +f('sys/module/soundcore/sections/__ksymtab_strings', 0o664, b'0xffffffffa0067bf0\n') +f('sys/module/soundcore/sections/.exit.text', 0o664, b'0xffffffffa0067850\n') +f('sys/module/soundcore/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0067874\n') +f('sys/module/soundcore/sections/.strtab', 0o664, b'0xffffffffa00686d0\n') +f('sys/module/soundcore/sections/__ksymtab', 0o664, b'0xffffffffa0067b00\n') +f('sys/module/soundcore/sections/.rodata', 0o664, b'0xffffffffa00678a0\n') +f('sys/module/soundcore/sections/.bss', 0o664, b'0xffffffffa00692c0\n') +f('sys/module/soundcore/sections/.text', 0o664, b'0xffffffffa0067000\n') +f('sys/module/soundcore/sections/.init.text', 0o664, b'0xffffffffa006b000\n') +f('sys/module/soundcore/sections/__kcrctab', 0o664, b'0xffffffffa0067ba0\n') +f('sys/module/soundcore/sections/.data', 0o664, b'0xffffffffa0068ec0\n') +f('sys/module/soundcore/sections/.symtab', 0o664, b'0xffffffffa0067cc8\n') +f('sys/module/soundcore/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0068f00\n') +f('sys/module/soundcore/sections/.rodata.str1.1', 0o664, b'0xffffffffa00679f8\n') +d('sys/module/soundcore/notes', 0o775) +f('sys/module/soundcore/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00^\x97fIs2\xf4Ck\xe0$]\xd8)]\xe2\x9c\xea\x1d\x0c') +d('sys/module/pcspkr', 0o775) +f('sys/module/pcspkr/initstate', 0o664, b'live\n') +f('sys/module/pcspkr/srcversion', 0o664, b'5757E9C81E627525BA9D165\n') +f('sys/module/pcspkr/refcnt', 0o664, b'0\n') +d('sys/module/pcspkr/drivers', 0o775) +l('sys/module/pcspkr/drivers/platform:pcspkr', '../../../bus/platform/drivers/pcspkr') +d('sys/module/pcspkr/sections', 0o775) +f('sys/module/pcspkr/sections/.exit.text', 0o664, b'0xffffffffa009e15c\n') +f('sys/module/pcspkr/sections/.note.gnu.build-id', 0o664, b'0xffffffffa009e250\n') +f('sys/module/pcspkr/sections/.strtab', 0o664, b'0xffffffffa009e6e8\n') +f('sys/module/pcspkr/sections/.devexit.text', 0o664, b'0xffffffffa009e16e\n') +f('sys/module/pcspkr/sections/.bss', 0o664, b'0xffffffffa009ed80\n') +f('sys/module/pcspkr/sections/.text', 0o664, b'0xffffffffa009e000\n') +f('sys/module/pcspkr/sections/.init.text', 0o664, b'0xffffffffa00a0000\n') +f('sys/module/pcspkr/sections/.data', 0o664, b'0xffffffffa009e900\n') +f('sys/module/pcspkr/sections/.devinit.text', 0o664, b'0xffffffffa009e1ad\n') +f('sys/module/pcspkr/sections/.symtab', 0o664, b'0xffffffffa009e298\n') +f('sys/module/pcspkr/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa009e9c0\n') +f('sys/module/pcspkr/sections/.rodata.str1.1', 0o664, b'0xffffffffa009e274\n') +d('sys/module/pcspkr/notes', 0o775) +f('sys/module/pcspkr/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xe3\xfd\xb1\xf7b\xd2\x8f\xc1\xd2C\xfc\xfe\xdf8\x80\x82\x85A\xc9!') +d('sys/module/sr_mod', 0o775) +f('sys/module/sr_mod/initstate', 0o664, b'live\n') +f('sys/module/sr_mod/srcversion', 0o664, b'3484F077F1A71803F453437\n') +f('sys/module/sr_mod/refcnt', 0o664, b'0\n') +d('sys/module/sr_mod/parameters', 0o775) +f('sys/module/sr_mod/parameters/xa_test', 0o664, b'0\n') +d('sys/module/sr_mod/sections', 0o775) +f('sys/module/sr_mod/sections/.smp_locks', 0o664, b'0xffffffffa0061488\n') +f('sys/module/sr_mod/sections/.exit.text', 0o664, b'0xffffffffa006126c\n') +f('sys/module/sr_mod/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0061290\n') +f('sys/module/sr_mod/sections/.strtab', 0o664, b'0xffffffffa00623f0\n') +f('sys/module/sr_mod/sections/.rodata', 0o664, b'0xffffffffa00612c0\n') +f('sys/module/sr_mod/sections/__param', 0o664, b'0xffffffffa0061750\n') +f('sys/module/sr_mod/sections/.bss', 0o664, b'0xffffffffa00630c0\n') +f('sys/module/sr_mod/sections/.text', 0o664, b'0xffffffffa005f000\n') +f('sys/module/sr_mod/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/sr_mod/sections/.data', 0o664, b'0xffffffffa0062aa0\n') +f('sys/module/sr_mod/sections/.symtab', 0o664, b'0xffffffffa0061778\n') +f('sys/module/sr_mod/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0062d00\n') +f('sys/module/sr_mod/sections/.rodata.str1.1', 0o664, b'0xffffffffa0061308\n') +d('sys/module/sr_mod/notes', 0o775) +f('sys/module/sr_mod/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xae\xa7\xdcHo\xe7\xe1\xa0#\x94\x9a\xfeV8\xa6O$@\xc1(') +d('sys/module/cfg80211', 0o775) +f('sys/module/cfg80211/initstate', 0o664, b'live\n') +f('sys/module/cfg80211/srcversion', 0o664, b'C43F275505B181F0D1625BE\n') +f('sys/module/cfg80211/refcnt', 0o664, b'2\n') +d('sys/module/cfg80211/holders', 0o775) +l('sys/module/cfg80211/holders/mac80211', '../../mac80211') +l('sys/module/cfg80211/holders/iwl3945', '../../iwl3945') +d('sys/module/cfg80211/parameters', 0o775) +f('sys/module/cfg80211/parameters/ieee80211_regdom', 0o664, b'US\n') +d('sys/module/cfg80211/sections', 0o775) +f('sys/module/cfg80211/sections/.smp_locks', 0o664, b'0xffffffffa00bd2a0\n') +f('sys/module/cfg80211/sections/__bug_table', 0o664, b'0xffffffffa00bd166\n') +f('sys/module/cfg80211/sections/__ksymtab_strings', 0o664, b'0xffffffffa00bd448\n') +f('sys/module/cfg80211/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00bce58\n') +f('sys/module/cfg80211/sections/.strtab', 0o664, b'0xffffffffa00be8c0\n') +f('sys/module/cfg80211/sections/__ksymtab', 0o664, b'0xffffffffa00bd370\n') +f('sys/module/cfg80211/sections/.rodata', 0o664, b'0xffffffffa00bce80\n') +f('sys/module/cfg80211/sections/.data.read_mostly', 0o664, b'0xffffffffa00bfe60\n') +f('sys/module/cfg80211/sections/__param', 0o664, b'0xffffffffa00bd518\n') +f('sys/module/cfg80211/sections/.bss', 0o664, b'0xffffffffa00c02c0\n') +f('sys/module/cfg80211/sections/.text', 0o664, b'0xffffffffa00b9000\n') +f('sys/module/cfg80211/sections/__kcrctab', 0o664, b'0xffffffffa00bd400\n') +f('sys/module/cfg80211/sections/.data', 0o664, b'0xffffffffa00bf760\n') +f('sys/module/cfg80211/sections/.symtab', 0o664, b'0xffffffffa00bd540\n') +f('sys/module/cfg80211/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00bff00\n') +f('sys/module/cfg80211/sections/.rodata.str1.1', 0o664, b'0xffffffffa00bd078\n') +d('sys/module/cfg80211/notes', 0o775) +f('sys/module/cfg80211/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00}-\xdb\xa6\xb1\xf6I\x90\xaf\xbdX\xed\x8d\xac\x86o(\xc8zC') +d('sys/module/snd_seq', 0o775) +f('sys/module/snd_seq/initstate', 0o664, b'live\n') +f('sys/module/snd_seq/srcversion', 0o664, b'94E19F6DBC8F63B241414FE\n') +f('sys/module/snd_seq/refcnt', 0o664, b'0\n') +d('sys/module/snd_seq/parameters', 0o775) +f('sys/module/snd_seq/parameters/seq_default_timer_device', 0o664, b'0\n') +f('sys/module/snd_seq/parameters/seq_default_timer_class', 0o664, b'1\n') +f('sys/module/snd_seq/parameters/seq_client_load', 0o664, b'-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1\n') +f('sys/module/snd_seq/parameters/seq_default_timer_sclass', 0o664, b'0\n') +f('sys/module/snd_seq/parameters/seq_default_timer_resolution', 0o664, b'0\n') +f('sys/module/snd_seq/parameters/seq_default_timer_subdevice', 0o664, b'0\n') +f('sys/module/snd_seq/parameters/seq_default_timer_card', 0o664, b'-1\n') +d('sys/module/snd_seq/sections', 0o775) +f('sys/module/snd_seq/sections/.smp_locks', 0o664, b'0xffffffffa02b1d30\n') +f('sys/module/snd_seq/sections/__ksymtab_strings', 0o664, b'0xffffffffa02b1748\n') +f('sys/module/snd_seq/sections/.exit.text', 0o664, b'0xffffffffa02b0ff0\n') +f('sys/module/snd_seq/sections/.note.gnu.build-id', 0o664, b'0xffffffffa02b10bc\n') +f('sys/module/snd_seq/sections/.strtab', 0o664, b'0xffffffffa02b4590\n') +f('sys/module/snd_seq/sections/__ksymtab', 0o664, b'0xffffffffa02b1610\n') +f('sys/module/snd_seq/sections/.rodata', 0o664, b'0xffffffffa02b10e0\n') +f('sys/module/snd_seq/sections/__param', 0o664, b'0xffffffffa02b1320\n') +f('sys/module/snd_seq/sections/.bss', 0o664, b'0xffffffffa02b6f80\n') +f('sys/module/snd_seq/sections/.text', 0o664, b'0xffffffffa02a9000\n') +f('sys/module/snd_seq/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/snd_seq/sections/__kcrctab', 0o664, b'0xffffffffa02b16e0\n') +f('sys/module/snd_seq/sections/.data', 0o664, b'0xffffffffa02b6860\n') +f('sys/module/snd_seq/sections/.symtab', 0o664, b'0xffffffffa02b1fc8\n') +f('sys/module/snd_seq/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02b6bc0\n') +f('sys/module/snd_seq/sections/.rodata.str1.1', 0o664, b'0xffffffffa02b18b6\n') +d('sys/module/snd_seq/notes', 0o775) +f('sys/module/snd_seq/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00O@T\xdaF\x1cl\x11\xfev\xdd\xaa \xea\x87\x92P\xfe\xb1\xf8') +d('sys/module/usb_storage', 0o775) +f('sys/module/usb_storage/initstate', 0o664, b'live\n') +f('sys/module/usb_storage/srcversion', 0o664, b'D07F7C47643AB7AFB6BEF6F\n') +f('sys/module/usb_storage/refcnt', 0o664, b'1\n') +d('sys/module/usb_storage/drivers', 0o775) +l('sys/module/usb_storage/drivers/usb:usb-storage', '../../../bus/usb/drivers/usb-storage') +d('sys/module/usb_storage/parameters', 0o775) +f('sys/module/usb_storage/parameters/swi_tru_install', 0o664, b'1\n') +f('sys/module/usb_storage/parameters/delay_use', 0o664, b'5\n') +d('sys/module/usb_storage/sections', 0o775) +f('sys/module/usb_storage/sections/.smp_locks', 0o664, b'0xffffffffa02e1820\n') +f('sys/module/usb_storage/sections/.exit.text', 0o664, b'0xffffffffa02e056c\n') +f('sys/module/usb_storage/sections/.note.gnu.build-id', 0o664, b'0xffffffffa02e0580\n') +f('sys/module/usb_storage/sections/.strtab', 0o664, b'0xffffffffa02e42d0\n') +f('sys/module/usb_storage/sections/.rodata', 0o664, b'0xffffffffa02e05b0\n') +f('sys/module/usb_storage/sections/__param', 0o664, b'0xffffffffa02e18b0\n') +f('sys/module/usb_storage/sections/.bss', 0o664, b'0xffffffffa02e9400\n') +f('sys/module/usb_storage/sections/.text', 0o664, b'0xffffffffa02dd000\n') +f('sys/module/usb_storage/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/usb_storage/sections/.data', 0o664, b'0xffffffffa02e5dc0\n') +f('sys/module/usb_storage/sections/.symtab', 0o664, b'0xffffffffa02e1900\n') +f('sys/module/usb_storage/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02e9040\n') +f('sys/module/usb_storage/sections/.rodata.str1.1', 0o664, b'0xffffffffa02e0ab1\n') +d('sys/module/usb_storage/notes', 0o775) +f('sys/module/usb_storage/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00B~(&&u\xc4Ax\xd8|\x80n\xc4G(i\xf3kG') +d('sys/module/acpi_cpufreq', 0o775) +f('sys/module/acpi_cpufreq/initstate', 0o664, b'live\n') +f('sys/module/acpi_cpufreq/srcversion', 0o664, b'09166B6001DCE2189668F16\n') +f('sys/module/acpi_cpufreq/refcnt', 0o664, b'1\n') +d('sys/module/acpi_cpufreq/parameters', 0o775) +f('sys/module/acpi_cpufreq/parameters/acpi_pstate_strict', 0o664, b'0\n') +d('sys/module/acpi_cpufreq/sections', 0o775) +f('sys/module/acpi_cpufreq/sections/.smp_locks', 0o664, b'0xffffffffa0254d68\n') +f('sys/module/acpi_cpufreq/sections/.exit.text', 0o664, b'0xffffffffa0254c4c\n') +f('sys/module/acpi_cpufreq/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0254c6c\n') +f('sys/module/acpi_cpufreq/sections/.strtab', 0o664, b'0xffffffffa0255620\n') +f('sys/module/acpi_cpufreq/sections/.rodata', 0o664, b'0xffffffffa0254ca0\n') +f('sys/module/acpi_cpufreq/sections/__param', 0o664, b'0xffffffffa0254d70\n') +f('sys/module/acpi_cpufreq/sections/.bss', 0o664, b'0xffffffffa0256000\n') +f('sys/module/acpi_cpufreq/sections/.text', 0o664, b'0xffffffffa0254000\n') +f('sys/module/acpi_cpufreq/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/acpi_cpufreq/sections/.data', 0o664, b'0xffffffffa0255bc0\n') +f('sys/module/acpi_cpufreq/sections/.symtab', 0o664, b'0xffffffffa0254dc8\n') +f('sys/module/acpi_cpufreq/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0255c40\n') +f('sys/module/acpi_cpufreq/sections/.rodata.str1.1', 0o664, b'0xffffffffa0254d98\n') +d('sys/module/acpi_cpufreq/notes', 0o775) +f('sys/module/acpi_cpufreq/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xa4\xfd\x13\xe7*\xbd\x99\x95\x99C\xf6\x95\x04\xf1r\xf9\xf7}aL') +d('sys/module/button', 0o775) +f('sys/module/button/initstate', 0o664, b'live\n') +f('sys/module/button/srcversion', 0o664, b'2713981C971D8EC4C059338\n') +f('sys/module/button/refcnt', 0o664, b'0\n') +d('sys/module/button/sections', 0o775) +f('sys/module/button/sections/.smp_locks', 0o664, b'0xffffffffa00a7c98\n') +f('sys/module/button/sections/.exit.text', 0o664, b'0xffffffffa00a781c\n') +f('sys/module/button/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00a7898\n') +f('sys/module/button/sections/.strtab', 0o664, b'0xffffffffa00a84d8\n') +f('sys/module/button/sections/.rodata', 0o664, b'0xffffffffa00a78c0\n') +f('sys/module/button/sections/.bss', 0o664, b'0xffffffffa00a8f40\n') +f('sys/module/button/sections/.text', 0o664, b'0xffffffffa00a7000\n') +f('sys/module/button/sections/.init.text', 0o664, b'0xffffffffa00aa000\n') +f('sys/module/button/sections/.data', 0o664, b'0xffffffffa00a89e0\n') +f('sys/module/button/sections/.symtab', 0o664, b'0xffffffffa00a7cb0\n') +f('sys/module/button/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00a8b80\n') +f('sys/module/button/sections/.rodata.str1.1', 0o664, b'0xffffffffa00a7b60\n') +d('sys/module/button/notes', 0o775) +f('sys/module/button/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00;\xc1\xa4qIi\xa7\xa0g\x7fb\xcb\xb4\xba\x80\xb1\x17Z#\xb5') +d('sys/module/processor', 0o775) +f('sys/module/processor/initstate', 0o664, b'live\n') +f('sys/module/processor/srcversion', 0o664, b'8A1C302AFF80867DBAC4684\n') +f('sys/module/processor/refcnt', 0o664, b'4\n') +d('sys/module/processor/holders', 0o775) +l('sys/module/processor/holders/acpi_cpufreq', '../../acpi_cpufreq') +l('sys/module/processor/holders/thermal', '../../thermal') +d('sys/module/processor/parameters', 0o775) +f('sys/module/processor/parameters/ignore_ppc', 0o664, b'0\n') +f('sys/module/processor/parameters/latency_factor', 0o664, b'2\n') +d('sys/module/processor/sections', 0o775) +f('sys/module/processor/sections/.smp_locks', 0o664, b'0xffffffffa0077788\n') +f('sys/module/processor/sections/__ex_table', 0o664, b'0xffffffffa0077768\n') +f('sys/module/processor/sections/__bug_table', 0o664, b'0xffffffffa0077621\n') +f('sys/module/processor/sections/__ksymtab_strings', 0o664, b'0xffffffffa00776b8\n') +f('sys/module/processor/sections/.exit.text', 0o664, b'0xffffffffa00763a9\n') +f('sys/module/processor/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00765c4\n') +f('sys/module/processor/sections/.strtab', 0o664, b'0xffffffffa0079438\n') +f('sys/module/processor/sections/.fixup', 0o664, b'0xffffffffa00765ad\n') +f('sys/module/processor/sections/__ksymtab', 0o664, b'0xffffffffa0077640\n') +f('sys/module/processor/sections/.rodata', 0o664, b'0xffffffffa00765f0\n') +f('sys/module/processor/sections/.data.read_mostly', 0o664, b'0xffffffffa007b7d8\n') +f('sys/module/processor/sections/__param', 0o664, b'0xffffffffa00777f0\n') +f('sys/module/processor/sections/.bss', 0o664, b'0xffffffffa007bbc0\n') +f('sys/module/processor/sections/.text', 0o664, b'0xffffffffa0072000\n') +f('sys/module/processor/sections/.init.text', 0o664, b'0xffffffffa007d000\n') +f('sys/module/processor/sections/__kcrctab', 0o664, b'0xffffffffa0077690\n') +f('sys/module/processor/sections/.data', 0o664, b'0xffffffffa007ab90\n') +f('sys/module/processor/sections/.cpuinit.data', 0o664, b'0xffffffffa007b040\n') +f('sys/module/processor/sections/.symtab', 0o664, b'0xffffffffa0077890\n') +f('sys/module/processor/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa007b800\n') +f('sys/module/processor/sections/.rodata.str1.1', 0o664, b'0xffffffffa0076863\n') +f('sys/module/processor/sections/.cpuinit.text', 0o664, b'0xffffffffa0075abc\n') +f('sys/module/processor/sections/.ref.text', 0o664, b'0xffffffffa007641a\n') +d('sys/module/processor/notes', 0o775) +f('sys/module/processor/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xa1\x01$C\tS,+Ue\\\x8cg\xb0Z\xe9\xa1\xaf[\xe5') +d('sys/module/oprofile', 0o775) +d('sys/module/oprofile/parameters', 0o775) +f('sys/module/oprofile/parameters/timer', 0o664, b'0\n') +d('sys/module/spurious', 0o775) +d('sys/module/spurious/parameters', 0o775) +f('sys/module/spurious/parameters/noirqdebug', 0o664, b'N\n') +f('sys/module/spurious/parameters/irqfixup', 0o664, b'0\n') +d('sys/module/raid1', 0o775) +f('sys/module/raid1/initstate', 0o664, b'live\n') +f('sys/module/raid1/srcversion', 0o664, b'EA08FDD37C2EEFA95DE4413\n') +f('sys/module/raid1/refcnt', 0o664, b'1\n') +d('sys/module/raid1/sections', 0o775) +f('sys/module/raid1/sections/.smp_locks', 0o664, b'0xffffffffa0236438\n') +f('sys/module/raid1/sections/__bug_table', 0o664, b'0xffffffffa02369c0\n') +f('sys/module/raid1/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0236414\n') +f('sys/module/raid1/sections/.strtab', 0o664, b'0xffffffffa02376f8\n') +f('sys/module/raid1/sections/.bss', 0o664, b'0xffffffffa0238280\n') +f('sys/module/raid1/sections/.text', 0o664, b'0xffffffffa0232000\n') +f('sys/module/raid1/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/raid1/sections/.data', 0o664, b'0xffffffffa0237e20\n') +f('sys/module/raid1/sections/.symtab', 0o664, b'0xffffffffa0236a08\n') +f('sys/module/raid1/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0237ec0\n') +f('sys/module/raid1/sections/.rodata.str1.1', 0o664, b'0xffffffffa0236618\n') +d('sys/module/raid1/notes', 0o775) +f('sys/module/raid1/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xcd\xdf0\xe8v}\x0cuP}\x93\xe1\x19\xcd\xed~\xf7\x14\xdd@') +d('sys/module/edd', 0o775) +f('sys/module/edd/version', 0o664, b'0.16\n') +f('sys/module/edd/initstate', 0o664, b'live\n') +f('sys/module/edd/srcversion', 0o664, b'ED68C1ACC4B2D1B19C7BEA7\n') +f('sys/module/edd/refcnt', 0o664, b'0\n') +d('sys/module/edd/sections', 0o775) +f('sys/module/edd/sections/.exit.text', 0o664, b'0xffffffffa02a1de8\n') +f('sys/module/edd/sections/.note.gnu.build-id', 0o664, b'0xffffffffa02a1e6c\n') +f('sys/module/edd/sections/.strtab', 0o664, b'0xffffffffa02a2b88\n') +f('sys/module/edd/sections/.rodata', 0o664, b'0xffffffffa02a1ea0\n') +f('sys/module/edd/sections/.bss', 0o664, b'0xffffffffa02a3880\n') +f('sys/module/edd/sections/.text', 0o664, b'0xffffffffa02a1000\n') +f('sys/module/edd/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/edd/sections/.data', 0o664, b'0xffffffffa02a3120\n') +f('sys/module/edd/sections/.symtab', 0o664, b'0xffffffffa02a22b8\n') +f('sys/module/edd/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02a34c0\n') +f('sys/module/edd/sections/.rodata.str1.1', 0o664, b'0xffffffffa02a1f18\n') +d('sys/module/edd/notes', 0o775) +f('sys/module/edd/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xbe\x92\xcfW\xc8l\x08\xaf\xb6\x1a\xb7!E\xb8\xd1\x9eU\xd2\xddM') +d('sys/module/hwmon', 0o775) +f('sys/module/hwmon/initstate', 0o664, b'live\n') +f('sys/module/hwmon/srcversion', 0o664, b'9344A0FAA4A298DC9AEBDC8\n') +f('sys/module/hwmon/refcnt', 0o664, b'1\n') +d('sys/module/hwmon/holders', 0o775) +l('sys/module/hwmon/holders/thinkpad_acpi', '../../thinkpad_acpi') +d('sys/module/hwmon/sections', 0o775) +f('sys/module/hwmon/sections/__ksymtab_gpl', 0o664, b'0xffffffffa007d1d0\n') +f('sys/module/hwmon/sections/__ksymtab_strings', 0o664, b'0xffffffffa007d200\n') +f('sys/module/hwmon/sections/.exit.text', 0o664, b'0xffffffffa007d138\n') +f('sys/module/hwmon/sections/.note.gnu.build-id', 0o664, b'0xffffffffa007d14c\n') +f('sys/module/hwmon/sections/.strtab', 0o664, b'0xffffffffa007d770\n') +f('sys/module/hwmon/sections/.bss', 0o664, b'0xffffffffa007de80\n') +f('sys/module/hwmon/sections/.text', 0o664, b'0xffffffffa007d000\n') +f('sys/module/hwmon/sections/.init.text', 0o664, b'0xffffffffa009a000\n') +f('sys/module/hwmon/sections/.data', 0o664, b'0xffffffffa007da20\n') +f('sys/module/hwmon/sections/.symtab', 0o664, b'0xffffffffa007d230\n') +f('sys/module/hwmon/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa007dac0\n') +f('sys/module/hwmon/sections/.rodata.str1.1', 0o664, b'0xffffffffa007d170\n') +f('sys/module/hwmon/sections/__kcrctab_gpl', 0o664, b'0xffffffffa007d1f0\n') +d('sys/module/hwmon/notes', 0o775) +f('sys/module/hwmon/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\x0fR\x0b\x94!\x19\xde\x14\x93\xac\x9e@\xa2&\xcam,\xba\x12\xd1') +d('sys/module/backlight', 0o775) +f('sys/module/backlight/initstate', 0o664, b'live\n') +f('sys/module/backlight/srcversion', 0o664, b'AFD1565C65F3DA6D942CB52\n') +f('sys/module/backlight/refcnt', 0o664, b'1\n') +d('sys/module/backlight/holders', 0o775) +l('sys/module/backlight/holders/thinkpad_acpi', '../../thinkpad_acpi') +d('sys/module/backlight/sections', 0o775) +f('sys/module/backlight/sections/__ksymtab_strings', 0o664, b'0xffffffffa0131700\n') +f('sys/module/backlight/sections/.exit.text', 0o664, b'0xffffffffa01315ec\n') +f('sys/module/backlight/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0131600\n') +f('sys/module/backlight/sections/.strtab', 0o664, b'0xffffffffa0131de0\n') +f('sys/module/backlight/sections/__ksymtab', 0o664, b'0xffffffffa01316d0\n') +f('sys/module/backlight/sections/.bss', 0o664, b'0xffffffffa01326c0\n') +f('sys/module/backlight/sections/.text', 0o664, b'0xffffffffa0131000\n') +f('sys/module/backlight/sections/.init.text', 0o664, b'0xffffffffa0070000\n') +f('sys/module/backlight/sections/__kcrctab', 0o664, b'0xffffffffa01316f0\n') +f('sys/module/backlight/sections/.data', 0o664, b'0xffffffffa0132220\n') +f('sys/module/backlight/sections/.symtab', 0o664, b'0xffffffffa0131738\n') +f('sys/module/backlight/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0132300\n') +f('sys/module/backlight/sections/.rodata.str1.1', 0o664, b'0xffffffffa0131624\n') +d('sys/module/backlight/notes', 0o775) +f('sys/module/backlight/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00d\xb6_\xb64[\x83\x90Fm(\x91J\xb1\xce\xf5\xaa\xd2\xf4}') +d('sys/module/snd', 0o775) +f('sys/module/snd/initstate', 0o664, b'live\n') +f('sys/module/snd/srcversion', 0o664, b'D48337942305C9A41A7CC12\n') +f('sys/module/snd/refcnt', 0o664, b'13\n') +d('sys/module/snd/holders', 0o775) +l('sys/module/snd/holders/snd_seq', '../../snd_seq') +l('sys/module/snd/holders/snd_timer', '../../snd_timer') +l('sys/module/snd/holders/snd_pcm', '../../snd_pcm') +l('sys/module/snd/holders/snd_hda_intel', '../../snd_hda_intel') +l('sys/module/snd/holders/snd_mixer_oss', '../../snd_mixer_oss') +l('sys/module/snd/holders/snd_pcm_oss', '../../snd_pcm_oss') +l('sys/module/snd/holders/snd_seq_device', '../../snd_seq_device') +d('sys/module/snd/parameters', 0o775) +f('sys/module/snd/parameters/slots', 0o664, b'snd-hda-intel,,,,,,,\n') +f('sys/module/snd/parameters/major', 0o664, b'116\n') +f('sys/module/snd/parameters/cards_limit', 0o664, b'1\n') +d('sys/module/snd/sections', 0o775) +f('sys/module/snd/sections/__ksymtab_strings', 0o664, b'0xffffffffa00d32e8\n') +f('sys/module/snd/sections/.exit.text', 0o664, b'0xffffffffa00d1bc4\n') +f('sys/module/snd/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00d1c8c\n') +f('sys/module/snd/sections/.strtab', 0o664, b'0xffffffffa00d6cc8\n') +f('sys/module/snd/sections/__ksymtab', 0o664, b'0xffffffffa00d2d00\n') +f('sys/module/snd/sections/.rodata', 0o664, b'0xffffffffa00d1cc0\n') +f('sys/module/snd/sections/__param', 0o664, b'0xffffffffa00d3270\n') +f('sys/module/snd/sections/.bss', 0o664, b'0xffffffffa00da480\n') +f('sys/module/snd/sections/.text', 0o664, b'0xffffffffa00ca000\n') +f('sys/module/snd/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/snd/sections/__kcrctab', 0o664, b'0xffffffffa00d30a0\n') +f('sys/module/snd/sections/.data', 0o664, b'0xffffffffa00d9be0\n') +f('sys/module/snd/sections/.symtab', 0o664, b'0xffffffffa00d3770\n') +f('sys/module/snd/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00da0c0\n') +f('sys/module/snd/sections/.rodata.str1.1', 0o664, b'0xffffffffa00d2558\n') +d('sys/module/snd/notes', 0o775) +f('sys/module/snd/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xee\x11+\xc0\xd4\x8f\x10\x02v\xf8\t\xb4\xa8\xf6[z\xd3\xb3\xb7\x87') +d('sys/module/mac80211', 0o775) +f('sys/module/mac80211/initstate', 0o664, b'live\n') +f('sys/module/mac80211/srcversion', 0o664, b'330E8FB2F2933F478C444A4\n') +f('sys/module/mac80211/refcnt', 0o664, b'1\n') +d('sys/module/mac80211/holders', 0o775) +l('sys/module/mac80211/holders/iwl3945', '../../iwl3945') +d('sys/module/mac80211/parameters', 0o775) +f('sys/module/mac80211/parameters/ieee80211_default_rc_algo', 0o664, b'pid\n') +d('sys/module/mac80211/sections', 0o775) +f('sys/module/mac80211/sections/__ksymtab_gpl', 0o664, b'0xffffffffa0127a50\n') +f('sys/module/mac80211/sections/.smp_locks', 0o664, b'0xffffffffa01270a0\n') +f('sys/module/mac80211/sections/__bug_table', 0o664, b'0xffffffffa0124183\n') +f('sys/module/mac80211/sections/__ksymtab_strings', 0o664, b'0xffffffffa0127630\n') +f('sys/module/mac80211/sections/.exit.text', 0o664, b'0xffffffffa0122de4\n') +f('sys/module/mac80211/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0122df4\n') +f('sys/module/mac80211/sections/.strtab', 0o664, b'0xffffffffa012b890\n') +f('sys/module/mac80211/sections/__ksymtab', 0o664, b'0xffffffffa01272a0\n') +f('sys/module/mac80211/sections/.rodata', 0o664, b'0xffffffffa0122e20\n') +f('sys/module/mac80211/sections/__param', 0o664, b'0xffffffffa0127a28\n') +f('sys/module/mac80211/sections/.bss', 0o664, b'0xffffffffa012fa40\n') +f('sys/module/mac80211/sections/.text', 0o664, b'0xffffffffa0109000\n') +f('sys/module/mac80211/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/mac80211/sections/__kcrctab', 0o664, b'0xffffffffa0127500\n') +f('sys/module/mac80211/sections/.data', 0o664, b'0xffffffffa012f340\n') +f('sys/module/mac80211/sections/.symtab', 0o664, b'0xffffffffa0127a80\n') +f('sys/module/mac80211/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa012f680\n') +f('sys/module/mac80211/sections/.rodata.str1.1', 0o664, b'0xffffffffa0123c40\n') +f('sys/module/mac80211/sections/__kcrctab_gpl', 0o664, b'0xffffffffa0127a70\n') +d('sys/module/mac80211/notes', 0o775) +f('sys/module/mac80211/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00"i\xe2\xa0\x92\xbc7\xc4#\xbc\xda\xf11\x02\x13\xd5\x155\x1cS') +d('sys/module/printk', 0o775) +d('sys/module/printk/parameters', 0o775) +f('sys/module/printk/parameters/time', 0o664, b'N\n') +d('sys/module/rtc_lib', 0o775) +f('sys/module/rtc_lib/initstate', 0o664, b'live\n') +f('sys/module/rtc_lib/srcversion', 0o664, b'7884E7FF8728D88C6BD1427\n') +f('sys/module/rtc_lib/refcnt', 0o664, b'1\n') +d('sys/module/rtc_lib/holders', 0o775) +l('sys/module/rtc_lib/holders/rtc_core', '../../rtc_core') +d('sys/module/rtc_lib/sections', 0o775) +f('sys/module/rtc_lib/sections/__ksymtab_strings', 0o664, b'0xffffffffa009c3f8\n') +f('sys/module/rtc_lib/sections/.note.gnu.build-id', 0o664, b'0xffffffffa009c31c\n') +f('sys/module/rtc_lib/sections/.strtab', 0o664, b'0xffffffffa009c8f0\n') +f('sys/module/rtc_lib/sections/__ksymtab', 0o664, b'0xffffffffa009c380\n') +f('sys/module/rtc_lib/sections/.rodata', 0o664, b'0xffffffffa009c340\n') +f('sys/module/rtc_lib/sections/.bss', 0o664, b'0xffffffffa009cf80\n') +f('sys/module/rtc_lib/sections/.text', 0o664, b'0xffffffffa009c000\n') +f('sys/module/rtc_lib/sections/__kcrctab', 0o664, b'0xffffffffa009c3d0\n') +f('sys/module/rtc_lib/sections/.data', 0o664, b'0xffffffffa009cba8\n') +f('sys/module/rtc_lib/sections/.symtab', 0o664, b'0xffffffffa009c440\n') +f('sys/module/rtc_lib/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa009cbc0\n') +d('sys/module/rtc_lib/notes', 0o775) +f('sys/module/rtc_lib/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xb4\xe2\xcfLw\x17j\xb2\xc7\xf1 \xfa\xc7G\x99+b^+S') +d('sys/module/mousedev', 0o775) +d('sys/module/mousedev/parameters', 0o775) +f('sys/module/mousedev/parameters/tap_time', 0o664, b'200\n') +f('sys/module/mousedev/parameters/yres', 0o664, b'768\n') +f('sys/module/mousedev/parameters/xres', 0o664, b'1024\n') +d('sys/module/rtc_cmos', 0o775) +f('sys/module/rtc_cmos/initstate', 0o664, b'live\n') +f('sys/module/rtc_cmos/srcversion', 0o664, b'7BE4B8C2A52556D0C62CB0B\n') +f('sys/module/rtc_cmos/refcnt', 0o664, b'0\n') +d('sys/module/rtc_cmos/sections', 0o775) +f('sys/module/rtc_cmos/sections/.exit.text', 0o664, b'0xffffffffa00fe370\n') +f('sys/module/rtc_cmos/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00fe4e4\n') +f('sys/module/rtc_cmos/sections/.strtab', 0o664, b'0xffffffffa00ff1a8\n') +f('sys/module/rtc_cmos/sections/.rodata', 0o664, b'0xffffffffa00fe520\n') +f('sys/module/rtc_cmos/sections/.bss', 0o664, b'0xffffffffa00ffd40\n') +f('sys/module/rtc_cmos/sections/.text', 0o664, b'0xffffffffa00fd000\n') +f('sys/module/rtc_cmos/sections/.init.text', 0o664, b'0xffffffffa007d000\n') +f('sys/module/rtc_cmos/sections/.data', 0o664, b'0xffffffffa00ff800\n') +f('sys/module/rtc_cmos/sections/.devinit.text', 0o664, b'0xffffffffa00fe44f\n') +f('sys/module/rtc_cmos/sections/.symtab', 0o664, b'0xffffffffa00fe6e0\n') +f('sys/module/rtc_cmos/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00ff980\n') +f('sys/module/rtc_cmos/sections/.rodata.str1.1', 0o664, b'0xffffffffa00fe6a2\n') +d('sys/module/rtc_cmos/notes', 0o775) +f('sys/module/rtc_cmos/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xf4\x82\xed4\xe7\x10\xb9\x7f\xa9 \x0c\xedIf0\x86u\xd41\x87') +d('sys/module/battery', 0o775) +f('sys/module/battery/initstate', 0o664, b'live\n') +f('sys/module/battery/srcversion', 0o664, b'5A2CE8D302B31A112CFB57A\n') +f('sys/module/battery/refcnt', 0o664, b'0\n') +d('sys/module/battery/parameters', 0o775) +f('sys/module/battery/parameters/cache_time', 0o664, b'1000\n') +d('sys/module/battery/sections', 0o775) +f('sys/module/battery/sections/.exit.text', 0o664, b'0xffffffffa008008c\n') +f('sys/module/battery/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00800ac\n') +f('sys/module/battery/sections/.strtab', 0o664, b'0xffffffffa0081318\n') +f('sys/module/battery/sections/.rodata', 0o664, b'0xffffffffa00800d0\n') +f('sys/module/battery/sections/__param', 0o664, b'0xffffffffa0080798\n') +f('sys/module/battery/sections/.bss', 0o664, b'0xffffffffa0082440\n') +f('sys/module/battery/sections/.text', 0o664, b'0xffffffffa007f000\n') +f('sys/module/battery/sections/.init.text', 0o664, b'0xffffffffa0084000\n') +f('sys/module/battery/sections/.data', 0o664, b'0xffffffffa0081a90\n') +f('sys/module/battery/sections/.symtab', 0o664, b'0xffffffffa00807c0\n') +f('sys/module/battery/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0082080\n') +f('sys/module/battery/sections/.rodata.str1.1', 0o664, b'0xffffffffa008025b\n') +d('sys/module/battery/notes', 0o775) +f('sys/module/battery/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xe3\xa8\xcc.j\xb3\xda\xc8\x88\x03\xca\xf6\xf0*\x9c-\xffE!\xd3') +d('sys/module/yenta_socket', 0o775) +f('sys/module/yenta_socket/initstate', 0o664, b'live\n') +f('sys/module/yenta_socket/srcversion', 0o664, b'B0538CB6E6ED071E80A4575\n') +f('sys/module/yenta_socket/refcnt', 0o664, b'1\n') +d('sys/module/yenta_socket/drivers', 0o775) +l('sys/module/yenta_socket/drivers/pci:yenta_cardbus', '../../../bus/pci/drivers/yenta_cardbus') +d('sys/module/yenta_socket/parameters', 0o775) +f('sys/module/yenta_socket/parameters/isa_probe', 0o664, b'Y\n') +f('sys/module/yenta_socket/parameters/disable_clkrun', 0o664, b'N\n') +f('sys/module/yenta_socket/parameters/pwr_irqs_off', 0o664, b'N\n') +d('sys/module/yenta_socket/sections', 0o775) +f('sys/module/yenta_socket/sections/__bug_table', 0o664, b'0xffffffffa0104aa6\n') +f('sys/module/yenta_socket/sections/.exit.text', 0o664, b'0xffffffffa0103c44\n') +f('sys/module/yenta_socket/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0104330\n') +f('sys/module/yenta_socket/sections/.strtab', 0o664, b'0xffffffffa0105e80\n') +f('sys/module/yenta_socket/sections/.rodata', 0o664, b'0xffffffffa0104354\n') +f('sys/module/yenta_socket/sections/__param', 0o664, b'0xffffffffa0104ad8\n') +f('sys/module/yenta_socket/sections/.bss', 0o664, b'0xffffffffa0107800\n') +f('sys/module/yenta_socket/sections/.text', 0o664, b'0xffffffffa0101000\n') +f('sys/module/yenta_socket/sections/.init.text', 0o664, b'0xffffffffa0084000\n') +f('sys/module/yenta_socket/sections/.data', 0o664, b'0xffffffffa0106ac0\n') +f('sys/module/yenta_socket/sections/.devinit.text', 0o664, b'0xffffffffa0103c60\n') +f('sys/module/yenta_socket/sections/.symtab', 0o664, b'0xffffffffa0104b78\n') +f('sys/module/yenta_socket/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0107440\n') +f('sys/module/yenta_socket/sections/.rodata.str1.1', 0o664, b'0xffffffffa0104388\n') +d('sys/module/yenta_socket/notes', 0o775) +f('sys/module/yenta_socket/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00H\xa8\xe9\xf1\x06e\xb4\xe4\xd7\xa1\x7f\xf8G)\x1a\xa3\xec\xe7m<') +d('sys/module/acpi', 0o775) +d('sys/module/acpi/parameters', 0o775) +f('sys/module/acpi/parameters/acpica_version', 0o664, b'20080609\n') +d('sys/module/cdc_acm', 0o775) +f('sys/module/cdc_acm/initstate', 0o664, b'live\n') +f('sys/module/cdc_acm/srcversion', 0o664, b'5DED3866AA046376E4E36DD\n') +f('sys/module/cdc_acm/refcnt', 0o664, b'0\n') +d('sys/module/cdc_acm/drivers', 0o775) +l('sys/module/cdc_acm/drivers/usb:cdc_acm', '../../../bus/usb/drivers/cdc_acm') +d('sys/module/cdc_acm/sections', 0o775) +f('sys/module/cdc_acm/sections/.smp_locks', 0o664, b'0xffffffffa02d9660\n') +f('sys/module/cdc_acm/sections/.exit.text', 0o664, b'0xffffffffa02d949c\n') +f('sys/module/cdc_acm/sections/.note.gnu.build-id', 0o664, b'0xffffffffa02d94c8\n') +f('sys/module/cdc_acm/sections/.strtab', 0o664, b'0xffffffffa02da838\n') +f('sys/module/cdc_acm/sections/.rodata', 0o664, b'0xffffffffa02d9500\n') +f('sys/module/cdc_acm/sections/.bss', 0o664, b'0xffffffffa02db8c0\n') +f('sys/module/cdc_acm/sections/.text', 0o664, b'0xffffffffa02d7000\n') +f('sys/module/cdc_acm/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/cdc_acm/sections/.data', 0o664, b'0xffffffffa02db0e0\n') +f('sys/module/cdc_acm/sections/.symtab', 0o664, b'0xffffffffa02d9968\n') +f('sys/module/cdc_acm/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02db500\n') +f('sys/module/cdc_acm/sections/.rodata.str1.1', 0o664, b'0xffffffffa02d9698\n') +d('sys/module/cdc_acm/notes', 0o775) +f('sys/module/cdc_acm/notes/.note.gnu.build-id', 0o664, b"\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xe1=\x89\xe9\xe8L\t\xfe|o\x9c+\xfe\x81\xe8\xc6P'\xa4$") +d('sys/module/snd_timer', 0o775) +f('sys/module/snd_timer/initstate', 0o664, b'live\n') +f('sys/module/snd_timer/srcversion', 0o664, b'1F1836030C5B604CF478CFC\n') +f('sys/module/snd_timer/refcnt', 0o664, b'2\n') +d('sys/module/snd_timer/holders', 0o775) +l('sys/module/snd_timer/holders/snd_seq', '../../snd_seq') +l('sys/module/snd_timer/holders/snd_pcm', '../../snd_pcm') +d('sys/module/snd_timer/parameters', 0o775) +f('sys/module/snd_timer/parameters/timer_tstamp_monotonic', 0o664, b'1\n') +f('sys/module/snd_timer/parameters/timer_limit', 0o664, b'1\n') +d('sys/module/snd_timer/sections', 0o775) +f('sys/module/snd_timer/sections/.smp_locks', 0o664, b'0xffffffffa00f8908\n') +f('sys/module/snd_timer/sections/__bug_table', 0o664, b'0xffffffffa00f888f\n') +f('sys/module/snd_timer/sections/__ksymtab_strings', 0o664, b'0xffffffffa00f8a98\n') +f('sys/module/snd_timer/sections/.exit.text', 0o664, b'0xffffffffa00f8520\n') +f('sys/module/snd_timer/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00f8590\n') +f('sys/module/snd_timer/sections/.strtab', 0o664, b'0xffffffffa00f9e90\n') +f('sys/module/snd_timer/sections/__ksymtab', 0o664, b'0xffffffffa00f8910\n') +f('sys/module/snd_timer/sections/.rodata', 0o664, b'0xffffffffa00f85c0\n') +f('sys/module/snd_timer/sections/__param', 0o664, b'0xffffffffa00f8a48\n') +f('sys/module/snd_timer/sections/.bss', 0o664, b'0xffffffffa00fb200\n') +f('sys/module/snd_timer/sections/.text', 0o664, b'0xffffffffa00f5000\n') +f('sys/module/snd_timer/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/snd_timer/sections/__kcrctab', 0o664, b'0xffffffffa00f89e0\n') +f('sys/module/snd_timer/sections/.data', 0o664, b'0xffffffffa00fad00\n') +f('sys/module/snd_timer/sections/.symtab', 0o664, b'0xffffffffa00f8b88\n') +f('sys/module/snd_timer/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00fae40\n') +f('sys/module/snd_timer/sections/.rodata.str1.1', 0o664, b'0xffffffffa00f8723\n') +d('sys/module/snd_timer/notes', 0o775) +f('sys/module/snd_timer/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xb2uP\xf49\x98_\xdcY\xc1\xbfY\xa4yn\xb0\xbe\x9c\xf2F') +d('sys/module/e1000e', 0o775) +f('sys/module/e1000e/version', 0o664, b'0.3.3.3-k2\n') +f('sys/module/e1000e/initstate', 0o664, b'live\n') +f('sys/module/e1000e/srcversion', 0o664, b'5B93BF2B618524ED19305C8\n') +f('sys/module/e1000e/refcnt', 0o664, b'0\n') +d('sys/module/e1000e/drivers', 0o775) +l('sys/module/e1000e/drivers/pci:e1000e', '../../../bus/pci/drivers/e1000e') +d('sys/module/e1000e/parameters', 0o775) +f('sys/module/e1000e/parameters/copybreak', 0o664, b'256\n') +d('sys/module/e1000e/sections', 0o775) +f('sys/module/e1000e/sections/.devinit.data', 0o664, b'0xffffffffa0024fe0\n') +f('sys/module/e1000e/sections/.smp_locks', 0o664, b'0xffffffffa001e730\n') +f('sys/module/e1000e/sections/__bug_table', 0o664, b'0xffffffffa001e590\n') +f('sys/module/e1000e/sections/.exit.text', 0o664, b'0xffffffffa001c64f\n') +f('sys/module/e1000e/sections/.note.gnu.build-id', 0o664, b'0xffffffffa001c750\n') +f('sys/module/e1000e/sections/.strtab', 0o664, b'0xffffffffa0021ac0\n') +f('sys/module/e1000e/sections/.devexit.text', 0o664, b'0xffffffffa001c672\n') +f('sys/module/e1000e/sections/.rodata', 0o664, b'0xffffffffa001c780\n') +f('sys/module/e1000e/sections/__param', 0o664, b'0xffffffffa001e5f0\n') +f('sys/module/e1000e/sections/.bss', 0o664, b'0xffffffffa0025800\n') +f('sys/module/e1000e/sections/.text', 0o664, b'0xffffffffa0009000\n') +f('sys/module/e1000e/sections/.init.text', 0o664, b'0xffffffffa0027000\n') +f('sys/module/e1000e/sections/.data', 0o664, b'0xffffffffa00243c0\n') +f('sys/module/e1000e/sections/.devinit.text', 0o664, b'0xffffffffa001b380\n') +f('sys/module/e1000e/sections/.symtab', 0o664, b'0xffffffffa001e8b0\n') +f('sys/module/e1000e/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0025440\n') +f('sys/module/e1000e/sections/.rodata.str1.1', 0o664, b'0xffffffffa001d6f0\n') +d('sys/module/e1000e/notes', 0o775) +f('sys/module/e1000e/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xcbJ\xb1\x8eG^\xf7\xba\xbf\xa6\x1b\x03\xfasqDl\xf7"\xf1') +d('sys/module/aes_x86_64', 0o775) +f('sys/module/aes_x86_64/initstate', 0o664, b'live\n') +f('sys/module/aes_x86_64/srcversion', 0o664, b'4E315E23114A08593D5D731\n') +f('sys/module/aes_x86_64/refcnt', 0o664, b'2\n') +d('sys/module/aes_x86_64/sections', 0o775) +f('sys/module/aes_x86_64/sections/.exit.text', 0o664, b'0xffffffffa02d471c\n') +f('sys/module/aes_x86_64/sections/.note.gnu.build-id', 0o664, b'0xffffffffa02d4730\n') +f('sys/module/aes_x86_64/sections/.strtab', 0o664, b'0xffffffffa02d4b60\n') +f('sys/module/aes_x86_64/sections/.bss', 0o664, b'0xffffffffa02d5200\n') +f('sys/module/aes_x86_64/sections/.text', 0o664, b'0xffffffffa02d3000\n') +f('sys/module/aes_x86_64/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/aes_x86_64/sections/.data', 0o664, b'0xffffffffa02d4d20\n') +f('sys/module/aes_x86_64/sections/.symtab', 0o664, b'0xffffffffa02d4758\n') +f('sys/module/aes_x86_64/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02d4e40\n') +d('sys/module/aes_x86_64/notes', 0o775) +f('sys/module/aes_x86_64/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\x1e3\x8c\xa9\xdd\xa1\xeb\\\xcf\xd3\x0f\xd1\xfc\xaa\xd2y\x08+f\xca') +d('sys/module/dm_mod', 0o775) +f('sys/module/dm_mod/initstate', 0o664, b'live\n') +f('sys/module/dm_mod/srcversion', 0o664, b'458AEB289C7AA031FFD0011\n') +f('sys/module/dm_mod/refcnt', 0o664, b'0\n') +d('sys/module/dm_mod/sections', 0o775) +f('sys/module/dm_mod/sections/__ksymtab_gpl', 0o664, b'0xffffffffa02122b0\n') +f('sys/module/dm_mod/sections/.smp_locks', 0o664, b'0xffffffffa0210eb8\n') +f('sys/module/dm_mod/sections/__bug_table', 0o664, b'0xffffffffa0211f54\n') +f('sys/module/dm_mod/sections/__ksymtab_strings', 0o664, b'0xffffffffa0212310\n') +f('sys/module/dm_mod/sections/.exit.text', 0o664, b'0xffffffffa0210c20\n') +f('sys/module/dm_mod/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0210c54\n') +f('sys/module/dm_mod/sections/.strtab', 0o664, b'0xffffffffa02151f0\n') +f('sys/module/dm_mod/sections/__ksymtab', 0o664, b'0xffffffffa02120d0\n') +f('sys/module/dm_mod/sections/.rodata', 0o664, b'0xffffffffa0210c80\n') +f('sys/module/dm_mod/sections/__param', 0o664, b'0xffffffffa02120a8\n') +f('sys/module/dm_mod/sections/.bss', 0o664, b'0xffffffffa02177c0\n') +f('sys/module/dm_mod/sections/.text', 0o664, b'0xffffffffa0209000\n') +f('sys/module/dm_mod/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/dm_mod/sections/__kcrctab', 0o664, b'0xffffffffa0212210\n') +f('sys/module/dm_mod/sections/.data', 0o664, b'0xffffffffa0216f40\n') +f('sys/module/dm_mod/sections/.init.data', 0o664, b'0xffffffffa00652c0\n') +f('sys/module/dm_mod/sections/.symtab', 0o664, b'0xffffffffa02124a8\n') +f('sys/module/dm_mod/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0217400\n') +f('sys/module/dm_mod/sections/.rodata.str1.1', 0o664, b'0xffffffffa0211c4d\n') +f('sys/module/dm_mod/sections/__kcrctab_gpl', 0o664, b'0xffffffffa02122f0\n') +d('sys/module/dm_mod/notes', 0o775) +f('sys/module/dm_mod/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00^(\xdd\x16OD6\xfb\x89\xe6\xca3Vl\xb0\xd7MBp\x84') +d('sys/module/usbhid', 0o775) +f('sys/module/usbhid/initstate', 0o664, b'live\n') +f('sys/module/usbhid/srcversion', 0o664, b'3D7B82FE16E5E534DE4C12B\n') +f('sys/module/usbhid/refcnt', 0o664, b'0\n') +d('sys/module/usbhid/drivers', 0o775) +l('sys/module/usbhid/drivers/usb:usbhid', '../../../bus/usb/drivers/usbhid') +d('sys/module/usbhid/parameters', 0o775) +f('sys/module/usbhid/parameters/mousepoll', 0o664, b'0\n') +f('sys/module/usbhid/parameters/rdesc_quirks', 0o664, b',,,\n') +f('sys/module/usbhid/parameters/quirks', 0o664, b',,,\n') +d('sys/module/usbhid/sections', 0o775) +f('sys/module/usbhid/sections/__ksymtab_gpl', 0o664, b'0xffffffffa0201e60\n') +f('sys/module/usbhid/sections/.smp_locks', 0o664, b'0xffffffffa0201700\n') +f('sys/module/usbhid/sections/__ksymtab_strings', 0o664, b'0xffffffffa0201e78\n') +f('sys/module/usbhid/sections/.exit.text', 0o664, b'0xffffffffa0200c6c\n') +f('sys/module/usbhid/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0200c84\n') +f('sys/module/usbhid/sections/.strtab', 0o664, b'0xffffffffa0202e68\n') +f('sys/module/usbhid/sections/.rodata', 0o664, b'0xffffffffa0200cc0\n') +f('sys/module/usbhid/sections/__param', 0o664, b'0xffffffffa0201de0\n') +f('sys/module/usbhid/sections/.bss', 0o664, b'0xffffffffa0203d80\n') +f('sys/module/usbhid/sections/.text', 0o664, b'0xffffffffa01fe000\n') +f('sys/module/usbhid/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/usbhid/sections/.data', 0o664, b'0xffffffffa02037c0\n') +f('sys/module/usbhid/sections/.symtab', 0o664, b'0xffffffffa0201e90\n') +f('sys/module/usbhid/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02039c0\n') +f('sys/module/usbhid/sections/.rodata.str1.1', 0o664, b'0xffffffffa02017a8\n') +f('sys/module/usbhid/sections/__kcrctab_gpl', 0o664, b'0xffffffffa0201e70\n') +d('sys/module/usbhid/notes', 0o775) +f('sys/module/usbhid/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00F\xd8\xa9\xb5\x91:~\xd6KY>\x94\xe1\x1d\xab\xf6\xe5\xeeu*') +d('sys/module/iwl3945', 0o775) +f('sys/module/iwl3945/version', 0o664, b'1.2.26ks\n') +f('sys/module/iwl3945/initstate', 0o664, b'live\n') +f('sys/module/iwl3945/srcversion', 0o664, b'5C079549ABD48E07B20F3C7\n') +f('sys/module/iwl3945/refcnt', 0o664, b'0\n') +d('sys/module/iwl3945/drivers', 0o775) +l('sys/module/iwl3945/drivers/pci:iwl3945', '../../../bus/pci/drivers/iwl3945') +d('sys/module/iwl3945/parameters', 0o775) +f('sys/module/iwl3945/parameters/disable_hw_scan', 0o664, b'0\n') +f('sys/module/iwl3945/parameters/queues_num', 0o664, b'8\n') +f('sys/module/iwl3945/parameters/debug', 0o664, b'0\n') +f('sys/module/iwl3945/parameters/disable', 0o664, b'0\n') +f('sys/module/iwl3945/parameters/hwcrypto', 0o664, b'0\n') +f('sys/module/iwl3945/parameters/antenna', 0o664, b'0\n') +f('sys/module/iwl3945/parameters/qos_enable', 0o664, b'1\n') +d('sys/module/iwl3945/sections', 0o775) +f('sys/module/iwl3945/sections/.smp_locks', 0o664, b'0xffffffffa015e0e0\n') +f('sys/module/iwl3945/sections/__bug_table', 0o664, b'0xffffffffa015e300\n') +f('sys/module/iwl3945/sections/.exit.text', 0o664, b'0xffffffffa015b2e4\n') +f('sys/module/iwl3945/sections/.note.gnu.build-id', 0o664, b'0xffffffffa015b2fc\n') +f('sys/module/iwl3945/sections/.strtab', 0o664, b'0xffffffffa0160f20\n') +f('sys/module/iwl3945/sections/.devexit.text', 0o664, b'0xffffffffa015b044\n') +f('sys/module/iwl3945/sections/.rodata', 0o664, b'0xffffffffa015b320\n') +f('sys/module/iwl3945/sections/__param', 0o664, b'0xffffffffa015e4b0\n') +f('sys/module/iwl3945/sections/.bss', 0o664, b'0xffffffffa0163d80\n') +f('sys/module/iwl3945/sections/.text', 0o664, b'0xffffffffa014b000\n') +f('sys/module/iwl3945/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/iwl3945/sections/.data', 0o664, b'0xffffffffa0162f00\n') +f('sys/module/iwl3945/sections/.symtab', 0o664, b'0xffffffffa015e5c8\n') +f('sys/module/iwl3945/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa01639c0\n') +f('sys/module/iwl3945/sections/.rodata.str1.1', 0o664, b'0xffffffffa015bc0c\n') +d('sys/module/iwl3945/notes', 0o775) +f('sys/module/iwl3945/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xd1^"`\xf9\xf2&\x0b\xe0T\x9b\xe1,\xab\x88\x9bos\x0b\xdb') +d('sys/module/rsrc_nonstatic', 0o775) +f('sys/module/rsrc_nonstatic/initstate', 0o664, b'live\n') +f('sys/module/rsrc_nonstatic/srcversion', 0o664, b'8554CBDFE6293476856E830\n') +f('sys/module/rsrc_nonstatic/refcnt', 0o664, b'1\n') +d('sys/module/rsrc_nonstatic/holders', 0o775) +l('sys/module/rsrc_nonstatic/holders/yenta_socket', '../../yenta_socket') +d('sys/module/rsrc_nonstatic/parameters', 0o775) +f('sys/module/rsrc_nonstatic/parameters/probe_mem', 0o664, b'1\n') +d('sys/module/rsrc_nonstatic/sections', 0o775) +f('sys/module/rsrc_nonstatic/sections/__ksymtab_strings', 0o664, b'0xffffffffa00ef8a0\n') +f('sys/module/rsrc_nonstatic/sections/.exit.text', 0o664, b'0xffffffffa00ef624\n') +f('sys/module/rsrc_nonstatic/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00ef69c\n') +f('sys/module/rsrc_nonstatic/sections/.strtab', 0o664, b'0xffffffffa00f0260\n') +f('sys/module/rsrc_nonstatic/sections/__ksymtab', 0o664, b'0xffffffffa00ef860\n') +f('sys/module/rsrc_nonstatic/sections/.devexit.text', 0o664, b'0xffffffffa00ef636\n') +f('sys/module/rsrc_nonstatic/sections/.rodata', 0o664, b'0xffffffffa00ef6c0\n') +f('sys/module/rsrc_nonstatic/sections/__param', 0o664, b'0xffffffffa00ef878\n') +f('sys/module/rsrc_nonstatic/sections/.bss', 0o664, b'0xffffffffa00f0dc0\n') +f('sys/module/rsrc_nonstatic/sections/.text', 0o664, b'0xffffffffa00ee000\n') +f('sys/module/rsrc_nonstatic/sections/.init.text', 0o664, b'0xffffffffa0084000\n') +f('sys/module/rsrc_nonstatic/sections/__kcrctab', 0o664, b'0xffffffffa00ef870\n') +f('sys/module/rsrc_nonstatic/sections/.ref.data', 0o664, b'0xffffffffa00f09c0\n') +f('sys/module/rsrc_nonstatic/sections/.data', 0o664, b'0xffffffffa00f0820\n') +f('sys/module/rsrc_nonstatic/sections/.devinit.text', 0o664, b'0xffffffffa00ef665\n') +f('sys/module/rsrc_nonstatic/sections/.symtab', 0o664, b'0xffffffffa00ef8b8\n') +f('sys/module/rsrc_nonstatic/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00f0a00\n') +f('sys/module/rsrc_nonstatic/sections/.rodata.str1.1', 0o664, b'0xffffffffa00ef78d\n') +d('sys/module/rsrc_nonstatic/notes', 0o775) +f('sys/module/rsrc_nonstatic/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xd5n\x94\x07\x89\xe1\x08\xe3\x07C\xb9\x83\x0c\x19*6\xe8\xe3\x10R') +d('sys/module/thinkpad_acpi', 0o775) +f('sys/module/thinkpad_acpi/version', 0o664, b'0.21\n') +f('sys/module/thinkpad_acpi/initstate', 0o664, b'live\n') +f('sys/module/thinkpad_acpi/srcversion', 0o664, b'FA276F7EFAA90BF39100654\n') +f('sys/module/thinkpad_acpi/refcnt', 0o664, b'0\n') +d('sys/module/thinkpad_acpi/drivers', 0o775) +l('sys/module/thinkpad_acpi/drivers/platform:thinkpad_hwmon', '../../../bus/platform/drivers/thinkpad_hwmon') +l('sys/module/thinkpad_acpi/drivers/platform:thinkpad_acpi', '../../../bus/platform/drivers/thinkpad_acpi') +d('sys/module/thinkpad_acpi/sections', 0o775) +f('sys/module/thinkpad_acpi/sections/.smp_locks', 0o664, b'0xffffffffa01e6088\n') +f('sys/module/thinkpad_acpi/sections/__bug_table', 0o664, b'0xffffffffa01e60e0\n') +f('sys/module/thinkpad_acpi/sections/.note.gnu.build-id', 0o664, b'0xffffffffa01e3a80\n') +f('sys/module/thinkpad_acpi/sections/.strtab', 0o664, b'0xffffffffa01e98b8\n') +f('sys/module/thinkpad_acpi/sections/.rodata', 0o664, b'0xffffffffa01e3ac0\n') +f('sys/module/thinkpad_acpi/sections/__param', 0o664, b'0xffffffffa01e61a0\n') +f('sys/module/thinkpad_acpi/sections/.bss', 0o664, b'0xffffffffa01ed600\n') +f('sys/module/thinkpad_acpi/sections/.text', 0o664, b'0xffffffffa01dd000\n') +f('sys/module/thinkpad_acpi/sections/.init.text', 0o664, b'0xffffffffa01ef000\n') +f('sys/module/thinkpad_acpi/sections/.data', 0o664, b'0xffffffffa01ebd60\n') +f('sys/module/thinkpad_acpi/sections/.init.data', 0o664, b'0xffffffffa01f1700\n') +f('sys/module/thinkpad_acpi/sections/.symtab', 0o664, b'0xffffffffa01e6498\n') +f('sys/module/thinkpad_acpi/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa01ed240\n') +f('sys/module/thinkpad_acpi/sections/.rodata.str1.1', 0o664, b'0xffffffffa01e3df0\n') +d('sys/module/thinkpad_acpi/notes', 0o775) +f('sys/module/thinkpad_acpi/notes/.note.gnu.build-id', 0o664, b"\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00]\xca\x1f\xba\xb1J'\xa8\x14\x83cj=h\x11\xe60;\x08\xd6") +d('sys/module/psmouse', 0o775) +d('sys/module/psmouse/drivers', 0o775) +l('sys/module/psmouse/drivers/serio:psmouse', '../../../bus/serio/drivers/psmouse') +d('sys/module/psmouse/parameters', 0o775) +f('sys/module/psmouse/parameters/proto', 0o664, b'''auto + +''') +f('sys/module/psmouse/parameters/resync_time', 0o664, b'0\n') +f('sys/module/psmouse/parameters/resolution', 0o664, b'200\n') +f('sys/module/psmouse/parameters/resetafter', 0o664, b'5\n') +f('sys/module/psmouse/parameters/rate', 0o664, b'100\n') +f('sys/module/psmouse/parameters/smartscroll', 0o664, b'Y\n') +d('sys/module/md_mod', 0o775) +f('sys/module/md_mod/initstate', 0o664, b'live\n') +f('sys/module/md_mod/srcversion', 0o664, b'1DB954BE8FA97D4755DC15B\n') +f('sys/module/md_mod/refcnt', 0o664, b'1\n') +d('sys/module/md_mod/holders', 0o775) +l('sys/module/md_mod/holders/raid1', '../../raid1') +d('sys/module/md_mod/parameters', 0o775) +f('sys/module/md_mod/parameters/start_ro', 0o664, b'0\n') +f('sys/module/md_mod/parameters/start_dirty_degraded', 0o664, b'0\n') +d('sys/module/md_mod/sections', 0o775) +f('sys/module/md_mod/sections/__ksymtab_gpl', 0o664, b'0xffffffffa022a790\n') +f('sys/module/md_mod/sections/.smp_locks', 0o664, b'0xffffffffa022a038\n') +f('sys/module/md_mod/sections/__bug_table', 0o664, b'0xffffffffa022a4b8\n') +f('sys/module/md_mod/sections/__ksymtab_strings', 0o664, b'0xffffffffa022a7f0\n') +f('sys/module/md_mod/sections/.exit.text', 0o664, b'0xffffffffa02283a0\n') +f('sys/module/md_mod/sections/.note.gnu.build-id', 0o664, b'0xffffffffa02284c8\n') +f('sys/module/md_mod/sections/.strtab', 0o664, b'0xffffffffa022d7a0\n') +f('sys/module/md_mod/sections/__ksymtab', 0o664, b'0xffffffffa022a590\n') +f('sys/module/md_mod/sections/.rodata', 0o664, b'0xffffffffa0228500\n') +f('sys/module/md_mod/sections/__param', 0o664, b'0xffffffffa022a740\n') +f('sys/module/md_mod/sections/.bss', 0o664, b'0xffffffffa0230880\n') +f('sys/module/md_mod/sections/.text', 0o664, b'0xffffffffa021a000\n') +f('sys/module/md_mod/sections/.init.text', 0o664, b'0xffffffffa0070000\n') +f('sys/module/md_mod/sections/__kcrctab', 0o664, b'0xffffffffa022a6b0\n') +f('sys/module/md_mod/sections/.data', 0o664, b'0xffffffffa022f660\n') +f('sys/module/md_mod/sections/.symtab', 0o664, b'0xffffffffa022a968\n') +f('sys/module/md_mod/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02304c0\n') +f('sys/module/md_mod/sections/.rodata.str1.1', 0o664, b'0xffffffffa022869e\n') +f('sys/module/md_mod/sections/__kcrctab_gpl', 0o664, b'0xffffffffa022a7d0\n') +d('sys/module/md_mod/notes', 0o775) +f('sys/module/md_mod/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xbd\xb6!\x84\x88Z\x8bnL\x0f\xf0\xbe\xf0]\n"\xd8\xf3\xb0*') +d('sys/module/snd_pcm', 0o775) +f('sys/module/snd_pcm/initstate', 0o664, b'live\n') +f('sys/module/snd_pcm/srcversion', 0o664, b'96530AD1426FF7F73757C4F\n') +f('sys/module/snd_pcm/refcnt', 0o664, b'2\n') +d('sys/module/snd_pcm/holders', 0o775) +l('sys/module/snd_pcm/holders/snd_hda_intel', '../../snd_hda_intel') +l('sys/module/snd_pcm/holders/snd_pcm_oss', '../../snd_pcm_oss') +d('sys/module/snd_pcm/parameters', 0o775) +f('sys/module/snd_pcm/parameters/preallocate_dma', 0o664, b'1\n') +f('sys/module/snd_pcm/parameters/maximum_substreams', 0o664, b'4\n') +d('sys/module/snd_pcm/sections', 0o775) +f('sys/module/snd_pcm/sections/.smp_locks', 0o664, b'0xffffffffa0141af8\n') +f('sys/module/snd_pcm/sections/__ex_table', 0o664, b'0xffffffffa0141b30\n') +f('sys/module/snd_pcm/sections/__ksymtab_strings', 0o664, b'0xffffffffa01415f0\n') +f('sys/module/snd_pcm/sections/.exit.text', 0o664, b'0xffffffffa01401d4\n') +f('sys/module/snd_pcm/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0140260\n') +f('sys/module/snd_pcm/sections/.strtab', 0o664, b'0xffffffffa0145428\n') +f('sys/module/snd_pcm/sections/.fixup', 0o664, b'0xffffffffa01401fe\n') +f('sys/module/snd_pcm/sections/__ksymtab', 0o664, b'0xffffffffa01410b0\n') +f('sys/module/snd_pcm/sections/.rodata', 0o664, b'0xffffffffa01402a0\n') +f('sys/module/snd_pcm/sections/__param', 0o664, b'0xffffffffa0141bb0\n') +f('sys/module/snd_pcm/sections/.bss', 0o664, b'0xffffffffa0149640\n') +f('sys/module/snd_pcm/sections/.text', 0o664, b'0xffffffffa0134000\n') +f('sys/module/snd_pcm/sections/.init.text', 0o664, b'0xffffffffa007d000\n') +f('sys/module/snd_pcm/sections/__kcrctab', 0o664, b'0xffffffffa0141430\n') +f('sys/module/snd_pcm/sections/.data', 0o664, b'0xffffffffa0148b60\n') +f('sys/module/snd_pcm/sections/.symtab', 0o664, b'0xffffffffa0141c00\n') +f('sys/module/snd_pcm/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0149280\n') +f('sys/module/snd_pcm/sections/.rodata.str1.1', 0o664, b'0xffffffffa0140930\n') +d('sys/module/snd_pcm/notes', 0o775) +f('sys/module/snd_pcm/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xc8N\x86\x9c\x8dq\x14\x04\xe7\xed\xee\x9b\xe0\x8f\xe4\x8fvF{\xfe') +d('sys/module/snd_hda_intel', 0o775) +f('sys/module/snd_hda_intel/initstate', 0o664, b'live\n') +f('sys/module/snd_hda_intel/srcversion', 0o664, b'B76633A09F11336101E5480\n') +f('sys/module/snd_hda_intel/refcnt', 0o664, b'3\n') +d('sys/module/snd_hda_intel/drivers', 0o775) +l('sys/module/snd_hda_intel/drivers/pci:HDA Intel', '../../../bus/pci/drivers/HDA Intel') +d('sys/module/snd_hda_intel/parameters', 0o775) +f('sys/module/snd_hda_intel/parameters/bdl_pos_adj', 0o664, b'1,-1,-1,-1,-1,-1,-1,-1\n') +f('sys/module/snd_hda_intel/parameters/enable', 0o664, b'Y,Y,Y,Y,Y,Y,Y,Y\n') +f('sys/module/snd_hda_intel/parameters/id', 0o664, b',,,,,,,\n') +f('sys/module/snd_hda_intel/parameters/probe_mask', 0o664, b'1,-1,-1,-1,-1,-1,-1,-1\n') +f('sys/module/snd_hda_intel/parameters/enable_msi', 0o664, b'0\n') +f('sys/module/snd_hda_intel/parameters/index', 0o664, b'-1,-1,-1,-1,-1,-1,-1,-1\n') +f('sys/module/snd_hda_intel/parameters/single_cmd', 0o664, b'N\n') +f('sys/module/snd_hda_intel/parameters/model', 0o664, b',,,,,,,\n') +f('sys/module/snd_hda_intel/parameters/position_fix', 0o664, b'0,0,0,0,0,0,0,0\n') +d('sys/module/snd_hda_intel/sections', 0o775) +f('sys/module/snd_hda_intel/sections/.devinit.data', 0o664, b'0xffffffffa01d7340\n') +f('sys/module/snd_hda_intel/sections/.exit.text', 0o664, b'0xffffffffa0182a58\n') +f('sys/module/snd_hda_intel/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0183f4c\n') +f('sys/module/snd_hda_intel/sections/.strtab', 0o664, b'0xffffffffa0193910\n') +f('sys/module/snd_hda_intel/sections/.devexit.text', 0o664, b'0xffffffffa0182a6a\n') +f('sys/module/snd_hda_intel/sections/.rodata', 0o664, b'0xffffffffa0183f80\n') +f('sys/module/snd_hda_intel/sections/__param', 0o664, b'0xffffffffa0189de8\n') +f('sys/module/snd_hda_intel/sections/.bss', 0o664, b'0xffffffffa01d7800\n') +f('sys/module/snd_hda_intel/sections/.text', 0o664, b'0xffffffffa0165000\n') +f('sys/module/snd_hda_intel/sections/.init.text', 0o664, b'0xffffffffa0070000\n') +f('sys/module/snd_hda_intel/sections/.data', 0o664, b'0xffffffffa019bd40\n') +f('sys/module/snd_hda_intel/sections/.devinit.text', 0o664, b'0xffffffffa0182aa0\n') +f('sys/module/snd_hda_intel/sections/.symtab', 0o664, b'0xffffffffa0189f50\n') +f('sys/module/snd_hda_intel/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa01d7440\n') +f('sys/module/snd_hda_intel/sections/.rodata.str1.1', 0o664, b'0xffffffffa0186d8b\n') +d('sys/module/snd_hda_intel/notes', 0o775) +f('sys/module/snd_hda_intel/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x002\xfe\x91\xd2K\x86\x1d\x92P\xdcX/c\x07=\xf3\xceY\xbc-') +d('sys/module/ehci_hcd', 0o775) +f('sys/module/ehci_hcd/initstate', 0o664, b'live\n') +f('sys/module/ehci_hcd/srcversion', 0o664, b'6EBBF13EC8AD467D8AB11A4\n') +f('sys/module/ehci_hcd/refcnt', 0o664, b'0\n') +d('sys/module/ehci_hcd/drivers', 0o775) +l('sys/module/ehci_hcd/drivers/pci:ehci_hcd', '../../../bus/pci/drivers/ehci_hcd') +d('sys/module/ehci_hcd/parameters', 0o775) +f('sys/module/ehci_hcd/parameters/park', 0o664, b'0\n') +f('sys/module/ehci_hcd/parameters/ignore_oc', 0o664, b'N\n') +f('sys/module/ehci_hcd/parameters/log2_irq_thresh', 0o664, b'0\n') +d('sys/module/ehci_hcd/sections', 0o775) +f('sys/module/ehci_hcd/sections/.smp_locks', 0o664, b'0xffffffffa00e4048\n') +f('sys/module/ehci_hcd/sections/__bug_table', 0o664, b'0xffffffffa00e3f22\n') +f('sys/module/ehci_hcd/sections/.exit.text', 0o664, b'0xffffffffa00e3b98\n') +f('sys/module/ehci_hcd/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00e3bac\n') +f('sys/module/ehci_hcd/sections/.strtab', 0o664, b'0xffffffffa00e54a8\n') +f('sys/module/ehci_hcd/sections/.rodata', 0o664, b'0xffffffffa00e3be0\n') +f('sys/module/ehci_hcd/sections/__param', 0o664, b'0xffffffffa00e42f0\n') +f('sys/module/ehci_hcd/sections/.bss', 0o664, b'0xffffffffa00e6480\n') +f('sys/module/ehci_hcd/sections/.text', 0o664, b'0xffffffffa00dd000\n') +f('sys/module/ehci_hcd/sections/.init.text', 0o664, b'0xffffffffa006b000\n') +f('sys/module/ehci_hcd/sections/.data', 0o664, b'0xffffffffa00e5f40\n') +f('sys/module/ehci_hcd/sections/.symtab', 0o664, b'0xffffffffa00e4368\n') +f('sys/module/ehci_hcd/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00e60c0\n') +f('sys/module/ehci_hcd/sections/.rodata.str1.1', 0o664, b'0xffffffffa00e3dd0\n') +d('sys/module/ehci_hcd/notes', 0o775) +f('sys/module/ehci_hcd/notes/.note.gnu.build-id', 0o664, b"\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00 \xc7\x01\xa9Mi;\xcaNB'\x08T\xc4\xf9\x80\xd7\x10\xb3h") +d('sys/module/sg', 0o775) +f('sys/module/sg/version', 0o664, b'3.5.34\n') +f('sys/module/sg/initstate', 0o664, b'live\n') +f('sys/module/sg/srcversion', 0o664, b'DC7DE342543B6D7AB46D718\n') +f('sys/module/sg/refcnt', 0o664, b'0\n') +d('sys/module/sg/parameters', 0o775) +f('sys/module/sg/parameters/allow_dio', 0o664, b'0\n') +f('sys/module/sg/parameters/scatter_elem_sz', 0o664, b'32768\n') +f('sys/module/sg/parameters/def_reserved_size', 0o664, b'32768\n') +d('sys/module/sg/sections', 0o775) +f('sys/module/sg/sections/.smp_locks', 0o664, b'0xffffffffa00054d8\n') +f('sys/module/sg/sections/__ex_table', 0o664, b'0xffffffffa0005530\n') +f('sys/module/sg/sections/__bug_table', 0o664, b'0xffffffffa00054e8\n') +f('sys/module/sg/sections/.exit.text', 0o664, b'0xffffffffa00049f0\n') +f('sys/module/sg/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0004afc\n') +f('sys/module/sg/sections/.strtab', 0o664, b'0xffffffffa0006710\n') +f('sys/module/sg/sections/.fixup', 0o664, b'0xffffffffa0004a33\n') +f('sys/module/sg/sections/.rodata', 0o664, b'0xffffffffa0004b20\n') +f('sys/module/sg/sections/__param', 0o664, b'0xffffffffa0005630\n') +f('sys/module/sg/sections/.bss', 0o664, b'0xffffffffa0007640\n') +f('sys/module/sg/sections/.text', 0o664, b'0xffffffffa0000000\n') +f('sys/module/sg/sections/.init.text', 0o664, b'0xffffffffa0009000\n') +f('sys/module/sg/sections/.data', 0o664, b'0xffffffffa0007040\n') +f('sys/module/sg/sections/.symtab', 0o664, b'0xffffffffa00056a8\n') +f('sys/module/sg/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0007280\n') +f('sys/module/sg/sections/.rodata.str1.1', 0o664, b'0xffffffffa0004bc0\n') +d('sys/module/sg/notes', 0o775) +f('sys/module/sg/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00q\x06\xb5<\xb3\x13\xd4\xe6\xc5W\xbb;{\x14\x93\xd5\x07\xc7\x13\xfa') +d('sys/module/snd_mixer_oss', 0o775) +f('sys/module/snd_mixer_oss/initstate', 0o664, b'live\n') +f('sys/module/snd_mixer_oss/srcversion', 0o664, b'9D2BFE821DD0ACFA2CFF364\n') +f('sys/module/snd_mixer_oss/refcnt', 0o664, b'1\n') +d('sys/module/snd_mixer_oss/holders', 0o775) +l('sys/module/snd_mixer_oss/holders/snd_pcm_oss', '../../snd_pcm_oss') +d('sys/module/snd_mixer_oss/sections', 0o775) +f('sys/module/snd_mixer_oss/sections/__ksymtab_strings', 0o664, b'0xffffffffa02bba78\n') +f('sys/module/snd_mixer_oss/sections/.exit.text', 0o664, b'0xffffffffa02bb508\n') +f('sys/module/snd_mixer_oss/sections/.note.gnu.build-id', 0o664, b'0xffffffffa02bb54c\n') +f('sys/module/snd_mixer_oss/sections/.strtab', 0o664, b'0xffffffffa02bc470\n') +f('sys/module/snd_mixer_oss/sections/__ksymtab', 0o664, b'0xffffffffa02bba60\n') +f('sys/module/snd_mixer_oss/sections/.rodata', 0o664, b'0xffffffffa02bb580\n') +f('sys/module/snd_mixer_oss/sections/.bss', 0o664, b'0xffffffffa02bd240\n') +f('sys/module/snd_mixer_oss/sections/.text', 0o664, b'0xffffffffa02b9000\n') +f('sys/module/snd_mixer_oss/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/snd_mixer_oss/sections/__kcrctab', 0o664, b'0xffffffffa02bba70\n') +f('sys/module/snd_mixer_oss/sections/.data', 0o664, b'0xffffffffa02bcb20\n') +f('sys/module/snd_mixer_oss/sections/.symtab', 0o664, b'0xffffffffa02bba98\n') +f('sys/module/snd_mixer_oss/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02bce80\n') +f('sys/module/snd_mixer_oss/sections/.rodata.str1.1', 0o664, b'0xffffffffa02bb760\n') +d('sys/module/snd_mixer_oss/notes', 0o775) +f('sys/module/snd_mixer_oss/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xc3u\x0b\x0eh,\x90W\xba\xf3S\xa9\x16\\<\x97u\x0f.\xa6') +d('sys/module/pcmcia', 0o775) +f('sys/module/pcmcia/initstate', 0o664, b'live\n') +f('sys/module/pcmcia/srcversion', 0o664, b'6544CB07B8D7D79F19A4CD6\n') +f('sys/module/pcmcia/refcnt', 0o664, b'0\n') +d('sys/module/pcmcia/parameters', 0o775) +f('sys/module/pcmcia/parameters/io_speed', 0o664, b'0\n') +d('sys/module/pcmcia/sections', 0o775) +f('sys/module/pcmcia/sections/__ksymtab_strings', 0o664, b'0xffffffffa01f9890\n') +f('sys/module/pcmcia/sections/.exit.text', 0o664, b'0xffffffffa01f85c4\n') +f('sys/module/pcmcia/sections/.note.gnu.build-id', 0o664, b'0xffffffffa01f86c8\n') +f('sys/module/pcmcia/sections/.strtab', 0o664, b'0xffffffffa01fb138\n') +f('sys/module/pcmcia/sections/__ksymtab', 0o664, b'0xffffffffa01f9710\n') +f('sys/module/pcmcia/sections/.rodata', 0o664, b'0xffffffffa01f8700\n') +f('sys/module/pcmcia/sections/__param', 0o664, b'0xffffffffa01f9a00\n') +f('sys/module/pcmcia/sections/.bss', 0o664, b'0xffffffffa01fcb40\n') +f('sys/module/pcmcia/sections/.text', 0o664, b'0xffffffffa01f5000\n') +f('sys/module/pcmcia/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/pcmcia/sections/__kcrctab', 0o664, b'0xffffffffa01f9810\n') +f('sys/module/pcmcia/sections/.ref.data', 0o664, b'0xffffffffa01fc720\n') +f('sys/module/pcmcia/sections/.data', 0o664, b'0xffffffffa01fc3a0\n') +f('sys/module/pcmcia/sections/.devinit.text', 0o664, b'0xffffffffa01f85e2\n') +f('sys/module/pcmcia/sections/.symtab', 0o664, b'0xffffffffa01f9a28\n') +f('sys/module/pcmcia/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa01fc780\n') +f('sys/module/pcmcia/sections/.rodata.str1.1', 0o664, b'0xffffffffa01f913d\n') +d('sys/module/pcmcia/notes', 0o775) +f('sys/module/pcmcia/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00v\xd6BR5q\xd2\xd4\x05y\xe0\x84j\x17\xab\xb2\xe6o\xd43') +d('sys/module/nvram', 0o775) +f('sys/module/nvram/initstate', 0o664, b'live\n') +f('sys/module/nvram/srcversion', 0o664, b'ECD12B2949BC771BDCE8146\n') +f('sys/module/nvram/refcnt', 0o664, b'1\n') +d('sys/module/nvram/holders', 0o775) +l('sys/module/nvram/holders/thinkpad_acpi', '../../thinkpad_acpi') +d('sys/module/nvram/sections', 0o775) +f('sys/module/nvram/sections/__ksymtab_strings', 0o664, b'0xffffffffa00ad2c0\n') +f('sys/module/nvram/sections/.exit.text', 0o664, b'0xffffffffa00ace3c\n') +f('sys/module/nvram/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00ace5c\n') +f('sys/module/nvram/sections/.strtab', 0o664, b'0xffffffffa00adc38\n') +f('sys/module/nvram/sections/__ksymtab', 0o664, b'0xffffffffa00ad230\n') +f('sys/module/nvram/sections/.rodata', 0o664, b'0xffffffffa00ace80\n') +f('sys/module/nvram/sections/.bss', 0o664, b'0xffffffffa00ae640\n') +f('sys/module/nvram/sections/.text', 0o664, b'0xffffffffa00ac000\n') +f('sys/module/nvram/sections/.init.text', 0o664, b'0xffffffffa00b0000\n') +f('sys/module/nvram/sections/__kcrctab', 0o664, b'0xffffffffa00ad290\n') +f('sys/module/nvram/sections/.data', 0o664, b'0xffffffffa00ae200\n') +f('sys/module/nvram/sections/.symtab', 0o664, b'0xffffffffa00ad338\n') +f('sys/module/nvram/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00ae280\n') +f('sys/module/nvram/sections/.rodata.str1.1', 0o664, b'0xffffffffa00acfb8\n') +d('sys/module/nvram/notes', 0o775) +f('sys/module/nvram/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\x00j\xf9\trf\x94M\xafD\\s\xced\xcc\x97c\xd5L\n') +d('sys/module/scsi_mod', 0o775) +d('sys/module/scsi_mod/parameters', 0o775) +f('sys/module/scsi_mod/parameters/scan', 0o664, b'sync\n') +f('sys/module/scsi_mod/parameters/default_dev_flags', 0o664, b'0\n') +f('sys/module/scsi_mod/parameters/scsi_logging_level', 0o664, b'0\n') +f('sys/module/scsi_mod/parameters/inq_timeout', 0o664, b'5\n') +f('sys/module/scsi_mod/parameters/max_luns', 0o664, b'512\n') +f('sys/module/scsi_mod/parameters/max_report_luns', 0o664, b'511\n') +d('sys/module/pcmcia_core', 0o775) +f('sys/module/pcmcia_core/initstate', 0o664, b'live\n') +f('sys/module/pcmcia_core/srcversion', 0o664, b'7C1220572DE8897E4D560EB\n') +f('sys/module/pcmcia_core/refcnt', 0o664, b'3\n') +d('sys/module/pcmcia_core/holders', 0o775) +l('sys/module/pcmcia_core/holders/yenta_socket', '../../yenta_socket') +l('sys/module/pcmcia_core/holders/rsrc_nonstatic', '../../rsrc_nonstatic') +l('sys/module/pcmcia_core/holders/pcmcia', '../../pcmcia') +d('sys/module/pcmcia_core/parameters', 0o775) +f('sys/module/pcmcia_core/parameters/setup_delay', 0o664, b'10\n') +f('sys/module/pcmcia_core/parameters/cis_speed', 0o664, b'300\n') +f('sys/module/pcmcia_core/parameters/unreset_delay', 0o664, b'10\n') +f('sys/module/pcmcia_core/parameters/shutdown_delay', 0o664, b'3\n') +f('sys/module/pcmcia_core/parameters/cis_width', 0o664, b'0\n') +f('sys/module/pcmcia_core/parameters/unreset_limit', 0o664, b'30\n') +f('sys/module/pcmcia_core/parameters/reset_time', 0o664, b'10\n') +f('sys/module/pcmcia_core/parameters/resume_delay', 0o664, b'20\n') +f('sys/module/pcmcia_core/parameters/unreset_check', 0o664, b'10\n') +f('sys/module/pcmcia_core/parameters/vcc_settle', 0o664, b'40\n') +d('sys/module/pcmcia_core/sections', 0o775) +f('sys/module/pcmcia_core/sections/__ksymtab_strings', 0o664, b'0xffffffffa0094310\n') +f('sys/module/pcmcia_core/sections/.exit.text', 0o664, b'0xffffffffa0093558\n') +f('sys/module/pcmcia_core/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0093668\n') +f('sys/module/pcmcia_core/sections/.strtab', 0o664, b'0xffffffffa0096898\n') +f('sys/module/pcmcia_core/sections/__ksymtab', 0o664, b'0xffffffffa0093e50\n') +f('sys/module/pcmcia_core/sections/.rodata', 0o664, b'0xffffffffa00936a0\n') +f('sys/module/pcmcia_core/sections/__param', 0o664, b'0xffffffffa0094180\n') +f('sys/module/pcmcia_core/sections/.bss', 0o664, b'0xffffffffa0098f40\n') +f('sys/module/pcmcia_core/sections/.text', 0o664, b'0xffffffffa008f000\n') +f('sys/module/pcmcia_core/sections/.init.text', 0o664, b'0xffffffffa009a000\n') +f('sys/module/pcmcia_core/sections/__kcrctab', 0o664, b'0xffffffffa0094070\n') +f('sys/module/pcmcia_core/sections/.data', 0o664, b'0xffffffffa0098700\n') +f('sys/module/pcmcia_core/sections/.symtab', 0o664, b'0xffffffffa00945d0\n') +f('sys/module/pcmcia_core/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0098b80\n') +f('sys/module/pcmcia_core/sections/.rodata.str1.1', 0o664, b'0xffffffffa0093a88\n') +f('sys/module/pcmcia_core/sections/.ref.text', 0o664, b'0xffffffffa0093580\n') +d('sys/module/pcmcia_core/notes', 0o775) +f('sys/module/pcmcia_core/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00M\xe5~\xb9\x10\x7f(\xb8\x18\xe2ma\xb4\xdc\x9a\x8er\xb2t\xbc') +d('sys/module/rtc_core', 0o775) +f('sys/module/rtc_core/initstate', 0o664, b'live\n') +f('sys/module/rtc_core/srcversion', 0o664, b'8684A14821938B7D8E50DB5\n') +f('sys/module/rtc_core/refcnt', 0o664, b'1\n') +d('sys/module/rtc_core/holders', 0o775) +l('sys/module/rtc_core/holders/rtc_cmos', '../../rtc_cmos') +d('sys/module/rtc_core/sections', 0o775) +f('sys/module/rtc_core/sections/__ksymtab_gpl', 0o664, b'0xffffffffa00ea380\n') +f('sys/module/rtc_core/sections/.smp_locks', 0o664, b'0xffffffffa00ea5b8\n') +f('sys/module/rtc_core/sections/__ksymtab_strings', 0o664, b'0xffffffffa00ea4d0\n') +f('sys/module/rtc_core/sections/.exit.text', 0o664, b'0xffffffffa00e9e60\n') +f('sys/module/rtc_core/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00e9ea4\n') +f('sys/module/rtc_core/sections/.strtab', 0o664, b'0xffffffffa00eb9c0\n') +f('sys/module/rtc_core/sections/.rodata', 0o664, b'0xffffffffa00e9ee0\n') +f('sys/module/rtc_core/sections/.bss', 0o664, b'0xffffffffa00ecd80\n') +f('sys/module/rtc_core/sections/.text', 0o664, b'0xffffffffa00e8000\n') +f('sys/module/rtc_core/sections/.init.text', 0o664, b'0xffffffffa007d000\n') +f('sys/module/rtc_core/sections/.data', 0o664, b'0xffffffffa00ec760\n') +f('sys/module/rtc_core/sections/.symtab', 0o664, b'0xffffffffa00ea5e0\n') +f('sys/module/rtc_core/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00ec9c0\n') +f('sys/module/rtc_core/sections/.rodata.str1.1', 0o664, b'0xffffffffa00ea098\n') +f('sys/module/rtc_core/sections/__kcrctab_gpl', 0o664, b'0xffffffffa00ea460\n') +d('sys/module/rtc_core/notes', 0o775) +f('sys/module/rtc_core/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xfbj\x90X\x98\xf7\x0e\x95\x19\xc6\xa1\xa1\xcd\xe0\x835$\x0e\x96\x17') +d('sys/module/led_class', 0o775) +f('sys/module/led_class/initstate', 0o664, b'live\n') +f('sys/module/led_class/srcversion', 0o664, b'B916A50F53ABBBB19DFF203\n') +f('sys/module/led_class/refcnt', 0o664, b'2\n') +d('sys/module/led_class/holders', 0o775) +l('sys/module/led_class/holders/iwl3945', '../../iwl3945') +l('sys/module/led_class/holders/thinkpad_acpi', '../../thinkpad_acpi') +d('sys/module/led_class/sections', 0o775) +f('sys/module/led_class/sections/__ksymtab_gpl', 0o664, b'0xffffffffa00f23c0\n') +f('sys/module/led_class/sections/__ksymtab_strings', 0o664, b'0xffffffffa00f2420\n') +f('sys/module/led_class/sections/.exit.text', 0o664, b'0xffffffffa00f2330\n') +f('sys/module/led_class/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00f2344\n') +f('sys/module/led_class/sections/.strtab', 0o664, b'0xffffffffa00f2bf8\n') +f('sys/module/led_class/sections/.bss', 0o664, b'0xffffffffa00f3500\n') +f('sys/module/led_class/sections/.text', 0o664, b'0xffffffffa00f2000\n') +f('sys/module/led_class/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/led_class/sections/.data', 0o664, b'0xffffffffa00f30c0\n') +f('sys/module/led_class/sections/.symtab', 0o664, b'0xffffffffa00f2478\n') +f('sys/module/led_class/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00f3140\n') +f('sys/module/led_class/sections/.rodata.str1.1', 0o664, b'0xffffffffa00f2368\n') +f('sys/module/led_class/sections/__kcrctab_gpl', 0o664, b'0xffffffffa00f2400\n') +d('sys/module/led_class/notes', 0o775) +f('sys/module/led_class/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00Iq;\xaf\xad\xf1\xe5\xcf8\xa5\x86u\xa9tMV\x02*\xfd\r') +d('sys/module/libata', 0o775) +d('sys/module/libata/parameters', 0o775) +f('sys/module/libata/parameters/acpi_gtf_filter', 0o664, b'7\n') +f('sys/module/libata/parameters/noacpi', 0o664, b'0\n') +f('sys/module/libata/parameters/atapi_passthru16', 0o664, b'1\n') +f('sys/module/libata/parameters/ata_probe_timeout', 0o664, b'0\n') +f('sys/module/libata/parameters/dma', 0o664, b'7\n') +f('sys/module/libata/parameters/atapi_dmadir', 0o664, b'0\n') +f('sys/module/libata/parameters/fua', 0o664, b'0\n') +f('sys/module/libata/parameters/ignore_hpa', 0o664, b'0\n') +f('sys/module/libata/parameters/atapi_enabled', 0o664, b'1\n') +f('sys/module/libata/parameters/allow_tpm', 0o664, b'0\n') +d('sys/module/thermal', 0o775) +f('sys/module/thermal/initstate', 0o664, b'live\n') +f('sys/module/thermal/srcversion', 0o664, b'1787CE9FEB053C917D031A9\n') +f('sys/module/thermal/refcnt', 0o664, b'0\n') +d('sys/module/thermal/parameters', 0o775) +f('sys/module/thermal/parameters/act', 0o664, b'0\n') +f('sys/module/thermal/parameters/tzp', 0o664, b'0\n') +f('sys/module/thermal/parameters/crt', 0o664, b'0\n') +f('sys/module/thermal/parameters/psv', 0o664, b'0\n') +d('sys/module/thermal/sections', 0o775) +f('sys/module/thermal/sections/.exit.text', 0o664, b'0xffffffffa00a1f14\n') +f('sys/module/thermal/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00a1f3c\n') +f('sys/module/thermal/sections/.strtab', 0o664, b'0xffffffffa00a3b28\n') +f('sys/module/thermal/sections/.rodata', 0o664, b'0xffffffffa00a1f60\n') +f('sys/module/thermal/sections/__param', 0o664, b'0xffffffffa00a29d0\n') +f('sys/module/thermal/sections/.bss', 0o664, b'0xffffffffa00a4bc0\n') +f('sys/module/thermal/sections/.text', 0o664, b'0xffffffffa00a0000\n') +f('sys/module/thermal/sections/.init.text', 0o664, b'0xffffffffa0070000\n') +f('sys/module/thermal/sections/.data', 0o664, b'0xffffffffa00a4640\n') +f('sys/module/thermal/sections/.init.data', 0o664, b'0xffffffffa0070090\n') +f('sys/module/thermal/sections/.symtab', 0o664, b'0xffffffffa00a2ac0\n') +f('sys/module/thermal/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00a4800\n') +f('sys/module/thermal/sections/.rodata.str1.1', 0o664, b'0xffffffffa00a242a\n') +d('sys/module/thermal/notes', 0o775) +f('sys/module/thermal/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\x97\xa9\xec\xf2\x01\x86!\x94\x89\xa4n%q\t\xb7\xb4\x97a\x1a\x85') +d('sys/module/keyboard', 0o775) +d('sys/module/keyboard/parameters', 0o775) +f('sys/module/keyboard/parameters/brl_nbchords', 0o664, b'1\n') +f('sys/module/keyboard/parameters/brl_timeout', 0o664, b'300\n') +d('sys/module/ahci', 0o775) +d('sys/module/ahci/drivers', 0o775) +l('sys/module/ahci/drivers/pci:ahci', '../../../bus/pci/drivers/ahci') +d('sys/module/ahci/parameters', 0o775) +f('sys/module/ahci/parameters/marvell_enable', 0o664, b'1\n') +f('sys/module/ahci/parameters/ahci_em_messages', 0o664, b'1\n') +f('sys/module/ahci/parameters/skip_host_reset', 0o664, b'0\n') +d('sys/module/snd_pcm_oss', 0o775) +f('sys/module/snd_pcm_oss/initstate', 0o664, b'live\n') +f('sys/module/snd_pcm_oss/srcversion', 0o664, b'E3D05A52B04130012283029\n') +f('sys/module/snd_pcm_oss/refcnt', 0o664, b'0\n') +d('sys/module/snd_pcm_oss/parameters', 0o775) +f('sys/module/snd_pcm_oss/parameters/dsp_map', 0o664, b'0,0,0,0,0,0,0,0\n') +f('sys/module/snd_pcm_oss/parameters/nonblock_open', 0o664, b'Y\n') +f('sys/module/snd_pcm_oss/parameters/adsp_map', 0o664, b'1,1,1,1,1,1,1,1\n') +d('sys/module/snd_pcm_oss/sections', 0o775) +f('sys/module/snd_pcm_oss/sections/.exit.text', 0o664, b'0xffffffffa02c6e7c\n') +f('sys/module/snd_pcm_oss/sections/.note.gnu.build-id', 0o664, b'0xffffffffa02c6e94\n') +f('sys/module/snd_pcm_oss/sections/.strtab', 0o664, b'0xffffffffa02c8818\n') +f('sys/module/snd_pcm_oss/sections/.rodata', 0o664, b'0xffffffffa02c6ec0\n') +f('sys/module/snd_pcm_oss/sections/__param', 0o664, b'0xffffffffa02c7378\n') +f('sys/module/snd_pcm_oss/sections/.bss', 0o664, b'0xffffffffa02c9b00\n') +f('sys/module/snd_pcm_oss/sections/.text', 0o664, b'0xffffffffa02bf000\n') +f('sys/module/snd_pcm_oss/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/snd_pcm_oss/sections/.data', 0o664, b'0xffffffffa02c96c0\n') +f('sys/module/snd_pcm_oss/sections/.symtab', 0o664, b'0xffffffffa02c73f0\n') +f('sys/module/snd_pcm_oss/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02c9740\n') +f('sys/module/snd_pcm_oss/sections/.rodata.str1.1', 0o664, b'0xffffffffa02c71a8\n') +d('sys/module/snd_pcm_oss/notes', 0o775) +f('sys/module/snd_pcm_oss/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xd7y|\xbf\xa5\x8aZm\x86\x85CF\x11s\xd3\xf5f\xbd7\xc6') +d('sys/module/ac', 0o775) +f('sys/module/ac/initstate', 0o664, b'live\n') +f('sys/module/ac/srcversion', 0o664, b'6E9CD20EE5BE8425A61B938\n') +f('sys/module/ac/refcnt', 0o664, b'0\n') +d('sys/module/ac/sections', 0o775) +f('sys/module/ac/sections/.exit.text', 0o664, b'0xffffffffa006d43c\n') +f('sys/module/ac/sections/.note.gnu.build-id', 0o664, b'0xffffffffa006d45c\n') +f('sys/module/ac/sections/.strtab', 0o664, b'0xffffffffa006dd28\n') +f('sys/module/ac/sections/.rodata', 0o664, b'0xffffffffa006d480\n') +f('sys/module/ac/sections/.bss', 0o664, b'0xffffffffa006e600\n') +f('sys/module/ac/sections/.text', 0o664, b'0xffffffffa006d000\n') +f('sys/module/ac/sections/.init.text', 0o664, b'0xffffffffa0070000\n') +f('sys/module/ac/sections/.data', 0o664, b'0xffffffffa006e0d0\n') +f('sys/module/ac/sections/.symtab', 0o664, b'0xffffffffa006d668\n') +f('sys/module/ac/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa006e240\n') +f('sys/module/ac/sections/.rodata.str1.1', 0o664, b'0xffffffffa006d5a0\n') +d('sys/module/ac/notes', 0o775) +f('sys/module/ac/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00^h\xf0\x19\xcc\x94"G\xf8\xbc\x1c\xf0\xa3\x8d?\xec\xa5\xc4\x95\x9f') +d('sys/module/dock', 0o775) +d('sys/module/dock/parameters', 0o775) +f('sys/module/dock/parameters/immediate_undock', 0o664, b'Y\n') +d('sys/module/pcie_aspm', 0o775) +d('sys/module/pcie_aspm/parameters', 0o775) +f('sys/module/pcie_aspm/parameters/policy', 0o664, b'[default] performance powersave \n') +d('sys/module/lockdep', 0o775) +d('sys/module/lockdep/parameters', 0o775) +f('sys/module/lockdep/parameters/lock_stat', 0o664, b'1\n') +d('sys/module/tcp_cubic', 0o775) +d('sys/module/tcp_cubic/parameters', 0o775) +f('sys/module/tcp_cubic/parameters/tcp_friendliness', 0o664, b'1\n') +f('sys/module/tcp_cubic/parameters/beta', 0o664, b'717\n') +f('sys/module/tcp_cubic/parameters/bic_scale', 0o664, b'41\n') +f('sys/module/tcp_cubic/parameters/fast_convergence', 0o664, b'1\n') +f('sys/module/tcp_cubic/parameters/initial_ssthresh', 0o664, b'0\n') +d('sys/module/ecb', 0o775) +f('sys/module/ecb/initstate', 0o664, b'live\n') +f('sys/module/ecb/srcversion', 0o664, b'5BBA8E5CDEA4EA8BA5ED31D\n') +f('sys/module/ecb/refcnt', 0o664, b'2\n') +d('sys/module/ecb/sections', 0o775) +f('sys/module/ecb/sections/.exit.text', 0o664, b'0xffffffffa0027300\n') +f('sys/module/ecb/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0027314\n') +f('sys/module/ecb/sections/.strtab', 0o664, b'0xffffffffa00277c0\n') +f('sys/module/ecb/sections/.bss', 0o664, b'0xffffffffa0027e80\n') +f('sys/module/ecb/sections/.text', 0o664, b'0xffffffffa0027000\n') +f('sys/module/ecb/sections/.init.text', 0o664, b'0xffffffffa006b000\n') +f('sys/module/ecb/sections/.data', 0o664, b'0xffffffffa0027a40\n') +f('sys/module/ecb/sections/.symtab', 0o664, b'0xffffffffa0027340\n') +f('sys/module/ecb/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0027ac0\n') +f('sys/module/ecb/sections/.rodata.str1.1', 0o664, b'0xffffffffa0027338\n') +d('sys/module/ecb/notes', 0o775) +f('sys/module/ecb/notes/.note.gnu.build-id', 0o664, b"\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xc20'\x18T\x8bW#\xf5\xe5\xf8JvI\xcb\xc4\x91\x95\nJ") +d('sys/module/snd_page_alloc', 0o775) +f('sys/module/snd_page_alloc/initstate', 0o664, b'live\n') +f('sys/module/snd_page_alloc/srcversion', 0o664, b'D9E59C27F28D5DA2B935016\n') +f('sys/module/snd_page_alloc/refcnt', 0o664, b'2\n') +d('sys/module/snd_page_alloc/holders', 0o775) +l('sys/module/snd_page_alloc/holders/snd_pcm', '../../snd_pcm') +l('sys/module/snd_page_alloc/holders/snd_hda_intel', '../../snd_hda_intel') +d('sys/module/snd_page_alloc/sections', 0o775) +f('sys/module/snd_page_alloc/sections/__ksymtab_strings', 0o664, b'0xffffffffa00350e8\n') +f('sys/module/snd_page_alloc/sections/.exit.text', 0o664, b'0xffffffffa0034cc0\n') +f('sys/module/snd_page_alloc/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0034cf8\n') +f('sys/module/snd_page_alloc/sections/.strtab', 0o664, b'0xffffffffa0035be8\n') +f('sys/module/snd_page_alloc/sections/__ksymtab', 0o664, b'0xffffffffa0035040\n') +f('sys/module/snd_page_alloc/sections/.rodata', 0o664, b'0xffffffffa0034d20\n') +f('sys/module/snd_page_alloc/sections/.bss', 0o664, b'0xffffffffa0036780\n') +f('sys/module/snd_page_alloc/sections/.text', 0o664, b'0xffffffffa0034000\n') +f('sys/module/snd_page_alloc/sections/.init.text', 0o664, b'0xffffffffa0038000\n') +f('sys/module/snd_page_alloc/sections/__kcrctab', 0o664, b'0xffffffffa00350b0\n') +f('sys/module/snd_page_alloc/sections/.data', 0o664, b'0xffffffffa0036300\n') +f('sys/module/snd_page_alloc/sections/.symtab', 0o664, b'0xffffffffa0035180\n') +f('sys/module/snd_page_alloc/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00363c0\n') +f('sys/module/snd_page_alloc/sections/.rodata.str1.1', 0o664, b'0xffffffffa0034fd5\n') +d('sys/module/snd_page_alloc/notes', 0o775) +f('sys/module/snd_page_alloc/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00s\xc1\x8a\x9a\xf7g\x83-x\xc0\xbe\x98\xb0[\x95"\xd7\x97Q=') +d('sys/module/loop', 0o775) +f('sys/module/loop/initstate', 0o664, b'live\n') +f('sys/module/loop/srcversion', 0o664, b'7595F5D46DFDB4A2D489DDD\n') +f('sys/module/loop/refcnt', 0o664, b'0\n') +d('sys/module/loop/sections', 0o775) +f('sys/module/loop/sections/__bug_table', 0o664, b'0xffffffffa023ca1f\n') +f('sys/module/loop/sections/__ksymtab_strings', 0o664, b'0xffffffffa023caf0\n') +f('sys/module/loop/sections/.exit.text', 0o664, b'0xffffffffa023c72c\n') +f('sys/module/loop/sections/.note.gnu.build-id', 0o664, b'0xffffffffa023c7e4\n') +f('sys/module/loop/sections/.strtab', 0o664, b'0xffffffffa023d960\n') +f('sys/module/loop/sections/__ksymtab', 0o664, b'0xffffffffa023ca70\n') +f('sys/module/loop/sections/.rodata', 0o664, b'0xffffffffa023c808\n') +f('sys/module/loop/sections/__param', 0o664, b'0xffffffffa023caa0\n') +f('sys/module/loop/sections/.bss', 0o664, b'0xffffffffa023e780\n') +f('sys/module/loop/sections/.text', 0o664, b'0xffffffffa023a000\n') +f('sys/module/loop/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/loop/sections/__kcrctab', 0o664, b'0xffffffffa023ca90\n') +f('sys/module/loop/sections/.data', 0o664, b'0xffffffffa023e180\n') +f('sys/module/loop/sections/.symtab', 0o664, b'0xffffffffa023cb20\n') +f('sys/module/loop/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa023e3c0\n') +f('sys/module/loop/sections/.rodata.str1.1', 0o664, b'0xffffffffa023c88a\n') +d('sys/module/loop/notes', 0o775) +f('sys/module/loop/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x007;\xf4\xa1\x0e\xe8\x13\xedX\xe6\xbc\xa4\xcd\xde_\x7fe\x84\x90\x85') +d('sys/module/aes_generic', 0o775) +f('sys/module/aes_generic/initstate', 0o664, b'live\n') +f('sys/module/aes_generic/srcversion', 0o664, b'CE7DEF557FD2F72DE36DE4A\n') +f('sys/module/aes_generic/refcnt', 0o664, b'1\n') +d('sys/module/aes_generic/holders', 0o775) +l('sys/module/aes_generic/holders/aes_x86_64', '../../aes_x86_64') +d('sys/module/aes_generic/sections', 0o775) +f('sys/module/aes_generic/sections/__ksymtab_gpl', 0o664, b'0xffffffffa02ccef0\n') +f('sys/module/aes_generic/sections/__ksymtab_strings', 0o664, b'0xffffffffa02ccf80\n') +f('sys/module/aes_generic/sections/.exit.text', 0o664, b'0xffffffffa02cceb8\n') +f('sys/module/aes_generic/sections/.note.gnu.build-id', 0o664, b'0xffffffffa02ccecc\n') +f('sys/module/aes_generic/sections/.strtab', 0o664, b'0xffffffffa02cd678\n') +f('sys/module/aes_generic/sections/.bss', 0o664, b'0xffffffffa02cdf80\n') +f('sys/module/aes_generic/sections/.text', 0o664, b'0xffffffffa02cb000\n') +f('sys/module/aes_generic/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/aes_generic/sections/.data', 0o664, b'0xffffffffa02cda80\n') +f('sys/module/aes_generic/sections/.init.data', 0o664, b'0xffffffffa0065300\n') +f('sys/module/aes_generic/sections/.symtab', 0o664, b'0xffffffffa02ccfe8\n') +f('sys/module/aes_generic/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02cdbc0\n') +f('sys/module/aes_generic/sections/__kcrctab_gpl', 0o664, b'0xffffffffa02ccf50\n') +d('sys/module/aes_generic/notes', 0o775) +f('sys/module/aes_generic/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00V@\xa6&\x10\xf7X\xe0q\xbf\xb9G\xd9d\x004\x06h\xe6\x13') +d('sys/module/snd_seq_device', 0o775) +f('sys/module/snd_seq_device/initstate', 0o664, b'live\n') +f('sys/module/snd_seq_device/srcversion', 0o664, b'A166653189DAF15E3F2B588\n') +f('sys/module/snd_seq_device/refcnt', 0o664, b'1\n') +d('sys/module/snd_seq_device/holders', 0o775) +l('sys/module/snd_seq_device/holders/snd_seq', '../../snd_seq') +d('sys/module/snd_seq_device/sections', 0o775) +f('sys/module/snd_seq_device/sections/__ksymtab_strings', 0o664, b'0xffffffffa02a5d10\n') +f('sys/module/snd_seq_device/sections/.exit.text', 0o664, b'0xffffffffa02a5a5c\n') +f('sys/module/snd_seq_device/sections/.note.gnu.build-id', 0o664, b'0xffffffffa02a5a90\n') +f('sys/module/snd_seq_device/sections/.strtab', 0o664, b'0xffffffffa02a66e0\n') +f('sys/module/snd_seq_device/sections/__ksymtab', 0o664, b'0xffffffffa02a5c80\n') +f('sys/module/snd_seq_device/sections/.bss', 0o664, b'0xffffffffa02a7280\n') +f('sys/module/snd_seq_device/sections/.text', 0o664, b'0xffffffffa02a5000\n') +f('sys/module/snd_seq_device/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/snd_seq_device/sections/__kcrctab', 0o664, b'0xffffffffa02a5ce0\n') +f('sys/module/snd_seq_device/sections/.data', 0o664, b'0xffffffffa02a6de0\n') +f('sys/module/snd_seq_device/sections/.symtab', 0o664, b'0xffffffffa02a5db0\n') +f('sys/module/snd_seq_device/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa02a6ec0\n') +f('sys/module/snd_seq_device/sections/.rodata.str1.1', 0o664, b'0xffffffffa02a5bd0\n') +d('sys/module/snd_seq_device/notes', 0o775) +f('sys/module/snd_seq_device/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xb6B\x93\xc2\xcc\x83\xa8\xfc\xc2r\xf6\x8c\xcej\n\xc5\x87ys\r') +d('sys/module/8250', 0o775) +d('sys/module/8250/parameters', 0o775) +f('sys/module/8250/parameters/share_irqs', 0o664, b'0\n') +f('sys/module/8250/parameters/nr_uarts', 0o664, b'4\n') +d('sys/module/ipv6', 0o775) +f('sys/module/ipv6/initstate', 0o664, b'live\n') +f('sys/module/ipv6/srcversion', 0o664, b'184C844E7A78529619B4C9D\n') +f('sys/module/ipv6/refcnt', 0o664, b'10\n') +d('sys/module/ipv6/sections', 0o775) +f('sys/module/ipv6/sections/__ksymtab_gpl', 0o664, b'0xffffffffa028ac10\n') +f('sys/module/ipv6/sections/.smp_locks', 0o664, b'0xffffffffa028a240\n') +f('sys/module/ipv6/sections/__bug_table', 0o664, b'0xffffffffa0288edd\n') +f('sys/module/ipv6/sections/__ksymtab_strings', 0o664, b'0xffffffffa028b108\n') +f('sys/module/ipv6/sections/.exit.text', 0o664, b'0xffffffffa0285e40\n') +f('sys/module/ipv6/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0286024\n') +f('sys/module/ipv6/sections/.strtab', 0o664, b'0xffffffffa02937f0\n') +f('sys/module/ipv6/sections/__ksymtab', 0o664, b'0xffffffffa028ad90\n') +f('sys/module/ipv6/sections/.rodata', 0o664, b'0xffffffffa0286060\n') +f('sys/module/ipv6/sections/.data.read_mostly', 0o664, b'0xffffffffa029cf20\n') +f('sys/module/ipv6/sections/.bss', 0o664, b'0xffffffffa029dd80\n') +f('sys/module/ipv6/sections/.text', 0o664, b'0xffffffffa0258000\n') +f('sys/module/ipv6/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/ipv6/sections/__kcrctab', 0o664, b'0xffffffffa028afe0\n') +f('sys/module/ipv6/sections/.data', 0o664, b'0xffffffffa02998c0\n') +f('sys/module/ipv6/sections/.init.data', 0o664, b'0xffffffffa0065d80\n') +f('sys/module/ipv6/sections/.symtab', 0o664, b'0xffffffffa028b4c8\n') +f('sys/module/ipv6/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa029d9c0\n') +f('sys/module/ipv6/sections/.rodata.str1.1', 0o664, b'0xffffffffa02883c0\n') +f('sys/module/ipv6/sections/.ref.text', 0o664, b'0xffffffffa0285f40\n') +f('sys/module/ipv6/sections/__kcrctab_gpl', 0o664, b'0xffffffffa028ad10\n') +d('sys/module/ipv6/notes', 0o775) +f('sys/module/ipv6/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\x90\x01\xde\xf3>\xfd_r\xbc\xbb\x16\xbd\xceIf\xc2vC\xbd\xc9') +d('sys/module/microcode', 0o775) +f('sys/module/microcode/initstate', 0o664, b'live\n') +f('sys/module/microcode/srcversion', 0o664, b'FC3DA13E858B639D12F2043\n') +f('sys/module/microcode/refcnt', 0o664, b'0\n') +d('sys/module/microcode/sections', 0o775) +f('sys/module/microcode/sections/__bug_table', 0o664, b'0xffffffffa02516f7\n') +f('sys/module/microcode/sections/.exit.text', 0o664, b'0xffffffffa0250ff6\n') +f('sys/module/microcode/sections/.note.gnu.build-id', 0o664, b'0xffffffffa0251040\n') +f('sys/module/microcode/sections/.strtab', 0o664, b'0xffffffffa02520b8\n') +f('sys/module/microcode/sections/.rodata', 0o664, b'0xffffffffa0251080\n') +f('sys/module/microcode/sections/.bss', 0o664, b'0xffffffffa0252c40\n') +f('sys/module/microcode/sections/.text', 0o664, b'0xffffffffa0250000\n') +f('sys/module/microcode/sections/.init.text', 0o664, b'0xffffffffa0065000\n') +f('sys/module/microcode/sections/.ref.data', 0o664, b'0xffffffffa0252850\n') +f('sys/module/microcode/sections/.data', 0o664, b'0xffffffffa0252600\n') +f('sys/module/microcode/sections/.symtab', 0o664, b'0xffffffffa0251740\n') +f('sys/module/microcode/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa0252880\n') +f('sys/module/microcode/sections/.rodata.str1.1', 0o664, b'0xffffffffa0251218\n') +f('sys/module/microcode/sections/.cpuinit.text', 0o664, b'0xffffffffa0250d90\n') +d('sys/module/microcode/notes', 0o775) +f('sys/module/microcode/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\x81 p\x0b\x99+\x14\x05\x9c\xb2\xf6{\xacs\xa9\xf3<\xb5\x99\x1a') +d('sys/module/i8042', 0o775) +d('sys/module/i8042/parameters', 0o775) +f('sys/module/i8042/parameters/debug', 0o664, b'N\n') +f('sys/module/i8042/parameters/panicblink', 0o664, b'500\n') +d('sys/module/usbcore', 0o775) +f('sys/module/usbcore/initstate', 0o664, b'live\n') +f('sys/module/usbcore/srcversion', 0o664, b'4FF77EB8DAB25F4076D7357\n') +f('sys/module/usbcore/refcnt', 0o664, b'5\n') +d('sys/module/usbcore/holders', 0o775) +l('sys/module/usbcore/holders/uhci_hcd', '../../uhci_hcd') +l('sys/module/usbcore/holders/usb_storage', '../../usb_storage') +l('sys/module/usbcore/holders/cdc_acm', '../../cdc_acm') +l('sys/module/usbcore/holders/usbhid', '../../usbhid') +l('sys/module/usbcore/holders/ehci_hcd', '../../ehci_hcd') +d('sys/module/usbcore/drivers', 0o775) +l('sys/module/usbcore/drivers/usb:usbfs', '../../../bus/usb/drivers/usbfs') +l('sys/module/usbcore/drivers/usb:usb', '../../../bus/usb/drivers/usb') +l('sys/module/usbcore/drivers/usb:hub', '../../../bus/usb/drivers/hub') +d('sys/module/usbcore/parameters', 0o775) +f('sys/module/usbcore/parameters/use_both_schemes', 0o664, b'Y\n') +f('sys/module/usbcore/parameters/blinkenlights', 0o664, b'N\n') +f('sys/module/usbcore/parameters/usbfs_snoop', 0o664, b'N\n') +f('sys/module/usbcore/parameters/autosuspend', 0o664, b'2\n') +f('sys/module/usbcore/parameters/nousb', 0o664, b'N\n') +f('sys/module/usbcore/parameters/old_scheme_first', 0o664, b'N\n') +d('sys/module/usbcore/sections', 0o775) +f('sys/module/usbcore/sections/__ksymtab_gpl', 0o664, b'0xffffffffa004ea30\n') +f('sys/module/usbcore/sections/.smp_locks', 0o664, b'0xffffffffa004f930\n') +f('sys/module/usbcore/sections/__ex_table', 0o664, b'0xffffffffa004fa58\n') +f('sys/module/usbcore/sections/__bug_table', 0o664, b'0xffffffffa004fa40\n') +f('sys/module/usbcore/sections/__ksymtab_strings', 0o664, b'0xffffffffa004f300\n') +f('sys/module/usbcore/sections/.exit.text', 0o664, b'0xffffffffa004ba30\n') +f('sys/module/usbcore/sections/.note.gnu.build-id', 0o664, b'0xffffffffa004bb30\n') +f('sys/module/usbcore/sections/.strtab', 0o664, b'0xffffffffa0055cf8\n') +f('sys/module/usbcore/sections/.fixup', 0o664, b'0xffffffffa004ba87\n') +f('sys/module/usbcore/sections/.rodata', 0o664, b'0xffffffffa004bb60\n') +f('sys/module/usbcore/sections/__param', 0o664, b'0xffffffffa004f210\n') +f('sys/module/usbcore/sections/.bss', 0o664, b'0xffffffffa005cec0\n') +f('sys/module/usbcore/sections/.text', 0o664, b'0xffffffffa0038000\n') +f('sys/module/usbcore/sections/.init.text', 0o664, b'0xffffffffa0027000\n') +f('sys/module/usbcore/sections/.data', 0o664, b'0xffffffffa005af00\n') +f('sys/module/usbcore/sections/.symtab', 0o664, b'0xffffffffa004fb18\n') +f('sys/module/usbcore/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa005cb00\n') +f('sys/module/usbcore/sections/.rodata.str1.1', 0o664, b'0xffffffffa004c044\n') +f('sys/module/usbcore/sections/__kcrctab_gpl', 0o664, b'0xffffffffa004ef70\n') +d('sys/module/usbcore/notes', 0o775) +f('sys/module/usbcore/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00!\xbeP\xa2@m\xffg\xff\x1b\xa8\x8f\xd2\xb3\x11\x14[\xb0\x89\x1e') +d('sys/module/intel_agp', 0o775) +f('sys/module/intel_agp/initstate', 0o664, b'live\n') +f('sys/module/intel_agp/srcversion', 0o664, b'98AFACFFF6A1ADC3A6FAB67\n') +f('sys/module/intel_agp/refcnt', 0o664, b'0\n') +d('sys/module/intel_agp/drivers', 0o775) +l('sys/module/intel_agp/drivers/pci:agpgart-intel', '../../../bus/pci/drivers/agpgart-intel') +d('sys/module/intel_agp/sections', 0o775) +f('sys/module/intel_agp/sections/.smp_locks', 0o664, b'0xffffffffa008ae38\n') +f('sys/module/intel_agp/sections/.exit.text', 0o664, b'0xffffffffa00893ac\n') +f('sys/module/intel_agp/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00896b0\n') +f('sys/module/intel_agp/sections/.strtab', 0o664, b'0xffffffffa008c1b8\n') +f('sys/module/intel_agp/sections/.devexit.text', 0o664, b'0xffffffffa00893be\n') +f('sys/module/intel_agp/sections/.rodata', 0o664, b'0xffffffffa00896e0\n') +f('sys/module/intel_agp/sections/.bss', 0o664, b'0xffffffffa008da00\n') +f('sys/module/intel_agp/sections/.text', 0o664, b'0xffffffffa0086000\n') +f('sys/module/intel_agp/sections/.init.text', 0o664, b'0xffffffffa008f000\n') +f('sys/module/intel_agp/sections/.data', 0o664, b'0xffffffffa008cf60\n') +f('sys/module/intel_agp/sections/.devinit.text', 0o664, b'0xffffffffa0089400\n') +f('sys/module/intel_agp/sections/.symtab', 0o664, b'0xffffffffa008ae50\n') +f('sys/module/intel_agp/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa008d640\n') +f('sys/module/intel_agp/sections/.rodata.str1.1', 0o664, b'0xffffffffa008a9c0\n') +d('sys/module/intel_agp/notes', 0o775) +f('sys/module/intel_agp/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\xb0\xb5IU\x04F\xdb\x80\xdf\x9a8\xedq\x0b\xd4\xc7K\x851\x86') +d('sys/module/evdev', 0o775) +f('sys/module/evdev/initstate', 0o664, b'live\n') +f('sys/module/evdev/srcversion', 0o664, b'6F6934C1F95317926EA0520\n') +f('sys/module/evdev/refcnt', 0o664, b'5\n') +d('sys/module/evdev/sections', 0o775) +f('sys/module/evdev/sections/.exit.text', 0o664, b'0xffffffffa00b3724\n') +f('sys/module/evdev/sections/.note.gnu.build-id', 0o664, b'0xffffffffa00b3738\n') +f('sys/module/evdev/sections/.strtab', 0o664, b'0xffffffffa00b4610\n') +f('sys/module/evdev/sections/.rodata', 0o664, b'0xffffffffa00b3760\n') +f('sys/module/evdev/sections/.bss', 0o664, b'0xffffffffa00b50c0\n') +f('sys/module/evdev/sections/.text', 0o664, b'0xffffffffa00b2000\n') +f('sys/module/evdev/sections/.init.text', 0o664, b'0xffffffffa00b7000\n') +f('sys/module/evdev/sections/.data', 0o664, b'0xffffffffa00b4be0\n') +f('sys/module/evdev/sections/.symtab', 0o664, b'0xffffffffa00b3b60\n') +f('sys/module/evdev/sections/.gnu.linkonce.this_module', 0o664, b'0xffffffffa00b4d00\n') +f('sys/module/evdev/sections/.rodata.str1.1', 0o664, b'0xffffffffa00b3a38\n') +d('sys/module/evdev/notes', 0o775) +f('sys/module/evdev/notes/.note.gnu.build-id', 0o664, b'\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00\x8d/u!\xb1\xf2\xe7\x10z\x8a\xf7\x0c\x88\x17\x1c4i\\2\xa8') +d('sys/module/atkbd', 0o775) +d('sys/module/atkbd/drivers', 0o775) +l('sys/module/atkbd/drivers/serio:atkbd', '../../../bus/serio/drivers/atkbd') +d('sys/class', 0o755) +d('sys/class/rfkill', 0o755) +l('sys/class/rfkill/rfkill0', '../../devices/platform/thinkpad_acpi/rfkill/rfkill0') +d('sys/class/rtc', 0o755) +l('sys/class/rtc/rtc0', '../../devices/pnp0/00:07/rtc/rtc0') +d('sys/class/usb_endpoint', 0o755) +l('sys/class/usb_endpoint/usbdev1.1_ep00', '../../devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00') +l('sys/class/usb_endpoint/usbdev4.3_ep83', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83') +l('sys/class/usb_endpoint/usbdev4.2_ep04', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04') +l('sys/class/usb_endpoint/usbdev1.1_ep81', '../../devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81') +l('sys/class/usb_endpoint/usbdev3.1_ep81', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81') +l('sys/class/usb_endpoint/usbdev4.1_ep00', '../../devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00') +l('sys/class/usb_endpoint/usbdev3.4_ep00', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00') +l('sys/class/usb_endpoint/usbdev4.2_ep00', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00') +l('sys/class/usb_endpoint/usbdev5.7_ep81', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81') +l('sys/class/usb_endpoint/usbdev5.9_ep81', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81') +l('sys/class/usb_endpoint/usbdev5.9_ep83', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83') +l('sys/class/usb_endpoint/usbdev5.9_ep84', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84') +l('sys/class/usb_endpoint/usbdev5.9_ep00', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00') +l('sys/class/usb_endpoint/usbdev4.2_ep03', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03') +l('sys/class/usb_endpoint/usbdev4.2_ep84', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84') +l('sys/class/usb_endpoint/usbdev3.1_ep00', '../../devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00') +l('sys/class/usb_endpoint/usbdev4.2_ep83', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83') +l('sys/class/usb_endpoint/usbdev4.2_ep02', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02') +l('sys/class/usb_endpoint/usbdev4.3_ep00', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00') +l('sys/class/usb_endpoint/usbdev5.7_ep00', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00') +l('sys/class/usb_endpoint/usbdev4.1_ep81', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81') +l('sys/class/usb_endpoint/usbdev5.9_ep02', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02') +l('sys/class/usb_endpoint/usbdev4.2_ep82', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82') +l('sys/class/usb_endpoint/usbdev2.1_ep81', '../../devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81') +l('sys/class/usb_endpoint/usbdev4.3_ep81', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81') +l('sys/class/usb_endpoint/usbdev2.1_ep00', '../../devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00') +l('sys/class/usb_endpoint/usbdev5.1_ep81', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81') +l('sys/class/usb_endpoint/usbdev4.2_ep81', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81') +l('sys/class/usb_endpoint/usbdev3.4_ep81', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81') +l('sys/class/usb_endpoint/usbdev4.3_ep02', '../../devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02') +l('sys/class/usb_endpoint/usbdev5.7_ep02', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02') +l('sys/class/usb_endpoint/usbdev5.1_ep00', '../../devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00') +l('sys/class/usb_endpoint/usbdev5.9_ep01', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01') +l('sys/class/usb_endpoint/usbdev5.9_ep82', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82') +d('sys/class/ieee80211', 0o755) +l('sys/class/ieee80211/phy0', '../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0/ieee80211/phy0') +d('sys/class/scsi_disk', 0o755) +l('sys/class/scsi_disk/7:0:0:0', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0') +l('sys/class/scsi_disk/0:0:0:0', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0') +d('sys/class/vc', 0o755) +l('sys/class/vc/vcsa3', '../../devices/virtual/vc/vcsa3') +l('sys/class/vc/vcsa6', '../../devices/virtual/vc/vcsa6') +l('sys/class/vc/vcsa2', '../../devices/virtual/vc/vcsa2') +l('sys/class/vc/vcsa', '../../devices/virtual/vc/vcsa') +l('sys/class/vc/vcs2', '../../devices/virtual/vc/vcs2') +l('sys/class/vc/vcs7', '../../devices/virtual/vc/vcs7') +l('sys/class/vc/vcsa5', '../../devices/virtual/vc/vcsa5') +l('sys/class/vc/vcsa10', '../../devices/virtual/vc/vcsa10') +l('sys/class/vc/vcs10', '../../devices/virtual/vc/vcs10') +l('sys/class/vc/vcsa1', '../../devices/virtual/vc/vcsa1') +l('sys/class/vc/vcsa4', '../../devices/virtual/vc/vcsa4') +l('sys/class/vc/vcs', '../../devices/virtual/vc/vcs') +l('sys/class/vc/vcs1', '../../devices/virtual/vc/vcs1') +l('sys/class/vc/vcs4', '../../devices/virtual/vc/vcs4') +l('sys/class/vc/vcsa7', '../../devices/virtual/vc/vcsa7') +l('sys/class/vc/vcs6', '../../devices/virtual/vc/vcs6') +l('sys/class/vc/vcs3', '../../devices/virtual/vc/vcs3') +l('sys/class/vc/vcs5', '../../devices/virtual/vc/vcs5') +d('sys/class/mem', 0o755) +l('sys/class/mem/zero', '../../devices/virtual/mem/zero') +l('sys/class/mem/kmsg', '../../devices/virtual/mem/kmsg') +l('sys/class/mem/mem', '../../devices/virtual/mem/mem') +l('sys/class/mem/urandom', '../../devices/virtual/mem/urandom') +l('sys/class/mem/port', '../../devices/virtual/mem/port') +l('sys/class/mem/null', '../../devices/virtual/mem/null') +l('sys/class/mem/kmem', '../../devices/virtual/mem/kmem') +l('sys/class/mem/full', '../../devices/virtual/mem/full') +l('sys/class/mem/random', '../../devices/virtual/mem/random') +d('sys/class/pci_bus', 0o755) +l('sys/class/pci_bus/0000:00', '../../devices/pci0000:00/pci_bus/0000:00') +l('sys/class/pci_bus/0000:01', '../../devices/pci0000:00/0000:00:01.0/pci_bus/0000:01') +l('sys/class/pci_bus/0000:03', '../../devices/pci0000:00/0000:00:1c.1/pci_bus/0000:03') +l('sys/class/pci_bus/0000:0c', '../../devices/pci0000:00/0000:00:1c.3/pci_bus/0000:0c') +l('sys/class/pci_bus/0000:16', '../../devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pci_bus/0000:16') +l('sys/class/pci_bus/0000:04', '../../devices/pci0000:00/0000:00:1c.2/pci_bus/0000:04') +l('sys/class/pci_bus/0000:02', '../../devices/pci0000:00/0000:00:1c.0/pci_bus/0000:02') +l('sys/class/pci_bus/0000:15', '../../devices/pci0000:00/0000:00:1e.0/pci_bus/0000:15') +d('sys/class/hwmon', 0o755) +l('sys/class/hwmon/hwmon0', '../../devices/platform/thinkpad_hwmon/hwmon/hwmon0') +d('sys/class/net', 0o755) +l('sys/class/net/wmaster0', '../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0') +l('sys/class/net/wlan0', '../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0') +l('sys/class/net/lo', '../../devices/virtual/net/lo') +l('sys/class/net/eth0', '../../devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0') +d('sys/class/dmi', 0o755) +l('sys/class/dmi/id', '../../devices/virtual/dmi/id') +d('sys/class/firmware', 0o755) +f('sys/class/firmware/timeout', 0o644, b'60\n') +d('sys/class/scsi_generic', 0o755) +l('sys/class/scsi_generic/sg0', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_generic/sg0') +l('sys/class/scsi_generic/sg1', '../../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_generic/sg1') +l('sys/class/scsi_generic/sg2', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg2') +d('sys/class/bdi', 0o755) +l('sys/class/bdi/7:1', '../../devices/virtual/bdi/7:1') +l('sys/class/bdi/7:0', '../../devices/virtual/bdi/7:0') +l('sys/class/bdi/7:2', '../../devices/virtual/bdi/7:2') +l('sys/class/bdi/7:4', '../../devices/virtual/bdi/7:4') +l('sys/class/bdi/7:3', '../../devices/virtual/bdi/7:3') +l('sys/class/bdi/11:0', '../../devices/virtual/bdi/11:0') +l('sys/class/bdi/7:5', '../../devices/virtual/bdi/7:5') +l('sys/class/bdi/8:0', '../../devices/virtual/bdi/8:0') +l('sys/class/bdi/default', '../../devices/virtual/bdi/default') +l('sys/class/bdi/0:16', '../../devices/virtual/bdi/0:16') +l('sys/class/bdi/8:16', '../../devices/virtual/bdi/8:16') +l('sys/class/bdi/9:0', '../../devices/virtual/bdi/9:0') +l('sys/class/bdi/7:7', '../../devices/virtual/bdi/7:7') +l('sys/class/bdi/7:6', '../../devices/virtual/bdi/7:6') +d('sys/class/leds', 0o755) +l('sys/class/leds/iwl-phy0:TX', '../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:TX') +l('sys/class/leds/tpacpi::bay_active', '../../devices/platform/thinkpad_acpi/leds/tpacpi::bay_active') +l('sys/class/leds/tpacpi:orange:batt', '../../devices/platform/thinkpad_acpi/leds/tpacpi:orange:batt') +l('sys/class/leds/tpacpi::dock_active', '../../devices/platform/thinkpad_acpi/leds/tpacpi::dock_active') +l('sys/class/leds/tpacpi::unknown_led', '../../devices/platform/thinkpad_acpi/leds/tpacpi::unknown_led') +l('sys/class/leds/iwl-phy0:assoc', '../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:assoc') +l('sys/class/leds/tpacpi:green:batt', '../../devices/platform/thinkpad_acpi/leds/tpacpi:green:batt') +l('sys/class/leds/iwl-phy0:radio', '../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:radio') +l('sys/class/leds/iwl-phy0:RX', '../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:RX') +l('sys/class/leds/tpacpi::dock_batt', '../../devices/platform/thinkpad_acpi/leds/tpacpi::dock_batt') +l('sys/class/leds/tpacpi::thinklight', '../../devices/platform/thinkpad_acpi/leds/tpacpi::thinklight') +l('sys/class/leds/tpacpi::power', '../../devices/platform/thinkpad_acpi/leds/tpacpi::power') +l('sys/class/leds/tpacpi::standby', '../../devices/platform/thinkpad_acpi/leds/tpacpi::standby') +d('sys/class/usb_host', 0o755) +l('sys/class/usb_host/usb_host1', '../../devices/pci0000:00/0000:00:1d.0/usb_host/usb_host1') +l('sys/class/usb_host/usb_host2', '../../devices/pci0000:00/0000:00:1d.1/usb_host/usb_host2') +l('sys/class/usb_host/usb_host4', '../../devices/pci0000:00/0000:00:1d.3/usb_host/usb_host4') +l('sys/class/usb_host/usb_host5', '../../devices/pci0000:00/0000:00:1d.7/usb_host/usb_host5') +l('sys/class/usb_host/usb_host3', '../../devices/pci0000:00/0000:00:1d.2/usb_host/usb_host3') +d('sys/class/pcmcia_socket', 0o755) +l('sys/class/pcmcia_socket/pcmcia_socket0', '../../devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0') +d('sys/class/sound', 0o755) +l('sys/class/sound/audio', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/audio') +l('sys/class/sound/dsp', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/dsp') +l('sys/class/sound/timer', '../../devices/virtual/sound/timer') +l('sys/class/sound/card0', '../../devices/pci0000:00/0000:00:1b.0/sound/card0') +l('sys/class/sound/seq', '../../devices/virtual/sound/seq') +l('sys/class/sound/mixer', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/mixer') +l('sys/class/sound/pcmC0D0p', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0p') +l('sys/class/sound/controlC0', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/controlC0') +l('sys/class/sound/pcmC0D0c', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c') +l('sys/class/sound/adsp', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/adsp') +l('sys/class/sound/pcmC0D1p', '../../devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D1p') +d('sys/class/misc', 0o755) +l('sys/class/misc/uinput', '../../devices/virtual/misc/uinput') +l('sys/class/misc/fuse', '../../devices/virtual/misc/fuse') +l('sys/class/misc/hpet', '../../devices/virtual/misc/hpet') +l('sys/class/misc/cpu_dma_latency', '../../devices/virtual/misc/cpu_dma_latency') +l('sys/class/misc/mcelog', '../../devices/virtual/misc/mcelog') +l('sys/class/misc/device-mapper', '../../devices/virtual/misc/device-mapper') +l('sys/class/misc/psaux', '../../devices/virtual/misc/psaux') +l('sys/class/misc/nvram', '../../devices/virtual/misc/nvram') +l('sys/class/misc/network_latency', '../../devices/virtual/misc/network_latency') +l('sys/class/misc/network_throughput', '../../devices/virtual/misc/network_throughput') +l('sys/class/misc/microcode', '../../devices/virtual/misc/microcode') +d('sys/class/vtconsole', 0o755) +l('sys/class/vtconsole/vtcon1', '../../devices/virtual/vtconsole/vtcon1') +l('sys/class/vtconsole/vtcon0', '../../devices/virtual/vtconsole/vtcon0') +d('sys/class/bsg', 0o755) +l('sys/class/bsg/7:0:0:0', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0') +l('sys/class/bsg/0:0:0:0', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0') +l('sys/class/bsg/4:0:0:0', '../../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0') +d('sys/class/input', 0o755) +l('sys/class/input/event0', '../../devices/platform/i8042/serio0/input/input0/event0') +l('sys/class/input/input0', '../../devices/platform/i8042/serio0/input/input0') +l('sys/class/input/event4', '../../devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/event4') +l('sys/class/input/mouse0', '../../devices/platform/i8042/serio1/input/input1/mouse0') +l('sys/class/input/mouse1', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/mouse1') +l('sys/class/input/event2', '../../devices/platform/pcspkr/input/input2/event2') +l('sys/class/input/input2', '../../devices/platform/pcspkr/input/input2') +l('sys/class/input/input5', '../../devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5') +l('sys/class/input/input8', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8') +l('sys/class/input/input3', '../../devices/LNXSYSTM:00/LNXPWRBN:00/input/input3') +l('sys/class/input/input1', '../../devices/platform/i8042/serio1/input/input1') +l('sys/class/input/mice', '../../devices/virtual/input/mice') +l('sys/class/input/event6', '../../devices/virtual/input/input6/event6') +l('sys/class/input/input6', '../../devices/virtual/input/input6') +l('sys/class/input/event3', '../../devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/event3') +l('sys/class/input/event1', '../../devices/platform/i8042/serio1/input/input1/event1') +l('sys/class/input/input4', '../../devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4') +l('sys/class/input/event7', '../../devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/event7') +l('sys/class/input/event5', '../../devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/event5') +d('sys/class/thermal', 0o755) +l('sys/class/thermal/thermal_zone1', '../../devices/virtual/thermal/thermal_zone1') +l('sys/class/thermal/cooling_device1', '../../devices/virtual/thermal/cooling_device1') +l('sys/class/thermal/cooling_device0', '../../devices/virtual/thermal/cooling_device0') +l('sys/class/thermal/thermal_zone0', '../../devices/virtual/thermal/thermal_zone0') +d('sys/class/power_supply', 0o755) +l('sys/class/power_supply/AC', '../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power_supply/AC') +l('sys/class/power_supply/BAT0', '../../devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0') +d('sys/class/block', 0o755) +l('sys/class/block/loop1', '../../devices/virtual/block/loop1') +l('sys/class/block/loop7', '../../devices/virtual/block/loop7') +l('sys/class/block/loop0', '../../devices/virtual/block/loop0') +l('sys/class/block/sda10', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10') +l('sys/class/block/sr0', '../../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0') +l('sys/class/block/loop5', '../../devices/virtual/block/loop5') +l('sys/class/block/loop3', '../../devices/virtual/block/loop3') +l('sys/class/block/sda9', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9') +l('sys/class/block/sda7', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7') +l('sys/class/block/loop6', '../../devices/virtual/block/loop6') +l('sys/class/block/sdb', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb') +l('sys/class/block/sda1', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1') +l('sys/class/block/loop2', '../../devices/virtual/block/loop2') +l('sys/class/block/sda8', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8') +l('sys/class/block/sda5', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5') +l('sys/class/block/loop4', '../../devices/virtual/block/loop4') +l('sys/class/block/sda6', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6') +l('sys/class/block/sda', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda') +l('sys/class/block/md0', '../../devices/virtual/block/md0') +l('sys/class/block/sdb1', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1') +d('sys/class/scsi_host', 0o755) +l('sys/class/scsi_host/host0', '../../devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0') +l('sys/class/scsi_host/host5', '../../devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5') +l('sys/class/scsi_host/host1', '../../devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1') +l('sys/class/scsi_host/host4', '../../devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4') +l('sys/class/scsi_host/host2', '../../devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2') +l('sys/class/scsi_host/host7', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7') +l('sys/class/scsi_host/host3', '../../devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3') +d('sys/class/graphics', 0o755) +l('sys/class/graphics/fbcon', '../../devices/virtual/graphics/fbcon') +l('sys/class/graphics/fb0', '../../devices/platform/vesafb.0/graphics/fb0') +d('sys/class/tty', 0o755) +l('sys/class/tty/tty51', '../../devices/virtual/tty/tty51') +l('sys/class/tty/tty24', '../../devices/virtual/tty/tty24') +l('sys/class/tty/tty61', '../../devices/virtual/tty/tty61') +l('sys/class/tty/ttyS1', '../../devices/platform/serial8250/tty/ttyS1') +l('sys/class/tty/tty40', '../../devices/virtual/tty/tty40') +l('sys/class/tty/tty60', '../../devices/virtual/tty/tty60') +l('sys/class/tty/tty15', '../../devices/virtual/tty/tty15') +l('sys/class/tty/tty27', '../../devices/virtual/tty/tty27') +l('sys/class/tty/tty7', '../../devices/virtual/tty/tty7') +l('sys/class/tty/tty43', '../../devices/virtual/tty/tty43') +l('sys/class/tty/tty23', '../../devices/virtual/tty/tty23') +l('sys/class/tty/tty14', '../../devices/virtual/tty/tty14') +l('sys/class/tty/tty56', '../../devices/virtual/tty/tty56') +l('sys/class/tty/tty3', '../../devices/virtual/tty/tty3') +l('sys/class/tty/ttyS3', '../../devices/platform/serial8250/tty/ttyS3') +l('sys/class/tty/tty49', '../../devices/virtual/tty/tty49') +l('sys/class/tty/tty47', '../../devices/virtual/tty/tty47') +l('sys/class/tty/tty57', '../../devices/virtual/tty/tty57') +l('sys/class/tty/tty30', '../../devices/virtual/tty/tty30') +l('sys/class/tty/tty45', '../../devices/virtual/tty/tty45') +l('sys/class/tty/tty22', '../../devices/virtual/tty/tty22') +l('sys/class/tty/tty55', '../../devices/virtual/tty/tty55') +l('sys/class/tty/tty11', '../../devices/virtual/tty/tty11') +l('sys/class/tty/tty53', '../../devices/virtual/tty/tty53') +l('sys/class/tty/tty12', '../../devices/virtual/tty/tty12') +l('sys/class/tty/tty28', '../../devices/virtual/tty/tty28') +l('sys/class/tty/tty58', '../../devices/virtual/tty/tty58') +l('sys/class/tty/tty32', '../../devices/virtual/tty/tty32') +l('sys/class/tty/tty44', '../../devices/virtual/tty/tty44') +l('sys/class/tty/tty6', '../../devices/virtual/tty/tty6') +l('sys/class/tty/tty9', '../../devices/virtual/tty/tty9') +l('sys/class/tty/tty26', '../../devices/virtual/tty/tty26') +l('sys/class/tty/tty10', '../../devices/virtual/tty/tty10') +l('sys/class/tty/tty39', '../../devices/virtual/tty/tty39') +l('sys/class/tty/tty0', '../../devices/virtual/tty/tty0') +l('sys/class/tty/tty36', '../../devices/virtual/tty/tty36') +l('sys/class/tty/tty34', '../../devices/virtual/tty/tty34') +l('sys/class/tty/tty16', '../../devices/virtual/tty/tty16') +l('sys/class/tty/tty25', '../../devices/virtual/tty/tty25') +l('sys/class/tty/tty13', '../../devices/virtual/tty/tty13') +l('sys/class/tty/tty52', '../../devices/virtual/tty/tty52') +l('sys/class/tty/ttyS0', '../../devices/platform/serial8250/tty/ttyS0') +l('sys/class/tty/tty31', '../../devices/virtual/tty/tty31') +l('sys/class/tty/tty35', '../../devices/virtual/tty/tty35') +l('sys/class/tty/tty54', '../../devices/virtual/tty/tty54') +l('sys/class/tty/tty63', '../../devices/virtual/tty/tty63') +l('sys/class/tty/tty1', '../../devices/virtual/tty/tty1') +l('sys/class/tty/tty33', '../../devices/virtual/tty/tty33') +l('sys/class/tty/tty18', '../../devices/virtual/tty/tty18') +l('sys/class/tty/ttyACM0', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0') +l('sys/class/tty/tty42', '../../devices/virtual/tty/tty42') +l('sys/class/tty/tty8', '../../devices/virtual/tty/tty8') +l('sys/class/tty/tty37', '../../devices/virtual/tty/tty37') +l('sys/class/tty/tty5', '../../devices/virtual/tty/tty5') +l('sys/class/tty/tty48', '../../devices/virtual/tty/tty48') +l('sys/class/tty/tty17', '../../devices/virtual/tty/tty17') +l('sys/class/tty/tty62', '../../devices/virtual/tty/tty62') +l('sys/class/tty/tty59', '../../devices/virtual/tty/tty59') +l('sys/class/tty/tty50', '../../devices/virtual/tty/tty50') +l('sys/class/tty/tty21', '../../devices/virtual/tty/tty21') +l('sys/class/tty/ttyS2', '../../devices/platform/serial8250/tty/ttyS2') +l('sys/class/tty/tty19', '../../devices/virtual/tty/tty19') +l('sys/class/tty/ptmx', '../../devices/virtual/tty/ptmx') +l('sys/class/tty/tty46', '../../devices/virtual/tty/tty46') +l('sys/class/tty/tty2', '../../devices/virtual/tty/tty2') +l('sys/class/tty/console', '../../devices/virtual/tty/console') +l('sys/class/tty/tty41', '../../devices/virtual/tty/tty41') +l('sys/class/tty/tty4', '../../devices/virtual/tty/tty4') +l('sys/class/tty/tty29', '../../devices/virtual/tty/tty29') +l('sys/class/tty/tty', '../../devices/virtual/tty/tty') +l('sys/class/tty/tty38', '../../devices/virtual/tty/tty38') +l('sys/class/tty/tty20', '../../devices/virtual/tty/tty20') +d('sys/class/scsi_device', 0o755) +l('sys/class/scsi_device/7:0:0:0', '../../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_device/7:0:0:0') +l('sys/class/scsi_device/0:0:0:0', '../../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0') +l('sys/class/scsi_device/4:0:0:0', '../../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_device/4:0:0:0') +d('sys/block', 0o755) +l('sys/block/loop1', '../devices/virtual/block/loop1') +l('sys/block/loop7', '../devices/virtual/block/loop7') +l('sys/block/loop0', '../devices/virtual/block/loop0') +l('sys/block/sr0', '../devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0') +l('sys/block/loop5', '../devices/virtual/block/loop5') +l('sys/block/loop3', '../devices/virtual/block/loop3') +l('sys/block/loop6', '../devices/virtual/block/loop6') +l('sys/block/sdb', '../devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb') +l('sys/block/loop2', '../devices/virtual/block/loop2') +l('sys/block/loop4', '../devices/virtual/block/loop4') +l('sys/block/sda', '../devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda') +l('sys/block/md0', '../devices/virtual/block/md0') +d('sys/devices', 0o755) +d('sys/devices/system', 0o755) +d('sys/devices/system/machinecheck', 0o755) +d('sys/devices/system/machinecheck/machinecheck1', 0o755) +f('sys/devices/system/machinecheck/machinecheck1/trigger', 0o644, b'\n') +f('sys/devices/system/machinecheck/machinecheck1/bank0ctl', 0o644, b'ffffffffffffffff\n') +f('sys/devices/system/machinecheck/machinecheck1/check_interval', 0o644, b'12c\n') +f('sys/devices/system/machinecheck/machinecheck1/tolerant', 0o644, b'1\n') +f('sys/devices/system/machinecheck/machinecheck1/bank1ctl', 0o644, b'ffffffffffffffff\n') +f('sys/devices/system/machinecheck/machinecheck1/bank5ctl', 0o644, b'ffffffffffffffff\n') +f('sys/devices/system/machinecheck/machinecheck1/bank3ctl', 0o644, b'ffffffffffffffff\n') +f('sys/devices/system/machinecheck/machinecheck1/bank2ctl', 0o644, b'ffffffffffffffff\n') +f('sys/devices/system/machinecheck/machinecheck1/bank4ctl', 0o644, b'ffffffffffffffff\n') +d('sys/devices/system/machinecheck/machinecheck0', 0o755) +f('sys/devices/system/machinecheck/machinecheck0/trigger', 0o644, b'\n') +f('sys/devices/system/machinecheck/machinecheck0/bank0ctl', 0o644, b'ffffffffffffffff\n') +f('sys/devices/system/machinecheck/machinecheck0/check_interval', 0o644, b'12c\n') +f('sys/devices/system/machinecheck/machinecheck0/tolerant', 0o644, b'1\n') +f('sys/devices/system/machinecheck/machinecheck0/bank1ctl', 0o644, b'ffffffffffffffff\n') +f('sys/devices/system/machinecheck/machinecheck0/bank5ctl', 0o644, b'ffffffffffffffff\n') +f('sys/devices/system/machinecheck/machinecheck0/bank3ctl', 0o644, b'ffffffffffffffff\n') +f('sys/devices/system/machinecheck/machinecheck0/bank2ctl', 0o644, b'ffffffffffffffff\n') +f('sys/devices/system/machinecheck/machinecheck0/bank4ctl', 0o644, b'ffffffffffffffff\n') +d('sys/devices/system/clocksource', 0o755) +d('sys/devices/system/clocksource/clocksource0', 0o755) +f('sys/devices/system/clocksource/clocksource0/available_clocksource', 0o644, b'hpet acpi_pm jiffies tsc \n') +f('sys/devices/system/clocksource/clocksource0/current_clocksource', 0o644, b'hpet\n') +d('sys/devices/system/cpu', 0o755) +f('sys/devices/system/cpu/possible', 0o644, b'0-1\n') +f('sys/devices/system/cpu/online', 0o644, b'0-1\n') +f('sys/devices/system/cpu/present', 0o644, b'0-1\n') +f('sys/devices/system/cpu/sched_mc_power_savings', 0o644, b'1\n') +d('sys/devices/system/cpu/cpu0', 0o755) +f('sys/devices/system/cpu/cpu0/crash_notes', 0o644, b'7fb20920\n') +d('sys/devices/system/cpu/cpu0/topology', 0o755) +f('sys/devices/system/cpu/cpu0/topology/thread_siblings', 0o644, b'01\n') +f('sys/devices/system/cpu/cpu0/topology/thread_siblings_list', 0o644, b'0\n') +f('sys/devices/system/cpu/cpu0/topology/core_siblings_list', 0o644, b'0-1\n') +f('sys/devices/system/cpu/cpu0/topology/core_siblings', 0o644, b'03\n') +f('sys/devices/system/cpu/cpu0/topology/core_id', 0o644, b'0\n') +f('sys/devices/system/cpu/cpu0/topology/physical_package_id', 0o644, b'0\n') +d('sys/devices/system/cpu/cpu0/thermal_throttle', 0o755) +f('sys/devices/system/cpu/cpu0/thermal_throttle/count', 0o644, b'0\n') +d('sys/devices/system/cpu/cpu0/cache', 0o755) +d('sys/devices/system/cpu/cpu0/cache/index0', 0o755) +f('sys/devices/system/cpu/cpu0/cache/index0/ways_of_associativity', 0o644, b'8\n') +f('sys/devices/system/cpu/cpu0/cache/index0/type', 0o644, b'Data\n') +f('sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size', 0o644, b'64\n') +f('sys/devices/system/cpu/cpu0/cache/index0/number_of_sets', 0o644, b'64\n') +f('sys/devices/system/cpu/cpu0/cache/index0/size', 0o644, b'32K\n') +f('sys/devices/system/cpu/cpu0/cache/index0/physical_line_partition', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_map', 0o644, b'01\n') +f('sys/devices/system/cpu/cpu0/cache/index0/level', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu0/cache/index0/shared_cpu_list', 0o644, b'0\n') +d('sys/devices/system/cpu/cpu0/cache/index2', 0o755) +f('sys/devices/system/cpu/cpu0/cache/index2/ways_of_associativity', 0o644, b'16\n') +f('sys/devices/system/cpu/cpu0/cache/index2/type', 0o644, b'Unified\n') +f('sys/devices/system/cpu/cpu0/cache/index2/coherency_line_size', 0o644, b'64\n') +f('sys/devices/system/cpu/cpu0/cache/index2/number_of_sets', 0o644, b'4096\n') +f('sys/devices/system/cpu/cpu0/cache/index2/size', 0o644, b'4096K\n') +f('sys/devices/system/cpu/cpu0/cache/index2/physical_line_partition', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu0/cache/index2/shared_cpu_map', 0o644, b'03\n') +f('sys/devices/system/cpu/cpu0/cache/index2/level', 0o644, b'2\n') +f('sys/devices/system/cpu/cpu0/cache/index2/shared_cpu_list', 0o644, b'0-1\n') +d('sys/devices/system/cpu/cpu0/cache/index1', 0o755) +f('sys/devices/system/cpu/cpu0/cache/index1/ways_of_associativity', 0o644, b'8\n') +f('sys/devices/system/cpu/cpu0/cache/index1/type', 0o644, b'Instruction\n') +f('sys/devices/system/cpu/cpu0/cache/index1/coherency_line_size', 0o644, b'64\n') +f('sys/devices/system/cpu/cpu0/cache/index1/number_of_sets', 0o644, b'64\n') +f('sys/devices/system/cpu/cpu0/cache/index1/size', 0o644, b'32K\n') +f('sys/devices/system/cpu/cpu0/cache/index1/physical_line_partition', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu0/cache/index1/shared_cpu_map', 0o644, b'01\n') +f('sys/devices/system/cpu/cpu0/cache/index1/level', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu0/cache/index1/shared_cpu_list', 0o644, b'0\n') +d('sys/devices/system/cpu/cpu0/cpuidle', 0o755) +d('sys/devices/system/cpu/cpu0/cpuidle/state2', 0o755) +f('sys/devices/system/cpu/cpu0/cpuidle/state2/desc', 0o644, b'ACPI FFH INTEL MWAIT 0x10\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state2/power', 0o644, b'500\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state2/latency', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state2/usage', 0o644, b'689\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state2/name', 0o644, b'C2\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state2/time', 0o644, b'209561\n') +d('sys/devices/system/cpu/cpu0/cpuidle/state3', 0o755) +f('sys/devices/system/cpu/cpu0/cpuidle/state3/desc', 0o644, b'ACPI FFH INTEL MWAIT 0x30\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state3/power', 0o644, b'100\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state3/latency', 0o644, b'57\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state3/usage', 0o644, b'11774\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state3/name', 0o644, b'C3\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state3/time', 0o644, b'116651688\n') +d('sys/devices/system/cpu/cpu0/cpuidle/state1', 0o755) +f('sys/devices/system/cpu/cpu0/cpuidle/state1/desc', 0o644, b'ACPI FFH INTEL MWAIT 0x0\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state1/power', 0o644, b'1000\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state1/latency', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state1/usage', 0o644, b'2\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state1/name', 0o644, b'C1\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state1/time', 0o644, b'1044\n') +d('sys/devices/system/cpu/cpu0/cpuidle/state0', 0o755) +f('sys/devices/system/cpu/cpu0/cpuidle/state0/desc', 0o644, b'\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state0/power', 0o644, b'4294967295\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state0/latency', 0o644, b'0\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state0/usage', 0o644, b'0\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state0/name', 0o644, b'\n') +f('sys/devices/system/cpu/cpu0/cpuidle/state0/time', 0o644, b'0\n') +d('sys/devices/system/cpu/cpu0/cpufreq', 0o755) +f('sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq', 0o644, b'1000000\n') +f('sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq', 0o644, b'2333000\n') +f('sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies', 0o644, b'2333000 2000000 1667000 1333000 1000000 \n') +f('sys/devices/system/cpu/cpu0/cpufreq/scaling_governor', 0o644, b'ondemand\n') +f('sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors', 0o644, b'ondemand performance \n') +f('sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq', 0o644, b'1000000\n') +f('sys/devices/system/cpu/cpu0/cpufreq/affected_cpus', 0o644, b'0 1\n') +f('sys/devices/system/cpu/cpu0/cpufreq/related_cpus', 0o644, b'0 1\n') +f('sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed', 0o644, b'\n') +f('sys/devices/system/cpu/cpu0/cpufreq/scaling_driver', 0o644, b'acpi-cpufreq\n') +f('sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq', 0o644, b'1000000\n') +f('sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq', 0o644, b'1000000\n') +f('sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq', 0o644, b'1000000\n') +d('sys/devices/system/cpu/cpu0/cpufreq/stats', 0o755) +f('sys/devices/system/cpu/cpu0/cpufreq/stats/total_trans', 0o644, b'12627\n') +f('sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state', 0o644, b'''2333000 92206 +2000000 442 +1667000 1009 +1333000 1713 +1000000 740740 +''') +d('sys/devices/system/cpu/cpu0/cpufreq/ondemand', 0o755) +f('sys/devices/system/cpu/cpu0/cpufreq/ondemand/powersave_bias', 0o644, b'0\n') +f('sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate_max', 0o644, b'10000000\n') +f('sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate', 0o644, b'20000\n') +f('sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold', 0o644, b'90\n') +f('sys/devices/system/cpu/cpu0/cpufreq/ondemand/ignore_nice_load', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate_min', 0o644, b'10000\n') +d('sys/devices/system/cpu/cpu0/microcode', 0o755) +f('sys/devices/system/cpu/cpu0/microcode/version', 0o644, b'0xc7\n') +f('sys/devices/system/cpu/cpu0/microcode/processor_flags', 0o644, b'0x20\n') +d('sys/devices/system/cpu/cpuidle', 0o755) +f('sys/devices/system/cpu/cpuidle/current_driver', 0o644, b'acpi_idle\n') +f('sys/devices/system/cpu/cpuidle/current_governor_ro', 0o644, b'menu\n') +d('sys/devices/system/cpu/cpu1', 0o755) +l('sys/devices/system/cpu/cpu1/cpufreq', '../cpu0/cpufreq') +f('sys/devices/system/cpu/cpu1/crash_notes', 0o644, b'7fb20b68\n') +f('sys/devices/system/cpu/cpu1/online', 0o644, b'1\n') +d('sys/devices/system/cpu/cpu1/topology', 0o755) +f('sys/devices/system/cpu/cpu1/topology/thread_siblings', 0o644, b'02\n') +f('sys/devices/system/cpu/cpu1/topology/thread_siblings_list', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu1/topology/core_siblings_list', 0o644, b'0-1\n') +f('sys/devices/system/cpu/cpu1/topology/core_siblings', 0o644, b'03\n') +f('sys/devices/system/cpu/cpu1/topology/core_id', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu1/topology/physical_package_id', 0o644, b'0\n') +d('sys/devices/system/cpu/cpu1/thermal_throttle', 0o755) +f('sys/devices/system/cpu/cpu1/thermal_throttle/count', 0o644, b'0\n') +d('sys/devices/system/cpu/cpu1/cache', 0o755) +d('sys/devices/system/cpu/cpu1/cache/index0', 0o755) +f('sys/devices/system/cpu/cpu1/cache/index0/ways_of_associativity', 0o644, b'8\n') +f('sys/devices/system/cpu/cpu1/cache/index0/type', 0o644, b'Data\n') +f('sys/devices/system/cpu/cpu1/cache/index0/coherency_line_size', 0o644, b'64\n') +f('sys/devices/system/cpu/cpu1/cache/index0/number_of_sets', 0o644, b'64\n') +f('sys/devices/system/cpu/cpu1/cache/index0/size', 0o644, b'32K\n') +f('sys/devices/system/cpu/cpu1/cache/index0/physical_line_partition', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu1/cache/index0/shared_cpu_map', 0o644, b'02\n') +f('sys/devices/system/cpu/cpu1/cache/index0/level', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu1/cache/index0/shared_cpu_list', 0o644, b'1\n') +d('sys/devices/system/cpu/cpu1/cache/index2', 0o755) +f('sys/devices/system/cpu/cpu1/cache/index2/ways_of_associativity', 0o644, b'16\n') +f('sys/devices/system/cpu/cpu1/cache/index2/type', 0o644, b'Unified\n') +f('sys/devices/system/cpu/cpu1/cache/index2/coherency_line_size', 0o644, b'64\n') +f('sys/devices/system/cpu/cpu1/cache/index2/number_of_sets', 0o644, b'4096\n') +f('sys/devices/system/cpu/cpu1/cache/index2/size', 0o644, b'4096K\n') +f('sys/devices/system/cpu/cpu1/cache/index2/physical_line_partition', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu1/cache/index2/shared_cpu_map', 0o644, b'03\n') +f('sys/devices/system/cpu/cpu1/cache/index2/level', 0o644, b'2\n') +f('sys/devices/system/cpu/cpu1/cache/index2/shared_cpu_list', 0o644, b'0-1\n') +d('sys/devices/system/cpu/cpu1/cache/index1', 0o755) +f('sys/devices/system/cpu/cpu1/cache/index1/ways_of_associativity', 0o644, b'8\n') +f('sys/devices/system/cpu/cpu1/cache/index1/type', 0o644, b'Instruction\n') +f('sys/devices/system/cpu/cpu1/cache/index1/coherency_line_size', 0o644, b'64\n') +f('sys/devices/system/cpu/cpu1/cache/index1/number_of_sets', 0o644, b'64\n') +f('sys/devices/system/cpu/cpu1/cache/index1/size', 0o644, b'32K\n') +f('sys/devices/system/cpu/cpu1/cache/index1/physical_line_partition', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu1/cache/index1/shared_cpu_map', 0o644, b'02\n') +f('sys/devices/system/cpu/cpu1/cache/index1/level', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu1/cache/index1/shared_cpu_list', 0o644, b'1\n') +d('sys/devices/system/cpu/cpu1/cpuidle', 0o755) +d('sys/devices/system/cpu/cpu1/cpuidle/state2', 0o755) +f('sys/devices/system/cpu/cpu1/cpuidle/state2/desc', 0o644, b'ACPI FFH INTEL MWAIT 0x10\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state2/power', 0o644, b'500\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state2/latency', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state2/usage', 0o644, b'271\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state2/name', 0o644, b'C2\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state2/time', 0o644, b'47233\n') +d('sys/devices/system/cpu/cpu1/cpuidle/state3', 0o755) +f('sys/devices/system/cpu/cpu1/cpuidle/state3/desc', 0o644, b'ACPI FFH INTEL MWAIT 0x30\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state3/power', 0o644, b'100\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state3/latency', 0o644, b'57\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state3/usage', 0o644, b'10601\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state3/name', 0o644, b'C3\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state3/time', 0o644, b'117038054\n') +d('sys/devices/system/cpu/cpu1/cpuidle/state1', 0o755) +f('sys/devices/system/cpu/cpu1/cpuidle/state1/desc', 0o644, b'ACPI FFH INTEL MWAIT 0x0\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state1/power', 0o644, b'1000\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state1/latency', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state1/usage', 0o644, b'1\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state1/name', 0o644, b'C1\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state1/time', 0o644, b'8\n') +d('sys/devices/system/cpu/cpu1/cpuidle/state0', 0o755) +f('sys/devices/system/cpu/cpu1/cpuidle/state0/desc', 0o644, b'\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state0/power', 0o644, b'4294967295\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state0/latency', 0o644, b'0\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state0/usage', 0o644, b'0\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state0/name', 0o644, b'\n') +f('sys/devices/system/cpu/cpu1/cpuidle/state0/time', 0o644, b'0\n') +d('sys/devices/system/cpu/cpu1/microcode', 0o755) +f('sys/devices/system/cpu/cpu1/microcode/version', 0o644, b'0xc7\n') +f('sys/devices/system/cpu/cpu1/microcode/processor_flags', 0o644, b'0x20\n') +d('sys/devices/pnp0', 0o755) +f('sys/devices/pnp0/uevent', 0o644, b'') +d('sys/devices/pnp0/00:04', 0o755) +l('sys/devices/pnp0/00:04/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00') +l('sys/devices/pnp0/00:04/subsystem', '../../../bus/pnp') +f('sys/devices/pnp0/00:04/options', 0o644, b'') +f('sys/devices/pnp0/00:04/id', 0o644, b'PNP0200\n') +f('sys/devices/pnp0/00:04/resources', 0o644, b'''state = active +io 0x0-0xf +io 0x80-0x8f +io 0xc0-0xdf +dma 4 +''') +f('sys/devices/pnp0/00:04/uevent', 0o644, b'') +d('sys/devices/pnp0/00:04/power', 0o755) +f('sys/devices/pnp0/00:04/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/00:0a', 0o755) +l('sys/devices/pnp0/00:0a/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00') +l('sys/devices/pnp0/00:0a/subsystem', '../../../bus/pnp') +f('sys/devices/pnp0/00:0a/options', 0o644, b'') +f('sys/devices/pnp0/00:0a/id', 0o644, b'''ATM1200 +PNP0c31 +''') +f('sys/devices/pnp0/00:0a/resources', 0o644, b'''state = active +mem 0xfed40000-0xfed40fff +''') +f('sys/devices/pnp0/00:0a/uevent', 0o644, b'') +d('sys/devices/pnp0/00:0a/power', 0o755) +f('sys/devices/pnp0/00:0a/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/00:03', 0o755) +l('sys/devices/pnp0/00:03/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00') +l('sys/devices/pnp0/00:03/subsystem', '../../../bus/pnp') +f('sys/devices/pnp0/00:03/options', 0o644, b'') +f('sys/devices/pnp0/00:03/id', 0o644, b'PNP0103\n') +f('sys/devices/pnp0/00:03/resources', 0o644, b'''state = active +mem 0xfed00000-0xfed003ff +''') +f('sys/devices/pnp0/00:03/uevent', 0o644, b'') +d('sys/devices/pnp0/00:03/power', 0o755) +f('sys/devices/pnp0/00:03/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/00:02', 0o755) +l('sys/devices/pnp0/00:02/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00') +l('sys/devices/pnp0/00:02/subsystem', '../../../bus/pnp') +l('sys/devices/pnp0/00:02/driver', '../../../bus/pnp/drivers/system') +f('sys/devices/pnp0/00:02/options', 0o644, b'') +f('sys/devices/pnp0/00:02/id', 0o644, b'PNP0c02\n') +f('sys/devices/pnp0/00:02/resources', 0o644, b'''state = active +io 0x10-0x1f +io 0x90-0x9f +io 0x24-0x25 +io 0x28-0x29 +io 0x2c-0x2d +io 0x30-0x31 +io 0x34-0x35 +io 0x38-0x39 +io 0x3c-0x3d +io 0xa4-0xa5 +io 0xa8-0xa9 +io 0xac-0xad +io 0xb0-0xb5 +io 0xb8-0xb9 +io 0xbc-0xbd +io 0x50-0x53 +io 0x72-0x77 +io 0x164e-0x164f +io 0x2e-0x2f +io 0x1000-0x107f +io 0x1180-0x11bf +io 0x800-0x80f +io 0x15e0-0x15ef +io 0x1600-0x165f +mem 0xf0000000-0xf3ffffff +mem 0xfed1c000-0xfed1ffff +mem 0xfed14000-0xfed17fff +mem 0xfed18000-0xfed18fff +mem 0xfed19000-0xfed19fff +''') +f('sys/devices/pnp0/00:02/uevent', 0o644, b'DRIVER=system\n') +d('sys/devices/pnp0/00:02/power', 0o755) +f('sys/devices/pnp0/00:02/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/00:00', 0o755) +l('sys/devices/pnp0/00:00/firmware_node', '../../LNXSYSTM:00/device:00/PNP0C01:00') +l('sys/devices/pnp0/00:00/subsystem', '../../../bus/pnp') +l('sys/devices/pnp0/00:00/driver', '../../../bus/pnp/drivers/system') +f('sys/devices/pnp0/00:00/options', 0o644, b'') +f('sys/devices/pnp0/00:00/id', 0o644, b'PNP0c01\n') +f('sys/devices/pnp0/00:00/resources', 0o644, b'''state = active +mem 0x0-0x9ffff +mem 0xc0000-0xc3fff +mem 0xc4000-0xc7fff +mem 0xc8000-0xcbfff +mem 0xcc000-0xcffff +mem disabled +mem disabled +mem disabled +mem 0xdc000-0xdffff +mem 0xe0000-0xe3fff +mem 0xe4000-0xe7fff +mem 0xe8000-0xebfff +mem 0xec000-0xeffff +mem 0xf0000-0xfffff +mem 0x100000-0x7fffffff +mem 0xfec00000-0xfed3ffff +mem 0xfed41000-0xffffffff +''') +f('sys/devices/pnp0/00:00/uevent', 0o644, b'DRIVER=system\n') +d('sys/devices/pnp0/00:00/power', 0o755) +f('sys/devices/pnp0/00:00/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/power', 0o755) +f('sys/devices/pnp0/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/00:09', 0o755) +l('sys/devices/pnp0/00:09/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00') +l('sys/devices/pnp0/00:09/subsystem', '../../../bus/pnp') +l('sys/devices/pnp0/00:09/driver', '../../../bus/pnp/drivers/i8042 aux') +f('sys/devices/pnp0/00:09/options', 0o644, b'') +f('sys/devices/pnp0/00:09/id', 0o644, b'''IBM0057 +PNP0f13 +''') +f('sys/devices/pnp0/00:09/resources', 0o644, b'''state = active +irq 12 +''') +f('sys/devices/pnp0/00:09/uevent', 0o644, b'DRIVER=i8042 aux\n') +d('sys/devices/pnp0/00:09/power', 0o755) +f('sys/devices/pnp0/00:09/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/00:07', 0o755) +l('sys/devices/pnp0/00:07/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00') +l('sys/devices/pnp0/00:07/subsystem', '../../../bus/pnp') +l('sys/devices/pnp0/00:07/driver', '../../../bus/pnp/drivers/rtc_cmos') +f('sys/devices/pnp0/00:07/options', 0o644, b'') +f('sys/devices/pnp0/00:07/id', 0o644, b'PNP0b00\n') +f('sys/devices/pnp0/00:07/nvram', 0o644, b'\x00\x00\x00\x00\x00\x00\x03\x80\x02\x00\xfc\x01\x00\x03\x00\x9f\x16\x00\x00\x02\x00\x00\x00\x01\x05\x00\x00\x11\x11\x01\x00\x00\x02e\x00\xfc \x8c\xc1\x01\x00|\x00\x00\x00\x00\x00\x00\x00\x00\x08D\xb0\x11\x00c\x11T/\x06\xd00\x80\x00\x00\x00\x00\x00\xc0\x05R\xfc\x01\x1d\x00[\x0f\x02\x03\x00\x00\x04\x04\x00\xdf8\xd3\xa0\x13r\xf2\x06\x13\xf9\xa7\xf1\x0e\x00\xc5\xfe\x00\x00\xf1\xff\xff\xff\xff\x00\x00\x00IS\xb2\x00') +f('sys/devices/pnp0/00:07/resources', 0o644, b'''state = active +io 0x70-0x71 +irq 8 +''') +f('sys/devices/pnp0/00:07/uevent', 0o644, b'DRIVER=rtc_cmos\n') +d('sys/devices/pnp0/00:07/rtc', 0o755) +d('sys/devices/pnp0/00:07/rtc/rtc0', 0o755) +l('sys/devices/pnp0/00:07/rtc/rtc0/subsystem', '../../../../../class/rtc') +l('sys/devices/pnp0/00:07/rtc/rtc0/device', '../../../00:07') +f('sys/devices/pnp0/00:07/rtc/rtc0/date', 0o644, b'2008-09-29\n') +f('sys/devices/pnp0/00:07/rtc/rtc0/dev', 0o644, b'253:0\n') +f('sys/devices/pnp0/00:07/rtc/rtc0/max_user_freq', 0o644, b'64\n') +f('sys/devices/pnp0/00:07/rtc/rtc0/wakealarm', 0o644, b'') +f('sys/devices/pnp0/00:07/rtc/rtc0/since_epoch', 0o644, b'1222655451\n') +f('sys/devices/pnp0/00:07/rtc/rtc0/name', 0o644, b'rtc_cmos\n') +f('sys/devices/pnp0/00:07/rtc/rtc0/time', 0o644, b'02:30:51\n') +f('sys/devices/pnp0/00:07/rtc/rtc0/uevent', 0o644, b'''MAJOR=253 +MINOR=0 +''') +d('sys/devices/pnp0/00:07/rtc/rtc0/power', 0o755) +f('sys/devices/pnp0/00:07/rtc/rtc0/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/00:07/power', 0o755) +f('sys/devices/pnp0/00:07/power/wakeup', 0o644, b'enabled\n') +d('sys/devices/pnp0/00:06', 0o755) +l('sys/devices/pnp0/00:06/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00') +l('sys/devices/pnp0/00:06/subsystem', '../../../bus/pnp') +f('sys/devices/pnp0/00:06/options', 0o644, b'') +f('sys/devices/pnp0/00:06/id', 0o644, b'PNP0c04\n') +f('sys/devices/pnp0/00:06/resources', 0o644, b'''state = active +io 0xf0-0xf0 +irq 13 +''') +f('sys/devices/pnp0/00:06/uevent', 0o644, b'') +d('sys/devices/pnp0/00:06/power', 0o755) +f('sys/devices/pnp0/00:06/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/00:08', 0o755) +l('sys/devices/pnp0/00:08/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00') +l('sys/devices/pnp0/00:08/subsystem', '../../../bus/pnp') +l('sys/devices/pnp0/00:08/driver', '../../../bus/pnp/drivers/i8042 kbd') +f('sys/devices/pnp0/00:08/options', 0o644, b'') +f('sys/devices/pnp0/00:08/id', 0o644, b'PNP0303\n') +f('sys/devices/pnp0/00:08/resources', 0o644, b'''state = active +io 0x60-0x60 +io 0x64-0x64 +irq 1 +''') +f('sys/devices/pnp0/00:08/uevent', 0o644, b'DRIVER=i8042 kbd\n') +d('sys/devices/pnp0/00:08/power', 0o755) +f('sys/devices/pnp0/00:08/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/00:05', 0o755) +l('sys/devices/pnp0/00:05/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00') +l('sys/devices/pnp0/00:05/subsystem', '../../../bus/pnp') +f('sys/devices/pnp0/00:05/options', 0o644, b'') +f('sys/devices/pnp0/00:05/id', 0o644, b'PNP0800\n') +f('sys/devices/pnp0/00:05/resources', 0o644, b'''state = active +io 0x61-0x61 +''') +f('sys/devices/pnp0/00:05/uevent', 0o644, b'') +d('sys/devices/pnp0/00:05/power', 0o755) +f('sys/devices/pnp0/00:05/power/wakeup', 0o644, b'\n') +d('sys/devices/pnp0/00:01', 0o755) +l('sys/devices/pnp0/00:01/subsystem', '../../../bus/pnp') +f('sys/devices/pnp0/00:01/options', 0o644, b'') +f('sys/devices/pnp0/00:01/id', 0o644, b'''PNP0a08 +PNP0a03 +''') +f('sys/devices/pnp0/00:01/resources', 0o644, b'''state = active +io 0xcf8-0xcff +''') +f('sys/devices/pnp0/00:01/uevent', 0o644, b'') +d('sys/devices/pnp0/00:01/power', 0o755) +f('sys/devices/pnp0/00:01/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00', 0o755) +l('sys/devices/pci0000:00/firmware_node', '../LNXSYSTM:00/device:00/PNP0A08:00') +f('sys/devices/pci0000:00/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1d.3', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:20') +l('sys/devices/pci0000:00/0000:00:1d.3/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1d.3/driver', '../../../bus/pci/drivers/uhci_hcd') +f('sys/devices/pci0000:00/0000:00:1d.3/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1d.3/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/modalias', 0o644, b'pci:v00008086d000027CBsv000017AAsd0000200Abc0Csc03i00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000001860 0x000000000000187f 0x0000000000020101 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/config', 0o644, b"\x86\x80\xcb'\x05\x00\x80\x02\x02\x00\x03\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00a\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\n \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1d.3/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1d.3/subsystem_device', 0o644, b'0x200a\n') +f('sys/devices/pci0000:00/0000:00:1d.3/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1d.3/irq', 0o644, b'19\n') +f('sys/devices/pci0000:00/0000:00:1d.3/pools', 0o644, b'''poolinfo - 0.1 +uhci_qh 13 32 128 1 +uhci_td 3 64 64 1 +buffer-2048 0 0 2048 0 +buffer-512 0 0 512 0 +buffer-128 0 0 128 0 +buffer-32 1 128 32 1 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/device', 0o644, b'0x27cb\n') +f('sys/devices/pci0000:00/0000:00:1d.3/class', 0o644, b'0x0c0300\n') +f('sys/devices/pci0000:00/0000:00:1d.3/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.3/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1d.3/uevent', 0o644, b'''DRIVER=uhci_hcd +PCI_CLASS=C0300 +PCI_ID=8086:27CB +PCI_SUBSYS_ID=17AA:200A +PCI_SLOT_NAME=0000:00:1d.3 +MODALIAS=pci:v00008086d000027CBsv000017AAsd0000200Abc0Csc03i00 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/resource4', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.3/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1d.3/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.3/usb_host/usb_host4', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb_host/usb_host4/subsystem', '../../../../../class/usb_host') +l('sys/devices/pci0000:00/0000:00:1d.3/usb_host/usb_host4/device', '../../../0000:00:1d.3') +f('sys/devices/pci0000:00/0000:00:1d.3/usb_host/usb_host4/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1d.3/usb_host/usb_host4/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb_host/usb_host4/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/subsystem', '../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/driver', '../../../../bus/usb/drivers/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/ep_00', 'usb_endpoint/usbdev4.1_ep00') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/version', 0o644, b' 1.10\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/authorized_default', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/maxchild', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/bDeviceClass', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/bcdDevice', 0o644, b'0206\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/devnum', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/bDeviceProtocol', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/idProduct', 0o644, b'0001\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/product', 0o644, b'UHCI Host Controller\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/bDeviceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/configuration', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/dev', 0o644, b'189:384\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/urbnum', 0o644, b'62\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/authorized', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/descriptors', 0o644, b'\x12\x01\x10\x01\t\x00\x00@k\x1d\x01\x00\x06\x02\x03\x02\x01\x01\t\x02\x19\x00\x01\x01\x00\xe0\x00\t\x04\x00\x00\x01\t\x00\x00\x00\x07\x05\x81\x03\x02\x00\xff') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/bNumConfigurations', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/serial', 0o644, b'0000:00:1d.3\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/speed', 0o644, b'12\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/bMaxPacketSize0', 0o644, b'64\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/bmAttributes', 0o644, b'e0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/busnum', 0o644, b'4\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/quirks', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/bConfigurationValue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/uevent', 0o644, b'''MAJOR=189 +MINOR=384 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=1d6b/1/206 +TYPE=9/0/0 +BUSNUM=004 +DEVNUM=001 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/manufacturer', 0o644, b'Linux 2.6.27-rc7-00106-g6ef190c-dirty uhci_hcd\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/idVendor', 0o644, b'1d6b\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/bNumInterfaces', 0o644, b' 1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/bMaxPower', 0o644, b' 0mA\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/subsystem', '../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/device', '../../../usb4') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/bEndpointAddress', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/type', 0o644, b'Control\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/dev', 0o644, b'252:7\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/direction', 0o644, b'both\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/bmAttributes', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/uevent', 0o644, b'''MAJOR=252 +MINOR=7 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/usb_endpoint/usbdev4.1_ep00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/subsystem', '../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/driver', '../../../../../bus/usb/drivers/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/ep_00', 'usb_endpoint/usbdev4.3_ep00') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/version', 0o644, b' 1.00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/maxchild', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/bDeviceClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/bcdDevice', 0o644, b'0001\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/devnum', 0o644, b'3\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/bDeviceProtocol', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/idProduct', 0o644, b'2016\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/product', 0o644, b'Biometric Coprocessor\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/bDeviceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/configuration', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/dev', 0o644, b'189:386\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/urbnum', 0o644, b'9\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/authorized', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/descriptors', 0o644, b"\x12\x01\x00\x01\x00\x00\x00\x08\x83\x04\x16 \x01\x00\x01\x02\x00\x01\t\x02'\x00\x01\x01\x00\xa02\t\x04\x00\x00\x03\xff\x00\x00\x00\x07\x05\x81\x02@\x00\x00\x07\x05\x02\x02@\x00\x00\x07\x05\x83\x03\x04\x00\x14") +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/bNumConfigurations', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/speed', 0o644, b'12\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/bMaxPacketSize0', 0o644, b'8\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/bmAttributes', 0o644, b'a0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/busnum', 0o644, b'4\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/quirks', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/bConfigurationValue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/uevent', 0o644, b'''MAJOR=189 +MINOR=386 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=483/2016/1 +TYPE=0/0/0 +BUSNUM=004 +DEVNUM=003 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/manufacturer', 0o644, b'STMicroelectronics\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/idVendor', 0o644, b'0483\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/bNumInterfaces', 0o644, b' 1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/bMaxPower', 0o644, b'100mA\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/subsystem', '../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/device', '../../../4-2') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/bEndpointAddress', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/type', 0o644, b'Control\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/dev', 0o644, b'252:23\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/direction', 0o644, b'both\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/wMaxPacketSize', 0o644, b'0008\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/bmAttributes', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/uevent', 0o644, b'''MAJOR=252 +MINOR=23 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/usb_endpoint/usbdev4.3_ep00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/power/active_duration', 0o644, b'8370363\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/power/wakeup', 0o644, b'enabled\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/power/connected_duration', 0o644, b'8370362\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/power/autosuspend', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/power/persist', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/power/level', 0o644, b'on\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/subsystem', '../../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/ep_83', 'usb_endpoint/usbdev4.3_ep83') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/ep_81', 'usb_endpoint/usbdev4.3_ep81') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/ep_02', 'usb_endpoint/usbdev4.3_ep02') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/modalias', 0o644, b'usb:v0483p2016d0001dc00dsc00dp00icFFisc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/bInterfaceNumber', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/bNumEndpoints', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/bInterfaceClass', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=483/2016/1 +TYPE=0/0/0 +INTERFACE=255/0/0 +MODALIAS=usb:v0483p2016d0001dc00dsc00dp00icFFisc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/device', '../../../4-2:1.0') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/interval', 0o644, b'20ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/bEndpointAddress', 0o644, b'83\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/type', 0o644, b'Interrupt\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/dev', 0o644, b'252:22\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/wMaxPacketSize', 0o644, b'0004\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/bmAttributes', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/uevent', 0o644, b'''MAJOR=252 +MINOR=22 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/bInterval', 0o644, b'14\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep83/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/device', '../../../4-2:1.0') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/bEndpointAddress', 0o644, b'81\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/dev', 0o644, b'252:20\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/uevent', 0o644, b'''MAJOR=252 +MINOR=20 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep81/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/device', '../../../4-2:1.0') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/bEndpointAddress', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/dev', 0o644, b'252:21\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/direction', 0o644, b'out\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/uevent', 0o644, b'''MAJOR=252 +MINOR=21 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/usb_endpoint/usbdev4.3_ep02/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-2/4-2:1.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/subsystem', '../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/ep_81', 'usb_endpoint/usbdev4.1_ep81') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/driver', '../../../../../bus/usb/drivers/hub') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/modalias', 0o644, b'usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/bInterfaceNumber', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/bNumEndpoints', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/bInterfaceClass', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/uevent', 0o644, b'''DEVTYPE=usb_interface +DRIVER=hub +PRODUCT=1d6b/1/206 +TYPE=9/0/0 +INTERFACE=9/0/0 +MODALIAS=usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/subsystem', '../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/device', '../../../4-0:1.0') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/interval', 0o644, b'255ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/bEndpointAddress', 0o644, b'81\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/type', 0o644, b'Interrupt\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/dev', 0o644, b'252:6\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/wMaxPacketSize', 0o644, b'0002\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/bmAttributes', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/uevent', 0o644, b'''MAJOR=252 +MINOR=6 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/bInterval', 0o644, b'ff\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/usb_endpoint/usbdev4.1_ep81/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-0:1.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/power/active_duration', 0o644, b'8372033\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/power/wakeup', 0o644, b'enabled\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/power/connected_duration', 0o644, b'8372033\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/power/autosuspend', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/power/level', 0o644, b'auto\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/subsystem', '../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/driver', '../../../../../bus/usb/drivers/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/ep_00', 'usb_endpoint/usbdev4.2_ep00') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/version', 0o644, b' 2.00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/maxchild', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/bDeviceClass', 0o644, b'e0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/bcdDevice', 0o644, b'0100\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/devnum', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/bDeviceProtocol', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/idProduct', 0o644, b'2110\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/product', 0o644, b'BCM2045B\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/bDeviceSubClass', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/configuration', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/dev', 0o644, b'189:385\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/urbnum', 0o644, b'12\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/authorized', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/descriptors', 0o644, b'\x12\x01\x00\x02\xe0\x01\x01@\\\n\x10!\x00\x01\x01\x02\x00\x01\t\x02\xd8\x00\x04\x01\x00\xe0\x00\t\x04\x00\x00\x03\xe0\x01\x01\x00\x07\x05\x81\x03\x10\x00\x01\x07\x05\x82\x02@\x00\x01\x07\x05\x02\x02@\x00\x01\t\x04\x01\x00\x02\xe0\x01\x01\x00\x07\x05\x83\x01\x00\x00\x01\x07\x05\x03\x01\x00\x00\x01\t\x04\x01\x01\x02\xe0\x01\x01\x00\x07\x05\x83\x01\t\x00\x01\x07\x05\x03\x01\t\x00\x01\t\x04\x01\x02\x02\xe0\x01\x01\x00\x07\x05\x83\x01\x11\x00\x01\x07\x05\x03\x01\x11\x00\x01\t\x04\x01\x03\x02\xe0\x01\x01\x00\x07\x05\x83\x01 \x00\x01\x07\x05\x03\x01 \x00\x01\t\x04\x01\x04\x02\xe0\x01\x01\x00\x07\x05\x83\x01@\x00\x01\x07\x05\x03\x01@\x00\x01\t\x04\x01\x05\x02\xe0\x01\x01\x00\x07\x05\x83\x01@\x00\x01\x07\x05\x03\x01@\x00\x01\t\x04\x02\x00\x02\xff\xff\xff\x00\x07\x05\x84\x02 \x00\x01\x07\x05\x04\x02 \x00\x01\t\x04\x03\x00\x00\xfe\x01\x00\x00\x07!\x07\x88\x13@\x00') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/bNumConfigurations', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/speed', 0o644, b'12\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/bMaxPacketSize0', 0o644, b'64\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/bmAttributes', 0o644, b'e0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/busnum', 0o644, b'4\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/quirks', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/bConfigurationValue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/uevent', 0o644, b'''MAJOR=189 +MINOR=385 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=a5c/2110/100 +TYPE=224/1/1 +BUSNUM=004 +DEVNUM=002 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/manufacturer', 0o644, b'Broadcom Corp\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/idVendor', 0o644, b'0a5c\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/bNumInterfaces', 0o644, b' 4\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/bMaxPower', 0o644, b' 0mA\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/modalias', 0o644, b'usb:v0A5Cp2110d0100dcE0dsc01dp01icFEisc01ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/bInterfaceNumber', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/bInterfaceSubClass', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/bInterfaceClass', 0o644, b'fe\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=a5c/2110/100 +TYPE=224/1/1 +INTERFACE=254/1/0 +MODALIAS=usb:v0A5Cp2110d0100dcE0dsc01dp01icFEisc01ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.3/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/subsystem', '../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/device', '../../../4-1') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/bEndpointAddress', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/type', 0o644, b'Control\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/dev', 0o644, b'252:19\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/direction', 0o644, b'both\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/bmAttributes', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/uevent', 0o644, b'''MAJOR=252 +MINOR=19 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/usb_endpoint/usbdev4.2_ep00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/subsystem', '../../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/ep_81', 'usb_endpoint/usbdev4.2_ep81') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/ep_02', 'usb_endpoint/usbdev4.2_ep02') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/ep_82', 'usb_endpoint/usbdev4.2_ep82') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/modalias', 0o644, b'usb:v0A5Cp2110d0100dcE0dsc01dp01icE0isc01ip01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/bInterfaceNumber', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/bNumEndpoints', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/bInterfaceSubClass', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/bInterfaceClass', 0o644, b'e0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=a5c/2110/100 +TYPE=224/1/1 +INTERFACE=224/1/1 +MODALIAS=usb:v0A5Cp2110d0100dcE0dsc01dp01icE0isc01ip01 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/bInterfaceProtocol', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/device', '../../../4-1:1.0') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/bEndpointAddress', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/dev', 0o644, b'252:14\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/direction', 0o644, b'out\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/uevent', 0o644, b'''MAJOR=252 +MINOR=14 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/bInterval', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep02/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/device', '../../../4-1:1.0') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/bEndpointAddress', 0o644, b'82\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/dev', 0o644, b'252:13\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/uevent', 0o644, b'''MAJOR=252 +MINOR=13 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/bInterval', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep82/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/device', '../../../4-1:1.0') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/interval', 0o644, b'1ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/bEndpointAddress', 0o644, b'81\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/type', 0o644, b'Interrupt\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/dev', 0o644, b'252:12\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/wMaxPacketSize', 0o644, b'0010\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/bmAttributes', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/uevent', 0o644, b'''MAJOR=252 +MINOR=12 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/bInterval', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/usb_endpoint/usbdev4.2_ep81/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/power/active_duration', 0o644, b'8370651\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/power/wakeup', 0o644, b'enabled\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/power/connected_duration', 0o644, b'8370650\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/power/autosuspend', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/power/persist', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/power/level', 0o644, b'on\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/subsystem', '../../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/ep_84', 'usb_endpoint/usbdev4.2_ep84') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/ep_04', 'usb_endpoint/usbdev4.2_ep04') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/modalias', 0o644, b'usb:v0A5Cp2110d0100dcE0dsc01dp01icFFiscFFipFF\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/bInterfaceNumber', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/bNumEndpoints', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/bInterfaceSubClass', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/bInterfaceClass', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=a5c/2110/100 +TYPE=224/1/1 +INTERFACE=255/255/255 +MODALIAS=usb:v0A5Cp2110d0100dcE0dsc01dp01icFFiscFFipFF +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/bInterfaceProtocol', 0o644, b'ff\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/device', '../../../4-1:1.2') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/bEndpointAddress', 0o644, b'04\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/dev', 0o644, b'252:18\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/direction', 0o644, b'out\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/wMaxPacketSize', 0o644, b'0020\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/uevent', 0o644, b'''MAJOR=252 +MINOR=18 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/bInterval', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep04/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/device', '../../../4-1:1.2') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/bEndpointAddress', 0o644, b'84\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/dev', 0o644, b'252:17\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/wMaxPacketSize', 0o644, b'0020\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/uevent', 0o644, b'''MAJOR=252 +MINOR=17 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/bInterval', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/usb_endpoint/usbdev4.2_ep84/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.2/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/subsystem', '../../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/ep_83', 'usb_endpoint/usbdev4.2_ep83') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/ep_03', 'usb_endpoint/usbdev4.2_ep03') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/modalias', 0o644, b'usb:v0A5Cp2110d0100dcE0dsc01dp01icE0isc01ip01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/bInterfaceNumber', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/bNumEndpoints', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/bInterfaceSubClass', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/bInterfaceClass', 0o644, b'e0\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=a5c/2110/100 +TYPE=224/1/1 +INTERFACE=224/1/1 +MODALIAS=usb:v0A5Cp2110d0100dcE0dsc01dp01icE0isc01ip01 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/bInterfaceProtocol', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/device', '../../../4-1:1.1') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/interval', 0o644, b'1ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/bEndpointAddress', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/type', 0o644, b'Isoc\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/dev', 0o644, b'252:16\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/direction', 0o644, b'out\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/wMaxPacketSize', 0o644, b'0000\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/bmAttributes', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/uevent', 0o644, b'''MAJOR=252 +MINOR=16 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/bInterval', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep03/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/device', '../../../4-1:1.1') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/interval', 0o644, b'1ms\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/bEndpointAddress', 0o644, b'83\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/type', 0o644, b'Isoc\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/dev', 0o644, b'252:15\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/wMaxPacketSize', 0o644, b'0000\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/bmAttributes', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/uevent', 0o644, b'''MAJOR=252 +MINOR=15 +''') +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/bInterval', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/usb_endpoint/usbdev4.2_ep83/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.3/usb4/4-1/4-1:1.1/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.2', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.2/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:0d') +l('sys/devices/pci0000:00/0000:00:1c.2/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1c.2/driver', '../../../bus/pci/drivers/pcieport-driver') +f('sys/devices/pci0000:00/0000:00:1c.2/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1c.2/enable', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1c.2/modalias', 0o644, b'pci:v00008086d000027D4sv00000000sd00000000bc06sc04i00\n') +f('sys/devices/pci0000:00/0000:00:1c.2/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000006000 0x0000000000007fff 0x0000000000000100 +0x00000000e8000000 0x00000000e9ffffff 0x0000000000000200 +0x00000000e4100000 0x00000000e41fffff 0x0000000000001201 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1c.2/config', 0o644, b"\x86\x80\xd4'\x07\x05\x10\x00\x02\x00\x04\x06\x10\x00\x81\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x0b\x00`p\x00\x00\x00\xe8\xf0\xe9\x11\xe4\x11\xe4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x0b\x03\x04\x00\x10\x80A\x01\xc0\x0f\x00\x00\x00\x00\x10\x00\x11L\x11\x03\x00\x00\x01\x10\xe0\xa0 \x00(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x90\x01\x00\x0c0\xe0\xfe\x89A\x00\x00\x00\x00\x00\x00\r\xa0\x00\x00\xaa\x17\x11 \x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x11\xc0\x00\x00\x00\x00\x00\x00\xc7\x00\x06\x07\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00\x02\x00\x01\x18\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xff\x00\x00\x80\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x11\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x01\x00\x00\x01\x02\x03\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x01\xc0\xd1\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07`\x00`\x00\x00\x00\x00`\x02\x00\x00\x0c\x00\x06\x00\x00\x00\x00\x00[`\xc9\xc0\x00p&u\x00\x10\x00\x00\xff\x0f\x00\x00\x16\x00\x00\x14\xb5\xbcJ\xbc\x0b*\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x10\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1c.2/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1c.2/subsystem_device', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:1c.2/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1c.2/irq', 0o644, b'508\n') +f('sys/devices/pci0000:00/0000:00:1c.2/device', 0o644, b'0x27d4\n') +f('sys/devices/pci0000:00/0000:00:1c.2/class', 0o644, b'0x060400\n') +f('sys/devices/pci0000:00/0000:00:1c.2/msi_bus', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.2/subsystem_vendor', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:1c.2/uevent', 0o644, b'''DRIVER=pcieport-driver +PCI_CLASS=60400 +PCI_ID=8086:27D4 +PCI_SUBSYS_ID=0000:0000 +PCI_SLOT_NAME=0000:00:1c.2 +MODALIAS=pci:v00008086d000027D4sv00000000sd00000000bc06sc04i00 +''') +f('sys/devices/pci0000:00/0000:00:1c.2/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie02', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie02/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie02/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie02/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie02/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie00', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie00/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie00/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.2/pci_bus', 0o755) +d('sys/devices/pci0000:00/0000:00:1c.2/pci_bus/0000:04', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.2/pci_bus/0000:04/subsystem', '../../../../../class/pci_bus') +l('sys/devices/pci0000:00/0000:00:1c.2/pci_bus/0000:04/device', '../../../0000:00:1c.2') +f('sys/devices/pci0000:00/0000:00:1c.2/pci_bus/0000:04/cpuaffinity', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1c.2/pci_bus/0000:04/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.2/pci_bus/0000:04/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.2/pci_bus/0000:04/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.2/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie03', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie03/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie03/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie03/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.2/0000:00:1c.2:pcie03/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1b.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1b.0/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:25') +l('sys/devices/pci0000:00/0000:00:1b.0/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1b.0/driver', '../../../bus/pci/drivers/HDA Intel') +f('sys/devices/pci0000:00/0000:00:1b.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1b.0/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1b.0/modalias', 0o644, b'pci:v00008086d000027D8sv000017AAsd00002010bc04sc03i00\n') +f('sys/devices/pci0000:00/0000:00:1b.0/resource', 0o644, b'''0x00000000ee400000 0x00000000ee403fff 0x0000000000020204 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1b.0/config', 0o644, b"\x86\x80\xd8'\x06\x01\x10\x00\x02\x00\x03\x04\x10\x00\x00\x00\x04\x00@\xee\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\x10 \x00\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x0b\x02\x00\x00\x03\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x01`B\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05p\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x91\x00\x00\x00\x00\x00\x00\x08\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00\x02\x00\x01\x13\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x01\x00\x00\x01\x02\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\xc0\xd1\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1b.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1b.0/subsystem_device', 0o644, b'0x2010\n') +f('sys/devices/pci0000:00/0000:00:1b.0/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1b.0/irq', 0o644, b'17\n') +f('sys/devices/pci0000:00/0000:00:1b.0/device', 0o644, b'0x27d8\n') +f('sys/devices/pci0000:00/0000:00:1b.0/class', 0o644, b'0x040300\n') +f('sys/devices/pci0000:00/0000:00:1b.0/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1b.0/resource0', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1b.0/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1b.0/uevent', 0o644, b'''DRIVER=HDA Intel +PCI_CLASS=40300 +PCI_ID=8086:27D8 +PCI_SUBSYS_ID=17AA:2010 +PCI_SLOT_NAME=0000:00:1b.0 +MODALIAS=pci:v00008086d000027D8sv000017AAsd00002010bc04sc03i00 +''') +f('sys/devices/pci0000:00/0000:00:1b.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1b.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1b.0/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1b.0/sound', 0o755) +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0', 0o755) +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/subsystem', '../../../../../class/sound') +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/device', '../../../0000:00:1b.0') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/audio', 0o755) +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/audio/subsystem', '../../../../../../class/sound') +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/audio/device', '../../card0') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/audio/dev', 0o644, b'14:4\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/audio/uevent', 0o644, b'''MAJOR=14 +MINOR=4 +''') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/audio/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/audio/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/dsp', 0o755) +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/dsp/subsystem', '../../../../../../class/sound') +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/dsp/device', '../../card0') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/dsp/dev', 0o644, b'14:3\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/dsp/uevent', 0o644, b'''MAJOR=14 +MINOR=3 +''') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/dsp/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/dsp/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/mixer', 0o755) +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/mixer/subsystem', '../../../../../../class/sound') +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/mixer/device', '../../card0') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/mixer/dev', 0o644, b'14:0\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/mixer/uevent', 0o644, b'''MAJOR=14 +MINOR=0 +''') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/mixer/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/mixer/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0p', 0o755) +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0p/subsystem', '../../../../../../class/sound') +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0p/device', '../../card0') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0p/pcm_class', 0o644, b'generic\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0p/dev', 0o644, b'116:16\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0p/uevent', 0o644, b'''MAJOR=116 +MINOR=16 +''') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0p/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0p/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/controlC0', 0o755) +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/controlC0/subsystem', '../../../../../../class/sound') +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/controlC0/device', '../../card0') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/controlC0/dev', 0o644, b'116:0\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/controlC0/uevent', 0o644, b'''MAJOR=116 +MINOR=0 +''') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/controlC0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/controlC0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c', 0o755) +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c/subsystem', '../../../../../../class/sound') +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c/device', '../../card0') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c/pcm_class', 0o644, b'generic\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c/dev', 0o644, b'116:24\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c/uevent', 0o644, b'''MAJOR=116 +MINOR=24 +''') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/adsp', 0o755) +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/adsp/subsystem', '../../../../../../class/sound') +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/adsp/device', '../../card0') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/adsp/dev', 0o644, b'14:12\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/adsp/uevent', 0o644, b'''MAJOR=14 +MINOR=12 +''') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/adsp/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/adsp/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D1p', 0o755) +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D1p/subsystem', '../../../../../../class/sound') +l('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D1p/device', '../../card0') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D1p/pcm_class', 0o644, b'generic\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D1p/dev', 0o644, b'116:17\n') +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D1p/uevent', 0o644, b'''MAJOR=116 +MINOR=17 +''') +d('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D1p/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D1p/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/pci_bus', 0o755) +d('sys/devices/pci0000:00/pci_bus/0000:00', 0o755) +l('sys/devices/pci0000:00/pci_bus/0000:00/subsystem', '../../../../class/pci_bus') +l('sys/devices/pci0000:00/pci_bus/0000:00/device', '../../../pci0000:00') +f('sys/devices/pci0000:00/pci_bus/0000:00/cpuaffinity', 0o644, b'ff\n') +f('sys/devices/pci0000:00/pci_bus/0000:00/uevent', 0o644, b'') +d('sys/devices/pci0000:00/pci_bus/0000:00/power', 0o755) +f('sys/devices/pci0000:00/pci_bus/0000:00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/power', 0o755) +f('sys/devices/pci0000:00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:21') +l('sys/devices/pci0000:00/0000:00:1d.7/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1d.7/driver', '../../../bus/pci/drivers/ehci_hcd') +f('sys/devices/pci0000:00/0000:00:1d.7/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1d.7/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/modalias', 0o644, b'pci:v00008086d000027CCsv000017AAsd0000200Bbc0Csc03i20\n') +f('sys/devices/pci0000:00/0000:00:1d.7/resource', 0o644, b'''0x00000000ee404000 0x00000000ee4043ff 0x0000000000020200 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/config', 0o644, b"\x86\x80\xcc'\x06\x01\x90\x02\x02 \x03\x0c\x00\x00\x00\x00\x00@@\xee\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\x0b \x00\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x0b\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01X\xc2\xc9\x00\x80\x00\x00\n\x00\xa0 \x00\x00\x00\x00 \x9f\x01\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x08\x80\x00\x00\xd7?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\xff\x00\xff\x00\xff\x00 \x00\x00\x88\x00\x00\x00\x00\xdb\xb6m\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\t\x88\x85@\x00\x86\x0f\x02\x00\x06\x17\x02 ") +f('sys/devices/pci0000:00/0000:00:1d.7/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1d.7/subsystem_device', 0o644, b'0x200b\n') +f('sys/devices/pci0000:00/0000:00:1d.7/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1d.7/irq', 0o644, b'19\n') +f('sys/devices/pci0000:00/0000:00:1d.7/pools', 0o644, b'''poolinfo - 0.1 +ehci_sitd 0 0 96 0 +ehci_itd 0 0 192 0 +ehci_qh 5 25 160 1 +ehci_qtd 5 42 96 1 +buffer-2048 16 32 2048 16 +buffer-512 0 0 512 0 +buffer-128 2 32 128 1 +buffer-32 2 128 32 1 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/device', 0o644, b'0x27cc\n') +f('sys/devices/pci0000:00/0000:00:1d.7/class', 0o644, b'0x0c0320\n') +f('sys/devices/pci0000:00/0000:00:1d.7/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.7/resource0', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.7/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1d.7/uevent', 0o644, b'''DRIVER=ehci_hcd +PCI_CLASS=C0320 +PCI_ID=8086:27CC +PCI_SUBSYS_ID=17AA:200B +PCI_SLOT_NAME=0000:00:1d.7 +MODALIAS=pci:v00008086d000027CCsv000017AAsd0000200Bbc0Csc03i20 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/subsystem', '../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/driver', '../../../../bus/usb/drivers/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/ep_00', 'usb_endpoint/usbdev5.1_ep00') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/version', 0o644, b' 2.00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/authorized_default', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/maxchild', 0o644, b'8\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/bDeviceClass', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/bcdDevice', 0o644, b'0206\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/devnum', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/bDeviceProtocol', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/idProduct', 0o644, b'0002\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/product', 0o644, b'EHCI Host Controller\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/bDeviceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/configuration', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/dev', 0o644, b'189:512\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/urbnum', 0o644, b'151\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/authorized', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/descriptors', 0o644, b'\x12\x01\x00\x02\t\x00\x00@k\x1d\x02\x00\x06\x02\x03\x02\x01\x01\t\x02\x19\x00\x01\x01\x00\xe0\x00\t\x04\x00\x00\x01\t\x00\x00\x00\x07\x05\x81\x03\x04\x00\x0c') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/bNumConfigurations', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/serial', 0o644, b'0000:00:1d.7\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/speed', 0o644, b'480\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/bMaxPacketSize0', 0o644, b'64\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/bmAttributes', 0o644, b'e0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/busnum', 0o644, b'5\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/quirks', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/bConfigurationValue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/uevent', 0o644, b'''MAJOR=189 +MINOR=512 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=1d6b/2/206 +TYPE=9/0/0 +BUSNUM=005 +DEVNUM=001 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/manufacturer', 0o644, b'Linux 2.6.27-rc7-00106-g6ef190c-dirty ehci_hcd\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/idVendor', 0o644, b'1d6b\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/bNumInterfaces', 0o644, b' 1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/bMaxPower', 0o644, b' 0mA\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/subsystem', '../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/device', '../../../usb5') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/bEndpointAddress', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/type', 0o644, b'Control\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/dev', 0o644, b'252:9\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/direction', 0o644, b'both\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/bmAttributes', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/uevent', 0o644, b'''MAJOR=252 +MINOR=9 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/usb_endpoint/usbdev5.1_ep00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/subsystem', '../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/driver', '../../../../../bus/usb/drivers/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/ep_00', 'usb_endpoint/usbdev5.7_ep00') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/version', 0o644, b' 2.00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/maxchild', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/bDeviceClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/bcdDevice', 0o644, b'0100\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/devnum', 0o644, b'7\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/bDeviceProtocol', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/idProduct', 0o644, b'8012\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/product', 0o644, b'Flash Disk\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/bDeviceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/configuration', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/dev', 0o644, b'189:518\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/urbnum', 0o644, b'743\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/authorized', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/descriptors', 0o644, b'\x12\x01\x00\x02\x00\x00\x00@C\x10\x12\x80\x00\x01\x01\x02\x00\x01\t\x02 \x00\x01\x01\x00\x802\t\x04\x00\x00\x02\x08\x06P\x00\x07\x05\x81\x02\x00\x02\x00\x07\x05\x02\x02\x00\x02\x00') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/bNumConfigurations', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/speed', 0o644, b'480\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/bMaxPacketSize0', 0o644, b'64\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/bmAttributes', 0o644, b'80\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/busnum', 0o644, b'5\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/quirks', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/bConfigurationValue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/uevent', 0o644, b'''MAJOR=189 +MINOR=518 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=1043/8012/100 +TYPE=0/0/0 +BUSNUM=005 +DEVNUM=007 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/manufacturer', 0o644, b'Generic\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/idVendor', 0o644, b'1043\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/bNumInterfaces', 0o644, b' 1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/bMaxPower', 0o644, b'100mA\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/subsystem', '../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/device', '../../../5-1') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/bEndpointAddress', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/type', 0o644, b'Control\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/dev', 0o644, b'252:24\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/direction', 0o644, b'both\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/bmAttributes', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/uevent', 0o644, b'''MAJOR=252 +MINOR=24 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/usb_endpoint/usbdev5.7_ep00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/power/active_duration', 0o644, b'65113\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/power/wakeup', 0o644, b'\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/power/connected_duration', 0o644, b'65113\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/power/autosuspend', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/power/persist', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/power/level', 0o644, b'on\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/subsystem', '../../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/ep_81', 'usb_endpoint/usbdev5.7_ep81') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/ep_02', 'usb_endpoint/usbdev5.7_ep02') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/driver', '../../../../../../bus/usb/drivers/usb-storage') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/modalias', 0o644, b'usb:v1043p8012d0100dc00dsc00dp00ic08isc06ip50\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/bInterfaceNumber', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/bNumEndpoints', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/bInterfaceSubClass', 0o644, b'06\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/bInterfaceClass', 0o644, b'08\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/uevent', 0o644, b'''DEVTYPE=usb_interface +DRIVER=usb-storage +PRODUCT=1043/8012/100 +TYPE=0/0/0 +INTERFACE=8/6/80 +MODALIAS=usb:v1043p8012d0100dc00dsc00dp00ic08isc06ip50 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/bInterfaceProtocol', 0o644, b'50\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/device', '../../../5-1:1.0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/bEndpointAddress', 0o644, b'81\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/dev', 0o644, b'252:10\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/wMaxPacketSize', 0o644, b'0200\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/uevent', 0o644, b'''MAJOR=252 +MINOR=10 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep81/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/device', '../../../5-1:1.0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/bEndpointAddress', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/dev', 0o644, b'252:11\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/direction', 0o644, b'out\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/wMaxPacketSize', 0o644, b'0200\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/uevent', 0o644, b'''MAJOR=252 +MINOR=11 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/usb_endpoint/usbdev5.7_ep02/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/subsystem', '../../../../../../../bus/scsi') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/uevent', 0o644, b'DEVTYPE=scsi_host\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/subsystem', '../../../../../../../../bus/scsi') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/uevent', 0o644, b'DEVTYPE=scsi_target\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/generic', 'scsi_generic/sg2') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/subsystem', '../../../../../../../../../bus/scsi') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/driver', '../../../../../../../../../bus/scsi/drivers/sd') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/iodone_cnt', 0o644, b'0xc3\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/device_blocked', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/max_sectors', 0o644, b'240\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/modalias', 0o644, b'scsi:t-0x00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_level', 0o644, b'3\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/queue_depth', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/rev', 0o644, b'1.00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/iocounterbits', 0o644, b'32\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/vendor', 0o644, b'Generic \n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/state', 0o644, b'running\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/queue_type', 0o644, b'none\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/iorequest_cnt', 0o644, b'0xc3\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/evt_media_change', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/model', 0o644, b'USB Flash Drive \n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/ioerr_cnt', 0o644, b'0x2\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/uevent', 0o644, b'''DEVTYPE=scsi_device +DRIVER=sd +MODALIAS=scsi:t-0x00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/timeout', 0o644, b'60\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/subsystem', '../../../../../../../../../../../class/scsi_disk') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/device', '../../../7:0:0:0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/app_tag_own', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/FUA', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/cache_type', 0o644, b'write through\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/protection_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/manage_start_stop', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/allow_restart', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_generic', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg2', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg2/subsystem', '../../../../../../../../../../../class/scsi_generic') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg2/device', '../../../7:0:0:0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg2/dev', 0o644, b'21:2\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg2/uevent', 0o644, b'''MAJOR=21 +MINOR=2 +''') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg2/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/bsg', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0/subsystem', '../../../../../../../../../../../class/bsg') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0/device', '../../../7:0:0:0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0/dev', 0o644, b'254:2\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0/uevent', 0o644, b'''MAJOR=254 +MINOR=2 +''') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/subsystem', '../../../../../../../../../../../class/block') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/bdi', '../../../../../../../../../../virtual/bdi/8:16') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/device', '../../../7:0:0:0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/capability', 0o644, b'13\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/ro', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/size', 0o644, b'257024\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/dev', 0o644, b'8:16\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/range', 0o644, b'16\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/removable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/stat', 0o644, b' 117 409 2103 272 0 0 0 0 0 194 272\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/uevent', 0o644, b'''MAJOR=8 +MINOR=16 +DEVTYPE=disk +''') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/bsg', '../../../bsg/7:0:0:0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/nr_requests', 0o644, b'128\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/nomerges', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/scheduler', 0o644, b'noop anticipatory deadline [cfq] \n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/hw_sector_size', 0o644, b'512\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/max_hw_sectors_kb', 0o644, b'120\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/read_ahead_kb', 0o644, b'128\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/max_sectors_kb', 0o644, b'120\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/iosched', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/iosched/slice_async_rq', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/iosched/back_seek_max', 0o644, b'16384\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/iosched/slice_sync', 0o644, b'100\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/iosched/slice_async', 0o644, b'40\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/iosched/fifo_expire_sync', 0o644, b'125\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/iosched/slice_idle', 0o644, b'8\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/iosched/back_seek_penalty', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/iosched/fifo_expire_async', 0o644, b'250\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/queue/iosched/quantum', 0o644, b'4\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1/subsystem', '../../../../../../../../../../../../class/block') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1/start', 0o644, b'32\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1/size', 0o644, b'256992\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1/dev', 0o644, b'8:17\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1/stat', 0o644, b' 109 392 1903 246 0 0 0 0 0 169 246\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1/uevent', 0o644, b'''MAJOR=8 +MINOR=17 +DEVTYPE=partition +''') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/block/sdb/sdb1/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_device', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_device/7:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_device/7:0:0:0/subsystem', '../../../../../../../../../../../class/scsi_device') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_device/7:0:0:0/device', '../../../7:0:0:0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_device/7:0:0:0/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_device/7:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/target7:0:0/7:0:0:0/scsi_device/7:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/subsystem', '../../../../../../../../../class/scsi_host') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/device', '../../../host7') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/unique_id', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/can_queue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/unchecked_isa_dma', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/active_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/sg_tablesize', 0o644, b'128\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/prot_guard_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/host_busy', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/proc_name', 0o644, b'usb-storage\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/state', 0o644, b'running\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/cmd_per_lun', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/supported_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/uevent', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/prot_capabilities', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-1/5-1:1.0/host7/scsi_host/host7/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/subsystem', '../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/driver', '../../../../../bus/usb/drivers/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/ep_00', 'usb_endpoint/usbdev5.9_ep00') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/version', 0o644, b' 2.00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/maxchild', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/bDeviceClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/bcdDevice', 0o644, b'0100\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/devnum', 0o644, b'9\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/bDeviceProtocol', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/idProduct', 0o644, b'007b\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/product', 0o644, b'N78\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/bDeviceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/configuration', 0o644, b'Bulk transfer method configuration\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/dev', 0o644, b'189:520\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/urbnum', 0o644, b'20\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/authorized', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/descriptors', 0o644, b'''\x12\x01\x00\x02\x02\x00\x00@!\x04{\x00\x00\x01\x01\x02\x03\x01\t\x02\xab\x01\x0e\x01\x04\xc02\t\x04\x00\x00\x01\x02\x02\x01\x06\x05$\x00\x00\x01\x04$\x02\x0f\x05$\x06\x00\x01\x07\x05\x81\x03@\x00\x08\t\x04\x01\x00\x02 +\x00\x00\x07\x07\x05\x82\x02\x00\x02\xff\x07\x05\x01\x02\x00\x02\xff\t\x04\x02\x00\x01\x02\x02\xff\x08\x05$\x00\x00\x01\x04$\x02\x0f\x05$\x06\x02\x03\x07\x05\x83\x03@\x00\x08\t\x04\x03\x00\x02 +\x00\x00\t\x07\x05\x84\x02\x00\x02\xff\x07\x05\x02\x02\x00\x02\xff\t\x04\x04\x00\x00\x02\x08\x00\x00\x05$\x00\x10\x01\x05$\x11\x00\x01\r$\x06\x04\x05\x06\x07\x08\t +\x0b\x0c\r\t\x04\x05\x00\x00\x02\x0b\x00 +\x05$\x00\x10\x01\x05$\x15\x00\x01\x05$\x06\x05\x06\t\x04\x06\x00\x00 +\x00\x00\x00\t\x04\x06\x01\x02 +\x00\x00\x00\x07\x05\x85\x02\x00\x02\xff\x07\x05\x03\x02\x00\x02\xff\t\x04\x07\x00\x00\x02\x0b\x00\x0b\x05$\x00\x10\x01\x05$\x15\x00\x01\x05$\x06\x07\x08\t\x04\x08\x00\x00 +\x00\x00\x00\t\x04\x08\x01\x02 +\x00\x00\x00\x07\x05\x86\x02\x00\x02\xff\x07\x05\x04\x02\x00\x02\xff\t\x04\t\x00\x00\x02\x08\x01\x00\x05$\x00\x10\x01\x05$\x08\x00\x01\x06$\x06\t +\x0b\t\x04 +\x00\x00\x02\xfe\x00\x00\x05$\x00\x10\x01\x05$\xab\x05\x15\x05$\x06 +\x0b\t\x04\x0b\x00\x00 +\x00\x00\x00\t\x04\x0b\x01\x02 +\x00\x00\x00\x04$\xfd\x01\x07\x05\x05\x02\x00\x02\xff\x07\x05\x87\x02\x00\x02\xff\t\x04\x0c\x00\x00\x02\xfd\x00\x0c\x05$\x00\x10\x01\x05$\xfc\x00\x01\x05$\x06\x0c\r\x04$\xfd\x00\t\x04\r\x00\x00 +\x00\x00\x00\t\x04\r\x01\x02 +\x00\x00\x00\x07\x05\x88\x03\x00\x02\x06\x07\x05\x06\x02\x00\x02\xff\t\x04\r\x02\x02 +\x00\x00\x00\x07\x05\x88\x02\x00\x02\xff\x07\x05\x06\x02\x00\x02\xff''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/bNumConfigurations', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/serial', 0o644, b'354172020305000\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/speed', 0o644, b'480\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/bMaxPacketSize0', 0o644, b'64\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/bmAttributes', 0o644, b'c0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/busnum', 0o644, b'5\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/quirks', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/bConfigurationValue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/uevent', 0o644, b'''MAJOR=189 +MINOR=520 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=421/7b/100 +TYPE=2/0/0 +BUSNUM=005 +DEVNUM=009 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/manufacturer', 0o644, b'Nokia\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/idVendor', 0o644, b'0421\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/bNumInterfaces', 0o644, b'14\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/bMaxPower', 0o644, b'100mA\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic02isc08ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/bInterfaceNumber', 0o644, b'04\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/bInterfaceSubClass', 0o644, b'08\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/bInterfaceClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=2/8/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic02isc08ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.4/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/subsystem', '../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/device', '../../../5-2') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/bEndpointAddress', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/type', 0o644, b'Control\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/dev', 0o644, b'252:33\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/direction', 0o644, b'both\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/bmAttributes', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/uevent', 0o644, b'''MAJOR=252 +MINOR=33 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/usb_endpoint/usbdev5.9_ep00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/subsystem', '../../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/ep_83', 'usb_endpoint/usbdev5.9_ep83') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic02isc02ipFF\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/bInterfaceNumber', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/bNumEndpoints', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/interface', 0o644, b'CDC Comms Interface\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/bInterfaceSubClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/bInterfaceClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=2/2/255 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic02isc02ipFF +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/bInterfaceProtocol', 0o644, b'ff\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/device', '../../../5-2:1.2') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/interval', 0o644, b'16ms\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/bEndpointAddress', 0o644, b'83\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/type', 0o644, b'Interrupt\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/dev', 0o644, b'252:30\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/bmAttributes', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/uevent', 0o644, b'''MAJOR=252 +MINOR=30 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/bInterval', 0o644, b'08\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/usb_endpoint/usbdev5.9_ep83/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.2/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/subsystem', '../../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/ep_01', 'usb_endpoint/usbdev5.9_ep01') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/ep_82', 'usb_endpoint/usbdev5.9_ep82') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/driver', '../../../../../../bus/usb/drivers/cdc_acm') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/bInterfaceNumber', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/bNumEndpoints', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/interface', 0o644, b'CDC Data Interface\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/bInterfaceClass', 0o644, b'0a\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/uevent', 0o644, b'''DEVTYPE=usb_interface +DRIVER=cdc_acm +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=10/0/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/device', '../../../5-2:1.1') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/interval', 0o644, b'31875us\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/bEndpointAddress', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/dev', 0o644, b'252:29\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/direction', 0o644, b'out\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/wMaxPacketSize', 0o644, b'0200\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/uevent', 0o644, b'''MAJOR=252 +MINOR=29 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/bInterval', 0o644, b'ff\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep01/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/device', '../../../5-2:1.1') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/bEndpointAddress', 0o644, b'82\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/dev', 0o644, b'252:28\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/wMaxPacketSize', 0o644, b'0200\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/uevent', 0o644, b'''MAJOR=252 +MINOR=28 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/bInterval', 0o644, b'ff\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/usb_endpoint/usbdev5.9_ep82/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.1/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic02iscFEip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/bInterfaceNumber', 0o644, b'0a\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/bInterfaceSubClass', 0o644, b'fe\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/bInterfaceClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=2/254/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic02iscFEip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.10/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic02isc0Bip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/bInterfaceNumber', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/interface', 0o644, b'PC Suite Services\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/bInterfaceSubClass', 0o644, b'0b\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/bInterfaceClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=2/11/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic02isc0Bip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.7/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/subsystem', '../../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/ep_81', 'usb_endpoint/usbdev5.9_ep81') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/driver', '../../../../../../bus/usb/drivers/cdc_acm') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic02isc02ip01\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/bInterfaceNumber', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/bmCapabilities', 0o644, b'15') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/bNumEndpoints', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/interface', 0o644, b'CDC Comms Interface\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/bInterfaceSubClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/bInterfaceClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/uevent', 0o644, b'''DEVTYPE=usb_interface +DRIVER=cdc_acm +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=2/2/1 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic02isc02ip01 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/bInterfaceProtocol', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/device', '../../../5-2:1.0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/interval', 0o644, b'16ms\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/bEndpointAddress', 0o644, b'81\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/type', 0o644, b'Interrupt\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/dev', 0o644, b'252:27\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/bmAttributes', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/uevent', 0o644, b'''MAJOR=252 +MINOR=27 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/bInterval', 0o644, b'08\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/usb_endpoint/usbdev5.9_ep81/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0/subsystem', '../../../../../../../../class/tty') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0/device', '../../../5-2:1.0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0/dev', 0o644, b'166:0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0/uevent', 0o644, b'''MAJOR=166 +MINOR=0 +DEVNAME=ttyACM0 +''') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic02isc08ip01\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/bInterfaceNumber', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/bInterfaceSubClass', 0o644, b'08\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/bInterfaceClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=2/8/1 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic02isc08ip01 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/bInterfaceProtocol', 0o644, b'01\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.9/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/bInterfaceNumber', 0o644, b'08\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/bInterfaceClass', 0o644, b'0a\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=10/0/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.8/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/power/active_duration', 0o644, b'20902\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/power/wakeup', 0o644, b'\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/power/connected_duration', 0o644, b'20901\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/power/autosuspend', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/power/persist', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/power/level', 0o644, b'on\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/bInterfaceNumber', 0o644, b'0d\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/bInterfaceClass', 0o644, b'0a\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=10/0/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.13/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic02isc0Bip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/bInterfaceNumber', 0o644, b'05\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/interface', 0o644, b'SYNCML-SYNC\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/bInterfaceSubClass', 0o644, b'0b\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/bInterfaceClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=2/11/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic02isc0Bip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.5/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/bInterfaceNumber', 0o644, b'0b\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/bInterfaceClass', 0o644, b'0a\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=10/0/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.11/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic02iscFDip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/bInterfaceNumber', 0o644, b'0c\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/interface', 0o644, b'LCIF_Alt0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/bInterfaceSubClass', 0o644, b'fd\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/bInterfaceClass', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=2/253/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic02iscFDip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.12/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/subsystem', '../../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/ep_02', 'usb_endpoint/usbdev5.9_ep02') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/ep_84', 'usb_endpoint/usbdev5.9_ep84') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/bInterfaceNumber', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/bNumEndpoints', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/interface', 0o644, b'CDC Data Interface\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/bInterfaceClass', 0o644, b'0a\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=10/0/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/device', '../../../5-2:1.3') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/bEndpointAddress', 0o644, b'84\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/dev', 0o644, b'252:31\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/wMaxPacketSize', 0o644, b'0200\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/uevent', 0o644, b'''MAJOR=252 +MINOR=31 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/bInterval', 0o644, b'ff\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep84/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/device', '../../../5-2:1.3') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/interval', 0o644, b'31875us\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/bEndpointAddress', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/type', 0o644, b'Bulk\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/dev', 0o644, b'252:32\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/direction', 0o644, b'out\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/wMaxPacketSize', 0o644, b'0200\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/bmAttributes', 0o644, b'02\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/uevent', 0o644, b'''MAJOR=252 +MINOR=32 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/bInterval', 0o644, b'ff\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/usb_endpoint/usbdev5.9_ep02/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.3/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/subsystem', '../../../../../../bus/usb') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/modalias', 0o644, b'usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/bInterfaceNumber', 0o644, b'06\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/bNumEndpoints', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/bInterfaceClass', 0o644, b'0a\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/uevent', 0o644, b'''DEVTYPE=usb_interface +PRODUCT=421/7b/100 +TYPE=2/0/0 +INTERFACE=10/0/0 +MODALIAS=usb:v0421p007Bd0100dc02dsc00dp00ic0Aisc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.6/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/power/active_duration', 0o644, b'547102\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/power/wakeup', 0o644, b'enabled\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/power/connected_duration', 0o644, b'8371932\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/power/autosuspend', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/power/level', 0o644, b'auto\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/subsystem', '../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/ep_81', 'usb_endpoint/usbdev5.1_ep81') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/driver', '../../../../../bus/usb/drivers/hub') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/modalias', 0o644, b'usb:v1D6Bp0002d0206dc09dsc00dp00ic09isc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/bInterfaceNumber', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/bNumEndpoints', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/bInterfaceClass', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/uevent', 0o644, b'''DEVTYPE=usb_interface +DRIVER=hub +PRODUCT=1d6b/2/206 +TYPE=9/0/0 +INTERFACE=9/0/0 +MODALIAS=usb:v1D6Bp0002d0206dc09dsc00dp00ic09isc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/subsystem', '../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/device', '../../../5-0:1.0') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/interval', 0o644, b'256ms\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/bEndpointAddress', 0o644, b'81\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/type', 0o644, b'Interrupt\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/dev', 0o644, b'252:8\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/wMaxPacketSize', 0o644, b'0004\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/bmAttributes', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/uevent', 0o644, b'''MAJOR=252 +MINOR=8 +''') +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/bInterval', 0o644, b'0c\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/usb_endpoint/usbdev5.1_ep81/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb5/5-0:1.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.7/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1d.7/usb_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.7/usb_host/usb_host5', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.7/usb_host/usb_host5/subsystem', '../../../../../class/usb_host') +l('sys/devices/pci0000:00/0000:00:1d.7/usb_host/usb_host5/device', '../../../0000:00:1d.7') +f('sys/devices/pci0000:00/0000:00:1d.7/usb_host/usb_host5/companion', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.7/usb_host/usb_host5/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1d.7/usb_host/usb_host5/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.7/usb_host/usb_host5/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:0c') +l('sys/devices/pci0000:00/0000:00:1c.1/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1c.1/driver', '../../../bus/pci/drivers/pcieport-driver') +f('sys/devices/pci0000:00/0000:00:1c.1/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1c.1/enable', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1c.1/modalias', 0o644, b'pci:v00008086d000027D2sv00000000sd00000000bc06sc04i00\n') +f('sys/devices/pci0000:00/0000:00:1c.1/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000004000 0x0000000000005fff 0x0000000000000100 +0x00000000ec000000 0x00000000edffffff 0x0000000000000200 +0x00000000e4000000 0x00000000e40fffff 0x0000000000001201 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1c.1/config', 0o644, b"\x86\x80\xd2'\x07\x05\x10\x00\x02\x00\x04\x06\x10\x00\x81\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x03\x00@P\x00\x00\x00\xec\xf0\xed\x01\xe4\x01\xe4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x0b\x02\x04\x00\x10\x80A\x01\xc0\x0f\x00\x00\x00\x00\x11\x00\x11,\x11\x02B\x00\x110\xe0\xa0\x18\x00\x00\x00H\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x90\x01\x00\x0c0\xe0\xfe\x81A\x00\x00\x00\x00\x00\x00\r\xa0\x00\x00\xaa\x17\x11 \x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x11\x00\x00\x00\x00\x00\x00\x0f\xc7\x80\x06\x07\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00\x02\x00\x01\x18\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x80\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x06\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x01\x00\x00\x01\x02\x02\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x01\xc0\xd1\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07`\x00`\x00\x00\x00\x00`\x02\x00\x00\x0c\x00\x06\x00\x00\x00\x001[`\xc9\xc0\x00p&u\xa2\x178\x00\xa1\x07G\x02\x16\x00\x00\x14\xb5\xbcJ\xbc\x0b*\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x0c\xb4\x00\xc4\x0c\xb6\x00A\x08z\x00Y\x00\x1b\x00[\x00\x1d\x00\x01\x00\xba\x00\xe3\x0f\xd3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1c.1/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1c.1/subsystem_device', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:1c.1/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1c.1/irq', 0o644, b'509\n') +f('sys/devices/pci0000:00/0000:00:1c.1/device', 0o644, b'0x27d2\n') +f('sys/devices/pci0000:00/0000:00:1c.1/class', 0o644, b'0x060400\n') +f('sys/devices/pci0000:00/0000:00:1c.1/msi_bus', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.1/subsystem_vendor', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:1c.1/uevent', 0o644, b'''DRIVER=pcieport-driver +PCI_CLASS=60400 +PCI_ID=8086:27D2 +PCI_SUBSYS_ID=0000:0000 +PCI_SLOT_NAME=0000:00:1c.1 +MODALIAS=pci:v00008086d000027D2sv00000000sd00000000bc06sc04i00 +''') +f('sys/devices/pci0000:00/0000:00:1c.1/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1c.1/pci_bus', 0o755) +d('sys/devices/pci0000:00/0000:00:1c.1/pci_bus/0000:03', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/pci_bus/0000:03/subsystem', '../../../../../class/pci_bus') +l('sys/devices/pci0000:00/0000:00:1c.1/pci_bus/0000:03/device', '../../../0000:00:1c.1') +f('sys/devices/pci0000:00/0000:00:1c.1/pci_bus/0000:03/cpuaffinity', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1c.1/pci_bus/0000:03/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.1/pci_bus/0000:03/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/pci_bus/0000:03/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie02', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie02/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie02/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie02/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie02/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie03', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie03/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie03/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie03/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie03/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/subsystem', '../../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/driver', '../../../../bus/pci/drivers/iwl3945') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/rs_window', 0o644, b''' 54Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 48Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 36Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 24Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 18Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 12Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 11Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 9Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 6Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 5Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 2Mbs: 00000000000000000000000000000000000000000000000000000000000000 + 1Mbs: 00000000000000000000000000000000000000000000000000000000000000 + +Average rate: 0Mbs +''') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/modalias', 0o644, b'pci:v00008086d00004227sv00008086sd00001011bc02sc80i00\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/resource', 0o644, b'''0x00000000edf00000 0x00000000edf00fff 0x0000000000020200 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/statistics', 0o644, b'''02 00 01 00 a4 c0 02 00 c6 27 01 00 80 16 01 00 .........\'...... +e9 0c 00 00 00 00 00 00 00 00 00 00 69 05 00 00 ............i... +de 98 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00 00 00 00 00 00 00 00 bd 01 00 00 00 00 00 00 ................ +fd 68 08 00 ae d3 06 00 78 65 04 00 b8 2b 00 00 .h......xe...+.. +00 00 00 00 00 00 00 00 7e 42 02 00 4f 95 01 00 ........~B..O... +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00 00 00 00 da 01 00 00 00 00 00 00 00 00 00 00 ................ +00 00 00 00 d8 dc 00 00 59 10 01 00 00 00 00 00 ........Y....... +df 0c 00 00 16 00 00 00 00 00 00 00 00 00 00 00 ................ +88 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................ +00 00 00 00 72 ff ff ff 00 00 00 00 00 00 00 00 ....r........... +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +00 00 00 00 01 00 00 00 bb 45 98 35 1c 91 e7 f1 .........E.5.... +4c 19 00 00 c2 0c 00 00 e7 ed 00 00 1c 4c 00 00 L............L.. +''') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/config', 0o644, b'\x86\x80\'B\x06\x05\x10\x00\x02\x00\x80\x02\x10\x00\x00\x00\x00\x00\xf0\xed\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x80\x11\x10\x00\x00\x00\x00\xc8\x00\x00\x00\x00\x00\x00\x00\x0b\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xd0"H\x00\x00\x00\r\x05\xe0\x81\x00\x0c\x10\xe0\xfe\x00\x00\x00\x00\xd1A\x00\x00\x10\x00\x11\x00\xc0\x0e\x00\x00\x10\x08\n\x00\x11\x1c\x07\x00B\x01\x11\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x14\x00\x00\x10\x00\x00\x00\x00\x00\x11 \x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x01\x00\x00\x04\x0f\x1a\x00\x00\x00\x01\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x01\x00\xd1\xaeu\xff\xff\xd2\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/filter_flags', 0o644, b'0x0024\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/retry_rate', 0o644, b'1') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/channels', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/subsystem_device', 0o644, b'0x1011\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/tx_power', 0o644, b'16\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/irq', 0o644, b'504\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/antenna', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/device', 0o644, b'0x4227\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/class', 0o644, b'0x028000\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/power_level', 0o644, b'6 (AC) OFF\n\x00') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/flags', 0o644, b'0x8015\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/resource0', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/temperature', 0o644, b'-142\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/measurement', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/subsystem_vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/uevent', 0o644, b'''DRIVER=iwl3945 +PCI_CLASS=28000 +PCI_ID=8086:4227 +PCI_SUBSYS_ID=8086:1011 +PCI_SLOT_NAME=0000:03:00.0 +MODALIAS=pci:v00008086d00004227sv00008086sd00001011bc02sc80i00 +''') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/status', 0o644, b'0x000002e4\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/ieee80211', 0o755) +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/ieee80211/phy0', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/ieee80211/phy0/subsystem', '../../../../../../class/ieee80211') +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/ieee80211/phy0/device', '../../../0000:03:00.0') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/ieee80211/phy0/index', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/ieee80211/phy0/uevent', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/ieee80211/phy0/macaddress', 0o644, b'00:19:d2:75:ae:d1\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/ieee80211/phy0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/ieee80211/phy0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net', 0o755) +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/subsystem', '../../../../../../class/net') +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/device', '../../../0000:03:00.0') +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/phy80211', '../../ieee80211/phy0') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/ifindex', 0o644, b'3\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/features', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/iflink', 0o644, b'3\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/dormant', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/dev_id', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/type', 0o644, b'801\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/operstate', 0o644, b'unknown\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/carrier', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/link_mode', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/tx_queue_len', 0o644, b'1000\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/flags', 0o644, b'0x1003\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/addr_len', 0o644, b'6\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/address', 0o644, b'00:19:d2:75:ae:ff\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/uevent', 0o644, b'''INTERFACE=wmaster0 +IFINDEX=3 +''') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/mtu', 0o644, b'1500\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/broadcast', 0o644, b'ff:ff:ff:ff:ff:ff\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/tx_aborted_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_crc_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_bytes', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/tx_packets', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/tx_carrier_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/tx_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_dropped', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/tx_fifo_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_length_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/tx_dropped', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_fifo_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_missed_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/tx_window_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/collisions', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_frame_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_packets', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_compressed', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/tx_compressed', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/multicast', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/rx_over_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/tx_bytes', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/statistics/tx_heartbeat_errors', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wmaster0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/subsystem', '../../../../../../class/net') +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/device', '../../../0000:03:00.0') +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/phy80211', '../../ieee80211/phy0') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/ifindex', 0o644, b'4\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/features', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/iflink', 0o644, b'4\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/dormant', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/dev_id', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/type', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/operstate', 0o644, b'up\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/carrier', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/link_mode', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/tx_queue_len', 0o644, b'1000\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/flags', 0o644, b'0x1003\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/addr_len', 0o644, b'6\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/address', 0o644, b'00:19:d2:75:ae:ff\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/uevent', 0o644, b'''INTERFACE=wlan0 +IFINDEX=4 +''') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/mtu', 0o644, b'1500\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/broadcast', 0o644, b'ff:ff:ff:ff:ff:ff\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/tx_aborted_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_crc_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_bytes', 0o644, b'289996\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/tx_packets', 0o644, b'1029\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/tx_carrier_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/tx_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_dropped', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/tx_fifo_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_length_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/tx_dropped', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_fifo_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_missed_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/tx_window_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/collisions', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_frame_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_packets', 0o644, b'788\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_compressed', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/tx_compressed', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/multicast', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/rx_over_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/tx_bytes', 0o644, b'530013\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/statistics/tx_heartbeat_errors', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless/beacon', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless/link', 0o644, b'77\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless/nwid', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless/retries', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless/fragment', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless/misc', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless/crypt', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless/noise', 0o644, b'178\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless/level', 0o644, b'199\n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlan0/wireless/status', 0o644, b'0x0\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds', 0o755) +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:TX', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:TX/subsystem', '../../../../../../class/leds') +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:TX/device', '../../../0000:03:00.0') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:TX/trigger', 0o644, b'none AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx [phy0tx] phy0assoc phy0radio \n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:TX/brightness', 0o644, b'0\n\x00') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:TX/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:TX/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:TX/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:assoc', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:assoc/subsystem', '../../../../../../class/leds') +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:assoc/device', '../../../0000:03:00.0') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:assoc/trigger', 0o644, b'none AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx [phy0assoc] phy0radio \n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:assoc/brightness', 0o644, b'255\n\x00') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:assoc/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:assoc/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:assoc/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:radio', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:radio/subsystem', '../../../../../../class/leds') +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:radio/device', '../../../0000:03:00.0') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:radio/trigger', 0o644, b'none AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx phy0assoc [phy0radio] \n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:radio/brightness', 0o644, b'255\n\x00') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:radio/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:radio/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:radio/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:RX', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:RX/subsystem', '../../../../../../class/leds') +l('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:RX/device', '../../../0000:03:00.0') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:RX/trigger', 0o644, b'none AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 [phy0rx] phy0tx phy0assoc phy0radio \n') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:RX/brightness', 0o644, b'0\n\x00') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:RX/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:RX/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/iwl-phy0:RX/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie00', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie00/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie00/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.1/0000:00:1c.1:pcie00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:00.0', 0o755) +l('sys/devices/pci0000:00/0000:00:00.0/subsystem', '../../../bus/pci') +f('sys/devices/pci0000:00/0000:00:00.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:00.0/enable', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:00.0/modalias', 0o644, b'pci:v00008086d000027A0sv000017AAsd00002015bc06sc00i00\n') +f('sys/devices/pci0000:00/0000:00:00.0/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:00.0/config', 0o644, b"\x86\x80\xa0'\x06\x01\x90 \x03\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\x15 \x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x90\xd1\xfe\x01@\xd1\xfe\x05\x00\x00\xf0\x01\x80\xd1\xfe\x00\x00\x02\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x11\x11\x000\x11\x11\x00\xff\x03\x00\x00\x80\x1a9\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\t\x00\tQJ\x00J\xb0\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x05\x00\x10\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:00.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:00.0/subsystem_device', 0o644, b'0x2015\n') +f('sys/devices/pci0000:00/0000:00:00.0/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:00.0/irq', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:00.0/device', 0o644, b'0x27a0\n') +f('sys/devices/pci0000:00/0000:00:00.0/class', 0o644, b'0x060000\n') +f('sys/devices/pci0000:00/0000:00:00.0/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:00.0/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:00.0/uevent', 0o644, b'''PCI_CLASS=60000 +PCI_ID=8086:27A0 +PCI_SUBSYS_ID=17AA:2015 +PCI_SLOT_NAME=0000:00:00.0 +MODALIAS=pci:v00008086d000027A0sv000017AAsd00002015bc06sc00i00 +''') +f('sys/devices/pci0000:00/0000:00:00.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:00.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:00.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.3', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.3/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:0f') +l('sys/devices/pci0000:00/0000:00:1c.3/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1c.3/driver', '../../../bus/pci/drivers/pcieport-driver') +f('sys/devices/pci0000:00/0000:00:1c.3/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1c.3/enable', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1c.3/modalias', 0o644, b'pci:v00008086d000027D6sv00000000sd00000000bc06sc04i00\n') +f('sys/devices/pci0000:00/0000:00:1c.3/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000008000 0x0000000000009fff 0x0000000000000100 +0x00000000ea000000 0x00000000ebffffff 0x0000000000000200 +0x00000000e4200000 0x00000000e42fffff 0x0000000000001201 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1c.3/config', 0o644, b"\x86\x80\xd6'\x07\x05\x10\x00\x02\x00\x04\x06\x10\x00\x81\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x13\x00\x80\x90\x00\x00\x00\xea\xf0\xeb!\xe4!\xe4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x0b\x04\x04\x00\x10\x80A\x01\xc0\x0f\x00\x00\x00\x00\x10\x00\x11L\x11\x04\x00\x00\x01\x10\xe0\xa0(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x90\x01\x00\x0c0\xe0\xfe\x91A\x00\x00\x00\x00\x00\x00\r\xa0\x00\x00\xaa\x17\x11 \x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x11\x00\x00\x00\x00\x00\x00\x00\xc7\x00\x06\x07\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00\x02\x00\x01\x18\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xff\x00\x00\x80\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x01\x00\x00\x01\x02\x04\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x01\xc0\xd1\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07`\x00`\x00\x00\x00\x00`\x02\x00\x00\x0c\x00\x06\x00\x00\x00\x00\x00[`\xc9\xc0\x00p&u\x00\x10\x00\x00\xff\x0f\x00\x00\x16\x00\x00\x14\xb5\xbcJ\xbc\x0b*\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1c.3/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1c.3/subsystem_device', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:1c.3/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1c.3/irq', 0o644, b'507\n') +f('sys/devices/pci0000:00/0000:00:1c.3/device', 0o644, b'0x27d6\n') +f('sys/devices/pci0000:00/0000:00:1c.3/class', 0o644, b'0x060400\n') +f('sys/devices/pci0000:00/0000:00:1c.3/msi_bus', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.3/subsystem_vendor', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:1c.3/uevent', 0o644, b'''DRIVER=pcieport-driver +PCI_CLASS=60400 +PCI_ID=8086:27D6 +PCI_SUBSYS_ID=0000:0000 +PCI_SLOT_NAME=0000:00:1c.3 +MODALIAS=pci:v00008086d000027D6sv00000000sd00000000bc06sc04i00 +''') +f('sys/devices/pci0000:00/0000:00:1c.3/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1c.3/pci_bus', 0o755) +d('sys/devices/pci0000:00/0000:00:1c.3/pci_bus/0000:0c', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.3/pci_bus/0000:0c/subsystem', '../../../../../class/pci_bus') +l('sys/devices/pci0000:00/0000:00:1c.3/pci_bus/0000:0c/device', '../../../0000:00:1c.3') +f('sys/devices/pci0000:00/0000:00:1c.3/pci_bus/0000:0c/cpuaffinity', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1c.3/pci_bus/0000:0c/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.3/pci_bus/0000:0c/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.3/pci_bus/0000:0c/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.3/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.3/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie02', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie02/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie02/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie02/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie02/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie03', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie03/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie03/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie03/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie03/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie00', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie00/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie00/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.3/0000:00:1c.3:pcie00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.0/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:01') +l('sys/devices/pci0000:00/0000:00:1f.0/subsystem', '../../../bus/pci') +f('sys/devices/pci0000:00/0000:00:1f.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1f.0/enable', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.0/modalias', 0o644, b'pci:v00008086d000027B9sv000017AAsd00002009bc06sc01i00\n') +f('sys/devices/pci0000:00/0000:00:1f.0/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1f.0/config', 0o644, b'''\x86\x80\xb9\'\x07\x00\x10\x02\x02\x00\x01\x06\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\t \x00\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x10\x00\x00\x80\x00\x00\x00\x81\x11\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8b\x8b\x8b\x8b\x92\x00\x00\x00\x8b\x8b\x8b\x8b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00 +\x1f\x01\x16|\x00\xe1\x15\x0c\x00\x81\x16\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x06\x02\x00\x00\x00\x00\x00\x13\x1c +\x00\x00\x03\x00\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x00\x00\x12 +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00D\x12\x11\x00gE\x00\x00\xc0\xff\x00\x00\x01\x00\x00\x00\t\x00\x0c\x10\xb4\x02$\x17\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\xd1\xfe\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00''') +f('sys/devices/pci0000:00/0000:00:1f.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1f.0/subsystem_device', 0o644, b'0x2009\n') +f('sys/devices/pci0000:00/0000:00:1f.0/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1f.0/irq', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.0/device', 0o644, b'0x27b9\n') +f('sys/devices/pci0000:00/0000:00:1f.0/class', 0o644, b'0x060100\n') +f('sys/devices/pci0000:00/0000:00:1f.0/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.0/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1f.0/uevent', 0o644, b'''PCI_CLASS=60100 +PCI_ID=8086:27B9 +PCI_SUBSYS_ID=17AA:2009 +PCI_SLOT_NAME=0000:00:1f.0 +MODALIAS=pci:v00008086d000027B9sv000017AAsd00002009bc06sc01i00 +''') +f('sys/devices/pci0000:00/0000:00:1f.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.0/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:0b') +l('sys/devices/pci0000:00/0000:00:1c.0/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1c.0/driver', '../../../bus/pci/drivers/pcieport-driver') +f('sys/devices/pci0000:00/0000:00:1c.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1c.0/enable', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1c.0/modalias', 0o644, b'pci:v00008086d000027D0sv00000000sd00000000bc06sc04i00\n') +f('sys/devices/pci0000:00/0000:00:1c.0/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000003000 0x0000000000003fff 0x0000000000000100 +0x00000000ee000000 0x00000000ee0fffff 0x0000000000000200 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1c.0/config', 0o644, b"\x86\x80\xd0'\x07\x05\x10\x00\x02\x00\x04\x06\x10\x00\x81\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x02\x0000\x00\x00\x00\xee\x00\xee\xf1\xff\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x0b\x01\x04\x00\x10\x80A\x01\xc0\x0f\x00\x00\x00\x00\x11\x00\x11,\x11\x01B\x00\x110\xe0\xa0\x10\x00(\x00@\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x90\x01\x00\x0c0\xe0\xfeyA\x00\x00\x00\x00\x00\x00\r\xa0\x00\x00\xaa\x17\x11 \x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x11\xc0\x00\x00\x00\x00\x00\x0f\xc7\x00\x06\x07\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00\x02\x00\x01\x18\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x80\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x11\x00\x06\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x01\x00\x00\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x01\xc0\xd1\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07`\x00`\x00\x00\x00\x00`\x02\x00\x00\x0c\x00\x06\x00\x00\x00\x00\x08[`\xc9\xc0\x00p&u:\x188\x009\x08\x9e\x0e\x16\x00\x00\x14\xb5\xbcJ\xbc\x0b*\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xec\t\xec\x00\xfc\t\xee\x00c\x00W\x00i\x00J\x00k\x00L\x00\x01\x00\x05\x00\x10\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x02\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1c.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1c.0/subsystem_device', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:1c.0/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1c.0/irq', 0o644, b'510\n') +f('sys/devices/pci0000:00/0000:00:1c.0/device', 0o644, b'0x27d0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/class', 0o644, b'0x060400\n') +f('sys/devices/pci0000:00/0000:00:1c.0/msi_bus', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.0/subsystem_vendor', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:1c.0/uevent', 0o644, b'''DRIVER=pcieport-driver +PCI_CLASS=60400 +PCI_ID=8086:27D0 +PCI_SUBSYS_ID=0000:0000 +PCI_SLOT_NAME=0000:00:1c.0 +MODALIAS=pci:v00008086d000027D0sv00000000sd00000000bc06sc04i00 +''') +f('sys/devices/pci0000:00/0000:00:1c.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie03', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie03/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie03/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie03/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie03/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.0/pci_bus', 0o755) +d('sys/devices/pci0000:00/0000:00:1c.0/pci_bus/0000:02', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.0/pci_bus/0000:02/subsystem', '../../../../../class/pci_bus') +l('sys/devices/pci0000:00/0000:00:1c.0/pci_bus/0000:02/device', '../../../0000:00:1c.0') +f('sys/devices/pci0000:00/0000:00:1c.0/pci_bus/0000:02/cpuaffinity', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1c.0/pci_bus/0000:02/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.0/pci_bus/0000:02/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.0/pci_bus/0000:02/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.0/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/subsystem', '../../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/driver', '../../../../bus/pci/drivers/e1000e') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/modalias', 0o644, b'pci:v00008086d0000109Asv000017AAsd00002001bc02sc00i00\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/resource', 0o644, b'''0x00000000ee000000 0x00000000ee01ffff 0x0000000000020200 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000003000 0x000000000000301f 0x0000000000020101 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/config', 0o644, b'\x86\x80\x9a\x10\x07\x05\x10\x00\x00\x00\x00\x02\x10\x00\x00\x00\x00\x00\x00\xee\x00\x00\x00\x00\x010\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\x01 \x00\x00\x00\x00\xc8\x00\x00\x00\x00\x00\x00\x00\x0b\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xd0"\xc8\x00 \x00\x0f\x05\xe0\x81\x00\x0c\x10\xe0\xfe\x00\x00\x00\x00\xc9A\x00\x00\x10\x00\x01\x00\xc1\x0c\x00\x00\x10(\x1a\x00\x11\x1c\x07\x00@\x01\x11\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x14\x00\x00\x10\x00\x00\x00\x00\x00\x11 \x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x01\x00\x00\x04\x0f\x03\x00\x00\x00\x01\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x01\x00\xc7\x8d\xe2\xff\xffA\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/resource2', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/subsystem_device', 0o644, b'0x2001\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/irq', 0o644, b'505\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/device', 0o644, b'0x109a\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/class', 0o644, b'0x020000\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/resource0', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/uevent', 0o644, b'''DRIVER=e1000e +PCI_CLASS=20000 +PCI_ID=8086:109A +PCI_SUBSYS_ID=17AA:2001 +PCI_SLOT_NAME=0000:02:00.0 +MODALIAS=pci:v00008086d0000109Asv000017AAsd00002001bc02sc00i00 +''') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net', 0o755) +d('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/subsystem', '../../../../../../class/net') +l('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/device', '../../../0000:02:00.0') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/ifindex', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/features', 0o644, b'0x111ba9\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/iflink', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/dormant', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/dev_id', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/type', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/operstate', 0o644, b'down\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/carrier', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/link_mode', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/tx_queue_len', 0o644, b'1000\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/flags', 0o644, b'0x1003\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/addr_len', 0o644, b'6\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/address', 0o644, b'00:16:41:e2:8d:ff\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/uevent', 0o644, b'''INTERFACE=eth0 +IFINDEX=2 +''') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/mtu', 0o644, b'1500\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/broadcast', 0o644, b'ff:ff:ff:ff:ff:ff\n') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/tx_aborted_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_crc_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_bytes', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/tx_packets', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/tx_carrier_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/tx_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_dropped', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/tx_fifo_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_length_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/tx_dropped', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_fifo_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_missed_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/tx_window_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/collisions', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_frame_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_packets', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_compressed', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/tx_compressed', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/multicast', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/rx_over_errors', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/tx_bytes', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/statistics/tx_heartbeat_errors', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/eth0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie00', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie00/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie00/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie02', 0o755) +l('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie02/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie02/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie02/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1c.0/0000:00:1c.0:pcie02/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.3', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.3/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:18') +l('sys/devices/pci0000:00/0000:00:1f.3/subsystem', '../../../bus/pci') +f('sys/devices/pci0000:00/0000:00:1f.3/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1f.3/enable', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.3/modalias', 0o644, b'pci:v00008086d000027DAsv000017AAsd0000200Fbc0Csc05i00\n') +f('sys/devices/pci0000:00/0000:00:1f.3/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x00000000000018e0 0x00000000000018ff 0x0000000000020101 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1f.3/config', 0o644, b"\x86\x80\xda'\x01\x01\x80\x02\x02\x00\x05\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe1\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\x0f \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1f.3/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1f.3/subsystem_device', 0o644, b'0x200f\n') +f('sys/devices/pci0000:00/0000:00:1f.3/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1f.3/irq', 0o644, b'11\n') +f('sys/devices/pci0000:00/0000:00:1f.3/device', 0o644, b'0x27da\n') +f('sys/devices/pci0000:00/0000:00:1f.3/class', 0o644, b'0x0c0500\n') +f('sys/devices/pci0000:00/0000:00:1f.3/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.3/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1f.3/uevent', 0o644, b'''PCI_CLASS=C0500 +PCI_ID=8086:27DA +PCI_SUBSYS_ID=17AA:200F +PCI_SLOT_NAME=0000:00:1f.3 +MODALIAS=pci:v00008086d000027DAsv000017AAsd0000200Fbc0Csc05i00 +''') +f('sys/devices/pci0000:00/0000:00:1f.3/resource4', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.3/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.3/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.3/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.0/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:19') +l('sys/devices/pci0000:00/0000:00:1d.0/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1d.0/driver', '../../../bus/pci/drivers/uhci_hcd') +f('sys/devices/pci0000:00/0000:00:1d.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1d.0/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.0/modalias', 0o644, b'pci:v00008086d000027C8sv000017AAsd0000200Abc0Csc03i00\n') +f('sys/devices/pci0000:00/0000:00:1d.0/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000001800 0x000000000000181f 0x0000000000020101 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1d.0/config', 0o644, b"\x86\x80\xc8'\x05\x00\x80\x02\x02\x00\x03\x0c\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\n \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1d.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1d.0/subsystem_device', 0o644, b'0x200a\n') +f('sys/devices/pci0000:00/0000:00:1d.0/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1d.0/irq', 0o644, b'16\n') +f('sys/devices/pci0000:00/0000:00:1d.0/pools', 0o644, b'''poolinfo - 0.1 +uhci_qh 11 32 128 1 +uhci_td 1 64 64 1 +buffer-2048 0 0 2048 0 +buffer-512 0 0 512 0 +buffer-128 0 0 128 0 +buffer-32 1 128 32 1 +''') +f('sys/devices/pci0000:00/0000:00:1d.0/device', 0o644, b'0x27c8\n') +f('sys/devices/pci0000:00/0000:00:1d.0/class', 0o644, b'0x0c0300\n') +f('sys/devices/pci0000:00/0000:00:1d.0/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.0/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1d.0/uevent', 0o644, b'''DRIVER=uhci_hcd +PCI_CLASS=C0300 +PCI_ID=8086:27C8 +PCI_SUBSYS_ID=17AA:200A +PCI_SLOT_NAME=0000:00:1d.0 +MODALIAS=pci:v00008086d000027C8sv000017AAsd0000200Abc0Csc03i00 +''') +f('sys/devices/pci0000:00/0000:00:1d.0/resource4', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1d.0/usb1', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.0/usb1/subsystem', '../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.0/usb1/driver', '../../../../bus/usb/drivers/usb') +l('sys/devices/pci0000:00/0000:00:1d.0/usb1/ep_00', 'usb_endpoint/usbdev1.1_ep00') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/version', 0o644, b' 1.10\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/authorized_default', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/maxchild', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/bDeviceClass', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/bcdDevice', 0o644, b'0206\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/devnum', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/bDeviceProtocol', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/idProduct', 0o644, b'0001\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/product', 0o644, b'UHCI Host Controller\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/bDeviceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/configuration', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/dev', 0o644, b'189:0\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/urbnum', 0o644, b'16\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/authorized', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/descriptors', 0o644, b'\x12\x01\x10\x01\t\x00\x00@k\x1d\x01\x00\x06\x02\x03\x02\x01\x01\t\x02\x19\x00\x01\x01\x00\xe0\x00\t\x04\x00\x00\x01\t\x00\x00\x00\x07\x05\x81\x03\x02\x00\xff') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/bNumConfigurations', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/serial', 0o644, b'0000:00:1d.0\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/speed', 0o644, b'12\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/bMaxPacketSize0', 0o644, b'64\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/bmAttributes', 0o644, b'e0\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/busnum', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/quirks', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/bConfigurationValue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/uevent', 0o644, b'''MAJOR=189 +MINOR=0 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=1d6b/1/206 +TYPE=9/0/0 +BUSNUM=001 +DEVNUM=001 +''') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/manufacturer', 0o644, b'Linux 2.6.27-rc7-00106-g6ef190c-dirty uhci_hcd\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/idVendor', 0o644, b'1d6b\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/bNumInterfaces', 0o644, b' 1\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/bMaxPower', 0o644, b' 0mA\n') +d('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/subsystem', '../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/device', '../../../usb1') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/bEndpointAddress', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/type', 0o644, b'Control\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/dev', 0o644, b'252:1\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/direction', 0o644, b'both\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/bmAttributes', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/uevent', 0o644, b'''MAJOR=252 +MINOR=1 +''') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/usb_endpoint/usbdev1.1_ep00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/subsystem', '../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/ep_81', 'usb_endpoint/usbdev1.1_ep81') +l('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/driver', '../../../../../bus/usb/drivers/hub') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/modalias', 0o644, b'usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/bInterfaceNumber', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/bNumEndpoints', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/bInterfaceClass', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/uevent', 0o644, b'''DEVTYPE=usb_interface +DRIVER=hub +PRODUCT=1d6b/1/206 +TYPE=9/0/0 +INTERFACE=9/0/0 +MODALIAS=usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/subsystem', '../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/device', '../../../1-0:1.0') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/interval', 0o644, b'255ms\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/bEndpointAddress', 0o644, b'81\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/type', 0o644, b'Interrupt\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/dev', 0o644, b'252:0\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/wMaxPacketSize', 0o644, b'0002\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/bmAttributes', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/uevent', 0o644, b'''MAJOR=252 +MINOR=0 +''') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/bInterval', 0o644, b'ff\n') +d('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/usb_endpoint/usbdev1.1_ep81/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/1-0:1.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.0/usb1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/power/active_duration', 0o644, b'2532\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/power/wakeup', 0o644, b'enabled\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/power/connected_duration', 0o644, b'8372376\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/power/autosuspend', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.0/usb1/power/level', 0o644, b'auto\n') +d('sys/devices/pci0000:00/0000:00:1d.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.0/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1d.0/usb_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.0/usb_host/usb_host1', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.0/usb_host/usb_host1/subsystem', '../../../../../class/usb_host') +l('sys/devices/pci0000:00/0000:00:1d.0/usb_host/usb_host1/device', '../../../0000:00:1d.0') +f('sys/devices/pci0000:00/0000:00:1d.0/usb_host/usb_host1/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1d.0/usb_host/usb_host1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.0/usb_host/usb_host1/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:16') +l('sys/devices/pci0000:00/0000:00:1f.2/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1f.2/driver', '../../../bus/pci/drivers/ahci') +f('sys/devices/pci0000:00/0000:00:1f.2/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1f.2/resource3', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.2/modalias', 0o644, b'pci:v00008086d000027C5sv000017AAsd0000200Dbc01sc06i01\n') +f('sys/devices/pci0000:00/0000:00:1f.2/resource', 0o644, b'''0x00000000000018c8 0x00000000000018cf 0x0000000000020101 +0x00000000000018ac 0x00000000000018af 0x0000000000020101 +0x00000000000018c0 0x00000000000018c7 0x0000000000020101 +0x00000000000018a8 0x00000000000018ab 0x0000000000020101 +0x00000000000018b0 0x00000000000018bf 0x0000000000020101 +0x00000000ee404400 0x00000000ee4047ff 0x0000000000020200 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1f.2/config', 0o644, b"\x86\x80\xc5'\x07\x04\xb0\x02\x02\x01\x06\x01\x00\x00\x00\x00\xc9\x18\x00\x00\xad\x18\x00\x00\xc1\x18\x00\x00\xa9\x18\x00\x00\xb1\x18\x00\x00\x00D@\xee\x00\x00\x00\x00\xaa\x17\r \x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x0b\x02\x00\x00\x07\xa3\x00\x80\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05p\x01\x00\x0c0\xe0\xfe\x99A\x00\x00\x00\x00\x00\x00@\x00\x11\x10\x80\x01\x00J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1f.2/resource1', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/resource2', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1f.2/subsystem_device', 0o644, b'0x200d\n') +f('sys/devices/pci0000:00/0000:00:1f.2/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1f.2/irq', 0o644, b'506\n') +f('sys/devices/pci0000:00/0000:00:1f.2/device', 0o644, b'0x27c5\n') +f('sys/devices/pci0000:00/0000:00:1f.2/class', 0o644, b'0x010601\n') +f('sys/devices/pci0000:00/0000:00:1f.2/resource5', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/resource0', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1f.2/uevent', 0o644, b'''DRIVER=ahci +PCI_CLASS=10601 +PCI_ID=8086:27C5 +PCI_SUBSYS_ID=17AA:200D +PCI_SLOT_NAME=0000:00:1f.2 +MODALIAS=pci:v00008086d000027C5sv000017AAsd0000200Dbc01sc06i01 +''') +f('sys/devices/pci0000:00/0000:00:1f.2/resource4', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/subsystem', '../../../../bus/scsi') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/uevent', 0o644, b'DEVTYPE=scsi_host\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/subsystem', '../../../../../bus/scsi') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/uevent', 0o644, b'DEVTYPE=scsi_target\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/generic', 'scsi_generic/sg0') +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/subsystem', '../../../../../../bus/scsi') +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/driver', '../../../../../../bus/scsi/drivers/sd') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/iodone_cnt', 0o644, b'0x6877\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/device_blocked', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/modalias', 0o644, b'scsi:t-0x00\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_level', 0o644, b'6\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/queue_depth', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/rev', 0o644, b'4.06\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sw_activity', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/whitespace_test', 0o644, b'WHITE SPACE \n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/iocounterbits', 0o644, b'32\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/vendor', 0o644, b'ATA \n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/state', 0o644, b'running\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/queue_type', 0o644, b'none\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/iorequest_cnt', 0o644, b'0x6877\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/evt_media_change', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/model', 0o644, b'ST910021AS \n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/ioerr_cnt', 0o644, b'0x6\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/uevent', 0o644, b'''DEVTYPE=scsi_device +DRIVER=sd +MODALIAS=scsi:t-0x00 +''') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/timeout', 0o644, b'60\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/subsystem', '../../../../../../../../class/scsi_disk') +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/device', '../../../0:0:0:0') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/app_tag_own', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/FUA', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/cache_type', 0o644, b'write back\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/protection_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/manage_start_stop', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/allow_restart', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_generic', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_generic/sg0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_generic/sg0/subsystem', '../../../../../../../../class/scsi_generic') +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_generic/sg0/device', '../../../0:0:0:0') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_generic/sg0/dev', 0o644, b'21:0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_generic/sg0/uevent', 0o644, b'''MAJOR=21 +MINOR=0 +''') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_generic/sg0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_generic/sg0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/bsg', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0/subsystem', '../../../../../../../../class/bsg') +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0/device', '../../../0:0:0:0') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0/dev', 0o644, b'254:0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0/uevent', 0o644, b'''MAJOR=254 +MINOR=0 +''') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/subsystem', '../../../../../../../../class/block') +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/bdi', '../../../../../../../virtual/bdi/8:0') +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/device', '../../../0:0:0:0') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/capability', 0o644, b'12\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/ro', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/test:colon+plus', 0o644, b'colon\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/size', 0o644, b'195371568\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/dev', 0o644, b'8:0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/range', 0o644, b'16\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/removable', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/stat', 0o644, b' 12939 5801 590192 194190 13755 63323 617056 2678026 0 114408 2872209\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/uevent', 0o644, b'''MAJOR=8 +MINOR=0 +DEVTYPE=disk +DEVNAME=sda +''') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/test_empty_file', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/bsg', '../../../bsg/0:0:0:0') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/nr_requests', 0o644, b'128\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/nomerges', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/scheduler', 0o644, b'noop anticipatory deadline [cfq] \n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/hw_sector_size', 0o644, b'512\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/max_hw_sectors_kb', 0o644, b'32767\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/read_ahead_kb', 0o644, b'128\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/max_sectors_kb', 0o644, b'512\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/iosched', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/iosched/slice_async_rq', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/iosched/back_seek_max', 0o644, b'16384\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/iosched/slice_sync', 0o644, b'100\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/iosched/slice_async', 0o644, b'40\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/iosched/fifo_expire_sync', 0o644, b'125\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/iosched/slice_idle', 0o644, b'8\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/iosched/back_seek_penalty', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/iosched/fifo_expire_async', 0o644, b'250\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/queue/iosched/quantum', 0o644, b'4\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10/subsystem', '../../../../../../../../../class/block') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10/start', 0o644, b'190820133\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10/size', 0o644, b'4546332\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10/dev', 0o644, b'8:10\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10/stat', 0o644, b' 42 43 384 417 0 0 0 0 0 286 417\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10/uevent', 0o644, b'''MAJOR=8 +MINOR=10 +DEVTYPE=partition +''') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/subsystem', '../../../../../../../../../class/block') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/start', 0o644, b'143942463\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/size', 0o644, b'46877607\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/dev', 0o644, b'8:9\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/stat', 0o644, b' 70 322 896 800 3 0 40 240 0 945 1039\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/uevent', 0o644, b'''MAJOR=8 +MINOR=9 +DEVTYPE=partition +''') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/holders', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/holders/md0', '../../../../../../../../../virtual/block/md0') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7/subsystem', '../../../../../../../../../class/block') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7/start', 0o644, b'104872383\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7/size', 0o644, b'19534977\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7/dev', 0o644, b'8:7\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7/stat', 0o644, b' 35 263 298 419 0 0 0 0 0 298 419\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7/uevent', 0o644, b'''MAJOR=8 +MINOR=7 +DEVTYPE=partition +''') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1/subsystem', '../../../../../../../../../class/block') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1/start', 0o644, b'63\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1/size', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1/dev', 0o644, b'8:1\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1/stat', 0o644, b' 2 0 4 36 0 0 0 0 0 36 36\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1/uevent', 0o644, b'''MAJOR=8 +MINOR=1 +DEVTYPE=partition +DEVNAME=sda1 +''') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8/subsystem', '../../../../../../../../../class/block') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8/start', 0o644, b'124407423\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8/size', 0o644, b'19534977\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8/dev', 0o644, b'8:8\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8/stat', 0o644, b' 34 264 298 498 0 0 0 0 0 368 498\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8/uevent', 0o644, b'''MAJOR=8 +MINOR=8 +DEVTYPE=partition +''') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5/subsystem', '../../../../../../../../../class/block') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5/start', 0o644, b'126\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5/size', 0o644, b'62926479\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5/dev', 0o644, b'8:5\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5/stat', 0o644, b' 11087 4819 566626 169007 2951 4548 59992 129572 0 65249 298573\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5/uevent', 0o644, b'''MAJOR=8 +MINOR=5 +DEVTYPE=partition +DEVNAME=sda5 +''') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6/subsystem', '../../../../../../../../../class/block') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6/start', 0o644, b'62926668\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6/size', 0o644, b'41945652\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6/dev', 0o644, b'8:6\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6/stat', 0o644, b' 1648 67 21334 22824 10801 58775 557024 2548214 0 51231 2571037\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6/uevent', 0o644, b'''MAJOR=8 +MINOR=6 +DEVTYPE=partition +''') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_device', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0/subsystem', '../../../../../../../../class/scsi_device') +l('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0/device', '../../../0:0:0:0') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/subsystem', '../../../../../../class/scsi_host') +l('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/device', '../../../host0') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/unique_id', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/can_queue', 0o644, b'31\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/unchecked_isa_dma', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/active_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/sg_tablesize', 0o644, b'168\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/prot_guard_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/link_power_management_policy', 0o644, b'medium_power\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/host_busy', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/proc_name', 0o644, b'ahci\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/state', 0o644, b'running\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/cmd_per_lun', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/em_message', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/em_message_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/supported_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/uevent', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/prot_capabilities', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host1', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host1/subsystem', '../../../../bus/scsi') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/uevent', 0o644, b'DEVTYPE=scsi_host\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host1/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/subsystem', '../../../../../../class/scsi_host') +l('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/device', '../../../host1') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/unique_id', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/can_queue', 0o644, b'31\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/unchecked_isa_dma', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/active_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/sg_tablesize', 0o644, b'168\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/prot_guard_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/link_power_management_policy', 0o644, b'max_performance\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/host_busy', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/proc_name', 0o644, b'ahci\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/state', 0o644, b'running\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/cmd_per_lun', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/em_message', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/em_message_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/supported_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/uevent', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/prot_capabilities', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host2', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host2/subsystem', '../../../../bus/scsi') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/uevent', 0o644, b'DEVTYPE=scsi_host\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host2/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/subsystem', '../../../../../../class/scsi_host') +l('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/device', '../../../host2') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/unique_id', 0o644, b'3\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/can_queue', 0o644, b'31\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/unchecked_isa_dma', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/active_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/sg_tablesize', 0o644, b'168\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/prot_guard_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/link_power_management_policy', 0o644, b'max_performance\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/host_busy', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/proc_name', 0o644, b'ahci\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/state', 0o644, b'running\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/cmd_per_lun', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/em_message', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/em_message_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/supported_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/uevent', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/prot_capabilities', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host3', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host3/subsystem', '../../../../bus/scsi') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/uevent', 0o644, b'DEVTYPE=scsi_host\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host3/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host3/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/subsystem', '../../../../../../class/scsi_host') +l('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/device', '../../../host3') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/unique_id', 0o644, b'4\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/can_queue', 0o644, b'31\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/unchecked_isa_dma', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/active_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/sg_tablesize', 0o644, b'168\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/prot_guard_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/link_power_management_policy', 0o644, b'max_performance\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/host_busy', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/proc_name', 0o644, b'ahci\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/state', 0o644, b'running\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/cmd_per_lun', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/em_message', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/em_message_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/supported_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/uevent', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/prot_capabilities', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:1d') +l('sys/devices/pci0000:00/0000:00:1d.2/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1d.2/driver', '../../../bus/pci/drivers/uhci_hcd') +f('sys/devices/pci0000:00/0000:00:1d.2/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1d.2/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/modalias', 0o644, b'pci:v00008086d000027CAsv000017AAsd0000200Abc0Csc03i00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000001840 0x000000000000185f 0x0000000000020101 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/config', 0o644, b"\x86\x80\xca'\x05\x00\x80\x02\x02\x00\x03\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00A\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\n \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1d.2/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1d.2/subsystem_device', 0o644, b'0x200a\n') +f('sys/devices/pci0000:00/0000:00:1d.2/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1d.2/irq', 0o644, b'18\n') +f('sys/devices/pci0000:00/0000:00:1d.2/pools', 0o644, b'''poolinfo - 0.1 +uhci_qh 13 32 128 1 +uhci_td 4 64 64 1 +buffer-2048 0 0 2048 0 +buffer-512 0 0 512 0 +buffer-128 3 32 128 1 +buffer-32 2 128 32 1 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/device', 0o644, b'0x27ca\n') +f('sys/devices/pci0000:00/0000:00:1d.2/class', 0o644, b'0x0c0300\n') +f('sys/devices/pci0000:00/0000:00:1d.2/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.2/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1d.2/uevent', 0o644, b'''DRIVER=uhci_hcd +PCI_CLASS=C0300 +PCI_ID=8086:27CA +PCI_SUBSYS_ID=17AA:200A +PCI_SLOT_NAME=0000:00:1d.2 +MODALIAS=pci:v00008086d000027CAsv000017AAsd0000200Abc0Csc03i00 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/resource4', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.2/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1d.2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.2/usb_host/usb_host3', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb_host/usb_host3/subsystem', '../../../../../class/usb_host') +l('sys/devices/pci0000:00/0000:00:1d.2/usb_host/usb_host3/device', '../../../0000:00:1d.2') +f('sys/devices/pci0000:00/0000:00:1d.2/usb_host/usb_host3/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1d.2/usb_host/usb_host3/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb_host/usb_host3/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/subsystem', '../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/driver', '../../../../bus/usb/drivers/usb') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/ep_00', 'usb_endpoint/usbdev3.1_ep00') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/version', 0o644, b' 1.10\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/authorized_default', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/maxchild', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/bDeviceClass', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/bcdDevice', 0o644, b'0206\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/devnum', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/bDeviceProtocol', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/idProduct', 0o644, b'0001\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/product', 0o644, b'UHCI Host Controller\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/bDeviceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/configuration', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/dev', 0o644, b'189:256\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/urbnum', 0o644, b'68\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/authorized', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/descriptors', 0o644, b'\x12\x01\x10\x01\t\x00\x00@k\x1d\x01\x00\x06\x02\x03\x02\x01\x01\t\x02\x19\x00\x01\x01\x00\xe0\x00\t\x04\x00\x00\x01\t\x00\x00\x00\x07\x05\x81\x03\x02\x00\xff') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/bNumConfigurations', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/serial', 0o644, b'0000:00:1d.2\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/speed', 0o644, b'12\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/bMaxPacketSize0', 0o644, b'64\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/bmAttributes', 0o644, b'e0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/busnum', 0o644, b'3\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/quirks', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/bConfigurationValue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/uevent', 0o644, b'''MAJOR=189 +MINOR=256 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=1d6b/1/206 +TYPE=9/0/0 +BUSNUM=003 +DEVNUM=001 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/manufacturer', 0o644, b'Linux 2.6.27-rc7-00106-g6ef190c-dirty uhci_hcd\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/idVendor', 0o644, b'1d6b\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/bNumInterfaces', 0o644, b' 1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/bMaxPower', 0o644, b' 0mA\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/subsystem', '../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/device', '../../../usb3') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/bEndpointAddress', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/type', 0o644, b'Control\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/dev', 0o644, b'252:5\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/direction', 0o644, b'both\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/bmAttributes', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/uevent', 0o644, b'''MAJOR=252 +MINOR=5 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/usb_endpoint/usbdev3.1_ep00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/subsystem', '../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/ep_81', 'usb_endpoint/usbdev3.1_ep81') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/driver', '../../../../../bus/usb/drivers/hub') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/modalias', 0o644, b'usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/bInterfaceNumber', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/bNumEndpoints', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/bInterfaceClass', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/uevent', 0o644, b'''DEVTYPE=usb_interface +DRIVER=hub +PRODUCT=1d6b/1/206 +TYPE=9/0/0 +INTERFACE=9/0/0 +MODALIAS=usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/subsystem', '../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/device', '../../../3-0:1.0') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/interval', 0o644, b'255ms\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/bEndpointAddress', 0o644, b'81\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/type', 0o644, b'Interrupt\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/dev', 0o644, b'252:4\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/wMaxPacketSize', 0o644, b'0002\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/bmAttributes', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/uevent', 0o644, b'''MAJOR=252 +MINOR=4 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/bInterval', 0o644, b'ff\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/usb_endpoint/usbdev3.1_ep81/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-0:1.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/power/active_duration', 0o644, b'603809\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/power/wakeup', 0o644, b'enabled\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/power/connected_duration', 0o644, b'8372166\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/power/autosuspend', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/power/level', 0o644, b'auto\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/subsystem', '../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/driver', '../../../../../bus/usb/drivers/usb') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/ep_00', 'usb_endpoint/usbdev3.4_ep00') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/version', 0o644, b' 2.00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/maxchild', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/bDeviceClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/bcdDevice', 0o644, b'2000\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/devnum', 0o644, b'4\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/bDeviceProtocol', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/idProduct', 0o644, b'c03e\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/product', 0o644, b'USB-PS/2 Optical Mouse\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/bDeviceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/configuration', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/dev', 0o644, b'189:259\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/urbnum', 0o644, b'12\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/authorized', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/descriptors', 0o644, b'\x12\x01\x00\x02\x00\x00\x00\x08m\x04>\xc0\x00 \x01\x02\x00\x01\t\x02"\x00\x01\x01\x00\xa01\t\x04\x00\x00\x01\x03\x01\x02\x00\t!\x10\x01\x00\x01"2\x00\x07\x05\x81\x03\x04\x00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/bNumConfigurations', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/speed', 0o644, b'1.5\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/bMaxPacketSize0', 0o644, b'8\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/bmAttributes', 0o644, b'a0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/busnum', 0o644, b'3\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/quirks', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/bConfigurationValue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/uevent', 0o644, b'''MAJOR=189 +MINOR=259 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=46d/c03e/2000 +TYPE=0/0/0 +BUSNUM=003 +DEVNUM=004 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/manufacturer', 0o644, b'Logitech\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/idVendor', 0o644, b'046d\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/bNumInterfaces', 0o644, b' 1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/bMaxPower', 0o644, b' 98mA\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/subsystem', '../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/device', '../../../3-1') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/bEndpointAddress', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/type', 0o644, b'Control\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/dev', 0o644, b'252:26\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/direction', 0o644, b'both\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/wMaxPacketSize', 0o644, b'0008\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/bmAttributes', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/uevent', 0o644, b'''MAJOR=252 +MINOR=26 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/usb_endpoint/usbdev3.4_ep00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/power/active_duration', 0o644, b'51384\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/power/wakeup', 0o644, b'enabled\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/power/connected_duration', 0o644, b'51383\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/power/autosuspend', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/power/persist', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/power/level', 0o644, b'on\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/subsystem', '../../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/ep_81', 'usb_endpoint/usbdev3.4_ep81') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/driver', '../../../../../../bus/usb/drivers/usbhid') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/modalias', 0o644, b'usb:v046DpC03Ed2000dc00dsc00dp00ic03isc01ip02\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/bInterfaceNumber', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/bNumEndpoints', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/bInterfaceSubClass', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/bInterfaceClass', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/uevent', 0o644, b'''DEVTYPE=usb_interface +DRIVER=usbhid +PRODUCT=46d/c03e/2000 +TYPE=0/0/0 +INTERFACE=3/1/2 +MODALIAS=usb:v046DpC03Ed2000dc00dsc00dp00ic03isc01ip02 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/bInterfaceProtocol', 0o644, b'02\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/subsystem', '../../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/device', '../../../3-1:1.0') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/interval', 0o644, b'10ms\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/bEndpointAddress', 0o644, b'81\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/type', 0o644, b'Interrupt\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/dev', 0o644, b'252:25\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/wMaxPacketSize', 0o644, b'0004\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/bmAttributes', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/uevent', 0o644, b'''MAJOR=252 +MINOR=25 +''') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/bInterval', 0o644, b'0a\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/usb_endpoint/usbdev3.4_ep81/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/subsystem', '../../../../../../../../class/input') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/device', '../../../3-1:1.0') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/uniq', 0o644, b'\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/phys', 0o644, b'usb-0000:00:1d.2-1/input0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/modalias', 0o644, b'input:b0003v046DpC03Ee0110-e0,1,2,4,k110,111,112,r0,1,8,am4,lsfw\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/name', 0o644, b'Logitech USB-PS/2 Optical Mouse\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/uevent', 0o644, b'''PRODUCT=3/46d/c03e/110 +NAME="Logitech USB-PS/2 Optical Mouse" +PHYS="usb-0000:00:1d.2-1/input0" +UNIQ="" +EV==17 +KEY==70000 0 0 0 0 +REL==103 +MSC==10 +MODALIAS=input:b0003v046DpC03Ee0110-e0,1,2,4,k110,111,112,r0,1,8,am4,lsfw +''') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/mouse1', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/mouse1/subsystem', '../../../../../../../../../class/input') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/mouse1/device', '../../input8') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/mouse1/dev', 0o644, b'13:33\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/mouse1/uevent', 0o644, b'''MAJOR=13 +MINOR=33 +''') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/mouse1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/mouse1/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/id', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/id/version', 0o644, b'0110\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/id/product', 0o644, b'c03e\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/id/vendor', 0o644, b'046d\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/id/bustype', 0o644, b'0003\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/event7', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/event7/subsystem', '../../../../../../../../../class/input') +l('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/event7/device', '../../input8') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/event7/dev', 0o644, b'13:71\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/event7/uevent', 0o644, b'''MAJOR=13 +MINOR=71 +''') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/event7/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/event7/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/capabilities', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/capabilities/msc', 0o644, b'10\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/capabilities/abs', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/capabilities/snd', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/capabilities/ff', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/capabilities/key', 0o644, b'70000 0 0 0 0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/capabilities/rel', 0o644, b'103\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/capabilities/sw', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/capabilities/ev', 0o644, b'17\n') +f('sys/devices/pci0000:00/0000:00:1d.2/usb3/3-1/3-1:1.0/input/input8/capabilities/led', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:01.0', 0o755) +l('sys/devices/pci0000:00/0000:00:01.0/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:06') +l('sys/devices/pci0000:00/0000:00:01.0/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:01.0/driver', '../../../bus/pci/drivers/pcieport-driver') +f('sys/devices/pci0000:00/0000:00:01.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:01.0/enable', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:01.0/modalias', 0o644, b'pci:v00008086d000027A1sv00000000sd00000000bc06sc04i00\n') +f('sys/devices/pci0000:00/0000:00:01.0/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000002000 0x0000000000002fff 0x0000000000000100 +0x00000000ee100000 0x00000000ee1fffff 0x0000000000000200 +0x00000000d0000000 0x00000000dfffffff 0x0000000000001201 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:01.0/config', 0o644, b'\x86\x80\xa1\'\x07\x05\x10\x00\x03\x00\x04\x06\x10\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x00 \x00\x00\x10\xee\x10\xee\x01\xd0\xf1\xdf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x88\x00\x00\x00\x00\x00\x00\x00\x0b\x01\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x01\x90\x02\xc8\x00\x00\x00\x00\r\x80\x00\x00\xaa\x17\x14 \x05\xa0\x01\x00\x0c0\xe0\xfeqA\x00\x00\x00\x00\x00\x00\x10\x00A\x01\x00\x00\x00\x00\x00\x00\x01\x00\x01M\x01\x02\x03\x00\x01\x11\x80%\x08\x00\xc0\x01H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x0f\x00\x00\x00\x00\x86\x0f\x05\x00\x00\x00\x00\x80\x02\x00\x01\x14\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x80\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x01\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x01\x00\x00\x01\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x90\xd1\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x06\x00\x01\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00n\x7f \x08\xf4\x0c\x00\x00\xb04 \x00\x00\x00\x00\x003\x0f\x00\x00\xff\xff\x03\x00\xd0\x0f\xf1\x05\xd1\x0f\xd1\x0f\x08\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\r/B\x00\x0c\x00\x00\x14\xb5\xbcJ\xbc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x0b\xe0\x00Q\x0b\xfe\x00 \x00\x08\x00\x85\x03\xf1\x00\x87\x03\xf3\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x04\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x14\x08\x88\x00\x00\x00\x00\x00\x00\x00\x00"wD\xb23\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x06`\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x06b\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\n\x06`\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\r\x06b\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x06`\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x06b\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x003\x06`\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x004\x06b\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x06`\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x002\x06b\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x004\x06`\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x002\x06b\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00;\x06`\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x003\x06b\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x009\x06`\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00:\x06b\x00 \x00\x00`\x02\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x007') +f('sys/devices/pci0000:00/0000:00:01.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:01.0/subsystem_device', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:01.0/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:01.0/irq', 0o644, b'511\n') +f('sys/devices/pci0000:00/0000:00:01.0/device', 0o644, b'0x27a1\n') +f('sys/devices/pci0000:00/0000:00:01.0/class', 0o644, b'0x060400\n') +f('sys/devices/pci0000:00/0000:00:01.0/msi_bus', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:01.0/subsystem_vendor', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:01.0/uevent', 0o644, b'''DRIVER=pcieport-driver +PCI_CLASS=60400 +PCI_ID=8086:27A1 +PCI_SUBSYS_ID=0000:0000 +PCI_SLOT_NAME=0000:00:01.0 +MODALIAS=pci:v00008086d000027A1sv00000000sd00000000bc06sc04i00 +''') +f('sys/devices/pci0000:00/0000:00:01.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:01.0/pci_bus', 0o755) +d('sys/devices/pci0000:00/0000:00:01.0/pci_bus/0000:01', 0o755) +l('sys/devices/pci0000:00/0000:00:01.0/pci_bus/0000:01/subsystem', '../../../../../class/pci_bus') +l('sys/devices/pci0000:00/0000:00:01.0/pci_bus/0000:01/device', '../../../0000:00:01.0') +f('sys/devices/pci0000:00/0000:00:01.0/pci_bus/0000:01/cpuaffinity', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:01.0/pci_bus/0000:01/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:01.0/pci_bus/0000:01/power', 0o755) +f('sys/devices/pci0000:00/0000:00:01.0/pci_bus/0000:01/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:01.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:01.0/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie03', 0o755) +l('sys/devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie03/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie03/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie03/power', 0o755) +f('sys/devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie03/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0', 0o755) +l('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/firmware_node', '../../../LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07') +l('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/subsystem', '../../../../bus/pci') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/enable', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/modalias', 0o644, b'pci:v00001002d000071D4sv000017AAsd000020A4bc03sc00i00\n') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/resource', 0o644, b'''0x00000000d0000000 0x00000000dfffffff 0x0000000000021208 +0x0000000000002000 0x00000000000020ff 0x0000000000020101 +0x00000000ee100000 0x00000000ee10ffff 0x0000000000020200 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x00000000ee120000 0x00000000ee13ffff 0x0000000000027202 +''') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/config', 0o644, b'\x02\x10\xd4q\x07\x01\x10\x00\x00\x00\x00\x03\x10\x00\x00\x00\x08\x00\x00\xd0\x01 \x00\x00\x00\x00\x10\xee\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\xa4 \x00\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00\x0b\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\xa4 \x01X\x02\x06\x00\x00\x00\x00\x10\x80\x11\x00\xa0\x0f,\x01\x10\x08\x00\x00\x01\r\x00\x00C\x00\x01\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11 \x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00@\x03\x00\x00\x00$\x8f\x0b\x00\xff\xff\x07e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/resource1', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/resource2', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/subsystem_device', 0o644, b'0x20a4\n') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/vendor', 0o644, b'0x1002\n') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/irq', 0o644, b'11\n') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/device', 0o644, b'0x71d4\n') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/class', 0o644, b'0x030000\n') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/rom', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/resource0', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/uevent', 0o644, b'''PCI_CLASS=30000 +PCI_ID=1002:71D4 +PCI_SUBSYS_ID=17AA:20A4 +PCI_SLOT_NAME=0000:01:00.0 +MODALIAS=pci:v00001002d000071D4sv000017AAsd000020A4bc03sc00i00 +''') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/resource0_wc', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie00', 0o755) +l('sys/devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie00/subsystem', '../../../../bus/pci_express') +f('sys/devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie00/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:01.0/0000:00:01.0:pcie00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:13') +l('sys/devices/pci0000:00/0000:00:1f.1/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1f.1/driver', '../../../bus/pci/drivers/ata_piix') +f('sys/devices/pci0000:00/0000:00:1f.1/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1f.1/resource3', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.1/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.1/modalias', 0o644, b'pci:v00008086d000027DFsv000017AAsd0000200Cbc01sc01i8a\n') +f('sys/devices/pci0000:00/0000:00:1f.1/resource', 0o644, b'''0x00000000000001f0 0x00000000000001f7 0x0000000000000110 +0x00000000000003f6 0x00000000000003f6 0x0000000000000110 +0x0000000000000170 0x0000000000000177 0x0000000000000110 +0x0000000000000376 0x0000000000000376 0x0000000000000110 +0x0000000000001880 0x000000000000188f 0x0000000000020101 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1f.1/config', 0o644, b"\x86\x80\xdf'\x05\x00\x80\x02\x02\x8a\x01\x01\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x81\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\x0c \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x03\x00\x00\x03\xe3\x00@\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1f.1/resource1', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.1/resource2', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.1/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1f.1/subsystem_device', 0o644, b'0x200c\n') +f('sys/devices/pci0000:00/0000:00:1f.1/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1f.1/irq', 0o644, b'16\n') +f('sys/devices/pci0000:00/0000:00:1f.1/device', 0o644, b'0x27df\n') +f('sys/devices/pci0000:00/0000:00:1f.1/class', 0o644, b'0x01018a\n') +f('sys/devices/pci0000:00/0000:00:1f.1/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.1/resource0', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.1/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1f.1/uevent', 0o644, b'''DRIVER=ata_piix +PCI_CLASS=1018A +PCI_ID=8086:27DF +PCI_SUBSYS_ID=17AA:200C +PCI_SLOT_NAME=0000:00:1f.1 +MODALIAS=pci:v00008086d000027DFsv000017AAsd0000200Cbc01sc01i8a +''') +f('sys/devices/pci0000:00/0000:00:1f.1/resource4', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.1/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host5', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/host5/subsystem', '../../../../bus/scsi') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/uevent', 0o644, b'DEVTYPE=scsi_host\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host5/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host5/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/subsystem', '../../../../../../class/scsi_host') +l('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/device', '../../../host5') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/unique_id', 0o644, b'6\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/can_queue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/unchecked_isa_dma', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/active_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/sg_tablesize', 0o644, b'128\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/prot_guard_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/host_busy', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/proc_name', 0o644, b'ata_piix\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/state', 0o644, b'running\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/cmd_per_lun', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/supported_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/uevent', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/prot_capabilities', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/host4/subsystem', '../../../../bus/scsi') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/uevent', 0o644, b'DEVTYPE=scsi_host\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/subsystem', '../../../../../bus/scsi') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/uevent', 0o644, b'DEVTYPE=scsi_target\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/generic', 'scsi_generic/sg1') +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/subsystem', '../../../../../../bus/scsi') +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/driver', '../../../../../../bus/scsi/drivers/sr') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/iodone_cnt', 0o644, b'0x20b3\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/device_blocked', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/modalias', 0o644, b'scsi:t-0x05\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_level', 0o644, b'6\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/queue_depth', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/rev', 0o644, b'RB01\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/type', 0o644, b'5\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/iocounterbits', 0o644, b'32\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/vendor', 0o644, b'MATSHITA\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/state', 0o644, b'running\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/queue_type', 0o644, b'none\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/iorequest_cnt', 0o644, b'0x82a9\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/evt_media_change', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/model', 0o644, b'DVD-RAM UJ-842 \n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/ioerr_cnt', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/uevent', 0o644, b'''DEVTYPE=scsi_device +DRIVER=sr +MODALIAS=scsi:t-0x05 +''') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/timeout', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_generic', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_generic/sg1', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_generic/sg1/subsystem', '../../../../../../../../class/scsi_generic') +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_generic/sg1/device', '../../../4:0:0:0') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_generic/sg1/dev', 0o644, b'21:1\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_generic/sg1/uevent', 0o644, b'''MAJOR=21 +MINOR=1 +''') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_generic/sg1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_generic/sg1/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/bsg', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0/subsystem', '../../../../../../../../class/bsg') +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0/device', '../../../4:0:0:0') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0/dev', 0o644, b'254:1\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0/uevent', 0o644, b'''MAJOR=254 +MINOR=1 +''') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/bsg/4:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/subsystem', '../../../../../../../../class/block') +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/bdi', '../../../../../../../virtual/bdi/11:0') +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/device', '../../../4:0:0:0') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/capability', 0o644, b'19\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/ro', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/make-it-fail', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/size', 0o644, b'2097151\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/dev', 0o644, b'11:0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/range', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/removable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/stat', 0o644, b' 0 0 0 0 0 0 0 0 0 0 0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/uevent', 0o644, b'''MAJOR=11 +MINOR=0 +DEVTYPE=disk +''') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/nr_requests', 0o644, b'128\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/nomerges', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/scheduler', 0o644, b'noop anticipatory deadline [cfq] \n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/hw_sector_size', 0o644, b'512\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/max_hw_sectors_kb', 0o644, b'128\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/read_ahead_kb', 0o644, b'128\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/max_sectors_kb', 0o644, b'128\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/iosched', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/iosched/slice_async_rq', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/iosched/back_seek_max', 0o644, b'16384\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/iosched/slice_sync', 0o644, b'100\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/iosched/slice_async', 0o644, b'40\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/iosched/fifo_expire_sync', 0o644, b'125\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/iosched/slice_idle', 0o644, b'8\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/iosched/back_seek_penalty', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/iosched/fifo_expire_async', 0o644, b'250\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/queue/iosched/quantum', 0o644, b'4\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/block/sr0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_device', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_device/4:0:0:0', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_device/4:0:0:0/subsystem', '../../../../../../../../class/scsi_device') +l('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_device/4:0:0:0/device', '../../../4:0:0:0') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_device/4:0:0:0/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_device/4:0:0:0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host4/target4:0:0/4:0:0:0/scsi_device/4:0:0:0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host4/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4', 0o755) +l('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/subsystem', '../../../../../../class/scsi_host') +l('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/device', '../../../host4') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/unique_id', 0o644, b'5\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/can_queue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/unchecked_isa_dma', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/active_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/sg_tablesize', 0o644, b'128\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/prot_guard_type', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/host_busy', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/proc_name', 0o644, b'ata_piix\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/state', 0o644, b'running\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/cmd_per_lun', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/supported_mode', 0o644, b'Initiator\n') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/uevent', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/prot_capabilities', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1e.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1e.0/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:11') +l('sys/devices/pci0000:00/0000:00:1e.0/subsystem', '../../../bus/pci') +f('sys/devices/pci0000:00/0000:00:1e.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1e.0/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1e.0/modalias', 0o644, b'pci:v00008086d00002448sv00000000sd00000000bc06sc04i01\n') +f('sys/devices/pci0000:00/0000:00:1e.0/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x000000000000a000 0x000000000000dfff 0x0000000000000100 +0x00000000e4300000 0x00000000e7ffffff 0x0000000000000200 +0x00000000e0000000 0x00000000e3ffffff 0x0000000000001201 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1e.0/config', 0o644, b'\x86\x80H$\x07\x00\x10\x00\xe2\x01\x04\x06\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x18 \xa0\xd0\x80"0\xe4\xf0\xe7\x01\xe0\xf1\xe3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\r\x00\x00\x00\xaa\x17\x13 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00') +f('sys/devices/pci0000:00/0000:00:1e.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1e.0/subsystem_device', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:1e.0/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1e.0/irq', 0o644, b'0\n') +f('sys/devices/pci0000:00/0000:00:1e.0/device', 0o644, b'0x2448\n') +f('sys/devices/pci0000:00/0000:00:1e.0/class', 0o644, b'0x060401\n') +f('sys/devices/pci0000:00/0000:00:1e.0/msi_bus', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1e.0/subsystem_vendor', 0o644, b'0x0000\n') +f('sys/devices/pci0000:00/0000:00:1e.0/uevent', 0o644, b'''PCI_CLASS=60401 +PCI_ID=8086:2448 +PCI_SUBSYS_ID=0000:0000 +PCI_SLOT_NAME=0000:00:1e.0 +MODALIAS=pci:v00008086d00002448sv00000000sd00000000bc06sc04i01 +''') +f('sys/devices/pci0000:00/0000:00:1e.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1e.0/pci_bus', 0o755) +d('sys/devices/pci0000:00/0000:00:1e.0/pci_bus/0000:15', 0o755) +l('sys/devices/pci0000:00/0000:00:1e.0/pci_bus/0000:15/subsystem', '../../../../../class/pci_bus') +l('sys/devices/pci0000:00/0000:00:1e.0/pci_bus/0000:15/device', '../../../0000:00:1e.0') +f('sys/devices/pci0000:00/0000:00:1e.0/pci_bus/0000:15/cpuaffinity', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1e.0/pci_bus/0000:15/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1e.0/pci_bus/0000:15/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1e.0/pci_bus/0000:15/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1e.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1e.0/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/firmware_node', '../../../LNXSYSTM:00/device:00/PNP0A08:00/device:11/device:12') +l('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/subsystem', '../../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/driver', '../../../../bus/pci/drivers/yenta_cardbus') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/enable', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/modalias', 0o644, b'pci:v0000104Cd0000AC56sv000017AAsd00002012bc06sc07i00\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/resource', 0o644, b'''0x00000000e4300000 0x00000000e4300fff 0x0000000000020200 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x000000000000a000 0x000000000000a0ff 0x0000000000020100 +0x000000000000a400 0x000000000000a4ff 0x0000000000020100 +0x00000000e0000000 0x00000000e3ffffff 0x0000000000021200 +0x0000000088000000 0x000000008bffffff 0x0000000000020200 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/config', 0o644, b'L\x10V\xac\x07\x00\x10\x02\x00\x00\x07\x06\x10\xa8\x02\x00\x00\x000\xe4\xa0\x00\x00\x02\x15\x16\x17\xb0\x00\x00\x00\xe0\x00\xf0\xff\xe3\x00\x00\x00\x88\x00\xf0\xff\x8b\x00\xa0\x00\x00\xfc\xa0\x00\x00\x00\xa4\x00\x00\xfc\xa4\x00\x00\x0b\x01\xc0\x05\xaa\x17\x12 \x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00p\xd0D\x08\x00\x00\x00\x00\x00\x00\x00\x00\x02\x10\xd0\x01\xc0\x02d@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x12\xfe\x00\x00\xc0\x00\x07\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/yenta_registers', 0o644, b'''CB registers: +00: 00000000 00000006 30000087 00000000 +10: 00000400 00000000 00000000 00000000 +20: 00000000 + +ExCA registers: +00: 84 01 00 50 00 08 00 00 - 00 00 01 00 00 00 01 00 +10: 00 00 00 00 00 00 c0 00 - 00 00 00 00 00 00 00 00 +20: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 +30: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 +40: 00 00 00 00 00 +''') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/subsystem_device', 0o644, b'0x2012\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/vendor', 0o644, b'0x104c\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/irq', 0o644, b'16\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/device', 0o644, b'0xac56\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/class', 0o644, b'0x060700\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/msi_bus', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/resource0', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/uevent', 0o644, b'''DRIVER=yenta_cardbus +PCI_CLASS=60700 +PCI_ID=104C:AC56 +PCI_SUBSYS_ID=17AA:2012 +PCI_SLOT_NAME=0000:15:00.0 +MODALIAS=pci:v0000104Cd0000AC56sv000017AAsd00002012bc06sc07i00 +''') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pci_bus', 0o755) +d('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pci_bus/0000:16', 0o755) +l('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pci_bus/0000:16/subsystem', '../../../../../../class/pci_bus') +l('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pci_bus/0000:16/device', '../../../0000:15:00.0') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pci_bus/0000:16/cpuaffinity', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pci_bus/0000:16/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pci_bus/0000:16/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pci_bus/0000:16/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket', 0o755) +d('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0', 0o755) +l('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/subsystem', '../../../../../../class/pcmcia_socket') +l('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/device', '../../../0000:15:00.0') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/card_vpp', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/available_resources_mem', 0o644, b'''0x000c0000 - 0x000fffff +0x60000000 - 0x60ffffff +0xa0000000 - 0xa0ffffff +0xe0000000 - 0xe3ffffff +0xe4300000 - 0xe7ffffff +''') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/available_resources_io', 0o644, b'''0x00000100 - 0x000003af +0x000003e0 - 0x000004ff +0x00000820 - 0x000008ff +0x00000a00 - 0x00000aff +0x00000c00 - 0x00000cf7 +0x0000a000 - 0x0000dfff +''') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/card_voltage', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/cis', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/available_resources_setup_done', 0o644, b'yes\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/card_irq_mask', 0o644, b'0x0cf8\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/card_pm_state', 0o644, b'on\n') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/card_vcc', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/card_type', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/uevent', 0o644, b'SOCKET_NO=0\n') +d('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1e.0/0000:15:00.0/pcmcia_socket/pcmcia_socket0/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.1', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.1/firmware_node', '../../LNXSYSTM:00/device:00/PNP0A08:00/device:1a') +l('sys/devices/pci0000:00/0000:00:1d.1/subsystem', '../../../bus/pci') +l('sys/devices/pci0000:00/0000:00:1d.1/driver', '../../../bus/pci/drivers/uhci_hcd') +f('sys/devices/pci0000:00/0000:00:1d.1/local_cpulist', 0o644, b'0-7\n') +f('sys/devices/pci0000:00/0000:00:1d.1/enable', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.1/modalias', 0o644, b'pci:v00008086d000027C9sv000017AAsd0000200Abc0Csc03i00\n') +f('sys/devices/pci0000:00/0000:00:1d.1/resource', 0o644, b'''0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000001820 0x000000000000183f 0x0000000000020101 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +0x0000000000000000 0x0000000000000000 0x0000000000000000 +''') +f('sys/devices/pci0000:00/0000:00:1d.1/config', 0o644, b"\x86\x80\xc9'\x05\x00\x80\x02\x02\x00\x03\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaa\x17\n \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x86\x0f\x02\x00\x00\x00\x00\x00") +f('sys/devices/pci0000:00/0000:00:1d.1/local_cpus', 0o644, b'ff\n') +f('sys/devices/pci0000:00/0000:00:1d.1/subsystem_device', 0o644, b'0x200a\n') +f('sys/devices/pci0000:00/0000:00:1d.1/vendor', 0o644, b'0x8086\n') +f('sys/devices/pci0000:00/0000:00:1d.1/irq', 0o644, b'17\n') +f('sys/devices/pci0000:00/0000:00:1d.1/pools', 0o644, b'''poolinfo - 0.1 +uhci_qh 11 32 128 1 +uhci_td 1 64 64 1 +buffer-2048 0 0 2048 0 +buffer-512 0 0 512 0 +buffer-128 0 0 128 0 +buffer-32 1 128 32 1 +''') +f('sys/devices/pci0000:00/0000:00:1d.1/device', 0o644, b'0x27c9\n') +f('sys/devices/pci0000:00/0000:00:1d.1/class', 0o644, b'0x0c0300\n') +f('sys/devices/pci0000:00/0000:00:1d.1/msi_bus', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.1/subsystem_vendor', 0o644, b'0x17aa\n') +f('sys/devices/pci0000:00/0000:00:1d.1/uevent', 0o644, b'''DRIVER=uhci_hcd +PCI_CLASS=C0300 +PCI_ID=8086:27C9 +PCI_SUBSYS_ID=17AA:200A +PCI_SLOT_NAME=0000:00:1d.1 +MODALIAS=pci:v00008086d000027C9sv000017AAsd0000200Abc0Csc03i00 +''') +f('sys/devices/pci0000:00/0000:00:1d.1/resource4', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.1/broken_parity_status', 0o644, b'0\n') +d('sys/devices/pci0000:00/0000:00:1d.1/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.1/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/pci0000:00/0000:00:1d.1/usb_host', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.1/usb_host/usb_host2', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.1/usb_host/usb_host2/subsystem', '../../../../../class/usb_host') +l('sys/devices/pci0000:00/0000:00:1d.1/usb_host/usb_host2/device', '../../../0000:00:1d.1') +f('sys/devices/pci0000:00/0000:00:1d.1/usb_host/usb_host2/uevent', 0o644, b'') +d('sys/devices/pci0000:00/0000:00:1d.1/usb_host/usb_host2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.1/usb_host/usb_host2/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.1/usb2', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.1/usb2/subsystem', '../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.1/usb2/driver', '../../../../bus/usb/drivers/usb') +l('sys/devices/pci0000:00/0000:00:1d.1/usb2/ep_00', 'usb_endpoint/usbdev2.1_ep00') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/version', 0o644, b' 1.10\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/authorized_default', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/maxchild', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/bDeviceClass', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/bcdDevice', 0o644, b'0206\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/devnum', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/bDeviceProtocol', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/idProduct', 0o644, b'0001\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/product', 0o644, b'UHCI Host Controller\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/bDeviceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/configuration', 0o644, b'') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/dev', 0o644, b'189:128\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/urbnum', 0o644, b'16\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/authorized', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/descriptors', 0o644, b'\x12\x01\x10\x01\t\x00\x00@k\x1d\x01\x00\x06\x02\x03\x02\x01\x01\t\x02\x19\x00\x01\x01\x00\xe0\x00\t\x04\x00\x00\x01\t\x00\x00\x00\x07\x05\x81\x03\x02\x00\xff') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/bNumConfigurations', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/serial', 0o644, b'0000:00:1d.1\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/speed', 0o644, b'12\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/bMaxPacketSize0', 0o644, b'64\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/bmAttributes', 0o644, b'e0\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/busnum', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/quirks', 0o644, b'0x0\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/bConfigurationValue', 0o644, b'1\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/uevent', 0o644, b'''MAJOR=189 +MINOR=128 +DEVTYPE=usb_device +DRIVER=usb +PRODUCT=1d6b/1/206 +TYPE=9/0/0 +BUSNUM=002 +DEVNUM=001 +''') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/manufacturer', 0o644, b'Linux 2.6.27-rc7-00106-g6ef190c-dirty uhci_hcd\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/idVendor', 0o644, b'1d6b\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/bNumInterfaces', 0o644, b' 1\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/bMaxPower', 0o644, b' 0mA\n') +d('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/subsystem', '../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/device', '../../../usb2') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/interval', 0o644, b'0ms\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/bEndpointAddress', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/type', 0o644, b'Control\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/dev', 0o644, b'252:3\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/direction', 0o644, b'both\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/wMaxPacketSize', 0o644, b'0040\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/bmAttributes', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/uevent', 0o644, b'''MAJOR=252 +MINOR=3 +''') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/bInterval', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/usb_endpoint/usbdev2.1_ep00/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.1/usb2/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/power/active_duration', 0o644, b'2363\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/power/wakeup', 0o644, b'enabled\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/power/connected_duration', 0o644, b'8372254\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/power/autosuspend', 0o644, b'2\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/power/level', 0o644, b'auto\n') +d('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/subsystem', '../../../../../bus/usb') +l('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/ep_81', 'usb_endpoint/usbdev2.1_ep81') +l('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/driver', '../../../../../bus/usb/drivers/hub') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/modalias', 0o644, b'usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/bInterfaceNumber', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/bNumEndpoints', 0o644, b'01\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/bInterfaceSubClass', 0o644, b'00\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/bAlternateSetting', 0o644, b' 0\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/bInterfaceClass', 0o644, b'09\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/uevent', 0o644, b'''DEVTYPE=usb_interface +DRIVER=hub +PRODUCT=1d6b/1/206 +TYPE=9/0/0 +INTERFACE=9/0/0 +MODALIAS=usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00 +''') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/bInterfaceProtocol', 0o644, b'00\n') +d('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint', 0o755) +d('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81', 0o755) +l('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/subsystem', '../../../../../../../class/usb_endpoint') +l('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/device', '../../../2-0:1.0') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/interval', 0o644, b'255ms\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/bEndpointAddress', 0o644, b'81\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/type', 0o644, b'Interrupt\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/dev', 0o644, b'252:2\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/direction', 0o644, b'in\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/bLength', 0o644, b'07\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/wMaxPacketSize', 0o644, b'0002\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/bmAttributes', 0o644, b'03\n') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/uevent', 0o644, b'''MAJOR=252 +MINOR=2 +''') +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/bInterval', 0o644, b'ff\n') +d('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/usb_endpoint/usbdev2.1_ep81/power/wakeup', 0o644, b'\n') +d('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/power', 0o755) +f('sys/devices/pci0000:00/0000:00:1d.1/usb2/2-0:1.0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual', 0o755) +d('sys/devices/virtual/vc', 0o755) +d('sys/devices/virtual/vc/vcsa3', 0o755) +l('sys/devices/virtual/vc/vcsa3/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcsa3/dev', 0o644, b'7:131\n') +f('sys/devices/virtual/vc/vcsa3/uevent', 0o644, b'''MAJOR=7 +MINOR=131 +''') +d('sys/devices/virtual/vc/vcsa3/power', 0o755) +f('sys/devices/virtual/vc/vcsa3/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcsa6', 0o755) +l('sys/devices/virtual/vc/vcsa6/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcsa6/dev', 0o644, b'7:134\n') +f('sys/devices/virtual/vc/vcsa6/uevent', 0o644, b'''MAJOR=7 +MINOR=134 +''') +d('sys/devices/virtual/vc/vcsa6/power', 0o755) +f('sys/devices/virtual/vc/vcsa6/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcsa2', 0o755) +l('sys/devices/virtual/vc/vcsa2/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcsa2/dev', 0o644, b'7:130\n') +f('sys/devices/virtual/vc/vcsa2/uevent', 0o644, b'''MAJOR=7 +MINOR=130 +''') +d('sys/devices/virtual/vc/vcsa2/power', 0o755) +f('sys/devices/virtual/vc/vcsa2/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcsa', 0o755) +l('sys/devices/virtual/vc/vcsa/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcsa/dev', 0o644, b'7:128\n') +f('sys/devices/virtual/vc/vcsa/uevent', 0o644, b'''MAJOR=7 +MINOR=128 +''') +d('sys/devices/virtual/vc/vcsa/power', 0o755) +f('sys/devices/virtual/vc/vcsa/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcs2', 0o755) +l('sys/devices/virtual/vc/vcs2/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcs2/dev', 0o644, b'7:2\n') +f('sys/devices/virtual/vc/vcs2/uevent', 0o644, b'''MAJOR=7 +MINOR=2 +''') +d('sys/devices/virtual/vc/vcs2/power', 0o755) +f('sys/devices/virtual/vc/vcs2/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcs7', 0o755) +l('sys/devices/virtual/vc/vcs7/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcs7/dev', 0o644, b'7:7\n') +f('sys/devices/virtual/vc/vcs7/uevent', 0o644, b'''MAJOR=7 +MINOR=7 +''') +d('sys/devices/virtual/vc/vcs7/power', 0o755) +f('sys/devices/virtual/vc/vcs7/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcsa5', 0o755) +l('sys/devices/virtual/vc/vcsa5/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcsa5/dev', 0o644, b'7:133\n') +f('sys/devices/virtual/vc/vcsa5/uevent', 0o644, b'''MAJOR=7 +MINOR=133 +''') +d('sys/devices/virtual/vc/vcsa5/power', 0o755) +f('sys/devices/virtual/vc/vcsa5/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcsa10', 0o755) +l('sys/devices/virtual/vc/vcsa10/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcsa10/dev', 0o644, b'7:138\n') +f('sys/devices/virtual/vc/vcsa10/uevent', 0o644, b'''MAJOR=7 +MINOR=138 +''') +d('sys/devices/virtual/vc/vcsa10/power', 0o755) +f('sys/devices/virtual/vc/vcsa10/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcs10', 0o755) +l('sys/devices/virtual/vc/vcs10/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcs10/dev', 0o644, b'7:10\n') +f('sys/devices/virtual/vc/vcs10/uevent', 0o644, b'''MAJOR=7 +MINOR=10 +''') +d('sys/devices/virtual/vc/vcs10/power', 0o755) +f('sys/devices/virtual/vc/vcs10/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcsa1', 0o755) +l('sys/devices/virtual/vc/vcsa1/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcsa1/dev', 0o644, b'7:129\n') +f('sys/devices/virtual/vc/vcsa1/uevent', 0o644, b'''MAJOR=7 +MINOR=129 +''') +d('sys/devices/virtual/vc/vcsa1/power', 0o755) +f('sys/devices/virtual/vc/vcsa1/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcsa4', 0o755) +l('sys/devices/virtual/vc/vcsa4/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcsa4/dev', 0o644, b'7:132\n') +f('sys/devices/virtual/vc/vcsa4/uevent', 0o644, b'''MAJOR=7 +MINOR=132 +''') +d('sys/devices/virtual/vc/vcsa4/power', 0o755) +f('sys/devices/virtual/vc/vcsa4/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcs', 0o755) +l('sys/devices/virtual/vc/vcs/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcs/dev', 0o644, b'7:0\n') +f('sys/devices/virtual/vc/vcs/uevent', 0o644, b'''MAJOR=7 +MINOR=0 +''') +d('sys/devices/virtual/vc/vcs/power', 0o755) +f('sys/devices/virtual/vc/vcs/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcs1', 0o755) +l('sys/devices/virtual/vc/vcs1/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcs1/dev', 0o644, b'7:1\n') +f('sys/devices/virtual/vc/vcs1/uevent', 0o644, b'''MAJOR=7 +MINOR=1 +''') +d('sys/devices/virtual/vc/vcs1/power', 0o755) +f('sys/devices/virtual/vc/vcs1/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcs4', 0o755) +l('sys/devices/virtual/vc/vcs4/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcs4/dev', 0o644, b'7:4\n') +f('sys/devices/virtual/vc/vcs4/uevent', 0o644, b'''MAJOR=7 +MINOR=4 +''') +d('sys/devices/virtual/vc/vcs4/power', 0o755) +f('sys/devices/virtual/vc/vcs4/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcsa7', 0o755) +l('sys/devices/virtual/vc/vcsa7/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcsa7/dev', 0o644, b'7:135\n') +f('sys/devices/virtual/vc/vcsa7/uevent', 0o644, b'''MAJOR=7 +MINOR=135 +''') +d('sys/devices/virtual/vc/vcsa7/power', 0o755) +f('sys/devices/virtual/vc/vcsa7/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcs6', 0o755) +l('sys/devices/virtual/vc/vcs6/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcs6/dev', 0o644, b'7:6\n') +f('sys/devices/virtual/vc/vcs6/uevent', 0o644, b'''MAJOR=7 +MINOR=6 +''') +d('sys/devices/virtual/vc/vcs6/power', 0o755) +f('sys/devices/virtual/vc/vcs6/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcs3', 0o755) +l('sys/devices/virtual/vc/vcs3/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcs3/dev', 0o644, b'7:3\n') +f('sys/devices/virtual/vc/vcs3/uevent', 0o644, b'''MAJOR=7 +MINOR=3 +''') +d('sys/devices/virtual/vc/vcs3/power', 0o755) +f('sys/devices/virtual/vc/vcs3/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vc/vcs5', 0o755) +l('sys/devices/virtual/vc/vcs5/subsystem', '../../../../class/vc') +f('sys/devices/virtual/vc/vcs5/dev', 0o644, b'7:5\n') +f('sys/devices/virtual/vc/vcs5/uevent', 0o644, b'''MAJOR=7 +MINOR=5 +''') +d('sys/devices/virtual/vc/vcs5/power', 0o755) +f('sys/devices/virtual/vc/vcs5/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/mem', 0o755) +d('sys/devices/virtual/mem/zero', 0o755) +l('sys/devices/virtual/mem/zero/subsystem', '../../../../class/mem') +f('sys/devices/virtual/mem/zero/dev', 0o644, b'1:5\n') +f('sys/devices/virtual/mem/zero/uevent', 0o644, b'''MAJOR=1 +MINOR=5 +''') +d('sys/devices/virtual/mem/zero/power', 0o755) +f('sys/devices/virtual/mem/zero/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/mem/kmsg', 0o755) +l('sys/devices/virtual/mem/kmsg/subsystem', '../../../../class/mem') +f('sys/devices/virtual/mem/kmsg/dev', 0o644, b'1:11\n') +f('sys/devices/virtual/mem/kmsg/uevent', 0o644, b'''MAJOR=1 +MINOR=11 +''') +d('sys/devices/virtual/mem/kmsg/power', 0o755) +f('sys/devices/virtual/mem/kmsg/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/mem/mem', 0o755) +l('sys/devices/virtual/mem/mem/subsystem', '../../../../class/mem') +f('sys/devices/virtual/mem/mem/dev', 0o644, b'1:1\n') +f('sys/devices/virtual/mem/mem/uevent', 0o644, b'''MAJOR=1 +MINOR=1 +''') +d('sys/devices/virtual/mem/mem/power', 0o755) +f('sys/devices/virtual/mem/mem/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/mem/urandom', 0o755) +l('sys/devices/virtual/mem/urandom/subsystem', '../../../../class/mem') +f('sys/devices/virtual/mem/urandom/dev', 0o644, b'1:9\n') +f('sys/devices/virtual/mem/urandom/uevent', 0o644, b'''MAJOR=1 +MINOR=9 +''') +d('sys/devices/virtual/mem/urandom/power', 0o755) +f('sys/devices/virtual/mem/urandom/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/mem/port', 0o755) +l('sys/devices/virtual/mem/port/subsystem', '../../../../class/mem') +f('sys/devices/virtual/mem/port/dev', 0o644, b'1:4\n') +f('sys/devices/virtual/mem/port/uevent', 0o644, b'''MAJOR=1 +MINOR=4 +''') +d('sys/devices/virtual/mem/port/power', 0o755) +f('sys/devices/virtual/mem/port/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/mem/null', 0o755) +l('sys/devices/virtual/mem/null/subsystem', '../../../../class/mem') +f('sys/devices/virtual/mem/null/dev', 0o644, b'1:3\n') +f('sys/devices/virtual/mem/null/uevent', 0o644, b'''MAJOR=1 +MINOR=3 +''') +d('sys/devices/virtual/mem/null/power', 0o755) +f('sys/devices/virtual/mem/null/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/mem/kmem', 0o755) +l('sys/devices/virtual/mem/kmem/subsystem', '../../../../class/mem') +f('sys/devices/virtual/mem/kmem/dev', 0o644, b'1:2\n') +f('sys/devices/virtual/mem/kmem/uevent', 0o644, b'''MAJOR=1 +MINOR=2 +''') +d('sys/devices/virtual/mem/kmem/power', 0o755) +f('sys/devices/virtual/mem/kmem/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/mem/full', 0o755) +l('sys/devices/virtual/mem/full/subsystem', '../../../../class/mem') +f('sys/devices/virtual/mem/full/dev', 0o644, b'1:7\n') +f('sys/devices/virtual/mem/full/uevent', 0o644, b'''MAJOR=1 +MINOR=7 +''') +d('sys/devices/virtual/mem/full/power', 0o755) +f('sys/devices/virtual/mem/full/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/mem/random', 0o755) +l('sys/devices/virtual/mem/random/subsystem', '../../../../class/mem') +f('sys/devices/virtual/mem/random/dev', 0o644, b'1:8\n') +f('sys/devices/virtual/mem/random/uevent', 0o644, b'''MAJOR=1 +MINOR=8 +''') +d('sys/devices/virtual/mem/random/power', 0o755) +f('sys/devices/virtual/mem/random/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/net', 0o755) +d('sys/devices/virtual/net/lo', 0o755) +l('sys/devices/virtual/net/lo/subsystem', '../../../../class/net') +f('sys/devices/virtual/net/lo/ifindex', 0o644, b'1\n') +f('sys/devices/virtual/net/lo/features', 0o644, b'0x13865\n') +f('sys/devices/virtual/net/lo/iflink', 0o644, b'1\n') +f('sys/devices/virtual/net/lo/dormant', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/dev_id', 0o644, b'0x0\n') +f('sys/devices/virtual/net/lo/type', 0o644, b'772\n') +f('sys/devices/virtual/net/lo/operstate', 0o644, b'unknown\n') +f('sys/devices/virtual/net/lo/carrier', 0o644, b'1\n') +f('sys/devices/virtual/net/lo/link_mode', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/tx_queue_len', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/flags', 0o644, b'0x9\n') +f('sys/devices/virtual/net/lo/addr_len', 0o644, b'6\n') +f('sys/devices/virtual/net/lo/address', 0o644, b'00:00:00:00:00:00\n') +f('sys/devices/virtual/net/lo/uevent', 0o644, b'''INTERFACE=lo +IFINDEX=1 +''') +f('sys/devices/virtual/net/lo/mtu', 0o644, b'16436\n') +f('sys/devices/virtual/net/lo/broadcast', 0o644, b'00:00:00:00:00:00\n') +d('sys/devices/virtual/net/lo/statistics', 0o755) +f('sys/devices/virtual/net/lo/statistics/tx_aborted_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/rx_crc_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/rx_bytes', 0o644, b'3380\n') +f('sys/devices/virtual/net/lo/statistics/rx_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/tx_packets', 0o644, b'46\n') +f('sys/devices/virtual/net/lo/statistics/tx_carrier_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/tx_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/rx_dropped', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/tx_fifo_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/rx_length_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/tx_dropped', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/rx_fifo_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/rx_missed_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/tx_window_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/collisions', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/rx_frame_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/rx_packets', 0o644, b'46\n') +f('sys/devices/virtual/net/lo/statistics/rx_compressed', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/tx_compressed', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/multicast', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/rx_over_errors', 0o644, b'0\n') +f('sys/devices/virtual/net/lo/statistics/tx_bytes', 0o644, b'3380\n') +f('sys/devices/virtual/net/lo/statistics/tx_heartbeat_errors', 0o644, b'0\n') +d('sys/devices/virtual/net/lo/power', 0o755) +f('sys/devices/virtual/net/lo/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/dmi', 0o755) +d('sys/devices/virtual/dmi/id', 0o755) +l('sys/devices/virtual/dmi/id/subsystem', '../../../../class/dmi') +f('sys/devices/virtual/dmi/id/product_name', 0o644, b'8741C4G\n') +f('sys/devices/virtual/dmi/id/modalias', 0o644, b'dmi:bvnLENOVO:bvr7IET31WW(1.12):bd09/19/2007:svnLENOVO:pn8741C4G:pvrThinkPadT60p:rvnLENOVO:rn8741C4G:rvrNotAvailable:cvnLENOVO:ct10:cvrNotAvailable:\n') +f('sys/devices/virtual/dmi/id/chassis_serial', 0o644, b'Not Available\n') +f('sys/devices/virtual/dmi/id/board_version', 0o644, b'Not Available\n') +f('sys/devices/virtual/dmi/id/board_serial', 0o644, b'VF0UV72C10X\n') +f('sys/devices/virtual/dmi/id/chassis_type', 0o644, b'10\n') +f('sys/devices/virtual/dmi/id/chassis_asset_tag', 0o644, b'No Asset Information\n') +f('sys/devices/virtual/dmi/id/product_uuid', 0o644, b'82161681-492E-11CB-BCCA-A7FDE26F414B\n') +f('sys/devices/virtual/dmi/id/board_name', 0o644, b'8741C4G\n') +f('sys/devices/virtual/dmi/id/board_asset_tag', 0o644, b'\n') +f('sys/devices/virtual/dmi/id/bios_date', 0o644, b'09/19/2007\n') +f('sys/devices/virtual/dmi/id/bios_version', 0o644, b'7IET31WW (1.12 )\n') +f('sys/devices/virtual/dmi/id/product_serial', 0o644, b'L3AK195\n') +f('sys/devices/virtual/dmi/id/chassis_version', 0o644, b'Not Available\n') +f('sys/devices/virtual/dmi/id/chassis_vendor', 0o644, b'LENOVO\n') +f('sys/devices/virtual/dmi/id/product_version', 0o644, b'ThinkPad T60p\n') +f('sys/devices/virtual/dmi/id/board_vendor', 0o644, b'LENOVO\n') +f('sys/devices/virtual/dmi/id/uevent', 0o644, b'MODALIAS=dmi:bvnLENOVO:bvr7IET31WW(1.12):bd09/19/2007:svnLENOVO:pn8741C4G:pvrThinkPadT60p:rvnLENOVO:rn8741C4G:rvrNotAvailable:cvnLENOVO:ct10:cvrNotAvailable:\n') +f('sys/devices/virtual/dmi/id/sys_vendor', 0o644, b'LENOVO\n') +f('sys/devices/virtual/dmi/id/bios_vendor', 0o644, b'LENOVO\n') +d('sys/devices/virtual/dmi/id/power', 0o755) +f('sys/devices/virtual/dmi/id/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi', 0o755) +d('sys/devices/virtual/bdi/7:1', 0o755) +l('sys/devices/virtual/bdi/7:1/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/7:1/read_ahead_kb', 0o644, b'0\n') +f('sys/devices/virtual/bdi/7:1/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/7:1/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/7:1/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/7:1/power', 0o755) +f('sys/devices/virtual/bdi/7:1/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/7:0', 0o755) +l('sys/devices/virtual/bdi/7:0/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/7:0/read_ahead_kb', 0o644, b'0\n') +f('sys/devices/virtual/bdi/7:0/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/7:0/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/7:0/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/7:0/power', 0o755) +f('sys/devices/virtual/bdi/7:0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/7:2', 0o755) +l('sys/devices/virtual/bdi/7:2/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/7:2/read_ahead_kb', 0o644, b'0\n') +f('sys/devices/virtual/bdi/7:2/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/7:2/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/7:2/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/7:2/power', 0o755) +f('sys/devices/virtual/bdi/7:2/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/7:4', 0o755) +l('sys/devices/virtual/bdi/7:4/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/7:4/read_ahead_kb', 0o644, b'0\n') +f('sys/devices/virtual/bdi/7:4/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/7:4/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/7:4/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/7:4/power', 0o755) +f('sys/devices/virtual/bdi/7:4/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/7:3', 0o755) +l('sys/devices/virtual/bdi/7:3/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/7:3/read_ahead_kb', 0o644, b'0\n') +f('sys/devices/virtual/bdi/7:3/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/7:3/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/7:3/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/7:3/power', 0o755) +f('sys/devices/virtual/bdi/7:3/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/11:0', 0o755) +l('sys/devices/virtual/bdi/11:0/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/11:0/read_ahead_kb', 0o644, b'128\n') +f('sys/devices/virtual/bdi/11:0/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/11:0/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/11:0/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/11:0/power', 0o755) +f('sys/devices/virtual/bdi/11:0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/7:5', 0o755) +l('sys/devices/virtual/bdi/7:5/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/7:5/read_ahead_kb', 0o644, b'0\n') +f('sys/devices/virtual/bdi/7:5/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/7:5/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/7:5/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/7:5/power', 0o755) +f('sys/devices/virtual/bdi/7:5/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/8:0', 0o755) +l('sys/devices/virtual/bdi/8:0/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/8:0/read_ahead_kb', 0o644, b'128\n') +f('sys/devices/virtual/bdi/8:0/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/8:0/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/8:0/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/8:0/power', 0o755) +f('sys/devices/virtual/bdi/8:0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/default', 0o755) +l('sys/devices/virtual/bdi/default/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/default/read_ahead_kb', 0o644, b'128\n') +f('sys/devices/virtual/bdi/default/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/default/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/default/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/default/power', 0o755) +f('sys/devices/virtual/bdi/default/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/0:16', 0o755) +l('sys/devices/virtual/bdi/0:16/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/0:16/read_ahead_kb', 0o644, b'128\n') +f('sys/devices/virtual/bdi/0:16/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/0:16/max_ratio', 0o644, b'1\n') +f('sys/devices/virtual/bdi/0:16/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/0:16/power', 0o755) +f('sys/devices/virtual/bdi/0:16/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/8:16', 0o755) +l('sys/devices/virtual/bdi/8:16/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/8:16/read_ahead_kb', 0o644, b'128\n') +f('sys/devices/virtual/bdi/8:16/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/8:16/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/8:16/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/8:16/power', 0o755) +f('sys/devices/virtual/bdi/8:16/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/9:0', 0o755) +l('sys/devices/virtual/bdi/9:0/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/9:0/read_ahead_kb', 0o644, b'128\n') +f('sys/devices/virtual/bdi/9:0/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/9:0/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/9:0/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/9:0/power', 0o755) +f('sys/devices/virtual/bdi/9:0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/7:7', 0o755) +l('sys/devices/virtual/bdi/7:7/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/7:7/read_ahead_kb', 0o644, b'0\n') +f('sys/devices/virtual/bdi/7:7/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/7:7/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/7:7/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/7:7/power', 0o755) +f('sys/devices/virtual/bdi/7:7/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/bdi/7:6', 0o755) +l('sys/devices/virtual/bdi/7:6/subsystem', '../../../../class/bdi') +f('sys/devices/virtual/bdi/7:6/read_ahead_kb', 0o644, b'0\n') +f('sys/devices/virtual/bdi/7:6/uevent', 0o644, b'') +f('sys/devices/virtual/bdi/7:6/max_ratio', 0o644, b'100\n') +f('sys/devices/virtual/bdi/7:6/min_ratio', 0o644, b'0\n') +d('sys/devices/virtual/bdi/7:6/power', 0o755) +f('sys/devices/virtual/bdi/7:6/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/sound', 0o755) +d('sys/devices/virtual/sound/timer', 0o755) +l('sys/devices/virtual/sound/timer/subsystem', '../../../../class/sound') +f('sys/devices/virtual/sound/timer/dev', 0o644, b'116:33\n') +f('sys/devices/virtual/sound/timer/uevent', 0o644, b'''MAJOR=116 +MINOR=33 +''') +d('sys/devices/virtual/sound/timer/power', 0o755) +f('sys/devices/virtual/sound/timer/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/sound/seq', 0o755) +l('sys/devices/virtual/sound/seq/subsystem', '../../../../class/sound') +f('sys/devices/virtual/sound/seq/dev', 0o644, b'116:1\n') +f('sys/devices/virtual/sound/seq/uevent', 0o644, b'''MAJOR=116 +MINOR=1 +''') +d('sys/devices/virtual/sound/seq/power', 0o755) +f('sys/devices/virtual/sound/seq/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc', 0o755) +d('sys/devices/virtual/misc/misc-fake89999', 0o755) +l('sys/devices/virtual/misc/misc-fake89999/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/misc-fake89999/dev', 0o644, b'4095:89999\n') +f('sys/devices/virtual/misc/misc-fake89999/uevent', 0o644, b'''MAJOR=4095 +MINOR=89999 +DEVNAME=misc-fake89999 +''') +d('sys/devices/virtual/misc/misc-fake89999/power', 0o755) +f('sys/devices/virtual/misc/misc-fake89999/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/uinput', 0o755) +l('sys/devices/virtual/misc/uinput/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/uinput/dev', 0o644, b'10:223\n') +f('sys/devices/virtual/misc/uinput/uevent', 0o644, b'''MAJOR=10 +MINOR=223 +''') +d('sys/devices/virtual/misc/uinput/power', 0o755) +f('sys/devices/virtual/misc/uinput/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/fuse', 0o755) +l('sys/devices/virtual/misc/fuse/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/fuse/dev', 0o644, b'10:229\n') +f('sys/devices/virtual/misc/fuse/uevent', 0o644, b'''MAJOR=10 +MINOR=229 +''') +d('sys/devices/virtual/misc/fuse/power', 0o755) +f('sys/devices/virtual/misc/fuse/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/hpet', 0o755) +l('sys/devices/virtual/misc/hpet/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/hpet/dev', 0o644, b'10:228\n') +f('sys/devices/virtual/misc/hpet/uevent', 0o644, b'''MAJOR=10 +MINOR=228 +''') +d('sys/devices/virtual/misc/hpet/power', 0o755) +f('sys/devices/virtual/misc/hpet/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/cpu_dma_latency', 0o755) +l('sys/devices/virtual/misc/cpu_dma_latency/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/cpu_dma_latency/dev', 0o644, b'10:63\n') +f('sys/devices/virtual/misc/cpu_dma_latency/uevent', 0o644, b'''MAJOR=10 +MINOR=63 +''') +d('sys/devices/virtual/misc/cpu_dma_latency/power', 0o755) +f('sys/devices/virtual/misc/cpu_dma_latency/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/mcelog', 0o755) +l('sys/devices/virtual/misc/mcelog/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/mcelog/dev', 0o644, b'10:227\n') +f('sys/devices/virtual/misc/mcelog/uevent', 0o644, b'''MAJOR=10 +MINOR=227 +''') +d('sys/devices/virtual/misc/mcelog/power', 0o755) +f('sys/devices/virtual/misc/mcelog/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/device-mapper', 0o755) +l('sys/devices/virtual/misc/device-mapper/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/device-mapper/dev', 0o644, b'10:60\n') +f('sys/devices/virtual/misc/device-mapper/uevent', 0o644, b'''MAJOR=10 +MINOR=60 +''') +d('sys/devices/virtual/misc/device-mapper/power', 0o755) +f('sys/devices/virtual/misc/device-mapper/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/psaux', 0o755) +l('sys/devices/virtual/misc/psaux/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/psaux/dev', 0o644, b'10:1\n') +f('sys/devices/virtual/misc/psaux/uevent', 0o644, b'''MAJOR=10 +MINOR=1 +''') +d('sys/devices/virtual/misc/psaux/power', 0o755) +f('sys/devices/virtual/misc/psaux/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/misc-fake1', 0o755) +l('sys/devices/virtual/misc/misc-fake1/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/misc-fake1/dev', 0o644, b'4095:1\n') +f('sys/devices/virtual/misc/misc-fake1/uevent', 0o644, b'''MAJOR=4095 +MINOR=1 +DEVNAME=misc-fake1 + +''') +d('sys/devices/virtual/misc/misc-fake1/power', 0o755) +f('sys/devices/virtual/misc/misc-fake1/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/nvram', 0o755) +l('sys/devices/virtual/misc/nvram/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/nvram/dev', 0o644, b'10:144\n') +f('sys/devices/virtual/misc/nvram/uevent', 0o644, b'''MAJOR=10 +MINOR=144 +''') +d('sys/devices/virtual/misc/nvram/power', 0o755) +f('sys/devices/virtual/misc/nvram/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/network_latency', 0o755) +l('sys/devices/virtual/misc/network_latency/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/network_latency/dev', 0o644, b'10:62\n') +f('sys/devices/virtual/misc/network_latency/uevent', 0o644, b'''MAJOR=10 +MINOR=62 +''') +d('sys/devices/virtual/misc/network_latency/power', 0o755) +f('sys/devices/virtual/misc/network_latency/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/network_throughput', 0o755) +l('sys/devices/virtual/misc/network_throughput/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/network_throughput/dev', 0o644, b'10:61\n') +f('sys/devices/virtual/misc/network_throughput/uevent', 0o644, b'''MAJOR=10 +MINOR=61 +''') +d('sys/devices/virtual/misc/network_throughput/power', 0o755) +f('sys/devices/virtual/misc/network_throughput/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/misc/microcode', 0o755) +l('sys/devices/virtual/misc/microcode/subsystem', '../../../../class/misc') +f('sys/devices/virtual/misc/microcode/dev', 0o644, b'10:184\n') +f('sys/devices/virtual/misc/microcode/uevent', 0o644, b'''MAJOR=10 +MINOR=184 +''') +d('sys/devices/virtual/misc/microcode/power', 0o755) +f('sys/devices/virtual/misc/microcode/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vtconsole', 0o755) +d('sys/devices/virtual/vtconsole/vtcon1', 0o755) +l('sys/devices/virtual/vtconsole/vtcon1/subsystem', '../../../../class/vtconsole') +f('sys/devices/virtual/vtconsole/vtcon1/bind', 0o644, b'1\n') +f('sys/devices/virtual/vtconsole/vtcon1/name', 0o644, b'(M) frame buffer device\n') +f('sys/devices/virtual/vtconsole/vtcon1/uevent', 0o644, b'') +d('sys/devices/virtual/vtconsole/vtcon1/power', 0o755) +f('sys/devices/virtual/vtconsole/vtcon1/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/vtconsole/vtcon0', 0o755) +l('sys/devices/virtual/vtconsole/vtcon0/subsystem', '../../../../class/vtconsole') +f('sys/devices/virtual/vtconsole/vtcon0/bind', 0o644, b'0\n') +f('sys/devices/virtual/vtconsole/vtcon0/name', 0o644, b'(S) dummy device\n') +f('sys/devices/virtual/vtconsole/vtcon0/uevent', 0o644, b'') +d('sys/devices/virtual/vtconsole/vtcon0/power', 0o755) +f('sys/devices/virtual/vtconsole/vtcon0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/input', 0o755) +d('sys/devices/virtual/input/mice', 0o755) +l('sys/devices/virtual/input/mice/subsystem', '../../../../class/input') +f('sys/devices/virtual/input/mice/dev', 0o644, b'13:63\n') +f('sys/devices/virtual/input/mice/uevent', 0o644, b'''MAJOR=13 +MINOR=63 +''') +d('sys/devices/virtual/input/mice/power', 0o755) +f('sys/devices/virtual/input/mice/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/input/input6', 0o755) +l('sys/devices/virtual/input/input6/subsystem', '../../../../class/input') +f('sys/devices/virtual/input/input6/uniq', 0o644, b'\n') +f('sys/devices/virtual/input/input6/phys', 0o644, b'thinkpad_acpi/input0\n') +f('sys/devices/virtual/input/input6/modalias', 0o644, b'input:b0019v17AAp5054e4101-e0,1,4,5,k71,72,73,8E,98,C0,C2,CD,E0,E1,E3,E4,EC,F0,168,174,181,1D2,1D7,1DB,1DC,ram4,lsfw3,\n') +f('sys/devices/virtual/input/input6/name', 0o644, b'ThinkPad Extra Buttons\n') +f('sys/devices/virtual/input/input6/uevent', 0o644, b'''PRODUCT=19/17aa/5054/4101 +NAME="ThinkPad Extra Buttons" +PHYS="thinkpad_acpi/input0" +EV==33 +KEY==18840000 2 10010000000000 0 1101b00002005 1004000 e000000000000 0 +MSC==10 +SW==8 +MODALIAS=input:b0019v17AAp5054e4101-e0,1,4,5,k71,72,73,8E,98,C0,C2,CD,E0,E1,E3,E4,EC,F0,168,174,181,1D2,1D7,1DB,1DC,ram4,lsfw3, +''') +d('sys/devices/virtual/input/input6/id', 0o755) +f('sys/devices/virtual/input/input6/id/version', 0o644, b'4101\n') +f('sys/devices/virtual/input/input6/id/product', 0o644, b'5054\n') +f('sys/devices/virtual/input/input6/id/vendor', 0o644, b'17aa\n') +f('sys/devices/virtual/input/input6/id/bustype', 0o644, b'0019\n') +d('sys/devices/virtual/input/input6/power', 0o755) +f('sys/devices/virtual/input/input6/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/input/input6/event6', 0o755) +l('sys/devices/virtual/input/input6/event6/subsystem', '../../../../../class/input') +l('sys/devices/virtual/input/input6/event6/device', '../../input6') +f('sys/devices/virtual/input/input6/event6/dev', 0o644, b'13:70\n') +f('sys/devices/virtual/input/input6/event6/uevent', 0o644, b'''MAJOR=13 +MINOR=70 +''') +d('sys/devices/virtual/input/input6/event6/power', 0o755) +f('sys/devices/virtual/input/input6/event6/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/input/input6/capabilities', 0o755) +f('sys/devices/virtual/input/input6/capabilities/msc', 0o644, b'10\n') +f('sys/devices/virtual/input/input6/capabilities/abs', 0o644, b'0\n') +f('sys/devices/virtual/input/input6/capabilities/snd', 0o644, b'0\n') +f('sys/devices/virtual/input/input6/capabilities/ff', 0o644, b'0\n') +f('sys/devices/virtual/input/input6/capabilities/key', 0o644, b'18840000 2 10010000000000 0 1101b00002005 1004000 e000000000000 0\n') +f('sys/devices/virtual/input/input6/capabilities/rel', 0o644, b'0\n') +f('sys/devices/virtual/input/input6/capabilities/sw', 0o644, b'8\n') +f('sys/devices/virtual/input/input6/capabilities/ev', 0o644, b'33\n') +f('sys/devices/virtual/input/input6/capabilities/led', 0o644, b'0\n') +d('sys/devices/virtual/thermal', 0o755) +d('sys/devices/virtual/thermal/thermal_zone1', 0o755) +l('sys/devices/virtual/thermal/thermal_zone1/subsystem', '../../../../class/thermal') +l('sys/devices/virtual/thermal/thermal_zone1/cdev1', '../cooling_device0') +l('sys/devices/virtual/thermal/thermal_zone1/cdev0', '../cooling_device1') +l('sys/devices/virtual/thermal/thermal_zone1/device', '../../../LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02') +f('sys/devices/virtual/thermal/thermal_zone1/trip_point_0_type', 0o644, b'critical\n') +f('sys/devices/virtual/thermal/thermal_zone1/trip_point_0_temp', 0o644, b'100000\n') +f('sys/devices/virtual/thermal/thermal_zone1/trip_point_1_temp', 0o644, b'95500\n') +f('sys/devices/virtual/thermal/thermal_zone1/type', 0o644, b'acpitz\n') +f('sys/devices/virtual/thermal/thermal_zone1/cdev1_trip_point', 0o644, b'1\n') +f('sys/devices/virtual/thermal/thermal_zone1/mode', 0o644, b'kernel\n') +f('sys/devices/virtual/thermal/thermal_zone1/temp', 0o644, b'47000\n') +f('sys/devices/virtual/thermal/thermal_zone1/cdev0_trip_point', 0o644, b'1\n') +f('sys/devices/virtual/thermal/thermal_zone1/uevent', 0o644, b'') +f('sys/devices/virtual/thermal/thermal_zone1/trip_point_1_type', 0o644, b'passive\n') +d('sys/devices/virtual/thermal/thermal_zone1/power', 0o755) +f('sys/devices/virtual/thermal/thermal_zone1/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/thermal/cooling_device1', 0o755) +l('sys/devices/virtual/thermal/cooling_device1/subsystem', '../../../../class/thermal') +l('sys/devices/virtual/thermal/cooling_device1/device', '../../../LNXSYSTM:00/ACPI0007:01') +f('sys/devices/virtual/thermal/cooling_device1/type', 0o644, b'Processor\n') +f('sys/devices/virtual/thermal/cooling_device1/max_state', 0o644, b'10\n') +f('sys/devices/virtual/thermal/cooling_device1/cur_state', 0o644, b'0\n') +f('sys/devices/virtual/thermal/cooling_device1/uevent', 0o644, b'') +d('sys/devices/virtual/thermal/cooling_device1/power', 0o755) +f('sys/devices/virtual/thermal/cooling_device1/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/thermal/cooling_device0', 0o755) +l('sys/devices/virtual/thermal/cooling_device0/subsystem', '../../../../class/thermal') +l('sys/devices/virtual/thermal/cooling_device0/device', '../../../LNXSYSTM:00/ACPI0007:00') +f('sys/devices/virtual/thermal/cooling_device0/type', 0o644, b'Processor\n') +f('sys/devices/virtual/thermal/cooling_device0/max_state', 0o644, b'10\n') +f('sys/devices/virtual/thermal/cooling_device0/cur_state', 0o644, b'0\n') +f('sys/devices/virtual/thermal/cooling_device0/uevent', 0o644, b'') +d('sys/devices/virtual/thermal/cooling_device0/power', 0o755) +f('sys/devices/virtual/thermal/cooling_device0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/thermal/thermal_zone0', 0o755) +l('sys/devices/virtual/thermal/thermal_zone0/subsystem', '../../../../class/thermal') +l('sys/devices/virtual/thermal/thermal_zone0/device', '../../../LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01') +f('sys/devices/virtual/thermal/thermal_zone0/trip_point_0_type', 0o644, b'critical\n') +f('sys/devices/virtual/thermal/thermal_zone0/trip_point_0_temp', 0o644, b'127000\n') +f('sys/devices/virtual/thermal/thermal_zone0/type', 0o644, b'acpitz\n') +f('sys/devices/virtual/thermal/thermal_zone0/mode', 0o644, b'kernel\n') +f('sys/devices/virtual/thermal/thermal_zone0/temp', 0o644, b'46000\n') +f('sys/devices/virtual/thermal/thermal_zone0/uevent', 0o644, b'') +d('sys/devices/virtual/thermal/thermal_zone0/power', 0o755) +f('sys/devices/virtual/thermal/thermal_zone0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/block', 0o755) +d('sys/devices/virtual/block/loop1', 0o755) +l('sys/devices/virtual/block/loop1/subsystem', '../../../../class/block') +l('sys/devices/virtual/block/loop1/bdi', '../../bdi/7:1') +f('sys/devices/virtual/block/loop1/capability', 0o644, b'10\n') +f('sys/devices/virtual/block/loop1/ro', 0o644, b'0\n') +f('sys/devices/virtual/block/loop1/make-it-fail', 0o644, b'0\n') +f('sys/devices/virtual/block/loop1/size', 0o644, b'0\n') +f('sys/devices/virtual/block/loop1/dev', 0o644, b'7:1\n') +f('sys/devices/virtual/block/loop1/range', 0o644, b'1\n') +f('sys/devices/virtual/block/loop1/removable', 0o644, b'0\n') +f('sys/devices/virtual/block/loop1/stat', 0o644, b' 0 0 0 0 0 0 0 0 0 0 0\n') +f('sys/devices/virtual/block/loop1/uevent', 0o644, b'''MAJOR=7 +MINOR=1 +DEVTYPE=disk +''') +d('sys/devices/virtual/block/loop1/power', 0o755) +f('sys/devices/virtual/block/loop1/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/block/loop7', 0o755) +l('sys/devices/virtual/block/loop7/subsystem', '../../../../class/block') +l('sys/devices/virtual/block/loop7/bdi', '../../bdi/7:7') +f('sys/devices/virtual/block/loop7/capability', 0o644, b'10\n') +f('sys/devices/virtual/block/loop7/ro', 0o644, b'0\n') +f('sys/devices/virtual/block/loop7/make-it-fail', 0o644, b'0\n') +f('sys/devices/virtual/block/loop7/size', 0o644, b'0\n') +f('sys/devices/virtual/block/loop7/dev', 0o644, b'7:7\n') +f('sys/devices/virtual/block/loop7/range', 0o644, b'1\n') +f('sys/devices/virtual/block/loop7/removable', 0o644, b'0\n') +f('sys/devices/virtual/block/loop7/stat', 0o644, b' 0 0 0 0 0 0 0 0 0 0 0\n') +f('sys/devices/virtual/block/loop7/uevent', 0o644, b'''MAJOR=7 +MINOR=7 +DEVTYPE=disk +''') +d('sys/devices/virtual/block/loop7/power', 0o755) +f('sys/devices/virtual/block/loop7/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/block/loop0', 0o755) +l('sys/devices/virtual/block/loop0/subsystem', '../../../../class/block') +l('sys/devices/virtual/block/loop0/bdi', '../../bdi/7:0') +f('sys/devices/virtual/block/loop0/capability', 0o644, b'10\n') +f('sys/devices/virtual/block/loop0/ro', 0o644, b'0\n') +f('sys/devices/virtual/block/loop0/make-it-fail', 0o644, b'0\n') +f('sys/devices/virtual/block/loop0/size', 0o644, b'0\n') +f('sys/devices/virtual/block/loop0/dev', 0o644, b'7:0\n') +f('sys/devices/virtual/block/loop0/range', 0o644, b'1\n') +f('sys/devices/virtual/block/loop0/removable', 0o644, b'0\n') +f('sys/devices/virtual/block/loop0/stat', 0o644, b' 0 0 0 0 0 0 0 0 0 0 0\n') +f('sys/devices/virtual/block/loop0/uevent', 0o644, b'''MAJOR=7 +MINOR=0 +DEVTYPE=disk +''') +d('sys/devices/virtual/block/loop0/power', 0o755) +f('sys/devices/virtual/block/loop0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/block/loop5', 0o755) +l('sys/devices/virtual/block/loop5/subsystem', '../../../../class/block') +l('sys/devices/virtual/block/loop5/bdi', '../../bdi/7:5') +f('sys/devices/virtual/block/loop5/capability', 0o644, b'10\n') +f('sys/devices/virtual/block/loop5/ro', 0o644, b'0\n') +f('sys/devices/virtual/block/loop5/make-it-fail', 0o644, b'0\n') +f('sys/devices/virtual/block/loop5/size', 0o644, b'0\n') +f('sys/devices/virtual/block/loop5/dev', 0o644, b'7:5\n') +f('sys/devices/virtual/block/loop5/range', 0o644, b'1\n') +f('sys/devices/virtual/block/loop5/removable', 0o644, b'0\n') +f('sys/devices/virtual/block/loop5/stat', 0o644, b' 0 0 0 0 0 0 0 0 0 0 0\n') +f('sys/devices/virtual/block/loop5/uevent', 0o644, b'''MAJOR=7 +MINOR=5 +DEVTYPE=disk +''') +d('sys/devices/virtual/block/loop5/power', 0o755) +f('sys/devices/virtual/block/loop5/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/block/loop3', 0o755) +l('sys/devices/virtual/block/loop3/subsystem', '../../../../class/block') +l('sys/devices/virtual/block/loop3/bdi', '../../bdi/7:3') +f('sys/devices/virtual/block/loop3/capability', 0o644, b'10\n') +f('sys/devices/virtual/block/loop3/ro', 0o644, b'0\n') +f('sys/devices/virtual/block/loop3/make-it-fail', 0o644, b'0\n') +f('sys/devices/virtual/block/loop3/size', 0o644, b'0\n') +f('sys/devices/virtual/block/loop3/dev', 0o644, b'7:3\n') +f('sys/devices/virtual/block/loop3/range', 0o644, b'1\n') +f('sys/devices/virtual/block/loop3/removable', 0o644, b'0\n') +f('sys/devices/virtual/block/loop3/stat', 0o644, b' 0 0 0 0 0 0 0 0 0 0 0\n') +f('sys/devices/virtual/block/loop3/uevent', 0o644, b'''MAJOR=7 +MINOR=3 +DEVTYPE=disk +''') +d('sys/devices/virtual/block/loop3/power', 0o755) +f('sys/devices/virtual/block/loop3/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/block/loop6', 0o755) +l('sys/devices/virtual/block/loop6/subsystem', '../../../../class/block') +l('sys/devices/virtual/block/loop6/bdi', '../../bdi/7:6') +f('sys/devices/virtual/block/loop6/capability', 0o644, b'10\n') +f('sys/devices/virtual/block/loop6/ro', 0o644, b'0\n') +f('sys/devices/virtual/block/loop6/make-it-fail', 0o644, b'0\n') +f('sys/devices/virtual/block/loop6/size', 0o644, b'0\n') +f('sys/devices/virtual/block/loop6/dev', 0o644, b'7:6\n') +f('sys/devices/virtual/block/loop6/range', 0o644, b'1\n') +f('sys/devices/virtual/block/loop6/removable', 0o644, b'0\n') +f('sys/devices/virtual/block/loop6/stat', 0o644, b' 0 0 0 0 0 0 0 0 0 0 0\n') +f('sys/devices/virtual/block/loop6/uevent', 0o644, b'''MAJOR=7 +MINOR=6 +DEVTYPE=disk +''') +d('sys/devices/virtual/block/loop6/power', 0o755) +f('sys/devices/virtual/block/loop6/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/block/loop2', 0o755) +l('sys/devices/virtual/block/loop2/subsystem', '../../../../class/block') +l('sys/devices/virtual/block/loop2/bdi', '../../bdi/7:2') +f('sys/devices/virtual/block/loop2/capability', 0o644, b'10\n') +f('sys/devices/virtual/block/loop2/ro', 0o644, b'0\n') +f('sys/devices/virtual/block/loop2/make-it-fail', 0o644, b'0\n') +f('sys/devices/virtual/block/loop2/size', 0o644, b'0\n') +f('sys/devices/virtual/block/loop2/dev', 0o644, b'7:2\n') +f('sys/devices/virtual/block/loop2/range', 0o644, b'1\n') +f('sys/devices/virtual/block/loop2/removable', 0o644, b'0\n') +f('sys/devices/virtual/block/loop2/stat', 0o644, b' 0 0 0 0 0 0 0 0 0 0 0\n') +f('sys/devices/virtual/block/loop2/uevent', 0o644, b'''MAJOR=7 +MINOR=2 +DEVTYPE=disk +''') +d('sys/devices/virtual/block/loop2/power', 0o755) +f('sys/devices/virtual/block/loop2/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/block/fake!blockdev0', 0o755) +l('sys/devices/virtual/block/fake!blockdev0/subsystem', '../../../../class/block') +f('sys/devices/virtual/block/fake!blockdev0/capability', 0o644, b'10\n') +f('sys/devices/virtual/block/fake!blockdev0/ro', 0o644, b'0\n') +f('sys/devices/virtual/block/fake!blockdev0/size', 0o644, b'0\n') +f('sys/devices/virtual/block/fake!blockdev0/dev', 0o644, b'711:0\n') +f('sys/devices/virtual/block/fake!blockdev0/range', 0o644, b'1\n') +f('sys/devices/virtual/block/fake!blockdev0/removable', 0o644, b'0\n') +f('sys/devices/virtual/block/fake!blockdev0/stat', 0o644, b' 0 0 0 0 0 0 0 0 0 0 0\n') +f('sys/devices/virtual/block/fake!blockdev0/uevent', 0o644, b'''MAJOR=7 +MINOR=0 +DEVTYPE=disk +DEVNAME=fake/blockdev0 +''') +d('sys/devices/virtual/block/loop4', 0o755) +l('sys/devices/virtual/block/loop4/subsystem', '../../../../class/block') +l('sys/devices/virtual/block/loop4/bdi', '../../bdi/7:4') +f('sys/devices/virtual/block/loop4/capability', 0o644, b'10\n') +f('sys/devices/virtual/block/loop4/ro', 0o644, b'0\n') +f('sys/devices/virtual/block/loop4/make-it-fail', 0o644, b'0\n') +f('sys/devices/virtual/block/loop4/size', 0o644, b'0\n') +f('sys/devices/virtual/block/loop4/dev', 0o644, b'7:4\n') +f('sys/devices/virtual/block/loop4/range', 0o644, b'1\n') +f('sys/devices/virtual/block/loop4/removable', 0o644, b'0\n') +f('sys/devices/virtual/block/loop4/stat', 0o644, b' 0 0 0 0 0 0 0 0 0 0 0\n') +f('sys/devices/virtual/block/loop4/uevent', 0o644, b'''MAJOR=7 +MINOR=4 +DEVTYPE=disk +''') +d('sys/devices/virtual/block/loop4/power', 0o755) +f('sys/devices/virtual/block/loop4/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/block/md0', 0o755) +l('sys/devices/virtual/block/md0/subsystem', '../../../../class/block') +l('sys/devices/virtual/block/md0/bdi', '../../bdi/9:0') +f('sys/devices/virtual/block/md0/capability', 0o644, b'10\n') +f('sys/devices/virtual/block/md0/ro', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/make-it-fail', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/size', 0o644, b'19534848\n') +f('sys/devices/virtual/block/md0/dev', 0o644, b'9:0\n') +f('sys/devices/virtual/block/md0/range', 0o644, b'1\n') +f('sys/devices/virtual/block/md0/removable', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/stat', 0o644, b' 60 0 480 0 0 0 0 0 0 0 0\n') +f('sys/devices/virtual/block/md0/uevent', 0o644, b'''MAJOR=9 +MINOR=0 +DEVTYPE=disk +''') +d('sys/devices/virtual/block/md0/power', 0o755) +f('sys/devices/virtual/block/md0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/block/md0/md', 0o755) +l('sys/devices/virtual/block/md0/md/rd1', 'dev-sda9') +f('sys/devices/virtual/block/md0/md/chunk_size', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/md/sync_action', 0o644, b'idle\n') +f('sys/devices/virtual/block/md0/md/sync_speed_min', 0o644, b'1000 (system)\n') +f('sys/devices/virtual/block/md0/md/sync_force_parallel', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/md/sync_min', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/md/mismatch_cnt', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/md/suspend_hi', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/md/sync_completed', 0o644, b'0 / 19534848\n') +f('sys/devices/virtual/block/md0/md/sync_max', 0o644, b'max\n') +f('sys/devices/virtual/block/md0/md/safe_mode_delay', 0o644, b'0.201\n') +f('sys/devices/virtual/block/md0/md/degraded', 0o644, b'1\n') +f('sys/devices/virtual/block/md0/md/component_size', 0o644, b'9767424\n') +f('sys/devices/virtual/block/md0/md/suspend_lo', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/md/resync_start', 0o644, b'18446744073709551615\n') +f('sys/devices/virtual/block/md0/md/sync_speed', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/md/reshape_position', 0o644, b'none\n') +f('sys/devices/virtual/block/md0/md/array_state', 0o644, b'clean\n') +f('sys/devices/virtual/block/md0/md/sync_speed_max', 0o644, b'200000 (system)\n') +f('sys/devices/virtual/block/md0/md/level', 0o644, b'raid1\n') +f('sys/devices/virtual/block/md0/md/layout', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/md/raid_disks', 0o644, b'2\n') +f('sys/devices/virtual/block/md0/md/metadata_version', 0o644, b'0.90\n') +d('sys/devices/virtual/block/md0/md/dev-sda9', 0o755) +l('sys/devices/virtual/block/md0/md/dev-sda9/block', '../../../../../pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9') +f('sys/devices/virtual/block/md0/md/dev-sda9/slot', 0o644, b'1\n') +f('sys/devices/virtual/block/md0/md/dev-sda9/size', 0o644, b'23438720\n') +f('sys/devices/virtual/block/md0/md/dev-sda9/state', 0o644, b'in_sync\n') +f('sys/devices/virtual/block/md0/md/dev-sda9/errors', 0o644, b'0\n') +f('sys/devices/virtual/block/md0/md/dev-sda9/offset', 0o644, b'0\n') +d('sys/devices/virtual/block/md0/slaves', 0o755) +l('sys/devices/virtual/block/md0/slaves/sda9', '../../../../pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9') +d('sys/devices/virtual/graphics', 0o755) +d('sys/devices/virtual/graphics/fbcon', 0o755) +l('sys/devices/virtual/graphics/fbcon/subsystem', '../../../../class/graphics') +f('sys/devices/virtual/graphics/fbcon/cursor_blink', 0o644, b'0\n') +f('sys/devices/virtual/graphics/fbcon/rotate', 0o644, b'0\n') +f('sys/devices/virtual/graphics/fbcon/uevent', 0o644, b'') +d('sys/devices/virtual/graphics/fbcon/power', 0o755) +f('sys/devices/virtual/graphics/fbcon/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty', 0o755) +d('sys/devices/virtual/tty/tty51', 0o755) +l('sys/devices/virtual/tty/tty51/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty51/dev', 0o644, b'4:51\n') +f('sys/devices/virtual/tty/tty51/uevent', 0o644, b'''MAJOR=4 +MINOR=51 +''') +d('sys/devices/virtual/tty/tty51/power', 0o755) +f('sys/devices/virtual/tty/tty51/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty24', 0o755) +l('sys/devices/virtual/tty/tty24/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty24/dev', 0o644, b'4:24\n') +f('sys/devices/virtual/tty/tty24/uevent', 0o644, b'''MAJOR=4 +MINOR=24 +''') +d('sys/devices/virtual/tty/tty24/power', 0o755) +f('sys/devices/virtual/tty/tty24/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty61', 0o755) +l('sys/devices/virtual/tty/tty61/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty61/dev', 0o644, b'4:61\n') +f('sys/devices/virtual/tty/tty61/uevent', 0o644, b'''MAJOR=4 +MINOR=61 +''') +d('sys/devices/virtual/tty/tty61/power', 0o755) +f('sys/devices/virtual/tty/tty61/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty40', 0o755) +l('sys/devices/virtual/tty/tty40/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty40/dev', 0o644, b'4:40\n') +f('sys/devices/virtual/tty/tty40/uevent', 0o644, b'''MAJOR=4 +MINOR=40 +''') +d('sys/devices/virtual/tty/tty40/power', 0o755) +f('sys/devices/virtual/tty/tty40/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty60', 0o755) +l('sys/devices/virtual/tty/tty60/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty60/dev', 0o644, b'4:60\n') +f('sys/devices/virtual/tty/tty60/uevent', 0o644, b'''MAJOR=4 +MINOR=60 +''') +d('sys/devices/virtual/tty/tty60/power', 0o755) +f('sys/devices/virtual/tty/tty60/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty15', 0o755) +l('sys/devices/virtual/tty/tty15/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty15/dev', 0o644, b'4:15\n') +f('sys/devices/virtual/tty/tty15/uevent', 0o644, b'''MAJOR=4 +MINOR=15 +''') +d('sys/devices/virtual/tty/tty15/power', 0o755) +f('sys/devices/virtual/tty/tty15/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty27', 0o755) +l('sys/devices/virtual/tty/tty27/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty27/dev', 0o644, b'4:27\n') +f('sys/devices/virtual/tty/tty27/uevent', 0o644, b'''MAJOR=4 +MINOR=27 +''') +d('sys/devices/virtual/tty/tty27/power', 0o755) +f('sys/devices/virtual/tty/tty27/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty7', 0o755) +l('sys/devices/virtual/tty/tty7/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty7/dev', 0o644, b'4:7\n') +f('sys/devices/virtual/tty/tty7/uevent', 0o644, b'''MAJOR=4 +MINOR=7 +''') +d('sys/devices/virtual/tty/tty7/power', 0o755) +f('sys/devices/virtual/tty/tty7/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty43', 0o755) +l('sys/devices/virtual/tty/tty43/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty43/dev', 0o644, b'4:43\n') +f('sys/devices/virtual/tty/tty43/uevent', 0o644, b'''MAJOR=4 +MINOR=43 +''') +d('sys/devices/virtual/tty/tty43/power', 0o755) +f('sys/devices/virtual/tty/tty43/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty23', 0o755) +l('sys/devices/virtual/tty/tty23/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty23/dev', 0o644, b'4:23\n') +f('sys/devices/virtual/tty/tty23/uevent', 0o644, b'''MAJOR=4 +MINOR=23 +''') +d('sys/devices/virtual/tty/tty23/power', 0o755) +f('sys/devices/virtual/tty/tty23/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty14', 0o755) +l('sys/devices/virtual/tty/tty14/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty14/dev', 0o644, b'4:14\n') +f('sys/devices/virtual/tty/tty14/uevent', 0o644, b'''MAJOR=4 +MINOR=14 +''') +d('sys/devices/virtual/tty/tty14/power', 0o755) +f('sys/devices/virtual/tty/tty14/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty56', 0o755) +l('sys/devices/virtual/tty/tty56/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty56/dev', 0o644, b'4:56\n') +f('sys/devices/virtual/tty/tty56/uevent', 0o644, b'''MAJOR=4 +MINOR=56 +''') +d('sys/devices/virtual/tty/tty56/power', 0o755) +f('sys/devices/virtual/tty/tty56/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty3', 0o755) +l('sys/devices/virtual/tty/tty3/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty3/dev', 0o644, b'4:3\n') +f('sys/devices/virtual/tty/tty3/uevent', 0o644, b'''MAJOR=4 +MINOR=3 +''') +d('sys/devices/virtual/tty/tty3/power', 0o755) +f('sys/devices/virtual/tty/tty3/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty49', 0o755) +l('sys/devices/virtual/tty/tty49/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty49/dev', 0o644, b'4:49\n') +f('sys/devices/virtual/tty/tty49/uevent', 0o644, b'''MAJOR=4 +MINOR=49 +''') +d('sys/devices/virtual/tty/tty49/power', 0o755) +f('sys/devices/virtual/tty/tty49/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty47', 0o755) +l('sys/devices/virtual/tty/tty47/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty47/dev', 0o644, b'4:47\n') +f('sys/devices/virtual/tty/tty47/uevent', 0o644, b'''MAJOR=4 +MINOR=47 +''') +d('sys/devices/virtual/tty/tty47/power', 0o755) +f('sys/devices/virtual/tty/tty47/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty57', 0o755) +l('sys/devices/virtual/tty/tty57/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty57/dev', 0o644, b'4:57\n') +f('sys/devices/virtual/tty/tty57/uevent', 0o644, b'''MAJOR=4 +MINOR=57 +''') +d('sys/devices/virtual/tty/tty57/power', 0o755) +f('sys/devices/virtual/tty/tty57/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty30', 0o755) +l('sys/devices/virtual/tty/tty30/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty30/dev', 0o644, b'4:30\n') +f('sys/devices/virtual/tty/tty30/uevent', 0o644, b'''MAJOR=4 +MINOR=30 +''') +d('sys/devices/virtual/tty/tty30/power', 0o755) +f('sys/devices/virtual/tty/tty30/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty45', 0o755) +l('sys/devices/virtual/tty/tty45/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty45/dev', 0o644, b'4:45\n') +f('sys/devices/virtual/tty/tty45/uevent', 0o644, b'''MAJOR=4 +MINOR=45 +''') +d('sys/devices/virtual/tty/tty45/power', 0o755) +f('sys/devices/virtual/tty/tty45/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty22', 0o755) +l('sys/devices/virtual/tty/tty22/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty22/dev', 0o644, b'4:22\n') +f('sys/devices/virtual/tty/tty22/uevent', 0o644, b'''MAJOR=4 +MINOR=22 +''') +d('sys/devices/virtual/tty/tty22/power', 0o755) +f('sys/devices/virtual/tty/tty22/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty55', 0o755) +l('sys/devices/virtual/tty/tty55/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty55/dev', 0o644, b'4:55\n') +f('sys/devices/virtual/tty/tty55/uevent', 0o644, b'''MAJOR=4 +MINOR=55 +''') +d('sys/devices/virtual/tty/tty55/power', 0o755) +f('sys/devices/virtual/tty/tty55/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty11', 0o755) +l('sys/devices/virtual/tty/tty11/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty11/dev', 0o644, b'4:11\n') +f('sys/devices/virtual/tty/tty11/uevent', 0o644, b'''MAJOR=4 +MINOR=11 +''') +d('sys/devices/virtual/tty/tty11/power', 0o755) +f('sys/devices/virtual/tty/tty11/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty53', 0o755) +l('sys/devices/virtual/tty/tty53/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty53/dev', 0o644, b'4:53\n') +f('sys/devices/virtual/tty/tty53/uevent', 0o644, b'''MAJOR=4 +MINOR=53 +''') +d('sys/devices/virtual/tty/tty53/power', 0o755) +f('sys/devices/virtual/tty/tty53/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty12', 0o755) +l('sys/devices/virtual/tty/tty12/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty12/dev', 0o644, b'4:12\n') +f('sys/devices/virtual/tty/tty12/uevent', 0o644, b'''MAJOR=4 +MINOR=12 +''') +d('sys/devices/virtual/tty/tty12/power', 0o755) +f('sys/devices/virtual/tty/tty12/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty28', 0o755) +l('sys/devices/virtual/tty/tty28/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty28/dev', 0o644, b'4:28\n') +f('sys/devices/virtual/tty/tty28/uevent', 0o644, b'''MAJOR=4 +MINOR=28 +''') +d('sys/devices/virtual/tty/tty28/power', 0o755) +f('sys/devices/virtual/tty/tty28/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty58', 0o755) +l('sys/devices/virtual/tty/tty58/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty58/dev', 0o644, b'4:58\n') +f('sys/devices/virtual/tty/tty58/uevent', 0o644, b'''MAJOR=4 +MINOR=58 +''') +d('sys/devices/virtual/tty/tty58/power', 0o755) +f('sys/devices/virtual/tty/tty58/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty32', 0o755) +l('sys/devices/virtual/tty/tty32/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty32/dev', 0o644, b'4:32\n') +f('sys/devices/virtual/tty/tty32/uevent', 0o644, b'''MAJOR=4 +MINOR=32 +''') +d('sys/devices/virtual/tty/tty32/power', 0o755) +f('sys/devices/virtual/tty/tty32/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty44', 0o755) +l('sys/devices/virtual/tty/tty44/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty44/dev', 0o644, b'4:44\n') +f('sys/devices/virtual/tty/tty44/uevent', 0o644, b'''MAJOR=4 +MINOR=44 +''') +d('sys/devices/virtual/tty/tty44/power', 0o755) +f('sys/devices/virtual/tty/tty44/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty6', 0o755) +l('sys/devices/virtual/tty/tty6/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty6/dev', 0o644, b'4:6\n') +f('sys/devices/virtual/tty/tty6/uevent', 0o644, b'''MAJOR=4 +MINOR=6 +''') +d('sys/devices/virtual/tty/tty6/power', 0o755) +f('sys/devices/virtual/tty/tty6/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty9', 0o755) +l('sys/devices/virtual/tty/tty9/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty9/dev', 0o644, b'4:9\n') +f('sys/devices/virtual/tty/tty9/uevent', 0o644, b'''MAJOR=4 +MINOR=9 +''') +d('sys/devices/virtual/tty/tty9/power', 0o755) +f('sys/devices/virtual/tty/tty9/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty26', 0o755) +l('sys/devices/virtual/tty/tty26/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty26/dev', 0o644, b'4:26\n') +f('sys/devices/virtual/tty/tty26/uevent', 0o644, b'''MAJOR=4 +MINOR=26 +''') +d('sys/devices/virtual/tty/tty26/power', 0o755) +f('sys/devices/virtual/tty/tty26/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty10', 0o755) +l('sys/devices/virtual/tty/tty10/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty10/dev', 0o644, b'4:10\n') +f('sys/devices/virtual/tty/tty10/uevent', 0o644, b'''MAJOR=4 +MINOR=10 +''') +d('sys/devices/virtual/tty/tty10/power', 0o755) +f('sys/devices/virtual/tty/tty10/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty39', 0o755) +l('sys/devices/virtual/tty/tty39/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty39/dev', 0o644, b'4:39\n') +f('sys/devices/virtual/tty/tty39/uevent', 0o644, b'''MAJOR=4 +MINOR=39 +''') +d('sys/devices/virtual/tty/tty39/power', 0o755) +f('sys/devices/virtual/tty/tty39/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty0', 0o755) +l('sys/devices/virtual/tty/tty0/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty0/dev', 0o644, b'4:0\n') +f('sys/devices/virtual/tty/tty0/uevent', 0o644, b'''MAJOR=4 +MINOR=0 +DEVNAME=tty0 +''') +d('sys/devices/virtual/tty/tty0/power', 0o755) +f('sys/devices/virtual/tty/tty0/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty36', 0o755) +l('sys/devices/virtual/tty/tty36/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty36/dev', 0o644, b'4:36\n') +f('sys/devices/virtual/tty/tty36/uevent', 0o644, b'''MAJOR=4 +MINOR=36 +''') +d('sys/devices/virtual/tty/tty36/power', 0o755) +f('sys/devices/virtual/tty/tty36/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty34', 0o755) +l('sys/devices/virtual/tty/tty34/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty34/dev', 0o644, b'4:34\n') +f('sys/devices/virtual/tty/tty34/uevent', 0o644, b'''MAJOR=4 +MINOR=34 +''') +d('sys/devices/virtual/tty/tty34/power', 0o755) +f('sys/devices/virtual/tty/tty34/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty16', 0o755) +l('sys/devices/virtual/tty/tty16/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty16/dev', 0o644, b'4:16\n') +f('sys/devices/virtual/tty/tty16/uevent', 0o644, b'''MAJOR=4 +MINOR=16 +''') +d('sys/devices/virtual/tty/tty16/power', 0o755) +f('sys/devices/virtual/tty/tty16/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty25', 0o755) +l('sys/devices/virtual/tty/tty25/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty25/dev', 0o644, b'4:25\n') +f('sys/devices/virtual/tty/tty25/uevent', 0o644, b'''MAJOR=4 +MINOR=25 +''') +d('sys/devices/virtual/tty/tty25/power', 0o755) +f('sys/devices/virtual/tty/tty25/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty13', 0o755) +l('sys/devices/virtual/tty/tty13/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty13/dev', 0o644, b'4:13\n') +f('sys/devices/virtual/tty/tty13/uevent', 0o644, b'''MAJOR=4 +MINOR=13 +''') +d('sys/devices/virtual/tty/tty13/power', 0o755) +f('sys/devices/virtual/tty/tty13/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty52', 0o755) +l('sys/devices/virtual/tty/tty52/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty52/dev', 0o644, b'4:52\n') +f('sys/devices/virtual/tty/tty52/uevent', 0o644, b'''MAJOR=4 +MINOR=52 +''') +d('sys/devices/virtual/tty/tty52/power', 0o755) +f('sys/devices/virtual/tty/tty52/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty31', 0o755) +l('sys/devices/virtual/tty/tty31/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty31/dev', 0o644, b'4:31\n') +f('sys/devices/virtual/tty/tty31/uevent', 0o644, b'''MAJOR=4 +MINOR=31 +''') +d('sys/devices/virtual/tty/tty31/power', 0o755) +f('sys/devices/virtual/tty/tty31/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty35', 0o755) +l('sys/devices/virtual/tty/tty35/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty35/dev', 0o644, b'4:35\n') +f('sys/devices/virtual/tty/tty35/uevent', 0o644, b'''MAJOR=4 +MINOR=35 +''') +d('sys/devices/virtual/tty/tty35/power', 0o755) +f('sys/devices/virtual/tty/tty35/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty54', 0o755) +l('sys/devices/virtual/tty/tty54/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty54/dev', 0o644, b'4:54\n') +f('sys/devices/virtual/tty/tty54/uevent', 0o644, b'''MAJOR=4 +MINOR=54 +''') +d('sys/devices/virtual/tty/tty54/power', 0o755) +f('sys/devices/virtual/tty/tty54/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty63', 0o755) +l('sys/devices/virtual/tty/tty63/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty63/dev', 0o644, b'4:63\n') +f('sys/devices/virtual/tty/tty63/uevent', 0o644, b'''MAJOR=4 +MINOR=63 +''') +d('sys/devices/virtual/tty/tty63/power', 0o755) +f('sys/devices/virtual/tty/tty63/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty1', 0o755) +l('sys/devices/virtual/tty/tty1/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty1/dev', 0o644, b'4:1\n') +f('sys/devices/virtual/tty/tty1/uevent', 0o644, b'''MAJOR=4 +MINOR=1 +''') +d('sys/devices/virtual/tty/tty1/power', 0o755) +f('sys/devices/virtual/tty/tty1/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty33', 0o755) +l('sys/devices/virtual/tty/tty33/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty33/dev', 0o644, b'4:33\n') +f('sys/devices/virtual/tty/tty33/uevent', 0o644, b'''MAJOR=4 +MINOR=33 +DEVNAME=tty33 +''') +d('sys/devices/virtual/tty/tty33/power', 0o755) +f('sys/devices/virtual/tty/tty33/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty18', 0o755) +l('sys/devices/virtual/tty/tty18/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty18/dev', 0o644, b'4:18\n') +f('sys/devices/virtual/tty/tty18/uevent', 0o644, b'''MAJOR=4 +MINOR=18 +''') +d('sys/devices/virtual/tty/tty18/power', 0o755) +f('sys/devices/virtual/tty/tty18/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty42', 0o755) +l('sys/devices/virtual/tty/tty42/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty42/dev', 0o644, b'4:42\n') +f('sys/devices/virtual/tty/tty42/uevent', 0o644, b'''MAJOR=4 +MINOR=42 +''') +d('sys/devices/virtual/tty/tty42/power', 0o755) +f('sys/devices/virtual/tty/tty42/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty8', 0o755) +l('sys/devices/virtual/tty/tty8/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty8/dev', 0o644, b'4:8\n') +f('sys/devices/virtual/tty/tty8/uevent', 0o644, b'''MAJOR=4 +MINOR=8 +''') +d('sys/devices/virtual/tty/tty8/power', 0o755) +f('sys/devices/virtual/tty/tty8/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty37', 0o755) +l('sys/devices/virtual/tty/tty37/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty37/dev', 0o644, b'4:37\n') +f('sys/devices/virtual/tty/tty37/uevent', 0o644, b'''MAJOR=4 +MINOR=37 +''') +d('sys/devices/virtual/tty/tty37/power', 0o755) +f('sys/devices/virtual/tty/tty37/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty5', 0o755) +l('sys/devices/virtual/tty/tty5/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty5/dev', 0o644, b'4:5\n') +f('sys/devices/virtual/tty/tty5/uevent', 0o644, b'''MAJOR=4 +MINOR=5 +''') +d('sys/devices/virtual/tty/tty5/power', 0o755) +f('sys/devices/virtual/tty/tty5/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty48', 0o755) +l('sys/devices/virtual/tty/tty48/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty48/dev', 0o644, b'4:48\n') +f('sys/devices/virtual/tty/tty48/uevent', 0o644, b'''MAJOR=4 +MINOR=48 +''') +d('sys/devices/virtual/tty/tty48/power', 0o755) +f('sys/devices/virtual/tty/tty48/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty17', 0o755) +l('sys/devices/virtual/tty/tty17/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty17/dev', 0o644, b'4:17\n') +f('sys/devices/virtual/tty/tty17/uevent', 0o644, b'''MAJOR=4 +MINOR=17 +''') +d('sys/devices/virtual/tty/tty17/power', 0o755) +f('sys/devices/virtual/tty/tty17/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty62', 0o755) +l('sys/devices/virtual/tty/tty62/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty62/dev', 0o644, b'4:62\n') +f('sys/devices/virtual/tty/tty62/uevent', 0o644, b'''MAJOR=4 +MINOR=62 +''') +d('sys/devices/virtual/tty/tty62/power', 0o755) +f('sys/devices/virtual/tty/tty62/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty59', 0o755) +l('sys/devices/virtual/tty/tty59/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty59/dev', 0o644, b'4:59\n') +f('sys/devices/virtual/tty/tty59/uevent', 0o644, b'''MAJOR=4 +MINOR=59 +''') +d('sys/devices/virtual/tty/tty59/power', 0o755) +f('sys/devices/virtual/tty/tty59/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty50', 0o755) +l('sys/devices/virtual/tty/tty50/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty50/dev', 0o644, b'4:50\n') +f('sys/devices/virtual/tty/tty50/uevent', 0o644, b'''MAJOR=4 +MINOR=50 +''') +d('sys/devices/virtual/tty/tty50/power', 0o755) +f('sys/devices/virtual/tty/tty50/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty21', 0o755) +l('sys/devices/virtual/tty/tty21/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty21/dev', 0o644, b'4:21\n') +f('sys/devices/virtual/tty/tty21/uevent', 0o644, b'''MAJOR=4 +MINOR=21 +''') +d('sys/devices/virtual/tty/tty21/power', 0o755) +f('sys/devices/virtual/tty/tty21/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty19', 0o755) +l('sys/devices/virtual/tty/tty19/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty19/dev', 0o644, b'4:19\n') +f('sys/devices/virtual/tty/tty19/uevent', 0o644, b'''MAJOR=4 +MINOR=19 +''') +d('sys/devices/virtual/tty/tty19/power', 0o755) +f('sys/devices/virtual/tty/tty19/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/ptmx', 0o755) +l('sys/devices/virtual/tty/ptmx/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/ptmx/dev', 0o644, b'5:2\n') +f('sys/devices/virtual/tty/ptmx/uevent', 0o644, b'''MAJOR=5 +MINOR=2 +''') +d('sys/devices/virtual/tty/ptmx/power', 0o755) +f('sys/devices/virtual/tty/ptmx/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty46', 0o755) +l('sys/devices/virtual/tty/tty46/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty46/dev', 0o644, b'4:46\n') +f('sys/devices/virtual/tty/tty46/uevent', 0o644, b'''MAJOR=4 +MINOR=46 +''') +d('sys/devices/virtual/tty/tty46/power', 0o755) +f('sys/devices/virtual/tty/tty46/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty2', 0o755) +l('sys/devices/virtual/tty/tty2/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty2/dev', 0o644, b'4:2\n') +f('sys/devices/virtual/tty/tty2/uevent', 0o644, b'''MAJOR=4 +MINOR=2 +''') +d('sys/devices/virtual/tty/tty2/power', 0o755) +f('sys/devices/virtual/tty/tty2/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/console', 0o755) +l('sys/devices/virtual/tty/console/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/console/dev', 0o644, b'5:1\n') +f('sys/devices/virtual/tty/console/uevent', 0o644, b'''MAJOR=5 +MINOR=1 +DEVNAME=console +''') +d('sys/devices/virtual/tty/console/power', 0o755) +f('sys/devices/virtual/tty/console/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty41', 0o755) +l('sys/devices/virtual/tty/tty41/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty41/dev', 0o644, b'4:41\n') +f('sys/devices/virtual/tty/tty41/uevent', 0o644, b'''MAJOR=4 +MINOR=41 +''') +d('sys/devices/virtual/tty/tty41/power', 0o755) +f('sys/devices/virtual/tty/tty41/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty4', 0o755) +l('sys/devices/virtual/tty/tty4/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty4/dev', 0o644, b'4:4\n') +f('sys/devices/virtual/tty/tty4/uevent', 0o644, b'''MAJOR=4 +MINOR=4 +''') +d('sys/devices/virtual/tty/tty4/power', 0o755) +f('sys/devices/virtual/tty/tty4/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty29', 0o755) +l('sys/devices/virtual/tty/tty29/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty29/dev', 0o644, b'4:29\n') +f('sys/devices/virtual/tty/tty29/uevent', 0o644, b'''MAJOR=4 +MINOR=29 +''') +d('sys/devices/virtual/tty/tty29/power', 0o755) +f('sys/devices/virtual/tty/tty29/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty', 0o755) +l('sys/devices/virtual/tty/tty/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty/dev', 0o644, b'5:0\n') +f('sys/devices/virtual/tty/tty/uevent', 0o644, b'''MAJOR=5 +MINOR=0 +''') +d('sys/devices/virtual/tty/tty/power', 0o755) +f('sys/devices/virtual/tty/tty/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty38', 0o755) +l('sys/devices/virtual/tty/tty38/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty38/dev', 0o644, b'4:38\n') +f('sys/devices/virtual/tty/tty38/uevent', 0o644, b'''MAJOR=4 +MINOR=38 +''') +d('sys/devices/virtual/tty/tty38/power', 0o755) +f('sys/devices/virtual/tty/tty38/power/wakeup', 0o644, b'\n') +d('sys/devices/virtual/tty/tty20', 0o755) +l('sys/devices/virtual/tty/tty20/subsystem', '../../../../class/tty') +f('sys/devices/virtual/tty/tty20/dev', 0o644, b'4:20\n') +f('sys/devices/virtual/tty/tty20/uevent', 0o644, b'''MAJOR=4 +MINOR=20 +''') +d('sys/devices/virtual/tty/tty20/power', 0o755) +f('sys/devices/virtual/tty/tty20/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00', 0o755) +l('sys/devices/LNXSYSTM:00/subsystem', '../../bus/acpi') +f('sys/devices/LNXSYSTM:00/hid', 0o644, b'LNXSYSTM\n') +f('sys/devices/LNXSYSTM:00/modalias', 0o644, b'acpi:LNXSYSTM:\n') +f('sys/devices/LNXSYSTM:00/path', 0o644, b'\\\n') +f('sys/devices/LNXSYSTM:00/uevent', 0o644, b'MODALIAS=acpi:LNXSYSTM:\n') +d('sys/devices/LNXSYSTM:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/ACPI0007:01', 0o755) +l('sys/devices/LNXSYSTM:00/ACPI0007:01/thermal_cooling', '../../virtual/thermal/cooling_device1') +l('sys/devices/LNXSYSTM:00/ACPI0007:01/subsystem', '../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/ACPI0007:01/sysdev', '../../system/cpu/cpu1') +l('sys/devices/LNXSYSTM:00/ACPI0007:01/driver', '../../../bus/acpi/drivers/processor') +f('sys/devices/LNXSYSTM:00/ACPI0007:01/hid', 0o644, b'ACPI0007\n') +f('sys/devices/LNXSYSTM:00/ACPI0007:01/modalias', 0o644, b'acpi:ACPI0007:\n') +f('sys/devices/LNXSYSTM:00/ACPI0007:01/path', 0o644, b'\\_PR_.CPU1\n') +f('sys/devices/LNXSYSTM:00/ACPI0007:01/uevent', 0o644, b'''DRIVER=processor +MODALIAS=acpi:ACPI0007: +''') +d('sys/devices/LNXSYSTM:00/ACPI0007:01/power', 0o755) +f('sys/devices/LNXSYSTM:00/ACPI0007:01/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/LNXTHERM:00', 0o755) +l('sys/devices/LNXSYSTM:00/LNXTHERM:00/subsystem', '../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/hid', 0o644, b'LNXTHERM\n') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/modalias', 0o644, b'acpi:LNXTHERM:\n') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/path', 0o644, b'\\_TZ_\n') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/uevent', 0o644, b'MODALIAS=acpi:LNXTHERM:\n') +d('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01', 0o755) +l('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01/thermal_zone', '../../../virtual/thermal/thermal_zone0') +l('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01/driver', '../../../../bus/acpi/drivers/thermal') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01/hid', 0o644, b'LNXTHERM\n') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01/modalias', 0o644, b'acpi:LNXTHERM:\n') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01/path', 0o644, b'\\_TZ_.THM0\n') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01/uevent', 0o644, b'''DRIVER=thermal +MODALIAS=acpi:LNXTHERM: +''') +d('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01/power', 0o755) +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:01/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/LNXTHERM:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02', 0o755) +l('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02/thermal_zone', '../../../virtual/thermal/thermal_zone1') +l('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02/driver', '../../../../bus/acpi/drivers/thermal') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02/hid', 0o644, b'LNXTHERM\n') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02/modalias', 0o644, b'acpi:LNXTHERM:\n') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02/path', 0o644, b'\\_TZ_.THM1\n') +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02/uevent', 0o644, b'''DRIVER=thermal +MODALIAS=acpi:LNXTHERM: +''') +d('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02/power', 0o755) +f('sys/devices/LNXSYSTM:00/LNXTHERM:00/LNXTHERM:02/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/subsystem', '../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/path', 0o644, b'\\_SB_\n') +f('sys/devices/LNXSYSTM:00/device:00/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:05', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:05/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:05/driver', '../../../../bus/acpi/drivers/pci_link') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:05/hid', 0o644, b'PNP0C0F\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:05/modalias', 0o644, b'acpi:PNP0C0F:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:05/path', 0o644, b'\\_SB_.LNKF\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:05/uevent', 0o644, b'''DRIVER=pci_link +MODALIAS=acpi:PNP0C0F: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:05/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:05/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/driver', '../../../../bus/acpi/drivers/button') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/hid', 0o644, b'PNP0C0E\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/modalias', 0o644, b'acpi:PNP0C0E:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/path', 0o644, b'\\_SB_.SLPB\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/uevent', 0o644, b'''DRIVER=button +MODALIAS=acpi:PNP0C0E: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input', 0o755) +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/subsystem', '../../../../../../class/input') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/device', '../../../PNP0C0E:00') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/uniq', 0o644, b'\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/phys', 0o644, b'PNP0C0E/button/input0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/modalias', 0o644, b'input:b0019v0000p0003e0000-e0,1,k8E,ramlsfw\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/name', 0o644, b'Sleep Button (CM)\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/uevent', 0o644, b'''PRODUCT=19/0/3/0 +NAME="Sleep Button (CM)" +PHYS="PNP0C0E/button/input0" +EV==3 +KEY==4000 0 0 +MODALIAS=input:b0019v0000p0003e0000-e0,1,k8E,ramlsfw +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/id', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/id/version', 0o644, b'0000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/id/product', 0o644, b'0003\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/id/vendor', 0o644, b'0000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/id/bustype', 0o644, b'0019\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/event5', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/event5/subsystem', '../../../../../../../class/input') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/event5/device', '../../input5') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/event5/dev', 0o644, b'13:69\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/event5/uevent', 0o644, b'''MAJOR=13 +MINOR=69 +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/event5/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/event5/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/capabilities', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/capabilities/msc', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/capabilities/abs', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/capabilities/snd', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/capabilities/ff', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/capabilities/key', 0o644, b'4000 0 0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/capabilities/rel', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/capabilities/sw', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/capabilities/ev', 0o644, b'3\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0E:00/input/input5/capabilities/led', 0o644, b'0\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/physical_node', '../../../pci0000:00') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/driver', '../../../../bus/acpi/drivers/pci_root') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/hid', 0o644, b'PNP0A08\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/modalias', 0o644, b'acpi:PNP0A08:PNP0A03:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/path', 0o644, b'\\_SB_.PCI0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/uevent', 0o644, b'''DRIVER=pci_root +MODALIAS=acpi:PNP0A08:PNP0A03: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/physical_node', '../../../../pci0000:00/0000:00:1e.0') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/path', 0o644, b'\\_SB_.PCI0.PCI1\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/device:12', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/device:12/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/device:12/physical_node', '../../../../../pci0000:00/0000:00:1e.0/0000:15:00.0') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/device:12/path', 0o644, b'\\_SB_.PCI0.PCI1.CDBS\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/device:12/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/device:12/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:11/device:12/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/physical_node', '../../../../pci0000:00/0000:00:1d.7') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/path', 0o644, b'\\_SB_.PCI0.USB7\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/path', 0o644, b'\\_SB_.PCI0.USB7.URTH\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:23', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:23/subsystem', '../../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:23/path', 0o644, b'\\_SB_.PCI0.USB7.URTH.UPDK\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:23/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:23/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:23/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:24', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:24/subsystem', '../../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:24/path', 0o644, b'\\_SB_.PCI0.USB7.URTH.UPEX\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:24/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:24/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:21/device:22/device:24/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0b', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0b/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0b/physical_node', '../../../../pci0000:00/0000:00:1c.0') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0b/path', 0o644, b'\\_SB_.PCI0.EXP0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0b/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0b/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0b/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/physical_node', '../../../../pci0000:00/0000:00:01.0') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/path', 0o644, b'\\_SB_.PCI0.AGP_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/physical_node', '../../../../../pci0000:00/0000:00:01.0/0000:01:00.0') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/modalias', 0o644, b'acpi:LNXVIDEO:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/path', 0o644, b'\\_SB_.PCI0.AGP_.VID_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/uevent', 0o644, b'MODALIAS=acpi:LNXVIDEO:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:08', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:08/subsystem', '../../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:08/path', 0o644, b'\\_SB_.PCI0.AGP_.VID_.LCD0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:08/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:08/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:08/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:09', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:09/subsystem', '../../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:09/path', 0o644, b'\\_SB_.PCI0.AGP_.VID_.CRT0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:09/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:09/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:09/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:0a', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:0a/subsystem', '../../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:0a/path', 0o644, b'\\_SB_.PCI0.AGP_.VID_.DVI0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:0a/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:0a/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:06/device:07/device:0a/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:18', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:18/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:18/physical_node', '../../../../pci0000:00/0000:00:1f.3') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:18/path', 0o644, b'\\_SB_.PCI0.SMBU\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:18/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:18/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:18/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c/physical_node', '../../../../pci0000:00/0000:00:1c.1') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c/path', 0o644, b'\\_SB_.PCI0.EXP1\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/subsystem', '../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/modalias', 0o644, b'acpi:LNXVIDEO:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/path', 0o644, b'\\_SB_.PCI0.VID_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/uevent', 0o644, b'MODALIAS=acpi:LNXVIDEO:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:04', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:04/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:04/path', 0o644, b'\\_SB_.PCI0.VID_.CRT0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:04/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:04/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:04/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:05', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:05/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:05/path', 0o644, b'\\_SB_.PCI0.VID_.DVI0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:05/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:05/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:05/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:03', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:03/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:03/path', 0o644, b'\\_SB_.PCI0.VID_.LCD0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:03/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:03/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:02/device:03/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/physical_node', '../../../../pci0000:00/0000:00:1f.1') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/path', 0o644, b'\\_SB_.PCI0.IDE0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/path', 0o644, b'\\_SB_.PCI0.IDE0.PRIM\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/device:15', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/device:15/subsystem', '../../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/device:15/modalias', 0o644, b'acpi:LNXIOBAY:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/device:15/path', 0o644, b'\\_SB_.PCI0.IDE0.PRIM.MSTR\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/device:15/uevent', 0o644, b'MODALIAS=acpi:LNXIOBAY:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/device:15/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:13/device:14/device:15/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/physical_node', '../../../../pci0000:00/0000:00:1d.2') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/path', 0o644, b'\\_SB_.PCI0.USB2\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/path', 0o644, b'\\_SB_.PCI0.USB2.URTH\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/device:1f', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/device:1f/subsystem', '../../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/device:1f/path', 0o644, b'\\_SB_.PCI0.USB2.URTH.UPDK\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/device:1f/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/device:1f/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/device:1f/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1d/device:1e/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:19', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:19/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:19/physical_node', '../../../../pci0000:00/0000:00:1d.0') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:19/path', 0o644, b'\\_SB_.PCI0.USB0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:19/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:19/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:19/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/physical_node', '../../../../pci0000:00/0000:00:1d.1') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/path', 0o644, b'\\_SB_.PCI0.USB1\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/path', 0o644, b'\\_SB_.PCI0.USB1.URTH\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/device:1c', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/device:1c/subsystem', '../../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/device:1c/path', 0o644, b'\\_SB_.PCI0.USB1.URTH.UPEX\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/device:1c/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/device:1c/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/device:1c/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:1a/device:1b/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/physical_node', '../../../../pci0000:00/0000:00:1c.2') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/path', 0o644, b'\\_SB_.PCI0.EXP2\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/device:0e', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/device:0e/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/device:0e/path', 0o644, b'\\_SB_.PCI0.EXP2.EXUP\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/device:0e/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/device:0e/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/device:0e/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0d/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:25', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:25/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:25/physical_node', '../../../../pci0000:00/0000:00:1b.0') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:25/path', 0o644, b'\\_SB_.PCI0.HDEF\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:25/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:25/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:25/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/physical_node', '../../../../pci0000:00/0000:00:1f.0') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/path', 0o644, b'\\_SB_.PCI0.LPC_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0000:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0000:00/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0000:00/hid', 0o644, b'PNP0000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0000:00/modalias', 0o644, b'acpi:PNP0000:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0000:00/path', 0o644, b'\\_SB_.PCI0.LPC_.PIC_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0000:00/uevent', 0o644, b'MODALIAS=acpi:PNP0000:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0000:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0000:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00/physical_node', '../../../../../pnp0/00:03') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00/hid', 0o644, b'PNP0103\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00/modalias', 0o644, b'acpi:PNP0103:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00/path', 0o644, b'\\_SB_.PCI0.LPC_.HPET\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00/uevent', 0o644, b'MODALIAS=acpi:PNP0103:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0103:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00/physical_node', '../../../../../pnp0/00:0a') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00/hid', 0o644, b'ATM1200\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00/modalias', 0o644, b'acpi:ATM1200:PNP0C31:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00/path', 0o644, b'\\_SB_.PCI0.LPC_.TPM_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00/uevent', 0o644, b'MODALIAS=acpi:ATM1200:PNP0C31:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/ATM1200:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00/physical_node', '../../../../../pnp0/00:08') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00/hid', 0o644, b'PNP0303\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00/modalias', 0o644, b'acpi:PNP0303:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00/path', 0o644, b'\\_SB_.PCI0.LPC_.KBD_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00/uevent', 0o644, b'MODALIAS=acpi:PNP0303:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0303:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00/physical_node', '../../../../../pnp0/00:06') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00/hid', 0o644, b'PNP0C04\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00/modalias', 0o644, b'acpi:PNP0C04:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00/path', 0o644, b'\\_SB_.PCI0.LPC_.FPU_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00/uevent', 0o644, b'MODALIAS=acpi:PNP0C04:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C04:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00/physical_node', '../../../../../pnp0/00:05') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00/hid', 0o644, b'PNP0800\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00/modalias', 0o644, b'acpi:PNP0800:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00/path', 0o644, b'\\_SB_.PCI0.LPC_.SPKR\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00/uevent', 0o644, b'MODALIAS=acpi:PNP0800:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0800:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00/physical_node', '../../../../../pnp0/00:02') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00/hid', 0o644, b'PNP0C02\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00/modalias', 0o644, b'acpi:PNP0C02:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00/path', 0o644, b'\\_SB_.PCI0.LPC_.SIO_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00/uevent', 0o644, b'MODALIAS=acpi:PNP0C02:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C02:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0100:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0100:00/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0100:00/hid', 0o644, b'PNP0100\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0100:00/modalias', 0o644, b'acpi:PNP0100:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0100:00/path', 0o644, b'\\_SB_.PCI0.LPC_.TIMR\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0100:00/uevent', 0o644, b'MODALIAS=acpi:PNP0100:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0100:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0100:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/driver', '../../../../../../bus/acpi/drivers/ec') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/hid', 0o644, b'PNP0C09\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/modalias', 0o644, b'acpi:PNP0C09:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/path', 0o644, b'\\_SB_.PCI0.LPC_.EC__\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/uevent', 0o644, b'''DRIVER=ec +MODALIAS=acpi:PNP0C09: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00/subsystem', '../../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00/driver', '../../../../../../../bus/acpi/drivers/power') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00/hid', 0o644, b'LNXPOWER\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00/modalias', 0o644, b'acpi:LNXPOWER:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00/path', 0o644, b'\\_SB_.PCI0.LPC_.EC__.PUBS\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00/uevent', 0o644, b'''DRIVER=power +MODALIAS=acpi:LNXPOWER: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/LNXPOWER:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/subsystem', '../../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/driver', '../../../../../../../bus/acpi/drivers/ac') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/hid', 0o644, b'ACPI0003\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/modalias', 0o644, b'acpi:ACPI0003:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/path', 0o644, b'\\_SB_.PCI0.LPC_.EC__.AC__\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/uevent', 0o644, b'''DRIVER=ac +MODALIAS=acpi:ACPI0003: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power_supply', 0o755) +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power_supply/AC', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power_supply/AC/subsystem', '../../../../../../../../../class/power_supply') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power_supply/AC/device', '../../../ACPI0003:00') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power_supply/AC/type', 0o644, b'Mains\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power_supply/AC/online', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power_supply/AC/uevent', 0o644, b'''POWER_SUPPLY_NAME=AC +POWER_SUPPLY_TYPE=Mains +POWER_SUPPLY_ONLINE=0 +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power_supply/AC/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/subsystem', '../../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/driver', '../../../../../../../bus/acpi/drivers/battery') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/hid', 0o644, b'PNP0C0A\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/modalias', 0o644, b'acpi:PNP0C0A:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/path', 0o644, b'\\_SB_.PCI0.LPC_.EC__.BAT0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/uevent', 0o644, b'''DRIVER=battery +MODALIAS=acpi:PNP0C0A: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply', 0o755) +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/subsystem', '../../../../../../../../../class/power_supply') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/device', '../../../PNP0C0A:00') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/model_name', 0o644, b'42T5245\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/voltage_min_design', 0o644, b'10800000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/type', 0o644, b'Battery\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/current_now', 0o644, b'25830000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_now', 0o644, b'59980000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/technology', 0o644, b'Li-ion\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/voltage_now', 0o644, b'12207000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_full_design', 0o644, b'84240000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/serial_number', 0o644, b' 6463\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/present', 0o644, b'1\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/alarm', 0o644, b'3075000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/uevent', 0o644, b'''POWER_SUPPLY_NAME=BAT0 +POWER_SUPPLY_TYPE=Battery +POWER_SUPPLY_STATUS=Discharging +POWER_SUPPLY_PRESENT=1 +POWER_SUPPLY_TECHNOLOGY=Li-ion +POWER_SUPPLY_VOLTAGE_MIN_DESIGN=10800000 +POWER_SUPPLY_VOLTAGE_NOW=12207000 +POWER_SUPPLY_CURRENT_NOW=25830000 +POWER_SUPPLY_ENERGY_FULL_DESIGN=84240000 +POWER_SUPPLY_ENERGY_FULL=61510000 +POWER_SUPPLY_ENERGY_NOW=59980000 +POWER_SUPPLY_MODEL_NAME=42T5245 +POWER_SUPPLY_MANUFACTURER=SANYO +POWER_SUPPLY_SERIAL_NUMBER= 6463 +''') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/manufacturer', 0o644, b'SANYO\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_full', 0o644, b'61510000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/status', 0o644, b'Discharging\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00/subsystem', '../../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00/driver', '../../../../../../../bus/acpi/drivers/thinkpad_hotkey') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00/hid', 0o644, b'IBM0068\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00/modalias', 0o644, b'acpi:IBM0068:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00/path', 0o644, b'\\_SB_.PCI0.LPC_.EC__.HKEY\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00/uevent', 0o644, b'''DRIVER=thinkpad_hotkey +MODALIAS=acpi:IBM0068: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0C09:00/IBM0068:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00/physical_node', '../../../../../pnp0/00:04') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00/hid', 0o644, b'PNP0200\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00/modalias', 0o644, b'acpi:PNP0200:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00/path', 0o644, b'\\_SB_.PCI0.LPC_.DMAC\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00/uevent', 0o644, b'MODALIAS=acpi:PNP0200:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0200:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00/physical_node', '../../../../../pnp0/00:09') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00/hid', 0o644, b'IBM0057\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00/modalias', 0o644, b'acpi:IBM0057:PNP0F13:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00/path', 0o644, b'\\_SB_.PCI0.LPC_.MOU_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00/uevent', 0o644, b'MODALIAS=acpi:IBM0057:PNP0F13:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/IBM0057:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00/subsystem', '../../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00/physical_node', '../../../../../pnp0/00:07') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00/hid', 0o644, b'PNP0B00\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00/modalias', 0o644, b'acpi:PNP0B00:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00/path', 0o644, b'\\_SB_.PCI0.LPC_.RTC_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00/uevent', 0o644, b'MODALIAS=acpi:PNP0B00:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:01/PNP0B00:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:20', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:20/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:20/physical_node', '../../../../pci0000:00/0000:00:1d.3') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:20/path', 0o644, b'\\_SB_.PCI0.USB3\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:20/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:20/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:20/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/physical_node', '../../../../pci0000:00/0000:00:1c.3') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/path', 0o644, b'\\_SB_.PCI0.EXP3\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/device:10', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/device:10/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/device:10/path', 0o644, b'\\_SB_.PCI0.EXP3.EXPD\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/device:10/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/device:10/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0f/device:10/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/subsystem', '../../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/physical_node', '../../../../pci0000:00/0000:00:1f.2') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/path', 0o644, b'\\_SB_.PCI0.SATA\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/device:17', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/device:17/subsystem', '../../../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/device:17/path', 0o644, b'\\_SB_.PCI0.SATA.PRT0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/device:17/uevent', 0o644, b'') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/device:17/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/device:17/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:16/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/IBM0079:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/IBM0079:00/subsystem', '../../../../bus/acpi') +f('sys/devices/LNXSYSTM:00/device:00/IBM0079:00/hid', 0o644, b'IBM0079\n') +f('sys/devices/LNXSYSTM:00/device:00/IBM0079:00/modalias', 0o644, b'acpi:IBM0079:PNP0C15:LNXDOCK:\n') +f('sys/devices/LNXSYSTM:00/device:00/IBM0079:00/path', 0o644, b'\\_SB_.GDCK\n') +f('sys/devices/LNXSYSTM:00/device:00/IBM0079:00/uevent', 0o644, b'MODALIAS=acpi:IBM0079:PNP0C15:LNXDOCK:\n') +d('sys/devices/LNXSYSTM:00/device:00/IBM0079:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/IBM0079:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/driver', '../../../../bus/acpi/drivers/button') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/hid', 0o644, b'PNP0C0D\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/modalias', 0o644, b'acpi:PNP0C0D:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/path', 0o644, b'\\_SB_.LID_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/uevent', 0o644, b'''DRIVER=button +MODALIAS=acpi:PNP0C0D: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input', 0o755) +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/subsystem', '../../../../../../class/input') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/device', '../../../PNP0C0D:00') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/uniq', 0o644, b'\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/phys', 0o644, b'PNP0C0D/button/input0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/modalias', 0o644, b'input:b0019v0000p0005e0000-e0,5,kramlsfw0,\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/name', 0o644, b'Lid Switch\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/uevent', 0o644, b'''PRODUCT=19/0/5/0 +NAME="Lid Switch" +PHYS="PNP0C0D/button/input0" +EV==21 +SW==1 +MODALIAS=input:b0019v0000p0005e0000-e0,5,kramlsfw0, +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/event4', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/event4/subsystem', '../../../../../../../class/input') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/event4/device', '../../input4') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/event4/dev', 0o644, b'13:68\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/event4/uevent', 0o644, b'''MAJOR=13 +MINOR=68 +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/event4/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/event4/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/id', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/id/version', 0o644, b'0000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/id/product', 0o644, b'0005\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/id/vendor', 0o644, b'0000\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/id/bustype', 0o644, b'0019\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/capabilities', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/capabilities/msc', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/capabilities/abs', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/capabilities/snd', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/capabilities/ff', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/capabilities/key', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/capabilities/rel', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/capabilities/sw', 0o644, b'1\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/capabilities/ev', 0o644, b'21\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input4/capabilities/led', 0o644, b'0\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C01:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C01:00/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C01:00/physical_node', '../../../pnp0/00:00') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C01:00/hid', 0o644, b'PNP0C01\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C01:00/modalias', 0o644, b'acpi:PNP0C01:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C01:00/path', 0o644, b'\\_SB_.MEM_\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C01:00/uevent', 0o644, b'MODALIAS=acpi:PNP0C01:\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C01:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C01:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:07', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:07/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:07/driver', '../../../../bus/acpi/drivers/pci_link') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:07/hid', 0o644, b'PNP0C0F\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:07/modalias', 0o644, b'acpi:PNP0C0F:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:07/path', 0o644, b'\\_SB_.LNKH\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:07/uevent', 0o644, b'''DRIVER=pci_link +MODALIAS=acpi:PNP0C0F: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:07/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:07/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:04', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:04/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:04/driver', '../../../../bus/acpi/drivers/pci_link') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:04/hid', 0o644, b'PNP0C0F\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:04/modalias', 0o644, b'acpi:PNP0C0F:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:04/path', 0o644, b'\\_SB_.LNKE\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:04/uevent', 0o644, b'''DRIVER=pci_link +MODALIAS=acpi:PNP0C0F: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:04/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:04/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:02', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:02/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:02/driver', '../../../../bus/acpi/drivers/pci_link') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:02/hid', 0o644, b'PNP0C0F\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:02/modalias', 0o644, b'acpi:PNP0C0F:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:02/path', 0o644, b'\\_SB_.LNKC\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:02/uevent', 0o644, b'''DRIVER=pci_link +MODALIAS=acpi:PNP0C0F: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:02/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:02/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:00', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:00/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:00/driver', '../../../../bus/acpi/drivers/pci_link') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:00/hid', 0o644, b'PNP0C0F\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:00/modalias', 0o644, b'acpi:PNP0C0F:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:00/path', 0o644, b'\\_SB_.LNKA\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:00/uevent', 0o644, b'''DRIVER=pci_link +MODALIAS=acpi:PNP0C0F: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:01', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:01/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:01/driver', '../../../../bus/acpi/drivers/pci_link') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:01/hid', 0o644, b'PNP0C0F\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:01/modalias', 0o644, b'acpi:PNP0C0F:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:01/path', 0o644, b'\\_SB_.LNKB\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:01/uevent', 0o644, b'''DRIVER=pci_link +MODALIAS=acpi:PNP0C0F: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:01/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:01/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:06', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:06/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:06/driver', '../../../../bus/acpi/drivers/pci_link') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:06/hid', 0o644, b'PNP0C0F\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:06/modalias', 0o644, b'acpi:PNP0C0F:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:06/path', 0o644, b'\\_SB_.LNKG\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:06/uevent', 0o644, b'''DRIVER=pci_link +MODALIAS=acpi:PNP0C0F: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:06/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:06/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:03', 0o755) +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:03/subsystem', '../../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:03/driver', '../../../../bus/acpi/drivers/pci_link') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:03/hid', 0o644, b'PNP0C0F\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:03/modalias', 0o644, b'acpi:PNP0C0F:\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:03/path', 0o644, b'\\_SB_.LNKD\n') +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:03/uevent', 0o644, b'''DRIVER=pci_link +MODALIAS=acpi:PNP0C0F: +''') +d('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:03/power', 0o755) +f('sys/devices/LNXSYSTM:00/device:00/PNP0C0F:03/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/ACPI0007:00', 0o755) +l('sys/devices/LNXSYSTM:00/ACPI0007:00/thermal_cooling', '../../virtual/thermal/cooling_device0') +l('sys/devices/LNXSYSTM:00/ACPI0007:00/subsystem', '../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/ACPI0007:00/sysdev', '../../system/cpu/cpu0') +l('sys/devices/LNXSYSTM:00/ACPI0007:00/driver', '../../../bus/acpi/drivers/processor') +f('sys/devices/LNXSYSTM:00/ACPI0007:00/hid', 0o644, b'ACPI0007\n') +f('sys/devices/LNXSYSTM:00/ACPI0007:00/modalias', 0o644, b'acpi:ACPI0007:\n') +f('sys/devices/LNXSYSTM:00/ACPI0007:00/path', 0o644, b'\\_PR_.CPU0\n') +f('sys/devices/LNXSYSTM:00/ACPI0007:00/uevent', 0o644, b'''DRIVER=processor +MODALIAS=acpi:ACPI0007: +''') +d('sys/devices/LNXSYSTM:00/ACPI0007:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/ACPI0007:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/LNXPWRBN:00', 0o755) +l('sys/devices/LNXSYSTM:00/LNXPWRBN:00/subsystem', '../../../bus/acpi') +l('sys/devices/LNXSYSTM:00/LNXPWRBN:00/driver', '../../../bus/acpi/drivers/button') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/hid', 0o644, b'LNXPWRBN\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/modalias', 0o644, b'acpi:LNXPWRBN:\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/uevent', 0o644, b'''DRIVER=button +MODALIAS=acpi:LNXPWRBN: +''') +d('sys/devices/LNXSYSTM:00/LNXPWRBN:00/power', 0o755) +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input', 0o755) +d('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3', 0o755) +l('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/subsystem', '../../../../../class/input') +l('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/device', '../../../LNXPWRBN:00') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/uniq', 0o644, b'\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/phys', 0o644, b'LNXPWRBN/button/input0\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/modalias', 0o644, b'input:b0019v0000p0002e0000-e0,1,k74,ramlsfw\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/name', 0o644, b'Power Button (FF)\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/uevent', 0o644, b'''PRODUCT=19/0/2/0 +NAME="Power Button (FF)" +PHYS="LNXPWRBN/button/input0" +EV==3 +KEY==10000000000000 0 +MODALIAS=input:b0019v0000p0002e0000-e0,1,k74,ramlsfw +''') +d('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/id', 0o755) +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/id/version', 0o644, b'0000\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/id/product', 0o644, b'0002\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/id/vendor', 0o644, b'0000\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/id/bustype', 0o644, b'0019\n') +d('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/power', 0o755) +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/event3', 0o755) +l('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/event3/subsystem', '../../../../../../class/input') +l('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/event3/device', '../../input3') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/event3/dev', 0o644, b'13:67\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/event3/uevent', 0o644, b'''MAJOR=13 +MINOR=67 +''') +d('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/event3/power', 0o755) +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/event3/power/wakeup', 0o644, b'\n') +d('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/capabilities', 0o755) +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/capabilities/msc', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/capabilities/abs', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/capabilities/snd', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/capabilities/ff', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/capabilities/key', 0o644, b'10000000000000 0\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/capabilities/rel', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/capabilities/sw', 0o644, b'0\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/capabilities/ev', 0o644, b'3\n') +f('sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input3/capabilities/led', 0o644, b'0\n') +d('sys/devices/platform', 0o755) +f('sys/devices/platform/uevent', 0o644, b'') +d('sys/devices/platform/pcspkr', 0o755) +l('sys/devices/platform/pcspkr/subsystem', '../../../bus/platform') +l('sys/devices/platform/pcspkr/driver', '../../../bus/platform/drivers/pcspkr') +f('sys/devices/platform/pcspkr/modalias', 0o644, b'platform:pcspkr\n') +f('sys/devices/platform/pcspkr/uevent', 0o644, b'''DRIVER=pcspkr +MODALIAS=platform:pcspkr +''') +d('sys/devices/platform/pcspkr/power', 0o755) +f('sys/devices/platform/pcspkr/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/pcspkr/input', 0o755) +d('sys/devices/platform/pcspkr/input/input2', 0o755) +l('sys/devices/platform/pcspkr/input/input2/subsystem', '../../../../../class/input') +l('sys/devices/platform/pcspkr/input/input2/device', '../../../pcspkr') +f('sys/devices/platform/pcspkr/input/input2/uniq', 0o644, b'\n') +f('sys/devices/platform/pcspkr/input/input2/phys', 0o644, b'isa0061/input0\n') +f('sys/devices/platform/pcspkr/input/input2/modalias', 0o644, b'input:b0010v001Fp0001e0100-e0,12,kramls1,2,fw\n') +f('sys/devices/platform/pcspkr/input/input2/name', 0o644, b'PC Speaker\n') +f('sys/devices/platform/pcspkr/input/input2/uevent', 0o644, b'''PRODUCT=10/1f/1/100 +NAME="PC Speaker" +PHYS="isa0061/input0" +EV==40001 +SND==6 +MODALIAS=input:b0010v001Fp0001e0100-e0,12,kramls1,2,fw +''') +d('sys/devices/platform/pcspkr/input/input2/event2', 0o755) +l('sys/devices/platform/pcspkr/input/input2/event2/subsystem', '../../../../../../class/input') +l('sys/devices/platform/pcspkr/input/input2/event2/device', '../../input2') +f('sys/devices/platform/pcspkr/input/input2/event2/dev', 0o644, b'13:66\n') +f('sys/devices/platform/pcspkr/input/input2/event2/uevent', 0o644, b'''MAJOR=13 +MINOR=66 +''') +d('sys/devices/platform/pcspkr/input/input2/event2/power', 0o755) +f('sys/devices/platform/pcspkr/input/input2/event2/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/pcspkr/input/input2/id', 0o755) +f('sys/devices/platform/pcspkr/input/input2/id/version', 0o644, b'0100\n') +f('sys/devices/platform/pcspkr/input/input2/id/product', 0o644, b'0001\n') +f('sys/devices/platform/pcspkr/input/input2/id/vendor', 0o644, b'001f\n') +f('sys/devices/platform/pcspkr/input/input2/id/bustype', 0o644, b'0010\n') +d('sys/devices/platform/pcspkr/input/input2/power', 0o755) +f('sys/devices/platform/pcspkr/input/input2/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/pcspkr/input/input2/capabilities', 0o755) +f('sys/devices/platform/pcspkr/input/input2/capabilities/msc', 0o644, b'0\n') +f('sys/devices/platform/pcspkr/input/input2/capabilities/abs', 0o644, b'0\n') +f('sys/devices/platform/pcspkr/input/input2/capabilities/snd', 0o644, b'6\n') +f('sys/devices/platform/pcspkr/input/input2/capabilities/ff', 0o644, b'0\n') +f('sys/devices/platform/pcspkr/input/input2/capabilities/key', 0o644, b'0\n') +f('sys/devices/platform/pcspkr/input/input2/capabilities/rel', 0o644, b'0\n') +f('sys/devices/platform/pcspkr/input/input2/capabilities/sw', 0o644, b'0\n') +f('sys/devices/platform/pcspkr/input/input2/capabilities/ev', 0o644, b'40001\n') +f('sys/devices/platform/pcspkr/input/input2/capabilities/led', 0o644, b'0\n') +d('sys/devices/platform/power', 0o755) +f('sys/devices/platform/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/vesafb.0', 0o755) +l('sys/devices/platform/vesafb.0/subsystem', '../../../bus/platform') +l('sys/devices/platform/vesafb.0/driver', '../../../bus/platform/drivers/vesafb') +f('sys/devices/platform/vesafb.0/modalias', 0o644, b'platform:vesafb\n') +f('sys/devices/platform/vesafb.0/uevent', 0o644, b'''DRIVER=vesafb +MODALIAS=platform:vesafb +''') +d('sys/devices/platform/vesafb.0/power', 0o755) +f('sys/devices/platform/vesafb.0/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/vesafb.0/graphics', 0o755) +d('sys/devices/platform/vesafb.0/graphics/fb0', 0o755) +l('sys/devices/platform/vesafb.0/graphics/fb0/subsystem', '../../../../../class/graphics') +l('sys/devices/platform/vesafb.0/graphics/fb0/device', '../../../vesafb.0') +f('sys/devices/platform/vesafb.0/graphics/fb0/pan', 0o644, b'0,0\n') +f('sys/devices/platform/vesafb.0/graphics/fb0/rotate', 0o644, b'0\n') +f('sys/devices/platform/vesafb.0/graphics/fb0/mode', 0o644, b'') +f('sys/devices/platform/vesafb.0/graphics/fb0/virtual_size', 0o644, b'800,600\n') +f('sys/devices/platform/vesafb.0/graphics/fb0/dev', 0o644, b'29:0\n') +f('sys/devices/platform/vesafb.0/graphics/fb0/state', 0o644, b'0\n') +f('sys/devices/platform/vesafb.0/graphics/fb0/blank', 0o644, b'') +f('sys/devices/platform/vesafb.0/graphics/fb0/bits_per_pixel', 0o644, b'16\n') +f('sys/devices/platform/vesafb.0/graphics/fb0/stride', 0o644, b'1600\n') +f('sys/devices/platform/vesafb.0/graphics/fb0/name', 0o644, b'VESA VGA\n') +f('sys/devices/platform/vesafb.0/graphics/fb0/modes', 0o644, b'U:800x600p-75\n') +f('sys/devices/platform/vesafb.0/graphics/fb0/cursor', 0o644, b'') +f('sys/devices/platform/vesafb.0/graphics/fb0/uevent', 0o644, b'''MAJOR=29 +MINOR=0 +''') +f('sys/devices/platform/vesafb.0/graphics/fb0/console', 0o644, b'') +d('sys/devices/platform/vesafb.0/graphics/fb0/power', 0o755) +f('sys/devices/platform/vesafb.0/graphics/fb0/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/dock.0', 0o755) +l('sys/devices/platform/dock.0/subsystem', '../../../bus/platform') +f('sys/devices/platform/dock.0/modalias', 0o644, b'platform:dock\n') +f('sys/devices/platform/dock.0/uid', 0o644, b'0\n') +f('sys/devices/platform/dock.0/flags', 0o644, b'0\n') +f('sys/devices/platform/dock.0/docked', 0o644, b'0\n') +f('sys/devices/platform/dock.0/uevent', 0o644, b'MODALIAS=platform:dock\n') +d('sys/devices/platform/dock.0/power', 0o755) +f('sys/devices/platform/dock.0/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/serial8250', 0o755) +l('sys/devices/platform/serial8250/subsystem', '../../../bus/platform') +l('sys/devices/platform/serial8250/driver', '../../../bus/platform/drivers/serial8250') +f('sys/devices/platform/serial8250/modalias', 0o644, b'platform:serial8250\n') +f('sys/devices/platform/serial8250/uevent', 0o644, b'''DRIVER=serial8250 +MODALIAS=platform:serial8250 +''') +d('sys/devices/platform/serial8250/power', 0o755) +f('sys/devices/platform/serial8250/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/serial8250/tty', 0o755) +d('sys/devices/platform/serial8250/tty/ttyS1', 0o755) +l('sys/devices/platform/serial8250/tty/ttyS1/subsystem', '../../../../../class/tty') +l('sys/devices/platform/serial8250/tty/ttyS1/device', '../../../serial8250') +f('sys/devices/platform/serial8250/tty/ttyS1/dev', 0o644, b'4:65\n') +f('sys/devices/platform/serial8250/tty/ttyS1/uevent', 0o644, b'''MAJOR=4 +MINOR=65 +''') +d('sys/devices/platform/serial8250/tty/ttyS1/power', 0o755) +f('sys/devices/platform/serial8250/tty/ttyS1/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/platform/serial8250/tty/ttyS3', 0o755) +l('sys/devices/platform/serial8250/tty/ttyS3/subsystem', '../../../../../class/tty') +l('sys/devices/platform/serial8250/tty/ttyS3/device', '../../../serial8250') +f('sys/devices/platform/serial8250/tty/ttyS3/dev', 0o644, b'4:67\n') +f('sys/devices/platform/serial8250/tty/ttyS3/uevent', 0o644, b'''MAJOR=4 +MINOR=67 +''') +d('sys/devices/platform/serial8250/tty/ttyS3/power', 0o755) +f('sys/devices/platform/serial8250/tty/ttyS3/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/platform/serial8250/tty/ttyS0', 0o755) +l('sys/devices/platform/serial8250/tty/ttyS0/subsystem', '../../../../../class/tty') +l('sys/devices/platform/serial8250/tty/ttyS0/device', '../../../serial8250') +f('sys/devices/platform/serial8250/tty/ttyS0/dev', 0o644, b'4:64\n') +f('sys/devices/platform/serial8250/tty/ttyS0/uevent', 0o644, b'''MAJOR=4 +MINOR=64 +''') +d('sys/devices/platform/serial8250/tty/ttyS0/power', 0o755) +f('sys/devices/platform/serial8250/tty/ttyS0/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/platform/serial8250/tty/ttyS2', 0o755) +l('sys/devices/platform/serial8250/tty/ttyS2/subsystem', '../../../../../class/tty') +l('sys/devices/platform/serial8250/tty/ttyS2/device', '../../../serial8250') +f('sys/devices/platform/serial8250/tty/ttyS2/dev', 0o644, b'4:66\n') +f('sys/devices/platform/serial8250/tty/ttyS2/uevent', 0o644, b'''MAJOR=4 +MINOR=66 +''') +d('sys/devices/platform/serial8250/tty/ttyS2/power', 0o755) +f('sys/devices/platform/serial8250/tty/ttyS2/power/wakeup', 0o644, b'disabled\n') +d('sys/devices/platform/thinkpad_acpi', 0o755) +l('sys/devices/platform/thinkpad_acpi/subsystem', '../../../bus/platform') +l('sys/devices/platform/thinkpad_acpi/driver', '../../../bus/platform/drivers/thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/modalias', 0o644, b'platform:thinkpad_acpi\n') +f('sys/devices/platform/thinkpad_acpi/hotkey_all_mask', 0o644, b'0x00ffffff\n') +f('sys/devices/platform/thinkpad_acpi/hotkey_poll_freq', 0o644, b'10\n') +f('sys/devices/platform/thinkpad_acpi/hotkey_bios_enabled', 0o644, b'0\n') +f('sys/devices/platform/thinkpad_acpi/hotkey_recommended_mask', 0o644, b'0x008c7fff\n') +f('sys/devices/platform/thinkpad_acpi/hotkey_bios_mask', 0o644, b'0x0000080c\n') +f('sys/devices/platform/thinkpad_acpi/hotkey_mask', 0o644, b'0x00ffffff\n') +f('sys/devices/platform/thinkpad_acpi/wakeup_hotunplug_complete', 0o644, b'0\n') +f('sys/devices/platform/thinkpad_acpi/hotkey_source_mask', 0o644, b'0x00000000\n') +f('sys/devices/platform/thinkpad_acpi/hotkey_report_mode', 0o644, b'1\n') +f('sys/devices/platform/thinkpad_acpi/hotkey_radio_sw', 0o644, b'1\n') +f('sys/devices/platform/thinkpad_acpi/hotkey_enable', 0o644, b'1\n') +f('sys/devices/platform/thinkpad_acpi/uevent', 0o644, b'''DRIVER=thinkpad_acpi +MODALIAS=platform:thinkpad_acpi +''') +f('sys/devices/platform/thinkpad_acpi/bluetooth_enable', 0o644, b'1\n') +f('sys/devices/platform/thinkpad_acpi/wakeup_reason', 0o644, b'0\n') +d('sys/devices/platform/thinkpad_acpi/rfkill', 0o755) +d('sys/devices/platform/thinkpad_acpi/rfkill/rfkill0', 0o755) +l('sys/devices/platform/thinkpad_acpi/rfkill/rfkill0/subsystem', '../../../../../class/rfkill') +l('sys/devices/platform/thinkpad_acpi/rfkill/rfkill0/device', '../../../thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/rfkill/rfkill0/type', 0o644, b'bluetooth\n') +f('sys/devices/platform/thinkpad_acpi/rfkill/rfkill0/state', 0o644, b'1\n') +f('sys/devices/platform/thinkpad_acpi/rfkill/rfkill0/name', 0o644, b'tpacpi_bluetooth_sw\n') +f('sys/devices/platform/thinkpad_acpi/rfkill/rfkill0/uevent', 0o644, b'''RFKILL_NAME=tpacpi_bluetooth_sw +RFKILL_TYPE=bluetooth +RFKILL_STATE=1 +''') +f('sys/devices/platform/thinkpad_acpi/rfkill/rfkill0/claim', 0o644, b'0\n') +d('sys/devices/platform/thinkpad_acpi/rfkill/rfkill0/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/rfkill/rfkill0/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_acpi/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_acpi/leds', 0o755) +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::bay_active', 0o755) +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::bay_active/subsystem', '../../../../../class/leds') +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::bay_active/device', '../../../thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::bay_active/trigger', 0o644, b'[none] AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx phy0assoc phy0radio \n') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::bay_active/brightness', 0o644, b'0\n\x00') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::bay_active/uevent', 0o644, b'') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::bay_active/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::bay_active/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi:orange:batt', 0o755) +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi:orange:batt/subsystem', '../../../../../class/leds') +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi:orange:batt/device', '../../../thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi:orange:batt/trigger', 0o644, b'[none] AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx phy0assoc phy0radio \n') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi:orange:batt/brightness', 0o644, b'0\n\x00') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi:orange:batt/uevent', 0o644, b'') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi:orange:batt/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi:orange:batt/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_active', 0o755) +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_active/subsystem', '../../../../../class/leds') +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_active/device', '../../../thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_active/trigger', 0o644, b'[none] AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx phy0assoc phy0radio \n') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_active/brightness', 0o644, b'0\n\x00') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_active/uevent', 0o644, b'') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_active/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_active/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::unknown_led', 0o755) +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::unknown_led/subsystem', '../../../../../class/leds') +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::unknown_led/device', '../../../thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::unknown_led/trigger', 0o644, b'[none] AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx phy0assoc phy0radio \n') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::unknown_led/brightness', 0o644, b'0\n\x00') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::unknown_led/uevent', 0o644, b'') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::unknown_led/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::unknown_led/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi:green:batt', 0o755) +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi:green:batt/subsystem', '../../../../../class/leds') +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi:green:batt/device', '../../../thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi:green:batt/trigger', 0o644, b'[none] AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx phy0assoc phy0radio \n') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi:green:batt/brightness', 0o644, b'0\n\x00') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi:green:batt/uevent', 0o644, b'') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi:green:batt/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi:green:batt/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_batt', 0o755) +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_batt/subsystem', '../../../../../class/leds') +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_batt/device', '../../../thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_batt/trigger', 0o644, b'[none] AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx phy0assoc phy0radio \n') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_batt/brightness', 0o644, b'0\n\x00') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_batt/uevent', 0o644, b'') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_batt/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::dock_batt/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight', 0o755) +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/subsystem', '../../../../../class/leds') +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/device', '../../../thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/trigger', 0o644, b'[none] AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx phy0assoc phy0radio \n') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/brightness', 0o644, b'255\n\x00') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/uevent', 0o644, b'') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::thinklight/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::power', 0o755) +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::power/subsystem', '../../../../../class/leds') +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::power/device', '../../../thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::power/trigger', 0o644, b'[none] AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx phy0assoc phy0radio \n') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::power/brightness', 0o644, b'0\n\x00') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::power/uevent', 0o644, b'') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::power/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::power/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::standby', 0o755) +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::standby/subsystem', '../../../../../class/leds') +l('sys/devices/platform/thinkpad_acpi/leds/tpacpi::standby/device', '../../../thinkpad_acpi') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::standby/trigger', 0o644, b'[none] AC-online BAT0-charging-or-full BAT0-charging BAT0-full rfkill0 phy0rx phy0tx phy0assoc phy0radio \n') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::standby/brightness', 0o644, b'0\n\x00') +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::standby/uevent', 0o644, b'') +d('sys/devices/platform/thinkpad_acpi/leds/tpacpi::standby/power', 0o755) +f('sys/devices/platform/thinkpad_acpi/leds/tpacpi::standby/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_hwmon', 0o755) +l('sys/devices/platform/thinkpad_hwmon/subsystem', '../../../bus/platform') +l('sys/devices/platform/thinkpad_hwmon/driver', '../../../bus/platform/drivers/thinkpad_hwmon') +f('sys/devices/platform/thinkpad_hwmon/fan1_input', 0o644, b'3446\n') +f('sys/devices/platform/thinkpad_hwmon/temp4_input', 0o644, b'63000\n') +f('sys/devices/platform/thinkpad_hwmon/pwm1', 0o644, b'255\n') +f('sys/devices/platform/thinkpad_hwmon/temp11_input', 0o644, b'43000\n') +f('sys/devices/platform/thinkpad_hwmon/modalias', 0o644, b'platform:thinkpad_hwmon\n') +f('sys/devices/platform/thinkpad_hwmon/temp15_input', 0o644, b'') +f('sys/devices/platform/thinkpad_hwmon/temp2_input', 0o644, b'41000\n') +f('sys/devices/platform/thinkpad_hwmon/temp1_input', 0o644, b'46000\n') +f('sys/devices/platform/thinkpad_hwmon/temp5_input', 0o644, b'35000\n') +f('sys/devices/platform/thinkpad_hwmon/temp13_input', 0o644, b'') +f('sys/devices/platform/thinkpad_hwmon/temp6_input', 0o644, b'') +f('sys/devices/platform/thinkpad_hwmon/temp8_input', 0o644, b'') +f('sys/devices/platform/thinkpad_hwmon/pwm1_enable', 0o644, b'2\n') +f('sys/devices/platform/thinkpad_hwmon/temp10_input', 0o644, b'49000\n') +f('sys/devices/platform/thinkpad_hwmon/temp3_input', 0o644, b'33000\n') +f('sys/devices/platform/thinkpad_hwmon/temp9_input', 0o644, b'35000\n') +f('sys/devices/platform/thinkpad_hwmon/name', 0o644, b'thinkpad\n') +f('sys/devices/platform/thinkpad_hwmon/temp12_input', 0o644, b'') +f('sys/devices/platform/thinkpad_hwmon/uevent', 0o644, b'''DRIVER=thinkpad_hwmon +MODALIAS=platform:thinkpad_hwmon +''') +f('sys/devices/platform/thinkpad_hwmon/temp7_input', 0o644, b'33000\n') +f('sys/devices/platform/thinkpad_hwmon/temp16_input', 0o644, b'') +f('sys/devices/platform/thinkpad_hwmon/temp14_input', 0o644, b'') +d('sys/devices/platform/thinkpad_hwmon/hwmon', 0o755) +d('sys/devices/platform/thinkpad_hwmon/hwmon/hwmon0', 0o755) +l('sys/devices/platform/thinkpad_hwmon/hwmon/hwmon0/subsystem', '../../../../../class/hwmon') +l('sys/devices/platform/thinkpad_hwmon/hwmon/hwmon0/device', '../../../thinkpad_hwmon') +f('sys/devices/platform/thinkpad_hwmon/hwmon/hwmon0/uevent', 0o644, b'') +d('sys/devices/platform/thinkpad_hwmon/hwmon/hwmon0/power', 0o755) +f('sys/devices/platform/thinkpad_hwmon/hwmon/hwmon0/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/thinkpad_hwmon/power', 0o755) +f('sys/devices/platform/thinkpad_hwmon/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/microcode', 0o755) +l('sys/devices/platform/microcode/subsystem', '../../../bus/platform') +f('sys/devices/platform/microcode/modalias', 0o644, b'platform:microcode\n') +f('sys/devices/platform/microcode/uevent', 0o644, b'MODALIAS=platform:microcode\n') +d('sys/devices/platform/microcode/power', 0o755) +f('sys/devices/platform/microcode/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/i8042', 0o755) +l('sys/devices/platform/i8042/subsystem', '../../../bus/platform') +l('sys/devices/platform/i8042/driver', '../../../bus/platform/drivers/i8042') +f('sys/devices/platform/i8042/modalias', 0o644, b'platform:i8042\n') +f('sys/devices/platform/i8042/uevent', 0o644, b'''DRIVER=i8042 +MODALIAS=platform:i8042 +''') +d('sys/devices/platform/i8042/power', 0o755) +f('sys/devices/platform/i8042/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/i8042/serio0', 0o755) +l('sys/devices/platform/i8042/serio0/subsystem', '../../../../bus/serio') +l('sys/devices/platform/i8042/serio0/driver', '../../../../bus/serio/drivers/atkbd') +f('sys/devices/platform/i8042/serio0/modalias', 0o644, b'serio:ty06pr00id00ex00\n') +f('sys/devices/platform/i8042/serio0/set', 0o644, b'2\n') +f('sys/devices/platform/i8042/serio0/bind_mode', 0o644, b'auto\n') +f('sys/devices/platform/i8042/serio0/description', 0o644, b'i8042 KBD port\n') +f('sys/devices/platform/i8042/serio0/softrepeat', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio0/scroll', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio0/softraw', 0o644, b'1\n') +f('sys/devices/platform/i8042/serio0/err_count', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio0/extra', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio0/uevent', 0o644, b'''DRIVER=atkbd +SERIO_TYPE=06 +SERIO_PROTO=00 +SERIO_ID=00 +SERIO_EXTRA=00 +MODALIAS=serio:ty06pr00id00ex00 +''') +d('sys/devices/platform/i8042/serio0/id', 0o755) +f('sys/devices/platform/i8042/serio0/id/proto', 0o644, b'00\n') +f('sys/devices/platform/i8042/serio0/id/id', 0o644, b'00\n') +f('sys/devices/platform/i8042/serio0/id/type', 0o644, b'06\n') +f('sys/devices/platform/i8042/serio0/id/extra', 0o644, b'00\n') +d('sys/devices/platform/i8042/serio0/power', 0o755) +f('sys/devices/platform/i8042/serio0/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/i8042/serio0/input', 0o755) +d('sys/devices/platform/i8042/serio0/input/input0', 0o755) +l('sys/devices/platform/i8042/serio0/input/input0/subsystem', '../../../../../../class/input') +l('sys/devices/platform/i8042/serio0/input/input0/device', '../../../serio0') +f('sys/devices/platform/i8042/serio0/input/input0/uniq', 0o644, b'\n') +f('sys/devices/platform/i8042/serio0/input/input0/phys', 0o644, b'isa0060/serio0/input0\n') +f('sys/devices/platform/i8042/serio0/input/input0/modalias', 0o644, b'input:b0011v0001p0001eAB54-e0,1,4,11,14,k71,72,73,74,75,76,77,79,7A,7B,7C,7D,7E,7F,80,8C,8E,8F,9B,9C,9D,9E,9F,A3,A4,A5,A6,AC,AD,B7,B8,B9,D9,E2,ram4,l0,1,2,sfw\n') +f('sys/devices/platform/i8042/serio0/input/input0/name', 0o644, b'AT Translated Set 2 keyboard\n') +f('sys/devices/platform/i8042/serio0/input/input0/uevent', 0o644, b'''PRODUCT=11/1/1/ab54 +NAME="AT Translated Set 2 keyboard" +PHYS="isa0060/serio0/input0" +EV==120013 +KEY==402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe +MSC==10 +LED==7 +MODALIAS=input:b0011v0001p0001eAB54-e0,1,4,11,14,k71,72,73,74,75,76,77,79,7A,7B,7C,7D,7E,7F,80,8C,8E,8F,9B,9C,9D,9E,9F,A3,A4,A5,A6,AC,AD,B7,B8,B9,D9,E2,ram4,l0,1,2,sfw +''') +d('sys/devices/platform/i8042/serio0/input/input0/event0', 0o755) +l('sys/devices/platform/i8042/serio0/input/input0/event0/subsystem', '../../../../../../../class/input') +l('sys/devices/platform/i8042/serio0/input/input0/event0/device', '../../input0') +f('sys/devices/platform/i8042/serio0/input/input0/event0/dev', 0o644, b'13:64\n') +f('sys/devices/platform/i8042/serio0/input/input0/event0/uevent', 0o644, b'''MAJOR=13 +MINOR=64 +''') +d('sys/devices/platform/i8042/serio0/input/input0/event0/power', 0o755) +f('sys/devices/platform/i8042/serio0/input/input0/event0/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/i8042/serio0/input/input0/id', 0o755) +f('sys/devices/platform/i8042/serio0/input/input0/id/version', 0o644, b'ab54\n') +f('sys/devices/platform/i8042/serio0/input/input0/id/product', 0o644, b'0001\n') +f('sys/devices/platform/i8042/serio0/input/input0/id/vendor', 0o644, b'0001\n') +f('sys/devices/platform/i8042/serio0/input/input0/id/bustype', 0o644, b'0011\n') +d('sys/devices/platform/i8042/serio0/input/input0/power', 0o755) +f('sys/devices/platform/i8042/serio0/input/input0/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/i8042/serio0/input/input0/capabilities', 0o755) +f('sys/devices/platform/i8042/serio0/input/input0/capabilities/msc', 0o644, b'10\n') +f('sys/devices/platform/i8042/serio0/input/input0/capabilities/abs', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio0/input/input0/capabilities/snd', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio0/input/input0/capabilities/ff', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio0/input/input0/capabilities/key', 0o644, b'402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe\n') +f('sys/devices/platform/i8042/serio0/input/input0/capabilities/rel', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio0/input/input0/capabilities/sw', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio0/input/input0/capabilities/ev', 0o644, b'120013\n') +f('sys/devices/platform/i8042/serio0/input/input0/capabilities/led', 0o644, b'7\n') +d('sys/devices/platform/i8042/serio1', 0o755) +l('sys/devices/platform/i8042/serio1/subsystem', '../../../../bus/serio') +l('sys/devices/platform/i8042/serio1/driver', '../../../../bus/serio/drivers/psmouse') +f('sys/devices/platform/i8042/serio1/upthresh', 0o644, b'255\n') +f('sys/devices/platform/i8042/serio1/modalias', 0o644, b'serio:ty01pr00id00ex00\n') +f('sys/devices/platform/i8042/serio1/resync_time', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio1/skipback', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio1/draghys', 0o644, b'255\n') +f('sys/devices/platform/i8042/serio1/ext_dev', 0o644, b'1\n') +f('sys/devices/platform/i8042/serio1/bind_mode', 0o644, b'auto\n') +f('sys/devices/platform/i8042/serio1/resolution', 0o644, b'200\n') +f('sys/devices/platform/i8042/serio1/resetafter', 0o644, b'5\n') +f('sys/devices/platform/i8042/serio1/sensitivity', 0o644, b'128\n') +f('sys/devices/platform/i8042/serio1/rate', 0o644, b'100\n') +f('sys/devices/platform/i8042/serio1/inertia', 0o644, b'6\n') +f('sys/devices/platform/i8042/serio1/mindrag', 0o644, b'20\n') +f('sys/devices/platform/i8042/serio1/reach', 0o644, b'10\n') +f('sys/devices/platform/i8042/serio1/description', 0o644, b'i8042 AUX port\n') +f('sys/devices/platform/i8042/serio1/press_to_select', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio1/ztime', 0o644, b'38\n') +f('sys/devices/platform/i8042/serio1/speed', 0o644, b'97\n') +f('sys/devices/platform/i8042/serio1/thresh', 0o644, b'8\n') +f('sys/devices/platform/i8042/serio1/jenks', 0o644, b'135\n') +f('sys/devices/platform/i8042/serio1/uevent', 0o644, b'''DRIVER=psmouse +SERIO_TYPE=01 +SERIO_PROTO=00 +SERIO_ID=00 +SERIO_EXTRA=00 +MODALIAS=serio:ty01pr00id00ex00 +''') +f('sys/devices/platform/i8042/serio1/protocol', 0o644, b'TPPS/2\n') +d('sys/devices/platform/i8042/serio1/id', 0o755) +f('sys/devices/platform/i8042/serio1/id/proto', 0o644, b'00\n') +f('sys/devices/platform/i8042/serio1/id/id', 0o644, b'00\n') +f('sys/devices/platform/i8042/serio1/id/type', 0o644, b'01\n') +f('sys/devices/platform/i8042/serio1/id/extra', 0o644, b'00\n') +d('sys/devices/platform/i8042/serio1/power', 0o755) +f('sys/devices/platform/i8042/serio1/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/i8042/serio1/input', 0o755) +d('sys/devices/platform/i8042/serio1/input/input1', 0o755) +l('sys/devices/platform/i8042/serio1/input/input1/subsystem', '../../../../../../class/input') +l('sys/devices/platform/i8042/serio1/input/input1/device', '../../../serio1') +f('sys/devices/platform/i8042/serio1/input/input1/uniq', 0o644, b'\n') +f('sys/devices/platform/i8042/serio1/input/input1/phys', 0o644, b'isa0060/serio1/input0\n') +f('sys/devices/platform/i8042/serio1/input/input1/modalias', 0o644, b'input:b0011v0002p000Ae0000-e0,1,2,k110,111,112,r0,1,amlsfw\n') +f('sys/devices/platform/i8042/serio1/input/input1/name', 0o644, b'TPPS/2 IBM TrackPoint\n') +f('sys/devices/platform/i8042/serio1/input/input1/uevent', 0o644, b'''PRODUCT=11/2/a/0 +NAME="TPPS/2 IBM TrackPoint" +PHYS="isa0060/serio1/input0" +EV==7 +KEY==70000 0 0 0 0 +REL==3 +MODALIAS=input:b0011v0002p000Ae0000-e0,1,2,k110,111,112,r0,1,amlsfw +''') +d('sys/devices/platform/i8042/serio1/input/input1/mouse0', 0o755) +l('sys/devices/platform/i8042/serio1/input/input1/mouse0/subsystem', '../../../../../../../class/input') +l('sys/devices/platform/i8042/serio1/input/input1/mouse0/device', '../../input1') +f('sys/devices/platform/i8042/serio1/input/input1/mouse0/dev', 0o644, b'13:32\n') +f('sys/devices/platform/i8042/serio1/input/input1/mouse0/uevent', 0o644, b'''MAJOR=13 +MINOR=32 +''') +d('sys/devices/platform/i8042/serio1/input/input1/mouse0/power', 0o755) +f('sys/devices/platform/i8042/serio1/input/input1/mouse0/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/i8042/serio1/input/input1/id', 0o755) +f('sys/devices/platform/i8042/serio1/input/input1/id/version', 0o644, b'0000\n') +f('sys/devices/platform/i8042/serio1/input/input1/id/product', 0o644, b'000a\n') +f('sys/devices/platform/i8042/serio1/input/input1/id/vendor', 0o644, b'0002\n') +f('sys/devices/platform/i8042/serio1/input/input1/id/bustype', 0o644, b'0011\n') +d('sys/devices/platform/i8042/serio1/input/input1/power', 0o755) +f('sys/devices/platform/i8042/serio1/input/input1/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/i8042/serio1/input/input1/event1', 0o755) +l('sys/devices/platform/i8042/serio1/input/input1/event1/subsystem', '../../../../../../../class/input') +l('sys/devices/platform/i8042/serio1/input/input1/event1/device', '../../input1') +f('sys/devices/platform/i8042/serio1/input/input1/event1/dev', 0o644, b'13:65\n') +f('sys/devices/platform/i8042/serio1/input/input1/event1/uevent', 0o644, b'''MAJOR=13 +MINOR=65 +''') +d('sys/devices/platform/i8042/serio1/input/input1/event1/power', 0o755) +f('sys/devices/platform/i8042/serio1/input/input1/event1/power/wakeup', 0o644, b'\n') +d('sys/devices/platform/i8042/serio1/input/input1/capabilities', 0o755) +f('sys/devices/platform/i8042/serio1/input/input1/capabilities/msc', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio1/input/input1/capabilities/abs', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio1/input/input1/capabilities/snd', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio1/input/input1/capabilities/ff', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio1/input/input1/capabilities/key', 0o644, b'70000 0 0 0 0\n') +f('sys/devices/platform/i8042/serio1/input/input1/capabilities/rel', 0o644, b'3\n') +f('sys/devices/platform/i8042/serio1/input/input1/capabilities/sw', 0o644, b'0\n') +f('sys/devices/platform/i8042/serio1/input/input1/capabilities/ev', 0o644, b'7\n') +f('sys/devices/platform/i8042/serio1/input/input1/capabilities/led', 0o644, b'0\n') diff --git a/test/sysinit.target b/test/sysinit.target new file mode 120000 index 00000000..33013381 --- /dev/null +++ b/test/sysinit.target @@ -0,0 +1 @@ +../units/sysinit.target \ No newline at end of file diff --git a/test/sysv-generator-test.py b/test/sysv-generator-test.py new file mode 100755 index 00000000..3d9c1ddb --- /dev/null +++ b/test/sysv-generator-test.py @@ -0,0 +1,411 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ +# +# systemd-sysv-generator integration test +# +# © 2015 Canonical Ltd. +# Author: Martin Pitt + +import collections +import os +import shutil +import subprocess +import sys +import tempfile +import unittest + +from configparser import RawConfigParser +from glob import glob + +sysv_generator = './systemd-sysv-generator' + +class MultiDict(collections.OrderedDict): + def __setitem__(self, key, value): + if isinstance(value, list) and key in self: + self[key].extend(value) + else: + super(MultiDict, self).__setitem__(key, value) + +class SysvGeneratorTest(unittest.TestCase): + def setUp(self): + self.workdir = tempfile.mkdtemp(prefix='sysv-gen-test.') + self.init_d_dir = os.path.join(self.workdir, 'init.d') + os.mkdir(self.init_d_dir) + self.rcnd_dir = self.workdir + self.unit_dir = os.path.join(self.workdir, 'systemd') + os.mkdir(self.unit_dir) + self.out_dir = os.path.join(self.workdir, 'output') + os.mkdir(self.out_dir) + + def tearDown(self): + shutil.rmtree(self.workdir) + + # + # Helper methods + # + + def run_generator(self, expect_error=False): + '''Run sysv-generator. + + Fail if stderr contains any "Fail", unless expect_error is True. + Return (stderr, filename -> ConfigParser) pair with output to stderr and + parsed generated units. + ''' + env = os.environ.copy() + env['SYSTEMD_LOG_LEVEL'] = 'debug' + env['SYSTEMD_LOG_TARGET'] = 'console' + env['SYSTEMD_SYSVINIT_PATH'] = self.init_d_dir + env['SYSTEMD_SYSVRCND_PATH'] = self.rcnd_dir + env['SYSTEMD_UNIT_PATH'] = self.unit_dir + gen = subprocess.Popen( + [sysv_generator, 'ignored', 'ignored', self.out_dir], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True, env=env) + (out, err) = gen.communicate() + if not expect_error: + self.assertFalse('Fail' in err, err) + self.assertEqual(gen.returncode, 0, err) + + results = {} + for service in glob(self.out_dir + '/*.service'): + if os.path.islink(service): + continue + try: + # for python3 we need here strict=False to parse multiple + # lines with the same key + cp = RawConfigParser(dict_type=MultiDict, strict=False) + except TypeError: + # RawConfigParser in python2 does not have the strict option + # but it allows multiple lines with the same key by default + cp = RawConfigParser(dict_type=MultiDict) + cp.optionxform = lambda o: o # don't lower-case option names + with open(service) as f: + cp.readfp(f) + results[os.path.basename(service)] = cp + + return (err, results) + + def add_sysv(self, fname, keys, enable=False, prio=1): + '''Create a SysV init script with the given keys in the LSB header + + There are sensible default values for all fields. + If enable is True, links will be created in the rcN.d dirs. In that + case, the priority can be given with "prio" (default to 1). + + Return path of generated script. + ''' + name_without_sh = fname.endswith('.sh') and fname[:-3] or fname + keys.setdefault('Provides', name_without_sh) + keys.setdefault('Required-Start', '$local_fs') + keys.setdefault('Required-Stop', keys['Required-Start']) + keys.setdefault('Default-Start', '2 3 4 5') + keys.setdefault('Default-Stop', '0 1 6') + keys.setdefault('Short-Description', 'test {} service'.format(name_without_sh)) + keys.setdefault('Description', 'long description for test {} service'.format(name_without_sh)) + script = os.path.join(self.init_d_dir, fname) + with open(script, 'w') as f: + f.write('#!/bin/init-d-interpreter\n### BEGIN INIT INFO\n') + for k, v in keys.items(): + if v is not None: + f.write('#{:>20} {}\n'.format(k + ':', v)) + f.write('### END INIT INFO\ncode --goes here\n') + os.chmod(script, 0o755) + + if enable: + def make_link(prefix, runlevel): + d = os.path.join(self.rcnd_dir, 'rc{}.d'.format(runlevel)) + if not os.path.isdir(d): + os.mkdir(d) + os.symlink('../init.d/' + fname, os.path.join(d, prefix + fname)) + + for rl in keys['Default-Start'].split(): + make_link('S%02i' % prio, rl) + for rl in keys['Default-Stop'].split(): + make_link('K%02i' % (99 - prio), rl) + + return script + + def assert_enabled(self, unit, targets): + '''assert that a unit is enabled in precisely the given targets''' + + all_targets = ['multi-user', 'graphical'] + + # should be enabled + for target in all_targets: + link = os.path.join(self.out_dir, '{}.target.wants'.format(target), unit) + if target in targets: + unit_file = os.readlink(link) + # os.path.exists() will fail on a dangling symlink + self.assertTrue(os.path.exists(link)) + self.assertEqual(os.path.basename(unit_file), unit) + else: + self.assertFalse(os.path.exists(link), + '{} unexpectedly exists'.format(link)) + + # + # test cases + # + + def test_nothing(self): + '''no input files''' + + results = self.run_generator()[1] + self.assertEqual(results, {}) + self.assertEqual(os.listdir(self.out_dir), []) + + def test_simple_disabled(self): + '''simple service without dependencies, disabled''' + + self.add_sysv('foo', {}, enable=False) + err, results = self.run_generator() + self.assertEqual(len(results), 1) + + # no enablement links or other stuff + self.assertEqual(os.listdir(self.out_dir), ['foo.service']) + + s = results['foo.service'] + self.assertEqual(s.sections(), ['Unit', 'Service']) + self.assertEqual(s.get('Unit', 'Description'), 'LSB: test foo service') + # $local_fs does not need translation, don't expect any dependency + # fields here + self.assertEqual(set(s.options('Unit')), + set(['Documentation', 'SourcePath', 'Description'])) + + self.assertEqual(s.get('Service', 'Type'), 'forking') + init_script = os.path.join(self.init_d_dir, 'foo') + self.assertEqual(s.get('Service', 'ExecStart'), + '{} start'.format(init_script)) + self.assertEqual(s.get('Service', 'ExecStop'), + '{} stop'.format(init_script)) + + self.assertNotIn('Overwriting', err) + + def test_simple_enabled_all(self): + '''simple service without dependencies, enabled in all runlevels''' + + self.add_sysv('foo', {}, enable=True) + err, results = self.run_generator() + self.assertEqual(list(results), ['foo.service']) + self.assert_enabled('foo.service', ['multi-user', 'graphical']) + self.assertNotIn('Overwriting', err) + + def test_simple_escaped(self): + '''simple service without dependencies, that requires escaping the name''' + + self.add_sysv('foo+', {}) + self.add_sysv('foo-admin', {}) + err, results = self.run_generator() + self.assertEqual(set(results), {'foo-admin.service', 'foo\\x2b.service'}) + self.assertNotIn('Overwriting', err) + + def test_simple_enabled_some(self): + '''simple service without dependencies, enabled in some runlevels''' + + self.add_sysv('foo', {'Default-Start': '2 4'}, enable=True) + err, results = self.run_generator() + self.assertEqual(list(results), ['foo.service']) + self.assert_enabled('foo.service', ['multi-user']) + + def test_lsb_macro_dep_single(self): + '''single LSB macro dependency: $network''' + + self.add_sysv('foo', {'Required-Start': '$network'}) + s = self.run_generator()[1]['foo.service'] + self.assertEqual(set(s.options('Unit')), + set(['Documentation', 'SourcePath', 'Description', 'After', 'Wants'])) + self.assertEqual(s.get('Unit', 'After'), 'network-online.target') + self.assertEqual(s.get('Unit', 'Wants'), 'network-online.target') + + def test_lsb_macro_dep_multi(self): + '''multiple LSB macro dependencies''' + + self.add_sysv('foo', {'Required-Start': '$named $portmap'}) + s = self.run_generator()[1]['foo.service'] + self.assertEqual(set(s.options('Unit')), + set(['Documentation', 'SourcePath', 'Description', 'After'])) + self.assertEqual(s.get('Unit', 'After').split(), ['nss-lookup.target', 'rpcbind.target']) + + def test_lsb_deps(self): + '''LSB header dependencies to other services''' + + # also give symlink priorities here; they should be ignored + self.add_sysv('foo', {'Required-Start': 'must1 must2', + 'Should-Start': 'may1 ne_may2'}, + enable=True, prio=40) + self.add_sysv('must1', {}, enable=True, prio=10) + self.add_sysv('must2', {}, enable=True, prio=15) + self.add_sysv('may1', {}, enable=True, prio=20) + # do not create ne_may2 + err, results = self.run_generator() + self.assertEqual(sorted(results), + ['foo.service', 'may1.service', 'must1.service', 'must2.service']) + + # foo should depend on all of them + self.assertEqual(sorted(results['foo.service'].get('Unit', 'After').split()), + ['may1.service', 'must1.service', 'must2.service', 'ne_may2.service']) + + # other services should not depend on each other + self.assertFalse(results['must1.service'].has_option('Unit', 'After')) + self.assertFalse(results['must2.service'].has_option('Unit', 'After')) + self.assertFalse(results['may1.service'].has_option('Unit', 'After')) + + def test_symlink_prio_deps(self): + '''script without LSB headers use rcN.d priority''' + + # create two init.d scripts without LSB header and enable them with + # startup priorities + for prio, name in [(10, 'provider'), (15, 'consumer')]: + with open(os.path.join(self.init_d_dir, name), 'w') as f: + f.write('#!/bin/init-d-interpreter\ncode --goes here\n') + os.fchmod(f.fileno(), 0o755) + + d = os.path.join(self.rcnd_dir, 'rc2.d') + if not os.path.isdir(d): + os.mkdir(d) + os.symlink('../init.d/' + name, os.path.join(d, 'S{:>2}{}'.format(prio, name))) + + err, results = self.run_generator() + self.assertEqual(sorted(results), ['consumer.service', 'provider.service']) + self.assertFalse(results['provider.service'].has_option('Unit', 'After')) + self.assertEqual(results['consumer.service'].get('Unit', 'After'), + 'provider.service') + + def test_multiple_provides(self): + '''multiple Provides: names''' + + self.add_sysv('foo', {'Provides': 'foo bar baz'}) + err, results = self.run_generator() + self.assertEqual(list(results), ['foo.service']) + self.assertEqual(set(results['foo.service'].options('Unit')), + set(['Documentation', 'SourcePath', 'Description'])) + # should create symlinks for the alternative names + for f in ['bar.service', 'baz.service']: + self.assertEqual(os.readlink(os.path.join(self.out_dir, f)), + 'foo.service') + self.assertNotIn('Overwriting', err) + + def test_provides_escaped(self): + '''a script that Provides: a name that requires escaping''' + + self.add_sysv('foo', {'Provides': 'foo foo+'}) + err, results = self.run_generator() + self.assertEqual(list(results), ['foo.service']) + self.assertEqual(os.readlink(os.path.join(self.out_dir, 'foo\\x2b.service')), + 'foo.service') + self.assertNotIn('Overwriting', err) + + def test_same_provides_in_multiple_scripts(self): + '''multiple init.d scripts provide the same name''' + + self.add_sysv('foo', {'Provides': 'foo common'}, enable=True, prio=1) + self.add_sysv('bar', {'Provides': 'bar common'}, enable=True, prio=2) + err, results = self.run_generator() + self.assertEqual(sorted(results), ['bar.service', 'foo.service']) + # should create symlink for the alternative name for either unit + self.assertIn(os.readlink(os.path.join(self.out_dir, 'common.service')), + ['foo.service', 'bar.service']) + + def test_provide_other_script(self): + '''init.d scripts provides the name of another init.d script''' + + self.add_sysv('foo', {'Provides': 'foo bar'}, enable=True) + self.add_sysv('bar', {'Provides': 'bar'}, enable=True) + err, results = self.run_generator() + self.assertEqual(sorted(results), ['bar.service', 'foo.service']) + # we do expect an overwrite here, bar.service should overwrite the + # alias link from foo.service + self.assertIn('Overwriting', err) + + def test_nonexecutable_script(self): + '''ignores non-executable init.d script''' + + os.chmod(self.add_sysv('foo', {}), 0o644) + err, results = self.run_generator() + self.assertEqual(results, {}) + + def test_sh_suffix(self): + '''init.d script with .sh suffix''' + + self.add_sysv('foo.sh', {}, enable=True) + err, results = self.run_generator() + s = results['foo.service'] + + self.assertEqual(s.sections(), ['Unit', 'Service']) + # should not have a .sh + self.assertEqual(s.get('Unit', 'Description'), 'LSB: test foo service') + + # calls correct script with .sh + init_script = os.path.join(self.init_d_dir, 'foo.sh') + self.assertEqual(s.get('Service', 'ExecStart'), + '{} start'.format(init_script)) + self.assertEqual(s.get('Service', 'ExecStop'), + '{} stop'.format(init_script)) + + self.assert_enabled('foo.service', ['multi-user', 'graphical']) + + def test_sh_suffix_with_provides(self): + '''init.d script with .sh suffix and Provides:''' + + self.add_sysv('foo.sh', {'Provides': 'foo bar'}) + err, results = self.run_generator() + # ensure we don't try to create a symlink to itself + self.assertNotIn('itself', err) + self.assertEqual(list(results), ['foo.service']) + self.assertEqual(results['foo.service'].get('Unit', 'Description'), + 'LSB: test foo service') + + # should create symlink for the alternative name + self.assertEqual(os.readlink(os.path.join(self.out_dir, 'bar.service')), + 'foo.service') + + def test_hidden_files(self): + '''init.d script with hidden file suffix''' + + script = self.add_sysv('foo', {}, enable=True) + # backup files (not enabled in rcN.d/) + shutil.copy(script, script + '.dpkg-new') + shutil.copy(script, script + '.dpkg-dist') + shutil.copy(script, script + '.swp') + shutil.copy(script, script + '.rpmsave') + + err, results = self.run_generator() + self.assertEqual(list(results), ['foo.service']) + + self.assert_enabled('foo.service', ['multi-user', 'graphical']) + + def test_backup_file(self): + '''init.d script with backup file''' + + script = self.add_sysv('foo', {}, enable=True) + # backup files (not enabled in rcN.d/) + shutil.copy(script, script + '.bak') + shutil.copy(script, script + '.old') + shutil.copy(script, script + '.tmp') + shutil.copy(script, script + '.new') + + err, results = self.run_generator() + print(err) + self.assertEqual(sorted(results), ['foo.service', 'foo.tmp.service']) + + # ensure we don't try to create a symlink to itself + self.assertNotIn('itself', err) + + self.assert_enabled('foo.service', ['multi-user', 'graphical']) + self.assert_enabled('foo.bak.service', []) + self.assert_enabled('foo.old.service', []) + + def test_existing_native_unit(self): + '''existing native unit''' + + with open(os.path.join(self.unit_dir, 'foo.service'), 'w') as f: + f.write('[Unit]\n') + + self.add_sysv('foo.sh', {'Provides': 'foo bar'}, enable=True) + err, results = self.run_generator() + self.assertEqual(list(results), []) + # no enablement or alias links, as native unit is disabled + self.assertEqual(os.listdir(self.out_dir), []) + + +if __name__ == '__main__': + unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) diff --git a/test/test-efi-create-disk.sh b/test/test-efi-create-disk.sh new file mode 100755 index 00000000..592b20af --- /dev/null +++ b/test/test-efi-create-disk.sh @@ -0,0 +1,50 @@ +#!/bin/bash -e + +out="$1" +systemd_efi="$2" +boot_stub="$3" +splash_bmp="$4" +if [ -z "$out" -o -z "$systemd_efi" -o -z "$boot_stub" -o -z "$splash_bmp" ]; then + exit 1 +fi + +# create GPT table with EFI System Partition +rm -f "$out" +dd if=/dev/null of="$out" bs=1M seek=512 count=1 status=none +parted --script "$out" "mklabel gpt" "mkpart ESP fat32 1MiB 511MiB" "set 1 boot on" + +# create FAT32 file system +LOOP=$(losetup --show -f -P "$out") +mkfs.vfat -F32 ${LOOP}p1 +mkdir -p mnt +mount ${LOOP}p1 mnt + +mkdir -p mnt/EFI/{BOOT,systemd} +cp "$systemd_efi" mnt/EFI/BOOT/BOOTX64.efi + +[ -e /boot/shellx64.efi ] && cp /boot/shellx64.efi mnt/ + +mkdir mnt/EFI/Linux +echo -n "foo=yes bar=no root=/dev/fakeroot debug rd.break=initqueue" >mnt/cmdline.txt +objcopy \ + --add-section .osrel=/etc/os-release --change-section-vma .osrel=0x20000 \ + --add-section .cmdline=mnt/cmdline.txt --change-section-vma .cmdline=0x30000 \ + --add-section .splash="$splash_bmp" --change-section-vma .splash=0x40000 \ + --add-section .linux=/boot/$(cat /etc/machine-id)/$(uname -r)/linux --change-section-vma .linux=0x2000000 \ + --add-section .initrd=/boot/$(cat /etc/machine-id)/$(uname -r)/initrd --change-section-vma .initrd=0x3000000 \ + "$boot_stub" mnt/EFI/Linux/linux-test.efi + +# install entries +mkdir -p mnt/loader/entries +echo -e "timeout 3\n" > mnt/loader/loader.conf +echo -e "title Test\nefi /test\n" > mnt/loader/entries/test.conf +echo -e "title Test2\nlinux /test2\noptions option=yes word number=1000 more\n" > mnt/loader/entries/test2.conf +echo -e "title Test3\nlinux /test3\n" > mnt/loader/entries/test3.conf +echo -e "title Test4\nlinux /test4\n" > mnt/loader/entries/test4.conf +echo -e "title Test5\nefi /test5\n" > mnt/loader/entries/test5.conf +echo -e "title Test6\nlinux /test6\n" > mnt/loader/entries/test6.conf + +sync +umount mnt +rmdir mnt +losetup -d $LOOP diff --git a/test/test-exec-deserialization.py b/test/test-exec-deserialization.py new file mode 100755 index 00000000..a11c5ecb --- /dev/null +++ b/test/test-exec-deserialization.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ +# +# Copyright © 2017 Michal Sekletar + +# ATTENTION: This uses the *installed* systemd, not the one from the built +# source tree. + +import unittest +import time +import os +import tempfile +import subprocess + +from enum import Enum + +class UnitFileChange(Enum): + NO_CHANGE = 0 + LINES_SWAPPED = 1 + COMMAND_ADDED_BEFORE = 2 + COMMAND_ADDED_AFTER = 3 + COMMAND_INTERLEAVED = 4 + REMOVAL = 5 + +class ExecutionResumeTest(unittest.TestCase): + def setUp(self): + self.unit = 'test-issue-518.service' + self.unitfile_path = '/run/systemd/system/{0}'.format(self.unit) + self.output_file = tempfile.mktemp() + self.unit_files = {} + + unit_file_content = ''' + [Service] + Type=oneshot + ExecStart=/bin/sleep 2 + ExecStart=/bin/bash -c "echo foo >> {0}" + '''.format(self.output_file) + self.unit_files[UnitFileChange.NO_CHANGE] = unit_file_content + + unit_file_content = ''' + [Service] + Type=oneshot + ExecStart=/bin/bash -c "echo foo >> {0}" + ExecStart=/bin/sleep 2 + '''.format(self.output_file) + self.unit_files[UnitFileChange.LINES_SWAPPED] = unit_file_content + + unit_file_content = ''' + [Service] + Type=oneshot + ExecStart=/bin/bash -c "echo bar >> {0}" + ExecStart=/bin/sleep 2 + ExecStart=/bin/bash -c "echo foo >> {0}" + '''.format(self.output_file) + self.unit_files[UnitFileChange.COMMAND_ADDED_BEFORE] = unit_file_content + + unit_file_content = ''' + [Service] + Type=oneshot + ExecStart=/bin/sleep 2 + ExecStart=/bin/bash -c "echo foo >> {0}" + ExecStart=/bin/bash -c "echo bar >> {0}" + '''.format(self.output_file) + self.unit_files[UnitFileChange.COMMAND_ADDED_AFTER] = unit_file_content + + unit_file_content = ''' + [Service] + Type=oneshot + ExecStart=/bin/bash -c "echo baz >> {0}" + ExecStart=/bin/sleep 2 + ExecStart=/bin/bash -c "echo foo >> {0}" + ExecStart=/bin/bash -c "echo bar >> {0}" + '''.format(self.output_file) + self.unit_files[UnitFileChange.COMMAND_INTERLEAVED] = unit_file_content + + unit_file_content = ''' + [Service] + Type=oneshot + ExecStart=/bin/bash -c "echo bar >> {0}" + ExecStart=/bin/bash -c "echo baz >> {0}" + '''.format(self.output_file) + self.unit_files[UnitFileChange.REMOVAL] = unit_file_content + + def reload(self): + subprocess.check_call(['systemctl', 'daemon-reload']) + + def write_unit_file(self, unit_file_change): + if not isinstance(unit_file_change, UnitFileChange): + raise ValueError('Unknown unit file change') + + content = self.unit_files[unit_file_change] + + with open(self.unitfile_path, 'w') as f: + f.write(content) + + self.reload() + + def check_output(self, expected_output): + try: + with open(self.output_file, 'r') as log: + output = log.read() + except IOError: + self.fail() + + self.assertEqual(output, expected_output) + + def setup_unit(self): + self.write_unit_file(UnitFileChange.NO_CHANGE) + subprocess.check_call(['systemctl', '--job-mode=replace', '--no-block', 'start', self.unit]) + + def test_no_change(self): + expected_output = 'foo\n' + + self.setup_unit() + self.reload() + time.sleep(4) + + self.check_output(expected_output) + + def test_swapped(self): + expected_output = '' + + self.setup_unit() + self.write_unit_file(UnitFileChange.LINES_SWAPPED) + self.reload() + time.sleep(4) + + self.assertTrue(not os.path.exists(self.output_file)) + + def test_added_before(self): + expected_output = 'foo\n' + + self.setup_unit() + self.write_unit_file(UnitFileChange.COMMAND_ADDED_BEFORE) + self.reload() + time.sleep(4) + + self.check_output(expected_output) + + def test_added_after(self): + expected_output = 'foo\nbar\n' + + self.setup_unit() + self.write_unit_file(UnitFileChange.COMMAND_ADDED_AFTER) + self.reload() + time.sleep(4) + + self.check_output(expected_output) + + def test_interleaved(self): + expected_output = 'foo\nbar\n' + + self.setup_unit() + self.write_unit_file(UnitFileChange.COMMAND_INTERLEAVED) + self.reload() + time.sleep(4) + + self.check_output(expected_output) + + def test_removal(self): + self.setup_unit() + self.write_unit_file(UnitFileChange.REMOVAL) + self.reload() + time.sleep(4) + + self.assertTrue(not os.path.exists(self.output_file)) + + def test_issue_6533(self): + unit = "test-issue-6533.service" + unitfile_path = "/run/systemd/system/{}".format(unit) + + content = ''' + [Service] + ExecStart=/bin/sleep 5 + ''' + + with open(unitfile_path, 'w') as f: + f.write(content) + + self.reload() + + subprocess.check_call(['systemctl', '--job-mode=replace', '--no-block', 'start', unit]) + time.sleep(2) + + content = ''' + [Service] + ExecStart=/bin/sleep 5 + ExecStart=/bin/true + ''' + + with open(unitfile_path, 'w') as f: + f.write(content) + + self.reload() + time.sleep(5) + + self.assertTrue(subprocess.call("journalctl -b _PID=1 | grep -q 'Freezing execution'", shell=True) != 0) + + def tearDown(self): + for f in [self.output_file, self.unitfile_path]: + try: + os.remove(f) + except OSError: + # ignore error if log file doesn't exist + pass + + self.reload() + +if __name__ == '__main__': + unittest.main() diff --git a/test/test-execute/exec-ambientcapabilities-merge-nfsnobody.service b/test/test-execute/exec-ambientcapabilities-merge-nfsnobody.service new file mode 100644 index 00000000..d2cadebd --- /dev/null +++ b/test/test-execute/exec-ambientcapabilities-merge-nfsnobody.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for AmbientCapabilities + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"' +Type=oneshot +User=nfsnobody +AmbientCapabilities=CAP_CHOWN +AmbientCapabilities=CAP_NET_RAW diff --git a/test/test-execute/exec-ambientcapabilities-merge-nobody.service b/test/test-execute/exec-ambientcapabilities-merge-nobody.service new file mode 100644 index 00000000..545081d6 --- /dev/null +++ b/test/test-execute/exec-ambientcapabilities-merge-nobody.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for AmbientCapabilities + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"' +Type=oneshot +User=nobody +AmbientCapabilities=CAP_CHOWN +AmbientCapabilities=CAP_NET_RAW diff --git a/test/test-execute/exec-ambientcapabilities-merge.service b/test/test-execute/exec-ambientcapabilities-merge.service new file mode 100644 index 00000000..2e3fe591 --- /dev/null +++ b/test/test-execute/exec-ambientcapabilities-merge.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for AmbientCapabilities (daemon) + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"' +Type=oneshot +User=daemon +AmbientCapabilities=CAP_CHOWN +AmbientCapabilities=CAP_NET_RAW diff --git a/test/test-execute/exec-ambientcapabilities-nfsnobody.service b/test/test-execute/exec-ambientcapabilities-nfsnobody.service new file mode 100644 index 00000000..9377ee16 --- /dev/null +++ b/test/test-execute/exec-ambientcapabilities-nfsnobody.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for AmbientCapabilities + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"' +Type=oneshot +User=nfsnobody +AmbientCapabilities=CAP_CHOWN CAP_NET_RAW diff --git a/test/test-execute/exec-ambientcapabilities-nobody.service b/test/test-execute/exec-ambientcapabilities-nobody.service new file mode 100644 index 00000000..07a6c751 --- /dev/null +++ b/test/test-execute/exec-ambientcapabilities-nobody.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for AmbientCapabilities + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"' +Type=oneshot +User=nobody +AmbientCapabilities=CAP_CHOWN CAP_NET_RAW diff --git a/test/test-execute/exec-ambientcapabilities.service b/test/test-execute/exec-ambientcapabilities.service new file mode 100644 index 00000000..d91cc09a --- /dev/null +++ b/test/test-execute/exec-ambientcapabilities.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for AmbientCapabilities (daemon) + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(grep "CapAmb:" /proc/self/status); test "$$c" = "CapAmb: 0000000000002001"' +Type=oneshot +User=daemon +AmbientCapabilities=CAP_CHOWN CAP_NET_RAW diff --git a/test/test-execute/exec-basic.service b/test/test-execute/exec-basic.service new file mode 100644 index 00000000..ae4618c3 --- /dev/null +++ b/test/test-execute/exec-basic.service @@ -0,0 +1,17 @@ +[Unit] +Description=Test for basic execution +ConditionKernelVersion=">=3.0" +ConditionKernelVersion=">=2.0" "<=60" "!=1.4" +ConditionKernelVersion=" >= 2.0" " <= 60 " "!= 1.4" +ConditionKernelVersion=" >= 2.0" " * " "*.*" + +[Service] +ExecStart=touch /tmp/a ; /bin/sh -c 'touch /tmp/b' ; touch /tmp/c +ExecStart=test -f /tmp/a +ExecStart=!test -f /tmp/b +ExecStart=!!test -f /tmp/c +ExecStart=+test -f /tmp/c +ExecStartPost=rm /tmp/a /tmp/b /tmp/c + +PrivateTmp=true +Type=oneshot diff --git a/test/test-execute/exec-bindpaths.service b/test/test-execute/exec-bindpaths.service new file mode 100644 index 00000000..edab18bb --- /dev/null +++ b/test/test-execute/exec-bindpaths.service @@ -0,0 +1,17 @@ +[Unit] +Description=Test for BindPaths= and BindReadOnlyPaths= + +[Service] +Type=oneshot +# Create a file in /tmp/test-exec-bindpaths +ExecStart=touch /tmp/test-exec-bindpaths/thisisasimpletest +# Then, the file can be access through /tmp +ExecStart=test -f /tmp/thisisasimpletest +# Also, through /tmp/test-exec-bindreadonlypaths +ExecStart=test -f /tmp/test-exec-bindreadonlypaths/thisisasimpletest +# The file cannot modify through /tmp/test-exec-bindreadonlypaths +ExecStart=/bin/sh -x -c '! touch /tmp/test-exec-bindreadonlypaths/thisisasimpletest' +# Cleanup +ExecStart=rm /tmp/thisisasimpletest +BindPaths=/tmp:/tmp/test-exec-bindpaths +BindReadOnlyPaths=/tmp:/tmp/test-exec-bindreadonlypaths diff --git a/test/test-execute/exec-capabilityboundingset-invert.service b/test/test-execute/exec-capabilityboundingset-invert.service new file mode 100644 index 00000000..5f374276 --- /dev/null +++ b/test/test-execute/exec-capabilityboundingset-invert.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for CapabilityBoundingSet + +[Service] +# sed: remove dropped capabilities (cap_xxx-[epi]) from the output +ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep "^Bounding set .*cap_chown"' +Type=oneshot +CapabilityBoundingSet=~CAP_CHOWN diff --git a/test/test-execute/exec-capabilityboundingset-merge.service b/test/test-execute/exec-capabilityboundingset-merge.service new file mode 100644 index 00000000..5c7fcaf4 --- /dev/null +++ b/test/test-execute/exec-capabilityboundingset-merge.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for CapabilityBoundingSet + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set =cap_chown,cap_fowner,cap_kill"' +Type=oneshot +CapabilityBoundingSet=CAP_FOWNER +CapabilityBoundingSet=CAP_KILL CAP_CHOWN diff --git a/test/test-execute/exec-capabilityboundingset-reset.service b/test/test-execute/exec-capabilityboundingset-reset.service new file mode 100644 index 00000000..d7d33202 --- /dev/null +++ b/test/test-execute/exec-capabilityboundingset-reset.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for CapabilityBoundingSet + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set ="' +Type=oneshot +CapabilityBoundingSet=CAP_FOWNER CAP_KILL +CapabilityBoundingSet= diff --git a/test/test-execute/exec-capabilityboundingset-simple.service b/test/test-execute/exec-capabilityboundingset-simple.service new file mode 100644 index 00000000..bf1a7f57 --- /dev/null +++ b/test/test-execute/exec-capabilityboundingset-simple.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for CapabilityBoundingSet + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(capsh --print | grep "Bounding set "); test "$$c" = "Bounding set =cap_fowner,cap_kill"' +Type=oneshot +CapabilityBoundingSet=CAP_FOWNER CAP_KILL diff --git a/test/test-execute/exec-condition-failed.service b/test/test-execute/exec-condition-failed.service new file mode 100644 index 00000000..4a406dc1 --- /dev/null +++ b/test/test-execute/exec-condition-failed.service @@ -0,0 +1,11 @@ +[Unit] +Description=Test for exec condition that fails the unit + +[Service] +Type=oneshot + +# exit 255 will fail the unit +ExecCondition=/bin/sh -c 'exit 255' + +# This should not get run +ExecStart=/bin/sh -c 'true' diff --git a/test/test-execute/exec-condition-skip.service b/test/test-execute/exec-condition-skip.service new file mode 100644 index 00000000..9450e844 --- /dev/null +++ b/test/test-execute/exec-condition-skip.service @@ -0,0 +1,15 @@ +[Unit] +Description=Test for exec condition that triggers skipping + +[Service] +Type=oneshot + +# exit codes [1, 254] will result in skipping the rest of execution +ExecCondition=/bin/sh -c 'exit 0' +ExecCondition=/bin/sh -c 'exit 254' + +# This would normally fail the unit but will not get run due to the skip above +ExecCondition=/bin/sh -c 'exit 255' + +# This should not get run +ExecStart=/bin/sh -c 'true' diff --git a/test/test-execute/exec-cpuaffinity1.service b/test/test-execute/exec-cpuaffinity1.service new file mode 100644 index 00000000..84d550a3 --- /dev/null +++ b/test/test-execute/exec-cpuaffinity1.service @@ -0,0 +1,6 @@ +[Unit] +Description=Test for CPUAffinity (simple) + +[Service] +ExecStart=/bin/sh -c 'test $$(cat /proc/self/status | grep Cpus_allowed: | rev | cut -c 1) = 1' +CPUAffinity=0 diff --git a/test/test-execute/exec-cpuaffinity2.service b/test/test-execute/exec-cpuaffinity2.service new file mode 100644 index 00000000..0dda77f9 --- /dev/null +++ b/test/test-execute/exec-cpuaffinity2.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for CPUAffinity (reset) + +[Service] +ExecStart=/bin/sh -c 'test $$(cat /proc/self/status | grep Cpus_allowed: | rev | cut -c 1) = 1' +CPUAffinity=0-1 3 +CPUAffinity= +CPUAffinity=0 diff --git a/test/test-execute/exec-cpuaffinity3.service b/test/test-execute/exec-cpuaffinity3.service new file mode 100644 index 00000000..4a45d3b2 --- /dev/null +++ b/test/test-execute/exec-cpuaffinity3.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for CPUAffinity (merge) + +[Service] +ExecStart=/bin/sh -c 'test $$(cat /proc/self/status | grep Cpus_allowed: | rev | cut -c 1) = 7' +CPUAffinity=0,1 +CPUAffinity=1-2 diff --git a/test/test-execute/exec-dynamicuser-fixeduser-adm.service b/test/test-execute/exec-dynamicuser-fixeduser-adm.service new file mode 100644 index 00000000..90040ee5 --- /dev/null +++ b/test/test-execute/exec-dynamicuser-fixeduser-adm.service @@ -0,0 +1,11 @@ +[Unit] +Description=Test DynamicUser with static User= whose uid and gid are different +# On Fedora, user adm has uid==3 and gid==4. + +[Service] +Type=oneshot +ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "adm" && test "$$(id -ng)" = "adm" && test "$$(id -nu)" = "adm"' +# Multiple ExecStart= lines causes the issue #9702. +ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "adm" && test "$$(id -ng)" = "adm" && test "$$(id -nu)" = "adm"' +DynamicUser=yes +User=adm diff --git a/test/test-execute/exec-dynamicuser-fixeduser-games.service b/test/test-execute/exec-dynamicuser-fixeduser-games.service new file mode 100644 index 00000000..1cc9518f --- /dev/null +++ b/test/test-execute/exec-dynamicuser-fixeduser-games.service @@ -0,0 +1,11 @@ +[Unit] +Description=Test DynamicUser with static User= whose uid and gid are different +# On Ubuntu or Debian, user games has uid==5 and gid==60. + +[Service] +Type=oneshot +ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "games" && test "$$(id -ng)" = "games" && test "$$(id -nu)" = "games"' +# Multiple ExecStart= lines causes the issue #9702. +ExecStart=/bin/sh -x -c 'test "$$(id -nG)" = "games" && test "$$(id -ng)" = "games" && test "$$(id -nu)" = "games"' +DynamicUser=yes +User=games diff --git a/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service b/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service new file mode 100644 index 00000000..bd7881d2 --- /dev/null +++ b/test/test-execute/exec-dynamicuser-fixeduser-one-supplementarygroup.service @@ -0,0 +1,10 @@ +[Unit] +Description=Test DynamicUser with User= and SupplementaryGroups= + +[Service] +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "1"' +Type=oneshot +User=1 +DynamicUser=yes +SupplementaryGroups=1 diff --git a/test/test-execute/exec-dynamicuser-fixeduser.service b/test/test-execute/exec-dynamicuser-fixeduser.service new file mode 100644 index 00000000..f28078f2 --- /dev/null +++ b/test/test-execute/exec-dynamicuser-fixeduser.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test DynamicUser with User= + +[Service] +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "1"' +Type=oneshot +User=1 +DynamicUser=yes diff --git a/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service b/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service new file mode 100644 index 00000000..5efc5483 --- /dev/null +++ b/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service @@ -0,0 +1,17 @@ +[Unit] +Description=Test DynamicUser= migrate StateDirectory= (preparation) + +[Service] +ExecStart=test -w /var/lib/test-dynamicuser-migrate +ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge +ExecStart=test ! -L /var/lib/test-dynamicuser-migrate +ExecStart=test ! -L /var/lib/test-dynamicuser-migrate2/hoge +ExecStart=test -d /var/lib/test-dynamicuser-migrate +ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge +ExecStart=touch /var/lib/test-dynamicuser-migrate/yay +ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay +ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/test-dynamicuser-migrate:%S/test-dynamicuser-migrate2/hoge"' + +Type=oneshot +DynamicUser=no +StateDirectory=test-dynamicuser-migrate test-dynamicuser-migrate2/hoge diff --git a/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service b/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service new file mode 100644 index 00000000..c72302ff --- /dev/null +++ b/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service @@ -0,0 +1,25 @@ +[Unit] +Description=Test DynamicUser= migrate StateDirectory= + +[Service] +ExecStart=test -w /var/lib/test-dynamicuser-migrate +ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge +ExecStart=test -L /var/lib/test-dynamicuser-migrate +ExecStart=test -L /var/lib/test-dynamicuser-migrate2/hoge +ExecStart=test -d /var/lib/test-dynamicuser-migrate +ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge +ExecStart=test -f /var/lib/test-dynamicuser-migrate/yay +ExecStart=test -f /var/lib/test-dynamicuser-migrate2/hoge/yayyay +ExecStart=test -d /var/lib/private/test-dynamicuser-migrate +ExecStart=test -d /var/lib/private/test-dynamicuser-migrate2/hoge +ExecStart=test -f /var/lib/private/test-dynamicuser-migrate/yay +ExecStart=test -f /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay +ExecStart=touch /var/lib/test-dynamicuser-migrate/yay +ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay +ExecStart=touch /var/lib/private/test-dynamicuser-migrate/yay +ExecStart=touch /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay +ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/test-dynamicuser-migrate:%S/test-dynamicuser-migrate2/hoge"' + +Type=oneshot +DynamicUser=yes +StateDirectory=test-dynamicuser-migrate test-dynamicuser-migrate2/hoge diff --git a/test/test-execute/exec-dynamicuser-statedir.service b/test/test-execute/exec-dynamicuser-statedir.service new file mode 100644 index 00000000..ca40934d --- /dev/null +++ b/test/test-execute/exec-dynamicuser-statedir.service @@ -0,0 +1,20 @@ +[Unit] +Description=Test DynamicUser= with StateDirectory= + +[Service] +ExecStart=test -w /var/lib/waldo +ExecStart=test -w /var/lib/quux/pief +ExecStart=touch /var/lib/waldo/yay +ExecStart=touch /var/lib/quux/pief/yayyay +ExecStart=test -f /var/lib/waldo/yay +ExecStart=test -f /var/lib/quux/pief/yayyay +ExecStart=test -f /var/lib/private/waldo/yay +ExecStart=test -f /var/lib/private/quux/pief/yayyay +ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/waldo:%S/quux/pief"' + +# Make sure that /var/lib/private/waldo is really the only writable directory besides the obvious candidates +ExecStart=sh -x -c 'test $$(find / \( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf -o -path /dev/.lxc \) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo' + +Type=oneshot +DynamicUser=yes +StateDirectory=waldo quux/pief diff --git a/test/test-execute/exec-dynamicuser-supplementarygroups.service b/test/test-execute/exec-dynamicuser-supplementarygroups.service new file mode 100644 index 00000000..e3549c22 --- /dev/null +++ b/test/test-execute/exec-dynamicuser-supplementarygroups.service @@ -0,0 +1,10 @@ +[Unit] +Description=Test DynamicUser with SupplementaryGroups= + +[Service] +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1' +Type=oneshot +DynamicUser=yes +SupplementaryGroups=1 2 3 diff --git a/test/test-execute/exec-environment-empty.service b/test/test-execute/exec-environment-empty.service new file mode 100644 index 00000000..9c92d4bc --- /dev/null +++ b/test/test-execute/exec-environment-empty.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for Environment + +[Service] +ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset"' +Type=oneshot +Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" +Environment= diff --git a/test/test-execute/exec-environment-multiple.service b/test/test-execute/exec-environment-multiple.service new file mode 100644 index 00000000..b9bc2256 --- /dev/null +++ b/test/test-execute/exec-environment-multiple.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for Environment + +[Service] +ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = foobar' +Type=oneshot +Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" +Environment="VAR3=foobar" diff --git a/test/test-execute/exec-environment-no-substitute.service b/test/test-execute/exec-environment-no-substitute.service new file mode 100644 index 00000000..6a2e60ec --- /dev/null +++ b/test/test-execute/exec-environment-no-substitute.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for No Environment Variable Substitution + +[Service] +ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2}" = "word3" && test "$${VAR3-unset}" = \'$word 5 6\'' +ExecStart=:/bin/sh -x -c 'test "$${VAR1-unset}" != "unset" && test "$${VAR2}" != "word3" && test "$${VAR3-unset}" != \'$word 5 6\'' +Type=oneshot +Environment="VAR2=word3" "VAR3=$word 5 6" diff --git a/test/test-execute/exec-environment.service b/test/test-execute/exec-environment.service new file mode 100644 index 00000000..06e77af2 --- /dev/null +++ b/test/test-execute/exec-environment.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Environment + +[Service] +ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6"' +Type=oneshot +Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" diff --git a/test/test-execute/exec-environmentfile.service b/test/test-execute/exec-environmentfile.service new file mode 100644 index 00000000..9bcb133a --- /dev/null +++ b/test/test-execute/exec-environmentfile.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for EnvironmentFile + +[Service] +ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes' +Type=oneshot +EnvironmentFile=/tmp/test-exec_environmentfile.conf diff --git a/test/test-execute/exec-group-nfsnobody.service b/test/test-execute/exec-group-nfsnobody.service new file mode 100644 index 00000000..e02100a8 --- /dev/null +++ b/test/test-execute/exec-group-nfsnobody.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Group + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "nfsnobody"' +Type=oneshot +Group=nfsnobody diff --git a/test/test-execute/exec-group-nobody.service b/test/test-execute/exec-group-nobody.service new file mode 100644 index 00000000..be7c7969 --- /dev/null +++ b/test/test-execute/exec-group-nobody.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Group + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "nobody"' +Type=oneshot +Group=nobody diff --git a/test/test-execute/exec-group-nogroup.service b/test/test-execute/exec-group-nogroup.service new file mode 100644 index 00000000..cf077322 --- /dev/null +++ b/test/test-execute/exec-group-nogroup.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Group + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "nogroup"' +Type=oneshot +Group=nogroup diff --git a/test/test-execute/exec-group.service b/test/test-execute/exec-group.service new file mode 100644 index 00000000..be559923 --- /dev/null +++ b/test/test-execute/exec-group.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Group (daemon) + +[Service] +ExecStart=/bin/sh -x -c 'test "$$(id -n -g)" = "daemon"' +Type=oneshot +Group=daemon diff --git a/test/test-execute/exec-ignoresigpipe-no.service b/test/test-execute/exec-ignoresigpipe-no.service new file mode 100644 index 00000000..73addf5f --- /dev/null +++ b/test/test-execute/exec-ignoresigpipe-no.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IgnoreSIGPIPE=no + +[Service] +ExecStart=/bin/sh -x -c 'kill -PIPE 0' +Type=oneshot +IgnoreSIGPIPE=no diff --git a/test/test-execute/exec-ignoresigpipe-yes.service b/test/test-execute/exec-ignoresigpipe-yes.service new file mode 100644 index 00000000..f81c0171 --- /dev/null +++ b/test/test-execute/exec-ignoresigpipe-yes.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IgnoreSIGPIPE=yes + +[Service] +ExecStart=/bin/sh -x -c 'kill -PIPE 0' +Type=oneshot +IgnoreSIGPIPE=yes diff --git a/test/test-execute/exec-inaccessiblepaths-mount-propagation.service b/test/test-execute/exec-inaccessiblepaths-mount-propagation.service new file mode 100644 index 00000000..430a6b78 --- /dev/null +++ b/test/test-execute/exec-inaccessiblepaths-mount-propagation.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test to make sure that InaccessiblePaths= disconnect mount propagation + +[Service] +InaccessiblePaths=-/i-dont-exist +ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo' +Type=oneshot diff --git a/test/test-execute/exec-inaccessiblepaths-sys.service b/test/test-execute/exec-inaccessiblepaths-sys.service new file mode 100644 index 00000000..5ff6f360 --- /dev/null +++ b/test/test-execute/exec-inaccessiblepaths-sys.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test to make sure that mount namespace setup works properly with the 'InaccessiblePaths=/proc' option + +[Service] +InaccessiblePaths=/sys +ExecStart=/bin/sh -x -c 'test "$$(stat -c %%a /sys)" = "0"' +Type=oneshot diff --git a/test/test-execute/exec-ioschedulingclass-best-effort.service b/test/test-execute/exec-ioschedulingclass-best-effort.service new file mode 100644 index 00000000..29bb8510 --- /dev/null +++ b/test/test-execute/exec-ioschedulingclass-best-effort.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IOSchedulingClass=best-effort + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "best-effort"' +Type=oneshot +IOSchedulingClass=best-effort diff --git a/test/test-execute/exec-ioschedulingclass-idle.service b/test/test-execute/exec-ioschedulingclass-idle.service new file mode 100644 index 00000000..87dbed14 --- /dev/null +++ b/test/test-execute/exec-ioschedulingclass-idle.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IOSchedulingClass=idle + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "idle"' +Type=oneshot +IOSchedulingClass=idle diff --git a/test/test-execute/exec-ioschedulingclass-none.service b/test/test-execute/exec-ioschedulingclass-none.service new file mode 100644 index 00000000..b6af122a --- /dev/null +++ b/test/test-execute/exec-ioschedulingclass-none.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IOSchedulingClass=none + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "none"' +Type=oneshot +IOSchedulingClass=none diff --git a/test/test-execute/exec-ioschedulingclass-realtime.service b/test/test-execute/exec-ioschedulingclass-realtime.service new file mode 100644 index 00000000..d920d5c6 --- /dev/null +++ b/test/test-execute/exec-ioschedulingclass-realtime.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IOSchedulingClass=realtime + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "realtime"' +Type=oneshot +IOSchedulingClass=realtime diff --git a/test/test-execute/exec-oomscoreadjust-negative.service b/test/test-execute/exec-oomscoreadjust-negative.service new file mode 100644 index 00000000..2234c53c --- /dev/null +++ b/test/test-execute/exec-oomscoreadjust-negative.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for OOMScoreAdjust + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(cat /proc/self/oom_score_adj); test "$$c" -eq -100' +Type=oneshot +OOMScoreAdjust=-100 diff --git a/test/test-execute/exec-oomscoreadjust-positive.service b/test/test-execute/exec-oomscoreadjust-positive.service new file mode 100644 index 00000000..456a8f80 --- /dev/null +++ b/test/test-execute/exec-oomscoreadjust-positive.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for OOMScoreAdjust + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(cat /proc/self/oom_score_adj); test "$$c" -eq 100' +Type=oneshot +OOMScoreAdjust=100 diff --git a/test/test-execute/exec-passenvironment-absent.service b/test/test-execute/exec-passenvironment-absent.service new file mode 100644 index 00000000..d257e48c --- /dev/null +++ b/test/test-execute/exec-passenvironment-absent.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PassEnvironment with variables absent from the execution environment + +[Service] +ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset" && test "$${VAR4-unset}" = "unset" && test "$${VAR5-unset}" = "unset"' +Type=oneshot +PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5 diff --git a/test/test-execute/exec-passenvironment-empty.service b/test/test-execute/exec-passenvironment-empty.service new file mode 100644 index 00000000..291259a3 --- /dev/null +++ b/test/test-execute/exec-passenvironment-empty.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for PassEnvironment and erasing the variable list + +[Service] +ExecStart=/bin/sh -x -c 'test "$${VAR1-unset}" = "unset" && test "$${VAR2-unset}" = "unset" && test "$${VAR3-unset}" = "unset" && test "$${VAR4-unset}" = "unset" && test "$${VAR5-unset}" = "unset"' +Type=oneshot +PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5 +PassEnvironment= diff --git a/test/test-execute/exec-passenvironment-repeated.service b/test/test-execute/exec-passenvironment-repeated.service new file mode 100644 index 00000000..e8869980 --- /dev/null +++ b/test/test-execute/exec-passenvironment-repeated.service @@ -0,0 +1,10 @@ +[Unit] +Description=Test for PassEnvironment with a variable name repeated + +[Service] +ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes' +Type=oneshot +PassEnvironment=VAR1 VAR2 +PassEnvironment=VAR1 VAR3 +PassEnvironment=VAR1 VAR4 +PassEnvironment=VAR1 VAR5 diff --git a/test/test-execute/exec-passenvironment.service b/test/test-execute/exec-passenvironment.service new file mode 100644 index 00000000..05c1bdfe --- /dev/null +++ b/test/test-execute/exec-passenvironment.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PassEnvironment + +[Service] +ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes' +Type=oneshot +PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5 diff --git a/test/test-execute/exec-personality-aarch64.service b/test/test-execute/exec-personality-aarch64.service new file mode 100644 index 00000000..85111744 --- /dev/null +++ b/test/test-execute/exec-personality-aarch64.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Personality=aarch64 + +[Service] +ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "aarch64")' +Type=oneshot +Personality=aarch64 diff --git a/test/test-execute/exec-personality-ppc64.service b/test/test-execute/exec-personality-ppc64.service new file mode 100644 index 00000000..ccc2c8d8 --- /dev/null +++ b/test/test-execute/exec-personality-ppc64.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Personality=ppc64 + +[Service] +ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "ppc64")' +Type=oneshot +Personality=ppc64 diff --git a/test/test-execute/exec-personality-ppc64le.service b/test/test-execute/exec-personality-ppc64le.service new file mode 100644 index 00000000..2a762508 --- /dev/null +++ b/test/test-execute/exec-personality-ppc64le.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Personality=ppc64le + +[Service] +ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "ppc64le")' +Type=oneshot +Personality=ppc64le diff --git a/test/test-execute/exec-personality-s390.service b/test/test-execute/exec-personality-s390.service new file mode 100644 index 00000000..89f7de89 --- /dev/null +++ b/test/test-execute/exec-personality-s390.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Personality=s390 + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "s390"' +Type=oneshot +Personality=s390 diff --git a/test/test-execute/exec-personality-x86-64.service b/test/test-execute/exec-personality-x86-64.service new file mode 100644 index 00000000..433e69a6 --- /dev/null +++ b/test/test-execute/exec-personality-x86-64.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Personality=x86-64 + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "x86_64"' +Type=oneshot +Personality=x86-64 diff --git a/test/test-execute/exec-personality-x86.service b/test/test-execute/exec-personality-x86.service new file mode 100644 index 00000000..4ece7de7 --- /dev/null +++ b/test/test-execute/exec-personality-x86.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Personality=x86 + +[Service] +ExecStart=/bin/sh -x -c 'c=$$(uname -m); test "$$c" = "i686" -o "$$c" = "x86_64"' +Type=oneshot +Personality=x86 diff --git a/test/test-execute/exec-privatedevices-disabled-by-prefix.service b/test/test-execute/exec-privatedevices-disabled-by-prefix.service new file mode 100644 index 00000000..19b1da52 --- /dev/null +++ b/test/test-execute/exec-privatedevices-disabled-by-prefix.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for PrivateDevices=yes with prefix + +[Service] +ExecStart=/bin/sh -x -c '! test -c /dev/kmsg' +ExecStart=+/bin/sh -x -c 'test -c /dev/kmsg' +Type=oneshot +PrivateDevices=yes diff --git a/test/test-execute/exec-privatedevices-no-capability-mknod.service b/test/test-execute/exec-privatedevices-no-capability-mknod.service new file mode 100644 index 00000000..4d61d9ff --- /dev/null +++ b/test/test-execute/exec-privatedevices-no-capability-mknod.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test CAP_MKNOD capability for PrivateDevices=no + +[Service] +PrivateDevices=no +# sed: remove dropped capabilities (cap_xxx-[epi]) from the output +ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_mknod' +Type=oneshot diff --git a/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service b/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service new file mode 100644 index 00000000..f7f7a167 --- /dev/null +++ b/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test CAP_SYS_RAWIO capability for PrivateDevices=no + +[Service] +PrivateDevices=no +# sed: remove dropped capabilities (cap_xxx-[epi]) from the output +ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_rawio' +Type=oneshot diff --git a/test/test-execute/exec-privatedevices-no.service b/test/test-execute/exec-privatedevices-no.service new file mode 100644 index 00000000..4ddbf189 --- /dev/null +++ b/test/test-execute/exec-privatedevices-no.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PrivateDevices=no + +[Service] +ExecStart=/bin/sh -x -c 'test -c /dev/kmsg' +Type=oneshot +PrivateDevices=no diff --git a/test/test-execute/exec-privatedevices-yes-capability-mknod.service b/test/test-execute/exec-privatedevices-yes-capability-mknod.service new file mode 100644 index 00000000..5bcace08 --- /dev/null +++ b/test/test-execute/exec-privatedevices-yes-capability-mknod.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test CAP_MKNOD capability for PrivateDevices=yes + +[Service] +PrivateDevices=yes +# sed: remove dropped capabilities (cap_xxx-[epi]) from the output +ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_mknod' +Type=oneshot diff --git a/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service b/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service new file mode 100644 index 00000000..a246f950 --- /dev/null +++ b/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test CAP_SYS_RAWIO capability for PrivateDevices=yes + +[Service] +PrivateDevices=yes +# sed: remove dropped capabilities (cap_xxx-[epi]) from the output +ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_rawio' +Type=oneshot diff --git a/test/test-execute/exec-privatedevices-yes.service b/test/test-execute/exec-privatedevices-yes.service new file mode 100644 index 00000000..35166672 --- /dev/null +++ b/test/test-execute/exec-privatedevices-yes.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PrivateDevices=yes + +[Service] +ExecStart=/bin/sh -c 'test ! -c /dev/kmsg' +Type=oneshot +PrivateDevices=yes diff --git a/test/test-execute/exec-privatenetwork-yes.service b/test/test-execute/exec-privatenetwork-yes.service new file mode 100644 index 00000000..8f5cbadf --- /dev/null +++ b/test/test-execute/exec-privatenetwork-yes.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PrivateNetwork + +[Service] +ExecStart=/bin/sh -x -c '! ip link | grep -E "^[0-9]+: " | grep -Ev ": (lo|(erspan|gre|gretap|ip_vti|ip6_vti|ip6gre|ip6tnl|sit|tunl)0@.*):"' +Type=oneshot +PrivateNetwork=yes diff --git a/test/test-execute/exec-privatetmp-no.service b/test/test-execute/exec-privatetmp-no.service new file mode 100644 index 00000000..59f60f47 --- /dev/null +++ b/test/test-execute/exec-privatetmp-no.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PrivateTmp=no + +[Service] +ExecStart=/bin/sh -x -c 'test -f /tmp/test-exec_privatetmp' +Type=oneshot +PrivateTmp=no diff --git a/test/test-execute/exec-privatetmp-yes.service b/test/test-execute/exec-privatetmp-yes.service new file mode 100644 index 00000000..907c291b --- /dev/null +++ b/test/test-execute/exec-privatetmp-yes.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PrivateTmp=yes + +[Service] +ExecStart=/bin/sh -x -c 'test ! -f /tmp/test-exec_privatetmp' +Type=oneshot +PrivateTmp=yes diff --git a/test/test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service b/test/test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service new file mode 100644 index 00000000..1522ff80 --- /dev/null +++ b/test/test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test ProtectHome=tmpfs vs ProtectSystem=strict +# Test for #11276 + +[Service] +ProtectHome=tmpfs +ProtectSystem=strict +Type=oneshot +ExecStart=/bin/sh -x -c 'test "$$(stat -fc %%T /home)" = "tmpfs"' diff --git a/test/test-execute/exec-protectkernellogs-no-capabilities.service b/test/test-execute/exec-protectkernellogs-no-capabilities.service new file mode 100644 index 00000000..47d88534 --- /dev/null +++ b/test/test-execute/exec-protectkernellogs-no-capabilities.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test CAP_SYSLOG for ProtectKernelLogs=no + +[Service] +ProtectKernelLogs=no +# sed: remove dropped capabilities (cap_xxx-[epi]) from the output +ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_syslog' +Type=oneshot diff --git a/test/test-execute/exec-protectkernellogs-yes-capabilities.service b/test/test-execute/exec-protectkernellogs-yes-capabilities.service new file mode 100644 index 00000000..11350f28 --- /dev/null +++ b/test/test-execute/exec-protectkernellogs-yes-capabilities.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test CAP_SYSLOG for ProtectKernelLogs=yes + +[Service] +ProtectKernelLogs=yes +# sed: remove dropped capabilities (cap_xxx-[epi]) from the output +ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_syslog' +Type=oneshot diff --git a/test/test-execute/exec-protectkernelmodules-no-capabilities.service b/test/test-execute/exec-protectkernelmodules-no-capabilities.service new file mode 100644 index 00000000..8d7e2b52 --- /dev/null +++ b/test/test-execute/exec-protectkernelmodules-no-capabilities.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test CAP_SYS_MODULE ProtectKernelModules=no + +[Service] +ProtectKernelModules=no +# sed: remove dropped capabilities (cap_xxx-[epi]) from the output +ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_module' +Type=oneshot diff --git a/test/test-execute/exec-protectkernelmodules-yes-capabilities.service b/test/test-execute/exec-protectkernelmodules-yes-capabilities.service new file mode 100644 index 00000000..fe2ae208 --- /dev/null +++ b/test/test-execute/exec-protectkernelmodules-yes-capabilities.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test CAP_SYS_MODULE for ProtectKernelModules=yes + +[Service] +ProtectKernelModules=yes +# sed: remove dropped capabilities (cap_xxx-[epi]) from the output +ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_module' +Type=oneshot diff --git a/test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service b/test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service new file mode 100644 index 00000000..07758121 --- /dev/null +++ b/test/test-execute/exec-protectkernelmodules-yes-mount-propagation.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test to make sure that passing ProtectKernelModules=yes disconnect mount propagation + +[Service] +ProtectKernelModules=yes +ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo' +Type=oneshot diff --git a/test/test-execute/exec-readonlypaths-mount-propagation.service b/test/test-execute/exec-readonlypaths-mount-propagation.service new file mode 100644 index 00000000..7edb0daa --- /dev/null +++ b/test/test-execute/exec-readonlypaths-mount-propagation.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test to make sure that passing ReadOnlyPaths= disconnect mount propagation + +[Service] +ReadOnlyPaths=-/i-dont-exist +ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo' +Type=oneshot diff --git a/test/test-execute/exec-readonlypaths-simple.service b/test/test-execute/exec-readonlypaths-simple.service new file mode 100644 index 00000000..a9a71590 --- /dev/null +++ b/test/test-execute/exec-readonlypaths-simple.service @@ -0,0 +1,11 @@ +[Unit] +Description=Test for ReadOnlyPaths= + +[Service] +Type=oneshot +# This should work, as we explicitly disable the effect of ReadOnlyPaths= +ExecStart=+/bin/sh -c 'touch /tmp/thisisasimpletest' +# This should also work, as we do not disable the effect of ReadOnlyPaths= but invert the exit code +ExecStart=/bin/sh -x -c '! touch /tmp/thisisasimpletest' +ExecStart=+/bin/sh -c 'rm /tmp/thisisasimpletest' +ReadOnlyPaths=/tmp diff --git a/test/test-execute/exec-readonlypaths-with-bindpaths.service b/test/test-execute/exec-readonlypaths-with-bindpaths.service new file mode 100644 index 00000000..438c7de7 --- /dev/null +++ b/test/test-execute/exec-readonlypaths-with-bindpaths.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for ReadOnlyPaths= + +[Service] +ReadOnlyPaths=/etc -/i-dont-exist /usr +BindPaths=/etc:/tmp/etc2 +ExecStart=/bin/sh -x -c 'test ! -w /etc && test ! -w /usr && test ! -e /i-dont-exist && test -w /var' +Type=oneshot diff --git a/test/test-execute/exec-readonlypaths.service b/test/test-execute/exec-readonlypaths.service new file mode 100644 index 00000000..a0ca68f6 --- /dev/null +++ b/test/test-execute/exec-readonlypaths.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for ReadOnlyPaths= + +[Service] +ReadOnlyPaths=/usr /etc /sys /dev -/i-dont-exist +PrivateDevices=yes +ExecStart=/bin/sh -x -c 'test ! -w /usr && test ! -w /etc && test ! -w /sys && test ! -w /sys/fs/cgroup' +ExecStart=/bin/sh -x -c 'test ! -w /dev && test ! -w /dev/shm && test ! -e /i-dont-exist && test -w /var' +Type=oneshot diff --git a/test/test-execute/exec-readwritepaths-mount-propagation.service b/test/test-execute/exec-readwritepaths-mount-propagation.service new file mode 100644 index 00000000..b38978df --- /dev/null +++ b/test/test-execute/exec-readwritepaths-mount-propagation.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test to make sure that passing ReadWritePaths= disconnect mount propagation + +[Service] +ReadWritePaths=-/i-dont-exist +ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); trap "umount \'$$d\' && rmdir \'$$d\'" EXIT; mount -t tmpfs tmpfs "$$d"; grep "$$d" /proc/self/mountinfo && ! grep "$$d" /proc/$${PPID}/mountinfo && ! grep "$$d" /proc/1/mountinfo' +Type=oneshot diff --git a/test/test-execute/exec-restrictnamespaces-merge-all.service b/test/test-execute/exec-restrictnamespaces-merge-all.service new file mode 100644 index 00000000..de98cd0a --- /dev/null +++ b/test/test-execute/exec-restrictnamespaces-merge-all.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test merging RestrictNamespaces= with all flags + +[Service] +RestrictNamespaces=mnt pid cgroup net uts ipc user +RestrictNamespaces=net +ExecStart=unshare -m -u -i -n -p -f +Type=oneshot diff --git a/test/test-execute/exec-restrictnamespaces-merge-and.service b/test/test-execute/exec-restrictnamespaces-merge-and.service new file mode 100644 index 00000000..6702e6aa --- /dev/null +++ b/test/test-execute/exec-restrictnamespaces-merge-and.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test merging RestrictNamespaces= with AND + +[Service] +RestrictNamespaces=mnt pid +RestrictNamespaces=~mnt usr +ExecStart=unshare -p -f +ExecStart=sh -c '! unshare -m -u -i -n' +Type=oneshot diff --git a/test/test-execute/exec-restrictnamespaces-merge-or.service b/test/test-execute/exec-restrictnamespaces-merge-or.service new file mode 100644 index 00000000..a5245520 --- /dev/null +++ b/test/test-execute/exec-restrictnamespaces-merge-or.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test merging RestrictNamespaces= with OR + +[Service] +RestrictNamespaces=mnt pid +RestrictNamespaces=mnt uts +ExecStart=unshare -m -u -p -f +ExecStart=sh -c '! unshare -u -i -n' +Type=oneshot diff --git a/test/test-execute/exec-restrictnamespaces-mnt-blacklist.service b/test/test-execute/exec-restrictnamespaces-mnt-blacklist.service new file mode 100644 index 00000000..7756a257 --- /dev/null +++ b/test/test-execute/exec-restrictnamespaces-mnt-blacklist.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test RestrictNamespaces=~mnt + +[Service] +RestrictNamespaces=~mnt +ExecStart=unshare -m +Type=oneshot diff --git a/test/test-execute/exec-restrictnamespaces-mnt.service b/test/test-execute/exec-restrictnamespaces-mnt.service new file mode 100644 index 00000000..2c5b9426 --- /dev/null +++ b/test/test-execute/exec-restrictnamespaces-mnt.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test RestrictNamespaces=mnt + +[Service] +RestrictNamespaces=mnt +ExecStart=unshare -m +Type=oneshot diff --git a/test/test-execute/exec-restrictnamespaces-no.service b/test/test-execute/exec-restrictnamespaces-no.service new file mode 100644 index 00000000..5ffe081e --- /dev/null +++ b/test/test-execute/exec-restrictnamespaces-no.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test RestrictNamespaces=no + +[Service] +RestrictNamespaces=no +ExecStart=unshare -m -u -i -n -p -f +Type=oneshot diff --git a/test/test-execute/exec-restrictnamespaces-yes.service b/test/test-execute/exec-restrictnamespaces-yes.service new file mode 100644 index 00000000..8e077ed3 --- /dev/null +++ b/test/test-execute/exec-restrictnamespaces-yes.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test RestrictNamespaces=yes + +[Service] +RestrictNamespaces=yes +ExecStart=unshare -m +Type=oneshot diff --git a/test/test-execute/exec-runtimedirectory-mode.service b/test/test-execute/exec-runtimedirectory-mode.service new file mode 100644 index 00000000..85ae5161 --- /dev/null +++ b/test/test-execute/exec-runtimedirectory-mode.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for RuntimeDirectoryMode + +[Service] +ExecStart=/bin/sh -x -c 'mode=$$(stat -c %%a %t/test-exec_runtimedirectory-mode); test "$$mode" = "750"' +ExecStart=/bin/sh -x -c 'test "$$RUNTIME_DIRECTORY" = "%t/test-exec_runtimedirectory-mode"' +Type=oneshot +RuntimeDirectory=test-exec_runtimedirectory-mode +RuntimeDirectoryMode=0750 diff --git a/test/test-execute/exec-runtimedirectory-owner-nfsnobody.service b/test/test-execute/exec-runtimedirectory-owner-nfsnobody.service new file mode 100644 index 00000000..1e3b6b41 --- /dev/null +++ b/test/test-execute/exec-runtimedirectory-owner-nfsnobody.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set) + +[Service] +ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G %t/test-exec_runtimedirectory-owner); test "$$group" = "nfsnobody"' +Type=oneshot +Group=nfsnobody +User=root +RuntimeDirectory=test-exec_runtimedirectory-owner diff --git a/test/test-execute/exec-runtimedirectory-owner-nobody.service b/test/test-execute/exec-runtimedirectory-owner-nobody.service new file mode 100644 index 00000000..54782f9b --- /dev/null +++ b/test/test-execute/exec-runtimedirectory-owner-nobody.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set) + +[Service] +ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G %t/test-exec_runtimedirectory-owner); test "$$group" = "nobody"' +Type=oneshot +Group=nobody +User=root +RuntimeDirectory=test-exec_runtimedirectory-owner diff --git a/test/test-execute/exec-runtimedirectory-owner-nogroup.service b/test/test-execute/exec-runtimedirectory-owner-nogroup.service new file mode 100644 index 00000000..663afe11 --- /dev/null +++ b/test/test-execute/exec-runtimedirectory-owner-nogroup.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set) + +[Service] +ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G %t/test-exec_runtimedirectory-owner); test "$$group" = "nogroup"' +Type=oneshot +Group=nogroup +User=root +RuntimeDirectory=test-exec_runtimedirectory-owner diff --git a/test/test-execute/exec-runtimedirectory-owner.service b/test/test-execute/exec-runtimedirectory-owner.service new file mode 100644 index 00000000..07dd7ca3 --- /dev/null +++ b/test/test-execute/exec-runtimedirectory-owner.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for RuntimeDirectory owner (must not be the default group of the user if Group is set) + +[Service] +ExecStart=/bin/sh -x -c 'group=$$(stat -c %%G %t/test-exec_runtimedirectory-owner-daemon); test "$$group" = "daemon"' +Type=oneshot +Group=daemon +User=root +RuntimeDirectory=test-exec_runtimedirectory-owner-daemon diff --git a/test/test-execute/exec-runtimedirectory.service b/test/test-execute/exec-runtimedirectory.service new file mode 100644 index 00000000..a33044d2 --- /dev/null +++ b/test/test-execute/exec-runtimedirectory.service @@ -0,0 +1,10 @@ +[Unit] +Description=Test for RuntimeDirectory + +[Service] +ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectory' +ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectory2/hogehoge' +ExecStart=/bin/sh -x -c 'test "$$RUNTIME_DIRECTORY" = "%t/test-exec_runtimedirectory:%t/test-exec_runtimedirectory2/hogehoge"' +Type=oneshot +RuntimeDirectory=test-exec_runtimedirectory +RuntimeDirectory=./test-exec_runtimedirectory2///./hogehoge/. diff --git a/test/test-execute/exec-specifier-interpolation.service b/test/test-execute/exec-specifier-interpolation.service new file mode 100644 index 00000000..f128e3c4 --- /dev/null +++ b/test/test-execute/exec-specifier-interpolation.service @@ -0,0 +1,6 @@ +[Unit] +Description=https://github.com/systemd/systemd/issues/2637 + +[Service] +Type=oneshot +ExecStart=/bin/sh -x -c "! test -x perl || perl -e 'exit(!(qq{%%U} eq qq{\\x25U}))'" diff --git a/test/test-execute/exec-specifier.service b/test/test-execute/exec-specifier.service new file mode 100644 index 00000000..7c3f81f2 --- /dev/null +++ b/test/test-execute/exec-specifier.service @@ -0,0 +1,31 @@ +[Unit] +Description=Test for specifiers + +[Service] +Type=oneshot +ExecStart=test %n = exec-specifier.service +ExecStart=test %N = exec-specifier +ExecStart=test %p = exec-specifier +ExecStart=test %P = exec/specifier +ExecStart=test %i = "" +ExecStart=test %I = "" +ExecStart=test %j = specifier +ExecStart=test %J = specifier +ExecStart=test %f = /exec/specifier +ExecStart=test %t = /run +ExecStart=test %S = /var/lib +ExecStart=test %C = /var/cache +ExecStart=test %L = /var/log +ExecStart=test %E = /etc +ExecStart=test %T = /tmp +ExecStart=test %V = /var/tmp +ExecStart=sh -c 'test %u = $$(id -un)' +ExecStart=sh -c 'test %U = $$(id -u)' +ExecStart=sh -c 'test %g = $$(id -gn)' +ExecStart=sh -c 'test %G = $$(id -g)' +ExecStart=test %h = /root +ExecStart=sh -c 'test %s = /bin/sh' +ExecStart=sh -c 'test %m = $$(cat /etc/machine-id)' +ExecStart=sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')' +ExecStart=sh -c 'test %H = $$(hostname)' +ExecStart=sh -c 'test %v = $$(uname -r)' diff --git a/test/test-execute/exec-specifier@.service b/test/test-execute/exec-specifier@.service new file mode 100644 index 00000000..a3889268 --- /dev/null +++ b/test/test-execute/exec-specifier@.service @@ -0,0 +1,29 @@ +[Unit] +Description=Test for specifiers (template unit) + +[Service] +Type=oneshot +ExecStart=test %n = exec-specifier@foo-bar.service +ExecStart=test %N = exec-specifier@foo-bar +ExecStart=test %p = exec-specifier +ExecStart=test %P = exec/specifier +ExecStart=test %i = foo-bar +ExecStart=test %I = foo/bar +ExecStart=test %j = specifier +ExecStart=test %J = specifier +ExecStart=test %f = /foo/bar +ExecStart=test %t = /run +ExecStart=test %S = /var/lib +ExecStart=test %C = /var/cache +ExecStart=test %L = /var/log +ExecStart=test %E = /etc +ExecStart=sh -c 'test %u = $$(id -un)' +ExecStart=sh -c 'test %U = $$(id -u)' +ExecStart=sh -c 'test %g = $$(id -gn)' +ExecStart=sh -c 'test %G = $$(id -g)' +ExecStart=test %h = /root +ExecStart=sh -c 'test %s = /bin/sh' +ExecStart=sh -c 'test %m = $$(cat /etc/machine-id)' +ExecStart=sh -c 'test %b = $$(cat /proc/sys/kernel/random/boot_id | sed -e 's/-//g')' +ExecStart=sh -c 'test %H = $$(hostname)' +ExecStart=sh -c 'test %v = $$(uname -r)' diff --git a/test/test-execute/exec-standardinput-data.service b/test/test-execute/exec-standardinput-data.service new file mode 100644 index 00000000..1ca536ff --- /dev/null +++ b/test/test-execute/exec-standardinput-data.service @@ -0,0 +1,19 @@ +[Unit] +Description=Test for StandardInputText= and StandardInputData= + +[Service] +ExecStart=/bin/sh -x -c 'd=$$(mktemp -d -p /tmp); echo -e "this is a test\nand this is more\nsomething encoded!\nsomething in multiple lines\nand some more\nand a more bas64 data\nsomething with strange\nembedded\tcharacters\nand something with a exec-stdin-data.service specifier" > $d/text ; cmp $d/text ; rm -rf $d' +Type=oneshot +StandardInput=data +StandardInputText=this is a test +StandardInputText=and this is more +StandardInputData=c29tZXRoaW5nIGVuY29kZWQhCg== +StandardInputText=something \ + in multiple lines +StandardInputText=\ +and some more +StandardInputData=YW5kIGEgbW9y \ + ZSBiYXM2NCBk\ +YXRhCg== +StandardInputText=something with strange\nembedded\tcharacters +StandardInputText=and something with a %n specifier diff --git a/test/test-execute/exec-standardinput-file-cat.service b/test/test-execute/exec-standardinput-file-cat.service new file mode 100644 index 00000000..a0c786c3 --- /dev/null +++ b/test/test-execute/exec-standardinput-file-cat.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for StandardInput=file: + +[Service] +ExecStart=cat +Type=oneshot +StandardInput=file:/etc/os-release +# We leave StandardOutput= unset here, to verify https://github.com/systemd/systemd/issues/14560 works +# The "cat" tool is going to write to stdout, which fails if we dup() stdin to stdout diff --git a/test/test-execute/exec-standardinput-file.service b/test/test-execute/exec-standardinput-file.service new file mode 100644 index 00000000..8fd11caf --- /dev/null +++ b/test/test-execute/exec-standardinput-file.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for StandardInput=file: + +[Service] +ExecStart=/usr/bin/cmp /usr/bin/cmp +Type=oneshot +StandardInput=file:/usr/bin/cmp diff --git a/test/test-execute/exec-standardoutput-append.service b/test/test-execute/exec-standardoutput-append.service new file mode 100644 index 00000000..8983bb05 --- /dev/null +++ b/test/test-execute/exec-standardoutput-append.service @@ -0,0 +1,13 @@ +[Unit] +Description=Test for StandardOutput=append: + +[Service] +ExecStartPre=sh -c 'printf "hello\n" > /tmp/test-exec-standardoutput-output' +ExecStartPre=sh -c 'printf "hello\nhello\n" > /tmp/test-exec-standardoutput-expected' +StandardInput=data +StandardInputText=hello +StandardOutput=append:/tmp/test-exec-standardoutput-output +StandardError=null +ExecStart=cat +ExecStart=cmp /tmp/test-exec-standardoutput-output /tmp/test-exec-standardoutput-expected +Type=oneshot diff --git a/test/test-execute/exec-standardoutput-file.service b/test/test-execute/exec-standardoutput-file.service new file mode 100644 index 00000000..71e2604b --- /dev/null +++ b/test/test-execute/exec-standardoutput-file.service @@ -0,0 +1,13 @@ +[Unit] +Description=Test for StandardOutput=file: + +[Service] +ExecStartPre=sh -c 'printf "nooo\nhello\n" > /tmp/test-exec-standardoutput-output' +ExecStartPre=sh -c 'printf "hello\nello\n" > /tmp/test-exec-standardoutput-expected' +StandardInput=data +StandardInputText=hello +StandardOutput=file:/tmp/test-exec-standardoutput-output +StandardError=null +ExecStart=cat +ExecStart=cmp /tmp/test-exec-standardoutput-expected /tmp/test-exec-standardoutput-output +Type=oneshot diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service b/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service new file mode 100644 index 00000000..2a7ce87b --- /dev/null +++ b/test/test-execute/exec-supplementarygroups-multiple-groups-default-group-user.service @@ -0,0 +1,11 @@ +[Unit] +Description=Test for Supplementary Group with multiple groups without Group and User + +[Service] +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "%G" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "%G" && test "$$(id -u)" = "%U"' +Type=oneshot +SupplementaryGroups=1 2 3 diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service b/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service new file mode 100644 index 00000000..aae20fbf --- /dev/null +++ b/test/test-execute/exec-supplementarygroups-multiple-groups-withgid.service @@ -0,0 +1,11 @@ +[Unit] +Description=Test for Supplementary Group with multiple groups and Group=1 + +[Service] +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "%U"' +Type=oneshot +Group=1 +SupplementaryGroups=1 2 3 diff --git a/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service b/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service new file mode 100644 index 00000000..2714235b --- /dev/null +++ b/test/test-execute/exec-supplementarygroups-multiple-groups-withuid.service @@ -0,0 +1,10 @@ +[Unit] +Description=Test for Supplementary Group with multiple groups and Uid=1 + +[Service] +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "2" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "3" && HAVE=1; done; test "$$HAVE" -eq 1' +Type=oneshot +User=1 +SupplementaryGroups=1 2 3 diff --git a/test/test-execute/exec-supplementarygroups-single-group-user.service b/test/test-execute/exec-supplementarygroups-single-group-user.service new file mode 100644 index 00000000..405c5f9b --- /dev/null +++ b/test/test-execute/exec-supplementarygroups-single-group-user.service @@ -0,0 +1,10 @@ +[Unit] +Description=Test for Supplementary Group with only one group and uid 1 + +[Service] +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "1"' +Type=oneshot +User=1 +Group=1 +SupplementaryGroups=1 diff --git a/test/test-execute/exec-supplementarygroups-single-group.service b/test/test-execute/exec-supplementarygroups-single-group.service new file mode 100644 index 00000000..f9b72169 --- /dev/null +++ b/test/test-execute/exec-supplementarygroups-single-group.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for Supplementary Group with only one group + +[Service] +ExecStart=/bin/sh -x -c 'HAVE=; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'test "$$(id -g)" = "1" && test "$$(id -u)" = "0"' +Type=oneshot +Group=1 +SupplementaryGroups=1 diff --git a/test/test-execute/exec-supplementarygroups.service b/test/test-execute/exec-supplementarygroups.service new file mode 100644 index 00000000..6f6e2ba8 --- /dev/null +++ b/test/test-execute/exec-supplementarygroups.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for Supplementary Group + +[Service] +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "%G" && HAVE=1; done; test "$$HAVE" -eq 1' +ExecStart=/bin/sh -x -c 'HAVE=0; for g in $$(id -G); do test "$$g" = "1" && HAVE=1; done; test "$$HAVE" -eq 1' +Type=oneshot +SupplementaryGroups=1 diff --git a/test/test-execute/exec-systemcallerrornumber-name.service b/test/test-execute/exec-systemcallerrornumber-name.service new file mode 100644 index 00000000..e167d271 --- /dev/null +++ b/test/test-execute/exec-systemcallerrornumber-name.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for SystemCallErrorNumber + +[Service] +ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)' +Type=oneshot +SystemCallFilter=~uname +SystemCallErrorNumber=EACCES diff --git a/test/test-execute/exec-systemcallerrornumber-number.service b/test/test-execute/exec-systemcallerrornumber-number.service new file mode 100644 index 00000000..20321568 --- /dev/null +++ b/test/test-execute/exec-systemcallerrornumber-number.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for SystemCallErrorNumber + +[Service] +ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)' +Type=oneshot +SystemCallFilter=~uname +SystemCallErrorNumber=255 diff --git a/test/test-execute/exec-systemcallfilter-failing.service b/test/test-execute/exec-systemcallfilter-failing.service new file mode 100644 index 00000000..996f8592 --- /dev/null +++ b/test/test-execute/exec-systemcallfilter-failing.service @@ -0,0 +1,10 @@ +[Unit] +Description=Test for SystemCallFilter + +[Service] +ExecStart=/bin/sh -c 'echo "This should not be seen"' +Type=oneshot +LimitCORE=0 +SystemCallFilter=ioperm +SystemCallFilter=~ioperm +SystemCallFilter=ioperm diff --git a/test/test-execute/exec-systemcallfilter-failing2.service b/test/test-execute/exec-systemcallfilter-failing2.service new file mode 100644 index 00000000..c74f4224 --- /dev/null +++ b/test/test-execute/exec-systemcallfilter-failing2.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for SystemCallFilter + +[Service] +ExecStart=/bin/sh -c 'echo "This should not be seen"' +Type=oneshot +LimitCORE=0 +SystemCallFilter=~write open execve exit_group close mmap munmap fstat DONOTEXIST diff --git a/test/test-execute/exec-systemcallfilter-not-failing.service b/test/test-execute/exec-systemcallfilter-not-failing.service new file mode 100644 index 00000000..f3a752b3 --- /dev/null +++ b/test/test-execute/exec-systemcallfilter-not-failing.service @@ -0,0 +1,10 @@ +[Unit] +Description=Test for SystemCallFilter + +[Service] +ExecStart=/bin/sh -c 'echo "Foo bar"' +Type=oneshot +SystemCallFilter=~read write open execve ioperm +SystemCallFilter=ioctl +SystemCallFilter=read write open execve +SystemCallFilter=~ioperm diff --git a/test/test-execute/exec-systemcallfilter-not-failing2.service b/test/test-execute/exec-systemcallfilter-not-failing2.service new file mode 100644 index 00000000..1df076ab --- /dev/null +++ b/test/test-execute/exec-systemcallfilter-not-failing2.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for SystemCallFilter + +[Service] +ExecStart=/bin/sh -c 'echo "Foo bar"' +Type=oneshot +SystemCallFilter= diff --git a/test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service b/test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service new file mode 100644 index 00000000..b1195d0d --- /dev/null +++ b/test/test-execute/exec-systemcallfilter-system-user-nfsnobody.service @@ -0,0 +1,11 @@ +[Unit] +Description=Test for SystemCallFilter in system mode with User set + +[Service] +ExecStart=/bin/sh -c 'echo "Foo bar"' +Type=oneshot +User=nfsnobody +SystemCallFilter=~read write open execve ioperm +SystemCallFilter=ioctl +SystemCallFilter=read write open execve +SystemCallFilter=~ioperm diff --git a/test/test-execute/exec-systemcallfilter-system-user-nobody.service b/test/test-execute/exec-systemcallfilter-system-user-nobody.service new file mode 100644 index 00000000..da129a30 --- /dev/null +++ b/test/test-execute/exec-systemcallfilter-system-user-nobody.service @@ -0,0 +1,11 @@ +[Unit] +Description=Test for SystemCallFilter in system mode with User set + +[Service] +ExecStart=/bin/sh -c 'echo "Foo bar"' +Type=oneshot +User=nobody +SystemCallFilter=~read write open execve ioperm +SystemCallFilter=ioctl +SystemCallFilter=read write open execve +SystemCallFilter=~ioperm diff --git a/test/test-execute/exec-systemcallfilter-system-user.service b/test/test-execute/exec-systemcallfilter-system-user.service new file mode 100644 index 00000000..488a3bb7 --- /dev/null +++ b/test/test-execute/exec-systemcallfilter-system-user.service @@ -0,0 +1,11 @@ +[Unit] +Description=Test for SystemCallFilter in system mode with User set (daemon) + +[Service] +ExecStart=/bin/sh -c 'echo "Foo bar"' +Type=oneshot +User=daemon +SystemCallFilter=~read write open execve ioperm +SystemCallFilter=ioctl +SystemCallFilter=read write open execve +SystemCallFilter=~ioperm diff --git a/test/test-execute/exec-systemcallfilter-with-errno-multi.service b/test/test-execute/exec-systemcallfilter-with-errno-multi.service new file mode 100644 index 00000000..951e7ac3 --- /dev/null +++ b/test/test-execute/exec-systemcallfilter-with-errno-multi.service @@ -0,0 +1,9 @@ +[Unit] +Description=Test for SystemCallFilter updating errno +# test for issue #9939 which is fixed by a5404992cc7724ebf7572a0aa89d9fdb26ce0b62 (#9942) + +[Service] +ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)' +Type=oneshot +SystemCallFilter=~uname:ENOENT uname:EILSEQ +SystemCallErrorNumber=EACCES diff --git a/test/test-execute/exec-systemcallfilter-with-errno-name.service b/test/test-execute/exec-systemcallfilter-with-errno-name.service new file mode 100644 index 00000000..8380d5a1 --- /dev/null +++ b/test/test-execute/exec-systemcallfilter-with-errno-name.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for SystemCallFilter with errno name + +[Service] +ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)' +Type=oneshot +SystemCallFilter=~uname:EILSEQ +SystemCallErrorNumber=EACCES diff --git a/test/test-execute/exec-systemcallfilter-with-errno-number.service b/test/test-execute/exec-systemcallfilter-with-errno-number.service new file mode 100644 index 00000000..dbb9540a --- /dev/null +++ b/test/test-execute/exec-systemcallfilter-with-errno-number.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for SystemCallFilter with errno number + +[Service] +ExecStart=/usr/bin/python3 -c 'import os\ntry: os.uname()\nexcept Exception as e: exit(e.errno)' +Type=oneshot +SystemCallFilter=~uname:255 +SystemCallErrorNumber=EACCES diff --git a/test/test-execute/exec-temporaryfilesystem-options.service b/test/test-execute/exec-temporaryfilesystem-options.service new file mode 100644 index 00000000..371e5674 --- /dev/null +++ b/test/test-execute/exec-temporaryfilesystem-options.service @@ -0,0 +1,16 @@ +[Unit] +Description=Test for TemporaryFileSystem with mount options + +[Service] +Type=oneshot + +# The mount options default to "mode=0755,nodev,strictatime". +# Let's override some of them, and test "ro". +TemporaryFileSystem=/var:ro,mode=0700,nostrictatime + +# Check /proc/self/mountinfo +ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$11 !~ /(^|,)mode=700(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""' + +ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$6 !~ /(^|,)ro(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""' +ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$6 !~ /(^|,)nodev(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""' +ExecStart=/bin/sh -x -c 'test "$$(awk \'$$5 == "/var" && $$6 ~ /(^|,)strictatime(,|$$)/ { print $$6 }\' /proc/self/mountinfo)" = ""' diff --git a/test/test-execute/exec-temporaryfilesystem-ro.service b/test/test-execute/exec-temporaryfilesystem-ro.service new file mode 100644 index 00000000..c161aecc --- /dev/null +++ b/test/test-execute/exec-temporaryfilesystem-ro.service @@ -0,0 +1,36 @@ +[Unit] +Description=Test for TemporaryFileSystem with read-only mode + +[Service] +Type=oneshot + +# Check directories exist +ExecStart=/bin/sh -c 'test -d /var/test-exec-temporaryfilesystem/rw && test -d /var/test-exec-temporaryfilesystem/ro' + +# Check TemporaryFileSystem= are empty +ExecStart=/bin/sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done' + +# Check default mode +ExecStart=sh -x -c 'test "$$(stat -c %%a /var)" = "755"' + +# Cannot create a file in /var +ExecStart=/bin/sh -c '! touch /var/hoge' + +# Create a file in /var/test-exec-temporaryfilesystem/rw +ExecStart=/bin/sh -c 'touch /var/test-exec-temporaryfilesystem/rw/thisisasimpletest-temporaryfilesystem' + +# Then, the file can be access through /tmp +ExecStart=/bin/sh -c 'test -f /tmp/thisisasimpletest-temporaryfilesystem' + +# Also, through /var/test-exec-temporaryfilesystem/ro +ExecStart=/bin/sh -c 'test -f /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem' + +# The file cannot modify through /var/test-exec-temporaryfilesystem/ro +ExecStart=/bin/sh -c '! touch /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem' + +# Cleanup +ExecStart=/bin/sh -c 'rm /tmp/thisisasimpletest-temporaryfilesystem' + +TemporaryFileSystem=/var:ro +BindPaths=/tmp:/var/test-exec-temporaryfilesystem/rw +BindReadOnlyPaths=/tmp:/var/test-exec-temporaryfilesystem/ro diff --git a/test/test-execute/exec-temporaryfilesystem-rw.service b/test/test-execute/exec-temporaryfilesystem-rw.service new file mode 100644 index 00000000..bb830595 --- /dev/null +++ b/test/test-execute/exec-temporaryfilesystem-rw.service @@ -0,0 +1,36 @@ +[Unit] +Description=Test for TemporaryFileSystem + +[Service] +Type=oneshot + +# Check directories exist +ExecStart=test -d /var/test-exec-temporaryfilesystem/rw -a -d /var/test-exec-temporaryfilesystem/ro + +# Check TemporaryFileSystem= are empty +ExecStart=sh -c 'for i in $$(ls -A /var); do test $$i = test-exec-temporaryfilesystem || false; done' + +# Check default mode +ExecStart=sh -x -c 'test "$$(stat -c %%a /var)" = "755"' + +# Create a file in /var +ExecStart=touch /var/hoge + +# Create a file in /var/test-exec-temporaryfilesystem/rw +ExecStart=touch /var/test-exec-temporaryfilesystem/rw/thisisasimpletest-temporaryfilesystem + +# Then, the file can be access through /tmp +ExecStart=test -f /tmp/thisisasimpletest-temporaryfilesystem + +# Also, through /var/test-exec-temporaryfilesystem/ro +ExecStart=test -f /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem + +# The file cannot modify through /var/test-exec-temporaryfilesystem/ro +ExecStart=sh -c '! touch /var/test-exec-temporaryfilesystem/ro/thisisasimpletest-temporaryfilesystem' + +# Cleanup +ExecStart=rm /tmp/thisisasimpletest-temporaryfilesystem + +TemporaryFileSystem=/var +BindPaths=/tmp:/var/test-exec-temporaryfilesystem/rw +BindReadOnlyPaths=/tmp:/var/test-exec-temporaryfilesystem/ro diff --git a/test/test-execute/exec-temporaryfilesystem-usr.service b/test/test-execute/exec-temporaryfilesystem-usr.service new file mode 100644 index 00000000..05c1ec06 --- /dev/null +++ b/test/test-execute/exec-temporaryfilesystem-usr.service @@ -0,0 +1,15 @@ +[Unit] +Description=Test for TemporaryFileSystem on /usr + +[Service] +Type=oneshot + +# Check TemporaryFileSystem= are empty +ExecStart=/bin/sh -c 'for i in $$(ls -A /usr); do test $$i = lib -o $$i = lib64 -o $$i = bin -o $$i = sbin || false; done' + +# Cannot create files under /usr +ExecStart=/bin/sh -c '! touch /usr/hoge' +ExecStart=/bin/sh -c '! touch /usr/bin/hoge' + +TemporaryFileSystem=/usr:ro +BindReadOnlyPaths=-/usr/lib -/usr/lib64 /usr/bin /usr/sbin diff --git a/test/test-execute/exec-umask-0177.service b/test/test-execute/exec-umask-0177.service new file mode 100644 index 00000000..c18293e4 --- /dev/null +++ b/test/test-execute/exec-umask-0177.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for UMask + +[Service] +ExecStart=/bin/sh -x -c 'rm /tmp/test-exec-umask; touch /tmp/test-exec-umask; mode=$$(stat -c %%a /tmp/test-exec-umask); test "$$mode" = "600"' +Type=oneshot +UMask=0177 +PrivateTmp=yes diff --git a/test/test-execute/exec-umask-default.service b/test/test-execute/exec-umask-default.service new file mode 100644 index 00000000..bf0573dd --- /dev/null +++ b/test/test-execute/exec-umask-default.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for UMask default + +[Service] +ExecStart=/bin/sh -x -c 'rm /tmp/test-exec-umask; touch /tmp/test-exec-umask; mode=$$(stat -c %%a /tmp/test-exec-umask); test "$$mode" = "644"' +Type=oneshot +PrivateTmp=yes diff --git a/test/test-execute/exec-unsetenvironment.service b/test/test-execute/exec-unsetenvironment.service new file mode 100644 index 00000000..5b0123b8 --- /dev/null +++ b/test/test-execute/exec-unsetenvironment.service @@ -0,0 +1,8 @@ +[Unit] +Description=Test for UnsetEnvironment + +[Service] +ExecStart=/bin/sh -x -c 'test "$$FOO" = "bar" && test "$${QUUX-X}" = "X" && test "$$VAR3" = "value3" && test "$${VAR4-X}" = "X" && test "$$VAR5" = "value5" && test "$${X%b-X}" = "X"' +Type=oneshot +Environment=FOO=bar QUUX=waldo VAR3=value3 VAR4=value4 VAR5=value5 X%b=%U +UnsetEnvironment=QUUX=waldo VAR3=somethingelse VAR4 X%b=%U diff --git a/test/test-execute/exec-user-nfsnobody.service b/test/test-execute/exec-user-nfsnobody.service new file mode 100644 index 00000000..aafda3aa --- /dev/null +++ b/test/test-execute/exec-user-nfsnobody.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for User + +[Service] +ExecStart=/bin/sh -x -c 'test "$$USER" = "nfsnobody"' +Type=oneshot +User=nfsnobody diff --git a/test/test-execute/exec-user-nobody.service b/test/test-execute/exec-user-nobody.service new file mode 100644 index 00000000..0a00c1ab --- /dev/null +++ b/test/test-execute/exec-user-nobody.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for User + +[Service] +ExecStart=/bin/sh -x -c 'test "$$USER" = "nobody"' +Type=oneshot +User=nobody diff --git a/test/test-execute/exec-user.service b/test/test-execute/exec-user.service new file mode 100644 index 00000000..d315a828 --- /dev/null +++ b/test/test-execute/exec-user.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for User (daemon) + +[Service] +ExecStart=/bin/sh -x -c 'test "$$USER" = "daemon"' +Type=oneshot +User=daemon diff --git a/test/test-execute/exec-workingdirectory-trailing-dot.service b/test/test-execute/exec-workingdirectory-trailing-dot.service new file mode 100644 index 00000000..5c807b31 --- /dev/null +++ b/test/test-execute/exec-workingdirectory-trailing-dot.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for WorkingDirectory with trailing dot + +[Service] +ExecStart=/bin/sh -x -c 'test "$$PWD" = "/tmp/test-exec_workingdirectory"' +Type=oneshot +WorkingDirectory=/tmp///./test-exec_workingdirectory/. diff --git a/test/test-execute/exec-workingdirectory.service b/test/test-execute/exec-workingdirectory.service new file mode 100644 index 00000000..fe3c420d --- /dev/null +++ b/test/test-execute/exec-workingdirectory.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for WorkingDirectory + +[Service] +ExecStart=/bin/sh -x -c 'test "$$PWD" = "/tmp/test-exec_workingdirectory"' +Type=oneshot +WorkingDirectory=/tmp/test-exec_workingdirectory diff --git a/test/test-functions b/test/test-functions new file mode 100644 index 00000000..468a36d3 --- /dev/null +++ b/test/test-functions @@ -0,0 +1,1825 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh +PATH=/sbin:/bin:/usr/sbin:/usr/bin +export PATH + +LOOKS_LIKE_DEBIAN=$(source /etc/os-release && [[ "$ID" = "debian" || " $ID_LIKE " = *" debian "* ]] && echo yes || :) +LOOKS_LIKE_ARCH=$(source /etc/os-release && [[ "$ID" = "arch" || " $ID_LIKE " = *" arch "* ]] && echo yes || :) +LOOKS_LIKE_SUSE=$(source /etc/os-release && [[ " $ID_LIKE " = *" suse "* ]] && echo yes || :) +KERNEL_VER=${KERNEL_VER-$(uname -r)} +KERNEL_MODS="/lib/modules/$KERNEL_VER/" +QEMU_TIMEOUT="${QEMU_TIMEOUT:-infinity}" +NSPAWN_TIMEOUT="${NSPAWN_TIMEOUT:-infinity}" +TIMED_OUT= # will be 1 after run_* if *_TIMEOUT is set and test timed out +[[ "$LOOKS_LIKE_SUSE" ]] && FSTYPE="${FSTYPE:-btrfs}" || FSTYPE="${FSTYPE:-ext4}" +UNIFIED_CGROUP_HIERARCHY="${UNIFIED_CGROUP_HIERARCHY:-default}" +EFI_MOUNT="$(bootctl -x 2>/dev/null || echo /boot)" +QEMU_MEM="${QEMU_MEM:-512M}" + +# Decide if we can (and want to) run QEMU with KVM acceleration. +# Check if nested KVM is explicitly enabled (TEST_NESTED_KVM). If not, +# check if it's not explicitly disabled (TEST_NO_KVM) and we're not already +# running under KVM. If these conditions are met, enable KVM (and possibly +# nested KVM), otherwise disable it. +if [[ -n "$TEST_NESTED_KVM" || ( -z "$TEST_NO_KVM" && $(systemd-detect-virt -v) != kvm ) ]]; then + QEMU_KVM=yes +else + QEMU_KVM=no +fi + +if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then + echo "WARNING! Cannot determine rootlibdir from pkg-config, assuming /usr/lib/systemd" >&2 + ROOTLIBDIR=/usr/lib/systemd +fi + +PATH_TO_INIT=$ROOTLIBDIR/systemd +[ "$SYSTEMD_JOURNALD" ] || SYSTEMD_JOURNALD=$(which -a $BUILD_DIR/systemd-journald $ROOTLIBDIR/systemd-journald 2>/dev/null | grep '^/' -m1) +[ "$SYSTEMD" ] || SYSTEMD=$(which -a $BUILD_DIR/systemd $ROOTLIBDIR/systemd 2>/dev/null | grep '^/' -m1) +[ "$SYSTEMD_NSPAWN" ] || SYSTEMD_NSPAWN=$(which -a $BUILD_DIR/systemd-nspawn systemd-nspawn 2>/dev/null | grep '^/' -m1) +[ "$JOURNALCTL" ] || JOURNALCTL=$(which -a $BUILD_DIR/journalctl journalctl 2>/dev/null | grep '^/' -m1) + +BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo head tail cat mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs" +DEBUGTOOLS="df free ls stty ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find vi mv" + +STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))" +STATEFILE="$STATEDIR/.testdir" +TESTLOG="$STATEDIR/test.log" + +is_built_with_asan() { + if ! type -P objdump >/dev/null; then + ddebug "Failed to find objdump. Assuming systemd hasn't been built with ASAN." + return 1 + fi + + # Borrowed from https://github.com/google/oss-fuzz/blob/cd9acd02f9d3f6e80011cc1e9549be526ce5f270/infra/base-images/base-runner/bad_build_check#L182 + local _asan_calls=$(objdump -dC $SYSTEMD_JOURNALD | egrep "callq\s+[0-9a-f]+\s+<__asan" -c) + if (( $_asan_calls < 1000 )); then + return 1 + else + return 0 + fi +} + +IS_BUILT_WITH_ASAN=$(is_built_with_asan && echo yes || echo no) + +if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then + STRIP_BINARIES=no + SKIP_INITRD="${SKIP_INITRD:-yes}" + PATH_TO_INIT=$ROOTLIBDIR/systemd-under-asan + QEMU_MEM="2048M" + QEMU_SMP=4 + + # We need to correctly distinguish between gcc's and clang's ASan DSOs. + if ldd $SYSTEMD | grep -q libasan.so; then + ASAN_COMPILER=gcc + elif ldd $SYSTEMD | grep -q libclang_rt.asan; then + ASAN_COMPILER=clang + + # As clang's ASan DSO is usually in a non-standard path, let's check if + # the environment is set accordingly. If not, warn the user and exit. + # We're not setting the LD_LIBRARY_PATH automagically here, because + # user should encounter (and fix) the same issue when running the unit + # tests (meson test) + if ldd "$SYSTEMD" | grep -q "libclang_rt.asan.*not found"; then + _asan_rt_name="$(ldd $SYSTEMD | awk '/libclang_rt.asan/ {print $1; exit}')" + _asan_rt_path="$(find /usr/lib* /usr/local/lib* -type f -name "$_asan_rt_name" 2>/dev/null | sed 1q)" + echo >&2 "clang's ASan DSO ($_asan_rt_name) is not present in the runtime library path" + echo >&2 "Consider setting LD_LIBRARY_PATH=${_asan_rt_path%/*}" + exit 1 + fi + else + echo >&2 "systemd is not linked against the ASan DSO" + echo >&2 "gcc does this by default, for clang compile with -shared-libasan" + exit 1 + fi +fi + +function find_qemu_bin() { + # SUSE and Red Hat call the binary qemu-kvm. Debian and Gentoo call it kvm. + if [[ $QEMU_KVM == "yes" ]]; then + [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a kvm qemu-kvm 2>/dev/null | grep '^/' -m1) + fi + + [ "$ARCH" ] || ARCH=$(uname -m) + case $ARCH in + x86_64) + # QEMU's own build system calls it qemu-system-x86_64 + [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-x86_64 2>/dev/null | grep '^/' -m1) + ;; + i*86) + # new i386 version of QEMU + [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-i386 2>/dev/null | grep '^/' -m1) + + # i386 version of QEMU + [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu 2>/dev/null | grep '^/' -m1) + ;; + ppc64*) + [ "$QEMU_BIN" ] || QEMU_BIN=$(which -a qemu-system-ppc64 2>/dev/null | grep '^/' -m1) + ;; + esac + + if [ ! -e "$QEMU_BIN" ]; then + echo "Could not find a suitable QEMU binary" >&2 + return 1 + fi +} + +# Return 0 if QEMU did run (then you must check the result state/logs for actual +# success), or 1 if QEMU is not available. +run_qemu() { + if [ -f /etc/machine-id ]; then + read MACHINE_ID < /etc/machine-id + [ -z "$INITRD" ] && [ -e "$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/initrd" ] \ + && INITRD="$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/initrd" + [ -z "$KERNEL_BIN" ] && [ -e "$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/linux" ] \ + && KERNEL_BIN="$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/linux" + fi + + CONSOLE=ttyS0 + + if [[ ! "$KERNEL_BIN" ]]; then + if [[ "$LOOKS_LIKE_ARCH" ]]; then + KERNEL_BIN=/boot/vmlinuz-linux + else + [ "$ARCH" ] || ARCH=$(uname -m) + case $ARCH in + ppc64*) + KERNEL_BIN=/boot/vmlinux-$KERNEL_VER + CONSOLE=hvc0 + ;; + *) + KERNEL_BIN=/boot/vmlinuz-$KERNEL_VER + ;; + esac + fi + fi + + default_fedora_initrd=/boot/initramfs-${KERNEL_VER}.img + default_debian_initrd=/boot/initrd.img-${KERNEL_VER} + default_arch_initrd=/boot/initramfs-linux-fallback.img + default_suse_initrd=/boot/initrd-${KERNEL_VER} + if [[ ! "$INITRD" ]]; then + if [[ -e "$default_fedora_initrd" ]]; then + INITRD="$default_fedora_initrd" + elif [[ "$LOOKS_LIKE_DEBIAN" && -e "$default_debian_initrd" ]]; then + INITRD="$default_debian_initrd" + elif [[ "$LOOKS_LIKE_ARCH" && -e "$default_arch_initrd" ]]; then + INITRD="$default_arch_initrd" + elif [[ "$LOOKS_LIKE_SUSE" && -e "$default_suse_initrd" ]]; then + INITRD="$default_suse_initrd" + fi + fi + + # If QEMU_SMP was not explicitly set, try to determine the value 'dynamically' + # i.e. use the number of online CPUs on the host machine. If the nproc utility + # is not installed or there's some other error when calling it, fall back + # to the original value (QEMU_SMP=1). + if ! [ "$QEMU_SMP" ]; then + if ! QEMU_SMP=$(nproc); then + dwarn "nproc utility is not installed, falling back to QEMU_SMP=1" + QEMU_SMP=1 + fi + fi + + find_qemu_bin || return 1 + + local _cgroup_args + if [[ "$UNIFIED_CGROUP_HIERARCHY" = "yes" ]]; then + _cgroup_args="systemd.unified_cgroup_hierarchy=yes" + elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "no" ]]; then + _cgroup_args="systemd.unified_cgroup_hierarchy=no systemd.legacy_systemd_cgroup_controller=yes" + elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "hybrid" ]]; then + _cgroup_args="systemd.unified_cgroup_hierarchy=no systemd.legacy_systemd_cgroup_controller=no" + elif [[ "$UNIFIED_CGROUP_HIERARCHY" != "default" ]]; then + dfatal "Unknown UNIFIED_CGROUP_HIERARCHY. Got $UNIFIED_CGROUP_HIERARCHY, expected [yes|no|hybrid|default]" + exit 1 + fi + + if [[ "$LOOKS_LIKE_SUSE" ]]; then + PARAMS+="rd.hostonly=0" + elif [[ "$LOOKS_LIKE_ARCH" ]]; then + PARAMS+="rw" + else + PARAMS+="ro" + fi + + KERNEL_APPEND="$PARAMS \ +root=/dev/sda1 \ +raid=noautodetect \ +rd.luks=0 \ +loglevel=2 \ +init=$PATH_TO_INIT \ +console=$CONSOLE \ +selinux=0 \ +printk.devkmsg=on \ +$_cgroup_args \ +$KERNEL_APPEND \ +" + + QEMU_OPTIONS="-smp $QEMU_SMP \ +-net none \ +-m $QEMU_MEM \ +-nographic \ +-kernel $KERNEL_BIN \ +-drive format=raw,cache=unsafe,file=${TESTDIR}/rootdisk.img \ +$QEMU_OPTIONS \ +" + + if [[ "$INITRD" && "$SKIP_INITRD" != "yes" ]]; then + QEMU_OPTIONS="$QEMU_OPTIONS -initrd $INITRD" + fi + + # Let's use KVM if possible + if [[ -c /dev/kvm && $QEMU_KVM == "yes" ]]; then + QEMU_OPTIONS="$QEMU_OPTIONS -machine accel=kvm -enable-kvm -cpu host" + fi + + if [[ "$QEMU_TIMEOUT" != "infinity" ]]; then + QEMU_BIN="timeout --foreground $QEMU_TIMEOUT $QEMU_BIN" + fi + (set -x; $QEMU_BIN $QEMU_OPTIONS -append "$KERNEL_APPEND") + rc=$? + if [ "$rc" = 124 ] && [ "$QEMU_TIMEOUT" != "infinity" ]; then + derror "test timed out after $QEMU_TIMEOUT s" + TIMED_OUT=1 + else + [ "$rc" != 0 ] && derror "QEMU failed with exit code $rc" + fi + return 0 +} + +# Return 0 if nspawn did run (then you must check the result state/logs for actual +# success), or 1 if nspawn is not available. +run_nspawn() { + [[ -d /run/systemd/system ]] || return 1 + + local _nspawn_cmd="$SYSTEMD_NSPAWN $NSPAWN_ARGUMENTS --register=no --kill-signal=SIGKILL --directory=$TESTDIR/$1 $PATH_TO_INIT $KERNEL_APPEND" + if [[ "$NSPAWN_TIMEOUT" != "infinity" ]]; then + _nspawn_cmd="timeout --foreground $NSPAWN_TIMEOUT $_nspawn_cmd" + fi + + if [[ "$UNIFIED_CGROUP_HIERARCHY" = "hybrid" ]]; then + dwarn "nspawn doesn't support SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=hybrid, skipping" + exit + elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "yes" || "$UNIFIED_CGROUP_HIERARCHY" = "no" ]]; then + _nspawn_cmd="env SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=$UNIFIED_CGROUP_HIERARCHY $_nspawn_cmd" + elif [[ "$UNIFIED_CGROUP_HIERARCHY" = "default" ]]; then + _nspawn_cmd="env --unset=UNIFIED_CGROUP_HIERARCHY --unset=SYSTEMD_NSPAWN_UNIFIED_HIERARCHY $_nspawn_cmd" + else + dfatal "Unknown UNIFIED_CGROUP_HIERARCHY. Got $UNIFIED_CGROUP_HIERARCHY, expected [yes|no|hybrid|default]" + exit 1 + fi + + (set -x; $_nspawn_cmd) + rc=$? + if [ "$rc" = 124 ] && [ "$NSPAWN_TIMEOUT" != "infinity" ]; then + derror "test timed out after $NSPAWN_TIMEOUT s" + TIMED_OUT=1 + else + [ "$rc" != 0 ] && derror "nspawn failed with exit code $rc" + fi + return 0 +} + +setup_basic_environment() { + # create the basic filesystem layout + setup_basic_dirs + + install_systemd + install_missing_libraries + install_config_files + create_rc_local + install_basic_tools + install_libnss + install_pam + install_dbus + install_fonts + install_keymaps + install_terminfo + install_execs + install_fsck + install_plymouth + install_debug_tools + install_ld_so_conf + setup_selinux + strip_binaries + install_depmod_files + generate_module_dependencies + if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then + create_asan_wrapper + fi +} + +setup_selinux() { + # don't forget KERNEL_APPEND='... selinux=1 ...' + if [[ "$SETUP_SELINUX" != "yes" ]]; then + ddebug "Don't setup SELinux" + return 0 + fi + ddebug "Setup SELinux" + local _conf_dir=/etc/selinux + local _fixfiles_tools="bash uname cat sort uniq awk grep egrep head expr find rm secon setfiles" + + rm -rf $initdir/$_conf_dir + if ! cp -ar $_conf_dir $initdir/$_conf_dir; then + dfatal "Failed to copy $_conf_dir" + exit 1 + fi + + cat <$initdir/etc/systemd/system/autorelabel.service +[Unit] +Description=Relabel all filesystems +DefaultDependencies=no +Requires=local-fs.target +Conflicts=shutdown.target +After=local-fs.target +Before=sysinit.target shutdown.target +ConditionSecurity=selinux +ConditionPathExists=|/.autorelabel + +[Service] +ExecStart=/bin/sh -x -c 'echo 0 >/sys/fs/selinux/enforce && fixfiles -f -F relabel && rm /.autorelabel && systemctl --force reboot' +Type=oneshot +TimeoutSec=0 +RemainAfterExit=yes +EOF + + touch $initdir/.autorelabel + mkdir -p $initdir/etc/systemd/system/basic.target.wants + ln -fs autorelabel.service $initdir/etc/systemd/system/basic.target.wants/autorelabel.service + + dracut_install $_fixfiles_tools + dracut_install fixfiles + dracut_install sestatus +} + +install_valgrind() { + if ! type -p valgrind; then + dfatal "Failed to install valgrind" + exit 1 + fi + + local _valgrind_bins=$(strace -e execve valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if /^execve\("([^"]+)"/') + dracut_install $_valgrind_bins + + local _valgrind_libs=$(LD_DEBUG=files valgrind /bin/true 2>&1 >/dev/null | perl -lne 'print $1 if m{calling init: (/.*vgpreload_.*)}') + dracut_install $_valgrind_libs + + local _valgrind_dbg_and_supp=$( + strace -e open valgrind /bin/true 2>&1 >/dev/null | + perl -lne 'if (my ($fname) = /^open\("([^"]+).*= (?!-)\d+/) { print $fname if $fname =~ /debug|\.supp$/ }' + ) + dracut_install $_valgrind_dbg_and_supp +} + +create_valgrind_wrapper() { + local _valgrind_wrapper=$initdir/$ROOTLIBDIR/systemd-under-valgrind + ddebug "Create $_valgrind_wrapper" + cat >$_valgrind_wrapper <$_asan_wrapper < not found" issues in the future +export PATH="/sbin:/bin:/usr/sbin:/usr/bin" + +mount -t proc proc /proc +mount -t sysfs sysfs /sys +mount -o remount,rw / + +PATH_TO_ASAN=\$(find / -name '$_asan_rt_pattern' | sed 1q) +if [[ "\$PATH_TO_ASAN" ]]; then + # A lot of services (most notably dbus) won't start without preloading libasan + # See https://github.com/systemd/systemd/issues/5004 + DEFAULT_ENVIRONMENT="\$DEFAULT_ENVIRONMENT LD_PRELOAD=\$PATH_TO_ASAN" + # Let's add the ASan DSO's path to the dynamic linker's cache. This is pretty + # unnecessary for gcc & libasan, however, for clang this is crucial, as its + # runtime ASan DSO is in a non-standard (library) path. + echo \${PATH_TO_ASAN%/*} > /etc/ld.so.conf.d/asan-path-override.conf + ldconfig +fi +echo DefaultEnvironment=\$DEFAULT_ENVIRONMENT >>/etc/systemd/system.conf +echo DefaultTimeoutStartSec=180s >>/etc/systemd/system.conf +echo DefaultStandardOutput=journal+console >>/etc/systemd/system.conf + +# ASAN and syscall filters aren't compatible with each other. +find / -name '*.service' -type f | xargs sed -i 's/^\\(MemoryDeny\\|SystemCall\\)/#\\1/' + +# The redirection of ASAN reports to a file prevents them from ending up in /dev/null. +# But, apparently, sometimes it doesn't work: https://github.com/google/sanitizers/issues/886. +JOURNALD_CONF_DIR=/etc/systemd/system/systemd-journald.service.d +mkdir -p "\$JOURNALD_CONF_DIR" +printf "[Service]\nEnvironment=ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd-journald.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS:log_path=/systemd-journald.ubsan.log\n" >"\$JOURNALD_CONF_DIR/env.conf" + +# Sometimes UBSan sends its reports to stderr regardless of what is specified in log_path +# Let's try to catch them by redirecting stderr (and stdout just in case) to a file +# See https://github.com/systemd/systemd/pull/12524#issuecomment-491108821 +printf "[Service]\nStandardOutput=file:/systemd-journald.out\n" >"\$JOURNALD_CONF_DIR/out.conf" + +# 90s isn't enough for some services to finish when literally everything is run +# under ASan+UBSan in containers, which, in turn, are run in VMs. +# Let's limit which environments such services should be executed in. +mkdir -p /etc/systemd/system/systemd-hwdb-update.service.d +printf "[Unit]\nConditionVirtualization=container\n\n[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-hwdb-update.service.d/env-override.conf + +# Let's override another hard-coded timeout that kicks in too early +mkdir -p /etc/systemd/system/systemd-journal-flush.service.d +printf "[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-journal-flush.service.d/timeout.conf + +# The 'mount' utility doesn't behave well under libasan, causing unexpected +# fails during boot and subsequent test results check: +# bash-5.0# mount -o remount,rw -v / +# mount: /dev/sda1 mounted on /. +# bash-5.0# echo \$? +# 1 +# Let's workaround this by clearing the previously set LD_PRELOAD env variable, +# so the libasan library is not loaded for this particular service +REMOUNTFS_CONF_DIR=/etc/systemd/system/systemd-remount-fs.service.d +mkdir -p "\$REMOUNTFS_CONF_DIR" +printf "[Service]\nUnsetEnvironment=LD_PRELOAD\n" >"\$REMOUNTFS_CONF_DIR/env.conf" + +export ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS +exec $ROOTLIBDIR/systemd "\$@" +EOF + + chmod 0755 $_asan_wrapper +} + +create_strace_wrapper() { + local _strace_wrapper=$initdir/$ROOTLIBDIR/systemd-under-strace + ddebug "Create $_strace_wrapper" + cat >$_strace_wrapper <> $initdir/etc/systemd/system.conf + # store coredumps in journal + echo Storage=journal >> $initdir/etc/systemd/coredump.conf +} + +get_ldpath() { + local _bin="$1" + local rpath=$(objdump -p "$_bin" 2>/dev/null | awk "/R(UN)?PATH/ { print \"$initdir\" \$2 }" | paste -sd :) + + if [ -z "$rpath" ] ; then + echo $BUILD_DIR + else + echo $rpath + fi +} + +install_missing_libraries() { + # install possible missing libraries + for i in $initdir{,/usr}/{sbin,bin}/* $initdir{,/usr}/lib/systemd/{,tests/{,manual/,unsafe/}}*; do + LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$(get_ldpath $i)" inst_libs $i + done +} + +create_empty_image() { + local _size=500 + if [[ "$STRIP_BINARIES" = "no" ]]; then + _size=$((4*_size)) + fi + rm -f "$TESTDIR/rootdisk.img" + # Create the blank file to use as a root filesystem + truncate -s "${_size}M" "$TESTDIR/rootdisk.img" + LOOPDEV=$(losetup --show -P -f $TESTDIR/rootdisk.img) + [ -b "$LOOPDEV" ] || return 1 + echo "LOOPDEV=$LOOPDEV" >> $STATEFILE + sfdisk "$LOOPDEV" < undef, + ); + } + print $2 if /\s(\S*)\[(\d+)\]:\s*SUMMARY:\s+\w+Sanitizer/ && !exists $services_to_ignore{$1}' + ) + if [[ ! -z "$pids" ]]; then + ret=$(($ret+1)) + for pid in $pids; do + "$JOURNALCTL" -D "$root/var/log/journal" _PID=$pid --no-pager + done + fi + fi + + return $ret +} + +check_result_nspawn() { + local ret=1 + local journald_report="" + local pids="" + [[ -e $TESTDIR/$1/testok ]] && ret=0 + [[ -f $TESTDIR/$1/failed ]] && cp -a $TESTDIR/$1/failed $TESTDIR + cp -a $TESTDIR/$1/var/log/journal $TESTDIR + [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed + ls -l $TESTDIR/journal/*/*.journal + test -s $TESTDIR/failed && ret=$(($ret+1)) + [ -n "$TIMED_OUT" ] && ret=$(($ret+1)) + check_asan_reports "$TESTDIR/$1" || ret=$(($ret+1)) + return $ret +} + +# can be overridden in specific test +check_result_qemu() { + local ret=1 + mkdir -p $initdir + mount ${LOOPDEV}p1 $initdir + [[ -e $initdir/testok ]] && ret=0 + [[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR + cp -a $initdir/var/log/journal $TESTDIR + check_asan_reports "$initdir" || ret=$(($ret+1)) + umount $initdir + [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed + ls -l $TESTDIR/journal/*/*.journal + test -s $TESTDIR/failed && ret=$(($ret+1)) + [ -n "$TIMED_OUT" ] && ret=$(($ret+1)) + return $ret +} + +strip_binaries() { + if [[ "$STRIP_BINARIES" = "no" ]]; then + ddebug "Don't strip binaries" + return 0 + fi + ddebug "Strip binaries" + find "$initdir" -executable -not -path '*/lib/modules/*.ko' -type f | \ + xargs strip --strip-unneeded |& \ + grep -vi 'file format not recognized' | \ + ddebug +} + +create_rc_local() { + mkdir -p $initdir/etc/rc.d + cat >$initdir/etc/rc.d/rc.local < $initdir/etc/environment + > $initdir/etc/machine-id + # set the hostname + echo systemd-testsuite > $initdir/etc/hostname + # fstab + if [[ "$LOOKS_LIKE_SUSE" ]]; then + ROOTMOUNT="/dev/sda1 / ${FSTYPE} rw 0 1" + else + ROOTMOUNT="LABEL=systemd / ${FSTYPE} rw 0 1" + fi + + cat >$initdir/etc/fstab < "$_getty_override/default-TERM.conf" + + cat > "$initdir/etc/motd" << EOF +To adjust the terminal size use: + export COLUMNS=xx + export LINES=yy +or + stty cols xx rows yy +EOF + fi +} + +install_libnss() { + # install libnss_files for login + NSS_LIBS=$(LD_DEBUG=files getent passwd 2>&1 >/dev/null |sed -n '/calling init: .*libnss_/ {s!^.* /!/!; p}') + dracut_install $NSS_LIBS +} + +install_dbus() { + inst $ROOTLIBDIR/system/dbus.socket + + # Newer Fedora versions use dbus-broker by default. Let's install it is available. + if [ -f $ROOTLIBDIR/system/dbus-broker.service ]; then + inst $ROOTLIBDIR/system/dbus-broker.service + inst_symlink /etc/systemd/system/dbus.service + inst /usr/bin/dbus-broker + inst /usr/bin/dbus-broker-launch + elif [ -f $ROOTLIBDIR/system/dbus-daemon.service ]; then + # Fedora rawhide replaced dbus.service with dbus-daemon.service + inst $ROOTLIBDIR/system/dbus-daemon.service + # Alias symlink + inst_symlink /etc/systemd/system/dbus.service + else + inst $ROOTLIBDIR/system/dbus.service + fi + + find \ + /etc/dbus-1 /usr/share/dbus-1 -xtype f \ + | while read file; do + inst $file + done +} + +install_pam() { + ( + if [[ "$LOOKS_LIKE_DEBIAN" ]] && type -p dpkg-architecture &>/dev/null; then + find "/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security" -xtype f + else + find /lib*/security -xtype f + fi + find /etc/pam.d /etc/security -xtype f + ) | while read file; do + inst $file + done + + # pam_unix depends on unix_chkpwd. + # see http://www.linux-pam.org/Linux-PAM-html/sag-pam_unix.html + dracut_install -o unix_chkpwd + + [[ "$LOOKS_LIKE_DEBIAN" ]] && + cp /etc/pam.d/systemd-user $initdir/etc/pam.d/ + + # set empty root password for easy debugging + sed -i 's/^root:x:/root::/' $initdir/etc/passwd +} + +install_keymaps() { + # The first three paths may be deprecated. + # It seems now the last two paths are used by many distributions. + for i in \ + /usr/lib/kbd/keymaps/include/* \ + /usr/lib/kbd/keymaps/i386/include/* \ + /usr/lib/kbd/keymaps/i386/qwerty/us.* \ + /usr/lib/kbd/keymaps/legacy/include/* \ + /usr/lib/kbd/keymaps/legacy/i386/qwerty/us.*; do + [[ -f $i ]] || continue + inst $i + done + + # When it takes any argument, then install more keymaps. + if [[ -n $1 ]]; then + for i in \ + /usr/lib/kbd/keymaps/i386/*/* \ + /usr/lib/kbd/keymaps/legacy/i386/*/*; do + [[ -f $i ]] || continue + inst $i + done + fi +} + +install_zoneinfo() { + for i in /usr/share/zoneinfo/{,*/,*/*/}*; do + [[ -f $i ]] || continue + inst $i + done +} + +install_fonts() { + for i in \ + /usr/lib/kbd/consolefonts/eurlatgr* \ + /usr/lib/kbd/consolefonts/latarcyrheb-sun16*; do + [[ -f $i ]] || continue + inst $i + done +} + +install_terminfo() { + for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do + [ -f ${_terminfodir}/l/linux ] && break + done + dracut_install -o ${_terminfodir}/l/linux +} + +setup_testsuite() { + cp $TEST_BASE_DIR/testsuite.target $initdir/etc/systemd/system/ + cp $TEST_BASE_DIR/end.service $initdir/etc/systemd/system/ + + mkdir -p $initdir/etc/systemd/system/testsuite.target.wants + ln -fs $TEST_BASE_DIR/testsuite.service $initdir/etc/systemd/system/testsuite.target.wants/testsuite.service + # Don't shutdown the machine after running the test when INTERACTIVE_DEBUG is set + [[ -z $INTERACTIVE_DEBUG ]] && ln -fs $TEST_BASE_DIR/end.service $initdir/etc/systemd/system/testsuite.target.wants/end.service + + # make the testsuite the default target + ln -fs testsuite.target $initdir/etc/systemd/system/default.target +} + +setup_nspawn_root() { + rm -fr $TESTDIR/nspawn-root + ddebug "cp -ar $initdir $TESTDIR/nspawn-root" + cp -ar $initdir $TESTDIR/nspawn-root + # we don't mount in the nspawn root + rm -f $TESTDIR/nspawn-root/etc/fstab + if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then + cp -ar $TESTDIR/nspawn-root $TESTDIR/unprivileged-nspawn-root + fi +} + +setup_basic_dirs() { + mkdir -p $initdir/run + mkdir -p $initdir/etc/systemd/system + mkdir -p $initdir/var/log/journal + + for d in usr/bin usr/sbin bin etc lib "$libdir" sbin tmp usr var var/log dev proc sys sysroot root run run/lock run/initramfs; do + if [ -L "/$d" ]; then + inst_symlink "/$d" + else + inst_dir "/$d" + fi + done + + ln -sfn /run "$initdir/var/run" + ln -sfn /run/lock "$initdir/var/lock" +} + +mask_supporting_services() { + # mask some services that we do not want to run in these tests + ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service + ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service + ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service + ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket + ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service +} + +inst_libs() { + local _bin=$1 + local _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)' + local _file _line + + LC_ALL=C ldd "$_bin" 2>/dev/null | while read _line; do + [[ $_line = 'not a dynamic executable' ]] && break + + if [[ $_line =~ $_so_regex ]]; then + _file=${BASH_REMATCH[1]} + [[ -e ${initdir}/$_file ]] && continue + inst_library "$_file" + continue + fi + + if [[ $_line =~ not\ found ]]; then + dfatal "Missing a shared library required by $_bin." + dfatal "Run \"ldd $_bin\" to find out what it is." + dfatal "$_line" + dfatal "dracut cannot create an initrd." + exit 1 + fi + done +} + +import_testdir() { + [[ -e $STATEFILE ]] && . $STATEFILE + if [[ ! -d "$TESTDIR" ]]; then + if [[ -z "$TESTDIR" ]]; then + TESTDIR=$(mktemp --tmpdir=/var/tmp -d -t systemd-test.XXXXXX) + else + mkdir -p "$TESTDIR" + fi + + echo "TESTDIR=\"$TESTDIR\"" > $STATEFILE + export TESTDIR + fi +} + +import_initdir() { + initdir=$TESTDIR/root + mkdir -p $initdir + export initdir +} + +## @brief Converts numeric logging level to the first letter of level name. +# +# @param lvl Numeric logging level in range from 1 to 6. +# @retval 1 if @a lvl is out of range. +# @retval 0 if @a lvl is correct. +# @result Echoes first letter of level name. +_lvl2char() { + case "$1" in + 1) echo F;; + 2) echo E;; + 3) echo W;; + 4) echo I;; + 5) echo D;; + 6) echo T;; + *) return 1;; + esac +} + +## @brief Internal helper function for _do_dlog() +# +# @param lvl Numeric logging level. +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +# +# @note This function is not supposed to be called manually. Please use +# dtrace(), ddebug(), or others instead which wrap this one. +# +# This function calls _do_dlog() either with parameter msg, or if +# none is given, it will read standard input and will use every line as +# a message. +# +# This enables: +# dwarn "This is a warning" +# echo "This is a warning" | dwarn +LOG_LEVEL=${LOG_LEVEL:-4} + +dlog() { + [ -z "$LOG_LEVEL" ] && return 0 + [ $1 -le $LOG_LEVEL ] || return 0 + local lvl="$1"; shift + local lvlc=$(_lvl2char "$lvl") || return 0 + + if [ $# -ge 1 ]; then + echo "$lvlc: $*" + else + while read line; do + echo "$lvlc: " "$line" + done + fi +} + +## @brief Logs message at TRACE level (6) +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +dtrace() { + set +x + dlog 6 "$@" + [ -n "$debug" ] && set -x || : +} + +## @brief Logs message at DEBUG level (5) +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +ddebug() { +# set +x + dlog 5 "$@" +# [ -n "$debug" ] && set -x || : +} + +## @brief Logs message at INFO level (4) +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +dinfo() { + set +x + dlog 4 "$@" + [ -n "$debug" ] && set -x || : +} + +## @brief Logs message at WARN level (3) +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +dwarn() { + set +x + dlog 3 "$@" + [ -n "$debug" ] && set -x || : +} + +## @brief Logs message at ERROR level (2) +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +derror() { +# set +x + dlog 2 "$@" +# [ -n "$debug" ] && set -x || : +} + +## @brief Logs message at FATAL level (1) +# +# @param msg Message. +# @retval 0 It's always returned, even if logging failed. +dfatal() { + set +x + dlog 1 "$@" + [ -n "$debug" ] && set -x || : +} + + +# Generic substring function. If $2 is in $1, return 0. +strstr() { [ "${1#*$2*}" != "$1" ]; } + +# normalize_path +# Prints the normalized path, where it removes any duplicated +# and trailing slashes. +# Example: +# $ normalize_path ///test/test// +# /test/test +normalize_path() { + shopt -q -s extglob + set -- "${1//+(\/)//}" + shopt -q -u extglob + echo "${1%/}" +} + +# convert_abs_rel +# Prints the relative path, when creating a symlink to from . +# Example: +# $ convert_abs_rel /usr/bin/test /bin/test-2 +# ../../bin/test-2 +# $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test +convert_abs_rel() { + local __current __absolute __abssize __cursize __newpath + local -i __i __level + + set -- "$(normalize_path "$1")" "$(normalize_path "$2")" + + # corner case #1 - self looping link + [[ "$1" == "$2" ]] && { echo "${1##*/}"; return; } + + # corner case #2 - own dir link + [[ "${1%/*}" == "$2" ]] && { echo "."; return; } + + IFS="/" __current=($1) + IFS="/" __absolute=($2) + + __abssize=${#__absolute[@]} + __cursize=${#__current[@]} + + while [[ ${__absolute[__level]} == ${__current[__level]} ]] + do + (( __level++ )) + if (( __level > __abssize || __level > __cursize )) + then + break + fi + done + + for ((__i = __level; __i < __cursize-1; __i++)) + do + if ((__i > __level)) + then + __newpath=$__newpath"/" + fi + __newpath=$__newpath".." + done + + for ((__i = __level; __i < __abssize; __i++)) + do + if [[ -n $__newpath ]] + then + __newpath=$__newpath"/" + fi + __newpath=$__newpath${__absolute[__i]} + done + + echo "$__newpath" +} + + +# Install a directory, keeping symlinks as on the original system. +# Example: if /lib points to /lib64 on the host, "inst_dir /lib/file" +# will create ${initdir}/lib64, ${initdir}/lib64/file, +# and a symlink ${initdir}/lib -> lib64. +inst_dir() { + [[ -e ${initdir}/"$1" ]] && return 0 # already there + + local _dir="$1" _part="${1%/*}" _file + while [[ "$_part" != "${_part%/*}" ]] && ! [[ -e "${initdir}/${_part}" ]]; do + _dir="$_part $_dir" + _part=${_part%/*} + done + + # iterate over parent directories + for _file in $_dir; do + [[ -e "${initdir}/$_file" ]] && continue + if [[ -L $_file ]]; then + inst_symlink "$_file" + else + # create directory + mkdir -m 0755 -p "${initdir}/$_file" || return 1 + [[ -e "$_file" ]] && chmod --reference="$_file" "${initdir}/$_file" + chmod u+w "${initdir}/$_file" + fi + done +} + +# $1 = file to copy to ramdisk +# $2 (optional) Name for the file on the ramdisk +# Location of the image dir is assumed to be $initdir +# We never overwrite the target if it exists. +inst_simple() { + [[ -f "$1" ]] || return 1 + strstr "$1" "/" || return 1 + + local _src=$1 target="${2:-$1}" + if ! [[ -d ${initdir}/$target ]]; then + [[ -e ${initdir}/$target ]] && return 0 + [[ -L ${initdir}/$target ]] && return 0 + [[ -d "${initdir}/${target%/*}" ]] || inst_dir "${target%/*}" + fi + # install checksum files also + if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then + inst "${_src%/*}/.${_src##*/}.hmac" "${target%/*}/.${target##*/}.hmac" + fi + ddebug "Installing $_src" + cp --sparse=always -pfL "$_src" "${initdir}/$target" +} + +# find symlinks linked to given library file +# $1 = library file +# Function searches for symlinks by stripping version numbers appended to +# library filename, checks if it points to the same target and finally +# prints the list of symlinks to stdout. +# +# Example: +# rev_lib_symlinks libfoo.so.8.1 +# output: libfoo.so.8 libfoo.so +# (Only if libfoo.so.8 and libfoo.so exists on host system.) +rev_lib_symlinks() { + [[ ! $1 ]] && return 0 + + local fn="$1" orig="$(readlink -f "$1")" links='' + + [[ ${fn} =~ .*\.so\..* ]] || return 1 + + until [[ ${fn##*.} == so ]]; do + fn="${fn%.*}" + [[ -L ${fn} && $(readlink -f "${fn}") == ${orig} ]] && links+=" ${fn}" + done + + echo "${links}" +} + +# Same as above, but specialized to handle dynamic libraries. +# It handles making symlinks according to how the original library +# is referenced. +inst_library() { + local _src="$1" _dest=${2:-$1} _lib _reallib _symlink + strstr "$1" "/" || return 1 + [[ -e $initdir/$_dest ]] && return 0 + if [[ -L $_src ]]; then + # install checksum files also + if [[ -e "${_src%/*}/.${_src##*/}.hmac" ]]; then + inst "${_src%/*}/.${_src##*/}.hmac" "${_dest%/*}/.${_dest##*/}.hmac" + fi + _reallib=$(readlink -f "$_src") + inst_simple "$_reallib" "$_reallib" + inst_dir "${_dest%/*}" + [[ -d "${_dest%/*}" ]] && _dest=$(readlink -f "${_dest%/*}")/${_dest##*/} + ln -sfn $(convert_abs_rel "${_dest}" "${_reallib}") "${initdir}/${_dest}" + else + inst_simple "$_src" "$_dest" + fi + + # Create additional symlinks. See rev_symlinks description. + for _symlink in $(rev_lib_symlinks $_src) $(rev_lib_symlinks $_reallib); do + [[ -e $initdir/$_symlink ]] || { + ddebug "Creating extra symlink: $_symlink" + inst_symlink $_symlink + } + done +} + +# find a binary. If we were not passed the full path directly, +# search in the usual places to find the binary. +find_binary() { + if [[ -z ${1##/*} ]]; then + if [[ -x $1 ]] || { strstr "$1" ".so" && ldd $1 &>/dev/null; }; then + echo $1 + return 0 + fi + fi + + type -P $1 +} + +# Same as above, but specialized to install binary executables. +# Install binary executable, and all shared library dependencies, if any. +inst_binary() { + local _bin _target + + # In certain cases we might attempt to install a binary which is already + # present in the test image, yet it's missing from the host system. + # In such cases, let's check if the binary indeed exists in the image + # before doing any other chcecks. If it does, immediately return with + # success. + [[ $# -eq 1 && -e $initdir/$1 ]] && return 0 + + _bin=$(find_binary "$1") || return 1 + _target=${2:-$_bin} + [[ -e $initdir/$_target ]] && return 0 + [[ -L $_bin ]] && inst_symlink $_bin $_target && return 0 + local _file _line + local _so_regex='([^ ]*/lib[^/]*/[^ ]*\.so[^ ]*)' + # I love bash! + LC_ALL=C ldd "$_bin" 2>/dev/null | while read _line; do + [[ $_line = 'not a dynamic executable' ]] && break + + if [[ $_line =~ $_so_regex ]]; then + _file=${BASH_REMATCH[1]} + [[ -e ${initdir}/$_file ]] && continue + inst_library "$_file" + continue + fi + + if [[ $_line =~ not\ found ]]; then + dfatal "Missing a shared library required by $_bin." + dfatal "Run \"ldd $_bin\" to find out what it is." + dfatal "$_line" + dfatal "dracut cannot create an initrd." + exit 1 + fi + done + inst_simple "$_bin" "$_target" +} + +# same as above, except for shell scripts. +# If your shell script does not start with shebang, it is not a shell script. +inst_script() { + local _bin + _bin=$(find_binary "$1") || return 1 + shift + local _line _shebang_regex + read -r -n 80 _line <"$_bin" + # If debug is set, clean unprintable chars to prevent messing up the term + [[ $debug ]] && _line=$(echo -n "$_line" | tr -c -d '[:print:][:space:]') + _shebang_regex='(#! *)(/[^ ]+).*' + [[ $_line =~ $_shebang_regex ]] || return 1 + inst "${BASH_REMATCH[2]}" && inst_simple "$_bin" "$@" +} + +# same as above, but specialized for symlinks +inst_symlink() { + local _src=$1 _target=${2:-$1} _realsrc + strstr "$1" "/" || return 1 + [[ -L $1 ]] || return 1 + [[ -L $initdir/$_target ]] && return 0 + _realsrc=$(readlink -f "$_src") + if ! [[ -e $initdir/$_realsrc ]]; then + if [[ -d $_realsrc ]]; then + inst_dir "$_realsrc" + else + inst "$_realsrc" + fi + fi + [[ ! -e $initdir/${_target%/*} ]] && inst_dir "${_target%/*}" + [[ -d ${_target%/*} ]] && _target=$(readlink -f ${_target%/*})/${_target##*/} + ln -sfn $(convert_abs_rel "${_target}" "${_realsrc}") "$initdir/$_target" +} + +# attempt to install any programs specified in a udev rule +inst_rule_programs() { + local _prog _bin + + if grep -qE 'PROGRAM==?"[^ "]+' "$1"; then + for _prog in $(grep -E 'PROGRAM==?"[^ "]+' "$1" | sed -r 's/.*PROGRAM==?"([^ "]+).*/\1/'); do + if [ -x /lib/udev/$_prog ]; then + _bin=/lib/udev/$_prog + else + _bin=$(find_binary "$_prog") || { + dinfo "Skipping program $_prog using in udev rule $(basename $1) as it cannot be found" + continue; + } + fi + + #dinfo "Installing $_bin due to it's use in the udev rule $(basename $1)" + dracut_install "$_bin" + done + fi +} + +# udev rules always get installed in the same place, so +# create a function to install them to make life simpler. +inst_rules() { + local _target=/etc/udev/rules.d _rule _found + + inst_dir "/lib/udev/rules.d" + inst_dir "$_target" + for _rule in "$@"; do + if [ "${rule#/}" = "$rule" ]; then + for r in /lib/udev/rules.d /etc/udev/rules.d; do + if [[ -f $r/$_rule ]]; then + _found="$r/$_rule" + inst_simple "$_found" + inst_rule_programs "$_found" + fi + done + fi + for r in '' ./ $dracutbasedir/rules.d/; do + if [[ -f ${r}$_rule ]]; then + _found="${r}$_rule" + inst_simple "$_found" "$_target/${_found##*/}" + inst_rule_programs "$_found" + fi + done + [[ $_found ]] || dinfo "Skipping udev rule: $_rule" + _found= + done +} + +# general purpose installation function +# Same args as above. +inst() { + local _x + + case $# in + 1) ;; + 2) [[ ! $initdir && -d $2 ]] && export initdir=$2 + [[ $initdir = $2 ]] && set $1;; + 3) [[ -z $initdir ]] && export initdir=$2 + set $1 $3;; + *) dfatal "inst only takes 1 or 2 or 3 arguments" + exit 1;; + esac + for _x in inst_symlink inst_script inst_binary inst_simple; do + $_x "$@" && return 0 + done + return 1 +} + +# install any of listed files +# +# If first argument is '-d' and second some destination path, first accessible +# source is installed into this path, otherwise it will installed in the same +# path as source. If none of listed files was installed, function return 1. +# On first successful installation it returns with 0 status. +# +# Example: +# +# inst_any -d /bin/foo /bin/bar /bin/baz +# +# Lets assume that /bin/baz exists, so it will be installed as /bin/foo in +# initramfs. +inst_any() { + local to f + + [[ $1 = '-d' ]] && to="$2" && shift 2 + + for f in "$@"; do + if [[ -e $f ]]; then + [[ $to ]] && inst "$f" "$to" && return 0 + inst "$f" && return 0 + fi + done + + return 1 +} + +# dracut_install [-o ] [ ... ] +# Install to the initramfs image +# -o optionally install the and don't fail, if it is not there +dracut_install() { + local _optional=no + if [[ $1 = '-o' ]]; then + _optional=yes + shift + fi + while (($# > 0)); do + if ! inst "$1" ; then + if [[ $_optional = yes ]]; then + dinfo "Skipping program $1 as it cannot be found and is" \ + "flagged to be optional" + else + dfatal "Failed to install $1" + exit 1 + fi + fi + shift + done +} + +# Install a single kernel module along with any firmware it may require. +# $1 = full path to kernel module to install +install_kmod_with_fw() { + # no need to go further if the module is already installed + + [[ -e "${initdir}/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" ]] \ + && return 0 + + [[ -e "$initdir/.kernelmodseen/${1##*/}" ]] && return 0 + + if [[ $omit_drivers ]]; then + local _kmod=${1##*/} + _kmod=${_kmod%.ko} + _kmod=${_kmod/-/_} + if [[ "$_kmod" =~ $omit_drivers ]]; then + dinfo "Omitting driver $_kmod" + return 1 + fi + if [[ "${1##*/lib/modules/$KERNEL_VER/}" =~ $omit_drivers ]]; then + dinfo "Omitting driver $_kmod" + return 1 + fi + fi + + [ -d "$initdir/.kernelmodseen" ] && \ + > "$initdir/.kernelmodseen/${1##*/}" + + inst_simple "$1" "/lib/modules/$KERNEL_VER/${1##*/lib/modules/$KERNEL_VER/}" \ + || return $? + + local _modname=${1##*/} _fwdir _found _fw + _modname=${_modname%.ko*} + for _fw in $(modinfo -k $KERNEL_VER -F firmware $1 2>/dev/null); do + _found='' + for _fwdir in $fw_dir; do + if [[ -d $_fwdir && -f $_fwdir/$_fw ]]; then + inst_simple "$_fwdir/$_fw" "/lib/firmware/$_fw" + _found=yes + fi + done + if [[ $_found != yes ]]; then + if ! grep -qe "\<${_modname//-/_}\>" /proc/modules; then + dinfo "Possible missing firmware \"${_fw}\" for kernel module" \ + "\"${_modname}.ko\"" + else + dwarn "Possible missing firmware \"${_fw}\" for kernel module" \ + "\"${_modname}.ko\"" + fi + fi + done + return 0 +} + +# Do something with all the dependencies of a kernel module. +# Note that kernel modules depend on themselves using the technique we use +# $1 = function to call for each dependency we find +# It will be passed the full path to the found kernel module +# $2 = module to get dependencies for +# rest of args = arguments to modprobe +# _fderr specifies FD passed from surrounding scope +for_each_kmod_dep() { + local _func=$1 _kmod=$2 _cmd _modpath _options _found=0 + shift 2 + modprobe "$@" --ignore-install --show-depends $_kmod 2>&${_fderr} | ( + while read _cmd _modpath _options; do + [[ $_cmd = insmod ]] || continue + $_func ${_modpath} || exit $? + _found=1 + done + [[ $_found -eq 0 ]] && exit 1 + exit 0 + ) +} + +# filter kernel modules to install certain modules that meet specific +# requirements. +# $1 = search only in subdirectory of /kernel/$1 +# $2 = function to call with module name to filter. +# This function will be passed the full path to the module to test. +# The behavior of this function can vary depending on whether $hostonly is set. +# If it is, we will only look at modules that are already in memory. +# If it is not, we will look at all kernel modules +# This function returns the full filenames of modules that match $1 +filter_kernel_modules_by_path () ( + local _modname _filtercmd + if ! [[ $hostonly ]]; then + _filtercmd='find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra"' + _filtercmd+=' "$KERNEL_MODS/weak-updates" -name "*.ko" -o -name "*.ko.gz"' + _filtercmd+=' -o -name "*.ko.xz"' + _filtercmd+=' 2>/dev/null' + else + _filtercmd='cut -d " " -f 1 $initdir/$$.ko + $2 $initdir/$$.ko && echo "$_modname" + rm -f $initdir/$$.ko + ;; + *.ko.xz) xz -dc "$_modname" > $initdir/$$.ko + $2 $initdir/$$.ko && echo "$_modname" + rm -f $initdir/$$.ko + ;; + esac + done +) +find_kernel_modules_by_path () ( + if ! [[ $hostonly ]]; then + find "$KERNEL_MODS/kernel/$1" "$KERNEL_MODS/extra" "$KERNEL_MODS/weak-updates" \ + -name "*.ko" -o -name "*.ko.gz" -o -name "*.ko.xz" 2>/dev/null + else + cut -d " " -f 1 /dev/null + fi +) + +filter_kernel_modules () { + filter_kernel_modules_by_path drivers "$1" +} + +find_kernel_modules () { + find_kernel_modules_by_path drivers +} + +# instmods [-c] [ ... ] +# instmods [-c] +# install kernel modules along with all their dependencies. +# can be e.g. "=block" or "=drivers/usb/storage" +instmods() { + [[ $no_kernel = yes ]] && return + # called [sub]functions inherit _fderr + local _fderr=9 + local _check=no + if [[ $1 = '-c' ]]; then + _check=yes + shift + fi + + function inst1mod() { + local _ret=0 _mod="$1" + case $_mod in + =*) + if [ -f $KERNEL_MODS/modules.${_mod#=} ]; then + ( [[ "$_mpargs" ]] && echo $_mpargs + cat "${KERNEL_MODS}/modules.${_mod#=}" ) \ + | instmods + else + ( [[ "$_mpargs" ]] && echo $_mpargs + find "$KERNEL_MODS" -path "*/${_mod#=}/*" -type f -printf '%f\n' ) \ + | instmods + fi + ;; + --*) _mpargs+=" $_mod" ;; + i2o_scsi) return ;; # Do not load this diagnostic-only module + *) + _mod=${_mod##*/} + # if we are already installed, skip this module and go on + # to the next one. + [[ -f "$initdir/.kernelmodseen/${_mod%.ko}.ko" ]] && return + + if [[ $omit_drivers ]] && [[ "$1" =~ $omit_drivers ]]; then + dinfo "Omitting driver ${_mod##$KERNEL_MODS}" + return + fi + # If we are building a host-specific initramfs and this + # module is not already loaded, move on to the next one. + [[ $hostonly ]] && ! grep -qe "\<${_mod//-/_}\>" /proc/modules \ + && ! echo $add_drivers | grep -qe "\<${_mod}\>" \ + && return + + # We use '-d' option in modprobe only if modules prefix path + # differs from default '/'. This allows us to use Dracut with + # old version of modprobe which doesn't have '-d' option. + local _moddirname=${KERNEL_MODS%%/lib/modules/*} + [[ -n ${_moddirname} ]] && _moddirname="-d ${_moddirname}/" + + # ok, load the module, all its dependencies, and any firmware + # it may require + for_each_kmod_dep install_kmod_with_fw $_mod \ + --set-version $KERNEL_VER ${_moddirname} $_mpargs + ((_ret+=$?)) + ;; + esac + return $_ret + } + + function instmods_1() { + local _mod _mpargs + if (($# == 0)); then # filenames from stdin + while read _mod; do + inst1mod "${_mod%.ko*}" || { + if [ "$_check" = "yes" ]; then + dfatal "Failed to install $_mod" + return 1 + fi + } + done + fi + while (($# > 0)); do # filenames as arguments + inst1mod ${1%.ko*} || { + if [ "$_check" = "yes" ]; then + dfatal "Failed to install $1" + return 1 + fi + } + shift + done + return 0 + } + + local _ret _filter_not_found='FATAL: Module .* not found.' + set -o pipefail + # Capture all stderr from modprobe to _fderr. We could use {var}>... + # redirections, but that would make dracut require bash4 at least. + eval "( instmods_1 \"\$@\" ) ${_fderr}>&1" \ + | while read line; do [[ "$line" =~ $_filter_not_found ]] && echo $line || echo $line >&2 ;done | derror + _ret=$? + set +o pipefail + return $_ret +} + +setup_suse() { + ln -fs ../usr/bin/systemctl $initdir/bin/ + ln -fs ../usr/lib/systemd $initdir/lib/ + inst_simple "/usr/lib/systemd/system/haveged.service" +} + +_umount_dir() { + if mountpoint -q $1; then + ddebug "umount $1" + umount $1 + fi +} + +_test_setup_cleanup() { + # only umount if create_empty_image_rootdir() was called to mount it + [[ -z $TEST_SETUP_CLEANUP_ROOTDIR ]] || _umount_dir $initdir +} + +# can be overridden in specific test +test_setup_cleanup() { + _test_setup_cleanup +} + +_test_cleanup() { + # (post-test) cleanup should always ignore failure and cleanup as much as possible + ( + set +e + _umount_dir $initdir + if [[ $LOOPDEV && -b $LOOPDEV ]]; then + ddebug "losetup -d $LOOPDEV" + losetup -d $LOOPDEV + fi + rm -fr "$TESTDIR" + rm -f "$STATEFILE" + ) || : +} + +# can be overridden in specific test +test_cleanup() { + _test_cleanup +} + +test_run() { + if [ -z "$TEST_NO_QEMU" ]; then + if run_qemu; then + check_result_qemu || return 1 + else + dwarn "can't run QEMU, skipping" + fi + fi + if [ -z "$TEST_NO_NSPAWN" ]; then + if run_nspawn "nspawn-root"; then + check_result_nspawn "nspawn-root" || return 1 + else + dwarn "can't run systemd-nspawn, skipping" + fi + + if [[ "$RUN_IN_UNPRIVILEGED_CONTAINER" = "yes" ]]; then + if NSPAWN_ARGUMENTS="-U --private-network $NSPAWN_ARGUMENTS" run_nspawn "unprivileged-nspawn-root"; then + check_result_nspawn "unprivileged-nspawn-root" || return 1 + else + dwarn "can't run systemd-nspawn, skipping" + fi + fi + fi + return 0 +} + +do_test() { + if [[ $UID != "0" ]]; then + echo "TEST: $TEST_DESCRIPTION [SKIPPED]: not root" >&2 + exit 0 + fi + + # Detect lib paths + [[ $libdir ]] || for libdir in /lib64 /lib; do + [[ -d $libdir ]] && libdirs+=" $libdir" && break + done + + [[ $usrlibdir ]] || for usrlibdir in /usr/lib64 /usr/lib; do + [[ -d $usrlibdir ]] && libdirs+=" $usrlibdir" && break + done + + mkdir -p "$STATEDIR" + + import_testdir + import_initdir + + while (($# > 0)); do + case $1 in + --run) + echo "TEST RUN: $TEST_DESCRIPTION" + test_run + ret=$? + if (( $ret == 0 )); then + echo "TEST RUN: $TEST_DESCRIPTION [OK]" + else + echo "TEST RUN: $TEST_DESCRIPTION [FAILED]" + fi + exit $ret;; + --setup) + echo "TEST SETUP: $TEST_DESCRIPTION" + test_setup + test_setup_cleanup + ;; + --clean) + echo "TEST CLEANUP: $TEST_DESCRIPTION" + test_cleanup + ;; + --all) + ret=0 + echo -n "TEST: $TEST_DESCRIPTION " + ( + test_setup + test_setup_cleanup + test_run + ) "$TESTLOG" 2>&1 || ret=$? + test_cleanup + if [ $ret -eq 0 ]; then + rm "$TESTLOG" + echo "[OK]" + else + echo "[FAILED]" + echo "see $TESTLOG" + fi + exit $ret;; + *) break ;; + esac + shift + done +} diff --git a/test/test-network/conf/10-dropin-test.netdev b/test/test-network/conf/10-dropin-test.netdev new file mode 100644 index 00000000..d85ea5bb --- /dev/null +++ b/test/test-network/conf/10-dropin-test.netdev @@ -0,0 +1,4 @@ +[NetDev] +Name=hoge +Kind=dummy +MACAddress=00:50:56:c0:00:18 diff --git a/test/test-network/conf/10-dropin-test.netdev.d/mac.conf b/test/test-network/conf/10-dropin-test.netdev.d/mac.conf new file mode 100644 index 00000000..0b3f7659 --- /dev/null +++ b/test/test-network/conf/10-dropin-test.netdev.d/mac.conf @@ -0,0 +1,2 @@ +[NetDev] +MACAddress=00:50:56:c0:00:28 diff --git a/test/test-network/conf/10-dropin-test.netdev.d/name.conf b/test/test-network/conf/10-dropin-test.netdev.d/name.conf new file mode 100644 index 00000000..99059320 --- /dev/null +++ b/test/test-network/conf/10-dropin-test.netdev.d/name.conf @@ -0,0 +1,2 @@ +[NetDev] +Name=dropin-test diff --git a/test/test-network/conf/11-dummy-mtu.netdev b/test/test-network/conf/11-dummy-mtu.netdev new file mode 100644 index 00000000..aeecc1dc --- /dev/null +++ b/test/test-network/conf/11-dummy-mtu.netdev @@ -0,0 +1,4 @@ +[NetDev] +Name=test1 +Kind=dummy +MTUBytes=1600 diff --git a/test/test-network/conf/11-dummy.netdev b/test/test-network/conf/11-dummy.netdev new file mode 100644 index 00000000..6797eb4b --- /dev/null +++ b/test/test-network/conf/11-dummy.netdev @@ -0,0 +1,3 @@ +[NetDev] +Name=test1 +Kind=dummy diff --git a/test/test-network/conf/11-dummy.network b/test/test-network/conf/11-dummy.network new file mode 100644 index 00000000..b117028a --- /dev/null +++ b/test/test-network/conf/11-dummy.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +IPv6AcceptRA=no diff --git a/test/test-network/conf/12-dummy.netdev b/test/test-network/conf/12-dummy.netdev new file mode 100644 index 00000000..a7fdc0f7 --- /dev/null +++ b/test/test-network/conf/12-dummy.netdev @@ -0,0 +1,3 @@ +[NetDev] +Name=dummy98 +Kind=dummy diff --git a/test/test-network/conf/13-not-match-udev-property.network b/test/test-network/conf/13-not-match-udev-property.network new file mode 100644 index 00000000..f0a530e9 --- /dev/null +++ b/test/test-network/conf/13-not-match-udev-property.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 +Property=INTERFACE=hoge + +[Network] +IPv6AcceptRA=false diff --git a/test/test-network/conf/14-match-udev-property.network b/test/test-network/conf/14-match-udev-property.network new file mode 100644 index 00000000..b632af16 --- /dev/null +++ b/test/test-network/conf/14-match-udev-property.network @@ -0,0 +1,7 @@ +[Match] +Name=dummy98 +Property=INTERFACE=dummy98 + +[Network] +IPv6AcceptRA=false +Address=10.1.2.3/16 diff --git a/test/test-network/conf/15-name-conflict-test.netdev b/test/test-network/conf/15-name-conflict-test.netdev new file mode 100644 index 00000000..c9d18d76 --- /dev/null +++ b/test/test-network/conf/15-name-conflict-test.netdev @@ -0,0 +1,4 @@ +[NetDev] +Name=dropin-test +Kind=dummy +MACAddress=00:50:56:c0:00:38 diff --git a/test/test-network/conf/21-macvlan.netdev b/test/test-network/conf/21-macvlan.netdev new file mode 100644 index 00000000..674c1f51 --- /dev/null +++ b/test/test-network/conf/21-macvlan.netdev @@ -0,0 +1,4 @@ +[NetDev] +Name=macvlan99 +Kind=macvlan +MTUBytes=2000 diff --git a/test/test-network/conf/21-macvtap.netdev b/test/test-network/conf/21-macvtap.netdev new file mode 100644 index 00000000..2c23aacf --- /dev/null +++ b/test/test-network/conf/21-macvtap.netdev @@ -0,0 +1,3 @@ +[NetDev] +Name=macvtap99 +Kind=macvtap diff --git a/test/test-network/conf/21-vlan-test1.network b/test/test-network/conf/21-vlan-test1.network new file mode 100644 index 00000000..afe1debe --- /dev/null +++ b/test/test-network/conf/21-vlan-test1.network @@ -0,0 +1,2 @@ +[Match] +Name=test1 diff --git a/test/test-network/conf/21-vlan-test1.network.d/override.conf b/test/test-network/conf/21-vlan-test1.network.d/override.conf new file mode 100644 index 00000000..06307ff3 --- /dev/null +++ b/test/test-network/conf/21-vlan-test1.network.d/override.conf @@ -0,0 +1,5 @@ +[Network] +VLAN=vlan99 +Address=192.168.24.5/24 +Address=192.168.25.5/24 +IPv6AcceptRA=false diff --git a/test/test-network/conf/21-vlan.netdev b/test/test-network/conf/21-vlan.netdev new file mode 100644 index 00000000..af39404b --- /dev/null +++ b/test/test-network/conf/21-vlan.netdev @@ -0,0 +1,3 @@ +[NetDev] +Name=vlan99 +Kind=vlan diff --git a/test/test-network/conf/21-vlan.netdev.d/override.conf b/test/test-network/conf/21-vlan.netdev.d/override.conf new file mode 100644 index 00000000..3b8d47d9 --- /dev/null +++ b/test/test-network/conf/21-vlan.netdev.d/override.conf @@ -0,0 +1,9 @@ +[NetDev] +MTUBytes=2000 + +[VLAN] +Id=99 +GVRP=true +MVRP=true +LooseBinding=true +ReorderHeader=true diff --git a/test/test-network/conf/21-vlan.network b/test/test-network/conf/21-vlan.network new file mode 100644 index 00000000..3edc59e7 --- /dev/null +++ b/test/test-network/conf/21-vlan.network @@ -0,0 +1,7 @@ +[Match] +Name=vlan99 + +[Network] +IPv6AcceptRA=false +Address=192.168.23.5/24 +LinkLocalAddressing=yes diff --git a/test/test-network/conf/23-active-slave.network b/test/test-network/conf/23-active-slave.network new file mode 100644 index 00000000..59a65960 --- /dev/null +++ b/test/test-network/conf/23-active-slave.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +Bond=bond199 +ActiveSlave=true diff --git a/test/test-network/conf/23-bond199.network b/test/test-network/conf/23-bond199.network new file mode 100644 index 00000000..31e5d12f --- /dev/null +++ b/test/test-network/conf/23-bond199.network @@ -0,0 +1,2 @@ +[Match] +Name=bond199 diff --git a/test/test-network/conf/23-emit-lldp.network b/test/test-network/conf/23-emit-lldp.network new file mode 100644 index 00000000..de350453 --- /dev/null +++ b/test/test-network/conf/23-emit-lldp.network @@ -0,0 +1,5 @@ +[Match] +Name=veth-peer + +[Network] +EmitLLDP=yes diff --git a/test/test-network/conf/23-primary-slave.network b/test/test-network/conf/23-primary-slave.network new file mode 100644 index 00000000..380ae267 --- /dev/null +++ b/test/test-network/conf/23-primary-slave.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +Bond=bond199 +PrimarySlave=true diff --git a/test/test-network/conf/24-keep-configuration-static.network b/test/test-network/conf/24-keep-configuration-static.network new file mode 100644 index 00000000..0c65a1d9 --- /dev/null +++ b/test/test-network/conf/24-keep-configuration-static.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +KeepConfiguration=static diff --git a/test/test-network/conf/24-lldp.network b/test/test-network/conf/24-lldp.network new file mode 100644 index 00000000..fbdfb1b6 --- /dev/null +++ b/test/test-network/conf/24-lldp.network @@ -0,0 +1,5 @@ +[Match] +Name=veth99 + +[Network] +LLDP=yes diff --git a/test/test-network/conf/24-search-domain.network b/test/test-network/conf/24-search-domain.network new file mode 100644 index 00000000..124af438 --- /dev/null +++ b/test/test-network/conf/24-search-domain.network @@ -0,0 +1,7 @@ +[Match] +Name=dummy98 + +[Network] +Address=192.168.42.100/24 +DNS=192.168.42.1 +Domains= one two three four five six seven eight nine ten diff --git a/test/test-network/conf/25-6rd-tunnel.netdev b/test/test-network/conf/25-6rd-tunnel.netdev new file mode 100644 index 00000000..756beccb --- /dev/null +++ b/test/test-network/conf/25-6rd-tunnel.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=sittun99 +Kind=sit + +[Tunnel] +Local=10.65.223.238 +IPv6RapidDeploymentPrefix=2602::/24 diff --git a/test/test-network/conf/25-address-link-section.network b/test/test-network/conf/25-address-link-section.network new file mode 100644 index 00000000..759e83c3 --- /dev/null +++ b/test/test-network/conf/25-address-link-section.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Link] +MACAddress=00:01:02:aa:bb:cc diff --git a/test/test-network/conf/25-address-preferred-lifetime-zero.network b/test/test-network/conf/25-address-preferred-lifetime-zero.network new file mode 100644 index 00000000..a1e76051 --- /dev/null +++ b/test/test-network/conf/25-address-preferred-lifetime-zero.network @@ -0,0 +1,33 @@ +[Match] +Name=dummy98 + +[Network] +# these lines are ignored +Address=hogehoge +Address=foofoo + +[Route] +Gateway=20.20.20.1 + +[Address] +Address=10.2.3.4/16 +PreferredLifetime=0 +Scope=link + +[Address] +Address=2001:0db8:0:f101::1/64 + +[Address] +Address=20.20.20.100/24 + +[Address] +# this section must be ignored +Peer=hoge +Address=10.10.0.1/16 +Label=30 + +[Address] +# this section must be ignored +Label=30 +Peer=hoge +Address=10.10.0.2/16 diff --git a/test/test-network/conf/25-address-static.network b/test/test-network/conf/25-address-static.network new file mode 100644 index 00000000..e9780f2e --- /dev/null +++ b/test/test-network/conf/25-address-static.network @@ -0,0 +1,53 @@ +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 +Address=10.1.2.4/16 +Address=10.2.2.4/16 +Address=2001:db8:0:f101::15/64 +Address=2001:db8:0:f101::16/64 +Address=2001:db8:0:f102::15/64 +# these lines are ignored +Address=hogehoge +Address=foofoo + +[Address] +Address=10.3.2.3/16 +Label=32 + +[Address] +Address=10.4.2.3/16 +Peer=10.4.2.4/16 +Label=33 + +[Address] +Address=0.0.0.0/24 +Label=34 + +[Address] +Address=0.0.0.0/16 +Label=35 + +[Address] +# this section must be ignored +Peer=hoge +Address=10.10.0.1/16 +Label=30 + +[Address] +# this section must be ignored +Label=30 +Peer=hoge +Address=10.10.0.2/16 + +[Address] +Address=2001:db8:0:f102::16/64 + +[Address] +Address=2001:db8:0:f103::20/128 +Peer=2001:db8:0:f103::10/128 + +[Address] +Address=::/64 diff --git a/test/test-network/conf/25-bind-carrier.network b/test/test-network/conf/25-bind-carrier.network new file mode 100644 index 00000000..cf854d35 --- /dev/null +++ b/test/test-network/conf/25-bind-carrier.network @@ -0,0 +1,8 @@ +[Match] +Name=test1 + +[Network] +BindCarrier=dummy99 dummy98 +Address=192.168.10.30/24 +Gateway=192.168.10.1 +IPv6AcceptRA=no diff --git a/test/test-network/conf/25-bond-active-backup-slave.netdev b/test/test-network/conf/25-bond-active-backup-slave.netdev new file mode 100644 index 00000000..1bbbf755 --- /dev/null +++ b/test/test-network/conf/25-bond-active-backup-slave.netdev @@ -0,0 +1,6 @@ +[NetDev] +Name=bond199 +Kind=bond + +[Bond] +Mode=active-backup diff --git a/test/test-network/conf/25-bond-balanced-tlb.netdev b/test/test-network/conf/25-bond-balanced-tlb.netdev new file mode 100644 index 00000000..7e6a9edc --- /dev/null +++ b/test/test-network/conf/25-bond-balanced-tlb.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=bond98 +Kind=bond + +[Bond] +Mode=balance-tlb +DynamicTransmitLoadBalancing=true diff --git a/test/test-network/conf/25-bond.netdev b/test/test-network/conf/25-bond.netdev new file mode 100644 index 00000000..4e4885c4 --- /dev/null +++ b/test/test-network/conf/25-bond.netdev @@ -0,0 +1,18 @@ +[NetDev] +Name=bond99 +Kind=bond + +[Bond] +Mode=802.3ad +TransmitHashPolicy=layer3+4 +MIIMonitorSec=1s +LACPTransmitRate=fast +UpDelaySec=2s +DownDelaySec=2s +ResendIGMP=4 +MinLinks=1 +AdActorSystemPriority=1218 +AdUserPortKey=811 +AdActorSystem=00:11:22:33:44:55 +# feed the sanitizer +AdActorSystem=00:11:22:33:44:55 diff --git a/test/test-network/conf/25-bridge-configure-without-carrier.network b/test/test-network/conf/25-bridge-configure-without-carrier.network new file mode 100644 index 00000000..c7d25832 --- /dev/null +++ b/test/test-network/conf/25-bridge-configure-without-carrier.network @@ -0,0 +1,7 @@ +[Match] +Name=bridge99 + +[Network] +LinkLocalAddressing=yes +IPv6AcceptRA=no +ConfigureWithoutCarrier=yes diff --git a/test/test-network/conf/25-bridge.netdev b/test/test-network/conf/25-bridge.netdev new file mode 100644 index 00000000..f5c93516 --- /dev/null +++ b/test/test-network/conf/25-bridge.netdev @@ -0,0 +1,14 @@ +[NetDev] +Name=bridge99 +Kind=bridge + +[Bridge] +HelloTimeSec=9 +MaxAgeSec=9 +ForwardDelaySec=9 +AgeingTimeSec=9 +Priority=9 +MulticastQuerier= true +MulticastSnooping=true +STP=true +MulticastIGMPVersion=3 diff --git a/test/test-network/conf/25-bridge.network b/test/test-network/conf/25-bridge.network new file mode 100644 index 00000000..d2f34638 --- /dev/null +++ b/test/test-network/conf/25-bridge.network @@ -0,0 +1,5 @@ +[Match] +Name=bridge99 + +[Network] +IPv6AcceptRA=no diff --git a/test/test-network/conf/25-erspan-tunnel-local-any.netdev b/test/test-network/conf/25-erspan-tunnel-local-any.netdev new file mode 100644 index 00000000..e9eb1c1c --- /dev/null +++ b/test/test-network/conf/25-erspan-tunnel-local-any.netdev @@ -0,0 +1,10 @@ +[NetDev] +Name=erspan98 +Kind=erspan + +[Tunnel] +ERSPANIndex=124 +Local = any +Remote = 172.16.1.100 +Key=102 +SerializeTunneledPackets=true diff --git a/test/test-network/conf/25-erspan-tunnel.netdev b/test/test-network/conf/25-erspan-tunnel.netdev new file mode 100644 index 00000000..86935e99 --- /dev/null +++ b/test/test-network/conf/25-erspan-tunnel.netdev @@ -0,0 +1,10 @@ +[NetDev] +Name=erspan99 +Kind=erspan + +[Tunnel] +ERSPANIndex=123 +Local = 172.16.1.200 +Remote = 172.16.1.100 +Key=101 +SerializeTunneledPackets=true diff --git a/test/test-network/conf/25-fibrule-invert.network b/test/test-network/conf/25-fibrule-invert.network new file mode 100644 index 00000000..bcca0c27 --- /dev/null +++ b/test/test-network/conf/25-fibrule-invert.network @@ -0,0 +1,10 @@ +[Match] +Name=test1 + +[RoutingPolicyRule] +TypeOfService=0x08 +Table=7 +From= 192.168.100.18 +Priority=111 +IPProtocol = tcp +InvertRule=true diff --git a/test/test-network/conf/25-fibrule-port-range.network b/test/test-network/conf/25-fibrule-port-range.network new file mode 100644 index 00000000..36646ec0 --- /dev/null +++ b/test/test-network/conf/25-fibrule-port-range.network @@ -0,0 +1,11 @@ +[Match] +Name=test1 + +[RoutingPolicyRule] +TypeOfService=0x08 +Table=7 +From= 192.168.100.18 +Priority=111 +SourcePort = 1123-1150 +DestinationPort = 3224-3290 +IPProtocol = tcp diff --git a/test/test-network/conf/25-fou-gre.netdev b/test/test-network/conf/25-fou-gre.netdev new file mode 100644 index 00000000..6ace606e --- /dev/null +++ b/test/test-network/conf/25-fou-gre.netdev @@ -0,0 +1,14 @@ +[NetDev] +Name=gretun96 +Kind=gre + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 +Key=1.2.5.103 +SerializeTunneledPackets=true +Independent=true + +FooOverUDP=yes +FOUDestinationPort=55556 +FOUSourcePort=1001 diff --git a/test/test-network/conf/25-fou-gretap.netdev b/test/test-network/conf/25-fou-gretap.netdev new file mode 100644 index 00000000..97fbc13d --- /dev/null +++ b/test/test-network/conf/25-fou-gretap.netdev @@ -0,0 +1,13 @@ +[NetDev] +Name=gretap96 +Kind=gretap + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 +Key=1.2.5.106 +SerializeTunneledPackets=true +Independent=true + +FooOverUDP=yes +FOUDestinationPort=55556 diff --git a/test/test-network/conf/25-fou-ipip.netdev b/test/test-network/conf/25-fou-ipip.netdev new file mode 100644 index 00000000..2f521574 --- /dev/null +++ b/test/test-network/conf/25-fou-ipip.netdev @@ -0,0 +1,12 @@ +[NetDev] +Name=ipiptun96 +Kind=ipip +MTUBytes=1480 + +[Tunnel] +Local=192.168.223.238 +Remote=192.169.224.239 +Independent=true + +FooOverUDP=yes +FOUDestinationPort=55555 diff --git a/test/test-network/conf/25-fou-ipproto-gre.netdev b/test/test-network/conf/25-fou-ipproto-gre.netdev new file mode 100644 index 00000000..09ecd9ef --- /dev/null +++ b/test/test-network/conf/25-fou-ipproto-gre.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=fou98 +Kind=fou + +[FooOverUDP] +Encapsulation=FooOverUDP +Port=55556 +Protocol=GRE diff --git a/test/test-network/conf/25-fou-ipproto-ipip.netdev b/test/test-network/conf/25-fou-ipproto-ipip.netdev new file mode 100644 index 00000000..b00d5ce5 --- /dev/null +++ b/test/test-network/conf/25-fou-ipproto-ipip.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=fou99 +Kind=fou + +[FooOverUDP] +Encapsulation=FooOverUDP +Port=55555 +Protocol=ipip diff --git a/test/test-network/conf/25-fou-sit.netdev b/test/test-network/conf/25-fou-sit.netdev new file mode 100644 index 00000000..f1b4f325 --- /dev/null +++ b/test/test-network/conf/25-fou-sit.netdev @@ -0,0 +1,11 @@ +[NetDev] +Name=sittun96 +Kind=sit + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 +Independent=true + +FooOverUDP=yes +FOUDestinationPort=55555 diff --git a/test/test-network/conf/25-gateway-next-static.network b/test/test-network/conf/25-gateway-next-static.network new file mode 100644 index 00000000..dfac8f48 --- /dev/null +++ b/test/test-network/conf/25-gateway-next-static.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +Address=149.10.124.58/28 +Gateway=149.10.124.60 diff --git a/test/test-network/conf/25-gateway-static.network b/test/test-network/conf/25-gateway-static.network new file mode 100644 index 00000000..448a21f2 --- /dev/null +++ b/test/test-network/conf/25-gateway-static.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +Address=149.10.124.58/28 +Gateway=149.10.124.59 diff --git a/test/test-network/conf/25-geneve.netdev b/test/test-network/conf/25-geneve.netdev new file mode 100644 index 00000000..279d7132 --- /dev/null +++ b/test/test-network/conf/25-geneve.netdev @@ -0,0 +1,12 @@ +[NetDev] +Name=geneve99 +Kind=geneve + +[GENEVE] +Id=99 +Remote=192.168.22.1 +TTL=1 +UDPChecksum=true +UDP6ZeroChecksumTx=true +UDP6ZeroChecksumRx=true +DestinationPort=6082 diff --git a/test/test-network/conf/25-gre-tunnel-any-any.netdev b/test/test-network/conf/25-gre-tunnel-any-any.netdev new file mode 100644 index 00000000..3467b169 --- /dev/null +++ b/test/test-network/conf/25-gre-tunnel-any-any.netdev @@ -0,0 +1,9 @@ +[NetDev] +Name=gretun96 +Kind=gre + +[Tunnel] +Local=any +Remote=any +Key=106 +SerializeTunneledPackets=false diff --git a/test/test-network/conf/25-gre-tunnel-local-any.netdev b/test/test-network/conf/25-gre-tunnel-local-any.netdev new file mode 100644 index 00000000..36bc5569 --- /dev/null +++ b/test/test-network/conf/25-gre-tunnel-local-any.netdev @@ -0,0 +1,9 @@ +[NetDev] +Name=gretun98 +Kind=gre + +[Tunnel] +Local=any +Remote=10.65.223.239 +Key=104 +SerializeTunneledPackets=false diff --git a/test/test-network/conf/25-gre-tunnel-remote-any.netdev b/test/test-network/conf/25-gre-tunnel-remote-any.netdev new file mode 100644 index 00000000..74c02c9c --- /dev/null +++ b/test/test-network/conf/25-gre-tunnel-remote-any.netdev @@ -0,0 +1,9 @@ +[NetDev] +Name=gretun97 +Kind=gre + +[Tunnel] +Local=10.65.223.238 +Remote=any +Key=105 +SerializeTunneledPackets=false diff --git a/test/test-network/conf/25-gre-tunnel.netdev b/test/test-network/conf/25-gre-tunnel.netdev new file mode 100644 index 00000000..89c7fe12 --- /dev/null +++ b/test/test-network/conf/25-gre-tunnel.netdev @@ -0,0 +1,10 @@ +[NetDev] +Name=gretun99 +Kind=gre + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 +InputKey=1.2.3.103 +OutputKey=1.2.4.103 +SerializeTunneledPackets=true diff --git a/test/test-network/conf/25-gretap-tunnel-local-any.netdev b/test/test-network/conf/25-gretap-tunnel-local-any.netdev new file mode 100644 index 00000000..17abcf69 --- /dev/null +++ b/test/test-network/conf/25-gretap-tunnel-local-any.netdev @@ -0,0 +1,9 @@ +[NetDev] +Name=gretap98 +Kind=gretap + +[Tunnel] +Local=any +Remote=10.65.223.239 +Key=107 +SerializeTunneledPackets=true diff --git a/test/test-network/conf/25-gretap-tunnel.netdev b/test/test-network/conf/25-gretap-tunnel.netdev new file mode 100644 index 00000000..912daf5b --- /dev/null +++ b/test/test-network/conf/25-gretap-tunnel.netdev @@ -0,0 +1,9 @@ +[NetDev] +Name=gretap99 +Kind=gretap + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 +Key=106 +SerializeTunneledPackets=true diff --git a/test/test-network/conf/25-ip6gre-tunnel-any-any.netdev b/test/test-network/conf/25-ip6gre-tunnel-any-any.netdev new file mode 100644 index 00000000..519474fe --- /dev/null +++ b/test/test-network/conf/25-ip6gre-tunnel-any-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=ip6gretun96 +Kind=ip6gre + +[Tunnel] +Local=any +Remote=any diff --git a/test/test-network/conf/25-ip6gre-tunnel-local-any.netdev b/test/test-network/conf/25-ip6gre-tunnel-local-any.netdev new file mode 100644 index 00000000..b3781f02 --- /dev/null +++ b/test/test-network/conf/25-ip6gre-tunnel-local-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=ip6gretun98 +Kind=ip6gre + +[Tunnel] +Local=any +Remote=2001:473:fece:cafe::5179 diff --git a/test/test-network/conf/25-ip6gre-tunnel-remote-any.netdev b/test/test-network/conf/25-ip6gre-tunnel-remote-any.netdev new file mode 100644 index 00000000..828c17f2 --- /dev/null +++ b/test/test-network/conf/25-ip6gre-tunnel-remote-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=ip6gretun97 +Kind=ip6gre + +[Tunnel] +Local=2a00:ffde:4567:edde::4987 +Remote=any diff --git a/test/test-network/conf/25-ip6gre-tunnel.netdev b/test/test-network/conf/25-ip6gre-tunnel.netdev new file mode 100644 index 00000000..ba7d2bc3 --- /dev/null +++ b/test/test-network/conf/25-ip6gre-tunnel.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=ip6gretun99 +Kind=ip6gre + +[Tunnel] +Local=2a00:ffde:4567:edde::4987 +Remote=2001:473:fece:cafe::5179 diff --git a/test/test-network/conf/25-ip6gretap-tunnel-local-any.netdev b/test/test-network/conf/25-ip6gretap-tunnel-local-any.netdev new file mode 100644 index 00000000..7a962e8a --- /dev/null +++ b/test/test-network/conf/25-ip6gretap-tunnel-local-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=ip6gretap98 +Kind=ip6gretap + +[Tunnel] +Local=any +Remote=2001:473:fece:cafe::5179 diff --git a/test/test-network/conf/25-ip6gretap-tunnel.netdev b/test/test-network/conf/25-ip6gretap-tunnel.netdev new file mode 100644 index 00000000..b16e0b49 --- /dev/null +++ b/test/test-network/conf/25-ip6gretap-tunnel.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=ip6gretap99 +Kind=ip6gretap + +[Tunnel] +Local=2a00:ffde:4567:edde::4987 +Remote=2001:473:fece:cafe::5179 diff --git a/test/test-network/conf/25-ip6tnl-tunnel-local-any.netdev b/test/test-network/conf/25-ip6tnl-tunnel-local-any.netdev new file mode 100644 index 00000000..7732eb88 --- /dev/null +++ b/test/test-network/conf/25-ip6tnl-tunnel-local-any.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=ip6tnl98 +Kind=ip6tnl + +[Tunnel] +Mode=ip6ip6 +Local=any +Remote=2001:473:fece:cafe::5179 diff --git a/test/test-network/conf/25-ip6tnl-tunnel-remote-any.netdev b/test/test-network/conf/25-ip6tnl-tunnel-remote-any.netdev new file mode 100644 index 00000000..0d9d1e90 --- /dev/null +++ b/test/test-network/conf/25-ip6tnl-tunnel-remote-any.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=ip6tnl97 +Kind=ip6tnl + +[Tunnel] +Mode=ip6ip6 +Local=2a00:ffde:4567:edde::4987 +Remote=any diff --git a/test/test-network/conf/25-ip6tnl-tunnel.netdev b/test/test-network/conf/25-ip6tnl-tunnel.netdev new file mode 100644 index 00000000..713e685e --- /dev/null +++ b/test/test-network/conf/25-ip6tnl-tunnel.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=ip6tnl99 +Kind=ip6tnl + +[Tunnel] +Mode=ip6ip6 +Local=2a00:ffde:4567:edde::4987 +Remote=2001:473:fece:cafe::5179 diff --git a/test/test-network/conf/25-ipip-tunnel-any-any.netdev b/test/test-network/conf/25-ipip-tunnel-any-any.netdev new file mode 100644 index 00000000..8803dd12 --- /dev/null +++ b/test/test-network/conf/25-ipip-tunnel-any-any.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=ipiptun96 +Kind=ipip +MTUBytes=1480 + +[Tunnel] +Local=any +Remote=any diff --git a/test/test-network/conf/25-ipip-tunnel-independent-loopback.netdev b/test/test-network/conf/25-ipip-tunnel-independent-loopback.netdev new file mode 100644 index 00000000..9ee26c90 --- /dev/null +++ b/test/test-network/conf/25-ipip-tunnel-independent-loopback.netdev @@ -0,0 +1,10 @@ +[NetDev] +Name=ipiptun99 +Kind=ipip +MTUBytes=1480 + +[Tunnel] +Local=192.168.223.238 +Remote=192.169.224.239 +Independent=true +AssignToLoopback=yes diff --git a/test/test-network/conf/25-ipip-tunnel-independent.netdev b/test/test-network/conf/25-ipip-tunnel-independent.netdev new file mode 100644 index 00000000..36ff8d94 --- /dev/null +++ b/test/test-network/conf/25-ipip-tunnel-independent.netdev @@ -0,0 +1,9 @@ +[NetDev] +Name=ipiptun99 +Kind=ipip +MTUBytes=1480 + +[Tunnel] +Local=192.168.223.238 +Remote=192.169.224.239 +Independent=true diff --git a/test/test-network/conf/25-ipip-tunnel-local-any.netdev b/test/test-network/conf/25-ipip-tunnel-local-any.netdev new file mode 100644 index 00000000..8fa27e82 --- /dev/null +++ b/test/test-network/conf/25-ipip-tunnel-local-any.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=ipiptun98 +Kind=ipip +MTUBytes=1480 + +[Tunnel] +Local=any +Remote=192.169.224.239 diff --git a/test/test-network/conf/25-ipip-tunnel-remote-any.netdev b/test/test-network/conf/25-ipip-tunnel-remote-any.netdev new file mode 100644 index 00000000..58d7feb6 --- /dev/null +++ b/test/test-network/conf/25-ipip-tunnel-remote-any.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=ipiptun97 +Kind=ipip +MTUBytes=1480 + +[Tunnel] +Local=192.168.223.238 +Remote=any diff --git a/test/test-network/conf/25-ipip-tunnel.netdev b/test/test-network/conf/25-ipip-tunnel.netdev new file mode 100644 index 00000000..159ac727 --- /dev/null +++ b/test/test-network/conf/25-ipip-tunnel.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=ipiptun99 +Kind=ipip +MTUBytes=1480 + +[Tunnel] +Local=192.168.223.238 +Remote=192.169.224.239 diff --git a/test/test-network/conf/25-ipv6-address-label-section.network b/test/test-network/conf/25-ipv6-address-label-section.network new file mode 100644 index 00000000..945b7dcc --- /dev/null +++ b/test/test-network/conf/25-ipv6-address-label-section.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[IPv6AddressLabel] +Label=4444 +Prefix=2004:da8:1:0::/64 diff --git a/test/test-network/conf/25-ipvlan.netdev b/test/test-network/conf/25-ipvlan.netdev new file mode 100644 index 00000000..d0f0c9a8 --- /dev/null +++ b/test/test-network/conf/25-ipvlan.netdev @@ -0,0 +1,3 @@ +[NetDev] +Name=ipvlan99 +Kind=ipvlan diff --git a/test/test-network/conf/25-ipvtap.netdev b/test/test-network/conf/25-ipvtap.netdev new file mode 100644 index 00000000..2e40adb7 --- /dev/null +++ b/test/test-network/conf/25-ipvtap.netdev @@ -0,0 +1,3 @@ +[NetDev] +Name=ipvtap99 +Kind=ipvtap diff --git a/test/test-network/conf/25-isatap-tunnel.netdev b/test/test-network/conf/25-isatap-tunnel.netdev new file mode 100644 index 00000000..3aa882a2 --- /dev/null +++ b/test/test-network/conf/25-isatap-tunnel.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=isataptun99 +Kind=sit + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 +ISATAP=true diff --git a/test/test-network/conf/25-l2tp-dummy.network b/test/test-network/conf/25-l2tp-dummy.network new file mode 100644 index 00000000..9f2eb909 --- /dev/null +++ b/test/test-network/conf/25-l2tp-dummy.network @@ -0,0 +1,7 @@ +[Match] +Name=test1 + +[Network] +Address=192.168.30.100/24 +IPv6AcceptRA=false +L2TP=l2tp99 diff --git a/test/test-network/conf/25-l2tp-ip.netdev b/test/test-network/conf/25-l2tp-ip.netdev new file mode 100644 index 00000000..ceae25fa --- /dev/null +++ b/test/test-network/conf/25-l2tp-ip.netdev @@ -0,0 +1,20 @@ +[NetDev] +Kind=l2tp +Name=l2tp99 + +[L2TP] +TunnelId=10 +PeerTunnelId=12 +Local=static +Remote=192.168.30.101 +EncapsulationType=ip + +[L2TPSession] +SessionId=25 +PeerSessionId=26 +Name=l2tp-ses3 + +[L2TPSession] +SessionId=27 +PeerSessionId=28 +Name=l2tp-ses4 diff --git a/test/test-network/conf/25-l2tp-udp.netdev b/test/test-network/conf/25-l2tp-udp.netdev new file mode 100644 index 00000000..84589b0b --- /dev/null +++ b/test/test-network/conf/25-l2tp-udp.netdev @@ -0,0 +1,25 @@ +[NetDev] +Kind=l2tp +Name=l2tp99 + +[L2TP] +TunnelId=10 +PeerTunnelId=11 +UDPSourcePort=3000 +UDPDestinationPort=4000 +Local=static +Remote=192.168.30.101 +EncapsulationType=udp +UDPCheckSum=true +UDP6CheckSumRx=true +UDP6CheckSumTx=true + +[L2TPSession] +SessionId=15 +PeerSessionId=16 +Name=l2tp-ses1 + +[L2TPSession] +SessionId=17 +PeerSessionId=18 +Name=l2tp-ses2 diff --git a/test/test-network/conf/25-l2tp.network b/test/test-network/conf/25-l2tp.network new file mode 100644 index 00000000..062eaac2 --- /dev/null +++ b/test/test-network/conf/25-l2tp.network @@ -0,0 +1,6 @@ +[Match] +Name=l2tp-ses* + +[Network] +IPv6AcceptRA=no +LinkLocalAddressing=yes diff --git a/test/test-network/conf/25-link-local-addressing-no.network b/test/test-network/conf/25-link-local-addressing-no.network new file mode 100644 index 00000000..8320414d --- /dev/null +++ b/test/test-network/conf/25-link-local-addressing-no.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +LinkLocalAddressing=no diff --git a/test/test-network/conf/25-link-local-addressing-yes.network b/test/test-network/conf/25-link-local-addressing-yes.network new file mode 100644 index 00000000..8268da5a --- /dev/null +++ b/test/test-network/conf/25-link-local-addressing-yes.network @@ -0,0 +1,6 @@ +[Match] +Name=test1 + +[Network] +LinkLocalAddressing=yes +IPv6AcceptRA=no diff --git a/test/test-network/conf/25-link-section-unmanaged.network b/test/test-network/conf/25-link-section-unmanaged.network new file mode 100644 index 00000000..4fe49160 --- /dev/null +++ b/test/test-network/conf/25-link-section-unmanaged.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Link] +MACAddress=00:01:02:aa:bb:cc +Unmanaged=true diff --git a/test/test-network/conf/25-macsec.key b/test/test-network/conf/25-macsec.key new file mode 100644 index 00000000..56c51fa9 --- /dev/null +++ b/test/test-network/conf/25-macsec.key @@ -0,0 +1 @@ +85858585858585858585858585858585 diff --git a/test/test-network/conf/25-macsec.netdev b/test/test-network/conf/25-macsec.netdev new file mode 100644 index 00000000..9b603ca0 --- /dev/null +++ b/test/test-network/conf/25-macsec.netdev @@ -0,0 +1,68 @@ +[NetDev] +Name=macsec99 +Kind=macsec + +[MACsec] +Port=11 +Encrypt=yes + +[MACsecTransmitAssociation] +PacketNumber=1024 +KeyId=01 +Key=81818181818181818181818181818181 +Activate=yes + +[MACsecTransmitAssociation] +PacketNumber=512 +KeyId=0203 +Key=82828282828282828282828282828282 +UseForEncoding=yes + +[MACsecReceiveChannel] +Port=2 +MACAddress=8c:16:45:6c:83:a9 + +[MACsecReceiveAssociation] +Port=2 +MACAddress=8c:16:45:6c:83:a9 +PacketNumber=16 +KeyId=020304 +Key=83838383838383838383838383838383 + +[MACsecReceiveAssociation] +Port=256 +MACAddress=c6:19:52:8f:e6:a0 +PacketNumber=32 +KeyId=02030405 +Key=84848484848484848484848484848484 +Activate=yes + +[MACsecReceiveAssociation] +Port=256 +MACAddress=c6:19:52:8f:e6:a0 +PacketNumber=128 +KeyId=0203040506 +KeyFile=/run/systemd/network/25-macsec.key +Activate=yes + +[MACsecReceiveAssociation] +Port=256 +MACAddress=c6:19:52:8f:e6:a0 +KeyId=020304050607 +Key=86868686868686868686868686868686 +Activate=no + +[MACsecReceiveAssociation] +Port=256 +MACAddress=c6:19:52:8f:e6:a0 +KeyId=02030405060708 +Key=87878787878787878787878787878787 +Activate=no + +[MACsecReceiveAssociation] +# This section should be dropped. +Port=256 +MACAddress=c6:19:52:8f:e6:a0 +KeyId=0203040506070809 +Key=88888888888888888888888888888888 +Activate=no diff --git a/test/test-network/conf/25-macsec.network b/test/test-network/conf/25-macsec.network new file mode 100644 index 00000000..6def92f6 --- /dev/null +++ b/test/test-network/conf/25-macsec.network @@ -0,0 +1,7 @@ +[Match] +Name=macsec99 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 +LinkLocalAddressing=yes diff --git a/test/test-network/conf/25-neighbor-ip-dummy.network b/test/test-network/conf/25-neighbor-ip-dummy.network new file mode 100644 index 00000000..e02c55e3 --- /dev/null +++ b/test/test-network/conf/25-neighbor-ip-dummy.network @@ -0,0 +1,7 @@ +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Tunnel=gretun97 +Tunnel=ip6gretun97 diff --git a/test/test-network/conf/25-neighbor-ip.network b/test/test-network/conf/25-neighbor-ip.network new file mode 100644 index 00000000..8865ccd9 --- /dev/null +++ b/test/test-network/conf/25-neighbor-ip.network @@ -0,0 +1,10 @@ +[Match] +Name=gretun97 + +[Network] +IPv6AcceptRA=no +Address=10.0.0.21 + +[Neighbor] +Address=10.0.0.22 +LinkLayerAddress=10.65.223.239 diff --git a/test/test-network/conf/25-neighbor-ipv6.network b/test/test-network/conf/25-neighbor-ipv6.network new file mode 100644 index 00000000..322f7396 --- /dev/null +++ b/test/test-network/conf/25-neighbor-ipv6.network @@ -0,0 +1,11 @@ +[Match] +Name=ip6gretun97 + +[Network] +IPv6AcceptRA=no +Address=2001:db8:0:f102::16/64 +LinkLocalAddressing=no + +[Neighbor] +Address=2001:db8:0:f102::17 +LinkLayerAddress=2a00:ffde:4567:edde::4988 diff --git a/test/test-network/conf/25-neighbor-next.network b/test/test-network/conf/25-neighbor-next.network new file mode 100644 index 00000000..d0591d58 --- /dev/null +++ b/test/test-network/conf/25-neighbor-next.network @@ -0,0 +1,9 @@ +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no + +[Neighbor] +Address=192.168.10.1 +LinkLayerAddress=00:00:5e:00:02:66 diff --git a/test/test-network/conf/25-neighbor-section.network b/test/test-network/conf/25-neighbor-section.network new file mode 100644 index 00000000..94c04943 --- /dev/null +++ b/test/test-network/conf/25-neighbor-section.network @@ -0,0 +1,13 @@ +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no + +[Neighbor] +Address=192.168.10.1 +LinkLayerAddress=00:00:5e:00:02:65 + +[Neighbor] +Address=2004:da8:1:0::1 +LinkLayerAddress=00:00:5e:00:02:66 diff --git a/test/test-network/conf/25-netdevsim.netdev b/test/test-network/conf/25-netdevsim.netdev new file mode 100644 index 00000000..899f2d9f --- /dev/null +++ b/test/test-network/conf/25-netdevsim.netdev @@ -0,0 +1,3 @@ +[NetDev] +Kind=netdevsim +Name=netdevsim99 diff --git a/test/test-network/conf/25-nexthop.network b/test/test-network/conf/25-nexthop.network new file mode 100644 index 00000000..3eea0773 --- /dev/null +++ b/test/test-network/conf/25-nexthop.network @@ -0,0 +1,11 @@ +[Match] +Name=veth99 + +[Network] +IPv6AcceptRA=no +Address=192.168.5.10/24 +Gateway=192.168.5.1 + +[NextHop] +Id=1 +Gateway=192.168.5.1 diff --git a/test/test-network/conf/25-nlmon.netdev b/test/test-network/conf/25-nlmon.netdev new file mode 100644 index 00000000..2ae6b124 --- /dev/null +++ b/test/test-network/conf/25-nlmon.netdev @@ -0,0 +1,3 @@ +[NetDev] +Kind=nlmon +Name=nlmon99 diff --git a/test/test-network/conf/25-qdisc.network b/test/test-network/conf/25-qdisc.network new file mode 100644 index 00000000..de8f7243 --- /dev/null +++ b/test/test-network/conf/25-qdisc.network @@ -0,0 +1,20 @@ +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.1.2.3/16 + +[TrafficControlQueueingDiscipline] +Parent=root +NetworkEmulatorDelaySec=50ms +NetworkEmulatorDelayJitterSec=10ms +NetworkEmulatorLossRate=20% +NetworkEmulatorPacketLimit=100 + +[TrafficControlQueueingDiscipline] +Parent=clsact +NetworkEmulatorDelaySec=100ms +NetworkEmulatorDelayJitterSec=13ms +NetworkEmulatorLossRate=20.5% +NetworkEmulatorPacketLimit=200 diff --git a/test/test-network/conf/25-route-ipv6-src.network b/test/test-network/conf/25-route-ipv6-src.network new file mode 100644 index 00000000..4e551c02 --- /dev/null +++ b/test/test-network/conf/25-route-ipv6-src.network @@ -0,0 +1,16 @@ +# This test cannot use a dummy interface: IPv6 addresses +# are added without having to go through tentative state + +[Match] +Name=bond199 + +[Network] +LinkLocalAddressing=ipv6 +Address=2001:1234:56:8f63::1/64 +Address=2001:1234:56:8f63::2/64 +IPv6AcceptRA=no + +[Route] +Destination=abcd::/16 +Gateway=2001:1234:56:8f63::1:1 +PreferredSource=2001:1234:56:8f63::2 diff --git a/test/test-network/conf/25-route-static.network b/test/test-network/conf/25-route-static.network new file mode 100644 index 00000000..9c8269e3 --- /dev/null +++ b/test/test-network/conf/25-route-static.network @@ -0,0 +1,64 @@ +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=2001:1234:5:8f63::1/128 +Address=149.10.124.58/28 +DefaultRouteOnDevice=yes +IPv4LLRoute=yes + +[Route] +Destination=2001:1234:5:8fff:ff:ff:ff:ff/128 +Scope=link + +[Route] +Destination=::/0 +Gateway=2001:1234:5:8fff:ff:ff:ff:ff + +[Route] +Destination=149.10.124.64 +Scope=link + +[Route] +Gateway=149.10.124.64 + +[Route] +Gateway=149.10.125.65 +GatewayOnLink=yes + +[Route] +Destination=192.168.1.1 +InitialCongestionWindow=20 + +[Route] +Destination=192.168.1.2 +InitialAdvertisedReceiveWindow=30 + +[Route] +Type=blackhole +Destination=202.54.1.2 + +[Route] +Type=unreachable +Destination=202.54.1.3 + +[Route] +Type=prohibit +Destination=202.54.1.4 + +[Route] +Type=local +Destination=149.10.123.1 + +[Route] +Type=anycast +Destination=149.10.123.2 + +[Route] +Type=broadcast +Destination=149.10.123.3 + +[Route] +Type=multicast +Destination=149.10.123.4 diff --git a/test/test-network/conf/25-sit-tunnel-any-any.netdev b/test/test-network/conf/25-sit-tunnel-any-any.netdev new file mode 100644 index 00000000..e961dcbd --- /dev/null +++ b/test/test-network/conf/25-sit-tunnel-any-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=sittun96 +Kind=sit + +[Tunnel] +Local=any +Remote=any diff --git a/test/test-network/conf/25-sit-tunnel-local-any.netdev b/test/test-network/conf/25-sit-tunnel-local-any.netdev new file mode 100644 index 00000000..20c1a334 --- /dev/null +++ b/test/test-network/conf/25-sit-tunnel-local-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=sittun98 +Kind=sit + +[Tunnel] +Local=any +Remote=10.65.223.239 diff --git a/test/test-network/conf/25-sit-tunnel-remote-any.netdev b/test/test-network/conf/25-sit-tunnel-remote-any.netdev new file mode 100644 index 00000000..ed7b9b74 --- /dev/null +++ b/test/test-network/conf/25-sit-tunnel-remote-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=sittun97 +Kind=sit + +[Tunnel] +Local=10.65.223.238 +Remote=any diff --git a/test/test-network/conf/25-sit-tunnel.netdev b/test/test-network/conf/25-sit-tunnel.netdev new file mode 100644 index 00000000..406d74bc --- /dev/null +++ b/test/test-network/conf/25-sit-tunnel.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=sittun99 +Kind=sit + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 diff --git a/test/test-network/conf/25-sysctl-disable-ipv6.network b/test/test-network/conf/25-sysctl-disable-ipv6.network new file mode 100644 index 00000000..c4c5fbc1 --- /dev/null +++ b/test/test-network/conf/25-sysctl-disable-ipv6.network @@ -0,0 +1,18 @@ +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Address=10.2.3.4/16 + +# This should be ignored when ipv6 is disabled +Gateway=2607:5300:0203:39ff:ff:ff:ff:ff + +[Address] +# This should be ignored when ipv6 is disabled +Address=2607:5300:0203:3906::/64 + +[Route] +# This should be ignored when ipv6 is disabled +Destination=2607:5300:0203:39ff:ff:ff:ff:ff +Scope=link diff --git a/test/test-network/conf/25-sysctl.network b/test/test-network/conf/25-sysctl.network new file mode 100644 index 00000000..68be3054 --- /dev/null +++ b/test/test-network/conf/25-sysctl.network @@ -0,0 +1,11 @@ +[Match] +Name=dummy98 + +[Network] +IPForward=true +IPv6PrivacyExtensions=true +IPv6DuplicateAddressDetection=3 +IPv6HopLimit=5 +IPv4ProxyARP=true +IPv6ProxyNDP=true +IPv6AcceptRA=no diff --git a/test/test-network/conf/25-tap.netdev b/test/test-network/conf/25-tap.netdev new file mode 100644 index 00000000..3876075a --- /dev/null +++ b/test/test-network/conf/25-tap.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=tap99 +Kind=tap + +[Tap] +MultiQueue=true +PacketInfo=true +VNetHeader=true diff --git a/test/test-network/conf/25-tun.netdev b/test/test-network/conf/25-tun.netdev new file mode 100644 index 00000000..37459c79 --- /dev/null +++ b/test/test-network/conf/25-tun.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=tun99 +Kind=tun + +[Tun] +MultiQueue=true +PacketInfo=true +VNetHeader=true diff --git a/test/test-network/conf/25-tunnel-any-any.network b/test/test-network/conf/25-tunnel-any-any.network new file mode 100644 index 00000000..7a9e39e9 --- /dev/null +++ b/test/test-network/conf/25-tunnel-any-any.network @@ -0,0 +1,8 @@ +[Match] +Name=*tun96 + +[Network] +IPv6AcceptRA=no +Address=2001:db8:0:f102::19/64 +Address=10.3.2.6/16 +LinkLocalAddressing=yes diff --git a/test/test-network/conf/25-tunnel-local-any.network b/test/test-network/conf/25-tunnel-local-any.network new file mode 100644 index 00000000..8ce05adb --- /dev/null +++ b/test/test-network/conf/25-tunnel-local-any.network @@ -0,0 +1,8 @@ +[Match] +Name=*tun98 *tap98 ip6tnl98 erspan98 + +[Network] +IPv6AcceptRA=no +Address=2001:db8:0:f102::17/64 +Address=10.3.2.4/16 +LinkLocalAddressing=yes diff --git a/test/test-network/conf/25-tunnel-remote-any.network b/test/test-network/conf/25-tunnel-remote-any.network new file mode 100644 index 00000000..becdcaa8 --- /dev/null +++ b/test/test-network/conf/25-tunnel-remote-any.network @@ -0,0 +1,8 @@ +[Match] +Name=*tun97 ip6tnl97 + +[Network] +IPv6AcceptRA=no +Address=2001:db8:0:f102::18/64 +Address=10.3.2.5/16 +LinkLocalAddressing=yes diff --git a/test/test-network/conf/25-tunnel.network b/test/test-network/conf/25-tunnel.network new file mode 100644 index 00000000..32c19867 --- /dev/null +++ b/test/test-network/conf/25-tunnel.network @@ -0,0 +1,8 @@ +[Match] +Name=*tun99 *tap99 ip6tnl99 erspan99 + +[Network] +IPv6AcceptRA=no +Address=2001:db8:0:f102::16/64 +Address=10.3.2.3/16 +LinkLocalAddressing=yes diff --git a/test/test-network/conf/25-vcan.netdev b/test/test-network/conf/25-vcan.netdev new file mode 100644 index 00000000..ff197953 --- /dev/null +++ b/test/test-network/conf/25-vcan.netdev @@ -0,0 +1,3 @@ +[NetDev] +Name=vcan99 +Kind=vcan diff --git a/test/test-network/conf/25-veth-peer.network b/test/test-network/conf/25-veth-peer.network new file mode 100644 index 00000000..f24956fe --- /dev/null +++ b/test/test-network/conf/25-veth-peer.network @@ -0,0 +1,7 @@ +[Match] +Name=veth-peer + +[Network] +IPv6AcceptRA=no +Address=2600::1/0 +Address=192.168.5.1/24 diff --git a/test/test-network/conf/25-veth.netdev b/test/test-network/conf/25-veth.netdev new file mode 100644 index 00000000..9ae4ad53 --- /dev/null +++ b/test/test-network/conf/25-veth.netdev @@ -0,0 +1,8 @@ +[NetDev] +Name=veth99 +Kind=veth +MACAddress=12:34:56:78:9a:bc + +[Peer] +Name=veth-peer +MACAddress=12:34:56:78:9a:bd diff --git a/test/test-network/conf/25-vrf.netdev b/test/test-network/conf/25-vrf.netdev new file mode 100644 index 00000000..bf949ec2 --- /dev/null +++ b/test/test-network/conf/25-vrf.netdev @@ -0,0 +1,6 @@ +[NetDev] +Name=vrf99 +Kind=vrf + +[VRF] +TableId=42 diff --git a/test/test-network/conf/25-vrf.network b/test/test-network/conf/25-vrf.network new file mode 100644 index 00000000..42ce5b19 --- /dev/null +++ b/test/test-network/conf/25-vrf.network @@ -0,0 +1,2 @@ +[Match] +Name=vrf99 diff --git a/test/test-network/conf/25-vti-tunnel-any-any.netdev b/test/test-network/conf/25-vti-tunnel-any-any.netdev new file mode 100644 index 00000000..3cac374b --- /dev/null +++ b/test/test-network/conf/25-vti-tunnel-any-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=vtitun96 +Kind=vti + +[Tunnel] +Local=any +Remote=any diff --git a/test/test-network/conf/25-vti-tunnel-local-any.netdev b/test/test-network/conf/25-vti-tunnel-local-any.netdev new file mode 100644 index 00000000..cab38864 --- /dev/null +++ b/test/test-network/conf/25-vti-tunnel-local-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=vtitun98 +Kind=vti + +[Tunnel] +Local=remote +Remote=10.65.223.239 diff --git a/test/test-network/conf/25-vti-tunnel-remote-any.netdev b/test/test-network/conf/25-vti-tunnel-remote-any.netdev new file mode 100644 index 00000000..b8bedffa --- /dev/null +++ b/test/test-network/conf/25-vti-tunnel-remote-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=vtitun97 +Kind=vti + +[Tunnel] +Local=10.65.223.238 +Remote=any diff --git a/test/test-network/conf/25-vti-tunnel.netdev b/test/test-network/conf/25-vti-tunnel.netdev new file mode 100644 index 00000000..cec62597 --- /dev/null +++ b/test/test-network/conf/25-vti-tunnel.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=vtitun99 +Kind=vti + +[Tunnel] +Local=10.65.223.238 +Remote=10.65.223.239 diff --git a/test/test-network/conf/25-vti6-tunnel-local-any.netdev b/test/test-network/conf/25-vti6-tunnel-local-any.netdev new file mode 100644 index 00000000..c3d05b4f --- /dev/null +++ b/test/test-network/conf/25-vti6-tunnel-local-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=vti6tun98 +Kind=vti6 + +[Tunnel] +Local=any +Remote=2001:473:fece:cafe::5179 diff --git a/test/test-network/conf/25-vti6-tunnel-remote-any.netdev b/test/test-network/conf/25-vti6-tunnel-remote-any.netdev new file mode 100644 index 00000000..b86c628a --- /dev/null +++ b/test/test-network/conf/25-vti6-tunnel-remote-any.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=vti6tun97 +Kind=vti6 + +[Tunnel] +Local=2a00:ffde:4567:edde::4987 +Remote=any diff --git a/test/test-network/conf/25-vti6-tunnel.netdev b/test/test-network/conf/25-vti6-tunnel.netdev new file mode 100644 index 00000000..d150c9ce --- /dev/null +++ b/test/test-network/conf/25-vti6-tunnel.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=vti6tun99 +Kind=vti6 + +[Tunnel] +Local=2a00:ffde:4567:edde::4987 +Remote=2001:473:fece:cafe::5179 diff --git a/test/test-network/conf/25-vxcan.netdev b/test/test-network/conf/25-vxcan.netdev new file mode 100644 index 00000000..6d879b15 --- /dev/null +++ b/test/test-network/conf/25-vxcan.netdev @@ -0,0 +1,6 @@ +[NetDev] +Name=vxcan99 +Kind=vxcan + +[VXCAN] +Peer=vxcan-peer diff --git a/test/test-network/conf/25-vxlan.netdev b/test/test-network/conf/25-vxlan.netdev new file mode 100644 index 00000000..d5acf48d --- /dev/null +++ b/test/test-network/conf/25-vxlan.netdev @@ -0,0 +1,16 @@ +[NetDev] +Name=vxlan99 +Kind=vxlan + +[VXLAN] +VNI=999 +L2MissNotification=true +L3MissNotification=true +RouteShortCircuit=true +UDPChecksum=true +UDP6ZeroChecksumTx=true +UDP6ZeroChecksumRx=true +RemoteChecksumTx=true +RemoteChecksumRx=true +GroupPolicyExtension=true +DestinationPort=5555 diff --git a/test/test-network/conf/25-wireguard-23-peers.netdev b/test/test-network/conf/25-wireguard-23-peers.netdev new file mode 100644 index 00000000..61a75e59 --- /dev/null +++ b/test/test-network/conf/25-wireguard-23-peers.netdev @@ -0,0 +1,150 @@ +[NetDev] +Name=wg98 +Kind=wireguard +Description=For issue #11404 +# Generated by the script https://launchpadlibrarian.net/405947185/systemd-wg + +[WireGuard] +# 51820 is common port for Wireguard, 4500 is IPSec/UDP +ListenPort=4500 +# The key below should be overridden by PrivateKeyFile= +PrivateKey=EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong= +PrivateKeyFile=/run/systemd/network/25-wireguard-private-key.txt + +# peer 1 +[WireGuardPeer] +PublicKey=TxVmU/YJ2R3G3cbGKUiIx02y6CgcKlElVGAkzrwJuXg= +AllowedIPs=fd8d:4d6d:3ccb:0500:0c79:2339:edce:ece1/128 +AllowedIPs=fd8d:4d6d:3ccb:0c79:2339:edce::/96 + +# peer 2 +[WireGuardPeer] +PublicKey=coGr5lLn1RsCeh1RWBXn1GvcDqKSQ82HSeN0GrUugHg= +AllowedIPs=fd8d:4d6d:3ccb:0500:a072:80da:de4f:add1/128 +AllowedIPs=fd8d:4d6d:3ccb:a072:80da:de4f::/96 + +# peer 3 +[WireGuardPeer] +PublicKey=PeiULTZjyfjqg/OOqnzKtLSWnrU+ipinqMsMw0hY+1w= +AllowedIPs=fd8d:4d6d:3ccb:0500:f349:c4f0:10c1:06b4/128 +AllowedIPs=fd8d:4d6d:3ccb:f349:c4f0:10c1::/96 + +# peer 4 +[WireGuardPeer] +PublicKey=PjdC8+BmQPdgheY7gle9s3gvM7r07L6A+gMBe5bOZXk= +AllowedIPs=fd8d:4d6d:3ccb:0500:b684:4f81:2e3e:132e/128 +AllowedIPs=fd8d:4d6d:3ccb:b684:4f81:2e3e::/96 + +# peer 5 +[WireGuardPeer] +PublicKey=1MGQurlRaQIAgdH/sd0qDNamDKAepMy/+pzZUx9oEDI= +AllowedIPs=fd8d:4d6d:3ccb:0500:c624:6bf7:4c09:3b59/128 +AllowedIPs=fd8d:4d6d:3ccb:c624:6bf7:4c09::/96 + +# peer 6 +[WireGuardPeer] +PublicKey=+FgzhoGfPIzNBvtIZfBwNtWls2FSGt/6Kve3M9Z1ZlE= +AllowedIPs=fd8d:4d6d:3ccb:0500:9c11:d820:2e96:9be0/128 +AllowedIPs=fd8d:4d6d:3ccb:9c11:d820:2e96::/96 + +# peer 7 +[WireGuardPeer] +PublicKey=Kb2ozFhzg9huKmV4miLlWgh05ToP+xVqd2N0e7Ebmyc= +AllowedIPs=fd8d:4d6d:3ccb:0500:bad5:495d:8e9c:3427/128 +AllowedIPs=fd8d:4d6d:3ccb:bad5:495d:8e9c::/96 + +# peer 8 +[WireGuardPeer] +PublicKey=p2kY786d4vFO/PpstaQrn7UPuakoHRABUHmcDKzXVi4= +AllowedIPs=fd8d:4d6d:3ccb:0500:1e54:1415:35d0:a47c/128 +AllowedIPs=fd8d:4d6d:3ccb:1e54:1415:35d0::/96 + +# peer 9 +[WireGuardPeer] +PublicKey=FNiQqmeizNXTmd9jEU/gvNkuEs1MoWovNp8IpPkoqz4= +AllowedIPs=fd8d:4d6d:3ccb:0500:1dbf:ca8a:32d3:dd81/128 +AllowedIPs=fd8d:4d6d:3ccb:1dbf:ca8a:32d3::/96 + +# peer 10 +[WireGuardPeer] +PublicKey=wAwyAuLSQTO7lwQnUQHTumrMgkwigIExGR26AthWTU8= +AllowedIPs=fd8d:4d6d:3ccb:0500:dcdd:d33b:90c9:6088/128 +AllowedIPs=fd8d:4d6d:3ccb:dcdd:d33b:90c9::/96 + +# peer 11 +[WireGuardPeer] +PublicKey=8gRYdXRyhgjiMSbqk3sj5kzXGsQqkZ4defvK2ONqHA0= +AllowedIPs=fd8d:4d6d:3ccb:0500:6f2e:6888:c6fd:dfb9/128 +AllowedIPs=fd8d:4d6d:3ccb:6f2e:6888:c6fd::/96 + +# peer 12 +[WireGuardPeer] +PublicKey=4Bj9Dalwnq2Trf5Bl7iJCpSOaxC83YEbxgrgBl0ljQk= +AllowedIPs=fd8d:4d6d:3ccb:0500:d4f9:05dc:9296:0a1a/128 +AllowedIPs=fd8d:4d6d:3ccb:d4f9:05dc:9296::/96 + +# peer 13 +[WireGuardPeer] +PublicKey=BOTxUDlPSIzYucVmML4IYcTIaX0TiqC7DOnfLUI7RRg= +AllowedIPs=fd8d:4d6d:3ccb:0500:b39c:9cdc:755a:ead3/128 +AllowedIPs=fd8d:4d6d:3ccb:b39c:9cdc:755a::/96 + +# peer 14 +[WireGuardPeer] +PublicKey=PiqEvBzow5vElGD2uOtRtZG6G60tM82kmjbyJP02mFQ= +AllowedIPs=fd8d:4d6d:3ccb:0500:bfe5:c3c3:5d77:0fcb/128 +AllowedIPs=fd8d:4d6d:3ccb:bfe5:c3c3:5d77::/96 + +# peer 15 +[WireGuardPeer] +PublicKey=Eor9QBsIoUG6C3ZKsKdqm4Vkt0n2N7qpSh2LzphQeho= +AllowedIPs=fd8d:4d6d:3ccb:0500:900c:d437:ec27:8822/128 +AllowedIPs=fd8d:4d6d:3ccb:900c:d437:ec27::/96 + +# peer 16 +[WireGuardPeer] +PublicKey=acXPW0Ar+TiTOqKuUDpop9AVLuPNdzqf0l+V8k5t7CM= +AllowedIPs=fd8d:4d6d:3ccb:0500:270d:b5dd:4a3f:8909/128 +AllowedIPs=fd8d:4d6d:3ccb:270d:b5dd:4a3f::/96 + +# peer 17 +[WireGuardPeer] +PublicKey=+0g/5jzbitHyfhB4gbJnWrhSMsSjCcOE2rftWTDEW3E= +AllowedIPs=fd8d:4d6d:3ccb:0500:e2e1:ae15:103f:f376/128 +AllowedIPs=fd8d:4d6d:3ccb:e2e1:ae15:103f::/96 + +# peer 18 +[WireGuardPeer] +PublicKey=FC7mjuWpkM8bjM3vaLPbba2HwHGbTSDK9QsLEZvUZ2I= +AllowedIPs=fd8d:4d6d:3ccb:0500:5660:679d:3532:94d8/128 +AllowedIPs=fd8d:4d6d:3ccb:5660:679d:3532::/96 + +# peer 19 +[WireGuardPeer] +PublicKey=fRdm/tbE2jGuLd6zMxSQYMP6pPfMmXYW84TUPJCPjHM= +AllowedIPs=fd8d:4d6d:3ccb:0500:6825:573f:30f3:9472/128 +AllowedIPs=fd8d:4d6d:3ccb:6825:573f:30f3::/96 + +# peer 20 +[WireGuardPeer] +PublicKey=xm540z0UwfTF5f0YwfjmCX0eGdHY8bOb/4ovVA2SgCI= +AllowedIPs=fd8d:4d6d:3ccb:0500:a94b:cd6a:a32d:90e6/128 +AllowedIPs=fd8d:4d6d:3ccb:a94b:cd6a:a32d::/96 + +# peer 21 +[WireGuardPeer] +PublicKey=5X5+9IiRBjaadazEKNO+CozpomiKPMIBQT7uJ4SnbVs= +AllowedIPs=fd8d:4d6d:3ccb:0500:8d4d:0bab:7280:a09a/128 +AllowedIPs=fd8d:4d6d:3ccb:8d4d:0bab:7280::/96 + +# peer 22 +[WireGuardPeer] +PublicKey=d61T4K0wmS4Z3lK9M8/Z48IXzldLCOCm7a6Mx1r/A3I= +AllowedIPs=fd8d:4d6d:3ccb:0500:a3f3:df38:19b0:0721/128 +AllowedIPs=fd8d:4d6d:3ccb:a3f3:df38:19b0::/96 + +# peer 23 +[WireGuardPeer] +PublicKey=Nt7N3hXfpMWsIsx9me4ID77okka+0Oe5eqnFDp00IFI= +AllowedIPs=fd8d:4d6d:3ccb:0500:9742:9931:5217:18d5/128 +AllowedIPs=fd8d:4d6d:3ccb:9742:9931:5217::/96 diff --git a/test/test-network/conf/25-wireguard-23-peers.network b/test/test-network/conf/25-wireguard-23-peers.network new file mode 100644 index 00000000..4dc87f8d --- /dev/null +++ b/test/test-network/conf/25-wireguard-23-peers.network @@ -0,0 +1,97 @@ +[Match] +Name=wg98 + +[Network] +Address=fd8d:4d6d:3ccb:0500::1/64 + +# nat64 via 1 +[Route] +Destination = fd8d:4d6d:3ccb:0c79:2339:edce::/96 + +# nat64 via 2 +[Route] +Destination = fd8d:4d6d:3ccb:a072:80da:de4f::/96 + +# nat64 via 3 +[Route] +Destination = fd8d:4d6d:3ccb:f349:c4f0:10c1::/96 + +# nat64 via 4 +[Route] +Destination = fd8d:4d6d:3ccb:b684:4f81:2e3e::/96 + +# nat64 via 5 +[Route] +Destination = fd8d:4d6d:3ccb:c624:6bf7:4c09::/96 + +# nat64 via 6 +[Route] +Destination = fd8d:4d6d:3ccb:9c11:d820:2e96::/96 + +# nat64 via 7 +[Route] +Destination = fd8d:4d6d:3ccb:bad5:495d:8e9c::/96 + +# nat64 via 8 +[Route] +Destination = fd8d:4d6d:3ccb:1e54:1415:35d0::/96 + +# nat64 via 9 +[Route] +Destination = fd8d:4d6d:3ccb:1dbf:ca8a:32d3::/96 + +# nat64 via 10 +[Route] +Destination = fd8d:4d6d:3ccb:dcdd:d33b:90c9::/96 + +# nat64 via 11 +[Route] +Destination = fd8d:4d6d:3ccb:6f2e:6888:c6fd::/96 + +# nat64 via 12 +[Route] +Destination = fd8d:4d6d:3ccb:d4f9:05dc:9296::/96 + +# nat64 via 13 +[Route] +Destination = fd8d:4d6d:3ccb:b39c:9cdc:755a::/96 + +# nat64 via 14 +[Route] +Destination = fd8d:4d6d:3ccb:bfe5:c3c3:5d77::/96 + +# nat64 via 15 +[Route] +Destination = fd8d:4d6d:3ccb:900c:d437:ec27::/96 + +# nat64 via 16 +[Route] +Destination = fd8d:4d6d:3ccb:270d:b5dd:4a3f::/96 + +# nat64 via 17 +[Route] +Destination = fd8d:4d6d:3ccb:e2e1:ae15:103f::/96 + +# nat64 via 18 +[Route] +Destination = fd8d:4d6d:3ccb:5660:679d:3532::/96 + +# nat64 via 19 +[Route] +Destination = fd8d:4d6d:3ccb:6825:573f:30f3::/96 + +# nat64 via 20 +[Route] +Destination = fd8d:4d6d:3ccb:a94b:cd6a:a32d::/96 + +# nat64 via 21 +[Route] +Destination = fd8d:4d6d:3ccb:8d4d:0bab:7280::/96 + +# nat64 via 22 +[Route] +Destination = fd8d:4d6d:3ccb:a3f3:df38:19b0::/96 + +# nat64 via 23 +[Route] +Destination = fd8d:4d6d:3ccb:9742:9931:5217::/96 diff --git a/test/test-network/conf/25-wireguard-preshared-key.txt b/test/test-network/conf/25-wireguard-preshared-key.txt new file mode 100644 index 00000000..021c443a --- /dev/null +++ b/test/test-network/conf/25-wireguard-preshared-key.txt @@ -0,0 +1,3 @@ +cPLOy1YUrEI0EM + MIycPJmOo0aTu3RZnw8bL5 + meVD6m0= diff --git a/test/test-network/conf/25-wireguard-private-key.txt b/test/test-network/conf/25-wireguard-private-key.txt new file mode 100644 index 00000000..469acd09 --- /dev/null +++ b/test/test-network/conf/25-wireguard-private-key.txt @@ -0,0 +1,6 @@ +CJQUtcS9emY2fLY + qDlpSZiE/QJyHkP + Wr+WHtZ + + +LZ90FU= diff --git a/test/test-network/conf/25-wireguard.netdev b/test/test-network/conf/25-wireguard.netdev new file mode 100644 index 00000000..4866c31c --- /dev/null +++ b/test/test-network/conf/25-wireguard.netdev @@ -0,0 +1,16 @@ +[NetDev] +Name=wg99 +Kind=wireguard + +[WireGuard] +PrivateKey=EEGlnEPYJV//kbvvIqxKkQwOiS+UENyPncC4bF46ong= +ListenPort=51820 +FwMark=1234 + +[WireGuardPeer] +PublicKey=RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA= +AllowedIPs=fd31:bf08:57cb::/48,192.168.26.0/24 +#Endpoint=wireguard.example.com:51820 +Endpoint=192.168.27.3:51820 +PresharedKey=IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M= +PersistentKeepalive=20 diff --git a/test/test-network/conf/25-wireguard.netdev.d/peer.conf b/test/test-network/conf/25-wireguard.netdev.d/peer.conf new file mode 100644 index 00000000..f559ea68 --- /dev/null +++ b/test/test-network/conf/25-wireguard.netdev.d/peer.conf @@ -0,0 +1,5 @@ +[WireGuardPeer] +PublicKey=lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= +AllowedIPs=fdbc:bae2:7871:0500:e1fe:0793:8636:dad1/128 +AllowedIPs=fdbc:bae2:7871:e1fe:0793:8636::/96 +PresharedKeyFile=/run/systemd/network/25-wireguard-preshared-key.txt diff --git a/test/test-network/conf/25-wireguard.network b/test/test-network/conf/25-wireguard.network new file mode 100644 index 00000000..ab305239 --- /dev/null +++ b/test/test-network/conf/25-wireguard.network @@ -0,0 +1,2 @@ +[Match] +Name=wg99 diff --git a/test/test-network/conf/25-xfrm-independent.netdev b/test/test-network/conf/25-xfrm-independent.netdev new file mode 100644 index 00000000..8ed43214 --- /dev/null +++ b/test/test-network/conf/25-xfrm-independent.netdev @@ -0,0 +1,6 @@ +[NetDev] +Kind=xfrm +Name=xfrm99 + +[Xfrm] +Independent=yes diff --git a/test/test-network/conf/25-xfrm.netdev b/test/test-network/conf/25-xfrm.netdev new file mode 100644 index 00000000..81b32dea --- /dev/null +++ b/test/test-network/conf/25-xfrm.netdev @@ -0,0 +1,3 @@ +[NetDev] +Kind=xfrm +Name=xfrm99 diff --git a/test/test-network/conf/26-bridge-slave-interface-1.network b/test/test-network/conf/26-bridge-slave-interface-1.network new file mode 100644 index 00000000..6aed1785 --- /dev/null +++ b/test/test-network/conf/26-bridge-slave-interface-1.network @@ -0,0 +1,18 @@ +[Match] +Name=dummy98 + +[Network] +Bridge=bridge99 + +[Bridge] +Cost=400 +HairPin = true +FastLeave = true +UnicastFlood = true +MulticastFlood = false +MulticastToUnicast = true +NeighborSuppression = true +Learning = false +Priority = 23 +UseBPDU = true +AllowPortToBeRoot=true diff --git a/test/test-network/conf/26-bridge-slave-interface-2.network b/test/test-network/conf/26-bridge-slave-interface-2.network new file mode 100644 index 00000000..5fccfec5 --- /dev/null +++ b/test/test-network/conf/26-bridge-slave-interface-2.network @@ -0,0 +1,8 @@ +[Match] +Name=test1 + +[Network] +Bridge=bridge99 + +[Bridge] +Priority=0 diff --git a/test/test-network/conf/26-bridge-vlan-master.network b/test/test-network/conf/26-bridge-vlan-master.network new file mode 100644 index 00000000..8493e325 --- /dev/null +++ b/test/test-network/conf/26-bridge-vlan-master.network @@ -0,0 +1,8 @@ +[Match] +Name=bridge99 + +[Network] +IPv6AcceptRA=false + +[BridgeVLAN] +VLAN=4060-4094 diff --git a/test/test-network/conf/26-bridge-vlan-slave.network b/test/test-network/conf/26-bridge-vlan-slave.network new file mode 100644 index 00000000..ba50508a --- /dev/null +++ b/test/test-network/conf/26-bridge-vlan-slave.network @@ -0,0 +1,9 @@ +[Match] +Name=test1 + +[Network] +IPv6AcceptRA=no +Bridge=bridge99 + +[BridgeVLAN] +VLAN=4064-4094 diff --git a/test/test-network/conf/26-bridge.netdev b/test/test-network/conf/26-bridge.netdev new file mode 100644 index 00000000..9b31e06b --- /dev/null +++ b/test/test-network/conf/26-bridge.netdev @@ -0,0 +1,3 @@ +[NetDev] +Name=bridge99 +Kind=bridge diff --git a/test/test-network/conf/26-link-local-addressing-ipv6.network b/test/test-network/conf/26-link-local-addressing-ipv6.network new file mode 100644 index 00000000..b4b5362a --- /dev/null +++ b/test/test-network/conf/26-link-local-addressing-ipv6.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +LinkLocalAddressing=ipv6 +IPv6AcceptRA=no diff --git a/test/test-network/conf/6rd.network b/test/test-network/conf/6rd.network new file mode 100644 index 00000000..84e5af0f --- /dev/null +++ b/test/test-network/conf/6rd.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=sittun99 diff --git a/test/test-network/conf/bond-slave.network b/test/test-network/conf/bond-slave.network new file mode 100644 index 00000000..4eeeae20 --- /dev/null +++ b/test/test-network/conf/bond-slave.network @@ -0,0 +1,12 @@ +[Match] +Name=dummy98 test1 + +[Network] +Bond=bond99 + +# Settings below should be ignored +IPv6AcceptRA=yes +LinkLocalAddressing=yes +DHCP=yes +Address=192.168.25.3/24 +Gateway=192.168.25.1 diff --git a/test/test-network/conf/bond99.network b/test/test-network/conf/bond99.network new file mode 100644 index 00000000..c5b417ab --- /dev/null +++ b/test/test-network/conf/bond99.network @@ -0,0 +1,6 @@ +[Match] +Name=bond99 + +[Network] +IPv6AcceptRA=no +Address=192.168.123.45/24 diff --git a/test/test-network/conf/bridge99-ignore-carrier-loss.network b/test/test-network/conf/bridge99-ignore-carrier-loss.network new file mode 100644 index 00000000..9797e2ed --- /dev/null +++ b/test/test-network/conf/bridge99-ignore-carrier-loss.network @@ -0,0 +1,13 @@ +[Match] +Name=bridge99 + +[Network] +Address=192.168.0.15/24 +Gateway=192.168.0.1 +IPv6AcceptRA=no +IgnoreCarrierLoss=true +ConfigureWithoutCarrier=true + +[RoutingPolicyRule] +To=8.8.8.8 +Table=100 diff --git a/test/test-network/conf/bridge99.network b/test/test-network/conf/bridge99.network new file mode 100644 index 00000000..1a00ec10 --- /dev/null +++ b/test/test-network/conf/bridge99.network @@ -0,0 +1,7 @@ +[Match] +Name=bridge99 + +[Network] +Address=192.168.0.15/24 +Gateway=192.168.0.1 +IPv6AcceptRA=no diff --git a/test/test-network/conf/configure-without-carrier.network b/test/test-network/conf/configure-without-carrier.network new file mode 100644 index 00000000..5bd9d7e8 --- /dev/null +++ b/test/test-network/conf/configure-without-carrier.network @@ -0,0 +1,7 @@ +[Match] +Name=test1 + +[Network] +Address=192.168.0.15/24 +Gateway=192.168.0.1 +ConfigureWithoutCarrier=true diff --git a/test/test-network/conf/dhcp-client-anonymize.network b/test/test-network/conf/dhcp-client-anonymize.network new file mode 100644 index 00000000..b92bdc90 --- /dev/null +++ b/test/test-network/conf/dhcp-client-anonymize.network @@ -0,0 +1,16 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCPv4] +Anonymize=true +UseMTU=true +UseRoutes=true +SendHostname=true +UseHostname=true +Hostname=test-hostname +ClientIdentifier=mac +VendorClassIdentifier=SusantVendorTest diff --git a/test/test-network/conf/dhcp-client-gateway-onlink-implicit.network b/test/test-network/conf/dhcp-client-gateway-onlink-implicit.network new file mode 100644 index 00000000..63e6e3a0 --- /dev/null +++ b/test/test-network/conf/dhcp-client-gateway-onlink-implicit.network @@ -0,0 +1,14 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +[Route] +Gateway=192.168.0.1 +Destination=10.0.0.0/8 + +[Route] +Gateway=192.168.0.1 +Destination=192.168.100.0/24 diff --git a/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network b/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network new file mode 100644 index 00000000..41d6ea40 --- /dev/null +++ b/test/test-network/conf/dhcp-client-ipv4-dhcp-settings.network @@ -0,0 +1,16 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCPv4] +UseMTU=true +UseRoutes=true +SendHostname=true +UseHostname=true +Hostname=test-hostname +ClientIdentifier=mac +VendorClassIdentifier=SusantVendorTest +RouteTable=211 diff --git a/test/test-network/conf/dhcp-client-ipv4-only-ipv6-disabled.network b/test/test-network/conf/dhcp-client-ipv4-only-ipv6-disabled.network new file mode 100644 index 00000000..384678cc --- /dev/null +++ b/test/test-network/conf/dhcp-client-ipv4-only-ipv6-disabled.network @@ -0,0 +1,10 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCPv4] +RoutesToDNS=yes +SendOption=12:string:test diff --git a/test/test-network/conf/dhcp-client-ipv4-only.network b/test/test-network/conf/dhcp-client-ipv4-only.network new file mode 100644 index 00000000..9bc019a6 --- /dev/null +++ b/test/test-network/conf/dhcp-client-ipv4-only.network @@ -0,0 +1,5 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 diff --git a/test/test-network/conf/dhcp-client-ipv6-only.network b/test/test-network/conf/dhcp-client-ipv6-only.network new file mode 100644 index 00000000..8b2e934f --- /dev/null +++ b/test/test-network/conf/dhcp-client-ipv6-only.network @@ -0,0 +1,6 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv6 +IPv6Token=::1a:2b:3c:4d diff --git a/test/test-network/conf/dhcp-client-ipv6-rapid-commit.network b/test/test-network/conf/dhcp-client-ipv6-rapid-commit.network new file mode 100644 index 00000000..72dfbf13 --- /dev/null +++ b/test/test-network/conf/dhcp-client-ipv6-rapid-commit.network @@ -0,0 +1,8 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv6 + +[DHCPv6] +RapidCommit=false diff --git a/test/test-network/conf/dhcp-client-keep-configuration-dhcp-on-stop.network b/test/test-network/conf/dhcp-client-keep-configuration-dhcp-on-stop.network new file mode 100644 index 00000000..e17c9854 --- /dev/null +++ b/test/test-network/conf/dhcp-client-keep-configuration-dhcp-on-stop.network @@ -0,0 +1,7 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false +KeepConfiguration=dhcp-on-stop diff --git a/test/test-network/conf/dhcp-client-keep-configuration-dhcp.network b/test/test-network/conf/dhcp-client-keep-configuration-dhcp.network new file mode 100644 index 00000000..c43f78d1 --- /dev/null +++ b/test/test-network/conf/dhcp-client-keep-configuration-dhcp.network @@ -0,0 +1,7 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false +KeepConfiguration=dhcp diff --git a/test/test-network/conf/dhcp-client-listen-port.network b/test/test-network/conf/dhcp-client-listen-port.network new file mode 100644 index 00000000..b7d779dc --- /dev/null +++ b/test/test-network/conf/dhcp-client-listen-port.network @@ -0,0 +1,9 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +[DHCPv4] +ListenPort=5555 diff --git a/test/test-network/conf/dhcp-client-reassign-static-routes-ipv4.network b/test/test-network/conf/dhcp-client-reassign-static-routes-ipv4.network new file mode 100644 index 00000000..829b4804 --- /dev/null +++ b/test/test-network/conf/dhcp-client-reassign-static-routes-ipv4.network @@ -0,0 +1,18 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +[Route] +Destination=192.168.5.0/24 + +[Route] +Destination=192.168.6.0/24 + +[Route] +Destination=192.168.7.0/24 + +[DHCPv4] +UseRoutes=no diff --git a/test/test-network/conf/dhcp-client-reassign-static-routes-ipv6.network b/test/test-network/conf/dhcp-client-reassign-static-routes-ipv6.network new file mode 100644 index 00000000..c662e997 --- /dev/null +++ b/test/test-network/conf/dhcp-client-reassign-static-routes-ipv6.network @@ -0,0 +1,8 @@ +[Match] +Name=veth99 + +[Network] +IPv6AcceptRA=yes + +[Route] +Destination=2600:0:0:1::/64 diff --git a/test/test-network/conf/dhcp-client-route-metric.network b/test/test-network/conf/dhcp-client-route-metric.network new file mode 100644 index 00000000..39496d9a --- /dev/null +++ b/test/test-network/conf/dhcp-client-route-metric.network @@ -0,0 +1,10 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCPv4] +UseRoutes=true +RouteMetric=24 diff --git a/test/test-network/conf/dhcp-client-route-table.network b/test/test-network/conf/dhcp-client-route-table.network new file mode 100644 index 00000000..d3a442e4 --- /dev/null +++ b/test/test-network/conf/dhcp-client-route-table.network @@ -0,0 +1,10 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=false + +[DHCPv4] +UseRoutes=true +RouteTable=12 diff --git a/test/test-network/conf/dhcp-client-timezone-router.network b/test/test-network/conf/dhcp-client-timezone-router.network new file mode 100644 index 00000000..9662c00a --- /dev/null +++ b/test/test-network/conf/dhcp-client-timezone-router.network @@ -0,0 +1,10 @@ +[Match] +Name=veth99 + +[Network] +IPv6AcceptRA=false +DHCP=ipv4 + +[DHCPv4] +UseRoutes=true +UseTimezone=true diff --git a/test/test-network/conf/dhcp-client-use-dns-ipv4-and-ra.network b/test/test-network/conf/dhcp-client-use-dns-ipv4-and-ra.network new file mode 100644 index 00000000..dfb9f752 --- /dev/null +++ b/test/test-network/conf/dhcp-client-use-dns-ipv4-and-ra.network @@ -0,0 +1,11 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 + +[DHCPv4] +UseDNS=yes + +[IPv6AcceptRA] +UseDNS=yes diff --git a/test/test-network/conf/dhcp-client-use-dns-ipv4.network b/test/test-network/conf/dhcp-client-use-dns-ipv4.network new file mode 100644 index 00000000..dbd0f7f3 --- /dev/null +++ b/test/test-network/conf/dhcp-client-use-dns-ipv4.network @@ -0,0 +1,14 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 + +[DHCPv4] +UseDNS=yes + +[DHCPv6] +UseDNS=no + +[IPv6AcceptRA] +UseDNS=no diff --git a/test/test-network/conf/dhcp-client-use-dns-no.network b/test/test-network/conf/dhcp-client-use-dns-no.network new file mode 100644 index 00000000..b928759c --- /dev/null +++ b/test/test-network/conf/dhcp-client-use-dns-no.network @@ -0,0 +1,14 @@ +[Match] +Name=veth99 + +[Network] +DHCP=yes + +[DHCPv4] +UseDNS=no + +[DHCPv6] +UseDNS=no + +[IPv6AcceptRA] +UseDNS=no diff --git a/test/test-network/conf/dhcp-client-use-dns-yes.network b/test/test-network/conf/dhcp-client-use-dns-yes.network new file mode 100644 index 00000000..4655b69f --- /dev/null +++ b/test/test-network/conf/dhcp-client-use-dns-yes.network @@ -0,0 +1,14 @@ +[Match] +Name=veth99 + +[Network] +DHCP=yes + +[DHCPv4] +UseDNS=yes + +[DHCPv6] +UseDNS=yes + +[IPv6AcceptRA] +UseDNS=no diff --git a/test/test-network/conf/dhcp-client-use-domains.network b/test/test-network/conf/dhcp-client-use-domains.network new file mode 100644 index 00000000..0d0e2dd7 --- /dev/null +++ b/test/test-network/conf/dhcp-client-use-domains.network @@ -0,0 +1,9 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no + +[DHCPv4] +UseDomains=yes diff --git a/test/test-network/conf/dhcp-client-vrf.network b/test/test-network/conf/dhcp-client-vrf.network new file mode 100644 index 00000000..bb1d2e09 --- /dev/null +++ b/test/test-network/conf/dhcp-client-vrf.network @@ -0,0 +1,8 @@ +[Match] +Name=veth99 + +[Network] +DHCP=yes +IPv6AcceptRA=yes +LinkLocalAddressing=yes +VRF=vrf99 diff --git a/test/test-network/conf/dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network b/test/test-network/conf/dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network new file mode 100644 index 00000000..9ebdbb4f --- /dev/null +++ b/test/test-network/conf/dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network @@ -0,0 +1,7 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +LinkLocalAddressing=fallback +IPv6AcceptRA=no diff --git a/test/test-network/conf/dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network b/test/test-network/conf/dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network new file mode 100644 index 00000000..5489c62a --- /dev/null +++ b/test/test-network/conf/dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network @@ -0,0 +1,10 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +LinkLocalAddressing=fallback +IPv6AcceptRA=no + +[DHCPv4] +MaxAttempts=1 diff --git a/test/test-network/conf/dhcp-client-with-static-address.network b/test/test-network/conf/dhcp-client-with-static-address.network new file mode 100644 index 00000000..b4e11bea --- /dev/null +++ b/test/test-network/conf/dhcp-client-with-static-address.network @@ -0,0 +1,7 @@ +[Match] +Name=veth99 + +[Network] +DHCP=ipv4 +IPv6AcceptRA=no +Address=192.168.5.250 diff --git a/test/test-network/conf/dhcp-client.network b/test/test-network/conf/dhcp-client.network new file mode 100644 index 00000000..5629bc48 --- /dev/null +++ b/test/test-network/conf/dhcp-client.network @@ -0,0 +1,5 @@ +[Match] +Name=veth99 + +[Network] +DHCP=yes diff --git a/test/test-network/conf/dhcp-server-timezone-router.network b/test/test-network/conf/dhcp-server-timezone-router.network new file mode 100644 index 00000000..3ebbf05d --- /dev/null +++ b/test/test-network/conf/dhcp-server-timezone-router.network @@ -0,0 +1,13 @@ +[Match] +Name=veth-peer + +[Network] +IPv6AcceptRA=false +Address=192.168.5.1/24 +DHCPServer=yes + +[DHCPServer] +PoolOffset=10 +PoolSize=50 +EmitRouter=yes +Timezone=Europe/Berlin diff --git a/test/test-network/conf/dhcp-server-veth-peer.network b/test/test-network/conf/dhcp-server-veth-peer.network new file mode 100644 index 00000000..f24956fe --- /dev/null +++ b/test/test-network/conf/dhcp-server-veth-peer.network @@ -0,0 +1,7 @@ +[Match] +Name=veth-peer + +[Network] +IPv6AcceptRA=no +Address=2600::1/0 +Address=192.168.5.1/24 diff --git a/test/test-network/conf/dhcp-server.network b/test/test-network/conf/dhcp-server.network new file mode 100644 index 00000000..439258a5 --- /dev/null +++ b/test/test-network/conf/dhcp-server.network @@ -0,0 +1,13 @@ +[Match] +Name=veth-peer + +[Network] +Address=192.168.5.1/24 +IPv6AcceptRA=false +DHCPServer=yes + +[DHCPServer] +PoolOffset=10 +PoolSize=50 +DNS=192.168.5.1 +NTP=192.168.5.1 diff --git a/test/test-network/conf/dhcp-v4-server-veth-peer.network b/test/test-network/conf/dhcp-v4-server-veth-peer.network new file mode 100644 index 00000000..4d4a815a --- /dev/null +++ b/test/test-network/conf/dhcp-v4-server-veth-peer.network @@ -0,0 +1,7 @@ +[Match] +Name=veth-peer + +[Network] +IPv6AcceptRA=no +Address=192.168.0.1/24 +Address=192.168.5.1/24 diff --git a/test/test-network/conf/erspan.network b/test/test-network/conf/erspan.network new file mode 100644 index 00000000..49364c50 --- /dev/null +++ b/test/test-network/conf/erspan.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=erspan99 +Tunnel=erspan98 diff --git a/test/test-network/conf/gretap.network b/test/test-network/conf/gretap.network new file mode 100644 index 00000000..1493fcf2 --- /dev/null +++ b/test/test-network/conf/gretap.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=gretap99 +Tunnel=gretap98 diff --git a/test/test-network/conf/gretun.network b/test/test-network/conf/gretun.network new file mode 100644 index 00000000..5510b1c9 --- /dev/null +++ b/test/test-network/conf/gretun.network @@ -0,0 +1,8 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=gretun99 +Tunnel=gretun98 +Tunnel=gretun97 +Tunnel=gretun96 diff --git a/test/test-network/conf/ip6gretap.network b/test/test-network/conf/ip6gretap.network new file mode 100644 index 00000000..7ae4e3ae --- /dev/null +++ b/test/test-network/conf/ip6gretap.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=ip6gretap99 +Tunnel=ip6gretap98 diff --git a/test/test-network/conf/ip6gretun.network b/test/test-network/conf/ip6gretun.network new file mode 100644 index 00000000..8fbee988 --- /dev/null +++ b/test/test-network/conf/ip6gretun.network @@ -0,0 +1,8 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=ip6gretun99 +Tunnel=ip6gretun98 +Tunnel=ip6gretun97 +Tunnel=ip6gretun96 diff --git a/test/test-network/conf/ip6tnl.network b/test/test-network/conf/ip6tnl.network new file mode 100644 index 00000000..15c6d15d --- /dev/null +++ b/test/test-network/conf/ip6tnl.network @@ -0,0 +1,7 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=ip6tnl99 +Tunnel=ip6tnl98 +Tunnel=ip6tnl97 diff --git a/test/test-network/conf/ipip.network b/test/test-network/conf/ipip.network new file mode 100644 index 00000000..ea4b3a13 --- /dev/null +++ b/test/test-network/conf/ipip.network @@ -0,0 +1,8 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=ipiptun99 +Tunnel=ipiptun98 +Tunnel=ipiptun97 +Tunnel=ipiptun96 diff --git a/test/test-network/conf/ipv6-prefix-veth.network b/test/test-network/conf/ipv6-prefix-veth.network new file mode 100644 index 00000000..3d2acecd --- /dev/null +++ b/test/test-network/conf/ipv6-prefix-veth.network @@ -0,0 +1,5 @@ +[Match] +Name=veth99 + +[Network] +IPv6AcceptRA=true diff --git a/test/test-network/conf/ipv6-prefix.network b/test/test-network/conf/ipv6-prefix.network new file mode 100644 index 00000000..c1932a84 --- /dev/null +++ b/test/test-network/conf/ipv6-prefix.network @@ -0,0 +1,10 @@ +[Match] +Name=veth-peer + +[Network] +IPv6PrefixDelegation=yes + +[IPv6Prefix] +Prefix=2002:da8:1:0::/64 +PreferredLifetimeSec=1000s +ValidLifetimeSec=2100s diff --git a/test/test-network/conf/ipv6ra-prefix-client.network b/test/test-network/conf/ipv6ra-prefix-client.network new file mode 100644 index 00000000..bc40b123 --- /dev/null +++ b/test/test-network/conf/ipv6ra-prefix-client.network @@ -0,0 +1,6 @@ +[Match] +Name=veth-peer + +[Network] +DHCP=no +IPv6AcceptRA=yes diff --git a/test/test-network/conf/ipv6ra-prefix.network b/test/test-network/conf/ipv6ra-prefix.network new file mode 100644 index 00000000..7bb66613 --- /dev/null +++ b/test/test-network/conf/ipv6ra-prefix.network @@ -0,0 +1,14 @@ +[Match] +Name=veth99 + +[Network] +DHCP=no +IPv6PrefixDelegation=yes +Address=2001:db8:0:1::1/64 + +[IPv6Prefix] +Prefix=2001:db8:0:1::4/64 + +[IPv6RoutePrefix] +Route=2001:db0:fff::/64 +LifetimeSec=1000 diff --git a/test/test-network/conf/ipvlan.network b/test/test-network/conf/ipvlan.network new file mode 100644 index 00000000..d0532205 --- /dev/null +++ b/test/test-network/conf/ipvlan.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +IPVLAN=ipvlan99 diff --git a/test/test-network/conf/ipvtap.network b/test/test-network/conf/ipvtap.network new file mode 100644 index 00000000..c81ba52e --- /dev/null +++ b/test/test-network/conf/ipvtap.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +IPVTAP=ipvtap99 diff --git a/test/test-network/conf/isatap.network b/test/test-network/conf/isatap.network new file mode 100644 index 00000000..e8d03ed6 --- /dev/null +++ b/test/test-network/conf/isatap.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=isataptun99 diff --git a/test/test-network/conf/macsec.network b/test/test-network/conf/macsec.network new file mode 100644 index 00000000..5558547c --- /dev/null +++ b/test/test-network/conf/macsec.network @@ -0,0 +1,10 @@ +[Match] +Name=dummy98 + +[Link] +MACAddress=00:50:56:c0:00:19 + +[Network] +IPv6AcceptRA=no +LinkLocalAddressing=yes +MACsec=macsec99 diff --git a/test/test-network/conf/macvlan.network b/test/test-network/conf/macvlan.network new file mode 100644 index 00000000..a41c1f91 --- /dev/null +++ b/test/test-network/conf/macvlan.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +MACVLAN=macvlan99 diff --git a/test/test-network/conf/macvtap.network b/test/test-network/conf/macvtap.network new file mode 100644 index 00000000..6ee99ab9 --- /dev/null +++ b/test/test-network/conf/macvtap.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +MACVTAP=macvtap99 diff --git a/test/test-network/conf/netdev-link-local-addressing-yes.network b/test/test-network/conf/netdev-link-local-addressing-yes.network new file mode 100644 index 00000000..d7dfa7ea --- /dev/null +++ b/test/test-network/conf/netdev-link-local-addressing-yes.network @@ -0,0 +1,19 @@ +[Match] +Name=ipvlan99 +Name=ipvtap99 +Name=macvlan99 +Name=macvtap99 +Name=veth99 +Name=veth-peer +Name=vcan99 +Name=vxcan99 +Name=vxcan-peer +Name=vrf99 +Name=geneve99 +Name=ipiptun99 +Name=nlmon99 +Name=xfrm99 + +[Network] +LinkLocalAddressing=yes +IPv6AcceptRA=no diff --git a/test/test-network/conf/routing-policy-rule-dummy98.network b/test/test-network/conf/routing-policy-rule-dummy98.network new file mode 100644 index 00000000..8136c20a --- /dev/null +++ b/test/test-network/conf/routing-policy-rule-dummy98.network @@ -0,0 +1,10 @@ +[Match] +Name=dummy98 + +[RoutingPolicyRule] +TypeOfService=0x08 +Table=8 +From= 192.168.101.18 +Priority=112 +IncomingInterface=dummy98 +OutgoingInterface=dummy98 diff --git a/test/test-network/conf/routing-policy-rule-test1.network b/test/test-network/conf/routing-policy-rule-test1.network new file mode 100644 index 00000000..ffcedc99 --- /dev/null +++ b/test/test-network/conf/routing-policy-rule-test1.network @@ -0,0 +1,22 @@ +[Match] +Name=test1 + +[RoutingPolicyRule] +TypeOfService=0x08 +Table=7 +From= 192.168.100.18 +Priority=111 +IncomingInterface=test1 +OutgoingInterface=test1 + +[RoutingPolicyRule] +IncomingInterface=test1 +Table=8 +Priority=100 +Family=ipv6 + +[RoutingPolicyRule] +IncomingInterface=test1 +Table=9 +Priority=101 +Family=both diff --git a/test/test-network/conf/sit.network b/test/test-network/conf/sit.network new file mode 100644 index 00000000..79909fcd --- /dev/null +++ b/test/test-network/conf/sit.network @@ -0,0 +1,8 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=sittun99 +Tunnel=sittun98 +Tunnel=sittun97 +Tunnel=sittun96 diff --git a/test/test-network/conf/state-file-tests.network b/test/test-network/conf/state-file-tests.network new file mode 100644 index 00000000..d0233841 --- /dev/null +++ b/test/test-network/conf/state-file-tests.network @@ -0,0 +1,15 @@ +[Match] +Name=dummy98 + +[Link] +RequiredForOnline=routable + +[Network] +DNS=10.10.10.10 10.10.10.11 +NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org +Domains=hogehoge ~foofoo +LLMNR=no +MulticastDNS=yes +DNSSEC=no +Address=192.168.10.10/24 +Address=192.168.12.12/24 diff --git a/test/test-network/conf/vlan6.netdev b/test/test-network/conf/vlan6.netdev new file mode 100644 index 00000000..310be91f --- /dev/null +++ b/test/test-network/conf/vlan6.netdev @@ -0,0 +1,7 @@ +[NetDev] +Name=vlan6 +Kind=vlan +MTUBytes=1500 + +[VLAN] +Id=6 diff --git a/test/test-network/conf/vlan6.network b/test/test-network/conf/vlan6.network new file mode 100644 index 00000000..64e9db52 --- /dev/null +++ b/test/test-network/conf/vlan6.network @@ -0,0 +1,6 @@ +[Match] +Name=vlan6 + +[Network] +IPv6AcceptRA=false +Address=100.100.100.2/24 diff --git a/test/test-network/conf/vti.network b/test/test-network/conf/vti.network new file mode 100644 index 00000000..761362e4 --- /dev/null +++ b/test/test-network/conf/vti.network @@ -0,0 +1,8 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=vtitun99 +Tunnel=vtitun98 +Tunnel=vtitun97 +Tunnel=vtitun96 diff --git a/test/test-network/conf/vti6.network b/test/test-network/conf/vti6.network new file mode 100644 index 00000000..60ccb77f --- /dev/null +++ b/test/test-network/conf/vti6.network @@ -0,0 +1,7 @@ +[Match] +Name=dummy98 + +[Network] +Tunnel=vti6tun99 +Tunnel=vti6tun98 +Tunnel=vti6tun97 diff --git a/test/test-network/conf/vxlan-test1.network b/test/test-network/conf/vxlan-test1.network new file mode 100644 index 00000000..aaffb646 --- /dev/null +++ b/test/test-network/conf/vxlan-test1.network @@ -0,0 +1,7 @@ +[Match] +Name=test1 + +[Network] +IPv6AcceptRA=false +LinkLocalAddressing=yes +VXLAN=vxlan99 diff --git a/test/test-network/conf/vxlan.network b/test/test-network/conf/vxlan.network new file mode 100644 index 00000000..fc8ac47a --- /dev/null +++ b/test/test-network/conf/vxlan.network @@ -0,0 +1,18 @@ +[Match] +Name=vxlan99 + +[Network] +IPv6AcceptRA=no +LinkLocalAddressing=yes + +[BridgeFDB] +MACAddress=00:11:22:33:44:55 +Destination=10.0.0.5 + +[BridgeFDB] +MACAddress=00:11:22:33:44:66 +Destination=10.0.0.6 + +[BridgeFDB] +MACAddress=00:11:22:33:44:77 +Destination=10.0.0.7 diff --git a/test/test-network/conf/xfrm.network b/test/test-network/conf/xfrm.network new file mode 100644 index 00000000..bfb2956a --- /dev/null +++ b/test/test-network/conf/xfrm.network @@ -0,0 +1,6 @@ +[Match] +Name=dummy98 + +[Network] +IPv6AcceptRA=no +Xfrm=xfrm99 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py new file mode 100755 index 00000000..ab6e11e0 --- /dev/null +++ b/test/test-network/systemd-networkd-tests.py @@ -0,0 +1,3327 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ +# systemd-networkd tests + +import argparse +import os +import re +import shutil +import signal +import subprocess +import sys +import time +import unittest +from shutil import copytree + +network_unit_file_path='/run/systemd/network' +networkd_runtime_directory='/run/systemd/netif' +networkd_ci_path='/run/networkd-ci' +network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf' +network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf' + +dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid' +dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file' + +systemd_lib_paths=['/usr/lib/systemd', '/lib/systemd'] +which_paths=':'.join(systemd_lib_paths + os.getenv('PATH', os.defpath).lstrip(':').split(':')) + +networkd_bin=shutil.which('systemd-networkd', path=which_paths) +resolved_bin=shutil.which('systemd-resolved', path=which_paths) +wait_online_bin=shutil.which('systemd-networkd-wait-online', path=which_paths) +networkctl_bin=shutil.which('networkctl', path=which_paths) +resolvectl_bin=shutil.which('resolvectl', path=which_paths) +timedatectl_bin=shutil.which('timedatectl', path=which_paths) + +use_valgrind=False +enable_debug=True +env = {} +asan_options=None +lsan_options=None +ubsan_options=None + +running_units = [] + +def check_output(*command, **kwargs): + # This replaces both check_output and check_call (output can be ignored) + command = command[0].split() + list(command[1:]) + return subprocess.check_output(command, universal_newlines=True, **kwargs).rstrip() + +def call(*command, **kwargs): + command = command[0].split() + list(command[1:]) + return subprocess.call(command, universal_newlines=True, **kwargs) + +def run(*command, **kwargs): + command = command[0].split() + list(command[1:]) + return subprocess.run(command, universal_newlines=True, **kwargs) + +def is_module_available(module_name): + lsmod_output = check_output('lsmod') + module_re = re.compile(rf'^{re.escape(module_name)}\b', re.MULTILINE) + return module_re.search(lsmod_output) or not call('modprobe', module_name, stderr=subprocess.DEVNULL) + +def expectedFailureIfModuleIsNotAvailable(module_name): + def f(func): + if not is_module_available(module_name): + return unittest.expectedFailure(func) + return func + + return f + +def expectedFailureIfERSPANModuleIsNotAvailable(): + def f(func): + rc = call('ip link add dev erspan99 type erspan seq key 30 local 192.168.1.4 remote 192.168.1.1 erspan_ver 1 erspan 123', stderr=subprocess.DEVNULL) + if rc == 0: + call('ip link del erspan99') + return func + else: + return unittest.expectedFailure(func) + + return f + +def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable(): + def f(func): + rc = call('ip rule add from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7', stderr=subprocess.DEVNULL) + if rc == 0: + call('ip rule del from 192.168.100.19 sport 1123-1150 dport 3224-3290 table 7') + return func + else: + return unittest.expectedFailure(func) + + return f + +def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable(): + def f(func): + rc = call('ip rule add not from 192.168.100.19 ipproto tcp table 7', stderr=subprocess.DEVNULL) + if rc == 0: + call('ip rule del not from 192.168.100.19 ipproto tcp table 7') + return func + else: + return unittest.expectedFailure(func) + + return f + +def expectedFailureIfLinkFileFieldIsNotSet(): + def f(func): + support = False + rc = call('ip link add name dummy99 type dummy', stderr=subprocess.DEVNULL) + if rc == 0: + ret = run('udevadm info -w10s /sys/class/net/dummy99', stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if ret.returncode == 0 and 'E: ID_NET_LINK_FILE=' in ret.stdout.rstrip(): + support = True + call('ip link del dummy99') + + if support: + return func + else: + return unittest.expectedFailure(func) + + return f + +def expectedFailureIfNexthopIsNotAvailable(): + def f(func): + rc = call('ip nexthop list', stderr=subprocess.DEVNULL) + if rc == 0: + return func + else: + return unittest.expectedFailure(func) + + return f + +def setUpModule(): + global running_units + + os.makedirs(network_unit_file_path, exist_ok=True) + os.makedirs(networkd_ci_path, exist_ok=True) + + shutil.rmtree(networkd_ci_path) + copytree(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf'), networkd_ci_path) + + for u in ['systemd-networkd.socket', 'systemd-networkd.service', 'systemd-resolved.service', 'firewalld.service']: + if call(f'systemctl is-active --quiet {u}') == 0: + check_output(f'systemctl stop {u}') + running_units.append(u) + + drop_in = [ + '[Service]', + 'Restart=no', + 'ExecStart=', + ] + if use_valgrind: + drop_in += [ + 'ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + networkd_bin, + 'PrivateTmp=yes' + ] + else: + drop_in += ['ExecStart=!!' + networkd_bin] + if enable_debug: + drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug'] + if asan_options: + drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"'] + if lsan_options: + drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"'] + if ubsan_options: + drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"'] + if asan_options or lsan_options or ubsan_options: + drop_in += ['SystemCallFilter='] + if use_valgrind or asan_options or lsan_options or ubsan_options: + drop_in += ['MemoryDenyWriteExecute=no'] + + os.makedirs('/run/systemd/system/systemd-networkd.service.d', exist_ok=True) + with open('/run/systemd/system/systemd-networkd.service.d/00-override.conf', mode='w') as f: + f.write('\n'.join(drop_in)) + + drop_in = [ + '[Service]', + 'Restart=no', + 'ExecStart=', + ] + if use_valgrind: + drop_in += ['ExecStart=!!valgrind --track-origins=yes --leak-check=full --show-leak-kinds=all ' + resolved_bin] + else: + drop_in += ['ExecStart=!!' + resolved_bin] + if enable_debug: + drop_in += ['Environment=SYSTEMD_LOG_LEVEL=debug'] + if asan_options: + drop_in += ['Environment=ASAN_OPTIONS="' + asan_options + '"'] + if lsan_options: + drop_in += ['Environment=LSAN_OPTIONS="' + lsan_options + '"'] + if ubsan_options: + drop_in += ['Environment=UBSAN_OPTIONS="' + ubsan_options + '"'] + if asan_options or lsan_options or ubsan_options: + drop_in += ['SystemCallFilter='] + if use_valgrind or asan_options or lsan_options or ubsan_options: + drop_in += ['MemoryDenyWriteExecute=no'] + + os.makedirs('/run/systemd/system/systemd-resolved.service.d', exist_ok=True) + with open('/run/systemd/system/systemd-resolved.service.d/00-override.conf', mode='w') as f: + f.write('\n'.join(drop_in)) + + check_output('systemctl daemon-reload') + print(check_output('systemctl cat systemd-networkd.service')) + print(check_output('systemctl cat systemd-resolved.service')) + check_output('systemctl restart systemd-resolved') + +def tearDownModule(): + global running_units + + shutil.rmtree(networkd_ci_path) + + for u in ['systemd-networkd.service', 'systemd-resolved.service']: + check_output(f'systemctl stop {u}') + + shutil.rmtree('/run/systemd/system/systemd-networkd.service.d') + shutil.rmtree('/run/systemd/system/systemd-resolved.service.d') + check_output('systemctl daemon-reload') + + for u in running_units: + check_output(f'systemctl start {u}') + +def read_link_attr(link, dev, attribute): + with open(os.path.join(os.path.join(os.path.join('/sys/class/net/', link), dev), attribute)) as f: + return f.readline().strip() + +def read_bridge_port_attr(bridge, link, attribute): + path_bridge = os.path.join('/sys/devices/virtual/net', bridge) + path_port = 'lower_' + link + '/brport' + path = os.path.join(path_bridge, path_port) + + with open(os.path.join(path, attribute)) as f: + return f.readline().strip() + +def link_exists(link): + return os.path.exists(os.path.join('/sys/class/net', link)) + +def remove_links(links): + for link in links: + if link_exists(link): + call('ip link del dev', link) + time.sleep(1) + +def remove_fou_ports(ports): + for port in ports: + call('ip fou del port', port, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + +def remove_routing_policy_rule_tables(tables): + for table in tables: + rc = 0 + while rc == 0: + rc = call('ip rule del table', table, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + +def remove_routes(routes): + for route_type, addr in routes: + call('ip route del', route_type, addr, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + +def remove_l2tp_tunnels(tunnel_ids): + output = check_output('ip l2tp show tunnel') + for tid in tunnel_ids: + words='Tunnel ' + tid + ', encap' + if words in output: + call('ip l2tp del tunnel tid', tid) + time.sleep(1) + +def read_ipv6_sysctl_attr(link, attribute): + with open(os.path.join(os.path.join(network_sysctl_ipv6_path, link), attribute)) as f: + return f.readline().strip() + +def read_ipv4_sysctl_attr(link, attribute): + with open(os.path.join(os.path.join(network_sysctl_ipv4_path, link), attribute)) as f: + return f.readline().strip() + +def copy_unit_to_networkd_unit_path(*units): + print() + for unit in units: + shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path) + if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))): + copytree(os.path.join(networkd_ci_path, unit + '.d'), os.path.join(network_unit_file_path, unit + '.d')) + +def remove_unit_from_networkd_path(units): + for unit in units: + if (os.path.exists(os.path.join(network_unit_file_path, unit))): + os.remove(os.path.join(network_unit_file_path, unit)) + if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))): + shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d')) + +def start_dnsmasq(additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'): + dnsmasq_command = f'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options + check_output(dnsmasq_command) + +def stop_dnsmasq(pid_file): + if os.path.exists(pid_file): + with open(pid_file, 'r') as f: + pid = f.read().rstrip(' \t\r\n\0') + os.kill(int(pid), signal.SIGTERM) + + os.remove(pid_file) + +def search_words_in_dnsmasq_log(words, show_all=False): + if os.path.exists(dnsmasq_log_file): + with open (dnsmasq_log_file) as in_file: + contents = in_file.read() + if show_all: + print(contents) + for line in contents.splitlines(): + if words in line: + in_file.close() + print("%s, %s" % (words, line)) + return True + return False + +def remove_lease_file(): + if os.path.exists(os.path.join(networkd_ci_path, 'lease')): + os.remove(os.path.join(networkd_ci_path, 'lease')) + +def remove_log_file(): + if os.path.exists(dnsmasq_log_file): + os.remove(dnsmasq_log_file) + +def remove_networkd_state_files(): + if os.path.exists(os.path.join(networkd_runtime_directory, 'state')): + os.remove(os.path.join(networkd_runtime_directory, 'state')) + +def stop_networkd(show_logs=True, remove_state_files=True): + if show_logs: + invocation_id = check_output('systemctl show systemd-networkd -p InvocationID --value') + check_output('systemctl stop systemd-networkd') + if show_logs: + print(check_output('journalctl _SYSTEMD_INVOCATION_ID=' + invocation_id)) + if remove_state_files: + remove_networkd_state_files() + +def start_networkd(sleep_sec=0): + check_output('systemctl start systemd-networkd') + if sleep_sec > 0: + time.sleep(sleep_sec) + +def restart_networkd(sleep_sec=0, show_logs=True, remove_state_files=True): + stop_networkd(show_logs, remove_state_files) + start_networkd(sleep_sec) + +def get_operstate(link, show_status=True, setup_state='configured'): + output = check_output(*networkctl_cmd, 'status', link, env=env) + if show_status: + print(output) + for line in output.splitlines(): + if 'State:' in line and (not setup_state or setup_state in line): + return line.split()[1] + return None + +class Utilities(): + def check_link_exists(self, link): + self.assertTrue(link_exists(link)) + + def check_operstate(self, link, expected, show_status=True, setup_state='configured'): + self.assertRegex(get_operstate(link, show_status, setup_state), expected) + + def wait_online(self, links_with_operstate, timeout='20s', bool_any=False, setup_state='configured'): + args = wait_online_cmd + [f'--timeout={timeout}'] + [f'--interface={link}' for link in links_with_operstate] + if bool_any: + args += ['--any'] + try: + check_output(*args, env=env) + except subprocess.CalledProcessError: + for link in links_with_operstate: + output = check_output(*networkctl_cmd, 'status', link.split(':')[0], env=env) + print(output) + raise + if not bool_any: + for link in links_with_operstate: + output = check_output(*networkctl_cmd, 'status', link.split(':')[0]) + print(output) + for line in output.splitlines(): + if 'State:' in line: + self.assertRegex(line, setup_state) + + def wait_address(self, link, address_regex, scope='global', ipv='', timeout_sec=100): + for i in range(timeout_sec): + if i > 0: + time.sleep(1) + output = check_output(f'ip {ipv} address show dev {link} scope {scope}') + if re.search(address_regex, output): + break + else: + self.assertRegex(output, address_regex) + +class NetworkctlTests(unittest.TestCase, Utilities): + + links = [ + 'dummy98', + 'test1', + 'veth99', + ] + + units = [ + '11-dummy.netdev', + '11-dummy-mtu.netdev', + '11-dummy.network', + '12-dummy.netdev', + '25-address-static.network', + '25-veth.netdev', + 'netdev-link-local-addressing-yes.network', + ] + + def setUp(self): + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_reconfigure(self): + copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('ip -4 address show dev dummy98') + print(output) + self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98') + self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98') + self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98') + + check_output('ip address del 10.1.2.3/16 dev dummy98') + check_output('ip address del 10.1.2.4/16 dev dummy98') + check_output('ip address del 10.2.2.4/16 dev dummy98') + + check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env) + self.wait_online(['dummy98:routable']) + + output = check_output('ip -4 address show dev dummy98') + print(output) + self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98') + self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98') + self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98') + + def test_reload(self): + start_networkd(3) + + copy_unit_to_networkd_unit_path('11-dummy.netdev') + check_output(*networkctl_cmd, 'reload', env=env) + time.sleep(3) + self.check_link_exists('test1') + self.check_operstate('test1', 'off', setup_state='unmanaged') + + copy_unit_to_networkd_unit_path('11-dummy.network') + check_output(*networkctl_cmd, 'reload', env=env) + self.wait_online(['test1:degraded']) + + remove_unit_from_networkd_path(['11-dummy.network']) + check_output(*networkctl_cmd, 'reload', env=env) + time.sleep(1) + self.check_operstate('test1', 'degraded', setup_state='unmanaged') + + remove_unit_from_networkd_path(['11-dummy.netdev']) + check_output(*networkctl_cmd, 'reload', env=env) + self.check_operstate('test1', 'degraded', setup_state='unmanaged') + + copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network') + check_output(*networkctl_cmd, 'reload', env=env) + self.check_operstate('test1', 'degraded') + + def test_glob(self): + copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network') + start_networkd() + + self.wait_online(['test1:degraded']) + + output = check_output(*networkctl_cmd, 'list', env=env) + self.assertRegex(output, '1 lo ') + self.assertRegex(output, 'test1') + + output = check_output(*networkctl_cmd, 'list', 'test1', env=env) + self.assertNotRegex(output, '1 lo ') + self.assertRegex(output, 'test1') + + output = check_output(*networkctl_cmd, 'list', 'te*', env=env) + self.assertNotRegex(output, '1 lo ') + self.assertRegex(output, 'test1') + + output = check_output(*networkctl_cmd, 'status', 'te*', env=env) + self.assertNotRegex(output, '1: lo ') + self.assertRegex(output, 'test1') + + output = check_output(*networkctl_cmd, 'status', 'tes[a-z][0-9]', env=env) + self.assertNotRegex(output, '1: lo ') + self.assertRegex(output, 'test1') + + def test_mtu(self): + copy_unit_to_networkd_unit_path('11-dummy-mtu.netdev', '11-dummy.network') + start_networkd() + + self.wait_online(['test1:degraded']) + + output = check_output(*networkctl_cmd, 'status', 'test1', env=env) + self.assertRegex(output, 'MTU: 1600') + + def test_type(self): + copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network') + start_networkd() + self.wait_online(['test1:degraded']) + + output = check_output(*networkctl_cmd, 'status', 'test1') + print(output) + self.assertRegex(output, 'Type: ether') + + output = check_output(*networkctl_cmd, 'status', 'lo') + print(output) + self.assertRegex(output, 'Type: loopback') + + @expectedFailureIfLinkFileFieldIsNotSet() + def test_udev_link_file(self): + copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network') + start_networkd() + self.wait_online(['test1:degraded']) + + output = check_output(*networkctl_cmd, 'status', 'test1') + print(output) + self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link') + self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network') + + output = check_output(*networkctl_cmd, 'status', 'lo') + print(output) + self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link') + self.assertRegex(output, r'Network File: n/a') + + def test_delete_links(self): + copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network', + '25-veth.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded']) + + check_output(*networkctl_cmd, 'delete', 'test1', 'veth99') + self.assertFalse(link_exists('test1')) + self.assertFalse(link_exists('veth99')) + self.assertFalse(link_exists('veth-peer')) + +class NetworkdNetDevTests(unittest.TestCase, Utilities): + + links_remove_earlier = [ + 'xfrm99', + ] + + links = [ + '6rdtun99', + 'bond99', + 'bridge99', + 'dropin-test', + 'dummy98', + 'erspan98', + 'erspan99', + 'geneve99', + 'gretap96', + 'gretap98', + 'gretap99', + 'gretun96', + 'gretun97', + 'gretun98', + 'gretun99', + 'ip6gretap98', + 'ip6gretap99', + 'ip6gretun96', + 'ip6gretun97', + 'ip6gretun98', + 'ip6gretun99', + 'ip6tnl97', + 'ip6tnl98', + 'ip6tnl99', + 'ipiptun96', + 'ipiptun97', + 'ipiptun98', + 'ipiptun99', + 'ipvlan99', + 'ipvtap99', + 'isataptun99', + 'macvlan99', + 'macvtap99', + 'nlmon99', + 'sittun96', + 'sittun97', + 'sittun98', + 'sittun99', + 'tap99', + 'test1', + 'tun99', + 'vcan99', + 'veth99', + 'vlan99', + 'vrf99', + 'vti6tun97', + 'vti6tun98', + 'vti6tun99', + 'vtitun96', + 'vtitun97', + 'vtitun98', + 'vtitun99', + 'vxcan99', + 'vxlan99', + 'wg98', + 'wg99', + ] + + units = [ + '10-dropin-test.netdev', + '11-dummy.netdev', + '11-dummy.network', + '12-dummy.netdev', + '13-not-match-udev-property.network', + '14-match-udev-property.network', + '15-name-conflict-test.netdev', + '21-macvlan.netdev', + '21-macvtap.netdev', + '21-vlan-test1.network', + '21-vlan.netdev', + '21-vlan.network', + '25-6rd-tunnel.netdev', + '25-bond.netdev', + '25-bond-balanced-tlb.netdev', + '25-bridge.netdev', + '25-bridge-configure-without-carrier.network', + '25-bridge.network', + '25-erspan-tunnel-local-any.netdev', + '25-erspan-tunnel.netdev', + '25-fou-gretap.netdev', + '25-fou-gre.netdev', + '25-fou-ipip.netdev', + '25-fou-ipproto-gre.netdev', + '25-fou-ipproto-ipip.netdev', + '25-fou-sit.netdev', + '25-geneve.netdev', + '25-gretap-tunnel-local-any.netdev', + '25-gretap-tunnel.netdev', + '25-gre-tunnel-any-any.netdev', + '25-gre-tunnel-local-any.netdev', + '25-gre-tunnel-remote-any.netdev', + '25-gre-tunnel.netdev', + '25-ip6gretap-tunnel-local-any.netdev', + '25-ip6gretap-tunnel.netdev', + '25-ip6gre-tunnel-any-any.netdev', + '25-ip6gre-tunnel-local-any.netdev', + '25-ip6gre-tunnel-remote-any.netdev', + '25-ip6gre-tunnel.netdev', + '25-ip6tnl-tunnel-any-any.netdev', + '25-ip6tnl-tunnel-local-any.netdev', + '25-ip6tnl-tunnel-remote-any.netdev', + '25-ip6tnl-tunnel.netdev', + '25-ipip-tunnel-any-any.netdev', + '25-ipip-tunnel-independent.netdev', + '25-ipip-tunnel-independent-loopback.netdev', + '25-ipip-tunnel-local-any.netdev', + '25-ipip-tunnel-remote-any.netdev', + '25-ipip-tunnel.netdev', + '25-ipvlan.netdev', + '25-ipvtap.netdev', + '25-isatap-tunnel.netdev', + '25-macsec.key', + '25-macsec.netdev', + '25-macsec.network', + '25-nlmon.netdev', + '25-sit-tunnel-any-any.netdev', + '25-sit-tunnel-local-any.netdev', + '25-sit-tunnel-remote-any.netdev', + '25-sit-tunnel.netdev', + '25-tap.netdev', + '25-tun.netdev', + '25-tunnel-local-any.network', + '25-tunnel-remote-any.network', + '25-tunnel.network', + '25-vcan.netdev', + '25-veth.netdev', + '25-vrf.netdev', + '25-vti6-tunnel-any-any.netdev', + '25-vti6-tunnel-local-any.netdev', + '25-vti6-tunnel-remote-any.netdev', + '25-vti6-tunnel.netdev', + '25-vti-tunnel-any-any.netdev', + '25-vti-tunnel-local-any.netdev', + '25-vti-tunnel-remote-any.netdev', + '25-vti-tunnel.netdev', + '25-vxcan.netdev', + '25-vxlan.netdev', + '25-wireguard-23-peers.netdev', + '25-wireguard-23-peers.network', + '25-wireguard-preshared-key.txt', + '25-wireguard-private-key.txt', + '25-wireguard.netdev', + '25-wireguard.network', + '25-xfrm.netdev', + '25-xfrm-independent.netdev', + '6rd.network', + 'erspan.network', + 'gre.network', + 'gretap.network', + 'gretun.network', + 'ip6gretap.network', + 'ip6gretun.network', + 'ip6tnl.network', + 'ipip.network', + 'ipvlan.network', + 'ipvtap.network', + 'isatap.network', + 'macsec.network', + 'macvlan.network', + 'macvtap.network', + 'netdev-link-local-addressing-yes.network', + 'sit.network', + 'vti6.network', + 'vti.network', + 'vxlan-test1.network', + 'vxlan.network', + 'xfrm.network', + ] + + fou_ports = [ + '55555', + '55556'] + + def setUp(self): + remove_fou_ports(self.fou_ports) + remove_links(self.links_remove_earlier) + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_fou_ports(self.fou_ports) + remove_links(self.links_remove_earlier) + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_dropin_and_name_conflict(self): + copy_unit_to_networkd_unit_path('10-dropin-test.netdev', '15-name-conflict-test.netdev') + start_networkd() + + self.wait_online(['dropin-test:off'], setup_state='unmanaged') + + output = check_output('ip link show dropin-test') + print(output) + self.assertRegex(output, '00:50:56:c0:00:28') + + def test_match_udev_property(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', '13-not-match-udev-property.network', '14-match-udev-property.network') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('networkctl status dummy98') + print(output) + self.assertRegex(output, 'Network File: /run/systemd/network/14-match-udev-property') + + def test_wait_online_any(self): + copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge.network', '11-dummy.netdev', '11-dummy.network') + start_networkd() + + self.wait_online(['bridge99', 'test1:degraded'], bool_any=True) + + self.check_operstate('bridge99', '(off|no-carrier)', setup_state='configuring') + self.check_operstate('test1', 'degraded') + + def test_bridge(self): + copy_unit_to_networkd_unit_path('25-bridge.netdev', '25-bridge-configure-without-carrier.network') + start_networkd() + + self.wait_online(['bridge99:no-carrier']) + + tick = os.sysconf('SC_CLK_TCK') + self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'hello_time')) / tick)) + self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'max_age')) / tick)) + self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'forward_delay')) / tick)) + self.assertEqual(9, round(float(read_link_attr('bridge99', 'bridge', 'ageing_time')) / tick)) + self.assertEqual(9, int(read_link_attr('bridge99', 'bridge', 'priority'))) + self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_querier'))) + self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'multicast_snooping'))) + self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state'))) + self.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version'))) + + output = check_output(*networkctl_cmd, 'status', 'bridge99') + print(output) + self.assertRegex(output, 'Priority: 9') + self.assertRegex(output, 'STP: yes') + self.assertRegex(output, 'Multicast IGMP Version: 3') + + def test_bond(self): + copy_unit_to_networkd_unit_path('25-bond.netdev', '25-bond-balanced-tlb.netdev') + start_networkd() + + self.wait_online(['bond99:off', 'bond98:off'], setup_state='unmanaged') + + self.assertEqual('802.3ad 4', read_link_attr('bond99', 'bonding', 'mode')) + self.assertEqual('layer3+4 1', read_link_attr('bond99', 'bonding', 'xmit_hash_policy')) + self.assertEqual('1000', read_link_attr('bond99', 'bonding', 'miimon')) + self.assertEqual('fast 1', read_link_attr('bond99', 'bonding', 'lacp_rate')) + self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'updelay')) + self.assertEqual('2000', read_link_attr('bond99', 'bonding', 'downdelay')) + self.assertEqual('4', read_link_attr('bond99', 'bonding', 'resend_igmp')) + self.assertEqual('1', read_link_attr('bond99', 'bonding', 'min_links')) + self.assertEqual('1218', read_link_attr('bond99', 'bonding', 'ad_actor_sys_prio')) + self.assertEqual('811', read_link_attr('bond99', 'bonding', 'ad_user_port_key')) + self.assertEqual('00:11:22:33:44:55', read_link_attr('bond99', 'bonding', 'ad_actor_system')) + + self.assertEqual('balance-tlb 5', read_link_attr('bond98', 'bonding', 'mode')) + self.assertEqual('1', read_link_attr('bond98', 'bonding', 'tlb_dynamic_lb')) + + def test_vlan(self): + copy_unit_to_networkd_unit_path('21-vlan.netdev', '11-dummy.netdev', + '21-vlan.network', '21-vlan-test1.network') + start_networkd() + + self.wait_online(['test1:degraded', 'vlan99:routable']) + + output = check_output('ip -d link show test1') + print(output) + self.assertRegex(output, ' mtu 2000 ') + + output = check_output('ip -d link show vlan99') + print(output) + self.assertRegex(output, ' mtu 2000 ') + self.assertRegex(output, 'REORDER_HDR') + self.assertRegex(output, 'LOOSE_BINDING') + self.assertRegex(output, 'GVRP') + self.assertRegex(output, 'MVRP') + self.assertRegex(output, ' id 99 ') + + output = check_output('ip -4 address show dev test1') + print(output) + self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1') + self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1') + + output = check_output('ip -4 address show dev vlan99') + print(output) + self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99') + + def test_macvtap(self): + for mode in ['private', 'vepa', 'bridge', 'passthru']: + with self.subTest(mode=mode): + if mode != 'private': + self.tearDown() + copy_unit_to_networkd_unit_path('21-macvtap.netdev', 'netdev-link-local-addressing-yes.network', + '11-dummy.netdev', 'macvtap.network') + with open(os.path.join(network_unit_file_path, '21-macvtap.netdev'), mode='a') as f: + f.write('[MACVTAP]\nMode=' + mode) + start_networkd() + + self.wait_online(['macvtap99:degraded', 'test1:degraded']) + + output = check_output('ip -d link show macvtap99') + print(output) + self.assertRegex(output, 'macvtap mode ' + mode + ' ') + + def test_macvlan(self): + for mode in ['private', 'vepa', 'bridge', 'passthru']: + with self.subTest(mode=mode): + if mode != 'private': + self.tearDown() + copy_unit_to_networkd_unit_path('21-macvlan.netdev', 'netdev-link-local-addressing-yes.network', + '11-dummy.netdev', 'macvlan.network') + with open(os.path.join(network_unit_file_path, '21-macvlan.netdev'), mode='a') as f: + f.write('[MACVLAN]\nMode=' + mode) + start_networkd() + + self.wait_online(['macvlan99:degraded', 'test1:degraded']) + + output = check_output('ip -d link show test1') + print(output) + self.assertRegex(output, ' mtu 2000 ') + + output = check_output('ip -d link show macvlan99') + print(output) + self.assertRegex(output, ' mtu 2000 ') + self.assertRegex(output, 'macvlan mode ' + mode + ' ') + + @expectedFailureIfModuleIsNotAvailable('ipvlan') + def test_ipvlan(self): + for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]: + with self.subTest(mode=mode, flag=flag): + if mode != 'L2': + self.tearDown() + copy_unit_to_networkd_unit_path('25-ipvlan.netdev', 'netdev-link-local-addressing-yes.network', + '11-dummy.netdev', 'ipvlan.network') + with open(os.path.join(network_unit_file_path, '25-ipvlan.netdev'), mode='a') as f: + f.write('[IPVLAN]\nMode=' + mode + '\nFlags=' + flag) + + start_networkd() + self.wait_online(['ipvlan99:degraded', 'test1:degraded']) + + output = check_output('ip -d link show ipvlan99') + print(output) + self.assertRegex(output, 'ipvlan *mode ' + mode.lower() + ' ' + flag) + + @expectedFailureIfModuleIsNotAvailable('ipvtap') + def test_ipvtap(self): + for mode, flag in [['L2', 'private'], ['L3', 'vepa'], ['L3S', 'bridge']]: + with self.subTest(mode=mode, flag=flag): + if mode != 'L2': + self.tearDown() + copy_unit_to_networkd_unit_path('25-ipvtap.netdev', 'netdev-link-local-addressing-yes.network', + '11-dummy.netdev', 'ipvtap.network') + with open(os.path.join(network_unit_file_path, '25-ipvtap.netdev'), mode='a') as f: + f.write('[IPVTAP]\nMode=' + mode + '\nFlags=' + flag) + + start_networkd() + self.wait_online(['ipvtap99:degraded', 'test1:degraded']) + + output = check_output('ip -d link show ipvtap99') + print(output) + self.assertRegex(output, 'ipvtap *mode ' + mode.lower() + ' ' + flag) + + def test_veth(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['veth99:degraded', 'veth-peer:degraded']) + + output = check_output('ip -d link show veth99') + print(output) + self.assertRegex(output, 'link/ether 12:34:56:78:9a:bc') + output = check_output('ip -d link show veth-peer') + print(output) + self.assertRegex(output, 'link/ether 12:34:56:78:9a:bd') + + def test_tun(self): + copy_unit_to_networkd_unit_path('25-tun.netdev') + start_networkd() + + self.wait_online(['tun99:off'], setup_state='unmanaged') + + output = check_output('ip -d link show tun99') + print(output) + # Old ip command does not support IFF_ flags + self.assertRegex(output, 'tun (type tun pi on vnet_hdr on multi_queue|addrgenmode) ') + + def test_tap(self): + copy_unit_to_networkd_unit_path('25-tap.netdev') + start_networkd() + + self.wait_online(['tap99:off'], setup_state='unmanaged') + + output = check_output('ip -d link show tap99') + print(output) + # Old ip command does not support IFF_ flags + self.assertRegex(output, 'tun (type tap pi on vnet_hdr on multi_queue|addrgenmode) ') + + @expectedFailureIfModuleIsNotAvailable('vrf') + def test_vrf(self): + copy_unit_to_networkd_unit_path('25-vrf.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['vrf99:carrier']) + + @expectedFailureIfModuleIsNotAvailable('vcan') + def test_vcan(self): + copy_unit_to_networkd_unit_path('25-vcan.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['vcan99:carrier']) + + @expectedFailureIfModuleIsNotAvailable('vxcan') + def test_vxcan(self): + copy_unit_to_networkd_unit_path('25-vxcan.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['vxcan99:carrier', 'vxcan-peer:carrier']) + + @expectedFailureIfModuleIsNotAvailable('wireguard') + def test_wireguard(self): + copy_unit_to_networkd_unit_path('25-wireguard.netdev', '25-wireguard.network', + '25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network', + '25-wireguard-preshared-key.txt', '25-wireguard-private-key.txt') + start_networkd() + self.wait_online(['wg99:carrier', 'wg98:routable']) + + if shutil.which('wg'): + call('wg') + + output = check_output('wg show wg99 listen-port') + self.assertRegex(output, '51820') + output = check_output('wg show wg99 fwmark') + self.assertRegex(output, '0x4d2') + output = check_output('wg show wg99 allowed-ips') + self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48') + self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128') + output = check_output('wg show wg99 persistent-keepalive') + self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20') + output = check_output('wg show wg99 endpoints') + self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820') + output = check_output('wg show wg99 private-key') + self.assertRegex(output, r'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=') + output = check_output('wg show wg99 preshared-keys') + self.assertRegex(output, r'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA= IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=') + self.assertRegex(output, r'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc= cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=') + + output = check_output('wg show wg98 private-key') + self.assertRegex(output, r'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=') + + def test_geneve(self): + copy_unit_to_networkd_unit_path('25-geneve.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['geneve99:degraded']) + + output = check_output('ip -d link show geneve99') + print(output) + self.assertRegex(output, '192.168.22.1') + self.assertRegex(output, '6082') + self.assertRegex(output, 'udpcsum') + self.assertRegex(output, 'udp6zerocsumrx') + + def test_ipip_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network', + '25-ipip-tunnel.netdev', '25-tunnel.network', + '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network', + '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', + '25-ipip-tunnel-any-any.netdev', '25-tunnel-any-any.network') + start_networkd() + self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'ipiptun96:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show ipiptun99') + print(output) + self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local 192.168.223.238 dev dummy98') + output = check_output('ip -d link show ipiptun98') + print(output) + self.assertRegex(output, 'ipip (ipip )?remote 192.169.224.239 local any dev dummy98') + output = check_output('ip -d link show ipiptun97') + print(output) + self.assertRegex(output, 'ipip (ipip )?remote any local 192.168.223.238 dev dummy98') + output = check_output('ip -d link show ipiptun96') + print(output) + self.assertRegex(output, 'ipip (ipip )?remote any local any dev dummy98') + + def test_gre_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network', + '25-gre-tunnel.netdev', '25-tunnel.network', + '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network', + '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', + '25-gre-tunnel-any-any.netdev', '25-tunnel-any-any.network') + start_networkd() + self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'gretun96:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show gretun99') + print(output) + self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98') + self.assertRegex(output, 'ikey 1.2.3.103') + self.assertRegex(output, 'okey 1.2.4.103') + self.assertRegex(output, 'iseq') + self.assertRegex(output, 'oseq') + output = check_output('ip -d link show gretun98') + print(output) + self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98') + self.assertRegex(output, 'ikey 0.0.0.104') + self.assertRegex(output, 'okey 0.0.0.104') + self.assertNotRegex(output, 'iseq') + self.assertNotRegex(output, 'oseq') + output = check_output('ip -d link show gretun97') + print(output) + self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98') + self.assertRegex(output, 'ikey 0.0.0.105') + self.assertRegex(output, 'okey 0.0.0.105') + self.assertNotRegex(output, 'iseq') + self.assertNotRegex(output, 'oseq') + output = check_output('ip -d link show gretun96') + print(output) + self.assertRegex(output, 'gre remote any local any dev dummy98') + self.assertRegex(output, 'ikey 0.0.0.106') + self.assertRegex(output, 'okey 0.0.0.106') + self.assertNotRegex(output, 'iseq') + self.assertNotRegex(output, 'oseq') + + def test_ip6gre_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network', + '25-ip6gre-tunnel.netdev', '25-tunnel.network', + '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network', + '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', + '25-ip6gre-tunnel-any-any.netdev', '25-tunnel-any-any.network') + start_networkd(5) + + # Old kernels seem not to support IPv6LL address on ip6gre tunnel, So please do not use wait_online() here. + + self.check_link_exists('dummy98') + self.check_link_exists('ip6gretun99') + self.check_link_exists('ip6gretun98') + self.check_link_exists('ip6gretun97') + self.check_link_exists('ip6gretun96') + + output = check_output('ip -d link show ip6gretun99') + print(output) + self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98') + output = check_output('ip -d link show ip6gretun98') + print(output) + self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98') + output = check_output('ip -d link show ip6gretun97') + print(output) + self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98') + output = check_output('ip -d link show ip6gretun96') + print(output) + self.assertRegex(output, 'ip6gre remote any local any dev dummy98') + + def test_gretap_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network', + '25-gretap-tunnel.netdev', '25-tunnel.network', + '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network') + start_networkd() + self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show gretap99') + print(output) + self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98') + self.assertRegex(output, 'ikey 0.0.0.106') + self.assertRegex(output, 'okey 0.0.0.106') + self.assertRegex(output, 'iseq') + self.assertRegex(output, 'oseq') + output = check_output('ip -d link show gretap98') + print(output) + self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98') + self.assertRegex(output, 'ikey 0.0.0.107') + self.assertRegex(output, 'okey 0.0.0.107') + self.assertRegex(output, 'iseq') + self.assertRegex(output, 'oseq') + + def test_ip6gretap_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network', + '25-ip6gretap-tunnel.netdev', '25-tunnel.network', + '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network') + start_networkd() + self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show ip6gretap99') + print(output) + self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98') + output = check_output('ip -d link show ip6gretap98') + print(output) + self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98') + + def test_vti_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network', + '25-vti-tunnel.netdev', '25-tunnel.network', + '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network', + '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', + '25-vti-tunnel-any-any.netdev', '25-tunnel-any-any.network') + start_networkd() + self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'vtitun96:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show vtitun99') + print(output) + self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98') + output = check_output('ip -d link show vtitun98') + print(output) + self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98') + output = check_output('ip -d link show vtitun97') + print(output) + self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98') + output = check_output('ip -d link show vtitun96') + print(output) + self.assertRegex(output, 'vti remote any local any dev dummy98') + + def test_vti6_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network', + '25-vti6-tunnel.netdev', '25-tunnel.network', + '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network', + '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network') + start_networkd() + self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show vti6tun99') + print(output) + self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98') + output = check_output('ip -d link show vti6tun98') + print(output) + self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98') + output = check_output('ip -d link show vti6tun97') + print(output) + self.assertRegex(output, 'vti6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98') + + def test_ip6tnl_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network', + '25-ip6tnl-tunnel.netdev', '25-tunnel.network', + '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network', + '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network') + start_networkd() + self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show ip6tnl99') + print(output) + self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98') + output = check_output('ip -d link show ip6tnl98') + print(output) + self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (any|::) dev dummy98') + output = check_output('ip -d link show ip6tnl97') + print(output) + self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98') + + def test_sit_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network', + '25-sit-tunnel.netdev', '25-tunnel.network', + '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network', + '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network', + '25-sit-tunnel-any-any.netdev', '25-tunnel-any-any.network') + start_networkd() + self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'sittun96:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show sittun99') + print(output) + self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local 10.65.223.238 dev dummy98") + output = check_output('ip -d link show sittun98') + print(output) + self.assertRegex(output, "sit (ip6ip )?remote 10.65.223.239 local any dev dummy98") + output = check_output('ip -d link show sittun97') + print(output) + self.assertRegex(output, "sit (ip6ip )?remote any local 10.65.223.238 dev dummy98") + output = check_output('ip -d link show sittun96') + print(output) + self.assertRegex(output, "sit (ip6ip )?remote any local any dev dummy98") + + def test_isatap_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network', + '25-isatap-tunnel.netdev', '25-tunnel.network') + start_networkd() + self.wait_online(['isataptun99:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show isataptun99') + print(output) + self.assertRegex(output, "isatap ") + + def test_6rd_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network', + '25-6rd-tunnel.netdev', '25-tunnel.network') + start_networkd() + self.wait_online(['sittun99:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show sittun99') + print(output) + self.assertRegex(output, '6rd-prefix 2602::/24') + + @expectedFailureIfERSPANModuleIsNotAvailable() + def test_erspan_tunnel(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network', + '25-erspan-tunnel.netdev', '25-tunnel.network', + '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network') + start_networkd() + self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded']) + + output = check_output('ip -d link show erspan99') + print(output) + self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200') + self.assertRegex(output, 'ikey 0.0.0.101') + self.assertRegex(output, 'okey 0.0.0.101') + self.assertRegex(output, 'iseq') + self.assertRegex(output, 'oseq') + output = check_output('ip -d link show erspan98') + print(output) + self.assertRegex(output, 'erspan remote 172.16.1.100 local any') + self.assertRegex(output, '102') + self.assertRegex(output, 'ikey 0.0.0.102') + self.assertRegex(output, 'okey 0.0.0.102') + self.assertRegex(output, 'iseq') + self.assertRegex(output, 'oseq') + + def test_tunnel_independent(self): + copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['ipiptun99:carrier']) + + def test_tunnel_independent_loopback(self): + copy_unit_to_networkd_unit_path('25-ipip-tunnel-independent-loopback.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['ipiptun99:carrier']) + + @expectedFailureIfModuleIsNotAvailable('xfrm_interface') + def test_xfrm(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'xfrm.network', + '25-xfrm.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['xfrm99:degraded', 'dummy98:degraded']) + + output = check_output('ip link show dev xfrm99') + print(output) + + @expectedFailureIfModuleIsNotAvailable('xfrm_interface') + def test_xfrm_independent(self): + copy_unit_to_networkd_unit_path('25-xfrm-independent.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['xfrm99:degraded']) + + @expectedFailureIfModuleIsNotAvailable('fou') + def test_fou(self): + # The following redundant check is necessary for CentOS CI. + # Maybe, error handling in lookup_id() in sd-netlink/generic-netlink.c needs to be updated. + self.assertTrue(is_module_available('fou')) + + copy_unit_to_networkd_unit_path('25-fou-ipproto-ipip.netdev', '25-fou-ipproto-gre.netdev', + '25-fou-ipip.netdev', '25-fou-sit.netdev', + '25-fou-gre.netdev', '25-fou-gretap.netdev') + start_networkd() + + self.wait_online(['ipiptun96:off', 'sittun96:off', 'gretun96:off', 'gretap96:off'], setup_state='unmanaged') + + output = check_output('ip fou show') + print(output) + self.assertRegex(output, 'port 55555 ipproto 4') + self.assertRegex(output, 'port 55556 ipproto 47') + + output = check_output('ip -d link show ipiptun96') + print(output) + self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555') + output = check_output('ip -d link show sittun96') + print(output) + self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555') + output = check_output('ip -d link show gretun96') + print(output) + self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556') + output = check_output('ip -d link show gretap96') + print(output) + self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556') + + def test_vxlan(self): + copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network', + '11-dummy.netdev', 'vxlan-test1.network') + start_networkd() + + self.wait_online(['test1:degraded', 'vxlan99:degraded']) + + output = check_output('ip -d link show vxlan99') + print(output) + self.assertRegex(output, '999') + self.assertRegex(output, '5555') + self.assertRegex(output, 'l2miss') + self.assertRegex(output, 'l3miss') + self.assertRegex(output, 'udpcsum') + self.assertRegex(output, 'udp6zerocsumtx') + self.assertRegex(output, 'udp6zerocsumrx') + self.assertRegex(output, 'remcsumtx') + self.assertRegex(output, 'remcsumrx') + self.assertRegex(output, 'gbp') + + output = check_output('bridge fdb show dev vxlan99') + print(output) + self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent') + self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent') + self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent') + + output = check_output(*networkctl_cmd, 'status', 'vxlan99') + print(output) + self.assertRegex(output, 'VNI: 999') + self.assertRegex(output, 'Destination Port: 5555') + self.assertRegex(output, 'Underlying Device: test1') + + def test_macsec(self): + copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key', + 'macsec.network', '12-dummy.netdev') + start_networkd() + + self.wait_online(['dummy98:degraded', 'macsec99:routable']) + + output = check_output('ip -d link show macsec99') + print(output) + self.assertRegex(output, 'macsec99@dummy98') + self.assertRegex(output, 'macsec sci [0-9a-f]*000b') + self.assertRegex(output, 'encrypt on') + + output = check_output('ip macsec show macsec99') + print(output) + self.assertRegex(output, 'encrypt on') + self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1') + self.assertRegex(output, '0: PN [0-9]*, state on, key 01000000000000000000000000000000') + self.assertRegex(output, '1: PN [0-9]*, state on, key 02030000000000000000000000000000') + self.assertRegex(output, 'RXSC: c619528fe6a00100, state on') + self.assertRegex(output, '0: PN [0-9]*, state on, key 02030405000000000000000000000000') + self.assertRegex(output, '1: PN [0-9]*, state on, key 02030405060000000000000000000000') + self.assertRegex(output, '2: PN [0-9]*, state off, key 02030405060700000000000000000000') + self.assertRegex(output, '3: PN [0-9]*, state off, key 02030405060708000000000000000000') + self.assertNotRegex(output, 'key 02030405067080900000000000000000') + self.assertRegex(output, 'RXSC: 8c16456c83a90002, state on') + self.assertRegex(output, '0: PN [0-9]*, state off, key 02030400000000000000000000000000') + + def test_nlmon(self): + copy_unit_to_networkd_unit_path('25-nlmon.netdev', 'netdev-link-local-addressing-yes.network') + start_networkd() + + self.wait_online(['nlmon99:carrier']) + +class NetworkdL2TPTests(unittest.TestCase, Utilities): + + links =[ + 'l2tp-ses1', + 'l2tp-ses2', + 'l2tp-ses3', + 'l2tp-ses4', + 'test1'] + + units = [ + '11-dummy.netdev', + '25-l2tp-dummy.network', + '25-l2tp.network', + '25-l2tp-ip.netdev', + '25-l2tp-udp.netdev'] + + l2tp_tunnel_ids = [ '10' ] + + def setUp(self): + remove_l2tp_tunnels(self.l2tp_tunnel_ids) + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_l2tp_tunnels(self.l2tp_tunnel_ids) + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + @expectedFailureIfModuleIsNotAvailable('l2tp_eth') + def test_l2tp_udp(self): + copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', + '25-l2tp-udp.netdev', '25-l2tp.network') + start_networkd() + + self.wait_online(['test1:routable', 'l2tp-ses1:degraded', 'l2tp-ses2:degraded']) + + output = check_output('ip l2tp show tunnel tunnel_id 10') + print(output) + self.assertRegex(output, "Tunnel 10, encap UDP") + self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101") + self.assertRegex(output, "Peer tunnel 11") + self.assertRegex(output, "UDP source / dest ports: 3000/4000") + self.assertRegex(output, "UDP checksum: enabled") + + output = check_output('ip l2tp show session tid 10 session_id 15') + print(output) + self.assertRegex(output, "Session 15 in tunnel 10") + self.assertRegex(output, "Peer session 16, tunnel 11") + self.assertRegex(output, "interface name: l2tp-ses1") + + output = check_output('ip l2tp show session tid 10 session_id 17') + print(output) + self.assertRegex(output, "Session 17 in tunnel 10") + self.assertRegex(output, "Peer session 18, tunnel 11") + self.assertRegex(output, "interface name: l2tp-ses2") + + @expectedFailureIfModuleIsNotAvailable('l2tp_ip') + def test_l2tp_ip(self): + copy_unit_to_networkd_unit_path('11-dummy.netdev', '25-l2tp-dummy.network', + '25-l2tp-ip.netdev', '25-l2tp.network') + start_networkd() + + self.wait_online(['test1:routable', 'l2tp-ses3:degraded', 'l2tp-ses4:degraded']) + + output = check_output('ip l2tp show tunnel tunnel_id 10') + print(output) + self.assertRegex(output, "Tunnel 10, encap IP") + self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101") + self.assertRegex(output, "Peer tunnel 12") + + output = check_output('ip l2tp show session tid 10 session_id 25') + print(output) + self.assertRegex(output, "Session 25 in tunnel 10") + self.assertRegex(output, "Peer session 26, tunnel 12") + self.assertRegex(output, "interface name: l2tp-ses3") + + output = check_output('ip l2tp show session tid 10 session_id 27') + print(output) + self.assertRegex(output, "Session 27 in tunnel 10") + self.assertRegex(output, "Peer session 28, tunnel 12") + self.assertRegex(output, "interface name: l2tp-ses4") + +class NetworkdNetworkTests(unittest.TestCase, Utilities): + links = [ + 'bond199', + 'dummy98', + 'dummy99', + 'gretun97', + 'ip6gretun97', + 'test1', + 'veth99', + ] + + units = [ + '11-dummy.netdev', + '12-dummy.netdev', + '23-active-slave.network', + '24-keep-configuration-static.network', + '24-search-domain.network', + '25-address-link-section.network', + '25-address-preferred-lifetime-zero.network', + '25-address-static.network', + '25-bind-carrier.network', + '25-bond-active-backup-slave.netdev', + '25-fibrule-invert.network', + '25-fibrule-port-range.network', + '25-gre-tunnel-remote-any.netdev', + '25-ip6gre-tunnel-remote-any.netdev', + '25-ipv6-address-label-section.network', + '25-link-local-addressing-no.network', + '25-link-local-addressing-yes.network', + '25-link-section-unmanaged.network', + '25-neighbor-section.network', + '25-neighbor-next.network', + '25-neighbor-ipv6.network', + '25-neighbor-ip-dummy.network', + '25-neighbor-ip.network', + '25-nexthop.network', + '25-qdisc.network', + '25-route-ipv6-src.network', + '25-route-static.network', + '25-gateway-static.network', + '25-gateway-next-static.network', + '25-sysctl-disable-ipv6.network', + '25-sysctl.network', + '25-veth-peer.network', + '25-veth.netdev', + '26-link-local-addressing-ipv6.network', + 'configure-without-carrier.network', + 'routing-policy-rule-dummy98.network', + 'routing-policy-rule-test1.network'] + + routing_policy_rule_tables = ['7', '8', '9'] + routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']] + + def setUp(self): + remove_routing_policy_rule_tables(self.routing_policy_rule_tables) + remove_routes(self.routes) + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_routing_policy_rule_tables(self.routing_policy_rule_tables) + remove_routes(self.routes) + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_address_static(self): + copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev') + start_networkd() + + self.wait_online(['dummy98:routable']) + + output = check_output('ip -4 address show dev dummy98') + print(output) + self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98') + self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98') + self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98') + + # invalid sections + self.assertNotRegex(output, '10.10.0.1/16') + self.assertNotRegex(output, '10.10.0.2/16') + + output = check_output('ip -4 address show dev dummy98 label 32') + self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32') + + output = check_output('ip -4 address show dev dummy98 label 33') + self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33') + + output = check_output('ip -4 address show dev dummy98 label 34') + self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34') + + output = check_output('ip -4 address show dev dummy98 label 35') + self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35') + + output = check_output('ip -6 address show dev dummy98') + print(output) + self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global') + self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global') + self.assertRegex(output, 'inet6 2001:db8:0:f102::15/64 scope global') + self.assertRegex(output, 'inet6 2001:db8:0:f102::16/64 scope global') + self.assertRegex(output, 'inet6 2001:db8:0:f103::20 peer 2001:db8:0:f103::10/128 scope global') + self.assertRegex(output, 'inet6 fd[0-9a-f:]*1/64 scope global') + + def test_address_preferred_lifetime_zero_ipv6(self): + copy_unit_to_networkd_unit_path('25-address-preferred-lifetime-zero.network', '12-dummy.netdev') + start_networkd(5) + + self.wait_online(['dummy98:routable']) + + output = check_output('ip address show dummy98') + print(output) + self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98') + self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global') + + output = check_output('ip route show dev dummy98') + print(output) + self.assertRegex(output, 'default via 20.20.20.1 proto static') + + def test_configure_without_carrier(self): + copy_unit_to_networkd_unit_path('configure-without-carrier.network', '11-dummy.netdev') + start_networkd() + self.wait_online(['test1:routable']) + + output = check_output(*networkctl_cmd, 'status', 'test1') + print(output) + self.assertRegex(output, '192.168.0.15') + self.assertRegex(output, '192.168.0.1') + self.assertRegex(output, 'routable') + + def test_routing_policy_rule(self): + copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev') + start_networkd() + self.wait_online(['test1:degraded']) + + output = check_output('ip rule list iif test1 priority 111') + print(output) + self.assertRegex(output, '111:') + self.assertRegex(output, 'from 192.168.100.18') + self.assertRegex(output, r'tos (0x08|throughput)\s') + self.assertRegex(output, 'iif test1') + self.assertRegex(output, 'oif test1') + self.assertRegex(output, 'lookup 7') + + output = check_output('ip rule list iif test1 priority 101') + print(output) + self.assertRegex(output, '101:') + self.assertRegex(output, 'from all') + self.assertRegex(output, 'iif test1') + self.assertRegex(output, 'lookup 9') + + output = check_output('ip -6 rule list iif test1 priority 100') + print(output) + self.assertRegex(output, '100:') + self.assertRegex(output, 'from all') + self.assertRegex(output, 'iif test1') + self.assertRegex(output, 'lookup 8') + + output = check_output('ip -6 rule list iif test1 priority 101') + print(output) + self.assertRegex(output, '101:') + self.assertRegex(output, 'from all') + self.assertRegex(output, 'iif test1') + self.assertRegex(output, 'lookup 9') + + def test_routing_policy_rule_issue_11280(self): + copy_unit_to_networkd_unit_path('routing-policy-rule-test1.network', '11-dummy.netdev', + 'routing-policy-rule-dummy98.network', '12-dummy.netdev') + + for trial in range(3): + # Remove state files only first time + start_networkd(3) + self.wait_online(['test1:degraded', 'dummy98:degraded']) + time.sleep(1) + + output = check_output('ip rule list table 7') + print(output) + self.assertRegex(output, '111: from 192.168.100.18 tos (0x08|throughput) iif test1 oif test1 lookup 7') + + output = check_output('ip rule list table 8') + print(output) + self.assertRegex(output, '112: from 192.168.101.18 tos (0x08|throughput) iif dummy98 oif dummy98 lookup 8') + + stop_networkd(remove_state_files=False) + + @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable() + def test_routing_policy_rule_port_range(self): + copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev') + start_networkd() + self.wait_online(['test1:degraded']) + + output = check_output('ip rule') + print(output) + self.assertRegex(output, '111') + self.assertRegex(output, 'from 192.168.100.18') + self.assertRegex(output, '1123-1150') + self.assertRegex(output, '3224-3290') + self.assertRegex(output, 'tcp') + self.assertRegex(output, 'lookup 7') + + @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable() + def test_routing_policy_rule_invert(self): + copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev') + start_networkd() + self.wait_online(['test1:degraded']) + + output = check_output('ip rule') + print(output) + self.assertRegex(output, '111') + self.assertRegex(output, 'not.*?from.*?192.168.100.18') + self.assertRegex(output, 'tcp') + self.assertRegex(output, 'lookup 7') + + def test_route_static(self): + copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output(*networkctl_cmd, 'status', 'dummy98', env=env) + print(output) + + print('### ip -6 route show dev dummy98') + output = check_output('ip -6 route show dev dummy98') + print(output) + self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static') + self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel') + + print('### ip -6 route show dev dummy98 default') + output = check_output('ip -6 route show dev dummy98 default') + print(output) + self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium') + + print('### ip -4 route show dev dummy98') + output = check_output('ip -4 route show dev dummy98') + print(output) + self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58') + self.assertRegex(output, '149.10.124.64 proto static scope link') + self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048') + self.assertRegex(output, '192.168.1.1 proto static initcwnd 20') + self.assertRegex(output, '192.168.1.2 proto static initrwnd 30') + self.assertRegex(output, 'multicast 149.10.123.4 proto static') + + print('### ip -4 route show dev dummy98 default') + output = check_output('ip -4 route show dev dummy98 default') + print(output) + self.assertRegex(output, 'default via 149.10.125.65 proto static onlink') + self.assertRegex(output, 'default via 149.10.124.64 proto static') + self.assertRegex(output, 'default proto static') + + print('### ip -4 route show table local dev dummy98') + output = check_output('ip -4 route show table local dev dummy98') + print(output) + self.assertRegex(output, 'local 149.10.123.1 proto static scope host') + self.assertRegex(output, 'anycast 149.10.123.2 proto static scope link') + self.assertRegex(output, 'broadcast 149.10.123.3 proto static scope link') + + print('### ip route show type blackhole') + output = check_output('ip route show type blackhole') + print(output) + self.assertRegex(output, 'blackhole 202.54.1.2 proto static') + + print('### ip route show type unreachable') + output = check_output('ip route show type unreachable') + print(output) + self.assertRegex(output, 'unreachable 202.54.1.3 proto static') + + print('### ip route show type prohibit') + output = check_output('ip route show type prohibit') + print(output) + self.assertRegex(output, 'prohibit 202.54.1.4 proto static') + + def test_gateway_reconfigure(self): + copy_unit_to_networkd_unit_path('25-gateway-static.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:routable']) + print('### ip -4 route show dev dummy98 default') + output = check_output('ip -4 route show dev dummy98 default') + print(output) + self.assertRegex(output, 'default via 149.10.124.59 proto static') + self.assertNotRegex(output, '149.10.124.60') + + remove_unit_from_networkd_path(['25-gateway-static.network']) + copy_unit_to_networkd_unit_path('25-gateway-next-static.network') + restart_networkd(3) + self.wait_online(['dummy98:routable']) + print('### ip -4 route show dev dummy98 default') + output = check_output('ip -4 route show dev dummy98 default') + print(output) + self.assertNotRegex(output, '149.10.124.59') + self.assertRegex(output, 'default via 149.10.124.60 proto static') + + def test_ip_route_ipv6_src_route(self): + # a dummy device does not make the addresses go through tentative state, so we + # reuse a bond from an earlier test, which does make the addresses go through + # tentative state, and do our test on that + copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:enslaved', 'bond199:routable']) + + output = check_output('ip -6 route list dev bond199') + print(output) + self.assertRegex(output, 'abcd::/16') + self.assertRegex(output, 'src') + self.assertRegex(output, '2001:1234:56:8f63::2') + + def test_ip_link_mac_address(self): + copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:degraded']) + + output = check_output('ip link show dummy98') + print(output) + self.assertRegex(output, '00:01:02:aa:bb:cc') + + def test_ip_link_unmanaged(self): + copy_unit_to_networkd_unit_path('25-link-section-unmanaged.network', '12-dummy.netdev') + start_networkd(5) + + self.check_link_exists('dummy98') + + self.check_operstate('dummy98', 'off', setup_state='unmanaged') + + def test_ipv6_address_label(self): + copy_unit_to_networkd_unit_path('25-ipv6-address-label-section.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:degraded']) + + output = check_output('ip addrlabel list') + print(output) + self.assertRegex(output, '2004:da8:1::/64') + + def test_neighbor_section(self): + copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:degraded'], timeout='40s') + + print('### ip neigh list dev dummy98') + output = check_output('ip neigh list dev dummy98') + print(output) + self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT') + self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT') + + def test_neighbor_reconfigure(self): + copy_unit_to_networkd_unit_path('25-neighbor-section.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:degraded'], timeout='40s') + + print('### ip neigh list dev dummy98') + output = check_output('ip neigh list dev dummy98') + print(output) + self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT') + self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT') + + remove_unit_from_networkd_path(['25-neighbor-section.network']) + copy_unit_to_networkd_unit_path('25-neighbor-next.network') + restart_networkd(3) + self.wait_online(['dummy98:degraded'], timeout='40s') + print('### ip neigh list dev dummy98') + output = check_output('ip neigh list dev dummy98') + print(output) + self.assertNotRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT') + self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:66.*PERMANENT') + self.assertNotRegex(output, '2004:da8:1::1.*PERMANENT') + + def test_neighbor_gre(self): + copy_unit_to_networkd_unit_path('25-neighbor-ip.network', '25-neighbor-ipv6.network', '25-neighbor-ip-dummy.network', + '12-dummy.netdev', '25-gre-tunnel-remote-any.netdev', '25-ip6gre-tunnel-remote-any.netdev') + start_networkd() + self.wait_online(['dummy98:degraded', 'gretun97:routable', 'ip6gretun97:routable'], timeout='40s') + + output = check_output('ip neigh list dev gretun97') + print(output) + self.assertRegex(output, '10.0.0.22 lladdr 10.65.223.239 PERMANENT') + + output = check_output('ip neigh list dev ip6gretun97') + print(output) + self.assertRegex(output, '2001:db8:0:f102::17 lladdr 2a:?00:ff:?de:45:?67:ed:?de:[0:]*:49:?88 PERMANENT') + + def test_link_local_addressing(self): + copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev', + '25-link-local-addressing-no.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['test1:degraded', 'dummy98:carrier']) + + output = check_output('ip address show dev test1') + print(output) + self.assertRegex(output, 'inet .* scope link') + self.assertRegex(output, 'inet6 .* scope link') + + output = check_output('ip address show dev dummy98') + print(output) + self.assertNotRegex(output, 'inet6* .* scope link') + + ''' + Documentation/networking/ip-sysctl.txt + + addr_gen_mode - INTEGER + Defines how link-local and autoconf addresses are generated. + + 0: generate address based on EUI64 (default) + 1: do no generate a link-local address, use EUI64 for addresses generated + from autoconf + 2: generate stable privacy addresses, using the secret from + stable_secret (RFC7217) + 3: generate stable privacy addresses, using a random secret if unset + ''' + + test1_addr_gen_mode = '' + if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')): + with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f: + try: + f.readline() + except IOError: + # if stable_secret is unset, then EIO is returned + test1_addr_gen_mode = '0' + else: + test1_addr_gen_mode = '2' + else: + test1_addr_gen_mode = '0' + + if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')): + self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode) + + if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')): + self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1') + + def test_link_local_addressing_remove_ipv6ll(self): + copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:degraded']) + + output = check_output('ip address show dev dummy98') + print(output) + self.assertRegex(output, 'inet6 .* scope link') + + copy_unit_to_networkd_unit_path('25-link-local-addressing-no.network') + restart_networkd(1) + self.wait_online(['dummy98:carrier']) + + output = check_output('ip address show dev dummy98') + print(output) + self.assertNotRegex(output, 'inet6* .* scope link') + + def test_sysctl(self): + copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:degraded']) + + self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'forwarding'), '1') + self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'use_tempaddr'), '2') + self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'dad_transmits'), '3') + self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'hop_limit'), '5') + self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'proxy_ndp'), '1') + self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1') + self.assertEqual(read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1') + + def test_sysctl_disable_ipv6(self): + copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev') + + print('## Disable ipv6') + check_output('sysctl net.ipv6.conf.all.disable_ipv6=1') + check_output('sysctl net.ipv6.conf.default.disable_ipv6=1') + + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('ip -4 address show dummy98') + print(output) + self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98') + output = check_output('ip -6 address show dummy98') + print(output) + self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global') + self.assertRegex(output, 'inet6 .* scope link') + output = check_output('ip -4 route show dev dummy98') + print(output) + self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4') + output = check_output('ip -6 route show dev dummy98') + print(output) + self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static') + + check_output('ip link del dummy98') + + print('## Enable ipv6') + check_output('sysctl net.ipv6.conf.all.disable_ipv6=0') + check_output('sysctl net.ipv6.conf.default.disable_ipv6=0') + + restart_networkd(3) + self.wait_online(['dummy98:routable']) + + output = check_output('ip -4 address show dummy98') + print(output) + self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98') + output = check_output('ip -6 address show dummy98') + print(output) + self.assertRegex(output, 'inet6 2607:5300:203:3906::/64 scope global') + self.assertRegex(output, 'inet6 .* scope link') + output = check_output('ip -4 route show dev dummy98') + print(output) + self.assertEqual(output, '10.2.0.0/16 proto kernel scope link src 10.2.3.4') + output = check_output('ip -6 route show dev dummy98') + print(output) + self.assertRegex(output, 'default via 2607:5300:203:39ff:ff:ff:ff:ff proto static') + + def test_bind_carrier(self): + copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev') + start_networkd() + self.wait_online(['test1:routable']) + + check_output('ip link add dummy98 type dummy') + check_output('ip link set dummy98 up') + time.sleep(2) + output = check_output('ip address show test1') + print(output) + self.assertRegex(output, 'UP,LOWER_UP') + self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1') + self.check_operstate('test1', 'routable') + + check_output('ip link add dummy99 type dummy') + check_output('ip link set dummy99 up') + time.sleep(2) + output = check_output('ip address show test1') + print(output) + self.assertRegex(output, 'UP,LOWER_UP') + self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1') + self.check_operstate('test1', 'routable') + + check_output('ip link del dummy98') + time.sleep(2) + output = check_output('ip address show test1') + print(output) + self.assertRegex(output, 'UP,LOWER_UP') + self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1') + self.check_operstate('test1', 'routable') + + check_output('ip link del dummy99') + time.sleep(2) + output = check_output('ip address show test1') + print(output) + self.assertNotRegex(output, 'UP,LOWER_UP') + self.assertRegex(output, 'DOWN') + self.assertNotRegex(output, '192.168.10') + self.check_operstate('test1', 'off') + + check_output('ip link add dummy98 type dummy') + check_output('ip link set dummy98 up') + time.sleep(2) + output = check_output('ip address show test1') + print(output) + self.assertRegex(output, 'UP,LOWER_UP') + self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1') + self.check_operstate('test1', 'routable') + + def test_domain(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output(*networkctl_cmd, 'status', 'dummy98', env=env) + print(output) + self.assertRegex(output, 'Address: 192.168.42.100') + self.assertRegex(output, 'DNS: 192.168.42.1') + self.assertRegex(output, 'Search Domains: one') + + def test_keep_configuration_static(self): + check_output('systemctl stop systemd-networkd') + + check_output('ip link add name dummy98 type dummy') + check_output('ip address add 10.1.2.3/16 dev dummy98') + check_output('ip address add 10.2.3.4/16 dev dummy98 valid_lft 600 preferred_lft 500') + output = check_output('ip address show dummy98') + print(output) + self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98') + self.assertRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98') + output = check_output('ip route show dev dummy98') + print(output) + + copy_unit_to_networkd_unit_path('24-keep-configuration-static.network') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output('ip address show dummy98') + print(output) + self.assertRegex(output, 'inet 10.1.2.3/16 scope global dummy98') + self.assertNotRegex(output, 'inet 10.2.3.4/16 scope global dynamic dummy98') + + @expectedFailureIfNexthopIsNotAvailable() + def test_nexthop(self): + copy_unit_to_networkd_unit_path('25-nexthop.network', '25-veth.netdev', '25-veth-peer.network') + start_networkd() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip nexthop list dev veth99') + print(output) + self.assertRegex(output, '192.168.5.1') + + def test_qdisc(self): + copy_unit_to_networkd_unit_path('25-qdisc.network', '12-dummy.netdev') + start_networkd() + + self.wait_online(['dummy98:routable']) + + output = check_output('tc qdisc show dev dummy98') + print(output) + self.assertRegex(output, 'limit 100 delay 50.0ms 10.0ms loss 20%') + self.assertRegex(output, 'limit 200 delay 100.0ms 13.0ms loss 20.5%') + +class NetworkdStateFileTests(unittest.TestCase, Utilities): + links = [ + 'dummy98', + ] + + units = [ + '12-dummy.netdev', + 'state-file-tests.network', + ] + + def setUp(self): + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_state_file(self): + copy_unit_to_networkd_unit_path('12-dummy.netdev', 'state-file-tests.network') + start_networkd() + self.wait_online(['dummy98:routable']) + + output = check_output(*networkctl_cmd, '--no-legend', 'list', 'dummy98', env=env) + print(output) + ifindex = output.split()[0] + + path = os.path.join('/run/systemd/netif/links/', ifindex) + self.assertTrue(os.path.exists(path)) + time.sleep(2) + + with open(path) as f: + data = f.read() + self.assertRegex(data, r'ADMIN_STATE=configured') + self.assertRegex(data, r'OPER_STATE=routable') + self.assertRegex(data, r'REQUIRED_FOR_ONLINE=yes') + self.assertRegex(data, r'REQUIRED_OPER_STATE_FOR_ONLINE=routable') + self.assertRegex(data, r'NETWORK_FILE=/run/systemd/network/state-file-tests.network') + self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11') + self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org') + self.assertRegex(data, r'DOMAINS=hogehoge') + self.assertRegex(data, r'ROUTE_DOMAINS=foofoo') + self.assertRegex(data, r'LLMNR=no') + self.assertRegex(data, r'MDNS=yes') + self.assertRegex(data, r'DNSSEC=no') + self.assertRegex(data, r'ADDRESSES=192.168.(10.10|12.12)/24 192.168.(12.12|10.10)/24') + + check_output(*resolvectl_cmd, 'dns', 'dummy98', '10.10.10.12', '10.10.10.13', env=env) + check_output(*resolvectl_cmd, 'domain', 'dummy98', 'hogehogehoge', '~foofoofoo', env=env) + check_output(*resolvectl_cmd, 'llmnr', 'dummy98', 'yes', env=env) + check_output(*resolvectl_cmd, 'mdns', 'dummy98', 'no', env=env) + check_output(*resolvectl_cmd, 'dnssec', 'dummy98', 'yes', env=env) + check_output(*timedatectl_cmd, 'ntp-servers', 'dummy98', '2.fedora.pool.ntp.org', '3.fedora.pool.ntp.org', env=env) + time.sleep(2) + + with open(path) as f: + data = f.read() + self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13') + self.assertRegex(data, r'NTP=2.fedora.pool.ntp.org 3.fedora.pool.ntp.org') + self.assertRegex(data, r'DOMAINS=hogehogehoge') + self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo') + self.assertRegex(data, r'LLMNR=yes') + self.assertRegex(data, r'MDNS=no') + self.assertRegex(data, r'DNSSEC=yes') + + check_output(*timedatectl_cmd, 'revert', 'dummy98', env=env) + time.sleep(2) + + with open(path) as f: + data = f.read() + self.assertRegex(data, r'DNS=10.10.10.12 10.10.10.13') + self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org') + self.assertRegex(data, r'DOMAINS=hogehogehoge') + self.assertRegex(data, r'ROUTE_DOMAINS=foofoofoo') + self.assertRegex(data, r'LLMNR=yes') + self.assertRegex(data, r'MDNS=no') + self.assertRegex(data, r'DNSSEC=yes') + + check_output(*resolvectl_cmd, 'revert', 'dummy98', env=env) + time.sleep(2) + + with open(path) as f: + data = f.read() + self.assertRegex(data, r'DNS=10.10.10.10 10.10.10.11') + self.assertRegex(data, r'NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org') + self.assertRegex(data, r'DOMAINS=hogehoge') + self.assertRegex(data, r'ROUTE_DOMAINS=foofoo') + self.assertRegex(data, r'LLMNR=no') + self.assertRegex(data, r'MDNS=yes') + self.assertRegex(data, r'DNSSEC=no') + +class NetworkdBondTests(unittest.TestCase, Utilities): + links = [ + 'bond199', + 'bond99', + 'dummy98', + 'test1'] + + units = [ + '11-dummy.netdev', + '12-dummy.netdev', + '23-active-slave.network', + '23-bond199.network', + '23-primary-slave.network', + '25-bond-active-backup-slave.netdev', + '25-bond.netdev', + 'bond99.network', + 'bond-slave.network'] + + def setUp(self): + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_bond_active_slave(self): + copy_unit_to_networkd_unit_path('23-active-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:enslaved', 'bond199:degraded']) + + output = check_output('ip -d link show bond199') + print(output) + self.assertRegex(output, 'active_slave dummy98') + + def test_bond_primary_slave(self): + copy_unit_to_networkd_unit_path('23-primary-slave.network', '23-bond199.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev') + start_networkd() + self.wait_online(['dummy98:enslaved', 'bond199:degraded']) + + output = check_output('ip -d link show bond199') + print(output) + self.assertRegex(output, 'primary dummy98') + + def test_bond_operstate(self): + copy_unit_to_networkd_unit_path('25-bond.netdev', '11-dummy.netdev', '12-dummy.netdev', + 'bond99.network','bond-slave.network') + start_networkd() + self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bond99:routable']) + + output = check_output('ip -d link show dummy98') + print(output) + self.assertRegex(output, 'SLAVE,UP,LOWER_UP') + + output = check_output('ip -d link show test1') + print(output) + self.assertRegex(output, 'SLAVE,UP,LOWER_UP') + + output = check_output('ip -d link show bond99') + print(output) + self.assertRegex(output, 'MASTER,UP,LOWER_UP') + + self.check_operstate('dummy98', 'enslaved') + self.check_operstate('test1', 'enslaved') + self.check_operstate('bond99', 'routable') + + check_output('ip link set dummy98 down') + time.sleep(2) + + self.check_operstate('dummy98', 'off') + self.check_operstate('test1', 'enslaved') + self.check_operstate('bond99', 'degraded-carrier') + + check_output('ip link set dummy98 up') + time.sleep(2) + + self.check_operstate('dummy98', 'enslaved') + self.check_operstate('test1', 'enslaved') + self.check_operstate('bond99', 'routable') + + check_output('ip link set dummy98 down') + check_output('ip link set test1 down') + time.sleep(2) + + self.check_operstate('dummy98', 'off') + self.check_operstate('test1', 'off') + + for trial in range(30): + if trial > 0: + time.sleep(1) + output = check_output('ip address show bond99') + print(output) + if get_operstate('bond99') == 'no-carrier': + break + else: + # Huh? Kernel does not recognize that all slave interfaces are down? + # Let's confirm that networkd's operstate is consistent with ip's result. + self.assertNotRegex(output, 'NO-CARRIER') + +class NetworkdBridgeTests(unittest.TestCase, Utilities): + links = [ + 'bridge99', + 'dummy98', + 'test1'] + + units = [ + '11-dummy.netdev', + '12-dummy.netdev', + '26-bridge.netdev', + '26-bridge-slave-interface-1.network', + '26-bridge-slave-interface-2.network', + '26-bridge-vlan-master.network', + '26-bridge-vlan-slave.network', + 'bridge99-ignore-carrier-loss.network', + 'bridge99.network'] + + routing_policy_rule_tables = ['100'] + + def setUp(self): + remove_routing_policy_rule_tables(self.routing_policy_rule_tables) + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_routing_policy_rule_tables(self.routing_policy_rule_tables) + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_bridge_vlan(self): + copy_unit_to_networkd_unit_path('11-dummy.netdev', '26-bridge-vlan-slave.network', + '26-bridge.netdev', '26-bridge-vlan-master.network') + start_networkd() + self.wait_online(['test1:enslaved', 'bridge99:degraded']) + + output = check_output('bridge vlan show dev test1') + print(output) + self.assertNotRegex(output, '4063') + for i in range(4064, 4095): + self.assertRegex(output, f'{i}') + self.assertNotRegex(output, '4095') + + output = check_output('bridge vlan show dev bridge99') + print(output) + self.assertNotRegex(output, '4059') + for i in range(4060, 4095): + self.assertRegex(output, f'{i}') + self.assertNotRegex(output, '4095') + + def test_bridge_property(self): + copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', + '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network', + 'bridge99.network') + start_networkd() + self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable']) + + output = check_output('ip -d link show test1') + print(output) + self.assertRegex(output, 'master') + self.assertRegex(output, 'bridge') + + output = check_output('ip -d link show dummy98') + print(output) + self.assertRegex(output, 'master') + self.assertRegex(output, 'bridge') + + output = check_output('ip addr show bridge99') + print(output) + self.assertRegex(output, '192.168.0.15/24') + + output = check_output('bridge -d link show dummy98') + print(output) + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400') + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1') + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_fast_leave'), '1') + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'unicast_flood'), '1') + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_flood'), '0') + # CONFIG_BRIDGE_IGMP_SNOOPING=y + if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')): + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1') + if (os.path.exists('/sys/devices/virtual/net/bridge99/lower_dummy98/brport/neigh_suppress')): + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'neigh_suppress'), '1') + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'learning'), '0') + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'priority'), '23') + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'bpdu_guard'), '1') + self.assertEqual(read_bridge_port_attr('bridge99', 'dummy98', 'root_block'), '1') + + output = check_output('bridge -d link show test1') + print(output) + self.assertEqual(read_bridge_port_attr('bridge99', 'test1', 'priority'), '0') + + check_output('ip address add 192.168.0.16/24 dev bridge99') + time.sleep(1) + + output = check_output('ip addr show bridge99') + print(output) + self.assertRegex(output, '192.168.0.16/24') + + # for issue #6088 + print('### ip -6 route list table all dev bridge99') + output = check_output('ip -6 route list table all dev bridge99') + print(output) + self.assertRegex(output, 'ff00::/8 table local metric 256 pref medium') + + self.assertEqual(call('ip link del test1'), 0) + time.sleep(3) + + self.check_operstate('bridge99', 'degraded-carrier') + + check_output('ip link del dummy98') + time.sleep(3) + + self.check_operstate('bridge99', 'no-carrier') + + output = check_output('ip address show bridge99') + print(output) + self.assertRegex(output, 'NO-CARRIER') + self.assertNotRegex(output, '192.168.0.15/24') + self.assertNotRegex(output, '192.168.0.16/24') + + print('### ip -6 route list table all dev bridge99') + output = check_output('ip -6 route list table all dev bridge99') + print(output) + self.assertRegex(output, 'ff00::/8 table local metric 256 (linkdown )?pref medium') + + def test_bridge_ignore_carrier_loss(self): + copy_unit_to_networkd_unit_path('11-dummy.netdev', '12-dummy.netdev', '26-bridge.netdev', + '26-bridge-slave-interface-1.network', '26-bridge-slave-interface-2.network', + 'bridge99-ignore-carrier-loss.network') + start_networkd() + self.wait_online(['dummy98:enslaved', 'test1:enslaved', 'bridge99:routable']) + + check_output('ip address add 192.168.0.16/24 dev bridge99') + time.sleep(1) + + check_output('ip link del test1') + check_output('ip link del dummy98') + time.sleep(3) + + output = check_output('ip address show bridge99') + print(output) + self.assertRegex(output, 'NO-CARRIER') + self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99') + self.assertRegex(output, 'inet 192.168.0.16/24 scope global secondary bridge99') + + def test_bridge_ignore_carrier_loss_frequent_loss_and_gain(self): + copy_unit_to_networkd_unit_path('26-bridge.netdev', '26-bridge-slave-interface-1.network', + 'bridge99-ignore-carrier-loss.network') + start_networkd() + self.wait_online(['bridge99:no-carrier']) + + for trial in range(4): + check_output('ip link add dummy98 type dummy') + check_output('ip link set dummy98 up') + if trial < 3: + check_output('ip link del dummy98') + + self.wait_online(['bridge99:routable', 'dummy98:enslaved']) + + output = check_output('ip address show bridge99') + print(output) + self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99') + + output = check_output('ip rule list table 100') + print(output) + self.assertEqual(output, '0: from all to 8.8.8.8 lookup 100') + +class NetworkdLLDPTests(unittest.TestCase, Utilities): + links = ['veth99'] + + units = [ + '23-emit-lldp.network', + '24-lldp.network', + '25-veth.netdev'] + + def setUp(self): + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_lldp(self): + copy_unit_to_networkd_unit_path('23-emit-lldp.network', '24-lldp.network', '25-veth.netdev') + start_networkd() + self.wait_online(['veth99:degraded', 'veth-peer:degraded']) + + output = check_output(*networkctl_cmd, 'lldp', env=env) + print(output) + self.assertRegex(output, 'veth-peer') + self.assertRegex(output, 'veth99') + +class NetworkdRATests(unittest.TestCase, Utilities): + links = ['veth99'] + + units = [ + '25-veth.netdev', + 'ipv6-prefix.network', + 'ipv6-prefix-veth.network'] + + def setUp(self): + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_ipv6_prefix_delegation(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6-prefix.network', 'ipv6-prefix-veth.network') + start_networkd() + self.wait_online(['veth99:routable', 'veth-peer:degraded']) + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, '2002:da8:1:0') + +class NetworkdDHCPServerTests(unittest.TestCase, Utilities): + links = ['veth99'] + + units = [ + '25-veth.netdev', + 'dhcp-client.network', + 'dhcp-client-timezone-router.network', + 'dhcp-server.network', + 'dhcp-server-timezone-router.network'] + + def setUp(self): + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_dhcp_server(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client.network', 'dhcp-server.network') + start_networkd() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, '192.168.5.*') + self.assertRegex(output, 'Gateway: 192.168.5.1') + self.assertRegex(output, 'DNS: 192.168.5.1') + self.assertRegex(output, 'NTP: 192.168.5.1') + + def test_emit_router_timezone(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-timezone-router.network', 'dhcp-server-timezone-router.network') + start_networkd() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, 'Gateway: 192.168.5.*') + self.assertRegex(output, '192.168.5.*') + self.assertRegex(output, 'Europe/Berlin') + +class NetworkdDHCPClientTests(unittest.TestCase, Utilities): + links = [ + 'veth99', + 'vrf99'] + + units = [ + '25-veth.netdev', + '25-vrf.netdev', + '25-vrf.network', + 'dhcp-client-anonymize.network', + 'dhcp-client-gateway-onlink-implicit.network', + 'dhcp-client-ipv4-dhcp-settings.network', + 'dhcp-client-ipv4-only-ipv6-disabled.network', + 'dhcp-client-ipv4-only.network', + 'dhcp-client-ipv6-only.network', + 'dhcp-client-ipv6-rapid-commit.network', + 'dhcp-client-keep-configuration-dhcp-on-stop.network', + 'dhcp-client-keep-configuration-dhcp.network', + 'dhcp-client-listen-port.network', + 'dhcp-client-reassign-static-routes-ipv4.network', + 'dhcp-client-reassign-static-routes-ipv6.network', + 'dhcp-client-route-metric.network', + 'dhcp-client-route-table.network', + 'dhcp-client-use-dns-ipv4-and-ra.network', + 'dhcp-client-use-dns-ipv4.network', + 'dhcp-client-use-dns-no.network', + 'dhcp-client-use-dns-yes.network', + 'dhcp-client-use-domains.network', + 'dhcp-client-use-routes-no.network', + 'dhcp-client-vrf.network', + 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network', + 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network', + 'dhcp-client-with-static-address.network', + 'dhcp-client.network', + 'dhcp-server-veth-peer.network', + 'dhcp-v4-server-veth-peer.network', + 'dhcp-client-use-domains.network', + 'static.network'] + + def setUp(self): + stop_dnsmasq(dnsmasq_pid_file) + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + stop_dnsmasq(dnsmasq_pid_file) + remove_lease_file() + remove_log_file() + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_dhcp_client_ipv6_only(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network') + + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, '2600::') + self.assertNotRegex(output, '192.168.5') + + # Confirm that ipv6 token is not set in the kernel + output = check_output('ip token show dev veth99') + print(output) + self.assertRegex(output, 'token :: dev veth99') + + def test_dhcp_client_ipv4_only(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network') + + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7', lease_time='2m') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertNotRegex(output, '2600::') + self.assertRegex(output, '192.168.5') + self.assertRegex(output, '192.168.5.6') + self.assertRegex(output, '192.168.5.7') + + # checking routes to DNS servers + output = check_output('ip route show dev veth99') + print(output) + self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024') + self.assertRegex(output, r'192.168.5.6 proto dhcp scope link src 192.168.5.181 metric 1024') + self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024') + + stop_dnsmasq(dnsmasq_pid_file) + start_dnsmasq(additional_options='--dhcp-option=option:dns-server,192.168.5.1,192.168.5.7,192.168.5.8', lease_time='2m') + + # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120 + print('Wait for the dynamic address to be renewed') + time.sleep(125) + + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertNotRegex(output, '2600::') + self.assertRegex(output, '192.168.5') + self.assertNotRegex(output, '192.168.5.6') + self.assertRegex(output, '192.168.5.7') + self.assertRegex(output, '192.168.5.8') + + # checking routes to DNS servers + output = check_output('ip route show dev veth99') + print(output) + self.assertNotRegex(output, r'192.168.5.6') + self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.181 metric 1024') + self.assertRegex(output, r'192.168.5.7 proto dhcp scope link src 192.168.5.181 metric 1024') + self.assertRegex(output, r'192.168.5.8 proto dhcp scope link src 192.168.5.181 metric 1024') + + def test_dhcp_client_ipv4_ipv6(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network', + 'dhcp-client-ipv4-only.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + # link become 'routable' when at least one protocol provide an valid address. + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, '2600::') + self.assertRegex(output, '192.168.5') + + def test_dhcp_client_settings(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-dhcp-settings.network') + + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + print('## ip address show dev veth99') + output = check_output('ip address show dev veth99') + print(output) + self.assertRegex(output, '12:34:56:78:9a:bc') + self.assertRegex(output, '192.168.5') + self.assertRegex(output, '1492') + + print('## ip route show table main dev veth99') + output = check_output('ip route show table main dev veth99') + print(output) + # See issue #8726 + main_table_is_empty = output == '' + if not main_table_is_empty: + self.assertNotRegex(output, 'proto dhcp') + + print('## ip route show table 211 dev veth99') + output = check_output('ip route show table 211 dev veth99') + print(output) + self.assertRegex(output, 'default via 192.168.5.1 proto dhcp') + if main_table_is_empty: + self.assertRegex(output, '192.168.5.0/24 proto dhcp') + self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp') + self.assertRegex(output, '192.168.5.1 proto dhcp scope link') + + print('## dnsmasq log') + self.assertTrue(search_words_in_dnsmasq_log('vendor class: SusantVendorTest', True)) + self.assertTrue(search_words_in_dnsmasq_log('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc')) + self.assertTrue(search_words_in_dnsmasq_log('client provides name: test-hostname')) + self.assertTrue(search_words_in_dnsmasq_log('26:mtu')) + + def test_dhcp6_client_settings_rapidcommit_true(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip address show dev veth99') + print(output) + self.assertRegex(output, '12:34:56:78:9a:bc') + self.assertTrue(search_words_in_dnsmasq_log('14:rapid-commit', True)) + + def test_dhcp6_client_settings_rapidcommit_false(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-rapid-commit.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip address show dev veth99') + print(output) + self.assertRegex(output, '12:34:56:78:9a:bc') + self.assertFalse(search_words_in_dnsmasq_log('14:rapid-commit', True)) + + def test_dhcp_client_settings_anonymize(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-anonymize.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + self.assertFalse(search_words_in_dnsmasq_log('VendorClassIdentifier=SusantVendorTest', True)) + self.assertFalse(search_words_in_dnsmasq_log('test-hostname')) + self.assertFalse(search_words_in_dnsmasq_log('26:mtu')) + + def test_dhcp_client_listen_port(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq('--dhcp-alternate-port=67,5555') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip -4 address show dev veth99') + print(output) + self.assertRegex(output, '192.168.5.* dynamic') + + def test_dhcp_client_with_static_address(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', + 'dhcp-client-with-static-address.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, r'inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99') + self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global secondary dynamic veth99') + + output = check_output('ip route show dev veth99') + print(output) + self.assertRegex(output, r'default via 192.168.5.1 proto dhcp src 192.168.5.[0-9]* metric 1024') + self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.250') + self.assertRegex(output, r'192.168.5.0/24 via 192.168.5.5 proto dhcp src 192.168.5.[0-9]* metric 1024') + self.assertRegex(output, r'192.168.5.1 proto dhcp scope link src 192.168.5.[0-9]* metric 1024') + + def test_dhcp_route_table_id(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip route show table 12') + print(output) + self.assertRegex(output, 'veth99 proto dhcp') + self.assertRegex(output, '192.168.5.1') + + def test_dhcp_route_metric(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-metric.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip route show dev veth99') + print(output) + self.assertRegex(output, 'metric 24') + + def test_dhcp_client_reassign_static_routes_ipv4(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', + 'dhcp-client-reassign-static-routes-ipv4.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq(lease_time='2m') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + + output = check_output('ip route show dev veth99') + print(output) + self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*') + self.assertRegex(output, r'192.168.5.0/24 proto static') + self.assertRegex(output, r'192.168.6.0/24 proto static') + self.assertRegex(output, r'192.168.7.0/24 proto static') + + stop_dnsmasq(dnsmasq_pid_file) + start_dnsmasq(ipv4_range='192.168.5.210,192.168.5.220', lease_time='2m') + + # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120 + print('Wait for the dynamic address to be renewed') + time.sleep(125) + + self.wait_online(['veth99:routable']) + + output = check_output('ip route show dev veth99') + print(output) + self.assertRegex(output, r'192.168.5.0/24 proto kernel scope link src 192.168.5.[0-9]*') + self.assertRegex(output, r'192.168.5.0/24 proto static') + self.assertRegex(output, r'192.168.6.0/24 proto static') + self.assertRegex(output, r'192.168.7.0/24 proto static') + + def test_dhcp_client_reassign_static_routes_ipv6(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', + 'dhcp-client-reassign-static-routes-ipv6.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq(lease_time='2m') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, r'inet6 2600::[0-9a-f]*/128 scope global (noprefixroute dynamic|dynamic noprefixroute)') + + output = check_output('ip -6 route show dev veth99') + print(output) + self.assertRegex(output, r'2600::/64 proto ra metric 1024') + self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium') + + stop_dnsmasq(dnsmasq_pid_file) + start_dnsmasq(ipv6_range='2600::30,2600::40', lease_time='2m') + + # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120 + print('Wait for the dynamic address to be renewed') + time.sleep(125) + + self.wait_online(['veth99:routable']) + + output = check_output('ip -6 route show dev veth99') + print(output) + self.assertRegex(output, r'2600::/64 proto ra metric 1024') + self.assertRegex(output, r'2600:0:0:1::/64 proto static metric 1024 pref medium') + + def test_dhcp_keep_configuration_dhcp(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq(lease_time='2m') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, r'192.168.5.*') + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, r'192.168.5.*') + + # Stopping dnsmasq as networkd won't be allowed to renew the DHCP lease. + stop_dnsmasq(dnsmasq_pid_file) + + # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120 + print('Wait for the dynamic address to be expired') + time.sleep(125) + + print('The lease address should be kept after lease expired') + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, r'192.168.5.*') + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, r'192.168.5.*') + + check_output('systemctl stop systemd-networkd') + + print('The lease address should be kept after networkd stopped') + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, r'192.168.5.*') + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, r'192.168.5.*') + + start_networkd(3) + self.wait_online(['veth-peer:routable']) + + print('Still the lease address should be kept after networkd restarted') + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, r'192.168.5.*') + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, r'192.168.5.*') + + def test_dhcp_keep_configuration_dhcp_on_stop(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-keep-configuration-dhcp-on-stop.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq(lease_time='2m') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, r'192.168.5.*') + + stop_dnsmasq(dnsmasq_pid_file) + check_output('systemctl stop systemd-networkd') + + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, r'192.168.5.*') + + restart_networkd(3) + self.wait_online(['veth-peer:routable']) + + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertNotRegex(output, r'192.168.5.*') + + def test_dhcp_client_reuse_address_as_static(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + # link become 'routable' when at least one protocol provide an valid address. + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') + + output = check_output('ip address show dev veth99 scope global') + print(output) + self.assertRegex(output, '192.168.5') + self.assertRegex(output, '2600::') + + ipv4_address = re.search(r'192.168.5.[0-9]*/24', output) + ipv6_address = re.search(r'2600::[0-9a-f:]*/128', output) + static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()]) + print(static_network) + + remove_unit_from_networkd_path(['dhcp-client.network']) + + with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f: + f.write(static_network) + + # When networkd started, the links are already configured, so let's wait for 5 seconds + # the links to be re-configured. + restart_networkd(5) + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip -4 address show dev veth99 scope global') + print(output) + self.assertRegex(output, '192.168.5') + self.assertRegex(output, 'valid_lft forever preferred_lft forever') + + output = check_output('ip -6 address show dev veth99 scope global') + print(output) + self.assertRegex(output, '2600::') + self.assertRegex(output, 'valid_lft forever preferred_lft forever') + + @expectedFailureIfModuleIsNotAvailable('vrf') + def test_dhcp_client_vrf(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-vrf.network', + '25-vrf.netdev', '25-vrf.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable', 'vrf99:carrier']) + + # link become 'routable' when at least one protocol provide an valid address. + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') + + print('## ip -d link show dev vrf99') + output = check_output('ip -d link show dev vrf99') + print(output) + self.assertRegex(output, 'vrf table 42') + + print('## ip address show vrf vrf99') + output = check_output('ip address show vrf vrf99') + print(output) + self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99') + self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)') + self.assertRegex(output, 'inet6 .* scope link') + + print('## ip address show dev veth99') + output = check_output('ip address show dev veth99') + print(output) + self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99') + self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + self.assertRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)') + self.assertRegex(output, 'inet6 .* scope link') + + print('## ip route show vrf vrf99') + output = check_output('ip route show vrf vrf99') + print(output) + self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.') + self.assertRegex(output, '169.254.0.0/16 dev veth99 proto kernel scope link src 169.254') + self.assertRegex(output, '192.168.5.0/24 dev veth99 proto kernel scope link src 192.168.5') + self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 dev veth99 proto dhcp') + self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5') + + print('## ip route show table main dev veth99') + output = check_output('ip route show table main dev veth99') + print(output) + self.assertEqual(output, '') + + def test_dhcp_client_gateway_onlink_implicit(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', + 'dhcp-client-gateway-onlink-implicit.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, '192.168.5') + + output = check_output('ip route list dev veth99 10.0.0.0/8') + print(output) + self.assertRegex(output, 'onlink') + output = check_output('ip route list dev veth99 192.168.100.0/24') + print(output) + self.assertRegex(output, 'onlink') + + def test_dhcp_client_with_ipv4ll_fallback_with_dhcp_server(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', + 'dhcp-client-with-ipv4ll-fallback-with-dhcp-server.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq(lease_time='2m') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip address show dev veth99') + print(output) + + output = check_output('ip -6 address show dev veth99 scope global dynamic') + self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic') + output = check_output('ip -6 address show dev veth99 scope link') + self.assertRegex(output, 'inet6 .* scope link') + output = check_output('ip -4 address show dev veth99 scope global dynamic') + self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + output = check_output('ip -4 address show dev veth99 scope link') + self.assertNotRegex(output, 'inet .* scope link') + + print('Wait for the dynamic address to be expired') + time.sleep(130) + + output = check_output('ip address show dev veth99') + print(output) + + output = check_output('ip -6 address show dev veth99 scope global dynamic') + self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic') + output = check_output('ip -6 address show dev veth99 scope link') + self.assertRegex(output, 'inet6 .* scope link') + output = check_output('ip -4 address show dev veth99 scope global dynamic') + self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + output = check_output('ip -4 address show dev veth99 scope link') + self.assertNotRegex(output, 'inet .* scope link') + + search_words_in_dnsmasq_log('DHCPOFFER', show_all=True) + + def test_dhcp_client_with_ipv4ll_fallback_without_dhcp_server(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', + 'dhcp-client-with-ipv4ll-fallback-without-dhcp-server.network') + start_networkd() + self.wait_online(['veth99:degraded', 'veth-peer:routable']) + + output = check_output('ip address show dev veth99') + print(output) + + output = check_output('ip -6 address show dev veth99 scope global dynamic') + self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic') + output = check_output('ip -6 address show dev veth99 scope link') + self.assertRegex(output, 'inet6 .* scope link') + output = check_output('ip -4 address show dev veth99 scope global dynamic') + self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + output = check_output('ip -4 address show dev veth99 scope link') + self.assertRegex(output, 'inet .* scope link') + + def test_dhcp_client_route_remove_on_renew(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', + 'dhcp-client-ipv4-only-ipv6-disabled.network') + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq(ipv4_range='192.168.5.100,192.168.5.199', lease_time='2m') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + # test for issue #12490 + + output = check_output('ip -4 address show dev veth99 scope global dynamic') + print(output) + self.assertRegex(output, 'inet 192.168.5.1[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + address1=None + for line in output.splitlines(): + if 'brd 192.168.5.255 scope global dynamic veth99' in line: + address1 = line.split()[1].split('/')[0] + break + + output = check_output('ip -4 route show dev veth99') + print(output) + self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024') + self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024') + + stop_dnsmasq(dnsmasq_pid_file) + start_dnsmasq(ipv4_range='192.168.5.200,192.168.5.250', lease_time='2m') + + print('Wait for the dynamic address to be expired') + time.sleep(130) + + output = check_output('ip -4 address show dev veth99 scope global dynamic') + print(output) + self.assertRegex(output, 'inet 192.168.5.2[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99') + address2=None + for line in output.splitlines(): + if 'brd 192.168.5.255 scope global dynamic veth99' in line: + address2 = line.split()[1].split('/')[0] + break + + self.assertNotEqual(address1, address2) + + output = check_output('ip -4 route show dev veth99') + print(output) + self.assertNotRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 1024') + self.assertNotRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 1024') + self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 1024') + self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 1024') + + def test_dhcp_client_use_dns_yes(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-yes.network') + + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + # link become 'routable' when at least one protocol provide an valid address. + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') + + time.sleep(3) + output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) + print(output) + self.assertRegex(output, '192.168.5.1') + self.assertRegex(output, '2600::1') + + def test_dhcp_client_use_dns_no(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-no.network') + + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + # link become 'routable' when at least one protocol provide an valid address. + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') + + time.sleep(3) + output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) + print(output) + self.assertNotRegex(output, '192.168.5.1') + self.assertNotRegex(output, '2600::1') + + def test_dhcp_client_use_dns_ipv4(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4.network') + + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + # link become 'routable' when at least one protocol provide an valid address. + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') + + time.sleep(3) + output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) + print(output) + self.assertRegex(output, '192.168.5.1') + self.assertNotRegex(output, '2600::1') + + def test_dhcp_client_use_dns_ipv4_and_ra(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-dns-ipv4-and-ra.network') + + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.1 --dhcp-option=option6:dns-server,[2600::1]') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + # link become 'routable' when at least one protocol provide an valid address. + self.wait_address('veth99', r'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic', ipv='-4') + self.wait_address('veth99', r'inet6 2600::[0-9a-f]*/128 scope global (dynamic noprefixroute|noprefixroute dynamic)', ipv='-6') + + time.sleep(3) + output = check_output(*resolvectl_cmd, 'dns', 'veth99', env=env) + print(output) + self.assertRegex(output, '192.168.5.1') + self.assertRegex(output, '2600::1') + + def test_dhcp_client_use_domains(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-use-domains.network') + + start_networkd() + self.wait_online(['veth-peer:carrier']) + start_dnsmasq('--dhcp-option=option:domain-search,example.com') + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output(*networkctl_cmd, 'status', 'veth99', env=env) + print(output) + self.assertRegex(output, 'Search Domains: example.com') + + time.sleep(3) + output = check_output(*resolvectl_cmd, 'domain', 'veth99', env=env) + print(output) + self.assertRegex(output, 'example.com') + +class NetworkdIPv6PrefixTests(unittest.TestCase, Utilities): + links = ['veth99'] + + units = [ + '25-veth.netdev', + 'ipv6ra-prefix-client.network', + 'ipv6ra-prefix.network' + ] + + def setUp(self): + remove_links(self.links) + stop_networkd(show_logs=False) + + def tearDown(self): + remove_log_file() + remove_links(self.links) + remove_unit_from_networkd_path(self.units) + stop_networkd(show_logs=True) + + def test_ipv6_route_prefix(self): + copy_unit_to_networkd_unit_path('25-veth.netdev', 'ipv6ra-prefix-client.network', 'ipv6ra-prefix.network') + + start_networkd() + self.wait_online(['veth99:routable', 'veth-peer:routable']) + + output = check_output('ip', '-6', 'route', 'show', 'dev', 'veth-peer') + print(output) + self.assertRegex(output, '2001:db8:0:1::/64 proto ra') + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--build-dir', help='Path to build dir', dest='build_dir') + parser.add_argument('--networkd', help='Path to systemd-networkd', dest='networkd_bin') + parser.add_argument('--resolved', help='Path to systemd-resolved', dest='resolved_bin') + parser.add_argument('--wait-online', help='Path to systemd-networkd-wait-online', dest='wait_online_bin') + parser.add_argument('--networkctl', help='Path to networkctl', dest='networkctl_bin') + parser.add_argument('--resolvectl', help='Path to resolvectl', dest='resolvectl_bin') + parser.add_argument('--timedatectl', help='Path to timedatectl', dest='timedatectl_bin') + parser.add_argument('--valgrind', help='Enable valgrind', dest='use_valgrind', type=bool, nargs='?', const=True, default=use_valgrind) + parser.add_argument('--debug', help='Generate debugging logs', dest='enable_debug', type=bool, nargs='?', const=True, default=enable_debug) + parser.add_argument('--asan-options', help='ASAN options', dest='asan_options') + parser.add_argument('--lsan-options', help='LSAN options', dest='lsan_options') + parser.add_argument('--ubsan-options', help='UBSAN options', dest='ubsan_options') + ns, args = parser.parse_known_args(namespace=unittest) + + if ns.build_dir: + if ns.networkd_bin or ns.resolved_bin or ns.wait_online_bin or ns.networkctl_bin or ns.resolvectl_bin or ns.timedatectl_bin: + print('WARNING: --networkd, --resolved, --wait-online, --networkctl, --resolvectl, or --timedatectl options are ignored when --build-dir is specified.') + networkd_bin = os.path.join(ns.build_dir, 'systemd-networkd') + resolved_bin = os.path.join(ns.build_dir, 'systemd-resolved') + wait_online_bin = os.path.join(ns.build_dir, 'systemd-networkd-wait-online') + networkctl_bin = os.path.join(ns.build_dir, 'networkctl') + resolvectl_bin = os.path.join(ns.build_dir, 'resolvectl') + timedatectl_bin = os.path.join(ns.build_dir, 'timedatectl') + else: + if ns.networkd_bin: + networkd_bin = ns.networkd_bin + if ns.resolved_bin: + resolved_bin = ns.resolved_bin + if ns.wait_online_bin: + wait_online_bin = ns.wait_online_bin + if ns.networkctl_bin: + networkctl_bin = ns.networkctl_bin + if ns.resolvectl_bin: + resolvectl_bin = ns.resolvectl_bin + if ns.timedatectl_bin: + timedatectl_bin = ns.timedatectl_bin + + use_valgrind = ns.use_valgrind + enable_debug = ns.enable_debug + asan_options = ns.asan_options + lsan_options = ns.lsan_options + ubsan_options = ns.ubsan_options + + if use_valgrind: + networkctl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', networkctl_bin] + resolvectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', resolvectl_bin] + timedatectl_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', timedatectl_bin] + wait_online_cmd = ['valgrind', '--track-origins=yes', '--leak-check=full', '--show-leak-kinds=all', wait_online_bin] + else: + networkctl_cmd = [networkctl_bin] + resolvectl_cmd = [resolvectl_bin] + timedatectl_cmd = [timedatectl_bin] + wait_online_cmd = [wait_online_bin] + + if enable_debug: + env.update({ 'SYSTEMD_LOG_LEVEL' : 'debug' }) + if asan_options: + env.update({ 'ASAN_OPTIONS' : asan_options }) + if lsan_options: + env.update({ 'LSAN_OPTIONS' : lsan_options }) + if ubsan_options: + env.update({ 'UBSAN_OPTIONS' : ubsan_options }) + + sys.argv[1:] = args + unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, + verbosity=3)) diff --git a/test/test-path/basic.target b/test/test-path/basic.target new file mode 120000 index 00000000..a882b72c --- /dev/null +++ b/test/test-path/basic.target @@ -0,0 +1 @@ +../../units/basic.target \ No newline at end of file diff --git a/test/test-path/path-changed.path b/test/test-path/path-changed.path new file mode 100644 index 00000000..e58bdd92 --- /dev/null +++ b/test/test-path/path-changed.path @@ -0,0 +1,8 @@ +[Unit] +Description=Test PathChanged + +[Path] +PathChanged=/tmp/test-path_changed + +[Install] +WantedBy=multi-user.target diff --git a/test/test-path/path-changed.service b/test/test-path/path-changed.service new file mode 120000 index 00000000..8bdf1788 --- /dev/null +++ b/test/test-path/path-changed.service @@ -0,0 +1 @@ +path-service.service \ No newline at end of file diff --git a/test/test-path/path-directorynotempty.path b/test/test-path/path-directorynotempty.path new file mode 100644 index 00000000..17e599fc --- /dev/null +++ b/test/test-path/path-directorynotempty.path @@ -0,0 +1,8 @@ +[Unit] +Description=Test DirectoryNotEmpty + +[Path] +DirectoryNotEmpty=/tmp/test-path_directorynotempty/ + +[Install] +WantedBy=multi-user.target diff --git a/test/test-path/path-directorynotempty.service b/test/test-path/path-directorynotempty.service new file mode 120000 index 00000000..8bdf1788 --- /dev/null +++ b/test/test-path/path-directorynotempty.service @@ -0,0 +1 @@ +path-service.service \ No newline at end of file diff --git a/test/test-path/path-exists.path b/test/test-path/path-exists.path new file mode 100644 index 00000000..c4c9105a --- /dev/null +++ b/test/test-path/path-exists.path @@ -0,0 +1,8 @@ +[Unit] +Description=Test PathExists + +[Path] +PathExists=/tmp/test-path_exists + +[Install] +WantedBy=multi-user.target diff --git a/test/test-path/path-exists.service b/test/test-path/path-exists.service new file mode 120000 index 00000000..8bdf1788 --- /dev/null +++ b/test/test-path/path-exists.service @@ -0,0 +1 @@ +path-service.service \ No newline at end of file diff --git a/test/test-path/path-existsglob.path b/test/test-path/path-existsglob.path new file mode 100644 index 00000000..a0585996 --- /dev/null +++ b/test/test-path/path-existsglob.path @@ -0,0 +1,8 @@ +[Unit] +Description=Test PathExistsGlob + +[Path] +PathExistsGlob=/tmp/test-path_existsglob* + +[Install] +WantedBy=multi-user.target diff --git a/test/test-path/path-existsglob.service b/test/test-path/path-existsglob.service new file mode 120000 index 00000000..8bdf1788 --- /dev/null +++ b/test/test-path/path-existsglob.service @@ -0,0 +1 @@ +path-service.service \ No newline at end of file diff --git a/test/test-path/path-makedirectory.path b/test/test-path/path-makedirectory.path new file mode 100644 index 00000000..9408479c --- /dev/null +++ b/test/test-path/path-makedirectory.path @@ -0,0 +1,10 @@ +[Unit] +Description=Test MakeDirectory & DirectoryMode + +[Path] +DirectoryNotEmpty=/tmp/test-path_makedirectory/ +MakeDirectory=yes +DirectoryMode=0744 + +[Install] +WantedBy=multi-user.target diff --git a/test/test-path/path-makedirectory.service b/test/test-path/path-makedirectory.service new file mode 120000 index 00000000..8bdf1788 --- /dev/null +++ b/test/test-path/path-makedirectory.service @@ -0,0 +1 @@ +path-service.service \ No newline at end of file diff --git a/test/test-path/path-modified.path b/test/test-path/path-modified.path new file mode 100644 index 00000000..18363227 --- /dev/null +++ b/test/test-path/path-modified.path @@ -0,0 +1,8 @@ +[Unit] +Description=Test PathModified + +[Path] +PathModified=/tmp/test-path_modified + +[Install] +WantedBy=multi-user.target diff --git a/test/test-path/path-modified.service b/test/test-path/path-modified.service new file mode 120000 index 00000000..8bdf1788 --- /dev/null +++ b/test/test-path/path-modified.service @@ -0,0 +1 @@ +path-service.service \ No newline at end of file diff --git a/test/test-path/path-mycustomunit.service b/test/test-path/path-mycustomunit.service new file mode 100644 index 00000000..172ac0d0 --- /dev/null +++ b/test/test-path/path-mycustomunit.service @@ -0,0 +1,6 @@ +[Unit] +Description=Service Test Path Unit= + +[Service] +ExecStart=/bin/true +Type=oneshot diff --git a/test/test-path/path-service.service b/test/test-path/path-service.service new file mode 100644 index 00000000..f8499ec6 --- /dev/null +++ b/test/test-path/path-service.service @@ -0,0 +1,6 @@ +[Unit] +Description=Service Test for Path units + +[Service] +ExecStart=/bin/true +Type=oneshot diff --git a/test/test-path/path-unit.path b/test/test-path/path-unit.path new file mode 100644 index 00000000..95e572d6 --- /dev/null +++ b/test/test-path/path-unit.path @@ -0,0 +1,9 @@ +[Unit] +Description=Test Path Unit= + +[Path] +PathExists=/tmp/test-path_unit +Unit=path-mycustomunit.service + +[Install] +WantedBy=multi-user.target diff --git a/test/test-path/paths.target b/test/test-path/paths.target new file mode 120000 index 00000000..b402796c --- /dev/null +++ b/test/test-path/paths.target @@ -0,0 +1 @@ +../../units/paths.target \ No newline at end of file diff --git a/test/test-path/sysinit.target b/test/test-path/sysinit.target new file mode 120000 index 00000000..9d10e5b2 --- /dev/null +++ b/test/test-path/sysinit.target @@ -0,0 +1 @@ +../../units/sysinit.target \ No newline at end of file diff --git a/test/test-resolve/_443._tcp.fedoraproject.org.pkts b/test/test-resolve/_443._tcp.fedoraproject.org.pkts new file mode 100644 index 0000000000000000000000000000000000000000..a383c6286ddb0c8df381a1712723a9ff0332b411 GIT binary patch literal 169 zcmeZgfB=?w6BA>W_>$xT-n7(|{G!ByqWrAX3=9Sgj0_ARt_&TF49pzN zj0}wXWm79A?O;2v_;_NxjKLGH$W1OYp9jzS^EF)2B<`Z2)J@~pKGlbkmh|s@v+g-d z%HDm7cQxCDYVv#)-@as>zT04F=&xq@kVN;@_eNxa{1-8frm_VbuU`dj5) zriCB>ujJnGY)}7G1&6vlviqglPw_abZ24mNlzEZhB(V>ylDE~*^skHN-KxO5-SL24 z!>L54x%I+2W_>R#DkSzx&Yc`ueRi83Tw7#J9*8C#f{n3!1_TbL&qn;KXoCR&&znOa(!r=}$v zrkGfoq!^hRStgqqrjc8<=28rCb^L z#U;6k#U-glSY#`tx0Nt3@Ch(5Fhwx%J2?P-XW&Sr)l5*UB|ugiVKJO6gG{Mq5VpVo E03mr?_5c6? literal 0 HcmV?d00001 diff --git a/test/test-resolve/fake-caa.pkts b/test/test-resolve/fake-caa.pkts new file mode 100644 index 0000000000000000000000000000000000000000..1c3ecc54919def5a36c343c16f2c613c33ca54e7 GIT binary patch literal 196 zcmdO7fB?4i{QUHsROaOTTn0u)21W*kkaz}R2G-2t;?mUO%G|`flGJ29psXfd4GpAf LXe3pG7^VgQS6MIc literal 0 HcmV?d00001 diff --git a/test/test-resolve/fedoraproject.org.pkts b/test/test-resolve/fedoraproject.org.pkts new file mode 100644 index 0000000000000000000000000000000000000000..17874844d9d6cf48942efbc557ccf15f829ecc19 GIT binary patch literal 1483 zcmZ3=00F#dsVVtIi3LUZS*gh-%=ty>3=9Sgj0_Bnq6{6349u*|j0}tirkS!XeKw)v zo^qdk)}OiB-ml$~^Z#}_Y%$upa%$FG?#De}64T%A-j#Prro5<#=jw|KRtF98c=um- zGU9&wr?9J&x9n0$gz1@_x0ZT^=60{Y$y{<-=X=Z2sPIxfTSJk0n_Wzn^U9Aql<)of zeVXH})`!8?>V2}vG?G~2feC5_kaK%$1-v-GC~}C<+|!wAt`FkwaWxkA=;9ct^~9XVH`1lY0JcE0$=LX~Y}LF()iJwB_F1`0{(2 z^Djkuy@_A-X-#M2H?7Zp+5dJvYkqur#l^M-{Li?qUk);UAo$~YSfaF$z!jOBTV8!V zz_xjjG3S}B3S1(dn-5OiUUcQ+yUCwz107<&^W6_IC=z_)pd-RHKmB)3?kDFYZ?}ar zw$F(Sd&BqR`QzEfL1$y0uDTO0VH@*M-e2JTziZ1SHyf`%;(s)5Ws=T5d6v18olTCP zJn`+u7gPNHSa*`Nbun%R;^VopPd#^7CBFoC_-5%|qRD1Dy@yOA<2z z{6mBN3Z26vi%Rpcg(l33VHTPiSVEH@8k)ikT&%f?nK>p%i4VVeIk0*QB=wS5%x8p} q&vMgk2cs$$1x!!{0-y|Gh-4Z;#mG)2s2Dk`5manMiZhIn6axTs>g=2V literal 0 HcmV?d00001 diff --git a/test/test-resolve/google.com.pkts b/test/test-resolve/google.com.pkts new file mode 100644 index 0000000000000000000000000000000000000000..f98c4cd85505436845df350370f6d8f5d0268a00 GIT binary patch literal 747 zcmb1QfB?4i{QUHsROaOTTm}Y4AY@?p!N79E>SmuBHWe~Z6#{DPKQ=h9aPUGDDewhg zQ_Tie&B0*BoL6j!Y!hcnUa@XsN^WKzvMAeOv$qTk%qS?^JxEOJ0b^RBE-@zuYy2{SObF3o5I~PHf~t*> q1D~L36OvRLBdgZL;&VoD$_2Vxn1MC3xVSX6xH2~}uOu}Y#9?8=Pt#Joi2{GxOQ1_K6=ur(tGBLg!RGb01z{R&4n#jO{=i>rJQi-`&k zUT`Dqdz$JjS@zyqZS{oQ{kn~+${uf()bCxsd-eX(oS13#pR}XrSno;avFa&0Q>*>l zmm{=C`i>m~&!6yxf8MOP{Ao?H+CqW7uGtnZDsHBCRB64izOr!jnGCZ%hhk=C>_}yu zvqoiukjFmtjQ_^5dCZkbKf4?Yx2!#I^ZDl~qVo%zpPbuhW1+v<%$Rkqk+{({@2qf# zTp7W7#!t*k*0iUkv(yx(eyY0OpOe{@AKo=X)5G_dL&|!ym7*>V6Hdm>%TZr8&7yE( zc$n5FTMgOX&`Dy8zt(K5R9h1F;GpHU%~I2nPF}Bfy0yFUBx92M@w>9#@&tm35fV)M z6_0jA3a;HPvUVxUsVvodXJ%f}s|jHV3oX#>$u~T4X~pd6_sp%LR)2EcelJO`M905j zhWADD7e8+}T+i+5-K5%eTzA!H$+}7Bo93K%UpS?1wc*`(DbJ7T_YEcN|Ce3(=hKp| zXZfPk=UMBP_Yt0-C)eb=2WuFwQL#{3EVM9B+`DOh%(58kQ~OT}$uhbu*|uWws>=#T zwgz)$Nh<%G_I~nB@0Sx5l)p{P(^fm@z}$DT;oG_w+wLm-v|dtl-6wbEg?LxvJZ85= zIZ`r{`4^V*y-3^cSNSf9X+qJ`Qk&NnoWUE_@BOxTyY1TX8RY@9UGs|OZ1-D#|7h05 zHqVl|QtYNQo&Ua=vHb{GdngA;T`YpEUs(_)ZOTNqScfoL0b5D5e*3K^K7 z1`B`;X3NRU%TGyVPR`F|AgtU7W)f3g6*0<5Gu;?jxdz1PINUCX5h#QmZ-Q(*VdbXC z%B8Wo23Tq^FlgyBu&n)mu2T)G5`Ji418G>;fuqX;t7-wLYDI-I+v0*WLxtQ5g+!~8 zk|I55*`)_8yA*U2b8=$w>UVPmCb^`<;#A$@%#u{yvecr?w9MqhlFa-(Td#_coTB(# zXa5uzvjWe&f-o;rH(x)?u*mY9eAkLZ*Zk1X5WmpUfQpQ4?13Z$^|gQ+gALdfA8aQ6 z|2IuV%@V7dbfA7xVq}^yPqbyp3Gw~EEB;D_`yb-q{^N80Q-{a7%Dxbv>q}>?)x~Ro z7!#vkb5Xo<{=})8E9*X|O=kPME&W{;0b7}v{?EyOC0!g8zx$<>vf$mCCAP=cyqI8p z%&tW9-i&?Ghnxu5%FH;mW*yI$&@{26WhH0VZ@9Dh$lYJB3E0Za^eKQnhEMZwyIi%^ zt-Bv=X6)P6tob;mU1dq!A;Wq9J^vA~m65S*%DE*QI$P&vylq+iIIzyV*`C!Ed#Xt$ HI@JIG&1O3A literal 0 HcmV?d00001 diff --git a/test/test-resolve/root.pkts b/test/test-resolve/root.pkts new file mode 100644 index 0000000000000000000000000000000000000000..54ba668c759efc5115cb4fa9bc2adbf766509ea7 GIT binary patch literal 1061 zcmWe;WPkz#1|U;^2_pw1BQpmxBLm|K28ETOX}g?WwC!&2xz+Nd?rZMesyB&hqMNf2U_GZM?rtr#7haht4_beB}RCnSHh|&Rhj`8`hmCV*>zuqhs5}*F2p_4^Ak9pyCU9RHj8Gg(e#hk{!pb0^uuYv)z3eHrAqLT>kqm5f&|tLHgv6gjZy*&mCG zbM&%SGo^TI2!Ad8qnIGa`_A+1yq8(d0(L>ZN$s|iVIji+4H||HMg~aG?E3E-tFwi5 zMqX0i)Ek%D<}p|@_MPlK;M40HH2Ft-RO9BAIdRkNt}rC*U-P8dw`06x{5UizWCy=E@B@JsJ&T8-1~Sf8aI)`q@j)RvOy-TZITL9e1cf_Gj8ZMk~1 zPgo!=_h?+{H*KEF3!02H3jOM0Y64s(;ZDzeKkl%)At)+*GF0Yz78d21W*kkaz|GkeY5@j<5AUEIk-zOl#0X z)@6iWmrhUpk3UPX=yJleEBFA+F0BdmKYl4;(dCSyO9tdZUSS3S1xAhyKt~yX92U4+ zF32*C!->dN#G4`$MDbuuvb5bI;$1w5c9-=P=1 zdG_Q*ldcpui@K}16yCni`+fP6yuoBOQ`Z)LnrKcW0CcDUoL|DzTdhI7}{(H|3g7+Wy z{_-qIDys@_6p8;ifwjsB)YR#>+R!+@eHipAE$zax39HNU)(G1VhM7GYXkttky)1E+ zqRDfB-}sGLzB?bkG|Q7|ey6hk^`d`$yZLb{9VfY~4z;sN`$AzqXoLyDK@hs)|(p*#oQMg2lV4!d>v#|CPYZz^GX~InYK-2BtyQfCM5k6Z zQr$v(0hc=?XVlaHs+mvuj+irjxx%%)RqdkXQ*Ip#FH-04b_cCF*zj5->0Z^Mxnr$U zo&)w1m34?kpMa4%`kU@qg(C?%!^All^QGbmTS(av@7tlMRE$~-zU^0X2ZC6jOhMLV z5FK}H6PG_EbGXP>mhm;Cq75axpJ6m#1?%|l(&P3vv#r!kx?1KvLOxsO%j((~0MkO< z7m#iu&MCI}%vCG>Wh0Xb17Xc!;Ed~GpR_DHI&leQkds1$fw{+#unu(TPZb*^`h)0{ zN*BksHa}AOw}rNz7J7>^NboJSAAB{RR!Iutz9?<|QXC`s-Yr ze@G~4SC%ZE!YSOOGDiW}H_1t1fIFY4-rPDBJ?A0RvKuoXChIb3h zd#!rRXqWh|IexfxilOIa;vVc`oi>HbzI* zAxO-qH`|3oCfp+g`FVQCp~?3No?<96?tvef;Ca)7C?A9klK1h_i~}JVd4V8+1QY15 zM*>}8xWLZJ!ps1=aES%P%Er#f4`Kjo^6)22xY-}vfZslgFTazm z`uJ!mw74@zX@`T9lWE72P=w(3~^kpsw0sXg7s>jkR&Bzq6`uQH>SaYQ{%CG-iS@MDB>lWN32qdoq!#fI!&}$ zRk>7u9i_mah$Zi?);6TAKzS5FQgXTyD@?NNJKM2EyqDc)Y~CinR&VmDhZPRWIrkF| z1npBFrNX9-3FQ&_Nz_@$nNU-P}yMZH%`#p*y%Lec5s;P370^> z3wMOR(C5k*Z7jaMxzvFunyaD|+9{c}1x4#wbop2-xDv{vB89oav| zKS~iYX8`;HkNYvkoC4)-EPdH6Un0EDwou<{yy2zqzZ~2vvq1}MM$Cx{#prTeaiF~@ zdl?C)?_3Z+;QO%!ZhE1nwav3l+=s03?fMelmr1-BVkPSBRAY4qN4m178(cP-#u_#3 z^e8WDZajT1b$jF!efaD`(7;(huVhqO$^3)Jls>~2$n->iX4`+{^NjOq!3AO_p?)kI*+ev=~ZbL z!b;PXolmrHh4Qm0)^{-F6~Twp7^Im^-J{n6qcFNu3gCe0O^+9`Hg`~7bZIbbBcW{= zV_ad}6k)NRXj9OyH-@mS`@{p9tMT>ZTAQmYF3ktx&aICfj_P~$eoXGU38 zv+Rr_56gB_CWF&!g=u%KBvE=YM<;%%YUHICz=F$v%O?&b$|(3#C9MBe3CDjMql$~` z+?*&M{`$TxLlC%Six8aZpWZ8CshxFl(SbMRgPq;;%iQso$E6w!G-}!F=g1;9FD(LM zG=hM!^kufMd+xsb+>d{B9UMGqBg+(BSo>X!O(&IAGg%W^-DD*9`&WXa)E!=J!=vw} zzG^~|mI}7K$+?i0!!!ez2Y&)6A4XxzzTG`XH^lpvh2rf|`1?*1t@^~Jd8TB;$$q~o zr-Juh*0Wcr^s`pV*Xse9N3a$9Cl*oSQ|=B~)qvH&VaQ0Ej98~){hPVPZs|RaC9}@< z{tAUh6^l8)WJcZ)%$6)h`NyA_CW^^tcvA#7!&Z8)Cx%t#ZL$Mbx({BVH#JGtS-+L* zU{n+^ti#bJozNUM>w4S$w)~8n_Tm=s*aPeFW?jp1LT!?EebObq+bF0_*_$esnY^T| zF?YWXH=zid&(`1FnLqBVoGyd=!Mo=6e~bvMb=Q5Uh%}*{L>?a9S&5pG2rUXdH9I}- zk{<%T%Gx}uEpUrDRCly$ISm3MTE(Mo-Fhw$33&i)(!d&y$zF4w7((lt>u`mfStK@% zV?!!vgZWkiWSiw2#Hsm#*%lMjO^+M*+?+^?SWSdl;RhtY296Y#t8LD~nfDBzJ%WLKPY?68*F$8rMGoZ5xFC literal 0 HcmV?d00001 diff --git a/test/test-umount/empty.mountinfo b/test/test-umount/empty.mountinfo new file mode 100644 index 00000000..e69de29b diff --git a/test/test-umount/example.swaps b/test/test-umount/example.swaps new file mode 100644 index 00000000..9de4e3e7 --- /dev/null +++ b/test/test-umount/example.swaps @@ -0,0 +1,4 @@ +Filename Type Size Used Priority +/dev/dm-2 partition 8151036 2283436 -2 +/some/swapfile file 111 111 0 +/some/swapfile2 (deleted) file 111 111 0 diff --git a/test/test-umount/garbled.mountinfo b/test/test-umount/garbled.mountinfo new file mode 100644 index 00000000..5f28aea4 --- /dev/null +++ b/test/test-umount/garbled.mountinfo @@ -0,0 +1,5 @@ +18 63 1000999:110999 / /sys rw,nosuid,nodev,noexec,relatime shared:2 - sysfs sysfs rw +44 44 +asdfasdf asdfasdf asdf asdfasdfasdf +asdfsadfasd +95 63 8:1 / /one-good-entry rw,relatime shared:34 - ext4 /dev/sda1 rw,data=ordered diff --git a/test/test-umount/rhbug-1554943.mountinfo b/test/test-umount/rhbug-1554943.mountinfo new file mode 100644 index 00000000..d8bdf358 --- /dev/null +++ b/test/test-umount/rhbug-1554943.mountinfo @@ -0,0 +1,47 @@ +18 63 0:18 / /sys rw,nosuid,nodev,noexec,relatime shared:2 - sysfs sysfs rw +19 63 0:4 / /proc rw,nosuid,nodev,noexec,relatime shared:23 - proc proc rw +20 63 0:6 / /dev rw,nosuid shared:19 - devtmpfs devtmpfs rw,size=3549752k,nr_inodes=887438,mode=755 +21 18 0:7 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:3 - securityfs securityfs rw +22 20 0:19 / /dev/shm rw,nosuid,nodev shared:20 - tmpfs tmpfs rw +23 20 0:20 / /dev/pts rw,nosuid,noexec,relatime shared:21 - devpts devpts rw,gid=5,mode=620,ptmxmode=000 +24 63 0:21 / /run rw,nosuid,nodev shared:22 - tmpfs tmpfs rw,mode=755 +25 18 0:22 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:4 - tmpfs tmpfs ro,mode=755 +26 25 0:23 / /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime shared:5 - cgroup2 cgroup rw +27 25 0:24 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:6 - cgroup cgroup rw,xattr,name=systemd +28 18 0:25 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:17 - pstore pstore rw +29 25 0:26 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:7 - cgroup cgroup rw,cpu,cpuacct +30 25 0:27 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:8 - cgroup cgroup rw,perf_event +31 25 0:28 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:9 - cgroup cgroup rw,freezer +32 25 0:29 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,hugetlb +33 25 0:30 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:11 - cgroup cgroup rw,cpuset +34 25 0:31 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:12 - cgroup cgroup rw,net_cls,net_prio +35 25 0:32 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:13 - cgroup cgroup rw,memory +36 25 0:33 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,pids +37 25 0:34 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,blkio +38 25 0:35 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,devices +61 18 0:36 / /sys/kernel/config rw,relatime shared:18 - configfs configfs rw +63 0 8:17 / / rw,relatime shared:1 - ext4 /dev/sdb1 rw,lazytime,commit=30,inode_readahead_blks=16 +39 18 0:8 / /sys/kernel/debug rw,relatime shared:24 - debugfs debugfs rw +40 20 0:37 / /dev/hugepages rw,relatime shared:25 - hugetlbfs hugetlbfs rw,pagesize=2M +41 19 0:38 / /proc/sys/fs/binfmt_misc rw,relatime shared:26 - autofs systemd-1 rw,fd=32,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=14807 +42 20 0:17 / /dev/mqueue rw,relatime shared:27 - mqueue mqueue rw +43 63 0:39 / /var/www/sessiondata rw,nosuid,noexec,noatime shared:28 - tmpfs tmpfs rw,size=4194304k +75 63 0:40 / /usr/share/mysql-test/var rw,noatime shared:29 - tmpfs tmpfs rw,size=4194304k,mode=750,uid=27,gid=27 +77 63 8:33 / /Volumes/dune rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16 +79 63 8:33 /builduser /home/builduser rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16 +81 77 0:41 / /Volumes/dune/mysql_data/autotest rw,nosuid,noexec,noatime shared:31 - tmpfs tmpfs rw,size=4194304k,mode=700,uid=27,gid=27 +83 63 8:33 /.tmp /var/tmp rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16 +85 77 0:42 / /Volumes/dune/www-servers/cms/cms/temp rw,nosuid,noexec,noatime shared:32 - tmpfs tmpfs rw,size=4194304k,mode=770,uid=48,gid=48 +87 77 8:33 /buildserver/autotest /Volumes/dune/www-servers/autotest rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16 +89 63 8:33 /.tmp /tmp rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16 +91 77 0:43 / /Volumes/dune/www-servers/cms/cms/logs rw,nosuid,noexec,noatime shared:33 - tmpfs tmpfs rw,size=4194304k,mode=770,uid=48,gid=48 +93 63 8:33 /www-servers/cms /usr/local/sftp-homes/flow/cms rw,relatime shared:30 - ext4 /dev/sdc1 rw,lazytime,commit=30,inode_readahead_blks=16 +95 63 8:1 / /boot rw,relatime shared:34 - ext4 /dev/sda1 rw,data=ordered +97 79 0:44 / /home/builduser/rpmbuild/PHP-PGO/logs rw,nosuid,noatime shared:35 - tmpfs tmpfs rw,size=4194304k,mode=770,uid=5000,gid=5000 +98 77 0:44 / /Volumes/dune/builduser/rpmbuild/PHP-PGO/logs rw,nosuid,noatime shared:35 - tmpfs tmpfs rw,size=4194304k,mode=770,uid=5000,gid=5000 +101 63 9:0 / /mnt/raid10 rw,relatime shared:36 - ext4 /dev/md0 rw,lazytime,commit=30,stripe=128,inode_readahead_blks=16 +558 24 0:52 / /run/user/48 rw,nosuid,nodev,relatime shared:83 - tmpfs tmpfs rw,size=711220k,mode=700,uid=48,gid=48 +588 24 0:53 / /run/user/5000 rw,nosuid,nodev,relatime shared:135 - tmpfs tmpfs rw,size=711220k,mode=700,uid=5000,gid=5000 +613 24 0:54 / /run/user/4503 rw,nosuid,nodev,relatime shared:85 - tmpfs tmpfs rw,size=711220k,mode=700,uid=4503,gid=4503 +653 24 0:45 / /run/user/4500 rw,nosuid,nodev,relatime shared:87 - tmpfs tmpfs rw,size=711220k,mode=700,uid=4500,gid=48 +699 24 0:55 / /run/user/0 rw,nosuid,nodev,relatime shared:89 - tmpfs tmpfs rw,size=711220k,mode=700 diff --git a/test/testsuite.target b/test/testsuite.target new file mode 100644 index 00000000..1a7e5b37 --- /dev/null +++ b/test/testsuite.target @@ -0,0 +1,6 @@ +[Unit] +Description=Testsuite target +Requires=multi-user.target +After=multi-user.target +Conflicts=rescue.target +AllowIsolate=yes diff --git a/test/timers.target b/test/timers.target new file mode 120000 index 00000000..576d47fe --- /dev/null +++ b/test/timers.target @@ -0,0 +1 @@ +../units/timers.target \ No newline at end of file diff --git a/test/udev-test.pl b/test/udev-test.pl new file mode 100755 index 00000000..95013279 --- /dev/null +++ b/test/udev-test.pl @@ -0,0 +1,1858 @@ +#!/usr/bin/env perl + +# udev test +# +# Provides automated testing of the udev binary. +# The whole test is self contained in this file, except the matching sysfs tree. +# Simply extend the @tests array, to add a new test variant. +# +# Every test is driven by its own temporary config file. +# This program prepares the environment, creates the config and calls udev. +# +# udev parses the rules, looks at the provided sysfs and +# first creates and then removes the device node. +# After creation and removal the result is checked against the +# expected value and the result is printed. +# +# Copyright © 2004 Leann Ogasawara + +use warnings; +use strict; + +my $udev_bin = "./test-udev"; +my $valgrind = 0; +my $gdb = 0; +my $strace = 0; +my $udev_bin_valgrind = "valgrind --tool=memcheck --leak-check=yes --track-origins=yes --quiet $udev_bin"; +my $udev_bin_gdb = "gdb --args $udev_bin"; +my $udev_bin_strace = "strace -efile $udev_bin"; +my $udev_run = "test/run"; +my $udev_tmpfs = "test/tmpfs"; +my $udev_sys = "${udev_tmpfs}/sys"; +my $udev_dev = "${udev_tmpfs}/dev"; +my $udev_rules_dir = "$udev_run/udev/rules.d"; +my $udev_rules = "$udev_rules_dir/udev-test.rules"; +my $EXIT_TEST_SKIP = 77; + +my $rules_10k_tags = ""; +for (my $i = 1; $i <= 10000; ++$i) { + $rules_10k_tags .= 'KERNEL=="sda", TAG+="test' . $i . "\"\n"; +} + +my $rules_10k_tags_continuation = "KERNEL==\"sda\", \\\n"; +for (my $i = 1; $i < 10000; ++$i) { + $rules_10k_tags_continuation .= 'TAG+="test' . $i . "\",\\\n"; +} +$rules_10k_tags_continuation .= "TAG+=\"test10000\"\\n"; + +my @tests = ( + { + desc => "no rules", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "sda", + exp_rem_error => "yes", + rules => < "label test of scsi disc", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "boot_disk", + rules => < "label test of scsi disc", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "boot_disk", + rules => < "label test of scsi disc", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "boot_disk", + rules => < "label test of scsi partition", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "boot_disk1", + rules => < "label test of pattern match", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "boot_disk1", + rules => < "label test of multiple sysfs files", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "boot_disk1", + rules => < "label test of max sysfs files (skip invalid rule)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "boot_disk1", + rules => < "catch device by *", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem/0", + rules => < "catch device by * - take 2", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem/0", + rules => < "catch device by ?", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem/0", + rules => < "catch device by character class", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem/0", + rules => < "replace kernel name", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem", + rules => < "Handle comment lines in config file (and replace kernel name)", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem", + rules => < "Handle comment lines in config file with whitespace (and replace kernel name)", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem", + rules => < "Handle whitespace only lines (and replace kernel name)", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "whitespace", + rules => < "Handle empty lines in config file (and replace kernel name)", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem", + rules => < "Handle backslashed multi lines in config file (and replace kernel name)", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem", + rules => < "preserve backslashes, if they are not for a newline", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "aaa", + rules => < "Handle stupid backslashed multi lines in config file (and replace kernel name)", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem", + rules => < "subdirectory handling", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "sub/direct/ory/modem", + rules => < "parent device name match of scsi partition", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "first_disk5", + rules => < "test substitution chars", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "Major:8:minor:5:kernelnumber:5:id:0:0:0:0", + rules => < "import of shell-value returned from program", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node12345678", + rules => < "substitution of sysfs value (%s{file})", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "disk-ATA-sda", + rules => < "program result substitution", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "special-device-5", + not_exp_name => "not", + rules => < "program result substitution (newline removal)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "newline_removed", + rules => < "program result substitution", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "test-0:0:0:0", + rules => < "program with lots of arguments", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "foo9", + rules => < "program with subshell", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "bar9", + rules => < "program arguments combined with apostrophes", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "foo7", + rules => < "program arguments combined with escaped double quotes, part 1", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "foo2", + rules => < "program arguments combined with escaped double quotes, part 2", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "foo2", + rules => < "program arguments combined with escaped double quotes, part 3", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "foo2", + rules => < "characters before the %c{N} substitution", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "my-foo9", + rules => < "substitute the second to last argument", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "my-foo8", + rules => < "test substitution by variable name", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "Major:8-minor:5-kernelnumber:5-id:0:0:0:0", + rules => < "test substitution by variable name 2", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "Major:8-minor:5-kernelnumber:5-id:0:0:0:0", + rules => < "test substitution by variable name 3", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "850:0:0:05", + rules => < "test substitution by variable name 4", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "855", + rules => < "test substitution by variable name 5", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "8550:0:0:0", + rules => < "non matching SUBSYSTEMS for device with no parent", + devpath => "/devices/virtual/tty/console", + exp_name => "TTY", + rules => < "non matching SUBSYSTEMS", + devpath => "/devices/virtual/tty/console", + exp_name => "TTY", + rules => < "ATTRS match", + devpath => "/devices/virtual/tty/console", + exp_name => "foo", + rules => < "ATTR (empty file)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "empty", + rules => < "ATTR (non-existent file)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "non-existent", + rules => < "program and bus type match", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "scsi-0:0:0:0", + rules => < "sysfs parent hierarchy", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem", + rules => < "name test with ! in the name", + devpath => "/devices/virtual/block/fake!blockdev0", + exp_name => "is/a/fake/blockdev0", + rules => < "name test with ! in the name, but no matching rule", + devpath => "/devices/virtual/block/fake!blockdev0", + exp_name => "fake/blockdev0", + exp_rem_error => "yes", + rules => < "KERNELS rule", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "scsi-0:0:0:0", + rules => < "KERNELS wildcard all", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "scsi-0:0:0:0", + rules => < "KERNELS wildcard partial", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "scsi-0:0:0:0", + rules => < "KERNELS wildcard partial 2", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "scsi-0:0:0:0", + rules => < "substitute attr with link target value (first match)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "driver-is-sd", + rules => < "substitute attr with link target value (currently selected device)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "driver-is-ahci", + rules => < "ignore ATTRS attribute whitespace", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "ignored", + rules => < "do not ignore ATTRS attribute whitespace", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "matched-with-space", + rules => < "permissions USER=bad GROUP=name", + devpath => "/devices/virtual/tty/tty33", + exp_name => "tty33", + exp_perms => "0:0:0600", + rules => < "permissions OWNER=1", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + exp_perms => "1::0600", + rules => < "permissions GROUP=1", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + exp_perms => ":1:0660", + rules => < "textual user id", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + exp_perms => "daemon::0600", + rules => < "textual group id", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + exp_perms => ":daemon:0660", + rules => < "textual user/group id", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + exp_perms => "root:mail:0660", + rules => < "permissions MODE=0777", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + exp_perms => "::0777", + rules => < "permissions OWNER=1 GROUP=1 MODE=0777", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + exp_perms => "1:1:0777", + rules => < "permissions OWNER to 1", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "ttyACM0", + exp_perms => "1::", + rules => < "permissions GROUP to 1", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "ttyACM0", + exp_perms => ":1:0660", + rules => < "permissions MODE to 0060", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "ttyACM0", + exp_perms => "::0060", + rules => < "permissions OWNER, GROUP, MODE", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "ttyACM0", + exp_perms => "1:1:0777", + rules => < "permissions only rule", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "ttyACM0", + exp_perms => "1:1:0777", + rules => < "multiple permissions only rule", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "ttyACM0", + exp_perms => "1:1:0777", + rules => < "permissions only rule with override at SYMLINK+ rule", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "ttyACM0", + exp_perms => "1:2:0777", + rules => < "major/minor number test", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + exp_majorminor => "8:0", + rules => < "big major number test", + devpath => "/devices/virtual/misc/misc-fake1", + exp_name => "node", + exp_majorminor => "4095:1", + rules => < "big major and big minor number test", + devpath => "/devices/virtual/misc/misc-fake89999", + exp_name => "node", + exp_majorminor => "4095:89999", + rules => < "multiple symlinks with format char", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "symlink2-ttyACM0", + rules => < "multiple symlinks with a lot of s p a c e s", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "one", + not_exp_name => " ", + rules => < "symlink with spaces in substituted variable", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "name-one_two_three-end", + not_exp_name => " ", + rules => < "symlink with leading space in substituted variable", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "name-one_two_three-end", + not_exp_name => " ", + rules => < "symlink with trailing space in substituted variable", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "name-one_two_three-end", + not_exp_name => " ", + rules => < "symlink with lots of space in substituted variable", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "name-one_two_three-end", + not_exp_name => " ", + rules => < "symlink with multiple spaces in substituted variable", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "name-one_two_three-end", + not_exp_name => " ", + rules => < "symlink with space and var with space, part 1", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "first", + not_exp_name => " ", + rules => < "symlink with space and var with space, part 2", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "name-one_two_three-end", + not_exp_name => " ", + rules => < "symlink with space and var with space, part 3", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "another_symlink", + not_exp_name => " ", + rules => < "symlink creation (same directory)", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "modem0", + rules => < "multiple symlinks", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "second-0", + rules => < "symlink name '.'", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => ".", + exp_add_error => "yes", + exp_rem_error => "yes", + rules => < "symlink node to itself", + devpath => "/devices/virtual/tty/tty0", + exp_name => "link", + exp_add_error => "yes", + exp_rem_error => "yes", + option => "clean", + rules => < "symlink %n substitution", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "symlink0", + rules => < "symlink %k substitution", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "symlink-ttyACM0", + rules => < "symlink %M:%m substitution", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "major-166:0", + rules => < "symlink %b substitution", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "symlink-0:0:0:0", + rules => < "symlink %c substitution", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "test", + rules => < "symlink %c{N} substitution", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "test", + rules => < "symlink %c{N+} substitution", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "this", + rules => < "symlink only rule with %c{N+}", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "test", + rules => < "symlink %s{filename} substitution", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "166:0", + rules => < "program result substitution (numbered part of)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "link1", + rules => < "program result substitution (numbered part of+)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", + exp_name => "link4", + rules => < "SUBSYSTEM match test", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + rules => < "DRIVERS match test", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + rules => < "devnode substitution test", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node", + rules => < "parent node name substitution test", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "sda-part-1", + rules => < "udev_root substitution", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "start-/dev-end", + rules => < "last_rule option", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "last", + rules => < "negation KERNEL!=", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "match", + rules => < "negation SUBSYSTEM!=", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "not-anything", + rules => < "negation PROGRAM!= exit code", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "nonzero-program", + rules => < "ENV{} test", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "true", + rules => < "ENV{} test", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "true", + rules => < "ENV{} test (assign)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "true", + rules => < "ENV{} test (assign 2 times)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "true", + rules => < "ENV{} test (assign2)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "part", + rules => < "untrusted string sanitize", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "sane", + rules => < "untrusted string sanitize (don't replace utf8)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "uber", + rules => < "untrusted string sanitize (replace invalid utf8)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "replaced", + rules => < "read sysfs value from parent device", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "serial-354172020305000", + rules => < "match against empty key string", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "ok", + rules => < "check ACTION value", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "ok", + rules => < "final assignment", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "ok", + exp_perms => "root:tty:0640", + rules => < "final assignment 2", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "ok", + exp_perms => "root:tty:0640", + rules => < "env substitution", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "node-add-me", + rules => < "reset list to current value", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "three", + not_exp_name => "two", + rules => < "test empty SYMLINK+ (empty override)", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "right", + not_exp_name => "wrong", + rules => < "test multi matches", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "right", + rules => < "test multi matches 2", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "right", + rules => < "test multi matches 3", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "right", + rules => < "test multi matches 4", + devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0", + exp_name => "right", + rules => < "test multi matches 5", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad", + rules => < "test multi matches 6", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad", + rules => < "test multi matches 7", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad", + rules => < "test multi matches 8", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad", + rules => < "test multi matches 9", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad", + rules => < "test multi matches 10", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad", + rules => < "IMPORT parent test sequence 1/2 (keep)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "parent", + option => "keep", + rules => < "IMPORT parent test sequence 2/2 (keep)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "parentenv-parent_right", + option => "clean", + rules => < "GOTO test", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "right", + rules => < "GOTO label does not exist", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "right", + rules => < "SYMLINK+ compare test", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "right", + not_exp_name => "wrong", + rules => < "invalid key operation", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "yes", + rules => < "operator chars in attribute", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "yes", + rules => < "overlong comment line", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1", + exp_name => "yes", + rules => < "magic subsys/kernel lookup", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "00:16:41:e2:8d:ff", + rules => < "TEST absolute path", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "there", + rules => < "TEST subsys/kernel lookup", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "yes", + rules => < "TEST relative path", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "relative", + rules => < "TEST wildcard substitution (find queue/nr_requests)", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found-subdir", + rules => < "TEST MODE=0000", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "sda", + exp_perms => "0:0:0000", + exp_rem_error => "yes", + rules => < "TEST PROGRAM feeds OWNER, GROUP, MODE", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "sda", + exp_perms => "1:1:0400", + exp_rem_error => "yes", + rules => < "TEST PROGRAM feeds MODE with overflow", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "sda", + exp_perms => "0:0:0440", + exp_rem_error => "yes", + rules => < "magic [subsys/sysname] attribute substitution", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "sda-8741C4G-end", + exp_perms => "0:0:0600", + rules => < "builtin path_id", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0", + rules => < "add and match tag", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad", + rules => < "don't crash with lots of tags", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + rules => $rules_10k_tags . < "continuations", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad", + rules => $rules_10k_tags_continuation . < "continuations with empty line", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad", + rules => < "continuations with white only line", + devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda", + exp_name => "found", + not_exp_name => "bad", + rules => <$udev_rules" || die "unable to create rules file: $udev_rules"; + print CONF $$rules; + close CONF; + + if ($valgrind > 0) { + return system("$udev_bin_valgrind $action $devpath"); + } elsif ($gdb > 0) { + return system("$udev_bin_gdb $action $devpath"); + } elsif ($strace > 0) { + return system("$udev_bin_strace $action $devpath"); + } else { + return system("$udev_bin", "$action", "$devpath"); + } +} + +my $error = 0; + +sub permissions_test { + my($rules, $uid, $gid, $mode) = @_; + + my $wrong = 0; + my $userid; + my $groupid; + + $rules->{exp_perms} =~ m/^(.*):(.*):(.*)$/; + if ($1 ne "") { + if (defined(getpwnam($1))) { + $userid = int(getpwnam($1)); + } else { + $userid = $1; + } + if ($uid != $userid) { $wrong = 1; } + } + if ($2 ne "") { + if (defined(getgrnam($2))) { + $groupid = int(getgrnam($2)); + } else { + $groupid = $2; + } + if ($gid != $groupid) { $wrong = 1; } + } + if ($3 ne "") { + if (($mode & 07777) != oct($3)) { $wrong = 1; }; + } + if ($wrong == 0) { + print "permissions: ok\n"; + } else { + printf " expected permissions are: %s:%s:%#o\n", $1, $2, oct($3); + printf " created permissions are : %i:%i:%#o\n", $uid, $gid, $mode & 07777; + print "permissions: error\n"; + $error++; + sleep(1); + } +} + +sub major_minor_test { + my($rules, $rdev) = @_; + + my $major = ($rdev >> 8) & 0xfff; + my $minor = ($rdev & 0xff) | (($rdev >> 12) & 0xfff00); + my $wrong = 0; + + $rules->{exp_majorminor} =~ m/^(.*):(.*)$/; + if ($1 ne "") { + if ($major != $1) { $wrong = 1; }; + } + if ($2 ne "") { + if ($minor != $2) { $wrong = 1; }; + } + if ($wrong == 0) { + print "major:minor: ok\n"; + } else { + printf " expected major:minor is: %i:%i\n", $1, $2; + printf " created major:minor is : %i:%i\n", $major, $minor; + print "major:minor: error\n"; + $error++; + sleep(1); + } +} + +sub udev_setup { + system("umount", $udev_tmpfs); + rmdir($udev_tmpfs); + mkdir($udev_tmpfs) || die "unable to create udev_tmpfs: $udev_tmpfs\n"; + + if (system("mount", "-o", "rw,mode=755,nosuid,noexec", "-t", "tmpfs", "tmpfs", $udev_tmpfs)) { + warn "unable to mount tmpfs"; + return 0; + } + + mkdir($udev_dev) || die "unable to create udev_dev: $udev_dev\n"; + # setting group and mode of udev_dev ensures the tests work + # even if the parent directory has setgid bit enabled. + chown (0, 0, $udev_dev) || die "unable to chown $udev_dev\n"; + chmod (0755, $udev_dev) || die "unable to chmod $udev_dev\n"; + + if (system("mknod", $udev_dev . "/null", "c", "1", "3")) { + warn "unable to create $udev_dev/null"; + return 0; + } + + # check if we are permitted to create block device nodes + my $block_device_filename = $udev_dev . "/sda"; + if (system("mknod", $block_device_filename, "b", "8", "0")) { + warn "unable to create $block_device_filename"; + return 0; + } + unlink $block_device_filename; + + system("cp", "-r", "test/sys/", $udev_sys) && die "unable to copy test/sys"; + + system("rm", "-rf", "$udev_run"); + + if (!mkdir($udev_run)) { + warn "unable to create directory $udev_run"; + return 0; + } + + return 1; +} + +sub run_test { + my ($rules, $number) = @_; + my $rc; + + print "TEST $number: $rules->{desc}\n"; + print "device \'$rules->{devpath}\' expecting node/link \'$rules->{exp_name}\'\n"; + + $rc = udev("add", $rules->{devpath}, \$rules->{rules}); + if ($rc != 0) { + print "$udev_bin add failed with code $rc\n"; + $error++; + } + if (defined($rules->{not_exp_name})) { + if ((-e "$udev_dev/$rules->{not_exp_name}") || + (-l "$udev_dev/$rules->{not_exp_name}")) { + print "nonexistent: error \'$rules->{not_exp_name}\' not expected to be there\n"; + $error++; + sleep(1); + } + } + + if ((-e "$udev_dev/$rules->{exp_name}") || + (-l "$udev_dev/$rules->{exp_name}")) { + + my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, + $atime, $mtime, $ctime, $blksize, $blocks) = stat("$udev_dev/$rules->{exp_name}"); + + if (defined($rules->{exp_perms})) { + permissions_test($rules, $uid, $gid, $mode); + } + if (defined($rules->{exp_majorminor})) { + major_minor_test($rules, $rdev); + } + print "add: ok\n"; + } else { + print "add: error"; + if ($rules->{exp_add_error}) { + print " as expected\n"; + } else { + print "\n"; + system("tree", "$udev_dev"); + print "\n"; + $error++; + sleep(1); + } + } + + if (defined($rules->{option}) && $rules->{option} eq "keep") { + print "\n\n"; + return; + } + + $rc = udev("remove", $rules->{devpath}, \$rules->{rules}); + if ($rc != 0) { + print "$udev_bin remove failed with code $rc\n"; + $error++; + } + if ((-e "$udev_dev/$rules->{exp_name}") || + (-l "$udev_dev/$rules->{exp_name}")) { + print "remove: error"; + if ($rules->{exp_rem_error}) { + print " as expected\n"; + } else { + print "\n"; + system("tree", "$udev_dev"); + print "\n"; + $error++; + sleep(1); + } + } else { + print "remove: ok\n"; + } + + print "\n"; + + if (defined($rules->{option}) && $rules->{option} eq "clean") { + udev_setup(); + } + +} + +sub cleanup { + system("rm", "-rf", "$udev_run"); + system("umount", "$udev_tmpfs"); + rmdir($udev_tmpfs); +} + +# only run if we have root permissions +# due to mknod restrictions +if (!($<==0)) { + print "Must have root permissions to run properly.\n"; + exit($EXIT_TEST_SKIP); +} + +# skip the test when running in a chroot +system("systemd-detect-virt", "-r", "-q"); +if ($? >> 8 == 0) { + print "Running in a chroot, skipping the test.\n"; + exit($EXIT_TEST_SKIP); +} + +if (!udev_setup()) { + warn "Failed to set up the environment, skipping the test"; + cleanup(); + exit($EXIT_TEST_SKIP); +} + +if (system($udev_bin, "check")) { + warn "$udev_bin failed to set up the environment, skipping the test"; + cleanup(); + exit($EXIT_TEST_SKIP); +} + +my $test_num = 1; +my @list; + +foreach my $arg (@ARGV) { + if ($arg =~ m/--valgrind/) { + $valgrind = 1; + printf("using valgrind\n"); + } elsif ($arg =~ m/--gdb/) { + $gdb = 1; + printf("using gdb\n"); + } elsif ($arg =~ m/--strace/) { + $strace = 1; + printf("using strace\n"); + } else { + push(@list, $arg); + } +} + +if ($list[0]) { + foreach my $arg (@list) { + if (defined($tests[$arg-1]->{desc})) { + print "udev-test will run test number $arg:\n\n"; + run_test($tests[$arg-1], $arg); + } else { + print "test does not exist.\n"; + } + } +} else { + # test all + print "\nudev-test will run ".($#tests + 1)." tests:\n\n"; + + foreach my $rules (@tests) { + run_test($rules, $test_num); + $test_num++; + } +} + +print "$error errors occurred\n\n"; + +cleanup(); + +if ($error > 0) { + exit(1); +} +exit(0); diff --git a/test/unit-.service.d/10-override.conf b/test/unit-.service.d/10-override.conf new file mode 100644 index 00000000..916737d4 --- /dev/null +++ b/test/unit-.service.d/10-override.conf @@ -0,0 +1,2 @@ +[Unit] +Description=override0 diff --git a/test/unit-with-.service.d/20-override.conf b/test/unit-with-.service.d/20-override.conf new file mode 100644 index 00000000..c6c2438f --- /dev/null +++ b/test/unit-with-.service.d/20-override.conf @@ -0,0 +1,2 @@ +[Unit] +Documentation=man:override1 diff --git a/test/unit-with-multiple-.service.d/20-override.conf b/test/unit-with-multiple-.service.d/20-override.conf new file mode 100644 index 00000000..62fafd2e --- /dev/null +++ b/test/unit-with-multiple-.service.d/20-override.conf @@ -0,0 +1,2 @@ +[Unit] +Documentation=man:override2 diff --git a/test/unit-with-multiple-.service.d/30-override.conf b/test/unit-with-multiple-.service.d/30-override.conf new file mode 100644 index 00000000..b9616da8 --- /dev/null +++ b/test/unit-with-multiple-.service.d/30-override.conf @@ -0,0 +1,2 @@ +[Unit] +Documentation=man:override3 diff --git a/test/unit-with-multiple-dashes.service b/test/unit-with-multiple-dashes.service new file mode 100644 index 00000000..b38b3604 --- /dev/null +++ b/test/unit-with-multiple-dashes.service @@ -0,0 +1,6 @@ +[Unit] +Description=A unit with multiple dashes +Documentation=man:test + +[Service] +ExecStart=/bin/true diff --git a/test/unit-with-multiple-dashes.service.d/10-override.conf b/test/unit-with-multiple-dashes.service.d/10-override.conf new file mode 100644 index 00000000..982c3621 --- /dev/null +++ b/test/unit-with-multiple-dashes.service.d/10-override.conf @@ -0,0 +1,2 @@ +[Unit] +Description=override4 diff --git a/test/unstoppable.service b/test/unstoppable.service new file mode 100644 index 00000000..56b72c98 --- /dev/null +++ b/test/unstoppable.service @@ -0,0 +1,5 @@ +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/bin/echo "I'm unstoppable!" +ExecStop=/bin/systemctl start --no-block unstoppable.service diff --git a/tmpfiles.d/etc.conf.m4 b/tmpfiles.d/etc.conf.m4 new file mode 100644 index 00000000..f82e0b82 --- /dev/null +++ b/tmpfiles.d/etc.conf.m4 @@ -0,0 +1,22 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5) for details + +L /etc/os-release - - - - ../usr/lib/os-release +L+ /etc/mtab - - - - ../proc/self/mounts +m4_ifdef(`HAVE_SMACK_RUN_LABEL', +t /etc/mtab - - - - security.SMACK64=_ +)m4_dnl +m4_ifdef(`ENABLE_RESOLVE', +L! /etc/resolv.conf - - - - ../run/systemd/resolve/stub-resolv.conf +)m4_dnl +C! /etc/nsswitch.conf - - - - +m4_ifdef(`HAVE_PAM', +C! /etc/pam.d - - - - +)m4_dnl +C! /etc/issue - - - - diff --git a/tmpfiles.d/home.conf b/tmpfiles.d/home.conf new file mode 100644 index 00000000..9f25b833 --- /dev/null +++ b/tmpfiles.d/home.conf @@ -0,0 +1,11 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5) for details + +Q /home 0755 - - - +q /srv 0755 - - - diff --git a/tmpfiles.d/journal-nocow.conf b/tmpfiles.d/journal-nocow.conf new file mode 100644 index 00000000..e32a3885 --- /dev/null +++ b/tmpfiles.d/journal-nocow.conf @@ -0,0 +1,27 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5) for details + +# Set the NOCOW attribute for directories of journal files. This flag +# is inherited by their new files and sub-directories. Matters only +# for btrfs filesystems. +# +# WARNING: Enabling the NOCOW attribute improves journal performance +# substantially, but also disables the btrfs checksum logic. In +# btrfs RAID filesystems the checksums are needed for rebuilding +# corrupted files. Without checksums such rebuilds are not +# possible. +# +# In a single-disk filesystem (or a filesystem without redundancy) +# enabling the NOCOW attribute for journal files is safe, because +# they have their own checksums and a rebuilding wouldn't be possible +# in any case. + +h /var/log/journal - - - - +C +h /var/log/journal/%m - - - - +C +h /var/log/journal/remote - - - - +C diff --git a/tmpfiles.d/legacy.conf b/tmpfiles.d/legacy.conf new file mode 100644 index 00000000..62e2ae09 --- /dev/null +++ b/tmpfiles.d/legacy.conf @@ -0,0 +1,27 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5) for details + +# These files are considered legacy and are unnecessary on legacy-free +# systems. + +d /run/lock 0755 root root - +L /var/lock - - - - ../run/lock + +# /run/lock/subsys is used for serializing SysV service execution, and +# hence without use on SysV-less systems. + +d /run/lock/subsys 0755 root root - + +# /forcefsck, /fastboot and /forcequotacheck are deprecated in favor of the +# kernel command line options 'fsck.mode=force', 'fsck.mode=skip' and +# 'quotacheck.mode=force' + +r! /forcefsck +r! /fastboot +r! /forcequotacheck diff --git a/tmpfiles.d/meson.build b/tmpfiles.d/meson.build new file mode 100644 index 00000000..e77f46d0 --- /dev/null +++ b/tmpfiles.d/meson.build @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: LGPL-2.1+ + +enable_tmpfiles = conf.get('ENABLE_TMPFILES') == 1 + +tmpfiles = [['home.conf', ''], + ['journal-nocow.conf', ''], + ['systemd-nologin.conf', 'HAVE_PAM'], + ['systemd-nspawn.conf', 'ENABLE_MACHINED'], + ['systemd-tmp.conf', ''], + ['portables.conf', 'ENABLE_PORTABLED'], + ['tmp.conf', ''], + ['x11.conf', ''], + ['legacy.conf', 'HAVE_SYSV_COMPAT'], + ] + +foreach pair : tmpfiles + if not enable_tmpfiles + # do nothing + elif pair[1] == '' or conf.get(pair[1]) == 1 + install_data(pair[0], install_dir : tmpfilesdir) + else + message('Not installing tmpfiles.d/@0@ because @1@ is @2@' + .format(pair[0], pair[1], conf.get(pair[1], 0))) + endif +endforeach + +in_files = ['static-nodes-permissions.conf'] + +foreach file : in_files + gen = configure_file( + input : file + '.in', + output : file, + configuration : substs) + if enable_tmpfiles + install_data(gen, + install_dir : tmpfilesdir) + endif +endforeach + +m4_files = ['etc.conf', + 'systemd.conf', + 'var.conf'] + +foreach file : m4_files + if enable_tmpfiles + custom_target( + 'tmpfiles.d_' + file, + input : file + '.m4', + output: file, + command : [meson_apply_m4, config_h, '@INPUT@'], + capture : true, + install : true, + install_dir : tmpfilesdir) + endif +endforeach + +if enable_tmpfiles + meson.add_install_script( + 'sh', '-c', + mkdir_p.format(join_paths(sysconfdir, 'tmpfiles.d'))) +endif diff --git a/tmpfiles.d/portables.conf b/tmpfiles.d/portables.conf new file mode 100644 index 00000000..b8ddf7f4 --- /dev/null +++ b/tmpfiles.d/portables.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# See tmpfiles.d(5) for details + +Q /var/lib/portables 0700 diff --git a/tmpfiles.d/static-nodes-permissions.conf.in b/tmpfiles.d/static-nodes-permissions.conf.in new file mode 100644 index 00000000..50cffe2c --- /dev/null +++ b/tmpfiles.d/static-nodes-permissions.conf.in @@ -0,0 +1,17 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# This file adds permissions on top of static-nodes.conf generated by +# kmod-static-nodes.service. Rules specified here should match the +# permissions specified for udev in 50-udev-default.rules. + +z /dev/snd/seq 0660 - audio - +z /dev/snd/timer 0660 - audio - +z /dev/loop-control 0660 - disk - +z /dev/net/tun 0666 - - - +z /dev/fuse 0666 - - - +z /dev/kvm @DEV_KVM_MODE@ - kvm - diff --git a/tmpfiles.d/systemd-nologin.conf b/tmpfiles.d/systemd-nologin.conf new file mode 100644 index 00000000..39cfd06e --- /dev/null +++ b/tmpfiles.d/systemd-nologin.conf @@ -0,0 +1,11 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5), systemd-user-sessions.service(8) and pam_nologin(8). +# This file has special suffix so it is not run by mistake. + +F! /run/nologin 0644 - - - "System is booting up. Unprivileged users are not permitted to log in yet. Please come back later. For technical details, see pam_nologin(8)." diff --git a/tmpfiles.d/systemd-nspawn.conf b/tmpfiles.d/systemd-nspawn.conf new file mode 100644 index 00000000..78bd1c67 --- /dev/null +++ b/tmpfiles.d/systemd-nspawn.conf @@ -0,0 +1,23 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5) for details + +Q /var/lib/machines 0700 - - - + +# Remove old temporary snapshots, but only at boot. Ideally we'd have +# "self-destroying" btrfs snapshots that go away if the last +# reference to it does. To mimic a scheme like this at least remove +# the old snapshots on fresh boots, where we know they cannot be +# referenced anymore. Note that we actually remove all temporary files +# in /var/lib/machines/ at boot, which should be safe since the +# directory has defined semantics. In the root directory (where +# systemd-nspawn --ephemeral places snapshots) we are more strict, to +# avoid removing unrelated temporary files. + +R! /var/lib/machines/.#* +R! /.#machine.* diff --git a/tmpfiles.d/systemd-tmp.conf b/tmpfiles.d/systemd-tmp.conf new file mode 100644 index 00000000..d47d468f --- /dev/null +++ b/tmpfiles.d/systemd-tmp.conf @@ -0,0 +1,23 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5) for details + +# Exclude namespace mountpoints created with PrivateTmp=yes +x /tmp/systemd-private-%b-* +X /tmp/systemd-private-%b-*/tmp +x /var/tmp/systemd-private-%b-* +X /var/tmp/systemd-private-%b-*/tmp + +# Remove top-level private temporary directories on each boot +R! /tmp/systemd-private-* +R! /var/tmp/systemd-private-* + +# Handle lost systemd-coredump temp files. They could be lost on old filesystems, +# for example, after hard reboot. +x /var/lib/systemd/coredump/.#core*.%b* +r! /var/lib/systemd/coredump/.#* diff --git a/tmpfiles.d/systemd.conf.m4 b/tmpfiles.d/systemd.conf.m4 new file mode 100644 index 00000000..9c57d3b2 --- /dev/null +++ b/tmpfiles.d/systemd.conf.m4 @@ -0,0 +1,79 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5) for details + +d /run/user 0755 root root - +m4_ifdef(`ENABLE_UTMP', +F! /run/utmp 0664 root utmp - +)m4_dnl + +d /run/systemd/ask-password 0755 root root - +d /run/systemd/seats 0755 root root - +d /run/systemd/sessions 0755 root root - +d /run/systemd/users 0755 root root - +d /run/systemd/machines 0755 root root - +d /run/systemd/shutdown 0755 root root - +m4_ifdef(`ENABLE_NETWORKD', +d /run/systemd/netif 0755 systemd-network systemd-network - +d /run/systemd/netif/links 0755 systemd-network systemd-network - +d /run/systemd/netif/leases 0755 systemd-network systemd-network - +)m4_dnl + +d /run/log 0755 root root - + +z /run/log/journal 2755 root systemd-journal - - +Z /run/log/journal/%m ~2750 root systemd-journal - - +m4_ifdef(`HAVE_ACL',`m4_dnl +m4_ifdef(`ENABLE_ADM_GROUP',`m4_dnl +m4_ifdef(`ENABLE_WHEEL_GROUP',`` +a+ /run/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x +a+ /run/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x +a+ /run/log/journal/%m/*.journal* - - - - group:adm:r--,group:wheel:r-- +'',`` +a+ /run/log/journal/%m - - - - d:group:adm:r-x +a+ /run/log/journal/%m - - - - group:adm:r-x +a+ /run/log/journal/%m/*.journal* - - - - group:adm:r-- +'')',`m4_dnl +m4_ifdef(`ENABLE_WHEEL_GROUP',`` +a+ /run/log/journal/%m - - - - d:group:wheel:r-x +a+ /run/log/journal/%m - - - - group:wheel:r-x +a+ /run/log/journal/%m/*.journal* - - - - group:wheel:r-- +'')')')m4_dnl + +z /var/log/journal 2755 root systemd-journal - - +z /var/log/journal/%m 2755 root systemd-journal - - +z /var/log/journal/%m/system.journal 0640 root systemd-journal - - +m4_ifdef(`HAVE_ACL',`m4_dnl +m4_ifdef(`ENABLE_ADM_GROUP',`m4_dnl +m4_ifdef(`ENABLE_WHEEL_GROUP',`` +a+ /var/log/journal - - - - d:group::r-x,d:group:adm:r-x,d:group:wheel:r-x +a+ /var/log/journal - - - - group::r-x,group:adm:r-x,group:wheel:r-x +a+ /var/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x +a+ /var/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x +a+ /var/log/journal/%m/system.journal - - - - group:adm:r--,group:wheel:r-- +'', `` +a+ /var/log/journal - - - - d:group::r-x,d:group:adm:r-x +a+ /var/log/journal - - - - group::r-x,group:adm:r-x +a+ /var/log/journal/%m - - - - d:group:adm:r-x +a+ /var/log/journal/%m - - - - group:adm:r-x +a+ /var/log/journal/%m/system.journal - - - - group:adm:r-- +'')',`m4_dnl +m4_ifdef(`ENABLE_WHEEL_GROUP',`` +a+ /var/log/journal - - - - d:group::r-x,d:group:wheel:r-x +a+ /var/log/journal - - - - group::r-x,group:wheel:r-x +a+ /var/log/journal/%m - - - - d:group:wheel:r-x +a+ /var/log/journal/%m - - - - group:wheel:r-x +a+ /var/log/journal/%m/system.journal - - - - group:wheel:r-- +'')')')m4_dnl + +d /var/lib/systemd 0755 root root - +d /var/lib/systemd/coredump 0755 root root 3d + +d /var/lib/private 0700 root root - +d /var/log/private 0700 root root - +d /var/cache/private 0700 root root - diff --git a/tmpfiles.d/tmp.conf b/tmpfiles.d/tmp.conf new file mode 100644 index 00000000..fe5225d7 --- /dev/null +++ b/tmpfiles.d/tmp.conf @@ -0,0 +1,12 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5) for details + +# Clear tmp directories separately, to make them easier to override +q /tmp 1777 root root 10d +q /var/tmp 1777 root root 30d diff --git a/tmpfiles.d/var.conf.m4 b/tmpfiles.d/var.conf.m4 new file mode 100644 index 00000000..0e2c5096 --- /dev/null +++ b/tmpfiles.d/var.conf.m4 @@ -0,0 +1,25 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5) for details + +q /var 0755 - - - + +L /var/run - - - - ../run + +d /var/log 0755 - - - +m4_ifdef(`ENABLE_UTMP', +f /var/log/wtmp 0664 root utmp - +f /var/log/btmp 0660 root utmp - +f /var/log/lastlog 0664 root utmp - +)m4_dnl + +d /var/cache 0755 - - - + +d /var/lib 0755 - - - + +d /var/spool 0755 - - - diff --git a/tmpfiles.d/x11.conf b/tmpfiles.d/x11.conf new file mode 100644 index 00000000..f63184ea --- /dev/null +++ b/tmpfiles.d/x11.conf @@ -0,0 +1,19 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +# See tmpfiles.d(5) for details + +# Make sure these are created by default so that nobody else can +# or empty them at startup +D! /tmp/.X11-unix 1777 root root 10d +D! /tmp/.ICE-unix 1777 root root 10d +D! /tmp/.XIM-unix 1777 root root 10d +D! /tmp/.font-unix 1777 root root 10d +D! /tmp/.Test-unix 1777 root root 10d + +# Unlink the X11 lock files +r! /tmp/.X[0-9]*-lock diff --git a/tools/add-git-hook.sh b/tools/add-git-hook.sh new file mode 100755 index 00000000..5b1bf172 --- /dev/null +++ b/tools/add-git-hook.sh @@ -0,0 +1,12 @@ +#!/bin/sh +set -eu + +cd "$MESON_SOURCE_ROOT" + +if [ ! -f .git/hooks/pre-commit.sample -o -f .git/hooks/pre-commit ]; then + exit 2 # not needed +fi + +cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit +chmod +x .git/hooks/pre-commit +echo 'Activated pre-commit hook' diff --git a/tools/catalog-report.py b/tools/catalog-report.py new file mode 100755 index 00000000..ca1e13df --- /dev/null +++ b/tools/catalog-report.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: MIT +# +# This file is distributed under the MIT license, see below. +# +# The MIT License (MIT) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +""" +Prints out journal entries with no or bad catalog explanations. +""" + +import re +from systemd import journal, id128 + +j = journal.Reader() + +logged = set() +pattern = re.compile('@[A-Z0-9_]+@') + +mids = {v:k for k,v in id128.__dict__.items() + if k.startswith('SD_MESSAGE')} + +freq = 1000 + +def log_entry(x): + if 'CODE_FILE' in x: + # some of our code was using 'CODE_FUNCTION' instead of 'CODE_FUNC' + print('{}:{} {}'.format(x.get('CODE_FILE', '???'), + x.get('CODE_LINE', '???'), + x.get('CODE_FUNC', None) or x.get('CODE_FUNCTION', '???'))) + print(' {}'.format(x.get('MESSAGE', 'no message!'))) + for k, v in x.items(): + if k.startswith('CODE_') or k in {'MESSAGE_ID', 'MESSAGE'}: + continue + print(' {}={}'.format(k, v)) + print() + +for i, x in enumerate(j): + if i % freq == 0: + print(i, end='\r') + + try: + mid = x['MESSAGE_ID'] + except KeyError: + continue + name = mids.get(mid, 'unknown') + + try: + desc = journal.get_catalog(mid) + except FileNotFoundError: + if mid in logged: + continue + + print('{} {.hex}: no catalog entry'.format(name, mid)) + log_entry(x) + logged.add(mid) + continue + + fields = [field[1:-1] for field in pattern.findall(desc)] + for field in fields: + index = (mid, field) + if field in x or index in logged: + continue + print('{} {.hex}: no field {}'.format(name, mid, field)) + log_entry(x) + logged.add(index) diff --git a/tools/check-directives.sh b/tools/check-directives.sh new file mode 100755 index 00000000..a90fb604 --- /dev/null +++ b/tools/check-directives.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -e + +which perl &>/dev/null || exit 77 + +function generate_directives() { + perl -aF'/[\s,]+/' -ne ' + if (my ($s, $d) = ($F[0] =~ /^([^\s\.]+)\.([^\s\.]+)$/)) { $d{$s}{"$d="} = 1; } + END { while (my ($key, $value) = each %d) { + printf "[%s]\n%s\n", $key, join("\n", keys(%$value)) + }}' "$1" +} + +ret=0 +if ! diff \ + <(generate_directives "$1"/src/network/networkd-network-gperf.gperf | sort) \ + <(cat "$1"/test/fuzz/fuzz-network-parser/directives.network | sort); then + echo "Looks like test/fuzz/fuzz-network-parser/directives.network hasn't been updated" + ret=1 +fi + +if ! diff \ + <(generate_directives "$1"/src/network/netdev/netdev-gperf.gperf | sort) \ + <(cat "$1"/test/fuzz/fuzz-netdev-parser/directives.netdev | sort); then + echo "Looks like test/fuzz/fuzz-netdev-parser/directives.netdev hasn't been updated" + ret=1 +fi + +if ! diff \ + <(generate_directives "$1"/src/udev/net/link-config-gperf.gperf | sort) \ + <(cat "$1"/test/fuzz/fuzz-link-parser/directives.link | sort) ; then + echo "Looks like test/fuzz/fuzz-link-parser/directives.link hasn't been updated" + ret=1 +fi + +exit $ret diff --git a/tools/check-includes.pl b/tools/check-includes.pl new file mode 100755 index 00000000..c8bfcba8 --- /dev/null +++ b/tools/check-includes.pl @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: CC0-1.0 +#!/usr/bin/env perl +# +# checkincludes: Find files included more than once in (other) files. + +foreach $file (@ARGV) { + open(FILE, $file) or die "Cannot open $file: $!.\n"; + + my %includedfiles = (); + + while () { + if (m/^\s*#\s*include\s*[<"](\S*)[>"]/o) { + ++$includedfiles{$1}; + } + } + foreach $filename (keys %includedfiles) { + if ($includedfiles{$filename} > 1) { + print "$file: $filename is included more than once.\n"; + } + } + + close(FILE); +} diff --git a/tools/choose-default-locale.sh b/tools/choose-default-locale.sh new file mode 100755 index 00000000..da9768ad --- /dev/null +++ b/tools/choose-default-locale.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -e + +# Fedora uses C.utf8 but Debian uses C.UTF-8 +if locale -a | grep -xq -E 'C\.(utf8|UTF-8)'; then + echo 'C.UTF-8' +elif locale -a | grep -xqF 'en_US.utf8'; then + echo 'en_US.UTF-8' +else + echo 'C' +fi diff --git a/tools/chromiumos/LICENSE b/tools/chromiumos/LICENSE new file mode 100644 index 00000000..b9e779f9 --- /dev/null +++ b/tools/chromiumos/LICENSE @@ -0,0 +1,27 @@ +// Copyright 2014 The Chromium OS Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/tools/chromiumos/gen_autosuspend_rules.py b/tools/chromiumos/gen_autosuspend_rules.py new file mode 100644 index 00000000..e50d6e74 --- /dev/null +++ b/tools/chromiumos/gen_autosuspend_rules.py @@ -0,0 +1,317 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# Copyright 2017 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Autosuspend udev rule generator + +This script is executed at build time to generate udev rules. The +resulting rules file is installed on the device, the script itself +is not. +""" + +from __future__ import print_function + +# List of USB devices (vendorid:productid) for which it is safe to enable +# autosuspend. +USB_IDS = [] + +# Host Controllers and internal hubs +USB_IDS += [ + # Linux Host Controller (UHCI) (most older x86 boards) + '1d6b:0001', + # Linux Host Controller (EHCI) (all boards) + '1d6b:0002', + # Linux Host Controller (XHCI) (most newer boards) + '1d6b:0003', + # SMSC (Internal HSIC Hub) (most Exynos boards) + '0424:3503', + # Intel (Rate Matching Hub) (all x86 boards) + '05e3:0610', + # Intel (Internal Hub?) (peppy, falco) + '8087:0024', + # Genesys Logic (Internal Hub) (rambi) + '8087:8000', +] + +# Webcams +USB_IDS += [ + # Chicony (zgb) + '04f2:b1d8', + # Chicony (mario) + '04f2:b262', + # Chicony (stout) + '04f2:b2fe', + # Chicony (butterfly) + '04f2:b35f', + # Chicony (rambi) + '04f2:b443', + # Chicony (glados) + '04f2:b552', + # LiteOn (spring) + '058f:b001', + # Foxlink? (butterfly) + '05c8:0351', + # Foxlink? (butterfly) + '05c8:0355', + # Cheng Uei? (falco) + '05c8:036e', + # SuYin (parrot) + '064e:d251', + # Realtek (falco) + '0bda:571c', + # IMC Networks (squawks) + '13d3:5657', + # Sunplus (parrot) + '1bcf:2c17', + # (C-13HDO10B39N) (alex) + '2232:1013', + # (C-10HDP11538N) (lumpy) + '2232:1017', + # (Namuga) (link) + '2232:1033', + # (C-03FFM12339N) (daisy) + '2232:1037', + # (C-10HDO13531N) (peach) + '2232:1056', + # (NCM-G102) (samus) + '2232:6001', + # Acer (stout) + '5986:0299', +] + +# Bluetooth Host Controller +USB_IDS += [ + # Hon-hai (parrot) + '0489:e04e', + # Hon-hai (peppy) + '0489:e056', + # Hon-hai (Kahlee) + '0489:e09f', + # QCA6174A (delan) + '0489:e0a2', + # LiteOn (parrot) + '04ca:3006', + # LiteOn (aleena) + '04ca:3016', + # LiteOn (scarlet) + '04ca:301a', + # Atheros (stumpy, stout) + '0cf3:3004', + # Atheros (AR3011) (mario, alex, zgb) + '0cf3:3005', + # Atheros (stumyp) + '0cf3:3007', + # Atheros (butterfly) + '0cf3:311e', + # Atheros (scarlet) + '0cf3:e300', + # Marvell (rambi) + '1286:2046', + # Marvell (gru) + '1286:204e', + # Intel (rambi, samus) + '8087:07dc', + # Intel (strago, glados) + '8087:0a2a', + # Intel (octopus) + '8087:0aaa', + # Intel (hatch) + '8087:0026', + # Intel (atlas) + '8087:0025', +] + +# WWAN (LTE) +USB_IDS += [ + # Huawei (ME936) (kip) + '12d1:15bb', + # Fibocom (L850-GL) (coral, nautilus, sarien) + '2cb7:0007', +] + +# Mass Storage +USB_IDS += [ + # Genesys (SD card reader) (lumpy, link, peppy) + '05e3:0727', + # Realtek (SD card reader) (mario, alex) + '0bda:0138', + # Realtek (SD card reader) (helios) + '0bda:0136', + # Realtek (SD card reader) (falco) + '0bda:0177', +] + +# Security Key +USB_IDS += [ + # Yubico.com + '1050:0211', + # Yubico.com (HID firmware) + '1050:0200', + # Google Titan key + '18d1:5026', +] + +# USB Audio devices +USB_IDS += [ + # Google USB-C to 3.5mm Digital Headphone Jack Adapter 'Mir' + '18d1:5025', + # Google USB-C to 3.5mm Digital Headphone Jack Adapter 'Mir' (HID only) + '18d1:5029', + # Google USB-C to 3.5mm Digital Headphone Jack Adapter 2018 'Condor' + '18d1:5034', + # Google Pixel USB-C Earbuds 'Blackbird' + '18d1:5033', + # Libratone Q Adapt In-Ear USB-C Earphones, Made for Google + '03eb:2433', + # Moshi USB-C to 3.5 mm Adapter/Charger, Made for Google + '282b:48f0', + # Moshi USB-C to 3.5 mm Adapter/Charger, Made for Google (HID only) + '282b:0026', + # AiAiAi TMA-2 C60 Cable, Made for Google + '0572:1a08', + # Apple USB-C to 3.5mm Headphone Jack Adapter + '05ac:110a', +] + +# List of PCI devices (vendorid:deviceid) for which it is safe to enable +# autosuspend. +PCI_IDS = [] + +# Intel +PCI_IDS += [ + # Host bridge + '8086:590c', + # i915 + '8086:591e', + # proc_thermal + '8086:1903', + # SPT PCH xHCI controller + '8086:9d2f', + # CNP PCH xHCI controller + '8086:9ded', + # intel_pmc_core + '8086:9d21', + # i801_smbus + '8086:9d23', + # iwlwifi + '8086:095a', + # GMM + '8086:1911', + # Thermal + '8086:9d31', + # MME + '8086:9d3a', + # CrOS EC + '8086:9d4b', + # PCH SPI + '8086:9d24', + # SATA + '8086:02d3', + # RAM memory + '8086:02ef', + # ISA bridge + '8086:0284', + # Communication controller + '8086:02e0', + # Network controller + '8086:02f0', + # Serial bus controller + '8086:02a4', + # USB controller + '8086:02ed', + # Graphics + '8086:9b41', + # DSP + '8086:02f9', + # Host bridge + '8086:9b61', + # Host bridge + '8086:9b71', + # PCI Bridge + '8086:02b0', + # i915 (atlas) + '8086:591c', + # iwlwifi (atlas) + '8086:2526', +] + +# Samsung +PCI_IDS += [ + # NVMe KUS030205M-B001 + '144d:a806', + # NVMe MZVLB256HAHQ + '144d:a808', +] + +# Lite-on +PCI_IDS += [ + # 3C07110288 + '14a4:9100', +] + +# Seagate +PCI_IDS += [ + # ZP256CM30011 + '7089:5012', +] + +# Kingston +PCI_IDS += [ + # RBUSNS8154P3128GJ3 + '2646:5008', +] + +################################################################################ + +UDEV_RULE = """\ +ACTION!="add", GOTO="autosuspend_end" +SUBSYSTEM!="i2c|pci|usb", GOTO="autosuspend_end" + +SUBSYSTEM=="i2c", GOTO="autosuspend_i2c" +SUBSYSTEM=="pci", GOTO="autosuspend_pci" +SUBSYSTEM=="usb", GOTO="autosuspend_usb" + +# I2C rules +LABEL="autosuspend_i2c" +ATTR{name}=="cyapa", ATTR{power/control}="on", GOTO="autosuspend_end" +GOTO="autosuspend_end" + +# PCI rules +LABEL="autosuspend_pci" +%(pci_rules)s\ +GOTO="autosuspend_end" + +# USB rules +LABEL="autosuspend_usb" +%(usb_rules)s\ +GOTO="autosuspend_end" + +# Enable autosuspend +LABEL="autosuspend_enable" +TEST=="power/control", ATTR{power/control}="auto", GOTO="autosuspend_end" + +LABEL="autosuspend_end" +""" + + +def main(): + pci_rules = '' + for dev_ids in PCI_IDS: + vendor, device = dev_ids.split(':') + pci_rules += ('ATTR{vendor}=="0x%s", ATTR{device}=="0x%s", ' + 'GOTO="autosuspend_enable"\n' % (vendor, device)) + + usb_rules = '' + for dev_ids in USB_IDS: + vid, pid = dev_ids.split(':') + usb_rules += ('ATTR{idVendor}=="%s", ATTR{idProduct}=="%s", ' + 'GOTO="autosuspend_enable"\n' % (vid, pid)) + + print(UDEV_RULE % {'pci_rules': pci_rules, 'usb_rules': usb_rules}) + + +if __name__ == '__main__': + main() diff --git a/tools/coverity.sh b/tools/coverity.sh new file mode 100755 index 00000000..8edce065 --- /dev/null +++ b/tools/coverity.sh @@ -0,0 +1,233 @@ +#!/bin/bash + +# The official unmodified version of the script can be found at +# https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh + +set -e + +# Declare build command +COVERITY_SCAN_BUILD_COMMAND="ninja -C cov-build" + +# Environment check +# Use default values if not set +SCAN_URL=${SCAN_URL:="https://scan.coverity.com"} +TOOL_BASE=${TOOL_BASE:="/tmp/coverity-scan-analysis"} +UPLOAD_URL=${UPLOAD_URL:="https://scan.coverity.com/builds"} + +# These must be set by environment +echo -e "\033[33;1mNote: COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN are available on Project Settings page on scan.coverity.com\033[0m" +[ -z "$COVERITY_SCAN_PROJECT_NAME" ] && echo "ERROR: COVERITY_SCAN_PROJECT_NAME must be set" && exit 1 +[ -z "$COVERITY_SCAN_NOTIFICATION_EMAIL" ] && echo "ERROR: COVERITY_SCAN_NOTIFICATION_EMAIL must be set" && exit 1 +[ -z "$COVERITY_SCAN_BRANCH_PATTERN" ] && echo "ERROR: COVERITY_SCAN_BRANCH_PATTERN must be set" && exit 1 +[ -z "$COVERITY_SCAN_BUILD_COMMAND" ] && echo "ERROR: COVERITY_SCAN_BUILD_COMMAND must be set" && exit 1 +[ -z "$COVERITY_SCAN_TOKEN" ] && echo "ERROR: COVERITY_SCAN_TOKEN must be set" && exit 1 + +# Do not run on pull requests +if [ "${TRAVIS_PULL_REQUEST}" = "true" ]; then + echo -e "\033[33;1mINFO: Skipping Coverity Analysis: branch is a pull request.\033[0m" + exit 0 +fi + +# Verify this branch should run +if [[ "${TRAVIS_BRANCH^^}" =~ "${COVERITY_SCAN_BRANCH_PATTERN^^}" ]]; then + echo -e "\033[33;1mCoverity Scan configured to run on branch ${TRAVIS_BRANCH}\033[0m" +else + echo -e "\033[33;1mCoverity Scan NOT configured to run on branch ${TRAVIS_BRANCH}\033[0m" + exit 1 +fi + +# Verify upload is permitted +AUTH_RES=`curl -s --form project="$COVERITY_SCAN_PROJECT_NAME" --form token="$COVERITY_SCAN_TOKEN" $SCAN_URL/api/upload_permitted` +if [ "$AUTH_RES" = "Access denied" ]; then + echo -e "\033[33;1mCoverity Scan API access denied. Check COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN.\033[0m" + exit 1 +else + AUTH=`echo $AUTH_RES | jq .upload_permitted` + if [ "$AUTH" = "true" ]; then + echo -e "\033[33;1mCoverity Scan analysis authorized per quota.\033[0m" + else + WHEN=`echo $AUTH_RES | jq .next_upload_permitted_at` + echo -e "\033[33;1mCoverity Scan analysis NOT authorized until $WHEN.\033[0m" + exit 1 + fi +fi + +TOOL_DIR=`find $TOOL_BASE -type d -name 'cov-analysis*'` +export PATH="$TOOL_DIR/bin:$PATH" + +# Disable CCACHE for cov-build to compilation units correctly +export CCACHE_DISABLE=1 + +# FUNCTION DEFINITIONS +# -------------------- +_help() +{ + # displays help and exits + cat <<-EOF + USAGE: $0 [CMD] [OPTIONS] + + CMD + build Issue Coverity build + upload Upload coverity archive for analysis + Note: By default, archive is created from default results directory. + To provide custom archive or results directory, see --result-dir + and --tar options below. + + OPTIONS + -h,--help Display this menu and exits + + Applicable to build command + --------------------------- + -o,--out-dir Specify Coverity intermediate directory (defaults to 'cov-int') + -t,--tar bool, archive the output to .tgz file (defaults to false) + + Applicable to upload command + ---------------------------- + -d, --result-dir Specify result directory if different from default ('cov-int') + -t, --tar ARCHIVE Use custom .tgz archive instead of intermediate directory or pre-archived .tgz + (by default 'analysis-result.tgz' + EOF + return; +} + +_pack() +{ + RESULTS_ARCHIVE=${RESULTS_ARCHIVE:-'analysis-results.tgz'} + + echo -e "\033[33;1mTarring Coverity Scan Analysis results...\033[0m" + tar czf $RESULTS_ARCHIVE $RESULTS_DIR + SHA=`git rev-parse --short HEAD` + + PACKED=true +} + + +_build() +{ + echo -e "\033[33;1mRunning Coverity Scan Analysis Tool...\033[0m" + local _cov_build_options="" + #local _cov_build_options="--return-emit-failures 8 --parse-error-threshold 85" + eval "${COVERITY_SCAN_BUILD_COMMAND_PREPEND}" + COVERITY_UNSUPPORTED=1 cov-build --dir $RESULTS_DIR $_cov_build_options sh -c "$COVERITY_SCAN_BUILD_COMMAND" + cov-import-scm --dir $RESULTS_DIR --scm git --log $RESULTS_DIR/scm_log.txt + + if [ $? != 0 ]; then + echo -e "\033[33;1mCoverity Scan Build failed: $TEXT.\033[0m" + return 1 + fi + + [ -z $TAR ] || [ $TAR = false ] && return 0 + + if [ "$TAR" = true ]; then + _pack + fi +} + + +_upload() +{ + # pack results + [ -z $PACKED ] || [ $PACKED = false ] && _pack + + # Upload results + echo -e "\033[33;1mUploading Coverity Scan Analysis results...\033[0m" + response=$(curl \ + --silent --write-out "\n%{http_code}\n" \ + --form project=$COVERITY_SCAN_PROJECT_NAME \ + --form token=$COVERITY_SCAN_TOKEN \ + --form email=$COVERITY_SCAN_NOTIFICATION_EMAIL \ + --form file=@$RESULTS_ARCHIVE \ + --form version=$SHA \ + --form description="Travis CI build" \ + $UPLOAD_URL) + printf "\033[33;1mThe response is\033[0m\n%s\n" "$response" + status_code=$(echo "$response" | sed -n '$p') + # Coverity Scan used to respond with 201 on successfully receiving analysis results. + # Now for some reason it sends 200 and may change back in the foreseeable future. + # See https://github.com/pmem/pmdk/commit/7b103fd2dd54b2e5974f71fb65c81ab3713c12c5 + if [ "$status_code" != "200" ]; then + TEXT=$(echo "$response" | sed '$d') + echo -e "\033[33;1mCoverity Scan upload failed: $TEXT.\033[0m" + exit 1 + fi + + echo -e "\n\033[33;1mCoverity Scan Analysis completed successfully.\033[0m" + exit 0 +} + +# PARSE COMMAND LINE OPTIONS +# -------------------------- + +case $1 in + -h|--help) + _help + exit 0 + ;; + build) + CMD='build' + TEMP=`getopt -o ho:t --long help,out-dir:,tar -n '$0' -- "$@"` + _ec=$? + [[ $_ec -gt 0 ]] && _help && exit $_ec + shift + ;; + upload) + CMD='upload' + TEMP=`getopt -o hd:t: --long help,result-dir:tar: -n '$0' -- "$@"` + _ec=$? + [[ $_ec -gt 0 ]] && _help && exit $_ec + shift + ;; + *) + _help && exit 1 ;; +esac + +RESULTS_DIR='cov-int' + +eval set -- "$TEMP" +if [ $? != 0 ] ; then exit 1 ; fi + +# extract options and their arguments into variables. +if [[ $CMD == 'build' ]]; then + TAR=false + while true ; do + case $1 in + -h|--help) + _help + exit 0 + ;; + -o|--out-dir) + RESULTS_DIR="$2" + shift 2 + ;; + -t|--tar) + TAR=true + shift + ;; + --) _build; shift ; break ;; + *) echo "Internal error" ; _help && exit 6 ;; + esac + done + +elif [[ $CMD == 'upload' ]]; then + while true ; do + case $1 in + -h|--help) + _help + exit 0 + ;; + -d|--result-dir) + CHANGE_DEFAULT_DIR=true + RESULTS_DIR="$2" + shift 2 + ;; + -t|--tar) + RESULTS_ARCHIVE="$2" + [ -z $CHANGE_DEFAULT_DIR ] || [ $CHANGE_DEFAULT_DIR = false ] && PACKED=true + shift 2 + ;; + --) _upload; shift ; break ;; + *) echo "Internal error" ; _help && exit 6 ;; + esac + done + +fi diff --git a/tools/find-build-dir.sh b/tools/find-build-dir.sh new file mode 100755 index 00000000..fb8a1c17 --- /dev/null +++ b/tools/find-build-dir.sh @@ -0,0 +1,32 @@ +#!/bin/sh +set -e + +# Try to guess the build directory: +# we look for subdirectories of the parent directory that look like ninja build dirs. + +if [ -n "$BUILD_DIR" ]; then + echo "$(realpath "$BUILD_DIR")" + exit 0 +fi + +root="$(dirname "$(realpath "$0")")" + +found= +for i in "$root"/../*/build.ninja; do + c="$(dirname $i)" + [ -d "$c" ] || continue + [ "$(basename "$c")" != mkosi.builddir ] || continue + + if [ -n "$found" ]; then + echo 'Found multiple candidates, specify build directory with $BUILD_DIR' >&2 + exit 2 + fi + found="$c" +done + +if [ -z "$found" ]; then + echo 'Specify build directory with $BUILD_DIR' >&2 + exit 1 +fi + +echo "$(realpath $found)" diff --git a/tools/find-double-newline.sh b/tools/find-double-newline.sh new file mode 100755 index 00000000..51204eb7 --- /dev/null +++ b/tools/find-double-newline.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# SPDX-License-Identifier: LGPL-2.1+ + +TOP=`git rev-parse --show-toplevel` + +case "$1" in + recdiff) + if [ "$2" = "" ] ; then + DIR="$TOP" + else + DIR="$2" + fi + + find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 diff \{\} \; + ;; + + recpatch) + if [ "$2" = "" ] ; then + DIR="$TOP" + else + DIR="$2" + fi + + find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 patch \{\} \; + ;; + + diff) + T=`mktemp` + sed '/^$/N;/^\n$/D' < "$2" > "$T" + diff -u "$2" "$T" + rm -f "$T" + ;; + + patch) + sed -i '/^$/N;/^\n$/D' "$2" + ;; + + *) + echo "Expected recdiff|recpatch|diff|patch as verb." >&2 + ;; +esac diff --git a/tools/find-tabs.sh b/tools/find-tabs.sh new file mode 100755 index 00000000..95249f9c --- /dev/null +++ b/tools/find-tabs.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# SPDX-License-Identifier: LGPL-2.1+ + +TOP=`git rev-parse --show-toplevel` + +case "$1" in + recdiff) + if [ "$2" = "" ] ; then + DIR="$TOP" + else + DIR="$2" + fi + + find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 diff \{\} \; + ;; + + recpatch) + if [ "$2" = "" ] ; then + DIR="$TOP" + else + DIR="$2" + fi + + find $DIR -type f \( -name '*.[ch]' -o -name '*.xml' \) -exec $0 patch \{\} \; + ;; + + diff) + T=`mktemp` + sed 's/\t/ /g' < "$2" > "$T" + diff -u "$2" "$T" + rm -f "$T" + ;; + + patch) + sed -i 's/\t/ /g' "$2" + ;; + + *) + echo "Expected recdiff|recpatch|diff|patch as verb." >&2 + ;; +esac diff --git a/tools/gdb-sd_dump_hashmaps.py b/tools/gdb-sd_dump_hashmaps.py new file mode 100644 index 00000000..4e8593f3 --- /dev/null +++ b/tools/gdb-sd_dump_hashmaps.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ + +from __future__ import print_function + +import gdb + +class sd_dump_hashmaps(gdb.Command): + "dump systemd's hashmaps" + + def __init__(self): + super(sd_dump_hashmaps, self).__init__("sd_dump_hashmaps", gdb.COMMAND_DATA, gdb.COMPLETE_NONE) + + def invoke(self, arg, from_tty): + d = gdb.parse_and_eval("hashmap_debug_list") + all_entry_sizes = gdb.parse_and_eval("all_entry_sizes") + all_direct_buckets = gdb.parse_and_eval("all_direct_buckets") + uchar_t = gdb.lookup_type("unsigned char") + ulong_t = gdb.lookup_type("unsigned long") + debug_offset = gdb.parse_and_eval("(unsigned long)&((HashmapBase*)0)->debug") + + print("type, hash, indirect, entries, max_entries, buckets, creator") + while d: + h = gdb.parse_and_eval("(HashmapBase*)((char*)%d - %d)" % (int(d.cast(ulong_t)), debug_offset)) + + if h["has_indirect"]: + storage_ptr = h["indirect"]["storage"].cast(uchar_t.pointer()) + n_entries = h["indirect"]["n_entries"] + n_buckets = h["indirect"]["n_buckets"] + else: + storage_ptr = h["direct"]["storage"].cast(uchar_t.pointer()) + n_entries = h["n_direct_entries"] + n_buckets = all_direct_buckets[int(h["type"])]; + + t = ["plain", "ordered", "set"][int(h["type"])] + + print("{}, {}, {}, {}, {}, {}, {} ({}:{})".format(t, h["hash_ops"], bool(h["has_indirect"]), n_entries, d["max_entries"], n_buckets, d["func"], d["file"], d["line"])) + + if arg != "" and n_entries > 0: + dib_raw_addr = storage_ptr + (all_entry_sizes[h["type"]] * n_buckets) + + histogram = {} + for i in xrange(0, n_buckets): + dib = int(dib_raw_addr[i]) + histogram[dib] = histogram.get(dib, 0) + 1 + + for dib in sorted(iter(histogram)): + if dib != 255: + print("{:>3} {:>8} {} of entries".format(dib, histogram[dib], 100.0*histogram[dib]/n_entries)) + else: + print("{:>3} {:>8} {} of slots".format(dib, histogram[dib], 100.0*histogram[dib]/n_buckets)) + print("mean DIB of entries: {}".format(sum([dib*histogram[dib] for dib in iter(histogram) if dib != 255])*1.0/n_entries)) + + blocks = [] + current_len = 1 + prev = int(dib_raw_addr[0]) + for i in xrange(1, n_buckets): + dib = int(dib_raw_addr[i]) + if (dib == 255) != (prev == 255): + if prev != 255: + blocks += [[i, current_len]] + current_len = 1 + else: + current_len += 1 + + prev = dib + if prev != 255: + blocks += [[i, current_len]] + # a block may be wrapped around + if len(blocks) > 1 and blocks[0][0] == blocks[0][1] and blocks[-1][0] == n_buckets - 1: + blocks[0][1] += blocks[-1][1] + blocks = blocks[0:-1] + print("max block: {}".format(max(blocks, key=lambda a: a[1]))) + print("sum block lens: {}".format(sum(b[1] for b in blocks))) + print("mean block len: {}".format((1.0 * sum(b[1] for b in blocks) / len(blocks)))) + + d = d["debug_list_next"] + +sd_dump_hashmaps() diff --git a/tools/generate-gperfs.py b/tools/generate-gperfs.py new file mode 100755 index 00000000..5392df0e --- /dev/null +++ b/tools/generate-gperfs.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ + +""" +Generate %-from-name.gperf from %-list.txt +""" + +import sys + +name, prefix, input = sys.argv[1:] + +print("""\ +%{ +#if __GNUC__ >= 7 +_Pragma("GCC diagnostic ignored \\"-Wimplicit-fallthrough\\"") +#endif +%}""") +print("""\ +struct {}_name {{ const char* name; int id; }}; +%null-strings +%%""".format(name)) + +for line in open(input): + print("{0}, {1}{0}".format(line.rstrip(), prefix)) diff --git a/tools/make-autosuspend-rules.py b/tools/make-autosuspend-rules.py new file mode 100755 index 00000000..25b261ea --- /dev/null +++ b/tools/make-autosuspend-rules.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ + +# Generate autosuspend rules for devices that have been whitelisted (IE tested) +# by the Chromium OS team. Please keep this script in sync with: +# https://chromium.googlesource.com/chromiumos/platform2/+/master/power_manager/udev/gen_autosuspend_rules.py + +import sys +import chromiumos.gen_autosuspend_rules + +if __name__ == '__main__': + if len(sys.argv) > 1: + sys.stdout = open(sys.argv[1], 'w') + chromiumos.gen_autosuspend_rules.main() diff --git a/tools/make-directive-index.py b/tools/make-directive-index.py new file mode 100755 index 00000000..da10575f --- /dev/null +++ b/tools/make-directive-index.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1+ + +import sys +import collections +import re +from xml_helper import xml_parse, xml_print, tree +from copy import deepcopy + +TEMPLATE = '''\ + + + + systemd.directives + systemd + + + + systemd.directives + 7 + + + + systemd.directives + Index of configuration directives + + + + Unit directives + + Directives for configuring units, used in unit + files. + + + + + + Options on the kernel command line + + Kernel boot options for configuring the behaviour of the + systemd process. + + + + + + Environment variables + + Environment variables understood by the systemd manager + and other programs and environment variable-compatible settings. + + + + + + EFI variables + + EFI variables understood by + systemd-boot7 + and other programs. + + + + + + UDEV directives + + Directives for configuring systemd units through the + udev database. + + + + + + Network directives + + Directives for configuring network links through the + net-setup-link udev builtin and networks through + systemd-networkd. + + + + + + Journal fields + + Fields in the journal events with a well known meaning. + + + + + + PAM configuration directives + + Directives for configuring PAM behaviour. + + + + + + <filename>/etc/crypttab</filename> and + <filename>/etc/fstab</filename> options + + Options which influence mounted filesystems and + encrypted volumes. + + + + + + <citerefentry><refentrytitle>systemd.nspawn</refentrytitle><manvolnum>5</manvolnum></citerefentry> + directives + + Directives for configuring systemd-nspawn containers. + + + + + + Program configuration options + + Directives for configuring the behaviour of the + systemd process and other tools through configuration files. + + + + + + Command line options + + Command-line options accepted by programs in the + systemd suite. + + + + + + Constants + + Various constant used and/or defined by systemd. + + + + + + Miscellaneous options and directives + + Other configuration elements which don't fit in + any of the above groups. + + + + + + Files and directories + + Paths and file names referred to in the + documentation. + + + + + + Colophon + + + +''' + +COLOPHON = '''\ +This index contains {count} entries in {sections} sections, +referring to {pages} individual manual pages. +''' + +def _extract_directives(directive_groups, formatting, page): + t = xml_parse(page) + section = t.find('./refmeta/manvolnum').text + pagename = t.find('./refmeta/refentrytitle').text + + storopt = directive_groups['options'] + for variablelist in t.iterfind('.//variablelist'): + klass = variablelist.attrib.get('class') + storvar = directive_groups[klass or 'miscellaneous'] + #